commit 8a365179eafdf3aea98e60ab9f5882b200d4c759 Author: px4dev Date: Sat Aug 4 15:12:36 2012 -0700 Fresh import of the PX4 firmware sources. diff --git a/Debug/NuttX b/Debug/NuttX new file mode 100644 index 0000000000..46ba3d1ff4 --- /dev/null +++ b/Debug/NuttX @@ -0,0 +1,211 @@ +# +# Generic GDB macros for working with NuttX +# + +echo Loading NuttX GDB macros. Use 'help nuttx' for more information.\n + +define nuttx + echo Use 'help nuttx' for more information.\n +end + +document nuttx +. Various macros for working with NuttX. +. +. showheap +. Prints the contents of the malloc heap(s). +. showtasks +. Prints a list of all tasks. +. showtask
+. Prints information about the task at
+. +. Use 'help ' for more specific help. +end + +################################################################################ +# Heap display +################################################################################ + +define _showheap + set $index = $arg0 + if (sizeof(struct mm_allocnode_s) == 4) + set $MM_ALLOC_BIT = 0x8000 + else + set $MM_ALLOC_BIT = 0x80000000 + end + printf "HEAP %d %p - %p\n", $index, g_heapstart[$index], g_heapend[$index] + printf "ptr size\n" + set $node = (char *)g_heapstart[$index] + sizeof(struct mm_allocnode_s) + while $node < g_heapend[$index] + printf " %p", $node + set $nodestruct = (struct mm_allocnode_s *)$node + printf " %u", $nodestruct->size + if !($nodestruct->preceding & $MM_ALLOC_BIT) + printf " FREE" + end + if ($nodestruct->size > g_heapsize) || (($node + $nodestruct->size) > g_heapend[$index]) + printf " (BAD SIZE)" + end + printf "\n" + set $node = $node + $nodestruct->size + end +end + +define showheap + set $nheaps = sizeof(g_heapstart) / sizeof(g_heapstart[0]) + printf "Printing %d heaps\n", $nheaps + set $heapindex = (int)0 + while $heapindex < $nheaps + showheap $heapindex + set $heapindex = $heapindex + 1 + end +end + +document showheap +. showheap +. Prints the contents of the malloc heap(s). +end + +################################################################################ +# Task display +################################################################################ + +define _showtask_oneline + set $task = (struct _TCB *)$arg0 + printf " %p %.2d %.3d %s\n", $task, $task->pid, $task->sched_priority, $task->name +end + +define _showtasklist + set $queue = (dq_queue_t *)$arg0 + set $cursor = (dq_entry_t *)$queue->head + + if $cursor != 0 + printf " TCB PID PRI\n" + else + printf " \n" + end + + while $cursor != 0 + + _showtask_oneline $cursor + + if $cursor == $queue->tail + set $cursor = 0 + else + set $next = $cursor->flink + + if $next->blink != $cursor + printf "task linkage corrupt\n" + set $cursor = 0 + else + set $cursor = $next + end + end + end +end + +# +# Print task registers for a NuttX v7em target with FPU enabled. +# +define _showtaskregs_v7em + set $task = (struct _TCB *)$arg0 + set $regs = (uint32_t *)&($task->xcp.regs[0]) + + printf " r0: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", $regs[27], $regs[28], $regs[29], $regs[30], $regs[2], $regs[3], $regs[4], $regs[5] + printf " r8: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", $regs[6], $regs[7], $regs[8], $regs[9], $regs[31], $regs[0], $regs[32], $regs[33] + printf " XPSR 0x%08x EXC_RETURN 0x%08x PRIMASK 0x%08x\n", $regs[34], $regs[10], $regs[1] +end + +# +# Print current registers for a NuttX v7em target with FPU enabled. +# +define _showcurrentregs_v7em + printf " r0: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", $r0, $r1, $r2, $r3, $r4, $r5, $r6, $r7 + printf " r8: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", $r8, $r9, $r10, $r11, $r12, $r13, $r14, $r15 + printf " XPSR 0x%08x\n", $xpsr +end + +# +# Print details of a semaphore +# +define _showsemaphore + printf "count %d ", $arg0->semcount + if $arg0->hlist.holder != 0 + set $_task = (struct _TCB *)$arg0->hlist.holder + printf "held by %s", $_task->name + end + printf "\n" +end + +define showtask + set $task = (struct _TCB *)$arg0 + + printf "%p %.2d ", $task, $task->pid + _showtaskstate $task + printf " %s\n", $task->name + set $stack_free = 0 + while ($stack_free < $task->adj_stack_size) && *(uint8_t *)($task->stack_alloc_ptr + $stack_free) + set $stack_free = $stack_free + 1 + end + printf" stack 0x%08x-0x%08x (%d) %d free\n", $task->stack_alloc_ptr, $task->adj_stack_ptr, $task->adj_stack_size, $stack_free + + if $task->task_state == TSTATE_WAIT_SEM + printf " waiting on %p ", $task->waitsem + _showsemaphore $task->waitsem + end + + if $task->task_state != TSTATE_TASK_RUNNING + _showtaskregs_v7em $task + else + _showcurrentregs_v7em + end + + # XXX print registers here +end + +document showtask +. showtask +. Print details of a task. +end + +define _showtaskstate + if $arg0->task_state == TSTATE_TASK_INVALID + printf "INVALID" + end + if $arg0->task_state == TSTATE_TASK_PENDING + printf "PENDING" + end + if $arg0->task_state == TSTATE_TASK_READYTORUN + printf "READYTORUN" + end + if $arg0->task_state == TSTATE_TASK_RUNNING + printf "RUNNING" + end + if $arg0->task_state == TSTATE_TASK_INACTIVE + printf "INACTIVE" + end + if $arg0->task_state == TSTATE_WAIT_SEM + printf "WAIT_SEM" + end + if $arg0->task_state == TSTATE_WAIT_SIG + printf "WAIT_SIG" + end + if $arg0->task_state > TSTATE_WAIT_SIG + printf "%d", $arg0->task_state + end +end + +define showtasks + printf "PENDING\n" + _showtasklist &g_pendingtasks + printf "RUNNABLE\n" + _showtasklist &g_readytorun + printf "WAITING\n" + _showtasklist &g_waitingforsemaphore + printf "INACTIVE\n" + _showtasklist &g_inactivetasks +end + +document showtasks +. showtasks +. Print a list of all tasks in the system, separated into their respective queues. +end diff --git a/Debug/NuttX_BMP b/Debug/NuttX_BMP new file mode 100644 index 0000000000..013fa44365 --- /dev/null +++ b/Debug/NuttX_BMP @@ -0,0 +1,6 @@ +# +# Setup macros for the BlackMagic debug probe and NuttX. +# + +mon swdp_scan +attach 1 diff --git a/Debug/memdump b/Debug/memdump new file mode 100644 index 0000000000..703c4ed8ba --- /dev/null +++ b/Debug/memdump @@ -0,0 +1,11 @@ +define f4_memdump + shell mkdir -p /tmp/dump + printf "Dumping CCSRAM to /tmp/dump/ccsram\n" + dump memory /tmp/dump/ccsram 0x10000000 0x10010000 + printf "Dumping SRAM to /tmp/dump/sram\n" + dump memory /tmp/dump/sram 0x20000000 0x20020000 +end + +document f4_memdump +Dumps the STM32F4 memory to files in /tmp/dump. +end diff --git a/Debug/stm32f4x.cfg b/Debug/stm32f4x.cfg new file mode 100644 index 0000000000..28bfcfbbbc --- /dev/null +++ b/Debug/stm32f4x.cfg @@ -0,0 +1,64 @@ +# script for stm32f2xxx + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME stm32f4xxx +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +# Work-area is a space in RAM used for flash programming +# By default use 64kB +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x10000 +} + +# JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz +# +# Since we may be running of an RC oscilator, we crank down the speed a +# bit more to be on the safe side. Perhaps superstition, but if are +# running off a crystal, we can run closer to the limit. Note +# that there can be a pretty wide band where things are more or less stable. +jtag_khz 1000 + +jtag_nsrst_delay 100 +jtag_ntrst_delay 100 + +#jtag scan chain +if { [info exists CPUTAPID ] } { + set _CPUTAPID $CPUTAPID +} else { + # See STM Document RM0033 + # Section 32.6.3 - corresponds to Cortex-M3 r2p0 + set _CPUTAPID 0x4ba00477 +} +jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID + +if { [info exists BSTAPID ] } { + set _BSTAPID $BSTAPID +} else { + # See STM Document RM0033 + # Section 32.6.2 + # + set _BSTAPID 0x06413041 +} +jtag newtap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m3 -endian $_ENDIAN -chain-position $_TARGETNAME -rtos auto + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME stm32f2x 0 0 0 0 $_TARGETNAME + +# if srst is not fitted use SYSRESETREQ to +# perform a soft reset +cortex_m3 reset_config sysresetreq diff --git a/Documentation/Doxyfile b/Documentation/Doxyfile new file mode 100644 index 0000000000..4802ef8189 --- /dev/null +++ b/Documentation/Doxyfile @@ -0,0 +1,1518 @@ +# Doxyfile 1.6.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "PX4 Autopilot Firmware" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it parses. +# With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this tag. +# The format is ext=language, where ext is a file extension, and language is one of +# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, +# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 500 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +# Simple version: FILE_VERSION_FILTER = "/bin/sh -c 'git log --pretty=\"format:%ci\" -1 \"${1}\" || echo no git'" +FILE_VERSION_FILTER = "sh versionfilter.sh" + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = doxy.log + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../apps + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.c *.h *.hpp *.hxx *.cc *.cpp *.cxx *.dox +#FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = ../dist/ \ + ../docs/html/ \ + html + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = YES + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = ../docs + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = YES + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. + +GENERATE_DOCSET = YES + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = ch.ethz.pixhawk.px4 + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. +# For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's +# filter section matches. +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NONE + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# When the SEARCHENGINE tag is enable doxygen will generate a search box for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP) +# there is already a search function so this one should typically +# be disabled. + +SEARCHENGINE = YES + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/Documentation/README b/Documentation/README new file mode 100644 index 0000000000..56fcfb332a --- /dev/null +++ b/Documentation/README @@ -0,0 +1,37 @@ +Linux/Mac OS X +============== +To install doxygen: +$sudo apt-get install doxygen + +If the above does not work go to: +http://www.stack.nl/~dimitri/doxygen/download.html for the correct download. + +Then go to the following website for inforamtion on the install: +http://www.stack.nl/~dimitri/doxygen/install.html + +Then to generate the html, run the following code while you are in the qgroundcontrol/doc directory: +$doxygen Doxyfile + +The html file index.html should be in doc/html unless you changed the output directory. + +The other option for generating the documentation is to use the wizard: +$doxywizard & + +doxywizard information: +http://www.stack.nl/~dimitri/doxygen/doxywizard_usage.html + +Or go to the Doxygen Manual for information at the website noted below. + +Windows +======= +Go to the following website for the correct download and follow the wizard to install: +http://www.stack.nl/~dimitri/doxygen/download.html + +Run the wizard to generate the documentation. +Go to the website below or the Doxygen Manual for information on running doxywizard. +http://www.stack.nl/~dimitri/doxygen/doxywizard_usage.html + +Doxygen Manual +============== +http://www.stack.nl/~dimitri/doxygen/ + diff --git a/Documentation/code_structure_diagrams.odg b/Documentation/code_structure_diagrams.odg new file mode 100644 index 0000000000..7bab5f4c85 Binary files /dev/null and b/Documentation/code_structure_diagrams.odg differ diff --git a/Documentation/code_structure_diagrams.pdf b/Documentation/code_structure_diagrams.pdf new file mode 100644 index 0000000000..ef7151cf54 Binary files /dev/null and b/Documentation/code_structure_diagrams.pdf differ diff --git a/Documentation/commander_app.odg b/Documentation/commander_app.odg new file mode 100644 index 0000000000..c05fba3c58 Binary files /dev/null and b/Documentation/commander_app.odg differ diff --git a/Documentation/commander_app.pdf b/Documentation/commander_app.pdf new file mode 100644 index 0000000000..6d55e28099 Binary files /dev/null and b/Documentation/commander_app.pdf differ diff --git a/Documentation/commander_app.png b/Documentation/commander_app.png new file mode 100644 index 0000000000..b71f1b8a78 Binary files /dev/null and b/Documentation/commander_app.png differ diff --git a/Documentation/doxygen.sh b/Documentation/doxygen.sh new file mode 100755 index 0000000000..326ff3017c --- /dev/null +++ b/Documentation/doxygen.sh @@ -0,0 +1,3 @@ +#!/bin/sh +rm -rf html +doxygen \ No newline at end of file diff --git a/Documentation/inter_app_communication.odg b/Documentation/inter_app_communication.odg new file mode 100644 index 0000000000..9f7b684402 Binary files /dev/null and b/Documentation/inter_app_communication.odg differ diff --git a/Documentation/inter_app_communication.pdf b/Documentation/inter_app_communication.pdf new file mode 100644 index 0000000000..384894832c Binary files /dev/null and b/Documentation/inter_app_communication.pdf differ diff --git a/Documentation/inter_app_communication.png b/Documentation/inter_app_communication.png new file mode 100644 index 0000000000..6681fe47d1 Binary files /dev/null and b/Documentation/inter_app_communication.png differ diff --git a/Documentation/position_estimator_app.odg b/Documentation/position_estimator_app.odg new file mode 100644 index 0000000000..a6fc673733 Binary files /dev/null and b/Documentation/position_estimator_app.odg differ diff --git a/Documentation/position_estimator_app.pdf b/Documentation/position_estimator_app.pdf new file mode 100644 index 0000000000..bc07209ee1 Binary files /dev/null and b/Documentation/position_estimator_app.pdf differ diff --git a/Documentation/position_estimator_app.png b/Documentation/position_estimator_app.png new file mode 100644 index 0000000000..377549f63c Binary files /dev/null and b/Documentation/position_estimator_app.png differ diff --git a/Documentation/px4_general_structure.png b/Documentation/px4_general_structure.png new file mode 100644 index 0000000000..7d1b964a21 Binary files /dev/null and b/Documentation/px4_general_structure.png differ diff --git a/Documentation/state_machine.png b/Documentation/state_machine.png new file mode 100644 index 0000000000..9fef9057ae Binary files /dev/null and b/Documentation/state_machine.png differ diff --git a/Documentation/versionfilter.sh b/Documentation/versionfilter.sh new file mode 100644 index 0000000000..a887d8bc46 --- /dev/null +++ b/Documentation/versionfilter.sh @@ -0,0 +1,2 @@ +#!/bin/sh +git log --pretty=format:"Last change: commit %h - %aN, %ar : %s" -1 $1 || echo no git \ No newline at end of file diff --git a/Firmware.sublime-project b/Firmware.sublime-project new file mode 100644 index 0000000000..24eabf6da3 --- /dev/null +++ b/Firmware.sublime-project @@ -0,0 +1,22 @@ +{ + "folders": + [ + { + "path": "." + } + ], + "settings": + { + "tab_size": 8, + "translate_tabs_to_spaces": false + }, + "build_systems": + [ + { + "name": "PX4", + "working_dir": "${project_path}", + "file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$", + "cmd": ["make"] + } + ] +} diff --git a/Images/px4fmu.prototype b/Images/px4fmu.prototype new file mode 100644 index 0000000000..da88f8490f --- /dev/null +++ b/Images/px4fmu.prototype @@ -0,0 +1,12 @@ +{ + "board_id": 5, + "magic": "PX4FWv1", + "description": "Firmware for the PX4FMU board", + "image": "", + "build_time": 0, + "summary": "PX4FMU", + "version": "0.1", + "image_size": 0, + "git_identity": "", + "board_revision": 0 +} diff --git a/Images/px4io.prototype b/Images/px4io.prototype new file mode 100644 index 0000000000..d00b7e5d90 --- /dev/null +++ b/Images/px4io.prototype @@ -0,0 +1,12 @@ +{ + "board_id": 7, + "magic": "PX4FWv1", + "description": "Firmware for the PX4IO board", + "image": "", + "build_time": 0, + "summary": "PX4IO", + "version": "0.1", + "image_size": 0, + "git_identity": "", + "board_revision": 0 +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..ef1bd98782 --- /dev/null +++ b/Makefile @@ -0,0 +1,142 @@ +# +# Top-level Makefile for building PX4 firmware images. +# +# +# Note that this is a transitional process; the eventual goal is for this +# project to slim down and simply generate PX4 link kits via the NuttX +# 'make export' mechanism. +# +# + +# +# Some useful paths. +# +export PX4BASE = $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) +export NUTTX_SRC = $(PX4BASE)/nuttx +export NUTTX_APPS = $(PX4BASE)/apps +export MAVLINK_SRC = $(PX4BASE)/mavlink +export ROMFS_SRC = $(PX4BASE)/ROMFS +export IMAGE_DIR = $(PX4BASE)/Images + +# +# Tools +# +MKFW = $(PX4BASE)/Tools/px_mkfw.py +UPLOADER = $(PX4BASE)/Tools/px_uploader.py + +# +# What are we currently configured for? +# +CONFIGURED = $(PX4BASE)/.configured +ifeq ($(wildcard $(CONFIGURED)),) +# the $(CONFIGURED) target will make this a reality before building +export TARGET = px4fmu +$(shell echo $(TARGET) > $(CONFIGURED)) +else +export TARGET = $(shell cat $(CONFIGURED)) +endif + +# +# What we will build +# +FIRMWARE_BUNDLE = $(IMAGE_DIR)/$(TARGET).px4 +FIRMWARE_BINARY = $(IMAGE_DIR)/$(TARGET).bin +FIRMWARE_PROTOTYPE = $(IMAGE_DIR)/$(TARGET).prototype + +# +# Debugging +# +MQUIET = --no-print-directory +#MQUIET = --print-directory + +all: $(FIRMWARE_BUNDLE) + +# +# Generate a wrapped .px4 file from the built binary +# +$(FIRMWARE_BUNDLE): $(FIRMWARE_BINARY) $(MKFW) $(FIRMWARE_PROTOTYPE) + @echo Generating $@ + @$(MKFW) --prototype $(FIRMWARE_PROTOTYPE) \ + --git_identity $(PX4BASE) \ + --image $(FIRMWARE_BINARY) > $@ +# +# Build the firmware binary. +# +.PHONY: $(FIRMWARE_BINARY) +$(FIRMWARE_BINARY): configure_$(TARGET) setup_$(TARGET) + @echo Building $@ + @make -C $(NUTTX_SRC) -r $(MQUIET) all + @cp $(NUTTX_SRC)/nuttx.bin $@ + +# +# The 'configure' targets select one particular firmware configuration +# and makes it current. +# +configure_px4fmu: +ifneq ($(TARGET),px4fmu) + @make -C $(PX4BASE) distclean +endif + @cd $(NUTTX_SRC)/tools && /bin/sh configure.sh px4fmu/nsh + @echo px4fmu > $(CONFIGURED) + +configure_px4io: +ifneq ($(TARGET),px4io) + @make -C $(PX4BASE) distclean +endif + @cd $(NUTTX_SRC)/tools && /bin/sh configure.sh px4io/io + @echo px4io > $(CONFIGURED) + +# +# Per-configuration additional targets +# +.PHONY: px4fmu_setup +setup_px4fmu: + @echo Generating ROMFS + @make -C $(ROMFS_SRC) all + +setup_px4io: + +# +# Firmware uploading. +# + +# serial port defaults by operating system. +SYSTYPE = $(shell uname) +ifeq ($(SYSTYPE),Darwin) +SERIAL_PORTS ?= "/dev/tty.usbmodemPX1,/dev/tty.usbmodemPX2,/dev/tty.usbmodemPX3,/dev/tty.usbmodemPX4" +endif +ifeq ($(SYSTYPE),Linux) +SERIAL_PORTS ?= "/dev/ttyACM5,/dev/ttyACM4,/dev/ttyACM3,/dev/ttyACM2,/dev/ttyACM1,/dev/ttyACM0" +endif +ifeq ($(SERIAL_PORTS),) +SERIAL_PORTS = "\\\\.\\COM18,\\\\.\\COM17,\\\\.\\COM16,\\\\.\\COM15,\\\\.\\COM14,\\\\.\\COM13,\\\\.\\COM12,\\\\.\\COM11,\\\\.\\COM10,\\\\.\\COM9,\\\\.\\COM8,\\\\.\\COM7,\\\\.\\COM6,\\\\.\\COM5,\\\\.\\COM4,\\\\.\\COM3,\\\\.\\COM2,\\\\.\\COM1,\\\\.\\COM0" +endif + +upload: $(FIRMWARE_BUNDLE) $(UPLOADER) + @python -u $(UPLOADER) --port $(SERIAL_PORTS) $(FIRMWARE_BUNDLE) + +# +# Hacks and fixups +# + +ifeq ($(SYSTYPE),Darwin) +# PATH inherited by Eclipse may not include toolchain install location +export PATH := $(PATH):/usr/local/bin +endif + +# +# Cleanup targets. 'clean' should remove all built products and force +# a complete re-compilation, 'distclean' should remove everything +# that's generated leaving only files that are in source control. +# +.PHONY: clean +clean: + @make -C $(NUTTX_SRC) -r $(MQUIET) clean + @make -C $(ROMFS_SRC) -r $(MQUIET) clean + +.PHONY: distclean +distclean: + @rm -f $(CONFIGURED) + @make -C $(NUTTX_SRC) -r $(MQUIET) distclean + @make -C $(ROMFS_SRC) -r $(MQUIET) distclean + diff --git a/ROMFS/.gitignore b/ROMFS/.gitignore new file mode 100644 index 0000000000..30d3d7fe50 --- /dev/null +++ b/ROMFS/.gitignore @@ -0,0 +1 @@ +/img diff --git a/ROMFS/Makefile b/ROMFS/Makefile new file mode 100644 index 0000000000..cc5a3ccd31 --- /dev/null +++ b/ROMFS/Makefile @@ -0,0 +1,102 @@ +# +# Makefile to generate a PX4FMU ROMFS image. +# +# In normal use, 'make install' will generate a new ROMFS header and place it +# into the px4fmu configuration in the appropriate location. +# + +# +# Directories of interest +# +SRCROOT ?= $(dir $(lastword $(MAKEFILE_LIST))) +BUILDROOT ?= $(SRCROOT)/img +ROMFS_HEADER ?= $(SRCROOT)/../nuttx/configs/px4fmu/include/nsh_romfsimg.h + +# +# List of files to install in the ROMFS, specified as ~ +# +ROMFS_FSSPEC := $(SRCROOT)/scripts/rcS~init.d/rcS \ + $(SRCROOT)/scripts/rc.sensors~init.d/rc.sensors \ + $(SRCROOT)/scripts/rc.logging~init.d/rc.logging \ + $(SRCROOT)/scripts/rc.standalone~init.d/rc.standalone \ + $(SRCROOT)/scripts/rc.PX4IO~init.d/rc.PX4IO \ + $(SRCROOT)/scripts/rc.PX4IOAR~init.d/rc.PX4IOAR + +# +# Add the PX4IO firmware to the spec if someone has dropped it into the +# source directory, or otherwise specified its location. +# +# Normally this is only something you'd do when working on PX4IO; most +# users will upgrade with firmware off the microSD card. +# +PX4IO_FIRMWARE ?= $(SRCROOT)/px4io.bin +ifneq ($(wildcard $(PX4IO_FIRMWARE)),) +ROMFS_FSSPEC += $(PX4IO_FIRMWARE)~px4io.bin +endif + +################################################################################ +# No user-serviceable parts below +################################################################################ + +# +# Just the source files from the ROMFS spec, so that we can fail cleanly if they don't +# exist +# +ROMFS_SRCFILES = $(foreach spec,$(ROMFS_FSSPEC),$(firstword $(subst ~, ,$(spec)))) + +# +# Just the destination directories from the ROMFS spec +# +ROMFS_DIRS = $(sort $(dir $(foreach spec,$(ROMFS_FSSPEC),$(lastword $(subst ~, ,$(spec)))))) + + +# +# Intermediate products +# +ROMFS_IMG = $(BUILDROOT)/romfs.img +ROMFS_WORKDIR = $(BUILDROOT)/romfs + +# +# Convenience target for rebuilding the ROMFS header +# +all: $(ROMFS_HEADER) + +$(ROMFS_HEADER): $(ROMFS_IMG) $(dir $(ROMFS_HEADER)) + @echo Generating the ROMFS header... + @(cd $(dir $(ROMFS_IMG)) && xxd -i $(notdir $(ROMFS_IMG))) > $@ + +$(ROMFS_IMG): $(ROMFS_WORKDIR) + @echo Generating the ROMFS image... + @genromfs -f $@ -d $(ROMFS_WORKDIR) -V "NSHInitVol" + +$(ROMFS_WORKDIR): $(ROMFS_SRCFILES) + @echo Rebuilding the ROMFS work area... + @rm -rf $(ROMFS_WORKDIR) + @mkdir -p $(ROMFS_WORKDIR) + @for dir in $(ROMFS_DIRS) ; do mkdir -p $(ROMFS_WORKDIR)/$$dir; done + @for spec in $(ROMFS_FSSPEC) ; do \ + echo $$spec | sed -e 's%^.*~% %' ;\ + `echo "cp $$spec" | sed -e 's%~% $(ROMFS_WORKDIR)/%'` ;\ + done + +$(BUILDROOT): + @mkdir -p $(BUILDROOT) + +clean: + @rm -rf $(BUILDROOT) + +distclean: clean + @rm -f $(PX4IO_FIRMWARE) $(ROMFS_HEADER) + +.PHONY: all install clean distclean + +# +# Hacks and fixups +# +SYSTYPE = $(shell uname) + +ifeq ($(SYSTYPE),Darwin) +# PATH inherited by Eclipse may not include toolchain install location +export PATH := $(PATH):/usr/local/bin +endif + diff --git a/ROMFS/scripts/rc.PX4IO b/ROMFS/scripts/rc.PX4IO new file mode 100644 index 0000000000..e2f4fca84f --- /dev/null +++ b/ROMFS/scripts/rc.PX4IO @@ -0,0 +1,74 @@ +#!nsh +# +# Flight startup script for PX4FMU with PX4IO carrier board. +# + +echo "[init] doing PX4IO startup..." + +# +# Start the ORB +# +uorb start + +# +# Start the sensors. +# +sh /etc/init.d/rc.sensors + +# +# Start MAVLink +# +mavlink -d /dev/ttyS0 -b 57600 & + +# +# Start the commander. +# +# XXX this should be ' start'. +# +commander & + +# +# Start the attitude estimator +# +# XXX this should be ' start'. +# +attitude_estimator_bm & +#position_estimator & + +# +# Configure PX4FMU for operation with PX4IO +# +# XXX arguments? +# +px4fmu start + +# +# Start the fixed-wing controller +# +# XXX this should be ' start'. +# +fixedwing_control & + +# +# Fire up the PX4IO interface. +# +px4io start + +# +# Start looking for a GPS. +# +# XXX this should not need to be backgrounded +# +gps -d /dev/ttyS3 -m all & + +# +# Start logging to microSD if we can +# +sh /etc/init.d/rc.logging + +# +# startup is done; we don't want the shell because we +# use the same UART for telemetry (dumb). +# +echo "[init] startup done, exiting." +exit diff --git a/ROMFS/scripts/rc.PX4IOAR b/ROMFS/scripts/rc.PX4IOAR new file mode 100644 index 0000000000..d626ca213f --- /dev/null +++ b/ROMFS/scripts/rc.PX4IOAR @@ -0,0 +1,69 @@ +#!nsh +# +# Flight startup script for PX4FMU on PX4IOAR carrier board. +# + +echo "[init] doing PX4IOAR startup..." + +# +# Start the ORB +# +uorb start + +# +# Start the sensors. +# +sh /etc/init.d/rc.sensors + +# +# Start MAVLink +# +mavlink -d /dev/ttyS0 -b 57600 & + +# +# Start the commander. +# +# XXX this should be ' start'. +# +commander & + +# +# Start the attitude estimator +# +# XXX this should be ' start'. +# +attitude_estimator_bm & +#position_estimator & + +# +# Configure PX4FMU for operation with PX4IOAR +# +# XXX arguments? +# +px4fmu start + +# +# Fire up the AR.Drone controller. +# +# XXX this should be ' start'. +# +ardrone_control -d /dev/ttyS1 -m attitude & + +# +# Start looking for a GPS. +# +# XXX this should not need to be backgrounded +# +gps -d /dev/ttyS3 -m all & + +# +# Start logging to microSD if we can +# +sh /etc/init.d/rc.logging + +# +# startup is done; we don't want the shell because we +# use the same UART for telemetry (dumb). +# +echo "[init] startup done, exiting." +exit diff --git a/ROMFS/scripts/rc.jig b/ROMFS/scripts/rc.jig new file mode 100644 index 0000000000..e2b5d8f30d --- /dev/null +++ b/ROMFS/scripts/rc.jig @@ -0,0 +1,10 @@ +#!nsh +# +# Test jig startup script +# + +echo "[testing] doing production test.." + +tests jig + +echo "[testing] testing done" diff --git a/ROMFS/scripts/rc.logging b/ROMFS/scripts/rc.logging new file mode 100644 index 0000000000..cbc303dab1 --- /dev/null +++ b/ROMFS/scripts/rc.logging @@ -0,0 +1,10 @@ +#!nsh +# +# Initialise logging services. +# + +if [ -d /fs/microsd ] +then + # XXX this should be ' start'. + # sdlog & +fi diff --git a/ROMFS/scripts/rc.sensors b/ROMFS/scripts/rc.sensors new file mode 100644 index 0000000000..7515c1947e --- /dev/null +++ b/ROMFS/scripts/rc.sensors @@ -0,0 +1,28 @@ +#!nsh +# +# Standard startup script for PX4FMU onboard sensor drivers. +# + +# +# Start sensor drivers here. +# + +#ms5611 start + +# +# Start the sensor collection task. +# +# XXX should be 'sensors start' +# +sensors & + +# +# Test sensor functionality +# +# XXX integrate with 'sensors start' ? +# +#if sensors quicktest +#then +# echo "[init] sensor initialisation FAILED." +# reboot +#fi diff --git a/ROMFS/scripts/rc.standalone b/ROMFS/scripts/rc.standalone new file mode 100644 index 0000000000..72153ef183 --- /dev/null +++ b/ROMFS/scripts/rc.standalone @@ -0,0 +1,67 @@ +#!nsh +# +# Flight startup script for PX4FMU standalone configuration. +# + +echo "[init] doing standalone PX4FMU startup..." + +# +# Start the ORB +# +#uorb start + +# +# Start the sensors. +# +#sh /etc/init.d/rc.sensors + +# +# Start MAVLink +# +# mavlink -d /dev/ttyS0 -b 57600 & + +# +# Start the commander. +# +# XXX this should be 'commander start'. +# +#commander & + +# +# Start the attitude estimator +# +# XXX this should be ' start'. +# +#attitude_estimator_bm & +#position_estimator & + +# +# Start the fixed-wing controller. +# +# XXX should this be looking for configuration to decide +# whether the board is configured for fixed-wing use? +# +# XXX this should be 'fixedwing_control start'. +# +#fixedwing_control & + +# +# Configure FMU for standalone mode +# +# XXX arguments? +# +#px4fmu start + +# +# Start looking for a GPS. +# +# XXX this should not need to be backgrounded +# +#gps -d /dev/ttyS3 -m all & + +# +# Start logging to microSD if we can +# +sh /etc/init.d/rc.logging + +echo "[init] startup done" diff --git a/ROMFS/scripts/rcS b/ROMFS/scripts/rcS new file mode 100755 index 0000000000..9b9a2fd614 --- /dev/null +++ b/ROMFS/scripts/rcS @@ -0,0 +1,120 @@ +#!nsh +# +# PX4FMU startup script. +# +# This script is responsible for: +# +# - mounting the microSD card (if present) +# - running the user startup script from the microSD card (if present) +# - detecting the configuration of the system and picking a suitable +# startup script to continue with +# +# Note: DO NOT add configuration-specific commands to this script; +# add them to the per-configuration scripts instead. +# + +# +# Default to auto-start mode. An init script on the microSD card +# can change this to prevent automatic startup of the flight script. +# +set MODE autostart +set USB_ALLOWED yes +set USB no + +# +# Try to mount the microSD card. +# +echo "[init] looking for microSD..." +if mount -t vfat /dev/mmcsd0 /fs/microsd +then + echo "[init] card mounted at /fs/microsd" +else + echo "[init] no microSD card found" +fi + +# +# Look for an init script on the microSD card. +# +# To prevent automatic startup in the current flight mode, +# the script should set MODE to some other value. +# +if [ -f /fs/microsd/etc/rc ] +then + echo "[init] reading /fs/microsd/etc/rc" + sh /fs/microsd/etc/rc +fi + +# +# Check for USB host +# +if [ $USB_ALLOWED == yes ] +then + if sercon + then + echo "[init] USB interface connected" + fi +fi + +# +# If we are still in flight mode, work out what airframe +# configuration we have and start up accordingly. +# +if [ $MODE != autostart ] +then + echo "[init] automatic startup cancelled by user script" +else + echo "[init] detecting attached hardware..." + + # + # Assume that we are PX4FMU in standalone mode + # + set BOARD PX4FMU + + # + # Are we attached to a PX4IOAR (AR.Drone carrier board)? + # + if boardinfo -t 7 + then + set BOARD PX4IOAR + if [ -f /etc/init.d/rc.PX4IOAR ] + then + echo "[init] reading /etc/init.d/rc.PX4IOAR" + sh /etc/init.d/rc.PX4IOAR + fi + else + echo "[init] PX4IOAR not detected" + fi + + # + # Are we attached to a PX4IO? + # + if boardinfo -t 6 + then + set BOARD PX4IO + if [ -f /etc/init.d/rc.PX4IO ] + then + echo "[init] reading /etc/init.d/rc.PX4IO" + sh /etc/init.d/rc.PX4IO + fi + else + echo "[init] PX4IO not detected" + fi + + # + # Looks like we are stand-alone + # + if [ $BOARD == PX4FMU ] + then + echo "[init] no expansion board detected" + if [ -f /etc/init.d/rc.standalone ] + then + echo "[init] reading /etc/init.d/rc.standalone" + sh /etc/init.d/rc.standalone + fi + fi + + # + # We may not reach here if the airframe-specific script exits the shell. + # + echo "[init] startup done." +fi diff --git a/Tools/fix_code_style.sh b/Tools/fix_code_style.sh new file mode 100755 index 0000000000..832ee79da6 --- /dev/null +++ b/Tools/fix_code_style.sh @@ -0,0 +1,19 @@ +#!/bin/sh +astyle \ + --style=linux \ + --indent=force-tab=8 \ + --indent-cases \ + --indent-preprocessor \ + --break-blocks=all \ + --pad-oper \ + --pad-header \ + --unpad-paren \ + --keep-one-line-blocks \ + --keep-one-line-statements \ + --align-pointer=name \ + --align-reference=name \ + --suffix=none \ + --ignore-exclude-errors-x \ + --lineend=linux \ + --exclude=EASTL \ + $* diff --git a/Tools/px_mkfw.py b/Tools/px_mkfw.py new file mode 100755 index 0000000000..9f4ddad62e --- /dev/null +++ b/Tools/px_mkfw.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# PX4 firmware image generator +# +# The PX4 firmware file is a JSON-encoded Python object, containing +# metadata fields and a zlib-compressed base64-encoded firmware image. +# + +import sys +import argparse +import json +import base64 +import zlib +import time +import subprocess + +# +# Construct a basic firmware description +# +def mkdesc(): + proto = {} + proto['magic'] = "PX4FWv1" + proto['board_id'] = 0 + proto['board_revision'] = 0 + proto['version'] = "" + proto['summary'] = "" + proto['description'] = "" + proto['git_identity'] = "" + proto['build_time'] = 0 + proto['image'] = base64.b64encode(bytearray()) + proto['image_size'] = 0 + return proto + +# Parse commandline +parser = argparse.ArgumentParser(description="Firmware generator for the PX autopilot system.") +parser.add_argument("--prototype", action="store", help="read a prototype description from a file") +parser.add_argument("--board_id", action="store", help="set the board ID required") +parser.add_argument("--board_revision", action="store", help="set the board revision required") +parser.add_argument("--version", action="store", help="set a version string") +parser.add_argument("--summary", action="store", help="set a brief description") +parser.add_argument("--description", action="store", help="set a longer description") +parser.add_argument("--git_identity", action="store", help="the working directory to check for git identity") +parser.add_argument("--image", action="store", help="the firmware image") +args = parser.parse_args() + +# Fetch the firmware descriptor prototype if specified +if args.prototype != None: + f = open(args.prototype,"r") + desc = json.load(f) + f.close() +else: + desc = mkdesc() + +desc['build_time'] = int(time.time()) + +if args.board_id != None: + desc['board_id'] = int(args.board_id) +if args.board_revision != None: + desc['board_revision'] = int(args.board_revision) +if args.version != None: + desc['version'] = str(args.version) +if args.summary != None: + desc['summary'] = str(args.summary) +if args.description != None: + desc['description'] = str(args.description) +if args.git_identity != None: + cmd = " ".join(["git", "--git-dir", args.git_identity + "/.git", "describe", "--always", "--dirty"]) + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout + desc['git_identity'] = p.read().strip() + p.close() +if args.image != None: + f = open(args.image, "rb") + bytes = f.read() + desc['image_size'] = len(bytes) + desc['image'] = base64.b64encode(zlib.compress(bytes,9)) + +print json.dumps(desc, indent=4) diff --git a/Tools/px_uploader.py b/Tools/px_uploader.py new file mode 100755 index 0000000000..89ceda3d2a --- /dev/null +++ b/Tools/px_uploader.py @@ -0,0 +1,318 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Serial firmware uploader for the PX4FMU bootloader +# +# The PX4 firmware file is a JSON-encoded Python object, containing +# metadata fields and a zlib-compressed base64-encoded firmware image. +# +# The uploader uses the following fields from the firmware file: +# +# image +# The firmware that will be uploaded. +# image_size +# The size of the firmware in bytes. +# board_id +# The board for which the firmware is intended. +# board_revision +# Currently only used for informational purposes. +# + +import sys +import argparse +import binascii +import serial +import os +import struct +import json +import zlib +import base64 +import time + +from sys import platform as _platform + +class firmware(object): + '''Loads a firmware file''' + + desc = {} + image = bytearray() + + def __init__(self, path): + + # read the file + f = open(path, "r") + self.desc = json.load(f) + f.close() + + self.image = zlib.decompress(base64.b64decode(self.desc['image'])) + + def property(self, propname): + return self.desc[propname] + + +class uploader(object): + '''Uploads a firmware file to the PX FMU bootloader''' + + NOP = chr(0x00) + OK = chr(0x10) + FAILED = chr(0x11) + INSYNC = chr(0x12) + EOC = chr(0x20) + GET_SYNC = chr(0x21) + GET_DEVICE = chr(0x22) + CHIP_ERASE = chr(0x23) + CHIP_VERIFY = chr(0x24) + PROG_MULTI = chr(0x27) + READ_MULTI = chr(0x28) + REBOOT = chr(0x30) + + INFO_BL_REV = chr(1) # bootloader protocol revision + BL_REV = 2 # supported bootloader protocol + INFO_BOARD_ID = chr(2) # board type + INFO_BOARD_REV = chr(3) # board revision + INFO_FLASH_SIZE = chr(4) # max firmware size in bytes + + PROG_MULTI_MAX = 60 # protocol max is 255, must be multiple of 4 + READ_MULTI_MAX = 60 # protocol max is 255, something overflows with >= 64 + + def __init__(self, portname, baudrate): + # open the port + self.port = serial.Serial(portname, baudrate, timeout=10) + + def close(self): + if self.port is not None: + self.port.close() + + def __send(self, c): +# print("send " + binascii.hexlify(c)) + self.port.write(str(c)) + + def __recv(self, count = 1): + c = self.port.read(count) + if (len(c) < 1): + raise RuntimeError("timeout waiting for data") +# print("recv " + binascii.hexlify(c)) + return c + + def __getSync(self): + self.port.flush() + c = self.__recv() + if (c != self.INSYNC): + raise RuntimeError("unexpected 0x%x instead of INSYNC" % ord(c)) + c = self.__recv() + if (c != self.OK): + raise RuntimeError("unexpected 0x%x instead of OK" % ord(c)) + + # attempt to get back into sync with the bootloader + def __sync(self): + # send a stream of ignored bytes longer than the longest possible conversation + # that we might still have in progress +# self.__send(uploader.NOP * (uploader.PROG_MULTI_MAX + 2)) + self.port.flushInput() + self.__send(uploader.GET_SYNC + + uploader.EOC) + self.__getSync() + + def __trySync(self): + c = self.__recv() + if (c != self.INSYNC): + #print("unexpected 0x%x instead of INSYNC" % ord(c)) + return False; + c = self.__recv() + if (c != self.OK): + #print("unexpected 0x%x instead of OK" % ord(c)) + return False + return True + + # send the GET_DEVICE command and wait for an info parameter + def __getInfo(self, param): + self.__send(uploader.GET_DEVICE + param + uploader.EOC) + raw = self.__recv(4) + self.__getSync() + value = struct.unpack_from(' + + * Initial version of the apps/ directory was released as contributed by + Uros Platise. + +6.0 2011-03-21 Gregory Nutt + + * README.txt -- README cosmetics + * hello/ -- hello world minor changes + * Makefile -- Makefile cosmetics (I am slowly adding the Darjeeling JVM) + * Make.defs -- New file adds common make definitions for applications. + * hello/Makefile -- Now uses new Make.defs definitions. Added README.txt. + * apps/poweroff -- New application to turn off board power. + * Moved NSH library, netutils, and examples from the nuttx/ directory to + the apps/ directory + * Moved exec_nuttapp machinery into the nuttapp/ directory. + +6.1 2011-04-10 Gregory Nutt + + * Creation of auto-generated header files now occurs during the context + build phase. + * Added sdcard insert and eject, nsh command '?' and some code remarks + * Renamed nuttapp to namedapp + * namedapp/binfs.c -- Create a tiny filesystem that can be used + to show the internal named apps under /bin. + * Numerous fixes to build system required to support building with native + Windows toolchain. + +6.2 2011-05-06 Gregory Nutt + + * apps/examples/nxffs: Add a test a a configuration that will be used to + verify NXFFS. + +6.3 2011-05-15 Gregory Nutt + + * apps/interpreter: Add a directory to hold interpreters. The Pascal add- + on module now installs and builds under this directory. + * apps/interpreter/ficl: Added logic to build Ficl (the "Forth Inspired + Command Language"). See http://ficl.sourceforge.net/. + * apps/netutils/dhcpc, dhcpcd, and tftp. If these directories are included + in the configuration but CONFIG_NET_UDP is disable (which is not very wise), + then a make error occurs because tools/mkdep.sh is called with no files. + * system/free: Move Uros' custom free command from vsn/free + * system/install: Add a new install command submitted by Uros Platise. + * examples/rgmp. Add a placeholder for an RGMP build example. + RGMP is a project for running GPOS and RTOS simultaneously on + multi-processor platforms. See http://rgmp.sourceforge.net/wiki/index.php/Main_Page + for further information about RGMP. NOTE: This is an empty example + on initial check-in. + +6.4 2011-06-06 Gregory Nutt + + * nshlib/nsh_netcmds.c: If a network device name and IP address are provided + with the ifconfig command, then this command will now set the network address. + (Contributed by Yu Qiang). + * netutils/ftpc: A library to support client-side FTP. + * examples/ftpc: A simple add-on to the NSH. From NSH, you can start + this simple FTP shell to transfer files to/from a remote FTP server. + +6.5 2011-06-21 Gregory Nutt + + * netutils/ftpc: Simpflication and size reduction. + +6.6 2011-07-11 Gregory Nutt + + * Make.defs, namedapp/namedapp.c: Several structural changes made to get a + clean compile under the ez80 ZDS-II toolchain (no design changes). + * apps/examples/buttons: Add a test for the new standardized button interfaces + * apps/examples/nxtext: Add another NX graphics test. This one focus on + placing text on the background while pop-up windows occur. Text should + continue to update normally with or without the popup windows present. + +6.7 2011-08-02 Gregory Nutt + + * apps/examples/nx and nxtext: These examples can now be built as NSH + "built-in" commands. + * apps/examples/nxhello: The simplest graphics example: It just says + "Hello, World!" in the center of the display. This example can also be + built as an NSH "built-in" command. + * apps/examples/nx, ntext, and nxhello: All updated to use the new + NuttX font interfaces. + * apps/examples/nximage: Another super simple graphics example: It just puts + the NuttX logo in the center of the display. This example can also be + built as an NSH "built-in" command. + * apps/examples/usbstorage: Can now be built as two NSH "built-in" commands: + 'msconn' will connect the USB mass storage device; 'msdis' will disconnect + the USB storage device. + * apps/examples/nx*: All NX header files moved from nuttx/include/nuttx to + nuttx/include/nuttx/nx. + * apps/examples/usbstorage: Added instrumentation to monitor memory usage + to check for memory leaks in the USB storage driver. + * apps/examples/nxhello/nxhello_bkgd.c: Fix handling of allocated glyph + memory. + +6.8 2011-08-11 Gregory Nutt + + * apps/examples/nxlines: Added a test for NX line drawing capabilities. + +6.9 2011-09-11 Gregory Nutt + + * apps/examples/nxlines: Extend the line drawing text to include drawing + of circles. + * apps/system/i2c: Add an I2C test tool that should help to bring up I2C + devices (when it is fully functional). + * apps/nshlib/nsh_timcmds.c: Add the date command that can be used to + show or set the time (only if CONFIG_RTC is set). + +6.10 2011-10-06 Gregory Nutt + + * apps/system/i2c: Add repitition and address auto-incrementing so that + and command can be executed numerous times. Add a new verify command + that will write to a register, read from register, and verify that + returned value. + * apps/graphics/tiff: Add a library that can be used to create TIFF files. + * apps/examples/tiff: Add a unit test for the TIFF file creation logic + * apps/examples/lcdrw: Add a test to verify if you can or can or read + data from an LCD correctly. + * apps/examples/usbterm: A USB terminal example.. more of a USB chat or + serial bridge: Data received on local console echoed via USB serial; + data received on USB serial is echoed on the local console. + * apps/examples/touchscreen: Add a simple, generic test for any + touschscreen driver. + * Makefile: The apps/ Makefile now checks for an apps/external directory + or symbolic link. If such a directory/link exists (and has a Makefile), + it will be added to the apps/ build. This allows external directories + to be included into the apps/ build by simply creating a symbolic link. + +6.11 2011-11-12 Gregory Nutt + + (No major changes from 6.10) + +6.12 2011-12-06 Gregory Nutt + + * apps/examples/buttons: The button test can now be executed as an NSH + built in command. + +6.13 2012-12-26 Gregory Nutt + + * apps/examples/dhcpd: May now be built as an NSH built-in application + by setting CONFIG_NSH_BUILTIN_APPS. + * apps/netutils/dhcpd/dhcpd.c: Fix several problems using host order address + where network addresses expected (and vice versa). + * apps/examples/nettest: May now be built as an NSH built-in application + by setting CONFIG_NSH_BUILTIN_APPS. + * apps/examples/nettest: Correct some build issues with the nettest is + built for performance evaluation. + * apps/examples/adc: Add a very simple test to drive and test an ADC + driver. + * apps/examples/pwm: Add an NSH PWM command to drive and test a PWM + driver. + * apps/examples/can: Add an NSH CAN command to drive and test a CAN + driver in loopback mode. + +6.14 2012-01-15 Gregory Nutt + + * apps/examples/buttons/main.c: The test needs to call up_buttoninit() to + properly configure the button interrupt GPIOs. + * apps/examples/pwm: Add support to test the pulse count option recently + added to the PWM interface. + +6.15 2012-02-12 Gregory Nutt + + * apps/nshlib/nsh_serial.c and nsh_usbdev.c: If NuttX is configured to use + a USB serial console, then NSH needs to wait until the USB console is + connected and available. + * apps/examples/composite: Add a test of the USB composite device. + * apps/examples/Telnetd: Move the tiny uIP shell example from + netutils/Telnetd to examples/Telnetd. Enhanced the Telnetd daemon so that + it supports Telnetd via a TTY device driver: A new TTY device driver is + created when each new Telnet connection is created. The shell thread + is started with stdin, stdout, and stderr mapped to the TTY device. + * netutils/Telnetd: The old uIP Telnet demo is gone. In its place is a new + Telnet infrastructure. The new Telnet daemon creates sessions that are + "wrapped" as character devices and mapped to stdin, stdout, and stderr. + Now the Telnet session can be inherited by spawned tasks. + * examples/Telnetd: Add a test for the new Telnet daemon. + * examples/Telnetd/telnetd_driver.c: Move the internal socket structure from + the daemon's socket array into the driver's state data so that it will be + independent from the the Telnetd daemon. + * apps/system/readline: Moved the old nuttx/lib/stdio/lib_fgets.c here + and renamed it as readline(). The old fgets was simplied and the overloaded + readline functionality was removed. + * apps/netutils/ftpd: Add an FTPD server (does not even compile on initial + checkin). + * apps/examples/ftpd: Add a test for the FTPD server (untest on initial + check-in). + * apps/nshlib/nsh_fscmds.c: Add support for a 'dmesg' command that will + dump the system log if CONFIG_SYSLOG is selected. + +6.16 2012-03-10 Gregory Nutt + + * apps/examples/qencoder: Add a quadrature driver test. + * apps/examples/ostest/fpu.c: Add a test to verify that FPU registers + are properly saved and restored on context switches. + * apps/system/readline/readline.c: readline() will now treat either a + backspace or a DEL character as a backspace (i.e., deleting the character + to the left of the cursor). This makes NSH less dependent on particular + keyboard mappings of the Backspace key. Submitted by Mike Smith. + * apps/examples/cdcacm: An example that illustrates how the CDC/ACM driver + may to connected and disconnected through software control. + * apps/examples/nsh/nsh_main.c: If available, call up_cxxinitialize() to + initialize all statically defined C++ classes. + * apps/nshlib: Now supports a USB serial device for NSH console I/O. This + allows NSH to be used on boards that have USB but no serial connectors. + +6.17 2012-04-14 Gregory Nutt + + * apps/examples/can: Add conditional compilation so that the test can be + configured to only send messages or to only receive messages. This will + let the test work in other modes than simple loopback testing. + * apps/examples/hello and apps/examples/ostest: Can now be built as NSH + built-int functions. + * vsn/hello: Removed. The modified apps/examples/hello is enough "Hello, + World!" + * apps/examples/nxconsole: Add a test of the NX console device. + * apps/examples/nxconsole: The NX console example now supports running + the NuttShell (NSH) within an NX window. + * apps/system/readline: Now uses standard definitions from + include/nuttx/ascii.h and vt100.h + * Kconfig, */Kconfig: Added skeleton Kconfig files to all directories that + may need them. + +6.18 2012-05-19 Gregory Nutt + + * Kconfig: Continued Kconfig file updates (no longer tracking on a per-file + basis in the ChangeLog) + * apps/examples/watchdog: Add a watchdog timer example. + * apps/examples/tiff: Fix wrong path used for temporary file. + * apps/examples/touchscreen: Standardize the board-specific, touchscreen + initialization interfaces. + +6.19 2012-06-15 Gregory Nutt + + * apps/nshlib/nsh_usbdev.c: Add the capability to use an arbitrary USB + device as the console (not necessarily /dev/console). This is a useful + option because then you can still use the serial console to debug with. + * apps/nshlib/nsh_usbdev.c: User now has to press ENTER 3 times before + USB console will start. Otherwise, the USB console starts before there + is anyone at the other end to listen. + * apps/nshlib/nsh_usbdev.c and nsh_consolemain.c: Add support for the USB + capability when a USB console is used. + * apps/nshlib/nsh_fscmds.c: Add the 'mv' command + +6.20 2012-07-12 Gregory Nutt + + * namedapp/exec_namedapp.c - Correct an error when round robin scheduling + is enabled. The priority of the new, named application was erroneously + being set to the priority of the parent thread; losing its configured + priority. Reported by Mike Smith. + +6.21 2012-xx-xx Gregory Nutt + + * apps/include/: Stylistic clean-up of all header files. + * apps/modbus and apps/include/modbus: A port of freemodbus-v1.5.0 + has been added to the NuttX apps/ source tree. + * apps/examples/modbus: A port of the freemodbus-v1.5.0 "demo" + program that will be used to verify the FreeModBus port + * apps/modbus: Don't use strerror(). It is just too big. + * apps/modbus: Add CONFIG_MB_TERMIOS. If the driver doesn't support + termios ioctls, then don't bother trying to configure the baud, parity + etc. + * apps/nslib: If waitpid() is supported, then NSH not catches the + return value from spawned applications (provided by Mike Smith) + * apps/nslib: Lock the schedule while starting built-in applications + in order to eliminate race conditions (also from Mike Smith). + * apps/examples/adc, pwm, and qencoder: Add support for testing + devices with multiple ADC, PWM, and QE devices. + * apps/nshlib/nsh_mntcmds.c: Separated mount-related commands out of + nsh_fscmds.c. Extended to the mount command so that if no arguments + are provided, then the current mountpoints are enumerated. + * apps/nshlib/nsh_mntcmds.c: Add an NSH df command to list the + properties of mounted file systems. diff --git a/apps/Kconfig b/apps/Kconfig new file mode 100644 index 0000000000..1f38c58baf --- /dev/null +++ b/apps/Kconfig @@ -0,0 +1,36 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +menu "Named Applications" +source "$APPSDIR/namedapp/Kconfig" +endmenu + +menu "Examples" +source "$APPSDIR/examples/Kconfig" +endmenu + +menu "Interpreters" +source "$APPSDIR/interpreters/Kconfig" +endmenu + +menu "Network Utilities" +source "$APPSDIR/netutils/Kconfig" +endmenu + +menu "ModBus" +source "$APPSDIR/modbus/Kconfig" +endmenu + +menu "NSH Library" +source "$APPSDIR/nshlib/Kconfig" +endmenu + +menu "System NSH Add-Ons" +source "$APPSDIR/system/Kconfig" +endmenu + +menu "VSN board Add-Ons" +source "$APPSDIR/vsn/Kconfig" +endmenu diff --git a/apps/Make.defs b/apps/Make.defs new file mode 100644 index 0000000000..f37a654c47 --- /dev/null +++ b/apps/Make.defs @@ -0,0 +1,41 @@ +############################################################################ +# apps/Make.defs +# Common make definitions provided to all applications +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +define REGISTER + @echo "Register: $1" + @echo "{ \"$1\", $2, $3, $4 }," >> "$(APPDIR)/namedapp/namedapp_list.h" + @echo "EXTERN int $4(int argc, char *argv[]);" >> "$(APPDIR)/namedapp/namedapp_proto.h" +endef diff --git a/apps/Makefile b/apps/Makefile new file mode 100644 index 0000000000..f087b7c33a --- /dev/null +++ b/apps/Makefile @@ -0,0 +1,176 @@ +############################################################################ +# apps/Makefile +# +# Copyright (C) 2011-2012 Uros Platise. All rights reserved. +# Authors: Uros Platise +# Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs +-include $(TOPDIR)/.config + +APPDIR = ${shell pwd} + +# Application Directories + +# CONFIGURED_APPS is the list of all configured built-in directories/built +# action. It is created by the configured appconfig file (a copy of which +# appears in this directory as .config) +# SUBDIRS is the list of all directories containing Makefiles. It is used +# only for cleaning. namedapp must always be the first in the list. This +# list can be extended by the .config file as well + +CONFIGURED_APPS = +#SUBDIRS = examples graphics interpreters modbus namedapp nshlib netutils system vsn +ALL_SUBDIRS = $(dir $(shell /usr/bin/find . -name Makefile)) +SUBDIRS = namedapp/ $(filter-out ./ ./namedapp/ ./examples/,$(ALL_SUBDIRS)) + + +# There are two different mechanisms for obtaining the list of configured +# directories: +# +# (1) In the legacy method, these paths are all provided in the appconfig +# file that is copied to the top-level apps/ directory as .config +# (2) With the development of the NuttX configuration tool, however, the +# selected applications are now enabled by the configuration tool. +# The apps/.config file is no longer used. Instead, the set of +# configured build directories can be found by including a Make.defs +# file contained in each of the apps/subdirectories. +# +# When the NuttX configuration tools executes, it will always define the +# configure CONFIG_NUTTX_NEWCONFIG to select between these two cases. Then +# legacy appconfig files will still work but newly configuration files will +# also work. Eventually the CONFIG_NUTTX_NEWCONFIG option will be phased +# out. + +ifeq ($(CONFIG_NUTTX_NEWCONFIG),y) + +-include examples/Make.defs +-include graphics/Make.defs +-include interpreters/Make.defs +-include modbus/Make.defs +-include namedapp/Make.defs +-include netutils/Make.defs +-include nshlib/Make.defs +-include system/Make.defs +-include vsn/Make.defs + +# INSTALLED_APPS is the list of currently available application directories. It +# is the same as CONFIGURED_APPS, but filtered to exclude any non-existent +# application directory. namedapp is always in the list of applications to be +# built. + +INSTALLED_APPS = + +# The legacy case: + +else +-include .config + +# INSTALLED_APPS is the list of currently available application directories. It +# is the same as CONFIGURED_APPS, but filtered to exclude any non-existent +# application directory. namedapp is always in the list of applications to be +# built. + +INSTALLED_APPS = namedapp +endif + +# Create the list of available applications (INSTALLED_APPS) + +define ADD_BUILTIN +INSTALLED_APPS += ${shell if [ -r $1/Makefile ]; then echo "$1"; fi} +endef + +$(foreach BUILTIN, $(CONFIGURED_APPS), $(eval $(call ADD_BUILTIN,$(BUILTIN)))) + +# The external/ directory may also be added to the INSTALLED_APPS. But there +# is no external/ directory in the repository. Rather, this directory may be +# provided by the user (possibly as a symbolic link) to add libraries and +# applications to the standard build from the repository. + +INSTALLED_APPS += ${shell if [ -r external/Makefile ]; then echo "external"; fi} +SUBDIRS += ${shell if [ -r external/Makefile ]; then echo "external"; fi} + +# The final build target + +BIN = libapps$(LIBEXT) + +# Build targets + +all: $(BIN) +.PHONY: $(INSTALLED_APPS) context depend clean distclean + +$(INSTALLED_APPS): + @$(MAKE) -C $@ TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; + +$(BIN): $(INSTALLED_APPS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +.context: + @for dir in $(INSTALLED_APPS) ; do \ + rm -f $$dir/.context ; \ + $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" context ; \ + done + @touch $@ + +context: .context + +.depend: context Makefile $(SRCS) + @for dir in $(INSTALLED_APPS) ; do \ + rm -f $$dir/.depend ; \ + $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" depend ; \ + done + @touch $@ + +depend: .depend + +clean: + @for dir in $(SUBDIRS) ; do \ + $(MAKE) -C $$dir clean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + @rm -f $(BIN) *~ .*.swp *.o + $(call CLEAN) + +distclean: # clean + @for dir in $(SUBDIRS) ; do \ + $(MAKE) -C $$dir distclean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + @rm -f .config .context .depend + @( if [ -e external ]; then \ + echo "********************************************************"; \ + echo "* The external directory/link must be removed manually *"; \ + echo "********************************************************"; \ + fi; \ + ) + + diff --git a/apps/README.txt b/apps/README.txt new file mode 100644 index 0000000000..6a78da4b54 --- /dev/null +++ b/apps/README.txt @@ -0,0 +1,211 @@ +Application Folder +================== + +Contents +-------- + + General + Directory Location + Named Applications + Named Startup main() function + NuttShell (NSH) Built-In Commands + Synchronous Built-In Commands + Application Configuration File + Example Named Application + Building NuttX with Board-Specific Pieces Outside the Source Tree + +General +------- +This folder provides various applications found in sub-directories. These +applications are not inherently a part of NuttX but are provided you help +you develop your own applications. The apps/ directory is a "break away" +part of the configuration that you may chose to use or not. + +Directory Location +------------------ +The default application directory used by the NuttX build should be named +apps/ (or apps-x.y/ where x.y is the NuttX version number). This apps/ +directory should appear in the directory tree at the same level as the +NuttX directory. Like: + + . + |- nuttx + | + `- apps + +If all of the above conditions are TRUE, then NuttX will be able to +find the application directory. If your application directory has a +different name or is location at a different position, then you will +have to inform the NuttX build system of that location. There are several +ways to do that: + +1) You can define CONFIG_APPS_DIR to be the full path to your application + directory in the NuttX configuration file. +2) You can provide the path to the application directory on the command line + like: make APPDIR= or make CONFIG_APPS_DIR= +3) When you configure NuttX using tools/configure.sh, you can provide that + path to the application directory on the configuration command line + like: ./configure.sh -a / + +Named Applications +------------------ +NuttX also supports applications that can be started using a name string. +In this case, application entry points with their requirements are gathered +together in two files: + + - namedapp/namedapp_proto.h Entry points, prototype function + - namedapp/namedapp_list.h Application specific information and requirements + +The build occurs in several phases as different build targets are executed: +(1) context, (2) depend, and (3) default (all). Application information is +collected during the make context build phase. + +To execute an application function: + + exec_namedapp() is defined in the nuttx/include/apps/apps.h + +NuttShell (NSH) Built-In Commands +--------------------------------- +One use of named applications is to provide a way of invoking your custom +application through the NuttShell (NSH) command line. NSH will support +a seamless method invoking the applications, when the following option is +enabled in the NuttX configuration file: + + CONFIG_NSH_BUILTIN_APPS=y + +Applications registered in the apps/namedapp/namedapp_list.h file will then +be accessible from the NSH command line. If you type 'help' at the NSH +prompt, you will see a list of the registered commands. + +Synchronous Built-In Commands +----------------------------- +By default, built-in commands started from the NSH command line will run +asynchronously with NSH. If you want to force NSH to execute commands +then wait for the command to execute, you can enable that feature by +adding the following to the NuttX configuration file: + +CONFIG_SCHED_WAITPID=y + +The configuration option enables support for the waitpid() RTOS interface. +When that interface is enabled, NSH will use it to wait, sleeping until +the built-in command executes to completion. + +Of course, even with CONFIG_SCHED_WAITPID=y defined, specific commands +can still be forced to run asynchronously by adding the ampersand (&) +after the NSH command. + +Application Configuration File +------------------------------ +A special configuration file is used to configure which applications +are to be included in the build. The source for this file is +configs///appconfig. The existence of the appconfig +file in the board configuration directory is sufficient to enable building +of applications. + +The appconfig file is copied into the apps/ directory as .config when +NuttX is configured. .config is included in the toplevel apps/Makefile. +As a minimum, this configuration file must define files to add to the +CONFIGURED_APPS list like: + + CONFIGURED_APPS += examples/hello vsn/poweroff + +Named Start-Up main() function +------------------------------ +A named application can even be used as the main, start-up entry point +into your embedded software. When the user defines this option in +the NuttX configuration file: + + CONFIG_BUILTIN_APP_START= + +that application shall be invoked immediately after system starts +*instead* of the normal, default "user_start" entry point. +Note that must be provided as: "hello", +will call: + + int hello_main(int argc, char *argv[]) + +Example Named Application +------------------------- +An example application skeleton can be found under the examples/hello +sub-directory. This example shows how a named application can be added +to the project. One must define: + + 1. create sub-directory as: appname + 2. provide entry point: appname_main() + 3. set the requirements in the file: Makefile, specially the lines: + + APPNAME = appname + PRIORITY = SCHED_PRIORITY_DEFAULT + STACKSIZE = 768 + ASRCS = asm source file list as a.asm b.asm ... + CSRCS = C source file list as foo1.c foo2.c .. + + 4. add application in the apps/.config + +Building NuttX with Board-Specific Pieces Outside the Source Tree +----------------------------------------------------------------- + +Q: Has anyone come up with a tidy way to build NuttX with board- + specific pieces outside the source tree? +A: Here are four: + + 1) There is a make target called 'make export'. It will build + NuttX, then bundle all of the header files, libaries, startup + objects, and other build components into a .zip file. You + can can move that .zip file into any build environment you + want. You even build NuttX under a DOS CMD window. + + This make target is documented in the top level nuttx/README.txt. + + 2) You can replace the entire apps/ directory. If there is + nothing in the apps/ directory that you need, you can define + CONFIG_APPS_DIR in your .config file so that it points to a + different, custom application directory. + + You can copy any pieces that you like from the old apps/directory + to your custom apps directory as necessary. + + This is documented in NuttX/configs/README.txt and + nuttx/Documentation/NuttxPortingGuide.html (Online at + http://nuttx.sourceforge.net/NuttxPortingGuide.html#apndxconfigs + under Build options). And in the apps/README.txt file. + + 3) If you like the random collection of stuff in the apps/ directory + but just want to expand the existing components with your own, + external sub-directory then there is an easy way to that too: + You just create the sympolic link at apps/external that + redirects to your application sub-directory. The apps/Makefile + will always automatically check for the existence of an + apps/external directory and if it exists, it will automatically + incorporate it into the build. + + This feature of the apps/Makefile is documented only here. + + You can, for example, create a script called install.sh that + installs a custom application, configuration, and board specific + directory: + + a) Copy 'MyBoard' directory to configs/MyBoard. + b) Add a symbolic link to MyApplication at apps/external + c) Configure NuttX (usually by: + + tools/configure.sh MyBoard/MyConfiguration + + or simply by copying defconfig->nutt/.config, + setenv.sh->nuttx/setenv.sh, Make.defs->nuttx/Make.defs, + appconfig->apps/.config + + Using the 'external' link makes it especially easy to add a + 'built-in' application an existing configuration. + + 4) Add any link to apps/ + + a) Add symbolic links apps/ to as many other directories as you + want. + b) Then just add the (relative) paths to the links in your + appconfig file (that becomes the apps/.config file). + + That is basically the same as my option #3 but doesn't use the + magic 'external' link. The toplevel apps/Makefile will always + to build whatever in finds in the apps/.config file (plus the + external link if present). diff --git a/apps/_dontignore b/apps/_dontignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/ardrone_control/.context b/apps/ardrone_control/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/ardrone_control/Makefile b/apps/ardrone_control/Makefile new file mode 100644 index 0000000000..23e2d49fb4 --- /dev/null +++ b/apps/ardrone_control/Makefile @@ -0,0 +1,45 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Makefile to build uORB +# + +APPNAME = ardrone_control +PRIORITY = SCHED_PRIORITY_MAX - 15 +STACKSIZE = 2048 + +# explicit list of sources - not everything is built currently +CSRCS = ardrone_control.c ardrone_motor_control.c ardrone_control_helper.c rate_control.c attitude_control.c pid.c + +include $(APPDIR)/mk/app.mk diff --git a/apps/ardrone_control/ardrone_control.c b/apps/ardrone_control/ardrone_control.c new file mode 100644 index 0000000000..e49a0ae29d --- /dev/null +++ b/apps/ardrone_control/ardrone_control.c @@ -0,0 +1,272 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * @file Implementation of AR.Drone 1.0 / 2.0 control interface + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ardrone_control.h" +#include "attitude_control.h" +#include "rate_control.h" +#include "ardrone_motor_control.h" +#include "position_control.h" +#include +#include +#include +#include +#include +#include +#include + +#include "ardrone_control_helper.h" + +__EXPORT int ardrone_control_main(int argc, char *argv[]); + +/**************************************************************************** + * Internal Definitions + ****************************************************************************/ + + +enum { + CONTROL_MODE_RATES = 0, + CONTROL_MODE_ATTITUDE = 1, +} control_mode; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/*File descriptors */ +int ardrone_write; +int gpios; + +bool position_control_thread_started; + +/**************************************************************************** + * pthread loops + ****************************************************************************/ +static void *position_control_loop(void *arg) +{ + struct vehicle_status_s *state = (struct vehicle_status_s *)arg; + // Set thread name + prctl(PR_SET_NAME, "ardrone pos ctrl", getpid()); + + while (1) { + if (state->state_machine == SYSTEM_STATE_AUTO) { +// control_position(); //FIXME TODO XXX + /* temporary 50 Hz execution */ + usleep(20000); + + } else { + position_control_thread_started = false; + break; + } + } + + return NULL; +} + +/**************************************************************************** + * main + ****************************************************************************/ + +int ardrone_control_main(int argc, char *argv[]) +{ + /* welcome user */ + printf("[ardrone_control] Control started, taking over motors\n"); + + /* default values for arguments */ + char *ardrone_uart_name = "/dev/ttyS1"; + control_mode = CONTROL_MODE_RATES; + + char *commandline_usage = "\tusage: ardrone_control -d ardrone-devicename -m mode\n\tmodes are:\n\t\trates\n\t\tattitude\n"; + + /* read commandline arguments */ + int i; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--device") == 0) { //ardrone set + if (argc > i + 1) { + ardrone_uart_name = argv[i + 1]; + + } else { + printf(commandline_usage); + return 0; + } + + } else if (strcmp(argv[i], "-m") == 0 || strcmp(argv[i], "--mode") == 0) { + if (argc > i + 1) { + if (strcmp(argv[i + 1], "rates") == 0) { + control_mode = CONTROL_MODE_RATES; + + } else if (strcmp(argv[i + 1], "attitude") == 0) { + control_mode = CONTROL_MODE_ATTITUDE; + + } else { + printf(commandline_usage); + return 0; + } + + } else { + printf(commandline_usage); + return 0; + } + } + } + + /* open uarts */ + printf("[ardrone_control] AR.Drone UART is %s\n", ardrone_uart_name); + ardrone_write = open(ardrone_uart_name, O_RDWR | O_NOCTTY | O_NDELAY); + + /* initialize motors */ + ar_init_motors(ardrone_write, &gpios); + int counter = 0; + + /* pthread for position control */ + pthread_t position_control_thread; + position_control_thread_started = false; + + /* structures */ + struct vehicle_status_s state; + struct vehicle_attitude_s att; + struct ardrone_control_s ar_control; + struct rc_channels_s rc; + struct sensor_combined_s raw; + struct ardrone_motors_setpoint_s setpoint; + + /* subscribe to attitude, motor setpoints and system state */ + int att_sub = orb_subscribe(ORB_ID(vehicle_attitude)); + int state_sub = orb_subscribe(ORB_ID(vehicle_status)); + int rc_sub = orb_subscribe(ORB_ID(rc_channels)); + int sensor_sub = orb_subscribe(ORB_ID(sensor_combined)); + int setpoint_sub = orb_subscribe(ORB_ID(ardrone_motors_setpoint)); + + /* publish AR.Drone motor control state */ + int ardrone_pub = orb_advertise(ORB_ID(ardrone_control), &ar_control); + + while (1) { + /* get a local copy of the vehicle state */ + orb_copy(ORB_ID(vehicle_status), state_sub, &state); + /* get a local copy of rc */ + orb_copy(ORB_ID(rc_channels), rc_sub, &rc); + /* get a local copy of attitude */ + orb_copy(ORB_ID(vehicle_attitude), att_sub, &att); + + if (state.state_machine == SYSTEM_STATE_AUTO) { + if (false == position_control_thread_started) { + pthread_attr_t position_control_thread_attr; + pthread_attr_init(&position_control_thread_attr); + pthread_attr_setstacksize(&position_control_thread_attr, 2048); + pthread_create(&position_control_thread, &position_control_thread_attr, position_control_loop, &state); + position_control_thread_started = true; + } + + control_attitude(&rc, &att, &state, ardrone_pub, &ar_control); + + //No check for remote sticks to disarm in auto mode, land/disarm with ground station + + } else if (state.state_machine == SYSTEM_STATE_MANUAL) { + if (control_mode == CONTROL_MODE_RATES) { + orb_copy(ORB_ID(sensor_combined), sensor_sub, &raw); + orb_copy(ORB_ID(ardrone_motors_setpoint), setpoint_sub, &setpoint); + control_rates(&raw, &setpoint); + + } else if (control_mode == CONTROL_MODE_ATTITUDE) { + control_attitude(&rc, &att, &state, ardrone_pub, &ar_control); + } + + } else { + + } + + //fancy led animation... + static int blubb = 0; + + if (counter % 20 == 0) { + if (blubb == 0) ar_set_leds(ardrone_write, 0, 1, 0, 0, 0, 0, 0 , 0); + + if (blubb == 1) ar_set_leds(ardrone_write, 1, 1, 0, 0, 0, 0, 0 , 0); + + if (blubb == 2) ar_set_leds(ardrone_write, 1, 0, 0, 0, 0, 0, 0 , 0); + + if (blubb == 3) ar_set_leds(ardrone_write, 0, 0, 0, 1, 0, 0, 0 , 0); + + if (blubb == 4) ar_set_leds(ardrone_write, 0, 0, 1, 1, 0, 0, 0 , 0); + + if (blubb == 5) ar_set_leds(ardrone_write, 0, 0, 1, 0, 0, 0, 0 , 0); + + if (blubb == 6) ar_set_leds(ardrone_write, 0, 0, 0, 0, 0, 1, 0 , 0); + + if (blubb == 7) ar_set_leds(ardrone_write, 0, 0, 0, 0, 1, 1, 0 , 0); + + if (blubb == 8) ar_set_leds(ardrone_write, 0, 0, 0, 0, 1, 0, 0 , 0); + + if (blubb == 9) ar_set_leds(ardrone_write, 0, 0, 0, 0, 0, 0, 0 , 1); + + if (blubb == 10) ar_set_leds(ardrone_write, 0, 0, 0, 0, 0, 0, 1 , 1); + + if (blubb == 11) ar_set_leds(ardrone_write, 0, 0, 0, 0, 0, 0, 1 , 0); + + blubb++; + + if (blubb == 12) blubb = 0; + } + + /* run at approximately 200 Hz */ + usleep(5000); + counter++; + } + + /* close uarts */ + close(ardrone_write); + ar_multiplexing_deinit(gpios); + + printf("[ardrone_control] ending now...\r\n"); + fflush(stdout); + return 0; +} + diff --git a/apps/ardrone_control/ardrone_control.h b/apps/ardrone_control/ardrone_control.h new file mode 100644 index 0000000000..7f9567f861 --- /dev/null +++ b/apps/ardrone_control/ardrone_control.h @@ -0,0 +1,12 @@ +/* + * ardrone_control.h + * + * Created on: Mar 23, 2012 + * Author: thomasgubler + */ + +#ifndef ARDRONE_CONTROL_H_ +#define ARDRONE_CONTROL_H_ + + +#endif /* ARDRONE_CONTROL_H_ */ diff --git a/apps/ardrone_control/ardrone_control_helper.c b/apps/ardrone_control/ardrone_control_helper.c new file mode 100644 index 0000000000..c073119e09 --- /dev/null +++ b/apps/ardrone_control/ardrone_control_helper.c @@ -0,0 +1,60 @@ +#include "ardrone_control_helper.h" +#include +#include +#include +#include + +// int read_sensors_raw(sensors_raw_t *sensors_raw) +// { +// static int ret; +// ret = global_data_wait(&global_data_sensors_raw->access_conf_rate_full); + +// if (ret == 0) { +// memcpy(sensors_raw->gyro_raw, global_data_sensors_raw->gyro_raw, sizeof(sensors_raw->gyro_raw)); +// // printf("Timestamp %d\n", &global_data_sensors_raw->timestamp); + +// } else { +// printf("Controller timeout, no new sensor values available\n"); +// } + +// global_data_unlock(&global_data_sensors_raw->access_conf_rate_full); +// return ret; +// } + +// int read_attitude(global_data_attitude_t *attitude) +// { + +// static int ret; +// ret = global_data_wait(&global_data_attitude->access_conf); + +// if (ret == 0) { +// memcpy(&attitude->roll, &global_data_attitude->roll, sizeof(global_data_attitude->roll)); +// memcpy(&attitude->pitch, &global_data_attitude->pitch, sizeof(global_data_attitude->pitch)); +// memcpy(&attitude->yaw, &global_data_attitude->yaw, sizeof(global_data_attitude->yaw)); +// memcpy(&attitude->rollspeed, &global_data_attitude->rollspeed, sizeof(global_data_attitude->rollspeed)); +// memcpy(&attitude->pitchspeed, &global_data_attitude->pitchspeed, sizeof(global_data_attitude->pitchspeed)); +// memcpy(&attitude->yawspeed, &global_data_attitude->yawspeed, sizeof(global_data_attitude->yawspeed)); + +// } else { +// printf("Controller timeout, no new attitude values available\n"); +// } + +// global_data_unlock(&global_data_attitude->access_conf); + + + +// return ret; +// } + +// void read_quad_motors_setpoint(quad_motors_setpoint_t *rate_setpoint) +// { + +// if (0 == global_data_trylock(&global_data_quad_motors_setpoint->access_conf)) { //TODO: check if trylock is the right choice, maybe only lock? +// rate_setpoint->motor_front_nw = global_data_quad_motors_setpoint->motor_front_nw; +// rate_setpoint->motor_right_ne = global_data_quad_motors_setpoint->motor_right_ne; +// rate_setpoint->motor_back_se = global_data_quad_motors_setpoint->motor_back_se; +// rate_setpoint->motor_left_sw = global_data_quad_motors_setpoint->motor_left_sw; + +// global_data_unlock(&global_data_quad_motors_setpoint->access_conf); +// } +// } diff --git a/apps/ardrone_control/ardrone_control_helper.h b/apps/ardrone_control/ardrone_control_helper.h new file mode 100644 index 0000000000..22eebe986d --- /dev/null +++ b/apps/ardrone_control/ardrone_control_helper.h @@ -0,0 +1,21 @@ +/* + * ardrone_control_helper.h + * + * Created on: May 15, 2012 + * Author: thomasgubler + */ + +#ifndef ARDRONE_CONTROL_HELPER_H_ +#define ARDRONE_CONTROL_HELPER_H_ + +#include + +// typedef struct { +// int16_t gyro_raw[3]; // l3gd20 +// } sensors_raw_t; + +// /* Copy quad_motors_setpoint values from global memory to private variables */ //TODO: change this once the new mavlink message for rates is available +// void read_quad_motors_setpoint(quad_motors_setpoint_t *rate_setpoint); + + +#endif /* ARDRONE_CONTROL_HELPER_H_ */ diff --git a/apps/ardrone_control/ardrone_motor_control.c b/apps/ardrone_control/ardrone_motor_control.c new file mode 100644 index 0000000000..25847e1da3 --- /dev/null +++ b/apps/ardrone_control/ardrone_motor_control.c @@ -0,0 +1,277 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * @file Implementation of AR.Drone 1.0 / 2.0 motor control interface + */ + + + +#include "ardrone_motor_control.h" + +static const unsigned long motor_gpios = GPIO_EXT_1 | GPIO_EXT_2 | GPIO_MULTI_1 | GPIO_MULTI_2; +static const unsigned long motor_gpio[4] = { GPIO_EXT_1, GPIO_EXT_2, GPIO_MULTI_1, GPIO_MULTI_2 }; + +typedef union { + uint16_t motor_value; + uint8_t bytes[2]; +} motor_union_t; + +/** + * @brief Generate the 8-byte motor set packet + * + * @return the number of bytes (8) + */ +void ar_get_motor_packet(uint8_t *motor_buf, uint16_t motor1, uint16_t motor2, uint16_t motor3, uint16_t motor4) +{ + motor_buf[0] = 0x20; + motor_buf[1] = 0x00; + motor_buf[2] = 0x00; + motor_buf[3] = 0x00; + motor_buf[4] = 0x00; + /* + * {0x20, 0x00, 0x00, 0x00, 0x00}; + * 0x20 is start sign / motor command + */ + motor_union_t curr_motor; + uint16_t nineBitMask = 0x1FF; + + /* Set motor 1 */ + curr_motor.motor_value = (motor1 & nineBitMask) << 4; + motor_buf[0] |= curr_motor.bytes[1]; + motor_buf[1] |= curr_motor.bytes[0]; + + /* Set motor 2 */ + curr_motor.motor_value = (motor2 & nineBitMask) << 3; + motor_buf[1] |= curr_motor.bytes[1]; + motor_buf[2] |= curr_motor.bytes[0]; + + /* Set motor 3 */ + curr_motor.motor_value = (motor3 & nineBitMask) << 2; + motor_buf[2] |= curr_motor.bytes[1]; + motor_buf[3] |= curr_motor.bytes[0]; + + /* Set motor 4 */ + curr_motor.motor_value = (motor4 & nineBitMask) << 1; + motor_buf[3] |= curr_motor.bytes[1]; + motor_buf[4] |= curr_motor.bytes[0]; +} + +void ar_enable_broadcast(int fd) +{ + ar_select_motor(fd, 0); +} + +int ar_multiplexing_init() +{ + int fd; + + fd = open("/dev/gpio", O_RDONLY | O_NONBLOCK); + + if (fd < 0) { + printf("GPIO: open fail\n"); + return fd; + } + + if (ioctl(fd, GPIO_SET_OUTPUT, motor_gpios) != 0) { + printf("GPIO: output set fail\n"); + close(fd); + return -1; + } + + /* deactivate all outputs */ + int ret = 0; + ret += ioctl(fd, GPIO_SET, motor_gpios); + + if (ret < 0) { + printf("GPIO: clearing pins fail\n"); + close(fd); + return -1; + } + + return fd; +} + +int ar_multiplexing_deinit(int fd) +{ + if (fd < 0) { + printf("GPIO: no valid descriptor\n"); + return fd; + } + + int ret = 0; + + /* deselect motor 1-4 */ + ret += ioctl(fd, GPIO_SET, motor_gpios); + + if (ret != 0) { + printf("GPIO: clear failed %d times\n", ret); + } + + if (ioctl(fd, GPIO_SET_INPUT, motor_gpios) != 0) { + printf("GPIO: input set fail\n"); + return -1; + } + + close(fd); + + return ret; +} + +int ar_select_motor(int fd, uint8_t motor) +{ + int ret = 0; + unsigned long gpioset; + /* + * Four GPIOS: + * GPIO_EXT1 + * GPIO_EXT2 + * GPIO_UART2_CTS + * GPIO_UART2_RTS + */ + + /* select motor 0 to enable broadcast */ + if (motor == 0) { + /* select motor 1-4 */ + ret += ioctl(fd, GPIO_CLEAR, motor_gpios); + + } else { + /* select reqested motor */ + ret += ioctl(fd, GPIO_CLEAR, motor_gpio[motor - 1]); + + /* deselect all others */ + gpioset = motor_gpios ^ motor_gpio[motor - 1]; + ret += ioctl(fd, GPIO_SET, gpioset); + } + + return ret; +} + +void ar_init_motors(int ardrone_uart, int *gpios_pin) +{ + /* Initialize multiplexing */ + *gpios_pin = ar_multiplexing_init(); + + /* Write ARDrone commands on UART2 */ + uint8_t initbuf[] = {0xE0, 0x91, 0xA1, 0x00, 0x40}; + uint8_t multicastbuf[] = {0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0}; + + /* initialize all motors + * - select one motor at a time + * - configure motor + */ + int i; + int errcounter = 0; + + for (i = 1; i < 5; ++i) { + /* Initialize motors 1-4 */ + initbuf[3] = i; + errcounter += ar_select_motor(*gpios_pin, i); + + write(ardrone_uart, initbuf + 0, 1); + + /* sleep 400 ms */ + usleep(200000); + usleep(200000); + + write(ardrone_uart, initbuf + 1, 1); + /* wait 50 ms */ + usleep(50000); + + write(ardrone_uart, initbuf + 2, 1); + /* wait 50 ms */ + usleep(50000); + + write(ardrone_uart, initbuf + 3, 1); + /* wait 50 ms */ + usleep(50000); + + write(ardrone_uart, initbuf + 4, 1); + /* wait 50 ms */ + usleep(50000); + + /* enable multicast */ + write(ardrone_uart, multicastbuf + 0, 1); + /* wait 1 ms */ + usleep(1000); + + write(ardrone_uart, multicastbuf + 1, 1); + /* wait 1 ms */ + usleep(1000); + + write(ardrone_uart, multicastbuf + 2, 1); + /* wait 1 ms */ + usleep(1000); + + write(ardrone_uart, multicastbuf + 3, 1); + /* wait 1 ms */ + usleep(1000); + + write(ardrone_uart, multicastbuf + 4, 1); + /* wait 1 ms */ + usleep(1000); + + write(ardrone_uart, multicastbuf + 5, 1); + /* wait 5 ms */ + usleep(50000); + } + + /* start the multicast part */ + errcounter += ar_select_motor(*gpios_pin, 0); + + if (errcounter != 0) { + printf("AR: init sequence incomplete, failed %d times", -errcounter); + fflush(stdout); + } +} + +/* + * Sets the leds on the motor controllers, 1 turns led on, 0 off. + */ +void ar_set_leds(int ardrone_uart, uint8_t led1_red, uint8_t led1_green, uint8_t led2_red, uint8_t led2_green, uint8_t led3_red, uint8_t led3_green, uint8_t led4_red, uint8_t led4_green) +{ + /* + * 2 bytes are sent. The first 3 bits describe the command: 011 means led control + * the following 4 bits are the red leds for motor 4, 3, 2, 1 + * then 4 bits with unknown function, then 4 bits for green leds for motor 4, 3, 2, 1 + * the last bit is unknown. + * + * The packet is therefore: + * 011 rrrr 0000 gggg 0 + */ + uint8_t leds[2]; + leds[0] = 0x60 | ((led4_red & 0x01) << 4) | ((led3_red & 0x01) << 3) | ((led2_red & 0x01) << 2) | ((led1_red & 0x01) << 1); + leds[1] = ((led4_green & 0x01) << 4) | ((led3_green & 0x01) << 3) | ((led2_green & 0x01) << 2) | ((led1_green & 0x01) << 1); + write(ardrone_uart, leds, 2); +} diff --git a/apps/ardrone_control/ardrone_motor_control.h b/apps/ardrone_control/ardrone_motor_control.h new file mode 100644 index 0000000000..bf41e3f3b4 --- /dev/null +++ b/apps/ardrone_control/ardrone_motor_control.h @@ -0,0 +1,61 @@ +/**************************************************************************** + * px4/ardrone_offboard_control.h + * + * Copyright (C) 2012 PX4 Autopilot Project. All rights reserved. + * Author: Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief Generate the 8-byte motor set packet + * + * @return the number of bytes (8) + */ +void ar_get_motor_packet(uint8_t *motor_buf, uint16_t motor1, uint16_t motor2, uint16_t motor3, uint16_t motor4); + +int ar_select_motor(int fd, uint8_t motor); + +void ar_enable_broadcast(int fd); + +int ar_multiplexing_init(void); +int ar_multiplexing_deinit(int fd); + +void ar_init_motors(int ardrone_uart, int *gpios_uart); + +void ar_set_leds(int ardrone_uart, uint8_t led1_red, uint8_t led1_green, uint8_t led2_red, uint8_t led2_green, uint8_t led3_red, uint8_t led3_green, uint8_t led4_red, uint8_t led4_green); + diff --git a/apps/ardrone_control/attitude_control.c b/apps/ardrone_control/attitude_control.c new file mode 100644 index 0000000000..2d2596d6db --- /dev/null +++ b/apps/ardrone_control/attitude_control.c @@ -0,0 +1,435 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: Thomas Gubler + * Julian Oes + * Laurens Mackay + * Tobias Naegeli + * Martin Rutschmann + * Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * @file Implementation of attitude controller + */ + +#include "attitude_control.h" +#include +#include +#include +#include +#include +#include //TODO: move matrix.h to somewhere else? +#include "ardrone_motor_control.h" +#include +#include +#include "pid.h" +#include + +extern int ardrone_write; +extern int gpios; + +#define CONTROL_PID_ATTITUDE_INTERVAL 5e-3 + +void turn_xy_plane(const float_vect3 *vector, float yaw, + float_vect3 *result) +{ + //turn clockwise + static uint16_t counter; + + result->x = (cos(yaw) * vector->x + sin(yaw) * vector->y); + result->y = (-sin(yaw) * vector->x + cos(yaw) * vector->y); + result->z = vector->z; //leave direction normal to xy-plane untouched + + counter++; +} + +void navi2body_xy_plane(const float_vect3 *vector, const float yaw, + float_vect3 *result) +{ + turn_xy_plane(vector, yaw, result); +// result->x = vector->x; +// result->y = vector->y; +// result->z = vector->z; + // result->x = cos(yaw) * vector->x + sin(yaw) * vector->y; + // result->y = -sin(yaw) * vector->x + cos(yaw) * vector->y; + // result->z = vector->z; //leave direction normal to xy-plane untouched +} + +void control_attitude(const struct rc_channels_s *rc, const struct vehicle_attitude_s *att, const struct vehicle_status_s *status, int ardrone_pub, struct ardrone_control_s *ar_control) +{ + static int motor_skip_counter = 0; + + static PID_t yaw_pos_controller; + static PID_t yaw_speed_controller; + static PID_t nick_controller; + static PID_t roll_controller; + + static const float min_gas = 1; + static const float max_gas = 512; + static uint16_t motor_pwm[4] = {0, 0, 0, 0}; + static float motor_calc[4] = {0.0f, 0.0f, 0.0f, 0.0f}; +// static float remote_control_weight_z = 1; +// static float position_control_weight_z = 0; + + static float pid_yawpos_lim; + static float pid_yawspeed_lim; + static float pid_att_lim; + + static bool initialized; + + static float_vect3 attitude_setpoint_navigationframe_from_positioncontroller; + + static hrt_abstime now_time; + static hrt_abstime last_time; + + static commander_state_machine_t current_state; + + /* initialize the pid controllers when the function is called for the first time */ + if (initialized == false) { + + pid_init(&yaw_pos_controller, + global_data_parameter_storage->pm.param_values[PARAM_PID_YAWPOS_P], + global_data_parameter_storage->pm.param_values[PARAM_PID_YAWPOS_I], + global_data_parameter_storage->pm.param_values[PARAM_PID_YAWPOS_D], + global_data_parameter_storage->pm.param_values[PARAM_PID_YAWPOS_AWU], + PID_MODE_DERIVATIV_CALC, 154); + + pid_init(&yaw_speed_controller, + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWSPEED_P], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWSPEED_I], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWSPEED_D], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWSPEED_AWU], + PID_MODE_DERIVATIV_CALC, 155); + + pid_init(&nick_controller, + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_P], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_I], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_D], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_AWU], + PID_MODE_DERIVATIV_SET, 156); + + pid_init(&roll_controller, + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_P], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_I], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_D], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_AWU], + PID_MODE_DERIVATIV_SET, 157); + + pid_yawpos_lim = global_data_parameter_storage->pm.param_values[PARAM_PID_YAWPOS_LIM]; + pid_yawspeed_lim = (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWSPEED_LIM]; + pid_att_lim = (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_LIM]; + + //TODO: true initialization? get gps while on ground? + attitude_setpoint_navigationframe_from_positioncontroller.x = 0.0f; + attitude_setpoint_navigationframe_from_positioncontroller.y = 0.0f; + attitude_setpoint_navigationframe_from_positioncontroller.z = 0.0f; + + last_time = 0; + initialized = true; + } + + /* load new parameters with lower rate */ + if (motor_skip_counter % 50 == 0) { + pid_set_parameters(&yaw_pos_controller, + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWPOS_P], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWPOS_I], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWPOS_D], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWPOS_AWU]); + + pid_set_parameters(&yaw_speed_controller, + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWSPEED_P], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWSPEED_I], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWSPEED_D], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWSPEED_AWU]); + + pid_set_parameters(&nick_controller, + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_P], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_I], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_D], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_AWU]); + + pid_set_parameters(&roll_controller, + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_P], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_I], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_D], + (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_AWU]); + + pid_yawpos_lim = global_data_parameter_storage->pm.param_values[PARAM_PID_YAWPOS_LIM]; + pid_yawspeed_lim = (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_YAWSPEED_LIM]; + pid_att_lim = (max_gas - min_gas) * global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_LIM]; + } + + current_state = status->state_machine; + float_vect3 attitude_setpoint_bodyframe = {}; //this is the setpoint in the bodyframe "mixed" together from the setpoint from the remote and the setpoint from the position controller + + if (current_state == SYSTEM_STATE_AUTO) { + + attitude_setpoint_navigationframe_from_positioncontroller.x = ar_control->attitude_setpoint_navigationframe_from_positioncontroller[0]; + attitude_setpoint_navigationframe_from_positioncontroller.y = ar_control->attitude_setpoint_navigationframe_from_positioncontroller[1]; + attitude_setpoint_navigationframe_from_positioncontroller.z = ar_control->attitude_setpoint_navigationframe_from_positioncontroller[2]; + + float yaw_e = att->yaw - attitude_setpoint_navigationframe_from_positioncontroller.z; + + // don't turn around the wrong side (only works if yaw angle is between +- 180 degree) + if (yaw_e > M_PI) { + yaw_e -= 2.0f * M_PI; + } + + if (yaw_e < -M_PI) { + yaw_e += 2.0f * M_PI; + } + + attitude_setpoint_navigationframe_from_positioncontroller.z = pid_calculate(&yaw_pos_controller, 0, yaw_e, 0, CONTROL_PID_ATTITUDE_INTERVAL); + + + /* limit control output */ + if (attitude_setpoint_navigationframe_from_positioncontroller.z > pid_yawpos_lim) { + attitude_setpoint_navigationframe_from_positioncontroller.z = pid_yawpos_lim; + yaw_pos_controller.saturated = 1; + } + + if (attitude_setpoint_navigationframe_from_positioncontroller.z < -pid_yawpos_lim) { + attitude_setpoint_navigationframe_from_positioncontroller.z = -pid_yawpos_lim; + yaw_pos_controller.saturated = 1; + } + + //transform attitude setpoint from position controller from navi to body frame on xy_plane + float_vect3 attitude_setpoint_bodyframe_from_positioncontroller; + navi2body_xy_plane(&attitude_setpoint_navigationframe_from_positioncontroller, att->yaw , &attitude_setpoint_bodyframe_from_positioncontroller); //yaw angle= att->yaw + //now everything is in body frame + + + //TODO: here we decide which input (position controller or ppm) we use. For now we have only the ppm, this should be decided dpending on the state machione (manula or auto) ppm should always overwrite auto (?) + attitude_setpoint_bodyframe.x = attitude_setpoint_bodyframe_from_positioncontroller.x; + attitude_setpoint_bodyframe.y = attitude_setpoint_bodyframe_from_positioncontroller.y; + attitude_setpoint_bodyframe.z = attitude_setpoint_bodyframe_from_positioncontroller.z; + + } else if (current_state == SYSTEM_STATE_MANUAL) { + attitude_setpoint_bodyframe.x = -((float)rc->chan[rc->function[ROLL]].scale / 10000.0f) * 3.14159265 / 8.0f; + attitude_setpoint_bodyframe.y = -((float)rc->chan[rc->function[PITCH]].scale / 10000.0f) * 3.14159265 / 8.0f; + attitude_setpoint_bodyframe.z = -((float)rc->chan[rc->function[YAW]].scale / 10000.0f) * 3.14159265; + } + + /* add an attitude offset which needs to be estimated somewhere */ + attitude_setpoint_bodyframe.x += global_data_parameter_storage->pm.param_values[PARAM_ATT_XOFFSET]; + attitude_setpoint_bodyframe.y += global_data_parameter_storage->pm.param_values[PARAM_ATT_YOFFSET]; + + /*Calculate Controllers*/ + //control Nick + float nick = pid_calculate(&nick_controller, attitude_setpoint_bodyframe.y, att->pitch, att->pitchspeed, CONTROL_PID_ATTITUDE_INTERVAL); + //control Roll + float roll = pid_calculate(&roll_controller, attitude_setpoint_bodyframe.x, att->roll, att->rollspeed, CONTROL_PID_ATTITUDE_INTERVAL); + //control Yaw Speed + float yaw = pid_calculate(&yaw_speed_controller, attitude_setpoint_bodyframe.z, att->yawspeed, 0, CONTROL_PID_ATTITUDE_INTERVAL); //attitude_setpoint_bodyframe.z is yaw speed! + + //compensation to keep force in z-direction + float zcompensation; + + if (fabs(att->roll) > 0.5f) { + zcompensation = 1.13949393f; + + } else { + zcompensation = 1.0f / cosf(att->roll); + } + + if (fabs(att->pitch) > 0.5f) { + zcompensation *= 1.13949393f; + + } else { + zcompensation *= 1.0f / cosf(att->pitch); + } + + // use global_data.position_control_output.z and mix parameter global_data.param[PARAM_MIX_POSITION_Z_WEIGHT] + // to compute thrust for Z position control + // + // float motor_thrust = min_gas + + // ( ( 1 - global_data.param[PARAM_MIX_POSITION_Z_WEIGHT] ) * ( max_gas - min_gas ) * global_data.gas_remote * zcompensation ) + // + ( global_data.param[PARAM_MIX_POSITION_Z_WEIGHT] * ( max_gas - min_gas ) * controlled_thrust * zcompensation ); + //calculate the basic thrust + + + + float motor_thrust = 0; + + // FLYING MODES + if (current_state == SYSTEM_STATE_MANUAL) { + motor_thrust = (float)rc->chan[rc->function[THROTTLE]].scale; + + } else if (current_state == SYSTEM_STATE_GROUND_READY || current_state == SYSTEM_STATE_STABILIZED || current_state == SYSTEM_STATE_AUTO || current_state == SYSTEM_STATE_MISSION_ABORT) { + motor_thrust = (float)rc->chan[rc->function[THROTTLE]].scale; //TODO + + } else if (current_state == SYSTEM_STATE_EMCY_LANDING) { + motor_thrust = (float)rc->chan[rc->function[THROTTLE]].scale; //TODO + + } else if (current_state == SYSTEM_STATE_EMCY_CUTOFF) { + motor_thrust = 0; //immediately cut off thrust! + + } else { + motor_thrust = 0; // Motor thrust must be zero in any other mode! + } + + // Convertion to motor-step units + motor_thrust *= zcompensation; + motor_thrust *= max_gas / 20000.0f; //TODO: check this + motor_thrust += (max_gas - min_gas) / 2.f; + + //limit control output + //yawspeed + if (yaw > pid_yawspeed_lim) { + yaw = pid_yawspeed_lim; + yaw_speed_controller.saturated = 1; + } + + if (yaw < -pid_yawspeed_lim) { + yaw = -pid_yawspeed_lim; + yaw_speed_controller.saturated = 1; + } + + if (nick > pid_att_lim) { + nick = pid_att_lim; + nick_controller.saturated = 1; + } + + if (nick < -pid_att_lim) { + nick = -pid_att_lim; + nick_controller.saturated = 1; + } + + + if (roll > pid_att_lim) { + roll = pid_att_lim; + roll_controller.saturated = 1; + } + + if (roll < -pid_att_lim) { + roll = -pid_att_lim; + roll_controller.saturated = 1; + } + + /* Emit controller values */ + ar_control->setpoint_thrust_cast = motor_thrust; + ar_control->setpoint_attitude[0] = attitude_setpoint_bodyframe.x; + ar_control->setpoint_attitude[1] = attitude_setpoint_bodyframe.y; + ar_control->setpoint_attitude[2] = attitude_setpoint_bodyframe.z; + ar_control->attitude_control_output[0] = roll; + ar_control->attitude_control_output[1] = nick; + ar_control->attitude_control_output[2] = yaw; + ar_control->zcompensation = zcompensation; + orb_publish(ORB_ID(ardrone_control), ardrone_pub, ar_control); + + static float output_band = 0.f; + static float band_factor = 0.75f; + static float startpoint_full_control = 150.0f; //TODO + static float yaw_factor = 1.0f; + + if (motor_thrust <= min_gas) { + motor_thrust = min_gas; + output_band = 0.f; + + } else if (motor_thrust < startpoint_full_control && motor_thrust > min_gas) { + output_band = band_factor * (motor_thrust - min_gas); + + } else if (motor_thrust >= startpoint_full_control && motor_thrust < max_gas - band_factor * startpoint_full_control) { + output_band = band_factor * startpoint_full_control; + + } else if (motor_thrust >= max_gas - band_factor * startpoint_full_control) { + output_band = band_factor * (max_gas - motor_thrust); + } + + //add the yaw, nick and roll components to the basic thrust //TODO:this should be done by the mixer + + // FRONT (MOTOR 1) + motor_calc[0] = motor_thrust + (roll / 2 + nick / 2 - yaw); + + // RIGHT (MOTOR 2) + motor_calc[1] = motor_thrust + (-roll / 2 + nick / 2 + yaw); + + // BACK (MOTOR 3) + motor_calc[2] = motor_thrust + (-roll / 2 - nick / 2 - yaw); + + // LEFT (MOTOR 4) + motor_calc[3] = motor_thrust + (roll / 2 - nick / 2 + yaw); + + // if we are not in the output band + if (!(motor_calc[0] < motor_thrust + output_band && motor_calc[0] > motor_thrust - output_band + && motor_calc[1] < motor_thrust + output_band && motor_calc[1] > motor_thrust - output_band + && motor_calc[2] < motor_thrust + output_band && motor_calc[2] > motor_thrust - output_band + && motor_calc[3] < motor_thrust + output_band && motor_calc[3] > motor_thrust - output_band)) { + + yaw_factor = 0.5f; + // FRONT (MOTOR 1) + motor_calc[0] = motor_thrust + (roll / 2 + nick / 2 - yaw * yaw_factor); + + // RIGHT (MOTOR 2) + motor_calc[1] = motor_thrust + (-roll / 2 + nick / 2 + yaw * yaw_factor); + + // BACK (MOTOR 3) + motor_calc[2] = motor_thrust + (-roll / 2 - nick / 2 - yaw * yaw_factor); + + // LEFT (MOTOR 4) + motor_calc[3] = motor_thrust + (roll / 2 - nick / 2 + yaw * yaw_factor); + } + + uint8_t i; + + for (i = 0; i < 4; i++) { + //check for limits + if (motor_calc[i] < motor_thrust - output_band) { + motor_calc[i] = motor_thrust - output_band; + } + + if (motor_calc[i] > motor_thrust + output_band) { + motor_calc[i] = motor_thrust + output_band; + } + } + + // Write out actual thrust + motor_pwm[0] = (uint16_t) motor_calc[0]; + motor_pwm[1] = (uint16_t) motor_calc[1]; + motor_pwm[2] = (uint16_t) motor_calc[2]; + motor_pwm[3] = (uint16_t) motor_calc[3]; + + //SEND MOTOR COMMANDS + uint8_t motorSpeedBuf[5] = {1, 2, 3, 4, 5}; + ar_get_motor_packet(motorSpeedBuf, motor_pwm[0], motor_pwm[1], motor_pwm[2], motor_pwm[3]); + write(ardrone_write, motorSpeedBuf, 5); + + motor_skip_counter++; + +// now_time = hrt_absolute_time() / 1000000; +// if(now_time - last_time > 0) +// { +// printf("Counter: %ld\n",control_counter); +// last_time = now_time; +// control_counter = 0; +// } +} diff --git a/apps/ardrone_control/attitude_control.h b/apps/ardrone_control/attitude_control.h new file mode 100644 index 0000000000..6f66926c0b --- /dev/null +++ b/apps/ardrone_control/attitude_control.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: Thomas Gubler + * Julian Oes + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* @file attitude control for quadrotors */ + +#ifndef ATTITUDE_CONTROL_H_ +#define ATTITUDE_CONTROL_H_ + +#include +#include +#include +#include +#include + +void control_attitude(const struct rc_channels_s *rc, const struct vehicle_attitude_s *att, + const struct vehicle_status_s *status, int ardrone_pub, + struct ardrone_control_s *ar_control); + +#endif /* ATTITUDE_CONTROL_H_ */ diff --git a/apps/ardrone_control/pid.c b/apps/ardrone_control/pid.c new file mode 100644 index 0000000000..5ce05670e3 --- /dev/null +++ b/apps/ardrone_control/pid.c @@ -0,0 +1,109 @@ +#include "pid.h" + +#include //TODO: move matrix.h to somewhere else? + +void pid_init(PID_t *pid, float kp, float ki, float kd, float intmax, + uint8_t mode, uint8_t plot_i) +{ + pid->kp = kp; + pid->ki = ki; + pid->kd = kd; + pid->intmax = intmax; + pid->mode = mode; + pid->plot_i = plot_i; + pid->count = 0; + pid->saturated = 0; + + pid->sp = 0; + pid->error_previous = 0; + pid->integral = 0; +} +void pid_set_parameters(PID_t *pid, float kp, float ki, float kd, float intmax) +{ + pid->kp = kp; + pid->ki = ki; + pid->kd = kd; + pid->intmax = intmax; + // pid->mode = mode; + + // pid->sp = 0; + // pid->error_previous = 0; + // pid->integral = 0; +} + +//void pid_set(PID_t *pid, float sp) +//{ +// pid->sp = sp; +// pid->error_previous = 0; +// pid->integral = 0; +//} + +/** + * + * @param pid + * @param val + * @param dt + * @return + */ +float pid_calculate(PID_t *pid, float sp, float val, float val_dot, float dt) +{ + /* error = setpoint - actual_position + integral = integral + (error*dt) + derivative = (error - previous_error)/dt + output = (Kp*error) + (Ki*integral) + (Kd*derivative) + previous_error = error + wait(dt) + goto start + */ + + float i, d; + pid->sp = sp; + float error = pid->sp - val; + + if (pid->saturated && (pid->integral * error > 0)) { + //Output is saturated and the integral would get bigger (positive or negative) + i = pid->integral; + + //Reset saturation. If we are still saturated this will be set again at output limit check. + pid->saturated = 0; + + } else { + i = pid->integral + (error * dt); + } + + // Anti-Windup. Needed if we don't use the saturation above. + if (pid->intmax != 0.0) { + if (i > pid->intmax) { + pid->integral = pid->intmax; + + } else if (i < -pid->intmax) { + + pid->integral = -pid->intmax; + + } else { + pid->integral = i; + } + + //Send Controller integrals + // Disabled because of new possibilities with debug_vect. + // Now sent in Main Loop at 5 Hz. 26.06.2010 Laurens + // if (pid->plot_i && (pid->count++ % 16 == 0)&&(global_data.param[PARAM_SEND_SLOT_DEBUG_2] == 1)) + // { + // mavlink_msg_debug_send(MAVLINK_COMM_1, pid->plot_i, pid->integral); + // } + } + + if (pid->mode == PID_MODE_DERIVATIV_CALC) { + d = (error - pid->error_previous) / dt; + + } else if (pid->mode == PID_MODE_DERIVATIV_SET) { + d = -val_dot; + + } else { + d = 0; + } + + pid->error_previous = error; + + return (error * pid->kp) + (i * pid->ki) + (d * pid->kd); +} diff --git a/apps/ardrone_control/pid.h b/apps/ardrone_control/pid.h new file mode 100644 index 0000000000..a721c839c6 --- /dev/null +++ b/apps/ardrone_control/pid.h @@ -0,0 +1,40 @@ +/* + * pid.h + * + * Created on: May 29, 2012 + * Author: thomasgubler + */ + +#ifndef PID_H_ +#define PID_H_ + +#include + +/* PID_MODE_DERIVATIV_CALC calculates discrete derivative from previous error + * val_dot in pid_calculate() will be ignored */ +#define PID_MODE_DERIVATIV_CALC 0 +/* Use PID_MODE_DERIVATIV_SET if you have the derivative already (Gyros, Kalman) */ +#define PID_MODE_DERIVATIV_SET 1 + +typedef struct { + float kp; + float ki; + float kd; + float intmax; + float sp; + float integral; + float error_previous; + uint8_t mode; + uint8_t plot_i; + uint8_t count; + uint8_t saturated; +} PID_t; + +void pid_init(PID_t *pid, float kp, float ki, float kd, float intmax, uint8_t mode, uint8_t plot_i); +void pid_set_parameters(PID_t *pid, float kp, float ki, float kd, float intmax); +//void pid_set(PID_t *pid, float sp); +float pid_calculate(PID_t *pid, float sp, float val, float val_dot, float dt); + + + +#endif /* PID_H_ */ diff --git a/apps/ardrone_control/position_control.c b/apps/ardrone_control/position_control.c new file mode 100644 index 0000000000..6ba1654595 --- /dev/null +++ b/apps/ardrone_control/position_control.c @@ -0,0 +1,308 @@ +/**************************************************************************** + * ardrone_control/position_control.c + * + * Copyright (C) 2008, 2012 Thomas Gubler, Julian Oes, Lorenz Meier. All rights reserved. + * Author: Based on the pixhawk quadrotor controller + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include "position_control.h" +#include +#include +#include +#include +#include +#include +#include +#include "pid.h" + +#ifndef FM_PI +#define FM_PI 3.1415926535897932384626433832795f +#endif + + + +#define CONTROL_PID_POSITION_INTERVAL 0.020 + +int read_lock_position(global_data_position_t *position) +{ + static int ret; + ret = global_data_wait(&global_data_position->access_conf); + + if (ret == 0) { + memcpy(&position->lat, &global_data_position->lat, sizeof(global_data_position->lat)); + memcpy(&position->lon, &global_data_position->lon, sizeof(global_data_position->lon)); + memcpy(&position->alt, &global_data_position->alt, sizeof(global_data_position->alt)); + memcpy(&position->relative_alt, &global_data_position->relative_alt, sizeof(global_data_position->relative_alt)); + memcpy(&position->vx, &global_data_position->vx, sizeof(global_data_position->vx)); + memcpy(&position->vy, &global_data_position->vy, sizeof(global_data_position->vy)); + memcpy(&position->vz, &global_data_position->vz, sizeof(global_data_position->vz)); + memcpy(&position->hdg, &global_data_position->hdg, sizeof(global_data_position->hdg)); + + + } else { + printf("Controller timeout, no new position values available\n"); + } + + global_data_unlock(&global_data_position->access_conf); + return ret; +} + +float get_distance_to_next_waypoint(float lat_now, float lon_now, float lat_next, float lon_next) +{ + double lat_now_rad = lat_now / 180.0 * M_PI; + double lon_now_rad = lon_now / 180.0 * M_PI; + double lat_next_rad = lat_next / 180.0 * M_PI; + double lon_next_rad = lon_next / 180.0 * M_PI; + + + double d_lat = lat_next_rad - lat_now_rad; + double d_lon = lon_next_rad - lon_now_rad; + + double a = sin(d_lat / 2.0) * sin(d_lat / 2.0) + sin(d_lon / 2.0) * sin(d_lon / 2.0) * cos(lat_now_rad) * cos(lat_next_rad); + double c = 2 * atan2(sqrt(a), sqrt(1 - a)); + + const double radius_earth = 6371000.0; + + return radius_earth * c; +} + +float get_bearing_to_next_waypoint(float lat_now, float lon_now, float lat_next, float lon_next) +{ + double lat_now_rad = lat_now / 180.0 * M_PI; + double lon_now_rad = lon_now / 180.0 * M_PI; + double lat_next_rad = lat_next / 180.0 * M_PI; + double lon_next_rad = lon_next / 180.0 * M_PI; + + double d_lat = lat_next_rad - lat_now_rad; + double d_lon = lon_next_rad - lon_now_rad; + + + float theta = atan2f(sin(d_lon) * cos(lat_next_rad) , cos(lat_now_rad) * sin(lat_next_rad) - sin(lat_now_rad) * cos(lat_next_rad) * cos(d_lon)); + + if (theta < 0) { + theta = theta + 2 * FM_PI; + } + + return theta; +} + +void control_position(void) +{ + static PID_t distance_controller; + + static int read_ret; + static global_data_position_t position_estimated; + + static uint16_t counter; + + static bool initialized; + static uint16_t pm_counter; + + static float lat_next; + static float lon_next; + + static float pitch_current; + + static float thrust_total; + + + if (initialized == false) { + + global_data_lock(&global_data_parameter_storage->access_conf); + + pid_init(&distance_controller, + global_data_parameter_storage->pm.param_values[PARAM_PID_POS_P], + global_data_parameter_storage->pm.param_values[PARAM_PID_POS_I], + global_data_parameter_storage->pm.param_values[PARAM_PID_POS_D], + global_data_parameter_storage->pm.param_values[PARAM_PID_POS_AWU], + PID_MODE_DERIVATIV_CALC, 150);//150 + +// pid_pos_lim = global_data_parameter_storage->pm.param_values[PARAM_PID_POS_LIM]; +// pid_pos_z_lim = global_data_parameter_storage->pm.param_values[PARAM_PID_POS_Z_LIM]; + + pm_counter = global_data_parameter_storage->counter; + + global_data_unlock(&global_data_parameter_storage->access_conf); + + thrust_total = 0.0f; + + /* Position initialization */ + /* Wait for new position estimate */ + do { + read_ret = read_lock_position(&position_estimated); + } while (read_ret != 0); + + lat_next = position_estimated.lat; + lon_next = position_estimated.lon; + + /* attitude initialization */ + global_data_lock(&global_data_attitude->access_conf); + pitch_current = global_data_attitude->pitch; + global_data_unlock(&global_data_attitude->access_conf); + + initialized = true; + } + + /* load new parameters with 10Hz */ + if (counter % 50 == 0) { + if (global_data_trylock(&global_data_parameter_storage->access_conf) == 0) { + /* check whether new parameters are available */ + if (global_data_parameter_storage->counter > pm_counter) { + pid_set_parameters(&distance_controller, + global_data_parameter_storage->pm.param_values[PARAM_PID_POS_P], + global_data_parameter_storage->pm.param_values[PARAM_PID_POS_I], + global_data_parameter_storage->pm.param_values[PARAM_PID_POS_D], + global_data_parameter_storage->pm.param_values[PARAM_PID_POS_AWU]); + +// +// pid_pos_lim = global_data_parameter_storage->pm.param_values[PARAM_PID_POS_LIM]; +// pid_pos_z_lim = global_data_parameter_storage->pm.param_values[PARAM_PID_POS_Z_LIM]; + + pm_counter = global_data_parameter_storage->counter; + printf("Position controller changed pid parameters\n"); + } + } + + global_data_unlock(&global_data_parameter_storage->access_conf); + } + + + /* Wait for new position estimate */ + do { + read_ret = read_lock_position(&position_estimated); + } while (read_ret != 0); + + /* Get next waypoint */ //TODO: add local copy + + if (0 == global_data_trylock(&global_data_position_setpoint->access_conf)) { + lat_next = global_data_position_setpoint->x; + lon_next = global_data_position_setpoint->y; + global_data_unlock(&global_data_position_setpoint->access_conf); + } + + /* Get distance to waypoint */ + float distance_to_waypoint = get_distance_to_next_waypoint(position_estimated.lat , position_estimated.lon, lat_next, lon_next); +// if(counter % 5 == 0) +// printf("distance_to_waypoint: %.4f\n", distance_to_waypoint); + + /* Get bearing to waypoint (direction on earth surface to next waypoint) */ + float bearing = get_bearing_to_next_waypoint(position_estimated.lat, position_estimated.lon, lat_next, lon_next); + + if (counter % 5 == 0) + printf("bearing: %.4f\n", bearing); + + /* Calculate speed in direction of bearing (needed for controller) */ + float speed_norm = sqrtf(position_estimated.vx * position_estimated.vx + position_estimated.vy * position_estimated.vy); +// if(counter % 5 == 0) +// printf("speed_norm: %.4f\n", speed_norm); + float speed_to_waypoint = 0; //(position_estimated.vx * cosf(bearing) + position_estimated.vy * sinf(bearing))/speed_norm; //FIXME, TODO: re-enable this once we have a full estimate of the speed, then we can do a PID for the distance controller + + /* Control Thrust in bearing direction */ + float horizontal_thrust = -pid_calculate(&distance_controller, 0, distance_to_waypoint, speed_to_waypoint, + CONTROL_PID_POSITION_INTERVAL); //TODO: maybe this "-" sign is an error somewhere else + +// if(counter % 5 == 0) +// printf("horizontal thrust: %.4f\n", horizontal_thrust); + + /* Get total thrust (from remote for now) */ + if (0 == global_data_trylock(&global_data_rc_channels->access_conf)) { + thrust_total = (float)global_data_rc_channels->chan[THROTTLE].scale; //TODO: how should we use the RC_CHANNELS_FUNCTION enum? + global_data_unlock(&global_data_rc_channels->access_conf); + } + + const float max_gas = 500.0f; + thrust_total *= max_gas / 20000.0f; //TODO: check this + thrust_total += max_gas / 2.0f; + + + if (horizontal_thrust > thrust_total) { + horizontal_thrust = thrust_total; + + } else if (horizontal_thrust < -thrust_total) { + horizontal_thrust = -thrust_total; + } + + + + //TODO: maybe we want to add a speed controller later... + + /* Calclulate thrust in east and north direction */ + float thrust_north = cosf(bearing) * horizontal_thrust; + float thrust_east = sinf(bearing) * horizontal_thrust; + + if (counter % 10 == 0) { + printf("thrust north: %.4f\n", thrust_north); + printf("thrust east: %.4f\n", thrust_east); + fflush(stdout); + } + + /* Get current attitude */ + if (0 == global_data_trylock(&global_data_attitude->access_conf)) { + pitch_current = global_data_attitude->pitch; + global_data_unlock(&global_data_attitude->access_conf); + } + + /* Get desired pitch & roll */ + float pitch_desired = 0.0f; + float roll_desired = 0.0f; + + if (thrust_total != 0) { + float pitch_fraction = -thrust_north / thrust_total; + float roll_fraction = thrust_east / (cosf(pitch_current) * thrust_total); + + if (roll_fraction < -1) { + roll_fraction = -1; + + } else if (roll_fraction > 1) { + roll_fraction = 1; + } + +// if(counter % 5 == 0) +// { +// printf("pitch_fraction: %.4f, roll_fraction: %.4f\n",pitch_fraction, roll_fraction); +// fflush(stdout); +// } + + pitch_desired = asinf(pitch_fraction); + roll_desired = asinf(roll_fraction); + } + + /*Broadcast desired angles */ + global_data_lock(&global_data_ardrone_control->access_conf); + global_data_ardrone_control->attitude_setpoint_navigationframe_from_positioncontroller[0] = roll_desired; + global_data_ardrone_control->attitude_setpoint_navigationframe_from_positioncontroller[1] = pitch_desired; + global_data_ardrone_control->attitude_setpoint_navigationframe_from_positioncontroller[2] = bearing; //TODO: add yaw setpoint + global_data_unlock(&global_data_ardrone_control->access_conf); + global_data_broadcast(&global_data_ardrone_control->access_conf); + + + counter++; +} diff --git a/apps/ardrone_control/position_control.h b/apps/ardrone_control/position_control.h new file mode 100644 index 0000000000..dbc0650e66 --- /dev/null +++ b/apps/ardrone_control/position_control.h @@ -0,0 +1,13 @@ +/* + * position_control.h + * + * Created on: May 29, 2012 + * Author: thomasgubler + */ + +#ifndef POSITION_CONTROL_H_ +#define POSITION_CONTROL_H_ + +void control_position(void); + +#endif /* POSITION_CONTROL_H_ */ diff --git a/apps/ardrone_control/rate_control.c b/apps/ardrone_control/rate_control.c new file mode 100644 index 0000000000..4abba62556 --- /dev/null +++ b/apps/ardrone_control/rate_control.c @@ -0,0 +1,320 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: Tobias Naegeli + * Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * @file Implementation of attitude rate control + */ + +#include "rate_control.h" +#include "ardrone_control_helper.h" +#include "ardrone_motor_control.h" +#include + +extern int ardrone_write; +extern int gpios; + +typedef struct { + uint16_t motor_front_nw; ///< Front motor in + configuration, front left motor in x configuration + uint16_t motor_right_ne; ///< Right motor in + configuration, front right motor in x configuration + uint16_t motor_back_se; ///< Back motor in + configuration, back right motor in x configuration + uint16_t motor_left_sw; ///< Left motor in + configuration, back left motor in x configuration + uint8_t target_system; ///< System ID of the system that should set these motor commands +} quad_motors_setpoint_t; + + +void control_rates(struct sensor_combined_s *raw, struct ardrone_motors_setpoint_s *setpoints) +{ + static quad_motors_setpoint_t actuators_desired; + //static quad_motors_setpoint_t quad_motors_setpoint_desired; + + static int16_t outputBand = 0; + +// static uint16_t control_counter; + static hrt_abstime now_time; + static hrt_abstime last_time; + + static float setpointXrate; + static float setpointYrate; + static float setpointZrate; + + static float setpointRateCast[3]; + static float Kp; +// static float Ki; + static float setpointThrustCast; + static float startpointFullControll; + static float maxThrustSetpoints; + + static float gyro_filtered[3]; + static float gyro_filtered_offset[3]; + static float gyro_alpha; + static float gyro_alpha_offset; +// static float errXrate; + static float attRatesScaled[3]; + + static uint16_t offsetCnt; +// static float antiwindup; + static int motor_skip_counter; + + static int read_ret; + + static bool initialized; + + if (initialized == false) { + initialized = true; + + /* Read sensors for initial values */ + + gyro_filtered_offset[0] = 0.00026631611f * (float)raw->gyro_raw[0]; + gyro_filtered_offset[1] = 0.00026631611f * (float)raw->gyro_raw[1]; + gyro_filtered_offset[2] = 0.00026631611f * (float)raw->gyro_raw[2]; + + gyro_filtered[0] = 0.00026631611f * (float)raw->gyro_raw[0]; + gyro_filtered[1] = 0.00026631611f * (float)raw->gyro_raw[1]; + gyro_filtered[2] = 0.00026631611f * (float)raw->gyro_raw[2]; + + outputBand = 0; + startpointFullControll = 150.0f; + maxThrustSetpoints = 511.0f; + //Kp=60; + //Kp=40.0f; + //Kp=45; + Kp = 30.0f; +// Ki=0.0f; +// antiwindup=50.0f; + } + + /* Get setpoint */ + + + //Rate Controller + setpointRateCast[0] = -((float)setpoints->motor_right_ne - 9999.0f) * 0.01f / 180.0f * 3.141f; + setpointRateCast[1] = -((float)setpoints->motor_front_nw - 9999.0f) * 0.01f / 180.0f * 3.141f; + setpointRateCast[2] = 0; //-((float)setpoints->motor_back_se-9999.0f)*0.01f; + //Ki=actuatorDesired.motorRight_NE*0.001f; + setpointThrustCast = setpoints->motor_left_sw; + + attRatesScaled[0] = 0.000317603994f * (float)raw->gyro_raw[0]; + attRatesScaled[1] = 0.000317603994f * (float)raw->gyro_raw[1]; + attRatesScaled[2] = 0.000317603994f * (float)raw->gyro_raw[2]; + + //filtering of the gyroscope values + + //compute filter coefficient alpha + + //gyro_alpha=0.005/(2.0f*3.1415f*200.0f+0.005f); + //gyro_alpha=0.009; + gyro_alpha = 0.09f; + gyro_alpha_offset = 0.001f; + //gyro_alpha=0.001; + //offset estimation and filtering + offsetCnt++; + uint8_t i; + + for (i = 0; i < 3; i++) { + if (offsetCnt < 5000) { + gyro_filtered_offset[i] = attRatesScaled[i] * gyro_alpha_offset + gyro_filtered_offset[i] * (1 - gyro_alpha_offset); + } + + gyro_filtered[i] = 1.0f * ((attRatesScaled[i] - gyro_filtered_offset[i]) * gyro_alpha + gyro_filtered[i] * (1 - gyro_alpha)) - 0 * setpointRateCast[i]; + } + + // //START DEBUG + // /* write filtered values to global_data_attitude */ + // global_data_attitude->rollspeed = gyro_filtered[0]; + // global_data_attitude->pitchspeed = gyro_filtered[1]; + // global_data_attitude->yawspeed = gyro_filtered[2]; + // //END DEBUG + + //rate controller + + //X-axis + setpointXrate = -Kp * (setpointRateCast[0] - gyro_filtered[0]); + //Y-axis + setpointYrate = -Kp * (setpointRateCast[1] - gyro_filtered[1]); + //Z-axis + setpointZrate = -Kp * (setpointRateCast[2] - gyro_filtered[2]); + + + + + //Mixing + if (setpointThrustCast <= 0) { + setpointThrustCast = 0; + outputBand = 0; + } + + if ((setpointThrustCast < startpointFullControll) && (setpointThrustCast > 0)) { + outputBand = 0.75f * setpointThrustCast; + } + + if ((setpointThrustCast >= startpointFullControll) && (setpointThrustCast < maxThrustSetpoints - 0.75f * startpointFullControll)) { + outputBand = 0.75f * startpointFullControll; + } + + if (setpointThrustCast >= maxThrustSetpoints - 0.75f * startpointFullControll) { + setpointThrustCast = 0.75f * startpointFullControll; + outputBand = 0.75f * startpointFullControll; + } + + actuators_desired.motor_front_nw = setpointThrustCast + (setpointXrate + setpointYrate + setpointZrate); + actuators_desired.motor_right_ne = setpointThrustCast + (-setpointXrate + setpointYrate - setpointZrate); + actuators_desired.motor_back_se = setpointThrustCast + (-setpointXrate - setpointYrate + setpointZrate); + actuators_desired.motor_left_sw = setpointThrustCast + (setpointXrate - setpointYrate - setpointZrate); + + + if ((setpointThrustCast + setpointXrate + setpointYrate + setpointZrate) > (setpointThrustCast + outputBand)) { + actuators_desired.motor_front_nw = setpointThrustCast + outputBand; + } + + if ((setpointThrustCast + setpointXrate + setpointYrate + setpointZrate) < (setpointThrustCast - outputBand)) { + actuators_desired.motor_front_nw = setpointThrustCast - outputBand; + } + + if ((setpointThrustCast + (-setpointXrate) + setpointYrate - setpointZrate) > (setpointThrustCast + outputBand)) { + actuators_desired.motor_right_ne = setpointThrustCast + outputBand; + } + + if ((setpointThrustCast + (-setpointXrate) + setpointYrate - setpointZrate) < (setpointThrustCast - outputBand)) { + actuators_desired.motor_right_ne = setpointThrustCast - outputBand; + } + + if ((setpointThrustCast + (-setpointXrate) + (-setpointYrate) + setpointZrate) > (setpointThrustCast + outputBand)) { + actuators_desired.motor_back_se = setpointThrustCast + outputBand; + } + + if ((setpointThrustCast + (-setpointXrate) + (-setpointYrate) + setpointZrate) < (setpointThrustCast - outputBand)) { + actuators_desired.motor_back_se = setpointThrustCast - outputBand; + } + + if ((setpointThrustCast + setpointXrate + (-setpointYrate) - setpointZrate) > (setpointThrustCast + outputBand)) { + actuators_desired.motor_left_sw = setpointThrustCast + outputBand; + } + + if ((setpointThrustCast + setpointXrate + (-setpointYrate) - setpointZrate) < (setpointThrustCast - outputBand)) { + actuators_desired.motor_left_sw = setpointThrustCast - outputBand; + } + + //printf("%lu,%lu,%lu,%lu\n",actuators_desired.motor_front_nw, actuators_desired.motor_right_ne, actuators_desired.motor_back_se, actuators_desired.motor_left_sw); + + if (motor_skip_counter % 5 == 0) { + uint8_t motorSpeedBuf[5]; + ar_get_motor_packet(motorSpeedBuf, actuators_desired.motor_front_nw, actuators_desired.motor_right_ne, actuators_desired.motor_back_se, actuators_desired.motor_left_sw); +// uint8_t* motorSpeedBuf = ar_get_motor_packet(1, 1, 1, 1); +// if(motor_skip_counter %50 == 0) +// { +// if(0==actuators_desired.motor_front_nw || 0 == actuators_desired.motor_right_ne || 0 == actuators_desired.motor_back_se || 0 == actuators_desired.motor_left_sw) +// printf("Motors set: %u, %u, %u, %u\n", actuators_desired.motor_front_nw, actuators_desired.motor_right_ne, actuators_desired.motor_back_se, actuators_desired.motor_left_sw); +// printf("input: %u\n", setpoints->motor_front_nw); +// printf("Roll casted desired: %f, Pitch casted desired: %f, Yaw casted desired: %f\n", setpointRateCast[0], setpointRateCast[1], setpointRateCast[2]); +// } + write(ardrone_write, motorSpeedBuf, 5); +// motor_skip_counter = 0; + } + + motor_skip_counter++; + + //START DEBUG +// global_data_lock(&global_data_ardrone_control->access_conf); +// global_data_ardrone_control->timestamp = hrt_absolute_time(); +// global_data_ardrone_control->gyro_scaled[0] = attRatesScaled[0]; +// global_data_ardrone_control->gyro_scaled[1] = attRatesScaled[1]; +// global_data_ardrone_control->gyro_scaled[2] = attRatesScaled[2]; +// global_data_ardrone_control->gyro_filtered[0] = gyro_filtered[0]; +// global_data_ardrone_control->gyro_filtered[1] = gyro_filtered[1]; +// global_data_ardrone_control->gyro_filtered[2] = gyro_filtered[2]; +// global_data_ardrone_control->gyro_filtered_offset[0] = gyro_filtered_offset[0]; +// global_data_ardrone_control->gyro_filtered_offset[1] = gyro_filtered_offset[1]; +// global_data_ardrone_control->gyro_filtered_offset[2] = gyro_filtered_offset[2]; +// global_data_ardrone_control->setpoint_rate_cast[0] = setpointRateCast[0]; +// global_data_ardrone_control->setpoint_rate_cast[1] = setpointRateCast[1]; +// global_data_ardrone_control->setpoint_rate_cast[2] = setpointRateCast[2]; +// global_data_ardrone_control->setpoint_thrust_cast = setpointThrustCast; +// global_data_ardrone_control->setpoint_rate[0] = setpointXrate; +// global_data_ardrone_control->setpoint_rate[1] = setpointYrate; +// global_data_ardrone_control->setpoint_rate[2] = setpointZrate; +// global_data_ardrone_control->motor_front_nw = actuators_desired.motor_front_nw; +// global_data_ardrone_control->motor_right_ne = actuators_desired.motor_right_ne; +// global_data_ardrone_control->motor_back_se = actuators_desired.motor_back_se; +// global_data_ardrone_control->motor_left_sw = actuators_desired.motor_left_sw; +// global_data_unlock(&global_data_ardrone_control->access_conf); +// global_data_broadcast(&global_data_ardrone_control->access_conf); + //END DEBUG + + + +// gettimeofday(&tv, NULL); +// now = ((uint32_t)tv.tv_sec) * 1000 + tv.tv_usec/1000; +// time_elapsed = now - last_run; +// if (time_elapsed*1000 > CONTROL_LOOP_USLEEP) +// { +// sleep_time = (int32_t)CONTROL_LOOP_USLEEP - ((int32_t)time_elapsed*1000 - (int32_t)CONTROL_LOOP_USLEEP); +// +// if(motor_skip_counter %500 == 0) +// { +// printf("Desired: %u, New usleep: %i, Time elapsed: %u, Now: %u, Last run: %u\n",(uint32_t)CONTROL_LOOP_USLEEP, sleep_time, time_elapsed*1000, now, last_run); +// } +// } +// +// if (sleep_time <= 0) +// { +// printf("WARNING: CPU Overload!\n"); +// printf("Desired: %u, New usleep: %i, Time elapsed: %u, Now: %u, Last run: %u\n",(uint32_t)CONTROL_LOOP_USLEEP, sleep_time, time_elapsed*1000, now, last_run); +// usleep(CONTROL_LOOP_USLEEP); +// } +// else +// { +// usleep(sleep_time); +// } +// last_run = now; +// +// now_time = hrt_absolute_time(); +// if(control_counter % 500 == 0) +// { +// printf("Now: %lu\n",(unsigned long)now_time); +// printf("Last: %lu\n",(unsigned long)last_time); +// printf("Difference: %lu\n", (unsigned long)(now_time - last_time)); +// printf("now seconds: %lu\n", (unsigned long)(now_time / 1000000)); +// } +// last_time = now_time; +// +// now_time = hrt_absolute_time() / 1000000; +// if(now_time - last_time > 0) +// { +// printf("Counter: %ld\n",control_counter); +// last_time = now_time; +// control_counter = 0; +// } +// control_counter++; +} diff --git a/apps/ardrone_control/rate_control.h b/apps/ardrone_control/rate_control.h new file mode 100644 index 0000000000..a69745d9b4 --- /dev/null +++ b/apps/ardrone_control/rate_control.h @@ -0,0 +1,48 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: Tobias Naegeli + * Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * @file Definition of attitude rate control + */ +#ifndef RATE_CONTROL_H_ +#define RATE_CONTROL_H_ + +#include +#include +#include + +void control_rates(struct sensor_combined_s *raw, struct ardrone_motors_setpoint_s *setpoints); + +#endif /* RATE_CONTROL_H_ */ diff --git a/apps/attitude_estimator_ekf/.context b/apps/attitude_estimator_ekf/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/attitude_estimator_ekf/Makefile b/apps/attitude_estimator_ekf/Makefile new file mode 100644 index 0000000000..cad20d3753 --- /dev/null +++ b/apps/attitude_estimator_ekf/Makefile @@ -0,0 +1,52 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +APPNAME = attitude_estimator_ekf +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 20000 + +CSRCS = attitude_estimator_ekf_main.c \ + codegen/eye.c \ + codegen/attitudeKalmanfilter.c \ + codegen/mrdivide.c \ + codegen/attitudeKalmanfilter_initialize.c \ + codegen/attitudeKalmanfilter_terminate.c \ + codegen/rt_nonfinite.c \ + codegen/rtGetInf.c \ + codegen/rtGetNaN.c \ + codegen/norm.c + +# XXX this is *horribly* broken +INCLUDES += $(TOPDIR)/../mavlink/include/mavlink + +include $(APPDIR)/mk/app.mk diff --git a/apps/attitude_estimator_ekf/attitudeKalmanfilter.m b/apps/attitude_estimator_ekf/attitudeKalmanfilter.m new file mode 100755 index 0000000000..5fb4aa94f8 --- /dev/null +++ b/apps/attitude_estimator_ekf/attitudeKalmanfilter.m @@ -0,0 +1,108 @@ +function [Rot_matrix,x_aposteriori,P_aposteriori] = attitudeKalmanfilter(dt,z_k,x_aposteriori_k,P_aposteriori_k,knownConst) +%#codegen + + +%Extended Attitude Kalmanfilter +% + %state vector x has the following entries [ax,ay,az||mx,my,mz||wox,woy,woz||wx,wy,wz]' + %measurement vector z has the following entries [ax,ay,az||mx,my,mz||wmx,wmy,wmz]' + %knownConst has the following entries [PrvaA,PrvarM,PrvarWO,PrvarW||MsvarA,MsvarM,MsvarW] + % + %[x_aposteriori,P_aposteriori] = AttKalman(dt,z_k,x_aposteriori_k,P_aposteriori_k,knownConst) + % + %Example.... + % + % $Author: Tobias Naegeli $ $Date: 2012 $ $Revision: 1 $ + + + %%define the matrices + acc_ProcessNoise=knownConst(1); + mag_ProcessNoise=knownConst(2); + ratesOffset_ProcessNoise=knownConst(3); + rates_ProcessNoise=knownConst(4); + + + acc_MeasurementNoise=knownConst(5); + mag_MeasurementNoise=knownConst(6); + rates_MeasurementNoise=knownConst(7); + + %process noise covariance matrix + Q = [ eye(3)*acc_ProcessNoise, zeros(3), zeros(3), zeros(3); + zeros(3), eye(3)*mag_ProcessNoise, zeros(3), zeros(3); + zeros(3), zeros(3), eye(3)*ratesOffset_ProcessNoise, zeros(3); + zeros(3), zeros(3), zeros(3), eye(3)*rates_ProcessNoise]; + + %measurement noise covariance matrix + R = [ eye(3)*acc_MeasurementNoise, zeros(3), zeros(3); + zeros(3), eye(3)*mag_MeasurementNoise, zeros(3); + zeros(3), zeros(3), eye(3)*rates_MeasurementNoise]; + + + %observation matrix + H_k=[ eye(3), zeros(3), zeros(3), zeros(3); + zeros(3), eye(3), zeros(3), zeros(3); + zeros(3), zeros(3), eye(3), eye(3)]; + + %compute A(t,w) + + %x_aposteriori_k[10,11,12] should be [p,q,r] + %R_temp=[1,-r, q + % r, 1, -p + % -q, p, 1] + + R_temp=[1,-dt*x_aposteriori_k(12),dt*x_aposteriori_k(11); + dt*x_aposteriori_k(12),1,-dt*x_aposteriori_k(10); + -dt*x_aposteriori_k(11), dt*x_aposteriori_k(10),1]; + + %strange, should not be transposed + A_pred=[R_temp', zeros(3), zeros(3), zeros(3); + zeros(3), R_temp', zeros(3), zeros(3); + zeros(3), zeros(3), eye(3), zeros(3); + zeros(3), zeros(3), zeros(3), eye(3)]; + + %%prediction step + x_apriori=A_pred*x_aposteriori_k; + + %linearization + acc_temp_mat=[0, dt*x_aposteriori_k(3), -dt*x_aposteriori_k(2); + -dt*x_aposteriori_k(3), 0, dt*x_aposteriori_k(1); + dt*x_aposteriori_k(2), -dt*x_aposteriori_k(1), 0]; + + mag_temp_mat=[0, dt*x_aposteriori_k(6), -dt*x_aposteriori_k(5); + -dt*x_aposteriori_k(6), 0, dt*x_aposteriori_k(4); + dt*x_aposteriori_k(5), -dt*x_aposteriori_k(4), 0]; + + A_lin=[R_temp', zeros(3), zeros(3), acc_temp_mat'; + zeros(3), R_temp', zeros(3), mag_temp_mat'; + zeros(3), zeros(3), eye(3), zeros(3); + zeros(3), zeros(3), zeros(3), eye(3)]; + + + P_apriori=A_lin*P_aposteriori_k*A_lin'+Q; + + + %%update step + + y_k=z_k-H_k*x_apriori; + S_k=H_k*P_apriori*H_k'+R; + K_k=(P_apriori*H_k'/(S_k)); + + + x_aposteriori=x_apriori+K_k*y_k; + P_aposteriori=(eye(12)-K_k*H_k)*P_apriori; + + + %%Rotation matrix generation + + earth_z=x_aposteriori(1:3)/norm(x_aposteriori(1:3)); + earth_x=cross(earth_z,x_aposteriori(4:6)/norm(x_aposteriori(4:6))); + earth_y=cross(earth_x,earth_z); + + Rot_matrix=[earth_x,earth_y,earth_z]; + + + + + + + diff --git a/apps/attitude_estimator_ekf/attitudeKalmanfilter.prj b/apps/attitude_estimator_ekf/attitudeKalmanfilter.prj new file mode 100755 index 0000000000..431ddb71e3 --- /dev/null +++ b/apps/attitude_estimator_ekf/attitudeKalmanfilter.prj @@ -0,0 +1,270 @@ + + + + option.general.TargetLang.C + true + true + true + true + true + true + true + option.general.FilePartitionMethod.MapMFileToCFile + option.general.GlobalDataSyncMethod.SyncAlways + true + option.general.DynamicMemoryAllocation.Disabled + option.paths.working.project + + option.paths.build.project + + + true + false + true + true + + + + + + + + + + true + 64 + true + 10 + 200 + 4000 + 200000 + 10000 + option.general.TargetLang.C + MATLAB Embedded Coder Target + option.CCompilerOptimization.On + + true + make_rtw + default_tmf + true + option.general.FilePartitionMethod.MapMFileToCFile + true + option.general.DynamicMemoryAllocation.Disabled + option.paths.working.project + + option.paths.build.project + + + true + false + true + true + false + $M$N + $M$N + $M$N + $M$N + $M$N + $M$N + emxArray_$M$N + 32 + + + + + + + + + + false + C89/C90 (ANSI) + true + C99 (ISO) + false + true + true + false + option.ParenthesesLevel.Nominal + false + true + true + 64 + true + 10 + 200 + 4000 + 200000 + 10000 + true + attitudeKalmanfilter_mex + attitudeKalmanfilter + option.target.artifact.lib + false + true + R2011a + true + + F:\codegenerationMatlabAttFilter\codegen\lib\attitudeKalmanfilter\html\index.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + single + 1 x 1 + + + false + + + single + 9 x 1 + + + false + + + single + 12 x 1 + + + false + + + single + 12 x 12 + + + false + + + single + 7 x 1 + + + false + + + + + + + + C:\Program Files\MATLAB\R2011a + + + false + false + true + false + false + false + false + false + 6.1 + false + true + win64 + true + + + + diff --git a/apps/attitude_estimator_ekf/attitude_estimator_ekf_main.c b/apps/attitude_estimator_ekf/attitude_estimator_ekf_main.c new file mode 100644 index 0000000000..fdf6c9d91d --- /dev/null +++ b/apps/attitude_estimator_ekf/attitude_estimator_ekf_main.c @@ -0,0 +1,263 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: Tobias Naegeli + * Laurens Mackay + * Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * @file Extended Kalman Filter for Attitude Estimation + */ + + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "codegen/attitudeKalmanfilter_initialize.h" +#include "codegen/attitudeKalmanfilter.h" + +__EXPORT int attitude_estimator_ekf_main(int argc, char *argv[]); + + +// #define N_STATES 6 + +// #define PROJECTION_INITIALIZE_COUNTER_LIMIT 5000 +// #define REPROJECTION_COUNTER_LIMIT 125 + +static unsigned int loop_interval_alarm = 4500; // loop interval in microseconds + +static float dt = 1; +/* 0, 0, -9.81, 1, 1, 1, wo (gyro offset), w */ +/* state vector x has the following entries [ax,ay,az||mx,my,mz||wox,woy,woz||wx,wy,wz]' */ +static float z_k[9] = {0}; /**< Measurement vector */ +static float x_aposteriori[12] = {0}; /**< */ +static float P_aposteriori[144] = {100.f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 100.f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 100.f, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 100.f, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 100.f, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 100.f, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 100.f, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 100.f, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 100.f, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 100.f, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100.f, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100.f + }; /**< init: diagonal matrix with big values */ +static float knownConst[7] = {1, 1, 1, 1, 1, 1, 1}; /**< knownConst has the following entries [PrvaA,PrvarM,PrvarWO,PrvarW||MsvarA,MsvarM,MsvarW] */ +static float Rot_matrix[9] = {1.f, 0, 0, + 0, 1.f, 0, + 0, 0, 1.f + }; /**< init: identity matrix */ + +// static float x_aposteriori_k[12] = {0}; +// static float P_aposteriori_k[144] = {0}; + +/* + * [Rot_matrix,x_aposteriori,P_aposteriori] = attitudeKalmanfilter(dt,z_k,x_aposteriori_k,P_aposteriori_k,knownConst) + */ + +/* + * EKF Attitude Estimator main function. + * + * Estimates the attitude recursively once started. + * + * @param argc number of commandline arguments (plus command name) + * @param argv strings containing the arguments + */ +int attitude_estimator_ekf_main(int argc, char *argv[]) +{ + // print text + printf("Extended Kalman Filter Attitude Estimator initialized..\n\n"); + fflush(stdout); + + int overloadcounter = 19; + + /* Initialize filter */ + attitudeKalmanfilter_initialize(); + + /* store start time to guard against too slow update rates */ + uint64_t last_run = hrt_absolute_time(); + + struct sensor_combined_s raw = {0}; + struct vehicle_attitude_s att = {}; + + uint64_t last_data = 0; + uint64_t last_measurement = 0; + + /* subscribe to raw data */ + int sub_raw = orb_subscribe(ORB_ID(sensor_combined)); + /* advertise attitude */ + int pub_att = orb_advertise(ORB_ID(vehicle_attitude), &att); + + + int loopcounter = 0; + int printcounter = 0; + + /* Main loop*/ + while (true) { + + struct pollfd fds[1] = { + { .fd = sub_raw, .events = POLLIN }, + }; + int ret = poll(fds, 1, 1000); + + /* check for a timeout */ + if (ret == 0) { + /* */ + + /* update successful, copy data on every 2nd run and execute filter */ + } else if (loopcounter & 0x01) { + + orb_copy(ORB_ID(sensor_combined), sub_raw, &raw); + + /* Calculate data time difference in seconds */ + dt = (raw.timestamp - last_measurement) / 1000000.0f; + last_measurement = raw.timestamp; + + // XXX Read out accel range via SPI on init, assuming 4G range at 14 bit res here + float range_g = 4.0f; + float mag_offset[3] = {0}; + /* scale from 14 bit to m/s2 */ + z_k[3] = ((raw.accelerometer_raw[0] * range_g) / 8192.0f) / 9.81f; // = accel * (1 / 32768.0f / 8.0f * 9.81f); + z_k[4] = ((raw.accelerometer_raw[1] * range_g) / 8192.0f) / 9.81f; // = accel * (1 / 32768.0f / 8.0f * 9.81f); + z_k[5] = ((raw.accelerometer_raw[2] * range_g) / 8192.0f) / 9.81f; // = accel * (1 / 32768.0f / 8.0f * 9.81f); + + // XXX Read out mag range via I2C on init, assuming 0.88 Ga and 12 bit res here + z_k[0] = (raw.magnetometer_raw[0] - mag_offset[0]) * 0.01f; + z_k[1] = (raw.magnetometer_raw[1] - mag_offset[1]) * 0.01f; + z_k[2] = (raw.magnetometer_raw[2] - mag_offset[2]) * 0.01f; + + /* Fill in gyro measurements */ + z_k[6] = raw.gyro_raw[0] * 0.00026631611f /* = gyro * (500.0f / 180.0f * pi / 32768.0f ) */; + z_k[7] = raw.gyro_raw[1] * 0.00026631611f /* = gyro * (500.0f / 180.0f * pi / 32768.0f ) */; + z_k[8] = raw.gyro_raw[2] * 0.00026631611f /* = gyro * (500.0f / 180.0f * pi / 32768.0f ) */; + + + uint64_t now = hrt_absolute_time(); + unsigned int time_elapsed = now - last_run; + last_run = now; + + if (time_elapsed > loop_interval_alarm) { + //TODO: add warning, cpu overload here + if (overloadcounter == 20) { + printf("CPU OVERLOAD DETECTED IN ATTITUDE ESTIMATOR BLACK MAGIC (%lu > %lu)\n", time_elapsed, loop_interval_alarm); + overloadcounter = 0; + } + + overloadcounter++; + } + +// now = hrt_absolute_time(); + /* filter values */ + /* + * function [Rot_matrix,x_aposteriori,P_aposteriori] = attitudeKalmanfilter(dt,z_k,x_aposteriori_k,P_aposteriori_k,knownConst) + */ + uint64_t timing_start = hrt_absolute_time(); + attitudeKalmanfilter(dt, z_k, x_aposteriori, P_aposteriori, knownConst, Rot_matrix, x_aposteriori, P_aposteriori); + uint64_t timing_diff = hrt_absolute_time() - timing_start; + + /* print rotation matrix every 200th time */ + if (printcounter % 200 == 0) { + printf("EKF attitude iteration: %d, runtime: %d us, dt: %d us (%d Hz)\n", loopcounter, (int)timing_diff, (int)(dt * 1000000.0f), (int)(1.0f / dt)); + printf("\n%d\t%d\t%d\n%d\t%d\t%d\n%d\t%d\t%d\n", (int)(Rot_matrix[0] * 100), (int)(Rot_matrix[1] * 100), (int)(Rot_matrix[2] * 100), + (int)(Rot_matrix[3] * 100), (int)(Rot_matrix[4] * 100), (int)(Rot_matrix[5] * 100), + (int)(Rot_matrix[6] * 100), (int)(Rot_matrix[7] * 100), (int)(Rot_matrix[8] * 100)); + } + + printcounter++; + +// time_elapsed = hrt_absolute_time() - now; +// if (blubb == 20) +// { +// printf("Estimator: %lu\n", time_elapsed); +// blubb = 0; +// } +// blubb++; + + if (last_data > 0 && raw.timestamp - last_data > 8000) printf("sensor data missed! (%llu)\n", raw.timestamp - last_data); + +// printf("%llu -> %llu = %llu\n", last_data, raw.timestamp, raw.timestamp - last_data); + last_data = raw.timestamp; + + /* send out */ + att.timestamp = raw.timestamp; + // att.roll = euler.x; + // att.pitch = euler.y; + // att.yaw = euler.z + F_M_PI; + + // if (att.yaw > 2 * F_M_PI) { + // att.yaw -= 2 * F_M_PI; + // } + + // att.rollspeed = rates.x; + // att.pitchspeed = rates.y; + // att.yawspeed = rates.z; + + // memcpy()R + + // Broadcast + orb_publish(ORB_ID(vehicle_attitude), pub_att, &att); + } + + loopcounter++; + } + + /* Should never reach here */ + return 0; +} + + + + + diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter.c b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter.c new file mode 100755 index 0000000000..4e275e3ee9 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter.c @@ -0,0 +1,635 @@ +/* + * attitudeKalmanfilter.c + * + * Code generation for function 'attitudeKalmanfilter' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +/* Include files */ +#include "rt_nonfinite.h" +#include "attitudeKalmanfilter.h" +#include "norm.h" +#include "eye.h" +#include "mrdivide.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ + +/* Function Definitions */ + +/* + * function [Rot_matrix,x_aposteriori,P_aposteriori] = attitudeKalmanfilter(dt,z_k,x_aposteriori_k,P_aposteriori_k,knownConst) + */ +void attitudeKalmanfilter(real32_T dt, const real32_T z_k[9], const real32_T + x_aposteriori_k[12], const real32_T P_aposteriori_k[144], const real32_T + knownConst[7], real32_T Rot_matrix[9], real32_T x_aposteriori[12], real32_T + P_aposteriori[144]) +{ + real32_T R_temp[9]; + real_T dv0[9]; + real_T dv1[9]; + int32_T i; + int32_T i0; + real32_T A_pred[144]; + real32_T x_apriori[12]; + real32_T b_A_pred[144]; + int32_T i1; + real32_T c_A_pred[144]; + static const int8_T iv0[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; + + real32_T P_apriori[144]; + real32_T b_P_apriori[108]; + static const int8_T iv1[108] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1 }; + + real32_T K_k[108]; + static const int8_T iv2[108] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; + + real32_T fv0[81]; + real32_T fv1[81]; + real32_T fv2[81]; + real32_T B; + real_T dv2[144]; + real32_T b_B; + real32_T earth_z[3]; + real32_T y[3]; + real32_T earth_x[3]; + + /* Extended Attitude Kalmanfilter */ + /* */ + /* state vector x has the following entries [ax,ay,az||mx,my,mz||wox,woy,woz||wx,wy,wz]' */ + /* measurement vector z has the following entries [ax,ay,az||mx,my,mz||wmx,wmy,wmz]' */ + /* knownConst has the following entries [PrvaA,PrvarM,PrvarWO,PrvarW||MsvarA,MsvarM,MsvarW] */ + /* */ + /* [x_aposteriori,P_aposteriori] = AttKalman(dt,z_k,x_aposteriori_k,P_aposteriori_k,knownConst) */ + /* */ + /* Example.... */ + /* */ + /* $Author: Tobias Naegeli $ $Date: 2012 $ $Revision: 1 $ */ + /* %define the matrices */ + /* 'attitudeKalmanfilter:19' acc_ProcessNoise=knownConst(1); */ + /* 'attitudeKalmanfilter:20' mag_ProcessNoise=knownConst(2); */ + /* 'attitudeKalmanfilter:21' ratesOffset_ProcessNoise=knownConst(3); */ + /* 'attitudeKalmanfilter:22' rates_ProcessNoise=knownConst(4); */ + /* 'attitudeKalmanfilter:25' acc_MeasurementNoise=knownConst(5); */ + /* 'attitudeKalmanfilter:26' mag_MeasurementNoise=knownConst(6); */ + /* 'attitudeKalmanfilter:27' rates_MeasurementNoise=knownConst(7); */ + /* process noise covariance matrix */ + /* 'attitudeKalmanfilter:30' Q = [ eye(3)*acc_ProcessNoise, zeros(3), zeros(3), zeros(3); */ + /* 'attitudeKalmanfilter:31' zeros(3), eye(3)*mag_ProcessNoise, zeros(3), zeros(3); */ + /* 'attitudeKalmanfilter:32' zeros(3), zeros(3), eye(3)*ratesOffset_ProcessNoise, zeros(3); */ + /* 'attitudeKalmanfilter:33' zeros(3), zeros(3), zeros(3), eye(3)*rates_ProcessNoise]; */ + /* measurement noise covariance matrix */ + /* 'attitudeKalmanfilter:36' R = [ eye(3)*acc_MeasurementNoise, zeros(3), zeros(3); */ + /* 'attitudeKalmanfilter:37' zeros(3), eye(3)*mag_MeasurementNoise, zeros(3); */ + /* 'attitudeKalmanfilter:38' zeros(3), zeros(3), eye(3)*rates_MeasurementNoise]; */ + /* observation matrix */ + /* 'attitudeKalmanfilter:42' H_k=[ eye(3), zeros(3), zeros(3), zeros(3); */ + /* 'attitudeKalmanfilter:43' zeros(3), eye(3), zeros(3), zeros(3); */ + /* 'attitudeKalmanfilter:44' zeros(3), zeros(3), eye(3), eye(3)]; */ + /* compute A(t,w) */ + /* x_aposteriori_k[10,11,12] should be [p,q,r] */ + /* R_temp=[1,-r, q */ + /* r, 1, -p */ + /* -q, p, 1] */ + /* 'attitudeKalmanfilter:53' R_temp=[1,-dt*x_aposteriori_k(12),dt*x_aposteriori_k(11); */ + /* 'attitudeKalmanfilter:54' dt*x_aposteriori_k(12),1,-dt*x_aposteriori_k(10); */ + /* 'attitudeKalmanfilter:55' -dt*x_aposteriori_k(11), dt*x_aposteriori_k(10),1]; */ + R_temp[0] = 1.0F; + R_temp[3] = -dt * x_aposteriori_k[11]; + R_temp[6] = dt * x_aposteriori_k[10]; + R_temp[1] = dt * x_aposteriori_k[11]; + R_temp[4] = 1.0F; + R_temp[7] = -dt * x_aposteriori_k[9]; + R_temp[2] = -dt * x_aposteriori_k[10]; + R_temp[5] = dt * x_aposteriori_k[9]; + R_temp[8] = 1.0F; + + /* strange, should not be transposed */ + /* 'attitudeKalmanfilter:58' A_pred=[R_temp', zeros(3), zeros(3), zeros(3); */ + /* 'attitudeKalmanfilter:59' zeros(3), R_temp', zeros(3), zeros(3); */ + /* 'attitudeKalmanfilter:60' zeros(3), zeros(3), eye(3), zeros(3); */ + /* 'attitudeKalmanfilter:61' zeros(3), zeros(3), zeros(3), eye(3)]; */ + eye(dv0); + eye(dv1); + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[i0 + 12 * i] = R_temp[i + 3 * i0]; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[i0 + 12 * (i + 3)] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[i0 + 12 * (i + 6)] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[i0 + 12 * (i + 9)] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * i) + 3] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 3)) + 3] = R_temp[i + 3 * i0]; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 6)) + 3] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 9)) + 3] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * i) + 6] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 3)) + 6] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 6)) + 6] = (real32_T)dv0[i0 + 3 * i]; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 9)) + 6] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * i) + 9] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 3)) + 9] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 6)) + 9] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 9)) + 9] = (real32_T)dv1[i0 + 3 * i]; + } + } + + /* %prediction step */ + /* 'attitudeKalmanfilter:64' x_apriori=A_pred*x_aposteriori_k; */ + for (i = 0; i < 12; i++) { + x_apriori[i] = 0.0F; + for (i0 = 0; i0 < 12; i0++) { + x_apriori[i] += A_pred[i + 12 * i0] * x_aposteriori_k[i0]; + } + } + + /* linearization */ + /* 'attitudeKalmanfilter:67' acc_temp_mat=[0, dt*x_aposteriori_k(3), -dt*x_aposteriori_k(2); */ + /* 'attitudeKalmanfilter:68' -dt*x_aposteriori_k(3), 0, dt*x_aposteriori_k(1); */ + /* 'attitudeKalmanfilter:69' dt*x_aposteriori_k(2), -dt*x_aposteriori_k(1), 0]; */ + /* 'attitudeKalmanfilter:71' mag_temp_mat=[0, dt*x_aposteriori_k(6), -dt*x_aposteriori_k(5); */ + /* 'attitudeKalmanfilter:72' -dt*x_aposteriori_k(6), 0, dt*x_aposteriori_k(4); */ + /* 'attitudeKalmanfilter:73' dt*x_aposteriori_k(5), -dt*x_aposteriori_k(4), 0]; */ + /* 'attitudeKalmanfilter:75' A_lin=[R_temp', zeros(3), zeros(3), acc_temp_mat'; */ + /* 'attitudeKalmanfilter:76' zeros(3), R_temp', zeros(3), mag_temp_mat'; */ + /* 'attitudeKalmanfilter:77' zeros(3), zeros(3), eye(3), zeros(3); */ + /* 'attitudeKalmanfilter:78' zeros(3), zeros(3), zeros(3), eye(3)]; */ + eye(dv0); + eye(dv1); + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[i0 + 12 * i] = R_temp[i + 3 * i0]; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[i0 + 12 * (i + 3)] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[i0 + 12 * (i + 6)] = 0.0F; + } + } + + A_pred[108] = 0.0F; + A_pred[109] = dt * x_aposteriori_k[2]; + A_pred[110] = -dt * x_aposteriori_k[1]; + A_pred[120] = -dt * x_aposteriori_k[2]; + A_pred[121] = 0.0F; + A_pred[122] = dt * x_aposteriori_k[0]; + A_pred[132] = dt * x_aposteriori_k[1]; + A_pred[133] = -dt * x_aposteriori_k[0]; + A_pred[134] = 0.0F; + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * i) + 3] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 3)) + 3] = R_temp[i + 3 * i0]; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 6)) + 3] = 0.0F; + } + } + + A_pred[111] = 0.0F; + A_pred[112] = dt * x_aposteriori_k[5]; + A_pred[113] = -dt * x_aposteriori_k[4]; + A_pred[123] = -dt * x_aposteriori_k[5]; + A_pred[124] = 0.0F; + A_pred[125] = dt * x_aposteriori_k[3]; + A_pred[135] = dt * x_aposteriori_k[4]; + A_pred[136] = -dt * x_aposteriori_k[3]; + A_pred[137] = 0.0F; + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * i) + 6] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 3)) + 6] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 6)) + 6] = (real32_T)dv0[i0 + 3 * i]; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 9)) + 6] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * i) + 9] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 3)) + 9] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 6)) + 9] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + A_pred[(i0 + 12 * (i + 9)) + 9] = (real32_T)dv1[i0 + 3 * i]; + } + } + + /* 'attitudeKalmanfilter:81' P_apriori=A_lin*P_aposteriori_k*A_lin'+Q; */ + for (i = 0; i < 12; i++) { + for (i0 = 0; i0 < 12; i0++) { + b_A_pred[i + 12 * i0] = 0.0F; + for (i1 = 0; i1 < 12; i1++) { + b_A_pred[i + 12 * i0] += A_pred[i + 12 * i1] * P_aposteriori_k[i1 + 12 * + i0]; + } + } + + for (i0 = 0; i0 < 12; i0++) { + c_A_pred[i + 12 * i0] = 0.0F; + for (i1 = 0; i1 < 12; i1++) { + c_A_pred[i + 12 * i0] += b_A_pred[i + 12 * i1] * A_pred[i0 + 12 * i1]; + } + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[i0 + 12 * i] = (real32_T)iv0[i0 + 3 * i] * knownConst[0]; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[i0 + 12 * (i + 3)] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[i0 + 12 * (i + 6)] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[i0 + 12 * (i + 9)] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[(i0 + 12 * i) + 3] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[(i0 + 12 * (i + 3)) + 3] = (real32_T)iv0[i0 + 3 * i] * + knownConst[1]; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[(i0 + 12 * (i + 6)) + 3] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[(i0 + 12 * (i + 9)) + 3] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[(i0 + 12 * i) + 6] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[(i0 + 12 * (i + 3)) + 6] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[(i0 + 12 * (i + 6)) + 6] = (real32_T)iv0[i0 + 3 * i] * + knownConst[2]; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[(i0 + 12 * (i + 9)) + 6] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[(i0 + 12 * i) + 9] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[(i0 + 12 * (i + 3)) + 9] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[(i0 + 12 * (i + 6)) + 9] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + b_A_pred[(i0 + 12 * (i + 9)) + 9] = (real32_T)iv0[i0 + 3 * i] * + knownConst[3]; + } + } + + for (i = 0; i < 12; i++) { + for (i0 = 0; i0 < 12; i0++) { + P_apriori[i0 + 12 * i] = c_A_pred[i0 + 12 * i] + b_A_pred[i0 + 12 * i]; + } + } + + /* %update step */ + /* 'attitudeKalmanfilter:86' y_k=z_k-H_k*x_apriori; */ + /* 'attitudeKalmanfilter:87' S_k=H_k*P_apriori*H_k'+R; */ + /* 'attitudeKalmanfilter:88' K_k=(P_apriori*H_k'/(S_k)); */ + for (i = 0; i < 12; i++) { + for (i0 = 0; i0 < 9; i0++) { + b_P_apriori[i + 12 * i0] = 0.0F; + for (i1 = 0; i1 < 12; i1++) { + b_P_apriori[i + 12 * i0] += P_apriori[i + 12 * i1] * (real32_T)iv1[i1 + + 12 * i0]; + } + } + } + + for (i = 0; i < 9; i++) { + for (i0 = 0; i0 < 12; i0++) { + K_k[i + 9 * i0] = 0.0F; + for (i1 = 0; i1 < 12; i1++) { + K_k[i + 9 * i0] += (real32_T)iv2[i + 9 * i1] * P_apriori[i1 + 12 * i0]; + } + } + + for (i0 = 0; i0 < 9; i0++) { + fv0[i + 9 * i0] = 0.0F; + for (i1 = 0; i1 < 12; i1++) { + fv0[i + 9 * i0] += K_k[i + 9 * i1] * (real32_T)iv1[i1 + 12 * i0]; + } + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + fv1[i0 + 9 * i] = (real32_T)iv0[i0 + 3 * i] * knownConst[4]; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + fv1[i0 + 9 * (i + 3)] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + fv1[i0 + 9 * (i + 6)] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + fv1[(i0 + 9 * i) + 3] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + fv1[(i0 + 9 * (i + 3)) + 3] = (real32_T)iv0[i0 + 3 * i] * knownConst[5]; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + fv1[(i0 + 9 * (i + 6)) + 3] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + fv1[(i0 + 9 * i) + 6] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + fv1[(i0 + 9 * (i + 3)) + 6] = 0.0F; + } + } + + for (i = 0; i < 3; i++) { + for (i0 = 0; i0 < 3; i0++) { + fv1[(i0 + 9 * (i + 6)) + 6] = (real32_T)iv0[i0 + 3 * i] * knownConst[6]; + } + } + + for (i = 0; i < 9; i++) { + for (i0 = 0; i0 < 9; i0++) { + fv2[i0 + 9 * i] = fv0[i0 + 9 * i] + fv1[i0 + 9 * i]; + } + } + + mrdivide(b_P_apriori, fv2, K_k); + + /* 'attitudeKalmanfilter:91' x_aposteriori=x_apriori+K_k*y_k; */ + for (i = 0; i < 9; i++) { + B = 0.0F; + for (i0 = 0; i0 < 12; i0++) { + B += (real32_T)iv2[i + 9 * i0] * x_apriori[i0]; + } + + R_temp[i] = z_k[i] - B; + } + + for (i = 0; i < 12; i++) { + B = 0.0F; + for (i0 = 0; i0 < 9; i0++) { + B += K_k[i + 12 * i0] * R_temp[i0]; + } + + x_aposteriori[i] = x_apriori[i] + B; + } + + /* 'attitudeKalmanfilter:92' P_aposteriori=(eye(12)-K_k*H_k)*P_apriori; */ + b_eye(dv2); + for (i = 0; i < 12; i++) { + for (i0 = 0; i0 < 12; i0++) { + B = 0.0F; + for (i1 = 0; i1 < 9; i1++) { + B += K_k[i + 12 * i1] * (real32_T)iv2[i1 + 9 * i0]; + } + + A_pred[i + 12 * i0] = (real32_T)dv2[i + 12 * i0] - B; + } + } + + for (i = 0; i < 12; i++) { + for (i0 = 0; i0 < 12; i0++) { + P_aposteriori[i + 12 * i0] = 0.0F; + for (i1 = 0; i1 < 12; i1++) { + P_aposteriori[i + 12 * i0] += A_pred[i + 12 * i1] * P_apriori[i1 + 12 * + i0]; + } + } + } + + /* %Rotation matrix generation */ + /* 'attitudeKalmanfilter:97' earth_z=x_aposteriori(1:3)/norm(x_aposteriori(1:3)); */ + B = norm(*(real32_T (*)[3])&x_aposteriori[0]); + + /* 'attitudeKalmanfilter:98' earth_x=cross(earth_z,x_aposteriori(4:6)/norm(x_aposteriori(4:6))); */ + b_B = norm(*(real32_T (*)[3])&x_aposteriori[3]); + for (i = 0; i < 3; i++) { + earth_z[i] = x_aposteriori[i] / B; + y[i] = x_aposteriori[i + 3] / b_B; + } + + earth_x[0] = earth_z[1] * y[2] - earth_z[2] * y[1]; + earth_x[1] = earth_z[2] * y[0] - earth_z[0] * y[2]; + earth_x[2] = earth_z[0] * y[1] - earth_z[1] * y[0]; + + /* 'attitudeKalmanfilter:99' earth_y=cross(earth_x,earth_z); */ + /* 'attitudeKalmanfilter:101' Rot_matrix=[earth_x,earth_y,earth_z]; */ + y[0] = earth_x[1] * earth_z[2] - earth_x[2] * earth_z[1]; + y[1] = earth_x[2] * earth_z[0] - earth_x[0] * earth_z[2]; + y[2] = earth_x[0] * earth_z[1] - earth_x[1] * earth_z[0]; + for (i = 0; i < 3; i++) { + Rot_matrix[i] = earth_x[i]; + Rot_matrix[3 + i] = y[i]; + Rot_matrix[6 + i] = earth_z[i]; + } +} + +/* End of code generation (attitudeKalmanfilter.c) */ diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter.h b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter.h new file mode 100755 index 0000000000..7aa3d048b7 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter.h @@ -0,0 +1,32 @@ +/* + * attitudeKalmanfilter.h + * + * Code generation for function 'attitudeKalmanfilter' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +#ifndef __ATTITUDEKALMANFILTER_H__ +#define __ATTITUDEKALMANFILTER_H__ +/* Include files */ +#include +#include +#include +#include + +#include "rtwtypes.h" +#include "attitudeKalmanfilter_types.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ +extern void attitudeKalmanfilter(real32_T dt, const real32_T z_k[9], const real32_T x_aposteriori_k[12], const real32_T P_aposteriori_k[144], const real32_T knownConst[7], real32_T Rot_matrix[9], real32_T x_aposteriori[12], real32_T P_aposteriori[144]); +#endif +/* End of code generation (attitudeKalmanfilter.h) */ diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.c b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.c new file mode 100755 index 0000000000..2800191c32 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.c @@ -0,0 +1,31 @@ +/* + * attitudeKalmanfilter_initialize.c + * + * Code generation for function 'attitudeKalmanfilter_initialize' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +/* Include files */ +#include "rt_nonfinite.h" +#include "attitudeKalmanfilter.h" +#include "attitudeKalmanfilter_initialize.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ + +/* Function Definitions */ +void attitudeKalmanfilter_initialize(void) +{ + rt_InitInfAndNaN(8U); +} + +/* End of code generation (attitudeKalmanfilter_initialize.c) */ diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.h b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.h new file mode 100755 index 0000000000..d2d97bb3b9 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.h @@ -0,0 +1,32 @@ +/* + * attitudeKalmanfilter_initialize.h + * + * Code generation for function 'attitudeKalmanfilter_initialize' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +#ifndef __ATTITUDEKALMANFILTER_INITIALIZE_H__ +#define __ATTITUDEKALMANFILTER_INITIALIZE_H__ +/* Include files */ +#include +#include +#include +#include + +#include "rtwtypes.h" +#include "attitudeKalmanfilter_types.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ +extern void attitudeKalmanfilter_initialize(void); +#endif +/* End of code generation (attitudeKalmanfilter_initialize.h) */ diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_ref.rsp b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_ref.rsp new file mode 100755 index 0000000000..e69de29bb2 diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_rtw.bat b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_rtw.bat new file mode 100755 index 0000000000..76fb78ca75 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_rtw.bat @@ -0,0 +1,11 @@ +@echo off +call "%VS100COMNTOOLS%..\..\VC\vcvarsall.bat" AMD64 + +cd . +nmake -f attitudeKalmanfilter_rtw.mk GENERATE_REPORT=1 ADD_MDL_NAME_TO_GLOBALS=0 +@if errorlevel 1 goto error_exit +exit /B 0 + +:error_exit +echo The make command returned an error of %errorlevel% +An_error_occurred_during_the_call_to_make diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_rtw.mk b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_rtw.mk new file mode 100755 index 0000000000..b2123704b1 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_rtw.mk @@ -0,0 +1,328 @@ +# Copyright 1994-2010 The MathWorks, Inc. +# +# File : xrt_vcx64.tmf $Revision: 1.1.6.1 $ +# +# Abstract: +# Code generation template makefile for building a Windows-based, +# stand-alone real-time version of MATLAB-code using generated C/C++ +# code and the +# Microsoft Visual C/C++ compiler version 8, 9, 10 for x64 +# +# Note that this template is automatically customized by the +# code generation build procedure to create ".mk" +# +# The following defines can be used to modify the behavior of the +# build: +# +# OPT_OPTS - Optimization option. See DEFAULT_OPT_OPTS in +# vctools.mak for default. +# OPTS - User specific options. +# CPP_OPTS - C++ compiler options. +# USER_SRCS - Additional user sources, such as files needed by +# S-functions. +# USER_INCLUDES - Additional include paths +# (i.e. USER_INCLUDES="-Iwhere-ever -Iwhere-ever2") +# +# To enable debugging: +# set OPT_OPTS=-Zi (may vary with compiler version, see compiler doc) +# modify tmf LDFLAGS to include /DEBUG +# + +#------------------------ Macros read by make_rtw ----------------------------- +# +# The following macros are read by the code generation build procedure: +# +# MAKECMD - This is the command used to invoke the make utility +# HOST - What platform this template makefile is targeted for +# (i.e. PC or UNIX) +# BUILD - Invoke make from the code generation build procedure +# (yes/no)? +# SYS_TARGET_FILE - Name of system target file. + +MAKECMD = nmake +HOST = PC +BUILD = yes +SYS_TARGET_FILE = ert.tlc +BUILD_SUCCESS = ^#^#^# Created +COMPILER_TOOL_CHAIN = vcx64 + +#---------------------- Tokens expanded by make_rtw --------------------------- +# +# The following tokens, when wrapped with "|>" and "<|" are expanded by the +# code generation build procedure. +# +# MODEL_NAME - Name of the Simulink block diagram +# MODEL_MODULES - Any additional generated source modules +# MAKEFILE_NAME - Name of makefile created from template makefile .mk +# MATLAB_ROOT - Path to where MATLAB is installed. +# MATLAB_BIN - Path to MATLAB executable. +# S_FUNCTIONS - List of S-functions. +# S_FUNCTIONS_LIB - List of S-functions libraries to link. +# SOLVER - Solver source file name +# NUMST - Number of sample times +# TID01EQ - yes (1) or no (0): Are sampling rates of continuous task +# (tid=0) and 1st discrete task equal. +# NCSTATES - Number of continuous states +# BUILDARGS - Options passed in at the command line. +# MULTITASKING - yes (1) or no (0): Is solver mode multitasking +# EXT_MODE - yes (1) or no (0): Build for external mode +# TMW_EXTMODE_TESTING - yes (1) or no (0): Build ext_test.c for external mode +# testing. +# EXTMODE_TRANSPORT - Index of transport mechanism (e.g. tcpip, serial) for extmode +# EXTMODE_STATIC - yes (1) or no (0): Use static instead of dynamic mem alloc. +# EXTMODE_STATIC_SIZE - Size of static memory allocation buffer. + +MODEL = attitudeKalmanfilter +MODULES = attitudeKalmanfilter.c eye.c mrdivide.c norm.c attitudeKalmanfilter_initialize.c attitudeKalmanfilter_terminate.c rt_nonfinite.c rtGetNaN.c rtGetInf.c +MAKEFILE = attitudeKalmanfilter_rtw.mk +MATLAB_ROOT = C:\Program Files\MATLAB\R2011a +ALT_MATLAB_ROOT = C:\PROGRA~1\MATLAB\R2011a +MATLAB_BIN = C:\Program Files\MATLAB\R2011a\bin +ALT_MATLAB_BIN = C:\PROGRA~1\MATLAB\R2011a\bin +S_FUNCTIONS = +S_FUNCTIONS_LIB = +SOLVER = +NUMST = 1 +TID01EQ = 0 +NCSTATES = 0 +BUILDARGS = GENERATE_REPORT=1 ADD_MDL_NAME_TO_GLOBALS=0 +MULTITASKING = 0 +EXT_MODE = 0 +TMW_EXTMODE_TESTING = 0 +EXTMODE_TRANSPORT = 0 +EXTMODE_STATIC = 0 +EXTMODE_STATIC_SIZE = 1000000 + +MODELREFS = +SHARED_SRC = +SHARED_SRC_DIR = +SHARED_BIN_DIR = +SHARED_LIB = +TARGET_LANG_EXT = c +OPTIMIZATION_FLAGS = /O2 /Oy- +ADDITIONAL_LDFLAGS = + +#--------------------------- Model and reference models ----------------------- +MODELLIB = attitudeKalmanfilter.lib +MODELREF_LINK_LIBS = +MODELREF_LINK_RSPFILE = attitudeKalmanfilter_ref.rsp +MODELREF_INC_PATH = +RELATIVE_PATH_TO_ANCHOR = F:\CODEGE~1 +MODELREF_TARGET_TYPE = RTW + +!if "$(MATLAB_ROOT)" != "$(ALT_MATLAB_ROOT)" +MATLAB_ROOT = $(ALT_MATLAB_ROOT) +!endif +!if "$(MATLAB_BIN)" != "$(ALT_MATLAB_BIN)" +MATLAB_BIN = $(ALT_MATLAB_BIN) +!endif + +#--------------------------- Tool Specifications ------------------------------ + +CPU = AMD64 +!include $(MATLAB_ROOT)\rtw\c\tools\vctools.mak +APPVER = 5.02 + +PERL = $(MATLAB_ROOT)\sys\perl\win32\bin\perl +#------------------------------ Include/Lib Path ------------------------------ + +MATLAB_INCLUDES = $(MATLAB_ROOT)\simulink\include +MATLAB_INCLUDES = $(MATLAB_INCLUDES);$(MATLAB_ROOT)\extern\include +MATLAB_INCLUDES = $(MATLAB_INCLUDES);$(MATLAB_ROOT)\rtw\c\src +MATLAB_INCLUDES = $(MATLAB_INCLUDES);$(MATLAB_ROOT)\rtw\c\src\ext_mode\common + +# Additional file include paths + +MATLAB_INCLUDES = $(MATLAB_INCLUDES);F:\codegenerationMatlabAttFilter\codegen\lib\attitudeKalmanfilter +MATLAB_INCLUDES = $(MATLAB_INCLUDES);F:\codegenerationMatlabAttFilter + +INCLUDE = .;$(RELATIVE_PATH_TO_ANCHOR);$(MATLAB_INCLUDES);$(INCLUDE);$(MODELREF_INC_PATH) + +!if "$(SHARED_SRC_DIR)" != "" +INCLUDE = $(INCLUDE);$(SHARED_SRC_DIR) +!endif + +#------------------------ External mode --------------------------------------- +# Uncomment -DVERBOSE to have information printed to stdout +# To add a new transport layer, see the comments in +# /toolbox/simulink/simulink/extmode_transports.m +!if $(EXT_MODE) == 1 +EXT_CC_OPTS = -DEXT_MODE # -DVERBOSE +!if $(EXTMODE_TRANSPORT) == 0 #tcpip +EXT_SRC = updown.c rtiostream_interface.c rtiostream_tcpip.c +EXT_LIB = wsock32.lib +!endif +!if $(EXTMODE_TRANSPORT) == 1 #serial_win32 +EXT_SRC = ext_svr.c updown.c ext_work.c ext_svr_serial_transport.c +EXT_SRC = $(EXT_SRC) ext_serial_pkt.c ext_serial_win32_port.c +EXT_LIB = +!endif +!if $(TMW_EXTMODE_TESTING) == 1 +EXT_SRC = $(EXT_SRC) ext_test.c +EXT_CC_OPTS = $(EXT_CC_OPTS) -DTMW_EXTMODE_TESTING +!endif +!if $(EXTMODE_STATIC) == 1 +EXT_SRC = $(EXT_SRC) mem_mgr.c +EXT_CC_OPTS = $(EXT_CC_OPTS) -DEXTMODE_STATIC -DEXTMODE_STATIC_SIZE=$(EXTMODE_STATIC_SIZE) +!endif +!else +EXT_SRC = +EXT_CC_OPTS = +EXT_LIB = +!endif + +#------------------------ rtModel ---------------------------------------------- + +RTM_CC_OPTS = -DUSE_RTMODEL + +#----------------- Compiler and Linker Options -------------------------------- + +# Optimization Options +# Set OPT_OPTS=-Zi for debugging (may depend on compiler version) +OPT_OPTS = $(DEFAULT_OPT_OPTS) + +# General User Options +OPTS = + +!if "$(OPTIMIZATION_FLAGS)" != "" +CC_OPTS = $(OPTS) $(EXT_CC_OPTS) $(RTM_CC_OPTS) $(OPTIMIZATION_FLAGS) +!else +CC_OPTS = $(OPT_OPTS) $(OPTS) $(EXT_CC_OPTS) $(RTM_CC_OPTS) +!endif + +CPP_REQ_DEFINES = -DMODEL=$(MODEL) -DRT -DNUMST=$(NUMST) \ + -DTID01EQ=$(TID01EQ) -DNCSTATES=$(NCSTATES) \ + -DMT=$(MULTITASKING) -DHAVESTDIO + +# Uncomment this line to move warning level to W4 +# cflags = $(cflags:W3=W4) +CFLAGS = $(CC_OPTS) $(CPP_REQ_DEFINES) $(USER_INCLUDES) \ + $(cflags) $(cvarsmt) /wd4996 +CPPFLAGS = $(CPP_OPTS) $(CC_OPTS) $(CPP_REQ_DEFINES) $(USER_INCLUDES) \ + $(cflags) $(cvarsmt) /wd4996 /EHsc- +LDFLAGS = $(ldebug) $(conflags) $(EXT_LIB) $(conlibs) libcpmt.lib $(ADDITIONAL_LDFLAGS) + +# libcpmt.lib is the multi-threaded, static lib version of the C++ standard lib + +#----------------------------- Source Files ----------------------------------- + + +#Standalone executable +!if "$(MODELREF_TARGET_TYPE)" == "NONE" +PRODUCT = $(RELATIVE_PATH_TO_ANCHOR)\$(MODEL).exe +REQ_SRCS = $(MODULES) $(EXT_SRC) + +#Model Reference Target +!else +PRODUCT = $(MODELLIB) +REQ_SRCS = $(MODULES) $(EXT_SRC) +!endif + +USER_SRCS = + +SRCS = $(REQ_SRCS) $(USER_SRCS) $(S_FUNCTIONS) +OBJS_CPP_UPPER = $(SRCS:.CPP=.obj) +OBJS_CPP_LOWER = $(OBJS_CPP_UPPER:.cpp=.obj) +OBJS_C_UPPER = $(OBJS_CPP_LOWER:.C=.obj) +OBJS = $(OBJS_C_UPPER:.c=.obj) +SHARED_OBJS = $(SHARED_SRC:.c=.obj) +# ------------------------- Additional Libraries ------------------------------ + +LIBS = + + +LIBS = $(LIBS) + +# ---------------------------- Linker Script ---------------------------------- + +CMD_FILE = $(MODEL).lnk +GEN_LNK_SCRIPT = $(MATLAB_ROOT)\rtw\c\tools\mkvc_lnk.pl + +#--------------------------------- Rules -------------------------------------- +all: set_environment_variables $(PRODUCT) + +!if "$(MODELREF_TARGET_TYPE)" == "NONE" +#--- Stand-alone model --- +$(PRODUCT) : $(OBJS) $(SHARED_LIB) $(LIBS) $(MODELREF_LINK_LIBS) + @cmd /C "echo ### Linking ..." + $(PERL) $(GEN_LNK_SCRIPT) $(CMD_FILE) $(OBJS) + $(LD) $(LDFLAGS) $(S_FUNCTIONS_LIB) $(SHARED_LIB) $(LIBS) $(MAT_LIBS) @$(CMD_FILE) @$(MODELREF_LINK_RSPFILE) -out:$@ + @del $(CMD_FILE) + @cmd /C "echo $(BUILD_SUCCESS) executable $(MODEL).exe" +!else +#--- Model reference code generation Target --- +$(PRODUCT) : $(OBJS) $(SHARED_LIB) + @cmd /C "echo ### Linking ..." + $(PERL) $(GEN_LNK_SCRIPT) $(CMD_FILE) $(OBJS) + $(LD) -lib /OUT:$(PRODUCT) @$(CMD_FILE) $(S_FUNCTIONS_LIB) + @cmd /C "echo $(BUILD_SUCCESS) static library $(MODELLIB)" +!endif + +{$(MATLAB_ROOT)\rtw\c\src}.c.obj : + @cmd /C "echo ### Compiling $<" + $(CC) $(CFLAGS) $< + +{$(MATLAB_ROOT)\rtw\c\src\ext_mode\common}.c.obj : + @cmd /C "echo ### Compiling $<" + $(CC) $(CFLAGS) $< + +{$(MATLAB_ROOT)\rtw\c\src\rtiostream\rtiostreamtcpip}.c.obj : + @cmd /C "echo ### Compiling $<" + $(CC) $(CFLAGS) $< + +{$(MATLAB_ROOT)\rtw\c\src\ext_mode\serial}.c.obj : + @cmd /C "echo ### Compiling $<" + $(CC) $(CFLAGS) $< + +{$(MATLAB_ROOT)\rtw\c\src\ext_mode\custom}.c.obj : + @cmd /C "echo ### Compiling $<" + $(CC) $(CFLAGS) $< + +# Additional sources + + + + + +# Put these rule last, otherwise nmake will check toolboxes first + +{$(RELATIVE_PATH_TO_ANCHOR)}.c.obj : + @cmd /C "echo ### Compiling $<" + $(CC) $(CFLAGS) $< + +{$(RELATIVE_PATH_TO_ANCHOR)}.cpp.obj : + @cmd /C "echo ### Compiling $<" + $(CC) $(CPPFLAGS) $< + +.c.obj : + @cmd /C "echo ### Compiling $<" + $(CC) $(CFLAGS) $< + +.cpp.obj : + @cmd /C "echo ### Compiling $<" + $(CC) $(CPPFLAGS) $< + +!if "$(SHARED_LIB)" != "" +$(SHARED_LIB) : $(SHARED_SRC) + @cmd /C "echo ### Creating $@" + @$(CC) $(CFLAGS) -Fo$(SHARED_BIN_DIR)\ @<< +$? +<< + @$(LIBCMD) /nologo /out:$@ $(SHARED_OBJS) + @cmd /C "echo ### $@ Created" +!endif + + +set_environment_variables: + @set INCLUDE=$(INCLUDE) + @set LIB=$(LIB) + +# Libraries: + + + + + +#----------------------------- Dependencies ----------------------------------- + +$(OBJS) : $(MAKEFILE) rtw_proj.tmw diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.c b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.c new file mode 100755 index 0000000000..eab8c7d6e0 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.c @@ -0,0 +1,31 @@ +/* + * attitudeKalmanfilter_terminate.c + * + * Code generation for function 'attitudeKalmanfilter_terminate' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +/* Include files */ +#include "rt_nonfinite.h" +#include "attitudeKalmanfilter.h" +#include "attitudeKalmanfilter_terminate.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ + +/* Function Definitions */ +void attitudeKalmanfilter_terminate(void) +{ + /* (no terminate code required) */ +} + +/* End of code generation (attitudeKalmanfilter_terminate.c) */ diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.h b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.h new file mode 100755 index 0000000000..fafd866e42 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.h @@ -0,0 +1,32 @@ +/* + * attitudeKalmanfilter_terminate.h + * + * Code generation for function 'attitudeKalmanfilter_terminate' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +#ifndef __ATTITUDEKALMANFILTER_TERMINATE_H__ +#define __ATTITUDEKALMANFILTER_TERMINATE_H__ +/* Include files */ +#include +#include +#include +#include + +#include "rtwtypes.h" +#include "attitudeKalmanfilter_types.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ +extern void attitudeKalmanfilter_terminate(void); +#endif +/* End of code generation (attitudeKalmanfilter_terminate.h) */ diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_types.h b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_types.h new file mode 100755 index 0000000000..05f4664cd9 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_types.h @@ -0,0 +1,16 @@ +/* + * attitudeKalmanfilter_types.h + * + * Code generation for function 'attitudeKalmanfilter' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +#ifndef __ATTITUDEKALMANFILTER_TYPES_H__ +#define __ATTITUDEKALMANFILTER_TYPES_H__ + +/* Type Definitions */ + +#endif +/* End of code generation (attitudeKalmanfilter_types.h) */ diff --git a/apps/attitude_estimator_ekf/codegen/buildInfo.mat b/apps/attitude_estimator_ekf/codegen/buildInfo.mat new file mode 100755 index 0000000000..b811d00397 Binary files /dev/null and b/apps/attitude_estimator_ekf/codegen/buildInfo.mat differ diff --git a/apps/attitude_estimator_ekf/codegen/eye.c b/apps/attitude_estimator_ekf/codegen/eye.c new file mode 100755 index 0000000000..e4655839c4 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/eye.c @@ -0,0 +1,51 @@ +/* + * eye.c + * + * Code generation for function 'eye' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +/* Include files */ +#include "rt_nonfinite.h" +#include "attitudeKalmanfilter.h" +#include "eye.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ + +/* Function Definitions */ + +/* + * + */ +void b_eye(real_T I[144]) +{ + int32_T i; + memset((void *)&I[0], 0, 144U * sizeof(real_T)); + for (i = 0; i < 12; i++) { + I[i + 12 * i] = 1.0; + } +} + +/* + * + */ +void eye(real_T I[9]) +{ + int32_T i; + memset((void *)&I[0], 0, 9U * sizeof(real_T)); + for (i = 0; i < 3; i++) { + I[i + 3 * i] = 1.0; + } +} + +/* End of code generation (eye.c) */ diff --git a/apps/attitude_estimator_ekf/codegen/eye.h b/apps/attitude_estimator_ekf/codegen/eye.h new file mode 100755 index 0000000000..e8881747f6 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/eye.h @@ -0,0 +1,33 @@ +/* + * eye.h + * + * Code generation for function 'eye' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +#ifndef __EYE_H__ +#define __EYE_H__ +/* Include files */ +#include +#include +#include +#include + +#include "rtwtypes.h" +#include "attitudeKalmanfilter_types.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ +extern void b_eye(real_T I[144]); +extern void eye(real_T I[9]); +#endif +/* End of code generation (eye.h) */ diff --git a/apps/attitude_estimator_ekf/codegen/mrdivide.c b/apps/attitude_estimator_ekf/codegen/mrdivide.c new file mode 100755 index 0000000000..cb81b53282 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/mrdivide.c @@ -0,0 +1,158 @@ +/* + * mrdivide.c + * + * Code generation for function 'mrdivide' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +/* Include files */ +#include "rt_nonfinite.h" +#include "attitudeKalmanfilter.h" +#include "mrdivide.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ + +/* Function Definitions */ + +/* + * + */ +void mrdivide(const real32_T A[108], const real32_T B[81], real32_T y[108]) +{ + int32_T jy; + int32_T iy; + real32_T b_A[81]; + int8_T ipiv[9]; + int32_T j; + int32_T mmj; + int32_T jj; + int32_T jp1j; + int32_T c; + int32_T ix; + real32_T temp; + int32_T k; + real32_T s; + int32_T loop_ub; + real32_T Y[108]; + for (jy = 0; jy < 9; jy++) { + for (iy = 0; iy < 9; iy++) { + b_A[iy + 9 * jy] = B[jy + 9 * iy]; + } + + ipiv[jy] = (int8_T)(1 + jy); + } + + for (j = 0; j < 8; j++) { + mmj = -j; + jj = j * 10; + jp1j = jj + 1; + c = mmj + 9; + jy = 0; + ix = jj; + temp = fabsf(b_A[jj]); + for (k = 2; k <= c; k++) { + ix++; + s = fabsf(b_A[ix]); + if (s > temp) { + jy = k - 1; + temp = s; + } + } + + if ((real_T)b_A[jj + jy] != 0.0) { + if (jy != 0) { + ipiv[j] = (int8_T)((j + jy) + 1); + ix = j; + iy = j + jy; + for (k = 0; k < 9; k++) { + temp = b_A[ix]; + b_A[ix] = b_A[iy]; + b_A[iy] = temp; + ix += 9; + iy += 9; + } + } + + loop_ub = (jp1j + mmj) + 8; + for (iy = jp1j; iy + 1 <= loop_ub; iy++) { + b_A[iy] /= b_A[jj]; + } + } + + c = 8 - j; + jy = jj + 9; + for (iy = 1; iy <= c; iy++) { + if ((real_T)b_A[jy] != 0.0) { + temp = b_A[jy] * -1.0F; + ix = jp1j; + loop_ub = (mmj + jj) + 18; + for (k = 10 + jj; k + 1 <= loop_ub; k++) { + b_A[k] += b_A[ix] * temp; + ix++; + } + } + + jy += 9; + jj += 9; + } + } + + for (jy = 0; jy < 12; jy++) { + for (iy = 0; iy < 9; iy++) { + Y[iy + 9 * jy] = A[jy + 12 * iy]; + } + } + + for (iy = 0; iy < 9; iy++) { + if (ipiv[iy] != iy + 1) { + for (j = 0; j < 12; j++) { + temp = Y[iy + 9 * j]; + Y[iy + 9 * j] = Y[(ipiv[iy] + 9 * j) - 1]; + Y[(ipiv[iy] + 9 * j) - 1] = temp; + } + } + } + + for (j = 0; j < 12; j++) { + c = 9 * j; + for (k = 0; k < 9; k++) { + jy = 9 * k; + if ((real_T)Y[k + c] != 0.0) { + for (iy = k + 2; iy < 10; iy++) { + Y[(iy + c) - 1] -= Y[k + c] * b_A[(iy + jy) - 1]; + } + } + } + } + + for (j = 0; j < 12; j++) { + c = 9 * j; + for (k = 8; k > -1; k += -1) { + jy = 9 * k; + if ((real_T)Y[k + c] != 0.0) { + Y[k + c] /= b_A[k + jy]; + for (iy = 0; iy + 1 <= k; iy++) { + Y[iy + c] -= Y[k + c] * b_A[iy + jy]; + } + } + } + } + + for (jy = 0; jy < 9; jy++) { + for (iy = 0; iy < 12; iy++) { + y[iy + 12 * jy] = Y[jy + 9 * iy]; + } + } +} + +/* End of code generation (mrdivide.c) */ diff --git a/apps/attitude_estimator_ekf/codegen/mrdivide.h b/apps/attitude_estimator_ekf/codegen/mrdivide.h new file mode 100755 index 0000000000..e81bfffc0a --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/mrdivide.h @@ -0,0 +1,32 @@ +/* + * mrdivide.h + * + * Code generation for function 'mrdivide' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +#ifndef __MRDIVIDE_H__ +#define __MRDIVIDE_H__ +/* Include files */ +#include +#include +#include +#include + +#include "rtwtypes.h" +#include "attitudeKalmanfilter_types.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ +extern void mrdivide(const real32_T A[108], const real32_T B[81], real32_T y[108]); +#endif +/* End of code generation (mrdivide.h) */ diff --git a/apps/attitude_estimator_ekf/codegen/norm.c b/apps/attitude_estimator_ekf/codegen/norm.c new file mode 100755 index 0000000000..1fbde052bc --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/norm.c @@ -0,0 +1,62 @@ +/* + * norm.c + * + * Code generation for function 'norm' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +/* Include files */ +#include "rt_nonfinite.h" +#include "attitudeKalmanfilter.h" +#include "norm.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ + +/* Function Definitions */ + +/* + * + */ +real32_T norm(const real32_T x[3]) +{ + real32_T y; + real32_T scale; + boolean_T firstNonZero; + int32_T k; + real32_T absxk; + real32_T t; + y = 0.0F; + scale = 0.0F; + firstNonZero = TRUE; + for (k = 0; k < 3; k++) { + if (x[k] != 0.0F) { + absxk = fabsf(x[k]); + if (firstNonZero) { + scale = absxk; + y = 1.0F; + firstNonZero = FALSE; + } else if (scale < absxk) { + t = scale / absxk; + y = 1.0F + y * t * t; + scale = absxk; + } else { + t = absxk / scale; + y += t * t; + } + } + } + + return scale * sqrtf(y); +} + +/* End of code generation (norm.c) */ diff --git a/apps/attitude_estimator_ekf/codegen/norm.h b/apps/attitude_estimator_ekf/codegen/norm.h new file mode 100755 index 0000000000..b0c7fe430e --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/norm.h @@ -0,0 +1,32 @@ +/* + * norm.h + * + * Code generation for function 'norm' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +#ifndef __NORM_H__ +#define __NORM_H__ +/* Include files */ +#include +#include +#include +#include + +#include "rtwtypes.h" +#include "attitudeKalmanfilter_types.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ +extern real32_T norm(const real32_T x[3]); +#endif +/* End of code generation (norm.h) */ diff --git a/apps/attitude_estimator_ekf/codegen/rtGetInf.c b/apps/attitude_estimator_ekf/codegen/rtGetInf.c new file mode 100755 index 0000000000..3cef176848 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/rtGetInf.c @@ -0,0 +1,139 @@ +/* + * rtGetInf.c + * + * Code generation for function 'attitudeKalmanfilter' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +/* + * Abstract: + * MATLAB for code generation function to initialize non-finite, Inf and MinusInf + */ +#include "rtGetInf.h" +#define NumBitsPerChar 8U + +/* Function: rtGetInf ================================================== + * Abstract: + * Initialize rtInf needed by the generated code. + * Inf is initialized as non-signaling. Assumes IEEE. + */ +real_T rtGetInf(void) +{ + size_t bitsPerReal = sizeof(real_T) * (NumBitsPerChar); + real_T inf = 0.0; + if (bitsPerReal == 32U) { + inf = rtGetInfF(); + } else { + uint16_T one = 1U; + enum { + LittleEndian, + BigEndian + } machByteOrder = (*((uint8_T *) &one) == 1U) ? LittleEndian : BigEndian; + switch (machByteOrder) { + case LittleEndian: + { + union { + LittleEndianIEEEDouble bitVal; + real_T fltVal; + } tmpVal; + + tmpVal.bitVal.words.wordH = 0x7FF00000U; + tmpVal.bitVal.words.wordL = 0x00000000U; + inf = tmpVal.fltVal; + break; + } + + case BigEndian: + { + union { + BigEndianIEEEDouble bitVal; + real_T fltVal; + } tmpVal; + + tmpVal.bitVal.words.wordH = 0x7FF00000U; + tmpVal.bitVal.words.wordL = 0x00000000U; + inf = tmpVal.fltVal; + break; + } + } + } + + return inf; +} + +/* Function: rtGetInfF ================================================== + * Abstract: + * Initialize rtInfF needed by the generated code. + * Inf is initialized as non-signaling. Assumes IEEE. + */ +real32_T rtGetInfF(void) +{ + IEEESingle infF; + infF.wordL.wordLuint = 0x7F800000U; + return infF.wordL.wordLreal; +} + +/* Function: rtGetMinusInf ================================================== + * Abstract: + * Initialize rtMinusInf needed by the generated code. + * Inf is initialized as non-signaling. Assumes IEEE. + */ +real_T rtGetMinusInf(void) +{ + size_t bitsPerReal = sizeof(real_T) * (NumBitsPerChar); + real_T minf = 0.0; + if (bitsPerReal == 32U) { + minf = rtGetMinusInfF(); + } else { + uint16_T one = 1U; + enum { + LittleEndian, + BigEndian + } machByteOrder = (*((uint8_T *) &one) == 1U) ? LittleEndian : BigEndian; + switch (machByteOrder) { + case LittleEndian: + { + union { + LittleEndianIEEEDouble bitVal; + real_T fltVal; + } tmpVal; + + tmpVal.bitVal.words.wordH = 0xFFF00000U; + tmpVal.bitVal.words.wordL = 0x00000000U; + minf = tmpVal.fltVal; + break; + } + + case BigEndian: + { + union { + BigEndianIEEEDouble bitVal; + real_T fltVal; + } tmpVal; + + tmpVal.bitVal.words.wordH = 0xFFF00000U; + tmpVal.bitVal.words.wordL = 0x00000000U; + minf = tmpVal.fltVal; + break; + } + } + } + + return minf; +} + +/* Function: rtGetMinusInfF ================================================== + * Abstract: + * Initialize rtMinusInfF needed by the generated code. + * Inf is initialized as non-signaling. Assumes IEEE. + */ +real32_T rtGetMinusInfF(void) +{ + IEEESingle minfF; + minfF.wordL.wordLuint = 0xFF800000U; + return minfF.wordL.wordLreal; +} + +/* End of code generation (rtGetInf.c) */ diff --git a/apps/attitude_estimator_ekf/codegen/rtGetInf.h b/apps/attitude_estimator_ekf/codegen/rtGetInf.h new file mode 100755 index 0000000000..ab2d5a70d5 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/rtGetInf.h @@ -0,0 +1,23 @@ +/* + * rtGetInf.h + * + * Code generation for function 'attitudeKalmanfilter' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +#ifndef __RTGETINF_H__ +#define __RTGETINF_H__ + +#include +#include "rtwtypes.h" +#include "rt_nonfinite.h" + +extern real_T rtGetInf(void); +extern real32_T rtGetInfF(void); +extern real_T rtGetMinusInf(void); +extern real32_T rtGetMinusInfF(void); + +#endif +/* End of code generation (rtGetInf.h) */ diff --git a/apps/attitude_estimator_ekf/codegen/rtGetNaN.c b/apps/attitude_estimator_ekf/codegen/rtGetNaN.c new file mode 100755 index 0000000000..17a093461f --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/rtGetNaN.c @@ -0,0 +1,96 @@ +/* + * rtGetNaN.c + * + * Code generation for function 'attitudeKalmanfilter' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +/* + * Abstract: + * MATLAB for code generation function to initialize non-finite, NaN + */ +#include "rtGetNaN.h" +#define NumBitsPerChar 8U + +/* Function: rtGetNaN ================================================== + * Abstract: + * Initialize rtNaN needed by the generated code. + * NaN is initialized as non-signaling. Assumes IEEE. + */ +real_T rtGetNaN(void) +{ + size_t bitsPerReal = sizeof(real_T) * (NumBitsPerChar); + real_T nan = 0.0; + if (bitsPerReal == 32U) { + nan = rtGetNaNF(); + } else { + uint16_T one = 1U; + enum { + LittleEndian, + BigEndian + } machByteOrder = (*((uint8_T *) &one) == 1U) ? LittleEndian : BigEndian; + switch (machByteOrder) { + case LittleEndian: + { + union { + LittleEndianIEEEDouble bitVal; + real_T fltVal; + } tmpVal; + + tmpVal.bitVal.words.wordH = 0xFFF80000U; + tmpVal.bitVal.words.wordL = 0x00000000U; + nan = tmpVal.fltVal; + break; + } + + case BigEndian: + { + union { + BigEndianIEEEDouble bitVal; + real_T fltVal; + } tmpVal; + + tmpVal.bitVal.words.wordH = 0x7FFFFFFFU; + tmpVal.bitVal.words.wordL = 0xFFFFFFFFU; + nan = tmpVal.fltVal; + break; + } + } + } + + return nan; +} + +/* Function: rtGetNaNF ================================================== + * Abstract: + * Initialize rtNaNF needed by the generated code. + * NaN is initialized as non-signaling. Assumes IEEE. + */ +real32_T rtGetNaNF(void) +{ + IEEESingle nanF = { { 0 } }; + uint16_T one = 1U; + enum { + LittleEndian, + BigEndian + } machByteOrder = (*((uint8_T *) &one) == 1U) ? LittleEndian : BigEndian; + switch (machByteOrder) { + case LittleEndian: + { + nanF.wordL.wordLuint = 0xFFC00000U; + break; + } + + case BigEndian: + { + nanF.wordL.wordLuint = 0x7FFFFFFFU; + break; + } + } + + return nanF.wordL.wordLreal; +} + +/* End of code generation (rtGetNaN.c) */ diff --git a/apps/attitude_estimator_ekf/codegen/rtGetNaN.h b/apps/attitude_estimator_ekf/codegen/rtGetNaN.h new file mode 100755 index 0000000000..2c254bbbf6 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/rtGetNaN.h @@ -0,0 +1,21 @@ +/* + * rtGetNaN.h + * + * Code generation for function 'attitudeKalmanfilter' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +#ifndef __RTGETNAN_H__ +#define __RTGETNAN_H__ + +#include +#include "rtwtypes.h" +#include "rt_nonfinite.h" + +extern real_T rtGetNaN(void); +extern real32_T rtGetNaNF(void); + +#endif +/* End of code generation (rtGetNaN.h) */ diff --git a/apps/attitude_estimator_ekf/codegen/rt_nonfinite.c b/apps/attitude_estimator_ekf/codegen/rt_nonfinite.c new file mode 100755 index 0000000000..005c4f28de --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/rt_nonfinite.c @@ -0,0 +1,87 @@ +/* + * rt_nonfinite.c + * + * Code generation for function 'attitudeKalmanfilter' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +/* + * Abstract: + * MATLAB for code generation function to initialize non-finites, + * (Inf, NaN and -Inf). + */ +#include "rt_nonfinite.h" +#include "rtGetNaN.h" +#include "rtGetInf.h" + +real_T rtInf; +real_T rtMinusInf; +real_T rtNaN; +real32_T rtInfF; +real32_T rtMinusInfF; +real32_T rtNaNF; + +/* Function: rt_InitInfAndNaN ================================================== + * Abstract: + * Initialize the rtInf, rtMinusInf, and rtNaN needed by the + * generated code. NaN is initialized as non-signaling. Assumes IEEE. + */ +void rt_InitInfAndNaN(size_t realSize) +{ + (void) (realSize); + rtNaN = rtGetNaN(); + rtNaNF = rtGetNaNF(); + rtInf = rtGetInf(); + rtInfF = rtGetInfF(); + rtMinusInf = rtGetMinusInf(); + rtMinusInfF = rtGetMinusInfF(); +} + +/* Function: rtIsInf ================================================== + * Abstract: + * Test if value is infinite + */ +boolean_T rtIsInf(real_T value) +{ + return ((value==rtInf || value==rtMinusInf) ? 1U : 0U); +} + +/* Function: rtIsInfF ================================================= + * Abstract: + * Test if single-precision value is infinite + */ +boolean_T rtIsInfF(real32_T value) +{ + return(((value)==rtInfF || (value)==rtMinusInfF) ? 1U : 0U); +} + +/* Function: rtIsNaN ================================================== + * Abstract: + * Test if value is not a number + */ +boolean_T rtIsNaN(real_T value) +{ +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + return _isnan(value)? TRUE:FALSE; +#else + return (value!=value)? 1U:0U; +#endif +} + +/* Function: rtIsNaNF ================================================= + * Abstract: + * Test if single-precision value is not a number + */ +boolean_T rtIsNaNF(real32_T value) +{ +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + return _isnan((real_T)value)? true:false; +#else + return (value!=value)? 1U:0U; +#endif +} + + +/* End of code generation (rt_nonfinite.c) */ diff --git a/apps/attitude_estimator_ekf/codegen/rt_nonfinite.h b/apps/attitude_estimator_ekf/codegen/rt_nonfinite.h new file mode 100755 index 0000000000..6481f011f8 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/rt_nonfinite.h @@ -0,0 +1,53 @@ +/* + * rt_nonfinite.h + * + * Code generation for function 'attitudeKalmanfilter' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +#ifndef __RT_NONFINITE_H__ +#define __RT_NONFINITE_H__ + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) +#include +#endif +#include +#include "rtwtypes.h" + +extern real_T rtInf; +extern real_T rtMinusInf; +extern real_T rtNaN; +extern real32_T rtInfF; +extern real32_T rtMinusInfF; +extern real32_T rtNaNF; +extern void rt_InitInfAndNaN(size_t realSize); +extern boolean_T rtIsInf(real_T value); +extern boolean_T rtIsInfF(real32_T value); +extern boolean_T rtIsNaN(real_T value); +extern boolean_T rtIsNaNF(real32_T value); + +typedef struct { + struct { + uint32_T wordH; + uint32_T wordL; + } words; +} BigEndianIEEEDouble; + +typedef struct { + struct { + uint32_T wordL; + uint32_T wordH; + } words; +} LittleEndianIEEEDouble; + +typedef struct { + union { + real32_T wordLreal; + uint32_T wordLuint; + } wordL; +} IEEESingle; + +#endif +/* End of code generation (rt_nonfinite.h) */ diff --git a/apps/attitude_estimator_ekf/codegen/rtw_proj.tmw b/apps/attitude_estimator_ekf/codegen/rtw_proj.tmw new file mode 100755 index 0000000000..1fb585abd7 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/rtw_proj.tmw @@ -0,0 +1 @@ +Code generation project for attitudeKalmanfilter using C:\Program Files\MATLAB\R2011a\toolbox\coder\coder\rtw\c\xrt\xrt_vcx64.tmf. MATLAB root = C:\Program Files\MATLAB\R2011a. diff --git a/apps/attitude_estimator_ekf/codegen/rtwtypes.h b/apps/attitude_estimator_ekf/codegen/rtwtypes.h new file mode 100755 index 0000000000..fd629ebcd0 --- /dev/null +++ b/apps/attitude_estimator_ekf/codegen/rtwtypes.h @@ -0,0 +1,159 @@ +/* + * rtwtypes.h + * + * Code generation for function 'attitudeKalmanfilter' + * + * C source code generated on: Wed Jul 11 08:38:35 2012 + * + */ + +#ifndef __RTWTYPES_H__ +#define __RTWTYPES_H__ +#ifndef TRUE +# define TRUE (1U) +#endif +#ifndef FALSE +# define FALSE (0U) +#endif +#ifndef __TMWTYPES__ +#define __TMWTYPES__ + +#include + +/*=======================================================================* + * Target hardware information + * Device type: Generic->MATLAB Host Computer + * Number of bits: char: 8 short: 16 int: 32 + * long: 32 native word size: 32 + * Byte ordering: LittleEndian + * Signed integer division rounds to: Zero + * Shift right on a signed integer as arithmetic shift: on + *=======================================================================*/ + +/*=======================================================================* + * Fixed width word size data types: * + * int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers * + * uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers * + * real32_T, real64_T - 32 and 64 bit floating point numbers * + *=======================================================================*/ + +typedef signed char int8_T; +typedef unsigned char uint8_T; +typedef short int16_T; +typedef unsigned short uint16_T; +typedef int int32_T; +typedef unsigned int uint32_T; +typedef float real32_T; +typedef double real64_T; + +/*===========================================================================* + * Generic type definitions: real_T, time_T, boolean_T, int_T, uint_T, * + * ulong_T, char_T and byte_T. * + *===========================================================================*/ + +typedef double real_T; +typedef double time_T; +typedef unsigned char boolean_T; +typedef int int_T; +typedef unsigned int uint_T; +typedef unsigned long ulong_T; +typedef char char_T; +typedef char_T byte_T; + +/*===========================================================================* + * Complex number type definitions * + *===========================================================================*/ +#define CREAL_T + typedef struct { + real32_T re; + real32_T im; + } creal32_T; + + typedef struct { + real64_T re; + real64_T im; + } creal64_T; + + typedef struct { + real_T re; + real_T im; + } creal_T; + + typedef struct { + int8_T re; + int8_T im; + } cint8_T; + + typedef struct { + uint8_T re; + uint8_T im; + } cuint8_T; + + typedef struct { + int16_T re; + int16_T im; + } cint16_T; + + typedef struct { + uint16_T re; + uint16_T im; + } cuint16_T; + + typedef struct { + int32_T re; + int32_T im; + } cint32_T; + + typedef struct { + uint32_T re; + uint32_T im; + } cuint32_T; + + +/*=======================================================================* + * Min and Max: * + * int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers * + * uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers * + *=======================================================================*/ + +#define MAX_int8_T ((int8_T)(127)) +#define MIN_int8_T ((int8_T)(-128)) +#define MAX_uint8_T ((uint8_T)(255)) +#define MIN_uint8_T ((uint8_T)(0)) +#define MAX_int16_T ((int16_T)(32767)) +#define MIN_int16_T ((int16_T)(-32768)) +#define MAX_uint16_T ((uint16_T)(65535)) +#define MIN_uint16_T ((uint16_T)(0)) +#define MAX_int32_T ((int32_T)(2147483647)) +#define MIN_int32_T ((int32_T)(-2147483647-1)) +#define MAX_uint32_T ((uint32_T)(0xFFFFFFFFU)) +#define MIN_uint32_T ((uint32_T)(0)) + +/* Logical type definitions */ +#if !defined(__cplusplus) && !defined(__true_false_are_keywords) +# ifndef false +# define false (0U) +# endif +# ifndef true +# define true (1U) +# endif +#endif + +/* + * MATLAB for code generation assumes the code is compiled on a target using a 2's compliment representation + * for signed integer values. + */ +#if ((SCHAR_MIN + 1) != -SCHAR_MAX) +#error "This code must be compiled using a 2's complement representation for signed integer values" +#endif + +/* + * Maximum length of a MATLAB identifier (function/variable) + * including the null-termination character. Referenced by + * rt_logging.c and rt_matrx.c. + */ +#define TMW_NAME_LENGTH_MAX 64 + +#endif +#endif +/* End of code generation (rtwtypes.h) */ diff --git a/apps/commander/.context b/apps/commander/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/commander/Makefile b/apps/commander/Makefile new file mode 100644 index 0000000000..a1149eb8de --- /dev/null +++ b/apps/commander/Makefile @@ -0,0 +1,45 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Commander application +# + +APPNAME = commander +PRIORITY = SCHED_PRIORITY_MAX - 10 +STACKSIZE = 3072 + +INCLUDES = $(TOPDIR)/../mavlink/include/mavlink + +include $(APPDIR)/mk/app.mk + diff --git a/apps/commander/commander.c b/apps/commander/commander.c new file mode 100644 index 0000000000..f342298ee7 --- /dev/null +++ b/apps/commander/commander.c @@ -0,0 +1,862 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Petri Tanskanen + * @author Lorenz Meier + * @author Thomas Gubler + * @author Julian Oes + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file commander.c + * Main system state machine implementation. + */ + +#include "commander.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "state_machine_helper.h" +#include "systemlib/systemlib.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +extern struct system_load_s system_load; + +/* Decouple update interval and hysteris counters, all depends on intervals */ +#define COMMANDER_MONITORING_INTERVAL 50000 +#define COMMANDER_MONITORING_LOOPSPERMSEC (1/(COMMANDER_MONITORING_INTERVAL/1000.0f)) +#define LOW_VOLTAGE_BATTERY_COUNTER_LIMIT (LOW_VOLTAGE_BATTERY_HYSTERESIS_TIME_MS*COMMANDER_MONITORING_LOOPSPERMSEC) +#define CRITICAL_VOLTAGE_BATTERY_COUNTER_LIMIT (CRITICAL_VOLTAGE_BATTERY_HYSTERESIS_TIME_MS*COMMANDER_MONITORING_LOOPSPERMSEC) + +#define STICK_ON_OFF_LIMIT 7500 +#define STICK_ON_OFF_HYSTERESIS_TIME_MS 1000 +#define STICK_ON_OFF_COUNTER_LIMIT (STICK_ON_OFF_HYSTERESIS_TIME_MS*COMMANDER_MONITORING_LOOPSPERMSEC) + +#define GPS_FIX_TYPE_2D 2 +#define GPS_FIX_TYPE_3D 3 +#define GPS_QUALITY_GOOD_COUNTER_LIMIT 50 + +/* File descriptors */ +static int leds; +static int buzzer; +static int mavlink_fd; +static bool commander_initialized = false; +static struct vehicle_status_s current_status = { + .state_machine = SYSTEM_STATE_PREFLIGHT, + .mode = 0 +}; /**< Main state machine */ +static int stat_pub; + +static uint16_t nofix_counter = 0; +static uint16_t gotfix_counter = 0; + +static void handle_command(int status_pub, struct vehicle_status_s *current_status, struct vehicle_command_s *cmd); + +/* pthread loops */ +static void *command_handling_loop(void *arg); +// static void *subsystem_info_loop(void *arg); + +__EXPORT int commander_main(int argc, char *argv[]); + +#ifdef CONFIG_TONE_ALARM +static int buzzer_init(void); +static void buzzer_deinit(void); + +static int buzzer_init() +{ + buzzer = open("/dev/tone_alarm", O_WRONLY); + + if (buzzer < 0) { + fprintf(stderr, "[commander] Buzzer: open fail\n"); + return ERROR; + } + + return 0; +} + +static void buzzer_deinit() +{ + close(buzzer); +} +#endif + +static int led_init(void); +static void led_deinit(void); +static int led_toggle(int led); +static int led_on(int led); +static int led_off(int led); + +static int led_init() +{ + leds = open("/dev/led", O_RDONLY | O_NONBLOCK); + + if (leds < 0) { + fprintf(stderr, "[commander] LED: open fail\n"); + return ERROR; + } + + if (ioctl(leds, LED_ON, LED_BLUE) || ioctl(leds, LED_ON, LED_AMBER)) { + fprintf(stderr, "[commander] LED: ioctl fail\n"); + return ERROR; + } + + return 0; +} + +static void led_deinit() +{ + close(leds); +} + +static int led_toggle(int led) +{ + static int last_blue = LED_ON; + static int last_amber = LED_ON; + + if (led == LED_BLUE) last_blue = (last_blue == LED_ON) ? LED_OFF : LED_ON; + + if (led == LED_AMBER) last_amber = (last_amber == LED_ON) ? LED_OFF : LED_ON; + + return ioctl(leds, ((led == LED_BLUE) ? last_blue : last_amber), led); +} + +static int led_on(int led) +{ + return ioctl(leds, LED_ON, led); +} + +static int led_off(int led) +{ + return ioctl(leds, LED_OFF, led); +} + +enum AUDIO_PATTERN { + AUDIO_PATTERN_ERROR = 1, + AUDIO_PATTERN_NOTIFY_POSITIVE = 2, + AUDIO_PATTERN_NOTIFY_NEUTRAL = 3, + AUDIO_PATTERN_NOTIFY_NEGATIVE = 4, + AUDIO_PATTERN_TETRIS = 5 +}; + +int trigger_audio_alarm(uint8_t old_mode, uint8_t old_state, uint8_t new_mode, uint8_t new_state) { + + /* Trigger alarm if going into any error state */ + if (((new_state == SYSTEM_STATE_GROUND_ERROR) && (old_state != SYSTEM_STATE_GROUND_ERROR)) || + ((new_state == SYSTEM_STATE_MISSION_ABORT) && (old_state != SYSTEM_STATE_MISSION_ABORT))) { + ioctl(buzzer, TONE_SET_ALARM, 0); + ioctl(buzzer, TONE_SET_ALARM, AUDIO_PATTERN_ERROR); + } + + /* Trigger neutral on arming / disarming */ + if (((new_state == SYSTEM_STATE_GROUND_READY) && (old_state != SYSTEM_STATE_GROUND_READY))) { + ioctl(buzzer, TONE_SET_ALARM, 0); + ioctl(buzzer, TONE_SET_ALARM, AUDIO_PATTERN_NOTIFY_NEUTRAL); + } + + /* Trigger Tetris on being bored */ + + return 0; +} + +void do_gyro_calibration(void) +{ + + const int calibration_count = 3000; + + int sub_sensor_combined = orb_subscribe(ORB_ID(sensor_combined)); + struct sensor_combined_s raw; + + int calibration_counter = 0; + float gyro_offset[3] = {0, 0, 0}; + + while (calibration_counter < calibration_count) { + + /* wait blocking for new data */ + struct pollfd fds[1] = { { .fd = sub_sensor_combined, .events = POLLIN } }; + + if (poll(fds, 1, 1000)) { + orb_copy(ORB_ID(sensor_combined), sub_sensor_combined, &raw); + gyro_offset[0] += raw.gyro_raw[0]; + gyro_offset[1] += raw.gyro_raw[1]; + gyro_offset[2] += raw.gyro_raw[2]; + calibration_counter++; + } + } + + gyro_offset[0] = gyro_offset[0] / calibration_count; + gyro_offset[1] = gyro_offset[1] / calibration_count; + gyro_offset[2] = gyro_offset[2] / calibration_count; + + global_data_parameter_storage->pm.param_values[PARAM_SENSOR_GYRO_XOFFSET] = gyro_offset[0]; + global_data_parameter_storage->pm.param_values[PARAM_SENSOR_GYRO_YOFFSET] = gyro_offset[1]; + global_data_parameter_storage->pm.param_values[PARAM_SENSOR_GYRO_ZOFFSET] = gyro_offset[2]; + + char offset_output[50]; + sprintf(offset_output, "[commander] gyro calibration finished, offsets: x:%d, y:%d, z:%d", (int)gyro_offset[0], (int)gyro_offset[1], (int)gyro_offset[2]); + mavlink_log_info(mavlink_fd, offset_output); + + close(sub_sensor_combined); + + // XXX Add a parameter changed broadcast notification +} + + + +void handle_command(int status_pub, struct vehicle_status_s *current_vehicle_status, struct vehicle_command_s *cmd) +{ + /* result of the command */ + uint8_t result = MAV_RESULT_UNSUPPORTED; + + + /* supported command handling start */ + + /* request to set different system mode */ + switch (cmd->command) { + + + case MAV_CMD_DO_SET_MODE: + { + update_state_machine_mode_request(status_pub, current_vehicle_status, (uint8_t)cmd->param1); + } + break; +// +// case MAV_CMD_COMPONENT_ARM_DISARM: +// { +// /* request to arm */ +// if (cmd->param1 == 1.0f) { +// if (0 == update_state_machine_custom_mode_request(status_pub, current_vehicle_status, SYSTEM_STATE_ARMED)) +// result = MAV_RESULT_ACCEPTED; +// /* request to disarm */ +// } else if (cmd->param1 == 0.0f) { +// if (0 == update_state_machine_custom_mode_request(status_pub, current_vehicle_status, SYSTEM_STATE_STANDBY)) +// result = MAV_RESULT_ACCEPTED; +// } +// } +// break; +// +// /* request for an autopilot reboot */ +// case MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN: +// { +// if (cmd->param1 == 1.0f) { +// if (0 == update_state_machine_custom_mode_request(status_pub, current_vehicle_status, SYSTEM_STATE_HALT)) { +// result = MAV_RESULT_ACCEPTED;//TODO: this has no effect +// } +// } +// +// } +// break; +// +// /* request to land */ +// case MAV_CMD_NAV_LAND: +// { +// //TODO: add check if landing possible +// //TODO: add landing maneuver +// +// if (0 == update_state_machine_custom_mode_request(status_pub, current_vehicle_status, SYSTEM_STATE_ARMED)) { +// result = MAV_RESULT_ACCEPTED; +// } } +// break; +// +// /* request to takeoff */ +// case MAV_CMD_NAV_TAKEOFF: +// { +// //TODO: add check if takeoff possible +// //TODO: add takeoff maneuver +// +// if (0 == update_state_machine_custom_mode_request(status_pub, current_vehicle_status, SYSTEM_STATE_AUTO)) { +// result = MAV_RESULT_ACCEPTED; +// } +// } +// break; +// + /* preflight calibration */ + case MAV_CMD_PREFLIGHT_CALIBRATION: { + if (cmd->param1 == 1.0) { + mavlink_log_info(mavlink_fd, "[commander] starting gyro calibration"); + do_gyro_calibration(); + result = MAV_RESULT_ACCEPTED; + + } else { + fprintf(stderr, "[commander] refusing unsupported calibration request\n"); + mavlink_log_critical(mavlink_fd, "[commander] refusing unsupported calibration request"); + result = MAV_RESULT_UNSUPPORTED; + } + } + break; + + /* preflight parameter load / store */ + case MAV_CMD_PREFLIGHT_STORAGE: { + /* Read all parameters from EEPROM to RAM */ + + if (cmd->param1 == 0.0) { + + if (OK == get_params_from_eeprom(global_data_parameter_storage)) { + printf("[commander] Loaded EEPROM params in RAM\n"); + mavlink_log_info(mavlink_fd, "[commander] Loaded EEPROM params in RAM"); + result = MAV_RESULT_ACCEPTED; + + } else { + fprintf(stderr, "[commander] ERROR loading EEPROM params in RAM\n"); + mavlink_log_critical(mavlink_fd, "[commander] ERROR loading EEPROM params in RAM"); + result = MAV_RESULT_FAILED; + } + + /* Write all parameters from RAM to EEPROM */ + + } else if (cmd->param1 == 1.0) { + + if (OK == store_params_in_eeprom(global_data_parameter_storage)) { + printf("[commander] RAM params written to EEPROM\n"); + mavlink_log_info(mavlink_fd, "[commander] RAM params written to EEPROM"); + result = MAV_RESULT_ACCEPTED; + + } else { + fprintf(stderr, "[commander] ERROR writing RAM params to EEPROM\n"); + mavlink_log_critical(mavlink_fd, "[commander] ERROR writing RAM params to EEPROM"); + result = MAV_RESULT_FAILED; + } + + } else { + fprintf(stderr, "[commander] refusing unsupported storage request\n"); + mavlink_log_critical(mavlink_fd, "[commander] refusing unsupported storage request"); + result = MAV_RESULT_UNSUPPORTED; + } + } + break; + + default: { + mavlink_log_critical(mavlink_fd, "[commander] refusing unsupported command"); + result = MAV_RESULT_UNSUPPORTED; + } + break; + } + + /* supported command handling stop */ + + + /* send any requested ACKs */ + if (cmd->confirmation > 0) { + /* send acknowledge command */ + mavlink_message_t msg; + mavlink_msg_command_ack_pack(0, 0, &msg, cmd->command, result); + //global_data_send_mavlink_message_out(&msg); + + } + +} + + +static void *command_handling_loop(void *arg) //handles commands which come from the mavlink app +{ + /* Set thread name */ + prctl(PR_SET_NAME, "commander cmd handler", getpid()); + + /* Subscribe to command topic */ + int cmd_sub = orb_subscribe(ORB_ID(vehicle_command)); + struct vehicle_command_s cmd; + + while (1) { + struct pollfd fds[1] = { { .fd = cmd_sub, .events = POLLIN } }; + + if (poll(fds, 1, 5000) == 0) { + /* timeout, but this is no problem */ + } else { + /* got command */ + orb_copy(ORB_ID(vehicle_command), cmd_sub, &cmd); + + /* handle it */ + handle_command(stat_pub, ¤t_status, &cmd); + } + } + + return NULL; +} + +// static void *subsystem_info_loop(void *arg) //handles status information coming from subsystems (present, enabled, health), these values do not indicate the quality (variance) of the signal +// { +// /* Set thread name */ +// prctl(PR_SET_NAME, "commander subsys", getpid()); + +// uint8_t current_info_local = SUBSYSTEM_INFO_BUFFER_SIZE; +// uint16_t total_counter = 0; + +// while (1) { + +// if (0 == global_data_wait(&global_data_subsystem_info->access_conf)) { +// // printf("got subsystem_info\n"); + +// while (current_info_local != global_data_subsystem_info->current_info) { +// // printf("current_info_local = %d, current_info = %d \n", current_info_local, global_data_subsystem_info->current_info); + +// current_info_local++; + +// if (current_info_local >= SUBSYSTEM_INFO_BUFFER_SIZE) +// current_info_local = 0; + +// /* Handle the new subsystem info and write updated version of global_data_sys_status */ +// subsystem_info_t *info = &(global_data_subsystem_info->info[current_info_local]); + +// // printf("Commander got subsystem info: %d %d %d\n", info->present, info->enabled, info->health); + + +// if (info->present != 0) { +// update_state_machine_subsystem_present(stat_pub, ¤t_status, &info->subsystem_type); + +// } else { +// update_state_machine_subsystem_notpresent(stat_pub, ¤t_status, &info->subsystem_type); +// } + +// if (info->enabled != 0) { +// update_state_machine_subsystem_enabled(stat_pub, ¤t_status, &info->subsystem_type); + +// } else { +// update_state_machine_subsystem_disabled(stat_pub, ¤t_status, &info->subsystem_type); +// } + +// if (info->health != 0) { +// update_state_machine_subsystem_healthy(stat_pub, ¤t_status, &info->subsystem_type); + +// } else { +// update_state_machine_subsystem_unhealthy(stat_pub, ¤t_status, &info->subsystem_type); +// } + +// total_counter++; +// } + +// if (global_data_subsystem_info->counter - total_counter > SUBSYSTEM_INFO_BUFFER_SIZE) { +// printf("[commander] Warning: Too many subsystem status updates, subsystem_info buffer full\n"); //TODO: add to error queue +// global_data_subsystem_info->counter = total_counter; //this makes sure we print the warning only once +// } + +// global_data_unlock(&global_data_subsystem_info->access_conf); +// } +// } + +// return NULL; +// } + + + +enum BAT_CHEM { + BAT_CHEM_LITHIUM_POLYMERE = 0, +}; + +/* + * Provides a coarse estimate of remaining battery power. + * + * The estimate is very basic and based on decharging voltage curves. + * + * @return the estimated remaining capacity in 0..1 + */ +float battery_remaining_estimate_voltage(int cells, int chemistry, float voltage) +{ + float ret = 0; + // XXX do this properly + // XXX rebase on parameters + const float chemistry_voltage_empty[] = {3.2f}; + const float chemistry_voltage_full[] = {4.05f}; + + ret = (voltage - cells * chemistry_voltage_empty[chemistry]) / (cells * (chemistry_voltage_full[chemistry] - chemistry_voltage_empty[chemistry])); + + /* limit to sane values */ + ret = (ret < 0) ? 0 : ret; + ret = (ret > 1) ? 1 : ret; + return ret; +} + +/**************************************************************************** + * Name: commander + ****************************************************************************/ + +int commander_main(int argc, char *argv[]) +{ + /* not yet initialized */ + commander_initialized = false; + + /* welcome user */ + printf("[commander] I am in command now!\n"); + + /* Pthreads */ + pthread_t command_handling_thread; + // pthread_t subsystem_info_thread; + + /* initialize */ + if (led_init() != 0) { + fprintf(stderr, "[commander] ERROR: Failed to initialize leds\n"); + } + + if (buzzer_init() != 0) { + fprintf(stderr, "[commander] ERROR: Failed to initialize buzzer\n"); + } + + mavlink_fd = open(MAVLINK_LOG_DEVICE, 0); + + if (mavlink_fd < 0) { + fprintf(stderr, "[commander] ERROR: Failed to open MAVLink log stream, start mavlink app first.\n"); + } + + /* advertise to ORB */ + stat_pub = orb_advertise(ORB_ID(vehicle_status), ¤t_status); + + if (stat_pub < 0) { + printf("[commander] ERROR: orb_advertise failed.\n"); + } + + /* make sure we are in preflight state */ + //do_state_update(stat_pub, ¤t_status, (commander_state_machine_t)SYSTEM_STATE_PREFLIGHT); + + mavlink_log_info(mavlink_fd, "[commander] system is running"); + + /* load EEPROM parameters */ + if (OK == get_params_from_eeprom(global_data_parameter_storage)) { + printf("[commander] Loaded EEPROM params in RAM\n"); + mavlink_log_info(mavlink_fd, "[commander] Loaded EEPROM params in RAM"); + + } else { + fprintf(stderr, "[commander] ERROR loading EEPROM params in RAM\n"); + mavlink_log_critical(mavlink_fd, "[commander] ERROR loading EEPROM params in RAM"); + } + + /* create pthreads */ + pthread_attr_t command_handling_attr; + pthread_attr_init(&command_handling_attr); + pthread_attr_setstacksize(&command_handling_attr, 3072); + pthread_create(&command_handling_thread, &command_handling_attr, command_handling_loop, NULL); + + // pthread_attr_t subsystem_info_attr; + // pthread_attr_init(&subsystem_info_attr); + // pthread_attr_setstacksize(&subsystem_info_attr, 2048); + // pthread_create(&subsystem_info_thread, &subsystem_info_attr, subsystem_info_loop, NULL); + + /* Start monitoring loop */ + uint16_t counter = 0; + uint8_t flight_env; + // uint8_t fix_type; + /* Initialize to 3.0V to make sure the low-pass loads below valid threshold */ + float battery_voltage = VOLTAGE_BATTERY_HIGH_VOLTS; + bool battery_voltage_valid = true; + bool low_battery_voltage_actions_done = false; + bool critical_battery_voltage_actions_done = false; + uint8_t low_voltage_counter = 0; + uint16_t critical_voltage_counter = 0; + int16_t mode_switch_rc_value; + float bat_remain = 1.0f; + +// bool arm_done = false; +// bool disarm_done = false; + + uint16_t stick_off_counter = 0; + uint16_t stick_on_counter = 0; + + float hdop = 65535.0f; + + int gps_quality_good_counter = 0; + + /* Subscribe to RC data */ + int rc_sub = orb_subscribe(ORB_ID(rc_channels)); + struct rc_channels_s rc = {0}; + + int gps_sub = orb_subscribe(ORB_ID(vehicle_gps_position)); + struct vehicle_gps_position_s gps = {0}; + + int sensor_sub = orb_subscribe(ORB_ID(sensor_combined)); + struct sensor_combined_s sensors = {0}; + + uint8_t vehicle_state_previous = current_status.state_machine; + + uint64_t last_idle_time = 0; + + /* now initialized */ + commander_initialized = true; + + while (1) { //TODO: this while loop needs cleanup, split into sub-functions + + /* Get current values */ + orb_copy(ORB_ID(rc_channels), rc_sub, &rc); + orb_copy(ORB_ID(vehicle_gps_position), gps_sub, &gps); + orb_copy(ORB_ID(sensor_combined), sensor_sub, &sensors); + + battery_voltage = sensors.battery_voltage_v; + battery_voltage_valid = sensors.battery_voltage_valid; + bat_remain = battery_remaining_estimate_voltage(3, BAT_CHEM_LITHIUM_POLYMERE, battery_voltage); + + flight_env = (uint8_t)(global_data_parameter_storage->pm.param_values[PARAM_FLIGHT_ENV]); + + /* Slow but important 5 Hz checks */ + if (counter % ((1000000 / COMMANDER_MONITORING_INTERVAL) / 8) == 0) { + /* toggle activity (blue) led at 1 Hz in standby, 10 Hz in armed mode */ + if ((current_status.state_machine == SYSTEM_STATE_GROUND_READY || current_status.state_machine == SYSTEM_STATE_AUTO || current_status.state_machine == SYSTEM_STATE_MANUAL)) { + /* armed */ + led_toggle(LED_BLUE); + + } else if (counter % (1000000 / COMMANDER_MONITORING_INTERVAL) == 0) { + /* not armed */ + led_toggle(LED_BLUE); + } + + /* toggle error led at 5 Hz in HIL mode */ + if ((current_status.mode & MAV_MODE_FLAG_HIL_ENABLED)) { + /* armed */ + led_toggle(LED_AMBER); + + } else if (bat_remain < 0.3f && (low_voltage_counter > LOW_VOLTAGE_BATTERY_COUNTER_LIMIT)) { + /* toggle error (red) at 5 Hz on low battery or error */ + led_toggle(LED_AMBER); + + } else { + /* Constant error indication in standby mode without GPS */ + if (flight_env == PX4_FLIGHT_ENVIRONMENT_OUTDOOR && !current_status.gps_valid) { + led_on(LED_AMBER); + + } else { + led_off(LED_AMBER); + } + } + + if (counter % (1000000 / COMMANDER_MONITORING_INTERVAL) == 0) { + //compute system load + uint64_t interval_runtime = system_load.tasks[0].total_runtime - last_idle_time; + + if (last_idle_time > 0) + current_status.load = 1000 - (interval_runtime / 1000); //system load is time spent in non-idle + + last_idle_time = system_load.tasks[0].total_runtime; + } + } + + // // XXX Export patterns and threshold to parameters + /* Trigger audio event for low battery */ + if (bat_remain < 0.1f && battery_voltage_valid && (counter % ((1000000 / COMMANDER_MONITORING_INTERVAL) / 4) == 0)) { + /* For less than 10%, start be really annoying at 5 Hz */ + ioctl(buzzer, TONE_SET_ALARM, 0); + ioctl(buzzer, TONE_SET_ALARM, 3); + + } else if (bat_remain < 0.1f && battery_voltage_valid && (counter % ((1000000 / COMMANDER_MONITORING_INTERVAL) / 4) == 2)) { + ioctl(buzzer, TONE_SET_ALARM, 0); + + } else if (bat_remain < 0.2f && battery_voltage_valid && (counter % ((1000000 / COMMANDER_MONITORING_INTERVAL) / 2) == 0)) { + /* For less than 20%, start be slightly annoying at 1 Hz */ + ioctl(buzzer, TONE_SET_ALARM, 0); + ioctl(buzzer, TONE_SET_ALARM, 2); + + } else if (bat_remain < 0.2f && battery_voltage_valid && (counter % ((1000000 / COMMANDER_MONITORING_INTERVAL) / 2) == 2)) { + ioctl(buzzer, TONE_SET_ALARM, 0); + } + + /* Check if last transition deserved an audio event */ +#warning This code depends on state that is no longer? maintained +#if 0 + trigger_audio_alarm(vehicle_mode_previous, vehicle_state_previous, current_status.mode, current_status.state_machine); +#endif + + /* only check gps fix if we are outdoor */ +// if (flight_env == PX4_FLIGHT_ENVIRONMENT_OUTDOOR) { +// +// hdop = (float)(gps.eph) / 100.0f; +// +// /* check if gps fix is ok */ +// if (gps.fix_type == GPS_FIX_TYPE_3D) { //TODO: is 2d-fix ok? //see http://en.wikipedia.org/wiki/Dilution_of_precision_%28GPS%29 +// +// if (gotfix_counter >= GPS_GOTFIX_COUNTER_REQUIRED) { //TODO: add also a required time? +// update_state_machine_got_position_fix(stat_pub, ¤t_status); +// gotfix_counter = 0; +// } else { +// gotfix_counter++; +// } +// nofix_counter = 0; +// +// if (hdop < 5.0f) { //TODO: this should be a parameter +// if (gps_quality_good_counter > GPS_QUALITY_GOOD_COUNTER_LIMIT) { +// current_status.gps_valid = true;//--> position estimator can use the gps measurements +// } +// +// gps_quality_good_counter++; +// +// +//// if(counter%10 == 0)//for testing only +//// printf("gps_quality_good_counter = %u\n", gps_quality_good_counter);//for testing only +// +// } else { +// gps_quality_good_counter = 0; +// current_status.gps_valid = false;//--> position estimator can not use the gps measurements +// } +// +// } else { +// gps_quality_good_counter = 0; +// current_status.gps_valid = false;//--> position estimator can not use the gps measurements +// +// if (nofix_counter > GPS_NOFIX_COUNTER_LIMIT) { //TODO: add also a timer limit? +// update_state_machine_no_position_fix(stat_pub, ¤t_status); +// nofix_counter = 0; +// } else { +// nofix_counter++; +// } +// gotfix_counter = 0; +// } +// +// } +// +// +// if (flight_env == PX4_FLIGHT_ENVIRONMENT_TESTING) //simulate position fix for quick indoor tests + update_state_machine_got_position_fix(stat_pub, ¤t_status); + /* end: check gps */ + + /* Check battery voltage */ + /* write to sys_status */ + current_status.voltage_battery = battery_voltage; + orb_publish(ORB_ID(vehicle_status), stat_pub, ¤t_status); + + /* if battery voltage is getting lower, warn using buzzer, etc. */ + if (battery_voltage_valid && (battery_voltage < VOLTAGE_BATTERY_LOW_VOLTS && false == low_battery_voltage_actions_done)) { //TODO: add filter, or call emergency after n measurements < VOLTAGE_BATTERY_MINIMAL_MILLIVOLTS + + if (low_voltage_counter > LOW_VOLTAGE_BATTERY_COUNTER_LIMIT) { + low_battery_voltage_actions_done = true; + mavlink_log_critical(mavlink_fd, "[commander] WARNING! LOW BATTERY!"); + } + + low_voltage_counter++; + } + + /* Critical, this is rather an emergency, kill signal to sdlog and change state machine */ + else if (battery_voltage_valid && (battery_voltage < VOLTAGE_BATTERY_CRITICAL_VOLTS && false == critical_battery_voltage_actions_done && true == low_battery_voltage_actions_done)) { + if (critical_voltage_counter > CRITICAL_VOLTAGE_BATTERY_COUNTER_LIMIT) { + critical_battery_voltage_actions_done = true; + mavlink_log_critical(mavlink_fd, "[commander] EMERGENCY! CIRITICAL BATTERY!"); + state_machine_emergency(stat_pub, ¤t_status); + } + + critical_voltage_counter++; + + } else { + low_voltage_counter = 0; + critical_voltage_counter = 0; + } + + /* End battery voltage check */ + + /* Start RC state check */ + + int16_t chan3_scale = rc.chan[rc.function[YAW]].scale; + int16_t chan2_scale = rc.chan[rc.function[THROTTLE]].scale; + + /* check if left stick is in lower left position --> switch to standby state */ + if (chan3_scale > STICK_ON_OFF_LIMIT && chan2_scale < -STICK_ON_OFF_LIMIT) { //TODO: remove hardcoded values + if (stick_off_counter > STICK_ON_OFF_COUNTER_LIMIT) { + update_state_machine_disarm(stat_pub, ¤t_status); + stick_on_counter = 0; + + } else { + stick_off_counter++; + stick_on_counter = 0; + } + } + + /* check if left stick is in lower right position --> arm */ + if (chan3_scale < -STICK_ON_OFF_LIMIT && chan2_scale < -STICK_ON_OFF_LIMIT) { //TODO: remove hardcoded values + if (stick_on_counter > STICK_ON_OFF_COUNTER_LIMIT) { + update_state_machine_arm(stat_pub, ¤t_status); + stick_on_counter = 0; + + } else { + stick_on_counter++; + stick_off_counter = 0; + } + } + + /* Check the value of the rc channel of the mode switch */ + mode_switch_rc_value = rc.chan[rc.function[OVERRIDE]].scale; + + if (mode_switch_rc_value > STICK_ON_OFF_LIMIT) { + update_state_machine_mode_manual(stat_pub, ¤t_status); + + } else if (mode_switch_rc_value < -STICK_ON_OFF_LIMIT) { + update_state_machine_mode_auto(stat_pub, ¤t_status); + + } else { + update_state_machine_mode_stabilized(stat_pub, ¤t_status); + } + + /* End mode switch */ + + /* END RC state check */ + + + current_status.counter++; + current_status.timestamp = hrt_absolute_time(); + orb_publish(ORB_ID(vehicle_status), stat_pub, ¤t_status); + + + + /* Store old modes to detect and act on state transitions */ + vehicle_state_previous = current_status.state_machine; + + fflush(stdout); + counter++; + usleep(COMMANDER_MONITORING_INTERVAL); + } + + /* wait for threads to complete */ + pthread_join(command_handling_thread, NULL); + // pthread_join(subsystem_info_thread, NULL); + + /* close fds */ + led_deinit(); + buzzer_deinit(); + + return 0; +} + diff --git a/apps/commander/commander.h b/apps/commander/commander.h new file mode 100644 index 0000000000..d537a0602c --- /dev/null +++ b/apps/commander/commander.h @@ -0,0 +1,48 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: Thomas Gubler + * Julian Oes + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* @file Main system state machine definition */ + +#ifndef COMMANDER_H_ +#define COMMANDER_H_ + +#define VOLTAGE_BATTERY_HIGH_VOLTS 12.0f +#define VOLTAGE_BATTERY_LOW_VOLTS 10.5f +#define VOLTAGE_BATTERY_CRITICAL_VOLTS 10.0f +#define LOW_VOLTAGE_BATTERY_HYSTERESIS_TIME_MS 1000.0f +#define CRITICAL_VOLTAGE_BATTERY_HYSTERESIS_TIME_MS 100.0f + +#endif /* COMMANDER_H_ */ diff --git a/apps/commander/state_machine_helper.c b/apps/commander/state_machine_helper.c new file mode 100644 index 0000000000..2171ccedfd --- /dev/null +++ b/apps/commander/state_machine_helper.c @@ -0,0 +1,564 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: Thomas Gubler + * Julian Oes + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* @file State machine helper functions implementations */ + +#include +#include "state_machine_helper.h" + +#include +#include +#include +#include + +static const char* system_state_txt[] = { + "SYSTEM_STATE_PREFLIGHT", + "SYSTEM_STATE_STANDBY", + "SYSTEM_STATE_GROUND_READY", + "SYSTEM_STATE_MANUAL", + "SYSTEM_STATE_STABILIZED", + "SYSTEM_STATE_AUTO", + "SYSTEM_STATE_MISSION_ABORT", + "SYSTEM_STATE_EMCY_LANDING", + "SYSTEM_STATE_EMCY_CUTOFF", + "SYSTEM_STATE_GROUND_ERROR", + "SYSTEM_STATE_REBOOT", + +}; + + +void do_state_update(int status_pub, struct vehicle_status_s *current_status, commander_state_machine_t new_state) +{ + int invalid_state = false; + + switch (new_state) { + case SYSTEM_STATE_MISSION_ABORT: { + /* Indoor or outdoor */ + uint8_t flight_environment_parameter = (uint8_t)(global_data_parameter_storage->pm.param_values[PARAM_FLIGHT_ENV]); + + if (flight_environment_parameter == PX4_FLIGHT_ENVIRONMENT_OUTDOOR) { + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_EMCY_LANDING); + + } else { + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_EMCY_CUTOFF); + } + + return; + } + break; + + case SYSTEM_STATE_EMCY_LANDING: + /* Tell the controller to land */ + //TODO: add emcy landing code here + + fprintf(stderr, "[commander] EMERGENCY LANDING!\n"); + //global_data_send_mavlink_statustext_message_out("Commander: state: emergency landing", MAV_SEVERITY_INFO); + break; + + case SYSTEM_STATE_EMCY_CUTOFF: + /* Tell the controller to cutoff the motors (thrust = 0), make sure that this is not overwritten by another app and stays at 0 */ + //TODO: add emcy cutoff code here + + fprintf(stderr, "[commander] EMERGENCY MOTOR CUTOFF!\n"); + //global_data_send_mavlink_statustext_message_out("Commander: state: emergency cutoff", MAV_SEVERITY_INFO); + break; + + case SYSTEM_STATE_GROUND_ERROR: + fprintf(stderr, "[commander] GROUND ERROR, locking down propulsion system\n"); + //global_data_send_mavlink_statustext_message_out("Commander: state: ground error", MAV_SEVERITY_INFO); + break; + + case SYSTEM_STATE_PREFLIGHT: + //global_data_send_mavlink_statustext_message_out("Commander: state: preflight", MAV_SEVERITY_INFO); + break; + + case SYSTEM_STATE_REBOOT: + usleep(500000); + reboot(); + break; + + case SYSTEM_STATE_STANDBY: + //global_data_send_mavlink_statustext_message_out("Commander: state: standby", MAV_SEVERITY_INFO); + break; + + case SYSTEM_STATE_GROUND_READY: + //global_data_send_mavlink_statustext_message_out("Commander: state: armed", MAV_SEVERITY_INFO); + + //if in manual mode switch to manual state +// if (current_status->remote_manual) { +// printf("[commander] manual mode\n"); +// do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_MANUAL); +// return; +// } + + break; + + case SYSTEM_STATE_AUTO: + //global_data_send_mavlink_statustext_message_out("Commander: state: auto", MAV_SEVERITY_INFO); + break; + + case SYSTEM_STATE_STABILIZED: + //global_data_send_mavlink_statustext_message_out("Commander: state: stabilized", MAV_SEVERITY_INFO); + break; + + case SYSTEM_STATE_MANUAL: + //global_data_send_mavlink_statustext_message_out("Commander: state: manual", MAV_SEVERITY_INFO); + break; + + default: + invalid_state = true; + break; + } + + if (invalid_state == false) { + //publish the new state + current_status->state_machine = new_state; + current_status->counter++; + current_status->timestamp = hrt_absolute_time(); + orb_publish(ORB_ID(vehicle_status), status_pub, current_status); + printf("[commander] new state: %s\n", system_state_txt[new_state]); + } +} + + +/* + * Private functions, update the state machine + */ +void state_machine_emergency_always_critical(int status_pub, struct vehicle_status_s *current_status) +{ + fprintf(stderr, "[commander] EMERGENCY HANDLER\n"); + /* Depending on the current state go to one of the error states */ + + if (current_status->state_machine == SYSTEM_STATE_PREFLIGHT || current_status->state_machine == SYSTEM_STATE_STANDBY || current_status->state_machine == SYSTEM_STATE_GROUND_READY) { + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_GROUND_ERROR); + + } else if (current_status->state_machine == SYSTEM_STATE_AUTO || current_status->state_machine == SYSTEM_STATE_MANUAL) { + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_MISSION_ABORT); + + } else { + fprintf(stderr, "[commander] Unknown system state: #%d\n", current_status->state_machine); + } +} + +void state_machine_emergency(int status_pub, struct vehicle_status_s *current_status) //do not call state_machine_emergency_always_critical if we are in manual mode for these errors +{ + if (current_status->state_machine != SYSTEM_STATE_MANUAL) { //if we are in manual: user can react to errors themself + state_machine_emergency_always_critical(status_pub, current_status); + + } else { + //global_data_send_mavlink_statustext_message_out("[commander] ERROR: take action immediately! (did not switch to error state because the system is in manual mode)", MAV_SEVERITY_CRITICAL); + } + +} + + + +// /* +// * Wrapper functions (to be used in the commander), all functions assume lock on current_status +// */ + +// /* These functions decide if an emergency exits and then switch to SYSTEM_STATE_MISSION_ABORT or SYSTEM_STATE_GROUND_ERROR +// * +// * START SUBSYSTEM/EMERGENCY FUNCTIONS +// * */ + +// void update_state_machine_subsystem_present(int status_pub, struct vehicle_status_s *current_status, subsystem_type_t *subsystem_type) +// { +// current_status->onboard_control_sensors_present |= 1 << *subsystem_type; +// current_status->counter++; +// current_status->timestamp = hrt_absolute_time(); +// orb_publish(ORB_ID(vehicle_status), status_pub, current_status); +// } + +// void update_state_machine_subsystem_notpresent(int status_pub, struct vehicle_status_s *current_status, subsystem_type_t *subsystem_type) +// { +// current_status->onboard_control_sensors_present &= ~(1 << *subsystem_type); +// current_status->counter++; +// current_status->timestamp = hrt_absolute_time(); +// orb_publish(ORB_ID(vehicle_status), status_pub, current_status); + +// /* if a subsystem was removed something went completely wrong */ + +// switch (*subsystem_type) { +// case SUBSYSTEM_TYPE_GYRO: +// //global_data_send_mavlink_statustext_message_out("Commander: gyro not present", MAV_SEVERITY_EMERGENCY); +// state_machine_emergency_always_critical(status_pub, current_status); +// break; + +// case SUBSYSTEM_TYPE_ACC: +// //global_data_send_mavlink_statustext_message_out("Commander: accelerometer not present", MAV_SEVERITY_EMERGENCY); +// state_machine_emergency_always_critical(status_pub, current_status); +// break; + +// case SUBSYSTEM_TYPE_MAG: +// //global_data_send_mavlink_statustext_message_out("Commander: magnetometer not present", MAV_SEVERITY_EMERGENCY); +// state_machine_emergency_always_critical(status_pub, current_status); +// break; + +// case SUBSYSTEM_TYPE_GPS: +// { +// uint8_t flight_env = global_data_parameter_storage->pm.param_values[PARAM_FLIGHT_ENV]; + +// if (flight_env == PX4_FLIGHT_ENVIRONMENT_OUTDOOR) { +// //global_data_send_mavlink_statustext_message_out("Commander: GPS not present", MAV_SEVERITY_EMERGENCY); +// state_machine_emergency(status_pub, current_status); +// } +// } +// break; + +// default: +// break; +// } + +// } + +// void update_state_machine_subsystem_enabled(int status_pub, struct vehicle_status_s *current_status, subsystem_type_t *subsystem_type) +// { +// current_status->onboard_control_sensors_enabled |= 1 << *subsystem_type; +// current_status->counter++; +// current_status->timestamp = hrt_absolute_time(); +// orb_publish(ORB_ID(vehicle_status), status_pub, current_status); +// } + +// void update_state_machine_subsystem_disabled(int status_pub, struct vehicle_status_s *current_status, subsystem_type_t *subsystem_type) +// { +// current_status->onboard_control_sensors_enabled &= ~(1 << *subsystem_type); +// current_status->counter++; +// current_status->timestamp = hrt_absolute_time(); +// orb_publish(ORB_ID(vehicle_status), status_pub, current_status); + +// /* if a subsystem was disabled something went completely wrong */ + +// switch (*subsystem_type) { +// case SUBSYSTEM_TYPE_GYRO: +// //global_data_send_mavlink_statustext_message_out("Commander: EMERGENCY - gyro disabled", MAV_SEVERITY_EMERGENCY); +// state_machine_emergency_always_critical(status_pub, current_status); +// break; + +// case SUBSYSTEM_TYPE_ACC: +// //global_data_send_mavlink_statustext_message_out("Commander: EMERGENCY - accelerometer disabled", MAV_SEVERITY_EMERGENCY); +// state_machine_emergency_always_critical(status_pub, current_status); +// break; + +// case SUBSYSTEM_TYPE_MAG: +// //global_data_send_mavlink_statustext_message_out("Commander: EMERGENCY - magnetometer disabled", MAV_SEVERITY_EMERGENCY); +// state_machine_emergency_always_critical(status_pub, current_status); +// break; + +// case SUBSYSTEM_TYPE_GPS: +// { +// uint8_t flight_env = (uint8_t)(global_data_parameter_storage->pm.param_values[PARAM_FLIGHT_ENV]); + +// if (flight_env == PX4_FLIGHT_ENVIRONMENT_OUTDOOR) { +// //global_data_send_mavlink_statustext_message_out("Commander: EMERGENCY - GPS disabled", MAV_SEVERITY_EMERGENCY); +// state_machine_emergency(status_pub, current_status); +// } +// } +// break; + +// default: +// break; +// } + +// } + + +// void update_state_machine_subsystem_healthy(int status_pub, struct vehicle_status_s *current_status, subsystem_type_t *subsystem_type) +// { +// current_status->onboard_control_sensors_health |= 1 << *subsystem_type; +// current_status->counter++; +// current_status->timestamp = hrt_absolute_time(); +// orb_publish(ORB_ID(vehicle_status), status_pub, current_status); + +// switch (*subsystem_type) { +// case SUBSYSTEM_TYPE_GYRO: +// //TODO state machine change (recovering) +// break; + +// case SUBSYSTEM_TYPE_ACC: +// //TODO state machine change +// break; + +// case SUBSYSTEM_TYPE_MAG: +// //TODO state machine change +// break; + +// case SUBSYSTEM_TYPE_GPS: +// //TODO state machine change +// break; + +// default: +// break; +// } + + +// } + + +// void update_state_machine_subsystem_unhealthy(int status_pub, struct vehicle_status_s *current_status, subsystem_type_t *subsystem_type) +// { +// bool previosly_healthy = (bool)(current_status->onboard_control_sensors_health & 1 << *subsystem_type); +// current_status->onboard_control_sensors_health &= ~(1 << *subsystem_type); +// current_status->counter++; +// current_status->timestamp = hrt_absolute_time(); +// orb_publish(ORB_ID(vehicle_status), status_pub, current_status); + +// /* if we received unhealthy message more than *_HEALTH_COUNTER_LIMIT, switch to error state */ + +// switch (*subsystem_type) { +// case SUBSYSTEM_TYPE_GYRO: +// //global_data_send_mavlink_statustext_message_out("Commander: gyro unhealthy", MAV_SEVERITY_CRITICAL); + +// if (previosly_healthy) //only throw emergency if previously healthy +// state_machine_emergency_always_critical(status_pub, current_status); + +// break; + +// case SUBSYSTEM_TYPE_ACC: +// //global_data_send_mavlink_statustext_message_out("Commander: accelerometer unhealthy", MAV_SEVERITY_CRITICAL); + +// if (previosly_healthy) //only throw emergency if previously healthy +// state_machine_emergency_always_critical(status_pub, current_status); + +// break; + +// case SUBSYSTEM_TYPE_MAG: +// //global_data_send_mavlink_statustext_message_out("Commander: magnetometer unhealthy", MAV_SEVERITY_CRITICAL); + +// if (previosly_healthy) //only throw emergency if previously healthy +// state_machine_emergency_always_critical(status_pub, current_status); + +// break; + +// case SUBSYSTEM_TYPE_GPS: +// // //TODO: remove this block +// // break; +// // /////////////////// +// //global_data_send_mavlink_statustext_message_out("Commander: GPS unhealthy", MAV_SEVERITY_CRITICAL); + +// // printf("previosly_healthy = %u\n", previosly_healthy); +// if (previosly_healthy) //only throw emergency if previously healthy +// state_machine_emergency(status_pub, current_status); + +// break; + +// default: +// break; +// } + +// } + + +/* END SUBSYSTEM/EMERGENCY FUNCTIONS*/ + + +void update_state_machine_got_position_fix(int status_pub, struct vehicle_status_s *current_status) +{ + /* Depending on the current state switch state */ + if (current_status->state_machine == SYSTEM_STATE_PREFLIGHT) { + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_STANDBY); + } +} + +void update_state_machine_no_position_fix(int status_pub, struct vehicle_status_s *current_status) +{ + /* Depending on the current state switch state */ + if (current_status->state_machine == SYSTEM_STATE_STANDBY || current_status->state_machine == SYSTEM_STATE_GROUND_READY || current_status->state_machine == SYSTEM_STATE_AUTO) { + state_machine_emergency(status_pub, current_status); + } +} + +void update_state_machine_arm(int status_pub, struct vehicle_status_s *current_status) +{ + if (current_status->state_machine == SYSTEM_STATE_STANDBY) { + printf("[commander] arming\n"); + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_GROUND_READY); + } /*else if (current_status->state_machine == SYSTEM_STATE_AUTO) { + + printf("[commander] landing\n"); + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_GROUND_READY); + }*/ +} + +void update_state_machine_disarm(int status_pub, struct vehicle_status_s *current_status) +{ + if (current_status->state_machine == SYSTEM_STATE_GROUND_READY || current_status->state_machine == SYSTEM_STATE_MANUAL || current_status->state_machine == SYSTEM_STATE_PREFLIGHT) { + printf("[commander] going standby\n"); + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_STANDBY); + + } else if (current_status->state_machine == SYSTEM_STATE_STABILIZED || current_status->state_machine == SYSTEM_STATE_AUTO) { + printf("[commander] MISSION ABORT!\n"); + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_STANDBY); + } +} + +void update_state_machine_mode_manual(int status_pub, struct vehicle_status_s *current_status) +{ + if (current_status->state_machine == SYSTEM_STATE_GROUND_READY || current_status->state_machine == SYSTEM_STATE_STABILIZED || current_status->state_machine == SYSTEM_STATE_AUTO) { + printf("[commander] manual mode\n"); + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_MANUAL); + } +} + +void update_state_machine_mode_stabilized(int status_pub, struct vehicle_status_s *current_status) +{ + if (current_status->state_machine == SYSTEM_STATE_GROUND_READY || current_status->state_machine == SYSTEM_STATE_MANUAL || current_status->state_machine == SYSTEM_STATE_AUTO) { + printf("[commander] stabilized mode\n"); + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_STABILIZED); + } +} + +void update_state_machine_mode_auto(int status_pub, struct vehicle_status_s *current_status) +{ + if (current_status->state_machine == SYSTEM_STATE_GROUND_READY || current_status->state_machine == SYSTEM_STATE_MANUAL || current_status->state_machine == SYSTEM_STATE_STABILIZED) { + printf("[commander] auto mode\n"); + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_AUTO); + } +} + + +uint8_t update_state_machine_mode_request(int status_pub, struct vehicle_status_s *current_status, uint8_t mode) +{ + commander_state_machine_t current_system_state = current_status->state_machine; + + printf("in update state request\n"); + uint8_t ret = 1; + + /* Switch on HIL if in standby */ + if ((current_system_state == SYSTEM_STATE_STANDBY) && (mode & MAV_MODE_FLAG_HIL_ENABLED)) { + /* Enable HIL on request */ + current_status->mode |= MAV_MODE_FLAG_HIL_ENABLED; + } + + /* NEVER actually switch off HIL without reboot */ + if ((current_status->mode & MAV_MODE_FLAG_HIL_ENABLED) && !(mode & MAV_MODE_FLAG_HIL_ENABLED)) { + fprintf(stderr, "[commander] DENYING request to switch of HIL. Please power cycle (safety reasons)\n"); + ret = ERROR; + } + + //TODO: clarify mapping between mavlink enum MAV_MODE and the state machine, then add more decisions to the switch (see also the system_state_loop function in mavlink.c) + switch (mode) { + case MAV_MODE_MANUAL_ARMED: //= SYSTEM_STATE_ARMED + if (current_system_state == SYSTEM_STATE_STANDBY) { + /* Set armed flag */ + current_status->mode |= MAV_MODE_FLAG_SAFETY_ARMED; + /* Set manual input enabled flag */ + current_status->mode |= MAV_MODE_FLAG_MANUAL_INPUT_ENABLED; + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_GROUND_READY); + ret = OK; + } + + break; + + case MAV_MODE_MANUAL_DISARMED: + if (current_system_state == SYSTEM_STATE_GROUND_READY) { + /* Clear armed flag, leave manual input enabled */ + current_status->mode &= ~MAV_MODE_FLAG_SAFETY_ARMED; + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_STANDBY); + ret = OK; + } + + break; + + default: + break; + } + + #warning STATE MACHINE IS INCOMPLETE HERE + +// if(ret != 0) //Debug +// { +// strcpy(mavlink_statustext_msg_content.values[0].string_value, "Commander: command rejected"); +// global_data_send_mavlink_message_out(&mavlink_statustext_msg_content); +// } + + return ret; +} + +uint8_t update_state_machine_custom_mode_request(int status_pub, struct vehicle_status_s *current_status, uint8_t custom_mode) //TODO: add more checks to avoid state switching in critical situations +{ + commander_state_machine_t current_system_state = current_status->state_machine; + + uint8_t ret = 1; + + switch (custom_mode) { + case SYSTEM_STATE_GROUND_READY: + break; + + case SYSTEM_STATE_STANDBY: + break; + + case SYSTEM_STATE_REBOOT: + printf("try to reboot\n"); + + if (current_system_state == SYSTEM_STATE_STANDBY || current_system_state == SYSTEM_STATE_PREFLIGHT) { + printf("system will reboot\n"); + //global_data_send_mavlink_statustext_message_out("Rebooting autopilot.. ", MAV_SEVERITY_INFO); + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_REBOOT); + ret = 0; + } + + break; + + case SYSTEM_STATE_AUTO: + printf("try to switch to auto/takeoff\n"); + + if (current_system_state == SYSTEM_STATE_GROUND_READY || current_system_state == SYSTEM_STATE_MANUAL) { + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_AUTO); + printf("state: auto\n"); + ret = 0; + } + + break; + + case SYSTEM_STATE_MANUAL: + printf("try to switch to manual\n"); + + if (current_system_state == SYSTEM_STATE_GROUND_READY || current_system_state == SYSTEM_STATE_AUTO) { + do_state_update(status_pub, current_status, (commander_state_machine_t)SYSTEM_STATE_MANUAL); + printf("state: manual\n"); + ret = 0; + } + + break; + + default: + break; + } + + return ret; +} + diff --git a/apps/commander/state_machine_helper.h b/apps/commander/state_machine_helper.h new file mode 100644 index 0000000000..0abc6349c7 --- /dev/null +++ b/apps/commander/state_machine_helper.h @@ -0,0 +1,133 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: Thomas Gubler + * Julian Oes + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* @file State machine helper functions definitions */ + +#ifndef STATE_MACHINE_HELPER_H_ +#define STATE_MACHINE_HELPER_H_ + +#define GPS_NOFIX_COUNTER_LIMIT 4 //need GPS_NOFIX_COUNTER_LIMIT gps packets with a bad fix to call an error (if outdoor) +#define GPS_GOTFIX_COUNTER_REQUIRED 4 //need GPS_GOTFIX_COUNTER_REQUIRED gps packets with a good fix to obtain position lock + +#include +#include +#include + + +/* + * @brief switch to new state with no checking * + * + * do_state_update: this is the functions that all other functions have to call in order to update the state. + * the function does not question the state change, this must be done before + * The function performs actions that are connected with the new state (buzzer, reboot, ...) + * + * + */ +void do_state_update(int status_pub, struct vehicle_status_s *current_status, commander_state_machine_t new_state); + +/* These functions decide if an emergency exits and then switch to SYSTEM_STATE_MISSION_ABORT or SYSTEM_STATE_GROUND_ERROR */ +// void update_state_machine_subsystem_present(int status_pub, struct vehicle_status_s *current_status, subsystem_type_t *subsystem_type); +// void update_state_machine_subsystem_notpresent(int status_pub, struct vehicle_status_s *current_status, subsystem_type_t *subsystem_type); + +// void update_state_machine_subsystem_enabled(int status_pub, struct vehicle_status_s *current_status, subsystem_type_t *subsystem_type); +// void update_state_machine_subsystem_disabled(int status_pub, struct vehicle_status_s *current_status, subsystem_type_t *subsystem_type); + +// void update_state_machine_subsystem_healthy(int status_pub, struct vehicle_status_s *current_status, subsystem_type_t *subsystem_type); +// void update_state_machine_subsystem_unhealthy(int status_pub, struct vehicle_status_s *current_status, subsystem_type_t *subsystem_type); + + +/* + * @brief handle state machine if got position fix + */ +void update_state_machine_got_position_fix(int status_pub, struct vehicle_status_s *current_status); + +/* + * @brief handle state machine if position fix lost + */ +void update_state_machine_no_position_fix(int status_pub, struct vehicle_status_s *current_status); + +/* + * @brief handle state machine if user wants to arm + */ +void update_state_machine_arm(int status_pub, struct vehicle_status_s *current_status); + +/* + * @brief handle state machine if user wants to disarm + */ +void update_state_machine_disarm(int status_pub, struct vehicle_status_s *current_status); + +/* + * @brief handle state machine if mode switch is manual + */ +void update_state_machine_mode_manual(int status_pub, struct vehicle_status_s *current_status); + +/* + * @brief handle state machine if mode switch is stabilized + */ +void update_state_machine_mode_stabilized(int status_pub, struct vehicle_status_s *current_status); + +/* + * @brief handle state machine if mode switch is auto + */ +void update_state_machine_mode_auto(int status_pub, struct vehicle_status_s *current_status); + + + + +/* + * Functions that handle incoming requests to change the state machine or a parameter (probably from the mavlink app). + * If the request is obeyed the functions return 0 + * + */ + +/* + * @brief handles *incoming request* to switch to a specific state, if state change is successful returns 0 + */ +uint8_t update_state_machine_mode_request(int status_pub, struct vehicle_status_s *current_status, uint8_t mode); + +/* + * @brief handles *incoming request* to switch to a specific custom state, if state change is successful returns 0 + */ +uint8_t update_state_machine_custom_mode_request(int status_pub, struct vehicle_status_s *current_status, uint8_t custom_mode); + + +void state_machine_emergency_always_critical(int status_pub, struct vehicle_status_s *current_status); +void state_machine_emergency(int status_pub, struct vehicle_status_s *current_status); + + + + +#endif /* STATE_MACHINE_HELPER_H_ */ diff --git a/apps/doxygen_mainpage.dox b/apps/doxygen_mainpage.dox new file mode 100644 index 0000000000..98b0eb6903 --- /dev/null +++ b/apps/doxygen_mainpage.dox @@ -0,0 +1,49 @@ +/** @mainpage PX4 Codebase Overview + +PX4 is an open-source, open-hardware project aiming at providing a high-end autopilot to the academic, hobby and industrial communities (BSD licensed). For full documentation, refer to the official project website: + +https://pixhawk.ethz.ch/px4/ + +Please follow the toolchain installation instructions at https://pixhawk.ethz.ch/px4/dev/px4_quickstart. + +*/ + +/** +@defgroup topics uORB Topics + +Small and efficient object request broker. + +The micro object request broker (uORB) is a very efficient implementation of an object +request broker following the publisher/subscriber design pattern. + +It is in detail described here: +https://pixhawk.ethz.ch/px4/dev/shared_object_communication +*/ + +/** +@defgroup apps Onboard Applications + +This is the list of the main functions of all onboard applications. The use of these +applications is documented here: +https://pixhawk.ethz.ch/px4/users/apps/start + +Developer documentation of individual applications and the uORB data sharing mechanisms +are described here: +https://pixhawk.ethz.ch/px4/dev/apps/start + +*/ + +/** +@defgroup attitude_estimation Attitude Estimation + +*/ + +/** +@defgroup position_estimation Position Estimation + +*/ + +/** + * @addtogroup topics + * @{ + */ \ No newline at end of file diff --git a/apps/drivers/bma180/Makefile b/apps/drivers/bma180/Makefile new file mode 100644 index 0000000000..cc01b629e6 --- /dev/null +++ b/apps/drivers/bma180/Makefile @@ -0,0 +1,42 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Makefile to build the BMA180 driver. +# + +APPNAME = bma180 +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +include $(APPDIR)/mk/app.mk diff --git a/apps/drivers/bma180/bma180.cpp b/apps/drivers/bma180/bma180.cpp new file mode 100644 index 0000000000..a5d66d86b3 --- /dev/null +++ b/apps/drivers/bma180/bma180.cpp @@ -0,0 +1,774 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Driver for the Bosch BMA 180 MEMS accelerometer connected via SPI. + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +extern "C" { __EXPORT int bma180_main(int argc, char *argv[]); } + +class BMA180 : public device::SPI +{ +public: + BMA180(int bus, spi_dev_e device); + ~BMA180(); + + virtual int init(); + + virtual ssize_t read(struct file *filp, char *buffer, size_t buflen); + virtual int ioctl(struct file *filp, int cmd, unsigned long arg); + + virtual int open_first(struct file *filp); + virtual int close_last(struct file *filp); + + /** + * Diagnostics - print some basic information about the driver. + */ + void print_info(); + +protected: + virtual int probe(); + +private: + + struct hrt_call _call; + unsigned _call_interval; + + unsigned _num_reports; + volatile unsigned _next_report; + volatile unsigned _oldest_report; + struct accel_report *_reports; + + struct accel_scale _scale; + float _range_scale; + + unsigned _reads; + + /** + * Start automatic measurement. + */ + void start(); + + /** + * Stop automatic measurement. + */ + void stop(); + + /** + * Static trampoline from the hrt_call context; because we don't have a + * generic hrt wrapper yet. + * + * Called by the HRT in interrupt context at the specified rate if + * automatic polling is enabled. + * + * @param arg Instance pointer for the driver that is polling. + */ + static void measure_trampoline(void *arg); + + /** + * Fetch measurements from the sensor and update the report ring. + */ + void measure(); + + /** + * Read a register from the BMA180 + * + * @param The register to read. + * @return The value that was read. + */ + uint8_t read_reg(unsigned reg); + + /** + * Write a register in the BMA180 + * + * @param reg The register to write. + * @param value The new value to write. + */ + void write_reg(unsigned reg, uint8_t value); + + /** + * Modify a register in the BMA180 + * + * Bits are cleared before bits are set. + * + * @param reg The register to modify. + * @param clearbits Bits in the register to clear. + * @param setbits Bits in the register to set. + */ + void modify_reg(unsigned reg, uint8_t clearbits, uint8_t setbits); + + /** + * Set the BMA180 measurement range. + * + * @param max_g The maximum G value the range must support. + * @return OK if the value can be supported, -ERANGE otherwise. + */ + int set_range(unsigned max_g); + + /** + * Set the BMA180 lowpass filter. + * + * @param frequency Set the lowpass filter cutoff frequency to no less than + * this frequency. + * @return OK if the value can be supported. + */ + int set_bandwidth(unsigned frequency); +}; + +/* helper macro for handling report buffer indices */ +#define INCREMENT(_x, _lim) do { _x++; if (_x >= _lim) _x = 0; } while(0) + +#define DIR_READ (1<<7) +#define DIR_WRITE (0<<7) + +#define ADDR_CHIP_ID 0x00 +#define CHIP_ID 0x03 + +#define ADDR_ACC_X_LSB 0x02 +#define ADDR_ACC_Y_LSB 0x04 +#define ADDR_ACC_Z_LSB 0x06 +#define ADDR_TEMPERATURE 0x08 + +#define ADDR_RESET 0x10 +#define SOFT_RESET 0xB6 + +#define ADDR_BW_TCS 0x20 +#define BW_TCS_BW_MASK (0xf<<4) +#define BW_TCS_BW_10HZ (0<<4) +#define BW_TCS_BW_20HZ (1<<4) +#define BW_TCS_BW_40HZ (2<<4) +#define BW_TCS_BW_75HZ (3<<4) +#define BW_TCS_BW_150HZ (4<<4) +#define BW_TCS_BW_300HZ (5<<4) +#define BW_TCS_BW_600HZ (6<<4) +#define BW_TCS_BW_1200HZ (7<<4) + +#define ADDR_HIGH_DUR 0x27 +#define HIGH_DUR_DIS_I2C (1<<0) + +#define ADDR_TCO_Z 0x30 +#define TCO_Z_MODE_MASK 0x3 + +#define ADDR_GAIN_Y 0x33 +#define GAIN_Y_SHADOW_DIS (1<<0) + +#define ADDR_OFFSET_LSB1 0x35 +#define OFFSET_LSB1_RANGE_MASK (7<<1) +#define OFFSET_LSB1_RANGE_1G (0<<1) +#define OFFSET_LSB1_RANGE_2G (2<<1) +#define OFFSET_LSB1_RANGE_3G (3<<1) +#define OFFSET_LSB1_RANGE_4G (4<<1) +#define OFFSET_LSB1_RANGE_8G (5<<1) +#define OFFSET_LSB1_RANGE_16G (6<<1) + +#define ADDR_OFFSET_T 0x37 +#define OFFSET_T_READOUT_12BIT (1<<0) + +/* + * Driver 'main' command. + */ +extern "C" { int bma180_main(int argc, char *argv[]); } + + +BMA180::BMA180(int bus, spi_dev_e device) : + SPI("BMA180", ACCEL_DEVICE_PATH, bus, device, SPIDEV_MODE3, 8000000), + _num_reports(0), + _next_report(0), + _oldest_report(0), + _reports(nullptr), + _reads(0) +{ + // enable debug() calls + _debug_enabled = true; + + // default scale factors + _scale.x_offset = 0; + _scale.x_scale = 1.0f; + _scale.y_offset = 0; + _scale.y_scale = 1.0f; + _scale.z_offset = 0; + _scale.z_scale = 1.0f; +} + +BMA180::~BMA180() +{ + /* make sure we are truly inactive */ + stop(); + + /* free any existing reports */ + if (_reports != nullptr) + delete[] _reports; +} + +int +BMA180::init() +{ + int ret; + + /* do SPI init (and probe) first */ + ret = SPI::init(); + + /* if probe/setup successful, finish chip init */ + if (ret == OK) { + + /* perform soft reset (p48) */ + write_reg(ADDR_RESET, SOFT_RESET); + + /* wait 10us (p49) */ + usleep(10); + + /* disable I2C interface */ + modify_reg(ADDR_HIGH_DUR, HIGH_DUR_DIS_I2C, 0); + + /* switch to low-noise mode */ + modify_reg(ADDR_TCO_Z, TCO_Z_MODE_MASK, 0); + + /* disable 12-bit mode */ + modify_reg(ADDR_OFFSET_T, OFFSET_T_READOUT_12BIT, 0); + + /* disable shadow-disable mode */ + modify_reg(ADDR_GAIN_Y, GAIN_Y_SHADOW_DIS, 0); + } + + return ret; +} + +int +BMA180::open_first(struct file *filp) +{ + /* reset to manual-poll mode */ + _call_interval = 0; + + /* allocate basic report buffers */ + _num_reports = 2; + _reports = new struct accel_report[_num_reports]; + _oldest_report = _next_report = 0; + + /* set default range and lowpass */ + set_range(4); /* 4G */ + set_bandwidth(600); /* 600Hz */ + + return OK; +} + +int +BMA180::close_last(struct file *filp) +{ + /* stop measurement */ + stop(); + + /* free report buffers */ + if (_reports != nullptr) { + delete[] _reports; + _num_reports = 0; + } + + return OK; +} + +int +BMA180::probe() +{ + if (read_reg(ADDR_CHIP_ID) == CHIP_ID) + return OK; + + return -EIO; +} + +ssize_t +BMA180::read(struct file *filp, char *buffer, size_t buflen) +{ + unsigned count = buflen / sizeof(struct accel_report); + int ret = 0; + + /* buffer must be large enough */ + if (count < 1) + return -ENOSPC; + + /* if automatic measurement is enabled */ + if (_call_interval > 0) { + + /* + * While there is space in the caller's buffer, and reports, copy them. + * Note that we may be pre-empted by the measurement code while we are doing this; + * we are careful to avoid racing with it. + */ + while (count--) { + if (_oldest_report != _next_report) { + memcpy(buffer, _reports + _oldest_report, sizeof(*_reports)); + ret += sizeof(_reports[0]); + INCREMENT(_oldest_report, _num_reports); + } + } + + _reads++; + + /* if there was no data, warn the caller */ + return ret ? ret : -EAGAIN; + } + + /* manual measurement */ + _oldest_report = _next_report = 0; + measure(); + + /* measurement will have generated a report, copy it out */ + memcpy(buffer, _reports, sizeof(*_reports)); + ret = sizeof(*_reports); + + return ret; +} + +int +BMA180::ioctl(struct file *filp, int cmd, unsigned long arg) +{ + switch (cmd) { + + case ACCELIOCSPOLLRATE: { + switch (arg) { + + /* switching to manual polling */ + case ACC_POLLRATE_MANUAL: + stop(); + _call_interval = 0; + return OK; + + /* external signalling not supported */ + case ACC_POLLRATE_EXTERNAL: + + /* zero would be bad */ + case 0: + return -EINVAL; + + /* adjust to a legal polling interval in Hz */ + default: { + /* do we need to start internal polling? */ + bool want_start = (_call_interval == 0); + + /* convert hz to hrt interval via microseconds */ + unsigned ticks = 1000000 / arg; + + /* check against maximum sane rate */ + if (ticks < 1000) + return -EINVAL; + + /* update interval for next measurement */ + /* XXX this is a bit shady, but no other way to adjust... */ + _call.period = _call_interval; + + /* if we need to start the poll state machine, do it */ + if (want_start) + start(); + + return OK; + } + } + } + + case ACCELIOCSQUEUEDEPTH: { + /* lower bound is mandatory, upper bound is a sanity check */ + if ((arg < 2) || (arg > 100)) + return -EINVAL; + + /* allocate new buffer */ + struct accel_report *buf = new struct accel_report[arg]; + + if (nullptr == buf) + return -ENOMEM; + + /* reset the measurement state machine with the new buffer, free the old */ + stop(); + delete[] _reports; + _num_reports = arg; + _reports = buf; + start(); + + return OK; + } + + case ACCELIOCSLOWPASS: + return set_bandwidth(arg); + + case ACCELIORANGE: + return set_range(arg); + + case ACCELIOCSSAMPLERATE: /* sensor sample rate is not (really) adjustable */ + case ACCELIOCSREPORTFORMAT: /* no alternate report formats */ + return -EINVAL; + + default: + /* give it to the superclass */ + return SPI::ioctl(filp, cmd, arg); + } +} + +uint8_t +BMA180::read_reg(unsigned reg) +{ + uint8_t cmd[2]; + + cmd[0] = reg | DIR_READ; + + transfer(cmd, cmd, sizeof(cmd)); + + return cmd[1]; +} + +void +BMA180::write_reg(unsigned reg, uint8_t value) +{ + uint8_t cmd[2]; + + cmd[0] = reg | DIR_WRITE; + cmd[1] = value; + + transfer(cmd, nullptr, sizeof(cmd)); +} + +void +BMA180::modify_reg(unsigned reg, uint8_t clearbits, uint8_t setbits) +{ + uint8_t val; + + val = read_reg(reg); + val &= ~clearbits; + val |= setbits; + write_reg(reg, val); +} + +int +BMA180::set_range(unsigned max_g) +{ + uint8_t rangebits; + float rangescale; + + if (max_g > 16) { + return -ERANGE; + + } else if (max_g > 8) { /* 16G */ + rangebits = OFFSET_LSB1_RANGE_16G; + rangescale = 1.98; + + } else if (max_g > 4) { /* 8G */ + rangebits = OFFSET_LSB1_RANGE_8G; + rangescale = 0.99; + + } else if (max_g > 3) { /* 4G */ + rangebits = OFFSET_LSB1_RANGE_4G; + rangescale = 0.5; + + } else if (max_g > 2) { /* 3G */ + rangebits = OFFSET_LSB1_RANGE_3G; + rangescale = 0.38; + + } else if (max_g > 1) { /* 2G */ + rangebits = OFFSET_LSB1_RANGE_2G; + rangescale = 0.25; + + } else { /* 1G */ + rangebits = OFFSET_LSB1_RANGE_1G; + rangescale = 0.13; + } + + /* adjust sensor configuration */ + modify_reg(ADDR_OFFSET_LSB1, OFFSET_LSB1_RANGE_MASK, rangebits); + _range_scale = rangescale; + + return OK; +} + +int +BMA180::set_bandwidth(unsigned frequency) +{ + uint8_t bwbits; + + if (frequency > 1200) { + return -ERANGE; + + } else if (frequency > 600) { + bwbits = BW_TCS_BW_1200HZ; + + } else if (frequency > 300) { + bwbits = BW_TCS_BW_600HZ; + + } else if (frequency > 150) { + bwbits = BW_TCS_BW_300HZ; + + } else if (frequency > 75) { + bwbits = BW_TCS_BW_150HZ; + + } else if (frequency > 40) { + bwbits = BW_TCS_BW_75HZ; + + } else if (frequency > 20) { + bwbits = BW_TCS_BW_40HZ; + + } else if (frequency > 10) { + bwbits = BW_TCS_BW_20HZ; + + } else { + bwbits = BW_TCS_BW_10HZ; + } + + /* adjust sensor configuration */ + modify_reg(ADDR_BW_TCS, BW_TCS_BW_MASK, bwbits); + + return OK; +} + +void +BMA180::start() +{ + /* make sure we are stopped first */ + stop(); + + /* reset the report ring */ + _oldest_report = _next_report = 0; + + /* start polling at the specified rate */ + hrt_call_every(&_call, 1000, _call_interval, (hrt_callout)&BMA180::measure_trampoline, this); +} + +void +BMA180::stop() +{ + hrt_cancel(&_call); +} + +void +BMA180::measure_trampoline(void *arg) +{ + BMA180 *dev = (BMA180 *)arg; + + /* make another measurement */ + dev->measure(); +} + +void +BMA180::measure() +{ + /* + * This evil is to deal with the stupid layout of the BMA180 + * measurement registers vs. the SPI transaction model. + */ + union { + uint8_t bytes[10]; + uint16_t words[5]; + } buf; + + /* + * Fetch the full set of measurements from the BMA180 in one pass; + * 7 bytes starting from the X LSB. + */ + buf.bytes[1] = ADDR_ACC_X_LSB; + transfer(&buf.bytes[1], &buf.bytes[1], 8); + + /* + * Adjust and scale results to mg. + * + * Note that we ignore the "new data" bits. At any time we read, each + * of the axis measurements are the "most recent", even if we've seen + * them before. There is no good way to synchronise with the internal + * measurement flow without using the external interrupt. + */ + _reports[_next_report].timestamp = hrt_absolute_time(); + _reports[_next_report].x = (buf.words[1] >> 2) * _range_scale; + _reports[_next_report].y = (buf.words[2] >> 2) * _range_scale; + _reports[_next_report].z = (buf.words[3] >> 2) * _range_scale; + + /* + * @todo Apply additional scaling / calibration factors here. + */ + + /* post a report to the ring - note, not locked */ + INCREMENT(_next_report, _num_reports); + + /* if we are running up against the oldest report, fix it */ + if (_next_report == _oldest_report) + INCREMENT(_oldest_report, _num_reports); + + /* notify anyone waiting for data */ + poll_notify(POLLIN); +} + +void +BMA180::print_info() +{ + printf("reads: %u\n", _reads); + printf("report queue: %u (%u/%u @ %p)\n", + _num_reports, _oldest_report, _next_report, _reports); +} + +/** + * Local functions in support of the shell command. + */ +namespace +{ + +BMA180 *g_dev; + +/* + * XXX this should just be part of the generic sensors test... + */ + +int +test() +{ + int fd = -1; + struct accel_report report; + ssize_t sz; + const char *reason = "test OK"; + + do { + + /* get the driver */ + fd = open(ACCEL_DEVICE_PATH, O_RDONLY); + + if (fd < 0) { + reason = "can't open driver"; + break; + } + + /* do a simple demand read */ + sz = read(fd, &report, sizeof(report)); + + if (sz != sizeof(report)) { + reason = "immediate read failed"; + break; + } + + printf("single read\n"); + fflush(stdout); + printf("time: %lld\n", report.timestamp); + printf("x: %f\n", report.x); + printf("y: %f\n", report.y); + printf("z: %f\n", report.z); + + } while (0); + + printf("BMA180: %s\n", reason); + + return OK; +} + +int +info() +{ + if (g_dev == nullptr) { + fprintf(stderr, "BMA180: driver not running\n"); + return -ENOENT; + } + + printf("state @ %p\n", g_dev); + g_dev->print_info(); + + return OK; +} + + +} // namespace + +int +bma180_main(int argc, char *argv[]) +{ + /* + * Start/load the driver. + * + * XXX it would be nice to have a wrapper for this... + */ + if (!strcmp(argv[1], "start")) { + + if (g_dev != nullptr) { + fprintf(stderr, "BMA180: already loaded\n"); + return -EBUSY; + } + + /* create the driver */ + g_dev = new BMA180(CONFIG_BMA180_SPI_BUS, (spi_dev_e)CONFIG_BMA180_SPI_DEVICE); + + if (g_dev == nullptr) { + fprintf(stderr, "BMA180: driver alloc failed\n"); + return -ENOMEM; + } + + if (OK != g_dev->init()) { + fprintf(stderr, "BMA180: driver init failed\n"); + usleep(100000); + delete g_dev; + g_dev = nullptr; + return -EIO; + } + + printf("BMA180: driver started\n"); + return OK; + } + + /* + * Test the driver/device. + */ + if (!strcmp(argv[1], "test")) + return test(); + + /* + * Print driver information. + */ + if (!strcmp(argv[1], "info")) + return info(); + + fprintf(stderr, "unrecognised command, try 'start', 'test' or 'info'\n"); + return -EINVAL; +} diff --git a/apps/drivers/device/Makefile b/apps/drivers/device/Makefile new file mode 100644 index 0000000000..f7b1fff888 --- /dev/null +++ b/apps/drivers/device/Makefile @@ -0,0 +1,38 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Build the device driver framework. +# + +include $(APPDIR)/mk/app.mk diff --git a/apps/drivers/device/cdev.cpp b/apps/drivers/device/cdev.cpp new file mode 100644 index 0000000000..6b8bf0c2d4 --- /dev/null +++ b/apps/drivers/device/cdev.cpp @@ -0,0 +1,396 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Character device base class. + */ + +#include "device.h" + +#include +#include + +#include +#include + +#ifdef CONFIG_DISABLE_POLL +# error This driver is not compatible with CONFIG_DISABLE_POLL +#endif + +namespace device +{ + +/* how much to grow the poll waiter set each time it has to be increased */ +static const unsigned pollset_increment = 0; + +/* + * The standard NuttX operation dispatch table can't call C++ member functions + * directly, so we have to bounce them through this dispatch table. + */ +static int cdev_open(struct file *filp); +static int cdev_close(struct file *filp); +static ssize_t cdev_read(struct file *filp, char *buffer, size_t buflen); +static ssize_t cdev_write(struct file *filp, const char *buffer, size_t buflen); +static off_t cdev_seek(struct file *filp, off_t offset, int whence); +static int cdev_ioctl(struct file *filp, int cmd, unsigned long arg); +static int cdev_poll(struct file *filp, struct pollfd *fds, bool setup); + +/** + * Character device indirection table. + * + * Every cdev we register gets the same function table; we use the private data + * field in the inode to store the instance pointer. + * + * Note that we use the GNU extension syntax here because we don't get designated + * initialisers in gcc 4.6. + */ +static const struct file_operations cdev_fops = { +open : cdev_open, +close : cdev_close, +read : cdev_read, +write : cdev_write, +seek : cdev_seek, +ioctl : cdev_ioctl, +poll : cdev_poll, +}; + +CDev::CDev(const char *name, + const char *devname, + int irq) : + // base class + Device(name, irq), + // public + // protected + // private + _devname(devname), + _registered(false), + _open_count(0) +{ + for (unsigned i = 0; i < _max_pollwaiters; i++) + _pollset[i] = nullptr; +} + +CDev::~CDev() +{ + if (_registered) + unregister_driver(_devname); +} + +int +CDev::init() +{ + int ret = OK; + + // base class init first + ret = Device::init(); + + if (ret != OK) + goto out; + + // now register the driver + ret = register_driver(_devname, &cdev_fops, 0666, (void *)this); + + if (ret != OK) + goto out; + + _registered = true; + +out: + return ret; +} + +/* + * Default implementations of the character device interface + */ +int +CDev::open(struct file *filp) +{ + int ret = OK; + + lock(); + /* increment the open count */ + _open_count++; + + if (_open_count == 1) { + + /* first-open callback may decline the open */ + ret = open_first(filp); + + if (ret != OK) + _open_count--; + } + + unlock(); + + return ret; +} + +int +CDev::open_first(struct file *filp) +{ + return OK; +} + +int +CDev::close(struct file *filp) +{ + int ret = OK; + + lock(); + + if (_open_count > 0) { + /* decrement the open count */ + _open_count--; + + /* callback cannot decline the close */ + if (_open_count == 0) + ret = close_last(filp); + + } else { + ret = -EBADF; + } + + unlock(); + + return ret; +} + +int +CDev::close_last(struct file *filp) +{ + return OK; +} + +ssize_t +CDev::read(struct file *filp, char *buffer, size_t buflen) +{ + return -ENOSYS; +} + +ssize_t +CDev::write(struct file *filp, const char *buffer, size_t buflen) +{ + return -ENOSYS; +} + +off_t +CDev::seek(struct file *filp, off_t offset, int whence) +{ + return -ENOSYS; +} + +int +CDev::ioctl(struct file *filp, int cmd, unsigned long arg) +{ + switch (cmd) { + + /* fetch a pointer to the driver's private data */ + case DIOC_GETPRIV: + *(void **)(uintptr_t)arg = (void *)this; + return OK; + } + + return -ENOTTY; +} + +int +CDev::poll(struct file *filp, struct pollfd *fds, bool setup) +{ + int ret = OK; + + /* + * Lock against pollnotify() (and possibly other callers) + */ + lock(); + + if (setup) { + /* + * Save the file pointer in the pollfd for the subclass' + * benefit. + */ + fds->priv = (void *)filp; + + /* + * Handle setup requests. + */ + ret = store_poll_waiter(fds); + + if (ret == OK) { + + /* + * Check to see whether we should send a poll notification + * immediately. + */ + fds->revents |= fds->events & poll_state(filp); + + /* yes? post the notification */ + if (fds->revents != 0) + sem_post(fds->sem); + } + + } else { + /* + * Handle a teardown request. + */ + ret = remove_poll_waiter(fds); + } + + unlock(); + + return ret; +} + +void +CDev::poll_notify(pollevent_t events) +{ + /* lock against poll() as well as other wakeups */ + irqstate_t state = irqsave(); + + for (unsigned i = 0; i < _max_pollwaiters; i++) + if (nullptr != _pollset[i]) + poll_notify_one(_pollset[i], events); + + irqrestore(state); +} + +void +CDev::poll_notify_one(struct pollfd *fds, pollevent_t events) +{ + /* update the reported event set */ + fds->revents |= fds->events & events; + + /* if the state is now interesting, wake the waiter if it's still asleep */ + /* XXX semcount check here is a vile hack; counting semphores should not be abused as cvars */ + if ((fds->revents != 0) && (fds->sem->semcount <= 0)) + sem_post(fds->sem); +} + +pollevent_t +CDev::poll_state(struct file *filp) +{ + /* by default, no poll events to report */ + return 0; +} + +int +CDev::store_poll_waiter(struct pollfd *fds) +{ + /* + * Look for a free slot. + */ + for (unsigned i = 0; i < _max_pollwaiters; i++) { + if (nullptr == _pollset[i]) { + + /* save the pollfd */ + _pollset[i] = fds; + + return OK; + } + } + + return ENOMEM; +} + +int +CDev::remove_poll_waiter(struct pollfd *fds) +{ + for (unsigned i = 0; i < _max_pollwaiters; i++) { + if (fds == _pollset[i]) { + + _pollset[i] = nullptr; + return OK; + + } + } + + puts("poll: bad fd state"); + return -EINVAL; +} + +static int +cdev_open(struct file *filp) +{ + CDev *cdev = (CDev *)(filp->f_inode->i_private); + + return cdev->open(filp); +} + +static int +cdev_close(struct file *filp) +{ + CDev *cdev = (CDev *)(filp->f_inode->i_private); + + return cdev->close(filp); +} + +static ssize_t +cdev_read(struct file *filp, char *buffer, size_t buflen) +{ + CDev *cdev = (CDev *)(filp->f_inode->i_private); + + return cdev->read(filp, buffer, buflen); +} + +static ssize_t +cdev_write(struct file *filp, const char *buffer, size_t buflen) +{ + CDev *cdev = (CDev *)(filp->f_inode->i_private); + + return cdev->write(filp, buffer, buflen); +} + +static off_t +cdev_seek(struct file *filp, off_t offset, int whence) +{ + CDev *cdev = (CDev *)(filp->f_inode->i_private); + + return cdev->seek(filp, offset, whence); +} + +static int +cdev_ioctl(struct file *filp, int cmd, unsigned long arg) +{ + CDev *cdev = (CDev *)(filp->f_inode->i_private); + + return cdev->ioctl(filp, cmd, arg); +} + +static int +cdev_poll(struct file *filp, struct pollfd *fds, bool setup) +{ + CDev *cdev = (CDev *)(filp->f_inode->i_private); + + return cdev->poll(filp, fds, setup); +} + +} // namespace device \ No newline at end of file diff --git a/apps/drivers/device/device.cpp b/apps/drivers/device/device.cpp new file mode 100644 index 0000000000..c14a3234da --- /dev/null +++ b/apps/drivers/device/device.cpp @@ -0,0 +1,225 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Fundamental driver base class for the device framework. + */ + +#include "device.h" + +#include +#include +#include + +namespace device +{ + +/** + * Interrupt dispatch table entry. + */ +struct irq_entry { + int irq; + Device *owner; +}; + +static const unsigned irq_nentries = 8; /**< size of the interrupt dispatch table */ +static irq_entry irq_entries[irq_nentries]; /**< interrupt dispatch table (XXX should be a vector) */ + +/** + * Register an interrupt to a specific device. + * + * @param irq The interrupt number to register. + * @param owner The device receiving the interrupt. + * @return OK if the interrupt was registered. + */ +static int register_interrupt(int irq, Device *owner); + +/** + * Unregister an interrupt. + * + * @param irq The previously-registered interrupt to be de-registered. + */ +static void unregister_interrupt(int irq); + +/** + * Handle an interrupt. + * + * @param irq The interrupt being invoked. + * @param context The interrupt register context. + * @return Always returns OK. + */ +static int interrupt(int irq, void *context); + +Device::Device(const char *name, + int irq) : + // public + // protected + _name(name), + _debug_enabled(false), + // private + _irq(irq), + _irq_attached(false) +{ + sem_init(&_lock, 0, 1); +} + +Device::~Device() +{ + sem_destroy(&_lock); + + if (_irq_attached) + unregister_interrupt(_irq); +} + +int +Device::init() +{ + int ret = OK; + + // If assigned an interrupt, connect it + if (_irq) { + /* ensure it's disabled */ + up_disable_irq(_irq); + + /* register */ + ret = register_interrupt(_irq, this); + + if (ret != OK) + goto out; + + _irq_attached = true; + } + +out: + return ret; +} + +void +Device::interrupt_enable() +{ + if (_irq_attached) + up_enable_irq(_irq); +} + +void +Device::interrupt_disable() +{ + if (_irq_attached) + up_disable_irq(_irq); +} + +void +Device::interrupt(void *context) +{ + // default action is to disable the interrupt so we don't get called again + interrupt_disable(); +} + +void +Device::log(const char *fmt, ...) +{ + va_list ap; + + printf("[%s] ", _name); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); + fflush(stdout); +} + +void +Device::debug(const char *fmt, ...) +{ + va_list ap; + + if (_debug_enabled) { + printf("<%s> ", _name); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); + fflush(stdout); + } +} + +static int +register_interrupt(int irq, Device *owner) +{ + int ret = -ENOMEM; + + // look for a slot where we can register the interrupt + for (unsigned i = 0; i < irq_nentries; i++) { + if (irq_entries[i].irq == 0) { + + // great, we could put it here; try attaching it + ret = irq_attach(irq, &interrupt); + + if (ret == OK) { + irq_entries[i].irq = irq; + irq_entries[i].owner = owner; + } + + break; + } + } + + return ret; +} + +static void +unregister_interrupt(int irq) +{ + for (unsigned i = 0; i < irq_nentries; i++) { + if (irq_entries[i].irq == irq) { + irq_entries[i].irq = 0; + irq_entries[i].owner = nullptr; + } + } +} + +static int +interrupt(int irq, void *context) +{ + for (unsigned i = 0; i < irq_nentries; i++) { + if (irq_entries[i].irq == irq) { + irq_entries[i].owner->interrupt(context); + break; + } + } + + return OK; +} + + +} // namespace device \ No newline at end of file diff --git a/apps/drivers/device/device.h b/apps/drivers/device/device.h new file mode 100644 index 0000000000..98dbf8bfb9 --- /dev/null +++ b/apps/drivers/device/device.h @@ -0,0 +1,439 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Definitions for the generic base classes in the device framework. + */ + +#ifndef _DEVICE_DEVICE_H +#define _DEVICE_DEVICE_H + +/* + * Includes here should only cover the needs of the framework definitions. + */ +#include + +#include +#include +#include +#include +#include + +#include + +/** + * Namespace encapsulating all device framework classes, functions and data. + */ +namespace device __EXPORT +{ + +/** + * Fundamental base class for all device drivers. + * + * This class handles the basic "being a driver" things, including + * interrupt registration and dispatch. + */ +class __EXPORT Device +{ +public: + /** + * Interrupt handler. + */ + virtual void interrupt(void *ctx); /**< interrupt handler */ + +protected: + const char *_name; /**< driver name */ + bool _debug_enabled; /**< if true, debug messages are printed */ + + /** + * Constructor + * + * @param name Driver name + * @param irq Interrupt assigned to the device. + */ + Device(const char *name, + int irq = 0); + ~Device(); + + /** + * Initialise the driver and make it ready for use. + * + * @return OK if the driver initialised OK. + */ + virtual int init(); + + /** + * Enable the device interrupt + */ + void interrupt_enable(); + + /** + * Disable the device interrupt + */ + void interrupt_disable(); + + /** + * Take the driver lock. + * + * Each driver instance has its own lock/semaphore. + * + * Note that we must loop as the wait may be interrupted by a signal. + */ + void lock() { + do {} while (sem_wait(&_lock) != 0); + } + + /** + * Release the driver lock. + */ + void unlock() { + sem_post(&_lock); + } + + /** + * Log a message. + * + * The message is prefixed with the driver name, and followed + * by a newline. + */ + void log(const char *fmt, ...); + + /** + * Print a debug message. + * + * The message is prefixed with the driver name, and followed + * by a newline. + */ + void debug(const char *fmt, ...); + +private: + int _irq; + bool _irq_attached; + sem_t _lock; + + /** disable copy construction for this and all subclasses */ + Device(const Device &); + + /** disable assignment for this and all subclasses */ + Device &operator = (const Device &); + + /** + * Register ourselves as a handler for an interrupt + * + * @param irq The interrupt to claim + * @return OK if the interrupt was registered + */ + int dev_register_interrupt(int irq); + + /** + * Unregister ourselves as a handler for any interrupt + */ + void dev_unregister_interrupt(); + + /** + * Interrupt dispatcher + * + * @param irq The interrupt that has been triggered. + * @param context Pointer to the interrupted context. + */ + static void dev_interrupt(int irq, void *context); +}; + +/** + * Abstract class for any character device + */ +class __EXPORT CDev : public Device +{ +public: + /** + * Constructor + * + * @param name Driver name + * @param devname Device node name + * @param irq Interrupt assigned to the device + */ + CDev(const char *name, const char *devname, int irq = 0); + + /** + * Destructor + */ + ~CDev(); + + virtual int init(); + + /** + * Handle an open of the device. + * + * This function is called for every open of the device. The default + * implementation maintains _open_count and always returns OK. + * + * @param filp Pointer to the NuttX file structure. + * @return OK if the open is allowed, -errno otherwise. + */ + virtual int open(struct file *filp); + + /** + * Handle a close of the device. + * + * This function is called for every close of the device. The default + * implementation maintains _open_count and returns OK as long as it is not zero. + * + * @param filp Pointer to the NuttX file structure. + * @return OK if the close was successful, -errno otherwise. + */ + virtual int close(struct file *filp); + + /** + * Perform a read from the device. + * + * The default implementation returns -ENOSYS. + * + * @param filp Pointer to the NuttX file structure. + * @param buffer Pointer to the buffer into which data should be placed. + * @param buflen The number of bytes to be read. + * @return The number of bytes read or -errno otherwise. + */ + virtual ssize_t read(struct file *filp, char *buffer, size_t buflen); + + /** + * Perform a write to the device. + * + * The default implementation returns -ENOSYS. + * + * @param filp Pointer to the NuttX file structure. + * @param buffer Pointer to the buffer from which data should be read. + * @param buflen The number of bytes to be written. + * @return The number of bytes written or -errno otherwise. + */ + virtual ssize_t write(struct file *filp, const char *buffer, size_t buflen); + + /** + * Perform a logical seek operation on the device. + * + * The default implementation returns -ENOSYS. + * + * @param filp Pointer to the NuttX file structure. + * @param offset The new file position relative to whence. + * @param whence SEEK_OFS, SEEK_CUR or SEEK_END. + * @return The previous offset, or -errno otherwise. + */ + virtual off_t seek(struct file *filp, off_t offset, int whence); + + /** + * Perform an ioctl operation on the device. + * + * The default implementation handles DIOC_GETPRIV, and otherwise + * returns -ENOTTY. Subclasses should call the default implementation + * for any command they do not handle themselves. + * + * @param filp Pointer to the NuttX file structure. + * @param cmd The ioctl command value. + * @param arg The ioctl argument value. + * @return OK on success, or -errno otherwise. + */ + virtual int ioctl(struct file *filp, int cmd, unsigned long arg); + + /** + * Perform a poll setup/teardown operation. + * + * This is handled internally and should not normally be overridden. + * + * @param filp Pointer to the NuttX file structure. + * @param fds Poll descriptor being waited on. + * @param arg True if this is establishing a request, false if + * it is being torn down. + * @return OK on success, or -errno otherwise. + */ + virtual int poll(struct file *filp, struct pollfd *fds, bool setup); + + /** + * Test whether the device is currently open. + * + * This can be used to avoid tearing down a device that is still active. + * + * @return True if the device is currently open. + */ + bool is_open() { return _open_count > 0; } + +protected: + /** + * Check the current state of the device for poll events from the + * perspective of the file. + * + * This function is called by the default poll() implementation when + * a poll is set up to determine whether the poll should return immediately. + * + * The default implementation returns no events. + * + * @param filp The file that's interested. + * @return The current set of poll events. + */ + virtual pollevent_t poll_state(struct file *filp); + + /** + * Report new poll events. + * + * This function should be called anytime the state of the device changes + * in a fashion that might be interesting to a poll waiter. + * + * @param events The new event(s) being announced. + */ + virtual void poll_notify(pollevent_t events); + + /** + * Internal implementation of poll_notify. + * + * @param fds A poll waiter to notify. + * @param events The event(s) to send to the waiter. + */ + virtual void poll_notify_one(struct pollfd *fds, pollevent_t events); + + /** + * Notification of the first open. + * + * This function is called when the device open count transitions from zero + * to one. The driver lock is held for the duration of the call. + * + * The default implementation returns OK. + * + * @param filp Pointer to the NuttX file structure. + * @return OK if the open should proceed, -errno otherwise. + */ + virtual int open_first(struct file *filp); + + /** + * Notification of the last close. + * + * This function is called when the device open count transitions from + * one to zero. The driver lock is held for the duration of the call. + * + * The default implementation returns OK. + * + * @param filp Pointer to the NuttX file structure. + * @return OK if the open should return OK, -errno otherwise. + */ + virtual int close_last(struct file *filp); + +private: + static const unsigned _max_pollwaiters = 8; + + const char *_devname; /**< device node name */ + bool _registered; /**< true if device name was registered */ + unsigned _open_count; /**< number of successful opens */ + + struct pollfd *_pollset[_max_pollwaiters]; + + /** + * Store a pollwaiter in a slot where we can find it later. + * + * Expands the pollset as required. Must be called with the driver locked. + * + * @return OK, or -errno on error. + */ + int store_poll_waiter(struct pollfd *fds); + + /** + * Remove a poll waiter. + * + * @return OK, or -errno on error. + */ + int remove_poll_waiter(struct pollfd *fds); +}; + +/** + * Abstract class for character device accessed via PIO + */ +class __EXPORT PIO : public CDev +{ +public: + /** + * Constructor + * + * @param name Driver name + * @param devname Device node name + * @param base Base address of the device PIO area + * @param irq Interrupt assigned to the device (or zero if none) + */ + PIO(const char *name, + const char *devname, + uint32_t base, + int irq = 0); + ~PIO(); + + int init(); + +protected: + + /** + * Read a register + * + * @param offset Register offset in bytes from the base address. + */ + uint32_t reg(uint32_t offset) { + return *(volatile uint32_t *)(_base + offset); + } + + /** + * Write a register + * + * @param offset Register offset in bytes from the base address. + * @param value Value to write. + */ + void reg(uint32_t offset, uint32_t value) { + *(volatile uint32_t *)(_base + offset) = value; + } + + /** + * Modify a register + * + * Note that there is a risk of a race during the read/modify/write cycle + * that must be taken care of by the caller. + * + * @param offset Register offset in bytes from the base address. + * @param clearbits Bits to clear in the register + * @param setbits Bits to set in the register + */ + void modify(uint32_t offset, uint32_t clearbits, uint32_t setbits) { + uint32_t val = reg(offset); + val &= ~clearbits; + val |= setbits; + reg(offset, val); + } + +private: + uint32_t _base; +}; + +} // namespace device + +#endif /* _DEVICE_DEVICE_H */ \ No newline at end of file diff --git a/apps/drivers/device/device.h.orig b/apps/drivers/device/device.h.orig new file mode 100644 index 0000000000..5030666e1c --- /dev/null +++ b/apps/drivers/device/device.h.orig @@ -0,0 +1,430 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Definitions for the generic base classes in the device framework. + */ + +#ifndef _DEVICE_DEVICE_H +#define _DEVICE_DEVICE_H + +/* + * Includes here should only cover the needs of the framework definitions. + */ +#include + +#include +#include +#include +#include +#include + +#include + +/** + * Namespace encapsulating all device framework classes, functions and data. + */ +namespace device __EXPORT +{ + +/** + * Fundamental base class for all device drivers. + * + * This class handles the basic "being a driver" things, including + * interrupt registration and dispatch. + */ +class __EXPORT Device +{ +public: + /** + * Interrupt handler. + */ + virtual void interrupt(void *ctx); /**< interrupt handler */ + +protected: + const char *_name; /**< driver name */ + bool _debug_enabled; /**< if true, debug messages are printed */ + + /** + * Constructor + * + * @param name Driver name + * @param irq Interrupt assigned to the device. + */ + Device(const char *name, + int irq = 0); + ~Device(); + + /** + * Initialise the driver and make it ready for use. + * + * @return OK if the driver initialised OK. + */ + virtual int init(); + + /** + * Enable the device interrupt + */ + void interrupt_enable(); + + /** + * Disable the device interrupt + */ + void interrupt_disable(); + + /** + * Take the driver lock. + * + * Each driver instance has its own lock/semaphore. + * + * Note that we must loop as the wait may be interrupted by a signal. + */ + void lock() { + do {} while (sem_wait(&_lock) != 0); + } + + /** + * Release the driver lock. + */ + void unlock() { + sem_post(&_lock); + } + + /** + * Log a message. + * + * The message is prefixed with the driver name, and followed + * by a newline. + */ + void log(const char *fmt, ...); + + /** + * Print a debug message. + * + * The message is prefixed with the driver name, and followed + * by a newline. + */ + void debug(const char *fmt, ...); + +private: + int _irq; + bool _irq_attached; + sem_t _lock; + + /** disable copy construction for this and all subclasses */ + Device(const Device &); + + /** disable assignment for this and all subclasses */ + Device &operator = (const Device &); + + /** + * Register ourselves as a handler for an interrupt + * + * @param irq The interrupt to claim + * @return OK if the interrupt was registered + */ + int dev_register_interrupt(int irq); + + /** + * Unregister ourselves as a handler for any interrupt + */ + void dev_unregister_interrupt(); + + /** + * Interrupt dispatcher + * + * @param irq The interrupt that has been triggered. + * @param context Pointer to the interrupted context. + */ + static void dev_interrupt(int irq, void *context); +}; + +/** + * Abstract class for any character device + */ +class __EXPORT CDev : public Device +{ +public: + /** + * Constructor + * + * @param name Driver name + * @param devname Device node name + * @param irq Interrupt assigned to the device + */ + CDev(const char *name, const char *devname, int irq = 0); + + /** + * Destructor + */ + ~CDev(); + + virtual int init(); + + /** + * Handle an open of the device. + * + * This function is called for every open of the device. The default + * implementation maintains _open_count and always returns OK. + * + * @param filp Pointer to the NuttX file structure. + * @return OK if the open is allowed, -errno otherwise. + */ + virtual int open(struct file *filp); + + /** + * Handle a close of the device. + * + * This function is called for every close of the device. The default + * implementation maintains _open_count and returns OK as long as it is not zero. + * + * @param filp Pointer to the NuttX file structure. + * @return OK if the close was successful, -errno otherwise. + */ + virtual int close(struct file *filp); + + /** + * Perform a read from the device. + * + * The default implementation returns -ENOSYS. + * + * @param filp Pointer to the NuttX file structure. + * @param buffer Pointer to the buffer into which data should be placed. + * @param buflen The number of bytes to be read. + * @return The number of bytes read or -errno otherwise. + */ + virtual ssize_t read(struct file *filp, char *buffer, size_t buflen); + + /** + * Perform a write to the device. + * + * The default implementation returns -ENOSYS. + * + * @param filp Pointer to the NuttX file structure. + * @param buffer Pointer to the buffer from which data should be read. + * @param buflen The number of bytes to be written. + * @return The number of bytes written or -errno otherwise. + */ + virtual ssize_t write(struct file *filp, const char *buffer, size_t buflen); + + /** + * Perform a logical seek operation on the device. + * + * The default implementation returns -ENOSYS. + * + * @param filp Pointer to the NuttX file structure. + * @param offset The new file position relative to whence. + * @param whence SEEK_OFS, SEEK_CUR or SEEK_END. + * @return The previous offset, or -errno otherwise. + */ + virtual off_t seek(struct file *filp, off_t offset, int whence); + + /** + * Perform an ioctl operation on the device. + * + * The default implementation handles DIOC_GETPRIV, and otherwise + * returns -ENOTTY. Subclasses should call the default implementation + * for any command they do not handle themselves. + * + * @param filp Pointer to the NuttX file structure. + * @param cmd The ioctl command value. + * @param arg The ioctl argument value. + * @return OK on success, or -errno otherwise. + */ + virtual int ioctl(struct file *filp, int cmd, unsigned long arg); + + /** + * Perform a poll setup/teardown operation. + * + * This is handled internally and should not normally be overridden. + * + * @param filp Pointer to the NuttX file structure. + * @param fds Poll descriptor being waited on. + * @param arg True if this is establishing a request, false if + * it is being torn down. + * @return OK on success, or -errno otherwise. + */ + virtual int poll(struct file *filp, struct pollfd *fds, bool setup); + +protected: + /** + * Check the current state of the device for poll events from the + * perspective of the file. + * + * This function is called by the default poll() implementation when + * a poll is set up to determine whether the poll should return immediately. + * + * The default implementation returns no events. + * + * @param filp The file that's interested. + * @return The current set of poll events. + */ + virtual pollevent_t poll_state(struct file *filp); + + /** + * Report new poll events. + * + * This function should be called anytime the state of the device changes + * in a fashion that might be interesting to a poll waiter. + * + * @param events The new event(s) being announced. + */ + virtual void poll_notify(pollevent_t events); + + /** + * Internal implementation of poll_notify. + * + * @param fds A poll waiter to notify. + * @param events The event(s) to send to the waiter. + */ + virtual void poll_notify_one(struct pollfd *fds, pollevent_t events); + + /** + * Notification of the first open. + * + * This function is called when the device open count transitions from zero + * to one. The driver lock is held for the duration of the call. + * + * The default implementation returns OK. + * + * @param filp Pointer to the NuttX file structure. + * @return OK if the open should proceed, -errno otherwise. + */ + virtual int open_first(struct file *filp); + + /** + * Notification of the last close. + * + * This function is called when the device open count transitions from + * one to zero. The driver lock is held for the duration of the call. + * + * The default implementation returns OK. + * + * @param filp Pointer to the NuttX file structure. + * @return OK if the open should return OK, -errno otherwise. + */ + virtual int close_last(struct file *filp); + +private: + static const unsigned _max_pollwaiters = 8; + + const char *_devname; /**< device node name */ + bool _registered; /**< true if device name was registered */ + unsigned _open_count; /**< number of successful opens */ + + struct pollfd *_pollset[_max_pollwaiters]; + + /** + * Store a pollwaiter in a slot where we can find it later. + * + * Expands the pollset as required. Must be called with the driver locked. + * + * @return OK, or -errno on error. + */ + int store_poll_waiter(struct pollfd *fds); + + /** + * Remove a poll waiter. + * + * @return OK, or -errno on error. + */ + int remove_poll_waiter(struct pollfd *fds); +}; + +/** + * Abstract class for character device accessed via PIO + */ +class __EXPORT PIO : public CDev +{ +public: + /** + * Constructor + * + * @param name Driver name + * @param devname Device node name + * @param base Base address of the device PIO area + * @param irq Interrupt assigned to the device (or zero if none) + */ + PIO(const char *name, + const char *devname, + uint32_t base, + int irq = 0); + ~PIO(); + + int init(); + +protected: + + /** + * Read a register + * + * @param offset Register offset in bytes from the base address. + */ + uint32_t reg(uint32_t offset) { + return *(volatile uint32_t *)(_base + offset); + } + + /** + * Write a register + * + * @param offset Register offset in bytes from the base address. + * @param value Value to write. + */ + void reg(uint32_t offset, uint32_t value) { + *(volatile uint32_t *)(_base + offset) = value; + } + + /** + * Modify a register + * + * Note that there is a risk of a race during the read/modify/write cycle + * that must be taken care of by the caller. + * + * @param offset Register offset in bytes from the base address. + * @param clearbits Bits to clear in the register + * @param setbits Bits to set in the register + */ + void modify(uint32_t offset, uint32_t clearbits, uint32_t setbits) { + uint32_t val = reg(offset); + val &= ~clearbits; + val |= setbits; + reg(offset, val); + } + +private: + uint32_t _base; +}; + +} // namespace device + +#endif /* _DEVICE_DEVICE_H */ \ No newline at end of file diff --git a/apps/drivers/device/i2c.cpp b/apps/drivers/device/i2c.cpp new file mode 100644 index 0000000000..8489db4bb0 --- /dev/null +++ b/apps/drivers/device/i2c.cpp @@ -0,0 +1,149 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Base class for devices attached via the I2C bus. + * + * @todo Bus frequency changes; currently we do nothing with the value + * that is supplied. Should we just depend on the bus knowing? + */ + +#include "i2c.h" + +namespace device +{ + +I2C::I2C(const char *name, + const char *devname, + int bus, + uint16_t address, + uint32_t frequency, + int irq) : + // base class + CDev(name, devname, irq), + // public + // protected + // private + _bus(bus), + _address(address), + _frequency(frequency), + _dev(nullptr) +{ +} + +I2C::~I2C() +{ + if (_dev) + up_i2cuninitialize(_dev); +} + +int +I2C::init() +{ + int ret = OK; + + // attach to the i2c bus + _dev = up_i2cinitialize(_bus); + + if (_dev == nullptr) { + debug("failed to init I2C"); + ret = -ENOENT; + goto out; + } + + // call the probe function to check whether the device is present + ret = probe(); + + if (ret != OK) { + debug("probe failed"); + goto out; + } + + // do base class init, which will create device node, etc + ret = CDev::init(); + + if (ret != OK) { + debug("cdev init failed"); + goto out; + } + + // tell the world where we are + log("on bus %d at 0x%02x", _bus, _address); + +out: + return ret; +} + +int +I2C::probe() +{ + // Assume the device is too stupid to be discoverable. + return OK; +} + +int +I2C::transfer(uint8_t *send, unsigned send_len, uint8_t *recv, unsigned recv_len) +{ + struct i2c_msg_s msgv[2]; + unsigned msgs; + int ret; + +// debug("transfer out %p/%u in %p/%u", send, send_len, recv, recv_len); + + msgs = 0; + + if (send_len > 0) { + msgv[msgs].addr = _address; + msgv[msgs].flags = 0; + msgv[msgs].buffer = send; + msgv[msgs].length = send_len; + msgs++; + } + + if (recv_len > 0) { + msgv[msgs].addr = _address; + msgv[msgs].flags = I2C_M_READ; + msgv[msgs].buffer = recv; + msgv[msgs].length = recv_len; + msgs++; + } + + if (msgs == 0) + return -EINVAL; + + ret = I2C_TRANSFER(_dev, &msgv[0], msgs); + + return ret; +} + +} // namespace device \ No newline at end of file diff --git a/apps/drivers/device/i2c.h b/apps/drivers/device/i2c.h new file mode 100644 index 0000000000..d84f7bd09b --- /dev/null +++ b/apps/drivers/device/i2c.h @@ -0,0 +1,116 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Base class for devices connected via I2C. + */ + +#ifndef _DEVICE_I2C_H +#define _DEVICE_I2C_H + +#include "device.h" + +#include + +namespace device __EXPORT +{ + +/** + * Abstract class for character device on I2C + */ +class __EXPORT I2C : public CDev +{ + +protected: + /** + * @ Constructor + * + * @param name Driver name + * @param devname Device node name + * @param bus I2C bus on which the device lives + * @param address I2C bus address, or zero if set_address will be used + * @param frequency I2C bus frequency for the device (currently not used) + * @param irq Interrupt assigned to the device (or zero if none) + */ + I2C(const char *name, + const char *devname, + int bus, + uint16_t address, + uint32_t frequency, + int irq = 0); + ~I2C(); + + virtual int init(); + + /** + * Check for the presence of the device on the bus. + */ + virtual int probe(); + + /** + * Perform an I2C transaction to the device. + * + * At least one of send_len and recv_len must be non-zero. + * + * @param send Pointer to bytes to send. + * @param send_len Number of bytes to send. + * @param recv Pointer to buffer for bytes received. + * @param recv_len Number of bytes to receive. + * @return OK if the transfer was successful, -errno + * otherwise. + */ + int transfer(uint8_t *send, unsigned send_len, + uint8_t *recv, unsigned recv_len); + + /** + * Change the bus address. + * + * Most often useful during probe() when the driver is testing + * several possible bus addresses. + * + * @param address The new bus address to set. + */ + void set_address(uint16_t address) { + _address = address; + } + +private: + int _bus; + uint16_t _address; + uint32_t _frequency; + struct i2c_dev_s *_dev; +}; + +} // namespace device + +#endif /* _DEVICE_I2C_H */ diff --git a/apps/drivers/device/pio.cpp b/apps/drivers/device/pio.cpp new file mode 100644 index 0000000000..5179752b55 --- /dev/null +++ b/apps/drivers/device/pio.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Base class for devices accessed via PIO to registers. + */ + +#include "device.h" + +namespace device +{ + +PIO::PIO(const char *name, + const char *devname, + uint32_t base, + int irq) : + // base class + CDev(name, devname, irq), + // public + // protected + // private + _base(base) +{ +} + +PIO::~PIO() +{ + // nothing to do here... +} + +int +PIO::init() +{ + int ret = OK; + + // base class init first + ret = CDev::init(); + + return ret; +} + +} // namespace device \ No newline at end of file diff --git a/apps/drivers/device/spi.cpp b/apps/drivers/device/spi.cpp new file mode 100644 index 0000000000..d0647bef62 --- /dev/null +++ b/apps/drivers/device/spi.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Base class for devices connected via SPI. + * + * @todo Work out if caching the mode/frequency would save any time. + */ + +#include "spi.h" + +#ifndef CONFIG_SPI_EXCHANGE +# error This driver requires CONFIG_SPI_EXCHANGE +#endif + +namespace device +{ + +SPI::SPI(const char *name, + const char *devname, + int bus, + enum spi_dev_e device, + enum spi_mode_e mode, + uint32_t frequency, + int irq) : + // base class + CDev(name, devname, irq), + // public + // protected + // private + _bus(bus), + _device(device), + _mode(mode), + _frequency(frequency), + _dev(nullptr) +{ +} + +SPI::~SPI() +{ + // XXX no way to let go of the bus... +} + +int +SPI::init() +{ + int ret = OK; + + // attach to the spi bus + if (_dev == nullptr) + _dev = up_spiinitialize(_bus); + + if (_dev == nullptr) { + debug("failed to init SPI"); + ret = -ENOENT; + goto out; + } + + // call the probe function to check whether the device is present + ret = probe(); + + if (ret != OK) { + debug("probe failed"); + goto out; + } + + // do base class init, which will create the device node, etc. + ret = CDev::init(); + + if (ret != OK) { + debug("cdev init failed"); + goto out; + } + + // tell the workd where we are + log("on bus %d at %d", _bus, _device); + +out: + return ret; +} + +int +SPI::probe() +{ + // assume the device is too stupid to be discoverable + return OK; +} + +int +SPI::transfer(uint8_t *send, uint8_t *recv, unsigned len) +{ + + if ((send == nullptr) && (recv == nullptr)) + return -EINVAL; + + /* do common setup */ + SPI_LOCK(_dev, true); + SPI_SETFREQUENCY(_dev, _frequency); + SPI_SETMODE(_dev, _mode); + SPI_SELECT(_dev, _device, true); + + /* do the transfer */ + SPI_EXCHANGE(_dev, send, recv, len); + + /* and clean up */ + SPI_SELECT(_dev, _device, false); + SPI_LOCK(_dev, false); + + return OK; +} + +} // namespace device \ No newline at end of file diff --git a/apps/drivers/device/spi.h b/apps/drivers/device/spi.h new file mode 100644 index 0000000000..ef382b03cf --- /dev/null +++ b/apps/drivers/device/spi.h @@ -0,0 +1,106 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Base class for devices connected via SPI. + */ + +#ifndef _DEVICE_SPI_H +#define _DEVICE_SPI_H + +#include "device.h" + +#include + +namespace device __EXPORT +{ + +/** + * Abstract class for character device on SPI + */ +class __EXPORT SPI : public CDev +{ +protected: + /** + * Constructor + * + * @param name Driver name + * @param devname Device node name + * @param bus SPI bus on which the device lives + * @param device Device handle (used by SPI_SELECT) + * @param mode SPI clock/data mode + * @param frequency SPI clock frequency + * @param irq Interrupt assigned to the device (or zero if none) + */ + SPI(const char *name, + const char *devname, + int bus, + enum spi_dev_e device, + enum spi_mode_e mode, + uint32_t frequency, + int irq = 0); + ~SPI(); + + virtual int init(); + + /** + * Check for the presence of the device on the bus. + */ + virtual int probe(); + + /** + * Perform a SPI transfer. + * + * At least one of send or recv must be non-null. + * + * @param send Bytes to send to the device, or nullptr if + * no data is to be sent. + * @param recv Buffer for receiving bytes from the device, + * or nullptr if no bytes are to be received. + * @param len Number of bytes to transfer. + * @return OK if the exchange was successful, -errno + * otherwise. + */ + int transfer(uint8_t *send, uint8_t *recv, unsigned len); + +private: + int _bus; + enum spi_dev_e _device; + enum spi_mode_e _mode; + uint32_t _frequency; + struct spi_dev_s *_dev; +}; + +} // namespace device + +#endif /* _DEVICE_SPI_H */ diff --git a/apps/drivers/drv_accel.h b/apps/drivers/drv_accel.h new file mode 100644 index 0000000000..bf13b2c32b --- /dev/null +++ b/apps/drivers/drv_accel.h @@ -0,0 +1,105 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Accelerometer driver interface. + */ + +#ifndef _DRV_ACCEL_H +#define _DRV_ACCEL_H + +#include +#include + +#include "drv_orb_dev.h" + +#define ACCEL_DEVICE_PATH "/dev/accel" + +/** + * accel report structure. Reads from the device must be in multiples of this + * structure. + */ +struct accel_report { + float x; + float y; + float z; + uint64_t timestamp; +}; + +/** accel scaling factors; Vout = (Vin * Vscale) + Voffset */ +struct accel_scale { + float x_offset; + float x_scale; + float y_offset; + float y_scale; + float z_offset; + float z_scale; +}; + +/* + * ObjDev tag for raw accelerometer data. + */ +ORB_DECLARE(sensor_accel); + +/* + * ioctl() definitions + */ + +#define _ACCELIOCBASE (_SNIOCBASE + 0x20) +#define _ACCELIOC(_n) (_IOC(_ACCELIOCBASE, _n)) + +/** set the driver polling rate to (arg) Hz, or one of the ACC_POLLRATE constants */ +#define ACCELIOCSPOLLRATE _ACCELIOC(0) + +#define ACC_POLLRATE_MANUAL 1000000 /**< poll when read */ +#define ACC_POLLRATE_EXTERNAL 1000001 /**< poll when device signals ready */ + +/** set the internal queue depth to (arg) entries, must be at least 1 */ +#define ACCELIOCSQUEUEDEPTH _ACCELIOC(1) + +/** set the accel internal sample rate to at least (arg) Hz */ +#define ACCELIOCSSAMPLERATE _ACCELIOC(2) + +/** set the accel internal lowpass filter to no lower than (arg) Hz */ +#define ACCELIOCSLOWPASS _ACCELIOC(3) + +/** set the report format to (arg); zero is the standard, 1-10 are reserved, all others are driver-specific. */ +#define ACCELIOCSREPORTFORMAT _ACCELIOC(4) + +/** set the accel scaling constants to the structure pointed to by (arg) */ +#define ACCELIOCSSCALE _ACCELIOC(5) + +/** set the accel measurement range to handle at least (arg) g */ +#define ACCELIORANGE _ACCELIOC(6) + +#endif /* _DRV_ACCEL_H */ diff --git a/apps/drivers/drv_baro.h b/apps/drivers/drv_baro.h new file mode 100644 index 0000000000..4cfb354547 --- /dev/null +++ b/apps/drivers/drv_baro.h @@ -0,0 +1,83 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Barometric pressure sensor driver interface. + */ + +#ifndef _DRV_BARO_H +#define _DRV_BARO_H + +#include +#include + +#include "drv_orb_dev.h" + +#define BARO_DEVICE_PATH "/dev/baro" + +/** + * baro report structure. Reads from the device must be in multiples of this + * structure. + */ +struct baro_report { + float pressure; + float altitude; + float temperature; + uint64_t timestamp; +}; + +/* + * ObjDev tag for raw barometer data. + */ +ORB_DECLARE(sensor_baro); + +/* + * ioctl() definitions + */ + +#define _BAROIOCBASE (_SNIOCBASE + 0x10) +#define _BAROIOC(_n) (_IOC(_BAROIOCBASE, _n)) + +/** set the driver polling rate to (arg) Hz, or one of the BARO_POLLRATE constants */ +#define BAROIOCSPOLLRATE _BAROIOC(0) + +#define BARO_POLLRATE_MANUAL 1000000 /**< poll when read */ +#define BARO_POLLRATE_EXTERNAL 1000001 /**< poll when device signals ready */ + +/** set the internal queue depth to (arg) entries, must be at least 1 */ +#define BAROIOCSQUEUEDEPTH _BAROIOC(1) + +/** set the report format to (arg); zero is the standard, 1-10 are reserved, all others are driver-specific. */ +#define BAROIOCSREPORTFORMAT _BAROIOC(2) + +#endif /* _DRV_BARO_H */ diff --git a/apps/drivers/drv_gpio.h b/apps/drivers/drv_gpio.h new file mode 100644 index 0000000000..b9684bce16 --- /dev/null +++ b/apps/drivers/drv_gpio.h @@ -0,0 +1,64 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Generic GPIO ioctl interface. + */ + +#ifndef _DRV_GPIO_H +#define _DRV_GPIO_H + +#include + +/* + * GPIO defines come from a board-specific header, as they are shared + * with board-specific logic. + * + * The board-specific header must define: + * GPIO_DEVICE_PATH + * GPIO_RESET + * GPIO_SET_OUTPUT + * GPIO_SET_INPUT + * GPIO_SET_ALT_1 + * GPIO_SET_ALT_2 + * GPIO_SET_ALT_3 + * GPIO_SET_ALT_4 + * GPIO_SET + * GPIO_CLEAR + * GPIO_GET + */ + +/* Include board-specific GPIO definitions as well. */ +#include + +#endif /* _DRV_GPIO_H */ \ No newline at end of file diff --git a/apps/drivers/drv_gyro.h b/apps/drivers/drv_gyro.h new file mode 100644 index 0000000000..21f6493b13 --- /dev/null +++ b/apps/drivers/drv_gyro.h @@ -0,0 +1,102 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Gyroscope driver interface. + */ + +#ifndef _DRV_GYRO_H +#define _DRV_GYRO_H + +#include +#include + +#include "drv_orb_dev.h" + +#define GYRO_DEVICE_PATH "/dev/gyro" + +/** + * gyro report structure. Reads from the device must be in multiples of this + * structure. + */ +struct gyro_report { + float x; + float y; + float z; + uint64_t timestamp; +}; + +/** gyro scaling factors; Vout = (Vin * Vscale) + Voffset */ +struct gyro_scale { + float x_offset; + float x_scale; + float y_offset; + float y_scale; + float z_offset; + float z_scale; +}; + +/* + * ObjDev tag for raw gyro data. + */ +ORB_DECLARE(sensor_gyro); + +/* + * ioctl() definitions + */ + +#define _GYROIOCBASE (_SNIOCBASE + 0x10) +#define _GYROIOC(_n) (_IOC(_GYROIOCBASE, _n)) + +/** set the driver polling rate to (arg) Hz, or one of the GYRO_POLLRATE constants */ +#define GYROIOCSPOLLRATE _GYROIOC(0) + +#define GYRO_POLLRATE_MANUAL 1000000 /**< poll when read */ +#define GYRO_POLLRATE_EXTERNAL 1000001 /**< poll when device signals ready */ + +/** set the internal queue depth to (arg) entries, must be at least 1 */ +#define GYROIOCSQUEUEDEPTH _GYROIOC(1) + +/** set the gyro internal sample rate to at least (arg) Hz */ +#define GYROIOCSSAMPLERATE _GYROIOC(2) + +/** set the gyro internal lowpass filter to no lower than (arg) Hz */ +#define GYROIOCSLOWPASS _GYROIOC(3) + +/** set the report format to (arg); zero is the standard, 1-10 are reserved, all others are driver-specific. */ +#define GYROIOCSREPORTFORMAT _GYROIOC(4) + +/** set the gyro scaling constants to (arg) */ +#define GYROIOCSSCALE _GYROIOC(5) + +#endif /* _DRV_GYRO_H */ diff --git a/apps/drivers/drv_mag.h b/apps/drivers/drv_mag.h new file mode 100644 index 0000000000..7e90e9e463 --- /dev/null +++ b/apps/drivers/drv_mag.h @@ -0,0 +1,102 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Magnetometer driver interface. + */ + +#ifndef _DRV_MAG_H +#define _DRV_MAG_H + +#include +#include + +#include "drv_orb_dev.h" + +#define MAG_DEVICE_PATH "/dev/mag" + +/** + * mag report structure. Reads from the device must be in multiples of this + * structure. + */ +struct mag_report { + float x; + float y; + float z; + uint64_t timestamp; +}; + +/** mag scaling factors; Vout = (Vin * Vscale) + Voffset */ +struct mag_scale { + float x_offset; + float x_scale; + float y_offset; + float y_scale; + float z_offset; + float z_scale; +}; + +/* + * ObjDev tag for raw magnetometer data. + */ +ORB_DECLARE(sensor_mag); + +/* + * ioctl() definitions + */ + +#define _MAGIOCBASE (_SNIOCBASE + 0x30) +#define _MAGIOC(_n) (_IOC(_MAGIOBASE, _n)) + +/** set the driver polling rate to (arg) Hz, or one of the MAG_POLLRATE constants */ +#define MAGIOCSPOLLRATE _MAGIOC(0) + +#define MAG_POLLRATE_MANUAL 1000000 /**< poll when read */ +#define MAG_POLLRATE_EXTERNAL 1000001 /**< poll when device signals ready */ + +/** set the internal queue depth to (arg) entries, must be at least 1 */ +#define MAGIOCSQUEUEDEPTH _MAGIOC(1) + +/** set the mag internal sample rate to at least (arg) Hz */ +#define MAGIOCSSAMPLERATE _MAGIOC(2) + +/** set the mag internal lowpass filter to no lower than (arg) Hz */ +#define MAGIOCSLOWPASS _MAGIOC(3) + +/** set the report format to (arg); zero is the standard, 1-10 are reserved, all others are driver-specific. */ +#define MAGIOCSREPORTFORMAT _MAGIOC(4) + +/** set the mag scaling constants to the structure pointed to by (arg) */ +#define MAGIOCSSCALE _MAGIOC(5) + +#endif /* _DRV_MAG_H */ diff --git a/apps/drivers/drv_orb_dev.h b/apps/drivers/drv_orb_dev.h new file mode 100644 index 0000000000..bacef1cd3a --- /dev/null +++ b/apps/drivers/drv_orb_dev.h @@ -0,0 +1,84 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef _DRV_UORB_H +#define _DRV_UORB_H + +/** + * @file uORB published object driver. + */ + +#include +#include +#include + +/* XXX for ORB_DECLARE used in many drivers */ +#include "../uORB/uORB.h" + +/* + * ioctl() definitions + */ + +/** path to the uORB control device for pub/sub topics */ +#define TOPIC_MASTER_DEVICE_PATH "/obj/_obj_" + +/** path to the uORB control device for parameter topics */ +#define PARAM_MASTER_DEVICE_PATH "/param/_param_" + +/** maximum ogbject name length */ +#define ORB_MAXNAME 32 + +#define _ORBIOCBASE (_DIOCBASE + 0x80) +#define _ORBIOC(_n) (_IOC(_ORBIOCBASE, _n)) + +/* + * IOCTLs for the uORB control device + */ + +/** Advertise a new topic described by *(uorb_metadata *)arg */ +#define ORBIOCADVERTISE _ORBIOC(0) + +/* + * IOCTLs for individual topics. + */ + +/** Fetch the time at which the topic was last updated into *(uint64_t *)arg */ +#define ORBIOCLASTUPDATE _ORBIOC(10) + +/** Check whether the topic has been updated since it was last read, sets *(bool *)arg */ +#define ORBIOCUPDATED _ORBIOC(11) + +/** Set the minimum interval at which the topic can be seen to be updated for this subscription */ +#define ORBIOCSETINTERVAL _ORBIOC(12) + +#endif /* _DRV_UORB_H */ diff --git a/apps/drivers/drv_pwm_output.h b/apps/drivers/drv_pwm_output.h new file mode 100644 index 0000000000..551f9b1a65 --- /dev/null +++ b/apps/drivers/drv_pwm_output.h @@ -0,0 +1,112 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file PWM servo output interface. + * + * Servo values can be set with the PWM_SERVO_SET ioctl, by writing a + * pwm_output_values structure to the device, or by publishing to the + * output_pwm ObjDev. + * Writing a value of 0 to a channel suppresses any output for that + * channel. + */ + +#ifndef _DRV_PWM_OUTPUT_H +#define _DRV_PWM_OUTPUT_H + +#include +#include + +#include "drv_orb_dev.h" + +/** + * Path for the default PWM output device. + * + * Note that on systems with more than one PWM output path (e.g. + * PX4FMU with PX4IO connected) there may be other devices that + * respond to this protocol. + */ +#define PWM_OUTPUT_DEVICE_PATH "/dev/pwm_output" + +/** + * Maximum number of PWM output channels in the system. + */ +#define PWM_OUTPUT_MAX_CHANNELS 16 + +/** + * Servo output signal type, value is actual servo output pulse + * width in microseconds. + */ +typedef uint16_t servo_position_t; + +/** + * Servo output status structure. + * + * May be published to output_pwm, or written to a PWM output + * device. + */ +struct pwm_output_values { + /** desired servo update rate in Hz */ + uint32_t update_rate; + + /** desired pulse widths for each of the supported channels */ + servo_position_t values[PWM_OUTPUT_MAX_CHANNELS]; +}; + +/* + * ObjDev tag for PWM outputs. + */ +ORB_DECLARE(output_pwm); + +/* + * ioctl() definitions + * + * Note that ioctls and ObjDev updates should not be mixed, as the + * behaviour of the system in this case is not defined. + */ +#define _PWM_SERVO_BASE 0x7500 + +/** arm all servo outputs handle by this driver */ +#define PWM_SERVO_ARM _IOC(_PWM_SERVO_BASE, 0) + +/** disarm all servo outputs (stop generating pulses) */ +#define PWM_SERVO_DISARM _IOC(_PWM_SERVO_BASE, 1) + +/** set a single servo to a specific value */ +#define PWM_SERVO_SET(_servo) _IOC(_PWM_SERVO_BASE, 0x20 + _servo) + +/** get a single specific servo value */ +#define PWM_SERVO_GET(_servo) _IOC(_PWM_SERVO_BASE, 0x40 + _servo) + + +#endif /* _DRV_PWM_OUTPUT_H */ diff --git a/apps/drivers/drv_rc_input.h b/apps/drivers/drv_rc_input.h new file mode 100644 index 0000000000..532e95fb58 --- /dev/null +++ b/apps/drivers/drv_rc_input.h @@ -0,0 +1,89 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file R/C input interface. + * + */ + +#ifndef _DRV_RC_INPUT_H +#define _DRV_RC_INPUT_H + +#include +#include + +#include "drv_orb_dev.h" + +/** + * Path for the default R/C input device. + * + * Note that on systems with more than one R/C input path (e.g. + * PX4FMU with PX4IO connected) there may be other devices that + * respond to this protocol. + * + * Input data may be obtained by subscribing to the input_rc + * object, or by poll/reading from the device. + */ +#define RC_INPUT_DEVICE_PATH "/dev/input_rc" + +/** + * Maximum number of R/C input channels in the system. + */ +#define RC_INPUT_MAX_CHANNELS 16 + +/** + * Input signal type, value is a control position from zero to 100 + * percent. + */ +typedef uint8_t rc_input_t; + +/** + * R/C input status structure. + * + * Published to input_rc, may also be published to other names depending + * on the board involved. + */ +struct rc_input_values { + /** number of channels actually being seen */ + uint32_t channel_count; + + /** desired pulse widths for each of the supported channels */ + rc_input_t values[RC_INPUT_MAX_CHANNELS]; +}; + +/* + * ObjDev tag for R/C inputs. + */ +ORB_DECLARE(input_rc); + +#endif /* _DRV_RC_INPUT_H */ diff --git a/apps/drivers/ms5611/Makefile b/apps/drivers/ms5611/Makefile new file mode 100644 index 0000000000..d8e67cba25 --- /dev/null +++ b/apps/drivers/ms5611/Makefile @@ -0,0 +1,42 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# MS5611 driver +# + +APPNAME = ms5611 +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +include $(APPDIR)/mk/app.mk diff --git a/apps/drivers/ms5611/ms5611.cpp b/apps/drivers/ms5611/ms5611.cpp new file mode 100644 index 0000000000..d3c75f755c --- /dev/null +++ b/apps/drivers/ms5611/ms5611.cpp @@ -0,0 +1,944 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Driver for the MS5611 barometric pressure sensor connected via I2C + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +/** + * Calibration PROM as reported by the device. + */ +#pragma pack(push,1) +struct ms5611_prom_s { + uint16_t factory_setup; + uint16_t c1_pressure_sens; + uint16_t c2_pressure_offset; + uint16_t c3_temp_coeff_pres_sens; + uint16_t c4_temp_coeff_pres_offset; + uint16_t c5_reference_temp; + uint16_t c6_temp_coeff_temp; + uint16_t serial_and_crc; +}; + +/** + * Grody hack for crc4() + */ +union ms5611_prom_u { + uint16_t c[8]; + struct ms5611_prom_s s; +}; +#pragma pack(pop) + +class MS5611 : public device::I2C +{ +public: + MS5611(int bus); + ~MS5611(); + + virtual int init(); + + virtual ssize_t read(struct file *filp, char *buffer, size_t buflen); + virtual int ioctl(struct file *filp, int cmd, unsigned long arg); + + virtual int open_first(struct file *filp); + virtual int close_last(struct file *filp); + + /** + * Diagnostics - print some basic information about the driver. + */ + void print_info(); + +protected: + virtual int probe(); + +private: + union ms5611_prom_u _prom; + + struct work_s _work; + unsigned _measure_ticks; + + unsigned _num_reports; + volatile unsigned _next_report; + volatile unsigned _oldest_report; + struct baro_report *_reports; + + bool _collect_phase; + unsigned _measure_phase; + + int32_t _dT; + int64_t _temp64; + + int _orbject; + + unsigned _reads; + unsigned _measure_errors; + unsigned _read_errors; + unsigned _buf_overflows; + + /** + * Test whether the device supported by the driver is present at a + * specific address. + * + * @param address The I2C bus address to probe. + * @return True if the device is present. + */ + int probe_address(uint8_t address); + + /** + * Initialise the automatic measurement state machine and start it. + * + * @note This function is called at open and error time. It might make sense + * to make it more aggressive about resetting the bus in case of errors. + */ + void start(); + + /** + * Stop the automatic measurement state machine. + */ + void stop(); + + /** + * Perform a poll cycle; collect from the previous measurement + * and start a new one. + * + * This is the heart of the measurement state machine. This function + * alternately starts a measurement, or collects the data from the + * previous measurement. + * + * When the interval between measurements is greater than the minimum + * measurement interval, a gap is inserted between collection + * and measurement to provide the most recent measurement possible + * at the next interval. + */ + void cycle(); + + /** + * Static trampoline from the workq context; because we don't have a + * generic workq wrapper yet. + * + * @param arg Instance pointer for the driver that is polling. + */ + static void cycle_trampoline(void *arg); + + /** + * Issue a measurement command for the current state. + * + * @return OK if the measurement command was successful. + */ + int measure(); + + /** + * Collect the result of the most recent measurement. + */ + int collect(); + + /** + * Read the MS5611 PROM + * + * @return OK if the PROM reads successfully. + */ + int read_prom(); + + /** + * PROM CRC routine ported from MS5611 application note + * + * @param n_prom Pointer to words read from PROM. + * @return True if the CRC matches. + */ + bool crc4(uint16_t *n_prom); + +}; + +/* helper macro for handling report buffer indices */ +#define INCREMENT(_x, _lim) do { _x++; if (_x >= _lim) _x = 0; } while(0) + +/* + * MS5611 internal constants and data structures. + */ + +/* internal conversion time: 9.17 ms, so should not be read at rates higher than 100 Hz */ +#define MS5611_CONVERSION_INTERVAL 10000 /* microseconds */ +#define MS5611_MEASUREMENT_RATIO 3 /* pressure measurements per temperature measurement */ + +#define MS5611_ADDRESS_1 0x76 /* address select pins pulled high (PX4FMU series v1.6+) */ +#define MS5611_ADDRESS_2 0x77 /* address select pins pulled low (PX4FMU prototypes) */ + +#define ADDR_RESET_CMD 0x1E /* read from this address to reset chip (0b0011110 on bus) */ +#define ADDR_CMD_CONVERT_D1 0x48 /* 4096 samples to this address to start conversion (0b01001000 on bus) */ +#define ADDR_CMD_CONVERT_D2 0x58 /* 4096 samples */ +#define ADDR_DATA 0x00 /* address of 3 bytes / 32bit pressure data */ +#define ADDR_PROM_SETUP 0xA0 /* address of 8x 2 bytes factory and calibration data */ +#define ADDR_PROM_C1 0xA2 /* address of 6x 2 bytes calibration data */ + +/* + * Driver 'main' command. + */ +extern "C" __EXPORT int ms5611_main(int argc, char *argv[]); + + +MS5611::MS5611(int bus) : + I2C("MS5611", BARO_DEVICE_PATH, bus, 0, 400000), + _measure_ticks(0), + _num_reports(0), + _next_report(0), + _oldest_report(0), + _reports(nullptr), + _collect_phase(false), + _measure_phase(0), + _dT(0), + _temp64(0), + _reads(0), + _measure_errors(0), + _read_errors(0), + _buf_overflows(0) +{ + // enable debug() calls + _debug_enabled = true; + + // work_cancel in the dtor will explode if we don't do this... + _work.worker = nullptr; +} + +MS5611::~MS5611() +{ + /* make sure we are truly inactive */ + stop(); + + /* free any existing reports */ + if (_reports != nullptr) + delete[] _reports; +} + +int +MS5611::init() +{ + int ret; + + /* do I2C init (and probe) first */ + ret = I2C::init(); + + /* assuming we're good, advertise the object */ + if (ret == OK) { + struct baro_report b; + + /* if this fails (e.g. no object in the system) that's OK */ + memset(&b, 0, sizeof(b)); + _orbject = orb_advertise(ORB_ID(sensor_baro), &b); + + if (_orbject < 0) + debug("failed to create sensor_baro object"); + } + + return ret; +} + +int +MS5611::open_first(struct file *filp) +{ + /* reset to manual-poll mode */ + _measure_ticks = 0; + + /* allocate basic report buffers */ + _num_reports = 2; + _reports = new struct baro_report[_num_reports]; + _oldest_report = _next_report = 0; + + return OK; +} + +int +MS5611::close_last(struct file *filp) +{ + /* stop measurement */ + stop(); + + /* free report buffers */ + if (_reports != nullptr) { + delete[] _reports; + _num_reports = 0; + } + + _measure_ticks = 0; + + return OK; +} + +int +MS5611::probe() +{ + if (OK == probe_address(MS5611_ADDRESS_1)) + return OK; + + if (OK == probe_address(MS5611_ADDRESS_2)) + return OK; + + return -EIO; +} + +int +MS5611::probe_address(uint8_t address) +{ + uint8_t cmd = ADDR_RESET_CMD; + + /* select the address we are going to try */ + set_address(address); + + /* send reset command */ + if (OK != transfer(&cmd, 1, nullptr, 0)) + return -EIO; + + /* wait for PROM contents to be in the device (2.8 ms) */ + usleep(3000); + + /* read PROM */ + if (OK != read_prom()) + return -EIO; + + return OK; +} + +ssize_t +MS5611::read(struct file *filp, char *buffer, size_t buflen) +{ + unsigned count = buflen / sizeof(struct baro_report); + int ret = 0; + + /* buffer must be large enough */ + if (count < 1) + return -ENOSPC; + + /* if automatic measurement is enabled */ + if (_measure_ticks > 0) { + + /* + * While there is space in the caller's buffer, and reports, copy them. + * Note that we may be pre-empted by the workq thread while we are doing this; + * we are careful to avoid racing with them. + */ + while (count--) { + if (_oldest_report != _next_report) { + memcpy(buffer, _reports + _oldest_report, sizeof(*_reports)); + ret += sizeof(_reports[0]); + INCREMENT(_oldest_report, _num_reports); + } + } + + _reads++; + + /* if there was no data, warn the caller */ + return ret ? ret : -EAGAIN; + } + + /* manual measurement - run one conversion */ + /* XXX really it'd be nice to lock against other readers here */ + do { + _measure_phase = 0; + _oldest_report = _next_report = 0; + + /* do temperature first */ + if (OK != measure()) { + ret = -EIO; + break; + } + + usleep(MS5611_CONVERSION_INTERVAL); + + if (OK != collect()) { + ret = -EIO; + break; + } + + /* now do a pressure measurement */ + if (OK != measure()) { + ret = -EIO; + break; + } + + usleep(MS5611_CONVERSION_INTERVAL); + + if (OK != collect()) { + ret = -EIO; + break; + } + + /* state machine will have generated a report, copy it out */ + memcpy(buffer, _reports, sizeof(*_reports)); + ret = sizeof(*_reports); + _reads++; + + } while (0); + + return ret; +} + +int +MS5611::ioctl(struct file *filp, int cmd, unsigned long arg) +{ + switch (cmd) { + + case BAROIOCSPOLLRATE: { + switch (arg) { + + /* switching to manual polling */ + case BARO_POLLRATE_MANUAL: + stop(); + _measure_ticks = 0; + return OK; + + /* external signalling not supported */ + case BARO_POLLRATE_EXTERNAL: + + /* zero would be bad */ + case 0: + return -EINVAL; + + /* adjust to a legal polling interval in Hz */ + default: { + /* do we need to start internal polling? */ + bool want_start = (_measure_ticks == 0); + + /* convert hz to tick interval via microseconds */ + unsigned ticks = USEC2TICK(1000000 / arg); + + /* check against maximum rate */ + if (ticks < USEC2TICK(MS5611_CONVERSION_INTERVAL)) + return -EINVAL; + + /* update interval for next measurement */ + _measure_ticks = ticks; + + /* if we need to start the poll state machine, do it */ + if (want_start) + start(); + + return OK; + } + } + } + + case BAROIOCSQUEUEDEPTH: { + /* lower bound is mandatory, upper bound is a sanity check */ + if ((arg < 2) || (arg > 100)) + return -EINVAL; + + /* allocate new buffer */ + struct baro_report *buf = new struct baro_report[arg]; + + if (nullptr == buf) + return -ENOMEM; + + /* reset the measurement state machine with the new buffer, free the old */ + stop(); + delete[] _reports; + _num_reports = arg; + _reports = buf; + start(); + + return OK; + } + + case BAROIOCSREPORTFORMAT: + return -EINVAL; + + default: + /* give it to the superclass */ + return I2C::ioctl(filp, cmd, arg); + } +} + +void +MS5611::start() +{ + /* make sure we are stopped first */ + stop(); + + /* reset the report ring and state machine */ + _collect_phase = false; + _measure_phase = 0; + _oldest_report = _next_report = 0; + + /* schedule a cycle to start things */ + work_queue(&_work, (worker_t)&MS5611::cycle_trampoline, this, 1); +} + +void +MS5611::stop() +{ + work_cancel(&_work); +} + +void +MS5611::cycle_trampoline(void *arg) +{ + MS5611 *dev = (MS5611 *)arg; + + dev->cycle(); +} + +void +MS5611::cycle() +{ + /* collection phase? */ + if (_collect_phase) { + + /* perform collection */ + if (OK != collect()) { + log("FATAL collection error - restarting\n"); + start(); + return; + } + + /* next phase is measurement */ + _collect_phase = false; + + /* + * Is there a collect->measure gap? + * Don't inject one after temperature measurements, so we can keep + * doing pressure measurements at something close to the desired rate. + */ + if ((_measure_phase != 0) && + (_measure_ticks > USEC2TICK(MS5611_CONVERSION_INTERVAL))) { + + /* schedule a fresh cycle call when we are ready to measure again */ + work_queue(&_work, + (worker_t)&MS5611::cycle_trampoline, + this, + _measure_ticks - USEC2TICK(MS5611_CONVERSION_INTERVAL)); + + return; + } + } + + /* measurement phase */ + if (OK != measure()) { + log("FATAL measure error - restarting\n"); + start(); + } + + /* next phase is collection */ + _collect_phase = true; + + /* schedule a fresh cycle call when the measurement is done */ + work_queue(&_work, + (worker_t)&MS5611::cycle_trampoline, + this, + USEC2TICK(MS5611_CONVERSION_INTERVAL)); +} + +int +MS5611::measure() +{ + int ret; + + /* + * In phase zero, request temperature; in other phases, request pressure. + */ + uint8_t cmd_data = (_measure_phase == 0) ? ADDR_CMD_CONVERT_D2 : ADDR_CMD_CONVERT_D1; + + /* + * Send the command to begin measuring. + */ + ret = transfer(&cmd_data, 1, nullptr, 0); + + if (OK != ret) + _measure_errors++; + + return ret; +} + +int +MS5611::collect() +{ + uint8_t cmd; + uint8_t data[3]; + + /* read the most recent measurement */ + cmd = 0; + + /* this should be fairly close to the end of the conversion, so the best approximation of the time */ + _reports[_next_report].timestamp = hrt_absolute_time(); + + if (OK != transfer(&cmd, 1, &data[0], 3)) { + _read_errors++; + return -EIO; + } + + /* fetch the raw value */ + uint32_t raw = (((uint32_t)data[0]) << 16) | (((uint32_t)data[1]) << 8) | ((uint32_t)data[2]); + + /* handle a measurement */ + if (_measure_phase == 0) { + + /* temperature calculation */ + _dT = raw - (((int32_t)_prom.s.c5_reference_temp) * 256); + _temp64 = 2000 + (((int64_t)_dT) * _prom.s.c6_temp_coeff_temp) / 8388608; + + } else { + + /* pressure calculation */ + int64_t offset = (int64_t)_prom.s.c2_pressure_offset * 65536 + ((int64_t)_dT * _prom.s.c4_temp_coeff_pres_offset) / 128; + int64_t sens = (int64_t)_prom.s.c1_pressure_sens * 32768 + ((int64_t)_dT * _prom.s.c3_temp_coeff_pres_sens) / 256; + + /* it's pretty cold, second order temperature compensation needed */ + if (_temp64 < 2000) { + /* second order temperature compensation */ + int64_t temp2 = (((int64_t)_dT) * _dT) >> 31; + int64_t tmp_64 = (_temp64 - 2000) * (_temp64 - 2000); + int64_t offset2 = (5 * tmp_64) >> 1; + int64_t sens2 = (5 * tmp_64) >> 2; + _temp64 = _temp64 - temp2; + offset = offset - offset2; + sens = sens - sens2; + } + + int64_t press_int64 = (((raw * sens) / 2097152 - offset) / 32768); + + /* generate a new report */ + _reports[_next_report].temperature = _temp64 / 100.0f; + _reports[_next_report].pressure = press_int64 / 100.0f; + /* convert as double for max. precision, store as float (more than enough precision) */ + _reports[_next_report].altitude = (44330.0 * (1.0 - pow((press_int64 / 101325.0), 0.190295))); + + /* publish it */ + orb_publish(ORB_ID(sensor_baro), _orbject, &_reports[_next_report]); + + /* post a report to the ring - note, not locked */ + INCREMENT(_next_report, _num_reports); + + /* if we are running up against the oldest report, toss it */ + if (_next_report == _oldest_report) { + _buf_overflows++; + INCREMENT(_oldest_report, _num_reports); + } + + /* notify anyone waiting for data */ + poll_notify(POLLIN); + } + + + /* update the measurement state machine */ + INCREMENT(_measure_phase, MS5611_MEASUREMENT_RATIO + 1); + + return OK; +} + +int +MS5611::read_prom() +{ + /* read PROM data */ + uint8_t prom_buf[2] = {255, 255}; + + for (int i = 0; i < 8; i++) { + uint8_t cmd = ADDR_PROM_SETUP + (i * 2); + + if (OK != transfer(&cmd, 1, &prom_buf[0], 2)) + break; + + /* assemble 16 bit value and convert from big endian (sensor) to little endian (MCU) */ + _prom.c[i] = (((uint16_t)prom_buf[0]) << 8) | ((uint16_t)prom_buf[1]); + + } + + /* calculate CRC and return false */ + return crc4(&_prom.c[0]) ? OK : -EIO; +} + +bool +MS5611::crc4(uint16_t *n_prom) +{ + int16_t cnt; + uint16_t n_rem; + uint16_t crc_read; + uint8_t n_bit; + + n_rem = 0x00; + + /* save the read crc */ + crc_read = n_prom[7]; + + /* remove CRC byte */ + n_prom[7] = (0xFF00 & (n_prom[7])); + + for (cnt = 0; cnt < 16; cnt++) { + /* uneven bytes */ + if (cnt & 1) { + n_rem ^= (uint8_t)((n_prom[cnt >> 1]) & 0x00FF); + + } else { + n_rem ^= (uint8_t)(n_prom[cnt >> 1] >> 8); + } + + for (n_bit = 8; n_bit > 0; n_bit--) { + if (n_rem & 0x8000) { + n_rem = (n_rem << 1) ^ 0x3000; + + } else { + n_rem = (n_rem << 1); + } + } + } + + /* final 4 bit remainder is CRC value */ + n_rem = (0x000F & (n_rem >> 12)); + n_prom[7] = crc_read; + + /* return true if CRCs match */ + return (0x000F & crc_read) == (n_rem ^ 0x00); +} + +void +MS5611::print_info() +{ + printf("reads: %u\n", _reads); + printf("measure errors: %u\n", _measure_errors); + printf("read errors: %u\n", _read_errors); + printf("read overflows: %u\n", _buf_overflows); + printf("poll interval: %u ticks\n", _measure_ticks); + printf("report queue: %u (%u/%u @ %p)\n", + _num_reports, _oldest_report, _next_report, _reports); + printf("dT/temp64: %d/%lld\n", _dT, _temp64); +} + +/** + * Local functions in support of the shell command. + */ +namespace +{ + +/* oddly, ERROR is not defined for c++ */ +#ifdef ERROR +# undef ERROR +#endif +const int ERROR = -1; + +MS5611 *g_dev; + +/* + * XXX this should just be part of the generic sensors test... + */ + + +int +test_fail(const char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, "FAIL: "); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + fflush(stderr); + return ERROR; +} + +int +test_note(const char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, "note: "); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + fflush(stderr); + return OK; +} + +/** + * Perform some basic functional tests on the driver; + * make sure we can collect data from the sensor in polled + * and automatic modes. + * + * @param fd An open file descriptor on the driver. + */ +int +test(int fd) +{ + struct baro_report report; + ssize_t sz; + int ret; + + + /* do a simple demand read */ + sz = read(fd, &report, sizeof(report)); + + if (sz != sizeof(report)) + return test_fail("immediate read failed: %d", errno); + + test_note("single read"); + test_note("pressure: %u", (unsigned)report.pressure); + test_note("altitude: %u", (unsigned)report.altitude); + test_note("temperature: %u", (unsigned)report.temperature); + test_note("time: %lld", report.timestamp); + usleep(1000000); + + /* set the queue depth to 10 */ + if (OK != ioctl(fd, BAROIOCSQUEUEDEPTH, 10)) + return test_fail("failed to set queue depth"); + + /* start the sensor polling at 2Hz */ + if (OK != ioctl(fd, BAROIOCSPOLLRATE, 2)) + return test_fail("failed to set 2Hz poll rate"); + + /* read the sensor 5x and report each value */ + for (unsigned i = 0; i < 5; i++) { + struct pollfd fds; + + /* wait for data to be ready */ + fds.fd = fd; + fds.events = POLLIN; + ret = poll(&fds, 1, 2000); + + if (ret != 1) + return test_fail("timed out waiting for sensor data"); + + /* now go get it */ + sz = read(fd, &report, sizeof(report)); + + if (sz != sizeof(report)) + return test_fail("periodic read failed: %d", errno); + + test_note("periodic read %u", i); + test_note("pressure: %u", (unsigned)report.pressure); + test_note("altitude: %u", (unsigned)report.altitude); + test_note("temperature: %u", (unsigned)report.temperature); + test_note("time: %lld", report.timestamp); + } + + return test_note("PASS"); + return OK; +} + +int +info() +{ + if (g_dev == nullptr) { + fprintf(stderr, "MS5611: driver not running\n"); + return -ENOENT; + } + + printf("state @ %p\n", g_dev); + g_dev->print_info(); + + return OK; +} + + +} // namespace + +int +ms5611_main(int argc, char *argv[]) +{ + /* + * Start/load the driver. + * + * XXX it would be nice to have a wrapper for this... + */ + if (!strcmp(argv[1], "start")) { + + if (g_dev != nullptr) { + fprintf(stderr, "MS5611: already loaded\n"); + return -EBUSY; + } + + /* create the driver */ + /* XXX HORRIBLE hack - the bus number should not come from here */ + g_dev = new MS5611(2); + + if (g_dev == nullptr) { + fprintf(stderr, "MS5611: driver alloc failed\n"); + return -ENOMEM; + } + + if (OK != g_dev->init()) { + fprintf(stderr, "MS5611: driver init failed\n"); + usleep(100000); + delete g_dev; + g_dev = nullptr; + return -EIO; + } + + return OK; + } + + /* + * Test the driver/device. + */ + if (!strcmp(argv[1], "test")) { + int fd, ret; + + fd = open(BARO_DEVICE_PATH, O_RDONLY); + + if (fd < 0) + return test_fail("driver open failed: %d", errno); + + ret = test(fd); + close(fd); + return ret; + } + + /* + * Print driver information. + */ + if (!strcmp(argv[1], "info")) + return info(); + + fprintf(stderr, "unrecognised command, try 'start', 'test' or 'info'\n"); + return -EINVAL; +} diff --git a/apps/examples/Kconfig b/apps/examples/Kconfig new file mode 100644 index 0000000000..a20f7c2e77 --- /dev/null +++ b/apps/examples/Kconfig @@ -0,0 +1,200 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +menu "ADC example" +source "$APPSDIR/examples/adc/Kconfig" +endmenu + +menu "Buttons example" +source "$APPSDIR/examples/buttons/Kconfig" +endmenu + +menu "CAN example" +source "$APPSDIR/examples/can/Kconfig" +endmenu + +menu "USB CDC/ACM class driver example" +source "$APPSDIR/examples/cdcacm/Kconfig" +endmenu + +menu "USB composite class driver example" +source "$APPSDIR/examples/composite/Kconfig" +endmenu + +menu "DHCP server example" +source "$APPSDIR/examples/dhcpd/Kconfig" +endmenu + +menu "FTP client example" +source "$APPSDIR/examples/ftpc/Kconfig" +endmenu + +menu "FTP server example" +source "$APPSDIR/examples/ftpd/Kconfig" +endmenu + +menu "\"Hello, World!\" example" +source "$APPSDIR/examples/hello/Kconfig" +endmenu + +menu "\"Hello, World!\" C++ example" +source "$APPSDIR/examples/helloxx/Kconfig" +endmenu + +menu "USB HID keyboard example" +source "$APPSDIR/examples/hidkbd/Kconfig" +endmenu + +menu "IGMP example" +source "$APPSDIR/examples/igmp/Kconfig" +endmenu + +menu "LCD read/write example" +source "$APPSDIR/examples/lcdrw/Kconfig" +endmenu + +menu "Memory management example" +source "$APPSDIR/examples/mm/Kconfig" +endmenu + +menu "File system mount example" +source "$APPSDIR/examples/mount/Kconfig" +endmenu + +menu "FreeModBus example" +source "$APPSDIR/examples/modbus/Kconfig" +endmenu + +menu "Network test example" +source "$APPSDIR/examples/nettest/Kconfig" +endmenu + +menu "NuttShell (NSH) example" +source "$APPSDIR/examples/nsh/Kconfig" +endmenu + +menu "NULL example" +source "$APPSDIR/examples/null/Kconfig" +endmenu + +menu "NX graphics example" +source "$APPSDIR/examples/nx/Kconfig" +endmenu + +menu "NxConsole example" +source "$APPSDIR/examples/nxconsole/Kconfig" +endmenu + +menu "NXFFS file system example" +source "$APPSDIR/examples/nxffs/Kconfig" +endmenu + +menu "NXFLAT example" +source "$APPSDIR/examples/nxflat/Kconfig" +endmenu + +menu "NX graphics \"Hello, World!\" example" +source "$APPSDIR/examples/nxhello/Kconfig" +endmenu + +menu "NX graphics image example" +source "$APPSDIR/examples/nximage/Kconfig" +endmenu + +menu "NX graphics lines example" +source "$APPSDIR/examples/nxlines/Kconfig" +endmenu + +menu "NX graphics text example" +source "$APPSDIR/examples/nxtext/Kconfig" +endmenu + +menu "OS test example" +source "$APPSDIR/examples/ostest/Kconfig" +endmenu + +menu "Pascal \"Hello, World!\"example" +source "$APPSDIR/examples/pashello/Kconfig" +endmenu + +menu "Pipe example" +source "$APPSDIR/examples/pipe/Kconfig" +endmenu + +menu "Poll example" +source "$APPSDIR/examples/poll/Kconfig" +endmenu + +menu "Pulse width modulation (PWM) example" +source "$APPSDIR/examples/pwm/Kconfig" +endmenu + +menu "Quadrature encoder example" +source "$APPSDIR/examples/qencoder/Kconfig" +endmenu + +menu "RGMP example" +source "$APPSDIR/examples/rgmp/Kconfig" +endmenu + +menu "ROMFS example" +source "$APPSDIR/examples/romfs/Kconfig" +endmenu + +menu "sendmail example" +source "$APPSDIR/examples/sendmail/Kconfig" +endmenu + +menu "Serial loopback example" +source "$APPSDIR/examples/serloop/Kconfig" +endmenu + +menu "Telnet daemon example" +source "$APPSDIR/examples/telnetd/Kconfig" +endmenu + +menu "THTTPD web server example" +source "$APPSDIR/examples/thttpd/Kconfig" +endmenu + +menu "TIFF generation example" +source "$APPSDIR/examples/tiff/Kconfig" +endmenu + +menu "Touchscreen example" +source "$APPSDIR/examples/touchscreen/Kconfig" +endmenu + +menu "UDP example" +source "$APPSDIR/examples/udp/Kconfig" +endmenu + +menu "uIP web server example" +source "$APPSDIR/examples/uip/Kconfig" +endmenu + +menu "USB serial test example" +source "$APPSDIR/examples/usbserial/Kconfig" +endmenu + +menu "USB mass storage class example" +source "$APPSDIR/examples/usbstorage/Kconfig" +endmenu + +menu "USB serial terminal example" +source "$APPSDIR/examples/usbterm/Kconfig" +endmenu + +menu "Watchdog timer example" +source "$APPSDIR/examples/watchdog/Kconfig" +endmenu + +menu "wget example" +source "$APPSDIR/examples/wget/Kconfig" +endmenu + +menu "WLAN example" +source "$APPSDIR/examples/wlan/Kconfig" +endmenu diff --git a/apps/examples/Make.defs b/apps/examples/Make.defs new file mode 100644 index 0000000000..aa8d83733b --- /dev/null +++ b/apps/examples/Make.defs @@ -0,0 +1,223 @@ +############################################################################ +# apps/examples/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_EXAMPLES_ADC),y) +CONFIGURED_APPS += examples/adc +endif + +ifeq ($(CONFIG_EXAMPLES_BUTTONS),y) +CONFIGURED_APPS += examples/buttons +endif + +ifeq ($(CONFIG_EXAMPLES_CAN),y) +CONFIGURED_APPS += examples/can +endif + +ifeq ($(CONFIG_EXAMPLES_CDCACM),y) +CONFIGURED_APPS += examples/cdcacm +endif + +ifeq ($(CONFIG_EXAMPLES_COMPOSITE),y) +CONFIGURED_APPS += examples/composite +endif + +ifeq ($(CONFIG_EXAMPLES_DHCPD),y) +CONFIGURED_APPS += examples/dhcpd +endif + +ifeq ($(CONFIG_EXAMPLES_FTPC),y) +CONFIGURED_APPS += examples/ftpc +endif + +ifeq ($(CONFIG_EXAMPLES_FTPD),y) +CONFIGURED_APPS += examples/ftpd +endif + +ifeq ($(CONFIG_EXAMPLES_HELLO),y) +CONFIGURED_APPS += examples/hello +endif + +ifeq ($(CONFIG_EXAMPLES_HELLOXX),y) +CONFIGURED_APPS += examples/helloxx +endif + +ifeq ($(CONFIG_EXAMPLES_HIDKBD),y) +CONFIGURED_APPS += examples/hidkbd +endif + +ifeq ($(CONFIG_EXAMPLES_IGMP),y) +CONFIGURED_APPS += examples/igmp +endif + +ifeq ($(CONFIG_EXAMPLES_LCDRW),y) +CONFIGURED_APPS += examples/lcdrw +endif + +ifeq ($(CONFIG_EXAMPLES_MM),y) +CONFIGURED_APPS += examples/mm +endif + +ifeq ($(CONFIG_EXAMPLES_MOUNT),y) +CONFIGURED_APPS += examples/mount +endif + +ifeq ($(CONFIG_EXAMPLES_NETTEST),y) +CONFIGURED_APPS += examples/nettest +endif + +ifeq ($(CONFIG_EXAMPLES_NSH),y) +CONFIGURED_APPS += examples/nsh +endif + +ifeq ($(CONFIG_EXAMPLES_NULL),y) +CONFIGURED_APPS += examples/null +endif + +ifeq ($(CONFIG_EXAMPLES_NX),y) +CONFIGURED_APPS += examples/nx +endif + +ifeq ($(CONFIG_EXAMPLES_NXCONSOLE),y) +CONFIGURED_APPS += examples/nxconsole +endif + +ifeq ($(CONFIG_EXAMPLES_NXFFS),y) +CONFIGURED_APPS += examples/nxffs +endif + +ifeq ($(CONFIG_EXAMPLES_NXFLAT),y) +CONFIGURED_APPS += examples/nxflat +endif + +ifeq ($(CONFIG_EXAMPLES_NXHELLO),y) +CONFIGURED_APPS += examples/nxhello +endif + +ifeq ($(CONFIG_EXAMPLES_NXIMAGE),y) +CONFIGURED_APPS += examples/nximage +endif + +ifeq ($(CONFIG_EXAMPLES_NXLINES),y) +CONFIGURED_APPS += examples/nxlines +endif + +ifeq ($(CONFIG_EXAMPLES_NXTEXT),y) +CONFIGURED_APPS += examples/nxtext +endif + +ifeq ($(CONFIG_EXAMPLES_OSTEST),y) +CONFIGURED_APPS += examples/ostest +endif + +ifeq ($(CONFIG_EXAMPLES_PASHELLO),y) +CONFIGURED_APPS += examples/pashello +endif + +ifeq ($(CONFIG_EXAMPLES_PIPE),y) +CONFIGURED_APPS += examples/pipe +endif + +ifeq ($(CONFIG_EXAMPLES_POLL),y) +CONFIGURED_APPS += examples/poll +endif + +ifeq ($(CONFIG_EXAMPLES_PWM),y) +CONFIGURED_APPS += examples/pwm +endif + +ifeq ($(CONFIG_EXAMPLES_QENCODER),y) +CONFIGURED_APPS += examples/qencoder +endif + +ifeq ($(CONFIG_EXAMPLES_RGMP),y) +CONFIGURED_APPS += examples/rgmp +endif + +ifeq ($(CONFIG_EXAMPLES_ROMFS),y) +CONFIGURED_APPS += examples/romfs +endif + +ifeq ($(CONFIG_EXAMPLES_SENDMAIL),y) +CONFIGURED_APPS += examples/sendmail +endif + +ifeq ($(CONFIG_EXAMPLES_SERLOOP),y) +CONFIGURED_APPS += examples/serloop +endif + +ifeq ($(CONFIG_EXAMPLES_TELNETD),y) +CONFIGURED_APPS += examples/telnetd +endif + +ifeq ($(CONFIG_EXAMPLES_THTTPD),y) +CONFIGURED_APPS += examples/thttpd +endif + +ifeq ($(CONFIG_EXAMPLES_TIFF),y) +CONFIGURED_APPS += examples/tiff +endif + +ifeq ($(CONFIG_EXAMPLES_TOUCHSCREEN),y) +CONFIGURED_APPS += examples/touchscreen +endif + +ifeq ($(CONFIG_EXAMPLES_UDP),y) +CONFIGURED_APPS += examples/udp +endif + +ifeq ($(CONFIG_EXAMPLES_UIP),y) +CONFIGURED_APPS += examples/uip +endif + +ifeq ($(CONFIG_EXAMPLES_USBSERIAL),y) +CONFIGURED_APPS += examples/usbserial +endif + +ifeq ($(CONFIG_EXAMPLES_USBMSC),y) +CONFIGURED_APPS += examples/usbmsc +endif + +ifeq ($(CONFIG_EXAMPLES_USBTERM),y) +CONFIGURED_APPS += examples/usbterm +endif + +ifeq ($(CONFIG_EXAMPLES_WGET),y) +CONFIGURED_APPS += examples/wget +endif + +ifeq ($(CONFIG_EXAMPLES_WLAN),y) +CONFIGURED_APPS += examples/wlan +endif diff --git a/apps/examples/Makefile b/apps/examples/Makefile new file mode 100644 index 0000000000..ad5be64978 --- /dev/null +++ b/apps/examples/Makefile @@ -0,0 +1,129 @@ +############################################################################ +# apps/examples/Makefile +# +# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config # Current configuration + +# Sub-directories + +SUBDIRS = adc buttons can cdcacm composite dhcpd ftpc ftpd hello helloxx \ + hidkbd igmp lcdrw mm modbus mount nettest nsh null nx nxconsole nxffs \ + nxflat nxhello nximage nxlines nxtext ostest pashello pipe poll pwm \ + qencoder rgmp romfs serloop telnetd thttpd tiff touchscreen udp uip \ + usbserial sendmail usbstorage usbterm watchdog wget wlan + +# Sub-directories that might need context setup. Directories may need +# context setup for a variety of reasons, but the most common is because +# the example may be built as an NSH built-in function. +# +# Directories that may be built as NSH built-in functions may have their +# own configuration setting (like CONFIG_EXAMPLES_HELLOXX_BUILTIN), but +# many only depend on the generic CONFIG_NSH_BUILTIN_APPS setting. And +# there a few which an ONLY be built as NSH built-in applications; these +# are included in the list unconditionally. + +CNTXTDIRS = pwm + +ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) +CNTXTDIRS += adc can cdcacm composite ftpd dhcpd modbus nettest qencoder telnetd watchdog +endif + +ifeq ($(CONFIG_EXAMPLES_HELLO_BUILTIN),y) +CNTXTDIRS += hello +endif +ifeq ($(CONFIG_EXAMPLES_HELLOXX_BUILTIN),y) +CNTXTDIRS += helloxx +endif +ifeq ($(CONFIG_EXAMPLES_LCDRW_BUILTIN),y) +CNTXTDIRS += lcdrw +endif +ifeq ($(CONFIG_EXAMPLES_NX_BUILTIN),y) +CNTXTDIRS += nx +endif +ifeq ($(CONFIG_EXAMPLES_NXHELLO_BUILTIN),y) +CNTXTDIRS += nxhello +endif +ifeq ($(CONFIG_EXAMPLES_NXIMAGE_BUILTIN),y) +CNTXTDIRS += nximage +endif +ifeq ($(CONFIG_EXAMPLES_LINES_BUILTIN),y) +CNTXTDIRS += nxlines +endif +ifeq ($(CONFIG_EXAMPLES_NXTEXT_BUILTIN),y) +CNTXTDIRS += nxtext +endif +ifeq ($(CONFIG_EXAMPLES_OSTEST_BUILTIN),y) +CNTXTDIRS += ostest +endif +ifeq ($(CONFIG_EXAMPLES_TIFF_BUILTIN),y) +CNTXTDIRS += tiff +endif +ifeq ($(CONFIG_EXAMPLES_TOUCHSCREEN_BUILTIN),y) +CNTXTDIRS += touchscreen +endif +ifeq ($(CONFIG_EXAMPLES_USBMSC_BUILTIN),y) +CNTXTDIRS += usbstorage +endif +ifeq ($(CONFIG_EXAMPLES_USBTERM_BUILTIN),y) +CNTXTDIRS += usbterm +endif + +all: nothing + +.PHONY: nothing context depend clean distclean + +nothing: + +context: + @for dir in $(CNTXTDIRS) ; do \ + $(MAKE) -C $$dir context TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + +depend: + @for dir in $(SUBDIRS) ; do \ + $(MAKE) -C $$dir depend TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + +clean: + @for dir in $(SUBDIRS) ; do \ + $(MAKE) -C $$dir clean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + +distclean: clean + @for dir in $(SUBDIRS) ; do \ + $(MAKE) -C $$dir distclean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + +-include Make.dep + diff --git a/apps/examples/README.txt b/apps/examples/README.txt new file mode 100644 index 0000000000..7d068f9794 --- /dev/null +++ b/apps/examples/README.txt @@ -0,0 +1,1649 @@ +examples +^^^^^^^^ + + appconfig and CONFIG_APPS + + The examples directory contains several sample applications that + can be linked with NuttX. The specific example is selected in the + configs//appconfig file via the CONFIGURED_APPS setting. + This setting provides the path to the directory containing the + application Makefile (this path is a relative to the apps/ top- + level directory). For example, + + CONFIGURE_APPS += examples/ostest + + Selects the examples/ostest example. + + Built-In functions + + Some of the examples may be built as "built-in" functions that + can be executed at run time (rather than as NuttX "main" programs). + These "built-in" examples can be also be executed from the NuttShell + (NSH) command line. In order to configure these built-in NSH + functions, you have to set up the following: + + - CONFIG_NSH_BUILTIN_APPS - Enable support for external registered, + "named" applications that can be executed from the NSH + command line (see apps/README.txt for more information). + - CONFIG_EXAMPLES_XYZ_BUILTIN -- Build the XYZ example as a "built-in" + that can be executed from the NSH command line (where XYZ is + the specific example. See the following for examples that + support this option). + +examples/adc +^^^^^^^^^^^^ + + A mindlessly simple test of an ADC devices. It simply reads from the + ADC device and dumps the data to the console forever. + + This test depends on these specific ADC/NSH configurations settings (your + specific ADC settings might require additional settings). + + CONFIG_ADC - Enabled ADC support + CONFIG_NSH_BUILTIN_APPS - Build the ADC test as an NSH built-in function. + Default: Built as a standalone problem + + Specific configuration options for this example include: + + CONFIG_EXAMPLES_ADC_DEVPATH - The default path to the ADC device. Default: /dev/adc0 + CONFIG_EXAMPLES_ADC_NSAMPLES - If CONFIG_NSH_BUILTIN_APPS + is defined, then the number of samples is provided on the command line + and this value is ignored. Otherwise, this number of samples is + collected and the program terminates. Default: Samples are collected + indefinitely. + CONFIG_EXAMPLES_ADC_GROUPSIZE - The number of samples to read at once. + Default: 4 + +examples/buttons +^^^^^^^^^^^^^^^^ + + This is a simple configuration that may be used to test the board- + specific button interfaces. Configuration options: + + CONFIG_ARCH_BUTTONS - Must be defined for button support + CONFIG_EXAMPLE_BUTTONS_MIN - Lowest button number (MIN=0) + CONFIG_EXAMPLE_BUTTONS_MAX - Highest button number (MAX=7) + + CONFIG_ARCH_IRQBUTTONS - Must be defined for interrupting button support + CONFIG_EXAMPLE_IRQBUTTONS_MIN - Lowest interrupting button number (MIN=0) + CONFIG_EXAMPLE_IRQBUTTONS_MAX - Highest interrupting button number (MAX=7) + + Name strings for buttons: + + CONFIG_EXAMPLE_BUTTONS_NAME0, CONFIG_EXAMPLE_BUTTONS_NAME1, + CONFIG_EXAMPLE_BUTTONS_NAME2, CONFIG_EXAMPLE_BUTTONS_NAME3, + CONFIG_EXAMPLE_BUTTONS_NAME4, CONFIG_EXAMPLE_BUTTONS_NAME5, + CONFIG_EXAMPLE_BUTTONS_NAME6, CONFIG_EXAMPLE_BUTTONS_NAME7, + + Additional architecture-/board- specific configuration settings may also + be required. + + NOTE: This test exercises internal button driver interfaces. As such, it + relies on internal OS interfaces that are not normally available to a + user-space program. As a result, this example cannot be used if a + NuttX is built as a protected, supervisor kernel (CONFIG_NUTTX_KERNEL). + +examples/can +^^^^^^^^^^^^ + + If the CAN device is configured in loopback mode, then this example can + be used to test the CAN device in loop back mode. It simple sinces a + sequence of CAN messages and verifies that those messages are returned + exactly as sent. + + This test depends on these specific CAN/NSH configurations settings (your + specific CAN settings might require additional settings). + + CONFIG_CAN - Enables CAN support. + CONFIG_CAN_LOOPBACK - A CAN driver may or may not support a loopback + mode for testing. The STM32 CAN driver does support loopback mode. + CONFIG_NSH_BUILTIN_APPS - Build the CAN test as an NSH built-in function. + Default: Built as a standalone problem + + Specific configuration options for this example include: + + CONFIG_EXAMPLES_CAN_DEVPATH - The path to the CAN device. Default: /dev/can0 + CONFIG_EXAMPLES_CAN_NMSGS - If CONFIG_NSH_BUILTIN_APPS + is defined, then the number of loops is provided on the command line + and this value is ignored. Otherwise, this number of CAN message is + collected and the program terminates. Default: If built as an NSH + built-in, the default is 32. Otherwise messages are sent and received + indefinitely. + + The default behavior assumes loopback mode. Messages are sent, then read + and verified. The behavior can be altered for other kinds of testing where + the test only sends or received (but does not verify) can messages. + + CONFIG_EXAMPLES_CAN_READONLY - Only receive messages + CONFIG_EXAMPLES_CAN_WRITEONLY - Only send messages + +examples/cdcacm +^^^^^^^^^^^^^^^ + + This very simple example shows how a USB CDC/ACM serial can be dynamically + connected and disconnected from a host. This example can only be used as + an NSH built-int command. If built-in, then two new NSH commands will be + supported: + + 1. sercon - Connect the CDC/ACM serial device + 2. serdis - Disconnect the CDC/ACM serial device + + Configuration prequisites (not complete): + + CONFIG_USBDEV=y : USB device support must be enabled + CONFIG_CDCACM=y : The CDC/ACM driver must be built + CONFIG_NSH_BUILTIN_APPS : NSH built-in application support must be enabled + + Configuration options specific to this example: + + CONFIG_EXAMPLES_CDCACM_DEVMINOR : The minor number of the CDC/ACM device. + : i.e., the 'x' in /dev/ttyACMx + + If CONFIG_USBDEV_TRACE is enabled (or CONFIG_DEBUG and CONFIG_DEBUG_USB, or + CONFIG_USBDEV_TRACE), then the example code will also initialize the USB trace + output. The amount of trace output can be controlled using: + + CONFIG_EXAMPLES_CDCACM_TRACEINIT + Show initialization events + CONFIG_EXAMPLES_CDCACM_TRACECLASS + Show class driver events + CONFIG_EXAMPLES_CDCACM_TRACETRANSFERS + Show data transfer events + CONFIG_EXAMPLES_CDCACM_TRACECONTROLLER + Show controller events + CONFIG_EXAMPLES_CDCACM_TRACEINTERRUPTS + Show interrupt-related events. + + Note: This example is only enables or disable USB CDC/ACM via the NSH + 'sercon' and 'serdis' command. It will enable and disable tracing per + the settings before enabling and after disabling the CDC/ACM device. It + will not, however, monitor buffered trace data in the interim. If + CONFIG_USBDEV_TRACE is defined (and the debug options are not), other + application logic will need to monitor the buffered trace data. + +examples/composite +^^^^^^^^^^^^^^^^^^ + + This example test a USB composite device. The only supported composite is + CDC/ACM serial with a USB mass storage device. + + Required overall configuration: + + CONFIG_USBDEV=y - USB device support + CONFIG_USBDEV_COMPOSITE=y - USB composite device support + CONFIG_COMPOSITE_IAD=y - Interface associate descriptor needed + + CONFIG_CDCACM=y - USB CDC/ACM serial device support + CONFIG_CDCACM_COMPOSITE=y - USB CDC/ACM serial composite device support + CONFIG_CDCACM_IFNOBASE=0 - CDC/ACM interfaces start with number 0 + CONFIG_CDCACM_STRBASE=4 - Base of string numbers (not really needed) + CONFIG_CDCACM_EPINTIN=1 - Endpoint numbers must be unique + CONFIG_CDCACM_EPBULKIN=2 + CONFIG_CDCACM_EPBULKOUT=3 + + CONFIG_USBMSC - USB mass storage device support + CONFIG_USBMSC_COMPOSITE=y - USB mass storage composite device support + CONFIG_USBMSC_IFNOBASE=2 - USB mass storage interfaces start with number 2 + CONFIG_USBMSC_STRBASE=4 - Base of string numbers (needed) + CONFIG_USBMSC_EPBULKOUT=4 - Endpoint numbers must be unique + CONFIG_USBMSC_EPBULKIN=5 + + CONFIG_NSH_BUILTIN_APPS + This example can be built as two NSH "built-in" commands if this option + is selected: 'conn' will connect the USB composite device; 'msdis' + will disconnect the USB composite device. + + Configuration options unique to this example: + + CONFIG_EXAMPLES_COMPOSITE_DEBUGMM + Enables some debug tests to check for memory usage and memory leaks. + + CONFIG_EXAMPLES_COMPOSITE_NLUNS + Defines the number of logical units (LUNs) exported by the USB storage + driver. Each LUN corresponds to one exported block driver (or partition + of a block driver). May be 1, 2, or 3. Default is 1. + CONFIG_EXAMPLES_COMPOSITE_DEVMINOR1 + The minor device number of the block driver for the first LUN. For + example, N in /dev/mmcsdN. Used for registering the block driver. Default + is zero. + CONFIG_EXAMPLES_COMPOSITE_DEVPATH1 + The full path to the registered block driver. Default is "/dev/mmcsd0" + CONFIG_EXAMPLES_COMPOSITE_DEVMINOR2 and CONFIG_EXAMPLES_COMPOSITE_DEVPATH2 + Similar parameters that would have to be provided if CONFIG_EXAMPLES_COMPOSITE_NLUNS + is 2 or 3. No defaults. + CONFIG_EXAMPLES_COMPOSITE_DEVMINOR3 and CONFIG_EXAMPLES_COMPOSITE_DEVPATH2 + Similar parameters that would have to be provided if CONFIG_EXAMPLES_COMPOSITE_NLUNS + is 3. No defaults. + CONFIG_EXAMPLES_COMPOSITE_BUFLEN. Default 256. + + CONFIG_EXAMPLES_COMPOSITE_TTYUSB - The minor number of the USB serial device. + Default is zero (corresponding to /dev/ttyUSB0 or /dev/ttyACM0). Default is zero. + CCONFIG_EXAMPLES_COMPOSITE_SERDEV - The string corresponding to + CONFIG_EXAMPLES_COMPOSITE_TTYUSB. The default is "/dev/ttyUSB0" (for the PL2303 + emulation) or "/dev/ttyACM0" (for the CDC/ACM serial device). + CONFIG_EXAMPLES_COMPOSITE_BUFSIZE - The size of the serial I/O buffer in + bytes. Default 256 bytes. + + If CONFIG_USBDEV_TRACE is enabled (or CONFIG_DEBUG and CONFIG_DEBUG_USB), then + the example code will also manage the USB trace output. The amount of trace output + can be controlled using: + + CONFIG_EXAMPLES_COMPOSITE_TRACEINIT + Show initialization events + CONFIG_EXAMPLES_COMPOSITE_TRACECLASS + Show class driver events + CONFIG_EXAMPLES_COMPOSITE_TRACETRANSFERS + Show data transfer events + CONFIG_EXAMPLES_COMPOSITE_TRACECONTROLLER + Show controller events + CONFIG_EXAMPLES_COMPOSITE_TRACEINTERRUPTS + Show interrupt-related events. + +examples/dhcpd +^^^^^^^^^^^^^^ + + This examples builds a tiny DCHP server for the target system. + + NOTE: For test purposes, this example can be built as a + host-based DHCPD server. This can be built as follows: + + cd examples/dhcpd + make -f Makefile.host TOPDIR= + + NuttX configuration settings: + + CONFIG_NET=y - Of course + CONFIG_NSOCKET_DESCRIPTORS - And, of course, you must allocate some + socket descriptors. + CONFIG_NET_UDP=y - UDP support is required for DHCP + (as well as various other UDP-related + configuration settings) + CONFIG_NET_BROADCAST=y - UDP broadcast support is needed. + + CONFIG_EXAMPLE_DHCPD_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLE_DHCPD_IPADDR - Target IP address + CONFIG_EXAMPLE_DHCPD_DRIPADDR - Default router IP addess + CONFIG_EXAMPLE_DHCPD_NETMASK - Network mask + + See also CONFIG_NETUTILS_DHCPD_* settings described elsewhere + and used in netutils/dhcpd/dhcpd.c. These settings are required + to described the behavior of the daemon. + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + +examples/ftpc +^^^^^^^^^^^^^ + + This is a simple FTP client shell used to exercise the capabilities + of the FTPC library (apps/netutils/ftpc). This example is configured + to that it will only work as a "built-in" program that can be run from + NSH when CONFIG_NSH_BUILTIN_APPS is defined. + + From NSH, the startup command sequence is as follows. This is only + an example, your configration could have different mass storage devices, + mount paths, and FTP directories: + + nsh> mount -t vfat /dev/mmcsd0 /tmp # Mount the SD card at /tmp + nsh> cd /tmp # cd into the /tmp directory + nsh> ftpc xx.xx.xx.xx[:pp] # Start the FTP client + nfc> login # Log into the FTP server + nfc> help # See a list of FTP commands + + where xx.xx.xx.xx is the IP address of the FTP server and pp is an + optional port number. + + NOTE: By default, FTPC uses readline to get data from stdin. So your + appconfig file must have the following build path: + + CONFIGURED_APPS += system/readline + + NOTE: If you use the ftpc task over a telnet NSH connection, then you + should set the following configuration item: + + CONFIG_EXAMPLES_FTPC_FGETS=y + + By default, the FTPC client will use readline() to get characters from + the console. Readline includes and command-line editor and echos + characters received in stdin back through stdout. Neither of these + behaviors are desire-able if Telnet is used. + + You may also want to define the following in your configuration file. + Otherwise, you will have not feeback about what is going on: + + CONFIG_DEBUG=y + CONFIG_DEBUG_VERBOSE=y + CONFIG_DEBUG_FTPC=y + +examples/ftpd +^^^^^^^^^^^^^^ + + This example exercises the FTPD daemon at apps/netuils/ftpd. Below are + configurations specific to the FTPD example (the FTPD daemon itself may + require other configuration options as well). + + CONFIG_EXAMPLES_FTPD_PRIO - Priority of the FTP daemon. + Default: SCHED_PRIORITY_DEFAULT + CONFIG_EXAMPLES_FTPD_STACKSIZE - Stack size allocated for the + FTP daemon. Default: 2048 + CONFIG_EXAMPLES_FTPD_NONETINIT - Define to suppress configuration of the + network by apps/examples/ftpd. You would need to suppress network + configuration if the network is configuration prior to running the + example. + + NSH always initializes the network so if CONFIG_NSH_BUILTIN_APPS is + defined, so is CONFIG_EXAMPLES_FTPD_NONETINIT (se it does not explicitly + need to be defined in that case): + + CONFIG_NSH_BUILTIN_APPS - Build the FTPD daemon example test as an + NSH built-in function. By default the FTPD daemon will be built + as a standalone application. + + If CONFIG_EXAMPLES_FTPD_NONETINIT is not defined, then the following may + be specified to customized the network configuration: + + CONFIG_EXAMPLE_FTPD_NOMAC - If the hardware has no MAC address of its + own, define this =y to provide a bogus address for testing. + CONFIG_EXAMPLE_FTPD_IPADDR - The target IP address. Default 10.0.0.2 + CONFIG_EXAMPLE_FTPD_DRIPADDR - The default router address. Default + 10.0.0.1 + CONFIG_EXAMPLE_FTPD_NETMASK - The network mask. Default: 255.255.255.0 + + Other required configuration settings: Of course TCP networking support + is required. But here are a couple that are less obvious: + + CONFIG_DISABLE_PTHREAD - pthread support is required + CONFIG_DISABLE_POLL - poll() support is required + + Other FTPD configuration options thay may be of interest: + + CONFIG_FTPD_VENDORID - The vendor name to use in FTP communications. + Default: "NuttX" + CONFIG_FTPD_SERVERID - The server name to use in FTP communications. + Default: "NuttX FTP Server" + CONFIG_FTPD_CMDBUFFERSIZE - The maximum size of one command. Default: + 512 bytes. + CONFIG_FTPD_DATABUFFERSIZE - The size of the I/O buffer for data + transfers. Default: 2048 bytes. + CONFIG_FTPD_WORKERSTACKSIZE - The stacksize to allocate for each + FTP daemon worker thread. Default: 2048 bytes. + + The appconfig file (apps/.config) should include: + + CONFIGURED_APPS += examples/ftpd + CONFIGURED_APPS += netutils/uiplib + CONFIGURED_APPS += netutils/ftpd + +examples/hello +^^^^^^^^^^^^^^ + + This is the mandatory, "Hello, World!!" example. It is little more + than examples/null with a single printf statement. Really useful only + for bringing up new NuttX architectures. + + * CONFIG_EXAMPLES_HELLO_BUILTIN + Build the "Hello, World" example as an NSH built-in application. + +examples/helloxx +^^^^^^^^^^^^^^^^ + + This is C++ version of the "Hello, World!!" example. It is intended + only to verify that the C++ compiler is functional, that basic C++ + library suupport is available, and that class are instantiated + correctly. + + NuttX configuration prerequisites: + + CONFIG_HAVE_CXX -- Enable C++ Support + + Optional NuttX configuration settings: + + CONFIG_HAVE_CXXINITIALIZE -- Enable support for static constructors + (may not be available on all platforms). + + NuttX configuration settings specific to this examp;le: + + CONFIG_EXAMPLES_HELLOXX_BUILTIN -- Build the helloxx example as a + "built-in" that can be executed from the NSH command line. + CONFIG_EXAMPLES_HELLOXX_NOSTACKCONST - Set if the system does not + support construction of objects on the stack. + + Also needed: + + CONFIG_HAVE_CXX=y + + And you may have to tinker with the following to get libxx to compile + properly: + + CONFIG_CXX_NEWLONG=y or =n + + The argument of the 'new' operators should take a type of size_t. But size_t + has an unknown underlying. In the nuttx sys/types.h header file, size_t + is typed as uint32_t (which is determined by architecture-specific logic). + But the C++ compiler may believe that size_t is of a different type resulting + in compilation errors in the operator. Using the underlying integer type + Instead of size_t seems to resolve the compilation issues. + +examples/hidkbd +^^^^^^^^^^^^^^^^ + + This is a simple test to debug/verify the USB host HID keyboard class + driver. + + CONFIG_EXAMPLES_HIDKBD_DEFPRIO - Priority of "waiter" thread. + CONFIG_EXAMPLES_HIDKBD_STACKSIZE - Stacksize of "waiter" thread. + +examples/igmp +^^^^^^^^^^^^^ + + This is a trivial test of the NuttX IGMP capability. It present it + does not do much of value -- Much more is needed in order to verify + the IGMP features! + + * CONFIG_EXAMPLE_IGMP_NOMAC + Set if the hardware has no MAC address; one will be assigned + * CONFIG_EXAMPLE_IGMP_IPADDR + Target board IP address + * CONFIG_EXAMPLE_IGMP_DRIPADDR + Default router address + * CONFIG_EXAMPLE_IGMP_NETMASK + Network mask + * CONFIG_EXAMPLE_IGMP_GRPADDR + Multicast group address + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + +examples/lcdrw +^^^^^^^^^^^^^^ + + This example may be used to verify if you can or cannot read data + correctly from an LCD interface. At present, this supports only LCDs + with RGB565 color format. + + * CONFIG_EXAMPLES_LDCRW_DEVNO + LCD device number. Default: 0 + * CONFIG_EXAMPLES_LDCRW_XRES + LCD X resolution. Default: 240 + * CONFIG_EXAMPLES_LDCRW_YRES + LCD Y resolution. Default: 320 + +examples/mm +^^^^^^^^^^^ + + This is a simplified version of the "built-in" memory manager test of + mm/mm_test.c. It is simplified because it does not have access to the + internals of the memory manager as does mm/mm_test.c, but it has the + advantage that it runs in the actual NuttX tasking environment (the + mm/mm_test.c only runs in a PC simulation environment). + +examples/modbus +^^^^^^^^^^^^^^^ + + This is a port of the FreeModbus Linux demo. It derives from the + demos/LINUX directory of the FreeModBus version 1.5.0 (June 6, 2010) + that can be downloaded in its entirety from http://developer.berlios.de/project/showfiles.php?group_id=6120. + + CONFIG_EXAMPLES_MODBUS_PORT, Default 0 (for /dev/ttyS0) + CONFIG_EXAMPLES_MODBUS_BAUD, Default B38400 + CONFIG_EXAMPLES_MODBUS_PARITY, Default MB_PAR_EVEN + + CONFIG_EXAMPLES_MODBUS_REG_INPUT_START, Default 1000 + CONFIG_EXAMPLES_MODBUS_REG_INPUT_NREGS, Default 4 + CONFIG_EXAMPLES_MODBUS_REG_HOLDING_START, Default 2000 + CONFIG_EXAMPLES_MODBUS_REG_HOLDING_NREGS, Default 130 + + The FreeModBus library resides at apps/modbus. See apps/modbus/README.txt + for additional configuration information. + +examples/mount +^^^^^^^^^^^^^^ + + This contains a simple test of filesystem mountpoints. + + * CONFIG_EXAMPLES_MOUNT_DEVNAME + The name of the user-provided block device to mount. + If CONFIG_EXAMPLES_MOUNT_DEVNAME is not provided, then + a RAM disk will be configured. + + * CONFIG_EXAMPLES_MOUNT_NSECTORS + The number of "sectors" in the RAM disk used when + CONFIG_EXAMPLES_MOUNT_DEVNAME is not defined. + + * CONFIG_EXAMPLES_MOUNT_SECTORSIZE + The size of each sectors in the RAM disk used when + CONFIG_EXAMPLES_MOUNT_DEVNAME is not defined. + + * CONFIG_EXAMPLES_MOUNT_RAMDEVNO + The RAM device minor number used to mount the RAM disk used + when CONFIG_EXAMPLES_MOUNT_DEVNAME is not defined. The + default is zero (meaning that "/dev/ram0" will be used). + +examples/netttest +^^^^^^^^^^^^^^^^^ + + This is a simple network test for verifying client- and server- + functionality in a TCP/IP connection. + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + +examples/nsh +^^^^^^^^^^^^ + + This directory provides an example of how to configure and use + the NuttShell (NSH) application. NSH is a simple shell + application. NSH is described in its own README located at + apps/nshlib/README.txt + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += nshlib + + NOTE: If the NSH serial console is used, then following is also + required to build the readline() library: + + CONFIGURED_APPS += system/readline + + And if networking is included: + + CONFIGURED_APPS += uiplib + CONFIGURED_APPS += dhcpc + CONFIGURED_APPS += resolv + CONFIGURED_APPS += tftp + CONFIGURED_APPS += webclient + + If the Telnet console is enabled, then the appconfig file (apps/.config) + should also include: + + CONFIGURED_APPS += netutils/telnetd + + Also if the Telnet console is enabled, make sure that you have the + following set in the NuttX configuration file or else the performance + will be very bad (because there will be only one character per TCP + transfer): + + CONFIG_STDIO_BUFFER_SIZE - Some value >= 64 + CONFIG_STDIO_LINEBUFFER=y + +examples/nx +^^^^^^^^^^^ + + This directory contains a simple test of a subset of the NX APIs + defined in include/nuttx/nx/nx.h. The following configuration options + can be selected: + + CONFIG_EXAMPLES_NX_BUILTIN -- Build the NX example as a "built-in" + that can be executed from the NSH command line + CONFIG_EXAMPLES_NX_VPLANE -- The plane to select from the frame- + buffer driver for use in the test. Default: 0 + CONFIG_EXAMPLES_NX_DEVNO - The LCD device to select from the LCD + driver for use in the test: Default: 0 + CONFIG_EXAMPLES_NX_BGCOLOR -- The color of the background. Default depends on + CONFIG_EXAMPLES_NX_BPP. + CONFIG_EXAMPLES_NX_COLOR1 -- The color of window 1. Default depends on + CONFIG_EXAMPLES_NX_BPP. + CONFIG_EXAMPLES_NX_COLOR2 -- The color of window 2. Default depends on + CONFIG_EXAMPLES_NX_BPP. + CONFIG_EXAMPLES_NX_TBCOLOR -- The color of the toolbar. Default depends on + CONFIG_EXAMPLES_NX_BPP. + CONFIG_EXAMPLES_NX_FONTID - Selects the font (see font ID numbers in + include/nuttx/nx/nxfonts.h) + CONFIG_EXAMPLES_NX_FONTCOLOR -- The color of the fonts. Default depends on + CONFIG_EXAMPLES_NX_BPP. + CONFIG_EXAMPLES_NX_BPP -- Pixels per pixel to use. Valid options + include 2, 4, 8, 16, 24, and 32. Default is 32. + CONFIG_EXAMPLES_NX_RAWWINDOWS -- Use raw windows; Default is to + use pretty, framed NXTK windows with toolbars. + CONFIG_EXAMPLES_NX_EXTERNINIT - The driver for the graphics device on + this platform requires some unusual initialization. This is the + for, for example, SPI LCD/OLED devices. If this configuration is + selected, then the platform code must provide an LCD initialization + function with a prototype like: + + #ifdef CONFIG_NX_LCDDRIVER + FAR struct lcd_dev_s *up_nxdrvinit(unsigned int devno); + #else + FAR struct fb_vtable_s *up_nxdrvinit(unsigned int devno); + #endif + + This test can be performed with either the single-user version of + NX or with the multiple user version of NX selected with CONFIG_NX_MULTIUSER. + If CONFIG_NX_MULTIUSER is defined, then the following configuration + options also apply: + + CONFIG_EXAMPLES_NX_STACKSIZE -- The stacksize to use when creating + the NX server. Default 2048 + CONFIG_EXAMPLES_NX_CLIENTPRIO -- The client priority. Default: 100 + CONFIG_EXAMPLES_NX_SERVERPRIO -- The server priority. Default: 120 + CONFIG_EXAMPLES_NX_LISTENERPRIO -- The priority of the event listener + thread. Default 80. + CONFIG_EXAMPLES_NX_NOTIFYSIGNO -- The signal number to use with + nx_eventnotify(). Default: 4 + + If CONFIG_NX_MULTIUSER is defined, then the example also expects the + following settings and will generate an error if they are not as expected: + + CONFIG_DISABLE_MQUEUE=n + CONFIG_DISABLE_SIGNALS=n + CONFIG_DISABLE_PTHREAD=n + CONFIG_NX_BLOCKING=y + +examples/nxconsole +^^^^^^^^^^^^^^^^^^ + + This directory contains yet another version of the NuttShell (NSH). This + version uses the NX console device defined in include/nuttx/nx/nxconsole.h + for output. the result is that the NSH input still come from the standard + console input (probably a serial console). But the text output will go to + an NX winbdow. Prerequisite configuration settings for this test include: + + CONFIG_NX=y -- NX graphics must be enabled + CONFIG_NXCONSOLE=y -- The NX console driver must be built + CONFIG_NX_MULTIUSER=y -- NX multi-user support must be enabled. + CONFIG_DISABLE_MQUEUE=n -- Message queue support must be available. + CONFIG_DISABLE_SIGNALS=n -- Signals are needed + CONFIG_DISABLE_PTHREAD=n -- pthreads are needed + CONFIG_NX_BLOCKING=y -- pthread APIs must be blocking + CONFIG_NSH_CONSOLE=y -- NSH must be configured to use a console. + + The following configuration options can be selected to customize the + test: + + CONFIG_EXAMPLES_NXCON_VPLANE -- The plane to select from the frame- + buffer driver for use in the test. Default: 0 + CONFIG_EXAMPLES_NXCON_DEVNO - The LCD device to select from the LCD + driver for use in the test: Default: 0 + CONFIG_EXAMPLES_NXCON_BGCOLOR -- The color of the background. Default + Default is a darker royal blue. + CONFIG_EXAMPLES_NXCON_WCOLOR -- The color of the window. Default is a light + slate blue. + CONFIG_EXAMPLES_NXCON_FONTID -- Selects the font (see font ID numbers in + include/nuttx/nx/nxfonts.h) + CONFIG_EXAMPLES_NXCON_FONTCOLOR -- The color of the fonts. Default is + black. + CONFIG_EXAMPLES_NXCON_BPP -- Pixels per pixel to use. Valid options + include 2, 4, 8, 16, 24, and 32. Default is 32. + CONFIG_EXAMPLES_NXCON_TOOLBAR_HEIGHT -- The height of the toolbar. + Default: 16 + CONFIG_EXAMPLES_NXCON_TBCOLOR -- The color of the toolbar. Default is + a medium grey. + CONFIG_EXAMPLES_NXCON_EXTERNINIT - The driver for the graphics device on + this platform requires some unusual initialization. This is the + for, for example, SPI LCD/OLED devices. If this configuration is + selected, then the platform code must provide an LCD initialization + function with a prototype like: + + #ifdef CONFIG_NX_LCDDRIVER + FAR struct lcd_dev_s *up_nxdrvinit(unsigned int devno); + #else + FAR struct fb_vtable_s *up_nxdrvinit(unsigned int devno); + #endif + + CONFIG_EXAMPLES_NXCON_MINOR -- The NX console device minor number. + Default is 0 corresponding to /dev/nxcon0 + CONFIG_EXAMPLES_NXCON_DEVNAME -- The quoated, full path to the + NX console device corresponding to CONFIG_EXAMPLES_NXCON_MINOR. + Default: "/dev/nxcon0" + CONFIG_EXAMPLES_NXCONSOLE_PRIO - Priority of the NxConsole task. + Default: SCHED_PRIORITY_DEFAULT + CONFIG_EXAMPLES_NXCONSOLE_STACKSIZE - Stack size allocated for the + NxConsole task. Default: 2048 + + The following configuration settings determine how to set up the NX + server (CONFIG_NX_MULTIUSER): + + CONFIG_EXAMPLES_NXCON_STACKSIZE -- The stacksize to use when creating + the NX server. Default 2048 + CONFIG_EXAMPLES_NXCON_CLIENTPRIO -- The client priority. Default: 100 + CONFIG_EXAMPLES_NXCON_SERVERPRIO -- The server priority. Default: 120 + CONFIG_EXAMPLES_NXCON_LISTENERPRIO -- The priority of the event listener + thread. Default 80. + CONFIG_EXAMPLES_NXCON_NOTIFYSIGNO -- The signal number to use with + nx_eventnotify(). Default: 4 + +examples/nxffs +^^^^^^^^^^^^^^ + + This is a test of the NuttX NXFFS FLASH file system. This is an NXFFS + stress test and beats on the file system very hard. It should only + be used in a simulation environment! Putting this NXFFS test on real + hardware will most likely destroy your FLASH. You have been warned. + +examples/nxflat +^^^^^^^^^^^^^^^ + + This example builds a small NXFLAT test case. This includes several + test programs under examples/nxflat tests. These tests are build using + the NXFLAT format and installed in a ROMFS file system. At run time, + each program in the ROMFS file system is executed. Requires CONFIG_NXFLAT. + +examplex/nxhello +^^^^^^^^^^^^^^^^ + + A very simple graphics example that just says "Hello, World!" in the + center of the display. + + The following configuration options can be selected: + + CONFIG_EXAMPLES_NXHELLO_BUILTIN -- Build the NXHELLO example as a "built-in" + that can be executed from the NSH command line + CONFIG_EXAMPLES_NXHELLO_VPLANE -- The plane to select from the frame- + buffer driver for use in the test. Default: 0 + CONFIG_EXAMPLES_NXHELLO_DEVNO - The LCD device to select from the LCD + driver for use in the test: Default: 0 + CONFIG_EXAMPLES_NXHELLO_BGCOLOR -- The color of the background. Default + depends on CONFIG_EXAMPLES_NXHELLO_BPP. + CONFIG_EXAMPLES_NXHELLO_FONTID - Selects the font (see font ID numbers in + include/nuttx/nx/nxfonts.h) + CONFIG_EXAMPLES_NXHELLO_FONTCOLOR -- The color of the fonts used in the + background window. Default depends on CONFIG_EXAMPLES_NXHELLO_BPP. + CONFIG_EXAMPLES_NXHELLO_BPP -- Pixels per pixel to use. Valid options + include 2, 4, 8, 16, 24, and 32. Default is 32. + CONFIG_EXAMPLES_NXHELLO_EXTERNINIT - The driver for the graphics device on + this platform requires some unusual initialization. This is the + for, for example, SPI LCD/OLED devices. If this configuration is + selected, then the platform code must provide an LCD initialization + function with a prototype like: + + #ifdef CONFIG_NX_LCDDRIVER + FAR struct lcd_dev_s *up_nxdrvinit(unsigned int devno); + #else + FAR struct fb_vtable_s *up_nxdrvinit(unsigned int devno); + #endif + +examples/nximage +^^^^^^^^^^^^^^^^ + + This is a simple example that just puts the NuttX logo image in the center + of the display. This only works for RGB23 (888), RGB16 (656), RGB8 (332), + and 8-bit greyscale for now. + + CONFIG_EXAMPLES_NXIMAGE_BUILTIN -- Build the NXIMAGE example as a "built-in" + that can be executed from the NSH command line + CONFIG_EXAMPLES_NXIMAGE_VPLANE -- The plane to select from the frame- + buffer driver for use in the test. Default: 0 + CONFIG_EXAMPLES_NXIMAGE_DEVNO - The LCD device to select from the LCD + driver for use in the test: Default: 0 + CONFIG_EXAMPLES_NXIMAGE_BPP -- Pixels per pixel to use. Valid options + include 8, 16, and 24. Default is 16. + CONFIG_EXAMPLES_NXIMAGE_XSCALEp5, CONFIG_EXAMPLES_NXIMAGE_XSCALE1p5, + CONFIG_EXAMPLES_NXIMAGE_XSCALE2p0 -- The logo image width is 160 columns. + One of these may be defined to rescale the image horizontally by .5, 1.5, + or 2.0. + CONFIG_EXAMPLES_NXIMAGE_YSCALEp5, CONFIG_EXAMPLES_NXIMAGE_YSCALE1p5, + CONFIG_EXAMPLES_NXIMAGE_YSCALE2p0 -- The logo image height is 160 rows. + One of these may be defined to rescale the image vertically by .5, 1.5, + or 2.0. + CONFIG_EXAMPLES_NXIMAGE_GREYSCALE -- Grey scale image. Default: RGB. + CONFIG_EXAMPLES_NXIMAGE_EXTERNINIT - The driver for the graphics device on + this platform requires some unusual initialization. This is the + for, for example, SPI LCD/OLED devices. If this configuration is + selected, then the platform code must provide an LCD initialization + function with a prototype like: + + #ifdef CONFIG_NX_LCDDRIVER + FAR struct lcd_dev_s *up_nxdrvinit(unsigned int devno); + #else + FAR struct fb_vtable_s *up_nxdrvinit(unsigned int devno); + #endif + + How was that run-length encoded image produced? + + a. I used GIMP output the image as a .c file. + b. I added som C logic to palette-ize the RGB image in the GIMP .c file + c. Then I add some simple run-length encoding to palette-ized image. + + NOTE: As of this writing, most of the pixel depth, scaling options, and + combinations thereof have not been tested. + +examplex/nxlines +^^^^^^^^^^^^^^^^ + + A very simple graphics example that just exercised the NX line drawing + logic. + + The following configuration options can be selected: + + CONFIG_EXAMPLES_NXLINES_BUILTIN -- Build the NXLINES example as a "built-in" + that can be executed from the NSH command line + CONFIG_EXAMPLES_NXLINES_VPLANE -- The plane to select from the frame- + buffer driver for use in the test. Default: 0 + CONFIG_EXAMPLES_NXLINES_DEVNO - The LCD device to select from the LCD + driver for use in the test: Default: 0 + CONFIG_EXAMPLES_NXLINES_BGCOLOR -- The color of the background. Default + depends on CONFIG_EXAMPLES_NXLINES_BPP. + CONFIG_EXAMPLES_NXLINES_LINEWIDTH - Selects the width of the lines in + pixels (default: 16) + CONFIG_EXAMPLES_NXLINES_LINECOLOR -- The color of the central lines drawn + in the background window. Default depends on CONFIG_EXAMPLES_NXLINES_BPP + (there really is no meaningful default). + CONFIG_EXAMPLES_NXLINES_BORDERWIDTH -- The width of the circular border + drawn in the background window. (default: 16). + CONFIG_EXAMPLES_NXLINES_BORDERCOLOR -- The color of the circular border + drawn in the background window. Default depends on CONFIG_EXAMPLES_NXLINES_BPP + (there really is no meaningful default). + CONFIG_EXAMPLES_NXLINES_CIRCLECOLOR -- The color of the circular region + filled in the background window. Default depends on CONFIG_EXAMPLES_NXLINES_BPP + (there really is no meaningful default). + CONFIG_EXAMPLES_NXLINES_BORDERCOLOR -- The color of the lines drawn in the + background window. Default depends on CONFIG_EXAMPLES_NXLINES_BPP (there + really is no meaningful default). + + CONFIG_EXAMPLES_NXLINES_BPP -- Pixels per pixel to use. Valid options + include 2, 4, 8, 16, 24, and 32. Default is 16. + CONFIG_EXAMPLES_NXLINES_EXTERNINIT - The driver for the graphics device on + this platform requires some unusual initialization. This is the + for, for example, SPI LCD/OLED devices. If this configuration is + selected, then the platform code must provide an LCD initialization + function with a prototype like: + + #ifdef CONFIG_NX_LCDDRIVER + FAR struct lcd_dev_s *up_nxdrvinit(unsigned int devno); + #else + FAR struct fb_vtable_s *up_nxdrvinit(unsigned int devno); + #endif + +examples/nxtext +^^^^^^^^^^^^^^^ + + This directory contains another simple test of a subset of the NX APIs + defined in include/nuttx/nx/nx.h. This text focuses on text displays on + the dispaly background combined with pop-up displays over the text. + The text display will continue to update while the pop-up is visible. + + NOTE: This example will *only* work with FB drivers and with LCD + drivers that support reading the contents of the internal LCD memory + *unless* you define CONFIG_EXAMPLES_NXTEXT_NOGETRUN. If you notice + garbage on the display or a failure at the point where the display + should scroll, it is probably because you have an LCD driver that is + write-only. + + The following configuration options can be selected: + + CONFIG_EXAMPLES_NXTEXT_BUILTIN -- Build the NXTEXT example as a "built-in" + that can be executed from the NSH command line + CONFIG_EXAMPLES_NXTEXT_VPLANE -- The plane to select from the frame- + buffer driver for use in the test. Default: 0 + CONFIG_EXAMPLES_NXTEXT_DEVNO - The LCD device to select from the LCD + driver for use in the test: Default: 0 + CONFIG_EXAMPLES_NXTEXT_BGCOLOR -- The color of the background. Default + depends on CONFIG_EXAMPLES_NXTEXT_BPP. + CONFIG_EXAMPLES_NXTEXT_BGFONTID - Selects the font to use in the + background text (see font ID numbers in include/nuttx/nx/nxfonts.h) + CONFIG_EXAMPLES_NXTEXT_BGFONTCOLOR -- The color of the fonts used in the + background window. Default depends on CONFIG_EXAMPLES_NXTEXT_BPP. + CONFIG_EXAMPLES_NXTEXT_PUCOLOR -- The color of the pop-up window. Default + depends on CONFIG_EXAMPLES_NXTEXT_BPP. + CONFIG_EXAMPLES_NXTEXT_PUFONTID - Selects the font to use in the pop-up + windows (see font ID numbers in include/nuttx/nx/nxfonts.h) + CONFIG_EXAMPLES_NXTEXT_PUFONTCOLOR -- The color of the fonts used in the + background window. Default depends on CONFIG_EXAMPLES_NXTEXT_BPP. + CONFIG_EXAMPLES_NXTEXT_BPP -- Pixels per pixel to use. Valid options + include 2, 4, 8, 16, 24, and 32. Default is 32. + CONFIG_EXAMPLES_NXTEXT_NOGETRUN -- If your display is read-only OR if + reading is not reliable, then select this configuration to avoid + reading from the display. + CONFIG_EXAMPLES_NXTEXT_EXTERNINIT - The driver for the graphics device on + this platform requires some unusual initialization. This is the + for, for example, SPI LCD/OLED devices. If this configuration is + selected, then the platform code must provide an LCD initialization + function with a prototype like: + + #ifdef CONFIG_NX_LCDDRIVER + FAR struct lcd_dev_s *up_nxdrvinit(unsigned int devno); + #else + FAR struct fb_vtable_s *up_nxdrvinit(unsigned int devno); + #endif + + CONFIG_EXAMPLES_NXTEXT_BMCACHE - The maximum number of characters that + can be put in the background window. Default is 128. + CONFIG_EXAMPLES_NXTEXT_GLCACHE - The maximum nuber of pre-rendered + fonts that can be retained for the background window. + + This test can be performed with either the single-user version of + NX or with the multiple user version of NX selected with CONFIG_NX_MULTIUSER. + If CONFIG_NX_MULTIUSER is defined, then the following configuration + options also apply: + + CONFIG_EXAMPLES_NXTEXT_STACKSIZE -- The stacksize to use when creating + the NX server. Default 2048 + CONFIG_EXAMPLES_NXTEXT_CLIENTPRIO -- The client priority. Default: 100 + CONFIG_EXAMPLES_NXTEXT_SERVERPRIO -- The server priority. Default: 120 + CONFIG_EXAMPLES_NXTEXT_LISTENERPRIO -- The priority of the event listener + thread. Default 80. + CONFIG_EXAMPLES_NXTEXT_NOTIFYSIGNO -- The signal number to use with + nx_eventnotify(). Default: 4 + + If CONFIG_NX_MULTIUSER is defined, then the example also expects the + following settings and will generate an error if they are not as expected: + + CONFIG_DISABLE_MQUEUE=n + CONFIG_DISABLE_SIGNALS=n + CONFIG_DISABLE_PTHREAD=n + CONFIG_NX_BLOCKING=y + +examples/null +^^^^^^^^^^^^^ + + This is the do nothing application. It is only used for bringing + up new NuttX architectures in the most minimal of environments. + +examples/ostest +^^^^^^^^^^^^^^^ + + This is the NuttX 'qualification' suite. It attempts to exercise + a broad set of OS functionality. Its coverage is not very extensive + as of this writing, but it is used to qualify each NuttX release. + + The behavior of the ostest can be modified with the following + settings in the configs//defconfig file: + + * CONFIG_EXAMPLES_OSTEST_BUILTIN + Build the OS test example as an NSH built-in application. + * CONFIG_EXAMPLES_OSTEST_LOOPS + Used to control the number of executions of the test. If + undefined, the test executes one time. If defined to be + zero, the test runs forever. + * CONFIG_EXAMPLES_OSTEST_STACKSIZE + Used to create the ostest task. Default is 8192. + * CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS + Specifies the number of threads to create in the barrier + test. The default is 8 but a smaller number may be needed on + systems without sufficient memory to start so many threads. + +examples/pashello +^^^^^^^^^^^^^^^^^ + + This is "Hello, World" implemented via the Pascal P-Code interpreter. In + order to use this example, you must first download and install the + NuttX pascal module. After unpacking the pascal module, you can find + installation instructions in pascal/nuttx/README.txt. + + The correct install location for the NuttX examples and build files is + apps/interpreters. + +examples/pipe +^^^^^^^^^^^^^ + + A test of the mkfifo() and pipe() APIs. + + * CONFIG_EXAMPLES_PIPE_STACKSIZE + Sets the size of the stack to use when creating the child tasks. + The default size is 1024. + +examples/poll +^^^^^^^^^^^^^ + + A test of the poll() and select() APIs using FIFOs and, if available, + stdin, and a TCP/IP socket. In order to build this test, you must the + following selected in your NuttX configuration file: + + CONFIG_NFILE_DESCRIPTORS - Defined to be greater than 0 + CONFIG_DISABLE_POLL - NOT defined + + In order to use the TCP/IP select test, you have also the following + additional things selected in your NuttX configuration file: + + CONFIG_NET - Defined for general network support + CONFIG_NET_TCP - Defined for TCP/IP support + CONFIG_NSOCKET_DESCRIPTORS - Defined to be greater than 0 + CONFIG_NET_NTCP_READAHEAD_BUFFERS - Defined to be greater than zero + + CONFIG_EXAMPLE_POLL_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLE_POLL_IPADDR - Target IP address + CONFIG_EXAMPLE_POLL_DRIPADDR - Default router IP addess + CONFIG_EXAMPLE_POLL_NETMASK - Network mask + + In order to for select to work with incoming connections, you + must also select: + + CONFIG_NET_TCPBACKLOG - Incoming connections pend in a backlog until accept() is called. + + In additional to the target device-side example, there is also + a host-side application in this directory. It can be compiled under + Linux or Cygwin as follows: + + cd examples/usbserial + make -f Makefile.host TOPDIR= TARGETIP= + + Where is the IP address of your target board. + + This will generate a small program called 'host'. Usage: + + 1. Build the examples/poll target program with TCP/IP poll support + and start the target. + + 3. Then start the host application: + + ./host + + The host and target will exchange are variety of small messages. Each + message sent from the host should cause the select to return in target. + The target example should read the small message and send it back to + the host. The host should then receive the echo'ed message. + + If networking is enabled, applications using this example will need to + provide an appconfig file in the configuration driver with instruction + to build applications like: + + CONFIGURED_APPS += uiplib + +examples/pwm +^^^^^^^^^^^^ + + A test of a PWM device driver. It simply enables a pulsed output for + a specified frequency and duty for a specified period of time. This + example can ONLY be built as an NSH built-in function. + + This test depends on these specific PWM/NSH configurations settings (your + specific PWM settings might require additional settings). + + CONFIG_PWM - Enables PWM support. + CONFIG_EXAMPLES_PWM_COUNT - Enabled PWM pulse count support (if the + hardware supports it). + CONFIG_NSH_BUILTIN_APPS - Build the PWM test as an NSH built-in function. + Default: Not built! The example can only be used as an NSH built-in + application + + Specific configuration options for this example include: + + CONFIG_EXAMPLES_PWM_DEVPATH - The path to the default PWM device. Default: /dev/pwm0 + CONFIG_EXAMPLES_PWM_FREQUENCY - The initial PWM frequency. Default: 100 Hz + CONFIG_EXAMPLES_PWM_DUTYPCT - The initial PWM duty as a percentage. Default: 50% + CONFIG_EXAMPLES_PWM_DURATION - The initial PWM pulse train duration in seconds. + Used only if the current pulse count is zero (pulse count is only supported + if CONFIG_PWM_PULSECOUNT is defined). Default: 5 seconds + CONFIG_EXAMPLES_PWM_PULSECOUNT - The initial PWM pulse count. This option is + only available if CONFIG_PWM_PULSECOUNT is non-zero. Default: 0 (i.e., use + the duration, not the count). + +examples/qencoder +^^^^^^^^^^^^^^^^^ + + This example is a simple test of a Quadrature Encoder driver. It simply reads + positional data from the encoder and prints it., + + This test depends on these specific QE/NSH configurations settings (your + specific PWM settings might require additional settings). + + CONFIG_QENCODER - Enables quadrature encoder support (upper-half driver). + CONFIG_NSH_BUILTIN_APPS - Build the QE test as an NSH built-in function. + Default: Built as a standalone progrem. + + Additional configuration options will mostly likely be required for the board- + specific lower-half driver. See the README.txt file in your board configuration + directory. + + Specific configuration options for this example include: + + CONFIG_EXAMPLES_QENCODER_DEVPATH - The path to the QE device. Default: + /dev/qe0 + CONFIG_EXAMPLES_QENCODER_NSAMPLES - If CONFIG_NSH_BUILTIN_APPS + is defined, then the number of samples is provided on the command line + and this value is ignored. Otherwise, this number of samples is + collected and the program terminates. Default: Samples are collected + indefinitely. + CONFIG_EXAMPLES_QENCODER_DELAY - This value provides the delay (in + milliseonds) between each sample. If CONFIG_NSH_BUILTIN_APPS + is defined, then this value is the default delay if no other delay is + provided on the command line. Default: 100 milliseconds + +examples/rgmp +^^^^^^^^^^^^^ + + RGMP stands for RTOS and GPOS on Multi-Processor. RGMP is a project for + running GPOS and RTOS simultaneously on multi-processor platforms. You can + port your favorite RTOS to RGMP together with an unmodified Linux to form a + hybrid operating system. This makes your application able to use both RTOS + and GPOS features. + + See http://rgmp.sourceforge.net/wiki/index.php/Main_Page for further + + At present, the RGMP example folder contains only an empty main.c file. + +examples/romfs +^^^^^^^^^^^^^^ + + This example exercises the romfs filesystem. Configuration options + include: + + * CONFIG_EXAMPLES_ROMFS_RAMDEVNO + The minor device number to use for the ROM disk. The default is + 1 (meaning /dev/ram1) + + * CONFIG_EXAMPLES_ROMFS_SECTORSIZE + The ROM disk sector size to use. Default is 64. + + * CONFIG_EXAMPLES_ROMFS_MOUNTPOINT + The location to mount the ROM disk. Deafault: "/usr/local/share" + +examples/sendmail +^^^^^^^^^^^^^^^^^ + + This examples exercises the uIP SMTP logic by sending a test message + to a selected recipient. This test can also be built to execute on + the Cygwin/Linux host environment: + + cd examples/sendmail + make -f Makefile.host TOPDIR= + + Settings unique to this example include: + + CONFIG_EXAMPLE_SENDMAIL_NOMAC - May be defined to use software assigned MAC (optional) + CONFIG_EXAMPLE_SENDMAIL_IPADDR - Target IP address (required) + CONFIG_EXAMPLE_SENDMAIL_DRIPADDR - Default router IP addess (required) + CONFIG_EXAMPLE_SENDMAILT_NETMASK - Network mask (required) + CONFIG_EXAMPLE_SENDMAIL_RECIPIENT - The recipient of the email (required) + CONFIG_EXAMPLE_SENDMAIL_SENDER - Optional. Default: "nuttx-testing@example.com" + CONFIG_EXAMPLE_SENDMAIL_SUBJECT - Optional. Default: "Testing SMTP from NuttX" + CONFIG_EXAMPLE_SENDMAIL_BODY - Optional. Default: "Test message sent by NuttX" + + NOTE: This test has not been verified on the NuttX target environment. + As of this writing, unit-tested in the Cygwin/Linux host environment. + + NOTE 2: This sendmail example only works for the simplest of + environments. Virus protection software on your host may have + to be disabled to allow you to send messages. Only very open, + unprotected recipients can be used. Most will protect themselves + from this test email because it looks like SPAM. + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + CONFIGURED_APPS += smtp + +examples/serloop +^^^^^^^^^^^^^^^^ + + This is a mindlessly simple loopback test on the console. Useful + for testing new serial drivers. Configuration options include: + + * CONFIG_EXAMPLES_SERLOOP_BUFIO + Use C buffered I/O (getchar/putchar) vs. raw console I/O + (read/read). + +examples/telnetd +^^^^^^^^^^^^^^^^ + + This directory contains a functional port of the tiny uIP shell. In + the NuttX environment, the NuttShell (at apps/nshlib) supercedes this + tiny shell and also supports telnetd. + + CONFIG_EXAMPLES_TELNETD_DAEMONPRIO - Priority of the Telnet daemon. + Default: SCHED_PRIORITY_DEFAULT + CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE - Stack size allocated for the + Telnet daemon. Default: 2048 + CONFIG_EXAMPLES_TELNETD_CLIENTPRIO- Priority of the Telnet client. + Default: SCHED_PRIORITY_DEFAULT + CONFIG_EXAMPLES_TELNETD_CLIENTSTACKSIZE - Stack size allocated for the + Telnet client. Default: 2048 + CONFIG_EXAMPLE_TELNETD_NOMAC - If the hardware has no MAC address of its + own, define this =y to provide a bogus address for testing. + CONFIG_EXAMPLE_TELNETD_IPADDR - The target IP address. Default 10.0.0.2 + CONFIG_EXAMPLE_TELNETD_DRIPADDR - The default router address. Default + 10.0.0.1 + CONFIG_EXAMPLE_TELNETD_NETMASK - The network mask. Default: 255.255.255.0 + + The appconfig file (apps/.config) should include: + + CONFIGURED_APPS += examples/telnetd + CONFIGURED_APPS += netutils/uiplib + CONFIGURED_APPS += netutils/telnetd + + Also, make sure that you have the following set in the NuttX configuration + file or else the performance will be very bad (because there will be only + one character per TCP transfer): + + CONFIG_STDIO_BUFFER_SIZE - Some value >= 64 + CONFIG_STDIO_LINEBUFFER=y + +examples/thttpd +^^^^^^^^^^^^^^^ + + An example that builds netutils/thttpd with some simple NXFLAT + CGI programs. see configs/README.txt for most THTTPD settings. + In addition to those, this example accepts: + + CONFIG_EXAMPLE_THTTPD_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLE_THTTPD_DRIPADDR - Default router IP addess + CONFIG_EXAMPLE_THTTPD_NETMASK - Network mask + + Applications using this example will need to provide an appconfig + file in the configuration directory with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + CONFIGURED_APPS += thttpd + +examples/tiff +^^^^^^^^^^^^^ + + This is a simple unit test for the TIFF creation library at apps/graphic/tiff. + It is configured to work in the Linux user-mode simulation and has not been + tested in any other environment. Since the example also depends on some + other logic to mount a file system, currently it will only work as an NSH + built-on, i.e., if the following is defined: + + CONFIG_NSH_BUILTIN_APPS=y + CONFIG_EXAMPLES_TIFF_BUILTIN=y + + At a miniumum, to run in an embedded environment, you will probably have to + change the configured paths to the TIFF files defined in the example. + + CONFIG_EXAMPLES_TIFF_OUTFILE - Name of the resulting TIFF file. Default is + "/tmp/result.tif" + CONFIG_EXAMPLES_TIFF_TMPFILE1/2 - Names of two temporaries files that + will be used in the file creation. Defaults are "/tmp/tmpfile1.dat" and + "/tmp/tmpfile2.dat" + + The following must also be defined in your apps/ configuration file: + + CONFIGURED_APPS += examples/tiff + CONFIGURED_APPS += graphics/tiff + +examples/touchscreen +^^^^^^^^^^^^^^^^^^^^ + + This configuration implements a simple touchscreen test at + apps/examples/touchscreen. This test will create an empty X11 window + and will print the touchscreen output as it is received from the + simulated touchscreen driver. + + CONFIG_EXAMPLES_TOUCHSCREEN_BUILTIN - Build the touchscreen test as + an NSH built-in function. Default: Built as a standalone problem + CONFIG_EXAMPLES_TOUCHSCREEN_MINOR - The minor device number. Minor=N + correspnds to touchscreen device /dev/input0. Note this value must + with CONFIG_EXAMPLES_TOUCHSCREEN_DEVPATH. Default 0. + CONFIG_EXAMPLES_TOUCHSCREEN_DEVPATH - The path to the touchscreen + device. This must be consistent with CONFIG_EXAMPLES_TOUCHSCREEN_MINOR. + Default: "/dev/input0" + CONFIG_EXAMPLES_TOUCHSCREEN_NSAMPLES - If CONFIG_EXAMPLES_TOUCHSCREEN_BUILTIN + is defined, then the number of samples is provided on the command line + and this value is ignored. Otherwise, this number of samples is + collected and the program terminates. Default: Samples are collected + indefinitely. + + The following additional configurations must be set in the NuttX + configuration file: + + CONFIG_INPUTP=y + (Plus any touchscreen-specific settings). + + The following must also be defined in your apps configuration file: + + CONFIGURED_APPS += examples/tiff + CONFIGURED_APPS += graphics/tiff + + The board-specific logic must provide the following interfaces that will + be called by the example in order to initialize and uninitialize the + touchscreen hardware: + + int arch_tcinitialize(int minor); + int arch_tcuninitialize(void); + +examples/udp +^^^^^^^^^^^^ + + This is a simple network test for verifying client- and server- + functionality over UDP. + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + +examples/uip +^^^^^^^^^^^^ + + This is a port of uIP tiny webserver example application. Settings + specific to this example include: + + CONFIG_EXAMPLE_UIP_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLE_UIP_IPADDR - Target IP address + CONFIG_EXAMPLE_UIP_DRIPADDR - Default router IP addess + CONFIG_EXAMPLE_UIP_NETMASK - Network mask + CONFIG_EXAMPLE_UIP_DHCPC - Select to get IP address via DHCP + + If you use DHCPC, then some special configuration network options are + required. These include: + + CONFIG_NET=y - Of course + CONFIG_NSOCKET_DESCRIPTORS - And, of course, you must allocate some + socket descriptors. + CONFIG_NET_UDP=y - UDP support is required for DHCP + (as well as various other UDP-related + configuration settings). + CONFIG_NET_BROADCAST=y - UDP broadcast support is needed. + CONFIG_NET_BUFSIZE=650 - Per RFC2131 (p. 9), the DHCP client must be + (or larger) prepared to receive DHCP messages of up to + 576 bytes (excluding Ethernet, IP, or UDP + headers and FCS). + + Other configuration items apply also to the selected webserver net utility. + Additional relevant settings for the uIP webserver net utility are: + + CONFIG_NETUTILS_HTTPDSTACKSIZE + CONFIG_NETUTILS_HTTPDFILESTATS + CONFIG_NETUTILS_HTTPDNETSTATS + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + CONFIGURED_APPS += dhcpc + CONFIGURED_APPS += resolv + CONFIGURED_APPS += webserver + +examples/usbserial +^^^^^^^^^^^^^^^^^^ + + TARGET CONFIGURATION: + + This is another implementation of "Hello, World" but this one uses + a USB serial driver. Configuration options can be used to simply + the test. These options include: + + CONFIG_EXAMPLES_USBSERIAL_INONLY + Only verify IN (device-to-host) data transfers. Default: both + CONFIG_EXAMPLES_USBSERIAL_OUTONLY + Only verify OUT (host-to-device) data transfers. Default: both + CONFIG_EXAMPLES_USBSERIAL_ONLYSMALL + Send only small, single packet messages. Default: Send large and small. + CONFIG_EXAMPLES_USBSERIAL_ONLYBIG + Send only large, multi-packet messages. Default: Send large and small. + + If CONFIG_USBDEV_TRACE is enabled (or CONFIG_DEBUG and CONFIG_DEBUG_USB), then + the example code will also manage the USB trace output. The amount of trace output + can be controlled using: + + CONFIG_EXAMPLES_USBSERIAL_TRACEINIT + Show initialization events + CONFIG_EXAMPLES_USBSERIAL_TRACECLASS + Show class driver events + CONFIG_EXAMPLES_USBSERIAL_TRACETRANSFERS + Show data transfer events + CONFIG_EXAMPLES_USBSERIAL_TRACECONTROLLER + Show controller events + CONFIG_EXAMPLES_USBSERIAL_TRACEINTERRUPTS + Show interrupt-related events. + + Error results are always shown in the trace output + + HOST-SIDE TEST PROGRAM + + In additional to the target device-side example, there is also a + host-side application in this directory. This host side application + must be executed on a Linux host in order to perform the USBSERIAL + test. The host application can be compiled under Linux (or Cygwin?) + as follows: + + cd examples/usbserial + make -f Makefile.host TOPDIR= + + RUNNING THE TEST + + This will generate a small program called 'host'. Usage: + + 1. Build the examples/usbserial target program and start the target. + + 2. Wait a bit, then do enter: + + dmesg + + At the end of the dmesg output, you should see the serial + device was successfully idenfied and assigned to a tty device, + probably /dev/ttyUSB0 or /dev/ttyACM0 (depending on the configured + USB serial driver). + + 3. Then start the host application: + + ./host [] + + Where: + + is the USB TTY device to use. The default is + "/dev/ttyUSB0" (for the PL2303 emulation) or "/dev/ttyACM0" (for + the CDC/ACM serial device). + + The host and target will exchange are variety of very small and very large + serial messages. + +examples/usbstorage +^^^^^^^^^^^^^^^^^^^ + + This example registers a block device driver, then exports the block + the device using the USB storage class driver. In order to use this + example, your board-specific logic must provide the function: + + void usbmsc_archinitialize(void); + + This function will be called by the example/usbstorage in order to + do the actual registration of the block device drivers. For examples + of the implementation of usbmsc_archinitialize() see + configs/mcu123-lpc124x/src/up_usbmsc.c or + configs/stm3210e-eval/src/usbmsc.c + + Configuration options: + + CONFIG_EXAMPLES_USBMSC_BUILTIN + This example can be built as two NSH "built-in" commands if this option + is selected: 'msconn' will connect the USB mass storage device; 'msdis' + will disconnect the USB storage device. + CONFIG_EXAMPLES_USBMSC_NLUNS + Defines the number of logical units (LUNs) exported by the USB storage + driver. Each LUN corresponds to one exported block driver (or partition + of a block driver). May be 1, 2, or 3. Default is 1. + CONFIG_EXAMPLES_USBMSC_DEVMINOR1 + The minor device number of the block driver for the first LUN. For + example, N in /dev/mmcsdN. Used for registering the block driver. Default + is zero. + CONFIG_EXAMPLES_USBMSC_DEVPATH1 + The full path to the registered block driver. Default is "/dev/mmcsd0" + CONFIG_EXAMPLES_USBMSC_DEVMINOR2 and CONFIG_EXAMPLES_USBMSC_DEVPATH2 + Similar parameters that would have to be provided if CONFIG_EXAMPLES_USBMSC_NLUNS + is 2 or 3. No defaults. + CONFIG_EXAMPLES_USBMSC_DEVMINOR3 and CONFIG_EXAMPLES_USBMSC_DEVPATH3 + Similar parameters that would have to be provided if CONFIG_EXAMPLES_USBMSC_NLUNS + is 3. No defaults. + CONFIG_EXAMPLES_USBMSC_DEBUGMM + Enables some debug tests to check for memory usage and memory leaks. + + If CONFIG_USBDEV_TRACE is enabled (or CONFIG_DEBUG and CONFIG_DEBUG_USB), then + the example code will also manage the USB trace output. The amount of trace output + can be controlled using: + + CONFIG_EXAMPLES_USBMSC_TRACEINIT + Show initialization events + CONFIG_EXAMPLES_USBMSC_TRACECLASS + Show class driver events + CONFIG_EXAMPLES_USBMSC_TRACETRANSFERS + Show data transfer events + CONFIG_EXAMPLES_USBMSC_TRACECONTROLLER + Show controller events + CONFIG_EXAMPLES_USBMSC_TRACEINTERRUPTS + Show interrupt-related events. + + Error results are always shown in the trace output + + NOTE 1: When built as an NSH add-on command (CONFIG_EXAMPLES_USBMSC_BUILTIN=y), + Caution should be used to assure that the SD drive (or other storage device) is + not in use when the USB storage device is configured. Specifically, the SD + driver should be unmounted like: + + nsh> mount -t vfat /dev/mmcsd0 /mnt/sdcard # Card is mounted in NSH + ... + nsh> umount /mnd/sdcard # Unmount before connecting USB!!! + nsh> msconn # Connect the USB storage device + ... + nsh> msdis # Disconnect USB storate device + nsh> mount -t vfat /dev/mmcsd0 /mnt/sdcard # Restore the mount + + Failure to do this could result in corruption of the SD card format. + + NOTE 2: This test exercises internal USB device driver interfaces. As such, + it relies on internal OS interfaces that are not normally available to a + user-space program. As a result, this example cannot be used if a + NuttX is built as a protected, supervisor kernel (CONFIG_NUTTX_KERNEL). + +examples/usbterm +^^^^^^^^^^^^^^^^ + + This example implements a little USB terminal.. more of a USB "chat" + edited lines are received from the remote host connected via USB + serial and echoed out the target serial console. Edited lines from + the local target serial console are received and forwarded to the + remote host via USB serial. + + Usage: + - Build the example and load into the target FLASH + - Connect on terminal to the target RS-232 connect and configure + for 115200 8N1. For example, suppose this Tera Term on a Windows + box. + - Power up the target board + - Connect the USB to a Linux box. Use the Linux dmesg command to + assure that the connect was successful. The USB CDC ACM device + should appear as /dev/ttyACM0 + - On the Linux box, open minicom with tty=/dev/ttyACM0. + Configure minicom so that (1) local characters are echoed and (2) + so that no CR is required. + - Now what you type on the target Tera Term window should echo on + the Linux minicom window and, conversely, what you type on the + minicom winow should be echo in the target Tera Term window. + + Configuration options: + + CONFIG_EXAMPLES_USBTERM_BUILTIN - Build the usbterm example as an NSH + built-in command. NOTE: This is not fully functional as of this + writing.. It should work, but there is no mechanism in place yet + to exit the USB terminal program and return to NSH. + CONFIG_EXAMPLES_USBTERM_DEVINIT - If defined, then the example will + call a user provided function as part of its initialization: + int usbterm_devinit(void); + And another user provided function at termination: + void usbterm_devuninit(void); + CONFIG_EXAMPLES_USBTERM_BUFLEN - The size of the input and output + buffers used for receiving data. Default 256 bytes. + + If CONFIG_USBDEV_TRACE is enabled (or CONFIG_DEBUG and CONFIG_DEBUG_USB, or + CONFIG_USBDEV_TRACE), then the example code will also manage the USB trace + output. The amount of trace output can be controlled using: + + CONFIG_EXAMPLES_USBTERM_TRACEINIT + Show initialization events + CONFIG_EXAMPLES_USBTERM_TRACECLASS + Show class driver events + CONFIG_EXAMPLES_USBTERM_TRACETRANSFERS + Show data transfer events + CONFIG_EXAMPLES_USBTERM_TRACECONTROLLER + Show controller events + CONFIG_EXAMPLES_USBTERM_TRACEINTERRUPTS + Show interrupt-related events. + + NOTE: By default, USBterm uses readline to get data from stdin. So your + appconfig file must have the following build path: + + CONFIGURED_APPS += system/readline + + NOTE: If you use the USBterm task over a telnet NSH connection, then you + should set the following configuration item: + + CONFIG_EXAMPLES_USBTERM_FGETS=y + + By default, the USBterm client will use readline() to get characters from + the console. Readline includes and command-line editor and echos + characters received in stdin back through stdout. Neither of these + behaviors are desire-able if Telnet is used. + + Error results are always shown in the trace output + + Other relevant configuration options: CONFIG_CDCACM selected by the + Prolifics emulation (not defined) and the CDC serial implementation + (when defined). CONFIG_USBDEV_TRACE_INITIALIDSET. + +examples/watchdog +^^^^^^^^^^^^^^^^^ + + A simple test of a watchdog timer driver. Initializes starts the watchdog + timer. It pings the watchdog timer for a period of time then lets the + watchdog timer expire... resetting the CPU is successful. This + example can ONLY be built as an NSH built-in function. + + This test depends on these specific Watchdog/NSH configurations settings (your + specific watchdog hardware settings might require additional settings). + + CONFIG_WATCHDOG- Enables watchdog timer support support. + CONFIG_NSH_BUILTIN_APPS - Build the watchdog time test as an NSH + built-in function. Default: Not built! The example can only be used + as an NSH built-in application + + Specific configuration options for this example include: + + CONFIG_EXAMPLES_WATCHDOG_DEVPATH - The path to the Watchdog device. + Default: /dev/watchdog0 + CONFIG_EXAMPLES_WATCHDOG_PINGTIME - Time in milliseconds that the example + will ping the watchdog before letting the watchdog expire. Default: 5000 + milliseconds + CONFIG_EXAMPLES_WATCHDOG_PINGDELAY - Time delay between pings in + milliseconds. Default: 500 milliseconds. + CONFIG_EXAMPLES_WATCHDOG_TIMEOUT - The watchdog timeout value in + milliseconds before the watchdog timer expires. Default: 2000 + milliseconds. + +examples/wget +^^^^^^^^^^^^^ + + A simple web client example. It will obtain a file from a server using the HTTP + protocol. Settings unique to this example include: + + CONFIG_EXAMPLE_WGET_URL - The URL of the file to get + CONFIG_EXAMPLE_WGET_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLE_WGET_IPADDR - Target IP address + CONFIG_EXAMPLE_WGET_DRIPADDR - Default router IP addess + CONFIG_EXAMPLE_WGET_NETMASK - Network mask + + This example uses netutils/webclient. Additional configuration settings apply + to that code as follows (but built-in defaults are probably OK): + + CONFIG_WEBCLIENT_GETMIMETYPE, CONFIG_WEBCLIENT_MAXHTTPLINE, + CONFIG_WEBCLIENT_MAXMIMESIZE, CONFIG_WEBCLIENT_MAXHOSTNAME, + CONFIG_WEBCLIENT_MAXFILENAME + + Of course, the example also requires other settings including CONFIG_NET and + CONFIG_NET_TCP. The example also uses the uIP resolver which requires CONFIG_UDP. + + WARNNG: As of this writing, wget is untested on the target platform. At present + it has been tested only in the host-based configuration described in the following + note. The primary difference is that the target version will rely on the also + untested uIP name resolver. + + NOTE: For test purposes, this example can be built as a host-based wget function. + This can be built as follows: + + cd examples/wget + make -f Makefile.host + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + CONFIGURED_APPS += resolv + CONFIGURED_APPS += webclient + + diff --git a/apps/examples/adc/Kconfig b/apps/examples/adc/Kconfig new file mode 100644 index 0000000000..b6dca047c7 --- /dev/null +++ b/apps/examples/adc/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_ADC + bool "ADC example" + default n + ---help--- + Enable the ADC example + +if EXAMPLES_ADC +endif diff --git a/apps/examples/adc/Makefile b/apps/examples/adc/Makefile new file mode 100644 index 0000000000..6357dfc3db --- /dev/null +++ b/apps/examples/adc/Makefile @@ -0,0 +1,105 @@ +############################################################################ +# apps/examples/adc/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# NuttX NX Graphics Example. + +ASRCS = +CSRCS = adc_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Touchscreen built-in application info + +APPNAME = adc +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Common build + +VPATH = + +all: .built +.PHONY: context clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: +ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ +endif + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/adc/adc.h b/apps/examples/adc/adc.h new file mode 100644 index 0000000000..9f79db92a3 --- /dev/null +++ b/apps/examples/adc/adc.h @@ -0,0 +1,125 @@ +/**************************************************************************** + * examples/examples/adc/adc.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_EXAMPLES_ADC_ADC_H +#define __APPS_EXAMPLES_ADC_ADC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_NSH_BUILTIN_APPS - Build the ADC test as an NSH built-in function. + * Default: Built as a standalone problem + * CONFIG_EXAMPLES_ADC_DEVPATH - The default path to the ADC device. Default: /dev/adc0 + * CONFIG_EXAMPLES_ADC_NSAMPLES - If CONFIG_NSH_BUILTIN_APPS + * is defined, then the number of samples is provided on the command line + * and this value is ignored. Otherwise, this number of samples is + * collected and the program terminates. Default: Samples are collected + * indefinitely. + * CONFIG_EXAMPLES_ADC_GROUPSIZE - The number of samples to read at once. + * Default: 4 + */ + +#ifndef CONFIG_ADC +# error "ADC device support is not enabled (CONFIG_ADC)" +#endif + +#ifndef CONFIG_EXAMPLES_ADC_DEVPATH +# define CONFIG_EXAMPLES_ADC_DEVPATH "/dev/adc0" +#endif + +#ifndef CONFIG_EXAMPLES_ADC_GROUPSIZE +# define CONFIG_EXAMPLES_ADC_GROUPSIZE 4 +#endif + +/* Debug ********************************************************************/ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_DEBUG +# define message(...) lib_rawprintf(__VA_ARGS__) +# define msgflush() +# else +# define message(...) printf(__VA_ARGS__) +# define msgflush() fflush(stdout) +# endif +#else +# ifdef CONFIG_DEBUG +# define message lib_rawprintf +# define msgflush() +# else +# define message printf +# define msgflush() fflush(stdout) +# endif +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct adc_state_s +{ + bool initialized; + FAR char *devpath; +#if defined(CONFIG_NSH_BUILTIN_APPS) || defined(CONFIG_EXAMPLES_ADC_NSAMPLES) + int count; +#endif +}; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: adc_devinit() + * + * Description: + * Perform architecuture-specific initialization of the ADC hardware. This + * interface must be provided by all configurations using apps/examples/adc + * + ****************************************************************************/ + +int adc_devinit(void); + +#endif /* __APPS_EXAMPLES_ADC_ADC_H */ diff --git a/apps/examples/adc/adc_main.c b/apps/examples/adc/adc_main.c new file mode 100644 index 0000000000..b880326549 --- /dev/null +++ b/apps/examples/adc/adc_main.c @@ -0,0 +1,367 @@ +/**************************************************************************** + * examples/adc/adc_main.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "adc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +# define MAIN_NAME adc_main +# define MAIN_STRING "adc_main: " +#else +# define MAIN_NAME user_start +# define MAIN_STRING "user_start: " +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct adc_state_s g_adcstate; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: adc_devpath + ****************************************************************************/ + +static void adc_devpath(FAR struct adc_state_s *adc, FAR const char *devpath) +{ + /* Get rid of any old device path */ + + if (adc->devpath) + { + free(adc->devpath); + } + + /* Then set-up the new device path by copying the string */ + + adc->devpath = strdup(devpath); +} + +/**************************************************************************** + * Name: adc_help + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static void adc_help(FAR struct adc_state_s *adc) +{ + message("Usage: adc [OPTIONS]\n"); + message("\nArguments are \"sticky\". For example, once the ADC device is\n"); + message("specified, that device will be re-used until it is changed.\n"); + message("\n\"sticky\" OPTIONS include:\n"); + message(" [-p devpath] selects the ADC device. " + "Default: %s Current: %s\n", + CONFIG_EXAMPLES_ADC_DEVPATH, g_adcstate.devpath ? g_adcstate.devpath : "NONE"); + message(" [-n count] selects the samples to collect. " + "Default: 1 Current: %d\n", adc->count); + message(" [-h] shows this message and exits\n"); +} +#endif + +/**************************************************************************** + * Name: arg_string + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static int arg_string(FAR char **arg, FAR char **value) +{ + FAR char *ptr = *arg; + + if (ptr[2] == '\0') + { + *value = arg[1]; + return 2; + } + else + { + *value = &ptr[2]; + return 1; + } +} +#endif + +/**************************************************************************** + * Name: arg_decimal + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static int arg_decimal(FAR char **arg, FAR long *value) +{ + FAR char *string; + int ret; + + ret = arg_string(arg, &string); + *value = strtol(string, NULL, 10); + return ret; +} +#endif + +/**************************************************************************** + * Name: parse_args + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static void parse_args(FAR struct adc_state_s *adc, int argc, FAR char **argv) +{ + FAR char *ptr; + FAR char *str; + long value; + int index; + int nargs; + + for (index = 1; index < argc; ) + { + ptr = argv[index]; + if (ptr[0] != '-') + { + message("Invalid options format: %s\n", ptr); + exit(0); + } + + switch (ptr[1]) + { + case 'n': + nargs = arg_decimal(&argv[index], &value); + if (value < 0) + { + message("Count must be non-negative: %ld\n", value); + exit(1); + } + + adc->count = (uint32_t)value; + index += nargs; + break; + + case 'p': + nargs = arg_string(&argv[index], &str); + adc_devpath(adc, str); + index += nargs; + break; + + case 'h': + adc_help(adc); + exit(0); + + default: + message("Unsupported option: %s\n", ptr); + adc_help(adc); + exit(1); + } + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start/adc_main + ****************************************************************************/ + +int MAIN_NAME(int argc, char *argv[]) +{ + struct adc_msg_s sample[CONFIG_EXAMPLES_ADC_GROUPSIZE]; + size_t readsize; + ssize_t nbytes; + int fd; + int errval = 0; + int ret; + int i; + + /* Check if we have initialized */ + + if (!g_adcstate.initialized) + { + /* Initialization of the ADC hardware is performed by logic external to + * this test. + */ + + message(MAIN_STRING "Initializing external ADC device\n"); + ret = adc_devinit(); + if (ret != OK) + { + message(MAIN_STRING "adc_devinit failed: %d\n", ret); + errval = 1; + goto errout; + } + + /* Set the default values */ + + adc_devpath(&g_adcstate, CONFIG_EXAMPLES_ADC_DEVPATH); + +#ifdef CONFIG_EXAMPLES_ADC_NSAMPLES + g_adcstate.count = CONFIG_EXAMPLES_ADC_NSAMPLES; +#else + g_adcstate.count = 1; +#endif + g_adcstate.initialized = true; + } + + /* Parse the command line */ + +#ifdef CONFIG_NSH_BUILTIN_APPS + parse_args(&g_adcstate, argc, argv); +#endif + + /* If this example is configured as an NX add-on, then limit the number of + * samples that we collect before returning. Otherwise, we never return + */ + +#if defined(CONFIG_NSH_BUILTIN_APPS) || defined(CONFIG_EXAMPLES_ADC_NSAMPLES) + message(MAIN_STRING "g_adcstate.count: %d\n", g_adcstate.count); +#endif + + /* Open the ADC device for reading */ + + message(MAIN_STRING "Hardware initialized. Opening the ADC device: %s\n", + g_adcstate.devpath); + + fd = open(g_adcstate.devpath, O_RDONLY); + if (fd < 0) + { + message(MAIN_STRING "open %s failed: %d\n", g_adcstate.devpath, errno); + errval = 2; + goto errout_with_dev; + } + + /* Now loop the appropriate number of times, displaying the collected + * ADC samples. + */ + +#if defined(CONFIG_NSH_BUILTIN_APPS) + for (; g_adcstate.count > 0; g_adcstate.count--) +#elif defined(CONFIG_EXAMPLES_ADC_NSAMPLES) + for (g_adcstate.count = 0; g_adcstate.count < CONFIG_EXAMPLES_ADC_NSAMPLES; g_adcstate.count++) +#else + for (;;) +#endif + { + /* Flush any output before the loop entered or from the previous pass + * through the loop. + */ + + msgflush(); + + /* Read CONFIG_EXAMPLES_ADC_GROUPSIZE samples */ + + readsize = CONFIG_EXAMPLES_ADC_GROUPSIZE * sizeof(struct adc_msg_s); + nbytes = read(fd, sample, readsize); + + /* Handle unexpected return values */ + + if (nbytes < 0) + { + errval = errno; + if (errval != EINTR) + { + message(MAIN_STRING "read %s failed: %d\n", + g_adcstate.devpath, errval); + errval = 3; + goto errout_with_dev; + } + + message(MAIN_STRING "Interrupted read...\n"); + } + else if (nbytes == 0) + { + message(MAIN_STRING "No data read, Ignoring\n"); + } + + /* Print the sample data on successful return */ + + else + { + int nsamples = nbytes / sizeof(struct adc_msg_s); + if (nsamples * sizeof(struct adc_msg_s) != nbytes) + { + message(MAIN_STRING "read size=%d is not a multiple of sample size=%d, Ignoring\n", + nbytes, sizeof(struct adc_msg_s)); + } + else + { + message("Sample:\n"); + for (i = 0; i < nsamples ; i++) + { + message("%d: channel: %d value: %d\n", + i, sample[i].am_channel, sample[i].am_data); + } + } + } + } + +errout_with_dev: + close(fd); + +errout: + message("Terminating!\n"); + msgflush(); + return errval; +} diff --git a/apps/examples/buttons/Kconfig b/apps/examples/buttons/Kconfig new file mode 100644 index 0000000000..9c34b37bcb --- /dev/null +++ b/apps/examples/buttons/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_BUTTONS + bool "Buttons example" + default n + ---help--- + Enable the buttons example + +if EXAMPLES_BUTTONS +endif diff --git a/apps/examples/buttons/Makefile b/apps/examples/buttons/Makefile new file mode 100644 index 0000000000..9c05871998 --- /dev/null +++ b/apps/examples/buttons/Makefile @@ -0,0 +1,105 @@ +############################################################################ +# apps/examples/buttons/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# Hello, World! Example + +ASRCS = +CSRCS = main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Buttons built-in application info + +APPNAME = buttons +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Common build + +VPATH = + +all: .built +.PHONY: context clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: +ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ +endif + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/buttons/main.c b/apps/examples/buttons/main.c new file mode 100644 index 0000000000..fe447ca6b6 --- /dev/null +++ b/apps/examples/buttons/main.c @@ -0,0 +1,509 @@ +/**************************************************************************** + * examples/buttons/main.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * NOTE: This test exercises internal button driver interfaces. As such, it + * it relies on internal OS interfaces that are not normally available to a + * user-space program. As a result, this example cannot be used if a + * NuttX is built as a protected, supervisor kernel (CONFIG_NUTTX_KERNEL). + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +#ifndef CONFIG_ARCH_BUTTONS +# error "CONFIG_ARCH_BUTTONS is not defined in the configuration" +#endif + +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME0 +# define CONFIG_EXAMPLE_BUTTONS_NAME0 "BUTTON0" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME1 +# define CONFIG_EXAMPLE_BUTTONS_NAME1 "BUTTON1" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME2 +# define CONFIG_EXAMPLE_BUTTONS_NAME2 "BUTTON2" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME3 +# define CONFIG_EXAMPLE_BUTTONS_NAME3 "BUTTON3" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME4 +# define CONFIG_EXAMPLE_BUTTONS_NAME4 "BUTTON4" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME5 +# define CONFIG_EXAMPLE_BUTTONS_NAME5 "BUTTON5" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME6 +# define CONFIG_EXAMPLE_BUTTONS_NAME6 "BUTTON6" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME7 +# define CONFIG_EXAMPLE_BUTTONS_NAME7 "BUTTON7" +#endif + +#define BUTTON_MIN 0 +#define BUTTON_MAX 7 + +#ifndef CONFIG_EXAMPLE_BUTTONS_MIN +# define CONFIG_EXAMPLE_BUTTONS_MIN BUTTON_MIN +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_MAX +# define CONFIG_EXAMPLE_BUTTONS_MAX BUTTON_MAX +#endif + +#if CONFIG_EXAMPLE_BUTTONS_MIN > CONFIG_EXAMPLE_BUTTONS_MAX +# error "CONFIG_EXAMPLE_BUTTONS_MIN > CONFIG_EXAMPLE_BUTTONS_MAX" +#endif +#if CONFIG_EXAMPLE_BUTTONS_MAX > 7 +# error "CONFIG_EXAMPLE_BUTTONS_MAX > 7" +#endif + +#ifndef CONFIG_EXAMPLE_IRQBUTTONS_MIN +# define CONFIG_EXAMPLE_IRQBUTTONS_MIN CONFIG_EXAMPLE_BUTTONS_MIN +#endif +#ifndef CONFIG_EXAMPLE_IRQBUTTONS_MAX +# define CONFIG_EXAMPLE_IRQBUTTONS_MAX CONFIG_EXAMPLE_BUTTONS_MAX +#endif + +#if CONFIG_EXAMPLE_IRQBUTTONS_MIN > CONFIG_EXAMPLE_IRQBUTTONS_MAX +# error "CONFIG_EXAMPLE_IRQBUTTONS_MIN > CONFIG_EXAMPLE_IRQBUTTONS_MAX" +#endif +#if CONFIG_EXAMPLE_IRQBUTTONS_MAX > 7 +# error "CONFIG_EXAMPLE_IRQBUTTONS_MAX > 7" +#endif + +#ifndef MIN +# define MIN(a,b) (a < b ? a : b) +#endif +#ifndef MAX +# define MAX(a,b) (a > b ? a : b) +#endif + +#define MIN_BUTTON MIN(CONFIG_EXAMPLE_BUTTONS_MIN, CONFIG_EXAMPLE_IRQBUTTONS_MIN) +#define MAX_BUTTON MAX(CONFIG_EXAMPLE_BUTTONS_MAX, CONFIG_EXAMPLE_IRQBUTTONS_MAX) + +#define NUM_BUTTONS (MAX_BUTTON - MIN_BUTTON + 1) +#define BUTTON_INDEX(b) ((b)-MIN_BUTTON) + +/* Is this being built as an NSH built-in application? */ + +#ifdef CONFIG_NSH_BUILTIN_APPS +# define MAIN_NAME buttons_main +# define MAIN_STRING "buttons_main: " +#else +# define MAIN_NAME user_start +# define MAIN_STRING "user_start: " +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct button_info_s +{ + FAR const char *name; /* Name for the button */ +#ifdef CONFIG_ARCH_IRQBUTTONS + xcpt_t handler; /* Button interrupt handler */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void show_buttons(uint8_t oldset, uint8_t newset); + +#ifdef CONFIG_ARCH_IRQBUTTONS +static void button_handler(int id, int irq); + +#if MIN_BUTTON < 1 +static int button0_handler(int irq, FAR void *context); +#endif +#if MIN_BUTTON < 2 && MAX_BUTTON > 0 +static int button1_handler(int irq, FAR void *context); +#endif +#if MIN_BUTTON < 3 && MAX_BUTTON > 1 +static int button2_handler(int irq, FAR void *context); +#endif +#if MIN_BUTTON < 4 && MAX_BUTTON > 2 +static int button3_handler(int irq, FAR void *context); +#endif +#if MIN_BUTTON < 5 && MAX_BUTTON > 3 +static int button4_handler(int irq, FAR void *context); +#endif +#if MIN_BUTTON < 6 && MAX_BUTTON > 4 +static int button5_handler(int irq, FAR void *context); +#endif +#if MIN_BUTTON < 7 && MAX_BUTTON > 5 +static int button6_handler(int irq, FAR void *context); +#endif +#if MAX_BUTTON > 6 +static int button7_handler(int irq, FAR void *context); +#endif +#endif /* CONFIG_ARCH_IRQBUTTONS */ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + + /* Button Names */ + +static const struct button_info_s g_buttoninfo[NUM_BUTTONS] = +{ +#if MIN_BUTTON < 1 + { + CONFIG_EXAMPLE_BUTTONS_NAME0, +#ifdef CONFIG_ARCH_IRQBUTTONS + button0_handler +#endif + }, +#endif +#if MIN_BUTTON < 2 && MAX_BUTTON > 0 + { + CONFIG_EXAMPLE_BUTTONS_NAME1, +#ifdef CONFIG_ARCH_IRQBUTTONS + button1_handler +#endif + }, +#endif +#if MIN_BUTTON < 3 && MAX_BUTTON > 1 + { + CONFIG_EXAMPLE_BUTTONS_NAME2, +#ifdef CONFIG_ARCH_IRQBUTTONS + button2_handler +#endif + }, +#endif +#if MIN_BUTTON < 4 && MAX_BUTTON > 2 + { + CONFIG_EXAMPLE_BUTTONS_NAME3, +#ifdef CONFIG_ARCH_IRQBUTTONS + button3_handler +#endif + }, +#endif +#if MIN_BUTTON < 5 && MAX_BUTTON > 3 + { + CONFIG_EXAMPLE_BUTTONS_NAME4, +#ifdef CONFIG_ARCH_IRQBUTTONS + button4_handler +#endif + }, +#endif +#if MIN_BUTTON < 6 && MAX_BUTTON > 4 + { + CONFIG_EXAMPLE_BUTTONS_NAME5, +#ifdef CONFIG_ARCH_IRQBUTTONS + button5_handler +#endif + }, +#endif +#if MIN_BUTTON < 7 && MAX_BUTTON > 5 + { + CONFIG_EXAMPLE_BUTTONS_NAME6, +#ifdef CONFIG_ARCH_IRQBUTTONS + button6_handler +#endif + }, +#endif +#if MAX_BUTTON > 6 + { + CONFIG_EXAMPLE_BUTTONS_NAME7, +#ifdef CONFIG_ARCH_IRQBUTTONS + button7_handler +#endif + } +#endif +}; + +/* Last sampled button set */ + +static uint8_t g_oldset; + +/* Used to limit the number of button presses */ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static volatile long g_nbuttons; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void show_buttons(uint8_t oldset, uint8_t newset) +{ + uint8_t chgset = oldset ^ newset; + int i; + + /* Update the count of button presses shown */ + +#ifdef CONFIG_NSH_BUILTIN_APPS + if ((chgset & newset) != 0) + { + g_nbuttons++; + } +#endif + + /* Show each button state change */ + + for (i = MIN_BUTTON; i <= MAX_BUTTON; i++) + { + uint8_t mask = (1 << i); + if ((chgset & mask) != 0) + { + FAR const char *state; + + /* Get the button state */ + + if ((newset & mask) != 0) + { + state = "depressed"; + } + else + { + state = "released"; + } + + /* Use lib_lowprintf() because we make be executing from an + * interrupt handler. + */ + + lib_lowprintf(" %s %s\n", g_buttoninfo[BUTTON_INDEX(i)].name, state); + } + } +} + +#ifdef CONFIG_ARCH_IRQBUTTONS +static void button_handler(int id, int irq) +{ + uint8_t newset = up_buttons(); + + lib_lowprintf("IRQ:%d Button %d:%s SET:%02x:\n", + irq, id, g_buttoninfo[BUTTON_INDEX(id)].name, newset); + show_buttons(g_oldset, newset); + g_oldset = newset; +} + +#if MIN_BUTTON < 1 +static int button0_handler(int irq, FAR void *context) +{ + button_handler(0, irq); + return OK; +} +#endif + +#if MIN_BUTTON < 2 && MAX_BUTTON > 0 +static int button1_handler(int irq, FAR void *context) +{ + button_handler(1, irq); + return OK; +} +#endif + +#if MIN_BUTTON < 3 && MAX_BUTTON > 1 +static int button2_handler(int irq, FAR void *context) +{ + button_handler(2, irq); + return OK; +} +#endif + +#if MIN_BUTTON < 4 && MAX_BUTTON > 2 +static int button3_handler(int irq, FAR void *context) +{ + button_handler(3, irq); + return OK; +} +#endif + +#if MIN_BUTTON < 5 && MAX_BUTTON > 3 +static int button4_handler(int irq, FAR void *context) +{ + button_handler(4, irq); + return OK; +} +#endif + +#if MIN_BUTTON < 6 && MAX_BUTTON > 4 +static int button5_handler(int irq, FAR void *context) +{ + button_handler(5, irq); + return OK; +} +#endif + +#if MIN_BUTTON < 7 && MAX_BUTTON > 5 +static int button6_handler(int irq, FAR void *context) +{ + button_handler(6, irq); + return OK; +} +#endif + +#if MAX_BUTTON > 6 +static int button7_handler(int irq, FAR void *context) +{ + button_handler(7, irq); + return OK; +} +#endif +#endif /* CONFIG_ARCH_IRQBUTTONS */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * user_start/buttons_main + ****************************************************************************/ + +int MAIN_NAME(int argc, char *argv[]) +{ + uint8_t newset; + irqstate_t flags; + int i; + + /* If this example is configured as an NX add-on, then limit the number of + * samples that we collect before returning. Otherwise, we never return + */ + +#ifdef CONFIG_NSH_BUILTIN_APPS + long maxbuttons = 1; + g_nbuttons = 0; + if (argc > 1) + { + maxbuttons = strtol(argv[1], NULL, 10); + } + lib_lowprintf("maxbuttons: %d\n", maxbuttons); +#endif + + /* Initialize the button GPIOs */ + + up_buttoninit(); + + /* Register to recieve button interrupts */ + +#ifdef CONFIG_ARCH_IRQBUTTONS + for (i = CONFIG_EXAMPLE_IRQBUTTONS_MIN; i <= CONFIG_EXAMPLE_IRQBUTTONS_MAX; i++) + { + xcpt_t oldhandler = up_irqbutton(i, g_buttoninfo[BUTTON_INDEX(i)].handler); + + /* Use lib_lowprintf() for compatibility with interrrupt handler output. */ + + lib_lowprintf("Attached handler at %p to button %d [%s], oldhandler:%p\n", + g_buttoninfo[BUTTON_INDEX(i)].handler, i, + g_buttoninfo[BUTTON_INDEX(i)].name, oldhandler); + + /* Some hardware multiplexes different GPIO button sources to the same + * physical interrupt. If we register multiple such multiplexed button + * interrupts, then the second registration will overwrite the first. In + * this case, the first button interrupts may be aliased to the second + * interrupt handler (or worse, could be lost). + */ + + if (oldhandler != NULL) + { + lib_lowprintf("WARNING: oldhandler:%p is not NULL! " + "Button events may be lost or aliased!\n", + oldhandler); + } + } +#endif + + /* Poll button state */ + + g_oldset = up_buttons(); +#ifdef CONFIG_NSH_BUILTIN_APPS + while (g_nbuttons < maxbuttons) +#else + for (;;) +#endif + { + /* Get the set of pressed and release buttons. */ + + newset = up_buttons(); + + /* Any changes from the last sample? */ + + if (newset != g_oldset) + { + /* Disable interrupts so that output here will not collide with + * output from an interrupt handler. + */ + + flags = irqsave(); + + /* Use lib_lowprintf() for compatibility with interrrupt handler + * output. + */ + + lib_lowprintf("POLL SET:%02x:\n", newset); + show_buttons(g_oldset, newset); + g_oldset = newset; + irqrestore(flags); + } + + /* Sleep a little... but not long. This will determine how fast we + * poll for button changes. + */ + + usleep(150000); /* 150 Milliseconds */ + } + + /* Un-register button handlers */ + +#if defined(CONFIG_ARCH_IRQBUTTONS) && defined(CONFIG_NSH_BUILTIN_APPS) + for (i = CONFIG_EXAMPLE_IRQBUTTONS_MIN; i <= CONFIG_EXAMPLE_IRQBUTTONS_MAX; i++) + { + (void)up_irqbutton(i, NULL); + } +#endif + + return 0; +} + diff --git a/apps/examples/can/Kconfig b/apps/examples/can/Kconfig new file mode 100644 index 0000000000..2b4504d68b --- /dev/null +++ b/apps/examples/can/Kconfig @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_CAN + bool "CAN example" + default n + ---help--- + Enable the CAN example + +if EXAMPLES_CAN +endif + diff --git a/apps/examples/can/Makefile b/apps/examples/can/Makefile new file mode 100644 index 0000000000..c6dc5af84c --- /dev/null +++ b/apps/examples/can/Makefile @@ -0,0 +1,105 @@ +############################################################################ +# apps/examples/can/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# NuttX NX Graphics Example. + +ASRCS = +CSRCS = can_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Touchscreen built-in application info + +APPNAME = can +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Common build + +VPATH = + +all: .built +.PHONY: context clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: +ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ +endif + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/can/can.h b/apps/examples/can/can.h new file mode 100644 index 0000000000..53a6b63ea0 --- /dev/null +++ b/apps/examples/can/can.h @@ -0,0 +1,131 @@ +/**************************************************************************** + * examples/examples/can/can.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_EXAMPLES_CAN_CAN_H +#define __APPS_EXAMPLES_CAN_CAN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* This test depends on these specific CAN configurations settings (your + * specific CAN settings might require additional settings). + * + * CONFIG_CAN - Enables CAN support. + * CONFIG_CAN_LOOPBACK - A CAN driver may or may not support a loopback + * mode for testing. The STM32 CAN driver does support loopback mode. + * + * Specific configuration options for this example include: + * + * CONFIG_NSH_BUILTIN_APPS - Build the CAN test as an NSH built-in function. + * Default: Built as a standalone problem + * CONFIG_CAN_LOOPBACK + * CONFIG_EXAMPLES_CAN_DEVPATH - The path to the CAN device. Default: /dev/can0 + * CONFIG_EXAMPLES_CAN_NMSGS - If CONFIG_NSH_BUILTIN_APPS + * is defined, then the number of loops is provided on the command line + * and this value is ignored. Otherwise, this number of CAN message is + * collected and the program terminates. Default: If built as an NSH + * built-in, the default is 32. Otherwise messages are sent and received + * indefinitely. + * CONFIG_EXAMPLES_CAN_READONLY - Only receive messages + * CONFIG_EXAMPLES_CAN_WRITEONLY - Only send messages + */ + +#ifndef CONFIG_CAN +# error "CAN device support is not enabled (CONFIG_CAN)" +#endif + +#ifndef CONFIG_CAN_LOOPBACK +# warning "CAN loopback is not enabled (CONFIG_CAN_LOOPBACK)" +#endif + +#ifndef CONFIG_EXAMPLES_CAN_DEVPATH +# define CONFIG_EXAMPLES_CAN_DEVPATH "/dev/can0" +#endif + +#if defined(CONFIG_NSH_BUILTIN_APPS) && !defined(CONFIG_EXAMPLES_CAN_NMSGS) +# define CONFIG_EXAMPLES_CAN_NMSGS 32 +#endif + +/* Debug ********************************************************************/ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_DEBUG +# define message(...) lib_rawprintf(__VA_ARGS__) +# define msgflush() +# else +# define message(...) printf(__VA_ARGS__) +# define msgflush() fflush(stdout) +# endif +#else +# ifdef CONFIG_DEBUG +# define message lib_rawprintf +# define msgflush() +# else +# define message printf +# define msgflush() fflush(stdout) +# endif +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: can_devinit() + * + * Description: + * Perform architecuture-specific initialization of the CAN hardware. This + * interface must be provided by all configurations using apps/examples/can + * + ****************************************************************************/ + +int can_devinit(void); + +#endif /* __APPS_EXAMPLES_CAN_CAN_H */ diff --git a/apps/examples/can/can_main.c b/apps/examples/can/can_main.c new file mode 100644 index 0000000000..0ea729e5e8 --- /dev/null +++ b/apps/examples/can/can_main.c @@ -0,0 +1,309 @@ +/**************************************************************************** + * examples/can/can_main.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "can.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if defined(CONFIG_EXAMPLES_CAN_READONLY) +# undef CONFIG_EXAMPLES_CAN_WRITEONLY +# undef CONFIG_EXAMPLES_CAN_READWRITE +# define CAN_OFLAGS O_RDONLY +#elif defined(CONFIG_EXAMPLES_CAN_WRITEONLY) +# undef CONFIG_EXAMPLES_CAN_READWRITE +# define CAN_OFLAGS O_WRONLY +#else +# undef CONFIG_EXAMPLES_CAN_READWRITE +# define CONFIG_EXAMPLES_CAN_READWRITE 1 +# define CAN_OFLAGS O_RDWR +#endif + +#ifdef CONFIG_CAN_EXTID +# define MAX_ID (1 << 29) +#else +# define MAX_ID (1 << 11) +#endif + +#ifdef CONFIG_NSH_BUILTIN_APPS +# define MAIN_NAME can_main +# define MAIN_STRING "can_main: " +#else +# define MAIN_NAME user_start +# define MAIN_STRING "user_start: " +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start/can_main + ****************************************************************************/ + +int MAIN_NAME(int argc, char *argv[]) +{ +#ifndef CONFIG_EXAMPLES_CAN_READONLY + struct can_msg_s txmsg; +#ifdef CONFIG_CAN_EXTID + uint32_t msgid; +#else + uint16_t msgid; +#endif + int msgdlc; + uint8_t msgdata; +#endif + +#ifndef CONFIG_EXAMPLES_CAN_WRITEONLY + struct can_msg_s rxmsg; +#endif + + size_t msgsize; + ssize_t nbytes; +#if defined(CONFIG_NSH_BUILTIN_APPS) || defined(CONFIG_EXAMPLES_CAN_NMSGS) + long nmsgs; +#endif + + int fd; + int errval = 0; + int ret; + int i; + + /* If this example is configured as an NX add-on, then limit the number of + * samples that we collect before returning. Otherwise, we never return + */ + +#if defined(CONFIG_NSH_BUILTIN_APPS) + nmsgs = CONFIG_EXAMPLES_CAN_NMSGS; + if (argc > 1) + { + nmsgs = strtol(argv[1], NULL, 10); + } + message(MAIN_STRING "nmsgs: %d\n", nmsgs); +#elif defined(CONFIG_EXAMPLES_CAN_NMSGS) + message(MAIN_STRING "nmsgs: %d\n", CONFIG_EXAMPLES_CAN_NMSGS); +#endif + + /* Initialization of the CAN hardware is performed by logic external to + * this test. + */ + + message(MAIN_STRING "Initializing external CAN device\n"); + ret = can_devinit(); + if (ret != OK) + { + message(MAIN_STRING "can_devinit failed: %d\n", ret); + errval = 1; + goto errout; + } + + /* Open the CAN device for reading */ + + message(MAIN_STRING "Hardware initialized. Opening the CAN device\n"); + fd = open(CONFIG_EXAMPLES_CAN_DEVPATH, CAN_OFLAGS); + if (fd < 0) + { + message(MAIN_STRING "open %s failed: %d\n", + CONFIG_EXAMPLES_CAN_DEVPATH, errno); + errval = 2; + goto errout_with_dev; + } + + /* Now loop the appropriate number of times, performing one loopback test + * on each pass. + */ + +#ifndef CONFIG_EXAMPLES_CAN_READONLY + msgdlc = 1; + msgid = 1; + msgdata = 0; +#endif + +#if defined(CONFIG_NSH_BUILTIN_APPS) + for (; nmsgs > 0; nmsgs--) +#elif defined(CONFIG_EXAMPLES_CAN_NMSGS) + for (nmsgs = 0; nmsgs < CONFIG_EXAMPLES_CAN_NMSGS; nmsgs++) +#else + for (;;) +#endif + { + /* Flush any output before the loop entered or from the previous pass + * through the loop. + */ + + msgflush(); + + /* Construct the next TX message */ + +#ifndef CONFIG_EXAMPLES_CAN_READONLY + txmsg.cm_hdr.ch_id = msgid; + txmsg.cm_hdr.ch_rtr = false; + txmsg.cm_hdr.ch_dlc = msgdlc; +#ifdef CONFIG_CAN_EXTID + txmsg.cm_hdr.ch_extid = true; +#endif + + for (i = 0; i < msgdlc; i++) + { + txmsg.cm_data[i] = msgdata + i; + } + + /* Send the TX message */ + + msgsize = CAN_MSGLEN(msgdlc); + nbytes = write(fd, &txmsg, msgsize); + if (nbytes != msgsize) + { + message("ERROR: write(%d) returned %d\n", msgsize, nbytes); + errval = 3; + goto errout_with_dev; + } +#endif + +#ifdef CONFIG_EXAMPLES_CAN_WRITEONLY + message(" ID: %4d DLC: %d\n", msgid, msgdlc); +#endif + + /* Read the RX message */ + +#ifndef CONFIG_EXAMPLES_CAN_WRITEONLY + msgsize = sizeof(struct can_msg_s); + nbytes = read(fd, &rxmsg, msgsize); + if (nbytes < CAN_MSGLEN(0) || nbytes > msgsize) + { + message("ERROR: read(%d) returned %d\n", msgsize, nbytes); + errval = 4; + goto errout_with_dev; + } +#endif + +#ifndef CONFIG_EXAMPLES_CAN_READONLY + message(" ID: %4d DLC: %d\n", rxmsg.cm_hdr.id, rxmsg.cm_hdr.dlc); +#endif + + /* Verify that the received messages are the same */ + +#ifdef CONFIG_EXAMPLES_CAN_READWRITE + if (memcmp(&txmsg.cm_hdr, &rxmsg.cm_hdr, sizeof(struct can_hdr_s)) != 0) + { + message("ERROR: Sent header does not match received header:\n"); + lib_dumpbuffer("Sent header", (FAR const uint8_t*)&txmsg.cm_hdr, + sizeof(struct can_hdr_s)); + lib_dumpbuffer("Received header", (FAR const uint8_t*)&rxmsg.cm_hdr, + sizeof(struct can_hdr_s)); + errval = 4; + goto errout_with_dev; + } + + if (memcmp(txmsg.cm_data, rxmsg.cm_data, msgdlc) != 0) + { + message("ERROR: Data does not match. DLC=%d\n", msgdlc); + for (i = 0; i < msgdlc; i++) + { + message(" %d: TX %02x RX %02x\n", i, txmsg.cm_data[i], rxmsg.cm_data[i]); + errval = 5; + goto errout_with_dev; + } + } + + /* Report success */ + + message(" ID: %4d DLC: %d -- OK\n", msgid, msgdlc); +#endif + + /* Set up for the next pass */ + +#ifndef CONFIG_EXAMPLES_CAN_READONLY + msgdata += msgdlc; + + if (++msgid >= MAX_ID) + { + msgid = 1; + } + + if (++msgdlc > CAN_MAXDATALEN) + { + msgdlc = 1; + } +#endif + } + +errout_with_dev: + close(fd); + +errout: + message("Terminating!\n"); + msgflush(); + return errval; +} diff --git a/apps/examples/cdcacm/.context b/apps/examples/cdcacm/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/examples/cdcacm/Kconfig b/apps/examples/cdcacm/Kconfig new file mode 100644 index 0000000000..8cd9c6e999 --- /dev/null +++ b/apps/examples/cdcacm/Kconfig @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_CDCACM + bool "CAN example" + default n + ---help--- + Enable the USB CDC/ACM class driver example + +if EXAMPLES_CDCACM +endif + diff --git a/apps/examples/cdcacm/Makefile b/apps/examples/cdcacm/Makefile new file mode 100644 index 0000000000..3fa886d561 --- /dev/null +++ b/apps/examples/cdcacm/Makefile @@ -0,0 +1,109 @@ +############################################################################ +# apps/examples/cdcacm/Makefile +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# USB CDC/ACM serial mass storage example + +ASRCS = +CSRCS = cdcacm_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# USB CDC/ACM built-in application info + +APPNAME1 = sercon +PRIORITY1 = SCHED_PRIORITY_DEFAULT +STACKSIZE1 = 2048 + +APPNAME2 = serdis +PRIORITY2 = SCHED_PRIORITY_DEFAULT +STACKSIZE2 = 2048 + +# Common build + +VPATH = + +all: .built +.PHONY: context clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: + $(call REGISTER,$(APPNAME1),$(PRIORITY1),$(STACKSIZE1),$(APPNAME1)_main) + $(call REGISTER,$(APPNAME2),$(PRIORITY2),$(STACKSIZE2),$(APPNAME2)_main) + @touch $@ + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep + diff --git a/apps/examples/cdcacm/cdcacm.h b/apps/examples/cdcacm/cdcacm.h new file mode 100644 index 0000000000..18570bff0c --- /dev/null +++ b/apps/examples/cdcacm/cdcacm.h @@ -0,0 +1,165 @@ +/**************************************************************************** + * examples/cdcacm/cdcacm.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __EXAMPLES_CDCACM_CDCACM_H +#define __EXAMPLES_CDCACM_CDCACM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* Prerequisites */ + +#ifndef CONFIG_USBDEV +# error "CONFIG_USBDEV is not defined" +#endif + +#ifndef CONFIG_CDCACM +# error "CONFIG_CDCACM is not defined" +#endif + +#ifndef CONFIG_NSH_BUILTIN_APPS +# error "This example can only be built as an NSH built-in application" +#endif + +/* Default configuration values */ + +#ifndef CONFIG_EXAMPLES_CDCACM_DEVMINOR +# define CONFIG_EXAMPLES_CDCACM_DEVMINOR 0 +#endif + +/* Trace Configuration ******************************************************/ + +#ifdef CONFIG_EXAMPLES_CDCACM_TRACEINIT +# define TRACE_INIT_BITS (TRACE_INIT_BIT) +#else +# define TRACE_INIT_BITS (0) +#endif + +#define TRACE_ERROR_BITS (TRACE_DEVERROR_BIT|TRACE_CLSERROR_BIT) + +#ifdef CONFIG_EXAMPLES_CDCACM_TRACECLASS +# define TRACE_CLASS_BITS (TRACE_CLASS_BIT|TRACE_CLASSAPI_BIT|TRACE_CLASSSTATE_BIT) +#else +# define TRACE_CLASS_BITS (0) +#endif + +#ifdef CONFIG_EXAMPLES_CDCACM_TRACETRANSFERS +# define TRACE_TRANSFER_BITS (TRACE_OUTREQQUEUED_BIT|TRACE_INREQQUEUED_BIT|TRACE_READ_BIT|\ + TRACE_WRITE_BIT|TRACE_COMPLETE_BIT) +#else +# define TRACE_TRANSFER_BITS (0) +#endif + +#ifdef CONFIG_EXAMPLES_CDCACM_TRACECONTROLLER +# define TRACE_CONTROLLER_BITS (TRACE_EP_BIT|TRACE_DEV_BIT) +#else +# define TRACE_CONTROLLER_BITS (0) +#endif + +#ifdef CONFIG_EXAMPLES_CDCACM_TRACEINTERRUPTS +# define TRACE_INTERRUPT_BITS (TRACE_INTENTRY_BIT|TRACE_INTDECODE_BIT|TRACE_INTEXIT_BIT) +#else +# define TRACE_INTERRUPT_BITS (0) +#endif + +#define TRACE_BITSET (TRACE_INIT_BITS|TRACE_ERROR_BITS|TRACE_CLASS_BITS|\ + TRACE_TRANSFER_BITS|TRACE_CONTROLLER_BITS|TRACE_INTERRUPT_BITS) + +/* Debug ********************************************************************/ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_DEBUG +# define message(...) lib_lowprintf(__VA_ARGS__) +# define msgflush() +# else +# define message(...) printf(__VA_ARGS__) +# define msgflush() fflush(stdout) +# endif +#else +# ifdef CONFIG_DEBUG +# define message lib_lowprintf +# define msgflush() +# else +# define message printf +# define msgflush() fflush(stdout) +# endif +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* All global variables used by this example are packed into a structure in + * order to avoid name collisions. + */ + +struct cdcacm_state_s +{ + /* This is the handle that references to this particular USB storage driver + * instance. It is only needed if the USB mass storage device example is + * built using CONFIG_NSH_BUILTIN_APPS. In this case, the value + * of the driver handle must be remembered between the 'sercon' and 'msdis' + * commands. + */ + + FAR void *handle; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* All global variables used by this example are packed into a structure in + * order to avoid name collisions. + */ + +extern struct cdcacm_state_s g_cdcacm; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* __EXAMPLES_CDCACM_CDCACM_H */ diff --git a/apps/examples/cdcacm/cdcacm_main.c b/apps/examples/cdcacm/cdcacm_main.c new file mode 100644 index 0000000000..aeb7a9e745 --- /dev/null +++ b/apps/examples/cdcacm/cdcacm_main.c @@ -0,0 +1,147 @@ +/**************************************************************************** + * examples/cdcacm/cdcacm_main.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include +#include + +#include "cdcacm.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* All global variables used by this example are packed into a structure in + * order to avoid name collisions. + */ + +struct cdcacm_state_s g_cdcacm; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * sercon_main + * + * Description: + * This is the main program that configures the CDC/ACM serial device. + * + ****************************************************************************/ + +int sercon_main(int argc, char *argv[]) +{ + int ret; + + /* Check if there is a non-NULL USB mass storage device handle (meaning that the + * USB mass storage device is already configured). + */ + + if (g_cdcacm.handle) + { + message("sercon:: ERROR: Already connected\n"); + return EXIT_FAILURE; + } + + /* Then, in any event, enable trace data collection as configured BEFORE + * enabling the CDC/ACM device. + */ + + usbtrace_enable(TRACE_BITSET); + + /* Initialize the USB CDC/ACM serial driver */ + + message("sercon: Registering CDC/ACM serial driver\n"); + ret = cdcacm_initialize(CONFIG_EXAMPLES_CDCACM_DEVMINOR, &g_cdcacm.handle); + if (ret < 0) + { + message("sercon: ERROR: Failed to create the CDC/ACM serial device: %d\n", -ret); + return EXIT_FAILURE; + } + + message("sercon: Successfully registered the CDC/ACM serial driver\n"); + return EXIT_SUCCESS; +} + +/**************************************************************************** + * serdis_main + * + * Description: + * This is a program entry point that will disconnect the CDC/ACM serial + * device. + * + ****************************************************************************/ + +int serdis_main(int argc, char *argv[]) +{ + /* First check if the USB mass storage device is already connected */ + + if (!g_cdcacm.handle) + { + message("serdis: ERROR: Not connected\n"); + return EXIT_FAILURE; + } + + /* Then, in any event, disable trace data collection as configured BEFORE + * enabling the CDC/ACM device. + */ + + usbtrace_enable(0); + + /* Then disconnect the device and uninitialize the USB mass storage driver */ + + cdcacm_uninitialize(g_cdcacm.handle); + g_cdcacm.handle = NULL; + message("serdis: Disconnected\n"); + return EXIT_SUCCESS; +} diff --git a/apps/examples/hello/Kconfig b/apps/examples/hello/Kconfig new file mode 100644 index 0000000000..d697daa8a2 --- /dev/null +++ b/apps/examples/hello/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_HELLO + bool "\"Hello, World!\" example" + default n + ---help--- + Enable the \"Hello, World!\" example + +if EXAMPLES_HELLO +endif diff --git a/apps/examples/hello/Makefile b/apps/examples/hello/Makefile new file mode 100644 index 0000000000..9c3cda894b --- /dev/null +++ b/apps/examples/hello/Makefile @@ -0,0 +1,105 @@ +############################################################################ +# apps/examples/hello/Makefile +# +# Copyright (C) 2008, 2010-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# Hello, World! built-in application info + +APPNAME = hello +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Hello, World! Example + +ASRCS = +CSRCS = main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: +ifeq ($(CONFIG_EXAMPLES_HELLO_BUILTIN),y) + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ +endif + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/hello/main.c b/apps/examples/hello/main.c new file mode 100644 index 0000000000..7934dc34ba --- /dev/null +++ b/apps/examples/hello/main.c @@ -0,0 +1,70 @@ +/**************************************************************************** + * examples/hello/main.c + * + * Copyright (C) 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * user_start/hello_main + ****************************************************************************/ + +#ifdef CONFIG_EXAMPLES_HELLO_BUILTIN +# define MAIN_NAME hello_main +#else +# define MAIN_NAME user_start +#endif + +int MAIN_NAME(int argc, char *argv[]) +{ + printf("Hello, World!!\n"); + return 0; +} + diff --git a/apps/examples/helloxx/Kconfig b/apps/examples/helloxx/Kconfig new file mode 100644 index 0000000000..336389d24e --- /dev/null +++ b/apps/examples/helloxx/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_HELLOXX + bool "\"Hello, World!\" C++ example" + default n + ---help--- + Enable the \"Hello, World!\" C++ example + +if EXAMPLES_HELLOXX +endif diff --git a/apps/examples/helloxx/Makefile b/apps/examples/helloxx/Makefile new file mode 100644 index 0000000000..c34378d249 --- /dev/null +++ b/apps/examples/helloxx/Makefile @@ -0,0 +1,122 @@ +############################################################################ +# apps/examples/helloxx/Makefile +# +# Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# Hello, World! C++ Example + +ASRCS = +CSRCS = +CXXSRCS = main.cxx + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) +CXXOBJS = $(CXXSRCS:.cxx=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) $(CXXSRCS) +OBJS = $(AOBJS) $(COBJS) $(CXXOBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# helloxx built-in application info + +APPNAME = helloxx +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend disclean chkcxx + +chkcxx: +ifneq ($(CONFIG_HAVE_CXX),y) + @echo "" + @echo "In order to use this example, you toolchain must support must" + @echo "" + @echo " (1) Explicitly select CONFIG_HAVE_CXX to build in C++ support" + @echo " (2) Define CXX, CXXFLAGS, and COMPILEXX in the Make.defs file" + @echo " of the configuration that you are using." + @echo "" + @exit 1 +endif + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(CXXOBJS): %$(OBJEXT): %.cxx + $(call COMPILEXX, $<, $@) + +.built: chkcxx $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: +ifeq ($(CONFIG_EXAMPLES_HELLOXX_BUILTIN),y) + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ +endif + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/helloxx/main.cxx b/apps/examples/helloxx/main.cxx new file mode 100644 index 0000000000..8514fead22 --- /dev/null +++ b/apps/examples/helloxx/main.cxx @@ -0,0 +1,178 @@ +//*************************************************************************** +// examples/helloxx/main.cxx +// +// Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +#include +#include + +#include +#include + +//*************************************************************************** +// Definitions +//*************************************************************************** +// Debug ******************************************************************** +// Non-standard debug that may be enabled just for testing the constructors + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_CXX +#endif + +#ifdef CONFIG_DEBUG_CXX +# define cxxdbg dbg +# define cxxlldbg lldbg +# ifdef CONFIG_DEBUG_VERBOSE +# define cxxvdbg vdbg +# define cxxllvdbg llvdbg +# else +# define cxxvdbg(x...) +# define cxxllvdbg(x...) +# endif +#else +# define cxxdbg(x...) +# define cxxlldbg(x...) +# define cxxvdbg(x...) +# define cxxllvdbg(x...) +#endif + +//*************************************************************************** +// Private Classes +//*************************************************************************** + +class CHelloWorld +{ + public: + CHelloWorld(void) : mSecret(42) + { + cxxdbg("Constructor: mSecret=%d\n", mSecret); + } + + ~CHelloWorld(void) + { + cxxdbg("Destructor\n"); + } + + bool HelloWorld(void) + { + cxxdbg("HelloWorld: mSecret=%d\n", mSecret); + + if (mSecret != 42) + { + printf("CHelloWorld::HelloWorld: CONSTRUCTION FAILED!\n"); + return false; + } + else + { + printf("CHelloWorld::HelloWorld: Hello, World!!\n"); + return true; + } + } + + private: + int mSecret; +}; + +//*************************************************************************** +// Private Data +//*************************************************************************** + +// Define a statically constructed CHellowWorld instance if C++ static +// initializers are supported by the platform + +#ifdef CONFIG_HAVE_CXXINITIALIZE +static CHelloWorld g_HelloWorld; +#endif + +//*************************************************************************** +// Public Functions +//*************************************************************************** + +//*************************************************************************** +// user_start +//*************************************************************************** + +/**************************************************************************** + * Name: user_start/nxhello_main + ****************************************************************************/ + +#ifdef CONFIG_EXAMPLES_HELLOXX_BUILTIN +extern "C" int helloxx_main(int argc, char *argv[]); +# define MAIN_NAME helloxx_main +# define MAIN_STRING "helloxx_main: " +#else +# define MAIN_NAME user_start +# define MAIN_STRING "user_start: " +#endif + +int MAIN_NAME(int argc, char *argv[]) +{ + // If C++ initialization for static constructors is supported, then do + // that first + +#ifdef CONFIG_HAVE_CXXINITIALIZE + up_cxxinitialize(); +#endif + + // Exercise an explictly instantiated C++ object + + CHelloWorld *pHelloWorld = new CHelloWorld; + printf(MAIN_STRING "Saying hello from the dynamically constructed instance\n"); + pHelloWorld->HelloWorld(); + + // Exercise an C++ object instantiated on the stack + +#ifndef CONFIG_EXAMPLES_HELLOXX_NOSTACKCONST + CHelloWorld HelloWorld; + + printf(MAIN_STRING "Saying hello from the instance constructed on the stack\n"); + HelloWorld.HelloWorld(); +#endif + + // Exercise an statically constructed C++ object + +#ifdef CONFIG_HAVE_CXXINITIALIZE + printf(MAIN_STRING "Saying hello from the statically constructed instance\n"); + g_HelloWorld.HelloWorld(); +#endif + + delete pHelloWorld; + return 0; +} + diff --git a/apps/examples/lcdrw/Kconfig b/apps/examples/lcdrw/Kconfig new file mode 100644 index 0000000000..2308ddc60a --- /dev/null +++ b/apps/examples/lcdrw/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_LCDRW + bool "LCD read/write example" + default n + ---help--- + Enable the LCD read/write example + +if EXAMPLES_LCDRW +endif diff --git a/apps/examples/lcdrw/Makefile b/apps/examples/lcdrw/Makefile new file mode 100644 index 0000000000..053c626703 --- /dev/null +++ b/apps/examples/lcdrw/Makefile @@ -0,0 +1,105 @@ +############################################################################ +# apps/examples/lcdrw/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# LCD Read/Write Test + +ASRCS = +CSRCS = lcdrw_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# LCD R/W built-in application info + +APPNAME = lcdrw +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: +ifeq ($(CONFIG_EXAMPLES_LCDRW_BUILTIN),y) + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ +endif + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/lcdrw/lcdrw_main.c b/apps/examples/lcdrw/lcdrw_main.c new file mode 100644 index 0000000000..c366743f47 --- /dev/null +++ b/apps/examples/lcdrw/lcdrw_main.c @@ -0,0 +1,259 @@ +/**************************************************************************** + * examples/lcdrw/lcdrw_main.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* Most of the NX configuration settings are probbably *not* needed by this + * example. But, presumeably you are using NX too and so the checks might + * be good for you. + */ + +#ifndef CONFIG_NX +# error "CONFIG_NX must be defined to use this test" +#endif + +#ifndef CONFIG_NX_LCDDRIVER +# error "CONFIG_NX_LCDDRIVER must be defined to use this test" +#endif + +#ifndef CONFIG_EXAMPLES_LCDRW_BPP +# define CONFIG_EXAMPLES_LCDRW_BPP 16 +#endif + +#if CONFIG_EXAMPLES_LCDRW_BPP != 16 +# error "Currently only RGB565 is supported -- feel free to extend" +#endif + +#ifdef CONFIG_NX_DISABLE_16BPP +# error "CONFIG_NX_DISABLE_16BPP disables 16-bit support" +#endif + +#ifndef CONFIG_EXAMPLES_LDCRW_DEVNO +# define CONFIG_EXAMPLES_LDCRW_DEVNO 0 +#endif + +#ifndef CONFIG_EXAMPLES_LDCRW_XRES +# define CONFIG_EXAMPLES_LDCRW_XRES 240 +#endif + +#ifndef CONFIG_EXAMPLES_LDCRW_YRES +# define CONFIG_EXAMPLES_LDCRW_YRES 320 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct lcdrw_instance_s +{ + /* LCD device handle and planeinfo */ + + FAR struct lcd_dev_s *dev; + struct lcd_planeinfo_s pinfo; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: lcdrw_initialize + ****************************************************************************/ + +static inline int lcdrw_initialize(FAR struct lcdrw_instance_s *inst) +{ + int ret; + + /* Initialize the LCD device */ + + printf("screens_initialize: Initializing LCD\n"); + ret = up_lcdinitialize(); + if (ret < 0) + { + fprintf(stderr, "screens_initialize: up_lcdinitialize failed: %d\n", -ret); + return ret; + } + + /* Get the device instance. */ + + printf("Get LCD instance\n"); + inst->dev = up_lcdgetdev(CONFIG_EXAMPLES_LDCRW_DEVNO); + if (!inst->dev) + { + fprintf(stderr, "up_lcdgetdev failed, devno=%d\n", CONFIG_EXAMPLES_LDCRW_DEVNO); + return ret; + } + + /* Turn the LCD on at 75% power. This should not be necessary. */ + + (void)inst->dev->setpower(inst->dev, ((3*CONFIG_LCD_MAXPOWER + 3)/4)); + + /* Get the planeinfo structure */ + + ret = inst->dev->getplaneinfo(inst->dev, 0, &inst->pinfo); + if (ret < 0) + { + fprintf(stderr, "getplaneinfo failed: %d\n", ret); + } + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lcdrw_main/user_start + ****************************************************************************/ + +#ifdef CONFIG_EXAMPLES_LCDRW_BUILTIN +# define MAIN_NAME lcdrw_main +#else +# define MAIN_NAME user_start +#endif + +int MAIN_NAME(int argc, char *argv[]) +{ + struct lcdrw_instance_s inst; + nxgl_coord_t row; + nxgl_coord_t col; + uint16_t value; + uint32_t offset; + FAR uint16_t *ptr; + int ret; + + /* Initialize the LCD driver */ + + ret = lcdrw_initialize(&inst); + if (ret < 0) + { + exit(1); + } + + /* Loop, writing all possible values to the LCD */ + + value = 0; + for (row = 0; row < CONFIG_EXAMPLES_LDCRW_YRES; row++) + { + /* Create a dummy row. The important thing is to try all + * bit combinations in a predictable way. + */ + + ptr = (FAR uint16_t*)inst.pinfo.buffer; + for (col = 0; col < CONFIG_EXAMPLES_LDCRW_XRES; col++) + { + *ptr++ = value++; + } + + /* Write the row to the LCD */ + + ret = inst.pinfo.putrun(row, 0, inst.pinfo.buffer, + CONFIG_EXAMPLES_LDCRW_XRES); + if (ret < 0) + { + fprintf(stderr, "putrun failed: %d\n", ret); + exit(1); + } + } + + /* Print a header */ + + printf(" "); + for (col = 0; col < 15; col++) + { + printf("---%x ", col); + } + printf("---f\n"); + + /* Then read each line back from the LCD. */ + + offset = 0; + for (row = 0; row < CONFIG_EXAMPLES_LDCRW_YRES; row++) + { + /* Read the row */ + + ret = inst.pinfo.getrun(row, 0, inst.pinfo.buffer, + CONFIG_EXAMPLES_LDCRW_XRES); + if (ret < 0) + { + fprintf(stderr, "getrun failed: %d\n", ret); + exit(1); + } + + /* Then dump the row to the display */ + + ptr = (FAR uint16_t*)inst.pinfo.buffer; + for (col = 0; col < CONFIG_EXAMPLES_LDCRW_XRES; col++) + { + if ((offset & 15) == 0) + { + printf("%06x ", offset); + } + + value = *ptr++; + offset++; + + if ((offset & 15) == 0) + { + printf("%04x\n", value); + } + else + { + printf("%04x ", value); + } + } + } + fflush(stdout); + + return 0; +} + diff --git a/apps/examples/mm/Kconfig b/apps/examples/mm/Kconfig new file mode 100644 index 0000000000..81ce4c4537 --- /dev/null +++ b/apps/examples/mm/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_MM + bool "Memory management example" + default n + ---help--- + Enable the memory management example + +if EXAMPLES_MM +endif diff --git a/apps/examples/mm/Makefile b/apps/examples/mm/Makefile new file mode 100644 index 0000000000..e5d9ffb4cf --- /dev/null +++ b/apps/examples/mm/Makefile @@ -0,0 +1,93 @@ +############################################################################ +# apps/examples/mm/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# Memory Management Test + +ASRCS = +CSRCS = mm_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +context: + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/mm/mm_main.c b/apps/examples/mm/mm_main.c new file mode 100644 index 0000000000..036c390474 --- /dev/null +++ b/apps/examples/mm/mm_main.c @@ -0,0 +1,300 @@ +/**************************************************************************** + * examples/mm/mm_main.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NTEST_ALLOCS 32 + +/* #define STOP_ON_ERRORS do{}while(0) */ +#define STOP_ON_ERRORS exit(1) + +/* All other definitions derive from these two */ + +#define MM_MIN_SHIFT 4 /* 16 bytes */ +#define MM_MIN_CHUNK (1 << MM_MIN_SHIFT) +#define MM_GRAN_MASK (MM_MIN_CHUNK-1) +#define MM_ALIGN_UP(a) (((a) + MM_GRAN_MASK) & ~MM_GRAN_MASK) +#define MM_ALIGN_DOWN(a) ((a) & ~MM_GRAN_MASK) + +#ifdef CONFIG_SMALL_MEMORY +# define SIZEOF_MM_ALLOCNODE 4 +#else +# define SIZEOF_MM_ALLOCNODE 8 +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* Test allocations */ + +static const int alloc_sizes[NTEST_ALLOCS] = +{ + 1024, 12, 962, 5692, 10254, 111, 9932, 601, + 222, 2746, 3, 124321, 68, 776, 6750, 852, + 4732, 28, 901, 480, 5011, 1536, 2011, 81647, + 646, 1646, 69179, 194, 2590, 7, 969, 70 +}; + +static const int realloc_sizes[NTEST_ALLOCS] = +{ + 18, 3088, 963, 123, 511, 11666, 3723, 42, + 9374, 1990, 1412, 6, 592, 4088, 11, 5040, + 8663, 91255, 28, 4346, 9172, 168, 229, 4734, + 59139, 221, 7830, 30421, 1666, 4, 812, 416 +}; + +static const int random1[NTEST_ALLOCS] = +{ + 20, 11, 3, 31, 9, 29, 7, 17, + 21, 2, 26, 18, 14, 25, 0, 10, + 27, 19, 22, 28, 8, 30, 12, 15, + 4, 1, 24, 6, 16, 13, 5, 23 +}; + +static const int random2[NTEST_ALLOCS] = +{ + 2, 19, 12, 23, 30, 11, 27, 4, + 20, 7, 0, 16, 28, 15, 5, 24, + 10, 17, 25, 31, 8, 29, 3, 26, + 9, 18, 22, 13, 1, 21, 14, 6 +}; + +static const int random3[NTEST_ALLOCS] = +{ + 8, 17, 3, 18, 26, 23, 30, 11, + 12, 22, 4, 20, 25, 10, 27, 1, + 29, 14, 19, 21, 0, 31, 7, 24, + 9, 15, 2, 28, 16, 6, 13, 5 +}; + +static const int alignment[NTEST_ALLOCS/2] = +{ + 128, 2048, 131072, 8192, 32, 32768, 16384 , 262144, + 512, 4096, 65536, 8, 64, 1024, 16, 4 +}; + +static void *allocs[NTEST_ALLOCS]; +static struct mallinfo alloc_info; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void mm_showmallinfo(void) +{ + alloc_info = mallinfo(); + printf(" mallinfo:\n"); + printf(" Total space allocated from system = %ld\n", + alloc_info.arena); + printf(" Number of non-inuse chunks = %ld\n", + alloc_info.ordblks); + printf(" Largest non-inuse chunk = %ld\n", + alloc_info.mxordblk); + printf(" Total allocated space = %ld\n", + alloc_info.uordblks); + printf(" Total non-inuse space = %ld\n", + alloc_info.fordblks); +} + +static void do_mallocs(void **mem, const int *size, const int *seq, int n) +{ + int i; + int j; + + for (i = 0; i < n; i++) + { + j = seq[i]; + if (!mem[j]) + { + printf("(%d)Allocating %d bytes\n", i, size[j]); + mem[j] = malloc(size[j]); + printf("(%d)Memory allocated at %p\n", i, mem[j]); + if (mem[j] == NULL) + { + int allocsize = MM_ALIGN_UP(size[j] + SIZEOF_MM_ALLOCNODE); + fprintf(stderr, "(%d)malloc failed for allocsize=%d\n", i, allocsize); + if (allocsize > alloc_info.mxordblk) + { + fprintf(stderr, " Normal, largest free block is only %ld\n", alloc_info.mxordblk); + } + else + { + fprintf(stderr, " ERROR largest free block is %ld\n", alloc_info.mxordblk); + exit(1); + } + } + else + { + memset(mem[j], 0xAA, size[j]); + } + + mm_showmallinfo(); + } + } +} + +static void do_reallocs(void **mem, const int *oldsize, const int *newsize, const int *seq, int n) +{ + int i; + int j; + + for (i = 0; i < n; i++) + { + j = seq[i]; + printf("(%d)Re-allocating at %p from %d to %d bytes\n", + i, mem[j], oldsize[j], newsize[j]); + mem[j] = realloc(mem[j], newsize[j]); + printf("(%d)Memory re-allocated at %p\n", i, mem[j]); + if (mem[j] == NULL) + { + int allocsize = MM_ALIGN_UP(newsize[j] + SIZEOF_MM_ALLOCNODE); + fprintf(stderr, "(%d)realloc failed for allocsize=%d\n", i, allocsize); + if (allocsize > alloc_info.mxordblk) + { + fprintf(stderr, " Normal, largest free block is only %ld\n", alloc_info.mxordblk); + } + else + { + fprintf(stderr, " ERROR largest free block is %ld\n", alloc_info.mxordblk); + exit(1); + } + } + else + { + memset(mem[j], 0x55, newsize[j]); + } + + mm_showmallinfo(); + } +} + +static void do_memaligns(void **mem, const int *size, const int *align, const int *seq, int n) +{ + int i; + int j; + + for (i = 0; i < n; i++) + { + j = seq[i]; + printf("(%d)Allocating %d bytes aligned to 0x%08x\n", + i, size[j], align[i]); + mem[j] = memalign(align[i], size[j]); + printf("(%d)Memory allocated at %p\n", i, mem[j]); + if (mem[j] == NULL) + { + int allocsize = MM_ALIGN_UP(size[j] + SIZEOF_MM_ALLOCNODE) + 2*align[i]; + fprintf(stderr, "(%d)memalign failed for allocsize=%d\n", i, allocsize); + if (allocsize > alloc_info.mxordblk) + { + fprintf(stderr, " Normal, largest free block is only %ld\n", alloc_info.mxordblk); + } + else + { + fprintf(stderr, " ERROR largest free block is %ld\n", alloc_info.mxordblk); + exit(1); + } + } + else + { + memset(mem[j], 0x33, size[j]); + } + + mm_showmallinfo(); + } +} + +static void do_frees(void **mem, const int *size, const int *seq, int n) +{ + int i; + int j; + + for (i = 0; i < n; i++) + { + j = seq[i]; + printf("(%d)Releasing memory at %p (size=%d bytes)\n", + i, mem[j], size[j]); + free(mem[j]); + mem[j] = NULL; + + mm_showmallinfo(); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + mm_showmallinfo(); + + /* Allocate some memory */ + + do_mallocs(allocs, alloc_sizes, random1, NTEST_ALLOCS); + + /* Re-allocate the memory */ + + do_reallocs(allocs, alloc_sizes, realloc_sizes, random2, NTEST_ALLOCS); + + /* Release the memory */ + + do_frees(allocs, realloc_sizes, random3, NTEST_ALLOCS); + + /* Allocate aligned memory */ + + do_memaligns(allocs, alloc_sizes, alignment, random2, NTEST_ALLOCS/2); + do_memaligns(allocs, alloc_sizes, alignment, &random2[NTEST_ALLOCS/2], NTEST_ALLOCS/2); + + /* Release aligned memory */ + + do_frees(allocs, alloc_sizes, random1, NTEST_ALLOCS); + + printf("TEST COMPLETE\n"); + return 0; +} diff --git a/apps/examples/mount/Kconfig b/apps/examples/mount/Kconfig new file mode 100644 index 0000000000..b38c4763c4 --- /dev/null +++ b/apps/examples/mount/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_MOUNT + bool "File system mount example" + default n + ---help--- + Enable the file system mount example + +if EXAMPLES_MOUNT +endif diff --git a/apps/examples/mount/Makefile b/apps/examples/mount/Makefile new file mode 100644 index 0000000000..7e48ea44a9 --- /dev/null +++ b/apps/examples/mount/Makefile @@ -0,0 +1,93 @@ +############################################################################ +# apps/Makefile +# +# Copyright (C) 2007-2008, 2010-2010 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# mount() test + +ASRCS = +CSRCS = mount_main.c ramdisk.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +context: + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/mount/mount.h b/apps/examples/mount/mount.h new file mode 100644 index 0000000000..68a03674da --- /dev/null +++ b/apps/examples/mount/mount.h @@ -0,0 +1,96 @@ +/**************************************************************************** + * examples/mount/mount.h + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __EXAMPLES_MOUNT_MOUNT_H +#define __EXAMPLES_MOUNT_MOUNT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Configure the test */ + +#if defined(CONFIG_EXAMPLES_MOUNT_DEVNAME) +# if !defined(CONFIG_FS_WRITABLE) +# error "Writable filesystem required in this configuration" +# endif +# undef CONFIG_EXAMPLES_MOUNT_NSECTORS +# undef CONFIG_EXAMPLES_MOUNT_SECTORSIZE +# undef CONFIG_EXAMPLES_MOUNT_RAMDEVNO +# define MOUNT_DEVNAME CONFIG_EXAMPLES_MOUNT_DEVNAME +#else +# if !defined(CONFIG_FS_FAT) +# error "CONFIG_FS_FAT required in this configuration" +# endif +# if !defined(CONFIG_EXAMPLES_MOUNT_SECTORSIZE) +# define CONFIG_EXAMPLES_MOUNT_SECTORSIZE 512 +# endif +# if !defined(CONFIG_EXAMPLES_MOUNT_NSECTORS) +# define CONFIG_EXAMPLES_MOUNT_NSECTORS 2048 +# endif +# if !defined(CONFIG_EXAMPLES_MOUNT_RAMDEVNO) +# define CONFIG_EXAMPLES_MOUNT_RAMDEVNO 0 +# endif +# define STR_RAMDEVNO(m) #m +# define MKMOUNT_DEVNAME(m) "/dev/ram" STR_RAMDEVNO(m) +# define MOUNT_DEVNAME MKMOUNT_DEVNAME(CONFIG_EXAMPLES_MOUNT_RAMDEVNO) +#endif + + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +extern const char g_source[]; /* Mount 'source' path */ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef CONFIG_EXAMPLES_MOUNT_DEVNAME +extern int create_ramdisk(void); +#endif + +#endif /* __EXAMPLES_MOUNT_MOUNT_H */ diff --git a/apps/examples/mount/mount_main.c b/apps/examples/mount/mount_main.c new file mode 100644 index 0000000000..00070b94c0 --- /dev/null +++ b/apps/examples/mount/mount_main.c @@ -0,0 +1,754 @@ +/**************************************************************************** + * examples/mount/mount_main.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "mount.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define TEST_USE_STAT 1 +#define TEST_SHOW_DIRECTORIES 1 +#define TEST_USE_STATFS 1 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char g_mntdir[] = "/mnt"; +static const char g_target[] = "/mnt/fs"; +static const char g_filesystemtype[] = "vfat"; + +static const char g_testdir1[] = "/mnt/fs/TestDir"; +static const char g_testdir2[] = "/mnt/fs/NewDir1"; +static const char g_testdir3[] = "/mnt/fs/NewDir2"; +static const char g_testdir4[] = "/mnt/fs/NewDir3"; +#ifdef CONFIG_EXAMPLES_MOUNT_DEVNAME +static const char g_testfile1[] = "/mnt/fs/TestDir/TestFile.txt"; +#endif +static const char g_testfile2[] = "/mnt/fs/TestDir/WrTest1.txt"; +static const char g_testfile3[] = "/mnt/fs/NewDir1/WrTest2.txt"; +static const char g_testfile4[] = "/mnt/fs/NewDir3/Renamed.txt"; +static const char g_testmsg[] = "This is a write test"; + +static int g_nerrors = 0; + +static char g_namebuffer[256]; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + + const char g_source[] = MOUNT_DEVNAME; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef TEST_USE_STAT +static void show_stat(const char *path, struct stat *ps) +{ + printf("%s stat:\n", path); + printf("\tmode : %08x\n", ps->st_mode); + if (S_ISREG(ps->st_mode)) + { + printf("\ttype : File\n"); + } + else if (S_ISDIR(ps->st_mode)) + { + printf("\ttype : Directory\n"); + } + else if (S_ISCHR(ps->st_mode)) + { + printf("\ttype : Character driver\n"); + } + else if (S_ISBLK(ps->st_mode)) + { + printf("\ttype : Block driver\n"); + } + else + { + printf("\ttype : Unknown\n"); + } + + printf("\tsize : %d (bytes)\n", ps->st_size); + printf("\tblock size : %d (bytes)\n", ps->st_blksize); + printf("\tsize : %d (blocks)\n", ps->st_blocks); + printf("\taccess time : %d\n", ps->st_atime); + printf("\tmodify time : %d\n", ps->st_mtime); + printf("\tchange time : %d\n", ps->st_ctime); +} +#endif + +/**************************************************************************** + * Name: show_statfs + ****************************************************************************/ + +#ifdef TEST_USE_STATFS +static void show_statfs(const char *path) +{ + struct statfs buf; + int ret; + + /* Try stat() against a file or directory. It should fail with expectederror */ + + printf("show_statfs: Try statfs(%s)\n", path); + ret = statfs(path, &buf); + if (ret == 0) + { + printf("show_statfs: statfs(%s) succeeded\n", path); + printf("\tFS Type : %0x\n", buf.f_type); + printf("\tBlock size : %d\n", buf.f_bsize); + printf("\tNumber of blocks : %d\n", buf.f_blocks); + printf("\tFree blocks : %d\n", buf.f_bfree); + printf("\tFree user blocks : %d\n", buf.f_bavail); + printf("\tNumber file nodes : %d\n", buf.f_files); + printf("\tFree file nodes : %d\n", buf.f_ffree); + printf("\tFile name length : %d\n", buf.f_namelen); + } + else + { + printf("show_statfs: ERROR statfs(%s) failed with errno=%d\n", + path, errno); + g_nerrors++; + } +} +#else +# define show_statfs(p) +#endif + +/**************************************************************************** + * Name: show_directories + ****************************************************************************/ + +#ifdef TEST_SHOW_DIRECTORIES +static void show_directories(const char *path, int indent) +{ + DIR *dirp; + struct dirent *direntry; + int i; + + dirp = opendir(path); + if ( !dirp ) + { + printf("show_directories: ERROR opendir(\"%s\") failed with errno=%d\n", + path, errno); + g_nerrors++; + return; + } + + for (direntry = readdir(dirp); direntry; direntry = readdir(dirp)) + { + for (i = 0; i < 2*indent; i++) + { + putchar(' '); + } + if (DIRENT_ISDIRECTORY(direntry->d_type)) + { + char *subdir; + printf("%s/\n", direntry->d_name); + sprintf(g_namebuffer, "%s/%s", path, direntry->d_name); + subdir = strdup(g_namebuffer); + show_directories( subdir, indent + 1); + free(subdir); + } + else + { + printf("%s\n", direntry->d_name); + } + } + + closedir(dirp); +} +#else +# define show_directories(p,i) +#endif + +/**************************************************************************** + * Name: fail_read_open + ****************************************************************************/ +#ifdef CONFIG_EXAMPLES_MOUNT_DEVNAME +static void fail_read_open(const char *path, int expectederror) +{ + int fd; + + printf("fail_read_open: Try open(%s) for reading\n", path); + + fd = open(path, O_RDONLY); + if (fd >= 0) + { + printf("fail_read_open: ERROR open(%s) succeeded\n", path); + g_nerrors++; + close(fd); + } + else if (errno != expectederror) + { + printf("fail_read_open: ERROR open(%s) failed with errno=%d (expected %d)\n", + path, errno, expectederror); + g_nerrors++; + } +} +#endif + +/**************************************************************************** + * Name: read_test_file + ****************************************************************************/ + +static void read_test_file(const char *path) +{ + char buffer[128]; + int nbytes; + int fd; + + /* Read a test file that is already on the test file system image */ + + printf("read_test_file: opening %s for reading\n", path); + + fd = open(path, O_RDONLY); + if (fd < 0) + { + printf("read_test_file: ERROR failed to open %s, errno=%d\n", + path, errno); + g_nerrors++; + } + else + { + memset(buffer, 0, 128); + nbytes = read(fd, buffer, 128); + if (nbytes < 0) + { + printf("read_test_file: ERROR failed to read from %s, errno=%d\n", + path, errno); + g_nerrors++; + } + else + { + buffer[127]='\0'; + printf("read_test_file: Read \"%s\" from %s\n", buffer, path); + } + close(fd); + } +} + +/**************************************************************************** + * Name: write_test_file + ****************************************************************************/ + +static void write_test_file(const char *path) +{ + int fd; + + /* Write a test file into a pre-existing file on the test file system */ + + printf("write_test_file: opening %s for writing\n", path); + + fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd < 0) + { + printf("write_test_file: ERROR failed to open %s for writing, errno=%d\n", + path, errno); + g_nerrors++; + } + else + { + int nbytes = write(fd, g_testmsg, strlen(g_testmsg)); + if (nbytes < 0) + { + printf("write_test_file: ERROR failed to write to %s, errno=%d\n", + path, errno); + g_nerrors++; + } + else + { + printf("write_test_file: wrote %d bytes to %s\n", nbytes, path); + } + close(fd); + } +} + +/**************************************************************************** + * Name: fail_mkdir + ****************************************************************************/ + +static void fail_mkdir(const char *path, int expectederror) +{ + int ret; + + /* Try mkdir() against a file or directory. It should fail with expectederror */ + + printf("fail_mkdir: Try mkdir(%s)\n", path); + + ret = mkdir(path, 0666); + if (ret == 0) + { + printf("fail_mkdir: ERROR mkdir(%s) succeeded\n", path); + g_nerrors++; + } + else if (errno != expectederror) + { + printf("fail_mkdir: ERROR mkdir(%s) failed with errno=%d (expected %d)\n", + path, errno, expectederror); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: succeed_mkdir + ****************************************************************************/ + +static void succeed_mkdir(const char *path) +{ + int ret; + + printf("succeed_mkdir: Try mkdir(%s)\n", path); + + ret = mkdir(path, 0666); + if (ret != 0) + { + printf("succeed_mkdir: ERROR mkdir(%s) failed with errno=%d\n", + path, errno); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: fail_rmdir + ****************************************************************************/ + +static void fail_rmdir(const char *path, int expectederror) +{ + int ret; + + /* Try rmdir() against a file or directory. It should fail with expectederror */ + + printf("fail_rmdir: Try rmdir(%s)\n", path); + + ret = rmdir(path); + if (ret == 0) + { + printf("fail_rmdir: ERROR rmdir(%s) succeeded\n", path); + g_nerrors++; + } + else if (errno != expectederror) + { + printf("fail_rmdir: ERROR rmdir(%s) failed with errno=%d (expected %d)\n", + path, errno, expectederror); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: succeed_rmdir + ****************************************************************************/ + +static void succeed_rmdir(const char *path) +{ + int ret; + + printf("succeed_rmdir: Try rmdir(%s)\n", path); + + ret = rmdir(path); + if (ret != 0) + { + printf("succeed_rmdir: ERROR rmdir(%s) failed with errno=%d\n", + path, errno); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: fail_unlink + ****************************************************************************/ + +static void fail_unlink(const char *path, int expectederror) +{ + int ret; + + /* Try unlink() against a file or directory. It should fail with expectederror */ + + printf("fail_unlink: Try unlink(%s)\n", path); + + ret = unlink(path); + if (ret == 0) + { + printf("fail_unlink: ERROR unlink(%s) succeeded\n", path); + g_nerrors++; + } + else if (errno != expectederror) + { + printf("fail_unlink: ERROR unlink(%s) failed with errno=%d (expected %d)\n", + path, errno, expectederror); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: succeed_unlink + ****************************************************************************/ + +static void succeed_unlink(const char *path) +{ + int ret; + + /* Try unlink() against the test file. It should succeed. */ + + printf("succeed_unlink: Try unlink(%s)\n", path); + + ret = unlink(path); + if (ret != 0) + { + printf("succeed_unlink: ERROR unlink(%s) failed with errno=%d\n", + path, errno); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: fail_rename + ****************************************************************************/ + +static void fail_rename(const char *oldpath, const char *newpath, int expectederror) +{ + int ret; + + /* Try rename() against a file or directory. It should fail with expectederror */ + + printf("fail_rename: Try rename(%s->%s)\n", oldpath, newpath); + + ret = rename(oldpath, newpath); + if (ret == 0) + { + printf("fail_rename: ERROR rename(%s->%s) succeeded\n", + oldpath, newpath); + g_nerrors++; + } + else if (errno != expectederror) + { + printf("fail_rename: ERROR rename(%s->%s) failed with errno=%d (expected %d)\n", + oldpath, newpath, errno, expectederror); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: succeed_rename + ****************************************************************************/ + +static void succeed_rename(const char *oldpath, const char *newpath) +{ + int ret; + + printf("succeed_rename: Try rename(%s->%s)\n", oldpath, newpath); + + ret = rename(oldpath, newpath); + if (ret != 0) + { + printf("succeed_rename: ERROR rename(%s->%s) failed with errno=%d\n", + oldpath, newpath, errno); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: fail_stat + ****************************************************************************/ + +#ifdef TEST_USE_STAT +static void fail_stat(const char *path, int expectederror) +{ + struct stat buf; + int ret; + + /* Try stat() against a file or directory. It should fail with expectederror */ + + printf("fail_stat: Try stat(%s)\n", path); + + ret = stat(path, &buf); + if (ret == 0) + { + printf("fail_stat: ERROR stat(%s) succeeded\n", path); + show_stat(path, &buf); + g_nerrors++; + } + else if (errno != expectederror) + { + printf("fail_stat: ERROR stat(%s) failed with errno=%d (expected %d)\n", + path, errno, expectederror); + g_nerrors++; + } +} +#else +# define fail_stat(p,e); +#endif + +/**************************************************************************** + * Name: succeed_stat + ****************************************************************************/ + +#ifdef TEST_USE_STAT +static void succeed_stat(const char *path) +{ + struct stat buf; + int ret; + + printf("succeed_stat: Try stat(%s)\n", path); + + ret = stat(path, &buf); + if (ret != 0) + { + printf("succeed_stat: ERROR stat(%s) failed with errno=%d\n", + path, errno); + g_nerrors++; + } + else + { + printf("succeed_stat: stat(%s) succeeded\n", path); + show_stat(path, &buf); + } +} +#else +#define succeed_stat(p) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + int ret; + +#ifndef CONFIG_EXAMPLES_MOUNT_DEVNAME + /* Create a RAM disk for the test */ + + ret = create_ramdisk(); + if (ret < 0) + { + printf("user_start: ERROR failed to create RAM disk\n"); + return 1; + } +#endif + + /* Mount the test file system (see arch/sim/src/up_deviceimage.c */ + + printf("user_start: mounting %s filesystem at target=%s with source=%s\n", + g_filesystemtype, g_target, g_source); + + ret = mount(g_source, g_target, g_filesystemtype, 0, NULL); + printf("user_start: mount() returned %d\n", ret); + + if (ret == 0) + { + show_statfs(g_mntdir); + show_statfs(g_target); + +#ifdef CONFIG_EXAMPLES_MOUNT_DEVNAME + /* Read a test file that is already on the test file system image */ + + show_directories("", 0); + succeed_stat(g_testfile1); + show_statfs(g_testfile1); + read_test_file(g_testfile1); +#else + /* Create the test directory that would have been on the canned filesystem */ + + succeed_mkdir(g_testdir1); + show_directories("", 0); + succeed_stat(g_testdir1); + show_statfs(g_testdir1); +#endif + + /* Write a test file into a pre-existing directory on the test file system */ + + fail_stat(g_testfile2, ENOENT); + write_test_file(g_testfile2); + show_directories("", 0); + succeed_stat(g_testfile2); + show_statfs(g_testfile2); + + /* Read the file that we just wrote */ + + read_test_file(g_testfile2); + + /* Try rmdir() against a file on the directory. It should fail with ENOTDIR */ +#ifdef CONFIG_EXAMPLES_MOUNT_DEVNAME + fail_rmdir(g_testfile1, ENOTDIR); +#endif + + /* Try rmdir() against the test directory. It should fail with ENOTEMPTY */ + + fail_rmdir(g_testdir1, ENOTEMPTY); + + /* Try unlink() against the test directory. It should fail with EISDIR */ + + fail_unlink(g_testdir1, EISDIR); + + /* Try unlink() against the test file1. It should succeed. */ +#ifdef CONFIG_EXAMPLES_MOUNT_DEVNAME + succeed_unlink(g_testfile1); + fail_stat(g_testfile1, ENOENT); + show_directories("", 0); +#endif + + /* Attempt to open testfile1 should fail with ENOENT */ +#ifdef CONFIG_EXAMPLES_MOUNT_DEVNAME + fail_read_open(g_testfile1, ENOENT); +#endif + /* Try rmdir() against the test directory. It should still fail with ENOTEMPTY */ + + fail_rmdir(g_testdir1, ENOTEMPTY); + + /* Try mkdir() against the test file2. It should fail with EEXIST. */ + + fail_mkdir(g_testfile2, EEXIST); + + /* Try unlink() against the test file2. It should succeed. */ + + succeed_unlink(g_testfile2); + show_directories("", 0); + fail_stat(g_testfile2, ENOENT); + + /* Try mkdir() against the test dir1. It should fail with EEXIST. */ + + fail_mkdir(g_testdir1, EEXIST); + + /* Try rmdir() against the test directory. mkdir should now succeed. */ + + succeed_rmdir(g_testdir1); + show_directories("", 0); + fail_stat(g_testdir1, ENOENT); + + /* Try mkdir() against the test dir2. It should succeed */ + + succeed_mkdir(g_testdir2); + show_directories("", 0); + succeed_stat(g_testdir2); + show_statfs(g_testdir2); + + /* Try mkdir() against the test dir2. It should fail with EXIST */ + + fail_mkdir(g_testdir2, EEXIST); + + /* Write a test file into a new directory on the test file system */ + + fail_stat(g_testfile3, ENOENT); + write_test_file(g_testfile3); + show_directories("", 0); + succeed_stat(g_testfile3); + show_statfs(g_testfile3); + + /* Read the file that we just wrote */ + + read_test_file(g_testfile3); + + /* Use mkdir() to create test dir3. It should succeed */ + + fail_stat(g_testdir3, ENOENT); + succeed_mkdir(g_testdir3); + show_directories("", 0); + succeed_stat(g_testdir3); + show_statfs(g_testdir3); + + /* Try rename() on the root directory. Should fail with EXDEV*/ + + fail_rename(g_target, g_testdir4, EXDEV); + + /* Try rename() to an existing directory. Should fail with EEXIST */ + + fail_rename(g_testdir2, g_testdir3, EEXIST); + + /* Try rename() to a non-existing directory. Should succeed */ + + fail_stat(g_testdir4, ENOENT); + succeed_rename(g_testdir3, g_testdir4); + show_directories("", 0); + fail_stat(g_testdir3, ENOENT); + succeed_stat(g_testdir4); + show_statfs(g_testdir4); + + /* Try rename() of file. Should work. */ + + fail_stat(g_testfile4, ENOENT); + succeed_rename(g_testfile3, g_testfile4); + show_directories("", 0); + fail_stat(g_testfile3, ENOENT); + succeed_stat(g_testfile4); + show_statfs(g_testfile4); + + /* Make sure that we can still read the renamed file */ + + read_test_file(g_testfile4); + + /* Unmount the file system */ + + printf("user_start: Try unmount(%s)\n", g_target); + + ret = umount(g_target); + if (ret != 0) + { + printf("user_start: ERROR umount() failed, errno %d\n", errno); + g_nerrors++; + } + + printf("user_start: %d errors reported\n", g_nerrors); + } + + fflush(stdout); + return 0; +} diff --git a/apps/examples/mount/ramdisk.c b/apps/examples/mount/ramdisk.c new file mode 100644 index 0000000000..9688580c06 --- /dev/null +++ b/apps/examples/mount/ramdisk.c @@ -0,0 +1,141 @@ +/**************************************************************************** + * examples/mount/ramdisk.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "mount.h" + +#ifndef CONFIG_EXAMPLES_MOUNT_DEVNAME + +/**************************************************************************** + * Private Definitions + ****************************************************************************/ + +#define BUFFER_SIZE (CONFIG_EXAMPLES_MOUNT_NSECTORS*CONFIG_EXAMPLES_MOUNT_SECTORSIZE) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct fat_format_s g_fmt = FAT_FORMAT_INITIALIZER; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: create_ramdisk + * + * Description: + * Create a RAM disk of the specified size formatting with a FAT file + * system + * + * Input Parameters: + * None + * + * Return: + * Zero on success, a negated errno on failure. + * + ****************************************************************************/ + +int create_ramdisk(void) +{ + char *pbuffer; + int ret; + + /* Allocate a buffer to hold the file system image. */ + + pbuffer = (char*)malloc(BUFFER_SIZE); + if (!pbuffer) + { + printf("create_ramdisk: Failed to allocate ramdisk of size %d\n", + BUFFER_SIZE); + return -ENOMEM; + } + + /* Register a RAMDISK device to manage this RAM image */ + + ret = ramdisk_register(CONFIG_EXAMPLES_MOUNT_RAMDEVNO, + pbuffer, + CONFIG_EXAMPLES_MOUNT_NSECTORS, + CONFIG_EXAMPLES_MOUNT_SECTORSIZE, + true); + if (ret < 0) + { + printf("create_ramdisk: Failed to register ramdisk at %s: %d\n", + g_source, -ret); + free(pbuffer); + return ret; + } + + /* Create a FAT filesystem on the ramdisk */ + + ret = mkfatfs(g_source, &g_fmt); + if (ret < 0) + { + printf("create_ramdisk: Failed to create FAT filesystem on ramdisk at %s\n", + g_source); + /* free(pbuffer); -- RAM disk is registered */ + return ret; + } + + return 0; +} +#endif /* !CONFIG_EXAMPLES_MOUNT_DEVNAME */ diff --git a/apps/examples/nsh/Kconfig b/apps/examples/nsh/Kconfig new file mode 100644 index 0000000000..289c7e515e --- /dev/null +++ b/apps/examples/nsh/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_NSH + bool "NuttShell (NSH) example" + default n + ---help--- + Enable the NuttShell (NSH) example + +if EXAMPLES_NSH +endif diff --git a/apps/examples/nsh/Makefile b/apps/examples/nsh/Makefile new file mode 100644 index 0000000000..b5844f9edc --- /dev/null +++ b/apps/examples/nsh/Makefile @@ -0,0 +1,93 @@ +############################################################################ +# apps/examples/nsh/Makefile +# +# Copyright (C) 2007-2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# NuttShell (NSH) Example + +ASRCS = +CSRCS = nsh_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +context: + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/nsh/nsh_main.c b/apps/examples/nsh/nsh_main.c new file mode 100644 index 0000000000..c5b671ab14 --- /dev/null +++ b/apps/examples/nsh/nsh_main.c @@ -0,0 +1,136 @@ +/**************************************************************************** + * examples/nsh/nsh_main.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The NSH telnet console requires networking support (and TCP/IP) */ + +#ifndef CONFIG_NET +# undef CONFIG_NSH_TELNET +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + int exitval = 0; + int ret; + + /* Call all C++ static constructors */ + +#if defined(CONFIG_HAVE_CXX) && defined(CONFIG_HAVE_CXXINITIALIZE) + up_cxxinitialize(); +#endif + + /* Initialize the NSH library */ + + nsh_initialize(); + + /* If the Telnet console is selected as a front-end, then start the + * Telnet daemon. + */ + +#ifdef CONFIG_NSH_TELNET + ret = nsh_telnetstart(); + if (ret < 0) + { + /* The daemon is NOT running. Report the the error then fail... + * either with the serial console up or just exiting. + */ + + fprintf(stderr, "ERROR: Failed to start TELNET daemon: %d\n", ret); + exitval = 1; + } +#endif + + /* If the serial console front end is selected, then run it on this thread */ + +#ifdef CONFIG_NSH_CONSOLE + ret = nsh_consolemain(0, NULL); + + /* nsh_consolemain() should not return. So if we get here, something + * is wrong. + */ + + fprintf(stderr, "ERROR: nsh_consolemain() returned: %d\n", ret); + exitval = 1; +#endif + + return exitval; +} diff --git a/apps/examples/null/Kconfig b/apps/examples/null/Kconfig new file mode 100644 index 0000000000..1f19dfd2cf --- /dev/null +++ b/apps/examples/null/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_NULL + bool "NULL example" + default n + ---help--- + Enable the NULL example + +if EXAMPLES_NULL +endif diff --git a/apps/examples/null/Makefile b/apps/examples/null/Makefile new file mode 100644 index 0000000000..3938eb1711 --- /dev/null +++ b/apps/examples/null/Makefile @@ -0,0 +1,93 @@ +############################################################################ +# examples/null/Makefile +# +# Copyright (C) 2007-2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# The smallest thing you can build -- the NULL example. + +ASRCS = +CSRCS = null_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +context: + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/null/null_main.c b/apps/examples/null/null_main.c new file mode 100644 index 0000000000..10fc1bf1e4 --- /dev/null +++ b/apps/examples/null/null_main.c @@ -0,0 +1,67 @@ +/**************************************************************************** + * examples/null/null_main.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + return 0; +} diff --git a/apps/examples/ostest/Kconfig b/apps/examples/ostest/Kconfig new file mode 100644 index 0000000000..ca89579934 --- /dev/null +++ b/apps/examples/ostest/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_OSTEST + bool "OS test example" + default n + ---help--- + Enable the OS test example + +if EXAMPLES_OSTEST +endif diff --git a/apps/examples/ostest/Makefile b/apps/examples/ostest/Makefile new file mode 100644 index 0000000000..eab1db8b39 --- /dev/null +++ b/apps/examples/ostest/Makefile @@ -0,0 +1,149 @@ +############################################################################ +# apps/examples/ostest/Makefile +# +# Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# ostest built-in application info + +APPNAME = ostest +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# NuttX OS Test + +ASRCS = +CSRCS = main.c dev_null.c + +ifeq ($(CONFIG_ARCH_FPU),y) +CSRCS += fpu.c +endif + +ifneq ($(CONFIG_DISABLE_PTHREAD),y) +CSRCS += cancel.c cond.c mutex.c sem.c barrier.c +ifneq ($(CONFIG_RR_INTERVAL),0) +CSRCS += roundrobin.c +endif # CONFIG_RR_INTERVAL +ifeq ($(CONFIG_MUTEX_TYPES),y) +CSRCS += rmutex.c +endif # CONFIG_MUTEX_TYPES +endif # CONFIG_DISABLE_PTHREAD + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +CSRCS += sighand.c +ifneq ($(CONFIG_DISABLE_PTHREAD),y) +ifneq ($(CONFIG_DISABLE_CLOCK),y) +CSRCS += timedwait.c +endif # CONFIG_DISABLE_CLOCK +endif # CONFIG_DISABLE_PTHREAD +endif # CONFIG_DISABLE_SIGNALS + +ifneq ($(CONFIG_DISABLE_MQUEUE),y) +ifneq ($(CONFIG_DISABLE_PTHREAD),y) +CSRCS += mqueue.c +ifneq ($(CONFIG_DISABLE_CLOCK),y) +CSRCS += timedmqueue.c +endif # CONFIG_DISABLE_CLOCK +endif # CONFIG_DISABLE_PTHREAD +endif # CONFIG_DISABLE_MQUEUE + +ifneq ($(CONFIG_DISABLE_POSIX_TIMERS),y) +CSRCS += posixtimer.c +endif + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +ifneq ($(CONFIG_DISABLE_PTHREAD),y) +ifeq ($(CONFIG_PRIORITY_INHERITANCE),y) +CSRCS += prioinherit.c +endif # CONFIG_PRIORITY_INHERITANCE +endif # CONFIG_DISABLE_PTHREAD +endif # CONFIG_DISABLE_SIGNALS + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: +ifeq ($(CONFIG_EXAMPLES_OSTEST_BUILTIN),y) + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ +endif + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/ostest/barrier.c b/apps/examples/ostest/barrier.c new file mode 100644 index 0000000000..da1301dc3c --- /dev/null +++ b/apps/examples/ostest/barrier.c @@ -0,0 +1,208 @@ +/**************************************************************************** + * examples/ostest/barrier.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "ostest.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define HALF_SECOND 500000L + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static pthread_barrier_t barrier; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: barrier_func + ****************************************************************************/ + +static void *barrier_func(void *parameter) +{ + int id = (int)parameter; + int status; + + printf("barrier_func: Thread %d started\n", id); +#ifndef CONFIG_DISABLE_SIGNALS + usleep(HALF_SECOND); +#endif + + /* Wait at the barrier until all threads are synchronized. */ + + printf("barrier_func: Thread %d calling pthread_barrier_wait()\n", + id); + FFLUSH(); + status = pthread_barrier_wait(&barrier); + if (status == 0) + { + printf("barrier_func: Thread %d, back with " + "status=0 (I am not special)\n", + id, status); + } + else if (status == PTHREAD_BARRIER_SERIAL_THREAD) + { + printf("barrier_func: Thread %d, back with " + "status=PTHREAD_BARRIER_SERIAL_THREAD (I AM SPECIAL)\n", + id, status); + } + else + { + printf("barrier_func: ERROR thread %d could not get semaphore value\n", + id); + } + FFLUSH(); + +#ifndef CONFIG_DISABLE_SIGNALS + usleep(HALF_SECOND); +#endif + printf("barrier_func: Thread %d done\n", id); + FFLUSH(); + return NULL; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: barrier_test + ****************************************************************************/ + +void barrier_test(void) +{ + pthread_t barrier_thread[CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS]; + pthread_addr_t result; + pthread_attr_t attr; + pthread_barrierattr_t barrierattr; + int status; + int i; + + printf("barrier_test: Initializing barrier\n"); + + status = pthread_barrierattr_init(&barrierattr); + if (status != OK) + { + printf("barrier_test: pthread_barrierattr_init failed, status=%d\n", + status); + } + + status = pthread_barrier_init(&barrier, &barrierattr, + CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS); + if (status != OK) + { + printf("barrier_test: pthread_barrierattr_init failed, status=%d\n", + status); + } + + /* Create the barrier */ + + status = pthread_barrierattr_init(&barrierattr); + + /* Start CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS thread instances */ + + status = pthread_attr_init(&attr); + if (status != OK) + { + printf("barrier_test: pthread_attr_init failed, status=%d\n", + status); + } + + for (i = 0; i < CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS; i++) + { + status = pthread_create(&barrier_thread[i], &attr, barrier_func, + (pthread_addr_t)i); + if (status != 0) + { + printf("barrier_test: Error in thread %d create, status=%d\n", + i, status); + printf("barrier_test: Test aborted with waiting threads\n"); + goto abort_test; + } + else + { + printf("barrier_test: Thread %d created\n", i); + } + } + FFLUSH(); + + /* Wait for all thread instances to complete */ + + for (i = 0; i < CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS; i++) + { + status = pthread_join(barrier_thread[i], &result); + if (status != 0) + { + printf("barrier_test: Error in thread %d join, status=%d\n", + i, status); + } + else + { + printf("barrier_test: Thread %d completed with result=%p\n", + i, result); + } + } + + /* Destroy the barrier */ + +abort_test: + status = pthread_barrier_destroy(&barrier); + if (status != OK) + { + printf("barrier_test: pthread_barrier_destroy failed, status=%d\n", + status); + } + + status = pthread_barrierattr_destroy(&barrierattr); + if (status != OK) + { + printf("barrier_test: pthread_barrierattr_destroy failed, status=%d\n", + status); + } + FFLUSH(); +} diff --git a/apps/examples/ostest/cancel.c b/apps/examples/ostest/cancel.c new file mode 100644 index 0000000000..bf2d03615f --- /dev/null +++ b/apps/examples/ostest/cancel.c @@ -0,0 +1,333 @@ +/*********************************************************************** + * examples/ostest/cancel.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ***********************************************************************/ + +#include +#include +#include +#include +#include "ostest.h" + +static pthread_mutex_t mutex; +static pthread_cond_t cond; + +static void *thread_waiter(void *parameter) +{ + int status; + + /* Take the mutex */ + + printf("thread_waiter: Taking mutex\n"); + status = pthread_mutex_lock(&mutex); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_mutex_lock failed, status=%d\n", status); + } + + printf("thread_waiter: Starting wait for condition\n"); + + /* Are we a non-cancelable thread? Yes, set the non-cancelable state */ + + if (!parameter) + { + printf("thread_waiter: Setting non-cancelable\n"); + status = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_setcancelstate failed, status=%d\n", status); + } + } + + /* The wait -- we will never awaken from this. */ + + status = pthread_cond_wait(&cond, &mutex); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_cond_wait failed, status=%d\n", status); + } + + /* Release the mutex */ + + printf("thread_waiter: Releasing mutex\n"); + status = pthread_mutex_unlock(&mutex); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_mutex_unlock failed, status=%d\n", status); + } + + /* Set the cancelable state */ + + printf("thread_waiter: Setting cancelable\n"); + status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_setcancelstate failed, status=%d\n", status); + } + + printf("thread_waiter: Exit with status 0x12345678\n"); + pthread_exit((pthread_addr_t)0x12345678); + return NULL; +} + +static void start_thread(pthread_t *waiter, int cancelable) +{ + pthread_attr_t attr; + int status; + + /* Initialize the mutex */ + + printf("start_thread: Initializing mutex\n"); + status = pthread_mutex_init(&mutex, NULL); + if (status != 0) + { + printf("start_thread: ERROR pthread_mutex_init failed, status=%d\n", status); + } + + /* Initialize the condition variable */ + + printf("start_thread: Initializing cond\n"); + status = pthread_cond_init(&cond, NULL); + if (status != 0) + { + printf("start_thread: ERROR pthread_cond_init failed, status=%d\n", status); + } + + /* Set up attributes */ + + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("start_thread: pthread_attr_init failed, status=%d\n", status); + } + + status = pthread_attr_setstacksize(&attr, STACKSIZE); + if (status != 0) + { + printf("start_thread: pthread_attr_setstacksize failed, status=%d\n", status); + } + + /* Start the waiter thread */ + + printf("start_thread: Starting thread\n"); + status = pthread_create(waiter, &attr, thread_waiter, (pthread_addr_t)cancelable); + if (status != 0) + { + printf("start_thread: ERROR pthread_create failed, status=%d\n", status); + } + + /* Make sure that the waiter thread gets a chance to run */ + + printf("start_thread: Yielding\n"); + pthread_yield(); +} + +static void restart_thread(pthread_t *waiter, int cancelable) +{ + int status; + + /* Destroy the condition variable */ + + printf("restart_thread: Destroying cond\n"); + status = pthread_cond_destroy(&cond); + if (status != 0) + { + printf("restart_thread: ERROR pthread_cond_destroy failed, status=%d\n", status); + } + + /* Destroy the mutex */ + + printf("restart_thread: Destroying mutex\n"); + status = pthread_cond_destroy(&cond); + if (status != 0) + { + printf("restart_thread: ERROR pthread_mutex_destroy failed, status=%d\n", status); + } + + /* Then restart the thread */ + + printf("restart_thread: Re-starting thread\n"); + start_thread(waiter, cancelable); +} + +void cancel_test(void) +{ + pthread_t waiter; + void *result; + int status; + + /* Test 1: Normal Cancel *********************************************/ + /* Start the waiter thread */ + + printf("cancel_test: Test 1: Normal Cancelation\n"); + printf("cancel_test: Starting thread\n"); + start_thread(&waiter, 1); + + /* Then cancel it. It should be in the pthread_cond_wait now */ + + printf("cancel_test: Canceling thread\n"); + status = pthread_cancel(waiter); + if (status != 0) + { + printf("cancel_test: ERROR pthread_cancel failed, status=%d\n", status); + } + + /* Then join to the thread to pick up the result (if we don't do + * we will have a memory leak!) + */ + + printf("cancel_test: Joining\n"); + status = pthread_join(waiter, &result); + if (status != 0) + { + printf("cancel_test: ERROR pthread_join failed, status=%d\n", status); + } + else + { + printf("cancel_test: waiter exited with result=%p\n", result); + if (result != PTHREAD_CANCELED) + { + printf("cancel_test: ERROR expected result=%p\n", PTHREAD_CANCELED); + } + else + { + printf("cancel_test: PASS thread terminated with PTHREAD_CANCELED\n"); + } + } + + /* Test 2: Cancel Detached Thread ************************************/ + + printf("cancel_test: Test 2: Cancelation of detached thread\n"); + printf("cancel_test: Re-starting thread\n"); + restart_thread(&waiter, 1); + + /* Detach the thread */ + + status = pthread_detach(waiter); + if (status != 0) + { + printf("cancel_test: ERROR pthread_detach, status=%d\n", status); + } + + /* Then cancel it. It should be in the pthread_cond_wait now */ + + printf("cancel_test: Canceling thread\n"); + status = pthread_cancel(waiter); + if (status != 0) + { + printf("cancel_test: ERROR pthread_cancel failed, status=%d\n", status); + } + + /* Join should now fail */ + + printf("cancel_test: Joining\n"); + status = pthread_join(waiter, &result); + if (status == 0) + { + printf("cancel_test: ERROR pthread_join succeeded\n"); + } + else if (status != ESRCH) + { + printf("cancel_test: ERROR pthread_join failed but with wrong status=%d\n", status); + } + else + { + printf("cancel_test: PASS pthread_join failed with status=ESRCH\n"); + } + + /* Test 3: Non-cancelable threads ************************************/ + + printf("cancel_test: Test 3: Non-cancelable threads\n"); + printf("cancel_test: Re-starting thread (non-cancelable)\n"); + restart_thread(&waiter, 0); + + /* Then cancel it. It should be in the pthread_cond_wait now. The + * behavior here is non-standard: when the thread is at a cancelation + * point, it should be cancelable, even when cancelation is disable. + * + * The cancelation should succeed, because the cancelation is pending. + */ + + printf("cancel_test: Canceling thread\n"); + status = pthread_cancel(waiter); + if (status != 0) + { + printf("cancel_test: ERROR pthread_cancel failed, status=%d\n", status); + } + + /* Signal the thread. It should wake up and restore the cancelable state. + * When the cancelable state is re-enabled, the thread should be canceled. + */ + + status = pthread_mutex_lock(&mutex); + if (status != 0) + { + printf("cancel_test: ERROR pthread_mutex_lock failed, status=%d\n", status); + } + + status = pthread_cond_signal(&cond); + if (status != 0) + { + printf("cancel_test: ERROR pthread_cond_signal failed, status=%d\n", status); + } + + status = pthread_mutex_unlock(&mutex); + if (status != 0) + { + printf("cancel_test: ERROR pthread_mutex_unlock failed, status=%d\n", status); + } + + /* Then join to the thread to pick up the result (if we don't do + * we will have a memory leak!) + */ + + printf("cancel_test: Joining\n"); + status = pthread_join(waiter, &result); + if (status != 0) + { + printf("cancel_test: ERROR pthread_join failed, status=%d\n", status); + } + else + { + printf("cancel_test: waiter exited with result=%p\n", result); + if (result != PTHREAD_CANCELED) + { + printf("cancel_test: ERROR expected result=%p\n", PTHREAD_CANCELED); + } + else + { + printf("cancel_test: PASS thread terminated with PTHREAD_CANCELED\n"); + } + } + +} diff --git a/apps/examples/ostest/cond.c b/apps/examples/ostest/cond.c new file mode 100644 index 0000000000..11191b7d52 --- /dev/null +++ b/apps/examples/ostest/cond.c @@ -0,0 +1,294 @@ +/*********************************************************************** + * cond.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ***********************************************************************/ + +#include +#include +#include +#include "ostest.h" + +#ifndef NULL +# define NULL (void*)0 +#endif + +static volatile enum { RUNNING, MUTEX_WAIT, COND_WAIT} waiter_state; + +static pthread_mutex_t mutex; +static pthread_cond_t cond; +static volatile int data_available = 0; +static int waiter_nloops = 0; +static int waiter_waits = 0; +static int waiter_nerrors = 0; +static int signaler_nloops = 0; +static int signaler_already = 0; +static int signaler_state = 0; +static int signaler_nerrors = 0; + +static void *thread_waiter(void *parameter) +{ + int status; + + printf("waiter_thread: Started\n"); + + for(;;) + { + /* Take the mutex */ + + waiter_state = MUTEX_WAIT; + status = pthread_mutex_lock(&mutex); + waiter_state = RUNNING; + + if (status != 0) + { + printf("waiter_thread: ERROR pthread_mutex_lock failed, status=%d\n", status); + waiter_nerrors++; + } + + /* Check if data is available -- if data is not available then + * wait for it + */ + + if (!data_available) + { + /* We are higher priority than the signaler thread so the + * only time that the signaler thread will have a chance to run is when + * we are waiting for the condition variable. In this case, pthread_cond_wait + * will automatically release the mutex for the signaler (then re-acquire + * the mutex before returning. + */ + + waiter_state = COND_WAIT; + status = pthread_cond_wait(&cond, &mutex); + waiter_state = RUNNING; + + if (status != 0) + { + printf("waiter_thread: ERROR pthread_cond_wait failed, status=%d\n", status); + waiter_nerrors++; + } + waiter_waits++; + } + + /* Now data should be available */ + + if (!data_available) + { + printf("waiter_thread: ERROR data not available after wait\n"); + waiter_nerrors++; + } + + /* Clear data available */ + + data_available = 0; + + /* Release the mutex */ + + status = pthread_mutex_unlock(&mutex); + if (status != 0) + { + printf("waiter_thread: ERROR waiter: pthread_mutex_unlock failed, status=%d\n", status); + waiter_nerrors++; + } + + waiter_nloops++; + } + return NULL; +} + +static void *thread_signaler(void *parameter) +{ + int status; + int i; + + printf("thread_signaler: Started\n"); + for (i = 0; i < 32; i++) + { + /* Take the mutex. The waiter is higher priority and should + * run until it waits for the condition. So, at this point + * signaler should be waiting for the condition. + */ + + status = pthread_mutex_lock(&mutex); + if (status != 0) + { + printf("thread_signaler: ERROR pthread_mutex_lock failed, status=%d\n", status); + signaler_nerrors++; + } + + /* Verify the state */ + + if (waiter_state != COND_WAIT) + { + printf("thread_signaler: ERROR waiter state = %d != COND_WAITING\n", waiter_state); + signaler_state++; + } + + if (data_available) + { + printf("thread_signaler: ERROR data already available, waiter_state=%d\n", waiter_state); + signaler_already++; + } + + /* Set data available and signal the waiter */ + + data_available = 1; + status = pthread_cond_signal(&cond); + if (status != 0) + { + printf("thread_signaler: ERROR pthread_cond_signal failed, status=%d\n", status); + signaler_nerrors++; + } + + /* Release the mutex */ + + status = pthread_mutex_unlock(&mutex); + if (status != 0) + { + printf("thread_signaler: ERROR pthread_mutex_unlock failed, status=%d\n", status); + signaler_nerrors++; + } + + signaler_nloops++; + } + + printf("thread_signaler: Terminating\n"); + pthread_exit(NULL); + return NULL; /* Non-reachable -- needed for some compilers */ +} + +void cond_test(void) +{ + pthread_t waiter; + pthread_t signaler; + pthread_attr_t attr; +#ifdef SDCC + pthread_addr_t result; +#endif + struct sched_param sparam; + int prio_min; + int prio_max; + int prio_mid; + int status; + + /* Initialize the mutex */ + + printf("cond_test: Initializing mutex\n"); + status = pthread_mutex_init(&mutex, NULL); + if (status != 0) + { + printf("cond_test: ERROR pthread_mutex_init failed, status=%d\n", status); + } + + /* Initialize the condition variable */ + + printf("cond_test: Initializing cond\n"); + status = pthread_cond_init(&cond, NULL); + if (status != 0) + { + printf("cond_test: ERROR pthread_condinit failed, status=%d\n", status); + } + + /* Start the waiter thread at higher priority */ + + printf("cond_test: Starting waiter\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("cond_test: pthread_attr_init failed, status=%d\n", status); + } + + prio_min = sched_get_priority_min(SCHED_FIFO); + prio_max = sched_get_priority_max(SCHED_FIFO); + prio_mid = (prio_min + prio_max) / 2; + + sparam.sched_priority = prio_mid; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("cond_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("cond_test: Set thread 1 priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&waiter, &attr, thread_waiter, NULL); + if (status != 0) + { + printf("cond_test: pthread_create failed, status=%d\n", status); + } + + printf("cond_test: Starting signaler\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("cond_test: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = (prio_min + prio_mid) / 2; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("cond_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("cond_test: Set thread 2 priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&signaler, &attr, thread_signaler, NULL); + if (status != 0) + { + printf("cond_test: pthread_create failed, status=%d\n", status); + } + + /* Wait for the threads to stop */ + +#ifdef SDCC + pthread_join(signaler, &result); +#else + pthread_join(signaler, NULL); +#endif + printf("cond_test: signaler terminated, now cancel the waiter\n"); + pthread_detach(waiter); + pthread_cancel(waiter); + + printf("cond_test: \tWaiter\tSignaler\n"); + printf("cond_test: Loops\t%d\t%d\n", waiter_nloops, signaler_nloops); + printf("cond_test: Errors\t%d\t%d\n", waiter_nerrors, signaler_nerrors); + printf("cond_test:\n"); + printf("cond_test: %d times, waiter did not have to wait for data\n", waiter_nloops - waiter_waits); + printf("cond_test: %d times, data was already available when the signaler run\n", signaler_already); + printf("cond_test: %d times, the waiter was in an unexpected state when the signaler ran\n", signaler_state); +} diff --git a/apps/examples/ostest/dev_null.c b/apps/examples/ostest/dev_null.c new file mode 100644 index 0000000000..e8fc6cf3f9 --- /dev/null +++ b/apps/examples/ostest/dev_null.c @@ -0,0 +1,92 @@ +/**************************************************************************** + * examples/ostest/dev_null.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include "ostest.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + +static FAR char buffer[1024]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int dev_null(void) +{ + int nbytes; + int fd; + + fd = open("/dev/null", O_RDWR); + if (fd < 0) + { + printf("dev_null: ERROR Failed to open /dev/null\n"); + return -1; + } + + nbytes = read(fd, buffer, 1024); + if (nbytes < 0) + { + printf("dev_null: ERROR Failed to read from /dev/null\n"); + close(fd); + return -1; + } + printf("dev_null: Read %d bytes from /dev/null\n", nbytes); + + nbytes = write(fd, buffer, 1024); + if (nbytes < 0) + { + printf("dev_null: ERROR Failed to write to /dev/null\n"); + close(fd); + return -1; + } + printf("dev_null: Wrote %d bytes to /dev/null\n", nbytes); + + close(fd); + return 0; +} + +#endif /*CONFIG_NFILE_DESCRIPTORS */ diff --git a/apps/examples/ostest/fpu.c b/apps/examples/ostest/fpu.c new file mode 100644 index 0000000000..89a1034ce9 --- /dev/null +++ b/apps/examples/ostest/fpu.c @@ -0,0 +1,344 @@ +/*********************************************************************** + * apps/examples/ostest/fpu.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ***********************************************************************/ + +/*********************************************************************** + * Included Files + ***********************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include + +#include "ostest.h" + +/*********************************************************************** + * Pre-processor definitions + ***********************************************************************/ +/* Configuration *******************************************************/ + +#undef HAVE_FPU +#ifdef CONFIG_ARCH_FPU +# if defined(CONFIG_EXAMPLES_OSTEST_FPUSIZE) && defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_DISABLE_SIGNALS) +# define HAVE_FPU 1 +# else +# ifndef CONFIG_EXAMPLES_OSTEST_FPUSIZE +# warning "FPU test not built; CONFIG_EXAMPLES_OSTEST_FPUSIZE not defined" +# endif +# ifndef CONFIG_SCHED_WAITPID +# warning "FPU test not built; CONFIG_SCHED_WAITPID not defined" +# endif +# ifdef CONFIG_DISABLE_SIGNALS +# warning "FPU test not built; CONFIG_DISABLE_SIGNALS defined" +# endif +# endif +#endif + +#ifdef HAVE_FPU + +#ifndef CONFIG_EXAMPLES_OSTEST_FPULOOPS +# define CONFIG_EXAMPLES_OSTEST_FPULOOPS 16 +#endif + +#ifndef CONFIG_EXAMPLES_OSTEST_FPUMSDELAY +# define CONFIG_EXAMPLES_OSTEST_FPUMSDELAY 750 +#endif + +#ifndef CONFIG_EXAMPLES_OSTEST_FPUPRIORITY +# define CONFIG_EXAMPLES_OSTEST_FPUPRIORITY SCHED_PRIORITY_DEFAULT +#endif + +#ifndef CONFIG_EXAMPLES_OSTEST_FPUSTACKSIZE +# define CONFIG_EXAMPLES_OSTEST_FPUSTACKSIZE 2048 +#endif + +/* Other defintions ****************************************************/ +/* We'll keep all data using 32-bit values only to force 32-bit alignment. + * This logic has no real notion of the underlying representation. + */ + +#define FPU_WORDSIZE ((CONFIG_EXAMPLES_OSTEST_FPUSIZE+3)>>2) +#define FPU_NTHREADS 2 + +#ifndef NULL +# define NULL (void*)0 +#endif + +/*********************************************************************** + * External Dependencies + ***********************************************************************/ +/* This test is very dependent on support provided by the chip/board- + * layer logic. In particular, it expects the following functions + * to be provided: + */ + +/* Given an array of size CONFIG_EXAMPLES_OSTEST_FPUSIZE, this function + * will return the current FPU registers. + */ + +extern void arch_getfpu(FAR uint32_t *fpusave); + +/* Given two arrays of size CONFIG_EXAMPLES_OSTEST_FPUSIZE this + * function will compare them and return true if they are identical. + */ + +extern bool arch_cmpfpu(FAR const uint32_t *fpusave1, + FAR const uint32_t *fpusave2); + +/*********************************************************************** + * Private Types + ***********************************************************************/ + +struct fpu_threaddata_s +{ + uint32_t save1[FPU_WORDSIZE]; + uint32_t save2[FPU_WORDSIZE]; + + /* These are just dummy values to force the compiler to do the + * requested floating point computations without the nonsense + * computations being optimized away. + */ + + volatile float sp1; + volatile float sp2; + volatile float sp3; + volatile float sp4; + + volatile float dp1; + volatile float dp2; + volatile float dp3; + volatile float dp4; +}; + +/*********************************************************************** + * Private Data + ***********************************************************************/ + +static uint8_t g_fpuno; +/* static */ struct fpu_threaddata_s g_fputhread[FPU_NTHREADS]; + +/*********************************************************************** + * Private Functions + ***********************************************************************/ + +static void fpu_dump(FAR uint32_t *buffer, FAR const char *msg) +{ + int i, j, k; + + printf("%s (%p):\n", msg, buffer); + for (i = 0; i < FPU_WORDSIZE; i += 8) + { + printf(" %04x: ", i); + for (j = 0; j < 8; j++) + { + k = i + j; + + if (k < FPU_WORDSIZE) + { + printf("%08x ", buffer[k]); + } + else + { + printf("\n"); + break; + } + } + printf("\n"); + } +} + +static int fpu_task(int argc, char *argv[]) +{ + FAR struct fpu_threaddata_s *fpu; + register float sp1; + register float sp2; + register float sp3; + register float sp4; + register double dp1; + register double dp2; + register double dp3; + register double dp4; + + int id; + int i; + + /* Which are we? */ + + sched_lock(); + fpu = &g_fputhread[g_fpuno]; + id = (int)(++g_fpuno); + sched_unlock(); + + /* Seed the flowing point values */ + + sp1 = (float)id; + dp1 = (double)id; + + for (i = 0; i < CONFIG_EXAMPLES_OSTEST_FPULOOPS; i++) + { + printf("FPU#%d: pass %d\n", id, i+1); + fflush(stdout); + + /* Set the FPU register save arrays to a known-but-illogical values so + * that we can verify that reading of the registers actually occurs. + */ + + memset(fpu->save1, 0xff, FPU_WORDSIZE * sizeof(uint32_t)); + memset(fpu->save2, 0xff, FPU_WORDSIZE * sizeof(uint32_t)); + + /* Prevent context switches while we set up some stuff */ + + sched_lock(); + + /* Do some trivial floating point operations that should cause some + * changes to floating point registers. First, some single preceision + * nonsense. + */ + + sp4 = (float)3.14159 * sp1; /* Multiple by Pi */ + sp3 = sp4 + (float)1.61803; /* Add the golden ratio */ + sp2 = sp3 / (float)2.71828; /* Divide by Euler's constant */ + sp1 = sp2 + (float)1.0; /* Plus one */ + + fpu->sp1 = sp1; /* Make the compiler believe that somebody cares about the result */ + fpu->sp2 = sp2; + fpu->sp3 = sp3; + fpu->sp4 = sp4; + + /* Again using double precision */ + + dp4 = (double)3.14159 * dp1; /* Multiple by Pi */ + dp3 = dp4 + (double)1.61803; /* Add the golden ratio */ + dp2 = dp3 / (double)2.71828; /* Divide by Euler's constant */ + dp1 = dp2 + (double)1.0; /* Plus one */ + + fpu->dp1 = dp1; /* Make the compiler believe that somebody cares about the result */ + fpu->dp2 = dp2; + fpu->dp3 = dp3; + fpu->dp4 = dp4; + + /* Sample the floating point registers */ + + arch_getfpu(fpu->save1); + + /* Re-read and verify the FPU registers consistently without corruption */ + + arch_getfpu(fpu->save2); + if (!arch_cmpfpu(fpu->save1, fpu->save2)) + { + printf("ERROR FPU#%d: save1 and save2 do not match\n", id); + fpu_dump(fpu->save1, "Values after math operations (save1)"); + fpu_dump(fpu->save2, "Values after verify re-read (save2)"); + return EXIT_FAILURE; + } + + /* Now unlock and sleep for a while -- this should result in some context switches */ + + sched_unlock(); + usleep(CONFIG_EXAMPLES_OSTEST_FPUMSDELAY * 1000); + + /* Several context switches should have occurred. Now verify that the floating + * point registers are still correctly set. + */ + + arch_getfpu(fpu->save2); + if (!arch_cmpfpu(fpu->save1, fpu->save2)) + { + printf("ERROR FPU#%d: save1 and save2 do not match\n", id); + fpu_dump(fpu->save1, "Values before waiting (save1)"); + fpu_dump(fpu->save2, "Values after waiting (save2)"); + return EXIT_FAILURE; + } + } + + printf("FPU#%d: Succeeded\n", id); + fflush(stdout); + return EXIT_SUCCESS; +} +#endif /* HAVE_FPU */ + +/*********************************************************************** + * Private Functions + ***********************************************************************/ + +void fpu_test(void) +{ +#ifdef HAVE_FPU + pid_t task1; + pid_t task2; + int statloc; + + /* Start two two tasks */ + + g_fpuno = 0; + printf("Starting task FPU#1\n"); + task1 = TASK_CREATE("FPU#1", CONFIG_EXAMPLES_OSTEST_FPUPRIORITY, CONFIG_EXAMPLES_OSTEST_FPUSTACKSIZE, fpu_task, NULL); + if (task1 < 0) + { + printf("fpu_test: ERROR Failed to start task FPU#1\n"); + } + else + { + printf("fpu_test: Started task FPU#1 at PID=%d\n", task1); + } + fflush(stdout); + usleep(250); + + printf("Starting task FPU#2\n"); + task2 = TASK_CREATE("FPU#2", CONFIG_EXAMPLES_OSTEST_FPUPRIORITY, CONFIG_EXAMPLES_OSTEST_FPUSTACKSIZE, fpu_task, NULL); + if (task2 < 0) + { + printf("fpu_test: ERROR Failed to start task FPU#1\n"); + } + else + { + printf("fpu_test: Started task FPU#2 at PID=%d\n", task2); + } + + /* Wait for each task to complete */ + + fflush(stdout); + (void)waitpid(task1, &statloc, 0); + (void)waitpid(task2, &statloc, 0); + +#else + printf("fpu_test: ERROR: The FPU test is not properly configured\n"); +#endif + printf("fpu_test: Returning\n"); +} diff --git a/apps/examples/ostest/main.c b/apps/examples/ostest/main.c new file mode 100644 index 0000000000..7d63c0ff48 --- /dev/null +++ b/apps/examples/ostest/main.c @@ -0,0 +1,530 @@ +/**************************************************************************** + * apps/examples/ostest/main.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ostest.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define PRIORITY 100 +#define NARGS 4 +#define HALF_SECOND_USEC 500000L + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char arg1[] = "Arg1"; +static const char arg2[] = "Arg2"; +static const char arg3[] = "Arg3"; +static const char arg4[] = "Arg4"; + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static const char write_data1[] = "stdio_test: write fd=1\n"; +static const char write_data2[] = "stdio_test: write fd=2\n"; +#endif + +#ifdef SDCC +/* I am not yet certain why SDCC does not like the following + * initializer. It involves some issues with 2- vs 3-byte + * pointer types. + */ + +static const char *g_argv[NARGS+1]; +#else +static const char *g_argv[NARGS+1] = { arg1, arg2, arg3, arg4, NULL }; +#endif + +#ifndef CONFIG_DISABLE_SIGNALS +static struct mallinfo g_mmbefore; +static struct mallinfo g_mmprevious; +static struct mallinfo g_mmafter; +#endif + +#ifndef CONFIG_DISABLE_ENVIRON +const char g_var1_name[] = "Variable1"; +const char g_var1_value[] = "GoodValue1"; +const char g_var2_name[] = "Variable2"; +const char g_var2_value[] = "GoodValue2"; +const char g_var3_name[] = "Variable3"; +const char g_var3_value[] = "GoodValue3"; + +const char g_bad_value1[] = "BadValue1"; +const char g_bad_value2[] = "BadValue2"; + +const char g_putenv_value[] = "Variable1=BadValue3"; + +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: show_memory_usage + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_SIGNALS +static void show_memory_usage(struct mallinfo *mmbefore, + struct mallinfo *mmafter) +{ + printf("VARIABLE BEFORE AFTER\n"); + printf("======== ======== ========\n"); + printf("arena %8x %8x\n", mmbefore->arena, mmafter->arena); + printf("ordblks %8d %8d\n", mmbefore->ordblks, mmafter->ordblks); + printf("mxordblk %8x %8x\n", mmbefore->mxordblk, mmafter->mxordblk); + printf("uordblks %8x %8x\n", mmbefore->uordblks, mmafter->uordblks); + printf("fordblks %8x %8x\n", mmbefore->fordblks, mmafter->fordblks); +} +#else +# define show_memory_usage(mm1, mm2) +#endif + +/**************************************************************************** + * Name: check_test_memory_usage + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_SIGNALS +static void check_test_memory_usage(void) +{ + /* Wait a little bit to let any threads terminate */ + + usleep(HALF_SECOND_USEC); + + /* Get the current memory usage */ + +#ifdef CONFIG_CAN_PASS_STRUCTS + g_mmafter = mallinfo(); +#else + (void)mallinfo(&g_mmafter); +#endif + + /* Show the change from the previous time */ + + printf("\nEnd of test memory usage:\n"); + show_memory_usage(&g_mmprevious, &g_mmafter); + + /* Set up for the next test */ + +#ifdef CONFIG_CAN_PASS_STRUCTS + g_mmprevious = g_mmafter; +#else + memcpy(&g_mmprevious, &g_mmafter, sizeof(struct mallinfo)); +#endif + + /* If so enabled, show the use of priority inheritance resources */ + + dump_nfreeholders("user_main:"); +} +#else +# define check_test_memory_usage() +#endif + +/**************************************************************************** + * Name: show_variable + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_ENVIRON +static void show_variable(const char *var_name, const char *exptd_value, bool var_valid) +{ + char *actual_value = getenv(var_name); + if (actual_value) + { + if (var_valid) + { + if (strcmp(actual_value, exptd_value) == 0) + { + printf("show_variable: Variable=%s has value=%s\n", var_name, exptd_value); + } + else + { + printf("show_variable: ERROR Variable=%s has the wrong value\n", var_name); + printf("show_variable: found=%s expected=%s\n", actual_value, exptd_value); + } + } + else + { + printf("show_variable: ERROR Variable=%s has a value when it should not\n", var_name); + printf("show_variable: value=%s\n", actual_value); + } + } + else if (var_valid) + { + printf("show_variable: ERROR Variable=%s has no value\n", var_name); + printf("show_variable: Should have had value=%s\n", exptd_value); + } + else + { + printf("show_variable: Variable=%s has no value\n", var_name); + } +} + +static void show_environment(bool var1_valid, bool var2_valid, bool var3_valid) +{ + show_variable(g_var1_name, g_var1_value, var1_valid); + show_variable(g_var2_name, g_var2_value, var2_valid); + show_variable(g_var3_name, g_var3_value, var3_valid); +} +#else +# define show_environment() +#endif + +/**************************************************************************** + * Name: user_main + ****************************************************************************/ + +static int user_main(int argc, char *argv[]) +{ + int i; + + /* Sample the memory usage now */ + +#ifndef CONFIG_DISABLE_SIGNALS + usleep(HALF_SECOND_USEC); + +#ifdef CONFIG_CAN_PASS_STRUCTS + g_mmbefore = mallinfo(); + g_mmprevious = g_mmbefore; +#else + (void)mallinfo(&g_mmbefore); + memcpy(&g_mmprevious, &g_mmbefore, sizeof(struct mallinfo)); +#endif +#endif + + printf("\nuser_main: Begin argument test\n"); + printf("user_main: Started with argc=%d\n", argc); + + /* Verify passed arguments */ + + if (argc != NARGS + 1) + { + printf("user_main: Error expected argc=%d got argc=%d\n", + NARGS+1, argc); + } + + for (i = 0; i <= NARGS; i++) + { + printf("user_main: argv[%d]=\"%s\"\n", i, argv[i]); + } + + for (i = 1; i <= NARGS; i++) + { + if (strcmp(argv[i], g_argv[i-1]) != 0) + { + printf("user_main: ERROR argv[%d]: Expected \"%s\" found \"%s\"\n", + i, g_argv[i-1], argv[i]); + } + } + check_test_memory_usage(); + + /* Check environment variables */ +#ifndef CONFIG_DISABLE_ENVIRON + show_environment(true, true, true); + + unsetenv(g_var1_name); + show_environment(false, true, true); + check_test_memory_usage(); + + clearenv(); + show_environment(false, false, false); + check_test_memory_usage(); +#endif + + /* Top of test loop */ + +#if CONFIG_EXAMPLES_OSTEST_LOOPS > 1 + for (i = 0; i < CONFIG_EXAMPLES_OSTEST_LOOPS; i++) +#elif CONFIG_EXAMPLES_OSTEST_LOOPS == 0 + for (;;) +#endif + { +#if CONFIG_NFILE_DESCRIPTORS > 0 + /* Checkout /dev/null */ + + printf("\nuser_main: /dev/null test\n"); + dev_null(); + check_test_memory_usage(); +#endif + +#ifdef CONFIG_ARCH_FPU + /* Check that the FPU is properly supported during context switching */ + + printf("\nuser_main: FPU test\n"); + fpu_test(); + check_test_memory_usage(); +#endif + +#ifndef CONFIG_DISABLE_PTHREAD + /* Verify pthreads and pthread mutex */ + + printf("\nuser_main: mutex test\n"); + mutex_test(); + check_test_memory_usage(); +#endif + +#if !defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_MUTEX_TYPES) + /* Verify recursive mutexes */ + + printf("\nuser_main: recursive mutex test\n"); + recursive_mutex_test(); + check_test_memory_usage(); +#endif + +#ifndef CONFIG_DISABLE_PTHREAD + /* Verify pthread cancellation */ + + printf("\nuser_main: cancel test\n"); + cancel_test(); + check_test_memory_usage(); +#endif + +#ifndef CONFIG_DISABLE_PTHREAD + /* Verify pthreads and semaphores */ + + printf("\nuser_main: semaphore test\n"); + sem_test(); + check_test_memory_usage(); +#endif + +#ifndef CONFIG_DISABLE_PTHREAD + /* Verify pthreads and condition variables */ + + printf("\nuser_main: condition variable test\n"); +#ifdef CONFIG_PRIORITY_INHERITANCE + printf("\n Skipping, Test logic incompatible with priority inheritance\n"); +#else + cond_test(); + check_test_memory_usage(); +#endif +#endif + +#if !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD) && !defined(CONFIG_DISABLE_CLOCK) + /* Verify pthreads and condition variable timed waits */ + + printf("\nuser_main: timed wait test\n"); + timedwait_test(); + check_test_memory_usage(); +#endif + +#if !defined(CONFIG_DISABLE_MQUEUE) && !defined(CONFIG_DISABLE_PTHREAD) + /* Verify pthreads and message queues */ + + printf("\nuser_main: message queue test\n"); + mqueue_test(); + check_test_memory_usage(); +#endif + +#if !defined(CONFIG_DISABLE_MQUEUE) && !defined(CONFIG_DISABLE_PTHREAD) && !defined(CONFIG_DISABLE_CLOCK) + /* Verify pthreads and message queues */ + + printf("\nuser_main: timed message queue test\n"); + timedmqueue_test(); + check_test_memory_usage(); +#endif + +#ifndef CONFIG_DISABLE_SIGNALS + /* Verify signal handlers */ + + printf("\nuser_main: signal handler test\n"); + sighand_test(); + check_test_memory_usage(); +#endif + +#if !defined(CONFIG_DISABLE_POSIX_TIMERS) && !defined(CONFIG_DISABLE_SIGNALS) + /* Verify posix timers */ + + printf("\nuser_main: POSIX timer test\n"); + timer_test(); + check_test_memory_usage(); +#endif + +#if !defined(CONFIG_DISABLE_PTHREAD) && CONFIG_RR_INTERVAL > 0 + /* Verify round robin scheduling */ + + printf("\nuser_main: round-robin scheduler test\n"); + rr_test(); + check_test_memory_usage(); +#endif + +#ifndef CONFIG_DISABLE_PTHREAD + /* Verify pthread barriers */ + + printf("\nuser_main: barrier test\n"); + barrier_test(); + check_test_memory_usage(); +#endif + +#if defined(CONFIG_PRIORITY_INHERITANCE) && !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD) + /* Verify priority inheritance */ + + printf("\nuser_main: priority inheritance test\n"); + priority_inheritance(); + check_test_memory_usage(); +#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */ + + /* Compare memory usage at time user_start started until + * user_main exits. These should not be identical, but should + * be similar enough that we can detect any serious OS memory + * leaks. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + usleep(HALF_SECOND_USEC); + +#ifdef CONFIG_CAN_PASS_STRUCTS + g_mmafter = mallinfo(); +#else + (void)mallinfo(&g_mmafter); +#endif + + printf("\nFinal memory usage:\n"); + show_memory_usage(&g_mmbefore, &g_mmafter); +#endif + } + printf("user_main: Exitting\n"); + return 0; +} + +/**************************************************************************** + * Name: stdio_test + ****************************************************************************/ + +static void stdio_test(void) +{ + /* Verify that we can communicate */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + write(1, write_data1, sizeof(write_data1)-1); +#endif + printf("stdio_test: Standard I/O Check: printf\n"); + +#if CONFIG_NFILE_DESCRIPTORS > 1 + write(2, write_data2, sizeof(write_data2)-1); +#endif +#if CONFIG_NFILE_STREAMS > 0 + fprintf(stderr, "stdio_test: Standard I/O Check: fprintf to stderr\n"); +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * user_start/ostest_main + ****************************************************************************/ + +#ifdef CONFIG_EXAMPLES_OSTEST_BUILTIN +# define MAIN_NAME ostest_main +# define MAIN_STRING "ostest_main: " +#else +# define MAIN_NAME user_start +# define MAIN_STRING "user_start: " +#endif + +int MAIN_NAME(int argc, char *argv[]) +{ + int result; + + /* Verify that stdio works first */ + + stdio_test(); + +#ifdef SDCC + /* I am not yet certain why SDCC does not like the following initilizers. + * It involves some issues with 2- vs 3-byte pointer types. + */ + + g_argv[0] = arg1; + g_argv[1] = arg2; + g_argv[2] = arg3; + g_argv[3] = arg4; + g_argv[4] = NULL; +#endif + + /* Set up some environment variables */ + +#ifndef CONFIG_DISABLE_ENVIRON + printf(MAIN_STRING "putenv(%s)\n", g_putenv_value); + putenv(g_putenv_value); /* Varaible1=BadValue3 */ + printf(MAIN_STRING "setenv(%s, %s, TRUE)\n", g_var1_name, g_var1_value); + setenv(g_var1_name, g_var1_value, TRUE); /* Variable1=GoodValue1 */ + + printf(MAIN_STRING "setenv(%s, %s, FALSE)\n", g_var2_name, g_bad_value1); + setenv(g_var2_name, g_bad_value1, FALSE); /* Variable2=BadValue1 */ + printf(MAIN_STRING "setenv(%s, %s, TRUE)\n", g_var2_name, g_var2_value); + setenv(g_var2_name, g_var2_value, TRUE); /* Variable2=GoodValue2 */ + + printf(MAIN_STRING "setenv(%s, %s, FALSE)\n", g_var3_name, g_var3_name); + setenv(g_var3_name, g_var3_value, FALSE); /* Variable3=GoodValue3 */ + printf(MAIN_STRING "setenv(%s, %s, FALSE)\n", g_var3_name, g_var3_name); + setenv(g_var3_name, g_bad_value2, FALSE); /* Variable3=GoodValue3 */ + show_environment(true, true, true); +#endif + + /* Verify that we can spawn a new task */ + +#ifndef CONFIG_CUSTOM_STACK + result = task_create("ostest", PRIORITY, STACKSIZE, user_main, g_argv); +#else + result = task_create("ostest", PRIORITY, user_main, g_argv); +#endif + if (result == ERROR) + { + printf(MAIN_STRING "ERROR Failed to start user_main\n"); + } + else + { + printf(MAIN_STRING "Started user_main at PID=%d\n", result); + } + + printf(MAIN_STRING "Exitting\n"); + return 0; +} diff --git a/apps/examples/ostest/mqueue.c b/apps/examples/ostest/mqueue.c new file mode 100644 index 0000000000..39ef76a53b --- /dev/null +++ b/apps/examples/ostest/mqueue.c @@ -0,0 +1,394 @@ +/************************************************************************** + * apps/examples/ostest/mqueue.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************/ + +/************************************************************************** + * Included Files + **************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ostest.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ + +#define TEST_MESSAGE "This is a test and only a test" +#if defined(SDCC) || defined(__ZILOG__) + /* Cannot use strlen in array size */ + +# define TEST_MSGLEN (31) +#else + /* Message lenght is the size of the message plus the null terminator */ + +# define TEST_MSGLEN (strlen(TEST_MESSAGE)+1) +#endif + +#define TEST_SEND_NMSGS (10) +#ifndef CONFIG_DISABLE_SIGNALS +# define TEST_RECEIVE_NMSGS (11) +#else +# define TEST_RECEIVE_NMSGS (10) +#endif + +#define HALF_SECOND_USEC_USEC 500000L + +/************************************************************************** + * Private Types + **************************************************************************/ + +/************************************************************************** + * Private Function Prototypes + **************************************************************************/ + +/************************************************************************** + * Global Variables + **************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/************************************************************************** + * Public Functions + **************************************************************************/ + +static void *sender_thread(void *arg) +{ + mqd_t mqfd; + char msg_buffer[TEST_MSGLEN]; + struct mq_attr attr; + int status = 0; + int nerrors = 0; + int i; + + printf("sender_thread: Starting\n"); + + /* Fill in attributes for message queue */ + + attr.mq_maxmsg = 20; + attr.mq_msgsize = TEST_MSGLEN; + attr.mq_flags = 0; + + /* Set the flags for the open of the queue. + * Make it a blocking open on the queue, meaning it will block if + * this process tries to send to the queue and the queue is full. + * + * O_CREAT - the queue will get created if it does not already exist. + * O_WRONLY - we are only planning to write to the queue. + * + * Open the queue, and create it if the receiving process hasn't + * already created it. + */ + + mqfd = mq_open("testmq", O_WRONLY|O_CREAT, 0666, &attr); + if (mqfd < 0) + { + printf("sender_thread: ERROR mq_open failed\n"); + pthread_exit((pthread_addr_t)1); + } + + /* Fill in a test message buffer to send */ + + memcpy(msg_buffer, TEST_MESSAGE, TEST_MSGLEN); + + /* Perform the send TEST_SEND_NMSGS times */ + + for (i = 0; i < TEST_SEND_NMSGS; i++) + { + status = mq_send(mqfd, msg_buffer, TEST_MSGLEN, 42); + if (status < 0) + { + printf("sender_thread: ERROR mq_send failure=%d on msg %d\n", status, i); + nerrors++; + } + else + { + printf("sender_thread: mq_send succeeded on msg %d\n", i); + } + } + + /* Close the queue and return success */ + + if (mq_close(mqfd) < 0) + { + printf("sender_thread: ERROR mq_close failed\n"); + } + + printf("sender_thread: returning nerrors=%d\n", nerrors); + return (pthread_addr_t)nerrors; +} + +static void *receiver_thread(void *arg) +{ + mqd_t mqfd; + char msg_buffer[TEST_MSGLEN]; + struct mq_attr attr; + int nbytes; + int nerrors = 0; + int i; + + printf("receiver_thread: Starting\n"); + + /* Fill in attributes for message queue */ + + attr.mq_maxmsg = 20; + attr.mq_msgsize = TEST_MSGLEN; + attr.mq_flags = 0; + + /* Set the flags for the open of the queue. + * Make it a blocking open on the queue, meaning it will block if + * this task tries to read from the queue when the queue is empty + * + * O_CREAT - the queue will get created if it does not already exist. + * O_RDONLY - we are only planning to read from the queue. + * + * Open the queue, and create it if the sending process hasn't + * already created it. + */ + + mqfd = mq_open("testmq", O_RDONLY|O_CREAT, 0666, &attr); + if (mqfd < 0) + { + printf("receiver_thread: ERROR mq_open failed\n"); + pthread_exit((pthread_addr_t)1); + } + + /* Perform the receive TEST_RECEIVE_NMSGS times */ + + for (i = 0; i < TEST_RECEIVE_NMSGS; i++) + { + memset(msg_buffer, 0xaa, TEST_MSGLEN); + nbytes = mq_receive(mqfd, msg_buffer, TEST_MSGLEN, 0); + if (nbytes < 0) + { + /* mq_receive failed. If the error is because of EINTR then + * it is not a failure. + */ + + if (errno != EINTR) + { + printf("receiver_thread: ERROR mq_receive failure on msg %d, errno=%d\n", i, errno); + nerrors++; + } + else + { + printf("receiver_thread: mq_receive interrupted!\n"); + } + } + else if (nbytes != TEST_MSGLEN) + { + printf("receiver_thread: mq_receive return bad size %d on msg %d\n", nbytes, i); + nerrors++; + } + else if (memcmp(TEST_MESSAGE, msg_buffer, nbytes) != 0) + { + int j; + + printf("receiver_thread: mq_receive returned corrupt message on msg %d\n", i); + printf("receiver_thread: i Expected Received\n"); + + for (j = 0; j < TEST_MSGLEN-1; j++) + { + if (isprint(msg_buffer[j])) + { + printf("receiver_thread: %2d %02x (%c) %02x (%c)\n", + j, TEST_MESSAGE[j], TEST_MESSAGE[j], msg_buffer[j], msg_buffer[j]); + } + else + { + printf("receiver_thread: %2d %02x (%c) %02x\n", + j, TEST_MESSAGE[j], TEST_MESSAGE[j], msg_buffer[j]); + } + } + printf("receiver_thread: %2d 00 %02x\n", + j, msg_buffer[j]); + } + else + { + printf("receiver_thread: mq_receive succeeded on msg %d\n", i); + } + } + + /* Close the queue and return success */ + + if (mq_close(mqfd) < 0) + { + printf("receiver_thread: ERROR mq_close failed\n"); + nerrors++; + } + + /* Destroy the queue */ + + if (mq_unlink("testmq") < 0) + { + printf("receiver_thread: ERROR mq_close failed\n"); + nerrors++; + } + + printf("receiver_thread: returning nerrors=%d\n", nerrors); + pthread_exit((pthread_addr_t)nerrors); + return (pthread_addr_t)nerrors; +} + +void mqueue_test(void) +{ + pthread_t sender; + pthread_t receiver; + void *result; + pthread_attr_t attr; + struct sched_param sparam; + int prio_min; + int prio_max; + int prio_mid; + int status; + + /* Start the sending thread at higher priority */ + + printf("mqueue_test: Starting receiver\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("mqueue_test: pthread_attr_init failed, status=%d\n", status); + } + + status = pthread_attr_setstacksize(&attr, STACKSIZE); + if (status != 0) + { + printf("mqueue_test: pthread_attr_setstacksize failed, status=%d\n", status); + } + + prio_min = sched_get_priority_min(SCHED_FIFO); + prio_max = sched_get_priority_max(SCHED_FIFO); + prio_mid = (prio_min + prio_max) / 2; + + sparam.sched_priority = prio_mid; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("mqueue_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("mqueue_test: Set receiver priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&receiver, &attr, receiver_thread, NULL); + if (status != 0) + { + printf("mqueue_test: pthread_create failed, status=%d\n", status); + } + + /* Start the sending thread at lower priority */ + + printf("mqueue_test: Starting sender\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("mqueue_test: pthread_attr_init failed, status=%d\n", status); + } + + status = pthread_attr_setstacksize(&attr, STACKSIZE); + if (status != 0) + { + printf("mqueue_test: pthread_attr_setstacksize failed, status=%d\n", status); + } + + sparam.sched_priority = (prio_min + prio_mid) / 2; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("mqueue_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("mqueue_test: Set sender thread priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&sender, &attr, sender_thread, NULL); + if (status != 0) + { + printf("mqueue_test: pthread_create failed, status=%d\n", status); + } + + printf("mqueue_test: Waiting for sender to complete\n"); + pthread_join(sender, &result); + if (result != (void*)0) + { + printf("mqueue_test: ERROR sender thread exited with %d errors\n", (int)result); + } + +#ifndef CONFIG_DISABLE_SIGNALS + /* Wake up the receiver thread with a signal */ + + printf("mqueue_test: Killing receiver\n"); + pthread_kill(receiver, 9); + + /* Wait a bit to see if the thread exits on its own */ + + usleep(HALF_SECOND_USEC_USEC); +#endif + + /* Then cancel the thread and see if it did */ + + printf("mqueue_test: Canceling receiver\n"); + status = pthread_cancel(receiver); + if (status == ESRCH) + { + printf("mqueue_test: receiver has already terminated\n"); + } + + pthread_join(receiver, &result); + if (result != (void*)0) + { + printf("mqueue_test: ERROR receiver thread exited with %d errors\n", (int)result); + } +} + + diff --git a/apps/examples/ostest/mutex.c b/apps/examples/ostest/mutex.c new file mode 100644 index 0000000000..752f833f25 --- /dev/null +++ b/apps/examples/ostest/mutex.c @@ -0,0 +1,142 @@ +/*********************************************************************** + * mutex.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ***********************************************************************/ + +#include +#include +#include "ostest.h" + +#ifndef NULL +# define NULL (void*)0 +#endif + +#define NLOOPS 32 + +static pthread_mutex_t mut; +static volatile int my_mutex = 0; +static unsigned long nloops[2] = {0, 0}; +static unsigned long nerrors[2] = {0, 0}; + +static void *thread_func(void *parameter) +{ + int id = (int)parameter; + int ndx = id - 1; + int i; + + for (nloops[ndx] = 0; nloops[ndx] < NLOOPS; nloops[ndx]++) + { + int status = pthread_mutex_lock(&mut); + if (status != 0) + { + printf("ERROR thread %d: pthread_mutex_lock failed, status=%d\n", + id, status); + } + + if (my_mutex == 1) + { + printf("ERROR thread=%d: " + "my_mutex should be zero, instead my_mutex=%d\n", + id, my_mutex); + nerrors[ndx]++; + } + + my_mutex = 1; + for (i = 0; i < 10; i++) + { + pthread_yield(); + } + my_mutex = 0; + + status = pthread_mutex_unlock(&mut); + if (status != 0) + { + printf("ERROR thread %d: pthread_mutex_unlock failed, status=%d\n", + id, status); + } + } + pthread_exit(NULL); + return NULL; /* Non-reachable -- needed for some compilers */ +} + +void mutex_test(void) +{ + pthread_t thread1, thread2; +#ifdef SDCC + pthread_addr_t result1, result2; + pthread_attr_t attr; +#endif + int status; + + /* Initialize the mutex */ + + printf("Initializing mutex\n"); + pthread_mutex_init(&mut, NULL); + + /* Start two thread instances */ + + printf("Starting thread 1\n"); +#ifdef SDCC + (void)pthread_attr_init(&attr); + status = pthread_create(&thread1, &attr, thread_func, (pthread_addr_t)1); +#else + status = pthread_create(&thread1, NULL, thread_func, (pthread_addr_t)1); +#endif + if (status != 0) + { + printf("Error in thread#1 creation\n"); + } + + printf("Starting thread 2\n"); +#ifdef SDCC + status = pthread_create(&thread2, &attr, thread_func, (pthread_addr_t)2); +#else + status = pthread_create(&thread2, NULL, thread_func, (pthread_addr_t)2); +#endif + if (status != 0) + { + printf("Error in thread#2 creation\n"); + } + +#ifdef SDCC + pthread_join(thread1, &result1); + pthread_join(thread2, &result2); +#else + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); +#endif + + printf("\t\tThread1\tThread2\n"); + printf("\tLoops\t%ld\t%ld\n", nloops[0], nloops[1]); + printf("\tErrors\t%ld\t%ld\n", nerrors[0], nerrors[1]); +} diff --git a/apps/examples/ostest/ostest.h b/apps/examples/ostest/ostest.h new file mode 100644 index 0000000000..a4af37f05f --- /dev/null +++ b/apps/examples/ostest/ostest.h @@ -0,0 +1,178 @@ +/**************************************************************************** + * apps/examples/ostest/ostest.h + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_EXAMPLES_OSTEST_OSTEST_H +#define __APPS_EXAMPLES_OSTEST_OSTEST_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* The task_create task size can be specified in the defconfig file */ + +#ifdef CONFIG_EXAMPLES_OSTEST_STACKSIZE +# define STACKSIZE CONFIG_EXAMPLES_OSTEST_STACKSIZE +#else +# define STACKSIZE 8192 +#endif + +/* The number of times to execute the test can be specified in the defconfig + * file. + */ + +#ifndef CONFIG_EXAMPLES_OSTEST_LOOPS +# define CONFIG_EXAMPLES_OSTEST_LOOPS 1 +#endif + +/* This is the number of threads that are created in the barrier test. + * A smaller number should be selected on systems without sufficient memory + * to start so many threads. + */ + +#ifndef CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS +# define CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS 8 +#endif + +/* Priority inheritance */ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_PRIORITY_INHERITANCE) && defined(CONFIG_SEM_PHDEBUG) +# define dump_nfreeholders(s) printf(s " nfreeholders: %d\n", sem_nfreeholders()) +#else +# define dump_nfreeholders(s) +#endif + +/* If CONFIG_STDIO_LINEBUFFER is defined, the STDIO buffer will be flushed + * on each new line. Otherwise, STDIO needs to be explicitly flushed to + * see the output in context. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && \ + CONFIG_STDIO_BUFFER_SIZE > 0 && !defined(CONFIG_STDIO_LINEBUFFER) +# define FFLUSH() fflush(stdout) +#else +# define FFLUSH() +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* dev_null.c ***************************************************************/ + +extern int dev_null(void); + +/* fpu.c ********************************************************************/ + +extern void fpu_test(void); + +/* mutex.c ******************************************************************/ + +extern void mutex_test(void); + +/* rmutex.c ******************************************************************/ + +extern void recursive_mutex_test(void); + +/* sem.c ********************************************************************/ + +extern void sem_test(void); + +/* cond.c *******************************************************************/ + +extern void cond_test(void); + +/* mqueue.c *****************************************************************/ + +extern void mqueue_test(void); + +/* timedmqueue.c ************************************************************/ + +extern void timedmqueue_test(void); + +/* cancel.c *****************************************************************/ + +extern void cancel_test(void); + +/* timedwait.c **************************************************************/ + +extern void timedwait_test(void); + +/* sighand.c ****************************************************************/ + +extern void sighand_test(void); + +/* posixtimers.c ************************************************************/ + +extern void timer_test(void); + +/* roundrobin.c *************************************************************/ + +extern void rr_test(void); + +/* barrier.c ****************************************************************/ + +extern void barrier_test(void); + +/* prioinherit.c ************************************************************/ + +extern void priority_inheritance(void); + +/* APIs exported (conditionally) by the OS specifically for testing of + * priority inheritance + */ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_PRIORITY_INHERITANCE) && defined(CONFIG_SEM_PHDEBUG) +extern void sem_enumholders(FAR sem_t *sem); +extern int sem_nfreeholders(void); +#else +# define sem_enumholders(sem) +# define sem_nfreeholders() +#endif + +#endif /* __APPS_EXAMPLES_OSTEST_OSTEST_H */ diff --git a/apps/examples/ostest/posixtimer.c b/apps/examples/ostest/posixtimer.c new file mode 100644 index 0000000000..3560c712be --- /dev/null +++ b/apps/examples/ostest/posixtimer.c @@ -0,0 +1,262 @@ +/*********************************************************************** + * examples/ostest/posixtimer.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ***********************************************************************/ + +/************************************************************************** + * Included Files + **************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "ostest.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ + +#ifndef NULL +# define NULL (void*)0 +#endif + +#define MY_TIMER_SIGNAL 17 +#define SIGVALUE_INT 42 + +/************************************************************************** + * Private Data + **************************************************************************/ + +static sem_t sem; +static int g_nsigreceived = 0; + +/************************************************************************** + * Private Functions + **************************************************************************/ + +static void timer_expiration(int signo, siginfo_t *info, void *ucontext) +{ + sigset_t oldset; + sigset_t allsigs; + int status; + + printf("timer_expiration: Received signal %d\n" , signo); + + g_nsigreceived++; + + /* Check signo */ + + if (signo != MY_TIMER_SIGNAL) + { + printf("timer_expiration: ERROR expected signo=%d\n" , MY_TIMER_SIGNAL); + } + + /* Check siginfo */ + + if (info->si_value.sival_int != SIGVALUE_INT) + { + printf("timer_expiration: ERROR sival_int=%d expected %d\n", + info->si_value.sival_int, SIGVALUE_INT); + } + else + { + printf("timer_expiration: sival_int=%d\n" , info->si_value.sival_int); + } + + if (info->si_signo != MY_TIMER_SIGNAL) + { + printf("timer_expiration: ERROR expected si_signo=%d, got=%d\n", + MY_TIMER_SIGNAL, info->si_signo); + } + + if (info->si_code == SI_TIMER) + { + printf("timer_expiration: si_code=%d (SI_TIMER)\n" , info->si_code); + } + else + { + printf("timer_expiration: ERROR si_code=%d, expected SI_TIMER=%d\n", + info->si_code, SI_TIMER); + } + + /* Check ucontext_t */ + + printf("timer_expiration: ucontext=%p\n" , ucontext); + + /* Check sigprocmask */ + + (void)sigfillset(&allsigs); + status = sigprocmask(SIG_SETMASK, NULL, &oldset); + if (status != OK) + { + printf("timer_expiration: ERROR sigprocmask failed, status=%d\n", + status); + } + + if (oldset != allsigs) + { + printf("timer_expiration: ERROR sigprocmask=%x expected=%x\n", + oldset, allsigs); + } + +} + +/************************************************************************** + * Public Functions + **************************************************************************/ + +void timer_test(void) +{ + sigset_t sigset; + struct sigaction act; + struct sigaction oact; + struct sigevent notify; + struct itimerspec timer; + timer_t timerid; + int status; + int i; + + printf("timer_test: Initializing semaphore to 0\n" ); + sem_init(&sem, 0, 0); + + /* Start waiter thread */ + + printf("timer_test: Unmasking signal %d\n" , MY_TIMER_SIGNAL); + + (void)sigemptyset(&sigset); + (void)sigaddset(&sigset, MY_TIMER_SIGNAL); + status = sigprocmask(SIG_UNBLOCK, &sigset, NULL); + if (status != OK) + { + printf("timer_test: ERROR sigprocmask failed, status=%d\n", + status); + } + + printf("timer_test: Registering signal handler\n" ); + act.sa_sigaction = timer_expiration; + act.sa_flags = SA_SIGINFO; + + (void)sigfillset(&act.sa_mask); + (void)sigdelset(&act.sa_mask, MY_TIMER_SIGNAL); + + status = sigaction(MY_TIMER_SIGNAL, &act, &oact); + if (status != OK) + { + printf("timer_test: ERROR sigaction failed, status=%d\n" , status); + } + +#ifndef SDCC + printf("timer_test: oact.sigaction=%p oact.sa_flags=%x oact.sa_mask=%x\n", + oact.sa_sigaction, oact.sa_flags, oact.sa_mask); +#endif + + /* Create the POSIX timer */ + + printf("timer_test: Creating timer\n" ); + + notify.sigev_notify = SIGEV_SIGNAL; + notify.sigev_signo = MY_TIMER_SIGNAL; + notify.sigev_value.sival_int = SIGVALUE_INT; + + status = timer_create(CLOCK_REALTIME, ¬ify, &timerid); + if (status != OK) + { + printf("timer_test: timer_create failed, errno=%d\n", errno); + goto errorout; + } + + /* Start the POSIX timer */ + + printf("timer_test: Starting timer\n" ); + + timer.it_value.tv_sec = 2; + timer.it_value.tv_nsec = 0; + timer.it_interval.tv_sec = 2; + timer.it_interval.tv_nsec = 0; + + status = timer_settime(timerid, 0, &timer, NULL); + if (status != OK) + { + printf("timer_test: timer_settime failed, errno=%d\n", errno); + goto errorout; + } + + /* Take the semaphore */ + + for (i = 0; i < 5; i++) + { + printf("timer_test: Waiting on semaphore\n" ); + FFLUSH(); + status = sem_wait(&sem); + if (status != 0) + { + int error = errno; + if (error == EINTR) + { + printf("timer_test: sem_wait() successfully interrupted by signal\n" ); + } + else + { + printf("timer_test: ERROR sem_wait failed, errno=%d\n" , error); + } + } + else + { + printf("timer_test: ERROR awakened with no error!\n" ); + } + printf("timer_test: g_nsigreceived=%d\n", g_nsigreceived); + } + +errorout: + sem_destroy(&sem); + + /* Then delete the timer */ + + printf("timer_test: Deleting timer\n" ); + status = timer_delete(timerid); + if (status != OK) + { + printf("timer_test: timer_create failed, errno=%d\n", errno); + } + + /* Detach the signal handler */ + + act.sa_sigaction = SIG_DFL; + status = sigaction(MY_TIMER_SIGNAL, &act, &oact); + + printf("timer_test: done\n" ); + FFLUSH(); +} diff --git a/apps/examples/ostest/prioinherit.c b/apps/examples/ostest/prioinherit.c new file mode 100644 index 0000000000..993c9e14a2 --- /dev/null +++ b/apps/examples/ostest/prioinherit.c @@ -0,0 +1,541 @@ +/**************************************************************************** + * examples/ostest/prioinherit.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#ifdef CONFIG_ARCH_SIM +# include +#endif + +#include "ostest.h" + +#if defined(CONFIG_PRIORITY_INHERITANCE) && !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD) + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#ifndef CONFIG_SEM_PREALLOCHOLDERS +# define CONFIG_SEM_PREALLOCHOLDERS 0 +#endif +#define NLOWPRI_THREADS (CONFIG_SEM_PREALLOCHOLDERS+1) + +#ifndef CONFIG_SEM_NNESTPRIO +# define CONFIG_SEM_NNESTPRIO 0 +#endif +#define NHIGHPRI_THREADS (CONFIG_SEM_NNESTPRIO+1) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +enum thstate_e +{ + NOTSTARTED = 0, + RUNNING, + WAITING, + DONE +}; + +static sem_t g_sem; +static volatile enum thstate_e g_middlestate; +static volatile enum thstate_e g_highstate[NHIGHPRI_THREADS]; +static volatile enum thstate_e g_lowstate[NLOWPRI_THREADS]; +static int g_highpri; +static int g_medpri; +static int g_lowpri; + +/**************************************************************************** + * Name: nhighpri_waiting + ****************************************************************************/ + +static int nhighpri_waiting(void) +{ + int n = 0; + int i; + + for (i = 0; i < NHIGHPRI_THREADS; i++) + { + if (g_highstate[i] == WAITING) + { + n++; + } + } + return n; +} + +/**************************************************************************** + * Name: nhighpri_running + ****************************************************************************/ + +static int nhighpri_running(void) +{ + int n = 0; + int i; + + for (i = 0; i < NHIGHPRI_THREADS; i++) + { + if (g_highstate[i] != DONE) + { + n++; + } + } + return n; +} + +/**************************************************************************** + * Name: highpri_thread + ****************************************************************************/ + +static void *highpri_thread(void *parameter) +{ + int threadno = (int)parameter; + int ret; + + g_highstate[threadno-1] = RUNNING; + + printf("highpri_thread-%d: Started\n", threadno); + FFLUSH(); + sleep(1); + + printf("highpri_thread-%d: Calling sem_wait()\n", threadno); + g_highstate[threadno-1] = WAITING; + ret = sem_wait(&g_sem); + g_highstate[threadno-1] = DONE; + + if (ret != 0) + { + printf("highpri_thread-%d: sem_take failed: %d\n", threadno, ret); + } + else if (g_middlestate == RUNNING) + { + printf("highpri_thread-%d: SUCCESS midpri_thread is still running!\n", threadno); + } + else + { + printf("highpri_thread-%d: ERROR -- midpri_thread has already exited!\n", threadno); + } + + sem_post(&g_sem); + printf("highpri_thread-%d: Okay... I'm done!\n", threadno); + FFLUSH(); + return NULL; +} + +/**************************************************************************** + * Name: hog_cpu + ****************************************************************************/ + +static inline void hog_cpu(void) +{ +#ifdef CONFIG_ARCH_SIM + /* The simulator doesn't have any mechanism to do asynchronous pre-emption + * (basically because it doesn't have any interupts/asynchronous events). + * The simulator does "fake" a timer interrupt in up_idle() -- the idle + * thread that only executes when nothing else is running. In the simulator, + * we cannot suspend the middle priority task, or we wouldn't have the + * test that we want. So, we have no option but to pump the fake clock + * here by calling up_idle(). Sigh! + */ + + up_idle(); +#else + /* On real platforms with a real timer interrupt, we really can hog the + * CPU. When the sleep() goes off in priority_inheritance(), it will + * wake up and start the high priority thread. + */ + + volatile int i; + for (i = 0; i < INT_MAX; i++); +#endif +} + +/**************************************************************************** + * Name: medpri_thread + ****************************************************************************/ + +static void *medpri_thread(void *parameter) +{ + printf("medpri_thread: Started ... I won't let go of the CPU!\n"); + g_middlestate = RUNNING; + FFLUSH(); + + /* The following loop will completely block lowpri_thread from running. + * UNLESS priority inheritance is working. In that case, its priority + * will be boosted. + */ + + while (nhighpri_running() > 0) + { + hog_cpu(); + } + + printf("medpri_thread: Okay... I'm done!\n"); + FFLUSH(); + g_middlestate = DONE; + return NULL; +} + +/**************************************************************************** + * Name: lowpri_thread + ****************************************************************************/ + +static void *lowpri_thread(void *parameter) +{ + void *retval = (void*)-1; + struct sched_param sparam; + int threadno = (int)parameter; + int expected; + int count; + int policy; + int ret; + int nwaiting; + int i; + + g_lowstate[threadno-1] = RUNNING; + printf("lowpri_thread-%d: Started\n", threadno); + + ret = pthread_getschedparam(pthread_self(), &policy, &sparam); + if (ret != 0) + { + printf("lowpri_thread-%d: ERROR pthread_getschedparam failed: %d\n", threadno, ret); + } + else + { + printf("lowpri_thread-%d: initial priority: %d\n", threadno, sparam.sched_priority); + if (sparam.sched_priority != g_lowpri) + { + printf(" ERROR should have been %d\n", g_lowpri); + } + } + + g_lowstate[threadno-1] = WAITING; + ret = sem_wait(&g_sem); + if (ret != 0) + { + printf("lowpri_thread-%d: sem_take failed: %d\n", threadno, ret); + } + else + { + /* Hang on to the thread until the middle priority thread runs */ + + while (g_middlestate == NOTSTARTED && nhighpri_waiting() < NHIGHPRI_THREADS) + { + printf("lowpri_thread-%d: Waiting for the midle pri task to run\n", threadno); + printf(" g_middlestate: %d\n", (int)g_middlestate); + for (i = 0; i < NHIGHPRI_THREADS; i++) + { + printf(" g_highstate[%d]: %d\n", i, (int)g_highstate[i]); + } + printf(" I still have a count on the semaphore\n"); + sem_enumholders(&g_sem); + FFLUSH(); + sleep(1); + } + + /* Account for all of the semaphore counts. At any given time if there are 'n' + * running hight prioity tasks, then the semaphore count should be '-n' + */ + + sched_lock(); /* Needs to be atomic */ + ret = sem_getvalue(&g_sem, &count); + nwaiting = nhighpri_waiting(); + sched_unlock(); + + if (ret < 0) + { + printf("lowpri_thread-%d: ERROR sem_getvalue failed: %d\n", threadno, errno); + } + printf("lowpri_thread-%d: Sem count: %d, No. highpri thread: %d\n", threadno, count, nwaiting); + + /* The middle priority task is running, let go of the semaphore */ + + if (g_middlestate == RUNNING && nwaiting == -count) + { + /* Good.. the middle priority task is still running and the counts are okay. */ + + retval = NULL; + } + else + { + /* If the sem count is positive, then there all of the higher priority threads + * should have already completed. + */ + + printf("lowpri_thread-%d: %s the middle priority task has already exitted!\n", + threadno, count >= 0 ? "SUCCESS" : "ERROR" ); + printf(" g_middlestate: %d sem count=%d\n", (int)g_middlestate, count); + for (i = 0; i < NHIGHPRI_THREADS; i++) + { + printf(" g_highstate[%d]: %d\n", i, (int)g_highstate[i]); + } + } + } + + ret = pthread_getschedparam(pthread_self(), &policy, &sparam); + sem_enumholders(&g_sem); + sem_post(&g_sem); + if (ret != 0) + { + printf("lowpri_thread-%d: ERROR pthread_getschedparam failed: %d\n", threadno, ret); + } + else + { + if (nwaiting > 0) + { + expected = g_highpri; + } + else + { + expected = g_lowpri; + } + + printf("lowpri_thread-%d: %s priority before sem_post: %d\n", + threadno, + sparam.sched_priority != expected ? "ERROR" : "SUCCESS", + sparam.sched_priority); + + if (sparam.sched_priority != expected) + { + printf(" ERROR should have been %d\n", expected); + } + } + + ret = pthread_getschedparam(pthread_self(), &policy, &sparam); + if (ret != 0) + { + printf("lowpri_thread-%d: ERROR pthread_getschedparam failed: %d\n", threadno, ret); + } + else + { + printf("lowpri_thread-%d: %s final priority: %d\n", + threadno, + sparam.sched_priority != g_lowpri ? "ERROR" : "SUCCESS", + sparam.sched_priority); + + if (sparam.sched_priority != g_lowpri) + { + printf(" ERROR should have been %d\n", g_lowpri); + } + } + sem_enumholders(&g_sem); + + printf("lowpri_thread-%d: Okay... I'm done!\n", threadno); + FFLUSH(); + g_lowstate[threadno-1] = DONE; + return retval; +} +#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: priority_inheritance + ****************************************************************************/ + +void priority_inheritance(void) +{ +#if defined(CONFIG_PRIORITY_INHERITANCE) && !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD) + pthread_t lowpri[NLOWPRI_THREADS]; + pthread_t medpri; + pthread_t highpri[NHIGHPRI_THREADS]; + pthread_addr_t result; + pthread_attr_t attr; + struct sched_param sparam; + int my_pri; + int status; + int i; + + printf("priority_inheritance: Started\n"); + + g_middlestate = NOTSTARTED; + for (i = 0; i < NHIGHPRI_THREADS; i++) g_highstate[i] = NOTSTARTED; + for (i = 0; i < NLOWPRI_THREADS; i++) g_lowstate[i] = NOTSTARTED; + + status = sched_getparam (getpid(), &sparam); + if (status != 0) + { + printf("priority_inheritance: sched_getparam failed\n"); + sparam.sched_priority = PTHREAD_DEFAULT_PRIORITY; + } + my_pri = sparam.sched_priority; + + g_highpri = sched_get_priority_max(SCHED_FIFO); + g_lowpri = sched_get_priority_min(SCHED_FIFO); + g_medpri = my_pri - 1; + + sem_init(&g_sem, 0, NLOWPRI_THREADS); + dump_nfreeholders("priority_inheritance:"); + + /* Start the low priority threads */ + + for (i = 0; i < NLOWPRI_THREADS; i++) + { + int threadno = i+1; + printf("priority_inheritance: Starting lowpri_thread-%d (of %d) at %d\n", + threadno, NLOWPRI_THREADS, g_lowpri); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("priority_inheritance: pthread_attr_init failed, status=%d\n", status); + } + sparam.sched_priority = g_lowpri; + status = pthread_attr_setschedparam(&attr,& sparam); + if (status != OK) + { + printf("priority_inheritance: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("priority_inheritance: Set lowpri_thread-%d priority to %d\n", + threadno, sparam.sched_priority); + } + + status = pthread_create(&lowpri[i], &attr, lowpri_thread, (void*)threadno); + if (status != 0) + { + printf("priority_inheritance: pthread_create failed, status=%d\n", status); + } + } + printf("priority_inheritance: Waiting...\n"); + sleep(2); + dump_nfreeholders("priority_inheritance:"); + + /* Start the medium priority thread */ + + printf("priority_inheritance: Starting medpri_thread at %d\n", g_medpri); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("priority_inheritance: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = g_medpri; + status = pthread_attr_setschedparam(&attr,& sparam); + if (status != OK) + { + printf("priority_inheritance: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("priority_inheritance: Set medpri_thread priority to %d\n", sparam.sched_priority); + } + FFLUSH(); + + status = pthread_create(&medpri, &attr, medpri_thread, NULL); + if (status != 0) + { + printf("priority_inheritance: pthread_create failed, status=%d\n", status); + } + printf("priority_inheritance: Waiting...\n"); + sleep(1); + dump_nfreeholders("priority_inheritance:"); + + /* Start the high priority threads */ + + for (i = 0; i < NHIGHPRI_THREADS; i++) + { + int threadno = i+1; + printf("priority_inheritance: Starting highpri_thread-%d (of %d) at %d\n", + threadno, NHIGHPRI_THREADS, g_highpri); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("priority_inheritance: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = g_highpri - i; + status = pthread_attr_setschedparam(&attr,& sparam); + if (status != OK) + { + printf("priority_inheritance: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("priority_inheritance: Set highpri_thread-%d priority to %d\n", + threadno, sparam.sched_priority); + } + FFLUSH(); + + status = pthread_create(&highpri[i], &attr, highpri_thread, (void*)threadno); + if (status != 0) + { + printf("priority_inheritance: pthread_create failed, status=%d\n", status); + } + } + dump_nfreeholders("priority_inheritance:"); + FFLUSH(); + + /* Wait for all thread instances to complete */ + + for (i = 0; i < NHIGHPRI_THREADS; i++) + { + printf("priority_inheritance: Waiting for highpri_thread-%d to complete\n", i+1); + FFLUSH(); + (void)pthread_join(highpri[i], &result); + dump_nfreeholders("priority_inheritance:"); + } + printf("priority_inheritance: Waiting for medpri_thread to complete\n"); + FFLUSH(); + (void)pthread_join(medpri, &result); + dump_nfreeholders("priority_inheritance:"); + for (i = 0; i < NLOWPRI_THREADS; i++) + { + printf("priority_inheritance: Waiting for lowpri_thread-%d to complete\n", i+1); + FFLUSH(); + (void)pthread_join(lowpri[i], &result); + dump_nfreeholders("priority_inheritance:"); + } + + printf("priority_inheritance: Finished\n"); + sem_destroy(&g_sem); + dump_nfreeholders("priority_inheritance:"); + FFLUSH(); +#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */ +} diff --git a/apps/examples/ostest/rmutex.c b/apps/examples/ostest/rmutex.c new file mode 100644 index 0000000000..44eb4bb3b5 --- /dev/null +++ b/apps/examples/ostest/rmutex.c @@ -0,0 +1,166 @@ +/*********************************************************************** + * rmutex.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ***********************************************************************/ + +#include +#include +#include "ostest.h" + +#ifndef NULL +# define NULL (void*)0 +#endif + +#define NTHREADS 3 +#define NLOOPS 3 +#define NRECURSIONS 3 + +static pthread_mutex_t mut; + +static void thread_inner(int id, int level) +{ + int status; + if (level < NRECURSIONS) + { + /* Take the mutex */ + + printf("thread_inner[%d, %d]: Locking\n", id, level); + status = pthread_mutex_lock(&mut); + if (status != 0) + { + printf("thread_inner[%d, %d]: ERROR pthread_mutex_lock failed: %d\n", + id, level, status); + } + printf("thread_inner[%d, %d]: Locked\n", id, level); + + /* Give the other threads a chance */ + + pthread_yield(); + thread_inner(id, level+1); + pthread_yield(); + + /* Unlock the mutex */ + + printf("thread_inner[%d, %d]: Unlocking\n", id, level); + status = pthread_mutex_unlock(&mut); + if (status != 0) + { + printf("thread_inner[%d, %d]: ERROR pthread_mutex_unlock failed: %d\n", + id, level, status); + } + printf("thread_inner[%d, %d]: Unlocked\n", id, level); + pthread_yield(); + } +} + +static void *thread_outer(void *parameter) +{ + int i; + printf("thread_outer[%d]: Started\n", (int)parameter); + for (i = 0; i < NLOOPS; i++) + { + printf("thread_outer[%d]: Loop %d\n", (int)parameter, i); + thread_inner((int)parameter, 0); + } + printf("thread_outer[%d]: Exitting\n", (int)parameter); + pthread_exit(NULL); + return NULL; /* Non-reachable -- needed for some compilers */ +} + +void recursive_mutex_test(void) +{ + pthread_t thread[NTHREADS]; +#ifdef SDCC + pthread_addr_t result[NTHREADS]; + pthread_attr_t attr; +#endif + pthread_mutexattr_t mattr; + int type; + int status; + int i; + + /* Initialize the mutex attributes */ + + pthread_mutexattr_init(&mattr); + status = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); + if (status != 0) + { + printf("recursive_mutex_test: ERROR pthread_mutexattr_settype failed, status=%d\n", status); + } + + status = pthread_mutexattr_gettype(&mattr, &type); + if (status != 0) + { + printf("recursive_mutex_test: ERROR pthread_mutexattr_gettype failed, status=%d\n", status); + } + if (type != PTHREAD_MUTEX_RECURSIVE) + { + printf("recursive_mutex_test: ERROR pthread_mutexattr_gettype return type=%d\n", type); + } + + /* Initialize the mutex */ + + printf("recursive_mutex_test: Initializing mutex\n"); + pthread_mutex_init(&mut, &mattr); + + /* Start the threads -- all at the same, default priority */ + + for (i = 0; i < NTHREADS; i++) + { + printf("recursive_mutex_test: Starting thread %d\n", i+1); +#ifdef SDCC + (void)pthread_attr_init(&attr); + status = pthread_create(&thread[i], &attr, thread_outer, (pthread_addr_t)i+1); +#else + status = pthread_create(&thread[i], NULL, thread_outer, (pthread_addr_t)i+1); +#endif + if (status != 0) + { + printf("recursive_mutex_test: ERRROR thread#%d creation: %d\n", i+1, status); + } + } + + /* Wait for all; of the threads to complete */ + + for (i = 0; i < NTHREADS; i++) + { + printf("recursive_mutex_test: Waiting for thread %d\n", i+1); +#ifdef SDCC + pthread_join(thread[i], &result1); +#else + pthread_join(thread[i], NULL); +#endif + } + + printf("recursive_mutex_test: Complete\n"); +} diff --git a/apps/examples/ostest/roundrobin.c b/apps/examples/ostest/roundrobin.c new file mode 100644 index 0000000000..061d51f3da --- /dev/null +++ b/apps/examples/ostest/roundrobin.c @@ -0,0 +1,232 @@ +/******************************************************************************** + * examples/ostest/roundrobin.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include +#include +#include "ostest.h" + +#if CONFIG_RR_INTERVAL > 0 + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/* This number may need to be tuned for different processor speeds. Since these + * arrays must be large to very correct SCHED_RR behavior, this test may require + * too much memory on many targets. + */ + +/* #define CONFIG_NINTEGERS 32768 Takes forever on 60Mhz ARM7 */ + +#define CONFIG_NINTEGERS 2048 + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +static int prime1[CONFIG_NINTEGERS]; +static int prime2[CONFIG_NINTEGERS]; + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: dosieve + * + * Description + * This implements a "sieve of aristophanes" algorithm for finding prime number. + * Credit for this belongs to someone, but I am not sure who anymore. Anyway, + * the only purpose here is that we need some algorithm that takes a long period + * of time to execute. + * + ********************************************************************************/ + +static void dosieve(int *prime) +{ + int a,d; + int i; + int j; + + a = 2; + d = a; + + for (i = 0; i < CONFIG_NINTEGERS; i++) + { + prime[i] = i+2; + } + + for (i = 1; i < 10; i++) + { + for (j = 0; j < CONFIG_NINTEGERS; j++) + { + d = a + d; + if (d < CONFIG_NINTEGERS) + { + prime[d]=0; + } + } + a++; + d = a; + i++; + } + +#if 0 /* We don't really care what the numbers are */ + for (i = 0, j= 0; i < CONFIG_NINTEGERS; i++) + { + if (prime[i] != 0) + { + printf(" Prime %d: %d\n", j, prime[i]); + j++; + } + } +#endif +} + +/******************************************************************************** + * Name: sieve1 + ********************************************************************************/ + +static void *sieve1(void *parameter) +{ + int i; + + printf("sieve1 started\n"); + + for (i = 0; i < 1000; i++) + { + dosieve(prime1); + } + + printf("sieve1 finished\n"); + + pthread_exit(NULL); + return NULL; /* To keep some compilers happy */ +} + +/******************************************************************************** + * Name: sieve2 + ********************************************************************************/ + +static void *sieve2(void *parameter) +{ + int i; + + printf("sieve2 started\n"); + + for (i = 0; i < 1000; i++) + { + dosieve(prime2); + } + + printf("sieve2 finished\n"); + + pthread_exit(NULL); + return NULL; /* To keep some compilers happy */ +} + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: rr_test + ********************************************************************************/ + +void rr_test(void) +{ + pthread_t sieve1_thread; + pthread_t sieve2_thread; + struct sched_param sparam; + pthread_attr_t attr; + pthread_addr_t result; + int status; + + printf("rr_test: Starting sieve1 thread \n"); + status = pthread_attr_init(&attr); + if (status != OK) + { + printf("rr_test: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = sched_get_priority_min(SCHED_FIFO); + status = pthread_attr_setschedparam(&attr, &sparam); + if (status != OK) + { + printf("rr_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("rr_test: Set thread priority to %d\n", sparam.sched_priority); + } + + status = pthread_attr_setschedpolicy(&attr, SCHED_RR); + if (status != OK) + { + printf("rr_test: pthread_attr_setschedpolicy failed, status=%d\n", status); + } + else + { + printf("rr_test: Set thread policty to SCHED_RR\n"); + } + + status = pthread_create(&sieve1_thread, &attr, sieve1, NULL); + if (status != 0) + { + printf("rr_test: Error in thread 1 creation, status=%d\n", status); + } + + printf("rr_test: Starting sieve1 thread \n"); + + status = pthread_create(&sieve2_thread, &attr, sieve2, NULL); + if (status != 0) + { + printf("rr_test: Error in thread 2 creation, status=%d\n", status); + } + + printf("rr_test: Waiting for sieves to complete -- this should take awhile\n"); + printf("rr_test: If RR scheduling is working, they should start and complete at\n"); + printf("rr_test: about the same time\n"); + + pthread_join(sieve2_thread, &result); + pthread_join(sieve1_thread, &result); + printf("rr_test: Done\n"); +} + +#endif /* CONFIG_RR_INTERVAL */ diff --git a/apps/examples/ostest/sem.c b/apps/examples/ostest/sem.c new file mode 100644 index 0000000000..850cf8040b --- /dev/null +++ b/apps/examples/ostest/sem.c @@ -0,0 +1,246 @@ +/*********************************************************************** + * sem.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ***********************************************************************/ + +#include +#include +#include +#include +#include "ostest.h" + +#ifndef NULL +# define NULL (void*)0 +#endif + +static sem_t sem; + +static void *waiter_func(void *parameter) +{ + int id = (int)parameter; + int status; + int value; + + printf("waiter_func: Thread %d Started\n", id); + + /* Take the semaphore */ + + status = sem_getvalue(&sem, &value); + if (status < 0) + { + printf("waiter_func: ERROR thread %d could not get semaphore value\n", id); + } + else + { + printf("waiter_func: Thread %d initial semaphore value = %d\n", id, value); + } + + printf("waiter_func: Thread %d waiting on semaphore\n", id); + status = sem_wait(&sem); + if (status != 0) + { + printf("waiter_func: ERROR thread %d sem_wait failed\n", id); + } + printf("waiter_func: Thread %d awakened\n", id); + + status = sem_getvalue(&sem, &value); + if (status < 0) + { + printf("waiter_func: ERROR thread %d could not get semaphore value\n", id); + } + else + { + printf("waiter_func: Thread %d new semaphore value = %d\n", id, value); + } + + printf("waiter_func: Thread %d done\n", id); + return NULL; +} + +static void *poster_func(void *parameter) +{ + int id = (int)parameter; + int status; + int value; + + printf("poster_func: Thread %d started\n", id); + + /* Take the semaphore */ + + do + { + status = sem_getvalue(&sem, &value); + if (status < 0) + { + printf("poster_func: ERROR thread %d could not get semaphore value\n", id); + } + else + { + printf("poster_func: Thread %d semaphore value = %d\n", id, value); + } + + if (value < 0) + { + printf("poster_func: Thread %d posting semaphore\n", id); + status = sem_post(&sem); + if (status != 0) + { + printf("poster_func: ERROR thread %d sem_wait failed\n", id); + } + + pthread_yield(); + + status = sem_getvalue(&sem, &value); + if (status < 0) + { + printf("poster_func: ERROR thread %d could not get semaphore value\n", id); + } + else + { + printf("poster_func: Thread %d new semaphore value = %d\n", id, value); + } + } + } + while (value < 0); + + printf("poster_func: Thread %d done\n", id); + return NULL; + +} + +void sem_test(void) +{ + pthread_t waiter_thread1; + pthread_t waiter_thread2; + pthread_t poster_thread; +#ifdef SDCC + pthread_addr_t result; +#endif + struct sched_param sparam; + int prio_min; + int prio_max; + int prio_mid; + pthread_attr_t attr; + int status; + + printf("sem_test: Initializing semaphore to 0\n"); + sem_init(&sem, 0, 0); + + /* Start two waiter thread instances */ + + printf("sem_test: Starting waiter thread 1\n"); + status = pthread_attr_init(&attr); + if (status != OK) + { + printf("sem_test: pthread_attr_init failed, status=%d\n", status); + } + + prio_min = sched_get_priority_min(SCHED_FIFO); + prio_max = sched_get_priority_max(SCHED_FIFO); + prio_mid = (prio_min + prio_max) / 2; + + sparam.sched_priority = (prio_mid + prio_max) / 2; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("sem_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("sem_test: Set thread 1 priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&waiter_thread1, &attr, waiter_func, (pthread_addr_t)1); + if (status != 0) + { + printf("sem_test: Error in thread 1 creation, status=%d\n", status); + } + + printf("sem_test: Starting waiter thread 2\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("sem_test: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = prio_mid; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("sem_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("sem_test: Set thread 2 priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&waiter_thread2, &attr, waiter_func, (pthread_addr_t)2); + if (status != 0) + { + printf("sem_test: Error in thread 2 creation, status=%d\n", status); + } + + printf("sem_test: Starting poster thread 3\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("sem_test: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = (prio_min + prio_mid) / 2; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("sem_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("sem_test: Set thread 3 priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&poster_thread, &attr, poster_func, (pthread_addr_t)3); + if (status != 0) + { + printf("sem_test: Error in thread 3 creation, status=%d\n", status); + } + +#ifdef SDCC + pthread_join(waiter_thread1, &result); + pthread_join(waiter_thread2, &result); + pthread_join(poster_thread, &result); +#else + pthread_join(waiter_thread1, NULL); + pthread_join(waiter_thread2, NULL); + pthread_join(poster_thread, NULL); +#endif +} diff --git a/apps/examples/ostest/sighand.c b/apps/examples/ostest/sighand.c new file mode 100644 index 0000000000..6815316395 --- /dev/null +++ b/apps/examples/ostest/sighand.c @@ -0,0 +1,267 @@ +/*********************************************************************** + * apps/examples/ostest/sighand.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ***********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ostest.h" + +#ifndef NULL +# define NULL (void*)0 +#endif + +#define WAKEUP_SIGNAL 17 +#define SIGVALUE_INT 42 + +static sem_t sem; +static bool sigreceived = false; +static bool threadexited = false; + +static void wakeup_action(int signo, siginfo_t *info, void *ucontext) +{ + sigset_t oldset; + sigset_t allsigs; + int status; + + printf("wakeup_action: Received signal %d\n" , signo); + + sigreceived = true; + + /* Check signo */ + + if (signo != WAKEUP_SIGNAL) + { + printf("wakeup_action: ERROR expected signo=%d\n" , WAKEUP_SIGNAL); + } + + /* Check siginfo */ + + if (info->si_value.sival_int != SIGVALUE_INT) + { + printf("wakeup_action: ERROR sival_int=%d expected %d\n", + info->si_value.sival_int, SIGVALUE_INT); + } + else + { + printf("wakeup_action: sival_int=%d\n" , info->si_value.sival_int); + } + + if (info->si_signo != WAKEUP_SIGNAL) + { + printf("wakeup_action: ERROR expected si_signo=%d, got=%d\n", + WAKEUP_SIGNAL, info->si_signo); + } + + printf("wakeup_action: si_code=%d\n" , info->si_code); + + /* Check ucontext_t */ + + printf("wakeup_action: ucontext=%p\n" , ucontext); + + /* Check sigprocmask */ + + (void)sigfillset(&allsigs); + status = sigprocmask(SIG_SETMASK, NULL, &oldset); + if (status != OK) + { + printf("wakeup_action: ERROR sigprocmask failed, status=%d\n", + status); + } + + if (oldset != allsigs) + { + printf("wakeup_action: ERROR sigprocmask=%x expected=%x\n", + oldset, allsigs); + } +} + +static int waiter_main(int argc, char *argv[]) +{ + sigset_t sigset; + struct sigaction act; + struct sigaction oact; + int status; + + printf("waiter_main: Waiter started\n" ); + + printf("waiter_main: Unmasking signal %d\n" , WAKEUP_SIGNAL); + (void)sigemptyset(&sigset); + (void)sigaddset(&sigset, WAKEUP_SIGNAL); + status = sigprocmask(SIG_UNBLOCK, &sigset, NULL); + if (status != OK) + { + printf("waiter_main: ERROR sigprocmask failed, status=%d\n", + status); + } + + printf("waiter_main: Registering signal handler\n" ); + act.sa_sigaction = wakeup_action; + act.sa_flags = SA_SIGINFO; + + (void)sigfillset(&act.sa_mask); + (void)sigdelset(&act.sa_mask, WAKEUP_SIGNAL); + + status = sigaction(WAKEUP_SIGNAL, &act, &oact); + if (status != OK) + { + printf("waiter_main: ERROR sigaction failed, status=%d\n" , status); + } + +#ifndef SDCC + printf("waiter_main: oact.sigaction=%p oact.sa_flags=%x oact.sa_mask=%x\n", + oact.sa_sigaction, oact.sa_flags, oact.sa_mask); +#endif + + /* Take the semaphore */ + + printf("waiter_main: Waiting on semaphore\n" ); + FFLUSH(); + + status = sem_wait(&sem); + if (status != 0) + { + int error = errno; + if (error == EINTR) + { + printf("waiter_main: sem_wait() successfully interrupted by signal\n" ); + } + else + { + printf("waiter_main: ERROR sem_wait failed, errno=%d\n" , error); + } + } + else + { + printf("waiter_main: ERROR awakened with no error!\n" ); + } + + /* Detach the signal handler */ + + act.sa_sigaction = SIG_DFL; + status = sigaction(WAKEUP_SIGNAL, &act, &oact); + + printf("waiter_main: done\n" ); + FFLUSH(); + + threadexited = true; + return 0; +} + +void sighand_test(void) +{ + struct sched_param param; + union sigval sigvalue; + pid_t waiterpid; + int policy; + int status; + + printf("sighand_test: Initializing semaphore to 0\n" ); + sem_init(&sem, 0, 0); + + /* Start waiter thread */ + + printf("sighand_test: Starting waiter task\n" ); + status = sched_getparam (0, ¶m); + if (status != OK) + { + printf("sighand_test: ERROR sched_getparam() failed\n" ); + param.sched_priority = PTHREAD_DEFAULT_PRIORITY; + } + + policy = sched_getscheduler(0); + if (policy == ERROR) + { + printf("sighand_test: ERROR sched_getscheduler() failed\n" ); + policy = SCHED_FIFO; + } + + waiterpid = task_create("waiter", param.sched_priority, + PTHREAD_STACK_DEFAULT, waiter_main, NULL); + if (waiterpid == ERROR) + { + printf("sighand_test: ERROR failed to start waiter_main\n" ); + } + else + { + printf("sighand_test: Started waiter_main pid=%d\n", waiterpid); + } + + /* Wait a bit */ + + FFLUSH(); + sleep(2); + + /* Then signal the waiter thread. */ + + printf("sighand_test: Signaling pid=%d with signo=%d sigvalue=%d\n", + waiterpid, WAKEUP_SIGNAL, SIGVALUE_INT); + + sigvalue.sival_int = SIGVALUE_INT; +#ifdef CONFIG_CAN_PASS_STRUCTS + status = sigqueue(waiterpid, WAKEUP_SIGNAL, sigvalue); +#else + status = sigqueue(waiterpid, WAKEUP_SIGNAL, sigvalue.sival_ptr); +#endif + if (status != OK) + { + printf("sighand_test: ERROR sigqueue failed\n" ); + task_delete(waiterpid); + } + + /* Wait a bit */ + + FFLUSH(); + sleep(2); + + /* Then check the result */ + + if (!threadexited) + { + printf("sighand_test: ERROR waiter task did not exit\n" ); + } + + if (!sigreceived) + { + printf("sighand_test: ERROR signal handler did not run\n" ); + } + + printf("sighand_test: done\n" ); + FFLUSH(); +} diff --git a/apps/examples/ostest/timedmqueue.c b/apps/examples/ostest/timedmqueue.c new file mode 100644 index 0000000000..807d8537bf --- /dev/null +++ b/apps/examples/ostest/timedmqueue.c @@ -0,0 +1,387 @@ +/************************************************************************** + * apps/examples/ostest/mqueue.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************/ + +/************************************************************************** + * Included Files + **************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ostest.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ + +#define TEST_MESSAGE "This is a test and only a test" +#if defined(SDCC) || defined(__ZILOG__) + /* Cannot use strlen in array size */ + +# define TEST_MSGLEN (31) +#else + /* Message lenght is the size of the message plus the null terminator */ + +# define TEST_MSGLEN (strlen(TEST_MESSAGE)+1) +#endif + +#define TEST_SEND_NMSGS (10) +#define TEST_RECEIVE_NMSGS (10) + +/************************************************************************** + * Private Types + **************************************************************************/ + +/************************************************************************** + * Private Function Prototypes + **************************************************************************/ + +/************************************************************************** + * Global Variables + **************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/************************************************************************** + * Public Functions + **************************************************************************/ + +static void *sender_thread(void *arg) +{ + mqd_t mqfd; + char msg_buffer[TEST_MSGLEN]; + struct mq_attr attr; + int status = 0; + int nerrors = 0; + int i; + + printf("sender_thread: Starting\n"); + + /* Fill in attributes for message queue */ + + attr.mq_maxmsg = TEST_SEND_NMSGS-1; + attr.mq_msgsize = TEST_MSGLEN; + attr.mq_flags = 0; + + /* Set the flags for the open of the queue. + * Make it a blocking open on the queue, meaning it will block if + * this process tries to send to the queue and the queue is full. + * + * O_CREAT - the queue will get created if it does not already exist. + * O_WRONLY - we are only planning to write to the queue. + * + * Open the queue, and create it if the receiving process hasn't + * already created it. + */ + + mqfd = mq_open("testmq", O_WRONLY|O_CREAT, 0666, &attr); + if (mqfd < 0) + { + printf("sender_thread: ERROR mq_open failed\n"); + pthread_exit((pthread_addr_t)1); + } + + /* Fill in a test message buffer to send */ + + memcpy(msg_buffer, TEST_MESSAGE, TEST_MSGLEN); + + /* Perform the send TEST_SEND_NMSGS times */ + + for (i = 0; i < TEST_SEND_NMSGS; i++) + { + struct timespec ts; + status = clock_gettime(CLOCK_REALTIME, &ts); + if (status != 0) + { + printf("sender_thread: ERROR clock_gettime failed\n"); + } + ts.tv_sec += 5; + + /* The first TEST_SEND_NMSGS-1 send should succeed. The last + * one should fail with errno == ETIMEDOUT + */ + + status = mq_timedsend(mqfd, msg_buffer, TEST_MSGLEN, 42, &ts); + if (status < 0) + { + if (i == TEST_SEND_NMSGS-1 && errno == ETIMEDOUT) + { + printf("sender_thread: mq_timedsend %d timed out as expected\n", i); + } + else + { + printf("sender_thread: ERROR mq_timedsend failure=%d on msg %d\n", errno, i); + nerrors++; + } + } + else + { + if (i == TEST_SEND_NMSGS-1) + { + printf("sender_thread: ERROR mq_timedsend of msg %d succeeded\n", i); + nerrors++; + } + else + { + printf("sender_thread: mq_timedsend succeeded on msg %d\n", i); + } + } + } + + /* Close the queue and return success */ + + if (mq_close(mqfd) < 0) + { + printf("sender_thread: ERROR mq_close failed\n"); + } + + printf("sender_thread: returning nerrors=%d\n", nerrors); + FFLUSH(); + return (pthread_addr_t)nerrors; +} + +static void *receiver_thread(void *arg) +{ + mqd_t mqfd; + char msg_buffer[TEST_MSGLEN]; + struct mq_attr attr; + int nbytes; + int nerrors = 0; + int i; + + printf("receiver_thread: Starting\n"); + + /* Fill in attributes for message queue */ + + attr.mq_maxmsg = TEST_SEND_NMSGS-1; + attr.mq_msgsize = TEST_MSGLEN; + attr.mq_flags = 0; + + /* Set the flags for the open of the queue. + * Make it a blocking open on the queue, meaning it will block if + * this process tries to* send to the queue and the queue is full. + * + * O_CREAT - the queue will get created if it does not already exist. + * O_RDONLY - we are only planning to write to the queue. + * + * Open the queue, and create it if the sending process hasn't + * already created it. + */ + + mqfd = mq_open("testmq", O_RDONLY|O_CREAT, 0666, &attr); + if (mqfd < 0) + { + printf("receiver_thread: ERROR mq_open failed\n"); + pthread_exit((pthread_addr_t)1); + } + + /* Perform the receive TEST_RECEIVE_NMSGS times */ + + for (i = 0; i < TEST_RECEIVE_NMSGS; i++) + { + struct timespec ts; + int status = clock_gettime(CLOCK_REALTIME, &ts); + if (status != 0) + { + printf("sender_thread: ERROR clock_gettime failed\n"); + } + ts.tv_sec += 5; + + /* The first TEST_SEND_NMSGS-1 send should succeed. The last + * one should fail with errno == ETIMEDOUT + */ + + memset(msg_buffer, 0xaa, TEST_MSGLEN); + nbytes = mq_timedreceive(mqfd, msg_buffer, TEST_MSGLEN, 0, &ts); + if (nbytes < 0) + { + if (i == TEST_SEND_NMSGS-1 && errno == ETIMEDOUT) + { + printf("receiver_thread: Receive %d timed out as expected\n", i); + } + else + { + printf("receiver_thread: ERROR mq_timedreceive failure=%d on msg %d\n", errno, i); + nerrors++; + } + } + else if (nbytes != TEST_MSGLEN) + { + printf("receiver_thread: mq_timedreceive return bad size %d on msg %d\n", nbytes, i); + nerrors++; + } + else if (memcmp(TEST_MESSAGE, msg_buffer, nbytes) != 0) + { + int j; + + printf("receiver_thread: mq_timedreceive returned corrupt message on msg %d\n", i); + printf("receiver_thread: i Expected Received\n"); + + for (j = 0; j < TEST_MSGLEN-1; j++) + { + if (isprint(msg_buffer[j])) + { + printf("receiver_thread: %2d %02x (%c) %02x (%c)\n", + j, TEST_MESSAGE[j], TEST_MESSAGE[j], msg_buffer[j], msg_buffer[j]); + } + else + { + printf("receiver_thread: %2d %02x (%c) %02x\n", + j, TEST_MESSAGE[j], TEST_MESSAGE[j], msg_buffer[j]); + } + } + printf("receiver_thread: %2d 00 %02x\n", + j, msg_buffer[j]); + } + else if (i == TEST_SEND_NMSGS-1) + { + printf("receiver_thread: ERROR mq_timedreceive of msg %d succeeded\n", i); + nerrors++; + } + else + { + printf("receiver_thread: mq_timedreceive succeeded on msg %d\n", i); + } + } + + /* Close the queue and return success */ + + if (mq_close(mqfd) < 0) + { + printf("receiver_thread: ERROR mq_close failed\n"); + nerrors++; + } + + /* Destroy the queue */ + + if (mq_unlink("testmq") < 0) + { + printf("receiver_thread: ERROR mq_close failed\n"); + nerrors++; + } + + printf("receiver_thread: returning nerrors=%d\n", nerrors); + FFLUSH(); + pthread_exit((pthread_addr_t)nerrors); + return (pthread_addr_t)nerrors; +} + +void timedmqueue_test(void) +{ + pthread_t sender; + pthread_t receiver; + void *result; + pthread_attr_t attr; + int status; + + /* Start the sending thread at the default priority */ + + printf("timedmqueue_test: Starting sender\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("timedmqueue_test: pthread_attr_init failed, status=%d\n", status); + } + + status = pthread_attr_setstacksize(&attr, STACKSIZE); + if (status != 0) + { + printf("timedmqueue_test: pthread_attr_setstacksize failed, status=%d\n", status); + } + + status = pthread_create(&sender, &attr, sender_thread, NULL); + if (status != 0) + { + printf("timedmqueue_test: pthread_create failed, status=%d\n", status); + } + + /* Wait for the sending thread to complete */ + + printf("timedmqueue_test: Waiting for sender to complete\n"); + pthread_join(sender, &result); + if (result != (void*)0) + { + printf("timedmqueue_test: ERROR sender thread exited with %d errors\n", (int)result); + } + + /* Start the receiving thread at the default priority */ + + printf("timedmqueue_test: Starting receiver\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("timedmqueue_test: pthread_attr_init failed, status=%d\n", status); + } + + status = pthread_attr_setstacksize(&attr, STACKSIZE); + if (status != 0) + { + printf("timedmqueue_test: pthread_attr_setstacksize failed, status=%d\n", status); + } + + status = pthread_create(&receiver, &attr, receiver_thread, NULL); + if (status != 0) + { + printf("timedmqueue_test: pthread_create failed, status=%d\n", status); + } + + /* Wait for the receiving thread to complete */ + + printf("timedmqueue_test: Waiting for receiver to complete\n"); + pthread_join(receiver, &result); + if (result != (void*)0) + { + printf("timedmqueue_test: ERROR receiver thread exited with %d errors\n", (int)result); + } + + printf("timedmqueue_test: Test complete\n"); +} + + diff --git a/apps/examples/ostest/timedwait.c b/apps/examples/ostest/timedwait.c new file mode 100644 index 0000000000..fc381ddda4 --- /dev/null +++ b/apps/examples/ostest/timedwait.c @@ -0,0 +1,195 @@ +/*********************************************************************** + * examples/ostest/timedwait.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ***********************************************************************/ + +/************************************************************************** + * Included Files + **************************************************************************/ + +#include +#include +#include +#include +#include + +#include "ostest.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ + +/************************************************************************** + * Private Data + **************************************************************************/ + +static pthread_mutex_t mutex; +static pthread_cond_t cond; + +/************************************************************************** + * Private Functions + **************************************************************************/ + +static void *thread_waiter(void *parameter) +{ + struct timespec ts; + int status; + + /* Take the mutex */ + + printf("thread_waiter: Taking mutex\n"); + status = pthread_mutex_lock(&mutex); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_mutex_lock failed, status=%d\n", status); + } + + printf("thread_waiter: Starting 5 second wait for condition\n"); + + status = clock_gettime(CLOCK_REALTIME, &ts); + if (status != 0) + { + printf("thread_waiter: ERROR clock_gettime failed\n"); + } + ts.tv_sec += 5; + + /* The wait -- no-one is ever going to awaken us */ + + status = pthread_cond_timedwait(&cond, &mutex, &ts); + if (status != 0) + { + if (status == ETIMEDOUT) + { + printf("thread_waiter: pthread_cond_timedwait timed out\n"); + } + else + { + printf("thread_waiter: ERROR pthread_cond_timedwait failed, status=%d\n", status); + } + } + else + { + printf("thread_waiter: ERROR pthread_cond_timedwait returned without timeout, status=%d\n", status); + } + + /* Release the mutex */ + + printf("thread_waiter: Releasing mutex\n"); + status = pthread_mutex_unlock(&mutex); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_mutex_unlock failed, status=%d\n", status); + } + + printf("thread_waiter: Exit with status 0x12345678\n"); + pthread_exit((pthread_addr_t)0x12345678); + return NULL; +} + +/************************************************************************** + * Public Definitions + **************************************************************************/ + +void timedwait_test(void) +{ + pthread_t waiter; + pthread_attr_t attr; + struct sched_param sparam; + void *result; + int prio_max; + int status; + + /* Initialize the mutex */ + + printf("thread_waiter: Initializing mutex\n"); + status = pthread_mutex_init(&mutex, NULL); + if (status != 0) + { + printf("timedwait_test: ERROR pthread_mutex_init failed, status=%d\n", status); + } + + /* Initialize the condition variable */ + + printf("timedwait_test: Initializing cond\n"); + status = pthread_cond_init(&cond, NULL); + if (status != 0) + { + printf("timedwait_test: ERROR pthread_condinit failed, status=%d\n", status); + } + + /* Start the waiter thread at higher priority */ + + printf("timedwait_test: Starting waiter\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("timedwait_test: pthread_attr_init failed, status=%d\n", status); + } + + prio_max = sched_get_priority_max(SCHED_FIFO); + status = sched_getparam (getpid(), &sparam); + if (status != 0) + { + printf("timedwait_test: sched_getparam failed\n"); + sparam.sched_priority = PTHREAD_DEFAULT_PRIORITY; + } + + sparam.sched_priority = (prio_max + sparam.sched_priority) / 2; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("timedwait_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("timedwait_test: Set thread 2 priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&waiter, &attr, thread_waiter, NULL); + if (status != 0) + { + printf("timedwait_test: pthread_create failed, status=%d\n", status); + } + + printf("timedwait_test: Joining\n"); + FFLUSH(); + status = pthread_join(waiter, &result); + if (status != 0) + { + printf("timedwait_test: ERROR pthread_join failed, status=%d\n", status); + } + else + { + printf("timedwait_test: waiter exited with result=%p\n", result); + } +} diff --git a/apps/examples/pipe/Kconfig b/apps/examples/pipe/Kconfig new file mode 100644 index 0000000000..26bc92fcc2 --- /dev/null +++ b/apps/examples/pipe/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_PIPE + bool "Pipe example" + default n + ---help--- + Enable the pipe example + +if EXAMPLES_PIPE +endif diff --git a/apps/examples/pipe/Makefile b/apps/examples/pipe/Makefile new file mode 100644 index 0000000000..3bcc9b5f78 --- /dev/null +++ b/apps/examples/pipe/Makefile @@ -0,0 +1,93 @@ +############################################################################ +# apps/examples/pipe/Makefile +# +# Copyright (C) 2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# Pipe Example + +ASRCS = +CSRCS = pipe_main.c transfer_test.c interlock_test.c redirect_test.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +context: + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/pipe/interlock_test.c b/apps/examples/pipe/interlock_test.c new file mode 100644 index 0000000000..e049a65f60 --- /dev/null +++ b/apps/examples/pipe/interlock_test.c @@ -0,0 +1,224 @@ +/**************************************************************************** + * examples/pipe/interlock_test.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +#include +#include +#include +#include + +#include "pipe.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: null_writer + ****************************************************************************/ + +static void *null_writer(pthread_addr_t pvarg) +{ + int fd; + + /* Wait a bit */ + + printf("null_writer: started -- sleeping\n"); + sleep(5); + + /* Then open the FIFO for write access */ + + printf("null_writer: Opening FIFO for write access\n"); + fd = open(FIFO_PATH2, O_WRONLY); + if (fd < 0) + { + fprintf(stderr, "null_writer: Failed to open FIFO %s for writing, errno=%d\n", + FIFO_PATH2, errno); + return (void*)1; + } + + /* Wait a bit more */ + + printf("null_writer: Opened %s for writing -- sleeping\n", FIFO_PATH2); + sleep(5); + + /* Then close the FIFO */ + + printf("null_writer: Closing %s\n", FIFO_PATH2); + if (close(fd) != 0) + { + fprintf(stderr, "null_writer: close failed: %d\n", errno); + } + sleep(5); + + printf("null_writer: Returning success\n"); + return (void*)0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: interlock_test + ****************************************************************************/ + +int interlock_test(void) +{ + pthread_t writerid; + void *value; + char data[16]; + ssize_t nbytes; + int fd; + int ret; + + /* Create a FIFO */ + + ret = mkfifo(FIFO_PATH2, 0666); + if (ret < 0) + { + fprintf(stderr, "interlock_test: mkfifo failed with errno=%d\n", errno); + return 1; + } + + /* Start the null_writer_thread */ + + printf("interlock_test: Starting null_writer thread\n"); + ret = pthread_create(&writerid, NULL, null_writer, (pthread_addr_t)NULL); + if (ret != 0) + { + fprintf(stderr, "interlock_test: Failed to create null_writer thread, error=%d\n", ret); + ret = 2; + goto errout_with_fifo; + } + + /* Open one end of the FIFO for reading. This open call should block until the + * null_writer thread opens the other end of the FIFO for writing. + */ + + printf("interlock_test: Opening FIFO for read access\n"); + fd = open(FIFO_PATH2, O_RDONLY); + if (fd < 0) + { + fprintf(stderr, "interlock_test: Failed to open FIFO %s for reading, errno=%d\n", + FIFO_PATH2, errno); + ret = 3; + goto errout_with_thread; + } + + /* Attempt to read one byte from the FIFO. This should return end-of-file because + * the null_writer closes the FIFO without writing anything. + */ + + printf("interlock_test: Reading from %s\n", FIFO_PATH2); + nbytes = read(fd, data, 16); + if (nbytes < 0 ) + { + fprintf(stderr, "interlock_test: read failed, errno=%d\n", errno); + ret = 4; + goto errout_with_file; + } + else if (ret != 0) + { + fprintf(stderr, "interlock_test: Read %d bytes of data -- aborting: %d\n", nbytes); + ret = 5; + goto errout_with_file; + } + + /* Close the file */ + + printf("interlock_test: Closing %s\n", FIFO_PATH2); + if (close(fd) != 0) + { + fprintf(stderr, "interlock_test: close failed: %d\n", errno); + } + + /* Wait for null_writer thread to complete */ + + printf("interlock_test: Waiting for null_writer thread\n"); + ret = pthread_join(writerid, &value); + if (ret != 0) + { + fprintf(stderr, "interlock_test: pthread_join failed, error=%d\n", ret); + ret = 6; + goto errout_with_fifo; + } + else + { + printf("interlock_test: writer returned %d\n", (int)value); + if (value != (void*)0) + { + ret = 7; + goto errout_with_fifo; + } + } + + /* unlink(FIFO_PATH2); */ + printf("interlock_test: Returning success\n"); + return 0; + +errout_with_file: + if (close(fd) != 0) + { + fprintf(stderr, "interlock_test: close failed: %d\n", errno); + } +errout_with_thread: + pthread_detach(writerid); + pthread_cancel(writerid); +errout_with_fifo: + /* unlink(FIFO_PATH2); */ + printf("interlock_test: Returning %d\n", ret); + return ret; +} diff --git a/apps/examples/pipe/pipe.h b/apps/examples/pipe/pipe.h new file mode 100644 index 0000000000..2c18fd868b --- /dev/null +++ b/apps/examples/pipe/pipe.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * examples/pipe/pipe.h + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __EXAMPLES_PIPE_PIPE_H +#define __EXAMPLES_PIPE_PIPE_H + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define FIFO_PATH1 "/tmp/testfifo-1" +#define FIFO_PATH2 "/tmp/testfifo-2" + +#ifndef CONFIG_EXAMPLES_PIPE_STACKSIZE +# define CONFIG_EXAMPLES_PIPE_STACKSIZE 1024 +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +extern int transfer_test(int fdin, int fdout); +extern int interlock_test(void); +extern int redirection_test(void); + +#endif /* __EXAMPLES_PIPE_PIPE_H */ diff --git a/apps/examples/pipe/pipe_main.c b/apps/examples/pipe/pipe_main.c new file mode 100644 index 0000000000..1f0f73032a --- /dev/null +++ b/apps/examples/pipe/pipe_main.c @@ -0,0 +1,189 @@ +/**************************************************************************** + * examples/pipe/pipe_main.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "pipe.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + int filedes[2]; + int ret; + + /* Test FIFO logic */ + + printf("\nuser_start: Performing FIFO test\n"); + ret = mkfifo(FIFO_PATH1, 0666); + if (ret < 0) + { + fprintf(stderr, "user_start: mkfifo failed with errno=%d\n", errno); + return 1; + } + + /* Open one end of the FIFO for reading and the other end for writing. NOTE: + * the following might not work on most FIFO implementations because the attempt + * to open just one end of the FIFO for writing might block. The NuttX FIFOs block + * only on open for read-only (see interlock_test()). + */ + + filedes[1] = open(FIFO_PATH1, O_WRONLY); + if (filedes[1] < 0) + { + fprintf(stderr, "user_start: Failed to open FIFO %s for writing, errno=%d\n", + FIFO_PATH1, errno); + return 2; + } + + filedes[0] = open(FIFO_PATH1, O_RDONLY); + if (filedes[0] < 0) + { + fprintf(stderr, "user_start: Failed to open FIFO %s for reading, errno=%d\n", + FIFO_PATH1, errno); + if (close(filedes[1]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + return 3; + } + + /* Then perform the test using those file descriptors */ + + ret = transfer_test(filedes[0], filedes[1]); + if (close(filedes[0]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + if (close(filedes[1]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + /* unlink(FIFO_PATH1); fails */ + + if (ret != 0) + { + fprintf(stderr, "user_start: FIFO test FAILED (%d)\n", ret); + return 4; + } + printf("user_start: FIFO test PASSED\n"); + + /* Test PIPE logic */ + + printf("\nuser_start: Performing pipe test\n"); + ret = pipe(filedes); + if (ret < 0) + { + fprintf(stderr, "user_start: pipe failed with errno=%d\n", errno); + return 5; + } + + /* Then perform the test using those file descriptors */ + + ret = transfer_test(filedes[0], filedes[1]); + if (close(filedes[0]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + if (close(filedes[1]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + + if (ret != 0) + { + fprintf(stderr, "user_start: PIPE test FAILED (%d)\n", ret); + return 6; + } + printf("user_start: PIPE test PASSED\n"); + + /* Perform the FIFO interlock test */ + + printf("\nuser_start: Performing pipe interlock test\n"); + ret = interlock_test(); + if (ret != 0) + { + fprintf(stderr, "user_start: FIFO interlock test FAILED (%d)\n", ret); + return 7; + } + printf("user_start: PIPE interlock test PASSED\n"); + + /* Perform the pipe redirection test */ + + printf("\nuser_start: Performing redirection test\n"); + ret = redirection_test(); + if (ret != 0) + { + fprintf(stderr, "user_start: FIFO redirection test FAILED (%d)\n", ret); + return 7; + } + printf("user_start: PIPE redirection test PASSED\n"); + + fflush(stdout); + return 0; +} diff --git a/apps/examples/pipe/redirect_test.c b/apps/examples/pipe/redirect_test.c new file mode 100644 index 0000000000..45e86c3560 --- /dev/null +++ b/apps/examples/pipe/redirect_test.c @@ -0,0 +1,326 @@ +/**************************************************************************** + * examples/pipe/redirect_test.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "pipe.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define READ_SIZE 37 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static sem_t g_rddone; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: redirect_reader + ****************************************************************************/ + +static int redirect_reader(int argc, char *argv[]) +{ + char buffer[READ_SIZE]; + int fdin; + int fdout; + int ret; + int nbytes = 0; + + printf("redirect_reader: started with fdin=%s\n", argv[1]); + + /* Convert the fdin to binary */ + + fdin = atoi(argv[1]); + fdout = atoi(argv[2]); + + /* Close fdout -- we don't need it */ + + ret = close(fdout); + if (ret != 0) + { + fprintf(stderr, "redirect_reader: failed to close fdout=%d\n", fdout); + return 1; + } + + /* Re-direct the fdin to stdin */ + + ret = dup2(fdin, 0); + if (ret != 0) + { + fprintf(stderr, "redirect_reader: dup2 failed: %d\n", errno); + close(fdin); + return 2; + } + + /* Close the original file descriptor */ + + ret = close(fdin); + if (ret != 0) + { + fprintf(stderr, "redirect_reader: failed to close fdin=%d\n", fdin); + return 3; + } + + /* Then read from stdin until we hit the end of file */ + + fflush(stdout); + for (;;) + { + /* Read from stdin */ + + ret = read(0, buffer, READ_SIZE); + if (ret < 0 ) + { + fprintf(stderr, "redirect_reader: read failed, errno=%d\n", errno); + return 4; + } + else if (ret == 0) + { + break; + } + nbytes += ret; + + /* Echo to stdout */ + + ret = write(1, buffer, ret); + if (ret < 0) + { + fprintf(stderr, "redirect_reader: read failed, errno=%d\n", errno); + return 5; + } + } + + printf("redirect_reader: %d bytes read\n", nbytes); + ret = close(0); + if (ret != 0) + { + fprintf(stderr, "redirect_reader: failed to close fd=0\n"); + return 6; + } + + sem_post(&g_rddone); + printf("redirect_reader: Returning success\n"); + return 0; +} + +/**************************************************************************** + * Name: redirect_writer + ****************************************************************************/ + +static int redirect_writer(int argc, char *argv[]) +{ + int fdin; + int fdout; + int nbytes = 0; + int ret; + + fprintf(stderr, "redirect_writer: started with fdout=%s\n", argv[2]); + + /* Convert the fdout to binary */ + + fdin = atoi(argv[1]); + fdout = atoi(argv[2]); + + /* Close fdin -- we don't need it */ + + ret = close(fdin); + if (ret != 0) + { + fprintf(stderr, "redirect_reader: failed to close fdin=%d\n", fdin); + return 1; + } + + /* Re-direct the fdout to stdout */ + + ret = dup2(fdout, 1); + if (ret != 0) + { + fprintf(stderr, "redirect_writer: dup2 failed: %d\n", errno); + return 2; + } + + /* Close the original file descriptor */ + + ret = close(fdout); + if (ret != 0) + { + fprintf(stderr, "redirect_reader: failed to close fdout=%d\n", fdout); + return 3; + } + + /* Then write a bunch of stuff to stdout */ + + fflush(stderr); + nbytes += printf("\nFour score and seven years ago our fathers brought forth on this continent a new nation,\n"); + nbytes += printf("conceived in Liberty, and dedicated to the proposition that all men are created equal.\n"); + nbytes += printf("\nNow we are engaged in a great civil war, testing whether that nation, or any nation, so\n"); + nbytes += printf("conceived and so dedicated, can long endure. We are met on a great battle-field of that war.\n"); + nbytes += printf("We have come to dedicate a portion of that field, as a final resting place for those who here\n"); + nbytes += printf("gave their lives that that nation might live. It is altogether fitting and proper that we\n"); + nbytes += printf("should do this.\n"); + nbytes += printf("\nBut, in a larger sense, we can not dedicate - we can not consecrate - we can not hallow - this ground.\n"); + nbytes += printf("The brave men, living and dead, who struggled here, have consecrated it, far above our poor power\n"); + nbytes += printf("to add or detract. The world will little note, nor long remember what we say here, but it can\n"); + nbytes += printf("never forget what they did here. It is for us the living, rather, to be dedicated here to the\n"); + nbytes += printf("unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to\n"); + nbytes += printf("be here dedicated to the great task remaining before us - that from these honored dead we take\n"); + nbytes += printf("increased devotion to that cause for which they gave the last full measure of devotion - that we\n"); + nbytes += printf("here highly resolve that these dead shall not have died in vain - that this nation, under God,\n"); + nbytes += printf("shall have a new birth of freedom - and that government of the people, by the people, for the\n"); + nbytes += printf("people, shall not perish from the earth.\n\n"); + fflush(stdout); + + fprintf(stderr, "redirect_writer: %d bytes written\n", nbytes); + + ret = close(1); + if (ret != 0) + { + fprintf(stderr, "redirect_writer: failed to close fd=1\n"); + return 4; + } + + fprintf(stderr, "redirect_writer: Returning success\n"); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: redirection_test + ****************************************************************************/ + +int redirection_test(void) +{ + const char *argv[3]; + char buffer1[8]; + char buffer2[8]; + int readerid; + int writerid; + int filedes[2]; + int ret; + + sem_init(&g_rddone, 0, 0); + + /* Create the pipe */ + + ret = pipe(filedes); + if (ret < 0) + { + fprintf(stderr, "redirection_test: pipe failed with errno=%d\n", errno); + return 5; + } + + sprintf(buffer1, "%d", filedes[0]); + argv[0] = buffer1; + sprintf(buffer2, "%d", filedes[1]); + argv[1] = buffer2; + argv[2] = NULL; + + /* Start redirect_reader thread */ + + printf("redirection_test: Starting redirect_reader task with fd=%d\n", filedes[0]); + readerid = task_create("redirect_reader", 50, CONFIG_EXAMPLES_PIPE_STACKSIZE, redirect_reader, argv); + if (readerid < 0) + { + fprintf(stderr, "redirection_test: Failed to create redirect_writer task: %d\n", errno); + return 1; + } + + /* Start redirect_writer task */ + + printf("redirection_test: Starting redirect_writer task with fd=%d\n", filedes[1]); + writerid = task_create("redirect_writer", 50, CONFIG_EXAMPLES_PIPE_STACKSIZE, redirect_writer, argv); + if (writerid < 0) + { + fprintf(stderr, "redirection_test: Failed to create redirect_writer task: %d\n", errno); + ret = task_delete(readerid); + if (ret != 0) + { + fprintf(stderr, "redirection_test: Failed to delete redirect_reader task %d\n", errno); + } + return 2; + } + + /* We should be able to close the pipe file descriptors now. */ + + if (close(filedes[0]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + if (close(filedes[1]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + + if (ret != 0) + { + fprintf(stderr, "user_start: PIPE test FAILED (%d)\n", ret); + return 6; + } + + /* Wait for redirect_writer thread to complete */ + + printf("redirection_test: Waiting...\n"); + fflush(stdout); + sem_wait(&g_rddone); + + printf("redirection_test: returning %d\n", ret); + return ret; +} + diff --git a/apps/examples/pipe/transfer_test.c b/apps/examples/pipe/transfer_test.c new file mode 100644 index 0000000000..cb8cad04a4 --- /dev/null +++ b/apps/examples/pipe/transfer_test.c @@ -0,0 +1,242 @@ +/**************************************************************************** + * examples/pipe/transfer_test.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "pipe.h" + +/**************************************************************************** + * Pre-proecessor Definitions + ****************************************************************************/ + +#define MAX_BYTE 13 + +#define WRITE_SIZE MAX_BYTE +#define NWRITES 1400 +#define NWRITE_BYTES (NWRITES * WRITE_SIZE) + +#define READ_SIZE (2*MAX_BYTE) +#define NREADS (NWRITES / 2) +#define NREAD_BYTES NWRITE_BYTES + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: transfer_reader + ****************************************************************************/ + +static void *transfer_reader(pthread_addr_t pvarg) +{ + char buffer[READ_SIZE]; + int fd = (int)pvarg; + int ret; + int nbytes; + int value; + int ndx; + + printf("transfer_reader: started\n"); + for (nbytes = 0, value = 0; nbytes < NREAD_BYTES;) + { + ret = read(fd, buffer, READ_SIZE); + if (ret < 0 ) + { + fprintf(stderr, "transfer_reader: read failed, errno=%d\n", errno); + return (void*)1; + } + else if (ret == 0) + { + if (nbytes < NREAD_BYTES) + { + fprintf(stderr, "transfer_reader: Too few bytes read -- aborting: %d\n", nbytes); + return (void*)2; + } + break; + } + for (ndx = 0; ndx < ret; ndx++) + { + if (value >= WRITE_SIZE) + { + value = 0; + } + if (buffer[ndx] != value) + { + fprintf(stderr, "transfer_reader: Byte %d, expected %d, found %d\n", + nbytes + ndx, value, buffer[ndx]); + return (void*)3; + } + value++; + } + nbytes += ret; + if (nbytes > NREAD_BYTES) + { + fprintf(stderr, "transfer_reader: Too many bytes read -- aborting: %d\n", nbytes); + return (void*)4; + } + } + printf("transfer_reader: %d bytes read\n", nbytes); + return (void*)0; +} + +/**************************************************************************** + * Name: transfer_writer + ****************************************************************************/ + +static void *transfer_writer(pthread_addr_t pvarg) +{ + char buffer[WRITE_SIZE]; + int fd = (int)pvarg; + int ret; + int i; + + printf("transfer_writer: started\n"); + for (i = 0; i < WRITE_SIZE; i++) + { + buffer[i] = i; + } + + for (i = 0; i < NWRITES; i++) + { + ret = write(fd, buffer, WRITE_SIZE); + if (ret < 0 ) + { + fprintf(stderr, "transfer_writer: write failed, errno=%d\n", errno); + return (void*)1; + } + else if (ret != WRITE_SIZE) + { + fprintf(stderr, "transfer_writer: Unexpected write size=%d\n", ret); + return (void*)2; + } + } + printf("transfer_writer: %d bytes written\n", NWRITE_BYTES); + return (void*)0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: transfer_test + ****************************************************************************/ + +int transfer_test(int fdin, int fdout) +{ + pthread_t readerid; + pthread_t writerid; + void *value; + int tmp; + int ret; + + /* Start transfer_reader thread */ + + printf("transfer_test: Starting transfer_reader thread\n"); + ret = pthread_create(&readerid, NULL, transfer_reader, (pthread_addr_t)fdin); + if (ret != 0) + { + fprintf(stderr, "transfer_test: Failed to create transfer_reader thread, error=%d\n", ret); + return 1; + } + + /* Start transfer_writer thread */ + + printf("transfer_test: Starting transfer_writer thread\n"); + ret = pthread_create(&writerid, NULL, transfer_writer, (pthread_addr_t)fdout); + if (ret != 0) + { + fprintf(stderr, "transfer_test: Failed to create transfer_writer thread, error=%d\n", ret); + pthread_detach(readerid); + ret = pthread_cancel(readerid); + if (ret != 0) + { + fprintf(stderr, "transfer_test: Failed to cancel transfer_reader thread, error=%d\n", ret); + } + return 2; + } + + /* Wait for transfer_writer thread to complete */ + + printf("transfer_test: Waiting for transfer_writer thread\n"); + ret = pthread_join(writerid, &value); + if (ret != 0) + { + fprintf(stderr, "transfer_test: pthread_join failed, error=%d\n", ret); + } + else + { + ret = (int)value; + printf("transfer_test: transfer_writer returned %d\n", ret); + } + + /* Wait for transfer_reader thread to complete */ + + printf("transfer_test: Waiting for transfer_reader thread\n"); + tmp = pthread_join(readerid, &value); + if (tmp != 0) + { + fprintf(stderr, "transfer_test: pthread_join failed, error=%d\n", ret); + } + else + { + tmp = (int)value; + printf("transfer_test: transfer_reader returned %d\n", tmp); + } + + if (ret == 0) + { + ret = tmp; + } + printf("transfer_test: returning %d\n", ret); + return ret; +} + diff --git a/apps/examples/poll/Kconfig b/apps/examples/poll/Kconfig new file mode 100644 index 0000000000..c528274968 --- /dev/null +++ b/apps/examples/poll/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_POLL + bool "Poll example" + default n + ---help--- + Enable the poll example + +if EXAMPLES_POLL +endif diff --git a/apps/examples/poll/Makefile b/apps/examples/poll/Makefile new file mode 100644 index 0000000000..1c85d6f36d --- /dev/null +++ b/apps/examples/poll/Makefile @@ -0,0 +1,94 @@ +############################################################################ +# apps/examples/poll/Makefile +# +# Copyright (C) 2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# Device Driver poll()/select() Example + +ASRCS = +CSRCS = poll_main.c poll_listener.c select_listener.c net_listener.c net_reader.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +context: + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +# Register application +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend host + +-include Make.dep diff --git a/apps/examples/poll/Makefile.host b/apps/examples/poll/Makefile.host new file mode 100644 index 0000000000..9d9daee27b --- /dev/null +++ b/apps/examples/poll/Makefile.host @@ -0,0 +1,54 @@ +############################################################################ +# apps/examples/poll/Makefile.host +# +# Copyright (C) 2008, 2009, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# TOPDIR must be defined on the make command line + +include $(TOPDIR)/.config +include $(TOPDIR)/Make.defs + +SRC = host.c +BIN = host + +DEFINES = -DTARGETIP=\"$(TARGETIP)\" + +all: $(BIN) + +$(BIN): $(SRC) + $(HOSTCC) $(HOSTCFLAGS) $(DEFINES) $^ -o $@ + +clean: + @rm -f $(BIN) *~ .*.swp *.o + $(call CLEAN) + diff --git a/apps/examples/poll/host.c b/apps/examples/poll/host.c new file mode 100644 index 0000000000..302cceb0f4 --- /dev/null +++ b/apps/examples/poll/host.c @@ -0,0 +1,171 @@ +/**************************************************************************** + * examples/poll/host.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define pthread_addr_t void * +#include "poll_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef TARGETIP +# error TARGETIP not defined +#endif + +#define IOBUFFER_SIZE 80 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * main + ****************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + struct sockaddr_in myaddr; + char outbuf[IOBUFFER_SIZE]; + char inbuf[IOBUFFER_SIZE]; + int sockfd; + int len; + int nbytessent; + int nbytesrecvd; + int i; + + /* Create a new TCP socket */ + + sockfd = socket(PF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + { + message("client socket failure %d\n", errno); + goto errout_with_outbufs; + } + + /* Connect the socket to the server */ + + myaddr.sin_family = AF_INET; + myaddr.sin_port = htons(LISTENER_PORT); + myaddr.sin_addr.s_addr = inet_addr(TARGETIP); + + message("client: Connecting to %s...\n", TARGETIP); + if (connect( sockfd, (struct sockaddr*)&myaddr, sizeof(struct sockaddr_in)) < 0) + { + message("client: connect failure: %d\n", errno); + goto errout_with_socket; + } + message("client: Connected\n"); + + /* Then send and receive messages */ + + for (i = 0; ; i++) + { + sprintf(outbuf, "Remote message %d", i); + len = strlen(outbuf); + + message("client: Sending '%s' (%d bytes)\n", outbuf, len); + nbytessent = send(sockfd, outbuf, len, 0); + message("client: Sent %d bytes\n", nbytessent); + + if (nbytessent < 0) + { + message("client: send failed: %d\n", errno); + goto errout_with_socket; + } + else if (nbytessent != len) + { + message("client: Bad send length: %d Expected: %d\n", nbytessent, len); + goto errout_with_socket; + } + + message("client: Receiving...\n"); + nbytesrecvd = recv(sockfd, inbuf, IOBUFFER_SIZE, 0); + + if (nbytesrecvd < 0) + { + message("client: recv failed: %d\n", errno); + goto errout_with_socket; + } + else if (nbytesrecvd == 0) + { + message("client: The server broke the connections\n"); + goto errout_with_socket; + } + + inbuf[nbytesrecvd] = '\0'; + message("client: Received '%s' (%d bytes)\n", inbuf, nbytesrecvd); + + if (nbytesrecvd != len) + { + message("client: Bad recv length: %d Expected: %d\n", nbytesrecvd, len); + goto errout_with_socket; + } + else if (memcmp(inbuf, outbuf, len) != 0) + { + message("client: Received outbuf does not match sent outbuf\n"); + goto errout_with_socket; + } + + message("client: Sleeping\n"); + sleep(8); + } + + close(sockfd); + return 0; + +errout_with_socket: + close(sockfd); +errout_with_outbufs: + exit(1); +} diff --git a/apps/examples/poll/net_listener.c b/apps/examples/poll/net_listener.c new file mode 100644 index 0000000000..81ad7cdcca --- /dev/null +++ b/apps/examples/poll/net_listener.c @@ -0,0 +1,428 @@ +/**************************************************************************** + * examples/poll/net_listener.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define IOBUFFER_SIZE 80 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct net_listener_s +{ + struct sockaddr_in addr; + fd_set master; + fd_set working; + char buffer[IOBUFFER_SIZE]; + int listensd; + int mxsd; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_closeclient + ****************************************************************************/ + +static bool net_closeclient(struct net_listener_s *nls, int sd) +{ + message("net_listener: Closing host side connection sd=%d\n", sd); + close(sd); + FD_CLR(sd, &nls->master); + + /* If we just closed the max SD, then search downward for the next biggest SD. */ + + while (FD_ISSET(nls->mxsd, &nls->master) == false) + { + nls->mxsd -= 1; + } + return true; +} + +/**************************************************************************** + * Name: net_incomingdata + ****************************************************************************/ + +static inline bool net_incomingdata(struct net_listener_s *nls, int sd) +{ + char *ptr; + int nbytes; + int ret; + + /* Read data from the socket */ + +#ifdef FIONBIO + for (;;) +#endif + { + message("net_listener: Read data from sd=%d\n", sd); + ret = recv(sd, nls->buffer, IOBUFFER_SIZE, 0); + if (ret < 0) + { + if (errno != EINTR) + { + message("net_listener: recv failed sd=%d: %d\n", sd, errno); + if (errno != EAGAIN) + { + net_closeclient(nls, sd); + return false; + } + } + } + else if (ret == 0) + { + message("net_listener: Client connection lost sd=%d\n", sd); + net_closeclient(nls, sd); + return false; + } + else + { + nls->buffer[ret]='\0'; + message("poll_listener: Read '%s' (%d bytes)\n", nls->buffer, ret); + + /* Echo the data back to the client */ + + for (nbytes = ret, ptr = nls->buffer; nbytes > 0; ) + { + ret = send(sd, ptr, nbytes, 0); + if (ret < 0) + { + if (errno != EINTR) + { + message("net_listener: Send failed sd=%d: \n", sd, errno); + net_closeclient(nls, sd); + return false; + } + } + else + { + nbytes -= ret; + ptr += ret; + } + } + } + } + return 0; +} + +/**************************************************************************** + * Name: net_connection + ****************************************************************************/ + +static inline bool net_connection(struct net_listener_s *nls) +{ + int sd; + + /* Loop until all connections have been processed */ + +#ifdef FIONBIO + for (;;) +#endif + { + message("net_listener: Accepting new connection on sd=%d\n", nls->listensd); + + sd = accept(nls->listensd, NULL, NULL); + if (sd < 0) + { + message("net_listener: accept failed: %d\n", errno); + + if (errno != EINTR) + { + return false; + } + } + else + { + /* Add the new connection to the master set */ + + message("net_listener: Connection accepted for sd=%d\n", sd); + + FD_SET(sd, &nls->master); + if (sd > nls->mxsd) + { + nls->mxsd = sd; + } + return true; + } + } + return false; +} + +/**************************************************************************** + * Name: net_mksocket + ****************************************************************************/ + +static inline bool net_mksocket(struct net_listener_s *nls) +{ + int value; + int ret; + + /* Create a listening socket */ + + message("net_listener: Initializing listener socket\n"); + nls->listensd = socket(AF_INET, SOCK_STREAM, 0); + if (nls->listensd < 0) + { + message("net_listener: socket failed: %d\n", errno); + return false; + } + + /* Configure the socket */ + + value = 1; + ret = setsockopt(nls->listensd, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(int)); + if (ret < 0) + { + message("net_listener: setsockopt failed: %d\n", errno); + close(nls->listensd); + return false; + } + + /* Set the socket to non-blocking */ + +#ifdef FIONBIO + ret = ioctl(nls->listensd, FIONBIO, (char *)&value); + if (ret < 0) + { + message("net_listener: ioctl failed: %d\n", errno); + close(nls->listensd); + return false; + } +#endif + + /* Bind the socket */ + + memset(&nls->addr, 0, sizeof(struct sockaddr_in)); + nls->addr.sin_family = AF_INET; + nls->addr.sin_addr.s_addr = htonl(INADDR_ANY); + nls->addr.sin_port = htons(LISTENER_PORT); + ret = bind(nls->listensd, (struct sockaddr *)&nls->addr, sizeof(struct sockaddr_in)); + if (ret < 0) + { + message("net_listener: bind failed: %d\n", errno); + close(nls->listensd); + return false; + } + + /* Mark the socket as a listener */ + + ret = listen(nls->listensd, 32); + if (ret < 0) + { + message("net_listener: bind failed: %d\n", errno); + close(nls->listensd); + return false; + } + + return true; +} + +/**************************************************************************** + * Name: net_configure + ****************************************************************************/ + +static void net_configure(void) +{ + struct in_addr addr; +#if defined(CONFIG_EXAMPLE_POLL_NOMAC) + uint8_t mac[IFHWADDRLEN]; +#endif + + /* Configure uIP */ + /* Many embedded network interfaces must have a software assigned MAC */ + +#ifdef CONFIG_EXAMPLE_POLL_NOMAC + mac[0] = 0x00; + mac[1] = 0xe0; + mac[2] = 0xde; + mac[3] = 0xad; + mac[4] = 0xbe; + mac[5] = 0xef; + uip_setmacaddr("eth0", mac); +#endif + + /* Set up our host address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_IPADDR); + uip_sethostaddr("eth0", &addr); + + /* Set up the default router address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_DRIPADDR); + uip_setdraddr("eth0", &addr); + + /* Setup the subnet mask */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_NETMASK); + uip_setnetmask("eth0", &addr); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_listener + ****************************************************************************/ + +void *net_listener(pthread_addr_t pvarg) +{ + struct net_listener_s nls; + struct timeval timeout; + int nsds; + int ret; + int i; + + /* Configure uIP */ + + net_configure(); + + /* Set up a listening socket */ + + memset(&nls, 0, sizeof(struct net_listener_s)); + if (!net_mksocket(&nls)) + { + return (void*)1; + } + + /* Initialize the 'master' file descriptor set */ + + FD_ZERO(&nls.master); + nls.mxsd = nls.listensd; + FD_SET(nls.listensd, &nls.master); + + /* Set up a 3 second timeout */ + + timeout.tv_sec = NET_LISTENER_DELAY; + timeout.tv_usec = 0; + + /* Loop waiting for incoming connections or for incoming data + * on any of the connect sockets. + */ + + for (;;) + { + /* Wait on select */ + + message("net_listener: Calling select(), listener sd=%d\n", nls.listensd); + memcpy(&nls.working, &nls.master, sizeof(fd_set)); + ret = select(nls.mxsd + 1, (FAR fd_set*)&nls.working, (FAR fd_set*)NULL, (FAR fd_set*)NULL, &timeout); + if (ret < 0) + { + message("net_listener: select failed: %d\n", errno); + break; + } + + /* Check for timeout */ + + if (ret == 0) + { + message("net_listener: Timeout\n"); + continue; + } + + /* Find which descriptors caused the wakeup */ + + nsds = ret; + for (i = 0; i <= nls.mxsd && nsds > 0; i++) + { + /* Is this descriptor ready? */ + + if (FD_ISSET(i, &nls.working)) + { + /* Yes, is it our listener? */ + + message("net_listener: Activity on sd=%d\n", i); + + nsds--; + if (i == nls.listensd) + { + (void)net_connection(&nls); + } + else + { + net_incomingdata(&nls, i); + } + } + } + } + + /* Cleanup */ + +#if 0 /* Don't get here */ + for (i = 0; i <= nls.mxsd; +i++) + { + if (FD_ISSET(i, &nls.master)) + { + close(i); + } + } +#endif + return NULL; /* Keeps some compilers from complaining */ +} diff --git a/apps/examples/poll/net_reader.c b/apps/examples/poll/net_reader.c new file mode 100644 index 0000000000..8a13618c37 --- /dev/null +++ b/apps/examples/poll/net_reader.c @@ -0,0 +1,317 @@ +/**************************************************************************** + * examples/poll/net_reader.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define IOBUFFER_SIZE 80 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_configure + ****************************************************************************/ + +static void net_configure(void) +{ + struct in_addr addr; +#if defined(CONFIG_EXAMPLE_POLL_NOMAC) + uint8_t mac[IFHWADDRLEN]; +#endif + + /* Configure uIP */ + /* Many embedded network interfaces must have a software assigned MAC */ + +#ifdef CONFIG_EXAMPLE_POLL_NOMAC + mac[0] = 0x00; + mac[1] = 0xe0; + mac[2] = 0xde; + mac[3] = 0xad; + mac[4] = 0xbe; + mac[5] = 0xef; + uip_setmacaddr("eth0", mac); +#endif + + /* Set up our host address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_IPADDR); + uip_sethostaddr("eth0", &addr); + + /* Set up the default router address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_DRIPADDR); + uip_setdraddr("eth0", &addr); + + /* Setup the subnet mask */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_NETMASK); + uip_setnetmask("eth0", &addr); +} + +/**************************************************************************** + * Name: net_receive + ****************************************************************************/ + +static void net_receive(int sd) +{ + struct timeval timeout; + char buffer[IOBUFFER_SIZE]; + char *ptr; + fd_set readset; + int nbytes; + int ret; + + /* Set up the timeout */ + + timeout.tv_sec = NET_LISTENER_DELAY; + timeout.tv_usec = 0; + + /* Loop while we have the connection */ + + for (;;) + { + /* Wait for incoming message */ + + do + { + FD_ZERO(&readset); + FD_SET(sd, &readset); + ret = select(sd + 1, (FAR fd_set*)&readset, (FAR fd_set*)NULL, (FAR fd_set*)NULL, &timeout); + } + while (ret < 0 && errno == EINTR); + + /* Something has happened */ + + if (ret < 0) + { + message("net_reader: select failed: %d\n", errno); + return; + } + else if (ret == 0) + { + message("net_reader: Timeout\n"); + } + else + { + message("net_reader: Read data from sd=%d\n", sd); + memset(buffer, '?', IOBUFFER_SIZE); /* Just to make sure we really receive something */ + ret = recv(sd, buffer, IOBUFFER_SIZE, 0); + if (ret < 0) + { + if (errno != EINTR) + { + message("net_reader: recv failed sd=%d: %d\n", sd, errno); + if (errno != EAGAIN) + { + return; + } + } + } + else if (ret == 0) + { + message("net_reader: Client connection lost sd=%d\n", sd); + return; + } + else + { + buffer[ret]='\0'; + message("net_reader: Read '%s' (%d bytes)\n", buffer, ret); + + /* Echo the data back to the client */ + + for (nbytes = ret, ptr = buffer; nbytes > 0; ) + { + ret = send(sd, ptr, nbytes, 0); + if (ret < 0) + { + if (errno != EINTR) + { + message("net_reader: Send failed sd=%d: %d\n", sd, errno); + return; + } + } + else + { + nbytes -= ret; + ptr += ret; + } + } + } + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_reader + ****************************************************************************/ + +void *net_reader(pthread_addr_t pvarg) +{ + struct sockaddr_in addr; +#ifdef POLL_HAVE_SOLINGER + struct linger ling; +#endif + int listensd; + int acceptsd; + socklen_t addrlen; + int optval; + + /* Configure uIP */ + + net_configure(); + + /* Create a new TCP socket */ + + listensd = socket(PF_INET, SOCK_STREAM, 0); + if (listensd < 0) + { + message("net_reader: socket failure: %d\n", errno); + goto errout; + } + + /* Set socket to reuse address */ + + optval = 1; + if (setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0) + { + message("net_reader: setsockopt SO_REUSEADDR failure: %d\n", errno); + goto errout_with_listensd; + } + + /* Bind the socket to a local address */ + + addr.sin_family = AF_INET; + addr.sin_port = HTONS(LISTENER_PORT); + addr.sin_addr.s_addr = INADDR_ANY; + + if (bind(listensd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0) + { + message("net_reader: bind failure: %d\n", errno); + goto errout_with_listensd; + } + + /* Listen for connections on the bound TCP socket */ + + if (listen(listensd, 5) < 0) + { + message("net_reader: listen failure %d\n", errno); + goto errout_with_listensd; + } + + /* Connection loop */ + + for (;;) + { + /* Accept only one connection */ + + message("net_reader: Accepting new connections on port %d\n", LISTENER_PORT); + addrlen = sizeof(struct sockaddr_in); + acceptsd = accept(listensd, (struct sockaddr*)&addr, &addrlen); + if (acceptsd < 0) + { + message("net_reader: accept failure: %d\n", errno); + continue; + } + message("net_reader: Connection accepted on sd=%d\n", acceptsd); + + /* Configure to "linger" until all data is sent when the socket is closed */ + +#ifdef POLL_HAVE_SOLINGER + ling.l_onoff = 1; + ling.l_linger = 30; /* timeout is seconds */ + if (setsockopt(acceptsd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger)) < 0) + { + message("net_reader: setsockopt SO_LINGER failure: %d\n", errno); + goto errout_with_acceptsd; + } +#endif + + /* Handle incoming messsages on the connection. */ + + net_receive(acceptsd); + + message("net_reader: Closing sd=%d\n", acceptsd); + close(acceptsd); + } + +#ifdef POLL_HAVE_SOLINGER +errout_with_acceptsd: + close(acceptsd); +#endif +errout_with_listensd: + close(listensd); +errout: + return NULL; +} diff --git a/apps/examples/poll/poll_internal.h b/apps/examples/poll/poll_internal.h new file mode 100644 index 0000000000..cbf42ac566 --- /dev/null +++ b/apps/examples/poll/poll_internal.h @@ -0,0 +1,128 @@ +/**************************************************************************** + * examples/poll/poll_internal.h + * + * Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __EXAMPLES_PIPE_PIPE_H +#define __EXAMPLES_PIPE_PIPE_H + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#ifdef CONFIG_DISABLE_POLL +# error "The polling API is disabled" +#endif + +/* Here are all of the configuration settings that must be met to have TCP/IP + * poll/select support. This kind of looks like overkill. + * + * CONFIG_NET - Network support must be enabled + * CONFIG_NSOCKET_DESCRIPTORS - Socket descriptors must be allocated + * CONFIG_NET_TCP - Only support on TCP (because read-ahead + * ibuffering s not yet support for UDP) + * CONFIG_NET_NTCP_READAHEAD_BUFFERS - TCP/IP read-ahead buffering must be enabled + */ + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 && \ + defined(CONFIG_NET_TCP) && CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 +# define HAVE_NETPOLL 1 +#else +# undef HAVE_NETPOLL +#endif + +/* If debug is enabled, then use lib_rawprintf so that OS debug output and + * the test output are synchronized. + * + * These macros will differ depending upon if the toolchain supports + * macros with a variable number of arguments or not. + */ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_DEBUG +# define message(...) lib_rawprintf(__VA_ARGS__) +# define msgflush() +# else +# define message(...) printf(__VA_ARGS__) +# define msgflush() fflush(stdout) +# endif +#else +# ifdef CONFIG_DEBUG +# define message lib_rawprintf +# define msgflush() +# else +# define message printf +# define msgflush() fflush(stdout) +# endif +#endif + +#define FIFO_PATH1 "/dev/fifo0" +#define FIFO_PATH2 "/dev/fifo1" + +#define POLL_LISTENER_DELAY 2000 /* 2 seconds */ +#define SELECT_LISTENER_DELAY 4 /* 4 seconds */ +#define NET_LISTENER_DELAY 3 /* 3 seconds */ +#define WRITER_DELAY 6 /* 6 seconds */ + +#define LISTENER_PORT 5471 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +extern void *poll_listener(pthread_addr_t pvarg); +extern void *select_listener(pthread_addr_t pvarg); + +#ifdef HAVE_NETPOLL +extern void *net_listener(pthread_addr_t pvarg); +extern void *net_reader(pthread_addr_t pvarg); +#endif +#endif /* __EXAMPLES_PIPE_PIPE_H */ diff --git a/apps/examples/poll/poll_listener.c b/apps/examples/poll/poll_listener.c new file mode 100644 index 0000000000..816647e340 --- /dev/null +++ b/apps/examples/poll/poll_listener.c @@ -0,0 +1,262 @@ +/**************************************************************************** + * examples/poll/poll_listener.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#if defined(CONFIG_DEV_CONSOLE) && !defined(CONFIG_DEV_LOWCONSOLE) +# define HAVE_CONSOLE +# define NPOLLFDS 2 +# define CONSNDX 0 +# define FIFONDX 1 +#else +# undef HAVE_CONSOLE +# define NPOLLFDS 1 +# define FIFONDX 0 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: poll_listener + ****************************************************************************/ + +void *poll_listener(pthread_addr_t pvarg) +{ + struct pollfd fds[NPOLLFDS]; + char buffer[64]; + ssize_t nbytes; + bool timeout; + bool pollin; + int nevents; + int fd; + int ret; + int i; + + /* Open the FIFO for non-blocking read */ + + message("poll_listener: Opening %s for non-blocking read\n", FIFO_PATH1); + fd = open(FIFO_PATH1, O_RDONLY|O_NONBLOCK); + if (fd < 0) + { + message("poll_listener: ERROR Failed to open FIFO %s: %d\n", + FIFO_PATH1, errno); + (void)close(fd); + return (void*)-1; + } + + /* Loop forever */ + + for (;;) + { + message("poll_listener: Calling poll()\n"); + + memset(fds, 0, sizeof(struct pollfd)*NPOLLFDS); +#ifdef HAVE_CONSOLE + fds[CONSNDX].fd = 0; + fds[CONSNDX].events = POLLIN; + fds[CONSNDX].revents = 0; +#endif + fds[FIFONDX].fd = fd; + fds[FIFONDX].events = POLLIN; + fds[FIFONDX].revents = 0; + + timeout = false; + pollin = false; + + ret = poll(fds, NPOLLFDS, POLL_LISTENER_DELAY); + + message("\npoll_listener: poll returned: %d\n", ret); + if (ret < 0) + { + message("poll_listener: ERROR poll failed: %d\n", errno); + } + else if (ret == 0) + { + message("poll_listener: Timeout\n"); + timeout = true; + } + else if (ret > NPOLLFDS) + { + message("poll_listener: ERROR poll reported: %d\n"); + } + else + { + pollin = true; + } + + nevents = 0; + for (i = 0; i < NPOLLFDS; i++) + { + message("poll_listener: FIFO revents[%d]=%02x\n", i, fds[i].revents); + if (timeout) + { + if (fds[i].revents != 0) + { + message("poll_listener: ERROR? expected revents=00, received revents[%d]=%02x\n", + fds[i].revents, i); + } + } + else if (pollin) + { + if (fds[i].revents == POLLIN) + { + nevents++; + } + else if (fds[i].revents != 0) + { + message("poll_listener: ERROR unexpected revents[i]=%02x\n", + i, fds[i].revents); + } + } + } + + if (pollin && nevents != ret) + { + message("poll_listener: ERROR found %d events, poll reported %d\n", nevents, ret); + } + + /* In any event, read until the pipe/serial is empty */ + + for (i = 0; i < NPOLLFDS; i++) + { + do + { +#ifdef HAVE_CONSOLE + /* Hack to work around the fact that the console driver on the + * simulator is always non-blocking. + */ + + if (i == CONSNDX) + { + if ((fds[CONSNDX].revents & POLLIN) != 0) + { + buffer[0] = getchar(); + nbytes = 1; + } + else + { + nbytes = 0; + } + } + else +#endif + { + /* The pipe works differently, it returns whatever data + * it has available without blocking. + */ + + nbytes = read(fds[i].fd, buffer, 63); + } + + if (nbytes <= 0) + { + if (nbytes == 0 || errno == EAGAIN) + { + if ((fds[i].revents & POLLIN) != 0) + { + message("poll_listener: ERROR no read data[%d]\n", i); + } + } + else if (errno != EINTR) + { + message("poll_listener: read[%d] failed: %d\n", i, errno); + } + nbytes = 0; + } + else + { + if (timeout) + { + message("poll_listener: ERROR? Poll timeout, but data read[%d]\n", i); + message(" (might just be a race condition)\n"); + } + + buffer[nbytes] = '\0'; + message("poll_listener: Read[%d] '%s' (%d bytes)\n", i, buffer, nbytes); + } + + /* Suppress error report if no read data on the next time through */ + + fds[i].revents = 0; + } + while (nbytes > 0); + } + + /* Make sure that everything is displayed */ + + msgflush(); + } + + /* Won't get here */ + + (void)close(fd); + return NULL; +} diff --git a/apps/examples/poll/poll_main.c b/apps/examples/poll/poll_main.c new file mode 100644 index 0000000000..3db0150e77 --- /dev/null +++ b/apps/examples/poll/poll_main.c @@ -0,0 +1,221 @@ +/**************************************************************************** + * examples/poll/poll_main.c + * + * Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + char buffer[64]; + ssize_t nbytes; + pthread_t tid1; + pthread_t tid2; +#ifdef HAVE_NETPOLL + pthread_t tid3; +#endif + int count; + int fd1 = -1; + int fd2 = -1; + int ret; + int exitcode = 0; + + /* Open FIFOs */ + + message("\nuser_start: Creating FIFO %s\n", FIFO_PATH1); + ret = mkfifo(FIFO_PATH1, 0666); + if (ret < 0) + { + message("user_start: mkfifo failed: %d\n", errno); + exitcode = 1; + goto errout; + } + + message("\nuser_start: Creating FIFO %s\n", FIFO_PATH2); + ret = mkfifo(FIFO_PATH2, 0666); + if (ret < 0) + { + message("user_start: mkfifo failed: %d\n", errno); + exitcode = 2; + goto errout; + } + + /* Open the FIFOs for blocking, write */ + + fd1 = open(FIFO_PATH1, O_WRONLY); + if (fd1 < 0) + { + message("user_start: Failed to open FIFO %s for writing, errno=%d\n", + FIFO_PATH1, errno); + exitcode = 3; + goto errout; + } + + fd2 = open(FIFO_PATH2, O_WRONLY); + if (fd2 < 0) + { + message("user_start: Failed to open FIFO %s for writing, errno=%d\n", + FIFO_PATH2, errno); + exitcode = 4; + goto errout; + } + + /* Start the listeners */ + + message("user_start: Starting poll_listener thread\n"); + + ret = pthread_create(&tid1, NULL, poll_listener, NULL); + if (ret != 0) + { + message("user_start: Failed to create poll_listener thread: %d\n", ret); + exitcode = 5; + goto errout; + } + + message("user_start: Starting select_listener thread\n"); + + ret = pthread_create(&tid2, NULL, select_listener, NULL); + if (ret != 0) + { + message("user_start: Failed to create select_listener thread: %d\n", ret); + exitcode = 6; + goto errout; + } + +#ifdef HAVE_NETPOLL +#ifdef CONFIG_NET_TCPBACKLOG + message("user_start: Starting net_listener thread\n"); + + ret = pthread_create(&tid3, NULL, net_listener, NULL); +#else + message("user_start: Starting net_reader thread\n"); + + ret = pthread_create(&tid3, NULL, net_reader, NULL); +#endif + if (ret != 0) + { + message("user_start: Failed to create net_listener thread: %d\n", ret); + } +#endif + + /* Loop forever */ + + for (count = 0; ; count++) + { + /* Send a message to the listener... this should wake the listener + * from the poll. + */ + + sprintf(buffer, "Message %d", count); + nbytes = write(fd1, buffer, strlen(buffer)); + if (nbytes < 0) + { + message("user_start: Write to fd1 failed: %d\n", errno); + exitcode = 7; + goto errout; + } + + nbytes = write(fd2, buffer, strlen(buffer)); + if (nbytes < 0) + { + message("user_start: Write fd2 failed: %d\n", errno); + exitcode = 8; + goto errout; + } + + message("\nuser_start: Sent '%s' (%d bytes)\n", buffer, nbytes); + msgflush(); + + /* Wait awhile. This delay should be long enough that the + * listener will timeout. + */ + + sleep(WRITER_DELAY); + } + +errout: + if (fd1 >= 0) + { + close(fd1); + } + + if (fd2 >= 0) + { + close(fd2); + } + + fflush(stdout); + return exitcode; +} diff --git a/apps/examples/poll/select_listener.c b/apps/examples/poll/select_listener.c new file mode 100644 index 0000000000..80039ada34 --- /dev/null +++ b/apps/examples/poll/select_listener.c @@ -0,0 +1,193 @@ +/**************************************************************************** + * examples/poll/select_listener.c + * + * Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: select_listener + ****************************************************************************/ + +void *select_listener(pthread_addr_t pvarg) +{ + fd_set rfds; + struct timeval tv; + char buffer[64]; + ssize_t nbytes; + bool timeout; + bool ready; + int fd; + int ret; + + /* Open the FIFO for non-blocking read */ + + message("select_listener: Opening %s for non-blocking read\n", FIFO_PATH2); + fd = open(FIFO_PATH2, O_RDONLY|O_NONBLOCK); + if (fd < 0) + { + message("select_listener: ERROR Failed to open FIFO %s: %d\n", + FIFO_PATH2, errno); + (void)close(fd); + return (void*)-1; + } + + /* Loop forever */ + + for (;;) + { + message("select_listener: Calling select()\n"); + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + tv.tv_sec = SELECT_LISTENER_DELAY; + tv.tv_usec = 0; + + timeout = false; + ready = false; + + ret = select(fd+1, (FAR fd_set*)&rfds, (FAR fd_set*)NULL, (FAR fd_set*)NULL, &tv); + message("\nselect_listener: select returned: %d\n", ret); + + if (ret < 0) + { + message("select_listener: ERROR select failed: %d\n"); + } + else if (ret == 0) + { + message("select_listener: Timeout\n"); + timeout = true; + } + else + { + if (ret != 1) + { + message("select_listener: ERROR poll reported: %d\n"); + } + else + { + ready = true; + } + + if (!FD_ISSET(fd, rfds)) + { + message("select_listener: ERROR fd=%d not in fd_set\n"); + } + } + + /* In any event, read until the pipe is empty */ + + do + { + nbytes = read(fd, buffer, 63); + if (nbytes <= 0) + { + if (nbytes == 0 || errno == EAGAIN) + { + if (ready) + { + message("select_listener: ERROR no read data\n"); + } + } + else if (errno != EINTR) + { + message("select_listener: read failed: %d\n", errno); + } + nbytes = 0; + } + else + { + if (timeout) + { + message("select_listener: ERROR? Poll timeout, but data read\n"); + message(" (might just be a race condition)\n"); + } + + buffer[nbytes] = '\0'; + message("select_listener: Read '%s' (%d bytes)\n", buffer, nbytes); + } + + timeout = false; + ready = false; + } + while (nbytes > 0); + + /* Make sure that everything is displayed */ + + msgflush(); + } + + /* Won't get here */ + + (void)close(fd); + return NULL; +} diff --git a/apps/examples/pwm/Kconfig b/apps/examples/pwm/Kconfig new file mode 100644 index 0000000000..78edd2178c --- /dev/null +++ b/apps/examples/pwm/Kconfig @@ -0,0 +1,48 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_PWM + bool "Pulse width modulation (PWM) example" + default n + depends on PWM && NSH_BUILTIN_APPS + ---help--- + Enable the Pulse width modulation (PWM) example + +if EXAMPLES_PWM + +config EXAMPLES_PWM_DEVPATH + string "PWM device path" + default "/dev/pwm0" + ---help--- + The path to the PWM device. Default: /dev/pwm0 + +config EXAMPLES_PWM_FREQUENCY + int "Default PWM freququency" + default 100 + ---help--- + The default PWM frequency. Default: 100 Hz + +config EXAMPLES_PWM_DUTYPCT + int "Default PWM duty percentage" + default 50 + ---help--- + The default PWM duty as a percentage. Default: 50% + +config EXAMPLES_PWM_DURATION + int "Default PWM duration" + default 5 if !EXAMPLES_PWM_PULSECOUNT + ---help--- + The default PWM pulse train duration in seconds. Used only if the current + pulse count is zero (pulse countis only supported if CONFIG_PWM_PULSECOUNT + is defined). Default: 5 seconds + +config EXAMPLES_PWM_PULSECOUNT + int "Default pulse count" + default 0 + ---help--- + The initial PWM pulse count. This option is only available if CONFIG_PWM_PULSECOUNT + is nonzero. Default: 0 (i.e., use the duration, not the count). + +endif diff --git a/apps/examples/pwm/Makefile b/apps/examples/pwm/Makefile new file mode 100644 index 0000000000..efbdb048e0 --- /dev/null +++ b/apps/examples/pwm/Makefile @@ -0,0 +1,103 @@ +############################################################################ +# apps/examples/pwm/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# PWM Example. + +ASRCS = +CSRCS = pwm_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# PWM built-in application info + +APPNAME = pwm +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Common build + +VPATH = + +all: .built +.PHONY: context clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/pwm/pwm.h b/apps/examples/pwm/pwm.h new file mode 100644 index 0000000000..5c049a8f8f --- /dev/null +++ b/apps/examples/pwm/pwm.h @@ -0,0 +1,134 @@ +/**************************************************************************** + * examples/examples/pwm/pwm.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_EXAMPLES_PWM_PWM_H +#define __APPS_EXAMPLES_PWM_PWM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_NSH_BUILTIN_APPS - Build the PWM test as an NSH built-in function. + * Default: Not built! The example can only be used as an NSH built-in + * application + * CONFIG_EXAMPLES_PWM_DEVPATH - The path to the PWM device. Default: /dev/pwm0 + * CONFIG_EXAMPLES_PWM_FREQUENCY - The initial PWM frequency. Default: 100 Hz + * CONFIG_EXAMPLES_PWM_DUTYPCT - The initial PWM duty as a percentage. Default: 50% + * CONFIG_EXAMPLES_PWM_DURATION - The initial PWM pulse train duration in seconds. + * Used only if the current pulse count is zero (pulse count is only supported + * if CONFIG_PWM_PULSECOUNT is defined). Default: 5 seconds + * CONFIG_EXAMPLES_PWM_PULSECOUNT - The initial PWM pulse count. This option is + * only available if CONFIG_PWM_PULSECOUNT is defined. Default: 0 (i.e., use + * the duration, not the count). + */ + +#ifndef CONFIG_PWM +# error "PWM device support is not enabled (CONFIG_PWM)" +#endif + +#ifndef CONFIG_NSH_BUILTIN_APPS +# warning "The PWM example only works as an NSH built-in application (CONFIG_NSH_BUILTIN_APPS)" +#endif + +#ifndef CONFIG_EXAMPLES_PWM_DEVPATH +# define CONFIG_EXAMPLES_PWM_DEVPATH "/dev/pwm0" +#endif + +#ifndef CONFIG_EXAMPLES_PWM_FREQUENCY +# define CONFIG_EXAMPLES_PWM_FREQUENCY 100 +#endif + +#ifndef CONFIG_EXAMPLES_PWM_DUTYPCT +# define CONFIG_EXAMPLES_PWM_DUTYPCT 50 +#endif + +#ifndef CONFIG_EXAMPLES_PWM_DURATION +# define CONFIG_EXAMPLES_PWM_DURATION 5 +#endif + +#ifndef CONFIG_EXAMPLES_PWM_COUNT +# define CONFIG_EXAMPLES_PWM_COUNT 0 +#endif + +/* Debug ********************************************************************/ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_DEBUG +# define message(...) lib_rawprintf(__VA_ARGS__) +# define msgflush() +# else +# define message(...) printf(__VA_ARGS__) +# define msgflush() fflush(stdout) +# endif +#else +# ifdef CONFIG_DEBUG +# define message lib_rawprintf +# define msgflush() +# else +# define message printf +# define msgflush() fflush(stdout) +# endif +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: pwm_devinit() + * + * Description: + * Perform architecuture-specific initialization of the PWM hardware. This + * interface must be provided by all configurations using apps/examples/pwm + * + ****************************************************************************/ + +int pwm_devinit(void); + +#endif /* __APPS_EXAMPLES_PWM_PWM_H */ diff --git a/apps/examples/pwm/pwm_main.c b/apps/examples/pwm/pwm_main.c new file mode 100644 index 0000000000..64c5dfb2c0 --- /dev/null +++ b/apps/examples/pwm/pwm_main.c @@ -0,0 +1,394 @@ +/**************************************************************************** + * examples/pwm/pwm_main.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "pwm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct pwm_state_s +{ + bool initialized; + FAR char *devpath; + uint8_t duty; + uint32_t freq; +#ifdef CONFIG_PWM_PULSECOUNT + uint32_t count; +#endif + int duration; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct pwm_state_s g_pwmstate; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pwm_devpath + ****************************************************************************/ + +static void pwm_devpath(FAR struct pwm_state_s *pwm, FAR const char *devpath) +{ + /* Get rid of any old device path */ + + if (pwm->devpath) + { + free(pwm->devpath); + } + + /* Then set-up the new device path by copying the string */ + + pwm->devpath = strdup(devpath); +} + +/**************************************************************************** + * Name: pwm_help + ****************************************************************************/ + +static void pwm_help(FAR struct pwm_state_s *pwm) +{ + message("Usage: pwm [OPTIONS]\n"); + message("\nArguments are \"sticky\". For example, once the PWM frequency is\n"); + message("specified, that frequency will be re-used until it is changed.\n"); + message("\n\"sticky\" OPTIONS include:\n"); + message(" [-p devpath] selects the PWM device. " + "Default: %s Current: %s\n", + CONFIG_EXAMPLES_PWM_DEVPATH, pwm->devpath ? pwm->devpath : "NONE"); + message(" [-f addr] selects the pulse frequency. " + "Default: %d Hz Current: %d Hz\n", + CONFIG_EXAMPLES_PWM_FREQUENCY, pwm->freq); + message(" [-d duty] selcts the pulse duty as a percentage. " + "Default: %d %% Current: %d %%\n", + CONFIG_EXAMPLES_PWM_DUTYPCT, pwm->duty); +#ifdef CONFIG_PWM_PULSECOUNT + message(" [-n count] selects the pulse count. " + "Default: %d Current: %d\n", + CONFIG_EXAMPLES_PWM_COUNT, pwm->count); +#endif + message(" [-t duration] is the duration of the pulse train in seconds. " + "Default: %d Current: %d\n", + CONFIG_EXAMPLES_PWM_DURATION, pwm->duration); + message(" [-h] shows this message and exits\n"); +} + +/**************************************************************************** + * Name: arg_string + ****************************************************************************/ + +static int arg_string(FAR char **arg, FAR char **value) +{ + FAR char *ptr = *arg; + + if (ptr[2] == '\0') + { + *value = arg[1]; + return 2; + } + else + { + *value = &ptr[2]; + return 1; + } +} + +/**************************************************************************** + * Name: arg_decimal + ****************************************************************************/ + +static int arg_decimal(FAR char **arg, FAR long *value) +{ + FAR char *string; + int ret; + + ret = arg_string(arg, &string); + *value = strtol(string, NULL, 10); + return ret; +} + +/**************************************************************************** + * Name: parse_args + ****************************************************************************/ + +static void parse_args(FAR struct pwm_state_s *pwm, int argc, FAR char **argv) +{ + FAR char *ptr; + FAR char *str; + long value; + int index; + int nargs; + + for (index = 1; index < argc; ) + { + ptr = argv[index]; + if (ptr[0] != '-') + { + message("Invalid options format: %s\n", ptr); + exit(0); + } + + switch (ptr[1]) + { + case 'f': + nargs = arg_decimal(&argv[index], &value); + if (value < 1) + { + message("Frequency out of range: %ld\n", value); + exit(1); + } + + pwm->freq = (uint32_t)value; + index += nargs; + break; + + case 'd': + nargs = arg_decimal(&argv[index], &value); + if (value < 1 || value > 99) + { + message("Duty out of range: %ld\n", value); + exit(1); + } + + pwm->duty = (uint8_t)value; + index += nargs; + break; + +#ifdef CONFIG_PWM_PULSECOUNT + case 'n': + nargs = arg_decimal(&argv[index], &value); + if (value < 0) + { + message("Count must be non-negative: %ld\n", value); + exit(1); + } + + pwm->count = (uint32_t)value; + index += nargs; + break; + +#endif + case 'p': + nargs = arg_string(&argv[index], &str); + pwm_devpath(pwm, str); + index += nargs; + break; + + case 't': + nargs = arg_decimal(&argv[index], &value); + if (value < 1 || value > INT_MAX) + { + message("Duration out of range: %ld\n", value); + exit(1); + } + + pwm->duration = (int)value; + index += nargs; + break; + + case 'h': + pwm_help(pwm); + exit(0); + + default: + message("Unsupported option: %s\n", ptr); + pwm_help(pwm); + exit(1); + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start/pwm_main + ****************************************************************************/ + +int pwm_main(int argc, char *argv[]) +{ + struct pwm_info_s info; + int fd; + int ret; + + /* Initialize the state data */ + + if (!g_pwmstate.initialized) + { + g_pwmstate.duty = CONFIG_EXAMPLES_PWM_DUTYPCT; + g_pwmstate.freq = CONFIG_EXAMPLES_PWM_FREQUENCY; + g_pwmstate.duration = CONFIG_EXAMPLES_PWM_DURATION; +#ifdef CONFIG_PWM_PULSECOUNT + g_pwmstate.count = CONFIG_EXAMPLES_PWM_COUNT; +#endif + g_pwmstate.initialized = true; + } + + /* Parse the command line */ + + parse_args(&g_pwmstate, argc, argv); + + /* Has a device been assigned? */ + + if (!g_pwmstate.devpath) + { + /* No.. use the default device */ + + pwm_devpath(&g_pwmstate, CONFIG_EXAMPLES_PWM_DEVPATH); + } + + /* Initialization of the PWM hardware is performed by logic external to + * this test. + */ + + ret = pwm_devinit(); + if (ret != OK) + { + message("pwm_main: pwm_devinit failed: %d\n", ret); + goto errout; + } + + /* Open the PWM device for reading */ + + fd = open(g_pwmstate.devpath, O_RDONLY); + if (fd < 0) + { + message("pwm_main: open %s failed: %d\n", g_pwmstate.devpath, errno); + goto errout; + } + + /* Configure the characteristics of the pulse train */ + + info.frequency = g_pwmstate.freq; + info.duty = ((uint32_t)g_pwmstate.duty << 16) / 100; +#ifdef CONFIG_PWM_PULSECOUNT + info.count = g_pwmstate.count; + + message("pwm_main: starting output with frequency: %d duty: %08x count: %d\n", + info.frequency, info.duty, info.count); + +#else + message("pwm_main: starting output with frequency: %d duty: %08x\n", + info.frequency, info.duty); + +#endif + + ret = ioctl(fd, PWMIOC_SETCHARACTERISTICS, (unsigned long)((uintptr_t)&info)); + if (ret < 0) + { + message("pwm_main: ioctl(PWMIOC_SETCHARACTERISTICS) failed: %d\n", errno); + goto errout_with_dev; + } + + /* Then start the pulse train. Since the driver was opened in blocking + * mode, this call will block if the count value is greater than zero. + */ + + ret = ioctl(fd, PWMIOC_START, 0); + if (ret < 0) + { + message("pwm_main: ioctl(PWMIOC_START) failed: %d\n", errno); + goto errout_with_dev; + } + + /* It a non-zero count was not specified, then wait for the selected + * duration, then stop the PWM output. + */ + +#ifdef CONFIG_PWM_PULSECOUNT + if (info.count == 0) +#endif + { + /* Wait for the specified duration */ + + sleep(g_pwmstate.duration); + + /* Then stop the pulse train */ + + message("pwm_main: stopping output\n", info.frequency, info.duty); + + ret = ioctl(fd, PWMIOC_STOP, 0); + if (ret < 0) + { + message("pwm_main: ioctl(PWMIOC_STOP) failed: %d\n", errno); + goto errout_with_dev; + } + } + + close(fd); + msgflush(); + return OK; + +errout_with_dev: + close(fd); +errout: + msgflush(); + return ERROR; +} diff --git a/apps/examples/qencoder/Kconfig b/apps/examples/qencoder/Kconfig new file mode 100644 index 0000000000..e0026d08c3 --- /dev/null +++ b/apps/examples/qencoder/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_QENCODER + bool "Quadrature encoder example" + default n + ---help--- + Enable the quadrature encoder example + +if EXAMPLES_QENCODER +endif diff --git a/apps/examples/qencoder/Makefile b/apps/examples/qencoder/Makefile new file mode 100644 index 0000000000..3f3fc9def8 --- /dev/null +++ b/apps/examples/qencoder/Makefile @@ -0,0 +1,105 @@ +############################################################################ +# apps/examples/qe/Makefile +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# NuttX NX Graphics Example. + +ASRCS = +CSRCS = qe_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Quadrature Encoder built-in application info + +APPNAME = qe +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Common build + +VPATH = + +all: .built +.PHONY: context clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: +ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ +endif + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/qencoder/qe.h b/apps/examples/qencoder/qe.h new file mode 100644 index 0000000000..4c03689ab6 --- /dev/null +++ b/apps/examples/qencoder/qe.h @@ -0,0 +1,134 @@ +/**************************************************************************** + * examples/examples/qe/qe.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_EXAMPLES_QENCODER_QE_H +#define __APPS_EXAMPLES_QENCODER_QE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_NSH_BUILTIN_APPS - Build the QE test as an NSH built-in function. + * Default: Built as a standalone problem + * CONFIG_EXAMPLES_QENCODER_DEVPATH - The path to the QE device. Default: + * /dev/qe0 + * CONFIG_EXAMPLES_QENCODER_NSAMPLES - If CONFIG_NSH_BUILTIN_APPS + * is defined, then the number of samples is provided on the command line + * and this value is ignored. Otherwise, this number of samples is + * collected and the program terminates. Default: Samples are collected + * indefinitely. + * CONFIG_EXAMPLES_QENCODER_DELAY - This value provides the delay (in + * milliseonds) between each sample. If CONFIG_NSH_BUILTIN_APPS + * is defined, then this value is the default delay if no other delay is + * provided on the command line. Default: 100 milliseconds + */ + +#ifndef CONFIG_QENCODER +# error "QE device support is not enabled (CONFIG_QENCODER)" +#endif + +#ifndef CONFIG_EXAMPLES_QENCODER_DEVPATH +# define CONFIG_EXAMPLES_QENCODER_DEVPATH "/dev/qe0" +#endif + +#ifndef CONFIG_EXAMPLES_QENCODER_DELAY +# define CONFIG_EXAMPLES_QENCODER_DELAY 100 +#endif + +/* Debug ********************************************************************/ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_DEBUG +# define message(...) lib_rawprintf(__VA_ARGS__) +# define msgflush() +# else +# define message(...) printf(__VA_ARGS__) +# define msgflush() fflush(stdout) +# endif +#else +# ifdef CONFIG_DEBUG +# define message lib_rawprintf +# define msgflush() +# else +# define message printf +# define msgflush() fflush(stdout) +# endif +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +struct qe_example_s +{ + bool initialized; /* True: QE devices have been initialized */ + bool reset; /* True: set the count back to zero */ + FAR char *devpath; /* Path to the QE device */ + unsigned int nloops; /* Collect this number of samples */ + unsigned int delay; /* Delay this number of seconds between samples */ +}; +#endif + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +extern struct qe_example_s g_qeexample; +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: qe_devinit() + * + * Description: + * Perform architecuture-specific initialization of the QE hardware. This + * interface must be provided by all configurations using apps/examples/qe + * + ****************************************************************************/ + +int qe_devinit(void); + +#endif /* __APPS_EXAMPLES_QENCODER_QE_H */ diff --git a/apps/examples/qencoder/qe_main.c b/apps/examples/qencoder/qe_main.c new file mode 100644 index 0000000000..c58a2b0ada --- /dev/null +++ b/apps/examples/qencoder/qe_main.c @@ -0,0 +1,370 @@ +/**************************************************************************** + * examples/qe/qe_main.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "qe.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +# define MAIN_NAME qe_main +# define MAIN_STRING "qe_main: " +#else +# define MAIN_NAME user_start +# define MAIN_STRING "user_start: " +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +struct qe_example_s g_qeexample; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: qe_devpath + ****************************************************************************/ + +static void qe_devpath(FAR const char *devpath) +{ + /* Get rid of any old device path */ + + if (g_qeexample.devpath) + { + free(g_qeexample.devpath); + } + + /* The set-up the new device path by copying the string */ + + g_qeexample.devpath = strdup(devpath); +} + +/**************************************************************************** + * Name: qe_help + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static void qe_help(void) +{ + message("\nUsage: qe [OPTIONS]\n\n"); + message("OPTIONS include:\n"); + message(" [-p devpath] QE device path\n"); + message(" [-n samples] Number of samples\n"); + message(" [-t msec] Delay between samples (msec)\n"); + message(" [-r] Reset the position to zero\n"); + message(" [-h] Shows this message and exits\n\n"); +} +#endif + +/**************************************************************************** + * Name: arg_string + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static int arg_string(FAR char **arg, FAR char **value) +{ + FAR char *ptr = *arg; + + if (ptr[2] == '\0') + { + *value = arg[1]; + return 2; + } + else + { + *value = &ptr[2]; + return 1; + } +} +#endif + +/**************************************************************************** + * Name: arg_decimal + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static int arg_decimal(FAR char **arg, FAR long *value) +{ + FAR char *string; + int ret; + + ret = arg_string(arg, &string); + *value = strtol(string, NULL, 10); + return ret; +} +#endif + +/**************************************************************************** + * Name: parse_args + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static void parse_args(int argc, FAR char **argv) +{ + FAR char *ptr; + FAR char *str; + long value; + int index; + int nargs; + + g_qeexample.reset = false; + g_qeexample.nloops = 1; + g_qeexample.delay = CONFIG_EXAMPLES_QENCODER_DELAY; + + for (index = 1; index < argc; ) + { + ptr = argv[index]; + if (ptr[0] != '-') + { + message("Invalid options format: %s\n", ptr); + exit(0); + } + + switch (ptr[1]) + { + case 'n': + nargs = arg_decimal(&argv[index], &value); + if (value < 0 || value > INT_MAX) + { + message("Sample count out of range: %ld\n", value); + exit(1); + } + + g_qeexample.nloops = (unsigned int)value; + index += nargs; + break; + + case 'p': + nargs = arg_string(&argv[index], &str); + qe_devpath(str); + index += nargs; + break; + + case 't': + nargs = arg_decimal(&argv[index], &value); + if (value < 0 || value > INT_MAX) + { + message("Sample delay out of range: %ld\n", value); + exit(1); + } + + g_qeexample.delay = (unsigned int)value; + index += nargs; + break; + + case 'r': + g_qeexample.reset = true; + index++; + break; + + case 'h': + qe_help(); + exit(EXIT_SUCCESS); + + default: + message("Unsupported option: %s\n", ptr); + qe_help(); + exit(EXIT_FAILURE); + } + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start/qe_main + ****************************************************************************/ + +int MAIN_NAME(int argc, char *argv[]) +{ + int32_t position; + int fd; + int exitval = EXIT_SUCCESS; + int ret; +#if defined(CONFIG_NSH_BUILTIN_APPS) || defined(CONFIG_EXAMPLES_QENCODER_NSAMPLES) + int nloops; +#endif + + /* Check if we have initialized */ + + if (!g_qeexample.initialized) + { + /* Initialization of the encoder hardware is performed by logic external to + * this test. + */ + + message(MAIN_STRING "Initializing external encoder(s)\n"); + ret = qe_devinit(); + if (ret != OK) + { + message(MAIN_STRING "qe_devinit failed: %d\n", ret); + exitval = EXIT_FAILURE; + goto errout; + } + + /* Set the default values */ + + qe_devpath(CONFIG_EXAMPLES_QENCODER_DEVPATH); + g_qeexample.initialized = true; + } + + /* Parse command line arguments */ + +#ifdef CONFIG_NSH_BUILTIN_APPS + parse_args(argc, argv); +#endif + + /* Open the encoder device for reading */ + + message(MAIN_STRING "Hardware initialized. Opening the encoder device: %s\n", + g_qeexample.devpath); + + fd = open(g_qeexample.devpath, O_RDONLY); + if (fd < 0) + { + message(MAIN_STRING "open %s failed: %d\n", g_qeexample.devpath, errno); + exitval = EXIT_FAILURE; + goto errout_with_dev; + } + + /* Reset the count if so requested */ + + if (g_qeexample.reset) + { + message(MAIN_STRING "Resetting the count...\n"); + ret = ioctl(fd, QEIOC_RESET, 0); + if (ret < 0) + { + message(MAIN_STRING "ioctl(QEIOC_RESET) failed: %d\n", errno); + exitval = EXIT_FAILURE; + goto errout_with_dev; + } + } + + /* Now loop the appropriate number of times, displaying the collected + * encoder samples. + */ + +#if defined(CONFIG_NSH_BUILTIN_APPS) + message(MAIN_STRING "Number of samples: %d\n", g_qeexample.nloops); + for (nloops = 0; nloops < g_qeexample.nloops; nloops++) +#elif defined(CONFIG_EXAMPLES_QENCODER_NSAMPLES) + message(MAIN_STRING "Number of samples: %d\n", CONFIG_EXAMPLES_QENCODER_NSAMPLES); + for (nloops = 0; nloops < CONFIG_EXAMPLES_QENCODER_NSAMPLES; nloops++) +#else + for (;;) +#endif + { + /* Flush any output before the loop entered or from the previous pass + * through the loop. + */ + + msgflush(); + + /* Get the positions data using the ioctl */ + + ret = ioctl(fd, QEIOC_POSITION, (unsigned long)((uintptr_t)&position)); + if (ret < 0) + { + message(MAIN_STRING "ioctl(QEIOC_POSITION) failed: %d\n", errno); + exitval = EXIT_FAILURE; + goto errout_with_dev; + } + + /* Print the sample data on successful return */ + + else + { + message(MAIN_STRING "%3d. %d\n", nloops+1, position); + } + + /* Delay a little bit */ + +#if defined(CONFIG_NSH_BUILTIN_APPS) + usleep(g_qeexample.delay * 1000); +#else + usleep(CONFIG_EXAMPLES_QENCODER_DELAY * 1000); +#endif + } + +errout_with_dev: + close(fd); + +errout: + message("Terminating!\n"); + msgflush(); + return exitval; +} diff --git a/apps/examples/romfs/Kconfig b/apps/examples/romfs/Kconfig new file mode 100644 index 0000000000..5a8c824a35 --- /dev/null +++ b/apps/examples/romfs/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_ROMFS + bool "ROMFS example" + default n + ---help--- + Enable the ROMFS example + +if EXAMPLES_ROMFS +endif diff --git a/apps/examples/romfs/Makefile b/apps/examples/romfs/Makefile new file mode 100644 index 0000000000..1db45765a7 --- /dev/null +++ b/apps/examples/romfs/Makefile @@ -0,0 +1,111 @@ +############################################################################ +# apps/examples/romfs/Makefile +# +# Copyright (C) 2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# ROMFS File System Example + +ASRCS = +CSRCS = romfs_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: checkgenromfs clean depend disclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +checkgenromfs: + @genromfs -h 1>/dev/null 2>&1 || { \ + echo "Host executable genromfs not available in PATH"; \ + echo "You may need to download in from http://romfs.sourceforge.net/"; \ + exit 1; \ + } + +testdir : testdir.tar.gz + @tar zxf $< || { echo "tar zxf $< failed" ; exit 1 ; } + +testdir.img : checkgenromfs testdir + @genromfs -f $@ -d testdir -V "ROMFS_Test" || { echo "genromfs failed" ; exit 1 ; } + +romfs_testdir.h : testdir.img + @xxd -i $< >$@ || { echo "xxd of $< failed" ; exit 1 ; } + +.built: romfs_testdir.h $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +context: + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +# Register application +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend testdir.img + +-include Make.dep + diff --git a/apps/examples/romfs/romfs_main.c b/apps/examples/romfs/romfs_main.c new file mode 100644 index 0000000000..32b3d2654b --- /dev/null +++ b/apps/examples/romfs/romfs_main.c @@ -0,0 +1,498 @@ +/**************************************************************************** + * examples/romfs/romfs_main.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* Mount the ROMFS image, Verifty that it contains the + * following: + * + * testdir + * |---------- [drwxr-xr-x 4096] adir + * | |------ [-rw-r--r-- 21] anotherfile.txt + * | |------ [drwxr-xr-x 4096] subdir + * | | `-- [-rw-r--r-- 21] subdirfile.txt + * | `------ [-rw-r--r-- 25] yafile.txt + * |---------- [-rw-r--r-- 15] afile.txt + * |---------- [-rw-r--r-- 21] hfile + * `---------- [lrwxrwxrwx 11] ldir -> adir/subdir + * + * testdir/ldir is a soft-link and should not be detectable. + * hfile is a hardlink to subdirfile and should be identical + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "romfs_testdir.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Configuration settings */ + +#ifndef CONFIG_EXAMPLES_ROMFS_RAMDEVNO +# define CONFIG_EXAMPLES_ROMFS_RAMDEVNO 1 +#endif + +#ifndef CONFIG_EXAMPLES_ROMFS_SECTORSIZE +# define CONFIG_EXAMPLES_ROMFS_SECTORSIZE 64 +#endif + +#ifndef CONFIG_EXAMPLES_ROMFS_MOUNTPOINT +# define CONFIG_EXAMPLES_ROMFS_MOUNTPOINT "/usr/local/share" +#endif + +#ifdef CONFIG_DISABLE_MOUNTPOINT +# error "Mountpoint support is disabled" +#endif + +#if CONFIG_NFILE_DESCRIPTORS < 4 +# error "Not enough file descriptors" +#endif + +#ifndef CONFIG_FS_ROMFS +# error "ROMFS support not enabled" +#endif + +#define NSECTORS(b) (((b)+CONFIG_EXAMPLES_ROMFS_SECTORSIZE-1)/CONFIG_EXAMPLES_ROMFS_SECTORSIZE) +#define STR_RAMDEVNO(m) #m +#define MKMOUNT_DEVNAME(m) "/dev/ram" STR_RAMDEVNO(m) +#define MOUNT_DEVNAME MKMOUNT_DEVNAME(CONFIG_EXAMPLES_ROMFS_RAMDEVNO) + +#define SCRATCHBUFFER_SIZE 1024 + +/* Test directory stuff */ + +#define WRITABLE_MODE (S_IWOTH|S_IWGRP|S_IWUSR) +#define READABLE_MODE (S_IROTH|S_IRGRP|S_IRUSR) +#define EXECUTABLE_MODE (S_IXOTH|S_IXGRP|S_IXUSR) + +#define DIRECTORY_MODE (S_IFDIR|READABLE_MODE|EXECUTABLE_MODE) +#define FILE_MODE (S_IFREG|READABLE_MODE) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct node_s +{ + struct node_s *peer; /* Next node in this directory */ + bool directory; /* True: directory */ + bool found; /* True: found and verified */ + const char *name; /* Node name */ + mode_t mode; /* Expected permissions */ + size_t size; /* Expected size */ + union + { + const char *filecontent; /* Context of text file */ + struct node_s *child; /* Subdirectory start */ + } u; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char g_afilecontent[] = "This is a file\n"; +static const char g_anotherfilecontent[] = "This is another file\n"; +static const char g_yafilecontent[] = "This is yet another file\n"; +static const char g_subdirfilecontent[] = "File in subdirectory\n"; + +#define g_hfilecontent g_subdirfilecontent + +static struct node_s g_adir; +static struct node_s g_afile; +static struct node_s g_hfile; + +static struct node_s g_anotherfile; +static struct node_s g_subdir; +static struct node_s g_yafile; + +static struct node_s g_subdirfile; + +static int g_nerrors = 0; + +static char g_scratchbuffer[SCRATCHBUFFER_SIZE]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: + ****************************************************************************/ + +static void connectem(void) +{ + g_adir.peer = &g_afile; + g_adir.directory = true; + g_adir.found = false; + g_adir.name = "adir"; + g_adir.mode = DIRECTORY_MODE; + g_adir.size = 0; + g_adir.u.child = &g_anotherfile; + + g_afile.peer = &g_hfile; + g_afile.directory = false; + g_afile.found = false; + g_afile.name = "afile.txt"; + g_afile.mode = FILE_MODE; + g_afile.size = strlen(g_afilecontent); + g_afile.u.filecontent = g_afilecontent; + + g_hfile.peer = NULL; + g_hfile.directory = false; /* Actually a hard link */ + g_hfile.found = false; + g_hfile.name = "hfile"; + g_hfile.mode = FILE_MODE; + g_hfile.size = strlen(g_hfilecontent); + g_hfile.u.filecontent = g_hfilecontent; + + g_anotherfile.peer = &g_yafile; + g_anotherfile.directory = false; + g_anotherfile.found = false; + g_anotherfile.name = "anotherfile.txt"; + g_anotherfile.mode = FILE_MODE; + g_anotherfile.size = strlen(g_anotherfilecontent); + g_anotherfile.u.filecontent = g_anotherfilecontent; + + g_yafile.peer = &g_subdir; + g_yafile.directory = false; + g_yafile.found = false; + g_yafile.name = "yafile.txt"; + g_yafile.mode = FILE_MODE; + g_yafile.size = strlen(g_yafilecontent); + g_yafile.u.filecontent = g_yafilecontent; + + g_subdir.peer = NULL; + g_subdir.directory = true; + g_subdir.found = false; + g_subdir.name = "subdir"; + g_subdir.mode = DIRECTORY_MODE; + g_subdir.size = 0; + g_subdir.u.child = &g_subdirfile; + + g_subdirfile.peer = NULL; + g_subdirfile.directory = false; + g_subdirfile.found = false; + g_subdirfile.name = "subdirfile.txt"; + g_subdirfile.mode = FILE_MODE; + g_subdirfile.size = strlen(g_subdirfilecontent); + g_subdirfile.u.filecontent = g_subdirfilecontent; +} + +/**************************************************************************** + * Name: findindirectory + ****************************************************************************/ + +static struct node_s *findindirectory(struct node_s *entry, const char *name) +{ + for (; entry; entry = entry->peer) + { + if (!entry->found && strcmp(entry->name, name) == 0) + { + entry->found = true; + return entry; + } + } + return NULL; +} + +/**************************************************************************** + * Name: checkattributes + ****************************************************************************/ + +static void checkattributes(const char *path, mode_t mode, size_t size) +{ + struct stat buf; + int ret; + + ret = stat(path, &buf); + if (ret != 0) + { + printf(" -- ERROR: Failed to stat %s: %d\n", path, errno); + g_nerrors++; + return; + } + + if (mode != buf.st_mode) + { + printf(" -- ERROR: Expected mode %08x, got %08x\n", mode, buf.st_mode); + g_nerrors++; + } + + if (size != buf.st_size) + { + printf(" -- ERROR: Expected size %d, got %d\n", mode, buf.st_size); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: checkfile + ****************************************************************************/ + +static void checkfile(const char *path, struct node_s *node) +{ + ssize_t nbytesread; + char *filedata; + int fd; + + /* Open the file */ + + fd = open(path, O_RDONLY); + if (fd < 0) + { + printf(" -- ERROR: Failed to open %s: %d\n", path, errno); + g_nerrors++; + return; + } + + /* Read and verify the file contents */ + + nbytesread = read(fd, g_scratchbuffer, SCRATCHBUFFER_SIZE); + if (nbytesread < 0) + { + printf(" -- ERROR: Failed to read from %s: %d\n", path, errno); + g_nerrors++; + } + else if (nbytesread != node->size) + { + printf(" -- ERROR: Read %d bytes, expected %d\n", nbytesread, node->size); + g_nerrors++; + } + else if (memcmp(g_scratchbuffer, node->u.filecontent, node->size) != 0) + { + g_scratchbuffer[nbytesread] = '\0'; + printf(" -- ERROR: File content read does not match expectation:\n"); + printf(" -- Read: [%s]\n", g_scratchbuffer); + printf(" -- Expected: [%s]\n", node->u.filecontent); + g_nerrors++; + } + + /* Memory map and verify the file contents */ + + filedata = (char*)mmap(NULL, node->size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0); + if (!filedata || filedata == (char*)MAP_FAILED) + { + printf(" -- ERROR: mmap of %s failed: %d\n", path, errno); + g_nerrors++; + } + else + { + if (memcmp(filedata, node->u.filecontent, node->size) != 0) + { + memcpy(g_scratchbuffer, filedata, node->size); + g_scratchbuffer[node->size] = '\0'; + printf(" -- ERROR: Mapped file content read does not match expectation:\n"); + printf(" -- Memory: [%s]\n", filedata); + printf(" -- Expected: [%s]\n", node->u.filecontent); + g_nerrors++; + } + munmap(filedata, node->size); + } + + /* Close the file */ + + if (close(fd) != OK) + { + printf(" -- ERROR: Failed to close %s: %d\n", path, errno); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: readdirectories + ****************************************************************************/ + +static void readdirectories(const char *path, struct node_s *entry) +{ + DIR *dirp; + struct node_s *node; + struct dirent *direntry; + char *fullpath; + + printf("Traversing directory: %s\n", path); + dirp = opendir(path); + if (!dirp) + { + printf(" ERROR opendir(\"%s\") failed: %d\n", path, errno); + g_nerrors++; + return; + } + + for (direntry = readdir(dirp); direntry; direntry = readdir(dirp)) + { + if (strcmp(direntry->d_name, ".") == 0 || strcmp(direntry->d_name, "..") == 0) + { + printf(" Skipping %s\n", direntry->d_name); + continue; + } + + node = findindirectory(entry, direntry->d_name); + if (!node) + { + printf(" ERROR: No node found for %s\n", direntry->d_name); + g_nerrors++; + continue; + } + + /* Get the full path to the entry */ + + sprintf(g_scratchbuffer, "%s/%s", path, direntry->d_name); + fullpath = strdup(g_scratchbuffer); + + if (DIRENT_ISDIRECTORY(direntry->d_type)) + { + printf(" DIRECTORY: %s/\n", fullpath); + if (!node->directory) + { + printf(" -- ERROR: Expected type directory\n"); + g_nerrors++; + } + else + { + checkattributes(fullpath, node->mode, 0); + readdirectories(fullpath, node->u.child); + printf("Continuing directory: %s\n", path); + } + } + else + { + printf(" FILE: %s/\n", fullpath); + if (node->directory) + { + printf(" -- ERROR: Expected type file\n"); + g_nerrors++; + } + else + { + checkattributes(fullpath, node->mode, node->size); + checkfile(fullpath, node); + } + } + free(fullpath); + } + + closedir(dirp); +} + +/**************************************************************************** + * Name: checkdirectories + ****************************************************************************/ + +static void checkdirectories(struct node_s *entry) +{ + for (; entry; entry = entry->peer) + { + if (!entry->found ) + { + printf("ERROR: %s never found\n", entry->name); + g_nerrors++; + } + + if (entry->directory) + { + checkdirectories(entry->u.child); + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + int ret; + + /* Create a RAM disk for the test */ + + ret = romdisk_register(CONFIG_EXAMPLES_ROMFS_RAMDEVNO, testdir_img, + NSECTORS(testdir_img_len), CONFIG_EXAMPLES_ROMFS_SECTORSIZE); + if (ret < 0) + { + printf("ERROR: Failed to create RAM disk\n"); + return 1; + } + + /* Mount the test file system */ + + printf("Mounting ROMFS filesystem at target=%s with source=%s\n", + CONFIG_EXAMPLES_ROMFS_MOUNTPOINT, MOUNT_DEVNAME); + + ret = mount(MOUNT_DEVNAME, CONFIG_EXAMPLES_ROMFS_MOUNTPOINT, "romfs", MS_RDONLY, NULL); + if (ret < 0) + { + printf("ERROR: Mount failed: %d\n", errno); + return 1; + } + + /* Perform the test */ + + connectem(); + readdirectories(CONFIG_EXAMPLES_ROMFS_MOUNTPOINT, &g_adir); + checkdirectories(&g_adir); + + if (g_nerrors) + { + printf("Finished with %d errors\n", g_nerrors); + return g_nerrors; + } + + printf("PASSED\n"); + return 0; +} diff --git a/apps/examples/romfs/romfs_testdir.h b/apps/examples/romfs/romfs_testdir.h new file mode 100644 index 0000000000..53f93105cf --- /dev/null +++ b/apps/examples/romfs/romfs_testdir.h @@ -0,0 +1,89 @@ +unsigned char testdir_img[] = { + 0x2d, 0x72, 0x6f, 0x6d, 0x31, 0x66, 0x73, 0x2d, 0x00, 0x00, 0x02, 0x60, + 0x27, 0x43, 0x4a, 0x8a, 0x52, 0x4f, 0x4d, 0x46, 0x53, 0x5f, 0x54, 0x65, + 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xff, 0x97, + 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xff, 0x80, 0x2e, 0x2e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, + 0x93, 0x9b, 0x95, 0xf0, 0x6c, 0x64, 0x69, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x64, 0x69, 0x72, + 0x2f, 0x73, 0x75, 0x62, 0x64, 0x69, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x19, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, + 0x9e, 0x9b, 0x93, 0xc5, 0x61, 0x64, 0x69, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x58, 0x47, 0x43, 0xf1, + 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x2e, + 0x74, 0x78, 0x74, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, + 0xa1, 0xc5, 0x69, 0xd8, 0x79, 0x61, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74, + 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x79, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x6f, 0x74, + 0x68, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x90, + 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xfe, 0x20, 0x2e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x70, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0xd1, 0xd1, 0xfe, 0x70, 0x2e, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x00, 0x00, 0x23, 0x18, 0x9c, 0x03, + 0x73, 0x75, 0x62, 0x64, 0x69, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd2, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x15, 0x3e, 0x3f, 0x06, 0xd8, 0x73, 0x75, 0x62, 0x64, + 0x69, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74, 0x00, 0x00, + 0x46, 0x69, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x75, 0x62, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, + 0x00, 0x00, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xfc, 0xa0, + 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, + 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xff, 0x70, 0x2e, 0x2e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x99, 0x92, 0xd4, 0x68, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc5, 0x6b, 0x22, 0x0b, + 0x61, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x61, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int testdir_img_len = 1024; diff --git a/apps/examples/romfs/testdir.tar.gz b/apps/examples/romfs/testdir.tar.gz new file mode 100644 index 0000000000..cd0e9c5182 Binary files /dev/null and b/apps/examples/romfs/testdir.tar.gz differ diff --git a/apps/examples/romfs/testdir.txt b/apps/examples/romfs/testdir.txt new file mode 100644 index 0000000000..e321d6ded7 --- /dev/null +++ b/apps/examples/romfs/testdir.txt @@ -0,0 +1,105 @@ +VOLUME HEADER: Name=ROMFS_Test +0000000: 2d72 6f6d 3166 732d 0000 0260 2743 4a8a -rom1fs-...`'CJ. +0000010: 524f 4d46 535f 5465 7374 0000 0000 0000 ROMFS_Test...... + +FILE HEADER 1: Name=. +0000020: 0000 0049 0000 0020 0000 0000 d1ff ff97 ...I... ........ +0000030: 2e00 0000 0000 0000 0000 0000 0000 0000 ................ + +FILE HEADER 2: Name=.. +0000040: 0000 0060 0000 0020 0000 0000 d1d1 ff80 ...`... ........ +0000050: 2e2e 0000 0000 0000 0000 0000 0000 0000 ................ + +FILE HEADER 3: Name=ldir +0000060: 0000 0093 0000 0000 0000 000b 939b 95f0 ................ +0000070: 6c64 6972 0000 0000 0000 0000 0000 0000 ldir............ + + FILE CONTENT: + 0000080: 6164 6972 2f73 7562 6469 7200 0000 0000 adir/subdir..... + +FILE HEADER 4: Name=adir +0000090: 0000 0219 0000 00b0 0000 0000 9e9b 93c5 ................ +00000a0: 6164 6972 0000 0000 0000 0000 0000 0000 adir............ + + FILE HEADER 4.1: Name=anotherfile.txt + 00000b0: 0000 00f2 0000 0000 0000 0015 5847 43f1 ............XGC. + 00000c0: 616e 6f74 6865 7266 696c 652e 7478 7400 anotherfile.txt. + + FILE CONTENT: + 00000d0: 5468 6973 2069 7320 616e 6f74 6865 7220 This is another + 00000e0: 6669 6c65 0a00 0000 0000 0000 0000 0000 file............ + + FILE HEADER 4.2: Name=yafile.txt + 00000f0: 0000 0132 0000 0000 0000 0019 a1c5 69d8 ...2..........i. + 0000100: 7961 6669 6c65 2e74 7874 0000 0000 0000 yafile.txt...... + + FILE CONTENT: + 0000110: 5468 6973 2069 7320 7965 7420 616e 6f74 This is yet anot + 0000120: 6865 7220 6669 6c65 0a00 0000 0000 0000 her file........ + + FILE HEADER 4.3: Name=. + 0000130: 0000 0150 0000 0090 0000 0000 d1ff fe20 ...P........... + 0000140: 2e00 0000 0000 0000 0000 0000 0000 0000 ................ + + FILE HEADER 4.4: Name=.. + 0000150: 0000 0170 0000 0020 0000 0000 d1d1 fe70 ...p... .......p + 0000160: 2e2e 0000 0000 0000 0000 0000 0000 0000 ................ + + FILE HEADER 4.5: Name=subdir + 0000170: 0000 0009 0000 0190 0000 0000 2318 9c03 ............#... + 0000180: 7375 6264 6972 0000 0000 0000 0000 0000 subdir.......... + + FILE HEADER 4.5.1: Name=subdirfile.txt + 0000190: 0000 01d2 0000 0000 0000 0015 3e3f 06d8 ............>?.. + 00001a0: 7375 6264 6972 6669 6c65 2e74 7874 0000 subdirfile.txt.. + + FILE CONTENT: + 00001b0: 4669 6c65 2069 6e20 7375 6264 6972 6563 File in subdirec + 00001c0: 746f 7279 0a00 0000 0000 0000 0000 0000 tory............ + + FILE HEADER 4.5.2: Name=. + 00001d0: 0000 01f0 0000 0170 0000 0000 d1ff fca0 .......p........ + 00001e0: 2e00 0000 0000 0000 0000 0000 0000 0000 ................ + + FILE HEADER 4.5.3: Name=.. + 00001f0: 0000 0000 0000 0090 0000 0000 d1d1 ff70 ...............p + 0000200: 2e2e 0000 0000 0000 0000 0000 0000 0000 ................ + +FILE HEADER 5: Name=hfile +0000210: 0000 0230 0000 0190 0000 0000 3299 92d4 ...0........2... +0000220: 6866 696c 6500 0000 0000 0000 0000 0000 hfile........... + +FILE HEADER 6: Name=afile.txt +0000230: 0000 0002 0000 0000 0000 000f c56b 220b .............k". +0000240: 6166 696c 652e 7478 7400 0000 0000 0000 afile.txt....... + + FILE CONTENT: + 0000250: 5468 6973 2069 7320 6120 6669 6c65 0a00 This is a file.. + +PADDING +0000260: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000270: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000280: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000290: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00002a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00002b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00002c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00002d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00002e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00002f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000300: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000310: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000320: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000330: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000340: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000350: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000360: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000370: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000380: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000390: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00003a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00003b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00003c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00003d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00003e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00003f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ diff --git a/apps/examples/serloop/Kconfig b/apps/examples/serloop/Kconfig new file mode 100644 index 0000000000..e52d35b3ff --- /dev/null +++ b/apps/examples/serloop/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_SERLOOP + bool "Serial loopback example" + default n + ---help--- + Enable the serial loopback example + +if EXAMPLES_SERLOOP +endif diff --git a/apps/examples/serloop/Makefile b/apps/examples/serloop/Makefile new file mode 100644 index 0000000000..67c805d46c --- /dev/null +++ b/apps/examples/serloop/Makefile @@ -0,0 +1,95 @@ +############################################################################ +# apps/examples/serloop/Makefile +# +# Copyright (C) 2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# Mindlessly simple console loopack test + +ASRCS = +CSRCS = main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +context: + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +# Register application +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep + diff --git a/apps/examples/serloop/main.c b/apps/examples/serloop/main.c new file mode 100644 index 0000000000..3c635fe886 --- /dev/null +++ b/apps/examples/serloop/main.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * examples/serloop/main.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ +#ifdef CONFIG_EXAMPLES_SERLOOP_BUFIO + int ch; + + for (;;) + { + ch = getchar(); + if (ch < 1) + { + ch = '!'; + } + else if ((ch < 0x20 || ch > 0x7e) && ch != '\n') + { + ch = '.'; + } + putchar(ch); + } +#else + uint8_t ch; + int ret; + + for (;;) + { + ret = read(0, &ch, 1); + if (ret < 1) + { + ch = '!'; + } + else if ((ch < 0x20 || ch > 0x7e) && ch != '\n') + { + ch = '.'; + } + ret = write(1, &ch, 1); + } +#endif + return 0; +} + diff --git a/apps/examples/watchdog/Kconfig b/apps/examples/watchdog/Kconfig new file mode 100644 index 0000000000..18daf9327c --- /dev/null +++ b/apps/examples/watchdog/Kconfig @@ -0,0 +1,40 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_WATCHDOG + bool "Watchdog Timer example" + default n + ---help--- + Enable the watchdog timer example + +if EXAMPLES_WATCHDOG + +config EXAMPLES_WATCHDOG_DEVPATH + string "Watchdog device path" + default "/dev/watchdog0" + ---help--- + The path to the watchdog device. Default: /dev/watchdog0 + +config CONFIG_EXAMPLES_WATCHDOG_PINGTIME + int "Watchdog ping time" + default 5000 + ---help--- + Time in milliseconds that the example will ping the watchdog before letting the + watchdog expire. Default: 5000 milliseconds. + +config CONFIG_EXAMPLES_WATCHDOG_PINGDELAY + int "Watchdog ping delay" + default 500 + ---help--- + Time delay between pings in milliseconds. Default: 500 milliseconds. + +config EXAMPLES_WATCHDOG_TIMEOUT + int "Watchdog timeout" + default 2000 + ---help--- + The watchdog timeout value in milliseconds before the watchdog timer + expires. Default: 2000 milliseconds. + +endif diff --git a/apps/examples/watchdog/Makefile b/apps/examples/watchdog/Makefile new file mode 100644 index 0000000000..d2739dbb0a --- /dev/null +++ b/apps/examples/watchdog/Makefile @@ -0,0 +1,103 @@ +############################################################################ +# apps/examples/watchdog/Makefile +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# Watchdog Timer Example. + +ASRCS = +CSRCS = watchdog_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Touchscreen built-in application info + +APPNAME = wdog +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Common build + +VPATH = + +all: .built +.PHONY: context clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/watchdog/watchdog.h b/apps/examples/watchdog/watchdog.h new file mode 100644 index 0000000000..dc2dea9447 --- /dev/null +++ b/apps/examples/watchdog/watchdog.h @@ -0,0 +1,120 @@ +/**************************************************************************** + * examples/examples/watchdog/watchdog.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_EXAMPLES_WATCHDOG_WATCHDOG_H +#define __APPS_EXAMPLES_WATCHDOG_WATCHDOG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_NSH_BUILTIN_APPS - Build the WATCHDOG test as an NSH built-in + * function. Default: Not built! The example can only be used as an NSH + * built-in application + * CONFIG_EXAMPLES_WATCHDOG_DEVPATH - The path to the Watchdog device. + * Default: /dev/watchdog0 + * CONFIG_EXAMPLES_WATCHDOG_PINGTIME - Time in milliseconds that the example + * will ping the watchdog before letting the watchdog expire. Default: 5000 + * milliseconds + * CONFIG_EXAMPLES_WATCHDOG_PINGDELAY - Time delay between pings in + * milliseconds. Default: 500 milliseconds. + * CONFIG_EXAMPLES_WATCHDOG_TIMEOUT - The watchdog timeout value in + * milliseconds before the watchdog timer expires. Default: 2000 + * milliseconds. + */ + +#ifndef CONFIG_WATCHDOG +# error "WATCHDOG device support is not enabled (CONFIG_WATCHDOG)" +#endif + +#ifndef CONFIG_NSH_BUILTIN_APPS +# warning "The WATCHDOG example only works as an NSH built-in application (CONFIG_NSH_BUILTIN_APPS)" +#endif + +#ifndef CONFIG_EXAMPLES_WATCHDOG_DEVPATH +# define CONFIG_EXAMPLES_WATCHDOG_DEVPATH "/dev/watchdog0" +#endif + +#ifndef CONFIG_EXAMPLES_WATCHDOG_PINGTIME +# define CONFIG_EXAMPLES_WATCHDOG_PINGTIME 5000 +#endif + +#ifndef CONFIG_EXAMPLES_WATCHDOG_PINGDELAY +# define CONFIG_EXAMPLES_WATCHDOG_PINGDELAY 500 +#endif + +#ifndef CONFIG_EXAMPLES_WATCHDOG_TIMEOUT +# define CONFIG_EXAMPLES_WATCHDOG_TIMEOUT 2000 +#endif + +/* Debug ********************************************************************/ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_DEBUG +# define message(...) lib_rawprintf(__VA_ARGS__) +# define msgflush() +# else +# define message(...) printf(__VA_ARGS__) +# define msgflush() fflush(stdout) +# endif +#else +# ifdef CONFIG_DEBUG +# define message lib_rawprintf +# define msgflush() +# else +# define message printf +# define msgflush() fflush(stdout) +# endif +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __APPS_EXAMPLES_WATCHDOG_WATCHDOG_H */ diff --git a/apps/examples/watchdog/watchdog_main.c b/apps/examples/watchdog/watchdog_main.c new file mode 100644 index 0000000000..c1341e0fb9 --- /dev/null +++ b/apps/examples/watchdog/watchdog_main.c @@ -0,0 +1,357 @@ +/**************************************************************************** + * examples/watchdog/watchdog_main.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "watchdog.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct wdog_example_s +{ + uint32_t pingtime; + uint32_t pingdelay; + uint32_t timeout; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wdog_help + ****************************************************************************/ + +static void wdog_help(void) +{ + message("Usage: wdog [-h] [-d ] [-t ]\n"); + message("\nInitialize the watchdog to the . Start the watchdog\n"); + message("timer. Ping for the watchdog for seconds, then let it expire.\n"); + message("\nOptions include:\n"); + message(" [-d ] = Selects the time in milliseconds. Default: %d\n", + CONFIG_EXAMPLES_WATCHDOG_PINGTIME); + message(" [-p pingtime = CONFIG_EXAMPLES_WATCHDOG_PINGTIME; + wdog->pingdelay = CONFIG_EXAMPLES_WATCHDOG_PINGDELAY; + wdog->timeout = CONFIG_EXAMPLES_WATCHDOG_TIMEOUT; + + for (index = 1; index < argc; ) + { + ptr = argv[index]; + if (ptr[0] != '-') + { + message("Invalid options format: %s\n", ptr); + exit(EXIT_SUCCESS); + } + + switch (ptr[1]) + { + case 'd': + nargs = arg_decimal(&argv[index], &value); + if (value < 1) + { + message("Ping delay out of range: %ld\n", value); + exit(EXIT_FAILURE); + } + + wdog->pingdelay = (uint32_t)value; + index += nargs; + break; + + case 'p': + nargs = arg_decimal(&argv[index], &value); + if (value < 1 || value > 99) + { + message("Ping time out of range: %ld\n", value); + exit(EXIT_FAILURE); + } + + wdog->pingtime = (uint8_t)value; + index += nargs; + break; + + case 't': + nargs = arg_decimal(&argv[index], &value); + if (value < 1 || value > INT_MAX) + { + message("Duration out of range: %ld\n", value); + exit(EXIT_FAILURE); + } + + wdog->timeout = (int)value; + index += nargs; + break; + + case 'h': + wdog_help(); + exit(EXIT_SUCCESS); + + default: + message("Unsupported option: %s\n", ptr); + wdog_help(); + exit(EXIT_FAILURE); + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start/wdog_main + ****************************************************************************/ + +int wdog_main(int argc, char *argv[]) +{ + struct wdog_example_s wdog; +#ifdef CONFIG_DEBUG_WATCHDOG + struct watchdog_status_s status; +#endif + long elapsed; + int fd; + int ret; + + /* Parse the command line */ + + parse_args(&wdog, argc, argv); + + /* Initialization of the WATCHDOG hardware is performed by logic external to + * this test. + */ + + ret = up_wdginitialize(); + if (ret != OK) + { + message("wdog_main: up_wdginitialize failed: %d\n", ret); + goto errout; + } + + /* Open the watchdog device for reading */ + + fd = open(CONFIG_EXAMPLES_WATCHDOG_DEVPATH, O_RDONLY); + if (fd < 0) + { + message("wdog_main: open %s failed: %d\n", + CONFIG_EXAMPLES_WATCHDOG_DEVPATH, errno); + goto errout; + } + + /* Set the watchdog timeout */ + + ret = ioctl(fd, WDIOC_SETTIMEOUT, (unsigned long)wdog.timeout); + if (ret < 0) + { + message("wdog_main: ioctl(WDIOC_SETTIMEOUT) failed: %d\n", errno); + goto errout_with_dev; + } + + /* Then start the watchdog timer. */ + + ret = ioctl(fd, WDIOC_START, 0); + if (ret < 0) + { + message("wdog_main: ioctl(WDIOC_START) failed: %d\n", errno); + goto errout_with_dev; + } + + /* Then ping */ + + for (elapsed = 0; elapsed < wdog.pingtime; elapsed += wdog.pingdelay) + { + /* Sleep for the requested amount of time */ + + usleep(wdog.pingdelay * 1000); + + /* Show watchdog status. Only if debug is enabled because this + * could interfere with the timer. + */ + +#ifdef CONFIG_DEBUG_WATCHDOG + ret = ioctl(fd, WDIOC_GETSTATUS, (unsigned long)&status); + if (ret < 0) + { + message("wdog_main: ioctl(WDIOC_GETSTATUS) failed: %d\n", errno); + goto errout_with_dev; + } + message("wdog_main: flags=%08x timeout=%d timeleft=%d\n", + status.flags, status.timeout, status.timeleft); +#endif + + /* Then ping */ + + ret = ioctl(fd, WDIOC_KEEPALIVE, 0); + if (ret < 0) + { + message("wdog_main: ioctl(WDIOC_KEEPALIVE) failed: %d\n", errno); + goto errout_with_dev; + } + + message(" ping elapsed=%ld\n", elapsed); + msgflush(); + } + + /* Then stop pinging */ + + for (; ; elapsed += wdog.pingdelay) + { + /* Sleep for the requested amount of time */ + + usleep(wdog.pingdelay * 1000); + + /* Show watchdog status. Only if debug is enabled because this + * could interfere with the timer. + */ + +#ifdef CONFIG_DEBUG_WATCHDOG + ret = ioctl(fd, WDIOC_GETSTATUS, (unsigned long)&status); + if (ret < 0) + { + message("wdog_main: ioctl(WDIOC_GETSTATUS) failed: %d\n", errno); + goto errout_with_dev; + } + message("wdog_main: flags=%08x timeout=%d timeleft=%d\n", + status.flags, status.timeout, status.timeleft); +#endif + + message(" NO ping elapsed=%ld\n", elapsed); + msgflush(); + } + + /* We should not get here */ + + ret = ioctl(fd, WDIOC_STOP, 0); + if (ret < 0) + { + message("wdog_main: ioctl(WDIOC_STOP) failed: %d\n", errno); + goto errout_with_dev; + } + + close(fd); + msgflush(); + return OK; + +errout_with_dev: + close(fd); +errout: + msgflush(); + return ERROR; +} diff --git a/apps/fixedwing_control/Makefile b/apps/fixedwing_control/Makefile new file mode 100644 index 0000000000..985708ae54 --- /dev/null +++ b/apps/fixedwing_control/Makefile @@ -0,0 +1,44 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# fixedwing_control Application +# + +APPNAME = fixedwing_control +PRIORITY = SCHED_PRIORITY_MAX - 1 +STACKSIZE = 12288 + +CSRCS = fixedwing_control.c + +include $(APPDIR)/mk/app.mk diff --git a/apps/fixedwing_control/fixedwing_control.c b/apps/fixedwing_control/fixedwing_control.c new file mode 100644 index 0000000000..d9d39f14dd --- /dev/null +++ b/apps/fixedwing_control/fixedwing_control.c @@ -0,0 +1,938 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: @author Ivan Ovinnikov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * @file fixedwing_control.c + * Implementation of a fixed wing attitude and position controller. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../mix_and_link/mix_and_link.h" +#include "fixedwing_control.h" + +__EXPORT int fixedwing_control_main(int argc, char *argv[]); + +#define PID_DT 0.01f +#define PID_SCALER 0.1f +#define PID_DERIVMODE_CALC 0 +#define HIL_MODE 32 +#define RAD2DEG ((1.0/180.0)*M_PI) +#define AUTO -1000 +#define MANUAL 3000 +#define SERVO_MIN 1000 +#define SERVO_MAX 2000 + +pthread_t control_thread; +pthread_t nav_thread; +pthread_t servo_thread; + +/** + * Servo channels function enumerator used for + * the servo writing part + */ + +enum SERVO_CHANNELS_FUNCTION { + + AIL_1 = 0, + AIL_2 = 1, + MOT = 2, + ACT_1 = 3, + ACT_2 = 4, + ACT_3 = 5, + ACT_4 = 6, + ACT_5 = 7 +}; + +/** + * The plane_data structure. + * + * The plane data structure is the local storage of all the flight information of the aircraft + */ +typedef struct { + double lat; + double lon; + float alt; + float vx; + float vy; + float vz; + float yaw; + float hdg; + float pitch; + float roll; + float yawspeed; + float pitchspeed; + float rollspeed; + float rollb; /* body frame angles */ + float pitchb; + float yawb; + float p; + float q; + float r; /* body angular rates */ + + /* PID parameters*/ + + float Kp_att; + float Ki_att; + float Kd_att; + float Kp_pos; + float Ki_pos; + float Kd_pos; + float intmax_att; + float intmax_pos; + + /* Next waypoint*/ + + float wp_x; + float wp_y; + float wp_z; + + /* Setpoints */ + + float airspeed; + float groundspeed; + float roll_setpoint; + float pitch_setpoint; + float throttle_setpoint; + + /* Navigation mode*/ + int mode; + +} plane_data_t; + +/** + * The control_outputs structure. + * + * The control outputs structure contains the control outputs + * of the aircraft + */ +typedef struct { + float roll_ailerons; + float pitch_elevator; + float yaw_rudder; + float throttle; + // set the aux values to 0 per default + float aux1; + float aux2; + float aux3; + float aux4; + uint8_t mode; // HIL_ENABLED: 32 + uint8_t nav_mode; +} control_outputs_t; + +/** + * Generic PID algorithm with PD scaling + */ +static float pid(float error, float error_deriv, uint16_t dt, float scaler, float K_p, float K_i, float K_d, float intmax); + +/* + * Output calculations + */ + +static void calc_body_angular_rates(float roll, float pitch, float yaw, float rollspeed, float pitchspeed, float yawspeed); +static void calc_rotation_matrix(float roll, float pitch, float yaw, float x, float y, float z); +static void calc_bodyframe_angles(float roll, float pitch, float yaw); +static float calc_bearing(void); +static float calc_roll_ail(void); +static float calc_pitch_elev(void); +static float calc_yaw_rudder(float hdg); +static float calc_throttle(void); +static float calc_gnd_speed(void); +static void get_parameters(void); +static float calc_roll_setpoint(void); +static float calc_pitch_setpoint(void); +static float calc_throttle_setpoint(void); +static float calc_wp_distance(void); +static void set_plane_mode(void); + +/* + * The control, navigation and servo loop threads + */ + +static void *control_loop(void *arg); +static void *nav_loop(void *arg); +static void *servo_loop(void *arg); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +plane_data_t plane_data; +control_outputs_t control_outputs; +float scaler = 1; //M_PI; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/** + * + * Calculates the PID control output given an error. Incorporates PD scaling and low-pass filter for the derivative component. + * + * @param error the input error + * @param error_deriv the derivative of the input error + * @param dt time constant + * @param scaler PD scaler + * @param K_p P gain + * @param K_i I gain + * @param K_d D gain + * @param intmax Integration limit + * + * @return the PID control output + */ + +static float pid(float error, float error_deriv, uint16_t dt, float scale, float K_p, float K_i, float K_d, float intmax) +{ + float Kp = K_p; + float Ki = K_i; + float Kd = K_d; + float delta_time = dt; + float lerror; + float imax = intmax; + float integrator; + float derivative; + float lderiv; + int fCut = 20; /* anything above 20 Hz is considered noise - low pass filter for the derivative */ + float output = 0; + + output += error * Kp; + + if ((fabs(Kd) > 0) && (dt > 0)) { + + if (PID_DERIVMODE_CALC) { + derivative = (error - lerror) / delta_time; + + /* + * discrete low pass filter, cuts out the + * high frequency noise that can drive the controller crazy + */ + float RC = 1 / (2 * M_PI * fCut); + derivative = lderiv + + (delta_time / (RC + delta_time)) * (derivative - lderiv); + + /* update state */ + lerror = error; + lderiv = derivative; + + } else { + derivative = error_deriv; + } + + /* add in derivative component */ + output += Kd * derivative; + } + + //printf("PID derivative %i\n", (int)(1000*derivative)); + + /* scale the P and D components with the PD scaler */ + output *= scale; + + /* Compute integral component if time has elapsed */ + if ((fabs(Ki) > 0) && (dt > 0)) { + integrator += (error * Ki) * scaler * delta_time; + + if (integrator < -imax) { + integrator = -imax; + + } else if (integrator > imax) { + integrator = imax; + } + + output += integrator; + } + + //printf("PID Integrator %i\n", (int)(1000*integrator)); + + return output; +} + +/** + * Load parameters from global storage. + * + * Fetches the current parameters from the global parameter storage and writes them + * to the plane_data structure + */ + +static void get_parameters() +{ + plane_data.Kp_att = global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_P]; + plane_data.Ki_att = global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_I]; + plane_data.Kd_att = global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_D]; + plane_data.Kp_pos = global_data_parameter_storage->pm.param_values[PARAM_PID_POS_P]; + plane_data.Ki_pos = global_data_parameter_storage->pm.param_values[PARAM_PID_POS_I]; + plane_data.Kd_pos = global_data_parameter_storage->pm.param_values[PARAM_PID_POS_D]; + plane_data.intmax_att = global_data_parameter_storage->pm.param_values[PARAM_PID_ATT_AWU]; + plane_data.intmax_pos = global_data_parameter_storage->pm.param_values[PARAM_PID_POS_AWU]; + plane_data.airspeed = global_data_parameter_storage->pm.param_values[PARAM_AIRSPEED]; + plane_data.wp_x = global_data_parameter_storage->pm.param_values[PARAM_WPLON]; + plane_data.wp_y = global_data_parameter_storage->pm.param_values[PARAM_WPLAT]; + plane_data.wp_z = global_data_parameter_storage->pm.param_values[PARAM_WPALT]; + plane_data.mode = global_data_parameter_storage->pm.param_values[PARAM_FLIGHTMODE]; +} + +/** + * Calculates the body angular rates. + * + * Calculates the rates of the plane using inertia matrix and + * writes them to the plane_data structure + * + * @param roll + * @param pitch + * @param yaw + * @param rollspeed + * @param pitchspeed + * @param yawspeed + * + */ +static void calc_body_angular_rates(float roll, float pitch, float yaw, float rollspeed, float pitchspeed, float yawspeed) +{ + plane_data.p = rollspeed - sinf(pitch) * yawspeed; + plane_data.q = cosf(roll) * pitchspeed + sinf(roll) * cos(pitch) * yawspeed; + plane_data.r = -sinf(roll) * pitchspeed + cosf(roll) * cos(pitch) * yawspeed; +} + +/** + * + * Calculates the attitude angles in the body reference frame. + * + * Writes them to the plane data structure + * + * @param roll + * @param pitch + * @param yaw + */ + +static void calc_bodyframe_angles(float roll, float pitch, float yaw) +{ + plane_data.rollb = cosf(yaw) * cosf(pitch) * roll + + (cosf(yaw) * sinf(pitch) * sinf(roll) + sinf(yaw) * cosf(roll)) * pitch + + (-cosf(yaw) * sinf(pitch) * cosf(roll) + sinf(yaw) * sinf(roll)) * yaw; + plane_data.pitchb = -sinf(yaw) * cosf(pitch) * roll + + (-sinf(yaw) * sinf(pitch) * sinf(roll) + cosf(yaw) * cosf(roll)) * pitch + + (sinf(yaw) * sinf(pitch) * cosf(roll) + cosf(yaw) * sinf(roll)) * yaw; + plane_data.yawb = sinf(pitch) * roll - cosf(pitch) * sinf(roll) * pitch + cosf(pitch) * cosf(roll) * yaw; +} + +/** + * calc_rotation_matrix + * + * Calculates the rotation matrix + * + * @param roll + * @param pitch + * @param yaw + * @param x + * @param y + * @param z + * + */ + +static void calc_rotation_matrix(float roll, float pitch, float yaw, float x, float y, float z) +{ + plane_data.rollb = cosf(yaw) * cosf(pitch) * x + + (cosf(yaw) * sinf(pitch) * sinf(roll) + sinf(yaw) * cosf(roll)) * y + + (-cosf(yaw) * sinf(pitch) * cosf(roll) + sinf(yaw) * sinf(roll)) * z; + plane_data.pitchb = -sinf(yaw) * cosf(pitch) * x + + (-sinf(yaw) * sinf(pitch) * sinf(roll) + cosf(yaw) * cosf(roll)) * y + + (sinf(yaw) * sinf(pitch) * cosf(roll) + cosf(yaw) * sinf(roll)) * z; + plane_data.yawb = sinf(pitch) * x - cosf(pitch) * sinf(roll) * y + cosf(pitch) * cosf(roll) * z; +} + +/** + * calc_bearing + * + * Calculates the bearing error of the plane compared to the waypoints + * + * @return bearing Bearing error + * + */ + +static float calc_bearing() +{ + float bearing = 90 + atan2(-(plane_data.wp_y - plane_data.lat), (plane_data.wp_x - plane_data.lon)) * RAD2DEG; + + if (bearing < 0) + bearing += 360; + + return bearing; +} + +/** + * calc_roll_ail + * + * Calculates the roll ailerons control output + * + * @return Roll ailerons control output (-1,1) + */ + +static float calc_roll_ail() +{ + float ret = pid((plane_data.roll_setpoint - plane_data.roll) / scaler, plane_data.rollspeed, PID_DT, PID_SCALER, + plane_data.Kp_att, plane_data.Ki_att, plane_data.Kd_att, plane_data.intmax_att); + + if (ret < -1) + return -1; + + if (ret > 1) + return 1; + + return ret; +} + +/** + * calc_pitch_elev + * + * Calculates the pitch elevators control output + * + * @return Pitch elevators control output (-1,1) + */ + +static float calc_pitch_elev() +{ + float ret = pid((plane_data.pitch_setpoint - plane_data.pitch) / scaler, plane_data.pitchspeed, PID_DT, PID_SCALER, + plane_data.Kp_att, plane_data.Ki_att, plane_data.Kd_att, plane_data.intmax_att); + + if (ret < -1) + return -1; + + if (ret > 1) + return 1; + + return ret; +} + +/** + * calc_yaw_rudder + * + * Calculates the yaw rudder control output (only if yaw rudder exists on the model) + * + * @return Yaw rudder control output (-1,1) + * + */ + +static float calc_yaw_rudder(float hdg) +{ + float ret = pid((plane_data.yaw / RAD2DEG - abs(hdg)) / scaler, plane_data.yawspeed, PID_DT, PID_SCALER, + plane_data.Kp_pos, plane_data.Ki_pos, plane_data.Kd_pos, plane_data.intmax_pos); + + if (ret < -1) + return -1; + + if (ret > 1) + return 1; + + return ret; +} + +/** + * calc_throttle + * + * Calculates the throttle control output + * + * @return Throttle control output (0,1) + */ + +static float calc_throttle() +{ + float ret = pid(plane_data.throttle_setpoint - calc_gnd_speed(), 0, PID_DT, PID_SCALER, + plane_data.Kp_pos, plane_data.Ki_pos, plane_data.Kd_pos, plane_data.intmax_pos); + + if (ret < 0.2) + return 0.2; + + if (ret > 1) + return 1; + + return ret; +} + +/** + * calc_gnd_speed + * + * Calculates the ground speed using the x and y components + * + * Input: none (operation on global data) + * + * Output: Ground speed of the plane + * + */ + +static float calc_gnd_speed() +{ + float gnd_speed = sqrtf(plane_data.vx * plane_data.vx + plane_data.vy * plane_data.vy); + return gnd_speed; +} + +/** + * calc_wp_distance + * + * Calculates the distance to the next waypoint + * + * @return the distance to the next waypoint + * + */ + +static float calc_wp_distance() +{ + return sqrtf((plane_data.lat - plane_data.wp_y) * (plane_data.lat - plane_data.wp_y) + + (plane_data.lon - plane_data.wp_x) * (plane_data.lon - plane_data.wp_x)); +} + +/** + * calc_roll_setpoint + * + * Calculates the offset angle for the roll plane, + * saturates at +- 35 deg. + * + * @return setpoint on which attitude control should stabilize while changing heading + * + */ + +static float calc_roll_setpoint() +{ + float setpoint = 0; + + if (plane_data.mode == TAKEOFF) { + setpoint = 0; + + } else { + setpoint = calc_bearing() - plane_data.yaw; + + if (setpoint < -35) + return -35; + + if (setpoint > 35) + return 35; + } + + return setpoint; +} + +/** + * calc_pitch_setpoint + * + * Calculates the offset angle for the pitch plane + * saturates at +- 35 deg. + * + * @return setpoint on which attitude control should stabilize while changing altitude + * + */ + +static float calc_pitch_setpoint() +{ + float setpoint = 0; + + if (plane_data.mode == TAKEOFF) { + setpoint = 35; + + } else { + setpoint = atanf((plane_data.wp_z - plane_data.alt) / calc_wp_distance()) * RAD2DEG; + + if (setpoint < -35) + return -35; + + if (setpoint > 35) + return 35; + } + + return setpoint; +} + +/** + * calc_throttle_setpoint + * + * Calculates the throttle setpoint for different flight modes + * + * @return throttle output setpoint + * + */ + +static float calc_throttle_setpoint() +{ + float setpoint = 0; + + // if TAKEOFF full throttle + if (plane_data.mode == TAKEOFF) { + setpoint = 60; + } + + // if CRUISE - parameter value + if (plane_data.mode == CRUISE) { + setpoint = plane_data.airspeed; + } + + // if LAND no throttle + if (plane_data.mode == LAND) { + setpoint = 0; + } + + return setpoint; +} + +/** + * set_plane_mode + * + * Sets the plane mode + * (TAKEOFF, CRUISE, LOITER or LAND) + * + */ + +static void set_plane_mode() +{ + if (plane_data.alt < 10) { + plane_data.mode = TAKEOFF; + + } else { + plane_data.mode = CRUISE; + // TODO: if reached waypoint and no further waypoint exists, go to LOITER mode + } + + // Debug override - don't need TAKEOFF mode for now + plane_data.mode = CRUISE; +} + +/* + * fixedwing_control_main + * + * @param argc number of arguments + * @param argv argument array + * + * @return 0 + * + */ + +int fixedwing_control_main(int argc, char *argv[]) +{ + /* print text */ + printf("Fixedwing control started\n"); + usleep(100000); + + /* default values for arguments */ + char *fixedwing_uart_name = "/dev/ttyS1"; + char *commandline_usage = "\tusage: fixedwing_control -d fixedwing-devicename\n"; + + /* read arguments */ + int i; + + if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--device") == 0) { + if (argc > i + 1) { + fixedwing_uart_name = argv[i + 1]; + + } else { + printf(commandline_usage); + return 0; + } + } + + /* Set up to publish fixed wing control messages */ + struct fixedwing_control_s control; + int fixedwing_control_pub = orb_advertise(ORB_ID(fixedwing_control), &control); + + /* Subscribe to global position, attitude and rc */ + struct vehicle_global_position_s global_pos; + int global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position)); + struct vehicle_attitude_s att; + int attitude_sub = orb_subscribe(ORB_ID(vehicle_attitude)); + struct rc_channels_s rc; + int rc_sub = orb_subscribe(ORB_ID(rc_channels)); + + /* Control constants */ + control_outputs.mode = HIL_MODE; + control_outputs.nav_mode = 0; + + /* Servo setup */ + + int fd; + servo_position_t data[PWM_SERVO_MAX_CHANNELS]; + + fd = open("/dev/pwm_servo", O_RDWR); + + if (fd < 0) { + printf("failed opening /dev/pwm_servo\n"); + } + + ioctl(fd, PWM_SERVO_ARM, 0); + + int16_t buffer_rc[3]; + int16_t buffer_servo[3]; + mixer_data_t mixer_buffer; + mixer_buffer.input = buffer_rc; + mixer_buffer.output = buffer_servo; + + mixer_conf_t mixers[3]; + + mixers[0].source = PITCH; + mixers[0].nr_actuators = 2; + mixers[0].dest[0] = AIL_1; + mixers[0].dest[1] = AIL_2; + mixers[0].dual_rate[0] = 1; + mixers[0].dual_rate[1] = 1; + + mixers[1].source = ROLL; + mixers[1].nr_actuators = 2; + mixers[1].dest[0] = AIL_1; + mixers[1].dest[1] = AIL_2; + mixers[1].dual_rate[0] = 1; + mixers[1].dual_rate[1] = -1; + + mixers[2].source = THROTTLE; + mixers[2].nr_actuators = 1; + mixers[2].dest[0] = MOT; + mixers[2].dual_rate[0] = 1; + + /* + * Main control, navigation and servo routine + */ + + while(1) + { + /* + * DATA Handling + * Fetch current flight data + */ + + /* get position, attitude and rc inputs */ + // XXX add error checking + orb_copy(ORB_ID(vehicle_global_position), global_pos_sub, &global_pos); + orb_copy(ORB_ID(vehicle_attitude), attitude_sub, &att); + orb_copy(ORB_ID(rc_channels), rc_sub, &rc); + + /* scaling factors are defined by the data from the APM Planner + * TODO: ifdef for other parameters (HIL/Real world switch) + */ + + /* position values*/ + plane_data.lat = global_pos.lat / 10000000; + plane_data.lon = global_pos.lon / 10000000; + plane_data.alt = global_pos.alt / 1000; + plane_data.vx = global_pos.vx / 100; + plane_data.vy = global_pos.vy / 100; + plane_data.vz = global_pos.vz / 100; + + /* attitude values*/ + plane_data.roll = att.roll; + plane_data.pitch = att.pitch; + plane_data.yaw = att.yaw; + plane_data.rollspeed = att.rollspeed; + plane_data.pitchspeed = att.pitchspeed; + plane_data.yawspeed = att.yawspeed; + + /* parameter values */ + get_parameters(); + + /* Attitude control part */ + +//#define MUTE +#ifndef MUTE + /******************************** DEBUG OUTPUT ************************************************************/ + + printf("Parameter: %i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i \n", (int)plane_data.Kp_att, (int)plane_data.Ki_att, + (int)plane_data.Kd_att, (int)plane_data.intmax_att, (int)plane_data.Kp_pos, (int)plane_data.Ki_pos, + (int)plane_data.Kd_pos, (int)plane_data.intmax_pos, (int)plane_data.airspeed, + (int)plane_data.wp_x, (int)plane_data.wp_y, (int)plane_data.wp_z); + +// printf("PITCH SETPOINT: %i\n", (int)plane_data.pitch_setpoint); +// printf("ROLL SETPOINT: %i\n", (int)plane_data.roll_setpoint); +// printf("THROTTLE SETPOINT: %i\n", (int)calc_throttle_setpoint()); + +// printf("\n\nVx: %i\t Vy: %i\t Current speed:%i\n\n", (int)plane_data.vx, (int)plane_data.vy, (int)(calc_gnd_speed())); + +// printf("Current Altitude: %i\n\n", (int)plane_data.alt); + + printf("\nAttitude values: \n R:%i \n P: %i \n Y: %i \n\n RS: %i \n PS: %i \n YS: %i \n ", + (int)(1000 * plane_data.roll), (int)(1000 * plane_data.pitch), (int)(1000 * plane_data.yaw), + (int)(100 * plane_data.rollspeed), (int)(100 * plane_data.pitchspeed), (int)(100 * plane_data.yawspeed)); + +// printf("\nBody Rates: \n P: %i \n Q: %i \n R: %i \n", +// (int)(10000 * plane_data.p), (int)(10000 * plane_data.q), (int)(10000 * plane_data.r)); + + printf("\nCalculated outputs: \n R: %i\n P: %i\n Y: %i\n T: %i \n", + (int)(10000 * control_outputs.roll_ailerons), (int)(10000 * control_outputs.pitch_elevator), + (int)(10000 * control_outputs.yaw_rudder), (int)(10000 * control_outputs.throttle)); + + /************************************************************************************************************/ + +#endif + + /* + * Computation section + * + * The function calls to compute the required control values happen + * in this section. + */ + + /* Set plane mode */ + set_plane_mode(); + + /* Calculate the P,Q,R body rates of the aircraft */ + calc_body_angular_rates(plane_data.roll / RAD2DEG, plane_data.pitch / RAD2DEG, plane_data.yaw / RAD2DEG, + plane_data.rollspeed, plane_data.pitchspeed, plane_data.yawspeed); + + /* Calculate the body frame angles of the aircraft */ + //calc_bodyframe_angles(plane_data.roll/RAD2DEG,plane_data.pitch/RAD2DEG,plane_data.yaw/RAD2DEG); + + /* Calculate the output values */ + control_outputs.roll_ailerons = calc_roll_ail(); + control_outputs.pitch_elevator = calc_pitch_elev(); + //control_outputs.yaw_rudder = calc_yaw_rudder(); + control_outputs.throttle = calc_throttle(); + + if (rc.chan[rc.function[OVERRIDE]].scale < MANUAL) { // if we're flying in automated mode + + if (plane_data.mode == TAKEOFF) { + control.attitude_control_output[ROLL] = 0; + control.attitude_control_output[PITCH] = 5000; + control.attitude_control_output[THROTTLE] = 10000; + //global_data_fixedwing_control->attitude_control_output[YAW] = (int16_t)(control_outputs.yaw_rudder); + } + + if (plane_data.mode == CRUISE) { + control.attitude_control_output[ROLL] = (int16_t)(10000 * control_outputs.roll_ailerons); + control.attitude_control_output[PITCH] = (int16_t)(10000 * control_outputs.pitch_elevator); + control.attitude_control_output[THROTTLE] = (int16_t)(10000 * control_outputs.throttle); + //control->attitude_control_output[YAW] = (int16_t)(control_outputs.yaw_rudder); + } + + control.counter++; + control.timestamp = hrt_absolute_time(); + } + + /* Navigation part */ + + // Get GPS Waypoint + + // if(global_data_wait(&global_data_position_setpoint->access_conf) == 0) + // { + // plane_data.wp_x = global_data_position_setpoint->x; + // plane_data.wp_y = global_data_position_setpoint->y; + // plane_data.wp_z = global_data_position_setpoint->z; + // } + // global_data_unlock(&global_data_position_setpoint->access_conf); + + if (rc.chan[rc.function[OVERRIDE]].scale < MANUAL) { // AUTO mode + // AUTO/HYBRID switch + + if (rc.chan[rc.function[OVERRIDE]].scale < AUTO) { + plane_data.roll_setpoint = calc_roll_setpoint(); + plane_data.pitch_setpoint = calc_pitch_setpoint(); + plane_data.throttle_setpoint = calc_throttle_setpoint(); + + } else { + plane_data.roll_setpoint = rc.chan[rc.function[ROLL]].scale / 200; + plane_data.pitch_setpoint = rc.chan[rc.function[PITCH]].scale / 200; + plane_data.throttle_setpoint = rc.chan[rc.function[THROTTLE]].scale / 200; + } + + //control_outputs.yaw_rudder = calc_yaw_rudder(plane_data.hdg); + + // 10 Hz loop + usleep(100000); + + } else { + control.attitude_control_output[ROLL] = rc.chan[rc.function[ROLL]].scale; + control.attitude_control_output[PITCH] = rc.chan[rc.function[PITCH]].scale; + control.attitude_control_output[THROTTLE] = rc.chan[rc.function[THROTTLE]].scale; + // since we don't have a yaw rudder + //control->attitude_control_output[3] = global_data_rc_channels->chan[YAW].scale; + + control.counter++; + control.timestamp = hrt_absolute_time(); + } + + /* publish the control data */ + + orb_publish(ORB_ID(fixedwing_control), fixedwing_control_pub, &control); + + /* Servo part */ + + buffer_rc[ROLL] = control.attitude_control_output[ROLL]; + buffer_rc[PITCH] = control.attitude_control_output[PITCH]; + buffer_rc[THROTTLE] = control.attitude_control_output[THROTTLE]; + + //mix_and_link(mixers, 3, 2, &mixer_buffer); + + // Scaling and saturation of servo outputs happens here + + data[AIL_1] = buffer_servo[AIL_1] / global_data_parameter_storage->pm.param_values[PARAM_SERVO_SCALE] + + global_data_parameter_storage->pm.param_values[PARAM_SERVO1_TRIM]; + + if (data[AIL_1] > SERVO_MAX) + data[AIL_1] = SERVO_MAX; + + if (data[AIL_1] < SERVO_MIN) + data[AIL_1] = SERVO_MIN; + + data[AIL_2] = buffer_servo[AIL_2] / global_data_parameter_storage->pm.param_values[PARAM_SERVO_SCALE] + + global_data_parameter_storage->pm.param_values[PARAM_SERVO2_TRIM]; + + if (data[AIL_2] > SERVO_MAX) + data[AIL_2] = SERVO_MAX; + + if (data[AIL_2] < SERVO_MIN) + data[AIL_2] = SERVO_MIN; + + data[MOT] = buffer_servo[MOT] / global_data_parameter_storage->pm.param_values[PARAM_SERVO_SCALE] + + global_data_parameter_storage->pm.param_values[PARAM_SERVO3_TRIM]; + + if (data[MOT] > SERVO_MAX) + data[MOT] = SERVO_MAX; + + if (data[MOT] < SERVO_MIN) + data[MOT] = SERVO_MIN; + + int result = write(fd, &data, sizeof(data)); + + if (result != sizeof(data)) { + printf("failed writing servo outputs\n"); + } + + /* 20Hz loop*/ + usleep(50000); + } + + return 0; +} diff --git a/apps/fixedwing_control/fixedwing_control.h b/apps/fixedwing_control/fixedwing_control.h new file mode 100644 index 0000000000..6023e39672 --- /dev/null +++ b/apps/fixedwing_control/fixedwing_control.h @@ -0,0 +1,66 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: Ivan Ovinnikov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * @file Definition of attitude controller + */ + +#ifndef FIXEDWING_CONTROL_H_ +#define FIXEDWING_CONTROL_H_ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Internal definitions + ****************************************************************************/ + + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#endif /* FIXEDWING_CONTROL_H_ */ diff --git a/apps/fixedwing_control/fixedwing_control.zip b/apps/fixedwing_control/fixedwing_control.zip new file mode 100644 index 0000000000..edaac33d5b Binary files /dev/null and b/apps/fixedwing_control/fixedwing_control.zip differ diff --git a/apps/fixedwing_control/pid.c b/apps/fixedwing_control/pid.c new file mode 100644 index 0000000000..81b4deac16 --- /dev/null +++ b/apps/fixedwing_control/pid.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * pid.c + * + * Copyright (C) 2012 Ivan Ovinnikov. All rights reserved. + * Authors: Ivan Ovinnikov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "pid.h" +#include "fixedwing_control.h" + +/******************************************************************************* + * pid() + * + * Calculates the PID control output given an error + * + * Input: float error, uint16_t dt, float scaler, float K_p, float K_i, float K_d + * + * Output: PID control value + * + ******************************************************************************/ + +static float pid(float error, float error_deriv, uint16_t dt, float scaler, float K_p, float K_i, float K_d, float intmax) +{ + // PID parameters + + float Kp = K_p; + float Ki = K_i; + float Kd = K_d; + float delta_time = dt; // delta time + float lerror; // last error value + float imax = intmax; // max integral value + float integrator; + float derivative; + float lderiv; + int fCut = 20; // anything above 20 Hz is considered noise - low pass filter for the derivative + float output = 0; // the output of the PID controller + + output += error * Kp; + + if ((fabs(Kd) > 0) && (dt > 0)) { + + if (PID_DERIVMODE_CALC) { + derivative = (error - lerror) / delta_time; + + // discrete low pass filter, cuts out the + // high frequency noise that can drive the controller crazy + float RC = 1 / (2 * M_PI * fCut); + derivative = lderiv + + (delta_time / (RC + delta_time)) * (derivative - lderiv); + + // update state + lerror = error; + lderiv = derivative; + + } else { + derivative = error_deriv; + } + + // add in derivative component + output += Kd * derivative; + } + + printf("PID derivative %i\n", (int)(1000 * derivative)); + + // scale the P and D components + output *= scaler; + + // Compute integral component if time has elapsed + if ((fabs(Ki) > 0) && (dt > 0)) { + integrator += (error * Ki) * scaler * delta_time; + + if (integrator < -imax) { + integrator = -imax; + + } else if (integrator > imax) { + integrator = imax; + } + + output += integrator; + } + + printf("PID Integrator %i\n", (int)(1000 * integrator)); + + return output; +} + diff --git a/apps/fixedwing_control/pid.h b/apps/fixedwing_control/pid.h new file mode 100644 index 0000000000..2f85c6c30a --- /dev/null +++ b/apps/fixedwing_control/pid.h @@ -0,0 +1,46 @@ +/**************************************************************************** + * pid.h + * + * Copyright (C) 2012 Ivan Ovinnikov. All rights reserved. + * Authors: Ivan Ovinnikov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + + +#ifndef PID_H_ +#define PID_H_ + +static float pid(float error, float error_deriv, uint16_t dt, float scaler, float K_p, float K_i, float K_d, float intmax); + +#endif /* PID_H_ */ diff --git a/apps/gps/.context b/apps/gps/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/gps/.gitignore b/apps/gps/.gitignore new file mode 100644 index 0000000000..a028271951 --- /dev/null +++ b/apps/gps/.gitignore @@ -0,0 +1,3 @@ +include +mavlink-* +pymavlink-* diff --git a/apps/gps/Makefile b/apps/gps/Makefile new file mode 100644 index 0000000000..7aaaf50cbc --- /dev/null +++ b/apps/gps/Makefile @@ -0,0 +1,59 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Makefile to build the GPS receiver application +# + +APPNAME = gps +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +CSRCS = gps.c \ + ubx.c \ + mtk.c \ + nmea_helper.c \ + nmealib/context.c \ + nmealib/generate.c \ + nmealib/generator.c \ + nmealib/gmath.c \ + nmealib/info.c \ + nmealib/parse.c \ + nmealib/parser.c \ + nmealib/sentence.c \ + nmealib/time.c \ + nmealib/tok.c + +INCLUDES = $(TOPDIR)/../mavlink/include/mavlink + +include $(APPDIR)/mk/app.mk diff --git a/apps/gps/gps.c b/apps/gps/gps.c new file mode 100644 index 0000000000..6d3ff0d6bf --- /dev/null +++ b/apps/gps/gps.c @@ -0,0 +1,505 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: Thomas Gubler + * Julian Oes + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* @file gps.c + * GPS app main loop. + */ + +#include "gps.h" + +#include +#include +#include +#include +#include +#include +#include "nmealib/nmea/nmea.h" // the nmea library +#include "nmea_helper.h" //header files for interacting with the nmea library +#include "mtk.h" //header files for the custom protocol for the mediatek diydrones chip +#include "ubx.h" //header files for the ubx protocol +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * GPS module readout and publishing. + * + * This function reads the onboard gps and publishes the vehicle_gps_positon topic. + * + * @see vehicle_gps_position_s + * @ingroup apps + */ +__EXPORT int gps_main(int argc, char *argv[]); + +/**************************************************************************** + * Definitions + ****************************************************************************/ +#define IMPORTANT_GPS_BAUD_RATES_N 2 +#define RETRY_INTERVAL_SECONDS 10 + +//gps_bin_ubx_state_t * ubx_state; +bool gps_mode_try_all; +bool gps_baud_try_all; +bool gps_mode_success; +bool terminate_gps_thread; +bool gps_verbose; +int current_gps_speed; + +enum GPS_MODES { + GPS_MODE_START = 0, + GPS_MODE_UBX = 1, + GPS_MODE_MTK = 2, + GPS_MODE_NMEA = 3, + GPS_MODE_END = 4 +}; + + + +#define AUTO_DETECTION_COUNT 8 +const int autodetection_baudrates[] = {B9600, B38400, B38400, B9600, B9600, B38400, B9600, B38400}; +const enum GPS_MODES autodetection_gpsmodes[] = {GPS_MODE_UBX, GPS_MODE_MTK, GPS_MODE_UBX, GPS_MODE_MTK, GPS_MODE_UBX, GPS_MODE_MTK, GPS_MODE_NMEA, GPS_MODE_NMEA}; //nmea is the fall-back if nothing else works, therefore we try the standard modes again before finally trying nmea + +/**************************************************************************** + * Private functions + ****************************************************************************/ +int open_port(char *port); + +void close_port(int fd); + +void setup_port(char *device, int speed, int *fd) +{ + + /* open port (baud rate is set in defconfig file) */ + *fd = open_port(device); + + if (*fd != -1) { + if (gps_verbose) printf("[gps] Port opened: %s at %d speed\r\n", device, speed); + + } else { + fprintf(stderr, "[gps] Could not open port, exiting gps app!\r\n"); + fflush(stdout); + } + + /* Try to set baud rate */ + struct termios uart_config; + int termios_state; + + if ((termios_state = tcgetattr(*fd, &uart_config)) < 0) { + fprintf(stderr, "[gps] ERROR getting baudrate / termios config for %s: %d\r\n", device, termios_state); + close(*fd); + } + + /* Set baud rate */ + cfsetispeed(&uart_config, speed); + cfsetospeed(&uart_config, speed); + + if ((termios_state = tcsetattr(*fd, TCSANOW, &uart_config)) < 0) { + fprintf(stderr, "[gps] ERROR setting baudrate / termios config for %s (tcsetattr)\r\n", device); + close(*fd); + } +} + + +/* + * Main function of gps app. + */ +int gps_main(int argc, char *argv[]) +{ + /* welcome message */ + printf("[gps] Initialized. Searching for GPS receiver..\n"); + + /* default values */ + const char *commandline_usage = "\tusage: %s -d devicename -b baudrate -m mode\n\tmodes are:\n\t\tubx\n\t\tmtkcustom\n\t\tnmea\n\t\tall\n"; + char *device = "/dev/ttyS3"; + char mode[10]; + strcpy(mode, "all"); + int baudrate = -1; + gps_mode_try_all = false; + gps_baud_try_all = false; + gps_mode_success = true; + terminate_gps_thread = false; + bool retry = false; + gps_verbose = false; + + int mavlink_fd = open(MAVLINK_LOG_DEVICE, 0); + + /* read arguments */ + int i; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { //device set + printf(commandline_usage, argv[0]); + return 0; + } + + if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--device") == 0) { //device set + if (argc > i + 1) { + device = argv[i + 1]; + + } else { + printf(commandline_usage, argv[0]); + return 0; + } + } + + if (strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--retry") == 0) { + if (argc > i + 1) { + retry = atoi(argv[i + 1]); + + } else { + printf(commandline_usage, argv[0]); + return 0; + } + } + + if (strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "--baud") == 0) { + if (argc > i + 1) { + baudrate = atoi(argv[i + 1]); + + } else { + printf(commandline_usage, argv[0]); + return 0; + } + } + + if (strcmp(argv[i], "-m") == 0 || strcmp(argv[i], "--mode") == 0) { + if (argc > i + 1) { + strcpy(mode, argv[i + 1]); + + } else { + printf(commandline_usage, argv[0]); + return 0; + } + } + + if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) { + gps_verbose = true; + } + } + + /* + * In case a baud rate is set only this baud rate will be tried, + * otherwise a array of usual baud rates for gps receivers is used + */ + + +// printf("baudrate = %d\n",baudrate); + switch (baudrate) { + case -1: gps_baud_try_all = true; break; + + case 0: current_gps_speed = B0; break; + + case 50: current_gps_speed = B50; break; + + case 75: current_gps_speed = B75; break; + + case 110: current_gps_speed = B110; break; + + case 134: current_gps_speed = B134; break; + + case 150: current_gps_speed = B150; break; + + case 200: current_gps_speed = B200; break; + + case 300: current_gps_speed = B300; break; + + case 600: current_gps_speed = B600; break; + + case 1200: current_gps_speed = B1200; break; + + case 1800: current_gps_speed = B1800; break; + + case 2400: current_gps_speed = B2400; break; + + case 4800: current_gps_speed = B4800; break; + + case 9600: current_gps_speed = B9600; break; + + case 19200: current_gps_speed = B19200; break; + + case 38400: current_gps_speed = B38400; break; + + case 57600: current_gps_speed = B57600; break; + + case 115200: current_gps_speed = B115200; break; + + case 230400: current_gps_speed = B230400; break; + + case 460800: current_gps_speed = B460800; break; + + case 921600: current_gps_speed = B921600; break; + + default: + fprintf(stderr, "[gps] ERROR: Unsupported baudrate: %d\n", baudrate); + fflush(stdout); + return -EINVAL; + } + + + enum GPS_MODES current_gps_mode = GPS_MODE_UBX; + + if (strcmp(mode, "ubx") == 0) { + current_gps_mode = GPS_MODE_UBX; + + } else if (strcmp(mode, "mtkcustom") == 0) { + current_gps_mode = GPS_MODE_MTK; + + } else if (strcmp(mode, "nmea") == 0) { + current_gps_mode = GPS_MODE_NMEA; + + } else if (strcmp(mode, "all") == 0) { + gps_mode_try_all = true; + + } else { + fprintf(stderr, "\t[gps] Invalid mode argument\n"); + printf(commandline_usage); + return ERROR; + } + + + while (true) { + /* Infinite retries or break if retry == false */ + + /* Loop over all configurations of baud rate and protocol */ + for (i = 0; i < AUTO_DETECTION_COUNT; i++) { + if (gps_mode_try_all) { + current_gps_mode = autodetection_gpsmodes[i]; + + if (false == gps_baud_try_all && autodetection_baudrates[i] != current_gps_speed) //there is no need to try modes which are not configured to run with the selcted baud rate + continue; + } + + if (gps_baud_try_all) { + current_gps_speed = autodetection_baudrates[i]; + + if (false == gps_mode_try_all && autodetection_gpsmodes[i] != current_gps_mode) //there is no need to try baud rates which are not usual for the selected mode + continue; + } + + + /* + * The watchdog_thread will return and set gps_mode_success to false if no data can be parsed. + * if the gps was once running the wtachdog thread will not return but instead try to reconfigure the gps (depending on the mode/protocol) + */ + + if (current_gps_mode == GPS_MODE_UBX) { //TODO: make a small enum with all modes to avoid all the strcpy + + if (gps_verbose) printf("[gps] Trying UBX mode at %d baud\n", current_gps_speed); + + mavlink_log_info(mavlink_fd, "GPS: trying to connect to a ubx module"); + + int fd; + setup_port(device, current_gps_speed, &fd); + + /* start ubx thread and watchdog */ + pthread_t ubx_thread; + pthread_t ubx_watchdog_thread; + + pthread_mutex_t ubx_mutex_d; + ubx_mutex = &ubx_mutex_d; + pthread_mutex_init(ubx_mutex, NULL); + gps_bin_ubx_state_t ubx_state_d; + ubx_state = &ubx_state_d; + ubx_decode_init(); + + pthread_attr_t ubx_loop_attr; + pthread_attr_init(&ubx_loop_attr); + pthread_attr_setstacksize(&ubx_loop_attr, 3000); + pthread_create(&ubx_thread, &ubx_loop_attr, ubx_loop, (void *)&fd); + sleep(2); // XXX TODO Check if this is too short, try to lower sleeps in UBX driver + + pthread_attr_t ubx_wd_attr; + pthread_attr_init(&ubx_wd_attr); + pthread_attr_setstacksize(&ubx_wd_attr, 1400); + int pthread_create_res = pthread_create(&ubx_watchdog_thread, &ubx_wd_attr, ubx_watchdog_loop, (void *)&fd); + + if (pthread_create_res != 0) fprintf(stderr, "[gps] ERROR: could not create ubx watchdog thread, pthread_create =%d\n", pthread_create_res); + + /* wait for threads to complete */ + pthread_join(ubx_watchdog_thread, NULL); + + if (gps_mode_success == false) { + if (gps_verbose) printf("[gps] no success with UBX mode and %d baud\n", current_gps_speed); + + terminate_gps_thread = true; + pthread_join(ubx_thread, NULL); + + gps_mode_success = true; + terminate_gps_thread = false; + } + + close_port(fd); + } + + if (current_gps_mode == GPS_MODE_MTK) { + if (gps_verbose) printf("[gps] trying MTK binary mode at %d baud\n", current_gps_speed); + + mavlink_log_info(mavlink_fd, "[gps] trying to connect to a MTK module"); + + + int fd; + setup_port(device, current_gps_speed, &fd); + + /* start mtk thread and watchdog */ + pthread_t mtk_thread; + pthread_t mtk_watchdog_thread; + + pthread_mutex_t mtk_mutex_d; + mtk_mutex = &mtk_mutex_d; + pthread_mutex_init(mtk_mutex, NULL); + + + gps_bin_mtk_state_t mtk_state_d; + mtk_state = &mtk_state_d; + mtk_decode_init(); + + + pthread_attr_t mtk_loop_attr; + pthread_attr_init(&mtk_loop_attr); + pthread_attr_setstacksize(&mtk_loop_attr, 2048); + pthread_create(&mtk_thread, &mtk_loop_attr, mtk_loop, (void *)&fd); + sleep(2); + pthread_create(&mtk_watchdog_thread, NULL, mtk_watchdog_loop, (void *)&fd); + + /* wait for threads to complete */ + pthread_join(mtk_watchdog_thread, (void *)&fd); + + if (gps_mode_success == false) { + if (gps_verbose) printf("[gps] No success with MTK binary mode and %d baud\n", current_gps_speed); + + terminate_gps_thread = true; + pthread_join(mtk_thread, NULL); + + // if(true == gps_mode_try_all) + // strcpy(mode, "nmea"); + + gps_mode_success = true; + terminate_gps_thread = false; + } + + close_port(fd); + + } + + if (current_gps_mode == GPS_MODE_NMEA) { + if (gps_verbose) printf("[gps] Trying NMEA mode at %d baud\n", current_gps_speed); + + mavlink_log_info(mavlink_fd, "[gps] trying to connect to a NMEA module"); + + int fd; + setup_port(device, current_gps_speed, &fd); + + /* start nmea thread and watchdog */ + pthread_t nmea_thread; + pthread_t nmea_watchdog_thread; + + pthread_mutex_t nmea_mutex_d; + nmea_mutex = &nmea_mutex_d; + pthread_mutex_init(nmea_mutex, NULL); + + gps_bin_nmea_state_t nmea_state_d; + nmea_state = &nmea_state_d; + + pthread_attr_t nmea_loop_attr; + pthread_attr_init(&nmea_loop_attr); + pthread_attr_setstacksize(&nmea_loop_attr, 4096); + pthread_create(&nmea_thread, &nmea_loop_attr, nmea_loop, (void *)&fd); + sleep(2); + pthread_create(&nmea_watchdog_thread, NULL, nmea_watchdog_loop, (void *)&fd); + + /* wait for threads to complete */ + pthread_join(nmea_watchdog_thread, (void *)&fd); + + if (gps_mode_success == false) { + if (gps_verbose) printf("[gps] No success with NMEA mode and %d baud\r\n", current_gps_speed); + + terminate_gps_thread = true; + pthread_join(nmea_thread, NULL); + + gps_mode_success = true; + terminate_gps_thread = false; + } + + close_port(fd); + } + + /* if both, mode and baud is set by argument, we only need one loop*/ + if (gps_mode_try_all == false && gps_baud_try_all == false) + break; + } + + if (retry) { + printf("[gps] No configuration was successful, retrying in %d seconds \n", RETRY_INTERVAL_SECONDS); + mavlink_log_info(mavlink_fd, "[gps] No configuration was successful, retrying..."); + fflush(stdout); + + } else { + fprintf(stderr, "[gps] No configuration was successful, exiting... \n"); + fflush(stdout); + mavlink_log_info(mavlink_fd, "[gps] No configuration was successful, exiting..."); + break; + } + + sleep(RETRY_INTERVAL_SECONDS); + } + + close(mavlink_fd); + + return ERROR; +} + +int open_port(char *port) +{ + int fd; /**< File descriptor for the gps port */ + + /* Open serial port */ + fd = open(port, O_CREAT | O_RDWR | O_NOCTTY); /* O_RDWR - Read and write O_NOCTTY - Ignore special chars like CTRL-C */ + return (fd); +} + + +void close_port(int fd) +{ + /* Close serial port */ + close(fd); +} + + + diff --git a/apps/gps/gps.h b/apps/gps/gps.h new file mode 100644 index 0000000000..313a3a2c2a --- /dev/null +++ b/apps/gps/gps.h @@ -0,0 +1,20 @@ +/* + * gps.h + * + * Created on: Mar 8, 2012 + * Author: thomasgubler + */ + +#ifndef GPS_H_ +#define GPS_H_ +/**************************************************************************** + * Included Files + ****************************************************************************/ + +int gps_fd; + +//extern gps_bin_ubx_state_t * ubx_state; + + + +#endif /* GPS_H_ */ diff --git a/apps/gps/mtk.c b/apps/gps/mtk.c new file mode 100644 index 0000000000..cef70601b3 --- /dev/null +++ b/apps/gps/mtk.c @@ -0,0 +1,423 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: Julian Oes + * Thomas Gubler + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* @file MTK custom binary (3DR) protocol implementation */ + +#include "mtk.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MTK_HEALTH_SUCCESS_COUNTER_LIMIT 2 +#define MTK_HEALTH_FAIL_COUNTER_LIMIT 2 + +// XXX decrease this substantially, it should be only a few dozen bytes max. +#warning XXX trying 128 for now +#define MTK_BUFFER_SIZE 128 + +pthread_mutex_t *mtk_mutex; +gps_bin_mtk_state_t *mtk_state; +static struct vehicle_gps_position_s *mtk_gps; + +extern bool gps_mode_try_all; +extern bool gps_mode_success; +extern bool terminate_gps_thread; +extern bool gps_baud_try_all; +extern bool gps_verbose; +extern int current_gps_speed; + + +void mtk_decode_init(void) +{ + mtk_state->ck_a = 0; + mtk_state->ck_b = 0; + mtk_state->rx_count = 0; + mtk_state->decode_state = MTK_DECODE_UNINIT; + mtk_state->print_errors = false; +} + +void mtk_checksum(uint8_t b, uint8_t *ck_a, uint8_t *ck_b) +{ + *(ck_a) = *(ck_a) + b; + *(ck_b) = *(ck_b) + *(ck_a); +// printf("Checksum now: %d\n",*(ck_b)); +} + + + +int mtk_parse(uint8_t b, char *gps_rx_buffer) +{ +// printf("b=%x\n",b); + // Debug output to telemetry port + // PIOS_COM_SendBufferNonBlocking(PIOS_COM_TELEM_RF, &b, 1); + if (mtk_state->decode_state == MTK_DECODE_UNINIT) { + + if (b == 0xd0) { + mtk_state->decode_state = MTK_DECODE_GOT_CK_A; + } + + } else if (mtk_state->decode_state == MTK_DECODE_GOT_CK_A) { + if (b == 0xdd) { + mtk_state->decode_state = MTK_DECODE_GOT_CK_B; + + } else { + // Second start symbol was wrong, reset state machine + mtk_decode_init(); + } + + } else if (mtk_state->decode_state == MTK_DECODE_GOT_CK_B) { + // Add to checksum + if (mtk_state->rx_count < 33) mtk_checksum(b, &(mtk_state->ck_a), &(mtk_state->ck_b)); + + // Fill packet buffer + gps_rx_buffer[mtk_state->rx_count] = b; + (mtk_state->rx_count)++; +// printf("Rx count: %d\n",mtk_state->rx_count); + uint8_t ret = 0; + + /* Packet size minus checksum */ + if (mtk_state->rx_count >= 35) { + gps_bin_mtk_packet_t *packet = (gps_bin_mtk_packet_t *) gps_rx_buffer; + + /* Check if checksum is valid */ + if (mtk_state->ck_a == packet->ck_a && mtk_state->ck_b == packet->ck_b) { + mtk_gps->lat = packet->latitude * 10; // mtk: degrees*1e6, mavlink/ubx: degrees*1e7 + mtk_gps->lon = packet->longitude * 10; // mtk: degrees*1e6, mavlink/ubx: degrees*1e7 + mtk_gps->alt = (int32_t)packet->msl_altitude * 10; // conversion from centimeters to millimeters, and from uint32_t to int16_t + mtk_gps->fix_type = packet->fix_type; + mtk_gps->eph = packet->hdop; + mtk_gps->epv = 65535; //unknown in mtk custom mode + mtk_gps->vel = packet->ground_speed; + mtk_gps->cog = 65535; //unknown in mtk custom mode + mtk_gps->satellites_visible = packet->satellites; + + /* convert time and date information to unix timestamp */ + struct tm timeinfo; //TODO: test this conversion + uint32_t timeinfo_conversion_temp; + + timeinfo.tm_mday = packet->date * 1e-4; + timeinfo_conversion_temp = packet->date - timeinfo.tm_mday * 1e4; + timeinfo.tm_mon = timeinfo_conversion_temp * 1e-2 - 1; + timeinfo.tm_year = (timeinfo_conversion_temp - (timeinfo.tm_mon + 1) * 1e2) + 100; + + timeinfo.tm_hour = packet->utc_time * 1e-7; + timeinfo_conversion_temp = packet->utc_time - timeinfo.tm_hour * 1e7; + timeinfo.tm_min = timeinfo_conversion_temp * 1e-5; + timeinfo_conversion_temp -= timeinfo.tm_min * 1e5; + timeinfo.tm_sec = timeinfo_conversion_temp * 1e-3; + timeinfo_conversion_temp -= timeinfo.tm_sec * 1e3; + time_t epoch = mktime(&timeinfo); + mtk_gps->timestamp = hrt_absolute_time(); + mtk_gps->time_gps_usec = epoch * 1e6; //TODO: test this + mtk_gps->time_gps_usec += timeinfo_conversion_temp * 1e3; + + mtk_gps->counter_pos_valid++; + + mtk_gps->timestamp = hrt_absolute_time(); + +// printf("%lu; %lu; %d.%d.%d %d:%d:%d:%d\n", packet->date, packet->utc_time,timeinfo.tm_year, timeinfo.tm_mon, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, timeinfo_conversion_temp); + + pthread_mutex_lock(mtk_mutex); +// printf("Write timestamp /n"); + mtk_state->last_message_timestamp = hrt_absolute_time(); + pthread_mutex_unlock(mtk_mutex); + + ret = 1; +// printf("found package\n"); + + } else { + if (gps_verbose) printf("[gps] Checksum invalid\r\n"); + + ret = 0; + } + + // Reset state machine to decode next packet + mtk_decode_init(); +// printf("prepared for next state\n"); + return ret; + } + } + + return 0; // no valid packet found + +} + +int read_gps_mtk(int fd, char *gps_rx_buffer, int buffer_size) // returns 1 if the thread should terminate +{ +// printf("in read_gps_mtk\n"); + uint8_t ret = 0; + + uint8_t c; + + int rx_count = 0; + int gpsRxOverflow = 0; + + struct pollfd fds; + fds.fd = fd; + fds.events = POLLIN; + + // This blocks the task until there is something on the buffer + while (1) { + //check if the thread should terminate + if (terminate_gps_thread == true) { +// printf("terminate_gps_thread=%u ", terminate_gps_thread); +// printf("exiting mtk thread\n"); +// fflush(stdout); + ret = 1; + break; + } + + if (poll(&fds, 1, 1000) > 0) { + if (read(fd, &c, 1) > 0) { +// printf("Read %x\n",c); + if (rx_count >= buffer_size) { + // The buffer is already full and we haven't found a valid NMEA sentence. + // Flush the buffer and note the overflow event. + gpsRxOverflow++; + rx_count = 0; + mtk_decode_init(); + + if (gps_verbose) printf("[gps] Buffer full\r\n"); + + } else { + //gps_rx_buffer[rx_count] = c; + rx_count++; + + } + + int msg_read = mtk_parse(c, gps_rx_buffer); + + if (msg_read > 0) { + // printf("Found sequence\n"); + break; + } + + } else { + break; + } + + } else { + break; + } + + } + + return ret; +} + +int configure_gps_mtk(int fd) +{ + int success = 0; + size_t result_write; + result_write = write(fd, MEDIATEK_REFRESH_RATE_10HZ, strlen(MEDIATEK_REFRESH_RATE_10HZ)); + + if (result_write != strlen(MEDIATEK_REFRESH_RATE_10HZ)) { + printf("[gps] Set update speed to 10 Hz failed\r\n"); + success = 1; + + } else { + if (gps_verbose) printf("[gps] Attempted to set update speed to 10 Hz..\r\n"); + } + + //set custom mode + result_write = write(fd, MEDIATEK_CUSTOM_BINARY_MODE, strlen(MEDIATEK_CUSTOM_BINARY_MODE)); + + if (result_write != strlen(MEDIATEK_CUSTOM_BINARY_MODE)) { + //global_data_send_subsystem_info(&mtk_present); + printf("[gps] Set MTK custom mode failed\r\n"); + success = 1; + + } else { + //global_data_send_subsystem_info(&mtk_present_enabled); + if (gps_verbose) printf("[gps] Attempted to set MTK custom mode..\r\n"); + } + + return success; +} + +void *mtk_loop(void *arg) +{ +// int oldstate; +// pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, oldstate); +// +// printf("in mtk loop\n"); + /* Set thread name */ + prctl(PR_SET_NAME, "gps mtk read", getpid()); + + /* Retrieve file descriptor */ + int fd = *((int *)arg); + + /* Initialize gps stuff */ +// int buffer_size = 1000; +// char * gps_rx_buffer = malloc(buffer_size*sizeof(char)); + char gps_rx_buffer[MTK_BUFFER_SIZE]; + + /* set parameters for mtk custom */ + + if (configure_gps_mtk(fd) != 0) { + printf("[gps] Could not write serial port..\r\n"); + + /* Write shared variable sys_status */ + + //global_data_send_subsystem_info(&mtk_present); + + } else { + if (gps_verbose) printf("[gps] Configuration finished, awaiting GPS data..\r\n"); + + + /* Write shared variable sys_status */ + + //global_data_send_subsystem_info(&mtk_present_enabled); + } + + /* advertise GPS topic */ + struct vehicle_gps_position_s mtk_gps_d; + mtk_gps = &mtk_gps_d; + int gps_handle = orb_advertise(ORB_ID(vehicle_gps_position), &mtk_gps); + + while (1) { + /* Parse a message from the gps receiver */ + if (OK == read_gps_mtk(fd, gps_rx_buffer, MTK_BUFFER_SIZE)) { + + /* publish new GPS position */ + orb_publish(ORB_ID(vehicle_gps_position), gps_handle, &mtk_gps); + + } else { + break; + } + + } + + return NULL; +} + +void *mtk_watchdog_loop(void *arg) +{ +// printf("in mtk watchdog loop\n"); + fflush(stdout); + + /* Set thread name */ + prctl(PR_SET_NAME, "gps mtk watchdog", getpid()); + + /* Retrieve file descriptor */ + int fd = *((int *)arg); + + bool mtk_healthy = false; + + uint8_t mtk_fail_count = 0; + uint8_t mtk_success_count = 0; + bool once_ok = false; + + int mavlink_fd = open(MAVLINK_LOG_DEVICE, 0); + + + while (1) { + fflush(stdout); + + /* if we have no update for a long time reconfigure gps */ + pthread_mutex_lock(mtk_mutex); + uint64_t timestamp_now = hrt_absolute_time(); + bool all_okay = true; + + if (timestamp_now - mtk_state->last_message_timestamp > MTK_WATCHDOG_CRITICAL_TIME_MICROSECONDS) { + all_okay = false; + } + + pthread_mutex_unlock(mtk_mutex); + + if (!all_okay) { +// printf("mtk unhealthy\n"); + mtk_fail_count++; + /* gps error */ +// if (err_skip_counter == 0) +// { +// printf("[gps] GPS module not connected or not responding..\n"); +// err_skip_counter = 20; +// } +// err_skip_counter--; + +// printf("gps_mode_try_all =%u, mtk_fail_count=%u, mtk_healthy=%u, once_ok=%u\n", gps_mode_try_all, mtk_fail_count, mtk_healthy, once_ok); + + /* If we have too many failures and another mode or baud should be tried, exit... */ + if ((gps_mode_try_all == true || gps_baud_try_all == true) && (mtk_fail_count >= MTK_HEALTH_FAIL_COUNTER_LIMIT) && (mtk_healthy == false) && once_ok == false) { + if (gps_verbose) printf("[gps] Connection attempt failed, no MTK module found\r\n"); + + gps_mode_success = false; + break; + } + + if (mtk_healthy && mtk_fail_count >= MTK_HEALTH_FAIL_COUNTER_LIMIT) { + printf("[gps] ERROR: MTK GPS module stopped responding\r\n"); + // global_data_send_subsystem_info(&mtk_present_enabled); + mavlink_log_critical(mavlink_fd, "[gps] MTK module stopped responding\n"); + mtk_healthy = false; + mtk_success_count = 0; + + } + + /* trying to reconfigure the gps configuration */ + configure_gps_mtk(fd); + fflush(stdout); + + } else { + /* gps healthy */ + mtk_success_count++; + + if (!mtk_healthy && mtk_success_count >= MTK_HEALTH_SUCCESS_COUNTER_LIMIT) { + printf("[gps] MTK module found, status ok (baud=%d)\r\n", current_gps_speed); + /* MTK never has sat info */ + // XXX Check if lock makes sense here + mtk_gps->satellite_info_available = 0; + // global_data_send_subsystem_info(&mtk_present_enabled_healthy); + mavlink_log_info(mavlink_fd, "[gps] MTK custom binary module found, status ok\n"); + mtk_healthy = true; + mtk_fail_count = 0; + once_ok = true; + } + } + + usleep(MTK_WATCHDOG_WAIT_TIME_MICROSECONDS); + } + + close(mavlink_fd); + + return NULL; +} diff --git a/apps/gps/mtk.h b/apps/gps/mtk.h new file mode 100644 index 0000000000..1c65a5865c --- /dev/null +++ b/apps/gps/mtk.h @@ -0,0 +1,98 @@ +/* + * mtk.h + * + * Created on: Mar 6, 2012 + * Author: thomasgubler + */ + +#ifndef MTK_H_ +#define MTK_H_ + +#include +#include +#include +#include +#include +#include +#include + +//Definition for mtk custom mode +#define MEDIATEK_REFRESH_RATE_4HZ "$PMTK220,250*29\r\n" //refresh rate - 4Hz - 250 milliseconds +#define MEDIATEK_REFRESH_RATE_5HZ "$PMTK220,200*2C\r\n" +#define MEDIATEK_REFRESH_RATE_10HZ "$PMTK220,100*2F\r\n" //refresh rate - 10Hz - 100 milliseconds +#define MEDIATEK_FACTORY_RESET "$PMTK104*37\r\n" //clear current settings +#define MEDIATEK_CUSTOM_BINARY_MODE "$PGCMD,16,0,0,0,0,0*6A\r\n" +#define MEDIATEK_FULL_COLD_RESTART "$PMTK104*37\r\n" +//#define NMEA_GGA_ENABLE "$PMTK314,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0*27\r\n" //Set GGA messages + +//definitions for watchdog +#define MTK_WATCHDOG_CRITICAL_TIME_MICROSECONDS 2000000 +#define MTK_WATCHDOG_WAIT_TIME_MICROSECONDS 800000 + + + + +// ************ +// the structure of the binary packet + +typedef struct { + uint8_t payload; ///< Number of payload bytes + int32_t latitude; ///< Latitude in degrees * 10^7 + int32_t longitude; ///< Longitude in degrees * 10^7 + uint32_t msl_altitude; ///< MSL altitude in meters * 10^2 + uint32_t ground_speed; ///< FIXME SPEC UNCLEAR + int32_t heading; + uint8_t satellites; + uint8_t fix_type; + uint32_t date; + uint32_t utc_time; + uint16_t hdop; + uint8_t ck_a; + uint8_t ck_b; +} __attribute__((__packed__)) type_gps_bin_mtk_packet; + +typedef type_gps_bin_mtk_packet gps_bin_mtk_packet_t; + +enum MTK_DECODE_STATES { + MTK_DECODE_UNINIT = 0, + MTK_DECODE_GOT_CK_A = 1, + MTK_DECODE_GOT_CK_B = 2 +}; + +typedef struct { + union { + uint16_t ck; + struct { + uint8_t ck_a; + uint8_t ck_b; + }; + }; + uint8_t decode_state; +// bool new_data; +// uint8_t fix; + bool print_errors; + int16_t rx_count; + + uint64_t last_message_timestamp; +} __attribute__((__packed__)) type_gps_bin_mtk_state; + +typedef type_gps_bin_mtk_state gps_bin_mtk_state_t; + +extern pthread_mutex_t *mtk_mutex; +extern gps_bin_mtk_state_t *mtk_state; + +void mtk_decode_init(void); + +void mtk_checksum(uint8_t b, uint8_t *ck_a, uint8_t *ck_b); + +int mtk_parse(uint8_t b, char *gps_rx_buffer); + +int read_gps_mtk(int fd, char *gps_rx_buffer, int buffer_size); + +int configure_gps_mtk(int fd); + +void *mtk_loop(void *arg); + +void *mtk_watchdog_loop(void *arg); + +#endif /* MTK_H_ */ diff --git a/apps/gps/nmea_helper.c b/apps/gps/nmea_helper.c new file mode 100644 index 0000000000..4b520d4036 --- /dev/null +++ b/apps/gps/nmea_helper.c @@ -0,0 +1,335 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: Julian Oes + * Thomas Gubler + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* @file NMEA protocol implementation */ + +#include "nmea_helper.h" +#include +#include +#include +#include +#include + +#define NMEA_HEALTH_SUCCESS_COUNTER_LIMIT 2 +#define NMEA_HEALTH_FAIL_COUNTER_LIMIT 2 + +#define NMEA_BUFFER_SIZE 1000 + +pthread_mutex_t *nmea_mutex; +gps_bin_nmea_state_t *nmea_state; +static struct vehicle_gps_position_s *nmea_gps; + +extern bool gps_mode_try_all; +extern bool gps_mode_success; +extern bool terminate_gps_thread; +extern bool gps_baud_try_all; +extern bool gps_verbose; +extern int current_gps_speed; + + +int read_gps_nmea(int fd, char *gps_rx_buffer, int buffer_size, nmeaINFO *info, nmeaPARSER *parser) +{ + int ret = 1; + char c; + int start_flag = 0; + int found_cr = 0; + int rx_count = 0; + int gpsRxOverflow = 0; + + struct pollfd fds; + fds.fd = fd; + fds.events = POLLIN; + + // NMEA or SINGLE-SENTENCE GPS mode + + + while (1) { + //check if the thread should terminate + if (terminate_gps_thread == true) { +// printf("terminate_gps_thread=%u ", terminate_gps_thread); +// printf("exiting mtk thread\n"); +// fflush(stdout); + ret = 2; + break; + } + + if (poll(&fds, 1, 1000) > 0) { + if (read(fd, &c, 1) > 0) { + // detect start while acquiring stream + // printf("Char = %c\n", c); + if (!start_flag && (c == '$')) { + start_flag = 1; + found_cr = 0; + rx_count = 0; + + } else if (!start_flag) { // keep looking for start sign + continue; + } + + if (rx_count >= buffer_size) { + // The buffer is already full and we haven't found a valid NMEA sentence. + // Flush the buffer and note the overflow event. + gpsRxOverflow++; + start_flag = 0; + found_cr = 0; + rx_count = 0; + + if (gps_verbose) printf("\t[gps] Buffer full\n"); + + } else { + // store chars in buffer + gps_rx_buffer[rx_count] = c; + rx_count++; + } + + // look for carriage return CR + if (start_flag && c == 0x0d) { + found_cr = 1; + } + + // and then look for line feed LF + if (start_flag && found_cr && c == 0x0a) { + // parse one NMEA line, use buffer up to rx_count + if (nmea_parse(parser, gps_rx_buffer, rx_count, info) > 0) { + ret = 0; + } + + break; + } + + } else { + break; + } + + } else { + break; + } + } + + + + // As soon as one NMEA message has been parsed, we break out of the loop and end here + return(ret); +} + + +/** + * \brief Convert NDEG (NMEA degree) to fractional degree + */ +float ndeg2degree(float val) +{ + float deg = ((int)(val / 100)); + val = deg + (val - deg * 100) / 60; + return val; +} + +void *nmea_loop(void *arg) +{ + /* Set thread name */ + prctl(PR_SET_NAME, "gps nmea read", getpid()); + + /* Retrieve file descriptor */ + int fd = *((int *)arg); + + /* Initialize gps stuff */ + nmeaINFO info_d; + nmeaINFO *info = &info_d; + char gps_rx_buffer[NMEA_BUFFER_SIZE]; + + /* gps parser (nmea) */ + nmeaPARSER parser; + nmea_parser_init(&parser); + nmea_zero_INFO(info); + + /* advertise GPS topic */ + struct vehicle_gps_position_s nmea_gps_d = {0}; + nmea_gps = &nmea_gps_d; + int gps_handle = orb_advertise(ORB_ID(vehicle_gps_position), nmea_gps); + + while (1) { + /* Parse a message from the gps receiver */ + uint8_t read_res = read_gps_nmea(fd, gps_rx_buffer, NMEA_BUFFER_SIZE, info, &parser); + + if (0 == read_res) { + + /* convert data, ready it for publishing */ + + /* convert nmea utc time to usec */ + struct tm timeinfo; + timeinfo.tm_year = info->utc.year; + timeinfo.tm_mon = info->utc.mon; + timeinfo.tm_mday = info->utc.day; + timeinfo.tm_hour = info->utc.hour; + timeinfo.tm_min = info->utc.min; + timeinfo.tm_sec = info->utc.sec; + + time_t epoch = mktime(&timeinfo); + + // printf("%d.%d.%d %d:%d:%d:%d\n", timeinfo.tm_year, timeinfo.tm_mon, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, info->utc.hsec); + + nmea_gps->timestamp = hrt_absolute_time(); + nmea_gps->time_gps_usec = epoch * 1e6 + info->utc.hsec * 1e4; + nmea_gps->fix_type = (uint8_t)info->fix; + nmea_gps->lat = (int32_t)ndeg2degree(info->lat) * 1e7; + nmea_gps->lon = (int32_t)ndeg2degree(info->lon) * 1e7; + nmea_gps->alt = (int32_t)(info->elv * 1e3); + nmea_gps->eph = (uint16_t)(info->HDOP * 100); //TODO:test scaling + nmea_gps->epv = (uint16_t)(info->VDOP * 100); //TODO:test scaling + nmea_gps->vel = (uint16_t)(info->speed * 1000 / 36); //*1000/3600*100 + nmea_gps->cog = 65535; + nmea_gps->satellites_visible = (uint8_t)info->satinfo.inview; + + int i = 0; + + /* Write info about individual satellites */ + for (i = 0; i < 12; i++) { + nmea_gps->satellite_prn[i] = (uint8_t)info->satinfo.sat[i].id; + nmea_gps->satellite_used[i] = (uint8_t)info->satinfo.sat[i].in_use; + nmea_gps->satellite_elevation[i] = (uint8_t)info->satinfo.sat[i].elv; + nmea_gps->satellite_azimuth[i] = (uint8_t)info->satinfo.sat[i].azimuth; + nmea_gps->satellite_snr[i] = (uint8_t)info->satinfo.sat[i].sig; + } + + if (nmea_gps->satellites_visible > 0) { + nmea_gps->satellite_info_available = 1; + + } else { + nmea_gps->satellite_info_available = 0; + } + + nmea_gps->counter_pos_valid++; + + nmea_gps->timestamp = hrt_absolute_time(); + nmea_gps->counter++; + + pthread_mutex_lock(nmea_mutex); + nmea_state->last_message_timestamp = hrt_absolute_time(); + pthread_mutex_unlock(nmea_mutex); + + /* publish new GPS position */ + orb_publish(ORB_ID(vehicle_gps_position), gps_handle, nmea_gps); + + } else if (read_res == 2) { //termination + /* de-advertise */ + close(gps_handle); + break; + } + + } + + //destroy gps parser + nmea_parser_destroy(&parser); + + return NULL; + +} + +void *nmea_watchdog_loop(void *arg) +{ + /* Set thread name */ + prctl(PR_SET_NAME, "gps nmea watchdog", getpid()); + + bool nmea_healthy = false; + + uint8_t nmea_fail_count = 0; + uint8_t nmea_success_count = 0; + bool once_ok = false; + + int mavlink_fd = open(MAVLINK_LOG_DEVICE, 0); + + while (1) { +// printf("nmea_watchdog_loop : while "); + /* if we have no update for a long time print warning (in nmea mode there is no reconfigure) */ + pthread_mutex_lock(nmea_mutex); + uint64_t timestamp_now = hrt_absolute_time(); + bool all_okay = true; + + if (timestamp_now - nmea_state->last_message_timestamp > NMEA_WATCHDOG_CRITICAL_TIME_MICROSECONDS) { + all_okay = false; + } + + pthread_mutex_unlock(nmea_mutex); + + if (!all_okay) { + /* gps error */ + nmea_fail_count++; +// printf("nmea error, nmea_fail_count=%u\n", nmea_fail_count); +// fflush(stdout); + + /* If we have too many failures and another mode or baud should be tried, exit... */ + if ((gps_mode_try_all == true || gps_baud_try_all == true) && (nmea_fail_count >= NMEA_HEALTH_FAIL_COUNTER_LIMIT) && (nmea_healthy == false) && once_ok == false) { + if (gps_verbose) printf("\t[gps] no NMEA module found\n"); + + gps_mode_success = false; + break; + } + + if (nmea_healthy && nmea_fail_count >= NMEA_HEALTH_FAIL_COUNTER_LIMIT) { + printf("\t[gps] ERROR: NMEA GPS module stopped responding\n"); + // global_data_send_subsystem_info(&nmea_present_enabled); + mavlink_log_critical(mavlink_fd, "[gps] NMEA module stopped responding\n"); + nmea_healthy = false; + nmea_success_count = 0; + + } + + + + fflush(stdout); + sleep(1); + + } else { + /* gps healthy */ +// printf("\t[gps] nmea success\n"); + nmea_success_count++; + + if (!nmea_healthy && nmea_success_count >= NMEA_HEALTH_SUCCESS_COUNTER_LIMIT) { + printf("[gps] NMEA module found, status ok (baud=%d)\r\n", current_gps_speed); + // global_data_send_subsystem_info(&nmea_present_enabled_healthy); + mavlink_log_info(mavlink_fd, "[gps] NMEA module found, status ok\n"); + nmea_healthy = true; + nmea_fail_count = 0; + once_ok = true; + } + + } + + usleep(NMEA_WATCHDOG_WAIT_TIME_MICROSECONDS); + } + + close(mavlink_fd); + + return NULL; +} diff --git a/apps/gps/nmea_helper.h b/apps/gps/nmea_helper.h new file mode 100644 index 0000000000..8fd630bcd3 --- /dev/null +++ b/apps/gps/nmea_helper.h @@ -0,0 +1,47 @@ +/* + * nmea_helper.h + * + * Created on: Mar 15, 2012 + * Author: thomasgubler + */ + +#ifndef NMEA_H_ +#define NMEA_H_ + +#include +#include +#include +#include +#include "nmealib/nmea/nmea.h" + + +//definitions for watchdog +#define NMEA_WATCHDOG_CRITICAL_TIME_MICROSECONDS 2000000 +#define NMEA_WATCHDOG_WAIT_TIME_MICROSECONDS 800000 + +typedef struct { + uint64_t last_message_timestamp; +} __attribute__((__packed__)) type_gps_bin_nmea_state; + +typedef type_gps_bin_nmea_state gps_bin_nmea_state_t; + +extern gps_bin_nmea_state_t *nmea_state; +extern pthread_mutex_t *nmea_mutex; + + + +int read_gps_nmea(int fd, char *gps_rx_buffer, int buffer_size, nmeaINFO *info, nmeaPARSER *parser); + +void *nmea_loop(void *arg); + +void *nmea_watchdog_loop(void *arg); + +/** + * \brief Convert NDEG (NMEA degree) to fractional degree + */ +float ndeg2degree(float val); + +void nmea_init(void); + + +#endif /* NMEA_H_ */ diff --git a/apps/gps/nmealib/LICENSE.TXT b/apps/gps/nmealib/LICENSE.TXT new file mode 100644 index 0000000000..807db79166 --- /dev/null +++ b/apps/gps/nmealib/LICENSE.TXT @@ -0,0 +1,506 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + + + diff --git a/apps/gps/nmealib/README.TXT b/apps/gps/nmealib/README.TXT new file mode 100644 index 0000000000..8ede6a0366 --- /dev/null +++ b/apps/gps/nmealib/README.TXT @@ -0,0 +1,26 @@ +NMEA library see: http://nmea.sourceforge.net/ + +Disclaimer + +The National Marine Electronics Association (NMEA) has developed a specification that defines the interface between various pieces of marine electronic equipment. The standard permits marine electronics to send information to computers and to other marine equipment. +Most computer programs that provide real time position information understand and expect data to be in NMEA format. This data includes the complete PVT (position, velocity, time) solution computed by the GPS receiver. The idea of NMEA is to send a line of data called a sentence that is totally self contained and independent from other sentences. All NMEA sentences is sequences of ACSII symbols begins with a '$' and ends with a carriage return/line feed sequence and can be no longer than 80 characters of visible text (plus the line terminators). + +Introduction + +We present library in 'C' programming language for work with NMEA protocol. Small and easy to use. The library build on different compilers under different platforms (see below). The code was tested in real projects. Just download and try... + +Features + +- Analysis NMEA sentences and granting GPS data in C structures +- Generate NMEA sentences +- Supported sentences: GPGGA, GPGSA, GPGSV, GPRMC, GPVTG +- Multilevel architecture of algorithms +- Additional functions of geographical mathematics and work with navigation data + +Supported (tested) platforms + +- Microsoft Windows (MS Visual Studio 8.0, GCC) +- Windows Mobile, Windows CE (MS Visual Studio 8.0) +- UNIX (GCC) + +Licence: LGPL diff --git a/apps/gps/nmealib/context.c b/apps/gps/nmealib/context.c new file mode 100644 index 0000000000..6ee2f5ad3d --- /dev/null +++ b/apps/gps/nmealib/context.c @@ -0,0 +1,67 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: context.c 17 2008-03-11 11:56:11Z xtimor $ + * + */ + +#include "nmea/context.h" + +#include +#include +#include + +nmeaPROPERTY * nmea_property(void) +{ + static nmeaPROPERTY prop = { + 0, 0, NMEA_DEF_PARSEBUFF + }; + + return ∝ +} + +void nmea_trace(const char *str, ...) +{ + int size; + va_list arg_list; + char buff[NMEA_DEF_PARSEBUFF]; + nmeaTraceFunc func = nmea_property()->trace_func; + + if(func) + { + va_start(arg_list, str); + size = NMEA_POSIX(vsnprintf)(&buff[0], NMEA_DEF_PARSEBUFF - 1, str, arg_list); + va_end(arg_list); + + if(size > 0) + (*func)(&buff[0], size); + } +} + +void nmea_trace_buff(const char *buff, int buff_size) +{ + nmeaTraceFunc func = nmea_property()->trace_func; + if(func && buff_size) + (*func)(buff, buff_size); +} + +void nmea_error(const char *str, ...) +{ + int size; + va_list arg_list; + char buff[NMEA_DEF_PARSEBUFF]; + nmeaErrorFunc func = nmea_property()->error_func; + + if(func) + { + va_start(arg_list, str); + size = NMEA_POSIX(vsnprintf)(&buff[0], NMEA_DEF_PARSEBUFF - 1, str, arg_list); + va_end(arg_list); + + if(size > 0) + (*func)(&buff[0], size); + } +} diff --git a/apps/gps/nmealib/generate.c b/apps/gps/nmealib/generate.c new file mode 100644 index 0000000000..4c9389300a --- /dev/null +++ b/apps/gps/nmealib/generate.c @@ -0,0 +1,229 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: generate.c 17 2008-03-11 11:56:11Z xtimor $ + * + */ + +#include "nmea/tok.h" +#include "nmea/sentence.h" +#include "nmea/generate.h" +#include "nmea/units.h" + +#include +#include +#include + +int nmea_gen_GPGGA(char *buff, int buff_sz, nmeaGPGGA *pack) +{ + return nmea_printf(buff, buff_sz, + "$GPGGA,%02d%02d%02d.%02d,%07.4f,%C,%07.4f,%C,%1d,%02d,%03.1f,%03.1f,%C,%03.1f,%C,%03.1f,%04d", + pack->utc.hour, pack->utc.min, pack->utc.sec, pack->utc.hsec, + pack->lat, pack->ns, pack->lon, pack->ew, + pack->sig, pack->satinuse, pack->HDOP, pack->elv, pack->elv_units, + pack->diff, pack->diff_units, pack->dgps_age, pack->dgps_sid); +} + +int nmea_gen_GPGSA(char *buff, int buff_sz, nmeaGPGSA *pack) +{ + return nmea_printf(buff, buff_sz, + "$GPGSA,%C,%1d,%02d,%02d,%02d,%02d,%02d,%02d,%02d,%02d,%02d,%02d,%02d,%02d,%03.1f,%03.1f,%03.1f", + pack->fix_mode, pack->fix_type, + pack->sat_prn[0], pack->sat_prn[1], pack->sat_prn[2], pack->sat_prn[3], pack->sat_prn[4], pack->sat_prn[5], + pack->sat_prn[6], pack->sat_prn[7], pack->sat_prn[8], pack->sat_prn[9], pack->sat_prn[10], pack->sat_prn[11], + pack->PDOP, pack->HDOP, pack->VDOP); +} + +int nmea_gen_GPGSV(char *buff, int buff_sz, nmeaGPGSV *pack) +{ + return nmea_printf(buff, buff_sz, + "$GPGSV,%1d,%1d,%02d," + "%02d,%02d,%03d,%02d," + "%02d,%02d,%03d,%02d," + "%02d,%02d,%03d,%02d," + "%02d,%02d,%03d,%02d", + pack->pack_count, pack->pack_index + 1, pack->sat_count, + pack->sat_data[0].id, pack->sat_data[0].elv, pack->sat_data[0].azimuth, pack->sat_data[0].sig, + pack->sat_data[1].id, pack->sat_data[1].elv, pack->sat_data[1].azimuth, pack->sat_data[1].sig, + pack->sat_data[2].id, pack->sat_data[2].elv, pack->sat_data[2].azimuth, pack->sat_data[2].sig, + pack->sat_data[3].id, pack->sat_data[3].elv, pack->sat_data[3].azimuth, pack->sat_data[3].sig); +} + +int nmea_gen_GPRMC(char *buff, int buff_sz, nmeaGPRMC *pack) +{ + return nmea_printf(buff, buff_sz, + "$GPRMC,%02d%02d%02d.%02d,%C,%07.4f,%C,%07.4f,%C,%03.1f,%03.1f,%02d%02d%02d,%03.1f,%C,%C", + pack->utc.hour, pack->utc.min, pack->utc.sec, pack->utc.hsec, + pack->status, pack->lat, pack->ns, pack->lon, pack->ew, + pack->speed, pack->direction, + pack->utc.day, pack->utc.mon + 1, pack->utc.year - 100, + pack->declination, pack->declin_ew, pack->mode); +} + +int nmea_gen_GPVTG(char *buff, int buff_sz, nmeaGPVTG *pack) +{ + return nmea_printf(buff, buff_sz, + "$GPVTG,%.1f,%C,%.1f,%C,%.1f,%C,%.1f,%C", + pack->dir, pack->dir_t, + pack->dec, pack->dec_m, + pack->spn, pack->spn_n, + pack->spk, pack->spk_k); +} + +void nmea_info2GPGGA(const nmeaINFO *info, nmeaGPGGA *pack) +{ + nmea_zero_GPGGA(pack); + + pack->utc = info->utc; + pack->lat = fabs(info->lat); + pack->ns = ((info->lat > 0)?'N':'S'); + pack->lon = fabs(info->lon); + pack->ew = ((info->lon > 0)?'E':'W'); + pack->sig = info->sig; + pack->satinuse = info->satinfo.inuse; + pack->HDOP = info->HDOP; + pack->elv = info->elv; +} + +void nmea_info2GPGSA(const nmeaINFO *info, nmeaGPGSA *pack) +{ + int it; + + nmea_zero_GPGSA(pack); + + pack->fix_type = info->fix; + pack->PDOP = info->PDOP; + pack->HDOP = info->HDOP; + pack->VDOP = info->VDOP; + + for(it = 0; it < NMEA_MAXSAT; ++it) + { + pack->sat_prn[it] = + ((info->satinfo.sat[it].in_use)?info->satinfo.sat[it].id:0); + } +} + +int nmea_gsv_npack(int sat_count) +{ + int pack_count = (int)ceil(((float)sat_count) / NMEA_SATINPACK); + + if(0 == pack_count) + pack_count = 1; + + return pack_count; +} + +void nmea_info2GPGSV(const nmeaINFO *info, nmeaGPGSV *pack, int pack_idx) +{ + int sit, pit; + + nmea_zero_GPGSV(pack); + + pack->sat_count = (info->satinfo.inview <= NMEA_MAXSAT)?info->satinfo.inview:NMEA_MAXSAT; + pack->pack_count = nmea_gsv_npack(pack->sat_count); + + if(pack->pack_count == 0) + pack->pack_count = 1; + + if(pack_idx >= pack->pack_count) + pack->pack_index = pack_idx % pack->pack_count; + else + pack->pack_index = pack_idx; + + for(pit = 0, sit = pack->pack_index * NMEA_SATINPACK; pit < NMEA_SATINPACK; ++pit, ++sit) + pack->sat_data[pit] = info->satinfo.sat[sit]; +} + +void nmea_info2GPRMC(const nmeaINFO *info, nmeaGPRMC *pack) +{ + nmea_zero_GPRMC(pack); + + pack->utc = info->utc; + pack->status = ((info->sig > 0)?'A':'V'); + pack->lat = fabs(info->lat); + pack->ns = ((info->lat > 0)?'N':'S'); + pack->lon = fabs(info->lon); + pack->ew = ((info->lon > 0)?'E':'W'); + pack->speed = info->speed / NMEA_TUD_KNOTS; + pack->direction = info->direction; + pack->declination = info->declination; + pack->declin_ew = 'E'; + pack->mode = ((info->sig > 0)?'A':'N'); +} + +void nmea_info2GPVTG(const nmeaINFO *info, nmeaGPVTG *pack) +{ + nmea_zero_GPVTG(pack); + + pack->dir = info->direction; + pack->dec = info->declination; + pack->spn = info->speed / NMEA_TUD_KNOTS; + pack->spk = info->speed; +} + +int nmea_generate( + char *buff, int buff_sz, + const nmeaINFO *info, + int generate_mask + ) +{ + int gen_count = 0, gsv_it, gsv_count; + int pack_mask = generate_mask; + + nmeaGPGGA gga; + nmeaGPGSA gsa; + nmeaGPGSV gsv; + nmeaGPRMC rmc; + nmeaGPVTG vtg; + + if(!buff) + return 0; + + while(pack_mask) + { + if(pack_mask & GPGGA) + { + nmea_info2GPGGA(info, &gga); + gen_count += nmea_gen_GPGGA(buff + gen_count, buff_sz - gen_count, &gga); + pack_mask &= ~GPGGA; + } + else if(pack_mask & GPGSA) + { + nmea_info2GPGSA(info, &gsa); + gen_count += nmea_gen_GPGSA(buff + gen_count, buff_sz - gen_count, &gsa); + pack_mask &= ~GPGSA; + } + else if(pack_mask & GPGSV) + { + gsv_count = nmea_gsv_npack(info->satinfo.inview); + for(gsv_it = 0; gsv_it < gsv_count && buff_sz - gen_count > 0; ++gsv_it) + { + nmea_info2GPGSV(info, &gsv, gsv_it); + gen_count += nmea_gen_GPGSV(buff + gen_count, buff_sz - gen_count, &gsv); + } + pack_mask &= ~GPGSV; + } + else if(pack_mask & GPRMC) + { + nmea_info2GPRMC(info, &rmc); + gen_count += nmea_gen_GPRMC(buff + gen_count, buff_sz - gen_count, &rmc); + pack_mask &= ~GPRMC; + } + else if(pack_mask & GPVTG) + { + nmea_info2GPVTG(info, &vtg); + gen_count += nmea_gen_GPVTG(buff + gen_count, buff_sz - gen_count, &vtg); + pack_mask &= ~GPVTG; + } + else + break; + + if(buff_sz - gen_count <= 0) + break; + } + + return gen_count; +} diff --git a/apps/gps/nmealib/generator.c b/apps/gps/nmealib/generator.c new file mode 100644 index 0000000000..ce40b0f1a0 --- /dev/null +++ b/apps/gps/nmealib/generator.c @@ -0,0 +1,399 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: generator.c 17 2008-03-11 11:56:11Z xtimor $ + * + */ + +#include "nmea/gmath.h" +#include "nmea/generate.h" +#include "nmea/generator.h" +#include "nmea/context.h" + +#include +#include + +#if defined(NMEA_WIN) && defined(_MSC_VER) +# pragma warning(disable: 4100) /* unreferenced formal parameter */ +#endif + +float nmea_random(float min, float max) +{ + static float rand_max = MAX_RAND;//RAND_MAX; //nuttx defines MAX_RAND instead of RAND_MAX + float rand_val = rand(); + float bounds = max - min; + return min + (rand_val * bounds) / rand_max; +} + +/* + * low level + */ + +int nmea_gen_init(nmeaGENERATOR *gen, nmeaINFO *info) +{ + int RetVal = 1; int smask = info->smask; + nmeaGENERATOR *igen = gen; + + nmea_zero_INFO(info); + info->smask = smask; + + info->lat = NMEA_DEF_LAT; + info->lon = NMEA_DEF_LON; + + while(RetVal && igen) + { + if(igen->init_call) + RetVal = (*igen->init_call)(igen, info); + igen = igen->next; + } + + return RetVal; +} + +int nmea_gen_loop(nmeaGENERATOR *gen, nmeaINFO *info) +{ + int RetVal = 1; + + if(gen->loop_call) + RetVal = (*gen->loop_call)(gen, info); + + if(RetVal && gen->next) + RetVal = nmea_gen_loop(gen->next, info); + + return RetVal; +} + +int nmea_gen_reset(nmeaGENERATOR *gen, nmeaINFO *info) +{ + int RetVal = 1; + + if(gen->reset_call) + RetVal = (*gen->reset_call)(gen, info); + + return RetVal; +} + +void nmea_gen_destroy(nmeaGENERATOR *gen) +{ + if(gen->next) + { + nmea_gen_destroy(gen->next); + gen->next = 0; + } + + if(gen->destroy_call) + (*gen->destroy_call)(gen); + + free(gen); +} + +void nmea_gen_add(nmeaGENERATOR *to, nmeaGENERATOR *gen) +{ + if(to->next) + nmea_gen_add(to->next, gen); + else + to->next = gen; +} + +int nmea_generate_from( + char *buff, int buff_sz, + nmeaINFO *info, + nmeaGENERATOR *gen, + int generate_mask + ) +{ + int retval; + + if(0 != (retval = nmea_gen_loop(gen, info))) + retval = nmea_generate(buff, buff_sz, info, generate_mask); + + return retval; +} + +/* + * NOISE generator + */ + +int nmea_igen_noise_init(nmeaGENERATOR *gen, nmeaINFO *info) +{ + return 1; +} + +int nmea_igen_noise_loop(nmeaGENERATOR *gen, nmeaINFO *info) +{ + int it; + int in_use; + + info->sig = (int)nmea_random(1, 3); + info->PDOP = nmea_random(0, 9); + info->HDOP = nmea_random(0, 9); + info->VDOP = nmea_random(0, 9); + info->fix = (int)nmea_random(2, 3); + info->lat = nmea_random(0, 100); + info->lon = nmea_random(0, 100); + info->speed = nmea_random(0, 100); + info->direction = nmea_random(0, 360); + info->declination = nmea_random(0, 360); + info->elv = (int)nmea_random(-100, 100); + + info->satinfo.inuse = 0; + info->satinfo.inview = 0; + + for(it = 0; it < 12; ++it) + { + info->satinfo.sat[it].id = it; + info->satinfo.sat[it].in_use = in_use = (int)nmea_random(0, 3); + info->satinfo.sat[it].elv = (int)nmea_random(0, 90); + info->satinfo.sat[it].azimuth = (int)nmea_random(0, 359); + info->satinfo.sat[it].sig = (int)(in_use?nmea_random(40, 99):nmea_random(0, 40)); + + if(in_use) + info->satinfo.inuse++; + if(info->satinfo.sat[it].sig > 0) + info->satinfo.inview++; + } + + return 1; +} + +int nmea_igen_noise_reset(nmeaGENERATOR *gen, nmeaINFO *info) +{ + return 1; +} + +/* + * STATIC generator + */ + +int nmea_igen_static_loop(nmeaGENERATOR *gen, nmeaINFO *info) +{ + nmea_time_now(&info->utc); + return 1; +}; + +int nmea_igen_static_reset(nmeaGENERATOR *gen, nmeaINFO *info) +{ + info->satinfo.inuse = 4; + info->satinfo.inview = 4; + + info->satinfo.sat[0].id = 1; + info->satinfo.sat[0].in_use = 1; + info->satinfo.sat[0].elv = 50; + info->satinfo.sat[0].azimuth = 0; + info->satinfo.sat[0].sig = 99; + + info->satinfo.sat[1].id = 2; + info->satinfo.sat[1].in_use = 1; + info->satinfo.sat[1].elv = 50; + info->satinfo.sat[1].azimuth = 90; + info->satinfo.sat[1].sig = 99; + + info->satinfo.sat[2].id = 3; + info->satinfo.sat[2].in_use = 1; + info->satinfo.sat[2].elv = 50; + info->satinfo.sat[2].azimuth = 180; + info->satinfo.sat[2].sig = 99; + + info->satinfo.sat[3].id = 4; + info->satinfo.sat[3].in_use = 1; + info->satinfo.sat[3].elv = 50; + info->satinfo.sat[3].azimuth = 270; + info->satinfo.sat[3].sig = 99; + + return 1; +} + +int nmea_igen_static_init(nmeaGENERATOR *gen, nmeaINFO *info) +{ + info->sig = 3; + info->fix = 3; + + nmea_igen_static_reset(gen, info); + + return 1; +} + +/* + * SAT_ROTATE generator + */ + +int nmea_igen_rotate_loop(nmeaGENERATOR *gen, nmeaINFO *info) +{ + int it; + int count = info->satinfo.inview; + float deg = 360 / (count?count:1); + float srt = (count?(info->satinfo.sat[0].azimuth):0) + 5; + + nmea_time_now(&info->utc); + + for(it = 0; it < count; ++it) + { + info->satinfo.sat[it].azimuth = + (int)((srt >= 360)?srt - 360:srt); + srt += deg; + } + + return 1; +}; + +int nmea_igen_rotate_reset(nmeaGENERATOR *gen, nmeaINFO *info) +{ + int it; + float deg = 360 / 8; + float srt = 0; + + info->satinfo.inuse = 8; + info->satinfo.inview = 8; + + for(it = 0; it < info->satinfo.inview; ++it) + { + info->satinfo.sat[it].id = it + 1; + info->satinfo.sat[it].in_use = 1; + info->satinfo.sat[it].elv = 5; + info->satinfo.sat[it].azimuth = (int)srt; + info->satinfo.sat[it].sig = 80; + srt += deg; + } + + return 1; +} + +int nmea_igen_rotate_init(nmeaGENERATOR *gen, nmeaINFO *info) +{ + info->sig = 3; + info->fix = 3; + + nmea_igen_rotate_reset(gen, info); + + return 1; +} + +/* + * POS_RANDMOVE generator + */ + +int nmea_igen_pos_rmove_init(nmeaGENERATOR *gen, nmeaINFO *info) +{ + info->sig = 3; + info->fix = 3; + info->direction = info->declination = 0; + info->speed = 20; + return 1; +} + +int nmea_igen_pos_rmove_loop(nmeaGENERATOR *gen, nmeaINFO *info) +{ + nmeaPOS crd; + + info->direction += nmea_random(-10, 10); + info->speed += nmea_random(-2, 3); + + if(info->direction < 0) + info->direction = 359 + info->direction; + if(info->direction > 359) + info->direction -= 359; + + if(info->speed > 40) + info->speed = 40; + if(info->speed < 1) + info->speed = 1; + + nmea_info2pos(info, &crd); + nmea_move_horz(&crd, &crd, info->direction, info->speed / 3600); + nmea_pos2info(&crd, info); + + info->declination = info->direction; + + return 1; +}; + +int nmea_igen_pos_rmove_destroy(nmeaGENERATOR *gen) +{ + return 1; +}; + +/* + * generator create + */ + +nmeaGENERATOR * __nmea_create_generator(int type, nmeaINFO *info) +{ + nmeaGENERATOR *gen = 0; + + switch(type) + { + case NMEA_GEN_NOISE: + if(0 == (gen = malloc(sizeof(nmeaGENERATOR)))) + nmea_error("Insufficient memory!"); + else + { + memset(gen, 0, sizeof(nmeaGENERATOR)); + gen->init_call = &nmea_igen_noise_init; + gen->loop_call = &nmea_igen_noise_loop; + gen->reset_call = &nmea_igen_noise_reset; + } + break; + case NMEA_GEN_STATIC: + case NMEA_GEN_SAT_STATIC: + if(0 == (gen = malloc(sizeof(nmeaGENERATOR)))) + nmea_error("Insufficient memory!"); + else + { + memset(gen, 0, sizeof(nmeaGENERATOR)); + gen->init_call = &nmea_igen_static_init; + gen->loop_call = &nmea_igen_static_loop; + gen->reset_call = &nmea_igen_static_reset; + } + break; + case NMEA_GEN_SAT_ROTATE: + if(0 == (gen = malloc(sizeof(nmeaGENERATOR)))) + nmea_error("Insufficient memory!"); + else + { + memset(gen, 0, sizeof(nmeaGENERATOR)); + gen->init_call = &nmea_igen_rotate_init; + gen->loop_call = &nmea_igen_rotate_loop; + gen->reset_call = &nmea_igen_rotate_reset; + } + break; + case NMEA_GEN_POS_RANDMOVE: + if(0 == (gen = malloc(sizeof(nmeaGENERATOR)))) + nmea_error("Insufficient memory!"); + else + { + memset(gen, 0, sizeof(nmeaGENERATOR)); + gen->init_call = &nmea_igen_pos_rmove_init; + gen->loop_call = &nmea_igen_pos_rmove_loop; + gen->destroy_call = &nmea_igen_pos_rmove_destroy; + } + break; + case NMEA_GEN_ROTATE: + gen = __nmea_create_generator(NMEA_GEN_SAT_ROTATE, info); + nmea_gen_add(gen, __nmea_create_generator(NMEA_GEN_POS_RANDMOVE, info)); + break; + }; + + return gen; +} + +nmeaGENERATOR * nmea_create_generator(int type, nmeaINFO *info) +{ + nmeaGENERATOR *gen = __nmea_create_generator(type, info); + + if(gen) + nmea_gen_init(gen, info); + + return gen; +} + +void nmea_destroy_generator(nmeaGENERATOR *gen) +{ + nmea_gen_destroy(gen); +} + +#if defined(NMEA_WIN) && defined(_MSC_VER) +# pragma warning(default: 4100) +#endif diff --git a/apps/gps/nmealib/gmath.c b/apps/gps/nmealib/gmath.c new file mode 100644 index 0000000000..327b982efe --- /dev/null +++ b/apps/gps/nmealib/gmath.c @@ -0,0 +1,376 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: gmath.c 17 2008-03-11 11:56:11Z xtimor $ + * + */ + +/*! \file gmath.h */ +#include "nmea/gmath.h" + +#include +#include + +/** + * \fn nmea_degree2radian + * \brief Convert degree to radian + */ +float nmea_degree2radian(float val) +{ return (val * NMEA_PI180); } + +/** + * \fn nmea_radian2degree + * \brief Convert radian to degree + */ +float nmea_radian2degree(float val) +{ return (val / NMEA_PI180); } + +/** + * \brief Convert NDEG (NMEA degree) to fractional degree + */ +float nmea_ndeg2degree(float val) +{ + float deg = ((int)(val / 100)); + val = deg + (val - deg * 100) / 60; + return val; +} + +/** + * \brief Convert fractional degree to NDEG (NMEA degree) + */ +float nmea_degree2ndeg(float val) +{ + float int_part; + float fra_part; + fra_part = modf(val, &int_part); + val = int_part * 100 + fra_part * 60; + return val; +} + +/** + * \fn nmea_ndeg2radian + * \brief Convert NDEG (NMEA degree) to radian + */ +float nmea_ndeg2radian(float val) +{ return nmea_degree2radian(nmea_ndeg2degree(val)); } + +/** + * \fn nmea_radian2ndeg + * \brief Convert radian to NDEG (NMEA degree) + */ +float nmea_radian2ndeg(float val) +{ return nmea_degree2ndeg(nmea_radian2degree(val)); } + +/** + * \brief Calculate PDOP (Position Dilution Of Precision) factor + */ +float nmea_calc_pdop(float hdop, float vdop) +{ + return sqrt(pow(hdop, 2) + pow(vdop, 2)); +} + +float nmea_dop2meters(float dop) +{ return (dop * NMEA_DOP_FACTOR); } + +float nmea_meters2dop(float meters) +{ return (meters / NMEA_DOP_FACTOR); } + +/** + * \brief Calculate distance between two points + * \return Distance in meters + */ +float nmea_distance( + const nmeaPOS *from_pos, /**< From position in radians */ + const nmeaPOS *to_pos /**< To position in radians */ + ) +{ + float dist = ((float)NMEA_EARTHRADIUS_M) * acos( + sin(to_pos->lat) * sin(from_pos->lat) + + cos(to_pos->lat) * cos(from_pos->lat) * cos(to_pos->lon - from_pos->lon) + ); + return dist; +} + +/** + * \brief Calculate distance between two points + * This function uses an algorithm for an oblate spheroid earth model. + * The algorithm is described here: + * http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf + * \return Distance in meters + */ +float nmea_distance_ellipsoid( + const nmeaPOS *from_pos, /**< From position in radians */ + const nmeaPOS *to_pos, /**< To position in radians */ + float *from_azimuth, /**< (O) azimuth at "from" position in radians */ + float *to_azimuth /**< (O) azimuth at "to" position in radians */ + ) +{ + /* All variables */ + float f, a, b, sqr_a, sqr_b; + float L, phi1, phi2, U1, U2, sin_U1, sin_U2, cos_U1, cos_U2; + float sigma, sin_sigma, cos_sigma, cos_2_sigmam, sqr_cos_2_sigmam, sqr_cos_alpha, lambda, sin_lambda, cos_lambda, delta_lambda; + int remaining_steps; + float sqr_u, A, B, delta_sigma; + + /* Check input */ + //NMEA_ASSERT(from_pos != 0); + //NMEA_ASSERT(to_pos != 0); + + if ((from_pos->lat == to_pos->lat) && (from_pos->lon == to_pos->lon)) + { /* Identical points */ + if ( from_azimuth != 0 ) + *from_azimuth = 0; + if ( to_azimuth != 0 ) + *to_azimuth = 0; + return 0; + } /* Identical points */ + + /* Earth geometry */ + f = NMEA_EARTH_FLATTENING; + a = NMEA_EARTH_SEMIMAJORAXIS_M; + b = (1 - f) * a; + sqr_a = a * a; + sqr_b = b * b; + + /* Calculation */ + L = to_pos->lon - from_pos->lon; + phi1 = from_pos->lat; + phi2 = to_pos->lat; + U1 = atan((1 - f) * tan(phi1)); + U2 = atan((1 - f) * tan(phi2)); + sin_U1 = sin(U1); + sin_U2 = sin(U2); + cos_U1 = cos(U1); + cos_U2 = cos(U2); + + /* Initialize iteration */ + sigma = 0; + sin_sigma = sin(sigma); + cos_sigma = cos(sigma); + cos_2_sigmam = 0; + sqr_cos_2_sigmam = cos_2_sigmam * cos_2_sigmam; + sqr_cos_alpha = 0; + lambda = L; + sin_lambda = sin(lambda); + cos_lambda = cos(lambda); + delta_lambda = lambda; + remaining_steps = 20; + + while ((delta_lambda > 1e-12) && (remaining_steps > 0)) + { /* Iterate */ + /* Variables */ + float tmp1, tmp2, tan_sigma, sin_alpha, cos_alpha, C, lambda_prev; + + /* Calculation */ + tmp1 = cos_U2 * sin_lambda; + tmp2 = cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda; + sin_sigma = sqrt(tmp1 * tmp1 + tmp2 * tmp2); + cos_sigma = sin_U1 * sin_U2 + cos_U1 * cos_U2 * cos_lambda; + tan_sigma = sin_sigma / cos_sigma; + sin_alpha = cos_U1 * cos_U2 * sin_lambda / sin_sigma; + cos_alpha = cos(asin(sin_alpha)); + sqr_cos_alpha = cos_alpha * cos_alpha; + cos_2_sigmam = cos_sigma - 2 * sin_U1 * sin_U2 / sqr_cos_alpha; + sqr_cos_2_sigmam = cos_2_sigmam * cos_2_sigmam; + C = f / 16 * sqr_cos_alpha * (4 + f * (4 - 3 * sqr_cos_alpha)); + lambda_prev = lambda; + sigma = asin(sin_sigma); + lambda = L + + (1 - C) * f * sin_alpha + * (sigma + C * sin_sigma * (cos_2_sigmam + C * cos_sigma * (-1 + 2 * sqr_cos_2_sigmam))); + delta_lambda = lambda_prev - lambda; + if ( delta_lambda < 0 ) delta_lambda = -delta_lambda; + sin_lambda = sin(lambda); + cos_lambda = cos(lambda); + remaining_steps--; + } /* Iterate */ + + /* More calculation */ + sqr_u = sqr_cos_alpha * (sqr_a - sqr_b) / sqr_b; + A = 1 + sqr_u / 16384 * (4096 + sqr_u * (-768 + sqr_u * (320 - 175 * sqr_u))); + B = sqr_u / 1024 * (256 + sqr_u * (-128 + sqr_u * (74 - 47 * sqr_u))); + delta_sigma = B * sin_sigma * ( + cos_2_sigmam + B / 4 * ( + cos_sigma * (-1 + 2 * sqr_cos_2_sigmam) - + B / 6 * cos_2_sigmam * (-3 + 4 * sin_sigma * sin_sigma) * (-3 + 4 * sqr_cos_2_sigmam) + )); + + /* Calculate result */ + if ( from_azimuth != 0 ) + { + float tan_alpha_1 = cos_U2 * sin_lambda / (cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda); + *from_azimuth = atan(tan_alpha_1); + } + if ( to_azimuth != 0 ) + { + float tan_alpha_2 = cos_U1 * sin_lambda / (-sin_U1 * cos_U2 + cos_U1 * sin_U2 * cos_lambda); + *to_azimuth = atan(tan_alpha_2); + } + + return b * A * (sigma - delta_sigma); +} + +/** + * \brief Horizontal move of point position + */ +int nmea_move_horz( + const nmeaPOS *start_pos, /**< Start position in radians */ + nmeaPOS *end_pos, /**< Result position in radians */ + float azimuth, /**< Azimuth (degree) [0, 359] */ + float distance /**< Distance (km) */ + ) +{ + nmeaPOS p1 = *start_pos; + int RetVal = 1; + + distance /= NMEA_EARTHRADIUS_KM; /* Angular distance covered on earth's surface */ + azimuth = nmea_degree2radian(azimuth); + + end_pos->lat = asin( + sin(p1.lat) * cos(distance) + cos(p1.lat) * sin(distance) * cos(azimuth)); + end_pos->lon = p1.lon + atan2( + sin(azimuth) * sin(distance) * cos(p1.lat), cos(distance) - sin(p1.lat) * sin(end_pos->lat)); + + if(NMEA_POSIX(isnan)(end_pos->lat) || NMEA_POSIX(isnan)(end_pos->lon)) + { + end_pos->lat = 0; end_pos->lon = 0; + RetVal = 0; + } + + return RetVal; +} + +/** + * \brief Horizontal move of point position + * This function uses an algorithm for an oblate spheroid earth model. + * The algorithm is described here: + * http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf + */ +int nmea_move_horz_ellipsoid( + const nmeaPOS *start_pos, /**< Start position in radians */ + nmeaPOS *end_pos, /**< (O) Result position in radians */ + float azimuth, /**< Azimuth in radians */ + float distance, /**< Distance (km) */ + float *end_azimuth /**< (O) Azimuth at end position in radians */ + ) +{ + /* Variables */ + float f, a, b, sqr_a, sqr_b; + float phi1, tan_U1, sin_U1, cos_U1, s, alpha1, sin_alpha1, cos_alpha1; + float tan_sigma1, sigma1, sin_alpha, cos_alpha, sqr_cos_alpha, sqr_u, A, B; + float sigma_initial, sigma, sigma_prev, sin_sigma, cos_sigma, cos_2_sigmam, sqr_cos_2_sigmam, delta_sigma; + int remaining_steps; + float tmp1, phi2, lambda, C, L; + + /* Check input */ + //NMEA_ASSERT(start_pos != 0); + //NMEA_ASSERT(end_pos != 0); + + if (fabs(distance) < 1e-12) + { /* No move */ + *end_pos = *start_pos; + if ( end_azimuth != 0 ) *end_azimuth = azimuth; + return ! (NMEA_POSIX(isnan)(end_pos->lat) || NMEA_POSIX(isnan)(end_pos->lon)); + } /* No move */ + + /* Earth geometry */ + f = NMEA_EARTH_FLATTENING; + a = NMEA_EARTH_SEMIMAJORAXIS_M; + b = (1 - f) * a; + sqr_a = a * a; + sqr_b = b * b; + + /* Calculation */ + phi1 = start_pos->lat; + tan_U1 = (1 - f) * tan(phi1); + cos_U1 = 1 / sqrt(1 + tan_U1 * tan_U1); + sin_U1 = tan_U1 * cos_U1; + s = distance; + alpha1 = azimuth; + sin_alpha1 = sin(alpha1); + cos_alpha1 = cos(alpha1); + tan_sigma1 = tan_U1 / cos_alpha1; + sigma1 = atan2(tan_U1, cos_alpha1); + sin_alpha = cos_U1 * sin_alpha1; + sqr_cos_alpha = 1 - sin_alpha * sin_alpha; + cos_alpha = sqrt(sqr_cos_alpha); + sqr_u = sqr_cos_alpha * (sqr_a - sqr_b) / sqr_b; + A = 1 + sqr_u / 16384 * (4096 + sqr_u * (-768 + sqr_u * (320 - 175 * sqr_u))); + B = sqr_u / 1024 * (256 + sqr_u * (-128 + sqr_u * (74 - 47 * sqr_u))); + + /* Initialize iteration */ + sigma_initial = s / (b * A); + sigma = sigma_initial; + sin_sigma = sin(sigma); + cos_sigma = cos(sigma); + cos_2_sigmam = cos(2 * sigma1 + sigma); + sqr_cos_2_sigmam = cos_2_sigmam * cos_2_sigmam; + delta_sigma = 0; + sigma_prev = 2 * NMEA_PI; + remaining_steps = 20; + + while ((fabs(sigma - sigma_prev) > 1e-12) && (remaining_steps > 0)) + { /* Iterate */ + cos_2_sigmam = cos(2 * sigma1 + sigma); + sqr_cos_2_sigmam = cos_2_sigmam * cos_2_sigmam; + sin_sigma = sin(sigma); + cos_sigma = cos(sigma); + delta_sigma = B * sin_sigma * ( + cos_2_sigmam + B / 4 * ( + cos_sigma * (-1 + 2 * sqr_cos_2_sigmam) - + B / 6 * cos_2_sigmam * (-3 + 4 * sin_sigma * sin_sigma) * (-3 + 4 * sqr_cos_2_sigmam) + )); + sigma_prev = sigma; + sigma = sigma_initial + delta_sigma; + remaining_steps --; + } /* Iterate */ + + /* Calculate result */ + tmp1 = (sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_alpha1); + phi2 = atan2( + sin_U1 * cos_sigma + cos_U1 * sin_sigma * cos_alpha1, + (1 - f) * sqrt(sin_alpha * sin_alpha + tmp1 * tmp1) + ); + lambda = atan2( + sin_sigma * sin_alpha1, + cos_U1 * cos_sigma - sin_U1 * sin_sigma * cos_alpha1 + ); + C = f / 16 * sqr_cos_alpha * (4 + f * (4 - 3 * sqr_cos_alpha)); + L = lambda - + (1 - C) * f * sin_alpha * ( + sigma + C * sin_sigma * + (cos_2_sigmam + C * cos_sigma * (-1 + 2 * sqr_cos_2_sigmam)) + ); + + /* Result */ + end_pos->lon = start_pos->lon + L; + end_pos->lat = phi2; + if ( end_azimuth != 0 ) + { + *end_azimuth = atan2( + sin_alpha, -sin_U1 * sin_sigma + cos_U1 * cos_sigma * cos_alpha1 + ); + } + return ! (NMEA_POSIX(isnan)(end_pos->lat) || NMEA_POSIX(isnan)(end_pos->lon)); +} + +/** + * \brief Convert position from INFO to radians position + */ +void nmea_info2pos(const nmeaINFO *info, nmeaPOS *pos) +{ + pos->lat = nmea_ndeg2radian(info->lat); + pos->lon = nmea_ndeg2radian(info->lon); +} + +/** + * \brief Convert radians position to INFOs position + */ +void nmea_pos2info(const nmeaPOS *pos, nmeaINFO *info) +{ + info->lat = nmea_radian2ndeg(pos->lat); + info->lon = nmea_radian2ndeg(pos->lon); +} diff --git a/apps/gps/nmealib/info.c b/apps/gps/nmealib/info.c new file mode 100644 index 0000000000..1d531ffc4d --- /dev/null +++ b/apps/gps/nmealib/info.c @@ -0,0 +1,21 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: info.c 17 2008-03-11 11:56:11Z xtimor $ + * + */ + +#include + +#include "nmea/info.h" + +void nmea_zero_INFO(nmeaINFO *info) +{ + memset(info, 0, sizeof(nmeaINFO)); + nmea_time_now(&info->utc); + info->sig = NMEA_SIG_BAD; + info->fix = NMEA_FIX_BAD; +} diff --git a/apps/gps/nmealib/nmea/config.h b/apps/gps/nmealib/nmea/config.h new file mode 100644 index 0000000000..5014662187 --- /dev/null +++ b/apps/gps/nmealib/nmea/config.h @@ -0,0 +1,51 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: config.h 17 2008-03-11 11:56:11Z xtimor $ + * + */ + +#ifndef __NMEA_CONFIG_H__ +#define __NMEA_CONFIG_H__ + +#define NMEA_VERSION ("0.5.3") +#define NMEA_VERSION_MAJOR (0) +#define NMEA_VERSION_MINOR (5) +#define NMEA_VERSION_PATCH (3) + +#define NMEA_CONVSTR_BUF (256) +#define NMEA_TIMEPARSE_BUF (256) + +#if defined(WINCE) || defined(UNDER_CE) +# define NMEA_CE +#endif + +#if defined(WIN32) || defined(NMEA_CE) +# define NMEA_WIN +#else +# define NMEA_UNI +#endif + +#if defined(NMEA_WIN) && (_MSC_VER >= 1400) +# pragma warning(disable: 4996) /* declared deprecated */ +#endif + +#if defined(_MSC_VER) +# define NMEA_POSIX(x) _##x +# define NMEA_INLINE __inline +#else +# define NMEA_POSIX(x) x +# define NMEA_INLINE inline +#endif + +#if !defined(NDEBUG) && !defined(NMEA_CE) +# include +# define NMEA_ASSERT(x) assert(x) +#else +# define NMEA_ASSERT(x) +#endif + +#endif /* __NMEA_CONFIG_H__ */ diff --git a/apps/gps/nmealib/nmea/context.h b/apps/gps/nmealib/nmea/context.h new file mode 100644 index 0000000000..06e5583276 --- /dev/null +++ b/apps/gps/nmealib/nmea/context.h @@ -0,0 +1,44 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: context.h 4 2007-08-27 13:11:03Z xtimor $ + * + */ + +#ifndef __NMEA_CONTEXT_H__ +#define __NMEA_CONTEXT_H__ + +#include "config.h" + +#define NMEA_DEF_PARSEBUFF (1024) +#define NMEA_MIN_PARSEBUFF (256) + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*nmeaTraceFunc)(const char *str, int str_size); +typedef void (*nmeaErrorFunc)(const char *str, int str_size); + +typedef struct _nmeaPROPERTY +{ + nmeaTraceFunc trace_func; + nmeaErrorFunc error_func; + int parse_buff_size; + +} nmeaPROPERTY; + +nmeaPROPERTY * nmea_property(void); + +void nmea_trace(const char *str, ...); +void nmea_trace_buff(const char *buff, int buff_size); +void nmea_error(const char *str, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* __NMEA_CONTEXT_H__ */ diff --git a/apps/gps/nmealib/nmea/generate.h b/apps/gps/nmealib/nmea/generate.h new file mode 100644 index 0000000000..9d7fdee51d --- /dev/null +++ b/apps/gps/nmealib/nmea/generate.h @@ -0,0 +1,44 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: generate.h 4 2007-08-27 13:11:03Z xtimor $ + * + */ + +#ifndef __NMEA_GENERATE_H__ +#define __NMEA_GENERATE_H__ + +#include "sentence.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int nmea_generate( + char *buff, int buff_sz, /* buffer */ + const nmeaINFO *info, /* source info */ + int generate_mask /* mask of sentence`s (e.g. GPGGA | GPGSA) */ + ); + +int nmea_gen_GPGGA(char *buff, int buff_sz, nmeaGPGGA *pack); +int nmea_gen_GPGSA(char *buff, int buff_sz, nmeaGPGSA *pack); +int nmea_gen_GPGSV(char *buff, int buff_sz, nmeaGPGSV *pack); +int nmea_gen_GPRMC(char *buff, int buff_sz, nmeaGPRMC *pack); +int nmea_gen_GPVTG(char *buff, int buff_sz, nmeaGPVTG *pack); + +void nmea_info2GPGGA(const nmeaINFO *info, nmeaGPGGA *pack); +void nmea_info2GPGSA(const nmeaINFO *info, nmeaGPGSA *pack); +void nmea_info2GPRMC(const nmeaINFO *info, nmeaGPRMC *pack); +void nmea_info2GPVTG(const nmeaINFO *info, nmeaGPVTG *pack); + +int nmea_gsv_npack(int sat_count); +void nmea_info2GPGSV(const nmeaINFO *info, nmeaGPGSV *pack, int pack_idx); + +#ifdef __cplusplus +} +#endif + +#endif /* __NMEA_GENERATE_H__ */ diff --git a/apps/gps/nmealib/nmea/generator.h b/apps/gps/nmealib/nmea/generator.h new file mode 100644 index 0000000000..a97b91b137 --- /dev/null +++ b/apps/gps/nmealib/nmea/generator.h @@ -0,0 +1,79 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: generator.h 4 2007-08-27 13:11:03Z xtimor $ + * + */ + +#ifndef __NMEA_GENERATOR_H__ +#define __NMEA_GENERATOR_H__ + +#include "info.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * high level + */ + +struct _nmeaGENERATOR; + +enum nmeaGENTYPE +{ + NMEA_GEN_NOISE = 0, + NMEA_GEN_STATIC, + NMEA_GEN_ROTATE, + + NMEA_GEN_SAT_STATIC, + NMEA_GEN_SAT_ROTATE, + NMEA_GEN_POS_RANDMOVE, + + NMEA_GEN_LAST +}; + +struct _nmeaGENERATOR * nmea_create_generator(int type, nmeaINFO *info); +void nmea_destroy_generator(struct _nmeaGENERATOR *gen); + +int nmea_generate_from( + char *buff, int buff_sz, /* buffer */ + nmeaINFO *info, /* source info */ + struct _nmeaGENERATOR *gen, /* generator */ + int generate_mask /* mask of sentence`s (e.g. GPGGA | GPGSA) */ + ); + +/* + * low level + */ + +typedef int (*nmeaNMEA_GEN_INIT)(struct _nmeaGENERATOR *gen, nmeaINFO *info); +typedef int (*nmeaNMEA_GEN_LOOP)(struct _nmeaGENERATOR *gen, nmeaINFO *info); +typedef int (*nmeaNMEA_GEN_RESET)(struct _nmeaGENERATOR *gen, nmeaINFO *info); +typedef int (*nmeaNMEA_GEN_DESTROY)(struct _nmeaGENERATOR *gen); + +typedef struct _nmeaGENERATOR +{ + void *gen_data; + nmeaNMEA_GEN_INIT init_call; + nmeaNMEA_GEN_LOOP loop_call; + nmeaNMEA_GEN_RESET reset_call; + nmeaNMEA_GEN_DESTROY destroy_call; + struct _nmeaGENERATOR *next; + +} nmeaGENERATOR; + +int nmea_gen_init(nmeaGENERATOR *gen, nmeaINFO *info); +int nmea_gen_loop(nmeaGENERATOR *gen, nmeaINFO *info); +int nmea_gen_reset(nmeaGENERATOR *gen, nmeaINFO *info); +void nmea_gen_destroy(nmeaGENERATOR *gen); +void nmea_gen_add(nmeaGENERATOR *to, nmeaGENERATOR *gen); + +#ifdef __cplusplus +} +#endif + +#endif /* __NMEA_GENERATOR_H__ */ diff --git a/apps/gps/nmealib/nmea/gmath.h b/apps/gps/nmealib/nmea/gmath.h new file mode 100644 index 0000000000..3133b7228c --- /dev/null +++ b/apps/gps/nmealib/nmea/gmath.h @@ -0,0 +1,92 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: gmath.h 17 2008-03-11 11:56:11Z xtimor $ + * + */ + +#ifndef __NMEA_GMATH_H__ +#define __NMEA_GMATH_H__ + +#include "info.h" + +#define NMEA_PI (3.141592653589793) /**< PI value */ +#define NMEA_PI180 (NMEA_PI / 180) /**< PI division by 180 */ +#define NMEA_EARTHRADIUS_KM (6378) /**< Earth's mean radius in km */ +#define NMEA_EARTHRADIUS_M (NMEA_EARTHRADIUS_KM * 1000) /**< Earth's mean radius in m */ +#define NMEA_EARTH_SEMIMAJORAXIS_M (6378137.0) /**< Earth's semi-major axis in m according WGS84 */ +#define NMEA_EARTH_SEMIMAJORAXIS_KM (NMEA_EARTHMAJORAXIS_KM / 1000) /**< Earth's semi-major axis in km according WGS 84 */ +#define NMEA_EARTH_FLATTENING (1 / 298.257223563) /**< Earth's flattening according WGS 84 */ +#define NMEA_DOP_FACTOR (5) /**< Factor for translating DOP to meters */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * degree VS radian + */ + +float nmea_degree2radian(float val); +float nmea_radian2degree(float val); + +/* + * NDEG (NMEA degree) + */ + +float nmea_ndeg2degree(float val); +float nmea_degree2ndeg(float val); + +float nmea_ndeg2radian(float val); +float nmea_radian2ndeg(float val); + +/* + * DOP + */ + +float nmea_calc_pdop(float hdop, float vdop); +float nmea_dop2meters(float dop); +float nmea_meters2dop(float meters); + +/* + * positions work + */ + +void nmea_info2pos(const nmeaINFO *info, nmeaPOS *pos); +void nmea_pos2info(const nmeaPOS *pos, nmeaINFO *info); + +float nmea_distance( + const nmeaPOS *from_pos, + const nmeaPOS *to_pos + ); + +float nmea_distance_ellipsoid( + const nmeaPOS *from_pos, + const nmeaPOS *to_pos, + float *from_azimuth, + float *to_azimuth + ); + +int nmea_move_horz( + const nmeaPOS *start_pos, + nmeaPOS *end_pos, + float azimuth, + float distance + ); + +int nmea_move_horz_ellipsoid( + const nmeaPOS *start_pos, + nmeaPOS *end_pos, + float azimuth, + float distance, + float *end_azimuth + ); + +#ifdef __cplusplus +} +#endif + +#endif /* __NMEA_GMATH_H__ */ diff --git a/apps/gps/nmealib/nmea/info.h b/apps/gps/nmealib/nmea/info.h new file mode 100644 index 0000000000..09ccd4c092 --- /dev/null +++ b/apps/gps/nmealib/nmea/info.h @@ -0,0 +1,112 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: info.h 10 2007-11-15 14:50:15Z xtimor $ + * + */ + +/*! \file */ + +#ifndef __NMEA_INFO_H__ +#define __NMEA_INFO_H__ + +#include "time.h" + +#define NMEA_SIG_BAD (0) +#define NMEA_SIG_LOW (1) +#define NMEA_SIG_MID (2) +#define NMEA_SIG_HIGH (3) + +#define NMEA_FIX_BAD (1) +#define NMEA_FIX_2D (2) +#define NMEA_FIX_3D (3) + +#define NMEA_MAXSAT (12) +#define NMEA_SATINPACK (4) +#define NMEA_NSATPACKS (NMEA_MAXSAT / NMEA_SATINPACK) + +#define NMEA_DEF_LAT (5001.2621) +#define NMEA_DEF_LON (3613.0595) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Position data in fractional degrees or radians + */ +typedef struct _nmeaPOS +{ + float lat; /**< Latitude */ + float lon; /**< Longitude */ + +} nmeaPOS; + +/** + * Information about satellite + * @see nmeaSATINFO + * @see nmeaGPGSV + */ +typedef struct _nmeaSATELLITE +{ + int id; /**< Satellite PRN number */ + int in_use; /**< Used in position fix */ + int elv; /**< Elevation in degrees, 90 maximum */ + int azimuth; /**< Azimuth, degrees from true north, 000 to 359 */ + int sig; /**< Signal, 00-99 dB */ + +} nmeaSATELLITE; + +/** + * Information about all satellites in view + * @see nmeaINFO + * @see nmeaGPGSV + */ +typedef struct _nmeaSATINFO +{ + int inuse; /**< Number of satellites in use (not those in view) */ + int inview; /**< Total number of satellites in view */ + nmeaSATELLITE sat[NMEA_MAXSAT]; /**< Satellites information */ + +} nmeaSATINFO; + +/** + * Summary GPS information from all parsed packets, + * used also for generating NMEA stream + * @see nmea_parse + * @see nmea_GPGGA2info, nmea_...2info + */ +typedef struct _nmeaINFO +{ + int smask; /**< Mask specifying types of packages from which data have been obtained */ + + nmeaTIME utc; /**< UTC of position */ + + int sig; /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */ + int fix; /**< Operating mode, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */ + + float PDOP; /**< Position Dilution Of Precision */ + float HDOP; /**< Horizontal Dilution Of Precision */ + float VDOP; /**< Vertical Dilution Of Precision */ + + float lat; /**< Latitude in NDEG - +/-[degree][min].[sec/60] */ + float lon; /**< Longitude in NDEG - +/-[degree][min].[sec/60] */ + float elv; /**< Antenna altitude above/below mean sea level (geoid) in meters */ + float speed; /**< Speed over the ground in kilometers/hour */ + float direction; /**< Track angle in degrees True */ + float declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */ + + nmeaSATINFO satinfo; /**< Satellites information */ + +} nmeaINFO; + +void nmea_zero_INFO(nmeaINFO *info); + +#ifdef __cplusplus +} +#endif + +#endif /* __NMEA_INFO_H__ */ diff --git a/apps/gps/nmealib/nmea/nmea.h b/apps/gps/nmealib/nmea/nmea.h new file mode 100644 index 0000000000..62692230f0 --- /dev/null +++ b/apps/gps/nmealib/nmea/nmea.h @@ -0,0 +1,25 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: nmea.h 17 2008-03-11 11:56:11Z xtimor $ + * + */ + +#ifndef __NMEA_H__ +#define __NMEA_H__ + +#include "./config.h" +#include "./units.h" +#include "./gmath.h" +#include "./info.h" +#include "./sentence.h" +#include "./generate.h" +#include "./generator.h" +#include "./parse.h" +#include "./parser.h" +#include "./context.h" + +#endif /* __NMEA_H__ */ diff --git a/apps/gps/nmealib/nmea/parse.h b/apps/gps/nmealib/nmea/parse.h new file mode 100644 index 0000000000..3e6b425db7 --- /dev/null +++ b/apps/gps/nmealib/nmea/parse.h @@ -0,0 +1,39 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: parse.h 4 2007-08-27 13:11:03Z xtimor $ + * + */ + +#ifndef __NMEA_PARSE_H__ +#define __NMEA_PARSE_H__ + +#include "sentence.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int nmea_pack_type(const char *buff, int buff_sz); +int nmea_find_tail(const char *buff, int buff_sz, int *res_crc); + +int nmea_parse_GPGGA(const char *buff, int buff_sz, nmeaGPGGA *pack); +int nmea_parse_GPGSA(const char *buff, int buff_sz, nmeaGPGSA *pack); +int nmea_parse_GPGSV(const char *buff, int buff_sz, nmeaGPGSV *pack); +int nmea_parse_GPRMC(const char *buff, int buff_sz, nmeaGPRMC *pack); +int nmea_parse_GPVTG(const char *buff, int buff_sz, nmeaGPVTG *pack); + +void nmea_GPGGA2info(nmeaGPGGA *pack, nmeaINFO *info); +void nmea_GPGSA2info(nmeaGPGSA *pack, nmeaINFO *info); +void nmea_GPGSV2info(nmeaGPGSV *pack, nmeaINFO *info); +void nmea_GPRMC2info(nmeaGPRMC *pack, nmeaINFO *info); +void nmea_GPVTG2info(nmeaGPVTG *pack, nmeaINFO *info); + +#ifdef __cplusplus +} +#endif + +#endif /* __NMEA_PARSE_H__ */ diff --git a/apps/gps/nmealib/nmea/parser.h b/apps/gps/nmealib/nmea/parser.h new file mode 100644 index 0000000000..51a3fab7fd --- /dev/null +++ b/apps/gps/nmealib/nmea/parser.h @@ -0,0 +1,59 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: parser.h 4 2007-08-27 13:11:03Z xtimor $ + * + */ + +#ifndef __NMEA_PARSER_H__ +#define __NMEA_PARSER_H__ + +#include "info.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * high level + */ + +typedef struct _nmeaPARSER +{ + void *top_node; + void *end_node; + unsigned char *buffer; + int buff_size; + int buff_use; + +} nmeaPARSER; + +int nmea_parser_init(nmeaPARSER *parser); +void nmea_parser_destroy(nmeaPARSER *parser); + +int nmea_parse( + nmeaPARSER *parser, + const char *buff, int buff_sz, + nmeaINFO *info + ); + +/* + * low level + */ + +int nmea_parser_push(nmeaPARSER *parser, const char *buff, int buff_sz); +int nmea_parser_top(nmeaPARSER *parser); +int nmea_parser_pop(nmeaPARSER *parser, void **pack_ptr); +int nmea_parser_peek(nmeaPARSER *parser, void **pack_ptr); +int nmea_parser_drop(nmeaPARSER *parser); +int nmea_parser_buff_clear(nmeaPARSER *parser); +int nmea_parser_queue_clear(nmeaPARSER *parser); + +#ifdef __cplusplus +} +#endif + +#endif /* __NMEA_PARSER_H__ */ diff --git a/apps/gps/nmealib/nmea/sentence.h b/apps/gps/nmealib/nmea/sentence.h new file mode 100644 index 0000000000..2aa975c717 --- /dev/null +++ b/apps/gps/nmealib/nmea/sentence.h @@ -0,0 +1,128 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: sentence.h 17 2008-03-11 11:56:11Z xtimor $ + * + */ + +/*! \file */ + +#ifndef __NMEA_SENTENCE_H__ +#define __NMEA_SENTENCE_H__ + +#include "info.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * NMEA packets type which parsed and generated by library + */ +enum nmeaPACKTYPE +{ + GPNON = 0x0000, /**< Unknown packet type. */ + GPGGA = 0x0001, /**< GGA - Essential fix data which provide 3D location and accuracy data. */ + GPGSA = 0x0002, /**< GSA - GPS receiver operating mode, SVs used for navigation, and DOP values. */ + GPGSV = 0x0004, /**< GSV - Number of SVs in view, PRN numbers, elevation, azimuth & SNR values. */ + GPRMC = 0x0008, /**< RMC - Recommended Minimum Specific GPS/TRANSIT Data. */ + GPVTG = 0x0010 /**< VTG - Actual track made good and speed over ground. */ +}; + +/** + * GGA packet information structure (Global Positioning System Fix Data) + */ +typedef struct _nmeaGPGGA +{ + nmeaTIME utc; /**< UTC of position (just time) */ + float lat; /**< Latitude in NDEG - [degree][min].[sec/60] */ + char ns; /**< [N]orth or [S]outh */ + float lon; /**< Longitude in NDEG - [degree][min].[sec/60] */ + char ew; /**< [E]ast or [W]est */ + int sig; /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */ + int satinuse; /**< Number of satellites in use (not those in view) */ + float HDOP; /**< Horizontal dilution of precision */ + float elv; /**< Antenna altitude above/below mean sea level (geoid) */ + char elv_units; /**< [M]eters (Antenna height unit) */ + float diff; /**< Geoidal separation (Diff. between WGS-84 earth ellipsoid and mean sea level. '-' = geoid is below WGS-84 ellipsoid) */ + char diff_units; /**< [M]eters (Units of geoidal separation) */ + float dgps_age; /**< Time in seconds since last DGPS update */ + int dgps_sid; /**< DGPS station ID number */ + +} nmeaGPGGA; + +/** + * GSA packet information structure (Satellite status) + */ +typedef struct _nmeaGPGSA +{ + char fix_mode; /**< Mode (M = Manual, forced to operate in 2D or 3D; A = Automatic, 3D/2D) */ + int fix_type; /**< Type, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */ + int sat_prn[NMEA_MAXSAT]; /**< PRNs of satellites used in position fix (null for unused fields) */ + float PDOP; /**< Dilution of precision */ + float HDOP; /**< Horizontal dilution of precision */ + float VDOP; /**< Vertical dilution of precision */ + +} nmeaGPGSA; + +/** + * GSV packet information structure (Satellites in view) + */ +typedef struct _nmeaGPGSV +{ + int pack_count; /**< Total number of messages of this type in this cycle */ + int pack_index; /**< Message number */ + int sat_count; /**< Total number of satellites in view */ + nmeaSATELLITE sat_data[NMEA_SATINPACK]; + +} nmeaGPGSV; + +/** + * RMC packet information structure (Recommended Minimum sentence C) + */ +typedef struct _nmeaGPRMC +{ + nmeaTIME utc; /**< UTC of position */ + char status; /**< Status (A = active or V = void) */ + float lat; /**< Latitude in NDEG - [degree][min].[sec/60] */ + char ns; /**< [N]orth or [S]outh */ + float lon; /**< Longitude in NDEG - [degree][min].[sec/60] */ + char ew; /**< [E]ast or [W]est */ + float speed; /**< Speed over the ground in knots */ + float direction; /**< Track angle in degrees True */ + float declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */ + char declin_ew; /**< [E]ast or [W]est */ + char mode; /**< Mode indicator of fix type (A = autonomous, D = differential, E = estimated, N = not valid, S = simulator) */ + +} nmeaGPRMC; + +/** + * VTG packet information structure (Track made good and ground speed) + */ +typedef struct _nmeaGPVTG +{ + float dir; /**< True track made good (degrees) */ + char dir_t; /**< Fixed text 'T' indicates that track made good is relative to true north */ + float dec; /**< Magnetic track made good */ + char dec_m; /**< Fixed text 'M' */ + float spn; /**< Ground speed, knots */ + char spn_n; /**< Fixed text 'N' indicates that speed over ground is in knots */ + float spk; /**< Ground speed, kilometers per hour */ + char spk_k; /**< Fixed text 'K' indicates that speed over ground is in kilometers/hour */ + +} nmeaGPVTG; + +void nmea_zero_GPGGA(nmeaGPGGA *pack); +void nmea_zero_GPGSA(nmeaGPGSA *pack); +void nmea_zero_GPGSV(nmeaGPGSV *pack); +void nmea_zero_GPRMC(nmeaGPRMC *pack); +void nmea_zero_GPVTG(nmeaGPVTG *pack); + +#ifdef __cplusplus +} +#endif + +#endif /* __NMEA_SENTENCE_H__ */ diff --git a/apps/gps/nmealib/nmea/time.h b/apps/gps/nmealib/nmea/time.h new file mode 100644 index 0000000000..bbe59f65c9 --- /dev/null +++ b/apps/gps/nmealib/nmea/time.h @@ -0,0 +1,47 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: time.h 4 2007-08-27 13:11:03Z xtimor $ + * + */ + +/*! \file */ + +#ifndef __NMEA_TIME_H__ +#define __NMEA_TIME_H__ + +#include "config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Date and time data + * @see nmea_time_now + */ +typedef struct _nmeaTIME +{ + int year; /**< Years since 1900 */ + int mon; /**< Months since January - [0,11] */ + int day; /**< Day of the month - [1,31] */ + int hour; /**< Hours since midnight - [0,23] */ + int min; /**< Minutes after the hour - [0,59] */ + int sec; /**< Seconds after the minute - [0,59] */ + int hsec; /**< Hundredth part of second - [0,99] */ + +} nmeaTIME; + +/** + * \brief Get time now to nmeaTIME structure + */ +void nmea_time_now(nmeaTIME *t); + +#ifdef __cplusplus +} +#endif + +#endif /* __NMEA_TIME_H__ */ diff --git a/apps/gps/nmealib/nmea/tok.h b/apps/gps/nmealib/nmea/tok.h new file mode 100644 index 0000000000..8f948dd2d5 --- /dev/null +++ b/apps/gps/nmealib/nmea/tok.h @@ -0,0 +1,31 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: tok.h 4 2007-08-27 13:11:03Z xtimor $ + * + */ + +#ifndef __NMEA_TOK_H__ +#define __NMEA_TOK_H__ + +#include "config.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int nmea_calc_crc(const char *buff, int buff_sz); +int nmea_atoi(const char *str, int str_sz, int radix); +float nmea_atof(const char *str, int str_sz); +int nmea_printf(char *buff, int buff_sz, const char *format, ...); +int nmea_scanf(const char *buff, int buff_sz, const char *format, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* __NMEA_TOK_H__ */ diff --git a/apps/gps/nmealib/nmea/units.h b/apps/gps/nmealib/nmea/units.h new file mode 100644 index 0000000000..767f980e2b --- /dev/null +++ b/apps/gps/nmealib/nmea/units.h @@ -0,0 +1,30 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: units.h 4 2007-08-27 13:11:03Z xtimor $ + * + */ + +#ifndef __NMEA_UNITS_H__ +#define __NMEA_UNITS_H__ + +#include "config.h" + +/* + * Distance units + */ + +#define NMEA_TUD_YARDS (1.0936) /**< Yeards, meter * NMEA_TUD_YARDS = yard */ +#define NMEA_TUD_KNOTS (1.852) /**< Knots, kilometer / NMEA_TUD_KNOTS = knot */ +#define NMEA_TUD_MILES (1.609) /**< Miles, kilometer / NMEA_TUD_MILES = mile */ + +/* + * Speed units + */ + +#define NMEA_TUS_MS (3.6) /**< Meters per seconds, (k/h) / NMEA_TUS_MS= (m/s) */ + +#endif /* __NMEA_UNITS_H__ */ diff --git a/apps/gps/nmealib/parse.c b/apps/gps/nmealib/parse.c new file mode 100644 index 0000000000..99bdf075be --- /dev/null +++ b/apps/gps/nmealib/parse.c @@ -0,0 +1,501 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: parse.c 17 2008-03-11 11:56:11Z xtimor $ + * + */ + +/** + * \file parse.h + * \brief Functions of a low level for analysis of + * packages of NMEA stream. + * + * \code + * ... + * ptype = nmea_pack_type( + * (const char *)parser->buffer + nparsed + 1, + * parser->buff_use - nparsed - 1); + * + * if(0 == (node = malloc(sizeof(nmeaParserNODE)))) + * goto mem_fail; + * + * node->pack = 0; + * + * switch(ptype) + * { + * case GPGGA: + * if(0 == (node->pack = malloc(sizeof(nmeaGPGGA)))) + * goto mem_fail; + * node->packType = GPGGA; + * if(!nmea_parse_GPGGA( + * (const char *)parser->buffer + nparsed, + * sen_sz, (nmeaGPGGA *)node->pack)) + * { + * free(node); + * node = 0; + * } + * break; + * case GPGSA: + * if(0 == (node->pack = malloc(sizeof(nmeaGPGSA)))) + * goto mem_fail; + * node->packType = GPGSA; + * if(!nmea_parse_GPGSA( + * (const char *)parser->buffer + nparsed, + * sen_sz, (nmeaGPGSA *)node->pack)) + * { + * free(node); + * node = 0; + * } + * break; + * ... + * \endcode + */ +#include "nmea/tok.h" +#include "nmea/parse.h" +#include "nmea/context.h" +#include "nmea/gmath.h" +#include "nmea/units.h" + +#include +#include + +int _nmea_parse_time(const char *buff, int buff_sz, nmeaTIME *res) +{ + int success = 0; + + switch(buff_sz) + { + case sizeof("hhmmss") - 1: + success = (3 == nmea_scanf(buff, buff_sz, + "%2d%2d%2d", &(res->hour), &(res->min), &(res->sec) + )); + break; + case sizeof("hhmmss.s") - 1: + case sizeof("hhmmss.ss") - 1: + case sizeof("hhmmss.sss") - 1: + success = (4 == nmea_scanf(buff, buff_sz, + "%2d%2d%2d.%d", &(res->hour), &(res->min), &(res->sec), &(res->hsec) + )); + break; + default: + nmea_error("Parse of time error (format error)!"); + success = 0; + break; + } + + return (success?0:-1); +} + +/** + * \brief Define packet type by header (nmeaPACKTYPE). + * @param buff a constant character pointer of packet buffer. + * @param buff_sz buffer size. + * @return The defined packet type + * @see nmeaPACKTYPE + */ +int nmea_pack_type(const char *buff, int buff_sz) +{ + static const char *pheads[] = { + "GPGGA", + "GPGSA", + "GPGSV", + "GPRMC", + "GPVTG", + }; + + //NMEA_ASSERT(buff); + + if(buff_sz < 5) + return GPNON; + else if(0 == memcmp(buff, pheads[0], 5)) + return GPGGA; + else if(0 == memcmp(buff, pheads[1], 5)) + return GPGSA; + else if(0 == memcmp(buff, pheads[2], 5)) + return GPGSV; + else if(0 == memcmp(buff, pheads[3], 5)) + return GPRMC; + else if(0 == memcmp(buff, pheads[4], 5)) + return GPVTG; + + return GPNON; +} + +/** + * \brief Find tail of packet ("\r\n") in buffer and check control sum (CRC). + * @param buff a constant character pointer of packets buffer. + * @param buff_sz buffer size. + * @param res_crc a integer pointer for return CRC of packet (must be defined). + * @return Number of bytes to packet tail. + */ +int nmea_find_tail(const char *buff, int buff_sz, int *res_crc) +{ + static const int tail_sz = 3 /* *[CRC] */ + 2 /* \r\n */; + + const char *end_buff = buff + buff_sz; + int nread = 0; + int crc = 0; + + //NMEA_ASSERT(buff && res_crc); + + *res_crc = -1; + + for(;buff < end_buff; ++buff, ++nread) + { + if(('$' == *buff) && nread) + { + buff = 0; + break; + } + else if('*' == *buff) + { + if(buff + tail_sz <= end_buff && '\r' == buff[3] && '\n' == buff[4]) + { + *res_crc = nmea_atoi(buff + 1, 2, 16); + nread = buff_sz - (int)(end_buff - (buff + tail_sz)); + if(*res_crc != crc) + { + *res_crc = -1; + buff = 0; + } + } + + break; + } + else if(nread) + crc ^= (int)*buff; + } + + if(*res_crc < 0 && buff) + nread = 0; + + return nread; +} + +/** + * \brief Parse GGA packet from buffer. + * @param buff a constant character pointer of packet buffer. + * @param buff_sz buffer size. + * @param pack a pointer of packet which will filled by function. + * @return 1 (true) - if parsed successfully or 0 (false) - if fail. + */ +int nmea_parse_GPGGA(const char *buff, int buff_sz, nmeaGPGGA *pack) +{ + char time_buff[NMEA_TIMEPARSE_BUF]; + + //NMEA_ASSERT(buff && pack); + + memset(pack, 0, sizeof(nmeaGPGGA)); + + nmea_trace_buff(buff, buff_sz); + + if(14 != nmea_scanf(buff, buff_sz, + "$GPGGA,%s,%f,%C,%f,%C,%d,%d,%f,%f,%C,%f,%C,%f,%d*", + &(time_buff[0]), + &(pack->lat), &(pack->ns), &(pack->lon), &(pack->ew), + &(pack->sig), &(pack->satinuse), &(pack->HDOP), &(pack->elv), &(pack->elv_units), + &(pack->diff), &(pack->diff_units), &(pack->dgps_age), &(pack->dgps_sid))) + { + nmea_error("GPGGA parse error!"); + return 0; + } + + if(0 != _nmea_parse_time(&time_buff[0], (int)strlen(&time_buff[0]), &(pack->utc))) + { + nmea_error("GPGGA time parse error!"); + return 0; + } + + return 1; +} + +/** + * \brief Parse GSA packet from buffer. + * @param buff a constant character pointer of packet buffer. + * @param buff_sz buffer size. + * @param pack a pointer of packet which will filled by function. + * @return 1 (true) - if parsed successfully or 0 (false) - if fail. + */ +int nmea_parse_GPGSA(const char *buff, int buff_sz, nmeaGPGSA *pack) +{ + //NMEA_ASSERT(buff && pack); + + memset(pack, 0, sizeof(nmeaGPGSA)); + + nmea_trace_buff(buff, buff_sz); + + if(17 != nmea_scanf(buff, buff_sz, + "$GPGSA,%C,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%f,%f,%f*", + &(pack->fix_mode), &(pack->fix_type), + &(pack->sat_prn[0]), &(pack->sat_prn[1]), &(pack->sat_prn[2]), &(pack->sat_prn[3]), &(pack->sat_prn[4]), &(pack->sat_prn[5]), + &(pack->sat_prn[6]), &(pack->sat_prn[7]), &(pack->sat_prn[8]), &(pack->sat_prn[9]), &(pack->sat_prn[10]), &(pack->sat_prn[11]), + &(pack->PDOP), &(pack->HDOP), &(pack->VDOP))) + { + nmea_error("GPGSA parse error!"); + return 0; + } + + return 1; +} + +/** + * \brief Parse GSV packet from buffer. + * @param buff a constant character pointer of packet buffer. + * @param buff_sz buffer size. + * @param pack a pointer of packet which will filled by function. + * @return 1 (true) - if parsed successfully or 0 (false) - if fail. + */ +int nmea_parse_GPGSV(const char *buff, int buff_sz, nmeaGPGSV *pack) +{ + int nsen, nsat; + + //NMEA_ASSERT(buff && pack); + + memset(pack, 0, sizeof(nmeaGPGSV)); + + nmea_trace_buff(buff, buff_sz); + + nsen = nmea_scanf(buff, buff_sz, + "$GPGSV,%d,%d,%d," + "%d,%d,%d,%d," + "%d,%d,%d,%d," + "%d,%d,%d,%d," + "%d,%d,%d,%d*", + &(pack->pack_count), &(pack->pack_index), &(pack->sat_count), + &(pack->sat_data[0].id), &(pack->sat_data[0].elv), &(pack->sat_data[0].azimuth), &(pack->sat_data[0].sig), + &(pack->sat_data[1].id), &(pack->sat_data[1].elv), &(pack->sat_data[1].azimuth), &(pack->sat_data[1].sig), + &(pack->sat_data[2].id), &(pack->sat_data[2].elv), &(pack->sat_data[2].azimuth), &(pack->sat_data[2].sig), + &(pack->sat_data[3].id), &(pack->sat_data[3].elv), &(pack->sat_data[3].azimuth), &(pack->sat_data[3].sig)); + + nsat = (pack->pack_index - 1) * NMEA_SATINPACK; + nsat = (nsat + NMEA_SATINPACK > pack->sat_count)?pack->sat_count - nsat:NMEA_SATINPACK; + nsat = nsat * 4 + 3 /* first three sentence`s */; + + if(nsen < nsat || nsen > (NMEA_SATINPACK * 4 + 3)) + { + nmea_error("GPGSV parse error!"); + return 0; + } + + return 1; +} + +/** + * \brief Parse RMC packet from buffer. + * @param buff a constant character pointer of packet buffer. + * @param buff_sz buffer size. + * @param pack a pointer of packet which will filled by function. + * @return 1 (true) - if parsed successfully or 0 (false) - if fail. + */ +int nmea_parse_GPRMC(const char *buff, int buff_sz, nmeaGPRMC *pack) +{ + int nsen; + char time_buff[NMEA_TIMEPARSE_BUF]; + + //NMEA_ASSERT(buff && pack); + + memset(pack, 0, sizeof(nmeaGPRMC)); + + nmea_trace_buff(buff, buff_sz); + + nsen = nmea_scanf(buff, buff_sz, + "$GPRMC,%s,%C,%f,%C,%f,%C,%f,%f,%2d%2d%2d,%f,%C,%C*", + &(time_buff[0]), + &(pack->status), &(pack->lat), &(pack->ns), &(pack->lon), &(pack->ew), + &(pack->speed), &(pack->direction), + &(pack->utc.day), &(pack->utc.mon), &(pack->utc.year), + &(pack->declination), &(pack->declin_ew), &(pack->mode)); + + if(nsen != 13 && nsen != 14) + { + nmea_error("GPRMC parse error!"); + return 0; + } + + if(0 != _nmea_parse_time(&time_buff[0], (int)strlen(&time_buff[0]), &(pack->utc))) + { + nmea_error("GPRMC time parse error!"); + return 0; + } + + if(pack->utc.year < 90) + pack->utc.year += 100; + pack->utc.mon -= 1; + + return 1; +} + +/** + * \brief Parse VTG packet from buffer. + * @param buff a constant character pointer of packet buffer. + * @param buff_sz buffer size. + * @param pack a pointer of packet which will filled by function. + * @return 1 (true) - if parsed successfully or 0 (false) - if fail. + */ +int nmea_parse_GPVTG(const char *buff, int buff_sz, nmeaGPVTG *pack) +{ + //NMEA_ASSERT(buff && pack); + + memset(pack, 0, sizeof(nmeaGPVTG)); + + nmea_trace_buff(buff, buff_sz); + + if(8 != nmea_scanf(buff, buff_sz, + "$GPVTG,%f,%C,%f,%C,%f,%C,%f,%C*", + &(pack->dir), &(pack->dir_t), + &(pack->dec), &(pack->dec_m), + &(pack->spn), &(pack->spn_n), + &(pack->spk), &(pack->spk_k))) + { + nmea_error("GPVTG parse error!"); + return 0; + } + + if( pack->dir_t != 'T' || + pack->dec_m != 'M' || + pack->spn_n != 'N' || + pack->spk_k != 'K') + { + nmea_error("GPVTG parse error (format error)!"); + return 0; + } + + return 1; +} + +/** + * \brief Fill nmeaINFO structure by GGA packet data. + * @param pack a pointer of packet structure. + * @param info a pointer of summary information structure. + */ +void nmea_GPGGA2info(nmeaGPGGA *pack, nmeaINFO *info) +{ + //NMEA_ASSERT(pack && info); + + info->utc.hour = pack->utc.hour; + info->utc.min = pack->utc.min; + info->utc.sec = pack->utc.sec; + info->utc.hsec = pack->utc.hsec; + info->sig = pack->sig; + info->HDOP = pack->HDOP; + info->elv = pack->elv; + info->lat = ((pack->ns == 'N')?pack->lat:-(pack->lat)); + info->lon = ((pack->ew == 'E')?pack->lon:-(pack->lon)); + info->smask |= GPGGA; +} + +/** + * \brief Fill nmeaINFO structure by GSA packet data. + * @param pack a pointer of packet structure. + * @param info a pointer of summary information structure. + */ +void nmea_GPGSA2info(nmeaGPGSA *pack, nmeaINFO *info) +{ + int i, j, nuse = 0; + + //NMEA_ASSERT(pack && info); + + info->fix = pack->fix_type; + info->PDOP = pack->PDOP; + info->HDOP = pack->HDOP; + info->VDOP = pack->VDOP; + + for(i = 0; i < NMEA_MAXSAT; ++i) + { + for(j = 0; j < info->satinfo.inview; ++j) + { + if(pack->sat_prn[i] && pack->sat_prn[i] == info->satinfo.sat[j].id) + { + info->satinfo.sat[j].in_use = 1; + nuse++; + } + } + } + + info->satinfo.inuse = nuse; + info->smask |= GPGSA; +} + +/** + * \brief Fill nmeaINFO structure by GSV packet data. + * @param pack a pointer of packet structure. + * @param info a pointer of summary information structure. + */ +void nmea_GPGSV2info(nmeaGPGSV *pack, nmeaINFO *info) +{ + int isat, isi, nsat; + + //NMEA_ASSERT(pack && info); + + if(pack->pack_index > pack->pack_count || + pack->pack_index * NMEA_SATINPACK > NMEA_MAXSAT) + return; + + if(pack->pack_index < 1) + pack->pack_index = 1; + + info->satinfo.inview = pack->sat_count; + + nsat = (pack->pack_index - 1) * NMEA_SATINPACK; + nsat = (nsat + NMEA_SATINPACK > pack->sat_count)?pack->sat_count - nsat:NMEA_SATINPACK; + + for(isat = 0; isat < nsat; ++isat) + { + isi = (pack->pack_index - 1) * NMEA_SATINPACK + isat; + info->satinfo.sat[isi].id = pack->sat_data[isat].id; + info->satinfo.sat[isi].elv = pack->sat_data[isat].elv; + info->satinfo.sat[isi].azimuth = pack->sat_data[isat].azimuth; + info->satinfo.sat[isi].sig = pack->sat_data[isat].sig; + } + + info->smask |= GPGSV; +} + +/** + * \brief Fill nmeaINFO structure by RMC packet data. + * @param pack a pointer of packet structure. + * @param info a pointer of summary information structure. + */ +void nmea_GPRMC2info(nmeaGPRMC *pack, nmeaINFO *info) +{ + //NMEA_ASSERT(pack && info); + + if('A' == pack->status) + { + if(NMEA_SIG_BAD == info->sig) + info->sig = NMEA_SIG_MID; + if(NMEA_FIX_BAD == info->fix) + info->fix = NMEA_FIX_2D; + } + else if('V' == pack->status) + { + info->sig = NMEA_SIG_BAD; + info->fix = NMEA_FIX_BAD; + } + + + info->utc = pack->utc; + info->lat = ((pack->ns == 'N')?pack->lat:-(pack->lat)); + info->lon = ((pack->ew == 'E')?pack->lon:-(pack->lon)); + info->speed = pack->speed * NMEA_TUD_KNOTS; + info->direction = pack->direction; + info->smask |= GPRMC; +} + +/** + * \brief Fill nmeaINFO structure by VTG packet data. + * @param pack a pointer of packet structure. + * @param info a pointer of summary information structure. + */ +void nmea_GPVTG2info(nmeaGPVTG *pack, nmeaINFO *info) +{ + //NMEA_ASSERT(pack && info); + + info->direction = pack->dir; + info->declination = pack->dec; + info->speed = pack->spk; + info->smask |= GPVTG; +} diff --git a/apps/gps/nmealib/parser.c b/apps/gps/nmealib/parser.c new file mode 100644 index 0000000000..f8b4158661 --- /dev/null +++ b/apps/gps/nmealib/parser.c @@ -0,0 +1,400 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: parser.c 17 2008-03-11 11:56:11Z xtimor $ + * + */ + +/** + * \file parser.h + */ +#include "nmea/tok.h" +#include "nmea/parse.h" +#include "nmea/parser.h" +#include "nmea/context.h" + +#include +#include + +typedef struct _nmeaParserNODE +{ + int packType; + void *pack; + struct _nmeaParserNODE *next_node; + +} nmeaParserNODE; + +/* + * high level + */ + +/** + * \brief Initialization of parser object + * @return true (1) - success or false (0) - fail + */ +int nmea_parser_init(nmeaPARSER *parser) +{ + int resv = 0; + int buff_size = nmea_property()->parse_buff_size; + + //NMEA_ASSERT(parser); + + if(buff_size < NMEA_MIN_PARSEBUFF) + buff_size = NMEA_MIN_PARSEBUFF; + + memset(parser, 0, sizeof(nmeaPARSER)); + + if(0 == (parser->buffer = malloc(buff_size))) + nmea_error("Insufficient memory!"); + else + { + parser->buff_size = buff_size; + resv = 1; + } + + return resv; +} + +/** + * \brief Destroy parser object + */ +void nmea_parser_destroy(nmeaPARSER *parser) +{ + //NMEA_ASSERT(parser && parser->buffer); + free(parser->buffer); + nmea_parser_queue_clear(parser); + memset(parser, 0, sizeof(nmeaPARSER)); +} + +/** + * \brief Analysis of buffer and put results to information structure + * @return Number of packets wos parsed + */ +int nmea_parse( + nmeaPARSER *parser, + const char *buff, int buff_sz, + nmeaINFO *info + ) +{ + int ptype, nread = 0; + void *pack = 0; + + //NMEA_ASSERT(parser && parser->buffer); + + nmea_parser_push(parser, buff, buff_sz); + + while(GPNON != (ptype = nmea_parser_pop(parser, &pack))) + { + nread++; + + switch(ptype) + { + case GPGGA: + nmea_GPGGA2info((nmeaGPGGA *)pack, info); + break; + case GPGSA: + nmea_GPGSA2info((nmeaGPGSA *)pack, info); + break; + case GPGSV: + nmea_GPGSV2info((nmeaGPGSV *)pack, info); + break; + case GPRMC: + nmea_GPRMC2info((nmeaGPRMC *)pack, info); + break; + case GPVTG: + nmea_GPVTG2info((nmeaGPVTG *)pack, info); + break; + }; + + free(pack); + } + + return nread; +} + +/* + * low level + */ + +int nmea_parser_real_push(nmeaPARSER *parser, const char *buff, int buff_sz) +{ + int nparsed = 0, crc, sen_sz, ptype; + nmeaParserNODE *node = 0; + + //NMEA_ASSERT(parser && parser->buffer); + + /* clear unuse buffer (for debug) */ + /* + memset( + parser->buffer + parser->buff_use, 0, + parser->buff_size - parser->buff_use + ); + */ + + /* add */ + if(parser->buff_use + buff_sz >= parser->buff_size) + nmea_parser_buff_clear(parser); + + memcpy(parser->buffer + parser->buff_use, buff, buff_sz); + parser->buff_use += buff_sz; + + /* parse */ + for(;;node = 0) + { + sen_sz = nmea_find_tail( + (const char *)parser->buffer + nparsed, + (int)parser->buff_use - nparsed, &crc); + + if(!sen_sz) + { + if(nparsed) + memcpy( + parser->buffer, + parser->buffer + nparsed, + parser->buff_use -= nparsed); + break; + } + else if(crc >= 0) + { + ptype = nmea_pack_type( + (const char *)parser->buffer + nparsed + 1, + parser->buff_use - nparsed - 1); + + if(0 == (node = malloc(sizeof(nmeaParserNODE)))) + goto mem_fail; + + node->pack = 0; + + switch(ptype) + { + case GPGGA: + if(0 == (node->pack = malloc(sizeof(nmeaGPGGA)))) + goto mem_fail; + node->packType = GPGGA; + if(!nmea_parse_GPGGA( + (const char *)parser->buffer + nparsed, + sen_sz, (nmeaGPGGA *)node->pack)) + { + free(node); + node = 0; + } + break; + case GPGSA: + if(0 == (node->pack = malloc(sizeof(nmeaGPGSA)))) + goto mem_fail; + node->packType = GPGSA; + if(!nmea_parse_GPGSA( + (const char *)parser->buffer + nparsed, + sen_sz, (nmeaGPGSA *)node->pack)) + { + free(node); + node = 0; + } + break; + case GPGSV: + if(0 == (node->pack = malloc(sizeof(nmeaGPGSV)))) + goto mem_fail; + node->packType = GPGSV; + if(!nmea_parse_GPGSV( + (const char *)parser->buffer + nparsed, + sen_sz, (nmeaGPGSV *)node->pack)) + { + free(node); + node = 0; + } + break; + case GPRMC: + if(0 == (node->pack = malloc(sizeof(nmeaGPRMC)))) + goto mem_fail; + node->packType = GPRMC; + if(!nmea_parse_GPRMC( + (const char *)parser->buffer + nparsed, + sen_sz, (nmeaGPRMC *)node->pack)) + { + free(node); + node = 0; + } + break; + case GPVTG: + if(0 == (node->pack = malloc(sizeof(nmeaGPVTG)))) + goto mem_fail; + node->packType = GPVTG; + if(!nmea_parse_GPVTG( + (const char *)parser->buffer + nparsed, + sen_sz, (nmeaGPVTG *)node->pack)) + { + free(node); + node = 0; + } + break; + default: + free(node); + node = 0; + break; + }; + + if(node) + { + if(parser->end_node) + ((nmeaParserNODE *)parser->end_node)->next_node = node; + parser->end_node = node; + if(!parser->top_node) + parser->top_node = node; + node->next_node = 0; + } + } + + nparsed += sen_sz; + } + + return nparsed; + +mem_fail: + if(node) + free(node); + + nmea_error("Insufficient memory!"); + + return -1; +} + +/** + * \brief Analysis of buffer and keep results into parser + * @return Number of bytes wos parsed from buffer + */ +int nmea_parser_push(nmeaPARSER *parser, const char *buff, int buff_sz) +{ + int nparse, nparsed = 0; + + do + { + if(buff_sz > parser->buff_size) + nparse = parser->buff_size; + else + nparse = buff_sz; + + nparsed += nmea_parser_real_push( + parser, buff, nparse); + + buff_sz -= nparse; + + } while(buff_sz); + + return nparsed; +} + +/** + * \brief Get type of top packet keeped into parser + * @return Type of packet + * @see nmeaPACKTYPE + */ +int nmea_parser_top(nmeaPARSER *parser) +{ + int retval = GPNON; + nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node; + + //NMEA_ASSERT(parser && parser->buffer); + + if(node) + retval = node->packType; + + return retval; +} + +/** + * \brief Withdraw top packet from parser + * @return Received packet type + * @see nmeaPACKTYPE + */ +int nmea_parser_pop(nmeaPARSER *parser, void **pack_ptr) +{ + int retval = GPNON; + nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node; + + //NMEA_ASSERT(parser && parser->buffer); + + if(node) + { + *pack_ptr = node->pack; + retval = node->packType; + parser->top_node = node->next_node; + if(!parser->top_node) + parser->end_node = 0; + free(node); + } + + return retval; +} + +/** + * \brief Get top packet from parser without withdraw + * @return Received packet type + * @see nmeaPACKTYPE + */ +int nmea_parser_peek(nmeaPARSER *parser, void **pack_ptr) +{ + int retval = GPNON; + nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node; + + //NMEA_ASSERT(parser && parser->buffer); + + if(node) + { + *pack_ptr = node->pack; + retval = node->packType; + } + + return retval; +} + +/** + * \brief Delete top packet from parser + * @return Deleted packet type + * @see nmeaPACKTYPE + */ +int nmea_parser_drop(nmeaPARSER *parser) +{ + int retval = GPNON; + nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node; + + //NMEA_ASSERT(parser && parser->buffer); + + if(node) + { + if(node->pack) + free(node->pack); + retval = node->packType; + parser->top_node = node->next_node; + if(!parser->top_node) + parser->end_node = 0; + free(node); + } + + return retval; +} + +/** + * \brief Clear cache of parser + * @return true (1) - success + */ +int nmea_parser_buff_clear(nmeaPARSER *parser) +{ + //NMEA_ASSERT(parser && parser->buffer); + parser->buff_use = 0; + return 1; +} + +/** + * \brief Clear packets queue into parser + * @return true (1) - success + */ +int nmea_parser_queue_clear(nmeaPARSER *parser) +{ + //NMEA_ASSERT(parser); + while(parser->top_node) + nmea_parser_drop(parser); + return 1; +} diff --git a/apps/gps/nmealib/sentence.c b/apps/gps/nmealib/sentence.c new file mode 100644 index 0000000000..a66393a4da --- /dev/null +++ b/apps/gps/nmealib/sentence.c @@ -0,0 +1,54 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: sentence.c 17 2008-03-11 11:56:11Z xtimor $ + * + */ + +#include "nmea/sentence.h" + +#include + +void nmea_zero_GPGGA(nmeaGPGGA *pack) +{ + memset(pack, 0, sizeof(nmeaGPGGA)); + nmea_time_now(&pack->utc); + pack->ns = 'N'; + pack->ew = 'E'; + pack->elv_units = 'M'; + pack->diff_units = 'M'; +} + +void nmea_zero_GPGSA(nmeaGPGSA *pack) +{ + memset(pack, 0, sizeof(nmeaGPGSA)); + pack->fix_mode = 'A'; + pack->fix_type = NMEA_FIX_BAD; +} + +void nmea_zero_GPGSV(nmeaGPGSV *pack) +{ + memset(pack, 0, sizeof(nmeaGPGSV)); +} + +void nmea_zero_GPRMC(nmeaGPRMC *pack) +{ + memset(pack, 0, sizeof(nmeaGPRMC)); + nmea_time_now(&pack->utc); + pack->status = 'V'; + pack->ns = 'N'; + pack->ew = 'E'; + pack->declin_ew = 'E'; +} + +void nmea_zero_GPVTG(nmeaGPVTG *pack) +{ + memset(pack, 0, sizeof(nmeaGPVTG)); + pack->dir_t = 'T'; + pack->dec_m = 'M'; + pack->spn_n = 'N'; + pack->spk_k = 'K'; +} diff --git a/apps/gps/nmealib/time.c b/apps/gps/nmealib/time.c new file mode 100644 index 0000000000..a243196301 --- /dev/null +++ b/apps/gps/nmealib/time.c @@ -0,0 +1,63 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: time.c 4 2007-08-27 13:11:03Z xtimor $ + * + */ + +/*! \file time.h */ + +#include "nmea/time.h" + +#ifdef NMEA_WIN +# pragma warning(disable: 4201) +# pragma warning(disable: 4214) +# pragma warning(disable: 4115) +# include +# pragma warning(default: 4201) +# pragma warning(default: 4214) +# pragma warning(default: 4115) +#else +# include +#endif + +#ifdef NMEA_WIN + +void nmea_time_now(nmeaTIME *stm) +{ + SYSTEMTIME st; + + GetSystemTime(&st); + + stm->year = st.wYear - 1900; + stm->mon = st.wMonth - 1; + stm->day = st.wDay; + stm->hour = st.wHour; + stm->min = st.wMinute; + stm->sec = st.wSecond; + stm->hsec = st.wMilliseconds / 10; +} + +#else /* NMEA_WIN */ + +void nmea_time_now(nmeaTIME *stm) +{ + time_t lt; + struct tm *tt; + + time(<); + tt = gmtime(<); + + stm->year = tt->tm_year; + stm->mon = tt->tm_mon; + stm->day = tt->tm_mday; + stm->hour = tt->tm_hour; + stm->min = tt->tm_min; + stm->sec = tt->tm_sec; + stm->hsec = 0; +} + +#endif diff --git a/apps/gps/nmealib/tok.c b/apps/gps/nmealib/tok.c new file mode 100644 index 0000000000..c7cf2f4dcb --- /dev/null +++ b/apps/gps/nmealib/tok.c @@ -0,0 +1,267 @@ +/* + * + * NMEA library + * URL: http://nmea.sourceforge.net + * Author: Tim (xtimor@gmail.com) + * Licence: http://www.gnu.org/licenses/lgpl.html + * $Id: tok.c 17 2008-03-11 11:56:11Z xtimor $ + * + */ + +/*! \file tok.h */ + +#include "nmea/tok.h" + +#include +#include +#include +#include +#include +#include + +#define NMEA_TOKS_COMPARE (1) +#define NMEA_TOKS_PERCENT (2) +#define NMEA_TOKS_WIDTH (3) +#define NMEA_TOKS_TYPE (4) + +//memchr replacement +void * +memchr(s, c, n) + const void *s; + unsigned char c; + size_t n; +{ + if (n != 0) { + const unsigned char *p = s; + + do { + if (*p++ == c) + return ((void *)(p - 1)); + } while (--n != 0); + } + return (NULL); +} + + +/** + * \brief Calculate control sum of binary buffer + */ +int nmea_calc_crc(const char *buff, int buff_sz) +{ + int chsum = 0, + it; + + for(it = 0; it < buff_sz; ++it) + chsum ^= (int)buff[it]; + + return chsum; +} + +/** + * \brief Convert string to number + */ +int nmea_atoi(const char *str, int str_sz, int radix) +{ + char *tmp_ptr; + char buff[NMEA_CONVSTR_BUF]; + int res = 0; + + if(str_sz < NMEA_CONVSTR_BUF) + { + memcpy(&buff[0], str, str_sz); + buff[str_sz] = '\0'; + res = strtol(&buff[0], &tmp_ptr, radix); + } + return res; +} + +/** + * \brief Convert string to fraction number + */ +float nmea_atof(const char *str, int str_sz) +{ + char *tmp_ptr; + char buff[NMEA_CONVSTR_BUF]; + float res = 0; + + if(str_sz < NMEA_CONVSTR_BUF) + { + memcpy(&buff[0], str, str_sz); + buff[str_sz] = '\0'; + res = (float)strtod(&buff[0], &tmp_ptr); + } + return res; +} + +/** + * \brief Formating string (like standart printf) with CRC tail (*CRC) + */ +int nmea_printf(char *buff, int buff_sz, const char *format, ...) +{ + int retval, add = 0; + va_list arg_ptr; + + if(buff_sz <= 0) + return 0; + + va_start(arg_ptr, format); + + retval = NMEA_POSIX(vsnprintf)(buff, buff_sz, format, arg_ptr); + + if(retval > 0) + { + add = NMEA_POSIX(snprintf)( + buff + retval, buff_sz - retval, "*%02x\r\n", + nmea_calc_crc(buff + 1, retval - 1)); + } + + retval += add; + + if(retval < 0 || retval > buff_sz) + { + memset(buff, ' ', buff_sz); + retval = buff_sz; + } + + va_end(arg_ptr); + + return retval; +} + +/** + * \brief Analyse string (specificate for NMEA sentences) + */ +int nmea_scanf(const char *buff, int buff_sz, const char *format, ...) +{ + const char *beg_tok; + const char *end_buf = buff + buff_sz; + + va_list arg_ptr; + int tok_type = NMEA_TOKS_COMPARE; + int width = 0; + const char *beg_fmt = 0; + int snum = 0, unum = 0; + + int tok_count = 0; + void *parg_target; + + va_start(arg_ptr, format); + + for(; *format && buff < end_buf; ++format) + { + switch(tok_type) + { + case NMEA_TOKS_COMPARE: + if('%' == *format) + tok_type = NMEA_TOKS_PERCENT; + else if(*buff++ != *format) + goto fail; + break; + case NMEA_TOKS_PERCENT: + width = 0; + beg_fmt = format; + tok_type = NMEA_TOKS_WIDTH; + case NMEA_TOKS_WIDTH: + if(isdigit(*format)) + break; + { + tok_type = NMEA_TOKS_TYPE; + if(format > beg_fmt) + width = nmea_atoi(beg_fmt, (int)(format - beg_fmt), 10); + } + case NMEA_TOKS_TYPE: + beg_tok = buff; + + if(!width && ('c' == *format || 'C' == *format) && *buff != format[1]) + width = 1; + + if(width) + { + if(buff + width <= end_buf) + buff += width; + else + goto fail; + } + else + { + if(!format[1] || (0 == (buff = (char *)memchr(buff, format[1], end_buf - buff)))) + buff = end_buf; + } + + if(buff > end_buf) + goto fail; + + tok_type = NMEA_TOKS_COMPARE; + tok_count++; + + parg_target = 0; width = (int)(buff - beg_tok); + + switch(*format) + { + case 'c': + case 'C': + parg_target = (void *)va_arg(arg_ptr, char *); + if(width && 0 != (parg_target)) + *((char *)parg_target) = *beg_tok; + break; + case 's': + case 'S': + parg_target = (void *)va_arg(arg_ptr, char *); + if(width && 0 != (parg_target)) + { + memcpy(parg_target, beg_tok, width); + ((char *)parg_target)[width] = '\0'; + } + break; + case 'f': + case 'g': + case 'G': + case 'e': + case 'E': + parg_target = (void *)va_arg(arg_ptr, float *); + if(width && 0 != (parg_target)) + *((float *)parg_target) = nmea_atof(beg_tok, width); + break; + }; + + if(parg_target) + break; + if(0 == (parg_target = (void *)va_arg(arg_ptr, int *))) + break; + if(!width) + break; + + switch(*format) + { + case 'd': + case 'i': + snum = nmea_atoi(beg_tok, width, 10); + memcpy(parg_target, &snum, sizeof(int)); + break; + case 'u': + unum = nmea_atoi(beg_tok, width, 10); + memcpy(parg_target, &unum, sizeof(unsigned int)); + break; + case 'x': + case 'X': + unum = nmea_atoi(beg_tok, width, 16); + memcpy(parg_target, &unum, sizeof(unsigned int)); + break; + case 'o': + unum = nmea_atoi(beg_tok, width, 8); + memcpy(parg_target, &unum, sizeof(unsigned int)); + break; + default: + goto fail; + }; + + break; + }; + } + +fail: + + va_end(arg_ptr); + + return tok_count; +} diff --git a/apps/gps/ubx.c b/apps/gps/ubx.c new file mode 100644 index 0000000000..771dfbd6c0 --- /dev/null +++ b/apps/gps/ubx.c @@ -0,0 +1,863 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: Thomas Gubler + * Julian Oes + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* @file U-Blox protocol implementation */ + +#include "ubx.h" +#include +#include +#include +#include +#include +#include +#include + +#define UBX_HEALTH_SUCCESS_COUNTER_LIMIT 2 +#define UBX_HEALTH_FAIL_COUNTER_LIMIT 2 + +#define UBX_BUFFER_SIZE 1000 + +extern bool gps_mode_try_all; +extern bool gps_mode_success; +extern bool terminate_gps_thread; +extern bool gps_baud_try_all; +extern bool gps_verbose; +extern int current_gps_speed; + +pthread_mutex_t *ubx_mutex; +gps_bin_ubx_state_t *ubx_state; +static struct vehicle_gps_position_s *ubx_gps; + + +//Definitions for ubx, last two bytes are checksum which is calculated below +uint8_t UBX_CONFIG_MESSAGE_PRT[] = {0xB5 , 0x62 , 0x06 , 0x00 , 0x14 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0xD0 , 0x08 , 0x00 , 0x00 , 0x80 , 0x25 , 0x00 , 0x00 , 0x07 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00}; +uint8_t UBX_CONFIG_MESSAGE_MSG_NAV_POSLLH[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0x01, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}; +uint8_t UBX_CONFIG_MESSAGE_MSG_NAV_TIMEUTC[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0x01, 0x21, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}; +uint8_t UBX_CONFIG_MESSAGE_MSG_NAV_DOP[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0x01, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}; +uint8_t UBX_CONFIG_MESSAGE_MSG_NAV_SVINFO[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0x01, 0x30, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}; +uint8_t UBX_CONFIG_MESSAGE_MSG_NAV_SOL[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0x01, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}; +uint8_t UBX_CONFIG_MESSAGE_MSG_NAV_VELNED[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0x01, 0x12, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}; +uint8_t UBX_CONFIG_MESSAGE_MSG_RXM_SVSI[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0x02, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}; + +void ubx_decode_init(void) +{ + ubx_state->ck_a = 0; + ubx_state->ck_b = 0; + ubx_state->rx_count = 0; + ubx_state->decode_state = UBX_DECODE_UNINIT; + ubx_state->message_class = CLASS_UNKNOWN; + ubx_state->message_id = ID_UNKNOWN; + ubx_state->payload_size = 0; + ubx_state->print_errors = false; +} + +void ubx_checksum(uint8_t b, uint8_t *ck_a, uint8_t *ck_b) +{ + *(ck_a) = *(ck_a) + b; + *(ck_b) = *(ck_b) + *(ck_a); +} + + + + + +int ubx_parse(uint8_t b, char *gps_rx_buffer) +{ +// printf("b=%x\n",b); + if (ubx_state->decode_state == UBX_DECODE_UNINIT) { + + if (b == 0xb5) { + ubx_state->decode_state = UBX_DECODE_GOT_SYNC1; + } + + } else if (ubx_state->decode_state == UBX_DECODE_GOT_SYNC1) { + if (b == 0x62) { + ubx_state->decode_state = UBX_DECODE_GOT_SYNC2; + + } else { + // Second start symbol was wrong, reset state machine + ubx_decode_init(); + } + + } else if (ubx_state->decode_state == UBX_DECODE_GOT_SYNC2) { + // Add to checksum + ubx_checksum(b, &(ubx_state->ck_a), &(ubx_state->ck_b)); + + //check for known class + switch (b) { + case UBX_CLASS_NAV: //NAV + ubx_state->decode_state = UBX_DECODE_GOT_CLASS; + ubx_state->message_class = NAV; + break; + + case UBX_CLASS_RXM: //RXM + ubx_state->decode_state = UBX_DECODE_GOT_CLASS; + ubx_state->message_class = RXM; + break; + + default: //unknown class: reset state machine + ubx_decode_init(); + break; + } + + } else if (ubx_state->decode_state == UBX_DECODE_GOT_CLASS) { + // Add to checksum + ubx_checksum(b, &(ubx_state->ck_a), &(ubx_state->ck_b)); + + //depending on class look for message id + switch (ubx_state->message_class) { + case NAV: + switch (b) { + case UBX_MESSAGE_NAV_POSLLH: //NAV-POSLLH: Geodetic Position Solution + ubx_state->decode_state = UBX_DECODE_GOT_MESSAGEID; + ubx_state->message_id = NAV_POSLLH; + break; + + case UBX_MESSAGE_NAV_SOL: + ubx_state->decode_state = UBX_DECODE_GOT_MESSAGEID; + ubx_state->message_id = NAV_SOL; + break; + + case UBX_MESSAGE_NAV_TIMEUTC: + ubx_state->decode_state = UBX_DECODE_GOT_MESSAGEID; + ubx_state->message_id = NAV_TIMEUTC; + break; + + case UBX_MESSAGE_NAV_DOP: + ubx_state->decode_state = UBX_DECODE_GOT_MESSAGEID; + ubx_state->message_id = NAV_DOP; + break; + + case UBX_MESSAGE_NAV_SVINFO: + ubx_state->decode_state = UBX_DECODE_GOT_MESSAGEID; + ubx_state->message_id = NAV_SVINFO; + break; + + case UBX_MESSAGE_NAV_VELNED: + ubx_state->decode_state = UBX_DECODE_GOT_MESSAGEID; + ubx_state->message_id = NAV_VELNED; + break; + + default: //unknown class: reset state machine, should not happen + ubx_decode_init(); + break; + } + + break; + + case RXM: + switch (b) { + case UBX_MESSAGE_RXM_SVSI: + ubx_state->decode_state = UBX_DECODE_GOT_MESSAGEID; + ubx_state->message_id = RXM_SVSI; + break; + + default: //unknown class: reset state machine, should not happen + ubx_decode_init(); + break; + } + + break; + + default: //should not happen + ubx_decode_init(); + break; + } + + } else if (ubx_state->decode_state == UBX_DECODE_GOT_MESSAGEID) { + // Add to checksum + ubx_checksum(b, &(ubx_state->ck_a), &(ubx_state->ck_b)); + + ubx_state->payload_size = b; + ubx_state->decode_state = UBX_DECODE_GOT_LENGTH1; + + } else if (ubx_state->decode_state == UBX_DECODE_GOT_LENGTH1) { + // Add to checksum + ubx_checksum(b, &(ubx_state->ck_a), &(ubx_state->ck_b)); + + ubx_state->payload_size += b << 8; + ubx_state->decode_state = UBX_DECODE_GOT_LENGTH2; + + } else if (ubx_state->decode_state == UBX_DECODE_GOT_LENGTH2) { + uint8_t ret = 0; + + // Add to checksum if not yet at checksum byte + if (ubx_state->rx_count < ubx_state->payload_size) ubx_checksum(b, &(ubx_state->ck_a), &(ubx_state->ck_b)); + + // Fill packet buffer + gps_rx_buffer[ubx_state->rx_count] = b; + + //if whole payload + checksum is in buffer: + if (ubx_state->rx_count >= ubx_state->payload_size + 1) { + //convert to correct struct + switch (ubx_state->message_id) { //this enum is unique for all ids --> no need to check the class + case NAV_POSLLH: { +// printf("GOT NAV_POSLLH MESSAGE\n"); + gps_bin_nav_posllh_packet_t *packet = (gps_bin_nav_posllh_packet_t *) gps_rx_buffer; + + //Check if checksum is valid and the store the gps information + if (ubx_state->ck_a == packet->ck_a && ubx_state->ck_b == packet->ck_b) { + ubx_gps->lat = packet->lat; + ubx_gps->lon = packet->lon; + ubx_gps->alt = packet->height_msl; + + ubx_gps->counter_pos_valid++; + + ubx_gps->timestamp = hrt_absolute_time(); + ubx_gps->counter++; + + pthread_mutex_lock(ubx_mutex); + ubx_state->last_message_timestamps[NAV_POSLLH - 1] = hrt_absolute_time(); + pthread_mutex_unlock(ubx_mutex); + ret = 1; + + } else { + if (gps_verbose) printf("[gps] NAV_POSLLH: checksum invalid\n"); + + ret = 0; + } + + // Reset state machine to decode next packet + ubx_decode_init(); + return ret; + + break; + } + + case NAV_SOL: { +// printf("GOT NAV_SOL MESSAGE\n"); + gps_bin_nav_sol_packet_t *packet = (gps_bin_nav_sol_packet_t *) gps_rx_buffer; + + //Check if checksum is valid and the store the gps information + if (ubx_state->ck_a == packet->ck_a && ubx_state->ck_b == packet->ck_b) { + + ubx_gps->fix_type = packet->gpsFix; + + ubx_gps->timestamp = hrt_absolute_time(); + ubx_gps->counter++; + + + pthread_mutex_lock(ubx_mutex); + ubx_state->last_message_timestamps[NAV_SOL - 1] = hrt_absolute_time(); + pthread_mutex_unlock(ubx_mutex); + ret = 1; + + } else { + if (gps_verbose) printf("[gps] NAV_SOL: checksum invalid\n"); + + ret = 0; + } + + // Reset state machine to decode next packet + ubx_decode_init(); + return ret; + + break; + } + + case NAV_DOP: { +// printf("GOT NAV_DOP MESSAGE\n"); + gps_bin_nav_dop_packet_t *packet = (gps_bin_nav_dop_packet_t *) gps_rx_buffer; + + //Check if checksum is valid and the store the gps information + if (ubx_state->ck_a == packet->ck_a && ubx_state->ck_b == packet->ck_b) { + + ubx_gps->eph = packet->hDOP; + ubx_gps->epv = packet->vDOP; + + ubx_gps->timestamp = hrt_absolute_time(); + ubx_gps->counter++; + + + pthread_mutex_lock(ubx_mutex); + ubx_state->last_message_timestamps[NAV_DOP - 1] = hrt_absolute_time(); + pthread_mutex_unlock(ubx_mutex); + ret = 1; + + } else { + if (gps_verbose) printf("[gps] NAV_DOP: checksum invalid\n"); + + ret = 0; + } + + // Reset state machine to decode next packet + ubx_decode_init(); + return ret; + + break; + } + + case NAV_TIMEUTC: { +// printf("GOT NAV_TIMEUTC MESSAGE\n"); + gps_bin_nav_timeutc_packet_t *packet = (gps_bin_nav_timeutc_packet_t *) gps_rx_buffer; + + //Check if checksum is valid and the store the gps information + if (ubx_state->ck_a == packet->ck_a && ubx_state->ck_b == packet->ck_b) { + //convert to unix timestamp + struct tm timeinfo; + timeinfo.tm_year = packet->year - 1900; + timeinfo.tm_mon = packet->month - 1; + timeinfo.tm_mday = packet->day; + timeinfo.tm_hour = packet->hour; + timeinfo.tm_min = packet->min; + timeinfo.tm_sec = packet->sec; + + time_t epoch = mktime(&timeinfo); + +// printf("%d.%d.%d %d:%d:%d:%d\n", timeinfo.tm_year, timeinfo.tm_mon, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, packet->time_nanoseconds); + + + + ubx_gps->time_gps_usec = (uint64_t)epoch * 1e6; //TODO: test this + ubx_gps->time_gps_usec += packet->time_nanoseconds * 1e-3; + + ubx_gps->timestamp = hrt_absolute_time(); + ubx_gps->counter++; + + + pthread_mutex_lock(ubx_mutex); + ubx_state->last_message_timestamps[NAV_TIMEUTC - 1] = hrt_absolute_time(); + pthread_mutex_unlock(ubx_mutex); + ret = 1; + + } else { + if (gps_verbose) printf("\t[gps] NAV_TIMEUTC: checksum invalid\n"); + + ret = 0; + } + + // Reset state machine to decode next packet + ubx_decode_init(); + return ret; + + break; + } + + case NAV_SVINFO: { +// printf("GOT NAV_SVINFO MESSAGE\n"); + + //this is a more complicated message: the length depends on the number of satellites. This number is extracted from the first part of the message + const int length_part1 = 8; + char gps_rx_buffer_part1[length_part1]; + memcpy(gps_rx_buffer_part1, gps_rx_buffer, length_part1); + gps_bin_nav_svinfo_part1_packet_t *packet_part1 = (gps_bin_nav_svinfo_part1_packet_t *) gps_rx_buffer_part1; + + //read checksum + const int length_part3 = 2; + char gps_rx_buffer_part3[length_part3]; + memcpy(gps_rx_buffer_part3, &(gps_rx_buffer[ubx_state->rx_count - 1]), length_part3); + gps_bin_nav_svinfo_part3_packet_t *packet_part3 = (gps_bin_nav_svinfo_part3_packet_t *) gps_rx_buffer_part3; + + //Check if checksum is valid and then store the gps information + if (ubx_state->ck_a == packet_part3->ck_a && ubx_state->ck_b == packet_part3->ck_b) { + //definitions needed to read numCh elements from the buffer: + const int length_part2 = 12; + gps_bin_nav_svinfo_part2_packet_t *packet_part2; + char gps_rx_buffer_part2[length_part2]; //for temporal storage + + + int i; + + for (i = 0; i < packet_part1->numCh; i++) { //for each channel + + /* Get satellite information from the buffer */ + + memcpy(gps_rx_buffer_part2, &(gps_rx_buffer[length_part1 + i * length_part2]), length_part2); + packet_part2 = (gps_bin_nav_svinfo_part2_packet_t *) gps_rx_buffer_part2; + + + /* Write satellite information in the global storage */ + + ubx_gps->satellite_prn[i] = packet_part2->svid; + + //if satellite information is healthy store the data + uint8_t unhealthy = packet_part2->flags & 1 << 4; //flags is a bitfield + + if (!unhealthy) { + + if ((packet_part2->flags) & 1) { //flags is a bitfield + ubx_gps->satellite_used[i] = 1; + + } else { + ubx_gps->satellite_used[i] = 0; + } + + ubx_gps->satellite_snr[i] = packet_part2->cno; + ubx_gps->satellite_elevation[i] = (uint8_t)(packet_part2->elev); + ubx_gps->satellite_azimuth[i] = (uint8_t)((float)packet_part2->azim * 255.0f / 360.0f); + + } else { + ubx_gps->satellite_used[i] = 0; + ubx_gps->satellite_snr[i] = 0; + ubx_gps->satellite_elevation[i] = 0; + ubx_gps->satellite_azimuth[i] = 0; + } + + } + + for (i = packet_part1->numCh; i < 20; i++) { //these channels are unused + /* Unused channels have to be set to zero for e.g. MAVLink */ + ubx_gps->satellite_prn[i] = 0; + ubx_gps->satellite_used[i] = 0; + ubx_gps->satellite_snr[i] = 0; + ubx_gps->satellite_elevation[i] = 0; + ubx_gps->satellite_azimuth[i] = 0; + } + + /* set flag if any sat info is available */ + if (!packet_part1->numCh > 0) { + ubx_gps->satellite_info_available = 1; + + } else { + ubx_gps->satellite_info_available = 0; + } + + ubx_gps->timestamp = hrt_absolute_time(); + ubx_gps->counter++; + + + pthread_mutex_lock(ubx_mutex); + ubx_state->last_message_timestamps[NAV_SVINFO - 1] = hrt_absolute_time(); + pthread_mutex_unlock(ubx_mutex); + ret = 1; + + } else { + if (gps_verbose) printf("\t[gps] NAV_SVINFO: checksum invalid\n"); + + ret = 0; + } + + // Reset state machine to decode next packet + ubx_decode_init(); + return ret; + + break; + } + + case NAV_VELNED: { +// printf("GOT NAV_VELNED MESSAGE\n"); + gps_bin_nav_velned_packet_t *packet = (gps_bin_nav_velned_packet_t *) gps_rx_buffer; + + //Check if checksum is valid and the store the gps information + if (ubx_state->ck_a == packet->ck_a && ubx_state->ck_b == packet->ck_b) { + + ubx_gps->vel = (uint16_t)packet->speed; + ubx_gps->cog = (uint16_t)((float)(packet->heading) * 1e-3); + + ubx_gps->timestamp = hrt_absolute_time(); + ubx_gps->counter++; + + + pthread_mutex_lock(ubx_mutex); + ubx_state->last_message_timestamps[NAV_VELNED - 1] = hrt_absolute_time(); + pthread_mutex_unlock(ubx_mutex); + ret = 1; + + } else { + if (gps_verbose) printf("[gps] NAV_VELNED: checksum invalid\n"); + + ret = 0; + } + + // Reset state machine to decode next packet + ubx_decode_init(); + return ret; + + break; + } + + case RXM_SVSI: { +// printf("GOT RXM_SVSI MESSAGE\n"); + const int length_part1 = 7; + char gps_rx_buffer_part1[length_part1]; + memcpy(gps_rx_buffer_part1, gps_rx_buffer, length_part1); + gps_bin_rxm_svsi_packet_t *packet = (gps_bin_rxm_svsi_packet_t *) gps_rx_buffer_part1; + + //Check if checksum is valid and the store the gps information + if (ubx_state->ck_a == gps_rx_buffer[ubx_state->rx_count - 1] && ubx_state->ck_b == gps_rx_buffer[ubx_state->rx_count]) { + + ubx_gps->satellites_visible = packet->numVis; + + ubx_gps->timestamp = hrt_absolute_time(); + ubx_gps->counter++; + + + pthread_mutex_lock(ubx_mutex); + ubx_state->last_message_timestamps[RXM_SVSI - 1] = hrt_absolute_time(); + pthread_mutex_unlock(ubx_mutex); + ret = 1; + + } else { + if (gps_verbose) printf("[gps] RXM_SVSI: checksum invalid\n"); + + ret = 0; + } + + // Reset state machine to decode next packet + ubx_decode_init(); + return ret; + + break; + } + + default: //something went wrong + ubx_decode_init(); + + break; + } + } + + (ubx_state->rx_count)++; + + + + } + + + return 0; // no valid packet found + +} + +void calculate_ubx_checksum(uint8_t *message, uint8_t length) +{ + uint8_t ck_a = 0; + uint8_t ck_b = 0; + + int i; + + for (i = 2; i < length - 2; i++) { + ck_a = ck_a + message[i]; + ck_b = ck_b + ck_a; + } + + message[length - 2] = ck_a; + message[length - 1] = ck_b; + +// printf("[%x,%x]", ck_a, ck_b); + +// printf("[%x,%x]\n", message[length-2], message[length-1]); +} + +int configure_gps_ubx(int fd) +{ + fflush((FILE *)fd); + + //TODO: write this in a loop once it is tested + //UBX_CFG_PRT_PART: + write_config_message_ubx(UBX_CONFIG_MESSAGE_PRT, sizeof(UBX_CONFIG_MESSAGE_PRT) / sizeof(uint8_t) , fd); + + usleep(100000); + + //NAV_POSLLH: + write_config_message_ubx(UBX_CONFIG_MESSAGE_MSG_NAV_POSLLH, sizeof(UBX_CONFIG_MESSAGE_MSG_NAV_POSLLH) / sizeof(uint8_t) , fd); + usleep(100000); + + //NAV_TIMEUTC: + write_config_message_ubx(UBX_CONFIG_MESSAGE_MSG_NAV_TIMEUTC, sizeof(UBX_CONFIG_MESSAGE_MSG_NAV_TIMEUTC) / sizeof(uint8_t) , fd); + usleep(100000); + + //NAV_DOP: + write_config_message_ubx(UBX_CONFIG_MESSAGE_MSG_NAV_DOP, sizeof(UBX_CONFIG_MESSAGE_MSG_NAV_DOP) / sizeof(uint8_t) , fd); + usleep(100000); + + //NAV_SOL: + write_config_message_ubx(UBX_CONFIG_MESSAGE_MSG_NAV_SOL, sizeof(UBX_CONFIG_MESSAGE_MSG_NAV_SOL) / sizeof(uint8_t) , fd); + usleep(100000); + + + //NAV_SVINFO: + write_config_message_ubx(UBX_CONFIG_MESSAGE_MSG_NAV_SVINFO, sizeof(UBX_CONFIG_MESSAGE_MSG_NAV_SVINFO) / sizeof(uint8_t) , fd); + usleep(100000); + + //NAV_VELNED: + write_config_message_ubx(UBX_CONFIG_MESSAGE_MSG_NAV_VELNED, sizeof(UBX_CONFIG_MESSAGE_MSG_NAV_VELNED) / sizeof(uint8_t) , fd); + usleep(100000); + + + //RXM_SVSI: + write_config_message_ubx(UBX_CONFIG_MESSAGE_MSG_RXM_SVSI, sizeof(UBX_CONFIG_MESSAGE_MSG_RXM_SVSI) / sizeof(uint8_t) , fd); + usleep(100000); + + return 0; +} + + + +int read_gps_ubx(int fd, char *gps_rx_buffer, int buffer_size) +{ + + uint8_t ret = 0; + uint8_t c; + int rx_count = 0; + int gpsRxOverflow = 0; + + struct pollfd fds; + fds.fd = fd; + fds.events = POLLIN; + + // UBX GPS mode + + // This blocks the task until there is something on the buffer + while (1) { + //check if the thread should terminate + if (terminate_gps_thread == true) { +// printf("terminate_gps_thread=%u ", terminate_gps_thread); +// printf("exiting mtk thread\n"); +// fflush(stdout); + ret = 1; + break; + } + + if (poll(&fds, 1, 1000) > 0) { + if (read(fd, &c, 1) > 0) { + + // printf("Read %x\n",c); + if (rx_count >= buffer_size) { + // The buffer is already full and we haven't found a valid ubx sentence. + // Flush the buffer and note the overflow event. + gpsRxOverflow++; + rx_count = 0; + ubx_decode_init(); + + if (gps_verbose) printf("[gps] Buffer full\n"); + + } else { + //gps_rx_buffer[rx_count] = c; + rx_count++; + + } + + int msg_read = ubx_parse(c, gps_rx_buffer); + + if (msg_read > 0) { + // printf("Found sequence\n"); + break; + } + + } else { + break; + } + + } else { + break; + } + + } + + return ret; +} + +int write_config_message_ubx(uint8_t *message, size_t length, int fd) +{ + //calculate and write checksum to the end + uint8_t ck_a = 0; + uint8_t ck_b = 0; + + int i; + + for (i = 2; i < length; i++) { + ck_a = ck_a + message[i]; + ck_b = ck_b + ck_a; + } + +// printf("[%x,%x]\n", ck_a, ck_b); + + int result_write = write(fd, message, length); + result_write += write(fd, &ck_a, 1); + result_write += write(fd, &ck_b, 1); + + return (result_write != length + 2); //return 0 as success + +} + +void *ubx_watchdog_loop(void *arg) +{ + /* Set thread name */ + prctl(PR_SET_NAME, "gps ubx watchdog", getpid()); + + + /* Retrieve file descriptor */ + int fd = *((int *)arg); + + /* GPS watchdog error message skip counter */ + + bool ubx_healthy = false; + + uint8_t ubx_fail_count = 0; + uint8_t ubx_success_count = 0; + bool once_ok = false; + + int mavlink_fd = open(MAVLINK_LOG_DEVICE, 0); + + while (1) { + /* if some values are to old reconfigure gps */ + int i; + pthread_mutex_lock(ubx_mutex); + bool all_okay = true; + uint64_t timestamp_now = hrt_absolute_time(); + + for (i = 0; i < UBX_NO_OF_MESSAGES; i++) { +// printf("timestamp_now=%llu\n", timestamp_now); +// printf("last_message_timestamps=%llu\n", ubx_state->last_message_timestamps[i]); + if (timestamp_now - ubx_state->last_message_timestamps[i] > UBX_WATCHDOG_CRITICAL_TIME_MICROSECONDS) { +// printf("Warning: GPS ubx message %d not received for a long time\n", i); + all_okay = false; + } + } + + pthread_mutex_unlock(ubx_mutex); + + if (!all_okay) { + /* gps error */ + ubx_fail_count++; +// if (err_skip_counter == 0) +// { +// printf("GPS Watchdog detected gps not running or having problems\n"); +// err_skip_counter = 20; +// } +// err_skip_counter--; +// printf("gps_mode_try_all =%u, ubx_fail_count=%u, ubx_healthy=%u, once_ok=%u\n", gps_mode_try_all, ubx_fail_count, ubx_healthy, once_ok); + + + /* If we have too many failures and another mode or baud should be tried, exit... */ + if ((gps_mode_try_all == true || gps_baud_try_all == true) && (ubx_fail_count >= UBX_HEALTH_FAIL_COUNTER_LIMIT) && (ubx_healthy == false) && once_ok == false) { + if (gps_verbose) printf("[gps] Connection attempt failed, no UBX module found\r\n"); + + gps_mode_success = false; + break; + } + + if (ubx_healthy && ubx_fail_count == UBX_HEALTH_FAIL_COUNTER_LIMIT) { + printf("[gps] ERROR: UBX GPS module stopped responding\r\n"); + // global_data_send_subsystem_info(&ubx_present_enabled); + mavlink_log_critical(mavlink_fd, "[gps] UBX module stopped responding\n"); + ubx_healthy = false; + ubx_success_count = 0; + } + + /* trying to reconfigure the gps configuration */ + configure_gps_ubx(fd); + fflush(stdout); + sleep(1); + + } else { + /* gps healthy */ + ubx_success_count++; + + if (!ubx_healthy && ubx_success_count == UBX_HEALTH_SUCCESS_COUNTER_LIMIT) { + printf("[gps] ublox UBX module status ok (baud=%d)\r\n", current_gps_speed); + // global_data_send_subsystem_info(&ubx_present_enabled_healthy); + mavlink_log_info(mavlink_fd, "[gps] UBX module found, status ok\n"); + ubx_healthy = true; + ubx_fail_count = 0; + once_ok = true; + } + + } + + usleep(UBX_WATCHDOG_WAIT_TIME_MICROSECONDS); + } + + close(mavlink_fd); + + return NULL; +} + +void *ubx_loop(void *arg) +{ + /* Set thread name */ + prctl(PR_SET_NAME, "gps ubx read", getpid()); + + /* Retrieve file descriptor */ + int fd = *((int *)arg); + + /* Initialize gps stuff */ + char gps_rx_buffer[UBX_BUFFER_SIZE]; + + + if (gps_verbose) printf("[gps] UBX protocol driver starting..\r\n"); + + //set parameters for ubx + + +// //ubx state +// gps_bin_ubx_state_t * ubx_state = malloc(sizeof(gps_bin_ubx_state_t)); +// printf("gps: ubx_state created\n"); +// ubx_decode_init(); +// ubx_state->print_errors = false; + + + /* set parameters for ubx */ + + if (configure_gps_ubx(fd) != 0) { + printf("[gps] Configuration of gps module to ubx failed\r\n"); + + /* Write shared variable sys_status */ + + //global_data_send_subsystem_info(&ubx_present); + + } else { + if (gps_verbose) printf("[gps] Attempting to configure GPS to UBX binary protocol\r\n"); + + // XXX Shouldn't the system status only change if the module is known to work ok? + + /* Write shared variable sys_status */ + + //global_data_send_subsystem_info(&ubx_present_enabled); + } + + struct vehicle_gps_position_s ubx_gps_d = {0}; + + ubx_gps = &ubx_gps_d; + + int gps_pub = orb_advertise(ORB_ID(vehicle_gps_position), &ubx_gps); + + while (1) { + /* Parse a message from the gps receiver */ + if (0 == read_gps_ubx(fd, gps_rx_buffer, UBX_BUFFER_SIZE)) { + /* publish new GPS position */ + orb_publish(ORB_ID(vehicle_gps_position), gps_pub, ubx_gps); + + } else { + /* de-advertise */ + close(gps_pub); + break; + } + } + + + return NULL; + +} diff --git a/apps/gps/ubx.h b/apps/gps/ubx.h new file mode 100644 index 0000000000..5def1ed33d --- /dev/null +++ b/apps/gps/ubx.h @@ -0,0 +1,314 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: Thomas Gubler + * Julian Oes + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* @file U-Blox protocol definitions */ + +#ifndef UBX_H_ +#define UBX_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + + +//internal definitions (not depending on the ubx protocol +#define CONFIGURE_UBX_FINISHED 0 +#define CONFIGURE_UBX_MESSAGE_ACKNOWLEDGED 1 +#define CONFIGURE_UBX_MESSAGE_NOT_ACKNOWLEDGED 2 +#define UBX_NO_OF_MESSAGES 7 /**< Read 7 UBX GPS messages */ +#define UBX_WATCHDOG_CRITICAL_TIME_MICROSECONDS 3000000 /**< Allow 3 seconds maximum inter-message time */ +#define UBX_WATCHDOG_WAIT_TIME_MICROSECONDS 500000 /**< Check for current state every 0.4 seconds */ + +#define APPNAME "gps: ubx" + +//UBX Protocoll definitions (this is the subset of the messages that are parsed) +#define UBX_CLASS_NAV 0x01 +#define UBX_CLASS_RXM 0x02 +#define UBX_CLASS_ACK 0x05 +#define UBX_CLASS_CFG 0x06 +#define UBX_MESSAGE_NAV_POSLLH 0x02 +#define UBX_MESSAGE_NAV_SOL 0x06 +#define UBX_MESSAGE_NAV_TIMEUTC 0x21 +#define UBX_MESSAGE_NAV_DOP 0x04 +#define UBX_MESSAGE_NAV_SVINFO 0x30 +#define UBX_MESSAGE_NAV_VELNED 0x12 +#define UBX_MESSAGE_RXM_SVSI 0x20 +#define UBX_MESSAGE_ACK_ACK 0x01 +#define UBX_MESSAGE_ACK_NAK 0x00 + + +// ************ +/** the structures of the binary packets */ +typedef struct { + uint32_t time_milliseconds; // GPS Millisecond Time of Week + int32_t lon; // Longitude * 1e-7, deg + int32_t lat; // Latitude * 1e-7, deg + int32_t height; // Height above Ellipsoid, mm + int32_t height_msl; // Height above mean sea level, mm + uint32_t hAcc; // Horizontal Accuracy Estimate, mm + uint32_t vAcc; // Vertical Accuracy Estimate, mm + + uint8_t ck_a; + uint8_t ck_b; +} __attribute__((__packed__)) type_gps_bin_nav_posllh_packet; + +typedef type_gps_bin_nav_posllh_packet gps_bin_nav_posllh_packet_t; + +typedef struct { + uint32_t time_milliseconds; // GPS Millisecond Time of Week + int32_t time_nanoseconds; // Fractional Nanoseconds remainder of rounded ms above, range -500000 .. 500000 + int16_t week; // GPS week (GPS time) + uint8_t gpsFix; //GPS Fix: 0 = No fix, 1 = Dead Reckoning only, 2 = 2D fix, 3 = 3d-fix, 4 = GPS + dead reckoning, 5 = time only fix + uint8_t flags; + int32_t ecefX; + int32_t ecefY; + int32_t ecefZ; + uint32_t pAcc; + int32_t ecefVX; + int32_t ecefVY; + int32_t ecefVZ; + uint32_t sAcc; + uint16_t pDOP; + uint8_t reserved1; + uint8_t numSV; + uint32_t reserved2; + + uint8_t ck_a; + uint8_t ck_b; +} __attribute__((__packed__)) type_gps_bin_nav_sol_packet; + +typedef type_gps_bin_nav_sol_packet gps_bin_nav_sol_packet_t; + +typedef struct { + uint32_t time_milliseconds; // GPS Millisecond Time of Week + uint32_t time_accuracy; //Time Accuracy Estimate, ns + int32_t time_nanoseconds; //Nanoseconds of second, range -1e9 .. 1e9 (UTC) + uint16_t year; //Year, range 1999..2099 (UTC) + uint8_t month; //Month, range 1..12 (UTC) + uint8_t day; //Day of Month, range 1..31 (UTC) + uint8_t hour; //Hour of Day, range 0..23 (UTC) + uint8_t min; //Minute of Hour, range 0..59 (UTC) + uint8_t sec; //Seconds of Minute, range 0..59 (UTC) + uint8_t valid_flag; //Validity Flags (see ubx documentation) + + + uint8_t ck_a; + uint8_t ck_b; +} __attribute__((__packed__)) type_gps_bin_nav_timeutc_packet; + +typedef type_gps_bin_nav_timeutc_packet gps_bin_nav_timeutc_packet_t; + +typedef struct { + uint32_t time_milliseconds; // GPS Millisecond Time of Week + uint16_t gDOP; //Geometric DOP (scaling 0.01) + uint16_t pDOP; //Position DOP (scaling 0.01) + uint16_t tDOP; //Time DOP (scaling 0.01) + uint16_t vDOP; //Vertical DOP (scaling 0.01) + uint16_t hDOP; //Horizontal DOP (scaling 0.01) + uint16_t nDOP; //Northing DOP (scaling 0.01) + uint16_t eDOP; //Easting DOP (scaling 0.01) + + + uint8_t ck_a; + uint8_t ck_b; +} __attribute__((__packed__)) type_gps_bin_nav_dop_packet; + +typedef type_gps_bin_nav_dop_packet gps_bin_nav_dop_packet_t; + +typedef struct { + uint32_t time_milliseconds; // GPS Millisecond Time of Week + uint8_t numCh; //Number of channels + uint8_t globalFlags; + uint16_t reserved2; + +} __attribute__((__packed__)) type_gps_bin_nav_svinfo_part1_packet; + +typedef type_gps_bin_nav_svinfo_part1_packet gps_bin_nav_svinfo_part1_packet_t; + +typedef struct { + uint8_t chn; //Channel number, 255 for SVs not assigned to a channel + uint8_t svid; //Satellite ID + uint8_t flags; + uint8_t quality; + uint8_t cno; //Carrier to Noise Ratio (Signal Strength), dbHz + int8_t elev; //Elevation in integer degrees + int16_t azim; //Azimuth in integer degrees + int32_t prRes; //Pseudo range residual in centimetres + +} __attribute__((__packed__)) type_gps_bin_nav_svinfo_part2_packet; + +typedef type_gps_bin_nav_svinfo_part2_packet gps_bin_nav_svinfo_part2_packet_t; + +typedef struct { + uint8_t ck_a; + uint8_t ck_b; + +} __attribute__((__packed__)) type_gps_bin_nav_svinfo_part3_packet; + +typedef type_gps_bin_nav_svinfo_part3_packet gps_bin_nav_svinfo_part3_packet_t; + + +typedef struct { + uint32_t time_milliseconds; // GPS Millisecond Time of Week + int32_t velN; //NED north velocity, cm/s + int32_t velE; //NED east velocity, cm/s + int32_t velD; //NED down velocity, cm/s + uint32_t speed; //Speed (3-D), cm/s + uint32_t gSpeed; //Ground Speed (2-D), cm/s + int32_t heading; //Heading of motion 2-D, deg, scaling: 1e-5 + uint32_t sAcc; //Speed Accuracy Estimate, cm/s + uint32_t cAcc; //Course / Heading Accuracy Estimate, scaling: 1e-5 + + uint8_t ck_a; + uint8_t ck_b; +} __attribute__((__packed__)) type_gps_bin_nav_velned_packet; + +typedef type_gps_bin_nav_velned_packet gps_bin_nav_velned_packet_t; + +typedef struct { + int32_t time_milliseconds; // Measurement integer millisecond GPS time of week + int16_t week; //Measurement GPS week number + uint8_t numVis; //Number of visible satellites + + //... rest of package is not used in this implementation + +} __attribute__((__packed__)) type_gps_bin_rxm_svsi_packet; + +typedef type_gps_bin_rxm_svsi_packet gps_bin_rxm_svsi_packet_t; + +typedef struct { + uint8_t clsID; + uint8_t msgId; + + uint8_t ck_a; + uint8_t ck_b; +} __attribute__((__packed__)) type_gps_bin_ack_ack_packet; + +typedef type_gps_bin_ack_ack_packet gps_bin_ack_ack_packet_t; + +typedef struct { + uint8_t clsID; + uint8_t msgId; + + uint8_t ck_a; + uint8_t ck_b; +} __attribute__((__packed__)) type_gps_bin_ack_nak_packet; + +typedef type_gps_bin_ack_nak_packet gps_bin_ack_nak_packet_t; + + +// END the structures of the binary packets +// ************ + +enum UBX_MESSAGE_CLASSES { + CLASS_UNKNOWN = 0, + NAV = 1, + RXM = 2, + ACK = 3 +}; + +enum UBX_MESSAGE_IDS { + //these numbers do NOT correspond to the message id numbers of the ubx protocol + ID_UNKNOWN = 0, + NAV_POSLLH = 1, + NAV_SOL = 2, + NAV_TIMEUTC = 3, + NAV_DOP = 4, + NAV_SVINFO = 5, + NAV_VELNED = 6, + RXM_SVSI = 7 +}; + +enum UBX_DECODE_STATES { + UBX_DECODE_UNINIT = 0, + UBX_DECODE_GOT_SYNC1 = 1, + UBX_DECODE_GOT_SYNC2 = 2, + UBX_DECODE_GOT_CLASS = 3, + UBX_DECODE_GOT_MESSAGEID = 4, + UBX_DECODE_GOT_LENGTH1 = 5, + UBX_DECODE_GOT_LENGTH2 = 6 +}; + +typedef struct { + union { + uint16_t ck; + struct { + uint8_t ck_a; + uint8_t ck_b; + }; + }; + enum UBX_DECODE_STATES decode_state; + bool print_errors; + int16_t rx_count; + uint16_t payload_size; + + enum UBX_MESSAGE_CLASSES message_class; + enum UBX_MESSAGE_IDS message_id; + uint64_t last_message_timestamps[UBX_NO_OF_MESSAGES]; + +} __attribute__((__packed__)) type_gps_bin_ubx_state; + +typedef type_gps_bin_ubx_state gps_bin_ubx_state_t; + +extern pthread_mutex_t *ubx_mutex; +extern gps_bin_ubx_state_t *ubx_state; + +void ubx_decode_init(void); + +void ubx_checksum(uint8_t b, uint8_t *ck_a, uint8_t *ck_b); + + + +int ubx_parse(uint8_t b, char *gps_rx_buffer); + +int configure_gps_ubx(int fd); + +int read_gps_ubx(int fd, char *gps_rx_buffer, int buffer_size); + +int write_config_message_ubx(uint8_t *message, size_t length, int fd); + +void calculate_ubx_checksum(uint8_t *message, uint8_t length); + +void *ubx_watchdog_loop(void *arg); + +void *ubx_loop(void *arg); + + +#endif /* UBX_H_ */ diff --git a/apps/include/apps.h b/apps/include/apps.h new file mode 100644 index 0000000000..520128203e --- /dev/null +++ b/apps/include/apps.h @@ -0,0 +1,149 @@ +/**************************************************************************** + * apps/include/apps.h + * + * Copyright(C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_INCLUDE_APPS_H +#define __APPS_INCLUDE_APPS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct namedapp_s +{ + const char *name; /* Invocation name and as seen under /sbin/ */ + int priority; /* Use: SCHED_PRIORITY_DEFAULT */ + int stacksize; /* Desired stack size */ + main_t main; /* Entry point: main(int argc, char *argv[]) */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* The "bindir" is file system that supports access to the named applications. + * It is typically mounted under /bin. + */ + +#ifdef CONFIG_APPS_BINDIR +struct mountpt_operations; +extern const struct mountpt_operations binfs_operations; +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: namedapp_isavail + * + * Description: + * Checks for availabiliy of application registerred during compile time. + * + * Input Parameter: + * filename - Name of the linked-in binary to be started. + * + * Returned Value: + * This is an end-user function, so it follows the normal convention: + * Returns index of builtin application. If it is not found then it + * returns -1 (ERROR) and sets errno appropriately. + * + ****************************************************************************/ + +EXTERN int namedapp_isavail(FAR const char *appname); + +/**************************************************************************** + * Name: namedapp_getname + * + * Description: + * Returns pointer to a name of built-in application pointed by the + * index. + * + * Input Parameter: + * index, from 0 and on ... + * + * Returned Value: + * Returns valid pointer pointing to the app name if index is valid. + * Otherwise NULL is returned. + * + ****************************************************************************/ + +EXTERN const char *namedapp_getname(int index); + +/**************************************************************************** + * Name: exec_namedapp + * + * Description: + * Executes builtin named application registered during compile time. + * New application is run in a separate task context (and thread). + * + * Input Parameter: + * filename - Name of the linked-in binary to be started. + * argv - Argument list + * + * Returned Value: + * This is an end-user function, so it follows the normal convention: + * Returns the PID of the exec'ed module. On failure, it.returns + * -1 (ERROR) and sets errno appropriately. + * + ****************************************************************************/ + +EXTERN int exec_namedapp(FAR const char *appname, FAR const char **argv); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __APPS_INCLUDE_APPS_H */ diff --git a/apps/include/ftpc.h b/apps/include/ftpc.h new file mode 100644 index 0000000000..f9a73676aa --- /dev/null +++ b/apps/include/ftpc.h @@ -0,0 +1,225 @@ +/**************************************************************************** + * apps/include/ftpc.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_INCLUDE_FTPC_H +#define __APPS_INCLUDE_FTPC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +#ifndef CONFIG_FTP_DEFTIMEO +# define CONFIG_FTP_DEFTIMEO 30 +#endif + +#ifndef CONFIG_FTP_ANONPWD +# define CONFIG_FTP_ANONPWD "" +#endif + +#ifndef CONFIG_FTP_DEFPORT +# define CONFIG_FTP_DEFPORT 21 +#endif + +#ifndef CONFIG_FTP_MAXREPLY +# define CONFIG_FTP_MAXREPLY 256 +#endif + +#ifndef CONFIG_FTP_TMPDIR +# define CONFIG_FTP_TMPDIR "/tmp" +#endif + +#ifndef CONFIG_FTP_BUFSIZE +# define CONFIG_FTP_BUFSIZE 1024 +#endif + +#ifndef CONFIG_FTP_MAXPATH +# define CONFIG_FTP_MAXPATH 256 +#endif + +#ifndef CONFIG_FTP_SIGNAL +# define CONFIG_FTP_SIGNAL SIGUSR1 +#endif + +/* Interface arguments ******************************************************/ +/* These definitions describe how a put operation should be performed */ + +#define FTPC_PUT_NORMAL 0 /* Just PUT the file on the server */ +#define FTPC_PUT_APPEND 1 /* Append file to an existing file on the server */ +#define FTPC_PUT_UNIQUE 2 /* Create a uniquely named file on the server */ +#define FTPC_PUT_RESUME 3 /* Resume a previously started PUT transfer */ + +/* These definitions describe how a get operation should be performed */ + +#define FTPC_GET_NORMAL 0 /* Just GET the file from the server */ +#define FTPC_GET_APPEND 1 /* Append new file to an existing file */ +#define FTPC_GET_RESUME 3 /* Resume a previously started GET transfer */ + +/* Transfer mode encoding */ + +#define FTPC_XFRMODE_UNKNOWN 0 /* Nothing has been transferred yet */ +#define FTPC_XFRMODE_ASCII 1 /* Last transfer was ASCII mode */ +#define FTPC_XFRMODE_BINARY 2 /* Last transfer was binary mode */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* This "handle" describes the FTP session */ + +typedef FAR void *SESSION; + +/* This structure provides information to connect to a host FTP server. + * + * addr - The IPv4 address of the FTP server (or the proxy) for the FTP + * server. + * port - The port number on the FTP server to connect to (in host byte + * order). This is usually port 21 for FTP. You may set this + * value to zero to let FTPC select the default port number for + * you (it will use CONFIG_FTP_DEFPORT). + */ + +struct ftpc_connect_s +{ + struct in_addr addr; /* Server/proxy IP address */ + uint16_t port; /* Server/proxy port number (usually 21) in network order */ +}; + +/* This structure provides FTP login information */ + +struct ftpc_login_s +{ + FAR const char *uname; /* Login uname */ + FAR const char *pwd; /* Login pwd */ + FAR const char *rdir; /* Initial remote directory */ + bool pasv; /* true: passive connection mode */ +}; + +/* This structure describes one simple directory listing. The directory + * list container as well the individual filename strings are allocated. + * The number of names in tha actual allocated array is variable, given + * by the nnames field. + * + * Since the structure and file names are allocated, they must be freed + * by calling ftpc_dirfree() when they are no longer needed. Allocated + * name strings maby be "stolen" from the array but the pointer int the + * array should be nullified so that the string is not freed by + * ftpc_dirfree(). + */ + +struct ftpc_dirlist_s +{ + unsigned int nnames; /* Number of entries in name[] array */ + FAR char *name[1]; /* Filename with absolute path */ +}; + +#define SIZEOF_FTPC_DIRLIST(n) \ + (sizeof(struct ftpc_dirlist_s) + ((n)-1)*sizeof(FAR char *)) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/* Connection management ****************************************************/ + +EXTERN SESSION ftpc_connect(FAR struct ftpc_connect_s *server); +EXTERN void ftpc_disconnect(SESSION handle); + +/* FTP commands *************************************************************/ + +EXTERN int ftpc_login(SESSION handle, FAR struct ftpc_login_s *login); +EXTERN int ftpc_quit(SESSION handle); + +EXTERN int ftpc_chdir(SESSION handle, FAR const char *path); +EXTERN FAR char *ftpc_rpwd(SESSION handle); +EXTERN int ftpc_cdup(SESSION handle); +EXTERN int ftpc_mkdir(SESSION handle, FAR const char *path); +EXTERN int ftpc_rmdir(SESSION handle, FAR const char *path); + +EXTERN int ftpc_unlink(SESSION handle, FAR const char *path); +EXTERN int ftpc_chmod(SESSION handle, FAR const char *path, FAR const char *mode); +EXTERN int ftpc_rename(SESSION handle, FAR const char *oldname, FAR const char *newname); +EXTERN off_t ftpc_filesize(SESSION handle, FAR const char *path); +EXTERN time_t ftpc_filetime(SESSION handle, FAR const char *filename); + +EXTERN int ftpc_idle(SESSION handle, unsigned int idletime); +EXTERN int ftpc_noop(SESSION handle); +EXTERN int ftpc_help(SESSION handle, FAR const char *arg); + +/* Directory listings *******************************************************/ + +EXTERN FAR struct ftpc_dirlist_s *ftpc_listdir(SESSION handle, + FAR const char *dirpath); +EXTERN void ftpc_dirfree(FAR struct ftpc_dirlist_s *dirlist); + +/* File transfers ***********************************************************/ + +EXTERN int ftpc_getfile(SESSION handle, FAR const char *rname, + FAR const char *lname, uint8_t how, uint8_t xfrmode); +EXTERN int ftp_putfile(SESSION handle, FAR const char *lname, + FAR const char *rname, uint8_t how, uint8_t xfrmode); + +/* FTP response *************************************************************/ + +EXTERN FAR char *ftpc_response(SESSION handle); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __APPS_INCLUDE_FTPC_H */ diff --git a/apps/include/nsh.h b/apps/include/nsh.h new file mode 100644 index 0000000000..4b5a3cd317 --- /dev/null +++ b/apps/include/nsh.h @@ -0,0 +1,121 @@ +/**************************************************************************** + * apps/include/nsh.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_INCLUDE_NSH_H +#define __APPS_INCLUDE_NSH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#if CONFIG_RR_INTERVAL > 0 +# define SCHED_NSH SCHED_RR +#else +# define SCHED_NSH SCHED_FIFO +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_initialize + * + * Description: + * This nterfaces is used to initialize the NuttShell (NSH). + * nsh_initialize() should be called one during application start-up prior + * to executing either nsh_consolemain() or nsh_telnetstart(). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +EXTERN void nsh_initialize(void); + +/**************************************************************************** + * Name: nsh_consolemain + * + * Description: + * This interfaces maybe to called or started with task_start to start a + * single an NSH instance that operates on stdin and stdout (/dev/console). + * This function does not return. + * + * Input Parameters: + * Standard task start-up arguements. These are not used. argc may be + * zero and argv may be NULL. + * + * Returned Values: + * This function does not normally return. exit() is usually called to + * terminate the NSH session. This function will return in the event of + * an error. In that case, a nonzero value is returned (1). + * + ****************************************************************************/ + +EXTERN int nsh_consolemain(int argc, char *argv[]); + +/* nsh_telnetstart() starts a telnet daemon that will allow multiple + * NSH connections via telnet. This function returns immediately after + * the daemon has been started. + */ + +EXTERN int nsh_telnetstart(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __APPS_INCLUDE_NSH_H */ diff --git a/apps/include/readline.h b/apps/include/readline.h new file mode 100644 index 0000000000..6477782108 --- /dev/null +++ b/apps/include/readline.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * apps/include/readline.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_INCLUDE_READLINE_H +#define __APPS_INCLUDE_READLINE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: readline + * + * readline() reads in at most one less than 'buflen' characters from + * 'instream' and stores them into the buffer pointed to by 'buf'. + * Characters are echoed on 'outstream'. Reading stops after an EOF or a + * newline. If a newline is read, it is stored into the buffer. A null + * terminator is stored after the last character in the buffer. + * + * This version of realine assumes that we are reading and writing to + * a VT100 console. This will not work well if 'instream' or 'outstream' + * corresponds to a raw byte steam. + * + * This function is inspired by the GNU readline but is an entirely + * different creature. + * + * Input Parameters: + * buf - The user allocated buffer to be filled. + * buflen - the size of the buffer. + * instream - The stream to read characters from + * outstream - The stream to each characters to. + * + * Returned values: + * On success, the (positive) number of bytes transferred is returned. + * A length of zero would indicated an end of file condition. An failure, + * a negated errno value is returned. + * + **************************************************************************/ + +EXTERN ssize_t readline(FAR char *buf, int buflen, FILE *instream, FILE *outstream); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __APPS_INCLUDE_READLINE_H */ diff --git a/apps/include/tiff.h b/apps/include/tiff.h new file mode 100644 index 0000000000..378af9fe01 --- /dev/null +++ b/apps/include/tiff.h @@ -0,0 +1,465 @@ +/************************************************************************************ + * apps/include/tiff.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Reference: + * "TIFF, Revision 6.0, Final," June 3, 1992, Adobe Developers Association. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __APPS_INCLUDE_TIFF_H +#define __APPS_INCLUDE_TIFF_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include + +/************************************************************************************ + * Pre-Processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ + +/* TIFF File Format Definitions *****************************************************/ +/* Values for the IFD field type */ + +#define IFD_FIELD_BYTE 1 /* 8-bit unsigned integer */ +#define IFD_FIELD_ASCII 2 /* 8-bit byte that contains a 7-bit ASCII code. + * The last byte must be NUL */ +#define IFD_FIELD_SHORT 3 /* 16-bit (2-byte) unsigned integer */ +#define IFD_FIELD_LONG 4 /* 32-bit (4-byte) unsigned integer */ +#define IFD_FIELD_RATIONAL 5 /* Two LONGs: the first represents the + * numerator of a fraction, the second the + * denominator */ +#define IFD_FIELD_SBYTE 6 /* An 8-bit signed (twos-complement) integer */ +#define IFD_FIELD_UNDEFINED 7 /* An 8-bit byte that may contain anything, + * depending on the definition of the field */ +#define IFD_FIELD_SSHORT 8 /* A 16-bit (2-byte) signed (twos-complement) + * integer */ +#define IFD_FIELD_SLONG 9 /* A 32-bit (4-byte) signed (twos-complement) + * integer */ +#define IFD_FIELD_SRATIONAL 10 /* Two SLONG’s: the first represents the + * numerator of a fraction, the second the + * denominator */ +#define IFD_FIELD_FLOAT 11 /* Single precision (4-byte) IEEE format */ +#define IFD_FIELD_DOUBLE 12 /* Double precision (8-byte) IEEE format */ + +/* Values for the IFD tag type */ + +#define IFD_TAG_NEWSUBFILETYPE 254 /* NewSubfileType, LONG */ +# define TAG_NEWSUBFILETYPE_REDUCED (1 << 0) /* Bit 0: Reduced resolution verson of image */ +# define TAG_NEWSUBFILETYPE_SINGLE (1 << 1) /* Bit 1: Single page of a multi-page image */ +# define TAG_NEWSUBFILETYPE_TRANSP (1 << 2) /* Bit 2: Defines a transparency mask for image */ +#define IFD_TAG_SUBFILETYPE 255 /* SubfileType, SHORT */ +# define TAG_SUBFILETYPE_FULL 1 /* Full-resolution image data */ +# define TAG_SUBFILETYPE_REDUCED 2 /* Reduced-resolution image data */ +# define TAG_SUBFILETYPE_SINGLE 3 /* Single page of a multi-page image */ +#define IFD_TAG_IMAGEWIDTH 256 /* ImageLength, SHORT or LONG (Required) */ +#define IFD_TAG_IMAGELENGTH 257 /* ImageWidth, SHORT or LONG (Required) */ +#define IFD_TAG_BITSPERSAMPLE 258 /* BitsPerSample, SHORT (Required + * in greyscale and pallette-color image files) */ +#define IFD_TAG_COMPRESSION 259 /* Compression, SHORT (Required) */ +# define TAG_COMP_NONE 1 /* No compression */ +# define TAG_COMP_CCITT 2 /* CCITT Group 3 1-Dimensional Modified Huffman + * run length encoding */ +# define TAG_COMP_T4 3 /* CCITT T.4 bi-level encoding */ +# define TAG_COMP_T6 4 /* CCITT T.6 bi-level encoding */ +# define TAG_COMP_LZW 5 /* LZW */ +# define TAG_COMP_JPEG 6 /* LZW */ +# define TAG_COMP_PACKBITS 32773 /* PackBits compression */ +#define IFD_TAG_PMI 262 /* PhotometricInterpretation, SHORT (Required) */ +# define TAG_PMI_WHITE 0 /* WhiteIsZero */ +# define TAG_PMI_BLACK 1 /* BlackIsZero */ +# define TAG_PMI_RGB 2 /* RGB */ +# define TAG_PMI_PALETTE 3 /* Palette color */ +# define TAG_PMI_TRANSP 4 /* Transparency mask */ +# define TAG_PMI_CMYK 5 /* CMYK */ +# define TAG_PMI_YCbCr 6 /* YCbCr */ +# define TAG_PMI_CIELAB 8 /* 1976 CIE L*a*b* */ +#define IFD_TAG_THRESHHOLDING 263 /* Threshholding, SHORT */ +# define TAG_THRESHHOLD_NONE 1 /* No dithering or halftoning has been applied */ +# define TAG_THRESHHOLD_ORDERED 2 /* Ordered dither or halftone technique has been applied */ +# define TAG_THRESHHOLD_RANDOM 3 /* Randomized process has been applied */ +#define IFD_TAG_CELLWIDTH 264 /* CellWidth, SHORT */ +#define IFD_TAG_CELLLENGTH 265 /* CellLength, SHORT */ +#define IFD_TAG_FILLORDER 266 /* FillOrder, SHORT */ +# define TAG_FILLORDER_HIGH 1 /* Lower column values are stored in the + * higher-order bits */ +# define TAG_FILLORDER_LOW 2 /* Lower column values are stored in the + * lower-order bits */ +#define IFD_TAG_DOCUMENTNAME 269 /* DocumentName, ASCII */ +#define IFD_TAG_IMAGEDESCRIPTION 270 /* ImageDescription, ASCII */ +#define IFD_TAG_MAKE 271 /* Make, ASCII */ +#define IFD_TAG_MODEL 272 /* Model, ASCII */ +#define IFD_TAG_STRIPOFFSETS 273 /* StripOffsets, SHORT or LONG (Required) */ +#define IFD_TAG_ORIENTATION 274 /* Orientation, SHORT */ +# define TAG_ORIENTATION_TL 1 /* (0,0)=top left */ +# define TAG_ORIENTATION_TR 2 /* (0,0)=top right */ +# define TAG_ORIENTATION_BR 3 /* (0,0)=bottom right */ +# define TAG_ORIENTATION_BL 4 /* (0,0)=bottom left */ +# define TAG_ORIENTATION_LT 5 /* (0,0)=left top */ +# define TAG_ORIENTATION_RT 6 /* (0,0)=right top */ +# define TAG_ORIENTATION_RB 7 /* (0,0)=right bottom */ +# define TAG_ORIENTATION_LB 8 /* (0,0)=left bottom */ +#define IFD_TAG_SAMPLESPERPIXEL 277 /* SamplesPerPixel, SHORT (Required in + * RGB full color files) */ +#define IFD_TAG_ROWSPERSTRIP 278 /* RowsPerStrip, SHORT or LONG (Required) */ +#define IFD_TAG_STRIPCOUNTS 279 /* StripByteCounts, SHORT or LONG (Required) */ +#define IFD_TAG_MINSAMPLEVALUE 280 /* MinSampleValue, SHORT */ +#define IFD_TAG_MAXSAMPLEVALUE 281 /* MaxSampleValue, SHORT */ +#define IFD_TAG_XRESOLUTION 282 /* XResolution, RATIONAL (Required) */ +#define IFD_TAG_YRESOLUTION 283 /* YResolution, RATIONAL (Required) */ +#define IFD_TAG_PLANARCONFIG 284 /* PlanarConfiguration, SHORT */ +# define TAG_PLCONFIG_CHUNKY 1 /* Chunky format */ +# define TAG_PLCONFIG_PLANAR 2 /* Planar format */ +#define IFD_TAG_PAGENAME 285 /* PageName, ASCII */ +#define IFD_TAG_XPOSITION 286 /* XPosition, RATIONAL */ +#define IFD_TAG_YPOSITION 287 /* YPosition, RATIONAL */ +#define IFD_TAG_FREEOFFSETS 288 /* FreeOffsets, LONG */ +#define IFD_TAG_FREEBYTECOUNTS 289 /* FreeByteCounts, LONG */ +#define IFD_TAG_GRAYRESPONSEUNIT 290 /* GrayResponseUnit, SHORT */ +# define TAG_GRAYRESPUNIT_10THS 1 /* Number represents tenths of a unit */ +# define TAG_GRAYRESPUNIT_100THS 2 /* Number represents hundredths of a unit */ +# define TAG_GRAYRESPUNIT_1KTHS 3 /* Number represents thousandths of a unit */ +# define TAG_GRAYRESPUNIT_10KTHS 4 /* Number represents ten-thousandths of a unit */ +# define TAG_GRAYRESPUNIT_100KTHS 5 /* Number represents hundred-thousandths of a unit */ +#define IFD_TAG_GRAYRESPONSECURVE 291 /* GrayResponseCurve, SHORT */ +#define IFD_TAG_T4OPTIONS 292 /* T4Options, LONG */ +# define TAG_T4OPTIONS_2D (1 << 0) /* 2-dimensional coding */ +# define TAG_T4OPTIONS_NONE (1 << 1) /* Uncompressed mode */ +# define TAG_T4OPTIONS_FILL (1 << 2) /* Fill bits have been added */ +#define IFD_TAG_T6OPTIONS 293 /* T6Options, LONG */ +# define TAG_T6OPTIONS_NONE (1 << 1) /* Uncompressed mode allowed */ +#define IFD_TAG_RESUNIT 296 /* ResolutionUnit, SHORT (Required) */ +# define TAG_RESUNIT_NONE 1 /* No absolute unit of measurement */ +# define TAG_RESUNIT_INCH 2 /* Inch (default) */ +# define TAG_RESUNIT_CENTIMETER 3 /* Centimeter */ +#define IFD_TAG_PAGENUMBER 297 /* PageNumber, SHORT */ +#define IFD_TAG_TRANSFERFUNCTION 301 /* TransferFunction, SHORT */ +#define IFD_TAG_SOFTWARE 305 /* Software, ASCII */ +#define IFD_TAG_DATETIME 306 /* DateTime, ASCII */ +#define IFD_TAG_ARTIST 315 /* Artist, ASCII */ +#define IFD_TAG_HOSTCOMPUTER 316 /* HostComputer, ASCII */ +#define IFD_TAG_PREDICTOR 317 /* Predictor SHORT */ +# define TAG_PREDICTOR_NONE 1 /* No prediction scheme used before coding */ +# define TAG_PREDICTOR_HORIZ 2 /* Horizontal differencing */ +#define IFD_TAG_WHITEPOINT 318 /* WhitePoint, RATIONAL */ +#define IFD_TAG_PRIMARYCHROMA 319 /* PrimaryChromaticities, RATIONAL */ +#define IFD_TAG_COLORMAP 320 /* ColorMap, SHORT (Required in palette + * color image files) */ +#define IFD_TAG_HALFTONEHINTS 321 /* HalftoneHints, SHORT */ +#define IFD_TAG_TILEWIDTH 322 /* TileWidth, SHORT or LONG */ +#define IFD_TAG_TILELENGTH 323 /* TileLength, SHORT or LONG */ +#define IFD_TAG_TILEOFFSETS 324 /* TileOffsets, LONG */ +#define IFD_TAG_TILEBYTECOUNTS 325 /* TileByteCounts, SHORT or LONG */ +#define IFD_TAG_INKSET 332 /* InkSet, SHORT */ +# define TAG_INKSET_CMYK 1 /* CMYK */ +# define TAG_INKSET_OTHER 2 /* Not CMYK */ +#define IFD_TAG_INKNAMES 333 /* InkNames, ASCII */ +#define IFD_TAG_NUMBEROFINKS 334 /* NumberOfInks, SHORT */ +#define IFD_TAG_DOTRANGE 336 /* DotRange, BYTE or SHORT */ +#define IFD_TAG_TARGETPRINTER 337 /* TargetPrinter, ASCII */ +#define IFD_TAG_EXTRASAMPLES 338 /* ExtraSamples, SHORT */ +# define TAG_EXTSAMP_UNSPEC 0 /* Unspecified */ +# define TAG_EXTSAMP_ASSOCALPHA 1 /* Associated alpha data */ +# define TAG_EXTSAMP_UNASSALPHA 2 /* Unassociated alpha data */ +#define IFD_TAG_SAMPLEFORMAT 339 /* SampleFormat, SHORT */ +# define TAG_SAMPLEFMT_UNSIGED 1 /* Unsigned integer data */ +# define TAG_SAMPLEFMT_SIGNED 2 /* Two’s complement signed integer data */ +# define TAG_SAMPLEFMT_FLOAT 3 /* IEEE floating point data */ +# define TAG_SAMPLEFMT_UNDEFINED 4 /* Undefined data format */ +#define IFD_TAG_SMINSAMPLEVALUE 340 /* SMinSampleValue, type matches sample data */ +#define IFD_TAG_SMAXSAMPLEVALUE 341 /* SMaxSampleValue, type matches sample data */ +#define IFD_TAG_TRANSFERRANGE 342 /* TransferRange, SHORT */ +#define IFD_TAG_JPEGPROC 512 /* JPEGProc, SHORT */ +#define IFD_TAG_JPEGFMT 513 /* JPEGInterchangeFormat, LONG */ +#define IFD_TAG_JPEGLENGTH 514 /* JPEGInterchangeFormatLength, LONG */ +#define IFD_TAG_JPEGRESTART 515 /* JPEGRestartInterval, SHORT */ +#define IFD_TAG_JPEGLLPREDICTORS 517 /* JPEGLosslessPredictors, SHORT */ +#define IFD_TAG_JPEGPOINTXFORMS 518 /* JPEGPointTransforms, SHORT */ +#define IFD_TAG_JPEGQTABLES 519 /* JPEGQTables, LONG */ +#define IFD_TAG_JPEGDCTABLES 520 /* JPEGDCTables, LONG */ +#define IFD_TAG_JPEGACTABLES 521 /* JPEGACTables, LONG */ +#define IFD_TAG_YCbCrCOEFFS 529 /* YCbCrCoefficients, RATIONAL */ +#define IFD_TAG_YCbCrSUBSAMPLING 530 /* YCbCrSubSampling, SHORT */ +#define IFD_TAG_YCbCrPOSITIONING 531 /* YCbCrPositioning, SHORT */ +#define IFD_TAG_REFERENCEBW 532 /* ReferenceBlackWhite, RATIONAL */ +#define IFD_TAG_COPYRIGHT 33432 /* Copyright, ASCII */ + +/************************************************************************************ + * Public Types + ************************************************************************************/ +/* TIFF File Format Structure *******************************************************/ +/* "A TIFF file begins with an 8-byte image file header that points to an + * image file directory (IFD). An image file directory contains information + * about the image, as well as pointers to the actual image data." + */ + +struct tiff_header_s +{ + uint8_t order[2]; /* 0-1: Byte order: "II"=little endian, "MM"=big endian */ + uint8_t magic[2]; /* 2-3: 42 in appropriate byte order */ + uint8_t offset[4]; /* 4-7: Offset to the first IFD */ +}; +#define SIZEOF_TIFF_HEADER 8 + +/* "An Image File Directory (IFD) consists of a 2-byte count of the number + * of directory entries (i.e., the number of fields), followed by a sequence + * of 12-byte field entries, followed by a 4-byte offset of the next IFD (or + * 0 if none). + * + * Each 12-byte IFD entry has the following format: + */ + +struct tiff_ifdentry_s +{ + uint8_t tag[2]; /* 0-1: The Tag that identifies the field */ + uint8_t type[2]; /* 2-3 The field Type */ + uint8_t count[4]; /* 4-7: The number of values of the indicated type */ + uint8_t offset[4]; /* 8-11: The Value Offset (or the value itself) */ +}; +#define SIZEOF_IFD_ENTRY 12 + +/************************************************************************************/ +/* Structures needed to interface with the TIFF file creation library )and also + * structures used only internally by the TIFF file creation library). + */ + +/* This structure describes on strip in tmpfile2 */ + +struct tiff_strip_s +{ + uint32_t offset; /* Offset to the strip data in tmpfile1 */ + uint32_t count; /* Count of pixels in the strip */ +}; + +/* This structure is used only internally by the TIFF file creation library to + * manage file offsets. + */ + +struct tiff_filefmt_s +{ + uint16_t nifdentries; /* Number of IFD entries */ + uint16_t soifdoffset; /* Offset to StripOffset IFD entry */ + uint16_t sbcifdoffset; /* Offset to StripByteCount IFD entry */ + uint16_t valoffset; /* Offset to first values */ + uint16_t xresoffset; /* Offset to XResolution values */ + uint16_t yresoffset; /* Offset to yResolution values */ + uint16_t swoffset; /* Offset to Software string */ + uint16_t dateoffset; /* Offset to DateTime string */ + uint16_t sbcoffset; /* Offset to StripByteCount values */ +}; + +/* These type is used to hold information about the TIFF file under + * construction + */ + +struct tiff_info_s +{ + /* The first fields are used to pass information to the TIFF file creation + * logic via tiff_initialize(). + * + * Filenames. Three file names are required. (1) path to the final + * output file and (2) two paths to temporary files. One temporary file + * (tmpfile1) will be used to hold the strip image data and the other + * (tmpfile2) will be used to hold strip offset and count information. + * + * colorfmt - Specifies the form of the color data that will be provided + * in the strip data. These are the FB_FMT_* definitions + * provided in include/nuttx/fb.h. Only the following values + * are supported: + * + * FB_FMT_Y1 BPP=1, monochrome, 0=black + * FB_FMT_Y4 BPP=4, 4-bit greyscale, 0=black + * FB_FMT_Y8 BPP=8, 8-bit greyscale, 0=black + * FB_FMT_RGB16_565 BPP=16 R=6, G=6, B=5 + * FB_FMT_RGB24 BPP=24 R=8, G=8, B=8 + * + * rps - TIFF RowsPerStrip + * imgwidth - TIFF ImageWidth, Number of columns in the image + * imgheight - TIFF ImageLength, Number of rows in the image + */ + + FAR const char *outfile; /* Full path to the final output file name */ + FAR const char *tmpfile1; /* Full path to first temporary file */ + FAR const char *tmpfile2; /* Full path to second temporary file */ + + uint8_t colorfmt; /* See FB_FMT_* definitions in include/nuttx/fb.h */ + nxgl_coord_t rps; /* TIFF RowsPerStrip */ + nxgl_coord_t imgwidth; /* TIFF ImageWidth, Number of columns in the image */ + nxgl_coord_t imgheight; /* TIFF ImageLength, Number of rows in the image */ + + /* The caller must provide an I/O buffer as well. This I/O buffer will + * used for color conversions and as the intermediate buffer for copying + * files. The larger the buffer, the better the performance. + */ + + FAR uint8_t *iobuffer; /* IO buffer allocated by the caller */ + unsigned int iosize; /* The size of the I/O buffer in bytes */ + + /* The second set of fields are used only internally by the TIFF file + * creation logic. These fields must be set to zero initially by the + * caller of tiff_initialize(). User logic should not depend upon any + * definitions in the following -- they are subject to change without + * notice. They are only exposed here so that the caller can allocate + * memory for their storage. + */ + + uint8_t imgflags; /* Bit-encoded image flags */ + nxgl_coord_t nstrips; /* Number of strips in tmpfile3 */ + size_t pps; /* Pixels per strip */ + size_t bps; /* Bytes per strip */ + int outfd; /* outfile file descriptor */ + int tmp1fd; /* tmpfile1 file descriptor */ + int tmp2fd; /* tmpfile2 file descriptor */ + off_t outsize; /* Current size of outfile */ + off_t tmp1size; /* Current size of tmpfile1 */ + off_t tmp2size; /* Current size of tmpfile2 */ + + /* Points to an internal constant structure of file offsets */ + + FAR const struct tiff_filefmt_s *filefmt; +}; + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Name: tiff_initialize + * + * Description: + * Setup to create a new TIFF file. The overall steps to creating a TIFF file are + * as follows: + * + * 1) Create an initialize a struct tiff_info_s instance + * 2) Call tiff_initialize() to setup the file creation + * 3) Call tiff_addstrip() repeatedly to add strips to the graphic image + * 4) Call tiff_finalize() to complete the file creation. + * + * Input Parameters: + * info - A pointer to the caller allocated parameter passing/TIFF state instance. + * + * Returned Value: + * Zero (OK) on success. A negated errno value on failure. + * + ************************************************************************************/ + +EXTERN int tiff_initialize(FAR struct tiff_info_s *info); + +/************************************************************************************ + * Name: tiff_addstrip + * + * Description: + * Add an image data strip. The size of the strip in pixels must be equal to + * the RowsPerStrip x ImageWidth values that were provided to tiff_initialize(). + * + * Input Parameters: + * info - A pointer to the caller allocated parameter passing/TIFF state instance. + * buffer - A buffer containing a single row of data. + * + * Returned Value: + * Zero (OK) on success. A negated errno value on failure. + * + ************************************************************************************/ + +EXTERN int tiff_addstrip(FAR struct tiff_info_s *info, FAR const uint8_t *strip); + +/************************************************************************************ + * Name: tiff_finalize + * + * Description: + * Finalize the TIFF output file, completing the TIFF file creation steps. + * + * Input Parameters: + * info - A pointer to the caller allocated parameter passing/TIFF state instance. + * + * Returned Value: + * Zero (OK) on success. A negated errno value on failure. + * + ************************************************************************************/ + +EXTERN int tiff_finalize(FAR struct tiff_info_s *info); + +/************************************************************************************ + * Name: tiff_abort + * + * Description: + * Abort the TIFF file creation and create-up resources. + * + * Input Parameters: + * info - A pointer to the caller allocated parameter passing/TIFF state instance. + * + * Returned Value: + * None + * + ************************************************************************************/ + +EXTERN void tiff_abort(FAR struct tiff_info_s *info); + +/************************************************************************************ + * Name: tiff_put/get16/32 + * + * Description: + * Put and get 16 and 32 values in the correct byte order at the specified position. + * + * Input Parameters: + * dest - The location to store the multi-byte data (put only) + * src - The location to get the multi-byte data (get only) + * + * Returned Value: + * None (put) + * The extracted value (get) + * + ************************************************************************************/ + +EXTERN void tiff_put16(FAR uint8_t *dest, uint16_t value); +EXTERN void tiff_put32(FAR uint8_t *dest, uint32_t value); +EXTERN uint16_t tiff_get16(FAR uint8_t *dest); +EXTERN uint32_t tiff_get32(FAR uint8_t *dest); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __APPS_INCLUDE_TIFF_H */ diff --git a/apps/interpreters/Kconfig b/apps/interpreters/Kconfig new file mode 100644 index 0000000000..34cbf2eeee --- /dev/null +++ b/apps/interpreters/Kconfig @@ -0,0 +1,21 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +comment "Interpreters" + +source "$APPSDIR/interpreters/ficl/Kconfig" + +config PCODE + bool "Pascal p-code interpreter" + default n + ---help--- + Enable support for the Pascal p-code interpreter. See README file at misc/pascal + and also the README.txt file in the apps/interpreter directory. Use of this + configuration implies that you have performed the required installation of the + Pascal run-time code. + +if PCODE +endif + diff --git a/apps/interpreters/Make.defs b/apps/interpreters/Make.defs new file mode 100644 index 0000000000..36ee7004da --- /dev/null +++ b/apps/interpreters/Make.defs @@ -0,0 +1,43 @@ +############################################################################ +# apps/interpreters/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +if ($(CONFIG_PCODE),y) +CONFIGURED_APPS += interpreters/pcode +endif + +if ($(CONFIG_FICL),y) +CONFIGURED_APPS += interpreters/ficl +endif diff --git a/apps/interpreters/Makefile b/apps/interpreters/Makefile new file mode 100644 index 0000000000..1ef9c7439c --- /dev/null +++ b/apps/interpreters/Makefile @@ -0,0 +1,70 @@ +############################################################################ +# apps/interpreters/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config # Current configuration + +# Sub-directories containing interpreter runtime + +SUBDIRS = pcode ficl + +# Create the list of installed runtime modules (INSTALLED_DIRS) + +define ADD_DIRECTORY +INSTALLED_DIRS += ${shell if [ -r $1/Makefile ]; then echo "$1"; fi} +endef + +$(foreach DIR, $(SUBDIRS), $(eval $(call ADD_DIRECTORY,$(DIR)))) + +all: nothing +.PHONY: nothing context depend clean distclean + +nothing: + +context: + +depend: + @for dir in $(INSTALLED_DIRS) ; do \ + $(MAKE) -C $$dir depend TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + +clean: + @for dir in $(INSTALLED_DIRS) ; do \ + $(MAKE) -C $$dir clean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + +distclean: clean + @for dir in $(INSTALLED_DIRS) ; do \ + $(MAKE) -C $$dir distclean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done diff --git a/apps/interpreters/README.txt b/apps/interpreters/README.txt new file mode 100644 index 0000000000..8cf7ce321b --- /dev/null +++ b/apps/interpreters/README.txt @@ -0,0 +1,67 @@ +apps/interpreters README file +============================= + +This apps/ directory is set aside to hold interpreters that may be +incorporated into NuttX. + +ficl +---- + + This is DIY port of Ficl (the "Forth Inspired Command Language"). See + http://ficl.sourceforge.net/. It is a "DIY" port because the Ficl source + is not in that directory, only an environment and instructions that will + let you build Ficl under NuttX. The rest is up to you. + +pcode +----- + + At present, only the NuttX Pascal add-on is supported. This NuttX add-on + must be downloaded separately (or is available in an SVN snapshot in the + misc/pascal directory). + + This Pascal add-on must be installed into the NuttX apps/ directory. After + unpacking the Pascal add-on package, an installation script and README.txt + instructions can be found at pascal/nuttx. + + INSTALL.sh -- The script that performs the operation. Usage: + + ./INSTALL.sh [-16|-32] + + If you are using this standard NuttX apps/ package, the correct + location for the is apps/interpreters. That is + where the examples and build logic will expect to find the pcode + sub-directory. + + Example: + + ./INSTALL.sh -16 $PWD/../../../apps/interpreters + + After installation, the NuttX apps/interpresters directory will contain + the following files + + pcode + |-- Makefile + |-- include + | `-- Common header files + |-- libboff + | `-- Pascal object format (POFF) library + `--insn + |-- include + | `-- model-specific header files + `-- prun + `-- model-specific source files + + pashello + + There is a simple Pascal example at apps/examples/pashello. This is the + standard "Hello, World!" example written in Pascal and interpreted from + Pascal P-Code at runtime. To use this example, place the following in + your appconfig file" + + # Path to example in apps/examples containing the user_start entry point + + CONFIGURED_APPS += examples/pashello + + # Path to the Pascal p-code runtime interpreter module + + CONFIGURED_APPS += interpreters/pcode diff --git a/apps/interpreters/ficl/Kconfig b/apps/interpreters/ficl/Kconfig new file mode 100644 index 0000000000..1860a15918 --- /dev/null +++ b/apps/interpreters/ficl/Kconfig @@ -0,0 +1,16 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config FICL + bool "Ficl Forth interpreter" + default n + ---help--- + Enable support for the Ficl interpreter interpreter. See README.txt file in the + apps/interpreters/ficl directory. Use of this configuration assumes + that you have performed the required installation of the Ficl run-time code. + +if FICL +endif + diff --git a/apps/interpreters/ficl/Makefile b/apps/interpreters/ficl/Makefile new file mode 100644 index 0000000000..183246b67a --- /dev/null +++ b/apps/interpreters/ficl/Makefile @@ -0,0 +1,118 @@ +############################################################################ +# apps/interpreters/ficl/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +BUILDDIR := ${shell pwd | sed -e 's/ /\\ /g'} + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# Tools + +INCDIR = $(TOPDIR)/tools/incdir.sh + +ifeq ($(WINTOOL),y) +INCDIROPT = -w +endif + +# Include paths + +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(BUILDDIR)/$(FICL_SUBDIR) $(BUILDDIR)/src} + +# Source Files + +ASRCS = +CXXSRCS = +CSRCS = nuttx.c + +-include Make.srcs + +ASRCS += $(FICL_ASRCS) +CXXSRCS += $(FICL_CXXSRCS) +CSRCS += $(FICL_CSRCS) + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOT_DEPPATH = --dep-path . +SRC_DEPPATH = --dep-path src + +VPATH = src:$(FICL_SUBDIR) + +all: .built +.PHONY: debug context depend clean distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +debug: + @#echo "FICL: $(FICL_SUBDIR)" + @#echo "VPATH: $(VPATH)" + @#echo "CFLAGS: $(CFLAGS)" + +.built: debug $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +context: + +.depend: debug Makefile $(SRCS) + @$(MKDEP) $(ROOT_DEPPATH) $(SRC_DEPPATH) $(FICL_DEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/interpreters/ficl/README.txt b/apps/interpreters/ficl/README.txt new file mode 100755 index 0000000000..bac9f31482 --- /dev/null +++ b/apps/interpreters/ficl/README.txt @@ -0,0 +1,42 @@ +apps/interpreter/README.txt +=========================== + +Ficl is a programming language interpreter designed to be embedded into +other systems as a command, macro, and development prototyping language. +Ficl is an acronym for "Forth Inspired Command Language". See +http://ficl.sourceforge.net/ + +Build Instructions +------------------ + +Disclaimer: This installation steps have only been exercised using Ficl +4.1.0. With new versions you will likely have to make some adjustments +to this instructtions or to the files within this directory. Think of this +information as "recommendations" -- not necessarily proven instructions. + +1. CD to apps/interpreters/ficl + +2. Download Ficl: http://sourceforge.net/projects/ficl/files/ + +3. Uznip the Ficl compressed file. + + For example, 'unzip ficl-4.1.0.zip' will leave the file + apps/interpreters/ficl/ficl-4.1.0 + +4. Configure to build Ficl in the apps/interpreters/ficl directory using + the configure.sh script. + + For example, './configure.sh ficl-4.1.0' will leave the Makefile + fragment 'Make.srcs' in the ficl build directory. + +5. Create your NuttX configuration. The appconfig file should include + (1) the path to your application code, and (2) the path to the Ficl + build directory. That latter would appear as the following line in + your appconfig file: + + CONFIGURED_APPS += interpreters/ficl + + 6. Configure and build NuttX. On successful completion, the Ficl objects + will be available in apps/libapps.a and that NuttX binary will be + linked against that file. Of course, Ficl will do nothing unless + you have written some application code that uses it! diff --git a/apps/interpreters/ficl/configure.sh b/apps/interpreters/ficl/configure.sh new file mode 100755 index 0000000000..cadc1d48a1 --- /dev/null +++ b/apps/interpreters/ficl/configure.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +USAGE="$0 " + +FICLDIR=$1 +if [ -z "${FICLDIR}" ]; then + echo "Missing command line argument" + echo $USAGE + exit 1 +fi + +if [ ! -d "${FICLDIR}" ]; then + echo "Sub-directory ${FICLDIR} does not exist" + echo $USAGE + exit 1 +fi + +if [ ! -r "${FICLDIR}/Makefile" ]; then + echo "Readable ${FICLDIR}/Makefile does not exist" + echo $USAGE + exit 1 +fi + +OBJECTS=`grep "^OBJECTS" ${FICLDIR}/Makefile` +if [ -z "${OBJECTS}" ]; then + echo "No OBJECTS found in ${FICLDIR}/Makefile" + echo $USAGE + exit 1 +fi + +OBJLIST=`echo ${OBJECTS} | cut -d'=' -f2 | sed -e "s/unix\.o//g"` + +rm -f Make.srcs +echo "# apps/interpreters/ficl/Make.obs" >> Make.srcs +echo "# Auto-generated file.. Do not edit" >> Make.srcs +echo "" >> Make.srcs +echo "FICL_SUBDIR = ${1}" >> Make.srcs +echo "FICL_DEPPATH = --dep-path ${1}" >> Make.srcs + +unset CSRCS +for OBJ in ${OBJLIST}; do + SRC=`echo ${OBJ} | sed -e "s/\.o/\.c/g"` + CSRCS=${CSRCS}" ${SRC}" +done +echo "FICL_ASRCS = " >> Make.srcs +echo "FICL_CXXSRCS = " >> Make.srcs +echo "FICL_CSRCS = ${CSRCS}" >> Make.srcs diff --git a/apps/interpreters/ficl/src/nuttx.c b/apps/interpreters/ficl/src/nuttx.c new file mode 100644 index 0000000000..16b3fa1dbc --- /dev/null +++ b/apps/interpreters/ficl/src/nuttx.c @@ -0,0 +1,65 @@ +#include +#include + +#include +#include +#include + +#include "ficl.h" + +void *ficlMalloc(size_t size) +{ + return malloc(size); +} + +void *ficlRealloc(void *p, size_t size) +{ + return realloc(p, size); +} + +void ficlFree(void *p) +{ + free(p); +} + +void ficlCallbackDefaultTextOut(ficlCallback *callback, char *message) +{ + FICL_IGNORE(callback); + if (message != NULL) + fputs(message, stdout); + else + fflush(stdout); + return; +} + +int ficlFileStatus(char *filename, int *status) +{ + struct stat statbuf; + if (stat(filename, &statbuf) == 0) + { + *status = statbuf.st_mode; + return 0; + } + *status = ENOENT; + return -1; +} + +long ficlFileSize(ficlFile *ff) +{ + struct stat statbuf; + if (ff == NULL) + return -1; + + statbuf.st_size = -1; + if (fstat(fileno(ff->f), &statbuf) != 0) + return -1; + + return statbuf.st_size; +} + +void ficlSystemCompilePlatform(ficlSystem *system) +{ + return; +} + + diff --git a/apps/interpreters/ficl/src/nuttx.h b/apps/interpreters/ficl/src/nuttx.h new file mode 100644 index 0000000000..e44031066b --- /dev/null +++ b/apps/interpreters/ficl/src/nuttx.h @@ -0,0 +1,19 @@ +#include + +typedef int8_t ficlInteger8; +typedef uint8_t ficlUnsigned8; +typedef int16_t ficlInteger16; +typedef uint16_t ficlUnsigned16; +typedef int32_t ficlInteger32; +typedef uint32_t ficlUnsigned32; + +typedef intptr_t ficlInteger; +typedef uintptr_t ficlUnsigned; +typedef float ficlFloat; + +#define FICL_PLATFORM_BASIC_TYPES (1) +#define FICL_PLATFORM_HAS_2INTEGER (0) +#define FICL_PLATFORM_HAS_FTRUNCATE (0) + +#define FICL_PLATFORM_OS "ansi" +#define FICL_PLATFORM_ARCHITECTURE "unknown" diff --git a/apps/mavlink/.context b/apps/mavlink/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/mavlink/.gitignore b/apps/mavlink/.gitignore new file mode 100644 index 0000000000..a028271951 --- /dev/null +++ b/apps/mavlink/.gitignore @@ -0,0 +1,3 @@ +include +mavlink-* +pymavlink-* diff --git a/apps/mavlink/Makefile b/apps/mavlink/Makefile new file mode 100644 index 0000000000..d4e9a5762a --- /dev/null +++ b/apps/mavlink/Makefile @@ -0,0 +1,44 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Mavlink Application +# + +APPNAME = mavlink +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 4096 + +INCLUDES = $(TOPDIR)/../mavlink/include/mavlink + +include $(APPDIR)/mk/app.mk diff --git a/apps/mavlink/mavlink.c b/apps/mavlink/mavlink.c new file mode 100644 index 0000000000..466ea75651 --- /dev/null +++ b/apps/mavlink/mavlink.c @@ -0,0 +1,1193 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file mavlink.c + * MAVLink 1.0 protocol implementation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mavlink_bridge_header.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "waypoints.h" +#include "mavlink_log.h" + + +__EXPORT int mavlink_main(int argc, char *argv[]); + +/* terminate MAVLink on user request - disabled by default */ +static bool mavlink_link_termination_allowed = false; +static bool mavlink_exit_requested = false; + +static int system_type = MAV_TYPE_FIXED_WING; +mavlink_system_t mavlink_system = {100, 50}; // System ID, 1-255, Component/Subsystem ID, 1-255 +static uint8_t chan = MAVLINK_COMM_0; +static mavlink_status_t status; + +/* pthreads */ +static pthread_t receive_thread; +static pthread_t uorb_receive_thread; + +static uint16_t mavlink_message_intervals[256]; /**< intervals at which to send MAVLink packets */ +/* Allocate storage space for waypoints */ +mavlink_wpm_storage wpm_s; +/* Global position */ +static struct vehicle_global_position_s global_pos = {0}; +/* Local position */ +static struct vehicle_local_position_s local_pos = {0}; +/* Vehicle status */ +static struct vehicle_status_s v_status = {0}; +/* RC channels */ +static struct rc_channels_s rc = {0}; + +/* HIL publishers */ +static int pub_hil_attitude = -1; +static struct vehicle_attitude_s hil_attitude = {0}; +static struct vehicle_global_position_s hil_global_pos = {0}; +static struct fixedwing_control_s fw_control = {0}; +static struct ardrone_motors_setpoint_s ardrone_motors = {0}; +static struct vehicle_command_s vcmd = {0}; +static int pub_hil_global_pos = -1; +static int ardrone_motors_pub = -1; +static int cmd_pub = -1; +static int global_pos_sub = -1; +static int local_pos_sub = -1; +static int global_position_setpoint_pub = -1; +static int local_position_setpoint_pub = -1; +static bool mavlink_hil_enabled = false; + +static char mavlink_message_string[51] = {0}; + + +/* 3: Define waypoint helper functions */ +void mavlink_wpm_send_message(mavlink_message_t *msg); +void mavlink_wpm_send_gcs_string(const char *string); +uint64_t mavlink_wpm_get_system_timestamp(void); +void mavlink_missionlib_send_message(mavlink_message_t *msg); +void mavlink_missionlib_send_gcs_string(const char *string); +uint64_t mavlink_missionlib_get_system_timestamp(void); + +/* 4: Include waypoint protocol */ +#include "waypoints.h" +mavlink_wpm_storage *wpm; + + +#include "mavlink_parameters.h" + +static uint8_t missionlib_msg_buf[MAVLINK_MAX_PACKET_LEN]; + +void mavlink_missionlib_send_message(mavlink_message_t *msg) +{ + uint16_t len = mavlink_msg_to_send_buffer(missionlib_msg_buf, msg); + write(uart, missionlib_msg_buf, len); +} + +void mavlink_missionlib_send_gcs_string(const char *string) +{ + const int len = MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN; + mavlink_statustext_t statustext; + int i = 0; + + while (i < len - 1) { + statustext.text[i] = string[i]; + + if (string[i] == '\0') + break; + + i++; + } + + if (i > 1) { + /* Enforce null termination */ + statustext.text[i] = '\0'; + mavlink_message_t msg; + + mavlink_msg_statustext_encode(mavlink_system.sysid, mavlink_system.compid, &msg, &statustext); + mavlink_missionlib_send_message(&msg); + } +} + +/* + * Get system time since boot in microseconds + * + * @return the system time since boot in microseconds + */ +uint64_t mavlink_missionlib_get_system_timestamp() +{ + return hrt_absolute_time(); +} + +extern void mavlink_missionlib_current_waypoint_changed(uint16_t index, float param1, + float param2, float param3, float param4, float param5_lat_x, + float param6_lon_y, float param7_alt_z, uint8_t frame, uint16_t command) +{ + /* Update controller setpoints */ + if (frame == (int)MAV_FRAME_GLOBAL) { + /* global, absolute waypoint */ + struct vehicle_global_position_setpoint_s sp; + sp.lat = param5_lat_x * 1e7; + sp.lon = param6_lon_y * 1e7; + sp.altitude = param7_alt_z; + sp.altitude_is_relative = false; + sp.yaw = (param4 / 180.0f) * ((float)M_PI) - ((float)M_PI); + orb_publish(ORB_ID(vehicle_global_position_setpoint), global_position_setpoint_pub, &sp); + + } else if (frame == (int)MAV_FRAME_GLOBAL_RELATIVE_ALT) { + /* global, relative alt (in relation to HOME) waypoint */ + struct vehicle_global_position_setpoint_s sp; + sp.lat = param5_lat_x * 1e7; + sp.lon = param6_lon_y * 1e7; + sp.altitude = param7_alt_z; + sp.altitude_is_relative = true; + sp.yaw = (param4 / 180.0f) * ((float)M_PI) - ((float)M_PI); + orb_publish(ORB_ID(vehicle_global_position_setpoint), global_position_setpoint_pub, &sp); + + } else if (frame == (int)MAV_FRAME_LOCAL_ENU || frame == (int)MAV_FRAME_LOCAL_NED) { + /* local, absolute waypoint */ + struct vehicle_local_position_setpoint_s sp; + sp.x = param5_lat_x; + sp.y = param6_lon_y; + sp.z = param7_alt_z; + sp.yaw = (param4 / 180.0f) * ((float)M_PI) - ((float)M_PI); + orb_publish(ORB_ID(vehicle_local_position_setpoint), local_position_setpoint_pub, &sp); + } + + printf("[mavlink mp] new setpoint: frame: %d, lat: %d, lon: %d, alt: %d, yaw: %d\n", frame, param5_lat_x, param6_lon_y, param7_alt_z, param4); +} + + +void handleMessage(mavlink_message_t *msg); + +/** + * Enable / disable Hardware in the Loop simulation mode. + */ +int set_hil_on_off(uint8_t vehicle_mode) +{ + int ret = OK; + + /* Enable HIL */ + if ((vehicle_mode & MAV_MODE_FLAG_HIL_ENABLED) && !mavlink_hil_enabled) { + + //printf("\n HIL ON \n"); + + (void)close(pub_hil_attitude); + (void)close(pub_hil_global_pos); + + /* Advertise topics */ + pub_hil_attitude = orb_advertise(ORB_ID(vehicle_attitude), &hil_attitude); + pub_hil_global_pos = orb_advertise(ORB_ID(vehicle_global_position), &hil_global_pos); + + printf("\n pub_hil_attitude :%i\n", pub_hil_attitude); + printf("\n pub_hil_global_pos :%i\n", pub_hil_global_pos); + + if (pub_hil_attitude > 0 && pub_hil_global_pos > 0) { + mavlink_hil_enabled = true; + + } else { + ret = ERROR; + } + } + + if (!(vehicle_mode & MAV_MODE_FLAG_HIL_ENABLED) && mavlink_hil_enabled) { + mavlink_hil_enabled = false; + (void)close(pub_hil_attitude); + (void)close(pub_hil_global_pos); + + } else { + ret = ERROR; + } + + return ret; +} + +/** + * Translate the custom state into standard mavlink modes and state. + */ +void get_mavlink_mode_and_state(const struct vehicle_status_s *c_status, uint8_t *mavlink_state, uint8_t *mavlink_mode) +{ + //TODO: Make this correct + switch (c_status->state_machine) { + case SYSTEM_STATE_PREFLIGHT: + *mavlink_state = MAV_STATE_UNINIT; + *mavlink_mode &= ~MAV_MODE_FLAG_SAFETY_ARMED; + break; + + case SYSTEM_STATE_STANDBY: + *mavlink_state = MAV_STATE_STANDBY; + *mavlink_mode &= ~MAV_MODE_FLAG_SAFETY_ARMED; + break; + + case SYSTEM_STATE_GROUND_READY: + *mavlink_state = MAV_STATE_ACTIVE; + *mavlink_mode |= MAV_MODE_FLAG_SAFETY_ARMED; + break; + + case SYSTEM_STATE_MANUAL: + *mavlink_state = MAV_STATE_ACTIVE; + *mavlink_mode |= MAV_MODE_FLAG_SAFETY_ARMED; + *mavlink_mode |= MAV_MODE_FLAG_MANUAL_INPUT_ENABLED; + break; + + case SYSTEM_STATE_STABILIZED: + *mavlink_state = MAV_STATE_ACTIVE; + *mavlink_mode |= MAV_MODE_FLAG_SAFETY_ARMED; + *mavlink_mode |= MAV_MODE_FLAG_STABILIZE_ENABLED; + break; + + case SYSTEM_STATE_AUTO: + *mavlink_state = MAV_STATE_ACTIVE; + *mavlink_mode |= MAV_MODE_FLAG_SAFETY_ARMED; + *mavlink_mode |= MAV_MODE_FLAG_GUIDED_ENABLED; + break; + + case SYSTEM_STATE_MISSION_ABORT: + *mavlink_state = MAV_STATE_EMERGENCY; + *mavlink_mode |= MAV_MODE_FLAG_SAFETY_ARMED; + break; + + case SYSTEM_STATE_EMCY_LANDING: + *mavlink_state = MAV_STATE_EMERGENCY; + *mavlink_mode |= MAV_MODE_FLAG_SAFETY_ARMED; + break; + + case SYSTEM_STATE_EMCY_CUTOFF: + *mavlink_state = MAV_STATE_EMERGENCY; + *mavlink_mode |= MAV_MODE_FLAG_SAFETY_ARMED; + break; + + case SYSTEM_STATE_GROUND_ERROR: + *mavlink_state = MAV_STATE_EMERGENCY; + *mavlink_mode &= ~MAV_MODE_FLAG_SAFETY_ARMED; + break; + + case SYSTEM_STATE_REBOOT: + *mavlink_state = MAV_STATE_POWEROFF; + *mavlink_mode &= ~MAV_MODE_FLAG_SAFETY_ARMED; + break; + } + +} + +/** + * Receive data from UART. + */ +static void *receiveloop(void *arg) +{ + uint8_t ch; + + mavlink_message_t msg; + + prctl(PR_SET_NAME, "mavlink uart rcv", getpid()); + + while (1) { + + if (mavlink_exit_requested) break; + + /* blocking read on next byte */ + int nread = read(uart, &ch, 1); + + + if (nread > 0 && mavlink_parse_char(chan, ch, &msg, &status)) { //parse the char + /* handle generic messages and commands */ + handleMessage(&msg); + + /* Handle packet with waypoint component */ + mavlink_wpm_message_handler(&msg, &global_pos, &local_pos); + + /* Handle packet with parameter component */ + mavlink_pm_message_handler(MAVLINK_COMM_0, &msg); + msg.msgid = -1; + } + + } + + return NULL; +} + +/** + * Listen for uORB topics and send via MAVLink. + * + * This pthread performs a blocking wait on selected + * uORB topics and sends them via MAVLink to other + * vehicles or a ground control station. + */ +static void *uorb_receiveloop(void *arg) +{ + /* Set thread name */ + prctl(PR_SET_NAME, "mavlink uORB async", getpid()); + + + /* --- IMPORTANT: DEFINE NUMBER OF ORB STRUCTS TO WAIT FOR HERE --- */ + /* number of messages */ + const ssize_t fdsc = 10; + /* Sanity check variable and index */ + ssize_t fdsc_count = 0; + /* file descriptors to wait for */ + struct pollfd fds[fdsc]; + + + union { + struct sensor_combined_s raw; + struct vehicle_attitude_s att; + struct vehicle_gps_position_s gps; + struct ardrone_control_s ar_control; + } buf; + + /* --- SENSORS RAW VALUE --- */ + /* subscribe to ORB for sensors raw */ + int sensor_sub = orb_subscribe(ORB_ID(sensor_combined)); + orb_set_interval(sensor_sub, 100); /* 10Hz updates */ + fds[fdsc_count].fd = sensor_sub; + fds[fdsc_count].events = POLLIN; + fdsc_count++; + + /* --- ATTITUDE VALUE --- */ + /* subscribe to ORB for attitude */ + int att_sub = orb_subscribe(ORB_ID(vehicle_attitude)); + orb_set_interval(att_sub, 100); /* 10Hz updates */ + fds[fdsc_count].fd = att_sub; + fds[fdsc_count].events = POLLIN; + fdsc_count++; + + /* --- GPS VALUE --- */ + /* subscribe to ORB for attitude */ + int gps_sub = orb_subscribe(ORB_ID(vehicle_gps_position)); + orb_set_interval(gps_sub, 1000); /* 1Hz updates */ + fds[fdsc_count].fd = gps_sub; + fds[fdsc_count].events = POLLIN; + fdsc_count++; + + /* --- ARDRONE CONTROL --- */ + /* subscribe to ORB for AR.Drone controller outputs */ + int ar_sub = orb_subscribe(ORB_ID(ardrone_control)); + orb_set_interval(ar_sub, 200); /* 5Hz updates */ + fds[fdsc_count].fd = ar_sub; + fds[fdsc_count].events = POLLIN; + fdsc_count++; + + /* --- SYSTEM STATE --- */ + /* struct already globally allocated */ + /* subscribe to topic */ + int status_sub = orb_subscribe(ORB_ID(vehicle_status)); + orb_set_interval(status_sub, 300); /* max 3.33 Hz updates */ + fds[fdsc_count].fd = status_sub; + fds[fdsc_count].events = POLLIN; + fdsc_count++; + + /* --- RC CHANNELS VALUE --- */ + /* struct already globally allocated */ + /* subscribe to ORB for global position */ + int rc_sub = orb_subscribe(ORB_ID(rc_channels)); + orb_set_interval(rc_sub, 100); /* 10Hz updates */ + fds[fdsc_count].fd = rc_sub; + fds[fdsc_count].events = POLLIN; + fdsc_count++; + + /* --- FIXED WING CONTROL VALUE --- */ + /* struct already globally allocated */ + /* subscribe to ORB for fixed wing control */ + int fw_sub = orb_subscribe(ORB_ID(fixedwing_control)); + orb_set_interval(fw_sub, 200); /* 5Hz updates */ + fds[fdsc_count].fd = fw_sub; + fds[fdsc_count].events = POLLIN; + fdsc_count++; + + /* --- GLOBAL POS VALUE --- */ + /* struct already globally allocated and topic already subscribed */ + fds[fdsc_count].fd = global_pos_sub; + fds[fdsc_count].events = POLLIN; + fdsc_count++; + + /* --- LOCAL POS VALUE --- */ + /* struct and topic already globally subscribed */ + fds[fdsc_count].fd = local_pos_sub; + fds[fdsc_count].events = POLLIN; + fdsc_count++; + + unsigned int sensors_raw_counter = 0; + unsigned int attitude_counter = 0; + unsigned int gps_counter = 0; + + /* WARNING: If you get the error message below, + * then the number of registered messages (fdsc) + * differs from the number of messages in the above list. + */ + if (fdsc_count > fdsc) { + fprintf(stderr, "[mavlink] WARNING: Not enough space for poll fds allocated. Check %s:%d.\n", __FILE__, __LINE__); + fdsc_count = fdsc; + } + + /* + * set up poll to block for new data, + * wait for a maximum of 1000 ms (1 second) + */ + const int timeout = 5000; + + while (1) { + if (mavlink_exit_requested) break; + + int poll_ret = poll(fds, fdsc_count, timeout); + + /* handle the poll result */ + if (poll_ret == 0) { + /* XXX this means none of our providers is giving us data - might be an error? */ + } else if (poll_ret < 0) { + /* XXX this is seriously bad - should be an emergency */ + } else { + + /* --- SENSORS RAW VALUE --- */ + if (fds[0].revents & POLLIN) { + + /* copy sensors raw data into local buffer */ + orb_copy(ORB_ID(sensor_combined), sensor_sub, &buf.raw); + + /* send raw imu data */ + mavlink_msg_raw_imu_send(MAVLINK_COMM_0, buf.raw.timestamp, buf.raw.accelerometer_raw[0], buf.raw.accelerometer_raw[1], buf.raw.accelerometer_raw[2], buf.raw.gyro_raw[0], buf.raw.gyro_raw[1], buf.raw.gyro_raw[2], buf.raw.magnetometer_raw[0], buf.raw.magnetometer_raw[1], buf.raw.magnetometer_raw[2]); + /* send scaled imu data */ + mavlink_msg_scaled_imu_send(MAVLINK_COMM_0, buf.raw.timestamp, buf.raw.accelerometer_m_s2[0] * 9810, buf.raw.accelerometer_m_s2[1] * 9810, buf.raw.accelerometer_m_s2[2] * 9810, buf.raw.gyro_rad_s[0] * 1000, buf.raw.gyro_rad_s[1] * 1000, buf.raw.gyro_rad_s[2] * 1000, buf.raw.magnetometer_ga[0] * 1000, buf.raw.magnetometer_ga[1] * 1000, buf.raw.magnetometer_ga[2] * 1000); + /* send pressure */ + mavlink_msg_scaled_pressure_send(MAVLINK_COMM_0, buf.raw.timestamp / 1000, buf.raw.baro_pres_mbar, buf.raw.baro_alt_meter, buf.raw.baro_temp_celcius * 100); + + sensors_raw_counter++; + } + + /* --- ATTITUDE VALUE --- */ + if (fds[1].revents & POLLIN) { + + /* copy attitude data into local buffer */ + orb_copy(ORB_ID(vehicle_attitude), att_sub, &buf.att); + + /* send sensor values */ + mavlink_msg_attitude_send(MAVLINK_COMM_0, buf.att.timestamp / 1000, buf.att.roll, buf.att.pitch, buf.att.yaw, buf.att.rollspeed, buf.att.pitchspeed, buf.att.yawspeed); + + attitude_counter++; + } + + /* --- GPS VALUE --- */ + if (fds[2].revents & POLLIN) { + /* copy gps data into local buffer */ + orb_copy(ORB_ID(vehicle_gps_position), gps_sub, &buf.gps); + /* GPS position */ + mavlink_msg_gps_raw_int_send(MAVLINK_COMM_0, buf.gps.timestamp, buf.gps.fix_type, buf.gps.lat, buf.gps.lon, buf.gps.alt, buf.gps.eph, buf.gps.epv, buf.gps.vel, buf.gps.cog, buf.gps.satellites_visible); + + if (buf.gps.satellite_info_available && (gps_counter % 4 == 0)) { + mavlink_msg_gps_status_send(MAVLINK_COMM_0, buf.gps.satellites_visible, buf.gps.satellite_prn, buf.gps.satellite_used, buf.gps.satellite_elevation, buf.gps.satellite_azimuth, buf.gps.satellite_snr); + } + + gps_counter++; + } + + /* --- ARDRONE CONTROL OUTPUTS --- */ + if (fds[3].revents & POLLIN) { + /* copy ardrone control data into local buffer */ + orb_copy(ORB_ID(ardrone_control), ar_sub, &buf.ar_control); + uint64_t timestamp = buf.ar_control.timestamp; + float setpoint_roll = buf.ar_control.setpoint_attitude[0]; + float setpoint_pitch = buf.ar_control.setpoint_attitude[1]; + float setpoint_yaw = buf.ar_control.setpoint_attitude[2]; + float setpoint_thrust = buf.ar_control.setpoint_thrust_cast; + + float control_roll = buf.ar_control.attitude_control_output[0]; + float control_pitch = buf.ar_control.attitude_control_output[1]; + float control_yaw = buf.ar_control.attitude_control_output[2]; + + mavlink_msg_roll_pitch_yaw_thrust_setpoint_send(MAVLINK_COMM_0, timestamp / 1000, setpoint_roll, setpoint_pitch, setpoint_yaw, setpoint_thrust); + mavlink_msg_named_value_float_send(MAVLINK_COMM_0, timestamp / 1000, "cl.roll", control_roll); + mavlink_msg_named_value_float_send(MAVLINK_COMM_0, timestamp / 1000, "cl.pitch", control_pitch); + mavlink_msg_named_value_float_send(MAVLINK_COMM_0, timestamp / 1000, "cl.yaw", control_yaw); + } + + /* --- SYSTEM STATUS --- */ + if (fds[4].revents & POLLIN) { + /* immediately communicate state changes back to user */ + orb_copy(ORB_ID(vehicle_status), status_sub, &v_status); + /* enable or disable HIL */ + set_hil_on_off(v_status.mode); + + /* translate the current syste state to mavlink state and mode */ + uint8_t mavlink_state = 0; + uint8_t mavlink_mode = v_status.mode; + get_mavlink_mode_and_state(&v_status, &mavlink_state, &mavlink_mode); + + /* send heartbeat */ + mavlink_msg_heartbeat_send(chan, system_type, MAV_AUTOPILOT_GENERIC, mavlink_mode, v_status.state_machine, mavlink_state); + } + + /* --- RC CHANNELS --- */ + if (fds[5].revents & POLLIN) { + /* copy rc channels into local buffer */ + orb_copy(ORB_ID(rc_channels), rc_sub, &rc); + /* Channels are sent in MAVLink main loop at a fixed interval */ + // TODO decide where to send channels + } + + /* --- FIXED WING CONTROL CHANNELS --- */ + if (fds[6].revents & POLLIN) { + /* copy fixed wing control into local buffer */ + orb_copy(ORB_ID(fixedwing_control), fw_sub, &fw_control); + // XXX Output fixed wing control + } + + /* --- VEHICLE GLOBAL POSITION --- */ + if (fds[7].revents & POLLIN) { + /* copy global position data into local buffer */ + orb_copy(ORB_ID(vehicle_global_position), global_pos_sub, &global_pos); + uint64_t timestamp = global_pos.timestamp; + int32_t lat = (int32_t)(global_pos.lat * 1e7); + int32_t lon = (int32_t)(global_pos.lon * 1e7); + int32_t alt = (int32_t)(global_pos.alt * 1e3); + int32_t relative_alt = (int32_t)(global_pos.relative_alt * 1e3); + int16_t vx = (int16_t)(global_pos.vx * 1e2); + int16_t vy = (int16_t)(global_pos.vy * 1e2); + int16_t vz = (int16_t)(global_pos.vz * 1e2); + /* heading in degrees * 10, from 0 to 36.000) */ + uint16_t hdg = (global_pos.hdg / M_PI_F) * (180 * 10) + (180 * 10); + + mavlink_msg_global_position_int_send(MAVLINK_COMM_0, timestamp / 1000, lat, lon, alt, relative_alt, vx, vy, vz, hdg); + } + + /* --- VEHICLE LOCAL POSITION --- */ + if (fds[8].revents & POLLIN) { + /* copy local position data into local buffer */ + orb_copy(ORB_ID(vehicle_local_position), local_pos_sub, &local_pos); + mavlink_msg_local_position_ned_send(MAVLINK_COMM_0, local_pos.timestamp / 1000, local_pos.x, local_pos.y, local_pos.z, local_pos.vx, local_pos.vy, local_pos.vz); + } + + } + } + + return NULL; +} + +/**************************************************************************** + * MAVLink text message logger + ****************************************************************************/ + +static int mavlink_dev_ioctl(struct file *filep, int cmd, unsigned long arg); + +static const struct file_operations mavlink_fops = { + .ioctl = mavlink_dev_ioctl +}; + +static int +mavlink_dev_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + static unsigned int total_counter = 0; + + switch (cmd) { + case (int)MAVLINK_IOC_SEND_TEXT_INFO: + case (int)MAVLINK_IOC_SEND_TEXT_CRITICAL: + case (int)MAVLINK_IOC_SEND_TEXT_EMERGENCY: { + const char *txt = (const char *)arg; + strncpy(mavlink_message_string, txt, 51); + total_counter++; + return OK; + } + + default: + return ENOTTY; + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +void handleMessage(mavlink_message_t *msg) +{ + if (msg->msgid == MAVLINK_MSG_ID_COMMAND_LONG) { + mavlink_command_long_t cmd_mavlink; + mavlink_msg_command_long_decode(msg, &cmd_mavlink); + + if (cmd_mavlink.target_system == mavlink_system.sysid && ((cmd_mavlink.target_component == mavlink_system.compid) || (cmd_mavlink.target_component == MAV_COMP_ID_ALL))) { + //check for MAVLINK terminate command + if (cmd_mavlink.command == MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN && cmd_mavlink.param1 == 3.0f) { + /* This is the link shutdown command, terminate mavlink */ //TODO: check what happens with global_data buffers that are read by the mavlink app + printf("[mavlink] Terminating .. \n"); + fflush(stdout); + usleep(50000); + + /* terminate other threads */ + mavlink_exit_requested = true; + pthread_cancel(receive_thread); + pthread_cancel(uorb_receive_thread); + + pthread_exit(NULL); + + } else { + + /* Copy the content of mavlink_command_long_t cmd_mavlink into command_t cmd */ + vcmd.param1 = cmd_mavlink.param1; + vcmd.param2 = cmd_mavlink.param2; + vcmd.param3 = cmd_mavlink.param3; + vcmd.param4 = cmd_mavlink.param4; + vcmd.param5 = cmd_mavlink.param5; + vcmd.param6 = cmd_mavlink.param6; + vcmd.param7 = cmd_mavlink.param7; + vcmd.command = cmd_mavlink.command; + vcmd.target_system = cmd_mavlink.target_system; + vcmd.target_component = cmd_mavlink.target_component; + vcmd.source_system = msg->sysid; + vcmd.source_component = msg->compid; + vcmd.confirmation = cmd_mavlink.confirmation; + + /* Publish */ + orb_publish(ORB_ID(vehicle_command), cmd_pub, &vcmd); + } + } + } + + if (msg->msgid == MAVLINK_MSG_ID_SET_MODE) { + /* Set mode on request */ + mavlink_set_mode_t new_mode; + mavlink_msg_set_mode_decode(msg, &new_mode); + + /* Copy the content of mavlink_command_long_t cmd_mavlink into command_t cmd */ + vcmd.param1 = new_mode.base_mode; + vcmd.param2 = new_mode.custom_mode; + vcmd.param3 = 0; + vcmd.param4 = 0; + vcmd.param5 = 0; + vcmd.param6 = 0; + vcmd.param7 = 0; + vcmd.command = MAV_CMD_DO_SET_MODE; + vcmd.target_system = new_mode.target_system; + vcmd.target_component = MAV_COMP_ID_ALL; + vcmd.source_system = msg->sysid; + vcmd.source_component = msg->compid; + vcmd.confirmation = 1; + + /* create command */ + orb_publish(ORB_ID(vehicle_command), cmd_pub, &vcmd); + } + + /* Handle quadrotor motor setpoints */ + + if (msg->msgid == MAVLINK_MSG_ID_SET_QUAD_MOTORS_SETPOINT) { + mavlink_set_quad_motors_setpoint_t quad_motors_setpoint; + mavlink_msg_set_quad_motors_setpoint_decode(msg, &quad_motors_setpoint); +// printf("got MAVLINK_MSG_ID_SET_QUAD_MOTORS_SETPOINT target_system=%u, sysid = %u\n", quad_motors_setpoint.target_system, mavlink_system.sysid); + + if (quad_motors_setpoint.target_system == mavlink_system.sysid) { + ardrone_motors.motor_front_nw = quad_motors_setpoint.motor_front_nw; + ardrone_motors.motor_right_ne = quad_motors_setpoint.motor_right_ne; + ardrone_motors.motor_back_se = quad_motors_setpoint.motor_back_se; + ardrone_motors.motor_left_sw = quad_motors_setpoint.motor_left_sw; + + ardrone_motors.counter++; + ardrone_motors.timestamp = hrt_absolute_time(); + + /* Publish */ + orb_publish(ORB_ID(ardrone_motors_setpoint), ardrone_motors_pub, &ardrone_motors); + } + } + + /* + * Only decode hil messages in HIL mode. + * + * The HIL mode is enabled by the HIL bit flag + * in the system mode. Either send a set mode + * COMMAND_LONG message or a SET_MODE message + */ + + // printf("\n HIL ENABLED?: %s \n",(mavlink_hil_enabled)?"true":"false"); +#define DEG2RAD ((1.0/180.0)*M_PI) + + if (mavlink_hil_enabled) { + + if (msg->msgid == MAVLINK_MSG_ID_HIL_STATE) { + + mavlink_hil_state_t hil_state; + mavlink_msg_hil_state_decode(msg, &hil_state); + + // printf("\n HILSTATE : \n LAT: %i \n LON: %i \n ALT: %i \n " + // "ROLL %i \n PITCH %i \n YAW %i \n" + // "ROLLSPEED: %i \n PITCHSPEED: %i \n, YAWSPEED: %i \n", + // hil_state.lat/1000000, // 1e7 + // hil_state.lon/1000000, // 1e7 + // hil_state.alt/1000, // mm + // hil_state.roll, // float rad + // hil_state.pitch, // float rad + // hil_state.yaw, // float rad + // hil_state.rollspeed, // float rad/s + // hil_state.pitchspeed, // float rad/s + // hil_state.yawspeed); // float rad/s + + + hil_global_pos.lat = hil_state.lat; + hil_global_pos.lon = hil_state.lon; + hil_global_pos.alt = hil_state.alt/1000; + hil_global_pos.vx = hil_state.vx; + hil_global_pos.vy = hil_state.vy; + hil_global_pos.vz = hil_state.vz; + + /* set timestamp and notify processes (broadcast) */ + hil_global_pos.timestamp = hrt_absolute_time(); + orb_publish(ORB_ID(vehicle_global_position), pub_hil_global_pos, &hil_global_pos); + + hil_attitude.roll = hil_state.roll; + hil_attitude.pitch = hil_state.pitch; + hil_attitude.yaw = hil_state.yaw; + hil_attitude.rollspeed = hil_state.rollspeed; + hil_attitude.pitchspeed = hil_state.pitchspeed; + hil_attitude.yawspeed = hil_state.yawspeed; + + /* set timestamp and notify processes (broadcast) */ + hil_attitude.counter++; + hil_attitude.timestamp = hrt_absolute_time(); + orb_publish(ORB_ID(vehicle_attitude), pub_hil_attitude, &hil_attitude); + } + + // if (msg->msgid == MAVLINK_MSG_ID_ATTITUDE) { + // mavlink_attitude_t att; + // mavlink_msg_attitude_decode(msg, &att); + // float RAD2DEG = 57.3f; + + // // printf("\n\n\n ATTITUDE \n\n\n %i \n", (int)(1000*att.rollspeed)); + + // global_data_lock(&global_data_attitude->access_conf); + // global_data_attitude->roll = RAD2DEG * att.roll; + // global_data_attitude->pitch = RAD2DEG * att.pitch; + // global_data_attitude->yaw = RAD2DEG * att.yaw; + // global_data_attitude->rollspeed = att.rollspeed; + // global_data_attitude->pitchspeed = att.pitchspeed; + // global_data_attitude->yawspeed = att.yawspeed; + + // global_data_attitude->counter++; + // global_data_attitude->timestamp = hrt_absolute_time(); + // global_data_unlock(&global_data_attitude->access_conf); + // global_data_broadcast(&global_data_attitude->access_conf); + // } + + // if (msg->msgid == MAVLINK_MSG_ID_RAW_IMU) { + // mavlink_raw_imu_t imu; + // mavlink_msg_raw_imu_decode(msg, &imu); + + // // printf("\n\n\n RAW_IMU : %i \n %i \n %i \n %i \n %i \n %i \n\n\n", (int)(1000*imu.xgyro), + // // (int)(1000*imu.ygyro), (int)(1000*imu.zgyro)); + + // global_data_lock(&global_data_attitude->access_conf); + // global_data_attitude->rollspeed = 1000 * imu.xgyro; + // global_data_attitude->pitchspeed = 1000 * imu.ygyro; + // global_data_attitude->yawspeed = 1000 * imu.zgyro; + + // global_data_attitude->counter++; + // global_data_attitude->timestamp = hrt_absolute_time(); + // global_data_unlock(&global_data_attitude->access_conf); + // global_data_broadcast(&global_data_attitude->access_conf); + // } + + // if (msg->msgid == MAVLINK_MSG_ID_SCALED_IMU) { + // mavlink_raw_imu_t imu; + // mavlink_msg_raw_imu_decode(msg, &imu); + + // // printf("\n\n\n SCALED_IMU : %i \n %i \n %i \n %i \n %i \n %i \n\n\n", (int)(1000*imu.xgyro), + // // (int)(1000*imu.ygyro), (int)(1000*imu.zgyro)); + + // global_data_lock(&global_data_attitude->access_conf); + // global_data_attitude->rollspeed = 1000 * imu.xgyro; + // global_data_attitude->pitchspeed = 1000 * imu.ygyro; + // global_data_attitude->yawspeed = 1000 * imu.zgyro; + + // global_data_attitude->counter++; + // global_data_attitude->timestamp = hrt_absolute_time(); + // global_data_unlock(&global_data_attitude->access_conf); + // global_data_broadcast(&global_data_attitude->access_conf); + // } + } +} + +int mavlink_open_uart(int baudrate, const char *uart_name, struct termios *uart_config_original, bool *is_usb) +{ + /* process baud rate */ + int speed; + + switch (baudrate) { + case 0: speed = B0; break; + + case 50: speed = B50; break; + + case 75: speed = B75; break; + + case 110: speed = B110; break; + + case 134: speed = B134; break; + + case 150: speed = B150; break; + + case 200: speed = B200; break; + + case 300: speed = B300; break; + + case 600: speed = B600; break; + + case 1200: speed = B1200; break; + + case 1800: speed = B1800; break; + + case 2400: speed = B2400; break; + + case 4800: speed = B4800; break; + + case 9600: speed = B9600; break; + + case 19200: speed = B19200; break; + + case 38400: speed = B38400; break; + + case 57600: speed = B57600; break; + + case 115200: speed = B115200; break; + + case 230400: speed = B230400; break; + + case 460800: speed = B460800; break; + + case 921600: speed = B921600; break; + + default: + fprintf(stderr, "[mavlink] ERROR: Unsupported baudrate: %d\n\tsupported examples:\n\n\t9600\n19200\n38400\n57600\n115200\n230400\n460800\n921600\n\n", baudrate); + return -EINVAL; + } + + /* open uart */ + printf("[mavlink] UART is %s, baudrate is %d\n", uart_name, baudrate); + uart = open(uart_name, O_RDWR | O_NOCTTY); + + /* Try to set baud rate */ + struct termios uart_config; + int termios_state; + *is_usb = false; + + if (strcmp(uart_name, "/dev/ttyACM0") != OK) { + /* Back up the original uart configuration to restore it after exit */ + if ((termios_state = tcgetattr(uart, uart_config_original)) < 0) { + fprintf(stderr, "[mavlink] ERROR getting baudrate / termios config for %s: %d\n", uart_name, termios_state); + close(uart); + return -1; + } + + /* Fill the struct for the new configuration */ + tcgetattr(uart, &uart_config); + + /* Clear ONLCR flag (which appends a CR for every LF) */ + uart_config.c_oflag &= ~ONLCR; + + /* Set baud rate */ + if (cfsetispeed(&uart_config, speed) < 0 || cfsetospeed(&uart_config, speed) < 0) { + fprintf(stderr, "[mavlink] ERROR setting baudrate / termios config for %s: %d (cfsetispeed, cfsetospeed)\n", uart_name, termios_state); + close(uart); + return -1; + } + + + if ((termios_state = tcsetattr(uart, TCSANOW, &uart_config)) < 0) { + fprintf(stderr, "[mavlink] ERROR setting baudrate / termios config for %s (tcsetattr)\n", uart_name); + close(uart); + return -1; + } + + } else { + *is_usb = true; + } + + return uart; +} + +/** + * MAVLink Protocol main function. + */ +int mavlink_main(int argc, char *argv[]) +{ + wpm = &wpm_s; + + // print text + printf("[mavlink] MAVLink v1.0 serial interface starting..\n"); + + // create the device node that's used for sending text log messages, etc. + register_driver(MAVLINK_LOG_DEVICE, &mavlink_fops, 0666, NULL); + + /* Send attitude at 10 Hz / every 100 ms */ + mavlink_message_intervals[MAVLINK_MSG_ID_ATTITUDE] = 100; + /* Send raw sensor values at 10 Hz / every 100 ms */ + mavlink_message_intervals[MAVLINK_MSG_ID_RAW_IMU] = 100; + + //default values for arguments + char *uart_name = "/dev/ttyS0"; + int baudrate = 115200; + const char *commandline_usage = "\tusage: %s -d -b [-e/--exit-allowed]\n"; + + /* read program arguments */ + int i; + + for (i = 1; i < argc; i++) { /* argv[0] is "mavlink" */ + if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { + printf(commandline_usage, argv[0]); + return 0; + } + + /* UART device ID */ + if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--device") == 0) { + if (argc > i + 1) { + uart_name = argv[i + 1]; + + } else { + printf(commandline_usage, argv[0]); + return 0; + } + } + + /* baud rate */ + if (strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "--baud") == 0) { + if (argc > i + 1) { + baudrate = atoi(argv[i + 1]); + + } else { + printf(commandline_usage, argv[0]); + return 0; + } + } + + /* terminating MAVLink is allowed - yes/no */ + if (strcmp(argv[i], "-e") == 0 || strcmp(argv[i], "--exit-allowed") == 0) { + mavlink_link_termination_allowed = true; + } + } + + struct termios uart_config_original; + + bool usb_uart; + + uart = mavlink_open_uart(baudrate, uart_name, &uart_config_original, &usb_uart); + + if (uart < 0) { + printf("[mavlink] FAILED to open %s, terminating.\n", uart_name); + return -1; + } + + /* Flush UART */ + fflush(stdout); + + /* topics to advertise */ + ardrone_motors_pub = orb_advertise(ORB_ID(ardrone_motors_setpoint), &ardrone_motors); + cmd_pub = orb_advertise(ORB_ID(vehicle_command), &vcmd); + + /* topics to subscribe globally */ + /* subscribe to ORB for global position */ + global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position)); + orb_set_interval(global_pos_sub, 1000); /* 1Hz active updates */ + /* subscribe to ORB for local position */ + local_pos_sub = orb_subscribe(ORB_ID(vehicle_local_position)); + orb_set_interval(local_pos_sub, 1000); /* 1Hz active updates */ + + + pthread_attr_t receiveloop_attr; + pthread_attr_init(&receiveloop_attr); + pthread_attr_setstacksize(&receiveloop_attr, 2048); + pthread_create(&receive_thread, &receiveloop_attr, receiveloop, NULL); + + pthread_attr_t uorb_attr; + pthread_attr_init(&uorb_attr); + /* Set stack size, needs more than 2048 bytes */ + pthread_attr_setstacksize(&uorb_attr, 4096); + pthread_create(&uorb_receive_thread, &uorb_attr, uorb_receiveloop, NULL); + + /* initialize waypoint manager */ + mavlink_wpm_init(wpm); + + uint16_t counter = 0; + int lowspeed_counter = 0; + + /**< Subscribe to system state and RC channels */ + // int status_sub = orb_subscribe(ORB_ID(vehicle_status)); + // int rc_sub = orb_subscribe(ORB_ID(rc_channels)); + + while (1) { + + if (mavlink_exit_requested) break; + + /* get local and global position */ + orb_copy(ORB_ID(vehicle_global_position), global_pos_sub, &global_pos); + orb_copy(ORB_ID(vehicle_local_position), local_pos_sub, &local_pos); + + /* check if waypoint has been reached against the last positions */ + mavlink_waypoint_eventloop(mavlink_missionlib_get_system_timestamp(), &global_pos, &local_pos); + + // sleep + usleep(50000); + + // 1 Hz + if (lowspeed_counter == 10) { + /* translate the current syste state to mavlink state and mode */ + uint8_t mavlink_state = 0; + uint8_t mavlink_mode = v_status.mode; + get_mavlink_mode_and_state(&v_status, &mavlink_state, &mavlink_mode); + + /* send heartbeat */ + mavlink_msg_heartbeat_send(chan, system_type, MAV_AUTOPILOT_GENERIC, mavlink_mode, v_status.state_machine, mavlink_state); + + /* send status (values already copied in the section above) */ + mavlink_msg_sys_status_send(chan, v_status.onboard_control_sensors_present, v_status.onboard_control_sensors_enabled, + v_status.onboard_control_sensors_health, v_status.load, v_status.voltage_battery * 1000.f, v_status.current_battery * 1000.f, + v_status.battery_remaining, v_status.drop_rate_comm, v_status.errors_comm, + v_status.errors_count1, v_status.errors_count2, v_status.errors_count3, v_status.errors_count4); + + /* send over MAVLink */ + mavlink_msg_rc_channels_raw_send(chan, rc.timestamp / 1000, 0, rc.chan[0].raw, rc.chan[1].raw, rc.chan[2].raw, rc.chan[3].raw, + rc.chan[4].raw, rc.chan[5].raw, rc.chan[6].raw, rc.chan[7].raw, rc.rssi); + + lowspeed_counter = 0; + } + + lowspeed_counter++; + + /* Only send in HIL mode */ + if (v_status.mode & MAV_MODE_FLAG_HIL_ENABLED) { + /* Send the desired attitude from RC or from the autonomous controller */ + // XXX it should not depend on a RC setting, but on a system_state value + + float roll_ail, pitch_elev, throttle, yaw_rudd; + + if (rc.chan[rc.function[OVERRIDE]].scale < 2000) { + + //orb_copy(ORB_ID(fixedwing_control), fixed_wing_control_sub, &fixed_wing_control); + roll_ail = fw_control.attitude_control_output[ROLL]; + pitch_elev = fw_control.attitude_control_output[PITCH]; + throttle = fw_control.attitude_control_output[THROTTLE]; + yaw_rudd = fw_control.attitude_control_output[YAW]; + + } else { + + roll_ail = rc.chan[rc.function[ROLL]].scale; + pitch_elev = rc.chan[rc.function[PITCH]].scale; + throttle = rc.chan[rc.function[THROTTLE]].scale; + yaw_rudd = rc.chan[rc.function[YAW]].scale; + } + + /* hacked HIL implementation in order for the APM Planner to work + * (correct cmd: mavlink_msg_hil_controls_send()) + */ + + mavlink_msg_rc_channels_scaled_send(chan, + hrt_absolute_time(), + 0, // port 0 + roll_ail, + pitch_elev, + throttle, + yaw_rudd, + 0, + 0, + 0, + 0, + 1 /*rssi=1*/); + /* correct command duplicate */ + mavlink_msg_hil_controls_send(chan, + hrt_absolute_time(), + roll_ail, + pitch_elev, + yaw_rudd, + throttle, + 0, + 0, + 0, + 0, + 32, /* HIL_MODE */ + 0); + } + + /* send parameters at 20 Hz (if queued for sending) */ + mavlink_pm_queued_send(); + usleep(50000); + mavlink_pm_queued_send(); + + /* send one string at 10 Hz */ + mavlink_missionlib_send_gcs_string(mavlink_message_string); + mavlink_message_string[0] = '\0'; + counter++; + } + + /* wait for threads to complete */ + pthread_join(receive_thread, NULL); + pthread_join(uorb_receive_thread, NULL); + + /* Reset the UART flags to original state */ + if (!usb_uart) { + int termios_state; + + if ((termios_state = tcsetattr(uart, TCSANOW, &uart_config_original)) < 0) { + fprintf(stderr, "[mavlink] ERROR setting baudrate / termios config for %s (tcsetattr)\r\n", uart_name); + } + + printf("[mavlink] Restored original UART config, exiting..\n"); + } + + /* close uart */ + close(uart); + + fflush(stdout); + fflush(stderr); + + return 0; +} + + diff --git a/apps/mavlink/mavlink_bridge_header.h b/apps/mavlink/mavlink_bridge_header.h new file mode 100644 index 0000000000..26bc26fdfc --- /dev/null +++ b/apps/mavlink/mavlink_bridge_header.h @@ -0,0 +1,89 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file mavlink_bridge_header + * MAVLink bridge header for UART access. + */ + +/* MAVLink adapter header */ +#ifndef MAVLINK_BRIDGE_HEADER_H +#define MAVLINK_BRIDGE_HEADER_H + +#define MAVLINK_USE_CONVENIENCE_FUNCTIONS + +//use efficient approach, see mavlink_helpers.h +#define MAVLINK_SEND_UART_BYTES mavlink_send_uart_bytes + +#include "v1.0/mavlink_types.h" +#include + + +/* Struct that stores the communication settings of this system. + you can also define / alter these settings elsewhere, as long + as they're included BEFORE mavlink.h. + So you can set the + + mavlink_system.sysid = 100; // System ID, 1-255 + mavlink_system.compid = 50; // Component/Subsystem ID, 1-255 + + Lines also in your main.c, e.g. by reading these parameter from EEPROM. + */ +extern mavlink_system_t mavlink_system; + + +mqd_t gps_queue; +int uart; + + +/** + * @brief Send multiple chars (uint8_t) over a comm channel + * + * @param chan MAVLink channel to use, usually MAVLINK_COMM_0 = UART0 + * @param ch Character to send + */ +static inline void mavlink_send_uart_bytes(mavlink_channel_t chan, uint8_t *ch, uint16_t length) +{ + ssize_t ret; + + if (chan == MAVLINK_COMM_0) { + ret = write(uart, ch, (size_t)(sizeof(uint8_t) * length)); + + if (ret != length) { + printf("[mavlink] Error: Written %u instead of %u\n", ret, length); + } + } +} + +#endif /* MAVLINK_BRIDGE_HEADER_H */ diff --git a/apps/mavlink/mavlink_log.h b/apps/mavlink/mavlink_log.h new file mode 100644 index 0000000000..1ad1364be9 --- /dev/null +++ b/apps/mavlink/mavlink_log.h @@ -0,0 +1,83 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file mavlink_log.h + * MAVLink text logging. + */ + +#ifndef MAVLINK_LOG +#define MAVLINK_LOG + +/* + * IOCTL interface for sending log messages. + */ +#include + +/* + * The mavlink log device node; must be opened before messages + * can be logged. + */ +#define MAVLINK_LOG_DEVICE "/dev/mavlink" + +#define MAVLINK_IOC_SEND_TEXT_INFO _IOC(0x1100, 1) +#define MAVLINK_IOC_SEND_TEXT_CRITICAL _IOC(0x1100, 2) +#define MAVLINK_IOC_SEND_TEXT_EMERGENCY _IOC(0x1100, 3) + +/** + * Send a mavlink emergency message. + * + * @param _fd A file descriptor returned from open(MAVLINK_LOG_DEVICE, 0); + * @param _text The text to log; + */ +#define mavlink_log_emergency(_fd, _text) ioctl(_fd, MAVLINK_IOC_SEND_TEXT_EMERGENCY, (unsigned long)_text); + +/** + * Send a mavlink critical message. + * + * @param _fd A file descriptor returned from open(MAVLINK_LOG_DEVICE, 0); + * @param _text The text to log; + */ +#define mavlink_log_critical(_fd, _text) ioctl(_fd, MAVLINK_IOC_SEND_TEXT_CRITICAL, (unsigned long)_text); + +/** + * Send a mavlink info message. + * + * @param _fd A file descriptor returned from open(MAVLINK_LOG_DEVICE, 0); + * @param _text The text to log; + */ +#define mavlink_log_info(_fd, _text) ioctl(_fd, MAVLINK_IOC_SEND_TEXT_INFO, (unsigned long)_text); + +#endif + diff --git a/apps/mavlink/mavlink_parameters.c b/apps/mavlink/mavlink_parameters.c new file mode 100644 index 0000000000..a064fc1675 --- /dev/null +++ b/apps/mavlink/mavlink_parameters.c @@ -0,0 +1,189 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file mavlink_parameters.c + * MAVLink parameter protocol implementation (BSD-relicensed). + */ + +#include "mavlink_parameters.h" +#include +#include "math.h" /* isinf / isnan checks */ +#include +#include +#include +#include +#include + +extern mavlink_system_t mavlink_system; + +extern void mavlink_missionlib_send_message(mavlink_message_t *msg); +extern void mavlink_missionlib_send_gcs_string(const char *string); + +/* send one parameter, assume lock on global_data_parameter_storage */ +void mavlink_pm_send_one_parameter(uint16_t next_param) +{ + if (next_param < global_data_parameter_storage->pm.size) { + static char name_buf[MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN]; + mavlink_message_t tx_msg; + + strncpy((char *)name_buf, global_data_parameter_storage->pm.param_names[next_param], MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN); + + mavlink_msg_param_value_pack_chan(mavlink_system.sysid, + mavlink_system.compid, + MAVLINK_COMM_0, + &tx_msg, + name_buf, + global_data_parameter_storage->pm.param_values[next_param], + MAVLINK_TYPE_FLOAT, + global_data_parameter_storage->pm.size, + next_param); + mavlink_missionlib_send_message(&tx_msg); + + + // mavlink_msg_param_value_send(MAVLINK_COMM_0, + // name_buf, + // global_data_parameter_storage->pm.param_values[next_param], + // MAVLINK_TYPE_FLOAT, + // global_data_parameter_storage->pm.size, + // next_param); + } +} + +void mavlink_pm_message_handler(const mavlink_channel_t chan, const mavlink_message_t *msg) +{ + switch (msg->msgid) { + case MAVLINK_MSG_ID_PARAM_REQUEST_LIST: { + /* Start sending parameters */ + global_data_parameter_storage->pm.next_param = 0; + mavlink_missionlib_send_gcs_string("[pm] sending list"); + } break; + + case MAVLINK_MSG_ID_PARAM_SET: { + + /* Handle parameter setting */ + + if (msg->msgid == MAVLINK_MSG_ID_PARAM_SET) { + mavlink_param_set_t mavlink_param_set; + mavlink_msg_param_set_decode(msg, &mavlink_param_set); + + if (mavlink_param_set.target_system == mavlink_system.sysid && ((mavlink_param_set.target_component == mavlink_system.compid) || (mavlink_param_set.target_component == MAV_COMP_ID_ALL))) { + + uint16_t i; //parameters + uint16_t j; //chars + bool match; + + for (i = 0; i < PARAM_MAX_COUNT; i++) { + match = true; + + for (j = 0; j < MAX_PARAM_NAME_LEN; j++) { + /* Compare char by char */ + if (global_data_parameter_storage->pm.param_names[i][j] != mavlink_param_set.param_id[j]) { + match = false; + } + + /* End matching if null termination is reached */ + if (global_data_parameter_storage->pm.param_names[i][j] == '\0') { + break; + } + } + + /* Check if matched */ + if (match) { + // XXX handle param type as well, assuming float here + global_data_parameter_storage->pm.param_values[i] = mavlink_param_set.param_value; + mavlink_pm_send_one_parameter(i); + } + } + } + } + } break; + + case MAVLINK_MSG_ID_PARAM_REQUEST_READ: { + mavlink_param_request_read_t mavlink_param_request_read; + mavlink_msg_param_request_read_decode(msg, &mavlink_param_request_read); + + if (mavlink_param_request_read.target_system == mavlink_system.sysid && ((mavlink_param_request_read.target_component == mavlink_system.compid) || (mavlink_param_request_read.target_component == MAV_COMP_ID_ALL))) { + /* when no index is given, loop through string ids and compare them */ + if (mavlink_param_request_read.param_index == -1) { + + uint16_t i; //parameters + uint16_t j; //chars + bool match; + + for (i = 0; i < PARAM_MAX_COUNT; i++) { + match = true; + + for (j = 0; j < MAX_PARAM_NAME_LEN; j++) { + /* Compare char by char */ + if (global_data_parameter_storage->pm.param_names[i][j] != mavlink_param_request_read.param_id[j]) { + match = false; + } + + /* End matching if null termination is reached */ + if (global_data_parameter_storage->pm.param_names[i][j] == '\0') { + break; + } + } + + /* Check if matched */ + if (match) { + mavlink_pm_send_one_parameter(i); + } + } + + } else { + /* when index is >= 0, send this parameter again */ + mavlink_pm_send_one_parameter(mavlink_param_request_read.param_index); + } + } + + } break; + } +} + + +/** + * Send low-priority messages at a maximum rate of xx Hertz. + * + * This function sends messages at a lower rate to not exceed the wireless + * bandwidth. It sends one message each time it is called until the buffer is empty. + * Call this function with xx Hertz to increase/decrease the bandwidth. + */ +void mavlink_pm_queued_send(void) +{ + //send parameters one by one: + mavlink_pm_send_one_parameter(global_data_parameter_storage->pm.next_param); + global_data_parameter_storage->pm.next_param++; +} diff --git a/apps/mavlink/mavlink_parameters.h b/apps/mavlink/mavlink_parameters.h new file mode 100644 index 0000000000..e32732f581 --- /dev/null +++ b/apps/mavlink/mavlink_parameters.h @@ -0,0 +1,48 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file mavlink_parameters.h + * MAVLink parameter protocol definitions (BSD-relicensed). + */ + +/* This assumes you have the mavlink headers on your include path + or in the same folder as this source file */ + + +#include "v1.0/common/mavlink.h" +#include + +void mavlink_pm_message_handler(const mavlink_channel_t chan, const mavlink_message_t *msg); +void mavlink_pm_queued_send(void); diff --git a/apps/mavlink/waypoints.c b/apps/mavlink/waypoints.c new file mode 100644 index 0000000000..977f7d47e8 --- /dev/null +++ b/apps/mavlink/waypoints.c @@ -0,0 +1,1137 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: @author Petri Tanskanen + * @author Lorenz Meier + * @author Thomas Gubler + * @author Julian Oes + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file waypoints.c + * MAVLink waypoint protocol implementation (BSD-relicensed). + */ + +#include "waypoints.h" +#include +#include +#include +#include + +#ifndef FM_PI +#define FM_PI 3.1415926535897932384626433832795f +#endif + +bool debug = false; +bool verbose = false; + +extern mavlink_wpm_storage *wpm; + +extern void mavlink_missionlib_send_message(mavlink_message_t *msg); +extern void mavlink_missionlib_send_gcs_string(const char *string); +extern uint64_t mavlink_missionlib_get_system_timestamp(void); +extern void mavlink_missionlib_current_waypoint_changed(uint16_t index, float param1, + float param2, float param3, float param4, float param5_lat_x, + float param6_lon_y, float param7_alt_z, uint8_t frame, uint16_t command); + + +#define MAVLINK_WPM_NO_PRINTF + +uint8_t mavlink_wpm_comp_id = MAV_COMP_ID_MISSIONPLANNER; + +void mavlink_wpm_init(mavlink_wpm_storage *state) +{ + // Set all waypoints to zero + + // Set count to zero + state->size = 0; + state->max_size = MAVLINK_WPM_MAX_WP_COUNT; + state->current_state = MAVLINK_WPM_STATE_IDLE; + state->current_partner_sysid = 0; + state->current_partner_compid = 0; + state->timestamp_lastaction = 0; + state->timestamp_last_send_setpoint = 0; + state->timeout = MAVLINK_WPM_PROTOCOL_TIMEOUT_DEFAULT; + state->delay_setpoint = MAVLINK_WPM_SETPOINT_DELAY_DEFAULT; + state->idle = false; ///< indicates if the system is following the waypoints or is waiting + state->current_active_wp_id = -1; ///< id of current waypoint + state->yaw_reached = false; ///< boolean for yaw attitude reached + state->pos_reached = false; ///< boolean for position reached + state->timestamp_lastoutside_orbit = 0;///< timestamp when the MAV was last outside the orbit or had the wrong yaw value + state->timestamp_firstinside_orbit = 0;///< timestamp when the MAV was the first time after a waypoint change inside the orbit and had the correct yaw value + +} + +/* + * @brief Sends an waypoint ack message + */ +void mavlink_wpm_send_waypoint_ack(uint8_t sysid, uint8_t compid, uint8_t type) +{ + mavlink_message_t msg; + mavlink_mission_ack_t wpa; + + wpa.target_system = wpm->current_partner_sysid; + wpa.target_component = wpm->current_partner_compid; + wpa.type = type; + + mavlink_msg_mission_ack_encode(mavlink_system.sysid, mavlink_wpm_comp_id, &msg, &wpa); + mavlink_missionlib_send_message(&msg); + + // FIXME TIMING usleep(paramClient->getParamValue("PROTOCOLDELAY")); + + if (MAVLINK_WPM_TEXT_FEEDBACK) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("Sent waypoint ACK"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Sent waypoint ack (%u) to ID %u\n", wpa.type, wpa.target_system); + +#endif + mavlink_missionlib_send_gcs_string("Sent waypoint ACK"); + } +} + +/* + * @brief Broadcasts the new target waypoint and directs the MAV to fly there + * + * This function broadcasts its new active waypoint sequence number and + * sends a message to the controller, advising it to fly to the coordinates + * of the waypoint with a given orientation + * + * @param seq The waypoint sequence number the MAV should fly to. + */ +void mavlink_wpm_send_waypoint_current(uint16_t seq) +{ + if (seq < wpm->size) { + mavlink_mission_item_t *cur = &(wpm->waypoints[seq]); + + mavlink_message_t msg; + mavlink_mission_current_t wpc; + + wpc.seq = cur->seq; + + mavlink_msg_mission_current_encode(mavlink_system.sysid, mavlink_wpm_comp_id, &msg, &wpc); + mavlink_missionlib_send_message(&msg); + + // FIXME TIMING usleep(paramClient->getParamValue("PROTOCOLDELAY")); + + if (MAVLINK_WPM_TEXT_FEEDBACK) mavlink_missionlib_send_gcs_string("Set current waypoint\n"); //// printf("Broadcasted new current waypoint %u\n", wpc.seq); + + } else { + if (MAVLINK_WPM_TEXT_FEEDBACK) mavlink_missionlib_send_gcs_string("ERROR: wp index out of bounds\n"); + } +} + +/* + * @brief Directs the MAV to fly to a position + * + * Sends a message to the controller, advising it to fly to the coordinates + * of the waypoint with a given orientation + * + * @param seq The waypoint sequence number the MAV should fly to. + */ +void mavlink_wpm_send_setpoint(uint16_t seq) +{ + if (seq < wpm->size) { + mavlink_mission_item_t *cur = &(wpm->waypoints[seq]); + mavlink_missionlib_current_waypoint_changed(cur->seq, cur->param1, + cur->param2, cur->param3, cur->param4, cur->x, + cur->y, cur->z, cur->frame, cur->command); + + wpm->timestamp_last_send_setpoint = mavlink_missionlib_get_system_timestamp(); + + } else { + if (MAVLINK_WPM_TEXT_FEEDBACK) mavlink_missionlib_send_gcs_string("ERROR: Waypoint index out of bounds\n"); //// if (verbose) // printf("ERROR: index out of bounds\n"); + } +} + +void mavlink_wpm_send_waypoint_count(uint8_t sysid, uint8_t compid, uint16_t count) +{ + mavlink_message_t msg; + mavlink_mission_count_t wpc; + + wpc.target_system = wpm->current_partner_sysid; + wpc.target_component = wpm->current_partner_compid; + wpc.count = count; + + mavlink_msg_mission_count_encode(mavlink_system.sysid, mavlink_wpm_comp_id, &msg, &wpc); + mavlink_missionlib_send_message(&msg); + + if (MAVLINK_WPM_TEXT_FEEDBACK) mavlink_missionlib_send_gcs_string("Sent waypoint count"); //// if (verbose) // printf("Sent waypoint count (%u) to ID %u\n", wpc.count, wpc.target_system); + + // FIXME TIMING usleep(paramClient->getParamValue("PROTOCOLDELAY")); +} + +void mavlink_wpm_send_waypoint(uint8_t sysid, uint8_t compid, uint16_t seq) +{ + if (seq < wpm->size) { + mavlink_message_t msg; + mavlink_mission_item_t *wp = &(wpm->waypoints[seq]); + wp->target_system = wpm->current_partner_sysid; + wp->target_component = wpm->current_partner_compid; + mavlink_msg_mission_item_encode(mavlink_system.sysid, mavlink_wpm_comp_id, &msg, wp); + mavlink_missionlib_send_message(&msg); + + if (MAVLINK_WPM_TEXT_FEEDBACK) mavlink_missionlib_send_gcs_string("Sent waypoint"); //// if (verbose) // printf("Sent waypoint %u to ID %u\n", wp->seq, wp->target_system); + + // FIXME TIMING usleep(paramClient->getParamValue("PROTOCOLDELAY")); + + } else { + if (MAVLINK_WPM_TEXT_FEEDBACK) mavlink_missionlib_send_gcs_string("ERROR: Waypoint index out of bounds\n"); + } +} + +void mavlink_wpm_send_waypoint_request(uint8_t sysid, uint8_t compid, uint16_t seq) +{ + if (seq < wpm->max_size) { + mavlink_message_t msg; + mavlink_mission_request_t wpr; + wpr.target_system = wpm->current_partner_sysid; + wpr.target_component = wpm->current_partner_compid; + wpr.seq = seq; + mavlink_msg_mission_request_encode(mavlink_system.sysid, mavlink_wpm_comp_id, &msg, &wpr); + mavlink_missionlib_send_message(&msg); + + if (MAVLINK_WPM_TEXT_FEEDBACK) mavlink_missionlib_send_gcs_string("Sent waypoint request"); //// if (verbose) // printf("Sent waypoint request %u to ID %u\n", wpr.seq, wpr.target_system); + + // FIXME TIMING usleep(paramClient->getParamValue("PROTOCOLDELAY")); + + } else { + if (MAVLINK_WPM_TEXT_FEEDBACK) mavlink_missionlib_send_gcs_string("ERROR: Waypoint index exceeds list capacity\n"); + } +} + +/* + * @brief emits a message that a waypoint reached + * + * This function broadcasts a message that a waypoint is reached. + * + * @param seq The waypoint sequence number the MAV has reached. + */ +void mavlink_wpm_send_waypoint_reached(uint16_t seq) +{ + mavlink_message_t msg; + mavlink_mission_item_reached_t wp_reached; + + wp_reached.seq = seq; + + mavlink_msg_mission_item_reached_encode(mavlink_system.sysid, mavlink_wpm_comp_id, &msg, &wp_reached); + mavlink_missionlib_send_message(&msg); + + if (MAVLINK_WPM_TEXT_FEEDBACK) mavlink_missionlib_send_gcs_string("Sent waypoint reached message"); //// if (verbose) // printf("Sent waypoint %u reached message\n", wp_reached.seq); + + // FIXME TIMING usleep(paramClient->getParamValue("PROTOCOLDELAY")); +} + +//float mavlink_wpm_distance_to_segment(uint16_t seq, float x, float y, float z) +//{ +// if (seq < wpm->size) +// { +// mavlink_mission_item_t *cur = waypoints->at(seq); +// +// const PxVector3 A(cur->x, cur->y, cur->z); +// const PxVector3 C(x, y, z); +// +// // seq not the second last waypoint +// if ((uint16_t)(seq+1) < wpm->size) +// { +// mavlink_mission_item_t *next = waypoints->at(seq+1); +// const PxVector3 B(next->x, next->y, next->z); +// const float r = (B-A).dot(C-A) / (B-A).lengthSquared(); +// if (r >= 0 && r <= 1) +// { +// const PxVector3 P(A + r*(B-A)); +// return (P-C).length(); +// } +// else if (r < 0.f) +// { +// return (C-A).length(); +// } +// else +// { +// return (C-B).length(); +// } +// } +// else +// { +// return (C-A).length(); +// } +// } +// else +// { +// // if (verbose) // printf("ERROR: index out of bounds\n"); +// } +// return -1.f; +//} + +/* + * Calculate distance in global frame. + * + * The distance calculation is based on the WGS84 geoid (GPS) + */ +float mavlink_wpm_distance_to_point_global_wgs84(uint16_t seq, float lat, float lon, float alt) +{ + //TODO: implement for z once altidude contoller is implemented + + static uint16_t counter; + +// if(counter % 10 == 0) printf(" x = %.10f, y = %.10f\n", x, y); + if (seq < wpm->size) { + mavlink_mission_item_t *cur = &(wpm->waypoints[seq]); + + double current_x_rad = cur->x / 180.0 * M_PI; + double current_y_rad = cur->y / 180.0 * M_PI; + double x_rad = lat / 180.0 * M_PI; + double y_rad = lon / 180.0 * M_PI; + + double d_lat = x_rad - current_x_rad; + double d_lon = y_rad - current_y_rad; + + double a = sin(d_lat / 2.0) * sin(d_lat / 2.0) + sin(d_lon / 2.0) * sin(d_lon / 2.0f) * cos(current_x_rad) * cos(x_rad); + double c = 2 * atan2(sqrt(a), sqrt(1 - a)); + + const double radius_earth = 6371000.0; + + return radius_earth * c; + + } else { + return -1.0f; + } + + counter++; + +} + +/* + * Calculate distance in local frame (NED) + */ +float mavlink_wpm_distance_to_point_local(uint16_t seq, float x, float y, float z) +{ + if (seq < wpm->size) { + mavlink_mission_item_t *cur = &(wpm->waypoints[seq]); + + float dx = (cur->x - x); + float dy = (cur->y - y); + float dz = (cur->z - z); + + return sqrt(dx * dx + dy * dy + dz * dz); + + } else { + return -1.0f; + } +} + +void check_waypoints_reached(uint64_t now, const struct vehicle_global_position_s *global_pos, struct vehicle_local_position_s *local_pos) +{ + static uint16_t counter; + + if (wpm->size > 0 && counter % 10 == 0) { + printf("Currect active waypoint id: %i\n", wpm->current_active_wp_id); + } + + + if (wpm->current_active_wp_id < wpm->size) { + + float orbit = wpm->waypoints[wpm->current_active_wp_id].param2; + int coordinate_frame = wpm->waypoints[wpm->current_active_wp_id].frame; + float dist = -1.0f; + + if (coordinate_frame == (int)MAV_FRAME_GLOBAL) { + dist = mavlink_wpm_distance_to_point_global_wgs84(wpm->current_active_wp_id, global_pos->lat, global_pos->lon, global_pos->alt); + + } else if (coordinate_frame == (int)MAV_FRAME_GLOBAL_RELATIVE_ALT) { + dist = mavlink_wpm_distance_to_point_global_wgs84(wpm->current_active_wp_id, global_pos->lat, global_pos->lon, global_pos->relative_alt); + + } else if (coordinate_frame == (int)MAV_FRAME_LOCAL_ENU || coordinate_frame == (int)MAV_FRAME_LOCAL_NED) { + dist = mavlink_wpm_distance_to_point_local(wpm->current_active_wp_id, local_pos->x, local_pos->y, local_pos->z); + + } else if (coordinate_frame == (int)MAV_FRAME_MISSION) { + /* Check if conditions of mission item are satisfied */ + // XXX TODO + } + + if (dist >= 0.f && dist <= orbit /*&& wpm->yaw_reached*/) { //TODO implement yaw + wpm->pos_reached = true; + + if (counter % 10 == 0) + printf("Setpoint reached: %0.4f, orbit: %.4f\n", dist, orbit); + } + +// else +// { +// if(counter % 100 == 0) +// printf("Setpoint not reached yet: %0.4f, orbit: %.4f\n",dist,orbit); +// } + } + + //check if the current waypoint was reached + if (wpm->pos_reached /*wpm->yaw_reached &&*/ && !wpm->idle) { + if (wpm->current_active_wp_id < wpm->size) { + mavlink_mission_item_t *cur_wp = &(wpm->waypoints[wpm->current_active_wp_id]); + + if (wpm->timestamp_firstinside_orbit == 0) { + // Announce that last waypoint was reached + printf("Reached waypoint %u for the first time \n", cur_wp->seq); + mavlink_wpm_send_waypoint_reached(cur_wp->seq); + wpm->timestamp_firstinside_orbit = now; + } + + // check if the MAV was long enough inside the waypoint orbit + //if (now-timestamp_lastoutside_orbit > (cur_wp->hold_time*1000)) + if (now - wpm->timestamp_firstinside_orbit >= cur_wp->param2 * 1000) { + printf("Reached waypoint %u long enough \n", cur_wp->seq); + + if (cur_wp->autocontinue) { + cur_wp->current = 0; + + if (wpm->current_active_wp_id == wpm->size - 1 && wpm->size > 1) { + //the last waypoint was reached, if auto continue is + //activated restart the waypoint list from the beginning + wpm->current_active_wp_id = 1; + + } else { + if ((uint16_t)(wpm->current_active_wp_id + 1) < wpm->size) + wpm->current_active_wp_id++; + } + + // Fly to next waypoint + wpm->timestamp_firstinside_orbit = 0; + mavlink_wpm_send_waypoint_current(wpm->current_active_wp_id); + mavlink_wpm_send_setpoint(wpm->current_active_wp_id); + wpm->waypoints[wpm->current_active_wp_id].current = true; + wpm->pos_reached = false; + wpm->yaw_reached = false; + printf("Set new waypoint (%u)\n", wpm->current_active_wp_id); + } + } + } + + } else { + wpm->timestamp_lastoutside_orbit = now; + } + + counter++; +} + + +int mavlink_waypoint_eventloop(uint64_t now, const struct vehicle_global_position_s *global_position, struct vehicle_local_position_s *local_position) +{ + /* check for timed-out operations */ + if (now - wpm->timestamp_lastaction > wpm->timeout && wpm->current_state != MAVLINK_WPM_STATE_IDLE) { + +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("Operation timeout switching -> IDLE"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Last operation (state=%u) timed out, changing state to MAVLINK_WPM_STATE_IDLE\n", wpm->current_state); + +#endif + wpm->current_state = MAVLINK_WPM_STATE_IDLE; + wpm->current_count = 0; + wpm->current_partner_sysid = 0; + wpm->current_partner_compid = 0; + wpm->current_wp_id = -1; + + if (wpm->size == 0) { + wpm->current_active_wp_id = -1; + } + } + + if (now - wpm->timestamp_last_send_setpoint > wpm->delay_setpoint && wpm->current_active_wp_id < wpm->size) { + mavlink_wpm_send_setpoint(wpm->current_active_wp_id); + } + + check_waypoints_reached(now, global_position , local_position); + + return OK; +} + + +void mavlink_wpm_message_handler(const mavlink_message_t *msg, const struct vehicle_global_position_s *global_pos , struct vehicle_local_position_s *local_pos) +{ + uint64_t now = mavlink_missionlib_get_system_timestamp(); + + switch (msg->msgid) { +// case MAVLINK_MSG_ID_ATTITUDE: +// { +// if(msg->sysid == mavlink_system.sysid && wpm->current_active_wp_id < wpm->size) +// { +// mavlink_mission_item_t *wp = &(wpm->waypoints[wpm->current_active_wp_id]); +// if(wp->frame == MAV_FRAME_LOCAL_ENU || wp->frame == MAV_FRAME_LOCAL_NED) +// { +// mavlink_attitude_t att; +// mavlink_msg_attitude_decode(msg, &att); +// float yaw_tolerance = wpm->accept_range_yaw; +// //compare current yaw +// if (att.yaw - yaw_tolerance >= 0.0f && att.yaw + yaw_tolerance < 2.f*FM_PI) +// { +// if (att.yaw - yaw_tolerance <= wp->param4 && att.yaw + yaw_tolerance >= wp->param4) +// wpm->yaw_reached = true; +// } +// else if(att.yaw - yaw_tolerance < 0.0f) +// { +// float lowerBound = 360.0f + att.yaw - yaw_tolerance; +// if (lowerBound < wp->param4 || wp->param4 < att.yaw + yaw_tolerance) +// wpm->yaw_reached = true; +// } +// else +// { +// float upperBound = att.yaw + yaw_tolerance - 2.f*FM_PI; +// if (att.yaw - yaw_tolerance < wp->param4 || wp->param4 < upperBound) +// wpm->yaw_reached = true; +// } +// } +// } +// break; +// } +// +// case MAVLINK_MSG_ID_LOCAL_POSITION_NED: +// { +// if(msg->sysid == mavlink_system.sysid && wpm->current_active_wp_id < wpm->size) +// { +// mavlink_mission_item_t *wp = &(wpm->waypoints[wpm->current_active_wp_id]); +// +// if(wp->frame == MAV_FRAME_LOCAL_ENU || MAV_FRAME_LOCAL_NED) +// { +// mavlink_local_position_ned_t pos; +// mavlink_msg_local_position_ned_decode(msg, &pos); +// //// if (debug) // printf("Received new position: x: %f | y: %f | z: %f\n", pos.x, pos.y, pos.z); +// +// wpm->pos_reached = false; +// +// // compare current position (given in message) with current waypoint +// float orbit = wp->param1; +// +// float dist; +//// if (wp->param2 == 0) +//// { +//// // FIXME segment distance +//// //dist = mavlink_wpm_distance_to_segment(current_active_wp_id, pos.x, pos.y, pos.z); +//// } +//// else +//// { +// dist = mavlink_wpm_distance_to_point(wpm->current_active_wp_id, pos.x, pos.y, pos.z); +//// } +// +// if (dist >= 0.f && dist <= orbit && wpm->yaw_reached) +// { +// wpm->pos_reached = true; +// } +// } +// } +// break; +// } + +// case MAVLINK_MSG_ID_CMD: // special action from ground station +// { +// mavlink_cmd_t action; +// mavlink_msg_cmd_decode(msg, &action); +// if(action.target == mavlink_system.sysid) +// { +// // if (verbose) std::cerr << "Waypoint: received message with action " << action.action << std::endl; +// switch (action.action) +// { +// // case MAV_ACTION_LAUNCH: +// // // if (verbose) std::cerr << "Launch received" << std::endl; +// // current_active_wp_id = 0; +// // if (wpm->size>0) +// // { +// // setActive(waypoints[current_active_wp_id]); +// // } +// // else +// // // if (verbose) std::cerr << "No launch, waypointList empty" << std::endl; +// // break; +// +// // case MAV_ACTION_CONTINUE: +// // // if (verbose) std::c +// // err << "Continue received" << std::endl; +// // idle = false; +// // setActive(waypoints[current_active_wp_id]); +// // break; +// +// // case MAV_ACTION_HALT: +// // // if (verbose) std::cerr << "Halt received" << std::endl; +// // idle = true; +// // break; +// +// // default: +// // // if (verbose) std::cerr << "Unknown action received with id " << action.action << ", no action taken" << std::endl; +// // break; +// } +// } +// break; +// } + + case MAVLINK_MSG_ID_MISSION_ACK: { + mavlink_mission_ack_t wpa; + mavlink_msg_mission_ack_decode(msg, &wpa); + + if ((msg->sysid == wpm->current_partner_sysid && msg->compid == wpm->current_partner_compid) && (wpa.target_system == mavlink_system.sysid /*&& wpa.target_component == mavlink_wpm_comp_id*/)) { + wpm->timestamp_lastaction = now; + + if (wpm->current_state == MAVLINK_WPM_STATE_SENDLIST || wpm->current_state == MAVLINK_WPM_STATE_SENDLIST_SENDWPS) { + if (wpm->current_wp_id == wpm->size - 1) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("Got last WP ACK state -> IDLE"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Received ACK after having sent last waypoint, going to state MAVLINK_WPM_STATE_IDLE\n"); + +#endif + wpm->current_state = MAVLINK_WPM_STATE_IDLE; + wpm->current_wp_id = 0; + } + } + + } else { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("REJ. WP CMD: curr partner id mismatch"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("IGNORED WAYPOINT COMMAND BECAUSE TARGET SYSTEM AND COMPONENT OR COMM PARTNER ID MISMATCH\n"); + +#endif + } + + break; + } + + case MAVLINK_MSG_ID_MISSION_SET_CURRENT: { + mavlink_mission_set_current_t wpc; + mavlink_msg_mission_set_current_decode(msg, &wpc); + + if (wpc.target_system == mavlink_system.sysid /*&& wpc.target_component == mavlink_wpm_comp_id*/) { + wpm->timestamp_lastaction = now; + + if (wpm->current_state == MAVLINK_WPM_STATE_IDLE) { + if (wpc.seq < wpm->size) { + // if (verbose) // printf("Received MAVLINK_MSG_ID_MISSION_ITEM_SET_CURRENT\n"); + wpm->current_active_wp_id = wpc.seq; + uint32_t i; + + for (i = 0; i < wpm->size; i++) { + if (i == wpm->current_active_wp_id) { + wpm->waypoints[i].current = true; + + } else { + wpm->waypoints[i].current = false; + } + } + +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("NEW WP SET"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("New current waypoint %u\n", wpm->current_active_wp_id); + +#endif + wpm->yaw_reached = false; + wpm->pos_reached = false; + mavlink_wpm_send_waypoint_current(wpm->current_active_wp_id); + mavlink_wpm_send_setpoint(wpm->current_active_wp_id); + wpm->timestamp_firstinside_orbit = 0; + + } else { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("IGN WP CURR CMD: Not in list"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM_SET_CURRENT: Index out of bounds\n"); + +#endif + } + + } else { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("IGN WP CURR CMD: Busy"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("IGNORED WAYPOINT COMMAND BECAUSE NOT IN IDLE STATE\n"); + +#endif + } + + } else { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("REJ. WP CMD: target id mismatch"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("IGNORED WAYPOINT COMMAND BECAUSE TARGET SYSTEM AND COMPONENT OR COMM PARTNER ID MISMATCH\n"); + +#endif + } + + break; + } + + case MAVLINK_MSG_ID_MISSION_REQUEST_LIST: { + mavlink_mission_request_list_t wprl; + mavlink_msg_mission_request_list_decode(msg, &wprl); + + if (wprl.target_system == mavlink_system.sysid /*&& wprl.target_component == mavlink_wpm_comp_id*/) { + wpm->timestamp_lastaction = now; + + if (wpm->current_state == MAVLINK_WPM_STATE_IDLE || wpm->current_state == MAVLINK_WPM_STATE_SENDLIST) { + if (wpm->size > 0) { + //if (verbose && wpm->current_state == MAVLINK_WPM_STATE_IDLE) // printf("Got MAVLINK_MSG_ID_MISSION_ITEM_REQUEST_LIST from %u changing state to MAVLINK_WPM_STATE_SENDLIST\n", msg->sysid); +// if (verbose && wpm->current_state == MAVLINK_WPM_STATE_SENDLIST) // printf("Got MAVLINK_MSG_ID_MISSION_ITEM_REQUEST_LIST again from %u staying in state MAVLINK_WPM_STATE_SENDLIST\n", msg->sysid); + wpm->current_state = MAVLINK_WPM_STATE_SENDLIST; + wpm->current_wp_id = 0; + wpm->current_partner_sysid = msg->sysid; + wpm->current_partner_compid = msg->compid; + + } else { + // if (verbose) // printf("Got MAVLINK_MSG_ID_MISSION_ITEM_REQUEST_LIST from %u but have no waypoints, staying in \n", msg->sysid); + } + + wpm->current_count = wpm->size; + mavlink_wpm_send_waypoint_count(msg->sysid, msg->compid, wpm->current_count); + + } else { + // if (verbose) // printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM_REQUEST_LIST because i'm doing something else already (state=%i).\n", wpm->current_state); + } + } else { + // if (verbose) // printf("IGNORED WAYPOINT COMMAND BECAUSE TARGET SYSTEM AND COMPONENT MISMATCH\n"); + } + + break; + } + + case MAVLINK_MSG_ID_MISSION_REQUEST: { + mavlink_mission_request_t wpr; + mavlink_msg_mission_request_decode(msg, &wpr); + + if (msg->sysid == wpm->current_partner_sysid && msg->compid == wpm->current_partner_compid && wpr.target_system == mavlink_system.sysid /*&& wpr.target_component == mavlink_wpm_comp_id*/) { + wpm->timestamp_lastaction = now; + + //ensure that we are in the correct state and that the first request has id 0 and the following requests have either the last id (re-send last waypoint) or last_id+1 (next waypoint) + if ((wpm->current_state == MAVLINK_WPM_STATE_SENDLIST && wpr.seq == 0) || (wpm->current_state == MAVLINK_WPM_STATE_SENDLIST_SENDWPS && (wpr.seq == wpm->current_wp_id || wpr.seq == wpm->current_wp_id + 1) && wpr.seq < wpm->size)) { + if (wpm->current_state == MAVLINK_WPM_STATE_SENDLIST) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("GOT WP REQ, state -> SEND"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Got MAVLINK_MSG_ID_MISSION_ITEM_REQUEST of waypoint %u from %u changing state to MAVLINK_WPM_STATE_SENDLIST_SENDWPS\n", wpr.seq, msg->sysid); + +#endif + } + + if (wpm->current_state == MAVLINK_WPM_STATE_SENDLIST_SENDWPS && wpr.seq == wpm->current_wp_id + 1) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("GOT 2nd WP REQ"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Got MAVLINK_MSG_ID_MISSION_ITEM_REQUEST of waypoint %u from %u staying in state MAVLINK_WPM_STATE_SENDLIST_SENDWPS\n", wpr.seq, msg->sysid); + +#endif + } + + if (wpm->current_state == MAVLINK_WPM_STATE_SENDLIST_SENDWPS && wpr.seq == wpm->current_wp_id) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("GOT 2nd WP REQ"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Got MAVLINK_MSG_ID_MISSION_ITEM_REQUEST of waypoint %u (again) from %u staying in state MAVLINK_WPM_STATE_SENDLIST_SENDWPS\n", wpr.seq, msg->sysid); + +#endif + } + + wpm->current_state = MAVLINK_WPM_STATE_SENDLIST_SENDWPS; + wpm->current_wp_id = wpr.seq; + mavlink_wpm_send_waypoint(wpm->current_partner_sysid, wpm->current_partner_compid, wpr.seq); + + } else { + // if (verbose) + { + if (!(wpm->current_state == MAVLINK_WPM_STATE_SENDLIST || wpm->current_state == MAVLINK_WPM_STATE_SENDLIST_SENDWPS)) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("REJ. WP CMD: Busy"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM_REQUEST because i'm doing something else already (state=%i).\n", wpm->current_state); + +#endif + break; + + } else if (wpm->current_state == MAVLINK_WPM_STATE_SENDLIST) { + if (wpr.seq != 0) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("REJ. WP CMD: First id != 0"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM_REQUEST because the first requested waypoint ID (%u) was not 0.\n", wpr.seq); + +#endif + } + + } else if (wpm->current_state == MAVLINK_WPM_STATE_SENDLIST_SENDWPS) { + if (wpr.seq != wpm->current_wp_id && wpr.seq != wpm->current_wp_id + 1) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("REJ. WP CMD: Req. WP was unexpected"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM_REQUEST because the requested waypoint ID (%u) was not the expected (%u or %u).\n", wpr.seq, wpm->current_wp_id, wpm->current_wp_id + 1); + +#endif + + } else if (wpr.seq >= wpm->size) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("REJ. WP CMD: Req. WP not in list"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM_REQUEST because the requested waypoint ID (%u) was out of bounds.\n", wpr.seq); + +#endif + } + + } else { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("REJ. WP CMD: ?"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM_REQUEST - FIXME: missed error description\n"); + +#endif + } + } + } + + } else { + //we we're target but already communicating with someone else + if ((wpr.target_system == mavlink_system.sysid /*&& wpr.target_component == mavlink_wpm_comp_id*/) && !(msg->sysid == wpm->current_partner_sysid && msg->compid == wpm->current_partner_compid)) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("REJ. WP CMD: Busy"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM_REQUEST from ID %u because i'm already talking to ID %u.\n", msg->sysid, wpm->current_partner_sysid); + +#endif + + } else { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("REJ. WP CMD: target id mismatch"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("IGNORED WAYPOINT COMMAND BECAUSE TARGET SYSTEM AND COMPONENT OR COMM PARTNER ID MISMATCH\n"); + +#endif + } + + } + + break; + } + + case MAVLINK_MSG_ID_MISSION_COUNT: { + mavlink_mission_count_t wpc; + mavlink_msg_mission_count_decode(msg, &wpc); + + if (wpc.target_system == mavlink_system.sysid/* && wpc.target_component == mavlink_wpm_comp_id*/) { + wpm->timestamp_lastaction = now; + + if (wpm->current_state == MAVLINK_WPM_STATE_IDLE || (wpm->current_state == MAVLINK_WPM_STATE_GETLIST && wpm->current_wp_id == 0)) { +// printf("wpc count in: %d\n",wpc.count); +// printf("Comp id: %d\n",msg->compid); +// printf("Current partner sysid: %d\n",wpm->current_partner_sysid); + + if (wpc.count > 0) { + if (wpm->current_state == MAVLINK_WPM_STATE_IDLE) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("WP CMD OK: state -> GETLIST"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Got MAVLINK_MSG_ID_MISSION_ITEM_COUNT (%u) from %u changing state to MAVLINK_WPM_STATE_GETLIST\n", wpc.count, msg->sysid); + +#endif + } + + if (wpm->current_state == MAVLINK_WPM_STATE_GETLIST) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("WP CMD OK AGAIN"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Got MAVLINK_MSG_ID_MISSION_ITEM_COUNT (%u) again from %u\n", wpc.count, msg->sysid); + +#endif + } + + wpm->current_state = MAVLINK_WPM_STATE_GETLIST; + wpm->current_wp_id = 0; + wpm->current_partner_sysid = msg->sysid; + wpm->current_partner_compid = msg->compid; + wpm->current_count = wpc.count; + +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("CLR RCV BUF: READY"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("clearing receive buffer and readying for receiving waypoints\n"); + +#endif + wpm->rcv_size = 0; + //while(waypoints_receive_buffer->size() > 0) +// { +// delete waypoints_receive_buffer->back(); +// waypoints_receive_buffer->pop_back(); +// } + + mavlink_wpm_send_waypoint_request(wpm->current_partner_sysid, wpm->current_partner_compid, wpm->current_wp_id); + + } else if (wpc.count == 0) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("COUNT 0"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("got waypoint count of 0, clearing waypoint list and staying in state MAVLINK_WPM_STATE_IDLE\n"); + +#endif + wpm->rcv_size = 0; + //while(waypoints_receive_buffer->size() > 0) +// { +// delete waypoints->back(); +// waypoints->pop_back(); +// } + wpm->current_active_wp_id = -1; + wpm->yaw_reached = false; + wpm->pos_reached = false; + break; + + } else { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("IGN WP CMD"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Ignoring MAVLINK_MSG_ID_MISSION_ITEM_COUNT from %u with count of %u\n", msg->sysid, wpc.count); + +#endif + } + + } else { + if (!(wpm->current_state == MAVLINK_WPM_STATE_IDLE || wpm->current_state == MAVLINK_WPM_STATE_GETLIST)) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("REJ. WP CMD: Busy"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM_COUNT because i'm doing something else already (state=%i).\n", wpm->current_state); + +#endif + + } else if (wpm->current_state == MAVLINK_WPM_STATE_GETLIST && wpm->current_wp_id != 0) { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("REJ. WP CMD: Busy"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM_COUNT because i'm already receiving waypoint %u.\n", wpm->current_wp_id); + +#endif + + } else { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("REJ. WP CMD: ?"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM_COUNT - FIXME: missed error description\n"); + +#endif + } + } + + } else { +#ifdef MAVLINK_WPM_NO_PRINTF + mavlink_missionlib_send_gcs_string("REJ. WP CMD: target id mismatch"); +#else + + if (MAVLINK_WPM_VERBOSE) printf("IGNORED WAYPOINT COMMAND BECAUSE TARGET SYSTEM AND COMPONENT OR COMM PARTNER ID MISMATCH\n"); + +#endif + } + + } + break; + + case MAVLINK_MSG_ID_MISSION_ITEM: { + mavlink_mission_item_t wp; + mavlink_msg_mission_item_decode(msg, &wp); + + mavlink_missionlib_send_gcs_string("GOT WP"); +// printf("sysid=%d, current_partner_sysid=%d\n", msg->sysid, wpm->current_partner_sysid); +// printf("compid=%d, current_partner_compid=%d\n", msg->compid, wpm->current_partner_compid); + +// if((msg->sysid == wpm->current_partner_sysid && msg->compid == wpm->current_partner_compid) && (wp.target_system == mavlink_system.sysid /*&& wp.target_component == mavlink_wpm_comp_id*/)) + if (wp.target_system == mavlink_system.sysid && wp.target_component == mavlink_wpm_comp_id) { + + wpm->timestamp_lastaction = now; + +// printf("wpm->current_state=%u, wp.seq = %d, wpm->current_wp_id=%d\n", wpm->current_state, wp.seq, wpm->current_wp_id); + +// wpm->current_state = MAVLINK_WPM_STATE_GETLIST;//removeme debug XXX TODO + + //ensure that we are in the correct state and that the first waypoint has id 0 and the following waypoints have the correct ids + if ((wpm->current_state == MAVLINK_WPM_STATE_GETLIST && wp.seq == 0) || (wpm->current_state == MAVLINK_WPM_STATE_GETLIST_GETWPS && wp.seq == wpm->current_wp_id && wp.seq < wpm->current_count)) { + //mavlink_missionlib_send_gcs_string("DEBUG 2"); + +// if (verbose && wpm->current_state == MAVLINK_WPM_STATE_GETLIST) // printf("Got MAVLINK_MSG_ID_MISSION_ITEM %u from %u changing state to MAVLINK_WPM_STATE_GETLIST_GETWPS\n", wp.seq, msg->sysid); +// if (verbose && wpm->current_state == MAVLINK_WPM_STATE_GETLIST_GETWPS && wp.seq == wpm->current_wp_id) // printf("Got MAVLINK_MSG_ID_MISSION_ITEM %u from %u\n", wp.seq, msg->sysid); +// if (verbose && wpm->current_state == MAVLINK_WPM_STATE_GETLIST_GETWPS && wp.seq-1 == wpm->current_wp_id) // printf("Got MAVLINK_MSG_ID_MISSION_ITEM %u (again) from %u\n", wp.seq, msg->sysid); +// + wpm->current_state = MAVLINK_WPM_STATE_GETLIST_GETWPS; + mavlink_mission_item_t *newwp = &(wpm->rcv_waypoints[wp.seq]); + memcpy(newwp, &wp, sizeof(mavlink_mission_item_t)); +// printf("WP seq: %d\n",wp.seq); + wpm->current_wp_id = wp.seq + 1; + + // if (verbose) // printf ("Added new waypoint to list. X= %f\t Y= %f\t Z= %f\t Yaw= %f\n", newwp->x, newwp->y, newwp->z, newwp->param4); +// printf ("Added new waypoint to list. X= %f\t Y= %f\t Z= %f\t Yaw= %f\n", newwp->x, newwp->y, newwp->z, newwp->param4); + +// printf ("wpm->current_wp_id =%d, wpm->current_count=%d\n\n", wpm->current_wp_id, wpm->current_count); + if (wpm->current_wp_id == wpm->current_count && wpm->current_state == MAVLINK_WPM_STATE_GETLIST_GETWPS) { + mavlink_missionlib_send_gcs_string("GOT ALL WPS"); + // if (verbose) // printf("Got all %u waypoints, changing state to MAVLINK_WPM_STATE_IDLE\n", wpm->current_count); + + mavlink_wpm_send_waypoint_ack(wpm->current_partner_sysid, wpm->current_partner_compid, 0); + + if (wpm->current_active_wp_id > wpm->rcv_size - 1) { + wpm->current_active_wp_id = wpm->rcv_size - 1; + } + + // switch the waypoints list + // FIXME CHECK!!! + uint32_t i; + + for (i = 0; i < wpm->current_count; ++i) { + wpm->waypoints[i] = wpm->rcv_waypoints[i]; + } + + wpm->size = wpm->current_count; + + //get the new current waypoint + + for (i = 0; i < wpm->size; i++) { + if (wpm->waypoints[i].current == 1) { + wpm->current_active_wp_id = i; + //// if (verbose) // printf("New current waypoint %u\n", current_active_wp_id); + wpm->yaw_reached = false; + wpm->pos_reached = false; + mavlink_wpm_send_waypoint_current(wpm->current_active_wp_id); + mavlink_wpm_send_setpoint(wpm->current_active_wp_id); + wpm->timestamp_firstinside_orbit = 0; + break; + } + } + + if (i == wpm->size) { + wpm->current_active_wp_id = -1; + wpm->yaw_reached = false; + wpm->pos_reached = false; + wpm->timestamp_firstinside_orbit = 0; + } + + wpm->current_state = MAVLINK_WPM_STATE_IDLE; + + } else { + mavlink_wpm_send_waypoint_request(wpm->current_partner_sysid, wpm->current_partner_compid, wpm->current_wp_id); + } + + } else { + if (wpm->current_state == MAVLINK_WPM_STATE_IDLE) { + //we're done receiving waypoints, answer with ack. + mavlink_wpm_send_waypoint_ack(wpm->current_partner_sysid, wpm->current_partner_compid, 0); + printf("Received MAVLINK_MSG_ID_MISSION_ITEM while state=MAVLINK_WPM_STATE_IDLE, answered with WAYPOINT_ACK.\n"); + } + + // if (verbose) + { + if (!(wpm->current_state == MAVLINK_WPM_STATE_GETLIST || wpm->current_state == MAVLINK_WPM_STATE_GETLIST_GETWPS)) { +// printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM %u because i'm doing something else already (state=%i).\n", wp.seq, wpm->current_state); + break; + + } else if (wpm->current_state == MAVLINK_WPM_STATE_GETLIST) { + if (!(wp.seq == 0)) { +// printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM because the first waypoint ID (%u) was not 0.\n", wp.seq); + } else { +// printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM %u - FIXME: missed error description\n", wp.seq); + } + } else if (wpm->current_state == MAVLINK_WPM_STATE_GETLIST_GETWPS) { + if (!(wp.seq == wpm->current_wp_id)) { +// printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM because the waypoint ID (%u) was not the expected %u.\n", wp.seq, wpm->current_wp_id); + mavlink_wpm_send_waypoint_request(wpm->current_partner_sysid, wpm->current_partner_compid, wpm->current_wp_id); + + } else if (!(wp.seq < wpm->current_count)) { +// printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM because the waypoint ID (%u) was out of bounds.\n", wp.seq); + } else { +// printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM %u - FIXME: missed error description\n", wp.seq); + } + } else { +// printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM %u - FIXME: missed error description\n", wp.seq); + } + } + } + } else { + //we we're target but already communicating with someone else + if ((wp.target_system == mavlink_system.sysid /*&& wp.target_component == mavlink_wpm_comp_id*/) && !(msg->sysid == wpm->current_partner_sysid && msg->compid == wpm->current_partner_compid) && wpm->current_state != MAVLINK_WPM_STATE_IDLE) { + // if (verbose) // printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM %u from ID %u because i'm already talking to ID %u.\n", wp.seq, msg->sysid, wpm->current_partner_sysid); + } else if (wp.target_system == mavlink_system.sysid /* && wp.target_component == mavlink_wpm_comp_id*/) { + // if (verbose) // printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM %u from ID %u because i have no idea what to do with it\n", wp.seq, msg->sysid); + } + } + + break; + } + + case MAVLINK_MSG_ID_MISSION_CLEAR_ALL: { + mavlink_mission_clear_all_t wpca; + mavlink_msg_mission_clear_all_decode(msg, &wpca); + + if (wpca.target_system == mavlink_system.sysid /*&& wpca.target_component == mavlink_wpm_comp_id */ && wpm->current_state == MAVLINK_WPM_STATE_IDLE) { + wpm->timestamp_lastaction = now; + + // if (verbose) // printf("Got MAVLINK_MSG_ID_MISSION_ITEM_CLEAR_LIST from %u deleting all waypoints\n", msg->sysid); + // Delete all waypoints + wpm->size = 0; + wpm->current_active_wp_id = -1; + wpm->yaw_reached = false; + wpm->pos_reached = false; + + } else if (wpca.target_system == mavlink_system.sysid /*&& wpca.target_component == mavlink_wpm_comp_id */ && wpm->current_state != MAVLINK_WPM_STATE_IDLE) { + // if (verbose) // printf("Ignored MAVLINK_MSG_ID_MISSION_ITEM_CLEAR_LIST from %u because i'm doing something else already (state=%i).\n", msg->sysid, wpm->current_state); + } + + break; + } + + default: { + // if (debug) // printf("Waypoint: received message of unknown type"); + break; + } + } + + check_waypoints_reached(now, global_pos, local_pos); +} diff --git a/apps/mavlink/waypoints.h b/apps/mavlink/waypoints.h new file mode 100644 index 0000000000..6011b16b21 --- /dev/null +++ b/apps/mavlink/waypoints.h @@ -0,0 +1,128 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: @author Lorenz Meier + * @author Thomas Gubler + * @author Julian Oes + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file waypoints.h + * MAVLink waypoint protocol definition (BSD-relicensed). + */ + +#ifndef WAYPOINTS_H_ +#define WAYPOINTS_H_ + +/* This assumes you have the mavlink headers on your include path + or in the same folder as this source file */ + +#include +extern void mavlink_send_uart_bytes(mavlink_channel_t chan, uint8_t *buffer, uint16_t len); + +#ifndef MAVLINK_SEND_UART_BYTES +#define MAVLINK_SEND_UART_BYTES(chan, buffer, len) mavlink_send_uart_bytes(chan, buffer, len) +#endif +extern mavlink_system_t mavlink_system; +#include +#include +#include +#include + +// FIXME XXX - TO BE MOVED TO XML +enum MAVLINK_WPM_STATES { + MAVLINK_WPM_STATE_IDLE = 0, + MAVLINK_WPM_STATE_SENDLIST, + MAVLINK_WPM_STATE_SENDLIST_SENDWPS, + MAVLINK_WPM_STATE_GETLIST, + MAVLINK_WPM_STATE_GETLIST_GETWPS, + MAVLINK_WPM_STATE_GETLIST_GOTALL, + MAVLINK_WPM_STATE_ENUM_END +}; + +enum MAVLINK_WPM_CODES { + MAVLINK_WPM_CODE_OK = 0, + MAVLINK_WPM_CODE_ERR_WAYPOINT_ACTION_NOT_SUPPORTED, + MAVLINK_WPM_CODE_ERR_WAYPOINT_FRAME_NOT_SUPPORTED, + MAVLINK_WPM_CODE_ERR_WAYPOINT_OUT_OF_BOUNDS, + MAVLINK_WPM_CODE_ERR_WAYPOINT_MAX_NUMBER_EXCEEDED, + MAVLINK_WPM_CODE_ENUM_END +}; + + +/* WAYPOINT MANAGER - MISSION LIB */ + +#define MAVLINK_WPM_MAX_WP_COUNT 15 +#define MAVLINK_WPM_CONFIG_IN_FLIGHT_UPDATE ///< Enable double buffer and in-flight updates +#ifndef MAVLINK_WPM_TEXT_FEEDBACK +#define MAVLINK_WPM_TEXT_FEEDBACK 0 ///< Report back status information as text +#endif +#define MAVLINK_WPM_PROTOCOL_TIMEOUT_DEFAULT 5000000 ///< Protocol communication timeout in useconds +#define MAVLINK_WPM_SETPOINT_DELAY_DEFAULT 1000000 ///< When to send a new setpoint +#define MAVLINK_WPM_PROTOCOL_DELAY_DEFAULT 40000 + + +struct mavlink_wpm_storage { + mavlink_mission_item_t waypoints[MAVLINK_WPM_MAX_WP_COUNT]; ///< Currently active waypoints +#ifdef MAVLINK_WPM_CONFIG_IN_FLIGHT_UPDATE + mavlink_mission_item_t rcv_waypoints[MAVLINK_WPM_MAX_WP_COUNT]; ///< Receive buffer for next waypoints +#endif + uint16_t size; + uint16_t max_size; + uint16_t rcv_size; + enum MAVLINK_WPM_STATES current_state; + uint16_t current_wp_id; ///< Waypoint in current transmission + uint16_t current_active_wp_id; ///< Waypoint the system is currently heading towards + uint16_t current_count; + uint8_t current_partner_sysid; + uint8_t current_partner_compid; + uint64_t timestamp_lastaction; + uint64_t timestamp_last_send_setpoint; + uint64_t timestamp_firstinside_orbit; + uint64_t timestamp_lastoutside_orbit; + uint32_t timeout; + uint32_t delay_setpoint; + float accept_range_yaw; + float accept_range_distance; + bool yaw_reached; + bool pos_reached; + bool idle; +}; + +typedef struct mavlink_wpm_storage mavlink_wpm_storage; + +void mavlink_wpm_init(mavlink_wpm_storage *state); +int mavlink_waypoint_eventloop(uint64_t now, const struct vehicle_global_position_s *global_position, + struct vehicle_local_position_s *local_pos); +void mavlink_wpm_message_handler(const mavlink_message_t *msg, const struct vehicle_global_position_s *global_pos , + struct vehicle_local_position_s *local_pos); + +#endif /* WAYPOINTS_H_ */ diff --git a/apps/mix_and_link/Makefile b/apps/mix_and_link/Makefile new file mode 100644 index 0000000000..a907277c79 --- /dev/null +++ b/apps/mix_and_link/Makefile @@ -0,0 +1,38 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Makefile to build the mix-and-link functions +# + +include $(APPDIR)/mk/app.mk diff --git a/apps/mix_and_link/mix_and_link.c b/apps/mix_and_link/mix_and_link.c new file mode 100644 index 0000000000..495f336b19 --- /dev/null +++ b/apps/mix_and_link/mix_and_link.c @@ -0,0 +1,81 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: Nils Wenzler + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * @file Mixing / linking of RC channels + */ + +#include +#include +#include + +#include "mix_and_link.h" + +/* + * Library function that mixes the abstract functions like ROLL, PITCH, THROTTLE + * to one or several actuators. + * @param *mixers is a pointer to the configuration struct, declared in mix_and_link.h + * @param nr_mixers is a integer that denotes the number of mixers that should be processed + * @param nr_actuators is a integer that denotes the max number of actuators that get linked to one source + * @param *data is a pointer to the mixer data struct, declared in mix_and_link.h + */ +void mix_and_link(const mixer_conf_t *mixers, uint8_t nr_mixers, uint8_t nr_actuators, mixer_data_t *data) +{ + + /* Reset the Output Array */ + uint8_t i, j; + + for (i = 0; i < nr_actuators; i++) { + data->output[i] = 0; + } + + /* Loop throug the given mixers */ + for (i = 0; i < nr_mixers; i++) { + + /* The actual mixing */ + for (j = 0; j < mixers[i].nr_actuators; j++) { + data->output[mixers[i].dest[j]] += (int16_t)(data->input[mixers[i].source] + * mixers[i].dual_rate[j]); + + /* Saturate to +-10000 */ + if (data->output[mixers[i].dest[j]] > 10000) + data->output[mixers[i].dest[j]] = 10000; + else if (data->output[mixers[i].dest[j]] < -10000) + data->output[mixers[i].dest[j]] = -10000; + + } + } +} + + diff --git a/apps/mix_and_link/mix_and_link.h b/apps/mix_and_link/mix_and_link.h new file mode 100644 index 0000000000..0a374fd855 --- /dev/null +++ b/apps/mix_and_link/mix_and_link.h @@ -0,0 +1,115 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: Nils Wenzler + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + + +#ifndef _MIX_AND_LINK_H_ +#define _MIX_AND_LINK_H_ + +#include +#include +#include + +/**< The maximum number of actuators that get linked to one abstract function*/ +#define NR_MAX_ACTUATORS 2 + +/** + * The struct mixer_conf_t contains all the necessary information for one mixer. + * Make an array of type mixer_conf_t for several mix functions. + */ +typedef struct { + uint8_t source; /**< source RC channel index 0..n */ + uint8_t nr_actuators; /**< number of actuators to output to */ + uint8_t dest[NR_MAX_ACTUATORS]; /**< Which actuators to output to */ + float dual_rate[NR_MAX_ACTUATORS]; /**< Direction and rate of mixing. Range [-1,1] */ +} mixer_conf_t; /**< Setup for one mixer */ + +/* + * The struct mixer_data contains two int16_t arrays with the abstract source functions + * (Throttle, Roll,...) in the input, and an empty array output of the desired + * size for the results. + */ +typedef struct { + int16_t *input; + int16_t *output; +} mixer_data_t; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* + * Mixes the functions to the actuators. + * e.g. Throttle, Roll,... + * + * Each mixer_conf struct in the mixers array contains the source function (ex. THROTTLE), the number + * of actuators, an array with the desired actuators, Dual Rate determines which + * percentage of the source gets mixed to the destination and sets the direction. + * It's range is between -1 and 1. + * + * EXAMPLE: Deltamix for a wing plane: + * + * mixer_data_t mixer_buffer; + * mixer_buffer.input = buffer_rc; + * mixer_buffer.output = buffer_servo; + * + * + * mixer_conf_t mixers[3]; + * + * mixers[0].source = PITCH; + * mixers[0].nr_actuators = 2; + * mixers[0].dest[0] = AIL_1; + * mixers[0].dest[1] = AIL_2; + * mixers[0].dual_rate[0] = 1; + * mixers[0].dual_rate[1] = 1; + * + * mixers[1].source = ROLL; + * mixers[1].nr_actuators = 2; + * mixers[1].dest[0] = AIL_1; + * mixers[1].dest[1] = AIL_2; + * mixers[1].dual_rate[0] = 1; + * mixers[1].dual_rate[0] = -1; + * + * mixers[2].source = THROTTLE; + * mixers[2].nr_actuators = 1; + * mixers[2].dest[0] = MOT; + * mixers[2].dual_rate[0] = 1; + * + * @param mixers pointer to the mixer struct array + * @param nr_mixers number of mixers in struct array + * @param nr_actuators number of actuators + * @param data pointer to the mixer_data struct. + */ +void mix_and_link(const mixer_conf_t *mixers, uint8_t nr_mixers, uint8_t nr_actuators, mixer_data_t *data); + +#endif diff --git a/apps/mk/app.mk b/apps/mk/app.mk new file mode 100644 index 0000000000..3948ef354f --- /dev/null +++ b/apps/mk/app.mk @@ -0,0 +1,223 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Common Makefile for nsh command modules and utility libraries; should be +# included by the module-specific Makefile. +# +# To build an app that appears as an nsh external command, the caller +# must define: +# +# APPNAME - the name of the application, defaults to the name +# of the parent directory. +# +# If APPNAME is not defined, a utility library is built instead. The library +# name is normally automatically determined, but it can be overridden by +# setting: +# +# LIBNAME - the name of the library, defaults to the name of the +# directory +# +# The calling makefile may also set: +# +# ASRCS - list of assembly source files, defaults to all .S +# files in the directory +# +# CSRCS - list of C source files, defaults to all .c files +# in the directory +# +# CXXSRCS - list of C++ source files, defaults to all .cpp +# files in the directory +# +# INCLUDES - list of directories to be added to the include +# search path +# +# PRIORITY - thread priority for the command (defaults to +# SCHED_PRIORITY_DEFAULT) +# +# STACKSIZE - stack size for the command (defaults to +# CONFIG_PTHREAD_STACK_DEFAULT) +# +# Symbols in the module are private to the module unless deliberately exported +# using the __EXPORT tag. +# + +############################################################################ +# No user-serviceable parts below +############################################################################ + + +############################################################################ +# Work out who included us so we can report decent errors +# +THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) +PARENT_MAKEFILE := $(lastword $(filter-out $(THIS_MAKEFILE),$(MAKEFILE_LIST))) + +############################################################################ +# Get configuration +# +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +############################################################################ +# Sanity-check the information we've been given and set any defaults +# +SRCDIR ?= $(dir $(PARENT_MAKEFILE)) +PRIORITY ?= SCHED_PRIORITY_DEFAULT +STACKSIZE ?= CONFIG_PTHREAD_STACK_DEFAULT + +INCLUDES += $(APPDIR) + +ASRCS ?= $(wildcard $(SRCDIR)/*.S) +CSRCS ?= $(wildcard $(SRCDIR)/*.c) +CXXSRCS ?= $(wildcard $(SRCDIR)/*.cpp) + +# if APPNAME is not set, this is a library +ifeq ($(APPNAME),) +LIBNAME ?= $(lastword $(subst /, ,$(realpath $(SRCDIR)))) +endif + +# there has to be a source file +ifeq ($(ASRCS)$(CSRCS)$(CXXSRCS),) +$(error $(realpath $(PARENT_MAKEFILE)): at least one of ASRCS, CSRCS or CXXSRCS must be set) +endif + +# check that C++ is configured if we have C++ source files and we are building +ifneq ($(CXXSRCS),) +ifneq ($(CONFIG_HAVE_CXX),y) +ifeq ($(MAKECMDGOALS),build) +$(error $(realpath $(PARENT_MAKEFILE)): cannot set CXXSRCS if CONFIG_HAVE_CXX not set in configuration) +endif +endif +endif + +############################################################################ +# Adjust compilation flags to implement EXPORT +# +CFLAGS += -fvisibility=hidden -include $(APPDIR)/systemlib/visibility.h +CXXFLAGS += -fvisibility=hidden -include $(APPDIR)/systemlib/visibility.h + +############################################################################ +# Add extra include directories +# +CFLAGS += $(addprefix -I,$(INCLUDES)) +CXXFLAGS += $(addprefix -I,$(INCLUDES)) + +############################################################################ +# Things we are going to build +# + +SRCS = $(ASRCS) $(CSRCS) $(CXXSRCS) +AOBJS = $(patsubst %.S,%.o,$(ASRCS)) +COBJS = $(patsubst %.c,%.o,$(CSRCS)) +CXXOBJS = $(patsubst %.cpp,%.o,$(CXXSRCS)) +OBJS = $(AOBJS) $(COBJS) $(CXXOBJS) + +# The prelinked object that we are ultimately going to build +ifneq ($(APPNAME),) +PRELINKOBJ = $(APPNAME).pre.o +else +PRELINKOBJ = $(LIBNAME).pre.o +endif + +# The archive that the object file will be placed in +# XXX does WINTOOL ever get set? +ifeq ($(WINTOOL),y) + INCDIROPT = -w + BIN = "$(shell cygpath -w $(APPDIR)/libapps$(LIBEXT))" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +############################################################################ +# Rules for building things +# + +all: .built +.PHONY: clean depend distclean + +# +# Top-level build; add prelinked object to the apps archive +# +.built: $(PRELINKOBJ) + @$(call ARCHIVE, $(BIN), $(PRELINKOBJ)) + @touch $@ + +# +# Source dependencies +# +depend: .depend +.depend: $(MAKEFILE_LIST) $(SRCS) + @$(MKDEP) --dep-path . $(CC) -- $(CFLAGS) -- $(CSRCS) >Make.dep + @$(MKDEP) --dep-path . $(CXX) -- $(CXXFLAGS) -- $(CXXSRCS) >>Make.dep + @touch $@ + +ifneq ($(APPNAME),) +# +# App registration +# +context: .context +.context: $(MAKEFILE_LIST) + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ +else +context: +endif + +# +# Object files +# +$(PRELINKOBJ): $(OBJS) + $(call PRELINK, $@, $(OBJS)) + +$(AOBJS): %.o : %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %.o : %.c + $(call COMPILE, $<, $@) + +$(CXXOBJS): %.o : %.cpp + $(call COMPILEXX, $<, $@) + +# +# Tidying up +# +clean: + @rm -f $(OBJS) $(PRELINKOBJ) Make.dep .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/namedapp/Kconfig b/apps/namedapp/Kconfig new file mode 100644 index 0000000000..8d8f03421b --- /dev/null +++ b/apps/namedapp/Kconfig @@ -0,0 +1,15 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config NAMEDAPP + bool "Support named applications" + default n + ---help--- + Enable support for named applications. This features assigns a string + name to an application. This feature is also the underlying requirement + to support built-in applications in the NuttShell (NSH). + +if NAMEDAPP +endif diff --git a/apps/namedapp/Make.defs b/apps/namedapp/Make.defs new file mode 100644 index 0000000000..a07b3b3c2a --- /dev/null +++ b/apps/namedapp/Make.defs @@ -0,0 +1,40 @@ +############################################################################ +# apps/namedapps/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +if ($(CONFIG_NAMEDAPP),y) +CONFIGURED_APPS += namedapp +endif + diff --git a/apps/namedapp/Makefile b/apps/namedapp/Makefile new file mode 100644 index 0000000000..fba8fb1ff9 --- /dev/null +++ b/apps/namedapp/Makefile @@ -0,0 +1,106 @@ +############################################################################ +# apps/nshlib/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# NSH Library + +# Source and object files + +ASRCS = +CSRCS = namedapp.c exec_namedapp.c + +ifeq ($(CONFIG_APPS_BINDIR),y) +CSRCS += binfs.c +endif + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . +VPATH = + +# Build Targets + +all: .built +.PHONY: .context context depend clean distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: + @echo "/* List of application requirements, generated during make context. */" > namedapp_list.h + @echo "/* List of application entry points, generated during make context. */" > namedapp_proto.h + @touch $@ + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f .context Make.dep .depend + @rm -f namedapp_list.h + @rm -f namedapp_proto.h + +-include Make.dep + diff --git a/apps/namedapp/binfs.c b/apps/namedapp/binfs.c new file mode 100644 index 0000000000..36e3ace92e --- /dev/null +++ b/apps/namedapp/binfs.c @@ -0,0 +1,596 @@ +/**************************************************************************** + * apps/namedapps/binfs.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "namedapp.h" + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_APPS_BINDIR) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure represents the overall mountpoint state. An instance of this + * structure is retained as inode private data on each mountpoint that is + * mounted with a fat32 filesystem. + */ + +struct binfs_state_s +{ + sem_t bm_sem; /* Used to assume thread-safe access */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void binfs_semtake(struct binfs_state_s *bm); +static inline void binfs_semgive(struct binfs_state_s *bm); +static int binfs_open(FAR struct file *filep, const char *relpath, + int oflags, mode_t mode); +static int binfs_close(FAR struct file *filep); +static ssize_t binfs_read(FAR struct file *filep, char *buffer, size_t buflen); +static int binfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg); + +static int binfs_opendir(struct inode *mountpt, const char *relpath, + struct fs_dirent_s *dir); +static int binfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir); +static int binfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir); + +static int binfs_bind(FAR struct inode *blkdriver, const void *data, + void **handle); +static int binfs_unbind(void *handle, FAR struct inode **blkdriver); +static int binfs_statfs(struct inode *mountpt, struct statfs *buf); + +static int binfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf); + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* See fs_mount.c -- this structure is explicitly externed there. + * We use the old-fashioned kind of initializers so that this will compile + * with any compiler. + */ + +const struct mountpt_operations binfs_operations = +{ + binfs_open, /* open */ + binfs_close, /* close */ + binfs_read, /* read */ + NULL, /* write */ + NULL, /* seek */ + binfs_ioctl, /* ioctl */ + NULL, /* sync */ + + binfs_opendir, /* opendir */ + NULL, /* closedir */ + binfs_readdir, /* readdir */ + binfs_rewinddir, /* rewinddir */ + + binfs_bind, /* bind */ + binfs_unbind, /* unbind */ + binfs_statfs, /* statfs */ + + NULL, /* unlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* rename */ + binfs_stat /* stat */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: binfs_semtake + ****************************************************************************/ + +static void binfs_semtake(struct binfs_state_s *bm) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&bm->bm_sem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Name: binfs_semgive + ****************************************************************************/ + +static inline void binfs_semgive(struct binfs_state_s *bm) +{ + sem_post(&bm->bm_sem); +} + +/**************************************************************************** + * Name: binfs_open + ****************************************************************************/ + +static int binfs_open(FAR struct file *filep, const char *relpath, + int oflags, mode_t mode) +{ + struct binfs_state_s *bm; + int ret = -ENOSYS; + + fvdbg("Open '%s'\n", relpath); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL); + + /* mountpoint private data from the inode reference from the file + * structure + */ + + bm = (struct binfs_state_s*)filep->f_inode->i_private; + DEBUGASSERT(bm != NULL); + + /* BINFS is read-only. Any attempt to open with any kind of write + * access is not permitted. + */ + + if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0) + { + fdbg("Only O_RDONLY supported\n"); + ret = -EACCES; + } + + /* Save open-specific state in filep->f_priv */ + + /* Opening of elements within the pseudo-file system is not yet supported */ + + return ret; +} + +/**************************************************************************** + * Name: binfs_close + ****************************************************************************/ + +static int binfs_close(FAR struct file *filep) +{ + struct binfs_state_s *bm; + int ret = -ENOSYS; + + fvdbg("Closing\n"); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover the open file state from the struct file instance */ + /* bf = filep->f_priv; */ + + /* Recover the file system state from the inode */ + + bm = filep->f_inode->i_private; + DEBUGASSERT(bm != NULL); + + /* Free the open file state */ + /* free(bf); */ + + filep->f_priv = NULL; + + /* Since open() is not yet supported, neither is close(). */ + + return ret; +} + +/**************************************************************************** + * Name: binfs_read + ****************************************************************************/ + +static ssize_t binfs_read(FAR struct file *filep, char *buffer, size_t buflen) +{ + struct binfs_state_s *bm; + + fvdbg("Read %d bytes from offset %d\n", buflen, filep->f_pos); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover the open file state data from the struct file instance */ + /* bf = filep->f_priv; */ + + /* Recover the file system state from the inode */ + + bm = filep->f_inode->i_private; + DEBUGASSERT(bm != NULL); + + /* Since open is not yet supported, neither is reading */ + + return -ENOSYS; +} + +/**************************************************************************** + * Name: binfs_ioctl + ****************************************************************************/ + +static int binfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + struct binfs_state_s *bm; + + fvdbg("cmd: %d arg: %08lx\n", cmd, arg); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover the open file state from the struct file instance */ + /* bf = filep->f_priv; */ + + /* Recover the file system state from the inode */ + + bm = filep->f_inode->i_private; + DEBUGASSERT(bm != NULL); + + /* No ioctl commands yet supported */ + + return -ENOTTY; +} + +/**************************************************************************** + * Name: binfs_opendir + * + * Description: + * Open a directory for read access + * + ****************************************************************************/ + +static int binfs_opendir(struct inode *mountpt, const char *relpath, + struct fs_dirent_s *dir) +{ + struct binfs_state_s *bm; + int ret; + + fvdbg("relpath: \"%s\"\n", relpath ? relpath : "NULL"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover the file system state from the inode instance */ + + bm = mountpt->i_private; + binfs_semtake(bm); + + /* The requested directory must be the volume-relative "root" directory */ + + if (relpath && relpath[0] != '\0') + { + ret = -ENOENT; + goto errout_with_semaphore; + } + + /* Set the index to the first entry */ + + dir->u.binfs.fb_index = 0; + ret = OK; + +errout_with_semaphore: + binfs_semgive(bm); + return ret; +} + +/**************************************************************************** + * Name: binfs_readdir + * + * Description: Read the next directory entry + * + ****************************************************************************/ + +static int binfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) +{ + struct binfs_state_s *bm; + unsigned int index; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover the file system state from the inode instance */ + + bm = mountpt->i_private; + binfs_semtake(bm); + + /* Have we reached the end of the directory */ + + index = dir->u.binfs.fb_index; + if (namedapps[index].name == NULL) + { + /* We signal the end of the directory by returning the + * special error -ENOENT + */ + + fvdbg("Entry %d: End of directory\n", index); + ret = -ENOENT; + } + else + { + /* Save the filename and file type */ + + fvdbg("Entry %d: \"%s\"\n", index, namedapps[index].name); + dir->fd_dir.d_type = DTYPE_FILE; + strncpy(dir->fd_dir.d_name, namedapps[index].name, NAME_MAX+1); + + /* The application list is terminated by an entry with a NULL name. + * Therefore, there is at least one more entry in the list. + */ + + index++; + + /* Set up the next directory entry offset. NOTE that we could use the + * standard f_pos instead of our own private fb_index. + */ + + dir->u.binfs.fb_index = index; + ret = OK; + } + + binfs_semgive(bm); + return ret; +} + +/**************************************************************************** + * Name: binfs_rewindir + * + * Description: Reset directory read to the first entry + * + ****************************************************************************/ + +static int binfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir) +{ + struct binfs_state_s *bm; + + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover the file system state from the inode instance */ + + bm = mountpt->i_private; + binfs_semtake(bm); + + dir->u.binfs.fb_index = 0; + + binfs_semgive(bm); + return OK; +} + +/**************************************************************************** + * Name: binfs_bind + * + * Description: This implements a portion of the mount operation. This + * function allocates and initializes the mountpoint private data and + * binds the blockdriver inode to the filesystem private data. The final + * binding of the private data (containing the blockdriver) to the + * mountpoint is performed by mount(). + * + ****************************************************************************/ + +static int binfs_bind(FAR struct inode *blkdriver, const void *data, + void **handle) +{ + struct binfs_state_s *bm; + + fvdbg("Entry\n"); + + /* Create an instance of the mountpt state structure */ + + bm = (struct binfs_state_s *)zalloc(sizeof(struct binfs_state_s)); + if (!bm) + { + fdbg("Failed to allocate mountpoint structure\n"); + return -ENOMEM; + } + + /* Initialize the allocated mountpt state structure. The filesystem is + * responsible for one reference ont the blkdriver inode and does not + * have to addref() here (but does have to release in ubind(). + */ + + sem_init(&bm->bm_sem, 0, 1); /* Initialize the semaphore that controls access */ + + /* Mounted! */ + + *handle = (void*)bm; + return OK; +} + +/**************************************************************************** + * Name: binfs_unbind + * + * Description: This implements the filesystem portion of the umount + * operation. + * + ****************************************************************************/ + +static int binfs_unbind(void *handle, FAR struct inode **blkdriver) +{ + struct binfs_state_s *bm = (struct binfs_state_s*)handle; + + fvdbg("Entry\n"); + +#ifdef CONFIG_DEBUG + if (!bm) + { + return -EINVAL; + } +#endif + + /* Check if there are sill any files opened on the filesystem. */ + + /* Release the mountpoint private data */ + + sem_destroy(&bm->bm_sem); + return OK; +} + +/**************************************************************************** + * Name: binfs_statfs + * + * Description: Return filesystem statistics + * + ****************************************************************************/ + +static int binfs_statfs(struct inode *mountpt, struct statfs *buf) +{ + struct binfs_state_s *bm; + + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + bm = mountpt->i_private; + binfs_semtake(bm); + + /* Fill in the statfs info */ + + memset(buf, 0, sizeof(struct statfs)); + buf->f_type = BINFS_MAGIC; + buf->f_bsize = 0; + buf->f_blocks = 0; + buf->f_bfree = 0; + buf->f_bavail = 0; + buf->f_namelen = NAME_MAX; + + binfs_semgive(bm); + return OK; +} + +/**************************************************************************** + * Name: binfs_stat + * + * Description: Return information about a file or directory + * + ****************************************************************************/ + +static int binfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf) +{ + struct binfs_state_s *bm; + int ret; + + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + bm = mountpt->i_private; + binfs_semtake(bm); + + /* The requested directory must be the volume-relative "root" directory */ + + if (relpath && relpath[0] != '\0') + { + /* Check if there is a file with this name. */ + + if (namedapp_isavail(relpath) < 0) + { + ret = -ENOENT; + goto errout_with_semaphore; + } + + /* It's a execute-only file name */ + + buf->st_mode = S_IFREG|S_IXOTH|S_IXGRP|S_IXUSR; + } + else + { + /* It's a read/execute-only directory name */ + + buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR|S_IXOTH|S_IXGRP|S_IXUSR; + } + + /* File/directory size, access block size */ + + buf->st_size = 0; + buf->st_blksize = 0; + buf->st_blocks = 0; + ret = OK; + +errout_with_semaphore: + binfs_semgive(bm); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_APPS_BINDIR */ + diff --git a/apps/namedapp/exec_namedapp.c b/apps/namedapp/exec_namedapp.c new file mode 100644 index 0000000000..264fca7b9e --- /dev/null +++ b/apps/namedapp/exec_namedapp.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * apps/namedaps/exec_namedapp.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * With updates, modifications, and general maintenance by: + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Auther: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include + +#include "namedapp.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: namedapp_getname + * + * Description: + * Return the name of the application at index in the table of named + * applications. + * + ****************************************************************************/ + +const char *namedapp_getname(int index) +{ + if (index < 0 || index >= number_namedapps()) + { + return NULL; + } + + return namedapps[index].name; +} + +/**************************************************************************** + * Name: namedapp_isavail + * + * Description: + * Return the index into the table of applications for the applicaiton with + * the name 'appname'. + * + ****************************************************************************/ + +int namedapp_isavail(FAR const char *appname) +{ + int i; + + for (i = 0; namedapps[i].name; i++) + { + if (!strcmp(namedapps[i].name, appname)) + { + return i; + } + } + + set_errno(ENOENT); + return ERROR; +} + +/**************************************************************************** + * Name: namedapp_isavail + * + * Description: + * Execute the application with name 'appname', providing the arguments + * in the argv[] array. + * + * Returned Value: + * On success, the task ID of the named application is returned. On + * failure, -1 (ERROR) is returned an the errno value is set appropriately. + * + ****************************************************************************/ + +int exec_namedapp(FAR const char *appname, FAR const char **argv) +{ + pid_t pid; + int index; + + /* Verify that an application with this name exists */ + + index = namedapp_isavail(appname); + if (index >= 0) + { + /* Disable pre-emption. This means that although we start the named + * application here, it will not actually run until pre-emption is + * re-enabled below. + */ + + sched_lock(); + + /* Start the named application task */ + + pid = TASK_CREATE(namedapps[index].name, namedapps[index].priority, + namedapps[index].stacksize, namedapps[index].main, + (argv) ? &argv[1] : (const char **)NULL); + + /* If robin robin scheduling is enabled, then set the scheduling policy + * of the new task to SCHED_RR before it has a chance to run. + */ + +#if CONFIG_RR_INTERVAL > 0 + if (pid > 0) + { + struct sched_param param; + + /* Pre-emption is disabled so the task creation and the + * following operation will be atomic. The priority of the + * new task cannot yet have changed from its initial value. + */ + + param.sched_priority = namedapps[index].priority; + sched_setscheduler(pid, SCHED_RR, ¶m); + } +#endif + /* Now let the named application run */ + + sched_unlock(); + + /* Return the task ID of the new task if the task was sucessfully + * started. Otherwise, pid will be ERROR (and the errno value will + * be set appropriately). + */ + + return pid; + } + + /* Return ERROR with errno set appropriately */ + + return ERROR; +} diff --git a/apps/namedapp/namedapp.c b/apps/namedapp/namedapp.c new file mode 100644 index 0000000000..a5c2bee0e2 --- /dev/null +++ b/apps/namedapp/namedapp.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * apps/namedaps/namedapp.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Authors: Uros Platise + * Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#include "namedapp_proto.h" + +const struct namedapp_s namedapps[] = +{ +# include "namedapp_list.h" + { NULL, 0, 0, 0 } +}; + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int number_namedapps(void) +{ + return sizeof(namedapps)/sizeof(struct namedapp_s) - 1; +} + + diff --git a/apps/namedapp/namedapp.h b/apps/namedapp/namedapp.h new file mode 100644 index 0000000000..7fcdf42dc2 --- /dev/null +++ b/apps/namedapp/namedapp.h @@ -0,0 +1,78 @@ +/**************************************************************************** + * apps/namedaps/namedapp.h + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Authors: Uros Platise + * Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_NAMEDAPP_NAMEDAPP_H +#define __APPS_NAMEDAPP_NAMEDAPP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN const struct namedapp_s namedapps[]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +EXTERN int number_namedapps(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __APPS_NAMEDAPP_NAMEDAPP_H */ + diff --git a/apps/nshlib/Kconfig b/apps/nshlib/Kconfig new file mode 100644 index 0000000000..7e419bdde4 --- /dev/null +++ b/apps/nshlib/Kconfig @@ -0,0 +1,484 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config NSH_LIBRARY + bool "NSH Library" + default n + ---help--- + Build the NSH support library. This is used, for example, by examples/nsh + in order to implement the full NuttShell (NSH). + +if NSH_LIBRARY +config NSH_BUILTIN_APPS + bool "Enable built-in applications" + default y + depends on NAMEDAPP + ---help--- + Support external registered, "named" applications that can be + executed from the NSH command line (see apps/README.txt for + more information). This options requires support for named applications + (NAMEDAPP). + +menu "Disable Individual commands" +config NSH_DISABLE_CAT + bool "Disable cat" + default n +config NSH_DISABLE_CD + bool "Disable cd" + default n +config NSH_DISABLE_CP + bool "Disable cp" + default n +config NSH_DISABLE_DD + bool "Disable dd" + default n +config NSH_DISABLE_ECHO + bool "Disable echo" + default n +config NSH_DISABLE_EXEC + bool "Disable exec" + default n +config NSH_DISABLE_EXIT + bool "Disable exit" + default n +config NSH_DISABLE_FREE + bool "Disable free" + default n +config NSH_DISABLE_GET + bool "Disable get" + default n +config NSH_DISABLE_HELP + bool "Disable help" + default n +config NSH_DISABLE_IFCONFIG + bool "Disable ifconfig" + default n +config NSH_DISABLE_KILL + bool "Disable kill" + default n +config NSH_DISABLE_LOSETUP + bool "Disable losetup" + default n +config NSH_DISABLE_LS + bool "Disable ls" + default n +config NSH_DISABLE_MB + bool "Disable mb" + default n +config NSH_DISABLE_MKDIR + bool "Disable mkdir" + default n +config NSH_DISABLE_MKFATFS + bool "Disable mkfatfs" + default n +config NSH_DISABLE_MKFIFO + bool "Disable mkfifo" + default n +config NSH_DISABLE_MKRD + bool "Disable mkrd" + default n +config NSH_DISABLE_MH + bool "Disable mh" + default n +config NSH_DISABLE_MOUNT + bool "Disable mount" + default n +config NSH_DISABLE_MW + bool "Disable mw" + default n +config NSH_DISABLE_NSFMOUNT + bool "Disable nfsmount" + default n +config NSH_DISABLE_PS + bool "Disable ps" + default n +config NSH_DISABLE_PING + bool "Disable ping" + default n +config NSH_DISABLE_PUT + bool "Disable put" + default n +config NSH_DISABLE_PWD + bool "Disable pwd" + default n +config NSH_DISABLE_RM + bool "Disable rm" + default n +config NSH_DISABLE_RMDIR + bool "Disable rmdir" + default n +config NSH_DISABLE_SET + bool "Disable set" + default n +config NSH_DISABLE_SH + bool "Disable sh" + default n +config NSH_DISABLE_SLEEP + bool "Disable sleep" + default n +config NSH_DISABLE_TEST + bool "Disable test" + default n +config NSH_DISABLE_UMOUNT + bool "Disable umount" + default n +config NSH_DISABLE_UNSET + bool "Disable unset" + default n +config NSH_DISABLE_USLEEP + bool "Disable usleep" + default n +config NSH_DISABLE_WGET + bool "Disable wget" + default n +config NSH_DISABLE_XD + bool "Disable xd" + default n +endmenu + +config NSH_FILEIOSIZE + int "NSH I/O buffer size" + default 1024 + ---help--- + Size of a static I/O buffer used for file access (ignored if + there is no filesystem). Default is 1024. + +config NSH_STRERROR + bool "Use strerror()" + default n + ---help--- + strerror(errno) makes more readable output but strerror() is + very large and will not be used unless this setting is 'y' + +config NSH_LINELEN + int "Max command line length" + default 80 + ---help--- + The maximum length of one command line and of one output line. + Default: 80 + +config NSH_NESTDEPTH + int "Maximum command nesting" + default 3 + ---help--- + The maximum number of nested if-then[-else]-fi sequences that + are permissable. Default: 3 + +config NSH_DISABLESCRIPT + bool "Disable script support" + default n + ---help--- + This can be set to 'y' to suppress support for scripting. This + setting disables the 'sh', 'test', and '[' commands and the + if-then[-else]-fi construct. This would only be set on systems + where a minimal footprint is a necessity and scripting is not. + +config NSH_DISABLEBG + bool "Disable background commands" + default n + ---help--- + This can be set to 'y' to suppress support for background + commands. This setting disables the 'nice' command prefix and + the '&' command suffix. This would only be set on systems + where a minimal footprint is a necessity and background command + execution is not. + +config NSH_MMCSDMINOR + int "MMC/SD minor device number" + default 0 + ---help--- + If the architecture supports an MMC/SD slot and if the NSH + architecture specific logic is present, this option will provide + the MMC/SD minor number, i.e., the MMC/SD block driver will + be registered as /dev/mmcsdN where N is the minor number. + Default is zero. + +config NSH_ROMFSETC + bool "Support ROMFS start-up script" + default n + ---help--- + Mount a ROMFS filesystem at /etc and provide a startup script + at /etc/init.d/rcS. The default startup script will mount + a FAT FS RAMDISK at /tmp but the logic is easily extensible. + +endif + +if NSH_ROMFSETC +config NSH_ROMFSMOUNTPT + string "ROMFS mount point" + default "/etc" + ---help--- + The default mountpoint for the ROMFS volume is /etc, but that + can be changed with this setting. This must be a absolute path + beginning with '/'. + +config NSH_INITSCRIPT + string "Relative path to startup script" + default "init.d/rcS" + ---help--- + This is the relative path to the startup script within the mountpoint. + The default is init.d/rcS. This is a relative path and must not + start with '/'. + +config NSH_ROMFSDEVNO + int "ROMFS block device minor number" + default 0 + ---help--- + This is the minor number of the ROMFS block device. The default is + '0' corresponding to /dev/ram0. + +config NSH_ROMFSSECTSIZE + int "ROMFS sector size" + default 64 + ---help--- + This is the sector size to use with the ROMFS volume. Since the + default volume is very small, this defaults to 64 but should be + increased if the ROMFS volume were to be become large. Any value + selected must be a power of 2. + +config NSH_FATDEVNO + int "FAT block device minor number" + default 0 + ---help--- + When the default rcS file used when NSH_ROMFSETC is selected, it + will mount a FAT FS under /tmp. This is the minor number of the FAT + FS block device. The default is '1' corresponding to /dev/ram1. + +config NSH_FATSECTSIZE + int "FAT sector size" + default 512 + ---help--- + When the default rcS file used when NSH_ROMFSETC is selected, it + will mount a FAT FS under /tmp. This is the sector size use with the + FAT FS. Default is 512. + +config NSH_FATNSECTORS + int "FAT number of sectors" + default 1024 + ---help--- + When the default rcS file used when NSH_ROMFSETC is selected, it + will mount a FAT FS under /tmp. This is the number of sectors to use + with the FAT FS. Defualt is 1024. The amount of memory used by the + FAT FS will be NSH_FATSECTSIZE * NSH_FATNSECTORS bytes. + +config NSH_FATMOUNTPT + string "FAT mount point" + default 512 + ---help--- + When the default rcS file used when NSH_ROMFSETC is selected, it + will mount a FAT FS under /tmp. This is the location where the FAT + FS will be mounted. Default is /tmp. +endif + +if NSH_LIBRARY +config NSH_CONSOLE + bool "Use console" + default y + ---help--- + If NSH_CONSOLE is set to 'y', then a character driver + console front-end is selected (/dev/console). + + Normally, the serial console device is a UART and RS-232 + interface. However, if CONFIG_USBDEV is defined, then a USB + serial device may, instead, be used if the one of + the following are defined: + + CONFIG_PL2303 and CONFIG_PL2303_CONSOLE - Sets up the + Prolifics PL2303 emulation as a console device at /dev/console. + + CONFIG_CDCACM and CONFIG_CDCACM_CONSOLE - Sets up the + CDC/ACM serial device as a console device at dev/console. + + CONFIG_NSH_USBCONSOLE and CONFIG_NSH_USBCONDEV - Sets up the + some other USB serial device as the NSH console (not necessarily + dev/console). + +config NSH_USBCONSOLE + bool "Use a USB console" + default n + depends on NSH_CONSOLE && USBDEV + ---help--- + If defined, then the an arbitrary USB device may be used + to as the NSH console. In this case, CONFIG_NSH_USBCONDEV + must be defined to indicate which USB device to use as + the console. + +config NSH_USBCONDEV + string "USB console device" + default "/dev/ttyACM0" + depends on NSH_USBCONSOLE + ---help--- + If CONFIG_NSH_USBCONSOLE is set to 'y', then CONFIG_NSH_USBCONDEV + must also be set to select the USB device used to support + the NSH console. This should be set to the quoted name of a + readable/write-able USB driver such as: + CONFIG_NSH_USBCONDEV="/dev/ttyACM0". + +config UBSDEV_MINOR + int "USB console device minor number" + default 0 + depends on NSH_USBCONSOLE + ---help--- + If there are more than one USB devices, then a USB device + minor number may also need to be provided. Default: 0 + +menu "USB Trace Support" + depends on USBDEV && (DEBUG || USBDEV_TRACE) + +config NSH_USBDEV_TRACEINIT + bool "Show initialization events" + default n + ---help--- + Show initialization events + +config NSH_USBDEV_TRACECLASS + bool "Show class driver events" + default n + ---help--- + Show class driver events + +config NSH_USBDEV_TRACETRANSFERS + bool "Show data transfer events" + default n + ---help--- + Show data transfer events + +config NSH_USBDEV_TRACECONTROLLER + bool "Show controller events" + default n + ---help--- + Show controller events + +config NSH_USBDEV_TRACEINTERRUPTS + bool "Show interrupt-related events" + default n + ---help--- + Show interrupt-related events + +endmenu + +config NSH_CONDEV + bool "Default console device" + default "/dev/console" + depends on NSH_CONSOLE && !NSH_USBCONSOLE + ---help--- + If NSH_CONSOLE is set to 'y', then NSH_CONDEV + may also be set to select the serial device used to support + the NSH console. This should be set to the quoted name of a + readable/write-able character driver such as: + NSH_CONDEV="/dev/ttyS1". This is useful, for example, + to separate the NSH command line from the system console when + the system console is used to provide debug output. Default: + stdin and stdout (probably "/dev/console") + + NOTE: When any other device other than /dev/console is used + for a user interface, (1) linefeeds (\n) will not be expanded to + carriage return / linefeeds (\r\n). You will need to set + your terminal program to account for this. And (2) input is + not automatically echoed so you will have to turn local echo on. + +config NSH_ARCHINIT + bool "Have architecture-specific initialization" + default n + ---help--- + Set if your board provides architecture specific initialization + via the board-specific function nsh_archinitialize(). This + function will be called early in NSH initialization to allow + board logic to do such things as configure MMC/SD slots. + +config NSH_TELNET + bool "Use Telnet console" + default n + depends on NET && NET_TCP + ---help--- + If NSH_TELNET is set to 'y', then a TELENET + server front-end is selected. When this option is provided, + you may log into NuttX remotely using telnet in order to + access NSH. + +endif + +if NSH_TELNET +config NSH_TELNETD_PORT + int "Telnet port number" + default 23 + ---help--- + The telnet daemon will listen on this TCP port number for connections. + Default: 23 + +config NSH_TELNETD_DAEMONPRIO + int "Telnet daemon priority" + default 100 + ---help--- + Priority of the Telnet daemon. Default: 100 + +config NSH_TELNETD_DAEMONSTACKSIZE + int "Telnet daemon stack size" + default 2048 + ---help--- + Stack size allocated for the Telnet daemon. Default: 2048 + +config NSH_TELNETD_CLIENTPRIO + int "Telnet client priority" + default 100 + ---help--- + Priority of the Telnet client. Default: 100 + +config NSH_TELNETD_CLIENTSTACKSIZE + int "Telnet client stack size" + default 2048 + ---help--- + Stack size allocated for the Telnet client. Default: 2048 + +config NSH_IOBUFFER_SIZE + int "Telnet I/O buffer size" + default 512 + ---help--- + Determines the size of the I/O buffer to use for sending/ + receiving TELNET commands/reponses. Default: 512 +endif + +config NSH_DHCPC + bool "Use DHCP to get IP address" + default n + depends on NSH_LIBRARY && NET && NET_UDP && NET_BROADCAST + ---help--- + Obtain the IP address via DHCP. + + Per RFC2131 (p. 9), the DHCP client must be prepared to receive DHCP + messages of up to 576 bytes (excluding Ethernet, IP, or UDP headers and FCS). + +config NSH_IPADDR + hex "Target IP address" + default 0x10000002 + depends on NSH_LIBRARY && NET && !NSH_DHCPC + ---help--- + If NSH_DHCPC is NOT set, then the static IP address must be provided. + This is a 32-bit integer value in host order. So, as an example, + 0x10000002 would be 10.0.0.2. + +config NSH_DRIPADDR + hex "Router IP address" + default 0x10000001 + depends on NSH_LIBRARY && NET && !NSH_DHCPC + ---help--- + Default router IP address (aka, Gateway). This is a 32-bit integer + value in host order. So, as an example, 0x10000001 would be 10.0.0.1. + +config NSH_NETMASK + hex "Network mask" + default 0xffffff00 + depends on NSH_LIBRARY && NET && !NSH_DHCPC + ---help--- + Network mask. This is a 32-bit integer value in host order. So, as + an example, 0xffffff00 would be 255.255.255.0. + +config NSH_NOMAC + bool "Hardware has no MAC address" + default n + depends on NSH_LIBRARY && NET + ---help--- + Set if your ethernet hardware has no built-in MAC address. + If set, a bogus MAC will be assigned. diff --git a/apps/nshlib/Make.defs b/apps/nshlib/Make.defs new file mode 100644 index 0000000000..c72c09bce7 --- /dev/null +++ b/apps/nshlib/Make.defs @@ -0,0 +1,40 @@ +############################################################################ +# apps/nshlib/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +if ($(CONFIG_NSH_LIBRARY),y) +CONFIGURED_APPS += nshlib +endif + diff --git a/apps/nshlib/Makefile b/apps/nshlib/Makefile new file mode 100644 index 0000000000..f616374bfd --- /dev/null +++ b/apps/nshlib/Makefile @@ -0,0 +1,131 @@ +############################################################################ +# apps/nshlib/Makefile +# +# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# NSH Library + +ASRCS = +CSRCS = nsh_init.c nsh_parse.c nsh_console.c nsh_fscmds.c nsh_ddcmd.c \ + nsh_proccmds.c nsh_mmcmds.c nsh_envcmds.c nsh_dbgcmds.c + +ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) +CSRCS += nsh_apps.c +endif + +ifeq ($(CONFIG_NSH_ROMFSETC),y) +CSRCS += nsh_romfsetc.c +endif + +ifeq ($(CONFIG_NET),y) +CSRCS += nsh_netinit.c nsh_netcmds.c +endif + +ifeq ($(CONFIG_RTC),y) +CSRCS += nsh_timcmds.c +endif + +ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y) +CSRCS += nsh_mntcmds.c +endif + +ifeq ($(CONFIG_NSH_CONSOLE),y) +CSRCS += nsh_consolemain.c +endif + +ifeq ($(CONFIG_NSH_TELNET),y) +CSRCS += nsh_telnetd.c +endif + +ifneq ($(CONFIG_NSH_DISABLESCRIPT),y) +CSRCS += nsh_test.c +endif + +ifeq ($(CONFIG_USBDEV),y) +CSRCS += nsh_usbdev.c +endif + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . +VPATH = + +# Build targets + +all: .built +.PHONY: context .depend depend clean distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +context: + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) \ + $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep + diff --git a/apps/nshlib/README.txt b/apps/nshlib/README.txt new file mode 100644 index 0000000000..543b9a448d --- /dev/null +++ b/apps/nshlib/README.txt @@ -0,0 +1,1159 @@ +apps/nshlib +^^^^^^^^^^^ + + This directory contains the NuttShell (NSH) library. This library can be + linked with other logic to provide a simple shell application for NuttX. + + - Console/NSH Front End + - Command Overview + - Conditional Command Execution + - Built-In Variables + - Current Working Directory + Environment Variables + - NSH Start-Up Script + - Simple Commands + - NSH Configuration Settings + Command Dependencies on Configuration Settings + NSH-Specific Configuration Settings + - Common Problems + +Console/NSH Front End +^^^^^^^^^^^^^^^^^^^^^ + + Using settings in the configuration file, NSH may be configured to + use either the serial stdin/out or a telnet connection as the console + or BOTH. When NSH is started, you will see the following welcome on + either console: + + NuttShell (NSH) + nsh> + + 'nsh>' is the NSH prompt and indicates that you may enter a command + from the console. + +Command Overview +^^^^^^^^^^^^^^^^ + + This directory contains the NuttShell (NSH). This is a simple + shell-like application. At present, NSH supports the following commands + forms: + + Simple command: + Command with re-directed output: > + >> + Background command: & + Re-directed background command: > & + >> & + + Where: + + is any one of the simple commands listed later. + is the full or relative path to any writable object + in the filesystem name space (file or character driver). + Such objects will be referred to simply as files throughout + this README. + + NSH executes at the mid-priority (128). Backgrounded commands can + be made to execute at higher or lower priorities using nice: + + [nice [-d >]] [> |>> ] [&] + + Where is any value between -20 and 19 where lower + (more negative values) correspond to higher priorities. The + default niceness is 10. + +Conditional Command Execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + An if-then[-else]-fi construct is also supported in order to + support conditional execution of commands. This works from the + command line but is primarily intended for use within NSH scripts + (see the sh commnd). The syntax is as follows: + + if + then + [sequence of ] + else + [sequence of ] + fi + +Built-In Variables +^^^^^^^^^^^^^^^^^^ + + $? - The result of the last simple command execution + +Current Working Directory +^^^^^^^^^^^^^^^^^^^^^^^^^ + + All path arguments to commands may be either an absolute path or a + path relative to the current working directory. The current working + directory is set using the 'cd' command and can be queried either + by using the 'pwd' command or by using the 'echo $PWD' command. + + Environment Variables: + ---------------------- + + PWD - The current working directory + OLDPWD - The previous working directory + +NSH Start-Up Script +^^^^^^^^^^^^^^^^^^^ + +NSH supports options to provide a start up script for NSH. In general +this capability is enabled with CONFIG_NSH_ROMFSETC, but has +several other related configuration options as described in the final +section of this README. This capability also depends on: + + - CONFIG_DISABLE_MOUNTPOINT not set + - CONFIG_NFILE_DESCRIPTORS > 4 + - CONFIG_FS_ROMFS + +Default Start-Up Behavior +------------------------- + +The implementation that is provided is intended to provide great flexibility +for the use of Start-Up files. This paragraph will discuss the general +behavior when all of the configuration options are set to the default +values. + +In this default case, enabling CONFIG_NSH_ROMFSETC will cause +NSH to behave as follows at NSH startup time: + +- NSH will create a read-only RAM disk (a ROM disk), containing a tiny + ROMFS filesystem containing the following: + + |--init.d/ + `-- rcS + + Where rcS is the NSH start-up script + +- NSH will then mount the ROMFS filesystem at /etc, resulting in: + + |--dev/ + | `-- ram0 + `--etc/ + `--init.d/ + `-- rcS + +- By default, the contents of rcS script are: + + # Create a RAMDISK and mount it at XXXRDMOUNTPOUNTXXX + + mkrd -m 1 -s 512 1024 + mkfatfs /dev/ram1 + mount -t vfat /dev/ram1 /tmp + +- NSH will execute the script at /etc/init.d/rcS at start-up (before the + first NSH prompt. After execution of the script, the root FS will look + like: + + |--dev/ + | |-- ram0 + | `-- ram1 + |--etc/ + | `--init.d/ + | `-- rcS + `--tmp/ + +Modifying the ROMFS Image +------------------------- + +The contents of the /etc directory are retained in the file +apps/nshlib/nsh_romfsimg.h (OR, if CONFIG_NSH_ARCHROMFS +is defined, include/arch/board/rcs.template). In order to modify +the start-up behavior, there are three things to study: + +1. Configuration Options. + The additional CONFIG_NSH_ROMFSETC configuration options + discussed in the final section of this README. + +2. tools/mkromfsimg.sh Script. + The script tools/mkromfsimg.sh creates nsh_romfsimg.h. + It is not automatically executed. If you want to change the + configuration settings associated with creating and mounting + the /tmp directory, then it will be necessary to re-generate + this header file using the mkromfsimg.sh script. + + The behavior of this script depends upon three things: + + - The configuration settings of the installed NuttX configuration. + - The genromfs tool (available from http://romfs.sourceforge.net). + - The file apps/nshlib/rcS.template (OR, if + CONFIG_NSH_ARCHROMFS is defined, include/arch/board/rcs.template) + +3. rcS.template. + The file apps/nshlib/rcS.template contains the general form + of the rcS file; configured values are plugged into this + template file to produce the final rcS file. + +NOTE: + + apps/nshlib/rcS.template generates the standard, default + nsh_romfsimg.h file. If CONFIG_NSH_ARCHROMFS is defined + in the NuttX configuration file, then a custom, board-specific + nsh_romfsimg.h file residing in configs//include will be + used. NOTE when the OS is configured, include/arch/board will + be linked to configs//include. + +All of the startup-behavior is contained in rcS.template. The +role of mkromfsimg.sh is to (1) apply the specific configuration +settings to rcS.template to create the final rcS, and (2) to +generate the header file nsh_romfsimg.h containg the ROMFS +file system image. + +Simple Commands +^^^^^^^^^^^^^^^ + +o [ ] +o test + + These are two alternative forms of the same command. They support + evaluation of a boolean expression which sets $?. This command + is used most frequently as the conditional command following the + 'if' in the if-then[-else]-fi construct. + + Expression Syntax: + ------------------ + + expression = simple-expression | !expression | + expression -o expression | expression -a expression + + simple-expression = unary-expression | binary-expression + + unary-expression = string-unary | file-unary + + string-unary = -n string | -z string + + file-unary = -b file | -c file | -d file | -e file | -f file | + -r file | -s file | -w file + + binary-expression = string-binary | numeric-binary + + string-binary = string = string | string == string | string != string + + numeric-binary = integer -eq integer | integer -ge integer | + integer -gt integer | integer -le integer | + integer -lt integer | integer -ne integer + +o cat [ [ ...]] + + This command copies and concatentates all of the files at + to the console (or to another file if the output is redirected). + +o cd [|-|~|..] + + Changes the current working directory (PWD). Also sets the + previous working directory environment variable (OLDPWD). + + FORMS: + ------ + + 'cd ' sets the current working directory to . + 'cd -' sets the current working directory to the previous + working directory ($OLDPWD). Equivalent to 'cd $OLDPWD'. + 'cd' or 'cd ~' set the current working directory to the 'home' + directory. The 'home' directory can be configured by setting + CONFIG_LIB_HOMEDIR in the configuration file. The default + 'home' directory is '/'. + 'cd ..' sets the current working directory to the parent directory. + +o cp + + Copy of the contents of the file at to the location + in the filesystem indicated by + +o date [-s "MMM DD HH:MM:SS YYYY"] + + Show or set the current date and time. This command is only supported + if the platform supported RTC hardware (CONFIG_RTC=y). + + Only one format is used both on display and when setting the date/time: + MMM DD HH:MM:SS YYYY. For example, + + data -s "Sep 1 11:30:00 2011" + + 24-hour time format is assumed. + +o dd if= of= [bs=] [count=] [skip=] + + Copy blocks from to . or may + be the path to a standard file, a character device, or a block device. + + Examples: + + 1. Read from character device, write to regular file. This will + create a new file of the specified size filled with zero. + + nsh> dd if=/dev/zero of=/tmp/zeros bs=64 count=16 + nsh> ls -l /tmp + /tmp: + -rw-rw-rw- 1024 ZEROS + + 2. Read from character device, write to block device. This will + fill the entire block device with zeros. + + nsh> ls -l /dev + /dev: + brw-rw-rw- 0 ram0 + crw-rw-rw- 0 zero + nsh> dd if=/dev/zero of=/dev/ram0 + + 3. Read from a block devic, write to a character device. This + will read the entire block device and dump the contents in + the bit bucket. + + nsh> ls -l /dev + /dev: + crw-rw-rw- 0 null + brw-rw-rw- 0 ram0 + nsh> dd if=/dev/ram0 of=/dev/null + +o df + + Show the state of each mounted volume + + Example: + + nsh> mount + /etc type romfs + /tmp type vfat + nsh> df + Block Number + Size Blocks Used Available Mounted on + 64 6 6 0 /etc + 512 985 2 983 /tmp + nsh> + +o echo [ [...]] + + Copy the sequence of strings and expanded environment variables to + console out (or to a file if the output is re-directed). + +o exec + + Execute the user logic at address . NSH will pause + until the execution unless the user logic is executed in background + via 'exec &' + +o exit + + Exit NSH. Only useful if you have started some other tasks (perhaps + using the 'exec' command') and you would like to have NSH out of the + way. + +o free + + Show the current state of the memory allocator. For example, + + nsh> free + free + total used free largest + Mem: 4194288 1591552 2602736 2601584 + + Where: + total - This is the total size of memory allocated for use + by malloc in bytes. + used - This is the total size of memory occupied by + chunks handed out by malloc. + free - This is the total size of memory occupied by + free (not in use) chunks. + largest - Size of the largest free (not in use) chunk + +o get [-b|-n] [-f ] -h + + Use TFTP to copy the file at from the host whose IP + address is identified by . Other options: + + -f + The file will be saved relative to the current working directory + unless is provided. + -b|-n + Selects either binary ("octect") or test ("netascii") transfer + mode. Default: text. + +o help + + Presents summary information about each command to console. + +o ifconfig + + Show the current configuration of the network, for example: + + nsh> ifconfig + eth0 HWaddr 00:18:11:80:10:06 + IPaddr:10.0.0.2 DRaddr:10.0.0.1 Mask:255.255.255.0 + + if uIP statistics are enabled (CONFIG_NET_STATISTICS), then + this command will also show the detailed state of uIP. + +o kill - + + Send the to the task identified by . + +o losetup [-d ] | [[-o ] [-r] ] + + Setup or teardown the loop device: + + 1. Teardown the setup for the loop device at : + + losetup d + + 2. Setup the loop device at to access the file at + as a block device: + + losetup [-o ] [-r] + + Example: + + nsh> dd if=/dev/zero of=/tmp/image bs=512 count=512 + nsh> ls -l /tmp + /tmp: + -rw-rw-rw- 262144 IMAGE + nsh> losetup /dev/loop0 /tmp/image + nsh> ls -l /dev + /dev: + brw-rw-rw- 0 loop0 + nsh> mkfatfs /dev/loop0 + nsh> mount -t vfat /dev/loop0 /mnt/example + nsh> ls -l /mnt + ls -l /mnt + /mnt: + drw-rw-rw- 0 example/ + nsh> echo "This is a test" >/mnt/example/atest.txt + nsh> ls -l /mnt/example + /mnt/example: + -rw-rw-rw- 16 ATEST.TXT + nsh> cat /mnt/example/atest.txt + This is a test + nsh> + +o ls [-lRs] + + Show the contents of the directory at . NOTE: + must refer to a directory and no other filesystem + object. + + Options: + -------- + + -R Show the constents of specified directory and all of its + sub-directories. + -s Show the size of the files along with the filenames in the + listing + -l Show size and mode information along with the filenames + in the listing. + +o mb [=][ ] +o mh [=][ ] +o mw [=][ ] + + Access memory using byte size access (mb), 16-bit accesses (mh), + or 32-bit access (mw). In each case, + + . Specifies the address to be accessed. The current + value at that address will always be read and displayed. + =. Read the value, then write + to the location. + . Perform the mb, mh, or mw operation on a total + of bytes, increment the appropriately + after each access + + Example + + nsh> mh 0 16 + 0 = 0x0c1e + 2 = 0x0100 + 4 = 0x0c1e + 6 = 0x0110 + 8 = 0x0c1e + a = 0x0120 + c = 0x0c1e + e = 0x0130 + 10 = 0x0c1e + 12 = 0x0140 + 14 = 0x0c1e + nsh> + +o mkdir + + Create the directory at . All components of of + except the final directory name must exist on a mounted file + system; the final directory must not. + + Recall that NuttX uses a pseudo filesystem for its root file system. + The mkdir command can only be used to create directories in volumes + set up with the mount command; it cannot be used to create directories + in the pseudo filesystem. + + Example: + ^^^^^^^^ + + nsh> mkdir /mnt/fs/tmp + nsh> ls -l /mnt/fs + /mnt/fs: + drw-rw-rw- 0 TESTDIR/ + drw-rw-rw- 0 TMP/ + nsh> + +o mkfatfs + + Format a fat file system on the block device specified by path. + NSH provides this command to access the mkfatfs() NuttX API. + This block device must reside in the NuttX psuedo filesystem and + must have been created by some call to register_blockdriver() (see + include/nuttx/fs/fs.h). + +o mkfifo + + Creates a FIFO character device anywhere in the pseudo file system, + creating whatever psuedo directories that may be needed to complete + the full path. By convention, however, device drivers are place in + the standard /dev directory. After it is created, the FIFO device + may be used as any other device driver. NSH provides this command + to access the mkfifo() NuttX API. + + Example: + ^^^^^^^^ + + nsh> ls -l /dev + /dev: + crw-rw-rw- 0 console + crw-rw-rw- 0 null + brw-rw-rw- 0 ram0 + nsh> mkfifo /dev/fifo + nsh> ls -l /dev + ls -l /dev + /dev: + crw-rw-rw- 0 console + crw-rw-rw- 0 fifo + crw-rw-rw- 0 null + brw-rw-rw- 0 ram0 + nsh> + +o mkrd [-m ] [-s ] + + Create a ramdisk consisting of , each of size + (or 512 bytes if is not specified. + The ramdisk will be registered as /dev/ram (if is not + specified, mkrd will attempt to register the ramdisk as + /dev/ram0. + + Example: + ^^^^^^^^ + + nsh> ls /dev + /dev: + console + null + ttyS0 + ttyS1 + nsh> mkrd 1024 + nsh> ls /dev + /dev: + console + null + ram0 + ttyS0 + ttyS1 + nsh> + + Once the ramdisk has been created, it may be formatted using + the mkfatfs command and mounted using the mount command. + + Example: + ^^^^^^^^ + nsh> mkrd 1024 + nsh> mkfatfs /dev/ram0 + nsh> mount -t vfat /dev/ram0 /tmp + nsh> ls /tmp + /tmp: + nsh> + +o mount [-t ] + + The mount command performs one of two different operations. If no + paramters are provided on the command line after the mount command, + then the 'mount' command will enumerate all of the current + mountpoints on the console. + + If the mount parameters are provied on the command after the 'mount' + command, then the 'mount' command will mount a file system in the + NuttX psuedo-file system. 'mount' performs a three way association, + binding: + + File system. The '-t ' option identifies the type of + file system that has been formatted on the . As + of this writing, vfat is the only supported value for + + Block Device. The argument is the full or relative + path to a block driver inode in the psuedo filesystem. By convention, + this is a name under the /dev sub-directory. This + must have been previously formatted with the same file system + type as specified by + + Mount Point. The mount point is the location in the psuedo file + system where the mounted volume will appear. This mount point + can only reside in the NuttX psuedo filesystem. By convention, this + mount point is a subdirectory under /mnt. The mount command will + create whatever psuedo directories that may be needed to complete + the full path but the full path must not already exist. + + After the volume has been mounted in the NuttX psuedo file + system, it may be access in the same way as other objects in the + file system. + + Examples: + ^^^^^^^^^ + + nsh> ls -l /dev + /dev: + crw-rw-rw- 0 console + crw-rw-rw- 0 null + brw-rw-rw- 0 ram0 + nsh> ls /mnt + nsh: ls: no such directory: /mnt + nsh> mount -t vfat /dev/ram0 /mnt/fs + nsh> ls -l /mnt/fs/testdir + /mnt/fs/testdir: + -rw-rw-rw- 15 TESTFILE.TXT + nsh> echo "This is a test" >/mnt/fs/testdir/example.txt + nsh> ls -l /mnt/fs/testdir + /mnt/fs/testdir: + -rw-rw-rw- 15 TESTFILE.TXT + -rw-rw-rw- 16 EXAMPLE.TXT + nsh> cat /mnt/fs/testdir/example.txt + This is a test + nsh> + + nsh> mount + /etc type romfs + /tmp type vfat + /mnt/fs type vfat + +o mv + + Rename the file object at to . Both paths must + reside in the same mounted filesystem. + +o nfsmount + + Mount the remote NFS server directory at on the target machine. + is the IP address of the remote server. + +o ps + + Show the currently active threads and tasks. For example, + + nsh> ps + PID PRI SCHD TYPE NP STATE NAME + 0 0 FIFO TASK READY Idle Task() + 1 128 RR TASK RUNNING init() + 2 128 FIFO TASK WAITSEM nsh_telnetmain() + 3 100 RR PTHREAD WAITSEM (21) + nsh> + +o ping [-c ] [-i ] + + Test the network communication with a remote peer. Example, + + nsh> 10.0.0.1 + PING 10.0.0.1 56 bytes of data + 56 bytes from 10.0.0.1: icmp_seq=1 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=2 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=3 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=4 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=5 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=6 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=7 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=8 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=9 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=10 time=0 ms + 10 packets transmitted, 10 received, 0% packet loss, time 10190 ms + nsh> + +o put [-b|-n] [-f ] -h + + Copy the file at to the host whose IP address is + identified by . Other options: + + -f + The file will be saved with the same name on the host unless + unless is provided. + -b|-n + Selects either binary ("octect") or test ("netascii") transfer + mode. Default: text. + +o pwd + + Show the current working directory. + + nsh> cd /dev + nsh> pwd + /dev + nsh> + + Same as 'echo $PWD' + + nsh> echo $PWD + /dev + nsh> + +o rm + + Remove the specified name from the mounted file system. + Recall that NuttX uses a pseudo filesystem for its root file system. + The rm command can only be used to remove (unlink) files in volumes + set up with the mount command; it cannot be used to remove names from + the pseudo filesystem. + + Example: + ^^^^^^^^ + + nsh> ls /mnt/fs/testdir + /mnt/fs/testdir: + TESTFILE.TXT + EXAMPLE.TXT + nsh> rm /mnt/fs/testdir/example.txt + nsh> ls /mnt/fs/testdir + /mnt/fs/testdir: + TESTFILE.TXT + nsh> + +o rmdir + + Remove the specified directory from the mounted file system. + Recall that NuttX uses a pseudo filesystem for its root file system. The + rmdir command can only be used to remove directories from volumes set up + with the mount command; it cannot be used to remove directories from the + pseudo filesystem. + + Example: + ^^^^^^^^ + + nsh> mkdir /mnt/fs/tmp + nsh> ls -l /mnt/fs + /mnt/fs: + drw-rw-rw- 0 TESTDIR/ + drw-rw-rw- 0 TMP/ + nsh> rmdir /mnt/fs/tmp + nsh> ls -l /mnt/fs + ls -l /mnt/fs + /mnt/fs: + drw-rw-rw- 0 TESTDIR/ + nsh> + +o set + + Set the environment variable to the sting . + For example, + + nsh> echo $foobar + + nsh> set foobar foovalue + nsh> echo $foobar + foovalue + nsh> + +o sh + + Execute the sequence of NSH commands in the file referred + to by . + +o sleep + + Pause execution (sleep) of seconds. + +o unset + + Remove the value associated with the environment variable + . Example: + + nsh> echo $foobar + foovalue + nsh> unset foobar + nsh> echo $foobar + + nsh> + +o usleep + + Pause execution (sleep) of microseconds. + +o wget [-o ] + + Use HTTP to copy the file at to the current directory. + Options: + + -o + The file will be saved relative to the current working directory + and with the same name as on the HTTP server unless + is provided. + +o xd + + Dump bytes of data from address + + Example: + ^^^^^^^^ + + nsh> xd 410e0 512 + Hex dump: + 0000: 00 00 00 00 9c 9d 03 00 00 00 00 01 11 01 10 06 ................ + 0010: 12 01 11 01 25 08 13 0b 03 08 1b 08 00 00 02 24 ....%..........$ + ... + 01f0: 08 3a 0b 3b 0b 49 13 00 00 04 13 01 01 13 03 08 .:.;.I.......... + nsh> + +NSH Configuration Settings +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The availability of the above commands depends upon features that +may or may not be enabled in the NuttX configuration file. The +following table indicates the dependency of each command on NuttX +configuration settings. General configuration settings are discussed +in the NuttX Porting Guide. Configuration settings specific to NSH +as discussed at the bottom of this README file. + +Command Dependencies on Configuration Settings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Command Depends on Configuration + ---------- -------------------------- + [ !CONFIG_NSH_DISABLESCRIPT + cat CONFIG_NFILE_DESCRIPTORS > 0 + cd !CONFIG_DISABLE_ENVIRON && CONFIG_NFILE_DESCRIPTORS > 0 + cp CONFIG_NFILE_DESCRIPTORS > 0 + dd CONFIG_NFILE_DESCRIPTORS > 0 + df !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_READABLE (see note 3) + echo -- + exec -- + exit -- + free -- + get CONFIG_NET && CONFIG_NET_UDP && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NET_BUFSIZE >= 558 (see note 1) + help -- + ifconfig CONFIG_NET + kill !CONFIG_DISABLE_SIGNALS + losetup !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 + ls CONFIG_NFILE_DESCRIPTORS > 0 + mb,mh,mw --- + mkdir !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE (see note 4) + mkfatfs !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_FAT + mkfifo CONFIG_NFILE_DESCRIPTORS > 0 + mkrd !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE (see note 4) + mount !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_READABLE (see note 3) + mv !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE (see note 4) + nfsmount !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NET && CONFIG_NFS + ping CONFIG_NET && CONFIG_NET_ICMP && CONFIG_NET_ICMP_PING && !CONFIG_DISABLE_CLOCK && !CONFIG_DISABLE_SIGNALS + ps -- + put CONFIG_NET && CONFIG_NET_UDP && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NET_BUFSIZE >= 558 (see note 1,2) + pwd !CONFIG_DISABLE_ENVIRON && CONFIG_NFILE_DESCRIPTORS > 0 + rm !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE (see note 4) + rmdir !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE (see note 4) + set !CONFIG_DISABLE_ENVIRON + sh CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !CONFIG_NSH_DISABLESCRIPT + sleep !CONFIG_DISABLE_SIGNALS + test !CONFIG_NSH_DISABLESCRIPT + umount !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_READABLE + unset !CONFIG_DISABLE_ENVIRON + usleep !CONFIG_DISABLE_SIGNALS + get CONFIG_NET && CONFIG_NET_TCP && CONFIG_NFILE_DESCRIPTORS > 0 + xd --- + +* NOTES: + 1. Because of hardware padding, the actual buffersize required for put and get + operations size may be larger. + 2. Special TFTP server start-up optionss will probably be required to permit + creation of file for the correct operation of the put command. + 3. CONFIG_FS_READABLE is not a user configuration but is set automatically + if any readable filesystem is selected. At present, this is either CONFIG_FS_FAT + and CONFIG_FS_ROMFS. + 4. CONFIG_FS_WRITABLE is not a user configuration but is set automatically + if any writable filesystem is selected. At present, this is only CONFIG_FS_FAT. + +In addition, each NSH command can be individually disabled via one of the following +settings. All of these settings make the configuration of NSH potentially complex but +also allow it to squeeze into very small memory footprints. + + CONFIG_NSH_DISABLE_CAT, CONFIG_NSH_DISABLE_CD, CONFIG_NSH_DISABLE_CP, + CONFIG_NSH_DISABLE_DD, CONFIG_NSH_DISABLE_DF, CONFIG_NSH_DISABLE_ECHO, + CONFIG_NSH_DISABLE_EXEC, CONFIG_NSH_DISABLE_EXIT, CONFIG_NSH_DISABLE_FREE, + CONFIG_NSH_DISABLE_GET, CONFIG_NSH_DISABLE_HELP, CONFIG_NSH_DISABLE_IFCONFIG, + CONFIG_NSH_DISABLE_KILL, CONFIG_NSH_DISABLE_LOSETUP, CONFIG_NSH_DISABLE_LS, + CONFIG_NSH_DISABLE_MB, CONFIG_NSH_DISABLE_MKDIR, CONFIG_NSH_DISABLE_MKFATFS, + CONFIG_NSH_DISABLE_MKFIFO, CONFIG_NSH_DISABLE_MKRD, CONFIG_NSH_DISABLE_MH, + CONFIG_NSH_DISABLE_MOUNT, CONFIG_NSH_DISABLE_MW, CONFIG_NSH_DISABLE_MV, + CONFIG_NSH_DISABLE_NFSMOUNT, CONFIG_NSH_DISABLE_PS, CONFIG_NSH_DISABLE_PING, + CONFIG_NSH_DISABLE_PUT, CONFIG_NSH_DISABLE_PWD, CONFIG_NSH_DISABLE_RM, + CONFIG_NSH_DISABLE_RMDIR, CONFIG_NSH_DISABLE_SET, CONFIG_NSH_DISABLE_SH, + CONFIG_NSH_DISABLE_SLEEP, CONFIG_NSH_DISABLE_TEST, CONFIG_NSH_DISABLE_UMOUNT, + CONFIG_NSH_DISABLE_UNSET, CONFIG_NSH_DISABLE_USLEEP, CONFIG_NSH_DISABLE_WGET, + CONFIG_NSH_DISABLE_XD + +NSH-Specific Configuration Settings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + The behavior of NSH can be modified with the following settings in + the configs//defconfig file: + + * CONFIG_NSH_BUILTIN_APPS + Support external registered, "named" applications that can be + executed from the NSH command line (see apps/README.txt for + more information). + + * CONFIG_NSH_FILEIOSIZE + Size of a static I/O buffer used for file access (ignored if + there is no filesystem). Default is 1024. + + * CONFIG_NSH_STRERROR + strerror(errno) makes more readable output but strerror() is + very large and will not be used unless this setting is 'y' + + * CONFIG_NSH_LINELEN + The maximum length of one command line and of one output line. + Default: 80 + + * CONFIG_NSH_NESTDEPTH + The maximum number of nested if-then[-else]-fi sequences that + are permissable. Default: 3 + + * CONFIG_NSH_DISABLESCRIPT + This can be set to 'y' to suppress support for scripting. This + setting disables the 'sh', 'test', and '[' commands and the + if-then[-else]-fi construct. This would only be set on systems + where a minimal footprint is a necessity and scripting is not. + + * CONFIG_NSH_DISABLEBG + This can be set to 'y' to suppress support for background + commands. This setting disables the 'nice' command prefix and + the '&' command suffix. This would only be set on systems + where a minimal footprint is a necessity and background command + execution is not. + + * CONFIG_NSH_MMCSDMINOR + If the architecture supports an MMC/SD slot and if the NSH + architecture specific logic is present, this option will provide + the MMC/SD minor number, i.e., the MMC/SD block driver will + be registered as /dev/mmcsdN where N is the minor number. + Default is zero. + + * CONFIG_NSH_ROMFSETC + Mount a ROMFS filesystem at /etc and provide a startup script + at /etc/init.d/rcS. The default startup script will mount + a FAT FS RAMDISK at /tmp but the logic is easily extensible. + + * CONFIG_NSH_CONSOLE + If CONFIG_NSH_CONSOLE is set to 'y', then a serial + console front-end is selected. + + Normally, the serial console device is a UART and RS-232 + interface. However, if CONFIG_USBDEV is defined, then a USB + serial device may, instead, be used if the one of + the following are defined: + + CONFIG_PL2303 and CONFIG_PL2303_CONSOLE - Sets up the + Prolifics PL2303 emulation as a console device + at /dev/console. + + CONFIG_CDCACM and CONFIG_CDCACM_CONSOLE - Sets up the + CDC/ACM serial device as a console device at + dev/console. + + CONFIG_NSH_USBCONSOLE + If defined, then the an arbitrary USB device may be used + to as the NSH console. In this case, CONFIG_NSH_USBCONDEV + must be defined to indicate which USB device to use as + the console. + + CONFIG_NSH_USBCONDEV + If CONFIG_NSH_USBCONSOLE is set to 'y', then CONFIG_NSH_USBCONDEV + must also be set to select the USB device used to support + the NSH console. This should be set to the quoted name of a + readable/write-able USB driver such as: + CONFIG_NSH_USBCONDEV="/dev/ttyACM0". + + If there are more than one USB devices, then a USB device + minor number may also need to be provided: + + CONFIG_NSH_UBSDEV_MINOR + The minor device number of the USB device. Default: 0 + + If USB tracing is enabled (CONFIG_USBDEV_TRACE), then NSH will + initialize USB tracing as requested by the following. Default: + Only USB errors are traced. + + CONFIG_NSH_USBDEV_TRACEINIT + Show initialization events + CONFIG_NSH_USBDEV_TRACECLASS + Show class driver events + CONFIG_NSH_USBDEV_TRACETRANSFERS + Show data transfer events + CONFIG_NSH_USBDEV_TRACECONTROLLER + Show controller events + CONFIG_NSH_USBDEV_TRACEINTERRUPTS + Show interrupt-related events. + + * CONFIG_NSH_CONDEV + If CONFIG_NSH_CONSOLE is set to 'y', then CONFIG_NSH_CONDEV + may also be set to select the serial device used to support + the NSH console. This should be set to the quoted name of a + readable/write-able character driver such as: + CONFIG_NSH_CONDEV="/dev/ttyS1". This is useful, for example, + to separate the NSH command line from the system console when + the system console is used to provide debug output. Default: + stdin and stdout (probably "/dev/console") + + NOTE: When any other device other than /dev/console is used + for a user interface, (1) linefeeds (\n) will not be expanded to + carriage return / linefeeds (\r\n). You will need to set + your terminal program to account for this. And (2) input is + not automatically echoed so you will have to turn local echo on. + + * CONFIG_NSH_TELNET + If CONFIG_NSH_TELNET is set to 'y', then a TELENET + server front-end is selected. When this option is provided, + you may log into NuttX remotely using telnet in order to + access NSH. + + * CONFIG_NSH_ARCHINIT + Set if your board provides architecture specific initialization + via the board-specific function nsh_archinitialize(). This + function will be called early in NSH initialization to allow + board logic to do such things as configure MMC/SD slots. + + If Telnet is selected for the NSH console, then we must configure + the resources used by the Telnet daemon and by the Telnet clients. + + * CONFIG_NSH_TELNETD_PORT - The telnet daemon will listen on this + TCP port number for connections. Default: 23 + + * CONFIG_NSH_TELNETD_DAEMONPRIO - Priority of the Telnet daemon. + Default: SCHED_PRIORITY_DEFAULT + + * CONFIG_NSH_TELNETD_DAEMONSTACKSIZE - Stack size allocated for the + Telnet daemon. Default: 2048 + + * CONFIG_NSH_TELNETD_CLIENTPRIO- Priority of the Telnet client. + Default: SCHED_PRIORITY_DEFAULT + + * CONFIG_NSH_TELNETD_CLIENTSTACKSIZE - Stack size allocated for the + Telnet client. Default: 2048 + + One or both of CONFIG_NSH_CONSOLE and CONFIG_NSH_TELNET + must be defined. If CONFIG_NSH_TELNET is selected, then there some + other configuration settings that apply: + + * CONFIG_NET=y + Of course, networking must be enabled + + * CONFIG_NSOCKET_DESCRIPTORS + And, of course, you must allocate some socket descriptors. + + * CONFIG_NET_TCP=y + TCP/IP support is required for telnet (as well as various other TCP-related + configuration settings). + + * CONFIG_NSH_IOBUFFER_SIZE + Determines the size of the I/O buffer to use for sending/ + receiving TELNET commands/reponses + + * CONFIG_NSH_DHCPC + Obtain the IP address via DHCP. + + * CONFIG_NSH_IPADDR + If CONFIG_NSH_DHCPC is NOT set, then the static IP + address must be provided. + + * CONFIG_NSH_DRIPADDR + Default router IP address + + * CONFIG_NSH_NETMASK + Network mask + + * CONFIG_NSH_NOMAC + Set if your ethernet hardware has no built-in MAC address. + If set, a bogus MAC will be assigned. + + If you use DHCPC, then some special configuration network options are + required. These include: + + * CONFIG_NET=y + Of course, networking must be enabled + + * CONFIG_NSOCKET_DESCRIPTORS + And, of course, you must allocate some socket descriptors. + + * CONFIG_NET_UDP=y + UDP support is required for DHCP (as well as various other UDP-related + configuration settings) + + * CONFIG_NET_BROADCAST=y + UDP broadcast support is needed. + + * CONFIG_NET_BUFSIZE=650 (or larger) + Per RFC2131 (p. 9), the DHCP client must be prepared to receive DHCP + messages of up to 576 bytes (excluding Ethernet, IP, or UDP headers and FCS). + + If CONFIG_NSH_ROMFSETC is selected, then the following additional + configuration setting apply: + + * CONFIG_NSH_ROMFSMOUNTPT + The default mountpoint for the ROMFS volume is /etc, but that + can be changed with this setting. This must be a absolute path + beginning with '/'. + + * CONFIG_NSH_INITSCRIPT + This is the relative path to the startup script within the mountpoint. + The default is init.d/rcS. This is a relative path and must not + start with '/'. + + * CONFIG_NSH_ROMFSDEVNO + This is the minor number of the ROMFS block device. The default is + '0' corresponding to /dev/ram0. + + * CONFIG_NSH_ROMFSSECTSIZE + This is the sector size to use with the ROMFS volume. Since the + default volume is very small, this defaults to 64 but should be + increased if the ROMFS volume were to be become large. Any value + selected must be a power of 2. + + When the default rcS file used when CONFIG_NSH_ROMFSETC is + selected, it will mount a FAT FS under /tmp. The following selections + describe that FAT FS. + + * CONFIG_NSH_FATDEVNO + This is the minor number of the FAT FS block device. The default is + '1' corresponding to /dev/ram1. + + * CONFIG_NSH_FATSECTSIZE + This is the sector size use with the FAT FS. Default is 512. + + * CONFIG_NSH_FATNSECTORS + This is the number of sectors to use with the FAT FS. Defalt is + 1024. The amount of memory used by the FAT FS will be + CONFIG_NSH_FATSECTSIZE * CONFIG_NSH_FATNSECTORS + bytes. + + * CONFIG_NSH_FATMOUNTPT + This is the location where the FAT FS will be mounted. Default + is /tmp. + +Common Problems +^^^^^^^^^^^^^^^ + + Problem: + Using NSH over serial, the "nsh>" prompt repeats over and over again + with no serial input. + Usual Cause: + NSH over serial needs to use the interrupt driven serial driver + (drivers/serial/serial.c) not the polled serial driver (drivers/serial/lowconsole.c). + Make sure that the polled console is disabled in the OS configuration + file, .config. That file should have CONFIG_DEV_LOWCONSOLE=n for + NSH over serial. + + Problem: + The function 'readline' is undefined. + Usual Cause: + The following is missing from your appconfig file: + + CONFIGURED_APPS += system/readline + diff --git a/apps/nshlib/nsh.h b/apps/nshlib/nsh.h new file mode 100644 index 0000000000..439c2ffd10 --- /dev/null +++ b/apps/nshlib/nsh.h @@ -0,0 +1,606 @@ +/**************************************************************************** + * apps/nshlib/nsh.h + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_NSHLIB_NSH_H +#define __APPS_NSHLIB_NSH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* The background commands require pthread support */ + +#ifdef CONFIG_DISABLE_PTHREAD +# ifndef CONFIG_NSH_DISABLEBG +# define CONFIG_NSH_DISABLEBG 1 +# endif +#endif + +/* Telnetd requires networking support */ + +#ifndef CONFIG_NET +# undef CONFIG_NSH_TELNET +#endif + +/* One front end must be defined */ + +#if !defined(CONFIG_NSH_CONSOLE) && !defined(CONFIG_NSH_TELNET) +# error "No NSH front end defined" +#endif + +/* If a USB device is selected for the NSH console then we need to handle some + * special start-up conditions. + */ + +#undef HAVE_USB_CONSOLE +#if defined(CONFIG_USBDEV) + +/* Check for a PL2303 serial console. Use console device "/dev/console". */ + +# if defined(CONFIG_PL2303) && defined(CONFIG_PL2303_CONSOLE) +# define HAVE_USB_CONSOLE 1 + +/* Check for a CDC/ACM serial console. Use console device "/dev/console". */ + +# elif defined(CONFIG_CDCACM) && defined(CONFIG_CDCACM_CONSOLE) +# define HAVE_USB_CONSOLE 1 + +/* Check for other USB console. USB console device must be provided in CONFIG_NSH_CONDEV */ + +# elif defined(CONFIG_NSH_USBCONSOLE) +# define HAVE_USB_CONSOLE 1 +# endif +#endif + +/* Defaults for the USB console */ + +#ifdef HAVE_USB_CONSOLE + +/* The default USB console device minor number is 0*/ + +# ifndef CONFIG_NSH_UBSDEV_MINOR +# define CONFIG_NSH_UBSDEV_MINOR 0 +# endif + +/* The default console device is always /dev/console */ + +# ifndef CONFIG_NSH_USBCONDEV +# define CONFIG_NSH_USBCONDEV "/dev/console" +# endif + +/* USB trace settings */ + +#ifdef CONFIG_NSH_USBDEV_TRACEINIT +# define TRACE_INIT_BITS (TRACE_INIT_BIT) +#else +# define TRACE_INIT_BITS (0) +#endif + +#define TRACE_ERROR_BITS (TRACE_DEVERROR_BIT|TRACE_CLSERROR_BIT) + +#ifdef CONFIG_NSH_USBDEV_TRACECLASS +# define TRACE_CLASS_BITS (TRACE_CLASS_BIT|TRACE_CLASSAPI_BIT|TRACE_CLASSSTATE_BIT) +#else +# define TRACE_CLASS_BITS (0) +#endif + +#ifdef CONFIG_NSH_USBDEV_TRACETRANSFERS +# define TRACE_TRANSFER_BITS (TRACE_OUTREQQUEUED_BIT|TRACE_INREQQUEUED_BIT|TRACE_READ_BIT|\ + TRACE_WRITE_BIT|TRACE_COMPLETE_BIT) +#else +# define TRACE_TRANSFER_BITS (0) +#endif + +#ifdef CONFIG_NSH_USBDEV_TRACECONTROLLER +# define TRACE_CONTROLLER_BITS (TRACE_EP_BIT|TRACE_DEV_BIT) +#else +# define TRACE_CONTROLLER_BITS (0) +#endif + +#ifdef CONFIG_NSH_USBDEV_TRACEINTERRUPTS +# define TRACE_INTERRUPT_BITS (TRACE_INTENTRY_BIT|TRACE_INTDECODE_BIT|TRACE_INTEXIT_BIT) +#else +# define TRACE_INTERRUPT_BITS (0) +#endif + +#define TRACE_BITSET (TRACE_INIT_BITS|TRACE_ERROR_BITS|TRACE_CLASS_BITS|\ + TRACE_TRANSFER_BITS|TRACE_CONTROLLER_BITS|TRACE_INTERRUPT_BITS) + +#endif + +/* If Telnet is selected for the NSH console, then we must configure + * the resources used by the Telnet daemon and by the Telnet clients. + * + * CONFIG_NSH_TELNETD_PORT - The telnet daemon will listen on this. + * port. Default: 23 + * CONFIG_NSH_TELNETD_DAEMONPRIO - Priority of the Telnet daemon. + * Default: SCHED_PRIORITY_DEFAULT + * CONFIG_NSH_TELNETD_DAEMONSTACKSIZE - Stack size allocated for the + * Telnet daemon. Default: 2048 + * CONFIG_NSH_TELNETD_CLIENTPRIO- Priority of the Telnet client. + * Default: SCHED_PRIORITY_DEFAULT + * CONFIG_NSH_TELNETD_CLIENTSTACKSIZE - Stack size allocated for the + * Telnet client. Default: 2048 + */ + +#ifndef CONFIG_NSH_TELNETD_PORT +# define CONFIG_NSH_TELNETD_PORT 23 +#endif + +#ifndef CONFIG_NSH_TELNETD_DAEMONPRIO +# define CONFIG_NSH_TELNETD_DAEMONPRIO SCHED_PRIORITY_DEFAULT +#endif + +#ifndef CONFIG_NSH_TELNETD_DAEMONSTACKSIZE +# define CONFIG_NSH_TELNETD_DAEMONSTACKSIZE 2048 +#endif + +#ifndef CONFIG_NSH_TELNETD_CLIENTPRIO +# define CONFIG_NSH_TELNETD_CLIENTPRIO SCHED_PRIORITY_DEFAULT +#endif + +#ifndef CONFIG_NSH_TELNETD_CLIENTSTACKSIZE +# define CONFIG_NSH_TELNETD_CLIENTSTACKSIZE 2048 +#endif + +/* Verify support for ROMFS /etc directory support options */ + +#ifdef CONFIG_NSH_ROMFSETC +# ifdef CONFIG_DISABLE_MOUNTPOINT +# error "Mountpoint support is disabled" +# undef CONFIG_NSH_ROMFSETC +# endif +# if CONFIG_NFILE_DESCRIPTORS < 4 +# error "Not enough file descriptors" +# undef CONFIG_NSH_ROMFSETC +# endif +# ifndef CONFIG_FS_ROMFS +# error "ROMFS support not enabled" +# undef CONFIG_NSH_ROMFSETC +# endif +# ifndef CONFIG_NSH_ROMFSMOUNTPT +# define CONFIG_NSH_ROMFSMOUNTPT "/etc" +# endif +# ifdef CONFIG_NSH_INIT +# ifndef CONFIG_NSH_INITSCRIPT +# define CONFIG_NSH_INITSCRIPT "init.d/rcS" +# endif +# endif +# undef NSH_INITPATH +# define NSH_INITPATH CONFIG_NSH_ROMFSMOUNTPT "/" CONFIG_NSH_INITSCRIPT +# ifndef CONFIG_NSH_ROMFSDEVNO +# define CONFIG_NSH_ROMFSDEVNO 0 +# endif +# ifndef CONFIG_NSH_ROMFSSECTSIZE +# define CONFIG_NSH_ROMFSSECTSIZE 64 +# endif +# define NSECTORS(b) (((b)+CONFIG_NSH_ROMFSSECTSIZE-1)/CONFIG_NSH_ROMFSSECTSIZE) +# define STR_RAMDEVNO(m) #m +# define MKMOUNT_DEVNAME(m) "/dev/ram" STR_RAMDEVNO(m) +# define MOUNT_DEVNAME MKMOUNT_DEVNAME(CONFIG_NSH_ROMFSDEVNO) +#else +# undef CONFIG_NSH_ROMFSMOUNTPT +# undef CONFIG_NSH_INIT +# undef CONFIG_NSH_INITSCRIPT +# undef CONFIG_NSH_ROMFSDEVNO +# undef CONFIG_NSH_ROMFSSECTSIZE +#endif + +/* This is the maximum number of arguments that will be accepted for a command */ + +#define NSH_MAX_ARGUMENTS 6 + +/* strerror() produces much nicer output but is, however, quite large and + * will only be used if CONFIG_NSH_STRERROR is defined. + */ + +#ifdef CONFIG_NSH_STRERROR +# define NSH_ERRNO strerror(errno) +# define NSH_ERRNO_OF(err) strerror(err) +#else +# define NSH_ERRNO (errno) +# define NSH_ERRNO_OF(err) (err) +#endif + +/* Maximum size of one command line (telnet or serial) */ + +#ifndef CONFIG_NSH_LINELEN +# define CONFIG_NSH_LINELEN 80 +#endif + +/* The following two settings are used only in the telnetd interface */ + +#ifndef CONFIG_NSH_IOBUFFER_SIZE +# define CONFIG_NSH_IOBUFFER_SIZE 512 +#endif + +/* The maximum number of nested if-then[-else]-fi sequences that + * are permissable. + */ + +#ifndef CONFIG_NSH_NESTDEPTH +# define CONFIG_NSH_NESTDEPTH 3 +#endif + +/* Define to enable dumping of all input/output buffers */ + +#undef CONFIG_NSH_TELNETD_DUMPBUFFER +#undef CONFIG_NSH_FULLPATH + +/* Make sure that the home directory is defined */ + +#ifndef CONFIG_LIB_HOMEDIR +# define CONFIG_LIB_HOMEDIR "/" +#endif + +/* Stubs used when working directory is not supported */ + +#if CONFIG_NFILE_DESCRIPTORS <= 0 || defined(CONFIG_DISABLE_ENVIRON) +# define nsh_getfullpath(v,p) ((char*)(p)) +# define nsh_freefullpath(p) +#endif + +/* The size of the I/O buffer may be specified in the + * configs/defconfig file -- provided that it is at least as + * large as PATH_MAX. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +# ifdef CONFIG_NSH_FILEIOSIZE +# if CONFIG_NSH_FILEIOSIZE > (PATH_MAX + 1) +# define IOBUFFERSIZE CONFIG_NSH_FILEIOSIZE +# else +# define IOBUFFERSIZE (PATH_MAX + 1) +# endif +# else +# define IOBUFFERSIZE 1024 +# endif +# else +# define IOBUFFERSIZE (PATH_MAX + 1) +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +enum nsh_parser_e +{ + NSH_PARSER_NORMAL = 0, + NSH_PARSER_IF, + NSH_PARSER_THEN, + NSH_PARSER_ELSE +}; + +struct nsh_state_s +{ + uint8_t ns_ifcond : 1; /* Value of command in 'if' statement */ + uint8_t ns_disabled : 1; /* TRUE: Unconditionally disabled */ + uint8_t ns_unused : 4; + uint8_t ns_state : 2; /* Parser state (see enum nsh_parser_e) */ +}; + +struct nsh_parser_s +{ +#ifndef CONFIG_NSH_DISABLEBG + bool np_bg; /* true: The last command executed in background */ +#endif + bool np_redirect; /* true: Output from the last command was re-directed */ + bool np_fail; /* true: The last command failed */ +#ifndef CONFIG_NSH_DISABLESCRIPT + uint8_t np_ndx; /* Current index into np_st[] */ +#endif +#ifndef CONFIG_NSH_DISABLEBG + int np_nice; /* "nice" value applied to last background cmd */ +#endif + + /* This is a stack of parser state information. It supports nested + * execution of commands that span multiple lines (like if-then-else-fi) + */ + +#ifndef CONFIG_NSH_DISABLESCRIPT + struct nsh_state_s np_st[CONFIG_NSH_NESTDEPTH]; +#endif +}; + +struct nsh_vtbl_s; /* Defined in nsh_console.h */ +typedef int (*cmd_t)(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern const char g_nshgreeting[]; +extern const char g_nshprompt[]; +extern const char g_nshsyntax[]; +extern const char g_fmtargrequired[]; +extern const char g_fmtarginvalid[]; +extern const char g_fmtargrange[]; +extern const char g_fmtcmdnotfound[]; +extern const char g_fmtnosuch[]; +extern const char g_fmttoomanyargs[]; +extern const char g_fmtdeepnesting[]; +extern const char g_fmtcontext[]; +extern const char g_fmtcmdfailed[]; +extern const char g_fmtcmdoutofmemory[]; +extern const char g_fmtinternalerror[]; +#ifndef CONFIG_DISABLE_SIGNALS +extern const char g_fmtsignalrecvd[]; +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Initialization */ + +#ifdef CONFIG_NSH_ROMFSETC +int nsh_romfsetc(void); +#else +# define nsh_romfsetc() (-ENOSYS) +#endif + +#ifdef CONFIG_NET +int nsh_netinit(void); +#else +# define nsh_netinit() (-ENOSYS) +#endif + +#ifdef HAVE_USB_CONSOLE +int nsh_usbconsole(void); +#else +# define nsh_usbconsole() (-ENOSYS) +#endif + +#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_NSH_DISABLESCRIPT) +int nsh_script(FAR struct nsh_vtbl_s *vtbl, const char *cmd, const char *path); +#endif + +/* Architecture-specific initialization */ + +#ifdef CONFIG_NSH_ARCHINIT +int nsh_archinitialize(void); +#else +# define nsh_archinitialize() (-ENOSYS) +#endif + +/* Message handler */ + +int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline); + +/* Application interface */ + +#ifdef CONFIG_NSH_BUILTIN_APPS +int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, FAR char **argv); +#endif + +/* Working directory support */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON) +FAR const char *nsh_getcwd(void); +char *nsh_getfullpath(FAR struct nsh_vtbl_s *vtbl, const char *relpath); +void nsh_freefullpath(char *relpath); +#endif + +/* Debug */ + +void nsh_dumpbuffer(FAR struct nsh_vtbl_s *vtbl, const char *msg, + const uint8_t *buffer, ssize_t nbytes); + +/* USB debug support */ + +#if defined(CONFIG_USBDEV_TRACE) && defined(HAVE_USB_CONSOLE) +void nsh_usbtrace(void); +#else +# define nsh_usbtrace() +#endif + +/* Shell command handlers */ + +#ifndef CONFIG_NSH_DISABLE_ECHO + int cmd_echo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif +#ifndef CONFIG_NSH_DISABLE_EXEC + int cmd_exec(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif +#ifndef CONFIG_NSH_DISABLE_MB + int cmd_mb(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif +#ifndef CONFIG_NSH_DISABLE_MH + int cmd_mh(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif +#ifndef CONFIG_NSH_DISABLE_MW + int cmd_mw(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif +#ifndef CONFIG_NSH_DISABLE_FREE + int cmd_free(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif +#ifndef CONFIG_NSH_DISABLE_PS + int cmd_ps(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif +#ifndef CONFIG_NSH_DISABLE_XD + int cmd_xd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif + +#if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_TEST) + int cmd_test(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); + int cmd_lbracket(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif + +#ifndef CONFIG_DISABLE_CLOCK +# if defined (CONFIG_RTC) && !defined(CONFIG_NSH_DISABLE_DATE) + int cmd_date(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +#endif + +#if CONFIG_NFILE_DESCRIPTORS > 0 +# ifndef CONFIG_NSH_DISABLE_CAT + int cmd_cat(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_CP + int cmd_cp(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_DD + int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_LS + int cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# if defined(CONFIG_SYSLOG) && defined(CONFIG_RAMLOG_SYSLOG) && !defined(CONFIG_NSH_DISABLE_DMESG) + int cmd_dmesg(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# if CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_NSH_DISABLESCRIPT) +# ifndef CONFIG_NSH_DISABLE_SH + int cmd_sh(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# endif /* CONFIG_NFILE_STREAMS && !CONFIG_NSH_DISABLESCRIPT */ +# ifndef CONFIG_DISABLE_MOUNTPOINT +# ifndef CONFIG_NSH_DISABLE_LOSETUP + int cmd_losetup(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_MKFIFO + int cmd_mkfifo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifdef CONFIG_FS_READABLE +# ifndef CONFIG_NSH_DISABLE_DF + int cmd_df(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_MOUNT + int cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_UMOUNT + int cmd_umount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifdef CONFIG_FS_WRITABLE +# ifndef CONFIG_NSH_DISABLE_MKDIR + int cmd_mkdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_MKRD + int cmd_mkrd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_MV + int cmd_mv(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_RM + int cmd_rm(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_RMDIR + int cmd_rmdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# endif /* CONFIG_FS_WRITABLE */ +# endif /* CONFIG_FS_READABLE */ +# ifdef CONFIG_FS_FAT +# ifndef CONFIG_NSH_DISABLE_MKFATFS + int cmd_mkfatfs(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# endif /* CONFIG_FS_FAT */ +# endif /* !CONFIG_DISABLE_MOUNTPOINT */ +# if !defined(CONFIG_DISABLE_ENVIRON) +# ifndef CONFIG_NSH_DISABLE_CD + int cmd_cd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_PWD + int cmd_pwd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# endif /* !CONFIG_DISABLE_MOUNTPOINT */ +#endif /* CONFIG_NFILE_DESCRIPTORS */ + +#if defined(CONFIG_NET) +# ifndef CONFIG_NSH_DISABLE_IFCONFIG + int cmd_ifconfig(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0 +# ifndef CONFIG_NSH_DISABLE_GET + int cmd_get(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_PUT + int cmd_put(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +#endif +#if defined(CONFIG_NET_TCP) && CONFIG_NFILE_DESCRIPTORS > 0 +# ifndef CONFIG_NSH_DISABLE_WGET + int cmd_wget(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +#endif +#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \ + !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS) +# ifndef CONFIG_NSH_DISABLE_PING + int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +#endif +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && \ + defined(CONFIG_FS_READABLE) && defined(CONFIG_NFS) +# ifndef CONFIG_NSH_DISABLE_NFSMOUNT + int cmd_nfsmount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +#endif +#endif + +#ifndef CONFIG_DISABLE_ENVIRON +# ifndef CONFIG_NSH_DISABLE_SET + int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_UNSET + int cmd_unset(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +#endif /* CONFIG_DISABLE_ENVIRON */ + +#ifndef CONFIG_DISABLE_SIGNALS +# ifndef CONFIG_NSH_DISABLE_KILL + int cmd_kill(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_SLEEP + int cmd_sleep(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +# ifndef CONFIG_NSH_DISABLE_USLEEP + int cmd_usleep(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +# endif +#endif /* CONFIG_DISABLE_SIGNALS */ + +#endif /* __APPS_NSHLIB_NSH_H */ diff --git a/apps/nshlib/nsh_apps.c b/apps/nshlib/nsh_apps.c new file mode 100644 index 0000000000..e335c2e2c2 --- /dev/null +++ b/apps/nshlib/nsh_apps.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * apps/nshlib/nsh_apps.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_SCHED_WAITPID +# include +#endif + +#include +#include +#include + +#include + +#include "nsh.h" +#include "nsh_console.h" + +#ifdef CONFIG_NSH_BUILTIN_APPS + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_execapp + * + * Description: + * Attempt to execute the application task whose name is 'cmd' + * + * Returned Value: + * <0 If exec_namedapp() fails, then the negated errno value + * is returned. + * -1 (ERROR) if the application task corresponding to 'cmd' could not + * be started (possibly because it doesn not exist). + * 0 (OK) if the application task corresponding to 'cmd' was + * and successfully started. If CONFIG_SCHED_WAITPID is + * defined, this return value also indicates that the + * application returned successful status (EXIT_SUCCESS) + * 1 If CONFIG_SCHED_WAITPID is defined, then this return value + * indicates that the application task was spawned successfully + * but returned failure exit status. + * + ****************************************************************************/ + +int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, + FAR char **argv) +{ + int ret = OK; + + /* Lock the scheduler to prevent the application from running until the + * waitpid() has been called. + */ + + sched_lock(); + + /* Try to find and execute the command within the list of builtin + * applications. + */ + + ret = exec_namedapp(cmd, (FAR const char **)argv); + if (ret >= 0) + { + /* The application was successfully started (but still blocked because the + * scheduler is locked). If the application was not backgrounded, then we + * need to wait here for the application to exit. + */ + +#ifdef CONFIG_SCHED_WAITPID + if (vtbl->np.np_bg == false) + { + int rc = 0; + + /* Wait for the application to exit. Since we have locked the + * scheduler above, we know that the application has not yet + * started and there is no possibility that it has already exited. + * The scheduler will be unlocked while waitpid is waiting and the + * application will be able to run. + */ + + ret = waitpid(ret, &rc, 0); + if (ret >= 0) + { + /* We can't return the exact status (nsh has nowhere to put it) + * so just pass back zero/nonzero in a fashion that doesn't look + * like an error. + */ + + ret = (rc == 0) ? OK : 1; + + /* TODO: Set the environment variable '?' to a string corresponding + * to WEXITSTATUS(rc) so that $? will expand to the exit status of + * the most recently executed task. + */ + } + } + else +#endif + { + struct sched_param param; + sched_getparam(0, ¶m); + nsh_output(vtbl, "%s [%d:%d]\n", cmd, ret, param.sched_priority); + + /* Backgrounded commands always 'succeed' as long as we can start + * them. + */ + + ret = OK; + } + } + + sched_unlock(); + + /* If exec_namedapp() or waitpid() failed, then return the negated errno + * value. + */ + + if (ret < 0) + { + return -errno; + } + + return ret; +} + +#endif /* CONFIG_NSH_BUILTIN_APPS */ diff --git a/apps/nshlib/nsh_console.c b/apps/nshlib/nsh_console.c new file mode 100644 index 0000000000..b066e71f53 --- /dev/null +++ b/apps/nshlib/nsh_console.c @@ -0,0 +1,432 @@ +/**************************************************************************** + * apps/nshlib/nsh_serial.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nsh.h" +#include "nsh_console.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct serialsave_s +{ + int cn_outfd; /* Re-directed output file descriptor */ + FILE *cn_outstream; /* Re-directed output stream */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLEBG +static FAR struct nsh_vtbl_s *nsh_consoleclone(FAR struct nsh_vtbl_s *vtbl); +#endif +static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl); +static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s *vtbl, FAR const void *buffer, size_t nbytes); +static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...); +static FAR char *nsh_consolelinebuffer(FAR struct nsh_vtbl_s *vtbl); +static void nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t *save); +static void nsh_consoleundirect(FAR struct nsh_vtbl_s *vtbl, FAR uint8_t *save); +static void nsh_consoleexit(FAR struct nsh_vtbl_s *vtbl, int exitstatus); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_openifnotopen + ****************************************************************************/ + +static int nsh_openifnotopen(struct console_stdio_s *pstate) +{ + /* The stream is open in a lazy fashion. This is done because the file + * descriptor may be opened on a different task than the stream. + */ + + if (!pstate->cn_outstream) + { + pstate->cn_outstream = fdopen(pstate->cn_outfd, "w"); + if (!pstate->cn_outstream) + { + return ERROR; + } + } + return 0; +} + +/**************************************************************************** + * Name: nsh_closeifnotclosed + * + * Description: + * Close the output stream if it is not the standard output stream. + * + ****************************************************************************/ + +static void nsh_closeifnotclosed(struct console_stdio_s *pstate) +{ + if (pstate->cn_outstream == OUTSTREAM(pstate)) + { + fflush(OUTSTREAM(pstate)); + pstate->cn_outfd = OUTFD(pstate); + } + else + { + if (pstate->cn_outstream) + { + fflush(pstate->cn_outstream); + fclose(pstate->cn_outstream); + } + else if (pstate->cn_outfd >= 0 && pstate->cn_outfd != OUTFD(pstate)) + { + close(pstate->cn_outfd); + } + + pstate->cn_outfd = -1; + pstate->cn_outstream = NULL; + } +} + +/**************************************************************************** + * Name: nsh_consolewrite + * + * Description: + * write a buffer to the remote shell window. + * + * Currently only used by cat. + * + ****************************************************************************/ + +static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s *vtbl, FAR const void *buffer, size_t nbytes) +{ + FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl; + ssize_t ret; + + /* The stream is open in a lazy fashion. This is done because the file + * descriptor may be opened on a different task than the stream. The + * actual open will then occur with the first output from the new task. + */ + + if (nsh_openifnotopen(pstate) != 0) + { + return (ssize_t)ERROR; + } + + /* Write the data to the output stream */ + + ret = fwrite(buffer, 1, nbytes, pstate->cn_outstream); + if (ret < 0) + { + dbg("[%d] Failed to send buffer: %d\n", pstate->cn_outfd, errno); + } + return ret; +} + +/**************************************************************************** + * Name: nsh_consoleoutput + * + * Description: + * Print a string to the currently selected stream. + * + ****************************************************************************/ + +static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...) +{ + FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl; + va_list ap; + int ret; + + /* The stream is open in a lazy fashion. This is done because the file + * descriptor may be opened on a different task than the stream. The + * actual open will then occur with the first output from the new task. + */ + + if (nsh_openifnotopen(pstate) != 0) + { + return ERROR; + } + + va_start(ap, fmt); + ret = vfprintf(pstate->cn_outstream, fmt, ap); + va_end(ap); + + return ret; +} + +/**************************************************************************** + * Name: nsh_consolelinebuffer + * + * Description: + * Return a reference to the current line buffer + * + ****************************************************************************/ + +static FAR char *nsh_consolelinebuffer(FAR struct nsh_vtbl_s *vtbl) +{ + FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl; + return pstate->cn_line; +} + +/**************************************************************************** + * Name: nsh_consoleclone + * + * Description: + * Make an independent copy of the vtbl + * + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLEBG +static FAR struct nsh_vtbl_s *nsh_consoleclone(FAR struct nsh_vtbl_s *vtbl) +{ + FAR struct console_stdio_s *pclone = nsh_newconsole(); + return &pclone->cn_vtbl; +} +#endif + +/**************************************************************************** + * Name: nsh_consolerelease + * + * Description: + * Release the cloned instance + * + ****************************************************************************/ + +static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl) +{ + FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl; + + /* Close the output stream */ + + nsh_closeifnotclosed(pstate); + + /* Close the console stream */ + +#ifdef CONFIG_NSH_CONDEV + (void)fclose(pstate->cn_constream); +#endif + + /* Then release the vtable container */ + + free(pstate); +} + +/**************************************************************************** + * Name: nsh_consoleredirect + * + * Description: + * Set up for redirected output. This function is called from nsh_parse() + * in two different contexts: + * + * 1) Redirected background commands of the form: command > xyz.text & + * + * In this case: + * - vtbl: A newly allocated and initialized instance created by + * nsh_consoleclone, + * - fd:- The file descriptor of the redirected output + * - save: NULL + * + * nsh_consolerelease() will perform the clean-up when the clone is + * destroyed. + * + * 2) Redirected foreground commands of the form: command > xyz.txt + * + * In this case: + * - vtbl: The current state structure, + * - fd: The file descriptor of the redirected output + * - save: Where to save the re-directed registers. + * + * nsh_consoleundirect() will perform the clean-up after the redirected + * command completes. + * + ****************************************************************************/ + +static void nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t *save) +{ + FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl; + FAR struct serialsave_s *ssave = (FAR struct serialsave_s *)save; + + /* Case 1: Redirected foreground commands */ + + if (ssave) + { + /* pstate->cn_outstream and cn_outfd refer refer to the + * currently opened output stream. If the output stream is open, flush + * any pending output. + */ + + if (pstate->cn_outstream) + { + fflush(pstate->cn_outstream); + } + + /* Save the current fd and stream values. These will be restored + * when nsh_consoleundirect() is called. + */ + + ssave->cn_outfd = pstate->cn_outfd; + ssave->cn_outstream = pstate->cn_outstream; + } + else + { + /* nsh_consoleclone() set pstate->cn_outfd and cn_outstream to refer + * to standard out. We just want to leave these alone and overwrite + * them with the fd for the re-directed stream. + */ + } + + /* In either case, set the fd of the new, re-directed output and nullify + * the output stream (it will be fdopen'ed if it is used). + */ + + pstate->cn_outfd = fd; + pstate->cn_outstream = NULL; +} + +/**************************************************************************** + * Name: nsh_consoleundirect + * + * Description: + * Set up for redirected output + * + ****************************************************************************/ + +static void nsh_consoleundirect(FAR struct nsh_vtbl_s *vtbl, FAR uint8_t *save) +{ + FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl; + FAR struct serialsave_s *ssave = (FAR struct serialsave_s *)save; + + nsh_closeifnotclosed(pstate); + pstate->cn_outfd = ssave->cn_outfd; + pstate->cn_outstream = ssave->cn_outstream; +} + +/**************************************************************************** + * Name: nsh_consoleexit + * + * Description: + * Exit the shell task + * + ****************************************************************************/ + +static void nsh_consoleexit(FAR struct nsh_vtbl_s *vtbl, int exitstatus) +{ + /* Destroy ourself then exit with the provided status */ + + nsh_consolerelease(vtbl); + exit(exitstatus); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_newconsole + ****************************************************************************/ + +FAR struct console_stdio_s *nsh_newconsole(void) +{ + struct console_stdio_s *pstate = (struct console_stdio_s *)zalloc(sizeof(struct console_stdio_s)); + if (pstate) + { + /* Initialize the call table */ + +#ifndef CONFIG_NSH_DISABLEBG + pstate->cn_vtbl.clone = nsh_consoleclone; + pstate->cn_vtbl.release = nsh_consolerelease; +#endif + pstate->cn_vtbl.write = nsh_consolewrite; + pstate->cn_vtbl.output = nsh_consoleoutput; + pstate->cn_vtbl.linebuffer = nsh_consolelinebuffer; + pstate->cn_vtbl.redirect = nsh_consoleredirect; + pstate->cn_vtbl.undirect = nsh_consoleundirect; + pstate->cn_vtbl.exit = nsh_consoleexit; + + /* (Re-) open the console input device */ + +#ifdef CONFIG_NSH_CONDEV + pstate->cn_confd = open(CONFIG_NSH_CONDEV, O_RDWR); + if (pstate->cn_confd < 0) + { + free(pstate); + return NULL; + } + + /* Create a standard C stream on the console device */ + + pstate->cn_constream = fdopen(pstate->cn_confd, "r+"); + if (!pstate->cn_constream) + { + close(pstate->cn_confd); + free(pstate); + return NULL; + } +#endif + + /* Initialize the output stream */ + + pstate->cn_outfd = OUTFD(pstate); + pstate->cn_outstream = OUTSTREAM(pstate); + } + return pstate; +} diff --git a/apps/nshlib/nsh_console.h b/apps/nshlib/nsh_console.h new file mode 100644 index 0000000000..8abf9154b0 --- /dev/null +++ b/apps/nshlib/nsh_console.h @@ -0,0 +1,159 @@ +/**************************************************************************** + * apps/nshlib/nsh_console.h + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_NSHLIB_NSH_CONSOLE_H +#define __APPS_NSHLIB_NSH_CONSOLE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Method access macros */ + +#define nsh_clone(v) (v)->clone(v) +#define nsh_release(v) (v)->release(v) +#define nsh_write(v,b,n) (v)->write(v,b,n) +#define nsh_linebuffer(v) (v)->linebuffer(v) +#define nsh_redirect(v,f,s) (v)->redirect(v,f,s) +#define nsh_undirect(v,s) (v)->undirect(v,s) +#define nsh_exit(v,s) (v)->exit(v,s) + +#ifdef CONFIG_CPP_HAVE_VARARGS +# define nsh_output(v, fmt...) (v)->output(v, ##fmt) +#else +# define nsh_output vtbl->output +#endif + +/* Size of info to be saved in call to nsh_redirect */ + +#define SAVE_SIZE (sizeof(int) + sizeof(FILE*) + sizeof(bool)) + +/* Are we using the NuttX console for I/O? Or some other character device? */ + +#ifdef CONFIG_NSH_CONDEV +# define INFD(p) ((p)->cn_confd) +# define INSTREAM(p) ((p)->cn_constream) +# define OUTFD(p) ((p)->cn_confd) +# define OUTSTREAM(p) ((p)->cn_constream) +#else +# define INFD(p) 0 +# define INSTREAM(p) stdin +# define OUTFD(p) 1 +# define OUTSTREAM(p) stdout +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* This describes a generic console front-end */ + +struct nsh_vtbl_s +{ + /* This function pointers are "hooks" into the front end logic to + * handle things like output of command results, redirection, etc. + * -- all of which must be done in a way that is unique to the nature + * of the front end. + */ + +#ifndef CONFIG_NSH_DISABLEBG + FAR struct nsh_vtbl_s *(*clone)(FAR struct nsh_vtbl_s *vtbl); + void (*addref)(FAR struct nsh_vtbl_s *vtbl); + void (*release)(FAR struct nsh_vtbl_s *vtbl); +#endif + ssize_t (*write)(FAR struct nsh_vtbl_s *vtbl, FAR const void *buffer, size_t nbytes); + int (*output)(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...); + FAR char *(*linebuffer)(FAR struct nsh_vtbl_s *vtbl); + void (*redirect)(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t *save); + void (*undirect)(FAR struct nsh_vtbl_s *vtbl, FAR uint8_t *save); + void (*exit)(FAR struct nsh_vtbl_s *vtbl, int exitstatus); + + /* Parser state data */ + + struct nsh_parser_s np; +}; + +/* This structure describes a console front-end that is based on stdin and + * stdout (which is all of the supported console types at the time being). + */ + +struct console_stdio_s +{ + /* NSH front-end call table */ + + struct nsh_vtbl_s cn_vtbl; + + /* NSH input/output streams */ + +#ifdef CONFIG_NSH_CONDEV + int cn_confd; /* Console I/O file descriptor */ +#endif + int cn_outfd; /* Output file descriptor (possibly redirected) */ +#ifdef CONFIG_NSH_CONDEV + FILE *cn_constream; /* Console I/O stream (possibly redirected) */ +#endif + FILE *cn_outstream; /* Output stream */ + + /* Line input buffer */ + + char cn_line[CONFIG_NSH_LINELEN]; +}; + + + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Defined in nsh_console.c *************************************************/ + +FAR struct console_stdio_s *nsh_newconsole(void); + +#endif /* __APPS_NSHLIB_NSH_CONSOLE_H */ diff --git a/apps/nshlib/nsh_consolemain.c b/apps/nshlib/nsh_consolemain.c new file mode 100644 index 0000000000..baf2e74b4d --- /dev/null +++ b/apps/nshlib/nsh_consolemain.c @@ -0,0 +1,169 @@ +/**************************************************************************** + * apps/nshlib/nsh_consolemain.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "nsh.h" +#include "nsh_console.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_consolemain + * + * Description: + * This interfaces maybe to called or started with task_start to start a + * single an NSH instance that operates on stdin and stdout (/dev/console). + * This function does not return. + * + * Input Parameters: + * Standard task start-up arguements. These are not used. argc may be + * zero and argv may be NULL. + * + * Returned Values: + * This function does not normally return. exit() is usually called to + * terminate the NSH session. This function will return in the event of + * an error. In that case, a nonzero value is returned (1). + * + ****************************************************************************/ + +int nsh_consolemain(int argc, char *argv[]) +{ + FAR struct console_stdio_s *pstate = nsh_newconsole(); + DEBUGASSERT(pstate); + int ret; + + /* If we are using a USB serial console, then we will have to wait for the + * USB to be connected to the host. + */ + +#ifdef HAVE_USB_CONSOLE + ret = nsh_usbconsole(); + DEBUGASSERT(ret == OK); +#endif + + /* Present a greeting */ + + fputs(g_nshgreeting, pstate->cn_outstream); + fflush(pstate->cn_outstream); + + /* Execute the startup script */ + +#ifdef CONFIG_NSH_ROMFSETC + (void)nsh_script(&pstate->cn_vtbl, "init", NSH_INITPATH); +#endif + + /* Then enter the command line parsing loop */ + + for (;;) + { + /* For the case of debugging the USB console... dump collected USB trace data */ + + nsh_usbtrace(); + + /* Display the prompt string */ + + fputs(g_nshprompt, pstate->cn_outstream); + fflush(pstate->cn_outstream); + + /* Get the next line of input */ + + ret = readline(pstate->cn_line, CONFIG_NSH_LINELEN, + INSTREAM(pstate), OUTSTREAM(pstate)); + if (ret > 0) + { + /* Parse process the command */ + + (void)nsh_parse(&pstate->cn_vtbl, pstate->cn_line); + fflush(pstate->cn_outstream); + } + + /* Readline normally returns the number of characters read, + * but will return 0 on end of file or a negative value + * if an error occurs. Either will cause the session to + * terminate. + */ + + else + { + fprintf(pstate->cn_outstream, g_fmtcmdfailed, "nsh_consolemain", + "readline", NSH_ERRNO_OF(-ret)); + nsh_exit(&pstate->cn_vtbl, 1); + } + } + + /* Clean up */ + + nsh_exit(&pstate->cn_vtbl, 0); + + /* We do not get here, but this is necessary to keep some compilers happy */ + + return OK; +} diff --git a/apps/nshlib/nsh_dbgcmds.c b/apps/nshlib/nsh_dbgcmds.c new file mode 100644 index 0000000000..384b377f3a --- /dev/null +++ b/apps/nshlib/nsh_dbgcmds.c @@ -0,0 +1,355 @@ +/**************************************************************************** + * apps/nshlib/dbg_dbgcmds.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "nsh.h" +#include "nsh_console.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct dbgmem_s +{ + bool dm_write; /* true: perfrom write operation */ + void *dm_addr; /* Address to access */ + uint32_t dm_value; /* Value to write */ + unsigned int dm_count; /* The number of bytes to access */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mem_parse + ****************************************************************************/ + +int mem_parse(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv, + struct dbgmem_s *mem) +{ + char *pcvalue = strchr(argv[1], '='); + unsigned long lvalue = 0; + + /* Check if we are writing a value */ + + if (pcvalue) + { + *pcvalue = '\0'; + pcvalue++; + + lvalue = (unsigned long)strtol(pcvalue, NULL, 16); + if (lvalue > 0xffffffff) + { + return -EINVAL; + } + + mem->dm_write = true; + mem->dm_value = (uint32_t)lvalue; + } + else + { + mem->dm_write = false; + mem->dm_value = 0; + } + + /* Get the address to be accessed */ + + mem->dm_addr = (void*)((uintptr_t)strtol(argv[1], NULL, 16)); + + /* Get the number of bytes to access */ + + if (argc > 2) + { + mem->dm_count = (unsigned int)strtol(argv[2], NULL, 16); + } + else + { + mem->dm_count = 1; + } + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cmd_mb + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_MB +int cmd_mb(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + struct dbgmem_s mem; + volatile uint8_t *ptr; + int ret; + int i; + + ret = mem_parse(vtbl, argc, argv, &mem); + if (ret == 0) + { + /* Loop for the number of requested bytes */ + + for (i = 0, ptr = (volatile uint8_t*)mem.dm_addr; i < mem.dm_count; i++, ptr++) + { + /* Print the value at the address */ + + nsh_output(vtbl, " %p = 0x%02x", ptr, *ptr); + + /* Are we supposed to write a value to this address? */ + + if (mem.dm_write) + { + /* Yes, was the supplied value within range? */ + + if (mem.dm_value > 0x000000ff) + { + nsh_output(vtbl, g_fmtargrange, argv[0]); + return ERROR; + } + + /* Write the value and re-read the address so that we print its + * current value (if the address is a process address, then the + * value read might not necessarily be the value written). + */ + + *ptr = (uint8_t)mem.dm_value; + nsh_output(vtbl, " -> 0x%02x", *ptr); + } + + /* Make sure we end it with a newline */ + + nsh_output(vtbl, "\n", *ptr); + } + } + return ret; +} +#endif + +/**************************************************************************** + * Name: cmd_mh + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_MH +int cmd_mh(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + struct dbgmem_s mem; + volatile uint16_t *ptr; + int ret; + int i; + + ret = mem_parse(vtbl, argc, argv, &mem); + if (ret == 0) + { + /* Loop for the number of requested bytes */ + + for (i = 0, ptr = (volatile uint16_t*)mem.dm_addr; i < mem.dm_count; i += 2, ptr++) + { + /* Print the value at the address */ + + nsh_output(vtbl, " %p = 0x%04x", ptr, *ptr); + + /* Are we supposed to write a value to this address? */ + + if (mem.dm_write) + { + /* Yes, was the supplied value within range? */ + + if (mem.dm_value > 0x0000ffff) + { + nsh_output(vtbl, g_fmtargrange, argv[0]); + return ERROR; + } + + /* Write the value and re-read the address so that we print its + * current value (if the address is a process address, then the + * value read might not necessarily be the value written). + */ + + *ptr = (uint16_t)mem.dm_value; + nsh_output(vtbl, " -> 0x%04x", *ptr); + } + + /* Make sure we end it with a newline */ + + nsh_output(vtbl, "\n", *ptr); + } + } + return ret; +} +#endif + +/**************************************************************************** + * Name: cmd_mw + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_MW +int cmd_mw(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + struct dbgmem_s mem; + volatile uint32_t *ptr; + int ret; + int i; + + ret = mem_parse(vtbl, argc, argv, &mem); + if (ret == 0) + { + /* Loop for the number of requested bytes */ + + for (i = 0, ptr = (volatile uint32_t*)mem.dm_addr; i < mem.dm_count; i += 4, ptr++) + { + /* Print the value at the address */ + + nsh_output(vtbl, " %p = 0x%08x", ptr, *ptr); + + /* Are we supposed to write a value to this address? */ + + if (mem.dm_write) + { + /* Write the value and re-read the address so that we print its + * current value (if the address is a process address, then the + * value read might not necessarily be the value written). + */ + + *ptr = mem.dm_value; + nsh_output(vtbl, " -> 0x%08x", *ptr); + } + + /* Make sure we end it with a newline */ + + nsh_output(vtbl, "\n", *ptr); + } + } + return ret; +} +#endif + +/**************************************************************************** + * Name: nsh_dumpbuffer + ****************************************************************************/ + +void nsh_dumpbuffer(FAR struct nsh_vtbl_s *vtbl, const char *msg, + const uint8_t *buffer, ssize_t nbytes) +{ + char line[128]; + int ch; + int i; + int j; + + nsh_output(vtbl, "%s:\n", msg); + for (i = 0; i < nbytes; i += 16) + { + sprintf(line, "%04x: ", i); + + for ( j = 0; j < 16; j++) + { + if (i + j < nbytes) + { + sprintf(&line[strlen(line)], "%02x ", buffer[i+j] ); + } + else + { + strcpy(&line[strlen(line)], " "); + } + } + + for ( j = 0; j < 16; j++) + { + if (i + j < nbytes) + { + ch = buffer[i+j]; + sprintf(&line[strlen(line)], "%c", ch >= 0x20 && ch <= 0x7e ? ch : '.'); + } + } + nsh_output(vtbl, "%s\n", line); + } +} + +/**************************************************************************** + * Name: cmd_xd + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_XD +int cmd_xd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + FAR char *addr; + FAR char *endptr; + int nbytes; + + addr = (char*)((uintptr_t)strtol(argv[1], &endptr, 16)); + if (argv[0][0] == '\0' || *endptr != '\0') + { + return ERROR; + } + + nbytes = (int)strtol(argv[2], &endptr, 0); + if (argv[0][0] == '\0' || *endptr != '\0' || nbytes < 0) + { + return ERROR; + } + + nsh_dumpbuffer(vtbl, "Hex dump", (uint8_t*)addr, nbytes); + return OK; +} +#endif diff --git a/apps/nshlib/nsh_ddcmd.c b/apps/nshlib/nsh_ddcmd.c new file mode 100644 index 0000000000..40a3710b1a --- /dev/null +++ b/apps/nshlib/nsh_ddcmd.c @@ -0,0 +1,643 @@ +/**************************************************************************** + * apps/nshlib/nsh_ddcmd.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "nsh.h" +#include "nsh_console.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_NSH_DISABLE_DD) + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* If no sector size is specified wity BS=, then the following default value + * is used. + */ + +#define DEFAULT_SECTSIZE 512 + +/* At present, piping of input and output are not support, i.e., both of= + * and if= arguments are required. + */ + +#undef CAN_PIPE_FROM_STD + +/* Function pointer calls are only need if block drivers are supported + * (or, rather, if mount points are supported in the file system) + */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT +# define DD_INFD ((dd)->inf.fd) +# define DD_INHANDLE ((dd)->inf.handle) +# define DD_OUTFD ((dd)->outf.fd) +# define DD_OUTHANDLE ((dd)->outf.handle) +# define DD_READ(dd) ((dd)->infread(dd)) +# define DD_WRITE(dd) ((dd)->outfwrite(dd)) +# define DD_INCLOSE(dd) ((dd)->infclose(dd)) +# define DD_OUTCLOSE(dd) ((dd)->outfclose(dd)) +#else +# define DD_INFD ((dd)->infd) +# undef DD_INHANDLE +# define DD_OUTFD ((dd)->outfd) +# undef DD_OUTHANDLE +# define DD_READ(dd) dd_readch(dd) +# define DD_WRITE(dd) dd_writech(dd) +# define DD_INCLOSE(dd) dd_infclosech(dd) +# define DD_OUTCLOSE(dd) dd_outfclosech(dd) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct dd_s +{ + FAR struct nsh_vtbl_s *vtbl; + +#ifndef CONFIG_DISABLE_MOUNTPOINT + union + { + FAR void *handle; /* BCH lib handle for block device*/ + int fd; /* File descriptor of the character device */ + } inf; +#else + int infd; /* File descriptor of the input device */ +#endif + +#ifndef CONFIG_DISABLE_MOUNTPOINT + union + { + FAR void *handle; /* BCH lib handle for block device*/ + int fd; /* File descriptor of the character device */ + } outf; +#else + int outfd; /* File descriptor of the output device */ +#endif + + uint32_t nsectors; /* Number of sectors to transfer */ + uint32_t sector; /* The current sector number */ + uint32_t skip; /* The number of sectors skipped on input */ + bool eof; /* true: The of the input or output file has been hit */ + uint16_t sectsize; /* Size of one sector */ + uint16_t nbytes; /* Number of valid bytes in the buffer */ + uint8_t *buffer; /* Buffer of data to write to the output file */ + + /* Function pointers to handle differences between block and character devices */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + int (*infread)(struct dd_s *dd); + void (*infclose)(struct dd_s *dd); + int (*outfwrite)(struct dd_s *dd); + void (*outfclose)(struct dd_s *dd); +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char g_dd[] = "dd"; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dd_outfcloseblk + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_MOUNTPOINT +static void dd_outfcloseblk(struct dd_s *dd) +{ + (void)bchlib_teardown(DD_OUTHANDLE); +} +#endif + + +/**************************************************************************** + * Name: dd_outfclosech + ****************************************************************************/ + +static void dd_outfclosech(struct dd_s *dd) +{ + (void)close(DD_OUTFD); +} + +/**************************************************************************** + * Name: dd_infcloseblk + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_MOUNTPOINT +static void dd_infcloseblk(struct dd_s *dd) +{ + (void)bchlib_teardown(DD_INHANDLE); +} +#endif + +/**************************************************************************** + * Name: dd_infclosech + ****************************************************************************/ + +static void dd_infclosech(struct dd_s *dd) +{ + (void)close(DD_INFD); +} + +/**************************************************************************** + * Name: dd_writeblk + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_MOUNTPOINT +static int dd_writeblk(struct dd_s *dd) +{ + ssize_t nbytes; + off_t offset = (dd->sector - dd->skip) * dd->sectsize; + + /* Write the sector at the specified offset */ + + nbytes = bchlib_write(DD_OUTHANDLE, (char*)dd->buffer, offset, dd->sectsize); + if (nbytes < 0) + { + /* bchlib_write return -EFBIG on attempts to write past the end of + * the device. + */ + + if (nbytes == -EFBIG) + { + dd->eof = true; /* Set end-of-file */ + } + else + { + FAR struct nsh_vtbl_s *vtbl = dd->vtbl; + nsh_output(vtbl, g_fmtcmdfailed, g_dd, "bshlib_write", NSH_ERRNO_OF(-nbytes)); + return ERROR; + } + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: dd_writech + ****************************************************************************/ + +static int dd_writech(struct dd_s *dd) +{ + uint8_t *buffer = dd->buffer; + uint16_t written ; + ssize_t nbytes; + + /* Is the out buffer full (or is this the last one)? */ + + written = 0; + do + { + nbytes = write(DD_OUTFD, buffer, dd->sectsize - written); + if (nbytes < 0) + { + FAR struct nsh_vtbl_s *vtbl = dd->vtbl; + nsh_output(vtbl, g_fmtcmdfailed, g_dd, "write", NSH_ERRNO_OF(-nbytes)); + return ERROR; + } + + written += nbytes; + buffer += nbytes; + } + while (written < dd->sectsize); + + return OK; +} + +/**************************************************************************** + * Name: dd_readblk + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_MOUNTPOINT +static int dd_readblk(struct dd_s *dd) +{ + ssize_t nbytes; + off_t offset = dd->sector * dd->sectsize; + + nbytes = bchlib_read(DD_INHANDLE, (char*)dd->buffer, offset, dd->sectsize); + if (nbytes < 0) + { + FAR struct nsh_vtbl_s *vtbl = dd->vtbl; + nsh_output(vtbl, g_fmtcmdfailed, g_dd, "bshlib_read", NSH_ERRNO_OF(-nbytes)); + return ERROR; + } + + /* bchlib_read return 0 on attempts to write past the end of the device. */ + + dd->nbytes = nbytes; + dd->eof = (nbytes == 0); + return OK; +} +#endif + +/**************************************************************************** + * Name: dd_readch + ****************************************************************************/ + +static int dd_readch(struct dd_s *dd) +{ + uint8_t *buffer = dd->buffer; + ssize_t nbytes; + + dd->nbytes = 0; + do + { + nbytes = read(DD_INFD, buffer, dd->sectsize - dd->nbytes); + if (nbytes < 0) + { + FAR struct nsh_vtbl_s *vtbl = dd->vtbl; + nsh_output(vtbl, g_fmtcmdfailed, g_dd, "read", NSH_ERRNO_OF(-nbytes)); + return ERROR; + } + + dd->nbytes += nbytes; + buffer += nbytes; + } + while (dd->nbytes < dd->sectsize && nbytes > 0); + + dd->eof |= (dd->nbytes == 0); + return OK; +} + +/**************************************************************************** + * Name: dd_infopen + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_MOUNTPOINT +static int dd_filetype(const char *filename) +{ + struct stat sb; + int ret; + + /* Get the type of the file */ + + ret = stat(filename, &sb); + if (ret < 0) + { + return ERROR; /* Return -1 on failure */ + } + + return S_ISBLK(sb.st_mode); /* Return true(1) if block, false(0) if char */ +} +#endif + +/**************************************************************************** + * Name: dd_infopen + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_MOUNTPOINT +static inline int dd_infopen(const char *name, struct dd_s *dd) +{ + FAR struct nsh_vtbl_s *vtbl = dd->vtbl; + int ret; + int type; + + /* Get the type of the input file */ + + type = dd_filetype(name); + if (type < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, g_dd, "stat", NSH_ERRNO_OF(-type)); + return type; + } + + /* Open the input file */ + + if (!type) + { + DD_INFD = open(name, O_RDONLY); + if (DD_INFD < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO); + return ERROR; + } + + dd->infread = dd_readch; /* Character oriented read */ + dd->infclose = dd_infclosech; + } + else + { + ret = bchlib_setup(name, true, &DD_INHANDLE); + if (ret < 0) + { + return ERROR; + } + + dd->infread = dd_readblk; + dd->infclose = dd_infcloseblk; + } + return OK; +} +#else +static inline int dd_infopen(const char *name, struct dd_s *dd) +{ + DD_INFD = open(name, O_RDONLY); + if (DD_INFD < 0) + { + FAR struct nsh_vtbl_s *vtbl = dd->vtbl; + nsh_output(vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO); + return ERROR; + } + return OK; +} +#endif + +/**************************************************************************** + * Name: dd_outfopen + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_MOUNTPOINT +static inline int dd_outfopen(const char *name, struct dd_s *dd) +{ + int type; + int ret = OK; + + /* Get the type of the output file */ + + type = dd_filetype(name); + + /* Open the block driver for input */ + + if (type == true) + { + ret = bchlib_setup(name, true, &DD_OUTHANDLE); + if (ret < 0) + { + return ERROR; + } + + dd->outfwrite = dd_writeblk; /* Block oriented write */ + dd->outfclose = dd_outfcloseblk; + } + + /* Otherwise, the file is character oriented or does not exist */ + + else + { + DD_OUTFD = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (DD_OUTFD < 0) + { + FAR struct nsh_vtbl_s *vtbl = dd->vtbl; + nsh_output(vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO); + return ERROR; + } + + dd->outfwrite = dd_writech; /* Character oriented write */ + dd->outfclose = dd_outfclosech; + } + return OK; +} +#else +static inline int dd_outfopen(const char *name, struct dd_s *dd) +{ + DD_OUTFD = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (DD_OUTFD < 0) + { + nsh_output(dd->vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO); + return ERROR; + } + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cmd_dd + ****************************************************************************/ + +int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + struct dd_s dd; + char *infile = NULL; + char *outfile = NULL; + int ret = ERROR; + int i; + + /* Initialize the dd structure */ + + memset(&dd, 0, sizeof(struct dd_s)); + dd.vtbl = vtbl; /* For nsh_output */ + dd.sectsize = DEFAULT_SECTSIZE; /* Sector size if 'bs=' not provided */ + dd.nsectors = 0xffffffff; /* MAX_UINT32 */ + + /* If no IF= option is provided on the command line, then read + * from stdin. + */ + +#ifdef CAN_PIPE_FROM_STD + DD_INFD = 0; /* stdin */ +#ifndef CONFIG_NSH_DISABLE_DD + dd.infread = readch; /* Character oriented read */ + dd.infclose = noclose; /* Don't close stdin */ +#endif +#endif + /* If no OF= option is provided on the command line, then write + * to stdout. + */ + +#ifdef CAN_PIPE_FROM_STD + DD_OUTDF = 1; /* stdout */ +#ifndef CONFIG_NSH_DISABLE_DD + dd.outfwrite = writech; /* Character oriented write */ + dd.outfclose = noclose; /* Don't close stdout */ +#endif +#endif + + /* Parse command line parameters */ + + for (i = 1; i < argc; i++) + { + if (strncmp(argv[i], "if=", 3) == 0) + { + infile = nsh_getfullpath(vtbl, &argv[i][3]); + } + else if (strncmp(argv[i], "of=", 3) == 0) + { + outfile = nsh_getfullpath(vtbl, &argv[i][3]); + } + else if (strncmp(argv[i], "bs=", 3) == 0) + { + dd.sectsize = atoi(&argv[i][3]); + } + else if (strncmp(argv[i], "count=", 6) == 0) + { + dd.nsectors = atoi(&argv[i][6]); + } + else if (strncmp(argv[i], "skip=", 5) == 0) + { + dd.skip = atoi(&argv[i][5]); + } + } + +#ifndef CAN_PIPE_FROM_STD + if (!infile || !outfile) + { + nsh_output(vtbl, g_fmtargrequired, g_dd); + goto errout_with_paths; + } +#endif + + if (dd.skip < 0 || dd.skip > dd.nsectors) + { + nsh_output(vtbl, g_fmtarginvalid, g_dd); + goto errout_with_paths; + } + + /* Allocate the I/O buffer */ + + dd.buffer = malloc(dd.sectsize); + if (!dd.buffer) + { + nsh_output(vtbl, g_fmtcmdoutofmemory, g_dd); + goto errout_with_paths; + } + + /* Open the input file */ + + ret = dd_infopen(infile, &dd); + if (ret < 0) + { + goto errout_with_paths; + } + + /* Open the output file */ + + ret = dd_outfopen(outfile, &dd); + if (ret < 0) + { + goto errout_with_inf; + } + + /* Then perform the data transfer */ + + dd.sector = 0; + while (!dd.eof && dd.nsectors > 0) + { + /* Read one sector from from the input */ + + ret = DD_READ(&dd); + if (ret < 0) + { + goto errout_with_outf; + } + + /* Has the incoming data stream ended? */ + + if (!dd.eof) + { + /* Pad with zero if necessary (at the end of file only) */ + + for (i = dd.nbytes; i < dd.sectsize; i++) + { + dd.buffer[i] = 0; + } + + /* Write one sector to the output file */ + + if (dd.sector >= dd.skip) + { + ret = DD_WRITE(&dd); + if (ret < 0) + { + goto errout_with_outf; + } + + /* Decrement to show that a sector was written */ + + dd.nsectors--; + } + + /* Increment the sector number */ + + dd.sector++; + } + } + ret = OK; + +errout_with_outf: + DD_INCLOSE(&dd); +errout_with_inf: + DD_OUTCLOSE(&dd); + free(dd.buffer); +errout_with_paths: + if (infile) + { + free(infile); + } + if (outfile) + { + free(outfile); + } + return ret; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS && !CONFIG_NSH_DISABLE_DD */ + diff --git a/apps/nshlib/nsh_envcmds.c b/apps/nshlib/nsh_envcmds.c new file mode 100644 index 0000000000..07b7755174 --- /dev/null +++ b/apps/nshlib/nsh_envcmds.c @@ -0,0 +1,338 @@ +/**************************************************************************** + * apps/nshlib/nsh_envcmds.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "nsh.h" +#include "nsh_console.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON) +static const char g_pwd[] = "PWD"; +static const char g_oldpwd[] = "OLDPWD"; +static const char g_home[] = CONFIG_LIB_HOMEDIR; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_getwd + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON) +static inline FAR const char *nsh_getwd(const char *wd) +{ + const char *val; + + /* If no working directory is defined, then default to the home directory */ + + val = getenv(wd); + if (!val) + { + val = g_home; + } + return val; +} +#endif + +/**************************************************************************** + * Name: nsh_getdirpath + ****************************************************************************/ + +static inline char *nsh_getdirpath(FAR struct nsh_vtbl_s *vtbl, + const char *dirpath, const char *relpath) +{ + char *alloc; + int len; + + /* Handle the special case where the dirpath is simply "/" */ + + if (strcmp(dirpath, "/") == 0) + { + len = strlen(relpath) + 2; + alloc = (char*)malloc(len); + if (alloc) + { + sprintf(alloc, "/%s", relpath); + } + } + else + { + len = strlen(dirpath) + strlen(relpath) + 2; + alloc = (char*)malloc(len); + if (alloc) + { + sprintf(alloc, "%s/%s", dirpath, relpath); + } + } + + if (!alloc) + { + nsh_output(vtbl, g_fmtcmdoutofmemory, "nsh_getdirpath"); + } + return alloc; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_getwd + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON) +FAR const char *nsh_getcwd(void) +{ + return nsh_getwd(g_pwd); +} +#endif + +/**************************************************************************** + * Name: nsh_getfullpath + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON) +char *nsh_getfullpath(FAR struct nsh_vtbl_s *vtbl, const char *relpath) +{ + const char *wd; + + /* Handle some special cases */ + + if (!relpath || relpath[0] == '\0') + { + /* No relative path provided */ + + return strdup(g_home); + } + else if (relpath[0] == '/') + { + return strdup(relpath); + } + + /* Get the path to the current working directory */ + + wd = nsh_getcwd(); + + /* Fake the '.' directory */ + + if (strcmp(relpath, ".") == 0) + { + return strdup(wd); + } + + /* Return the full path */ + + return nsh_getdirpath(vtbl, wd, relpath); +} +#endif + +/**************************************************************************** + * Name: nsh_freefullpath + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON) +void nsh_freefullpath(char *relpath) +{ + if (relpath) + { + free(relpath); + } +} +#endif + +/**************************************************************************** + * Name: cmd_cd + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON) +#ifndef CONFIG_NSH_DISABLE_CD +int cmd_cd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + const char *path = argv[1]; + char *alloc = NULL; + char *fullpath = NULL; + int ret = OK; + + /* Check for special arguments */ + + if (argc < 2 || strcmp(path, "~") == 0) + { + path = g_home; + } + else if (strcmp(path, "-") == 0) + { + alloc = strdup(nsh_getwd(g_oldpwd)); + path = alloc; + } + else if (strcmp(path, "..") == 0) + { + alloc = strdup(nsh_getcwd()); + path = dirname(alloc); + } + else + { + fullpath = nsh_getfullpath(vtbl, path); + path = fullpath; + } + + /* Set the new workding directory */ + + ret = chdir(path); + if (ret != 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "chdir", NSH_ERRNO); + ret = ERROR; + } + + /* Free any memory that was allocated */ + + if (alloc) + { + free(alloc); + } + + if (fullpath) + { + nsh_freefullpath(fullpath); + } + return ret; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_echo + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_ECHO +int cmd_echo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + int i; + + /* echo each argument, separated by a space as it must have been on the + * command line + */ + + for (i = 1; i < argc; i++) + { + nsh_output(vtbl, "%s ", argv[i]); + } + nsh_output(vtbl, "\n"); + return OK; +} +#endif + +/**************************************************************************** + * Name: cmd_pwd + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON) +#ifndef CONFIG_NSH_DISABLE_PWD +int cmd_pwd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + nsh_output(vtbl, "%s\n", nsh_getcwd()); + return OK; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_set + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_ENVIRON +#ifndef CONFIG_NSH_DISABLE_SET +int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + int ret = setenv(argv[1], argv[2], TRUE); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "setenv", NSH_ERRNO); + } + return ret; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_unset + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_ENVIRON +#ifndef CONFIG_NSH_DISABLE_UNSET +int cmd_unset(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + int ret = unsetenv(argv[1]); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "unsetenv", NSH_ERRNO); + } + return ret; +} +#endif +#endif diff --git a/apps/nshlib/nsh_fscmds.c b/apps/nshlib/nsh_fscmds.c new file mode 100644 index 0000000000..1a9f2eb576 --- /dev/null +++ b/apps/nshlib/nsh_fscmds.c @@ -0,0 +1,1299 @@ +/**************************************************************************** + * apps/nshlib/nsh_fscmds.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#if CONFIG_NFILE_DESCRIPTORS > 0 +# include +# include +# if !defined(CONFIG_DISABLE_MOUNTPOINT) +# ifdef CONFIG_FS_READABLE /* Need at least one filesytem in configuration */ +# include +# include +# endif +# ifdef CONFIG_FS_FAT +# include +# endif +# ifdef CONFIG_NFS +# include +# include +# include +# endif +# ifdef CONFIG_RAMLOG_SYSLOG +# include +# endif +#endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nsh.h" +#include "nsh_console.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define LSFLAGS_SIZE 1 +#define LSFLAGS_LONG 2 +#define LSFLAGS_RECURSIVE 4 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +typedef int (*direntry_handler_t)(FAR struct nsh_vtbl_s *, const char *, + struct dirent *, void *); + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Common buffer for file I/O. Note the use of this common buffer precludes + * multiple copies of NSH running concurrently. It should be allocated per + * NSH instance and retained in the "vtbl" as is done for the telnet + * connection. + */ + +static char g_iobuffer[IOBUFFERSIZE]; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: trim_dir + ****************************************************************************/ + +static void trim_dir(char *arg) +{ + /* Skip any trailing '/' characters (unless it is also the leading '/') */ + + int len = strlen(arg) - 1; + while (len > 0 && arg[len] == '/') + { + arg[len] = '\0'; + len--; + } +} + +/**************************************************************************** + * Name: nsh_getdirpath + ****************************************************************************/ + +static char *nsh_getdirpath(const char *path, const char *file) +{ + /* Handle the case where all that is left is '/' */ + + if (strcmp(path, "/") == 0) + { + sprintf(g_iobuffer, "/%s", file); + } + else + { + sprintf(g_iobuffer, "%s/%s", path, file); + } + + g_iobuffer[PATH_MAX] = '\0'; + return strdup(g_iobuffer); +} + +/**************************************************************************** + * Name: foreach_direntry + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static int foreach_direntry(FAR struct nsh_vtbl_s *vtbl, const char *cmd, const char *dirpath, + direntry_handler_t handler, void *pvarg) +{ + DIR *dirp; + int ret = OK; + + /* Trim trailing '/' from directory names */ + +#ifdef CONFIG_NSH_FULLPATH + trim_dir(arg); +#endif + + /* Open the directory */ + + dirp = opendir(dirpath); + + if (!dirp) + { + /* Failed to open the directory */ + + nsh_output(vtbl, g_fmtnosuch, cmd, "directory", dirpath); + return ERROR; + } + + /* Read each directory entry */ + + for (;;) + { + struct dirent *entryp = readdir(dirp); + if (!entryp) + { + /* Finished with this directory */ + + break; + } + + /* Call the handler with this directory entry */ + + if (handler(vtbl, dirpath, entryp, pvarg) < 0) + { + /* The handler reported a problem */ + + ret = ERROR; + break; + } + } + + closedir(dirp); + return ret; +} +#endif + +/**************************************************************************** + * Name: ls_specialdir + ****************************************************************************/ + +static inline int ls_specialdir(const char *dir) +{ + /* '.' and '..' directories are not listed like normal directories */ + + return (strcmp(dir, ".") == 0 || strcmp(dir, "..") == 0); +} + +/**************************************************************************** + * Name: ls_handler + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static int ls_handler(FAR struct nsh_vtbl_s *vtbl, const char *dirpath, struct dirent *entryp, void *pvarg) +{ + unsigned int lsflags = (unsigned int)pvarg; + int ret; + + /* Check if any options will require that we stat the file */ + + if ((lsflags & (LSFLAGS_SIZE|LSFLAGS_LONG)) != 0) + { + struct stat buf; + char *fullpath = nsh_getdirpath(dirpath, entryp->d_name); + + /* Yes, stat the file */ + + ret = stat(fullpath, &buf); + free(fullpath); + if (ret != 0) + { + nsh_output(vtbl, g_fmtcmdfailed, "ls", "stat", NSH_ERRNO); + return ERROR; + } + + if ((lsflags & LSFLAGS_LONG) != 0) + { + char details[] = "----------"; + if (S_ISDIR(buf.st_mode)) + { + details[0]='d'; + } + else if (S_ISCHR(buf.st_mode)) + { + details[0]='c'; + } + else if (S_ISBLK(buf.st_mode)) + { + details[0]='b'; + } + + if ((buf.st_mode & S_IRUSR) != 0) + { + details[1]='r'; + } + + if ((buf.st_mode & S_IWUSR) != 0) + { + details[2]='w'; + } + + if ((buf.st_mode & S_IXUSR) != 0) + { + details[3]='x'; + } + + if ((buf.st_mode & S_IRGRP) != 0) + { + details[4]='r'; + } + + if ((buf.st_mode & S_IWGRP) != 0) + { + details[5]='w'; + } + + if ((buf.st_mode & S_IXGRP) != 0) + { + details[6]='x'; + } + + if ((buf.st_mode & S_IROTH) != 0) + { + details[7]='r'; + } + + if ((buf.st_mode & S_IWOTH) != 0) + { + details[8]='w'; + } + + if ((buf.st_mode & S_IXOTH) != 0) + { + details[9]='x'; + } + + nsh_output(vtbl, " %s", details); + } + + if ((lsflags & LSFLAGS_SIZE) != 0) + { + nsh_output(vtbl, "%8d", buf.st_size); + } + } + + /* then provide the filename that is common to normal and verbose output */ + +#ifdef CONFIG_NSH_FULLPATH + nsh_output(vtbl, " %s/%s", arg, entryp->d_name); +#else + nsh_output(vtbl, " %s", entryp->d_name); +#endif + + if (DIRENT_ISDIRECTORY(entryp->d_type) && !ls_specialdir(entryp->d_name)) + { + nsh_output(vtbl, "/\n"); + } + else + { + nsh_output(vtbl, "\n"); + } + return OK; +} +#endif + +/**************************************************************************** + * Name: ls_recursive + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static int ls_recursive(FAR struct nsh_vtbl_s *vtbl, const char *dirpath, + struct dirent *entryp, void *pvarg) +{ + int ret = OK; + + /* Is this entry a directory (and not one of the special directories, . and ..)? */ + + if (DIRENT_ISDIRECTORY(entryp->d_type) && !ls_specialdir(entryp->d_name)) + { + /* Yes.. */ + + char *newpath; + newpath = nsh_getdirpath(dirpath, entryp->d_name); + + /* List the directory contents */ + + nsh_output(vtbl, "%s:\n", newpath); + + /* Traverse the directory */ + + ret = foreach_direntry(vtbl, "ls", newpath, ls_handler, pvarg); + if (ret == 0) + { + /* Then recurse to list each directory within the directory */ + + ret = foreach_direntry(vtbl, "ls", newpath, ls_recursive, pvarg); + free(newpath); + } + } + return ret; +} +#endif + +/**************************************************************************** + * Name: cat_common + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +#ifndef CONFIG_NSH_DISABLE_CAT +static int cat_common(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, + FAR const char *filename) +{ + char buffer[IOBUFFERSIZE]; + int fd; + int ret = OK; + + /* Open the file for reading */ + + fd = open(filename, O_RDONLY); + if (fd < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, cmd, "open", NSH_ERRNO); + return ERROR; + } + + /* And just dump it byte for byte into stdout */ + + for (;;) + { + int nbytesread = read(fd, buffer, IOBUFFERSIZE); + + /* Check for read errors */ + + if (nbytesread < 0) + { + int errval = errno; + + /* EINTR is not an error (but will stop stop the cat) */ + +#ifndef CONFIG_DISABLE_SIGNALS + if (errval == EINTR) + { + nsh_output(vtbl, g_fmtsignalrecvd, cmd); + } + else +#endif + { + nsh_output(vtbl, g_fmtcmdfailed, cmd, "read", NSH_ERRNO_OF(errval)); + } + + ret = ERROR; + break; + } + + /* Check for data successfully read */ + + else if (nbytesread > 0) + { + int nbyteswritten = 0; + + while (nbyteswritten < nbytesread) + { + ssize_t n = nsh_write(vtbl, buffer, nbytesread); + if (n < 0) + { + int errval = errno; + + /* EINTR is not an error (but will stop stop the cat) */ + + #ifndef CONFIG_DISABLE_SIGNALS + if (errval == EINTR) + { + nsh_output(vtbl, g_fmtsignalrecvd, cmd); + } + else +#endif + { + nsh_output(vtbl, g_fmtcmdfailed, cmd, "write", NSH_ERRNO); + } + + ret = ERROR; + break; + } + else + { + nbyteswritten += n; + } + } + } + + /* Otherwise, it is the end of file */ + + else + { + break; + } + } + + (void)close(fd); + return ret; +} +#endif +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cmd_cat + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +#ifndef CONFIG_NSH_DISABLE_CAT +int cmd_cat(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *fullpath; + int i; + int ret = OK; + + /* Loop for each file name on the command line */ + + for (i = 1; i < argc && ret == OK; i++) + { + /* Get the fullpath to the file */ + + fullpath = nsh_getfullpath(vtbl, argv[i]); + if (!fullpath) + { + ret = ERROR; + } + else + { + /* Dump the file to the console */ + + ret = cat_common(vtbl, argv[0], fullpath); + + /* Free the allocated full path */ + + nsh_freefullpath(fullpath); + } + } + + return ret; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_dmesg + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_SYSLOG) && \ + defined(CONFIG_RAMLOG_SYSLOG) && !defined(CONFIG_NSH_DISABLE_DMESG) +int cmd_dmesg(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + return cat_common(vtbl, argv[0], CONFIG_SYSLOG_DEVPATH); +} +#endif + +/**************************************************************************** + * Name: cmd_cp + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +#ifndef CONFIG_NSH_DISABLE_CP +int cmd_cp(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + struct stat buf; + char *srcpath = NULL; + char *destpath = NULL; + char *allocpath = NULL; + int oflags = O_WRONLY|O_CREAT|O_TRUNC; + int rdfd; + int wrfd; + int ret = ERROR; + + /* Get the full path to the source file */ + + srcpath = nsh_getfullpath(vtbl, argv[1]); + if (!srcpath) + { + goto errout; + } + + /* Open the source file for reading */ + + rdfd = open(srcpath, O_RDONLY); + if (rdfd < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO); + goto errout_with_srcpath; + } + + /* Get the full path to the destination file or directory */ + + destpath = nsh_getfullpath(vtbl, argv[2]); + if (!destpath) + { + goto errout_with_rdfd; + } + + /* Check if the destination is a directory */ + + ret = stat(destpath, &buf); + if (ret == 0) + { + /* Something exists here... is it a directory? */ + + if (S_ISDIR(buf.st_mode)) + { + /* Yes, it is a directory. Remove any trailing '/' characters from the path */ + + trim_dir(argv[2]); + + /* Construct the full path to the new file */ + + allocpath = nsh_getdirpath(argv[2], basename(argv[1]) ); + if (!allocpath) + { + nsh_output(vtbl, g_fmtcmdoutofmemory, argv[0]); + goto errout_with_destpath; + } + + /* Open then dest for writing */ + + nsh_freefullpath(destpath); + destpath = allocpath; + } + else if (!S_ISREG(buf.st_mode)) + { + /* Maybe it is a driver? */ + + oflags = O_WRONLY; + } + } + + /* Now open the destination */ + + wrfd = open(destpath, oflags, 0666); + if (wrfd < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO); + goto errout_with_allocpath; + } + + /* Now copy the file */ + + for (;;) + { + int nbytesread; + int nbyteswritten; + + do + { + nbytesread = read(rdfd, g_iobuffer, IOBUFFERSIZE); + if (nbytesread == 0) + { + /* End of file */ + + ret = OK; + goto errout_with_wrfd; + } + else if (nbytesread < 0) + { + /* EINTR is not an error (but will still stop the copy) */ + +#ifndef CONFIG_DISABLE_SIGNALS + if (errno == EINTR) + { + nsh_output(vtbl, g_fmtsignalrecvd, argv[0]); + } + else +#endif + { + /* Read error */ + + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO); + } + goto errout_with_wrfd; + } + } + while (nbytesread <= 0); + + do + { + nbyteswritten = write(wrfd, g_iobuffer, nbytesread); + if (nbyteswritten >= 0) + { + nbytesread -= nbyteswritten; + } + else + { + /* EINTR is not an error (but will still stop the copy) */ + +#ifndef CONFIG_DISABLE_SIGNALS + if (errno == EINTR) + { + nsh_output(vtbl, g_fmtsignalrecvd, argv[0]); + } + else +#endif + { + /* Read error */ + + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "write", NSH_ERRNO); + } + goto errout_with_wrfd; + } + } + while (nbytesread > 0); + } + +errout_with_wrfd: + close(wrfd); + +errout_with_allocpath: + if (allocpath) + { + free(allocpath); + } + +errout_with_destpath: + if (destpath && !allocpath) + { + nsh_freefullpath(destpath); + } + +errout_with_rdfd: + close(rdfd); + +errout_with_srcpath: + if (srcpath) + { + nsh_freefullpath(srcpath); + } +errout: + return ret; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_losetup + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) +#ifndef CONFIG_NSH_DISABLE_LOSETUP +int cmd_losetup(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *loopdev = NULL; + char *filepath = NULL; + bool teardown = false; + bool readonly = false; + off_t offset = 0; + bool badarg = false; + int ret = ERROR; + int option; + + /* Get the losetup options: Two forms are supported: + * + * losetup -d + * losetup [-o ] [-r] + * + * NOTE that the -o and -r options are accepted with the -d option, but + * will be ignored. + */ + + while ((option = getopt(argc, argv, "d:o:r")) != ERROR) + { + switch (option) + { + case 'd': + loopdev = nsh_getfullpath(vtbl, optarg); + teardown = true; + break; + + case 'o': + offset = atoi(optarg); + break; + + case 'r': + readonly = true; + break; + + case '?': + default: + nsh_output(vtbl, g_fmtarginvalid, argv[0]); + badarg = true; + break; + } + } + + /* If a bad argument was encountered, then return without processing the command */ + + if (badarg) + { + goto errout_with_paths; + } + + /* If this is not a tear down operation, then additional command line + * parameters are required. + */ + + if (!teardown) + { + /* There must be two arguments on the command line after the options */ + + if (optind + 1 < argc) + { + loopdev = nsh_getfullpath(vtbl, argv[optind]); + optind++; + + filepath = nsh_getfullpath(vtbl, argv[optind]); + optind++; + } + else + { + nsh_output(vtbl, g_fmtargrequired, argv[0]); + goto errout_with_paths; + } + } + + /* There should be nothing else on the command line */ + + if (optind < argc) + { + nsh_output(vtbl, g_fmttoomanyargs, argv[0]); + goto errout_with_paths; + } + + /* Perform the teardown operation */ + + if (teardown) + { + /* Tear down the loop device. */ + + ret = loteardown(loopdev); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "loteardown", NSH_ERRNO_OF(-ret)); + goto errout_with_paths; + } + } + else + { + /* Set up the loop device */ + + ret = losetup(loopdev, filepath, 512, offset, readonly); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "losetup", NSH_ERRNO_OF(-ret)); + goto errout_with_paths; + } + } + + /* Free memory */ + +errout_with_paths: + if (loopdev) + { + free(loopdev); + } + + if (filepath) + { + free(filepath); + } + return ret; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_ls + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +#ifndef CONFIG_NSH_DISABLE_LS +int cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + const char *relpath; + unsigned int lsflags = 0; + char *fullpath; + bool badarg = false; + int ret; + + /* Get the ls options */ + + int option; + while ((option = getopt(argc, argv, "lRs")) != ERROR) + { + switch (option) + { + case 'l': + lsflags |= (LSFLAGS_SIZE|LSFLAGS_LONG); + break; + + case 'R': + lsflags |= LSFLAGS_RECURSIVE; + break; + + case 's': + lsflags |= LSFLAGS_SIZE; + break; + + case '?': + default: + nsh_output(vtbl, g_fmtarginvalid, argv[0]); + badarg = true; + break; + } + } + + /* If a bad argument was encountered, then return without processing the command */ + + if (badarg) + { + return ERROR; + } + + /* There may be one argument after the options */ + + if (optind + 1 < argc) + { + nsh_output(vtbl, g_fmttoomanyargs, argv[0]); + return ERROR; + } + else if (optind >= argc) + { +#ifndef CONFIG_DISABLE_ENVIRON + relpath = nsh_getcwd(); +#else + nsh_output(vtbl, g_fmtargrequired, argv[0]); + return ERROR; +#endif + } + else + { + relpath = argv[optind]; + } + + /* Get the fullpath to the directory */ + + fullpath = nsh_getfullpath(vtbl, relpath); + if (!fullpath) + { + return ERROR; + } + + /* List the directory contents */ + + nsh_output(vtbl, "%s:\n", fullpath); + ret = foreach_direntry(vtbl, "ls", fullpath, ls_handler, (void*)lsflags); + if (ret == OK && (lsflags & LSFLAGS_RECURSIVE) != 0) + { + /* Then recurse to list each directory within the directory */ + + ret = foreach_direntry(vtbl, "ls", fullpath, ls_recursive, (void*)lsflags); + } + nsh_freefullpath(fullpath); + return ret; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_mkdir + ****************************************************************************/ + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE) +#ifndef CONFIG_NSH_DISABLE_MKDIR +int cmd_mkdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *fullpath = nsh_getfullpath(vtbl, argv[1]); + int ret = ERROR; + + if (fullpath) + { + ret = mkdir(fullpath, 0777); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mkdir", NSH_ERRNO); + } + nsh_freefullpath(fullpath); + } + return ret; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_mkfatfs + ****************************************************************************/ + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_FAT) +#ifndef CONFIG_NSH_DISABLE_MKFATFS +int cmd_mkfatfs(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + struct fat_format_s fmt = FAT_FORMAT_INITIALIZER; + char *fullpath = nsh_getfullpath(vtbl, argv[1]); + int ret = ERROR; + + if (fullpath) + { + ret = mkfatfs(fullpath, &fmt); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mkfatfs", NSH_ERRNO); + } + nsh_freefullpath(fullpath); + } + return ret; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_mkfifo + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +#ifndef CONFIG_NSH_DISABLE_MKFIFO +int cmd_mkfifo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *fullpath = nsh_getfullpath(vtbl, argv[1]); + int ret = ERROR; + + if (fullpath) + { + ret = mkfifo(fullpath, 0777); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mkfifo", NSH_ERRNO); + } + nsh_freefullpath(fullpath); + } + return ret; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_mkrd + ****************************************************************************/ + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE) +#ifndef CONFIG_NSH_DISABLE_MKRD +int cmd_mkrd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + const char *fmt; + uint8_t *buffer; + uint32_t nsectors; + bool badarg = false; + int sectsize = 512; + int minor = 0; + int ret; + + /* Get the mkrd options */ + + int option; + while ((option = getopt(argc, argv, ":m:s:")) != ERROR) + { + switch (option) + { + case 'm': + minor = atoi(optarg); + if (minor < 0 || minor > 255) + { + nsh_output(vtbl, g_fmtargrange, argv[0]); + badarg = true; + } + break; + + case 's': + sectsize = atoi(optarg); + if (minor < 0 || minor > 16384) + { + nsh_output(vtbl, g_fmtargrange, argv[0]); + badarg = true; + } + break; + + case ':': + nsh_output(vtbl, g_fmtargrequired, argv[0]); + badarg = true; + break; + + case '?': + default: + nsh_output(vtbl, g_fmtarginvalid, argv[0]); + badarg = true; + break; + } + } + + /* If a bad argument was encountered, then return without processing the command */ + + if (badarg) + { + return ERROR; + } + + /* There should be exactly on parameter left on the command-line */ + + if (optind == argc-1) + { + nsectors = (uint32_t)atoi(argv[optind]); + } + else if (optind >= argc) + { + fmt = g_fmttoomanyargs; + goto errout_with_fmt; + } + else + { + fmt = g_fmtargrequired; + goto errout_with_fmt; + } + + /* Allocate the memory backing up the ramdisk */ + + buffer = (uint8_t*)malloc(sectsize * nsectors); + if (!buffer) + { + fmt = g_fmtcmdoutofmemory; + goto errout_with_fmt; + } + +#ifdef CONFIG_DEBUG_VERBOSE + memset(buffer, 0, sectsize * nsectors); +#endif + dbg("RAMDISK at %p\n", buffer); + + /* Then register the ramdisk */ + + ret = ramdisk_register(minor, buffer, nsectors, sectsize, true); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "ramdisk_register", NSH_ERRNO_OF(-ret)); + free(buffer); + return ERROR; + } + return ret; + +errout_with_fmt: + nsh_output(vtbl, fmt, argv[0]); + return ERROR; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_mv + ****************************************************************************/ + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE) +#ifndef CONFIG_NSH_DISABLE_MV +int cmd_mv(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *oldpath; + char *newpath; + int ret; + + /* Get the full path to the old and new file paths */ + + oldpath = nsh_getfullpath(vtbl, argv[1]); + if (!oldpath) + { + return ERROR; + } + + newpath = nsh_getfullpath(vtbl, argv[2]); + if (!newpath) + { + nsh_freefullpath(newpath); + return ERROR; + } + + /* Perform the mount */ + + ret = rename(oldpath, newpath); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "rename", NSH_ERRNO); + } + + /* Free the file paths */ + + nsh_freefullpath(oldpath); + nsh_freefullpath(newpath); + return ret; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_rm + ****************************************************************************/ + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE) +#ifndef CONFIG_NSH_DISABLE_RM +int cmd_rm(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *fullpath = nsh_getfullpath(vtbl, argv[1]); + int ret = ERROR; + + if (fullpath) + { + ret = unlink(fullpath); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "unlink", NSH_ERRNO); + } + nsh_freefullpath(fullpath); + } + return ret; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_rmdir + ****************************************************************************/ + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE) +#ifndef CONFIG_NSH_DISABLE_RMDIR +int cmd_rmdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *fullpath = nsh_getfullpath(vtbl, argv[1]); + int ret = ERROR; + + if (fullpath) + { + ret = rmdir(fullpath); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "rmdir", NSH_ERRNO); + } + nsh_freefullpath(fullpath); + } + return ret; +} +#endif +#endif + +/**************************************************************************** + * Name: nsh_script + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_NSH_DISABLESCRIPT) +int nsh_script(FAR struct nsh_vtbl_s *vtbl, const char *cmd, const char *path) +{ + char *fullpath; + FILE *stream; + char *buffer; + char *pret; + int ret = ERROR; + + /* The path to the script may be relative to the current working directory */ + + fullpath = nsh_getfullpath(vtbl, path); + if (!fullpath) + { + return ERROR; + } + + /* Get a reference to the common input buffer */ + + buffer = nsh_linebuffer(vtbl); + if (buffer) + { + /* Open the file containing the script */ + + stream = fopen(fullpath, "r"); + if (!stream) + { + nsh_output(vtbl, g_fmtcmdfailed, cmd, "fopen", NSH_ERRNO); + nsh_freefullpath(fullpath); + return ERROR; + } + + /* Loop, processing each command line in the script file (or + * until an error occurs) + */ + + do + { + /* Get the next line of input from the file */ + + fflush(stdout); + pret = fgets(buffer, CONFIG_NSH_LINELEN, stream); + if (pret) + { + /* Parse process the command. NOTE: this is recursive... + * we got to cmd_sh via a call to nsh_parse. So some + * considerable amount of stack may be used. + */ + + ret = nsh_parse(vtbl, buffer); + } + } + while (pret && ret == OK); + fclose(stream); + } + + nsh_freefullpath(fullpath); + return ret; +} +#endif + +/**************************************************************************** + * Name: cmd_sh + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_NSH_DISABLESCRIPT) +#ifndef CONFIG_NSH_DISABLE_SH +int cmd_sh(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + return nsh_script(vtbl, argv[0], argv[1]); +} +#endif +#endif diff --git a/apps/nshlib/nsh_init.c b/apps/nshlib/nsh_init.c new file mode 100644 index 0000000000..7c7e78ea1f --- /dev/null +++ b/apps/nshlib/nsh_init.c @@ -0,0 +1,102 @@ +/**************************************************************************** + * apps/nshlib/nsh_init.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "nsh.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_initialize + * + * Description: + * This nterfaces is used to initialize the NuttShell (NSH). + * nsh_initialize() should be called one during application start-up prior + * to executing either nsh_consolemain() or nsh_telnetstart(). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void nsh_initialize(void) +{ + /* Mount the /etc filesystem */ + + (void)nsh_romfsetc(); + + /* Perform architecture-specific initialization (if available) */ + + (void)nsh_archinitialize(); + + /* Bring up the network */ + + (void)nsh_netinit(); +} + diff --git a/apps/nshlib/nsh_mmcmds.c b/apps/nshlib/nsh_mmcmds.c new file mode 100644 index 0000000000..545ae60ad4 --- /dev/null +++ b/apps/nshlib/nsh_mmcmds.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * apps/nshlib/nsh_mmcmds.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "nsh.h" +#include "nsh_console.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cmd_free + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_FREE +int cmd_free(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + struct mallinfo mem; + +#ifdef CONFIG_CAN_PASS_STRUCTS + mem = mallinfo(); +#else + (void)mallinfo(&mem); +#endif + + nsh_output(vtbl, " total used free largest\n"); + nsh_output(vtbl, "Mem: %11d%11d%11d%11d\n", + mem.arena, mem.uordblks, mem.fordblks, mem.mxordblk); + + return OK; +} +#endif /* !CONFIG_NSH_DISABLE_FREE */ diff --git a/apps/nshlib/nsh_mntcmds.c b/apps/nshlib/nsh_mntcmds.c new file mode 100644 index 0000000000..b5935bdea1 --- /dev/null +++ b/apps/nshlib/nsh_mntcmds.c @@ -0,0 +1,416 @@ +/**************************************************************************** + * apps/nshlib/nsh_mntcmds.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "nsh.h" +#include "nsh_console.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: df_handler + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \ + defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_MOUNT) +static int df_handler(FAR const char *mountpoint, + FAR struct statfs *statbuf, FAR void *arg) +{ + FAR struct nsh_vtbl_s *vtbl = (FAR struct nsh_vtbl_s *)arg; + + DEBUGASSERT(mountpoint && statbuf && vtbl); + + nsh_output(vtbl, "%6ld %8ld %8ld %8ld %s\n", + statbuf->f_bsize, statbuf->f_blocks, + statbuf->f_blocks - statbuf->f_bavail, statbuf->f_bavail, + mountpoint); + + return OK; +} +#endif + +/**************************************************************************** + * Name: mount_handler + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \ + defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_MOUNT) +static int mount_handler(FAR const char *mountpoint, + FAR struct statfs *statbuf, FAR void *arg) +{ + FAR struct nsh_vtbl_s *vtbl = (FAR struct nsh_vtbl_s *)arg; + FAR const char *fstype; + + DEBUGASSERT(mountpoint && statbuf && vtbl); + + /* Get the file system type */ + + switch (statbuf->f_type) + { +#ifdef CONFIG_FS_FAT + case MSDOS_SUPER_MAGIC: + fstype = "vfat"; + break; +#endif + +#ifdef CONFIG_FS_ROMFS + case ROMFS_MAGIC: + fstype = "romfs"; + break; +#endif + +#ifdef CONFIG_APPS_BINDIR + case BINFS_MAGIC: + fstype = "bindir"; + break; +#endif + +#ifdef CONFIG_FS_NXFFS + case NXFFS_MAGIC: + fstype = "nxffs"; + break; +#endif + +#ifdef CONFIG_NFS + case NFS_SUPER_MAGIC: + fstype = "nfs"; + break; +#endif + + default: + fstype = "Unrecognized"; + break; + } + + nsh_output(vtbl, " %s type %s\n", mountpoint, fstype); + return OK; +} +#endif + +/**************************************************************************** + * Name: mount_show + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \ + defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_MOUNT) +static inline int mount_show(FAR struct nsh_vtbl_s *vtbl, FAR const char *progname) +{ + return foreach_mountpoint(mount_handler, (FAR void *)vtbl); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cmd_df + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \ + defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_DF) +int cmd_df(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + nsh_output(vtbl, " Block Number\n"); + nsh_output(vtbl, " Size Blocks Used Available Mounted on\n"); + + return foreach_mountpoint(df_handler, (FAR void *)vtbl); +} +#endif + +/**************************************************************************** + * Name: cmd_mount + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \ + defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_MOUNT) +int cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *source; + char *target; + char *filesystem = 0; + bool badarg = false; + int ret; + + /* The mount command behaves differently if no parameters are provided */ + + if (argc < 2) + { + return mount_show(vtbl, argv[0]); + } + + /* Get the mount options */ + + int option; + while ((option = getopt(argc, argv, ":t:")) != ERROR) + { + switch (option) + { + case 't': + filesystem = optarg; + break; + + case ':': + nsh_output(vtbl, g_fmtargrequired, argv[0]); + badarg = true; + break; + + case '?': + default: + nsh_output(vtbl, g_fmtarginvalid, argv[0]); + badarg = true; + break; + } + } + + /* If a bad argument was encountered, then return without processing the command */ + + if (badarg) + { + return ERROR; + } + + /* There are two required arguments after the options */ + + if (optind + 2 < argc) + { + nsh_output(vtbl, g_fmttoomanyargs, argv[0]); + return ERROR; + } + else if (optind + 2 > argc) + { + nsh_output(vtbl, g_fmtargrequired, argv[0]); + return ERROR; + } + + /* The source and target paths might be relative to the current + * working directory. + */ + + source = nsh_getfullpath(vtbl, argv[optind]); + if (!source) + { + return ERROR; + } + + target = nsh_getfullpath(vtbl, argv[optind+1]); + if (!target) + { + nsh_freefullpath(source); + return ERROR; + } + + /* Perform the mount */ + + ret = mount(source, target, filesystem, 0, NULL); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mount", NSH_ERRNO); + } + + nsh_freefullpath(source); + nsh_freefullpath(target); + return ret; +} +#endif + +/**************************************************************************** + * Name: cmd_nfsmount + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \ + defined(CONFIG_NET) && defined(CONFIG_NFS) && !defined(CONFIG_NSH_DISABLE_NFSMOUNT) +int cmd_nfsmount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + struct nfs_args data; + FAR char *address; + FAR char *lpath; + FAR char *rpath; + bool badarg = false; +#ifdef CONFIG_NET_IPv6 + FAR struct sockaddr_in6 *sin; + struct in6_addr inaddr; +#else + FAR struct sockaddr_in *sin; + struct in_addr inaddr; +#endif + int ret; + + /* If a bad argument was encountered, then return without processing the + * command. + */ + + if (badarg) + { + return ERROR; + } + + /* The fist argument on the command line should be the NFS server IP address + * in standard IPv4 (or IPv6) dot format. + */ + + address = argv[1]; + if (!address) + { + return ERROR; + } + + /* The local mount point path (lpath) might be relative to the current working + * directory. + */ + + lpath = nsh_getfullpath(vtbl, argv[2]); + if (!lpath) + { + return ERROR; + } + + /* Get the remote mount point path */ + + rpath = argv[3]; + + /* Convert the IP address string into its binary form */ + +#ifdef CONFIG_NET_IPv6 + ret = inet_pton(AF_INET6, address, &inaddr); +#else + ret = inet_pton(AF_INET, address, &inaddr); +#endif + if (ret != 1) + { + nsh_freefullpath(lpath); + return ERROR; + } + + /* Place all of the NFS arguements into the nfs_args structure */ + + memset(&data, 0, sizeof(data)); + +#ifdef CONFIG_NET_IPv6 + sin = (FAR struct sockaddr_in6 *)&data.addr; + sin->sin_family = AF_INET6; + sin->sin_port = htons(NFS_PMAPPORT); + memcpy(&sin->sin6_addr, &inaddr, sizeof(struct in6_addr)); + data.addrlen = sizeof(struct sockaddr_in6); +#else + sin = (FAR struct sockaddr_in *)&data.addr; + sin->sin_family = AF_INET; + sin->sin_port = htons(NFS_PMAPPORT); + sin->sin_addr = inaddr; + data.addrlen = sizeof(struct sockaddr_in); +#endif + + data.sotype = SOCK_DGRAM; + data.path = rpath; + data.flags = 0; /* 0=Use all defaults */ + + /* Perform the mount */ + + ret = mount(NULL, lpath, "nfs", 0, (FAR void *)&data); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mount", NSH_ERRNO); + } + + /* We no longer need the allocated mount point path */ + + nsh_freefullpath(lpath); + return ret; +} +#endif + +/**************************************************************************** + * Name: cmd_umount + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \ + defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_UMOUNT) +int cmd_umount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *fullpath = nsh_getfullpath(vtbl, argv[1]); + int ret = ERROR; + + if (fullpath) + { + /* Perform the umount */ + + ret = umount(fullpath); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "umount", NSH_ERRNO); + } + nsh_freefullpath(fullpath); + } + + return ret; +} +#endif diff --git a/apps/nshlib/nsh_netcmds.c b/apps/nshlib/nsh_netcmds.c new file mode 100644 index 0000000000..cfea5a08a0 --- /dev/null +++ b/apps/nshlib/nsh_netcmds.c @@ -0,0 +1,864 @@ +/**************************************************************************** + * apps/nshlib/nsh_netcmds.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include /* Needed for open */ +#include +#include +#include +#include +#include +#include +#include +#include /* Needed for open */ +#include /* Needed for basename */ +#include + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_NET_STATISTICS +# include +#endif + +#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \ + !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS) +# include +#endif + +#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0 +# include +# include +#endif + +#if defined(CONFIG_NET_TCP) && CONFIG_NFILE_DESCRIPTORS > 0 +# ifndef CONFIG_NSH_DISABLE_WGET +# include +# include +# endif +#endif + +#include "nsh.h" +#include "nsh_console.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define DEFAULT_PING_DATALEN 56 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0 +struct tftpc_args_s +{ + bool binary; /* true:binary ("octect") false:text ("netascii") */ + bool allocated; /* true: destpath is allocated */ + char *destpath; /* Path at destination */ + const char *srcpath; /* Path at src */ + in_addr_t ipaddr; /* Host IP address */ +}; +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \ + !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS) +static uint16_t g_pingid = 0; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ping_newid + ****************************************************************************/ + +#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \ + !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS) +static inline uint16_t ping_newid(void) +{ + irqstate_t save = irqsave(); + uint16_t ret = ++g_pingid; + irqrestore(save); + return ret; +} +#endif + +/**************************************************************************** + * Name: uip_statistics + ****************************************************************************/ + +#if defined(CONFIG_NET_STATISTICS) && !defined(CONFIG_NSH_DISABLE_IFCONFIG) +static inline void uip_statistics(FAR struct nsh_vtbl_s *vtbl) +{ + nsh_output(vtbl, "uIP IP "); +#ifdef CONFIG_NET_TCP + nsh_output(vtbl, " TCP"); +#endif +#ifdef CONFIG_NET_UDP + nsh_output(vtbl, " UDP"); +#endif +#ifdef CONFIG_NET_ICMP + nsh_output(vtbl, " ICMP"); +#endif + nsh_output(vtbl, "\n"); + + /* Received packets */ + + nsh_output(vtbl, "Received %04x",uip_stat.ip.recv); +#ifdef CONFIG_NET_TCP + nsh_output(vtbl, " %04x",uip_stat.tcp.recv); +#endif +#ifdef CONFIG_NET_UDP + nsh_output(vtbl, " %04x",uip_stat.udp.recv); +#endif +#ifdef CONFIG_NET_ICMP + nsh_output(vtbl, " %04x",uip_stat.icmp.recv); +#endif + nsh_output(vtbl, "\n"); + + /* Dropped packets */ + + nsh_output(vtbl, "Dropped %04x",uip_stat.ip.drop); +#ifdef CONFIG_NET_TCP + nsh_output(vtbl, " %04x",uip_stat.tcp.drop); +#endif +#ifdef CONFIG_NET_UDP + nsh_output(vtbl, " %04x",uip_stat.udp.drop); +#endif +#ifdef CONFIG_NET_ICMP + nsh_output(vtbl, " %04x",uip_stat.icmp.drop); +#endif + nsh_output(vtbl, "\n"); + + nsh_output(vtbl, " IP VHL: %04x HBL: %04x\n", + uip_stat.ip.vhlerr, uip_stat.ip.hblenerr); + nsh_output(vtbl, " LBL: %04x Frg: %04x\n", + uip_stat.ip.lblenerr, uip_stat.ip.fragerr); + + nsh_output(vtbl, " Checksum %04x",uip_stat.ip.chkerr); +#ifdef CONFIG_NET_TCP + nsh_output(vtbl, " %04x",uip_stat.tcp.chkerr); +#endif +#ifdef CONFIG_NET_UDP + nsh_output(vtbl, " %04x",uip_stat.udp.chkerr); +#endif +#ifdef CONFIG_NET_ICMP + nsh_output(vtbl, " ----"); +#endif + nsh_output(vtbl, "\n"); + +#ifdef CONFIG_NET_TCP + nsh_output(vtbl, " TCP ACK: %04x SYN: %04x\n", + uip_stat.tcp.ackerr, uip_stat.tcp.syndrop); + nsh_output(vtbl, " RST: %04x %04x\n", + uip_stat.tcp.rst, uip_stat.tcp.synrst); +#endif + + nsh_output(vtbl, " Type %04x",uip_stat.ip.protoerr); +#ifdef CONFIG_NET_TCP + nsh_output(vtbl, " ----"); +#endif +#ifdef CONFIG_NET_UDP + nsh_output(vtbl, " ----"); +#endif +#ifdef CONFIG_NET_ICMP + nsh_output(vtbl, " %04x",uip_stat.icmp.typeerr); +#endif + nsh_output(vtbl, "\n"); + + /* Sent packets */ + + nsh_output(vtbl, "Sent ----",uip_stat.ip.sent); +#ifdef CONFIG_NET_TCP + nsh_output(vtbl, " %04x",uip_stat.tcp.sent); +#endif +#ifdef CONFIG_NET_UDP + nsh_output(vtbl, " %04x",uip_stat.udp.sent); +#endif +#ifdef CONFIG_NET_ICMP + nsh_output(vtbl, " %04x",uip_stat.icmp.sent); +#endif + nsh_output(vtbl, "\n"); + +#ifdef CONFIG_NET_TCP + nsh_output(vtbl, " Rexmit ---- %04x",uip_stat.tcp.rexmit); +#ifdef CONFIG_NET_UDP + nsh_output(vtbl, " ----"); +#endif +#ifdef CONFIG_NET_ICMP + nsh_output(vtbl, " ----"); +#endif + nsh_output(vtbl, "\n"); +#endif + nsh_output(vtbl, "\n"); +} +#else +# define uip_statistics(vtbl) +#endif + + +/**************************************************************************** + * Name: ifconfig_callback + ****************************************************************************/ + +int ifconfig_callback(FAR struct uip_driver_s *dev, void *arg) +{ + struct nsh_vtbl_s *vtbl = (struct nsh_vtbl_s*)arg; + struct in_addr addr; + + nsh_output(vtbl, "%s\tHWaddr %s\n", dev->d_ifname, ether_ntoa(&dev->d_mac)); + addr.s_addr = dev->d_ipaddr; + nsh_output(vtbl, "\tIPaddr:%s ", inet_ntoa(addr)); + addr.s_addr = dev->d_draddr; + nsh_output(vtbl, "DRaddr:%s ", inet_ntoa(addr)); + addr.s_addr = dev->d_netmask; + nsh_output(vtbl, "Mask:%s\n\n", inet_ntoa(addr)); + return OK; +} + +/**************************************************************************** + * Name: tftpc_parseargs + ****************************************************************************/ + +#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0 +int tftpc_parseargs(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv, + struct tftpc_args_s *args) +{ + FAR const char *fmt = g_fmtarginvalid; + bool badarg = false; + int option; + + /* Get the ping options */ + + memset(args, 0, sizeof(struct tftpc_args_s)); + while ((option = getopt(argc, argv, ":bnf:h:")) != ERROR) + { + switch (option) + { + case 'b': + args->binary = true; + break; + + case 'n': + args->binary = false; + break; + + case 'f': + args->destpath = optarg; + break; + + case 'h': + if (!uiplib_ipaddrconv(optarg, (FAR unsigned char*)&args->ipaddr)) + { + nsh_output(vtbl, g_fmtarginvalid, argv[0]); + badarg = true; + } + break; + + case ':': + nsh_output(vtbl, g_fmtargrequired, argv[0]); + badarg = true; + break; + + case '?': + default: + nsh_output(vtbl, g_fmtarginvalid, argv[0]); + badarg = true; + break; + } + } + + /* If a bad argument was encountered, then return without processing the command */ + + if (badarg) + { + return ERROR; + } + + /* There should be exactly one parameter left on the command-line */ + + if (optind == argc-1) + { + args->srcpath = argv[optind]; + } + + /* optind == argc means that there is nothing left on the command-line */ + + else if (optind >= argc) + { + fmt = g_fmtargrequired; + goto errout; + } + + /* optind < argc-1 means that there are too many arguments on the + * command-line + */ + + else + { + fmt = g_fmttoomanyargs; + goto errout; + } + + /* The HOST IP address is also required */ + + if (!args->ipaddr) + { + fmt = g_fmtargrequired; + goto errout; + } + + /* If the destpath was not provided, then we have do a little work. */ + + if (!args->destpath) + { + char *tmp1; + char *tmp2; + + /* Copy the srcpath... baseanme might modify it */ + + fmt = g_fmtcmdoutofmemory; + tmp1 = strdup(args->srcpath); + if (!tmp1) + { + goto errout; + } + + /* Get the basename of the srcpath */ + + tmp2 = basename(tmp1); + if (!tmp2) + { + free(tmp1); + goto errout; + } + + /* Use that basename as the destpath */ + + args->destpath = strdup(tmp2); + free(tmp1); + if (!args->destpath) + { + goto errout; + } + args->allocated = true; + } + + return OK; + +errout: + nsh_output(vtbl, fmt, argv[0]); + return ERROR; +} +#endif + +/**************************************************************************** + * Name: wget_callback + ****************************************************************************/ + +#if defined(CONFIG_NET_TCP) && CONFIG_NFILE_DESCRIPTORS > 0 +#ifndef CONFIG_NSH_DISABLE_WGET +static void wget_callback(FAR char **buffer, int offset, int datend, + FAR int *buflen, FAR void *arg) +{ + (void)write((int)arg, &((*buffer)[offset]), datend - offset); +} +#endif +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cmd_get + ****************************************************************************/ + +#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0 +#ifndef CONFIG_NSH_DISABLE_GET +int cmd_get(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + struct tftpc_args_s args; + char *fullpath; + + /* Parse the input parameter list */ + + if (tftpc_parseargs(vtbl, argc, argv, &args) != OK) + { + return ERROR; + } + + /* Get the full path to the local file */ + + fullpath = nsh_getfullpath(vtbl, args.srcpath); + + /* Then perform the TFTP get operation */ + + if (tftpget(args.srcpath, fullpath, args.ipaddr, args.binary) != OK) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "tftpget", NSH_ERRNO); + } + + /* Release any allocated memory */ + + if (args.allocated) + { + free(args.destpath); + } + free(fullpath); + return OK; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_ifconfig + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_IFCONFIG +int cmd_ifconfig(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + struct in_addr addr; + in_addr_t ip; + + /* With one or no arguments, ifconfig simply shows the status of ethernet + * device: + * + * ifconfig + * ifconfig [nic_name] + */ + + if (argc <= 2) + { + netdev_foreach(ifconfig_callback, vtbl); + uip_statistics(vtbl); + return OK; + } + + /* If both the network interface name and an IP address are supplied as + * arguments, then ifconfig will set the address of the ethernet device: + * + * ifconfig nic_name ip_address + */ + + /* Set host ip address */ + + ip = addr.s_addr = inet_addr(argv[2]); + uip_sethostaddr(argv[1], &addr); + + /* Set gateway */ + + ip = NTOHL(ip); + ip &= ~0x000000ff; + ip |= 0x00000001; + + addr.s_addr = HTONL(ip); + uip_setdraddr(argv[1], &addr); + + /* Set netmask */ + + addr.s_addr = inet_addr("255.255.255.0"); + uip_setnetmask(argv[1], &addr); + + return OK; +} +#endif + +/**************************************************************************** + * Name: cmd_ping + ****************************************************************************/ + +#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \ + !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS) +#ifndef CONFIG_NSH_DISABLE_PING +int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + FAR const char *fmt = g_fmtarginvalid; + const char *staddr; + uip_ipaddr_t ipaddr; + uint32_t start; + uint32_t next; + uint32_t dsec = 10; + uint16_t id; + bool badarg = false; + int count = 10; + int option; + int seqno; + int replies = 0; + int elapsed; + int tmp; + int i; + + /* Get the ping options */ + + while ((option = getopt(argc, argv, ":c:i:")) != ERROR) + { + switch (option) + { + case 'c': + count = atoi(optarg); + if (count < 1 || count > 10000) + { + nsh_output(vtbl, g_fmtargrange, argv[0]); + badarg = true; + } + break; + + case 'i': + tmp = atoi(optarg); + if (tmp < 1 || tmp >= 4294) + { + nsh_output(vtbl, g_fmtargrange, argv[0]); + badarg = true; + } + else + { + dsec = 10 * tmp; + } + break; + + case ':': + nsh_output(vtbl, g_fmtargrequired, argv[0]); + badarg = true; + break; + + case '?': + default: + nsh_output(vtbl, g_fmtarginvalid, argv[0]); + badarg = true; + break; + } + } + + /* If a bad argument was encountered, then return without processing the command */ + + if (badarg) + { + return ERROR; + } + + /* There should be exactly on parameter left on the command-line */ + + if (optind == argc-1) + { + staddr = argv[optind]; + if (!uiplib_ipaddrconv(staddr, (FAR unsigned char*)&ipaddr)) + { + goto errout; + } + } + else if (optind >= argc) + { + fmt = g_fmttoomanyargs; + goto errout; + } + else + { + fmt = g_fmtargrequired; + goto errout; + } + + /* Get the ID to use */ + + id = ping_newid(); + + /* Loop for the specified count */ + + nsh_output(vtbl, "PING %s %d bytes of data\n", staddr, DEFAULT_PING_DATALEN); + start = g_system_timer; + for (i = 1; i <= count; i++) + { + /* Send the ECHO request and wait for the response */ + + next = g_system_timer; + seqno = uip_ping(ipaddr, id, i, DEFAULT_PING_DATALEN, dsec); + + /* Was any response returned? We can tell if a non-negative sequence + * number was returned. + */ + + if (seqno >= 0 && seqno <= i) + { + /* Get the elpased time from the time that the request was + * sent until the response was received. If we got a response + * to an earlier request, then fudge the elpased time. + */ + + elapsed = TICK2MSEC(g_system_timer - next); + if (seqno < i) + { + elapsed += 100*dsec*(i - seqno); + } + + /* Report the receipt of the reply */ + + nsh_output(vtbl, "%d bytes from %s: icmp_seq=%d time=%d ms\n", + DEFAULT_PING_DATALEN, staddr, seqno, elapsed); + replies++; + } + + /* Wait for the remainder of the interval. If the last seqno> 1)) / count; + + nsh_output(vtbl, "%d packets transmitted, %d received, %d%% packet loss, time %d ms\n", + count, replies, tmp, elapsed); + return OK; + +errout: + nsh_output(vtbl, fmt, argv[0]); + return ERROR; +} +#endif +#endif /* CONFIG_NET_ICMP && CONFIG_NET_ICMP_PING */ + +/**************************************************************************** + * Name: cmd_put + ****************************************************************************/ + +#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0 +#ifndef CONFIG_NSH_DISABLE_PUT +int cmd_put(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + struct tftpc_args_s args; + char *fullpath; + + /* Parse the input parameter list */ + + if (tftpc_parseargs(vtbl, argc, argv, &args) != OK) + { + return ERROR; + } + + /* Get the full path to the local file */ + + fullpath = nsh_getfullpath(vtbl, args.srcpath); + + /* Then perform the TFTP put operation */ + + if (tftpput(fullpath, args.destpath, args.ipaddr, args.binary) != OK) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "tftpput", NSH_ERRNO); + } + + /* Release any allocated memory */ + + if (args.allocated) + { + free(args.destpath); + } + free(fullpath); + return OK; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_wget + ****************************************************************************/ + +#if defined(CONFIG_NET_TCP) && CONFIG_NFILE_DESCRIPTORS > 0 +#ifndef CONFIG_NSH_DISABLE_WGET +int cmd_wget(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *localfile = NULL; + char *allocfile = NULL; + char *buffer = NULL; + char *fullpath = NULL; + char *url; + const char *fmt; + bool badarg = false; + int option; + int fd = -1; + int ret; + + /* Get the wget options */ + + while ((option = getopt(argc, argv, ":o:")) != ERROR) + { + switch (option) + { + case 'o': + localfile = optarg; + break; + + case ':': + nsh_output(vtbl, g_fmtargrequired, argv[0]); + badarg = true; + break; + + case '?': + default: + nsh_output(vtbl, g_fmtarginvalid, argv[0]); + badarg = true; + break; + } + } + + /* If a bad argument was encountered, then return without processing the command */ + + if (badarg) + { + return ERROR; + } + + /* There should be exactly on parameter left on the command-line */ + + if (optind == argc-1) + { + url = argv[optind]; + } + else if (optind >= argc) + { + fmt = g_fmttoomanyargs; + goto errout; + } + else + { + fmt = g_fmtargrequired; + goto errout; + } + + /* Get the local file name */ + + if (!localfile) + { + allocfile = strdup(url); + localfile = basename(allocfile); + } + + /* Get the full path to the local file */ + + fullpath = nsh_getfullpath(vtbl, localfile); + + /* Open the local file for writing */ + + fd = open(fullpath, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO); + ret = ERROR; + goto exit; + } + + /* Allocate an I/O buffer */ + + buffer = malloc(512); + if (!buffer) + { + fmt = g_fmtcmdoutofmemory; + goto errout; + } + + /* And perform the wget */ + + ret = wget(url, buffer, 512, wget_callback, (FAR void *)fd); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "wget", NSH_ERRNO); + goto exit; + } + + /* Free allocated resources */ + +exit: + if (fd >= 0) + { + close(fd); + } + if (allocfile) + { + free(allocfile); + } + if (fullpath) + { + free(fullpath); + } + if (buffer) + { + free(buffer); + } + return ret; + +errout: + nsh_output(vtbl, fmt, argv[0]); + ret = ERROR; + goto exit; +} +#endif +#endif + +#endif /* CONFIG_NET */ diff --git a/apps/nshlib/nsh_netinit.c b/apps/nshlib/nsh_netinit.c new file mode 100644 index 0000000000..5d74b30d77 --- /dev/null +++ b/apps/nshlib/nsh_netinit.c @@ -0,0 +1,170 @@ +/**************************************************************************** + * apps/nshlib/nsh_netinit.c + * + * Copyright (C) 2010-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This is influenced by similar logic from uIP: + * + * Author: Adam Dunkels + * Copyright (c) 2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include +#if defined(CONFIG_NSH_DHCPC) +# include +# include +#endif + +#include "nsh.h" + +#ifdef CONFIG_NET + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_netinit + * + * Description: + * Initialize the network per the selected NuttX configuration + * + ****************************************************************************/ + +int nsh_netinit(void) +{ + struct in_addr addr; +#if defined(CONFIG_NSH_DHCPC) + FAR void *handle; +#endif +#if defined(CONFIG_NSH_DHCPC) || defined(CONFIG_NSH_NOMAC) + uint8_t mac[IFHWADDRLEN]; +#endif + +/* Many embedded network interfaces must have a software assigned MAC */ + +#ifdef CONFIG_NSH_NOMAC + mac[0] = 0x00; + mac[1] = 0xe0; + mac[2] = 0xde; + mac[3] = 0xad; + mac[4] = 0xbe; + mac[5] = 0xef; + uip_setmacaddr("eth0", mac); +#endif + + /* Set up our host address */ + +#if !defined(CONFIG_NSH_DHCPC) + addr.s_addr = HTONL(CONFIG_NSH_IPADDR); +#else + addr.s_addr = 0; +#endif + uip_sethostaddr("eth0", &addr); + + /* Set up the default router address */ + + addr.s_addr = HTONL(CONFIG_NSH_DRIPADDR); + uip_setdraddr("eth0", &addr); + + /* Setup the subnet mask */ + + addr.s_addr = HTONL(CONFIG_NSH_NETMASK); + uip_setnetmask("eth0", &addr); + +#if defined(CONFIG_NSH_DHCPC) + /* Set up the resolver */ + + resolv_init(); +#endif + +#if defined(CONFIG_NSH_DHCPC) + /* Get the MAC address of the NIC */ + + uip_getmacaddr("eth0", mac); + + /* Set up the DHCPC modules */ + + handle = dhcpc_open(&mac, IFHWADDRLEN); + + /* Get an IP address. Note that there is no logic for renewing the IP address in this + * example. The address should be renewed in ds.lease_time/2 seconds. + */ + + if (handle) + { + struct dhcpc_state ds; + (void)dhcpc_request(handle, &ds); + uip_sethostaddr("eth1", &ds.ipaddr); + if (ds.netmask.s_addr != 0) + { + uip_setnetmask("eth0", &ds.netmask); + } + if (ds.default_router.s_addr != 0) + { + uip_setdraddr("eth0", &ds.default_router); + } + if (ds.dnsaddr.s_addr != 0) + { + resolv_conf(&ds.dnsaddr); + } + dhcpc_close(handle); + } +#endif + return OK; +} + +#endif /* CONFIG_NET */ diff --git a/apps/nshlib/nsh_parse.c b/apps/nshlib/nsh_parse.c new file mode 100644 index 0000000000..00319a98b9 --- /dev/null +++ b/apps/nshlib/nsh_parse.c @@ -0,0 +1,1367 @@ +/**************************************************************************** + * apps/nshlib/nsh_parse.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef CONFIG_NSH_DISABLEBG +# include +#endif + +#ifdef CONFIG_NSH_BUILTIN_APPS +# include +#endif +#include + +#include "nsh.h" +#include "nsh_console.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Argument list size + * + * argv[0]: The command name. + * argv[1]: The beginning of argument (up to NSH_MAX_ARGUMENTS) + * argv[argc-3]: Possibly '>' or '>>' + * argv[argc-2]: Possibly + * argv[argc-1]: Possibly '&' (if pthreads are enabled) + * argv[argc]: NULL terminating pointer + * + * Maximum size is NSH_MAX_ARGUMENTS+5 + */ + +#ifndef CONFIG_NSH_DISABLEBG +# define MAX_ARGV_ENTRIES (NSH_MAX_ARGUMENTS+5) +#else +# define MAX_ARGV_ENTRIES (NSH_MAX_ARGUMENTS+4) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct cmdmap_s +{ + const char *cmd; /* Name of the command */ + cmd_t handler; /* Function that handles the command */ + uint8_t minargs; /* Minimum number of arguments (including command) */ + uint8_t maxargs; /* Maximum number of arguments (including command) */ + const char *usage; /* Usage instructions for 'help' command */ +}; + +#ifndef CONFIG_NSH_DISABLEBG +struct cmdarg_s +{ + FAR struct nsh_vtbl_s *vtbl; /* For front-end interaction */ + int fd; /* FD for output redirection */ + int argc; /* Number of arguments in argv */ + FAR char *argv[MAX_ARGV_ENTRIES]; /* Argument list */ +}; +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_HELP + static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif + +#ifndef CONFIG_NSH_DISABLE_EXIT + static int cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif +static int cmd_unrecognized(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char g_delim[] = " \t\n"; +static const char g_redirect1[] = ">"; +static const char g_redirect2[] = ">>"; +static const char g_exitstatus[] = "$?"; +static const char g_success[] = "0"; +static const char g_failure[] = "1"; + +static const struct cmdmap_s g_cmdmap[] = +{ +#if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_TEST) + { "[", cmd_lbracket, 4, NSH_MAX_ARGUMENTS, " ]" }, +#endif + +#ifndef CONFIG_NSH_DISABLE_HELP + { "?", cmd_help, 1, 1, NULL }, +#endif + +#if CONFIG_NFILE_DESCRIPTORS > 0 +# ifndef CONFIG_NSH_DISABLE_CAT + { "cat", cmd_cat, 2, NSH_MAX_ARGUMENTS, " [ [ ...]]" }, +# endif +#ifndef CONFIG_DISABLE_ENVIRON +# ifndef CONFIG_NSH_DISABLE_CD + { "cd", cmd_cd, 1, 2, "[|-|~|..]" }, +# endif +#endif +# ifndef CONFIG_NSH_DISABLE_CP + { "cp", cmd_cp, 3, 3, " " }, +# endif +#endif + +#if defined (CONFIG_RTC) && !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_NSH_DISABLE_DATE) + { "date", cmd_date, 1, 3, "[-s \"MMM DD HH:MM:SS YYYY\"]" }, +#endif + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_NSH_DISABLE_DD) + { "dd", cmd_dd, 3, 6, "if= of= [bs=] [count=] [skip=]" }, +# endif + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \ + defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_DF) + { "df", cmd_df, 1, 1, NULL }, +#endif + +#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_SYSLOG) && \ + defined(CONFIG_RAMLOG_SYSLOG) && !defined(CONFIG_NSH_DISABLE_DMESG) + { "dmesg", cmd_dmesg, 1, 1, NULL }, +#endif + +#ifndef CONFIG_NSH_DISABLE_ECHO +# ifndef CONFIG_DISABLE_ENVIRON + { "echo", cmd_echo, 0, NSH_MAX_ARGUMENTS, "[ [...]]" }, +# else + { "echo", cmd_echo, 0, NSH_MAX_ARGUMENTS, "[ [...]]" }, +# endif +#endif + +#ifndef CONFIG_NSH_DISABLE_EXEC + { "exec", cmd_exec, 2, 3, "" }, +#endif +#ifndef CONFIG_NSH_DISABLE_EXIT + { "exit", cmd_exit, 1, 1, NULL }, +#endif + +#ifndef CONFIG_NSH_DISABLE_FREE + { "free", cmd_free, 1, 1, NULL }, +#endif + +#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0 +# ifndef CONFIG_NSH_DISABLE_GET + { "get", cmd_get, 4, 7, "[-b|-n] [-f ] -h " }, +# endif +#endif + +#ifndef CONFIG_NSH_DISABLE_HELP + { "help", cmd_help, 1, 1, NULL }, +#endif + +#ifdef CONFIG_NET +# ifndef CONFIG_NSH_DISABLE_IFCONFIG + { "ifconfig", cmd_ifconfig, 1, 3, "[nic_name [ip]]" }, +# endif +#endif + +#ifndef CONFIG_DISABLE_SIGNALS +# ifndef CONFIG_NSH_DISABLE_KILL + { "kill", cmd_kill, 3, 3, "- " }, +# endif +#endif + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) +# ifndef CONFIG_NSH_DISABLE_LOSETUP + { "losetup", cmd_losetup, 3, 6, "[-d ] | [[-o ] [-r] ]" }, +# endif +#endif + +#if CONFIG_NFILE_DESCRIPTORS > 0 +# ifndef CONFIG_NSH_DISABLE_LS + { "ls", cmd_ls, 1, 5, "[-lRs] " }, +# endif +#endif + +#ifndef CONFIG_NSH_DISABLE_MB + { "mb", cmd_mb, 2, 3, "[=][ ]" }, +#endif + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE) +# ifndef CONFIG_NSH_DISABLE_MKDIR + { "mkdir", cmd_mkdir, 2, 2, "" }, +# endif +#endif + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_FAT) +# ifndef CONFIG_NSH_DISABLE_MKFATFS + { "mkfatfs", cmd_mkfatfs, 2, 2, "" }, +# endif +#endif + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 +# ifndef CONFIG_NSH_DISABLE_MKFIFO + { "mkfifo", cmd_mkfifo, 2, 2, "" }, +# endif +#endif + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE) +# ifndef CONFIG_NSH_DISABLE_MKRD + { "mkrd", cmd_mkrd, 2, 6, "[-m ] [-s ] " }, +# endif +#endif + +#ifndef CONFIG_NSH_DISABLE_MH + { "mh", cmd_mh, 2, 3, "[=][ ]" }, +#endif + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_READABLE) +# ifndef CONFIG_NSH_DISABLE_MOUNT + { "mount", cmd_mount, 1, 5, "[-t ]" }, +# endif +#endif + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE) +# ifndef CONFIG_NSH_DISABLE_MV + { "mv", cmd_mv, 3, 3, " " }, +# endif +#endif + +#ifndef CONFIG_NSH_DISABLE_MW + { "mw", cmd_mw, 2, 3, "[=][ ]" }, +#endif + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && \ + defined(CONFIG_NET) && defined(CONFIG_NFS) +# ifndef CONFIG_NSH_DISABLE_NFSMOUNT + { "nfsmount", cmd_nfsmount, 4, 4, " " }, +# endif +#endif + +#if defined(CONFIG_NET) && defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \ + !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS) +# ifndef CONFIG_NSH_DISABLE_PING + { "ping", cmd_ping, 2, 6, "[-c ] [-i ] " }, +# endif +#endif + +#ifndef CONFIG_NSH_DISABLE_PS + { "ps", cmd_ps, 1, 1, NULL }, +#endif + +#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0 +# ifndef CONFIG_NSH_DISABLE_PUT + { "put", cmd_put, 4, 7, "[-b|-n] [-f ] -h " }, +# endif +#endif + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON) +# ifndef CONFIG_NSH_DISABLE_PWD + { "pwd", cmd_pwd, 1, 1, NULL }, +# endif +#endif + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE) +# ifndef CONFIG_NSH_DISABLE_RM + { "rm", cmd_rm, 2, 2, "" }, +# endif +# ifndef CONFIG_NSH_DISABLE_RMDIR + { "rmdir", cmd_rmdir, 2, 2, "" }, +# endif +#endif + +#ifndef CONFIG_DISABLE_ENVIRON +# ifndef CONFIG_NSH_DISABLE_SET + { "set", cmd_set, 3, 3, " " }, +# endif +#endif + +#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_NSH_DISABLESCRIPT) +# ifndef CONFIG_NSH_DISABLE_SH + { "sh", cmd_sh, 2, 2, "" }, +# endif +#endif + +#ifndef CONFIG_DISABLE_SIGNALS +# ifndef CONFIG_NSH_DISABLE_SLEEP + { "sleep", cmd_sleep, 2, 2, "" }, +# endif +#endif + +#if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_TEST) + { "test", cmd_test, 3, NSH_MAX_ARGUMENTS, "" }, +#endif + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_READABLE) +# ifndef CONFIG_NSH_DISABLE_UMOUNT + { "umount", cmd_umount, 2, 2, "" }, +# endif +#endif + +#ifndef CONFIG_DISABLE_ENVIRON +# ifndef CONFIG_NSH_DISABLE_UNSET + { "unset", cmd_unset, 2, 2, "" }, +# endif +#endif + +#ifndef CONFIG_DISABLE_SIGNALS +# ifndef CONFIG_NSH_DISABLE_USLEEP + { "usleep", cmd_usleep, 2, 2, "" }, +# endif +#endif + +#if defined(CONFIG_NET_TCP) && CONFIG_NFILE_DESCRIPTORS > 0 +# ifndef CONFIG_NSH_DISABLE_GET + { "wget", cmd_wget, 2, 4, "[-o ] " }, +# endif +#endif + +#ifndef CONFIG_NSH_DISABLE_XD + { "xd", cmd_xd, 3, 3, " " }, +#endif + { NULL, NULL, 1, 1, NULL } +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* If NuttX versioning information is available, Include that information + * in the NSH greeting. + */ + +#if CONFIG_VERSION_MAJOR != 0 || CONFIG_VERSION_MINOR != 0 +const char g_nshgreeting[] = "\nNuttShell (NSH) NuttX-" CONFIG_VERSION_STRING "\n"; +#else +const char g_nshgreeting[] = "\nNuttShell (NSH)\n"; +#endif + +/* The NSH prompt */ + +const char g_nshprompt[] = "nsh> "; + +/* Common, message formats */ + +const char g_nshsyntax[] = "nsh: %s: syntax error\n"; +const char g_fmtargrequired[] = "nsh: %s: missing required argument(s)\n"; +const char g_fmtarginvalid[] = "nsh: %s: argument invalid\n"; +const char g_fmtargrange[] = "nsh: %s: value out of range\n"; +const char g_fmtcmdnotfound[] = "nsh: %s: command not found\n"; +const char g_fmtnosuch[] = "nsh: %s: no such %s: %s\n"; +const char g_fmttoomanyargs[] = "nsh: %s: too many arguments\n"; +const char g_fmtdeepnesting[] = "nsh: %s: nesting too deep\n"; +const char g_fmtcontext[] = "nsh: %s: not valid in this context\n"; +#ifdef CONFIG_NSH_STRERROR +const char g_fmtcmdfailed[] = "nsh: %s: %s failed: %s\n"; +#else +const char g_fmtcmdfailed[] = "nsh: %s: %s failed: %d\n"; +#endif +const char g_fmtcmdoutofmemory[] = "nsh: %s: out of memory\n"; +const char g_fmtinternalerror[] = "nsh: %s: Internal error\n"; +#ifndef CONFIG_DISABLE_SIGNALS +const char g_fmtsignalrecvd[] = "nsh: %s: Interrupted by signal\n"; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cmd_help + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_HELP +static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + const struct cmdmap_s *ptr; +#ifdef CONFIG_NSH_BUILTIN_APPS + FAR const char * name; + int i; +#endif + + nsh_output(vtbl, "NSH command forms:\n"); +#ifndef CONFIG_NSH_DISABLEBG + nsh_output(vtbl, " [nice [-d >]] [> |>> ] [&]\n"); +#else + nsh_output(vtbl, " [> |>> ]\n"); +#endif +#ifndef CONFIG_NSH_DISABLESCRIPT + nsh_output(vtbl, "OR\n"); + nsh_output(vtbl, " if \n"); + nsh_output(vtbl, " then\n"); + nsh_output(vtbl, " [sequence of ]\n"); + nsh_output(vtbl, " else\n"); + nsh_output(vtbl, " [sequence of ]\n"); + nsh_output(vtbl, " fi\n"); +#endif + nsh_output(vtbl, "Where is one of:\n"); + for (ptr = g_cmdmap; ptr->cmd; ptr++) + { + if (ptr->usage) + { + nsh_output(vtbl, " %s %s\n", ptr->cmd, ptr->usage); + } + else + { + nsh_output(vtbl, " %s\n", ptr->cmd); + } + } + + /* List the set of available built-in commands */ + +#ifdef CONFIG_NSH_BUILTIN_APPS + nsh_output(vtbl, "\nBuiltin Apps:\n"); + for (i = 0; (name = namedapp_getname(i)) != NULL; i++) + { + nsh_output(vtbl, " %s\n", name); + } +#endif + + return OK; +} +#endif + +/**************************************************************************** + * Name: cmd_unrecognized + ****************************************************************************/ + +static int cmd_unrecognized(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + nsh_output(vtbl, g_fmtcmdnotfound, argv[0]); + return ERROR; +} + +/**************************************************************************** + * Name: cmd_exit + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_EXIT +static int cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + nsh_exit(vtbl, 0); + return OK; +} +#endif + +/**************************************************************************** + * Name: nsh_execute + * + * Description: + * Exectue the command in argv[0] + * + * Returned Value: + * <0 If exec_namedapp() fails, then the negated errno value + * is returned. + * -1 (ERRROR) if the command was unsuccessful + * 0 (OK) if the command was successful + * 1 if an application task was spawned successfully, but + * returned failure exit status. + * + ****************************************************************************/ + +static int nsh_execute(FAR struct nsh_vtbl_s *vtbl, int argc, char *argv[]) +{ + const struct cmdmap_s *cmdmap; + const char *cmd; + cmd_t handler = cmd_unrecognized; + int ret; + + /* The form of argv is: + * + * argv[0]: The command name. This is argv[0] when the arguments + * are, finally, received by the command vtblr + * argv[1]: The beginning of argument (up to NSH_MAX_ARGUMENTS) + * argv[argc]: NULL terminating pointer + */ + + cmd = argv[0]; + + /* Try to find a command in the application library. */ + +#ifdef CONFIG_NSH_BUILTIN_APPS + ret = nsh_execapp(vtbl, cmd, argv); + + /* If the built-in application was successfully started, return OK + * or 1 (if the application returned a non-zero exit status). + */ + + if (ret >= 0) + { + return ret; + } +#endif + + /* See if the command is one that we understand */ + + for (cmdmap = g_cmdmap; cmdmap->cmd; cmdmap++) + { + if (strcmp(cmdmap->cmd, cmd) == 0) + { + /* Check if a valid number of arguments was provided. We + * do this simple, imperfect checking here so that it does + * not have to be performed in each command. + */ + + if (argc < cmdmap->minargs) + { + /* Fewer than the minimum number were provided */ + + nsh_output(vtbl, g_fmtargrequired, cmd); + return ERROR; + } + else if (argc > cmdmap->maxargs) + { + /* More than the maximum number were provided */ + + nsh_output(vtbl, g_fmttoomanyargs, cmd); + return ERROR; + } + else + { + /* A valid number of arguments were provided (this does + * not mean they are right). + */ + + handler = cmdmap->handler; + break; + } + } + } + + ret = handler(vtbl, argc, argv); + return ret; +} + +/**************************************************************************** + * Name: nsh_releaseargs + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLEBG +static void nsh_releaseargs(struct cmdarg_s *arg) +{ + FAR struct nsh_vtbl_s *vtbl = arg->vtbl; + int i; + + /* If the output was redirected, then file descriptor should + * be closed. The created task has its one, independent copy of + * the file descriptor + */ + + if (vtbl->np.np_redirect) + { + (void)close(arg->fd); + } + + /* Released the cloned vtbl instance */ + + nsh_release(vtbl); + + /* Release the cloned args */ + + for (i = 0; i < arg->argc; i++) + { + free(arg->argv[i]); + } + free(arg); +} +#endif + +/**************************************************************************** + * Name: nsh_child + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLEBG +static pthread_addr_t nsh_child(pthread_addr_t arg) +{ + struct cmdarg_s *carg = (struct cmdarg_s *)arg; + int ret; + + dbg("BG %s\n", carg->argv[0]); + + /* Execute the specified command on the child thread */ + + ret = nsh_execute(carg->vtbl, carg->argc, carg->argv); + + /* Released the cloned arguments */ + + dbg("BG %s complete\n", carg->argv[0]); + nsh_releaseargs(carg); + return (void*)ret; +} +#endif + +/**************************************************************************** + * Name: nsh_cloneargs + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLEBG +static inline struct cmdarg_s *nsh_cloneargs(FAR struct nsh_vtbl_s *vtbl, + int fd, int argc, char *argv[]) +{ + struct cmdarg_s *ret = (struct cmdarg_s *)zalloc(sizeof(struct cmdarg_s)); + int i; + + if (ret) + { + ret->vtbl = vtbl; + ret->fd = fd; + ret->argc = argc; + + for (i = 0; i < argc; i++) + { + ret->argv[i] = strdup(argv[i]); + } + } + return ret; +} +#endif + +/**************************************************************************** + * Name: nsh_argument + ****************************************************************************/ + +char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, char **saveptr) +{ + char *pbegin = *saveptr; + char *pend = NULL; + const char *term; +#ifndef CONFIG_DISABLE_ENVIRON + bool quoted = false; +#endif + + /* Find the beginning of the next token */ + + for (; + *pbegin && strchr(g_delim, *pbegin) != NULL; + pbegin++); + + /* If we are at the end of the string with nothing + * but delimiters found, then return NULL. + */ + + if (!*pbegin) + { + return NULL; + } + + /* Does the token begin with '>' -- redirection of output? */ + + if (*pbegin == '>') + { + /* Yes.. does it begin with ">>"? */ + + if (*(pbegin + 1) == '>') + { + *saveptr = pbegin + 2; + pbegin = (char*)g_redirect2; + } + else + { + *saveptr = pbegin + 1; + pbegin = (char*)g_redirect1; + } + } + + /* Does the token begin with '#' -- comment */ + + else if (*pbegin == '#') + { + /* Return NULL meaning that we are at the end of the line */ + + *saveptr = pbegin; + pbegin = NULL; + } + else + { + /* Otherwise, we are going to have to parse to find the end of + * the token. Does the token begin with '"'? + */ + + if (*pbegin == '"') + { + /* Yes.. then only another '"' can terminate the string */ + + pbegin++; + term = "\""; +#ifndef CONFIG_DISABLE_ENVIRON + quoted = true; +#endif + } + else + { + /* No, then any of the usual terminators will terminate the argument */ + + term = g_delim; + } + + /* Find the end of the string */ + + for (pend = pbegin + 1; + *pend && strchr(term, *pend) == NULL; + pend++); + + /* pend either points to the end of the string or to + * the first delimiter after the string. + */ + + if (*pend) + { + /* Turn the delimiter into a null terminator */ + + *pend++ = '\0'; + } + + /* Save the pointer where we left off */ + + *saveptr = pend; + +#ifndef CONFIG_DISABLE_ENVIRON + /* Check for references to environment variables */ + + if (pbegin[0] == '$' && !quoted) + { + /* Check for built-in variables */ + + if (strcmp(pbegin, g_exitstatus) == 0) + { + if (vtbl->np.np_fail) + { + return (char*)g_failure; + } + else + { + return (char*)g_success; + } + } + + /* Not a built-in? Return the value of the environment variable with this name */ + + else + { + char *value = getenv(pbegin+1); + if (value) + { + return value; + } + else + { + return (char*)""; + } + } + } +#endif + } + + /* Return the beginning of the token. */ + + return pbegin; +} + +/**************************************************************************** + * Name: nsh_cmdenabled + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLESCRIPT +static inline bool nsh_cmdenabled(FAR struct nsh_vtbl_s *vtbl) +{ + struct nsh_parser_s *np = &vtbl->np; + bool ret = !np->np_st[np->np_ndx].ns_disabled; + if (ret) + { + switch (np->np_st[np->np_ndx].ns_state) + { + case NSH_PARSER_NORMAL : + case NSH_PARSER_IF: + default: + break; + + case NSH_PARSER_THEN: + ret = !np->np_st[np->np_ndx].ns_ifcond; + break; + + case NSH_PARSER_ELSE: + ret = np->np_st[np->np_ndx].ns_ifcond; + break; + } + } + return ret; +} +#endif + +/**************************************************************************** + * Name: nsh_ifthenelse + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLESCRIPT +static inline int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, FAR char **saveptr) +{ + struct nsh_parser_s *np = &vtbl->np; + FAR char *cmd = *ppcmd; + bool disabled; + + if (cmd) + { + /* Check if the command is preceeded by "if" */ + + if (strcmp(cmd, "if") == 0) + { + /* Get the cmd following the if */ + + *ppcmd = nsh_argument(vtbl, saveptr); + if (!*ppcmd) + { + nsh_output(vtbl, g_fmtarginvalid, "if"); + goto errout; + } + + /* Verify that "if" is valid in this context */ + + if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_NORMAL && + np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN && + np->np_st[np->np_ndx].ns_state != NSH_PARSER_ELSE) + { + nsh_output(vtbl, g_fmtcontext, "if"); + goto errout; + } + + /* Check if we have exceeded the maximum depth of nesting */ + + if (np->np_ndx >= CONFIG_NSH_NESTDEPTH-1) + { + nsh_output(vtbl, g_fmtdeepnesting, "if"); + goto errout; + } + + /* "Push" the old state and set the new state */ + + disabled = !nsh_cmdenabled(vtbl); + np->np_ndx++; + np->np_st[np->np_ndx].ns_state = NSH_PARSER_IF; + np->np_st[np->np_ndx].ns_disabled = disabled; + np->np_st[np->np_ndx].ns_ifcond = false; + } + else if (strcmp(cmd, "then") == 0) + { + /* Get the cmd following the then -- there shouldn't be one */ + + *ppcmd = nsh_argument(vtbl, saveptr); + if (*ppcmd) + { + nsh_output(vtbl, g_fmtarginvalid, "then"); + goto errout; + } + + /* Verify that "then" is valid in this context */ + + if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_IF) + { + nsh_output(vtbl, g_fmtcontext, "then"); + goto errout; + } + np->np_st[np->np_ndx].ns_state = NSH_PARSER_THEN; + } + else if (strcmp(cmd, "else") == 0) + { + /* Get the cmd following the else -- there shouldn't be one */ + + *ppcmd = nsh_argument(vtbl, saveptr); + if (*ppcmd) + { + nsh_output(vtbl, g_fmtarginvalid, "else"); + goto errout; + } + + /* Verify that "then" is valid in this context */ + + if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN) + { + nsh_output(vtbl, g_fmtcontext, "else"); + goto errout; + } + np->np_st[np->np_ndx].ns_state = NSH_PARSER_ELSE; + } + else if (strcmp(cmd, "fi") == 0) + { + /* Get the cmd following the fi -- there should be one */ + + *ppcmd = nsh_argument(vtbl, saveptr); + if (*ppcmd) + { + nsh_output(vtbl, g_fmtarginvalid, "fi"); + goto errout; + } + + /* Verify that "fi" is valid in this context */ + + if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN && + np->np_st[np->np_ndx].ns_state != NSH_PARSER_ELSE) + { + nsh_output(vtbl, g_fmtcontext, "fi"); + goto errout; + } + + if (np->np_ndx < 1) /* Shouldn't happen */ + { + nsh_output(vtbl, g_fmtinternalerror, "if"); + goto errout; + } + + /* "Pop" the previous state */ + + np->np_ndx--; + } + else if (np->np_st[np->np_ndx].ns_state == NSH_PARSER_IF) + { + nsh_output(vtbl, g_fmtcontext, cmd); + goto errout; + } + } + return OK; + +errout: + np->np_ndx = 0; + np->np_st[0].ns_state = NSH_PARSER_NORMAL; + np->np_st[0].ns_disabled = false; + np->np_st[0].ns_ifcond = false; + return ERROR; +} +#endif + +/**************************************************************************** + * Name: nsh_saveresult + ****************************************************************************/ + +static inline int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, bool result) +{ + struct nsh_parser_s *np = &vtbl->np; + +#ifndef CONFIG_NSH_DISABLESCRIPT + if (np->np_st[np->np_ndx].ns_state == NSH_PARSER_IF) + { + np->np_fail = false; + np->np_st[np->np_ndx].ns_ifcond = result; + return OK; + } + else +#endif + { + np->np_fail = result; + return result ? ERROR : OK; + } +} + +/**************************************************************************** + * Name: nsh_nice + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLEBG +static inline int nsh_nice(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, FAR char **saveptr) +{ + FAR char *cmd = *ppcmd; + + vtbl->np.np_nice = 0; + if (cmd) + { + /* Check if the command is preceded by "nice" */ + + if (strcmp(cmd, "nice") == 0) + { + /* Nicenesses range from -20 (most favorable scheduling) to 19 + * (least favorable). Default is 10. + */ + + vtbl->np.np_nice = 10; + + /* Get the cmd (or -d option of nice command) */ + + cmd = nsh_argument(vtbl, saveptr); + if (cmd && strcmp(cmd, "-d") == 0) + { + FAR char *val = nsh_argument(vtbl, saveptr); + if (val) + { + char *endptr; + vtbl->np.np_nice = (int)strtol(val, &endptr, 0); + if (vtbl->np.np_nice > 19 || vtbl->np.np_nice < -20 || + endptr == val || *endptr != '\0') + { + nsh_output(vtbl, g_fmtarginvalid, "nice"); + return ERROR; + } + cmd = nsh_argument(vtbl, saveptr); + } + } + + /* Return the real command name */ + + *ppcmd = cmd; + } + } + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_parse + * + * Description: + * This function parses and executes one NSH command. + * + ****************************************************************************/ + +int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) +{ + FAR char *argv[MAX_ARGV_ENTRIES]; + FAR char *saveptr; + FAR char *cmd; + FAR char *redirfile = NULL; + int fd = -1; + int oflags = 0; + int argc; + int ret; + + /* Initialize parser state */ + + memset(argv, 0, MAX_ARGV_ENTRIES*sizeof(FAR char *)); +#ifndef CONFIG_NSH_DISABLEBG + vtbl->np.np_bg = false; +#endif + vtbl->np.np_redirect = false; + + /* Parse out the command at the beginning of the line */ + + saveptr = cmdline; + cmd = nsh_argument(vtbl, &saveptr); + + /* Handler if-then-else-fi */ + +#ifndef CONFIG_NSH_DISABLESCRIPT + if (nsh_ifthenelse(vtbl, &cmd, &saveptr) != 0) + { + goto errout; + } +#endif + + /* Handle nice */ + +#ifndef CONFIG_NSH_DISABLEBG + if (nsh_nice(vtbl, &cmd, &saveptr) != 0) + { + goto errout; + } +#endif + + /* Check if any command was provided -OR- if command processing is + * currently disabled. + */ + +#ifndef CONFIG_NSH_DISABLESCRIPT + if (!cmd || !nsh_cmdenabled(vtbl)) +#else + if (!cmd) +#endif + { + /* An empty line is not an error and an unprocessed command cannot + * generate an error, but neither should they change the last + * command status. + */ + + return OK; + } + + /* Parse all of the arguments following the command name. The form + * of argv is: + * + * argv[0]: The command name. + * argv[1]: The beginning of argument (up to NSH_MAX_ARGUMENTS) + * argv[argc-3]: Possibly '>' or '>>' + * argv[argc-2]: Possibly + * argv[argc-1]: Possibly '&' + * argv[argc]: NULL terminating pointer + * + * Maximum size is NSH_MAX_ARGUMENTS+5 + */ + + argv[0] = cmd; + for (argc = 1; argc < MAX_ARGV_ENTRIES-1; argc++) + { + argv[argc] = nsh_argument(vtbl, &saveptr); + if (!argv[argc]) + { + break; + } + } + + argv[argc] = NULL; + + /* Check if the command should run in background */ + +#ifndef CONFIG_NSH_DISABLEBG + if (argc > 1 && strcmp(argv[argc-1], "&") == 0) + { + vtbl->np.np_bg = true; + argv[argc-1] = NULL; + argc--; + } +#endif + + /* Check if the output was re-directed using > or >> */ + + if (argc > 2) + { + /* Check for redirection to a new file */ + + if (strcmp(argv[argc-2], g_redirect1) == 0) + { + vtbl->np.np_redirect = true; + oflags = O_WRONLY|O_CREAT|O_TRUNC; + redirfile = nsh_getfullpath(vtbl, argv[argc-1]); + argc -= 2; + } + + /* Check for redirection by appending to an existing file */ + + else if (strcmp(argv[argc-2], g_redirect2) == 0) + { + vtbl->np.np_redirect = true; + oflags = O_WRONLY|O_CREAT|O_APPEND; + redirfile = nsh_getfullpath(vtbl, argv[argc-1]); + argc -= 2; + } + } + + /* Redirected output? */ + + if (vtbl->np.np_redirect) + { + /* Open the redirection file. This file will eventually + * be closed by a call to either nsh_release (if the command + * is executed in the background) or by nsh_undirect if the + * command is executed in the foreground. + */ + + fd = open(redirfile, oflags, 0666); + nsh_freefullpath(redirfile); + redirfile = NULL; + + if (fd < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, cmd, "open", NSH_ERRNO); + goto errout; + } + } + + /* Check if the maximum number of arguments was exceeded */ + + if (argc > NSH_MAX_ARGUMENTS) + { + nsh_output(vtbl, g_fmttoomanyargs, cmd); + } + + /* Handle the case where the command is executed in background. + * However is app is to be started as namedapp new process will + * be created anyway, so skip this step. */ + +#ifndef CONFIG_NSH_DISABLEBG + if (vtbl->np.np_bg +#ifdef CONFIG_NSH_BUILTIN_APPS + && namedapp_isavail(argv[0]) < 0 +#endif + ) + { + struct sched_param param; + struct nsh_vtbl_s *bkgvtbl; + struct cmdarg_s *args; + pthread_attr_t attr; + pthread_t thread; + + /* Get a cloned copy of the vtbl with reference count=1. + * after the command has been processed, the nsh_release() call + * at the end of nsh_child() will destroy the clone. + */ + + bkgvtbl = nsh_clone(vtbl); + if (!bkgvtbl) + { + goto errout_with_redirect; + } + + /* Create a container for the command arguments */ + + args = nsh_cloneargs(bkgvtbl, fd, argc, argv); + if (!args) + { + nsh_release(bkgvtbl); + goto errout_with_redirect; + } + + /* Handle redirection of output via a file descriptor */ + + if (vtbl->np.np_redirect) + { + (void)nsh_redirect(bkgvtbl, fd, NULL); + } + + /* Get the execution priority of this task */ + + ret = sched_getparam(0, ¶m); + if (ret != 0) + { + nsh_output(vtbl, g_fmtcmdfailed, cmd, "sched_getparm", NSH_ERRNO); + nsh_releaseargs(args); + nsh_release(bkgvtbl); + goto errout; + } + + /* Determine the priority to execute the command */ + + if (vtbl->np.np_nice != 0) + { + int priority = param.sched_priority - vtbl->np.np_nice; + if (vtbl->np.np_nice < 0) + { + int max_priority = sched_get_priority_max(SCHED_NSH); + if (priority > max_priority) + { + priority = max_priority; + } + } + else + { + int min_priority = sched_get_priority_min(SCHED_NSH); + if (priority < min_priority) + { + priority = min_priority; + } + } + param.sched_priority = priority; + } + + /* Set up the thread attributes */ + + (void)pthread_attr_init(&attr); + (void)pthread_attr_setschedpolicy(&attr, SCHED_NSH); + (void)pthread_attr_setschedparam(&attr, ¶m); + + /* Execute the command as a separate thread at the appropriate priority */ + + ret = pthread_create(&thread, &attr, nsh_child, (pthread_addr_t)args); + if (ret != 0) + { + nsh_output(vtbl, g_fmtcmdfailed, cmd, "pthread_create", NSH_ERRNO_OF(ret)); + nsh_releaseargs(args); + nsh_release(bkgvtbl); + goto errout; + } + + nsh_output(vtbl, "%s [%d:%d]\n", cmd, thread, param.sched_priority); + } + else +#endif + { + uint8_t save[SAVE_SIZE]; + + /* Handle redirection of output via a file descriptor */ + + if (vtbl->np.np_redirect) + { + nsh_redirect(vtbl, fd, save); + } + + /* Then execute the command in "foreground" -- i.e., while the user waits + * for the next prompt. nsh_execute will return: + * + * -1 (ERRROR) if the command was unsuccessful + * 0 (OK) if the command was successful + * 1 if an application task was spawned successfully, but + * returned failure exit status. + */ + + ret = nsh_execute(vtbl, argc, argv); + + /* Restore the original output. Undirect will close the redirection + * file descriptor. + */ + + if (vtbl->np.np_redirect) + { + nsh_undirect(vtbl, save); + } + + /* Treat both errors and non-zero return codes as "errors" so that + * it is possible to test for non-zero returns in nsh scripts. + */ + + if (ret != OK) + { + goto errout; + } + } + + /* Return success if the command succeeded (or at least, starting of the + * command task succeeded). + */ + + return nsh_saveresult(vtbl, false); + +#ifndef CONFIG_NSH_DISABLEBG +errout_with_redirect: + if (vtbl->np.np_redirect) + { + close(fd); + } +#endif +errout: + return nsh_saveresult(vtbl, true); +} diff --git a/apps/nshlib/nsh_proccmds.c b/apps/nshlib/nsh_proccmds.c new file mode 100644 index 0000000000..487214501f --- /dev/null +++ b/apps/nshlib/nsh_proccmds.c @@ -0,0 +1,310 @@ +/**************************************************************************** + * apps/nshlib/nsh_proccmds.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "nsh.h" +#include "nsh_console.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The returned value should be zero for sucess or TRUE or non zero for + * failure or FALSE. + */ + +typedef int (*exec_t)(void); + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_PS +static const char *g_statenames[] = +{ + "INVALID ", + "PENDING ", + "READY ", + "RUNNING ", + "INACTIVE", + "WAITSEM ", +#ifndef CONFIG_DISABLE_MQUEUE + "WAITSIG ", +#endif +#ifndef CONFIG_DISABLE_MQUEUE + "MQNEMPTY", + "MQNFULL " +#endif +}; + +static const char *g_ttypenames[4] = +{ + "TASK ", + "PTHREAD", + "KTHREAD", + "--?-- " +}; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ps_task + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_PS +static void ps_task(FAR _TCB *tcb, FAR void *arg) +{ + struct nsh_vtbl_s *vtbl = (struct nsh_vtbl_s*)arg; +#if CONFIG_MAX_TASK_ARGS > 2 + int i; +#endif + + /* Show task status */ + + nsh_output(vtbl, "%5d %3d %4s %7s%c%c %8s ", + tcb->pid, tcb->sched_priority, + tcb->flags & TCB_FLAG_ROUND_ROBIN ? "RR " : "FIFO", + g_ttypenames[(tcb->flags & TCB_FLAG_TTYPE_MASK) >> TCB_FLAG_TTYPE_SHIFT], + tcb->flags & TCB_FLAG_NONCANCELABLE ? 'N' : ' ', + tcb->flags & TCB_FLAG_CANCEL_PENDING ? 'P' : ' ', + g_statenames[tcb->task_state]); + + /* Show task name and arguments */ + + nsh_output(vtbl, "%s(", tcb->argv[0]); + + /* Special case 1st argument (no comma) */ + + if (tcb->argv[1]) + { + nsh_output(vtbl, "%p", tcb->argv[1]); + } + + /* Then any additional arguments */ + +#if CONFIG_MAX_TASK_ARGS > 2 + for (i = 2; i <= CONFIG_MAX_TASK_ARGS && tcb->argv[i]; i++) + { + nsh_output(vtbl, ", %p", tcb->argv[i]); + } +#endif + nsh_output(vtbl, ")\n"); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cmd_exec + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_EXEC +int cmd_exec(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *endptr; + uintptr_t addr; + + addr = (uintptr_t)strtol(argv[1], &endptr, 0); + if (!addr || endptr == argv[1] || *endptr != '\0') + { + nsh_output(vtbl, g_fmtarginvalid, argv[0]); + return ERROR; + } + + nsh_output(vtbl, "Calling %p\n", (exec_t)addr); + return ((exec_t)addr)(); +} +#endif + +/**************************************************************************** + * Name: cmd_ps + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_PS +int cmd_ps(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + nsh_output(vtbl, "PID PRI SCHD TYPE NP STATE NAME\n"); + sched_foreach(ps_task, vtbl); + return OK; +} +#endif + +/**************************************************************************** + * Name: cmd_kill + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_SIGNALS +#ifndef CONFIG_NSH_DISABLE_KILL +int cmd_kill(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *ptr; + char *endptr; + long signal; + long pid; + + /* Check incoming parameters. The first parameter should be "-" */ + + ptr = argv[1]; + if (*ptr != '-' || ptr[1] < '0' || ptr[1] > '9') + { + goto invalid_arg; + } + + /* Extract the signal number */ + + signal = strtol(&ptr[1], &endptr, 0); + + /* The second parameter should be */ + + ptr = argv[2]; + if (*ptr < '0' || *ptr > '9') + { + goto invalid_arg; + } + + /* Extract athe pid */ + + pid = strtol(ptr, &endptr, 0); + + /* Send the signal. Kill return values: + * + * EINVAL An invalid signal was specified. + * EPERM The process does not have permission to send the signal to any + * of the target processes. + * ESRCH The pid or process group does not exist. + * ENOSYS Do not support sending signals to process groups. + */ + + if (kill((pid_t)pid, (int)signal) == 0) + { + return OK; + } + + switch (errno) + { + case EINVAL: + goto invalid_arg; + + case ESRCH: + nsh_output(vtbl, g_fmtnosuch, argv[0], "task", argv[2]); + return ERROR; + + case EPERM: + case ENOSYS: + default: + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "kill", NSH_ERRNO); + return ERROR; + } + +invalid_arg: + nsh_output(vtbl, g_fmtarginvalid, argv[0]); + return ERROR; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_sleep + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_SIGNALS +#ifndef CONFIG_NSH_DISABLE_SLEEP +int cmd_sleep(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *endptr; + long secs; + + secs = strtol(argv[1], &endptr, 0); + if (!secs || endptr == argv[1] || *endptr != '\0') + { + nsh_output(vtbl, g_fmtarginvalid, argv[0]); + return ERROR; + } + sleep(secs); + return OK; +} +#endif +#endif + +/**************************************************************************** + * Name: cmd_usleep + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_SIGNALS +#ifndef CONFIG_NSH_DISABLE_USLEEP +int cmd_usleep(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + char *endptr; + long usecs; + + usecs = strtol(argv[1], &endptr, 0); + if (!usecs || endptr == argv[1] || *endptr != '\0') + { + nsh_output(vtbl, g_fmtarginvalid, argv[0]); + return ERROR; + } + usleep(usecs); + return OK; +} +#endif +#endif diff --git a/apps/nshlib/nsh_romfsetc.c b/apps/nshlib/nsh_romfsetc.c new file mode 100644 index 0000000000..4134b45a3d --- /dev/null +++ b/apps/nshlib/nsh_romfsetc.c @@ -0,0 +1,124 @@ +/**************************************************************************** + * apps/nshlib/nsh_romfsetc.c + * + * Copyright (C) 2008-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "nsh.h" + +#ifdef CONFIG_NSH_ROMFSETC + +/* Should we use the default ROMFS image? Or a custom, board-specific + * ROMFS image? + */ + +#ifdef CONFIG_NSH_ARCHROMFS +# include +#else +# include "nsh_romfsimg.h" +#endif + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_romfsetc + ****************************************************************************/ + +int nsh_romfsetc(void) +{ + int ret; + + /* Create a ROM disk for the /etc filesystem */ + + ret = romdisk_register(CONFIG_NSH_ROMFSDEVNO, romfs_img, + NSECTORS(romfs_img_len), CONFIG_NSH_ROMFSSECTSIZE); + if (ret < 0) + { + dbg("nsh: romdisk_register failed: %d\n", -ret); + return ERROR; + } + + /* Mount the file system */ + + vdbg("Mounting ROMFS filesystem at target=%s with source=%s\n", + CONFIG_NSH_ROMFSMOUNTPT, MOUNT_DEVNAME); + + ret = mount(MOUNT_DEVNAME, CONFIG_NSH_ROMFSMOUNTPT, "romfs", MS_RDONLY, NULL); + if (ret < 0) + { + dbg("nsh: mount(%s,%s,romfs) failed: %d\n", + MOUNT_DEVNAME, CONFIG_NSH_ROMFSMOUNTPT, errno); + return ERROR; + } + return OK; +} + +#endif /* CONFIG_NSH_ROMFSETC */ + diff --git a/apps/nshlib/nsh_romfsimg.h b/apps/nshlib/nsh_romfsimg.h new file mode 100644 index 0000000000..49b0ad166f --- /dev/null +++ b/apps/nshlib/nsh_romfsimg.h @@ -0,0 +1,89 @@ +unsigned char romfs_img[] = { + 0x2d, 0x72, 0x6f, 0x6d, 0x31, 0x66, 0x73, 0x2d, 0x00, 0x00, 0x01, 0x50, + 0x9f, 0x13, 0x82, 0x87, 0x4e, 0x53, 0x48, 0x49, 0x6e, 0x69, 0x74, 0x56, + 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xff, 0x97, + 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xff, 0x80, 0x2e, 0x2e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x68, 0x2d, 0x96, 0x03, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xff, 0x00, + 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6e, 0x8d, 0x9c, 0xab, 0x58, 0x72, 0x63, 0x53, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x52, + 0x41, 0x4d, 0x44, 0x49, 0x53, 0x4b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x69, 0x74, 0x20, 0x61, 0x74, 0x20, 0x2f, + 0x74, 0x6d, 0x70, 0x0a, 0x0a, 0x6d, 0x6b, 0x72, 0x64, 0x20, 0x2d, 0x6d, + 0x20, 0x32, 0x20, 0x2d, 0x73, 0x20, 0x35, 0x31, 0x32, 0x20, 0x31, 0x30, + 0x32, 0x34, 0x0a, 0x6d, 0x6b, 0x66, 0x61, 0x74, 0x66, 0x73, 0x20, 0x2f, + 0x64, 0x65, 0x76, 0x2f, 0x72, 0x61, 0x6d, 0x32, 0x0a, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x20, 0x2d, 0x74, 0x20, 0x76, 0x66, 0x61, 0x74, 0x20, 0x2f, + 0x64, 0x65, 0x76, 0x2f, 0x72, 0x61, 0x6d, 0x32, 0x20, 0x2f, 0x74, 0x6d, + 0x70, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xff, 0xe0, 0x2e, 0x2e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int romfs_img_len = 1024; diff --git a/apps/nshlib/nsh_telnetd.c b/apps/nshlib/nsh_telnetd.c new file mode 100644 index 0000000000..0117aad042 --- /dev/null +++ b/apps/nshlib/nsh_telnetd.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * apps/nshlib/nsh_telnetd.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "nsh.h" +#include "nsh_console.h" + +#ifdef CONFIG_NSH_TELNET + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_telnetmain + ****************************************************************************/ + +int nsh_telnetmain(int argc, char *argv[]) +{ + FAR struct console_stdio_s *pstate = nsh_newconsole(); + DEBUGASSERT(pstate != NULL); + + dbg("Session [%d] Started\n", getpid()); + + /* Present a greeting */ + + fputs(g_nshgreeting, pstate->cn_outstream); + fflush(pstate->cn_outstream); + + /* Execute the startup script */ + +#if defined(CONFIG_NSH_ROMFSETC) && !defined(CONFIG_NSH_CONSOLE) + (void)nsh_script(&pstate->cn_vtbl, "init", NSH_INITPATH); +#endif + + /* Then enter the command line parsing loop */ + + for (;;) + { + /* Display the prompt string */ + + fputs(g_nshprompt, pstate->cn_outstream); + fflush(pstate->cn_outstream); + + /* Get the next line of input from the Telnet client */ + + if (fgets(pstate->cn_line, CONFIG_NSH_LINELEN, INSTREAM(pstate)) != NULL) + { + /* Parse process the received Telnet command */ + + (void)nsh_parse(&pstate->cn_vtbl, pstate->cn_line); + fflush(pstate->cn_outstream); + } + else + { + fprintf(pstate->cn_outstream, g_fmtcmdfailed, "nsh_telnetmain", + "fgets", NSH_ERRNO); + nsh_exit(&pstate->cn_vtbl, 1); + } + } + + /* Clean up */ + + nsh_exit(&pstate->cn_vtbl, 0); + + /* We do not get here, but this is necessary to keep some compilers happy */ + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_telnetstart + * + * Description: + * nsh_telnetstart() starts the Telnet daemon that will allow multiple + * NSH connections via Telnet. This function returns immediately after + * the daemon has been started. + * + * Input Parameters: + * None. All of the properties of the Telnet daemon are controlled by + * NuttX configuration setting. + * + * Returned Values: + * Zero if the Telnet daemon was successfully started. A negated errno + * value will be returned on failure. + * + ****************************************************************************/ + +int nsh_telnetstart(void) +{ + struct telnetd_config_s config; + int ret; + + /* Configure the telnet daemon */ + + config.d_port = HTONS(CONFIG_NSH_TELNETD_PORT); + config.d_priority = CONFIG_NSH_TELNETD_DAEMONPRIO; + config.d_stacksize = CONFIG_NSH_TELNETD_DAEMONSTACKSIZE; + config.t_priority = CONFIG_NSH_TELNETD_CLIENTPRIO; + config.t_stacksize = CONFIG_NSH_TELNETD_CLIENTSTACKSIZE; + config.t_entry = nsh_telnetmain; + + /* Start the telnet daemon */ + + vdbg("Starting the Telnet daemon\n"); + ret = telnetd_start(&config); + if (ret < 0) + { + dbg("Failed to tart the Telnet daemon: %d\n", ret); + } + + return ret; +} + +#endif /* CONFIG_NSH_TELNET */ diff --git a/apps/nshlib/nsh_test.c b/apps/nshlib/nsh_test.c new file mode 100644 index 0000000000..6e1b65e5f4 --- /dev/null +++ b/apps/nshlib/nsh_test.c @@ -0,0 +1,438 @@ +/**************************************************************************** + * apps/nshlib/nsh_test.c + * + * Copyright (C) 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* Test syntax: + * + * expression = simple-expression | !expression | + * expression -o expression | expression -a expression + * + * simple-expression = unary-expression | binary-expression + * + * unary-expression = string-unary | file-unary + * + * string-unary = -n string | -z string + * + * file-unary = -b file | -c file | -d file | -e file | -f file | + * -r file | -s file | -w file + * + * binary-expression = string-binary | numeric-binary + * + * string-binary = string = string | string == string | string != string + * + * numeric-binary = integer -eq integer | integer -ge integer | + * integer -gt integer | integer -le integer | + * integer -lt integer | integer -ne integer + * + * Note that the smallest expression consists of two strings. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "nsh.h" +#include "nsh_console.h" + +#if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_TEST) + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define TEST_TRUE OK +#define TEST_FALSE ERROR +#define TEST_ERROR 1 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: binaryexpression + ****************************************************************************/ + +static inline int binaryexpression(FAR struct nsh_vtbl_s *vtbl, char **argv) +{ + char *endptr; + long integer1; + long integer2; + + /* STRING2 = STRING2 */ + + if (strcmp(argv[1], "=") == 0 || strcmp(argv[1], "==") == 0) + { + /* Return true if the strings are identical */ + + return strcmp(argv[0], argv[2]) == 0 ? TEST_TRUE : TEST_FALSE; + } + + /* STRING1 != STRING2 */ + + if (strcmp(argv[1], "!=") == 0) + { + /* Return true if the strings are different */ + + return strcmp(argv[0], argv[2]) != 0 ? TEST_TRUE : TEST_FALSE; + } + + /* The remaining operators assuming that the two values are integers */ + + integer1 = strtol(argv[0], &endptr, 0); + if (argv[0][0] == '\0' || *endptr != '\0') + { + return TEST_ERROR; + } + + integer2 = strtol(argv[2], &endptr, 0); + if (argv[2][0] == '\0' || *endptr != '\0') + { + return TEST_ERROR; + } + + /* INTEGER1 -eq INTEGER2 */ + + if (strcmp(argv[1], "-eq") == 0) + { + /* Return true if the strings are different */ + + return integer1 == integer2 ? TEST_TRUE : TEST_FALSE; + } + + /* INTEGER1 -ge INTEGER2 */ + + if (strcmp(argv[1], "-ge") == 0) + { + /* Return true if the strings are different */ + + return integer1 >= integer2 ? TEST_TRUE : TEST_FALSE; + } + + /* INTEGER1 -gt INTEGER2 */ + + if (strcmp(argv[1], "-gt") == 0) + { + /* Return true if the strings are different */ + + return integer1 > integer2 ? TEST_TRUE : TEST_FALSE; + } + + /* INTEGER1 -le INTEGER2 */ + + if (strcmp(argv[1], "-le") == 0) + { + /* Return true if the strings are different */ + + return integer1 <= integer2 ? TEST_TRUE : TEST_FALSE; + } + + /* INTEGER1 -lt INTEGER2 */ + + if (strcmp(argv[1], "-lt") == 0) + { + /* Return true if the strings are different */ + + return integer1 < integer2 ? TEST_TRUE : TEST_FALSE; + } + + /* INTEGER1 -ne INTEGER2 */ + + if (strcmp(argv[1], "-ne") == 0) + { + /* Return true if the strings are different */ + + return integer1 != integer2 ? TEST_TRUE : TEST_FALSE; + } + + return TEST_ERROR; +} + +/**************************************************************************** + * Name: unaryexpression + ****************************************************************************/ + +static inline int unaryexpression(FAR struct nsh_vtbl_s *vtbl, char **argv) +{ + struct stat buf; + char *fullpath; + int ret; + + /* -n STRING */ + + if (strcmp(argv[0], "-n") == 0) + { + /* Return true if the length of the string is non-zero */ + + return strlen(argv[1]) != 0 ? TEST_TRUE : TEST_FALSE; + } + + /* -z STRING */ + + if (strcmp(argv[0], "-z") == 0) + { + /* Return true if the length of the string is zero */ + + return strlen(argv[1]) == 0 ? TEST_TRUE : TEST_FALSE; + } + + /* All of the remaining assume that the following argument is the + * path to a file. + */ + + fullpath = nsh_getfullpath(vtbl, argv[1]); + if (!fullpath) + { + return TEST_FALSE; + } + + ret = stat(fullpath, &buf); + nsh_freefullpath(fullpath); + + if (ret != 0) + { + /* The file does not exist (or another error occurred) -- return FALSE */ + + return TEST_FALSE; + } + + /* -b FILE */ + + if (strcmp(argv[0], "-b") == 0) + { + /* Return true if the path is a block device */ + + return S_ISBLK(buf.st_mode) ? TEST_TRUE : TEST_FALSE; + } + + /* -c FILE */ + + if (strcmp(argv[0], "-c") == 0) + { + /* Return true if the path is a character device */ + + return S_ISCHR(buf.st_mode) ? TEST_TRUE : TEST_FALSE; + } + + /* -d FILE */ + + if (strcmp(argv[0], "-d") == 0) + { + /* Return true if the path is a directory */ + + return S_ISDIR(buf.st_mode) ? TEST_TRUE : TEST_FALSE; + } + + /* -e FILE */ + + if (strcmp(argv[0], "-e") == 0) + { + /* Return true if the file exists */ + + return TEST_TRUE; + } + + /* -f FILE */ + + if (strcmp(argv[0], "-f") == 0) + { + /* Return true if the path refers to a regular file */ + + return S_ISREG(buf.st_mode) ? TEST_TRUE : TEST_FALSE; + } + + /* -r FILE */ + + if (strcmp(argv[0], "-r") == 0) + { + /* Return true if the file is readable */ + + return (buf.st_mode & (S_IRUSR|S_IRGRP|S_IROTH)) != 0 ? TEST_TRUE : TEST_FALSE; + } + + /* -s FILE */ + + if (strcmp(argv[0], "-s") == 0) + { + /* Return true if the size of the file is greater than zero */ + + return buf.st_size > 0 ? TEST_TRUE : TEST_FALSE; + } + + /* -w FILE */ + + if (strcmp(argv[0], "-w") == 0) + { + /* Return true if the file is write-able */ + + return (buf.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) != 0 ? TEST_TRUE : TEST_FALSE; + } + + /* Unrecognized operator */ + + return TEST_ERROR; +} + +/**************************************************************************** + * Name: expression + ****************************************************************************/ + +static int expression(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + int value; + int i = 0; + + /* Check for unary operations on expressions */ + + if (strcmp(argv[0], "!") == 0) + { + if (argc < 2) + { + goto errout_syntax; + } + return expression(vtbl, argc-1, &argv[1]) == TEST_TRUE ? TEST_FALSE : TEST_TRUE; + } + + /* Check for unary operations on simple, typed arguments */ + + else if (argv[0][0] == '-') + { + if (argc < 2) + { + goto errout_syntax; + } + i += 2; + value = unaryexpression(vtbl, argv); + } + + /* Check for binary operations on simple, typed arguments */ + + else + { + if (argc < 3) + { + goto errout_syntax; + } + i += 3; + value = binaryexpression(vtbl, argv); + } + + /* Test if there any failure */ + + if (value == TEST_ERROR) + { + goto errout_syntax; + } + + /* Is there anything after the simple expression? */ + + if (i < argc) + { + /* EXPRESSION -a EXPRESSION */ + + if (strcmp(argv[i], "-a") == 0) + { + if (value != TEST_TRUE) + { + return TEST_FALSE; + } + else + { + i++; + return expression(vtbl, argc-i, &argv[i]); + } + } + + /* EXPRESSION -o EXPRESSION */ + + else if (strcmp(argv[i], "-o") == 0) + { + if (value == TEST_TRUE) + { + return TEST_TRUE; + } + else + { + i++; + return expression(vtbl, argc-i, &argv[i]); + } + } + else + { + goto errout_syntax; + } + } + return value; + +errout_syntax: + nsh_output(vtbl, g_nshsyntax, "test"); + return TEST_FALSE; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cmd_test + ****************************************************************************/ + +int cmd_test(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + return expression(vtbl, argc-1, &argv[1]); +} + +/**************************************************************************** + * Name: cmd_lbracket + ****************************************************************************/ + +int cmd_lbracket(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + if (strcmp(argv[argc-1], "]") != 0) + { + nsh_output(vtbl, g_nshsyntax, argv[0]); + return ERROR; + } + else + { + return expression(vtbl, argc-2, &argv[1]); + } +} + +#endif /* !CONFIG_NSH_DISABLESCRIPT && !CONFIG_NSH_DISABLE_TEST */ diff --git a/apps/nshlib/nsh_timcmds.c b/apps/nshlib/nsh_timcmds.c new file mode 100644 index 0000000000..bc2bda6f4b --- /dev/null +++ b/apps/nshlib/nsh_timcmds.c @@ -0,0 +1,331 @@ +/**************************************************************************** + * apps/nshlib/dbg_timcmds.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "nsh.h" +#include "nsh_console.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define MAX_TIME_STRING 80 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if defined (CONFIG_RTC) && !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_NSH_DISABLE_DATE) +static FAR const char * const g_datemontab[] = +{ + "jan", "feb", "mar", "apr", "may", "jun", + "jul", "aug", "sep", "oct", "nov", "dec" +}; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: date_month + ****************************************************************************/ + +#if defined (CONFIG_RTC) && !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_NSH_DISABLE_DATE) +static inline int date_month(FAR const char *abbrev) +{ + int i; + + for (i = 0; i < 12; i++) + { + if (strncasecmp(g_datemontab[i], abbrev, 3) == 0) + { + return i; + } + } + return ERROR; +} +#endif + +/**************************************************************************** + * Name: date_gettime + ****************************************************************************/ + +#if defined (CONFIG_RTC) && !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_NSH_DISABLE_DATE) +static inline int date_showtime(FAR struct nsh_vtbl_s *vtbl, FAR const char *name) +{ + static const char format[] = "%b %d %H:%M:%S %Y"; + struct timespec ts; + struct tm tm; + char timbuf[MAX_TIME_STRING]; + int ret; + + /* Get the current time */ + + ret = clock_gettime(CLOCK_REALTIME, &ts); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, name, "clock_gettime", NSH_ERRNO); + return ERROR; + } + + /* Break the current time up into the format needed by strftime */ + + (void)gmtime_r((FAR const time_t*)&ts.tv_sec, &tm); + + /* Show the current time in the requested format */ + + (void)strftime(timbuf, MAX_TIME_STRING, format, &tm); + nsh_output(vtbl, "%s\n", timbuf); + return OK; +} +#endif + +/**************************************************************************** + * Name: date_settime + ****************************************************************************/ + +#if defined (CONFIG_RTC) && !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_NSH_DISABLE_DATE) +static inline int date_settime(FAR struct nsh_vtbl_s *vtbl, FAR const char *name, + FAR char *newtime) +{ + struct timespec ts; + struct tm tm; + FAR char *token; + FAR char *saveptr; + long result; + int ret; + + /* Only this date format is supported: MMM DD HH:MM:SS YYYY */ + /* Get the month abbreviation */ + + token = strtok_r(newtime, " \t",&saveptr); + if (token == NULL) + { + goto errout_bad_parm; + } + + tm.tm_mon = date_month(token); + if (tm.tm_mon < 0) + { + goto errout_bad_parm; + } + + /* Get the day of the month. NOTE: Accepts day-of-month up to 31 for all months */ + + token = strtok_r(NULL, " \t",&saveptr); + if (token == NULL) + { + goto errout_bad_parm; + } + + result = strtol(token, NULL, 10); + if (result < 1 || result > 31) + { + goto errout_bad_parm; + } + tm.tm_mday = (int)result; + + /* Get the hours */ + + token = strtok_r(NULL, " \t:", &saveptr); + if (token == NULL) + { + goto errout_bad_parm; + } + + result = strtol(token, NULL, 10); + if (result < 0 || result > 23) + { + goto errout_bad_parm; + } + tm.tm_hour = (int)result; + + /* Get the minutes */ + + token = strtok_r(NULL, " \t:", &saveptr); + if (token == NULL) + { + goto errout_bad_parm; + } + + result = strtol(token, NULL, 10); + if (result < 0 || result > 59) + { + goto errout_bad_parm; + } + tm.tm_min = (int)result; + + /* Get the seconds */ + + token = strtok_r(NULL, " \t:", &saveptr); + if (token == NULL) + { + goto errout_bad_parm; + } + + result = strtol(token, NULL, 10); + if (result < 0 || result > 61) + { + goto errout_bad_parm; + } + tm.tm_sec = (int)result; + + /* And finally the year */ + + token = strtok_r(NULL, " \t", &saveptr); + if (token == NULL) + { + goto errout_bad_parm; + } + + result = strtol(token, NULL, 10); + if (result < 1900 || result > 2100) + { + goto errout_bad_parm; + } + tm.tm_year = (int)result - 1900; + + /* Convert this to the right form, then set the timer */ + + ts.tv_sec = mktime(&tm); + ts.tv_nsec = 0; + + ret = clock_settime(CLOCK_REALTIME, &ts); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, name, "clock_settime", NSH_ERRNO); + return ERROR; + } + return OK; + +errout_bad_parm: + nsh_output(vtbl, g_fmtarginvalid, name); + return ERROR; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cmd_date + ****************************************************************************/ + +#if defined (CONFIG_RTC) && !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_NSH_DISABLE_DATE) +int cmd_date(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + FAR char *newtime = NULL; + FAR const char *errfmt; + bool badarg = false; + int option; + int ret; + + /* Get the date options: date [-s time] [+FORMAT] */ + + while ((option = getopt(argc, argv, "s:")) != ERROR) + { + if (option == 's') + { + /* We will be setting the time */ + + newtime = optarg; + } + else /* option = '?' */ + { + /* We need to parse to the end anyway so that getopt stays healthy */ + + badarg = true; + } + } + + /* If a bad argument was encountered then exit with an error */ + + if (badarg) + { + errfmt = g_fmtarginvalid; + goto errout; + } + + /* optind < argc-1 means that there are additional, unexpected arguments on + * th command-line + */ + + if (optind < argc) + { + errfmt = g_fmttoomanyargs; + goto errout; + } + + /* Display or set the time */ + + if (newtime) + { + ret = date_settime(vtbl, argv[0], newtime); + } + else + { + ret = date_showtime(vtbl, argv[0]); + } + return ret; + +errout: + nsh_output(vtbl, errfmt, argv[0]); + return ERROR; +} +#endif diff --git a/apps/nshlib/nsh_usbdev.c b/apps/nshlib/nsh_usbdev.c new file mode 100644 index 0000000000..3d123532aa --- /dev/null +++ b/apps/nshlib/nsh_usbdev.c @@ -0,0 +1,243 @@ +/**************************************************************************** + * apps/nshlib/nsh_usbdev.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_CDCACM +# include +#endif + +#ifdef CONFIG_CDCACM +# include +#endif + +#include "nsh.h" + +#ifdef CONFIG_USBDEV + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) || defined(CONFIG_NSH_USBCONSOLE) +# define trmessage lib_lowprintf +#else +# define trmessage printf +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_tracecallback + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_TRACE +static int nsh_tracecallback(struct usbtrace_s *trace, void *arg) +{ + usbtrace_trprintf((trprintf_t)trmessage, trace->event, trace->value); + return 0; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_usbconsole + ****************************************************************************/ + +#ifdef HAVE_USB_CONSOLE +int nsh_usbconsole(void) +{ + char inch; + ssize_t nbytes; + int nlc; + int fd; + int ret; + + /* Initialize any USB tracing options that were requested */ + +#ifdef CONFIG_USBDEV_TRACE + usbtrace_enable(TRACE_BITSET); +#endif + + /* Don't start the NSH console until the console device is ready. Chances + * are, we get here with no functional console. The USB console will not + * be available until the device is connected to the host and until the + * host-side application opens the connection. + */ + + /* Initialize the USB serial driver */ + +#if defined(CONFIG_PL2303) || defined(CONFIG_CDCACM) +#ifdef CONFIG_CDCACM + ret = cdcacm_initialize(CONFIG_NSH_UBSDEV_MINOR, NULL); +#else + ret = usbdev_serialinitialize(CONFIG_NSH_UBSDEV_MINOR); +#endif + DEBUGASSERT(ret == OK); +#endif + + /* Open the USB serial device for read/write access */ + + do + { + /* Try to open the console */ + + fd = open(CONFIG_NSH_USBCONDEV, O_RDWR); + if (fd < 0) + { + /* ENOTCONN means that the USB device is not yet connected. Anything + * else is bad. + */ + + DEBUGASSERT(errno == ENOTCONN); + + /* Sleep a bit and try again */ + + sleep(2); + } + } + while (fd < 0); + + /* Now waiting until we successfully read a carriage return a few times. + * That is a sure way of know that there is something at the other end of + * the USB serial connection that is ready to talk with us. The user needs + * to hit ENTER a few times to get things started. + */ + + nlc = 0; + do + { + /* Read one byte */ + + inch = 0; + nbytes = read(fd, &inch, 1); + + /* Is it a carriage return (or maybe a newline)? */ + + if (nbytes == 1 && (inch == '\n' || inch == '\r')) + { + /* Yes.. increment the count */ + + nlc++; + } + else + { + /* No.. Reset the count. We need to see 3 in a row to continue. */ + + nlc = 0; + } + } + while (nlc < 3); + + /* Make sure the stdin, stdout, and stderr are closed */ + + (void)fclose(stdin); + (void)fclose(stdout); + (void)fclose(stderr); + + /* Dup the fd to create standard fd 0-2 */ + + (void)dup2(fd, 0); + (void)dup2(fd, 1); + (void)dup2(fd, 2); + + /* We can close the original file descriptor now (unless it was one of 0-2) */ + + if (fd > 2) + { + close(fd); + } + + /* fdopen to get the stdin, stdout and stderr streams. The following logic depends + * on the fact that the library layer will allocate FILEs in order. And since + * we closed stdin, stdout, and stderr above, that is what we should get. + * + * fd = 0 is stdin (read-only) + * fd = 1 is stdout (write-only, append) + * fd = 2 is stderr (write-only, append) + */ + + (void)fdopen(0, "r"); + (void)fdopen(1, "a"); + (void)fdopen(2, "a"); + return OK; +} + +#endif /* HAVE_USB_CONSOLE */ + +/**************************************************************************** + * Name: nsh_usbtrace + ****************************************************************************/ + +#if defined(CONFIG_USBDEV_TRACE) && defined(HAVE_USB_CONSOLE) +void nsh_usbtrace(void) +{ + (void)usbtrace_enumerate(nsh_tracecallback, NULL); +} +#endif + +#endif /* CONFIG_USBDEV */ diff --git a/apps/nshlib/rcS.template b/apps/nshlib/rcS.template new file mode 100644 index 0000000000..996f37fb13 --- /dev/null +++ b/apps/nshlib/rcS.template @@ -0,0 +1,5 @@ +# Create a RAMDISK and mount it at XXXRDMOUNTPOUNTXXX + +mkrd -m XXXMKRDMINORXXX -s XXMKRDSECTORSIZEXXX XXMKRDBLOCKSXXX +mkfatfs /dev/ramXXXMKRDMINORXXX +mount -t vfat /dev/ramXXXMKRDMINORXXX XXXRDMOUNTPOUNTXXX diff --git a/apps/position_estimator/.context b/apps/position_estimator/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/position_estimator/Makefile b/apps/position_estimator/Makefile new file mode 100644 index 0000000000..a766f1666b --- /dev/null +++ b/apps/position_estimator/Makefile @@ -0,0 +1,52 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Makefile to build the position estimator +# + +APPNAME = position_estimator +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 4096 + +CSRCS = position_estimator_main.c \ + codegen/position_estimator.c \ + codegen/position_estimator_initialize.c \ + codegen/position_estimator_terminate.c \ + codegen/rt_nonfinite.c \ + codegen/rtGetInf.c \ + codegen/rtGetNaN.c + +INCLUDES = $(TOPDIR)/../mavlink/include/mavlink + +include $(APPDIR)/mk/app.mk diff --git a/apps/position_estimator/codegen/position_estimator.c b/apps/position_estimator/codegen/position_estimator.c new file mode 100644 index 0000000000..731ae03e34 --- /dev/null +++ b/apps/position_estimator/codegen/position_estimator.c @@ -0,0 +1,261 @@ +/* + * position_estimator.c + * + * Code generation for function 'position_estimator' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +/* Include files */ +#include "rt_nonfinite.h" +#include "position_estimator.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ + +/* Function Definitions */ +void position_estimator(const real32_T u[2], const real32_T z[3], const real32_T + xapo[6], const real32_T Papo[36], const real32_T gps_covariance[3], uint8_T + predict_only, real32_T xapo1[6], real32_T Papo1[36]) +{ + real32_T fv0[6]; + real32_T fv1[6]; + real32_T I[36]; + real32_T xapri[6]; + int32_T i; + int32_T r1; + static const real32_T fv2[36] = { 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.004F, + 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, + 0.004F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, + 0.0F, 0.0F, 0.004F, 1.0F }; + + static const real32_T fv3[12] = { 0.0F, 0.0F, 0.1744F, 87.2F, 0.0F, 0.0F, + -0.1744F, -87.2F, 0.0F, 0.0F, 0.0F, 0.0F }; + + int32_T r2; + real32_T Papri[36]; + real32_T maxval; + static const real32_T fv4[36] = { 1.0F, 0.004F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, + 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.004F, 0.0F, 0.0F, 0.0F, + 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.004F, 0.0F, + 0.0F, 0.0F, 0.0F, 0.0F, 1.0F }; + + static const real32_T fv5[36] = { 1.0E-7F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, + 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0E-7F, 0.0F, 0.0F, 0.0F, 0.0F, + 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0E-7F, 0.0F, 0.0F, + 0.0F, 0.0F, 0.0F, 0.0F, 1.0F }; + + real32_T K[18]; + static const int8_T iv0[18] = { 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0 }; + + real32_T fv6[9]; + static const int8_T iv1[18] = { 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0 }; + + real32_T b_gps_covariance[9]; + real32_T A[9]; + real32_T B[18]; + int32_T r3; + real32_T a21; + real32_T Y[18]; + real32_T b_z[3]; + int8_T b_I[36]; + + /* if predit_onli == 1: no update step: use this when no new gps data is available */ + /* %initialization */ + /* use model F=m*a x''=F/m */ + /* 250Hz---> dT = 0.004s */ + /* u=[phi;theta] */ + /* x=[px;vx;py;vy]; */ + /* %------------------------------------------ */ + /* %------------------------------------------------ */ + /* R_t=[1,-r*dT,q*dT;r*dT,1,-p*dT;-q*dT,p*dT,1]; */ + /* process Covariance Matrix */ + /* measurement Covariance Matrix */ + /* %prediction */ + for (i = 0; i < 6; i++) { + fv0[i] = 0.0F; + for (r1 = 0; r1 < 6; r1++) { + fv0[i] += fv2[i + 6 * r1] * xapo[r1]; + } + + fv1[i] = 0.0F; + for (r1 = 0; r1 < 2; r1++) { + fv1[i] += fv3[i + 6 * r1] * u[r1]; + } + + xapri[i] = fv0[i] + fv1[i]; + for (r1 = 0; r1 < 6; r1++) { + I[i + 6 * r1] = 0.0F; + for (r2 = 0; r2 < 6; r2++) { + I[i + 6 * r1] += fv2[i + 6 * r2] * Papo[r2 + 6 * r1]; + } + } + } + + for (i = 0; i < 6; i++) { + for (r1 = 0; r1 < 6; r1++) { + maxval = 0.0F; + for (r2 = 0; r2 < 6; r2++) { + maxval += I[i + 6 * r2] * fv4[r2 + 6 * r1]; + } + + Papri[i + 6 * r1] = maxval + fv5[i + 6 * r1]; + } + } + + if (1 != predict_only) { + /* update */ + for (i = 0; i < 3; i++) { + for (r1 = 0; r1 < 6; r1++) { + K[i + 3 * r1] = 0.0F; + for (r2 = 0; r2 < 6; r2++) { + K[i + 3 * r1] += (real32_T)iv0[i + 3 * r2] * Papri[r2 + 6 * r1]; + } + } + } + + for (i = 0; i < 3; i++) { + for (r1 = 0; r1 < 3; r1++) { + fv6[i + 3 * r1] = 0.0F; + for (r2 = 0; r2 < 6; r2++) { + fv6[i + 3 * r1] += K[r1 + 3 * r2] * (real32_T)iv1[r2 + 6 * i]; + } + } + } + + b_gps_covariance[0] = gps_covariance[0]; + b_gps_covariance[1] = 0.0F; + b_gps_covariance[2] = 0.0F; + b_gps_covariance[3] = 0.0F; + b_gps_covariance[4] = gps_covariance[1]; + b_gps_covariance[5] = 0.0F; + b_gps_covariance[6] = 0.0F; + b_gps_covariance[7] = 0.0F; + b_gps_covariance[8] = gps_covariance[2]; + for (i = 0; i < 3; i++) { + for (r1 = 0; r1 < 3; r1++) { + A[r1 + 3 * i] = fv6[r1 + 3 * i] + b_gps_covariance[r1 + 3 * i]; + } + + for (r1 = 0; r1 < 6; r1++) { + B[i + 3 * r1] = 0.0F; + for (r2 = 0; r2 < 6; r2++) { + B[i + 3 * r1] += Papri[r1 + 6 * r2] * (real32_T)iv1[r2 + 6 * i]; + } + } + } + + r1 = 0; + r2 = 1; + r3 = 2; + maxval = (real32_T)fabs(A[0]); + a21 = (real32_T)fabs(A[1]); + if (a21 > maxval) { + maxval = a21; + r1 = 1; + r2 = 0; + } + + if ((real32_T)fabs(A[2]) > maxval) { + r1 = 2; + r2 = 1; + r3 = 0; + } + + A[r2] /= A[r1]; + A[r3] /= A[r1]; + A[3 + r2] -= A[r2] * A[3 + r1]; + A[3 + r3] -= A[r3] * A[3 + r1]; + A[6 + r2] -= A[r2] * A[6 + r1]; + A[6 + r3] -= A[r3] * A[6 + r1]; + if ((real32_T)fabs(A[3 + r3]) > (real32_T)fabs(A[3 + r2])) { + i = r2; + r2 = r3; + r3 = i; + } + + A[3 + r3] /= A[3 + r2]; + A[6 + r3] -= A[3 + r3] * A[6 + r2]; + for (i = 0; i < 6; i++) { + Y[3 * i] = B[r1 + 3 * i]; + Y[1 + 3 * i] = B[r2 + 3 * i] - Y[3 * i] * A[r2]; + Y[2 + 3 * i] = (B[r3 + 3 * i] - Y[3 * i] * A[r3]) - Y[1 + 3 * i] * A[3 + + r3]; + Y[2 + 3 * i] /= A[6 + r3]; + Y[3 * i] -= Y[2 + 3 * i] * A[6 + r1]; + Y[1 + 3 * i] -= Y[2 + 3 * i] * A[6 + r2]; + Y[1 + 3 * i] /= A[3 + r2]; + Y[3 * i] -= Y[1 + 3 * i] * A[3 + r1]; + Y[3 * i] /= A[r1]; + } + + for (i = 0; i < 3; i++) { + for (r1 = 0; r1 < 6; r1++) { + K[r1 + 6 * i] = Y[i + 3 * r1]; + } + } + + for (i = 0; i < 3; i++) { + maxval = 0.0F; + for (r1 = 0; r1 < 6; r1++) { + maxval += (real32_T)iv0[i + 3 * r1] * xapri[r1]; + } + + b_z[i] = z[i] - maxval; + } + + for (i = 0; i < 6; i++) { + maxval = 0.0F; + for (r1 = 0; r1 < 3; r1++) { + maxval += K[i + 6 * r1] * b_z[r1]; + } + + xapo1[i] = xapri[i] + maxval; + } + + for (i = 0; i < 36; i++) { + b_I[i] = 0; + } + + for (i = 0; i < 6; i++) { + b_I[i + 6 * i] = 1; + } + + for (i = 0; i < 6; i++) { + for (r1 = 0; r1 < 6; r1++) { + maxval = 0.0F; + for (r2 = 0; r2 < 3; r2++) { + maxval += K[i + 6 * r2] * (real32_T)iv0[r2 + 3 * r1]; + } + + I[i + 6 * r1] = (real32_T)b_I[i + 6 * r1] - maxval; + } + } + + for (i = 0; i < 6; i++) { + for (r1 = 0; r1 < 6; r1++) { + Papo1[i + 6 * r1] = 0.0F; + for (r2 = 0; r2 < 6; r2++) { + Papo1[i + 6 * r1] += I[i + 6 * r2] * Papri[r2 + 6 * r1]; + } + } + } + } else { + memcpy((void *)&Papo1[0], (void *)&Papri[0], 36U * sizeof(real32_T)); + for (i = 0; i < 6; i++) { + xapo1[i] = xapri[i]; + } + } +} + +/* End of code generation (position_estimator.c) */ diff --git a/apps/position_estimator/codegen/position_estimator.h b/apps/position_estimator/codegen/position_estimator.h new file mode 100644 index 0000000000..5e2c9acd89 --- /dev/null +++ b/apps/position_estimator/codegen/position_estimator.h @@ -0,0 +1,32 @@ +/* + * position_estimator.h + * + * Code generation for function 'position_estimator' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +#ifndef __POSITION_ESTIMATOR_H__ +#define __POSITION_ESTIMATOR_H__ +/* Include files */ +#include +#include +#include +#include + +#include "rtwtypes.h" +#include "position_estimator_types.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ +extern void position_estimator(const real32_T u[2], const real32_T z[3], const real32_T xapo[6], const real32_T Papo[36], const real32_T gps_covariance[3], uint8_T predict_only, real32_T xapo1[6], real32_T Papo1[36]); +#endif +/* End of code generation (position_estimator.h) */ diff --git a/apps/position_estimator/codegen/position_estimator_initialize.c b/apps/position_estimator/codegen/position_estimator_initialize.c new file mode 100644 index 0000000000..862381d3b3 --- /dev/null +++ b/apps/position_estimator/codegen/position_estimator_initialize.c @@ -0,0 +1,31 @@ +/* + * position_estimator_initialize.c + * + * Code generation for function 'position_estimator_initialize' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +/* Include files */ +#include "rt_nonfinite.h" +#include "position_estimator.h" +#include "position_estimator_initialize.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ + +/* Function Definitions */ +void position_estimator_initialize(void) +{ + rt_InitInfAndNaN(8U); +} + +/* End of code generation (position_estimator_initialize.c) */ diff --git a/apps/position_estimator/codegen/position_estimator_initialize.h b/apps/position_estimator/codegen/position_estimator_initialize.h new file mode 100644 index 0000000000..71013b390f --- /dev/null +++ b/apps/position_estimator/codegen/position_estimator_initialize.h @@ -0,0 +1,32 @@ +/* + * position_estimator_initialize.h + * + * Code generation for function 'position_estimator_initialize' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +#ifndef __POSITION_ESTIMATOR_INITIALIZE_H__ +#define __POSITION_ESTIMATOR_INITIALIZE_H__ +/* Include files */ +#include +#include +#include +#include + +#include "rtwtypes.h" +#include "position_estimator_types.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ +extern void position_estimator_initialize(void); +#endif +/* End of code generation (position_estimator_initialize.h) */ diff --git a/apps/position_estimator/codegen/position_estimator_terminate.c b/apps/position_estimator/codegen/position_estimator_terminate.c new file mode 100644 index 0000000000..b25aabf408 --- /dev/null +++ b/apps/position_estimator/codegen/position_estimator_terminate.c @@ -0,0 +1,31 @@ +/* + * position_estimator_terminate.c + * + * Code generation for function 'position_estimator_terminate' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +/* Include files */ +#include "rt_nonfinite.h" +#include "position_estimator.h" +#include "position_estimator_terminate.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ + +/* Function Definitions */ +void position_estimator_terminate(void) +{ + /* (no terminate code required) */ +} + +/* End of code generation (position_estimator_terminate.c) */ diff --git a/apps/position_estimator/codegen/position_estimator_terminate.h b/apps/position_estimator/codegen/position_estimator_terminate.h new file mode 100644 index 0000000000..d9fcf838b0 --- /dev/null +++ b/apps/position_estimator/codegen/position_estimator_terminate.h @@ -0,0 +1,32 @@ +/* + * position_estimator_terminate.h + * + * Code generation for function 'position_estimator_terminate' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +#ifndef __POSITION_ESTIMATOR_TERMINATE_H__ +#define __POSITION_ESTIMATOR_TERMINATE_H__ +/* Include files */ +#include +#include +#include +#include + +#include "rtwtypes.h" +#include "position_estimator_types.h" + +/* Type Definitions */ + +/* Named Constants */ + +/* Variable Declarations */ + +/* Variable Definitions */ + +/* Function Declarations */ +extern void position_estimator_terminate(void); +#endif +/* End of code generation (position_estimator_terminate.h) */ diff --git a/apps/position_estimator/codegen/position_estimator_types.h b/apps/position_estimator/codegen/position_estimator_types.h new file mode 100644 index 0000000000..cb01c74263 --- /dev/null +++ b/apps/position_estimator/codegen/position_estimator_types.h @@ -0,0 +1,16 @@ +/* + * position_estimator_types.h + * + * Code generation for function 'position_estimator' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +#ifndef __POSITION_ESTIMATOR_TYPES_H__ +#define __POSITION_ESTIMATOR_TYPES_H__ + +/* Type Definitions */ + +#endif +/* End of code generation (position_estimator_types.h) */ diff --git a/apps/position_estimator/codegen/rtGetInf.c b/apps/position_estimator/codegen/rtGetInf.c new file mode 100644 index 0000000000..20a64117c9 --- /dev/null +++ b/apps/position_estimator/codegen/rtGetInf.c @@ -0,0 +1,139 @@ +/* + * rtGetInf.c + * + * Code generation for function 'position_estimator' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +/* + * Abstract: + * MATLAB for code generation function to initialize non-finite, Inf and MinusInf + */ +#include "rtGetInf.h" +#define NumBitsPerChar 8U + +/* Function: rtGetInf ================================================== + * Abstract: + * Initialize rtInf needed by the generated code. + * Inf is initialized as non-signaling. Assumes IEEE. + */ +real_T rtGetInf(void) +{ + size_t bitsPerReal = sizeof(real_T) * (NumBitsPerChar); + real_T inf = 0.0; + if (bitsPerReal == 32U) { + inf = rtGetInfF(); + } else { + uint16_T one = 1U; + enum { + LittleEndian, + BigEndian + } machByteOrder = (*((uint8_T *) &one) == 1U) ? LittleEndian : BigEndian; + switch (machByteOrder) { + case LittleEndian: + { + union { + LittleEndianIEEEDouble bitVal; + real_T fltVal; + } tmpVal; + + tmpVal.bitVal.words.wordH = 0x7FF00000U; + tmpVal.bitVal.words.wordL = 0x00000000U; + inf = tmpVal.fltVal; + break; + } + + case BigEndian: + { + union { + BigEndianIEEEDouble bitVal; + real_T fltVal; + } tmpVal; + + tmpVal.bitVal.words.wordH = 0x7FF00000U; + tmpVal.bitVal.words.wordL = 0x00000000U; + inf = tmpVal.fltVal; + break; + } + } + } + + return inf; +} + +/* Function: rtGetInfF ================================================== + * Abstract: + * Initialize rtInfF needed by the generated code. + * Inf is initialized as non-signaling. Assumes IEEE. + */ +real32_T rtGetInfF(void) +{ + IEEESingle infF; + infF.wordL.wordLuint = 0x7F800000U; + return infF.wordL.wordLreal; +} + +/* Function: rtGetMinusInf ================================================== + * Abstract: + * Initialize rtMinusInf needed by the generated code. + * Inf is initialized as non-signaling. Assumes IEEE. + */ +real_T rtGetMinusInf(void) +{ + size_t bitsPerReal = sizeof(real_T) * (NumBitsPerChar); + real_T minf = 0.0; + if (bitsPerReal == 32U) { + minf = rtGetMinusInfF(); + } else { + uint16_T one = 1U; + enum { + LittleEndian, + BigEndian + } machByteOrder = (*((uint8_T *) &one) == 1U) ? LittleEndian : BigEndian; + switch (machByteOrder) { + case LittleEndian: + { + union { + LittleEndianIEEEDouble bitVal; + real_T fltVal; + } tmpVal; + + tmpVal.bitVal.words.wordH = 0xFFF00000U; + tmpVal.bitVal.words.wordL = 0x00000000U; + minf = tmpVal.fltVal; + break; + } + + case BigEndian: + { + union { + BigEndianIEEEDouble bitVal; + real_T fltVal; + } tmpVal; + + tmpVal.bitVal.words.wordH = 0xFFF00000U; + tmpVal.bitVal.words.wordL = 0x00000000U; + minf = tmpVal.fltVal; + break; + } + } + } + + return minf; +} + +/* Function: rtGetMinusInfF ================================================== + * Abstract: + * Initialize rtMinusInfF needed by the generated code. + * Inf is initialized as non-signaling. Assumes IEEE. + */ +real32_T rtGetMinusInfF(void) +{ + IEEESingle minfF; + minfF.wordL.wordLuint = 0xFF800000U; + return minfF.wordL.wordLreal; +} + +/* End of code generation (rtGetInf.c) */ diff --git a/apps/position_estimator/codegen/rtGetInf.h b/apps/position_estimator/codegen/rtGetInf.h new file mode 100644 index 0000000000..c74f1fc284 --- /dev/null +++ b/apps/position_estimator/codegen/rtGetInf.h @@ -0,0 +1,23 @@ +/* + * rtGetInf.h + * + * Code generation for function 'position_estimator' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +#ifndef __RTGETINF_H__ +#define __RTGETINF_H__ + +#include +#include "rtwtypes.h" +#include "rt_nonfinite.h" + +extern real_T rtGetInf(void); +extern real32_T rtGetInfF(void); +extern real_T rtGetMinusInf(void); +extern real32_T rtGetMinusInfF(void); + +#endif +/* End of code generation (rtGetInf.h) */ diff --git a/apps/position_estimator/codegen/rtGetNaN.c b/apps/position_estimator/codegen/rtGetNaN.c new file mode 100644 index 0000000000..6aa2f46393 --- /dev/null +++ b/apps/position_estimator/codegen/rtGetNaN.c @@ -0,0 +1,96 @@ +/* + * rtGetNaN.c + * + * Code generation for function 'position_estimator' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +/* + * Abstract: + * MATLAB for code generation function to initialize non-finite, NaN + */ +#include "rtGetNaN.h" +#define NumBitsPerChar 8U + +/* Function: rtGetNaN ================================================== + * Abstract: + * Initialize rtNaN needed by the generated code. + * NaN is initialized as non-signaling. Assumes IEEE. + */ +real_T rtGetNaN(void) +{ + size_t bitsPerReal = sizeof(real_T) * (NumBitsPerChar); + real_T nan = 0.0; + if (bitsPerReal == 32U) { + nan = rtGetNaNF(); + } else { + uint16_T one = 1U; + enum { + LittleEndian, + BigEndian + } machByteOrder = (*((uint8_T *) &one) == 1U) ? LittleEndian : BigEndian; + switch (machByteOrder) { + case LittleEndian: + { + union { + LittleEndianIEEEDouble bitVal; + real_T fltVal; + } tmpVal; + + tmpVal.bitVal.words.wordH = 0xFFF80000U; + tmpVal.bitVal.words.wordL = 0x00000000U; + nan = tmpVal.fltVal; + break; + } + + case BigEndian: + { + union { + BigEndianIEEEDouble bitVal; + real_T fltVal; + } tmpVal; + + tmpVal.bitVal.words.wordH = 0x7FFFFFFFU; + tmpVal.bitVal.words.wordL = 0xFFFFFFFFU; + nan = tmpVal.fltVal; + break; + } + } + } + + return nan; +} + +/* Function: rtGetNaNF ================================================== + * Abstract: + * Initialize rtNaNF needed by the generated code. + * NaN is initialized as non-signaling. Assumes IEEE. + */ +real32_T rtGetNaNF(void) +{ + IEEESingle nanF = { { 0 } }; + uint16_T one = 1U; + enum { + LittleEndian, + BigEndian + } machByteOrder = (*((uint8_T *) &one) == 1U) ? LittleEndian : BigEndian; + switch (machByteOrder) { + case LittleEndian: + { + nanF.wordL.wordLuint = 0xFFC00000U; + break; + } + + case BigEndian: + { + nanF.wordL.wordLuint = 0x7FFFFFFFU; + break; + } + } + + return nanF.wordL.wordLreal; +} + +/* End of code generation (rtGetNaN.c) */ diff --git a/apps/position_estimator/codegen/rtGetNaN.h b/apps/position_estimator/codegen/rtGetNaN.h new file mode 100644 index 0000000000..d3ec61c9e2 --- /dev/null +++ b/apps/position_estimator/codegen/rtGetNaN.h @@ -0,0 +1,21 @@ +/* + * rtGetNaN.h + * + * Code generation for function 'position_estimator' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +#ifndef __RTGETNAN_H__ +#define __RTGETNAN_H__ + +#include +#include "rtwtypes.h" +#include "rt_nonfinite.h" + +extern real_T rtGetNaN(void); +extern real32_T rtGetNaNF(void); + +#endif +/* End of code generation (rtGetNaN.h) */ diff --git a/apps/position_estimator/codegen/rt_nonfinite.c b/apps/position_estimator/codegen/rt_nonfinite.c new file mode 100644 index 0000000000..40e15fd227 --- /dev/null +++ b/apps/position_estimator/codegen/rt_nonfinite.c @@ -0,0 +1,87 @@ +/* + * rt_nonfinite.c + * + * Code generation for function 'position_estimator' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +/* + * Abstract: + * MATLAB for code generation function to initialize non-finites, + * (Inf, NaN and -Inf). + */ +#include "rt_nonfinite.h" +#include "rtGetNaN.h" +#include "rtGetInf.h" + +real_T rtInf; +real_T rtMinusInf; +real_T rtNaN; +real32_T rtInfF; +real32_T rtMinusInfF; +real32_T rtNaNF; + +/* Function: rt_InitInfAndNaN ================================================== + * Abstract: + * Initialize the rtInf, rtMinusInf, and rtNaN needed by the + * generated code. NaN is initialized as non-signaling. Assumes IEEE. + */ +void rt_InitInfAndNaN(size_t realSize) +{ + (void) (realSize); + rtNaN = rtGetNaN(); + rtNaNF = rtGetNaNF(); + rtInf = rtGetInf(); + rtInfF = rtGetInfF(); + rtMinusInf = rtGetMinusInf(); + rtMinusInfF = rtGetMinusInfF(); +} + +/* Function: rtIsInf ================================================== + * Abstract: + * Test if value is infinite + */ +boolean_T rtIsInf(real_T value) +{ + return ((value==rtInf || value==rtMinusInf) ? 1U : 0U); +} + +/* Function: rtIsInfF ================================================= + * Abstract: + * Test if single-precision value is infinite + */ +boolean_T rtIsInfF(real32_T value) +{ + return(((value)==rtInfF || (value)==rtMinusInfF) ? 1U : 0U); +} + +/* Function: rtIsNaN ================================================== + * Abstract: + * Test if value is not a number + */ +boolean_T rtIsNaN(real_T value) +{ +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + return _isnan(value)? TRUE:FALSE; +#else + return (value!=value)? 1U:0U; +#endif +} + +/* Function: rtIsNaNF ================================================= + * Abstract: + * Test if single-precision value is not a number + */ +boolean_T rtIsNaNF(real32_T value) +{ +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + return _isnan((real_T)value)? true:false; +#else + return (value!=value)? 1U:0U; +#endif +} + + +/* End of code generation (rt_nonfinite.c) */ diff --git a/apps/position_estimator/codegen/rt_nonfinite.h b/apps/position_estimator/codegen/rt_nonfinite.h new file mode 100644 index 0000000000..ac9660124d --- /dev/null +++ b/apps/position_estimator/codegen/rt_nonfinite.h @@ -0,0 +1,53 @@ +/* + * rt_nonfinite.h + * + * Code generation for function 'position_estimator' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +#ifndef __RT_NONFINITE_H__ +#define __RT_NONFINITE_H__ + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) +#include +#endif +#include +#include "rtwtypes.h" + +extern real_T rtInf; +extern real_T rtMinusInf; +extern real_T rtNaN; +extern real32_T rtInfF; +extern real32_T rtMinusInfF; +extern real32_T rtNaNF; +extern void rt_InitInfAndNaN(size_t realSize); +extern boolean_T rtIsInf(real_T value); +extern boolean_T rtIsInfF(real32_T value); +extern boolean_T rtIsNaN(real_T value); +extern boolean_T rtIsNaNF(real32_T value); + +typedef struct { + struct { + uint32_T wordH; + uint32_T wordL; + } words; +} BigEndianIEEEDouble; + +typedef struct { + struct { + uint32_T wordL; + uint32_T wordH; + } words; +} LittleEndianIEEEDouble; + +typedef struct { + union { + real32_T wordLreal; + uint32_T wordLuint; + } wordL; +} IEEESingle; + +#endif +/* End of code generation (rt_nonfinite.h) */ diff --git a/apps/position_estimator/codegen/rtwtypes.h b/apps/position_estimator/codegen/rtwtypes.h new file mode 100644 index 0000000000..e87ae1fdca --- /dev/null +++ b/apps/position_estimator/codegen/rtwtypes.h @@ -0,0 +1,175 @@ +/* + * rtwtypes.h + * + * Code generation for function 'position_estimator' + * + * C source code generated on: Fri Jun 8 13:31:21 2012 + * + */ + +#ifndef __RTWTYPES_H__ +#define __RTWTYPES_H__ +#ifndef TRUE +# define TRUE (1U) +#endif +#ifndef FALSE +# define FALSE (0U) +#endif +#ifndef __TMWTYPES__ +#define __TMWTYPES__ + +#include + +/*=======================================================================* + * Target hardware information + * Device type: Generic->MATLAB Host Computer + * Number of bits: char: 8 short: 16 int: 32 + * long: 64 native word size: 64 + * Byte ordering: LittleEndian + * Signed integer division rounds to: Zero + * Shift right on a signed integer as arithmetic shift: on + *=======================================================================*/ + +/*=======================================================================* + * Fixed width word size data types: * + * int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers * + * uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers * + * real32_T, real64_T - 32 and 64 bit floating point numbers * + *=======================================================================*/ + +typedef signed char int8_T; +typedef unsigned char uint8_T; +typedef short int16_T; +typedef unsigned short uint16_T; +typedef int int32_T; +typedef unsigned int uint32_T; +typedef long int64_T; +typedef unsigned long uint64_T; +typedef float real32_T; +typedef double real64_T; + +/*===========================================================================* + * Generic type definitions: real_T, time_T, boolean_T, int_T, uint_T, * + * ulong_T, char_T and byte_T. * + *===========================================================================*/ + +typedef double real_T; +typedef double time_T; +typedef unsigned char boolean_T; +typedef int int_T; +typedef unsigned uint_T; +typedef unsigned long ulong_T; +typedef char char_T; +typedef char_T byte_T; + +/*===========================================================================* + * Complex number type definitions * + *===========================================================================*/ +#define CREAL_T + typedef struct { + real32_T re; + real32_T im; + } creal32_T; + + typedef struct { + real64_T re; + real64_T im; + } creal64_T; + + typedef struct { + real_T re; + real_T im; + } creal_T; + + typedef struct { + int8_T re; + int8_T im; + } cint8_T; + + typedef struct { + uint8_T re; + uint8_T im; + } cuint8_T; + + typedef struct { + int16_T re; + int16_T im; + } cint16_T; + + typedef struct { + uint16_T re; + uint16_T im; + } cuint16_T; + + typedef struct { + int32_T re; + int32_T im; + } cint32_T; + + typedef struct { + uint32_T re; + uint32_T im; + } cuint32_T; + + typedef struct { + int64_T re; + int64_T im; + } cint64_T; + + typedef struct { + uint64_T re; + uint64_T im; + } cuint64_T; + + +/*=======================================================================* + * Min and Max: * + * int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers * + * uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers * + *=======================================================================*/ + +#define MAX_int8_T ((int8_T)(127)) +#define MIN_int8_T ((int8_T)(-128)) +#define MAX_uint8_T ((uint8_T)(255)) +#define MIN_uint8_T ((uint8_T)(0)) +#define MAX_int16_T ((int16_T)(32767)) +#define MIN_int16_T ((int16_T)(-32768)) +#define MAX_uint16_T ((uint16_T)(65535)) +#define MIN_uint16_T ((uint16_T)(0)) +#define MAX_int32_T ((int32_T)(2147483647)) +#define MIN_int32_T ((int32_T)(-2147483647-1)) +#define MAX_uint32_T ((uint32_T)(0xFFFFFFFFU)) +#define MIN_uint32_T ((uint32_T)(0)) +#define MAX_int64_T ((int64_T)(9223372036854775807L)) +#define MIN_int64_T ((int64_T)(-9223372036854775807L-1L)) +#define MAX_uint64_T ((uint64_T)(0xFFFFFFFFFFFFFFFFUL)) +#define MIN_uint64_T ((uint64_T)(0UL)) + +/* Logical type definitions */ +#if !defined(__cplusplus) && !defined(__true_false_are_keywords) +# ifndef false +# define false (0U) +# endif +# ifndef true +# define true (1U) +# endif +#endif + +/* + * MATLAB for code generation assumes the code is compiled on a target using a 2's compliment representation + * for signed integer values. + */ +#if ((SCHAR_MIN + 1) != -SCHAR_MAX) +#error "This code must be compiled using a 2's complement representation for signed integer values" +#endif + +/* + * Maximum length of a MATLAB identifier (function/variable) + * including the null-termination character. Referenced by + * rt_logging.c and rt_matrx.c. + */ +#define TMW_NAME_LENGTH_MAX 64 + +#endif +#endif +/* End of code generation (rtwtypes.h) */ diff --git a/apps/position_estimator/position_estimator.m b/apps/position_estimator/position_estimator.m new file mode 100644 index 0000000000..2ef4d8b069 --- /dev/null +++ b/apps/position_estimator/position_estimator.m @@ -0,0 +1,62 @@ +function [xapo1,Papo1] = position_estimator(u,z,xapo,Papo,gps_covariance,predict_only) %if predit_onli == 1: no update step: use this when no new gps data is available +%#codegen +%%initialization +%use model F=m*a x''=F/m +% 250Hz---> dT = 0.004s +%u=[phi;theta] +%x=[px;vx;py;vy]; +%%------------------------------------------ +dT=0.004; +%%------------------------------------------------ + +%R_t=[1,-r*dT,q*dT;r*dT,1,-p*dT;-q*dT,p*dT,1]; + + +F=[ 1, 0.004, 0, 0, 0, 0; + 0, 1, 0, 0, 0, 0; + 0, 0, 1, 0.004, 0, 0; + 0, 0, 0, 1, 0, 0; + 0, 0, 0, 0, 1, 0.004; + 0, 0, 0, 0, 0, 1]; + +B=[ 0, -0.1744; + 0, -87.2; + 0.1744, 0; + 87.2, 0; + 0, 0; + 0, 0]; + +H=[1,0,0,0,0,0; + 0,0,1,0,0,0; + 0,0,0,0,1,0]; + + + + Q=[1e-007 ,0 ,0 ,0 ,0 ,0; + 0 ,1 ,0 ,0 ,0 ,0; + 0 ,0 ,1e-007 ,0 ,0 ,0; + 0 ,0 ,0 ,1 ,0 ,0 + 0 ,0 ,0 ,0 ,1e-007 ,0; + 0 ,0 ,0 ,0 ,0 ,1]; %process Covariance Matrix + + +R=[gps_covariance(1), 0, 0; + 0, gps_covariance(2), 0; + 0, 0, gps_covariance(3)]; %measurement Covariance Matrix + +%%prediction + +xapri=F*xapo+B*u; +Papri=F*Papo*F'+Q; + +if 1 ~= predict_only + %update + yr=z-H*xapri; + S=H*Papri*H'+R; + K=(Papri*H')/S; + xapo1=xapri+K*yr; + Papo1=(eye(6)-K*H)*Papri; +else + Papo1=Papri; + xapo1=xapri; +end \ No newline at end of file diff --git a/apps/position_estimator/position_estimator.prj b/apps/position_estimator/position_estimator.prj new file mode 100644 index 0000000000..d754f36cc6 --- /dev/null +++ b/apps/position_estimator/position_estimator.prj @@ -0,0 +1,269 @@ + + + + option.general.TargetLang.C + true + true + false + true + true + true + true + option.general.FilePartitionMethod.MapMFileToCFile + option.general.GlobalDataSyncMethod.SyncAlways + true + option.general.DynamicMemoryAllocation.Disabled + option.paths.working.project + + option.paths.build.project + + + true + false + true + true + + + + + + + + + + true + 64 + true + 10 + 200 + 4000 + 200000 + 10000 + option.general.TargetLang.C + MATLAB Embedded Coder Target + option.CCompilerOptimization.Off + + false + make_rtw + default_tmf + true + option.general.FilePartitionMethod.MapMFileToCFile + true + option.general.DynamicMemoryAllocation.Disabled + option.paths.working.project + + option.paths.build.specified + ./codegen + + false + false + true + false + false + $M$N + $M$N + $M$N + $M$N + $M$N + $M$N + emxArray_$M$N + 32 + + + + + + + + + + false + C89/C90 (ANSI) + true + C89/C90 (ANSI) + false + true + true + false + option.ParenthesesLevel.Nominal + false + true + true + 64 + true + 10 + 200 + 4000 + 200000 + 10000 + true + position_estimator_mex + position_estimator + option.target.artifact.lib + true + true + R2011a + true + /home/thomasgubler/Dropbox/Semester Project Autonomous Landing PX4/position_estimator/codegen/mex/position_estimator/html/index.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + single + 2 x 1 + + + false + + + single + 3 x 1 + + + false + + + single + 6 x 1 + + + false + + + single + 6 x 6 + + + false + + + single + 3 x 1 + + + false + + + uint8 + 1 x 1 + + + false + + + + + + + + + /home/thomasgubler/tools/matlab + + + true + false + false + false + false + false + true + false + 3.2.0-25-generic + false + true + glnxa64 + true + + + + diff --git a/apps/position_estimator/position_estimator_main.c b/apps/position_estimator/position_estimator_main.c new file mode 100644 index 0000000000..773cd87ff3 --- /dev/null +++ b/apps/position_estimator/position_estimator_main.c @@ -0,0 +1,425 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: Tobias Naegeli + * Thomas Gubler + * Julian Oes + * Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * @file Model-identification based position estimator for multirotors + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "codegen/position_estimator.h" + +#define N_STATES 6 +#define ERROR_COVARIANCE_INIT 3 +#define R_EARTH 6371000.0 + +#define PROJECTION_INITIALIZE_COUNTER_LIMIT 5000 +#define REPROJECTION_COUNTER_LIMIT 125 + +__EXPORT int position_estimator_main(int argc, char *argv[]); + +static uint16_t position_estimator_counter_position_information; + +/* values for map projection */ +static double phi_1; +static double sin_phi_1; +static double cos_phi_1; +static double lambda_0; +static double scale; + +/** + * Initializes the map transformation. + * + * Initializes the transformation between the geographic coordinate system and the azimuthal equidistant plane + * @param lat in degrees (47.1234567°, not 471234567°) + * @param lon in degrees (8.1234567°, not 81234567°) + */ +static void map_projection_init(double lat_0, double lon_0) //lat_0, lon_0 are expected to be in correct format: -> 47.1234567 and not 471234567 +{ + /* notation and formulas according to: http://mathworld.wolfram.com/AzimuthalEquidistantProjection.html */ + phi_1 = lat_0 / 180.0 * M_PI; + lambda_0 = lon_0 / 180.0 * M_PI; + + sin_phi_1 = sin(phi_1); + cos_phi_1 = cos(phi_1); + + /* calculate local scale by using the relation of true distance and the distance on plane */ //TODO: this is a quick solution, there are probably easier ways to determine the scale + + /* 1) calculate true distance d on sphere to a point: http://www.movable-type.co.uk/scripts/latlong.html */ + const double r_earth = 6371000; + + double lat1 = phi_1; + double lon1 = lambda_0; + + double lat2 = phi_1 + 0.5 / 180 * M_PI; + double lon2 = lambda_0 + 0.5 / 180 * M_PI; + double sin_lat_2 = sin(lat2); + double cos_lat_2 = cos(lat2); + double d = acos(sin(lat1) * sin_lat_2 + cos(lat1) * cos_lat_2 * cos(lon2 - lon1)) * r_earth; + + /* 2) calculate distance rho on plane */ + double k_bar = 0; + double c = acos(sin_phi_1 * sin_lat_2 + cos_phi_1 * cos_lat_2 * cos(lon2 - lambda_0)); + + if (0 != c) + k_bar = c / sin(c); + + double x2 = k_bar * (cos_lat_2 * sin(lon2 - lambda_0)); //Projection of point 2 on plane + double y2 = k_bar * ((cos_phi_1 * sin_lat_2 - sin_phi_1 * cos_lat_2 * cos(lon2 - lambda_0))); + double rho = sqrt(pow(x2, 2) + pow(y2, 2)); + + scale = d / rho; + +} + +/** + * Transforms a point in the geographic coordinate system to the local azimuthal equidistant plane + * @param x north + * @param y east + * @param lat in degrees (47.1234567°, not 471234567°) + * @param lon in degrees (8.1234567°, not 81234567°) + */ +static void map_projection_project(double lat, double lon, float *x, float *y) +{ + /* notation and formulas accoring to: http://mathworld.wolfram.com/AzimuthalEquidistantProjection.html */ + double phi = lat / 180.0 * M_PI; + double lambda = lon / 180.0 * M_PI; + + double sin_phi = sin(phi); + double cos_phi = cos(phi); + + double k_bar = 0; + /* using small angle approximation (formula in comment is without aproximation) */ + double c = acos(sin_phi_1 * sin_phi + cos_phi_1 * cos_phi * (1 - pow((lambda - lambda_0), 2) / 2)); //double c = acos( sin_phi_1 * sin_phi + cos_phi_1 * cos_phi * cos(lambda - lambda_0) ); + + if (0 != c) + k_bar = c / sin(c); + + /* using small angle approximation (formula in comment is without aproximation) */ + *y = k_bar * (cos_phi * (lambda - lambda_0)) * scale;//*y = k_bar * (cos_phi * sin(lambda - lambda_0)) * scale; + *x = k_bar * ((cos_phi_1 * sin_phi - sin_phi_1 * cos_phi * (1 - pow((lambda - lambda_0), 2) / 2))) * scale; // *x = k_bar * ((cos_phi_1 * sin_phi - sin_phi_1 * cos_phi * cos(lambda - lambda_0))) * scale; + +// printf("%phi_1=%.10f, lambda_0 =%.10f\n", phi_1, lambda_0); +} + +/** + * Transforms a point in the local azimuthal equidistant plane to the geographic coordinate system + * + * @param x north + * @param y east + * @param lat in degrees (47.1234567°, not 471234567°) + * @param lon in degrees (8.1234567°, not 81234567°) + */ +static void map_projection_reproject(float x, float y, double *lat, double *lon) +{ + /* notation and formulas accoring to: http://mathworld.wolfram.com/AzimuthalEquidistantProjection.html */ + + double x_descaled = x / scale; + double y_descaled = y / scale; + + double c = sqrt(pow(x_descaled, 2) + pow(y_descaled, 2)); + double sin_c = sin(c); + double cos_c = cos(c); + + double lat_sphere = 0; + + if (c != 0) + lat_sphere = asin(cos_c * sin_phi_1 + (x_descaled * sin_c * cos_phi_1) / c); + else + lat_sphere = asin(cos_c * sin_phi_1); + +// printf("lat_sphere = %.10f\n",lat_sphere); + + double lon_sphere = 0; + + if (phi_1 == M_PI / 2) { + //using small angle approximation (formula in comment is without aproximation) + lon_sphere = (lambda_0 - y_descaled / x_descaled); //lon_sphere = (lambda_0 + atan2(-y_descaled, x_descaled)); + + } else if (phi_1 == -M_PI / 2) { + //using small angle approximation (formula in comment is without aproximation) + lon_sphere = (lambda_0 + y_descaled / x_descaled); //lon_sphere = (lambda_0 + atan2(y_descaled, x_descaled)); + + } else { + + lon_sphere = (lambda_0 + atan2(y_descaled * sin_c , c * cos_phi_1 * cos_c - x_descaled * sin_phi_1 * sin_c)); + //using small angle approximation +// double denominator = (c * cos_phi_1 * cos_c - x_descaled * sin_phi_1 * sin_c); +// if(denominator != 0) +// { +// lon_sphere = (lambda_0 + (y_descaled * sin_c) / denominator); +// } +// else +// { +// ... +// } + } + +// printf("lon_sphere = %.10f\n",lon_sphere); + + *lat = lat_sphere * 180.0 / M_PI; + *lon = lon_sphere * 180.0 / M_PI; + +} + +/**************************************************************************** + * main + ****************************************************************************/ + +int position_estimator_main(int argc, char *argv[]) +{ + + /* welcome user */ + printf("[multirotor position_estimator] started\n"); + + /* initialize values */ + static float u[2] = {0, 0}; + static float z[3] = {0, 0, 0}; + static float xapo[N_STATES] = {0, 0, 0, 0, 0, 0}; + static float Papo[N_STATES * N_STATES] = {ERROR_COVARIANCE_INIT, 0, 0, 0, 0, 0, + ERROR_COVARIANCE_INIT, 0, 0, 0, 0, 0, + ERROR_COVARIANCE_INIT, 0, 0, 0, 0, 0, + ERROR_COVARIANCE_INIT, 0, 0, 0, 0, 0, + ERROR_COVARIANCE_INIT, 0, 0, 0, 0, 0, + ERROR_COVARIANCE_INIT, 0, 0, 0, 0, 0 + }; + + static float xapo1[N_STATES]; + static float Papo1[36]; + + static float gps_covariance[3] = {0.0f, 0.0f, 0.0f}; + + static uint16_t counter = 0; + position_estimator_counter_position_information = 0; + + uint8_t predict_only = 1; + + bool gps_valid = false; + + bool new_initialization = true; + + static double lat_current = 0;//[°]] --> 47.0 + static double lon_current = 0; //[°]] -->8.5 + + + //TODO: handle flight without gps but with estimator + + /* subscribe to vehicle status, attitude, gps */ + struct vehicle_gps_position_s gps; + struct vehicle_status_s vstatus; + struct vehicle_attitude_s att; + + int vehicle_gps_sub = orb_subscribe(ORB_ID(vehicle_gps_position)); + int vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status)); + + /* subscribe to attitude at 100 Hz */ + int vehicle_attitude_sub = orb_subscribe(ORB_ID(vehicle_attitude)); + + /* wait until gps signal turns valid, only then can we initialize the projection */ + while (!gps_valid) { + struct pollfd fds[1] = { {.fd = vehicle_gps_sub, .events = POLLIN} }; + + /* wait for GPS updates, BUT READ VEHICLE STATUS (!) + * this choice is critical, since the vehicle status might not + * actually change, if this app is started after GPS lock was + * aquired. + */ + if (poll(fds, 1, 5000)) { + /* Wait for the GPS update to propagate (we have some time) */ + usleep(5000); + /* Read wether the vehicle status changed */ + orb_copy(ORB_ID(vehicle_status), vehicle_status_sub, &vstatus); + gps_valid = vstatus.gps_valid; + } + } + + /* get gps value for first initialization */ + orb_copy(ORB_ID(vehicle_gps_position), vehicle_gps_sub, &gps); + lat_current = ((double)(gps.lat)) * 1e-7; + lon_current = ((double)(gps.lon)) * 1e-7; + + /* publish global position messages only after first GPS message */ + struct vehicle_global_position_s global_pos = { + .lat = lat_current * 1e7, + .lon = lon_current * 1e7, + .alt = gps.alt + }; + int global_pos_pub = orb_advertise(ORB_ID(vehicle_global_position), &global_pos); + + printf("[multirotor position estimator] initialized projection with: lat: %.10f, lon:%.10f\n", lat_current, lon_current); + + while (1) { + + /*This runs at the rate of the sensors, if we have also a new gps update this is used in the position_estimator function */ + struct pollfd fds[1] = { {.fd = vehicle_attitude_sub, .events = POLLIN} }; + + if (poll(fds, 1, 5000) <= 0) { + /* error / timeout */ + } else { + + orb_copy(ORB_ID(vehicle_attitude), vehicle_attitude_sub, &att); + /* got attitude, updating pos as well */ + orb_copy(ORB_ID(vehicle_gps_position), vehicle_gps_sub, &gps); + orb_copy(ORB_ID(vehicle_status), vehicle_status_sub, &vstatus); + + /*copy attitude */ + u[0] = att.roll; + u[1] = att.pitch; + + /* initialize map projection with the last estimate (not at full rate) */ + if (counter % PROJECTION_INITIALIZE_COUNTER_LIMIT == 0) { + map_projection_init(lat_current, lon_current); + new_initialization = true; + + } else { + new_initialization = false; + } + + /*check if new gps values are available */ + gps_valid = vstatus.gps_valid; + + + if (gps_valid) { //we are safe to use the gps signal (it has good quality) + + predict_only = 0; + /* Project gps lat lon (Geographic coordinate system) to plane*/ + map_projection_project((double)(gps.lat) * 1e-7, (double)(gps.lon) * 1e-7, &(z[0]), &(z[1])); + + /* copy altitude */ + z[2] = (gps.alt) * 1e-3; + + gps_covariance[0] = gps.eph; //TODO: needs scaling + gps_covariance[1] = gps.eph; + gps_covariance[2] = gps.epv; + + } else { + /* we can not use the gps signal (it is of low quality) */ + predict_only = 1; + } + + // predict_only = 0; //TODO: only for testing, removeme, XXX + // z[0] = sinf(((float)counter)/180.0f*3.14159265f); //TODO: only for testing, removeme, XXX + // usleep(100000); //TODO: only for testing, removeme, XXX + + + /*Get new estimation (this is calculated in the plane) */ + //TODO: if new_initialization == true: use 0,0,0, else use xapo + if (true == new_initialization) { //TODO,XXX: uncomment! + xapo[0] = 0; //we have a new plane initialization. the current estimate is in the center of the plane + xapo[2] = 0; + xapo[4] = 0; + position_estimator(u, z, xapo, Papo, gps_covariance, predict_only, xapo1, Papo1); + + } else { + position_estimator(u, z, xapo, Papo, gps_covariance, predict_only, xapo1, Papo1); + } + + + + /* Copy values from xapo1 to xapo */ + int i; + + for (i = 0; i < N_STATES; i++) { + xapo[i] = xapo1[i]; + } + + if ((counter % REPROJECTION_COUNTER_LIMIT == 0) || (counter % (PROJECTION_INITIALIZE_COUNTER_LIMIT - 1) == 0)) { + /* Reproject from plane to geographic coordinate system */ + // map_projection_reproject(xapo1[0], xapo1[2], map_scale, phi_1, lambda_0, &lat_current, &lon_current) //TODO,XXX: uncomment! + map_projection_reproject(z[0], z[1], &lat_current, &lon_current); //do not use estimator for projection testing, removeme + // //DEBUG + // if(counter%500 == 0) + // { + // printf("phi_1: %.10f\n", phi_1); + // printf("lambda_0: %.10f\n", lambda_0); + // printf("lat_estimated: %.10f\n", lat_current); + // printf("lon_estimated: %.10f\n", lon_current); + // printf("z[0]=%.10f, z[1]=%.10f, z[2]=%f\n", z[0], z[1], z[2]); + // fflush(stdout); + // + // } + + // if(!isnan(lat_current) && !isnan(lon_current))// && !isnan(xapo1[4]) && !isnan(xapo1[1]) && !isnan(xapo1[3]) && !isnan(xapo1[5])) + // { + /* send out */ + + global_pos.lat = lat_current; + global_pos.lon = lon_current; + global_pos.alt = xapo1[4]; + global_pos.vx = xapo1[1]; + global_pos.vy = xapo1[3]; + global_pos.vz = xapo1[5]; + + /* publish current estimate */ + orb_publish(ORB_ID(vehicle_global_position), global_pos_pub, &global_pos); + // } + // else + // { + // printf("[position estimator] ERROR: nan values, lat_current=%.4f, lon_current=%.4f, z[0]=%.4f z[1]=%.4f\n", lat_current, lon_current, z[0], z[1]); + // fflush(stdout); + // } + + } + + counter++; + } + + } + + return 0; +} + + diff --git a/apps/px4/attitude_estimator_bm/.context b/apps/px4/attitude_estimator_bm/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/px4/attitude_estimator_bm/Makefile b/apps/px4/attitude_estimator_bm/Makefile new file mode 100644 index 0000000000..358b062c09 --- /dev/null +++ b/apps/px4/attitude_estimator_bm/Makefile @@ -0,0 +1,45 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Makefile to build the black magic attitude estimator +# + +APPNAME = attitude_estimator_bm +PRIORITY = SCHED_PRIORITY_MAX - 10 +STACKSIZE = 3000 + +# XXX this is *horribly* broken +INCLUDES = $(TOPDIR)/../mavlink/include/mavlink + +include $(APPDIR)/mk/app.mk diff --git a/apps/px4/attitude_estimator_bm/attitude_bm.c b/apps/px4/attitude_estimator_bm/attitude_bm.c new file mode 100644 index 0000000000..41ef479184 --- /dev/null +++ b/apps/px4/attitude_estimator_bm/attitude_bm.c @@ -0,0 +1,314 @@ + +/* + * attitude_bm.c + * + * Created on: 21.12.2010 + * Author: Laurens Mackay, Tobias Naegeli + */ + +#include +#include "attitude_bm.h" +#include "kalman.h" + + +#define TIME_STEP (1.0f / 500.0f) + +static kalman_t attitude_blackmagic_kal; + +void vect_norm(float_vect3 *vect) +{ + float length = sqrtf( + vect->x * vect->x + vect->y * vect->y + vect->z * vect->z); + + if (length != 0) { + vect->x /= length; + vect->y /= length; + vect->z /= length; + } +} + + +void vect_cross_product(const float_vect3 *a, const float_vect3 *b, + float_vect3 *c) +{ + c->x = a->y * b->z - a->z * b->y; + c->y = a->z * b->x - a->x * b->z; + c->z = a->x * b->y - a->y * b->x; +} + +void attitude_blackmagic_update_a(void) +{ + // for acc + // Idendity matrix already in A. + M(attitude_blackmagic_kal.a, 0, 1) = TIME_STEP * kalman_get_state( + &attitude_blackmagic_kal, 11); + M(attitude_blackmagic_kal.a, 0, 2) = -TIME_STEP * kalman_get_state( + &attitude_blackmagic_kal, 10); + + M(attitude_blackmagic_kal.a, 1, 0) = -TIME_STEP * kalman_get_state( + &attitude_blackmagic_kal, 11); + M(attitude_blackmagic_kal.a, 1, 2) = TIME_STEP * kalman_get_state( + &attitude_blackmagic_kal, 9); + + M(attitude_blackmagic_kal.a, 2, 0) = TIME_STEP * kalman_get_state( + &attitude_blackmagic_kal, 10); + M(attitude_blackmagic_kal.a, 2, 1) = -TIME_STEP * kalman_get_state( + &attitude_blackmagic_kal, 9); + + // for mag + // Idendity matrix already in A. + M(attitude_blackmagic_kal.a, 3, 4) = TIME_STEP * kalman_get_state( + &attitude_blackmagic_kal, 11); + M(attitude_blackmagic_kal.a, 3, 5) = -TIME_STEP * kalman_get_state( + &attitude_blackmagic_kal, 10); + + M(attitude_blackmagic_kal.a, 4, 3) = -TIME_STEP * kalman_get_state( + &attitude_blackmagic_kal, 11); + M(attitude_blackmagic_kal.a, 4, 5) = TIME_STEP * kalman_get_state( + &attitude_blackmagic_kal, 9); + + M(attitude_blackmagic_kal.a, 5, 3) = TIME_STEP * kalman_get_state( + &attitude_blackmagic_kal, 10); + M(attitude_blackmagic_kal.a, 5, 4) = -TIME_STEP * kalman_get_state( + &attitude_blackmagic_kal, 9); + +} + +void attitude_blackmagic_init(void) +{ + //X Kalmanfilter + //initalize matrices + + static m_elem kal_a[12 * 12] = { + 1.0f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 1.0f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 1.0f, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 1.0f, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 1.0f, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 1.0f, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 1.0f, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 1.0f, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 1.0f, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0f, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0f, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0f + }; + + static m_elem kal_c[9 * 12] = { + 1.0f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 1.0f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 1.0f, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 1.0f, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 1.0f, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 1.0f, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 1.0f, 0, 0, 1.0f, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 1.0f, 0, 0, 1.0f, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 1.0f, 0, 0, 1.0f + }; + + + +#define FACTOR 0.5 +#define FACTORstart 1 + + +// static m_elem kal_gain[12 * 9] = +// { 0.004 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +// 0 , 0.004 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +// 0 , 0 , 0.004 , 0 , 0 , 0 , 0 , 0 , 0, +// 0 , 0 , 0 , 0.015, 0 , 0 , 0 , 0 , 0, +// 0 , 0 , 0 , 0 , 0.015, 0 , 0 , 0 , 0, +// 0 , 0 , 0 , 0 , 0 , 0.015, 0 , 0 , 0, +// 0.0000 , +0.00002,0 , 0 , 0, 0, 0, 0 , 0, +// -0.00002,0 , 0 , 0 , 0, 0, 0, 0, 0, +// 0, 0 , 0 , 0, 0, 0, 0, 0, 0, +// 0 , 0 , 0 , 0 , 0 , 0 , 0.4 , 0 , 0, +// 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0.4 , 0, +// 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0.4 +// }; + + static m_elem kal_gain[12 * 9] = { + 0.0006f , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, + 0 , 0.0006f , 0 , 0 , 0 , 0 , 0 , 0 , 0, + 0 , 0 , 0.0006f , 0 , 0 , 0 , 0 , 0 , 0, + 0 , 0 , 0 , 0.015f, 0 , 0 , 0 , 0 , 0, + 0 , 0 , 0 , 0 , 0.015f, 0 , 0 , 0 , 0, + 0 , 0 , 0 , 0 , 0 , 0.015f, 0 , 0 , 0, + 0.0000f , +0.00002f, 0 , 0 , 0, 0, 0, 0 , 0, + -0.00002f, 0 , 0 , 0 , 0, 0, 0, 0, 0, + 0, 0 , 0 , 0, 0, 0, 0, 0, 0, + 0 , 0 , 0 , 0 , 0 , 0 , 0.6f , 0 , 0, + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0.6f , 0, + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0.6f + }; + //offset update only correct if not upside down. + +#define K (10.0f*TIME_STEP) + + static m_elem kal_gain_start[12 * 9] = { + K, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, K, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, K, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, K, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, K, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, K, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, K, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, K, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, K, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + + + static m_elem kal_x_apriori[12 * 1] = + { }; + + + //---> initial states sind aposteriori!? ---> fehler + static m_elem kal_x_aposteriori[12 * 1] = + { 0.0f, 0.0f, -1.0f, 0.6f, 0.0f, 0.8f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + + kalman_init(&attitude_blackmagic_kal, 12, 9, kal_a, kal_c, + kal_gain_start, kal_gain, kal_x_apriori, kal_x_aposteriori, 1000); + +} + +void attitude_blackmagic(const float_vect3 *accel, const float_vect3 *mag, const float_vect3 *gyro) +{ + //Transform accelerometer used in all directions + // float_vect3 acc_nav; + //body2navi(&global_data.accel_si, &global_data.attitude, &acc_nav); + + // Kalman Filter + + //Calculate new linearized A matrix + attitude_blackmagic_update_a(); + + kalman_predict(&attitude_blackmagic_kal); + + //correction update + + m_elem measurement[9] = + { }; + m_elem mask[9] = + { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; + + measurement[0] = accel->x; + measurement[1] = accel->y; + measurement[2] = accel->z; + + measurement[3] = mag->x; + measurement[4] = mag->y; + measurement[5] = mag->z; + + measurement[6] = gyro->x; + measurement[7] = gyro->y; + measurement[8] = gyro->z; + + //Put measurements into filter + + +// static int j = 0; +// if (j >= 3) +// { +// j = 0; +// +// mask[3]=1; +// mask[4]=1; +// mask[5]=1; +// j=0; +// +// }else{ +// j++;} + + kalman_correct(&attitude_blackmagic_kal, measurement, mask); + +} +void attitude_blackmagic_get_all(float_vect3 *euler, float_vect3 *rates, float_vect3 *x_n_b, float_vect3 *y_n_b, float_vect3 *z_n_b) +{ + //debug + + // save outputs + float_vect3 kal_acc; + float_vect3 kal_mag; +// float_vect3 kal_w0, kal_w; + + kal_acc.x = kalman_get_state(&attitude_blackmagic_kal, 0); + kal_acc.y = kalman_get_state(&attitude_blackmagic_kal, 1); + kal_acc.z = kalman_get_state(&attitude_blackmagic_kal, 2); + + kal_mag.x = kalman_get_state(&attitude_blackmagic_kal, 3); + kal_mag.y = kalman_get_state(&attitude_blackmagic_kal, 4); + kal_mag.z = kalman_get_state(&attitude_blackmagic_kal, 5); + +// kal_w0.x = kalman_get_state(&attitude_blackmagic_kal, 6); +// kal_w0.y = kalman_get_state(&attitude_blackmagic_kal, 7); +// kal_w0.z = kalman_get_state(&attitude_blackmagic_kal, 8); +// +// kal_w.x = kalman_get_state(&attitude_blackmagic_kal, 9); +// kal_w.y = kalman_get_state(&attitude_blackmagic_kal, 10); +// kal_w.z = kalman_get_state(&attitude_blackmagic_kal, 11); + + rates->x = kalman_get_state(&attitude_blackmagic_kal, 9); + rates->y = kalman_get_state(&attitude_blackmagic_kal, 10); + rates->z = kalman_get_state(&attitude_blackmagic_kal, 11); + + + +// kal_w = kal_w; // XXX hack to silence compiler warning +// kal_w0 = kal_w0; // XXX hack to silence compiler warning + + + + //debug_vect("magn", mag); + + //float_vect3 x_n_b, y_n_b, z_n_b; + z_n_b->x = -kal_acc.x; + z_n_b->y = -kal_acc.y; + z_n_b->z = -kal_acc.z; + vect_norm(z_n_b); + vect_cross_product(z_n_b, &kal_mag, y_n_b); + vect_norm(y_n_b); + + vect_cross_product(y_n_b, z_n_b, x_n_b); + + + + //save euler angles + euler->x = atan2f(z_n_b->y, z_n_b->z); + euler->y = -asinf(z_n_b->x); + euler->z = atan2f(y_n_b->x, x_n_b->x); + +} diff --git a/apps/px4/attitude_estimator_bm/attitude_bm.h b/apps/px4/attitude_estimator_bm/attitude_bm.h new file mode 100644 index 0000000000..c21b3d6f16 --- /dev/null +++ b/apps/px4/attitude_estimator_bm/attitude_bm.h @@ -0,0 +1,24 @@ +/* + * attitude_blackmagic.h + * + * Created on: May 31, 2011 + * Author: pixhawk + */ + +#ifndef attitude_blackmagic_H_ +#define attitude_blackmagic_H_ + +#include "matrix.h" + +void vect_norm(float_vect3 *vect); + +void vect_cross_product(const float_vect3 *a, const float_vect3 *b, float_vect3 *c); + +void attitude_blackmagic_update_a(void); + +void attitude_blackmagic_init(void); + +void attitude_blackmagic(const float_vect3 *accel, const float_vect3 *mag, const float_vect3 *gyro); + +void attitude_blackmagic_get_all(float_vect3 *euler, float_vect3 *rates, float_vect3 *x_n_b, float_vect3 *y_n_b, float_vect3 *z_n_b); +#endif /* attitude_blackmagic_H_ */ diff --git a/apps/px4/attitude_estimator_bm/attitude_estimator_bm.c b/apps/px4/attitude_estimator_bm/attitude_estimator_bm.c new file mode 100644 index 0000000000..3c6c8eec31 --- /dev/null +++ b/apps/px4/attitude_estimator_bm/attitude_estimator_bm.c @@ -0,0 +1,228 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: Tobias Naegeli + * Laurens Mackay + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* @file Black Magic Attitude Estimator */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "attitude_bm.h" + +static unsigned int loop_interval_alarm = 4500; // loop interval in microseconds + +__EXPORT int attitude_estimator_bm_main(int argc, char *argv[]); + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * user_start + ****************************************************************************/ +int attitude_estimator_bm_update(struct sensor_combined_s *raw, float_vect3 *euler, float_vect3 *rates, float_vect3 *x_n_b, float_vect3 *y_n_b, float_vect3 *z_n_b); + +int attitude_estimator_bm_update(struct sensor_combined_s *raw, float_vect3 *euler, float_vect3 *rates, float_vect3 *x_n_b, float_vect3 *y_n_b, float_vect3 *z_n_b) +{ + float_vect3 gyro_values; + gyro_values.x = raw->gyro_rad_s[0]; + gyro_values.y = raw->gyro_rad_s[1]; + gyro_values.z = raw->gyro_rad_s[2]; + + float_vect3 accel_values; + accel_values.x = raw->accelerometer_m_s2[0]; + accel_values.y = raw->accelerometer_m_s2[1]; + accel_values.z = raw->accelerometer_m_s2[2]; + + float_vect3 mag_values; + mag_values.x = raw->magnetometer_ga[0]; + mag_values.y = raw->magnetometer_ga[1]; + mag_values.z = raw->magnetometer_ga[2]; + + attitude_blackmagic(&accel_values, &mag_values, &gyro_values); + + /* read out values */ + attitude_blackmagic_get_all(euler, rates, x_n_b, y_n_b, z_n_b); + + return OK; +} + + +int attitude_estimator_bm_main(int argc, char *argv[]) +{ + // print text + printf("Black Magic Attitude Estimator initialized..\n\n"); + fflush(stdout); + + /* data structures to read euler angles and rotation matrix back */ + float_vect3 euler = {.x = 0, .y = 0, .z = 0}; + float_vect3 rates; + float_vect3 x_n_b; + float_vect3 y_n_b; + float_vect3 z_n_b; + + int overloadcounter = 19; + + /* initialize */ + attitude_blackmagic_init(); + + /* store start time to guard against too slow update rates */ + uint64_t last_run = hrt_absolute_time(); + + struct sensor_combined_s sensor_combined_s_local = { .gyro_raw = {0}}; + struct vehicle_attitude_s att = {.roll = 0.0f, .pitch = 0.0f, .yaw = 0.0f, + .rollspeed = 0.0f, .pitchspeed = 0.0f, .yawspeed = 0.0f, + .R = {0}, .timestamp = 0}; + + uint64_t last_data = 0; + + /* subscribe to raw data */ + int sub_raw = orb_subscribe(ORB_ID(sensor_combined)); + + /* rate-limit raw data updates to 200Hz */ + //orb_set_interval(sub_raw, 5); + + /* advertise attitude */ + int pub_att = orb_advertise(ORB_ID(vehicle_attitude), &att); + + struct pollfd fds[] = { + { .fd = sub_raw, .events = POLLIN }, + }; + + // int paramcounter = 100; + + /* Main loop*/ + while (true) { + + /* wait for sensor update */ + int ret = poll(fds, 1, 5000); + + if (ret < 0) { + /* XXX this is seriously bad - should be an emergency */ + } else if (ret == 0) { + /* XXX this means no sensor data - should be critical or emergency */ + printf("[attitude estimator bm] WARNING: Not getting sensor data - sensor app running?\n"); + continue; + } + + orb_copy(ORB_ID(sensor_combined), sub_raw, &sensor_combined_s_local); + + uint64_t now = hrt_absolute_time(); + unsigned int time_elapsed = now - last_run; + last_run = now; + +//#if 0 + + if (time_elapsed > loop_interval_alarm) { + //TODO: add warning, cpu overload here + if (overloadcounter == 20) { + printf("CPU OVERLOAD DETECTED IN ATTITUDE ESTIMATOR BLACK MAGIC (%lu > %lu)\n", time_elapsed, loop_interval_alarm); + overloadcounter = 0; + } + + overloadcounter++; + } + +//#endif +// now = hrt_absolute_time(); + /* filter values */ + attitude_estimator_bm_update(&sensor_combined_s_local, &euler, &rates, &x_n_b, &y_n_b, &z_n_b); + +// time_elapsed = hrt_absolute_time() - now; +// if (blubb == 20) +// { +// printf("Estimator: %lu\n", time_elapsed); +// blubb = 0; +// } +// blubb++; + +// if (last_data > 0 && sensor_combined_s_local.timestamp - last_data > 8000) printf("sensor data missed! (%llu)\n", sensor_combined_s_local.timestamp - last_data); + +// printf("%llu -> %llu = %llu\n", last_data, sensor_combined_s_local.timestamp, sensor_combined_s_local.timestamp - last_data); + // last_data = sensor_combined_s_local.timestamp; + + /*correct yaw */ +// euler.z = euler.z + M_PI; + + /* send out */ + + att.timestamp = sensor_combined_s_local.timestamp; + att.roll = euler.x; + att.pitch = euler.y; + att.yaw = euler.z + M_PI; + + if (att.yaw > 2.0f * ((float)M_PI)) { + att.yaw -= 2.0f * ((float)M_PI); + } + + att.rollspeed = rates.x; + att.pitchspeed = rates.y; + att.yawspeed = rates.z; + + att.R[0][0] = x_n_b.x; + att.R[0][1] = x_n_b.y; + att.R[0][2] = x_n_b.z; + // XXX add remaining entries + + // Broadcast + orb_publish(ORB_ID(vehicle_attitude), pub_att, &att); + } + + /* Should never reach here */ + return 0; +} + + diff --git a/apps/px4/attitude_estimator_bm/kalman.c b/apps/px4/attitude_estimator_bm/kalman.c new file mode 100644 index 0000000000..e4ea7a4173 --- /dev/null +++ b/apps/px4/attitude_estimator_bm/kalman.c @@ -0,0 +1,115 @@ +/* + * kalman.c + * + * Created on: 01.12.2010 + * Author: Laurens Mackay + */ +#include "kalman.h" +//#include "mavlink_debug.h" + +void kalman_init(kalman_t *kalman, int states, int measurements, m_elem a[], + m_elem c[], m_elem gain_start[], m_elem gain[], m_elem x_apriori[], + m_elem x_aposteriori[], int gainfactorsteps) +{ + kalman->states = states; + kalman->measurements = measurements; + kalman->gainfactorsteps = gainfactorsteps; + kalman->gainfactor = 0; + + //Create all matrices that are persistent + kalman->a = matrix_create(states, states, a); + kalman->c = matrix_create(measurements, states, c); + kalman->gain_start = matrix_create(states, measurements, gain_start); + kalman->gain = matrix_create(states, measurements, gain); + kalman->x_apriori = matrix_create(states, 1, x_apriori); + kalman->x_aposteriori = matrix_create(states, 1, x_aposteriori); +} + +void kalman_predict(kalman_t *kalman) +{ + matrix_mult(kalman->a, kalman->x_aposteriori, kalman->x_apriori); +} + +void kalman_correct(kalman_t *kalman, m_elem measurement_a[], m_elem mask_a[]) +{ + //create matrices from inputs + matrix_t measurement = + matrix_create(kalman->measurements, 1, measurement_a); + matrix_t mask = matrix_create(kalman->measurements, 1, mask_a); + + //create temporary matrices + m_elem gain_start_part_a[KALMAN_MAX_STATES * KALMAN_MAX_MEASUREMENTS] = + { }; + matrix_t gain_start_part = matrix_create(kalman->states, + kalman->measurements, gain_start_part_a); + + m_elem gain_part_a[KALMAN_MAX_STATES * KALMAN_MAX_MEASUREMENTS] = + { }; + matrix_t gain_part = matrix_create(kalman->states, kalman->measurements, + gain_part_a); + + m_elem gain_sum_a[KALMAN_MAX_STATES * KALMAN_MAX_MEASUREMENTS] = + { }; + matrix_t gain_sum = matrix_create(kalman->states, kalman->measurements, + gain_sum_a); + + m_elem error_a[KALMAN_MAX_MEASUREMENTS * 1] = + { }; + matrix_t error = matrix_create(kalman->measurements, 1, error_a); + + m_elem measurement_estimate_a[KALMAN_MAX_MEASUREMENTS * 1] = + { }; + matrix_t measurement_estimate = matrix_create(kalman->measurements, 1, + measurement_estimate_a); + + m_elem x_update_a[KALMAN_MAX_STATES * 1] = + { }; + matrix_t x_update = matrix_create(kalman->states, 1, x_update_a); + + + + //x(:,i+1)=xapriori+(gainfactor*[M_50(:,1) M(:,2)]+(1-gainfactor)*M_start)*(z-C*xapriori); + + + //est=C*xapriori; + matrix_mult(kalman->c, kalman->x_apriori, measurement_estimate); + //error=(z-C*xapriori) = measurement-estimate + matrix_sub(measurement, measurement_estimate, error); + matrix_mult_element(error, mask, error); + + kalman->gainfactor = kalman->gainfactor * (1.0f - 1.0f + / kalman->gainfactorsteps) + 1.0f * 1.0f / kalman->gainfactorsteps; + + + + matrix_mult_scalar(kalman->gainfactor, kalman->gain, gain_part); + + matrix_mult_scalar(1.0f - kalman->gainfactor, kalman->gain_start, + gain_start_part); + + matrix_add(gain_start_part, gain_part, gain_sum); + + //gain*(z-C*xapriori) + matrix_mult(gain_sum, error, x_update); + + //xaposteriori = xapriori + update + + matrix_add(kalman->x_apriori, x_update, kalman->x_aposteriori); + + +// static int i=0; +// if(i++==4){ +// i=0; +// float_vect3 out_kal; +// out_kal.x = M(gain_sum,0,1); +//// out_kal_z.x = z_measurement[1]; +// out_kal.y = M(gain_sum,1,1); +// out_kal.z = M(gain_sum,2,1); +// debug_vect("out_kal", out_kal); +// } +} + +m_elem kalman_get_state(kalman_t *kalman, int state) +{ + return M(kalman->x_aposteriori, state, 0); +} diff --git a/apps/px4/attitude_estimator_bm/kalman.h b/apps/px4/attitude_estimator_bm/kalman.h new file mode 100644 index 0000000000..0a6a185059 --- /dev/null +++ b/apps/px4/attitude_estimator_bm/kalman.h @@ -0,0 +1,35 @@ +/* + * kalman.h + * + * Created on: 01.12.2010 + * Author: Laurens Mackay + */ + +#ifndef KALMAN_H_ +#define KALMAN_H_ + +#include "matrix.h" + +#define KALMAN_MAX_STATES 12 +#define KALMAN_MAX_MEASUREMENTS 9 +typedef struct { + int states; + int measurements; + matrix_t a; + matrix_t c; + matrix_t gain_start; + matrix_t gain; + matrix_t x_apriori; + matrix_t x_aposteriori; + float gainfactor; + int gainfactorsteps; +} kalman_t; + +void kalman_init(kalman_t *kalman, int states, int measurements, m_elem a[], + m_elem c[], m_elem gain_start[], m_elem gain[], m_elem x_apriori[], + m_elem x_aposteriori[], int gainfactorsteps); +void kalman_predict(kalman_t *kalman); +void kalman_correct(kalman_t *kalman, m_elem measurement_a[], m_elem mask_a[]); +m_elem kalman_get_state(kalman_t *kalman, int state); + +#endif /* KALMAN_H_ */ diff --git a/apps/px4/attitude_estimator_bm/matrix.h b/apps/px4/attitude_estimator_bm/matrix.h new file mode 100644 index 0000000000..613a2d0811 --- /dev/null +++ b/apps/px4/attitude_estimator_bm/matrix.h @@ -0,0 +1,156 @@ +/* + * matrix.h + * + * Created on: 18.11.2010 + * Author: Laurens Mackay + */ + +#ifndef MATRIX_H_ +#define MATRIX_H_ + +typedef float m_elem; + +typedef struct { + int rows; + int cols; + m_elem *a; +} matrix_t; + +typedef struct { + float x; + float y; + float z; +} float_vect3; + +#define M(m,i,j) m.a[m.cols*i+j] + +///* This is the datatype used for the math and non-type specific ops. */ +// +//matrix_t matrix_create(const int rows, const int cols, m_elem * a); +///* matrix C = matrix A + matrix B , both of size m x n */ +//void matrix_add(const matrix_t a, const matrix_t b, matrix_t c); +// +///* matrix C = matrix A - matrix B , all of size m x n */ +//void matrix_sub(const matrix_t a, const matrix_t b, matrix_t c); +// +///* matrix C = matrix A x matrix B , A(a_rows x a_cols), B(a_cols x b_cols) */ +//void matrix_mult(const matrix_t a, const matrix_t b, matrix_t c); +// +//void matrix_mult_scalar(const float f, const matrix_t a, matrix_t c); +// +//void matrix_mult_element(const matrix_t a, const matrix_t b, matrix_t c); +// +///* matrix C = A*B'*/ +//void matrix_mult_trans(const matrix_t a, const matrix_t b, matrix_t c); + + +static inline matrix_t matrix_create(const int rows, const int cols, m_elem *a) +{ + matrix_t ret; + ret.rows = rows; + ret.cols = cols; + ret.a = a; + return ret; +} + +static inline void matrix_add(const matrix_t a, const matrix_t b, matrix_t c) +{ + if (a.rows != c.rows || a.cols != c.cols || b.rows != c.rows || b.cols + != c.cols) { + //debug_message_buffer("matrix_add: Dimension mismatch"); + } + + for (int i = 0; i < c.rows; i++) { + for (int j = 0; j < c.cols; j++) { + M(c, i, j) = M(a, i, j) + M(b, i, j); + } + + } +} + +static inline void matrix_sub(const matrix_t a, const matrix_t b, matrix_t c) +{ + if (a.rows != c.rows || a.cols != c.cols || b.rows != c.rows || b.cols + != c.cols) { + //debug_message_buffer("matrix_sub: Dimension mismatch"); + } + + for (int i = 0; i < c.rows; i++) { + for (int j = 0; j < c.cols; j++) { + M(c, i, j) = M(a, i, j) - M(b, i, j); + } + + } +} + +static inline void matrix_mult(const matrix_t a, const matrix_t b, matrix_t c) +{ + if (a.rows != c.rows || b.cols != c.cols || a.cols != b.rows) { + //debug_message_buffer("matrix_mult: Dimension mismatch"); + } + + for (int i = 0; i < a.rows; i++) { + for (int j = 0; j < b.cols; j++) { + M(c, i, j) = 0; + + for (int k = 0; k < a.cols; k++) { + M(c, i, j) += M(a, i, k) * M(b, k, j); + } + } + + } +} + +static inline void matrix_mult_trans(const matrix_t a, const matrix_t b, matrix_t c) +{ + + if (a.rows != c.rows || b.rows != c.cols || a.cols != b.cols) { + //debug_message_buffer("matrix_mult: Dimension mismatch"); + } + + for (int i = 0; i < a.rows; i++) { + for (int j = 0; j < b.cols; j++) { + M(c, i, j) = 0; + + for (int k = 0; k < a.cols; k++) { + M(c, i, j) += M(a, i, k) * M(b, j, k); + } + } + + } + +} + +static inline void matrix_mult_scalar(const float f, const matrix_t a, matrix_t c) +{ + if (a.rows != c.rows || a.cols != c.cols) { + //debug_message_buffer("matrix_mult_scalar: Dimension mismatch"); + } + + for (int i = 0; i < c.rows; i++) { + for (int j = 0; j < c.cols; j++) { + M(c, i, j) = f * M(a, i, j); + } + + } +} + + +static inline void matrix_mult_element(const matrix_t a, const matrix_t b, matrix_t c) +{ + if (a.rows != c.rows || a.cols != c.cols || b.rows != c.rows || b.cols + != c.cols) { + //debug_message_buffer("matrix_mult_element: Dimension mismatch"); + } + + for (int i = 0; i < c.rows; i++) { + for (int j = 0; j < c.cols; j++) { + M(c, i, j) = M(a, i, j) * M(b, i, j); + } + + } +} + + + +#endif /* MATRIX_H_ */ diff --git a/apps/px4/fmu/Makefile b/apps/px4/fmu/Makefile new file mode 100644 index 0000000000..7f1f836e30 --- /dev/null +++ b/apps/px4/fmu/Makefile @@ -0,0 +1,38 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Interface driver for the PX4FMU board +# + +include $(APPDIR)/mk/app.mk diff --git a/apps/px4/fmu/fmu.cpp b/apps/px4/fmu/fmu.cpp new file mode 100644 index 0000000000..6c7d9f7426 --- /dev/null +++ b/apps/px4/fmu/fmu.cpp @@ -0,0 +1,452 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Driver/configurator for the PX4 FMU multi-purpose port. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include + +class FMUServo : public device::CDev +{ +public: + enum Mode { + MODE_2PWM, + MODE_4PWM, + MODE_NONE + }; + FMUServo(Mode mode); + ~FMUServo(); + + virtual int ioctl(struct file *filp, int cmd, unsigned long arg); + + virtual int init(); + +private: + Mode _mode; + int _task; + int _t_actuators; + int _t_armed; + unsigned _num_outputs; + + volatile bool _task_should_exit; + bool _armed; + + MixMixer *_mixer[4]; + + static void task_main_trampoline(int argc, char *argv[]); + void task_main(); +}; + +namespace { + +FMUServo *g_servo; + +} // namespace + +FMUServo::FMUServo(Mode mode) : + CDev("fmuservo", PWM_OUTPUT_DEVICE_PATH), + _mode(mode), + _task(-1), + _t_actuators(-1), + _t_armed(-1), + _task_should_exit(false), + _armed(false) +{ + for (unsigned i = 0; i < 4; i++) + _mixer[i] = nullptr; +} + +FMUServo::~FMUServo() +{ + if (_task != -1) { + /* task should wake up every 100ms or so at least */ + _task_should_exit = true; + + unsigned i = 0; + do { + /* wait 20ms */ + usleep(20000); + + /* if we have given up, kill it */ + if (++i > 10) { + task_delete(_task); + break; + } + + } while (_task != -1); + } + + g_servo = nullptr; +} + +int +FMUServo::init() +{ + int ret; + + ASSERT(_task == -1); + + /* do regular cdev init */ + ret = CDev::init(); + if (ret != OK) + return ret; + + /* start the IO interface task */ + _task = task_create("fmuservo", SCHED_PRIORITY_DEFAULT, 1024, (main_t)&FMUServo::task_main_trampoline, nullptr); + if (_task < 0) { + debug("task start failed: %d", errno); + return -errno; + } + + return OK; +} + +void +FMUServo::task_main_trampoline(int argc, char *argv[]) +{ + g_servo->task_main(); +} + +void +FMUServo::task_main() +{ + log("ready"); + + /* configure for PWM output */ + switch (_mode) { + case MODE_2PWM: + /* multi-port with flow control lines as PWM */ + /* XXX magic numbers */ + up_pwm_servo_init(0x3); + break; + case MODE_4PWM: + /* multi-port as 4 PWM outs */ + /* XXX magic numbers */ + up_pwm_servo_init(0xf); + break; + case MODE_NONE: + /* we should never get here... */ + break; + } + + /* subscribe to objects that we are interested in watching */ + _t_actuators = orb_subscribe(ORB_ID(actuator_controls)); + orb_set_interval(_t_actuators, 20); /* 50Hz update rate */ + + _t_armed = orb_subscribe(ORB_ID(actuator_armed)); + orb_set_interval(_t_armed, 100); /* 10Hz update rate */ + + struct pollfd fds[2]; + fds[0].fd = _t_actuators; + fds[0].events = POLLIN; + fds[1].fd = _t_armed; + fds[1].events = POLLIN; + + unsigned num_outputs = (_mode == MODE_2PWM) ? 2 : 4; + + /* loop until killed */ + while (!_task_should_exit) { + + /* sleep waiting for data, but no more than 100ms */ + int ret = ::poll(&fds[0], 2, 100); + + /* this would be bad... */ + if (ret < 0) { + log("poll error %d", errno); + usleep(1000000); + continue; + } + + /* do we have a control update? */ + if (fds[0].revents & POLLIN) { + struct actuator_controls ac; + + /* get controls */ + orb_copy(ORB_ID(actuator_controls), _t_actuators, &ac); + + /* iterate actuators */ + for (unsigned i = 0; i < num_outputs; i++) { + + /* if the actuator is configured */ + if (_mixer[i] != nullptr) { + + /* mix controls to the actuator */ + float output = mixer_mix(_mixer[i], &ac.control[0]); + + /* scale for PWM output 900 - 2100us */ + up_pwm_servo_set(i, 1500 + (600 * output)); + } + } + } + + /* how about an arming update? */ + if (fds[1].revents & POLLIN) { + struct actuator_armed aa; + + /* get new value */ + orb_copy(ORB_ID(actuator_armed), _t_armed, &aa); + + /* update PMW servo armed status */ + up_pwm_servo_arm(aa.armed); + } + } + + ::close(_t_actuators); + ::close(_t_armed); + + /* make sure servos are off */ + up_pwm_servo_deinit(); + + /* note - someone else is responsible for restoring the GPIO config */ + + /* tell the dtor that we are exiting */ + _task = -1; + _exit(0); +} + +int +FMUServo::ioctl(struct file *filp, int cmd, unsigned long arg) +{ + int ret = OK; + + switch (cmd) { + case PWM_SERVO_ARM: + up_pwm_servo_arm(true); + break; + + case PWM_SERVO_DISARM: + up_pwm_servo_arm(false); + break; + + case PWM_SERVO_SET(2): + case PWM_SERVO_SET(3): + if (_mode != MODE_4PWM) { + ret = -EINVAL; + break; + } + /* FALLTHROUGH */ + case PWM_SERVO_SET(0): + case PWM_SERVO_SET(1): + if (arg < 2100) { + int channel = cmd - PWM_SERVO_SET(0); + up_pwm_servo_set(channel, arg); + } else { + ret = -EINVAL; + } + break; + + case PWM_SERVO_GET(2): + case PWM_SERVO_GET(3): + if (_mode != MODE_4PWM) { + ret = -EINVAL; + break; + } + /* FALLTHROUGH */ + case PWM_SERVO_GET(0): + case PWM_SERVO_GET(1): { + int channel = cmd - PWM_SERVO_SET(0); + *(servo_position_t *)arg = up_pwm_servo_get(channel); + break; + } + + default: + ret = -ENOTTY; + break; + } + return ret; +} + +namespace { + +enum PortMode { + PORT_FULL_GPIO, + PORT_FULL_SERIAL, + PORT_FULL_PWM, + PORT_GPIO_AND_SERIAL, + PORT_PWM_AND_SERIAL, + PORT_PWM_AND_GPIO, + PORT_MODE_UNSET +}; + +PortMode g_port_mode; + +int +fmu_new_mode(PortMode new_mode) +{ + int fd; + int ret = OK; + uint32_t gpio_bits; + FMUServo::Mode servo_mode; + + /* get hold of the GPIO configuration descriptor */ + fd = open(GPIO_DEVICE_PATH, 0); + if (fd < 0) + return -errno; + + /* start by tearing down any existing state and revert to all-GPIO-inputs */ + if (g_servo != nullptr) { + delete g_servo; + g_servo = nullptr; + } + + /* reset to all-inputs */ + ioctl(fd, GPIO_RESET, 0); + + gpio_bits = 0; + servo_mode = FMUServo::MODE_NONE; + + switch (new_mode) { + case PORT_FULL_GPIO: + case PORT_MODE_UNSET: + /* nothing more to do here */ + break; + + case PORT_FULL_SERIAL: + /* set all multi-GPIOs to serial mode */ + gpio_bits = GPIO_MULTI_1 | GPIO_MULTI_2 | GPIO_MULTI_3 | GPIO_MULTI_4; + break; + + case PORT_FULL_PWM: + /* select 4-pin PWM mode */ + servo_mode = FMUServo::MODE_4PWM; + break; + + case PORT_GPIO_AND_SERIAL: + /* set RX/TX multi-GPIOs to serial mode */ + gpio_bits = GPIO_MULTI_3 | GPIO_MULTI_4; + break; + + case PORT_PWM_AND_SERIAL: + /* select 2-pin PWM mode */ + servo_mode = FMUServo::MODE_2PWM; + /* set RX/TX multi-GPIOs to serial mode */ + gpio_bits = GPIO_MULTI_3 | GPIO_MULTI_4; + break; + + case PORT_PWM_AND_GPIO: + /* select 2-pin PWM mode */ + servo_mode = FMUServo::MODE_2PWM; + break; + } + + /* adjust GPIO config for serial mode(s) */ + if (gpio_bits != 0) + ioctl(fd, GPIO_SET_ALT_1, gpio_bits); + close(fd); + + /* create new PWM driver if required */ + if (servo_mode != FMUServo::MODE_NONE) { + g_servo = new FMUServo(servo_mode); + if (g_servo == nullptr) { + ret = -ENOMEM; + } else { + ret = g_servo->init(); + if (ret != OK) { + delete g_servo; + g_servo = nullptr; + } + } + } + + return ret; +} + +} // namespace + +extern "C" int fmu_main(int argc, char *argv[]); + +int +fmu_main(int argc, char *argv[]) +{ + PortMode new_mode = PORT_MODE_UNSET; + + /* + * Mode switches. + * + * XXX use getopt + */ + if (!strcmp(argv[1], "mode_gpio")) { + new_mode = PORT_FULL_GPIO; + } else if (!strcmp(argv[1], "mode_serial")) { + new_mode = PORT_FULL_SERIAL; + } else if (!strcmp(argv[1], "mode_pwm")) { + new_mode = PORT_FULL_PWM; + } else if (!strcmp(argv[1], "mode_gpio_serial")) { + new_mode = PORT_GPIO_AND_SERIAL; + } else if (!strcmp(argv[1], "mode_pwm_serial")) { + new_mode = PORT_PWM_AND_SERIAL; + } else if (!strcmp(argv[1], "mode_pwm_gpio")) { + new_mode = PORT_PWM_AND_GPIO; + } + + /* was a new mode set? */ + if (new_mode != PORT_MODE_UNSET) { + + /* yes but it's the same mode */ + if (new_mode == g_port_mode) + return OK; + + /* switch modes */ + return fmu_new_mode(new_mode); + } + + /* test, etc. here */ + + fprintf(stderr, "FMU: unrecognised command, try:\n"); + fprintf(stderr, " mode_gpio, mode_serial, mode_pwm, mode_gpio_serial, mode_pwm_serial, mode_pwm_gpio\n"); + return -EINVAL; +} diff --git a/apps/px4/px4io/driver/.context b/apps/px4/px4io/driver/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/px4/px4io/driver/Makefile b/apps/px4/px4io/driver/Makefile new file mode 100644 index 0000000000..cbd9425463 --- /dev/null +++ b/apps/px4/px4io/driver/Makefile @@ -0,0 +1,42 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Interface driver for the PX4IO board. +# + +APPNAME = px4io +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +include $(APPDIR)/mk/app.mk diff --git a/apps/px4/px4io/driver/px4io.cpp b/apps/px4/px4io/driver/px4io.cpp new file mode 100644 index 0000000000..c3f14e3a4b --- /dev/null +++ b/apps/px4/px4io/driver/px4io.cpp @@ -0,0 +1,560 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Driver for the PX4IO board. + * + * PX4IO is connected via serial (or possibly some other interface at a later + * point). + * + * XXX current design is racy as all hell; need a locking strategy. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include "../protocol.h" +#include "uploader.h" + +class PX4IO; + + +namespace +{ + +/* oddly, ERROR is not defined for c++ */ +#ifdef ERROR +# undef ERROR +#endif +const int ERROR = -1; + +PX4IO *g_dev; + +} + + +class PX4IO_RC : public device::CDev +{ +public: + PX4IO_RC(); + ~PX4IO_RC(); + + virtual int init(); + virtual ssize_t read(struct file *filp, char *buffer, size_t buflen); + + friend class PX4IO; +protected: + void set_channels(unsigned count, const servo_position_t *data); + +private: + int _publication; + struct rc_input_values _input; +}; + +/* XXX this may conflict with the onboard PPM input */ +PX4IO_RC::PX4IO_RC() : + CDev("px4io_rc", RC_INPUT_DEVICE_PATH), + _publication(-1) +{ + for (unsigned i = 0; i < RC_INPUT_MAX_CHANNELS; i++) { + _input.values[i] = 0; + } + _input.channel_count = 0; +} + +PX4IO_RC::~PX4IO_RC() +{ + if (_publication != -1) + ::close(_publication); +} + +int +PX4IO_RC::init() +{ + int ret; + + ret = CDev::init(); + + /* advertise ourselves as the RC input controller */ + if (ret == OK) { + _publication = orb_advertise(ORB_ID(input_rc), &_input); + if (_publication < 0) + ret = -errno; + } + + return ret; +} + +ssize_t +PX4IO_RC::read(struct file *filp, char *buffer, size_t buflen) +{ + unsigned channels = buflen / sizeof(rc_input_t); + rc_input_t *pdata = (rc_input_t *)buffer; + unsigned i; + + if (channels > PX4IO_INPUT_CHANNELS) + return -EIO; + + lock(); + for (i = 0; i < channels; i++) + pdata[i] = _input.values[i]; + unlock(); + + return i * sizeof(servo_position_t); +} + +void +PX4IO_RC::set_channels(unsigned count, const servo_position_t *data) +{ + + ASSERT(count <= PX4IO_INPUT_CHANNELS); + + /* convert incoming servo position values into 0-100 range */ + lock(); + for (unsigned i = 0; i < count; i++) { + rc_input_t chn; + + if (data[i] < 1000) { + chn = 0; + } else if (data[i] > 2000) { + chn = 100; + } else { + chn = (data[i] - 1000) / 10; + } + + _input.values[i] = chn; + } + _input.channel_count = count; + unlock(); + + /* publish to anyone that might be listening */ + if (_publication != -1) + orb_publish(ORB_ID(input_rc), _publication, &_input); + +} + +class PX4IO : public device::CDev +{ +public: + PX4IO(); + ~PX4IO(); + + virtual int init(); + + virtual ssize_t write(struct file *filp, const char *buffer, size_t buflen); + virtual int ioctl(struct file *filp, int cmd, unsigned long arg); + +private: + int _fd; + int _task; + PX4IO_RC *_rc; + + /** command to be sent to IO */ + struct px4io_command _next_command; + + /** RC channel input from IO */ + servo_position_t _rc_channel[PX4IO_INPUT_CHANNELS]; + int _rc_channel_count; + + volatile bool _armed; + volatile bool _task_should_exit; + + bool _send_needed; + + hx_stream_t _io_stream; + + static void task_main_trampoline(int argc, char *argv[]); + void task_main(); + void io_recv(); + + static void rx_callback_trampoline(void *arg, const void *buffer, size_t bytes_received); + void rx_callback(const uint8_t *buffer, size_t bytes_received); + + void io_send(); +}; + +PX4IO::PX4IO() : + CDev("px4io", "/dev/px4io"), + _fd(-1), + _task(-1), + _rc(new PX4IO_RC), + _rc_channel_count(0), + _armed(false), + _task_should_exit(false), + _send_needed(false), + _io_stream(nullptr) +{ + /* set up the command we will use */ + _next_command.f2i_magic = F2I_MAGIC; + + /* we need this potentially before it could be set in px4io_main */ + g_dev = this; + + _debug_enabled = true; +} + +PX4IO::~PX4IO() +{ + if (_rc != nullptr) + delete _rc; + if (_task != -1) { + /* task should wake up every 100ms or so at least */ + _task_should_exit = true; + + unsigned i = 0; + do { + /* wait 20ms */ + usleep(20000); + + /* if we have given up, kill it */ + if (++i > 10) { + task_delete(_task); + break; + } + + } while (_task != -1); + } + + g_dev = nullptr; +} + +int +PX4IO::init() +{ + int ret; + + ASSERT(_task == -1); + + /* XXX send a who-are-you request */ + + /* XXX verify firmware/protocol version */ + + /* do regular cdev init */ + ret = CDev::init(); + if (ret != OK) + return ret; + + /* start the IO interface task */ + _task = task_create("px4io", SCHED_PRIORITY_DEFAULT, 1024, (main_t)&PX4IO::task_main_trampoline, nullptr); + if (_task < 0) { + debug("task start failed: %d", errno); + return -errno; + } + + return OK; +} + +void +PX4IO::task_main_trampoline(int argc, char *argv[]) +{ + g_dev->task_main(); +} + +void +PX4IO::task_main() +{ + ASSERT(_fd == -1); + + log("ready"); + + /* open the serial port */ + _fd = ::open("/dev/ttyS2", O_RDWR | O_NONBLOCK); + if (_fd < 0) { + debug("failed to open serial port for IO: %d", errno); + _task = -1; + _exit(errno); + } + + /* protocol stream */ + _io_stream = hx_stream_init(_fd, &PX4IO::rx_callback_trampoline, this); + + perf_counter_t pc_tx_bytes = perf_alloc(PC_COUNT, "PX4IO frames transmitted"); + perf_counter_t pc_rx_bytes = perf_alloc(PC_COUNT, "PX4IO frames received"); + perf_counter_t pc_rx_errors = perf_alloc(PC_COUNT, "PX4IO receive errors"); + hx_stream_set_counters(_io_stream, pc_tx_bytes, pc_rx_bytes, pc_rx_errors); + + /* poll descriptor(s) */ + struct pollfd fds[1]; + fds[0].fd = _fd; + fds[0].events = POLLIN; + + /* loop handling received serial bytes */ + while (!_task_should_exit) { + + /* sleep waiting for data, but no more than 100ms */ + int ret = ::poll(&fds[0], 1, 100); + + /* this would be bad... */ + if (ret < 0) { + log("poll error %d", errno); + usleep(1000000); + continue; + } + + /* if we timed out waiting, we should send an update */ + if (ret == 0) + _send_needed = true; + + /* if we have new data from IO, go handle it */ + if ((ret > 0) && (fds[0].revents & POLLIN)) + io_recv(); + + /* send an update to IO if required */ + if (_send_needed) { + _send_needed = false; + io_send(); + } + } + if (_io_stream != nullptr) + hx_stream_free(_io_stream); + ::close(_fd); + + /* tell the dtor that we are exiting */ + _task = -1; + _exit(0); +} + +void +PX4IO::io_recv() +{ + uint8_t c; + + /* handle bytes from IO */ + while (::read(_fd, &c, 1) == 1) + hx_stream_rx(_io_stream, c); +} + +void +PX4IO::rx_callback_trampoline(void *arg, const void *buffer, size_t bytes_received) +{ + g_dev->rx_callback((const uint8_t *)buffer, bytes_received); +} + +void +PX4IO::rx_callback(const uint8_t *buffer, size_t bytes_received) +{ + const struct px4io_report *rep = (const struct px4io_report *)buffer; + + /* sanity-check the received frame size */ + if (bytes_received != sizeof(struct px4io_report)) + return; + + lock(); + + /* pass RC input data to the driver */ + if (_rc != nullptr) + _rc->set_channels(rep->channel_count, &rep->rc_channel[0]); + _armed = rep->armed; + + /* send an update frame */ + _send_needed = true; + + unlock(); + +} + +void +PX4IO::io_send() +{ + lock(); + + /* send packet to IO while we're guaranteed it won't change */ + hx_stream_send(_io_stream, &_next_command, sizeof(_next_command)); + + unlock(); +} + +ssize_t +PX4IO::write(struct file *filp, const char *buffer, size_t len) +{ + unsigned channels = len / sizeof(servo_position_t); + servo_position_t *pdata = (servo_position_t *)buffer; + unsigned i; + + if (channels > PX4IO_OUTPUT_CHANNELS) + return -EIO; + + lock(); + for (i = 0; i < channels; i++) + _next_command.servo_command[i] = pdata[i]; + unlock(); + + return i * sizeof(servo_position_t); +} + +int +PX4IO::ioctl(struct file *filep, int cmd, unsigned long arg) +{ + int ret = -ENOTTY; + + lock(); + + /* regular ioctl? */ + switch (cmd) { + case PWM_SERVO_ARM: + _next_command.arm_ok = true; + ret = 0; + break; + + case PWM_SERVO_DISARM: + _next_command.arm_ok = false; + ret = 0; + break; + + default: + /* channel set? */ + if ((cmd >= PWM_SERVO_SET(0)) && (cmd < PWM_SERVO_SET(PX4IO_OUTPUT_CHANNELS))) { + /* XXX sanity-check value? */ + _next_command.servo_command[cmd - PWM_SERVO_SET(0)] = arg; + ret = 0; + break; + } + + /* channel get? */ + if ((cmd >= PWM_SERVO_GET(0)) && (cmd < PWM_SERVO_GET(PX4IO_INPUT_CHANNELS))) { + int channel = cmd - PWM_SERVO_GET(0); + + /* currently no data for this channel */ + if (channel >= _rc_channel_count) { + ret = -ERANGE; + break; + } + + *(servo_position_t *)arg = _rc_channel[channel]; + ret = 0; + break; + } + + /* not a recognised value */ + ret = -ENOTTY; + } + unlock(); + + return ret; +} + +extern "C" __EXPORT int px4io_main(int argc, char *argv[]); + +int +px4io_main(int argc, char *argv[]) +{ + if (!strcmp(argv[1], "start")) { + + if (g_dev != nullptr) { + fprintf(stderr, "PX4IO: already loaded\n"); + return -EBUSY; + } + + /* create the driver - it will set g_dev */ + (void)new PX4IO; + + if (g_dev == nullptr) { + fprintf(stderr, "PX4IO: driver alloc failed\n"); + return -ENOMEM; + } + + if (OK != g_dev->init()) { + fprintf(stderr, "PX4IO: driver init failed\n"); + delete g_dev; + return -EIO; + } + + return OK; + } + + if (!strcmp(argv[1], "update")) { + PX4IO_Uploader *up; + const char *fn[3]; + + /* work out what we're uploading... */ + if (argc > 2) { + fn[0] = argv[2]; + fn[1] = nullptr; + } else { + fn[0] = "/fs/microsd/px4io.bin"; + fn[1] = "/etc/px4io.bin"; + fn[2] = nullptr; + } + + up = new PX4IO_Uploader; + int ret = up->upload(&fn[0]); + delete up; + + switch (ret) { + case OK: + break; + case -ENOENT: + fprintf(stderr, "PX4IO firmware file '%s' not found\n", fn); + break; + case -EEXIST: + case -EIO: + fprintf(stderr, "error updating PX4IO - check that bootloader mode is enabled\n"); + break; + case -EINVAL: + fprintf(stderr, "verify failed - retry the update\n"); + break; + case -ETIMEDOUT: + fprintf(stderr, "timed out waiting for bootloader - power-cycle and try again\n"); + default: + fprintf(stderr, "unexpected error %d\n", ret); + break; + } + return ret; + } + + + + printf("need a verb, only support 'start'\n"); + return ERROR; +} diff --git a/apps/px4/px4io/driver/uploader.cpp b/apps/px4/px4io/driver/uploader.cpp new file mode 100644 index 0000000000..7d6a9e1714 --- /dev/null +++ b/apps/px4/px4io/driver/uploader.cpp @@ -0,0 +1,387 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Firmware uploader for PX4IO + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uploader.h" + +PX4IO_Uploader::PX4IO_Uploader() : + _io_fd(-1), + _fw_fd(-1) +{ +} + +PX4IO_Uploader::~PX4IO_Uploader() +{ +} + +int +PX4IO_Uploader::upload(const char *filenames[]) +{ + int ret; + + _io_fd = open("/dev/ttyS2", O_RDWR); + if (_io_fd < 0) { + log("could not open interface"); + return -errno; + } + + /* look for the bootloader */ + ret = sync(); + if (ret != OK) { + /* this is immediately fatal */ + log("bootloader not responding"); + return -EIO; + } + + for (unsigned i = 0; filenames[i] != nullptr; i++) { + _fw_fd = open(filenames[i], O_RDONLY); + + if (_fw_fd < 0) { + log("failed to open %s", filenames[i]); + continue; + } + log("using firmware from %s", filenames[i]); + break; + } + if (_fw_fd == -1) + return -ENOENT; + + /* do the usual program thing - allow for failure */ + for (unsigned retries = 0; retries < 1; retries++) { + if (retries > 0) { + log("retrying update..."); + ret = sync(); + if (ret != OK) { + /* this is immediately fatal */ + log("bootloader not responding"); + return -EIO; + } + } + + ret = erase(); + if (ret != OK) { + log("erase failed"); + continue; + } + ret = program(); + if (ret != OK) { + log("program failed"); + continue; + } + ret = verify(); + if (ret != OK) { + log("verify failed"); + continue; + } + ret = reboot(); + if (ret != OK) { + log("reboot failed"); + return ret; + } + log("update complete"); + + ret = OK; + break; + } + + close(_fw_fd); + return ret; +} + +int +PX4IO_Uploader::recv(uint8_t &c, unsigned timeout) +{ + struct pollfd fds[1]; + + fds[0].fd = _io_fd; + fds[0].events = POLLIN; + + /* wait 100 ms for a character */ + int ret = ::poll(&fds[0], 1, timeout); + if (ret < 1) { + //log("poll timeout %d", ret); + return -ETIMEDOUT; + } + + read(_io_fd, &c, 1); + //log("recv 0x%02x", c); + return OK; +} + +int +PX4IO_Uploader::recv(uint8_t *p, unsigned count) +{ + while (count--) { + int ret = recv(*p++); + if (ret != OK) + return ret; + } + return OK; +} + +void +PX4IO_Uploader::drain() +{ + uint8_t c; + int ret; + + do { + ret = recv(c, 10); + //log("discard 0x%02x", c); + } while(ret == OK); +} + +int +PX4IO_Uploader::send(uint8_t c) +{ + //log("send 0x%02x", c); + if (write(_io_fd, &c, 1) != 1) + return -errno; + return OK; +} + +int +PX4IO_Uploader::send(uint8_t *p, unsigned count) +{ + while (count--) { + int ret = send(*p++); + if (ret != OK) + return ret; + } + return OK; +} + +int +PX4IO_Uploader::get_sync(unsigned timeout) +{ + uint8_t c[2]; + int ret; + + ret = recv(c[0], timeout); + if (ret != OK) + return ret; + ret = recv(c[1], timeout); + if (ret != OK) + return ret; + if ((c[0] != PROTO_INSYNC) || (c[1] != PROTO_OK)) { + log("bad sync 0x%02x,0x%02x", c[0], c[1]); + return -EIO; + } + return OK; +} + +int +PX4IO_Uploader::sync() +{ + drain(); + /* complete any pending program operation */ + for (unsigned i = 0; i < (PROG_MULTI_MAX + 6); i++) + send(0); + send(PROTO_GET_SYNC); + send(PROTO_EOC); + return get_sync(); +} + +int +PX4IO_Uploader::get_info(int param, uint32_t &val) +{ + int ret; + + send(PROTO_GET_DEVICE); + send(param); + send(PROTO_EOC); + + ret = recv((uint8_t *)&val, sizeof(val)); + if (ret != OK) + return ret; + return get_sync(); +} + +int +PX4IO_Uploader::erase() +{ + log("erase..."); + send(PROTO_CHIP_ERASE); + send(PROTO_EOC); + return get_sync(10000); /* allow 10s timeout */ +} + +int +PX4IO_Uploader::program() +{ + uint8_t file_buf[PROG_MULTI_MAX]; + ssize_t count; + int ret; + + log("program..."); + lseek(_fw_fd, 0, SEEK_SET); + + while (true) { + /* get more bytes to program */ + //log(" %d", (int)lseek(_fw_fd, 0, SEEK_CUR)); + count = read(_fw_fd, file_buf, sizeof(file_buf)); + if (count == 0) + return OK; + if (count < 0) + return -errno; + ASSERT((count % 4) == 0); + + send(PROTO_PROG_MULTI); + send(count); + send(&file_buf[0], count); + send(PROTO_EOC); + + ret = get_sync(1000); + if (ret != OK) + return ret; + } +} + +int +PX4IO_Uploader::verify() +{ + uint8_t file_buf[PROG_MULTI_MAX]; + ssize_t count; + int ret; + + log("verify..."); + lseek(_fw_fd, 0, SEEK_SET); + + send(PROTO_CHIP_VERIFY); + send(PROTO_EOC); + ret = get_sync(); + if (ret != OK) + return ret; + + while (true) { + /* get more bytes to verify */ + int base = (int)lseek(_fw_fd, 0, SEEK_CUR); + count = read(_fw_fd, file_buf, sizeof(file_buf)); + if (count == 0) + break; + if (count < 0) + return -errno; + ASSERT((count % 4) == 0); + + send(PROTO_READ_MULTI); + send(count); + send(PROTO_EOC); + for (ssize_t i = 0; i < count; i++) { + uint8_t c; + + ret = recv(c); + if (ret != OK) { + log("%d: got %d waiting for bytes", ret); + return ret; + } + + if (c != file_buf[i]) { + log("%d: got 0x%02x expected 0x%02x", base + i, c, file_buf[i]); + return -EINVAL; + } + } + ret = get_sync(); + if (ret != OK) { + log("timeout waiting for post-verify sync"); + return ret; + } + } + return OK; +} + +int +PX4IO_Uploader::reboot() +{ + send(PROTO_REBOOT); + send(PROTO_EOC); + + return OK; +} + +int +PX4IO_Uploader::compare(bool &identical) +{ + uint32_t file_vectors[15]; + uint32_t fw_vectors[15]; + int ret; + + lseek(_fw_fd, 0, SEEK_SET); + ret = read(_fw_fd, &file_vectors[0], sizeof(file_vectors)); + + send(PROTO_CHIP_VERIFY); + send(PROTO_EOC); + ret = get_sync(); + if (ret != OK) + return ret; + + send(PROTO_READ_MULTI); + send(sizeof(fw_vectors)); + send(PROTO_EOC); + ret = recv((uint8_t *)&fw_vectors[0], sizeof(fw_vectors)); + if (ret != OK) + return ret; + + identical = (memcmp(&file_vectors[0], &fw_vectors[0], sizeof(file_vectors))) ? true : false; + + return OK; +} + +void +PX4IO_Uploader::log(const char *fmt, ...) +{ + va_list ap; + + printf("[PX4IO] "); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); + fflush(stdout); +} \ No newline at end of file diff --git a/apps/px4/px4io/driver/uploader.h b/apps/px4/px4io/driver/uploader.h new file mode 100644 index 0000000000..8d41992f85 --- /dev/null +++ b/apps/px4/px4io/driver/uploader.h @@ -0,0 +1,99 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Firmware uploader for PX4IO + */ + +#ifndef _PX4IO_UPLOADER_H +#define _PX4IO_UPLOADER_H value + +#include +#include + + +class PX4IO_Uploader +{ +public: + PX4IO_Uploader(); + ~PX4IO_Uploader(); + + int upload(const char *filenames[]); + +private: + enum { + + PROTO_NOP = 0x00, + PROTO_OK = 0x10, + PROTO_FAILED = 0x11, + PROTO_INSYNC = 0x12, + PROTO_EOC = 0x20, + PROTO_GET_SYNC = 0x21, + PROTO_GET_DEVICE = 0x22, + PROTO_CHIP_ERASE = 0x23, + PROTO_CHIP_VERIFY = 0x24, + PROTO_PROG_MULTI = 0x27, + PROTO_READ_MULTI = 0x28, + PROTO_REBOOT = 0x30, + + INFO_BL_REV = 1, /**< bootloader protocol revision */ + BL_REV = 2, /**< supported bootloader protocol */ + INFO_BOARD_ID = 2, /**< board type */ + INFO_BOARD_REV = 3, /**< board revision */ + INFO_FLASH_SIZE = 4, /**< max firmware size in bytes */ + + PROG_MULTI_MAX = 60, /**< protocol max is 255, must be multiple of 4 */ + READ_MULTI_MAX = 60, /**< protocol max is 255, something overflows with >= 64 */ + }; + + int _io_fd; + int _fw_fd; + + void log(const char *fmt, ...); + + int recv(uint8_t &c, unsigned timeout = 1000); + int recv(uint8_t *p, unsigned count); + void drain(); + int send(uint8_t c); + int send(uint8_t *p, unsigned count); + int get_sync(unsigned timeout = 1000); + int sync(); + int get_info(int param, uint32_t &val); + int erase(); + int program(); + int verify(); + int reboot(); + int compare(bool &identical); +}; + +#endif \ No newline at end of file diff --git a/apps/px4/px4io/protocol.h b/apps/px4/px4io/protocol.h new file mode 100644 index 0000000000..c186c5b862 --- /dev/null +++ b/apps/px4/px4io/protocol.h @@ -0,0 +1,73 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file PX4FMU <-> PX4IO messaging protocol. + * + * This initial version of the protocol is very simple; each side transmits a + * complete update with each frame. This avoids the sending of many small + * messages and the corresponding complexity involved. + */ + +/* + * XXX MUST BE KEPT IN SYNC WITH THE VERSION IN PX4FMU UNTIL + * TREES ARE MERGED. + */ + +#define PX4IO_OUTPUT_CHANNELS 8 +#define PX4IO_INPUT_CHANNELS 12 +#define PX4IO_RELAY_CHANNELS 2 + +#pragma pack(push,1) + +/* command from FMU to IO */ +struct px4io_command { + uint16_t f2i_magic; +#define F2I_MAGIC 0x636d + + uint16_t servo_command[PX4IO_OUTPUT_CHANNELS]; + bool relay_state[PX4IO_RELAY_CHANNELS]; + bool arm_ok; +}; + +/* report from IO to FMU */ +struct px4io_report { + uint16_t i2f_magic; +#define I2F_MAGIC 0x7570 + + uint16_t rc_channel[PX4IO_INPUT_CHANNELS]; + bool armed; + uint8_t channel_count; +} __attribute__((packed)); + +#pragma pack(pop) diff --git a/apps/px4/sensors_bringup/.context b/apps/px4/sensors_bringup/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/px4/sensors_bringup/Makefile b/apps/px4/sensors_bringup/Makefile new file mode 100644 index 0000000000..8867653a01 --- /dev/null +++ b/apps/px4/sensors_bringup/Makefile @@ -0,0 +1,42 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Makefile to build the sensor bringup tests +# + +APPNAME = sensors_bringup +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +include $(APPDIR)/mk/app.mk diff --git a/apps/px4/sensors_bringup/bma180.c b/apps/px4/sensors_bringup/bma180.c new file mode 100644 index 0000000000..6c4b9d4834 --- /dev/null +++ b/apps/px4/sensors_bringup/bma180.c @@ -0,0 +1,209 @@ +/* + * Operations for the Bosch BMA180 3D Accelerometer + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "sensors.h" + +#define DIR_READ (1<<7) +#define DIR_WRITE (0<<7) +#define ADDR_INCREMENT (1<<6) + +#define ADDR_CHIP_ID 0x00 +#define CHIP_ID 0x03 +#define ADDR_VERSION 0x01 + +#define ADDR_CTRL_REG0 0x0D +#define ADDR_CTRL_REG1 0x0E +#define ADDR_CTRL_REG2 0x0F +#define ADDR_BWTCS 0x20 +#define ADDR_CTRL_REG3 0x21 +#define ADDR_CTRL_REG4 0x22 +#define ADDR_OLSB1 0x35 + +#define ADDR_ACC_X_LSB 0x02 +#define ADDR_ACC_Z_MSB 0x07 +#define ADDR_TEMPERATURE 0x08 + +#define ADDR_STATUS_REG1 0x09 +#define ADDR_STATUS_REG2 0x0A +#define ADDR_STATUS_REG3 0x0B +#define ADDR_STATUS_REG4 0x0C + +#define ADDR_RESET 0x10 +#define SOFT_RESET 0xB6 + +#define ADDR_DIS_I2C 0x27 + +#define REG0_WRITE_ENABLE 0x10 + +#define BWTCS_LP_10HZ (0<<4) +#define BWTCS_LP_20HZ (1<<4) +#define BWTCS_LP_40HZ (2<<4) +#define BWTCS_LP_75HZ (3<<4) +#define BWTCS_LP_150HZ (4<<4) +#define BWTCS_LP_300HZ (5<<4) +#define BWTCS_LP_600HZ (6<<4) +#define BWTCS_LP_1200HZ (7<<4) + +#define RANGE_1G (0<<1) +#define RANGE_1_5G (1<<1) +#define RANGE_2G (2<<1) +#define RANGE_3G (3<<1) +#define RANGE_4G (4<<1) +#define RANGE_8G (5<<1) +#define RANGE_16G (6<<1) + +#define RANGEMASK 0x0E +#define BWMASK 0xF0 + + +static void +write_reg(struct spi_dev_s *spi, uint8_t address, uint8_t data) +{ + uint8_t cmd[2] = { address | DIR_WRITE, data }; + + SPI_SELECT(spi, PX4_SPIDEV_ACCEL, true); + SPI_SNDBLOCK(spi, &cmd, sizeof(cmd)); + SPI_SELECT(spi, PX4_SPIDEV_ACCEL, false); +} + +static uint8_t +read_reg(struct spi_dev_s *spi, uint8_t address) +{ + uint8_t cmd[2] = {address | DIR_READ, 0}; + uint8_t data[2]; + + SPI_SELECT(spi, PX4_SPIDEV_ACCEL, true); + SPI_EXCHANGE(spi, cmd, data, sizeof(cmd)); + SPI_SELECT(spi, PX4_SPIDEV_ACCEL, false); + + return data[1]; +} + +int +bma180_test_configure(struct spi_dev_s *spi) +{ + uint8_t id; + + id = read_reg(spi, ADDR_CHIP_ID); + uint8_t version = read_reg(spi, 0x01); + + if (id == CHIP_ID) + { + message("BMA180 SUCCESS: 0x%02x, version: %d\n", id, version); + } + else + { + message("BMA180 FAIL: 0x%02x\n", id); + } + //message("got id 0x%02x, expected ID 0x03\n", id); + + write_reg(spi, ADDR_RESET, SOFT_RESET); // page 48 + usleep(12000); // wait 10 ms, see page 49 + + // Configuring the BMA180 + + /* enable writing to chip config */ + uint8_t ctrl0 = read_reg(spi, ADDR_CTRL_REG0); + ctrl0 |= REG0_WRITE_ENABLE; + write_reg(spi, ADDR_CTRL_REG0, ctrl0); + + uint8_t disi2c = read_reg(spi, ADDR_DIS_I2C); // read + disi2c |= 0x01; // set bit0 to 1, SPI only + write_reg(spi, ADDR_DIS_I2C, disi2c); // Set spi, disable i2c, page 31 + + /* set bandwidth */ + uint8_t bwtcs = read_reg(spi, ADDR_BWTCS); + printf("bwtcs: %d\n", bwtcs); + bwtcs &= (~BWMASK); + bwtcs |= (BWTCS_LP_600HZ);// & BWMASK); + write_reg(spi, ADDR_BWTCS, bwtcs); + + /* set range */ + uint8_t olsb1 = read_reg(spi, ADDR_OLSB1); + printf("olsb1: %d\n", olsb1); + olsb1 &= (~RANGEMASK); + olsb1 |= (RANGE_4G);// & RANGEMASK); + write_reg(spi, ADDR_OLSB1, olsb1); + +// uint8_t reg3 = read_reg(spi, ADDR_CTRL_REG3); +// //reg3 &= 0xFD; // REset bit 1 enable interrupt +// //reg3 |= 0x02; // enable +// write_reg(spi, ADDR_CTRL_REG3, reg3); // + + /* block writing to chip config */ + ctrl0 = read_reg(spi, ADDR_CTRL_REG0); + ctrl0 &= (~REG0_WRITE_ENABLE); + printf("ctrl0: %d\n", ctrl0); + write_reg(spi, ADDR_CTRL_REG0, ctrl0); + + return 0; +} + +int +bma180_test_read(struct spi_dev_s *spi) +{ + + + + struct { /* status register and data as read back from the device */ + uint8_t cmd; + int16_t x; + int16_t y; + int16_t z; + uint8_t temp; + } __attribute__((packed)) report; + + report.x = 0; + report.y = 0; + report.z = 0; + +// uint8_t temp; +// uint8_t status1; +// uint8_t status2; +// uint8_t status3; +// uint8_t status4; + + report.cmd = ADDR_ACC_X_LSB | DIR_READ | ADDR_INCREMENT; + + //SPI_LOCK(spi, true); + //SPI_SELECT(spi, PX4_SPIDEV_ACCEL, true); + //SPI_EXCHANGE(spi, &report, &report, sizeof(report)); + //SPI_SELECT(spi, PX4_SPIDEV_ACCEL, false); + //SPI_LOCK(spi, false); + + report.x = read_reg(spi, ADDR_ACC_X_LSB); + report.x |= (read_reg(spi, ADDR_ACC_X_LSB+1) << 8); + report.y = read_reg(spi, ADDR_ACC_X_LSB+2); + report.y |= (read_reg(spi, ADDR_ACC_X_LSB+3) << 8); + report.z = read_reg(spi, ADDR_ACC_X_LSB+4); + report.z |= (read_reg(spi, ADDR_ACC_X_LSB+5) << 8); + report.temp = read_reg(spi, ADDR_ACC_X_LSB+6); + + // Collect status and remove two top bits + + uint8_t new_data = (report.x & 0x01) + (report.x & 0x01) + (report.x & 0x01); + report.x = (report.x >> 2); + report.y = (report.y >> 2); + report.z = (report.z >> 2); + + message("ACC: x: %d\ty: %d\tz: %d\ttemp: %d new: %d\n", report.x, report.y, report.z, report.temp, new_data); + usleep(2000); + + return 0; +} diff --git a/apps/px4/sensors_bringup/l3gd20.c b/apps/px4/sensors_bringup/l3gd20.c new file mode 100644 index 0000000000..5bdc10e06e --- /dev/null +++ b/apps/px4/sensors_bringup/l3gd20.c @@ -0,0 +1,184 @@ +/* + * Operations for the l3g4200 + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "sensors.h" + +#define DIR_READ (1<<7) +#define DIR_WRITE (0<<7) +#define ADDR_INCREMENT (1<<6) + +#define ADDR_WHO_AM_I 0x0f +#define WHO_I_AM 0xd4 + +#define ADDR_CTRL_REG1 0x20 /* sample rate constants are in the public header */ +#define REG1_POWER_NORMAL (1<<3) +#define REG1_Z_ENABLE (1<<2) +#define REG1_Y_ENABLE (1<<1) +#define REG1_X_ENABLE (1<<0) + +#define ADDR_CTRL_REG2 0x21 +/* high-pass filter - usefulness TBD */ + +#define ADDR_CTRL_REG3 0x22 + +#define ADDR_CTRL_REG4 0x23 +#define REG4_BDU (1<<7) +#define REG4_BIG_ENDIAN (1<<6) +#define REG4_SPI_3WIRE (1<<0) + +#define ADDR_CTRL_REG5 0x24 +#define REG5_BOOT (1<<7) +#define REG5_FIFO_EN (1<<6) +#define REG5_HIGHPASS_ENABLE (1<<4) + +#define ADDR_REFERENCE 0x25 +#define ADDR_TEMPERATURE 0x26 + +#define ADDR_STATUS_REG 0x27 +#define STATUS_ZYXOR (1<<7) +#define SATAUS_ZOR (1<<6) +#define STATUS_YOR (1<<5) +#define STATUS_XOR (1<<4) +#define STATUS_ZYXDA (1<<3) +#define STATUS_ZDA (1<<2) +#define STATUS_YDA (1<<1) +#define STATUS_XDA (1<<0) + +#define ADDR_OUT_X 0x28 /* 16 bits */ +#define ADDR_OUT_Y 0x2A /* 16 bits */ +#define ADDR_OUT_Z 0x2C /* 16 bits */ + +#define ADDR_FIFO_CTRL 0x2e +#define FIFO_MODE_BYPASS (0<<5) +#define FIFO_MODE_FIFO (1<<5) +#define FIFO_MODE_STREAM (2<<5) +#define FIFO_MODE_STREAM_TO_FIFO (3<<5) +#define FIFO_MODE_BYPASS_TO_STREAM (4<<5) +#define FIFO_THRESHOLD_MASK 0x1f + +#define ADDR_FIFO_SRC 0x2f +#define FIFO_THREHSHOLD_OVER (1<<7) +#define FIFO_OVERRUN (1<<6) +#define FIFO_EMPTY (1<<5) + +#define L3G4200_RATE_100Hz ((0<<6) | (0<<4)) +#define L3G4200_RATE_200Hz ((1<<6) | (0<<4)) +#define L3G4200_RATE_400Hz ((2<<6) | (1<<4)) +#define L3G4200_RATE_800Hz ((3<<6) | (2<<4)) + +#define L3G4200_RANGE_250dps (0<<4) +#define L3G4200_RANGE_500dps (1<<4) +#define L3G4200_RANGE_2000dps (3<<4) + +static void +write_reg(struct spi_dev_s *spi, uint8_t address, uint8_t data) +{ + uint8_t cmd[2] = { address | DIR_WRITE, data }; + + SPI_SELECT(spi, PX4_SPIDEV_GYRO, true); + SPI_SNDBLOCK(spi, &cmd, sizeof(cmd)); + SPI_SELECT(spi, PX4_SPIDEV_GYRO, false); +} + +static uint8_t +read_reg(struct spi_dev_s *spi, uint8_t address) +{ + uint8_t cmd[2] = {address | DIR_READ, 0}; + uint8_t data[2]; + + SPI_SELECT(spi, PX4_SPIDEV_GYRO, true); + SPI_EXCHANGE(spi, cmd, data, sizeof(cmd)); + SPI_SELECT(spi, PX4_SPIDEV_GYRO, false); + + return data[1]; +} + +int +l3gd20_test_configure(struct spi_dev_s *spi) +{ + uint8_t id; + + id = read_reg(spi, ADDR_WHO_AM_I); + + if (id == WHO_I_AM) + { + message("L3GD20 SUCCESS: 0x%02x\n", id); + } + else + { + message("L3GD20 FAIL: 0x%02x\n", id); + } + + struct { /* status register and data as read back from the device */ + uint8_t cmd; + uint8_t temp; + uint8_t status; + int16_t x; + int16_t y; + int16_t z; + } __attribute__((packed)) report; + + report.cmd = 0x26 | DIR_READ | ADDR_INCREMENT; + + write_reg(spi, ADDR_CTRL_REG2, 0); /* disable high-pass filters */ + write_reg(spi, ADDR_CTRL_REG3, 0); /* no interrupts - we don't use them */ + write_reg(spi, ADDR_CTRL_REG5, 0); /* turn off FIFO mode */ + + write_reg(spi, ADDR_CTRL_REG4, ((3<<4) & 0x30) | REG4_BDU); + + + write_reg(spi, ADDR_CTRL_REG1, + (((2<<6) | (1<<4)) & 0xf0) | REG1_POWER_NORMAL | REG1_Z_ENABLE | REG1_Y_ENABLE | REG1_X_ENABLE); + + SPI_SELECT(spi, PX4_SPIDEV_GYRO, true); + SPI_EXCHANGE(spi, &report, &report, sizeof(report)); + SPI_SELECT(spi, PX4_SPIDEV_GYRO, false); + + message("Init-read: gyro: x: %d\ty: %d\tz: %d\n", report.x, report.y, report.z); + usleep(1000); + + //message("got id 0x%02x, expected ID 0xd4\n", id); + + return 0; +} + +int +l3gd20_test_read(struct spi_dev_s *spi) +{ + struct { /* status register and data as read back from the device */ + uint8_t cmd; + uint8_t temp; + uint8_t status; + int16_t x; + int16_t y; + int16_t z; + } __attribute__((packed)) report; + + report.cmd = 0x26 | DIR_READ | ADDR_INCREMENT; + + SPI_LOCK(spi, true); + SPI_SELECT(spi, PX4_SPIDEV_GYRO, true); + SPI_EXCHANGE(spi, &report, &report, sizeof(report)); + SPI_SELECT(spi, PX4_SPIDEV_GYRO, false); + SPI_LOCK(spi, false); + + message("gyro: x: %d\ty: %d\tz: %d\n", report.x, report.y, report.z); + usleep(1000); + return 0; +} diff --git a/apps/px4/sensors_bringup/sensors.h b/apps/px4/sensors_bringup/sensors.h new file mode 100644 index 0000000000..5fc2fbb082 --- /dev/null +++ b/apps/px4/sensors_bringup/sensors.h @@ -0,0 +1,88 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_PX4_SENSORS_H +#define __APPS_PX4_SENSORS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Debug ********************************************************************/ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_DEBUG +# define message(...) lib_rawprintf(__VA_ARGS__) +# define msgflush() +# else +# define message(...) printf(__VA_ARGS__) +# define msgflush() fflush(stdout) +# endif +#else +# ifdef CONFIG_DEBUG +# define message lib_rawprintf +# define msgflush() +# else +# define message printf +# define msgflush() fflush(stdout) +# endif +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int l3gd20_test_configure(struct spi_dev_s *spi); +int l3gd20_test_read(struct spi_dev_s *spi); +int bma180_test_configure(struct spi_dev_s *spi); +int bma180_test_read(struct spi_dev_s *spi); +int bma180_test(struct spi_dev_s *spi); +int hmc5883l_test(struct i2c_dev_s *i2c); + +#endif /* __APPS_PX4_SENSORS_H */ diff --git a/apps/px4/sensors_bringup/sensors_main.c b/apps/px4/sensors_bringup/sensors_main.c new file mode 100644 index 0000000000..3aa21ae14a --- /dev/null +++ b/apps/px4/sensors_bringup/sensors_main.c @@ -0,0 +1,409 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "sensors.h" + +__EXPORT int sensors_bringup_main(int argc, char *argv[]); + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start/adc_main + ****************************************************************************/ + +int sensors_bringup_main(int argc, char *argv[]) +{ + struct spi_dev_s *spi; + int result = -1; + + spi = up_spiinitialize(1); + if (!spi) { + message("Failed to initialize SPI port 1\n"); + goto out; + } + + struct i2c_dev_s *i2c; + i2c = up_i2cinitialize(2); + if (!i2c) { + message("Failed to initialize I2C bus 2\n"); + goto out; + } + + int ret; + +#define EEPROM_ADDRESS 0x50 +#define HMC5883L_ADDRESS 0x1E + + //uint8_t devaddr = EEPROM_ADDRESS; + + I2C_SETFREQUENCY(i2c, 100000); +// +// uint8_t subaddr = 0x00; +// int ret = 0; +// +// // ATTEMPT HMC5883L CONFIG +// I2C_SETADDRESS(i2c, HMC5883L_ADDRESS, 7); +// subaddr = 0x02; // mode register +// ret = I2C_WRITE(i2c, &subaddr, 0); +// if (ret < 0) +// { +// message("I2C_WRITE failed: %d\n", ret); +// } +// else +// { +// message("I2C_WRITE SUCCEEDED: %d\n", ret); +// } + + //fflush(stdout); +// +// +// + + +#define STATUS_REGISTER 0x09 // Of HMC5883L + + // ATTEMPT HMC5883L WRITE + I2C_SETADDRESS(i2c, HMC5883L_ADDRESS, 7); + uint8_t cmd = 0x09; + uint8_t status_id[4] = {0, 0, 0, 0}; + + + ret = I2C_WRITEREAD(i2c, &cmd, 1, status_id, 4); + + if (ret >= 0 && status_id[1] == 'H' && status_id[2] == '4' && status_id[3] == '3') + { + message("HMC5883L identified, device status: %d\n", status_id[0]); + } else { + message("HMC5883L identification failed: %d\n", ret); + } + +#define HMC5883L_ADDR_CONF_A 0x00 +#define HMC5883L_ADDR_CONF_B 0x01 +#define HMC5883L_ADDR_MODE 0x02 + +#define HMC5883L_AVERAGING_1 (0 << 5) /* conf a register */ +#define HMC5883L_AVERAGING_2 (1 << 5) +#define HMC5883L_AVERAGING_4 (2 << 5) +#define HMC5883L_AVERAGING_8 (3 << 5) + +#define HMC5883L_RATE_75HZ (6 << 2) /* 75 Hz */ + +#define HMC5883L_RANGE_0_88GA (0 << 5) + + uint8_t rate_cmd[] = {HMC5883L_ADDR_CONF_A, HMC5883L_RATE_75HZ | HMC5883L_AVERAGING_8}; + ret = I2C_WRITE(i2c, rate_cmd, sizeof(rate_cmd)); + message("Wrote %d into register 0x00 of HMC, result: %d (0 = success)\n", HMC5883L_RATE_75HZ | HMC5883L_AVERAGING_8, ret); + + uint8_t range_cmd[] = {HMC5883L_ADDR_CONF_B, HMC5883L_RANGE_0_88GA}; + ret = I2C_WRITE(i2c, range_cmd, sizeof(range_cmd)); + message("Wrote %d into register 0x01 of HMC, result: %d (0 = success)\n", HMC5883L_RANGE_0_88GA, ret); + + // Set HMC into continous mode + // First write address, then value + uint8_t cont_address[] = {HMC5883L_ADDR_MODE, 0x00}; + ret = I2C_WRITE(i2c, cont_address, sizeof(cont_address)); + + message("Wrote 0x00 into register 0x02 of HMC, result: %d (0 = success)\n", ret); + + + // ATTEMPT HMC5883L READ + int h = 0; + + I2C_SETADDRESS(i2c, HMC5883L_ADDRESS, 7); + for (h = 0; h < 5; h++) + { + + cont_address[0] = HMC5883L_ADDR_MODE; + cont_address[1] = 0x01; + ret = I2C_WRITE(i2c, cont_address, sizeof(cont_address)); + + message("Wrote 0x01 into register 0x02 of HMC, result: %d (0 = success)\n", ret); + + usleep(100000); + + cont_address[1] = 0x00; + uint8_t dummy; + ret = I2C_WRITEREAD(i2c, cont_address, sizeof(cont_address), &dummy, 1); + + message("Wrote 0x00 into register 0x02 of HMC, result: %d (0 = success)\n", ret); + + usleep(100000); + + + int16_t hmc5883l_data[3] = {0, 0, 0}; + uint8_t data_address = 0x03; + uint8_t* data_ptr = (uint8_t*)hmc5883l_data; + ret = I2C_WRITEREAD(i2c, &data_address, 1, data_ptr, 6); + if (ret < 0) + { + message("HMC5883L READ failed: %d\n", ret); + } + else + { + // mask out top four bits as only 12 bits are valid + hmc5883l_data[0] &= 0xFFF; + hmc5883l_data[1] &= 0xFFF; + hmc5883l_data[2] &= 0xFFF; + + message("HMC5883L READ SUCCEEDED: %d, val: %d %d %d\n", ret, hmc5883l_data[0], hmc5883l_data[1], hmc5883l_data[2]); + uint8_t hmc_status; + ret = I2C_WRITEREAD(i2c, &cmd, 1, &hmc_status, 1); + + message("\t status: %d\n", hmc_status); + } + } + + + // Possible addresses: 0x77 or 0x76 +#define MS5611_ADDRESS_1 0x76 +#define MS5611_ADDRESS_2 0x77 + I2C_SETADDRESS(i2c, MS5611_ADDRESS_1, 7); + // Reset cmd + uint8_t ms5611_cmd[2] = {0x00, 0x1E}; + ret = I2C_WRITE(i2c, ms5611_cmd, 2); + if (ret < 0) + { + message("MS5611 #1 WRITE failed: %d\n", ret); + } + else + { + message("MS5611 #1 WRITE SUCCEEDED: %d\n", ret); + } + + fflush(stdout); + + I2C_SETADDRESS(i2c, MS5611_ADDRESS_2, 7); + ret = I2C_WRITE(i2c, ms5611_cmd, 2); + if (ret < 0) + { + message("MS5611 #2 WRITE failed: %d\n", ret); + } + else + { + message("MS5611 #2 WRITE SUCCEEDED: %d\n", ret); + } + + fflush(stdout); + + + // Wait for reset to complete (10 ms nominal, wait: 100 ms) + usleep(100000); + + // Read PROM data + uint8_t prom_buf[2] = {0,1}; + + uint16_t calibration[6]; + + int i = 0; + + prom_buf[0] = 0xA2 + (i*2); + + struct i2c_msg_s msgv[2] = { + { + .addr = MS5611_ADDRESS_2, + .flags = 0, + .buffer = prom_buf, + .length = 1 + }, + { + .addr = MS5611_ADDRESS_2, + .flags = I2C_M_READ, + .buffer = prom_buf, + .length = 1 + } + }; + + calibration[i] = prom_buf[0]*256; + calibration[i]+= prom_buf[1]; + + int retval; + + if ( (retval = I2C_TRANSFER(i2c, msgv, 2)) == OK ) + { + printf("SUCCESS ACCESSING PROM OF MS5611: %d, value C1: %d\n", retval, (int)calibration[0]); + } + else + { + printf("FAIL ACCESSING PROM OF MS5611\n"); + } + + + + + // TESTING CODE, EEPROM READ/WRITE + uint8_t val[1] = {10}; + int retval_eeprom; + uint8_t eeprom_subaddr[2] = {0, 0}; + + struct i2c_msg_s msgv_eeprom[2] = { + { + .addr = EEPROM_ADDRESS, + .flags = 0, + .buffer = eeprom_subaddr, + .length = 2 + }, + { + .addr = EEPROM_ADDRESS, + .flags = I2C_M_READ, + .buffer = val, + .length = 1 + } + }; + + val[0] = 5; + + if ( (retval_eeprom = I2C_TRANSFER(i2c, msgv_eeprom, 2)) == OK ) + { + printf("SUCCESS READING EEPROM: %d, value: %d\n", retval_eeprom, (int)val[0]); + } + else + { + printf("FAIL READING EEPROM: %d, value: %d\n", retval_eeprom, (int)val[0]); + } + + // Increment val + val[0] = val[0] + 1; + + struct i2c_msg_s msgv_eeprom_write[2] = { + { + .addr = EEPROM_ADDRESS, + .flags = I2C_M_NORESTART, + .buffer = eeprom_subaddr, + .length = 2 + }, + { + .addr = EEPROM_ADDRESS, + .flags = I2C_M_NORESTART, + .buffer = val, + .length = 1 + } + }; + + + if ( (retval_eeprom = I2C_TRANSFER(i2c, msgv_eeprom_write, 2)) == OK ) + { + printf("SUCCESS WRITING EEPROM: %d\n", retval_eeprom); + } + + usleep(10000); + + struct i2c_msg_s msgv_eeprom2[2] = { + { + .addr = EEPROM_ADDRESS, + .flags = 0, + .buffer = eeprom_subaddr, + .length = 2 + }, + { + .addr = EEPROM_ADDRESS, + .flags = I2C_M_READ, + .buffer = val, + .length = 1 + } + }; + + val[0] = 5; + + + if ( (retval_eeprom = I2C_TRANSFER(i2c, msgv_eeprom2, 2)) == OK ) + { + printf("SUCCESS READING WRITE RESULT EEPROM: %d, value: %d\n", retval_eeprom, (int)val[0]); + } + else + { + printf("FAIL READING WRITE RESULT EEPROM: %d, value: %d\n", retval_eeprom, (int)val[0]); + } + + // Configure sensors + l3gd20_test_configure(spi); + bma180_test_configure(spi); + + for (int i = 0; i < 3; i++) + { + l3gd20_test_read(spi); + bma180_test_read(spi); + printf("# %d of 10\n", i+1); + usleep(50000); + } + + + out: + msgflush(); + return result; +} diff --git a/apps/px4/tests/.context b/apps/px4/tests/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/px4/tests/Makefile b/apps/px4/tests/Makefile new file mode 100644 index 0000000000..41979f85a9 --- /dev/null +++ b/apps/px4/tests/Makefile @@ -0,0 +1,42 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Makefile to build assorted test cases +# + +APPNAME = tests +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 4096 + +include $(APPDIR)/mk/app.mk diff --git a/apps/px4/tests/test_adc.c b/apps/px4/tests/test_adc.c new file mode 100644 index 0000000000..7795f07acf --- /dev/null +++ b/apps/px4/tests/test_adc.c @@ -0,0 +1,211 @@ +/**************************************************************************** + * px4/sensors/test_gpio.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "tests.h" + +#include + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_gpio + ****************************************************************************/ + +int test_adc(int argc, char *argv[]) +{ + int fd0; + int ret = 0; + //struct adc_msg_s sample[4],sample2[4],sample3[4],sample4[4],sample5[4],sample6[4],sample7[4],sample8[4],sample9[4]; + + struct adc_msg4_s { + uint8_t am_channel1; /* The 8-bit ADC Channel */ + int32_t am_data1; /* ADC convert result (4 bytes) */ + uint8_t am_channel2; /* The 8-bit ADC Channel */ + int32_t am_data2; /* ADC convert result (4 bytes) */ + uint8_t am_channel3; /* The 8-bit ADC Channel */ + int32_t am_data3; /* ADC convert result (4 bytes) */ + uint8_t am_channel4; /* The 8-bit ADC Channel */ + int32_t am_data4; /* ADC convert result (4 bytes) */ + } __attribute__((__packed__));; + + struct adc_msg4_s sample1[4], sample2[4]; + + size_t readsize; + ssize_t nbytes, nbytes2; + int i; + int j; + int errval; + + for (j = 0; j < 1; j++) { + char name[11]; + sprintf(name, "/dev/adc%d", j); + fd0 = open(name, O_RDONLY | O_NONBLOCK); + + if (fd0 < 0) { + printf("ADC: %s open fail\n", name); + return ERROR; + + } else { + printf("Opened %s successfully\n", name); + } + + /* first adc read round */ + readsize = 4 * sizeof(struct adc_msg_s); + up_udelay(10000);//microseconds + nbytes = read(fd0, sample1, readsize); + up_udelay(10000);//microseconds + nbytes2 = read(fd0, sample2, readsize); +// nbytes2 = read(fd0, sample3, readsize); +// nbytes2 = read(fd0, sample4, readsize); +// nbytes2 = read(fd0, sample5, readsize); +// nbytes2 = read(fd0, sample6, readsize); +// nbytes2 = read(fd0, sample7, readsize); +// nbytes2 = read(fd0, sample8, readsize); + //nbytes2 = read(fd0, sample9, readsize); + + /* Handle unexpected return values */ + + if (nbytes < 0) { + errval = errno; + + if (errval != EINTR) { + message("read %s failed: %d\n", + name, errval); + errval = 3; + goto errout_with_dev; + } + + message("\tInterrupted read...\n"); + + } else if (nbytes == 0) { + message("\tNo data read, Ignoring\n"); + } + + /* Print the sample data on successful return */ + + else { + int nsamples = nbytes / sizeof(struct adc_msg_s); + + if (nsamples * sizeof(struct adc_msg_s) != nbytes) { + message("\tread size=%d is not a multiple of sample size=%d, Ignoring\n", + nbytes, sizeof(struct adc_msg_s)); + + } else { + message("Sample:"); + + for (i = 0; i < 1 ; i++) { + message("%d: channel: %d value: %d\n", + i, sample1[i].am_channel1, sample1[i].am_data1); + message("Sample:"); + message("%d: channel: %d value: %d\n", + i, sample1[i].am_channel2, sample1[i].am_data2); + message("Sample:"); + message("%d: channel: %d value: %d\n", + i, sample1[i].am_channel3, sample1[i].am_data3); + message("Sample:"); + message("%d: channel: %d value: %d\n", + i, sample1[i].am_channel4, sample1[i].am_data4); + message("Sample:"); + message("%d: channel: %d value: %d\n", + i + 1, sample2[i].am_channel1, sample2[i].am_data1); + message("Sample:"); + message("%d: channel: %d value: %d\n", + i + 1, sample2[i].am_channel2, sample2[i].am_data2); + message("Sample:"); + message("%d: channel: %d value: %d\n", + i + 1, sample2[i].am_channel3, sample2[i].am_data3); + message("Sample:"); + message("%d: channel: %d value: %d\n", + i + 1, sample2[i].am_channel4, sample2[i].am_data4); +// message("%d: channel: %d value: %d\n", +// i, sample9[i].am_channel, sample9[i].am_data); + } + } + } + } + + printf("\t ADC test successful.\n"); + +errout_with_dev: + + if (fd0 != 0) close(fd0); + + return ret; +} diff --git a/apps/px4/tests/test_eeproms.c b/apps/px4/tests/test_eeproms.c new file mode 100644 index 0000000000..29ca8267ff --- /dev/null +++ b/apps/px4/tests/test_eeproms.c @@ -0,0 +1,328 @@ +/**************************************************************************** + * px4/eeproms/test_eeproms.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "tests.h" + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int onboard_eeprom(int argc, char *argv[]); +static int baseboard_eeprom(int argc, char *argv[]); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct { + const char *name; + const char *path; + int (* test)(int argc, char *argv[]); +} eeproms[] = { + {"onboard_eeprom", "/dev/eeprom", onboard_eeprom}, + {"baseboard_eeprom", "/dev/baseboard_eeprom", baseboard_eeprom}, + {NULL, NULL, NULL} +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int +onboard_eeprom(int argc, char *argv[]) +{ + printf("\tonboard_eeprom: test start\n"); + fflush(stdout); + + int fd; + uint8_t buf1[210] = {' ', 'P', 'X', '4', ' ', 'E', 'E', 'P', 'R', 'O', 'M', ' ', 'T', 'E', 'S', 'T', ' '}; + int ret; + bool force_write = false; + if (strcmp(argv[0], "jig") == 0) force_write = true; + + /* fill with spaces */ + //memset(buf1+16, 'x', sizeof(buf1-16)); + + /* fill in some magic values at magic positions */ + buf1[63] = 'E'; + buf1[64] = 'S'; + buf1[127] = 'F'; + buf1[128] = 'T'; + + /* terminate string */ + buf1[sizeof(buf1) - 1] = '\0'; + + fd = open("/dev/eeprom", O_RDWR | O_NONBLOCK); + + if (fd < 0) { + printf("onboard eeprom: open fail\n"); + return ERROR; + } + + /* read data */ + ret = read(fd, buf1, 1); + + if (ret != 1) { + printf("\tonboard eeprom: ERROR: reading first byte fail: %d\n", ret); + + switch (-ret) { + case EPERM: + printf("\treason: %s\n", EPERM_STR); + break; + + case ENOENT: + printf("\treason: %s\n", ENOENT_STR); + break; + + case ESRCH: + printf("\treason: %s\n", ESRCH_STR); + break; + + case EINTR: + printf("\treason: %s\n", EINTR_STR); + break; + + } + } + + printf("\tonboard eeprom: first byte: %d\n", buf1[0]); + if (!force_write) { + printf("\tonboard eeprom: WARNING: FURTHER TEST STEPS WILL DESTROY YOUR FLIGHT PARAMETER CONFIGURATION. PROCEED? (y/N)\n"); + + printf("Input: "); + char c = getchar(); + printf("%c\n", c); + if (c != 'y' && c != 'Y') { + /* not yes, abort */ + close(fd); + + /* Let user know everything is ok */ + printf("\tOK: onboard eeprom test aborted by user, read test successful\r\n"); + return OK; + } + } + + printf("\tonboard eeprom: proceeding with write test\r\n"); + + /* increment counter */ + buf1[0] = buf1[0] + 1; + + /* rewind to the start of the file */ + lseek(fd, 0, SEEK_SET); + + /* write data */ + ret = write(fd, buf1, sizeof(buf1)); + + if (ret != sizeof(buf1)) { + printf("\tonboard eeprom: ERROR: write fail: %d\n", (char)ret); + + switch (-ret) { + case EPERM: + printf("\treason: %s\n", EPERM_STR); + break; + + case ENOENT: + printf("\treason: %s\n", ENOENT_STR); + break; + + case ESRCH: + printf("\treason: %s\n", ESRCH_STR); + break; + + case EINTR: + printf("\treason: %s\n", EINTR_STR); + break; + + } + + //return ERROR; + } + + /* rewind to the start of the file */ + lseek(fd, 0, SEEK_SET); + + /* read data */ + ret = read(fd, buf1, sizeof(buf1)); + + if (ret != sizeof(buf1)) { + printf("\tonboard eeprom: ERROR: read fail: %d\n", ret); + + switch (-ret) { + case EPERM: + printf("\treason: %s\n", EPERM_STR); + break; + + case ENOENT: + printf("\treason: %s\n", ENOENT_STR); + break; + + case ESRCH: + printf("\treason: %s\n", ESRCH_STR); + break; + + case EINTR: + printf("\treason: %s\n", EINTR_STR); + break; + + } + + return ERROR; + + } else { + /* enforce null termination and print as string */ + if (buf1[sizeof(buf1) - 1] != 0) { + printf("\tWARNING: Null termination in file not present as expected, enforcing it now..\r\n"); + buf1[sizeof(buf1) - 1] = '\0'; + } + + /* read out counter and replace val */ + int counter = buf1[0]; + printf("\tonboard eeprom: count: #%d, read values: %s\n", counter, (char *)buf1 + 1); + printf("\tAll %d bytes:\n\n\t", sizeof(buf1)); + + for (int i = 0; i < sizeof(buf1); i++) { + printf("0x%02x ", buf1[i]); + + if (i % 8 == 7) printf("\n\t"); + + if (i % 64 == 63) printf("\n\t"); + } + + /* end any open line */ + printf("\n\n"); + } + + close(fd); + + /* Let user know everything is ok */ + printf("\tOK: onboard eeprom passed all tests successfully\n"); + return ret; +} + +static int +baseboard_eeprom(int argc, char *argv[]) +{ + printf("\tbaseboard eeprom: test start\n"); + fflush(stdout); + + int fd; + uint8_t buf[128] = {'R', 'E', 'A', 'D', ' ', 'F', 'A', 'I', 'L', 'E', 'D', '\0'}; + int ret; + + fd = open("/dev/baseboard_eeprom", O_RDONLY | O_NONBLOCK); + + if (fd < 0) { + printf("\tbaseboard eeprom: open fail\n"); + return ERROR; + } + + /* read data */ + ret = read(fd, buf, sizeof(buf)); + /* set last char to string termination */ + buf[127] = '\0'; + + if (ret != sizeof(buf)) { + printf("\tbaseboard eeprom: ERROR: read fail\n", ret); + return ERROR; + + } else { + printf("\tbaseboard eeprom: string: %s\n", (char *)buf); + } + + close(fd); + + /* XXX more tests here */ + + /* Let user know everything is ok */ + printf("\tOK: baseboard eeprom passed all tests successfully\n"); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_eeproms + ****************************************************************************/ + +int test_eeproms(int argc, char *argv[]) +{ + unsigned i; + + printf("Running EEPROMs tests:\n\n"); + fflush(stdout); + + for (i = 0; eeproms[i].name; i++) { + printf(" eeprom: %s\n", eeproms[i].name); + eeproms[i].test(argc, argv); + fflush(stdout); + /* wait 100 ms to make sure buffer is emptied */ + usleep(100000); + } + + return 0; +} diff --git a/apps/px4/tests/test_float.c b/apps/px4/tests/test_float.c new file mode 100644 index 0000000000..02e748e702 --- /dev/null +++ b/apps/px4/tests/test_float.c @@ -0,0 +1,282 @@ +/**************************************************************************** + * px4/sensors/test_gpio.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "tests.h" + +#include +#include + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_led + ****************************************************************************/ + +typedef union { + float f; + double d; + uint8_t b[8]; +} test_float_double_t; + +int test_float(int argc, char *argv[]) +{ + int ret = 0; + + printf("\n--- SINGLE PRECISION TESTS ---\n"); + printf("The single precision test involves calls to fabs(),\nif test fails check this function as well.\n\n"); + + float f1 = 1.55f; + + float sinf_zero = sinf(0.0f); + float sinf_one = sinf(1.0f); + float sqrt_two = sqrt(2.0f); + + if (sinf_zero == 0.0f) { + printf("\t success: sinf(0.0f) == 0.0f\n"); + + } else { + printf("\t FAIL: sinf(0.0f) != 0.0f, result: %f\n", sinf_zero); + ret = -4; + } + + fflush(stdout); + + if (fabs((sinf_one - 0.841470956802368164062500000000f)) < FLT_EPSILON) { + printf("\t success: sinf(1.0f) == 0.84147f\n"); + + } else { + printf("\t FAIL: sinf(1.0f) != 0.84147f, result: %f\n", sinf_one); + ret = -1; + } + + fflush(stdout); + + float asinf_one = asinf(1.0f); + + if (fabs((asinf_one - 1.570796251296997070312500000000f)) < FLT_EPSILON * 1.5f) { + printf("\t success: asinf(1.0f) == 1.57079f\n"); + + } else { + printf("\t FAIL: asinf(1.0f) != 1.57079f, result: %f\n", asinf_one); + ret = -1; + } + + fflush(stdout); + + float cosf_one = cosf(1.0f); + + if (fabs((cosf_one - 0.540302336215972900390625000000f)) < FLT_EPSILON) { + printf("\t success: cosf(1.0f) == 0.54030f\n"); + + } else { + printf("\t FAIL: cosf(1.0f) != 0.54030f, result: %f\n", cosf_one); + ret = -1; + } + + fflush(stdout); + + + float acosf_one = acosf(1.0f); + + if (fabs((acosf_one - 0.000000000000000000000000000000f)) < FLT_EPSILON) { + printf("\t success: acosf(1.0f) == 0.0f\n"); + + } else { + printf("\t FAIL: acosf(1.0f) != 0.0f, result: %f\n", acosf_one); + ret = -1; + } + + fflush(stdout); + + + float sinf_zero_one = sinf(0.1f); + + if (fabs(sinf_zero_one - 0.0998334166f) < FLT_EPSILON) { + printf("\t success: sinf(0.1f) == 0.09983f\n"); + + } else { + printf("\t FAIL: sinf(0.1f) != 0.09983f, result: %f\n", sinf_zero_one); + ret = -2; + } + + if (sqrt_two == 1.41421356f) { + printf("\t success: sqrt(2.0f) == 1.41421f\n"); + + } else { + printf("\t FAIL: sqrt(2.0f) != 1.41421f, result: %f\n", sinf_zero_one); + ret = -3; + } + + float atan2f_ones = atan2(1.0f, 1.0f); + + if (fabs(atan2f_ones - 0.785398163397448278999490867136f) < FLT_EPSILON) { + printf("\t success: atan2f(1.0f, 1.0f) == 0.78539f\n"); + + } else { + printf("\t FAIL: atan2f(1.0f, 1.0f) != 0.78539f, result: %f\n", atan2f_ones); + ret = -4; + } + + printf("\t testing printing: printf(0.553415f): %f\n", 0.553415f); + + + + + + printf("\n--- DOUBLE PRECISION TESTS ---\n"); + + double d1 = 1.0111; + double d2 = 2.0; + + double d1d2 = d1 * d2; + + if (d1d2 == 2.022200000000000219557705349871) { + printf("\t success: 1.0111 * 2.0 == 2.0222\n"); + + } else { + printf("\t FAIL: 1.0111 * 2.0 != 2.0222, result: %f\n", d1d2); + } + + fflush(stdout); + + // Assign value of f1 to d1 + d1 = f1; + + if (f1 == (float)d1) { + printf("\t success: (float) 1.55f == 1.55 (double)\n"); + + } else { + printf("\t FAIL: (float) 1.55f != 1.55 (double), result: %f\n", f1); + ret = -4; + } + + fflush(stdout); + + + double sin_zero = sin(0.0); + double sin_one = sin(1.0); + double atan2_ones = atan2(1.0, 1.0); + + if (sin_zero == 0.0) { + printf("\t success: sin(0.0) == 0.0\n"); + + } else { + printf("\t FAIL: sin(0.0) != 0.0, result: %f\n", sin_zero); + ret = -5; + } + + if (sin_one == 0.841470984807896504875657228695) { + printf("\t success: sin(1.0) == 0.84147098480\n"); + + } else { + printf("\t FAIL: sin(1.0) != 1.0, result: %f\n", sin_one); + ret = -6; + } + + if (atan2_ones != 0.785398) { + printf("\t success: atan2(1.0, 1.0) == 0.785398\n"); + + } else { + printf("\t FAIL: atan2(1.0, 1.0) != 0.785398, result: %f\n", atan2_ones); + ret = -7; + } + + printf("\t testing printing: printf(0.553415): %f\n", 0.553415); + + printf("\t testing pow() with magic value\n"); + printf("\t (44330.0 * (1.0 - pow((96286LL / 101325.0), 0.190295)));\n"); + fflush(stdout); + usleep(20000); + double powres = (44330.0 * (1.0 - pow((96286LL / 101325.0), 0.190295))); + printf("\t success: result: %f\n", (float)powres); + + + if (ret == 0) { + printf("\n SUCCESS: All float and double tests passed.\n"); + + } else { + printf("\n FAIL: One or more tests failed.\n"); + } + + printf("\n"); + + return ret; +} diff --git a/apps/px4/tests/test_gpio.c b/apps/px4/tests/test_gpio.c new file mode 100644 index 0000000000..ab536d9560 --- /dev/null +++ b/apps/px4/tests/test_gpio.c @@ -0,0 +1,115 @@ +/**************************************************************************** + * px4/sensors/test_gpio.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "tests.h" + +#include + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_gpio + ****************************************************************************/ + +int test_gpio(int argc, char *argv[]) +{ + int fd; + int ret = 0; + + fd = open(GPIO_DEVICE_PATH, 0); + + if (fd < 0) { + printf("GPIO: open fail\n"); + return ERROR; + } + + /* set all GPIOs to default state */ + ioctl(fd, GPIO_RESET, ~0); + + + /* XXX need to add some GPIO waving stuff here */ + + + /* Go back to default */ + ioctl(fd, GPIO_RESET, ~0); + + printf("\t GPIO test successful.\n"); + + return ret; +} diff --git a/apps/px4/tests/test_hrt.c b/apps/px4/tests/test_hrt.c new file mode 100644 index 0000000000..41f207b7e4 --- /dev/null +++ b/apps/px4/tests/test_hrt.c @@ -0,0 +1,219 @@ +/**************************************************************************** + * px4/sensors/test_hrt.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "tests.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +extern uint16_t ppm_buffer[]; +extern unsigned ppm_decoded_channels; +extern uint16_t ppm_edge_history[]; +extern uint16_t ppm_pulse_history[]; + +int test_ppm(int argc, char *argv[]) +{ +#ifdef CONFIG_HRT_PPM + unsigned i; + + printf("channels: %u\n", ppm_decoded_channels); + + for (i = 0; i < ppm_decoded_channels; i++) + printf(" %u\n", ppm_buffer[i]); + + printf("edges\n"); + + for (i = 0; i < 32; i++) + printf(" %u\n", ppm_edge_history[i]); + + printf("pulses\n"); + + for (i = 0; i < 32; i++) + printf(" %u\n", ppm_pulse_history[i]); + + fflush(stdout); +#else + printf("PPM not configured\n"); +#endif + return 0; +} + +int test_tone(int argc, char *argv[]) +{ +#ifdef CONFIG_TONE_ALARM + int fd, result; + unsigned long tone; + + fd = open("/dev/tone_alarm", O_WRONLY); + + if (fd < 0) { + printf("failed opening /dev/tone_alarm\n"); + goto out; + } + + tone = 1; + + if (argc == 2) + tone = atoi(argv[1]); + + if (tone == 0) { + result = ioctl(fd, TONE_SET_ALARM, 0); + + if (result < 0) { + printf("failed clearing alarms\n"); + goto out; + + } else { + printf("Alarm stopped.\n"); + } + + } else { + result = ioctl(fd, TONE_SET_ALARM, 0); + + if (result < 0) { + printf("failed clearing alarms\n"); + goto out; + } + + result = ioctl(fd, TONE_SET_ALARM, tone); + + if (result < 0) { + printf("failed setting alarm %lu\n", tone); + + } else { + printf("Alarm %lu (disable with: tests tone 0)\n", tone); + } + } + +out: + + if (fd >= 0) + close(fd); + +#endif + return 0; +} + +/**************************************************************************** + * Name: test_hrt + ****************************************************************************/ + +int test_hrt(int argc, char *argv[]) +{ + struct hrt_call call; + hrt_abstime prev, now; + int i; + struct timeval tv1, tv2; + + printf("start-time (hrt, sec/usec), end-time (hrt, sec/usec), microseconds per half second\n"); + + for (i = 0; i < 10; i++) { + prev = hrt_absolute_time(); + gettimeofday(&tv1, NULL); + usleep(500000); + now = hrt_absolute_time(); + gettimeofday(&tv2, NULL); + printf("%lu (%lu/%lu), %lu (%lu/%lu), %lu\n", + (unsigned long)prev, (unsigned long)tv1.tv_sec, (unsigned long)tv1.tv_usec, + (unsigned long)now, (unsigned long)tv2.tv_sec, (unsigned long)tv2.tv_usec, + (unsigned long)(hrt_absolute_time() - prev)); + fflush(stdout); + } + + usleep(1000000); + + printf("one-second ticks\n"); + + for (i = 0; i < 10; i++) { + hrt_call_after(&call, 1000000, NULL, NULL); + + while (!hrt_called(&call)) { + usleep(1000); + } + + printf("tick\n"); + fflush(stdout); + } + + return 0; +} diff --git a/apps/px4/tests/test_int.c b/apps/px4/tests/test_int.c new file mode 100644 index 0000000000..40e0306417 --- /dev/null +++ b/apps/px4/tests/test_int.c @@ -0,0 +1,151 @@ +/**************************************************************************** + * px4/sensors/test_gpio.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "tests.h" + +#include +#include + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_led + ****************************************************************************/ + +typedef union { + int32_t i; + int64_t l; + uint8_t b[8]; +} test_32_64_t; + +int test_int(int argc, char *argv[]) +{ + int ret = 0; + + printf("\n--- 64 BIT MATH TESTS ---\n"); + + int64_t large = 354156329598; + + int64_t calc = large * 5; + + if (calc == 1770781647990) { + printf("\t success: 354156329598 * 5 == %lld\n", calc); + + } else { + printf("\t FAIL: 354156329598 * 5 != %lld\n", calc); + ret = -1; + } + + fflush(stdout); + + + + + + printf("\n--- 32 BIT / 64 BIT MIXED MATH TESTS ---\n"); + + + int32_t small = 50; + int32_t large_int = 2147483647; // MAX INT value + + uint64_t small_times_large = large_int * (uint64_t)small; + + if (small_times_large == 107374182350) { + printf("\t success: 64bit calculation: 50 * 2147483647 (max int val) == %lld\n", small_times_large); + + } else { + printf("\t FAIL: 50 * 2147483647 != %lld, 64bit cast might fail\n", small_times_large); + ret = -1; + } + + fflush(stdout); + + if (ret == 0) { + printf("\n SUCCESS: All float and double tests passed.\n"); + + } else { + printf("\n FAIL: One or more tests failed.\n"); + } + + printf("\n"); + + return ret; +} diff --git a/apps/px4/tests/test_jig_voltages.c b/apps/px4/tests/test_jig_voltages.c new file mode 100644 index 0000000000..51f9b9a5bd --- /dev/null +++ b/apps/px4/tests/test_jig_voltages.c @@ -0,0 +1,217 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "tests.h" + +#include + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_gpio + ****************************************************************************/ + +int test_jig_voltages(int argc, char *argv[]) +{ + int fd0 = 0; + int ret = OK; + const int nchannels = 4; + + struct adc_msg4_s + { + uint8_t am_channel1; /* The 8-bit ADC Channel */ + int32_t am_data1; /* ADC convert result (4 bytes) */ + uint8_t am_channel2; /* The 8-bit ADC Channel */ + int32_t am_data2; /* ADC convert result (4 bytes) */ + uint8_t am_channel3; /* The 8-bit ADC Channel */ + int32_t am_data3; /* ADC convert result (4 bytes) */ + uint8_t am_channel4; /* The 8-bit ADC Channel */ + int32_t am_data4; /* ADC convert result (4 bytes) */ + }__attribute__((__packed__));; + + struct adc_msg4_s sample1[4]; + + size_t readsize; + ssize_t nbytes; + int i = 0; + int j = 0; + int errval; + + char name[11]; + sprintf(name, "/dev/adc%d", j); + fd0 = open(name, O_RDONLY | O_NONBLOCK); + if (fd0 < 0) + { + printf("ADC: %s open fail\n", name); + return ERROR; + } else { + printf("Opened %s successfully\n", name); + } + + + /* Expected values */ + int16_t expected_min[] = {2700, 2700, 2200, 2000}; + int16_t expected_max[] = {3000, 3000, 2500, 2200}; + char* check_res[nchannels]; + + /* first adc read round */ + readsize = 4 * sizeof(struct adc_msg_s); + + /* Empty all buffers */ + do { + nbytes = read(fd0, sample1, readsize); + } + while (nbytes > 0); + + up_udelay(20000);//microseconds + /* Take measurements */ + nbytes = read(fd0, sample1, readsize); + + /* Handle unexpected return values */ + + if (nbytes <= 0) + { + errval = errno; + if (errval != EINTR) + { + message("read %s failed: %d\n", + name, errval); + errval = 3; + goto errout_with_dev; + } + + message("\tInterrupted read...\n"); + } + else if (nbytes == 0) + { + message("\tNo data read, Ignoring\n"); + } + + /* Print the sample data on successful return */ + + else + { + int nsamples = nbytes / sizeof(struct adc_msg_s); + if (nsamples * sizeof(struct adc_msg_s) != nbytes) + { + message("\tread size=%d is not a multiple of sample size=%d, Ignoring\n", + nbytes, sizeof(struct adc_msg_s)); + } + else + { + /* Check values */ + check_res[0] = (expected_min[0] < sample1[i].am_data1 && expected_max[0] > sample1[i].am_data1) ? "OK" : "FAIL"; + check_res[1] = (expected_min[1] < sample1[i].am_data2 && expected_max[1] > sample1[i].am_data2) ? "OK" : "FAIL"; + check_res[2] = (expected_min[2] < sample1[i].am_data3 && expected_max[2] > sample1[i].am_data3) ? "OK" : "FAIL"; + check_res[3] = (expected_min[3] < sample1[i].am_data4 && expected_max[3] > sample1[i].am_data4) ? "OK" : "FAIL"; + + /* Accumulate result */ + ret += (expected_min[0] > sample1[i].am_data1 || expected_max[0] < sample1[i].am_data1) ? 1 : 0; + // XXX Chan 11 not connected on test setup + //ret += (expected_min[1] > sample1[i].am_data2 || expected_max[1] < sample1[i].am_data2) ? 1 : 0; + ret += (expected_min[2] > sample1[i].am_data3 || expected_max[2] < sample1[i].am_data3) ? 1 : 0; + ret += (expected_min[3] > sample1[i].am_data4 || expected_max[3] < sample1[i].am_data4) ? 1 : 0; + + message("Sample:"); + message("%d: channel: %d value: %d (allowed min: %d, allowed max: %d), result: %s\n", + i, sample1[i].am_channel1, sample1[i].am_data1, expected_min[0], expected_max[0], check_res[0]); + message("Sample:"); + message("%d: channel: %d value: %d (allowed min: %d, allowed max: %d), result: %s\n", + i, sample1[i].am_channel2, sample1[i].am_data2, expected_min[1], expected_max[1], check_res[1]); + message("Sample:"); + message("%d: channel: %d value: %d (allowed min: %d, allowed max: %d), result: %s\n", + i, sample1[i].am_channel3, sample1[i].am_data3, expected_min[2], expected_max[2], check_res[2]); + message("Sample:"); + message("%d: channel: %d value: %d (allowed min: %d, allowed max: %d), result: %s\n", + i, sample1[i].am_channel4, sample1[i].am_data4, expected_min[3], expected_max[3], check_res[3]); + + if (ret != OK) { + printf("\t ADC test FAILED. Some channels where out of allowed range. Check supply voltages.\n"); + goto errout_with_dev; + } + } + } + + printf("\t ADC test successful.\n"); + + errout_with_dev: + if (fd0 != 0) close(fd0); + + return ret; +} diff --git a/apps/px4/tests/test_led.c b/apps/px4/tests/test_led.c new file mode 100644 index 0000000000..53615ccd82 --- /dev/null +++ b/apps/px4/tests/test_led.c @@ -0,0 +1,134 @@ +/**************************************************************************** + * px4/sensors/test_gpio.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "tests.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_led + ****************************************************************************/ + +int test_led(int argc, char *argv[]) +{ + int fd; + int ret = 0; + + fd = open("/dev/led", O_RDONLY | O_NONBLOCK); + + if (fd < 0) { + printf("\tLED: open fail\n"); + return ERROR; + } + + if (ioctl(fd, LED_ON, LED_BLUE) || + ioctl(fd, LED_ON, LED_AMBER)) { + + printf("\tLED: ioctl fail\n"); + return ERROR; + } + + /* let them blink for fun */ + + int i; + uint8_t ledon = 1; + + for (i = 0; i < 10; i++) { + if (ledon) { + ioctl(fd, LED_ON, LED_BLUE); + ioctl(fd, LED_OFF, LED_AMBER); + + } else { + ioctl(fd, LED_OFF, LED_BLUE); + ioctl(fd, LED_ON, LED_AMBER); + } + + ledon = !ledon; + usleep(60000); + } + + /* Go back to default */ + ioctl(fd, LED_ON, LED_BLUE); + ioctl(fd, LED_OFF, LED_AMBER); + + printf("\t LED test completed, no errors.\n"); + + return ret; +} diff --git a/apps/px4/tests/test_sensors.c b/apps/px4/tests/test_sensors.c new file mode 100644 index 0000000000..bdb68f88bb --- /dev/null +++ b/apps/px4/tests/test_sensors.c @@ -0,0 +1,501 @@ +/**************************************************************************** + * px4/sensors/test_sensors.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "tests.h" + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +//static int lis331(int argc, char *argv[]); +static int l3gd20(int argc, char *argv[]); +static int bma180(int argc, char *argv[]); +static int hmc5883l(int argc, char *argv[]); +static int ms5611(int argc, char *argv[]); +static int mpu6000(int argc, char *argv[]); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct { + const char *name; + const char *path; + int (* test)(int argc, char *argv[]); +} sensors[] = { + {"l3gd20", "/dev/l3gd20", l3gd20}, + {"bma180", "/dev/bma180", bma180}, + {"hmc5883l", "/dev/hmc5883l", hmc5883l}, + {"ms5611", "/dev/ms5611", ms5611}, + {"mpu6000", "/dev/mpu6000", mpu6000}, +// {"lis331", "/dev/lis331", lis331}, + {NULL, NULL, NULL} +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +//static int +//lis331(int argc, char *argv[]) +//{ +// int fd; +// int16_t buf[3]; +// int ret; +// +// fd = open("/dev/lis331", O_RDONLY); +// if (fd < 0) { +// printf("\tlis331: not present on PX4FMU v1.5 and later\n"); +// return ERROR; +// } +// +// if (ioctl(fd, LIS331_SETRATE, LIS331_RATE_50Hz) || +// ioctl(fd, LIS331_SETRANGE, LIS331_RANGE_4G)) { +// +// printf("LIS331: ioctl fail\n"); +// return ERROR; +// } +// +// /* wait at least 100ms, sensor should have data after no more than 20ms */ +// usleep(100000); +// +// /* read data - expect samples */ +// ret = read(fd, buf, sizeof(buf)); +// if (ret != sizeof(buf)) { +// printf("LIS331: read1 fail (%d)\n", ret); +// return ERROR; +// } +// +// /* read data - expect no samples (should not be ready again yet) */ +// ret = read(fd, buf, sizeof(buf)); +// if (ret != 0) { +// printf("LIS331: read2 fail (%d)\n", ret); +// return ERROR; +// } +// +// /* XXX more tests here */ +// +// return 0; +//} + +static int +l3gd20(int argc, char *argv[]) +{ + printf("\tL3GD20: test start\n"); + fflush(stdout); + + int fd; + int16_t buf[3] = {0, 0, 0}; + int ret; + + fd = open("/dev/l3gd20", O_RDONLY | O_NONBLOCK); + + if (fd < 0) { + printf("L3GD20: open fail\n"); + return ERROR; + } + +// if (ioctl(fd, L3GD20_SETRATE, L3GD20_RATE_760HZ_LP_50HZ) || +// ioctl(fd, L3GD20_SETRANGE, L3GD20_RANGE_500DPS)) { +// +// printf("L3GD20: ioctl fail\n"); +// return ERROR; +// } else { +// printf("\tconfigured..\n"); +// } +// +// /* wait at least 100ms, sensor should have data after no more than 2ms */ +// usleep(100000); + + + + /* read data - expect samples */ + ret = read(fd, buf, sizeof(buf)); + + if (ret != sizeof(buf)) { + printf("\tL3GD20: read1 fail (%d should have been %d)\n", ret, sizeof(buf)); + //return ERROR; + + } else { + printf("\tL3GD20 values #1: x:%d\ty:%d\tz:%d\n", buf[0], buf[1], buf[2]); + } + + /* wait at least 2 ms, sensor should have data after no more than 1.5ms */ + usleep(2000); + + /* read data - expect no samples (should not be ready again yet) */ + ret = read(fd, buf, sizeof(buf)); + + if (ret != sizeof(buf)) { + printf("\tL3GD20: read2 fail (%d)\n", ret); + close(fd); + return ERROR; + + } else { + printf("\tL3GD20 values #2: x:%d\ty:%d\tz:%d\n", buf[0], buf[1], buf[2]); + } + + /* empty sensor buffer */ + ret = 0; + + while (ret != sizeof(buf)) { + // Keep reading until successful + ret = read(fd, buf, sizeof(buf)); + } + + /* test if FIFO is operational */ + usleep(14800); // Expecting 10 measurements + + ret = 0; + int count = 0; + bool dataready = true; + + while (dataready) { + // Keep reading until successful + ret = read(fd, buf, sizeof(buf)); + + if (ret != sizeof(buf)) { + dataready = false; + + } else { + count++; + } + } + + printf("\tL3GD20: Drained FIFO with %d values (expected 8-12)\n", count); + + /* read data - expect no samples (should not be ready again yet) */ + ret = read(fd, buf, sizeof(buf)); + + if (ret != 0) { + printf("\tL3GD20: Note: read3 got data - there should not have been data ready\n", ret); +// return ERROR; + } + + close(fd); + + /* Let user know everything is ok */ + printf("\tOK: L3GD20 passed all tests successfully\n"); + return OK; +} + +static int +bma180(int argc, char *argv[]) +{ + printf("\tBMA180: test start\n"); + fflush(stdout); + + int fd; + int16_t buf[3] = {0, 0, 0}; + int ret; + + fd = open("/dev/bma180", O_RDONLY); + + if (fd < 0) { + printf("\tBMA180: open fail\n"); + return ERROR; + } + +// if (ioctl(fd, LIS331_SETRATE, LIS331_RATE_50Hz) || +// ioctl(fd, LIS331_SETRANGE, LIS331_RANGE_4G)) { +// +// printf("BMA180: ioctl fail\n"); +// return ERROR; +// } +// + /* wait at least 100ms, sensor should have data after no more than 20ms */ + usleep(100000); + + /* read data - expect samples */ + ret = read(fd, buf, sizeof(buf)); + + if (ret != sizeof(buf)) { + printf("\tBMA180: read1 fail (%d)\n", ret); + close(fd); + return ERROR; + + } else { + printf("\tBMA180 values: x:%d\ty:%d\tz:%d\n", buf[0], buf[1], buf[2]); + } + + /* wait at least 10ms, sensor should have data after no more than 2ms */ + usleep(100000); + + ret = read(fd, buf, sizeof(buf)); + + if (ret != sizeof(buf)) { + printf("\tBMA180: read2 fail (%d)\n", ret); + close(fd); + return ERROR; + + } else { + printf("\tBMA180: x:%d\ty:%d\tz:%d\n", buf[0], buf[1], buf[2]); + } + + /* empty sensor buffer */ + ret = 0; + + while (ret != sizeof(buf)) { + // Keep reading until successful + ret = read(fd, buf, sizeof(buf)); + } + + ret = read(fd, buf, sizeof(buf)); + + if (ret != 0) { + printf("\tBMA180: Note: read3 got data - there should not have been data ready\n", ret); + } + + /* Let user know everything is ok */ + printf("\tOK: BMA180 passed all tests successfully\n"); + close(fd); + + return OK; +} + +static int +mpu6000(int argc, char *argv[]) +{ + printf("\tMPU-6000: test start\n"); + fflush(stdout); + + int fd; + int16_t buf[5] = { -1, 0, -1, 0, -1, 0}; + int ret; + + fd = open("/dev/mpu6000", O_RDONLY); + + if (fd < 0) { + printf("\tMPU-6000: open fail\n"); + return ERROR; + } + + // /* wait at least 100ms, sensor should have data after no more than 20ms */ + // usleep(100000); + + // /* read data - expect samples */ + // ret = read(fd, buf, sizeof(buf)); + + // if (ret != sizeof(buf)) { + // printf("\tMPU-6000: read1 fail (%d)\n", ret); + // return ERROR; + + // } else { + // printf("\tMPU-6000 values: acc: x:%d\ty:%d\tz:%d\tgyro: r:%d\tp:%d\ty:%d\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + // } + + // /* wait at least 10ms, sensor should have data after no more than 2ms */ + // usleep(100000); + + // ret = read(fd, buf, sizeof(buf)); + + // if (ret != sizeof(buf)) { + // printf("\tMPU-6000: read2 fail (%d)\n", ret); + // return ERROR; + + // } else { + // printf("\tMPU-6000 values: acc: x:%d\ty:%d\tz:%d\tgyro: r:%d\tp:%d\ty:%d\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + // } + + /* XXX more tests here */ + + /* Let user know everything is ok */ + printf("\tOK: MPU-6000 passed all tests successfully\n"); + + return OK; +} + +static int +ms5611(int argc, char *argv[]) +{ + printf("\tMS5611: test start\n"); + fflush(stdout); + + int fd; + float buf[3] = {0.0f, 0.0f, 0.0f}; + int ret; + + fd = open("/dev/ms5611", O_RDONLY); + + if (fd < 0) { + printf("\tMS5611: open fail\n"); + return ERROR; + } + + for (int i = 0; i < 5; i++) { + /* read data - expect samples */ + ret = read(fd, buf, sizeof(buf)); + + if (ret != sizeof(buf)) { + if ((uint8_t)ret == -EAGAIN || (uint8_t)ret == -EINPROGRESS || i < 3) { + /* waiting for device to become ready, this is not an error */ + } else { + printf("\tMS5611: read fail (%d)\n", ret); + close(fd); + return ERROR; + } + + } else { + + /* hack for float printing */ + int32_t pressure_int = buf[0]; + int32_t altitude_int = buf[1]; + int32_t temperature_int = buf[2]; + + printf("\tMS5611: pressure:%d.%03d mbar - altitude: %d.%02d meters - temp:%d.%02d deg celcius\n", pressure_int, (int)(buf[0] * 1000 - pressure_int * 1000), altitude_int, (int)(buf[1] * 100 - altitude_int * 100), temperature_int, (int)(buf[2] * 100 - temperature_int * 100)); + } + + /* wait at least 10ms, sensor should have data after no more than 6.5ms */ + usleep(10000); + } + + close(fd); + + /* Let user know everything is ok */ + printf("\tOK: MS5611 passed all tests successfully\n"); + + return OK; +} + +static int +hmc5883l(int argc, char *argv[]) +{ + printf("\tHMC5883L: test start\n"); + fflush(stdout); + + int fd; + int16_t buf[3] = {0, 0, 0}; + int ret; + + fd = open("/dev/hmc5883l", O_RDONLY); + + if (fd < 0) { + printf("\tHMC5883L: open fail\n"); + return ERROR; + } + + int i; + + for (i = 0; i < 5; i++) { + /* wait at least 7ms, sensor should have data after no more than 6.5ms */ + usleep(7000); + + /* read data - expect samples */ + ret = read(fd, buf, sizeof(buf)); + + if (ret != sizeof(buf)) { + printf("\tHMC5883L: read1 fail (%d) values: x:%d\ty:%d\tz:%d\n", ret, buf[0], buf[1], buf[2]); + close(fd); + return ERROR; + + } else { + printf("\tHMC5883L: x:%d\ty:%d\tz:%d\n", buf[0], buf[1], buf[2]); + } + } + + close(fd); + + /* Let user know everything is ok */ + printf("\tOK: HMC5883L passed all tests successfully\n"); + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_sensors + ****************************************************************************/ + +int test_sensors(int argc, char *argv[]) +{ + unsigned i; + + printf("Running sensors tests:\n\n"); + fflush(stdout); + + int ret = OK; + + for (i = 0; sensors[i].name; i++) { + printf(" sensor: %s\n", sensors[i].name); + + /* Flush and leave enough time for the flush to become effective */ + fflush(stdout); + usleep(50000); + /* Test the sensor - if the tests crash at this point, the right sensor name has been printed */ + + ret += sensors[i].test(argc, argv); + } + + return ret; +} diff --git a/apps/px4/tests/test_servo.c b/apps/px4/tests/test_servo.c new file mode 100644 index 0000000000..f95760ca8e --- /dev/null +++ b/apps/px4/tests/test_servo.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * px4/sensors/test_hrt.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "tests.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_servo + ****************************************************************************/ + +int test_servo(int argc, char *argv[]) +{ + int fd, result; + servo_position_t data[PWM_OUTPUT_MAX_CHANNELS]; + servo_position_t pos; + + fd = open(PWM_OUTPUT_DEVICE_PATH, O_RDWR); + + if (fd < 0) { + printf("failed opening /dev/pwm_servo\n"); + goto out; + } + + result = read(fd, &data, sizeof(data)); + + if (result != sizeof(data)) { + printf("failed bulk-reading channel values\n"); + goto out; + } + + printf("Servo readback, pairs of values should match defaults\n"); + + for (unsigned i = 0; i < PWM_OUTPUT_MAX_CHANNELS; i++) { + result = ioctl(fd, PWM_SERVO_GET(i), (unsigned long)&pos); + + if (result < 0) { + printf("failed reading channel %u\n", i); + goto out; + } + + printf("%u: %u %u\n", i, pos, data[i]); + + } + + printf("Servos arming at default values\n"); + result = ioctl(fd, PWM_SERVO_ARM, 0); + usleep(5000000); + printf("Advancing channel 0 to 1500\n"); + result = ioctl(fd, PWM_SERVO_SET(0), 1500); +out: + return 0; +} diff --git a/apps/px4/tests/test_sleep.c b/apps/px4/tests/test_sleep.c new file mode 100644 index 0000000000..911a9c2e19 --- /dev/null +++ b/apps/px4/tests/test_sleep.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * px4/sensors/test_gpio.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "tests.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_sleep + ****************************************************************************/ + +int test_sleep(int argc, char *argv[]) +{ + unsigned int nsleeps = 100; + printf("\t %d 100ms sleeps\n", nsleeps); + fflush(stdout); + + for (int i = 0; i < nsleeps; i++) { + usleep(100000); + //printf("\ttick\n"); + } + + printf("\t Sleep test successful.\n"); + + return OK; +} diff --git a/apps/px4/tests/test_time.c b/apps/px4/tests/test_time.c new file mode 100644 index 0000000000..c128c73a39 --- /dev/null +++ b/apps/px4/tests/test_time.c @@ -0,0 +1,160 @@ +/**************************************************************************** + * px4/tests/test_time.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "tests.h" + +#include +#include +#include + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* emulate hrt_absolute_time using the cycle counter */ +static hrt_abstime +cycletime(void) +{ + static uint64_t basetime; + static uint32_t lasttime; + uint32_t cycles; + + cycles = *(unsigned long *)0xe0001004; + + if (cycles < lasttime) + basetime += 0x100000000ULL; + + lasttime = cycles; + + return (basetime + cycles) / 168; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_led + ****************************************************************************/ + +int test_time(int argc, char *argv[]) +{ + hrt_abstime h, c; + int64_t lowdelta, maxdelta = 0; + int64_t delta, deltadelta; + + /* enable the cycle counter */ + (*(unsigned long *)0xe000edfc) |= (1 << 24); /* DEMCR |= DEMCR_TRCENA */ + (*(unsigned long *)0xe0001000) |= 1; /* DWT_CTRL |= DWT_CYCCNT_ENA */ + + /* get an average delta between the two clocks - this should stay roughly the same */ + delta = 0; + + for (unsigned i = 0; i < 100; i++) { + uint32_t flags = irqsave(); + + h = hrt_absolute_time(); + c = cycletime(); + + irqrestore(flags); + + delta += h - c; + } + + lowdelta = abs(delta / 100); + + /* loop checking the time */ + for (unsigned i = 0; i < 100000; i++) { + + usleep(rand() * 10); + + uint32_t flags = irqsave(); + + c = cycletime(); + h = hrt_absolute_time(); + + irqrestore(flags); + + delta = abs(h - c); + deltadelta = abs(delta - lowdelta); + + if (deltadelta > maxdelta) + maxdelta = deltadelta; + + if (deltadelta > 1000) + fprintf(stderr, "h %llu c %llu d %lld\n", h, c, delta - lowdelta); + } + + printf("Maximum jitter %lld\n", maxdelta); + + return 0; +} diff --git a/apps/px4/tests/test_uart_baudchange.c b/apps/px4/tests/test_uart_baudchange.c new file mode 100644 index 0000000000..06965bd3d5 --- /dev/null +++ b/apps/px4/tests/test_uart_baudchange.c @@ -0,0 +1,160 @@ +/**************************************************************************** + * px4/sensors/test_gpio.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "tests.h" + +#include +#include + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_led + ****************************************************************************/ + +int test_uart_baudchange(int argc, char *argv[]) +{ + int uart2_nwrite = 0; + + /* assuming NuttShell is on UART1 (/dev/ttyS0) */ + int uart2 = open("/dev/ttyS1", O_RDWR | O_NONBLOCK | O_NOCTTY); // + + if (uart2 < 0) { + printf("ERROR opening UART2, aborting..\n"); + return uart2; + } + + struct termios uart2_config; + + struct termios uart2_config_original; + + int termios_state = 0; + +#define UART_BAUDRATE_RUNTIME_CONF +#ifdef UART_BAUDRATE_RUNTIME_CONF + + if ((termios_state = tcgetattr(uart2, &uart2_config)) < 0) { + printf("ERROR getting termios config for UART2: %d\n", termios_state); + exit(termios_state); + } + + memcpy(&uart2_config_original, &uart2_config, sizeof(struct termios)); + + /* Set baud rate */ + if (cfsetispeed(&uart2_config, B9600) < 0 || cfsetospeed(&uart2_config, B9600) < 0) { + printf("ERROR setting termios config for UART2: %d\n", termios_state); + exit(ERROR); + } + + if ((termios_state = tcsetattr(uart2, TCSANOW, &uart2_config)) < 0) { + printf("ERROR setting termios config for UART2\n"); + exit(termios_state); + } + + /* Set back to original settings */ + if ((termios_state = tcsetattr(uart2, TCSANOW, &uart2_config_original)) < 0) { + printf("ERROR setting termios config for UART2\n"); + exit(termios_state); + } + +#endif + + uint8_t sample_uart2[] = {'U', 'A', 'R', 'T', '2', ' ', '#', 0, '\n'}; + + int i, r; + + for (i = 0; i < 100; i++) { + /* uart2 -> */ + r = write(uart2, sample_uart2, sizeof(sample_uart2)); + + if (r > 0) + uart2_nwrite += r; + } + + close(uart2); + + printf("uart2_nwrite %d\n", uart2_nwrite); + + return OK; +} diff --git a/apps/px4/tests/test_uart_console.c b/apps/px4/tests/test_uart_console.c new file mode 100644 index 0000000000..de1249b8ca --- /dev/null +++ b/apps/px4/tests/test_uart_console.c @@ -0,0 +1,177 @@ +/**************************************************************************** + * px4/sensors/test_uart_console.c + * + * Copyright (C) 2012 Lorenz Meier. All rights reserved. + * Authors: Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "tests.h" + +#include +#include +#include + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_led + ****************************************************************************/ + +static void *receive_loop(void *arg) +{ + int uart_usb = open("/dev/ttyACM0", O_RDONLY | O_NOCTTY); + + while (1) { + char c; + read(uart_usb, &c, 1); + printf("%c", c); + fflush(stdout); + } + + return NULL; +} + +int test_uart_console(int argc, char *argv[]) +{ + /* assuming NuttShell is on UART1 (/dev/ttyS0) */ + // + int uart_usb = open("/dev/ttyACM0", O_WRONLY | O_NOCTTY); + + if (uart_usb < 0) { + printf("ERROR opening /dev/ttyACM0. Do you need to run sercon first? Aborting..\n"); + return uart_usb; + } + + uint8_t sample_uart_usb[] = {'S', 'A', 'M', 'P', 'L', 'E', ' ', '\n'}; + + pthread_t receive_thread; + + pthread_create(&receive_thread, NULL, receive_loop, NULL); + + //wait for threads to complete: + pthread_join(receive_thread, NULL); + + for (int i = 0; i < 30; i++) { + write(uart_usb, sample_uart_usb, sizeof(sample_uart_usb)); + printf("."); + fflush(stdout); + sleep(1); + } + +// uint64_t start_time = hrt_absolute_time(); +// +//// while (true) +// for (int i = 0; i < 1000; i++) +// { +// //write(uart_usb, sample_uart_usb, sizeof(sample_uart_usb)); +// int nread = 0; +// char c; +// do { +// nread = read(uart_usb, &c, 1); +// if (nread > 0) +// { +// printf("%c", c); +// } +// } while (nread > 0); +// +// do { +// nread = read(uart_console, &c, 1); +// if (nread > 0) +// { +// if (c == 0x03) +// { +// close(uart_usb); +// close(uart_console); +// exit(OK); +// } +// else +// { +// write(uart_usb, &c, 1); +// } +// } +// } while (nread > 0); +// usleep(10000); +// } +// +// int interval = hrt_absolute_time() - start_time; + + close(uart_usb); +// close(uart_console); + + return 0; +} diff --git a/apps/px4/tests/test_uart_loopback.c b/apps/px4/tests/test_uart_loopback.c new file mode 100644 index 0000000000..b2e07df1c0 --- /dev/null +++ b/apps/px4/tests/test_uart_loopback.c @@ -0,0 +1,197 @@ +/**************************************************************************** + * px4/sensors/test_gpio.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "tests.h" + +#include +#include + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_led + ****************************************************************************/ + +int test_uart_loopback(int argc, char *argv[]) +{ + + int uart5_nread = 0; + int uart2_nread = 0; + int uart5_nwrite = 0; + int uart2_nwrite = 0; + + int uart1 = open("/dev/ttyS0", O_RDWR | O_NOCTTY); // + + /* assuming NuttShell is on UART1 (/dev/ttyS0) */ + int uart2 = open("/dev/ttyS1", O_RDWR | O_NONBLOCK | O_NOCTTY); // + int uart5 = open("/dev/ttyS2", O_RDWR | O_NONBLOCK | O_NOCTTY); // + + if (uart2 < 0) { + printf("ERROR opening UART2, aborting..\n"); + return uart2; + } + + if (uart5 < 0) { + printf("ERROR opening UART5, aborting..\n"); + exit(uart5); + } + + uint8_t sample_uart1[] = {'C', 'O', 'U', 'N', 'T', ' ', '#', '\n'}; + uint8_t sample_uart2[] = {'C', 'O', 'U', 'N', 'T', ' ', '#', 0}; + uint8_t sample_uart5[] = {'C', 'O', 'U', 'N', 'T', ' ', '#', 0}; + + int i, r; + + for (i = 0; i < 1000; i++) { +// printf("TEST #%d\n",i); + write(uart1, sample_uart1, sizeof(sample_uart1)); + + /* uart2 -> uart5 */ + r = write(uart2, sample_uart2, sizeof(sample_uart2)); + + if (r > 0) + uart2_nwrite += r; + +// printf("TEST #%d\n",i); + write(uart1, sample_uart1, sizeof(sample_uart1)); + + /* uart2 -> uart5 */ + r = write(uart5, sample_uart5, sizeof(sample_uart5)); + + if (r > 0) + uart5_nwrite += r; + +// printf("TEST #%d\n",i); + write(uart1, sample_uart1, sizeof(sample_uart1)); + + /* try to read back values */ + do { + r = read(uart5, sample_uart2, sizeof(sample_uart2)); + + if (r > 0) + uart5_nread += r; + } while (r > 0); + +// printf("TEST #%d\n",i); + write(uart1, sample_uart1, sizeof(sample_uart1)); + + do { + r = read(uart2, sample_uart5, sizeof(sample_uart5)); + + if (r > 0) + uart2_nread += r; + } while (r > 0); + +// printf("TEST #%d\n",i); +// write(uart1, sample_uart1, sizeof(sample_uart5)); + } + + for (i = 0; i < 200000; i++) { + + /* try to read back values */ + r = read(uart5, sample_uart2, sizeof(sample_uart2)); + + if (r > 0) + uart5_nread += r; + + r = read(uart2, sample_uart5, sizeof(sample_uart5)); + + if (r > 0) + uart2_nread += r; + + if ((uart2_nread == uart2_nwrite) && (uart5_nread == uart5_nwrite)) + break; + } + + + close(uart1); + close(uart2); + close(uart5); + + printf("uart2_nwrite %d\n", uart2_nwrite); + printf("uart5_nwrite %d\n", uart5_nwrite); + printf("uart2_nread %d\n", uart2_nread); + printf("uart5_nread %d\n", uart5_nread); + + + return 0; +} diff --git a/apps/px4/tests/test_uart_send.c b/apps/px4/tests/test_uart_send.c new file mode 100644 index 0000000000..83d205440d --- /dev/null +++ b/apps/px4/tests/test_uart_send.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * px4/sensors/test_gpio.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "tests.h" + +#include +#include +#include + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_led + ****************************************************************************/ + +int test_uart_send(int argc, char *argv[]) +{ + /* input handling */ + char *uart_name = "/dev/ttyS3"; + + if (argc > 1) uart_name = argv[1]; + + /* assuming NuttShell is on UART1 (/dev/ttyS0) */ + int test_uart = open(uart_name, O_RDWR | O_NONBLOCK | O_NOCTTY); // + + if (test_uart < 0) { + printf("ERROR opening UART %s, aborting..\n", uart_name); + return test_uart; + + } else { + printf("Writing to UART %s\n", uart_name); + } + + char sample_test_uart[25];// = {'S', 'A', 'M', 'P', 'L', 'E', ' ', '\n'}; + + int i, r, n; + + uint64_t start_time = hrt_absolute_time(); + + for (i = 0; i < 30000; i++) { + n = sprintf(sample_test_uart, "SAMPLE #%d\n", i); + write(test_uart, sample_test_uart, n); + } + + int interval = hrt_absolute_time() - start_time; + + int bytes = i * sizeof(sample_test_uart); + + printf("Wrote %d bytes in %d ms on UART %s\n", bytes, interval / 1000, uart_name); + + close(test_uart); + + return 0; +} diff --git a/apps/px4/tests/tests.h b/apps/px4/tests/tests.h new file mode 100644 index 0000000000..aa6dae1e09 --- /dev/null +++ b/apps/px4/tests/tests.h @@ -0,0 +1,99 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_PX4_TESTS_H +#define __APPS_PX4_TESTS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Debug ********************************************************************/ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_DEBUG +# define message(...) lib_rawprintf(__VA_ARGS__) +# define msgflush() +# else +# define message(...) printf(__VA_ARGS__) +# define msgflush() fflush(stdout) +# endif +#else +# ifdef CONFIG_DEBUG +# define message lib_rawprintf +# define msgflush() +# else +# define message printf +# define msgflush() fflush(stdout) +# endif +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +extern int test_sensors(int argc, char *argv[]); +extern int test_gpio(int argc, char *argv[]); +extern int test_hrt(int argc, char *argv[]); +extern int test_tone(int argc, char *argv[]); +extern int test_led(int argc, char *argv[]); +extern int test_adc(int argc, char *argv[]); +extern int test_int(int argc, char *argv[]); +extern int test_float(int argc, char *argv[]); +extern int test_eeproms(int argc, char *argv[]); +extern int test_ppm(int argc, char *argv[]); +extern int test_servo(int argc, char *argv[]); +extern int test_uart_loopback(int argc, char *argv[]); +extern int test_uart_baudchange(int argc, char *argv[]); +extern int test_cpuload(int argc, char *argv[]); +extern int test_uart_send(int argc, char *argv[]); +extern int test_sleep(int argc, char *argv[]); +extern int test_time(int argc, char *argv[]); +extern int test_uart_console(int argc, char *argv[]); +extern int test_jig_voltages(int argc, char *argv[]); + +#endif /* __APPS_PX4_TESTS_H */ diff --git a/apps/px4/tests/tests_main.c b/apps/px4/tests/tests_main.c new file mode 100644 index 0000000000..704b5a2372 --- /dev/null +++ b/apps/px4/tests/tests_main.c @@ -0,0 +1,339 @@ +/**************************************************************************** + * px4/sensors/tests_main.c + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include "tests.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int test_help(int argc, char *argv[]); +static int test_all(int argc, char *argv[]); +static int test_perf(int argc, char *argv[]); +static int test_jig(int argc, char *argv[]); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct { + const char *name; + int (* fn)(int argc, char *argv[]); + unsigned options; + int passed; +#define OPT_NOHELP (1<<0) +#define OPT_NOALLTEST (1<<1) +#define OPT_NOJIGTEST (1<<2) +} tests[] = { + {"led", test_led, 0, 0}, + {"int", test_int, 0, 0}, + {"float", test_float, 0, 0}, + {"sensors", test_sensors, 0, 0}, + {"gpio", test_gpio, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, + {"hrt", test_hrt, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, + {"ppm", test_ppm, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, + {"servo", test_servo, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, + {"adc", test_adc, OPT_NOJIGTEST, 0}, + {"jig_voltages", test_jig_voltages, OPT_NOALLTEST, 0}, + {"eeproms", test_eeproms, 0, 0}, + {"uart_loopback", test_uart_loopback, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, + {"uart_baudchange", test_uart_baudchange, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, + {"uart_send", test_uart_send, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, + {"uart_console", test_uart_console, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, + {"tone", test_tone, 0, 0}, + {"sleep", test_sleep, OPT_NOJIGTEST, 0}, + {"time", test_time, OPT_NOJIGTEST, 0}, + {"perf", test_perf, OPT_NOJIGTEST, 0}, + {"all", test_all, OPT_NOALLTEST | OPT_NOJIGTEST, 0}, + {"jig", test_jig, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, + {"help", test_help, OPT_NOALLTEST | OPT_NOHELP | OPT_NOJIGTEST, 0}, + {NULL, NULL, 0, 0} +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int +test_help(int argc, char *argv[]) +{ + unsigned i; + + printf("Available tests:\n"); + + for (i = 0; tests[i].name; i++) + printf(" %s\n", tests[i].name); + + return 0; +} + +static int +test_all(int argc, char *argv[]) +{ + unsigned i; + char *args[2] = {"all", NULL}; + unsigned int failcount = 0; + + printf("\nRunning all tests...\n\n"); + + for (i = 0; tests[i].name; i++) { + /* Only run tests that are not excluded */ + if (!(tests[i].options & OPT_NOALLTEST)) { + printf(" [%s] \t\t\tSTARTING TEST\n", tests[i].name); + fflush(stdout); + + /* Execute test */ + if (tests[i].fn(1, args) != 0) { + fprintf(stderr, " [%s] \t\t\tFAIL\n", tests[i].name); + fflush(stderr); + failcount++; + + } else { + tests[i].passed = 1; + printf(" [%s] \t\t\tPASS\n", tests[i].name); + fflush(stdout); + } + } + } + + /* Print summary */ + printf("\n"); + int j; + + for (j = 0; j < 40; j++) { + printf("-"); + } + + printf("\n\n"); + + printf(" T E S T S U M M A R Y\n\n"); + + if (failcount == 0) { + printf(" ______ __ __ ______ __ __ \n"); + printf(" /\\ __ \\ /\\ \\ /\\ \\ /\\ __ \\ /\\ \\/ / \n"); + printf(" \\ \\ __ \\ \\ \\ \\____ \\ \\ \\____ \\ \\ \\/\\ \\ \\ \\ _\"-. \n"); + printf(" \\ \\_\\ \\_\\ \\ \\_____\\ \\ \\_____\\ \\ \\_____\\ \\ \\_\\ \\_\\ \n"); + printf(" \\/_/\\/_/ \\/_____/ \\/_____/ \\/_____/ \\/_/\\/_/ \n"); + printf("\n"); + printf(" All tests passed (%d of %d)\n", i, i); + + } else { + printf(" ______ ______ __ __ \n"); + printf(" /\\ ___\\ /\\ __ \\ /\\ \\ /\\ \\ \n"); + printf(" \\ \\ __\\ \\ \\ __ \\ \\ \\ \\ \\ \\ \\__\n"); + printf(" \\ \\_\\ \\ \\_\\ \\_\\ \\ \\_\\ \\ \\_____\\ \n"); + printf(" \\/_/ \\/_/\\/_/ \\/_/ \\/_____/ \n"); + printf("\n"); + printf(" Some tests failed (%d of %d)\n", failcount, i); + } + + printf("\n"); + + /* Print failed tests */ + if (failcount > 0) printf(" Failed tests:\n\n"); + + int k; + + for (k = 0; k < i; k++) { + if ((tests[k].passed == 0) && !(tests[k].options & OPT_NOALLTEST)) { + printf(" [%s] to obtain details, please re-run with\n\t nsh> tests %s\n\n", tests[k].name, tests[k].name); + } + } + + fflush(stdout); + + return 0; +} + +static int +test_perf(int argc, char *argv[]) +{ + perf_counter_t cc, ec; + + cc = perf_alloc(PC_COUNT, "test_count"); + ec = perf_alloc(PC_ELAPSED, "test_elapsed"); + + if ((cc == NULL) || (ec == NULL)) { + printf("perf: counter alloc failed\n"); + return 1; + } + + perf_begin(ec); + perf_count(cc); + perf_count(cc); + perf_count(cc); + perf_count(cc); + printf("perf: expect count of 4\n"); + perf_print_counter(cc); + perf_end(ec); + printf("perf: expect count of 1\n"); + perf_print_counter(ec); + printf("perf: expect at least two counters\n"); + perf_print_all(); + + perf_free(cc); + perf_free(ec); +} + +test_jig(int argc, char *argv[]) +{ + unsigned i; + char *args[2] = {"jig", NULL}; + unsigned int failcount = 0; + + printf("\nRunning all tests...\n\n"); + for (i = 0; tests[i].name; i++) { + /* Only run tests that are not excluded */ + if (!(tests[i].options & OPT_NOJIGTEST)) { + printf(" [%s] \t\t\tSTARTING TEST\n", tests[i].name); + fflush(stdout); + /* Execute test */ + if (tests[i].fn(1, args) != 0) { + fprintf(stderr, " [%s] \t\t\tFAIL\n", tests[i].name); + fflush(stderr); + failcount++; + } else { + tests[i].passed = 1; + printf(" [%s] \t\t\tPASS\n", tests[i].name); + fflush(stdout); + } + } + } + + /* Print summary */ + printf("\n"); + int j; + for (j = 0; j < 40; j++) + { + printf("-"); + } + printf("\n\n"); + + printf(" T E S T S U M M A R Y\n\n"); + if (failcount == 0) { + printf(" ______ __ __ ______ __ __ \n"); + printf(" /\\ __ \\ /\\ \\ /\\ \\ /\\ __ \\ /\\ \\/ / \n"); + printf(" \\ \\ __ \\ \\ \\ \\____ \\ \\ \\____ \\ \\ \\/\\ \\ \\ \\ _\"-. \n"); + printf(" \\ \\_\\ \\_\\ \\ \\_____\\ \\ \\_____\\ \\ \\_____\\ \\ \\_\\ \\_\\ \n"); + printf(" \\/_/\\/_/ \\/_____/ \\/_____/ \\/_____/ \\/_/\\/_/ \n"); + printf("\n"); + printf(" All tests passed (%d of %d)\n", i, i); + } else { + printf(" ______ ______ __ __ \n"); + printf(" /\\ ___\\ /\\ __ \\ /\\ \\ /\\ \\ \n"); + printf(" \\ \\ __\\ \\ \\ __ \\ \\ \\ \\ \\ \\ \\__\n"); + printf(" \\ \\_\\ \\ \\_\\ \\_\\ \\ \\_\\ \\ \\_____\\ \n"); + printf(" \\/_/ \\/_/\\/_/ \\/_/ \\/_____/ \n"); + printf("\n"); + printf(" Some tests failed (%d of %d)\n", failcount, i); + } + printf("\n"); + + /* Print failed tests */ + if (failcount > 0) printf(" Failed tests:\n\n"); + int k; + for (k = 0; k < i; k++) + { + if ((tests[k].passed == 0) && !(tests[k].options & OPT_NOJIGTEST)) + { + printf(" [%s] to obtain details, please re-run with\n\t nsh> tests %s\n\n", tests[k].name, tests[k].name); + } + } + fflush(stdout); + + return 0; +} + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +__EXPORT int tests_main(int argc, char *argv[]); + +/**************************************************************************** + * Name: tests_main + ****************************************************************************/ + +int tests_main(int argc, char *argv[]) +{ + unsigned i; + + if (argc < 2) { + printf("tests: missing test name - 'tests help' for a list of tests\n"); + return 1; + } + + for (i = 0; tests[i].name; i++) { + if (!strcmp(tests[i].name, argv[1])) + return tests[i].fn(argc - 1, argv + 1); + } + + printf("tests: no test called '%s' - 'tests help' for a list of tests\n", argv[1]); + return ERROR; +} diff --git a/apps/px4io/Makefile b/apps/px4io/Makefile new file mode 100644 index 0000000000..06be90a0ce --- /dev/null +++ b/apps/px4io/Makefile @@ -0,0 +1,38 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Build the px4io application. +# + +include $(APPDIR)/mk/app.mk diff --git a/apps/px4io/comms.c b/apps/px4io/comms.c new file mode 100644 index 0000000000..19802bf4f3 --- /dev/null +++ b/apps/px4io/comms.c @@ -0,0 +1,136 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file FMU communication for the PX4IO module. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "px4io.h" + +#define FMU_MIN_REPORT_INTERVAL 5000 /* 5ms */ +#define FMU_MAX_REPORT_INTERVAL 100000 /* 100ms */ + +static int fmu_fd; +static hx_stream_t stream; + +static struct px4io_report report; + +static void comms_handle_frame(void *arg, const void *buffer, size_t length); + +void +comms_init(void) +{ + fmu_fd = open("/dev/ttyS1", O_RDWR | O_NONBLOCK); + if (fmu_fd < 0) + lib_lowprintf("COMMS: fmu open failed %d\n", errno); + + stream = hx_stream_init(fmu_fd, comms_handle_frame, NULL); + + report.i2f_magic = I2F_MAGIC; +} + +void +comms_check(void) +{ + static hrt_abstime last_report_time; + hrt_abstime now, delta; + uint8_t c; + + /* should we send a report to the FMU? */ + now = hrt_absolute_time(); + delta = now - last_report_time; + if ((delta > FMU_MIN_REPORT_INTERVAL) && + (system_state.fmu_report_due || (delta > FMU_MAX_REPORT_INTERVAL))) { + + system_state.fmu_report_due = false; + last_report_time = now; + + /* populate the report */ + for (unsigned i = 0; i < system_state.rc_channels; i++) + report.rc_channel[i] = system_state.rc_channel_data[i]; + report.channel_count = system_state.rc_channels; + report.armed = system_state.armed; + + /* and send it */ + hx_stream_send(stream, &report, sizeof(report)); + } + + /* feed any received bytes to the HDLC receive engine */ + while (read(fmu_fd, &c, 1) == 1) + hx_stream_rx(stream, c); +} + +static void +comms_handle_frame(void *arg, const void *buffer, size_t length) +{ + struct px4io_command *cmd; + + /* make sure it's what we are expecting */ + if (length != sizeof(struct px4io_command)) + return; + + cmd = (struct px4io_command *)buffer; + + /* fetch new PWM output values */ + for (unsigned i = 0; i < PX4IO_OUTPUT_CHANNELS; i++) + system_state.fmu_channel_data[i] = cmd->servo_command[i]; + + system_state.arm_ok = cmd->arm_ok; + system_state.mixer_use_fmu = true; + system_state.fmu_data_received = true; + + /* handle changes signalled by FMU */ + if (!system_state.arm_ok && system_state.armed) + system_state.armed = false; + + /* XXX do relay changes here */ + for (unsigned i = 0; i < PX4IO_RELAY_CHANNELS; i++) + system_state.relays[i] = cmd->relay_state[i]; +} diff --git a/apps/px4io/mixer.c b/apps/px4io/mixer.c new file mode 100644 index 0000000000..9dc1fdcba7 --- /dev/null +++ b/apps/px4io/mixer.c @@ -0,0 +1,245 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Control channel input/output mixer and failsafe. + */ + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "px4io.h" + +#ifdef CONFIG_DISABLE_MQUEUE +# error Mixer requires message queues - set CONFIG_DISABLE_MQUEUE=n and try again +#endif + +static mqd_t input_queue; + +/* + * Count of periodic calls in which we have no data. + */ +static unsigned mixer_input_drops; +#define MIXER_INPUT_DROP_LIMIT 10 + +/* + * Count of periodic calls in which we have no FMU input. + */ +static unsigned fmu_input_drops; +#define FMU_INPUT_DROP_LIMIT 10 + +/* + * HRT periodic call used to check for control input data. + */ +static struct hrt_call mixer_input_call; + +/* + * Mixer periodic tick. + */ +static void mixer_tick(void *arg); + +/* + * Collect RC input data from the controller source(s). + */ +static void mixer_get_rc_input(void); + +/* + * Update a mixer based on the current control signals. + */ +static void mixer_update(int mixer, uint16_t *inputs, int input_count); + +/* servo driver handle */ +int mixer_servo_fd; + +/* current servo arm/disarm state */ +bool mixer_servos_armed; + +/* + * Each mixer consumes a set of inputs and produces a single output. + */ +struct mixer { + uint16_t current_value; + /* XXX more config here */ +} mixers[IO_SERVO_COUNT]; + +int +mixer_init(const char *mq_name) +{ + /* open the control input queue; this should always exist */ + input_queue = mq_open(mq_name, O_RDONLY | O_NONBLOCK); + ASSERTCODE((input_queue >= 0), A_INPUTQ_OPEN_FAIL); + + /* open the servo driver */ + mixer_servo_fd = open("/dev/pwm_servo", O_WRONLY); + ASSERTCODE((mixer_servo_fd >= 0), A_SERVO_OPEN_FAIL); + + /* look for control data at 50Hz */ + hrt_call_every(&mixer_input_call, 1000, 20000, mixer_tick, NULL); + + return 0; +} + +static void +mixer_tick(void *arg) +{ + uint16_t *control_values; + int control_count; + int i; + bool should_arm; + + /* + * Start by looking for R/C control inputs. + * This updates system_state with any control inputs received. + */ + mixer_get_rc_input(); + + /* + * Decide which set of inputs we're using. + */ + if (system_state.mixer_use_fmu) { + /* we have recent control data from the FMU */ + control_count = PX4IO_OUTPUT_CHANNELS; + control_values = &system_state.fmu_channel_data[0]; + + /* check that we are receiving fresh data from the FMU */ + if (!system_state.fmu_data_received) { + fmu_input_drops++; + + /* too many frames without FMU input, time to go to failsafe */ + if (fmu_input_drops >= FMU_INPUT_DROP_LIMIT) { + system_state.mixer_use_fmu = false; + } + } else { + fmu_input_drops = 0; + system_state.fmu_data_received = false; + } + + } else if (system_state.rc_channels > 0) { + /* we have control data from an R/C input */ + control_count = system_state.rc_channels; + control_values = &system_state.rc_channel_data[0]; + + } else { + /* we have no control input */ + control_count = 0; + } + + /* + * Tickle each mixer, if we have control data. + */ + if (control_count > 0) { + for (i = 0; i < PX4IO_OUTPUT_CHANNELS; i++) { + mixer_update(i, control_values, control_count); + + /* + * If we are armed, update the servo output. + */ + if (system_state.armed) + ioctl(mixer_servo_fd, PWM_SERVO_SET(i), mixers[i].current_value); + } + + } + + /* + * Decide whether the servos should be armed right now. + */ + should_arm = system_state.armed && (control_count > 0); + if (should_arm && !mixer_servos_armed) { + /* need to arm, but not armed */ + ioctl(mixer_servo_fd, PWM_SERVO_ARM, 0); + mixer_servos_armed = true; + + } else if (!should_arm && mixer_servos_armed) { + /* armed but need to disarm*/ + ioctl(mixer_servo_fd, PWM_SERVO_DISARM, 0); + mixer_servos_armed = false; + } +} + +static void +mixer_get_rc_input(void) +{ + ssize_t len; + + /* + * Pull channel data from the message queue into the system state structure. + * + */ + len = mq_receive(input_queue, &system_state.rc_channel_data, sizeof(system_state.rc_channel_data), NULL); + + /* + * If we have data, update the count and status. + */ + if (len > 0) { + system_state.rc_channels = len / sizeof(system_state.rc_channel_data[0]); + mixer_input_drops = 0; + + system_state.fmu_report_due = true; + } else { + /* + * No data; count the 'frame drops' and once we hit the limit + * assume that we have lost input. + */ + if (mixer_input_drops < MIXER_INPUT_DROP_LIMIT) { + mixer_input_drops++; + + /* if we hit the limit, stop pretending we have input and let the FMU know */ + if (mixer_input_drops == MIXER_INPUT_DROP_LIMIT) { + system_state.rc_channels = 0; + system_state.fmu_report_due = true; + } + } + } +} + +static void +mixer_update(int mixer, uint16_t *inputs, int input_count) +{ + /* simple passthrough for now */ + if (mixer < input_count) { + mixers[mixer].current_value = inputs[mixer]; + } else { + mixers[mixer].current_value = 0; + } +} diff --git a/apps/px4io/protocol.h b/apps/px4io/protocol.h new file mode 100644 index 0000000000..92558a61df --- /dev/null +++ b/apps/px4io/protocol.h @@ -0,0 +1,69 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file PX4FMU <-> PX4IO messaging protocol. + * + * This initial version of the protocol is very simple; each side transmits a + * complete update with each frame. This avoids the sending of many small + * messages and the corresponding complexity involved. + */ + +/* + * XXX MUST BE KEPT IN SYNC WITH THE VERSION IN PX4FMU UNTIL + * TREES ARE MERGED. + */ + +#define PX4IO_OUTPUT_CHANNELS 8 +#define PX4IO_INPUT_CHANNELS 12 +#define PX4IO_RELAY_CHANNELS 2 + +/* command from FMU to IO */ +struct px4io_command { + uint16_t f2i_magic; +#define F2I_MAGIC 0x636d + + uint16_t servo_command[PX4IO_OUTPUT_CHANNELS]; + bool relay_state[PX4IO_RELAY_CHANNELS]; + bool arm_ok; +} __attribute__((packed)); + +/* report from IO to FMU */ +struct px4io_report { + uint16_t i2f_magic; +#define I2F_MAGIC 0x7570 + + uint16_t rc_channel[PX4IO_INPUT_CHANNELS]; + bool armed; + uint8_t channel_count; +} __attribute__((packed)); diff --git a/apps/px4io/px4io.c b/apps/px4io/px4io.c new file mode 100644 index 0000000000..44b62f3f97 --- /dev/null +++ b/apps/px4io/px4io.c @@ -0,0 +1,183 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Top-level logic for the PX4IO module. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "px4io.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +__EXPORT int user_start(int argc, char *argv[]); + +/**************************************************************************** + * user_start + ****************************************************************************/ + +struct sys_state_s system_state; +int gpio_fd; + +static const char cursor[] = {'|', '/', '-', '\\'}; + +static const char *rc_input_mq_name = "rc_input"; + +static struct hrt_call timer_tick_call; +volatile int timers[TIMER_NUM_TIMERS]; +static void timer_tick(void *arg); + +int user_start(int argc, char *argv[]) +{ + int cycle = 0; + bool heartbeat = false; + bool failsafe = false; + + /* Do board init */ + (void)up_boardinitialize(); + + /* print some startup info */ + lib_lowprintf("\nPX4IO: starting\n"); + struct mallinfo minfo = mallinfo(); + lib_lowprintf("free %u largest %u\n", minfo.mxordblk, minfo.fordblks); + + /* start the software timer service */ + hrt_call_every(&timer_tick_call, 1000, 1000, timer_tick, NULL); + + /* Open the GPIO driver so we can do LEDs and the like. */ + gpio_fd = open("/dev/gpio", 0); + ASSERTCODE((gpio_fd >= 0), A_GPIO_OPEN_FAIL); + + /* default all the LEDs to off while we start */ + LED_AMBER(heartbeat); + LED_BLUE(failsafe); + LED_SAFETY(false); + + /* turn on servo power */ + POWER_SERVO(true); + + /* configure the PPM input driver */ + ppm_input_init(rc_input_mq_name); + + /* start the mixer */ + mixer_init(rc_input_mq_name); + + /* start the safety switch handler */ + safety_init(); + + /* init the FMU link */ + comms_init(); + + /* set up some timers for the main loop */ + timers[TIMER_BLINK_AMBER] = 250; /* heartbeat blink @ 2Hz */ + timers[TIMER_STATUS_PRINT] = 1000; /* print status message @ 1Hz */ + + /* + * Main loop servicing communication with FMU + */ + while(true) { + + /* check for communication from FMU, send updates */ + comms_check(); + + /* blink the heartbeat LED */ + if (timers[TIMER_BLINK_AMBER] == 0) { + timers[TIMER_BLINK_AMBER] = 250; + LED_AMBER((heartbeat = !heartbeat)); + } + + /* blink the failsafe LED if we don't have FMU input */ + if (!system_state.mixer_use_fmu) { + if (timers[TIMER_BLINK_BLUE] == 0) { + timers[TIMER_BLINK_BLUE] = 125; + LED_BLUE((failsafe = !failsafe)); + } + } else { + LED_BLUE((failsafe = false)); + } + + /* print some simple status */ + if (timers[TIMER_STATUS_PRINT] == 0) { + timers[TIMER_STATUS_PRINT] = 1000; + lib_lowprintf("%c %s | %s | %s | C=%d \r", + cursor[cycle++ & 3], + (system_state.armed ? "ARMED" : "SAFE"), + (system_state.rc_channels ? "RC OK" : "NO RC"), + (system_state.mixer_use_fmu ? "FMU OK" : "NO FMU"), + system_state.rc_channels + ); + } + + } + + /* Should never reach here */ + return ERROR; +} + +static void +timer_tick(void *arg) +{ + for (unsigned i = 0; i < TIMER_NUM_TIMERS; i++) + if (timers[i] > 0) + timers[i]--; +} diff --git a/apps/px4io/px4io.h b/apps/px4io/px4io.h new file mode 100644 index 0000000000..d90f7e36b2 --- /dev/null +++ b/apps/px4io/px4io.h @@ -0,0 +1,142 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + + /** + * @file General defines and structures for the PX4IO module firmware. + */ + +#include +#include "protocol.h" + +/* + * Constants and limits. + */ +#define MAX_CONTROL_CHANNELS 12 +#define IO_SERVO_COUNT 8 + +/* + * System state structure. + */ +struct sys_state_s +{ + + bool armed; /* actually armed */ + bool arm_ok; /* FMU says OK to arm */ + + /* + * Data from the remote control input(s) + */ + int rc_channels; + uint16_t rc_channel_data[PX4IO_INPUT_CHANNELS]; + + /* + * Control signals from FMU. + */ + uint16_t fmu_channel_data[PX4IO_OUTPUT_CHANNELS]; + + /* + * Relay controls + */ + bool relays[PX4IO_RELAY_CHANNELS]; + + /* + * If true, we are using the FMU controls. + */ + bool mixer_use_fmu; + + /* + * If true, state that should be reported to FMU has been updated. + */ + bool fmu_report_due; + + /* + * If true, new control data from the FMU has been received. + */ + bool fmu_data_received; +}; + +extern struct sys_state_s system_state; + +/* + * Software countdown timers. + * + * Each timer counts down to zero at one tick per ms. + */ +#define TIMER_BLINK_AMBER 0 +#define TIMER_BLINK_BLUE 1 +#define TIMER_STATUS_PRINT 2 +#define TIMER_SANITY 7 +#define TIMER_NUM_TIMERS 8 +extern volatile int timers[TIMER_NUM_TIMERS]; + +/* + * GPIO handling. + */ +extern int gpio_fd; + +#define POWER_SERVO(_s) ioctl(gpio_fd, GPIO_SET(GPIO_SERVO_POWER), (_s)) +#define POWER_ACC1(_s) ioctl(gpio_fd, GPIO_SET(GPIO_SERVO_ACC1), (_s)) +#define POWER_ACC2(_s) ioctl(gpio_fd, GPIO_SET(GPIO_SERVO_ACC2), (_s)) +#define POWER_RELAY1(_s) ioctl(gpio_fd, GPIO_SET(GPIO_RELAY1, (_s)) +#define POWER_RELAY2(_s) ioctl(gpio_fd, GPIO_SET(GPIO_RELAY2, (_s)) + +#define LED_AMBER(_s) ioctl(gpio_fd, GPIO_SET(GPIO_LED_AMBER), !(_s)) +#define LED_BLUE(_s) ioctl(gpio_fd, GPIO_SET(GPIO_LED_BLUE), !(_s)) +#define LED_SAFETY(_s) ioctl(gpio_fd, GPIO_SET(GPIO_LED_SAFETY), !(_s)) + +#define OVERCURRENT_ACC ioctl(gpio_fd, GPIO_GET(GPIO_ACC_OVERCURRENT), 0) +#define OVERCURRENT_SERVO ioctl(gpio_fd, GPIO_GET(GPIO_SERVO_OVERCURRENT), 0) +#define BUTTON_SAFETY ioctl(gpio_fd, GPIO_GET(GPIO_SAFETY_BUTTON), 0) + +/* + * Mixer + */ +extern int mixer_init(const char *mq_name); + +/* + * Safety switch/LED. + */ +extern void safety_init(void); + +/* + * FMU communications + */ +extern void comms_init(void); +extern void comms_check(void); + +/* + * Assertion codes + */ +#define A_GPIO_OPEN_FAIL 100 +#define A_SERVO_OPEN_FAIL 101 +#define A_INPUTQ_OPEN_FAIL 102 diff --git a/apps/px4io/safety.c b/apps/px4io/safety.c new file mode 100644 index 0000000000..895c33806f --- /dev/null +++ b/apps/px4io/safety.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + + /** + * @file Safety button logic. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "px4io.h" + +static struct hrt_call arming_call; + +/* + * Count the number of times in a row that we see the arming button + * held down. + */ +static unsigned arm_counter; +#define ARM_COUNTER_THRESHOLD 10 + +static bool safety_led_state; + +static void safety_check_button(void *arg); + +void +safety_init(void) +{ + /* arrange for the button handler to be called at 10Hz */ + hrt_call_every(&arming_call, 1000, 100000, safety_check_button, NULL); +} + +static void +safety_check_button(void *arg) +{ + /* + * Debounce the safety button, change state if it has been held for long enough. + * + * Ignore the button if FMU has not said it's OK to arm yet. + */ + if (BUTTON_SAFETY && system_state.arm_ok) { + if (arm_counter < ARM_COUNTER_THRESHOLD) { + arm_counter++; + } else if (arm_counter == ARM_COUNTER_THRESHOLD) { + /* change our armed state and notify the FMU */ + system_state.armed = !system_state.armed; + arm_counter++; + system_state.fmu_report_due = true; + } + } else { + arm_counter = 0; + } + + /* when armed, toggle the LED; when safe, leave it on */ + if (system_state.armed) { + safety_led_state = !safety_led_state; + } else { + safety_led_state = true; + } + LED_SAFETY(safety_led_state); +} diff --git a/apps/sdlog/Makefile b/apps/sdlog/Makefile new file mode 100644 index 0000000000..1e5abdb553 --- /dev/null +++ b/apps/sdlog/Makefile @@ -0,0 +1,44 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# sdlog Application +# + +APPNAME = sdlog +PRIORITY = SCHED_PRIORITY_DEFAULT - 1 +STACKSIZE = 3000 + +INCLUDES = $(TOPDIR)/../mavlink/include/mavlink + +include $(APPDIR)/mk/app.mk diff --git a/apps/sdlog/mfile.template b/apps/sdlog/mfile.template new file mode 100644 index 0000000000..0f7ebd0454 --- /dev/null +++ b/apps/sdlog/mfile.template @@ -0,0 +1,136 @@ +%% Import logfiles + +if (exist ('OCTAVE_VERSION', 'builtin')) + % Octave + graphics_toolkit ("fltk") +else + % Matlab +end + +% define log file and GPSs +logfileFolder = 'logfiles'; +fileName = 'all'; +fileEnding = 'px4log'; + +numberOfLogTypes = length(logTypes); + +path = [fileName,'.', fileEnding]; +fid = fopen(path, 'r'); + +% get file length +fseek(fid, 0,'eof'); +fileLength = ftell(fid); +fseek(fid, 0,'bof'); + +% get length of one block +blockLength = 4; % check: $$$$ +for i=1:numberOfLogTypes + blockLength = blockLength + logTypes{i}.type_bytes*logTypes{i}.number_of_array; +end + +% determine number of entries +entries = fileLength / blockLength; + + +% import data +offset = 0; +for i=1:numberOfLogTypes + + data.(genvarname(logTypes{i}.data)).(genvarname(logTypes{i}.variable_name)) = transpose(fread(fid,[logTypes{i}.number_of_array,entries],[num2str(logTypes{i}.number_of_array),'*',logTypes{i}.type_name,'=>',logTypes{i}.type_name],blockLength-logTypes{i}.type_bytes*logTypes{i}.number_of_array)); + offset = offset + logTypes{i}.type_bytes*logTypes{i}.number_of_array; + fseek(fid, offset,'bof'); + + progressPercentage = i/numberOfLogTypes*100; + fprintf('%3.0f%%',progressPercentage); +end + + +%% Plots + +figure +plot(data.sensors_raw.timestamp,data.sensors_raw.gyro_raw) + +figure +plot(data.sensors_raw.timestamp,data.sensors_raw.accelerometer_raw) + +%% Check for lost data + +% to detect lost frames (either when logging to sd card or if no new data is +% data is available for some time) +diff_counter = diff(data.sensors_raw.gyro_raw_counter); +figure +plot(diff_counter) + +% to detect how accurate the timing was +diff_timestamp = diff(data.sensors_raw.timestamp); + +figure +plot(diff_timestamp) + +%% Export to file for google earth + + +if(isfield(data.gps,'lat') && isfield(data.gps,'lon') && isfield(data.gps,'alt')) + + % extract coordinates and height where they are not zero + maskWhereNotZero = ((data.gps.lon ~= 0 & data.gps.lat ~= 0 ) & data.gps.alt ~= 0); + + % plot + figure + plot3(data.gps.lon(maskWhereNotZero),data.gps.lat(maskWhereNotZero),data.gps.alt(maskWhereNotZero)) + + + % create a kml file according to https://developers.google.com/kml/documentation/kml_tut + % also see https://support.google.com/earth/bin/answer.py?hl=en&answer=148072&topic=2376756&ctx=topic + + % open file and overwrite content + fileId = fopen('gps_path.kml','w+'); + + % define strings that should be written to file + fileStartDocumentString = ['PathsPath']; + + fileStyleString = ''; + + filePlacemarkString = 'Absolute ExtrudedTransparent blue wall with blue outlines#blueLinebluePoly11absolute'; + + fileEndPlacemarkString = ''; + fileEndDocumentString = ''; + + % start writing to file + fprintf(fileId,fileStartDocumentString); + + fprintf(fileId,fileStyleString); + fprintf(fileId,filePlacemarkString); + + + lonTemp = double(data.gps.lon(maskWhereNotZero))/1E7; + latTemp = double(data.gps.lat(maskWhereNotZero))/1E7; + altTemp = double(data.gps.alt(maskWhereNotZero))/1E3 + 100.0; % in order to see the lines above ground + + % write coordinates to file + for k=1:length(data.gps.lat(maskWhereNotZero)) + if(mod(k,10)==0) + fprintf(fileId,'%.10f,%.10f,%.10f\\n',lonTemp(k),latTemp(k),altTemp(k)); + end + end + + % write end placemark + fprintf(fileId,fileEndPlacemarkString); + + % write end of file + fprintf(fileId,fileEndDocumentString); + + % close file, it should now be readable in Google Earth using File -> Open + fclose(fileId); + +end + +if(isfield(data.position,'lat') && isfield(data.position,'lon') && isfield(data.position,'alt')) + + % extract coordinates and height where they are not zero + maskWhereNotZero = ((data.position.lon ~= 0 & data.position.lat ~= 0 ) & data.position.alt ~= 0); + + % plot + figure + plot3(data.position.lon(maskWhereNotZero),data.position.lat(maskWhereNotZero),data.position.alt(maskWhereNotZero)) +end diff --git a/apps/sdlog/sdlog.c b/apps/sdlog/sdlog.c new file mode 100644 index 0000000000..1b87aab77b --- /dev/null +++ b/apps/sdlog/sdlog.c @@ -0,0 +1,442 @@ +/**************************************************************************** + * examples/hello/main.c + * + * Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sdlog.h" +#include "sdlog_generated.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +__EXPORT int sdlog_main(int argc, char *argv[]); + +const char *src = "/dev/mmcsd0"; +const char *trgt = "/fs/microsd"; +const char *type = "vfat"; +const char *logfile_end = ".px4log"; +const char *mfile_end = ".m"; +char folder_path[64]; + +#define SDLOG_LED_PRIORITY LED_REQUEST_PRIORITY_MAX +#define BUFFER_BYTES 1000 // length of buffer +#define SAVE_EVERY_BYTES 2000 +#define MAX_MOUNT_TRIES 5 + +static void sdlog_sig_handler(int signo, siginfo_t *info, void *ucontext); // is executed when SIGUSR1 is received +bool sdlog_sigusr1_rcvd; // if this is set to true through SIGUSR1, sdlog will terminate + +static pthread_t logbuffer_thread; // thread to copy log values to the buffer +static void *logbuffer_loop(void *arg); + + +uint8_t *buffer_start; // always points to the very beginning +uint8_t *buffer_end; // always points to the very end +uint8_t *buffer_cursor_start; // points to the start of the current buffer +uint8_t *buffer_cursor_end; // points to the end of the current buffer +size_t buffer_bytes_used; // amount stored in the buffer at the moment + +uint32_t bytes_recv; // to count bytes received and written to the sdcard +uint32_t bytes_sent; // to count the bytes written to the buffer + +/**************************************************************************** + * user_start + ****************************************************************************/ + +int file_exist(const char *filename) +{ + struct stat buffer; + return (stat(filename, &buffer) == 0); +} + + +int sdlog_main(int argc, char *argv[]) +{ + // print text + printf("[sdlog] initialized\n"); + usleep(10000); + + sdlog_sigusr1_rcvd = false; + + led_request_t amber_on_request = {.led = LED_AMBER, .priority = SDLOG_LED_PRIORITY, .request_type = LED_REQUEST_ON}; + led_request_t amber_off_request = {.led = LED_AMBER, .priority = SDLOG_LED_PRIORITY, .request_type = LED_REQUEST_OFF}; + amber_on_request.pid = getpid(); + amber_off_request.pid = getpid(); + + /* signal handler to abort when low voltage occurs */ + struct sigaction act; + struct sigaction oact; + act.sa_sigaction = sdlog_sig_handler; + (void)sigemptyset(&act.sa_mask); + (void)sigaddset(&act.sa_mask, SIGUSR1); + (void)sigaction(SIGUSR1, &act, &oact); + + uint8_t mount_counter = 0; + + commander_state_machine_t current_system_state; + + global_data_send_led_request(&amber_on_request); + + if (file_exist(trgt) == 1) { + printf("[sdlog] Mount already available at %s\n", trgt); + global_data_send_led_request(&amber_off_request); + + } else { + printf("[sdlog] Mount not available yet, trying to mount...\n"); + + /* mostly the first mount fails, sometimes it helps to press the card onto the board! */ + while (mount(src, trgt, type, 0, "") != 0) { + /* abort if kill signal is received */ + if (sdlog_sigusr1_rcvd == true) { + return 0; + } + + //make sure were not airborne + global_data_trylock(&global_data_sys_status->access_conf); + current_system_state = global_data_sys_status->state_machine; + global_data_unlock(&global_data_sys_status->access_conf); + + if (current_system_state == SYSTEM_STATE_STANDBY || current_system_state == SYSTEM_STATE_PREFLIGHT || current_system_state == SYSTEM_STATE_GROUND_ERROR) { + usleep(1000000); + printf("[sdlog] ERROR: Failed to mount SD card (attempt %d of %d), reason: %s\n", mount_counter + 1, MAX_MOUNT_TRIES, strerror((int)*get_errno_ptr())); + global_data_send_led_request(&amber_off_request); + mount_counter++; + + } else { + printf("[sdlog] WARNING: Not mounting SD card in flight!\n"); + printf("[sdlog] ending now...\n"); + fflush(stdout); + return 0; + } + + if (mount_counter >= MAX_MOUNT_TRIES) { + printf("[sdlog] ERROR: SD card could not be mounted!\n"); + printf("[sdlog] ending now...\n"); + fflush(stdout); + return 0; + } + } + + printf("[sdlog] Mount created at %s...\n", trgt); + global_data_send_led_request(&amber_off_request); + } + + + /* make folder on sdcard */ + uint16_t foldernumber = 1; // start with folder 0001 + int mkdir_ret; + + /* look for the next folder that does not exist */ + while (foldernumber < MAX_NO_LOGFOLDER) { + /* set up file path: e.g. /mnt/sdcard/logfile0001.txt */ + sprintf(folder_path, "%s/session%04u", trgt, foldernumber); + mkdir_ret = mkdir(folder_path, S_IRWXU | S_IRWXG | S_IRWXO); + /* the result is -1 if the folder exists */ + + if (mkdir_ret == 0) { + /* folder does not exist */ + break; + + } else if (mkdir_ret == -1) { + /* folder exists already */ + foldernumber++; // to try next time + continue; + + } else { + printf("[sdlog] ERROR: Failed creating new folder: %s\n", strerror((int)*get_errno_ptr())); + return -1; + } + } + + if (foldernumber >= MAX_NO_LOGFOLDER) { + /* we should not end up here, either we have more than MAX_NO_LOGFOLDER on the SD card, or another problem */ + printf("[sdlog] ERROR: all %d possible folders exist already\n", MAX_NO_LOGFOLDER); + return -1; + } + + + /* write m-file for evaluation in Matlab */ + FILE *mfile; + char mfile_path[64] = ""; // string to hold the path to the mfile + const char *mfilename = "sdlog_eval"; + + sprintf(mfile_path, "%s/%s%s", folder_path, mfilename, mfile_end); + + if (NULL == (mfile = fopen(mfile_path, "w"))) { + printf("[sdlog] ERROR: opening %s failed: %s\n", mfile_path, strerror((int)*get_errno_ptr())); + } + + /* write file contents generated using updatesdlog.sh and mfile.template in nuttx/configs/px4fmu/include */ + fwrite(MFILE_STRING, sizeof(MFILE_STRING), 1, mfile); + fprintf(mfile, "\n"); + fclose(mfile); + printf("[sdlog] m-file written to sdcard\n"); + + + /* create the ringbuffer */ + uint8_t buffer[BUFFER_BYTES]; + buffer_start = buffer; + buffer_cursor_start = buffer; + buffer_cursor_end = buffer; + buffer_end = buffer + BUFFER_BYTES; + + /* create loop to write log data in a ringbuffer */ + pthread_attr_t logbuffer_attr; + pthread_attr_init(&logbuffer_attr); + pthread_attr_setstacksize(&logbuffer_attr, 2400); + pthread_create(&logbuffer_thread, &logbuffer_attr, logbuffer_loop, NULL); + + /* create logfile */ + FILE *logfile; + char logfile_path[64] = ""; // string to hold the path to the logfile + const char *logfilename = "all"; + + /* set up file path: e.g. /mnt/sdcard/session0001/gpslog.txt */ + sprintf(logfile_path, "%s/%s%s", folder_path, logfilename, logfile_end); + + + if (NULL == (logfile = fopen(logfile_path, "wb"))) { + printf("[sdlog] opening %s failed: %s\n", logfile_path, strerror((int)*get_errno_ptr())); + } + +// else +// { +// printf("[sdlog] opening %s was successful\n",logfile_path); +// } + + int logfile_no = fileno(logfile); + + bytes_recv = 0; /**< count all bytes that were received and written to the sdcard */ + size_t ret_write; /**< last amount written to sdcard */ + size_t target_write; /**< desired amount to write to sdcard */ + int ret_fsync; /**< return value of fsync() system call */ + int error_count = 0; /**< number of continous errors (one successful write resets it) */ + + /* Start logging */ + while (1) { + /* write as soon as content is in the buffer */ + while (buffer_bytes_used > 1) { + /* case where the data is not wrapped in the buffer */ + if (buffer_cursor_start < buffer_cursor_end) { + /* write all available data */ + target_write = (size_t)(buffer_cursor_end - buffer_cursor_start); + + if (0 <= (ret_write = fwrite(buffer_cursor_start, 1, target_write, logfile))) { + /* decrease the amount stored in the buffer, normally to 0 */ + buffer_bytes_used -= ret_write; + /* set new cursor position: wrap it in case it falls out of the buffer */ + buffer_cursor_start = buffer_start + (buffer_cursor_start - buffer_start + ret_write) % BUFFER_BYTES; + bytes_recv += ret_write; + error_count = 0; + + } else { + error_count++; + printf("[sdlog] ERROR: Write fail: %d of %d, %s\n", ret_write, target_write, strerror((int)*get_errno_ptr())); + } + } + + /* case where the content is wrapped around the buffer */ + else if (buffer_cursor_start > buffer_cursor_end) { + /* write data until the end of the buffer */ + target_write = (size_t)(buffer_end - buffer_cursor_start); + + if (0 <= (ret_write = fwrite(buffer_cursor_start, 1, target_write, logfile))) { + /* decrease the amount stored in the buffer */ + buffer_bytes_used -= ret_write; + /* set new cursor position: wrap it in case it falls out of the buffer */ + buffer_cursor_start = buffer_start + (buffer_cursor_start - buffer_start + ret_write) % BUFFER_BYTES; + bytes_recv += ret_write; + error_count = 0; + + } else { + error_count++; + printf("[sdlog] ERROR: Write fail: %d of %d, %s\n", ret_write, target_write, strerror((int)*get_errno_ptr())); + } + + /* write the rest of the data at the beginning of the buffer */ + target_write = (size_t)(buffer_cursor_end - buffer_start); + + if (0 <= (ret_write = fwrite(buffer_start, 1, target_write, logfile))) { + /* decrease the amount stored in the buffer, now normally to 0 */ + buffer_bytes_used -= ret_write; + /* set new cursor position: wrap it in case it falls out of the buffer */ + buffer_cursor_start = buffer_start + (buffer_cursor_start - buffer_start + ret_write) % BUFFER_BYTES; + bytes_recv += ret_write; + error_count = 0; + + } else { + error_count++; + printf("[sdlog] ERROR: write fail: %d of %d, %s\n", ret_write, target_write, strerror((int)*get_errno_ptr())); + } + + } else { + error_count++; + printf("[sdlog] ERROR: dropped data\n"); + } + +// if(bytes_recv>500000) +// { +// goto finished; +// } + } + + + /* save and exit if we received signal 1 or have a permanent error */ + if (sdlog_sigusr1_rcvd == true || error_count > 100) { + fclose(logfile); + umount(trgt); + + if (error_count > 100) { + return ERROR; + + } else { + return OK; + } + } + + /* save file from time to time */ + else if ((bytes_recv > 0 && bytes_recv % SAVE_EVERY_BYTES == 0)) { + if ((ret_fsync = fsync(logfile_no)) != OK) { + printf("[sdlog] ERROR: sync fail: #%d, %s\n", ret_fsync, strerror((int)*get_errno_ptr())); + } + } + +// else if(bytes_recv > 2*SAVE_EVERY_BYTES) +// { +// goto finished; +// } + /* sleep, not to block everybody else */ + usleep(1000); + } + +//finished: +// +// /* at the moment we should not end here */ +// fclose(logfile); +// printf("[sdlog] logfile saved\n"); +// umount(trgt); +// printf("[sdlog] ending...\n"); +// fflush(stdout); + + return 0; +} + +/* is executed when SIGUSR1 is raised (to terminate the app) */ +static void sdlog_sig_handler(int signo, siginfo_t *info, void *ucontext) +{ + sdlog_sigusr1_rcvd = true; +} + + +static void *logbuffer_loop(void *arg) +{ + /* set name for this pthread */ + prctl(PR_SET_NAME, "sdlog logbuffer", getpid()); + + bytes_sent = 0; // count all bytes written to the buffer + + //size_t block_length = sizeof(global_data_sensors_raw_t) - 4*sizeof(access_conf_t); + size_t first_block_length; + size_t second_block_length; + buffer_bytes_used = 0; + + log_block_t log_block = {.check = {'$', '$', '$', '$'}}; + + size_t block_length = sizeof(log_block_t); +// printf("Block length is: %u",(uint16_t)block_length); + +// uint16_t test_counter = 0; + + /* start copying data to buffer */ + while (1) { + copy_block(&log_block); + + /* no more free space in buffer */ + if (buffer_bytes_used + (uint16_t)block_length > BUFFER_BYTES) { + printf("[sdlog] buf full, skipping\n"); + } + + /* data needs to be wrapped around ringbuffer*/ + else if (buffer_cursor_end + block_length >= buffer_end) { + /* first block length is from cursor until the end of the buffer */ + first_block_length = (size_t)(buffer_end - buffer_cursor_end); + /* second block length is the rest */ + second_block_length = block_length - first_block_length; + /* copy the data, not the pointer conversion */ + memcpy(buffer_cursor_end, ((uint8_t *) & (log_block)), first_block_length); + memcpy(buffer_start, ((uint8_t *) & (log_block)) + first_block_length, second_block_length); + /* set the end position of the cursor */ + buffer_cursor_end = buffer_start + second_block_length; + /* increase the amount stored in the buffer */ + buffer_bytes_used += block_length; + bytes_sent += block_length; + } + + /* data does not need to be wrapped around */ + else { + /* copy the whole block in one step */ + memcpy(buffer_cursor_end, ((uint8_t *) & (log_block)), block_length); + /* set the cursor to 0 of the buffer instead of the end */ + buffer_cursor_end = buffer_start + (buffer_cursor_end - buffer_start + block_length) % BUFFER_BYTES; + /* increase the amount stored in the buffer */ + buffer_bytes_used += block_length; + bytes_sent += block_length; + } + + /* also end the pthread when we receive a SIGUSR1 */ + if (sdlog_sigusr1_rcvd == true) { + break; + } + } + + return NULL; +} diff --git a/apps/sdlog/sdlog.h b/apps/sdlog/sdlog.h new file mode 100644 index 0000000000..8012af1777 --- /dev/null +++ b/apps/sdlog/sdlog.h @@ -0,0 +1,17 @@ +/* + * sdlog.h + * + * Created on: Mar 8, 2012 + * Author: romanpatscheider + */ + +#ifndef SENSORS_H_ +#define SENSORS_H_ +/**************************************************************************** + * Included Files + ****************************************************************************/ + + +#define MAX_NO_LOGFOLDER 3000 // tested up to here... + +#endif /* SENSORS_H_ */ diff --git a/apps/sdlog/sdlog_generated.h b/apps/sdlog/sdlog_generated.h new file mode 100644 index 0000000000..ca16ef908a --- /dev/null +++ b/apps/sdlog/sdlog_generated.h @@ -0,0 +1,238 @@ +/* This file is autogenerated in nuttx/configs/px4fmu/include/updatesdlog.py */ + +#ifndef SDLOG_GENERATED_H_ +#define SDLOG_GENERATED_H_ + + +typedef struct { + uint64_t sensors_raw_timestamp; + int16_t sensors_raw_gyro_raw[3]; + uint16_t sensors_raw_gyro_raw_counter; + int16_t sensors_raw_accelerometer_raw[3]; + uint16_t sensors_raw_accelerometer_raw_counter; + float attitude_roll; + float attitude_pitch; + float attitude_yaw; + float position_lat; + float position_lon; + float position_alt; + float position_relative_alt; + float position_vx; + float position_vy; + float position_vz; + int32_t gps_lat; + int32_t gps_lon; + int32_t gps_alt; + uint16_t gps_eph; + float ardrone_control_setpoint_thrust_cast; + float ardrone_control_setpoint_attitude[3]; + float ardrone_control_position_control_output[3]; + float ardrone_control_attitude_setpoint_navigationframe_from_positioncontroller[3]; + char check[4]; +} __attribute__((__packed__)) log_block_t; + +void copy_block(log_block_t *log_block) +{ + if (global_data_wait(&global_data_sensors_raw->access_conf_rate_low) == 0) { + memcpy(&log_block->sensors_raw_timestamp, &global_data_sensors_raw->timestamp, sizeof(uint64_t) * 1); + memcpy(&log_block->sensors_raw_gyro_raw, &global_data_sensors_raw->gyro_raw, sizeof(int16_t) * 3); + memcpy(&log_block->sensors_raw_gyro_raw_counter, &global_data_sensors_raw->gyro_raw_counter, sizeof(uint16_t) * 1); + memcpy(&log_block->sensors_raw_accelerometer_raw, &global_data_sensors_raw->accelerometer_raw, sizeof(int16_t) * 3); + memcpy(&log_block->sensors_raw_accelerometer_raw_counter, &global_data_sensors_raw->accelerometer_raw_counter, sizeof(uint16_t) * 1); + + if (global_data_trylock(&global_data_attitude->access_conf) == 0) { + memcpy(&log_block->attitude_roll, &global_data_attitude->roll, sizeof(float) * 1); + memcpy(&log_block->attitude_pitch, &global_data_attitude->pitch, sizeof(float) * 1); + memcpy(&log_block->attitude_yaw, &global_data_attitude->yaw, sizeof(float) * 1); + global_data_unlock(&global_data_attitude->access_conf); + } + + if (global_data_trylock(&global_data_position->access_conf) == 0) { + memcpy(&log_block->position_lat, &global_data_position->lat, sizeof(float) * 1); + memcpy(&log_block->position_lon, &global_data_position->lon, sizeof(float) * 1); + memcpy(&log_block->position_alt, &global_data_position->alt, sizeof(float) * 1); + memcpy(&log_block->position_relative_alt, &global_data_position->relative_alt, sizeof(float) * 1); + memcpy(&log_block->position_vx, &global_data_position->vx, sizeof(float) * 1); + memcpy(&log_block->position_vy, &global_data_position->vy, sizeof(float) * 1); + memcpy(&log_block->position_vz, &global_data_position->vz, sizeof(float) * 1); + global_data_unlock(&global_data_position->access_conf); + } + + if (global_data_trylock(&global_data_gps->access_conf) == 0) { + memcpy(&log_block->gps_lat, &global_data_gps->lat, sizeof(int32_t) * 1); + memcpy(&log_block->gps_lon, &global_data_gps->lon, sizeof(int32_t) * 1); + memcpy(&log_block->gps_alt, &global_data_gps->alt, sizeof(int32_t) * 1); + memcpy(&log_block->gps_eph, &global_data_gps->eph, sizeof(uint16_t) * 1); + global_data_unlock(&global_data_gps->access_conf); + } + + if (global_data_trylock(&global_data_ardrone_control->access_conf) == 0) { + memcpy(&log_block->ardrone_control_setpoint_thrust_cast, &global_data_ardrone_control->setpoint_thrust_cast, sizeof(float) * 1); + memcpy(&log_block->ardrone_control_setpoint_attitude, &global_data_ardrone_control->setpoint_attitude, sizeof(float) * 3); + memcpy(&log_block->ardrone_control_position_control_output, &global_data_ardrone_control->position_control_output, sizeof(float) * 3); + memcpy(&log_block->ardrone_control_attitude_setpoint_navigationframe_from_positioncontroller, &global_data_ardrone_control->attitude_setpoint_navigationframe_from_positioncontroller, sizeof(float) * 3); + global_data_unlock(&global_data_ardrone_control->access_conf); + } + + global_data_unlock(&global_data_sensors_raw->access_conf_rate_low); + } +} +#define MFILE_STRING "% This file is autogenerated in updatesdlog.py and mfile.template in apps/sdlog\n\ +%% Define logged values \n\ +\n\ +logTypes = {};\n\ +logTypes{end+1} = struct('data','sensors_raw','variable_name','timestamp','type_name','uint64','type_bytes',8,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','sensors_raw','variable_name','gyro_raw','type_name','int16','type_bytes',2,'number_of_array',3);\n\ +logTypes{end+1} = struct('data','sensors_raw','variable_name','gyro_raw_counter','type_name','uint16','type_bytes',2,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','sensors_raw','variable_name','accelerometer_raw','type_name','int16','type_bytes',2,'number_of_array',3);\n\ +logTypes{end+1} = struct('data','sensors_raw','variable_name','accelerometer_raw_counter','type_name','uint16','type_bytes',2,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','attitude','variable_name','roll','type_name','float','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','attitude','variable_name','pitch','type_name','float','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','attitude','variable_name','yaw','type_name','float','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','position','variable_name','lat','type_name','float','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','position','variable_name','lon','type_name','float','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','position','variable_name','alt','type_name','float','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','position','variable_name','relative_alt','type_name','float','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','position','variable_name','vx','type_name','float','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','position','variable_name','vy','type_name','float','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','position','variable_name','vz','type_name','float','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','gps','variable_name','lat','type_name','int32','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','gps','variable_name','lon','type_name','int32','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','gps','variable_name','alt','type_name','int32','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','gps','variable_name','eph','type_name','uint16','type_bytes',2,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','ardrone_control','variable_name','setpoint_thrust_cast','type_name','float','type_bytes',4,'number_of_array',1);\n\ +logTypes{end+1} = struct('data','ardrone_control','variable_name','setpoint_attitude','type_name','float','type_bytes',4,'number_of_array',3);\n\ +logTypes{end+1} = struct('data','ardrone_control','variable_name','position_control_output','type_name','float','type_bytes',4,'number_of_array',3);\n\ +logTypes{end+1} = struct('data','ardrone_control','variable_name','attitude_setpoint_navigationframe_from_positioncontroller','type_name','float','type_bytes',4,'number_of_array',3);\n\ +\ +%% Import logfiles\n\ +\n\ +% define log file and GPSs\n\ +logfileFolder = 'logfiles';\n\ +fileName = 'all';\n\ +fileEnding = 'px4log';\n\ +\n\ +numberOfLogTypes = length(logTypes);\n\ +\n\ +path = [fileName,'.', fileEnding];\n\ +fid = fopen(path, 'r');\n\ +\n\ +% get file length\n\ +fseek(fid, 0,'eof');\n\ +fileLength = ftell(fid);\n\ +fseek(fid, 0,'bof');\n\ +\n\ +% get length of one block\n\ +blockLength = 4; % check: $$$$\n\ +for i=1:numberOfLogTypes\n\ + blockLength = blockLength + logTypes{i}.type_bytes*logTypes{i}.number_of_array;\n\ +end\n\ +\n\ +% determine number of entries\n\ +entries = fileLength / blockLength;\n\ +\n\ +\n\ +% import data\n\ +offset = 0;\n\ +for i=1:numberOfLogTypes\n\ + \n\ + data.(genvarname(logTypes{i}.data)).(genvarname(logTypes{i}.variable_name)) = transpose(fread(fid,[logTypes{i}.number_of_array,entries],[num2str(logTypes{i}.number_of_array),'*',logTypes{i}.type_name,'=>',logTypes{i}.type_name],blockLength-logTypes{i}.type_bytes*logTypes{i}.number_of_array));\n\ + offset = offset + logTypes{i}.type_bytes*logTypes{i}.number_of_array;\n\ + fseek(fid, offset,'bof');\n\ + \n\ + progressPercentage = i/numberOfLogTypes*100;\n\ + fprintf('%3.0f%%',progressPercentage);\n\ +end\n\ +\n\ +\n\ +%% Plots\n\ +\n\ +figure\n\ +plot(data.sensors_raw.timestamp,data.sensors_raw.gyro_raw)\n\ +\n\ +figure\n\ +plot(data.sensors_raw.timestamp,data.sensors_raw.accelerometer_raw)\n\ +\n\ +%% Check for lost data\n\ +\n\ +% to detect lost frames (either when logging to sd card or if no new data is\n\ +% data is available for some time)\n\ +diff_counter = diff(data.sensors_raw.gyro_raw_counter);\n\ +figure\n\ +plot(diff_counter)\n\ +\n\ +% to detect how accurate the timing was\n\ +diff_timestamp = diff(data.sensors_raw.timestamp);\n\ +\n\ +figure\n\ +plot(diff_timestamp)\n\ +\n\ +%% Export to file for google earth\n\ +\n\ +\n\ +if(isfield(data.gps,'lat') && isfield(data.gps,'lon') && isfield(data.gps,'alt'))\n\ +\n\ + % extract coordinates and height where they are not zero\n\ + maskWhereNotZero = ((data.gps.lon ~= 0 & data.gps.lat ~= 0 ) & data.gps.alt ~= 0);\n\ +\n\ + % plot\n\ + figure\n\ + plot3(data.gps.lon(maskWhereNotZero),data.gps.lat(maskWhereNotZero),data.gps.alt(maskWhereNotZero))\n\ +\n\ +\n\ + % create a kml file according to https://developers.google.com/kml/documentation/kml_tut\n\ + % also see https://support.google.com/earth/bin/answer.py?hl=en&answer=148072&topic=2376756&ctx=topic\n\ +\n\ + % open file and overwrite content\n\ + fileId = fopen('gps_path.kml','w+');\n\ +\n\ + % define strings that should be written to file\n\ + fileStartDocumentString = ['PathsPath'];\n\ +\n\ + fileStyleString = '';\n\ +\n\ + filePlacemarkString = 'Absolute ExtrudedTransparent blue wall with blue outlines#blueLinebluePoly11absolute';\n\ +\n\ + fileEndPlacemarkString = '';\n\ + fileEndDocumentString = '';\n\ +\n\ + % start writing to file\n\ + fprintf(fileId,fileStartDocumentString);\n\ +\n\ + fprintf(fileId,fileStyleString);\n\ + fprintf(fileId,filePlacemarkString);\n\ +\n\ + \n\ + lonTemp = double(data.gps.lon(maskWhereNotZero))/1E7;\n\ + latTemp = double(data.gps.lat(maskWhereNotZero))/1E7;\n\ + altTemp = double(data.gps.alt(maskWhereNotZero))/1E3 + 100.0; % in order to see the lines above ground\n\ +\n\ + % write coordinates to file\n\ + for k=1:length(data.gps.lat(maskWhereNotZero))\n\ + if(mod(k,10)==0)\n\ + fprintf(fileId,'%.10f,%.10f,%.10f\\n',lonTemp(k),latTemp(k),altTemp(k));\n\ + end\n\ + end\n\ +\n\ + % write end placemark\n\ + fprintf(fileId,fileEndPlacemarkString);\n\ +\n\ + % write end of file\n\ + fprintf(fileId,fileEndDocumentString);\n\ +\n\ + % close file, it should now be readable in Google Earth using File -> Open\n\ + fclose(fileId);\n\ +\n\ +end\n\ +\n\ +if(isfield(data.position,'lat') && isfield(data.position,'lon') && isfield(data.position,'alt'))\n\ +\n\ + % extract coordinates and height where they are not zero\n\ + maskWhereNotZero = ((data.position.lon ~= 0 & data.position.lat ~= 0 ) & data.position.alt ~= 0);\n\ + \n\ + % plot\n\ + figure\n\ + plot3(data.position.lon(maskWhereNotZero),data.position.lat(maskWhereNotZero),data.position.alt(maskWhereNotZero))\n\ +end\n\ +" +#endif \ No newline at end of file diff --git a/apps/sdlog/updatesdlog.py b/apps/sdlog/updatesdlog.py new file mode 100644 index 0000000000..5892bc40ae --- /dev/null +++ b/apps/sdlog/updatesdlog.py @@ -0,0 +1,199 @@ +import os +import glob + +# path to global data files +base_path = '../orb/' +cfile = './sdlog_generated.h' +mfile_template = './mfile.template' + +# there should be one LOGBROADCAST which gives the timing for the logging +logbroadcast_found = 0 + +# these types can nicely be imported into Matlab +allowed_types = ['uint8_t','int8_t','uint16_t','int16_t','uint32_t','int32_t','uint64_t','int64_t','float','double'] + +log_entries = [] +# loop through global_data_files ending in _t.h and look for LOGME (per variable) and LOGBROADCAST (overall) +for path in glob.glob( os.path.join(base_path, '*_t.h') ): + # filename is supposed to be global_data_bapedibup_t.h + if 'global_data' not in path: + print 'path: ' + path + raise 'wrong filename found' + f = open(path, 'r') + access_conf_found = False; + # strip away ../../../../apps/orb/ and _t.h + data_name = path.lstrip(base_path)[0:-4] + # strip away ../../../../apps/orb/ and global_data_ and _t.h + name = path.lstrip(base_path)[12:-4] + log_entry = {'data_name': data_name,'name':name,'vars': []} + + logbroadcast = False; + + # loop throug lines + for line in f: + + line_parts = line.split() + # access_conf is needed to lock the data + if 'access_conf_t' in line: + + # always use the access_conf which has the LOGBROADCAST flag + if 'LOGBROADCAST' in line: + access_conf_found = True + log_entry['access_conf_name'] = line_parts[1].rstrip(';') + logbroadcast = True + print 'LOGBROADCAST found in ' + data_name + logbroadcast_found += 1 + # but use an access_conf anyway + elif access_conf_found == False: + access_conf_found = True + log_entry['access_conf_name'] = line_parts[1].rstrip(';') + # variables flagged with LOGME should be logged + elif 'LOGME' in line: + var_entry = {'type': line_parts[0]} + + # check that it is an allowed type + if var_entry['type'] not in allowed_types: + print 'file: '+ path + ', type: ' + var_entry['type'] + raise 'unsupported type' + + # save variable name and number for array + if '[' in line_parts[1]: + var_entry['name'] = line_parts[1].split('[')[0] + var_entry['number'] = line_parts[1].split('[')[1].rstrip('];') + else: + var_entry['name'] = line_parts[1].rstrip(';') + var_entry['number'] = 1 + + # add the variable + log_entry['vars'].append(var_entry) + # only use the global data file if any variables have a LOGME + if logbroadcast == True and len(log_entry['vars']) > 0: + logbroadcast_entry = log_entry + elif len(log_entry['vars']) > 0: + print 'added ' + log_entry['data_name'] + log_entries.append(log_entry) + f.close() + +# check that we have one and only one LOGBROADCAST +if logbroadcast_found > 1: + raise 'too many LOGBROADCAST found\n' +elif logbroadcast_found == 0: + raise 'no LOGBROADCAST found\n' + +# write function to c file + +header = '/* This file is autogenerated in nuttx/configs/px4fmu/include/updatesdlog.py */\n\ +\n\ +#ifndef SDLOG_GENERATED_H_\n\ +#define SDLOG_GENERATED_H_\n\ +\n\ +\n\ +' + +cstruct = 'typedef struct\n{\n' + +for j in logbroadcast_entry['vars']: + cstruct += '\t' + j['type'] + ' ' + logbroadcast_entry['name'] + '_' + j['name'] + if j['number'] == 1: + cstruct += ';\n' + else: + cstruct += '[' + j['number'] + '];\n' + +for i in log_entries: + for j in i['vars']: + cstruct += '\t' + j['type'] + ' ' + i['name'] + '_' + j['name'] + if j['number'] == 1: + cstruct += ';\n' + else: + cstruct += '[' + j['number'] + '];\n' + +cstruct += '\tchar check[4];\n} __attribute__((__packed__)) log_block_t;\n\n' + + +copy_function = 'void copy_block(log_block_t* log_block)\n{\n' +copy_function += '\tif(global_data_wait(&' + logbroadcast_entry['data_name'] + '->' + logbroadcast_entry['access_conf_name'] + ') == 0)\n\t{\n' + +for j in logbroadcast_entry['vars']: + copy_function += '\t\tmemcpy(&log_block->' + logbroadcast_entry['name'] + '_' + j['name'] + ',&' + logbroadcast_entry['data_name'] + '->' + j['name'] + ',sizeof(' + j['type'] + ')*' + str(j['number']) + ');\n' + #copy_function += '\t\t}\n' + +# generate logging MACRO + + +for i in log_entries: + copy_function += '\t\tif(global_data_trylock(&' + i['data_name'] + '->' + i['access_conf_name'] + ') == 0)\n\t\t{\n' + + for j in i['vars']: + copy_function += '\t\t\tmemcpy(&log_block->' + i['name'] + '_' + j['name'] + ',&' + i['data_name'] + '->' + j['name'] + ',sizeof(' + j['type'] + ')*' + str(j['number']) + ');\n' + + copy_function += '\t\t\tglobal_data_unlock(&' + i['data_name'] + '->' + i['access_conf_name'] + ');\n' + copy_function += '\t\t}\n' +copy_function += '\t\tglobal_data_unlock(&' + logbroadcast_entry['data_name'] + '->' + logbroadcast_entry['access_conf_name'] + ');\n' +copy_function += '\t}\n' + +copy_function += '}\n' + +footer = '\n#endif' + + + +# generate mfile + +type_bytes = { +'uint8_t' : 1, +'int8_t' : 1, +'uint16_t' : 2, +'int16_t' : 2, +'uint32_t' : 4, +'int32_t' : 4, +'uint64_t' : 8, +'int64_t' : 8, +'float' : 4, +'double' : 8, +} + +type_names_matlab = { +'uint8_t' : 'uint8', +'int8_t' : 'int8', +'uint16_t' : 'uint16', +'int16_t' : 'int16', +'uint32_t' : 'uint32', +'int32_t' : 'int32', +'uint64_t' : 'uint64', +'int64_t' : 'int64', +'float' : 'float', +'double' : 'double', +} + + +# read template mfile +mf = open(mfile_template, 'r') +mfile_template_string = mf.read() + +mfile_define = '#define MFILE_STRING "% This file is autogenerated in updatesdlog.py and mfile.template in apps/sdlog\\n\\\n' +mfile_define += '%% Define logged values \\n\\\n\\n\\\nlogTypes = {};\\n\\\n' + +for j in logbroadcast_entry['vars']: + mfile_define += 'logTypes{end+1} = struct(\'data\',\'' + logbroadcast_entry['name'] + '\',\'variable_name\',\'' + j['name'] + '\',\'type_name\',\'' + type_names_matlab.get(j['type']) + '\',\'type_bytes\',' + str(type_bytes.get(j['type'])) + ',\'number_of_array\',' + str(j['number']) + ');\\n\\\n' + +for i in log_entries: + for j in i['vars']: + mfile_define += 'logTypes{end+1} = struct(\'data\',\'' + i['name'] + '\',\'variable_name\',\'' + j['name'] + '\',\'type_name\',\'' + type_names_matlab.get(j['type']) + '\',\'type_bytes\',' + str(type_bytes.get(j['type'])) + ',\'number_of_array\',' + str(j['number']) + ');\\n\\\n' + + + +mfile_define += '\\\n' + mfile_template_string.replace('\n', '\\n\\\n').replace('\"','\\\"') + '"' + + +# write to c File +cf = open(cfile, 'w') +cf.write(header) +cf.write(cstruct); +cf.write(copy_function) + +cf.write(mfile_define) + +cf.write(footer) +cf.close() + +print 'finished, cleanbuild needed!' diff --git a/apps/sensors/.context b/apps/sensors/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/sensors/Makefile b/apps/sensors/Makefile new file mode 100644 index 0000000000..0bc5b52d66 --- /dev/null +++ b/apps/sensors/Makefile @@ -0,0 +1,42 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Makefile to build the sensor data collector +# + +APPNAME = sensors +PRIORITY = SCHED_PRIORITY_MAX-5 +STACKSIZE = 2560 + +include $(APPDIR)/mk/app.mk diff --git a/apps/sensors/sensors.c b/apps/sensors/sensors.c new file mode 100644 index 0000000000..a88361e1ac --- /dev/null +++ b/apps/sensors/sensors.c @@ -0,0 +1,852 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Lorenz Meier + * @author Thomas Gubler + * @author Julian Oes + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file sensors.c + * Sensor readout process. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "sensors.h" + +#define errno *get_errno_ptr() + +#define SENSOR_INTERVAL_MICROSEC 2000 + +#define GYRO_HEALTH_COUNTER_LIMIT_ERROR 20 /* 40 ms downtime at 500 Hz update rate */ +#define ACC_HEALTH_COUNTER_LIMIT_ERROR 20 /* 40 ms downtime at 500 Hz update rate */ +#define MAGN_HEALTH_COUNTER_LIMIT_ERROR 100 /* 1000 ms downtime at 100 Hz update rate */ +#define BARO_HEALTH_COUNTER_LIMIT_ERROR 50 /* 500 ms downtime at 100 Hz update rate */ +#define ADC_HEALTH_COUNTER_LIMIT_ERROR 10 /* 100 ms downtime at 100 Hz update rate */ + +#define GYRO_HEALTH_COUNTER_LIMIT_OK 5 +#define ACC_HEALTH_COUNTER_LIMIT_OK 5 +#define MAGN_HEALTH_COUNTER_LIMIT_OK 5 +#define BARO_HEALTH_COUNTER_LIMIT_OK 5 +#define ADC_HEALTH_COUNTER_LIMIT_OK 5 + +#define ADC_BATTERY_VOLATGE_CHANNEL 10 + +#define BAT_VOL_INITIAL 12.f +#define BAT_VOL_LOWPASS_1 0.99f +#define BAT_VOL_LOWPASS_2 0.01f +#define VOLTAGE_BATTERY_IGNORE_THRESHOLD_VOLTS 3.5f + +/*PPM Settings*/ +#define PPM_MIN 1000 +#define PPM_MAX 2000 +/*Our internal resolution is 10000*/ +#define PPM_SCALE 10000/((PPM_MAX-PPM_MIN)/2) + +#define PPM_MID (PPM_MIN+PPM_MAX)/2 + +/**************************************************************************** + * Definitions + ****************************************************************************/ +static pthread_cond_t sensors_read_ready; +static pthread_mutex_t sensors_read_ready_mutex; + +static int sensors_timer_loop_counter = 0; + +/* File descriptors for all sensors */ +static int fd_gyro = -1; +static int fd_accelerometer = -1; +static int fd_magnetometer = -1; +static int fd_barometer = -1; +static int fd_adc = -1; + +/* Private functions declared static */ +static void sensors_timer_loop(void *arg); + +#ifdef CONFIG_HRT_PPM +extern uint16_t ppm_buffer[]; +extern unsigned ppm_decoded_channels; +#endif + +/* file handle that will be used for subscribing */ +static int sensor_pub; + +/** + * Sensor readout and publishing. + * + * This function reads all onboard sensors and publishes the sensor_combined topic. + * + * @see sensor_combined_s + * @ingroup apps + */ +__EXPORT int sensors_main(int argc, char *argv[]); + +/** + * Initialize all sensor drivers. + * + * @return 0 on success, != 0 on failure + */ +static int sensors_init(void) +{ + printf("[sensors] Sensor configuration..\n"); + + /* open magnetometer */ + fd_magnetometer = open("/dev/hmc5883l", O_RDONLY); + + if (fd_magnetometer < 0) { + fprintf(stderr, "[sensors] HMC5883L open fail (err #%d): %s\n", (int)*get_errno_ptr(), strerror((int)*get_errno_ptr())); + fflush(stderr); + /* this sensor is critical, exit on failed init */ + errno = ENOSYS; + return ERROR; + + } else { + printf("[sensors] HMC5883L open ok\n"); + } + + /* open barometer */ + fd_barometer = open("/dev/ms5611", O_RDONLY); + + if (fd_barometer < 0) { + fprintf(stderr, "[sensors] MS5611 open fail (err #%d): %s\n", (int)*get_errno_ptr(), strerror((int)*get_errno_ptr())); + fflush(stderr); + + } else { + printf("[sensors] MS5611 open ok\n"); + } + + /* open gyro */ + fd_gyro = open("/dev/l3gd20", O_RDONLY); + + if (fd_gyro < 0) { + fprintf(stderr, "[sensors] L3GD20 open fail (err #%d): %s\n", (int)*get_errno_ptr(), strerror((int)*get_errno_ptr())); + fflush(stderr); + /* this sensor is critical, exit on failed init */ + errno = ENOSYS; + return ERROR; + + } else { + printf("[sensors] L3GD20 open ok\n"); + } + + /* open accelerometer */ + fd_accelerometer = open("/dev/bma180", O_RDONLY); + + if (fd_accelerometer < 0) { + fprintf(stderr, "[sensors] BMA180: open fail (err #%d): %s\n", (int)*get_errno_ptr(), strerror((int)*get_errno_ptr())); + fflush(stderr); + /* this sensor is critical, exit on failed init */ + errno = ENOSYS; + return ERROR; + + } else { + printf("[sensors] BMA180 open ok\n"); + } + + /* open adc */ + fd_adc = open("/dev/adc0", O_RDONLY | O_NONBLOCK); + + if (fd_adc < 0) { + fprintf(stderr, "[sensors] ADC: open fail (err #%d): %s\n", (int)*get_errno_ptr(), strerror((int)*get_errno_ptr())); + fflush(stderr); + /* this sensor is critical, exit on failed init */ + errno = ENOSYS; + return ERROR; + + } else { + printf("[sensors] ADC open ok\n"); + } + + /* configure gyro */ + if (ioctl(fd_gyro, L3GD20_SETRATE, L3GD20_RATE_760HZ_LP_30HZ) || ioctl(fd_gyro, L3GD20_SETRANGE, L3GD20_RANGE_500DPS)) { + fprintf(stderr, "[sensors] L3GD20 configuration (ioctl) fail (err #%d): %s\n", (int)*get_errno_ptr(), strerror((int)*get_errno_ptr())); + fflush(stderr); + /* this sensor is critical, exit on failed init */ + errno = ENOSYS; + return ERROR; + + } else { + printf("[sensors] L3GD20 configuration ok\n"); + } + + /* XXX Add IOCTL configuration of remaining sensors */ + + printf("[sensors] All sensors configured\n"); + return OK; +} + +/** + * Callback function called by high resolution timer. + * + * This function signals a pthread condition and wakes up the + * sensor main loop. + */ +static void sensors_timer_loop(void *arg) +{ + /* Inform the read thread that it is now time to read */ + sensors_timer_loop_counter++; + /* Do not use global data broadcast because of + * use of printf() in call - would be fatal here + */ + pthread_cond_broadcast(&sensors_read_ready); +} + +int sensors_main(int argc, char *argv[]) +{ + /* inform about start */ + printf("[sensors] Initializing..\n"); + fflush(stdout); + int ret = OK; + + /* start sensor reading */ + if (sensors_init() != OK) { + fprintf(stderr, "[sensors] ERROR: Failed to initialize all sensors\n"); + /* Clean up */ + close(fd_gyro); + close(fd_accelerometer); + close(fd_magnetometer); + close(fd_barometer); + close(fd_adc); + + fprintf(stderr, "[sensors] rebooting system.\n"); + fflush(stderr); + fflush(stdout); + usleep(100000); + + /* Sensors are critical, immediately reboot system on failure */ + reboot(); + /* Not ever reaching here */ + + } else { + /* flush stdout from init routine */ + fflush(stdout); + } + + bool gyro_healthy = false; + bool acc_healthy = false; + bool magn_healthy = false; + bool baro_healthy = false; + bool adc_healthy = false; + + bool hil_enabled = false; + + int magcounter = 0; + int barocounter = 0; + int adccounter = 0; + + unsigned int mag_fail_count = 0; + unsigned int mag_success_count = 0; + + unsigned int baro_fail_count = 0; + unsigned int baro_success_count = 0; + + unsigned int gyro_fail_count = 0; + unsigned int gyro_success_count = 0; + + unsigned int acc_fail_count = 0; + unsigned int acc_success_count = 0; + + unsigned int adc_fail_count = 0; + unsigned int adc_success_count = 0; + + ssize_t ret_gyro; + ssize_t ret_accelerometer; + ssize_t ret_magnetometer; + ssize_t ret_barometer; + ssize_t ret_adc; + int nsamples_adc; + + int16_t buf_gyro[3]; + int16_t buf_accelerometer[3]; + int16_t buf_magnetometer[3]; + float buf_barometer[3]; + + int16_t mag_offset[3] = {0, 0, 0}; + int16_t acc_offset[3] = {0, 0, 0}; + int16_t gyro_offset[3] = {0, 0, 0}; + + struct adc_msg4_s { + uint8_t am_channel1; /**< The 8-bit ADC Channel 1 */ + int32_t am_data1; /**< ADC convert result 1 (4 bytes) */ + uint8_t am_channel2; /**< The 8-bit ADC Channel 2 */ + int32_t am_data2; /**< ADC convert result 2 (4 bytes) */ + uint8_t am_channel3; /**< The 8-bit ADC Channel 3 */ + int32_t am_data3; /**< ADC convert result 3 (4 bytes) */ + uint8_t am_channel4; /**< The 8-bit ADC Channel 4 */ + int32_t am_data4; /**< ADC convert result 4 (4 bytes) */ + } __attribute__((__packed__));; + struct adc_msg4_s buf_adc; + size_t adc_readsize = 1 * sizeof(struct adc_msg4_s); + + float battery_voltage_conversion; + battery_voltage_conversion = global_data_parameter_storage->pm.param_values[PARAM_BATTERYVOLTAGE_CONVERSION]; + + if (-1.0f == battery_voltage_conversion) { + /**< default is conversion factor for the PX4IO / PX4IOAR board, the factor for PX4FMU standalone is different */ + battery_voltage_conversion = 3.3f * 52.0f / 5.0f / 4095.0f; + } + +#ifdef CONFIG_HRT_PPM + int ppmcounter = 0; +#endif + /* initialize to 100 to execute immediately */ + int paramcounter = 100; + + int excessive_readout_time_counter = 0; + + int read_loop_counter = 0; + + /* Empty sensor buffers, avoid junk values */ + /* Read first two values of each sensor into void */ + (void)read(fd_gyro, buf_gyro, sizeof(buf_gyro)); + (void)read(fd_accelerometer, buf_accelerometer, sizeof(buf_accelerometer)); + (void)read(fd_magnetometer, buf_magnetometer, sizeof(buf_magnetometer)); + + if (fd_barometer > 0)(void)read(fd_barometer, buf_barometer, sizeof(buf_barometer)); + + struct sensor_combined_s raw = { + .timestamp = hrt_absolute_time(), + .gyro_raw = {buf_gyro[0], buf_gyro[1], buf_gyro[2]}, + .gyro_raw_counter = 0, + .gyro_rad_s = {0, 0, 0}, + .accelerometer_raw = {buf_accelerometer[0], buf_accelerometer[1], buf_accelerometer[2]}, + .accelerometer_raw_counter = 0, + .accelerometer_m_s2 = {0, 0, 0}, + .magnetometer_raw = {buf_magnetometer[0], buf_magnetometer[1], buf_magnetometer[2]}, + .magnetometer_raw_counter = 0, + .baro_pres_mbar = 0, + .baro_alt_meter = 0, + .baro_temp_celcius = 0, + .battery_voltage_v = BAT_VOL_INITIAL, + .adc_voltage_v = {0, 0 , 0}, + .baro_raw_counter = 0, + .battery_voltage_counter = 0, + .battery_voltage_valid = false, + }; + + /* condition to wait for */ + pthread_mutex_init(&sensors_read_ready_mutex, NULL); + pthread_cond_init(&sensors_read_ready, NULL); + + /* advertise the topic and make the initial publication */ + sensor_pub = orb_advertise(ORB_ID(sensor_combined), &raw); + + /* advertise the rc topic */ + struct rc_channels_s rc = {0}; + int rc_pub = orb_advertise(ORB_ID(rc_channels), &rc); + + /* subscribe to system status */ + struct vehicle_status_s vstatus; + int vstatus_sub = orb_subscribe(ORB_ID(vehicle_status)); + + + printf("[sensors] rate: %u Hz\n", (unsigned int)(1000000 / SENSOR_INTERVAL_MICROSEC)); + + struct hrt_call sensors_hrt_call; + /* Enable high resolution timer callback to unblock main thread, run after 2 ms */ + hrt_call_every(&sensors_hrt_call, 2000, SENSOR_INTERVAL_MICROSEC, &sensors_timer_loop, NULL); + + while (1) { + pthread_mutex_lock(&sensors_read_ready_mutex); + + struct timespec time_to_wait = {0, 0}; + /* Wait 2 seconds until timeout */ + time_to_wait.tv_nsec = 0; + time_to_wait.tv_sec = time(NULL) + 2; + + if (pthread_cond_timedwait(&sensors_read_ready, &sensors_read_ready_mutex, &time_to_wait) == OK) { + pthread_mutex_unlock(&sensors_read_ready_mutex); + + bool gyro_updated = false; + bool acc_updated = false; + bool magn_updated = false; + bool baro_updated = false; + bool adc_updated = false; + + /* store the time closest to all measurements */ + uint64_t current_time = hrt_absolute_time(); + raw.timestamp = current_time; + + if (paramcounter == 100) { + // XXX paramcounter is not a good name, rename / restructure + // XXX make counter ticks dependent on update rate of sensor main loop + + /* Check HIL state */ + orb_copy(ORB_ID(vehicle_status), vstatus_sub, &vstatus); + + /* switching from non-HIL to HIL mode */ + if ((vstatus.mode & VEHICLE_MODE_FLAG_HIL_ENABLED) && !hil_enabled) { + hil_enabled = true; + close(sensor_pub); + + /* switching from HIL to non-HIL mode */ + + } else if (!(vstatus.mode & VEHICLE_MODE_FLAG_HIL_ENABLED) && hil_enabled) { + /* advertise the topic and make the initial publication */ + sensor_pub = orb_advertise(ORB_ID(sensor_combined), &raw); + hil_enabled = false; + } + + + /* Update RC scalings and function mappings */ + rc.chan[0].scaling_factor = (10000 / ((global_data_parameter_storage->pm.param_values[PARAM_RC1_MAX] - global_data_parameter_storage->pm.param_values[PARAM_RC1_MIN]) / 2) + * global_data_parameter_storage->pm.param_values[PARAM_RC1_REV]); + rc.chan[0].mid = (uint16_t)global_data_parameter_storage->pm.param_values[PARAM_RC1_TRIM]; + + rc.chan[1].scaling_factor = (10000 / ((global_data_parameter_storage->pm.param_values[PARAM_RC2_MAX] - global_data_parameter_storage->pm.param_values[PARAM_RC2_MIN]) / 2) + * global_data_parameter_storage->pm.param_values[PARAM_RC2_REV]); + rc.chan[1].mid = (uint16_t)global_data_parameter_storage->pm.param_values[PARAM_RC2_TRIM]; + + rc.chan[2].scaling_factor = (10000 / ((global_data_parameter_storage->pm.param_values[PARAM_RC3_MAX] - global_data_parameter_storage->pm.param_values[PARAM_RC3_MIN]) / 2) + * global_data_parameter_storage->pm.param_values[PARAM_RC3_REV]); + rc.chan[2].mid = (uint16_t)global_data_parameter_storage->pm.param_values[PARAM_RC3_TRIM]; + + rc.chan[3].scaling_factor = (10000 / ((global_data_parameter_storage->pm.param_values[PARAM_RC4_MAX] - global_data_parameter_storage->pm.param_values[PARAM_RC4_MIN]) / 2) + * global_data_parameter_storage->pm.param_values[PARAM_RC4_REV]); + rc.chan[3].mid = (uint16_t)global_data_parameter_storage->pm.param_values[PARAM_RC4_TRIM]; + + rc.chan[4].scaling_factor = (10000 / ((global_data_parameter_storage->pm.param_values[PARAM_RC5_MAX] - global_data_parameter_storage->pm.param_values[PARAM_RC5_MIN]) / 2) + * global_data_parameter_storage->pm.param_values[PARAM_RC5_REV]); + rc.chan[4].mid = (uint16_t)global_data_parameter_storage->pm.param_values[PARAM_RC5_TRIM]; + + rc.function[0] = global_data_parameter_storage->pm.param_values[PARAM_THROTTLE_CHAN] - 1; + rc.function[1] = global_data_parameter_storage->pm.param_values[PARAM_ROLL_CHAN] - 1; + rc.function[2] = global_data_parameter_storage->pm.param_values[PARAM_PITCH_CHAN] - 1; + rc.function[3] = global_data_parameter_storage->pm.param_values[PARAM_YAW_CHAN] - 1; + rc.function[4] = global_data_parameter_storage->pm.param_values[PARAM_OVERRIDE_CHAN] - 1; + + gyro_offset[0] = global_data_parameter_storage->pm.param_values[PARAM_SENSOR_GYRO_XOFFSET]; + gyro_offset[1] = global_data_parameter_storage->pm.param_values[PARAM_SENSOR_GYRO_YOFFSET]; + gyro_offset[2] = global_data_parameter_storage->pm.param_values[PARAM_SENSOR_GYRO_ZOFFSET]; + + mag_offset[0] = global_data_parameter_storage->pm.param_values[PARAM_SENSOR_MAG_XOFFSET]; + mag_offset[1] = global_data_parameter_storage->pm.param_values[PARAM_SENSOR_MAG_YOFFSET]; + mag_offset[2] = global_data_parameter_storage->pm.param_values[PARAM_SENSOR_MAG_ZOFFSET]; + + paramcounter = 0; + } + + paramcounter++; + + /* try reading gyro */ + uint64_t start_gyro = hrt_absolute_time(); + ret_gyro = read(fd_gyro, buf_gyro, sizeof(buf_gyro)); + int gyrotime = hrt_absolute_time() - start_gyro; + + if (gyrotime > 500) printf("GYRO (pure read): %d us\n", gyrotime); + + /* GYROSCOPE */ + if (ret_gyro != sizeof(buf_gyro)) { + gyro_fail_count++; + + if ((((gyro_fail_count % 20) == 0) || (gyro_fail_count > 20 && gyro_fail_count < 100)) && (int)*get_errno_ptr() != EAGAIN) { + fprintf(stderr, "[sensors] L3GD20 ERROR #%d: %s\n", (int)*get_errno_ptr(), strerror((int)*get_errno_ptr())); + } + + if (gyro_healthy && gyro_fail_count >= GYRO_HEALTH_COUNTER_LIMIT_ERROR) { + // global_data_send_subsystem_info(&gyro_present_enabled); + gyro_healthy = false; + gyro_success_count = 0; + } + + } else { + gyro_success_count++; + + if (!gyro_healthy && gyro_success_count >= GYRO_HEALTH_COUNTER_LIMIT_OK) { + // global_data_send_subsystem_info(&gyro_present_enabled_healthy); + gyro_healthy = true; + gyro_fail_count = 0; + + } + + gyro_updated = true; + } + + gyrotime = hrt_absolute_time() - start_gyro; + + if (gyrotime > 500) printf("GYRO (complete): %d us\n", gyrotime); + + /* try reading acc */ + uint64_t start_acc = hrt_absolute_time(); + ret_accelerometer = read(fd_accelerometer, buf_accelerometer, sizeof(buf_accelerometer)); + + /* ACCELEROMETER */ + if (ret_accelerometer != sizeof(buf_accelerometer)) { + acc_fail_count++; + + if (acc_fail_count & 0b1000 || (acc_fail_count > 20 && acc_fail_count < 100)) { + fprintf(stderr, "[sensors] BMA180 ERROR #%d: %s\n", (int)*get_errno_ptr(), strerror((int)*get_errno_ptr())); + } + + if (acc_healthy && acc_fail_count >= ACC_HEALTH_COUNTER_LIMIT_ERROR) { + // global_data_send_subsystem_info(&acc_present_enabled); + gyro_healthy = false; + acc_success_count = 0; + } + + } else { + acc_success_count++; + + if (!acc_healthy && acc_success_count >= ACC_HEALTH_COUNTER_LIMIT_OK) { + + // global_data_send_subsystem_info(&acc_present_enabled_healthy); + acc_healthy = true; + acc_fail_count = 0; + + } + + acc_updated = true; + } + + int acctime = hrt_absolute_time() - start_acc; + + if (acctime > 500) printf("ACC: %d us\n", acctime); + + /* MAGNETOMETER */ + if (magcounter == 4) { //(magcounter == 4) // 100 Hz + uint64_t start_mag = hrt_absolute_time(); + ret_magnetometer = read(fd_magnetometer, buf_magnetometer, sizeof(buf_magnetometer)); + int errcode_mag = (int) * get_errno_ptr(); + int magtime = hrt_absolute_time() - start_mag; + + if (magtime > 2000) { + printf("MAG (pure read): %d us\n", magtime); + } + + if (ret_magnetometer != sizeof(buf_magnetometer)) { + mag_fail_count++; + + if (mag_fail_count & 0b1000 || (mag_fail_count > 20 && mag_fail_count < 100)) { + fprintf(stderr, "[sensors] HMC5883L ERROR #%d: %s\n", (int)*get_errno_ptr(), strerror((int)*get_errno_ptr())); + } + + if (magn_healthy && mag_fail_count >= MAGN_HEALTH_COUNTER_LIMIT_ERROR) { + // global_data_send_subsystem_info(&magn_present_enabled); + magn_healthy = false; + mag_success_count = 0; + } + + } else { + mag_success_count++; + + if (!magn_healthy && mag_success_count >= MAGN_HEALTH_COUNTER_LIMIT_OK) { + // global_data_send_subsystem_info(&magn_present_enabled_healthy); + magn_healthy = true; + mag_fail_count = 0; + } + + magn_updated = true; + } + + magtime = hrt_absolute_time() - start_mag; + + if (magtime > 2000) { + printf("MAG (overall time): %d us\n", magtime); + fprintf(stderr, "[sensors] TIMEOUT HMC5883L ERROR #%d: %s\n", errcode_mag, strerror(errcode_mag)); + } + + magcounter = 0; + } + + magcounter++; + + /* BAROMETER */ + if (barocounter == 5 && (fd_barometer > 0)) { //(barocounter == 4) // 100 Hz + uint64_t start_baro = hrt_absolute_time(); + *get_errno_ptr() = 0; + ret_barometer = read(fd_barometer, buf_barometer, sizeof(buf_barometer)); + + if (ret_barometer != sizeof(buf_barometer)) { + baro_fail_count++; + + if ((baro_fail_count & 0b1000 || (baro_fail_count > 20 && baro_fail_count < 100)) && (int)*get_errno_ptr() != EAGAIN) { + fprintf(stderr, "[sensors] MS5611 ERROR #%d: %s\n", (int)*get_errno_ptr(), strerror((int)*get_errno_ptr())); + } + + if (baro_healthy && baro_fail_count >= BARO_HEALTH_COUNTER_LIMIT_ERROR) { + /* switched from healthy to unhealthy */ + baro_healthy = false; + baro_success_count = 0; + // global_data_send_subsystem_info(&baro_present_enabled); + } + + } else { + baro_success_count++; + + if (!baro_healthy && baro_success_count >= MAGN_HEALTH_COUNTER_LIMIT_OK) { + /* switched from unhealthy to healthy */ + baro_healthy = true; + baro_fail_count = 0; + // global_data_send_subsystem_info(&baro_present_enabled_healthy); + } + + baro_updated = true; + } + + barocounter = 0; + int barotime = hrt_absolute_time() - start_baro; + + if (barotime > 2000) printf("BARO: %d us\n", barotime); + } + + barocounter++; + + /* ADC */ + if (adccounter == 5) { + ret_adc = read(fd_adc, &buf_adc, adc_readsize); + nsamples_adc = ret_adc / sizeof(struct adc_msg_s); + + if (ret_adc < 0 || nsamples_adc * sizeof(struct adc_msg_s) != ret_adc) { + adc_fail_count++; + + if ((adc_fail_count & 0b1000 || adc_fail_count < 10) && (int)*get_errno_ptr() != EAGAIN) { + fprintf(stderr, "[sensors] ADC ERROR #%d: %s\n", (int)*get_errno_ptr(), strerror((int)*get_errno_ptr())); + } + + if (adc_healthy && adc_fail_count >= ADC_HEALTH_COUNTER_LIMIT_ERROR) { + adc_healthy = false; + adc_success_count = 0; + } + + } else { + adc_success_count++; + + if (!adc_healthy && adc_success_count >= ADC_HEALTH_COUNTER_LIMIT_OK) { + adc_healthy = true; + adc_fail_count = 0; + } + + adc_updated = true; + } + + adccounter = 0; + + } + + adccounter++; + + + +#ifdef CONFIG_HRT_PPM + bool ppm_updated = false; + + /* PPM */ + if (ppmcounter == 5) { + + /* Read out values from HRT */ + for (int i = 0; i < ppm_decoded_channels; i++) { + rc.chan[i].raw = ppm_buffer[i]; + /* Set the range to +-, then scale up */ + rc.chan[i].scale = (ppm_buffer[i] - rc.chan[i].mid) * rc.chan[i].scaling_factor; + } + + rc.chan_count = ppm_decoded_channels; + + rc.timestamp = hrt_absolute_time(); + /* publish a few lines of code later if set to true */ + ppm_updated = true; + + + //TODO: XXX check the mode switch channel and eventually send a request to the commander (see implementation in commander and mavlink) + ppmcounter = 0; + } + + ppmcounter++; +#endif + + /* Copy values of gyro, acc, magnetometer & barometer */ + + /* GYROSCOPE */ + if (gyro_updated) { + /* copy sensor readings to global data and transform coordinates into px4fmu board frame */ + + raw.gyro_raw[0] = ((buf_gyro[1] == -32768) ? -32767 : buf_gyro[1]); // x of the board is y of the sensor + /* assign negated value, except for -SHORT_MAX, as it would wrap there */ + raw.gyro_raw[1] = ((buf_gyro[0] == -32768) ? 32767 : -buf_gyro[0]); // y on the board is -x of the sensor + raw.gyro_raw[2] = ((buf_gyro[2] == -32768) ? -32767 : buf_gyro[2]); // z of the board is -z of the sensor + + /* scale measurements */ + // XXX request scaling from driver instead of hardcoding it + /* scaling calculated as: raw * (1/(32768*(500/180*PI))) */ + raw.gyro_rad_s[0] = (raw.gyro_raw[0] - gyro_offset[0]) * 0.000266316109f; + raw.gyro_rad_s[1] = (raw.gyro_raw[1] - gyro_offset[1]) * 0.000266316109f; + raw.gyro_rad_s[2] = (raw.gyro_raw[2] - gyro_offset[2]) * 0.000266316109f; + + raw.gyro_raw_counter++; + } + + /* ACCELEROMETER */ + if (acc_updated) { + /* copy sensor readings to global data and transform coordinates into px4fmu board frame */ + + /* assign negated value, except for -SHORT_MAX, as it would wrap there */ + raw.accelerometer_raw[0] = (buf_accelerometer[1] == -32768) ? 32767 : -buf_accelerometer[1]; // x of the board is -y of the sensor + raw.accelerometer_raw[1] = (buf_accelerometer[0] == -32768) ? -32767 : buf_accelerometer[0]; // y on the board is x of the sensor + raw.accelerometer_raw[2] = (buf_accelerometer[2] == -32768) ? -32767 : buf_accelerometer[2]; // z of the board is z of the sensor + + // XXX read range from sensor + float range_g = 4.0f; + /* scale from 14 bit to m/s2 */ + raw.accelerometer_m_s2[0] = (((raw.accelerometer_raw[0] - acc_offset[0]) * range_g) / 8192.0f) / 9.81f; + raw.accelerometer_m_s2[1] = (((raw.accelerometer_raw[1] - acc_offset[1]) * range_g) / 8192.0f) / 9.81f; + raw.accelerometer_m_s2[2] = (((raw.accelerometer_raw[2] - acc_offset[2]) * range_g) / 8192.0f) / 9.81f; + + raw.accelerometer_raw_counter++; + } + + /* MAGNETOMETER */ + if (magn_updated) { + /* copy sensor readings to global data and transform coordinates into px4fmu board frame */ + + /* assign negated value, except for -SHORT_MAX, as it would wrap there */ + raw.magnetometer_raw[0] = (buf_magnetometer[1] == -32768) ? 32767 : -buf_magnetometer[1]; // x of the board is -y of the sensor + raw.magnetometer_raw[1] = (buf_magnetometer[0] == -32768) ? -32767 : buf_magnetometer[0]; // y on the board is x of the sensor + raw.magnetometer_raw[2] = (buf_magnetometer[2] == -32768) ? -32767 : buf_magnetometer[2]; // z of the board is z of the sensor + + // XXX Read out mag range via I2C on init, assuming 0.88 Ga and 12 bit res here + raw.magnetometer_ga[0] = ((raw.magnetometer_raw[0] - mag_offset[0]) / 4096.0f) * 0.88f; + raw.magnetometer_ga[1] = ((raw.magnetometer_raw[1] - mag_offset[1]) / 4096.0f) * 0.88f; + raw.magnetometer_ga[2] = ((raw.magnetometer_raw[2] - mag_offset[2]) / 4096.0f) * 0.88f; + + raw.magnetometer_raw_counter++; + } + + /* BAROMETER */ + if (baro_updated) { + /* copy sensor readings to global data and transform coordinates into px4fmu board frame */ + + raw.baro_pres_mbar = buf_barometer[0]; // Pressure in mbar + raw.baro_alt_meter = buf_barometer[1]; // Altitude in meters + raw.baro_temp_celcius = buf_barometer[2]; // Temperature in degrees celcius + + raw.baro_raw_counter++; + } + + /* ADC */ + if (adc_updated) { + /* copy sensor readings to global data*/ + + if (ADC_BATTERY_VOLATGE_CHANNEL == buf_adc.am_channel1) { + /* Voltage in volts */ + raw.battery_voltage_v = (BAT_VOL_LOWPASS_1 * (raw.battery_voltage_v + BAT_VOL_LOWPASS_2 * (uint16_t)(buf_adc.am_data1 * battery_voltage_conversion))); + + if ((buf_adc.am_data1 * battery_voltage_conversion) < VOLTAGE_BATTERY_IGNORE_THRESHOLD_VOLTS) { + raw.battery_voltage_valid = false; + raw.battery_voltage_v = 0.f; + + } else { + raw.battery_voltage_valid = true; + } + + raw.battery_voltage_counter++; + } + } + + uint64_t total_time = hrt_absolute_time() - current_time; + + /* Inform other processes that new data is available to copy */ + if ((gyro_updated || acc_updated || magn_updated || baro_updated) && !hil_enabled) { + /* Values changed, publish */ + orb_publish(ORB_ID(sensor_combined), sensor_pub, &raw); + } + +#ifdef CONFIG_HRT_PPM + + if (ppm_updated) { + orb_publish(ORB_ID(rc_channels), rc_pub, &rc); + } + +#endif + + if (total_time > 2600) { + excessive_readout_time_counter++; + } + + if (total_time > 2600 && excessive_readout_time_counter > 100 && excessive_readout_time_counter % 100 == 0) { + fprintf(stderr, "[sensors] slow update (>2600 us): %d us (#%d)\n", (int)total_time, excessive_readout_time_counter); + + } else if (total_time > 6000) { + if (excessive_readout_time_counter < 100 || excessive_readout_time_counter % 100 == 0) fprintf(stderr, "[sensors] WARNING: Slow update (>6000 us): %d us (#%d)\n", (int)total_time, excessive_readout_time_counter); + } + + + read_loop_counter++; +#ifdef CONFIG_SENSORS_DEBUG_ENABLED + + if (read_loop_counter % 1000 == 0) printf("[sensors] read loop counter: %d\n", read_loop_counter); + + fflush(stdout); + + if (sensors_timer_loop_counter % 1000 == 0) printf("[sensors] timer/trigger loop counter: %d\n", sensors_timer_loop_counter); + +#endif + } + } + + /* Never really getting here */ + printf("[sensors] sensor readout stopped\n"); + + close(fd_gyro); + close(fd_accelerometer); + close(fd_magnetometer); + close(fd_barometer); + close(fd_adc); + + printf("[sensors] exiting.\n"); + + return ret; +} + diff --git a/apps/sensors/sensors.h b/apps/sensors/sensors.h new file mode 100644 index 0000000000..87ea19972b --- /dev/null +++ b/apps/sensors/sensors.h @@ -0,0 +1,14 @@ +/* + * gps.h + * + * Created on: Mar 8, 2012 + * Author: thomasgubler + */ + +#ifndef SENSORS_H_ +#define SENSORS_H_ +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#endif /* SENSORS_H_ */ diff --git a/apps/system/Kconfig b/apps/system/Kconfig new file mode 100644 index 0000000000..44bf5a2e64 --- /dev/null +++ b/apps/system/Kconfig @@ -0,0 +1,20 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +menu "Custom free memory command" +source "$APPSDIR/system/free/Kconfig" +endmenu + +menu "I2C tool" +source "$APPSDIR/system/i2c/Kconfig" +endmenu + +menu "FLASH Program Installation" +source "$APPSDIR/system/install/Kconfig" +endmenu + +menu "readline() support" +source "$APPSDIR/system/readline/Kconfig" +endmenu diff --git a/apps/system/Make.defs b/apps/system/Make.defs new file mode 100644 index 0000000000..1ddabd3375 --- /dev/null +++ b/apps/system/Make.defs @@ -0,0 +1,51 @@ +############################################################################ +# apps/system/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +if ($(CONFIG_VSN_POWEROFF),y) +CONFIGURED_APPS += vsn/poweroff +endif + +if ($(CONFIG_VSN_RAMTRON),y) +CONFIGURED_APPS += vsn/ramtron +endif + +if ($(CONFIG_VSN_SDCARD),y) +CONFIGURED_APPS += vsn/sdcard +endif + +if ($(CONFIG_VSN_SYSINFO),y) +CONFIGURED_APPS += vsn/sysinfo +endif diff --git a/apps/system/Makefile b/apps/system/Makefile new file mode 100644 index 0000000000..a0eb5dfdee --- /dev/null +++ b/apps/system/Makefile @@ -0,0 +1,70 @@ +############################################################################ +# apps/system/Makefile +# +# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config # Current configuration + +# Sub-directories containing system task + +SUBDIRS = free i2c install readline + +# Create the list of installed runtime modules (INSTALLED_DIRS) + +define ADD_DIRECTORY +INSTALLED_DIRS += ${shell if [ -r $1/Makefile ]; then echo "$1"; fi} +endef + +$(foreach DIR, $(SUBDIRS), $(eval $(call ADD_DIRECTORY,$(DIR)))) + +all: nothing +.PHONY: nothing context depend clean distclean + +nothing: + +context: + +depend: + @for dir in $(INSTALLED_DIRS) ; do \ + $(MAKE) -C $$dir depend TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + +clean: + @for dir in $(INSTALLED_DIRS) ; do \ + $(MAKE) -C $$dir clean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + +distclean: clean + @for dir in $(INSTALLED_DIRS) ; do \ + $(MAKE) -C $$dir distclean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done diff --git a/apps/system/free/Kconfig b/apps/system/free/Kconfig new file mode 100644 index 0000000000..239559867e --- /dev/null +++ b/apps/system/free/Kconfig @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config SYSTEM_FREE + bool "NSH free command replacement" + default n + ---help--- + Enable support for the NSH free replacement command. + +if SYSTEM_FREE +endif + diff --git a/apps/system/free/Makefile b/apps/system/free/Makefile new file mode 100644 index 0000000000..974c989133 --- /dev/null +++ b/apps/system/free/Makefile @@ -0,0 +1,114 @@ +############################################################################ +# apps/system/free/Makefile +# +# Copyright (C) 2011 Uros Platise. All rights reserved. +# Author: Uros Platise +# Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# TODO, this makefile should run make under the app dirs, instead of +# sourcing the Make.defs! + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +ifeq ($(WINTOOL),y) +INCDIROPT = -w +endif + +# Hello Application +# TODO: appname can be automatically extracted from the directory name + +APPNAME = free +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 768 + +ASRCS = +CSRCS = free.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: context depend clean distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +# Register application + +.context: + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ + +context: .context + +# Create dependencies + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f .context Make.dep .depend + +-include Make.dep diff --git a/apps/system/free/README.txt b/apps/system/free/README.txt new file mode 100644 index 0000000000..dd92a94ae2 --- /dev/null +++ b/apps/system/free/README.txt @@ -0,0 +1,6 @@ + +This application provides UNIX style memory free information. + + Source: NuttX + Author: Gregory Nutt + Date: 17. March 2011 diff --git a/apps/system/free/free.c b/apps/system/free/free.c new file mode 100644 index 0000000000..2f61a1dae3 --- /dev/null +++ b/apps/system/free/free.c @@ -0,0 +1,112 @@ +/**************************************************************************** + * apps/system/free/free.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include +#include + +#include +#include + + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* \todo Max block size only works on uniform prog mem */ + +void free_getprogmeminfo(struct mallinfo * mem) +{ + uint16_t page = 0, stpage = 0xFFFF; + uint16_t pagesize = 0; + int status; + + mem->arena = 0; + mem->fordblks = 0; + mem->uordblks = 0; + mem->mxordblk = 0; + + for (status=0, page=0; status >= 0; page++) { + + status = up_progmem_ispageerased(page); + pagesize = up_progmem_pagesize(page); + + mem->arena += pagesize; + + /* Is this beginning of new free space section */ + if (status == 0) { + if (stpage == 0xFFFF) stpage = page; + mem->fordblks += pagesize; + } + else if (status != 0) { + mem->uordblks += pagesize; + + if (stpage != 0xFFFF && up_progmem_isuniform()) { + stpage = page - stpage; + if (stpage > mem->mxordblk) + mem->mxordblk = stpage; + stpage = 0xFFFF; + } + } + } + + mem->mxordblk *= pagesize; +} + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int free_main(int argc, char **argv) +{ + struct mallinfo data; + struct mallinfo prog; + +#ifdef CONFIG_CAN_PASS_STRUCTS + data = mallinfo(); +#else + (void)mallinfo(&data); +#endif + + free_getprogmeminfo(&prog); + + printf(" total used free largest\n"); + printf("Data: %11d%11d%11d%11d\n", + data.arena, data.uordblks, data.fordblks, data.mxordblk); + printf("Prog: %11d%11d%11d%11d\n", + prog.arena, prog.uordblks, prog.fordblks, prog.mxordblk); + + return OK; +} diff --git a/apps/system/i2c/Kconfig b/apps/system/i2c/Kconfig new file mode 100644 index 0000000000..745378b372 --- /dev/null +++ b/apps/system/i2c/Kconfig @@ -0,0 +1,61 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + + +config SYSTEM_I2CTOOL + bool "I2C tool" + default n + depends on I2C + ---help--- + Enable support for the I2C tool. + +config I2CTOOL_BUILTIN + bool "NSH built-in command" + default y + depends on SYSTEM_I2CTOOL && NSH_BUILTIN_APPS + ---help--- + Build the tools as an NSH built-in command + +config I2CTOOL_MINBUS + int "Minimum bus number" + default 0 + depends on SYSTEM_I2CTOOL + ---help--- + Smallest bus index supported by the hardware (default 0). + +config I2CTOOL_MAXBUS + int "Maximum bus number" + depends on SYSTEM_I2CTOOL + default 3 + ---help--- + Largest bus index supported by the hardware (default 3) + +config I2CTOOL_MINADDR + hex "Minimum I2C address" + depends on SYSTEM_I2CTOOL + default 0x03 + ---help--- + Minium 7-bit device address (default: 0x03) + +config I2CTOOL_MAXADDR + hex "Maximum I2C address" + depends on SYSTEM_I2CTOOL + default 0x77 + ---help--- + Largest 7-bit device address (default: 0x77) + +config I2CTOOL_MAXREGADDR + hex "Maximum I2C register address" + default 0xff + depends on SYSTEM_I2CTOOL + ---help--- + Largest I2C register address (default: 0xff) + +config I2CTOOL_DEFFREQ + int "Default I2C frequency" + default 4000000 + depends on SYSTEM_I2CTOOL + ---help--- + Default I2C frequency (default: 4000000) diff --git a/apps/system/i2c/Makefile b/apps/system/i2c/Makefile new file mode 100644 index 0000000000..845c149f6c --- /dev/null +++ b/apps/system/i2c/Makefile @@ -0,0 +1,102 @@ +############################################################################ +# apps/system/i2c +# +# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# I2C tool + +ASRCS = +CSRCS = i2c_bus.c i2c_common.c i2c_dev.c i2c_get.c i2c_main.c i2c_set.c i2c_verf.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . +VPATH = + +APPNAME = i2c +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Build targets + +all: .built +.PHONY: .context context .depend depend clean distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) \ + $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep + diff --git a/apps/system/i2c/README.txt b/apps/system/i2c/README.txt new file mode 100755 index 0000000000..97801bcaaa --- /dev/null +++ b/apps/system/i2c/README.txt @@ -0,0 +1,397 @@ +README File for the I2C Tool +============================ + +The I2C tool provides a way to debug I2C related problems. This README file +will provide usage information for the I2C tools. + +CONTENTS +======== + + o System Requirements + - I2C Driver + - Configuration Options + o Help + o Common Line Form + o Common Command Options + - "Sticky" Options + - Environment variables + - Common Option Summary + o Command summary + - bus + - dev + - get + - set + - verf + o I2C Build Configuration + - NuttX Configuration Requirements + - I2C Tool Configuration Options + +System Requirements +=================== + +I2C Driver +---------- +In order to use the I2C driver, you system -- in particular, your I2C driver -- +must meet certain requirements: + +1. It support calling up_i2cinitialize() numerous times, resetting the I2C + hardware on each (initial) time. up_i2cuninitialize() will be called after + each call to up_i2cinitialize() to free any resources and disable the I2C. +2. up_i2cinitialize must accept any interface number without crashing. It + must simply return NULL if the device is not supported. +3. The I2C driver must support the transfer method (CONFIG_I2C_TRANSFER=y). + +The I2C tool is designed to be implemented as a NuttShell (NSH) add-on. Read +the apps/nshlib/README.txt file for information about add-ons. + +Configuration Options +--------------------- +CONFIG_I2CTOOL_BUILTIN - Build the tools as an NSH built-in command +CONFIG_I2CTOOL_MINBUS - Smallest bus index supported by the hardware (default 0). +CONFIG_I2CTOOL_MAXBUS - Largest bus index supported by the hardware (default 3) +CONFIG_I2CTOOL_MINADDR - Minium device address (default: 0x03) +CONFIG_I2CTOOL_MAXADDR - Largest device address (default: 0x77) +CONFIG_I2CTOOL_MAXREGADDR - Largest register address (default: 0xff) +CONFIG_I2CTOOL_DEFFREQ - Default frequency (default: 4000000) + +HELP +==== + +First of all, the I2C tools supports a pretty extensive help output. That +help output can be view by entering either: + + nsh> i2c help + +or + + nsh> i2c ? + +Here is an example of the help output. I shows the general form of the +command line, the various I2C commands supported with their unique command +line options, and a more detailed summary of the command I2C command +options. + + nsh> i2c help + Usage: i2c [arguments] + Where is one of: + + Show help : ? + List buses : bus + List devices : dev [OPTIONS] + Read register : get [OPTIONS] [] + Show help : help + Write register: set [OPTIONS] [] + Verify access : verf [OPTIONS] [] + + Where common "sticky" OPTIONS include: + [-a addr] is the I2C device address (hex). Default: 03 Current: 03 + [-b bus] is the I2C bus number (decimal). Default: 1 Current: 1 + [-r regaddr] is the I2C device register address (hex). Default: 00 Current: 00 + [-w width] is the data width (8 or 16 decimal). Default: 8 Current: 8 + [-s|n], send/don't send start between command and data. Default: -n Current: -n + [-i|j], Auto increment|don't increment regaddr on repititions. Default: NO Current: NO + [-f freq] I2C frequency. Default: 100000 Current: 100000 + + NOTES: + o An environment variable like $PATH may be used for any argument. + o Arguments are "sticky". For example, once the I2C address is + specified, that address will be re-used until it is changed. + + WARNING: + o The I2C dev command may have bad side effects on your I2C devices. + Use only at your own risk. + +COMMAND LINE FORM +================= + +The I2C is started from NSH by invoking the 'i2c' command from the NSH +command line. The general form of the 'i2c' command is: + + i2c [arguments] + +Where is a "sub-command" and identifies one I2C operations supported +by the tool. [arguments] represents the list of arguments needed to perform +the I2C operation. Those arguments vary from command to command as +described below. However, there is also a core set of common OPTIONS +supported by all commands. So perhaps a better representation of the +general I2C command would be: + + i2c [OPTIONS] [arguments] + +Where [OPTIONS] represents the common options and and arguments represent +the operation-specific arguments. + +COMMON COMMAND OPTIONS +====================== + +"Sticky" Options +---------------- +In order to interact with I2C devices, there are a number of I2C parameters +that must be set correctly. One way to do this would be to provide to set +the value of each separate command for each I2C parameter. The I2C tool +takes a different approach, instead: The I2C configuration can be specified +as a (potentially long) sequence of command line arguments. + +These arguments, however, are "sticky." They are sticky in the sense that +once you set the I2C parameter, that value will remain until it is reset +with a new value (or until you reset the board). + +Environment Variables +--------------------- +NOTE also that if environment variables are not disabled (by +CONFIG_DISABLE_ENVIRON=y), then these options may also be environment +variables. Environment variables must be preceded with the special +character $. For example, PWD is the variable that holds the current +working directory and so $PWD could be used as a command line argument. The +use of environment variables on the I2C tools command is really only useful +if you wish to write NSH scripts to execute a longer, more complex series of +I2C commands. + +Common Option Summary +--------------------- + +[-a addr] is the I2C device address (hex). Default: 03 Current: 03 + + The [-a addr] sets the I2C device address. The valid range is 0x03 + through 0x77 (this valid range is controlled by the configuration settings + CONFIG_I2CTOOL_MINADDR and CONFIG_I2CTOOL_MAXADDR). If you are working + with the same device, the address needs to be set only once. + + All I2C address are 7-bit, hexadecimal values. + + NOTE 1: Notice in the "help" output above it shows both default value of + the I2C address (03 hex) and the current address value (also 03 hex). + + NOTE 2: Sometimes I2C addresses are represented as 8-bit values (with + bit zero indicating a read or write operation). The I2C tool uses a + 7-bit representation of the address with bit 7 unused and no read/write + indication in bit 0. Essentially, the 7-bit address is like the 8-bit + address shifted right by 1. + + NOTE 3: Most I2C bus controllers will also support 10-bit addressing. + That capability has not been integrated into the I2C tool as of this + writing. + +[-b bus] is the I2C bus number (decimal). Default: 1 Current: 1 + + Most devices support multiple I2C devices and also have unique bus + numbering. This option identifies which bus you are working with now. + The valid range of bus numbers is controlled by the configuration settings + CONFIG_I2CTOOL_MINBUS and CONFIG_I2CTOOL_MAXBUS. + + The bus numbers are small, decimal numbers. + +[-r regaddr] is the I2C device register address (hex). Default: 00 Current: 00 + + The I2C set and get commands will access registers on the I2C device. This + option selects the device register address (sometimes called the sub-address). + This is an 8-bit hexadecimal value. The maximum value is determined by + the configuration setting CONFIG_I2CTOOL_MAXREGADDR. + +[-w width] is the data width (8 or 16 decimal). Default: 8 Current: 8 + + Device register data may be 8-bit or 16-bit. This options selects one of + those two data widths. + +[-s|n], send/don't send start between command and data. Default: -n Current: -n + + This determines whether or not there should be a new I2C START between + sending of the register address and sending/receiving of the register data. + +[-i|j], Auto increment|don't increment regaddr on repititions. Default: NO Current: NO + + On commands that take a optional number of repetitions, the option can be + used to temporarily increment the regaddr value by one on each repitition. + +[-f freq] I2C frequency. Default: 400000 Current: 400000 + + The [-f freq] sets the frequency of the I2C device. + +COMMAND SUMMARY +=============== + +We have already seen the I2C help (or ?) commands above. This section will +discusse the remaining commands. + +List buses: bus [OPTIONS] +-------------------------- + +This command will simply list all of the configured I2C buses and indicate +which are supported by the driver and which are not: + + BUS EXISTS? + Bus 1: YES + Bus 2: NO + +The valid range of bus numbers is controlled by the configuration settings +CONFIG_I2CTOOL_MINBUS and CONFIG_I2CTOOL_MAXBUS. + +List devices: dev [OPTIONS] +------------------------------------------ + +The 'dev' command will attempt to identify all of the I2C devices on the +selected bus. The and arguments are 7-bit, hexadecimal +I2C addresses. This command will examine a range of addresses beginning +with and continuing through . It will request the value +of register zero from each device. + +If the device at an address responds, then this command will display the +address of the device. If the device does not respond, this command will +display "--". The resulting display is like: + +nsh> i2c dev 03 77 + 0 1 2 3 4 5 6 7 8 9 a b c d e f +00: -- -- -- -- -- -- -- -- -- -- -- -- -- +10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +40: -- -- -- -- -- -- -- -- -- 49 -- -- -- -- -- -- +50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +70: -- -- -- -- -- -- -- -- + +WARNINGS: + o The I2C dev command may have bad side effects on certain I2C devices. + For example, if could cause data loss in an EEPROM device. + o The I2C dev command also depends upon the underlying behavior of the + I2C driver. How does the driver respond to addressing failures? + +Read register: get [OPTIONS] +---------------------------- + + This command will read the value of the I2C register using the selected + I2C parameters in the common options. No other arguments are required. + + This command with write the 8-bit address value then read an 8- or 16-bit + data value from the device. Optionally, it may re-start the transfer + before obtaining the data. + + An optional argument can be supplied to repeat the + read operation an arbitrary number of times (up to 2 billion). If + auto-increment is select (-i), then the register address will be + temporarily incremented on each repitions. The increment is temporary + in the since that it will not alter the "sticky" value of the + register address. + + On success, the output will look like the following (the data value + read will be shown as a 4-character hexadecimal number if the 16-bit + data width option is selected). + + READ Bus: 1 Addr: 49 Subaddr: 04 Value: 96 + + All values (except the bus numbers) are hexadecimal. + +Write register: set [OPTIONS] +------------------------------------- + + This command will write a value to an I2C register using the selected + I2C parameters in the common options. The value to write must be provided + as the final, hexadecimal value. This value may be an 8-bit value (in the + range 00-ff) or a 16-bit value (in the range 0000-ffff), depending upon + the selected data width. + + This command will write the 8-bit address value then write the 8- or 16-bit + data value to the device. Optionally, it may re-start the transfer + before writing the data. + + An optional argument can be supplied to repeat the + write operation an arbitrary number of times (up to 2 billion). If + auto-increment is select (-i), then the register address will be + temporarily incremented on each repitions. The increment is temporary + in the since that it will not alter the "sticky" value of the + register address. + + On success, the output will look like the following (the data value + written will be shown as a 4-character hexadecimal number if the 16-bit + data width option is selected). + + WROTE Bus: 1 Addr: 49 Subaddr: 04 Value: 96 + + All values (except the bus numbers) are hexadecimal. + +Verify access : verf [OPTIONS] [] +------------------------------------------------------ + + This command combines writing and reading from an I2C device register. + It will write a value to an will write a value to an I2C register using + the selected I2C parameters in the common options just as described for + tie 'set' command. Then this command will read the value back just + as described with the 'get' command. Finally, this command will compare + the value read and against the value written and emit an error message + if they do not match. + + If no value is provided, then this command will use the register address + itself as the data, providing for a address-in-address test. + + An optional argument can be supplied to repeat the + verify operation an arbitrary number of times (up to 2 billion). If + auto-increment is select (-i), then the register address will be + temporarily incremented on each repitions. The increment is temporary + in the since that it will not alter the "sticky" value of the + register address. + + On success, the output will look like the following (the data value + written will be shown as a 4-character hexadecimal number if the 16-bit + data width option is selected). + + VERIFY Bus: 1 Addr: 49 Subaddr: 04 Wrote: 96 Read: 92 FAILURE + + All values (except the bus numbers) are hexadecimal. + +I2C BUILD CONFIGURATION +======================= + +NuttX Configuration Requirements +-------------------------------- +The I2C tools requires the following in your NuttX configuration: + +1. Device-specific I2C support must be enabled. The I2C tool will call the + platform-specific function up_i2cinitialize() to get instances of the + I2C interface and the platform-specific function up_i2cuninitialize() + to discard instances of the I2C interface. + + NOTE 1: The I2C interface is defined in include/nuttx/i2c.h. + + NOTE 2: This I2C tool uses direct I2C device interfaces. As such, it + relies on internal OS interfaces that are not normally available to a + user-space program. As a result, the I2C tool cannot be used if a + NuttX is built as a protected, supervisor kernel (CONFIG_NUTTX_KERNEL). + +2. I2C driver configuration + + The CONFIG_I2C_TRANSFER option must also be set in your NuttX + configuration. This configuration is the defconfig file in your + configuration directory that is copied to the NuttX top-level + directory as .config when NuttX is configured. + + CONFIG_I2C_TRANSFER=y + + NOTE: CONFIG_I2C_TRANSFER adds extra methods to the I2C interface. + Not all I2C interfaces support these extra methods. If your platform's + I2C driver does not support these extra methods, then you cannot use + the I2C tool unless you extend the support in your platform I2C + driver. + +3. Application configuration. + + The path to the I2C tool directory must also be set in your NuttX + application configuration. This application configuration is the + appconfig file in your configuration directory that is copied to the + NuttX application directory as .config when NuttX is configured. + + CONFIGURE_APPS += system/i2c + +I2C Tool Configuration Options +------------------------------ + +The default behavior of the I2C tool can be modified by the setting the +options in the NuttX configuration. This configuration is the defconfig +file in your configuration directory that is copied to the NuttX top-level +directory as .config when NuttX is configured. + + CONFIG_I2CTOOL_BUILTIN: Build the tools as an NSH built-in command + CONFIG_I2CTOOL_MINBUS: Smallest bus index supported by the hardware (default 0). + CONFIG_I2CTOOL_MAXBUS: Largest bus index supported by the hardware (default 3) + CONFIG_I2CTOOL_MINADDR: Minium device address (default: 0x03) + CONFIG_I2CTOOL_MAXADDR: Largest device address (default: 0x77) + CONFIG_I2CTOOL_MAXREGADDR: Largest register address (default: 0xff) + CONFIG_I2CTOOL_DEFFREQ: Default frequency (default: 4000000) diff --git a/apps/system/i2c/i2c_bus.c b/apps/system/i2c/i2c_bus.c new file mode 100644 index 0000000000..07e6d2da38 --- /dev/null +++ b/apps/system/i2c/i2c_bus.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * apps/system/i2c/i2c_bus.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "i2ctool.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i2ccmd_bus + ****************************************************************************/ + +int i2ccmd_bus(FAR struct i2ctool_s *i2ctool, int argc, char **argv) +{ + FAR struct i2c_dev_s *dev; + int i; + + i2ctool_printf(i2ctool, " BUS EXISTS?\n"); + for (i = CONFIG_I2CTOOL_MINBUS; i <= CONFIG_I2CTOOL_MAXBUS; i++) + { + dev = up_i2cinitialize(i); + if (dev) + { + i2ctool_printf(i2ctool, "Bus %d: YES\n", i); + (void)up_i2cuninitialize(dev); + } + else + { + i2ctool_printf(i2ctool, "Bus %d: NO\n", i); + } + } + + return OK; +} diff --git a/apps/system/i2c/i2c_common.c b/apps/system/i2c/i2c_common.c new file mode 100644 index 0000000000..e7b27693ad --- /dev/null +++ b/apps/system/i2c/i2c_common.c @@ -0,0 +1,216 @@ +/**************************************************************************** + * apps/system/i2c/i2c_common.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "i2ctool.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: common_args + ****************************************************************************/ + +int common_args(FAR struct i2ctool_s *i2ctool, FAR char **arg) +{ + FAR char *ptr = *arg; + long value; + int ret; + + if (ptr[0] != '-') + { + goto invalid_argument; + } + + switch (ptr[1]) + { + case 'a': + ret = arg_hex(arg, &value); + if (value < CONFIG_I2CTOOL_MINADDR || value > CONFIG_I2CTOOL_MAXADDR) + { + goto out_of_range; + } + + i2ctool->addr = (uint8_t) value; + return ret; + + case 'b': + ret = arg_decimal(arg, &value); + if (value < CONFIG_I2CTOOL_MINBUS || value > CONFIG_I2CTOOL_MAXBUS) + { + goto out_of_range; + } + + i2ctool->bus = (uint8_t) value; + return ret; + + case 'f': + ret = arg_decimal(arg, &value); + if (value == 0) + { + goto out_of_range; + } + + i2ctool->freq = value; + return ret; + + case 'i': + i2ctool->autoincr = true; + return 1; + + case 'j': + i2ctool->autoincr = false; + return 1; + + case 'n': + i2ctool->start = false; + return 1; + + case 'r': + ret = arg_hex(arg, &value); + if (value < 0 || value > CONFIG_I2CTOOL_MAXREGADDR) + { + goto out_of_range; + } + + i2ctool->regaddr = (uint8_t) value; + return ret; + + case 's': + i2ctool->start = true; + return 1; + + case 'w': + ret = arg_decimal(arg, &value); + if (value != 8 && value != 16) + { + goto out_of_range; + } + + i2ctool->width = (uint8_t) value; + return ret; + + default: + goto invalid_argument; + } + +invalid_argument: + i2ctool_printf(i2ctool, g_i2carginvalid, ptr); + return ERROR; + +out_of_range: + i2ctool_printf(i2ctool, g_i2cargrange, ptr); + return ERROR; +} + +/**************************************************************************** + * Name: arg_string + ****************************************************************************/ + +int arg_string(FAR char **arg, FAR char **value) +{ + FAR char *ptr = *arg; + + if (ptr[2] == '\0') + { + *value = arg[1]; + return 2; + } + else + { + *value = &ptr[2]; + return 1; + } +} + +/**************************************************************************** + * Name: arg_decimal + ****************************************************************************/ + +int arg_decimal(FAR char **arg, FAR long *value) +{ + FAR char *string; + int ret; + + ret = arg_string(arg, &string); + *value = strtol(string, NULL, 10); + return ret; +} + +/**************************************************************************** + * Name: arg_hex + ****************************************************************************/ + +int arg_hex(FAR char **arg, FAR long *value) +{ + FAR char *string; + int ret; + + ret = arg_string(arg, &string); + *value = strtol(string, NULL, 16); + return ret; +} diff --git a/apps/system/i2c/i2c_dev.c b/apps/system/i2c/i2c_dev.c new file mode 100644 index 0000000000..f2b5a0e212 --- /dev/null +++ b/apps/system/i2c/i2c_dev.c @@ -0,0 +1,235 @@ +/**************************************************************************** + * apps/system/i2c/i2c_dev.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "i2ctool.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i2ccmd_dev + ****************************************************************************/ + +int i2ccmd_dev(FAR struct i2ctool_s *i2ctool, int argc, char **argv) +{ + FAR struct i2c_dev_s *dev; + struct i2c_msg_s msg[2]; + FAR char *ptr; + union + { + uint16_t data16; + uint8_t data8; + } u; + + uint8_t regaddr; + long first; + long last; + int addr; + int nargs; + int argndx; + int ret; + int i; + int j; + + /* Parse any command line arguments */ + + for (argndx = 1; argndx < argc; ) + { + /* Break out of the look when the last option has been parsed */ + + ptr = argv[argndx]; + if (*ptr != '-') + { + break; + } + + /* Otherwise, check for common options */ + + nargs = common_args(i2ctool, &argv[argndx]); + if (nargs < 0) + { + return ERROR; + } + argndx += nargs; + } + + /* There should be exactly two more things on the command line: The first and + * last addresses to be probed. + */ + + if (argndx+1 < argc) + { + first = strtol(argv[argndx], NULL, 16); + last = strtol(argv[argndx+1], NULL, 16); + if (first < 0 || first > 0x7f || last < 0 || last > 0x7f || first > last) + { + i2ctool_printf(i2ctool, g_i2cargrange, argv[0]); + return ERROR; + } + + argndx += 2; + } + else + { + i2ctool_printf(i2ctool, g_i2cargrequired, argv[0]); + return ERROR; + } + + if (argndx != argc) + { + i2ctool_printf(i2ctool, g_i2ctoomanyargs, argv[0]); + return ERROR; + } + + /* Get a handle to the I2C bus */ + + dev = up_i2cinitialize(i2ctool->bus); + if (!dev) + { + i2ctool_printf(i2ctool, "Failed to get bus %d\n", i2ctool->bus); + return ERROR; + } + + /* Set the frequency and address (NOTE: Only 7-bit address supported now) */ + + I2C_SETFREQUENCY(dev, i2ctool->freq); + + /* Probe each address */ + + i2ctool_printf(i2ctool, " 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); + for (i = 0; i < 128; i += 16) + { + i2ctool_printf(i2ctool, "%02x: ", i); + for (j = 0; j < 16; j++) + { + /* Skip addresses that are out of the selected range */ + + addr = i+j; + if (addr < first || addr > last) + { + i2ctool_printf(i2ctool, " "); + continue; + } + + /* Set the I2C address */ + + I2C_SETADDRESS(dev, addr, 7); + + /* Set up data structures */ + + regaddr = 0; + + msg[0].addr = addr; + msg[0].flags = 0; + msg[0].buffer = ®addr; + msg[0].length = 1; + + msg[1].addr = addr; + msg[1].flags = I2C_M_READ; + if (i2ctool->width == 8) + { + msg[1].buffer = &u.data8; + msg[1].length = 1; + } + else + { + msg[1].buffer = (uint8_t*)&u.data16; + msg[1].length = 2; + } + + if (i2ctool->start) + { + ret = I2C_TRANSFER(dev, &msg[0], 1); + if (ret == OK) + { + ret = I2C_TRANSFER(dev, &msg[1], 1); + } + } + else + { + ret = I2C_TRANSFER(dev, msg, 2); + } + + if (ret == OK) + { + i2ctool_printf(i2ctool, "%02x ", addr); + } + else + { + i2ctool_printf(i2ctool, "-- "); + } + } + i2ctool_printf(i2ctool, "\n"); + i2ctool_flush(i2ctool); + } + + (void)up_i2cuninitialize(dev); + return OK; +} diff --git a/apps/system/i2c/i2c_get.c b/apps/system/i2c/i2c_get.c new file mode 100644 index 0000000000..773f2c9637 --- /dev/null +++ b/apps/system/i2c/i2c_get.c @@ -0,0 +1,257 @@ +/**************************************************************************** + * apps/system/i2c/i2c_get.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "i2ctool.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i2ccmd_get + ****************************************************************************/ + +int i2ccmd_get(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv) +{ + FAR struct i2c_dev_s *dev; + FAR char *ptr; + uint16_t result; + uint8_t regaddr; + long repititions; + int nargs; + int argndx; + int ret; + int i; + + /* Parse any command line arguments */ + + for (argndx = 1; argndx < argc; ) + { + /* Break out of the look when the last option has been parsed */ + + ptr = argv[argndx]; + if (*ptr != '-') + { + break; + } + + /* Otherwise, check for common options */ + + nargs = common_args(i2ctool, &argv[argndx]); + if (nargs < 0) + { + return ERROR; + } + argndx += nargs; + } + + /* There may be one more thing on the command line: The repitition + * count. + */ + + repititions = 1; + if (argndx < argc) + { + repititions = strtol(argv[argndx], NULL, 16); + if (repititions < 1) + { + i2ctool_printf(i2ctool, g_i2cargrange, argv[0]); + return ERROR; + } + + argndx++; + } + + if (argndx != argc) + { + i2ctool_printf(i2ctool, g_i2ctoomanyargs, argv[0]); + return ERROR; + } + + /* Get a handle to the I2C bus */ + + dev = up_i2cinitialize(i2ctool->bus); + if (!dev) + { + i2ctool_printf(i2ctool, "Failed to get bus %d\n", i2ctool->bus); + return ERROR; + } + + /* Set the frequency and the address (NOTE: Only 7-bit address supported now) */ + + I2C_SETFREQUENCY(dev, i2ctool->freq); + I2C_SETADDRESS(dev, i2ctool->addr, 7); + + /* Loop for the requested number of repititions */ + + regaddr = i2ctool->regaddr; + ret = OK; + + for (i = 0; i < repititions; i++) + { + /* Read from the I2C bus */ + + ret = i2ctool_get(i2ctool, dev, regaddr, &result); + + /* Display the result */ + + if (ret == OK) + { + i2ctool_printf(i2ctool, "READ Bus: %d Addr: %02x Subaddr: %02x Value: ", + i2ctool->bus, i2ctool->addr, i2ctool->regaddr); + if (i2ctool->width == 8) + { + i2ctool_printf(i2ctool, "%02x\n", result); + } + else + { + i2ctool_printf(i2ctool, "%04x\n", result); + } + } + else + { + i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret); + break; + } + + /* Auto-increment the address if so configured */ + + if (i2ctool->autoincr) + { + regaddr++; + } + } + + (void)up_i2cuninitialize(dev); + return ret; +} + +/**************************************************************************** + * Name: i2ctool_get + ****************************************************************************/ + +int i2ctool_get(FAR struct i2ctool_s *i2ctool, FAR struct i2c_dev_s *dev, + uint8_t regaddr, uint16_t *result) +{ + struct i2c_msg_s msg[2]; + union + { + uint16_t data16; + uint8_t data8; + } u; + int ret; + + /* Set up data structures */ + + msg[0].addr = i2ctool->addr; + msg[0].flags = 0; + msg[0].buffer = ®addr; + msg[0].length = 1; + + msg[1].addr = i2ctool->addr; + msg[1].flags = I2C_M_READ; + if (i2ctool->width == 8) + { + msg[1].buffer = &u.data8; + msg[1].length = 1; + } + else + { + msg[1].buffer = (uint8_t*)&u.data16; + msg[1].length = 2; + } + + if (i2ctool->start) + { + ret = I2C_TRANSFER(dev, &msg[0], 1); + if (ret== OK) + { + ret = I2C_TRANSFER(dev, &msg[1], 1); + } + } + else + { + ret = I2C_TRANSFER(dev, msg, 2); + } + + /* Return the result of the read operation */ + + if (ret == OK) + { + if (i2ctool->width == 8) + { + *result = (uint16_t)u.data8; + } + else + { + *result = u.data16; + } + } + return ret; +} diff --git a/apps/system/i2c/i2c_main.c b/apps/system/i2c/i2c_main.c new file mode 100644 index 0000000000..2a0e5d626d --- /dev/null +++ b/apps/system/i2c/i2c_main.c @@ -0,0 +1,454 @@ +/**************************************************************************** + * apps/system/i2c/i2c_main.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i2ctool.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int i2ccmd_help(FAR struct i2ctool_s *i2ctool, int argc, char **argv); +static int i2ccmd_unrecognized(FAR struct i2ctool_s *i2ctool, int argc, char **argv); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct i2ctool_s g_i2ctool; + +static const struct cmdmap_s g_i2ccmds[] = +{ + { "?", i2ccmd_help, "Show help ", NULL }, + { "bus", i2ccmd_bus, "List busses ", NULL }, + { "dev", i2ccmd_dev, "List devices ", "[OPTIONS] " }, + { "get", i2ccmd_get, "Read register ", "[OPTIONS] []" }, + { "help", i2ccmd_help, "Show help ", NULL }, + { "set", i2ccmd_set, "Write register", "[OPTIONS] []" }, + { "verf", i2ccmd_verf, "Verify access ", "[OPTIONS] [] []" }, + { NULL, NULL, NULL, NULL } +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Common, message formats */ + +const char g_i2cargrequired[] = "i2ctool: %s: missing required argument(s)\n"; +const char g_i2carginvalid[] = "i2ctool: %s: argument invalid\n"; +const char g_i2cargrange[] = "i2ctool: %s: value out of range\n"; +const char g_i2ccmdnotfound[] = "i2ctool: %s: command not found\n"; +const char g_i2ctoomanyargs[] = "i2ctool: %s: too many arguments\n"; +const char g_i2ccmdfailed[] = "i2ctool: %s: %s failed: %d\n"; +const char g_i2cxfrerror[] = "i2ctool: %s: Transfer failed: %d\n"; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i2ccmd_help + ****************************************************************************/ + +static int i2ccmd_help(FAR struct i2ctool_s *i2ctool, int argc, char **argv) +{ + const struct cmdmap_s *ptr; + + i2ctool_printf(i2ctool, "Usage: i2c [arguments]\n"); + i2ctool_printf(i2ctool, "Where is one of:\n\n"); + for (ptr = g_i2ccmds; ptr->cmd; ptr++) + { + if (ptr->usage) + { + i2ctool_printf(i2ctool, " %s: %s %s\n", ptr->desc, ptr->cmd, ptr->usage); + } + else + { + i2ctool_printf(i2ctool, " %s: %s\n", ptr->desc, ptr->cmd); + } + } + + i2ctool_printf(i2ctool, "\nWhere common \"sticky\" OPTIONS include:\n"); + i2ctool_printf(i2ctool, " [-a addr] is the I2C device address (hex). " + "Default: %02x Current: %02x\n", + CONFIG_I2CTOOL_MINADDR, i2ctool->addr); + i2ctool_printf(i2ctool, " [-b bus] is the I2C bus number (decimal). " + "Default: %d Current: %d\n", + CONFIG_I2CTOOL_MINBUS, i2ctool->bus); + i2ctool_printf(i2ctool, " [-r regaddr] is the I2C device register address (hex). " + "Default: 00 Current: %02x\n", + i2ctool->regaddr); + i2ctool_printf(i2ctool, " [-w width] is the data width (8 or 16 decimal). " + "Default: 8 Current: %d\n", + i2ctool->width); + i2ctool_printf(i2ctool, " [-s|n], send/don't send start between command and data. " + "Default: -n Current: %s\n", + i2ctool->start ? "-s" : "-n"); + i2ctool_printf(i2ctool, " [-i|j], Auto increment|don't increment regaddr on repititions. " + "Default: NO Current: %s\n", + i2ctool->autoincr ? "YES" : "NO"); + i2ctool_printf(i2ctool, " [-f freq] I2C frequency. " + "Default: %d Current: %d\n", + CONFIG_I2CTOOL_DEFFREQ, i2ctool->freq); + i2ctool_printf(i2ctool, "\nNOTES:\n"); +#ifndef CONFIG_DISABLE_ENVIRON + i2ctool_printf(i2ctool, "o An environment variable like $PATH may be used for any argument.\n"); +#endif + i2ctool_printf(i2ctool, "o Arguments are \"sticky\". For example, once the I2C address is\n"); + i2ctool_printf(i2ctool, " specified, that address will be re-used until it is changed.\n"); + i2ctool_printf(i2ctool, "\nWARNING:\n"); + i2ctool_printf(i2ctool, "o The I2C dev command may have bad side effects on your I2C devices.\n"); + i2ctool_printf(i2ctool, " Use only at your own risk.\n"); + return OK; +} + +/**************************************************************************** + * Name: i2ccmd_unrecognized + ****************************************************************************/ + +static int i2ccmd_unrecognized(FAR struct i2ctool_s *i2ctool, int argc, char **argv) +{ + i2ctool_printf(i2ctool, g_i2ccmdnotfound, argv[0]); + return ERROR; +} + +/**************************************************************************** + * Name: i2c_execute + ****************************************************************************/ + +static int i2c_execute(FAR struct i2ctool_s *i2ctool, int argc, char *argv[]) +{ + const struct cmdmap_s *cmdmap; + const char *cmd; + cmd_t handler; + int ret; + + /* The form of argv is: + * + * argv[0]: The command name. This is argv[0] when the arguments + * are, finally, received by the command vtblr + * argv[1]: The beginning of argument (up to MAX_ARGUMENTS) + * argv[argc]: NULL terminating pointer + */ + + /* See if the command is one that we understand */ + + cmd = argv[0]; + handler = i2ccmd_unrecognized; + + for (cmdmap = g_i2ccmds; cmdmap->cmd; cmdmap++) + { + if (strcmp(cmdmap->cmd, cmd) == 0) + { + handler = cmdmap->handler; + break; + } + } + + ret = handler(i2ctool, argc, argv); + return ret; +} + +/**************************************************************************** + * Name: i2c_argument + ****************************************************************************/ + +FAR char *i2c_argument(FAR struct i2ctool_s *i2ctool, int argc, char *argv[], int *pindex) +{ + FAR char *arg; + int index = *pindex; + + /* If we are at the end of the arguments with nothing, then return NULL */ + + if (index >= argc) + { + return NULL; + } + + /* Get the return parameter */ + + arg = argv[index]; + *pindex = index + 1; + +#ifndef CONFIG_DISABLE_ENVIRON + /* Check for references to environment variables */ + + if (arg[0] == '$') + { + /* Return the value of the environment variable with this name */ + + FAR char *value = getenv(arg+1); + if (value) + { + return value; + } + else + { + return (FAR char*)""; + } + } +#endif + + /* Return the next argument. */ + + return arg; +} + +/**************************************************************************** + * Name: i2c_parse + ****************************************************************************/ + +int i2c_parse(FAR struct i2ctool_s *i2ctool, int argc, char *argv[]) +{ + FAR char *newargs[MAX_ARGUMENTS+2]; + FAR char *cmd; + int nargs; + int index; + + /* Parse out the command, skipping the first argument (the program name)*/ + + index = 1; + cmd = i2c_argument(i2ctool, argc, argv, &index); + + /* Check if any command was provided */ + + if (!cmd) + { + /* An empty line is not an error and an unprocessed command cannot + * generate an error, but neither should they change the last + * command status. + */ + + return i2ccmd_help(i2ctool, 0, NULL); + } + + /* Parse all of the arguments following the command name. */ + + newargs[0] = cmd; + for (nargs = 1; nargs <= MAX_ARGUMENTS; nargs++) + { + newargs[nargs] = i2c_argument(i2ctool, argc, argv, &index); + if (!newargs[nargs]) + { + break; + } + } + newargs[nargs] = NULL; + + /* Then execute the command */ + + return i2c_execute(i2ctool, nargs, newargs); +} + +/**************************************************************************** + * Name: i2c_setup + ****************************************************************************/ + +static inline int i2c_setup(FAR struct i2ctool_s *i2ctool) +{ + /* Initialize the output stream */ + +#ifdef CONFIG_I2CTOOL_OUTDEV + i2ctool->ss_outfd = open(CONFIG_I2CTOOL_OUTDEV, O_WRONLY); + if (i2ctool->ss_outfd < 0) + { + fprintf(stderr, g_i2ccmdfailed, "open", errno); + return ERROR; + } + + /* Create a standard C stream on the console device */ + + i2ctool->ss_outstream = fdopen(i2ctool->ss_outfd, "w"); + if (!i2ctool->ss_outstream) + { + fprintf(stderr, g_i2ccmdfailed, "fdopen", errno); + return ERROR; + } +#endif + + return OK; +} + +/**************************************************************************** + * Name: i2c_teardown + * + * Description: + * Close the output stream if it is not the standard output stream. + * + ****************************************************************************/ + +static void i2c_teardown(FAR struct i2ctool_s *i2ctool) +{ + fflush(OUTSTREAM(&g_i2ctool)); + +#ifdef CONFIG_I2CTOOL_OUTDEV + fclose(i2ctool->ss_outstream); +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i2c_main + ****************************************************************************/ + +#ifdef CONFIG_I2CTOOL_BUILTIN +# define MAIN_NAME i2c_main +# define MAIN_NAME_STRING "i2c_main" +#else +# define MAIN_NAME user_start +# define MAIN_NAME_STRING "user_start" +#endif + +int MAIN_NAME(int argc, char *argv[]) +{ + /* Verify settings */ + + if (g_i2ctool.bus < CONFIG_I2CTOOL_MINBUS || g_i2ctool.bus > CONFIG_I2CTOOL_MAXBUS) + { + g_i2ctool.bus = CONFIG_I2CTOOL_MINBUS; + } + + if (g_i2ctool.addr < CONFIG_I2CTOOL_MINADDR || g_i2ctool.addr > CONFIG_I2CTOOL_MAXADDR) + { + g_i2ctool.addr = CONFIG_I2CTOOL_MINADDR; + } + + if (g_i2ctool.regaddr < CONFIG_I2CTOOL_MAXREGADDR) + { + g_i2ctool.regaddr = 0; + } + + if (g_i2ctool.width != 8 && g_i2ctool.width != 16) + { + g_i2ctool.width = 8; + } + + if (g_i2ctool.freq == 0) + { + g_i2ctool.freq = CONFIG_I2CTOOL_DEFFREQ; + } + + /* Parse process the command line */ + + i2c_setup(&g_i2ctool); + (void)i2c_parse(&g_i2ctool, argc, argv); + + i2ctool_flush(&g_i2ctool); + i2c_teardown(&g_i2ctool); + return OK; +} + +/**************************************************************************** + * Name: i2ctool_printf + * + * Description: + * Print a string to the currently selected stream. + * + ****************************************************************************/ + +int i2ctool_printf(FAR struct i2ctool_s *i2ctool, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = vfprintf(OUTSTREAM(i2ctool), fmt, ap); + va_end(ap); + + return ret; +} + +/**************************************************************************** + * Name: i2ctool_write + * + * Description: + * write a buffer to the currently selected stream. + * + ****************************************************************************/ + +ssize_t i2ctool_write(FAR struct i2ctool_s *i2ctool, FAR const void *buffer, size_t nbytes) +{ + ssize_t ret; + + /* Write the data to the output stream */ + + ret = fwrite(buffer, 1, nbytes, OUTSTREAM(i2ctool)); + if (ret < 0) + { + dbg("[%d] Failed to send buffer: %d\n", OUTFD(i2ctool), errno); + } + return ret; +} + +/**************************************************************************** + * Name: i2ctool_flush + * + * Description: + * Flush buffered I/O to the currently selected stream. + * + ****************************************************************************/ + +void i2ctool_flush(FAR struct i2ctool_s *i2ctool) +{ + fflush(OUTSTREAM(i2ctool)); +} diff --git a/apps/system/i2c/i2c_set.c b/apps/system/i2c/i2c_set.c new file mode 100644 index 0000000000..66fd8c85a0 --- /dev/null +++ b/apps/system/i2c/i2c_set.c @@ -0,0 +1,275 @@ +/**************************************************************************** + * apps/system/i2c/i2c_set.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "i2ctool.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i2ccmd_set + ****************************************************************************/ + +int i2ccmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv) +{ + FAR struct i2c_dev_s *dev; + FAR char *ptr; + uint8_t regaddr; + long value; + long repititions; + int nargs; + int argndx; + int ret; + int i; + + /* Parse any command line arguments */ + + for (argndx = 1; argndx < argc; ) + { + /* Break out of the look when the last option has been parsed */ + + ptr = argv[argndx]; + if (*ptr != '-') + { + break; + } + + /* Otherwise, check for common options */ + + nargs = common_args(i2ctool, &argv[argndx]); + if (nargs < 0) + { + return ERROR; + } + argndx += nargs; + } + + /* There must be at least one more thing on the command line: The value + * to be written. + */ + + if (argndx < argc) + { + value = strtol(argv[argndx], NULL, 16); + if (i2ctool->width == 8) + { + if (value < 0 || value > 255) + { + i2ctool_printf(i2ctool, g_i2cargrange, argv[0]); + return ERROR; + } + } + else if (value < 0 || value > 65535) + { + i2ctool_printf(i2ctool, g_i2cargrange, argv[0]); + return ERROR; + } + + argndx++; + } + else + { + i2ctool_printf(i2ctool, g_i2cargrequired, argv[0]); + return ERROR; + } + + /* There may be one more thing on the command line: The repitition + * count. + */ + + repititions = 1; + if (argndx < argc) + { + repititions = strtol(argv[argndx], NULL, 16); + if (repititions < 1) + { + i2ctool_printf(i2ctool, g_i2cargrange, argv[0]); + return ERROR; + } + + argndx++; + } + + if (argndx != argc) + { + i2ctool_printf(i2ctool, g_i2ctoomanyargs, argv[0]); + return ERROR; + } + + /* Get a handle to the I2C bus */ + + dev = up_i2cinitialize(i2ctool->bus); + if (!dev) + { + i2ctool_printf(i2ctool, "Failed to get bus %d\n", i2ctool->bus); + return ERROR; + } + + /* Set the frequency and the address (NOTE: Only 7-bit address supported now) */ + + I2C_SETFREQUENCY(dev, i2ctool->freq); + I2C_SETADDRESS(dev, i2ctool->addr, 7); + + /* Loop for the requested number of repititions */ + + regaddr = i2ctool->regaddr; + ret = OK; + + for (i = 0; i < repititions; i++) + { + /* Write to the I2C bus */ + + ret = i2ctool_set(i2ctool, dev, regaddr, (uint16_t)value); + + /* Display the result */ + + if (ret == OK) + { + i2ctool_printf(i2ctool, "WROTE Bus: %d Addr: %02x Subaddr: %02x Value: ", + i2ctool->bus, i2ctool->addr, i2ctool->regaddr); + if (i2ctool->width == 8) + { + i2ctool_printf(i2ctool, "%02x\n", (int)value); + } + else + { + i2ctool_printf(i2ctool, "%04x\n", (int)value); + } + } + else + { + i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret); + break; + } + + /* Auto-increment the address if so configured */ + + if (i2ctool->autoincr) + { + regaddr++; + } + } + + (void)up_i2cuninitialize(dev); + return ret; +} + +/**************************************************************************** + * Name: i2ctool_set + ****************************************************************************/ + +int i2ctool_set(FAR struct i2ctool_s *i2ctool, FAR struct i2c_dev_s *dev, + uint8_t regaddr, uint16_t value) +{ + struct i2c_msg_s msg[2]; + union + { + uint16_t data16; + uint8_t data8; + } u; + int ret; + + /* Set up data structures */ + + msg[0].addr = i2ctool->addr; + msg[0].flags = 0; + msg[0].buffer = ®addr; + msg[0].length = 1; + + msg[1].addr = i2ctool->addr; + msg[1].flags = 0; + if (i2ctool->width == 8) + { + u.data8 = (uint8_t)value; + msg[1].buffer = &u.data8; + msg[1].length = 1; + } + else + { + u.data16 = value; + msg[1].buffer = (uint8_t*)&u.data16; + msg[1].length = 2; + } + + if (i2ctool->start) + { + ret = I2C_TRANSFER(dev, &msg[0], 1); + if (ret == OK) + { + ret = I2C_TRANSFER(dev, &msg[1], 1); + } + } + else + { + ret = I2C_TRANSFER(dev, msg, 2); + } + + return ret; +} diff --git a/apps/system/i2c/i2c_verf.c b/apps/system/i2c/i2c_verf.c new file mode 100644 index 0000000000..0fa34b96e1 --- /dev/null +++ b/apps/system/i2c/i2c_verf.c @@ -0,0 +1,249 @@ +/**************************************************************************** + * apps/system/i2c/i2c_verf.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "i2ctool.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i2ccmd_verf + ****************************************************************************/ + +int i2ccmd_verf(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv) +{ + FAR struct i2c_dev_s *dev; + FAR char *ptr; + uint16_t rdvalue; + uint8_t regaddr; + bool addrinaddr; + long wrvalue; + long repititions; + int nargs; + int argndx; + int ret; + int i; + + /* Parse any command line arguments */ + + for (argndx = 1; argndx < argc; ) + { + /* Break out of the look when the last option has been parsed */ + + ptr = argv[argndx]; + if (*ptr != '-') + { + break; + } + + /* Otherwise, check for common options */ + + nargs = common_args(i2ctool, &argv[argndx]); + if (nargs < 0) + { + return ERROR; + } + argndx += nargs; + } + + /* The options may be followed by the optional wrvalue to be written. If omitted, then + * the register address will be used as the wrvalue, providing an address-in-address + * test. + */ + + addrinaddr = true; + wrvalue = 0; + + if (argndx < argc) + { + wrvalue = strtol(argv[argndx], NULL, 16); + if (i2ctool->width == 8) + { + if (wrvalue < 0 || wrvalue > 255) + { + i2ctool_printf(i2ctool, g_i2cargrange, argv[0]); + return ERROR; + } + } + else if (wrvalue < 0 || wrvalue > 65535) + { + i2ctool_printf(i2ctool, g_i2cargrange, argv[0]); + return ERROR; + } + + addrinaddr = false; + argndx++; + } + + /* There may be one more thing on the command line: The repitition + * count. + */ + + repititions = 1; + if (argndx < argc) + { + repititions = strtol(argv[argndx], NULL, 16); + if (repititions < 1) + { + i2ctool_printf(i2ctool, g_i2cargrange, argv[0]); + return ERROR; + } + + argndx++; + } + + if (argndx != argc) + { + i2ctool_printf(i2ctool, g_i2ctoomanyargs, argv[0]); + return ERROR; + } + + /* Get a handle to the I2C bus */ + + dev = up_i2cinitialize(i2ctool->bus); + if (!dev) + { + i2ctool_printf(i2ctool, "Failed to get bus %d\n", i2ctool->bus); + return ERROR; + } + + /* Set the frequency and the address (NOTE: Only 7-bit address supported now) */ + + I2C_SETFREQUENCY(dev, i2ctool->freq); + I2C_SETADDRESS(dev, i2ctool->addr, 7); + + /* Loop for the requested number of repititions */ + + regaddr = i2ctool->regaddr; + ret = OK; + + for (i = 0; i < repititions; i++) + { + /* If we are performing an address-in-address test, then use the register + * address as the value to write. + */ + + if (addrinaddr) + { + wrvalue = regaddr; + } + + /* Write to the I2C bus */ + + ret = i2ctool_set(i2ctool, dev, regaddr, (uint16_t)wrvalue); + if (ret == OK) + { + /* Read the value back from the I2C bus */ + + ret = i2ctool_get(i2ctool, dev, regaddr, &rdvalue); + } + + /* Display the result */ + + if (ret == OK) + { + i2ctool_printf(i2ctool, "VERIFY Bus: %d Addr: %02x Subaddr: %02x Wrote: ", + i2ctool->bus, i2ctool->addr, i2ctool->regaddr); + + if (i2ctool->width == 8) + { + i2ctool_printf(i2ctool, "%02x Read: %02x", (int)wrvalue, (int)rdvalue); + } + else + { + i2ctool_printf(i2ctool, "%04x Read: %04x", (int)wrvalue, (int)rdvalue); + } + + if (wrvalue != rdvalue) + { + i2ctool_printf(i2ctool, " <<< FAILURE\n"); + } + else + { + i2ctool_printf(i2ctool, "\n"); + } + } + else + { + i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret); + break; + } + + /* Auto-increment the address if so configured */ + + if (i2ctool->autoincr) + { + regaddr++; + } + } + + (void)up_i2cuninitialize(dev); + return ret; +} diff --git a/apps/system/i2c/i2ctool.h b/apps/system/i2c/i2ctool.h new file mode 100644 index 0000000000..9726f0083f --- /dev/null +++ b/apps/system/i2c/i2ctool.h @@ -0,0 +1,210 @@ +/**************************************************************************** + * apps/system/i2c/i2ctool.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_SYSTEM_I2C_I2CTOOLS_H +#define __APPS_SYSTEM_I2C_I2CTOOLS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_I2CTOOL_BUILTIN - Build the tools as an NSH built-in command + * CONFIG_I2CTOOL_MINBUS - Smallest bus index supported by the hardware (default 0). + * CONFIG_I2CTOOL_MAXBUS - Largest bus index supported by the hardware (default 3) + * CONFIG_I2CTOOL_MINADDR - Minium device address (default: 0x03) + * CONFIG_I2CTOOL_MAXADDR - Largest device address (default: 0x77) + * CONFIG_I2CTOOL_MAXREGADDR - Largest register address (default: 0xff) + * CONFIG_I2CTOOL_DEFFREQ - Default frequency (default: 4000000) + */ + +#ifndef CONFIG_I2C_TRANSFER +# error "CONFIG_I2C_TRANSFER is required in the configuration" +#endif + +#ifndef CONFIG_I2CTOOL_MINBUS +# define CONFIG_I2CTOOL_MINBUS 0 +#endif + +#ifndef CONFIG_I2CTOOL_MAXBUS +# define CONFIG_I2CTOOL_MAXBUS 3 +#endif + +#ifndef CONFIG_I2CTOOL_MINADDR +# define CONFIG_I2CTOOL_MINADDR 0x03 +#endif + +#ifndef CONFIG_I2CTOOL_MAXADDR +# define CONFIG_I2CTOOL_MAXADDR 0x77 +#endif + +#ifndef CONFIG_I2CTOOL_MAXREGADDR +# define CONFIG_I2CTOOL_MAXREGADDR 0xff +#endif + +#ifndef CONFIG_I2CTOOL_DEFFREQ +# define CONFIG_I2CTOOL_DEFFREQ 100000 +#endif + +/* This is the maximum number of arguments that will be accepted for a + * command. The only real limit is in the OS configuration that limits + * the number of parameters passed to a task. + */ + +#define MAX_ARGUMENTS (CONFIG_MAX_TASK_ARGS-1) + +/* Maximum size of one command line */ + +#define MAX_LINELEN 80 + +/* Are we using the NuttX console for I/O? Or some other character device? */ + +#ifdef CONFIG_I2CTOOL_INDEV +# define INFD(p) ((p)->ss_infd) +# define INSTREAM(p) ((p)->ss_instream) +#else +# define INFD(p) 0 +# define INSTREAM(p) stdin +#endif + +#ifdef CONFIG_I2CTOOL_OUTDEV +# define OUTFD(p) ((p)->ss_outfd) +# define OUTSTREAM(p) ((p)->ss_outstream) +#else +# define OUTFD(p) 1 +# define OUTSTREAM(p) stdout +#endif + +/* Output is via printf but can be changed using this macro */ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# define i2c_output(v, fmt...) printf(v, ##fmt) +#else +# define i2c_output printf +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct i2ctool_s +{ + /* Sticky options */ + + uint8_t addr; /* [-a addr] is the I2C device address */ + uint8_t bus; /* [-b bus] is the I2C bus number */ + uint8_t regaddr; /* [-r regaddr] is the I2C device register address */ + uint8_t width; /* [-w width] is the data width (8 or 16) */ + bool start; /* [-s|n], send|don't send start between command and data */ + bool autoincr; /* [-i|j], Auto increment|don't increment regaddr on repititions */ + uint32_t freq; /* [-f freq] I2C frequency */ + + /* Output streams */ + +#ifdef CONFIG_I2CTOOL_OUTDEV + int ss_outfd; /* Output file descriptor */ + FILE *ss_outstream; /* Output stream */ +#endif +}; + +typedef int (*cmd_t)(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); + +struct cmdmap_s +{ + FAR const char *cmd; /* Name of the command */ + cmd_t handler; /* Function that handles the command */ + FAR const char *desc; /* Short description */ + FAR const char *usage; /* Usage instructions for 'help' command */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern const char g_i2cargrequired[]; +extern const char g_i2carginvalid[]; +extern const char g_i2cargrange[]; +extern const char g_i2ccmdnotfound[]; +extern const char g_i2ctoomanyargs[]; +extern const char g_i2ccmdfailed[]; +extern const char g_i2cxfrerror[]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Message handler */ + +ssize_t i2ctool_write(FAR struct i2ctool_s *i2ctool, FAR const void *buffer, size_t nbytes); +int i2ctool_printf(FAR struct i2ctool_s *i2ctool, const char *fmt, ...); +void i2ctool_flush(FAR struct i2ctool_s *i2ctool); + +/* Command handlers */ + +int i2ccmd_bus(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); +int i2ccmd_dev(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); +int i2ccmd_get(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); +int i2ccmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); +int i2ccmd_verf(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); + +/* I2C access functions */ + +int i2ctool_get(FAR struct i2ctool_s *i2ctool, FAR struct i2c_dev_s *dev, + uint8_t addr, uint16_t *result); +int i2ctool_set(FAR struct i2ctool_s *i2ctool, FAR struct i2c_dev_s *dev, + uint8_t regaddr, uint16_t value); + +/* Common logic */ + +int common_args(FAR struct i2ctool_s *i2ctool, FAR char **arg); +int arg_string(FAR char **arg, FAR char **value); +int arg_decimal(FAR char **arg, FAR long *value); +int arg_hex(FAR char **arg, FAR long *value); + +#endif /* __APPS_SYSTEM_I2C_I2CTOOLS_H */ diff --git a/apps/system/install/Kconfig b/apps/system/install/Kconfig new file mode 100644 index 0000000000..a48f67f20b --- /dev/null +++ b/apps/system/install/Kconfig @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config SYSTEM_INSTALL + bool "FLASH installation tool" + default n + ---help--- + Enable support for the FLASH installation tool. + +if SYSTEM_INSTALL +endif + diff --git a/apps/system/install/Makefile b/apps/system/install/Makefile new file mode 100755 index 0000000000..4528ad44ef --- /dev/null +++ b/apps/system/install/Makefile @@ -0,0 +1,114 @@ +############################################################################ +# apps/system/install/Makefile +# +# Copyright (C) 2011 Uros Platise. All rights reserved. +# Author: Uros Platise +# Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# TODO, this makefile should run make under the app dirs, instead of +# sourcing the Make.defs! + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +ifeq ($(WINTOOL),y) +INCDIROPT = -w +endif + +# Hello Application +# TODO: appname can be automatically extracted from the directory name + +APPNAME = install +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 1024 + +ASRCS = +CSRCS = install.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: context depend clean distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +# Register application + +.context: + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ + +context: .context + +# Create dependencies + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f .context Make.dep .depend + +-include Make.dep diff --git a/apps/system/install/README.txt b/apps/system/install/README.txt new file mode 100755 index 0000000000..66e9b0939a --- /dev/null +++ b/apps/system/install/README.txt @@ -0,0 +1,26 @@ + +Install Program +=============== + + Source: NuttX + Author: Uros Platise + Date: 7. May 2011 + +This application installs XIP application by placing it directly into +the program memory (flash) area into free area and creates a start-up +script into selected directory (i.e. /usr/bin/progname). + +Usage: + install [--stack RequiredStackSpace] [--priority Priority] + source-file destination-directory + +If stackspace is not given default stack space of 4096 Bytes is used. +If priority is not given system default is used. + +Additional options: + + --remove destination-file i.e. install --remove /usr/bin/myapp + --force to replace existing installation + --start install app at or after + --margin leave some free space after the kernel + Default is 16 pages so kernel may grow. diff --git a/apps/system/install/install.c b/apps/system/install/install.c new file mode 100755 index 0000000000..2f11c64340 --- /dev/null +++ b/apps/system/install/install.c @@ -0,0 +1,412 @@ +/**************************************************************************** + * apps/system/install/install.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include + + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define ACTION_INSTALL 0x01 +#define ACTION_REMOVE 0x00 +#define ACTION_REINSTALL 0x03 +#define ACTION_INSUFPARAM 0x80 + +#define INSTALL_PROGRAMBLOCKSIZE 1024 + + +/**************************************************************************** + * Private data + ****************************************************************************/ + +const char *install_help = + "Installs XIP program into flash and creates a start-up script in the\n" + "destination directory.\n\n" + "Usage:\t%s [options] source-file.xip destination-directory\n\n" + "Example:\n\t%s --stack 1024 /sdcard/demo.xip /usr/bin\n\n" + "Options:\n" + "\t--stack \n" + "\t--priority \n" + "\t--remove \tRemoves installed application\n" + "\t--force\t\t\tReplaces existing installation\n" + "\t--start \t\tInstalls application at or after \n" + "\t--margin \tLeave some free space after the kernel (default 16)\n"; + +const char *install_script_text = + "# XIP stacksize=%x priority=%x size=%x\n"; + +const char *install_script_exec = + "exec 0x%x\n"; + + +/**************************************************************************** + * Private functions + ****************************************************************************/ + +int install_getstartpage(int startpage, int pagemargin, int desiredsize) +{ + uint16_t page = 0, stpage = 0xFFFF; + uint16_t pagesize = 0; + int maxlen = -1; + int maxlen_start = 0xFFFF; + int status; + + for (status=0, page=0; status >= 0; page++) { + + status = up_progmem_ispageerased(page); + pagesize = up_progmem_pagesize(page); + + /* Is this beginning of new free space section */ + if (status == 0) { + if (stpage == 0xFFFF) stpage = page; + } + else if (status != 0) { + + if (stpage != 0xFFFF) { + + if ( (page - stpage) > maxlen) { + + if (maxlen==-1) { /* First time found sth? */ + stpage += pagemargin; + maxlen = 0; + } + + if(stpage < startpage) + stpage = startpage; + + if (page > stpage) { + maxlen = page - stpage; + maxlen_start = stpage; + } + + if (maxlen*pagesize >= desiredsize) { + /* printf("Found page at %d ... %d\n", stpage, page); */ + return maxlen_start*pagesize; + } + } + + stpage = 0xFFFF; + } + } + } + + /* Requested space is not available */ + + return -1; +} + + +int install_programflash(int startaddr, const char *source) +{ + int status; + int count; + int totalsize = 0; + char *buf; + FILE *fp; + + if ( (buf = malloc(INSTALL_PROGRAMBLOCKSIZE)) == NULL ) + return -errno; + + if ( (fp=fopen(source, "r")) ) { + do { + count = fread(buf, 1, INSTALL_PROGRAMBLOCKSIZE, fp); + + if ( (status = up_progmem_write(startaddr, buf, count)) < 0) { + totalsize = status; + break; + } + + startaddr += count; + totalsize += count; + } + while(count); + } + else totalsize = -errno; + + fclose(fp); + free(buf); + + return totalsize; +} + + +void install_getscriptname(char *scriptname, const char *progname, const char *destdir) +{ + const char * progonly; + + /* I.e. as /usr/bin */ + strcpy(scriptname, destdir); + + /* extract from i.e. /sdcard/demo -> /demo, together with / */ + progonly = strrchr(progname, '/'); + strcat(scriptname, progonly); +} + + +int install_getprogsize(const char *progname) +{ + struct stat fileinfo; + + if ( stat(progname, &fileinfo) < 0 ) + return -1; + + return fileinfo.st_size; +} + + +int install_alreadyexists(const char *scriptname) +{ + FILE *fp; + + if ( (fp=fopen(scriptname, "r"))==NULL ) + return 0; + + fclose(fp); + return 1; +} + + +int install_createscript(int addr, int stacksize, int progsize, + int priority, const char *scriptname) +{ + FILE *fp; + + if ( (fp=fopen(scriptname, "w+"))==NULL ) + return -errno; + + fprintf(fp, install_script_text, stacksize, priority, progsize); + fprintf(fp, install_script_exec, addr); + + fflush(fp); + fclose(fp); + + return 0; +} + + +int install_getlasthexvalue(FILE *fp, char delimiter) +{ + char buf[128]; + char *p; + + if (fgets(buf, 127, fp)) { + if ( (p = strrchr(buf, delimiter)) ) { + return strtol(p+1, NULL, 16); + } + } + return -1; +} + + +int install_remove(const char *scriptname) +{ + FILE *fp; + int progsize, addr, freedsize; + uint16_t page; + int status = 0; + + /* Parse script */ + + if ( (fp=fopen(scriptname, "r")) ) { + progsize = install_getlasthexvalue(fp,'='); + addr = install_getlasthexvalue(fp,' '); + freedsize = progsize; + } + else return -errno; + + fclose(fp); + + /* Remove pages */ + + if (progsize <= 0 || addr <= 0) + return -EIO; + + do { + if ((page = up_progmem_getpage(addr)) < 0) { + status = -page; + break; + } + + if ( up_progmem_erasepage(page) < 0) { + status = -page; + break; + } + + addr += up_progmem_pagesize(page); + progsize -= up_progmem_pagesize(page); + + } while(progsize > 0); + + if (status < 0) return status; + + /* Remove script file */ + + if (unlink(scriptname) < 0) return -errno; + + return freedsize; +} + + +/**************************************************************************** + * Start + ****************************************************************************/ + +int install_main(int argc, char *argv[]) +{ + int i; + int progsize; + int scrsta; + int stacksize = 4096; + int priority = SCHED_PRIORITY_DEFAULT; + int pagemargin = 16; + int startpage = 0; + int startaddr = 0; + int action = ACTION_INSTALL; + char scriptname[128]; + + /* Supported? */ + + if ( !up_progmem_isuniform() ) { + fprintf(stderr, "Error: install supports uniform organization only.\n"); + return -1; + } + + /* Parse arguments */ + + for (i=1; i argc-1) { + action = ACTION_INSUFPARAM; + break; /* are there sufficient parameters */ + } + if ( (scrsta=install_remove(argv[i])) < 0) { + fprintf(stderr, "Could not remove program: %s\n", strerror(-scrsta) ); + return -1; + } + printf("Removed %s and freed %d bytes\n", argv[i], scrsta); + return 0; + + + case ACTION_INSTALL: + if (i > argc-2) { + action = ACTION_INSUFPARAM; + break; /* are there sufficient parameters */ + } + + install_getscriptname(scriptname, argv[i], argv[i+1]); + + // script-exists? + if (install_alreadyexists(scriptname)==1) { + + if (action != ACTION_REINSTALL) { + fprintf(stderr, "Program with that name already exists.\n"); + return -EEXIST; + } + + if ( (scrsta=install_remove(scriptname)) < 0) { + fprintf(stderr, "Could not remove program: %s\n", strerror(-scrsta) ); + return -1; + } + + printf("Replacing %s\n", scriptname); + } + + startaddr = install_getstartpage(startpage, pagemargin, install_getprogsize(argv[i]) ); + if (startpage < 0) { + fprintf(stderr, "Not enough memory\n"); + return -ENOMEM; + } + + if ( (progsize = install_programflash(startaddr, argv[i])) <= 0) { + fprintf(stderr, "Error writing program memory: %s\n" + "Note: Flash pages are not released, so you may try again and program will be\n" + " written in other pages.\n", strerror(-progsize) ); + + return -EIO; + } + if ( (scrsta = install_createscript(startaddr, stacksize, progsize, + priority, scriptname)) < 0) { + fprintf(stderr, "Error writing program script at %s: %s\n", + argv[i+1], strerror(-scrsta) ); + return -EIO; + } + + printf("Installed application of size %d bytes to program memory [%xh - %xh].\n", + progsize, startaddr, startaddr + progsize); + + return 0; + } + + fprintf(stderr, install_help, argv[0], argv[0]); + return -1; +} diff --git a/apps/system/readline/Kconfig b/apps/system/readline/Kconfig new file mode 100644 index 0000000000..2ed9cafd67 --- /dev/null +++ b/apps/system/readline/Kconfig @@ -0,0 +1,39 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config SYSTEM_READLINE + bool "readline() support" + default n + ---help--- + Enable support for the readline() function. + +if SYSTEM_READLINE +config READLINE_ECHO + bool "Echo character input" + default y + ---help--- + Echo received character input back via stdout. This is normal + behavior and should be selected unless the source of stdin input + already has local echo support or you need to suppress the back-channel + responses for any other reason. + +choice + prompt "Newline Options" + default EOL_IS_EITHER_CRLF + +config EOL_IS_CR + bool "EOL is CR" + +config EOL_IS_LF + bool "EOL is LF" + +config EOL_IS_BOTH_CRLF + bool "EOL is CR and LF" + +config EOL_IS_EITHER_CRLF + bool "EOL is CR or LF" + +endchoice +endif diff --git a/apps/system/readline/Makefile b/apps/system/readline/Makefile new file mode 100644 index 0000000000..34fab7e810 --- /dev/null +++ b/apps/system/readline/Makefile @@ -0,0 +1,103 @@ +############################################################################ +# apps/system/readline/Makefile +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +ifeq ($(WINTOOL),y) +INCDIROPT = -w +endif + +# The Readline Library + +ASRCS = +CSRCS = readline.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: context depend clean distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +# Context build phase target + +context: + +# Dependency build phase target + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +# Housekeeping targets + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f .context Make.dep .depend + +-include Make.dep diff --git a/apps/system/readline/readline.c b/apps/system/readline/readline.c new file mode 100644 index 0000000000..f7fa6a6351 --- /dev/null +++ b/apps/system/readline/readline.c @@ -0,0 +1,345 @@ +/**************************************************************************** + * lib/stdio/lib_fgets.c + * + * Copyright (C) 2007-2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* In some systems, the underlying serial logic may automatically echo + * characters back to the console. We will assume that that is not the case + & here + */ + +#define CONFIG_READLINE_ECHO 1 + +/* Some environments may return CR as end-of-line, others LF, and others + * both. The logic here assumes either but not both. + */ + +#undef CONFIG_EOL_IS_CR +#undef CONFIG_EOL_IS_LF +#undef CONFIG_EOL_IS_BOTH_CRLF +#define CONFIG_EOL_IS_EITHER_CRLF 1 + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* [K is the VT100 command erases to the end of the line. */ + +static const char g_erasetoeol[] = VT100_CLEAREOL; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: readline_rawgetc + ****************************************************************************/ + +static inline int readline_rawgetc(int infd) +{ + char buffer; + ssize_t nread; + + nread = read(infd, &buffer, 1); + if (nread < 1) + { + /* Return EOF if the end of file (0) or error (-1) occurs */ + + return EOF; + } + return (int)buffer; +} + +/**************************************************************************** + * Name: readline_consoleputc + ****************************************************************************/ + +#ifdef CONFIG_READLINE_ECHO +static inline void readline_consoleputc(int ch, int outfd) +{ + char buffer = ch; + (void)write(outfd, &buffer, 1); +} +#endif + +/**************************************************************************** + * Name: readline_consolewrite + ****************************************************************************/ + +#ifdef CONFIG_READLINE_ECHO +static inline void readline_consolewrite(int outfd, FAR const char *buffer, size_t buflen) +{ + (void)write(outfd, buffer, buflen); +} +#endif + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: readline + * + * readline() reads in at most one less than 'buflen' characters from + * 'instream' and stores them into the buffer pointed to by 'buf'. + * Characters are echoed on 'outstream'. Reading stops after an EOF or a + * newline. If a newline is read, it is stored into the buffer. A null + * terminator is stored after the last character in the buffer. + * + * This version of realine assumes that we are reading and writing to + * a VT100 console. This will not work well if 'instream' or 'outstream' + * corresponds to a raw byte steam. + * + * This function is inspired by the GNU readline but is an entirely + * different creature. + * + * Input Parameters: + * buf - The user allocated buffer to be filled. + * buflen - the size of the buffer. + * instream - The stream to read characters from + * outstream - The stream to each characters to. + * + * Returned values: + * On success, the (positive) number of bytes transferred is returned. + * A length of zero would indicate an end of file condition. On failure, + * a negated errno value is returned. + * + **************************************************************************/ + +ssize_t readline(FAR char *buf, int buflen, FILE *instream, FILE *outstream) +{ + int infd; + int outfd; + int escape; + int nch; + + /* Sanity checks */ + + if (!instream || !outstream || !buf || buflen < 1) + { + return -EINVAL; + } + + if (buflen < 2) + { + *buf = '\0'; + return 0; + } + + /* Extract the file descriptions. This is cheating (and horribly non- + * standard) + */ + + infd = instream->fs_filedes; + outfd = outstream->fs_filedes; + + /* [K is the VT100 command that erases to the end of the line. */ + +#ifdef CONFIG_READLINE_ECHO + readline_consolewrite(outfd, g_erasetoeol, sizeof(g_erasetoeol)); +#endif + + /* Read characters until we have a full line. On each the loop we must + * be assured that there are two free bytes in the line buffer: One for + * the next character and one for the null terminator. + */ + + escape = 0; + nch = 0; + + for(;;) + { + /* Get the next character */ + + int ch = readline_rawgetc(infd); + + /* Are we processing a VT100 escape sequence */ + + if (escape) + { + /* Yes, is it an [, 3 byte sequence */ + + if (ch != ASCII_LBRACKET || escape == 2) + { + /* We are finished with the escape sequence */ + + escape = 0; + ch = 'a'; + } + else + { + /* The next character is the end of a 3-byte sequence. + * NOTE: Some of the [ sequences are longer than + * 3-bytes, but I have not encountered any in normal use + * yet and, so, have not provided the decoding logic. + */ + + escape = 2; + } + } + + /* Check for backspace + * + * There are several notions of backspace, for an elaborate summary see + * http://www.ibb.net/~anne/keyboard.html. There is no clean solution. + * Here both DEL and backspace are treated like backspace here. The + * Unix/Linux screen terminal by default outputs DEL (0x7f) when the + * backspace key is pressed. + */ + + else if (ch == ASCII_BS || ch == ASCII_DEL) + { + /* Eliminate that last character in the buffer. */ + + if (nch > 0) + { + nch--; + +#ifdef CONFIG_READLINE_ECHO + /* Echo the backspace character on the console. Always output + * the backspace character because the VT100 terminal doesn't + * understand DEL properly. + */ + + readline_consoleputc(ASCII_BS, outfd); + readline_consolewrite(outfd, g_erasetoeol, sizeof(g_erasetoeol)); +#endif + } + } + + /* Check for the beginning of a VT100 escape sequence */ + + else if (ch == ASCII_ESC) + { + /* The next character is escaped */ + + escape = 1; + } + + /* Check for end-of-line. This is tricky only in that some + * environments may return CR as end-of-line, others LF, and + * others both. + */ + +#if defined(CONFIG_EOL_IS_LF) || defined(CONFIG_EOL_IS_BOTH_CRLF) + else if (ch == '\n') +#elif defined(CONFIG_EOL_IS_CR) + else if (ch == '\r') +#elif CONFIG_EOL_IS_EITHER_CRLF + else if (ch == '\n' || ch == '\r') +#endif + { + /* The newline is stored in the buffer along with the null + * terminator. + */ + + buf[nch++] = '\n'; + buf[nch] = '\0'; + +#ifdef CONFIG_READLINE_ECHO + /* Echo the newline to the console */ + + readline_consoleputc('\n', outfd); +#endif + return nch; + } + + /* Check for end-of-file */ + + else if (ch == EOF) + { + /* Terminate the line (which might be zero length) */ + + buf[nch] = '\0'; + return nch; + } + + /* Otherwise, check if the character is printable and, if so, put the + * character in the line buffer + */ + + else if (isprint(ch)) + { + buf[nch++] = ch; + +#ifdef CONFIG_READLINE_ECHO + /* Echo the character to the console */ + + readline_consoleputc(ch, outfd); +#endif + /* Check if there is room for another character and the line's + * null terminator. If not then we have to end the line now. + */ + + if (nch + 1 >= buflen) + { + buf[nch] = '\0'; + return nch; + } + } + } +} + diff --git a/apps/systemcmds/boardinfo/.context b/apps/systemcmds/boardinfo/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/systemcmds/boardinfo/Makefile b/apps/systemcmds/boardinfo/Makefile new file mode 100644 index 0000000000..753a6843e5 --- /dev/null +++ b/apps/systemcmds/boardinfo/Makefile @@ -0,0 +1,42 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Build the boardinfo tool. +# + +APPNAME = boardinfo +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +include $(APPDIR)/mk/app.mk diff --git a/apps/systemcmds/boardinfo/boardinfo.c b/apps/systemcmds/boardinfo/boardinfo.c new file mode 100644 index 0000000000..61a6ea2217 --- /dev/null +++ b/apps/systemcmds/boardinfo/boardinfo.c @@ -0,0 +1,265 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: Lorenz Meier + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* @file autopilot and carrier board information app */ + + +#include +#include +#include +#include +#include + +#include "systemlib/systemlib.h" + +__EXPORT int boardinfo_main(int argc, char *argv[]); + +/* + * Reads out the board information + * + * @param argc the number of string arguments (including the executable name) + * @param argv the argument strings + * + * @return 0 on success, 1 on error + */ +int boardinfo_main(int argc, char *argv[]) +{ + const char *commandline_usage = "\tusage: boardinfo [-c|-f] [-t id] [-w \"\"]\n"; + + bool carrier_mode = false; + bool fmu_mode = false; + bool write_mode = false; + char *write_string = 0; + bool silent = false; + bool test_enabled = false; + int test_boardid = -1; + int ch; + + while ((ch = getopt(argc, argv, "cft:w:v")) != -1) { + switch (ch) { + case 'c': + carrier_mode = true; + break; + + case 'f': + fmu_mode = true; + break; + + case 't': + test_enabled = true; + test_boardid = strtol(optarg, NULL, 10); + silent = true; + break; + + case 'w': + write_mode = true; + write_string = optarg; + break; + + default: + printf(commandline_usage); + exit(0); + } + } + + /* Check if write is required - only one mode is allowed then */ + if (write_mode && fmu_mode && carrier_mode) { + fprintf(stderr, "[boardinfo] Please choose only one mode for writing: --carrier or --fmu\n"); + printf(commandline_usage); + return ERROR; + } + + /* Write FMU information + if (fmu_mode && write_mode) { + struct fmu_board_info_s info; + int ret = fmu_store_board_info(&info); + + + if (ret == OK) { + printf("[boardinfo] Successfully wrote FMU board info\n"); + } else { + fprintf(stderr, "[boardinfo] ERROR writing board info to FMU EEPROM, aborting\n"); + return ERROR; + } + }*/ + + /* write carrier board info */ + if (carrier_mode && write_mode) { + + struct carrier_board_info_s info; + bool parse_ok = true; + unsigned parse_idx = 0; + //int maxlen = strlen(write_string); + char *curr_char; + + /* Parse board info string */ + if (write_string[0] != 'P' || write_string[1] != 'X' || write_string[2] != '4') { + fprintf(stderr, "[boardinfo] header must start with 'PX4'\n"); + parse_ok = false; + } + + info.header[0] = 'P'; info.header[1] = 'X'; info.header[2] = '4'; + parse_idx = 3; + /* Copy board name */ + + int i = 0; + + while (write_string[parse_idx] != 0x20 && (parse_idx < sizeof(info.board_name) + sizeof(info.header))) { + info.board_name[i] = write_string[parse_idx]; + i++; parse_idx++; + } + + /* Enforce null termination */ + info.board_name[sizeof(info.board_name) - 1] = '\0'; + + curr_char = write_string + parse_idx; + + /* Index is now on next field */ + info.board_id = strtol(curr_char, &curr_char, 10);//atoi(write_string + parse_index); + info.board_version = strtol(curr_char, &curr_char, 10); + + /* Read in multi ports */ + for (i = 0; i < MULT_COUNT; i++) { + info.multi_port_config[i] = strtol(curr_char, &curr_char, 10); + } + + /* Read in production data */ + info.production_year = strtol(curr_char, &curr_char, 10); + + if (info.production_year < 2012 || info.production_year > 3000) { + fprintf(stderr, "[boardinfo] production year is invalid: %d\n", info.production_year); + parse_ok = false; + } + + info.production_month = strtol(curr_char, &curr_char, 10); + + if (info.production_month < 1 || info.production_month > 12) { + fprintf(stderr, "[boardinfo] production month is invalid: %d\n", info.production_month); + parse_ok = false; + } + + info.production_day = strtol(curr_char, &curr_char, 10); + + if (info.production_day < 1 || info.production_day > 31) { + fprintf(stderr, "[boardinfo] production day is invalid: %d\n", info.production_day); + parse_ok = false; + } + + info.production_fab = strtol(curr_char, &curr_char, 10); + info.production_tester = strtol(curr_char, &curr_char, 10); + + if (!parse_ok) { + /* Parsing failed */ + fprintf(stderr, "[boardinfo] failed parsing info string:\n\t%s\naborting\n", write_string); + return ERROR; + + } else { + int ret = carrier_store_board_info(&info); + + /* Display result */ + if (ret == sizeof(info)) { + printf("[boardinfo] Successfully wrote carrier board info\n"); + + } else { + fprintf(stderr, "[boardinfo] ERROR writing board info to carrier EEPROM (forgot to pull the WRITE_ENABLE line high?), aborting\n"); + return ERROR; + } + } + } + + /* Print FMU information */ + if (fmu_mode && !silent) { + struct fmu_board_info_s info; + int ret = fmu_get_board_info(&info); + + /* Print human readable name */ + if (ret == sizeof(info)) { + printf("[boardinfo] Autopilot:\n\t%s\n", info.header); + + } else { + fprintf(stderr, "[boardinfo] ERROR loading board info from FMU, aborting\n"); + return ERROR; + } + } + + /* print carrier information */ + if (carrier_mode && !silent) { + + struct carrier_board_info_s info; + int ret = carrier_get_board_info(&info); + + /* Print human readable name */ + if (ret == sizeof(info)) { + printf("[boardinfo] Carrier board:\n\t%s\n", info.header); + printf("\tboard id:\t\t%d\n", info.board_id); + printf("\tversion:\t\t%d\n", info.board_version); + + for (unsigned i = 0; i < MULT_COUNT; i++) { + printf("\tmulti port #%d:\t\t%s: function #%d\n", i, multiport_info.port_names[i], info.multi_port_config[i]); + } + + printf("\tproduction date:\t%d-%d-%d (fab #%d / tester #%d)\n", info.production_year, info.production_month, info.production_day, info.production_fab, info.production_tester); + + } else { + fprintf(stderr, "[boardinfo] ERROR loading board info from carrier EEPROM (errno #%d), aborting\n", -ret); + return ERROR; + } + } + + /* test for a specific carrier */ + if (test_enabled) { + + struct carrier_board_info_s info; + int ret = carrier_get_board_info(&info); + + if (ret != sizeof(info)) { + fprintf(stderr, "[boardinfo] ERROR loading board info from EEPROM (errno #%d), aborting\n", -ret); + exit(1); + } + + if (info.board_id == test_boardid) { + printf("[boardinfo] Found carrier board with ID %d, test succeeded\n", info.board_id); + exit(0); + + } else { + /* exit silently with an error so we can test for multiple boards quietly */ + exit(1); + } + } + + return 0; +} + + diff --git a/apps/systemcmds/calibration/Makefile b/apps/systemcmds/calibration/Makefile new file mode 100644 index 0000000000..aa1aa77610 --- /dev/null +++ b/apps/systemcmds/calibration/Makefile @@ -0,0 +1,42 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Makefile to build the calibration tool +# + +APPNAME = calibration +PRIORITY = SCHED_PRIORITY_MAX - 1 +STACKSIZE = 4096 + +include $(APPDIR)/mk/app.mk diff --git a/apps/systemcmds/calibration/calibration.c b/apps/systemcmds/calibration/calibration.c new file mode 100755 index 0000000000..7f8b9240f4 --- /dev/null +++ b/apps/systemcmds/calibration/calibration.c @@ -0,0 +1,147 @@ +/**************************************************************************** + * calibration.c + * + * Copyright (C) 2012 Ivan Ovinnikov. All rights reserved. + * Authors: Nils Wenzler + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include +#include +#include +#include "calibration.h" + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int calibrate_help(int argc, char *argv[]); +static int calibrate_all(int argc, char *argv[]); + +__EXPORT int calibration_main(int argc, char *argv[]); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct { + const char *name; + int (* fn)(int argc, char *argv[]); + unsigned options; +#define OPT_NOHELP (1<<0) +#define OPT_NOALLTEST (1<<1) +} calibrates[] = { + {"range", range_cal, 0}, + {"servo", servo_cal, 0}, + {"all", calibrate_all, OPT_NOALLTEST}, + {"help", calibrate_help, OPT_NOALLTEST | OPT_NOHELP}, + {NULL, NULL} +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int +calibrate_help(int argc, char *argv[]) +{ + unsigned i; + + printf("Available calibration routines:\n"); + + for (i = 0; calibrates[i].name; i++) + printf(" %s\n", calibrates[i].name); + + return 0; +} + +static int +calibrate_all(int argc, char *argv[]) +{ + unsigned i; + char *args[2] = {"all", NULL}; + + printf("Running all calibration routines...\n\n"); + + for (i = 0; calibrates[i].name; i++) { + printf(" %s:\n", calibrates[i].name); + + if (calibrates[i].fn(1, args)) { + printf(" FAIL\n"); + + } else { + printf(" DONE\n"); + } + } + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void press_enter(void) +{ + int c; + printf("Press CTRL+ENTER to continue... \n"); + fflush(stdout); + + do c = getchar(); while ((c != '\n') && (c != EOF)); +} + +/**************************************************************************** + * Name: calibrate_main + ****************************************************************************/ + +int calibration_main(int argc, char *argv[]) +{ + unsigned i; + + if (argc < 2) { + printf("calibration: missing name - 'calibration help' for a list of routines\n"); + return 1; + } + + for (i = 0; calibrates[i].name; i++) { + if (!strcmp(calibrates[i].name, argv[1])) + return calibrates[i].fn(argc - 1, argv + 1); + } + + printf("calibrate: no routines called '%s' - 'calibration help' for a list of routines\n", argv[1]); + return 1; +} diff --git a/apps/systemcmds/calibration/calibration.h b/apps/systemcmds/calibration/calibration.h new file mode 100644 index 0000000000..028853ec8e --- /dev/null +++ b/apps/systemcmds/calibration/calibration.h @@ -0,0 +1,60 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef _CALIBRATION_H +#define _CALIBRATION_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +extern int range_cal(int argc, char *argv[]); +extern int servo_cal(int argc, char *argv[]); + +#endif diff --git a/apps/systemcmds/calibration/channels_cal.c b/apps/systemcmds/calibration/channels_cal.c new file mode 100755 index 0000000000..575138b120 --- /dev/null +++ b/apps/systemcmds/calibration/channels_cal.c @@ -0,0 +1,196 @@ +/**************************************************************************** + * channels_cal.c + * + * Copyright (C) 2012 Nils Wenzler. All rights reserved. + * Authors: Nils Wenzler + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include +#include +#include +#include "calibration.h" + +/**************************************************************************** + * Defines + ****************************************************************************/ +#define ABS(a) (((a) < 0) ? -(a) : (a)) +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +/**************************************************************************** + * Private Data + ****************************************************************************/ +//Store the values here before writing them to global_data_rc_channels +uint16_t old_values[NR_CHANNELS]; +uint16_t cur_values[NR_CHANNELS]; +uint8_t function_map[NR_CHANNELS]; +char names[12][9]; + + + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +void press_enter_2(void) +{ + int c; + printf("Press CTRL+ENTER to continue... \n"); + fflush(stdout); + + do c = getchar(); while ((c != '\n') && (c != EOF)); +} + +/**This gets all current values and writes them to min or max + */ +uint8_t get_val(uint16_t *buffer) +{ + if (0 == global_data_trylock(&global_data_rc_channels->access_conf)) { + uint8_t i; + + for (i = 0; i < NR_CHANNELS; i++) { + printf("Channel: %i\t RAW Value: %i: \n", i, global_data_rc_channels->chan[i].raw); + buffer[i] = global_data_rc_channels->chan[i].raw; + } + + global_data_unlock(&global_data_rc_channels->access_conf); + return 0; + + } else + return -1; +} + +void set_channel(void) +{ + static uint8_t j = 0; + uint8_t i; + + for (i = 0; i < NR_CHANNELS; i++) { + if (ABS(old_values - cur_values) > 50) { + function_map[j] = i; + strcpy(names[i], global_data_rc_channels->function_names[j]); + j++; + } + } +} + +void write_dat(void) +{ + global_data_lock(&global_data_rc_channels->access_conf); + uint8_t i; + + for (i = 0; i < NR_CHANNELS; i++) { + global_data_rc_channels->function[i] = function_map[i]; + strcpy(global_data_rc_channels->chan[i].name, names[i]); + + printf("Channel %i\t Function %s\n", i, + global_data_rc_channels->chan[i].name); + } + + global_data_unlock(&global_data_rc_channels->access_conf); +} + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +int channels_cal(int argc, char *argv[]) +{ + + printf("This routine maps the input functions on the remote control\n"); + printf("to the corresponding function (Throttle, Roll,..)\n"); + printf("Always move the stick all the way\n"); + press_enter_2(); + + printf("Pull the THROTTLE stick down\n"); + press_enter_2(); + + while (get_val(old_values)); + + printf("Move the THROTTLE stick up\n "); + press_enter_2(); + + while (get_val(cur_values)); + + set_channel(); + + printf("Pull the PITCH stick down\n"); + press_enter_2(); + + while (get_val(old_values)); + + printf("Move the PITCH stick up\n "); + press_enter_2(); + + while (get_val(cur_values)); + + set_channel(); + + printf("Put the ROLL stick to the left\n"); + press_enter_2(); + + while (get_val(old_values)); + + printf("Put the ROLL stick to the right\n "); + press_enter_2(); + + while (get_val(cur_values)); + + set_channel(); + + printf("Put the YAW stick to the left\n"); + press_enter_2(); + + while (get_val(old_values)); + + printf("Put the YAW stick to the right\n "); + press_enter_2(); + + while (get_val(cur_values)); + + set_channel(); + + uint8_t k; + + for (k = 5; k < NR_CHANNELS; k++) { + function_map[k] = k; + strcpy(names[k], global_data_rc_channels->function_names[k]); + } + +//write the values to global_data_rc_channels + write_dat(); + + return 0; + +} + diff --git a/apps/systemcmds/calibration/range_cal.c b/apps/systemcmds/calibration/range_cal.c new file mode 100755 index 0000000000..159a0d06b7 --- /dev/null +++ b/apps/systemcmds/calibration/range_cal.c @@ -0,0 +1,224 @@ +/**************************************************************************** + * range_cal.c + * + * Copyright (C) 2012 Nils Wenzler. All rights reserved. + * Authors: Nils Wenzler + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include +#include +#include "calibration.h" + +/**************************************************************************** + * Defines + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ +//Store the values here before writing them to global_data_rc_channels +uint16_t max_values[NR_CHANNELS]; +uint16_t min_values[NR_CHANNELS]; +uint16_t mid_values[NR_CHANNELS]; + + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**This sets the middle values + */ +uint8_t set_mid(void) +{ + if (0 == global_data_trylock(&global_data_rc_channels->access_conf)) { + uint8_t i; + + for (i = 0; i < NR_CHANNELS; i++) { + if (i == global_data_rc_channels->function[ROLL] || + i == global_data_rc_channels->function[YAW] || + i == global_data_rc_channels->function[PITCH]) { + + mid_values[i] = global_data_rc_channels->chan[i].raw; + + } else { + mid_values[i] = (max_values[i] + min_values[i]) / 2; + } + + } + + global_data_unlock(&global_data_rc_channels->access_conf); + return 0; + + } else + return -1; +} + +/**This gets all current values and writes them to min or max + */ +uint8_t get_value(void) +{ + if (0 == global_data_trylock(&global_data_rc_channels->access_conf)) { + uint8_t i; + + for (i = 0; i < NR_CHANNELS; i++) { + //see if the value is bigger or smaller than 1500 (roughly neutral) + //and write to the appropriate array + if (global_data_rc_channels->chan[i].raw != 0 && + global_data_rc_channels->chan[i].raw < 1500) { + min_values[i] = global_data_rc_channels->chan[i].raw; + + } else if (global_data_rc_channels->chan[i].raw != 0 && + global_data_rc_channels->chan[i].raw > 1500) { + max_values[i] = global_data_rc_channels->chan[i].raw; + + } else { + max_values[i] = 0; + min_values[i] = 0; + } + } + + global_data_unlock(&global_data_rc_channels->access_conf); + return 0; + + } else + return -1; +} + + +void write_data(void) +{ + // global_data_lock(&global_data_rc_channels->access_conf); + // uint8_t i; + // for(i=0; i < NR_CHANNELS; i++){ + // //Write the data to global_data_rc_channels (if not 0) + // if(mid_values[i]!=0 && min_values[i]!=0 && max_values[i]!=0){ + // global_data_rc_channels->chan[i].scaling_factor = + // 10000/((max_values[i] - min_values[i])/2); + // + // global_data_rc_channels->chan[i].mid = mid_values[i]; + // } + // + // printf("Channel %i\t Function %s \t\t Min %i\t\t Max %i\t\t Scaling Factor: %i\t Middle Value %i\n", + // i, + // global_data_rc_channels->function_name[global_data_rc_channels->function[i]], + // min_values[i], max_values[i], + // global_data_rc_channels->chan[i].scaling_factor, + // global_data_rc_channels->chan[i].mid); + // } + // global_data_unlock(&global_data_rc_channels->access_conf); + + //Write to the Parameter storage + + global_data_parameter_storage->pm.param_values[PARAM_RC1_MIN] = min_values[0]; + global_data_parameter_storage->pm.param_values[PARAM_RC2_MIN] = min_values[1]; + global_data_parameter_storage->pm.param_values[PARAM_RC3_MIN] = min_values[2]; + global_data_parameter_storage->pm.param_values[PARAM_RC4_MIN] = min_values[3]; + global_data_parameter_storage->pm.param_values[PARAM_RC5_MIN] = min_values[4]; + global_data_parameter_storage->pm.param_values[PARAM_RC6_MIN] = min_values[5]; + global_data_parameter_storage->pm.param_values[PARAM_RC7_MIN] = min_values[6]; + global_data_parameter_storage->pm.param_values[PARAM_RC8_MIN] = min_values[7]; + + + global_data_parameter_storage->pm.param_values[PARAM_RC1_MAX] = max_values[0]; + global_data_parameter_storage->pm.param_values[PARAM_RC2_MAX] = max_values[1]; + global_data_parameter_storage->pm.param_values[PARAM_RC3_MAX] = max_values[2]; + global_data_parameter_storage->pm.param_values[PARAM_RC4_MAX] = max_values[3]; + global_data_parameter_storage->pm.param_values[PARAM_RC5_MAX] = max_values[4]; + global_data_parameter_storage->pm.param_values[PARAM_RC6_MAX] = max_values[5]; + global_data_parameter_storage->pm.param_values[PARAM_RC7_MAX] = max_values[6]; + global_data_parameter_storage->pm.param_values[PARAM_RC8_MAX] = max_values[7]; + + + global_data_parameter_storage->pm.param_values[PARAM_RC1_TRIM] = mid_values[0]; + global_data_parameter_storage->pm.param_values[PARAM_RC2_TRIM] = mid_values[1]; + global_data_parameter_storage->pm.param_values[PARAM_RC3_TRIM] = mid_values[2]; + global_data_parameter_storage->pm.param_values[PARAM_RC4_TRIM] = mid_values[3]; + global_data_parameter_storage->pm.param_values[PARAM_RC5_TRIM] = mid_values[4]; + global_data_parameter_storage->pm.param_values[PARAM_RC6_TRIM] = mid_values[5]; + global_data_parameter_storage->pm.param_values[PARAM_RC7_TRIM] = mid_values[6]; + global_data_parameter_storage->pm.param_values[PARAM_RC8_TRIM] = mid_values[7]; + + usleep(3e6); + uint8_t i; + + for (i = 0; i < NR_CHANNELS; i++) { + printf("Channel %i:\t\t Min %i\t\t Max %i\t\t Scaling Factor: %i\t Middle Value %i\n", + i, + min_values[i], max_values[i], + global_data_rc_channels->chan[i].scaling_factor, + global_data_rc_channels->chan[i].mid); + } + + +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +int range_cal(int argc, char *argv[]) +{ + + printf("The range calibration routine assumes you already did the channel\n"); + printf("assignment\n"); + printf("This routine chooses the minimum, maximum and middle\n"); + printf("value for each channel separatly. The ROLL, PITCH and YAW function\n"); + printf("get their middle value from the RC direct, for the rest it is\n"); + printf("calculated out of the min and max values.\n"); + press_enter(); + + printf("Hold both sticks in lower left corner and continue\n "); + press_enter(); + usleep(500000); + + while (get_value()); + + printf("Hold both sticks in upper right corner and continue\n"); + press_enter(); + usleep(500000); + + while (get_value()); + + printf("Set the trim to 0 and leave the sticks in the neutral position\n"); + press_enter(); + + //Loop until successfull + while (set_mid()); + + //write the values to global_data_rc_channels + write_data(); + + return 0; + +} + diff --git a/apps/systemcmds/calibration/servo_cal.c b/apps/systemcmds/calibration/servo_cal.c new file mode 100644 index 0000000000..96b3045a95 --- /dev/null +++ b/apps/systemcmds/calibration/servo_cal.c @@ -0,0 +1,264 @@ +/**************************************************************************** + * servo_cal.c + * + * Copyright (C) 2012 Nils Wenzler. All rights reserved. + * Authors: Nils Wenzler + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include +#include +#include +#include +#include "calibration.h" + +/**************************************************************************** + * Defines + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ +//Store the values here before writing them to global_data_rc_channels +uint16_t max_values_servo[PWM_SERVO_MAX_CHANNELS]; +uint16_t min_values_servo[PWM_SERVO_MAX_CHANNELS]; +uint16_t mid_values_servo[PWM_SERVO_MAX_CHANNELS]; + +// Servo loop thread + +pthread_t servo_calib_thread; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**This sets the middle values + */ +uint8_t set_mid_s(void) +{ + if (0 == global_data_trylock(&global_data_rc_channels->access_conf)) { + uint8_t i; + + for (i = 0; i < PWM_SERVO_MAX_CHANNELS; i++) { + if (i == global_data_rc_channels->function[ROLL] || + i == global_data_rc_channels->function[YAW] || + i == global_data_rc_channels->function[PITCH]) { + + mid_values_servo[i] = global_data_rc_channels->chan[i].raw; + + } else { + mid_values_servo[i] = (max_values_servo[i] + min_values_servo[i]) / 2; + } + + } + + global_data_unlock(&global_data_rc_channels->access_conf); + return 0; + + } else + return -1; +} + +/**This gets all current values and writes them to min or max + */ +uint8_t get_value_s(void) +{ + if (0 == global_data_trylock(&global_data_rc_channels->access_conf)) { + uint8_t i; + + for (i = 0; i < PWM_SERVO_MAX_CHANNELS; i++) { + //see if the value is bigger or smaller than 1500 (roughly neutral) + //and write to the appropriate array + if (global_data_rc_channels->chan[i].raw != 0 && + global_data_rc_channels->chan[i].raw < 1500) { + min_values_servo[i] = global_data_rc_channels->chan[i].raw; + + } else if (global_data_rc_channels->chan[i].raw != 0 && + global_data_rc_channels->chan[i].raw > 1500) { + max_values_servo[i] = global_data_rc_channels->chan[i].raw; + + } else { + max_values_servo[i] = 0; + min_values_servo[i] = 0; + } + } + + global_data_unlock(&global_data_rc_channels->access_conf); + return 0; + + } else + return -1; +} + + +void write_data_s(void) +{ + // global_data_lock(&global_data_rc_channels->access_conf); + // uint8_t i; + // for(i=0; i < NR_CHANNELS; i++){ + // //Write the data to global_data_rc_channels (if not 0) + // if(mid_values_servo[i]!=0 && min_values_servo[i]!=0 && max_values_servo[i]!=0){ + // global_data_rc_channels->chan[i].scaling_factor = + // 10000/((max_values_servo[i] - min_values_servo[i])/2); + // + // global_data_rc_channels->chan[i].mid = mid_values_servo[i]; + // } + // + // printf("Channel %i\t Function %s \t\t Min %i\t\t Max %i\t\t Scaling Factor: %i\t Middle Value %i\n", + // i, + // global_data_rc_channels->function_name[global_data_rc_channels->function[i]], + // min_values_servo[i], max_values_servo[i], + // global_data_rc_channels->chan[i].scaling_factor, + // global_data_rc_channels->chan[i].mid); + // } + // global_data_unlock(&global_data_rc_channels->access_conf); + + //Write to the Parameter storage + + + + global_data_lock(&global_data_parameter_storage->access_conf); + + global_data_parameter_storage->pm.param_values[PARAM_SERVO1_MIN] = min_values_servo[0]; + global_data_parameter_storage->pm.param_values[PARAM_SERVO2_MIN] = min_values_servo[1]; + global_data_parameter_storage->pm.param_values[PARAM_SERVO3_MIN] = min_values_servo[2]; + global_data_parameter_storage->pm.param_values[PARAM_SERVO4_MIN] = min_values_servo[3]; + + global_data_parameter_storage->pm.param_values[PARAM_SERVO1_MAX] = max_values_servo[0]; + global_data_parameter_storage->pm.param_values[PARAM_SERVO2_MAX] = max_values_servo[1]; + global_data_parameter_storage->pm.param_values[PARAM_SERVO3_MAX] = max_values_servo[2]; + global_data_parameter_storage->pm.param_values[PARAM_SERVO4_MAX] = max_values_servo[3]; + + global_data_parameter_storage->pm.param_values[PARAM_SERVO1_TRIM] = mid_values_servo[0]; + global_data_parameter_storage->pm.param_values[PARAM_SERVO2_TRIM] = mid_values_servo[1]; + global_data_parameter_storage->pm.param_values[PARAM_SERVO3_TRIM] = mid_values_servo[2]; + global_data_parameter_storage->pm.param_values[PARAM_SERVO4_TRIM] = mid_values_servo[3]; + + global_data_unlock(&global_data_parameter_storage->access_conf); + + usleep(3e6); + uint8_t i; + + for (i = 0; i < NR_CHANNELS; i++) { + printf("Channel %i:\t\t Min %i\t\t Max %i\t\t Scaling Factor: %i\t Middle Value %i\n", + i, + min_values_servo[i], max_values_servo[i], + global_data_rc_channels->chan[i].scaling_factor, + global_data_rc_channels->chan[i].mid); + } + +} + +static void *servo_loop(void *arg) +{ + + // Set thread name + prctl(1, "calibration servo", getpid()); + + // initialize servos + int fd; + servo_position_t data[PWM_SERVO_MAX_CHANNELS]; + + fd = open("/dev/pwm_servo", O_RDWR); + + if (fd < 0) { + printf("failed opening /dev/pwm_servo\n"); + } + + ioctl(fd, PWM_SERVO_ARM, 0); + + while (1) { + int i; + + for (i = 0; i < 4; i++) { + data[i] = global_data_rc_channels->chan[global_data_rc_channels->function[THROTTLE]].raw; + } + + int result = write(fd, &data, sizeof(data)); + + if (result != sizeof(data)) { + printf("failed bulk-reading channel values\n"); + } + + // 5Hz loop + usleep(200000); + } + + return NULL; +} + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +int servo_cal(int argc, char *argv[]) +{ + // pthread_attr_t servo_loop_attr; + // pthread_attr_init(&servo_loop_attr); + // pthread_attr_setstacksize(&servo_loop_attr, 1024); + pthread_create(&servo_calib_thread, NULL, servo_loop, NULL); + pthread_join(servo_calib_thread, NULL); + + printf("The servo calibration routine assumes you already did the channel\n"); + printf("assignment with 'calibration channels'\n"); + printf("This routine chooses the minimum, maximum and middle\n"); + printf("value for each channel separately. The ROLL, PITCH and YAW function\n"); + printf("get their middle value from the RC direct, for the rest it is\n"); + printf("calculated out of the min and max values.\n"); + press_enter(); + + printf("Hold both sticks in lower left corner and continue\n "); + press_enter(); + usleep(500000); + + while (get_value_s()); + + printf("Hold both sticks in upper right corner and continue\n"); + press_enter(); + usleep(500000); + + while (get_value_s()); + + printf("Set the trim to 0 and leave the sticks in the neutral position\n"); + press_enter(); + + //Loop until successfull + while (set_mid_s()); + + //write the values to global_data_rc_channels + write_data_s(); + + return 0; + +} + diff --git a/apps/systemcmds/perf/.context b/apps/systemcmds/perf/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/systemcmds/perf/Makefile b/apps/systemcmds/perf/Makefile new file mode 100644 index 0000000000..0134c9948b --- /dev/null +++ b/apps/systemcmds/perf/Makefile @@ -0,0 +1,42 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# perf_counter reporting tool +# + +APPNAME = perf +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +include $(APPDIR)/mk/app.mk diff --git a/apps/systemcmds/perf/perf.c b/apps/systemcmds/perf/perf.c new file mode 100644 index 0000000000..72406e9c79 --- /dev/null +++ b/apps/systemcmds/perf/perf.c @@ -0,0 +1,72 @@ +/**************************************************************************** + * + * Copyright (C) 2012 Lorenz Meier. All rights reserved. + * Author: Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + + +#include +#include +#include + +#include "systemlib/perf_counter.h" + + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +__EXPORT int perf_main(int argc, char *argv[]); + +/**************************************************************************** + * user_start + ****************************************************************************/ + +int perf_main(int argc, char *argv[]) +{ + perf_print_all(); + fflush(stdout); + return 0; +} + + diff --git a/apps/systemcmds/reboot/.context b/apps/systemcmds/reboot/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/systemcmds/reboot/Makefile b/apps/systemcmds/reboot/Makefile new file mode 100644 index 0000000000..9609a24fd0 --- /dev/null +++ b/apps/systemcmds/reboot/Makefile @@ -0,0 +1,42 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Reboot command. +# + +APPNAME = reboot +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +include $(APPDIR)/mk/app.mk diff --git a/apps/systemcmds/reboot/reboot.c b/apps/systemcmds/reboot/reboot.c new file mode 100644 index 0000000000..2a4cb18d0b --- /dev/null +++ b/apps/systemcmds/reboot/reboot.c @@ -0,0 +1,72 @@ +/**************************************************************************** + * apps/reboot.c + * + * Copyright (C) 2012 Lorenz Meier. All rights reserved. + * Author: Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + + +#include +#include +#include + +#include "systemlib/systemlib.h" + + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +__EXPORT int reboot_main(int argc, char *argv[]); + +/**************************************************************************** + * user_start + ****************************************************************************/ + +int reboot_main(int argc, char *argv[]) +{ + reboot(); + return 0; +} + + diff --git a/apps/systemcmds/top/.context b/apps/systemcmds/top/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/systemcmds/top/Makefile b/apps/systemcmds/top/Makefile new file mode 100644 index 0000000000..c45775f4be --- /dev/null +++ b/apps/systemcmds/top/Makefile @@ -0,0 +1,42 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# realtime system performance display +# + +APPNAME = top +PRIORITY = SCHED_PRIORITY_DEFAULT - 10 +STACKSIZE = 3000 + +include $(APPDIR)/mk/app.mk diff --git a/apps/systemcmds/top/top.c b/apps/systemcmds/top/top.c new file mode 100644 index 0000000000..af1bb23d90 --- /dev/null +++ b/apps/systemcmds/top/top.c @@ -0,0 +1,245 @@ +/**************************************************************************** + * apps/reboot.c + * + * Copyright (C) 2012 Lorenz Meier. All rights reserved. + * Author: Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +__EXPORT int top_main(int argc, char *argv[]); + +/**************************************************************************** + * user_start + ****************************************************************************/ + +extern struct system_load_s system_load; + +bool top_sigusr1_rcvd = false; + +int top_main(int argc, char *argv[]) +{ + int t; + + uint64_t total_user_time = 0; + + int running_count = 0; + int blocked_count = 0; + + uint64_t new_time = hrt_absolute_time(); + uint64_t interval_start_time = new_time; + + uint64_t last_times[CONFIG_MAX_TASKS]; + float curr_loads[CONFIG_MAX_TASKS]; + + for (t = 0; t < CONFIG_MAX_TASKS; t++) + last_times[t] = 0; + + float interval_time_ms_inv = 0.f; + + /* Open console directly to grab CTRL-C signal */ + int console = open("/dev/console", O_NONBLOCK | O_RDONLY | O_NOCTTY); + + while (true) +// for (t = 0; t < 10; t++) + { + int i; + + uint64_t curr_time_ms = (hrt_absolute_time() / 1000LLU); + unsigned int curr_time_s = curr_time_ms / 1000LLU; + + uint64_t idle_time_total_ms = (system_load.tasks[0].total_runtime / 1000LLU); + unsigned int idle_time_total_s = idle_time_total_ms / 1000LLU; + + if (new_time > interval_start_time) + interval_time_ms_inv = 1.f / ((float)((new_time - interval_start_time) / 1000)); + + running_count = 0; + blocked_count = 0; + total_user_time = 0; + + for (i = 0; i < CONFIG_MAX_TASKS; i++) { + uint64_t interval_runtime = (system_load.tasks[i].valid && last_times[i] > 0 && system_load.tasks[i].total_runtime > last_times[i]) ? (system_load.tasks[i].total_runtime - last_times[i]) / 1000 : 0; + + last_times[i] = system_load.tasks[i].total_runtime; + + if (system_load.tasks[i].valid && (new_time > interval_start_time)) { + curr_loads[i] = interval_runtime * interval_time_ms_inv; + + if (i > 0) + total_user_time += interval_runtime; + + } else + curr_loads[i] = 0; + } + + for (i = 0; i < CONFIG_MAX_TASKS; i++) { + if (system_load.tasks[i].valid && (new_time > interval_start_time)) { + if (system_load.tasks[i].tcb->pid == 0) { + float idle = curr_loads[0]; + float task_load = (float)(total_user_time) * interval_time_ms_inv; + + if (task_load > (1.f - idle)) task_load = (1.f - idle); /* this can happen if one tasks total runtime was not computed correctly by the scheduler instrumentation TODO */ + + float sched_load = 1.f - idle - task_load; + + /* print system information */ + printf("\033[H"); /* cursor home */ + printf("\033[KProcesses: %d total, %d running, %d sleeping\n", system_load.total_count, running_count, blocked_count); + printf("\033[KCPU usage: %d.%02d%% tasks, %d.%02d%% sched, %d.%02d%% idle\n", (int)(task_load * 100), (int)((task_load * 10000.0f) - (int)(task_load * 100.0f) * 100), (int)(sched_load * 100), (int)((sched_load * 10000.0f) - (int)(sched_load * 100.0f) * 100), (int)(idle * 100), (int)((idle * 10000.0f) - ((int)(idle * 100)) * 100)); + printf("\033[KUptime: %u.%03u s total, %d.%03d s idle\n\033[K\n", curr_time_s, (unsigned int)(curr_time_ms - curr_time_s * 1000LLU), idle_time_total_s, (int)(idle_time_total_ms - idle_time_total_s * 1000)); + + /* 34 chars command name length (32 chars plus two spaces) */ + char header_spaces[CONFIG_TASK_NAME_SIZE + 1]; + memset(header_spaces, ' ', CONFIG_TASK_NAME_SIZE); + header_spaces[CONFIG_TASK_NAME_SIZE] = '\0'; +#if CONFIG_RR_INTERVAL > 0 + printf("\033[KPID\tCOMMAND%s CPU TOTAL \t%%CPU CURR \tMIN STACK USE\tCURR (BASE) PRIO\tRR SLICE\n", header_spaces); +#else + printf("\033[KPID\tCOMMAND%s CPU TOTAL \t%%CPU CURR \tMIN STACK USE\tCURR (BASE) PRIO\n", header_spaces); +#endif + + } else { + enum tstate_e task_state = (enum tstate_e)system_load.tasks[i].tcb->task_state; + + if (task_state == TSTATE_TASK_PENDING || + task_state == TSTATE_TASK_READYTORUN || + task_state == TSTATE_TASK_RUNNING) { + running_count++; + } + + if (task_state == TSTATE_TASK_INACTIVE || /* BLOCKED - Initialized but not yet activated */ + task_state == TSTATE_WAIT_SEM /* BLOCKED - Waiting for a semaphore */ +#ifndef CONFIG_DISABLE_SIGNALS + || task_state == TSTATE_WAIT_SIG /* BLOCKED - Waiting for a signal */ +#endif +#ifndef CONFIG_DISABLE_MQUEUE + || task_state == TSTATE_WAIT_MQNOTEMPTY /* BLOCKED - Waiting for a MQ to become not empty. */ + || task_state == TSTATE_WAIT_MQNOTFULL /* BLOCKED - Waiting for a MQ to become not full. */ +#endif +#ifdef CONFIG_PAGING + || task_state == TSTATE_WAIT_PAGEFILL /* BLOCKED - Waiting for page fill */ +#endif + ) { + blocked_count++; + } + + char spaces[CONFIG_TASK_NAME_SIZE + 2]; + + /* count name len */ + int namelen = 0; + + while (namelen < CONFIG_TASK_NAME_SIZE) { + if (system_load.tasks[i].tcb->name[namelen] == '\0') break; + + namelen++; + } + + int s = 0; + + for (s = 0; s < CONFIG_TASK_NAME_SIZE + 2 - namelen; s++) { + spaces[s] = ' '; + } + + spaces[s] = '\0'; + + char *runtime_spaces = " "; + + if ((system_load.tasks[i].total_runtime / 1000) < 99) { + runtime_spaces = ""; + } + + printf("\033[K % 2d\t%s%s\t% 8lld ms%s \t % 2d.%03d \t % 6d B", (int)system_load.tasks[i].tcb->pid, system_load.tasks[i].tcb->name, spaces, (system_load.tasks[i].total_runtime / 1000), runtime_spaces, (int)(curr_loads[i] * 100), (int)(curr_loads[i] * 100000.0f - (int)(curr_loads[i] * 1000.0f) * 100), (uint32_t)system_load.tasks[i].tcb->adj_stack_ptr - (uint32_t)system_load.tasks[i].tcb->xcp.regs[REG_R13]); + /* Print scheduling info with RR time slice */ +#if CONFIG_RR_INTERVAL > 0 + printf("\t%d\t(%d)\t\t%d\n", (int)system_load.tasks[i].tcb->sched_priority, (int)system_load.tasks[i].tcb->base_priority, (int)system_load.tasks[i].tcb->timeslice); +#else + /* Print scheduling info without time slice*/ + printf("\t%d (%d)\n", (int)system_load.tasks[i].tcb->sched_priority, (int)system_load.tasks[i].tcb->base_priority); +#endif + } + } + } + + printf("\033[K[ Hit Ctrl-C to quit. ]\n\033[J"); + fflush(stdout); + + interval_start_time = new_time; + + char c; + + /* Sleep 200 ms waiting for user input four times */ + /* XXX use poll ... */ + for (int k = 0; k < 4; k++) { + if (read(console, &c, 1) == 1) { + if (c == 0x03 || c == 0x63) { + printf("Abort\n"); + close(console); + return OK; + } + } + + usleep(200000); + } + + new_time = hrt_absolute_time(); + } + + close(console); + + return OK; +} diff --git a/apps/systemlib/Makefile b/apps/systemlib/Makefile new file mode 100644 index 0000000000..cb126825d3 --- /dev/null +++ b/apps/systemlib/Makefile @@ -0,0 +1,49 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# System utility library +# + +CSRCS = hx_stream.c \ + mixer.c \ + perf_counter.c + +# +# XXX this really should be a CONFIG_* test +# +ifeq ($(TARGET),px4fmu) +CSRCS += systemlib.c +endif + +include $(APPDIR)/mk/app.mk diff --git a/apps/systemlib/hx_stream.c b/apps/systemlib/hx_stream.c new file mode 100644 index 0000000000..e7e974998e --- /dev/null +++ b/apps/systemlib/hx_stream.c @@ -0,0 +1,244 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file A simple serial line framing protocol based on HDLC + * with 32-bit CRC protection. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "perf_counter.h" + +#include "hx_stream.h" + + +struct hx_stream { + uint8_t buf[HX_STREAM_MAX_FRAME + 4]; + unsigned frame_bytes; + bool escaped; + bool txerror; + + int fd; + hx_stream_rx_callback callback; + void *callback_arg; + + perf_counter_t pc_tx_frames; + perf_counter_t pc_rx_frames; + perf_counter_t pc_rx_errors; +}; + +/* + * Protocol magic numbers, straight out of HDLC. + */ +#define FBO 0x7e /**< Frame Boundary Octet */ +#define CEO 0x7c /**< Control Escape Octet */ + +static void hx_tx_raw(hx_stream_t stream, uint8_t c); +static void hx_tx_raw(hx_stream_t stream, uint8_t c); +static int hx_rx_frame(hx_stream_t stream); + +static void +hx_tx_raw(hx_stream_t stream, uint8_t c) +{ + if (write(stream->fd, &c, 1) != 1) + stream->txerror = true; +} + +static void +hx_tx_byte(hx_stream_t stream, uint8_t c) +{ + switch (c) { + case FBO: + case CEO: + hx_tx_raw(stream, CEO); + c ^= 0x20; + break; + } + + hx_tx_raw(stream, c); +} + +static int +hx_rx_frame(hx_stream_t stream) +{ + union { + uint8_t b[4]; + uint32_t w; + } u; + unsigned length = stream->frame_bytes; + + /* reset the stream */ + stream->frame_bytes = 0; + stream->escaped = false; + + /* not a real frame - too short */ + if (length < 4) { + if (length > 1) + perf_count(stream->pc_rx_errors); + + return 0; + } + + length -= 4; + + /* compute expected CRC */ + u.w = crc32(&stream->buf[0], length); + + /* compare computed and actual CRC */ + for (unsigned i = 0; i < 4; i++) { + if (u.b[i] != stream->buf[length + i]) { + perf_count(stream->pc_rx_errors); + return 0; + } + } + + /* frame is good */ + perf_count(stream->pc_rx_frames); + stream->callback(stream->callback_arg, &stream->buf[0], length); + return 1; +} + +hx_stream_t +hx_stream_init(int fd, + hx_stream_rx_callback callback, + void *arg) +{ + hx_stream_t stream; + + stream = (hx_stream_t)malloc(sizeof(struct hx_stream)); + + if (stream != NULL) { + memset(stream, 0, sizeof(struct hx_stream)); + stream->fd = fd; + stream->callback = callback; + stream->callback_arg = arg; + } + + return stream; +} + +void +hx_stream_free(hx_stream_t stream) +{ + free(stream); +} + +void +hx_stream_set_counters(hx_stream_t stream, + perf_counter_t tx_frames, + perf_counter_t rx_frames, + perf_counter_t rx_errors) +{ + stream->pc_tx_frames = tx_frames; + stream->pc_rx_frames = rx_frames; + stream->pc_rx_errors = rx_errors; +} + +int +hx_stream_send(hx_stream_t stream, + const void *data, + size_t count) +{ + union { + uint8_t b[4]; + uint32_t w; + } u; + const uint8_t *p = (const uint8_t *)data; + unsigned resid = count; + + if (resid > HX_STREAM_MAX_FRAME) { + errno = EINVAL; + return -1; + } + + /* start the frame */ + hx_tx_raw(stream, FBO); + + /* transmit the data */ + while (resid--) + hx_tx_byte(stream, *p++); + + /* compute the CRC */ + u.w = crc32(data, count); + + /* send the CRC */ + p = &u.b[0]; + resid = 4; + + while (resid--) + hx_tx_byte(stream, *p++); + + /* and the trailing frame separator */ + hx_tx_raw(stream, FBO); + + /* check for transmit error */ + if (stream->txerror) { + stream->txerror = false; + return -1; + } + + return -1; +} + +void +hx_stream_rx(hx_stream_t stream, uint8_t c) +{ + /* frame end? */ + if (c == FBO) { + hx_rx_frame(stream); + return; + } + + /* escaped? */ + if (stream->escaped) { + stream->escaped = false; + c ^= 0x20; + + } else if (c == CEO) { + /* now escaped, ignore the byte */ + stream->escaped = true; + return; + } + + /* save for later */ + if (stream->frame_bytes < sizeof(stream->buf)) + stream->buf[stream->frame_bytes++] = c; +} diff --git a/apps/systemlib/hx_stream.h b/apps/systemlib/hx_stream.h new file mode 100644 index 0000000000..591bb12914 --- /dev/null +++ b/apps/systemlib/hx_stream.h @@ -0,0 +1,121 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file A simple serial line framing protocol based on HDLC + * with 32-bit CRC protection. + */ + +#ifndef _SYSTEMLIB_HX_STREAM_H +#define _SYSTEMLIB_HX_STREAM_H + +#include + +#include "perf_counter.h" + +struct hx_stream; +typedef struct hx_stream *hx_stream_t; + +#define HX_STREAM_MAX_FRAME 64 + +typedef void (* hx_stream_rx_callback)(void *arg, const void *data, size_t length); + +__BEGIN_DECLS + +/** + * Allocate a new hx_stream object. + * + * @param fd The file handle over which the protocol will + * communicate. + * @param callback Called when a frame is received. + * @param callback_arg Passed to the callback. + * @return A handle to the stream, or NULL if memory could + * not be allocated. + */ +__EXPORT extern hx_stream_t hx_stream_init(int fd, + hx_stream_rx_callback callback, + void *arg); + +/** + * Free a hx_stream object. + * + * @param stream A handle returned from hx_stream_init. + */ +__EXPORT extern void hx_stream_free(hx_stream_t stream); + +/** + * Set performance counters for the stream. + * + * Any counter may be set to NULL to disable counting that datum. + * + * @param tx_frames Counter for transmitted frames. + * @param rx_frames Counter for received frames. + * @param rx_errors Counter for short and corrupt received frames. + */ +__EXPORT extern void hx_stream_set_counters(hx_stream_t stream, + perf_counter_t tx_frames, + perf_counter_t rx_frames, + perf_counter_t rx_errors); + +/** + * Send a frame. + * + * This function will block until all frame bytes are sent if + * the descriptor passed to hx_stream_init is marked blocking, + * otherwise it will return -1 (but may transmit a + * runt frame at the same time). + * + * @todo Handling of non-blocking streams needs to be better. + * + * @param stream A handle returned from hx_stream_init. + * @param data Pointer to the data to send. + * @param count The number of bytes to send. + * @return Zero on success, nonzero with errno + * set on error. + */ +__EXPORT extern int hx_stream_send(hx_stream_t stream, + const void *data, + size_t count); + +/** + * Handle a byte from the stream. + * + * @param stream A handle returned from hx_stream_init. + * @param c The character to process. + */ +__EXPORT extern void hx_stream_rx(hx_stream_t stream, + uint8_t c); + +__END_DECLS + +#endif diff --git a/apps/systemlib/mixer.c b/apps/systemlib/mixer.c new file mode 100644 index 0000000000..f372d04bc6 --- /dev/null +++ b/apps/systemlib/mixer.c @@ -0,0 +1,79 @@ +/** + * @file Generic control value mixing library. + * + * This library implements a generic mixer function that can be used + * by any driver or subsytem that wants to combine several control signals + * into a single output. + * + * See mixer.h for more details. + */ + +#include "mixer.h" + +static int +scale_check(struct MixScaler *scale) +{ + if (scale->offset > 1.0f) + return -1; + if (scale->offset > 1.0f) + return -1; + if (scale->lower_limit > scale->upper_limit) + return -1; + if (scale->lower_limit < -1.0f) + return -1; + if (scale->upper_limit > 1.0f) + return -1; + return 0; +} + +int +mixer_check(struct MixMixer *mixer, unsigned control_count) +{ + if (mixer->control_count < 1) + return -1; + if (mixer->control_count > control_count) + return -1; + if (!scale_check(&mixer->output_scaler)) + return -1; + + for (unsigned i = 0; i < mixer->control_count; i++) { + if (mixer->control_scaler[i].control >= control_count) + return -1; + if (!scale_check(&mixer->control_scaler[i])) + return -1; + } + return 0; +} + +static float +scale(struct MixScaler *scaler, float input) +{ + float output; + + if (input < 0.0f) { + output = (input * scaler->negative_scale) + scaler->offset; + } else { + output = (input * scaler->positive_scale) + scaler->offset; + } + if (output > scaler->upper_limit) { + output = scaler->upper_limit; + } else if (output < scaler->lower_limit) { + output = scaler->lower_limit; + } + + return output; +} + +float +mixer_mix(struct MixMixer *mixer, float *controls) +{ + struct MixScaler *scaler; + float sum = 0.0f; + + for (unsigned i = 0; i < mixer->control_count; i++) { + scaler = &mixer->control_scaler[i]; + sum += scale(scaler, controls[scaler->control]); + } + + return scale(&mixer->output_scaler, sum); +} diff --git a/apps/systemlib/mixer.h b/apps/systemlib/mixer.h new file mode 100644 index 0000000000..fe95204a65 --- /dev/null +++ b/apps/systemlib/mixer.h @@ -0,0 +1,130 @@ +/** + * @file Generic control value mixing library. + * + * This library implements a generic mixer function that can be used + * by any driver or subsytem that wants to combine several control signals + * into a single output. + * + * Terminology + * =========== + * + * control + * A mixer input value, typically provided by some controlling + * component of the system. + * + * actuator + * The mixer output value. + * + * Mixing basics + * ============= + * + * An actuator derives its value from the combination of one or more + * control values. Each of the control values is scaled according to + * the actuator's configuration and then combined to produce the + * actuator value, which may then be further scaled to suit the specific + * output type. + * + * Internally, all scaling is performed using floating point values. + * Inputs and outputs are clamped to the range -1.0 to 1.0. + * + * control control control + * | | | + * v v v + * scale scale scale + * | | | + * | v | + * +-------> mix <------+ + * | + * scale + * | + * v + * out + * + * Scaling + * ------- + * + * Each scaler allows the input value to be scaled independently for + * inputs greater/less than zero. An offset can be applied to the output, + * as well as lower and upper boundary constraints. + * Negative scaling factors cause the output to be inverted (negative input + * produces positive output). + * + * Scaler pseudocode: + * + * if (input < 0) + * output = (input * NEGATIVE_SCALE) + OFFSET + * else + * output = (input * POSITIVE_SCALE) + OFFSET + * + * if (output < LOWER_LIMIT) + * output = LOWER_LIMIT + * if (output > UPPER_LIMIT) + * output = UPPER_LIMIT + * + * + * Mixing + * ------ + * + * Mixing is performed by summing the scaled control values. + * + * + * Controls + * -------- + * + * Each mixer is presented with an array of controls from which it + * selects the set that will be mixed for each actuator. + * + * The precise assignment of controls may vary depending on the + * application, but the following assignments should be used + * when appropriate. + * + * control | standard meaning + * --------+----------------------- + * 0 | roll + * 1 | pitch + * 2 | yaw + * 3 | primary thrust + */ + + struct MixScaler + { + unsigned control; /**< control consumed by this scaler */ + float negative_scale; /**< scale for inputs < 0 */ + float positive_scale; /**< scale for inputs > 0 */ + float offset; /**< bias applied to output */ + float lower_limit; /**< minimum output value */ + float upper_limit; /**< maximum output value */ + }; + + struct MixMixer + { + unsigned control_count; /**< number of control scalers */ + struct MixScaler output_scaler; /**< scaler applied to mixer output */ + struct MixScaler control_scaler[0]; /**< array of control scalers */ + }; + +__BEGIN_DECLS + +/** + * Perform a mixer calculation. + * + * Note that the controls array is assumed to be sufficiently large for any control + * index in the mixer. + * + * @param mixer Mixer configuration. + * @param controls Array of input control values. + * @return The mixed output. + */ + __EXPORT float mixer_mix(struct MixMixer *mixer, float *controls); + + /** + * Check a mixer configuration for sanity. + * + * @param mixer The mixer configuration to be checked. + * @param control_count The number of controls in the system. + * @return Zero if the mixer configuration is sane, + * nonzero otherwise. + */ + __EXPORT int mixer_check(struct MixMixer *mixer, unsigned control_count); + +__END_DECLS diff --git a/apps/systemlib/perf_counter.c b/apps/systemlib/perf_counter.c new file mode 100644 index 0000000000..14bd3c4366 --- /dev/null +++ b/apps/systemlib/perf_counter.c @@ -0,0 +1,212 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file perf_counter.c + * + * @brief Performance measuring tools. + */ + +#include +#include +#include +#include + +#include "perf_counter.h" + +/** + * Header common to all counters. + */ +struct perf_ctr_header { + sq_entry_t link; /**< list linkage */ + enum perf_counter_type type; /**< counter type */ + const char *name; /**< counter name */ +}; + +/** + * PC_EVENT counter. + */ +struct perf_ctr_count { + struct perf_ctr_header hdr; + uint64_t event_count; +}; + +/** + * PC_ELAPSED counter. + */ +struct perf_ctr_elapsed { + struct perf_ctr_header hdr; + uint64_t event_count; + uint64_t time_start; + uint64_t time_total; + uint64_t time_least; + uint64_t time_most; +}; + +/** + * List of all known counters. + */ +static sq_queue_t perf_counters; + + +perf_counter_t +perf_alloc(enum perf_counter_type type, const char *name) +{ + perf_counter_t ctr = NULL; + + switch (type) { + case PC_COUNT: + ctr = (perf_counter_t)calloc(sizeof(struct perf_ctr_count), 1); + break; + + case PC_ELAPSED: + ctr = (perf_counter_t)calloc(sizeof(struct perf_ctr_elapsed), 1); + break; + + default: + break; + } + + if (ctr != NULL) { + ctr->type = type; + ctr->name = name; + sq_addfirst(&ctr->link, &perf_counters); + } + + return ctr; +} + +void +perf_free(perf_counter_t handle) +{ + if (handle == NULL) + return; + + sq_rem(&handle->link, &perf_counters); + free(handle); +} + +void +perf_count(perf_counter_t handle) +{ + if (handle == NULL) + return; + + switch (handle->type) { + case PC_COUNT: + ((struct perf_ctr_count *)handle)->event_count++; + break; + + default: + break; + } +} + +void +perf_begin(perf_counter_t handle) +{ + if (handle == NULL) + return; + + switch (handle->type) { + case PC_ELAPSED: + ((struct perf_ctr_elapsed *)handle)->time_start = hrt_absolute_time(); + break; + + default: + break; + } +} + +void +perf_end(perf_counter_t handle) +{ + if (handle == NULL) + return; + + switch (handle->type) { + case PC_ELAPSED: { + struct perf_ctr_elapsed *pce = (struct perf_ctr_elapsed *)handle; + hrt_abstime elapsed = hrt_absolute_time() - pce->time_start; + + pce->event_count++; + pce->time_total += elapsed; + + if ((pce->time_least > elapsed) || (pce->time_least == 0)) + pce->time_least = elapsed; + + if (pce->time_most < elapsed) + pce->time_most = elapsed; + } + + default: + break; + } +} + +void +perf_print_counter(perf_counter_t handle) +{ + if (handle == NULL) + return; + + switch (handle->type) { + case PC_COUNT: + printf("%s: %llu events\n", + handle->name, + ((struct perf_ctr_count *)handle)->event_count); + break; + + case PC_ELAPSED: + printf("%s: %llu events, %lluus elapsed, min %lluus max %lluus\n", + handle->name, + ((struct perf_ctr_elapsed *)handle)->event_count, + ((struct perf_ctr_elapsed *)handle)->time_total, + ((struct perf_ctr_elapsed *)handle)->time_least, + ((struct perf_ctr_elapsed *)handle)->time_most); + + default: + break; + } +} + +void +perf_print_all(void) +{ + perf_counter_t handle = (perf_counter_t)sq_peek(&perf_counters); + + while (handle != NULL) { + perf_print_counter(handle); + handle = (perf_counter_t)sq_next(&handle->link); + } +} diff --git a/apps/systemlib/perf_counter.h b/apps/systemlib/perf_counter.h new file mode 100644 index 0000000000..2ea6591c55 --- /dev/null +++ b/apps/systemlib/perf_counter.h @@ -0,0 +1,113 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Performance measuring tools. + */ + +#ifndef _SYSTEMLIB_PERF_COUNTER_H +#define _SYSTEMLIB_PERF_COUNTER_H value + +/** + * Counter types. + */ +enum perf_counter_type { + PC_COUNT, /**< count the number of times an event occurs */ + PC_ELAPSED /**< measure the time elapsed performing an event */ +}; + +struct perf_ctr_header; +typedef struct perf_ctr_header *perf_counter_t; + +__BEGIN_DECLS + +/** + * Create a new counter. + * + * @param type The type of the new counter. + * @param name The counter name. + * @return Handle for the new counter, or NULL if a counter + * could not be allocated. + */ +__EXPORT extern perf_counter_t perf_alloc(enum perf_counter_type type, const char *name); + +/** + * Free a counter. + * + * @param handle The performance counter's handle. + */ +__EXPORT extern void perf_free(perf_counter_t handle); + +/** + * Count a performance event. + * + * This call only affects counters that take single events; PC_COUNT etc. + * + * @param handle The handle returned from perf_alloc. + */ +__EXPORT extern void perf_count(perf_counter_t handle); + +/** + * Begin a performance event. + * + * This call applies to counters that operate over ranges of time; PC_ELAPSED etc. + * + * @param handle The handle returned from perf_alloc. + */ +__EXPORT extern void perf_begin(perf_counter_t handle); + +/** + * End a performance event. + * + * This call applies to counters that operate over ranges of time; PC_ELAPSED etc. + * + * @param handle The handle returned from perf_alloc. + */ +__EXPORT extern void perf_end(perf_counter_t handle); + + +/** + * Print one performance counter. + * + * @param handle The counter to print. + */ +__EXPORT extern void perf_print_counter(perf_counter_t handle); + +/** + * Print all of the performance counters. + */ +__EXPORT extern void perf_print_all(void); + +__END_DECLS + +#endif diff --git a/apps/systemlib/systemlib.c b/apps/systemlib/systemlib.c new file mode 100644 index 0000000000..6bde8b8ae7 --- /dev/null +++ b/apps/systemlib/systemlib.c @@ -0,0 +1,320 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: Lorenz Meier + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** @file implementation of commonly used low-level system-call like functions */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "systemlib.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +const struct __multiport_info multiport_info = { + .port_names = {"MULT_0_US2_RXTX", "MULT_1_US2_FLOW", "MULT_2_GPIO_12"} +}; + +#define EEPROM_OFFSET 64 + +#define EEPROM_PARAM_MAGIC_BYTE 0xAF + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void kill_task(FAR _TCB *tcb, FAR void *arg); + +/**************************************************************************** + * user_start + ****************************************************************************/ + +int reboot(void) +{ + sched_lock(); + // print text + printf("\r\nRebooting system - ending tasks and performing hard reset\r\n\r\n"); + fflush(stdout); + //usleep(5000); + + /* Sending kill signal to other tasks */ + //killall(); + + /* Waiting maximum time for all to exit */ + //usleep(5000); + //sched_lock(); + + /* Resetting CPU */ + // FIXME Need check for ARM architecture here +#ifndef NVIC_AIRCR +#define NVIC_AIRCR (*((uint32_t*)0xE000ED0C)) +#endif + + /* Set the SYSRESETREQ bit to force a reset */ + NVIC_AIRCR = 0x05fa0004; + + /* Spinning until the board is really reset */ + while (true); + + /* Should never reach here */ + return 0; +} + +void killall() +{ +// printf("Sending SIGUSR1 to all processes now\n"); + + /* iterate through all tasks and send kill signal */ + sched_foreach(kill_task, NULL); +} + +void kill_task(FAR _TCB *tcb, FAR void *arg) +{ + kill(tcb->pid, SIGUSR1); +} + +int store_params_in_eeprom(struct global_data_parameter_storage_t *params) +{ + int ret = ERROR; + int fd = open("/dev/eeprom", O_RDWR | O_NONBLOCK); + int lseek_res = lseek(fd, EEPROM_OFFSET, SEEK_SET); //don't touch first 64 bytes + int write_res; + + if (fd < 0) { + fprintf(stderr, "onboard eeprom: open fail\n"); + ret = ERROR; + + } else if (lseek_res < 0) { + fprintf(stderr, "onboard eeprom: set offet fail\n"); + ret = ERROR; + + } else { + /*Write start magic byte */ + uint8_t mb = EEPROM_PARAM_MAGIC_BYTE; + write_res = write(fd, &mb, sizeof(mb)); + + if (write_res != sizeof(mb)) { + ret = ERROR; + + } else { + for (int i = 0; i < params->pm.size; i++) { + write_res = write(fd, params->pm.param_values + i, sizeof(params->pm.param_values[i])); + + if (write_res != sizeof(params->pm.param_values[i])) return ERROR; + } + + /*Write end magic byte */ + write_res = write(fd, &mb, sizeof(mb)); + + if (write_res != sizeof(mb)) { + ret = ERROR; + + } else { + ret = OK; + } + } + + } + + close(fd); + + return ret; +} + +int get_params_from_eeprom(struct global_data_parameter_storage_t *params) +{ + int ret = ERROR; + uint8_t magic_byte = 0; + int fd = open("/dev/eeprom", O_RDWR | O_NONBLOCK); + int lseek_res = lseek(fd, EEPROM_OFFSET, SEEK_SET); //don't touch first 64 bytes + + if (fd < 0) { + fprintf(stderr, "onboard eeprom: open fail\n"); + ret = ERROR; + + } else if (lseek_res < 0) { + fprintf(stderr, "onboard eeprom: set offet fail\n"); + ret = ERROR; + + } else { + /*Get start magic byte */ + magic_byte = 0; + int read_res = read(fd, &magic_byte, sizeof(uint8_t)); + + if (read_res != sizeof(uint8_t)) { + ret = ERROR; + + } else { + if (magic_byte != EEPROM_PARAM_MAGIC_BYTE) { + ret = ERROR; + fprintf(stderr, "onboard eeprom: parameters: start magic byte wrong\n"); + + } else { + /*get end magic byte */ + lseek_res = lseek(fd, EEPROM_OFFSET + 1 + params->pm.size * sizeof(float), SEEK_SET); // jump to 2nd magic byte + + if (lseek_res == OK) { + /*Get end magic */ + read_res = read(fd, &magic_byte, sizeof(uint8_t)); + + if (read_res != sizeof(uint8_t)) { + ret = ERROR; + + } else { + if (magic_byte != EEPROM_PARAM_MAGIC_BYTE) { + ret = ERROR; + printf("onboard eeprom: parameters: end magic byte wrong\n"); + + } else { + lseek_res = lseek(fd, EEPROM_OFFSET + 1, SEEK_SET); + + /* read data */ + if (lseek_res == OK) { + + for (int i = 0; i < params->pm.size; i++) { + read_res = read(fd, params->pm.param_values + i, sizeof(params->pm.param_values[i])); + + if (read_res != sizeof(params->pm.param_values[i])) return ERROR; + } + + ret = OK; + + } else { + /* lseek #2 failed */ + ret = ERROR; + } + } + } + + } else { + /* lseek #1 failed */ + ret = ERROR; + } + } + } + + } + + close(fd); + + return ret; +} + +#define PX4_BOARD_ID_FMU (5) + +int fmu_get_board_info(struct fmu_board_info_s *info) +{ + /* Check which FMU version we're on */ + struct stat sb; + int statres; + + /* Copy version-specific fields */ + statres = stat("/dev/bma280", &sb); + + if (statres == OK) { + /* BMA280 indicates a v1.7+ board */ + strcpy(info->board_name, "FMU v1.7"); + info->board_version = 17; + + } else { + statres = stat("/dev/bma180", &sb); + + if (statres == OK) { + /* BMA180 indicates a v1.5-v1.6 board */ + strcpy(info->board_name, "FMU v1.6"); + info->board_version = 16; + + } else { + /* If no BMA pressure sensor is present, it is a v1.3 board */ + strcpy(info->board_name, "FMU v1.3"); + info->board_version = 13; + } + } + + /* Copy general FMU fields */ + memcpy(info->header, "PX4", 3); + info->board_id = PX4_BOARD_ID_FMU; + + return sizeof(struct fmu_board_info_s); +} + +int carrier_store_board_info(const struct carrier_board_info_s *info) +{ + int ret; + int fd = open("/dev/eeprom", O_RDWR | O_NONBLOCK); + + if (fd < 0) fprintf(stderr, "[boardinfo carrier] ERROR opening carrier eeprom\n"); + + /* Enforce correct header */ + ret = write(fd, info, sizeof(struct carrier_board_info_s)); + //ret = write(fd, "PX4", 3); + close(fd); + + return ret; +} + +int carrier_get_board_info(struct carrier_board_info_s *info) +{ + int ret; + int fd = open("/dev/eeprom", O_RDONLY | O_NONBLOCK); + + if (fd < 0) fprintf(stderr, "[boardinfo carrier] ERROR opening carrier eeprom\n"); + + ret = read(fd, info, sizeof(struct carrier_board_info_s)); + + /* Enforce NUL termination of human-readable string */ + if (ret == sizeof(struct carrier_board_info_s)) { + info->board_name[sizeof(info->board_name) - 1] = '\0'; + } + + close(fd); + + return ret; +} diff --git a/apps/systemlib/systemlib.h b/apps/systemlib/systemlib.h new file mode 100644 index 0000000000..e75f6ec9ca --- /dev/null +++ b/apps/systemlib/systemlib.h @@ -0,0 +1,116 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: Lorenz Meier + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** @file definition of commonly used low-level system-call like functions */ + +#ifndef SYSTEMLIB_H_ +#define SYSTEMLIB_H_ +#include +#include + +__BEGIN_DECLS + +/** Reboots the board */ +__EXPORT int reboot(void); + +/** Sends SIGUSR1 to all processes */ +__EXPORT void killall(void); + +struct global_data_parameter_storage_t; + +__EXPORT int store_params_in_eeprom(struct global_data_parameter_storage_t *params); + +__EXPORT int get_params_from_eeprom(struct global_data_parameter_storage_t *params); + +enum MULT_PORTS { + MULT_0_US2_RXTX = 0, + MULT_1_US2_FLOW, + MULT_2_GPIO_12, + MULT_COUNT +}; + +/* Check max multi port count */ +#if (MULT_COUNT > 33) +#error "MULT_COUNT HAS TO BE LESS THAN OR EQUAL 33" +#endif + +/* FMU board info, to be stored in the first 64 bytes of the FMU EEPROM */ +#pragma pack(push,1) +struct fmu_board_info_s { + char header[3]; /**< {'P', 'X', '4'} */ + char board_name[20]; /**< Human readable board name, \0 terminated */ + uint8_t board_id; /**< board ID, constantly increasing number per board */ + uint8_t board_version; /**< board version, major * 10 + minor: v1.7 = 17 */ + uint8_t multi_port_config[MULT_COUNT]; /**< Configuration of multi ports 1-3 */ + uint8_t reserved[33 - MULT_COUNT]; /**< Reserved space for more multi ports */ + uint16_t production_year; + uint8_t production_month; + uint8_t production_day; + uint8_t production_fab; + uint8_t production_tester; +}; /**< stores autopilot board information meta data from EEPROM */ +#pragma pack(pop) + +/* Carrier board info, to be stored in the 128 byte board info EEPROM */ +#pragma pack(push,1) +struct carrier_board_info_s { + char header[3]; /**< {'P', 'X', '4'} */ + char board_name[20]; /**< Human readable board name, \0 terminated */ + uint8_t board_id; /**< board ID, constantly increasing number per board */ + uint8_t board_version; /**< board version, major * 10 + minor: v1.7 = 17 */ + uint8_t multi_port_config[MULT_COUNT]; /**< Configuration of multi ports 1-3 */ + uint8_t reserved[33 - MULT_COUNT]; /**< Reserved space for more multi ports */ + uint16_t production_year; + uint8_t production_month; + uint8_t production_day; + uint8_t production_fab; + uint8_t production_tester; + char board_custom_data[64]; +}; /**< stores carrier board information meta data from EEPROM */ +#pragma pack(pop) + +struct __multiport_info { + const char *port_names[MULT_COUNT]; +}; +__EXPORT extern const struct __multiport_info multiport_info; + +__EXPORT int carrier_store_board_info(const struct carrier_board_info_s *info); +__EXPORT int carrier_get_board_info(struct carrier_board_info_s *info); + +__EXPORT int fmu_get_board_info(struct fmu_board_info_s *info); + +__END_DECLS + +#endif /* SYSTEMLIB_H_ */ diff --git a/apps/systemlib/visibility.h b/apps/systemlib/visibility.h new file mode 100644 index 0000000000..9bd20e2a89 --- /dev/null +++ b/apps/systemlib/visibility.h @@ -0,0 +1,60 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Definitions controlling symbol naming and visibility. + * + * This file is normally included automatically by the build system. + */ + +#ifndef __SYSTEMLIB_VISIBILITY_H +#define __SYSTEMLIB_VISIBILITY_H + +#ifdef __EXPORT +# undef __EXPORT +#endif +#define __EXPORT __attribute__ ((visibility ("default"))) + +#ifdef __PRIVATE +# undef __PRIVATE +#endif +#define __PRIVATE __attribute__ ((visibility ("hidden"))) + +#ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +#else +# define __BEGIN_DECLS +# define __END_DECLS +#endif +#endif \ No newline at end of file diff --git a/apps/uORB/.context b/apps/uORB/.context new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/uORB/Makefile b/apps/uORB/Makefile new file mode 100644 index 0000000000..0766a66eb0 --- /dev/null +++ b/apps/uORB/Makefile @@ -0,0 +1,42 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Makefile to build uORB +# + +APPNAME = uorb +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +include $(APPDIR)/mk/app.mk diff --git a/apps/uORB/objects_common.cpp b/apps/uORB/objects_common.cpp new file mode 100644 index 0000000000..8d84ff3c26 --- /dev/null +++ b/apps/uORB/objects_common.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Common object definitions without a better home. + */ + +#include + +#include + +#include +ORB_DEFINE(sensor_mag, struct mag_report); + +#include +ORB_DEFINE(sensor_accel, struct accel_report); + +#include +ORB_DEFINE(sensor_gyro, struct gyro_report); + +#include +ORB_DEFINE(sensor_baro, struct baro_report); + +#include +ORB_DEFINE(output_pwm, struct pwm_output_values); + +#include +ORB_DEFINE(input_rc, struct rc_input_values); + +// XXX need to check wether these should be here +#include "topics/vehicle_attitude.h" +ORB_DEFINE(vehicle_attitude, struct vehicle_attitude_s); + +#include "topics/sensor_combined.h" +ORB_DEFINE(sensor_combined, struct sensor_combined_s); + +#include "topics/vehicle_gps_position.h" +ORB_DEFINE(vehicle_gps_position, struct vehicle_gps_position_s); + +#include "topics/vehicle_status.h" +ORB_DEFINE(vehicle_status, struct vehicle_status_s); + +#include "topics/vehicle_global_position.h" +ORB_DEFINE(vehicle_global_position, struct vehicle_global_position_s); + +#include "topics/vehicle_local_position.h" +ORB_DEFINE(vehicle_local_position, struct vehicle_local_position_s); + +#include "topics/ardrone_control.h" +ORB_DEFINE(ardrone_control, struct ardrone_control_s); + +#include "topics/ardrone_motors_setpoint.h" +ORB_DEFINE(ardrone_motors_setpoint, struct ardrone_motors_setpoint_s); + +#include "topics/rc_channels.h" +ORB_DEFINE(rc_channels, struct rc_channels_s); + +#include "topics/fixedwing_control.h" +ORB_DEFINE(fixedwing_control, struct fixedwing_control_s); + +#include "topics/vehicle_command.h" +ORB_DEFINE(vehicle_command, struct vehicle_command_s); + +#include "topics/vehicle_local_position_setpoint.h" +ORB_DEFINE(vehicle_local_position_setpoint, struct vehicle_local_position_setpoint_s); + +#include "topics/vehicle_global_position_setpoint.h" +ORB_DEFINE(vehicle_global_position_setpoint, struct vehicle_global_position_setpoint_s); + +#include "topics/vehicle_attitude_setpoint.h" +ORB_DEFINE(vehicle_attitude_setpoint, struct vehicle_attitude_s); diff --git a/apps/uORB/parameter_storage.c b/apps/uORB/parameter_storage.c new file mode 100644 index 0000000000..f4bd1c7120 --- /dev/null +++ b/apps/uORB/parameter_storage.c @@ -0,0 +1,379 @@ + +#include "parameter_storage.h" +#include + + +/* Global symbols / flags */ + +struct global_data_parameter_storage_t global_data_parameter_storage_d = { /*.counter = 0, .timestamp = 0,*/ .pm = {.size = PARAM_MAX_COUNT, + .param_values[PARAM_SYSTEM_ID] = 12, + .param_names[PARAM_SYSTEM_ID] = "SYS_ID", + .param_needs_write[PARAM_SYSTEM_ID] = false, + + .param_values[PARAM_COMP_ID] = 200, + .param_names[PARAM_COMP_ID] = "COMP_ID", + .param_needs_write[PARAM_COMP_ID] = false, + + .param_values[PARAM_FLIGHT_ENV] = (float)PX4_FLIGHT_ENVIRONMENT_INDOOR, + .param_names[PARAM_FLIGHT_ENV] = "FLIGHT_ENV", + .param_needs_write[PARAM_FLIGHT_ENV] = false, + + .param_values[PARAM_BATTERYVOLTAGE_CONVERSION] = -1.f, + .param_names[PARAM_BATTERYVOLTAGE_CONVERSION] = "BATVOLTAG_CONV", + .param_needs_write[PARAM_BATTERYVOLTAGE_CONVERSION] = false, + + .param_values[PARAM_PID_YAWPOS_P] = 0.3f, + .param_names[PARAM_PID_YAWPOS_P] = "PID_YAWPOS_P", + .param_needs_write[PARAM_PID_YAWPOS_P] = false, + + .param_values[PARAM_PID_YAWPOS_I] = 0.15f, + .param_names[PARAM_PID_YAWPOS_I] = "PID_YAWPOS_I", + .param_needs_write[PARAM_PID_YAWPOS_I] = false, + + .param_values[PARAM_PID_YAWPOS_D] = 0.0f, + .param_names[PARAM_PID_YAWPOS_D] = "PID_YAWPOS_D", + .param_needs_write[PARAM_PID_YAWPOS_D] = false, + + .param_values[PARAM_PID_YAWPOS_AWU] = 1.0f, + .param_names[PARAM_PID_YAWPOS_AWU] = "PID_YAWPOS_AWU", + .param_needs_write[PARAM_PID_YAWPOS_AWU] = false, + + .param_values[PARAM_PID_YAWPOS_LIM] = 3.0f, + .param_names[PARAM_PID_YAWPOS_LIM] = "PID_YAWPOS_LIM", + .param_needs_write[PARAM_PID_YAWPOS_LIM] = false, + + .param_values[PARAM_PID_YAWSPEED_P] = 0.1f, + .param_names[PARAM_PID_YAWSPEED_P] = "PID_YAWSPD_P", + .param_needs_write[PARAM_PID_YAWSPEED_P] = false, + + .param_values[PARAM_PID_YAWSPEED_I] = 0.02f, + .param_names[PARAM_PID_YAWSPEED_I] = "PID_YAWSPD_I", + .param_needs_write[PARAM_PID_YAWSPEED_I] = false, + + .param_values[PARAM_PID_YAWSPEED_D] = 0.0f, + .param_names[PARAM_PID_YAWSPEED_D] = "PID_YAWSPD_D", + .param_needs_write[PARAM_PID_YAWSPEED_D] = false, + + .param_values[PARAM_PID_YAWSPEED_AWU] = 0.02f, + .param_names[PARAM_PID_YAWSPEED_AWU] = "PID_YAWSPD_AWU", + .param_needs_write[PARAM_PID_YAWSPEED_AWU] = false, + + .param_values[PARAM_PID_YAWSPEED_LIM] = 0.1f, + .param_names[PARAM_PID_YAWSPEED_LIM] = "PID_YAWSPD_LIM", + .param_needs_write[PARAM_PID_YAWSPEED_LIM] = false, + + .param_values[PARAM_PID_ATT_P] = 0.3f, + .param_names[PARAM_PID_ATT_P] = "PID_ATT_P", + .param_needs_write[PARAM_PID_ATT_P] = false, + + .param_values[PARAM_PID_ATT_I] = 0.0f, + .param_names[PARAM_PID_ATT_I] = "PID_ATT_I", + .param_needs_write[PARAM_PID_ATT_I] = false, + + .param_values[PARAM_PID_ATT_D] = 0.1f, + .param_names[PARAM_PID_ATT_D] = "PID_ATT_D", + .param_needs_write[PARAM_PID_ATT_D] = false, + + .param_values[PARAM_PID_ATT_AWU] = 0.05f, + .param_names[PARAM_PID_ATT_AWU] = "PID_ATT_AWU", + .param_needs_write[PARAM_PID_ATT_AWU] = false, + + .param_values[PARAM_PID_ATT_LIM] = 0.3f, + .param_names[PARAM_PID_ATT_LIM] = "PID_ATT_LIM", + .param_needs_write[PARAM_PID_ATT_LIM] = false, + + .param_values[PARAM_PID_POS_P] = 40.0f, + .param_names[PARAM_PID_POS_P] = "PID_POS_P", + .param_needs_write[PARAM_PID_POS_P] = false, + + .param_values[PARAM_PID_POS_I] = 0.0f, + .param_names[PARAM_PID_POS_I] = "PID_POS_I", + .param_needs_write[PARAM_PID_POS_I] = false, + + .param_values[PARAM_PID_POS_D] = 0.0f, + .param_names[PARAM_PID_POS_D] = "PID_POS_D", + .param_needs_write[PARAM_PID_POS_D] = false, + + .param_values[PARAM_PID_POS_AWU] = 5.0f, + .param_names[PARAM_PID_POS_AWU] = "PID_POS_AWU", + .param_needs_write[PARAM_PID_POS_AWU] = false, + + .param_values[PARAM_PID_POS_LIM] = 0.3f, + .param_names[PARAM_PID_POS_LIM] = "PID_POS_LIM", + .param_needs_write[PARAM_PID_POS_LIM] = false, + + .param_values[PARAM_PID_POS_Z_P] = 10.0f, + .param_names[PARAM_PID_POS_Z_P] = "PID_POS_Z_P", + .param_needs_write[PARAM_PID_POS_Z_P] = false, + + .param_values[PARAM_PID_POS_Z_I] = 0.0f, + .param_names[PARAM_PID_POS_Z_I] = "PID_POS_Z_I", + .param_needs_write[PARAM_PID_POS_Z_I] = false, + + .param_values[PARAM_PID_POS_Z_D] = 0.0f, + .param_names[PARAM_PID_POS_Z_D] = "PID_POS_Z_D", + .param_needs_write[PARAM_PID_POS_Z_D] = false, + + .param_values[PARAM_PID_POS_Z_AWU] = 3.0f, + .param_names[PARAM_PID_POS_Z_AWU] = "PID_POS_Z_AWU", + .param_needs_write[PARAM_PID_POS_Z_AWU] = false, + + .param_values[PARAM_PID_POS_Z_LIM] = 0.3f, + .param_names[PARAM_PID_POS_Z_LIM] = "PID_POS_Z_LIM", + .param_needs_write[PARAM_PID_POS_Z_LIM] = false, + + .param_values[PARAM_AIRSPEED] = 30.0f, + .param_names[PARAM_AIRSPEED] = "AIRSPEED", + .param_needs_write[PARAM_AIRSPEED] = false, + + .param_values[PARAM_WPLON] = -120.0f, + .param_names[PARAM_WPLON] = "WPLON", + .param_needs_write[PARAM_WPLON] = false, + + .param_values[PARAM_WPLAT] = 38.0f, + .param_names[PARAM_WPLAT] = "WPLAT", + .param_needs_write[PARAM_WPLAT] = false, + + .param_values[PARAM_WPALT] = 500.0f, + .param_names[PARAM_WPALT] = "WPALT", + .param_needs_write[PARAM_WPALT] = false, + + .param_values[PARAM_FLIGHTMODE] = CRUISE, + .param_names[PARAM_FLIGHTMODE] = "FLIGHTMODE", + .param_needs_write[PARAM_FLIGHTMODE] = false, + + .param_values[PARAM_SENSOR_GYRO_XOFFSET] = 700.f, + .param_names[PARAM_SENSOR_GYRO_XOFFSET] = "SENSOR_GYRO_XOF", + .param_needs_write[PARAM_SENSOR_GYRO_XOFFSET] = false, + + .param_values[PARAM_SENSOR_GYRO_YOFFSET] = 1400.0f, + .param_names[PARAM_SENSOR_GYRO_YOFFSET] = "SENSOR_GYRO_YOF", + .param_needs_write[PARAM_SENSOR_GYRO_YOFFSET] = false, + + .param_values[PARAM_SENSOR_GYRO_ZOFFSET] = 0.0f, + .param_names[PARAM_SENSOR_GYRO_ZOFFSET] = "SENSOR_GYRO_ZOF", + .param_needs_write[PARAM_SENSOR_GYRO_ZOFFSET] = false, + + .param_values[PARAM_SENSOR_MAG_XOFFSET] = 422.0f, + .param_names[PARAM_SENSOR_MAG_XOFFSET] = "SENSOR_MAG_XOF", + .param_needs_write[PARAM_SENSOR_MAG_XOFFSET] = false, + + .param_values[PARAM_SENSOR_MAG_YOFFSET] = -85.0f, + .param_names[PARAM_SENSOR_MAG_YOFFSET] = "SENSOR_MAG_YOF", + .param_needs_write[PARAM_SENSOR_MAG_YOFFSET] = false, + + .param_values[PARAM_SENSOR_MAG_ZOFFSET] = -370.0f, + .param_names[PARAM_SENSOR_MAG_ZOFFSET] = "SENSOR_MAG_ZOF", + .param_needs_write[PARAM_SENSOR_MAG_ZOFFSET] = false, + + .param_values[PARAM_ATT_XOFFSET] = 0.0f, + .param_names[PARAM_ATT_XOFFSET] = "ATT_XOFF", + .param_needs_write[PARAM_ATT_XOFFSET] = false, + + .param_values[PARAM_ATT_YOFFSET] = 0.0f, + .param_names[PARAM_ATT_YOFFSET] = "ATT_YOFF", + .param_needs_write[PARAM_ATT_YOFFSET] = false, + + .param_values[PARAM_RC1_MIN] = 1000.0f, + .param_names[PARAM_RC1_MIN] = "RC1_MIN", + .param_needs_write[PARAM_RC1_MIN] = false, + + .param_values[PARAM_RC1_MAX] = 2000.0f, + .param_names[PARAM_RC1_MAX] = "RC1_MAX", + .param_needs_write[PARAM_RC1_MAX] = false, + + .param_values[PARAM_RC1_TRIM] = 1500.0f, + .param_names[PARAM_RC1_TRIM] = "RC1_TRIM", + .param_needs_write[PARAM_RC1_TRIM] = false, + + .param_values[PARAM_RC1_REV] = 1.0f, + .param_names[PARAM_RC1_REV] = "RC1_REV", + .param_needs_write[PARAM_RC1_REV] = false, + + .param_values[PARAM_RC2_MIN] = 1000.0f, + .param_names[PARAM_RC2_MIN] = "RC2_MIN", + .param_needs_write[PARAM_RC2_MIN] = false, + + .param_values[PARAM_RC2_MAX] = 2000.0f, + .param_names[PARAM_RC2_MAX] = "RC2_MAX", + .param_needs_write[PARAM_RC2_MAX] = false, + + .param_values[PARAM_RC2_TRIM] = 1500.0f, + .param_names[PARAM_RC2_TRIM] = "RC2_TRIM", + .param_needs_write[PARAM_RC2_TRIM] = false, + + .param_values[PARAM_RC2_REV] = 1.0f, + .param_names[PARAM_RC2_REV] = "RC2_REV", + .param_needs_write[PARAM_RC2_REV] = false, + + .param_values[PARAM_RC3_MIN] = 1000.0f, + .param_names[PARAM_RC3_MIN] = "RC3_MIN", + .param_needs_write[PARAM_RC3_MIN] = false, + + .param_values[PARAM_RC3_MAX] = 2000.0f, + .param_names[PARAM_RC3_MAX] = "RC3_MAX", + .param_needs_write[PARAM_RC3_MAX] = false, + + .param_values[PARAM_RC3_TRIM] = 1500.0f, + .param_names[PARAM_RC3_TRIM] = "RC3_TRIM", + .param_needs_write[PARAM_RC3_TRIM] = false, + + .param_values[PARAM_RC3_REV] = 1.0f, + .param_names[PARAM_RC3_REV] = "RC3_REV", + .param_needs_write[PARAM_RC3_REV] = false, + + .param_values[PARAM_RC4_MIN] = 1000.0f, + .param_names[PARAM_RC4_MIN] = "RC4_MIN", + .param_needs_write[PARAM_RC4_MIN] = false, + + .param_values[PARAM_RC4_MAX] = 2000.0f, + .param_names[PARAM_RC4_MAX] = "RC4_MAX", + .param_needs_write[PARAM_RC4_MAX] = false, + + .param_values[PARAM_RC4_TRIM] = 1500.0f, + .param_names[PARAM_RC4_TRIM] = "RC4_TRIM", + .param_needs_write[PARAM_RC4_TRIM] = false, + + .param_values[PARAM_RC4_REV] = 1.0f, + .param_names[PARAM_RC4_REV] = "RC4_REV", + .param_needs_write[PARAM_RC4_MIN] = false, + + .param_values[PARAM_RC5_MIN] = 1000.0f, + .param_names[PARAM_RC5_MIN] = "RC5_MIN", + .param_needs_write[PARAM_RC5_MIN] = false, + + .param_values[PARAM_RC5_MAX] = 2000.0f, + .param_names[PARAM_RC5_MAX] = "RC5_MAX", + .param_needs_write[PARAM_RC5_MAX] = false, + + .param_values[PARAM_RC5_TRIM] = 1500.0f, + .param_names[PARAM_RC5_TRIM] = "RC5_TRIM", + .param_needs_write[PARAM_RC5_TRIM] = false, + + .param_values[PARAM_RC5_REV] = 1.0f, + .param_names[PARAM_RC5_REV] = "RC5_REV", + .param_needs_write[PARAM_RC5_REV] = false, + + .param_values[PARAM_RC6_MIN] = 1000.0f, + .param_names[PARAM_RC6_MIN] = "RC6_MIN", + .param_needs_write[PARAM_RC6_MIN] = false, + + .param_values[PARAM_RC6_MAX] = 2000.0f, + .param_names[PARAM_RC6_MAX] = "RC6_MAX", + .param_needs_write[PARAM_RC6_MAX] = false, + + .param_values[PARAM_RC6_TRIM] = 1500.0f, + .param_names[PARAM_RC6_TRIM] = "RC6_TRIM", + .param_needs_write[PARAM_RC6_TRIM] = false, + + .param_values[PARAM_RC6_REV] = 1.0f, + .param_names[PARAM_RC6_REV] = "RC6_REV", + .param_needs_write[PARAM_RC6_REV] = false, + + .param_values[PARAM_RC7_MIN] = 1000, + .param_names[PARAM_RC7_MIN] = "RC7_MIN", + .param_needs_write[PARAM_RC7_MIN] = false, + + .param_values[PARAM_RC7_MAX] = 2000, + .param_names[PARAM_RC7_MAX] = "RC7_MAX", + .param_needs_write[PARAM_RC7_MAX] = false, + + .param_values[PARAM_RC7_TRIM] = 1500, + .param_names[PARAM_RC7_TRIM] = "RC7_TRIM", + .param_needs_write[PARAM_RC7_TRIM] = false, + + .param_values[PARAM_RC7_REV] = 1.0f, + .param_names[PARAM_RC7_REV] = "RC7_REV", + .param_needs_write[PARAM_RC7_REV] = false, + + .param_values[PARAM_RC8_MIN] = 1000, + .param_names[PARAM_RC8_MIN] = "RC8_MIN", + .param_needs_write[PARAM_RC8_MIN] = false, + + .param_values[PARAM_RC8_MAX] = 2000, + .param_names[PARAM_RC8_MAX] = "RC8_MAX", + .param_needs_write[PARAM_RC8_MAX] = false, + + .param_values[PARAM_RC8_TRIM] = 1500, + .param_names[PARAM_RC8_TRIM] = "RC8_TRIM", + .param_needs_write[PARAM_RC8_TRIM] = false, + + .param_values[PARAM_RC8_REV] = 1.0f, + .param_names[PARAM_RC8_REV] = "RC8_REV", + .param_needs_write[PARAM_RC8_REV] = false, + + .param_values[PARAM_ROLL_CHAN] = 1, + .param_names[PARAM_ROLL_CHAN] = "ROLL_CHAN", + .param_needs_write[PARAM_ROLL_CHAN] = false, + + .param_values[PARAM_PITCH_CHAN] = 2, + .param_names[PARAM_PITCH_CHAN] = "PITCH_CHAN", + .param_needs_write[PARAM_PITCH_CHAN] = false, + + .param_values[PARAM_THROTTLE_CHAN] = 3, + .param_names[PARAM_THROTTLE_CHAN] = "THROTTLE_CHAN", + .param_needs_write[PARAM_THROTTLE_CHAN] = false, + + .param_values[PARAM_YAW_CHAN] = 4, + .param_names[PARAM_YAW_CHAN] = "YAW_CHAN", + .param_needs_write[PARAM_YAW_CHAN] = false, + + .param_values[PARAM_OVERRIDE_CHAN] = 5, + .param_names[PARAM_OVERRIDE_CHAN] = "OVERRIDE_CHAN", + .param_needs_write[PARAM_OVERRIDE_CHAN] = false, + + .param_values[PARAM_SERVO1_MIN] = 1000.0f, + .param_names[PARAM_SERVO1_MIN] = "SERVO1_MIN", + .param_needs_write[PARAM_SERVO1_MIN] = false, + + .param_values[PARAM_SERVO1_MAX] = 2000.0f, + .param_names[PARAM_SERVO1_MAX] = "SERVO1_MAX", + .param_needs_write[PARAM_SERVO1_MAX] = false, + + .param_values[PARAM_SERVO1_TRIM] = 1500.0f, + .param_names[PARAM_SERVO1_TRIM] = "SERVO1_TRIM", + .param_needs_write[PARAM_SERVO1_TRIM] = false, + + .param_values[PARAM_SERVO2_MIN] = 1000.0f, + .param_names[PARAM_SERVO2_MIN] = "SERVO2_MIN", + .param_needs_write[PARAM_SERVO2_MIN] = false, + + .param_values[PARAM_SERVO2_MAX] = 2000.0f, + .param_names[PARAM_SERVO2_MAX] = "SERVO2_MAX", + .param_needs_write[PARAM_SERVO2_MAX] = false, + + .param_values[PARAM_SERVO2_TRIM] = 1500.0f, + .param_names[PARAM_SERVO2_TRIM] = "SERVO2_TRIM", + .param_needs_write[PARAM_SERVO2_TRIM] = false, + + .param_values[PARAM_SERVO3_MIN] = 1000.0f, + .param_names[PARAM_SERVO3_MIN] = "SERVO3_MIN", + .param_needs_write[PARAM_SERVO3_MIN] = false, + + .param_values[PARAM_SERVO3_MAX] = 2000.0f, + .param_names[PARAM_SERVO3_MAX] = "SERVO3_MAX", + .param_needs_write[PARAM_SERVO3_MAX] = false, + + .param_values[PARAM_SERVO3_TRIM] = 1500.0f, + .param_names[PARAM_SERVO3_TRIM] = "SERVO3_TRIM", + .param_needs_write[PARAM_SERVO3_TRIM] = false, + + .param_values[PARAM_SERVO4_MIN] = 1000.0f, + .param_names[PARAM_SERVO4_MIN] = "SERVO4_MIN", + .param_needs_write[PARAM_SERVO4_MIN] = false, + + .param_values[PARAM_SERVO4_MAX] = 2000.0f, + .param_names[PARAM_SERVO4_MAX] = "SERVO4_MAX", + .param_needs_write[PARAM_SERVO4_MAX] = false, + + .param_values[PARAM_SERVO4_TRIM] = 1500.0f, + .param_names[PARAM_SERVO4_TRIM] = "SERVO4_TRIM", + .param_needs_write[PARAM_SERVO4_TRIM] = false, + + .param_values[PARAM_SERVO_SCALE] = 20.0f, + .param_names[PARAM_SERVO_SCALE] = "SERVO_SCALE", + .param_needs_write[PARAM_SERVO_SCALE] = false + } +}; + +struct global_data_parameter_storage_t *global_data_parameter_storage = &global_data_parameter_storage_d; diff --git a/apps/uORB/parameter_storage.h b/apps/uORB/parameter_storage.h new file mode 100644 index 0000000000..54ae63cb93 --- /dev/null +++ b/apps/uORB/parameter_storage.h @@ -0,0 +1,148 @@ +/* Structure for storage of parameters */ + +#ifndef GLOBAL_DATA_PARAMETER_STORAGE_T_H_ //adjust this line! +#define GLOBAL_DATA_PARAMETER_STORAGE_T_H_ //adjust this line! + +#define PX4_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN 16 +#define MAX_PARAM_NAME_LEN 16 + +#include +#include + +enum MODE { + TAKEOFF = 1, + CRUISE, + LOITER, + LAND +}; + +enum PARAM { + PARAM_SYSTEM_ID = 0, ///< System ID used for communication + PARAM_COMP_ID, ///< Component ID + PARAM_FLIGHT_ENV, ///< Flight environment, indoor or outdoor + PARAM_BATTERYVOLTAGE_CONVERSION, ///< Conversion factor from adc measurement to millivolts. if not set the sensor app will use the default value for the ardrone board + PARAM_PID_YAWPOS_P, + PARAM_PID_YAWPOS_I, + PARAM_PID_YAWPOS_D, + PARAM_PID_YAWPOS_AWU, + PARAM_PID_YAWPOS_LIM, + PARAM_PID_YAWSPEED_P, + PARAM_PID_YAWSPEED_I, + PARAM_PID_YAWSPEED_D, + PARAM_PID_YAWSPEED_AWU, + PARAM_PID_YAWSPEED_LIM, + PARAM_PID_ATT_P, + PARAM_PID_ATT_I, + PARAM_PID_ATT_D, + PARAM_PID_ATT_AWU, + PARAM_PID_ATT_LIM, + PARAM_PID_POS_P, + PARAM_PID_POS_I, + PARAM_PID_POS_D, + PARAM_PID_POS_AWU, + PARAM_PID_POS_LIM, + PARAM_PID_POS_Z_P, + PARAM_PID_POS_Z_I, + PARAM_PID_POS_Z_D, + PARAM_PID_POS_Z_AWU, + PARAM_PID_POS_Z_LIM, + PARAM_AIRSPEED, + PARAM_WPLON, + PARAM_WPLAT, + PARAM_WPALT, + PARAM_FLIGHTMODE, + PARAM_SENSOR_GYRO_XOFFSET, + PARAM_SENSOR_GYRO_YOFFSET, + PARAM_SENSOR_GYRO_ZOFFSET, + PARAM_SENSOR_MAG_XOFFSET, + PARAM_SENSOR_MAG_YOFFSET, + PARAM_SENSOR_MAG_ZOFFSET, + PARAM_ATT_XOFFSET, + PARAM_ATT_YOFFSET, + PARAM_RC1_MIN, + PARAM_RC1_MAX, + PARAM_RC1_TRIM, + PARAM_RC1_REV, + PARAM_RC2_MIN, + PARAM_RC2_MAX, + PARAM_RC2_TRIM, + PARAM_RC2_REV, + PARAM_RC3_MIN, + PARAM_RC3_MAX, + PARAM_RC3_TRIM, + PARAM_RC3_REV, + PARAM_RC4_MIN, + PARAM_RC4_MAX, + PARAM_RC4_TRIM, + PARAM_RC4_REV, + PARAM_RC5_MIN, + PARAM_RC5_MAX, + PARAM_RC5_TRIM, + PARAM_RC5_REV, + PARAM_RC6_MIN, + PARAM_RC6_MAX, + PARAM_RC6_TRIM, + PARAM_RC6_REV, + PARAM_RC7_MIN, + PARAM_RC7_MAX, + PARAM_RC7_TRIM, + PARAM_RC7_REV, + PARAM_RC8_MIN, + PARAM_RC8_MAX, + PARAM_RC8_TRIM, + PARAM_RC8_REV, + PARAM_THROTTLE_CHAN, + PARAM_ROLL_CHAN, + PARAM_PITCH_CHAN, + PARAM_YAW_CHAN, + PARAM_OVERRIDE_CHAN, + PARAM_SERVO1_MIN, + PARAM_SERVO1_MAX, + PARAM_SERVO1_TRIM, + PARAM_SERVO2_MIN, + PARAM_SERVO2_MAX, + PARAM_SERVO2_TRIM, + PARAM_SERVO3_MIN, + PARAM_SERVO3_MAX, + PARAM_SERVO3_TRIM, + PARAM_SERVO4_MIN, + PARAM_SERVO4_MAX, + PARAM_SERVO4_TRIM, + PARAM_SERVO_SCALE, + PARAM_MAX_COUNT ///< LEAVE THIS IN PLACE AS LAST ELEMENT! +}; + +struct px4_parameter_storage_t { + float param_values[PARAM_MAX_COUNT]; ///< Parameter values + const char *param_names[PARAM_MAX_COUNT]; ///< Parameter names + bool param_needs_write[PARAM_MAX_COUNT]; + uint16_t next_param; + uint16_t size; +}; + + +#define PX4_FLIGHT_ENVIRONMENT_INDOOR 0 +#define PX4_FLIGHT_ENVIRONMENT_OUTDOOR 1 +#define PX4_FLIGHT_ENVIRONMENT_TESTING 2 //NO check for position fix in this environment + +struct global_data_parameter_storage_t { + + /* use of a counter and timestamp recommended (but not necessary) */ + +// uint16_t counter; //incremented by the writing thread everytime new data is stored +// uint64_t timestamp; //in microseconds since system start, is set whenever the writing thread stores new data + + /* Actual data, this is specific to the type of data which is stored in this struct */ + + //***** Start: Add your variables here ***** + + /* Parameters (set by a param_set mavlink message */ + struct px4_parameter_storage_t pm; + + //*****END: Add your variables here ***** + +}; + +__attribute__ ((visibility ("default"))) extern struct global_data_parameter_storage_t *global_data_parameter_storage; //adjust this line! + +#endif diff --git a/apps/uORB/topics/UNPORTED_subsystem_info.h b/apps/uORB/topics/UNPORTED_subsystem_info.h new file mode 100644 index 0000000000..24f973a02c --- /dev/null +++ b/apps/uORB/topics/UNPORTED_subsystem_info.h @@ -0,0 +1,68 @@ +/* Structure for storage of shared variables (extended( */ + +/* global_data_subsystem_info stores a buffer of the sensor info/status messages (sent by sensors or gps app), this is then handled by the commander. (The commander then writes to global_data_sys_status which is read by mavlink) */ + +/* (any app) --> global_data_subsystem_info (buffered) --> (commander app) --> global_data_sys_status --> (mavlink app) */ + +#ifndef GLOBAL_DATA_SUBSYSTEM_INFO_T_H_ //adjust this line! +#define GLOBAL_DATA_SUBSYSTEM_INFO_T_H_ //adjust this line! + +#define SUBSYSTEM_INFO_BUFFER_SIZE 10 + +#include "global_data_access.h" + +typedef enum //values correspond to bitmasks of mavlink message sys_status, this is crucial for the underlying bitmask to work +{ + SUBSYSTEM_TYPE_GYRO = 0, + SUBSYSTEM_TYPE_ACC = 1, + SUBSYSTEM_TYPE_MAG = 2, + SUBSYSTEM_TYPE_ABSPRESSURE = 3, + SUBSYSTEM_TYPE_DIFFPRESSURE = 4, + SUBSYSTEM_TYPE_GPS = 5, + SUBSYSTEM_TYPE_OPTICALFLOW = 6, + SUBSYSTEM_TYPE_CVPOSITION = 7, + SUBSYSTEM_TYPE_LASERPOSITION = 8, + SUBSYSTEM_TYPE_EXTERNALGROUNDTRUTH = 9, + SUBSYSTEM_TYPE_ANGULARRATECONTROL = 10, + SUBSYSTEM_TYPE_ATTITUDESTABILIZATION = 11, + SUBSYSTEM_TYPE_YAWPOSITION = 12, + SUBSYSTEM_TYPE_ALTITUDECONTROL = 13, + SUBSYSTEM_TYPE_POSITIONCONTROL = 14, + SUBSYSTEM_TYPE_MOTORCONTROL = 15 + +} subsystem_type_t; + +typedef struct +{ + uint8_t present; + uint8_t enabled; + uint8_t health; + + subsystem_type_t subsystem_type; + +} __attribute__((__packed__)) subsystem_info_t; + +typedef struct +{ + /* Struct which stores the access configuration, this is the same for all shared structs */ + + access_conf_t access_conf; //don't remove this line! + + /* use of a counter and timestamp recommended (but not necessary) */ + + uint16_t counter; //incremented by the writing thread everytime new data is stored + uint64_t timestamp; //in microseconds since system start, is set whenever the writing thread stores new data + + /* Actual data, this is specific to the type of data which is stored in this struct */ + + //***** Start: Add your variables here ***** + subsystem_info_t info[SUBSYSTEM_INFO_BUFFER_SIZE]; + uint8_t current_info; + + //*****END: Add your variables here ***** + +} global_data_subsystem_info_t; //adjust this line! + +extern global_data_subsystem_info_t* global_data_subsystem_info; //adjust this line! + +#endif diff --git a/apps/uORB/topics/actuator_controls.h b/apps/uORB/topics/actuator_controls.h new file mode 100644 index 0000000000..03c0c7b7da --- /dev/null +++ b/apps/uORB/topics/actuator_controls.h @@ -0,0 +1,64 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Actuator control topic - mixer inputs. + * + * Values published to this topic are the outputs of the vehicle control + * system, and are expected to be mixed and used to drive the actuators + * (servos, speed controls, etc.) that operate the vehicle. + */ + +#ifndef TOPIC_ACTUATOR_CONTROLS_H +#define TOPIC_ACTUATOR_CONTROLS_H + +#include +#include "../uORB.h" + +#define NUM_ACTUATOR_CONTROLS 16 + +struct actuator_controls +{ + float control[NUM_ACTUATOR_CONTROLS]; +}; + +ORB_DECLARE(actuator_controls); + +struct actuator_armed +{ + bool armed; +}; + +ORB_DECLARE(actuator_armed); + +#endif \ No newline at end of file diff --git a/apps/uORB/topics/ardrone_control.h b/apps/uORB/topics/ardrone_control.h new file mode 100644 index 0000000000..1f582f52ac --- /dev/null +++ b/apps/uORB/topics/ardrone_control.h @@ -0,0 +1,83 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Thomas Gubler + * @author Julian Oes + * @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * @file ardrone_control.c + * Definition of the ardrone_control uORB topic. + */ + +#ifndef TOPIC_ARDRONE_CONTROL_H_ +#define TOPIC_ARDRONE_CONTROL_H_ + +#include +#include "../uORB.h" + +/** + * @addtogroup topics + * @{ + */ + +struct ardrone_control_s +{ + uint16_t counter; /**< incremented by the publishing thread everytime new data is stored. */ + uint64_t timestamp; /**< in microseconds since system start, is set whenever the writing thread stores new data. */ + + float setpoint_rate_cast[3]; + float setpoint_thrust_cast; /**< LOGME */ + float setpoint_attitude_rate[3]; + float setpoint_attitude[3]; /**< LOGME */ + float attitude_control_output[3]; /**< roll, pitch, yaw. */ + float position_control_output[3]; /**< x, y, z. */ + float attitude_setpoint_navigationframe_from_positioncontroller[3]; /**< LOGME */ + float gyro_scaled[3]; + float gyro_filtered[3]; + float gyro_filtered_offset[3]; + float zcompensation; + uint16_t motor_front_nw; + uint16_t motor_right_ne; + uint16_t motor_back_se; + uint16_t motor_left_sw; + +}; /**< ardrone control status */ + +/** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(ardrone_control); + +#endif /* TOPIC_ARDRONE_CONTROL_H_ */ diff --git a/apps/uORB/topics/ardrone_motors_setpoint.h b/apps/uORB/topics/ardrone_motors_setpoint.h new file mode 100644 index 0000000000..54d81b7065 --- /dev/null +++ b/apps/uORB/topics/ardrone_motors_setpoint.h @@ -0,0 +1,70 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file ardrone_motors_setpoint.h + * Definition of the ardrone_motors_setpoint uORB topic. + */ + +#ifndef TOPIC_ARDRONE_MOTORS_SETPOINT_H_ +#define TOPIC_ARDRONE_MOTORS_SETPOINT_H_ + +#include +#include "../uORB.h" + +/** + * @addtogroup topics + * @{ + */ + +struct ardrone_motors_setpoint_s +{ + uint16_t counter; //incremented by the writing thread everytime new data is stored + uint64_t timestamp; //in microseconds since system start, is set whenever the writing thread stores new data + + uint16_t motor_front_nw; ///< Front motor in + configuration, front left motor in x configuration + uint16_t motor_right_ne; ///< Right motor in + configuration, front right motor in x configuration + uint16_t motor_back_se; ///< Back motor in + configuration, back right motor in x configuration + uint16_t motor_left_sw; ///< Left motor in + configuration, back left motor in x configuration + +}; /**< AR.Drone low level motors */ + + /** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(ardrone_motors_setpoint); + +#endif diff --git a/apps/uORB/topics/fixedwing_control.h b/apps/uORB/topics/fixedwing_control.h new file mode 100644 index 0000000000..e904709b6c --- /dev/null +++ b/apps/uORB/topics/fixedwing_control.h @@ -0,0 +1,77 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Lorenz Meier + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file fixedwing_control.h + * Definition of the fixedwing_control uORB topic. + */ + +#ifndef TOPIC_FIXEDWING_CONTROL_H_ +#define TOPIC_FIXEDWING_CONTROL_H_ + +#include +#include "../uORB.h" + +/** + * @addtogroup topics + * @{ + */ + +/** + * fixed wing control status. + */ +struct fixedwing_control_s +{ + /* use of a counter and timestamp recommended (but not necessary) */ + + uint16_t counter; //incremented by the writing thread everytime new data is stored + uint64_t timestamp; //in microseconds since system start, is set whenever the writing thread stores new data + + float setpoint_rate_cast[3]; + float setpoint_attitude_rate[3]; + float setpoint_attitude[3]; + int16_t attitude_control_output[4]; /**< roll, pitch, yaw, throttle */ + float position_control_output[4]; + +}; + +/** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(fixedwing_control); + +#endif //GLOBAL_DATA_FIXEDWING_CONTROL_T_H_ diff --git a/apps/uORB/topics/rc_channels.h b/apps/uORB/topics/rc_channels.h new file mode 100644 index 0000000000..5bd2adeec4 --- /dev/null +++ b/apps/uORB/topics/rc_channels.h @@ -0,0 +1,116 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: @author Nils Wenzler + * @author Ivan Ovinnikov + * @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file rc_channels.h + * Definition of the rc_channels uORB topic. + */ + +#ifndef RC_CHANNELS_H_ +#define RC_CHANNELS_H_ + +#include +#include "../uORB.h" + +/** + * @addtogroup topics + * @{ + */ + +enum RC_CHANNELS_STATUS +{ + UNKNOWN = 0, + KNOWN = 1, + SIGNAL = 2, + TIMEOUT = 3 +}; + +/** + * This defines the mapping of the RC functions. + * The value assigned to the specific function corresponds to the entry of + * the channel array chan[]. + * Ex. To read out the scaled Pitch value: + * pitch = global_data_rc_channels->chan[PITCH].scale; + * The override is on channel 8, since we don't usually have a 12 channel RC + * and channel 5/6 (GRAUPNER/FUTABA) are mapped to the second ROLL servo, which + * can only be disabled on more advanced RC sets. + */ +enum RC_CHANNELS_FUNCTION +{ + THROTTLE = 0, + ROLL = 1, + PITCH = 2, + YAW = 3, + OVERRIDE = 4, + FUNC_0 = 5, + FUNC_1 = 6, + FUNC_2 = 7, + FUNC_3 = 8, + FUNC_4 = 9, + FUNC_5 = 10, + FUNC_6 = 11, + RC_CHANNELS_FUNCTION_MAX = 12 +}; + +struct rc_channels_s { + + uint64_t timestamp; /**< In microseconds since boot time. */ + uint64_t timestamp_last_valid; /**< timestamp of last valid RC signal. */ + struct { + uint16_t mid; /**< midpoint (0). */ + float scaling_factor; /**< scaling factor from raw counts to 0..1 */ + uint16_t raw; /**< current raw value */ + int16_t scale; + float scaled; /**< Scaled */ + uint16_t override; + enum RC_CHANNELS_STATUS status; /**< status of the channel */ + } chan[RC_CHANNELS_FUNCTION_MAX]; + uint8_t chan_count; /**< maximum number of valid channels */ + + /*String array to store the names of the functions*/ + const char function_name[RC_CHANNELS_FUNCTION_MAX][20]; + uint8_t function[RC_CHANNELS_FUNCTION_MAX]; + uint8_t rssi; /**< Overall receive signal strength */ +}; /**< radio control channels. */ + +/** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(rc_channels); + +#endif diff --git a/apps/uORB/topics/sensor_combined.h b/apps/uORB/topics/sensor_combined.h new file mode 100644 index 0000000000..ecf5ea81d6 --- /dev/null +++ b/apps/uORB/topics/sensor_combined.h @@ -0,0 +1,103 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: @author Thomas Gubler + * @author Julian Oes + * @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file sensor_combined.h + * Definition of the sensor_combined uORB topic. + */ + +#ifndef SENSOR_COMBINED_H_ +#define SENSOR_COMBINED_H_ + +#include +#include +#include "../uORB.h" + +/** + * @addtogroup topics + * @{ + */ + +/** + * Sensor readings in raw and SI-unit form. + * + * These values are read from the sensors. Raw values are in sensor-specific units, + * the scaled values are in SI-units, as visible from the ending of the variable + * or the comments. The use of the SI fields is in general advised, as these fields + * are scaled and offset-compensated where possible and do not change with board + * revisions and sensor updates. + * + */ +struct sensor_combined_s { + + /* + * Actual data, this is specific to the type of data which is stored in this struct + * A line containing L0GME will be added by the Python logging code generator to the + * logged dataset. + */ + + /* NOTE: Ordering of fields optimized to align to 32 bit / 4 bytes Change with consideration only */ + + uint64_t timestamp; /**< Timestamp in microseconds since boot LOGME */ + + int16_t gyro_raw[3]; /**< Raw sensor values of angular velocity LOGME */ + uint16_t gyro_raw_counter; /**< Number of raw measurments taken LOGME */ + float gyro_rad_s[3]; /**< Angular velocity in radian per seconds LOGME */ + int16_t accelerometer_raw[3]; /**< Raw acceleration in NED body frame LOGME */ + uint16_t accelerometer_raw_counter; /**< Number of raw acc measurements taken LOGME */ + float accelerometer_m_s2[3]; /**< Acceleration in NED body frame, in m/s^2 LOGME */ + int16_t magnetometer_raw[3]; /**< Raw magnetic field in NED body frame LOGME */ + float magnetometer_ga[3]; /**< Magnetic field in NED body frame, in Gauss LOGME */ + uint16_t magnetometer_raw_counter; /**< Number of raw mag measurements taken LOGME */ + float baro_pres_mbar; /**< Barometric pressure, already temp. comp. LOGME */ + float baro_alt_meter; /**< Altitude, already temp. comp. LOGME */ + float baro_temp_celcius; /**< Temperature in degrees celsius LOGME */ + float battery_voltage_v; /**< Battery voltage in volts, filtered LOGME */ + float adc_voltage_v[3]; /**< ADC voltages of ADC Chan 11/12/13 or -1 LOGME */ + uint16_t baro_raw_counter; /**< Number of raw baro measurements taken LOGME */ + uint16_t battery_voltage_counter; /**< Number of voltage measurements taken LOGME */ + bool battery_voltage_valid; /**< True if battery voltage can be measured LOGME */ + +}; + +/** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(sensor_combined); + +#endif diff --git a/apps/uORB/topics/vehicle_attitude.h b/apps/uORB/topics/vehicle_attitude.h new file mode 100644 index 0000000000..e365a65574 --- /dev/null +++ b/apps/uORB/topics/vehicle_attitude.h @@ -0,0 +1,92 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: @author Thomas Gubler + * @author Julian Oes + * @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file vehicle_attitude.h + * Definition of the attitude uORB topic. + */ + +#ifndef VEHICLE_ATTITUDE_H_ +#define VEHICLE_ATTITUDE_H_ + +#include +#include +#include "../uORB.h" + +/** + * @addtogroup topics + */ + +/** + * Attitude in NED body frame in SI units. + * + * @see http://en.wikipedia.org/wiki/International_System_of_Units + */ +struct vehicle_attitude_s { + + /* + * Actual data, this is specific to the type of data which is stored in this struct + * A line containing L0GME will be added by the Python logging code generator to the + * logged dataset. + */ + uint64_t timestamp; /**< in microseconds since system start */ + + /* This is similar to the mavlink message ATTITUDE, but for onboard use */ + + /* @warning Roll, pitch and yaw have always to be valid, the rotation matrix and quaternion are optional */ + + float roll; /**< Roll angle (rad, Tait-Bryan, NED) LOGME */ + float pitch; /**< Pitch angle (rad, Tait-Bryan, NED) LOGME */ + float yaw; /**< Yaw angle (rad, Tait-Bryan, NED) LOGME */ + float rollspeed; /**< Roll angular speed (rad/s, Tait-Bryan, NED) LOGME */ + float pitchspeed; /**< Pitch angular speed (rad/s, Tait-Bryan, NED) LOGME */ + float yawspeed; /**< Yaw angular speed (rad/s, Tait-Bryan, NED) LOGME */ + float R[3][3]; /**< Rotation matrix body to world, (Tait-Bryan, NED) */ + float q[4]; /**< Quaternion (NED) */ + bool R_valid; /**< Rotation matrix valid */ + bool q_valid; /**< Quaternion valid */ + uint16_t counter; /**< Counter of all attitude messages (wraps) */ + +}; + +/** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(vehicle_attitude); + +#endif diff --git a/apps/uORB/topics/vehicle_attitude_setpoint.h b/apps/uORB/topics/vehicle_attitude_setpoint.h new file mode 100644 index 0000000000..6b37574028 --- /dev/null +++ b/apps/uORB/topics/vehicle_attitude_setpoint.h @@ -0,0 +1,77 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file vehicle_attitude_setpoint.h + * Definition of the vehicle attitude setpoint uORB topic. + */ + +#ifndef TOPIC_VEHICLE_ATTITUDE_SETPOINT_H_ +#define TOPIC_VEHICLE_ATTITUDE_SETPOINT_H_ + +#include +#include +#include + +/** + * @addtogroup topics + * @{ + */ + +/** + * vehicle attitude setpoint. + */ +struct vehicle_attitude_setpoint_s +{ + uint64_t timestamp; /**< in microseconds since system start, is set whenever the writing thread stores new data */ + + float roll_tait_bryan; /**< Tait-Bryan angle in NED frame */ + float pitch_tait_bryan; /**< Tait-Bryan angle in NED frame */ + float yaw_tait_bryan; /**< Tait-Bryan angle in NED frame */ + float tait_bryan_valid; /**< Set to true if Tait-Bryan angles are valid */ + + float R_body[9]; /**< Rotation matrix describing the setpoint as rotation from the current body frame */ + bool R_valid; /**< Set to true if rotation matrix is valid */ + float thrust; /**< Thrust in Newton the power system should generate */ + +}; + +/** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(vehicle_attitude_setpoint); + +#endif /* TOPIC_ARDRONE_CONTROL_H_ */ diff --git a/apps/uORB/topics/vehicle_command.h b/apps/uORB/topics/vehicle_command.h new file mode 100644 index 0000000000..dca928efd2 --- /dev/null +++ b/apps/uORB/topics/vehicle_command.h @@ -0,0 +1,79 @@ +/**************************************************************************** + * + * Copyright (C) 2008-2012 PX4 Development Team. All rights reserved. + * Author: @author Thomas Gubler + * @author Julian Oes + * @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file vehicle_command.h + * Definition of the vehicle command uORB topic. + */ + +#ifndef TOPIC_VEHICLE_COMMAND_H_ +#define TOPIC_VEHICLE_COMMAND_H_ + +#include +#include "../uORB.h" + +/** + * @addtogroup topics + * @{ + */ + +struct vehicle_command_s +{ + float param1; /**< Parameter 1, as defined by MAVLink MAV_CMD enum. */ + float param2; /**< Parameter 2, as defined by MAVLink MAV_CMD enum. */ + float param3; /**< Parameter 3, as defined by MAVLink MAV_CMD enum. */ + float param4; /**< Parameter 4, as defined by MAVLink MAV_CMD enum. */ + float param5; /**< Parameter 5, as defined by MAVLink MAV_CMD enum. */ + float param6; /**< Parameter 6, as defined by MAVLink MAV_CMD enum. */ + float param7; /**< Parameter 7, as defined by MAVLink MAV_CMD enum. */ + uint16_t command; /**< Command ID, as defined MAVLink by MAV_CMD enum. */ + uint8_t target_system; /**< System which should execute the command */ + uint8_t target_component; /**< Component which should execute the command, 0 for all components */ + uint8_t source_system; /**< System sending the command */ + uint8_t source_component; /**< Component sending the command */ + uint8_t confirmation; /**< 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) */ +}; /**< command sent to vehicle */ + +/** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(vehicle_command); + + + +#endif diff --git a/apps/uORB/topics/vehicle_global_position.h b/apps/uORB/topics/vehicle_global_position.h new file mode 100644 index 0000000000..f036c72237 --- /dev/null +++ b/apps/uORB/topics/vehicle_global_position.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Thomas Gubler + * @author Julian Oes + * @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file vehicle_global_position.h + * Definition of the global fused WGS84 position uORB topic. + */ + +#ifndef VEHICLE_GLOBAL_POSITION_T_H_ +#define VEHICLE_GLOBAL_POSITION_T_H_ + +#include +#include +#include "../uORB.h" + +/** + * @addtogroup topics + * @{ + */ + + /** + * Fused global position in WGS84. + * + * This struct contains the system's believ about its position. It is not the raw GPS + * measurement (@see vehicle_gps_position). This topic is usually published by the position + * estimator, which will take more sources of information into account than just GPS, + * e.g. control inputs of the vehicle in a Kalman-filter implementation. + */ +struct vehicle_global_position_s +{ + uint64_t timestamp; /**< time of this estimate, in microseconds since system start */ + uint64_t time_gps_usec; /**< GPS timestamp in microseconds */ + bool valid; /**< true if position satisfies validity criteria of estimator */ + + int32_t lat; /**< Latitude in 1E7 degrees LOGME */ + int32_t lon; /**< Longitude in 1E7 degrees LOGME */ + float alt; /**< Altitude in meters LOGME */ + float relative_alt; /**< Altitude above home position in meters, LOGME */ + float vx; /**< Ground X Speed (Latitude), m/s in ENU LOGME */ + float vy; /**< Ground Y Speed (Longitude), m/s in ENU LOGME */ + float vz; /**< Ground Z Speed (Altitude), m/s in ENU LOGME */ + float hdg; /**< Compass heading in radians -PI..+PI. */ + +}; + +/** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(vehicle_global_position); + +#endif diff --git a/apps/uORB/topics/vehicle_global_position_setpoint.h b/apps/uORB/topics/vehicle_global_position_setpoint.h new file mode 100644 index 0000000000..b73e2a363e --- /dev/null +++ b/apps/uORB/topics/vehicle_global_position_setpoint.h @@ -0,0 +1,78 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Thomas Gubler + * @author Julian Oes + * @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file vehicle_global_position_setpoint.h + * Definition of the global WGS84 position setpoint uORB topic. + */ + +#ifndef TOPIC_VEHICLE_GLOBAL_POSITION_SETPOINT_H_ +#define TOPIC_VEHICLE_GLOBAL_POSITION_SETPOINT_H_ + +#include +#include +#include "../uORB.h" + +/** + * @addtogroup topics + * @{ + */ + +/** + * Global position setpoint in WGS84 coordinates. + * + * This is the position the MAV is heading towards. If it of type loiter, + * the MAV is circling around it with the given loiter radius in meters. + */ +struct vehicle_global_position_setpoint_s +{ + bool altitude_is_relative; /**< true if altitude is relative from start point */ + int32_t lat; /**< latitude in degrees * 1E7 */ + int32_t lon; /**< longitude in degrees * 1E7 */ + float altitude; /**< altitude in meters */ + float yaw; /**< in radians NED -PI..+PI */ + float loiter_radius; /**< loiter radius in meters, 0 for a VTOL to hover */ + bool is_loiter; /**< true if loitering is enabled */ +}; + +/** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(vehicle_global_position_setpoint); + +#endif diff --git a/apps/uORB/topics/vehicle_gps_position.h b/apps/uORB/topics/vehicle_gps_position.h new file mode 100644 index 0000000000..60d01a831c --- /dev/null +++ b/apps/uORB/topics/vehicle_gps_position.h @@ -0,0 +1,89 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Thomas Gubler + * @author Julian Oes + * @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file vehicle_gps_position.h + * Definition of the GPS WGS84 uORB topic. + */ + +#ifndef TOPIC_VEHICLE_GPS_H_ +#define TOPIC_VEHICLE_GPS_H_ + +#include +#include "../uORB.h" + +/** + * @addtogroup topics + * @{ + */ + +/** + * GPS position in WGS84 coordinates. + */ +struct vehicle_gps_position_s +{ + uint64_t timestamp; /**< Timestamp (microseconds since system boot) */ + uint32_t counter; /**< Count of GPS messages */ + uint64_t time_gps_usec; /**< Timestamp (microseconds in GPS format), this is the timestamp which comes from the gps module */ + + int32_t lat; /**< Latitude in 1E7 degrees //LOGME */ + int32_t lon; /**< Longitude in 1E7 degrees //LOGME */ + int32_t alt; /**< Altitude in 1E3 meters (millimeters) above MSL //LOGME */ + uint16_t counter_pos_valid; /**< is only increased when new lat/lon/alt information was added */ + uint16_t eph; /**< GPS HDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 //LOGME */ + uint16_t epv; /**< GPS VDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 */ + uint16_t vel; /**< GPS ground speed (m/s * 100). If unknown, set to: 65535 */ + uint16_t cog; /**< Course over ground (NOT heading, but direction of movement) in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 */ + uint8_t fix_type; /**< 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. */ + uint8_t satellites_visible; /**< Number of satellites visible. If unknown, set to 255 */ + + uint8_t satellite_prn[20]; /**< Global satellite ID */ + uint8_t satellite_used[20]; /**< 0: Satellite not used, 1: used for localization */ + uint8_t satellite_elevation[20]; /**< Elevation (0: right on top of receiver, 90: on the horizon) of satellite */ + uint8_t satellite_azimuth[20]; /**< Direction of satellite, 0: 0 deg, 255: 360 deg. */ + uint8_t satellite_snr[20]; /**< Signal to noise ratio of satellite */ + uint8_t satellite_info_available; /**< 0 for no info, 1 for info available */ + +}; + +/** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(vehicle_gps_position); + +#endif diff --git a/apps/uORB/topics/vehicle_local_position.h b/apps/uORB/topics/vehicle_local_position.h new file mode 100644 index 0000000000..76eddeacd2 --- /dev/null +++ b/apps/uORB/topics/vehicle_local_position.h @@ -0,0 +1,87 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file vehicle_local_position.h + * Definition of the local fused NED position uORB topic. + */ + +#ifndef TOPIC_VEHICLE_LOCAL_POSITION_H_ +#define TOPIC_VEHICLE_LOCAL_POSITION_H_ + +#include +#include +#include "../uORB.h" + +/** + * @addtogroup topics + * @{ + */ + +/** + * Fused local position in NED. + */ +struct vehicle_local_position_s +{ + uint64_t timestamp; /**< time of this estimate, in microseconds since system start */ + bool valid; /**< true if position satisfies validity criteria of estimator */ + + float x; /**< X positin in meters in NED earth-fixed frame */ + float y; /**< X positin in meters in NED earth-fixed frame */ + float z; /**< Z positin in meters in NED earth-fixed frame (negative altitude) */ + float absolute_alt; /**< Altitude as defined by pressure / GPS, LOGME */ + float vx; /**< Ground X Speed (Latitude), m/s in NED LOGME */ + float vy; /**< Ground Y Speed (Longitude), m/s in NED LOGME */ + float vz; /**< Ground Z Speed (Altitude), m/s in NED LOGME */ + float hdg; /**< Compass heading in radians -PI..+PI. */ + + // TODO Add covariances here + + /* Reference position in GPS / WGS84 frame */ + uint64_t home_timestamp;/**< Time when home position was set */ + int32_t home_lat; /**< Latitude in 1E7 degrees LOGME */ + int32_t home_lon; /**< Longitude in 1E7 degrees LOGME */ + float home_alt; /**< Altitude in meters LOGME */ + float home_hdg; /**< Compass heading in radians -PI..+PI. */ + +}; + +/** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(vehicle_local_position); + +#endif diff --git a/apps/uORB/topics/vehicle_local_position_setpoint.h b/apps/uORB/topics/vehicle_local_position_setpoint.h new file mode 100644 index 0000000000..d24d81e3a4 --- /dev/null +++ b/apps/uORB/topics/vehicle_local_position_setpoint.h @@ -0,0 +1,67 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Thomas Gubler + * @author Julian Oes + * @author Lorenz Meier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file vehicle_local_position_setpoint.h + * Definition of the local NED position setpoint uORB topic. + */ + +#ifndef TOPIC_VEHICLE_LOCAL_POSITION_SETPOINT_H_ +#define TOPIC_VEHICLE_LOCAL_POSITION_SETPOINT_H_ + +#include "../uORB.h" + +/** + * @addtogroup topics + * @{ + */ + +struct vehicle_local_position_setpoint_s +{ + float x; /**< in meters NED */ + float y; /**< in meters NED */ + float z; /**< in meters NED */ + float yaw; /**< in radians NED -PI..+PI */ +}; /**< Local position in NED frame to go to */ + +/** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(vehicle_local_position_setpoint); + +#endif diff --git a/apps/uORB/topics/vehicle_status.h b/apps/uORB/topics/vehicle_status.h new file mode 100644 index 0000000000..d92b800469 --- /dev/null +++ b/apps/uORB/topics/vehicle_status.h @@ -0,0 +1,140 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Lorenz Meier + * @author Petri Tanskanen + * @author Thomas Gubler + * @author Julian Oes + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file vehicle_status.h + * Definition of the vehicle_status uORB topic. + * + * Published the state machine and the system status bitfields + * (see SYS_STATUS mavlink message), published only by commander app. + * + * All apps should write to subsystem_info: + * + * (any app) --> subsystem_info (published) --> (commander app state machine) --> vehicle_status --> (mavlink app) + */ + +#ifndef VEHICLE_STATUS_H_ +#define VEHICLE_STATUS_H_ + +#include +#include +#include "../uORB.h" + +/** + * @addtogroup topics @{ + */ + +/* State Machine */ +typedef enum +{ + SYSTEM_STATE_PREFLIGHT = 0, + SYSTEM_STATE_STANDBY = 1, + SYSTEM_STATE_GROUND_READY = 2, + SYSTEM_STATE_MANUAL = 3, + SYSTEM_STATE_STABILIZED = 4, + SYSTEM_STATE_AUTO = 5, + SYSTEM_STATE_MISSION_ABORT = 6, + SYSTEM_STATE_EMCY_LANDING = 7, + SYSTEM_STATE_EMCY_CUTOFF = 8, + SYSTEM_STATE_GROUND_ERROR = 9, + SYSTEM_STATE_REBOOT= 10, + +} commander_state_machine_t; + +enum VEHICLE_MODE_FLAG { + VEHICLE_MODE_FLAG_SAFETY_ARMED = 128, + VEHICLE_MODE_FLAG_MANUAL_INPUT_ENABLED = 64, + VEHICLE_MODE_FLAG_HIL_ENABLED = 32, + VEHICLE_MODE_FLAG_STABILIZE_ENABLED = 16, + VEHICLE_MODE_FLAG_GUIDED_ENABLED = 8, + VEHICLE_MODE_FLAG_AUTO_ENABLED = 4, + VEHICLE_MODE_FLAG_TEST_ENABLED = 2, + VEHICLE_MODE_FLAG_CUSTOM_MODE_ENABLED = 1 +}; /**< Same as MAV_MODE_FLAG of MAVLink 1.0 protocol */ + +/** + * state machine / state of vehicle. + * + * Encodes the complete system state and is set by the commander app. + */ +struct vehicle_status_s +{ + /* use of a counter and timestamp recommended (but not necessary) */ + + uint16_t counter; /**< incremented by the writing thread everytime new data is stored */ + uint64_t timestamp; /**< in microseconds since system start, is set whenever the writing thread stores new data */ + + commander_state_machine_t state_machine; + uint8_t mode; + + bool control_manual_enabled; /**< true if manual input is mixed in */ + bool control_rates_enabled; /**< true if rates are stabilized */ + bool control_attitude_enabled; /**< true if attitude stabilization is mixed in */ + bool control_speed_enabled; /**< true if speed (implies direction) is controlled */ + bool control_position_enabled; /**< true if position is controlled */ + + bool preflight_gyro_calibration; /**< true if gyro calibration is requested */ + bool preflight_mag_calibration; /**< true if mag calibration is requested */ + + /* see SYS_STATUS mavlink message for the following */ + uint32_t onboard_control_sensors_present; + uint32_t onboard_control_sensors_enabled; + uint32_t onboard_control_sensors_health; + uint16_t load; + uint16_t voltage_battery; + int16_t current_battery; + int8_t battery_remaining; + uint16_t drop_rate_comm; + uint16_t errors_comm; + uint16_t errors_count1; + uint16_t errors_count2; + uint16_t errors_count3; + uint16_t errors_count4; + +// bool remote_manual; /**< set to true by the commander when the manual-switch on the remote is set to manual */ + bool gps_valid; /**< set to true by the commander app if the quality of the gps signal is good enough to use it in the position estimator */ + +}; + +/** + * @} + */ + +/* register this as object request broker structure */ +ORB_DECLARE(vehicle_status); + +#endif diff --git a/apps/uORB/uORB.cpp b/apps/uORB/uORB.cpp new file mode 100644 index 0000000000..270e3861cf --- /dev/null +++ b/apps/uORB/uORB.cpp @@ -0,0 +1,969 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file A lightweight object broker. + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include "uORB.h" + +/** + * Utility functions. + */ +namespace +{ + +static const unsigned orb_maxpath = 64; + +/* oddly, ERROR is not defined for c++ */ +#ifdef ERROR +# undef ERROR +#endif +const int ERROR = -1; + +enum Flavor { + PUBSUB, + PARAM +}; + +int +node_mkpath(char *buf, Flavor f, const struct orb_metadata *meta) +{ + unsigned len; + + len = snprintf(buf, orb_maxpath, "/%s/%s", + (f == PUBSUB) ? "obj" : "param", + meta->o_name); + + if (len >= orb_maxpath) + return -ENAMETOOLONG; + + return OK; +} + +} + +/** + * Per-object device instance. + */ +class ORBDevNode : public device::CDev +{ +public: + ORBDevNode(const struct orb_metadata *meta, const char *name, const char *path); + ~ORBDevNode(); + + virtual int open(struct file *filp); + virtual int close(struct file *filp); + virtual ssize_t read(struct file *filp, char *buffer, size_t buflen); + virtual ssize_t write(struct file *filp, const char *buffer, size_t buflen); + virtual int ioctl(struct file *filp, int cmd, unsigned long arg); + +protected: + virtual pollevent_t poll_state(struct file *filp); + virtual void poll_notify_one(struct pollfd *fds, pollevent_t events); + +private: + struct SubscriberData { + unsigned generation; /**< last generation the subscriber has seen */ + unsigned update_interval; /**< if nonzero minimum interval between updates */ + struct hrt_call update_call; /**< deferred wakeup call if update_period is nonzero */ + void *poll_priv; /**< saved copy of fds->f_priv while poll is active */ + bool update_reported; /**< true if we have reported the update via poll/check */ + }; + + const struct orb_metadata *_meta; /**< object metadata information */ + uint8_t *_data; /**< allocated object buffer */ + hrt_abstime _last_update; /**< time the object was last updated */ + volatile unsigned _generation; /**< object generation count */ + pid_t _publisher; /**< if nonzero, current publisher */ + + SubscriberData *filp_to_sd(struct file *filp) { + SubscriberData *sd = (SubscriberData *)(filp->f_priv); + return sd; + } + + /** + * Perform a deferred update for a rate-limited subscriber. + */ + void update_deferred(); + + /** + * Bridge from hrt_call to update_deferred + * + * void *arg ORBDevNode pointer for which the deferred update is performed. + */ + static void update_deferred_trampoline(void *arg); + + /** + * Check whether a topic appears updated to a subscriber. + * + * @param sd The subscriber for whom to check. + * @return True if the topic should appear updated to the subscriber + */ + bool appears_updated(SubscriberData *sd); +}; + +ORBDevNode::ORBDevNode(const struct orb_metadata *meta, const char *name, const char *path) : + CDev(name, path), + _meta(meta), + _data(nullptr), + _last_update(0), + _generation(0), + _publisher(0) +{ + // enable debug() calls + _debug_enabled = true; +} + +ORBDevNode::~ORBDevNode() +{ + if (_data != nullptr) + delete[] _data; +} + +int +ORBDevNode::open(struct file *filp) +{ + int ret; + + /* is this a publisher? */ + if (filp->f_oflags == O_WRONLY) { + + /* become the publisher if we can */ + lock(); + + if (_publisher == 0) { + _publisher = getpid(); + ret = OK; + + } else { + ret = -EBUSY; + } + + unlock(); + + /* now complete the open */ + if (ret == OK) { + ret = CDev::open(filp); + + /* open failed - not the publisher anymore */ + if (ret != OK) + _publisher = 0; + } + + return ret; + } + + /* is this a new subscriber? */ + if (filp->f_oflags == O_RDONLY) { + + /* allocate subscriber data */ + SubscriberData *sd = new SubscriberData; + + if (nullptr == sd) + return -ENOMEM; + + memset(sd, 0, sizeof(*sd)); + + /* default to no pending update */ + sd->generation = _generation; + + filp->f_priv = (void *)sd; + + ret = CDev::open(filp); + + if (ret != OK) + free(sd); + + return ret; + } + + /* can only be pub or sub, not both */ + return -EINVAL; +} + +int +ORBDevNode::close(struct file *filp) +{ + /* is this the publisher closing? */ + if (getpid() == _publisher) { + _publisher = 0; + + } else { + SubscriberData *sd = filp_to_sd(filp); + + if (sd != nullptr) + delete sd; + } + + return CDev::close(filp); +} + +ssize_t +ORBDevNode::read(struct file *filp, char *buffer, size_t buflen) +{ + SubscriberData *sd = (SubscriberData *)filp_to_sd(filp); + + /* if the object has not been written yet, return zero */ + if (_data == nullptr) + return 0; + + /* if the caller's buffer is the wrong size, that's an error */ + if (buflen != _meta->o_size) + return -EIO; + + /* + * Perform an atomic copy & state update + */ + irqstate_t flags = irqsave(); + + /* if the caller doesn't want the data, don't give it to them */ + if (nullptr != buffer) + memcpy(buffer, _data, _meta->o_size); + + /* track the last generation that the file has seen */ + sd->generation = _generation; + + /* + * Clear the flag that indicates that an update has been reported, as + * we have just collected it. + */ + sd->update_reported = false; + + irqrestore(flags); + + return _meta->o_size; +} + +ssize_t +ORBDevNode::write(struct file *filp, const char *buffer, size_t buflen) +{ + /* + * Writes are legal from interrupt context as long as the + * object has already been initialised from thread context. + * + * Writes outside interrupt context will allocate the object + * if it has not yet been allocated. + */ + if (nullptr == _data) { + if (!up_interrupt_context()) { + + lock(); + + /* re-check size */ + if (nullptr == _data) + _data = new uint8_t[_meta->o_size]; + + unlock(); + } + + /* failed or could not allocate */ + if (nullptr == _data) + return -ENOMEM; + } + + /* If write size does not match, that is an error */ + if (_meta->o_size != buflen) + return -EIO; + + /* Perform an atomic copy. */ + irqstate_t flags = irqsave(); + memcpy(_data, buffer, _meta->o_size); + irqrestore(flags); + + /* update the timestamp and generation count */ + _last_update = hrt_absolute_time(); + _generation++; + + /* notify any poll waiters */ + poll_notify(POLLIN); + + return _meta->o_size; +} + +int +ORBDevNode::ioctl(struct file *filp, int cmd, unsigned long arg) +{ + SubscriberData *sd = filp_to_sd(filp); + + switch (cmd) { + case ORBIOCLASTUPDATE: + *(hrt_abstime *)arg = _last_update; + return OK; + + case ORBIOCUPDATED: + *(bool *)arg = appears_updated(sd); + return OK; + + case ORBIOCSETINTERVAL: + sd->update_interval = arg; + return OK; + + default: + /* give it to the superclass */ + return CDev::ioctl(filp, cmd, arg); + } +} + +pollevent_t +ORBDevNode::poll_state(struct file *filp) +{ + SubscriberData *sd = filp_to_sd(filp); + + /* + * If the topic appears updated to the subscriber, say so. + */ + if (appears_updated(sd)) + return POLLIN; + + return 0; +} + +void +ORBDevNode::poll_notify_one(struct pollfd *fds, pollevent_t events) +{ + SubscriberData *sd = filp_to_sd((struct file *)fds->priv); + + /* + * If the topic looks updated to the subscriber, go ahead and notify them. + */ + if (appears_updated(sd)) + CDev::poll_notify_one(fds, events); +} + +bool +ORBDevNode::appears_updated(SubscriberData *sd) +{ + /* assume it doesn't look updated */ + bool ret = false; + + /* avoid racing between interrupt and non-interrupt context calls */ + irqstate_t state = irqsave(); + + /* + * If the subscriber's generation count matches the update generation + * count, there has been no update from their perspective; if they + * don't match then we might have a visible update. + */ + while (sd->generation != _generation) { + + /* + * Handle non-rate-limited subscribers. + */ + if (sd->update_interval == 0) { + ret = true; + break; + } + + /* + * If we have previously told the subscriber that there is data, + * and they have not yet collected it, continue to tell them + * that there has been an update. This mimics the non-rate-limited + * behaviour where checking / polling continues to report an update + * until the topic is read. + */ + if (sd->update_reported) { + ret = true; + break; + } + + /* + * If the interval timer is still running, the topic should not + * appear updated, even though at this point we know that it has. + * We have previously been through here, so the subscriber + * must have collected the update we reported, otherwise + * update_reported would still be true. + */ + if (!hrt_called(&sd->update_call)) + break; + + /* + * Make sure that we don't consider the topic to be updated again + * until the interval has passed once more by restarting the interval + * timer and thereby re-scheduling a poll notification at that time. + */ + hrt_call_after(&sd->update_call, + sd->update_interval, + &ORBDevNode::update_deferred_trampoline, + (void *)this); + + /* + * Remember that we have told the subscriber that there is data. + */ + sd->update_reported = true; + ret = true; + + break; + } + + irqrestore(state); + + /* consider it updated */ + return ret; +} + +void +ORBDevNode::update_deferred() +{ + /* + * Instigate a poll notification; any subscribers whose intervals have + * expired will be woken. + */ + poll_notify(POLLIN); +} + +void +ORBDevNode::update_deferred_trampoline(void *arg) +{ + ORBDevNode *node = (ORBDevNode *)arg; + + node->update_deferred(); +} + +/** + * Master control device for ObjDev. + * + * Used primarily to create new objects via the ORBIOCCREATE + * ioctl. + */ +class ORBDevMaster : public device::CDev +{ +public: + ORBDevMaster(Flavor f); + ~ORBDevMaster(); + + virtual int ioctl(struct file *filp, int cmd, unsigned long arg); +private: + Flavor _flavor; +}; + +ORBDevMaster::ORBDevMaster(Flavor f) : + CDev((f == PUBSUB) ? "obj_master" : "param_master", + (f == PUBSUB) ? TOPIC_MASTER_DEVICE_PATH : PARAM_MASTER_DEVICE_PATH), + _flavor(f) +{ + // enable debug() calls + _debug_enabled = true; + +} + +ORBDevMaster::~ORBDevMaster() +{ +} + +int +ORBDevMaster::ioctl(struct file *filp, int cmd, unsigned long arg) +{ + int ret; + + switch (cmd) { + case ORBIOCADVERTISE: { + const struct orb_metadata *meta = (const struct orb_metadata *)arg; + const char *objname; + char nodepath[orb_maxpath]; + ORBDevNode *node; + + /* construct a path to the node - this also checks the node name */ + ret = node_mkpath(nodepath, _flavor, meta); + + if (ret != OK) + return ret; + + /* driver wants a permanent copy of the node name, so make one here */ + objname = strdup(meta->o_name); + + if (objname == nullptr) + return -ENOMEM; + + /* construct the new node */ + node = new ORBDevNode(meta, objname, nodepath); + + /* initialise the node - this may fail if e.g. a node with this name already exists */ + if (node != nullptr) + ret = node->init(); + + /* if we didn't get a device, that's bad */ + if (node == nullptr) + return -ENOMEM; + + /* if init failed, discard the node and its name */ + if (ret != OK) { + delete node; + free((void *)objname); + } + + return ret; + } + + default: + /* give it to the superclass */ + return CDev::ioctl(filp, cmd, arg); + } +} + + +/** + * Local functions in support of the shell command. + */ + +namespace +{ + +ORBDevMaster *g_dev; + +struct orb_test { + int val; +}; + +ORB_DEFINE(orb_test, struct orb_test); + +int +test_fail(const char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, "FAIL: "); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + fflush(stderr); + return ERROR; +} + +int +test_note(const char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, "note: "); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + fflush(stderr); + return OK; +} + +ORB_DECLARE(sensor_combined); + +int +test() +{ + struct orb_test t, u; + int pfd, sfd; + bool updated; + + t.val = 0; + pfd = orb_advertise(ORB_ID(orb_test), &t); + + if (pfd < 0) + return test_fail("advertise failed: %d", errno); + + test_note("publish fd %d", pfd); + sfd = orb_subscribe(ORB_ID(orb_test)); + + if (sfd < 0) + return test_fail("subscribe failed: %d", errno); + + test_note("subscribe fd %d", sfd); + u.val = 1; + + if (OK != orb_copy(ORB_ID(orb_test), sfd, &u)) + return test_fail("copy(1) failed: %d", errno); + + if (u.val != t.val) + return test_fail("copy(1) mismatch: %d expected %d", u.val, t.val); + + if (OK != orb_check(sfd, &updated)) + return test_fail("check(1) failed"); + + if (updated) + return test_fail("spurious updated flag"); + + t.val = 2; + test_note("try publish"); + + if (OK != orb_publish(ORB_ID(orb_test), pfd, &t)) + return test_fail("publish failed"); + + if (OK != orb_check(sfd, &updated)) + return test_fail("check(2) failed"); + + if (!updated) + return test_fail("missing updated flag"); + + if (OK != orb_copy(ORB_ID(orb_test), sfd, &u)) + return test_fail("copy(2) failed: %d", errno); + + if (u.val != t.val) + return test_fail("copy(2) mismatch: %d expected %d", u.val, t.val); + + orb_unsubscribe(sfd); + close(pfd); + +#if 0 + /* this is a hacky test that exploits the sensors app to test rate-limiting */ + + sfd = orb_subscribe(ORB_ID(sensor_combined)); + + hrt_abstime start, end; + unsigned count; + + start = hrt_absolute_time(); + count = 0; + + do { + orb_check(sfd, &updated); + + if (updated) { + orb_copy(ORB_ID(sensor_combined), sfd, nullptr); + count++; + } + } while (count < 100); + + end = hrt_absolute_time(); + test_note("full-speed, 100 updates in %llu", end - start); + + orb_set_interval(sfd, 10); + + start = hrt_absolute_time(); + count = 0; + + do { + orb_check(sfd, &updated); + + if (updated) { + orb_copy(ORB_ID(sensor_combined), sfd, nullptr); + count++; + } + } while (count < 100); + + end = hrt_absolute_time(); + test_note("100Hz, 100 updates in %llu", end - start); + + orb_unsubscribe(sfd); +#endif + + return test_note("PASS"); +} + +int +info() +{ + return OK; +} + + +} // namespace + +/* + * uORB server 'main'. + */ +extern "C" { __EXPORT int uorb_main(int argc, char *argv[]); } + +int +uorb_main(int argc, char *argv[]) +{ + /* + * Start/load the driver. + * + * XXX it would be nice to have a wrapper for this... + */ + if (!strcmp(argv[1], "start")) { + + if (g_dev != nullptr) { + fprintf(stderr, "[uorb] already loaded\n"); + return -EBUSY; + } + + /* create the driver */ + g_dev = new ORBDevMaster(PUBSUB); + + if (g_dev == nullptr) { + fprintf(stderr, "[uorb] driver alloc failed\n"); + return -ENOMEM; + } + + if (OK != g_dev->init()) { + fprintf(stderr, "[uorb] driver init failed\n"); + delete g_dev; + g_dev = nullptr; + return -EIO; + } + + printf("[uorb] ready\n"); + return OK; + } + + /* + * Test the driver/device. + */ + if (!strcmp(argv[1], "test")) + return test(); + + /* + * Print driver information. + */ + if (!strcmp(argv[1], "info")) + return info(); + + fprintf(stderr, "unrecognised command, try 'start', 'test' or 'info'\n"); + return -EINVAL; +} + +/* + * Library functions. + */ +namespace +{ + +void debug(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + fflush(stderr); + usleep(100000); +} + +/** + * Advertise a node; don't consider it an error if the node has + * already been advertised. + * + * @todo verify that the existing node is the same as the one + * we tried to advertise. + */ +int +node_advertise(const struct orb_metadata *meta) +{ + int fd = -1; + int ret = ERROR; + + /* open the control device */ + fd = open(TOPIC_MASTER_DEVICE_PATH, 0); + + if (fd < 0) + goto out; + + /* advertise the object */ + ret = ioctl(fd, ORBIOCADVERTISE, (unsigned long)(uintptr_t)meta); + + /* it's OK if it already exists */ + if ((OK != ret) && (EEXIST == errno)) + ret = OK; + +out: + + if (fd >= 0) + close(fd); + + return ret; +} + +/** + * Common implementation for orb_advertise and orb_subscribe. + * + * Handles creation of the object and the initial publication for + * advertisers. + */ +int +node_open(Flavor f, const struct orb_metadata *meta, const void *data, bool advertiser) +{ + char path[orb_maxpath]; + int fd, ret; + + /* + * If meta is null, the object was not defined, i.e. it is not + * known to the system. We can't advertise/subscribe such a thing. + */ + if (nullptr == meta) { + errno = ENOENT; + return ERROR; + } + + /* + * Advertiser must publish an initial value. + */ + if (advertiser && (data == nullptr)) { + errno = EINVAL; + return ERROR; + } + + /* + * Generate the path to the node and try to open it. + */ + ret = node_mkpath(path, f, meta); + + if (ret != OK) { + errno = -ret; + return ERROR; + } + + /* open the path as either the advertiser or the subscriber */ + fd = open(path, (advertiser) ? O_WRONLY : O_RDONLY); + + /* we may need to advertise the node... */ + if (fd < 0) { + + /* try to create the node */ + ret = node_advertise(meta); + + /* on success, try the open again */ + if (ret == OK) + fd = open(path, (advertiser) ? O_WRONLY : O_RDONLY); + } + + if (fd < 0) { + errno = EIO; + return ERROR; + } + + /* the advertiser must perform an initial publish to initialise the object */ + if (advertiser) { + ret = orb_publish(meta, fd, data); + + if (ret != OK) { + /* save errno across the close */ + ret = errno; + close(fd); + errno = ret; + return ERROR; + } + } + + /* everything has been OK, we can return the handle now */ + return fd; +} + +} // namespace + +int +orb_advertise(const struct orb_metadata *meta, const void *data) +{ + return node_open(PUBSUB, meta, data, true); +} + +int +orb_subscribe(const struct orb_metadata *meta) +{ + return node_open(PUBSUB, meta, nullptr, false); +} + +int +orb_unsubscribe(int handle) +{ + return close(handle); +} + +int +orb_publish(const struct orb_metadata *meta, int handle, const void *data) +{ + int ret; + + ret = write(handle, data, meta->o_size); + + if (ret < 0) + return ERROR; + + if (ret != (int)meta->o_size) { + errno = EIO; + return ERROR; + } + + return OK; +} + +int +orb_copy(const struct orb_metadata *meta, int handle, void *buffer) +{ + int ret; + + ret = read(handle, buffer, meta->o_size); + + if (ret < 0) + return ERROR; + + if (ret != (int)meta->o_size) { + errno = EIO; + return ERROR; + } + + return OK; +} + +int +orb_check(int handle, bool *updated) +{ + return ioctl(handle, ORBIOCUPDATED, (unsigned long)(uintptr_t)updated); +} + +int +orb_stat(int handle, uint64_t *time) +{ + return ioctl(handle, ORBIOCLASTUPDATE, (unsigned long)(uintptr_t)time); +} + +int +orb_set_interval(int handle, unsigned interval) +{ + return ioctl(handle, ORBIOCSETINTERVAL, interval * 1000); +} + diff --git a/apps/uORB/uORB.h b/apps/uORB/uORB.h new file mode 100644 index 0000000000..c36d0044f2 --- /dev/null +++ b/apps/uORB/uORB.h @@ -0,0 +1,248 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef _UORB_UORB_H +#define _UORB_UORB_H + +/** + * @file API for the uORB lightweight object broker. + */ + +#include +#include +#include + // Hack until parameter storage is cleaned up +#include "parameter_storage.h" + +// Hack until everything is using this header +#include + +/** + * Object metadata. + */ +struct orb_metadata { + const char *o_name; /**< unique object name */ + const size_t o_size; /**< object size */ +}; + +/** + * Generates a pointer to the uORB metadata structure for + * a given topic. + * + * The topic must have been declared previously in scope + * with ORB_DECLARE(). + * + * @param _name The name of the topic. + */ +#define ORB_ID(_name) &__orb_##_name + +/** + * Declare (prototype) the uORB metadata for a topic. + * + * Note that optional topics are declared weak; this allows a potential + * subscriber to attempt to subscribe to a topic that is not known to the + * system at runtime. The ORB_ID() macro will return NULL/nullptr for + * such a topic, and attempts to advertise or subscribe to it will + * return -1/ENOENT (see below). + * + * @param _name The name of the topic. + */ +#if defined(__cplusplus) +# define ORB_DECLARE(_name) extern "C" const struct orb_metadata __orb_##_name __EXPORT +# define ORB_DECLARE_OPTIONAL(_name) extern "C" const struct orb_metadata __orb_##_name __EXPORT __attribute__((weak)) +#else +# define ORB_DECLARE(_name) extern const struct orb_metadata __orb_##_name __EXPORT +# define ORB_DECLARE_OPTIONAL(_name) extern const struct orb_metadata __orb_##_name __EXPORT __attribute__((weak)) +#endif + +/** + * Define (instantiate) the uORB metadata for a topic. + * + * The uORB metadata is used to help ensure that updates and + * copies are accessing the right data. + * + * Note that there must be no more than one instance of this macro + * for each topic. + * + * @param _name The name of the topic. + * @param _struct The structure the topic provides. + */ +#define ORB_DEFINE(_name, _struct) \ + const struct orb_metadata __orb_##_name = { \ + #_name, \ + sizeof(_struct) \ + }; struct hack + +__BEGIN_DECLS + +/** + * Advertise as the publisher of a topic. + * + * This performs the initial advertisement of a topic; it creates the topic + * node in /obj if required and publishes the initial data. + * + * @param meta The uORB metadata (usually from the ORB_ID() macro) + * for the topic. + * @param data A pointer to the initial data to be published. + * For topics updated by interrupt handlers, the advertisement + * must be performed from non-interrupt context. + * @return ERROR on error, otherwise returns a handle + * that can be used to publish to the topic. + * If the topic in question is not known (due to an + * ORB_DEFINE with no corresponding ORB_DECLARE) + * this function will return -1 and set errno to ENOENT. + */ +extern int orb_advertise(const struct orb_metadata *meta, const void *data) __EXPORT; + +/** + * Publish new data to a topic. + * + * The data is atomically published to the topic and any waiting subscribers + * will be notified. Subscribers that are not waiting can check the topic + * for updates using orb_check and/or orb_stat. + * + * @handle The handle returned from orb_advertise. + * @param meta The uORB metadata (usually from the ORB_ID() macro) + * for the topic. + * @param data A pointer to the data to be published. + * @return OK on success, ERROR otherwise with errno set accordingly. + */ +extern int orb_publish(const struct orb_metadata *meta, int handle, const void *data) __EXPORT; + +/** + * Subscribe to a topic. + * + * The returned value is a file descriptor that can be passed to poll() + * in order to wait for updates to a topic, as well as topic_read, + * orb_check and orb_stat. + * + * Subscription will succeed even if the topic has not been advertised; + * in this case the topic will have a timestamp of zero, it will never + * signal a poll() event, checking will always return false and it cannot + * be copied. When the topic is subsequently advertised, poll, check, + * stat and copy calls will react to the initial publication that is + * performed as part of the advertisement. + * + * Subscription will fail if the topic is not known to the system, i.e. + * there is nothing in the system that has declared the topic and thus it + * can never be published. + * + * @param meta The uORB metadata (usually from the ORB_ID() macro) + * for the topic. + * @return ERROR on error, otherwise returns a handle + * that can be used to read and update the topic. + * If the topic in question is not known (due to an + * ORB_DEFINE_OPTIONAL with no corresponding ORB_DECLARE) + * this function will return -1 and set errno to ENOENT. + */ +extern int orb_subscribe(const struct orb_metadata *meta) __EXPORT; + +/** + * Unsubscribe from a topic. + * + * @param handle A handle returned from orb_subscribe. + * @return OK on success, ERROR otherwise with errno set accordingly. + */ +extern int orb_unsubscribe(int handle) __EXPORT; + +/** + * Fetch data from a topic. + * + * This is the only operation that will reset the internal marker that + * indicates that a topic has been updated for a subscriber. Once poll + * or check return indicating that an updaet is available, this call + * must be used to update the subscription. + * + * @param meta The uORB metadata (usually from the ORB_ID() macro) + * for the topic. + * @param handle A handle returned from orb_subscribe. + * @param buffer Pointer to the buffer receiving the data, or NULL + * if the caller wants to clear the updated flag without + * using the data. + * @return OK on success, ERROR otherwise with errno set accordingly. + */ +extern int orb_copy(const struct orb_metadata *meta, int handle, void *buffer) __EXPORT; + +/** + * Check whether a topic has been published to since the last orb_copy. + * + * This check can be used to determine whether to copy the topic when + * not using poll(), or to avoid the overhead of calling poll() when the + * topic is likely to have updated. + * + * Updates are tracked on a per-handle basis; this call will continue to + * return true until orb_copy is called using the same handle. This interface + * should be preferred over calling orb_stat due to the race window between + * stat and copy that can lead to missed updates. + * + * @param handle A handle returned from orb_subscribe. + * @param updated Set to true if the topic has been updated since the + * last time it was copied using this handle. + * @return OK if the check was successful, ERROR otherwise with + * errno set accordingly. + */ +extern int orb_check(int handle, bool *updated) __EXPORT; + +/** + * Return the last time that the topic was updated. + * + * @param handle A handle returned from orb_subscribe. + * @param time Returns the absolute time that the topic was updated, or zero if it has + * never been updated. Time is measured in microseconds. + * @return OK on success, ERROR otherwise with errno set accordingly. + */ +extern int orb_stat(int handle, uint64_t *time) __EXPORT; + +/** + * Set the minimum interval between which updates are seen for a subscription. + * + * If this interval is set, the subscriber will not see more than one update + * within the period. + * + * Specifically, the first time an update is reported to the subscriber a timer + * is started. The update will continue to be reported via poll and orb_check, but + * once fetched via orb_copy another update will not be reported until the timer + * expires. + * + * This feature can be used to pace a subscriber that is watching a topic that + * would otherwise update too quickly. + * + * @param handle A handle returned from orb_subscribe. + * @param interval An interval period in milliseconds. + * @return OK on success, ERROR otherwise with ERRNO set accordingly. + */ +extern int orb_set_interval(int handle, unsigned interval) __EXPORT; + +__END_DECLS + +#endif /* _UORB_UORB_H */ diff --git a/mavlink/include/mavlink/config.h b/mavlink/include/mavlink/config.h new file mode 100644 index 0000000000..db7db0d7d6 --- /dev/null +++ b/mavlink/include/mavlink/config.h @@ -0,0 +1 @@ +#define MAVLINK_VERSION "1.0.7" diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/ardupilotmega.h b/mavlink/include/mavlink/v0.9/ardupilotmega/ardupilotmega.h new file mode 100644 index 0000000000..4148b5a6a9 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/ardupilotmega.h @@ -0,0 +1,154 @@ +/** @file + * @brief MAVLink comm protocol generated from ardupilotmega.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef ARDUPILOTMEGA_H +#define ARDUPILOTMEGA_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {3, 4, 8, 14, 8, 28, 3, 32, 0, 2, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 19, 2, 23, 21, 0, 37, 26, 101, 26, 16, 32, 32, 37, 32, 11, 17, 17, 16, 18, 36, 4, 4, 2, 2, 4, 2, 2, 3, 14, 12, 18, 16, 8, 27, 25, 18, 18, 24, 24, 0, 0, 0, 26, 16, 36, 5, 6, 56, 26, 21, 18, 0, 0, 18, 20, 20, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 8, 4, 12, 15, 13, 6, 15, 14, 0, 12, 3, 8, 28, 36, 3, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 14, 14, 51, 5} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {72, 39, 190, 92, 191, 217, 104, 119, 0, 219, 60, 186, 10, 0, 0, 0, 0, 0, 0, 0, 89, 159, 162, 121, 0, 149, 222, 110, 179, 136, 66, 126, 185, 147, 112, 252, 162, 215, 229, 128, 9, 106, 101, 213, 4, 229, 21, 214, 215, 14, 206, 50, 157, 126, 108, 213, 95, 5, 127, 0, 0, 0, 57, 126, 130, 119, 193, 191, 236, 158, 143, 0, 0, 104, 123, 131, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 29, 208, 188, 118, 242, 19, 97, 233, 0, 18, 68, 136, 127, 42, 21, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 224, 60, 106, 7} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, MAVLINK_MESSAGE_INFO_BOOT, MAVLINK_MESSAGE_INFO_SYSTEM_TIME, MAVLINK_MESSAGE_INFO_PING, MAVLINK_MESSAGE_INFO_SYSTEM_TIME_UTC, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK, MAVLINK_MESSAGE_INFO_AUTH_KEY, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_ACTION_ACK, MAVLINK_MESSAGE_INFO_ACTION, MAVLINK_MESSAGE_INFO_SET_MODE, MAVLINK_MESSAGE_INFO_SET_NAV_MODE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST, MAVLINK_MESSAGE_INFO_PARAM_VALUE, MAVLINK_MESSAGE_INFO_PARAM_SET, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_GPS_RAW_INT, MAVLINK_MESSAGE_INFO_SCALED_IMU, MAVLINK_MESSAGE_INFO_GPS_STATUS, MAVLINK_MESSAGE_INFO_RAW_IMU, MAVLINK_MESSAGE_INFO_RAW_PRESSURE, MAVLINK_MESSAGE_INFO_ATTITUDE, MAVLINK_MESSAGE_INFO_LOCAL_POSITION, MAVLINK_MESSAGE_INFO_GPS_RAW, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION, MAVLINK_MESSAGE_INFO_SYS_STATUS, MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW, MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED, MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW, MAVLINK_MESSAGE_INFO_SCALED_PRESSURE, MAVLINK_MESSAGE_INFO_WAYPOINT, MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST, MAVLINK_MESSAGE_INFO_WAYPOINT_SET_CURRENT, MAVLINK_MESSAGE_INFO_WAYPOINT_CURRENT, MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST_LIST, MAVLINK_MESSAGE_INFO_WAYPOINT_COUNT, MAVLINK_MESSAGE_INFO_WAYPOINT_CLEAR_ALL, MAVLINK_MESSAGE_INFO_WAYPOINT_REACHED, MAVLINK_MESSAGE_INFO_WAYPOINT_ACK, MAVLINK_MESSAGE_INFO_GPS_SET_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_GPS_LOCAL_ORIGIN_SET, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT_SET, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_CONTROL_STATUS, MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT, MAVLINK_MESSAGE_INFO_POSITION_TARGET, MAVLINK_MESSAGE_INFO_STATE_CORRECTION, MAVLINK_MESSAGE_INFO_SET_ALTITUDE, MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM, MAVLINK_MESSAGE_INFO_HIL_STATE, MAVLINK_MESSAGE_INFO_HIL_CONTROLS, MAVLINK_MESSAGE_INFO_MANUAL_CONTROL, MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT, MAVLINK_MESSAGE_INFO_VFR_HUD, MAVLINK_MESSAGE_INFO_COMMAND, MAVLINK_MESSAGE_INFO_COMMAND_ACK, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OPTICAL_FLOW, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OBJECT_DETECTION_EVENT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_SENSOR_OFFSETS, MAVLINK_MESSAGE_INFO_SET_MAG_OFFSETS, MAVLINK_MESSAGE_INFO_MEMINFO, MAVLINK_MESSAGE_INFO_AP_ADC, MAVLINK_MESSAGE_INFO_DIGICAM_CONFIGURE, MAVLINK_MESSAGE_INFO_DIGICAM_CONTROL, MAVLINK_MESSAGE_INFO_MOUNT_CONFIGURE, MAVLINK_MESSAGE_INFO_MOUNT_CONTROL, MAVLINK_MESSAGE_INFO_MOUNT_STATUS, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_FENCE_POINT, MAVLINK_MESSAGE_INFO_FENCE_FETCH_POINT, MAVLINK_MESSAGE_INFO_FENCE_STATUS, MAVLINK_MESSAGE_INFO_AHRS, MAVLINK_MESSAGE_INFO_SIMSTATE, MAVLINK_MESSAGE_INFO_HWSTATUS, MAVLINK_MESSAGE_INFO_RADIO, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_DEBUG_VECT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT, MAVLINK_MESSAGE_INFO_STATUSTEXT, MAVLINK_MESSAGE_INFO_DEBUG} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_ARDUPILOTMEGA + +#include "../common/common.h" + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +// ENUM DEFINITIONS + + +/** @brief Enumeration of possible mount operation modes */ +#ifndef HAVE_ENUM_MAV_MOUNT_MODE +#define HAVE_ENUM_MAV_MOUNT_MODE +enum MAV_MOUNT_MODE +{ + MAV_MOUNT_MODE_RETRACT=0, /* Load and keep safe position (Roll,Pitch,Yaw) from EEPROM and stop stabilization | */ + MAV_MOUNT_MODE_NEUTRAL=1, /* Load and keep neutral position (Roll,Pitch,Yaw) from EEPROM. | */ + MAV_MOUNT_MODE_MAVLINK_TARGETING=2, /* Load neutral position and start MAVLink Roll,Pitch,Yaw control with stabilization | */ + MAV_MOUNT_MODE_RC_TARGETING=3, /* Load neutral position and start RC Roll,Pitch,Yaw control with stabilization | */ + MAV_MOUNT_MODE_GPS_POINT=4, /* Load neutral position and start to point to Lat,Lon,Alt | */ + MAV_MOUNT_MODE_ENUM_END=5, /* | */ +}; +#endif + +/** @brief */ +#ifndef HAVE_ENUM_MAV_CMD +#define HAVE_ENUM_MAV_CMD +enum MAV_CMD +{ + MAV_CMD_NAV_WAYPOINT=16, /* Navigate to waypoint. |Hold time in decimal seconds. (ignored by fixed wing, time to stay at waypoint for rotary wing)| Acceptance radius in meters (if the sphere with this radius is hit, the waypoint counts as reached)| 0 to pass through the WP, if > 0 radius in meters to pass by WP. Positive value for clockwise orbit, negative value for counter-clockwise orbit. Allows trajectory control.| Desired yaw angle at waypoint (rotary wing)| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_UNLIM=17, /* Loiter around this waypoint an unlimited amount of time |Empty| Empty| Radius around waypoint, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_TURNS=18, /* Loiter around this waypoint for X turns |Turns| Empty| Radius around waypoint, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_TIME=19, /* Loiter around this waypoint for X seconds |Seconds (decimal)| Empty| Radius around waypoint, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_RETURN_TO_LAUNCH=20, /* Return to launch location |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_NAV_LAND=21, /* Land at location |Empty| Empty| Empty| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_TAKEOFF=22, /* Takeoff from ground / hand |Minimum pitch (if airspeed sensor present), desired pitch without sensor| Empty| Empty| Yaw angle (if magnetometer present), ignored without magnetometer| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_ROI=80, /* Sets the region of interest (ROI) for a sensor set or the + vehicle itself. This can then be used by the vehicles control + system to control the vehicle attitude and the attitude of various + sensors such as cameras. |Region of intereset mode. (see MAV_ROI enum)| Waypoint index/ target ID. (see MAV_ROI enum)| ROI index (allows a vehicle to manage multiple ROI's)| Empty| x the location of the fixed ROI (see MAV_FRAME)| y| z| */ + MAV_CMD_NAV_PATHPLANNING=81, /* Control autonomous path planning on the MAV. |0: Disable local obstacle avoidance / local path planning (without resetting map), 1: Enable local path planning, 2: Enable and reset local path planning| 0: Disable full path planning (without resetting map), 1: Enable, 2: Enable and reset map/occupancy grid, 3: Enable and reset planned route, but not occupancy grid| Empty| Yaw angle at goal, in compass degrees, [0..360]| Latitude/X of goal| Longitude/Y of goal| Altitude/Z of goal| */ + MAV_CMD_NAV_LAST=95, /* NOP - This command is only used to mark the upper limit of the NAV/ACTION commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_DELAY=112, /* Delay mission state machine. |Delay in seconds (decimal)| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_CHANGE_ALT=113, /* Ascend/descend at rate. Delay mission state machine until desired altitude reached. |Descent / Ascend rate (m/s)| Empty| Empty| Empty| Empty| Empty| Finish Altitude| */ + MAV_CMD_CONDITION_DISTANCE=114, /* Delay mission state machine until within desired distance of next NAV point. |Distance (meters)| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_YAW=115, /* Reach a certain target angle. |target angle: [0-360], 0 is north| speed during yaw change:[deg per second]| direction: negative: counter clockwise, positive: clockwise [-1,1]| relative offset or absolute angle: [ 1,0]| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_LAST=159, /* NOP - This command is only used to mark the upper limit of the CONDITION commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_MODE=176, /* Set system mode. |Mode, as defined by ENUM MAV_MODE| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_JUMP=177, /* Jump to the desired command in the mission list. Repeat this action only the specified number of times |Sequence number| Repeat count| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_CHANGE_SPEED=178, /* Change speed and/or throttle set points. |Speed type (0=Airspeed, 1=Ground Speed)| Speed (m/s, -1 indicates no change)| Throttle ( Percent, -1 indicates no change)| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_HOME=179, /* Changes the home location either to the current location or a specified location. |Use current (1=use current location, 0=use specified location)| Empty| Empty| Empty| Latitude| Longitude| Altitude| */ + MAV_CMD_DO_SET_PARAMETER=180, /* Set a system parameter. Caution! Use of this command requires knowledge of the numeric enumeration value of the parameter. |Parameter number| Parameter value| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_RELAY=181, /* Set a relay to a condition. |Relay number| Setting (1=on, 0=off, others possible depending on system hardware)| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_REPEAT_RELAY=182, /* Cycle a relay on and off for a desired number of cyles with a desired period. |Relay number| Cycle count| Cycle time (seconds, decimal)| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_SERVO=183, /* Set a servo to a desired PWM value. |Servo number| PWM (microseconds, 1000 to 2000 typical)| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_REPEAT_SERVO=184, /* Cycle a between its nominal setting and a desired PWM for a desired number of cycles with a desired period. |Servo number| PWM (microseconds, 1000 to 2000 typical)| Cycle count| Cycle time (seconds)| Empty| Empty| Empty| */ + MAV_CMD_DO_CONTROL_VIDEO=200, /* Control onboard camera capturing. |Camera ID (-1 for all)| Transmission: 0: disabled, 1: enabled compressed, 2: enabled raw| Transmission mode: 0: video stream, >0: single images every n seconds (decimal)| Recording: 0: disabled, 1: enabled compressed, 2: enabled raw| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_ROI=201, /* Sets the region of interest (ROI) for a sensor set or the + vehicle itself. This can then be used by the vehicles control + system to control the vehicle attitude and the attitude of various + devices such as cameras. + |Region of interest mode. (see MAV_ROI enum)| Waypoint index/ target ID. (see MAV_ROI enum)| ROI index (allows a vehicle to manage multiple cameras etc.)| Empty| x the location of the fixed ROI (see MAV_FRAME)| y| z| */ + MAV_CMD_DO_DIGICAM_CONFIGURE=202, /* Mission command to configure an on-board camera controller system. |Modes: P, TV, AV, M, Etc| Shutter speed: Divisor number for one second| Aperture: F stop number| ISO number e.g. 80, 100, 200, Etc| Exposure type enumerator| Command Identity| Main engine cut-off time before camera trigger in seconds/10 (0 means no cut-off)| */ + MAV_CMD_DO_DIGICAM_CONTROL=203, /* Mission command to control an on-board camera controller system. |Session control e.g. show/hide lens| Zoom's absolute position| Zooming step value to offset zoom from the current position| Focus Locking, Unlocking or Re-locking| Shooting Command| Command Identity| Empty| */ + MAV_CMD_DO_MOUNT_CONFIGURE=204, /* Mission command to configure a camera or antenna mount |Mount operation mode (see MAV_MOUNT_MODE enum)| stabilize roll? (1 = yes, 0 = no)| stabilize pitch? (1 = yes, 0 = no)| stabilize yaw? (1 = yes, 0 = no)| Empty| Empty| Empty| */ + MAV_CMD_DO_MOUNT_CONTROL=205, /* Mission command to control a camera or antenna mount |pitch(deg*100) or lat, depending on mount mode.| roll(deg*100) or lon depending on mount mode| yaw(deg*100) or alt (in cm) depending on mount mode| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_LAST=240, /* NOP - This command is only used to mark the upper limit of the DO commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_PREFLIGHT_CALIBRATION=241, /* Trigger calibration. This command will be only accepted if in pre-flight mode. |Gyro calibration: 0: no, 1: yes| Magnetometer calibration: 0: no, 1: yes| Ground pressure: 0: no, 1: yes| Radio calibration: 0: no, 1: yes| Empty| Empty| Empty| */ + MAV_CMD_PREFLIGHT_STORAGE=245, /* Request storage of different parameter values and logs. This command will be only accepted if in pre-flight mode. |Parameter storage: 0: READ FROM FLASH/EEPROM, 1: WRITE CURRENT TO FLASH/EEPROM| Mission storage: 0: READ FROM FLASH/EEPROM, 1: WRITE CURRENT TO FLASH/EEPROM| Reserved| Reserved| Empty| Empty| Empty| */ + MAV_CMD_ENUM_END=246, /* | */ +}; +#endif + +/** @brief */ +#ifndef HAVE_ENUM_FENCE_ACTION +#define HAVE_ENUM_FENCE_ACTION +enum FENCE_ACTION +{ + FENCE_ACTION_NONE=0, /* Disable fenced mode | */ + FENCE_ACTION_GUIDED=1, /* Switched to guided mode to return point (fence point 0) | */ + FENCE_ACTION_ENUM_END=2, /* | */ +}; +#endif + +/** @brief */ +#ifndef HAVE_ENUM_FENCE_BREACH +#define HAVE_ENUM_FENCE_BREACH +enum FENCE_BREACH +{ + FENCE_BREACH_NONE=0, /* No last fence breach | */ + FENCE_BREACH_MINALT=1, /* Breached minimum altitude | */ + FENCE_BREACH_MAXALT=2, /* Breached minimum altitude | */ + FENCE_BREACH_BOUNDARY=3, /* Breached fence boundary | */ + FENCE_BREACH_ENUM_END=4, /* | */ +}; +#endif + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_sensor_offsets.h" +#include "./mavlink_msg_set_mag_offsets.h" +#include "./mavlink_msg_meminfo.h" +#include "./mavlink_msg_ap_adc.h" +#include "./mavlink_msg_digicam_configure.h" +#include "./mavlink_msg_digicam_control.h" +#include "./mavlink_msg_mount_configure.h" +#include "./mavlink_msg_mount_control.h" +#include "./mavlink_msg_mount_status.h" +#include "./mavlink_msg_fence_point.h" +#include "./mavlink_msg_fence_fetch_point.h" +#include "./mavlink_msg_fence_status.h" +#include "./mavlink_msg_ahrs.h" +#include "./mavlink_msg_simstate.h" +#include "./mavlink_msg_hwstatus.h" +#include "./mavlink_msg_radio.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // ARDUPILOTMEGA_H diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink.h new file mode 100644 index 0000000000..72e0248d98 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink.h @@ -0,0 +1,27 @@ +/** @file + * @brief MAVLink comm protocol built from ardupilotmega.xml + * @see http://pixhawk.ethz.ch/software/mavlink + */ +#ifndef MAVLINK_H +#define MAVLINK_H + +#ifndef MAVLINK_STX +#define MAVLINK_STX 85 +#endif + +#ifndef MAVLINK_ENDIAN +#define MAVLINK_ENDIAN MAVLINK_BIG_ENDIAN +#endif + +#ifndef MAVLINK_ALIGNED_FIELDS +#define MAVLINK_ALIGNED_FIELDS 0 +#endif + +#ifndef MAVLINK_CRC_EXTRA +#define MAVLINK_CRC_EXTRA 0 +#endif + +#include "version.h" +#include "ardupilotmega.h" + +#endif // MAVLINK_H diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_ahrs.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_ahrs.h new file mode 100644 index 0000000000..9cb06e6b1a --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_ahrs.h @@ -0,0 +1,276 @@ +// MESSAGE AHRS PACKING + +#define MAVLINK_MSG_ID_AHRS 163 + +typedef struct __mavlink_ahrs_t +{ + float omegaIx; ///< X gyro drift estimate rad/s + float omegaIy; ///< Y gyro drift estimate rad/s + float omegaIz; ///< Z gyro drift estimate rad/s + float accel_weight; ///< average accel_weight + float renorm_val; ///< average renormalisation value + float error_rp; ///< average error_roll_pitch value + float error_yaw; ///< average error_yaw value +} mavlink_ahrs_t; + +#define MAVLINK_MSG_ID_AHRS_LEN 28 +#define MAVLINK_MSG_ID_163_LEN 28 + + + +#define MAVLINK_MESSAGE_INFO_AHRS { \ + "AHRS", \ + 7, \ + { { "omegaIx", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_ahrs_t, omegaIx) }, \ + { "omegaIy", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_ahrs_t, omegaIy) }, \ + { "omegaIz", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_ahrs_t, omegaIz) }, \ + { "accel_weight", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_ahrs_t, accel_weight) }, \ + { "renorm_val", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_ahrs_t, renorm_val) }, \ + { "error_rp", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_ahrs_t, error_rp) }, \ + { "error_yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_ahrs_t, error_yaw) }, \ + } \ +} + + +/** + * @brief Pack a ahrs message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param omegaIx X gyro drift estimate rad/s + * @param omegaIy Y gyro drift estimate rad/s + * @param omegaIz Z gyro drift estimate rad/s + * @param accel_weight average accel_weight + * @param renorm_val average renormalisation value + * @param error_rp average error_roll_pitch value + * @param error_yaw average error_yaw value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ahrs_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float omegaIx, float omegaIy, float omegaIz, float accel_weight, float renorm_val, float error_rp, float error_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_float(buf, 0, omegaIx); + _mav_put_float(buf, 4, omegaIy); + _mav_put_float(buf, 8, omegaIz); + _mav_put_float(buf, 12, accel_weight); + _mav_put_float(buf, 16, renorm_val); + _mav_put_float(buf, 20, error_rp); + _mav_put_float(buf, 24, error_yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_ahrs_t packet; + packet.omegaIx = omegaIx; + packet.omegaIy = omegaIy; + packet.omegaIz = omegaIz; + packet.accel_weight = accel_weight; + packet.renorm_val = renorm_val; + packet.error_rp = error_rp; + packet.error_yaw = error_yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_AHRS; + return mavlink_finalize_message(msg, system_id, component_id, 28); +} + +/** + * @brief Pack a ahrs message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param omegaIx X gyro drift estimate rad/s + * @param omegaIy Y gyro drift estimate rad/s + * @param omegaIz Z gyro drift estimate rad/s + * @param accel_weight average accel_weight + * @param renorm_val average renormalisation value + * @param error_rp average error_roll_pitch value + * @param error_yaw average error_yaw value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ahrs_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float omegaIx,float omegaIy,float omegaIz,float accel_weight,float renorm_val,float error_rp,float error_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_float(buf, 0, omegaIx); + _mav_put_float(buf, 4, omegaIy); + _mav_put_float(buf, 8, omegaIz); + _mav_put_float(buf, 12, accel_weight); + _mav_put_float(buf, 16, renorm_val); + _mav_put_float(buf, 20, error_rp); + _mav_put_float(buf, 24, error_yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_ahrs_t packet; + packet.omegaIx = omegaIx; + packet.omegaIy = omegaIy; + packet.omegaIz = omegaIz; + packet.accel_weight = accel_weight; + packet.renorm_val = renorm_val; + packet.error_rp = error_rp; + packet.error_yaw = error_yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_AHRS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 28); +} + +/** + * @brief Encode a ahrs struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param ahrs C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_ahrs_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_ahrs_t* ahrs) +{ + return mavlink_msg_ahrs_pack(system_id, component_id, msg, ahrs->omegaIx, ahrs->omegaIy, ahrs->omegaIz, ahrs->accel_weight, ahrs->renorm_val, ahrs->error_rp, ahrs->error_yaw); +} + +/** + * @brief Send a ahrs message + * @param chan MAVLink channel to send the message + * + * @param omegaIx X gyro drift estimate rad/s + * @param omegaIy Y gyro drift estimate rad/s + * @param omegaIz Z gyro drift estimate rad/s + * @param accel_weight average accel_weight + * @param renorm_val average renormalisation value + * @param error_rp average error_roll_pitch value + * @param error_yaw average error_yaw value + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_ahrs_send(mavlink_channel_t chan, float omegaIx, float omegaIy, float omegaIz, float accel_weight, float renorm_val, float error_rp, float error_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_float(buf, 0, omegaIx); + _mav_put_float(buf, 4, omegaIy); + _mav_put_float(buf, 8, omegaIz); + _mav_put_float(buf, 12, accel_weight); + _mav_put_float(buf, 16, renorm_val); + _mav_put_float(buf, 20, error_rp); + _mav_put_float(buf, 24, error_yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AHRS, buf, 28); +#else + mavlink_ahrs_t packet; + packet.omegaIx = omegaIx; + packet.omegaIy = omegaIy; + packet.omegaIz = omegaIz; + packet.accel_weight = accel_weight; + packet.renorm_val = renorm_val; + packet.error_rp = error_rp; + packet.error_yaw = error_yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AHRS, (const char *)&packet, 28); +#endif +} + +#endif + +// MESSAGE AHRS UNPACKING + + +/** + * @brief Get field omegaIx from ahrs message + * + * @return X gyro drift estimate rad/s + */ +static inline float mavlink_msg_ahrs_get_omegaIx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field omegaIy from ahrs message + * + * @return Y gyro drift estimate rad/s + */ +static inline float mavlink_msg_ahrs_get_omegaIy(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field omegaIz from ahrs message + * + * @return Z gyro drift estimate rad/s + */ +static inline float mavlink_msg_ahrs_get_omegaIz(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field accel_weight from ahrs message + * + * @return average accel_weight + */ +static inline float mavlink_msg_ahrs_get_accel_weight(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field renorm_val from ahrs message + * + * @return average renormalisation value + */ +static inline float mavlink_msg_ahrs_get_renorm_val(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field error_rp from ahrs message + * + * @return average error_roll_pitch value + */ +static inline float mavlink_msg_ahrs_get_error_rp(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field error_yaw from ahrs message + * + * @return average error_yaw value + */ +static inline float mavlink_msg_ahrs_get_error_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Decode a ahrs message into a struct + * + * @param msg The message to decode + * @param ahrs C-struct to decode the message contents into + */ +static inline void mavlink_msg_ahrs_decode(const mavlink_message_t* msg, mavlink_ahrs_t* ahrs) +{ +#if MAVLINK_NEED_BYTE_SWAP + ahrs->omegaIx = mavlink_msg_ahrs_get_omegaIx(msg); + ahrs->omegaIy = mavlink_msg_ahrs_get_omegaIy(msg); + ahrs->omegaIz = mavlink_msg_ahrs_get_omegaIz(msg); + ahrs->accel_weight = mavlink_msg_ahrs_get_accel_weight(msg); + ahrs->renorm_val = mavlink_msg_ahrs_get_renorm_val(msg); + ahrs->error_rp = mavlink_msg_ahrs_get_error_rp(msg); + ahrs->error_yaw = mavlink_msg_ahrs_get_error_yaw(msg); +#else + memcpy(ahrs, _MAV_PAYLOAD(msg), 28); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_ap_adc.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_ap_adc.h new file mode 100644 index 0000000000..07eacc9a91 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_ap_adc.h @@ -0,0 +1,254 @@ +// MESSAGE AP_ADC PACKING + +#define MAVLINK_MSG_ID_AP_ADC 153 + +typedef struct __mavlink_ap_adc_t +{ + uint16_t adc1; ///< ADC output 1 + uint16_t adc2; ///< ADC output 2 + uint16_t adc3; ///< ADC output 3 + uint16_t adc4; ///< ADC output 4 + uint16_t adc5; ///< ADC output 5 + uint16_t adc6; ///< ADC output 6 +} mavlink_ap_adc_t; + +#define MAVLINK_MSG_ID_AP_ADC_LEN 12 +#define MAVLINK_MSG_ID_153_LEN 12 + + + +#define MAVLINK_MESSAGE_INFO_AP_ADC { \ + "AP_ADC", \ + 6, \ + { { "adc1", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_ap_adc_t, adc1) }, \ + { "adc2", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_ap_adc_t, adc2) }, \ + { "adc3", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_ap_adc_t, adc3) }, \ + { "adc4", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_ap_adc_t, adc4) }, \ + { "adc5", NULL, MAVLINK_TYPE_UINT16_T, 0, 8, offsetof(mavlink_ap_adc_t, adc5) }, \ + { "adc6", NULL, MAVLINK_TYPE_UINT16_T, 0, 10, offsetof(mavlink_ap_adc_t, adc6) }, \ + } \ +} + + +/** + * @brief Pack a ap_adc message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param adc1 ADC output 1 + * @param adc2 ADC output 2 + * @param adc3 ADC output 3 + * @param adc4 ADC output 4 + * @param adc5 ADC output 5 + * @param adc6 ADC output 6 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ap_adc_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t adc1, uint16_t adc2, uint16_t adc3, uint16_t adc4, uint16_t adc5, uint16_t adc6) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint16_t(buf, 0, adc1); + _mav_put_uint16_t(buf, 2, adc2); + _mav_put_uint16_t(buf, 4, adc3); + _mav_put_uint16_t(buf, 6, adc4); + _mav_put_uint16_t(buf, 8, adc5); + _mav_put_uint16_t(buf, 10, adc6); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_ap_adc_t packet; + packet.adc1 = adc1; + packet.adc2 = adc2; + packet.adc3 = adc3; + packet.adc4 = adc4; + packet.adc5 = adc5; + packet.adc6 = adc6; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_AP_ADC; + return mavlink_finalize_message(msg, system_id, component_id, 12); +} + +/** + * @brief Pack a ap_adc message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param adc1 ADC output 1 + * @param adc2 ADC output 2 + * @param adc3 ADC output 3 + * @param adc4 ADC output 4 + * @param adc5 ADC output 5 + * @param adc6 ADC output 6 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ap_adc_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t adc1,uint16_t adc2,uint16_t adc3,uint16_t adc4,uint16_t adc5,uint16_t adc6) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint16_t(buf, 0, adc1); + _mav_put_uint16_t(buf, 2, adc2); + _mav_put_uint16_t(buf, 4, adc3); + _mav_put_uint16_t(buf, 6, adc4); + _mav_put_uint16_t(buf, 8, adc5); + _mav_put_uint16_t(buf, 10, adc6); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_ap_adc_t packet; + packet.adc1 = adc1; + packet.adc2 = adc2; + packet.adc3 = adc3; + packet.adc4 = adc4; + packet.adc5 = adc5; + packet.adc6 = adc6; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_AP_ADC; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12); +} + +/** + * @brief Encode a ap_adc struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param ap_adc C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_ap_adc_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_ap_adc_t* ap_adc) +{ + return mavlink_msg_ap_adc_pack(system_id, component_id, msg, ap_adc->adc1, ap_adc->adc2, ap_adc->adc3, ap_adc->adc4, ap_adc->adc5, ap_adc->adc6); +} + +/** + * @brief Send a ap_adc message + * @param chan MAVLink channel to send the message + * + * @param adc1 ADC output 1 + * @param adc2 ADC output 2 + * @param adc3 ADC output 3 + * @param adc4 ADC output 4 + * @param adc5 ADC output 5 + * @param adc6 ADC output 6 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_ap_adc_send(mavlink_channel_t chan, uint16_t adc1, uint16_t adc2, uint16_t adc3, uint16_t adc4, uint16_t adc5, uint16_t adc6) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint16_t(buf, 0, adc1); + _mav_put_uint16_t(buf, 2, adc2); + _mav_put_uint16_t(buf, 4, adc3); + _mav_put_uint16_t(buf, 6, adc4); + _mav_put_uint16_t(buf, 8, adc5); + _mav_put_uint16_t(buf, 10, adc6); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AP_ADC, buf, 12); +#else + mavlink_ap_adc_t packet; + packet.adc1 = adc1; + packet.adc2 = adc2; + packet.adc3 = adc3; + packet.adc4 = adc4; + packet.adc5 = adc5; + packet.adc6 = adc6; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AP_ADC, (const char *)&packet, 12); +#endif +} + +#endif + +// MESSAGE AP_ADC UNPACKING + + +/** + * @brief Get field adc1 from ap_adc message + * + * @return ADC output 1 + */ +static inline uint16_t mavlink_msg_ap_adc_get_adc1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field adc2 from ap_adc message + * + * @return ADC output 2 + */ +static inline uint16_t mavlink_msg_ap_adc_get_adc2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Get field adc3 from ap_adc message + * + * @return ADC output 3 + */ +static inline uint16_t mavlink_msg_ap_adc_get_adc3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field adc4 from ap_adc message + * + * @return ADC output 4 + */ +static inline uint16_t mavlink_msg_ap_adc_get_adc4(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field adc5 from ap_adc message + * + * @return ADC output 5 + */ +static inline uint16_t mavlink_msg_ap_adc_get_adc5(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Get field adc6 from ap_adc message + * + * @return ADC output 6 + */ +static inline uint16_t mavlink_msg_ap_adc_get_adc6(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 10); +} + +/** + * @brief Decode a ap_adc message into a struct + * + * @param msg The message to decode + * @param ap_adc C-struct to decode the message contents into + */ +static inline void mavlink_msg_ap_adc_decode(const mavlink_message_t* msg, mavlink_ap_adc_t* ap_adc) +{ +#if MAVLINK_NEED_BYTE_SWAP + ap_adc->adc1 = mavlink_msg_ap_adc_get_adc1(msg); + ap_adc->adc2 = mavlink_msg_ap_adc_get_adc2(msg); + ap_adc->adc3 = mavlink_msg_ap_adc_get_adc3(msg); + ap_adc->adc4 = mavlink_msg_ap_adc_get_adc4(msg); + ap_adc->adc5 = mavlink_msg_ap_adc_get_adc5(msg); + ap_adc->adc6 = mavlink_msg_ap_adc_get_adc6(msg); +#else + memcpy(ap_adc, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_digicam_configure.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_digicam_configure.h new file mode 100644 index 0000000000..8df0a00d8b --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_digicam_configure.h @@ -0,0 +1,364 @@ +// MESSAGE DIGICAM_CONFIGURE PACKING + +#define MAVLINK_MSG_ID_DIGICAM_CONFIGURE 154 + +typedef struct __mavlink_digicam_configure_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t mode; ///< Mode enumeration from 1 to N //P, TV, AV, M, Etc (0 means ignore) + uint16_t shutter_speed; ///< Divisor number //e.g. 1000 means 1/1000 (0 means ignore) + uint8_t aperture; ///< F stop number x 10 //e.g. 28 means 2.8 (0 means ignore) + uint8_t iso; ///< ISO enumeration from 1 to N //e.g. 80, 100, 200, Etc (0 means ignore) + uint8_t exposure_type; ///< Exposure type enumeration from 1 to N (0 means ignore) + uint8_t command_id; ///< Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + uint8_t engine_cut_off; ///< Main engine cut-off time before camera trigger in seconds/10 (0 means no cut-off) + uint8_t extra_param; ///< Extra parameters enumeration (0 means ignore) + float extra_value; ///< Correspondent value to given extra_param +} mavlink_digicam_configure_t; + +#define MAVLINK_MSG_ID_DIGICAM_CONFIGURE_LEN 15 +#define MAVLINK_MSG_ID_154_LEN 15 + + + +#define MAVLINK_MESSAGE_INFO_DIGICAM_CONFIGURE { \ + "DIGICAM_CONFIGURE", \ + 11, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_digicam_configure_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_digicam_configure_t, target_component) }, \ + { "mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_digicam_configure_t, mode) }, \ + { "shutter_speed", NULL, MAVLINK_TYPE_UINT16_T, 0, 3, offsetof(mavlink_digicam_configure_t, shutter_speed) }, \ + { "aperture", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_digicam_configure_t, aperture) }, \ + { "iso", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_digicam_configure_t, iso) }, \ + { "exposure_type", NULL, MAVLINK_TYPE_UINT8_T, 0, 7, offsetof(mavlink_digicam_configure_t, exposure_type) }, \ + { "command_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_digicam_configure_t, command_id) }, \ + { "engine_cut_off", NULL, MAVLINK_TYPE_UINT8_T, 0, 9, offsetof(mavlink_digicam_configure_t, engine_cut_off) }, \ + { "extra_param", NULL, MAVLINK_TYPE_UINT8_T, 0, 10, offsetof(mavlink_digicam_configure_t, extra_param) }, \ + { "extra_value", NULL, MAVLINK_TYPE_FLOAT, 0, 11, offsetof(mavlink_digicam_configure_t, extra_value) }, \ + } \ +} + + +/** + * @brief Pack a digicam_configure message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param mode Mode enumeration from 1 to N //P, TV, AV, M, Etc (0 means ignore) + * @param shutter_speed Divisor number //e.g. 1000 means 1/1000 (0 means ignore) + * @param aperture F stop number x 10 //e.g. 28 means 2.8 (0 means ignore) + * @param iso ISO enumeration from 1 to N //e.g. 80, 100, 200, Etc (0 means ignore) + * @param exposure_type Exposure type enumeration from 1 to N (0 means ignore) + * @param command_id Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + * @param engine_cut_off Main engine cut-off time before camera trigger in seconds/10 (0 means no cut-off) + * @param extra_param Extra parameters enumeration (0 means ignore) + * @param extra_value Correspondent value to given extra_param + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_digicam_configure_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t mode, uint16_t shutter_speed, uint8_t aperture, uint8_t iso, uint8_t exposure_type, uint8_t command_id, uint8_t engine_cut_off, uint8_t extra_param, float extra_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, mode); + _mav_put_uint16_t(buf, 3, shutter_speed); + _mav_put_uint8_t(buf, 5, aperture); + _mav_put_uint8_t(buf, 6, iso); + _mav_put_uint8_t(buf, 7, exposure_type); + _mav_put_uint8_t(buf, 8, command_id); + _mav_put_uint8_t(buf, 9, engine_cut_off); + _mav_put_uint8_t(buf, 10, extra_param); + _mav_put_float(buf, 11, extra_value); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 15); +#else + mavlink_digicam_configure_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mode = mode; + packet.shutter_speed = shutter_speed; + packet.aperture = aperture; + packet.iso = iso; + packet.exposure_type = exposure_type; + packet.command_id = command_id; + packet.engine_cut_off = engine_cut_off; + packet.extra_param = extra_param; + packet.extra_value = extra_value; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 15); +#endif + + msg->msgid = MAVLINK_MSG_ID_DIGICAM_CONFIGURE; + return mavlink_finalize_message(msg, system_id, component_id, 15); +} + +/** + * @brief Pack a digicam_configure message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param mode Mode enumeration from 1 to N //P, TV, AV, M, Etc (0 means ignore) + * @param shutter_speed Divisor number //e.g. 1000 means 1/1000 (0 means ignore) + * @param aperture F stop number x 10 //e.g. 28 means 2.8 (0 means ignore) + * @param iso ISO enumeration from 1 to N //e.g. 80, 100, 200, Etc (0 means ignore) + * @param exposure_type Exposure type enumeration from 1 to N (0 means ignore) + * @param command_id Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + * @param engine_cut_off Main engine cut-off time before camera trigger in seconds/10 (0 means no cut-off) + * @param extra_param Extra parameters enumeration (0 means ignore) + * @param extra_value Correspondent value to given extra_param + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_digicam_configure_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t mode,uint16_t shutter_speed,uint8_t aperture,uint8_t iso,uint8_t exposure_type,uint8_t command_id,uint8_t engine_cut_off,uint8_t extra_param,float extra_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, mode); + _mav_put_uint16_t(buf, 3, shutter_speed); + _mav_put_uint8_t(buf, 5, aperture); + _mav_put_uint8_t(buf, 6, iso); + _mav_put_uint8_t(buf, 7, exposure_type); + _mav_put_uint8_t(buf, 8, command_id); + _mav_put_uint8_t(buf, 9, engine_cut_off); + _mav_put_uint8_t(buf, 10, extra_param); + _mav_put_float(buf, 11, extra_value); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 15); +#else + mavlink_digicam_configure_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mode = mode; + packet.shutter_speed = shutter_speed; + packet.aperture = aperture; + packet.iso = iso; + packet.exposure_type = exposure_type; + packet.command_id = command_id; + packet.engine_cut_off = engine_cut_off; + packet.extra_param = extra_param; + packet.extra_value = extra_value; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 15); +#endif + + msg->msgid = MAVLINK_MSG_ID_DIGICAM_CONFIGURE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 15); +} + +/** + * @brief Encode a digicam_configure struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param digicam_configure C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_digicam_configure_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_digicam_configure_t* digicam_configure) +{ + return mavlink_msg_digicam_configure_pack(system_id, component_id, msg, digicam_configure->target_system, digicam_configure->target_component, digicam_configure->mode, digicam_configure->shutter_speed, digicam_configure->aperture, digicam_configure->iso, digicam_configure->exposure_type, digicam_configure->command_id, digicam_configure->engine_cut_off, digicam_configure->extra_param, digicam_configure->extra_value); +} + +/** + * @brief Send a digicam_configure message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param mode Mode enumeration from 1 to N //P, TV, AV, M, Etc (0 means ignore) + * @param shutter_speed Divisor number //e.g. 1000 means 1/1000 (0 means ignore) + * @param aperture F stop number x 10 //e.g. 28 means 2.8 (0 means ignore) + * @param iso ISO enumeration from 1 to N //e.g. 80, 100, 200, Etc (0 means ignore) + * @param exposure_type Exposure type enumeration from 1 to N (0 means ignore) + * @param command_id Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + * @param engine_cut_off Main engine cut-off time before camera trigger in seconds/10 (0 means no cut-off) + * @param extra_param Extra parameters enumeration (0 means ignore) + * @param extra_value Correspondent value to given extra_param + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_digicam_configure_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t mode, uint16_t shutter_speed, uint8_t aperture, uint8_t iso, uint8_t exposure_type, uint8_t command_id, uint8_t engine_cut_off, uint8_t extra_param, float extra_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, mode); + _mav_put_uint16_t(buf, 3, shutter_speed); + _mav_put_uint8_t(buf, 5, aperture); + _mav_put_uint8_t(buf, 6, iso); + _mav_put_uint8_t(buf, 7, exposure_type); + _mav_put_uint8_t(buf, 8, command_id); + _mav_put_uint8_t(buf, 9, engine_cut_off); + _mav_put_uint8_t(buf, 10, extra_param); + _mav_put_float(buf, 11, extra_value); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DIGICAM_CONFIGURE, buf, 15); +#else + mavlink_digicam_configure_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mode = mode; + packet.shutter_speed = shutter_speed; + packet.aperture = aperture; + packet.iso = iso; + packet.exposure_type = exposure_type; + packet.command_id = command_id; + packet.engine_cut_off = engine_cut_off; + packet.extra_param = extra_param; + packet.extra_value = extra_value; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DIGICAM_CONFIGURE, (const char *)&packet, 15); +#endif +} + +#endif + +// MESSAGE DIGICAM_CONFIGURE UNPACKING + + +/** + * @brief Get field target_system from digicam_configure message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_digicam_configure_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from digicam_configure message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_digicam_configure_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field mode from digicam_configure message + * + * @return Mode enumeration from 1 to N //P, TV, AV, M, Etc (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_configure_get_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field shutter_speed from digicam_configure message + * + * @return Divisor number //e.g. 1000 means 1/1000 (0 means ignore) + */ +static inline uint16_t mavlink_msg_digicam_configure_get_shutter_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 3); +} + +/** + * @brief Get field aperture from digicam_configure message + * + * @return F stop number x 10 //e.g. 28 means 2.8 (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_configure_get_aperture(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field iso from digicam_configure message + * + * @return ISO enumeration from 1 to N //e.g. 80, 100, 200, Etc (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_configure_get_iso(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Get field exposure_type from digicam_configure message + * + * @return Exposure type enumeration from 1 to N (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_configure_get_exposure_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 7); +} + +/** + * @brief Get field command_id from digicam_configure message + * + * @return Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + */ +static inline uint8_t mavlink_msg_digicam_configure_get_command_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Get field engine_cut_off from digicam_configure message + * + * @return Main engine cut-off time before camera trigger in seconds/10 (0 means no cut-off) + */ +static inline uint8_t mavlink_msg_digicam_configure_get_engine_cut_off(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 9); +} + +/** + * @brief Get field extra_param from digicam_configure message + * + * @return Extra parameters enumeration (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_configure_get_extra_param(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 10); +} + +/** + * @brief Get field extra_value from digicam_configure message + * + * @return Correspondent value to given extra_param + */ +static inline float mavlink_msg_digicam_configure_get_extra_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 11); +} + +/** + * @brief Decode a digicam_configure message into a struct + * + * @param msg The message to decode + * @param digicam_configure C-struct to decode the message contents into + */ +static inline void mavlink_msg_digicam_configure_decode(const mavlink_message_t* msg, mavlink_digicam_configure_t* digicam_configure) +{ +#if MAVLINK_NEED_BYTE_SWAP + digicam_configure->target_system = mavlink_msg_digicam_configure_get_target_system(msg); + digicam_configure->target_component = mavlink_msg_digicam_configure_get_target_component(msg); + digicam_configure->mode = mavlink_msg_digicam_configure_get_mode(msg); + digicam_configure->shutter_speed = mavlink_msg_digicam_configure_get_shutter_speed(msg); + digicam_configure->aperture = mavlink_msg_digicam_configure_get_aperture(msg); + digicam_configure->iso = mavlink_msg_digicam_configure_get_iso(msg); + digicam_configure->exposure_type = mavlink_msg_digicam_configure_get_exposure_type(msg); + digicam_configure->command_id = mavlink_msg_digicam_configure_get_command_id(msg); + digicam_configure->engine_cut_off = mavlink_msg_digicam_configure_get_engine_cut_off(msg); + digicam_configure->extra_param = mavlink_msg_digicam_configure_get_extra_param(msg); + digicam_configure->extra_value = mavlink_msg_digicam_configure_get_extra_value(msg); +#else + memcpy(digicam_configure, _MAV_PAYLOAD(msg), 15); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_digicam_control.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_digicam_control.h new file mode 100644 index 0000000000..f0cc511de7 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_digicam_control.h @@ -0,0 +1,342 @@ +// MESSAGE DIGICAM_CONTROL PACKING + +#define MAVLINK_MSG_ID_DIGICAM_CONTROL 155 + +typedef struct __mavlink_digicam_control_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t session; ///< 0: stop, 1: start or keep it up //Session control e.g. show/hide lens + uint8_t zoom_pos; ///< 1 to N //Zoom's absolute position (0 means ignore) + int8_t zoom_step; ///< -100 to 100 //Zooming step value to offset zoom from the current position + uint8_t focus_lock; ///< 0: unlock focus or keep unlocked, 1: lock focus or keep locked, 3: re-lock focus + uint8_t shot; ///< 0: ignore, 1: shot or start filming + uint8_t command_id; ///< Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + uint8_t extra_param; ///< Extra parameters enumeration (0 means ignore) + float extra_value; ///< Correspondent value to given extra_param +} mavlink_digicam_control_t; + +#define MAVLINK_MSG_ID_DIGICAM_CONTROL_LEN 13 +#define MAVLINK_MSG_ID_155_LEN 13 + + + +#define MAVLINK_MESSAGE_INFO_DIGICAM_CONTROL { \ + "DIGICAM_CONTROL", \ + 10, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_digicam_control_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_digicam_control_t, target_component) }, \ + { "session", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_digicam_control_t, session) }, \ + { "zoom_pos", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_digicam_control_t, zoom_pos) }, \ + { "zoom_step", NULL, MAVLINK_TYPE_INT8_T, 0, 4, offsetof(mavlink_digicam_control_t, zoom_step) }, \ + { "focus_lock", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_digicam_control_t, focus_lock) }, \ + { "shot", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_digicam_control_t, shot) }, \ + { "command_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 7, offsetof(mavlink_digicam_control_t, command_id) }, \ + { "extra_param", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_digicam_control_t, extra_param) }, \ + { "extra_value", NULL, MAVLINK_TYPE_FLOAT, 0, 9, offsetof(mavlink_digicam_control_t, extra_value) }, \ + } \ +} + + +/** + * @brief Pack a digicam_control message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param session 0: stop, 1: start or keep it up //Session control e.g. show/hide lens + * @param zoom_pos 1 to N //Zoom's absolute position (0 means ignore) + * @param zoom_step -100 to 100 //Zooming step value to offset zoom from the current position + * @param focus_lock 0: unlock focus or keep unlocked, 1: lock focus or keep locked, 3: re-lock focus + * @param shot 0: ignore, 1: shot or start filming + * @param command_id Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + * @param extra_param Extra parameters enumeration (0 means ignore) + * @param extra_value Correspondent value to given extra_param + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_digicam_control_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t session, uint8_t zoom_pos, int8_t zoom_step, uint8_t focus_lock, uint8_t shot, uint8_t command_id, uint8_t extra_param, float extra_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, session); + _mav_put_uint8_t(buf, 3, zoom_pos); + _mav_put_int8_t(buf, 4, zoom_step); + _mav_put_uint8_t(buf, 5, focus_lock); + _mav_put_uint8_t(buf, 6, shot); + _mav_put_uint8_t(buf, 7, command_id); + _mav_put_uint8_t(buf, 8, extra_param); + _mav_put_float(buf, 9, extra_value); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 13); +#else + mavlink_digicam_control_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.session = session; + packet.zoom_pos = zoom_pos; + packet.zoom_step = zoom_step; + packet.focus_lock = focus_lock; + packet.shot = shot; + packet.command_id = command_id; + packet.extra_param = extra_param; + packet.extra_value = extra_value; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 13); +#endif + + msg->msgid = MAVLINK_MSG_ID_DIGICAM_CONTROL; + return mavlink_finalize_message(msg, system_id, component_id, 13); +} + +/** + * @brief Pack a digicam_control message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param session 0: stop, 1: start or keep it up //Session control e.g. show/hide lens + * @param zoom_pos 1 to N //Zoom's absolute position (0 means ignore) + * @param zoom_step -100 to 100 //Zooming step value to offset zoom from the current position + * @param focus_lock 0: unlock focus or keep unlocked, 1: lock focus or keep locked, 3: re-lock focus + * @param shot 0: ignore, 1: shot or start filming + * @param command_id Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + * @param extra_param Extra parameters enumeration (0 means ignore) + * @param extra_value Correspondent value to given extra_param + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_digicam_control_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t session,uint8_t zoom_pos,int8_t zoom_step,uint8_t focus_lock,uint8_t shot,uint8_t command_id,uint8_t extra_param,float extra_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, session); + _mav_put_uint8_t(buf, 3, zoom_pos); + _mav_put_int8_t(buf, 4, zoom_step); + _mav_put_uint8_t(buf, 5, focus_lock); + _mav_put_uint8_t(buf, 6, shot); + _mav_put_uint8_t(buf, 7, command_id); + _mav_put_uint8_t(buf, 8, extra_param); + _mav_put_float(buf, 9, extra_value); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 13); +#else + mavlink_digicam_control_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.session = session; + packet.zoom_pos = zoom_pos; + packet.zoom_step = zoom_step; + packet.focus_lock = focus_lock; + packet.shot = shot; + packet.command_id = command_id; + packet.extra_param = extra_param; + packet.extra_value = extra_value; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 13); +#endif + + msg->msgid = MAVLINK_MSG_ID_DIGICAM_CONTROL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 13); +} + +/** + * @brief Encode a digicam_control struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param digicam_control C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_digicam_control_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_digicam_control_t* digicam_control) +{ + return mavlink_msg_digicam_control_pack(system_id, component_id, msg, digicam_control->target_system, digicam_control->target_component, digicam_control->session, digicam_control->zoom_pos, digicam_control->zoom_step, digicam_control->focus_lock, digicam_control->shot, digicam_control->command_id, digicam_control->extra_param, digicam_control->extra_value); +} + +/** + * @brief Send a digicam_control message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param session 0: stop, 1: start or keep it up //Session control e.g. show/hide lens + * @param zoom_pos 1 to N //Zoom's absolute position (0 means ignore) + * @param zoom_step -100 to 100 //Zooming step value to offset zoom from the current position + * @param focus_lock 0: unlock focus or keep unlocked, 1: lock focus or keep locked, 3: re-lock focus + * @param shot 0: ignore, 1: shot or start filming + * @param command_id Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + * @param extra_param Extra parameters enumeration (0 means ignore) + * @param extra_value Correspondent value to given extra_param + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_digicam_control_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t session, uint8_t zoom_pos, int8_t zoom_step, uint8_t focus_lock, uint8_t shot, uint8_t command_id, uint8_t extra_param, float extra_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, session); + _mav_put_uint8_t(buf, 3, zoom_pos); + _mav_put_int8_t(buf, 4, zoom_step); + _mav_put_uint8_t(buf, 5, focus_lock); + _mav_put_uint8_t(buf, 6, shot); + _mav_put_uint8_t(buf, 7, command_id); + _mav_put_uint8_t(buf, 8, extra_param); + _mav_put_float(buf, 9, extra_value); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DIGICAM_CONTROL, buf, 13); +#else + mavlink_digicam_control_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.session = session; + packet.zoom_pos = zoom_pos; + packet.zoom_step = zoom_step; + packet.focus_lock = focus_lock; + packet.shot = shot; + packet.command_id = command_id; + packet.extra_param = extra_param; + packet.extra_value = extra_value; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DIGICAM_CONTROL, (const char *)&packet, 13); +#endif +} + +#endif + +// MESSAGE DIGICAM_CONTROL UNPACKING + + +/** + * @brief Get field target_system from digicam_control message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_digicam_control_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from digicam_control message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_digicam_control_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field session from digicam_control message + * + * @return 0: stop, 1: start or keep it up //Session control e.g. show/hide lens + */ +static inline uint8_t mavlink_msg_digicam_control_get_session(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field zoom_pos from digicam_control message + * + * @return 1 to N //Zoom's absolute position (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_control_get_zoom_pos(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field zoom_step from digicam_control message + * + * @return -100 to 100 //Zooming step value to offset zoom from the current position + */ +static inline int8_t mavlink_msg_digicam_control_get_zoom_step(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int8_t(msg, 4); +} + +/** + * @brief Get field focus_lock from digicam_control message + * + * @return 0: unlock focus or keep unlocked, 1: lock focus or keep locked, 3: re-lock focus + */ +static inline uint8_t mavlink_msg_digicam_control_get_focus_lock(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field shot from digicam_control message + * + * @return 0: ignore, 1: shot or start filming + */ +static inline uint8_t mavlink_msg_digicam_control_get_shot(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Get field command_id from digicam_control message + * + * @return Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + */ +static inline uint8_t mavlink_msg_digicam_control_get_command_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 7); +} + +/** + * @brief Get field extra_param from digicam_control message + * + * @return Extra parameters enumeration (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_control_get_extra_param(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Get field extra_value from digicam_control message + * + * @return Correspondent value to given extra_param + */ +static inline float mavlink_msg_digicam_control_get_extra_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 9); +} + +/** + * @brief Decode a digicam_control message into a struct + * + * @param msg The message to decode + * @param digicam_control C-struct to decode the message contents into + */ +static inline void mavlink_msg_digicam_control_decode(const mavlink_message_t* msg, mavlink_digicam_control_t* digicam_control) +{ +#if MAVLINK_NEED_BYTE_SWAP + digicam_control->target_system = mavlink_msg_digicam_control_get_target_system(msg); + digicam_control->target_component = mavlink_msg_digicam_control_get_target_component(msg); + digicam_control->session = mavlink_msg_digicam_control_get_session(msg); + digicam_control->zoom_pos = mavlink_msg_digicam_control_get_zoom_pos(msg); + digicam_control->zoom_step = mavlink_msg_digicam_control_get_zoom_step(msg); + digicam_control->focus_lock = mavlink_msg_digicam_control_get_focus_lock(msg); + digicam_control->shot = mavlink_msg_digicam_control_get_shot(msg); + digicam_control->command_id = mavlink_msg_digicam_control_get_command_id(msg); + digicam_control->extra_param = mavlink_msg_digicam_control_get_extra_param(msg); + digicam_control->extra_value = mavlink_msg_digicam_control_get_extra_value(msg); +#else + memcpy(digicam_control, _MAV_PAYLOAD(msg), 13); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_fence_fetch_point.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_fence_fetch_point.h new file mode 100644 index 0000000000..112b1ecf07 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_fence_fetch_point.h @@ -0,0 +1,188 @@ +// MESSAGE FENCE_FETCH_POINT PACKING + +#define MAVLINK_MSG_ID_FENCE_FETCH_POINT 161 + +typedef struct __mavlink_fence_fetch_point_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t idx; ///< point index (first point is 1, 0 is for return point) +} mavlink_fence_fetch_point_t; + +#define MAVLINK_MSG_ID_FENCE_FETCH_POINT_LEN 3 +#define MAVLINK_MSG_ID_161_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_FENCE_FETCH_POINT { \ + "FENCE_FETCH_POINT", \ + 3, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_fence_fetch_point_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_fence_fetch_point_t, target_component) }, \ + { "idx", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_fence_fetch_point_t, idx) }, \ + } \ +} + + +/** + * @brief Pack a fence_fetch_point message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param idx point index (first point is 1, 0 is for return point) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_fence_fetch_point_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t idx) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, idx); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_fence_fetch_point_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.idx = idx; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_FENCE_FETCH_POINT; + return mavlink_finalize_message(msg, system_id, component_id, 3); +} + +/** + * @brief Pack a fence_fetch_point message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param idx point index (first point is 1, 0 is for return point) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_fence_fetch_point_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t idx) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, idx); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_fence_fetch_point_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.idx = idx; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_FENCE_FETCH_POINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3); +} + +/** + * @brief Encode a fence_fetch_point struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param fence_fetch_point C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_fence_fetch_point_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_fence_fetch_point_t* fence_fetch_point) +{ + return mavlink_msg_fence_fetch_point_pack(system_id, component_id, msg, fence_fetch_point->target_system, fence_fetch_point->target_component, fence_fetch_point->idx); +} + +/** + * @brief Send a fence_fetch_point message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param idx point index (first point is 1, 0 is for return point) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_fence_fetch_point_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t idx) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, idx); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FENCE_FETCH_POINT, buf, 3); +#else + mavlink_fence_fetch_point_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.idx = idx; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FENCE_FETCH_POINT, (const char *)&packet, 3); +#endif +} + +#endif + +// MESSAGE FENCE_FETCH_POINT UNPACKING + + +/** + * @brief Get field target_system from fence_fetch_point message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_fence_fetch_point_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from fence_fetch_point message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_fence_fetch_point_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field idx from fence_fetch_point message + * + * @return point index (first point is 1, 0 is for return point) + */ +static inline uint8_t mavlink_msg_fence_fetch_point_get_idx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a fence_fetch_point message into a struct + * + * @param msg The message to decode + * @param fence_fetch_point C-struct to decode the message contents into + */ +static inline void mavlink_msg_fence_fetch_point_decode(const mavlink_message_t* msg, mavlink_fence_fetch_point_t* fence_fetch_point) +{ +#if MAVLINK_NEED_BYTE_SWAP + fence_fetch_point->target_system = mavlink_msg_fence_fetch_point_get_target_system(msg); + fence_fetch_point->target_component = mavlink_msg_fence_fetch_point_get_target_component(msg); + fence_fetch_point->idx = mavlink_msg_fence_fetch_point_get_idx(msg); +#else + memcpy(fence_fetch_point, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_fence_point.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_fence_point.h new file mode 100644 index 0000000000..b46b259f44 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_fence_point.h @@ -0,0 +1,254 @@ +// MESSAGE FENCE_POINT PACKING + +#define MAVLINK_MSG_ID_FENCE_POINT 160 + +typedef struct __mavlink_fence_point_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t idx; ///< point index (first point is 1, 0 is for return point) + uint8_t count; ///< total number of points (for sanity checking) + float lat; ///< Latitude of point + float lng; ///< Longitude of point +} mavlink_fence_point_t; + +#define MAVLINK_MSG_ID_FENCE_POINT_LEN 12 +#define MAVLINK_MSG_ID_160_LEN 12 + + + +#define MAVLINK_MESSAGE_INFO_FENCE_POINT { \ + "FENCE_POINT", \ + 6, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_fence_point_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_fence_point_t, target_component) }, \ + { "idx", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_fence_point_t, idx) }, \ + { "count", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_fence_point_t, count) }, \ + { "lat", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_fence_point_t, lat) }, \ + { "lng", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_fence_point_t, lng) }, \ + } \ +} + + +/** + * @brief Pack a fence_point message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param idx point index (first point is 1, 0 is for return point) + * @param count total number of points (for sanity checking) + * @param lat Latitude of point + * @param lng Longitude of point + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_fence_point_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t idx, uint8_t count, float lat, float lng) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, idx); + _mav_put_uint8_t(buf, 3, count); + _mav_put_float(buf, 4, lat); + _mav_put_float(buf, 8, lng); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_fence_point_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.idx = idx; + packet.count = count; + packet.lat = lat; + packet.lng = lng; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_FENCE_POINT; + return mavlink_finalize_message(msg, system_id, component_id, 12); +} + +/** + * @brief Pack a fence_point message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param idx point index (first point is 1, 0 is for return point) + * @param count total number of points (for sanity checking) + * @param lat Latitude of point + * @param lng Longitude of point + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_fence_point_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t idx,uint8_t count,float lat,float lng) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, idx); + _mav_put_uint8_t(buf, 3, count); + _mav_put_float(buf, 4, lat); + _mav_put_float(buf, 8, lng); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_fence_point_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.idx = idx; + packet.count = count; + packet.lat = lat; + packet.lng = lng; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_FENCE_POINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12); +} + +/** + * @brief Encode a fence_point struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param fence_point C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_fence_point_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_fence_point_t* fence_point) +{ + return mavlink_msg_fence_point_pack(system_id, component_id, msg, fence_point->target_system, fence_point->target_component, fence_point->idx, fence_point->count, fence_point->lat, fence_point->lng); +} + +/** + * @brief Send a fence_point message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param idx point index (first point is 1, 0 is for return point) + * @param count total number of points (for sanity checking) + * @param lat Latitude of point + * @param lng Longitude of point + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_fence_point_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t idx, uint8_t count, float lat, float lng) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, idx); + _mav_put_uint8_t(buf, 3, count); + _mav_put_float(buf, 4, lat); + _mav_put_float(buf, 8, lng); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FENCE_POINT, buf, 12); +#else + mavlink_fence_point_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.idx = idx; + packet.count = count; + packet.lat = lat; + packet.lng = lng; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FENCE_POINT, (const char *)&packet, 12); +#endif +} + +#endif + +// MESSAGE FENCE_POINT UNPACKING + + +/** + * @brief Get field target_system from fence_point message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_fence_point_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from fence_point message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_fence_point_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field idx from fence_point message + * + * @return point index (first point is 1, 0 is for return point) + */ +static inline uint8_t mavlink_msg_fence_point_get_idx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field count from fence_point message + * + * @return total number of points (for sanity checking) + */ +static inline uint8_t mavlink_msg_fence_point_get_count(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field lat from fence_point message + * + * @return Latitude of point + */ +static inline float mavlink_msg_fence_point_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field lng from fence_point message + * + * @return Longitude of point + */ +static inline float mavlink_msg_fence_point_get_lng(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Decode a fence_point message into a struct + * + * @param msg The message to decode + * @param fence_point C-struct to decode the message contents into + */ +static inline void mavlink_msg_fence_point_decode(const mavlink_message_t* msg, mavlink_fence_point_t* fence_point) +{ +#if MAVLINK_NEED_BYTE_SWAP + fence_point->target_system = mavlink_msg_fence_point_get_target_system(msg); + fence_point->target_component = mavlink_msg_fence_point_get_target_component(msg); + fence_point->idx = mavlink_msg_fence_point_get_idx(msg); + fence_point->count = mavlink_msg_fence_point_get_count(msg); + fence_point->lat = mavlink_msg_fence_point_get_lat(msg); + fence_point->lng = mavlink_msg_fence_point_get_lng(msg); +#else + memcpy(fence_point, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_fence_status.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_fence_status.h new file mode 100644 index 0000000000..77b3e56310 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_fence_status.h @@ -0,0 +1,210 @@ +// MESSAGE FENCE_STATUS PACKING + +#define MAVLINK_MSG_ID_FENCE_STATUS 162 + +typedef struct __mavlink_fence_status_t +{ + uint8_t breach_status; ///< 0 if currently inside fence, 1 if outside + uint16_t breach_count; ///< number of fence breaches + uint8_t breach_type; ///< last breach type (see FENCE_BREACH_* enum) + uint32_t breach_time; ///< time of last breach in milliseconds since boot +} mavlink_fence_status_t; + +#define MAVLINK_MSG_ID_FENCE_STATUS_LEN 8 +#define MAVLINK_MSG_ID_162_LEN 8 + + + +#define MAVLINK_MESSAGE_INFO_FENCE_STATUS { \ + "FENCE_STATUS", \ + 4, \ + { { "breach_status", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_fence_status_t, breach_status) }, \ + { "breach_count", NULL, MAVLINK_TYPE_UINT16_T, 0, 1, offsetof(mavlink_fence_status_t, breach_count) }, \ + { "breach_type", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_fence_status_t, breach_type) }, \ + { "breach_time", NULL, MAVLINK_TYPE_UINT32_T, 0, 4, offsetof(mavlink_fence_status_t, breach_time) }, \ + } \ +} + + +/** + * @brief Pack a fence_status message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param breach_status 0 if currently inside fence, 1 if outside + * @param breach_count number of fence breaches + * @param breach_type last breach type (see FENCE_BREACH_* enum) + * @param breach_time time of last breach in milliseconds since boot + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_fence_status_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t breach_status, uint16_t breach_count, uint8_t breach_type, uint32_t breach_time) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint8_t(buf, 0, breach_status); + _mav_put_uint16_t(buf, 1, breach_count); + _mav_put_uint8_t(buf, 3, breach_type); + _mav_put_uint32_t(buf, 4, breach_time); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_fence_status_t packet; + packet.breach_status = breach_status; + packet.breach_count = breach_count; + packet.breach_type = breach_type; + packet.breach_time = breach_time; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_FENCE_STATUS; + return mavlink_finalize_message(msg, system_id, component_id, 8); +} + +/** + * @brief Pack a fence_status message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param breach_status 0 if currently inside fence, 1 if outside + * @param breach_count number of fence breaches + * @param breach_type last breach type (see FENCE_BREACH_* enum) + * @param breach_time time of last breach in milliseconds since boot + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_fence_status_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t breach_status,uint16_t breach_count,uint8_t breach_type,uint32_t breach_time) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint8_t(buf, 0, breach_status); + _mav_put_uint16_t(buf, 1, breach_count); + _mav_put_uint8_t(buf, 3, breach_type); + _mav_put_uint32_t(buf, 4, breach_time); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_fence_status_t packet; + packet.breach_status = breach_status; + packet.breach_count = breach_count; + packet.breach_type = breach_type; + packet.breach_time = breach_time; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_FENCE_STATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 8); +} + +/** + * @brief Encode a fence_status struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param fence_status C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_fence_status_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_fence_status_t* fence_status) +{ + return mavlink_msg_fence_status_pack(system_id, component_id, msg, fence_status->breach_status, fence_status->breach_count, fence_status->breach_type, fence_status->breach_time); +} + +/** + * @brief Send a fence_status message + * @param chan MAVLink channel to send the message + * + * @param breach_status 0 if currently inside fence, 1 if outside + * @param breach_count number of fence breaches + * @param breach_type last breach type (see FENCE_BREACH_* enum) + * @param breach_time time of last breach in milliseconds since boot + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_fence_status_send(mavlink_channel_t chan, uint8_t breach_status, uint16_t breach_count, uint8_t breach_type, uint32_t breach_time) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint8_t(buf, 0, breach_status); + _mav_put_uint16_t(buf, 1, breach_count); + _mav_put_uint8_t(buf, 3, breach_type); + _mav_put_uint32_t(buf, 4, breach_time); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FENCE_STATUS, buf, 8); +#else + mavlink_fence_status_t packet; + packet.breach_status = breach_status; + packet.breach_count = breach_count; + packet.breach_type = breach_type; + packet.breach_time = breach_time; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FENCE_STATUS, (const char *)&packet, 8); +#endif +} + +#endif + +// MESSAGE FENCE_STATUS UNPACKING + + +/** + * @brief Get field breach_status from fence_status message + * + * @return 0 if currently inside fence, 1 if outside + */ +static inline uint8_t mavlink_msg_fence_status_get_breach_status(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field breach_count from fence_status message + * + * @return number of fence breaches + */ +static inline uint16_t mavlink_msg_fence_status_get_breach_count(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 1); +} + +/** + * @brief Get field breach_type from fence_status message + * + * @return last breach type (see FENCE_BREACH_* enum) + */ +static inline uint8_t mavlink_msg_fence_status_get_breach_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field breach_time from fence_status message + * + * @return time of last breach in milliseconds since boot + */ +static inline uint32_t mavlink_msg_fence_status_get_breach_time(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 4); +} + +/** + * @brief Decode a fence_status message into a struct + * + * @param msg The message to decode + * @param fence_status C-struct to decode the message contents into + */ +static inline void mavlink_msg_fence_status_decode(const mavlink_message_t* msg, mavlink_fence_status_t* fence_status) +{ +#if MAVLINK_NEED_BYTE_SWAP + fence_status->breach_status = mavlink_msg_fence_status_get_breach_status(msg); + fence_status->breach_count = mavlink_msg_fence_status_get_breach_count(msg); + fence_status->breach_type = mavlink_msg_fence_status_get_breach_type(msg); + fence_status->breach_time = mavlink_msg_fence_status_get_breach_time(msg); +#else + memcpy(fence_status, _MAV_PAYLOAD(msg), 8); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_hwstatus.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_hwstatus.h new file mode 100644 index 0000000000..47cc21484a --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_hwstatus.h @@ -0,0 +1,166 @@ +// MESSAGE HWSTATUS PACKING + +#define MAVLINK_MSG_ID_HWSTATUS 165 + +typedef struct __mavlink_hwstatus_t +{ + uint16_t Vcc; ///< board voltage (mV) + uint8_t I2Cerr; ///< I2C error count +} mavlink_hwstatus_t; + +#define MAVLINK_MSG_ID_HWSTATUS_LEN 3 +#define MAVLINK_MSG_ID_165_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_HWSTATUS { \ + "HWSTATUS", \ + 2, \ + { { "Vcc", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_hwstatus_t, Vcc) }, \ + { "I2Cerr", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_hwstatus_t, I2Cerr) }, \ + } \ +} + + +/** + * @brief Pack a hwstatus message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param Vcc board voltage (mV) + * @param I2Cerr I2C error count + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hwstatus_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t Vcc, uint8_t I2Cerr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, Vcc); + _mav_put_uint8_t(buf, 2, I2Cerr); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_hwstatus_t packet; + packet.Vcc = Vcc; + packet.I2Cerr = I2Cerr; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_HWSTATUS; + return mavlink_finalize_message(msg, system_id, component_id, 3); +} + +/** + * @brief Pack a hwstatus message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param Vcc board voltage (mV) + * @param I2Cerr I2C error count + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hwstatus_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t Vcc,uint8_t I2Cerr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, Vcc); + _mav_put_uint8_t(buf, 2, I2Cerr); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_hwstatus_t packet; + packet.Vcc = Vcc; + packet.I2Cerr = I2Cerr; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_HWSTATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3); +} + +/** + * @brief Encode a hwstatus struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param hwstatus C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_hwstatus_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_hwstatus_t* hwstatus) +{ + return mavlink_msg_hwstatus_pack(system_id, component_id, msg, hwstatus->Vcc, hwstatus->I2Cerr); +} + +/** + * @brief Send a hwstatus message + * @param chan MAVLink channel to send the message + * + * @param Vcc board voltage (mV) + * @param I2Cerr I2C error count + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_hwstatus_send(mavlink_channel_t chan, uint16_t Vcc, uint8_t I2Cerr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, Vcc); + _mav_put_uint8_t(buf, 2, I2Cerr); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HWSTATUS, buf, 3); +#else + mavlink_hwstatus_t packet; + packet.Vcc = Vcc; + packet.I2Cerr = I2Cerr; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HWSTATUS, (const char *)&packet, 3); +#endif +} + +#endif + +// MESSAGE HWSTATUS UNPACKING + + +/** + * @brief Get field Vcc from hwstatus message + * + * @return board voltage (mV) + */ +static inline uint16_t mavlink_msg_hwstatus_get_Vcc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field I2Cerr from hwstatus message + * + * @return I2C error count + */ +static inline uint8_t mavlink_msg_hwstatus_get_I2Cerr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a hwstatus message into a struct + * + * @param msg The message to decode + * @param hwstatus C-struct to decode the message contents into + */ +static inline void mavlink_msg_hwstatus_decode(const mavlink_message_t* msg, mavlink_hwstatus_t* hwstatus) +{ +#if MAVLINK_NEED_BYTE_SWAP + hwstatus->Vcc = mavlink_msg_hwstatus_get_Vcc(msg); + hwstatus->I2Cerr = mavlink_msg_hwstatus_get_I2Cerr(msg); +#else + memcpy(hwstatus, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_meminfo.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_meminfo.h new file mode 100644 index 0000000000..e9efa5da22 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_meminfo.h @@ -0,0 +1,166 @@ +// MESSAGE MEMINFO PACKING + +#define MAVLINK_MSG_ID_MEMINFO 152 + +typedef struct __mavlink_meminfo_t +{ + uint16_t brkval; ///< heap top + uint16_t freemem; ///< free memory +} mavlink_meminfo_t; + +#define MAVLINK_MSG_ID_MEMINFO_LEN 4 +#define MAVLINK_MSG_ID_152_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_MEMINFO { \ + "MEMINFO", \ + 2, \ + { { "brkval", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_meminfo_t, brkval) }, \ + { "freemem", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_meminfo_t, freemem) }, \ + } \ +} + + +/** + * @brief Pack a meminfo message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param brkval heap top + * @param freemem free memory + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_meminfo_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t brkval, uint16_t freemem) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, brkval); + _mav_put_uint16_t(buf, 2, freemem); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_meminfo_t packet; + packet.brkval = brkval; + packet.freemem = freemem; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_MEMINFO; + return mavlink_finalize_message(msg, system_id, component_id, 4); +} + +/** + * @brief Pack a meminfo message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param brkval heap top + * @param freemem free memory + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_meminfo_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t brkval,uint16_t freemem) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, brkval); + _mav_put_uint16_t(buf, 2, freemem); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_meminfo_t packet; + packet.brkval = brkval; + packet.freemem = freemem; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_MEMINFO; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4); +} + +/** + * @brief Encode a meminfo struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param meminfo C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_meminfo_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_meminfo_t* meminfo) +{ + return mavlink_msg_meminfo_pack(system_id, component_id, msg, meminfo->brkval, meminfo->freemem); +} + +/** + * @brief Send a meminfo message + * @param chan MAVLink channel to send the message + * + * @param brkval heap top + * @param freemem free memory + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_meminfo_send(mavlink_channel_t chan, uint16_t brkval, uint16_t freemem) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, brkval); + _mav_put_uint16_t(buf, 2, freemem); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MEMINFO, buf, 4); +#else + mavlink_meminfo_t packet; + packet.brkval = brkval; + packet.freemem = freemem; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MEMINFO, (const char *)&packet, 4); +#endif +} + +#endif + +// MESSAGE MEMINFO UNPACKING + + +/** + * @brief Get field brkval from meminfo message + * + * @return heap top + */ +static inline uint16_t mavlink_msg_meminfo_get_brkval(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field freemem from meminfo message + * + * @return free memory + */ +static inline uint16_t mavlink_msg_meminfo_get_freemem(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Decode a meminfo message into a struct + * + * @param msg The message to decode + * @param meminfo C-struct to decode the message contents into + */ +static inline void mavlink_msg_meminfo_decode(const mavlink_message_t* msg, mavlink_meminfo_t* meminfo) +{ +#if MAVLINK_NEED_BYTE_SWAP + meminfo->brkval = mavlink_msg_meminfo_get_brkval(msg); + meminfo->freemem = mavlink_msg_meminfo_get_freemem(msg); +#else + memcpy(meminfo, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_mount_configure.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_mount_configure.h new file mode 100644 index 0000000000..688d89415a --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_mount_configure.h @@ -0,0 +1,254 @@ +// MESSAGE MOUNT_CONFIGURE PACKING + +#define MAVLINK_MSG_ID_MOUNT_CONFIGURE 156 + +typedef struct __mavlink_mount_configure_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t mount_mode; ///< mount operating mode (see MAV_MOUNT_MODE enum) + uint8_t stab_roll; ///< (1 = yes, 0 = no) + uint8_t stab_pitch; ///< (1 = yes, 0 = no) + uint8_t stab_yaw; ///< (1 = yes, 0 = no) +} mavlink_mount_configure_t; + +#define MAVLINK_MSG_ID_MOUNT_CONFIGURE_LEN 6 +#define MAVLINK_MSG_ID_156_LEN 6 + + + +#define MAVLINK_MESSAGE_INFO_MOUNT_CONFIGURE { \ + "MOUNT_CONFIGURE", \ + 6, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_mount_configure_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_mount_configure_t, target_component) }, \ + { "mount_mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_mount_configure_t, mount_mode) }, \ + { "stab_roll", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_mount_configure_t, stab_roll) }, \ + { "stab_pitch", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_mount_configure_t, stab_pitch) }, \ + { "stab_yaw", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_mount_configure_t, stab_yaw) }, \ + } \ +} + + +/** + * @brief Pack a mount_configure message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param mount_mode mount operating mode (see MAV_MOUNT_MODE enum) + * @param stab_roll (1 = yes, 0 = no) + * @param stab_pitch (1 = yes, 0 = no) + * @param stab_yaw (1 = yes, 0 = no) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mount_configure_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t mount_mode, uint8_t stab_roll, uint8_t stab_pitch, uint8_t stab_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, mount_mode); + _mav_put_uint8_t(buf, 3, stab_roll); + _mav_put_uint8_t(buf, 4, stab_pitch); + _mav_put_uint8_t(buf, 5, stab_yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_mount_configure_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mount_mode = mount_mode; + packet.stab_roll = stab_roll; + packet.stab_pitch = stab_pitch; + packet.stab_yaw = stab_yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_MOUNT_CONFIGURE; + return mavlink_finalize_message(msg, system_id, component_id, 6); +} + +/** + * @brief Pack a mount_configure message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param mount_mode mount operating mode (see MAV_MOUNT_MODE enum) + * @param stab_roll (1 = yes, 0 = no) + * @param stab_pitch (1 = yes, 0 = no) + * @param stab_yaw (1 = yes, 0 = no) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mount_configure_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t mount_mode,uint8_t stab_roll,uint8_t stab_pitch,uint8_t stab_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, mount_mode); + _mav_put_uint8_t(buf, 3, stab_roll); + _mav_put_uint8_t(buf, 4, stab_pitch); + _mav_put_uint8_t(buf, 5, stab_yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_mount_configure_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mount_mode = mount_mode; + packet.stab_roll = stab_roll; + packet.stab_pitch = stab_pitch; + packet.stab_yaw = stab_yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_MOUNT_CONFIGURE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 6); +} + +/** + * @brief Encode a mount_configure struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mount_configure C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mount_configure_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mount_configure_t* mount_configure) +{ + return mavlink_msg_mount_configure_pack(system_id, component_id, msg, mount_configure->target_system, mount_configure->target_component, mount_configure->mount_mode, mount_configure->stab_roll, mount_configure->stab_pitch, mount_configure->stab_yaw); +} + +/** + * @brief Send a mount_configure message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param mount_mode mount operating mode (see MAV_MOUNT_MODE enum) + * @param stab_roll (1 = yes, 0 = no) + * @param stab_pitch (1 = yes, 0 = no) + * @param stab_yaw (1 = yes, 0 = no) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mount_configure_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t mount_mode, uint8_t stab_roll, uint8_t stab_pitch, uint8_t stab_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, mount_mode); + _mav_put_uint8_t(buf, 3, stab_roll); + _mav_put_uint8_t(buf, 4, stab_pitch); + _mav_put_uint8_t(buf, 5, stab_yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MOUNT_CONFIGURE, buf, 6); +#else + mavlink_mount_configure_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mount_mode = mount_mode; + packet.stab_roll = stab_roll; + packet.stab_pitch = stab_pitch; + packet.stab_yaw = stab_yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MOUNT_CONFIGURE, (const char *)&packet, 6); +#endif +} + +#endif + +// MESSAGE MOUNT_CONFIGURE UNPACKING + + +/** + * @brief Get field target_system from mount_configure message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mount_configure_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from mount_configure message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mount_configure_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field mount_mode from mount_configure message + * + * @return mount operating mode (see MAV_MOUNT_MODE enum) + */ +static inline uint8_t mavlink_msg_mount_configure_get_mount_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field stab_roll from mount_configure message + * + * @return (1 = yes, 0 = no) + */ +static inline uint8_t mavlink_msg_mount_configure_get_stab_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field stab_pitch from mount_configure message + * + * @return (1 = yes, 0 = no) + */ +static inline uint8_t mavlink_msg_mount_configure_get_stab_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field stab_yaw from mount_configure message + * + * @return (1 = yes, 0 = no) + */ +static inline uint8_t mavlink_msg_mount_configure_get_stab_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Decode a mount_configure message into a struct + * + * @param msg The message to decode + * @param mount_configure C-struct to decode the message contents into + */ +static inline void mavlink_msg_mount_configure_decode(const mavlink_message_t* msg, mavlink_mount_configure_t* mount_configure) +{ +#if MAVLINK_NEED_BYTE_SWAP + mount_configure->target_system = mavlink_msg_mount_configure_get_target_system(msg); + mount_configure->target_component = mavlink_msg_mount_configure_get_target_component(msg); + mount_configure->mount_mode = mavlink_msg_mount_configure_get_mount_mode(msg); + mount_configure->stab_roll = mavlink_msg_mount_configure_get_stab_roll(msg); + mount_configure->stab_pitch = mavlink_msg_mount_configure_get_stab_pitch(msg); + mount_configure->stab_yaw = mavlink_msg_mount_configure_get_stab_yaw(msg); +#else + memcpy(mount_configure, _MAV_PAYLOAD(msg), 6); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_mount_control.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_mount_control.h new file mode 100644 index 0000000000..f13bea2d9f --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_mount_control.h @@ -0,0 +1,254 @@ +// MESSAGE MOUNT_CONTROL PACKING + +#define MAVLINK_MSG_ID_MOUNT_CONTROL 157 + +typedef struct __mavlink_mount_control_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + int32_t input_a; ///< pitch(deg*100) or lat, depending on mount mode + int32_t input_b; ///< roll(deg*100) or lon depending on mount mode + int32_t input_c; ///< yaw(deg*100) or alt (in cm) depending on mount mode + uint8_t save_position; ///< if "1" it will save current trimmed position on EEPROM (just valid for NEUTRAL and LANDING) +} mavlink_mount_control_t; + +#define MAVLINK_MSG_ID_MOUNT_CONTROL_LEN 15 +#define MAVLINK_MSG_ID_157_LEN 15 + + + +#define MAVLINK_MESSAGE_INFO_MOUNT_CONTROL { \ + "MOUNT_CONTROL", \ + 6, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_mount_control_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_mount_control_t, target_component) }, \ + { "input_a", NULL, MAVLINK_TYPE_INT32_T, 0, 2, offsetof(mavlink_mount_control_t, input_a) }, \ + { "input_b", NULL, MAVLINK_TYPE_INT32_T, 0, 6, offsetof(mavlink_mount_control_t, input_b) }, \ + { "input_c", NULL, MAVLINK_TYPE_INT32_T, 0, 10, offsetof(mavlink_mount_control_t, input_c) }, \ + { "save_position", NULL, MAVLINK_TYPE_UINT8_T, 0, 14, offsetof(mavlink_mount_control_t, save_position) }, \ + } \ +} + + +/** + * @brief Pack a mount_control message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param input_a pitch(deg*100) or lat, depending on mount mode + * @param input_b roll(deg*100) or lon depending on mount mode + * @param input_c yaw(deg*100) or alt (in cm) depending on mount mode + * @param save_position if "1" it will save current trimmed position on EEPROM (just valid for NEUTRAL and LANDING) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mount_control_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, int32_t input_a, int32_t input_b, int32_t input_c, uint8_t save_position) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int32_t(buf, 2, input_a); + _mav_put_int32_t(buf, 6, input_b); + _mav_put_int32_t(buf, 10, input_c); + _mav_put_uint8_t(buf, 14, save_position); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 15); +#else + mavlink_mount_control_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.input_a = input_a; + packet.input_b = input_b; + packet.input_c = input_c; + packet.save_position = save_position; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 15); +#endif + + msg->msgid = MAVLINK_MSG_ID_MOUNT_CONTROL; + return mavlink_finalize_message(msg, system_id, component_id, 15); +} + +/** + * @brief Pack a mount_control message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param input_a pitch(deg*100) or lat, depending on mount mode + * @param input_b roll(deg*100) or lon depending on mount mode + * @param input_c yaw(deg*100) or alt (in cm) depending on mount mode + * @param save_position if "1" it will save current trimmed position on EEPROM (just valid for NEUTRAL and LANDING) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mount_control_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,int32_t input_a,int32_t input_b,int32_t input_c,uint8_t save_position) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int32_t(buf, 2, input_a); + _mav_put_int32_t(buf, 6, input_b); + _mav_put_int32_t(buf, 10, input_c); + _mav_put_uint8_t(buf, 14, save_position); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 15); +#else + mavlink_mount_control_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.input_a = input_a; + packet.input_b = input_b; + packet.input_c = input_c; + packet.save_position = save_position; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 15); +#endif + + msg->msgid = MAVLINK_MSG_ID_MOUNT_CONTROL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 15); +} + +/** + * @brief Encode a mount_control struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mount_control C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mount_control_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mount_control_t* mount_control) +{ + return mavlink_msg_mount_control_pack(system_id, component_id, msg, mount_control->target_system, mount_control->target_component, mount_control->input_a, mount_control->input_b, mount_control->input_c, mount_control->save_position); +} + +/** + * @brief Send a mount_control message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param input_a pitch(deg*100) or lat, depending on mount mode + * @param input_b roll(deg*100) or lon depending on mount mode + * @param input_c yaw(deg*100) or alt (in cm) depending on mount mode + * @param save_position if "1" it will save current trimmed position on EEPROM (just valid for NEUTRAL and LANDING) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mount_control_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, int32_t input_a, int32_t input_b, int32_t input_c, uint8_t save_position) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int32_t(buf, 2, input_a); + _mav_put_int32_t(buf, 6, input_b); + _mav_put_int32_t(buf, 10, input_c); + _mav_put_uint8_t(buf, 14, save_position); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MOUNT_CONTROL, buf, 15); +#else + mavlink_mount_control_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.input_a = input_a; + packet.input_b = input_b; + packet.input_c = input_c; + packet.save_position = save_position; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MOUNT_CONTROL, (const char *)&packet, 15); +#endif +} + +#endif + +// MESSAGE MOUNT_CONTROL UNPACKING + + +/** + * @brief Get field target_system from mount_control message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mount_control_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from mount_control message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mount_control_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field input_a from mount_control message + * + * @return pitch(deg*100) or lat, depending on mount mode + */ +static inline int32_t mavlink_msg_mount_control_get_input_a(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 2); +} + +/** + * @brief Get field input_b from mount_control message + * + * @return roll(deg*100) or lon depending on mount mode + */ +static inline int32_t mavlink_msg_mount_control_get_input_b(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 6); +} + +/** + * @brief Get field input_c from mount_control message + * + * @return yaw(deg*100) or alt (in cm) depending on mount mode + */ +static inline int32_t mavlink_msg_mount_control_get_input_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 10); +} + +/** + * @brief Get field save_position from mount_control message + * + * @return if "1" it will save current trimmed position on EEPROM (just valid for NEUTRAL and LANDING) + */ +static inline uint8_t mavlink_msg_mount_control_get_save_position(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 14); +} + +/** + * @brief Decode a mount_control message into a struct + * + * @param msg The message to decode + * @param mount_control C-struct to decode the message contents into + */ +static inline void mavlink_msg_mount_control_decode(const mavlink_message_t* msg, mavlink_mount_control_t* mount_control) +{ +#if MAVLINK_NEED_BYTE_SWAP + mount_control->target_system = mavlink_msg_mount_control_get_target_system(msg); + mount_control->target_component = mavlink_msg_mount_control_get_target_component(msg); + mount_control->input_a = mavlink_msg_mount_control_get_input_a(msg); + mount_control->input_b = mavlink_msg_mount_control_get_input_b(msg); + mount_control->input_c = mavlink_msg_mount_control_get_input_c(msg); + mount_control->save_position = mavlink_msg_mount_control_get_save_position(msg); +#else + memcpy(mount_control, _MAV_PAYLOAD(msg), 15); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_mount_status.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_mount_status.h new file mode 100644 index 0000000000..75a44321ec --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_mount_status.h @@ -0,0 +1,232 @@ +// MESSAGE MOUNT_STATUS PACKING + +#define MAVLINK_MSG_ID_MOUNT_STATUS 158 + +typedef struct __mavlink_mount_status_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + int32_t pointing_a; ///< pitch(deg*100) or lat, depending on mount mode + int32_t pointing_b; ///< roll(deg*100) or lon depending on mount mode + int32_t pointing_c; ///< yaw(deg*100) or alt (in cm) depending on mount mode +} mavlink_mount_status_t; + +#define MAVLINK_MSG_ID_MOUNT_STATUS_LEN 14 +#define MAVLINK_MSG_ID_158_LEN 14 + + + +#define MAVLINK_MESSAGE_INFO_MOUNT_STATUS { \ + "MOUNT_STATUS", \ + 5, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_mount_status_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_mount_status_t, target_component) }, \ + { "pointing_a", NULL, MAVLINK_TYPE_INT32_T, 0, 2, offsetof(mavlink_mount_status_t, pointing_a) }, \ + { "pointing_b", NULL, MAVLINK_TYPE_INT32_T, 0, 6, offsetof(mavlink_mount_status_t, pointing_b) }, \ + { "pointing_c", NULL, MAVLINK_TYPE_INT32_T, 0, 10, offsetof(mavlink_mount_status_t, pointing_c) }, \ + } \ +} + + +/** + * @brief Pack a mount_status message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param pointing_a pitch(deg*100) or lat, depending on mount mode + * @param pointing_b roll(deg*100) or lon depending on mount mode + * @param pointing_c yaw(deg*100) or alt (in cm) depending on mount mode + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mount_status_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, int32_t pointing_a, int32_t pointing_b, int32_t pointing_c) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int32_t(buf, 2, pointing_a); + _mav_put_int32_t(buf, 6, pointing_b); + _mav_put_int32_t(buf, 10, pointing_c); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_mount_status_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.pointing_a = pointing_a; + packet.pointing_b = pointing_b; + packet.pointing_c = pointing_c; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_MOUNT_STATUS; + return mavlink_finalize_message(msg, system_id, component_id, 14); +} + +/** + * @brief Pack a mount_status message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param pointing_a pitch(deg*100) or lat, depending on mount mode + * @param pointing_b roll(deg*100) or lon depending on mount mode + * @param pointing_c yaw(deg*100) or alt (in cm) depending on mount mode + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mount_status_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,int32_t pointing_a,int32_t pointing_b,int32_t pointing_c) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int32_t(buf, 2, pointing_a); + _mav_put_int32_t(buf, 6, pointing_b); + _mav_put_int32_t(buf, 10, pointing_c); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_mount_status_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.pointing_a = pointing_a; + packet.pointing_b = pointing_b; + packet.pointing_c = pointing_c; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_MOUNT_STATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 14); +} + +/** + * @brief Encode a mount_status struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mount_status C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mount_status_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mount_status_t* mount_status) +{ + return mavlink_msg_mount_status_pack(system_id, component_id, msg, mount_status->target_system, mount_status->target_component, mount_status->pointing_a, mount_status->pointing_b, mount_status->pointing_c); +} + +/** + * @brief Send a mount_status message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param pointing_a pitch(deg*100) or lat, depending on mount mode + * @param pointing_b roll(deg*100) or lon depending on mount mode + * @param pointing_c yaw(deg*100) or alt (in cm) depending on mount mode + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mount_status_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, int32_t pointing_a, int32_t pointing_b, int32_t pointing_c) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int32_t(buf, 2, pointing_a); + _mav_put_int32_t(buf, 6, pointing_b); + _mav_put_int32_t(buf, 10, pointing_c); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MOUNT_STATUS, buf, 14); +#else + mavlink_mount_status_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.pointing_a = pointing_a; + packet.pointing_b = pointing_b; + packet.pointing_c = pointing_c; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MOUNT_STATUS, (const char *)&packet, 14); +#endif +} + +#endif + +// MESSAGE MOUNT_STATUS UNPACKING + + +/** + * @brief Get field target_system from mount_status message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mount_status_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from mount_status message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mount_status_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field pointing_a from mount_status message + * + * @return pitch(deg*100) or lat, depending on mount mode + */ +static inline int32_t mavlink_msg_mount_status_get_pointing_a(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 2); +} + +/** + * @brief Get field pointing_b from mount_status message + * + * @return roll(deg*100) or lon depending on mount mode + */ +static inline int32_t mavlink_msg_mount_status_get_pointing_b(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 6); +} + +/** + * @brief Get field pointing_c from mount_status message + * + * @return yaw(deg*100) or alt (in cm) depending on mount mode + */ +static inline int32_t mavlink_msg_mount_status_get_pointing_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 10); +} + +/** + * @brief Decode a mount_status message into a struct + * + * @param msg The message to decode + * @param mount_status C-struct to decode the message contents into + */ +static inline void mavlink_msg_mount_status_decode(const mavlink_message_t* msg, mavlink_mount_status_t* mount_status) +{ +#if MAVLINK_NEED_BYTE_SWAP + mount_status->target_system = mavlink_msg_mount_status_get_target_system(msg); + mount_status->target_component = mavlink_msg_mount_status_get_target_component(msg); + mount_status->pointing_a = mavlink_msg_mount_status_get_pointing_a(msg); + mount_status->pointing_b = mavlink_msg_mount_status_get_pointing_b(msg); + mount_status->pointing_c = mavlink_msg_mount_status_get_pointing_c(msg); +#else + memcpy(mount_status, _MAV_PAYLOAD(msg), 14); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_radio.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_radio.h new file mode 100644 index 0000000000..50b23b4e0f --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_radio.h @@ -0,0 +1,276 @@ +// MESSAGE RADIO PACKING + +#define MAVLINK_MSG_ID_RADIO 166 + +typedef struct __mavlink_radio_t +{ + uint8_t rssi; ///< local signal strength + uint8_t remrssi; ///< remote signal strength + uint8_t txbuf; ///< how full the tx buffer is as a percentage + uint8_t noise; ///< background noise level + uint8_t remnoise; ///< remote background noise level + uint16_t rxerrors; ///< receive errors + uint16_t fixed; ///< count of error corrected packets +} mavlink_radio_t; + +#define MAVLINK_MSG_ID_RADIO_LEN 9 +#define MAVLINK_MSG_ID_166_LEN 9 + + + +#define MAVLINK_MESSAGE_INFO_RADIO { \ + "RADIO", \ + 7, \ + { { "rssi", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_radio_t, rssi) }, \ + { "remrssi", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_radio_t, remrssi) }, \ + { "txbuf", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_radio_t, txbuf) }, \ + { "noise", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_radio_t, noise) }, \ + { "remnoise", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_radio_t, remnoise) }, \ + { "rxerrors", NULL, MAVLINK_TYPE_UINT16_T, 0, 5, offsetof(mavlink_radio_t, rxerrors) }, \ + { "fixed", NULL, MAVLINK_TYPE_UINT16_T, 0, 7, offsetof(mavlink_radio_t, fixed) }, \ + } \ +} + + +/** + * @brief Pack a radio message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param rssi local signal strength + * @param remrssi remote signal strength + * @param txbuf how full the tx buffer is as a percentage + * @param noise background noise level + * @param remnoise remote background noise level + * @param rxerrors receive errors + * @param fixed count of error corrected packets + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_radio_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t rssi, uint8_t remrssi, uint8_t txbuf, uint8_t noise, uint8_t remnoise, uint16_t rxerrors, uint16_t fixed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint8_t(buf, 0, rssi); + _mav_put_uint8_t(buf, 1, remrssi); + _mav_put_uint8_t(buf, 2, txbuf); + _mav_put_uint8_t(buf, 3, noise); + _mav_put_uint8_t(buf, 4, remnoise); + _mav_put_uint16_t(buf, 5, rxerrors); + _mav_put_uint16_t(buf, 7, fixed); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 9); +#else + mavlink_radio_t packet; + packet.rssi = rssi; + packet.remrssi = remrssi; + packet.txbuf = txbuf; + packet.noise = noise; + packet.remnoise = remnoise; + packet.rxerrors = rxerrors; + packet.fixed = fixed; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 9); +#endif + + msg->msgid = MAVLINK_MSG_ID_RADIO; + return mavlink_finalize_message(msg, system_id, component_id, 9); +} + +/** + * @brief Pack a radio message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param rssi local signal strength + * @param remrssi remote signal strength + * @param txbuf how full the tx buffer is as a percentage + * @param noise background noise level + * @param remnoise remote background noise level + * @param rxerrors receive errors + * @param fixed count of error corrected packets + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_radio_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t rssi,uint8_t remrssi,uint8_t txbuf,uint8_t noise,uint8_t remnoise,uint16_t rxerrors,uint16_t fixed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint8_t(buf, 0, rssi); + _mav_put_uint8_t(buf, 1, remrssi); + _mav_put_uint8_t(buf, 2, txbuf); + _mav_put_uint8_t(buf, 3, noise); + _mav_put_uint8_t(buf, 4, remnoise); + _mav_put_uint16_t(buf, 5, rxerrors); + _mav_put_uint16_t(buf, 7, fixed); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 9); +#else + mavlink_radio_t packet; + packet.rssi = rssi; + packet.remrssi = remrssi; + packet.txbuf = txbuf; + packet.noise = noise; + packet.remnoise = remnoise; + packet.rxerrors = rxerrors; + packet.fixed = fixed; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 9); +#endif + + msg->msgid = MAVLINK_MSG_ID_RADIO; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 9); +} + +/** + * @brief Encode a radio struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param radio C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_radio_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_radio_t* radio) +{ + return mavlink_msg_radio_pack(system_id, component_id, msg, radio->rssi, radio->remrssi, radio->txbuf, radio->noise, radio->remnoise, radio->rxerrors, radio->fixed); +} + +/** + * @brief Send a radio message + * @param chan MAVLink channel to send the message + * + * @param rssi local signal strength + * @param remrssi remote signal strength + * @param txbuf how full the tx buffer is as a percentage + * @param noise background noise level + * @param remnoise remote background noise level + * @param rxerrors receive errors + * @param fixed count of error corrected packets + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_radio_send(mavlink_channel_t chan, uint8_t rssi, uint8_t remrssi, uint8_t txbuf, uint8_t noise, uint8_t remnoise, uint16_t rxerrors, uint16_t fixed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint8_t(buf, 0, rssi); + _mav_put_uint8_t(buf, 1, remrssi); + _mav_put_uint8_t(buf, 2, txbuf); + _mav_put_uint8_t(buf, 3, noise); + _mav_put_uint8_t(buf, 4, remnoise); + _mav_put_uint16_t(buf, 5, rxerrors); + _mav_put_uint16_t(buf, 7, fixed); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RADIO, buf, 9); +#else + mavlink_radio_t packet; + packet.rssi = rssi; + packet.remrssi = remrssi; + packet.txbuf = txbuf; + packet.noise = noise; + packet.remnoise = remnoise; + packet.rxerrors = rxerrors; + packet.fixed = fixed; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RADIO, (const char *)&packet, 9); +#endif +} + +#endif + +// MESSAGE RADIO UNPACKING + + +/** + * @brief Get field rssi from radio message + * + * @return local signal strength + */ +static inline uint8_t mavlink_msg_radio_get_rssi(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field remrssi from radio message + * + * @return remote signal strength + */ +static inline uint8_t mavlink_msg_radio_get_remrssi(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field txbuf from radio message + * + * @return how full the tx buffer is as a percentage + */ +static inline uint8_t mavlink_msg_radio_get_txbuf(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field noise from radio message + * + * @return background noise level + */ +static inline uint8_t mavlink_msg_radio_get_noise(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field remnoise from radio message + * + * @return remote background noise level + */ +static inline uint8_t mavlink_msg_radio_get_remnoise(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field rxerrors from radio message + * + * @return receive errors + */ +static inline uint16_t mavlink_msg_radio_get_rxerrors(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 5); +} + +/** + * @brief Get field fixed from radio message + * + * @return count of error corrected packets + */ +static inline uint16_t mavlink_msg_radio_get_fixed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 7); +} + +/** + * @brief Decode a radio message into a struct + * + * @param msg The message to decode + * @param radio C-struct to decode the message contents into + */ +static inline void mavlink_msg_radio_decode(const mavlink_message_t* msg, mavlink_radio_t* radio) +{ +#if MAVLINK_NEED_BYTE_SWAP + radio->rssi = mavlink_msg_radio_get_rssi(msg); + radio->remrssi = mavlink_msg_radio_get_remrssi(msg); + radio->txbuf = mavlink_msg_radio_get_txbuf(msg); + radio->noise = mavlink_msg_radio_get_noise(msg); + radio->remnoise = mavlink_msg_radio_get_remnoise(msg); + radio->rxerrors = mavlink_msg_radio_get_rxerrors(msg); + radio->fixed = mavlink_msg_radio_get_fixed(msg); +#else + memcpy(radio, _MAV_PAYLOAD(msg), 9); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_sensor_offsets.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_sensor_offsets.h new file mode 100644 index 0000000000..3016ea9bd9 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_sensor_offsets.h @@ -0,0 +1,386 @@ +// MESSAGE SENSOR_OFFSETS PACKING + +#define MAVLINK_MSG_ID_SENSOR_OFFSETS 150 + +typedef struct __mavlink_sensor_offsets_t +{ + int16_t mag_ofs_x; ///< magnetometer X offset + int16_t mag_ofs_y; ///< magnetometer Y offset + int16_t mag_ofs_z; ///< magnetometer Z offset + float mag_declination; ///< magnetic declination (radians) + int32_t raw_press; ///< raw pressure from barometer + int32_t raw_temp; ///< raw temperature from barometer + float gyro_cal_x; ///< gyro X calibration + float gyro_cal_y; ///< gyro Y calibration + float gyro_cal_z; ///< gyro Z calibration + float accel_cal_x; ///< accel X calibration + float accel_cal_y; ///< accel Y calibration + float accel_cal_z; ///< accel Z calibration +} mavlink_sensor_offsets_t; + +#define MAVLINK_MSG_ID_SENSOR_OFFSETS_LEN 42 +#define MAVLINK_MSG_ID_150_LEN 42 + + + +#define MAVLINK_MESSAGE_INFO_SENSOR_OFFSETS { \ + "SENSOR_OFFSETS", \ + 12, \ + { { "mag_ofs_x", NULL, MAVLINK_TYPE_INT16_T, 0, 0, offsetof(mavlink_sensor_offsets_t, mag_ofs_x) }, \ + { "mag_ofs_y", NULL, MAVLINK_TYPE_INT16_T, 0, 2, offsetof(mavlink_sensor_offsets_t, mag_ofs_y) }, \ + { "mag_ofs_z", NULL, MAVLINK_TYPE_INT16_T, 0, 4, offsetof(mavlink_sensor_offsets_t, mag_ofs_z) }, \ + { "mag_declination", NULL, MAVLINK_TYPE_FLOAT, 0, 6, offsetof(mavlink_sensor_offsets_t, mag_declination) }, \ + { "raw_press", NULL, MAVLINK_TYPE_INT32_T, 0, 10, offsetof(mavlink_sensor_offsets_t, raw_press) }, \ + { "raw_temp", NULL, MAVLINK_TYPE_INT32_T, 0, 14, offsetof(mavlink_sensor_offsets_t, raw_temp) }, \ + { "gyro_cal_x", NULL, MAVLINK_TYPE_FLOAT, 0, 18, offsetof(mavlink_sensor_offsets_t, gyro_cal_x) }, \ + { "gyro_cal_y", NULL, MAVLINK_TYPE_FLOAT, 0, 22, offsetof(mavlink_sensor_offsets_t, gyro_cal_y) }, \ + { "gyro_cal_z", NULL, MAVLINK_TYPE_FLOAT, 0, 26, offsetof(mavlink_sensor_offsets_t, gyro_cal_z) }, \ + { "accel_cal_x", NULL, MAVLINK_TYPE_FLOAT, 0, 30, offsetof(mavlink_sensor_offsets_t, accel_cal_x) }, \ + { "accel_cal_y", NULL, MAVLINK_TYPE_FLOAT, 0, 34, offsetof(mavlink_sensor_offsets_t, accel_cal_y) }, \ + { "accel_cal_z", NULL, MAVLINK_TYPE_FLOAT, 0, 38, offsetof(mavlink_sensor_offsets_t, accel_cal_z) }, \ + } \ +} + + +/** + * @brief Pack a sensor_offsets message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param mag_ofs_x magnetometer X offset + * @param mag_ofs_y magnetometer Y offset + * @param mag_ofs_z magnetometer Z offset + * @param mag_declination magnetic declination (radians) + * @param raw_press raw pressure from barometer + * @param raw_temp raw temperature from barometer + * @param gyro_cal_x gyro X calibration + * @param gyro_cal_y gyro Y calibration + * @param gyro_cal_z gyro Z calibration + * @param accel_cal_x accel X calibration + * @param accel_cal_y accel Y calibration + * @param accel_cal_z accel Z calibration + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sensor_offsets_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + int16_t mag_ofs_x, int16_t mag_ofs_y, int16_t mag_ofs_z, float mag_declination, int32_t raw_press, int32_t raw_temp, float gyro_cal_x, float gyro_cal_y, float gyro_cal_z, float accel_cal_x, float accel_cal_y, float accel_cal_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + _mav_put_int16_t(buf, 0, mag_ofs_x); + _mav_put_int16_t(buf, 2, mag_ofs_y); + _mav_put_int16_t(buf, 4, mag_ofs_z); + _mav_put_float(buf, 6, mag_declination); + _mav_put_int32_t(buf, 10, raw_press); + _mav_put_int32_t(buf, 14, raw_temp); + _mav_put_float(buf, 18, gyro_cal_x); + _mav_put_float(buf, 22, gyro_cal_y); + _mav_put_float(buf, 26, gyro_cal_z); + _mav_put_float(buf, 30, accel_cal_x); + _mav_put_float(buf, 34, accel_cal_y); + _mav_put_float(buf, 38, accel_cal_z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 42); +#else + mavlink_sensor_offsets_t packet; + packet.mag_ofs_x = mag_ofs_x; + packet.mag_ofs_y = mag_ofs_y; + packet.mag_ofs_z = mag_ofs_z; + packet.mag_declination = mag_declination; + packet.raw_press = raw_press; + packet.raw_temp = raw_temp; + packet.gyro_cal_x = gyro_cal_x; + packet.gyro_cal_y = gyro_cal_y; + packet.gyro_cal_z = gyro_cal_z; + packet.accel_cal_x = accel_cal_x; + packet.accel_cal_y = accel_cal_y; + packet.accel_cal_z = accel_cal_z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 42); +#endif + + msg->msgid = MAVLINK_MSG_ID_SENSOR_OFFSETS; + return mavlink_finalize_message(msg, system_id, component_id, 42); +} + +/** + * @brief Pack a sensor_offsets message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param mag_ofs_x magnetometer X offset + * @param mag_ofs_y magnetometer Y offset + * @param mag_ofs_z magnetometer Z offset + * @param mag_declination magnetic declination (radians) + * @param raw_press raw pressure from barometer + * @param raw_temp raw temperature from barometer + * @param gyro_cal_x gyro X calibration + * @param gyro_cal_y gyro Y calibration + * @param gyro_cal_z gyro Z calibration + * @param accel_cal_x accel X calibration + * @param accel_cal_y accel Y calibration + * @param accel_cal_z accel Z calibration + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sensor_offsets_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + int16_t mag_ofs_x,int16_t mag_ofs_y,int16_t mag_ofs_z,float mag_declination,int32_t raw_press,int32_t raw_temp,float gyro_cal_x,float gyro_cal_y,float gyro_cal_z,float accel_cal_x,float accel_cal_y,float accel_cal_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + _mav_put_int16_t(buf, 0, mag_ofs_x); + _mav_put_int16_t(buf, 2, mag_ofs_y); + _mav_put_int16_t(buf, 4, mag_ofs_z); + _mav_put_float(buf, 6, mag_declination); + _mav_put_int32_t(buf, 10, raw_press); + _mav_put_int32_t(buf, 14, raw_temp); + _mav_put_float(buf, 18, gyro_cal_x); + _mav_put_float(buf, 22, gyro_cal_y); + _mav_put_float(buf, 26, gyro_cal_z); + _mav_put_float(buf, 30, accel_cal_x); + _mav_put_float(buf, 34, accel_cal_y); + _mav_put_float(buf, 38, accel_cal_z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 42); +#else + mavlink_sensor_offsets_t packet; + packet.mag_ofs_x = mag_ofs_x; + packet.mag_ofs_y = mag_ofs_y; + packet.mag_ofs_z = mag_ofs_z; + packet.mag_declination = mag_declination; + packet.raw_press = raw_press; + packet.raw_temp = raw_temp; + packet.gyro_cal_x = gyro_cal_x; + packet.gyro_cal_y = gyro_cal_y; + packet.gyro_cal_z = gyro_cal_z; + packet.accel_cal_x = accel_cal_x; + packet.accel_cal_y = accel_cal_y; + packet.accel_cal_z = accel_cal_z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 42); +#endif + + msg->msgid = MAVLINK_MSG_ID_SENSOR_OFFSETS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 42); +} + +/** + * @brief Encode a sensor_offsets struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param sensor_offsets C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_sensor_offsets_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_sensor_offsets_t* sensor_offsets) +{ + return mavlink_msg_sensor_offsets_pack(system_id, component_id, msg, sensor_offsets->mag_ofs_x, sensor_offsets->mag_ofs_y, sensor_offsets->mag_ofs_z, sensor_offsets->mag_declination, sensor_offsets->raw_press, sensor_offsets->raw_temp, sensor_offsets->gyro_cal_x, sensor_offsets->gyro_cal_y, sensor_offsets->gyro_cal_z, sensor_offsets->accel_cal_x, sensor_offsets->accel_cal_y, sensor_offsets->accel_cal_z); +} + +/** + * @brief Send a sensor_offsets message + * @param chan MAVLink channel to send the message + * + * @param mag_ofs_x magnetometer X offset + * @param mag_ofs_y magnetometer Y offset + * @param mag_ofs_z magnetometer Z offset + * @param mag_declination magnetic declination (radians) + * @param raw_press raw pressure from barometer + * @param raw_temp raw temperature from barometer + * @param gyro_cal_x gyro X calibration + * @param gyro_cal_y gyro Y calibration + * @param gyro_cal_z gyro Z calibration + * @param accel_cal_x accel X calibration + * @param accel_cal_y accel Y calibration + * @param accel_cal_z accel Z calibration + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_sensor_offsets_send(mavlink_channel_t chan, int16_t mag_ofs_x, int16_t mag_ofs_y, int16_t mag_ofs_z, float mag_declination, int32_t raw_press, int32_t raw_temp, float gyro_cal_x, float gyro_cal_y, float gyro_cal_z, float accel_cal_x, float accel_cal_y, float accel_cal_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + _mav_put_int16_t(buf, 0, mag_ofs_x); + _mav_put_int16_t(buf, 2, mag_ofs_y); + _mav_put_int16_t(buf, 4, mag_ofs_z); + _mav_put_float(buf, 6, mag_declination); + _mav_put_int32_t(buf, 10, raw_press); + _mav_put_int32_t(buf, 14, raw_temp); + _mav_put_float(buf, 18, gyro_cal_x); + _mav_put_float(buf, 22, gyro_cal_y); + _mav_put_float(buf, 26, gyro_cal_z); + _mav_put_float(buf, 30, accel_cal_x); + _mav_put_float(buf, 34, accel_cal_y); + _mav_put_float(buf, 38, accel_cal_z); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SENSOR_OFFSETS, buf, 42); +#else + mavlink_sensor_offsets_t packet; + packet.mag_ofs_x = mag_ofs_x; + packet.mag_ofs_y = mag_ofs_y; + packet.mag_ofs_z = mag_ofs_z; + packet.mag_declination = mag_declination; + packet.raw_press = raw_press; + packet.raw_temp = raw_temp; + packet.gyro_cal_x = gyro_cal_x; + packet.gyro_cal_y = gyro_cal_y; + packet.gyro_cal_z = gyro_cal_z; + packet.accel_cal_x = accel_cal_x; + packet.accel_cal_y = accel_cal_y; + packet.accel_cal_z = accel_cal_z; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SENSOR_OFFSETS, (const char *)&packet, 42); +#endif +} + +#endif + +// MESSAGE SENSOR_OFFSETS UNPACKING + + +/** + * @brief Get field mag_ofs_x from sensor_offsets message + * + * @return magnetometer X offset + */ +static inline int16_t mavlink_msg_sensor_offsets_get_mag_ofs_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 0); +} + +/** + * @brief Get field mag_ofs_y from sensor_offsets message + * + * @return magnetometer Y offset + */ +static inline int16_t mavlink_msg_sensor_offsets_get_mag_ofs_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 2); +} + +/** + * @brief Get field mag_ofs_z from sensor_offsets message + * + * @return magnetometer Z offset + */ +static inline int16_t mavlink_msg_sensor_offsets_get_mag_ofs_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 4); +} + +/** + * @brief Get field mag_declination from sensor_offsets message + * + * @return magnetic declination (radians) + */ +static inline float mavlink_msg_sensor_offsets_get_mag_declination(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 6); +} + +/** + * @brief Get field raw_press from sensor_offsets message + * + * @return raw pressure from barometer + */ +static inline int32_t mavlink_msg_sensor_offsets_get_raw_press(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 10); +} + +/** + * @brief Get field raw_temp from sensor_offsets message + * + * @return raw temperature from barometer + */ +static inline int32_t mavlink_msg_sensor_offsets_get_raw_temp(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 14); +} + +/** + * @brief Get field gyro_cal_x from sensor_offsets message + * + * @return gyro X calibration + */ +static inline float mavlink_msg_sensor_offsets_get_gyro_cal_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 18); +} + +/** + * @brief Get field gyro_cal_y from sensor_offsets message + * + * @return gyro Y calibration + */ +static inline float mavlink_msg_sensor_offsets_get_gyro_cal_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 22); +} + +/** + * @brief Get field gyro_cal_z from sensor_offsets message + * + * @return gyro Z calibration + */ +static inline float mavlink_msg_sensor_offsets_get_gyro_cal_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 26); +} + +/** + * @brief Get field accel_cal_x from sensor_offsets message + * + * @return accel X calibration + */ +static inline float mavlink_msg_sensor_offsets_get_accel_cal_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 30); +} + +/** + * @brief Get field accel_cal_y from sensor_offsets message + * + * @return accel Y calibration + */ +static inline float mavlink_msg_sensor_offsets_get_accel_cal_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 34); +} + +/** + * @brief Get field accel_cal_z from sensor_offsets message + * + * @return accel Z calibration + */ +static inline float mavlink_msg_sensor_offsets_get_accel_cal_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 38); +} + +/** + * @brief Decode a sensor_offsets message into a struct + * + * @param msg The message to decode + * @param sensor_offsets C-struct to decode the message contents into + */ +static inline void mavlink_msg_sensor_offsets_decode(const mavlink_message_t* msg, mavlink_sensor_offsets_t* sensor_offsets) +{ +#if MAVLINK_NEED_BYTE_SWAP + sensor_offsets->mag_ofs_x = mavlink_msg_sensor_offsets_get_mag_ofs_x(msg); + sensor_offsets->mag_ofs_y = mavlink_msg_sensor_offsets_get_mag_ofs_y(msg); + sensor_offsets->mag_ofs_z = mavlink_msg_sensor_offsets_get_mag_ofs_z(msg); + sensor_offsets->mag_declination = mavlink_msg_sensor_offsets_get_mag_declination(msg); + sensor_offsets->raw_press = mavlink_msg_sensor_offsets_get_raw_press(msg); + sensor_offsets->raw_temp = mavlink_msg_sensor_offsets_get_raw_temp(msg); + sensor_offsets->gyro_cal_x = mavlink_msg_sensor_offsets_get_gyro_cal_x(msg); + sensor_offsets->gyro_cal_y = mavlink_msg_sensor_offsets_get_gyro_cal_y(msg); + sensor_offsets->gyro_cal_z = mavlink_msg_sensor_offsets_get_gyro_cal_z(msg); + sensor_offsets->accel_cal_x = mavlink_msg_sensor_offsets_get_accel_cal_x(msg); + sensor_offsets->accel_cal_y = mavlink_msg_sensor_offsets_get_accel_cal_y(msg); + sensor_offsets->accel_cal_z = mavlink_msg_sensor_offsets_get_accel_cal_z(msg); +#else + memcpy(sensor_offsets, _MAV_PAYLOAD(msg), 42); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_set_mag_offsets.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_set_mag_offsets.h new file mode 100644 index 0000000000..99473e2f12 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_set_mag_offsets.h @@ -0,0 +1,232 @@ +// MESSAGE SET_MAG_OFFSETS PACKING + +#define MAVLINK_MSG_ID_SET_MAG_OFFSETS 151 + +typedef struct __mavlink_set_mag_offsets_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + int16_t mag_ofs_x; ///< magnetometer X offset + int16_t mag_ofs_y; ///< magnetometer Y offset + int16_t mag_ofs_z; ///< magnetometer Z offset +} mavlink_set_mag_offsets_t; + +#define MAVLINK_MSG_ID_SET_MAG_OFFSETS_LEN 8 +#define MAVLINK_MSG_ID_151_LEN 8 + + + +#define MAVLINK_MESSAGE_INFO_SET_MAG_OFFSETS { \ + "SET_MAG_OFFSETS", \ + 5, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_set_mag_offsets_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_set_mag_offsets_t, target_component) }, \ + { "mag_ofs_x", NULL, MAVLINK_TYPE_INT16_T, 0, 2, offsetof(mavlink_set_mag_offsets_t, mag_ofs_x) }, \ + { "mag_ofs_y", NULL, MAVLINK_TYPE_INT16_T, 0, 4, offsetof(mavlink_set_mag_offsets_t, mag_ofs_y) }, \ + { "mag_ofs_z", NULL, MAVLINK_TYPE_INT16_T, 0, 6, offsetof(mavlink_set_mag_offsets_t, mag_ofs_z) }, \ + } \ +} + + +/** + * @brief Pack a set_mag_offsets message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param mag_ofs_x magnetometer X offset + * @param mag_ofs_y magnetometer Y offset + * @param mag_ofs_z magnetometer Z offset + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_mag_offsets_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, int16_t mag_ofs_x, int16_t mag_ofs_y, int16_t mag_ofs_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int16_t(buf, 2, mag_ofs_x); + _mav_put_int16_t(buf, 4, mag_ofs_y); + _mav_put_int16_t(buf, 6, mag_ofs_z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_set_mag_offsets_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mag_ofs_x = mag_ofs_x; + packet.mag_ofs_y = mag_ofs_y; + packet.mag_ofs_z = mag_ofs_z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_MAG_OFFSETS; + return mavlink_finalize_message(msg, system_id, component_id, 8); +} + +/** + * @brief Pack a set_mag_offsets message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param mag_ofs_x magnetometer X offset + * @param mag_ofs_y magnetometer Y offset + * @param mag_ofs_z magnetometer Z offset + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_mag_offsets_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,int16_t mag_ofs_x,int16_t mag_ofs_y,int16_t mag_ofs_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int16_t(buf, 2, mag_ofs_x); + _mav_put_int16_t(buf, 4, mag_ofs_y); + _mav_put_int16_t(buf, 6, mag_ofs_z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_set_mag_offsets_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mag_ofs_x = mag_ofs_x; + packet.mag_ofs_y = mag_ofs_y; + packet.mag_ofs_z = mag_ofs_z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_MAG_OFFSETS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 8); +} + +/** + * @brief Encode a set_mag_offsets struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_mag_offsets C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_mag_offsets_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_mag_offsets_t* set_mag_offsets) +{ + return mavlink_msg_set_mag_offsets_pack(system_id, component_id, msg, set_mag_offsets->target_system, set_mag_offsets->target_component, set_mag_offsets->mag_ofs_x, set_mag_offsets->mag_ofs_y, set_mag_offsets->mag_ofs_z); +} + +/** + * @brief Send a set_mag_offsets message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param mag_ofs_x magnetometer X offset + * @param mag_ofs_y magnetometer Y offset + * @param mag_ofs_z magnetometer Z offset + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_mag_offsets_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, int16_t mag_ofs_x, int16_t mag_ofs_y, int16_t mag_ofs_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int16_t(buf, 2, mag_ofs_x); + _mav_put_int16_t(buf, 4, mag_ofs_y); + _mav_put_int16_t(buf, 6, mag_ofs_z); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_MAG_OFFSETS, buf, 8); +#else + mavlink_set_mag_offsets_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mag_ofs_x = mag_ofs_x; + packet.mag_ofs_y = mag_ofs_y; + packet.mag_ofs_z = mag_ofs_z; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_MAG_OFFSETS, (const char *)&packet, 8); +#endif +} + +#endif + +// MESSAGE SET_MAG_OFFSETS UNPACKING + + +/** + * @brief Get field target_system from set_mag_offsets message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_set_mag_offsets_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from set_mag_offsets message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_set_mag_offsets_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field mag_ofs_x from set_mag_offsets message + * + * @return magnetometer X offset + */ +static inline int16_t mavlink_msg_set_mag_offsets_get_mag_ofs_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 2); +} + +/** + * @brief Get field mag_ofs_y from set_mag_offsets message + * + * @return magnetometer Y offset + */ +static inline int16_t mavlink_msg_set_mag_offsets_get_mag_ofs_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 4); +} + +/** + * @brief Get field mag_ofs_z from set_mag_offsets message + * + * @return magnetometer Z offset + */ +static inline int16_t mavlink_msg_set_mag_offsets_get_mag_ofs_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 6); +} + +/** + * @brief Decode a set_mag_offsets message into a struct + * + * @param msg The message to decode + * @param set_mag_offsets C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_mag_offsets_decode(const mavlink_message_t* msg, mavlink_set_mag_offsets_t* set_mag_offsets) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_mag_offsets->target_system = mavlink_msg_set_mag_offsets_get_target_system(msg); + set_mag_offsets->target_component = mavlink_msg_set_mag_offsets_get_target_component(msg); + set_mag_offsets->mag_ofs_x = mavlink_msg_set_mag_offsets_get_mag_ofs_x(msg); + set_mag_offsets->mag_ofs_y = mavlink_msg_set_mag_offsets_get_mag_ofs_y(msg); + set_mag_offsets->mag_ofs_z = mavlink_msg_set_mag_offsets_get_mag_ofs_z(msg); +#else + memcpy(set_mag_offsets, _MAV_PAYLOAD(msg), 8); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_simstate.h b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_simstate.h new file mode 100644 index 0000000000..05f9ca3cc4 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/mavlink_msg_simstate.h @@ -0,0 +1,320 @@ +// MESSAGE SIMSTATE PACKING + +#define MAVLINK_MSG_ID_SIMSTATE 164 + +typedef struct __mavlink_simstate_t +{ + float roll; ///< Roll angle (rad) + float pitch; ///< Pitch angle (rad) + float yaw; ///< Yaw angle (rad) + float xacc; ///< X acceleration m/s/s + float yacc; ///< Y acceleration m/s/s + float zacc; ///< Z acceleration m/s/s + float xgyro; ///< Angular speed around X axis rad/s + float ygyro; ///< Angular speed around Y axis rad/s + float zgyro; ///< Angular speed around Z axis rad/s +} mavlink_simstate_t; + +#define MAVLINK_MSG_ID_SIMSTATE_LEN 36 +#define MAVLINK_MSG_ID_164_LEN 36 + + + +#define MAVLINK_MESSAGE_INFO_SIMSTATE { \ + "SIMSTATE", \ + 9, \ + { { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_simstate_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_simstate_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_simstate_t, yaw) }, \ + { "xacc", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_simstate_t, xacc) }, \ + { "yacc", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_simstate_t, yacc) }, \ + { "zacc", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_simstate_t, zacc) }, \ + { "xgyro", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_simstate_t, xgyro) }, \ + { "ygyro", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_simstate_t, ygyro) }, \ + { "zgyro", NULL, MAVLINK_TYPE_FLOAT, 0, 32, offsetof(mavlink_simstate_t, zgyro) }, \ + } \ +} + + +/** + * @brief Pack a simstate message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param xacc X acceleration m/s/s + * @param yacc Y acceleration m/s/s + * @param zacc Z acceleration m/s/s + * @param xgyro Angular speed around X axis rad/s + * @param ygyro Angular speed around Y axis rad/s + * @param zgyro Angular speed around Z axis rad/s + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_simstate_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float roll, float pitch, float yaw, float xacc, float yacc, float zacc, float xgyro, float ygyro, float zgyro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, xacc); + _mav_put_float(buf, 16, yacc); + _mav_put_float(buf, 20, zacc); + _mav_put_float(buf, 24, xgyro); + _mav_put_float(buf, 28, ygyro); + _mav_put_float(buf, 32, zgyro); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_simstate_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_SIMSTATE; + return mavlink_finalize_message(msg, system_id, component_id, 36); +} + +/** + * @brief Pack a simstate message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param xacc X acceleration m/s/s + * @param yacc Y acceleration m/s/s + * @param zacc Z acceleration m/s/s + * @param xgyro Angular speed around X axis rad/s + * @param ygyro Angular speed around Y axis rad/s + * @param zgyro Angular speed around Z axis rad/s + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_simstate_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float roll,float pitch,float yaw,float xacc,float yacc,float zacc,float xgyro,float ygyro,float zgyro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, xacc); + _mav_put_float(buf, 16, yacc); + _mav_put_float(buf, 20, zacc); + _mav_put_float(buf, 24, xgyro); + _mav_put_float(buf, 28, ygyro); + _mav_put_float(buf, 32, zgyro); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_simstate_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_SIMSTATE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 36); +} + +/** + * @brief Encode a simstate struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param simstate C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_simstate_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_simstate_t* simstate) +{ + return mavlink_msg_simstate_pack(system_id, component_id, msg, simstate->roll, simstate->pitch, simstate->yaw, simstate->xacc, simstate->yacc, simstate->zacc, simstate->xgyro, simstate->ygyro, simstate->zgyro); +} + +/** + * @brief Send a simstate message + * @param chan MAVLink channel to send the message + * + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param xacc X acceleration m/s/s + * @param yacc Y acceleration m/s/s + * @param zacc Z acceleration m/s/s + * @param xgyro Angular speed around X axis rad/s + * @param ygyro Angular speed around Y axis rad/s + * @param zgyro Angular speed around Z axis rad/s + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_simstate_send(mavlink_channel_t chan, float roll, float pitch, float yaw, float xacc, float yacc, float zacc, float xgyro, float ygyro, float zgyro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, xacc); + _mav_put_float(buf, 16, yacc); + _mav_put_float(buf, 20, zacc); + _mav_put_float(buf, 24, xgyro); + _mav_put_float(buf, 28, ygyro); + _mav_put_float(buf, 32, zgyro); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SIMSTATE, buf, 36); +#else + mavlink_simstate_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SIMSTATE, (const char *)&packet, 36); +#endif +} + +#endif + +// MESSAGE SIMSTATE UNPACKING + + +/** + * @brief Get field roll from simstate message + * + * @return Roll angle (rad) + */ +static inline float mavlink_msg_simstate_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field pitch from simstate message + * + * @return Pitch angle (rad) + */ +static inline float mavlink_msg_simstate_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field yaw from simstate message + * + * @return Yaw angle (rad) + */ +static inline float mavlink_msg_simstate_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field xacc from simstate message + * + * @return X acceleration m/s/s + */ +static inline float mavlink_msg_simstate_get_xacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field yacc from simstate message + * + * @return Y acceleration m/s/s + */ +static inline float mavlink_msg_simstate_get_yacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field zacc from simstate message + * + * @return Z acceleration m/s/s + */ +static inline float mavlink_msg_simstate_get_zacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field xgyro from simstate message + * + * @return Angular speed around X axis rad/s + */ +static inline float mavlink_msg_simstate_get_xgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field ygyro from simstate message + * + * @return Angular speed around Y axis rad/s + */ +static inline float mavlink_msg_simstate_get_ygyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field zgyro from simstate message + * + * @return Angular speed around Z axis rad/s + */ +static inline float mavlink_msg_simstate_get_zgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 32); +} + +/** + * @brief Decode a simstate message into a struct + * + * @param msg The message to decode + * @param simstate C-struct to decode the message contents into + */ +static inline void mavlink_msg_simstate_decode(const mavlink_message_t* msg, mavlink_simstate_t* simstate) +{ +#if MAVLINK_NEED_BYTE_SWAP + simstate->roll = mavlink_msg_simstate_get_roll(msg); + simstate->pitch = mavlink_msg_simstate_get_pitch(msg); + simstate->yaw = mavlink_msg_simstate_get_yaw(msg); + simstate->xacc = mavlink_msg_simstate_get_xacc(msg); + simstate->yacc = mavlink_msg_simstate_get_yacc(msg); + simstate->zacc = mavlink_msg_simstate_get_zacc(msg); + simstate->xgyro = mavlink_msg_simstate_get_xgyro(msg); + simstate->ygyro = mavlink_msg_simstate_get_ygyro(msg); + simstate->zgyro = mavlink_msg_simstate_get_zgyro(msg); +#else + memcpy(simstate, _MAV_PAYLOAD(msg), 36); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ardupilotmega/testsuite.h b/mavlink/include/mavlink/v0.9/ardupilotmega/testsuite.h new file mode 100644 index 0000000000..a3ac5476ca --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ardupilotmega/testsuite.h @@ -0,0 +1,908 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from ardupilotmega.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef ARDUPILOTMEGA_TESTSUITE_H +#define ARDUPILOTMEGA_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL +static void mavlink_test_common(uint8_t, uint8_t, mavlink_message_t *last_msg); +static void mavlink_test_ardupilotmega(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_test_common(system_id, component_id, last_msg); + mavlink_test_ardupilotmega(system_id, component_id, last_msg); +} +#endif + +#include "../common/testsuite.h" + + +static void mavlink_test_sensor_offsets(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_sensor_offsets_t packet_in = { + 17235, + 17339, + 17443, + 59.0, + 963497984, + 963498192, + 143.0, + 171.0, + 199.0, + 227.0, + 255.0, + 283.0, + }; + mavlink_sensor_offsets_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.mag_ofs_x = packet_in.mag_ofs_x; + packet1.mag_ofs_y = packet_in.mag_ofs_y; + packet1.mag_ofs_z = packet_in.mag_ofs_z; + packet1.mag_declination = packet_in.mag_declination; + packet1.raw_press = packet_in.raw_press; + packet1.raw_temp = packet_in.raw_temp; + packet1.gyro_cal_x = packet_in.gyro_cal_x; + packet1.gyro_cal_y = packet_in.gyro_cal_y; + packet1.gyro_cal_z = packet_in.gyro_cal_z; + packet1.accel_cal_x = packet_in.accel_cal_x; + packet1.accel_cal_y = packet_in.accel_cal_y; + packet1.accel_cal_z = packet_in.accel_cal_z; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_sensor_offsets_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_sensor_offsets_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_sensor_offsets_pack(system_id, component_id, &msg , packet1.mag_ofs_x , packet1.mag_ofs_y , packet1.mag_ofs_z , packet1.mag_declination , packet1.raw_press , packet1.raw_temp , packet1.gyro_cal_x , packet1.gyro_cal_y , packet1.gyro_cal_z , packet1.accel_cal_x , packet1.accel_cal_y , packet1.accel_cal_z ); + mavlink_msg_sensor_offsets_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_sensor_offsets_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.mag_ofs_x , packet1.mag_ofs_y , packet1.mag_ofs_z , packet1.mag_declination , packet1.raw_press , packet1.raw_temp , packet1.gyro_cal_x , packet1.gyro_cal_y , packet1.gyro_cal_z , packet1.accel_cal_x , packet1.accel_cal_y , packet1.accel_cal_z ); + mavlink_msg_sensor_offsets_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; i>8) ^ (tmp<<8) ^ (tmp <<3) ^ (tmp>>4); +} + +/** + * @brief Initiliaze the buffer for the X.25 CRC + * + * @param crcAccum the 16 bit X.25 CRC + */ +static inline void crc_init(uint16_t* crcAccum) +{ + *crcAccum = X25_INIT_CRC; +} + + +/** + * @brief Calculates the X.25 checksum on a byte buffer + * + * @param pBuffer buffer containing the byte array to hash + * @param length length of the byte array + * @return the checksum over the buffer bytes + **/ +static inline uint16_t crc_calculate(uint8_t* pBuffer, uint16_t length) +{ + uint16_t crcTmp; + crc_init(&crcTmp); + while (length--) { + crc_accumulate(*pBuffer++, &crcTmp); + } + return crcTmp; +} + +/** + * @brief Accumulate the X.25 CRC by adding an array of bytes + * + * The checksum function adds the hash of one char at a time to the + * 16 bit checksum (uint16_t). + * + * @param data new bytes to hash + * @param crcAccum the already accumulated checksum + **/ +static inline void crc_accumulate_buffer(uint16_t *crcAccum, const char *pBuffer, uint8_t length) +{ + const uint8_t *p = (const uint8_t *)pBuffer; + while (length--) { + crc_accumulate(*p++, crcAccum); + } +} + + + + +#endif /* _CHECKSUM_H_ */ + +#ifdef __cplusplus +} +#endif diff --git a/mavlink/include/mavlink/v0.9/common/common.h b/mavlink/include/mavlink/v0.9/common/common.h new file mode 100644 index 0000000000..84538ed570 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/common.h @@ -0,0 +1,208 @@ +/** @file + * @brief MAVLink comm protocol generated from common.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef COMMON_H +#define COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {3, 4, 8, 14, 8, 28, 3, 32, 0, 2, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 19, 2, 23, 21, 0, 37, 26, 101, 26, 16, 32, 32, 37, 32, 11, 17, 17, 16, 18, 36, 4, 4, 2, 2, 4, 2, 2, 3, 14, 12, 18, 16, 8, 27, 25, 18, 18, 24, 24, 0, 0, 0, 26, 16, 36, 5, 6, 56, 26, 21, 18, 0, 0, 18, 20, 20, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 14, 14, 51, 5} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {72, 39, 190, 92, 191, 217, 104, 119, 0, 219, 60, 186, 10, 0, 0, 0, 0, 0, 0, 0, 89, 159, 162, 121, 0, 149, 222, 110, 179, 136, 66, 126, 185, 147, 112, 252, 162, 215, 229, 128, 9, 106, 101, 213, 4, 229, 21, 214, 215, 14, 206, 50, 157, 126, 108, 213, 95, 5, 127, 0, 0, 0, 57, 126, 130, 119, 193, 191, 236, 158, 143, 0, 0, 104, 123, 131, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 224, 60, 106, 7} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, MAVLINK_MESSAGE_INFO_BOOT, MAVLINK_MESSAGE_INFO_SYSTEM_TIME, MAVLINK_MESSAGE_INFO_PING, MAVLINK_MESSAGE_INFO_SYSTEM_TIME_UTC, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK, MAVLINK_MESSAGE_INFO_AUTH_KEY, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_ACTION_ACK, MAVLINK_MESSAGE_INFO_ACTION, MAVLINK_MESSAGE_INFO_SET_MODE, MAVLINK_MESSAGE_INFO_SET_NAV_MODE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST, MAVLINK_MESSAGE_INFO_PARAM_VALUE, MAVLINK_MESSAGE_INFO_PARAM_SET, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_GPS_RAW_INT, MAVLINK_MESSAGE_INFO_SCALED_IMU, MAVLINK_MESSAGE_INFO_GPS_STATUS, MAVLINK_MESSAGE_INFO_RAW_IMU, MAVLINK_MESSAGE_INFO_RAW_PRESSURE, MAVLINK_MESSAGE_INFO_ATTITUDE, MAVLINK_MESSAGE_INFO_LOCAL_POSITION, MAVLINK_MESSAGE_INFO_GPS_RAW, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION, MAVLINK_MESSAGE_INFO_SYS_STATUS, MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW, MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED, MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW, MAVLINK_MESSAGE_INFO_SCALED_PRESSURE, MAVLINK_MESSAGE_INFO_WAYPOINT, MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST, MAVLINK_MESSAGE_INFO_WAYPOINT_SET_CURRENT, MAVLINK_MESSAGE_INFO_WAYPOINT_CURRENT, MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST_LIST, MAVLINK_MESSAGE_INFO_WAYPOINT_COUNT, MAVLINK_MESSAGE_INFO_WAYPOINT_CLEAR_ALL, MAVLINK_MESSAGE_INFO_WAYPOINT_REACHED, MAVLINK_MESSAGE_INFO_WAYPOINT_ACK, MAVLINK_MESSAGE_INFO_GPS_SET_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_GPS_LOCAL_ORIGIN_SET, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT_SET, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_CONTROL_STATUS, MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT, MAVLINK_MESSAGE_INFO_POSITION_TARGET, MAVLINK_MESSAGE_INFO_STATE_CORRECTION, MAVLINK_MESSAGE_INFO_SET_ALTITUDE, MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM, MAVLINK_MESSAGE_INFO_HIL_STATE, MAVLINK_MESSAGE_INFO_HIL_CONTROLS, MAVLINK_MESSAGE_INFO_MANUAL_CONTROL, MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT, MAVLINK_MESSAGE_INFO_VFR_HUD, MAVLINK_MESSAGE_INFO_COMMAND, MAVLINK_MESSAGE_INFO_COMMAND_ACK, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OPTICAL_FLOW, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OBJECT_DETECTION_EVENT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_DEBUG_VECT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT, MAVLINK_MESSAGE_INFO_STATUSTEXT, MAVLINK_MESSAGE_INFO_DEBUG} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_COMMON + + + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +// ENUM DEFINITIONS + + +/** @brief Commands to be executed by the MAV. They can be executed on user request, + or as part of a mission script. If the action is used in a mission, the parameter mapping + to the waypoint/mission message is as follows: + Param 1, Param 2, Param 3, Param 4, X: Param 5, Y:Param 6, Z:Param 7. This command list is similar what + ARINC 424 is for commercial aircraft: A data format how to interpret waypoint/mission data. */ +#ifndef HAVE_ENUM_MAV_CMD +#define HAVE_ENUM_MAV_CMD +enum MAV_CMD +{ + MAV_CMD_NAV_WAYPOINT=16, /* Navigate to waypoint. |Hold time in decimal seconds. (ignored by fixed wing, time to stay at waypoint for rotary wing)| Acceptance radius in meters (if the sphere with this radius is hit, the waypoint counts as reached)| 0 to pass through the WP, if > 0 radius in meters to pass by WP. Positive value for clockwise orbit, negative value for counter-clockwise orbit. Allows trajectory control.| Desired yaw angle at waypoint (rotary wing)| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_UNLIM=17, /* Loiter around this waypoint an unlimited amount of time |Empty| Empty| Radius around waypoint, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_TURNS=18, /* Loiter around this waypoint for X turns |Turns| Empty| Radius around waypoint, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_TIME=19, /* Loiter around this waypoint for X seconds |Seconds (decimal)| Empty| Radius around waypoint, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_RETURN_TO_LAUNCH=20, /* Return to launch location |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_NAV_LAND=21, /* Land at location |Empty| Empty| Empty| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_TAKEOFF=22, /* Takeoff from ground / hand |Minimum pitch (if airspeed sensor present), desired pitch without sensor| Empty| Empty| Yaw angle (if magnetometer present), ignored without magnetometer| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_ROI=80, /* Sets the region of interest (ROI) for a sensor set or the + vehicle itself. This can then be used by the vehicles control + system to control the vehicle attitude and the attitude of various + sensors such as cameras. |Region of intereset mode. (see MAV_ROI enum)| Waypoint index/ target ID. (see MAV_ROI enum)| ROI index (allows a vehicle to manage multiple ROI's)| Empty| x the location of the fixed ROI (see MAV_FRAME)| y| z| */ + MAV_CMD_NAV_PATHPLANNING=81, /* Control autonomous path planning on the MAV. |0: Disable local obstacle avoidance / local path planning (without resetting map), 1: Enable local path planning, 2: Enable and reset local path planning| 0: Disable full path planning (without resetting map), 1: Enable, 2: Enable and reset map/occupancy grid, 3: Enable and reset planned route, but not occupancy grid| Empty| Yaw angle at goal, in compass degrees, [0..360]| Latitude/X of goal| Longitude/Y of goal| Altitude/Z of goal| */ + MAV_CMD_NAV_LAST=95, /* NOP - This command is only used to mark the upper limit of the NAV/ACTION commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_DELAY=112, /* Delay mission state machine. |Delay in seconds (decimal)| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_CHANGE_ALT=113, /* Ascend/descend at rate. Delay mission state machine until desired altitude reached. |Descent / Ascend rate (m/s)| Empty| Empty| Empty| Empty| Empty| Finish Altitude| */ + MAV_CMD_CONDITION_DISTANCE=114, /* Delay mission state machine until within desired distance of next NAV point. |Distance (meters)| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_YAW=115, /* Reach a certain target angle. |target angle: [0-360], 0 is north| speed during yaw change:[deg per second]| direction: negative: counter clockwise, positive: clockwise [-1,1]| relative offset or absolute angle: [ 1,0]| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_LAST=159, /* NOP - This command is only used to mark the upper limit of the CONDITION commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_MODE=176, /* Set system mode. |Mode, as defined by ENUM MAV_MODE| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_JUMP=177, /* Jump to the desired command in the mission list. Repeat this action only the specified number of times |Sequence number| Repeat count| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_CHANGE_SPEED=178, /* Change speed and/or throttle set points. |Speed type (0=Airspeed, 1=Ground Speed)| Speed (m/s, -1 indicates no change)| Throttle ( Percent, -1 indicates no change)| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_HOME=179, /* Changes the home location either to the current location or a specified location. |Use current (1=use current location, 0=use specified location)| Empty| Empty| Empty| Latitude| Longitude| Altitude| */ + MAV_CMD_DO_SET_PARAMETER=180, /* Set a system parameter. Caution! Use of this command requires knowledge of the numeric enumeration value of the parameter. |Parameter number| Parameter value| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_RELAY=181, /* Set a relay to a condition. |Relay number| Setting (1=on, 0=off, others possible depending on system hardware)| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_REPEAT_RELAY=182, /* Cycle a relay on and off for a desired number of cyles with a desired period. |Relay number| Cycle count| Cycle time (seconds, decimal)| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_SERVO=183, /* Set a servo to a desired PWM value. |Servo number| PWM (microseconds, 1000 to 2000 typical)| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_REPEAT_SERVO=184, /* Cycle a between its nominal setting and a desired PWM for a desired number of cycles with a desired period. |Servo number| PWM (microseconds, 1000 to 2000 typical)| Cycle count| Cycle time (seconds)| Empty| Empty| Empty| */ + MAV_CMD_DO_CONTROL_VIDEO=200, /* Control onboard camera capturing. |Camera ID (-1 for all)| Transmission: 0: disabled, 1: enabled compressed, 2: enabled raw| Transmission mode: 0: video stream, >0: single images every n seconds (decimal)| Recording: 0: disabled, 1: enabled compressed, 2: enabled raw| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_ROI=201, /* Sets the region of interest (ROI) for a sensor set or the + vehicle itself. This can then be used by the vehicles control + system to control the vehicle attitude and the attitude of various + devices such as cameras. + |Region of interest mode. (see MAV_ROI enum)| Waypoint index/ target ID. (see MAV_ROI enum)| ROI index (allows a vehicle to manage multiple cameras etc.)| Empty| x the location of the fixed ROI (see MAV_FRAME)| y| z| */ + MAV_CMD_DO_LAST=240, /* NOP - This command is only used to mark the upper limit of the DO commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_PREFLIGHT_CALIBRATION=241, /* Trigger calibration. This command will be only accepted if in pre-flight mode. |Gyro calibration: 0: no, 1: yes| Magnetometer calibration: 0: no, 1: yes| Ground pressure: 0: no, 1: yes| Radio calibration: 0: no, 1: yes| Empty| Empty| Empty| */ + MAV_CMD_PREFLIGHT_STORAGE=245, /* Request storage of different parameter values and logs. This command will be only accepted if in pre-flight mode. |Parameter storage: 0: READ FROM FLASH/EEPROM, 1: WRITE CURRENT TO FLASH/EEPROM| Mission storage: 0: READ FROM FLASH/EEPROM, 1: WRITE CURRENT TO FLASH/EEPROM| Reserved| Reserved| Empty| Empty| Empty| */ + MAV_CMD_ENUM_END=246, /* | */ +}; +#endif + +/** @brief Data stream IDs. A data stream is not a fixed set of messages, but rather a + recommendation to the autopilot software. Individual autopilots may or may not obey + the recommended messages. + */ +#ifndef HAVE_ENUM_MAV_DATA_STREAM +#define HAVE_ENUM_MAV_DATA_STREAM +enum MAV_DATA_STREAM +{ + MAV_DATA_STREAM_ALL=0, /* Enable all data streams | */ + MAV_DATA_STREAM_RAW_SENSORS=1, /* Enable IMU_RAW, GPS_RAW, GPS_STATUS packets. | */ + MAV_DATA_STREAM_EXTENDED_STATUS=2, /* Enable GPS_STATUS, CONTROL_STATUS, AUX_STATUS | */ + MAV_DATA_STREAM_RC_CHANNELS=3, /* Enable RC_CHANNELS_SCALED, RC_CHANNELS_RAW, SERVO_OUTPUT_RAW | */ + MAV_DATA_STREAM_RAW_CONTROLLER=4, /* Enable ATTITUDE_CONTROLLER_OUTPUT, POSITION_CONTROLLER_OUTPUT, NAV_CONTROLLER_OUTPUT. | */ + MAV_DATA_STREAM_POSITION=6, /* Enable LOCAL_POSITION, GLOBAL_POSITION/GLOBAL_POSITION_INT messages. | */ + MAV_DATA_STREAM_EXTRA1=10, /* Dependent on the autopilot | */ + MAV_DATA_STREAM_EXTRA2=11, /* Dependent on the autopilot | */ + MAV_DATA_STREAM_EXTRA3=12, /* Dependent on the autopilot | */ + MAV_DATA_STREAM_ENUM_END=13, /* | */ +}; +#endif + +/** @brief The ROI (region of interest) for the vehicle. This can be + be used by the vehicle for camera/vehicle attitude alignment (see + MAV_CMD_NAV_ROI). + */ +#ifndef HAVE_ENUM_MAV_ROI +#define HAVE_ENUM_MAV_ROI +enum MAV_ROI +{ + MAV_ROI_NONE=0, /* No region of interest. | */ + MAV_ROI_WPNEXT=1, /* Point toward next waypoint. | */ + MAV_ROI_WPINDEX=2, /* Point toward given waypoint. | */ + MAV_ROI_LOCATION=3, /* Point toward fixed location. | */ + MAV_ROI_TARGET=4, /* Point toward of given id. | */ + MAV_ROI_ENUM_END=5, /* | */ +}; +#endif + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_heartbeat.h" +#include "./mavlink_msg_boot.h" +#include "./mavlink_msg_system_time.h" +#include "./mavlink_msg_ping.h" +#include "./mavlink_msg_system_time_utc.h" +#include "./mavlink_msg_change_operator_control.h" +#include "./mavlink_msg_change_operator_control_ack.h" +#include "./mavlink_msg_auth_key.h" +#include "./mavlink_msg_action_ack.h" +#include "./mavlink_msg_action.h" +#include "./mavlink_msg_set_mode.h" +#include "./mavlink_msg_set_nav_mode.h" +#include "./mavlink_msg_param_request_read.h" +#include "./mavlink_msg_param_request_list.h" +#include "./mavlink_msg_param_value.h" +#include "./mavlink_msg_param_set.h" +#include "./mavlink_msg_gps_raw_int.h" +#include "./mavlink_msg_scaled_imu.h" +#include "./mavlink_msg_gps_status.h" +#include "./mavlink_msg_raw_imu.h" +#include "./mavlink_msg_raw_pressure.h" +#include "./mavlink_msg_scaled_pressure.h" +#include "./mavlink_msg_attitude.h" +#include "./mavlink_msg_local_position.h" +#include "./mavlink_msg_global_position.h" +#include "./mavlink_msg_gps_raw.h" +#include "./mavlink_msg_sys_status.h" +#include "./mavlink_msg_rc_channels_raw.h" +#include "./mavlink_msg_rc_channels_scaled.h" +#include "./mavlink_msg_servo_output_raw.h" +#include "./mavlink_msg_waypoint.h" +#include "./mavlink_msg_waypoint_request.h" +#include "./mavlink_msg_waypoint_set_current.h" +#include "./mavlink_msg_waypoint_current.h" +#include "./mavlink_msg_waypoint_request_list.h" +#include "./mavlink_msg_waypoint_count.h" +#include "./mavlink_msg_waypoint_clear_all.h" +#include "./mavlink_msg_waypoint_reached.h" +#include "./mavlink_msg_waypoint_ack.h" +#include "./mavlink_msg_gps_set_global_origin.h" +#include "./mavlink_msg_gps_local_origin_set.h" +#include "./mavlink_msg_local_position_setpoint_set.h" +#include "./mavlink_msg_local_position_setpoint.h" +#include "./mavlink_msg_control_status.h" +#include "./mavlink_msg_safety_set_allowed_area.h" +#include "./mavlink_msg_safety_allowed_area.h" +#include "./mavlink_msg_set_roll_pitch_yaw_thrust.h" +#include "./mavlink_msg_set_roll_pitch_yaw_speed_thrust.h" +#include "./mavlink_msg_roll_pitch_yaw_thrust_setpoint.h" +#include "./mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint.h" +#include "./mavlink_msg_nav_controller_output.h" +#include "./mavlink_msg_position_target.h" +#include "./mavlink_msg_state_correction.h" +#include "./mavlink_msg_set_altitude.h" +#include "./mavlink_msg_request_data_stream.h" +#include "./mavlink_msg_hil_state.h" +#include "./mavlink_msg_hil_controls.h" +#include "./mavlink_msg_manual_control.h" +#include "./mavlink_msg_rc_channels_override.h" +#include "./mavlink_msg_global_position_int.h" +#include "./mavlink_msg_vfr_hud.h" +#include "./mavlink_msg_command.h" +#include "./mavlink_msg_command_ack.h" +#include "./mavlink_msg_optical_flow.h" +#include "./mavlink_msg_object_detection_event.h" +#include "./mavlink_msg_debug_vect.h" +#include "./mavlink_msg_named_value_float.h" +#include "./mavlink_msg_named_value_int.h" +#include "./mavlink_msg_statustext.h" +#include "./mavlink_msg_debug.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // COMMON_H diff --git a/mavlink/include/mavlink/v0.9/common/mavlink.h b/mavlink/include/mavlink/v0.9/common/mavlink.h new file mode 100644 index 0000000000..02ff5bd392 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink.h @@ -0,0 +1,27 @@ +/** @file + * @brief MAVLink comm protocol built from common.xml + * @see http://pixhawk.ethz.ch/software/mavlink + */ +#ifndef MAVLINK_H +#define MAVLINK_H + +#ifndef MAVLINK_STX +#define MAVLINK_STX 85 +#endif + +#ifndef MAVLINK_ENDIAN +#define MAVLINK_ENDIAN MAVLINK_BIG_ENDIAN +#endif + +#ifndef MAVLINK_ALIGNED_FIELDS +#define MAVLINK_ALIGNED_FIELDS 0 +#endif + +#ifndef MAVLINK_CRC_EXTRA +#define MAVLINK_CRC_EXTRA 0 +#endif + +#include "version.h" +#include "common.h" + +#endif // MAVLINK_H diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_action.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_action.h new file mode 100644 index 0000000000..ada9aa7a29 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_action.h @@ -0,0 +1,188 @@ +// MESSAGE ACTION PACKING + +#define MAVLINK_MSG_ID_ACTION 10 + +typedef struct __mavlink_action_t +{ + uint8_t target; ///< The system executing the action + uint8_t target_component; ///< The component executing the action + uint8_t action; ///< The action id +} mavlink_action_t; + +#define MAVLINK_MSG_ID_ACTION_LEN 3 +#define MAVLINK_MSG_ID_10_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_ACTION { \ + "ACTION", \ + 3, \ + { { "target", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_action_t, target) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_action_t, target_component) }, \ + { "action", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_action_t, action) }, \ + } \ +} + + +/** + * @brief Pack a action message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target The system executing the action + * @param target_component The component executing the action + * @param action The action id + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_action_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target, uint8_t target_component, uint8_t action) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, action); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_action_t packet; + packet.target = target; + packet.target_component = target_component; + packet.action = action; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_ACTION; + return mavlink_finalize_message(msg, system_id, component_id, 3); +} + +/** + * @brief Pack a action message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system executing the action + * @param target_component The component executing the action + * @param action The action id + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_action_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,uint8_t target_component,uint8_t action) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, action); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_action_t packet; + packet.target = target; + packet.target_component = target_component; + packet.action = action; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_ACTION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3); +} + +/** + * @brief Encode a action struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param action C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_action_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_action_t* action) +{ + return mavlink_msg_action_pack(system_id, component_id, msg, action->target, action->target_component, action->action); +} + +/** + * @brief Send a action message + * @param chan MAVLink channel to send the message + * + * @param target The system executing the action + * @param target_component The component executing the action + * @param action The action id + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_action_send(mavlink_channel_t chan, uint8_t target, uint8_t target_component, uint8_t action) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, action); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ACTION, buf, 3); +#else + mavlink_action_t packet; + packet.target = target; + packet.target_component = target_component; + packet.action = action; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ACTION, (const char *)&packet, 3); +#endif +} + +#endif + +// MESSAGE ACTION UNPACKING + + +/** + * @brief Get field target from action message + * + * @return The system executing the action + */ +static inline uint8_t mavlink_msg_action_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from action message + * + * @return The component executing the action + */ +static inline uint8_t mavlink_msg_action_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field action from action message + * + * @return The action id + */ +static inline uint8_t mavlink_msg_action_get_action(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a action message into a struct + * + * @param msg The message to decode + * @param action C-struct to decode the message contents into + */ +static inline void mavlink_msg_action_decode(const mavlink_message_t* msg, mavlink_action_t* action) +{ +#if MAVLINK_NEED_BYTE_SWAP + action->target = mavlink_msg_action_get_target(msg); + action->target_component = mavlink_msg_action_get_target_component(msg); + action->action = mavlink_msg_action_get_action(msg); +#else + memcpy(action, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_action_ack.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_action_ack.h new file mode 100644 index 0000000000..a87b35b599 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_action_ack.h @@ -0,0 +1,166 @@ +// MESSAGE ACTION_ACK PACKING + +#define MAVLINK_MSG_ID_ACTION_ACK 9 + +typedef struct __mavlink_action_ack_t +{ + uint8_t action; ///< The action id + uint8_t result; ///< 0: Action DENIED, 1: Action executed +} mavlink_action_ack_t; + +#define MAVLINK_MSG_ID_ACTION_ACK_LEN 2 +#define MAVLINK_MSG_ID_9_LEN 2 + + + +#define MAVLINK_MESSAGE_INFO_ACTION_ACK { \ + "ACTION_ACK", \ + 2, \ + { { "action", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_action_ack_t, action) }, \ + { "result", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_action_ack_t, result) }, \ + } \ +} + + +/** + * @brief Pack a action_ack message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param action The action id + * @param result 0: Action DENIED, 1: Action executed + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_action_ack_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t action, uint8_t result) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, action); + _mav_put_uint8_t(buf, 1, result); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_action_ack_t packet; + packet.action = action; + packet.result = result; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_ACTION_ACK; + return mavlink_finalize_message(msg, system_id, component_id, 2); +} + +/** + * @brief Pack a action_ack message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param action The action id + * @param result 0: Action DENIED, 1: Action executed + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_action_ack_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t action,uint8_t result) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, action); + _mav_put_uint8_t(buf, 1, result); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_action_ack_t packet; + packet.action = action; + packet.result = result; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_ACTION_ACK; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 2); +} + +/** + * @brief Encode a action_ack struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param action_ack C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_action_ack_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_action_ack_t* action_ack) +{ + return mavlink_msg_action_ack_pack(system_id, component_id, msg, action_ack->action, action_ack->result); +} + +/** + * @brief Send a action_ack message + * @param chan MAVLink channel to send the message + * + * @param action The action id + * @param result 0: Action DENIED, 1: Action executed + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_action_ack_send(mavlink_channel_t chan, uint8_t action, uint8_t result) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, action); + _mav_put_uint8_t(buf, 1, result); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ACTION_ACK, buf, 2); +#else + mavlink_action_ack_t packet; + packet.action = action; + packet.result = result; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ACTION_ACK, (const char *)&packet, 2); +#endif +} + +#endif + +// MESSAGE ACTION_ACK UNPACKING + + +/** + * @brief Get field action from action_ack message + * + * @return The action id + */ +static inline uint8_t mavlink_msg_action_ack_get_action(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field result from action_ack message + * + * @return 0: Action DENIED, 1: Action executed + */ +static inline uint8_t mavlink_msg_action_ack_get_result(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Decode a action_ack message into a struct + * + * @param msg The message to decode + * @param action_ack C-struct to decode the message contents into + */ +static inline void mavlink_msg_action_ack_decode(const mavlink_message_t* msg, mavlink_action_ack_t* action_ack) +{ +#if MAVLINK_NEED_BYTE_SWAP + action_ack->action = mavlink_msg_action_ack_get_action(msg); + action_ack->result = mavlink_msg_action_ack_get_result(msg); +#else + memcpy(action_ack, _MAV_PAYLOAD(msg), 2); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_attitude.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_attitude.h new file mode 100644 index 0000000000..188f1eb0ff --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_attitude.h @@ -0,0 +1,276 @@ +// MESSAGE ATTITUDE PACKING + +#define MAVLINK_MSG_ID_ATTITUDE 30 + +typedef struct __mavlink_attitude_t +{ + uint64_t usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + float roll; ///< Roll angle (rad) + float pitch; ///< Pitch angle (rad) + float yaw; ///< Yaw angle (rad) + float rollspeed; ///< Roll angular speed (rad/s) + float pitchspeed; ///< Pitch angular speed (rad/s) + float yawspeed; ///< Yaw angular speed (rad/s) +} mavlink_attitude_t; + +#define MAVLINK_MSG_ID_ATTITUDE_LEN 32 +#define MAVLINK_MSG_ID_30_LEN 32 + + + +#define MAVLINK_MESSAGE_INFO_ATTITUDE { \ + "ATTITUDE", \ + 7, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_attitude_t, usec) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_attitude_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_attitude_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_attitude_t, yaw) }, \ + { "rollspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_attitude_t, rollspeed) }, \ + { "pitchspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_attitude_t, pitchspeed) }, \ + { "yawspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_attitude_t, yawspeed) }, \ + } \ +} + + +/** + * @brief Pack a attitude message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_attitude_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, float roll, float pitch, float yaw, float rollspeed, float pitchspeed, float yawspeed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, roll); + _mav_put_float(buf, 12, pitch); + _mav_put_float(buf, 16, yaw); + _mav_put_float(buf, 20, rollspeed); + _mav_put_float(buf, 24, pitchspeed); + _mav_put_float(buf, 28, yawspeed); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_attitude_t packet; + packet.usec = usec; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_ATTITUDE; + return mavlink_finalize_message(msg, system_id, component_id, 32); +} + +/** + * @brief Pack a attitude message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_attitude_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float roll,float pitch,float yaw,float rollspeed,float pitchspeed,float yawspeed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, roll); + _mav_put_float(buf, 12, pitch); + _mav_put_float(buf, 16, yaw); + _mav_put_float(buf, 20, rollspeed); + _mav_put_float(buf, 24, pitchspeed); + _mav_put_float(buf, 28, yawspeed); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_attitude_t packet; + packet.usec = usec; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_ATTITUDE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32); +} + +/** + * @brief Encode a attitude struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param attitude C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_attitude_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_attitude_t* attitude) +{ + return mavlink_msg_attitude_pack(system_id, component_id, msg, attitude->usec, attitude->roll, attitude->pitch, attitude->yaw, attitude->rollspeed, attitude->pitchspeed, attitude->yawspeed); +} + +/** + * @brief Send a attitude message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_attitude_send(mavlink_channel_t chan, uint64_t usec, float roll, float pitch, float yaw, float rollspeed, float pitchspeed, float yawspeed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, roll); + _mav_put_float(buf, 12, pitch); + _mav_put_float(buf, 16, yaw); + _mav_put_float(buf, 20, rollspeed); + _mav_put_float(buf, 24, pitchspeed); + _mav_put_float(buf, 28, yawspeed); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ATTITUDE, buf, 32); +#else + mavlink_attitude_t packet; + packet.usec = usec; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ATTITUDE, (const char *)&packet, 32); +#endif +} + +#endif + +// MESSAGE ATTITUDE UNPACKING + + +/** + * @brief Get field usec from attitude message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_attitude_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field roll from attitude message + * + * @return Roll angle (rad) + */ +static inline float mavlink_msg_attitude_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field pitch from attitude message + * + * @return Pitch angle (rad) + */ +static inline float mavlink_msg_attitude_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field yaw from attitude message + * + * @return Yaw angle (rad) + */ +static inline float mavlink_msg_attitude_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field rollspeed from attitude message + * + * @return Roll angular speed (rad/s) + */ +static inline float mavlink_msg_attitude_get_rollspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field pitchspeed from attitude message + * + * @return Pitch angular speed (rad/s) + */ +static inline float mavlink_msg_attitude_get_pitchspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field yawspeed from attitude message + * + * @return Yaw angular speed (rad/s) + */ +static inline float mavlink_msg_attitude_get_yawspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Decode a attitude message into a struct + * + * @param msg The message to decode + * @param attitude C-struct to decode the message contents into + */ +static inline void mavlink_msg_attitude_decode(const mavlink_message_t* msg, mavlink_attitude_t* attitude) +{ +#if MAVLINK_NEED_BYTE_SWAP + attitude->usec = mavlink_msg_attitude_get_usec(msg); + attitude->roll = mavlink_msg_attitude_get_roll(msg); + attitude->pitch = mavlink_msg_attitude_get_pitch(msg); + attitude->yaw = mavlink_msg_attitude_get_yaw(msg); + attitude->rollspeed = mavlink_msg_attitude_get_rollspeed(msg); + attitude->pitchspeed = mavlink_msg_attitude_get_pitchspeed(msg); + attitude->yawspeed = mavlink_msg_attitude_get_yawspeed(msg); +#else + memcpy(attitude, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_auth_key.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_auth_key.h new file mode 100644 index 0000000000..c451444eac --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_auth_key.h @@ -0,0 +1,144 @@ +// MESSAGE AUTH_KEY PACKING + +#define MAVLINK_MSG_ID_AUTH_KEY 7 + +typedef struct __mavlink_auth_key_t +{ + char key[32]; ///< key +} mavlink_auth_key_t; + +#define MAVLINK_MSG_ID_AUTH_KEY_LEN 32 +#define MAVLINK_MSG_ID_7_LEN 32 + +#define MAVLINK_MSG_AUTH_KEY_FIELD_KEY_LEN 32 + +#define MAVLINK_MESSAGE_INFO_AUTH_KEY { \ + "AUTH_KEY", \ + 1, \ + { { "key", NULL, MAVLINK_TYPE_CHAR, 32, 0, offsetof(mavlink_auth_key_t, key) }, \ + } \ +} + + +/** + * @brief Pack a auth_key message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param key key + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_auth_key_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const char *key) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + + _mav_put_char_array(buf, 0, key, 32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_auth_key_t packet; + + mav_array_memcpy(packet.key, key, sizeof(char)*32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_AUTH_KEY; + return mavlink_finalize_message(msg, system_id, component_id, 32); +} + +/** + * @brief Pack a auth_key message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param key key + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_auth_key_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const char *key) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + + _mav_put_char_array(buf, 0, key, 32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_auth_key_t packet; + + mav_array_memcpy(packet.key, key, sizeof(char)*32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_AUTH_KEY; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32); +} + +/** + * @brief Encode a auth_key struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param auth_key C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_auth_key_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_auth_key_t* auth_key) +{ + return mavlink_msg_auth_key_pack(system_id, component_id, msg, auth_key->key); +} + +/** + * @brief Send a auth_key message + * @param chan MAVLink channel to send the message + * + * @param key key + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_auth_key_send(mavlink_channel_t chan, const char *key) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + + _mav_put_char_array(buf, 0, key, 32); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AUTH_KEY, buf, 32); +#else + mavlink_auth_key_t packet; + + mav_array_memcpy(packet.key, key, sizeof(char)*32); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AUTH_KEY, (const char *)&packet, 32); +#endif +} + +#endif + +// MESSAGE AUTH_KEY UNPACKING + + +/** + * @brief Get field key from auth_key message + * + * @return key + */ +static inline uint16_t mavlink_msg_auth_key_get_key(const mavlink_message_t* msg, char *key) +{ + return _MAV_RETURN_char_array(msg, key, 32, 0); +} + +/** + * @brief Decode a auth_key message into a struct + * + * @param msg The message to decode + * @param auth_key C-struct to decode the message contents into + */ +static inline void mavlink_msg_auth_key_decode(const mavlink_message_t* msg, mavlink_auth_key_t* auth_key) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_auth_key_get_key(msg, auth_key->key); +#else + memcpy(auth_key, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_boot.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_boot.h new file mode 100644 index 0000000000..570949bd56 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_boot.h @@ -0,0 +1,144 @@ +// MESSAGE BOOT PACKING + +#define MAVLINK_MSG_ID_BOOT 1 + +typedef struct __mavlink_boot_t +{ + uint32_t version; ///< The onboard software version +} mavlink_boot_t; + +#define MAVLINK_MSG_ID_BOOT_LEN 4 +#define MAVLINK_MSG_ID_1_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_BOOT { \ + "BOOT", \ + 1, \ + { { "version", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_boot_t, version) }, \ + } \ +} + + +/** + * @brief Pack a boot message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param version The onboard software version + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_boot_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t version) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint32_t(buf, 0, version); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_boot_t packet; + packet.version = version; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_BOOT; + return mavlink_finalize_message(msg, system_id, component_id, 4); +} + +/** + * @brief Pack a boot message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param version The onboard software version + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_boot_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t version) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint32_t(buf, 0, version); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_boot_t packet; + packet.version = version; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_BOOT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4); +} + +/** + * @brief Encode a boot struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param boot C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_boot_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_boot_t* boot) +{ + return mavlink_msg_boot_pack(system_id, component_id, msg, boot->version); +} + +/** + * @brief Send a boot message + * @param chan MAVLink channel to send the message + * + * @param version The onboard software version + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_boot_send(mavlink_channel_t chan, uint32_t version) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint32_t(buf, 0, version); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_BOOT, buf, 4); +#else + mavlink_boot_t packet; + packet.version = version; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_BOOT, (const char *)&packet, 4); +#endif +} + +#endif + +// MESSAGE BOOT UNPACKING + + +/** + * @brief Get field version from boot message + * + * @return The onboard software version + */ +static inline uint32_t mavlink_msg_boot_get_version(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Decode a boot message into a struct + * + * @param msg The message to decode + * @param boot C-struct to decode the message contents into + */ +static inline void mavlink_msg_boot_decode(const mavlink_message_t* msg, mavlink_boot_t* boot) +{ +#if MAVLINK_NEED_BYTE_SWAP + boot->version = mavlink_msg_boot_get_version(msg); +#else + memcpy(boot, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_change_operator_control.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_change_operator_control.h new file mode 100644 index 0000000000..8fad932ea8 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_change_operator_control.h @@ -0,0 +1,204 @@ +// MESSAGE CHANGE_OPERATOR_CONTROL PACKING + +#define MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL 5 + +typedef struct __mavlink_change_operator_control_t +{ + uint8_t target_system; ///< System the GCS requests control for + uint8_t control_request; ///< 0: request control of this MAV, 1: Release control of this MAV + uint8_t version; ///< 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. + char passkey[25]; ///< Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" +} mavlink_change_operator_control_t; + +#define MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_LEN 28 +#define MAVLINK_MSG_ID_5_LEN 28 + +#define MAVLINK_MSG_CHANGE_OPERATOR_CONTROL_FIELD_PASSKEY_LEN 25 + +#define MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL { \ + "CHANGE_OPERATOR_CONTROL", \ + 4, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_change_operator_control_t, target_system) }, \ + { "control_request", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_change_operator_control_t, control_request) }, \ + { "version", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_change_operator_control_t, version) }, \ + { "passkey", NULL, MAVLINK_TYPE_CHAR, 25, 3, offsetof(mavlink_change_operator_control_t, passkey) }, \ + } \ +} + + +/** + * @brief Pack a change_operator_control message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System the GCS requests control for + * @param control_request 0: request control of this MAV, 1: Release control of this MAV + * @param version 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. + * @param passkey Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_change_operator_control_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t control_request, uint8_t version, const char *passkey) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, control_request); + _mav_put_uint8_t(buf, 2, version); + _mav_put_char_array(buf, 3, passkey, 25); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_change_operator_control_t packet; + packet.target_system = target_system; + packet.control_request = control_request; + packet.version = version; + mav_array_memcpy(packet.passkey, passkey, sizeof(char)*25); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL; + return mavlink_finalize_message(msg, system_id, component_id, 28); +} + +/** + * @brief Pack a change_operator_control message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System the GCS requests control for + * @param control_request 0: request control of this MAV, 1: Release control of this MAV + * @param version 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. + * @param passkey Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_change_operator_control_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t control_request,uint8_t version,const char *passkey) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, control_request); + _mav_put_uint8_t(buf, 2, version); + _mav_put_char_array(buf, 3, passkey, 25); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_change_operator_control_t packet; + packet.target_system = target_system; + packet.control_request = control_request; + packet.version = version; + mav_array_memcpy(packet.passkey, passkey, sizeof(char)*25); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 28); +} + +/** + * @brief Encode a change_operator_control struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param change_operator_control C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_change_operator_control_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_change_operator_control_t* change_operator_control) +{ + return mavlink_msg_change_operator_control_pack(system_id, component_id, msg, change_operator_control->target_system, change_operator_control->control_request, change_operator_control->version, change_operator_control->passkey); +} + +/** + * @brief Send a change_operator_control message + * @param chan MAVLink channel to send the message + * + * @param target_system System the GCS requests control for + * @param control_request 0: request control of this MAV, 1: Release control of this MAV + * @param version 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. + * @param passkey Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_change_operator_control_send(mavlink_channel_t chan, uint8_t target_system, uint8_t control_request, uint8_t version, const char *passkey) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, control_request); + _mav_put_uint8_t(buf, 2, version); + _mav_put_char_array(buf, 3, passkey, 25); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL, buf, 28); +#else + mavlink_change_operator_control_t packet; + packet.target_system = target_system; + packet.control_request = control_request; + packet.version = version; + mav_array_memcpy(packet.passkey, passkey, sizeof(char)*25); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL, (const char *)&packet, 28); +#endif +} + +#endif + +// MESSAGE CHANGE_OPERATOR_CONTROL UNPACKING + + +/** + * @brief Get field target_system from change_operator_control message + * + * @return System the GCS requests control for + */ +static inline uint8_t mavlink_msg_change_operator_control_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field control_request from change_operator_control message + * + * @return 0: request control of this MAV, 1: Release control of this MAV + */ +static inline uint8_t mavlink_msg_change_operator_control_get_control_request(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field version from change_operator_control message + * + * @return 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. + */ +static inline uint8_t mavlink_msg_change_operator_control_get_version(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field passkey from change_operator_control message + * + * @return Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" + */ +static inline uint16_t mavlink_msg_change_operator_control_get_passkey(const mavlink_message_t* msg, char *passkey) +{ + return _MAV_RETURN_char_array(msg, passkey, 25, 3); +} + +/** + * @brief Decode a change_operator_control message into a struct + * + * @param msg The message to decode + * @param change_operator_control C-struct to decode the message contents into + */ +static inline void mavlink_msg_change_operator_control_decode(const mavlink_message_t* msg, mavlink_change_operator_control_t* change_operator_control) +{ +#if MAVLINK_NEED_BYTE_SWAP + change_operator_control->target_system = mavlink_msg_change_operator_control_get_target_system(msg); + change_operator_control->control_request = mavlink_msg_change_operator_control_get_control_request(msg); + change_operator_control->version = mavlink_msg_change_operator_control_get_version(msg); + mavlink_msg_change_operator_control_get_passkey(msg, change_operator_control->passkey); +#else + memcpy(change_operator_control, _MAV_PAYLOAD(msg), 28); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_change_operator_control_ack.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_change_operator_control_ack.h new file mode 100644 index 0000000000..e9e195bbb9 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_change_operator_control_ack.h @@ -0,0 +1,188 @@ +// MESSAGE CHANGE_OPERATOR_CONTROL_ACK PACKING + +#define MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK 6 + +typedef struct __mavlink_change_operator_control_ack_t +{ + uint8_t gcs_system_id; ///< ID of the GCS this message + uint8_t control_request; ///< 0: request control of this MAV, 1: Release control of this MAV + uint8_t ack; ///< 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control +} mavlink_change_operator_control_ack_t; + +#define MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK_LEN 3 +#define MAVLINK_MSG_ID_6_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK { \ + "CHANGE_OPERATOR_CONTROL_ACK", \ + 3, \ + { { "gcs_system_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_change_operator_control_ack_t, gcs_system_id) }, \ + { "control_request", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_change_operator_control_ack_t, control_request) }, \ + { "ack", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_change_operator_control_ack_t, ack) }, \ + } \ +} + + +/** + * @brief Pack a change_operator_control_ack message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param gcs_system_id ID of the GCS this message + * @param control_request 0: request control of this MAV, 1: Release control of this MAV + * @param ack 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_change_operator_control_ack_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t gcs_system_id, uint8_t control_request, uint8_t ack) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, gcs_system_id); + _mav_put_uint8_t(buf, 1, control_request); + _mav_put_uint8_t(buf, 2, ack); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_change_operator_control_ack_t packet; + packet.gcs_system_id = gcs_system_id; + packet.control_request = control_request; + packet.ack = ack; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK; + return mavlink_finalize_message(msg, system_id, component_id, 3); +} + +/** + * @brief Pack a change_operator_control_ack message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param gcs_system_id ID of the GCS this message + * @param control_request 0: request control of this MAV, 1: Release control of this MAV + * @param ack 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_change_operator_control_ack_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t gcs_system_id,uint8_t control_request,uint8_t ack) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, gcs_system_id); + _mav_put_uint8_t(buf, 1, control_request); + _mav_put_uint8_t(buf, 2, ack); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_change_operator_control_ack_t packet; + packet.gcs_system_id = gcs_system_id; + packet.control_request = control_request; + packet.ack = ack; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3); +} + +/** + * @brief Encode a change_operator_control_ack struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param change_operator_control_ack C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_change_operator_control_ack_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_change_operator_control_ack_t* change_operator_control_ack) +{ + return mavlink_msg_change_operator_control_ack_pack(system_id, component_id, msg, change_operator_control_ack->gcs_system_id, change_operator_control_ack->control_request, change_operator_control_ack->ack); +} + +/** + * @brief Send a change_operator_control_ack message + * @param chan MAVLink channel to send the message + * + * @param gcs_system_id ID of the GCS this message + * @param control_request 0: request control of this MAV, 1: Release control of this MAV + * @param ack 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_change_operator_control_ack_send(mavlink_channel_t chan, uint8_t gcs_system_id, uint8_t control_request, uint8_t ack) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, gcs_system_id); + _mav_put_uint8_t(buf, 1, control_request); + _mav_put_uint8_t(buf, 2, ack); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK, buf, 3); +#else + mavlink_change_operator_control_ack_t packet; + packet.gcs_system_id = gcs_system_id; + packet.control_request = control_request; + packet.ack = ack; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK, (const char *)&packet, 3); +#endif +} + +#endif + +// MESSAGE CHANGE_OPERATOR_CONTROL_ACK UNPACKING + + +/** + * @brief Get field gcs_system_id from change_operator_control_ack message + * + * @return ID of the GCS this message + */ +static inline uint8_t mavlink_msg_change_operator_control_ack_get_gcs_system_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field control_request from change_operator_control_ack message + * + * @return 0: request control of this MAV, 1: Release control of this MAV + */ +static inline uint8_t mavlink_msg_change_operator_control_ack_get_control_request(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field ack from change_operator_control_ack message + * + * @return 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control + */ +static inline uint8_t mavlink_msg_change_operator_control_ack_get_ack(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a change_operator_control_ack message into a struct + * + * @param msg The message to decode + * @param change_operator_control_ack C-struct to decode the message contents into + */ +static inline void mavlink_msg_change_operator_control_ack_decode(const mavlink_message_t* msg, mavlink_change_operator_control_ack_t* change_operator_control_ack) +{ +#if MAVLINK_NEED_BYTE_SWAP + change_operator_control_ack->gcs_system_id = mavlink_msg_change_operator_control_ack_get_gcs_system_id(msg); + change_operator_control_ack->control_request = mavlink_msg_change_operator_control_ack_get_control_request(msg); + change_operator_control_ack->ack = mavlink_msg_change_operator_control_ack_get_ack(msg); +#else + memcpy(change_operator_control_ack, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_command.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_command.h new file mode 100644 index 0000000000..b5d44f8b2b --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_command.h @@ -0,0 +1,298 @@ +// MESSAGE COMMAND PACKING + +#define MAVLINK_MSG_ID_COMMAND 75 + +typedef struct __mavlink_command_t +{ + uint8_t target_system; ///< System which should execute the command + uint8_t target_component; ///< Component which should execute the command, 0 for all components + uint8_t command; ///< Command ID, as defined by MAV_CMD enum. + uint8_t confirmation; ///< 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) + float param1; ///< Parameter 1, as defined by MAV_CMD enum. + float param2; ///< Parameter 2, as defined by MAV_CMD enum. + float param3; ///< Parameter 3, as defined by MAV_CMD enum. + float param4; ///< Parameter 4, as defined by MAV_CMD enum. +} mavlink_command_t; + +#define MAVLINK_MSG_ID_COMMAND_LEN 20 +#define MAVLINK_MSG_ID_75_LEN 20 + + + +#define MAVLINK_MESSAGE_INFO_COMMAND { \ + "COMMAND", \ + 8, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_command_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_command_t, target_component) }, \ + { "command", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_command_t, command) }, \ + { "confirmation", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_command_t, confirmation) }, \ + { "param1", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_command_t, param1) }, \ + { "param2", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_command_t, param2) }, \ + { "param3", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_command_t, param3) }, \ + { "param4", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_command_t, param4) }, \ + } \ +} + + +/** + * @brief Pack a command message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System which should execute the command + * @param target_component Component which should execute the command, 0 for all components + * @param command Command ID, as defined by MAV_CMD enum. + * @param confirmation 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) + * @param param1 Parameter 1, as defined by MAV_CMD enum. + * @param param2 Parameter 2, as defined by MAV_CMD enum. + * @param param3 Parameter 3, as defined by MAV_CMD enum. + * @param param4 Parameter 4, as defined by MAV_CMD enum. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_command_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t command, uint8_t confirmation, float param1, float param2, float param3, float param4) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, command); + _mav_put_uint8_t(buf, 3, confirmation); + _mav_put_float(buf, 4, param1); + _mav_put_float(buf, 8, param2); + _mav_put_float(buf, 12, param3); + _mav_put_float(buf, 16, param4); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_command_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.command = command; + packet.confirmation = confirmation; + packet.param1 = param1; + packet.param2 = param2; + packet.param3 = param3; + packet.param4 = param4; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_COMMAND; + return mavlink_finalize_message(msg, system_id, component_id, 20); +} + +/** + * @brief Pack a command message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System which should execute the command + * @param target_component Component which should execute the command, 0 for all components + * @param command Command ID, as defined by MAV_CMD enum. + * @param confirmation 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) + * @param param1 Parameter 1, as defined by MAV_CMD enum. + * @param param2 Parameter 2, as defined by MAV_CMD enum. + * @param param3 Parameter 3, as defined by MAV_CMD enum. + * @param param4 Parameter 4, as defined by MAV_CMD enum. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_command_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t command,uint8_t confirmation,float param1,float param2,float param3,float param4) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, command); + _mav_put_uint8_t(buf, 3, confirmation); + _mav_put_float(buf, 4, param1); + _mav_put_float(buf, 8, param2); + _mav_put_float(buf, 12, param3); + _mav_put_float(buf, 16, param4); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_command_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.command = command; + packet.confirmation = confirmation; + packet.param1 = param1; + packet.param2 = param2; + packet.param3 = param3; + packet.param4 = param4; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_COMMAND; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 20); +} + +/** + * @brief Encode a command struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param command C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_command_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_command_t* command) +{ + return mavlink_msg_command_pack(system_id, component_id, msg, command->target_system, command->target_component, command->command, command->confirmation, command->param1, command->param2, command->param3, command->param4); +} + +/** + * @brief Send a command message + * @param chan MAVLink channel to send the message + * + * @param target_system System which should execute the command + * @param target_component Component which should execute the command, 0 for all components + * @param command Command ID, as defined by MAV_CMD enum. + * @param confirmation 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) + * @param param1 Parameter 1, as defined by MAV_CMD enum. + * @param param2 Parameter 2, as defined by MAV_CMD enum. + * @param param3 Parameter 3, as defined by MAV_CMD enum. + * @param param4 Parameter 4, as defined by MAV_CMD enum. + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_command_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t command, uint8_t confirmation, float param1, float param2, float param3, float param4) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, command); + _mav_put_uint8_t(buf, 3, confirmation); + _mav_put_float(buf, 4, param1); + _mav_put_float(buf, 8, param2); + _mav_put_float(buf, 12, param3); + _mav_put_float(buf, 16, param4); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_COMMAND, buf, 20); +#else + mavlink_command_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.command = command; + packet.confirmation = confirmation; + packet.param1 = param1; + packet.param2 = param2; + packet.param3 = param3; + packet.param4 = param4; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_COMMAND, (const char *)&packet, 20); +#endif +} + +#endif + +// MESSAGE COMMAND UNPACKING + + +/** + * @brief Get field target_system from command message + * + * @return System which should execute the command + */ +static inline uint8_t mavlink_msg_command_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from command message + * + * @return Component which should execute the command, 0 for all components + */ +static inline uint8_t mavlink_msg_command_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field command from command message + * + * @return Command ID, as defined by MAV_CMD enum. + */ +static inline uint8_t mavlink_msg_command_get_command(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field confirmation from command message + * + * @return 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) + */ +static inline uint8_t mavlink_msg_command_get_confirmation(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field param1 from command message + * + * @return Parameter 1, as defined by MAV_CMD enum. + */ +static inline float mavlink_msg_command_get_param1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field param2 from command message + * + * @return Parameter 2, as defined by MAV_CMD enum. + */ +static inline float mavlink_msg_command_get_param2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field param3 from command message + * + * @return Parameter 3, as defined by MAV_CMD enum. + */ +static inline float mavlink_msg_command_get_param3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field param4 from command message + * + * @return Parameter 4, as defined by MAV_CMD enum. + */ +static inline float mavlink_msg_command_get_param4(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Decode a command message into a struct + * + * @param msg The message to decode + * @param command C-struct to decode the message contents into + */ +static inline void mavlink_msg_command_decode(const mavlink_message_t* msg, mavlink_command_t* command) +{ +#if MAVLINK_NEED_BYTE_SWAP + command->target_system = mavlink_msg_command_get_target_system(msg); + command->target_component = mavlink_msg_command_get_target_component(msg); + command->command = mavlink_msg_command_get_command(msg); + command->confirmation = mavlink_msg_command_get_confirmation(msg); + command->param1 = mavlink_msg_command_get_param1(msg); + command->param2 = mavlink_msg_command_get_param2(msg); + command->param3 = mavlink_msg_command_get_param3(msg); + command->param4 = mavlink_msg_command_get_param4(msg); +#else + memcpy(command, _MAV_PAYLOAD(msg), 20); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_command_ack.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_command_ack.h new file mode 100644 index 0000000000..ee4c89dcfa --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_command_ack.h @@ -0,0 +1,166 @@ +// MESSAGE COMMAND_ACK PACKING + +#define MAVLINK_MSG_ID_COMMAND_ACK 76 + +typedef struct __mavlink_command_ack_t +{ + float command; ///< Current airspeed in m/s + float result; ///< 1: Action ACCEPTED and EXECUTED, 1: Action TEMPORARY REJECTED/DENIED, 2: Action PERMANENTLY DENIED, 3: Action UNKNOWN/UNSUPPORTED, 4: Requesting CONFIRMATION +} mavlink_command_ack_t; + +#define MAVLINK_MSG_ID_COMMAND_ACK_LEN 8 +#define MAVLINK_MSG_ID_76_LEN 8 + + + +#define MAVLINK_MESSAGE_INFO_COMMAND_ACK { \ + "COMMAND_ACK", \ + 2, \ + { { "command", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_command_ack_t, command) }, \ + { "result", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_command_ack_t, result) }, \ + } \ +} + + +/** + * @brief Pack a command_ack message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param command Current airspeed in m/s + * @param result 1: Action ACCEPTED and EXECUTED, 1: Action TEMPORARY REJECTED/DENIED, 2: Action PERMANENTLY DENIED, 3: Action UNKNOWN/UNSUPPORTED, 4: Requesting CONFIRMATION + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_command_ack_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float command, float result) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_float(buf, 0, command); + _mav_put_float(buf, 4, result); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_command_ack_t packet; + packet.command = command; + packet.result = result; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_COMMAND_ACK; + return mavlink_finalize_message(msg, system_id, component_id, 8); +} + +/** + * @brief Pack a command_ack message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param command Current airspeed in m/s + * @param result 1: Action ACCEPTED and EXECUTED, 1: Action TEMPORARY REJECTED/DENIED, 2: Action PERMANENTLY DENIED, 3: Action UNKNOWN/UNSUPPORTED, 4: Requesting CONFIRMATION + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_command_ack_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float command,float result) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_float(buf, 0, command); + _mav_put_float(buf, 4, result); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_command_ack_t packet; + packet.command = command; + packet.result = result; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_COMMAND_ACK; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 8); +} + +/** + * @brief Encode a command_ack struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param command_ack C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_command_ack_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_command_ack_t* command_ack) +{ + return mavlink_msg_command_ack_pack(system_id, component_id, msg, command_ack->command, command_ack->result); +} + +/** + * @brief Send a command_ack message + * @param chan MAVLink channel to send the message + * + * @param command Current airspeed in m/s + * @param result 1: Action ACCEPTED and EXECUTED, 1: Action TEMPORARY REJECTED/DENIED, 2: Action PERMANENTLY DENIED, 3: Action UNKNOWN/UNSUPPORTED, 4: Requesting CONFIRMATION + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_command_ack_send(mavlink_channel_t chan, float command, float result) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_float(buf, 0, command); + _mav_put_float(buf, 4, result); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_COMMAND_ACK, buf, 8); +#else + mavlink_command_ack_t packet; + packet.command = command; + packet.result = result; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_COMMAND_ACK, (const char *)&packet, 8); +#endif +} + +#endif + +// MESSAGE COMMAND_ACK UNPACKING + + +/** + * @brief Get field command from command_ack message + * + * @return Current airspeed in m/s + */ +static inline float mavlink_msg_command_ack_get_command(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field result from command_ack message + * + * @return 1: Action ACCEPTED and EXECUTED, 1: Action TEMPORARY REJECTED/DENIED, 2: Action PERMANENTLY DENIED, 3: Action UNKNOWN/UNSUPPORTED, 4: Requesting CONFIRMATION + */ +static inline float mavlink_msg_command_ack_get_result(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Decode a command_ack message into a struct + * + * @param msg The message to decode + * @param command_ack C-struct to decode the message contents into + */ +static inline void mavlink_msg_command_ack_decode(const mavlink_message_t* msg, mavlink_command_ack_t* command_ack) +{ +#if MAVLINK_NEED_BYTE_SWAP + command_ack->command = mavlink_msg_command_ack_get_command(msg); + command_ack->result = mavlink_msg_command_ack_get_result(msg); +#else + memcpy(command_ack, _MAV_PAYLOAD(msg), 8); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_control_status.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_control_status.h new file mode 100644 index 0000000000..ebc1568cc1 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_control_status.h @@ -0,0 +1,298 @@ +// MESSAGE CONTROL_STATUS PACKING + +#define MAVLINK_MSG_ID_CONTROL_STATUS 52 + +typedef struct __mavlink_control_status_t +{ + uint8_t position_fix; ///< Position fix: 0: lost, 2: 2D position fix, 3: 3D position fix + uint8_t vision_fix; ///< Vision position fix: 0: lost, 1: 2D local position hold, 2: 2D global position fix, 3: 3D global position fix + uint8_t gps_fix; ///< GPS position fix: 0: no reception, 1: Minimum 1 satellite, but no position fix, 2: 2D position fix, 3: 3D position fix + uint8_t ahrs_health; ///< Attitude estimation health: 0: poor, 255: excellent + uint8_t control_att; ///< 0: Attitude control disabled, 1: enabled + uint8_t control_pos_xy; ///< 0: X, Y position control disabled, 1: enabled + uint8_t control_pos_z; ///< 0: Z position control disabled, 1: enabled + uint8_t control_pos_yaw; ///< 0: Yaw angle control disabled, 1: enabled +} mavlink_control_status_t; + +#define MAVLINK_MSG_ID_CONTROL_STATUS_LEN 8 +#define MAVLINK_MSG_ID_52_LEN 8 + + + +#define MAVLINK_MESSAGE_INFO_CONTROL_STATUS { \ + "CONTROL_STATUS", \ + 8, \ + { { "position_fix", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_control_status_t, position_fix) }, \ + { "vision_fix", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_control_status_t, vision_fix) }, \ + { "gps_fix", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_control_status_t, gps_fix) }, \ + { "ahrs_health", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_control_status_t, ahrs_health) }, \ + { "control_att", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_control_status_t, control_att) }, \ + { "control_pos_xy", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_control_status_t, control_pos_xy) }, \ + { "control_pos_z", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_control_status_t, control_pos_z) }, \ + { "control_pos_yaw", NULL, MAVLINK_TYPE_UINT8_T, 0, 7, offsetof(mavlink_control_status_t, control_pos_yaw) }, \ + } \ +} + + +/** + * @brief Pack a control_status message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param position_fix Position fix: 0: lost, 2: 2D position fix, 3: 3D position fix + * @param vision_fix Vision position fix: 0: lost, 1: 2D local position hold, 2: 2D global position fix, 3: 3D global position fix + * @param gps_fix GPS position fix: 0: no reception, 1: Minimum 1 satellite, but no position fix, 2: 2D position fix, 3: 3D position fix + * @param ahrs_health Attitude estimation health: 0: poor, 255: excellent + * @param control_att 0: Attitude control disabled, 1: enabled + * @param control_pos_xy 0: X, Y position control disabled, 1: enabled + * @param control_pos_z 0: Z position control disabled, 1: enabled + * @param control_pos_yaw 0: Yaw angle control disabled, 1: enabled + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_control_status_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t position_fix, uint8_t vision_fix, uint8_t gps_fix, uint8_t ahrs_health, uint8_t control_att, uint8_t control_pos_xy, uint8_t control_pos_z, uint8_t control_pos_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint8_t(buf, 0, position_fix); + _mav_put_uint8_t(buf, 1, vision_fix); + _mav_put_uint8_t(buf, 2, gps_fix); + _mav_put_uint8_t(buf, 3, ahrs_health); + _mav_put_uint8_t(buf, 4, control_att); + _mav_put_uint8_t(buf, 5, control_pos_xy); + _mav_put_uint8_t(buf, 6, control_pos_z); + _mav_put_uint8_t(buf, 7, control_pos_yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_control_status_t packet; + packet.position_fix = position_fix; + packet.vision_fix = vision_fix; + packet.gps_fix = gps_fix; + packet.ahrs_health = ahrs_health; + packet.control_att = control_att; + packet.control_pos_xy = control_pos_xy; + packet.control_pos_z = control_pos_z; + packet.control_pos_yaw = control_pos_yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_CONTROL_STATUS; + return mavlink_finalize_message(msg, system_id, component_id, 8); +} + +/** + * @brief Pack a control_status message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param position_fix Position fix: 0: lost, 2: 2D position fix, 3: 3D position fix + * @param vision_fix Vision position fix: 0: lost, 1: 2D local position hold, 2: 2D global position fix, 3: 3D global position fix + * @param gps_fix GPS position fix: 0: no reception, 1: Minimum 1 satellite, but no position fix, 2: 2D position fix, 3: 3D position fix + * @param ahrs_health Attitude estimation health: 0: poor, 255: excellent + * @param control_att 0: Attitude control disabled, 1: enabled + * @param control_pos_xy 0: X, Y position control disabled, 1: enabled + * @param control_pos_z 0: Z position control disabled, 1: enabled + * @param control_pos_yaw 0: Yaw angle control disabled, 1: enabled + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_control_status_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t position_fix,uint8_t vision_fix,uint8_t gps_fix,uint8_t ahrs_health,uint8_t control_att,uint8_t control_pos_xy,uint8_t control_pos_z,uint8_t control_pos_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint8_t(buf, 0, position_fix); + _mav_put_uint8_t(buf, 1, vision_fix); + _mav_put_uint8_t(buf, 2, gps_fix); + _mav_put_uint8_t(buf, 3, ahrs_health); + _mav_put_uint8_t(buf, 4, control_att); + _mav_put_uint8_t(buf, 5, control_pos_xy); + _mav_put_uint8_t(buf, 6, control_pos_z); + _mav_put_uint8_t(buf, 7, control_pos_yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_control_status_t packet; + packet.position_fix = position_fix; + packet.vision_fix = vision_fix; + packet.gps_fix = gps_fix; + packet.ahrs_health = ahrs_health; + packet.control_att = control_att; + packet.control_pos_xy = control_pos_xy; + packet.control_pos_z = control_pos_z; + packet.control_pos_yaw = control_pos_yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_CONTROL_STATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 8); +} + +/** + * @brief Encode a control_status struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param control_status C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_control_status_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_control_status_t* control_status) +{ + return mavlink_msg_control_status_pack(system_id, component_id, msg, control_status->position_fix, control_status->vision_fix, control_status->gps_fix, control_status->ahrs_health, control_status->control_att, control_status->control_pos_xy, control_status->control_pos_z, control_status->control_pos_yaw); +} + +/** + * @brief Send a control_status message + * @param chan MAVLink channel to send the message + * + * @param position_fix Position fix: 0: lost, 2: 2D position fix, 3: 3D position fix + * @param vision_fix Vision position fix: 0: lost, 1: 2D local position hold, 2: 2D global position fix, 3: 3D global position fix + * @param gps_fix GPS position fix: 0: no reception, 1: Minimum 1 satellite, but no position fix, 2: 2D position fix, 3: 3D position fix + * @param ahrs_health Attitude estimation health: 0: poor, 255: excellent + * @param control_att 0: Attitude control disabled, 1: enabled + * @param control_pos_xy 0: X, Y position control disabled, 1: enabled + * @param control_pos_z 0: Z position control disabled, 1: enabled + * @param control_pos_yaw 0: Yaw angle control disabled, 1: enabled + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_control_status_send(mavlink_channel_t chan, uint8_t position_fix, uint8_t vision_fix, uint8_t gps_fix, uint8_t ahrs_health, uint8_t control_att, uint8_t control_pos_xy, uint8_t control_pos_z, uint8_t control_pos_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint8_t(buf, 0, position_fix); + _mav_put_uint8_t(buf, 1, vision_fix); + _mav_put_uint8_t(buf, 2, gps_fix); + _mav_put_uint8_t(buf, 3, ahrs_health); + _mav_put_uint8_t(buf, 4, control_att); + _mav_put_uint8_t(buf, 5, control_pos_xy); + _mav_put_uint8_t(buf, 6, control_pos_z); + _mav_put_uint8_t(buf, 7, control_pos_yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CONTROL_STATUS, buf, 8); +#else + mavlink_control_status_t packet; + packet.position_fix = position_fix; + packet.vision_fix = vision_fix; + packet.gps_fix = gps_fix; + packet.ahrs_health = ahrs_health; + packet.control_att = control_att; + packet.control_pos_xy = control_pos_xy; + packet.control_pos_z = control_pos_z; + packet.control_pos_yaw = control_pos_yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CONTROL_STATUS, (const char *)&packet, 8); +#endif +} + +#endif + +// MESSAGE CONTROL_STATUS UNPACKING + + +/** + * @brief Get field position_fix from control_status message + * + * @return Position fix: 0: lost, 2: 2D position fix, 3: 3D position fix + */ +static inline uint8_t mavlink_msg_control_status_get_position_fix(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field vision_fix from control_status message + * + * @return Vision position fix: 0: lost, 1: 2D local position hold, 2: 2D global position fix, 3: 3D global position fix + */ +static inline uint8_t mavlink_msg_control_status_get_vision_fix(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field gps_fix from control_status message + * + * @return GPS position fix: 0: no reception, 1: Minimum 1 satellite, but no position fix, 2: 2D position fix, 3: 3D position fix + */ +static inline uint8_t mavlink_msg_control_status_get_gps_fix(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field ahrs_health from control_status message + * + * @return Attitude estimation health: 0: poor, 255: excellent + */ +static inline uint8_t mavlink_msg_control_status_get_ahrs_health(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field control_att from control_status message + * + * @return 0: Attitude control disabled, 1: enabled + */ +static inline uint8_t mavlink_msg_control_status_get_control_att(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field control_pos_xy from control_status message + * + * @return 0: X, Y position control disabled, 1: enabled + */ +static inline uint8_t mavlink_msg_control_status_get_control_pos_xy(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field control_pos_z from control_status message + * + * @return 0: Z position control disabled, 1: enabled + */ +static inline uint8_t mavlink_msg_control_status_get_control_pos_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Get field control_pos_yaw from control_status message + * + * @return 0: Yaw angle control disabled, 1: enabled + */ +static inline uint8_t mavlink_msg_control_status_get_control_pos_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 7); +} + +/** + * @brief Decode a control_status message into a struct + * + * @param msg The message to decode + * @param control_status C-struct to decode the message contents into + */ +static inline void mavlink_msg_control_status_decode(const mavlink_message_t* msg, mavlink_control_status_t* control_status) +{ +#if MAVLINK_NEED_BYTE_SWAP + control_status->position_fix = mavlink_msg_control_status_get_position_fix(msg); + control_status->vision_fix = mavlink_msg_control_status_get_vision_fix(msg); + control_status->gps_fix = mavlink_msg_control_status_get_gps_fix(msg); + control_status->ahrs_health = mavlink_msg_control_status_get_ahrs_health(msg); + control_status->control_att = mavlink_msg_control_status_get_control_att(msg); + control_status->control_pos_xy = mavlink_msg_control_status_get_control_pos_xy(msg); + control_status->control_pos_z = mavlink_msg_control_status_get_control_pos_z(msg); + control_status->control_pos_yaw = mavlink_msg_control_status_get_control_pos_yaw(msg); +#else + memcpy(control_status, _MAV_PAYLOAD(msg), 8); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_debug.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_debug.h new file mode 100644 index 0000000000..5a0fbdd710 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_debug.h @@ -0,0 +1,166 @@ +// MESSAGE DEBUG PACKING + +#define MAVLINK_MSG_ID_DEBUG 255 + +typedef struct __mavlink_debug_t +{ + uint8_t ind; ///< index of debug variable + float value; ///< DEBUG value +} mavlink_debug_t; + +#define MAVLINK_MSG_ID_DEBUG_LEN 5 +#define MAVLINK_MSG_ID_255_LEN 5 + + + +#define MAVLINK_MESSAGE_INFO_DEBUG { \ + "DEBUG", \ + 2, \ + { { "ind", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_debug_t, ind) }, \ + { "value", NULL, MAVLINK_TYPE_FLOAT, 0, 1, offsetof(mavlink_debug_t, value) }, \ + } \ +} + + +/** + * @brief Pack a debug message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param ind index of debug variable + * @param value DEBUG value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_debug_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t ind, float value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[5]; + _mav_put_uint8_t(buf, 0, ind); + _mav_put_float(buf, 1, value); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 5); +#else + mavlink_debug_t packet; + packet.ind = ind; + packet.value = value; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 5); +#endif + + msg->msgid = MAVLINK_MSG_ID_DEBUG; + return mavlink_finalize_message(msg, system_id, component_id, 5); +} + +/** + * @brief Pack a debug message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param ind index of debug variable + * @param value DEBUG value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_debug_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t ind,float value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[5]; + _mav_put_uint8_t(buf, 0, ind); + _mav_put_float(buf, 1, value); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 5); +#else + mavlink_debug_t packet; + packet.ind = ind; + packet.value = value; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 5); +#endif + + msg->msgid = MAVLINK_MSG_ID_DEBUG; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 5); +} + +/** + * @brief Encode a debug struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param debug C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_debug_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_debug_t* debug) +{ + return mavlink_msg_debug_pack(system_id, component_id, msg, debug->ind, debug->value); +} + +/** + * @brief Send a debug message + * @param chan MAVLink channel to send the message + * + * @param ind index of debug variable + * @param value DEBUG value + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_debug_send(mavlink_channel_t chan, uint8_t ind, float value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[5]; + _mav_put_uint8_t(buf, 0, ind); + _mav_put_float(buf, 1, value); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DEBUG, buf, 5); +#else + mavlink_debug_t packet; + packet.ind = ind; + packet.value = value; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DEBUG, (const char *)&packet, 5); +#endif +} + +#endif + +// MESSAGE DEBUG UNPACKING + + +/** + * @brief Get field ind from debug message + * + * @return index of debug variable + */ +static inline uint8_t mavlink_msg_debug_get_ind(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field value from debug message + * + * @return DEBUG value + */ +static inline float mavlink_msg_debug_get_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 1); +} + +/** + * @brief Decode a debug message into a struct + * + * @param msg The message to decode + * @param debug C-struct to decode the message contents into + */ +static inline void mavlink_msg_debug_decode(const mavlink_message_t* msg, mavlink_debug_t* debug) +{ +#if MAVLINK_NEED_BYTE_SWAP + debug->ind = mavlink_msg_debug_get_ind(msg); + debug->value = mavlink_msg_debug_get_value(msg); +#else + memcpy(debug, _MAV_PAYLOAD(msg), 5); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_debug_vect.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_debug_vect.h new file mode 100644 index 0000000000..51895f3bad --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_debug_vect.h @@ -0,0 +1,226 @@ +// MESSAGE DEBUG_VECT PACKING + +#define MAVLINK_MSG_ID_DEBUG_VECT 251 + +typedef struct __mavlink_debug_vect_t +{ + char name[10]; ///< Name + uint64_t usec; ///< Timestamp + float x; ///< x + float y; ///< y + float z; ///< z +} mavlink_debug_vect_t; + +#define MAVLINK_MSG_ID_DEBUG_VECT_LEN 30 +#define MAVLINK_MSG_ID_251_LEN 30 + +#define MAVLINK_MSG_DEBUG_VECT_FIELD_NAME_LEN 10 + +#define MAVLINK_MESSAGE_INFO_DEBUG_VECT { \ + "DEBUG_VECT", \ + 5, \ + { { "name", NULL, MAVLINK_TYPE_CHAR, 10, 0, offsetof(mavlink_debug_vect_t, name) }, \ + { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 10, offsetof(mavlink_debug_vect_t, usec) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 18, offsetof(mavlink_debug_vect_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 22, offsetof(mavlink_debug_vect_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 26, offsetof(mavlink_debug_vect_t, z) }, \ + } \ +} + + +/** + * @brief Pack a debug_vect message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param name Name + * @param usec Timestamp + * @param x x + * @param y y + * @param z z + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_debug_vect_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const char *name, uint64_t usec, float x, float y, float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_uint64_t(buf, 10, usec); + _mav_put_float(buf, 18, x); + _mav_put_float(buf, 22, y); + _mav_put_float(buf, 26, z); + _mav_put_char_array(buf, 0, name, 10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 30); +#else + mavlink_debug_vect_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 30); +#endif + + msg->msgid = MAVLINK_MSG_ID_DEBUG_VECT; + return mavlink_finalize_message(msg, system_id, component_id, 30); +} + +/** + * @brief Pack a debug_vect message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param name Name + * @param usec Timestamp + * @param x x + * @param y y + * @param z z + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_debug_vect_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const char *name,uint64_t usec,float x,float y,float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_uint64_t(buf, 10, usec); + _mav_put_float(buf, 18, x); + _mav_put_float(buf, 22, y); + _mav_put_float(buf, 26, z); + _mav_put_char_array(buf, 0, name, 10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 30); +#else + mavlink_debug_vect_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 30); +#endif + + msg->msgid = MAVLINK_MSG_ID_DEBUG_VECT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 30); +} + +/** + * @brief Encode a debug_vect struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param debug_vect C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_debug_vect_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_debug_vect_t* debug_vect) +{ + return mavlink_msg_debug_vect_pack(system_id, component_id, msg, debug_vect->name, debug_vect->usec, debug_vect->x, debug_vect->y, debug_vect->z); +} + +/** + * @brief Send a debug_vect message + * @param chan MAVLink channel to send the message + * + * @param name Name + * @param usec Timestamp + * @param x x + * @param y y + * @param z z + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_debug_vect_send(mavlink_channel_t chan, const char *name, uint64_t usec, float x, float y, float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_uint64_t(buf, 10, usec); + _mav_put_float(buf, 18, x); + _mav_put_float(buf, 22, y); + _mav_put_float(buf, 26, z); + _mav_put_char_array(buf, 0, name, 10); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DEBUG_VECT, buf, 30); +#else + mavlink_debug_vect_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DEBUG_VECT, (const char *)&packet, 30); +#endif +} + +#endif + +// MESSAGE DEBUG_VECT UNPACKING + + +/** + * @brief Get field name from debug_vect message + * + * @return Name + */ +static inline uint16_t mavlink_msg_debug_vect_get_name(const mavlink_message_t* msg, char *name) +{ + return _MAV_RETURN_char_array(msg, name, 10, 0); +} + +/** + * @brief Get field usec from debug_vect message + * + * @return Timestamp + */ +static inline uint64_t mavlink_msg_debug_vect_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 10); +} + +/** + * @brief Get field x from debug_vect message + * + * @return x + */ +static inline float mavlink_msg_debug_vect_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 18); +} + +/** + * @brief Get field y from debug_vect message + * + * @return y + */ +static inline float mavlink_msg_debug_vect_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 22); +} + +/** + * @brief Get field z from debug_vect message + * + * @return z + */ +static inline float mavlink_msg_debug_vect_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 26); +} + +/** + * @brief Decode a debug_vect message into a struct + * + * @param msg The message to decode + * @param debug_vect C-struct to decode the message contents into + */ +static inline void mavlink_msg_debug_vect_decode(const mavlink_message_t* msg, mavlink_debug_vect_t* debug_vect) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_debug_vect_get_name(msg, debug_vect->name); + debug_vect->usec = mavlink_msg_debug_vect_get_usec(msg); + debug_vect->x = mavlink_msg_debug_vect_get_x(msg); + debug_vect->y = mavlink_msg_debug_vect_get_y(msg); + debug_vect->z = mavlink_msg_debug_vect_get_z(msg); +#else + memcpy(debug_vect, _MAV_PAYLOAD(msg), 30); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_global_position.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_global_position.h new file mode 100644 index 0000000000..5e0b9fe810 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_global_position.h @@ -0,0 +1,276 @@ +// MESSAGE GLOBAL_POSITION PACKING + +#define MAVLINK_MSG_ID_GLOBAL_POSITION 33 + +typedef struct __mavlink_global_position_t +{ + uint64_t usec; ///< Timestamp (microseconds since unix epoch) + float lat; ///< Latitude, in degrees + float lon; ///< Longitude, in degrees + float alt; ///< Absolute altitude, in meters + float vx; ///< X Speed (in Latitude direction, positive: going north) + float vy; ///< Y Speed (in Longitude direction, positive: going east) + float vz; ///< Z Speed (in Altitude direction, positive: going up) +} mavlink_global_position_t; + +#define MAVLINK_MSG_ID_GLOBAL_POSITION_LEN 32 +#define MAVLINK_MSG_ID_33_LEN 32 + + + +#define MAVLINK_MESSAGE_INFO_GLOBAL_POSITION { \ + "GLOBAL_POSITION", \ + 7, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_global_position_t, usec) }, \ + { "lat", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_global_position_t, lat) }, \ + { "lon", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_global_position_t, lon) }, \ + { "alt", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_global_position_t, alt) }, \ + { "vx", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_global_position_t, vx) }, \ + { "vy", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_global_position_t, vy) }, \ + { "vz", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_global_position_t, vz) }, \ + } \ +} + + +/** + * @brief Pack a global_position message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (microseconds since unix epoch) + * @param lat Latitude, in degrees + * @param lon Longitude, in degrees + * @param alt Absolute altitude, in meters + * @param vx X Speed (in Latitude direction, positive: going north) + * @param vy Y Speed (in Longitude direction, positive: going east) + * @param vz Z Speed (in Altitude direction, positive: going up) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_global_position_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, float lat, float lon, float alt, float vx, float vy, float vz) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, lat); + _mav_put_float(buf, 12, lon); + _mav_put_float(buf, 16, alt); + _mav_put_float(buf, 20, vx); + _mav_put_float(buf, 24, vy); + _mav_put_float(buf, 28, vz); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_global_position_t packet; + packet.usec = usec; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_GLOBAL_POSITION; + return mavlink_finalize_message(msg, system_id, component_id, 32); +} + +/** + * @brief Pack a global_position message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (microseconds since unix epoch) + * @param lat Latitude, in degrees + * @param lon Longitude, in degrees + * @param alt Absolute altitude, in meters + * @param vx X Speed (in Latitude direction, positive: going north) + * @param vy Y Speed (in Longitude direction, positive: going east) + * @param vz Z Speed (in Altitude direction, positive: going up) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_global_position_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float lat,float lon,float alt,float vx,float vy,float vz) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, lat); + _mav_put_float(buf, 12, lon); + _mav_put_float(buf, 16, alt); + _mav_put_float(buf, 20, vx); + _mav_put_float(buf, 24, vy); + _mav_put_float(buf, 28, vz); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_global_position_t packet; + packet.usec = usec; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_GLOBAL_POSITION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32); +} + +/** + * @brief Encode a global_position struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param global_position C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_global_position_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_global_position_t* global_position) +{ + return mavlink_msg_global_position_pack(system_id, component_id, msg, global_position->usec, global_position->lat, global_position->lon, global_position->alt, global_position->vx, global_position->vy, global_position->vz); +} + +/** + * @brief Send a global_position message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (microseconds since unix epoch) + * @param lat Latitude, in degrees + * @param lon Longitude, in degrees + * @param alt Absolute altitude, in meters + * @param vx X Speed (in Latitude direction, positive: going north) + * @param vy Y Speed (in Longitude direction, positive: going east) + * @param vz Z Speed (in Altitude direction, positive: going up) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_global_position_send(mavlink_channel_t chan, uint64_t usec, float lat, float lon, float alt, float vx, float vy, float vz) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, lat); + _mav_put_float(buf, 12, lon); + _mav_put_float(buf, 16, alt); + _mav_put_float(buf, 20, vx); + _mav_put_float(buf, 24, vy); + _mav_put_float(buf, 28, vz); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GLOBAL_POSITION, buf, 32); +#else + mavlink_global_position_t packet; + packet.usec = usec; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GLOBAL_POSITION, (const char *)&packet, 32); +#endif +} + +#endif + +// MESSAGE GLOBAL_POSITION UNPACKING + + +/** + * @brief Get field usec from global_position message + * + * @return Timestamp (microseconds since unix epoch) + */ +static inline uint64_t mavlink_msg_global_position_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field lat from global_position message + * + * @return Latitude, in degrees + */ +static inline float mavlink_msg_global_position_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field lon from global_position message + * + * @return Longitude, in degrees + */ +static inline float mavlink_msg_global_position_get_lon(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field alt from global_position message + * + * @return Absolute altitude, in meters + */ +static inline float mavlink_msg_global_position_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field vx from global_position message + * + * @return X Speed (in Latitude direction, positive: going north) + */ +static inline float mavlink_msg_global_position_get_vx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field vy from global_position message + * + * @return Y Speed (in Longitude direction, positive: going east) + */ +static inline float mavlink_msg_global_position_get_vy(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field vz from global_position message + * + * @return Z Speed (in Altitude direction, positive: going up) + */ +static inline float mavlink_msg_global_position_get_vz(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Decode a global_position message into a struct + * + * @param msg The message to decode + * @param global_position C-struct to decode the message contents into + */ +static inline void mavlink_msg_global_position_decode(const mavlink_message_t* msg, mavlink_global_position_t* global_position) +{ +#if MAVLINK_NEED_BYTE_SWAP + global_position->usec = mavlink_msg_global_position_get_usec(msg); + global_position->lat = mavlink_msg_global_position_get_lat(msg); + global_position->lon = mavlink_msg_global_position_get_lon(msg); + global_position->alt = mavlink_msg_global_position_get_alt(msg); + global_position->vx = mavlink_msg_global_position_get_vx(msg); + global_position->vy = mavlink_msg_global_position_get_vy(msg); + global_position->vz = mavlink_msg_global_position_get_vz(msg); +#else + memcpy(global_position, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_global_position_int.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_global_position_int.h new file mode 100644 index 0000000000..859a500499 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_global_position_int.h @@ -0,0 +1,254 @@ +// MESSAGE GLOBAL_POSITION_INT PACKING + +#define MAVLINK_MSG_ID_GLOBAL_POSITION_INT 73 + +typedef struct __mavlink_global_position_int_t +{ + int32_t lat; ///< Latitude, expressed as * 1E7 + int32_t lon; ///< Longitude, expressed as * 1E7 + int32_t alt; ///< Altitude in meters, expressed as * 1000 (millimeters) + int16_t vx; ///< Ground X Speed (Latitude), expressed as m/s * 100 + int16_t vy; ///< Ground Y Speed (Longitude), expressed as m/s * 100 + int16_t vz; ///< Ground Z Speed (Altitude), expressed as m/s * 100 +} mavlink_global_position_int_t; + +#define MAVLINK_MSG_ID_GLOBAL_POSITION_INT_LEN 18 +#define MAVLINK_MSG_ID_73_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT { \ + "GLOBAL_POSITION_INT", \ + 6, \ + { { "lat", NULL, MAVLINK_TYPE_INT32_T, 0, 0, offsetof(mavlink_global_position_int_t, lat) }, \ + { "lon", NULL, MAVLINK_TYPE_INT32_T, 0, 4, offsetof(mavlink_global_position_int_t, lon) }, \ + { "alt", NULL, MAVLINK_TYPE_INT32_T, 0, 8, offsetof(mavlink_global_position_int_t, alt) }, \ + { "vx", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_global_position_int_t, vx) }, \ + { "vy", NULL, MAVLINK_TYPE_INT16_T, 0, 14, offsetof(mavlink_global_position_int_t, vy) }, \ + { "vz", NULL, MAVLINK_TYPE_INT16_T, 0, 16, offsetof(mavlink_global_position_int_t, vz) }, \ + } \ +} + + +/** + * @brief Pack a global_position_int message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param lat Latitude, expressed as * 1E7 + * @param lon Longitude, expressed as * 1E7 + * @param alt Altitude in meters, expressed as * 1000 (millimeters) + * @param vx Ground X Speed (Latitude), expressed as m/s * 100 + * @param vy Ground Y Speed (Longitude), expressed as m/s * 100 + * @param vz Ground Z Speed (Altitude), expressed as m/s * 100 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_global_position_int_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + int32_t lat, int32_t lon, int32_t alt, int16_t vx, int16_t vy, int16_t vz) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_int32_t(buf, 0, lat); + _mav_put_int32_t(buf, 4, lon); + _mav_put_int32_t(buf, 8, alt); + _mav_put_int16_t(buf, 12, vx); + _mav_put_int16_t(buf, 14, vy); + _mav_put_int16_t(buf, 16, vz); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_global_position_int_t packet; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_GLOBAL_POSITION_INT; + return mavlink_finalize_message(msg, system_id, component_id, 18); +} + +/** + * @brief Pack a global_position_int message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param lat Latitude, expressed as * 1E7 + * @param lon Longitude, expressed as * 1E7 + * @param alt Altitude in meters, expressed as * 1000 (millimeters) + * @param vx Ground X Speed (Latitude), expressed as m/s * 100 + * @param vy Ground Y Speed (Longitude), expressed as m/s * 100 + * @param vz Ground Z Speed (Altitude), expressed as m/s * 100 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_global_position_int_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + int32_t lat,int32_t lon,int32_t alt,int16_t vx,int16_t vy,int16_t vz) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_int32_t(buf, 0, lat); + _mav_put_int32_t(buf, 4, lon); + _mav_put_int32_t(buf, 8, alt); + _mav_put_int16_t(buf, 12, vx); + _mav_put_int16_t(buf, 14, vy); + _mav_put_int16_t(buf, 16, vz); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_global_position_int_t packet; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_GLOBAL_POSITION_INT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18); +} + +/** + * @brief Encode a global_position_int struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param global_position_int C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_global_position_int_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_global_position_int_t* global_position_int) +{ + return mavlink_msg_global_position_int_pack(system_id, component_id, msg, global_position_int->lat, global_position_int->lon, global_position_int->alt, global_position_int->vx, global_position_int->vy, global_position_int->vz); +} + +/** + * @brief Send a global_position_int message + * @param chan MAVLink channel to send the message + * + * @param lat Latitude, expressed as * 1E7 + * @param lon Longitude, expressed as * 1E7 + * @param alt Altitude in meters, expressed as * 1000 (millimeters) + * @param vx Ground X Speed (Latitude), expressed as m/s * 100 + * @param vy Ground Y Speed (Longitude), expressed as m/s * 100 + * @param vz Ground Z Speed (Altitude), expressed as m/s * 100 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_global_position_int_send(mavlink_channel_t chan, int32_t lat, int32_t lon, int32_t alt, int16_t vx, int16_t vy, int16_t vz) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_int32_t(buf, 0, lat); + _mav_put_int32_t(buf, 4, lon); + _mav_put_int32_t(buf, 8, alt); + _mav_put_int16_t(buf, 12, vx); + _mav_put_int16_t(buf, 14, vy); + _mav_put_int16_t(buf, 16, vz); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GLOBAL_POSITION_INT, buf, 18); +#else + mavlink_global_position_int_t packet; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GLOBAL_POSITION_INT, (const char *)&packet, 18); +#endif +} + +#endif + +// MESSAGE GLOBAL_POSITION_INT UNPACKING + + +/** + * @brief Get field lat from global_position_int message + * + * @return Latitude, expressed as * 1E7 + */ +static inline int32_t mavlink_msg_global_position_int_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 0); +} + +/** + * @brief Get field lon from global_position_int message + * + * @return Longitude, expressed as * 1E7 + */ +static inline int32_t mavlink_msg_global_position_int_get_lon(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 4); +} + +/** + * @brief Get field alt from global_position_int message + * + * @return Altitude in meters, expressed as * 1000 (millimeters) + */ +static inline int32_t mavlink_msg_global_position_int_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 8); +} + +/** + * @brief Get field vx from global_position_int message + * + * @return Ground X Speed (Latitude), expressed as m/s * 100 + */ +static inline int16_t mavlink_msg_global_position_int_get_vx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Get field vy from global_position_int message + * + * @return Ground Y Speed (Longitude), expressed as m/s * 100 + */ +static inline int16_t mavlink_msg_global_position_int_get_vy(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 14); +} + +/** + * @brief Get field vz from global_position_int message + * + * @return Ground Z Speed (Altitude), expressed as m/s * 100 + */ +static inline int16_t mavlink_msg_global_position_int_get_vz(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 16); +} + +/** + * @brief Decode a global_position_int message into a struct + * + * @param msg The message to decode + * @param global_position_int C-struct to decode the message contents into + */ +static inline void mavlink_msg_global_position_int_decode(const mavlink_message_t* msg, mavlink_global_position_int_t* global_position_int) +{ +#if MAVLINK_NEED_BYTE_SWAP + global_position_int->lat = mavlink_msg_global_position_int_get_lat(msg); + global_position_int->lon = mavlink_msg_global_position_int_get_lon(msg); + global_position_int->alt = mavlink_msg_global_position_int_get_alt(msg); + global_position_int->vx = mavlink_msg_global_position_int_get_vx(msg); + global_position_int->vy = mavlink_msg_global_position_int_get_vy(msg); + global_position_int->vz = mavlink_msg_global_position_int_get_vz(msg); +#else + memcpy(global_position_int, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_local_origin_set.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_local_origin_set.h new file mode 100644 index 0000000000..5faec2812c --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_local_origin_set.h @@ -0,0 +1,188 @@ +// MESSAGE GPS_LOCAL_ORIGIN_SET PACKING + +#define MAVLINK_MSG_ID_GPS_LOCAL_ORIGIN_SET 49 + +typedef struct __mavlink_gps_local_origin_set_t +{ + int32_t latitude; ///< Latitude (WGS84), expressed as * 1E7 + int32_t longitude; ///< Longitude (WGS84), expressed as * 1E7 + int32_t altitude; ///< Altitude(WGS84), expressed as * 1000 +} mavlink_gps_local_origin_set_t; + +#define MAVLINK_MSG_ID_GPS_LOCAL_ORIGIN_SET_LEN 12 +#define MAVLINK_MSG_ID_49_LEN 12 + + + +#define MAVLINK_MESSAGE_INFO_GPS_LOCAL_ORIGIN_SET { \ + "GPS_LOCAL_ORIGIN_SET", \ + 3, \ + { { "latitude", NULL, MAVLINK_TYPE_INT32_T, 0, 0, offsetof(mavlink_gps_local_origin_set_t, latitude) }, \ + { "longitude", NULL, MAVLINK_TYPE_INT32_T, 0, 4, offsetof(mavlink_gps_local_origin_set_t, longitude) }, \ + { "altitude", NULL, MAVLINK_TYPE_INT32_T, 0, 8, offsetof(mavlink_gps_local_origin_set_t, altitude) }, \ + } \ +} + + +/** + * @brief Pack a gps_local_origin_set message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param latitude Latitude (WGS84), expressed as * 1E7 + * @param longitude Longitude (WGS84), expressed as * 1E7 + * @param altitude Altitude(WGS84), expressed as * 1000 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_local_origin_set_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + int32_t latitude, int32_t longitude, int32_t altitude) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_gps_local_origin_set_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_LOCAL_ORIGIN_SET; + return mavlink_finalize_message(msg, system_id, component_id, 12); +} + +/** + * @brief Pack a gps_local_origin_set message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param latitude Latitude (WGS84), expressed as * 1E7 + * @param longitude Longitude (WGS84), expressed as * 1E7 + * @param altitude Altitude(WGS84), expressed as * 1000 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_local_origin_set_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + int32_t latitude,int32_t longitude,int32_t altitude) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_gps_local_origin_set_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_LOCAL_ORIGIN_SET; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12); +} + +/** + * @brief Encode a gps_local_origin_set struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param gps_local_origin_set C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_gps_local_origin_set_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_gps_local_origin_set_t* gps_local_origin_set) +{ + return mavlink_msg_gps_local_origin_set_pack(system_id, component_id, msg, gps_local_origin_set->latitude, gps_local_origin_set->longitude, gps_local_origin_set->altitude); +} + +/** + * @brief Send a gps_local_origin_set message + * @param chan MAVLink channel to send the message + * + * @param latitude Latitude (WGS84), expressed as * 1E7 + * @param longitude Longitude (WGS84), expressed as * 1E7 + * @param altitude Altitude(WGS84), expressed as * 1000 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_gps_local_origin_set_send(mavlink_channel_t chan, int32_t latitude, int32_t longitude, int32_t altitude) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_LOCAL_ORIGIN_SET, buf, 12); +#else + mavlink_gps_local_origin_set_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_LOCAL_ORIGIN_SET, (const char *)&packet, 12); +#endif +} + +#endif + +// MESSAGE GPS_LOCAL_ORIGIN_SET UNPACKING + + +/** + * @brief Get field latitude from gps_local_origin_set message + * + * @return Latitude (WGS84), expressed as * 1E7 + */ +static inline int32_t mavlink_msg_gps_local_origin_set_get_latitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 0); +} + +/** + * @brief Get field longitude from gps_local_origin_set message + * + * @return Longitude (WGS84), expressed as * 1E7 + */ +static inline int32_t mavlink_msg_gps_local_origin_set_get_longitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 4); +} + +/** + * @brief Get field altitude from gps_local_origin_set message + * + * @return Altitude(WGS84), expressed as * 1000 + */ +static inline int32_t mavlink_msg_gps_local_origin_set_get_altitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 8); +} + +/** + * @brief Decode a gps_local_origin_set message into a struct + * + * @param msg The message to decode + * @param gps_local_origin_set C-struct to decode the message contents into + */ +static inline void mavlink_msg_gps_local_origin_set_decode(const mavlink_message_t* msg, mavlink_gps_local_origin_set_t* gps_local_origin_set) +{ +#if MAVLINK_NEED_BYTE_SWAP + gps_local_origin_set->latitude = mavlink_msg_gps_local_origin_set_get_latitude(msg); + gps_local_origin_set->longitude = mavlink_msg_gps_local_origin_set_get_longitude(msg); + gps_local_origin_set->altitude = mavlink_msg_gps_local_origin_set_get_altitude(msg); +#else + memcpy(gps_local_origin_set, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_raw.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_raw.h new file mode 100644 index 0000000000..255cb27bef --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_raw.h @@ -0,0 +1,320 @@ +// MESSAGE GPS_RAW PACKING + +#define MAVLINK_MSG_ID_GPS_RAW 32 + +typedef struct __mavlink_gps_raw_t +{ + uint64_t usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + uint8_t fix_type; ///< 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + float lat; ///< Latitude in degrees + float lon; ///< Longitude in degrees + float alt; ///< Altitude in meters + float eph; ///< GPS HDOP + float epv; ///< GPS VDOP + float v; ///< GPS ground speed + float hdg; ///< Compass heading in degrees, 0..360 degrees +} mavlink_gps_raw_t; + +#define MAVLINK_MSG_ID_GPS_RAW_LEN 37 +#define MAVLINK_MSG_ID_32_LEN 37 + + + +#define MAVLINK_MESSAGE_INFO_GPS_RAW { \ + "GPS_RAW", \ + 9, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_gps_raw_t, usec) }, \ + { "fix_type", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_gps_raw_t, fix_type) }, \ + { "lat", NULL, MAVLINK_TYPE_FLOAT, 0, 9, offsetof(mavlink_gps_raw_t, lat) }, \ + { "lon", NULL, MAVLINK_TYPE_FLOAT, 0, 13, offsetof(mavlink_gps_raw_t, lon) }, \ + { "alt", NULL, MAVLINK_TYPE_FLOAT, 0, 17, offsetof(mavlink_gps_raw_t, alt) }, \ + { "eph", NULL, MAVLINK_TYPE_FLOAT, 0, 21, offsetof(mavlink_gps_raw_t, eph) }, \ + { "epv", NULL, MAVLINK_TYPE_FLOAT, 0, 25, offsetof(mavlink_gps_raw_t, epv) }, \ + { "v", NULL, MAVLINK_TYPE_FLOAT, 0, 29, offsetof(mavlink_gps_raw_t, v) }, \ + { "hdg", NULL, MAVLINK_TYPE_FLOAT, 0, 33, offsetof(mavlink_gps_raw_t, hdg) }, \ + } \ +} + + +/** + * @brief Pack a gps_raw message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param fix_type 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + * @param lat Latitude in degrees + * @param lon Longitude in degrees + * @param alt Altitude in meters + * @param eph GPS HDOP + * @param epv GPS VDOP + * @param v GPS ground speed + * @param hdg Compass heading in degrees, 0..360 degrees + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_raw_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, uint8_t fix_type, float lat, float lon, float alt, float eph, float epv, float v, float hdg) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[37]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_uint8_t(buf, 8, fix_type); + _mav_put_float(buf, 9, lat); + _mav_put_float(buf, 13, lon); + _mav_put_float(buf, 17, alt); + _mav_put_float(buf, 21, eph); + _mav_put_float(buf, 25, epv); + _mav_put_float(buf, 29, v); + _mav_put_float(buf, 33, hdg); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 37); +#else + mavlink_gps_raw_t packet; + packet.usec = usec; + packet.fix_type = fix_type; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.eph = eph; + packet.epv = epv; + packet.v = v; + packet.hdg = hdg; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 37); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_RAW; + return mavlink_finalize_message(msg, system_id, component_id, 37); +} + +/** + * @brief Pack a gps_raw message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param fix_type 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + * @param lat Latitude in degrees + * @param lon Longitude in degrees + * @param alt Altitude in meters + * @param eph GPS HDOP + * @param epv GPS VDOP + * @param v GPS ground speed + * @param hdg Compass heading in degrees, 0..360 degrees + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_raw_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,uint8_t fix_type,float lat,float lon,float alt,float eph,float epv,float v,float hdg) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[37]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_uint8_t(buf, 8, fix_type); + _mav_put_float(buf, 9, lat); + _mav_put_float(buf, 13, lon); + _mav_put_float(buf, 17, alt); + _mav_put_float(buf, 21, eph); + _mav_put_float(buf, 25, epv); + _mav_put_float(buf, 29, v); + _mav_put_float(buf, 33, hdg); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 37); +#else + mavlink_gps_raw_t packet; + packet.usec = usec; + packet.fix_type = fix_type; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.eph = eph; + packet.epv = epv; + packet.v = v; + packet.hdg = hdg; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 37); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_RAW; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 37); +} + +/** + * @brief Encode a gps_raw struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param gps_raw C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_gps_raw_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_gps_raw_t* gps_raw) +{ + return mavlink_msg_gps_raw_pack(system_id, component_id, msg, gps_raw->usec, gps_raw->fix_type, gps_raw->lat, gps_raw->lon, gps_raw->alt, gps_raw->eph, gps_raw->epv, gps_raw->v, gps_raw->hdg); +} + +/** + * @brief Send a gps_raw message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param fix_type 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + * @param lat Latitude in degrees + * @param lon Longitude in degrees + * @param alt Altitude in meters + * @param eph GPS HDOP + * @param epv GPS VDOP + * @param v GPS ground speed + * @param hdg Compass heading in degrees, 0..360 degrees + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_gps_raw_send(mavlink_channel_t chan, uint64_t usec, uint8_t fix_type, float lat, float lon, float alt, float eph, float epv, float v, float hdg) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[37]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_uint8_t(buf, 8, fix_type); + _mav_put_float(buf, 9, lat); + _mav_put_float(buf, 13, lon); + _mav_put_float(buf, 17, alt); + _mav_put_float(buf, 21, eph); + _mav_put_float(buf, 25, epv); + _mav_put_float(buf, 29, v); + _mav_put_float(buf, 33, hdg); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_RAW, buf, 37); +#else + mavlink_gps_raw_t packet; + packet.usec = usec; + packet.fix_type = fix_type; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.eph = eph; + packet.epv = epv; + packet.v = v; + packet.hdg = hdg; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_RAW, (const char *)&packet, 37); +#endif +} + +#endif + +// MESSAGE GPS_RAW UNPACKING + + +/** + * @brief Get field usec from gps_raw message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_gps_raw_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field fix_type from gps_raw message + * + * @return 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + */ +static inline uint8_t mavlink_msg_gps_raw_get_fix_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Get field lat from gps_raw message + * + * @return Latitude in degrees + */ +static inline float mavlink_msg_gps_raw_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 9); +} + +/** + * @brief Get field lon from gps_raw message + * + * @return Longitude in degrees + */ +static inline float mavlink_msg_gps_raw_get_lon(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 13); +} + +/** + * @brief Get field alt from gps_raw message + * + * @return Altitude in meters + */ +static inline float mavlink_msg_gps_raw_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 17); +} + +/** + * @brief Get field eph from gps_raw message + * + * @return GPS HDOP + */ +static inline float mavlink_msg_gps_raw_get_eph(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 21); +} + +/** + * @brief Get field epv from gps_raw message + * + * @return GPS VDOP + */ +static inline float mavlink_msg_gps_raw_get_epv(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 25); +} + +/** + * @brief Get field v from gps_raw message + * + * @return GPS ground speed + */ +static inline float mavlink_msg_gps_raw_get_v(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 29); +} + +/** + * @brief Get field hdg from gps_raw message + * + * @return Compass heading in degrees, 0..360 degrees + */ +static inline float mavlink_msg_gps_raw_get_hdg(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 33); +} + +/** + * @brief Decode a gps_raw message into a struct + * + * @param msg The message to decode + * @param gps_raw C-struct to decode the message contents into + */ +static inline void mavlink_msg_gps_raw_decode(const mavlink_message_t* msg, mavlink_gps_raw_t* gps_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP + gps_raw->usec = mavlink_msg_gps_raw_get_usec(msg); + gps_raw->fix_type = mavlink_msg_gps_raw_get_fix_type(msg); + gps_raw->lat = mavlink_msg_gps_raw_get_lat(msg); + gps_raw->lon = mavlink_msg_gps_raw_get_lon(msg); + gps_raw->alt = mavlink_msg_gps_raw_get_alt(msg); + gps_raw->eph = mavlink_msg_gps_raw_get_eph(msg); + gps_raw->epv = mavlink_msg_gps_raw_get_epv(msg); + gps_raw->v = mavlink_msg_gps_raw_get_v(msg); + gps_raw->hdg = mavlink_msg_gps_raw_get_hdg(msg); +#else + memcpy(gps_raw, _MAV_PAYLOAD(msg), 37); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_raw_int.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_raw_int.h new file mode 100644 index 0000000000..f1e7a05e5d --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_raw_int.h @@ -0,0 +1,320 @@ +// MESSAGE GPS_RAW_INT PACKING + +#define MAVLINK_MSG_ID_GPS_RAW_INT 25 + +typedef struct __mavlink_gps_raw_int_t +{ + uint64_t usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + uint8_t fix_type; ///< 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + int32_t lat; ///< Latitude in 1E7 degrees + int32_t lon; ///< Longitude in 1E7 degrees + int32_t alt; ///< Altitude in 1E3 meters (millimeters) + float eph; ///< GPS HDOP + float epv; ///< GPS VDOP + float v; ///< GPS ground speed (m/s) + float hdg; ///< Compass heading in degrees, 0..360 degrees +} mavlink_gps_raw_int_t; + +#define MAVLINK_MSG_ID_GPS_RAW_INT_LEN 37 +#define MAVLINK_MSG_ID_25_LEN 37 + + + +#define MAVLINK_MESSAGE_INFO_GPS_RAW_INT { \ + "GPS_RAW_INT", \ + 9, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_gps_raw_int_t, usec) }, \ + { "fix_type", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_gps_raw_int_t, fix_type) }, \ + { "lat", NULL, MAVLINK_TYPE_INT32_T, 0, 9, offsetof(mavlink_gps_raw_int_t, lat) }, \ + { "lon", NULL, MAVLINK_TYPE_INT32_T, 0, 13, offsetof(mavlink_gps_raw_int_t, lon) }, \ + { "alt", NULL, MAVLINK_TYPE_INT32_T, 0, 17, offsetof(mavlink_gps_raw_int_t, alt) }, \ + { "eph", NULL, MAVLINK_TYPE_FLOAT, 0, 21, offsetof(mavlink_gps_raw_int_t, eph) }, \ + { "epv", NULL, MAVLINK_TYPE_FLOAT, 0, 25, offsetof(mavlink_gps_raw_int_t, epv) }, \ + { "v", NULL, MAVLINK_TYPE_FLOAT, 0, 29, offsetof(mavlink_gps_raw_int_t, v) }, \ + { "hdg", NULL, MAVLINK_TYPE_FLOAT, 0, 33, offsetof(mavlink_gps_raw_int_t, hdg) }, \ + } \ +} + + +/** + * @brief Pack a gps_raw_int message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param fix_type 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + * @param lat Latitude in 1E7 degrees + * @param lon Longitude in 1E7 degrees + * @param alt Altitude in 1E3 meters (millimeters) + * @param eph GPS HDOP + * @param epv GPS VDOP + * @param v GPS ground speed (m/s) + * @param hdg Compass heading in degrees, 0..360 degrees + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_raw_int_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, uint8_t fix_type, int32_t lat, int32_t lon, int32_t alt, float eph, float epv, float v, float hdg) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[37]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_uint8_t(buf, 8, fix_type); + _mav_put_int32_t(buf, 9, lat); + _mav_put_int32_t(buf, 13, lon); + _mav_put_int32_t(buf, 17, alt); + _mav_put_float(buf, 21, eph); + _mav_put_float(buf, 25, epv); + _mav_put_float(buf, 29, v); + _mav_put_float(buf, 33, hdg); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 37); +#else + mavlink_gps_raw_int_t packet; + packet.usec = usec; + packet.fix_type = fix_type; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.eph = eph; + packet.epv = epv; + packet.v = v; + packet.hdg = hdg; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 37); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_RAW_INT; + return mavlink_finalize_message(msg, system_id, component_id, 37); +} + +/** + * @brief Pack a gps_raw_int message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param fix_type 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + * @param lat Latitude in 1E7 degrees + * @param lon Longitude in 1E7 degrees + * @param alt Altitude in 1E3 meters (millimeters) + * @param eph GPS HDOP + * @param epv GPS VDOP + * @param v GPS ground speed (m/s) + * @param hdg Compass heading in degrees, 0..360 degrees + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_raw_int_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,uint8_t fix_type,int32_t lat,int32_t lon,int32_t alt,float eph,float epv,float v,float hdg) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[37]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_uint8_t(buf, 8, fix_type); + _mav_put_int32_t(buf, 9, lat); + _mav_put_int32_t(buf, 13, lon); + _mav_put_int32_t(buf, 17, alt); + _mav_put_float(buf, 21, eph); + _mav_put_float(buf, 25, epv); + _mav_put_float(buf, 29, v); + _mav_put_float(buf, 33, hdg); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 37); +#else + mavlink_gps_raw_int_t packet; + packet.usec = usec; + packet.fix_type = fix_type; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.eph = eph; + packet.epv = epv; + packet.v = v; + packet.hdg = hdg; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 37); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_RAW_INT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 37); +} + +/** + * @brief Encode a gps_raw_int struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param gps_raw_int C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_gps_raw_int_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_gps_raw_int_t* gps_raw_int) +{ + return mavlink_msg_gps_raw_int_pack(system_id, component_id, msg, gps_raw_int->usec, gps_raw_int->fix_type, gps_raw_int->lat, gps_raw_int->lon, gps_raw_int->alt, gps_raw_int->eph, gps_raw_int->epv, gps_raw_int->v, gps_raw_int->hdg); +} + +/** + * @brief Send a gps_raw_int message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param fix_type 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + * @param lat Latitude in 1E7 degrees + * @param lon Longitude in 1E7 degrees + * @param alt Altitude in 1E3 meters (millimeters) + * @param eph GPS HDOP + * @param epv GPS VDOP + * @param v GPS ground speed (m/s) + * @param hdg Compass heading in degrees, 0..360 degrees + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_gps_raw_int_send(mavlink_channel_t chan, uint64_t usec, uint8_t fix_type, int32_t lat, int32_t lon, int32_t alt, float eph, float epv, float v, float hdg) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[37]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_uint8_t(buf, 8, fix_type); + _mav_put_int32_t(buf, 9, lat); + _mav_put_int32_t(buf, 13, lon); + _mav_put_int32_t(buf, 17, alt); + _mav_put_float(buf, 21, eph); + _mav_put_float(buf, 25, epv); + _mav_put_float(buf, 29, v); + _mav_put_float(buf, 33, hdg); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_RAW_INT, buf, 37); +#else + mavlink_gps_raw_int_t packet; + packet.usec = usec; + packet.fix_type = fix_type; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.eph = eph; + packet.epv = epv; + packet.v = v; + packet.hdg = hdg; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_RAW_INT, (const char *)&packet, 37); +#endif +} + +#endif + +// MESSAGE GPS_RAW_INT UNPACKING + + +/** + * @brief Get field usec from gps_raw_int message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_gps_raw_int_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field fix_type from gps_raw_int message + * + * @return 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + */ +static inline uint8_t mavlink_msg_gps_raw_int_get_fix_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Get field lat from gps_raw_int message + * + * @return Latitude in 1E7 degrees + */ +static inline int32_t mavlink_msg_gps_raw_int_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 9); +} + +/** + * @brief Get field lon from gps_raw_int message + * + * @return Longitude in 1E7 degrees + */ +static inline int32_t mavlink_msg_gps_raw_int_get_lon(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 13); +} + +/** + * @brief Get field alt from gps_raw_int message + * + * @return Altitude in 1E3 meters (millimeters) + */ +static inline int32_t mavlink_msg_gps_raw_int_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 17); +} + +/** + * @brief Get field eph from gps_raw_int message + * + * @return GPS HDOP + */ +static inline float mavlink_msg_gps_raw_int_get_eph(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 21); +} + +/** + * @brief Get field epv from gps_raw_int message + * + * @return GPS VDOP + */ +static inline float mavlink_msg_gps_raw_int_get_epv(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 25); +} + +/** + * @brief Get field v from gps_raw_int message + * + * @return GPS ground speed (m/s) + */ +static inline float mavlink_msg_gps_raw_int_get_v(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 29); +} + +/** + * @brief Get field hdg from gps_raw_int message + * + * @return Compass heading in degrees, 0..360 degrees + */ +static inline float mavlink_msg_gps_raw_int_get_hdg(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 33); +} + +/** + * @brief Decode a gps_raw_int message into a struct + * + * @param msg The message to decode + * @param gps_raw_int C-struct to decode the message contents into + */ +static inline void mavlink_msg_gps_raw_int_decode(const mavlink_message_t* msg, mavlink_gps_raw_int_t* gps_raw_int) +{ +#if MAVLINK_NEED_BYTE_SWAP + gps_raw_int->usec = mavlink_msg_gps_raw_int_get_usec(msg); + gps_raw_int->fix_type = mavlink_msg_gps_raw_int_get_fix_type(msg); + gps_raw_int->lat = mavlink_msg_gps_raw_int_get_lat(msg); + gps_raw_int->lon = mavlink_msg_gps_raw_int_get_lon(msg); + gps_raw_int->alt = mavlink_msg_gps_raw_int_get_alt(msg); + gps_raw_int->eph = mavlink_msg_gps_raw_int_get_eph(msg); + gps_raw_int->epv = mavlink_msg_gps_raw_int_get_epv(msg); + gps_raw_int->v = mavlink_msg_gps_raw_int_get_v(msg); + gps_raw_int->hdg = mavlink_msg_gps_raw_int_get_hdg(msg); +#else + memcpy(gps_raw_int, _MAV_PAYLOAD(msg), 37); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_set_global_origin.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_set_global_origin.h new file mode 100644 index 0000000000..cdd1f242a7 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_set_global_origin.h @@ -0,0 +1,232 @@ +// MESSAGE GPS_SET_GLOBAL_ORIGIN PACKING + +#define MAVLINK_MSG_ID_GPS_SET_GLOBAL_ORIGIN 48 + +typedef struct __mavlink_gps_set_global_origin_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + int32_t latitude; ///< global position * 1E7 + int32_t longitude; ///< global position * 1E7 + int32_t altitude; ///< global position * 1000 +} mavlink_gps_set_global_origin_t; + +#define MAVLINK_MSG_ID_GPS_SET_GLOBAL_ORIGIN_LEN 14 +#define MAVLINK_MSG_ID_48_LEN 14 + + + +#define MAVLINK_MESSAGE_INFO_GPS_SET_GLOBAL_ORIGIN { \ + "GPS_SET_GLOBAL_ORIGIN", \ + 5, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_gps_set_global_origin_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_gps_set_global_origin_t, target_component) }, \ + { "latitude", NULL, MAVLINK_TYPE_INT32_T, 0, 2, offsetof(mavlink_gps_set_global_origin_t, latitude) }, \ + { "longitude", NULL, MAVLINK_TYPE_INT32_T, 0, 6, offsetof(mavlink_gps_set_global_origin_t, longitude) }, \ + { "altitude", NULL, MAVLINK_TYPE_INT32_T, 0, 10, offsetof(mavlink_gps_set_global_origin_t, altitude) }, \ + } \ +} + + +/** + * @brief Pack a gps_set_global_origin message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param latitude global position * 1E7 + * @param longitude global position * 1E7 + * @param altitude global position * 1000 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_set_global_origin_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, int32_t latitude, int32_t longitude, int32_t altitude) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int32_t(buf, 2, latitude); + _mav_put_int32_t(buf, 6, longitude); + _mav_put_int32_t(buf, 10, altitude); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_gps_set_global_origin_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_SET_GLOBAL_ORIGIN; + return mavlink_finalize_message(msg, system_id, component_id, 14); +} + +/** + * @brief Pack a gps_set_global_origin message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param latitude global position * 1E7 + * @param longitude global position * 1E7 + * @param altitude global position * 1000 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_set_global_origin_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,int32_t latitude,int32_t longitude,int32_t altitude) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int32_t(buf, 2, latitude); + _mav_put_int32_t(buf, 6, longitude); + _mav_put_int32_t(buf, 10, altitude); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_gps_set_global_origin_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_SET_GLOBAL_ORIGIN; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 14); +} + +/** + * @brief Encode a gps_set_global_origin struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param gps_set_global_origin C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_gps_set_global_origin_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_gps_set_global_origin_t* gps_set_global_origin) +{ + return mavlink_msg_gps_set_global_origin_pack(system_id, component_id, msg, gps_set_global_origin->target_system, gps_set_global_origin->target_component, gps_set_global_origin->latitude, gps_set_global_origin->longitude, gps_set_global_origin->altitude); +} + +/** + * @brief Send a gps_set_global_origin message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param latitude global position * 1E7 + * @param longitude global position * 1E7 + * @param altitude global position * 1000 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_gps_set_global_origin_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, int32_t latitude, int32_t longitude, int32_t altitude) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int32_t(buf, 2, latitude); + _mav_put_int32_t(buf, 6, longitude); + _mav_put_int32_t(buf, 10, altitude); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_SET_GLOBAL_ORIGIN, buf, 14); +#else + mavlink_gps_set_global_origin_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_SET_GLOBAL_ORIGIN, (const char *)&packet, 14); +#endif +} + +#endif + +// MESSAGE GPS_SET_GLOBAL_ORIGIN UNPACKING + + +/** + * @brief Get field target_system from gps_set_global_origin message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_gps_set_global_origin_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from gps_set_global_origin message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_gps_set_global_origin_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field latitude from gps_set_global_origin message + * + * @return global position * 1E7 + */ +static inline int32_t mavlink_msg_gps_set_global_origin_get_latitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 2); +} + +/** + * @brief Get field longitude from gps_set_global_origin message + * + * @return global position * 1E7 + */ +static inline int32_t mavlink_msg_gps_set_global_origin_get_longitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 6); +} + +/** + * @brief Get field altitude from gps_set_global_origin message + * + * @return global position * 1000 + */ +static inline int32_t mavlink_msg_gps_set_global_origin_get_altitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 10); +} + +/** + * @brief Decode a gps_set_global_origin message into a struct + * + * @param msg The message to decode + * @param gps_set_global_origin C-struct to decode the message contents into + */ +static inline void mavlink_msg_gps_set_global_origin_decode(const mavlink_message_t* msg, mavlink_gps_set_global_origin_t* gps_set_global_origin) +{ +#if MAVLINK_NEED_BYTE_SWAP + gps_set_global_origin->target_system = mavlink_msg_gps_set_global_origin_get_target_system(msg); + gps_set_global_origin->target_component = mavlink_msg_gps_set_global_origin_get_target_component(msg); + gps_set_global_origin->latitude = mavlink_msg_gps_set_global_origin_get_latitude(msg); + gps_set_global_origin->longitude = mavlink_msg_gps_set_global_origin_get_longitude(msg); + gps_set_global_origin->altitude = mavlink_msg_gps_set_global_origin_get_altitude(msg); +#else + memcpy(gps_set_global_origin, _MAV_PAYLOAD(msg), 14); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_status.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_status.h new file mode 100644 index 0000000000..e13ffe3829 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_gps_status.h @@ -0,0 +1,252 @@ +// MESSAGE GPS_STATUS PACKING + +#define MAVLINK_MSG_ID_GPS_STATUS 27 + +typedef struct __mavlink_gps_status_t +{ + uint8_t satellites_visible; ///< Number of satellites visible + int8_t satellite_prn[20]; ///< Global satellite ID + int8_t satellite_used[20]; ///< 0: Satellite not used, 1: used for localization + int8_t satellite_elevation[20]; ///< Elevation (0: right on top of receiver, 90: on the horizon) of satellite + int8_t satellite_azimuth[20]; ///< Direction of satellite, 0: 0 deg, 255: 360 deg. + int8_t satellite_snr[20]; ///< Signal to noise ratio of satellite +} mavlink_gps_status_t; + +#define MAVLINK_MSG_ID_GPS_STATUS_LEN 101 +#define MAVLINK_MSG_ID_27_LEN 101 + +#define MAVLINK_MSG_GPS_STATUS_FIELD_SATELLITE_PRN_LEN 20 +#define MAVLINK_MSG_GPS_STATUS_FIELD_SATELLITE_USED_LEN 20 +#define MAVLINK_MSG_GPS_STATUS_FIELD_SATELLITE_ELEVATION_LEN 20 +#define MAVLINK_MSG_GPS_STATUS_FIELD_SATELLITE_AZIMUTH_LEN 20 +#define MAVLINK_MSG_GPS_STATUS_FIELD_SATELLITE_SNR_LEN 20 + +#define MAVLINK_MESSAGE_INFO_GPS_STATUS { \ + "GPS_STATUS", \ + 6, \ + { { "satellites_visible", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_gps_status_t, satellites_visible) }, \ + { "satellite_prn", NULL, MAVLINK_TYPE_INT8_T, 20, 1, offsetof(mavlink_gps_status_t, satellite_prn) }, \ + { "satellite_used", NULL, MAVLINK_TYPE_INT8_T, 20, 21, offsetof(mavlink_gps_status_t, satellite_used) }, \ + { "satellite_elevation", NULL, MAVLINK_TYPE_INT8_T, 20, 41, offsetof(mavlink_gps_status_t, satellite_elevation) }, \ + { "satellite_azimuth", NULL, MAVLINK_TYPE_INT8_T, 20, 61, offsetof(mavlink_gps_status_t, satellite_azimuth) }, \ + { "satellite_snr", NULL, MAVLINK_TYPE_INT8_T, 20, 81, offsetof(mavlink_gps_status_t, satellite_snr) }, \ + } \ +} + + +/** + * @brief Pack a gps_status message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param satellites_visible Number of satellites visible + * @param satellite_prn Global satellite ID + * @param satellite_used 0: Satellite not used, 1: used for localization + * @param satellite_elevation Elevation (0: right on top of receiver, 90: on the horizon) of satellite + * @param satellite_azimuth Direction of satellite, 0: 0 deg, 255: 360 deg. + * @param satellite_snr Signal to noise ratio of satellite + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_status_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t satellites_visible, const int8_t *satellite_prn, const int8_t *satellite_used, const int8_t *satellite_elevation, const int8_t *satellite_azimuth, const int8_t *satellite_snr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[101]; + _mav_put_uint8_t(buf, 0, satellites_visible); + _mav_put_int8_t_array(buf, 1, satellite_prn, 20); + _mav_put_int8_t_array(buf, 21, satellite_used, 20); + _mav_put_int8_t_array(buf, 41, satellite_elevation, 20); + _mav_put_int8_t_array(buf, 61, satellite_azimuth, 20); + _mav_put_int8_t_array(buf, 81, satellite_snr, 20); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 101); +#else + mavlink_gps_status_t packet; + packet.satellites_visible = satellites_visible; + mav_array_memcpy(packet.satellite_prn, satellite_prn, sizeof(int8_t)*20); + mav_array_memcpy(packet.satellite_used, satellite_used, sizeof(int8_t)*20); + mav_array_memcpy(packet.satellite_elevation, satellite_elevation, sizeof(int8_t)*20); + mav_array_memcpy(packet.satellite_azimuth, satellite_azimuth, sizeof(int8_t)*20); + mav_array_memcpy(packet.satellite_snr, satellite_snr, sizeof(int8_t)*20); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 101); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_STATUS; + return mavlink_finalize_message(msg, system_id, component_id, 101); +} + +/** + * @brief Pack a gps_status message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param satellites_visible Number of satellites visible + * @param satellite_prn Global satellite ID + * @param satellite_used 0: Satellite not used, 1: used for localization + * @param satellite_elevation Elevation (0: right on top of receiver, 90: on the horizon) of satellite + * @param satellite_azimuth Direction of satellite, 0: 0 deg, 255: 360 deg. + * @param satellite_snr Signal to noise ratio of satellite + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_status_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t satellites_visible,const int8_t *satellite_prn,const int8_t *satellite_used,const int8_t *satellite_elevation,const int8_t *satellite_azimuth,const int8_t *satellite_snr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[101]; + _mav_put_uint8_t(buf, 0, satellites_visible); + _mav_put_int8_t_array(buf, 1, satellite_prn, 20); + _mav_put_int8_t_array(buf, 21, satellite_used, 20); + _mav_put_int8_t_array(buf, 41, satellite_elevation, 20); + _mav_put_int8_t_array(buf, 61, satellite_azimuth, 20); + _mav_put_int8_t_array(buf, 81, satellite_snr, 20); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 101); +#else + mavlink_gps_status_t packet; + packet.satellites_visible = satellites_visible; + mav_array_memcpy(packet.satellite_prn, satellite_prn, sizeof(int8_t)*20); + mav_array_memcpy(packet.satellite_used, satellite_used, sizeof(int8_t)*20); + mav_array_memcpy(packet.satellite_elevation, satellite_elevation, sizeof(int8_t)*20); + mav_array_memcpy(packet.satellite_azimuth, satellite_azimuth, sizeof(int8_t)*20); + mav_array_memcpy(packet.satellite_snr, satellite_snr, sizeof(int8_t)*20); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 101); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_STATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 101); +} + +/** + * @brief Encode a gps_status struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param gps_status C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_gps_status_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_gps_status_t* gps_status) +{ + return mavlink_msg_gps_status_pack(system_id, component_id, msg, gps_status->satellites_visible, gps_status->satellite_prn, gps_status->satellite_used, gps_status->satellite_elevation, gps_status->satellite_azimuth, gps_status->satellite_snr); +} + +/** + * @brief Send a gps_status message + * @param chan MAVLink channel to send the message + * + * @param satellites_visible Number of satellites visible + * @param satellite_prn Global satellite ID + * @param satellite_used 0: Satellite not used, 1: used for localization + * @param satellite_elevation Elevation (0: right on top of receiver, 90: on the horizon) of satellite + * @param satellite_azimuth Direction of satellite, 0: 0 deg, 255: 360 deg. + * @param satellite_snr Signal to noise ratio of satellite + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_gps_status_send(mavlink_channel_t chan, uint8_t satellites_visible, const int8_t *satellite_prn, const int8_t *satellite_used, const int8_t *satellite_elevation, const int8_t *satellite_azimuth, const int8_t *satellite_snr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[101]; + _mav_put_uint8_t(buf, 0, satellites_visible); + _mav_put_int8_t_array(buf, 1, satellite_prn, 20); + _mav_put_int8_t_array(buf, 21, satellite_used, 20); + _mav_put_int8_t_array(buf, 41, satellite_elevation, 20); + _mav_put_int8_t_array(buf, 61, satellite_azimuth, 20); + _mav_put_int8_t_array(buf, 81, satellite_snr, 20); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_STATUS, buf, 101); +#else + mavlink_gps_status_t packet; + packet.satellites_visible = satellites_visible; + mav_array_memcpy(packet.satellite_prn, satellite_prn, sizeof(int8_t)*20); + mav_array_memcpy(packet.satellite_used, satellite_used, sizeof(int8_t)*20); + mav_array_memcpy(packet.satellite_elevation, satellite_elevation, sizeof(int8_t)*20); + mav_array_memcpy(packet.satellite_azimuth, satellite_azimuth, sizeof(int8_t)*20); + mav_array_memcpy(packet.satellite_snr, satellite_snr, sizeof(int8_t)*20); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_STATUS, (const char *)&packet, 101); +#endif +} + +#endif + +// MESSAGE GPS_STATUS UNPACKING + + +/** + * @brief Get field satellites_visible from gps_status message + * + * @return Number of satellites visible + */ +static inline uint8_t mavlink_msg_gps_status_get_satellites_visible(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field satellite_prn from gps_status message + * + * @return Global satellite ID + */ +static inline uint16_t mavlink_msg_gps_status_get_satellite_prn(const mavlink_message_t* msg, int8_t *satellite_prn) +{ + return _MAV_RETURN_int8_t_array(msg, satellite_prn, 20, 1); +} + +/** + * @brief Get field satellite_used from gps_status message + * + * @return 0: Satellite not used, 1: used for localization + */ +static inline uint16_t mavlink_msg_gps_status_get_satellite_used(const mavlink_message_t* msg, int8_t *satellite_used) +{ + return _MAV_RETURN_int8_t_array(msg, satellite_used, 20, 21); +} + +/** + * @brief Get field satellite_elevation from gps_status message + * + * @return Elevation (0: right on top of receiver, 90: on the horizon) of satellite + */ +static inline uint16_t mavlink_msg_gps_status_get_satellite_elevation(const mavlink_message_t* msg, int8_t *satellite_elevation) +{ + return _MAV_RETURN_int8_t_array(msg, satellite_elevation, 20, 41); +} + +/** + * @brief Get field satellite_azimuth from gps_status message + * + * @return Direction of satellite, 0: 0 deg, 255: 360 deg. + */ +static inline uint16_t mavlink_msg_gps_status_get_satellite_azimuth(const mavlink_message_t* msg, int8_t *satellite_azimuth) +{ + return _MAV_RETURN_int8_t_array(msg, satellite_azimuth, 20, 61); +} + +/** + * @brief Get field satellite_snr from gps_status message + * + * @return Signal to noise ratio of satellite + */ +static inline uint16_t mavlink_msg_gps_status_get_satellite_snr(const mavlink_message_t* msg, int8_t *satellite_snr) +{ + return _MAV_RETURN_int8_t_array(msg, satellite_snr, 20, 81); +} + +/** + * @brief Decode a gps_status message into a struct + * + * @param msg The message to decode + * @param gps_status C-struct to decode the message contents into + */ +static inline void mavlink_msg_gps_status_decode(const mavlink_message_t* msg, mavlink_gps_status_t* gps_status) +{ +#if MAVLINK_NEED_BYTE_SWAP + gps_status->satellites_visible = mavlink_msg_gps_status_get_satellites_visible(msg); + mavlink_msg_gps_status_get_satellite_prn(msg, gps_status->satellite_prn); + mavlink_msg_gps_status_get_satellite_used(msg, gps_status->satellite_used); + mavlink_msg_gps_status_get_satellite_elevation(msg, gps_status->satellite_elevation); + mavlink_msg_gps_status_get_satellite_azimuth(msg, gps_status->satellite_azimuth); + mavlink_msg_gps_status_get_satellite_snr(msg, gps_status->satellite_snr); +#else + memcpy(gps_status, _MAV_PAYLOAD(msg), 101); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_heartbeat.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_heartbeat.h new file mode 100644 index 0000000000..aad90d29f3 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_heartbeat.h @@ -0,0 +1,185 @@ +// MESSAGE HEARTBEAT PACKING + +#define MAVLINK_MSG_ID_HEARTBEAT 0 + +typedef struct __mavlink_heartbeat_t +{ + uint8_t type; ///< Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + uint8_t autopilot; ///< Type of the Autopilot: 0: Generic, 1: PIXHAWK, 2: SLUGS, 3: Ardupilot (up to 15 types), defined in MAV_AUTOPILOT_TYPE ENUM + uint8_t mavlink_version; ///< MAVLink version +} mavlink_heartbeat_t; + +#define MAVLINK_MSG_ID_HEARTBEAT_LEN 3 +#define MAVLINK_MSG_ID_0_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_HEARTBEAT { \ + "HEARTBEAT", \ + 3, \ + { { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_heartbeat_t, type) }, \ + { "autopilot", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_heartbeat_t, autopilot) }, \ + { "mavlink_version", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_heartbeat_t, mavlink_version) }, \ + } \ +} + + +/** + * @brief Pack a heartbeat message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + * @param autopilot Type of the Autopilot: 0: Generic, 1: PIXHAWK, 2: SLUGS, 3: Ardupilot (up to 15 types), defined in MAV_AUTOPILOT_TYPE ENUM + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_heartbeat_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t type, uint8_t autopilot) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint8_t(buf, 1, autopilot); + _mav_put_uint8_t(buf, 2, 2); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_heartbeat_t packet; + packet.type = type; + packet.autopilot = autopilot; + packet.mavlink_version = 2; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_HEARTBEAT; + return mavlink_finalize_message(msg, system_id, component_id, 3); +} + +/** + * @brief Pack a heartbeat message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + * @param autopilot Type of the Autopilot: 0: Generic, 1: PIXHAWK, 2: SLUGS, 3: Ardupilot (up to 15 types), defined in MAV_AUTOPILOT_TYPE ENUM + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_heartbeat_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t type,uint8_t autopilot) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint8_t(buf, 1, autopilot); + _mav_put_uint8_t(buf, 2, 2); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_heartbeat_t packet; + packet.type = type; + packet.autopilot = autopilot; + packet.mavlink_version = 2; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_HEARTBEAT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3); +} + +/** + * @brief Encode a heartbeat struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param heartbeat C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_heartbeat_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_heartbeat_t* heartbeat) +{ + return mavlink_msg_heartbeat_pack(system_id, component_id, msg, heartbeat->type, heartbeat->autopilot); +} + +/** + * @brief Send a heartbeat message + * @param chan MAVLink channel to send the message + * + * @param type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + * @param autopilot Type of the Autopilot: 0: Generic, 1: PIXHAWK, 2: SLUGS, 3: Ardupilot (up to 15 types), defined in MAV_AUTOPILOT_TYPE ENUM + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_heartbeat_send(mavlink_channel_t chan, uint8_t type, uint8_t autopilot) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint8_t(buf, 1, autopilot); + _mav_put_uint8_t(buf, 2, 2); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HEARTBEAT, buf, 3); +#else + mavlink_heartbeat_t packet; + packet.type = type; + packet.autopilot = autopilot; + packet.mavlink_version = 2; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HEARTBEAT, (const char *)&packet, 3); +#endif +} + +#endif + +// MESSAGE HEARTBEAT UNPACKING + + +/** + * @brief Get field type from heartbeat message + * + * @return Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + */ +static inline uint8_t mavlink_msg_heartbeat_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field autopilot from heartbeat message + * + * @return Type of the Autopilot: 0: Generic, 1: PIXHAWK, 2: SLUGS, 3: Ardupilot (up to 15 types), defined in MAV_AUTOPILOT_TYPE ENUM + */ +static inline uint8_t mavlink_msg_heartbeat_get_autopilot(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field mavlink_version from heartbeat message + * + * @return MAVLink version + */ +static inline uint8_t mavlink_msg_heartbeat_get_mavlink_version(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a heartbeat message into a struct + * + * @param msg The message to decode + * @param heartbeat C-struct to decode the message contents into + */ +static inline void mavlink_msg_heartbeat_decode(const mavlink_message_t* msg, mavlink_heartbeat_t* heartbeat) +{ +#if MAVLINK_NEED_BYTE_SWAP + heartbeat->type = mavlink_msg_heartbeat_get_type(msg); + heartbeat->autopilot = mavlink_msg_heartbeat_get_autopilot(msg); + heartbeat->mavlink_version = mavlink_msg_heartbeat_get_mavlink_version(msg); +#else + memcpy(heartbeat, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_hil_controls.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_hil_controls.h new file mode 100644 index 0000000000..231c6f216b --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_hil_controls.h @@ -0,0 +1,276 @@ +// MESSAGE HIL_CONTROLS PACKING + +#define MAVLINK_MSG_ID_HIL_CONTROLS 68 + +typedef struct __mavlink_hil_controls_t +{ + uint64_t time_us; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + float roll_ailerons; ///< Control output -3 .. 1 + float pitch_elevator; ///< Control output -1 .. 1 + float yaw_rudder; ///< Control output -1 .. 1 + float throttle; ///< Throttle 0 .. 1 + uint8_t mode; ///< System mode (MAV_MODE) + uint8_t nav_mode; ///< Navigation mode (MAV_NAV_MODE) +} mavlink_hil_controls_t; + +#define MAVLINK_MSG_ID_HIL_CONTROLS_LEN 26 +#define MAVLINK_MSG_ID_68_LEN 26 + + + +#define MAVLINK_MESSAGE_INFO_HIL_CONTROLS { \ + "HIL_CONTROLS", \ + 7, \ + { { "time_us", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_hil_controls_t, time_us) }, \ + { "roll_ailerons", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_hil_controls_t, roll_ailerons) }, \ + { "pitch_elevator", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_hil_controls_t, pitch_elevator) }, \ + { "yaw_rudder", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_hil_controls_t, yaw_rudder) }, \ + { "throttle", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_hil_controls_t, throttle) }, \ + { "mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 24, offsetof(mavlink_hil_controls_t, mode) }, \ + { "nav_mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 25, offsetof(mavlink_hil_controls_t, nav_mode) }, \ + } \ +} + + +/** + * @brief Pack a hil_controls message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_us Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll_ailerons Control output -3 .. 1 + * @param pitch_elevator Control output -1 .. 1 + * @param yaw_rudder Control output -1 .. 1 + * @param throttle Throttle 0 .. 1 + * @param mode System mode (MAV_MODE) + * @param nav_mode Navigation mode (MAV_NAV_MODE) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hil_controls_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time_us, float roll_ailerons, float pitch_elevator, float yaw_rudder, float throttle, uint8_t mode, uint8_t nav_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, time_us); + _mav_put_float(buf, 8, roll_ailerons); + _mav_put_float(buf, 12, pitch_elevator); + _mav_put_float(buf, 16, yaw_rudder); + _mav_put_float(buf, 20, throttle); + _mav_put_uint8_t(buf, 24, mode); + _mav_put_uint8_t(buf, 25, nav_mode); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_hil_controls_t packet; + packet.time_us = time_us; + packet.roll_ailerons = roll_ailerons; + packet.pitch_elevator = pitch_elevator; + packet.yaw_rudder = yaw_rudder; + packet.throttle = throttle; + packet.mode = mode; + packet.nav_mode = nav_mode; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_HIL_CONTROLS; + return mavlink_finalize_message(msg, system_id, component_id, 26); +} + +/** + * @brief Pack a hil_controls message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_us Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll_ailerons Control output -3 .. 1 + * @param pitch_elevator Control output -1 .. 1 + * @param yaw_rudder Control output -1 .. 1 + * @param throttle Throttle 0 .. 1 + * @param mode System mode (MAV_MODE) + * @param nav_mode Navigation mode (MAV_NAV_MODE) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hil_controls_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time_us,float roll_ailerons,float pitch_elevator,float yaw_rudder,float throttle,uint8_t mode,uint8_t nav_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, time_us); + _mav_put_float(buf, 8, roll_ailerons); + _mav_put_float(buf, 12, pitch_elevator); + _mav_put_float(buf, 16, yaw_rudder); + _mav_put_float(buf, 20, throttle); + _mav_put_uint8_t(buf, 24, mode); + _mav_put_uint8_t(buf, 25, nav_mode); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_hil_controls_t packet; + packet.time_us = time_us; + packet.roll_ailerons = roll_ailerons; + packet.pitch_elevator = pitch_elevator; + packet.yaw_rudder = yaw_rudder; + packet.throttle = throttle; + packet.mode = mode; + packet.nav_mode = nav_mode; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_HIL_CONTROLS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 26); +} + +/** + * @brief Encode a hil_controls struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param hil_controls C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_hil_controls_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_hil_controls_t* hil_controls) +{ + return mavlink_msg_hil_controls_pack(system_id, component_id, msg, hil_controls->time_us, hil_controls->roll_ailerons, hil_controls->pitch_elevator, hil_controls->yaw_rudder, hil_controls->throttle, hil_controls->mode, hil_controls->nav_mode); +} + +/** + * @brief Send a hil_controls message + * @param chan MAVLink channel to send the message + * + * @param time_us Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll_ailerons Control output -3 .. 1 + * @param pitch_elevator Control output -1 .. 1 + * @param yaw_rudder Control output -1 .. 1 + * @param throttle Throttle 0 .. 1 + * @param mode System mode (MAV_MODE) + * @param nav_mode Navigation mode (MAV_NAV_MODE) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_hil_controls_send(mavlink_channel_t chan, uint64_t time_us, float roll_ailerons, float pitch_elevator, float yaw_rudder, float throttle, uint8_t mode, uint8_t nav_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, time_us); + _mav_put_float(buf, 8, roll_ailerons); + _mav_put_float(buf, 12, pitch_elevator); + _mav_put_float(buf, 16, yaw_rudder); + _mav_put_float(buf, 20, throttle); + _mav_put_uint8_t(buf, 24, mode); + _mav_put_uint8_t(buf, 25, nav_mode); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HIL_CONTROLS, buf, 26); +#else + mavlink_hil_controls_t packet; + packet.time_us = time_us; + packet.roll_ailerons = roll_ailerons; + packet.pitch_elevator = pitch_elevator; + packet.yaw_rudder = yaw_rudder; + packet.throttle = throttle; + packet.mode = mode; + packet.nav_mode = nav_mode; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HIL_CONTROLS, (const char *)&packet, 26); +#endif +} + +#endif + +// MESSAGE HIL_CONTROLS UNPACKING + + +/** + * @brief Get field time_us from hil_controls message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_hil_controls_get_time_us(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field roll_ailerons from hil_controls message + * + * @return Control output -3 .. 1 + */ +static inline float mavlink_msg_hil_controls_get_roll_ailerons(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field pitch_elevator from hil_controls message + * + * @return Control output -1 .. 1 + */ +static inline float mavlink_msg_hil_controls_get_pitch_elevator(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field yaw_rudder from hil_controls message + * + * @return Control output -1 .. 1 + */ +static inline float mavlink_msg_hil_controls_get_yaw_rudder(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field throttle from hil_controls message + * + * @return Throttle 0 .. 1 + */ +static inline float mavlink_msg_hil_controls_get_throttle(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field mode from hil_controls message + * + * @return System mode (MAV_MODE) + */ +static inline uint8_t mavlink_msg_hil_controls_get_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 24); +} + +/** + * @brief Get field nav_mode from hil_controls message + * + * @return Navigation mode (MAV_NAV_MODE) + */ +static inline uint8_t mavlink_msg_hil_controls_get_nav_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 25); +} + +/** + * @brief Decode a hil_controls message into a struct + * + * @param msg The message to decode + * @param hil_controls C-struct to decode the message contents into + */ +static inline void mavlink_msg_hil_controls_decode(const mavlink_message_t* msg, mavlink_hil_controls_t* hil_controls) +{ +#if MAVLINK_NEED_BYTE_SWAP + hil_controls->time_us = mavlink_msg_hil_controls_get_time_us(msg); + hil_controls->roll_ailerons = mavlink_msg_hil_controls_get_roll_ailerons(msg); + hil_controls->pitch_elevator = mavlink_msg_hil_controls_get_pitch_elevator(msg); + hil_controls->yaw_rudder = mavlink_msg_hil_controls_get_yaw_rudder(msg); + hil_controls->throttle = mavlink_msg_hil_controls_get_throttle(msg); + hil_controls->mode = mavlink_msg_hil_controls_get_mode(msg); + hil_controls->nav_mode = mavlink_msg_hil_controls_get_nav_mode(msg); +#else + memcpy(hil_controls, _MAV_PAYLOAD(msg), 26); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_hil_state.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_hil_state.h new file mode 100644 index 0000000000..6692c22580 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_hil_state.h @@ -0,0 +1,474 @@ +// MESSAGE HIL_STATE PACKING + +#define MAVLINK_MSG_ID_HIL_STATE 67 + +typedef struct __mavlink_hil_state_t +{ + uint64_t usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + float roll; ///< Roll angle (rad) + float pitch; ///< Pitch angle (rad) + float yaw; ///< Yaw angle (rad) + float rollspeed; ///< Roll angular speed (rad/s) + float pitchspeed; ///< Pitch angular speed (rad/s) + float yawspeed; ///< Yaw angular speed (rad/s) + int32_t lat; ///< Latitude, expressed as * 1E7 + int32_t lon; ///< Longitude, expressed as * 1E7 + int32_t alt; ///< Altitude in meters, expressed as * 1000 (millimeters) + int16_t vx; ///< Ground X Speed (Latitude), expressed as m/s * 100 + int16_t vy; ///< Ground Y Speed (Longitude), expressed as m/s * 100 + int16_t vz; ///< Ground Z Speed (Altitude), expressed as m/s * 100 + int16_t xacc; ///< X acceleration (mg) + int16_t yacc; ///< Y acceleration (mg) + int16_t zacc; ///< Z acceleration (mg) +} mavlink_hil_state_t; + +#define MAVLINK_MSG_ID_HIL_STATE_LEN 56 +#define MAVLINK_MSG_ID_67_LEN 56 + + + +#define MAVLINK_MESSAGE_INFO_HIL_STATE { \ + "HIL_STATE", \ + 16, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_hil_state_t, usec) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_hil_state_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_hil_state_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_hil_state_t, yaw) }, \ + { "rollspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_hil_state_t, rollspeed) }, \ + { "pitchspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_hil_state_t, pitchspeed) }, \ + { "yawspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_hil_state_t, yawspeed) }, \ + { "lat", NULL, MAVLINK_TYPE_INT32_T, 0, 32, offsetof(mavlink_hil_state_t, lat) }, \ + { "lon", NULL, MAVLINK_TYPE_INT32_T, 0, 36, offsetof(mavlink_hil_state_t, lon) }, \ + { "alt", NULL, MAVLINK_TYPE_INT32_T, 0, 40, offsetof(mavlink_hil_state_t, alt) }, \ + { "vx", NULL, MAVLINK_TYPE_INT16_T, 0, 44, offsetof(mavlink_hil_state_t, vx) }, \ + { "vy", NULL, MAVLINK_TYPE_INT16_T, 0, 46, offsetof(mavlink_hil_state_t, vy) }, \ + { "vz", NULL, MAVLINK_TYPE_INT16_T, 0, 48, offsetof(mavlink_hil_state_t, vz) }, \ + { "xacc", NULL, MAVLINK_TYPE_INT16_T, 0, 50, offsetof(mavlink_hil_state_t, xacc) }, \ + { "yacc", NULL, MAVLINK_TYPE_INT16_T, 0, 52, offsetof(mavlink_hil_state_t, yacc) }, \ + { "zacc", NULL, MAVLINK_TYPE_INT16_T, 0, 54, offsetof(mavlink_hil_state_t, zacc) }, \ + } \ +} + + +/** + * @brief Pack a hil_state message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + * @param lat Latitude, expressed as * 1E7 + * @param lon Longitude, expressed as * 1E7 + * @param alt Altitude in meters, expressed as * 1000 (millimeters) + * @param vx Ground X Speed (Latitude), expressed as m/s * 100 + * @param vy Ground Y Speed (Longitude), expressed as m/s * 100 + * @param vz Ground Z Speed (Altitude), expressed as m/s * 100 + * @param xacc X acceleration (mg) + * @param yacc Y acceleration (mg) + * @param zacc Z acceleration (mg) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hil_state_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, float roll, float pitch, float yaw, float rollspeed, float pitchspeed, float yawspeed, int32_t lat, int32_t lon, int32_t alt, int16_t vx, int16_t vy, int16_t vz, int16_t xacc, int16_t yacc, int16_t zacc) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[56]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, roll); + _mav_put_float(buf, 12, pitch); + _mav_put_float(buf, 16, yaw); + _mav_put_float(buf, 20, rollspeed); + _mav_put_float(buf, 24, pitchspeed); + _mav_put_float(buf, 28, yawspeed); + _mav_put_int32_t(buf, 32, lat); + _mav_put_int32_t(buf, 36, lon); + _mav_put_int32_t(buf, 40, alt); + _mav_put_int16_t(buf, 44, vx); + _mav_put_int16_t(buf, 46, vy); + _mav_put_int16_t(buf, 48, vz); + _mav_put_int16_t(buf, 50, xacc); + _mav_put_int16_t(buf, 52, yacc); + _mav_put_int16_t(buf, 54, zacc); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 56); +#else + mavlink_hil_state_t packet; + packet.usec = usec; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 56); +#endif + + msg->msgid = MAVLINK_MSG_ID_HIL_STATE; + return mavlink_finalize_message(msg, system_id, component_id, 56); +} + +/** + * @brief Pack a hil_state message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + * @param lat Latitude, expressed as * 1E7 + * @param lon Longitude, expressed as * 1E7 + * @param alt Altitude in meters, expressed as * 1000 (millimeters) + * @param vx Ground X Speed (Latitude), expressed as m/s * 100 + * @param vy Ground Y Speed (Longitude), expressed as m/s * 100 + * @param vz Ground Z Speed (Altitude), expressed as m/s * 100 + * @param xacc X acceleration (mg) + * @param yacc Y acceleration (mg) + * @param zacc Z acceleration (mg) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hil_state_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float roll,float pitch,float yaw,float rollspeed,float pitchspeed,float yawspeed,int32_t lat,int32_t lon,int32_t alt,int16_t vx,int16_t vy,int16_t vz,int16_t xacc,int16_t yacc,int16_t zacc) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[56]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, roll); + _mav_put_float(buf, 12, pitch); + _mav_put_float(buf, 16, yaw); + _mav_put_float(buf, 20, rollspeed); + _mav_put_float(buf, 24, pitchspeed); + _mav_put_float(buf, 28, yawspeed); + _mav_put_int32_t(buf, 32, lat); + _mav_put_int32_t(buf, 36, lon); + _mav_put_int32_t(buf, 40, alt); + _mav_put_int16_t(buf, 44, vx); + _mav_put_int16_t(buf, 46, vy); + _mav_put_int16_t(buf, 48, vz); + _mav_put_int16_t(buf, 50, xacc); + _mav_put_int16_t(buf, 52, yacc); + _mav_put_int16_t(buf, 54, zacc); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 56); +#else + mavlink_hil_state_t packet; + packet.usec = usec; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 56); +#endif + + msg->msgid = MAVLINK_MSG_ID_HIL_STATE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 56); +} + +/** + * @brief Encode a hil_state struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param hil_state C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_hil_state_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_hil_state_t* hil_state) +{ + return mavlink_msg_hil_state_pack(system_id, component_id, msg, hil_state->usec, hil_state->roll, hil_state->pitch, hil_state->yaw, hil_state->rollspeed, hil_state->pitchspeed, hil_state->yawspeed, hil_state->lat, hil_state->lon, hil_state->alt, hil_state->vx, hil_state->vy, hil_state->vz, hil_state->xacc, hil_state->yacc, hil_state->zacc); +} + +/** + * @brief Send a hil_state message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + * @param lat Latitude, expressed as * 1E7 + * @param lon Longitude, expressed as * 1E7 + * @param alt Altitude in meters, expressed as * 1000 (millimeters) + * @param vx Ground X Speed (Latitude), expressed as m/s * 100 + * @param vy Ground Y Speed (Longitude), expressed as m/s * 100 + * @param vz Ground Z Speed (Altitude), expressed as m/s * 100 + * @param xacc X acceleration (mg) + * @param yacc Y acceleration (mg) + * @param zacc Z acceleration (mg) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_hil_state_send(mavlink_channel_t chan, uint64_t usec, float roll, float pitch, float yaw, float rollspeed, float pitchspeed, float yawspeed, int32_t lat, int32_t lon, int32_t alt, int16_t vx, int16_t vy, int16_t vz, int16_t xacc, int16_t yacc, int16_t zacc) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[56]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, roll); + _mav_put_float(buf, 12, pitch); + _mav_put_float(buf, 16, yaw); + _mav_put_float(buf, 20, rollspeed); + _mav_put_float(buf, 24, pitchspeed); + _mav_put_float(buf, 28, yawspeed); + _mav_put_int32_t(buf, 32, lat); + _mav_put_int32_t(buf, 36, lon); + _mav_put_int32_t(buf, 40, alt); + _mav_put_int16_t(buf, 44, vx); + _mav_put_int16_t(buf, 46, vy); + _mav_put_int16_t(buf, 48, vz); + _mav_put_int16_t(buf, 50, xacc); + _mav_put_int16_t(buf, 52, yacc); + _mav_put_int16_t(buf, 54, zacc); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HIL_STATE, buf, 56); +#else + mavlink_hil_state_t packet; + packet.usec = usec; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HIL_STATE, (const char *)&packet, 56); +#endif +} + +#endif + +// MESSAGE HIL_STATE UNPACKING + + +/** + * @brief Get field usec from hil_state message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_hil_state_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field roll from hil_state message + * + * @return Roll angle (rad) + */ +static inline float mavlink_msg_hil_state_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field pitch from hil_state message + * + * @return Pitch angle (rad) + */ +static inline float mavlink_msg_hil_state_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field yaw from hil_state message + * + * @return Yaw angle (rad) + */ +static inline float mavlink_msg_hil_state_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field rollspeed from hil_state message + * + * @return Roll angular speed (rad/s) + */ +static inline float mavlink_msg_hil_state_get_rollspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field pitchspeed from hil_state message + * + * @return Pitch angular speed (rad/s) + */ +static inline float mavlink_msg_hil_state_get_pitchspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field yawspeed from hil_state message + * + * @return Yaw angular speed (rad/s) + */ +static inline float mavlink_msg_hil_state_get_yawspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field lat from hil_state message + * + * @return Latitude, expressed as * 1E7 + */ +static inline int32_t mavlink_msg_hil_state_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 32); +} + +/** + * @brief Get field lon from hil_state message + * + * @return Longitude, expressed as * 1E7 + */ +static inline int32_t mavlink_msg_hil_state_get_lon(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 36); +} + +/** + * @brief Get field alt from hil_state message + * + * @return Altitude in meters, expressed as * 1000 (millimeters) + */ +static inline int32_t mavlink_msg_hil_state_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 40); +} + +/** + * @brief Get field vx from hil_state message + * + * @return Ground X Speed (Latitude), expressed as m/s * 100 + */ +static inline int16_t mavlink_msg_hil_state_get_vx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 44); +} + +/** + * @brief Get field vy from hil_state message + * + * @return Ground Y Speed (Longitude), expressed as m/s * 100 + */ +static inline int16_t mavlink_msg_hil_state_get_vy(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 46); +} + +/** + * @brief Get field vz from hil_state message + * + * @return Ground Z Speed (Altitude), expressed as m/s * 100 + */ +static inline int16_t mavlink_msg_hil_state_get_vz(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 48); +} + +/** + * @brief Get field xacc from hil_state message + * + * @return X acceleration (mg) + */ +static inline int16_t mavlink_msg_hil_state_get_xacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 50); +} + +/** + * @brief Get field yacc from hil_state message + * + * @return Y acceleration (mg) + */ +static inline int16_t mavlink_msg_hil_state_get_yacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 52); +} + +/** + * @brief Get field zacc from hil_state message + * + * @return Z acceleration (mg) + */ +static inline int16_t mavlink_msg_hil_state_get_zacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 54); +} + +/** + * @brief Decode a hil_state message into a struct + * + * @param msg The message to decode + * @param hil_state C-struct to decode the message contents into + */ +static inline void mavlink_msg_hil_state_decode(const mavlink_message_t* msg, mavlink_hil_state_t* hil_state) +{ +#if MAVLINK_NEED_BYTE_SWAP + hil_state->usec = mavlink_msg_hil_state_get_usec(msg); + hil_state->roll = mavlink_msg_hil_state_get_roll(msg); + hil_state->pitch = mavlink_msg_hil_state_get_pitch(msg); + hil_state->yaw = mavlink_msg_hil_state_get_yaw(msg); + hil_state->rollspeed = mavlink_msg_hil_state_get_rollspeed(msg); + hil_state->pitchspeed = mavlink_msg_hil_state_get_pitchspeed(msg); + hil_state->yawspeed = mavlink_msg_hil_state_get_yawspeed(msg); + hil_state->lat = mavlink_msg_hil_state_get_lat(msg); + hil_state->lon = mavlink_msg_hil_state_get_lon(msg); + hil_state->alt = mavlink_msg_hil_state_get_alt(msg); + hil_state->vx = mavlink_msg_hil_state_get_vx(msg); + hil_state->vy = mavlink_msg_hil_state_get_vy(msg); + hil_state->vz = mavlink_msg_hil_state_get_vz(msg); + hil_state->xacc = mavlink_msg_hil_state_get_xacc(msg); + hil_state->yacc = mavlink_msg_hil_state_get_yacc(msg); + hil_state->zacc = mavlink_msg_hil_state_get_zacc(msg); +#else + memcpy(hil_state, _MAV_PAYLOAD(msg), 56); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_local_position.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_local_position.h new file mode 100644 index 0000000000..121fb3af64 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_local_position.h @@ -0,0 +1,276 @@ +// MESSAGE LOCAL_POSITION PACKING + +#define MAVLINK_MSG_ID_LOCAL_POSITION 31 + +typedef struct __mavlink_local_position_t +{ + uint64_t usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + float x; ///< X Position + float y; ///< Y Position + float z; ///< Z Position + float vx; ///< X Speed + float vy; ///< Y Speed + float vz; ///< Z Speed +} mavlink_local_position_t; + +#define MAVLINK_MSG_ID_LOCAL_POSITION_LEN 32 +#define MAVLINK_MSG_ID_31_LEN 32 + + + +#define MAVLINK_MESSAGE_INFO_LOCAL_POSITION { \ + "LOCAL_POSITION", \ + 7, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_local_position_t, usec) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_local_position_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_local_position_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_local_position_t, z) }, \ + { "vx", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_local_position_t, vx) }, \ + { "vy", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_local_position_t, vy) }, \ + { "vz", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_local_position_t, vz) }, \ + } \ +} + + +/** + * @brief Pack a local_position message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param vx X Speed + * @param vy Y Speed + * @param vz Z Speed + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_local_position_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, float x, float y, float z, float vx, float vy, float vz) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, vx); + _mav_put_float(buf, 24, vy); + _mav_put_float(buf, 28, vz); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_local_position_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_LOCAL_POSITION; + return mavlink_finalize_message(msg, system_id, component_id, 32); +} + +/** + * @brief Pack a local_position message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param vx X Speed + * @param vy Y Speed + * @param vz Z Speed + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_local_position_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float x,float y,float z,float vx,float vy,float vz) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, vx); + _mav_put_float(buf, 24, vy); + _mav_put_float(buf, 28, vz); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_local_position_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_LOCAL_POSITION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32); +} + +/** + * @brief Encode a local_position struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param local_position C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_local_position_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_local_position_t* local_position) +{ + return mavlink_msg_local_position_pack(system_id, component_id, msg, local_position->usec, local_position->x, local_position->y, local_position->z, local_position->vx, local_position->vy, local_position->vz); +} + +/** + * @brief Send a local_position message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param vx X Speed + * @param vy Y Speed + * @param vz Z Speed + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_local_position_send(mavlink_channel_t chan, uint64_t usec, float x, float y, float z, float vx, float vy, float vz) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, vx); + _mav_put_float(buf, 24, vy); + _mav_put_float(buf, 28, vz); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LOCAL_POSITION, buf, 32); +#else + mavlink_local_position_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LOCAL_POSITION, (const char *)&packet, 32); +#endif +} + +#endif + +// MESSAGE LOCAL_POSITION UNPACKING + + +/** + * @brief Get field usec from local_position message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_local_position_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field x from local_position message + * + * @return X Position + */ +static inline float mavlink_msg_local_position_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field y from local_position message + * + * @return Y Position + */ +static inline float mavlink_msg_local_position_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field z from local_position message + * + * @return Z Position + */ +static inline float mavlink_msg_local_position_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field vx from local_position message + * + * @return X Speed + */ +static inline float mavlink_msg_local_position_get_vx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field vy from local_position message + * + * @return Y Speed + */ +static inline float mavlink_msg_local_position_get_vy(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field vz from local_position message + * + * @return Z Speed + */ +static inline float mavlink_msg_local_position_get_vz(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Decode a local_position message into a struct + * + * @param msg The message to decode + * @param local_position C-struct to decode the message contents into + */ +static inline void mavlink_msg_local_position_decode(const mavlink_message_t* msg, mavlink_local_position_t* local_position) +{ +#if MAVLINK_NEED_BYTE_SWAP + local_position->usec = mavlink_msg_local_position_get_usec(msg); + local_position->x = mavlink_msg_local_position_get_x(msg); + local_position->y = mavlink_msg_local_position_get_y(msg); + local_position->z = mavlink_msg_local_position_get_z(msg); + local_position->vx = mavlink_msg_local_position_get_vx(msg); + local_position->vy = mavlink_msg_local_position_get_vy(msg); + local_position->vz = mavlink_msg_local_position_get_vz(msg); +#else + memcpy(local_position, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_local_position_setpoint.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_local_position_setpoint.h new file mode 100644 index 0000000000..2e6178d96e --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_local_position_setpoint.h @@ -0,0 +1,210 @@ +// MESSAGE LOCAL_POSITION_SETPOINT PACKING + +#define MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT 51 + +typedef struct __mavlink_local_position_setpoint_t +{ + float x; ///< x position + float y; ///< y position + float z; ///< z position + float yaw; ///< Desired yaw angle +} mavlink_local_position_setpoint_t; + +#define MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT_LEN 16 +#define MAVLINK_MSG_ID_51_LEN 16 + + + +#define MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT { \ + "LOCAL_POSITION_SETPOINT", \ + 4, \ + { { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_local_position_setpoint_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_local_position_setpoint_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_local_position_setpoint_t, z) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_local_position_setpoint_t, yaw) }, \ + } \ +} + + +/** + * @brief Pack a local_position_setpoint message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param x x position + * @param y y position + * @param z z position + * @param yaw Desired yaw angle + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_local_position_setpoint_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_local_position_setpoint_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT; + return mavlink_finalize_message(msg, system_id, component_id, 16); +} + +/** + * @brief Pack a local_position_setpoint message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param x x position + * @param y y position + * @param z z position + * @param yaw Desired yaw angle + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_local_position_setpoint_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float x,float y,float z,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_local_position_setpoint_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 16); +} + +/** + * @brief Encode a local_position_setpoint struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param local_position_setpoint C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_local_position_setpoint_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_local_position_setpoint_t* local_position_setpoint) +{ + return mavlink_msg_local_position_setpoint_pack(system_id, component_id, msg, local_position_setpoint->x, local_position_setpoint->y, local_position_setpoint->z, local_position_setpoint->yaw); +} + +/** + * @brief Send a local_position_setpoint message + * @param chan MAVLink channel to send the message + * + * @param x x position + * @param y y position + * @param z z position + * @param yaw Desired yaw angle + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_local_position_setpoint_send(mavlink_channel_t chan, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT, buf, 16); +#else + mavlink_local_position_setpoint_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT, (const char *)&packet, 16); +#endif +} + +#endif + +// MESSAGE LOCAL_POSITION_SETPOINT UNPACKING + + +/** + * @brief Get field x from local_position_setpoint message + * + * @return x position + */ +static inline float mavlink_msg_local_position_setpoint_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field y from local_position_setpoint message + * + * @return y position + */ +static inline float mavlink_msg_local_position_setpoint_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field z from local_position_setpoint message + * + * @return z position + */ +static inline float mavlink_msg_local_position_setpoint_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field yaw from local_position_setpoint message + * + * @return Desired yaw angle + */ +static inline float mavlink_msg_local_position_setpoint_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Decode a local_position_setpoint message into a struct + * + * @param msg The message to decode + * @param local_position_setpoint C-struct to decode the message contents into + */ +static inline void mavlink_msg_local_position_setpoint_decode(const mavlink_message_t* msg, mavlink_local_position_setpoint_t* local_position_setpoint) +{ +#if MAVLINK_NEED_BYTE_SWAP + local_position_setpoint->x = mavlink_msg_local_position_setpoint_get_x(msg); + local_position_setpoint->y = mavlink_msg_local_position_setpoint_get_y(msg); + local_position_setpoint->z = mavlink_msg_local_position_setpoint_get_z(msg); + local_position_setpoint->yaw = mavlink_msg_local_position_setpoint_get_yaw(msg); +#else + memcpy(local_position_setpoint, _MAV_PAYLOAD(msg), 16); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_local_position_setpoint_set.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_local_position_setpoint_set.h new file mode 100644 index 0000000000..e676c28329 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_local_position_setpoint_set.h @@ -0,0 +1,254 @@ +// MESSAGE LOCAL_POSITION_SETPOINT_SET PACKING + +#define MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT_SET 50 + +typedef struct __mavlink_local_position_setpoint_set_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + float x; ///< x position + float y; ///< y position + float z; ///< z position + float yaw; ///< Desired yaw angle +} mavlink_local_position_setpoint_set_t; + +#define MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT_SET_LEN 18 +#define MAVLINK_MSG_ID_50_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT_SET { \ + "LOCAL_POSITION_SETPOINT_SET", \ + 6, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_local_position_setpoint_set_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_local_position_setpoint_set_t, target_component) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 2, offsetof(mavlink_local_position_setpoint_set_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 6, offsetof(mavlink_local_position_setpoint_set_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 10, offsetof(mavlink_local_position_setpoint_set_t, z) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 14, offsetof(mavlink_local_position_setpoint_set_t, yaw) }, \ + } \ +} + + +/** + * @brief Pack a local_position_setpoint_set message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param x x position + * @param y y position + * @param z z position + * @param yaw Desired yaw angle + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_local_position_setpoint_set_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 2, x); + _mav_put_float(buf, 6, y); + _mav_put_float(buf, 10, z); + _mav_put_float(buf, 14, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_local_position_setpoint_set_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT_SET; + return mavlink_finalize_message(msg, system_id, component_id, 18); +} + +/** + * @brief Pack a local_position_setpoint_set message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param x x position + * @param y y position + * @param z z position + * @param yaw Desired yaw angle + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_local_position_setpoint_set_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,float x,float y,float z,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 2, x); + _mav_put_float(buf, 6, y); + _mav_put_float(buf, 10, z); + _mav_put_float(buf, 14, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_local_position_setpoint_set_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT_SET; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18); +} + +/** + * @brief Encode a local_position_setpoint_set struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param local_position_setpoint_set C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_local_position_setpoint_set_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_local_position_setpoint_set_t* local_position_setpoint_set) +{ + return mavlink_msg_local_position_setpoint_set_pack(system_id, component_id, msg, local_position_setpoint_set->target_system, local_position_setpoint_set->target_component, local_position_setpoint_set->x, local_position_setpoint_set->y, local_position_setpoint_set->z, local_position_setpoint_set->yaw); +} + +/** + * @brief Send a local_position_setpoint_set message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param x x position + * @param y y position + * @param z z position + * @param yaw Desired yaw angle + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_local_position_setpoint_set_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 2, x); + _mav_put_float(buf, 6, y); + _mav_put_float(buf, 10, z); + _mav_put_float(buf, 14, yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT_SET, buf, 18); +#else + mavlink_local_position_setpoint_set_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT_SET, (const char *)&packet, 18); +#endif +} + +#endif + +// MESSAGE LOCAL_POSITION_SETPOINT_SET UNPACKING + + +/** + * @brief Get field target_system from local_position_setpoint_set message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_local_position_setpoint_set_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from local_position_setpoint_set message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_local_position_setpoint_set_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field x from local_position_setpoint_set message + * + * @return x position + */ +static inline float mavlink_msg_local_position_setpoint_set_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 2); +} + +/** + * @brief Get field y from local_position_setpoint_set message + * + * @return y position + */ +static inline float mavlink_msg_local_position_setpoint_set_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 6); +} + +/** + * @brief Get field z from local_position_setpoint_set message + * + * @return z position + */ +static inline float mavlink_msg_local_position_setpoint_set_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 10); +} + +/** + * @brief Get field yaw from local_position_setpoint_set message + * + * @return Desired yaw angle + */ +static inline float mavlink_msg_local_position_setpoint_set_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 14); +} + +/** + * @brief Decode a local_position_setpoint_set message into a struct + * + * @param msg The message to decode + * @param local_position_setpoint_set C-struct to decode the message contents into + */ +static inline void mavlink_msg_local_position_setpoint_set_decode(const mavlink_message_t* msg, mavlink_local_position_setpoint_set_t* local_position_setpoint_set) +{ +#if MAVLINK_NEED_BYTE_SWAP + local_position_setpoint_set->target_system = mavlink_msg_local_position_setpoint_set_get_target_system(msg); + local_position_setpoint_set->target_component = mavlink_msg_local_position_setpoint_set_get_target_component(msg); + local_position_setpoint_set->x = mavlink_msg_local_position_setpoint_set_get_x(msg); + local_position_setpoint_set->y = mavlink_msg_local_position_setpoint_set_get_y(msg); + local_position_setpoint_set->z = mavlink_msg_local_position_setpoint_set_get_z(msg); + local_position_setpoint_set->yaw = mavlink_msg_local_position_setpoint_set_get_yaw(msg); +#else + memcpy(local_position_setpoint_set, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_manual_control.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_manual_control.h new file mode 100644 index 0000000000..26b70ce4ae --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_manual_control.h @@ -0,0 +1,320 @@ +// MESSAGE MANUAL_CONTROL PACKING + +#define MAVLINK_MSG_ID_MANUAL_CONTROL 69 + +typedef struct __mavlink_manual_control_t +{ + uint8_t target; ///< The system to be controlled + float roll; ///< roll + float pitch; ///< pitch + float yaw; ///< yaw + float thrust; ///< thrust + uint8_t roll_manual; ///< roll control enabled auto:0, manual:1 + uint8_t pitch_manual; ///< pitch auto:0, manual:1 + uint8_t yaw_manual; ///< yaw auto:0, manual:1 + uint8_t thrust_manual; ///< thrust auto:0, manual:1 +} mavlink_manual_control_t; + +#define MAVLINK_MSG_ID_MANUAL_CONTROL_LEN 21 +#define MAVLINK_MSG_ID_69_LEN 21 + + + +#define MAVLINK_MESSAGE_INFO_MANUAL_CONTROL { \ + "MANUAL_CONTROL", \ + 9, \ + { { "target", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_manual_control_t, target) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 1, offsetof(mavlink_manual_control_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 5, offsetof(mavlink_manual_control_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 9, offsetof(mavlink_manual_control_t, yaw) }, \ + { "thrust", NULL, MAVLINK_TYPE_FLOAT, 0, 13, offsetof(mavlink_manual_control_t, thrust) }, \ + { "roll_manual", NULL, MAVLINK_TYPE_UINT8_T, 0, 17, offsetof(mavlink_manual_control_t, roll_manual) }, \ + { "pitch_manual", NULL, MAVLINK_TYPE_UINT8_T, 0, 18, offsetof(mavlink_manual_control_t, pitch_manual) }, \ + { "yaw_manual", NULL, MAVLINK_TYPE_UINT8_T, 0, 19, offsetof(mavlink_manual_control_t, yaw_manual) }, \ + { "thrust_manual", NULL, MAVLINK_TYPE_UINT8_T, 0, 20, offsetof(mavlink_manual_control_t, thrust_manual) }, \ + } \ +} + + +/** + * @brief Pack a manual_control message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target The system to be controlled + * @param roll roll + * @param pitch pitch + * @param yaw yaw + * @param thrust thrust + * @param roll_manual roll control enabled auto:0, manual:1 + * @param pitch_manual pitch auto:0, manual:1 + * @param yaw_manual yaw auto:0, manual:1 + * @param thrust_manual thrust auto:0, manual:1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_manual_control_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target, float roll, float pitch, float yaw, float thrust, uint8_t roll_manual, uint8_t pitch_manual, uint8_t yaw_manual, uint8_t thrust_manual) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_float(buf, 1, roll); + _mav_put_float(buf, 5, pitch); + _mav_put_float(buf, 9, yaw); + _mav_put_float(buf, 13, thrust); + _mav_put_uint8_t(buf, 17, roll_manual); + _mav_put_uint8_t(buf, 18, pitch_manual); + _mav_put_uint8_t(buf, 19, yaw_manual); + _mav_put_uint8_t(buf, 20, thrust_manual); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 21); +#else + mavlink_manual_control_t packet; + packet.target = target; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + packet.roll_manual = roll_manual; + packet.pitch_manual = pitch_manual; + packet.yaw_manual = yaw_manual; + packet.thrust_manual = thrust_manual; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 21); +#endif + + msg->msgid = MAVLINK_MSG_ID_MANUAL_CONTROL; + return mavlink_finalize_message(msg, system_id, component_id, 21); +} + +/** + * @brief Pack a manual_control message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system to be controlled + * @param roll roll + * @param pitch pitch + * @param yaw yaw + * @param thrust thrust + * @param roll_manual roll control enabled auto:0, manual:1 + * @param pitch_manual pitch auto:0, manual:1 + * @param yaw_manual yaw auto:0, manual:1 + * @param thrust_manual thrust auto:0, manual:1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_manual_control_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,float roll,float pitch,float yaw,float thrust,uint8_t roll_manual,uint8_t pitch_manual,uint8_t yaw_manual,uint8_t thrust_manual) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_float(buf, 1, roll); + _mav_put_float(buf, 5, pitch); + _mav_put_float(buf, 9, yaw); + _mav_put_float(buf, 13, thrust); + _mav_put_uint8_t(buf, 17, roll_manual); + _mav_put_uint8_t(buf, 18, pitch_manual); + _mav_put_uint8_t(buf, 19, yaw_manual); + _mav_put_uint8_t(buf, 20, thrust_manual); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 21); +#else + mavlink_manual_control_t packet; + packet.target = target; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + packet.roll_manual = roll_manual; + packet.pitch_manual = pitch_manual; + packet.yaw_manual = yaw_manual; + packet.thrust_manual = thrust_manual; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 21); +#endif + + msg->msgid = MAVLINK_MSG_ID_MANUAL_CONTROL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 21); +} + +/** + * @brief Encode a manual_control struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param manual_control C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_manual_control_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_manual_control_t* manual_control) +{ + return mavlink_msg_manual_control_pack(system_id, component_id, msg, manual_control->target, manual_control->roll, manual_control->pitch, manual_control->yaw, manual_control->thrust, manual_control->roll_manual, manual_control->pitch_manual, manual_control->yaw_manual, manual_control->thrust_manual); +} + +/** + * @brief Send a manual_control message + * @param chan MAVLink channel to send the message + * + * @param target The system to be controlled + * @param roll roll + * @param pitch pitch + * @param yaw yaw + * @param thrust thrust + * @param roll_manual roll control enabled auto:0, manual:1 + * @param pitch_manual pitch auto:0, manual:1 + * @param yaw_manual yaw auto:0, manual:1 + * @param thrust_manual thrust auto:0, manual:1 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_manual_control_send(mavlink_channel_t chan, uint8_t target, float roll, float pitch, float yaw, float thrust, uint8_t roll_manual, uint8_t pitch_manual, uint8_t yaw_manual, uint8_t thrust_manual) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_float(buf, 1, roll); + _mav_put_float(buf, 5, pitch); + _mav_put_float(buf, 9, yaw); + _mav_put_float(buf, 13, thrust); + _mav_put_uint8_t(buf, 17, roll_manual); + _mav_put_uint8_t(buf, 18, pitch_manual); + _mav_put_uint8_t(buf, 19, yaw_manual); + _mav_put_uint8_t(buf, 20, thrust_manual); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MANUAL_CONTROL, buf, 21); +#else + mavlink_manual_control_t packet; + packet.target = target; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + packet.roll_manual = roll_manual; + packet.pitch_manual = pitch_manual; + packet.yaw_manual = yaw_manual; + packet.thrust_manual = thrust_manual; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MANUAL_CONTROL, (const char *)&packet, 21); +#endif +} + +#endif + +// MESSAGE MANUAL_CONTROL UNPACKING + + +/** + * @brief Get field target from manual_control message + * + * @return The system to be controlled + */ +static inline uint8_t mavlink_msg_manual_control_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field roll from manual_control message + * + * @return roll + */ +static inline float mavlink_msg_manual_control_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 1); +} + +/** + * @brief Get field pitch from manual_control message + * + * @return pitch + */ +static inline float mavlink_msg_manual_control_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 5); +} + +/** + * @brief Get field yaw from manual_control message + * + * @return yaw + */ +static inline float mavlink_msg_manual_control_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 9); +} + +/** + * @brief Get field thrust from manual_control message + * + * @return thrust + */ +static inline float mavlink_msg_manual_control_get_thrust(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 13); +} + +/** + * @brief Get field roll_manual from manual_control message + * + * @return roll control enabled auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_manual_control_get_roll_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 17); +} + +/** + * @brief Get field pitch_manual from manual_control message + * + * @return pitch auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_manual_control_get_pitch_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 18); +} + +/** + * @brief Get field yaw_manual from manual_control message + * + * @return yaw auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_manual_control_get_yaw_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 19); +} + +/** + * @brief Get field thrust_manual from manual_control message + * + * @return thrust auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_manual_control_get_thrust_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 20); +} + +/** + * @brief Decode a manual_control message into a struct + * + * @param msg The message to decode + * @param manual_control C-struct to decode the message contents into + */ +static inline void mavlink_msg_manual_control_decode(const mavlink_message_t* msg, mavlink_manual_control_t* manual_control) +{ +#if MAVLINK_NEED_BYTE_SWAP + manual_control->target = mavlink_msg_manual_control_get_target(msg); + manual_control->roll = mavlink_msg_manual_control_get_roll(msg); + manual_control->pitch = mavlink_msg_manual_control_get_pitch(msg); + manual_control->yaw = mavlink_msg_manual_control_get_yaw(msg); + manual_control->thrust = mavlink_msg_manual_control_get_thrust(msg); + manual_control->roll_manual = mavlink_msg_manual_control_get_roll_manual(msg); + manual_control->pitch_manual = mavlink_msg_manual_control_get_pitch_manual(msg); + manual_control->yaw_manual = mavlink_msg_manual_control_get_yaw_manual(msg); + manual_control->thrust_manual = mavlink_msg_manual_control_get_thrust_manual(msg); +#else + memcpy(manual_control, _MAV_PAYLOAD(msg), 21); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_named_value_float.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_named_value_float.h new file mode 100644 index 0000000000..5cf76e372e --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_named_value_float.h @@ -0,0 +1,160 @@ +// MESSAGE NAMED_VALUE_FLOAT PACKING + +#define MAVLINK_MSG_ID_NAMED_VALUE_FLOAT 252 + +typedef struct __mavlink_named_value_float_t +{ + char name[10]; ///< Name of the debug variable + float value; ///< Floating point value +} mavlink_named_value_float_t; + +#define MAVLINK_MSG_ID_NAMED_VALUE_FLOAT_LEN 14 +#define MAVLINK_MSG_ID_252_LEN 14 + +#define MAVLINK_MSG_NAMED_VALUE_FLOAT_FIELD_NAME_LEN 10 + +#define MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT { \ + "NAMED_VALUE_FLOAT", \ + 2, \ + { { "name", NULL, MAVLINK_TYPE_CHAR, 10, 0, offsetof(mavlink_named_value_float_t, name) }, \ + { "value", NULL, MAVLINK_TYPE_FLOAT, 0, 10, offsetof(mavlink_named_value_float_t, value) }, \ + } \ +} + + +/** + * @brief Pack a named_value_float message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param name Name of the debug variable + * @param value Floating point value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_named_value_float_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const char *name, float value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_float(buf, 10, value); + _mav_put_char_array(buf, 0, name, 10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_named_value_float_t packet; + packet.value = value; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAMED_VALUE_FLOAT; + return mavlink_finalize_message(msg, system_id, component_id, 14); +} + +/** + * @brief Pack a named_value_float message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param name Name of the debug variable + * @param value Floating point value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_named_value_float_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const char *name,float value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_float(buf, 10, value); + _mav_put_char_array(buf, 0, name, 10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_named_value_float_t packet; + packet.value = value; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAMED_VALUE_FLOAT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 14); +} + +/** + * @brief Encode a named_value_float struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param named_value_float C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_named_value_float_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_named_value_float_t* named_value_float) +{ + return mavlink_msg_named_value_float_pack(system_id, component_id, msg, named_value_float->name, named_value_float->value); +} + +/** + * @brief Send a named_value_float message + * @param chan MAVLink channel to send the message + * + * @param name Name of the debug variable + * @param value Floating point value + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_named_value_float_send(mavlink_channel_t chan, const char *name, float value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_float(buf, 10, value); + _mav_put_char_array(buf, 0, name, 10); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAMED_VALUE_FLOAT, buf, 14); +#else + mavlink_named_value_float_t packet; + packet.value = value; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAMED_VALUE_FLOAT, (const char *)&packet, 14); +#endif +} + +#endif + +// MESSAGE NAMED_VALUE_FLOAT UNPACKING + + +/** + * @brief Get field name from named_value_float message + * + * @return Name of the debug variable + */ +static inline uint16_t mavlink_msg_named_value_float_get_name(const mavlink_message_t* msg, char *name) +{ + return _MAV_RETURN_char_array(msg, name, 10, 0); +} + +/** + * @brief Get field value from named_value_float message + * + * @return Floating point value + */ +static inline float mavlink_msg_named_value_float_get_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 10); +} + +/** + * @brief Decode a named_value_float message into a struct + * + * @param msg The message to decode + * @param named_value_float C-struct to decode the message contents into + */ +static inline void mavlink_msg_named_value_float_decode(const mavlink_message_t* msg, mavlink_named_value_float_t* named_value_float) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_named_value_float_get_name(msg, named_value_float->name); + named_value_float->value = mavlink_msg_named_value_float_get_value(msg); +#else + memcpy(named_value_float, _MAV_PAYLOAD(msg), 14); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_named_value_int.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_named_value_int.h new file mode 100644 index 0000000000..93f0911aa8 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_named_value_int.h @@ -0,0 +1,160 @@ +// MESSAGE NAMED_VALUE_INT PACKING + +#define MAVLINK_MSG_ID_NAMED_VALUE_INT 253 + +typedef struct __mavlink_named_value_int_t +{ + char name[10]; ///< Name of the debug variable + int32_t value; ///< Signed integer value +} mavlink_named_value_int_t; + +#define MAVLINK_MSG_ID_NAMED_VALUE_INT_LEN 14 +#define MAVLINK_MSG_ID_253_LEN 14 + +#define MAVLINK_MSG_NAMED_VALUE_INT_FIELD_NAME_LEN 10 + +#define MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT { \ + "NAMED_VALUE_INT", \ + 2, \ + { { "name", NULL, MAVLINK_TYPE_CHAR, 10, 0, offsetof(mavlink_named_value_int_t, name) }, \ + { "value", NULL, MAVLINK_TYPE_INT32_T, 0, 10, offsetof(mavlink_named_value_int_t, value) }, \ + } \ +} + + +/** + * @brief Pack a named_value_int message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param name Name of the debug variable + * @param value Signed integer value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_named_value_int_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const char *name, int32_t value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_int32_t(buf, 10, value); + _mav_put_char_array(buf, 0, name, 10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_named_value_int_t packet; + packet.value = value; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAMED_VALUE_INT; + return mavlink_finalize_message(msg, system_id, component_id, 14); +} + +/** + * @brief Pack a named_value_int message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param name Name of the debug variable + * @param value Signed integer value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_named_value_int_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const char *name,int32_t value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_int32_t(buf, 10, value); + _mav_put_char_array(buf, 0, name, 10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_named_value_int_t packet; + packet.value = value; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAMED_VALUE_INT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 14); +} + +/** + * @brief Encode a named_value_int struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param named_value_int C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_named_value_int_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_named_value_int_t* named_value_int) +{ + return mavlink_msg_named_value_int_pack(system_id, component_id, msg, named_value_int->name, named_value_int->value); +} + +/** + * @brief Send a named_value_int message + * @param chan MAVLink channel to send the message + * + * @param name Name of the debug variable + * @param value Signed integer value + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_named_value_int_send(mavlink_channel_t chan, const char *name, int32_t value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_int32_t(buf, 10, value); + _mav_put_char_array(buf, 0, name, 10); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAMED_VALUE_INT, buf, 14); +#else + mavlink_named_value_int_t packet; + packet.value = value; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAMED_VALUE_INT, (const char *)&packet, 14); +#endif +} + +#endif + +// MESSAGE NAMED_VALUE_INT UNPACKING + + +/** + * @brief Get field name from named_value_int message + * + * @return Name of the debug variable + */ +static inline uint16_t mavlink_msg_named_value_int_get_name(const mavlink_message_t* msg, char *name) +{ + return _MAV_RETURN_char_array(msg, name, 10, 0); +} + +/** + * @brief Get field value from named_value_int message + * + * @return Signed integer value + */ +static inline int32_t mavlink_msg_named_value_int_get_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 10); +} + +/** + * @brief Decode a named_value_int message into a struct + * + * @param msg The message to decode + * @param named_value_int C-struct to decode the message contents into + */ +static inline void mavlink_msg_named_value_int_decode(const mavlink_message_t* msg, mavlink_named_value_int_t* named_value_int) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_named_value_int_get_name(msg, named_value_int->name); + named_value_int->value = mavlink_msg_named_value_int_get_value(msg); +#else + memcpy(named_value_int, _MAV_PAYLOAD(msg), 14); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_nav_controller_output.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_nav_controller_output.h new file mode 100644 index 0000000000..64a4a7fb4e --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_nav_controller_output.h @@ -0,0 +1,298 @@ +// MESSAGE NAV_CONTROLLER_OUTPUT PACKING + +#define MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT 62 + +typedef struct __mavlink_nav_controller_output_t +{ + float nav_roll; ///< Current desired roll in degrees + float nav_pitch; ///< Current desired pitch in degrees + int16_t nav_bearing; ///< Current desired heading in degrees + int16_t target_bearing; ///< Bearing to current waypoint/target in degrees + uint16_t wp_dist; ///< Distance to active waypoint in meters + float alt_error; ///< Current altitude error in meters + float aspd_error; ///< Current airspeed error in meters/second + float xtrack_error; ///< Current crosstrack error on x-y plane in meters +} mavlink_nav_controller_output_t; + +#define MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT_LEN 26 +#define MAVLINK_MSG_ID_62_LEN 26 + + + +#define MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT { \ + "NAV_CONTROLLER_OUTPUT", \ + 8, \ + { { "nav_roll", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_nav_controller_output_t, nav_roll) }, \ + { "nav_pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_nav_controller_output_t, nav_pitch) }, \ + { "nav_bearing", NULL, MAVLINK_TYPE_INT16_T, 0, 8, offsetof(mavlink_nav_controller_output_t, nav_bearing) }, \ + { "target_bearing", NULL, MAVLINK_TYPE_INT16_T, 0, 10, offsetof(mavlink_nav_controller_output_t, target_bearing) }, \ + { "wp_dist", NULL, MAVLINK_TYPE_UINT16_T, 0, 12, offsetof(mavlink_nav_controller_output_t, wp_dist) }, \ + { "alt_error", NULL, MAVLINK_TYPE_FLOAT, 0, 14, offsetof(mavlink_nav_controller_output_t, alt_error) }, \ + { "aspd_error", NULL, MAVLINK_TYPE_FLOAT, 0, 18, offsetof(mavlink_nav_controller_output_t, aspd_error) }, \ + { "xtrack_error", NULL, MAVLINK_TYPE_FLOAT, 0, 22, offsetof(mavlink_nav_controller_output_t, xtrack_error) }, \ + } \ +} + + +/** + * @brief Pack a nav_controller_output message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param nav_roll Current desired roll in degrees + * @param nav_pitch Current desired pitch in degrees + * @param nav_bearing Current desired heading in degrees + * @param target_bearing Bearing to current waypoint/target in degrees + * @param wp_dist Distance to active waypoint in meters + * @param alt_error Current altitude error in meters + * @param aspd_error Current airspeed error in meters/second + * @param xtrack_error Current crosstrack error on x-y plane in meters + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_nav_controller_output_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float nav_roll, float nav_pitch, int16_t nav_bearing, int16_t target_bearing, uint16_t wp_dist, float alt_error, float aspd_error, float xtrack_error) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_float(buf, 0, nav_roll); + _mav_put_float(buf, 4, nav_pitch); + _mav_put_int16_t(buf, 8, nav_bearing); + _mav_put_int16_t(buf, 10, target_bearing); + _mav_put_uint16_t(buf, 12, wp_dist); + _mav_put_float(buf, 14, alt_error); + _mav_put_float(buf, 18, aspd_error); + _mav_put_float(buf, 22, xtrack_error); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_nav_controller_output_t packet; + packet.nav_roll = nav_roll; + packet.nav_pitch = nav_pitch; + packet.nav_bearing = nav_bearing; + packet.target_bearing = target_bearing; + packet.wp_dist = wp_dist; + packet.alt_error = alt_error; + packet.aspd_error = aspd_error; + packet.xtrack_error = xtrack_error; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT; + return mavlink_finalize_message(msg, system_id, component_id, 26); +} + +/** + * @brief Pack a nav_controller_output message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param nav_roll Current desired roll in degrees + * @param nav_pitch Current desired pitch in degrees + * @param nav_bearing Current desired heading in degrees + * @param target_bearing Bearing to current waypoint/target in degrees + * @param wp_dist Distance to active waypoint in meters + * @param alt_error Current altitude error in meters + * @param aspd_error Current airspeed error in meters/second + * @param xtrack_error Current crosstrack error on x-y plane in meters + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_nav_controller_output_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float nav_roll,float nav_pitch,int16_t nav_bearing,int16_t target_bearing,uint16_t wp_dist,float alt_error,float aspd_error,float xtrack_error) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_float(buf, 0, nav_roll); + _mav_put_float(buf, 4, nav_pitch); + _mav_put_int16_t(buf, 8, nav_bearing); + _mav_put_int16_t(buf, 10, target_bearing); + _mav_put_uint16_t(buf, 12, wp_dist); + _mav_put_float(buf, 14, alt_error); + _mav_put_float(buf, 18, aspd_error); + _mav_put_float(buf, 22, xtrack_error); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_nav_controller_output_t packet; + packet.nav_roll = nav_roll; + packet.nav_pitch = nav_pitch; + packet.nav_bearing = nav_bearing; + packet.target_bearing = target_bearing; + packet.wp_dist = wp_dist; + packet.alt_error = alt_error; + packet.aspd_error = aspd_error; + packet.xtrack_error = xtrack_error; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 26); +} + +/** + * @brief Encode a nav_controller_output struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param nav_controller_output C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_nav_controller_output_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_nav_controller_output_t* nav_controller_output) +{ + return mavlink_msg_nav_controller_output_pack(system_id, component_id, msg, nav_controller_output->nav_roll, nav_controller_output->nav_pitch, nav_controller_output->nav_bearing, nav_controller_output->target_bearing, nav_controller_output->wp_dist, nav_controller_output->alt_error, nav_controller_output->aspd_error, nav_controller_output->xtrack_error); +} + +/** + * @brief Send a nav_controller_output message + * @param chan MAVLink channel to send the message + * + * @param nav_roll Current desired roll in degrees + * @param nav_pitch Current desired pitch in degrees + * @param nav_bearing Current desired heading in degrees + * @param target_bearing Bearing to current waypoint/target in degrees + * @param wp_dist Distance to active waypoint in meters + * @param alt_error Current altitude error in meters + * @param aspd_error Current airspeed error in meters/second + * @param xtrack_error Current crosstrack error on x-y plane in meters + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_nav_controller_output_send(mavlink_channel_t chan, float nav_roll, float nav_pitch, int16_t nav_bearing, int16_t target_bearing, uint16_t wp_dist, float alt_error, float aspd_error, float xtrack_error) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_float(buf, 0, nav_roll); + _mav_put_float(buf, 4, nav_pitch); + _mav_put_int16_t(buf, 8, nav_bearing); + _mav_put_int16_t(buf, 10, target_bearing); + _mav_put_uint16_t(buf, 12, wp_dist); + _mav_put_float(buf, 14, alt_error); + _mav_put_float(buf, 18, aspd_error); + _mav_put_float(buf, 22, xtrack_error); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT, buf, 26); +#else + mavlink_nav_controller_output_t packet; + packet.nav_roll = nav_roll; + packet.nav_pitch = nav_pitch; + packet.nav_bearing = nav_bearing; + packet.target_bearing = target_bearing; + packet.wp_dist = wp_dist; + packet.alt_error = alt_error; + packet.aspd_error = aspd_error; + packet.xtrack_error = xtrack_error; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT, (const char *)&packet, 26); +#endif +} + +#endif + +// MESSAGE NAV_CONTROLLER_OUTPUT UNPACKING + + +/** + * @brief Get field nav_roll from nav_controller_output message + * + * @return Current desired roll in degrees + */ +static inline float mavlink_msg_nav_controller_output_get_nav_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field nav_pitch from nav_controller_output message + * + * @return Current desired pitch in degrees + */ +static inline float mavlink_msg_nav_controller_output_get_nav_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field nav_bearing from nav_controller_output message + * + * @return Current desired heading in degrees + */ +static inline int16_t mavlink_msg_nav_controller_output_get_nav_bearing(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 8); +} + +/** + * @brief Get field target_bearing from nav_controller_output message + * + * @return Bearing to current waypoint/target in degrees + */ +static inline int16_t mavlink_msg_nav_controller_output_get_target_bearing(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 10); +} + +/** + * @brief Get field wp_dist from nav_controller_output message + * + * @return Distance to active waypoint in meters + */ +static inline uint16_t mavlink_msg_nav_controller_output_get_wp_dist(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 12); +} + +/** + * @brief Get field alt_error from nav_controller_output message + * + * @return Current altitude error in meters + */ +static inline float mavlink_msg_nav_controller_output_get_alt_error(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 14); +} + +/** + * @brief Get field aspd_error from nav_controller_output message + * + * @return Current airspeed error in meters/second + */ +static inline float mavlink_msg_nav_controller_output_get_aspd_error(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 18); +} + +/** + * @brief Get field xtrack_error from nav_controller_output message + * + * @return Current crosstrack error on x-y plane in meters + */ +static inline float mavlink_msg_nav_controller_output_get_xtrack_error(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 22); +} + +/** + * @brief Decode a nav_controller_output message into a struct + * + * @param msg The message to decode + * @param nav_controller_output C-struct to decode the message contents into + */ +static inline void mavlink_msg_nav_controller_output_decode(const mavlink_message_t* msg, mavlink_nav_controller_output_t* nav_controller_output) +{ +#if MAVLINK_NEED_BYTE_SWAP + nav_controller_output->nav_roll = mavlink_msg_nav_controller_output_get_nav_roll(msg); + nav_controller_output->nav_pitch = mavlink_msg_nav_controller_output_get_nav_pitch(msg); + nav_controller_output->nav_bearing = mavlink_msg_nav_controller_output_get_nav_bearing(msg); + nav_controller_output->target_bearing = mavlink_msg_nav_controller_output_get_target_bearing(msg); + nav_controller_output->wp_dist = mavlink_msg_nav_controller_output_get_wp_dist(msg); + nav_controller_output->alt_error = mavlink_msg_nav_controller_output_get_alt_error(msg); + nav_controller_output->aspd_error = mavlink_msg_nav_controller_output_get_aspd_error(msg); + nav_controller_output->xtrack_error = mavlink_msg_nav_controller_output_get_xtrack_error(msg); +#else + memcpy(nav_controller_output, _MAV_PAYLOAD(msg), 26); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_object_detection_event.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_object_detection_event.h new file mode 100644 index 0000000000..617eb50d44 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_object_detection_event.h @@ -0,0 +1,270 @@ +// MESSAGE OBJECT_DETECTION_EVENT PACKING + +#define MAVLINK_MSG_ID_OBJECT_DETECTION_EVENT 140 + +typedef struct __mavlink_object_detection_event_t +{ + uint32_t time; ///< Timestamp in milliseconds since system boot + uint16_t object_id; ///< Object ID + uint8_t type; ///< Object type: 0: image, 1: letter, 2: ground vehicle, 3: air vehicle, 4: surface vehicle, 5: sub-surface vehicle, 6: human, 7: animal + char name[20]; ///< Name of the object as defined by the detector + uint8_t quality; ///< Detection quality / confidence. 0: bad, 255: maximum confidence + float bearing; ///< Angle of the object with respect to the body frame in NED coordinates in radians. 0: front + float distance; ///< Ground distance in meters +} mavlink_object_detection_event_t; + +#define MAVLINK_MSG_ID_OBJECT_DETECTION_EVENT_LEN 36 +#define MAVLINK_MSG_ID_140_LEN 36 + +#define MAVLINK_MSG_OBJECT_DETECTION_EVENT_FIELD_NAME_LEN 20 + +#define MAVLINK_MESSAGE_INFO_OBJECT_DETECTION_EVENT { \ + "OBJECT_DETECTION_EVENT", \ + 7, \ + { { "time", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_object_detection_event_t, time) }, \ + { "object_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_object_detection_event_t, object_id) }, \ + { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_object_detection_event_t, type) }, \ + { "name", NULL, MAVLINK_TYPE_CHAR, 20, 7, offsetof(mavlink_object_detection_event_t, name) }, \ + { "quality", NULL, MAVLINK_TYPE_UINT8_T, 0, 27, offsetof(mavlink_object_detection_event_t, quality) }, \ + { "bearing", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_object_detection_event_t, bearing) }, \ + { "distance", NULL, MAVLINK_TYPE_FLOAT, 0, 32, offsetof(mavlink_object_detection_event_t, distance) }, \ + } \ +} + + +/** + * @brief Pack a object_detection_event message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time Timestamp in milliseconds since system boot + * @param object_id Object ID + * @param type Object type: 0: image, 1: letter, 2: ground vehicle, 3: air vehicle, 4: surface vehicle, 5: sub-surface vehicle, 6: human, 7: animal + * @param name Name of the object as defined by the detector + * @param quality Detection quality / confidence. 0: bad, 255: maximum confidence + * @param bearing Angle of the object with respect to the body frame in NED coordinates in radians. 0: front + * @param distance Ground distance in meters + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_object_detection_event_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time, uint16_t object_id, uint8_t type, const char *name, uint8_t quality, float bearing, float distance) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_uint32_t(buf, 0, time); + _mav_put_uint16_t(buf, 4, object_id); + _mav_put_uint8_t(buf, 6, type); + _mav_put_uint8_t(buf, 27, quality); + _mav_put_float(buf, 28, bearing); + _mav_put_float(buf, 32, distance); + _mav_put_char_array(buf, 7, name, 20); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_object_detection_event_t packet; + packet.time = time; + packet.object_id = object_id; + packet.type = type; + packet.quality = quality; + packet.bearing = bearing; + packet.distance = distance; + mav_array_memcpy(packet.name, name, sizeof(char)*20); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBJECT_DETECTION_EVENT; + return mavlink_finalize_message(msg, system_id, component_id, 36); +} + +/** + * @brief Pack a object_detection_event message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time Timestamp in milliseconds since system boot + * @param object_id Object ID + * @param type Object type: 0: image, 1: letter, 2: ground vehicle, 3: air vehicle, 4: surface vehicle, 5: sub-surface vehicle, 6: human, 7: animal + * @param name Name of the object as defined by the detector + * @param quality Detection quality / confidence. 0: bad, 255: maximum confidence + * @param bearing Angle of the object with respect to the body frame in NED coordinates in radians. 0: front + * @param distance Ground distance in meters + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_object_detection_event_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time,uint16_t object_id,uint8_t type,const char *name,uint8_t quality,float bearing,float distance) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_uint32_t(buf, 0, time); + _mav_put_uint16_t(buf, 4, object_id); + _mav_put_uint8_t(buf, 6, type); + _mav_put_uint8_t(buf, 27, quality); + _mav_put_float(buf, 28, bearing); + _mav_put_float(buf, 32, distance); + _mav_put_char_array(buf, 7, name, 20); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_object_detection_event_t packet; + packet.time = time; + packet.object_id = object_id; + packet.type = type; + packet.quality = quality; + packet.bearing = bearing; + packet.distance = distance; + mav_array_memcpy(packet.name, name, sizeof(char)*20); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBJECT_DETECTION_EVENT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 36); +} + +/** + * @brief Encode a object_detection_event struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param object_detection_event C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_object_detection_event_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_object_detection_event_t* object_detection_event) +{ + return mavlink_msg_object_detection_event_pack(system_id, component_id, msg, object_detection_event->time, object_detection_event->object_id, object_detection_event->type, object_detection_event->name, object_detection_event->quality, object_detection_event->bearing, object_detection_event->distance); +} + +/** + * @brief Send a object_detection_event message + * @param chan MAVLink channel to send the message + * + * @param time Timestamp in milliseconds since system boot + * @param object_id Object ID + * @param type Object type: 0: image, 1: letter, 2: ground vehicle, 3: air vehicle, 4: surface vehicle, 5: sub-surface vehicle, 6: human, 7: animal + * @param name Name of the object as defined by the detector + * @param quality Detection quality / confidence. 0: bad, 255: maximum confidence + * @param bearing Angle of the object with respect to the body frame in NED coordinates in radians. 0: front + * @param distance Ground distance in meters + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_object_detection_event_send(mavlink_channel_t chan, uint32_t time, uint16_t object_id, uint8_t type, const char *name, uint8_t quality, float bearing, float distance) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_uint32_t(buf, 0, time); + _mav_put_uint16_t(buf, 4, object_id); + _mav_put_uint8_t(buf, 6, type); + _mav_put_uint8_t(buf, 27, quality); + _mav_put_float(buf, 28, bearing); + _mav_put_float(buf, 32, distance); + _mav_put_char_array(buf, 7, name, 20); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBJECT_DETECTION_EVENT, buf, 36); +#else + mavlink_object_detection_event_t packet; + packet.time = time; + packet.object_id = object_id; + packet.type = type; + packet.quality = quality; + packet.bearing = bearing; + packet.distance = distance; + mav_array_memcpy(packet.name, name, sizeof(char)*20); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBJECT_DETECTION_EVENT, (const char *)&packet, 36); +#endif +} + +#endif + +// MESSAGE OBJECT_DETECTION_EVENT UNPACKING + + +/** + * @brief Get field time from object_detection_event message + * + * @return Timestamp in milliseconds since system boot + */ +static inline uint32_t mavlink_msg_object_detection_event_get_time(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field object_id from object_detection_event message + * + * @return Object ID + */ +static inline uint16_t mavlink_msg_object_detection_event_get_object_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field type from object_detection_event message + * + * @return Object type: 0: image, 1: letter, 2: ground vehicle, 3: air vehicle, 4: surface vehicle, 5: sub-surface vehicle, 6: human, 7: animal + */ +static inline uint8_t mavlink_msg_object_detection_event_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Get field name from object_detection_event message + * + * @return Name of the object as defined by the detector + */ +static inline uint16_t mavlink_msg_object_detection_event_get_name(const mavlink_message_t* msg, char *name) +{ + return _MAV_RETURN_char_array(msg, name, 20, 7); +} + +/** + * @brief Get field quality from object_detection_event message + * + * @return Detection quality / confidence. 0: bad, 255: maximum confidence + */ +static inline uint8_t mavlink_msg_object_detection_event_get_quality(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 27); +} + +/** + * @brief Get field bearing from object_detection_event message + * + * @return Angle of the object with respect to the body frame in NED coordinates in radians. 0: front + */ +static inline float mavlink_msg_object_detection_event_get_bearing(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field distance from object_detection_event message + * + * @return Ground distance in meters + */ +static inline float mavlink_msg_object_detection_event_get_distance(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 32); +} + +/** + * @brief Decode a object_detection_event message into a struct + * + * @param msg The message to decode + * @param object_detection_event C-struct to decode the message contents into + */ +static inline void mavlink_msg_object_detection_event_decode(const mavlink_message_t* msg, mavlink_object_detection_event_t* object_detection_event) +{ +#if MAVLINK_NEED_BYTE_SWAP + object_detection_event->time = mavlink_msg_object_detection_event_get_time(msg); + object_detection_event->object_id = mavlink_msg_object_detection_event_get_object_id(msg); + object_detection_event->type = mavlink_msg_object_detection_event_get_type(msg); + mavlink_msg_object_detection_event_get_name(msg, object_detection_event->name); + object_detection_event->quality = mavlink_msg_object_detection_event_get_quality(msg); + object_detection_event->bearing = mavlink_msg_object_detection_event_get_bearing(msg); + object_detection_event->distance = mavlink_msg_object_detection_event_get_distance(msg); +#else + memcpy(object_detection_event, _MAV_PAYLOAD(msg), 36); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_optical_flow.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_optical_flow.h new file mode 100644 index 0000000000..33067cc891 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_optical_flow.h @@ -0,0 +1,254 @@ +// MESSAGE OPTICAL_FLOW PACKING + +#define MAVLINK_MSG_ID_OPTICAL_FLOW 100 + +typedef struct __mavlink_optical_flow_t +{ + uint64_t time; ///< Timestamp (UNIX) + uint8_t sensor_id; ///< Sensor ID + int16_t flow_x; ///< Flow in pixels in x-sensor direction + int16_t flow_y; ///< Flow in pixels in y-sensor direction + uint8_t quality; ///< Optical flow quality / confidence. 0: bad, 255: maximum quality + float ground_distance; ///< Ground distance in meters +} mavlink_optical_flow_t; + +#define MAVLINK_MSG_ID_OPTICAL_FLOW_LEN 18 +#define MAVLINK_MSG_ID_100_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_OPTICAL_FLOW { \ + "OPTICAL_FLOW", \ + 6, \ + { { "time", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_optical_flow_t, time) }, \ + { "sensor_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_optical_flow_t, sensor_id) }, \ + { "flow_x", NULL, MAVLINK_TYPE_INT16_T, 0, 9, offsetof(mavlink_optical_flow_t, flow_x) }, \ + { "flow_y", NULL, MAVLINK_TYPE_INT16_T, 0, 11, offsetof(mavlink_optical_flow_t, flow_y) }, \ + { "quality", NULL, MAVLINK_TYPE_UINT8_T, 0, 13, offsetof(mavlink_optical_flow_t, quality) }, \ + { "ground_distance", NULL, MAVLINK_TYPE_FLOAT, 0, 14, offsetof(mavlink_optical_flow_t, ground_distance) }, \ + } \ +} + + +/** + * @brief Pack a optical_flow message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time Timestamp (UNIX) + * @param sensor_id Sensor ID + * @param flow_x Flow in pixels in x-sensor direction + * @param flow_y Flow in pixels in y-sensor direction + * @param quality Optical flow quality / confidence. 0: bad, 255: maximum quality + * @param ground_distance Ground distance in meters + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_optical_flow_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time, uint8_t sensor_id, int16_t flow_x, int16_t flow_y, uint8_t quality, float ground_distance) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint64_t(buf, 0, time); + _mav_put_uint8_t(buf, 8, sensor_id); + _mav_put_int16_t(buf, 9, flow_x); + _mav_put_int16_t(buf, 11, flow_y); + _mav_put_uint8_t(buf, 13, quality); + _mav_put_float(buf, 14, ground_distance); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_optical_flow_t packet; + packet.time = time; + packet.sensor_id = sensor_id; + packet.flow_x = flow_x; + packet.flow_y = flow_y; + packet.quality = quality; + packet.ground_distance = ground_distance; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_OPTICAL_FLOW; + return mavlink_finalize_message(msg, system_id, component_id, 18); +} + +/** + * @brief Pack a optical_flow message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time Timestamp (UNIX) + * @param sensor_id Sensor ID + * @param flow_x Flow in pixels in x-sensor direction + * @param flow_y Flow in pixels in y-sensor direction + * @param quality Optical flow quality / confidence. 0: bad, 255: maximum quality + * @param ground_distance Ground distance in meters + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_optical_flow_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time,uint8_t sensor_id,int16_t flow_x,int16_t flow_y,uint8_t quality,float ground_distance) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint64_t(buf, 0, time); + _mav_put_uint8_t(buf, 8, sensor_id); + _mav_put_int16_t(buf, 9, flow_x); + _mav_put_int16_t(buf, 11, flow_y); + _mav_put_uint8_t(buf, 13, quality); + _mav_put_float(buf, 14, ground_distance); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_optical_flow_t packet; + packet.time = time; + packet.sensor_id = sensor_id; + packet.flow_x = flow_x; + packet.flow_y = flow_y; + packet.quality = quality; + packet.ground_distance = ground_distance; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_OPTICAL_FLOW; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18); +} + +/** + * @brief Encode a optical_flow struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param optical_flow C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_optical_flow_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_optical_flow_t* optical_flow) +{ + return mavlink_msg_optical_flow_pack(system_id, component_id, msg, optical_flow->time, optical_flow->sensor_id, optical_flow->flow_x, optical_flow->flow_y, optical_flow->quality, optical_flow->ground_distance); +} + +/** + * @brief Send a optical_flow message + * @param chan MAVLink channel to send the message + * + * @param time Timestamp (UNIX) + * @param sensor_id Sensor ID + * @param flow_x Flow in pixels in x-sensor direction + * @param flow_y Flow in pixels in y-sensor direction + * @param quality Optical flow quality / confidence. 0: bad, 255: maximum quality + * @param ground_distance Ground distance in meters + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_optical_flow_send(mavlink_channel_t chan, uint64_t time, uint8_t sensor_id, int16_t flow_x, int16_t flow_y, uint8_t quality, float ground_distance) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint64_t(buf, 0, time); + _mav_put_uint8_t(buf, 8, sensor_id); + _mav_put_int16_t(buf, 9, flow_x); + _mav_put_int16_t(buf, 11, flow_y); + _mav_put_uint8_t(buf, 13, quality); + _mav_put_float(buf, 14, ground_distance); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OPTICAL_FLOW, buf, 18); +#else + mavlink_optical_flow_t packet; + packet.time = time; + packet.sensor_id = sensor_id; + packet.flow_x = flow_x; + packet.flow_y = flow_y; + packet.quality = quality; + packet.ground_distance = ground_distance; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OPTICAL_FLOW, (const char *)&packet, 18); +#endif +} + +#endif + +// MESSAGE OPTICAL_FLOW UNPACKING + + +/** + * @brief Get field time from optical_flow message + * + * @return Timestamp (UNIX) + */ +static inline uint64_t mavlink_msg_optical_flow_get_time(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field sensor_id from optical_flow message + * + * @return Sensor ID + */ +static inline uint8_t mavlink_msg_optical_flow_get_sensor_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Get field flow_x from optical_flow message + * + * @return Flow in pixels in x-sensor direction + */ +static inline int16_t mavlink_msg_optical_flow_get_flow_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 9); +} + +/** + * @brief Get field flow_y from optical_flow message + * + * @return Flow in pixels in y-sensor direction + */ +static inline int16_t mavlink_msg_optical_flow_get_flow_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 11); +} + +/** + * @brief Get field quality from optical_flow message + * + * @return Optical flow quality / confidence. 0: bad, 255: maximum quality + */ +static inline uint8_t mavlink_msg_optical_flow_get_quality(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 13); +} + +/** + * @brief Get field ground_distance from optical_flow message + * + * @return Ground distance in meters + */ +static inline float mavlink_msg_optical_flow_get_ground_distance(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 14); +} + +/** + * @brief Decode a optical_flow message into a struct + * + * @param msg The message to decode + * @param optical_flow C-struct to decode the message contents into + */ +static inline void mavlink_msg_optical_flow_decode(const mavlink_message_t* msg, mavlink_optical_flow_t* optical_flow) +{ +#if MAVLINK_NEED_BYTE_SWAP + optical_flow->time = mavlink_msg_optical_flow_get_time(msg); + optical_flow->sensor_id = mavlink_msg_optical_flow_get_sensor_id(msg); + optical_flow->flow_x = mavlink_msg_optical_flow_get_flow_x(msg); + optical_flow->flow_y = mavlink_msg_optical_flow_get_flow_y(msg); + optical_flow->quality = mavlink_msg_optical_flow_get_quality(msg); + optical_flow->ground_distance = mavlink_msg_optical_flow_get_ground_distance(msg); +#else + memcpy(optical_flow, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_param_request_list.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_param_request_list.h new file mode 100644 index 0000000000..39e35915e1 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_param_request_list.h @@ -0,0 +1,166 @@ +// MESSAGE PARAM_REQUEST_LIST PACKING + +#define MAVLINK_MSG_ID_PARAM_REQUEST_LIST 21 + +typedef struct __mavlink_param_request_list_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_param_request_list_t; + +#define MAVLINK_MSG_ID_PARAM_REQUEST_LIST_LEN 2 +#define MAVLINK_MSG_ID_21_LEN 2 + + + +#define MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST { \ + "PARAM_REQUEST_LIST", \ + 2, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_param_request_list_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_param_request_list_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a param_request_list message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_request_list_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_param_request_list_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_REQUEST_LIST; + return mavlink_finalize_message(msg, system_id, component_id, 2); +} + +/** + * @brief Pack a param_request_list message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_request_list_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_param_request_list_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_REQUEST_LIST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 2); +} + +/** + * @brief Encode a param_request_list struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param param_request_list C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_param_request_list_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_param_request_list_t* param_request_list) +{ + return mavlink_msg_param_request_list_pack(system_id, component_id, msg, param_request_list->target_system, param_request_list->target_component); +} + +/** + * @brief Send a param_request_list message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_param_request_list_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_REQUEST_LIST, buf, 2); +#else + mavlink_param_request_list_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_REQUEST_LIST, (const char *)&packet, 2); +#endif +} + +#endif + +// MESSAGE PARAM_REQUEST_LIST UNPACKING + + +/** + * @brief Get field target_system from param_request_list message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_param_request_list_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from param_request_list message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_param_request_list_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Decode a param_request_list message into a struct + * + * @param msg The message to decode + * @param param_request_list C-struct to decode the message contents into + */ +static inline void mavlink_msg_param_request_list_decode(const mavlink_message_t* msg, mavlink_param_request_list_t* param_request_list) +{ +#if MAVLINK_NEED_BYTE_SWAP + param_request_list->target_system = mavlink_msg_param_request_list_get_target_system(msg); + param_request_list->target_component = mavlink_msg_param_request_list_get_target_component(msg); +#else + memcpy(param_request_list, _MAV_PAYLOAD(msg), 2); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_param_request_read.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_param_request_read.h new file mode 100644 index 0000000000..c02cb04492 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_param_request_read.h @@ -0,0 +1,204 @@ +// MESSAGE PARAM_REQUEST_READ PACKING + +#define MAVLINK_MSG_ID_PARAM_REQUEST_READ 20 + +typedef struct __mavlink_param_request_read_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + int8_t param_id[15]; ///< Onboard parameter id + int16_t param_index; ///< Parameter index. Send -1 to use the param ID field as identifier +} mavlink_param_request_read_t; + +#define MAVLINK_MSG_ID_PARAM_REQUEST_READ_LEN 19 +#define MAVLINK_MSG_ID_20_LEN 19 + +#define MAVLINK_MSG_PARAM_REQUEST_READ_FIELD_PARAM_ID_LEN 15 + +#define MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ { \ + "PARAM_REQUEST_READ", \ + 4, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_param_request_read_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_param_request_read_t, target_component) }, \ + { "param_id", NULL, MAVLINK_TYPE_INT8_T, 15, 2, offsetof(mavlink_param_request_read_t, param_id) }, \ + { "param_index", NULL, MAVLINK_TYPE_INT16_T, 0, 17, offsetof(mavlink_param_request_read_t, param_index) }, \ + } \ +} + + +/** + * @brief Pack a param_request_read message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param param_id Onboard parameter id + * @param param_index Parameter index. Send -1 to use the param ID field as identifier + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_request_read_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, const int8_t *param_id, int16_t param_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[19]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int16_t(buf, 17, param_index); + _mav_put_int8_t_array(buf, 2, param_id, 15); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 19); +#else + mavlink_param_request_read_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.param_index = param_index; + mav_array_memcpy(packet.param_id, param_id, sizeof(int8_t)*15); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 19); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_REQUEST_READ; + return mavlink_finalize_message(msg, system_id, component_id, 19); +} + +/** + * @brief Pack a param_request_read message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param param_id Onboard parameter id + * @param param_index Parameter index. Send -1 to use the param ID field as identifier + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_request_read_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,const int8_t *param_id,int16_t param_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[19]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int16_t(buf, 17, param_index); + _mav_put_int8_t_array(buf, 2, param_id, 15); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 19); +#else + mavlink_param_request_read_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.param_index = param_index; + mav_array_memcpy(packet.param_id, param_id, sizeof(int8_t)*15); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 19); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_REQUEST_READ; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 19); +} + +/** + * @brief Encode a param_request_read struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param param_request_read C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_param_request_read_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_param_request_read_t* param_request_read) +{ + return mavlink_msg_param_request_read_pack(system_id, component_id, msg, param_request_read->target_system, param_request_read->target_component, param_request_read->param_id, param_request_read->param_index); +} + +/** + * @brief Send a param_request_read message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param param_id Onboard parameter id + * @param param_index Parameter index. Send -1 to use the param ID field as identifier + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_param_request_read_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, const int8_t *param_id, int16_t param_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[19]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_int16_t(buf, 17, param_index); + _mav_put_int8_t_array(buf, 2, param_id, 15); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_REQUEST_READ, buf, 19); +#else + mavlink_param_request_read_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.param_index = param_index; + mav_array_memcpy(packet.param_id, param_id, sizeof(int8_t)*15); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_REQUEST_READ, (const char *)&packet, 19); +#endif +} + +#endif + +// MESSAGE PARAM_REQUEST_READ UNPACKING + + +/** + * @brief Get field target_system from param_request_read message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_param_request_read_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from param_request_read message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_param_request_read_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field param_id from param_request_read message + * + * @return Onboard parameter id + */ +static inline uint16_t mavlink_msg_param_request_read_get_param_id(const mavlink_message_t* msg, int8_t *param_id) +{ + return _MAV_RETURN_int8_t_array(msg, param_id, 15, 2); +} + +/** + * @brief Get field param_index from param_request_read message + * + * @return Parameter index. Send -1 to use the param ID field as identifier + */ +static inline int16_t mavlink_msg_param_request_read_get_param_index(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 17); +} + +/** + * @brief Decode a param_request_read message into a struct + * + * @param msg The message to decode + * @param param_request_read C-struct to decode the message contents into + */ +static inline void mavlink_msg_param_request_read_decode(const mavlink_message_t* msg, mavlink_param_request_read_t* param_request_read) +{ +#if MAVLINK_NEED_BYTE_SWAP + param_request_read->target_system = mavlink_msg_param_request_read_get_target_system(msg); + param_request_read->target_component = mavlink_msg_param_request_read_get_target_component(msg); + mavlink_msg_param_request_read_get_param_id(msg, param_request_read->param_id); + param_request_read->param_index = mavlink_msg_param_request_read_get_param_index(msg); +#else + memcpy(param_request_read, _MAV_PAYLOAD(msg), 19); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_param_set.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_param_set.h new file mode 100644 index 0000000000..e6648430f6 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_param_set.h @@ -0,0 +1,204 @@ +// MESSAGE PARAM_SET PACKING + +#define MAVLINK_MSG_ID_PARAM_SET 23 + +typedef struct __mavlink_param_set_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + int8_t param_id[15]; ///< Onboard parameter id + float param_value; ///< Onboard parameter value +} mavlink_param_set_t; + +#define MAVLINK_MSG_ID_PARAM_SET_LEN 21 +#define MAVLINK_MSG_ID_23_LEN 21 + +#define MAVLINK_MSG_PARAM_SET_FIELD_PARAM_ID_LEN 15 + +#define MAVLINK_MESSAGE_INFO_PARAM_SET { \ + "PARAM_SET", \ + 4, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_param_set_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_param_set_t, target_component) }, \ + { "param_id", NULL, MAVLINK_TYPE_INT8_T, 15, 2, offsetof(mavlink_param_set_t, param_id) }, \ + { "param_value", NULL, MAVLINK_TYPE_FLOAT, 0, 17, offsetof(mavlink_param_set_t, param_value) }, \ + } \ +} + + +/** + * @brief Pack a param_set message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param param_id Onboard parameter id + * @param param_value Onboard parameter value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_set_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, const int8_t *param_id, float param_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 17, param_value); + _mav_put_int8_t_array(buf, 2, param_id, 15); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 21); +#else + mavlink_param_set_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.param_value = param_value; + mav_array_memcpy(packet.param_id, param_id, sizeof(int8_t)*15); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 21); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_SET; + return mavlink_finalize_message(msg, system_id, component_id, 21); +} + +/** + * @brief Pack a param_set message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param param_id Onboard parameter id + * @param param_value Onboard parameter value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_set_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,const int8_t *param_id,float param_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 17, param_value); + _mav_put_int8_t_array(buf, 2, param_id, 15); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 21); +#else + mavlink_param_set_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.param_value = param_value; + mav_array_memcpy(packet.param_id, param_id, sizeof(int8_t)*15); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 21); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_SET; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 21); +} + +/** + * @brief Encode a param_set struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param param_set C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_param_set_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_param_set_t* param_set) +{ + return mavlink_msg_param_set_pack(system_id, component_id, msg, param_set->target_system, param_set->target_component, param_set->param_id, param_set->param_value); +} + +/** + * @brief Send a param_set message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param param_id Onboard parameter id + * @param param_value Onboard parameter value + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_param_set_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, const int8_t *param_id, float param_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 17, param_value); + _mav_put_int8_t_array(buf, 2, param_id, 15); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_SET, buf, 21); +#else + mavlink_param_set_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.param_value = param_value; + mav_array_memcpy(packet.param_id, param_id, sizeof(int8_t)*15); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_SET, (const char *)&packet, 21); +#endif +} + +#endif + +// MESSAGE PARAM_SET UNPACKING + + +/** + * @brief Get field target_system from param_set message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_param_set_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from param_set message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_param_set_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field param_id from param_set message + * + * @return Onboard parameter id + */ +static inline uint16_t mavlink_msg_param_set_get_param_id(const mavlink_message_t* msg, int8_t *param_id) +{ + return _MAV_RETURN_int8_t_array(msg, param_id, 15, 2); +} + +/** + * @brief Get field param_value from param_set message + * + * @return Onboard parameter value + */ +static inline float mavlink_msg_param_set_get_param_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 17); +} + +/** + * @brief Decode a param_set message into a struct + * + * @param msg The message to decode + * @param param_set C-struct to decode the message contents into + */ +static inline void mavlink_msg_param_set_decode(const mavlink_message_t* msg, mavlink_param_set_t* param_set) +{ +#if MAVLINK_NEED_BYTE_SWAP + param_set->target_system = mavlink_msg_param_set_get_target_system(msg); + param_set->target_component = mavlink_msg_param_set_get_target_component(msg); + mavlink_msg_param_set_get_param_id(msg, param_set->param_id); + param_set->param_value = mavlink_msg_param_set_get_param_value(msg); +#else + memcpy(param_set, _MAV_PAYLOAD(msg), 21); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_param_value.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_param_value.h new file mode 100644 index 0000000000..634fbb1527 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_param_value.h @@ -0,0 +1,204 @@ +// MESSAGE PARAM_VALUE PACKING + +#define MAVLINK_MSG_ID_PARAM_VALUE 22 + +typedef struct __mavlink_param_value_t +{ + int8_t param_id[15]; ///< Onboard parameter id + float param_value; ///< Onboard parameter value + uint16_t param_count; ///< Total number of onboard parameters + uint16_t param_index; ///< Index of this onboard parameter +} mavlink_param_value_t; + +#define MAVLINK_MSG_ID_PARAM_VALUE_LEN 23 +#define MAVLINK_MSG_ID_22_LEN 23 + +#define MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN 15 + +#define MAVLINK_MESSAGE_INFO_PARAM_VALUE { \ + "PARAM_VALUE", \ + 4, \ + { { "param_id", NULL, MAVLINK_TYPE_INT8_T, 15, 0, offsetof(mavlink_param_value_t, param_id) }, \ + { "param_value", NULL, MAVLINK_TYPE_FLOAT, 0, 15, offsetof(mavlink_param_value_t, param_value) }, \ + { "param_count", NULL, MAVLINK_TYPE_UINT16_T, 0, 19, offsetof(mavlink_param_value_t, param_count) }, \ + { "param_index", NULL, MAVLINK_TYPE_UINT16_T, 0, 21, offsetof(mavlink_param_value_t, param_index) }, \ + } \ +} + + +/** + * @brief Pack a param_value message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param param_id Onboard parameter id + * @param param_value Onboard parameter value + * @param param_count Total number of onboard parameters + * @param param_index Index of this onboard parameter + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_value_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const int8_t *param_id, float param_value, uint16_t param_count, uint16_t param_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[23]; + _mav_put_float(buf, 15, param_value); + _mav_put_uint16_t(buf, 19, param_count); + _mav_put_uint16_t(buf, 21, param_index); + _mav_put_int8_t_array(buf, 0, param_id, 15); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 23); +#else + mavlink_param_value_t packet; + packet.param_value = param_value; + packet.param_count = param_count; + packet.param_index = param_index; + mav_array_memcpy(packet.param_id, param_id, sizeof(int8_t)*15); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 23); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_VALUE; + return mavlink_finalize_message(msg, system_id, component_id, 23); +} + +/** + * @brief Pack a param_value message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param param_id Onboard parameter id + * @param param_value Onboard parameter value + * @param param_count Total number of onboard parameters + * @param param_index Index of this onboard parameter + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_value_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const int8_t *param_id,float param_value,uint16_t param_count,uint16_t param_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[23]; + _mav_put_float(buf, 15, param_value); + _mav_put_uint16_t(buf, 19, param_count); + _mav_put_uint16_t(buf, 21, param_index); + _mav_put_int8_t_array(buf, 0, param_id, 15); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 23); +#else + mavlink_param_value_t packet; + packet.param_value = param_value; + packet.param_count = param_count; + packet.param_index = param_index; + mav_array_memcpy(packet.param_id, param_id, sizeof(int8_t)*15); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 23); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_VALUE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 23); +} + +/** + * @brief Encode a param_value struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param param_value C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_param_value_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_param_value_t* param_value) +{ + return mavlink_msg_param_value_pack(system_id, component_id, msg, param_value->param_id, param_value->param_value, param_value->param_count, param_value->param_index); +} + +/** + * @brief Send a param_value message + * @param chan MAVLink channel to send the message + * + * @param param_id Onboard parameter id + * @param param_value Onboard parameter value + * @param param_count Total number of onboard parameters + * @param param_index Index of this onboard parameter + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_param_value_send(mavlink_channel_t chan, const int8_t *param_id, float param_value, uint16_t param_count, uint16_t param_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[23]; + _mav_put_float(buf, 15, param_value); + _mav_put_uint16_t(buf, 19, param_count); + _mav_put_uint16_t(buf, 21, param_index); + _mav_put_int8_t_array(buf, 0, param_id, 15); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_VALUE, buf, 23); +#else + mavlink_param_value_t packet; + packet.param_value = param_value; + packet.param_count = param_count; + packet.param_index = param_index; + mav_array_memcpy(packet.param_id, param_id, sizeof(int8_t)*15); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_VALUE, (const char *)&packet, 23); +#endif +} + +#endif + +// MESSAGE PARAM_VALUE UNPACKING + + +/** + * @brief Get field param_id from param_value message + * + * @return Onboard parameter id + */ +static inline uint16_t mavlink_msg_param_value_get_param_id(const mavlink_message_t* msg, int8_t *param_id) +{ + return _MAV_RETURN_int8_t_array(msg, param_id, 15, 0); +} + +/** + * @brief Get field param_value from param_value message + * + * @return Onboard parameter value + */ +static inline float mavlink_msg_param_value_get_param_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 15); +} + +/** + * @brief Get field param_count from param_value message + * + * @return Total number of onboard parameters + */ +static inline uint16_t mavlink_msg_param_value_get_param_count(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 19); +} + +/** + * @brief Get field param_index from param_value message + * + * @return Index of this onboard parameter + */ +static inline uint16_t mavlink_msg_param_value_get_param_index(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 21); +} + +/** + * @brief Decode a param_value message into a struct + * + * @param msg The message to decode + * @param param_value C-struct to decode the message contents into + */ +static inline void mavlink_msg_param_value_decode(const mavlink_message_t* msg, mavlink_param_value_t* param_value) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_param_value_get_param_id(msg, param_value->param_id); + param_value->param_value = mavlink_msg_param_value_get_param_value(msg); + param_value->param_count = mavlink_msg_param_value_get_param_count(msg); + param_value->param_index = mavlink_msg_param_value_get_param_index(msg); +#else + memcpy(param_value, _MAV_PAYLOAD(msg), 23); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_ping.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_ping.h new file mode 100644 index 0000000000..ad076fd9b5 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_ping.h @@ -0,0 +1,210 @@ +// MESSAGE PING PACKING + +#define MAVLINK_MSG_ID_PING 3 + +typedef struct __mavlink_ping_t +{ + uint32_t seq; ///< PING sequence + uint8_t target_system; ///< 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system + uint8_t target_component; ///< 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system + uint64_t time; ///< Unix timestamp in microseconds +} mavlink_ping_t; + +#define MAVLINK_MSG_ID_PING_LEN 14 +#define MAVLINK_MSG_ID_3_LEN 14 + + + +#define MAVLINK_MESSAGE_INFO_PING { \ + "PING", \ + 4, \ + { { "seq", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_ping_t, seq) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_ping_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_ping_t, target_component) }, \ + { "time", NULL, MAVLINK_TYPE_UINT64_T, 0, 6, offsetof(mavlink_ping_t, time) }, \ + } \ +} + + +/** + * @brief Pack a ping message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param seq PING sequence + * @param target_system 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system + * @param target_component 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system + * @param time Unix timestamp in microseconds + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ping_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t seq, uint8_t target_system, uint8_t target_component, uint64_t time) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint32_t(buf, 0, seq); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + _mav_put_uint64_t(buf, 6, time); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_ping_t packet; + packet.seq = seq; + packet.target_system = target_system; + packet.target_component = target_component; + packet.time = time; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_PING; + return mavlink_finalize_message(msg, system_id, component_id, 14); +} + +/** + * @brief Pack a ping message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param seq PING sequence + * @param target_system 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system + * @param target_component 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system + * @param time Unix timestamp in microseconds + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ping_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t seq,uint8_t target_system,uint8_t target_component,uint64_t time) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint32_t(buf, 0, seq); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + _mav_put_uint64_t(buf, 6, time); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_ping_t packet; + packet.seq = seq; + packet.target_system = target_system; + packet.target_component = target_component; + packet.time = time; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_PING; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 14); +} + +/** + * @brief Encode a ping struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param ping C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_ping_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_ping_t* ping) +{ + return mavlink_msg_ping_pack(system_id, component_id, msg, ping->seq, ping->target_system, ping->target_component, ping->time); +} + +/** + * @brief Send a ping message + * @param chan MAVLink channel to send the message + * + * @param seq PING sequence + * @param target_system 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system + * @param target_component 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system + * @param time Unix timestamp in microseconds + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_ping_send(mavlink_channel_t chan, uint32_t seq, uint8_t target_system, uint8_t target_component, uint64_t time) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint32_t(buf, 0, seq); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + _mav_put_uint64_t(buf, 6, time); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PING, buf, 14); +#else + mavlink_ping_t packet; + packet.seq = seq; + packet.target_system = target_system; + packet.target_component = target_component; + packet.time = time; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PING, (const char *)&packet, 14); +#endif +} + +#endif + +// MESSAGE PING UNPACKING + + +/** + * @brief Get field seq from ping message + * + * @return PING sequence + */ +static inline uint32_t mavlink_msg_ping_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field target_system from ping message + * + * @return 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system + */ +static inline uint8_t mavlink_msg_ping_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field target_component from ping message + * + * @return 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system + */ +static inline uint8_t mavlink_msg_ping_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field time from ping message + * + * @return Unix timestamp in microseconds + */ +static inline uint64_t mavlink_msg_ping_get_time(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 6); +} + +/** + * @brief Decode a ping message into a struct + * + * @param msg The message to decode + * @param ping C-struct to decode the message contents into + */ +static inline void mavlink_msg_ping_decode(const mavlink_message_t* msg, mavlink_ping_t* ping) +{ +#if MAVLINK_NEED_BYTE_SWAP + ping->seq = mavlink_msg_ping_get_seq(msg); + ping->target_system = mavlink_msg_ping_get_target_system(msg); + ping->target_component = mavlink_msg_ping_get_target_component(msg); + ping->time = mavlink_msg_ping_get_time(msg); +#else + memcpy(ping, _MAV_PAYLOAD(msg), 14); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_position_target.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_position_target.h new file mode 100644 index 0000000000..6cd7719fb2 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_position_target.h @@ -0,0 +1,210 @@ +// MESSAGE POSITION_TARGET PACKING + +#define MAVLINK_MSG_ID_POSITION_TARGET 63 + +typedef struct __mavlink_position_target_t +{ + float x; ///< x position + float y; ///< y position + float z; ///< z position + float yaw; ///< yaw orientation in radians, 0 = NORTH +} mavlink_position_target_t; + +#define MAVLINK_MSG_ID_POSITION_TARGET_LEN 16 +#define MAVLINK_MSG_ID_63_LEN 16 + + + +#define MAVLINK_MESSAGE_INFO_POSITION_TARGET { \ + "POSITION_TARGET", \ + 4, \ + { { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_position_target_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_position_target_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_position_target_t, z) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_position_target_t, yaw) }, \ + } \ +} + + +/** + * @brief Pack a position_target message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param x x position + * @param y y position + * @param z z position + * @param yaw yaw orientation in radians, 0 = NORTH + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_position_target_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_position_target_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_POSITION_TARGET; + return mavlink_finalize_message(msg, system_id, component_id, 16); +} + +/** + * @brief Pack a position_target message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param x x position + * @param y y position + * @param z z position + * @param yaw yaw orientation in radians, 0 = NORTH + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_position_target_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float x,float y,float z,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_position_target_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_POSITION_TARGET; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 16); +} + +/** + * @brief Encode a position_target struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param position_target C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_position_target_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_position_target_t* position_target) +{ + return mavlink_msg_position_target_pack(system_id, component_id, msg, position_target->x, position_target->y, position_target->z, position_target->yaw); +} + +/** + * @brief Send a position_target message + * @param chan MAVLink channel to send the message + * + * @param x x position + * @param y y position + * @param z z position + * @param yaw yaw orientation in radians, 0 = NORTH + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_position_target_send(mavlink_channel_t chan, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POSITION_TARGET, buf, 16); +#else + mavlink_position_target_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POSITION_TARGET, (const char *)&packet, 16); +#endif +} + +#endif + +// MESSAGE POSITION_TARGET UNPACKING + + +/** + * @brief Get field x from position_target message + * + * @return x position + */ +static inline float mavlink_msg_position_target_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field y from position_target message + * + * @return y position + */ +static inline float mavlink_msg_position_target_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field z from position_target message + * + * @return z position + */ +static inline float mavlink_msg_position_target_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field yaw from position_target message + * + * @return yaw orientation in radians, 0 = NORTH + */ +static inline float mavlink_msg_position_target_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Decode a position_target message into a struct + * + * @param msg The message to decode + * @param position_target C-struct to decode the message contents into + */ +static inline void mavlink_msg_position_target_decode(const mavlink_message_t* msg, mavlink_position_target_t* position_target) +{ +#if MAVLINK_NEED_BYTE_SWAP + position_target->x = mavlink_msg_position_target_get_x(msg); + position_target->y = mavlink_msg_position_target_get_y(msg); + position_target->z = mavlink_msg_position_target_get_z(msg); + position_target->yaw = mavlink_msg_position_target_get_yaw(msg); +#else + memcpy(position_target, _MAV_PAYLOAD(msg), 16); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_raw_imu.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_raw_imu.h new file mode 100644 index 0000000000..c60945ae9f --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_raw_imu.h @@ -0,0 +1,342 @@ +// MESSAGE RAW_IMU PACKING + +#define MAVLINK_MSG_ID_RAW_IMU 28 + +typedef struct __mavlink_raw_imu_t +{ + uint64_t usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + int16_t xacc; ///< X acceleration (raw) + int16_t yacc; ///< Y acceleration (raw) + int16_t zacc; ///< Z acceleration (raw) + int16_t xgyro; ///< Angular speed around X axis (raw) + int16_t ygyro; ///< Angular speed around Y axis (raw) + int16_t zgyro; ///< Angular speed around Z axis (raw) + int16_t xmag; ///< X Magnetic field (raw) + int16_t ymag; ///< Y Magnetic field (raw) + int16_t zmag; ///< Z Magnetic field (raw) +} mavlink_raw_imu_t; + +#define MAVLINK_MSG_ID_RAW_IMU_LEN 26 +#define MAVLINK_MSG_ID_28_LEN 26 + + + +#define MAVLINK_MESSAGE_INFO_RAW_IMU { \ + "RAW_IMU", \ + 10, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_raw_imu_t, usec) }, \ + { "xacc", NULL, MAVLINK_TYPE_INT16_T, 0, 8, offsetof(mavlink_raw_imu_t, xacc) }, \ + { "yacc", NULL, MAVLINK_TYPE_INT16_T, 0, 10, offsetof(mavlink_raw_imu_t, yacc) }, \ + { "zacc", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_raw_imu_t, zacc) }, \ + { "xgyro", NULL, MAVLINK_TYPE_INT16_T, 0, 14, offsetof(mavlink_raw_imu_t, xgyro) }, \ + { "ygyro", NULL, MAVLINK_TYPE_INT16_T, 0, 16, offsetof(mavlink_raw_imu_t, ygyro) }, \ + { "zgyro", NULL, MAVLINK_TYPE_INT16_T, 0, 18, offsetof(mavlink_raw_imu_t, zgyro) }, \ + { "xmag", NULL, MAVLINK_TYPE_INT16_T, 0, 20, offsetof(mavlink_raw_imu_t, xmag) }, \ + { "ymag", NULL, MAVLINK_TYPE_INT16_T, 0, 22, offsetof(mavlink_raw_imu_t, ymag) }, \ + { "zmag", NULL, MAVLINK_TYPE_INT16_T, 0, 24, offsetof(mavlink_raw_imu_t, zmag) }, \ + } \ +} + + +/** + * @brief Pack a raw_imu message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param xacc X acceleration (raw) + * @param yacc Y acceleration (raw) + * @param zacc Z acceleration (raw) + * @param xgyro Angular speed around X axis (raw) + * @param ygyro Angular speed around Y axis (raw) + * @param zgyro Angular speed around Z axis (raw) + * @param xmag X Magnetic field (raw) + * @param ymag Y Magnetic field (raw) + * @param zmag Z Magnetic field (raw) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_raw_imu_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, int16_t xacc, int16_t yacc, int16_t zacc, int16_t xgyro, int16_t ygyro, int16_t zgyro, int16_t xmag, int16_t ymag, int16_t zmag) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_int16_t(buf, 8, xacc); + _mav_put_int16_t(buf, 10, yacc); + _mav_put_int16_t(buf, 12, zacc); + _mav_put_int16_t(buf, 14, xgyro); + _mav_put_int16_t(buf, 16, ygyro); + _mav_put_int16_t(buf, 18, zgyro); + _mav_put_int16_t(buf, 20, xmag); + _mav_put_int16_t(buf, 22, ymag); + _mav_put_int16_t(buf, 24, zmag); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_raw_imu_t packet; + packet.usec = usec; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + packet.xmag = xmag; + packet.ymag = ymag; + packet.zmag = zmag; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_RAW_IMU; + return mavlink_finalize_message(msg, system_id, component_id, 26); +} + +/** + * @brief Pack a raw_imu message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param xacc X acceleration (raw) + * @param yacc Y acceleration (raw) + * @param zacc Z acceleration (raw) + * @param xgyro Angular speed around X axis (raw) + * @param ygyro Angular speed around Y axis (raw) + * @param zgyro Angular speed around Z axis (raw) + * @param xmag X Magnetic field (raw) + * @param ymag Y Magnetic field (raw) + * @param zmag Z Magnetic field (raw) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_raw_imu_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,int16_t xacc,int16_t yacc,int16_t zacc,int16_t xgyro,int16_t ygyro,int16_t zgyro,int16_t xmag,int16_t ymag,int16_t zmag) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_int16_t(buf, 8, xacc); + _mav_put_int16_t(buf, 10, yacc); + _mav_put_int16_t(buf, 12, zacc); + _mav_put_int16_t(buf, 14, xgyro); + _mav_put_int16_t(buf, 16, ygyro); + _mav_put_int16_t(buf, 18, zgyro); + _mav_put_int16_t(buf, 20, xmag); + _mav_put_int16_t(buf, 22, ymag); + _mav_put_int16_t(buf, 24, zmag); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_raw_imu_t packet; + packet.usec = usec; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + packet.xmag = xmag; + packet.ymag = ymag; + packet.zmag = zmag; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_RAW_IMU; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 26); +} + +/** + * @brief Encode a raw_imu struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param raw_imu C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_raw_imu_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_raw_imu_t* raw_imu) +{ + return mavlink_msg_raw_imu_pack(system_id, component_id, msg, raw_imu->usec, raw_imu->xacc, raw_imu->yacc, raw_imu->zacc, raw_imu->xgyro, raw_imu->ygyro, raw_imu->zgyro, raw_imu->xmag, raw_imu->ymag, raw_imu->zmag); +} + +/** + * @brief Send a raw_imu message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param xacc X acceleration (raw) + * @param yacc Y acceleration (raw) + * @param zacc Z acceleration (raw) + * @param xgyro Angular speed around X axis (raw) + * @param ygyro Angular speed around Y axis (raw) + * @param zgyro Angular speed around Z axis (raw) + * @param xmag X Magnetic field (raw) + * @param ymag Y Magnetic field (raw) + * @param zmag Z Magnetic field (raw) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_raw_imu_send(mavlink_channel_t chan, uint64_t usec, int16_t xacc, int16_t yacc, int16_t zacc, int16_t xgyro, int16_t ygyro, int16_t zgyro, int16_t xmag, int16_t ymag, int16_t zmag) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_int16_t(buf, 8, xacc); + _mav_put_int16_t(buf, 10, yacc); + _mav_put_int16_t(buf, 12, zacc); + _mav_put_int16_t(buf, 14, xgyro); + _mav_put_int16_t(buf, 16, ygyro); + _mav_put_int16_t(buf, 18, zgyro); + _mav_put_int16_t(buf, 20, xmag); + _mav_put_int16_t(buf, 22, ymag); + _mav_put_int16_t(buf, 24, zmag); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RAW_IMU, buf, 26); +#else + mavlink_raw_imu_t packet; + packet.usec = usec; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + packet.xmag = xmag; + packet.ymag = ymag; + packet.zmag = zmag; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RAW_IMU, (const char *)&packet, 26); +#endif +} + +#endif + +// MESSAGE RAW_IMU UNPACKING + + +/** + * @brief Get field usec from raw_imu message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_raw_imu_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field xacc from raw_imu message + * + * @return X acceleration (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_xacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 8); +} + +/** + * @brief Get field yacc from raw_imu message + * + * @return Y acceleration (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_yacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 10); +} + +/** + * @brief Get field zacc from raw_imu message + * + * @return Z acceleration (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_zacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Get field xgyro from raw_imu message + * + * @return Angular speed around X axis (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_xgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 14); +} + +/** + * @brief Get field ygyro from raw_imu message + * + * @return Angular speed around Y axis (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_ygyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 16); +} + +/** + * @brief Get field zgyro from raw_imu message + * + * @return Angular speed around Z axis (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_zgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 18); +} + +/** + * @brief Get field xmag from raw_imu message + * + * @return X Magnetic field (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_xmag(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 20); +} + +/** + * @brief Get field ymag from raw_imu message + * + * @return Y Magnetic field (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_ymag(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 22); +} + +/** + * @brief Get field zmag from raw_imu message + * + * @return Z Magnetic field (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_zmag(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 24); +} + +/** + * @brief Decode a raw_imu message into a struct + * + * @param msg The message to decode + * @param raw_imu C-struct to decode the message contents into + */ +static inline void mavlink_msg_raw_imu_decode(const mavlink_message_t* msg, mavlink_raw_imu_t* raw_imu) +{ +#if MAVLINK_NEED_BYTE_SWAP + raw_imu->usec = mavlink_msg_raw_imu_get_usec(msg); + raw_imu->xacc = mavlink_msg_raw_imu_get_xacc(msg); + raw_imu->yacc = mavlink_msg_raw_imu_get_yacc(msg); + raw_imu->zacc = mavlink_msg_raw_imu_get_zacc(msg); + raw_imu->xgyro = mavlink_msg_raw_imu_get_xgyro(msg); + raw_imu->ygyro = mavlink_msg_raw_imu_get_ygyro(msg); + raw_imu->zgyro = mavlink_msg_raw_imu_get_zgyro(msg); + raw_imu->xmag = mavlink_msg_raw_imu_get_xmag(msg); + raw_imu->ymag = mavlink_msg_raw_imu_get_ymag(msg); + raw_imu->zmag = mavlink_msg_raw_imu_get_zmag(msg); +#else + memcpy(raw_imu, _MAV_PAYLOAD(msg), 26); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_raw_pressure.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_raw_pressure.h new file mode 100644 index 0000000000..b493b7e988 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_raw_pressure.h @@ -0,0 +1,232 @@ +// MESSAGE RAW_PRESSURE PACKING + +#define MAVLINK_MSG_ID_RAW_PRESSURE 29 + +typedef struct __mavlink_raw_pressure_t +{ + uint64_t usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + int16_t press_abs; ///< Absolute pressure (raw) + int16_t press_diff1; ///< Differential pressure 1 (raw) + int16_t press_diff2; ///< Differential pressure 2 (raw) + int16_t temperature; ///< Raw Temperature measurement (raw) +} mavlink_raw_pressure_t; + +#define MAVLINK_MSG_ID_RAW_PRESSURE_LEN 16 +#define MAVLINK_MSG_ID_29_LEN 16 + + + +#define MAVLINK_MESSAGE_INFO_RAW_PRESSURE { \ + "RAW_PRESSURE", \ + 5, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_raw_pressure_t, usec) }, \ + { "press_abs", NULL, MAVLINK_TYPE_INT16_T, 0, 8, offsetof(mavlink_raw_pressure_t, press_abs) }, \ + { "press_diff1", NULL, MAVLINK_TYPE_INT16_T, 0, 10, offsetof(mavlink_raw_pressure_t, press_diff1) }, \ + { "press_diff2", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_raw_pressure_t, press_diff2) }, \ + { "temperature", NULL, MAVLINK_TYPE_INT16_T, 0, 14, offsetof(mavlink_raw_pressure_t, temperature) }, \ + } \ +} + + +/** + * @brief Pack a raw_pressure message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param press_abs Absolute pressure (raw) + * @param press_diff1 Differential pressure 1 (raw) + * @param press_diff2 Differential pressure 2 (raw) + * @param temperature Raw Temperature measurement (raw) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_raw_pressure_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, int16_t press_abs, int16_t press_diff1, int16_t press_diff2, int16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_int16_t(buf, 8, press_abs); + _mav_put_int16_t(buf, 10, press_diff1); + _mav_put_int16_t(buf, 12, press_diff2); + _mav_put_int16_t(buf, 14, temperature); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_raw_pressure_t packet; + packet.usec = usec; + packet.press_abs = press_abs; + packet.press_diff1 = press_diff1; + packet.press_diff2 = press_diff2; + packet.temperature = temperature; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_RAW_PRESSURE; + return mavlink_finalize_message(msg, system_id, component_id, 16); +} + +/** + * @brief Pack a raw_pressure message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param press_abs Absolute pressure (raw) + * @param press_diff1 Differential pressure 1 (raw) + * @param press_diff2 Differential pressure 2 (raw) + * @param temperature Raw Temperature measurement (raw) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_raw_pressure_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,int16_t press_abs,int16_t press_diff1,int16_t press_diff2,int16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_int16_t(buf, 8, press_abs); + _mav_put_int16_t(buf, 10, press_diff1); + _mav_put_int16_t(buf, 12, press_diff2); + _mav_put_int16_t(buf, 14, temperature); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_raw_pressure_t packet; + packet.usec = usec; + packet.press_abs = press_abs; + packet.press_diff1 = press_diff1; + packet.press_diff2 = press_diff2; + packet.temperature = temperature; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_RAW_PRESSURE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 16); +} + +/** + * @brief Encode a raw_pressure struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param raw_pressure C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_raw_pressure_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_raw_pressure_t* raw_pressure) +{ + return mavlink_msg_raw_pressure_pack(system_id, component_id, msg, raw_pressure->usec, raw_pressure->press_abs, raw_pressure->press_diff1, raw_pressure->press_diff2, raw_pressure->temperature); +} + +/** + * @brief Send a raw_pressure message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param press_abs Absolute pressure (raw) + * @param press_diff1 Differential pressure 1 (raw) + * @param press_diff2 Differential pressure 2 (raw) + * @param temperature Raw Temperature measurement (raw) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_raw_pressure_send(mavlink_channel_t chan, uint64_t usec, int16_t press_abs, int16_t press_diff1, int16_t press_diff2, int16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_int16_t(buf, 8, press_abs); + _mav_put_int16_t(buf, 10, press_diff1); + _mav_put_int16_t(buf, 12, press_diff2); + _mav_put_int16_t(buf, 14, temperature); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RAW_PRESSURE, buf, 16); +#else + mavlink_raw_pressure_t packet; + packet.usec = usec; + packet.press_abs = press_abs; + packet.press_diff1 = press_diff1; + packet.press_diff2 = press_diff2; + packet.temperature = temperature; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RAW_PRESSURE, (const char *)&packet, 16); +#endif +} + +#endif + +// MESSAGE RAW_PRESSURE UNPACKING + + +/** + * @brief Get field usec from raw_pressure message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_raw_pressure_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field press_abs from raw_pressure message + * + * @return Absolute pressure (raw) + */ +static inline int16_t mavlink_msg_raw_pressure_get_press_abs(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 8); +} + +/** + * @brief Get field press_diff1 from raw_pressure message + * + * @return Differential pressure 1 (raw) + */ +static inline int16_t mavlink_msg_raw_pressure_get_press_diff1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 10); +} + +/** + * @brief Get field press_diff2 from raw_pressure message + * + * @return Differential pressure 2 (raw) + */ +static inline int16_t mavlink_msg_raw_pressure_get_press_diff2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Get field temperature from raw_pressure message + * + * @return Raw Temperature measurement (raw) + */ +static inline int16_t mavlink_msg_raw_pressure_get_temperature(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 14); +} + +/** + * @brief Decode a raw_pressure message into a struct + * + * @param msg The message to decode + * @param raw_pressure C-struct to decode the message contents into + */ +static inline void mavlink_msg_raw_pressure_decode(const mavlink_message_t* msg, mavlink_raw_pressure_t* raw_pressure) +{ +#if MAVLINK_NEED_BYTE_SWAP + raw_pressure->usec = mavlink_msg_raw_pressure_get_usec(msg); + raw_pressure->press_abs = mavlink_msg_raw_pressure_get_press_abs(msg); + raw_pressure->press_diff1 = mavlink_msg_raw_pressure_get_press_diff1(msg); + raw_pressure->press_diff2 = mavlink_msg_raw_pressure_get_press_diff2(msg); + raw_pressure->temperature = mavlink_msg_raw_pressure_get_temperature(msg); +#else + memcpy(raw_pressure, _MAV_PAYLOAD(msg), 16); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_rc_channels_override.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_rc_channels_override.h new file mode 100644 index 0000000000..30e5a8f98e --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_rc_channels_override.h @@ -0,0 +1,342 @@ +// MESSAGE RC_CHANNELS_OVERRIDE PACKING + +#define MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE 70 + +typedef struct __mavlink_rc_channels_override_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint16_t chan1_raw; ///< RC channel 1 value, in microseconds + uint16_t chan2_raw; ///< RC channel 2 value, in microseconds + uint16_t chan3_raw; ///< RC channel 3 value, in microseconds + uint16_t chan4_raw; ///< RC channel 4 value, in microseconds + uint16_t chan5_raw; ///< RC channel 5 value, in microseconds + uint16_t chan6_raw; ///< RC channel 6 value, in microseconds + uint16_t chan7_raw; ///< RC channel 7 value, in microseconds + uint16_t chan8_raw; ///< RC channel 8 value, in microseconds +} mavlink_rc_channels_override_t; + +#define MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE_LEN 18 +#define MAVLINK_MSG_ID_70_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE { \ + "RC_CHANNELS_OVERRIDE", \ + 10, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_rc_channels_override_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_rc_channels_override_t, target_component) }, \ + { "chan1_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_rc_channels_override_t, chan1_raw) }, \ + { "chan2_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_rc_channels_override_t, chan2_raw) }, \ + { "chan3_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_rc_channels_override_t, chan3_raw) }, \ + { "chan4_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 8, offsetof(mavlink_rc_channels_override_t, chan4_raw) }, \ + { "chan5_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 10, offsetof(mavlink_rc_channels_override_t, chan5_raw) }, \ + { "chan6_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 12, offsetof(mavlink_rc_channels_override_t, chan6_raw) }, \ + { "chan7_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 14, offsetof(mavlink_rc_channels_override_t, chan7_raw) }, \ + { "chan8_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 16, offsetof(mavlink_rc_channels_override_t, chan8_raw) }, \ + } \ +} + + +/** + * @brief Pack a rc_channels_override message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_rc_channels_override_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint16_t chan1_raw, uint16_t chan2_raw, uint16_t chan3_raw, uint16_t chan4_raw, uint16_t chan5_raw, uint16_t chan6_raw, uint16_t chan7_raw, uint16_t chan8_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, chan1_raw); + _mav_put_uint16_t(buf, 4, chan2_raw); + _mav_put_uint16_t(buf, 6, chan3_raw); + _mav_put_uint16_t(buf, 8, chan4_raw); + _mav_put_uint16_t(buf, 10, chan5_raw); + _mav_put_uint16_t(buf, 12, chan6_raw); + _mav_put_uint16_t(buf, 14, chan7_raw); + _mav_put_uint16_t(buf, 16, chan8_raw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_rc_channels_override_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE; + return mavlink_finalize_message(msg, system_id, component_id, 18); +} + +/** + * @brief Pack a rc_channels_override message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_rc_channels_override_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint16_t chan1_raw,uint16_t chan2_raw,uint16_t chan3_raw,uint16_t chan4_raw,uint16_t chan5_raw,uint16_t chan6_raw,uint16_t chan7_raw,uint16_t chan8_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, chan1_raw); + _mav_put_uint16_t(buf, 4, chan2_raw); + _mav_put_uint16_t(buf, 6, chan3_raw); + _mav_put_uint16_t(buf, 8, chan4_raw); + _mav_put_uint16_t(buf, 10, chan5_raw); + _mav_put_uint16_t(buf, 12, chan6_raw); + _mav_put_uint16_t(buf, 14, chan7_raw); + _mav_put_uint16_t(buf, 16, chan8_raw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_rc_channels_override_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18); +} + +/** + * @brief Encode a rc_channels_override struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param rc_channels_override C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_rc_channels_override_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_rc_channels_override_t* rc_channels_override) +{ + return mavlink_msg_rc_channels_override_pack(system_id, component_id, msg, rc_channels_override->target_system, rc_channels_override->target_component, rc_channels_override->chan1_raw, rc_channels_override->chan2_raw, rc_channels_override->chan3_raw, rc_channels_override->chan4_raw, rc_channels_override->chan5_raw, rc_channels_override->chan6_raw, rc_channels_override->chan7_raw, rc_channels_override->chan8_raw); +} + +/** + * @brief Send a rc_channels_override message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_rc_channels_override_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint16_t chan1_raw, uint16_t chan2_raw, uint16_t chan3_raw, uint16_t chan4_raw, uint16_t chan5_raw, uint16_t chan6_raw, uint16_t chan7_raw, uint16_t chan8_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, chan1_raw); + _mav_put_uint16_t(buf, 4, chan2_raw); + _mav_put_uint16_t(buf, 6, chan3_raw); + _mav_put_uint16_t(buf, 8, chan4_raw); + _mav_put_uint16_t(buf, 10, chan5_raw); + _mav_put_uint16_t(buf, 12, chan6_raw); + _mav_put_uint16_t(buf, 14, chan7_raw); + _mav_put_uint16_t(buf, 16, chan8_raw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE, buf, 18); +#else + mavlink_rc_channels_override_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE, (const char *)&packet, 18); +#endif +} + +#endif + +// MESSAGE RC_CHANNELS_OVERRIDE UNPACKING + + +/** + * @brief Get field target_system from rc_channels_override message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_rc_channels_override_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from rc_channels_override message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_rc_channels_override_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field chan1_raw from rc_channels_override message + * + * @return RC channel 1 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan1_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Get field chan2_raw from rc_channels_override message + * + * @return RC channel 2 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan2_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field chan3_raw from rc_channels_override message + * + * @return RC channel 3 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan3_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field chan4_raw from rc_channels_override message + * + * @return RC channel 4 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan4_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Get field chan5_raw from rc_channels_override message + * + * @return RC channel 5 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan5_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 10); +} + +/** + * @brief Get field chan6_raw from rc_channels_override message + * + * @return RC channel 6 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan6_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 12); +} + +/** + * @brief Get field chan7_raw from rc_channels_override message + * + * @return RC channel 7 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan7_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 14); +} + +/** + * @brief Get field chan8_raw from rc_channels_override message + * + * @return RC channel 8 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan8_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 16); +} + +/** + * @brief Decode a rc_channels_override message into a struct + * + * @param msg The message to decode + * @param rc_channels_override C-struct to decode the message contents into + */ +static inline void mavlink_msg_rc_channels_override_decode(const mavlink_message_t* msg, mavlink_rc_channels_override_t* rc_channels_override) +{ +#if MAVLINK_NEED_BYTE_SWAP + rc_channels_override->target_system = mavlink_msg_rc_channels_override_get_target_system(msg); + rc_channels_override->target_component = mavlink_msg_rc_channels_override_get_target_component(msg); + rc_channels_override->chan1_raw = mavlink_msg_rc_channels_override_get_chan1_raw(msg); + rc_channels_override->chan2_raw = mavlink_msg_rc_channels_override_get_chan2_raw(msg); + rc_channels_override->chan3_raw = mavlink_msg_rc_channels_override_get_chan3_raw(msg); + rc_channels_override->chan4_raw = mavlink_msg_rc_channels_override_get_chan4_raw(msg); + rc_channels_override->chan5_raw = mavlink_msg_rc_channels_override_get_chan5_raw(msg); + rc_channels_override->chan6_raw = mavlink_msg_rc_channels_override_get_chan6_raw(msg); + rc_channels_override->chan7_raw = mavlink_msg_rc_channels_override_get_chan7_raw(msg); + rc_channels_override->chan8_raw = mavlink_msg_rc_channels_override_get_chan8_raw(msg); +#else + memcpy(rc_channels_override, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_rc_channels_raw.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_rc_channels_raw.h new file mode 100644 index 0000000000..855f7cced3 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_rc_channels_raw.h @@ -0,0 +1,320 @@ +// MESSAGE RC_CHANNELS_RAW PACKING + +#define MAVLINK_MSG_ID_RC_CHANNELS_RAW 35 + +typedef struct __mavlink_rc_channels_raw_t +{ + uint16_t chan1_raw; ///< RC channel 1 value, in microseconds + uint16_t chan2_raw; ///< RC channel 2 value, in microseconds + uint16_t chan3_raw; ///< RC channel 3 value, in microseconds + uint16_t chan4_raw; ///< RC channel 4 value, in microseconds + uint16_t chan5_raw; ///< RC channel 5 value, in microseconds + uint16_t chan6_raw; ///< RC channel 6 value, in microseconds + uint16_t chan7_raw; ///< RC channel 7 value, in microseconds + uint16_t chan8_raw; ///< RC channel 8 value, in microseconds + uint8_t rssi; ///< Receive signal strength indicator, 0: 0%, 255: 100% +} mavlink_rc_channels_raw_t; + +#define MAVLINK_MSG_ID_RC_CHANNELS_RAW_LEN 17 +#define MAVLINK_MSG_ID_35_LEN 17 + + + +#define MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW { \ + "RC_CHANNELS_RAW", \ + 9, \ + { { "chan1_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_rc_channels_raw_t, chan1_raw) }, \ + { "chan2_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_rc_channels_raw_t, chan2_raw) }, \ + { "chan3_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_rc_channels_raw_t, chan3_raw) }, \ + { "chan4_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_rc_channels_raw_t, chan4_raw) }, \ + { "chan5_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 8, offsetof(mavlink_rc_channels_raw_t, chan5_raw) }, \ + { "chan6_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 10, offsetof(mavlink_rc_channels_raw_t, chan6_raw) }, \ + { "chan7_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 12, offsetof(mavlink_rc_channels_raw_t, chan7_raw) }, \ + { "chan8_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 14, offsetof(mavlink_rc_channels_raw_t, chan8_raw) }, \ + { "rssi", NULL, MAVLINK_TYPE_UINT8_T, 0, 16, offsetof(mavlink_rc_channels_raw_t, rssi) }, \ + } \ +} + + +/** + * @brief Pack a rc_channels_raw message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_rc_channels_raw_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t chan1_raw, uint16_t chan2_raw, uint16_t chan3_raw, uint16_t chan4_raw, uint16_t chan5_raw, uint16_t chan6_raw, uint16_t chan7_raw, uint16_t chan8_raw, uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[17]; + _mav_put_uint16_t(buf, 0, chan1_raw); + _mav_put_uint16_t(buf, 2, chan2_raw); + _mav_put_uint16_t(buf, 4, chan3_raw); + _mav_put_uint16_t(buf, 6, chan4_raw); + _mav_put_uint16_t(buf, 8, chan5_raw); + _mav_put_uint16_t(buf, 10, chan6_raw); + _mav_put_uint16_t(buf, 12, chan7_raw); + _mav_put_uint16_t(buf, 14, chan8_raw); + _mav_put_uint8_t(buf, 16, rssi); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 17); +#else + mavlink_rc_channels_raw_t packet; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + packet.rssi = rssi; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 17); +#endif + + msg->msgid = MAVLINK_MSG_ID_RC_CHANNELS_RAW; + return mavlink_finalize_message(msg, system_id, component_id, 17); +} + +/** + * @brief Pack a rc_channels_raw message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_rc_channels_raw_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t chan1_raw,uint16_t chan2_raw,uint16_t chan3_raw,uint16_t chan4_raw,uint16_t chan5_raw,uint16_t chan6_raw,uint16_t chan7_raw,uint16_t chan8_raw,uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[17]; + _mav_put_uint16_t(buf, 0, chan1_raw); + _mav_put_uint16_t(buf, 2, chan2_raw); + _mav_put_uint16_t(buf, 4, chan3_raw); + _mav_put_uint16_t(buf, 6, chan4_raw); + _mav_put_uint16_t(buf, 8, chan5_raw); + _mav_put_uint16_t(buf, 10, chan6_raw); + _mav_put_uint16_t(buf, 12, chan7_raw); + _mav_put_uint16_t(buf, 14, chan8_raw); + _mav_put_uint8_t(buf, 16, rssi); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 17); +#else + mavlink_rc_channels_raw_t packet; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + packet.rssi = rssi; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 17); +#endif + + msg->msgid = MAVLINK_MSG_ID_RC_CHANNELS_RAW; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 17); +} + +/** + * @brief Encode a rc_channels_raw struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param rc_channels_raw C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_rc_channels_raw_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_rc_channels_raw_t* rc_channels_raw) +{ + return mavlink_msg_rc_channels_raw_pack(system_id, component_id, msg, rc_channels_raw->chan1_raw, rc_channels_raw->chan2_raw, rc_channels_raw->chan3_raw, rc_channels_raw->chan4_raw, rc_channels_raw->chan5_raw, rc_channels_raw->chan6_raw, rc_channels_raw->chan7_raw, rc_channels_raw->chan8_raw, rc_channels_raw->rssi); +} + +/** + * @brief Send a rc_channels_raw message + * @param chan MAVLink channel to send the message + * + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_rc_channels_raw_send(mavlink_channel_t chan, uint16_t chan1_raw, uint16_t chan2_raw, uint16_t chan3_raw, uint16_t chan4_raw, uint16_t chan5_raw, uint16_t chan6_raw, uint16_t chan7_raw, uint16_t chan8_raw, uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[17]; + _mav_put_uint16_t(buf, 0, chan1_raw); + _mav_put_uint16_t(buf, 2, chan2_raw); + _mav_put_uint16_t(buf, 4, chan3_raw); + _mav_put_uint16_t(buf, 6, chan4_raw); + _mav_put_uint16_t(buf, 8, chan5_raw); + _mav_put_uint16_t(buf, 10, chan6_raw); + _mav_put_uint16_t(buf, 12, chan7_raw); + _mav_put_uint16_t(buf, 14, chan8_raw); + _mav_put_uint8_t(buf, 16, rssi); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RC_CHANNELS_RAW, buf, 17); +#else + mavlink_rc_channels_raw_t packet; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + packet.rssi = rssi; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RC_CHANNELS_RAW, (const char *)&packet, 17); +#endif +} + +#endif + +// MESSAGE RC_CHANNELS_RAW UNPACKING + + +/** + * @brief Get field chan1_raw from rc_channels_raw message + * + * @return RC channel 1 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan1_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field chan2_raw from rc_channels_raw message + * + * @return RC channel 2 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan2_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Get field chan3_raw from rc_channels_raw message + * + * @return RC channel 3 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan3_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field chan4_raw from rc_channels_raw message + * + * @return RC channel 4 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan4_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field chan5_raw from rc_channels_raw message + * + * @return RC channel 5 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan5_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Get field chan6_raw from rc_channels_raw message + * + * @return RC channel 6 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan6_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 10); +} + +/** + * @brief Get field chan7_raw from rc_channels_raw message + * + * @return RC channel 7 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan7_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 12); +} + +/** + * @brief Get field chan8_raw from rc_channels_raw message + * + * @return RC channel 8 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan8_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 14); +} + +/** + * @brief Get field rssi from rc_channels_raw message + * + * @return Receive signal strength indicator, 0: 0%, 255: 100% + */ +static inline uint8_t mavlink_msg_rc_channels_raw_get_rssi(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 16); +} + +/** + * @brief Decode a rc_channels_raw message into a struct + * + * @param msg The message to decode + * @param rc_channels_raw C-struct to decode the message contents into + */ +static inline void mavlink_msg_rc_channels_raw_decode(const mavlink_message_t* msg, mavlink_rc_channels_raw_t* rc_channels_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP + rc_channels_raw->chan1_raw = mavlink_msg_rc_channels_raw_get_chan1_raw(msg); + rc_channels_raw->chan2_raw = mavlink_msg_rc_channels_raw_get_chan2_raw(msg); + rc_channels_raw->chan3_raw = mavlink_msg_rc_channels_raw_get_chan3_raw(msg); + rc_channels_raw->chan4_raw = mavlink_msg_rc_channels_raw_get_chan4_raw(msg); + rc_channels_raw->chan5_raw = mavlink_msg_rc_channels_raw_get_chan5_raw(msg); + rc_channels_raw->chan6_raw = mavlink_msg_rc_channels_raw_get_chan6_raw(msg); + rc_channels_raw->chan7_raw = mavlink_msg_rc_channels_raw_get_chan7_raw(msg); + rc_channels_raw->chan8_raw = mavlink_msg_rc_channels_raw_get_chan8_raw(msg); + rc_channels_raw->rssi = mavlink_msg_rc_channels_raw_get_rssi(msg); +#else + memcpy(rc_channels_raw, _MAV_PAYLOAD(msg), 17); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_rc_channels_scaled.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_rc_channels_scaled.h new file mode 100644 index 0000000000..49df14a7ac --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_rc_channels_scaled.h @@ -0,0 +1,320 @@ +// MESSAGE RC_CHANNELS_SCALED PACKING + +#define MAVLINK_MSG_ID_RC_CHANNELS_SCALED 36 + +typedef struct __mavlink_rc_channels_scaled_t +{ + int16_t chan1_scaled; ///< RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan2_scaled; ///< RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan3_scaled; ///< RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan4_scaled; ///< RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan5_scaled; ///< RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan6_scaled; ///< RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan7_scaled; ///< RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan8_scaled; ///< RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + uint8_t rssi; ///< Receive signal strength indicator, 0: 0%, 255: 100% +} mavlink_rc_channels_scaled_t; + +#define MAVLINK_MSG_ID_RC_CHANNELS_SCALED_LEN 17 +#define MAVLINK_MSG_ID_36_LEN 17 + + + +#define MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED { \ + "RC_CHANNELS_SCALED", \ + 9, \ + { { "chan1_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 0, offsetof(mavlink_rc_channels_scaled_t, chan1_scaled) }, \ + { "chan2_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 2, offsetof(mavlink_rc_channels_scaled_t, chan2_scaled) }, \ + { "chan3_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 4, offsetof(mavlink_rc_channels_scaled_t, chan3_scaled) }, \ + { "chan4_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 6, offsetof(mavlink_rc_channels_scaled_t, chan4_scaled) }, \ + { "chan5_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 8, offsetof(mavlink_rc_channels_scaled_t, chan5_scaled) }, \ + { "chan6_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 10, offsetof(mavlink_rc_channels_scaled_t, chan6_scaled) }, \ + { "chan7_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_rc_channels_scaled_t, chan7_scaled) }, \ + { "chan8_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 14, offsetof(mavlink_rc_channels_scaled_t, chan8_scaled) }, \ + { "rssi", NULL, MAVLINK_TYPE_UINT8_T, 0, 16, offsetof(mavlink_rc_channels_scaled_t, rssi) }, \ + } \ +} + + +/** + * @brief Pack a rc_channels_scaled message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param chan1_scaled RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan2_scaled RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan3_scaled RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan4_scaled RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan5_scaled RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan6_scaled RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan7_scaled RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan8_scaled RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_rc_channels_scaled_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + int16_t chan1_scaled, int16_t chan2_scaled, int16_t chan3_scaled, int16_t chan4_scaled, int16_t chan5_scaled, int16_t chan6_scaled, int16_t chan7_scaled, int16_t chan8_scaled, uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[17]; + _mav_put_int16_t(buf, 0, chan1_scaled); + _mav_put_int16_t(buf, 2, chan2_scaled); + _mav_put_int16_t(buf, 4, chan3_scaled); + _mav_put_int16_t(buf, 6, chan4_scaled); + _mav_put_int16_t(buf, 8, chan5_scaled); + _mav_put_int16_t(buf, 10, chan6_scaled); + _mav_put_int16_t(buf, 12, chan7_scaled); + _mav_put_int16_t(buf, 14, chan8_scaled); + _mav_put_uint8_t(buf, 16, rssi); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 17); +#else + mavlink_rc_channels_scaled_t packet; + packet.chan1_scaled = chan1_scaled; + packet.chan2_scaled = chan2_scaled; + packet.chan3_scaled = chan3_scaled; + packet.chan4_scaled = chan4_scaled; + packet.chan5_scaled = chan5_scaled; + packet.chan6_scaled = chan6_scaled; + packet.chan7_scaled = chan7_scaled; + packet.chan8_scaled = chan8_scaled; + packet.rssi = rssi; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 17); +#endif + + msg->msgid = MAVLINK_MSG_ID_RC_CHANNELS_SCALED; + return mavlink_finalize_message(msg, system_id, component_id, 17); +} + +/** + * @brief Pack a rc_channels_scaled message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param chan1_scaled RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan2_scaled RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan3_scaled RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan4_scaled RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan5_scaled RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan6_scaled RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan7_scaled RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan8_scaled RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_rc_channels_scaled_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + int16_t chan1_scaled,int16_t chan2_scaled,int16_t chan3_scaled,int16_t chan4_scaled,int16_t chan5_scaled,int16_t chan6_scaled,int16_t chan7_scaled,int16_t chan8_scaled,uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[17]; + _mav_put_int16_t(buf, 0, chan1_scaled); + _mav_put_int16_t(buf, 2, chan2_scaled); + _mav_put_int16_t(buf, 4, chan3_scaled); + _mav_put_int16_t(buf, 6, chan4_scaled); + _mav_put_int16_t(buf, 8, chan5_scaled); + _mav_put_int16_t(buf, 10, chan6_scaled); + _mav_put_int16_t(buf, 12, chan7_scaled); + _mav_put_int16_t(buf, 14, chan8_scaled); + _mav_put_uint8_t(buf, 16, rssi); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 17); +#else + mavlink_rc_channels_scaled_t packet; + packet.chan1_scaled = chan1_scaled; + packet.chan2_scaled = chan2_scaled; + packet.chan3_scaled = chan3_scaled; + packet.chan4_scaled = chan4_scaled; + packet.chan5_scaled = chan5_scaled; + packet.chan6_scaled = chan6_scaled; + packet.chan7_scaled = chan7_scaled; + packet.chan8_scaled = chan8_scaled; + packet.rssi = rssi; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 17); +#endif + + msg->msgid = MAVLINK_MSG_ID_RC_CHANNELS_SCALED; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 17); +} + +/** + * @brief Encode a rc_channels_scaled struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param rc_channels_scaled C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_rc_channels_scaled_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_rc_channels_scaled_t* rc_channels_scaled) +{ + return mavlink_msg_rc_channels_scaled_pack(system_id, component_id, msg, rc_channels_scaled->chan1_scaled, rc_channels_scaled->chan2_scaled, rc_channels_scaled->chan3_scaled, rc_channels_scaled->chan4_scaled, rc_channels_scaled->chan5_scaled, rc_channels_scaled->chan6_scaled, rc_channels_scaled->chan7_scaled, rc_channels_scaled->chan8_scaled, rc_channels_scaled->rssi); +} + +/** + * @brief Send a rc_channels_scaled message + * @param chan MAVLink channel to send the message + * + * @param chan1_scaled RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan2_scaled RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan3_scaled RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan4_scaled RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan5_scaled RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan6_scaled RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan7_scaled RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan8_scaled RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_rc_channels_scaled_send(mavlink_channel_t chan, int16_t chan1_scaled, int16_t chan2_scaled, int16_t chan3_scaled, int16_t chan4_scaled, int16_t chan5_scaled, int16_t chan6_scaled, int16_t chan7_scaled, int16_t chan8_scaled, uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[17]; + _mav_put_int16_t(buf, 0, chan1_scaled); + _mav_put_int16_t(buf, 2, chan2_scaled); + _mav_put_int16_t(buf, 4, chan3_scaled); + _mav_put_int16_t(buf, 6, chan4_scaled); + _mav_put_int16_t(buf, 8, chan5_scaled); + _mav_put_int16_t(buf, 10, chan6_scaled); + _mav_put_int16_t(buf, 12, chan7_scaled); + _mav_put_int16_t(buf, 14, chan8_scaled); + _mav_put_uint8_t(buf, 16, rssi); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RC_CHANNELS_SCALED, buf, 17); +#else + mavlink_rc_channels_scaled_t packet; + packet.chan1_scaled = chan1_scaled; + packet.chan2_scaled = chan2_scaled; + packet.chan3_scaled = chan3_scaled; + packet.chan4_scaled = chan4_scaled; + packet.chan5_scaled = chan5_scaled; + packet.chan6_scaled = chan6_scaled; + packet.chan7_scaled = chan7_scaled; + packet.chan8_scaled = chan8_scaled; + packet.rssi = rssi; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RC_CHANNELS_SCALED, (const char *)&packet, 17); +#endif +} + +#endif + +// MESSAGE RC_CHANNELS_SCALED UNPACKING + + +/** + * @brief Get field chan1_scaled from rc_channels_scaled message + * + * @return RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan1_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 0); +} + +/** + * @brief Get field chan2_scaled from rc_channels_scaled message + * + * @return RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan2_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 2); +} + +/** + * @brief Get field chan3_scaled from rc_channels_scaled message + * + * @return RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan3_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 4); +} + +/** + * @brief Get field chan4_scaled from rc_channels_scaled message + * + * @return RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan4_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 6); +} + +/** + * @brief Get field chan5_scaled from rc_channels_scaled message + * + * @return RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan5_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 8); +} + +/** + * @brief Get field chan6_scaled from rc_channels_scaled message + * + * @return RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan6_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 10); +} + +/** + * @brief Get field chan7_scaled from rc_channels_scaled message + * + * @return RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan7_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Get field chan8_scaled from rc_channels_scaled message + * + * @return RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan8_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 14); +} + +/** + * @brief Get field rssi from rc_channels_scaled message + * + * @return Receive signal strength indicator, 0: 0%, 255: 100% + */ +static inline uint8_t mavlink_msg_rc_channels_scaled_get_rssi(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 16); +} + +/** + * @brief Decode a rc_channels_scaled message into a struct + * + * @param msg The message to decode + * @param rc_channels_scaled C-struct to decode the message contents into + */ +static inline void mavlink_msg_rc_channels_scaled_decode(const mavlink_message_t* msg, mavlink_rc_channels_scaled_t* rc_channels_scaled) +{ +#if MAVLINK_NEED_BYTE_SWAP + rc_channels_scaled->chan1_scaled = mavlink_msg_rc_channels_scaled_get_chan1_scaled(msg); + rc_channels_scaled->chan2_scaled = mavlink_msg_rc_channels_scaled_get_chan2_scaled(msg); + rc_channels_scaled->chan3_scaled = mavlink_msg_rc_channels_scaled_get_chan3_scaled(msg); + rc_channels_scaled->chan4_scaled = mavlink_msg_rc_channels_scaled_get_chan4_scaled(msg); + rc_channels_scaled->chan5_scaled = mavlink_msg_rc_channels_scaled_get_chan5_scaled(msg); + rc_channels_scaled->chan6_scaled = mavlink_msg_rc_channels_scaled_get_chan6_scaled(msg); + rc_channels_scaled->chan7_scaled = mavlink_msg_rc_channels_scaled_get_chan7_scaled(msg); + rc_channels_scaled->chan8_scaled = mavlink_msg_rc_channels_scaled_get_chan8_scaled(msg); + rc_channels_scaled->rssi = mavlink_msg_rc_channels_scaled_get_rssi(msg); +#else + memcpy(rc_channels_scaled, _MAV_PAYLOAD(msg), 17); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_request_data_stream.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_request_data_stream.h new file mode 100644 index 0000000000..e80473aa11 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_request_data_stream.h @@ -0,0 +1,232 @@ +// MESSAGE REQUEST_DATA_STREAM PACKING + +#define MAVLINK_MSG_ID_REQUEST_DATA_STREAM 66 + +typedef struct __mavlink_request_data_stream_t +{ + uint8_t target_system; ///< The target requested to send the message stream. + uint8_t target_component; ///< The target requested to send the message stream. + uint8_t req_stream_id; ///< The ID of the requested message type + uint16_t req_message_rate; ///< Update rate in Hertz + uint8_t start_stop; ///< 1 to start sending, 0 to stop sending. +} mavlink_request_data_stream_t; + +#define MAVLINK_MSG_ID_REQUEST_DATA_STREAM_LEN 6 +#define MAVLINK_MSG_ID_66_LEN 6 + + + +#define MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM { \ + "REQUEST_DATA_STREAM", \ + 5, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_request_data_stream_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_request_data_stream_t, target_component) }, \ + { "req_stream_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_request_data_stream_t, req_stream_id) }, \ + { "req_message_rate", NULL, MAVLINK_TYPE_UINT16_T, 0, 3, offsetof(mavlink_request_data_stream_t, req_message_rate) }, \ + { "start_stop", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_request_data_stream_t, start_stop) }, \ + } \ +} + + +/** + * @brief Pack a request_data_stream message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system The target requested to send the message stream. + * @param target_component The target requested to send the message stream. + * @param req_stream_id The ID of the requested message type + * @param req_message_rate Update rate in Hertz + * @param start_stop 1 to start sending, 0 to stop sending. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_request_data_stream_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t req_stream_id, uint16_t req_message_rate, uint8_t start_stop) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, req_stream_id); + _mav_put_uint16_t(buf, 3, req_message_rate); + _mav_put_uint8_t(buf, 5, start_stop); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_request_data_stream_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.req_stream_id = req_stream_id; + packet.req_message_rate = req_message_rate; + packet.start_stop = start_stop; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_REQUEST_DATA_STREAM; + return mavlink_finalize_message(msg, system_id, component_id, 6); +} + +/** + * @brief Pack a request_data_stream message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system The target requested to send the message stream. + * @param target_component The target requested to send the message stream. + * @param req_stream_id The ID of the requested message type + * @param req_message_rate Update rate in Hertz + * @param start_stop 1 to start sending, 0 to stop sending. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_request_data_stream_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t req_stream_id,uint16_t req_message_rate,uint8_t start_stop) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, req_stream_id); + _mav_put_uint16_t(buf, 3, req_message_rate); + _mav_put_uint8_t(buf, 5, start_stop); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_request_data_stream_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.req_stream_id = req_stream_id; + packet.req_message_rate = req_message_rate; + packet.start_stop = start_stop; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_REQUEST_DATA_STREAM; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 6); +} + +/** + * @brief Encode a request_data_stream struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param request_data_stream C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_request_data_stream_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_request_data_stream_t* request_data_stream) +{ + return mavlink_msg_request_data_stream_pack(system_id, component_id, msg, request_data_stream->target_system, request_data_stream->target_component, request_data_stream->req_stream_id, request_data_stream->req_message_rate, request_data_stream->start_stop); +} + +/** + * @brief Send a request_data_stream message + * @param chan MAVLink channel to send the message + * + * @param target_system The target requested to send the message stream. + * @param target_component The target requested to send the message stream. + * @param req_stream_id The ID of the requested message type + * @param req_message_rate Update rate in Hertz + * @param start_stop 1 to start sending, 0 to stop sending. + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_request_data_stream_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t req_stream_id, uint16_t req_message_rate, uint8_t start_stop) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, req_stream_id); + _mav_put_uint16_t(buf, 3, req_message_rate); + _mav_put_uint8_t(buf, 5, start_stop); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_REQUEST_DATA_STREAM, buf, 6); +#else + mavlink_request_data_stream_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.req_stream_id = req_stream_id; + packet.req_message_rate = req_message_rate; + packet.start_stop = start_stop; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_REQUEST_DATA_STREAM, (const char *)&packet, 6); +#endif +} + +#endif + +// MESSAGE REQUEST_DATA_STREAM UNPACKING + + +/** + * @brief Get field target_system from request_data_stream message + * + * @return The target requested to send the message stream. + */ +static inline uint8_t mavlink_msg_request_data_stream_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from request_data_stream message + * + * @return The target requested to send the message stream. + */ +static inline uint8_t mavlink_msg_request_data_stream_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field req_stream_id from request_data_stream message + * + * @return The ID of the requested message type + */ +static inline uint8_t mavlink_msg_request_data_stream_get_req_stream_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field req_message_rate from request_data_stream message + * + * @return Update rate in Hertz + */ +static inline uint16_t mavlink_msg_request_data_stream_get_req_message_rate(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 3); +} + +/** + * @brief Get field start_stop from request_data_stream message + * + * @return 1 to start sending, 0 to stop sending. + */ +static inline uint8_t mavlink_msg_request_data_stream_get_start_stop(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Decode a request_data_stream message into a struct + * + * @param msg The message to decode + * @param request_data_stream C-struct to decode the message contents into + */ +static inline void mavlink_msg_request_data_stream_decode(const mavlink_message_t* msg, mavlink_request_data_stream_t* request_data_stream) +{ +#if MAVLINK_NEED_BYTE_SWAP + request_data_stream->target_system = mavlink_msg_request_data_stream_get_target_system(msg); + request_data_stream->target_component = mavlink_msg_request_data_stream_get_target_component(msg); + request_data_stream->req_stream_id = mavlink_msg_request_data_stream_get_req_stream_id(msg); + request_data_stream->req_message_rate = mavlink_msg_request_data_stream_get_req_message_rate(msg); + request_data_stream->start_stop = mavlink_msg_request_data_stream_get_start_stop(msg); +#else + memcpy(request_data_stream, _MAV_PAYLOAD(msg), 6); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint.h new file mode 100644 index 0000000000..b344f3aa27 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint.h @@ -0,0 +1,232 @@ +// MESSAGE ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT PACKING + +#define MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT 58 + +typedef struct __mavlink_roll_pitch_yaw_speed_thrust_setpoint_t +{ + uint64_t time_us; ///< Timestamp in micro seconds since unix epoch + float roll_speed; ///< Desired roll angular speed in rad/s + float pitch_speed; ///< Desired pitch angular speed in rad/s + float yaw_speed; ///< Desired yaw angular speed in rad/s + float thrust; ///< Collective thrust, normalized to 0 .. 1 +} mavlink_roll_pitch_yaw_speed_thrust_setpoint_t; + +#define MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT_LEN 24 +#define MAVLINK_MSG_ID_58_LEN 24 + + + +#define MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT { \ + "ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT", \ + 5, \ + { { "time_us", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_roll_pitch_yaw_speed_thrust_setpoint_t, time_us) }, \ + { "roll_speed", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_roll_pitch_yaw_speed_thrust_setpoint_t, roll_speed) }, \ + { "pitch_speed", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_roll_pitch_yaw_speed_thrust_setpoint_t, pitch_speed) }, \ + { "yaw_speed", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_roll_pitch_yaw_speed_thrust_setpoint_t, yaw_speed) }, \ + { "thrust", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_roll_pitch_yaw_speed_thrust_setpoint_t, thrust) }, \ + } \ +} + + +/** + * @brief Pack a roll_pitch_yaw_speed_thrust_setpoint message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_us Timestamp in micro seconds since unix epoch + * @param roll_speed Desired roll angular speed in rad/s + * @param pitch_speed Desired pitch angular speed in rad/s + * @param yaw_speed Desired yaw angular speed in rad/s + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time_us, float roll_speed, float pitch_speed, float yaw_speed, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_uint64_t(buf, 0, time_us); + _mav_put_float(buf, 8, roll_speed); + _mav_put_float(buf, 12, pitch_speed); + _mav_put_float(buf, 16, yaw_speed); + _mav_put_float(buf, 20, thrust); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_roll_pitch_yaw_speed_thrust_setpoint_t packet; + packet.time_us = time_us; + packet.roll_speed = roll_speed; + packet.pitch_speed = pitch_speed; + packet.yaw_speed = yaw_speed; + packet.thrust = thrust; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT; + return mavlink_finalize_message(msg, system_id, component_id, 24); +} + +/** + * @brief Pack a roll_pitch_yaw_speed_thrust_setpoint message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_us Timestamp in micro seconds since unix epoch + * @param roll_speed Desired roll angular speed in rad/s + * @param pitch_speed Desired pitch angular speed in rad/s + * @param yaw_speed Desired yaw angular speed in rad/s + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time_us,float roll_speed,float pitch_speed,float yaw_speed,float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_uint64_t(buf, 0, time_us); + _mav_put_float(buf, 8, roll_speed); + _mav_put_float(buf, 12, pitch_speed); + _mav_put_float(buf, 16, yaw_speed); + _mav_put_float(buf, 20, thrust); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_roll_pitch_yaw_speed_thrust_setpoint_t packet; + packet.time_us = time_us; + packet.roll_speed = roll_speed; + packet.pitch_speed = pitch_speed; + packet.yaw_speed = yaw_speed; + packet.thrust = thrust; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 24); +} + +/** + * @brief Encode a roll_pitch_yaw_speed_thrust_setpoint struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param roll_pitch_yaw_speed_thrust_setpoint C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_roll_pitch_yaw_speed_thrust_setpoint_t* roll_pitch_yaw_speed_thrust_setpoint) +{ + return mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_pack(system_id, component_id, msg, roll_pitch_yaw_speed_thrust_setpoint->time_us, roll_pitch_yaw_speed_thrust_setpoint->roll_speed, roll_pitch_yaw_speed_thrust_setpoint->pitch_speed, roll_pitch_yaw_speed_thrust_setpoint->yaw_speed, roll_pitch_yaw_speed_thrust_setpoint->thrust); +} + +/** + * @brief Send a roll_pitch_yaw_speed_thrust_setpoint message + * @param chan MAVLink channel to send the message + * + * @param time_us Timestamp in micro seconds since unix epoch + * @param roll_speed Desired roll angular speed in rad/s + * @param pitch_speed Desired pitch angular speed in rad/s + * @param yaw_speed Desired yaw angular speed in rad/s + * @param thrust Collective thrust, normalized to 0 .. 1 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_send(mavlink_channel_t chan, uint64_t time_us, float roll_speed, float pitch_speed, float yaw_speed, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_uint64_t(buf, 0, time_us); + _mav_put_float(buf, 8, roll_speed); + _mav_put_float(buf, 12, pitch_speed); + _mav_put_float(buf, 16, yaw_speed); + _mav_put_float(buf, 20, thrust); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, buf, 24); +#else + mavlink_roll_pitch_yaw_speed_thrust_setpoint_t packet; + packet.time_us = time_us; + packet.roll_speed = roll_speed; + packet.pitch_speed = pitch_speed; + packet.yaw_speed = yaw_speed; + packet.thrust = thrust; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, (const char *)&packet, 24); +#endif +} + +#endif + +// MESSAGE ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT UNPACKING + + +/** + * @brief Get field time_us from roll_pitch_yaw_speed_thrust_setpoint message + * + * @return Timestamp in micro seconds since unix epoch + */ +static inline uint64_t mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_time_us(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field roll_speed from roll_pitch_yaw_speed_thrust_setpoint message + * + * @return Desired roll angular speed in rad/s + */ +static inline float mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_roll_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field pitch_speed from roll_pitch_yaw_speed_thrust_setpoint message + * + * @return Desired pitch angular speed in rad/s + */ +static inline float mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_pitch_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field yaw_speed from roll_pitch_yaw_speed_thrust_setpoint message + * + * @return Desired yaw angular speed in rad/s + */ +static inline float mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_yaw_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field thrust from roll_pitch_yaw_speed_thrust_setpoint message + * + * @return Collective thrust, normalized to 0 .. 1 + */ +static inline float mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_thrust(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Decode a roll_pitch_yaw_speed_thrust_setpoint message into a struct + * + * @param msg The message to decode + * @param roll_pitch_yaw_speed_thrust_setpoint C-struct to decode the message contents into + */ +static inline void mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_decode(const mavlink_message_t* msg, mavlink_roll_pitch_yaw_speed_thrust_setpoint_t* roll_pitch_yaw_speed_thrust_setpoint) +{ +#if MAVLINK_NEED_BYTE_SWAP + roll_pitch_yaw_speed_thrust_setpoint->time_us = mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_time_us(msg); + roll_pitch_yaw_speed_thrust_setpoint->roll_speed = mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_roll_speed(msg); + roll_pitch_yaw_speed_thrust_setpoint->pitch_speed = mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_pitch_speed(msg); + roll_pitch_yaw_speed_thrust_setpoint->yaw_speed = mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_yaw_speed(msg); + roll_pitch_yaw_speed_thrust_setpoint->thrust = mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_thrust(msg); +#else + memcpy(roll_pitch_yaw_speed_thrust_setpoint, _MAV_PAYLOAD(msg), 24); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_roll_pitch_yaw_thrust_setpoint.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_roll_pitch_yaw_thrust_setpoint.h new file mode 100644 index 0000000000..16155f1343 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_roll_pitch_yaw_thrust_setpoint.h @@ -0,0 +1,232 @@ +// MESSAGE ROLL_PITCH_YAW_THRUST_SETPOINT PACKING + +#define MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT 57 + +typedef struct __mavlink_roll_pitch_yaw_thrust_setpoint_t +{ + uint64_t time_us; ///< Timestamp in micro seconds since unix epoch + float roll; ///< Desired roll angle in radians + float pitch; ///< Desired pitch angle in radians + float yaw; ///< Desired yaw angle in radians + float thrust; ///< Collective thrust, normalized to 0 .. 1 +} mavlink_roll_pitch_yaw_thrust_setpoint_t; + +#define MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT_LEN 24 +#define MAVLINK_MSG_ID_57_LEN 24 + + + +#define MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT { \ + "ROLL_PITCH_YAW_THRUST_SETPOINT", \ + 5, \ + { { "time_us", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_roll_pitch_yaw_thrust_setpoint_t, time_us) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_roll_pitch_yaw_thrust_setpoint_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_roll_pitch_yaw_thrust_setpoint_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_roll_pitch_yaw_thrust_setpoint_t, yaw) }, \ + { "thrust", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_roll_pitch_yaw_thrust_setpoint_t, thrust) }, \ + } \ +} + + +/** + * @brief Pack a roll_pitch_yaw_thrust_setpoint message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_us Timestamp in micro seconds since unix epoch + * @param roll Desired roll angle in radians + * @param pitch Desired pitch angle in radians + * @param yaw Desired yaw angle in radians + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_roll_pitch_yaw_thrust_setpoint_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time_us, float roll, float pitch, float yaw, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_uint64_t(buf, 0, time_us); + _mav_put_float(buf, 8, roll); + _mav_put_float(buf, 12, pitch); + _mav_put_float(buf, 16, yaw); + _mav_put_float(buf, 20, thrust); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_roll_pitch_yaw_thrust_setpoint_t packet; + packet.time_us = time_us; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT; + return mavlink_finalize_message(msg, system_id, component_id, 24); +} + +/** + * @brief Pack a roll_pitch_yaw_thrust_setpoint message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_us Timestamp in micro seconds since unix epoch + * @param roll Desired roll angle in radians + * @param pitch Desired pitch angle in radians + * @param yaw Desired yaw angle in radians + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_roll_pitch_yaw_thrust_setpoint_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time_us,float roll,float pitch,float yaw,float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_uint64_t(buf, 0, time_us); + _mav_put_float(buf, 8, roll); + _mav_put_float(buf, 12, pitch); + _mav_put_float(buf, 16, yaw); + _mav_put_float(buf, 20, thrust); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_roll_pitch_yaw_thrust_setpoint_t packet; + packet.time_us = time_us; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 24); +} + +/** + * @brief Encode a roll_pitch_yaw_thrust_setpoint struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param roll_pitch_yaw_thrust_setpoint C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_roll_pitch_yaw_thrust_setpoint_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_roll_pitch_yaw_thrust_setpoint_t* roll_pitch_yaw_thrust_setpoint) +{ + return mavlink_msg_roll_pitch_yaw_thrust_setpoint_pack(system_id, component_id, msg, roll_pitch_yaw_thrust_setpoint->time_us, roll_pitch_yaw_thrust_setpoint->roll, roll_pitch_yaw_thrust_setpoint->pitch, roll_pitch_yaw_thrust_setpoint->yaw, roll_pitch_yaw_thrust_setpoint->thrust); +} + +/** + * @brief Send a roll_pitch_yaw_thrust_setpoint message + * @param chan MAVLink channel to send the message + * + * @param time_us Timestamp in micro seconds since unix epoch + * @param roll Desired roll angle in radians + * @param pitch Desired pitch angle in radians + * @param yaw Desired yaw angle in radians + * @param thrust Collective thrust, normalized to 0 .. 1 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_roll_pitch_yaw_thrust_setpoint_send(mavlink_channel_t chan, uint64_t time_us, float roll, float pitch, float yaw, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_uint64_t(buf, 0, time_us); + _mav_put_float(buf, 8, roll); + _mav_put_float(buf, 12, pitch); + _mav_put_float(buf, 16, yaw); + _mav_put_float(buf, 20, thrust); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT, buf, 24); +#else + mavlink_roll_pitch_yaw_thrust_setpoint_t packet; + packet.time_us = time_us; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT, (const char *)&packet, 24); +#endif +} + +#endif + +// MESSAGE ROLL_PITCH_YAW_THRUST_SETPOINT UNPACKING + + +/** + * @brief Get field time_us from roll_pitch_yaw_thrust_setpoint message + * + * @return Timestamp in micro seconds since unix epoch + */ +static inline uint64_t mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_time_us(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field roll from roll_pitch_yaw_thrust_setpoint message + * + * @return Desired roll angle in radians + */ +static inline float mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field pitch from roll_pitch_yaw_thrust_setpoint message + * + * @return Desired pitch angle in radians + */ +static inline float mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field yaw from roll_pitch_yaw_thrust_setpoint message + * + * @return Desired yaw angle in radians + */ +static inline float mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field thrust from roll_pitch_yaw_thrust_setpoint message + * + * @return Collective thrust, normalized to 0 .. 1 + */ +static inline float mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_thrust(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Decode a roll_pitch_yaw_thrust_setpoint message into a struct + * + * @param msg The message to decode + * @param roll_pitch_yaw_thrust_setpoint C-struct to decode the message contents into + */ +static inline void mavlink_msg_roll_pitch_yaw_thrust_setpoint_decode(const mavlink_message_t* msg, mavlink_roll_pitch_yaw_thrust_setpoint_t* roll_pitch_yaw_thrust_setpoint) +{ +#if MAVLINK_NEED_BYTE_SWAP + roll_pitch_yaw_thrust_setpoint->time_us = mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_time_us(msg); + roll_pitch_yaw_thrust_setpoint->roll = mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_roll(msg); + roll_pitch_yaw_thrust_setpoint->pitch = mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_pitch(msg); + roll_pitch_yaw_thrust_setpoint->yaw = mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_yaw(msg); + roll_pitch_yaw_thrust_setpoint->thrust = mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_thrust(msg); +#else + memcpy(roll_pitch_yaw_thrust_setpoint, _MAV_PAYLOAD(msg), 24); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_safety_allowed_area.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_safety_allowed_area.h new file mode 100644 index 0000000000..07b91fd0ed --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_safety_allowed_area.h @@ -0,0 +1,276 @@ +// MESSAGE SAFETY_ALLOWED_AREA PACKING + +#define MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA 54 + +typedef struct __mavlink_safety_allowed_area_t +{ + uint8_t frame; ///< Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + float p1x; ///< x position 1 / Latitude 1 + float p1y; ///< y position 1 / Longitude 1 + float p1z; ///< z position 1 / Altitude 1 + float p2x; ///< x position 2 / Latitude 2 + float p2y; ///< y position 2 / Longitude 2 + float p2z; ///< z position 2 / Altitude 2 +} mavlink_safety_allowed_area_t; + +#define MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA_LEN 25 +#define MAVLINK_MSG_ID_54_LEN 25 + + + +#define MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA { \ + "SAFETY_ALLOWED_AREA", \ + 7, \ + { { "frame", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_safety_allowed_area_t, frame) }, \ + { "p1x", NULL, MAVLINK_TYPE_FLOAT, 0, 1, offsetof(mavlink_safety_allowed_area_t, p1x) }, \ + { "p1y", NULL, MAVLINK_TYPE_FLOAT, 0, 5, offsetof(mavlink_safety_allowed_area_t, p1y) }, \ + { "p1z", NULL, MAVLINK_TYPE_FLOAT, 0, 9, offsetof(mavlink_safety_allowed_area_t, p1z) }, \ + { "p2x", NULL, MAVLINK_TYPE_FLOAT, 0, 13, offsetof(mavlink_safety_allowed_area_t, p2x) }, \ + { "p2y", NULL, MAVLINK_TYPE_FLOAT, 0, 17, offsetof(mavlink_safety_allowed_area_t, p2y) }, \ + { "p2z", NULL, MAVLINK_TYPE_FLOAT, 0, 21, offsetof(mavlink_safety_allowed_area_t, p2z) }, \ + } \ +} + + +/** + * @brief Pack a safety_allowed_area message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param frame Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + * @param p1x x position 1 / Latitude 1 + * @param p1y y position 1 / Longitude 1 + * @param p1z z position 1 / Altitude 1 + * @param p2x x position 2 / Latitude 2 + * @param p2y y position 2 / Longitude 2 + * @param p2z z position 2 / Altitude 2 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_safety_allowed_area_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t frame, float p1x, float p1y, float p1z, float p2x, float p2y, float p2z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[25]; + _mav_put_uint8_t(buf, 0, frame); + _mav_put_float(buf, 1, p1x); + _mav_put_float(buf, 5, p1y); + _mav_put_float(buf, 9, p1z); + _mav_put_float(buf, 13, p2x); + _mav_put_float(buf, 17, p2y); + _mav_put_float(buf, 21, p2z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 25); +#else + mavlink_safety_allowed_area_t packet; + packet.frame = frame; + packet.p1x = p1x; + packet.p1y = p1y; + packet.p1z = p1z; + packet.p2x = p2x; + packet.p2y = p2y; + packet.p2z = p2z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 25); +#endif + + msg->msgid = MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA; + return mavlink_finalize_message(msg, system_id, component_id, 25); +} + +/** + * @brief Pack a safety_allowed_area message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param frame Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + * @param p1x x position 1 / Latitude 1 + * @param p1y y position 1 / Longitude 1 + * @param p1z z position 1 / Altitude 1 + * @param p2x x position 2 / Latitude 2 + * @param p2y y position 2 / Longitude 2 + * @param p2z z position 2 / Altitude 2 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_safety_allowed_area_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t frame,float p1x,float p1y,float p1z,float p2x,float p2y,float p2z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[25]; + _mav_put_uint8_t(buf, 0, frame); + _mav_put_float(buf, 1, p1x); + _mav_put_float(buf, 5, p1y); + _mav_put_float(buf, 9, p1z); + _mav_put_float(buf, 13, p2x); + _mav_put_float(buf, 17, p2y); + _mav_put_float(buf, 21, p2z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 25); +#else + mavlink_safety_allowed_area_t packet; + packet.frame = frame; + packet.p1x = p1x; + packet.p1y = p1y; + packet.p1z = p1z; + packet.p2x = p2x; + packet.p2y = p2y; + packet.p2z = p2z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 25); +#endif + + msg->msgid = MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 25); +} + +/** + * @brief Encode a safety_allowed_area struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param safety_allowed_area C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_safety_allowed_area_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_safety_allowed_area_t* safety_allowed_area) +{ + return mavlink_msg_safety_allowed_area_pack(system_id, component_id, msg, safety_allowed_area->frame, safety_allowed_area->p1x, safety_allowed_area->p1y, safety_allowed_area->p1z, safety_allowed_area->p2x, safety_allowed_area->p2y, safety_allowed_area->p2z); +} + +/** + * @brief Send a safety_allowed_area message + * @param chan MAVLink channel to send the message + * + * @param frame Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + * @param p1x x position 1 / Latitude 1 + * @param p1y y position 1 / Longitude 1 + * @param p1z z position 1 / Altitude 1 + * @param p2x x position 2 / Latitude 2 + * @param p2y y position 2 / Longitude 2 + * @param p2z z position 2 / Altitude 2 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_safety_allowed_area_send(mavlink_channel_t chan, uint8_t frame, float p1x, float p1y, float p1z, float p2x, float p2y, float p2z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[25]; + _mav_put_uint8_t(buf, 0, frame); + _mav_put_float(buf, 1, p1x); + _mav_put_float(buf, 5, p1y); + _mav_put_float(buf, 9, p1z); + _mav_put_float(buf, 13, p2x); + _mav_put_float(buf, 17, p2y); + _mav_put_float(buf, 21, p2z); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA, buf, 25); +#else + mavlink_safety_allowed_area_t packet; + packet.frame = frame; + packet.p1x = p1x; + packet.p1y = p1y; + packet.p1z = p1z; + packet.p2x = p2x; + packet.p2y = p2y; + packet.p2z = p2z; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA, (const char *)&packet, 25); +#endif +} + +#endif + +// MESSAGE SAFETY_ALLOWED_AREA UNPACKING + + +/** + * @brief Get field frame from safety_allowed_area message + * + * @return Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + */ +static inline uint8_t mavlink_msg_safety_allowed_area_get_frame(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field p1x from safety_allowed_area message + * + * @return x position 1 / Latitude 1 + */ +static inline float mavlink_msg_safety_allowed_area_get_p1x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 1); +} + +/** + * @brief Get field p1y from safety_allowed_area message + * + * @return y position 1 / Longitude 1 + */ +static inline float mavlink_msg_safety_allowed_area_get_p1y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 5); +} + +/** + * @brief Get field p1z from safety_allowed_area message + * + * @return z position 1 / Altitude 1 + */ +static inline float mavlink_msg_safety_allowed_area_get_p1z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 9); +} + +/** + * @brief Get field p2x from safety_allowed_area message + * + * @return x position 2 / Latitude 2 + */ +static inline float mavlink_msg_safety_allowed_area_get_p2x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 13); +} + +/** + * @brief Get field p2y from safety_allowed_area message + * + * @return y position 2 / Longitude 2 + */ +static inline float mavlink_msg_safety_allowed_area_get_p2y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 17); +} + +/** + * @brief Get field p2z from safety_allowed_area message + * + * @return z position 2 / Altitude 2 + */ +static inline float mavlink_msg_safety_allowed_area_get_p2z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 21); +} + +/** + * @brief Decode a safety_allowed_area message into a struct + * + * @param msg The message to decode + * @param safety_allowed_area C-struct to decode the message contents into + */ +static inline void mavlink_msg_safety_allowed_area_decode(const mavlink_message_t* msg, mavlink_safety_allowed_area_t* safety_allowed_area) +{ +#if MAVLINK_NEED_BYTE_SWAP + safety_allowed_area->frame = mavlink_msg_safety_allowed_area_get_frame(msg); + safety_allowed_area->p1x = mavlink_msg_safety_allowed_area_get_p1x(msg); + safety_allowed_area->p1y = mavlink_msg_safety_allowed_area_get_p1y(msg); + safety_allowed_area->p1z = mavlink_msg_safety_allowed_area_get_p1z(msg); + safety_allowed_area->p2x = mavlink_msg_safety_allowed_area_get_p2x(msg); + safety_allowed_area->p2y = mavlink_msg_safety_allowed_area_get_p2y(msg); + safety_allowed_area->p2z = mavlink_msg_safety_allowed_area_get_p2z(msg); +#else + memcpy(safety_allowed_area, _MAV_PAYLOAD(msg), 25); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_safety_set_allowed_area.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_safety_set_allowed_area.h new file mode 100644 index 0000000000..3c122227a6 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_safety_set_allowed_area.h @@ -0,0 +1,320 @@ +// MESSAGE SAFETY_SET_ALLOWED_AREA PACKING + +#define MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA 53 + +typedef struct __mavlink_safety_set_allowed_area_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t frame; ///< Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + float p1x; ///< x position 1 / Latitude 1 + float p1y; ///< y position 1 / Longitude 1 + float p1z; ///< z position 1 / Altitude 1 + float p2x; ///< x position 2 / Latitude 2 + float p2y; ///< y position 2 / Longitude 2 + float p2z; ///< z position 2 / Altitude 2 +} mavlink_safety_set_allowed_area_t; + +#define MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA_LEN 27 +#define MAVLINK_MSG_ID_53_LEN 27 + + + +#define MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA { \ + "SAFETY_SET_ALLOWED_AREA", \ + 9, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_safety_set_allowed_area_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_safety_set_allowed_area_t, target_component) }, \ + { "frame", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_safety_set_allowed_area_t, frame) }, \ + { "p1x", NULL, MAVLINK_TYPE_FLOAT, 0, 3, offsetof(mavlink_safety_set_allowed_area_t, p1x) }, \ + { "p1y", NULL, MAVLINK_TYPE_FLOAT, 0, 7, offsetof(mavlink_safety_set_allowed_area_t, p1y) }, \ + { "p1z", NULL, MAVLINK_TYPE_FLOAT, 0, 11, offsetof(mavlink_safety_set_allowed_area_t, p1z) }, \ + { "p2x", NULL, MAVLINK_TYPE_FLOAT, 0, 15, offsetof(mavlink_safety_set_allowed_area_t, p2x) }, \ + { "p2y", NULL, MAVLINK_TYPE_FLOAT, 0, 19, offsetof(mavlink_safety_set_allowed_area_t, p2y) }, \ + { "p2z", NULL, MAVLINK_TYPE_FLOAT, 0, 23, offsetof(mavlink_safety_set_allowed_area_t, p2z) }, \ + } \ +} + + +/** + * @brief Pack a safety_set_allowed_area message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param frame Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + * @param p1x x position 1 / Latitude 1 + * @param p1y y position 1 / Longitude 1 + * @param p1z z position 1 / Altitude 1 + * @param p2x x position 2 / Latitude 2 + * @param p2y y position 2 / Longitude 2 + * @param p2z z position 2 / Altitude 2 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_safety_set_allowed_area_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t frame, float p1x, float p1y, float p1z, float p2x, float p2y, float p2z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[27]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, frame); + _mav_put_float(buf, 3, p1x); + _mav_put_float(buf, 7, p1y); + _mav_put_float(buf, 11, p1z); + _mav_put_float(buf, 15, p2x); + _mav_put_float(buf, 19, p2y); + _mav_put_float(buf, 23, p2z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 27); +#else + mavlink_safety_set_allowed_area_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.frame = frame; + packet.p1x = p1x; + packet.p1y = p1y; + packet.p1z = p1z; + packet.p2x = p2x; + packet.p2y = p2y; + packet.p2z = p2z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 27); +#endif + + msg->msgid = MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA; + return mavlink_finalize_message(msg, system_id, component_id, 27); +} + +/** + * @brief Pack a safety_set_allowed_area message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param frame Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + * @param p1x x position 1 / Latitude 1 + * @param p1y y position 1 / Longitude 1 + * @param p1z z position 1 / Altitude 1 + * @param p2x x position 2 / Latitude 2 + * @param p2y y position 2 / Longitude 2 + * @param p2z z position 2 / Altitude 2 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_safety_set_allowed_area_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t frame,float p1x,float p1y,float p1z,float p2x,float p2y,float p2z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[27]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, frame); + _mav_put_float(buf, 3, p1x); + _mav_put_float(buf, 7, p1y); + _mav_put_float(buf, 11, p1z); + _mav_put_float(buf, 15, p2x); + _mav_put_float(buf, 19, p2y); + _mav_put_float(buf, 23, p2z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 27); +#else + mavlink_safety_set_allowed_area_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.frame = frame; + packet.p1x = p1x; + packet.p1y = p1y; + packet.p1z = p1z; + packet.p2x = p2x; + packet.p2y = p2y; + packet.p2z = p2z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 27); +#endif + + msg->msgid = MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 27); +} + +/** + * @brief Encode a safety_set_allowed_area struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param safety_set_allowed_area C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_safety_set_allowed_area_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_safety_set_allowed_area_t* safety_set_allowed_area) +{ + return mavlink_msg_safety_set_allowed_area_pack(system_id, component_id, msg, safety_set_allowed_area->target_system, safety_set_allowed_area->target_component, safety_set_allowed_area->frame, safety_set_allowed_area->p1x, safety_set_allowed_area->p1y, safety_set_allowed_area->p1z, safety_set_allowed_area->p2x, safety_set_allowed_area->p2y, safety_set_allowed_area->p2z); +} + +/** + * @brief Send a safety_set_allowed_area message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param frame Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + * @param p1x x position 1 / Latitude 1 + * @param p1y y position 1 / Longitude 1 + * @param p1z z position 1 / Altitude 1 + * @param p2x x position 2 / Latitude 2 + * @param p2y y position 2 / Longitude 2 + * @param p2z z position 2 / Altitude 2 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_safety_set_allowed_area_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t frame, float p1x, float p1y, float p1z, float p2x, float p2y, float p2z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[27]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, frame); + _mav_put_float(buf, 3, p1x); + _mav_put_float(buf, 7, p1y); + _mav_put_float(buf, 11, p1z); + _mav_put_float(buf, 15, p2x); + _mav_put_float(buf, 19, p2y); + _mav_put_float(buf, 23, p2z); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA, buf, 27); +#else + mavlink_safety_set_allowed_area_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.frame = frame; + packet.p1x = p1x; + packet.p1y = p1y; + packet.p1z = p1z; + packet.p2x = p2x; + packet.p2y = p2y; + packet.p2z = p2z; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA, (const char *)&packet, 27); +#endif +} + +#endif + +// MESSAGE SAFETY_SET_ALLOWED_AREA UNPACKING + + +/** + * @brief Get field target_system from safety_set_allowed_area message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_safety_set_allowed_area_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from safety_set_allowed_area message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_safety_set_allowed_area_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field frame from safety_set_allowed_area message + * + * @return Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + */ +static inline uint8_t mavlink_msg_safety_set_allowed_area_get_frame(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field p1x from safety_set_allowed_area message + * + * @return x position 1 / Latitude 1 + */ +static inline float mavlink_msg_safety_set_allowed_area_get_p1x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 3); +} + +/** + * @brief Get field p1y from safety_set_allowed_area message + * + * @return y position 1 / Longitude 1 + */ +static inline float mavlink_msg_safety_set_allowed_area_get_p1y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 7); +} + +/** + * @brief Get field p1z from safety_set_allowed_area message + * + * @return z position 1 / Altitude 1 + */ +static inline float mavlink_msg_safety_set_allowed_area_get_p1z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 11); +} + +/** + * @brief Get field p2x from safety_set_allowed_area message + * + * @return x position 2 / Latitude 2 + */ +static inline float mavlink_msg_safety_set_allowed_area_get_p2x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 15); +} + +/** + * @brief Get field p2y from safety_set_allowed_area message + * + * @return y position 2 / Longitude 2 + */ +static inline float mavlink_msg_safety_set_allowed_area_get_p2y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 19); +} + +/** + * @brief Get field p2z from safety_set_allowed_area message + * + * @return z position 2 / Altitude 2 + */ +static inline float mavlink_msg_safety_set_allowed_area_get_p2z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 23); +} + +/** + * @brief Decode a safety_set_allowed_area message into a struct + * + * @param msg The message to decode + * @param safety_set_allowed_area C-struct to decode the message contents into + */ +static inline void mavlink_msg_safety_set_allowed_area_decode(const mavlink_message_t* msg, mavlink_safety_set_allowed_area_t* safety_set_allowed_area) +{ +#if MAVLINK_NEED_BYTE_SWAP + safety_set_allowed_area->target_system = mavlink_msg_safety_set_allowed_area_get_target_system(msg); + safety_set_allowed_area->target_component = mavlink_msg_safety_set_allowed_area_get_target_component(msg); + safety_set_allowed_area->frame = mavlink_msg_safety_set_allowed_area_get_frame(msg); + safety_set_allowed_area->p1x = mavlink_msg_safety_set_allowed_area_get_p1x(msg); + safety_set_allowed_area->p1y = mavlink_msg_safety_set_allowed_area_get_p1y(msg); + safety_set_allowed_area->p1z = mavlink_msg_safety_set_allowed_area_get_p1z(msg); + safety_set_allowed_area->p2x = mavlink_msg_safety_set_allowed_area_get_p2x(msg); + safety_set_allowed_area->p2y = mavlink_msg_safety_set_allowed_area_get_p2y(msg); + safety_set_allowed_area->p2z = mavlink_msg_safety_set_allowed_area_get_p2z(msg); +#else + memcpy(safety_set_allowed_area, _MAV_PAYLOAD(msg), 27); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_scaled_imu.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_scaled_imu.h new file mode 100644 index 0000000000..4315dac275 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_scaled_imu.h @@ -0,0 +1,342 @@ +// MESSAGE SCALED_IMU PACKING + +#define MAVLINK_MSG_ID_SCALED_IMU 26 + +typedef struct __mavlink_scaled_imu_t +{ + uint64_t usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + int16_t xacc; ///< X acceleration (mg) + int16_t yacc; ///< Y acceleration (mg) + int16_t zacc; ///< Z acceleration (mg) + int16_t xgyro; ///< Angular speed around X axis (millirad /sec) + int16_t ygyro; ///< Angular speed around Y axis (millirad /sec) + int16_t zgyro; ///< Angular speed around Z axis (millirad /sec) + int16_t xmag; ///< X Magnetic field (milli tesla) + int16_t ymag; ///< Y Magnetic field (milli tesla) + int16_t zmag; ///< Z Magnetic field (milli tesla) +} mavlink_scaled_imu_t; + +#define MAVLINK_MSG_ID_SCALED_IMU_LEN 26 +#define MAVLINK_MSG_ID_26_LEN 26 + + + +#define MAVLINK_MESSAGE_INFO_SCALED_IMU { \ + "SCALED_IMU", \ + 10, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_scaled_imu_t, usec) }, \ + { "xacc", NULL, MAVLINK_TYPE_INT16_T, 0, 8, offsetof(mavlink_scaled_imu_t, xacc) }, \ + { "yacc", NULL, MAVLINK_TYPE_INT16_T, 0, 10, offsetof(mavlink_scaled_imu_t, yacc) }, \ + { "zacc", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_scaled_imu_t, zacc) }, \ + { "xgyro", NULL, MAVLINK_TYPE_INT16_T, 0, 14, offsetof(mavlink_scaled_imu_t, xgyro) }, \ + { "ygyro", NULL, MAVLINK_TYPE_INT16_T, 0, 16, offsetof(mavlink_scaled_imu_t, ygyro) }, \ + { "zgyro", NULL, MAVLINK_TYPE_INT16_T, 0, 18, offsetof(mavlink_scaled_imu_t, zgyro) }, \ + { "xmag", NULL, MAVLINK_TYPE_INT16_T, 0, 20, offsetof(mavlink_scaled_imu_t, xmag) }, \ + { "ymag", NULL, MAVLINK_TYPE_INT16_T, 0, 22, offsetof(mavlink_scaled_imu_t, ymag) }, \ + { "zmag", NULL, MAVLINK_TYPE_INT16_T, 0, 24, offsetof(mavlink_scaled_imu_t, zmag) }, \ + } \ +} + + +/** + * @brief Pack a scaled_imu message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param xacc X acceleration (mg) + * @param yacc Y acceleration (mg) + * @param zacc Z acceleration (mg) + * @param xgyro Angular speed around X axis (millirad /sec) + * @param ygyro Angular speed around Y axis (millirad /sec) + * @param zgyro Angular speed around Z axis (millirad /sec) + * @param xmag X Magnetic field (milli tesla) + * @param ymag Y Magnetic field (milli tesla) + * @param zmag Z Magnetic field (milli tesla) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_scaled_imu_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, int16_t xacc, int16_t yacc, int16_t zacc, int16_t xgyro, int16_t ygyro, int16_t zgyro, int16_t xmag, int16_t ymag, int16_t zmag) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_int16_t(buf, 8, xacc); + _mav_put_int16_t(buf, 10, yacc); + _mav_put_int16_t(buf, 12, zacc); + _mav_put_int16_t(buf, 14, xgyro); + _mav_put_int16_t(buf, 16, ygyro); + _mav_put_int16_t(buf, 18, zgyro); + _mav_put_int16_t(buf, 20, xmag); + _mav_put_int16_t(buf, 22, ymag); + _mav_put_int16_t(buf, 24, zmag); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_scaled_imu_t packet; + packet.usec = usec; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + packet.xmag = xmag; + packet.ymag = ymag; + packet.zmag = zmag; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_SCALED_IMU; + return mavlink_finalize_message(msg, system_id, component_id, 26); +} + +/** + * @brief Pack a scaled_imu message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param xacc X acceleration (mg) + * @param yacc Y acceleration (mg) + * @param zacc Z acceleration (mg) + * @param xgyro Angular speed around X axis (millirad /sec) + * @param ygyro Angular speed around Y axis (millirad /sec) + * @param zgyro Angular speed around Z axis (millirad /sec) + * @param xmag X Magnetic field (milli tesla) + * @param ymag Y Magnetic field (milli tesla) + * @param zmag Z Magnetic field (milli tesla) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_scaled_imu_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,int16_t xacc,int16_t yacc,int16_t zacc,int16_t xgyro,int16_t ygyro,int16_t zgyro,int16_t xmag,int16_t ymag,int16_t zmag) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_int16_t(buf, 8, xacc); + _mav_put_int16_t(buf, 10, yacc); + _mav_put_int16_t(buf, 12, zacc); + _mav_put_int16_t(buf, 14, xgyro); + _mav_put_int16_t(buf, 16, ygyro); + _mav_put_int16_t(buf, 18, zgyro); + _mav_put_int16_t(buf, 20, xmag); + _mav_put_int16_t(buf, 22, ymag); + _mav_put_int16_t(buf, 24, zmag); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_scaled_imu_t packet; + packet.usec = usec; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + packet.xmag = xmag; + packet.ymag = ymag; + packet.zmag = zmag; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_SCALED_IMU; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 26); +} + +/** + * @brief Encode a scaled_imu struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param scaled_imu C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_scaled_imu_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_scaled_imu_t* scaled_imu) +{ + return mavlink_msg_scaled_imu_pack(system_id, component_id, msg, scaled_imu->usec, scaled_imu->xacc, scaled_imu->yacc, scaled_imu->zacc, scaled_imu->xgyro, scaled_imu->ygyro, scaled_imu->zgyro, scaled_imu->xmag, scaled_imu->ymag, scaled_imu->zmag); +} + +/** + * @brief Send a scaled_imu message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param xacc X acceleration (mg) + * @param yacc Y acceleration (mg) + * @param zacc Z acceleration (mg) + * @param xgyro Angular speed around X axis (millirad /sec) + * @param ygyro Angular speed around Y axis (millirad /sec) + * @param zgyro Angular speed around Z axis (millirad /sec) + * @param xmag X Magnetic field (milli tesla) + * @param ymag Y Magnetic field (milli tesla) + * @param zmag Z Magnetic field (milli tesla) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_scaled_imu_send(mavlink_channel_t chan, uint64_t usec, int16_t xacc, int16_t yacc, int16_t zacc, int16_t xgyro, int16_t ygyro, int16_t zgyro, int16_t xmag, int16_t ymag, int16_t zmag) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_int16_t(buf, 8, xacc); + _mav_put_int16_t(buf, 10, yacc); + _mav_put_int16_t(buf, 12, zacc); + _mav_put_int16_t(buf, 14, xgyro); + _mav_put_int16_t(buf, 16, ygyro); + _mav_put_int16_t(buf, 18, zgyro); + _mav_put_int16_t(buf, 20, xmag); + _mav_put_int16_t(buf, 22, ymag); + _mav_put_int16_t(buf, 24, zmag); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SCALED_IMU, buf, 26); +#else + mavlink_scaled_imu_t packet; + packet.usec = usec; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + packet.xmag = xmag; + packet.ymag = ymag; + packet.zmag = zmag; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SCALED_IMU, (const char *)&packet, 26); +#endif +} + +#endif + +// MESSAGE SCALED_IMU UNPACKING + + +/** + * @brief Get field usec from scaled_imu message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_scaled_imu_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field xacc from scaled_imu message + * + * @return X acceleration (mg) + */ +static inline int16_t mavlink_msg_scaled_imu_get_xacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 8); +} + +/** + * @brief Get field yacc from scaled_imu message + * + * @return Y acceleration (mg) + */ +static inline int16_t mavlink_msg_scaled_imu_get_yacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 10); +} + +/** + * @brief Get field zacc from scaled_imu message + * + * @return Z acceleration (mg) + */ +static inline int16_t mavlink_msg_scaled_imu_get_zacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Get field xgyro from scaled_imu message + * + * @return Angular speed around X axis (millirad /sec) + */ +static inline int16_t mavlink_msg_scaled_imu_get_xgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 14); +} + +/** + * @brief Get field ygyro from scaled_imu message + * + * @return Angular speed around Y axis (millirad /sec) + */ +static inline int16_t mavlink_msg_scaled_imu_get_ygyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 16); +} + +/** + * @brief Get field zgyro from scaled_imu message + * + * @return Angular speed around Z axis (millirad /sec) + */ +static inline int16_t mavlink_msg_scaled_imu_get_zgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 18); +} + +/** + * @brief Get field xmag from scaled_imu message + * + * @return X Magnetic field (milli tesla) + */ +static inline int16_t mavlink_msg_scaled_imu_get_xmag(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 20); +} + +/** + * @brief Get field ymag from scaled_imu message + * + * @return Y Magnetic field (milli tesla) + */ +static inline int16_t mavlink_msg_scaled_imu_get_ymag(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 22); +} + +/** + * @brief Get field zmag from scaled_imu message + * + * @return Z Magnetic field (milli tesla) + */ +static inline int16_t mavlink_msg_scaled_imu_get_zmag(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 24); +} + +/** + * @brief Decode a scaled_imu message into a struct + * + * @param msg The message to decode + * @param scaled_imu C-struct to decode the message contents into + */ +static inline void mavlink_msg_scaled_imu_decode(const mavlink_message_t* msg, mavlink_scaled_imu_t* scaled_imu) +{ +#if MAVLINK_NEED_BYTE_SWAP + scaled_imu->usec = mavlink_msg_scaled_imu_get_usec(msg); + scaled_imu->xacc = mavlink_msg_scaled_imu_get_xacc(msg); + scaled_imu->yacc = mavlink_msg_scaled_imu_get_yacc(msg); + scaled_imu->zacc = mavlink_msg_scaled_imu_get_zacc(msg); + scaled_imu->xgyro = mavlink_msg_scaled_imu_get_xgyro(msg); + scaled_imu->ygyro = mavlink_msg_scaled_imu_get_ygyro(msg); + scaled_imu->zgyro = mavlink_msg_scaled_imu_get_zgyro(msg); + scaled_imu->xmag = mavlink_msg_scaled_imu_get_xmag(msg); + scaled_imu->ymag = mavlink_msg_scaled_imu_get_ymag(msg); + scaled_imu->zmag = mavlink_msg_scaled_imu_get_zmag(msg); +#else + memcpy(scaled_imu, _MAV_PAYLOAD(msg), 26); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_scaled_pressure.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_scaled_pressure.h new file mode 100644 index 0000000000..579f7f4ee3 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_scaled_pressure.h @@ -0,0 +1,210 @@ +// MESSAGE SCALED_PRESSURE PACKING + +#define MAVLINK_MSG_ID_SCALED_PRESSURE 38 + +typedef struct __mavlink_scaled_pressure_t +{ + uint64_t usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + float press_abs; ///< Absolute pressure (hectopascal) + float press_diff; ///< Differential pressure 1 (hectopascal) + int16_t temperature; ///< Temperature measurement (0.01 degrees celsius) +} mavlink_scaled_pressure_t; + +#define MAVLINK_MSG_ID_SCALED_PRESSURE_LEN 18 +#define MAVLINK_MSG_ID_38_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_SCALED_PRESSURE { \ + "SCALED_PRESSURE", \ + 4, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_scaled_pressure_t, usec) }, \ + { "press_abs", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_scaled_pressure_t, press_abs) }, \ + { "press_diff", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_scaled_pressure_t, press_diff) }, \ + { "temperature", NULL, MAVLINK_TYPE_INT16_T, 0, 16, offsetof(mavlink_scaled_pressure_t, temperature) }, \ + } \ +} + + +/** + * @brief Pack a scaled_pressure message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param press_abs Absolute pressure (hectopascal) + * @param press_diff Differential pressure 1 (hectopascal) + * @param temperature Temperature measurement (0.01 degrees celsius) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_scaled_pressure_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, float press_abs, float press_diff, int16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, press_abs); + _mav_put_float(buf, 12, press_diff); + _mav_put_int16_t(buf, 16, temperature); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_scaled_pressure_t packet; + packet.usec = usec; + packet.press_abs = press_abs; + packet.press_diff = press_diff; + packet.temperature = temperature; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_SCALED_PRESSURE; + return mavlink_finalize_message(msg, system_id, component_id, 18); +} + +/** + * @brief Pack a scaled_pressure message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param press_abs Absolute pressure (hectopascal) + * @param press_diff Differential pressure 1 (hectopascal) + * @param temperature Temperature measurement (0.01 degrees celsius) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_scaled_pressure_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float press_abs,float press_diff,int16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, press_abs); + _mav_put_float(buf, 12, press_diff); + _mav_put_int16_t(buf, 16, temperature); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_scaled_pressure_t packet; + packet.usec = usec; + packet.press_abs = press_abs; + packet.press_diff = press_diff; + packet.temperature = temperature; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_SCALED_PRESSURE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18); +} + +/** + * @brief Encode a scaled_pressure struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param scaled_pressure C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_scaled_pressure_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_scaled_pressure_t* scaled_pressure) +{ + return mavlink_msg_scaled_pressure_pack(system_id, component_id, msg, scaled_pressure->usec, scaled_pressure->press_abs, scaled_pressure->press_diff, scaled_pressure->temperature); +} + +/** + * @brief Send a scaled_pressure message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param press_abs Absolute pressure (hectopascal) + * @param press_diff Differential pressure 1 (hectopascal) + * @param temperature Temperature measurement (0.01 degrees celsius) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_scaled_pressure_send(mavlink_channel_t chan, uint64_t usec, float press_abs, float press_diff, int16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, press_abs); + _mav_put_float(buf, 12, press_diff); + _mav_put_int16_t(buf, 16, temperature); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SCALED_PRESSURE, buf, 18); +#else + mavlink_scaled_pressure_t packet; + packet.usec = usec; + packet.press_abs = press_abs; + packet.press_diff = press_diff; + packet.temperature = temperature; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SCALED_PRESSURE, (const char *)&packet, 18); +#endif +} + +#endif + +// MESSAGE SCALED_PRESSURE UNPACKING + + +/** + * @brief Get field usec from scaled_pressure message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_scaled_pressure_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field press_abs from scaled_pressure message + * + * @return Absolute pressure (hectopascal) + */ +static inline float mavlink_msg_scaled_pressure_get_press_abs(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field press_diff from scaled_pressure message + * + * @return Differential pressure 1 (hectopascal) + */ +static inline float mavlink_msg_scaled_pressure_get_press_diff(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field temperature from scaled_pressure message + * + * @return Temperature measurement (0.01 degrees celsius) + */ +static inline int16_t mavlink_msg_scaled_pressure_get_temperature(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 16); +} + +/** + * @brief Decode a scaled_pressure message into a struct + * + * @param msg The message to decode + * @param scaled_pressure C-struct to decode the message contents into + */ +static inline void mavlink_msg_scaled_pressure_decode(const mavlink_message_t* msg, mavlink_scaled_pressure_t* scaled_pressure) +{ +#if MAVLINK_NEED_BYTE_SWAP + scaled_pressure->usec = mavlink_msg_scaled_pressure_get_usec(msg); + scaled_pressure->press_abs = mavlink_msg_scaled_pressure_get_press_abs(msg); + scaled_pressure->press_diff = mavlink_msg_scaled_pressure_get_press_diff(msg); + scaled_pressure->temperature = mavlink_msg_scaled_pressure_get_temperature(msg); +#else + memcpy(scaled_pressure, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_servo_output_raw.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_servo_output_raw.h new file mode 100644 index 0000000000..b5be3318cc --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_servo_output_raw.h @@ -0,0 +1,298 @@ +// MESSAGE SERVO_OUTPUT_RAW PACKING + +#define MAVLINK_MSG_ID_SERVO_OUTPUT_RAW 37 + +typedef struct __mavlink_servo_output_raw_t +{ + uint16_t servo1_raw; ///< Servo output 1 value, in microseconds + uint16_t servo2_raw; ///< Servo output 2 value, in microseconds + uint16_t servo3_raw; ///< Servo output 3 value, in microseconds + uint16_t servo4_raw; ///< Servo output 4 value, in microseconds + uint16_t servo5_raw; ///< Servo output 5 value, in microseconds + uint16_t servo6_raw; ///< Servo output 6 value, in microseconds + uint16_t servo7_raw; ///< Servo output 7 value, in microseconds + uint16_t servo8_raw; ///< Servo output 8 value, in microseconds +} mavlink_servo_output_raw_t; + +#define MAVLINK_MSG_ID_SERVO_OUTPUT_RAW_LEN 16 +#define MAVLINK_MSG_ID_37_LEN 16 + + + +#define MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW { \ + "SERVO_OUTPUT_RAW", \ + 8, \ + { { "servo1_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_servo_output_raw_t, servo1_raw) }, \ + { "servo2_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_servo_output_raw_t, servo2_raw) }, \ + { "servo3_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_servo_output_raw_t, servo3_raw) }, \ + { "servo4_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_servo_output_raw_t, servo4_raw) }, \ + { "servo5_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 8, offsetof(mavlink_servo_output_raw_t, servo5_raw) }, \ + { "servo6_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 10, offsetof(mavlink_servo_output_raw_t, servo6_raw) }, \ + { "servo7_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 12, offsetof(mavlink_servo_output_raw_t, servo7_raw) }, \ + { "servo8_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 14, offsetof(mavlink_servo_output_raw_t, servo8_raw) }, \ + } \ +} + + +/** + * @brief Pack a servo_output_raw message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param servo1_raw Servo output 1 value, in microseconds + * @param servo2_raw Servo output 2 value, in microseconds + * @param servo3_raw Servo output 3 value, in microseconds + * @param servo4_raw Servo output 4 value, in microseconds + * @param servo5_raw Servo output 5 value, in microseconds + * @param servo6_raw Servo output 6 value, in microseconds + * @param servo7_raw Servo output 7 value, in microseconds + * @param servo8_raw Servo output 8 value, in microseconds + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_servo_output_raw_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t servo1_raw, uint16_t servo2_raw, uint16_t servo3_raw, uint16_t servo4_raw, uint16_t servo5_raw, uint16_t servo6_raw, uint16_t servo7_raw, uint16_t servo8_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_uint16_t(buf, 0, servo1_raw); + _mav_put_uint16_t(buf, 2, servo2_raw); + _mav_put_uint16_t(buf, 4, servo3_raw); + _mav_put_uint16_t(buf, 6, servo4_raw); + _mav_put_uint16_t(buf, 8, servo5_raw); + _mav_put_uint16_t(buf, 10, servo6_raw); + _mav_put_uint16_t(buf, 12, servo7_raw); + _mav_put_uint16_t(buf, 14, servo8_raw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_servo_output_raw_t packet; + packet.servo1_raw = servo1_raw; + packet.servo2_raw = servo2_raw; + packet.servo3_raw = servo3_raw; + packet.servo4_raw = servo4_raw; + packet.servo5_raw = servo5_raw; + packet.servo6_raw = servo6_raw; + packet.servo7_raw = servo7_raw; + packet.servo8_raw = servo8_raw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_SERVO_OUTPUT_RAW; + return mavlink_finalize_message(msg, system_id, component_id, 16); +} + +/** + * @brief Pack a servo_output_raw message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param servo1_raw Servo output 1 value, in microseconds + * @param servo2_raw Servo output 2 value, in microseconds + * @param servo3_raw Servo output 3 value, in microseconds + * @param servo4_raw Servo output 4 value, in microseconds + * @param servo5_raw Servo output 5 value, in microseconds + * @param servo6_raw Servo output 6 value, in microseconds + * @param servo7_raw Servo output 7 value, in microseconds + * @param servo8_raw Servo output 8 value, in microseconds + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_servo_output_raw_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t servo1_raw,uint16_t servo2_raw,uint16_t servo3_raw,uint16_t servo4_raw,uint16_t servo5_raw,uint16_t servo6_raw,uint16_t servo7_raw,uint16_t servo8_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_uint16_t(buf, 0, servo1_raw); + _mav_put_uint16_t(buf, 2, servo2_raw); + _mav_put_uint16_t(buf, 4, servo3_raw); + _mav_put_uint16_t(buf, 6, servo4_raw); + _mav_put_uint16_t(buf, 8, servo5_raw); + _mav_put_uint16_t(buf, 10, servo6_raw); + _mav_put_uint16_t(buf, 12, servo7_raw); + _mav_put_uint16_t(buf, 14, servo8_raw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_servo_output_raw_t packet; + packet.servo1_raw = servo1_raw; + packet.servo2_raw = servo2_raw; + packet.servo3_raw = servo3_raw; + packet.servo4_raw = servo4_raw; + packet.servo5_raw = servo5_raw; + packet.servo6_raw = servo6_raw; + packet.servo7_raw = servo7_raw; + packet.servo8_raw = servo8_raw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_SERVO_OUTPUT_RAW; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 16); +} + +/** + * @brief Encode a servo_output_raw struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param servo_output_raw C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_servo_output_raw_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_servo_output_raw_t* servo_output_raw) +{ + return mavlink_msg_servo_output_raw_pack(system_id, component_id, msg, servo_output_raw->servo1_raw, servo_output_raw->servo2_raw, servo_output_raw->servo3_raw, servo_output_raw->servo4_raw, servo_output_raw->servo5_raw, servo_output_raw->servo6_raw, servo_output_raw->servo7_raw, servo_output_raw->servo8_raw); +} + +/** + * @brief Send a servo_output_raw message + * @param chan MAVLink channel to send the message + * + * @param servo1_raw Servo output 1 value, in microseconds + * @param servo2_raw Servo output 2 value, in microseconds + * @param servo3_raw Servo output 3 value, in microseconds + * @param servo4_raw Servo output 4 value, in microseconds + * @param servo5_raw Servo output 5 value, in microseconds + * @param servo6_raw Servo output 6 value, in microseconds + * @param servo7_raw Servo output 7 value, in microseconds + * @param servo8_raw Servo output 8 value, in microseconds + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_servo_output_raw_send(mavlink_channel_t chan, uint16_t servo1_raw, uint16_t servo2_raw, uint16_t servo3_raw, uint16_t servo4_raw, uint16_t servo5_raw, uint16_t servo6_raw, uint16_t servo7_raw, uint16_t servo8_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_uint16_t(buf, 0, servo1_raw); + _mav_put_uint16_t(buf, 2, servo2_raw); + _mav_put_uint16_t(buf, 4, servo3_raw); + _mav_put_uint16_t(buf, 6, servo4_raw); + _mav_put_uint16_t(buf, 8, servo5_raw); + _mav_put_uint16_t(buf, 10, servo6_raw); + _mav_put_uint16_t(buf, 12, servo7_raw); + _mav_put_uint16_t(buf, 14, servo8_raw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SERVO_OUTPUT_RAW, buf, 16); +#else + mavlink_servo_output_raw_t packet; + packet.servo1_raw = servo1_raw; + packet.servo2_raw = servo2_raw; + packet.servo3_raw = servo3_raw; + packet.servo4_raw = servo4_raw; + packet.servo5_raw = servo5_raw; + packet.servo6_raw = servo6_raw; + packet.servo7_raw = servo7_raw; + packet.servo8_raw = servo8_raw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SERVO_OUTPUT_RAW, (const char *)&packet, 16); +#endif +} + +#endif + +// MESSAGE SERVO_OUTPUT_RAW UNPACKING + + +/** + * @brief Get field servo1_raw from servo_output_raw message + * + * @return Servo output 1 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo1_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field servo2_raw from servo_output_raw message + * + * @return Servo output 2 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo2_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Get field servo3_raw from servo_output_raw message + * + * @return Servo output 3 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo3_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field servo4_raw from servo_output_raw message + * + * @return Servo output 4 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo4_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field servo5_raw from servo_output_raw message + * + * @return Servo output 5 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo5_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Get field servo6_raw from servo_output_raw message + * + * @return Servo output 6 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo6_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 10); +} + +/** + * @brief Get field servo7_raw from servo_output_raw message + * + * @return Servo output 7 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo7_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 12); +} + +/** + * @brief Get field servo8_raw from servo_output_raw message + * + * @return Servo output 8 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo8_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 14); +} + +/** + * @brief Decode a servo_output_raw message into a struct + * + * @param msg The message to decode + * @param servo_output_raw C-struct to decode the message contents into + */ +static inline void mavlink_msg_servo_output_raw_decode(const mavlink_message_t* msg, mavlink_servo_output_raw_t* servo_output_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP + servo_output_raw->servo1_raw = mavlink_msg_servo_output_raw_get_servo1_raw(msg); + servo_output_raw->servo2_raw = mavlink_msg_servo_output_raw_get_servo2_raw(msg); + servo_output_raw->servo3_raw = mavlink_msg_servo_output_raw_get_servo3_raw(msg); + servo_output_raw->servo4_raw = mavlink_msg_servo_output_raw_get_servo4_raw(msg); + servo_output_raw->servo5_raw = mavlink_msg_servo_output_raw_get_servo5_raw(msg); + servo_output_raw->servo6_raw = mavlink_msg_servo_output_raw_get_servo6_raw(msg); + servo_output_raw->servo7_raw = mavlink_msg_servo_output_raw_get_servo7_raw(msg); + servo_output_raw->servo8_raw = mavlink_msg_servo_output_raw_get_servo8_raw(msg); +#else + memcpy(servo_output_raw, _MAV_PAYLOAD(msg), 16); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_altitude.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_altitude.h new file mode 100644 index 0000000000..72cc5e7b0c --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_altitude.h @@ -0,0 +1,166 @@ +// MESSAGE SET_ALTITUDE PACKING + +#define MAVLINK_MSG_ID_SET_ALTITUDE 65 + +typedef struct __mavlink_set_altitude_t +{ + uint8_t target; ///< The system setting the altitude + uint32_t mode; ///< The new altitude in meters +} mavlink_set_altitude_t; + +#define MAVLINK_MSG_ID_SET_ALTITUDE_LEN 5 +#define MAVLINK_MSG_ID_65_LEN 5 + + + +#define MAVLINK_MESSAGE_INFO_SET_ALTITUDE { \ + "SET_ALTITUDE", \ + 2, \ + { { "target", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_set_altitude_t, target) }, \ + { "mode", NULL, MAVLINK_TYPE_UINT32_T, 0, 1, offsetof(mavlink_set_altitude_t, mode) }, \ + } \ +} + + +/** + * @brief Pack a set_altitude message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target The system setting the altitude + * @param mode The new altitude in meters + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_altitude_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target, uint32_t mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[5]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint32_t(buf, 1, mode); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 5); +#else + mavlink_set_altitude_t packet; + packet.target = target; + packet.mode = mode; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 5); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_ALTITUDE; + return mavlink_finalize_message(msg, system_id, component_id, 5); +} + +/** + * @brief Pack a set_altitude message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system setting the altitude + * @param mode The new altitude in meters + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_altitude_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,uint32_t mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[5]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint32_t(buf, 1, mode); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 5); +#else + mavlink_set_altitude_t packet; + packet.target = target; + packet.mode = mode; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 5); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_ALTITUDE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 5); +} + +/** + * @brief Encode a set_altitude struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_altitude C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_altitude_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_altitude_t* set_altitude) +{ + return mavlink_msg_set_altitude_pack(system_id, component_id, msg, set_altitude->target, set_altitude->mode); +} + +/** + * @brief Send a set_altitude message + * @param chan MAVLink channel to send the message + * + * @param target The system setting the altitude + * @param mode The new altitude in meters + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_altitude_send(mavlink_channel_t chan, uint8_t target, uint32_t mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[5]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint32_t(buf, 1, mode); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_ALTITUDE, buf, 5); +#else + mavlink_set_altitude_t packet; + packet.target = target; + packet.mode = mode; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_ALTITUDE, (const char *)&packet, 5); +#endif +} + +#endif + +// MESSAGE SET_ALTITUDE UNPACKING + + +/** + * @brief Get field target from set_altitude message + * + * @return The system setting the altitude + */ +static inline uint8_t mavlink_msg_set_altitude_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field mode from set_altitude message + * + * @return The new altitude in meters + */ +static inline uint32_t mavlink_msg_set_altitude_get_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 1); +} + +/** + * @brief Decode a set_altitude message into a struct + * + * @param msg The message to decode + * @param set_altitude C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_altitude_decode(const mavlink_message_t* msg, mavlink_set_altitude_t* set_altitude) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_altitude->target = mavlink_msg_set_altitude_get_target(msg); + set_altitude->mode = mavlink_msg_set_altitude_get_mode(msg); +#else + memcpy(set_altitude, _MAV_PAYLOAD(msg), 5); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_mode.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_mode.h new file mode 100644 index 0000000000..8a3f20593d --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_mode.h @@ -0,0 +1,166 @@ +// MESSAGE SET_MODE PACKING + +#define MAVLINK_MSG_ID_SET_MODE 11 + +typedef struct __mavlink_set_mode_t +{ + uint8_t target; ///< The system setting the mode + uint8_t mode; ///< The new mode +} mavlink_set_mode_t; + +#define MAVLINK_MSG_ID_SET_MODE_LEN 2 +#define MAVLINK_MSG_ID_11_LEN 2 + + + +#define MAVLINK_MESSAGE_INFO_SET_MODE { \ + "SET_MODE", \ + 2, \ + { { "target", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_set_mode_t, target) }, \ + { "mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_set_mode_t, mode) }, \ + } \ +} + + +/** + * @brief Pack a set_mode message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target The system setting the mode + * @param mode The new mode + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_mode_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target, uint8_t mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint8_t(buf, 1, mode); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_set_mode_t packet; + packet.target = target; + packet.mode = mode; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_MODE; + return mavlink_finalize_message(msg, system_id, component_id, 2); +} + +/** + * @brief Pack a set_mode message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system setting the mode + * @param mode The new mode + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_mode_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,uint8_t mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint8_t(buf, 1, mode); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_set_mode_t packet; + packet.target = target; + packet.mode = mode; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_MODE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 2); +} + +/** + * @brief Encode a set_mode struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_mode C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_mode_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_mode_t* set_mode) +{ + return mavlink_msg_set_mode_pack(system_id, component_id, msg, set_mode->target, set_mode->mode); +} + +/** + * @brief Send a set_mode message + * @param chan MAVLink channel to send the message + * + * @param target The system setting the mode + * @param mode The new mode + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_mode_send(mavlink_channel_t chan, uint8_t target, uint8_t mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint8_t(buf, 1, mode); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_MODE, buf, 2); +#else + mavlink_set_mode_t packet; + packet.target = target; + packet.mode = mode; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_MODE, (const char *)&packet, 2); +#endif +} + +#endif + +// MESSAGE SET_MODE UNPACKING + + +/** + * @brief Get field target from set_mode message + * + * @return The system setting the mode + */ +static inline uint8_t mavlink_msg_set_mode_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field mode from set_mode message + * + * @return The new mode + */ +static inline uint8_t mavlink_msg_set_mode_get_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Decode a set_mode message into a struct + * + * @param msg The message to decode + * @param set_mode C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_mode_decode(const mavlink_message_t* msg, mavlink_set_mode_t* set_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_mode->target = mavlink_msg_set_mode_get_target(msg); + set_mode->mode = mavlink_msg_set_mode_get_mode(msg); +#else + memcpy(set_mode, _MAV_PAYLOAD(msg), 2); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_nav_mode.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_nav_mode.h new file mode 100644 index 0000000000..02efa26b19 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_nav_mode.h @@ -0,0 +1,166 @@ +// MESSAGE SET_NAV_MODE PACKING + +#define MAVLINK_MSG_ID_SET_NAV_MODE 12 + +typedef struct __mavlink_set_nav_mode_t +{ + uint8_t target; ///< The system setting the mode + uint8_t nav_mode; ///< The new navigation mode +} mavlink_set_nav_mode_t; + +#define MAVLINK_MSG_ID_SET_NAV_MODE_LEN 2 +#define MAVLINK_MSG_ID_12_LEN 2 + + + +#define MAVLINK_MESSAGE_INFO_SET_NAV_MODE { \ + "SET_NAV_MODE", \ + 2, \ + { { "target", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_set_nav_mode_t, target) }, \ + { "nav_mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_set_nav_mode_t, nav_mode) }, \ + } \ +} + + +/** + * @brief Pack a set_nav_mode message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target The system setting the mode + * @param nav_mode The new navigation mode + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_nav_mode_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target, uint8_t nav_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint8_t(buf, 1, nav_mode); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_set_nav_mode_t packet; + packet.target = target; + packet.nav_mode = nav_mode; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_NAV_MODE; + return mavlink_finalize_message(msg, system_id, component_id, 2); +} + +/** + * @brief Pack a set_nav_mode message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system setting the mode + * @param nav_mode The new navigation mode + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_nav_mode_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,uint8_t nav_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint8_t(buf, 1, nav_mode); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_set_nav_mode_t packet; + packet.target = target; + packet.nav_mode = nav_mode; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_NAV_MODE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 2); +} + +/** + * @brief Encode a set_nav_mode struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_nav_mode C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_nav_mode_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_nav_mode_t* set_nav_mode) +{ + return mavlink_msg_set_nav_mode_pack(system_id, component_id, msg, set_nav_mode->target, set_nav_mode->nav_mode); +} + +/** + * @brief Send a set_nav_mode message + * @param chan MAVLink channel to send the message + * + * @param target The system setting the mode + * @param nav_mode The new navigation mode + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_nav_mode_send(mavlink_channel_t chan, uint8_t target, uint8_t nav_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint8_t(buf, 1, nav_mode); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_NAV_MODE, buf, 2); +#else + mavlink_set_nav_mode_t packet; + packet.target = target; + packet.nav_mode = nav_mode; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_NAV_MODE, (const char *)&packet, 2); +#endif +} + +#endif + +// MESSAGE SET_NAV_MODE UNPACKING + + +/** + * @brief Get field target from set_nav_mode message + * + * @return The system setting the mode + */ +static inline uint8_t mavlink_msg_set_nav_mode_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field nav_mode from set_nav_mode message + * + * @return The new navigation mode + */ +static inline uint8_t mavlink_msg_set_nav_mode_get_nav_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Decode a set_nav_mode message into a struct + * + * @param msg The message to decode + * @param set_nav_mode C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_nav_mode_decode(const mavlink_message_t* msg, mavlink_set_nav_mode_t* set_nav_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_nav_mode->target = mavlink_msg_set_nav_mode_get_target(msg); + set_nav_mode->nav_mode = mavlink_msg_set_nav_mode_get_nav_mode(msg); +#else + memcpy(set_nav_mode, _MAV_PAYLOAD(msg), 2); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_roll_pitch_yaw_speed_thrust.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_roll_pitch_yaw_speed_thrust.h new file mode 100644 index 0000000000..6a9c01215b --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_roll_pitch_yaw_speed_thrust.h @@ -0,0 +1,254 @@ +// MESSAGE SET_ROLL_PITCH_YAW_SPEED_THRUST PACKING + +#define MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST 56 + +typedef struct __mavlink_set_roll_pitch_yaw_speed_thrust_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + float roll_speed; ///< Desired roll angular speed in rad/s + float pitch_speed; ///< Desired pitch angular speed in rad/s + float yaw_speed; ///< Desired yaw angular speed in rad/s + float thrust; ///< Collective thrust, normalized to 0 .. 1 +} mavlink_set_roll_pitch_yaw_speed_thrust_t; + +#define MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST_LEN 18 +#define MAVLINK_MSG_ID_56_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST { \ + "SET_ROLL_PITCH_YAW_SPEED_THRUST", \ + 6, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_set_roll_pitch_yaw_speed_thrust_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_set_roll_pitch_yaw_speed_thrust_t, target_component) }, \ + { "roll_speed", NULL, MAVLINK_TYPE_FLOAT, 0, 2, offsetof(mavlink_set_roll_pitch_yaw_speed_thrust_t, roll_speed) }, \ + { "pitch_speed", NULL, MAVLINK_TYPE_FLOAT, 0, 6, offsetof(mavlink_set_roll_pitch_yaw_speed_thrust_t, pitch_speed) }, \ + { "yaw_speed", NULL, MAVLINK_TYPE_FLOAT, 0, 10, offsetof(mavlink_set_roll_pitch_yaw_speed_thrust_t, yaw_speed) }, \ + { "thrust", NULL, MAVLINK_TYPE_FLOAT, 0, 14, offsetof(mavlink_set_roll_pitch_yaw_speed_thrust_t, thrust) }, \ + } \ +} + + +/** + * @brief Pack a set_roll_pitch_yaw_speed_thrust message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param roll_speed Desired roll angular speed in rad/s + * @param pitch_speed Desired pitch angular speed in rad/s + * @param yaw_speed Desired yaw angular speed in rad/s + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_roll_pitch_yaw_speed_thrust_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, float roll_speed, float pitch_speed, float yaw_speed, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 2, roll_speed); + _mav_put_float(buf, 6, pitch_speed); + _mav_put_float(buf, 10, yaw_speed); + _mav_put_float(buf, 14, thrust); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_set_roll_pitch_yaw_speed_thrust_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.roll_speed = roll_speed; + packet.pitch_speed = pitch_speed; + packet.yaw_speed = yaw_speed; + packet.thrust = thrust; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST; + return mavlink_finalize_message(msg, system_id, component_id, 18); +} + +/** + * @brief Pack a set_roll_pitch_yaw_speed_thrust message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param roll_speed Desired roll angular speed in rad/s + * @param pitch_speed Desired pitch angular speed in rad/s + * @param yaw_speed Desired yaw angular speed in rad/s + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_roll_pitch_yaw_speed_thrust_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,float roll_speed,float pitch_speed,float yaw_speed,float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 2, roll_speed); + _mav_put_float(buf, 6, pitch_speed); + _mav_put_float(buf, 10, yaw_speed); + _mav_put_float(buf, 14, thrust); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_set_roll_pitch_yaw_speed_thrust_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.roll_speed = roll_speed; + packet.pitch_speed = pitch_speed; + packet.yaw_speed = yaw_speed; + packet.thrust = thrust; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18); +} + +/** + * @brief Encode a set_roll_pitch_yaw_speed_thrust struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_roll_pitch_yaw_speed_thrust C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_roll_pitch_yaw_speed_thrust_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_roll_pitch_yaw_speed_thrust_t* set_roll_pitch_yaw_speed_thrust) +{ + return mavlink_msg_set_roll_pitch_yaw_speed_thrust_pack(system_id, component_id, msg, set_roll_pitch_yaw_speed_thrust->target_system, set_roll_pitch_yaw_speed_thrust->target_component, set_roll_pitch_yaw_speed_thrust->roll_speed, set_roll_pitch_yaw_speed_thrust->pitch_speed, set_roll_pitch_yaw_speed_thrust->yaw_speed, set_roll_pitch_yaw_speed_thrust->thrust); +} + +/** + * @brief Send a set_roll_pitch_yaw_speed_thrust message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param roll_speed Desired roll angular speed in rad/s + * @param pitch_speed Desired pitch angular speed in rad/s + * @param yaw_speed Desired yaw angular speed in rad/s + * @param thrust Collective thrust, normalized to 0 .. 1 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_roll_pitch_yaw_speed_thrust_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, float roll_speed, float pitch_speed, float yaw_speed, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 2, roll_speed); + _mav_put_float(buf, 6, pitch_speed); + _mav_put_float(buf, 10, yaw_speed); + _mav_put_float(buf, 14, thrust); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST, buf, 18); +#else + mavlink_set_roll_pitch_yaw_speed_thrust_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.roll_speed = roll_speed; + packet.pitch_speed = pitch_speed; + packet.yaw_speed = yaw_speed; + packet.thrust = thrust; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST, (const char *)&packet, 18); +#endif +} + +#endif + +// MESSAGE SET_ROLL_PITCH_YAW_SPEED_THRUST UNPACKING + + +/** + * @brief Get field target_system from set_roll_pitch_yaw_speed_thrust message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from set_roll_pitch_yaw_speed_thrust message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field roll_speed from set_roll_pitch_yaw_speed_thrust message + * + * @return Desired roll angular speed in rad/s + */ +static inline float mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_roll_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 2); +} + +/** + * @brief Get field pitch_speed from set_roll_pitch_yaw_speed_thrust message + * + * @return Desired pitch angular speed in rad/s + */ +static inline float mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_pitch_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 6); +} + +/** + * @brief Get field yaw_speed from set_roll_pitch_yaw_speed_thrust message + * + * @return Desired yaw angular speed in rad/s + */ +static inline float mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_yaw_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 10); +} + +/** + * @brief Get field thrust from set_roll_pitch_yaw_speed_thrust message + * + * @return Collective thrust, normalized to 0 .. 1 + */ +static inline float mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_thrust(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 14); +} + +/** + * @brief Decode a set_roll_pitch_yaw_speed_thrust message into a struct + * + * @param msg The message to decode + * @param set_roll_pitch_yaw_speed_thrust C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_roll_pitch_yaw_speed_thrust_decode(const mavlink_message_t* msg, mavlink_set_roll_pitch_yaw_speed_thrust_t* set_roll_pitch_yaw_speed_thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_roll_pitch_yaw_speed_thrust->target_system = mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_target_system(msg); + set_roll_pitch_yaw_speed_thrust->target_component = mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_target_component(msg); + set_roll_pitch_yaw_speed_thrust->roll_speed = mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_roll_speed(msg); + set_roll_pitch_yaw_speed_thrust->pitch_speed = mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_pitch_speed(msg); + set_roll_pitch_yaw_speed_thrust->yaw_speed = mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_yaw_speed(msg); + set_roll_pitch_yaw_speed_thrust->thrust = mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_thrust(msg); +#else + memcpy(set_roll_pitch_yaw_speed_thrust, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_roll_pitch_yaw_thrust.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_roll_pitch_yaw_thrust.h new file mode 100644 index 0000000000..dad4f657dd --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_set_roll_pitch_yaw_thrust.h @@ -0,0 +1,254 @@ +// MESSAGE SET_ROLL_PITCH_YAW_THRUST PACKING + +#define MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST 55 + +typedef struct __mavlink_set_roll_pitch_yaw_thrust_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + float roll; ///< Desired roll angle in radians + float pitch; ///< Desired pitch angle in radians + float yaw; ///< Desired yaw angle in radians + float thrust; ///< Collective thrust, normalized to 0 .. 1 +} mavlink_set_roll_pitch_yaw_thrust_t; + +#define MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST_LEN 18 +#define MAVLINK_MSG_ID_55_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST { \ + "SET_ROLL_PITCH_YAW_THRUST", \ + 6, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_set_roll_pitch_yaw_thrust_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_set_roll_pitch_yaw_thrust_t, target_component) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 2, offsetof(mavlink_set_roll_pitch_yaw_thrust_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 6, offsetof(mavlink_set_roll_pitch_yaw_thrust_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 10, offsetof(mavlink_set_roll_pitch_yaw_thrust_t, yaw) }, \ + { "thrust", NULL, MAVLINK_TYPE_FLOAT, 0, 14, offsetof(mavlink_set_roll_pitch_yaw_thrust_t, thrust) }, \ + } \ +} + + +/** + * @brief Pack a set_roll_pitch_yaw_thrust message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param roll Desired roll angle in radians + * @param pitch Desired pitch angle in radians + * @param yaw Desired yaw angle in radians + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_roll_pitch_yaw_thrust_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, float roll, float pitch, float yaw, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 2, roll); + _mav_put_float(buf, 6, pitch); + _mav_put_float(buf, 10, yaw); + _mav_put_float(buf, 14, thrust); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_set_roll_pitch_yaw_thrust_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST; + return mavlink_finalize_message(msg, system_id, component_id, 18); +} + +/** + * @brief Pack a set_roll_pitch_yaw_thrust message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param roll Desired roll angle in radians + * @param pitch Desired pitch angle in radians + * @param yaw Desired yaw angle in radians + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_roll_pitch_yaw_thrust_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,float roll,float pitch,float yaw,float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 2, roll); + _mav_put_float(buf, 6, pitch); + _mav_put_float(buf, 10, yaw); + _mav_put_float(buf, 14, thrust); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_set_roll_pitch_yaw_thrust_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18); +} + +/** + * @brief Encode a set_roll_pitch_yaw_thrust struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_roll_pitch_yaw_thrust C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_roll_pitch_yaw_thrust_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_roll_pitch_yaw_thrust_t* set_roll_pitch_yaw_thrust) +{ + return mavlink_msg_set_roll_pitch_yaw_thrust_pack(system_id, component_id, msg, set_roll_pitch_yaw_thrust->target_system, set_roll_pitch_yaw_thrust->target_component, set_roll_pitch_yaw_thrust->roll, set_roll_pitch_yaw_thrust->pitch, set_roll_pitch_yaw_thrust->yaw, set_roll_pitch_yaw_thrust->thrust); +} + +/** + * @brief Send a set_roll_pitch_yaw_thrust message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param roll Desired roll angle in radians + * @param pitch Desired pitch angle in radians + * @param yaw Desired yaw angle in radians + * @param thrust Collective thrust, normalized to 0 .. 1 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_roll_pitch_yaw_thrust_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, float roll, float pitch, float yaw, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 2, roll); + _mav_put_float(buf, 6, pitch); + _mav_put_float(buf, 10, yaw); + _mav_put_float(buf, 14, thrust); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST, buf, 18); +#else + mavlink_set_roll_pitch_yaw_thrust_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST, (const char *)&packet, 18); +#endif +} + +#endif + +// MESSAGE SET_ROLL_PITCH_YAW_THRUST UNPACKING + + +/** + * @brief Get field target_system from set_roll_pitch_yaw_thrust message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_set_roll_pitch_yaw_thrust_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from set_roll_pitch_yaw_thrust message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_set_roll_pitch_yaw_thrust_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field roll from set_roll_pitch_yaw_thrust message + * + * @return Desired roll angle in radians + */ +static inline float mavlink_msg_set_roll_pitch_yaw_thrust_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 2); +} + +/** + * @brief Get field pitch from set_roll_pitch_yaw_thrust message + * + * @return Desired pitch angle in radians + */ +static inline float mavlink_msg_set_roll_pitch_yaw_thrust_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 6); +} + +/** + * @brief Get field yaw from set_roll_pitch_yaw_thrust message + * + * @return Desired yaw angle in radians + */ +static inline float mavlink_msg_set_roll_pitch_yaw_thrust_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 10); +} + +/** + * @brief Get field thrust from set_roll_pitch_yaw_thrust message + * + * @return Collective thrust, normalized to 0 .. 1 + */ +static inline float mavlink_msg_set_roll_pitch_yaw_thrust_get_thrust(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 14); +} + +/** + * @brief Decode a set_roll_pitch_yaw_thrust message into a struct + * + * @param msg The message to decode + * @param set_roll_pitch_yaw_thrust C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_roll_pitch_yaw_thrust_decode(const mavlink_message_t* msg, mavlink_set_roll_pitch_yaw_thrust_t* set_roll_pitch_yaw_thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_roll_pitch_yaw_thrust->target_system = mavlink_msg_set_roll_pitch_yaw_thrust_get_target_system(msg); + set_roll_pitch_yaw_thrust->target_component = mavlink_msg_set_roll_pitch_yaw_thrust_get_target_component(msg); + set_roll_pitch_yaw_thrust->roll = mavlink_msg_set_roll_pitch_yaw_thrust_get_roll(msg); + set_roll_pitch_yaw_thrust->pitch = mavlink_msg_set_roll_pitch_yaw_thrust_get_pitch(msg); + set_roll_pitch_yaw_thrust->yaw = mavlink_msg_set_roll_pitch_yaw_thrust_get_yaw(msg); + set_roll_pitch_yaw_thrust->thrust = mavlink_msg_set_roll_pitch_yaw_thrust_get_thrust(msg); +#else + memcpy(set_roll_pitch_yaw_thrust, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_state_correction.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_state_correction.h new file mode 100644 index 0000000000..ddd785a2ac --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_state_correction.h @@ -0,0 +1,320 @@ +// MESSAGE STATE_CORRECTION PACKING + +#define MAVLINK_MSG_ID_STATE_CORRECTION 64 + +typedef struct __mavlink_state_correction_t +{ + float xErr; ///< x position error + float yErr; ///< y position error + float zErr; ///< z position error + float rollErr; ///< roll error (radians) + float pitchErr; ///< pitch error (radians) + float yawErr; ///< yaw error (radians) + float vxErr; ///< x velocity + float vyErr; ///< y velocity + float vzErr; ///< z velocity +} mavlink_state_correction_t; + +#define MAVLINK_MSG_ID_STATE_CORRECTION_LEN 36 +#define MAVLINK_MSG_ID_64_LEN 36 + + + +#define MAVLINK_MESSAGE_INFO_STATE_CORRECTION { \ + "STATE_CORRECTION", \ + 9, \ + { { "xErr", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_state_correction_t, xErr) }, \ + { "yErr", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_state_correction_t, yErr) }, \ + { "zErr", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_state_correction_t, zErr) }, \ + { "rollErr", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_state_correction_t, rollErr) }, \ + { "pitchErr", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_state_correction_t, pitchErr) }, \ + { "yawErr", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_state_correction_t, yawErr) }, \ + { "vxErr", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_state_correction_t, vxErr) }, \ + { "vyErr", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_state_correction_t, vyErr) }, \ + { "vzErr", NULL, MAVLINK_TYPE_FLOAT, 0, 32, offsetof(mavlink_state_correction_t, vzErr) }, \ + } \ +} + + +/** + * @brief Pack a state_correction message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param xErr x position error + * @param yErr y position error + * @param zErr z position error + * @param rollErr roll error (radians) + * @param pitchErr pitch error (radians) + * @param yawErr yaw error (radians) + * @param vxErr x velocity + * @param vyErr y velocity + * @param vzErr z velocity + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_state_correction_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float xErr, float yErr, float zErr, float rollErr, float pitchErr, float yawErr, float vxErr, float vyErr, float vzErr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, xErr); + _mav_put_float(buf, 4, yErr); + _mav_put_float(buf, 8, zErr); + _mav_put_float(buf, 12, rollErr); + _mav_put_float(buf, 16, pitchErr); + _mav_put_float(buf, 20, yawErr); + _mav_put_float(buf, 24, vxErr); + _mav_put_float(buf, 28, vyErr); + _mav_put_float(buf, 32, vzErr); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_state_correction_t packet; + packet.xErr = xErr; + packet.yErr = yErr; + packet.zErr = zErr; + packet.rollErr = rollErr; + packet.pitchErr = pitchErr; + packet.yawErr = yawErr; + packet.vxErr = vxErr; + packet.vyErr = vyErr; + packet.vzErr = vzErr; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_STATE_CORRECTION; + return mavlink_finalize_message(msg, system_id, component_id, 36); +} + +/** + * @brief Pack a state_correction message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param xErr x position error + * @param yErr y position error + * @param zErr z position error + * @param rollErr roll error (radians) + * @param pitchErr pitch error (radians) + * @param yawErr yaw error (radians) + * @param vxErr x velocity + * @param vyErr y velocity + * @param vzErr z velocity + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_state_correction_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float xErr,float yErr,float zErr,float rollErr,float pitchErr,float yawErr,float vxErr,float vyErr,float vzErr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, xErr); + _mav_put_float(buf, 4, yErr); + _mav_put_float(buf, 8, zErr); + _mav_put_float(buf, 12, rollErr); + _mav_put_float(buf, 16, pitchErr); + _mav_put_float(buf, 20, yawErr); + _mav_put_float(buf, 24, vxErr); + _mav_put_float(buf, 28, vyErr); + _mav_put_float(buf, 32, vzErr); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_state_correction_t packet; + packet.xErr = xErr; + packet.yErr = yErr; + packet.zErr = zErr; + packet.rollErr = rollErr; + packet.pitchErr = pitchErr; + packet.yawErr = yawErr; + packet.vxErr = vxErr; + packet.vyErr = vyErr; + packet.vzErr = vzErr; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_STATE_CORRECTION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 36); +} + +/** + * @brief Encode a state_correction struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param state_correction C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_state_correction_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_state_correction_t* state_correction) +{ + return mavlink_msg_state_correction_pack(system_id, component_id, msg, state_correction->xErr, state_correction->yErr, state_correction->zErr, state_correction->rollErr, state_correction->pitchErr, state_correction->yawErr, state_correction->vxErr, state_correction->vyErr, state_correction->vzErr); +} + +/** + * @brief Send a state_correction message + * @param chan MAVLink channel to send the message + * + * @param xErr x position error + * @param yErr y position error + * @param zErr z position error + * @param rollErr roll error (radians) + * @param pitchErr pitch error (radians) + * @param yawErr yaw error (radians) + * @param vxErr x velocity + * @param vyErr y velocity + * @param vzErr z velocity + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_state_correction_send(mavlink_channel_t chan, float xErr, float yErr, float zErr, float rollErr, float pitchErr, float yawErr, float vxErr, float vyErr, float vzErr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, xErr); + _mav_put_float(buf, 4, yErr); + _mav_put_float(buf, 8, zErr); + _mav_put_float(buf, 12, rollErr); + _mav_put_float(buf, 16, pitchErr); + _mav_put_float(buf, 20, yawErr); + _mav_put_float(buf, 24, vxErr); + _mav_put_float(buf, 28, vyErr); + _mav_put_float(buf, 32, vzErr); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_STATE_CORRECTION, buf, 36); +#else + mavlink_state_correction_t packet; + packet.xErr = xErr; + packet.yErr = yErr; + packet.zErr = zErr; + packet.rollErr = rollErr; + packet.pitchErr = pitchErr; + packet.yawErr = yawErr; + packet.vxErr = vxErr; + packet.vyErr = vyErr; + packet.vzErr = vzErr; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_STATE_CORRECTION, (const char *)&packet, 36); +#endif +} + +#endif + +// MESSAGE STATE_CORRECTION UNPACKING + + +/** + * @brief Get field xErr from state_correction message + * + * @return x position error + */ +static inline float mavlink_msg_state_correction_get_xErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field yErr from state_correction message + * + * @return y position error + */ +static inline float mavlink_msg_state_correction_get_yErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field zErr from state_correction message + * + * @return z position error + */ +static inline float mavlink_msg_state_correction_get_zErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field rollErr from state_correction message + * + * @return roll error (radians) + */ +static inline float mavlink_msg_state_correction_get_rollErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field pitchErr from state_correction message + * + * @return pitch error (radians) + */ +static inline float mavlink_msg_state_correction_get_pitchErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field yawErr from state_correction message + * + * @return yaw error (radians) + */ +static inline float mavlink_msg_state_correction_get_yawErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field vxErr from state_correction message + * + * @return x velocity + */ +static inline float mavlink_msg_state_correction_get_vxErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field vyErr from state_correction message + * + * @return y velocity + */ +static inline float mavlink_msg_state_correction_get_vyErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field vzErr from state_correction message + * + * @return z velocity + */ +static inline float mavlink_msg_state_correction_get_vzErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 32); +} + +/** + * @brief Decode a state_correction message into a struct + * + * @param msg The message to decode + * @param state_correction C-struct to decode the message contents into + */ +static inline void mavlink_msg_state_correction_decode(const mavlink_message_t* msg, mavlink_state_correction_t* state_correction) +{ +#if MAVLINK_NEED_BYTE_SWAP + state_correction->xErr = mavlink_msg_state_correction_get_xErr(msg); + state_correction->yErr = mavlink_msg_state_correction_get_yErr(msg); + state_correction->zErr = mavlink_msg_state_correction_get_zErr(msg); + state_correction->rollErr = mavlink_msg_state_correction_get_rollErr(msg); + state_correction->pitchErr = mavlink_msg_state_correction_get_pitchErr(msg); + state_correction->yawErr = mavlink_msg_state_correction_get_yawErr(msg); + state_correction->vxErr = mavlink_msg_state_correction_get_vxErr(msg); + state_correction->vyErr = mavlink_msg_state_correction_get_vyErr(msg); + state_correction->vzErr = mavlink_msg_state_correction_get_vzErr(msg); +#else + memcpy(state_correction, _MAV_PAYLOAD(msg), 36); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_statustext.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_statustext.h new file mode 100644 index 0000000000..c65f629e99 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_statustext.h @@ -0,0 +1,160 @@ +// MESSAGE STATUSTEXT PACKING + +#define MAVLINK_MSG_ID_STATUSTEXT 254 + +typedef struct __mavlink_statustext_t +{ + uint8_t severity; ///< Severity of status, 0 = info message, 255 = critical fault + int8_t text[50]; ///< Status text message, without null termination character +} mavlink_statustext_t; + +#define MAVLINK_MSG_ID_STATUSTEXT_LEN 51 +#define MAVLINK_MSG_ID_254_LEN 51 + +#define MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN 50 + +#define MAVLINK_MESSAGE_INFO_STATUSTEXT { \ + "STATUSTEXT", \ + 2, \ + { { "severity", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_statustext_t, severity) }, \ + { "text", NULL, MAVLINK_TYPE_INT8_T, 50, 1, offsetof(mavlink_statustext_t, text) }, \ + } \ +} + + +/** + * @brief Pack a statustext message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param severity Severity of status, 0 = info message, 255 = critical fault + * @param text Status text message, without null termination character + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_statustext_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t severity, const int8_t *text) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[51]; + _mav_put_uint8_t(buf, 0, severity); + _mav_put_int8_t_array(buf, 1, text, 50); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 51); +#else + mavlink_statustext_t packet; + packet.severity = severity; + mav_array_memcpy(packet.text, text, sizeof(int8_t)*50); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 51); +#endif + + msg->msgid = MAVLINK_MSG_ID_STATUSTEXT; + return mavlink_finalize_message(msg, system_id, component_id, 51); +} + +/** + * @brief Pack a statustext message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param severity Severity of status, 0 = info message, 255 = critical fault + * @param text Status text message, without null termination character + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_statustext_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t severity,const int8_t *text) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[51]; + _mav_put_uint8_t(buf, 0, severity); + _mav_put_int8_t_array(buf, 1, text, 50); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 51); +#else + mavlink_statustext_t packet; + packet.severity = severity; + mav_array_memcpy(packet.text, text, sizeof(int8_t)*50); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 51); +#endif + + msg->msgid = MAVLINK_MSG_ID_STATUSTEXT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 51); +} + +/** + * @brief Encode a statustext struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param statustext C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_statustext_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_statustext_t* statustext) +{ + return mavlink_msg_statustext_pack(system_id, component_id, msg, statustext->severity, statustext->text); +} + +/** + * @brief Send a statustext message + * @param chan MAVLink channel to send the message + * + * @param severity Severity of status, 0 = info message, 255 = critical fault + * @param text Status text message, without null termination character + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_statustext_send(mavlink_channel_t chan, uint8_t severity, const int8_t *text) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[51]; + _mav_put_uint8_t(buf, 0, severity); + _mav_put_int8_t_array(buf, 1, text, 50); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_STATUSTEXT, buf, 51); +#else + mavlink_statustext_t packet; + packet.severity = severity; + mav_array_memcpy(packet.text, text, sizeof(int8_t)*50); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_STATUSTEXT, (const char *)&packet, 51); +#endif +} + +#endif + +// MESSAGE STATUSTEXT UNPACKING + + +/** + * @brief Get field severity from statustext message + * + * @return Severity of status, 0 = info message, 255 = critical fault + */ +static inline uint8_t mavlink_msg_statustext_get_severity(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field text from statustext message + * + * @return Status text message, without null termination character + */ +static inline uint16_t mavlink_msg_statustext_get_text(const mavlink_message_t* msg, int8_t *text) +{ + return _MAV_RETURN_int8_t_array(msg, text, 50, 1); +} + +/** + * @brief Decode a statustext message into a struct + * + * @param msg The message to decode + * @param statustext C-struct to decode the message contents into + */ +static inline void mavlink_msg_statustext_decode(const mavlink_message_t* msg, mavlink_statustext_t* statustext) +{ +#if MAVLINK_NEED_BYTE_SWAP + statustext->severity = mavlink_msg_statustext_get_severity(msg); + mavlink_msg_statustext_get_text(msg, statustext->text); +#else + memcpy(statustext, _MAV_PAYLOAD(msg), 51); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_sys_status.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_sys_status.h new file mode 100644 index 0000000000..1217ea60e9 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_sys_status.h @@ -0,0 +1,276 @@ +// MESSAGE SYS_STATUS PACKING + +#define MAVLINK_MSG_ID_SYS_STATUS 34 + +typedef struct __mavlink_sys_status_t +{ + uint8_t mode; ///< System mode, see MAV_MODE ENUM in mavlink/include/mavlink_types.h + uint8_t nav_mode; ///< Navigation mode, see MAV_NAV_MODE ENUM + uint8_t status; ///< System status flag, see MAV_STATUS ENUM + uint16_t load; ///< Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 + uint16_t vbat; ///< Battery voltage, in millivolts (1 = 1 millivolt) + uint16_t battery_remaining; ///< Remaining battery energy: (0%: 0, 100%: 1000) + uint16_t packet_drop; ///< Dropped packets (packets that were corrupted on reception on the MAV) +} mavlink_sys_status_t; + +#define MAVLINK_MSG_ID_SYS_STATUS_LEN 11 +#define MAVLINK_MSG_ID_34_LEN 11 + + + +#define MAVLINK_MESSAGE_INFO_SYS_STATUS { \ + "SYS_STATUS", \ + 7, \ + { { "mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_sys_status_t, mode) }, \ + { "nav_mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_sys_status_t, nav_mode) }, \ + { "status", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_sys_status_t, status) }, \ + { "load", NULL, MAVLINK_TYPE_UINT16_T, 0, 3, offsetof(mavlink_sys_status_t, load) }, \ + { "vbat", NULL, MAVLINK_TYPE_UINT16_T, 0, 5, offsetof(mavlink_sys_status_t, vbat) }, \ + { "battery_remaining", NULL, MAVLINK_TYPE_UINT16_T, 0, 7, offsetof(mavlink_sys_status_t, battery_remaining) }, \ + { "packet_drop", NULL, MAVLINK_TYPE_UINT16_T, 0, 9, offsetof(mavlink_sys_status_t, packet_drop) }, \ + } \ +} + + +/** + * @brief Pack a sys_status message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param mode System mode, see MAV_MODE ENUM in mavlink/include/mavlink_types.h + * @param nav_mode Navigation mode, see MAV_NAV_MODE ENUM + * @param status System status flag, see MAV_STATUS ENUM + * @param load Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 + * @param vbat Battery voltage, in millivolts (1 = 1 millivolt) + * @param battery_remaining Remaining battery energy: (0%: 0, 100%: 1000) + * @param packet_drop Dropped packets (packets that were corrupted on reception on the MAV) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sys_status_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t mode, uint8_t nav_mode, uint8_t status, uint16_t load, uint16_t vbat, uint16_t battery_remaining, uint16_t packet_drop) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[11]; + _mav_put_uint8_t(buf, 0, mode); + _mav_put_uint8_t(buf, 1, nav_mode); + _mav_put_uint8_t(buf, 2, status); + _mav_put_uint16_t(buf, 3, load); + _mav_put_uint16_t(buf, 5, vbat); + _mav_put_uint16_t(buf, 7, battery_remaining); + _mav_put_uint16_t(buf, 9, packet_drop); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 11); +#else + mavlink_sys_status_t packet; + packet.mode = mode; + packet.nav_mode = nav_mode; + packet.status = status; + packet.load = load; + packet.vbat = vbat; + packet.battery_remaining = battery_remaining; + packet.packet_drop = packet_drop; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 11); +#endif + + msg->msgid = MAVLINK_MSG_ID_SYS_STATUS; + return mavlink_finalize_message(msg, system_id, component_id, 11); +} + +/** + * @brief Pack a sys_status message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param mode System mode, see MAV_MODE ENUM in mavlink/include/mavlink_types.h + * @param nav_mode Navigation mode, see MAV_NAV_MODE ENUM + * @param status System status flag, see MAV_STATUS ENUM + * @param load Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 + * @param vbat Battery voltage, in millivolts (1 = 1 millivolt) + * @param battery_remaining Remaining battery energy: (0%: 0, 100%: 1000) + * @param packet_drop Dropped packets (packets that were corrupted on reception on the MAV) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sys_status_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t mode,uint8_t nav_mode,uint8_t status,uint16_t load,uint16_t vbat,uint16_t battery_remaining,uint16_t packet_drop) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[11]; + _mav_put_uint8_t(buf, 0, mode); + _mav_put_uint8_t(buf, 1, nav_mode); + _mav_put_uint8_t(buf, 2, status); + _mav_put_uint16_t(buf, 3, load); + _mav_put_uint16_t(buf, 5, vbat); + _mav_put_uint16_t(buf, 7, battery_remaining); + _mav_put_uint16_t(buf, 9, packet_drop); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 11); +#else + mavlink_sys_status_t packet; + packet.mode = mode; + packet.nav_mode = nav_mode; + packet.status = status; + packet.load = load; + packet.vbat = vbat; + packet.battery_remaining = battery_remaining; + packet.packet_drop = packet_drop; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 11); +#endif + + msg->msgid = MAVLINK_MSG_ID_SYS_STATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 11); +} + +/** + * @brief Encode a sys_status struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param sys_status C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_sys_status_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_sys_status_t* sys_status) +{ + return mavlink_msg_sys_status_pack(system_id, component_id, msg, sys_status->mode, sys_status->nav_mode, sys_status->status, sys_status->load, sys_status->vbat, sys_status->battery_remaining, sys_status->packet_drop); +} + +/** + * @brief Send a sys_status message + * @param chan MAVLink channel to send the message + * + * @param mode System mode, see MAV_MODE ENUM in mavlink/include/mavlink_types.h + * @param nav_mode Navigation mode, see MAV_NAV_MODE ENUM + * @param status System status flag, see MAV_STATUS ENUM + * @param load Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 + * @param vbat Battery voltage, in millivolts (1 = 1 millivolt) + * @param battery_remaining Remaining battery energy: (0%: 0, 100%: 1000) + * @param packet_drop Dropped packets (packets that were corrupted on reception on the MAV) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_sys_status_send(mavlink_channel_t chan, uint8_t mode, uint8_t nav_mode, uint8_t status, uint16_t load, uint16_t vbat, uint16_t battery_remaining, uint16_t packet_drop) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[11]; + _mav_put_uint8_t(buf, 0, mode); + _mav_put_uint8_t(buf, 1, nav_mode); + _mav_put_uint8_t(buf, 2, status); + _mav_put_uint16_t(buf, 3, load); + _mav_put_uint16_t(buf, 5, vbat); + _mav_put_uint16_t(buf, 7, battery_remaining); + _mav_put_uint16_t(buf, 9, packet_drop); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SYS_STATUS, buf, 11); +#else + mavlink_sys_status_t packet; + packet.mode = mode; + packet.nav_mode = nav_mode; + packet.status = status; + packet.load = load; + packet.vbat = vbat; + packet.battery_remaining = battery_remaining; + packet.packet_drop = packet_drop; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SYS_STATUS, (const char *)&packet, 11); +#endif +} + +#endif + +// MESSAGE SYS_STATUS UNPACKING + + +/** + * @brief Get field mode from sys_status message + * + * @return System mode, see MAV_MODE ENUM in mavlink/include/mavlink_types.h + */ +static inline uint8_t mavlink_msg_sys_status_get_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field nav_mode from sys_status message + * + * @return Navigation mode, see MAV_NAV_MODE ENUM + */ +static inline uint8_t mavlink_msg_sys_status_get_nav_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field status from sys_status message + * + * @return System status flag, see MAV_STATUS ENUM + */ +static inline uint8_t mavlink_msg_sys_status_get_status(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field load from sys_status message + * + * @return Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 + */ +static inline uint16_t mavlink_msg_sys_status_get_load(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 3); +} + +/** + * @brief Get field vbat from sys_status message + * + * @return Battery voltage, in millivolts (1 = 1 millivolt) + */ +static inline uint16_t mavlink_msg_sys_status_get_vbat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 5); +} + +/** + * @brief Get field battery_remaining from sys_status message + * + * @return Remaining battery energy: (0%: 0, 100%: 1000) + */ +static inline uint16_t mavlink_msg_sys_status_get_battery_remaining(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 7); +} + +/** + * @brief Get field packet_drop from sys_status message + * + * @return Dropped packets (packets that were corrupted on reception on the MAV) + */ +static inline uint16_t mavlink_msg_sys_status_get_packet_drop(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 9); +} + +/** + * @brief Decode a sys_status message into a struct + * + * @param msg The message to decode + * @param sys_status C-struct to decode the message contents into + */ +static inline void mavlink_msg_sys_status_decode(const mavlink_message_t* msg, mavlink_sys_status_t* sys_status) +{ +#if MAVLINK_NEED_BYTE_SWAP + sys_status->mode = mavlink_msg_sys_status_get_mode(msg); + sys_status->nav_mode = mavlink_msg_sys_status_get_nav_mode(msg); + sys_status->status = mavlink_msg_sys_status_get_status(msg); + sys_status->load = mavlink_msg_sys_status_get_load(msg); + sys_status->vbat = mavlink_msg_sys_status_get_vbat(msg); + sys_status->battery_remaining = mavlink_msg_sys_status_get_battery_remaining(msg); + sys_status->packet_drop = mavlink_msg_sys_status_get_packet_drop(msg); +#else + memcpy(sys_status, _MAV_PAYLOAD(msg), 11); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_system_time.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_system_time.h new file mode 100644 index 0000000000..362586a70d --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_system_time.h @@ -0,0 +1,144 @@ +// MESSAGE SYSTEM_TIME PACKING + +#define MAVLINK_MSG_ID_SYSTEM_TIME 2 + +typedef struct __mavlink_system_time_t +{ + uint64_t time_usec; ///< Timestamp of the master clock in microseconds since UNIX epoch. +} mavlink_system_time_t; + +#define MAVLINK_MSG_ID_SYSTEM_TIME_LEN 8 +#define MAVLINK_MSG_ID_2_LEN 8 + + + +#define MAVLINK_MESSAGE_INFO_SYSTEM_TIME { \ + "SYSTEM_TIME", \ + 1, \ + { { "time_usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_system_time_t, time_usec) }, \ + } \ +} + + +/** + * @brief Pack a system_time message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_usec Timestamp of the master clock in microseconds since UNIX epoch. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_system_time_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time_usec) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint64_t(buf, 0, time_usec); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_system_time_t packet; + packet.time_usec = time_usec; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_SYSTEM_TIME; + return mavlink_finalize_message(msg, system_id, component_id, 8); +} + +/** + * @brief Pack a system_time message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_usec Timestamp of the master clock in microseconds since UNIX epoch. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_system_time_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time_usec) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint64_t(buf, 0, time_usec); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_system_time_t packet; + packet.time_usec = time_usec; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_SYSTEM_TIME; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 8); +} + +/** + * @brief Encode a system_time struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param system_time C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_system_time_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_system_time_t* system_time) +{ + return mavlink_msg_system_time_pack(system_id, component_id, msg, system_time->time_usec); +} + +/** + * @brief Send a system_time message + * @param chan MAVLink channel to send the message + * + * @param time_usec Timestamp of the master clock in microseconds since UNIX epoch. + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_system_time_send(mavlink_channel_t chan, uint64_t time_usec) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint64_t(buf, 0, time_usec); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SYSTEM_TIME, buf, 8); +#else + mavlink_system_time_t packet; + packet.time_usec = time_usec; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SYSTEM_TIME, (const char *)&packet, 8); +#endif +} + +#endif + +// MESSAGE SYSTEM_TIME UNPACKING + + +/** + * @brief Get field time_usec from system_time message + * + * @return Timestamp of the master clock in microseconds since UNIX epoch. + */ +static inline uint64_t mavlink_msg_system_time_get_time_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Decode a system_time message into a struct + * + * @param msg The message to decode + * @param system_time C-struct to decode the message contents into + */ +static inline void mavlink_msg_system_time_decode(const mavlink_message_t* msg, mavlink_system_time_t* system_time) +{ +#if MAVLINK_NEED_BYTE_SWAP + system_time->time_usec = mavlink_msg_system_time_get_time_usec(msg); +#else + memcpy(system_time, _MAV_PAYLOAD(msg), 8); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_system_time_utc.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_system_time_utc.h new file mode 100644 index 0000000000..5688435d53 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_system_time_utc.h @@ -0,0 +1,166 @@ +// MESSAGE SYSTEM_TIME_UTC PACKING + +#define MAVLINK_MSG_ID_SYSTEM_TIME_UTC 4 + +typedef struct __mavlink_system_time_utc_t +{ + uint32_t utc_date; ///< GPS UTC date ddmmyy + uint32_t utc_time; ///< GPS UTC time hhmmss +} mavlink_system_time_utc_t; + +#define MAVLINK_MSG_ID_SYSTEM_TIME_UTC_LEN 8 +#define MAVLINK_MSG_ID_4_LEN 8 + + + +#define MAVLINK_MESSAGE_INFO_SYSTEM_TIME_UTC { \ + "SYSTEM_TIME_UTC", \ + 2, \ + { { "utc_date", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_system_time_utc_t, utc_date) }, \ + { "utc_time", NULL, MAVLINK_TYPE_UINT32_T, 0, 4, offsetof(mavlink_system_time_utc_t, utc_time) }, \ + } \ +} + + +/** + * @brief Pack a system_time_utc message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param utc_date GPS UTC date ddmmyy + * @param utc_time GPS UTC time hhmmss + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_system_time_utc_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t utc_date, uint32_t utc_time) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint32_t(buf, 0, utc_date); + _mav_put_uint32_t(buf, 4, utc_time); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_system_time_utc_t packet; + packet.utc_date = utc_date; + packet.utc_time = utc_time; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_SYSTEM_TIME_UTC; + return mavlink_finalize_message(msg, system_id, component_id, 8); +} + +/** + * @brief Pack a system_time_utc message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param utc_date GPS UTC date ddmmyy + * @param utc_time GPS UTC time hhmmss + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_system_time_utc_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t utc_date,uint32_t utc_time) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint32_t(buf, 0, utc_date); + _mav_put_uint32_t(buf, 4, utc_time); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_system_time_utc_t packet; + packet.utc_date = utc_date; + packet.utc_time = utc_time; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_SYSTEM_TIME_UTC; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 8); +} + +/** + * @brief Encode a system_time_utc struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param system_time_utc C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_system_time_utc_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_system_time_utc_t* system_time_utc) +{ + return mavlink_msg_system_time_utc_pack(system_id, component_id, msg, system_time_utc->utc_date, system_time_utc->utc_time); +} + +/** + * @brief Send a system_time_utc message + * @param chan MAVLink channel to send the message + * + * @param utc_date GPS UTC date ddmmyy + * @param utc_time GPS UTC time hhmmss + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_system_time_utc_send(mavlink_channel_t chan, uint32_t utc_date, uint32_t utc_time) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint32_t(buf, 0, utc_date); + _mav_put_uint32_t(buf, 4, utc_time); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SYSTEM_TIME_UTC, buf, 8); +#else + mavlink_system_time_utc_t packet; + packet.utc_date = utc_date; + packet.utc_time = utc_time; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SYSTEM_TIME_UTC, (const char *)&packet, 8); +#endif +} + +#endif + +// MESSAGE SYSTEM_TIME_UTC UNPACKING + + +/** + * @brief Get field utc_date from system_time_utc message + * + * @return GPS UTC date ddmmyy + */ +static inline uint32_t mavlink_msg_system_time_utc_get_utc_date(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field utc_time from system_time_utc message + * + * @return GPS UTC time hhmmss + */ +static inline uint32_t mavlink_msg_system_time_utc_get_utc_time(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 4); +} + +/** + * @brief Decode a system_time_utc message into a struct + * + * @param msg The message to decode + * @param system_time_utc C-struct to decode the message contents into + */ +static inline void mavlink_msg_system_time_utc_decode(const mavlink_message_t* msg, mavlink_system_time_utc_t* system_time_utc) +{ +#if MAVLINK_NEED_BYTE_SWAP + system_time_utc->utc_date = mavlink_msg_system_time_utc_get_utc_date(msg); + system_time_utc->utc_time = mavlink_msg_system_time_utc_get_utc_time(msg); +#else + memcpy(system_time_utc, _MAV_PAYLOAD(msg), 8); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_vfr_hud.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_vfr_hud.h new file mode 100644 index 0000000000..0f92de775e --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_vfr_hud.h @@ -0,0 +1,254 @@ +// MESSAGE VFR_HUD PACKING + +#define MAVLINK_MSG_ID_VFR_HUD 74 + +typedef struct __mavlink_vfr_hud_t +{ + float airspeed; ///< Current airspeed in m/s + float groundspeed; ///< Current ground speed in m/s + int16_t heading; ///< Current heading in degrees, in compass units (0..360, 0=north) + uint16_t throttle; ///< Current throttle setting in integer percent, 0 to 100 + float alt; ///< Current altitude (MSL), in meters + float climb; ///< Current climb rate in meters/second +} mavlink_vfr_hud_t; + +#define MAVLINK_MSG_ID_VFR_HUD_LEN 20 +#define MAVLINK_MSG_ID_74_LEN 20 + + + +#define MAVLINK_MESSAGE_INFO_VFR_HUD { \ + "VFR_HUD", \ + 6, \ + { { "airspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_vfr_hud_t, airspeed) }, \ + { "groundspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_vfr_hud_t, groundspeed) }, \ + { "heading", NULL, MAVLINK_TYPE_INT16_T, 0, 8, offsetof(mavlink_vfr_hud_t, heading) }, \ + { "throttle", NULL, MAVLINK_TYPE_UINT16_T, 0, 10, offsetof(mavlink_vfr_hud_t, throttle) }, \ + { "alt", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_vfr_hud_t, alt) }, \ + { "climb", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_vfr_hud_t, climb) }, \ + } \ +} + + +/** + * @brief Pack a vfr_hud message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param airspeed Current airspeed in m/s + * @param groundspeed Current ground speed in m/s + * @param heading Current heading in degrees, in compass units (0..360, 0=north) + * @param throttle Current throttle setting in integer percent, 0 to 100 + * @param alt Current altitude (MSL), in meters + * @param climb Current climb rate in meters/second + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vfr_hud_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float airspeed, float groundspeed, int16_t heading, uint16_t throttle, float alt, float climb) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_float(buf, 0, airspeed); + _mav_put_float(buf, 4, groundspeed); + _mav_put_int16_t(buf, 8, heading); + _mav_put_uint16_t(buf, 10, throttle); + _mav_put_float(buf, 12, alt); + _mav_put_float(buf, 16, climb); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_vfr_hud_t packet; + packet.airspeed = airspeed; + packet.groundspeed = groundspeed; + packet.heading = heading; + packet.throttle = throttle; + packet.alt = alt; + packet.climb = climb; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_VFR_HUD; + return mavlink_finalize_message(msg, system_id, component_id, 20); +} + +/** + * @brief Pack a vfr_hud message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param airspeed Current airspeed in m/s + * @param groundspeed Current ground speed in m/s + * @param heading Current heading in degrees, in compass units (0..360, 0=north) + * @param throttle Current throttle setting in integer percent, 0 to 100 + * @param alt Current altitude (MSL), in meters + * @param climb Current climb rate in meters/second + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vfr_hud_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float airspeed,float groundspeed,int16_t heading,uint16_t throttle,float alt,float climb) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_float(buf, 0, airspeed); + _mav_put_float(buf, 4, groundspeed); + _mav_put_int16_t(buf, 8, heading); + _mav_put_uint16_t(buf, 10, throttle); + _mav_put_float(buf, 12, alt); + _mav_put_float(buf, 16, climb); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_vfr_hud_t packet; + packet.airspeed = airspeed; + packet.groundspeed = groundspeed; + packet.heading = heading; + packet.throttle = throttle; + packet.alt = alt; + packet.climb = climb; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_VFR_HUD; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 20); +} + +/** + * @brief Encode a vfr_hud struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param vfr_hud C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_vfr_hud_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_vfr_hud_t* vfr_hud) +{ + return mavlink_msg_vfr_hud_pack(system_id, component_id, msg, vfr_hud->airspeed, vfr_hud->groundspeed, vfr_hud->heading, vfr_hud->throttle, vfr_hud->alt, vfr_hud->climb); +} + +/** + * @brief Send a vfr_hud message + * @param chan MAVLink channel to send the message + * + * @param airspeed Current airspeed in m/s + * @param groundspeed Current ground speed in m/s + * @param heading Current heading in degrees, in compass units (0..360, 0=north) + * @param throttle Current throttle setting in integer percent, 0 to 100 + * @param alt Current altitude (MSL), in meters + * @param climb Current climb rate in meters/second + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_vfr_hud_send(mavlink_channel_t chan, float airspeed, float groundspeed, int16_t heading, uint16_t throttle, float alt, float climb) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_float(buf, 0, airspeed); + _mav_put_float(buf, 4, groundspeed); + _mav_put_int16_t(buf, 8, heading); + _mav_put_uint16_t(buf, 10, throttle); + _mav_put_float(buf, 12, alt); + _mav_put_float(buf, 16, climb); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VFR_HUD, buf, 20); +#else + mavlink_vfr_hud_t packet; + packet.airspeed = airspeed; + packet.groundspeed = groundspeed; + packet.heading = heading; + packet.throttle = throttle; + packet.alt = alt; + packet.climb = climb; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VFR_HUD, (const char *)&packet, 20); +#endif +} + +#endif + +// MESSAGE VFR_HUD UNPACKING + + +/** + * @brief Get field airspeed from vfr_hud message + * + * @return Current airspeed in m/s + */ +static inline float mavlink_msg_vfr_hud_get_airspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field groundspeed from vfr_hud message + * + * @return Current ground speed in m/s + */ +static inline float mavlink_msg_vfr_hud_get_groundspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field heading from vfr_hud message + * + * @return Current heading in degrees, in compass units (0..360, 0=north) + */ +static inline int16_t mavlink_msg_vfr_hud_get_heading(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 8); +} + +/** + * @brief Get field throttle from vfr_hud message + * + * @return Current throttle setting in integer percent, 0 to 100 + */ +static inline uint16_t mavlink_msg_vfr_hud_get_throttle(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 10); +} + +/** + * @brief Get field alt from vfr_hud message + * + * @return Current altitude (MSL), in meters + */ +static inline float mavlink_msg_vfr_hud_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field climb from vfr_hud message + * + * @return Current climb rate in meters/second + */ +static inline float mavlink_msg_vfr_hud_get_climb(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Decode a vfr_hud message into a struct + * + * @param msg The message to decode + * @param vfr_hud C-struct to decode the message contents into + */ +static inline void mavlink_msg_vfr_hud_decode(const mavlink_message_t* msg, mavlink_vfr_hud_t* vfr_hud) +{ +#if MAVLINK_NEED_BYTE_SWAP + vfr_hud->airspeed = mavlink_msg_vfr_hud_get_airspeed(msg); + vfr_hud->groundspeed = mavlink_msg_vfr_hud_get_groundspeed(msg); + vfr_hud->heading = mavlink_msg_vfr_hud_get_heading(msg); + vfr_hud->throttle = mavlink_msg_vfr_hud_get_throttle(msg); + vfr_hud->alt = mavlink_msg_vfr_hud_get_alt(msg); + vfr_hud->climb = mavlink_msg_vfr_hud_get_climb(msg); +#else + memcpy(vfr_hud, _MAV_PAYLOAD(msg), 20); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint.h new file mode 100644 index 0000000000..d9b21e3c94 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint.h @@ -0,0 +1,430 @@ +// MESSAGE WAYPOINT PACKING + +#define MAVLINK_MSG_ID_WAYPOINT 39 + +typedef struct __mavlink_waypoint_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint16_t seq; ///< Sequence + uint8_t frame; ///< The coordinate system of the waypoint. see MAV_FRAME in mavlink_types.h + uint8_t command; ///< The scheduled action for the waypoint. see MAV_COMMAND in common.xml MAVLink specs + uint8_t current; ///< false:0, true:1 + uint8_t autocontinue; ///< autocontinue to next wp + float param1; ///< PARAM1 / For NAV command waypoints: Radius in which the waypoint is accepted as reached, in meters + float param2; ///< PARAM2 / For NAV command waypoints: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds + float param3; ///< PARAM3 / For LOITER command waypoints: Orbit to circle around the waypoint, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. + float param4; ///< PARAM4 / For NAV and LOITER command waypoints: Yaw orientation in degrees, [0..360] 0 = NORTH + float x; ///< PARAM5 / local: x position, global: latitude + float y; ///< PARAM6 / y position: global: longitude + float z; ///< PARAM7 / z position: global: altitude +} mavlink_waypoint_t; + +#define MAVLINK_MSG_ID_WAYPOINT_LEN 36 +#define MAVLINK_MSG_ID_39_LEN 36 + + + +#define MAVLINK_MESSAGE_INFO_WAYPOINT { \ + "WAYPOINT", \ + 14, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_waypoint_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_waypoint_t, target_component) }, \ + { "seq", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_waypoint_t, seq) }, \ + { "frame", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_waypoint_t, frame) }, \ + { "command", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_waypoint_t, command) }, \ + { "current", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_waypoint_t, current) }, \ + { "autocontinue", NULL, MAVLINK_TYPE_UINT8_T, 0, 7, offsetof(mavlink_waypoint_t, autocontinue) }, \ + { "param1", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_waypoint_t, param1) }, \ + { "param2", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_waypoint_t, param2) }, \ + { "param3", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_waypoint_t, param3) }, \ + { "param4", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_waypoint_t, param4) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_waypoint_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_waypoint_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 32, offsetof(mavlink_waypoint_t, z) }, \ + } \ +} + + +/** + * @brief Pack a waypoint message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @param frame The coordinate system of the waypoint. see MAV_FRAME in mavlink_types.h + * @param command The scheduled action for the waypoint. see MAV_COMMAND in common.xml MAVLink specs + * @param current false:0, true:1 + * @param autocontinue autocontinue to next wp + * @param param1 PARAM1 / For NAV command waypoints: Radius in which the waypoint is accepted as reached, in meters + * @param param2 PARAM2 / For NAV command waypoints: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds + * @param param3 PARAM3 / For LOITER command waypoints: Orbit to circle around the waypoint, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. + * @param param4 PARAM4 / For NAV and LOITER command waypoints: Yaw orientation in degrees, [0..360] 0 = NORTH + * @param x PARAM5 / local: x position, global: latitude + * @param y PARAM6 / y position: global: longitude + * @param z PARAM7 / z position: global: altitude + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint16_t seq, uint8_t frame, uint8_t command, uint8_t current, uint8_t autocontinue, float param1, float param2, float param3, float param4, float x, float y, float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, seq); + _mav_put_uint8_t(buf, 4, frame); + _mav_put_uint8_t(buf, 5, command); + _mav_put_uint8_t(buf, 6, current); + _mav_put_uint8_t(buf, 7, autocontinue); + _mav_put_float(buf, 8, param1); + _mav_put_float(buf, 12, param2); + _mav_put_float(buf, 16, param3); + _mav_put_float(buf, 20, param4); + _mav_put_float(buf, 24, x); + _mav_put_float(buf, 28, y); + _mav_put_float(buf, 32, z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_waypoint_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.seq = seq; + packet.frame = frame; + packet.command = command; + packet.current = current; + packet.autocontinue = autocontinue; + packet.param1 = param1; + packet.param2 = param2; + packet.param3 = param3; + packet.param4 = param4; + packet.x = x; + packet.y = y; + packet.z = z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT; + return mavlink_finalize_message(msg, system_id, component_id, 36); +} + +/** + * @brief Pack a waypoint message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @param frame The coordinate system of the waypoint. see MAV_FRAME in mavlink_types.h + * @param command The scheduled action for the waypoint. see MAV_COMMAND in common.xml MAVLink specs + * @param current false:0, true:1 + * @param autocontinue autocontinue to next wp + * @param param1 PARAM1 / For NAV command waypoints: Radius in which the waypoint is accepted as reached, in meters + * @param param2 PARAM2 / For NAV command waypoints: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds + * @param param3 PARAM3 / For LOITER command waypoints: Orbit to circle around the waypoint, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. + * @param param4 PARAM4 / For NAV and LOITER command waypoints: Yaw orientation in degrees, [0..360] 0 = NORTH + * @param x PARAM5 / local: x position, global: latitude + * @param y PARAM6 / y position: global: longitude + * @param z PARAM7 / z position: global: altitude + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint16_t seq,uint8_t frame,uint8_t command,uint8_t current,uint8_t autocontinue,float param1,float param2,float param3,float param4,float x,float y,float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, seq); + _mav_put_uint8_t(buf, 4, frame); + _mav_put_uint8_t(buf, 5, command); + _mav_put_uint8_t(buf, 6, current); + _mav_put_uint8_t(buf, 7, autocontinue); + _mav_put_float(buf, 8, param1); + _mav_put_float(buf, 12, param2); + _mav_put_float(buf, 16, param3); + _mav_put_float(buf, 20, param4); + _mav_put_float(buf, 24, x); + _mav_put_float(buf, 28, y); + _mav_put_float(buf, 32, z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_waypoint_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.seq = seq; + packet.frame = frame; + packet.command = command; + packet.current = current; + packet.autocontinue = autocontinue; + packet.param1 = param1; + packet.param2 = param2; + packet.param3 = param3; + packet.param4 = param4; + packet.x = x; + packet.y = y; + packet.z = z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 36); +} + +/** + * @brief Encode a waypoint struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param waypoint C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_waypoint_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_waypoint_t* waypoint) +{ + return mavlink_msg_waypoint_pack(system_id, component_id, msg, waypoint->target_system, waypoint->target_component, waypoint->seq, waypoint->frame, waypoint->command, waypoint->current, waypoint->autocontinue, waypoint->param1, waypoint->param2, waypoint->param3, waypoint->param4, waypoint->x, waypoint->y, waypoint->z); +} + +/** + * @brief Send a waypoint message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @param frame The coordinate system of the waypoint. see MAV_FRAME in mavlink_types.h + * @param command The scheduled action for the waypoint. see MAV_COMMAND in common.xml MAVLink specs + * @param current false:0, true:1 + * @param autocontinue autocontinue to next wp + * @param param1 PARAM1 / For NAV command waypoints: Radius in which the waypoint is accepted as reached, in meters + * @param param2 PARAM2 / For NAV command waypoints: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds + * @param param3 PARAM3 / For LOITER command waypoints: Orbit to circle around the waypoint, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. + * @param param4 PARAM4 / For NAV and LOITER command waypoints: Yaw orientation in degrees, [0..360] 0 = NORTH + * @param x PARAM5 / local: x position, global: latitude + * @param y PARAM6 / y position: global: longitude + * @param z PARAM7 / z position: global: altitude + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_waypoint_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint16_t seq, uint8_t frame, uint8_t command, uint8_t current, uint8_t autocontinue, float param1, float param2, float param3, float param4, float x, float y, float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, seq); + _mav_put_uint8_t(buf, 4, frame); + _mav_put_uint8_t(buf, 5, command); + _mav_put_uint8_t(buf, 6, current); + _mav_put_uint8_t(buf, 7, autocontinue); + _mav_put_float(buf, 8, param1); + _mav_put_float(buf, 12, param2); + _mav_put_float(buf, 16, param3); + _mav_put_float(buf, 20, param4); + _mav_put_float(buf, 24, x); + _mav_put_float(buf, 28, y); + _mav_put_float(buf, 32, z); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT, buf, 36); +#else + mavlink_waypoint_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.seq = seq; + packet.frame = frame; + packet.command = command; + packet.current = current; + packet.autocontinue = autocontinue; + packet.param1 = param1; + packet.param2 = param2; + packet.param3 = param3; + packet.param4 = param4; + packet.x = x; + packet.y = y; + packet.z = z; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT, (const char *)&packet, 36); +#endif +} + +#endif + +// MESSAGE WAYPOINT UNPACKING + + +/** + * @brief Get field target_system from waypoint message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_waypoint_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from waypoint message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_waypoint_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field seq from waypoint message + * + * @return Sequence + */ +static inline uint16_t mavlink_msg_waypoint_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Get field frame from waypoint message + * + * @return The coordinate system of the waypoint. see MAV_FRAME in mavlink_types.h + */ +static inline uint8_t mavlink_msg_waypoint_get_frame(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field command from waypoint message + * + * @return The scheduled action for the waypoint. see MAV_COMMAND in common.xml MAVLink specs + */ +static inline uint8_t mavlink_msg_waypoint_get_command(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field current from waypoint message + * + * @return false:0, true:1 + */ +static inline uint8_t mavlink_msg_waypoint_get_current(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Get field autocontinue from waypoint message + * + * @return autocontinue to next wp + */ +static inline uint8_t mavlink_msg_waypoint_get_autocontinue(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 7); +} + +/** + * @brief Get field param1 from waypoint message + * + * @return PARAM1 / For NAV command waypoints: Radius in which the waypoint is accepted as reached, in meters + */ +static inline float mavlink_msg_waypoint_get_param1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field param2 from waypoint message + * + * @return PARAM2 / For NAV command waypoints: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds + */ +static inline float mavlink_msg_waypoint_get_param2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field param3 from waypoint message + * + * @return PARAM3 / For LOITER command waypoints: Orbit to circle around the waypoint, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. + */ +static inline float mavlink_msg_waypoint_get_param3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field param4 from waypoint message + * + * @return PARAM4 / For NAV and LOITER command waypoints: Yaw orientation in degrees, [0..360] 0 = NORTH + */ +static inline float mavlink_msg_waypoint_get_param4(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field x from waypoint message + * + * @return PARAM5 / local: x position, global: latitude + */ +static inline float mavlink_msg_waypoint_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field y from waypoint message + * + * @return PARAM6 / y position: global: longitude + */ +static inline float mavlink_msg_waypoint_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field z from waypoint message + * + * @return PARAM7 / z position: global: altitude + */ +static inline float mavlink_msg_waypoint_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 32); +} + +/** + * @brief Decode a waypoint message into a struct + * + * @param msg The message to decode + * @param waypoint C-struct to decode the message contents into + */ +static inline void mavlink_msg_waypoint_decode(const mavlink_message_t* msg, mavlink_waypoint_t* waypoint) +{ +#if MAVLINK_NEED_BYTE_SWAP + waypoint->target_system = mavlink_msg_waypoint_get_target_system(msg); + waypoint->target_component = mavlink_msg_waypoint_get_target_component(msg); + waypoint->seq = mavlink_msg_waypoint_get_seq(msg); + waypoint->frame = mavlink_msg_waypoint_get_frame(msg); + waypoint->command = mavlink_msg_waypoint_get_command(msg); + waypoint->current = mavlink_msg_waypoint_get_current(msg); + waypoint->autocontinue = mavlink_msg_waypoint_get_autocontinue(msg); + waypoint->param1 = mavlink_msg_waypoint_get_param1(msg); + waypoint->param2 = mavlink_msg_waypoint_get_param2(msg); + waypoint->param3 = mavlink_msg_waypoint_get_param3(msg); + waypoint->param4 = mavlink_msg_waypoint_get_param4(msg); + waypoint->x = mavlink_msg_waypoint_get_x(msg); + waypoint->y = mavlink_msg_waypoint_get_y(msg); + waypoint->z = mavlink_msg_waypoint_get_z(msg); +#else + memcpy(waypoint, _MAV_PAYLOAD(msg), 36); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_ack.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_ack.h new file mode 100644 index 0000000000..ddba2adf4c --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_ack.h @@ -0,0 +1,188 @@ +// MESSAGE WAYPOINT_ACK PACKING + +#define MAVLINK_MSG_ID_WAYPOINT_ACK 47 + +typedef struct __mavlink_waypoint_ack_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t type; ///< 0: OK, 1: Error +} mavlink_waypoint_ack_t; + +#define MAVLINK_MSG_ID_WAYPOINT_ACK_LEN 3 +#define MAVLINK_MSG_ID_47_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_WAYPOINT_ACK { \ + "WAYPOINT_ACK", \ + 3, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_waypoint_ack_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_waypoint_ack_t, target_component) }, \ + { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_waypoint_ack_t, type) }, \ + } \ +} + + +/** + * @brief Pack a waypoint_ack message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param type 0: OK, 1: Error + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_ack_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t type) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, type); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_waypoint_ack_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.type = type; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_ACK; + return mavlink_finalize_message(msg, system_id, component_id, 3); +} + +/** + * @brief Pack a waypoint_ack message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param type 0: OK, 1: Error + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_ack_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t type) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, type); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_waypoint_ack_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.type = type; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_ACK; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3); +} + +/** + * @brief Encode a waypoint_ack struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param waypoint_ack C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_waypoint_ack_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_waypoint_ack_t* waypoint_ack) +{ + return mavlink_msg_waypoint_ack_pack(system_id, component_id, msg, waypoint_ack->target_system, waypoint_ack->target_component, waypoint_ack->type); +} + +/** + * @brief Send a waypoint_ack message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param type 0: OK, 1: Error + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_waypoint_ack_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t type) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, type); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_ACK, buf, 3); +#else + mavlink_waypoint_ack_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.type = type; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_ACK, (const char *)&packet, 3); +#endif +} + +#endif + +// MESSAGE WAYPOINT_ACK UNPACKING + + +/** + * @brief Get field target_system from waypoint_ack message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_waypoint_ack_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from waypoint_ack message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_waypoint_ack_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field type from waypoint_ack message + * + * @return 0: OK, 1: Error + */ +static inline uint8_t mavlink_msg_waypoint_ack_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a waypoint_ack message into a struct + * + * @param msg The message to decode + * @param waypoint_ack C-struct to decode the message contents into + */ +static inline void mavlink_msg_waypoint_ack_decode(const mavlink_message_t* msg, mavlink_waypoint_ack_t* waypoint_ack) +{ +#if MAVLINK_NEED_BYTE_SWAP + waypoint_ack->target_system = mavlink_msg_waypoint_ack_get_target_system(msg); + waypoint_ack->target_component = mavlink_msg_waypoint_ack_get_target_component(msg); + waypoint_ack->type = mavlink_msg_waypoint_ack_get_type(msg); +#else + memcpy(waypoint_ack, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_clear_all.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_clear_all.h new file mode 100644 index 0000000000..8eab44b267 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_clear_all.h @@ -0,0 +1,166 @@ +// MESSAGE WAYPOINT_CLEAR_ALL PACKING + +#define MAVLINK_MSG_ID_WAYPOINT_CLEAR_ALL 45 + +typedef struct __mavlink_waypoint_clear_all_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_waypoint_clear_all_t; + +#define MAVLINK_MSG_ID_WAYPOINT_CLEAR_ALL_LEN 2 +#define MAVLINK_MSG_ID_45_LEN 2 + + + +#define MAVLINK_MESSAGE_INFO_WAYPOINT_CLEAR_ALL { \ + "WAYPOINT_CLEAR_ALL", \ + 2, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_waypoint_clear_all_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_waypoint_clear_all_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a waypoint_clear_all message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_clear_all_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_waypoint_clear_all_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_CLEAR_ALL; + return mavlink_finalize_message(msg, system_id, component_id, 2); +} + +/** + * @brief Pack a waypoint_clear_all message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_clear_all_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_waypoint_clear_all_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_CLEAR_ALL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 2); +} + +/** + * @brief Encode a waypoint_clear_all struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param waypoint_clear_all C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_waypoint_clear_all_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_waypoint_clear_all_t* waypoint_clear_all) +{ + return mavlink_msg_waypoint_clear_all_pack(system_id, component_id, msg, waypoint_clear_all->target_system, waypoint_clear_all->target_component); +} + +/** + * @brief Send a waypoint_clear_all message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_waypoint_clear_all_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_CLEAR_ALL, buf, 2); +#else + mavlink_waypoint_clear_all_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_CLEAR_ALL, (const char *)&packet, 2); +#endif +} + +#endif + +// MESSAGE WAYPOINT_CLEAR_ALL UNPACKING + + +/** + * @brief Get field target_system from waypoint_clear_all message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_waypoint_clear_all_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from waypoint_clear_all message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_waypoint_clear_all_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Decode a waypoint_clear_all message into a struct + * + * @param msg The message to decode + * @param waypoint_clear_all C-struct to decode the message contents into + */ +static inline void mavlink_msg_waypoint_clear_all_decode(const mavlink_message_t* msg, mavlink_waypoint_clear_all_t* waypoint_clear_all) +{ +#if MAVLINK_NEED_BYTE_SWAP + waypoint_clear_all->target_system = mavlink_msg_waypoint_clear_all_get_target_system(msg); + waypoint_clear_all->target_component = mavlink_msg_waypoint_clear_all_get_target_component(msg); +#else + memcpy(waypoint_clear_all, _MAV_PAYLOAD(msg), 2); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_count.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_count.h new file mode 100644 index 0000000000..af1dd382b6 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_count.h @@ -0,0 +1,188 @@ +// MESSAGE WAYPOINT_COUNT PACKING + +#define MAVLINK_MSG_ID_WAYPOINT_COUNT 44 + +typedef struct __mavlink_waypoint_count_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint16_t count; ///< Number of Waypoints in the Sequence +} mavlink_waypoint_count_t; + +#define MAVLINK_MSG_ID_WAYPOINT_COUNT_LEN 4 +#define MAVLINK_MSG_ID_44_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_WAYPOINT_COUNT { \ + "WAYPOINT_COUNT", \ + 3, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_waypoint_count_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_waypoint_count_t, target_component) }, \ + { "count", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_waypoint_count_t, count) }, \ + } \ +} + + +/** + * @brief Pack a waypoint_count message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param count Number of Waypoints in the Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_count_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint16_t count) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, count); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_waypoint_count_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.count = count; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_COUNT; + return mavlink_finalize_message(msg, system_id, component_id, 4); +} + +/** + * @brief Pack a waypoint_count message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param count Number of Waypoints in the Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_count_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint16_t count) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, count); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_waypoint_count_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.count = count; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_COUNT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4); +} + +/** + * @brief Encode a waypoint_count struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param waypoint_count C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_waypoint_count_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_waypoint_count_t* waypoint_count) +{ + return mavlink_msg_waypoint_count_pack(system_id, component_id, msg, waypoint_count->target_system, waypoint_count->target_component, waypoint_count->count); +} + +/** + * @brief Send a waypoint_count message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param count Number of Waypoints in the Sequence + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_waypoint_count_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint16_t count) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, count); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_COUNT, buf, 4); +#else + mavlink_waypoint_count_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.count = count; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_COUNT, (const char *)&packet, 4); +#endif +} + +#endif + +// MESSAGE WAYPOINT_COUNT UNPACKING + + +/** + * @brief Get field target_system from waypoint_count message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_waypoint_count_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from waypoint_count message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_waypoint_count_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field count from waypoint_count message + * + * @return Number of Waypoints in the Sequence + */ +static inline uint16_t mavlink_msg_waypoint_count_get_count(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Decode a waypoint_count message into a struct + * + * @param msg The message to decode + * @param waypoint_count C-struct to decode the message contents into + */ +static inline void mavlink_msg_waypoint_count_decode(const mavlink_message_t* msg, mavlink_waypoint_count_t* waypoint_count) +{ +#if MAVLINK_NEED_BYTE_SWAP + waypoint_count->target_system = mavlink_msg_waypoint_count_get_target_system(msg); + waypoint_count->target_component = mavlink_msg_waypoint_count_get_target_component(msg); + waypoint_count->count = mavlink_msg_waypoint_count_get_count(msg); +#else + memcpy(waypoint_count, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_current.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_current.h new file mode 100644 index 0000000000..a7e4557d6e --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_current.h @@ -0,0 +1,144 @@ +// MESSAGE WAYPOINT_CURRENT PACKING + +#define MAVLINK_MSG_ID_WAYPOINT_CURRENT 42 + +typedef struct __mavlink_waypoint_current_t +{ + uint16_t seq; ///< Sequence +} mavlink_waypoint_current_t; + +#define MAVLINK_MSG_ID_WAYPOINT_CURRENT_LEN 2 +#define MAVLINK_MSG_ID_42_LEN 2 + + + +#define MAVLINK_MESSAGE_INFO_WAYPOINT_CURRENT { \ + "WAYPOINT_CURRENT", \ + 1, \ + { { "seq", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_waypoint_current_t, seq) }, \ + } \ +} + + +/** + * @brief Pack a waypoint_current message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_current_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint16_t(buf, 0, seq); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_waypoint_current_t packet; + packet.seq = seq; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_CURRENT; + return mavlink_finalize_message(msg, system_id, component_id, 2); +} + +/** + * @brief Pack a waypoint_current message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_current_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint16_t(buf, 0, seq); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_waypoint_current_t packet; + packet.seq = seq; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_CURRENT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 2); +} + +/** + * @brief Encode a waypoint_current struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param waypoint_current C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_waypoint_current_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_waypoint_current_t* waypoint_current) +{ + return mavlink_msg_waypoint_current_pack(system_id, component_id, msg, waypoint_current->seq); +} + +/** + * @brief Send a waypoint_current message + * @param chan MAVLink channel to send the message + * + * @param seq Sequence + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_waypoint_current_send(mavlink_channel_t chan, uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint16_t(buf, 0, seq); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_CURRENT, buf, 2); +#else + mavlink_waypoint_current_t packet; + packet.seq = seq; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_CURRENT, (const char *)&packet, 2); +#endif +} + +#endif + +// MESSAGE WAYPOINT_CURRENT UNPACKING + + +/** + * @brief Get field seq from waypoint_current message + * + * @return Sequence + */ +static inline uint16_t mavlink_msg_waypoint_current_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Decode a waypoint_current message into a struct + * + * @param msg The message to decode + * @param waypoint_current C-struct to decode the message contents into + */ +static inline void mavlink_msg_waypoint_current_decode(const mavlink_message_t* msg, mavlink_waypoint_current_t* waypoint_current) +{ +#if MAVLINK_NEED_BYTE_SWAP + waypoint_current->seq = mavlink_msg_waypoint_current_get_seq(msg); +#else + memcpy(waypoint_current, _MAV_PAYLOAD(msg), 2); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_reached.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_reached.h new file mode 100644 index 0000000000..d28dce1494 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_reached.h @@ -0,0 +1,144 @@ +// MESSAGE WAYPOINT_REACHED PACKING + +#define MAVLINK_MSG_ID_WAYPOINT_REACHED 46 + +typedef struct __mavlink_waypoint_reached_t +{ + uint16_t seq; ///< Sequence +} mavlink_waypoint_reached_t; + +#define MAVLINK_MSG_ID_WAYPOINT_REACHED_LEN 2 +#define MAVLINK_MSG_ID_46_LEN 2 + + + +#define MAVLINK_MESSAGE_INFO_WAYPOINT_REACHED { \ + "WAYPOINT_REACHED", \ + 1, \ + { { "seq", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_waypoint_reached_t, seq) }, \ + } \ +} + + +/** + * @brief Pack a waypoint_reached message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_reached_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint16_t(buf, 0, seq); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_waypoint_reached_t packet; + packet.seq = seq; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_REACHED; + return mavlink_finalize_message(msg, system_id, component_id, 2); +} + +/** + * @brief Pack a waypoint_reached message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_reached_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint16_t(buf, 0, seq); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_waypoint_reached_t packet; + packet.seq = seq; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_REACHED; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 2); +} + +/** + * @brief Encode a waypoint_reached struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param waypoint_reached C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_waypoint_reached_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_waypoint_reached_t* waypoint_reached) +{ + return mavlink_msg_waypoint_reached_pack(system_id, component_id, msg, waypoint_reached->seq); +} + +/** + * @brief Send a waypoint_reached message + * @param chan MAVLink channel to send the message + * + * @param seq Sequence + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_waypoint_reached_send(mavlink_channel_t chan, uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint16_t(buf, 0, seq); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_REACHED, buf, 2); +#else + mavlink_waypoint_reached_t packet; + packet.seq = seq; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_REACHED, (const char *)&packet, 2); +#endif +} + +#endif + +// MESSAGE WAYPOINT_REACHED UNPACKING + + +/** + * @brief Get field seq from waypoint_reached message + * + * @return Sequence + */ +static inline uint16_t mavlink_msg_waypoint_reached_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Decode a waypoint_reached message into a struct + * + * @param msg The message to decode + * @param waypoint_reached C-struct to decode the message contents into + */ +static inline void mavlink_msg_waypoint_reached_decode(const mavlink_message_t* msg, mavlink_waypoint_reached_t* waypoint_reached) +{ +#if MAVLINK_NEED_BYTE_SWAP + waypoint_reached->seq = mavlink_msg_waypoint_reached_get_seq(msg); +#else + memcpy(waypoint_reached, _MAV_PAYLOAD(msg), 2); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_request.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_request.h new file mode 100644 index 0000000000..38167c0806 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_request.h @@ -0,0 +1,188 @@ +// MESSAGE WAYPOINT_REQUEST PACKING + +#define MAVLINK_MSG_ID_WAYPOINT_REQUEST 40 + +typedef struct __mavlink_waypoint_request_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint16_t seq; ///< Sequence +} mavlink_waypoint_request_t; + +#define MAVLINK_MSG_ID_WAYPOINT_REQUEST_LEN 4 +#define MAVLINK_MSG_ID_40_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST { \ + "WAYPOINT_REQUEST", \ + 3, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_waypoint_request_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_waypoint_request_t, target_component) }, \ + { "seq", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_waypoint_request_t, seq) }, \ + } \ +} + + +/** + * @brief Pack a waypoint_request message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_request_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, seq); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_waypoint_request_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.seq = seq; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_REQUEST; + return mavlink_finalize_message(msg, system_id, component_id, 4); +} + +/** + * @brief Pack a waypoint_request message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_request_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, seq); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_waypoint_request_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.seq = seq; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_REQUEST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4); +} + +/** + * @brief Encode a waypoint_request struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param waypoint_request C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_waypoint_request_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_waypoint_request_t* waypoint_request) +{ + return mavlink_msg_waypoint_request_pack(system_id, component_id, msg, waypoint_request->target_system, waypoint_request->target_component, waypoint_request->seq); +} + +/** + * @brief Send a waypoint_request message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_waypoint_request_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, seq); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_REQUEST, buf, 4); +#else + mavlink_waypoint_request_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.seq = seq; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_REQUEST, (const char *)&packet, 4); +#endif +} + +#endif + +// MESSAGE WAYPOINT_REQUEST UNPACKING + + +/** + * @brief Get field target_system from waypoint_request message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_waypoint_request_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from waypoint_request message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_waypoint_request_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field seq from waypoint_request message + * + * @return Sequence + */ +static inline uint16_t mavlink_msg_waypoint_request_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Decode a waypoint_request message into a struct + * + * @param msg The message to decode + * @param waypoint_request C-struct to decode the message contents into + */ +static inline void mavlink_msg_waypoint_request_decode(const mavlink_message_t* msg, mavlink_waypoint_request_t* waypoint_request) +{ +#if MAVLINK_NEED_BYTE_SWAP + waypoint_request->target_system = mavlink_msg_waypoint_request_get_target_system(msg); + waypoint_request->target_component = mavlink_msg_waypoint_request_get_target_component(msg); + waypoint_request->seq = mavlink_msg_waypoint_request_get_seq(msg); +#else + memcpy(waypoint_request, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_request_list.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_request_list.h new file mode 100644 index 0000000000..ba21fbc82d --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_request_list.h @@ -0,0 +1,166 @@ +// MESSAGE WAYPOINT_REQUEST_LIST PACKING + +#define MAVLINK_MSG_ID_WAYPOINT_REQUEST_LIST 43 + +typedef struct __mavlink_waypoint_request_list_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_waypoint_request_list_t; + +#define MAVLINK_MSG_ID_WAYPOINT_REQUEST_LIST_LEN 2 +#define MAVLINK_MSG_ID_43_LEN 2 + + + +#define MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST_LIST { \ + "WAYPOINT_REQUEST_LIST", \ + 2, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_waypoint_request_list_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_waypoint_request_list_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a waypoint_request_list message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_request_list_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_waypoint_request_list_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_REQUEST_LIST; + return mavlink_finalize_message(msg, system_id, component_id, 2); +} + +/** + * @brief Pack a waypoint_request_list message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_request_list_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_waypoint_request_list_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_REQUEST_LIST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 2); +} + +/** + * @brief Encode a waypoint_request_list struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param waypoint_request_list C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_waypoint_request_list_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_waypoint_request_list_t* waypoint_request_list) +{ + return mavlink_msg_waypoint_request_list_pack(system_id, component_id, msg, waypoint_request_list->target_system, waypoint_request_list->target_component); +} + +/** + * @brief Send a waypoint_request_list message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_waypoint_request_list_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_REQUEST_LIST, buf, 2); +#else + mavlink_waypoint_request_list_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_REQUEST_LIST, (const char *)&packet, 2); +#endif +} + +#endif + +// MESSAGE WAYPOINT_REQUEST_LIST UNPACKING + + +/** + * @brief Get field target_system from waypoint_request_list message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_waypoint_request_list_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from waypoint_request_list message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_waypoint_request_list_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Decode a waypoint_request_list message into a struct + * + * @param msg The message to decode + * @param waypoint_request_list C-struct to decode the message contents into + */ +static inline void mavlink_msg_waypoint_request_list_decode(const mavlink_message_t* msg, mavlink_waypoint_request_list_t* waypoint_request_list) +{ +#if MAVLINK_NEED_BYTE_SWAP + waypoint_request_list->target_system = mavlink_msg_waypoint_request_list_get_target_system(msg); + waypoint_request_list->target_component = mavlink_msg_waypoint_request_list_get_target_component(msg); +#else + memcpy(waypoint_request_list, _MAV_PAYLOAD(msg), 2); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_set_current.h b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_set_current.h new file mode 100644 index 0000000000..f1ba68b456 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/mavlink_msg_waypoint_set_current.h @@ -0,0 +1,188 @@ +// MESSAGE WAYPOINT_SET_CURRENT PACKING + +#define MAVLINK_MSG_ID_WAYPOINT_SET_CURRENT 41 + +typedef struct __mavlink_waypoint_set_current_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint16_t seq; ///< Sequence +} mavlink_waypoint_set_current_t; + +#define MAVLINK_MSG_ID_WAYPOINT_SET_CURRENT_LEN 4 +#define MAVLINK_MSG_ID_41_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_WAYPOINT_SET_CURRENT { \ + "WAYPOINT_SET_CURRENT", \ + 3, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_waypoint_set_current_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_waypoint_set_current_t, target_component) }, \ + { "seq", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_waypoint_set_current_t, seq) }, \ + } \ +} + + +/** + * @brief Pack a waypoint_set_current message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_set_current_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, seq); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_waypoint_set_current_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.seq = seq; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_SET_CURRENT; + return mavlink_finalize_message(msg, system_id, component_id, 4); +} + +/** + * @brief Pack a waypoint_set_current message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_waypoint_set_current_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, seq); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_waypoint_set_current_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.seq = seq; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_WAYPOINT_SET_CURRENT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4); +} + +/** + * @brief Encode a waypoint_set_current struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param waypoint_set_current C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_waypoint_set_current_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_waypoint_set_current_t* waypoint_set_current) +{ + return mavlink_msg_waypoint_set_current_pack(system_id, component_id, msg, waypoint_set_current->target_system, waypoint_set_current->target_component, waypoint_set_current->seq); +} + +/** + * @brief Send a waypoint_set_current message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_waypoint_set_current_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, seq); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_SET_CURRENT, buf, 4); +#else + mavlink_waypoint_set_current_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.seq = seq; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WAYPOINT_SET_CURRENT, (const char *)&packet, 4); +#endif +} + +#endif + +// MESSAGE WAYPOINT_SET_CURRENT UNPACKING + + +/** + * @brief Get field target_system from waypoint_set_current message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_waypoint_set_current_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from waypoint_set_current message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_waypoint_set_current_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field seq from waypoint_set_current message + * + * @return Sequence + */ +static inline uint16_t mavlink_msg_waypoint_set_current_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Decode a waypoint_set_current message into a struct + * + * @param msg The message to decode + * @param waypoint_set_current C-struct to decode the message contents into + */ +static inline void mavlink_msg_waypoint_set_current_decode(const mavlink_message_t* msg, mavlink_waypoint_set_current_t* waypoint_set_current) +{ +#if MAVLINK_NEED_BYTE_SWAP + waypoint_set_current->target_system = mavlink_msg_waypoint_set_current_get_target_system(msg); + waypoint_set_current->target_component = mavlink_msg_waypoint_set_current_get_target_component(msg); + waypoint_set_current->seq = mavlink_msg_waypoint_set_current_get_seq(msg); +#else + memcpy(waypoint_set_current, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/common/testsuite.h b/mavlink/include/mavlink/v0.9/common/testsuite.h new file mode 100644 index 0000000000..b3a94e96ea --- /dev/null +++ b/mavlink/include/mavlink/v0.9/common/testsuite.h @@ -0,0 +1,3700 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from common.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef COMMON_TESTSUITE_H +#define COMMON_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL + +static void mavlink_test_common(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + + mavlink_test_common(system_id, component_id, last_msg); +} +#endif + + + + +static void mavlink_test_heartbeat(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_heartbeat_t packet_in = { + 5, + 72, + 2, + }; + mavlink_heartbeat_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.type = packet_in.type; + packet1.autopilot = packet_in.autopilot; + packet1.mavlink_version = packet_in.mavlink_version; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_heartbeat_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_heartbeat_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_heartbeat_pack(system_id, component_id, &msg , packet1.type , packet1.autopilot ); + mavlink_msg_heartbeat_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_heartbeat_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.type , packet1.autopilot ); + mavlink_msg_heartbeat_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; imagic = MAVLINK_STX; + msg->len = length; + msg->sysid = system_id; + msg->compid = component_id; + // One sequence number per component + msg->seq = mavlink_get_channel_status(chan)->current_tx_seq; + mavlink_get_channel_status(chan)->current_tx_seq = mavlink_get_channel_status(chan)->current_tx_seq+1; + checksum = crc_calculate((uint8_t*)&msg->len, length + MAVLINK_CORE_HEADER_LEN); +#if MAVLINK_CRC_EXTRA + crc_accumulate(crc_extra, &checksum); +#endif + mavlink_ck_a(msg) = (uint8_t)(checksum & 0xFF); + mavlink_ck_b(msg) = (uint8_t)(checksum >> 8); + + return length + MAVLINK_NUM_NON_PAYLOAD_BYTES; +} + + +/** + * @brief Finalize a MAVLink message with MAVLINK_COMM_0 as default channel + */ +#if MAVLINK_CRC_EXTRA +MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t length, uint8_t crc_extra) +{ + return mavlink_finalize_message_chan(msg, system_id, component_id, MAVLINK_COMM_0, length, crc_extra); +} +#else +MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t length) +{ + return mavlink_finalize_message_chan(msg, system_id, component_id, MAVLINK_COMM_0, length); +} +#endif + +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS +MAVLINK_HELPER void _mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len); + +/** + * @brief Finalize a MAVLink message with channel assignment and send + */ +#if MAVLINK_CRC_EXTRA +MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet, + uint8_t length, uint8_t crc_extra) +#else +MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet, uint8_t length) +#endif +{ + uint16_t checksum; + uint8_t buf[MAVLINK_NUM_HEADER_BYTES]; + uint8_t ck[2]; + mavlink_status_t *status = mavlink_get_channel_status(chan); + buf[0] = MAVLINK_STX; + buf[1] = length; + buf[2] = status->current_tx_seq; + buf[3] = mavlink_system.sysid; + buf[4] = mavlink_system.compid; + buf[5] = msgid; + status->current_tx_seq++; + checksum = crc_calculate((uint8_t*)&buf[1], MAVLINK_CORE_HEADER_LEN); + crc_accumulate_buffer(&checksum, packet, length); +#if MAVLINK_CRC_EXTRA + crc_accumulate(crc_extra, &checksum); +#endif + ck[0] = (uint8_t)(checksum & 0xFF); + ck[1] = (uint8_t)(checksum >> 8); + + MAVLINK_START_UART_SEND(chan, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)length); + _mavlink_send_uart(chan, (const char *)buf, MAVLINK_NUM_HEADER_BYTES); + _mavlink_send_uart(chan, packet, length); + _mavlink_send_uart(chan, (const char *)ck, 2); + MAVLINK_END_UART_SEND(chan, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)length); +} +#endif // MAVLINK_USE_CONVENIENCE_FUNCTIONS + +/** + * @brief Pack a message to send it over a serial byte stream + */ +MAVLINK_HELPER uint16_t mavlink_msg_to_send_buffer(uint8_t *buffer, const mavlink_message_t *msg) +{ + memcpy(buffer, (uint8_t *)&msg->magic, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)msg->len); + return MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)msg->len; +} + +union __mavlink_bitfield { + uint8_t uint8; + int8_t int8; + uint16_t uint16; + int16_t int16; + uint32_t uint32; + int32_t int32; +}; + + +MAVLINK_HELPER void mavlink_start_checksum(mavlink_message_t* msg) +{ + crc_init(&msg->checksum); +} + +MAVLINK_HELPER void mavlink_update_checksum(mavlink_message_t* msg, uint8_t c) +{ + crc_accumulate(c, &msg->checksum); +} + +/** + * This is a convenience function which handles the complete MAVLink parsing. + * the function will parse one byte at a time and return the complete packet once + * it could be successfully decoded. Checksum and other failures will be silently + * ignored. + * + * @param chan ID of the current channel. This allows to parse different channels with this function. + * a channel is not a physical message channel like a serial port, but a logic partition of + * the communication streams in this case. COMM_NB is the limit for the number of channels + * on MCU (e.g. ARM7), while COMM_NB_HIGH is the limit for the number of channels in Linux/Windows + * @param c The char to barse + * + * @param returnMsg NULL if no message could be decoded, the message data else + * @return 0 if no message could be decoded, 1 else + * + * A typical use scenario of this function call is: + * + * @code + * #include // For fixed-width uint8_t type + * + * mavlink_message_t msg; + * int chan = 0; + * + * + * while(serial.bytesAvailable > 0) + * { + * uint8_t byte = serial.getNextByte(); + * if (mavlink_parse_char(chan, byte, &msg)) + * { + * printf("Received message with ID %d, sequence: %d from component %d of system %d", msg.msgid, msg.seq, msg.compid, msg.sysid); + * } + * } + * + * + * @endcode + */ +MAVLINK_HELPER uint8_t mavlink_parse_char(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status) +{ + static mavlink_message_t m_mavlink_message[MAVLINK_COMM_NUM_BUFFERS]; + + /* + default message crc function. You can override this per-system to + put this data in a different memory segment + */ +#if MAVLINK_CRC_EXTRA +#ifndef MAVLINK_MESSAGE_CRC + static const uint8_t mavlink_message_crcs[256] = MAVLINK_MESSAGE_CRCS; +#define MAVLINK_MESSAGE_CRC(msgid) mavlink_message_crcs[msgid] +#endif +#endif + + mavlink_message_t* rxmsg = &m_mavlink_message[chan]; ///< The currently decoded message + mavlink_status_t* status = mavlink_get_channel_status(chan); ///< The current decode status + int bufferIndex = 0; + + status->msg_received = 0; + + switch (status->parse_state) + { + case MAVLINK_PARSE_STATE_UNINIT: + case MAVLINK_PARSE_STATE_IDLE: + if (c == MAVLINK_STX) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; + rxmsg->len = 0; + mavlink_start_checksum(rxmsg); + } + break; + + case MAVLINK_PARSE_STATE_GOT_STX: + if (status->msg_received + /* Support shorter buffers than the + default maximum packet size */ +#if (MAVLINK_MAX_PAYLOAD_LEN < 255) + || c > MAVLINK_MAX_PAYLOAD_LEN +#endif + ) + { + status->buffer_overrun++; + status->parse_error++; + status->msg_received = 0; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + } + else + { + // NOT counting STX, LENGTH, SEQ, SYSID, COMPID, MSGID, CRC1 and CRC2 + rxmsg->len = c; + status->packet_idx = 0; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_LENGTH; + } + break; + + case MAVLINK_PARSE_STATE_GOT_LENGTH: + rxmsg->seq = c; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_SEQ; + break; + + case MAVLINK_PARSE_STATE_GOT_SEQ: + rxmsg->sysid = c; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_SYSID; + break; + + case MAVLINK_PARSE_STATE_GOT_SYSID: + rxmsg->compid = c; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_COMPID; + break; + + case MAVLINK_PARSE_STATE_GOT_COMPID: + rxmsg->msgid = c; + mavlink_update_checksum(rxmsg, c); + if (rxmsg->len == 0) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD; + } + else + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_MSGID; + } + break; + + case MAVLINK_PARSE_STATE_GOT_MSGID: + _MAV_PAYLOAD(rxmsg)[status->packet_idx++] = (char)c; + mavlink_update_checksum(rxmsg, c); + if (status->packet_idx == rxmsg->len) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD; + } + break; + + case MAVLINK_PARSE_STATE_GOT_PAYLOAD: +#if MAVLINK_CRC_EXTRA + mavlink_update_checksum(rxmsg, MAVLINK_MESSAGE_CRC(rxmsg->msgid)); +#endif + if (c != (rxmsg->checksum & 0xFF)) { + // Check first checksum byte + status->parse_error++; + status->msg_received = 0; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + if (c == MAVLINK_STX) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; + rxmsg->len = 0; + mavlink_start_checksum(rxmsg); + } + } + else + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_CRC1; + } + break; + + case MAVLINK_PARSE_STATE_GOT_CRC1: + if (c != (rxmsg->checksum >> 8)) { + // Check second checksum byte + status->parse_error++; + status->msg_received = 0; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + if (c == MAVLINK_STX) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; + rxmsg->len = 0; + mavlink_start_checksum(rxmsg); + } + } + else + { + // Successfully got message + status->msg_received = 1; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + memcpy(r_message, rxmsg, sizeof(mavlink_message_t)); + } + break; + } + + bufferIndex++; + // If a message has been sucessfully decoded, check index + if (status->msg_received == 1) + { + //while(status->current_seq != rxmsg->seq) + //{ + // status->packet_rx_drop_count++; + // status->current_seq++; + //} + status->current_rx_seq = rxmsg->seq; + // Initial condition: If no packet has been received so far, drop count is undefined + if (status->packet_rx_success_count == 0) status->packet_rx_drop_count = 0; + // Count this packet as received + status->packet_rx_success_count++; + } + + r_mavlink_status->current_rx_seq = status->current_rx_seq+1; + r_mavlink_status->packet_rx_success_count = status->packet_rx_success_count; + r_mavlink_status->packet_rx_drop_count = status->parse_error; + status->parse_error = 0; + return status->msg_received; +} + +/** + * @brief Put a bitfield of length 1-32 bit into the buffer + * + * @param b the value to add, will be encoded in the bitfield + * @param bits number of bits to use to encode b, e.g. 1 for boolean, 2, 3, etc. + * @param packet_index the position in the packet (the index of the first byte to use) + * @param bit_index the position in the byte (the index of the first bit to use) + * @param buffer packet buffer to write into + * @return new position of the last used byte in the buffer + */ +MAVLINK_HELPER uint8_t put_bitfield_n_by_index(int32_t b, uint8_t bits, uint8_t packet_index, uint8_t bit_index, uint8_t* r_bit_index, uint8_t* buffer) +{ + uint16_t bits_remain = bits; + // Transform number into network order + int32_t v; + uint8_t i_bit_index, i_byte_index, curr_bits_n; +#if MAVLINK_NEED_BYTE_SWAP + union { + int32_t i; + uint8_t b[4]; + } bin, bout; + bin.i = b; + bout.b[0] = bin.b[3]; + bout.b[1] = bin.b[2]; + bout.b[2] = bin.b[1]; + bout.b[3] = bin.b[0]; + v = bout.i; +#else + v = b; +#endif + + // buffer in + // 01100000 01000000 00000000 11110001 + // buffer out + // 11110001 00000000 01000000 01100000 + + // Existing partly filled byte (four free slots) + // 0111xxxx + + // Mask n free bits + // 00001111 = 2^0 + 2^1 + 2^2 + 2^3 = 2^n - 1 + // = ((uint32_t)(1 << n)) - 1; // = 2^n - 1 + + // Shift n bits into the right position + // out = in >> n; + + // Mask and shift bytes + i_bit_index = bit_index; + i_byte_index = packet_index; + if (bit_index > 0) + { + // If bits were available at start, they were available + // in the byte before the current index + i_byte_index--; + } + + // While bits have not been packed yet + while (bits_remain > 0) + { + // Bits still have to be packed + // there can be more than 8 bits, so + // we might have to pack them into more than one byte + + // First pack everything we can into the current 'open' byte + //curr_bits_n = bits_remain << 3; // Equals bits_remain mod 8 + //FIXME + if (bits_remain <= (uint8_t)(8 - i_bit_index)) + { + // Enough space + curr_bits_n = (uint8_t)bits_remain; + } + else + { + curr_bits_n = (8 - i_bit_index); + } + + // Pack these n bits into the current byte + // Mask out whatever was at that position with ones (xxx11111) + buffer[i_byte_index] &= (0xFF >> (8 - curr_bits_n)); + // Put content to this position, by masking out the non-used part + buffer[i_byte_index] |= ((0x00 << curr_bits_n) & v); + + // Increment the bit index + i_bit_index += curr_bits_n; + + // Now proceed to the next byte, if necessary + bits_remain -= curr_bits_n; + if (bits_remain > 0) + { + // Offer another 8 bits / one byte + i_byte_index++; + i_bit_index = 0; + } + } + + *r_bit_index = i_bit_index; + // If a partly filled byte is present, mark this as consumed + if (i_bit_index != 7) i_byte_index++; + return i_byte_index - packet_index; +} + +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +// To make MAVLink work on your MCU, define comm_send_ch() if you wish +// to send 1 byte at a time, or MAVLINK_SEND_UART_BYTES() to send a +// whole packet at a time + +/* + +#include "mavlink_types.h" + +void comm_send_ch(mavlink_channel_t chan, uint8_t ch) +{ + if (chan == MAVLINK_COMM_0) + { + uart0_transmit(ch); + } + if (chan == MAVLINK_COMM_1) + { + uart1_transmit(ch); + } +} + */ + +MAVLINK_HELPER void _mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len) +{ +#ifdef MAVLINK_SEND_UART_BYTES + /* this is the more efficient approach, if the platform + defines it */ + MAVLINK_SEND_UART_BYTES(chan, (uint8_t *)buf, len); +#else + /* fallback to one byte at a time */ + uint16_t i; + for (i = 0; i < len; i++) { + comm_send_ch(chan, (uint8_t)buf[i]); + } +#endif +} +#endif // MAVLINK_USE_CONVENIENCE_FUNCTIONS + +#endif /* _MAVLINK_HELPERS_H_ */ diff --git a/mavlink/include/mavlink/v0.9/mavlink_types.h b/mavlink/include/mavlink/v0.9/mavlink_types.h new file mode 100644 index 0000000000..630cb84b77 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/mavlink_types.h @@ -0,0 +1,300 @@ +#ifndef MAVLINK_TYPES_H_ +#define MAVLINK_TYPES_H_ + +#include "inttypes.h" + +enum MAV_CLASS +{ + MAV_CLASS_GENERIC = 0, ///< Generic autopilot, full support for everything + MAV_CLASS_PIXHAWK = 1, ///< PIXHAWK autopilot, http://pixhawk.ethz.ch + MAV_CLASS_SLUGS = 2, ///< SLUGS autopilot, http://slugsuav.soe.ucsc.edu + MAV_CLASS_ARDUPILOTMEGA = 3, ///< ArduPilotMega / ArduCopter, http://diydrones.com + MAV_CLASS_OPENPILOT = 4, ///< OpenPilot, http://openpilot.org + MAV_CLASS_GENERIC_MISSION_WAYPOINTS_ONLY = 5, ///< Generic autopilot only supporting simple waypoints + MAV_CLASS_GENERIC_MISSION_NAVIGATION_ONLY = 6, ///< Generic autopilot supporting waypoints and other simple navigation commands + MAV_CLASS_GENERIC_MISSION_FULL = 7, ///< Generic autopilot supporting the full mission command set + MAV_CLASS_NONE = 8, ///< No valid autopilot + MAV_CLASS_NB ///< Number of autopilot classes +}; + +enum MAV_ACTION +{ + MAV_ACTION_HOLD = 0, + MAV_ACTION_MOTORS_START = 1, + MAV_ACTION_LAUNCH = 2, + MAV_ACTION_RETURN = 3, + MAV_ACTION_EMCY_LAND = 4, + MAV_ACTION_EMCY_KILL = 5, + MAV_ACTION_CONFIRM_KILL = 6, + MAV_ACTION_CONTINUE = 7, + MAV_ACTION_MOTORS_STOP = 8, + MAV_ACTION_HALT = 9, + MAV_ACTION_SHUTDOWN = 10, + MAV_ACTION_REBOOT = 11, + MAV_ACTION_SET_MANUAL = 12, + MAV_ACTION_SET_AUTO = 13, + MAV_ACTION_STORAGE_READ = 14, + MAV_ACTION_STORAGE_WRITE = 15, + MAV_ACTION_CALIBRATE_RC = 16, + MAV_ACTION_CALIBRATE_GYRO = 17, + MAV_ACTION_CALIBRATE_MAG = 18, + MAV_ACTION_CALIBRATE_ACC = 19, + MAV_ACTION_CALIBRATE_PRESSURE = 20, + MAV_ACTION_REC_START = 21, + MAV_ACTION_REC_PAUSE = 22, + MAV_ACTION_REC_STOP = 23, + MAV_ACTION_TAKEOFF = 24, + MAV_ACTION_NAVIGATE = 25, + MAV_ACTION_LAND = 26, + MAV_ACTION_LOITER = 27, + MAV_ACTION_SET_ORIGIN = 28, + MAV_ACTION_RELAY_ON = 29, + MAV_ACTION_RELAY_OFF = 30, + MAV_ACTION_GET_IMAGE = 31, + MAV_ACTION_VIDEO_START = 32, + MAV_ACTION_VIDEO_STOP = 33, + MAV_ACTION_RESET_MAP = 34, + MAV_ACTION_RESET_PLAN = 35, + MAV_ACTION_DELAY_BEFORE_COMMAND = 36, + MAV_ACTION_ASCEND_AT_RATE = 37, + MAV_ACTION_CHANGE_MODE = 38, + MAV_ACTION_LOITER_MAX_TURNS = 39, + MAV_ACTION_LOITER_MAX_TIME = 40, + MAV_ACTION_START_HILSIM = 41, + MAV_ACTION_STOP_HILSIM = 42, + MAV_ACTION_NB ///< Number of MAV actions +}; + +enum MAV_MODE +{ + MAV_MODE_UNINIT = 0, ///< System is in undefined state + MAV_MODE_LOCKED = 1, ///< Motors are blocked, system is safe + MAV_MODE_MANUAL = 2, ///< System is allowed to be active, under manual (RC) control + MAV_MODE_GUIDED = 3, ///< System is allowed to be active, under autonomous control, manual setpoint + MAV_MODE_AUTO = 4, ///< System is allowed to be active, under autonomous control and navigation + MAV_MODE_TEST1 = 5, ///< Generic test mode, for custom use + MAV_MODE_TEST2 = 6, ///< Generic test mode, for custom use + MAV_MODE_TEST3 = 7, ///< Generic test mode, for custom use + MAV_MODE_READY = 8, ///< System is ready, motors are unblocked, but controllers are inactive + MAV_MODE_RC_TRAINING = 9 ///< System is blocked, only RC valued are read and reported back +}; + +enum MAV_STATE +{ + MAV_STATE_UNINIT = 0, + MAV_STATE_BOOT, + MAV_STATE_CALIBRATING, + MAV_STATE_STANDBY, + MAV_STATE_ACTIVE, + MAV_STATE_CRITICAL, + MAV_STATE_EMERGENCY, + MAV_STATE_HILSIM, + MAV_STATE_POWEROFF +}; + +enum MAV_NAV +{ + MAV_NAV_GROUNDED = 0, + MAV_NAV_LIFTOFF, + MAV_NAV_HOLD, + MAV_NAV_WAYPOINT, + MAV_NAV_VECTOR, + MAV_NAV_RETURNING, + MAV_NAV_LANDING, + MAV_NAV_LOST, + MAV_NAV_LOITER, + MAV_NAV_FREE_DRIFT +}; + +enum MAV_TYPE +{ + MAV_GENERIC = 0, + MAV_FIXED_WING = 1, + MAV_QUADROTOR = 2, + MAV_COAXIAL = 3, + MAV_HELICOPTER = 4, + MAV_GROUND = 5, + OCU = 6, + MAV_AIRSHIP = 7, + MAV_FREE_BALLOON = 8, + MAV_ROCKET = 9, + UGV_GROUND_ROVER = 10, + UGV_SURFACE_SHIP = 11 +}; + +enum MAV_AUTOPILOT_TYPE +{ + MAV_AUTOPILOT_GENERIC = 0, + MAV_AUTOPILOT_PIXHAWK = 1, + MAV_AUTOPILOT_SLUGS = 2, + MAV_AUTOPILOT_ARDUPILOTMEGA = 3, + MAV_AUTOPILOT_NONE = 4 +}; + +enum MAV_COMPONENT +{ + MAV_COMP_ID_GPS, + MAV_COMP_ID_WAYPOINTPLANNER, + MAV_COMP_ID_BLOBTRACKER, + MAV_COMP_ID_PATHPLANNER, + MAV_COMP_ID_AIRSLAM, + MAV_COMP_ID_MAPPER, + MAV_COMP_ID_CAMERA, + MAV_COMP_ID_RADIO = 68, + MAV_COMP_ID_IMU = 200, + MAV_COMP_ID_IMU_2 = 201, + MAV_COMP_ID_IMU_3 = 202, + MAV_COMP_ID_UDP_BRIDGE = 240, + MAV_COMP_ID_UART_BRIDGE = 241, + MAV_COMP_ID_SYSTEM_CONTROL = 250 +}; + +enum MAV_FRAME +{ + MAV_FRAME_GLOBAL = 0, + MAV_FRAME_LOCAL = 1, + MAV_FRAME_MISSION = 2, + MAV_FRAME_GLOBAL_RELATIVE_ALT = 3, + MAV_FRAME_LOCAL_ENU = 4 +}; + +enum MAVLINK_DATA_STREAM_TYPE +{ + MAVLINK_DATA_STREAM_IMG_JPEG, + MAVLINK_DATA_STREAM_IMG_BMP, + MAVLINK_DATA_STREAM_IMG_RAW8U, + MAVLINK_DATA_STREAM_IMG_RAW32U, + MAVLINK_DATA_STREAM_IMG_PGM, + MAVLINK_DATA_STREAM_IMG_PNG +}; + +#ifndef MAVLINK_MAX_PAYLOAD_LEN +// it is possible to override this, but be careful! +#define MAVLINK_MAX_PAYLOAD_LEN 255 ///< Maximum payload length +#endif + +#define MAVLINK_CORE_HEADER_LEN 5 ///< Length of core header (of the comm. layer): message length (1 byte) + message sequence (1 byte) + message system id (1 byte) + message component id (1 byte) + message type id (1 byte) +#define MAVLINK_NUM_HEADER_BYTES (MAVLINK_CORE_HEADER_LEN + 1) ///< Length of all header bytes, including core and checksum +#define MAVLINK_NUM_CHECKSUM_BYTES 2 +#define MAVLINK_NUM_NON_PAYLOAD_BYTES (MAVLINK_NUM_HEADER_BYTES + MAVLINK_NUM_CHECKSUM_BYTES) + +#define MAVLINK_MAX_PACKET_LEN (MAVLINK_MAX_PAYLOAD_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES) ///< Maximum packet length + +typedef struct param_union { + union { + float param_float; + int32_t param_int32; + uint32_t param_uint32; + }; + uint8_t type; +} mavlink_param_union_t; + +typedef struct __mavlink_system { + uint8_t sysid; ///< Used by the MAVLink message_xx_send() convenience function + uint8_t compid; ///< Used by the MAVLink message_xx_send() convenience function + uint8_t type; ///< Unused, can be used by user to store the system's type + uint8_t state; ///< Unused, can be used by user to store the system's state + uint8_t mode; ///< Unused, can be used by user to store the system's mode + uint8_t nav_mode; ///< Unused, can be used by user to store the system's navigation mode +} mavlink_system_t; + +typedef struct __mavlink_message { + uint16_t checksum; /// sent at end of packet + uint8_t magic; ///< protocol magic marker + uint8_t len; ///< Length of payload + uint8_t seq; ///< Sequence of packet + uint8_t sysid; ///< ID of message sender system/aircraft + uint8_t compid; ///< ID of the message sender component + uint8_t msgid; ///< ID of message in payload + uint64_t payload64[(MAVLINK_MAX_PAYLOAD_LEN+MAVLINK_NUM_CHECKSUM_BYTES+7)/8]; +} mavlink_message_t; + +typedef enum { + MAVLINK_TYPE_CHAR = 0, + MAVLINK_TYPE_UINT8_T = 1, + MAVLINK_TYPE_INT8_T = 2, + MAVLINK_TYPE_UINT16_T = 3, + MAVLINK_TYPE_INT16_T = 4, + MAVLINK_TYPE_UINT32_T = 5, + MAVLINK_TYPE_INT32_T = 6, + MAVLINK_TYPE_UINT64_T = 7, + MAVLINK_TYPE_INT64_T = 8, + MAVLINK_TYPE_FLOAT = 9, + MAVLINK_TYPE_DOUBLE = 10 +} mavlink_message_type_t; + +#define MAVLINK_MAX_FIELDS 64 + +typedef struct __mavlink_field_info { + const char *name; // name of this field + const char *print_format; // printing format hint, or NULL + mavlink_message_type_t type; // type of this field + unsigned array_length; // if non-zero, field is an array + unsigned wire_offset; // offset of each field in the payload + unsigned structure_offset; // offset in a C structure +} mavlink_field_info_t; + +// note that in this structure the order of fields is the order +// in the XML file, not necessary the wire order +typedef struct __mavlink_message_info { + const char *name; // name of the message + unsigned num_fields; // how many fields in this message + mavlink_field_info_t fields[MAVLINK_MAX_FIELDS]; // field information +} mavlink_message_info_t; + +#define _MAV_PAYLOAD(msg) ((char *)(&(msg)->payload64[0])) +#define _MAV_PAYLOAD_NON_CONST(msg) ((char *)(&((msg)->payload64[0]))) + +// checksum is immediately after the payload bytes +#define mavlink_ck_a(msg) *(msg->len + (uint8_t *)_MAV_PAYLOAD(msg)) +#define mavlink_ck_b(msg) *((msg->len+(uint16_t)1) + (uint8_t *)_MAV_PAYLOAD(msg)) + +typedef enum { + MAVLINK_COMM_0, + MAVLINK_COMM_1, + MAVLINK_COMM_2, + MAVLINK_COMM_3 +} mavlink_channel_t; + +/* + * applications can set MAVLINK_COMM_NUM_BUFFERS to the maximum number + * of buffers they will use. If more are used, then the result will be + * a stack overrun + */ +#ifndef MAVLINK_COMM_NUM_BUFFERS +#if (defined linux) | (defined __linux) | (defined __MACH__) | (defined _WIN32) +# define MAVLINK_COMM_NUM_BUFFERS 16 +#else +# define MAVLINK_COMM_NUM_BUFFERS 4 +#endif +#endif + +typedef enum { + MAVLINK_PARSE_STATE_UNINIT=0, + MAVLINK_PARSE_STATE_IDLE, + MAVLINK_PARSE_STATE_GOT_STX, + MAVLINK_PARSE_STATE_GOT_SEQ, + MAVLINK_PARSE_STATE_GOT_LENGTH, + MAVLINK_PARSE_STATE_GOT_SYSID, + MAVLINK_PARSE_STATE_GOT_COMPID, + MAVLINK_PARSE_STATE_GOT_MSGID, + MAVLINK_PARSE_STATE_GOT_PAYLOAD, + MAVLINK_PARSE_STATE_GOT_CRC1 +} mavlink_parse_state_t; ///< The state machine for the comm parser + +typedef struct __mavlink_status { + uint8_t msg_received; ///< Number of received messages + uint8_t buffer_overrun; ///< Number of buffer overruns + uint8_t parse_error; ///< Number of parse errors + mavlink_parse_state_t parse_state; ///< Parsing state machine + uint8_t packet_idx; ///< Index in current packet + uint8_t current_rx_seq; ///< Sequence number of last packet received + uint8_t current_tx_seq; ///< Sequence number of last packet sent + uint16_t packet_rx_success_count; ///< Received packets + uint16_t packet_rx_drop_count; ///< Number of packet drops +} mavlink_status_t; + +#define MAVLINK_BIG_ENDIAN 0 +#define MAVLINK_LITTLE_ENDIAN 1 + +#endif /* MAVLINK_TYPES_H_ */ diff --git a/mavlink/include/mavlink/v0.9/minimal/mavlink.h b/mavlink/include/mavlink/v0.9/minimal/mavlink.h new file mode 100644 index 0000000000..3f1c8b4295 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/minimal/mavlink.h @@ -0,0 +1,27 @@ +/** @file + * @brief MAVLink comm protocol built from minimal.xml + * @see http://pixhawk.ethz.ch/software/mavlink + */ +#ifndef MAVLINK_H +#define MAVLINK_H + +#ifndef MAVLINK_STX +#define MAVLINK_STX 85 +#endif + +#ifndef MAVLINK_ENDIAN +#define MAVLINK_ENDIAN MAVLINK_BIG_ENDIAN +#endif + +#ifndef MAVLINK_ALIGNED_FIELDS +#define MAVLINK_ALIGNED_FIELDS 0 +#endif + +#ifndef MAVLINK_CRC_EXTRA +#define MAVLINK_CRC_EXTRA 0 +#endif + +#include "version.h" +#include "minimal.h" + +#endif // MAVLINK_H diff --git a/mavlink/include/mavlink/v0.9/minimal/mavlink_msg_heartbeat.h b/mavlink/include/mavlink/v0.9/minimal/mavlink_msg_heartbeat.h new file mode 100644 index 0000000000..aad90d29f3 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/minimal/mavlink_msg_heartbeat.h @@ -0,0 +1,185 @@ +// MESSAGE HEARTBEAT PACKING + +#define MAVLINK_MSG_ID_HEARTBEAT 0 + +typedef struct __mavlink_heartbeat_t +{ + uint8_t type; ///< Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + uint8_t autopilot; ///< Type of the Autopilot: 0: Generic, 1: PIXHAWK, 2: SLUGS, 3: Ardupilot (up to 15 types), defined in MAV_AUTOPILOT_TYPE ENUM + uint8_t mavlink_version; ///< MAVLink version +} mavlink_heartbeat_t; + +#define MAVLINK_MSG_ID_HEARTBEAT_LEN 3 +#define MAVLINK_MSG_ID_0_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_HEARTBEAT { \ + "HEARTBEAT", \ + 3, \ + { { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_heartbeat_t, type) }, \ + { "autopilot", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_heartbeat_t, autopilot) }, \ + { "mavlink_version", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_heartbeat_t, mavlink_version) }, \ + } \ +} + + +/** + * @brief Pack a heartbeat message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + * @param autopilot Type of the Autopilot: 0: Generic, 1: PIXHAWK, 2: SLUGS, 3: Ardupilot (up to 15 types), defined in MAV_AUTOPILOT_TYPE ENUM + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_heartbeat_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t type, uint8_t autopilot) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint8_t(buf, 1, autopilot); + _mav_put_uint8_t(buf, 2, 2); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_heartbeat_t packet; + packet.type = type; + packet.autopilot = autopilot; + packet.mavlink_version = 2; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_HEARTBEAT; + return mavlink_finalize_message(msg, system_id, component_id, 3); +} + +/** + * @brief Pack a heartbeat message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + * @param autopilot Type of the Autopilot: 0: Generic, 1: PIXHAWK, 2: SLUGS, 3: Ardupilot (up to 15 types), defined in MAV_AUTOPILOT_TYPE ENUM + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_heartbeat_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t type,uint8_t autopilot) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint8_t(buf, 1, autopilot); + _mav_put_uint8_t(buf, 2, 2); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_heartbeat_t packet; + packet.type = type; + packet.autopilot = autopilot; + packet.mavlink_version = 2; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_HEARTBEAT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3); +} + +/** + * @brief Encode a heartbeat struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param heartbeat C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_heartbeat_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_heartbeat_t* heartbeat) +{ + return mavlink_msg_heartbeat_pack(system_id, component_id, msg, heartbeat->type, heartbeat->autopilot); +} + +/** + * @brief Send a heartbeat message + * @param chan MAVLink channel to send the message + * + * @param type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + * @param autopilot Type of the Autopilot: 0: Generic, 1: PIXHAWK, 2: SLUGS, 3: Ardupilot (up to 15 types), defined in MAV_AUTOPILOT_TYPE ENUM + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_heartbeat_send(mavlink_channel_t chan, uint8_t type, uint8_t autopilot) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint8_t(buf, 1, autopilot); + _mav_put_uint8_t(buf, 2, 2); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HEARTBEAT, buf, 3); +#else + mavlink_heartbeat_t packet; + packet.type = type; + packet.autopilot = autopilot; + packet.mavlink_version = 2; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HEARTBEAT, (const char *)&packet, 3); +#endif +} + +#endif + +// MESSAGE HEARTBEAT UNPACKING + + +/** + * @brief Get field type from heartbeat message + * + * @return Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + */ +static inline uint8_t mavlink_msg_heartbeat_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field autopilot from heartbeat message + * + * @return Type of the Autopilot: 0: Generic, 1: PIXHAWK, 2: SLUGS, 3: Ardupilot (up to 15 types), defined in MAV_AUTOPILOT_TYPE ENUM + */ +static inline uint8_t mavlink_msg_heartbeat_get_autopilot(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field mavlink_version from heartbeat message + * + * @return MAVLink version + */ +static inline uint8_t mavlink_msg_heartbeat_get_mavlink_version(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a heartbeat message into a struct + * + * @param msg The message to decode + * @param heartbeat C-struct to decode the message contents into + */ +static inline void mavlink_msg_heartbeat_decode(const mavlink_message_t* msg, mavlink_heartbeat_t* heartbeat) +{ +#if MAVLINK_NEED_BYTE_SWAP + heartbeat->type = mavlink_msg_heartbeat_get_type(msg); + heartbeat->autopilot = mavlink_msg_heartbeat_get_autopilot(msg); + heartbeat->mavlink_version = mavlink_msg_heartbeat_get_mavlink_version(msg); +#else + memcpy(heartbeat, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/minimal/minimal.h b/mavlink/include/mavlink/v0.9/minimal/minimal.h new file mode 100644 index 0000000000..5979f806b8 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/minimal/minimal.h @@ -0,0 +1,53 @@ +/** @file + * @brief MAVLink comm protocol generated from minimal.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef MINIMAL_H +#define MINIMAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_MINIMAL + + + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +// ENUM DEFINITIONS + + + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_heartbeat.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // MINIMAL_H diff --git a/mavlink/include/mavlink/v0.9/minimal/testsuite.h b/mavlink/include/mavlink/v0.9/minimal/testsuite.h new file mode 100644 index 0000000000..be1d5ed6dd --- /dev/null +++ b/mavlink/include/mavlink/v0.9/minimal/testsuite.h @@ -0,0 +1,82 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from minimal.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef MINIMAL_TESTSUITE_H +#define MINIMAL_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL + +static void mavlink_test_minimal(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + + mavlink_test_minimal(system_id, component_id, last_msg); +} +#endif + + + + +static void mavlink_test_heartbeat(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_heartbeat_t packet_in = { + 5, + 72, + 2, + }; + mavlink_heartbeat_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.type = packet_in.type; + packet1.autopilot = packet_in.autopilot; + packet1.mavlink_version = packet_in.mavlink_version; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_heartbeat_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_heartbeat_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_heartbeat_pack(system_id, component_id, &msg , packet1.type , packet1.autopilot ); + mavlink_msg_heartbeat_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_heartbeat_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.type , packet1.autopilot ); + mavlink_msg_heartbeat_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; imsgid = MAVLINK_MSG_ID_ATTITUDE_CONTROL; + return mavlink_finalize_message(msg, system_id, component_id, 21); +} + +/** + * @brief Pack a attitude_control message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system to be controlled + * @param roll roll + * @param pitch pitch + * @param yaw yaw + * @param thrust thrust + * @param roll_manual roll control enabled auto:0, manual:1 + * @param pitch_manual pitch auto:0, manual:1 + * @param yaw_manual yaw auto:0, manual:1 + * @param thrust_manual thrust auto:0, manual:1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_attitude_control_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,float roll,float pitch,float yaw,float thrust,uint8_t roll_manual,uint8_t pitch_manual,uint8_t yaw_manual,uint8_t thrust_manual) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_float(buf, 1, roll); + _mav_put_float(buf, 5, pitch); + _mav_put_float(buf, 9, yaw); + _mav_put_float(buf, 13, thrust); + _mav_put_uint8_t(buf, 17, roll_manual); + _mav_put_uint8_t(buf, 18, pitch_manual); + _mav_put_uint8_t(buf, 19, yaw_manual); + _mav_put_uint8_t(buf, 20, thrust_manual); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 21); +#else + mavlink_attitude_control_t packet; + packet.target = target; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + packet.roll_manual = roll_manual; + packet.pitch_manual = pitch_manual; + packet.yaw_manual = yaw_manual; + packet.thrust_manual = thrust_manual; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 21); +#endif + + msg->msgid = MAVLINK_MSG_ID_ATTITUDE_CONTROL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 21); +} + +/** + * @brief Encode a attitude_control struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param attitude_control C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_attitude_control_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_attitude_control_t* attitude_control) +{ + return mavlink_msg_attitude_control_pack(system_id, component_id, msg, attitude_control->target, attitude_control->roll, attitude_control->pitch, attitude_control->yaw, attitude_control->thrust, attitude_control->roll_manual, attitude_control->pitch_manual, attitude_control->yaw_manual, attitude_control->thrust_manual); +} + +/** + * @brief Send a attitude_control message + * @param chan MAVLink channel to send the message + * + * @param target The system to be controlled + * @param roll roll + * @param pitch pitch + * @param yaw yaw + * @param thrust thrust + * @param roll_manual roll control enabled auto:0, manual:1 + * @param pitch_manual pitch auto:0, manual:1 + * @param yaw_manual yaw auto:0, manual:1 + * @param thrust_manual thrust auto:0, manual:1 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_attitude_control_send(mavlink_channel_t chan, uint8_t target, float roll, float pitch, float yaw, float thrust, uint8_t roll_manual, uint8_t pitch_manual, uint8_t yaw_manual, uint8_t thrust_manual) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_float(buf, 1, roll); + _mav_put_float(buf, 5, pitch); + _mav_put_float(buf, 9, yaw); + _mav_put_float(buf, 13, thrust); + _mav_put_uint8_t(buf, 17, roll_manual); + _mav_put_uint8_t(buf, 18, pitch_manual); + _mav_put_uint8_t(buf, 19, yaw_manual); + _mav_put_uint8_t(buf, 20, thrust_manual); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ATTITUDE_CONTROL, buf, 21); +#else + mavlink_attitude_control_t packet; + packet.target = target; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + packet.roll_manual = roll_manual; + packet.pitch_manual = pitch_manual; + packet.yaw_manual = yaw_manual; + packet.thrust_manual = thrust_manual; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ATTITUDE_CONTROL, (const char *)&packet, 21); +#endif +} + +#endif + +// MESSAGE ATTITUDE_CONTROL UNPACKING + + +/** + * @brief Get field target from attitude_control message + * + * @return The system to be controlled + */ +static inline uint8_t mavlink_msg_attitude_control_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field roll from attitude_control message + * + * @return roll + */ +static inline float mavlink_msg_attitude_control_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 1); +} + +/** + * @brief Get field pitch from attitude_control message + * + * @return pitch + */ +static inline float mavlink_msg_attitude_control_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 5); +} + +/** + * @brief Get field yaw from attitude_control message + * + * @return yaw + */ +static inline float mavlink_msg_attitude_control_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 9); +} + +/** + * @brief Get field thrust from attitude_control message + * + * @return thrust + */ +static inline float mavlink_msg_attitude_control_get_thrust(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 13); +} + +/** + * @brief Get field roll_manual from attitude_control message + * + * @return roll control enabled auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_attitude_control_get_roll_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 17); +} + +/** + * @brief Get field pitch_manual from attitude_control message + * + * @return pitch auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_attitude_control_get_pitch_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 18); +} + +/** + * @brief Get field yaw_manual from attitude_control message + * + * @return yaw auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_attitude_control_get_yaw_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 19); +} + +/** + * @brief Get field thrust_manual from attitude_control message + * + * @return thrust auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_attitude_control_get_thrust_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 20); +} + +/** + * @brief Decode a attitude_control message into a struct + * + * @param msg The message to decode + * @param attitude_control C-struct to decode the message contents into + */ +static inline void mavlink_msg_attitude_control_decode(const mavlink_message_t* msg, mavlink_attitude_control_t* attitude_control) +{ +#if MAVLINK_NEED_BYTE_SWAP + attitude_control->target = mavlink_msg_attitude_control_get_target(msg); + attitude_control->roll = mavlink_msg_attitude_control_get_roll(msg); + attitude_control->pitch = mavlink_msg_attitude_control_get_pitch(msg); + attitude_control->yaw = mavlink_msg_attitude_control_get_yaw(msg); + attitude_control->thrust = mavlink_msg_attitude_control_get_thrust(msg); + attitude_control->roll_manual = mavlink_msg_attitude_control_get_roll_manual(msg); + attitude_control->pitch_manual = mavlink_msg_attitude_control_get_pitch_manual(msg); + attitude_control->yaw_manual = mavlink_msg_attitude_control_get_yaw_manual(msg); + attitude_control->thrust_manual = mavlink_msg_attitude_control_get_thrust_manual(msg); +#else + memcpy(attitude_control, _MAV_PAYLOAD(msg), 21); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_brief_feature.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_brief_feature.h new file mode 100644 index 0000000000..866d1be44e --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_brief_feature.h @@ -0,0 +1,292 @@ +// MESSAGE BRIEF_FEATURE PACKING + +#define MAVLINK_MSG_ID_BRIEF_FEATURE 195 + +typedef struct __mavlink_brief_feature_t +{ + float x; ///< x position in m + float y; ///< y position in m + float z; ///< z position in m + uint8_t orientation_assignment; ///< Orientation assignment 0: false, 1:true + uint16_t size; ///< Size in pixels + uint16_t orientation; ///< Orientation + uint8_t descriptor[32]; ///< Descriptor + float response; ///< Harris operator response at this location +} mavlink_brief_feature_t; + +#define MAVLINK_MSG_ID_BRIEF_FEATURE_LEN 53 +#define MAVLINK_MSG_ID_195_LEN 53 + +#define MAVLINK_MSG_BRIEF_FEATURE_FIELD_DESCRIPTOR_LEN 32 + +#define MAVLINK_MESSAGE_INFO_BRIEF_FEATURE { \ + "BRIEF_FEATURE", \ + 8, \ + { { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_brief_feature_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_brief_feature_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_brief_feature_t, z) }, \ + { "orientation_assignment", NULL, MAVLINK_TYPE_UINT8_T, 0, 12, offsetof(mavlink_brief_feature_t, orientation_assignment) }, \ + { "size", NULL, MAVLINK_TYPE_UINT16_T, 0, 13, offsetof(mavlink_brief_feature_t, size) }, \ + { "orientation", NULL, MAVLINK_TYPE_UINT16_T, 0, 15, offsetof(mavlink_brief_feature_t, orientation) }, \ + { "descriptor", NULL, MAVLINK_TYPE_UINT8_T, 32, 17, offsetof(mavlink_brief_feature_t, descriptor) }, \ + { "response", NULL, MAVLINK_TYPE_FLOAT, 0, 49, offsetof(mavlink_brief_feature_t, response) }, \ + } \ +} + + +/** + * @brief Pack a brief_feature message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param x x position in m + * @param y y position in m + * @param z z position in m + * @param orientation_assignment Orientation assignment 0: false, 1:true + * @param size Size in pixels + * @param orientation Orientation + * @param descriptor Descriptor + * @param response Harris operator response at this location + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_brief_feature_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float x, float y, float z, uint8_t orientation_assignment, uint16_t size, uint16_t orientation, const uint8_t *descriptor, float response) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[53]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_uint8_t(buf, 12, orientation_assignment); + _mav_put_uint16_t(buf, 13, size); + _mav_put_uint16_t(buf, 15, orientation); + _mav_put_float(buf, 49, response); + _mav_put_uint8_t_array(buf, 17, descriptor, 32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 53); +#else + mavlink_brief_feature_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.orientation_assignment = orientation_assignment; + packet.size = size; + packet.orientation = orientation; + packet.response = response; + mav_array_memcpy(packet.descriptor, descriptor, sizeof(uint8_t)*32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 53); +#endif + + msg->msgid = MAVLINK_MSG_ID_BRIEF_FEATURE; + return mavlink_finalize_message(msg, system_id, component_id, 53); +} + +/** + * @brief Pack a brief_feature message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param x x position in m + * @param y y position in m + * @param z z position in m + * @param orientation_assignment Orientation assignment 0: false, 1:true + * @param size Size in pixels + * @param orientation Orientation + * @param descriptor Descriptor + * @param response Harris operator response at this location + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_brief_feature_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float x,float y,float z,uint8_t orientation_assignment,uint16_t size,uint16_t orientation,const uint8_t *descriptor,float response) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[53]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_uint8_t(buf, 12, orientation_assignment); + _mav_put_uint16_t(buf, 13, size); + _mav_put_uint16_t(buf, 15, orientation); + _mav_put_float(buf, 49, response); + _mav_put_uint8_t_array(buf, 17, descriptor, 32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 53); +#else + mavlink_brief_feature_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.orientation_assignment = orientation_assignment; + packet.size = size; + packet.orientation = orientation; + packet.response = response; + mav_array_memcpy(packet.descriptor, descriptor, sizeof(uint8_t)*32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 53); +#endif + + msg->msgid = MAVLINK_MSG_ID_BRIEF_FEATURE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 53); +} + +/** + * @brief Encode a brief_feature struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param brief_feature C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_brief_feature_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_brief_feature_t* brief_feature) +{ + return mavlink_msg_brief_feature_pack(system_id, component_id, msg, brief_feature->x, brief_feature->y, brief_feature->z, brief_feature->orientation_assignment, brief_feature->size, brief_feature->orientation, brief_feature->descriptor, brief_feature->response); +} + +/** + * @brief Send a brief_feature message + * @param chan MAVLink channel to send the message + * + * @param x x position in m + * @param y y position in m + * @param z z position in m + * @param orientation_assignment Orientation assignment 0: false, 1:true + * @param size Size in pixels + * @param orientation Orientation + * @param descriptor Descriptor + * @param response Harris operator response at this location + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_brief_feature_send(mavlink_channel_t chan, float x, float y, float z, uint8_t orientation_assignment, uint16_t size, uint16_t orientation, const uint8_t *descriptor, float response) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[53]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_uint8_t(buf, 12, orientation_assignment); + _mav_put_uint16_t(buf, 13, size); + _mav_put_uint16_t(buf, 15, orientation); + _mav_put_float(buf, 49, response); + _mav_put_uint8_t_array(buf, 17, descriptor, 32); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_BRIEF_FEATURE, buf, 53); +#else + mavlink_brief_feature_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.orientation_assignment = orientation_assignment; + packet.size = size; + packet.orientation = orientation; + packet.response = response; + mav_array_memcpy(packet.descriptor, descriptor, sizeof(uint8_t)*32); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_BRIEF_FEATURE, (const char *)&packet, 53); +#endif +} + +#endif + +// MESSAGE BRIEF_FEATURE UNPACKING + + +/** + * @brief Get field x from brief_feature message + * + * @return x position in m + */ +static inline float mavlink_msg_brief_feature_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field y from brief_feature message + * + * @return y position in m + */ +static inline float mavlink_msg_brief_feature_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field z from brief_feature message + * + * @return z position in m + */ +static inline float mavlink_msg_brief_feature_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field orientation_assignment from brief_feature message + * + * @return Orientation assignment 0: false, 1:true + */ +static inline uint8_t mavlink_msg_brief_feature_get_orientation_assignment(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 12); +} + +/** + * @brief Get field size from brief_feature message + * + * @return Size in pixels + */ +static inline uint16_t mavlink_msg_brief_feature_get_size(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 13); +} + +/** + * @brief Get field orientation from brief_feature message + * + * @return Orientation + */ +static inline uint16_t mavlink_msg_brief_feature_get_orientation(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 15); +} + +/** + * @brief Get field descriptor from brief_feature message + * + * @return Descriptor + */ +static inline uint16_t mavlink_msg_brief_feature_get_descriptor(const mavlink_message_t* msg, uint8_t *descriptor) +{ + return _MAV_RETURN_uint8_t_array(msg, descriptor, 32, 17); +} + +/** + * @brief Get field response from brief_feature message + * + * @return Harris operator response at this location + */ +static inline float mavlink_msg_brief_feature_get_response(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 49); +} + +/** + * @brief Decode a brief_feature message into a struct + * + * @param msg The message to decode + * @param brief_feature C-struct to decode the message contents into + */ +static inline void mavlink_msg_brief_feature_decode(const mavlink_message_t* msg, mavlink_brief_feature_t* brief_feature) +{ +#if MAVLINK_NEED_BYTE_SWAP + brief_feature->x = mavlink_msg_brief_feature_get_x(msg); + brief_feature->y = mavlink_msg_brief_feature_get_y(msg); + brief_feature->z = mavlink_msg_brief_feature_get_z(msg); + brief_feature->orientation_assignment = mavlink_msg_brief_feature_get_orientation_assignment(msg); + brief_feature->size = mavlink_msg_brief_feature_get_size(msg); + brief_feature->orientation = mavlink_msg_brief_feature_get_orientation(msg); + mavlink_msg_brief_feature_get_descriptor(msg, brief_feature->descriptor); + brief_feature->response = mavlink_msg_brief_feature_get_response(msg); +#else + memcpy(brief_feature, _MAV_PAYLOAD(msg), 53); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_data_transmission_handshake.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_data_transmission_handshake.h new file mode 100644 index 0000000000..9c0d75a9a1 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_data_transmission_handshake.h @@ -0,0 +1,232 @@ +// MESSAGE DATA_TRANSMISSION_HANDSHAKE PACKING + +#define MAVLINK_MSG_ID_DATA_TRANSMISSION_HANDSHAKE 193 + +typedef struct __mavlink_data_transmission_handshake_t +{ + uint8_t type; ///< type of requested/acknowledged data (as defined in ENUM DATA_TYPES in mavlink/include/mavlink_types.h) + uint32_t size; ///< total data size in bytes (set on ACK only) + uint8_t packets; ///< number of packets beeing sent (set on ACK only) + uint8_t payload; ///< payload size per packet (normally 253 byte, see DATA field size in message ENCAPSULATED_DATA) (set on ACK only) + uint8_t jpg_quality; ///< JPEG quality out of [1,100] +} mavlink_data_transmission_handshake_t; + +#define MAVLINK_MSG_ID_DATA_TRANSMISSION_HANDSHAKE_LEN 8 +#define MAVLINK_MSG_ID_193_LEN 8 + + + +#define MAVLINK_MESSAGE_INFO_DATA_TRANSMISSION_HANDSHAKE { \ + "DATA_TRANSMISSION_HANDSHAKE", \ + 5, \ + { { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_data_transmission_handshake_t, type) }, \ + { "size", NULL, MAVLINK_TYPE_UINT32_T, 0, 1, offsetof(mavlink_data_transmission_handshake_t, size) }, \ + { "packets", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_data_transmission_handshake_t, packets) }, \ + { "payload", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_data_transmission_handshake_t, payload) }, \ + { "jpg_quality", NULL, MAVLINK_TYPE_UINT8_T, 0, 7, offsetof(mavlink_data_transmission_handshake_t, jpg_quality) }, \ + } \ +} + + +/** + * @brief Pack a data_transmission_handshake message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param type type of requested/acknowledged data (as defined in ENUM DATA_TYPES in mavlink/include/mavlink_types.h) + * @param size total data size in bytes (set on ACK only) + * @param packets number of packets beeing sent (set on ACK only) + * @param payload payload size per packet (normally 253 byte, see DATA field size in message ENCAPSULATED_DATA) (set on ACK only) + * @param jpg_quality JPEG quality out of [1,100] + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_data_transmission_handshake_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t type, uint32_t size, uint8_t packets, uint8_t payload, uint8_t jpg_quality) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint32_t(buf, 1, size); + _mav_put_uint8_t(buf, 5, packets); + _mav_put_uint8_t(buf, 6, payload); + _mav_put_uint8_t(buf, 7, jpg_quality); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_data_transmission_handshake_t packet; + packet.type = type; + packet.size = size; + packet.packets = packets; + packet.payload = payload; + packet.jpg_quality = jpg_quality; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_DATA_TRANSMISSION_HANDSHAKE; + return mavlink_finalize_message(msg, system_id, component_id, 8); +} + +/** + * @brief Pack a data_transmission_handshake message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param type type of requested/acknowledged data (as defined in ENUM DATA_TYPES in mavlink/include/mavlink_types.h) + * @param size total data size in bytes (set on ACK only) + * @param packets number of packets beeing sent (set on ACK only) + * @param payload payload size per packet (normally 253 byte, see DATA field size in message ENCAPSULATED_DATA) (set on ACK only) + * @param jpg_quality JPEG quality out of [1,100] + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_data_transmission_handshake_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t type,uint32_t size,uint8_t packets,uint8_t payload,uint8_t jpg_quality) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint32_t(buf, 1, size); + _mav_put_uint8_t(buf, 5, packets); + _mav_put_uint8_t(buf, 6, payload); + _mav_put_uint8_t(buf, 7, jpg_quality); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_data_transmission_handshake_t packet; + packet.type = type; + packet.size = size; + packet.packets = packets; + packet.payload = payload; + packet.jpg_quality = jpg_quality; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_DATA_TRANSMISSION_HANDSHAKE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 8); +} + +/** + * @brief Encode a data_transmission_handshake struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param data_transmission_handshake C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_data_transmission_handshake_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_data_transmission_handshake_t* data_transmission_handshake) +{ + return mavlink_msg_data_transmission_handshake_pack(system_id, component_id, msg, data_transmission_handshake->type, data_transmission_handshake->size, data_transmission_handshake->packets, data_transmission_handshake->payload, data_transmission_handshake->jpg_quality); +} + +/** + * @brief Send a data_transmission_handshake message + * @param chan MAVLink channel to send the message + * + * @param type type of requested/acknowledged data (as defined in ENUM DATA_TYPES in mavlink/include/mavlink_types.h) + * @param size total data size in bytes (set on ACK only) + * @param packets number of packets beeing sent (set on ACK only) + * @param payload payload size per packet (normally 253 byte, see DATA field size in message ENCAPSULATED_DATA) (set on ACK only) + * @param jpg_quality JPEG quality out of [1,100] + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_data_transmission_handshake_send(mavlink_channel_t chan, uint8_t type, uint32_t size, uint8_t packets, uint8_t payload, uint8_t jpg_quality) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint32_t(buf, 1, size); + _mav_put_uint8_t(buf, 5, packets); + _mav_put_uint8_t(buf, 6, payload); + _mav_put_uint8_t(buf, 7, jpg_quality); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DATA_TRANSMISSION_HANDSHAKE, buf, 8); +#else + mavlink_data_transmission_handshake_t packet; + packet.type = type; + packet.size = size; + packet.packets = packets; + packet.payload = payload; + packet.jpg_quality = jpg_quality; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DATA_TRANSMISSION_HANDSHAKE, (const char *)&packet, 8); +#endif +} + +#endif + +// MESSAGE DATA_TRANSMISSION_HANDSHAKE UNPACKING + + +/** + * @brief Get field type from data_transmission_handshake message + * + * @return type of requested/acknowledged data (as defined in ENUM DATA_TYPES in mavlink/include/mavlink_types.h) + */ +static inline uint8_t mavlink_msg_data_transmission_handshake_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field size from data_transmission_handshake message + * + * @return total data size in bytes (set on ACK only) + */ +static inline uint32_t mavlink_msg_data_transmission_handshake_get_size(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 1); +} + +/** + * @brief Get field packets from data_transmission_handshake message + * + * @return number of packets beeing sent (set on ACK only) + */ +static inline uint8_t mavlink_msg_data_transmission_handshake_get_packets(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field payload from data_transmission_handshake message + * + * @return payload size per packet (normally 253 byte, see DATA field size in message ENCAPSULATED_DATA) (set on ACK only) + */ +static inline uint8_t mavlink_msg_data_transmission_handshake_get_payload(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Get field jpg_quality from data_transmission_handshake message + * + * @return JPEG quality out of [1,100] + */ +static inline uint8_t mavlink_msg_data_transmission_handshake_get_jpg_quality(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 7); +} + +/** + * @brief Decode a data_transmission_handshake message into a struct + * + * @param msg The message to decode + * @param data_transmission_handshake C-struct to decode the message contents into + */ +static inline void mavlink_msg_data_transmission_handshake_decode(const mavlink_message_t* msg, mavlink_data_transmission_handshake_t* data_transmission_handshake) +{ +#if MAVLINK_NEED_BYTE_SWAP + data_transmission_handshake->type = mavlink_msg_data_transmission_handshake_get_type(msg); + data_transmission_handshake->size = mavlink_msg_data_transmission_handshake_get_size(msg); + data_transmission_handshake->packets = mavlink_msg_data_transmission_handshake_get_packets(msg); + data_transmission_handshake->payload = mavlink_msg_data_transmission_handshake_get_payload(msg); + data_transmission_handshake->jpg_quality = mavlink_msg_data_transmission_handshake_get_jpg_quality(msg); +#else + memcpy(data_transmission_handshake, _MAV_PAYLOAD(msg), 8); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_encapsulated_data.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_encapsulated_data.h new file mode 100644 index 0000000000..705a6cc29d --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_encapsulated_data.h @@ -0,0 +1,160 @@ +// MESSAGE ENCAPSULATED_DATA PACKING + +#define MAVLINK_MSG_ID_ENCAPSULATED_DATA 194 + +typedef struct __mavlink_encapsulated_data_t +{ + uint16_t seqnr; ///< sequence number (starting with 0 on every transmission) + uint8_t data[253]; ///< image data bytes +} mavlink_encapsulated_data_t; + +#define MAVLINK_MSG_ID_ENCAPSULATED_DATA_LEN 255 +#define MAVLINK_MSG_ID_194_LEN 255 + +#define MAVLINK_MSG_ENCAPSULATED_DATA_FIELD_DATA_LEN 253 + +#define MAVLINK_MESSAGE_INFO_ENCAPSULATED_DATA { \ + "ENCAPSULATED_DATA", \ + 2, \ + { { "seqnr", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_encapsulated_data_t, seqnr) }, \ + { "data", NULL, MAVLINK_TYPE_UINT8_T, 253, 2, offsetof(mavlink_encapsulated_data_t, data) }, \ + } \ +} + + +/** + * @brief Pack a encapsulated_data message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param seqnr sequence number (starting with 0 on every transmission) + * @param data image data bytes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_encapsulated_data_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t seqnr, const uint8_t *data) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[255]; + _mav_put_uint16_t(buf, 0, seqnr); + _mav_put_uint8_t_array(buf, 2, data, 253); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 255); +#else + mavlink_encapsulated_data_t packet; + packet.seqnr = seqnr; + mav_array_memcpy(packet.data, data, sizeof(uint8_t)*253); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 255); +#endif + + msg->msgid = MAVLINK_MSG_ID_ENCAPSULATED_DATA; + return mavlink_finalize_message(msg, system_id, component_id, 255); +} + +/** + * @brief Pack a encapsulated_data message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param seqnr sequence number (starting with 0 on every transmission) + * @param data image data bytes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_encapsulated_data_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t seqnr,const uint8_t *data) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[255]; + _mav_put_uint16_t(buf, 0, seqnr); + _mav_put_uint8_t_array(buf, 2, data, 253); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 255); +#else + mavlink_encapsulated_data_t packet; + packet.seqnr = seqnr; + mav_array_memcpy(packet.data, data, sizeof(uint8_t)*253); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 255); +#endif + + msg->msgid = MAVLINK_MSG_ID_ENCAPSULATED_DATA; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 255); +} + +/** + * @brief Encode a encapsulated_data struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param encapsulated_data C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_encapsulated_data_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_encapsulated_data_t* encapsulated_data) +{ + return mavlink_msg_encapsulated_data_pack(system_id, component_id, msg, encapsulated_data->seqnr, encapsulated_data->data); +} + +/** + * @brief Send a encapsulated_data message + * @param chan MAVLink channel to send the message + * + * @param seqnr sequence number (starting with 0 on every transmission) + * @param data image data bytes + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_encapsulated_data_send(mavlink_channel_t chan, uint16_t seqnr, const uint8_t *data) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[255]; + _mav_put_uint16_t(buf, 0, seqnr); + _mav_put_uint8_t_array(buf, 2, data, 253); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ENCAPSULATED_DATA, buf, 255); +#else + mavlink_encapsulated_data_t packet; + packet.seqnr = seqnr; + mav_array_memcpy(packet.data, data, sizeof(uint8_t)*253); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ENCAPSULATED_DATA, (const char *)&packet, 255); +#endif +} + +#endif + +// MESSAGE ENCAPSULATED_DATA UNPACKING + + +/** + * @brief Get field seqnr from encapsulated_data message + * + * @return sequence number (starting with 0 on every transmission) + */ +static inline uint16_t mavlink_msg_encapsulated_data_get_seqnr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field data from encapsulated_data message + * + * @return image data bytes + */ +static inline uint16_t mavlink_msg_encapsulated_data_get_data(const mavlink_message_t* msg, uint8_t *data) +{ + return _MAV_RETURN_uint8_t_array(msg, data, 253, 2); +} + +/** + * @brief Decode a encapsulated_data message into a struct + * + * @param msg The message to decode + * @param encapsulated_data C-struct to decode the message contents into + */ +static inline void mavlink_msg_encapsulated_data_decode(const mavlink_message_t* msg, mavlink_encapsulated_data_t* encapsulated_data) +{ +#if MAVLINK_NEED_BYTE_SWAP + encapsulated_data->seqnr = mavlink_msg_encapsulated_data_get_seqnr(msg); + mavlink_msg_encapsulated_data_get_data(msg, encapsulated_data->data); +#else + memcpy(encapsulated_data, _MAV_PAYLOAD(msg), 255); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_image_available.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_image_available.h new file mode 100644 index 0000000000..40d1901c69 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_image_available.h @@ -0,0 +1,628 @@ +// MESSAGE IMAGE_AVAILABLE PACKING + +#define MAVLINK_MSG_ID_IMAGE_AVAILABLE 154 + +typedef struct __mavlink_image_available_t +{ + uint64_t cam_id; ///< Camera id + uint8_t cam_no; ///< Camera # (starts with 0) + uint64_t timestamp; ///< Timestamp + uint64_t valid_until; ///< Until which timestamp this buffer will stay valid + uint32_t img_seq; ///< The image sequence number + uint32_t img_buf_index; ///< Position of the image in the buffer, starts with 0 + uint16_t width; ///< Image width + uint16_t height; ///< Image height + uint16_t depth; ///< Image depth + uint8_t channels; ///< Image channels + uint32_t key; ///< Shared memory area key + uint32_t exposure; ///< Exposure time, in microseconds + float gain; ///< Camera gain + float roll; ///< Roll angle in rad + float pitch; ///< Pitch angle in rad + float yaw; ///< Yaw angle in rad + float local_z; ///< Local frame Z coordinate (height over ground) + float lat; ///< GPS X coordinate + float lon; ///< GPS Y coordinate + float alt; ///< Global frame altitude + float ground_x; ///< Ground truth X + float ground_y; ///< Ground truth Y + float ground_z; ///< Ground truth Z +} mavlink_image_available_t; + +#define MAVLINK_MSG_ID_IMAGE_AVAILABLE_LEN 92 +#define MAVLINK_MSG_ID_154_LEN 92 + + + +#define MAVLINK_MESSAGE_INFO_IMAGE_AVAILABLE { \ + "IMAGE_AVAILABLE", \ + 23, \ + { { "cam_id", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_image_available_t, cam_id) }, \ + { "cam_no", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_image_available_t, cam_no) }, \ + { "timestamp", NULL, MAVLINK_TYPE_UINT64_T, 0, 9, offsetof(mavlink_image_available_t, timestamp) }, \ + { "valid_until", NULL, MAVLINK_TYPE_UINT64_T, 0, 17, offsetof(mavlink_image_available_t, valid_until) }, \ + { "img_seq", NULL, MAVLINK_TYPE_UINT32_T, 0, 25, offsetof(mavlink_image_available_t, img_seq) }, \ + { "img_buf_index", NULL, MAVLINK_TYPE_UINT32_T, 0, 29, offsetof(mavlink_image_available_t, img_buf_index) }, \ + { "width", NULL, MAVLINK_TYPE_UINT16_T, 0, 33, offsetof(mavlink_image_available_t, width) }, \ + { "height", NULL, MAVLINK_TYPE_UINT16_T, 0, 35, offsetof(mavlink_image_available_t, height) }, \ + { "depth", NULL, MAVLINK_TYPE_UINT16_T, 0, 37, offsetof(mavlink_image_available_t, depth) }, \ + { "channels", NULL, MAVLINK_TYPE_UINT8_T, 0, 39, offsetof(mavlink_image_available_t, channels) }, \ + { "key", NULL, MAVLINK_TYPE_UINT32_T, 0, 40, offsetof(mavlink_image_available_t, key) }, \ + { "exposure", NULL, MAVLINK_TYPE_UINT32_T, 0, 44, offsetof(mavlink_image_available_t, exposure) }, \ + { "gain", NULL, MAVLINK_TYPE_FLOAT, 0, 48, offsetof(mavlink_image_available_t, gain) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 52, offsetof(mavlink_image_available_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 56, offsetof(mavlink_image_available_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 60, offsetof(mavlink_image_available_t, yaw) }, \ + { "local_z", NULL, MAVLINK_TYPE_FLOAT, 0, 64, offsetof(mavlink_image_available_t, local_z) }, \ + { "lat", NULL, MAVLINK_TYPE_FLOAT, 0, 68, offsetof(mavlink_image_available_t, lat) }, \ + { "lon", NULL, MAVLINK_TYPE_FLOAT, 0, 72, offsetof(mavlink_image_available_t, lon) }, \ + { "alt", NULL, MAVLINK_TYPE_FLOAT, 0, 76, offsetof(mavlink_image_available_t, alt) }, \ + { "ground_x", NULL, MAVLINK_TYPE_FLOAT, 0, 80, offsetof(mavlink_image_available_t, ground_x) }, \ + { "ground_y", NULL, MAVLINK_TYPE_FLOAT, 0, 84, offsetof(mavlink_image_available_t, ground_y) }, \ + { "ground_z", NULL, MAVLINK_TYPE_FLOAT, 0, 88, offsetof(mavlink_image_available_t, ground_z) }, \ + } \ +} + + +/** + * @brief Pack a image_available message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param cam_id Camera id + * @param cam_no Camera # (starts with 0) + * @param timestamp Timestamp + * @param valid_until Until which timestamp this buffer will stay valid + * @param img_seq The image sequence number + * @param img_buf_index Position of the image in the buffer, starts with 0 + * @param width Image width + * @param height Image height + * @param depth Image depth + * @param channels Image channels + * @param key Shared memory area key + * @param exposure Exposure time, in microseconds + * @param gain Camera gain + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @param local_z Local frame Z coordinate (height over ground) + * @param lat GPS X coordinate + * @param lon GPS Y coordinate + * @param alt Global frame altitude + * @param ground_x Ground truth X + * @param ground_y Ground truth Y + * @param ground_z Ground truth Z + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_image_available_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t cam_id, uint8_t cam_no, uint64_t timestamp, uint64_t valid_until, uint32_t img_seq, uint32_t img_buf_index, uint16_t width, uint16_t height, uint16_t depth, uint8_t channels, uint32_t key, uint32_t exposure, float gain, float roll, float pitch, float yaw, float local_z, float lat, float lon, float alt, float ground_x, float ground_y, float ground_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[92]; + _mav_put_uint64_t(buf, 0, cam_id); + _mav_put_uint8_t(buf, 8, cam_no); + _mav_put_uint64_t(buf, 9, timestamp); + _mav_put_uint64_t(buf, 17, valid_until); + _mav_put_uint32_t(buf, 25, img_seq); + _mav_put_uint32_t(buf, 29, img_buf_index); + _mav_put_uint16_t(buf, 33, width); + _mav_put_uint16_t(buf, 35, height); + _mav_put_uint16_t(buf, 37, depth); + _mav_put_uint8_t(buf, 39, channels); + _mav_put_uint32_t(buf, 40, key); + _mav_put_uint32_t(buf, 44, exposure); + _mav_put_float(buf, 48, gain); + _mav_put_float(buf, 52, roll); + _mav_put_float(buf, 56, pitch); + _mav_put_float(buf, 60, yaw); + _mav_put_float(buf, 64, local_z); + _mav_put_float(buf, 68, lat); + _mav_put_float(buf, 72, lon); + _mav_put_float(buf, 76, alt); + _mav_put_float(buf, 80, ground_x); + _mav_put_float(buf, 84, ground_y); + _mav_put_float(buf, 88, ground_z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 92); +#else + mavlink_image_available_t packet; + packet.cam_id = cam_id; + packet.cam_no = cam_no; + packet.timestamp = timestamp; + packet.valid_until = valid_until; + packet.img_seq = img_seq; + packet.img_buf_index = img_buf_index; + packet.width = width; + packet.height = height; + packet.depth = depth; + packet.channels = channels; + packet.key = key; + packet.exposure = exposure; + packet.gain = gain; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.local_z = local_z; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.ground_x = ground_x; + packet.ground_y = ground_y; + packet.ground_z = ground_z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 92); +#endif + + msg->msgid = MAVLINK_MSG_ID_IMAGE_AVAILABLE; + return mavlink_finalize_message(msg, system_id, component_id, 92); +} + +/** + * @brief Pack a image_available message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param cam_id Camera id + * @param cam_no Camera # (starts with 0) + * @param timestamp Timestamp + * @param valid_until Until which timestamp this buffer will stay valid + * @param img_seq The image sequence number + * @param img_buf_index Position of the image in the buffer, starts with 0 + * @param width Image width + * @param height Image height + * @param depth Image depth + * @param channels Image channels + * @param key Shared memory area key + * @param exposure Exposure time, in microseconds + * @param gain Camera gain + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @param local_z Local frame Z coordinate (height over ground) + * @param lat GPS X coordinate + * @param lon GPS Y coordinate + * @param alt Global frame altitude + * @param ground_x Ground truth X + * @param ground_y Ground truth Y + * @param ground_z Ground truth Z + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_image_available_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t cam_id,uint8_t cam_no,uint64_t timestamp,uint64_t valid_until,uint32_t img_seq,uint32_t img_buf_index,uint16_t width,uint16_t height,uint16_t depth,uint8_t channels,uint32_t key,uint32_t exposure,float gain,float roll,float pitch,float yaw,float local_z,float lat,float lon,float alt,float ground_x,float ground_y,float ground_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[92]; + _mav_put_uint64_t(buf, 0, cam_id); + _mav_put_uint8_t(buf, 8, cam_no); + _mav_put_uint64_t(buf, 9, timestamp); + _mav_put_uint64_t(buf, 17, valid_until); + _mav_put_uint32_t(buf, 25, img_seq); + _mav_put_uint32_t(buf, 29, img_buf_index); + _mav_put_uint16_t(buf, 33, width); + _mav_put_uint16_t(buf, 35, height); + _mav_put_uint16_t(buf, 37, depth); + _mav_put_uint8_t(buf, 39, channels); + _mav_put_uint32_t(buf, 40, key); + _mav_put_uint32_t(buf, 44, exposure); + _mav_put_float(buf, 48, gain); + _mav_put_float(buf, 52, roll); + _mav_put_float(buf, 56, pitch); + _mav_put_float(buf, 60, yaw); + _mav_put_float(buf, 64, local_z); + _mav_put_float(buf, 68, lat); + _mav_put_float(buf, 72, lon); + _mav_put_float(buf, 76, alt); + _mav_put_float(buf, 80, ground_x); + _mav_put_float(buf, 84, ground_y); + _mav_put_float(buf, 88, ground_z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 92); +#else + mavlink_image_available_t packet; + packet.cam_id = cam_id; + packet.cam_no = cam_no; + packet.timestamp = timestamp; + packet.valid_until = valid_until; + packet.img_seq = img_seq; + packet.img_buf_index = img_buf_index; + packet.width = width; + packet.height = height; + packet.depth = depth; + packet.channels = channels; + packet.key = key; + packet.exposure = exposure; + packet.gain = gain; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.local_z = local_z; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.ground_x = ground_x; + packet.ground_y = ground_y; + packet.ground_z = ground_z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 92); +#endif + + msg->msgid = MAVLINK_MSG_ID_IMAGE_AVAILABLE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 92); +} + +/** + * @brief Encode a image_available struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param image_available C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_image_available_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_image_available_t* image_available) +{ + return mavlink_msg_image_available_pack(system_id, component_id, msg, image_available->cam_id, image_available->cam_no, image_available->timestamp, image_available->valid_until, image_available->img_seq, image_available->img_buf_index, image_available->width, image_available->height, image_available->depth, image_available->channels, image_available->key, image_available->exposure, image_available->gain, image_available->roll, image_available->pitch, image_available->yaw, image_available->local_z, image_available->lat, image_available->lon, image_available->alt, image_available->ground_x, image_available->ground_y, image_available->ground_z); +} + +/** + * @brief Send a image_available message + * @param chan MAVLink channel to send the message + * + * @param cam_id Camera id + * @param cam_no Camera # (starts with 0) + * @param timestamp Timestamp + * @param valid_until Until which timestamp this buffer will stay valid + * @param img_seq The image sequence number + * @param img_buf_index Position of the image in the buffer, starts with 0 + * @param width Image width + * @param height Image height + * @param depth Image depth + * @param channels Image channels + * @param key Shared memory area key + * @param exposure Exposure time, in microseconds + * @param gain Camera gain + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @param local_z Local frame Z coordinate (height over ground) + * @param lat GPS X coordinate + * @param lon GPS Y coordinate + * @param alt Global frame altitude + * @param ground_x Ground truth X + * @param ground_y Ground truth Y + * @param ground_z Ground truth Z + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_image_available_send(mavlink_channel_t chan, uint64_t cam_id, uint8_t cam_no, uint64_t timestamp, uint64_t valid_until, uint32_t img_seq, uint32_t img_buf_index, uint16_t width, uint16_t height, uint16_t depth, uint8_t channels, uint32_t key, uint32_t exposure, float gain, float roll, float pitch, float yaw, float local_z, float lat, float lon, float alt, float ground_x, float ground_y, float ground_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[92]; + _mav_put_uint64_t(buf, 0, cam_id); + _mav_put_uint8_t(buf, 8, cam_no); + _mav_put_uint64_t(buf, 9, timestamp); + _mav_put_uint64_t(buf, 17, valid_until); + _mav_put_uint32_t(buf, 25, img_seq); + _mav_put_uint32_t(buf, 29, img_buf_index); + _mav_put_uint16_t(buf, 33, width); + _mav_put_uint16_t(buf, 35, height); + _mav_put_uint16_t(buf, 37, depth); + _mav_put_uint8_t(buf, 39, channels); + _mav_put_uint32_t(buf, 40, key); + _mav_put_uint32_t(buf, 44, exposure); + _mav_put_float(buf, 48, gain); + _mav_put_float(buf, 52, roll); + _mav_put_float(buf, 56, pitch); + _mav_put_float(buf, 60, yaw); + _mav_put_float(buf, 64, local_z); + _mav_put_float(buf, 68, lat); + _mav_put_float(buf, 72, lon); + _mav_put_float(buf, 76, alt); + _mav_put_float(buf, 80, ground_x); + _mav_put_float(buf, 84, ground_y); + _mav_put_float(buf, 88, ground_z); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_IMAGE_AVAILABLE, buf, 92); +#else + mavlink_image_available_t packet; + packet.cam_id = cam_id; + packet.cam_no = cam_no; + packet.timestamp = timestamp; + packet.valid_until = valid_until; + packet.img_seq = img_seq; + packet.img_buf_index = img_buf_index; + packet.width = width; + packet.height = height; + packet.depth = depth; + packet.channels = channels; + packet.key = key; + packet.exposure = exposure; + packet.gain = gain; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.local_z = local_z; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.ground_x = ground_x; + packet.ground_y = ground_y; + packet.ground_z = ground_z; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_IMAGE_AVAILABLE, (const char *)&packet, 92); +#endif +} + +#endif + +// MESSAGE IMAGE_AVAILABLE UNPACKING + + +/** + * @brief Get field cam_id from image_available message + * + * @return Camera id + */ +static inline uint64_t mavlink_msg_image_available_get_cam_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field cam_no from image_available message + * + * @return Camera # (starts with 0) + */ +static inline uint8_t mavlink_msg_image_available_get_cam_no(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Get field timestamp from image_available message + * + * @return Timestamp + */ +static inline uint64_t mavlink_msg_image_available_get_timestamp(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 9); +} + +/** + * @brief Get field valid_until from image_available message + * + * @return Until which timestamp this buffer will stay valid + */ +static inline uint64_t mavlink_msg_image_available_get_valid_until(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 17); +} + +/** + * @brief Get field img_seq from image_available message + * + * @return The image sequence number + */ +static inline uint32_t mavlink_msg_image_available_get_img_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 25); +} + +/** + * @brief Get field img_buf_index from image_available message + * + * @return Position of the image in the buffer, starts with 0 + */ +static inline uint32_t mavlink_msg_image_available_get_img_buf_index(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 29); +} + +/** + * @brief Get field width from image_available message + * + * @return Image width + */ +static inline uint16_t mavlink_msg_image_available_get_width(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 33); +} + +/** + * @brief Get field height from image_available message + * + * @return Image height + */ +static inline uint16_t mavlink_msg_image_available_get_height(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 35); +} + +/** + * @brief Get field depth from image_available message + * + * @return Image depth + */ +static inline uint16_t mavlink_msg_image_available_get_depth(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 37); +} + +/** + * @brief Get field channels from image_available message + * + * @return Image channels + */ +static inline uint8_t mavlink_msg_image_available_get_channels(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 39); +} + +/** + * @brief Get field key from image_available message + * + * @return Shared memory area key + */ +static inline uint32_t mavlink_msg_image_available_get_key(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 40); +} + +/** + * @brief Get field exposure from image_available message + * + * @return Exposure time, in microseconds + */ +static inline uint32_t mavlink_msg_image_available_get_exposure(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 44); +} + +/** + * @brief Get field gain from image_available message + * + * @return Camera gain + */ +static inline float mavlink_msg_image_available_get_gain(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 48); +} + +/** + * @brief Get field roll from image_available message + * + * @return Roll angle in rad + */ +static inline float mavlink_msg_image_available_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 52); +} + +/** + * @brief Get field pitch from image_available message + * + * @return Pitch angle in rad + */ +static inline float mavlink_msg_image_available_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 56); +} + +/** + * @brief Get field yaw from image_available message + * + * @return Yaw angle in rad + */ +static inline float mavlink_msg_image_available_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 60); +} + +/** + * @brief Get field local_z from image_available message + * + * @return Local frame Z coordinate (height over ground) + */ +static inline float mavlink_msg_image_available_get_local_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 64); +} + +/** + * @brief Get field lat from image_available message + * + * @return GPS X coordinate + */ +static inline float mavlink_msg_image_available_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 68); +} + +/** + * @brief Get field lon from image_available message + * + * @return GPS Y coordinate + */ +static inline float mavlink_msg_image_available_get_lon(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 72); +} + +/** + * @brief Get field alt from image_available message + * + * @return Global frame altitude + */ +static inline float mavlink_msg_image_available_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 76); +} + +/** + * @brief Get field ground_x from image_available message + * + * @return Ground truth X + */ +static inline float mavlink_msg_image_available_get_ground_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 80); +} + +/** + * @brief Get field ground_y from image_available message + * + * @return Ground truth Y + */ +static inline float mavlink_msg_image_available_get_ground_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 84); +} + +/** + * @brief Get field ground_z from image_available message + * + * @return Ground truth Z + */ +static inline float mavlink_msg_image_available_get_ground_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 88); +} + +/** + * @brief Decode a image_available message into a struct + * + * @param msg The message to decode + * @param image_available C-struct to decode the message contents into + */ +static inline void mavlink_msg_image_available_decode(const mavlink_message_t* msg, mavlink_image_available_t* image_available) +{ +#if MAVLINK_NEED_BYTE_SWAP + image_available->cam_id = mavlink_msg_image_available_get_cam_id(msg); + image_available->cam_no = mavlink_msg_image_available_get_cam_no(msg); + image_available->timestamp = mavlink_msg_image_available_get_timestamp(msg); + image_available->valid_until = mavlink_msg_image_available_get_valid_until(msg); + image_available->img_seq = mavlink_msg_image_available_get_img_seq(msg); + image_available->img_buf_index = mavlink_msg_image_available_get_img_buf_index(msg); + image_available->width = mavlink_msg_image_available_get_width(msg); + image_available->height = mavlink_msg_image_available_get_height(msg); + image_available->depth = mavlink_msg_image_available_get_depth(msg); + image_available->channels = mavlink_msg_image_available_get_channels(msg); + image_available->key = mavlink_msg_image_available_get_key(msg); + image_available->exposure = mavlink_msg_image_available_get_exposure(msg); + image_available->gain = mavlink_msg_image_available_get_gain(msg); + image_available->roll = mavlink_msg_image_available_get_roll(msg); + image_available->pitch = mavlink_msg_image_available_get_pitch(msg); + image_available->yaw = mavlink_msg_image_available_get_yaw(msg); + image_available->local_z = mavlink_msg_image_available_get_local_z(msg); + image_available->lat = mavlink_msg_image_available_get_lat(msg); + image_available->lon = mavlink_msg_image_available_get_lon(msg); + image_available->alt = mavlink_msg_image_available_get_alt(msg); + image_available->ground_x = mavlink_msg_image_available_get_ground_x(msg); + image_available->ground_y = mavlink_msg_image_available_get_ground_y(msg); + image_available->ground_z = mavlink_msg_image_available_get_ground_z(msg); +#else + memcpy(image_available, _MAV_PAYLOAD(msg), 92); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_image_trigger_control.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_image_trigger_control.h new file mode 100644 index 0000000000..36b280ec0d --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_image_trigger_control.h @@ -0,0 +1,144 @@ +// MESSAGE IMAGE_TRIGGER_CONTROL PACKING + +#define MAVLINK_MSG_ID_IMAGE_TRIGGER_CONTROL 153 + +typedef struct __mavlink_image_trigger_control_t +{ + uint8_t enable; ///< 0 to disable, 1 to enable +} mavlink_image_trigger_control_t; + +#define MAVLINK_MSG_ID_IMAGE_TRIGGER_CONTROL_LEN 1 +#define MAVLINK_MSG_ID_153_LEN 1 + + + +#define MAVLINK_MESSAGE_INFO_IMAGE_TRIGGER_CONTROL { \ + "IMAGE_TRIGGER_CONTROL", \ + 1, \ + { { "enable", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_image_trigger_control_t, enable) }, \ + } \ +} + + +/** + * @brief Pack a image_trigger_control message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param enable 0 to disable, 1 to enable + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_image_trigger_control_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t enable) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[1]; + _mav_put_uint8_t(buf, 0, enable); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 1); +#else + mavlink_image_trigger_control_t packet; + packet.enable = enable; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 1); +#endif + + msg->msgid = MAVLINK_MSG_ID_IMAGE_TRIGGER_CONTROL; + return mavlink_finalize_message(msg, system_id, component_id, 1); +} + +/** + * @brief Pack a image_trigger_control message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param enable 0 to disable, 1 to enable + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_image_trigger_control_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t enable) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[1]; + _mav_put_uint8_t(buf, 0, enable); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 1); +#else + mavlink_image_trigger_control_t packet; + packet.enable = enable; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 1); +#endif + + msg->msgid = MAVLINK_MSG_ID_IMAGE_TRIGGER_CONTROL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 1); +} + +/** + * @brief Encode a image_trigger_control struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param image_trigger_control C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_image_trigger_control_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_image_trigger_control_t* image_trigger_control) +{ + return mavlink_msg_image_trigger_control_pack(system_id, component_id, msg, image_trigger_control->enable); +} + +/** + * @brief Send a image_trigger_control message + * @param chan MAVLink channel to send the message + * + * @param enable 0 to disable, 1 to enable + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_image_trigger_control_send(mavlink_channel_t chan, uint8_t enable) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[1]; + _mav_put_uint8_t(buf, 0, enable); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_IMAGE_TRIGGER_CONTROL, buf, 1); +#else + mavlink_image_trigger_control_t packet; + packet.enable = enable; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_IMAGE_TRIGGER_CONTROL, (const char *)&packet, 1); +#endif +} + +#endif + +// MESSAGE IMAGE_TRIGGER_CONTROL UNPACKING + + +/** + * @brief Get field enable from image_trigger_control message + * + * @return 0 to disable, 1 to enable + */ +static inline uint8_t mavlink_msg_image_trigger_control_get_enable(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Decode a image_trigger_control message into a struct + * + * @param msg The message to decode + * @param image_trigger_control C-struct to decode the message contents into + */ +static inline void mavlink_msg_image_trigger_control_decode(const mavlink_message_t* msg, mavlink_image_trigger_control_t* image_trigger_control) +{ +#if MAVLINK_NEED_BYTE_SWAP + image_trigger_control->enable = mavlink_msg_image_trigger_control_get_enable(msg); +#else + memcpy(image_trigger_control, _MAV_PAYLOAD(msg), 1); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_image_triggered.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_image_triggered.h new file mode 100644 index 0000000000..a40bc134b5 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_image_triggered.h @@ -0,0 +1,386 @@ +// MESSAGE IMAGE_TRIGGERED PACKING + +#define MAVLINK_MSG_ID_IMAGE_TRIGGERED 152 + +typedef struct __mavlink_image_triggered_t +{ + uint64_t timestamp; ///< Timestamp + uint32_t seq; ///< IMU seq + float roll; ///< Roll angle in rad + float pitch; ///< Pitch angle in rad + float yaw; ///< Yaw angle in rad + float local_z; ///< Local frame Z coordinate (height over ground) + float lat; ///< GPS X coordinate + float lon; ///< GPS Y coordinate + float alt; ///< Global frame altitude + float ground_x; ///< Ground truth X + float ground_y; ///< Ground truth Y + float ground_z; ///< Ground truth Z +} mavlink_image_triggered_t; + +#define MAVLINK_MSG_ID_IMAGE_TRIGGERED_LEN 52 +#define MAVLINK_MSG_ID_152_LEN 52 + + + +#define MAVLINK_MESSAGE_INFO_IMAGE_TRIGGERED { \ + "IMAGE_TRIGGERED", \ + 12, \ + { { "timestamp", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_image_triggered_t, timestamp) }, \ + { "seq", NULL, MAVLINK_TYPE_UINT32_T, 0, 8, offsetof(mavlink_image_triggered_t, seq) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_image_triggered_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_image_triggered_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_image_triggered_t, yaw) }, \ + { "local_z", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_image_triggered_t, local_z) }, \ + { "lat", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_image_triggered_t, lat) }, \ + { "lon", NULL, MAVLINK_TYPE_FLOAT, 0, 32, offsetof(mavlink_image_triggered_t, lon) }, \ + { "alt", NULL, MAVLINK_TYPE_FLOAT, 0, 36, offsetof(mavlink_image_triggered_t, alt) }, \ + { "ground_x", NULL, MAVLINK_TYPE_FLOAT, 0, 40, offsetof(mavlink_image_triggered_t, ground_x) }, \ + { "ground_y", NULL, MAVLINK_TYPE_FLOAT, 0, 44, offsetof(mavlink_image_triggered_t, ground_y) }, \ + { "ground_z", NULL, MAVLINK_TYPE_FLOAT, 0, 48, offsetof(mavlink_image_triggered_t, ground_z) }, \ + } \ +} + + +/** + * @brief Pack a image_triggered message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param timestamp Timestamp + * @param seq IMU seq + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @param local_z Local frame Z coordinate (height over ground) + * @param lat GPS X coordinate + * @param lon GPS Y coordinate + * @param alt Global frame altitude + * @param ground_x Ground truth X + * @param ground_y Ground truth Y + * @param ground_z Ground truth Z + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_image_triggered_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t timestamp, uint32_t seq, float roll, float pitch, float yaw, float local_z, float lat, float lon, float alt, float ground_x, float ground_y, float ground_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[52]; + _mav_put_uint64_t(buf, 0, timestamp); + _mav_put_uint32_t(buf, 8, seq); + _mav_put_float(buf, 12, roll); + _mav_put_float(buf, 16, pitch); + _mav_put_float(buf, 20, yaw); + _mav_put_float(buf, 24, local_z); + _mav_put_float(buf, 28, lat); + _mav_put_float(buf, 32, lon); + _mav_put_float(buf, 36, alt); + _mav_put_float(buf, 40, ground_x); + _mav_put_float(buf, 44, ground_y); + _mav_put_float(buf, 48, ground_z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 52); +#else + mavlink_image_triggered_t packet; + packet.timestamp = timestamp; + packet.seq = seq; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.local_z = local_z; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.ground_x = ground_x; + packet.ground_y = ground_y; + packet.ground_z = ground_z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 52); +#endif + + msg->msgid = MAVLINK_MSG_ID_IMAGE_TRIGGERED; + return mavlink_finalize_message(msg, system_id, component_id, 52); +} + +/** + * @brief Pack a image_triggered message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param timestamp Timestamp + * @param seq IMU seq + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @param local_z Local frame Z coordinate (height over ground) + * @param lat GPS X coordinate + * @param lon GPS Y coordinate + * @param alt Global frame altitude + * @param ground_x Ground truth X + * @param ground_y Ground truth Y + * @param ground_z Ground truth Z + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_image_triggered_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t timestamp,uint32_t seq,float roll,float pitch,float yaw,float local_z,float lat,float lon,float alt,float ground_x,float ground_y,float ground_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[52]; + _mav_put_uint64_t(buf, 0, timestamp); + _mav_put_uint32_t(buf, 8, seq); + _mav_put_float(buf, 12, roll); + _mav_put_float(buf, 16, pitch); + _mav_put_float(buf, 20, yaw); + _mav_put_float(buf, 24, local_z); + _mav_put_float(buf, 28, lat); + _mav_put_float(buf, 32, lon); + _mav_put_float(buf, 36, alt); + _mav_put_float(buf, 40, ground_x); + _mav_put_float(buf, 44, ground_y); + _mav_put_float(buf, 48, ground_z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 52); +#else + mavlink_image_triggered_t packet; + packet.timestamp = timestamp; + packet.seq = seq; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.local_z = local_z; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.ground_x = ground_x; + packet.ground_y = ground_y; + packet.ground_z = ground_z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 52); +#endif + + msg->msgid = MAVLINK_MSG_ID_IMAGE_TRIGGERED; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 52); +} + +/** + * @brief Encode a image_triggered struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param image_triggered C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_image_triggered_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_image_triggered_t* image_triggered) +{ + return mavlink_msg_image_triggered_pack(system_id, component_id, msg, image_triggered->timestamp, image_triggered->seq, image_triggered->roll, image_triggered->pitch, image_triggered->yaw, image_triggered->local_z, image_triggered->lat, image_triggered->lon, image_triggered->alt, image_triggered->ground_x, image_triggered->ground_y, image_triggered->ground_z); +} + +/** + * @brief Send a image_triggered message + * @param chan MAVLink channel to send the message + * + * @param timestamp Timestamp + * @param seq IMU seq + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @param local_z Local frame Z coordinate (height over ground) + * @param lat GPS X coordinate + * @param lon GPS Y coordinate + * @param alt Global frame altitude + * @param ground_x Ground truth X + * @param ground_y Ground truth Y + * @param ground_z Ground truth Z + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_image_triggered_send(mavlink_channel_t chan, uint64_t timestamp, uint32_t seq, float roll, float pitch, float yaw, float local_z, float lat, float lon, float alt, float ground_x, float ground_y, float ground_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[52]; + _mav_put_uint64_t(buf, 0, timestamp); + _mav_put_uint32_t(buf, 8, seq); + _mav_put_float(buf, 12, roll); + _mav_put_float(buf, 16, pitch); + _mav_put_float(buf, 20, yaw); + _mav_put_float(buf, 24, local_z); + _mav_put_float(buf, 28, lat); + _mav_put_float(buf, 32, lon); + _mav_put_float(buf, 36, alt); + _mav_put_float(buf, 40, ground_x); + _mav_put_float(buf, 44, ground_y); + _mav_put_float(buf, 48, ground_z); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_IMAGE_TRIGGERED, buf, 52); +#else + mavlink_image_triggered_t packet; + packet.timestamp = timestamp; + packet.seq = seq; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.local_z = local_z; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.ground_x = ground_x; + packet.ground_y = ground_y; + packet.ground_z = ground_z; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_IMAGE_TRIGGERED, (const char *)&packet, 52); +#endif +} + +#endif + +// MESSAGE IMAGE_TRIGGERED UNPACKING + + +/** + * @brief Get field timestamp from image_triggered message + * + * @return Timestamp + */ +static inline uint64_t mavlink_msg_image_triggered_get_timestamp(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field seq from image_triggered message + * + * @return IMU seq + */ +static inline uint32_t mavlink_msg_image_triggered_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 8); +} + +/** + * @brief Get field roll from image_triggered message + * + * @return Roll angle in rad + */ +static inline float mavlink_msg_image_triggered_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field pitch from image_triggered message + * + * @return Pitch angle in rad + */ +static inline float mavlink_msg_image_triggered_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field yaw from image_triggered message + * + * @return Yaw angle in rad + */ +static inline float mavlink_msg_image_triggered_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field local_z from image_triggered message + * + * @return Local frame Z coordinate (height over ground) + */ +static inline float mavlink_msg_image_triggered_get_local_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field lat from image_triggered message + * + * @return GPS X coordinate + */ +static inline float mavlink_msg_image_triggered_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field lon from image_triggered message + * + * @return GPS Y coordinate + */ +static inline float mavlink_msg_image_triggered_get_lon(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 32); +} + +/** + * @brief Get field alt from image_triggered message + * + * @return Global frame altitude + */ +static inline float mavlink_msg_image_triggered_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 36); +} + +/** + * @brief Get field ground_x from image_triggered message + * + * @return Ground truth X + */ +static inline float mavlink_msg_image_triggered_get_ground_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 40); +} + +/** + * @brief Get field ground_y from image_triggered message + * + * @return Ground truth Y + */ +static inline float mavlink_msg_image_triggered_get_ground_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 44); +} + +/** + * @brief Get field ground_z from image_triggered message + * + * @return Ground truth Z + */ +static inline float mavlink_msg_image_triggered_get_ground_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 48); +} + +/** + * @brief Decode a image_triggered message into a struct + * + * @param msg The message to decode + * @param image_triggered C-struct to decode the message contents into + */ +static inline void mavlink_msg_image_triggered_decode(const mavlink_message_t* msg, mavlink_image_triggered_t* image_triggered) +{ +#if MAVLINK_NEED_BYTE_SWAP + image_triggered->timestamp = mavlink_msg_image_triggered_get_timestamp(msg); + image_triggered->seq = mavlink_msg_image_triggered_get_seq(msg); + image_triggered->roll = mavlink_msg_image_triggered_get_roll(msg); + image_triggered->pitch = mavlink_msg_image_triggered_get_pitch(msg); + image_triggered->yaw = mavlink_msg_image_triggered_get_yaw(msg); + image_triggered->local_z = mavlink_msg_image_triggered_get_local_z(msg); + image_triggered->lat = mavlink_msg_image_triggered_get_lat(msg); + image_triggered->lon = mavlink_msg_image_triggered_get_lon(msg); + image_triggered->alt = mavlink_msg_image_triggered_get_alt(msg); + image_triggered->ground_x = mavlink_msg_image_triggered_get_ground_x(msg); + image_triggered->ground_y = mavlink_msg_image_triggered_get_ground_y(msg); + image_triggered->ground_z = mavlink_msg_image_triggered_get_ground_z(msg); +#else + memcpy(image_triggered, _MAV_PAYLOAD(msg), 52); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_marker.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_marker.h new file mode 100644 index 0000000000..f5d20dd045 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_marker.h @@ -0,0 +1,276 @@ +// MESSAGE MARKER PACKING + +#define MAVLINK_MSG_ID_MARKER 171 + +typedef struct __mavlink_marker_t +{ + uint16_t id; ///< ID + float x; ///< x position + float y; ///< y position + float z; ///< z position + float roll; ///< roll orientation + float pitch; ///< pitch orientation + float yaw; ///< yaw orientation +} mavlink_marker_t; + +#define MAVLINK_MSG_ID_MARKER_LEN 26 +#define MAVLINK_MSG_ID_171_LEN 26 + + + +#define MAVLINK_MESSAGE_INFO_MARKER { \ + "MARKER", \ + 7, \ + { { "id", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_marker_t, id) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 2, offsetof(mavlink_marker_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 6, offsetof(mavlink_marker_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 10, offsetof(mavlink_marker_t, z) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 14, offsetof(mavlink_marker_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 18, offsetof(mavlink_marker_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 22, offsetof(mavlink_marker_t, yaw) }, \ + } \ +} + + +/** + * @brief Pack a marker message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param id ID + * @param x x position + * @param y y position + * @param z z position + * @param roll roll orientation + * @param pitch pitch orientation + * @param yaw yaw orientation + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_marker_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t id, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint16_t(buf, 0, id); + _mav_put_float(buf, 2, x); + _mav_put_float(buf, 6, y); + _mav_put_float(buf, 10, z); + _mav_put_float(buf, 14, roll); + _mav_put_float(buf, 18, pitch); + _mav_put_float(buf, 22, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_marker_t packet; + packet.id = id; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_MARKER; + return mavlink_finalize_message(msg, system_id, component_id, 26); +} + +/** + * @brief Pack a marker message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param id ID + * @param x x position + * @param y y position + * @param z z position + * @param roll roll orientation + * @param pitch pitch orientation + * @param yaw yaw orientation + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_marker_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t id,float x,float y,float z,float roll,float pitch,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint16_t(buf, 0, id); + _mav_put_float(buf, 2, x); + _mav_put_float(buf, 6, y); + _mav_put_float(buf, 10, z); + _mav_put_float(buf, 14, roll); + _mav_put_float(buf, 18, pitch); + _mav_put_float(buf, 22, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_marker_t packet; + packet.id = id; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_MARKER; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 26); +} + +/** + * @brief Encode a marker struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param marker C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_marker_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_marker_t* marker) +{ + return mavlink_msg_marker_pack(system_id, component_id, msg, marker->id, marker->x, marker->y, marker->z, marker->roll, marker->pitch, marker->yaw); +} + +/** + * @brief Send a marker message + * @param chan MAVLink channel to send the message + * + * @param id ID + * @param x x position + * @param y y position + * @param z z position + * @param roll roll orientation + * @param pitch pitch orientation + * @param yaw yaw orientation + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_marker_send(mavlink_channel_t chan, uint16_t id, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint16_t(buf, 0, id); + _mav_put_float(buf, 2, x); + _mav_put_float(buf, 6, y); + _mav_put_float(buf, 10, z); + _mav_put_float(buf, 14, roll); + _mav_put_float(buf, 18, pitch); + _mav_put_float(buf, 22, yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MARKER, buf, 26); +#else + mavlink_marker_t packet; + packet.id = id; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MARKER, (const char *)&packet, 26); +#endif +} + +#endif + +// MESSAGE MARKER UNPACKING + + +/** + * @brief Get field id from marker message + * + * @return ID + */ +static inline uint16_t mavlink_msg_marker_get_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field x from marker message + * + * @return x position + */ +static inline float mavlink_msg_marker_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 2); +} + +/** + * @brief Get field y from marker message + * + * @return y position + */ +static inline float mavlink_msg_marker_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 6); +} + +/** + * @brief Get field z from marker message + * + * @return z position + */ +static inline float mavlink_msg_marker_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 10); +} + +/** + * @brief Get field roll from marker message + * + * @return roll orientation + */ +static inline float mavlink_msg_marker_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 14); +} + +/** + * @brief Get field pitch from marker message + * + * @return pitch orientation + */ +static inline float mavlink_msg_marker_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 18); +} + +/** + * @brief Get field yaw from marker message + * + * @return yaw orientation + */ +static inline float mavlink_msg_marker_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 22); +} + +/** + * @brief Decode a marker message into a struct + * + * @param msg The message to decode + * @param marker C-struct to decode the message contents into + */ +static inline void mavlink_msg_marker_decode(const mavlink_message_t* msg, mavlink_marker_t* marker) +{ +#if MAVLINK_NEED_BYTE_SWAP + marker->id = mavlink_msg_marker_get_id(msg); + marker->x = mavlink_msg_marker_get_x(msg); + marker->y = mavlink_msg_marker_get_y(msg); + marker->z = mavlink_msg_marker_get_z(msg); + marker->roll = mavlink_msg_marker_get_roll(msg); + marker->pitch = mavlink_msg_marker_get_pitch(msg); + marker->yaw = mavlink_msg_marker_get_yaw(msg); +#else + memcpy(marker, _MAV_PAYLOAD(msg), 26); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_pattern_detected.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_pattern_detected.h new file mode 100644 index 0000000000..a5aabe9f9c --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_pattern_detected.h @@ -0,0 +1,204 @@ +// MESSAGE PATTERN_DETECTED PACKING + +#define MAVLINK_MSG_ID_PATTERN_DETECTED 190 + +typedef struct __mavlink_pattern_detected_t +{ + uint8_t type; ///< 0: Pattern, 1: Letter + float confidence; ///< Confidence of detection + char file[100]; ///< Pattern file name + uint8_t detected; ///< Accepted as true detection, 0 no, 1 yes +} mavlink_pattern_detected_t; + +#define MAVLINK_MSG_ID_PATTERN_DETECTED_LEN 106 +#define MAVLINK_MSG_ID_190_LEN 106 + +#define MAVLINK_MSG_PATTERN_DETECTED_FIELD_FILE_LEN 100 + +#define MAVLINK_MESSAGE_INFO_PATTERN_DETECTED { \ + "PATTERN_DETECTED", \ + 4, \ + { { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_pattern_detected_t, type) }, \ + { "confidence", NULL, MAVLINK_TYPE_FLOAT, 0, 1, offsetof(mavlink_pattern_detected_t, confidence) }, \ + { "file", NULL, MAVLINK_TYPE_CHAR, 100, 5, offsetof(mavlink_pattern_detected_t, file) }, \ + { "detected", NULL, MAVLINK_TYPE_UINT8_T, 0, 105, offsetof(mavlink_pattern_detected_t, detected) }, \ + } \ +} + + +/** + * @brief Pack a pattern_detected message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param type 0: Pattern, 1: Letter + * @param confidence Confidence of detection + * @param file Pattern file name + * @param detected Accepted as true detection, 0 no, 1 yes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_pattern_detected_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t type, float confidence, const char *file, uint8_t detected) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[106]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_float(buf, 1, confidence); + _mav_put_uint8_t(buf, 105, detected); + _mav_put_char_array(buf, 5, file, 100); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 106); +#else + mavlink_pattern_detected_t packet; + packet.type = type; + packet.confidence = confidence; + packet.detected = detected; + mav_array_memcpy(packet.file, file, sizeof(char)*100); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 106); +#endif + + msg->msgid = MAVLINK_MSG_ID_PATTERN_DETECTED; + return mavlink_finalize_message(msg, system_id, component_id, 106); +} + +/** + * @brief Pack a pattern_detected message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param type 0: Pattern, 1: Letter + * @param confidence Confidence of detection + * @param file Pattern file name + * @param detected Accepted as true detection, 0 no, 1 yes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_pattern_detected_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t type,float confidence,const char *file,uint8_t detected) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[106]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_float(buf, 1, confidence); + _mav_put_uint8_t(buf, 105, detected); + _mav_put_char_array(buf, 5, file, 100); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 106); +#else + mavlink_pattern_detected_t packet; + packet.type = type; + packet.confidence = confidence; + packet.detected = detected; + mav_array_memcpy(packet.file, file, sizeof(char)*100); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 106); +#endif + + msg->msgid = MAVLINK_MSG_ID_PATTERN_DETECTED; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 106); +} + +/** + * @brief Encode a pattern_detected struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param pattern_detected C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_pattern_detected_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_pattern_detected_t* pattern_detected) +{ + return mavlink_msg_pattern_detected_pack(system_id, component_id, msg, pattern_detected->type, pattern_detected->confidence, pattern_detected->file, pattern_detected->detected); +} + +/** + * @brief Send a pattern_detected message + * @param chan MAVLink channel to send the message + * + * @param type 0: Pattern, 1: Letter + * @param confidence Confidence of detection + * @param file Pattern file name + * @param detected Accepted as true detection, 0 no, 1 yes + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_pattern_detected_send(mavlink_channel_t chan, uint8_t type, float confidence, const char *file, uint8_t detected) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[106]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_float(buf, 1, confidence); + _mav_put_uint8_t(buf, 105, detected); + _mav_put_char_array(buf, 5, file, 100); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PATTERN_DETECTED, buf, 106); +#else + mavlink_pattern_detected_t packet; + packet.type = type; + packet.confidence = confidence; + packet.detected = detected; + mav_array_memcpy(packet.file, file, sizeof(char)*100); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PATTERN_DETECTED, (const char *)&packet, 106); +#endif +} + +#endif + +// MESSAGE PATTERN_DETECTED UNPACKING + + +/** + * @brief Get field type from pattern_detected message + * + * @return 0: Pattern, 1: Letter + */ +static inline uint8_t mavlink_msg_pattern_detected_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field confidence from pattern_detected message + * + * @return Confidence of detection + */ +static inline float mavlink_msg_pattern_detected_get_confidence(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 1); +} + +/** + * @brief Get field file from pattern_detected message + * + * @return Pattern file name + */ +static inline uint16_t mavlink_msg_pattern_detected_get_file(const mavlink_message_t* msg, char *file) +{ + return _MAV_RETURN_char_array(msg, file, 100, 5); +} + +/** + * @brief Get field detected from pattern_detected message + * + * @return Accepted as true detection, 0 no, 1 yes + */ +static inline uint8_t mavlink_msg_pattern_detected_get_detected(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 105); +} + +/** + * @brief Decode a pattern_detected message into a struct + * + * @param msg The message to decode + * @param pattern_detected C-struct to decode the message contents into + */ +static inline void mavlink_msg_pattern_detected_decode(const mavlink_message_t* msg, mavlink_pattern_detected_t* pattern_detected) +{ +#if MAVLINK_NEED_BYTE_SWAP + pattern_detected->type = mavlink_msg_pattern_detected_get_type(msg); + pattern_detected->confidence = mavlink_msg_pattern_detected_get_confidence(msg); + mavlink_msg_pattern_detected_get_file(msg, pattern_detected->file); + pattern_detected->detected = mavlink_msg_pattern_detected_get_detected(msg); +#else + memcpy(pattern_detected, _MAV_PAYLOAD(msg), 106); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_point_of_interest.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_point_of_interest.h new file mode 100644 index 0000000000..008ed436ed --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_point_of_interest.h @@ -0,0 +1,292 @@ +// MESSAGE POINT_OF_INTEREST PACKING + +#define MAVLINK_MSG_ID_POINT_OF_INTEREST 191 + +typedef struct __mavlink_point_of_interest_t +{ + uint8_t type; ///< 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + uint8_t color; ///< 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + uint8_t coordinate_system; ///< 0: global, 1:local + uint16_t timeout; ///< 0: no timeout, >1: timeout in seconds + float x; ///< X Position + float y; ///< Y Position + float z; ///< Z Position + char name[26]; ///< POI name +} mavlink_point_of_interest_t; + +#define MAVLINK_MSG_ID_POINT_OF_INTEREST_LEN 43 +#define MAVLINK_MSG_ID_191_LEN 43 + +#define MAVLINK_MSG_POINT_OF_INTEREST_FIELD_NAME_LEN 26 + +#define MAVLINK_MESSAGE_INFO_POINT_OF_INTEREST { \ + "POINT_OF_INTEREST", \ + 8, \ + { { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_point_of_interest_t, type) }, \ + { "color", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_point_of_interest_t, color) }, \ + { "coordinate_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_point_of_interest_t, coordinate_system) }, \ + { "timeout", NULL, MAVLINK_TYPE_UINT16_T, 0, 3, offsetof(mavlink_point_of_interest_t, timeout) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 5, offsetof(mavlink_point_of_interest_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 9, offsetof(mavlink_point_of_interest_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 13, offsetof(mavlink_point_of_interest_t, z) }, \ + { "name", NULL, MAVLINK_TYPE_CHAR, 26, 17, offsetof(mavlink_point_of_interest_t, name) }, \ + } \ +} + + +/** + * @brief Pack a point_of_interest message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param type 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + * @param color 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + * @param coordinate_system 0: global, 1:local + * @param timeout 0: no timeout, >1: timeout in seconds + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param name POI name + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_point_of_interest_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t type, uint8_t color, uint8_t coordinate_system, uint16_t timeout, float x, float y, float z, const char *name) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[43]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint8_t(buf, 1, color); + _mav_put_uint8_t(buf, 2, coordinate_system); + _mav_put_uint16_t(buf, 3, timeout); + _mav_put_float(buf, 5, x); + _mav_put_float(buf, 9, y); + _mav_put_float(buf, 13, z); + _mav_put_char_array(buf, 17, name, 26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 43); +#else + mavlink_point_of_interest_t packet; + packet.type = type; + packet.color = color; + packet.coordinate_system = coordinate_system; + packet.timeout = timeout; + packet.x = x; + packet.y = y; + packet.z = z; + mav_array_memcpy(packet.name, name, sizeof(char)*26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 43); +#endif + + msg->msgid = MAVLINK_MSG_ID_POINT_OF_INTEREST; + return mavlink_finalize_message(msg, system_id, component_id, 43); +} + +/** + * @brief Pack a point_of_interest message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param type 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + * @param color 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + * @param coordinate_system 0: global, 1:local + * @param timeout 0: no timeout, >1: timeout in seconds + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param name POI name + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_point_of_interest_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t type,uint8_t color,uint8_t coordinate_system,uint16_t timeout,float x,float y,float z,const char *name) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[43]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint8_t(buf, 1, color); + _mav_put_uint8_t(buf, 2, coordinate_system); + _mav_put_uint16_t(buf, 3, timeout); + _mav_put_float(buf, 5, x); + _mav_put_float(buf, 9, y); + _mav_put_float(buf, 13, z); + _mav_put_char_array(buf, 17, name, 26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 43); +#else + mavlink_point_of_interest_t packet; + packet.type = type; + packet.color = color; + packet.coordinate_system = coordinate_system; + packet.timeout = timeout; + packet.x = x; + packet.y = y; + packet.z = z; + mav_array_memcpy(packet.name, name, sizeof(char)*26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 43); +#endif + + msg->msgid = MAVLINK_MSG_ID_POINT_OF_INTEREST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 43); +} + +/** + * @brief Encode a point_of_interest struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param point_of_interest C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_point_of_interest_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_point_of_interest_t* point_of_interest) +{ + return mavlink_msg_point_of_interest_pack(system_id, component_id, msg, point_of_interest->type, point_of_interest->color, point_of_interest->coordinate_system, point_of_interest->timeout, point_of_interest->x, point_of_interest->y, point_of_interest->z, point_of_interest->name); +} + +/** + * @brief Send a point_of_interest message + * @param chan MAVLink channel to send the message + * + * @param type 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + * @param color 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + * @param coordinate_system 0: global, 1:local + * @param timeout 0: no timeout, >1: timeout in seconds + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param name POI name + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_point_of_interest_send(mavlink_channel_t chan, uint8_t type, uint8_t color, uint8_t coordinate_system, uint16_t timeout, float x, float y, float z, const char *name) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[43]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint8_t(buf, 1, color); + _mav_put_uint8_t(buf, 2, coordinate_system); + _mav_put_uint16_t(buf, 3, timeout); + _mav_put_float(buf, 5, x); + _mav_put_float(buf, 9, y); + _mav_put_float(buf, 13, z); + _mav_put_char_array(buf, 17, name, 26); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POINT_OF_INTEREST, buf, 43); +#else + mavlink_point_of_interest_t packet; + packet.type = type; + packet.color = color; + packet.coordinate_system = coordinate_system; + packet.timeout = timeout; + packet.x = x; + packet.y = y; + packet.z = z; + mav_array_memcpy(packet.name, name, sizeof(char)*26); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POINT_OF_INTEREST, (const char *)&packet, 43); +#endif +} + +#endif + +// MESSAGE POINT_OF_INTEREST UNPACKING + + +/** + * @brief Get field type from point_of_interest message + * + * @return 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + */ +static inline uint8_t mavlink_msg_point_of_interest_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field color from point_of_interest message + * + * @return 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + */ +static inline uint8_t mavlink_msg_point_of_interest_get_color(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field coordinate_system from point_of_interest message + * + * @return 0: global, 1:local + */ +static inline uint8_t mavlink_msg_point_of_interest_get_coordinate_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field timeout from point_of_interest message + * + * @return 0: no timeout, >1: timeout in seconds + */ +static inline uint16_t mavlink_msg_point_of_interest_get_timeout(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 3); +} + +/** + * @brief Get field x from point_of_interest message + * + * @return X Position + */ +static inline float mavlink_msg_point_of_interest_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 5); +} + +/** + * @brief Get field y from point_of_interest message + * + * @return Y Position + */ +static inline float mavlink_msg_point_of_interest_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 9); +} + +/** + * @brief Get field z from point_of_interest message + * + * @return Z Position + */ +static inline float mavlink_msg_point_of_interest_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 13); +} + +/** + * @brief Get field name from point_of_interest message + * + * @return POI name + */ +static inline uint16_t mavlink_msg_point_of_interest_get_name(const mavlink_message_t* msg, char *name) +{ + return _MAV_RETURN_char_array(msg, name, 26, 17); +} + +/** + * @brief Decode a point_of_interest message into a struct + * + * @param msg The message to decode + * @param point_of_interest C-struct to decode the message contents into + */ +static inline void mavlink_msg_point_of_interest_decode(const mavlink_message_t* msg, mavlink_point_of_interest_t* point_of_interest) +{ +#if MAVLINK_NEED_BYTE_SWAP + point_of_interest->type = mavlink_msg_point_of_interest_get_type(msg); + point_of_interest->color = mavlink_msg_point_of_interest_get_color(msg); + point_of_interest->coordinate_system = mavlink_msg_point_of_interest_get_coordinate_system(msg); + point_of_interest->timeout = mavlink_msg_point_of_interest_get_timeout(msg); + point_of_interest->x = mavlink_msg_point_of_interest_get_x(msg); + point_of_interest->y = mavlink_msg_point_of_interest_get_y(msg); + point_of_interest->z = mavlink_msg_point_of_interest_get_z(msg); + mavlink_msg_point_of_interest_get_name(msg, point_of_interest->name); +#else + memcpy(point_of_interest, _MAV_PAYLOAD(msg), 43); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_point_of_interest_connection.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_point_of_interest_connection.h new file mode 100644 index 0000000000..d8de738c79 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_point_of_interest_connection.h @@ -0,0 +1,358 @@ +// MESSAGE POINT_OF_INTEREST_CONNECTION PACKING + +#define MAVLINK_MSG_ID_POINT_OF_INTEREST_CONNECTION 192 + +typedef struct __mavlink_point_of_interest_connection_t +{ + uint8_t type; ///< 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + uint8_t color; ///< 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + uint8_t coordinate_system; ///< 0: global, 1:local + uint16_t timeout; ///< 0: no timeout, >1: timeout in seconds + float xp1; ///< X1 Position + float yp1; ///< Y1 Position + float zp1; ///< Z1 Position + float xp2; ///< X2 Position + float yp2; ///< Y2 Position + float zp2; ///< Z2 Position + char name[26]; ///< POI connection name +} mavlink_point_of_interest_connection_t; + +#define MAVLINK_MSG_ID_POINT_OF_INTEREST_CONNECTION_LEN 55 +#define MAVLINK_MSG_ID_192_LEN 55 + +#define MAVLINK_MSG_POINT_OF_INTEREST_CONNECTION_FIELD_NAME_LEN 26 + +#define MAVLINK_MESSAGE_INFO_POINT_OF_INTEREST_CONNECTION { \ + "POINT_OF_INTEREST_CONNECTION", \ + 11, \ + { { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_point_of_interest_connection_t, type) }, \ + { "color", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_point_of_interest_connection_t, color) }, \ + { "coordinate_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_point_of_interest_connection_t, coordinate_system) }, \ + { "timeout", NULL, MAVLINK_TYPE_UINT16_T, 0, 3, offsetof(mavlink_point_of_interest_connection_t, timeout) }, \ + { "xp1", NULL, MAVLINK_TYPE_FLOAT, 0, 5, offsetof(mavlink_point_of_interest_connection_t, xp1) }, \ + { "yp1", NULL, MAVLINK_TYPE_FLOAT, 0, 9, offsetof(mavlink_point_of_interest_connection_t, yp1) }, \ + { "zp1", NULL, MAVLINK_TYPE_FLOAT, 0, 13, offsetof(mavlink_point_of_interest_connection_t, zp1) }, \ + { "xp2", NULL, MAVLINK_TYPE_FLOAT, 0, 17, offsetof(mavlink_point_of_interest_connection_t, xp2) }, \ + { "yp2", NULL, MAVLINK_TYPE_FLOAT, 0, 21, offsetof(mavlink_point_of_interest_connection_t, yp2) }, \ + { "zp2", NULL, MAVLINK_TYPE_FLOAT, 0, 25, offsetof(mavlink_point_of_interest_connection_t, zp2) }, \ + { "name", NULL, MAVLINK_TYPE_CHAR, 26, 29, offsetof(mavlink_point_of_interest_connection_t, name) }, \ + } \ +} + + +/** + * @brief Pack a point_of_interest_connection message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param type 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + * @param color 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + * @param coordinate_system 0: global, 1:local + * @param timeout 0: no timeout, >1: timeout in seconds + * @param xp1 X1 Position + * @param yp1 Y1 Position + * @param zp1 Z1 Position + * @param xp2 X2 Position + * @param yp2 Y2 Position + * @param zp2 Z2 Position + * @param name POI connection name + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_point_of_interest_connection_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t type, uint8_t color, uint8_t coordinate_system, uint16_t timeout, float xp1, float yp1, float zp1, float xp2, float yp2, float zp2, const char *name) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[55]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint8_t(buf, 1, color); + _mav_put_uint8_t(buf, 2, coordinate_system); + _mav_put_uint16_t(buf, 3, timeout); + _mav_put_float(buf, 5, xp1); + _mav_put_float(buf, 9, yp1); + _mav_put_float(buf, 13, zp1); + _mav_put_float(buf, 17, xp2); + _mav_put_float(buf, 21, yp2); + _mav_put_float(buf, 25, zp2); + _mav_put_char_array(buf, 29, name, 26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 55); +#else + mavlink_point_of_interest_connection_t packet; + packet.type = type; + packet.color = color; + packet.coordinate_system = coordinate_system; + packet.timeout = timeout; + packet.xp1 = xp1; + packet.yp1 = yp1; + packet.zp1 = zp1; + packet.xp2 = xp2; + packet.yp2 = yp2; + packet.zp2 = zp2; + mav_array_memcpy(packet.name, name, sizeof(char)*26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 55); +#endif + + msg->msgid = MAVLINK_MSG_ID_POINT_OF_INTEREST_CONNECTION; + return mavlink_finalize_message(msg, system_id, component_id, 55); +} + +/** + * @brief Pack a point_of_interest_connection message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param type 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + * @param color 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + * @param coordinate_system 0: global, 1:local + * @param timeout 0: no timeout, >1: timeout in seconds + * @param xp1 X1 Position + * @param yp1 Y1 Position + * @param zp1 Z1 Position + * @param xp2 X2 Position + * @param yp2 Y2 Position + * @param zp2 Z2 Position + * @param name POI connection name + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_point_of_interest_connection_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t type,uint8_t color,uint8_t coordinate_system,uint16_t timeout,float xp1,float yp1,float zp1,float xp2,float yp2,float zp2,const char *name) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[55]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint8_t(buf, 1, color); + _mav_put_uint8_t(buf, 2, coordinate_system); + _mav_put_uint16_t(buf, 3, timeout); + _mav_put_float(buf, 5, xp1); + _mav_put_float(buf, 9, yp1); + _mav_put_float(buf, 13, zp1); + _mav_put_float(buf, 17, xp2); + _mav_put_float(buf, 21, yp2); + _mav_put_float(buf, 25, zp2); + _mav_put_char_array(buf, 29, name, 26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 55); +#else + mavlink_point_of_interest_connection_t packet; + packet.type = type; + packet.color = color; + packet.coordinate_system = coordinate_system; + packet.timeout = timeout; + packet.xp1 = xp1; + packet.yp1 = yp1; + packet.zp1 = zp1; + packet.xp2 = xp2; + packet.yp2 = yp2; + packet.zp2 = zp2; + mav_array_memcpy(packet.name, name, sizeof(char)*26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 55); +#endif + + msg->msgid = MAVLINK_MSG_ID_POINT_OF_INTEREST_CONNECTION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 55); +} + +/** + * @brief Encode a point_of_interest_connection struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param point_of_interest_connection C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_point_of_interest_connection_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_point_of_interest_connection_t* point_of_interest_connection) +{ + return mavlink_msg_point_of_interest_connection_pack(system_id, component_id, msg, point_of_interest_connection->type, point_of_interest_connection->color, point_of_interest_connection->coordinate_system, point_of_interest_connection->timeout, point_of_interest_connection->xp1, point_of_interest_connection->yp1, point_of_interest_connection->zp1, point_of_interest_connection->xp2, point_of_interest_connection->yp2, point_of_interest_connection->zp2, point_of_interest_connection->name); +} + +/** + * @brief Send a point_of_interest_connection message + * @param chan MAVLink channel to send the message + * + * @param type 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + * @param color 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + * @param coordinate_system 0: global, 1:local + * @param timeout 0: no timeout, >1: timeout in seconds + * @param xp1 X1 Position + * @param yp1 Y1 Position + * @param zp1 Z1 Position + * @param xp2 X2 Position + * @param yp2 Y2 Position + * @param zp2 Z2 Position + * @param name POI connection name + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_point_of_interest_connection_send(mavlink_channel_t chan, uint8_t type, uint8_t color, uint8_t coordinate_system, uint16_t timeout, float xp1, float yp1, float zp1, float xp2, float yp2, float zp2, const char *name) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[55]; + _mav_put_uint8_t(buf, 0, type); + _mav_put_uint8_t(buf, 1, color); + _mav_put_uint8_t(buf, 2, coordinate_system); + _mav_put_uint16_t(buf, 3, timeout); + _mav_put_float(buf, 5, xp1); + _mav_put_float(buf, 9, yp1); + _mav_put_float(buf, 13, zp1); + _mav_put_float(buf, 17, xp2); + _mav_put_float(buf, 21, yp2); + _mav_put_float(buf, 25, zp2); + _mav_put_char_array(buf, 29, name, 26); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POINT_OF_INTEREST_CONNECTION, buf, 55); +#else + mavlink_point_of_interest_connection_t packet; + packet.type = type; + packet.color = color; + packet.coordinate_system = coordinate_system; + packet.timeout = timeout; + packet.xp1 = xp1; + packet.yp1 = yp1; + packet.zp1 = zp1; + packet.xp2 = xp2; + packet.yp2 = yp2; + packet.zp2 = zp2; + mav_array_memcpy(packet.name, name, sizeof(char)*26); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POINT_OF_INTEREST_CONNECTION, (const char *)&packet, 55); +#endif +} + +#endif + +// MESSAGE POINT_OF_INTEREST_CONNECTION UNPACKING + + +/** + * @brief Get field type from point_of_interest_connection message + * + * @return 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + */ +static inline uint8_t mavlink_msg_point_of_interest_connection_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field color from point_of_interest_connection message + * + * @return 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + */ +static inline uint8_t mavlink_msg_point_of_interest_connection_get_color(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field coordinate_system from point_of_interest_connection message + * + * @return 0: global, 1:local + */ +static inline uint8_t mavlink_msg_point_of_interest_connection_get_coordinate_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field timeout from point_of_interest_connection message + * + * @return 0: no timeout, >1: timeout in seconds + */ +static inline uint16_t mavlink_msg_point_of_interest_connection_get_timeout(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 3); +} + +/** + * @brief Get field xp1 from point_of_interest_connection message + * + * @return X1 Position + */ +static inline float mavlink_msg_point_of_interest_connection_get_xp1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 5); +} + +/** + * @brief Get field yp1 from point_of_interest_connection message + * + * @return Y1 Position + */ +static inline float mavlink_msg_point_of_interest_connection_get_yp1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 9); +} + +/** + * @brief Get field zp1 from point_of_interest_connection message + * + * @return Z1 Position + */ +static inline float mavlink_msg_point_of_interest_connection_get_zp1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 13); +} + +/** + * @brief Get field xp2 from point_of_interest_connection message + * + * @return X2 Position + */ +static inline float mavlink_msg_point_of_interest_connection_get_xp2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 17); +} + +/** + * @brief Get field yp2 from point_of_interest_connection message + * + * @return Y2 Position + */ +static inline float mavlink_msg_point_of_interest_connection_get_yp2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 21); +} + +/** + * @brief Get field zp2 from point_of_interest_connection message + * + * @return Z2 Position + */ +static inline float mavlink_msg_point_of_interest_connection_get_zp2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 25); +} + +/** + * @brief Get field name from point_of_interest_connection message + * + * @return POI connection name + */ +static inline uint16_t mavlink_msg_point_of_interest_connection_get_name(const mavlink_message_t* msg, char *name) +{ + return _MAV_RETURN_char_array(msg, name, 26, 29); +} + +/** + * @brief Decode a point_of_interest_connection message into a struct + * + * @param msg The message to decode + * @param point_of_interest_connection C-struct to decode the message contents into + */ +static inline void mavlink_msg_point_of_interest_connection_decode(const mavlink_message_t* msg, mavlink_point_of_interest_connection_t* point_of_interest_connection) +{ +#if MAVLINK_NEED_BYTE_SWAP + point_of_interest_connection->type = mavlink_msg_point_of_interest_connection_get_type(msg); + point_of_interest_connection->color = mavlink_msg_point_of_interest_connection_get_color(msg); + point_of_interest_connection->coordinate_system = mavlink_msg_point_of_interest_connection_get_coordinate_system(msg); + point_of_interest_connection->timeout = mavlink_msg_point_of_interest_connection_get_timeout(msg); + point_of_interest_connection->xp1 = mavlink_msg_point_of_interest_connection_get_xp1(msg); + point_of_interest_connection->yp1 = mavlink_msg_point_of_interest_connection_get_yp1(msg); + point_of_interest_connection->zp1 = mavlink_msg_point_of_interest_connection_get_zp1(msg); + point_of_interest_connection->xp2 = mavlink_msg_point_of_interest_connection_get_xp2(msg); + point_of_interest_connection->yp2 = mavlink_msg_point_of_interest_connection_get_yp2(msg); + point_of_interest_connection->zp2 = mavlink_msg_point_of_interest_connection_get_zp2(msg); + mavlink_msg_point_of_interest_connection_get_name(msg, point_of_interest_connection->name); +#else + memcpy(point_of_interest_connection, _MAV_PAYLOAD(msg), 55); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_position_control_offset_set.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_position_control_offset_set.h new file mode 100644 index 0000000000..1591b6abea --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_position_control_offset_set.h @@ -0,0 +1,254 @@ +// MESSAGE POSITION_CONTROL_OFFSET_SET PACKING + +#define MAVLINK_MSG_ID_POSITION_CONTROL_OFFSET_SET 160 + +typedef struct __mavlink_position_control_offset_set_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + float x; ///< x position offset + float y; ///< y position offset + float z; ///< z position offset + float yaw; ///< yaw orientation offset in radians, 0 = NORTH +} mavlink_position_control_offset_set_t; + +#define MAVLINK_MSG_ID_POSITION_CONTROL_OFFSET_SET_LEN 18 +#define MAVLINK_MSG_ID_160_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_POSITION_CONTROL_OFFSET_SET { \ + "POSITION_CONTROL_OFFSET_SET", \ + 6, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_position_control_offset_set_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_position_control_offset_set_t, target_component) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 2, offsetof(mavlink_position_control_offset_set_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 6, offsetof(mavlink_position_control_offset_set_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 10, offsetof(mavlink_position_control_offset_set_t, z) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 14, offsetof(mavlink_position_control_offset_set_t, yaw) }, \ + } \ +} + + +/** + * @brief Pack a position_control_offset_set message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param x x position offset + * @param y y position offset + * @param z z position offset + * @param yaw yaw orientation offset in radians, 0 = NORTH + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_position_control_offset_set_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 2, x); + _mav_put_float(buf, 6, y); + _mav_put_float(buf, 10, z); + _mav_put_float(buf, 14, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_position_control_offset_set_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_POSITION_CONTROL_OFFSET_SET; + return mavlink_finalize_message(msg, system_id, component_id, 18); +} + +/** + * @brief Pack a position_control_offset_set message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param x x position offset + * @param y y position offset + * @param z z position offset + * @param yaw yaw orientation offset in radians, 0 = NORTH + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_position_control_offset_set_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,float x,float y,float z,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 2, x); + _mav_put_float(buf, 6, y); + _mav_put_float(buf, 10, z); + _mav_put_float(buf, 14, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_position_control_offset_set_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_POSITION_CONTROL_OFFSET_SET; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18); +} + +/** + * @brief Encode a position_control_offset_set struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param position_control_offset_set C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_position_control_offset_set_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_position_control_offset_set_t* position_control_offset_set) +{ + return mavlink_msg_position_control_offset_set_pack(system_id, component_id, msg, position_control_offset_set->target_system, position_control_offset_set->target_component, position_control_offset_set->x, position_control_offset_set->y, position_control_offset_set->z, position_control_offset_set->yaw); +} + +/** + * @brief Send a position_control_offset_set message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param x x position offset + * @param y y position offset + * @param z z position offset + * @param yaw yaw orientation offset in radians, 0 = NORTH + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_position_control_offset_set_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_float(buf, 2, x); + _mav_put_float(buf, 6, y); + _mav_put_float(buf, 10, z); + _mav_put_float(buf, 14, yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POSITION_CONTROL_OFFSET_SET, buf, 18); +#else + mavlink_position_control_offset_set_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POSITION_CONTROL_OFFSET_SET, (const char *)&packet, 18); +#endif +} + +#endif + +// MESSAGE POSITION_CONTROL_OFFSET_SET UNPACKING + + +/** + * @brief Get field target_system from position_control_offset_set message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_position_control_offset_set_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from position_control_offset_set message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_position_control_offset_set_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field x from position_control_offset_set message + * + * @return x position offset + */ +static inline float mavlink_msg_position_control_offset_set_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 2); +} + +/** + * @brief Get field y from position_control_offset_set message + * + * @return y position offset + */ +static inline float mavlink_msg_position_control_offset_set_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 6); +} + +/** + * @brief Get field z from position_control_offset_set message + * + * @return z position offset + */ +static inline float mavlink_msg_position_control_offset_set_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 10); +} + +/** + * @brief Get field yaw from position_control_offset_set message + * + * @return yaw orientation offset in radians, 0 = NORTH + */ +static inline float mavlink_msg_position_control_offset_set_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 14); +} + +/** + * @brief Decode a position_control_offset_set message into a struct + * + * @param msg The message to decode + * @param position_control_offset_set C-struct to decode the message contents into + */ +static inline void mavlink_msg_position_control_offset_set_decode(const mavlink_message_t* msg, mavlink_position_control_offset_set_t* position_control_offset_set) +{ +#if MAVLINK_NEED_BYTE_SWAP + position_control_offset_set->target_system = mavlink_msg_position_control_offset_set_get_target_system(msg); + position_control_offset_set->target_component = mavlink_msg_position_control_offset_set_get_target_component(msg); + position_control_offset_set->x = mavlink_msg_position_control_offset_set_get_x(msg); + position_control_offset_set->y = mavlink_msg_position_control_offset_set_get_y(msg); + position_control_offset_set->z = mavlink_msg_position_control_offset_set_get_z(msg); + position_control_offset_set->yaw = mavlink_msg_position_control_offset_set_get_yaw(msg); +#else + memcpy(position_control_offset_set, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_position_control_setpoint.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_position_control_setpoint.h new file mode 100644 index 0000000000..3e13f402d3 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_position_control_setpoint.h @@ -0,0 +1,232 @@ +// MESSAGE POSITION_CONTROL_SETPOINT PACKING + +#define MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT 170 + +typedef struct __mavlink_position_control_setpoint_t +{ + uint16_t id; ///< ID of waypoint, 0 for plain position + float x; ///< x position + float y; ///< y position + float z; ///< z position + float yaw; ///< yaw orientation in radians, 0 = NORTH +} mavlink_position_control_setpoint_t; + +#define MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT_LEN 18 +#define MAVLINK_MSG_ID_170_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_POSITION_CONTROL_SETPOINT { \ + "POSITION_CONTROL_SETPOINT", \ + 5, \ + { { "id", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_position_control_setpoint_t, id) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 2, offsetof(mavlink_position_control_setpoint_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 6, offsetof(mavlink_position_control_setpoint_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 10, offsetof(mavlink_position_control_setpoint_t, z) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 14, offsetof(mavlink_position_control_setpoint_t, yaw) }, \ + } \ +} + + +/** + * @brief Pack a position_control_setpoint message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param id ID of waypoint, 0 for plain position + * @param x x position + * @param y y position + * @param z z position + * @param yaw yaw orientation in radians, 0 = NORTH + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_position_control_setpoint_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t id, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint16_t(buf, 0, id); + _mav_put_float(buf, 2, x); + _mav_put_float(buf, 6, y); + _mav_put_float(buf, 10, z); + _mav_put_float(buf, 14, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_position_control_setpoint_t packet; + packet.id = id; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT; + return mavlink_finalize_message(msg, system_id, component_id, 18); +} + +/** + * @brief Pack a position_control_setpoint message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param id ID of waypoint, 0 for plain position + * @param x x position + * @param y y position + * @param z z position + * @param yaw yaw orientation in radians, 0 = NORTH + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_position_control_setpoint_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t id,float x,float y,float z,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint16_t(buf, 0, id); + _mav_put_float(buf, 2, x); + _mav_put_float(buf, 6, y); + _mav_put_float(buf, 10, z); + _mav_put_float(buf, 14, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_position_control_setpoint_t packet; + packet.id = id; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18); +} + +/** + * @brief Encode a position_control_setpoint struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param position_control_setpoint C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_position_control_setpoint_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_position_control_setpoint_t* position_control_setpoint) +{ + return mavlink_msg_position_control_setpoint_pack(system_id, component_id, msg, position_control_setpoint->id, position_control_setpoint->x, position_control_setpoint->y, position_control_setpoint->z, position_control_setpoint->yaw); +} + +/** + * @brief Send a position_control_setpoint message + * @param chan MAVLink channel to send the message + * + * @param id ID of waypoint, 0 for plain position + * @param x x position + * @param y y position + * @param z z position + * @param yaw yaw orientation in radians, 0 = NORTH + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_position_control_setpoint_send(mavlink_channel_t chan, uint16_t id, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint16_t(buf, 0, id); + _mav_put_float(buf, 2, x); + _mav_put_float(buf, 6, y); + _mav_put_float(buf, 10, z); + _mav_put_float(buf, 14, yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT, buf, 18); +#else + mavlink_position_control_setpoint_t packet; + packet.id = id; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT, (const char *)&packet, 18); +#endif +} + +#endif + +// MESSAGE POSITION_CONTROL_SETPOINT UNPACKING + + +/** + * @brief Get field id from position_control_setpoint message + * + * @return ID of waypoint, 0 for plain position + */ +static inline uint16_t mavlink_msg_position_control_setpoint_get_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field x from position_control_setpoint message + * + * @return x position + */ +static inline float mavlink_msg_position_control_setpoint_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 2); +} + +/** + * @brief Get field y from position_control_setpoint message + * + * @return y position + */ +static inline float mavlink_msg_position_control_setpoint_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 6); +} + +/** + * @brief Get field z from position_control_setpoint message + * + * @return z position + */ +static inline float mavlink_msg_position_control_setpoint_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 10); +} + +/** + * @brief Get field yaw from position_control_setpoint message + * + * @return yaw orientation in radians, 0 = NORTH + */ +static inline float mavlink_msg_position_control_setpoint_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 14); +} + +/** + * @brief Decode a position_control_setpoint message into a struct + * + * @param msg The message to decode + * @param position_control_setpoint C-struct to decode the message contents into + */ +static inline void mavlink_msg_position_control_setpoint_decode(const mavlink_message_t* msg, mavlink_position_control_setpoint_t* position_control_setpoint) +{ +#if MAVLINK_NEED_BYTE_SWAP + position_control_setpoint->id = mavlink_msg_position_control_setpoint_get_id(msg); + position_control_setpoint->x = mavlink_msg_position_control_setpoint_get_x(msg); + position_control_setpoint->y = mavlink_msg_position_control_setpoint_get_y(msg); + position_control_setpoint->z = mavlink_msg_position_control_setpoint_get_z(msg); + position_control_setpoint->yaw = mavlink_msg_position_control_setpoint_get_yaw(msg); +#else + memcpy(position_control_setpoint, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_position_control_setpoint_set.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_position_control_setpoint_set.h new file mode 100644 index 0000000000..4a556e57f4 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_position_control_setpoint_set.h @@ -0,0 +1,276 @@ +// MESSAGE POSITION_CONTROL_SETPOINT_SET PACKING + +#define MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT_SET 159 + +typedef struct __mavlink_position_control_setpoint_set_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint16_t id; ///< ID of waypoint, 0 for plain position + float x; ///< x position + float y; ///< y position + float z; ///< z position + float yaw; ///< yaw orientation in radians, 0 = NORTH +} mavlink_position_control_setpoint_set_t; + +#define MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT_SET_LEN 20 +#define MAVLINK_MSG_ID_159_LEN 20 + + + +#define MAVLINK_MESSAGE_INFO_POSITION_CONTROL_SETPOINT_SET { \ + "POSITION_CONTROL_SETPOINT_SET", \ + 7, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_position_control_setpoint_set_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_position_control_setpoint_set_t, target_component) }, \ + { "id", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_position_control_setpoint_set_t, id) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_position_control_setpoint_set_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_position_control_setpoint_set_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_position_control_setpoint_set_t, z) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_position_control_setpoint_set_t, yaw) }, \ + } \ +} + + +/** + * @brief Pack a position_control_setpoint_set message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param id ID of waypoint, 0 for plain position + * @param x x position + * @param y y position + * @param z z position + * @param yaw yaw orientation in radians, 0 = NORTH + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_position_control_setpoint_set_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint16_t id, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, id); + _mav_put_float(buf, 4, x); + _mav_put_float(buf, 8, y); + _mav_put_float(buf, 12, z); + _mav_put_float(buf, 16, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_position_control_setpoint_set_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.id = id; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT_SET; + return mavlink_finalize_message(msg, system_id, component_id, 20); +} + +/** + * @brief Pack a position_control_setpoint_set message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param id ID of waypoint, 0 for plain position + * @param x x position + * @param y y position + * @param z z position + * @param yaw yaw orientation in radians, 0 = NORTH + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_position_control_setpoint_set_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint16_t id,float x,float y,float z,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, id); + _mav_put_float(buf, 4, x); + _mav_put_float(buf, 8, y); + _mav_put_float(buf, 12, z); + _mav_put_float(buf, 16, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_position_control_setpoint_set_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.id = id; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT_SET; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 20); +} + +/** + * @brief Encode a position_control_setpoint_set struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param position_control_setpoint_set C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_position_control_setpoint_set_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_position_control_setpoint_set_t* position_control_setpoint_set) +{ + return mavlink_msg_position_control_setpoint_set_pack(system_id, component_id, msg, position_control_setpoint_set->target_system, position_control_setpoint_set->target_component, position_control_setpoint_set->id, position_control_setpoint_set->x, position_control_setpoint_set->y, position_control_setpoint_set->z, position_control_setpoint_set->yaw); +} + +/** + * @brief Send a position_control_setpoint_set message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param id ID of waypoint, 0 for plain position + * @param x x position + * @param y y position + * @param z z position + * @param yaw yaw orientation in radians, 0 = NORTH + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_position_control_setpoint_set_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint16_t id, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint16_t(buf, 2, id); + _mav_put_float(buf, 4, x); + _mav_put_float(buf, 8, y); + _mav_put_float(buf, 12, z); + _mav_put_float(buf, 16, yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT_SET, buf, 20); +#else + mavlink_position_control_setpoint_set_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.id = id; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT_SET, (const char *)&packet, 20); +#endif +} + +#endif + +// MESSAGE POSITION_CONTROL_SETPOINT_SET UNPACKING + + +/** + * @brief Get field target_system from position_control_setpoint_set message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_position_control_setpoint_set_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from position_control_setpoint_set message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_position_control_setpoint_set_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field id from position_control_setpoint_set message + * + * @return ID of waypoint, 0 for plain position + */ +static inline uint16_t mavlink_msg_position_control_setpoint_set_get_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Get field x from position_control_setpoint_set message + * + * @return x position + */ +static inline float mavlink_msg_position_control_setpoint_set_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field y from position_control_setpoint_set message + * + * @return y position + */ +static inline float mavlink_msg_position_control_setpoint_set_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field z from position_control_setpoint_set message + * + * @return z position + */ +static inline float mavlink_msg_position_control_setpoint_set_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field yaw from position_control_setpoint_set message + * + * @return yaw orientation in radians, 0 = NORTH + */ +static inline float mavlink_msg_position_control_setpoint_set_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Decode a position_control_setpoint_set message into a struct + * + * @param msg The message to decode + * @param position_control_setpoint_set C-struct to decode the message contents into + */ +static inline void mavlink_msg_position_control_setpoint_set_decode(const mavlink_message_t* msg, mavlink_position_control_setpoint_set_t* position_control_setpoint_set) +{ +#if MAVLINK_NEED_BYTE_SWAP + position_control_setpoint_set->target_system = mavlink_msg_position_control_setpoint_set_get_target_system(msg); + position_control_setpoint_set->target_component = mavlink_msg_position_control_setpoint_set_get_target_component(msg); + position_control_setpoint_set->id = mavlink_msg_position_control_setpoint_set_get_id(msg); + position_control_setpoint_set->x = mavlink_msg_position_control_setpoint_set_get_x(msg); + position_control_setpoint_set->y = mavlink_msg_position_control_setpoint_set_get_y(msg); + position_control_setpoint_set->z = mavlink_msg_position_control_setpoint_set_get_z(msg); + position_control_setpoint_set->yaw = mavlink_msg_position_control_setpoint_set_get_yaw(msg); +#else + memcpy(position_control_setpoint_set, _MAV_PAYLOAD(msg), 20); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_raw_aux.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_raw_aux.h new file mode 100644 index 0000000000..154653de2d --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_raw_aux.h @@ -0,0 +1,276 @@ +// MESSAGE RAW_AUX PACKING + +#define MAVLINK_MSG_ID_RAW_AUX 172 + +typedef struct __mavlink_raw_aux_t +{ + uint16_t adc1; ///< ADC1 (J405 ADC3, LPC2148 AD0.6) + uint16_t adc2; ///< ADC2 (J405 ADC5, LPC2148 AD0.2) + uint16_t adc3; ///< ADC3 (J405 ADC6, LPC2148 AD0.1) + uint16_t adc4; ///< ADC4 (J405 ADC7, LPC2148 AD1.3) + uint16_t vbat; ///< Battery voltage + int16_t temp; ///< Temperature (degrees celcius) + int32_t baro; ///< Barometric pressure (hecto Pascal) +} mavlink_raw_aux_t; + +#define MAVLINK_MSG_ID_RAW_AUX_LEN 16 +#define MAVLINK_MSG_ID_172_LEN 16 + + + +#define MAVLINK_MESSAGE_INFO_RAW_AUX { \ + "RAW_AUX", \ + 7, \ + { { "adc1", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_raw_aux_t, adc1) }, \ + { "adc2", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_raw_aux_t, adc2) }, \ + { "adc3", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_raw_aux_t, adc3) }, \ + { "adc4", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_raw_aux_t, adc4) }, \ + { "vbat", NULL, MAVLINK_TYPE_UINT16_T, 0, 8, offsetof(mavlink_raw_aux_t, vbat) }, \ + { "temp", NULL, MAVLINK_TYPE_INT16_T, 0, 10, offsetof(mavlink_raw_aux_t, temp) }, \ + { "baro", NULL, MAVLINK_TYPE_INT32_T, 0, 12, offsetof(mavlink_raw_aux_t, baro) }, \ + } \ +} + + +/** + * @brief Pack a raw_aux message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param adc1 ADC1 (J405 ADC3, LPC2148 AD0.6) + * @param adc2 ADC2 (J405 ADC5, LPC2148 AD0.2) + * @param adc3 ADC3 (J405 ADC6, LPC2148 AD0.1) + * @param adc4 ADC4 (J405 ADC7, LPC2148 AD1.3) + * @param vbat Battery voltage + * @param temp Temperature (degrees celcius) + * @param baro Barometric pressure (hecto Pascal) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_raw_aux_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t adc1, uint16_t adc2, uint16_t adc3, uint16_t adc4, uint16_t vbat, int16_t temp, int32_t baro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_uint16_t(buf, 0, adc1); + _mav_put_uint16_t(buf, 2, adc2); + _mav_put_uint16_t(buf, 4, adc3); + _mav_put_uint16_t(buf, 6, adc4); + _mav_put_uint16_t(buf, 8, vbat); + _mav_put_int16_t(buf, 10, temp); + _mav_put_int32_t(buf, 12, baro); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_raw_aux_t packet; + packet.adc1 = adc1; + packet.adc2 = adc2; + packet.adc3 = adc3; + packet.adc4 = adc4; + packet.vbat = vbat; + packet.temp = temp; + packet.baro = baro; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_RAW_AUX; + return mavlink_finalize_message(msg, system_id, component_id, 16); +} + +/** + * @brief Pack a raw_aux message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param adc1 ADC1 (J405 ADC3, LPC2148 AD0.6) + * @param adc2 ADC2 (J405 ADC5, LPC2148 AD0.2) + * @param adc3 ADC3 (J405 ADC6, LPC2148 AD0.1) + * @param adc4 ADC4 (J405 ADC7, LPC2148 AD1.3) + * @param vbat Battery voltage + * @param temp Temperature (degrees celcius) + * @param baro Barometric pressure (hecto Pascal) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_raw_aux_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t adc1,uint16_t adc2,uint16_t adc3,uint16_t adc4,uint16_t vbat,int16_t temp,int32_t baro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_uint16_t(buf, 0, adc1); + _mav_put_uint16_t(buf, 2, adc2); + _mav_put_uint16_t(buf, 4, adc3); + _mav_put_uint16_t(buf, 6, adc4); + _mav_put_uint16_t(buf, 8, vbat); + _mav_put_int16_t(buf, 10, temp); + _mav_put_int32_t(buf, 12, baro); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_raw_aux_t packet; + packet.adc1 = adc1; + packet.adc2 = adc2; + packet.adc3 = adc3; + packet.adc4 = adc4; + packet.vbat = vbat; + packet.temp = temp; + packet.baro = baro; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_RAW_AUX; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 16); +} + +/** + * @brief Encode a raw_aux struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param raw_aux C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_raw_aux_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_raw_aux_t* raw_aux) +{ + return mavlink_msg_raw_aux_pack(system_id, component_id, msg, raw_aux->adc1, raw_aux->adc2, raw_aux->adc3, raw_aux->adc4, raw_aux->vbat, raw_aux->temp, raw_aux->baro); +} + +/** + * @brief Send a raw_aux message + * @param chan MAVLink channel to send the message + * + * @param adc1 ADC1 (J405 ADC3, LPC2148 AD0.6) + * @param adc2 ADC2 (J405 ADC5, LPC2148 AD0.2) + * @param adc3 ADC3 (J405 ADC6, LPC2148 AD0.1) + * @param adc4 ADC4 (J405 ADC7, LPC2148 AD1.3) + * @param vbat Battery voltage + * @param temp Temperature (degrees celcius) + * @param baro Barometric pressure (hecto Pascal) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_raw_aux_send(mavlink_channel_t chan, uint16_t adc1, uint16_t adc2, uint16_t adc3, uint16_t adc4, uint16_t vbat, int16_t temp, int32_t baro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_uint16_t(buf, 0, adc1); + _mav_put_uint16_t(buf, 2, adc2); + _mav_put_uint16_t(buf, 4, adc3); + _mav_put_uint16_t(buf, 6, adc4); + _mav_put_uint16_t(buf, 8, vbat); + _mav_put_int16_t(buf, 10, temp); + _mav_put_int32_t(buf, 12, baro); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RAW_AUX, buf, 16); +#else + mavlink_raw_aux_t packet; + packet.adc1 = adc1; + packet.adc2 = adc2; + packet.adc3 = adc3; + packet.adc4 = adc4; + packet.vbat = vbat; + packet.temp = temp; + packet.baro = baro; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RAW_AUX, (const char *)&packet, 16); +#endif +} + +#endif + +// MESSAGE RAW_AUX UNPACKING + + +/** + * @brief Get field adc1 from raw_aux message + * + * @return ADC1 (J405 ADC3, LPC2148 AD0.6) + */ +static inline uint16_t mavlink_msg_raw_aux_get_adc1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field adc2 from raw_aux message + * + * @return ADC2 (J405 ADC5, LPC2148 AD0.2) + */ +static inline uint16_t mavlink_msg_raw_aux_get_adc2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Get field adc3 from raw_aux message + * + * @return ADC3 (J405 ADC6, LPC2148 AD0.1) + */ +static inline uint16_t mavlink_msg_raw_aux_get_adc3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field adc4 from raw_aux message + * + * @return ADC4 (J405 ADC7, LPC2148 AD1.3) + */ +static inline uint16_t mavlink_msg_raw_aux_get_adc4(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field vbat from raw_aux message + * + * @return Battery voltage + */ +static inline uint16_t mavlink_msg_raw_aux_get_vbat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Get field temp from raw_aux message + * + * @return Temperature (degrees celcius) + */ +static inline int16_t mavlink_msg_raw_aux_get_temp(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 10); +} + +/** + * @brief Get field baro from raw_aux message + * + * @return Barometric pressure (hecto Pascal) + */ +static inline int32_t mavlink_msg_raw_aux_get_baro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 12); +} + +/** + * @brief Decode a raw_aux message into a struct + * + * @param msg The message to decode + * @param raw_aux C-struct to decode the message contents into + */ +static inline void mavlink_msg_raw_aux_decode(const mavlink_message_t* msg, mavlink_raw_aux_t* raw_aux) +{ +#if MAVLINK_NEED_BYTE_SWAP + raw_aux->adc1 = mavlink_msg_raw_aux_get_adc1(msg); + raw_aux->adc2 = mavlink_msg_raw_aux_get_adc2(msg); + raw_aux->adc3 = mavlink_msg_raw_aux_get_adc3(msg); + raw_aux->adc4 = mavlink_msg_raw_aux_get_adc4(msg); + raw_aux->vbat = mavlink_msg_raw_aux_get_vbat(msg); + raw_aux->temp = mavlink_msg_raw_aux_get_temp(msg); + raw_aux->baro = mavlink_msg_raw_aux_get_baro(msg); +#else + memcpy(raw_aux, _MAV_PAYLOAD(msg), 16); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_set_cam_shutter.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_set_cam_shutter.h new file mode 100644 index 0000000000..c51ac730df --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_set_cam_shutter.h @@ -0,0 +1,254 @@ +// MESSAGE SET_CAM_SHUTTER PACKING + +#define MAVLINK_MSG_ID_SET_CAM_SHUTTER 151 + +typedef struct __mavlink_set_cam_shutter_t +{ + uint8_t cam_no; ///< Camera id + uint8_t cam_mode; ///< Camera mode: 0 = auto, 1 = manual + uint8_t trigger_pin; ///< Trigger pin, 0-3 for PtGrey FireFly + uint16_t interval; ///< Shutter interval, in microseconds + uint16_t exposure; ///< Exposure time, in microseconds + float gain; ///< Camera gain +} mavlink_set_cam_shutter_t; + +#define MAVLINK_MSG_ID_SET_CAM_SHUTTER_LEN 11 +#define MAVLINK_MSG_ID_151_LEN 11 + + + +#define MAVLINK_MESSAGE_INFO_SET_CAM_SHUTTER { \ + "SET_CAM_SHUTTER", \ + 6, \ + { { "cam_no", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_set_cam_shutter_t, cam_no) }, \ + { "cam_mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_set_cam_shutter_t, cam_mode) }, \ + { "trigger_pin", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_set_cam_shutter_t, trigger_pin) }, \ + { "interval", NULL, MAVLINK_TYPE_UINT16_T, 0, 3, offsetof(mavlink_set_cam_shutter_t, interval) }, \ + { "exposure", NULL, MAVLINK_TYPE_UINT16_T, 0, 5, offsetof(mavlink_set_cam_shutter_t, exposure) }, \ + { "gain", NULL, MAVLINK_TYPE_FLOAT, 0, 7, offsetof(mavlink_set_cam_shutter_t, gain) }, \ + } \ +} + + +/** + * @brief Pack a set_cam_shutter message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param cam_no Camera id + * @param cam_mode Camera mode: 0 = auto, 1 = manual + * @param trigger_pin Trigger pin, 0-3 for PtGrey FireFly + * @param interval Shutter interval, in microseconds + * @param exposure Exposure time, in microseconds + * @param gain Camera gain + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_cam_shutter_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t cam_no, uint8_t cam_mode, uint8_t trigger_pin, uint16_t interval, uint16_t exposure, float gain) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[11]; + _mav_put_uint8_t(buf, 0, cam_no); + _mav_put_uint8_t(buf, 1, cam_mode); + _mav_put_uint8_t(buf, 2, trigger_pin); + _mav_put_uint16_t(buf, 3, interval); + _mav_put_uint16_t(buf, 5, exposure); + _mav_put_float(buf, 7, gain); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 11); +#else + mavlink_set_cam_shutter_t packet; + packet.cam_no = cam_no; + packet.cam_mode = cam_mode; + packet.trigger_pin = trigger_pin; + packet.interval = interval; + packet.exposure = exposure; + packet.gain = gain; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 11); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_CAM_SHUTTER; + return mavlink_finalize_message(msg, system_id, component_id, 11); +} + +/** + * @brief Pack a set_cam_shutter message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param cam_no Camera id + * @param cam_mode Camera mode: 0 = auto, 1 = manual + * @param trigger_pin Trigger pin, 0-3 for PtGrey FireFly + * @param interval Shutter interval, in microseconds + * @param exposure Exposure time, in microseconds + * @param gain Camera gain + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_cam_shutter_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t cam_no,uint8_t cam_mode,uint8_t trigger_pin,uint16_t interval,uint16_t exposure,float gain) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[11]; + _mav_put_uint8_t(buf, 0, cam_no); + _mav_put_uint8_t(buf, 1, cam_mode); + _mav_put_uint8_t(buf, 2, trigger_pin); + _mav_put_uint16_t(buf, 3, interval); + _mav_put_uint16_t(buf, 5, exposure); + _mav_put_float(buf, 7, gain); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 11); +#else + mavlink_set_cam_shutter_t packet; + packet.cam_no = cam_no; + packet.cam_mode = cam_mode; + packet.trigger_pin = trigger_pin; + packet.interval = interval; + packet.exposure = exposure; + packet.gain = gain; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 11); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_CAM_SHUTTER; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 11); +} + +/** + * @brief Encode a set_cam_shutter struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_cam_shutter C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_cam_shutter_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_cam_shutter_t* set_cam_shutter) +{ + return mavlink_msg_set_cam_shutter_pack(system_id, component_id, msg, set_cam_shutter->cam_no, set_cam_shutter->cam_mode, set_cam_shutter->trigger_pin, set_cam_shutter->interval, set_cam_shutter->exposure, set_cam_shutter->gain); +} + +/** + * @brief Send a set_cam_shutter message + * @param chan MAVLink channel to send the message + * + * @param cam_no Camera id + * @param cam_mode Camera mode: 0 = auto, 1 = manual + * @param trigger_pin Trigger pin, 0-3 for PtGrey FireFly + * @param interval Shutter interval, in microseconds + * @param exposure Exposure time, in microseconds + * @param gain Camera gain + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_cam_shutter_send(mavlink_channel_t chan, uint8_t cam_no, uint8_t cam_mode, uint8_t trigger_pin, uint16_t interval, uint16_t exposure, float gain) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[11]; + _mav_put_uint8_t(buf, 0, cam_no); + _mav_put_uint8_t(buf, 1, cam_mode); + _mav_put_uint8_t(buf, 2, trigger_pin); + _mav_put_uint16_t(buf, 3, interval); + _mav_put_uint16_t(buf, 5, exposure); + _mav_put_float(buf, 7, gain); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_CAM_SHUTTER, buf, 11); +#else + mavlink_set_cam_shutter_t packet; + packet.cam_no = cam_no; + packet.cam_mode = cam_mode; + packet.trigger_pin = trigger_pin; + packet.interval = interval; + packet.exposure = exposure; + packet.gain = gain; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_CAM_SHUTTER, (const char *)&packet, 11); +#endif +} + +#endif + +// MESSAGE SET_CAM_SHUTTER UNPACKING + + +/** + * @brief Get field cam_no from set_cam_shutter message + * + * @return Camera id + */ +static inline uint8_t mavlink_msg_set_cam_shutter_get_cam_no(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field cam_mode from set_cam_shutter message + * + * @return Camera mode: 0 = auto, 1 = manual + */ +static inline uint8_t mavlink_msg_set_cam_shutter_get_cam_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field trigger_pin from set_cam_shutter message + * + * @return Trigger pin, 0-3 for PtGrey FireFly + */ +static inline uint8_t mavlink_msg_set_cam_shutter_get_trigger_pin(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field interval from set_cam_shutter message + * + * @return Shutter interval, in microseconds + */ +static inline uint16_t mavlink_msg_set_cam_shutter_get_interval(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 3); +} + +/** + * @brief Get field exposure from set_cam_shutter message + * + * @return Exposure time, in microseconds + */ +static inline uint16_t mavlink_msg_set_cam_shutter_get_exposure(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 5); +} + +/** + * @brief Get field gain from set_cam_shutter message + * + * @return Camera gain + */ +static inline float mavlink_msg_set_cam_shutter_get_gain(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 7); +} + +/** + * @brief Decode a set_cam_shutter message into a struct + * + * @param msg The message to decode + * @param set_cam_shutter C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_cam_shutter_decode(const mavlink_message_t* msg, mavlink_set_cam_shutter_t* set_cam_shutter) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_cam_shutter->cam_no = mavlink_msg_set_cam_shutter_get_cam_no(msg); + set_cam_shutter->cam_mode = mavlink_msg_set_cam_shutter_get_cam_mode(msg); + set_cam_shutter->trigger_pin = mavlink_msg_set_cam_shutter_get_trigger_pin(msg); + set_cam_shutter->interval = mavlink_msg_set_cam_shutter_get_interval(msg); + set_cam_shutter->exposure = mavlink_msg_set_cam_shutter_get_exposure(msg); + set_cam_shutter->gain = mavlink_msg_set_cam_shutter_get_gain(msg); +#else + memcpy(set_cam_shutter, _MAV_PAYLOAD(msg), 11); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_vicon_position_estimate.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_vicon_position_estimate.h new file mode 100644 index 0000000000..d2b4fbefba --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_vicon_position_estimate.h @@ -0,0 +1,276 @@ +// MESSAGE VICON_POSITION_ESTIMATE PACKING + +#define MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE 157 + +typedef struct __mavlink_vicon_position_estimate_t +{ + uint64_t usec; ///< Timestamp (milliseconds) + float x; ///< Global X position + float y; ///< Global Y position + float z; ///< Global Z position + float roll; ///< Roll angle in rad + float pitch; ///< Pitch angle in rad + float yaw; ///< Yaw angle in rad +} mavlink_vicon_position_estimate_t; + +#define MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE_LEN 32 +#define MAVLINK_MSG_ID_157_LEN 32 + + + +#define MAVLINK_MESSAGE_INFO_VICON_POSITION_ESTIMATE { \ + "VICON_POSITION_ESTIMATE", \ + 7, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_vicon_position_estimate_t, usec) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_vicon_position_estimate_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_vicon_position_estimate_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_vicon_position_estimate_t, z) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_vicon_position_estimate_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_vicon_position_estimate_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_vicon_position_estimate_t, yaw) }, \ + } \ +} + + +/** + * @brief Pack a vicon_position_estimate message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vicon_position_estimate_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_vicon_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE; + return mavlink_finalize_message(msg, system_id, component_id, 32); +} + +/** + * @brief Pack a vicon_position_estimate message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vicon_position_estimate_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float x,float y,float z,float roll,float pitch,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_vicon_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32); +} + +/** + * @brief Encode a vicon_position_estimate struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param vicon_position_estimate C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_vicon_position_estimate_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_vicon_position_estimate_t* vicon_position_estimate) +{ + return mavlink_msg_vicon_position_estimate_pack(system_id, component_id, msg, vicon_position_estimate->usec, vicon_position_estimate->x, vicon_position_estimate->y, vicon_position_estimate->z, vicon_position_estimate->roll, vicon_position_estimate->pitch, vicon_position_estimate->yaw); +} + +/** + * @brief Send a vicon_position_estimate message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_vicon_position_estimate_send(mavlink_channel_t chan, uint64_t usec, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE, buf, 32); +#else + mavlink_vicon_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE, (const char *)&packet, 32); +#endif +} + +#endif + +// MESSAGE VICON_POSITION_ESTIMATE UNPACKING + + +/** + * @brief Get field usec from vicon_position_estimate message + * + * @return Timestamp (milliseconds) + */ +static inline uint64_t mavlink_msg_vicon_position_estimate_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field x from vicon_position_estimate message + * + * @return Global X position + */ +static inline float mavlink_msg_vicon_position_estimate_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field y from vicon_position_estimate message + * + * @return Global Y position + */ +static inline float mavlink_msg_vicon_position_estimate_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field z from vicon_position_estimate message + * + * @return Global Z position + */ +static inline float mavlink_msg_vicon_position_estimate_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field roll from vicon_position_estimate message + * + * @return Roll angle in rad + */ +static inline float mavlink_msg_vicon_position_estimate_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field pitch from vicon_position_estimate message + * + * @return Pitch angle in rad + */ +static inline float mavlink_msg_vicon_position_estimate_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field yaw from vicon_position_estimate message + * + * @return Yaw angle in rad + */ +static inline float mavlink_msg_vicon_position_estimate_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Decode a vicon_position_estimate message into a struct + * + * @param msg The message to decode + * @param vicon_position_estimate C-struct to decode the message contents into + */ +static inline void mavlink_msg_vicon_position_estimate_decode(const mavlink_message_t* msg, mavlink_vicon_position_estimate_t* vicon_position_estimate) +{ +#if MAVLINK_NEED_BYTE_SWAP + vicon_position_estimate->usec = mavlink_msg_vicon_position_estimate_get_usec(msg); + vicon_position_estimate->x = mavlink_msg_vicon_position_estimate_get_x(msg); + vicon_position_estimate->y = mavlink_msg_vicon_position_estimate_get_y(msg); + vicon_position_estimate->z = mavlink_msg_vicon_position_estimate_get_z(msg); + vicon_position_estimate->roll = mavlink_msg_vicon_position_estimate_get_roll(msg); + vicon_position_estimate->pitch = mavlink_msg_vicon_position_estimate_get_pitch(msg); + vicon_position_estimate->yaw = mavlink_msg_vicon_position_estimate_get_yaw(msg); +#else + memcpy(vicon_position_estimate, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_vision_position_estimate.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_vision_position_estimate.h new file mode 100644 index 0000000000..d257972b70 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_vision_position_estimate.h @@ -0,0 +1,276 @@ +// MESSAGE VISION_POSITION_ESTIMATE PACKING + +#define MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE 156 + +typedef struct __mavlink_vision_position_estimate_t +{ + uint64_t usec; ///< Timestamp (milliseconds) + float x; ///< Global X position + float y; ///< Global Y position + float z; ///< Global Z position + float roll; ///< Roll angle in rad + float pitch; ///< Pitch angle in rad + float yaw; ///< Yaw angle in rad +} mavlink_vision_position_estimate_t; + +#define MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE_LEN 32 +#define MAVLINK_MSG_ID_156_LEN 32 + + + +#define MAVLINK_MESSAGE_INFO_VISION_POSITION_ESTIMATE { \ + "VISION_POSITION_ESTIMATE", \ + 7, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_vision_position_estimate_t, usec) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_vision_position_estimate_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_vision_position_estimate_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_vision_position_estimate_t, z) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_vision_position_estimate_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_vision_position_estimate_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_vision_position_estimate_t, yaw) }, \ + } \ +} + + +/** + * @brief Pack a vision_position_estimate message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vision_position_estimate_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_vision_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE; + return mavlink_finalize_message(msg, system_id, component_id, 32); +} + +/** + * @brief Pack a vision_position_estimate message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vision_position_estimate_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float x,float y,float z,float roll,float pitch,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_vision_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32); +} + +/** + * @brief Encode a vision_position_estimate struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param vision_position_estimate C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_vision_position_estimate_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_vision_position_estimate_t* vision_position_estimate) +{ + return mavlink_msg_vision_position_estimate_pack(system_id, component_id, msg, vision_position_estimate->usec, vision_position_estimate->x, vision_position_estimate->y, vision_position_estimate->z, vision_position_estimate->roll, vision_position_estimate->pitch, vision_position_estimate->yaw); +} + +/** + * @brief Send a vision_position_estimate message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_vision_position_estimate_send(mavlink_channel_t chan, uint64_t usec, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE, buf, 32); +#else + mavlink_vision_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE, (const char *)&packet, 32); +#endif +} + +#endif + +// MESSAGE VISION_POSITION_ESTIMATE UNPACKING + + +/** + * @brief Get field usec from vision_position_estimate message + * + * @return Timestamp (milliseconds) + */ +static inline uint64_t mavlink_msg_vision_position_estimate_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field x from vision_position_estimate message + * + * @return Global X position + */ +static inline float mavlink_msg_vision_position_estimate_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field y from vision_position_estimate message + * + * @return Global Y position + */ +static inline float mavlink_msg_vision_position_estimate_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field z from vision_position_estimate message + * + * @return Global Z position + */ +static inline float mavlink_msg_vision_position_estimate_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field roll from vision_position_estimate message + * + * @return Roll angle in rad + */ +static inline float mavlink_msg_vision_position_estimate_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field pitch from vision_position_estimate message + * + * @return Pitch angle in rad + */ +static inline float mavlink_msg_vision_position_estimate_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field yaw from vision_position_estimate message + * + * @return Yaw angle in rad + */ +static inline float mavlink_msg_vision_position_estimate_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Decode a vision_position_estimate message into a struct + * + * @param msg The message to decode + * @param vision_position_estimate C-struct to decode the message contents into + */ +static inline void mavlink_msg_vision_position_estimate_decode(const mavlink_message_t* msg, mavlink_vision_position_estimate_t* vision_position_estimate) +{ +#if MAVLINK_NEED_BYTE_SWAP + vision_position_estimate->usec = mavlink_msg_vision_position_estimate_get_usec(msg); + vision_position_estimate->x = mavlink_msg_vision_position_estimate_get_x(msg); + vision_position_estimate->y = mavlink_msg_vision_position_estimate_get_y(msg); + vision_position_estimate->z = mavlink_msg_vision_position_estimate_get_z(msg); + vision_position_estimate->roll = mavlink_msg_vision_position_estimate_get_roll(msg); + vision_position_estimate->pitch = mavlink_msg_vision_position_estimate_get_pitch(msg); + vision_position_estimate->yaw = mavlink_msg_vision_position_estimate_get_yaw(msg); +#else + memcpy(vision_position_estimate, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_vision_speed_estimate.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_vision_speed_estimate.h new file mode 100644 index 0000000000..22929dd215 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_vision_speed_estimate.h @@ -0,0 +1,210 @@ +// MESSAGE VISION_SPEED_ESTIMATE PACKING + +#define MAVLINK_MSG_ID_VISION_SPEED_ESTIMATE 158 + +typedef struct __mavlink_vision_speed_estimate_t +{ + uint64_t usec; ///< Timestamp (milliseconds) + float x; ///< Global X speed + float y; ///< Global Y speed + float z; ///< Global Z speed +} mavlink_vision_speed_estimate_t; + +#define MAVLINK_MSG_ID_VISION_SPEED_ESTIMATE_LEN 20 +#define MAVLINK_MSG_ID_158_LEN 20 + + + +#define MAVLINK_MESSAGE_INFO_VISION_SPEED_ESTIMATE { \ + "VISION_SPEED_ESTIMATE", \ + 4, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_vision_speed_estimate_t, usec) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_vision_speed_estimate_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_vision_speed_estimate_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_vision_speed_estimate_t, z) }, \ + } \ +} + + +/** + * @brief Pack a vision_speed_estimate message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (milliseconds) + * @param x Global X speed + * @param y Global Y speed + * @param z Global Z speed + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vision_speed_estimate_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, float x, float y, float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_vision_speed_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_VISION_SPEED_ESTIMATE; + return mavlink_finalize_message(msg, system_id, component_id, 20); +} + +/** + * @brief Pack a vision_speed_estimate message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (milliseconds) + * @param x Global X speed + * @param y Global Y speed + * @param z Global Z speed + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vision_speed_estimate_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float x,float y,float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_vision_speed_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_VISION_SPEED_ESTIMATE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 20); +} + +/** + * @brief Encode a vision_speed_estimate struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param vision_speed_estimate C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_vision_speed_estimate_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_vision_speed_estimate_t* vision_speed_estimate) +{ + return mavlink_msg_vision_speed_estimate_pack(system_id, component_id, msg, vision_speed_estimate->usec, vision_speed_estimate->x, vision_speed_estimate->y, vision_speed_estimate->z); +} + +/** + * @brief Send a vision_speed_estimate message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (milliseconds) + * @param x Global X speed + * @param y Global Y speed + * @param z Global Z speed + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_vision_speed_estimate_send(mavlink_channel_t chan, uint64_t usec, float x, float y, float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VISION_SPEED_ESTIMATE, buf, 20); +#else + mavlink_vision_speed_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VISION_SPEED_ESTIMATE, (const char *)&packet, 20); +#endif +} + +#endif + +// MESSAGE VISION_SPEED_ESTIMATE UNPACKING + + +/** + * @brief Get field usec from vision_speed_estimate message + * + * @return Timestamp (milliseconds) + */ +static inline uint64_t mavlink_msg_vision_speed_estimate_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field x from vision_speed_estimate message + * + * @return Global X speed + */ +static inline float mavlink_msg_vision_speed_estimate_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field y from vision_speed_estimate message + * + * @return Global Y speed + */ +static inline float mavlink_msg_vision_speed_estimate_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field z from vision_speed_estimate message + * + * @return Global Z speed + */ +static inline float mavlink_msg_vision_speed_estimate_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Decode a vision_speed_estimate message into a struct + * + * @param msg The message to decode + * @param vision_speed_estimate C-struct to decode the message contents into + */ +static inline void mavlink_msg_vision_speed_estimate_decode(const mavlink_message_t* msg, mavlink_vision_speed_estimate_t* vision_speed_estimate) +{ +#if MAVLINK_NEED_BYTE_SWAP + vision_speed_estimate->usec = mavlink_msg_vision_speed_estimate_get_usec(msg); + vision_speed_estimate->x = mavlink_msg_vision_speed_estimate_get_x(msg); + vision_speed_estimate->y = mavlink_msg_vision_speed_estimate_get_y(msg); + vision_speed_estimate->z = mavlink_msg_vision_speed_estimate_get_z(msg); +#else + memcpy(vision_speed_estimate, _MAV_PAYLOAD(msg), 20); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_watchdog_command.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_watchdog_command.h new file mode 100644 index 0000000000..a3ffe71adb --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_watchdog_command.h @@ -0,0 +1,210 @@ +// MESSAGE WATCHDOG_COMMAND PACKING + +#define MAVLINK_MSG_ID_WATCHDOG_COMMAND 183 + +typedef struct __mavlink_watchdog_command_t +{ + uint8_t target_system_id; ///< Target system ID + uint16_t watchdog_id; ///< Watchdog ID + uint16_t process_id; ///< Process ID + uint8_t command_id; ///< Command ID +} mavlink_watchdog_command_t; + +#define MAVLINK_MSG_ID_WATCHDOG_COMMAND_LEN 6 +#define MAVLINK_MSG_ID_183_LEN 6 + + + +#define MAVLINK_MESSAGE_INFO_WATCHDOG_COMMAND { \ + "WATCHDOG_COMMAND", \ + 4, \ + { { "target_system_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_watchdog_command_t, target_system_id) }, \ + { "watchdog_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 1, offsetof(mavlink_watchdog_command_t, watchdog_id) }, \ + { "process_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 3, offsetof(mavlink_watchdog_command_t, process_id) }, \ + { "command_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_watchdog_command_t, command_id) }, \ + } \ +} + + +/** + * @brief Pack a watchdog_command message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system_id Target system ID + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param command_id Command ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_command_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system_id, uint16_t watchdog_id, uint16_t process_id, uint8_t command_id) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint8_t(buf, 0, target_system_id); + _mav_put_uint16_t(buf, 1, watchdog_id); + _mav_put_uint16_t(buf, 3, process_id); + _mav_put_uint8_t(buf, 5, command_id); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_watchdog_command_t packet; + packet.target_system_id = target_system_id; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.command_id = command_id; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_COMMAND; + return mavlink_finalize_message(msg, system_id, component_id, 6); +} + +/** + * @brief Pack a watchdog_command message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system_id Target system ID + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param command_id Command ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_command_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system_id,uint16_t watchdog_id,uint16_t process_id,uint8_t command_id) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint8_t(buf, 0, target_system_id); + _mav_put_uint16_t(buf, 1, watchdog_id); + _mav_put_uint16_t(buf, 3, process_id); + _mav_put_uint8_t(buf, 5, command_id); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_watchdog_command_t packet; + packet.target_system_id = target_system_id; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.command_id = command_id; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_COMMAND; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 6); +} + +/** + * @brief Encode a watchdog_command struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param watchdog_command C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_watchdog_command_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_watchdog_command_t* watchdog_command) +{ + return mavlink_msg_watchdog_command_pack(system_id, component_id, msg, watchdog_command->target_system_id, watchdog_command->watchdog_id, watchdog_command->process_id, watchdog_command->command_id); +} + +/** + * @brief Send a watchdog_command message + * @param chan MAVLink channel to send the message + * + * @param target_system_id Target system ID + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param command_id Command ID + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_watchdog_command_send(mavlink_channel_t chan, uint8_t target_system_id, uint16_t watchdog_id, uint16_t process_id, uint8_t command_id) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint8_t(buf, 0, target_system_id); + _mav_put_uint16_t(buf, 1, watchdog_id); + _mav_put_uint16_t(buf, 3, process_id); + _mav_put_uint8_t(buf, 5, command_id); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_COMMAND, buf, 6); +#else + mavlink_watchdog_command_t packet; + packet.target_system_id = target_system_id; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.command_id = command_id; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_COMMAND, (const char *)&packet, 6); +#endif +} + +#endif + +// MESSAGE WATCHDOG_COMMAND UNPACKING + + +/** + * @brief Get field target_system_id from watchdog_command message + * + * @return Target system ID + */ +static inline uint8_t mavlink_msg_watchdog_command_get_target_system_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field watchdog_id from watchdog_command message + * + * @return Watchdog ID + */ +static inline uint16_t mavlink_msg_watchdog_command_get_watchdog_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 1); +} + +/** + * @brief Get field process_id from watchdog_command message + * + * @return Process ID + */ +static inline uint16_t mavlink_msg_watchdog_command_get_process_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 3); +} + +/** + * @brief Get field command_id from watchdog_command message + * + * @return Command ID + */ +static inline uint8_t mavlink_msg_watchdog_command_get_command_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Decode a watchdog_command message into a struct + * + * @param msg The message to decode + * @param watchdog_command C-struct to decode the message contents into + */ +static inline void mavlink_msg_watchdog_command_decode(const mavlink_message_t* msg, mavlink_watchdog_command_t* watchdog_command) +{ +#if MAVLINK_NEED_BYTE_SWAP + watchdog_command->target_system_id = mavlink_msg_watchdog_command_get_target_system_id(msg); + watchdog_command->watchdog_id = mavlink_msg_watchdog_command_get_watchdog_id(msg); + watchdog_command->process_id = mavlink_msg_watchdog_command_get_process_id(msg); + watchdog_command->command_id = mavlink_msg_watchdog_command_get_command_id(msg); +#else + memcpy(watchdog_command, _MAV_PAYLOAD(msg), 6); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_watchdog_heartbeat.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_watchdog_heartbeat.h new file mode 100644 index 0000000000..6dbe21104b --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_watchdog_heartbeat.h @@ -0,0 +1,166 @@ +// MESSAGE WATCHDOG_HEARTBEAT PACKING + +#define MAVLINK_MSG_ID_WATCHDOG_HEARTBEAT 180 + +typedef struct __mavlink_watchdog_heartbeat_t +{ + uint16_t watchdog_id; ///< Watchdog ID + uint16_t process_count; ///< Number of processes +} mavlink_watchdog_heartbeat_t; + +#define MAVLINK_MSG_ID_WATCHDOG_HEARTBEAT_LEN 4 +#define MAVLINK_MSG_ID_180_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_WATCHDOG_HEARTBEAT { \ + "WATCHDOG_HEARTBEAT", \ + 2, \ + { { "watchdog_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_watchdog_heartbeat_t, watchdog_id) }, \ + { "process_count", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_watchdog_heartbeat_t, process_count) }, \ + } \ +} + + +/** + * @brief Pack a watchdog_heartbeat message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param watchdog_id Watchdog ID + * @param process_count Number of processes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_heartbeat_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t watchdog_id, uint16_t process_count) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_count); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_watchdog_heartbeat_t packet; + packet.watchdog_id = watchdog_id; + packet.process_count = process_count; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_HEARTBEAT; + return mavlink_finalize_message(msg, system_id, component_id, 4); +} + +/** + * @brief Pack a watchdog_heartbeat message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param watchdog_id Watchdog ID + * @param process_count Number of processes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_heartbeat_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t watchdog_id,uint16_t process_count) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_count); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_watchdog_heartbeat_t packet; + packet.watchdog_id = watchdog_id; + packet.process_count = process_count; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_HEARTBEAT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4); +} + +/** + * @brief Encode a watchdog_heartbeat struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param watchdog_heartbeat C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_watchdog_heartbeat_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_watchdog_heartbeat_t* watchdog_heartbeat) +{ + return mavlink_msg_watchdog_heartbeat_pack(system_id, component_id, msg, watchdog_heartbeat->watchdog_id, watchdog_heartbeat->process_count); +} + +/** + * @brief Send a watchdog_heartbeat message + * @param chan MAVLink channel to send the message + * + * @param watchdog_id Watchdog ID + * @param process_count Number of processes + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_watchdog_heartbeat_send(mavlink_channel_t chan, uint16_t watchdog_id, uint16_t process_count) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_count); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_HEARTBEAT, buf, 4); +#else + mavlink_watchdog_heartbeat_t packet; + packet.watchdog_id = watchdog_id; + packet.process_count = process_count; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_HEARTBEAT, (const char *)&packet, 4); +#endif +} + +#endif + +// MESSAGE WATCHDOG_HEARTBEAT UNPACKING + + +/** + * @brief Get field watchdog_id from watchdog_heartbeat message + * + * @return Watchdog ID + */ +static inline uint16_t mavlink_msg_watchdog_heartbeat_get_watchdog_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field process_count from watchdog_heartbeat message + * + * @return Number of processes + */ +static inline uint16_t mavlink_msg_watchdog_heartbeat_get_process_count(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Decode a watchdog_heartbeat message into a struct + * + * @param msg The message to decode + * @param watchdog_heartbeat C-struct to decode the message contents into + */ +static inline void mavlink_msg_watchdog_heartbeat_decode(const mavlink_message_t* msg, mavlink_watchdog_heartbeat_t* watchdog_heartbeat) +{ +#if MAVLINK_NEED_BYTE_SWAP + watchdog_heartbeat->watchdog_id = mavlink_msg_watchdog_heartbeat_get_watchdog_id(msg); + watchdog_heartbeat->process_count = mavlink_msg_watchdog_heartbeat_get_process_count(msg); +#else + memcpy(watchdog_heartbeat, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_watchdog_process_info.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_watchdog_process_info.h new file mode 100644 index 0000000000..42e8966927 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_watchdog_process_info.h @@ -0,0 +1,227 @@ +// MESSAGE WATCHDOG_PROCESS_INFO PACKING + +#define MAVLINK_MSG_ID_WATCHDOG_PROCESS_INFO 181 + +typedef struct __mavlink_watchdog_process_info_t +{ + uint16_t watchdog_id; ///< Watchdog ID + uint16_t process_id; ///< Process ID + char name[100]; ///< Process name + char arguments[147]; ///< Process arguments + int32_t timeout; ///< Timeout (seconds) +} mavlink_watchdog_process_info_t; + +#define MAVLINK_MSG_ID_WATCHDOG_PROCESS_INFO_LEN 255 +#define MAVLINK_MSG_ID_181_LEN 255 + +#define MAVLINK_MSG_WATCHDOG_PROCESS_INFO_FIELD_NAME_LEN 100 +#define MAVLINK_MSG_WATCHDOG_PROCESS_INFO_FIELD_ARGUMENTS_LEN 147 + +#define MAVLINK_MESSAGE_INFO_WATCHDOG_PROCESS_INFO { \ + "WATCHDOG_PROCESS_INFO", \ + 5, \ + { { "watchdog_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_watchdog_process_info_t, watchdog_id) }, \ + { "process_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_watchdog_process_info_t, process_id) }, \ + { "name", NULL, MAVLINK_TYPE_CHAR, 100, 4, offsetof(mavlink_watchdog_process_info_t, name) }, \ + { "arguments", NULL, MAVLINK_TYPE_CHAR, 147, 104, offsetof(mavlink_watchdog_process_info_t, arguments) }, \ + { "timeout", NULL, MAVLINK_TYPE_INT32_T, 0, 251, offsetof(mavlink_watchdog_process_info_t, timeout) }, \ + } \ +} + + +/** + * @brief Pack a watchdog_process_info message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param name Process name + * @param arguments Process arguments + * @param timeout Timeout (seconds) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_process_info_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t watchdog_id, uint16_t process_id, const char *name, const char *arguments, int32_t timeout) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[255]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_id); + _mav_put_int32_t(buf, 251, timeout); + _mav_put_char_array(buf, 4, name, 100); + _mav_put_char_array(buf, 104, arguments, 147); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 255); +#else + mavlink_watchdog_process_info_t packet; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.timeout = timeout; + mav_array_memcpy(packet.name, name, sizeof(char)*100); + mav_array_memcpy(packet.arguments, arguments, sizeof(char)*147); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 255); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_PROCESS_INFO; + return mavlink_finalize_message(msg, system_id, component_id, 255); +} + +/** + * @brief Pack a watchdog_process_info message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param name Process name + * @param arguments Process arguments + * @param timeout Timeout (seconds) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_process_info_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t watchdog_id,uint16_t process_id,const char *name,const char *arguments,int32_t timeout) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[255]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_id); + _mav_put_int32_t(buf, 251, timeout); + _mav_put_char_array(buf, 4, name, 100); + _mav_put_char_array(buf, 104, arguments, 147); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 255); +#else + mavlink_watchdog_process_info_t packet; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.timeout = timeout; + mav_array_memcpy(packet.name, name, sizeof(char)*100); + mav_array_memcpy(packet.arguments, arguments, sizeof(char)*147); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 255); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_PROCESS_INFO; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 255); +} + +/** + * @brief Encode a watchdog_process_info struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param watchdog_process_info C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_watchdog_process_info_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_watchdog_process_info_t* watchdog_process_info) +{ + return mavlink_msg_watchdog_process_info_pack(system_id, component_id, msg, watchdog_process_info->watchdog_id, watchdog_process_info->process_id, watchdog_process_info->name, watchdog_process_info->arguments, watchdog_process_info->timeout); +} + +/** + * @brief Send a watchdog_process_info message + * @param chan MAVLink channel to send the message + * + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param name Process name + * @param arguments Process arguments + * @param timeout Timeout (seconds) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_watchdog_process_info_send(mavlink_channel_t chan, uint16_t watchdog_id, uint16_t process_id, const char *name, const char *arguments, int32_t timeout) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[255]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_id); + _mav_put_int32_t(buf, 251, timeout); + _mav_put_char_array(buf, 4, name, 100); + _mav_put_char_array(buf, 104, arguments, 147); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_PROCESS_INFO, buf, 255); +#else + mavlink_watchdog_process_info_t packet; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.timeout = timeout; + mav_array_memcpy(packet.name, name, sizeof(char)*100); + mav_array_memcpy(packet.arguments, arguments, sizeof(char)*147); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_PROCESS_INFO, (const char *)&packet, 255); +#endif +} + +#endif + +// MESSAGE WATCHDOG_PROCESS_INFO UNPACKING + + +/** + * @brief Get field watchdog_id from watchdog_process_info message + * + * @return Watchdog ID + */ +static inline uint16_t mavlink_msg_watchdog_process_info_get_watchdog_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field process_id from watchdog_process_info message + * + * @return Process ID + */ +static inline uint16_t mavlink_msg_watchdog_process_info_get_process_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Get field name from watchdog_process_info message + * + * @return Process name + */ +static inline uint16_t mavlink_msg_watchdog_process_info_get_name(const mavlink_message_t* msg, char *name) +{ + return _MAV_RETURN_char_array(msg, name, 100, 4); +} + +/** + * @brief Get field arguments from watchdog_process_info message + * + * @return Process arguments + */ +static inline uint16_t mavlink_msg_watchdog_process_info_get_arguments(const mavlink_message_t* msg, char *arguments) +{ + return _MAV_RETURN_char_array(msg, arguments, 147, 104); +} + +/** + * @brief Get field timeout from watchdog_process_info message + * + * @return Timeout (seconds) + */ +static inline int32_t mavlink_msg_watchdog_process_info_get_timeout(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 251); +} + +/** + * @brief Decode a watchdog_process_info message into a struct + * + * @param msg The message to decode + * @param watchdog_process_info C-struct to decode the message contents into + */ +static inline void mavlink_msg_watchdog_process_info_decode(const mavlink_message_t* msg, mavlink_watchdog_process_info_t* watchdog_process_info) +{ +#if MAVLINK_NEED_BYTE_SWAP + watchdog_process_info->watchdog_id = mavlink_msg_watchdog_process_info_get_watchdog_id(msg); + watchdog_process_info->process_id = mavlink_msg_watchdog_process_info_get_process_id(msg); + mavlink_msg_watchdog_process_info_get_name(msg, watchdog_process_info->name); + mavlink_msg_watchdog_process_info_get_arguments(msg, watchdog_process_info->arguments); + watchdog_process_info->timeout = mavlink_msg_watchdog_process_info_get_timeout(msg); +#else + memcpy(watchdog_process_info, _MAV_PAYLOAD(msg), 255); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_watchdog_process_status.h b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_watchdog_process_status.h new file mode 100644 index 0000000000..de5c7b2b21 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/mavlink_msg_watchdog_process_status.h @@ -0,0 +1,254 @@ +// MESSAGE WATCHDOG_PROCESS_STATUS PACKING + +#define MAVLINK_MSG_ID_WATCHDOG_PROCESS_STATUS 182 + +typedef struct __mavlink_watchdog_process_status_t +{ + uint16_t watchdog_id; ///< Watchdog ID + uint16_t process_id; ///< Process ID + uint8_t state; ///< Is running / finished / suspended / crashed + uint8_t muted; ///< Is muted + int32_t pid; ///< PID + uint16_t crashes; ///< Number of crashes +} mavlink_watchdog_process_status_t; + +#define MAVLINK_MSG_ID_WATCHDOG_PROCESS_STATUS_LEN 12 +#define MAVLINK_MSG_ID_182_LEN 12 + + + +#define MAVLINK_MESSAGE_INFO_WATCHDOG_PROCESS_STATUS { \ + "WATCHDOG_PROCESS_STATUS", \ + 6, \ + { { "watchdog_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_watchdog_process_status_t, watchdog_id) }, \ + { "process_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_watchdog_process_status_t, process_id) }, \ + { "state", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_watchdog_process_status_t, state) }, \ + { "muted", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_watchdog_process_status_t, muted) }, \ + { "pid", NULL, MAVLINK_TYPE_INT32_T, 0, 6, offsetof(mavlink_watchdog_process_status_t, pid) }, \ + { "crashes", NULL, MAVLINK_TYPE_UINT16_T, 0, 10, offsetof(mavlink_watchdog_process_status_t, crashes) }, \ + } \ +} + + +/** + * @brief Pack a watchdog_process_status message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param state Is running / finished / suspended / crashed + * @param muted Is muted + * @param pid PID + * @param crashes Number of crashes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_process_status_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t watchdog_id, uint16_t process_id, uint8_t state, uint8_t muted, int32_t pid, uint16_t crashes) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_id); + _mav_put_uint8_t(buf, 4, state); + _mav_put_uint8_t(buf, 5, muted); + _mav_put_int32_t(buf, 6, pid); + _mav_put_uint16_t(buf, 10, crashes); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_watchdog_process_status_t packet; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.state = state; + packet.muted = muted; + packet.pid = pid; + packet.crashes = crashes; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_PROCESS_STATUS; + return mavlink_finalize_message(msg, system_id, component_id, 12); +} + +/** + * @brief Pack a watchdog_process_status message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param state Is running / finished / suspended / crashed + * @param muted Is muted + * @param pid PID + * @param crashes Number of crashes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_process_status_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t watchdog_id,uint16_t process_id,uint8_t state,uint8_t muted,int32_t pid,uint16_t crashes) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_id); + _mav_put_uint8_t(buf, 4, state); + _mav_put_uint8_t(buf, 5, muted); + _mav_put_int32_t(buf, 6, pid); + _mav_put_uint16_t(buf, 10, crashes); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_watchdog_process_status_t packet; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.state = state; + packet.muted = muted; + packet.pid = pid; + packet.crashes = crashes; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_PROCESS_STATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12); +} + +/** + * @brief Encode a watchdog_process_status struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param watchdog_process_status C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_watchdog_process_status_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_watchdog_process_status_t* watchdog_process_status) +{ + return mavlink_msg_watchdog_process_status_pack(system_id, component_id, msg, watchdog_process_status->watchdog_id, watchdog_process_status->process_id, watchdog_process_status->state, watchdog_process_status->muted, watchdog_process_status->pid, watchdog_process_status->crashes); +} + +/** + * @brief Send a watchdog_process_status message + * @param chan MAVLink channel to send the message + * + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param state Is running / finished / suspended / crashed + * @param muted Is muted + * @param pid PID + * @param crashes Number of crashes + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_watchdog_process_status_send(mavlink_channel_t chan, uint16_t watchdog_id, uint16_t process_id, uint8_t state, uint8_t muted, int32_t pid, uint16_t crashes) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_id); + _mav_put_uint8_t(buf, 4, state); + _mav_put_uint8_t(buf, 5, muted); + _mav_put_int32_t(buf, 6, pid); + _mav_put_uint16_t(buf, 10, crashes); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_PROCESS_STATUS, buf, 12); +#else + mavlink_watchdog_process_status_t packet; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.state = state; + packet.muted = muted; + packet.pid = pid; + packet.crashes = crashes; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_PROCESS_STATUS, (const char *)&packet, 12); +#endif +} + +#endif + +// MESSAGE WATCHDOG_PROCESS_STATUS UNPACKING + + +/** + * @brief Get field watchdog_id from watchdog_process_status message + * + * @return Watchdog ID + */ +static inline uint16_t mavlink_msg_watchdog_process_status_get_watchdog_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field process_id from watchdog_process_status message + * + * @return Process ID + */ +static inline uint16_t mavlink_msg_watchdog_process_status_get_process_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Get field state from watchdog_process_status message + * + * @return Is running / finished / suspended / crashed + */ +static inline uint8_t mavlink_msg_watchdog_process_status_get_state(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field muted from watchdog_process_status message + * + * @return Is muted + */ +static inline uint8_t mavlink_msg_watchdog_process_status_get_muted(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field pid from watchdog_process_status message + * + * @return PID + */ +static inline int32_t mavlink_msg_watchdog_process_status_get_pid(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 6); +} + +/** + * @brief Get field crashes from watchdog_process_status message + * + * @return Number of crashes + */ +static inline uint16_t mavlink_msg_watchdog_process_status_get_crashes(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 10); +} + +/** + * @brief Decode a watchdog_process_status message into a struct + * + * @param msg The message to decode + * @param watchdog_process_status C-struct to decode the message contents into + */ +static inline void mavlink_msg_watchdog_process_status_decode(const mavlink_message_t* msg, mavlink_watchdog_process_status_t* watchdog_process_status) +{ +#if MAVLINK_NEED_BYTE_SWAP + watchdog_process_status->watchdog_id = mavlink_msg_watchdog_process_status_get_watchdog_id(msg); + watchdog_process_status->process_id = mavlink_msg_watchdog_process_status_get_process_id(msg); + watchdog_process_status->state = mavlink_msg_watchdog_process_status_get_state(msg); + watchdog_process_status->muted = mavlink_msg_watchdog_process_status_get_muted(msg); + watchdog_process_status->pid = mavlink_msg_watchdog_process_status_get_pid(msg); + watchdog_process_status->crashes = mavlink_msg_watchdog_process_status_get_crashes(msg); +#else + memcpy(watchdog_process_status, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/pixhawk/pixhawk.h b/mavlink/include/mavlink/v0.9/pixhawk/pixhawk.h new file mode 100644 index 0000000000..feb759ef99 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/pixhawk.h @@ -0,0 +1,86 @@ +/** @file + * @brief MAVLink comm protocol generated from pixhawk.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef PIXHAWK_H +#define PIXHAWK_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {3, 4, 8, 14, 8, 28, 3, 32, 0, 2, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 19, 2, 23, 21, 0, 37, 26, 101, 26, 16, 32, 32, 37, 32, 11, 17, 17, 16, 18, 36, 4, 4, 2, 2, 4, 2, 2, 3, 14, 12, 18, 16, 8, 27, 25, 18, 18, 24, 24, 0, 0, 0, 26, 16, 36, 5, 6, 56, 26, 21, 18, 0, 0, 18, 20, 20, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 52, 1, 92, 0, 32, 32, 20, 20, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 26, 16, 0, 0, 0, 0, 0, 0, 0, 4, 255, 12, 6, 0, 0, 0, 0, 0, 0, 106, 43, 55, 8, 255, 53, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 14, 14, 51, 5} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {72, 39, 190, 92, 191, 217, 104, 119, 0, 219, 60, 186, 10, 0, 0, 0, 0, 0, 0, 0, 89, 159, 162, 121, 0, 149, 222, 110, 179, 136, 66, 126, 185, 147, 112, 252, 162, 215, 229, 128, 9, 106, 101, 213, 4, 229, 21, 214, 215, 14, 206, 50, 157, 126, 108, 213, 95, 5, 127, 0, 0, 0, 57, 126, 130, 119, 193, 191, 236, 158, 143, 0, 0, 104, 123, 131, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 86, 95, 49, 0, 158, 56, 208, 218, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 136, 140, 0, 0, 0, 0, 0, 0, 0, 153, 110, 92, 188, 0, 0, 0, 0, 0, 0, 106, 154, 83, 98, 223, 254, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 224, 60, 106, 7} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, MAVLINK_MESSAGE_INFO_BOOT, MAVLINK_MESSAGE_INFO_SYSTEM_TIME, MAVLINK_MESSAGE_INFO_PING, MAVLINK_MESSAGE_INFO_SYSTEM_TIME_UTC, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK, MAVLINK_MESSAGE_INFO_AUTH_KEY, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_ACTION_ACK, MAVLINK_MESSAGE_INFO_ACTION, MAVLINK_MESSAGE_INFO_SET_MODE, MAVLINK_MESSAGE_INFO_SET_NAV_MODE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST, MAVLINK_MESSAGE_INFO_PARAM_VALUE, MAVLINK_MESSAGE_INFO_PARAM_SET, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_GPS_RAW_INT, MAVLINK_MESSAGE_INFO_SCALED_IMU, MAVLINK_MESSAGE_INFO_GPS_STATUS, MAVLINK_MESSAGE_INFO_RAW_IMU, MAVLINK_MESSAGE_INFO_RAW_PRESSURE, MAVLINK_MESSAGE_INFO_ATTITUDE, MAVLINK_MESSAGE_INFO_LOCAL_POSITION, MAVLINK_MESSAGE_INFO_GPS_RAW, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION, MAVLINK_MESSAGE_INFO_SYS_STATUS, MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW, MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED, MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW, MAVLINK_MESSAGE_INFO_SCALED_PRESSURE, MAVLINK_MESSAGE_INFO_WAYPOINT, MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST, MAVLINK_MESSAGE_INFO_WAYPOINT_SET_CURRENT, MAVLINK_MESSAGE_INFO_WAYPOINT_CURRENT, MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST_LIST, MAVLINK_MESSAGE_INFO_WAYPOINT_COUNT, MAVLINK_MESSAGE_INFO_WAYPOINT_CLEAR_ALL, MAVLINK_MESSAGE_INFO_WAYPOINT_REACHED, MAVLINK_MESSAGE_INFO_WAYPOINT_ACK, MAVLINK_MESSAGE_INFO_GPS_SET_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_GPS_LOCAL_ORIGIN_SET, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT_SET, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_CONTROL_STATUS, MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT, MAVLINK_MESSAGE_INFO_POSITION_TARGET, MAVLINK_MESSAGE_INFO_STATE_CORRECTION, MAVLINK_MESSAGE_INFO_SET_ALTITUDE, MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM, MAVLINK_MESSAGE_INFO_HIL_STATE, MAVLINK_MESSAGE_INFO_HIL_CONTROLS, MAVLINK_MESSAGE_INFO_MANUAL_CONTROL, MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT, MAVLINK_MESSAGE_INFO_VFR_HUD, MAVLINK_MESSAGE_INFO_COMMAND, MAVLINK_MESSAGE_INFO_COMMAND_ACK, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OPTICAL_FLOW, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OBJECT_DETECTION_EVENT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_SET_CAM_SHUTTER, MAVLINK_MESSAGE_INFO_IMAGE_TRIGGERED, MAVLINK_MESSAGE_INFO_IMAGE_TRIGGER_CONTROL, MAVLINK_MESSAGE_INFO_IMAGE_AVAILABLE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_VISION_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VICON_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VISION_SPEED_ESTIMATE, MAVLINK_MESSAGE_INFO_POSITION_CONTROL_SETPOINT_SET, MAVLINK_MESSAGE_INFO_POSITION_CONTROL_OFFSET_SET, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_POSITION_CONTROL_SETPOINT, MAVLINK_MESSAGE_INFO_MARKER, MAVLINK_MESSAGE_INFO_RAW_AUX, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_WATCHDOG_HEARTBEAT, MAVLINK_MESSAGE_INFO_WATCHDOG_PROCESS_INFO, MAVLINK_MESSAGE_INFO_WATCHDOG_PROCESS_STATUS, MAVLINK_MESSAGE_INFO_WATCHDOG_COMMAND, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PATTERN_DETECTED, MAVLINK_MESSAGE_INFO_POINT_OF_INTEREST, MAVLINK_MESSAGE_INFO_POINT_OF_INTEREST_CONNECTION, MAVLINK_MESSAGE_INFO_DATA_TRANSMISSION_HANDSHAKE, MAVLINK_MESSAGE_INFO_ENCAPSULATED_DATA, MAVLINK_MESSAGE_INFO_BRIEF_FEATURE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_ATTITUDE_CONTROL, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_DEBUG_VECT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT, MAVLINK_MESSAGE_INFO_STATUSTEXT, MAVLINK_MESSAGE_INFO_DEBUG} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_PIXHAWK + +#include "../common/common.h" + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +// ENUM DEFINITIONS + + +/** @brief Content Types for data transmission handshake */ +#ifndef HAVE_ENUM_DATA_TYPES +#define HAVE_ENUM_DATA_TYPES +enum DATA_TYPES +{ + DATA_TYPE_JPEG_IMAGE=1, /* | */ + DATA_TYPE_RAW_IMAGE=2, /* | */ + DATA_TYPE_KINECT=3, /* | */ + DATA_TYPES_ENUM_END=4, /* | */ +}; +#endif + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_set_cam_shutter.h" +#include "./mavlink_msg_image_triggered.h" +#include "./mavlink_msg_image_trigger_control.h" +#include "./mavlink_msg_image_available.h" +#include "./mavlink_msg_vision_position_estimate.h" +#include "./mavlink_msg_vicon_position_estimate.h" +#include "./mavlink_msg_vision_speed_estimate.h" +#include "./mavlink_msg_position_control_setpoint_set.h" +#include "./mavlink_msg_position_control_offset_set.h" +#include "./mavlink_msg_position_control_setpoint.h" +#include "./mavlink_msg_marker.h" +#include "./mavlink_msg_raw_aux.h" +#include "./mavlink_msg_watchdog_heartbeat.h" +#include "./mavlink_msg_watchdog_process_info.h" +#include "./mavlink_msg_watchdog_process_status.h" +#include "./mavlink_msg_watchdog_command.h" +#include "./mavlink_msg_pattern_detected.h" +#include "./mavlink_msg_point_of_interest.h" +#include "./mavlink_msg_point_of_interest_connection.h" +#include "./mavlink_msg_data_transmission_handshake.h" +#include "./mavlink_msg_encapsulated_data.h" +#include "./mavlink_msg_brief_feature.h" +#include "./mavlink_msg_attitude_control.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // PIXHAWK_H diff --git a/mavlink/include/mavlink/v0.9/pixhawk/testsuite.h b/mavlink/include/mavlink/v0.9/pixhawk/testsuite.h new file mode 100644 index 0000000000..3e18abc827 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/pixhawk/testsuite.h @@ -0,0 +1,1312 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from pixhawk.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef PIXHAWK_TESTSUITE_H +#define PIXHAWK_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL +static void mavlink_test_common(uint8_t, uint8_t, mavlink_message_t *last_msg); +static void mavlink_test_pixhawk(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_test_common(system_id, component_id, last_msg); + mavlink_test_pixhawk(system_id, component_id, last_msg); +} +#endif + +#include "../common/testsuite.h" + + +static void mavlink_test_set_cam_shutter(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_set_cam_shutter_t packet_in = { + 5, + 72, + 139, + 17391, + 17495, + 66.0, + }; + mavlink_set_cam_shutter_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.cam_no = packet_in.cam_no; + packet1.cam_mode = packet_in.cam_mode; + packet1.trigger_pin = packet_in.trigger_pin; + packet1.interval = packet_in.interval; + packet1.exposure = packet_in.exposure; + packet1.gain = packet_in.gain; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_set_cam_shutter_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_set_cam_shutter_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_set_cam_shutter_pack(system_id, component_id, &msg , packet1.cam_no , packet1.cam_mode , packet1.trigger_pin , packet1.interval , packet1.exposure , packet1.gain ); + mavlink_msg_set_cam_shutter_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_set_cam_shutter_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.cam_no , packet1.cam_mode , packet1.trigger_pin , packet1.interval , packet1.exposure , packet1.gain ); + mavlink_msg_set_cam_shutter_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; ilen + MAVLINK_NUM_NON_PAYLOAD_BYTES; +} + +#if MAVLINK_NEED_BYTE_SWAP +static inline void byte_swap_2(char *dst, const char *src) +{ + dst[0] = src[1]; + dst[1] = src[0]; +} +static inline void byte_swap_4(char *dst, const char *src) +{ + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; +} +static inline void byte_swap_8(char *dst, const char *src) +{ + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; +} +#elif !MAVLINK_ALIGNED_FIELDS +static inline void byte_copy_2(char *dst, const char *src) +{ + dst[0] = src[0]; + dst[1] = src[1]; +} +static inline void byte_copy_4(char *dst, const char *src) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} +static inline void byte_copy_8(char *dst, const char *src) +{ + memcpy(dst, src, 8); +} +#endif + +#define _mav_put_uint8_t(buf, wire_offset, b) buf[wire_offset] = (uint8_t)b +#define _mav_put_int8_t(buf, wire_offset, b) buf[wire_offset] = (int8_t)b +#define _mav_put_char(buf, wire_offset, b) buf[wire_offset] = b + +#if MAVLINK_NEED_BYTE_SWAP +#define _mav_put_uint16_t(buf, wire_offset, b) byte_swap_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_int16_t(buf, wire_offset, b) byte_swap_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint32_t(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_int32_t(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint64_t(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_int64_t(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_float(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_double(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b) +#elif !MAVLINK_ALIGNED_FIELDS +#define _mav_put_uint16_t(buf, wire_offset, b) byte_copy_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_int16_t(buf, wire_offset, b) byte_copy_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint32_t(buf, wire_offset, b) byte_copy_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_int32_t(buf, wire_offset, b) byte_copy_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint64_t(buf, wire_offset, b) byte_copy_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_int64_t(buf, wire_offset, b) byte_copy_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_float(buf, wire_offset, b) byte_copy_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_double(buf, wire_offset, b) byte_copy_8(&buf[wire_offset], (const char *)&b) +#else +#define _mav_put_uint16_t(buf, wire_offset, b) *(uint16_t *)&buf[wire_offset] = b +#define _mav_put_int16_t(buf, wire_offset, b) *(int16_t *)&buf[wire_offset] = b +#define _mav_put_uint32_t(buf, wire_offset, b) *(uint32_t *)&buf[wire_offset] = b +#define _mav_put_int32_t(buf, wire_offset, b) *(int32_t *)&buf[wire_offset] = b +#define _mav_put_uint64_t(buf, wire_offset, b) *(uint64_t *)&buf[wire_offset] = b +#define _mav_put_int64_t(buf, wire_offset, b) *(int64_t *)&buf[wire_offset] = b +#define _mav_put_float(buf, wire_offset, b) *(float *)&buf[wire_offset] = b +#define _mav_put_double(buf, wire_offset, b) *(double *)&buf[wire_offset] = b +#endif + +/* + like memcpy(), but if src is NULL, do a memset to zero + */ +static void mav_array_memcpy(void *dest, const void *src, size_t n) +{ + if (src == NULL) { + memset(dest, 0, n); + } else { + memcpy(dest, src, n); + } +} + +/* + * Place a char array into a buffer + */ +static inline void _mav_put_char_array(char *buf, uint8_t wire_offset, const char *b, uint8_t array_length) +{ + mav_array_memcpy(&buf[wire_offset], b, array_length); +} + +/* + * Place a uint8_t array into a buffer + */ +static inline void _mav_put_uint8_t_array(char *buf, uint8_t wire_offset, const uint8_t *b, uint8_t array_length) +{ + mav_array_memcpy(&buf[wire_offset], b, array_length); +} + +/* + * Place a int8_t array into a buffer + */ +static inline void _mav_put_int8_t_array(char *buf, uint8_t wire_offset, const int8_t *b, uint8_t array_length) +{ + mav_array_memcpy(&buf[wire_offset], b, array_length); +} + +#if MAVLINK_NEED_BYTE_SWAP +#define _MAV_PUT_ARRAY(TYPE, V) \ +static inline void _mav_put_ ## TYPE ##_array(char *buf, uint8_t wire_offset, const TYPE *b, uint8_t array_length) \ +{ \ + if (b == NULL) { \ + memset(&buf[wire_offset], 0, array_length*sizeof(TYPE)); \ + } else { \ + uint16_t i; \ + for (i=0; imsgid = MAVLINK_MSG_ID_AIR_DATA; + return mavlink_finalize_message(msg, system_id, component_id, 10); +} + +/** + * @brief Pack a air_data message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param dynamicPressure Dynamic pressure (Pa) + * @param staticPressure Static pressure (Pa) + * @param temperature Board temperature + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_air_data_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float dynamicPressure,float staticPressure,uint16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[10]; + _mav_put_float(buf, 0, dynamicPressure); + _mav_put_float(buf, 4, staticPressure); + _mav_put_uint16_t(buf, 8, temperature); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 10); +#else + mavlink_air_data_t packet; + packet.dynamicPressure = dynamicPressure; + packet.staticPressure = staticPressure; + packet.temperature = temperature; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 10); +#endif + + msg->msgid = MAVLINK_MSG_ID_AIR_DATA; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 10); +} + +/** + * @brief Encode a air_data struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param air_data C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_air_data_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_air_data_t* air_data) +{ + return mavlink_msg_air_data_pack(system_id, component_id, msg, air_data->dynamicPressure, air_data->staticPressure, air_data->temperature); +} + +/** + * @brief Send a air_data message + * @param chan MAVLink channel to send the message + * + * @param dynamicPressure Dynamic pressure (Pa) + * @param staticPressure Static pressure (Pa) + * @param temperature Board temperature + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_air_data_send(mavlink_channel_t chan, float dynamicPressure, float staticPressure, uint16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[10]; + _mav_put_float(buf, 0, dynamicPressure); + _mav_put_float(buf, 4, staticPressure); + _mav_put_uint16_t(buf, 8, temperature); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AIR_DATA, buf, 10); +#else + mavlink_air_data_t packet; + packet.dynamicPressure = dynamicPressure; + packet.staticPressure = staticPressure; + packet.temperature = temperature; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AIR_DATA, (const char *)&packet, 10); +#endif +} + +#endif + +// MESSAGE AIR_DATA UNPACKING + + +/** + * @brief Get field dynamicPressure from air_data message + * + * @return Dynamic pressure (Pa) + */ +static inline float mavlink_msg_air_data_get_dynamicPressure(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field staticPressure from air_data message + * + * @return Static pressure (Pa) + */ +static inline float mavlink_msg_air_data_get_staticPressure(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field temperature from air_data message + * + * @return Board temperature + */ +static inline uint16_t mavlink_msg_air_data_get_temperature(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Decode a air_data message into a struct + * + * @param msg The message to decode + * @param air_data C-struct to decode the message contents into + */ +static inline void mavlink_msg_air_data_decode(const mavlink_message_t* msg, mavlink_air_data_t* air_data) +{ +#if MAVLINK_NEED_BYTE_SWAP + air_data->dynamicPressure = mavlink_msg_air_data_get_dynamicPressure(msg); + air_data->staticPressure = mavlink_msg_air_data_get_staticPressure(msg); + air_data->temperature = mavlink_msg_air_data_get_temperature(msg); +#else + memcpy(air_data, _MAV_PAYLOAD(msg), 10); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_cpu_load.h b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_cpu_load.h new file mode 100644 index 0000000000..a3bc972f1b --- /dev/null +++ b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_cpu_load.h @@ -0,0 +1,188 @@ +// MESSAGE CPU_LOAD PACKING + +#define MAVLINK_MSG_ID_CPU_LOAD 170 + +typedef struct __mavlink_cpu_load_t +{ + uint8_t sensLoad; ///< Sensor DSC Load + uint8_t ctrlLoad; ///< Control DSC Load + uint16_t batVolt; ///< Battery Voltage in millivolts +} mavlink_cpu_load_t; + +#define MAVLINK_MSG_ID_CPU_LOAD_LEN 4 +#define MAVLINK_MSG_ID_170_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_CPU_LOAD { \ + "CPU_LOAD", \ + 3, \ + { { "sensLoad", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_cpu_load_t, sensLoad) }, \ + { "ctrlLoad", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_cpu_load_t, ctrlLoad) }, \ + { "batVolt", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_cpu_load_t, batVolt) }, \ + } \ +} + + +/** + * @brief Pack a cpu_load message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param sensLoad Sensor DSC Load + * @param ctrlLoad Control DSC Load + * @param batVolt Battery Voltage in millivolts + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_cpu_load_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t sensLoad, uint8_t ctrlLoad, uint16_t batVolt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, sensLoad); + _mav_put_uint8_t(buf, 1, ctrlLoad); + _mav_put_uint16_t(buf, 2, batVolt); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_cpu_load_t packet; + packet.sensLoad = sensLoad; + packet.ctrlLoad = ctrlLoad; + packet.batVolt = batVolt; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_CPU_LOAD; + return mavlink_finalize_message(msg, system_id, component_id, 4); +} + +/** + * @brief Pack a cpu_load message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param sensLoad Sensor DSC Load + * @param ctrlLoad Control DSC Load + * @param batVolt Battery Voltage in millivolts + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_cpu_load_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t sensLoad,uint8_t ctrlLoad,uint16_t batVolt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, sensLoad); + _mav_put_uint8_t(buf, 1, ctrlLoad); + _mav_put_uint16_t(buf, 2, batVolt); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_cpu_load_t packet; + packet.sensLoad = sensLoad; + packet.ctrlLoad = ctrlLoad; + packet.batVolt = batVolt; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_CPU_LOAD; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4); +} + +/** + * @brief Encode a cpu_load struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param cpu_load C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_cpu_load_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_cpu_load_t* cpu_load) +{ + return mavlink_msg_cpu_load_pack(system_id, component_id, msg, cpu_load->sensLoad, cpu_load->ctrlLoad, cpu_load->batVolt); +} + +/** + * @brief Send a cpu_load message + * @param chan MAVLink channel to send the message + * + * @param sensLoad Sensor DSC Load + * @param ctrlLoad Control DSC Load + * @param batVolt Battery Voltage in millivolts + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_cpu_load_send(mavlink_channel_t chan, uint8_t sensLoad, uint8_t ctrlLoad, uint16_t batVolt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, sensLoad); + _mav_put_uint8_t(buf, 1, ctrlLoad); + _mav_put_uint16_t(buf, 2, batVolt); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CPU_LOAD, buf, 4); +#else + mavlink_cpu_load_t packet; + packet.sensLoad = sensLoad; + packet.ctrlLoad = ctrlLoad; + packet.batVolt = batVolt; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CPU_LOAD, (const char *)&packet, 4); +#endif +} + +#endif + +// MESSAGE CPU_LOAD UNPACKING + + +/** + * @brief Get field sensLoad from cpu_load message + * + * @return Sensor DSC Load + */ +static inline uint8_t mavlink_msg_cpu_load_get_sensLoad(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field ctrlLoad from cpu_load message + * + * @return Control DSC Load + */ +static inline uint8_t mavlink_msg_cpu_load_get_ctrlLoad(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field batVolt from cpu_load message + * + * @return Battery Voltage in millivolts + */ +static inline uint16_t mavlink_msg_cpu_load_get_batVolt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Decode a cpu_load message into a struct + * + * @param msg The message to decode + * @param cpu_load C-struct to decode the message contents into + */ +static inline void mavlink_msg_cpu_load_decode(const mavlink_message_t* msg, mavlink_cpu_load_t* cpu_load) +{ +#if MAVLINK_NEED_BYTE_SWAP + cpu_load->sensLoad = mavlink_msg_cpu_load_get_sensLoad(msg); + cpu_load->ctrlLoad = mavlink_msg_cpu_load_get_ctrlLoad(msg); + cpu_load->batVolt = mavlink_msg_cpu_load_get_batVolt(msg); +#else + memcpy(cpu_load, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_ctrl_srfc_pt.h b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_ctrl_srfc_pt.h new file mode 100644 index 0000000000..d6f94e1dac --- /dev/null +++ b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_ctrl_srfc_pt.h @@ -0,0 +1,166 @@ +// MESSAGE CTRL_SRFC_PT PACKING + +#define MAVLINK_MSG_ID_CTRL_SRFC_PT 181 + +typedef struct __mavlink_ctrl_srfc_pt_t +{ + uint8_t target; ///< The system setting the commands + uint16_t bitfieldPt; ///< Bitfield containing the PT configuration +} mavlink_ctrl_srfc_pt_t; + +#define MAVLINK_MSG_ID_CTRL_SRFC_PT_LEN 3 +#define MAVLINK_MSG_ID_181_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_CTRL_SRFC_PT { \ + "CTRL_SRFC_PT", \ + 2, \ + { { "target", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_ctrl_srfc_pt_t, target) }, \ + { "bitfieldPt", NULL, MAVLINK_TYPE_UINT16_T, 0, 1, offsetof(mavlink_ctrl_srfc_pt_t, bitfieldPt) }, \ + } \ +} + + +/** + * @brief Pack a ctrl_srfc_pt message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target The system setting the commands + * @param bitfieldPt Bitfield containing the PT configuration + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ctrl_srfc_pt_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target, uint16_t bitfieldPt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint16_t(buf, 1, bitfieldPt); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_ctrl_srfc_pt_t packet; + packet.target = target; + packet.bitfieldPt = bitfieldPt; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_CTRL_SRFC_PT; + return mavlink_finalize_message(msg, system_id, component_id, 3); +} + +/** + * @brief Pack a ctrl_srfc_pt message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system setting the commands + * @param bitfieldPt Bitfield containing the PT configuration + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ctrl_srfc_pt_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,uint16_t bitfieldPt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint16_t(buf, 1, bitfieldPt); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_ctrl_srfc_pt_t packet; + packet.target = target; + packet.bitfieldPt = bitfieldPt; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_CTRL_SRFC_PT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3); +} + +/** + * @brief Encode a ctrl_srfc_pt struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param ctrl_srfc_pt C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_ctrl_srfc_pt_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_ctrl_srfc_pt_t* ctrl_srfc_pt) +{ + return mavlink_msg_ctrl_srfc_pt_pack(system_id, component_id, msg, ctrl_srfc_pt->target, ctrl_srfc_pt->bitfieldPt); +} + +/** + * @brief Send a ctrl_srfc_pt message + * @param chan MAVLink channel to send the message + * + * @param target The system setting the commands + * @param bitfieldPt Bitfield containing the PT configuration + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_ctrl_srfc_pt_send(mavlink_channel_t chan, uint8_t target, uint16_t bitfieldPt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint16_t(buf, 1, bitfieldPt); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CTRL_SRFC_PT, buf, 3); +#else + mavlink_ctrl_srfc_pt_t packet; + packet.target = target; + packet.bitfieldPt = bitfieldPt; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CTRL_SRFC_PT, (const char *)&packet, 3); +#endif +} + +#endif + +// MESSAGE CTRL_SRFC_PT UNPACKING + + +/** + * @brief Get field target from ctrl_srfc_pt message + * + * @return The system setting the commands + */ +static inline uint8_t mavlink_msg_ctrl_srfc_pt_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field bitfieldPt from ctrl_srfc_pt message + * + * @return Bitfield containing the PT configuration + */ +static inline uint16_t mavlink_msg_ctrl_srfc_pt_get_bitfieldPt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 1); +} + +/** + * @brief Decode a ctrl_srfc_pt message into a struct + * + * @param msg The message to decode + * @param ctrl_srfc_pt C-struct to decode the message contents into + */ +static inline void mavlink_msg_ctrl_srfc_pt_decode(const mavlink_message_t* msg, mavlink_ctrl_srfc_pt_t* ctrl_srfc_pt) +{ +#if MAVLINK_NEED_BYTE_SWAP + ctrl_srfc_pt->target = mavlink_msg_ctrl_srfc_pt_get_target(msg); + ctrl_srfc_pt->bitfieldPt = mavlink_msg_ctrl_srfc_pt_get_bitfieldPt(msg); +#else + memcpy(ctrl_srfc_pt, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_data_log.h b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_data_log.h new file mode 100644 index 0000000000..19a03e5c68 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_data_log.h @@ -0,0 +1,254 @@ +// MESSAGE DATA_LOG PACKING + +#define MAVLINK_MSG_ID_DATA_LOG 177 + +typedef struct __mavlink_data_log_t +{ + float fl_1; ///< Log value 1 + float fl_2; ///< Log value 2 + float fl_3; ///< Log value 3 + float fl_4; ///< Log value 4 + float fl_5; ///< Log value 5 + float fl_6; ///< Log value 6 +} mavlink_data_log_t; + +#define MAVLINK_MSG_ID_DATA_LOG_LEN 24 +#define MAVLINK_MSG_ID_177_LEN 24 + + + +#define MAVLINK_MESSAGE_INFO_DATA_LOG { \ + "DATA_LOG", \ + 6, \ + { { "fl_1", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_data_log_t, fl_1) }, \ + { "fl_2", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_data_log_t, fl_2) }, \ + { "fl_3", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_data_log_t, fl_3) }, \ + { "fl_4", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_data_log_t, fl_4) }, \ + { "fl_5", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_data_log_t, fl_5) }, \ + { "fl_6", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_data_log_t, fl_6) }, \ + } \ +} + + +/** + * @brief Pack a data_log message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param fl_1 Log value 1 + * @param fl_2 Log value 2 + * @param fl_3 Log value 3 + * @param fl_4 Log value 4 + * @param fl_5 Log value 5 + * @param fl_6 Log value 6 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_data_log_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float fl_1, float fl_2, float fl_3, float fl_4, float fl_5, float fl_6) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_float(buf, 0, fl_1); + _mav_put_float(buf, 4, fl_2); + _mav_put_float(buf, 8, fl_3); + _mav_put_float(buf, 12, fl_4); + _mav_put_float(buf, 16, fl_5); + _mav_put_float(buf, 20, fl_6); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_data_log_t packet; + packet.fl_1 = fl_1; + packet.fl_2 = fl_2; + packet.fl_3 = fl_3; + packet.fl_4 = fl_4; + packet.fl_5 = fl_5; + packet.fl_6 = fl_6; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_DATA_LOG; + return mavlink_finalize_message(msg, system_id, component_id, 24); +} + +/** + * @brief Pack a data_log message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param fl_1 Log value 1 + * @param fl_2 Log value 2 + * @param fl_3 Log value 3 + * @param fl_4 Log value 4 + * @param fl_5 Log value 5 + * @param fl_6 Log value 6 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_data_log_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float fl_1,float fl_2,float fl_3,float fl_4,float fl_5,float fl_6) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_float(buf, 0, fl_1); + _mav_put_float(buf, 4, fl_2); + _mav_put_float(buf, 8, fl_3); + _mav_put_float(buf, 12, fl_4); + _mav_put_float(buf, 16, fl_5); + _mav_put_float(buf, 20, fl_6); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_data_log_t packet; + packet.fl_1 = fl_1; + packet.fl_2 = fl_2; + packet.fl_3 = fl_3; + packet.fl_4 = fl_4; + packet.fl_5 = fl_5; + packet.fl_6 = fl_6; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_DATA_LOG; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 24); +} + +/** + * @brief Encode a data_log struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param data_log C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_data_log_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_data_log_t* data_log) +{ + return mavlink_msg_data_log_pack(system_id, component_id, msg, data_log->fl_1, data_log->fl_2, data_log->fl_3, data_log->fl_4, data_log->fl_5, data_log->fl_6); +} + +/** + * @brief Send a data_log message + * @param chan MAVLink channel to send the message + * + * @param fl_1 Log value 1 + * @param fl_2 Log value 2 + * @param fl_3 Log value 3 + * @param fl_4 Log value 4 + * @param fl_5 Log value 5 + * @param fl_6 Log value 6 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_data_log_send(mavlink_channel_t chan, float fl_1, float fl_2, float fl_3, float fl_4, float fl_5, float fl_6) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_float(buf, 0, fl_1); + _mav_put_float(buf, 4, fl_2); + _mav_put_float(buf, 8, fl_3); + _mav_put_float(buf, 12, fl_4); + _mav_put_float(buf, 16, fl_5); + _mav_put_float(buf, 20, fl_6); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DATA_LOG, buf, 24); +#else + mavlink_data_log_t packet; + packet.fl_1 = fl_1; + packet.fl_2 = fl_2; + packet.fl_3 = fl_3; + packet.fl_4 = fl_4; + packet.fl_5 = fl_5; + packet.fl_6 = fl_6; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DATA_LOG, (const char *)&packet, 24); +#endif +} + +#endif + +// MESSAGE DATA_LOG UNPACKING + + +/** + * @brief Get field fl_1 from data_log message + * + * @return Log value 1 + */ +static inline float mavlink_msg_data_log_get_fl_1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field fl_2 from data_log message + * + * @return Log value 2 + */ +static inline float mavlink_msg_data_log_get_fl_2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field fl_3 from data_log message + * + * @return Log value 3 + */ +static inline float mavlink_msg_data_log_get_fl_3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field fl_4 from data_log message + * + * @return Log value 4 + */ +static inline float mavlink_msg_data_log_get_fl_4(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field fl_5 from data_log message + * + * @return Log value 5 + */ +static inline float mavlink_msg_data_log_get_fl_5(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field fl_6 from data_log message + * + * @return Log value 6 + */ +static inline float mavlink_msg_data_log_get_fl_6(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Decode a data_log message into a struct + * + * @param msg The message to decode + * @param data_log C-struct to decode the message contents into + */ +static inline void mavlink_msg_data_log_decode(const mavlink_message_t* msg, mavlink_data_log_t* data_log) +{ +#if MAVLINK_NEED_BYTE_SWAP + data_log->fl_1 = mavlink_msg_data_log_get_fl_1(msg); + data_log->fl_2 = mavlink_msg_data_log_get_fl_2(msg); + data_log->fl_3 = mavlink_msg_data_log_get_fl_3(msg); + data_log->fl_4 = mavlink_msg_data_log_get_fl_4(msg); + data_log->fl_5 = mavlink_msg_data_log_get_fl_5(msg); + data_log->fl_6 = mavlink_msg_data_log_get_fl_6(msg); +#else + memcpy(data_log, _MAV_PAYLOAD(msg), 24); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_diagnostic.h b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_diagnostic.h new file mode 100644 index 0000000000..5cdf890aea --- /dev/null +++ b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_diagnostic.h @@ -0,0 +1,254 @@ +// MESSAGE DIAGNOSTIC PACKING + +#define MAVLINK_MSG_ID_DIAGNOSTIC 173 + +typedef struct __mavlink_diagnostic_t +{ + float diagFl1; ///< Diagnostic float 1 + float diagFl2; ///< Diagnostic float 2 + float diagFl3; ///< Diagnostic float 3 + int16_t diagSh1; ///< Diagnostic short 1 + int16_t diagSh2; ///< Diagnostic short 2 + int16_t diagSh3; ///< Diagnostic short 3 +} mavlink_diagnostic_t; + +#define MAVLINK_MSG_ID_DIAGNOSTIC_LEN 18 +#define MAVLINK_MSG_ID_173_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_DIAGNOSTIC { \ + "DIAGNOSTIC", \ + 6, \ + { { "diagFl1", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_diagnostic_t, diagFl1) }, \ + { "diagFl2", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_diagnostic_t, diagFl2) }, \ + { "diagFl3", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_diagnostic_t, diagFl3) }, \ + { "diagSh1", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_diagnostic_t, diagSh1) }, \ + { "diagSh2", NULL, MAVLINK_TYPE_INT16_T, 0, 14, offsetof(mavlink_diagnostic_t, diagSh2) }, \ + { "diagSh3", NULL, MAVLINK_TYPE_INT16_T, 0, 16, offsetof(mavlink_diagnostic_t, diagSh3) }, \ + } \ +} + + +/** + * @brief Pack a diagnostic message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param diagFl1 Diagnostic float 1 + * @param diagFl2 Diagnostic float 2 + * @param diagFl3 Diagnostic float 3 + * @param diagSh1 Diagnostic short 1 + * @param diagSh2 Diagnostic short 2 + * @param diagSh3 Diagnostic short 3 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_diagnostic_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float diagFl1, float diagFl2, float diagFl3, int16_t diagSh1, int16_t diagSh2, int16_t diagSh3) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, diagFl1); + _mav_put_float(buf, 4, diagFl2); + _mav_put_float(buf, 8, diagFl3); + _mav_put_int16_t(buf, 12, diagSh1); + _mav_put_int16_t(buf, 14, diagSh2); + _mav_put_int16_t(buf, 16, diagSh3); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_diagnostic_t packet; + packet.diagFl1 = diagFl1; + packet.diagFl2 = diagFl2; + packet.diagFl3 = diagFl3; + packet.diagSh1 = diagSh1; + packet.diagSh2 = diagSh2; + packet.diagSh3 = diagSh3; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_DIAGNOSTIC; + return mavlink_finalize_message(msg, system_id, component_id, 18); +} + +/** + * @brief Pack a diagnostic message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param diagFl1 Diagnostic float 1 + * @param diagFl2 Diagnostic float 2 + * @param diagFl3 Diagnostic float 3 + * @param diagSh1 Diagnostic short 1 + * @param diagSh2 Diagnostic short 2 + * @param diagSh3 Diagnostic short 3 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_diagnostic_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float diagFl1,float diagFl2,float diagFl3,int16_t diagSh1,int16_t diagSh2,int16_t diagSh3) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, diagFl1); + _mav_put_float(buf, 4, diagFl2); + _mav_put_float(buf, 8, diagFl3); + _mav_put_int16_t(buf, 12, diagSh1); + _mav_put_int16_t(buf, 14, diagSh2); + _mav_put_int16_t(buf, 16, diagSh3); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_diagnostic_t packet; + packet.diagFl1 = diagFl1; + packet.diagFl2 = diagFl2; + packet.diagFl3 = diagFl3; + packet.diagSh1 = diagSh1; + packet.diagSh2 = diagSh2; + packet.diagSh3 = diagSh3; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_DIAGNOSTIC; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18); +} + +/** + * @brief Encode a diagnostic struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param diagnostic C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_diagnostic_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_diagnostic_t* diagnostic) +{ + return mavlink_msg_diagnostic_pack(system_id, component_id, msg, diagnostic->diagFl1, diagnostic->diagFl2, diagnostic->diagFl3, diagnostic->diagSh1, diagnostic->diagSh2, diagnostic->diagSh3); +} + +/** + * @brief Send a diagnostic message + * @param chan MAVLink channel to send the message + * + * @param diagFl1 Diagnostic float 1 + * @param diagFl2 Diagnostic float 2 + * @param diagFl3 Diagnostic float 3 + * @param diagSh1 Diagnostic short 1 + * @param diagSh2 Diagnostic short 2 + * @param diagSh3 Diagnostic short 3 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_diagnostic_send(mavlink_channel_t chan, float diagFl1, float diagFl2, float diagFl3, int16_t diagSh1, int16_t diagSh2, int16_t diagSh3) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, diagFl1); + _mav_put_float(buf, 4, diagFl2); + _mav_put_float(buf, 8, diagFl3); + _mav_put_int16_t(buf, 12, diagSh1); + _mav_put_int16_t(buf, 14, diagSh2); + _mav_put_int16_t(buf, 16, diagSh3); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DIAGNOSTIC, buf, 18); +#else + mavlink_diagnostic_t packet; + packet.diagFl1 = diagFl1; + packet.diagFl2 = diagFl2; + packet.diagFl3 = diagFl3; + packet.diagSh1 = diagSh1; + packet.diagSh2 = diagSh2; + packet.diagSh3 = diagSh3; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DIAGNOSTIC, (const char *)&packet, 18); +#endif +} + +#endif + +// MESSAGE DIAGNOSTIC UNPACKING + + +/** + * @brief Get field diagFl1 from diagnostic message + * + * @return Diagnostic float 1 + */ +static inline float mavlink_msg_diagnostic_get_diagFl1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field diagFl2 from diagnostic message + * + * @return Diagnostic float 2 + */ +static inline float mavlink_msg_diagnostic_get_diagFl2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field diagFl3 from diagnostic message + * + * @return Diagnostic float 3 + */ +static inline float mavlink_msg_diagnostic_get_diagFl3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field diagSh1 from diagnostic message + * + * @return Diagnostic short 1 + */ +static inline int16_t mavlink_msg_diagnostic_get_diagSh1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Get field diagSh2 from diagnostic message + * + * @return Diagnostic short 2 + */ +static inline int16_t mavlink_msg_diagnostic_get_diagSh2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 14); +} + +/** + * @brief Get field diagSh3 from diagnostic message + * + * @return Diagnostic short 3 + */ +static inline int16_t mavlink_msg_diagnostic_get_diagSh3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 16); +} + +/** + * @brief Decode a diagnostic message into a struct + * + * @param msg The message to decode + * @param diagnostic C-struct to decode the message contents into + */ +static inline void mavlink_msg_diagnostic_decode(const mavlink_message_t* msg, mavlink_diagnostic_t* diagnostic) +{ +#if MAVLINK_NEED_BYTE_SWAP + diagnostic->diagFl1 = mavlink_msg_diagnostic_get_diagFl1(msg); + diagnostic->diagFl2 = mavlink_msg_diagnostic_get_diagFl2(msg); + diagnostic->diagFl3 = mavlink_msg_diagnostic_get_diagFl3(msg); + diagnostic->diagSh1 = mavlink_msg_diagnostic_get_diagSh1(msg); + diagnostic->diagSh2 = mavlink_msg_diagnostic_get_diagSh2(msg); + diagnostic->diagSh3 = mavlink_msg_diagnostic_get_diagSh3(msg); +#else + memcpy(diagnostic, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_gps_date_time.h b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_gps_date_time.h new file mode 100644 index 0000000000..6104fd7a7b --- /dev/null +++ b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_gps_date_time.h @@ -0,0 +1,276 @@ +// MESSAGE GPS_DATE_TIME PACKING + +#define MAVLINK_MSG_ID_GPS_DATE_TIME 179 + +typedef struct __mavlink_gps_date_time_t +{ + uint8_t year; ///< Year reported by Gps + uint8_t month; ///< Month reported by Gps + uint8_t day; ///< Day reported by Gps + uint8_t hour; ///< Hour reported by Gps + uint8_t min; ///< Min reported by Gps + uint8_t sec; ///< Sec reported by Gps + uint8_t visSat; ///< Visible sattelites reported by Gps +} mavlink_gps_date_time_t; + +#define MAVLINK_MSG_ID_GPS_DATE_TIME_LEN 7 +#define MAVLINK_MSG_ID_179_LEN 7 + + + +#define MAVLINK_MESSAGE_INFO_GPS_DATE_TIME { \ + "GPS_DATE_TIME", \ + 7, \ + { { "year", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_gps_date_time_t, year) }, \ + { "month", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_gps_date_time_t, month) }, \ + { "day", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_gps_date_time_t, day) }, \ + { "hour", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_gps_date_time_t, hour) }, \ + { "min", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_gps_date_time_t, min) }, \ + { "sec", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_gps_date_time_t, sec) }, \ + { "visSat", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_gps_date_time_t, visSat) }, \ + } \ +} + + +/** + * @brief Pack a gps_date_time message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param year Year reported by Gps + * @param month Month reported by Gps + * @param day Day reported by Gps + * @param hour Hour reported by Gps + * @param min Min reported by Gps + * @param sec Sec reported by Gps + * @param visSat Visible sattelites reported by Gps + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_date_time_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec, uint8_t visSat) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[7]; + _mav_put_uint8_t(buf, 0, year); + _mav_put_uint8_t(buf, 1, month); + _mav_put_uint8_t(buf, 2, day); + _mav_put_uint8_t(buf, 3, hour); + _mav_put_uint8_t(buf, 4, min); + _mav_put_uint8_t(buf, 5, sec); + _mav_put_uint8_t(buf, 6, visSat); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 7); +#else + mavlink_gps_date_time_t packet; + packet.year = year; + packet.month = month; + packet.day = day; + packet.hour = hour; + packet.min = min; + packet.sec = sec; + packet.visSat = visSat; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 7); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_DATE_TIME; + return mavlink_finalize_message(msg, system_id, component_id, 7); +} + +/** + * @brief Pack a gps_date_time message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param year Year reported by Gps + * @param month Month reported by Gps + * @param day Day reported by Gps + * @param hour Hour reported by Gps + * @param min Min reported by Gps + * @param sec Sec reported by Gps + * @param visSat Visible sattelites reported by Gps + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_date_time_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t year,uint8_t month,uint8_t day,uint8_t hour,uint8_t min,uint8_t sec,uint8_t visSat) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[7]; + _mav_put_uint8_t(buf, 0, year); + _mav_put_uint8_t(buf, 1, month); + _mav_put_uint8_t(buf, 2, day); + _mav_put_uint8_t(buf, 3, hour); + _mav_put_uint8_t(buf, 4, min); + _mav_put_uint8_t(buf, 5, sec); + _mav_put_uint8_t(buf, 6, visSat); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 7); +#else + mavlink_gps_date_time_t packet; + packet.year = year; + packet.month = month; + packet.day = day; + packet.hour = hour; + packet.min = min; + packet.sec = sec; + packet.visSat = visSat; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 7); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_DATE_TIME; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 7); +} + +/** + * @brief Encode a gps_date_time struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param gps_date_time C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_gps_date_time_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_gps_date_time_t* gps_date_time) +{ + return mavlink_msg_gps_date_time_pack(system_id, component_id, msg, gps_date_time->year, gps_date_time->month, gps_date_time->day, gps_date_time->hour, gps_date_time->min, gps_date_time->sec, gps_date_time->visSat); +} + +/** + * @brief Send a gps_date_time message + * @param chan MAVLink channel to send the message + * + * @param year Year reported by Gps + * @param month Month reported by Gps + * @param day Day reported by Gps + * @param hour Hour reported by Gps + * @param min Min reported by Gps + * @param sec Sec reported by Gps + * @param visSat Visible sattelites reported by Gps + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_gps_date_time_send(mavlink_channel_t chan, uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec, uint8_t visSat) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[7]; + _mav_put_uint8_t(buf, 0, year); + _mav_put_uint8_t(buf, 1, month); + _mav_put_uint8_t(buf, 2, day); + _mav_put_uint8_t(buf, 3, hour); + _mav_put_uint8_t(buf, 4, min); + _mav_put_uint8_t(buf, 5, sec); + _mav_put_uint8_t(buf, 6, visSat); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_DATE_TIME, buf, 7); +#else + mavlink_gps_date_time_t packet; + packet.year = year; + packet.month = month; + packet.day = day; + packet.hour = hour; + packet.min = min; + packet.sec = sec; + packet.visSat = visSat; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_DATE_TIME, (const char *)&packet, 7); +#endif +} + +#endif + +// MESSAGE GPS_DATE_TIME UNPACKING + + +/** + * @brief Get field year from gps_date_time message + * + * @return Year reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_year(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field month from gps_date_time message + * + * @return Month reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_month(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field day from gps_date_time message + * + * @return Day reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_day(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field hour from gps_date_time message + * + * @return Hour reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_hour(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field min from gps_date_time message + * + * @return Min reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_min(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field sec from gps_date_time message + * + * @return Sec reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_sec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field visSat from gps_date_time message + * + * @return Visible sattelites reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_visSat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Decode a gps_date_time message into a struct + * + * @param msg The message to decode + * @param gps_date_time C-struct to decode the message contents into + */ +static inline void mavlink_msg_gps_date_time_decode(const mavlink_message_t* msg, mavlink_gps_date_time_t* gps_date_time) +{ +#if MAVLINK_NEED_BYTE_SWAP + gps_date_time->year = mavlink_msg_gps_date_time_get_year(msg); + gps_date_time->month = mavlink_msg_gps_date_time_get_month(msg); + gps_date_time->day = mavlink_msg_gps_date_time_get_day(msg); + gps_date_time->hour = mavlink_msg_gps_date_time_get_hour(msg); + gps_date_time->min = mavlink_msg_gps_date_time_get_min(msg); + gps_date_time->sec = mavlink_msg_gps_date_time_get_sec(msg); + gps_date_time->visSat = mavlink_msg_gps_date_time_get_visSat(msg); +#else + memcpy(gps_date_time, _MAV_PAYLOAD(msg), 7); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_mid_lvl_cmds.h b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_mid_lvl_cmds.h new file mode 100644 index 0000000000..4ae723b440 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_mid_lvl_cmds.h @@ -0,0 +1,210 @@ +// MESSAGE MID_LVL_CMDS PACKING + +#define MAVLINK_MSG_ID_MID_LVL_CMDS 180 + +typedef struct __mavlink_mid_lvl_cmds_t +{ + uint8_t target; ///< The system setting the commands + float hCommand; ///< Commanded Airspeed + float uCommand; ///< Log value 2 + float rCommand; ///< Log value 3 +} mavlink_mid_lvl_cmds_t; + +#define MAVLINK_MSG_ID_MID_LVL_CMDS_LEN 13 +#define MAVLINK_MSG_ID_180_LEN 13 + + + +#define MAVLINK_MESSAGE_INFO_MID_LVL_CMDS { \ + "MID_LVL_CMDS", \ + 4, \ + { { "target", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_mid_lvl_cmds_t, target) }, \ + { "hCommand", NULL, MAVLINK_TYPE_FLOAT, 0, 1, offsetof(mavlink_mid_lvl_cmds_t, hCommand) }, \ + { "uCommand", NULL, MAVLINK_TYPE_FLOAT, 0, 5, offsetof(mavlink_mid_lvl_cmds_t, uCommand) }, \ + { "rCommand", NULL, MAVLINK_TYPE_FLOAT, 0, 9, offsetof(mavlink_mid_lvl_cmds_t, rCommand) }, \ + } \ +} + + +/** + * @brief Pack a mid_lvl_cmds message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target The system setting the commands + * @param hCommand Commanded Airspeed + * @param uCommand Log value 2 + * @param rCommand Log value 3 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mid_lvl_cmds_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target, float hCommand, float uCommand, float rCommand) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_float(buf, 1, hCommand); + _mav_put_float(buf, 5, uCommand); + _mav_put_float(buf, 9, rCommand); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 13); +#else + mavlink_mid_lvl_cmds_t packet; + packet.target = target; + packet.hCommand = hCommand; + packet.uCommand = uCommand; + packet.rCommand = rCommand; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 13); +#endif + + msg->msgid = MAVLINK_MSG_ID_MID_LVL_CMDS; + return mavlink_finalize_message(msg, system_id, component_id, 13); +} + +/** + * @brief Pack a mid_lvl_cmds message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system setting the commands + * @param hCommand Commanded Airspeed + * @param uCommand Log value 2 + * @param rCommand Log value 3 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mid_lvl_cmds_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,float hCommand,float uCommand,float rCommand) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_float(buf, 1, hCommand); + _mav_put_float(buf, 5, uCommand); + _mav_put_float(buf, 9, rCommand); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 13); +#else + mavlink_mid_lvl_cmds_t packet; + packet.target = target; + packet.hCommand = hCommand; + packet.uCommand = uCommand; + packet.rCommand = rCommand; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 13); +#endif + + msg->msgid = MAVLINK_MSG_ID_MID_LVL_CMDS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 13); +} + +/** + * @brief Encode a mid_lvl_cmds struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mid_lvl_cmds C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mid_lvl_cmds_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mid_lvl_cmds_t* mid_lvl_cmds) +{ + return mavlink_msg_mid_lvl_cmds_pack(system_id, component_id, msg, mid_lvl_cmds->target, mid_lvl_cmds->hCommand, mid_lvl_cmds->uCommand, mid_lvl_cmds->rCommand); +} + +/** + * @brief Send a mid_lvl_cmds message + * @param chan MAVLink channel to send the message + * + * @param target The system setting the commands + * @param hCommand Commanded Airspeed + * @param uCommand Log value 2 + * @param rCommand Log value 3 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mid_lvl_cmds_send(mavlink_channel_t chan, uint8_t target, float hCommand, float uCommand, float rCommand) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_float(buf, 1, hCommand); + _mav_put_float(buf, 5, uCommand); + _mav_put_float(buf, 9, rCommand); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MID_LVL_CMDS, buf, 13); +#else + mavlink_mid_lvl_cmds_t packet; + packet.target = target; + packet.hCommand = hCommand; + packet.uCommand = uCommand; + packet.rCommand = rCommand; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MID_LVL_CMDS, (const char *)&packet, 13); +#endif +} + +#endif + +// MESSAGE MID_LVL_CMDS UNPACKING + + +/** + * @brief Get field target from mid_lvl_cmds message + * + * @return The system setting the commands + */ +static inline uint8_t mavlink_msg_mid_lvl_cmds_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field hCommand from mid_lvl_cmds message + * + * @return Commanded Airspeed + */ +static inline float mavlink_msg_mid_lvl_cmds_get_hCommand(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 1); +} + +/** + * @brief Get field uCommand from mid_lvl_cmds message + * + * @return Log value 2 + */ +static inline float mavlink_msg_mid_lvl_cmds_get_uCommand(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 5); +} + +/** + * @brief Get field rCommand from mid_lvl_cmds message + * + * @return Log value 3 + */ +static inline float mavlink_msg_mid_lvl_cmds_get_rCommand(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 9); +} + +/** + * @brief Decode a mid_lvl_cmds message into a struct + * + * @param msg The message to decode + * @param mid_lvl_cmds C-struct to decode the message contents into + */ +static inline void mavlink_msg_mid_lvl_cmds_decode(const mavlink_message_t* msg, mavlink_mid_lvl_cmds_t* mid_lvl_cmds) +{ +#if MAVLINK_NEED_BYTE_SWAP + mid_lvl_cmds->target = mavlink_msg_mid_lvl_cmds_get_target(msg); + mid_lvl_cmds->hCommand = mavlink_msg_mid_lvl_cmds_get_hCommand(msg); + mid_lvl_cmds->uCommand = mavlink_msg_mid_lvl_cmds_get_uCommand(msg); + mid_lvl_cmds->rCommand = mavlink_msg_mid_lvl_cmds_get_rCommand(msg); +#else + memcpy(mid_lvl_cmds, _MAV_PAYLOAD(msg), 13); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_sensor_bias.h b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_sensor_bias.h new file mode 100644 index 0000000000..7afb96bd64 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_sensor_bias.h @@ -0,0 +1,254 @@ +// MESSAGE SENSOR_BIAS PACKING + +#define MAVLINK_MSG_ID_SENSOR_BIAS 172 + +typedef struct __mavlink_sensor_bias_t +{ + float axBias; ///< Accelerometer X bias (m/s) + float ayBias; ///< Accelerometer Y bias (m/s) + float azBias; ///< Accelerometer Z bias (m/s) + float gxBias; ///< Gyro X bias (rad/s) + float gyBias; ///< Gyro Y bias (rad/s) + float gzBias; ///< Gyro Z bias (rad/s) +} mavlink_sensor_bias_t; + +#define MAVLINK_MSG_ID_SENSOR_BIAS_LEN 24 +#define MAVLINK_MSG_ID_172_LEN 24 + + + +#define MAVLINK_MESSAGE_INFO_SENSOR_BIAS { \ + "SENSOR_BIAS", \ + 6, \ + { { "axBias", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_sensor_bias_t, axBias) }, \ + { "ayBias", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_sensor_bias_t, ayBias) }, \ + { "azBias", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_sensor_bias_t, azBias) }, \ + { "gxBias", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_sensor_bias_t, gxBias) }, \ + { "gyBias", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_sensor_bias_t, gyBias) }, \ + { "gzBias", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_sensor_bias_t, gzBias) }, \ + } \ +} + + +/** + * @brief Pack a sensor_bias message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param axBias Accelerometer X bias (m/s) + * @param ayBias Accelerometer Y bias (m/s) + * @param azBias Accelerometer Z bias (m/s) + * @param gxBias Gyro X bias (rad/s) + * @param gyBias Gyro Y bias (rad/s) + * @param gzBias Gyro Z bias (rad/s) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sensor_bias_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float axBias, float ayBias, float azBias, float gxBias, float gyBias, float gzBias) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_float(buf, 0, axBias); + _mav_put_float(buf, 4, ayBias); + _mav_put_float(buf, 8, azBias); + _mav_put_float(buf, 12, gxBias); + _mav_put_float(buf, 16, gyBias); + _mav_put_float(buf, 20, gzBias); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_sensor_bias_t packet; + packet.axBias = axBias; + packet.ayBias = ayBias; + packet.azBias = azBias; + packet.gxBias = gxBias; + packet.gyBias = gyBias; + packet.gzBias = gzBias; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_SENSOR_BIAS; + return mavlink_finalize_message(msg, system_id, component_id, 24); +} + +/** + * @brief Pack a sensor_bias message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param axBias Accelerometer X bias (m/s) + * @param ayBias Accelerometer Y bias (m/s) + * @param azBias Accelerometer Z bias (m/s) + * @param gxBias Gyro X bias (rad/s) + * @param gyBias Gyro Y bias (rad/s) + * @param gzBias Gyro Z bias (rad/s) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sensor_bias_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float axBias,float ayBias,float azBias,float gxBias,float gyBias,float gzBias) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_float(buf, 0, axBias); + _mav_put_float(buf, 4, ayBias); + _mav_put_float(buf, 8, azBias); + _mav_put_float(buf, 12, gxBias); + _mav_put_float(buf, 16, gyBias); + _mav_put_float(buf, 20, gzBias); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_sensor_bias_t packet; + packet.axBias = axBias; + packet.ayBias = ayBias; + packet.azBias = azBias; + packet.gxBias = gxBias; + packet.gyBias = gyBias; + packet.gzBias = gzBias; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_SENSOR_BIAS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 24); +} + +/** + * @brief Encode a sensor_bias struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param sensor_bias C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_sensor_bias_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_sensor_bias_t* sensor_bias) +{ + return mavlink_msg_sensor_bias_pack(system_id, component_id, msg, sensor_bias->axBias, sensor_bias->ayBias, sensor_bias->azBias, sensor_bias->gxBias, sensor_bias->gyBias, sensor_bias->gzBias); +} + +/** + * @brief Send a sensor_bias message + * @param chan MAVLink channel to send the message + * + * @param axBias Accelerometer X bias (m/s) + * @param ayBias Accelerometer Y bias (m/s) + * @param azBias Accelerometer Z bias (m/s) + * @param gxBias Gyro X bias (rad/s) + * @param gyBias Gyro Y bias (rad/s) + * @param gzBias Gyro Z bias (rad/s) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_sensor_bias_send(mavlink_channel_t chan, float axBias, float ayBias, float azBias, float gxBias, float gyBias, float gzBias) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_float(buf, 0, axBias); + _mav_put_float(buf, 4, ayBias); + _mav_put_float(buf, 8, azBias); + _mav_put_float(buf, 12, gxBias); + _mav_put_float(buf, 16, gyBias); + _mav_put_float(buf, 20, gzBias); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SENSOR_BIAS, buf, 24); +#else + mavlink_sensor_bias_t packet; + packet.axBias = axBias; + packet.ayBias = ayBias; + packet.azBias = azBias; + packet.gxBias = gxBias; + packet.gyBias = gyBias; + packet.gzBias = gzBias; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SENSOR_BIAS, (const char *)&packet, 24); +#endif +} + +#endif + +// MESSAGE SENSOR_BIAS UNPACKING + + +/** + * @brief Get field axBias from sensor_bias message + * + * @return Accelerometer X bias (m/s) + */ +static inline float mavlink_msg_sensor_bias_get_axBias(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field ayBias from sensor_bias message + * + * @return Accelerometer Y bias (m/s) + */ +static inline float mavlink_msg_sensor_bias_get_ayBias(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field azBias from sensor_bias message + * + * @return Accelerometer Z bias (m/s) + */ +static inline float mavlink_msg_sensor_bias_get_azBias(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field gxBias from sensor_bias message + * + * @return Gyro X bias (rad/s) + */ +static inline float mavlink_msg_sensor_bias_get_gxBias(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field gyBias from sensor_bias message + * + * @return Gyro Y bias (rad/s) + */ +static inline float mavlink_msg_sensor_bias_get_gyBias(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field gzBias from sensor_bias message + * + * @return Gyro Z bias (rad/s) + */ +static inline float mavlink_msg_sensor_bias_get_gzBias(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Decode a sensor_bias message into a struct + * + * @param msg The message to decode + * @param sensor_bias C-struct to decode the message contents into + */ +static inline void mavlink_msg_sensor_bias_decode(const mavlink_message_t* msg, mavlink_sensor_bias_t* sensor_bias) +{ +#if MAVLINK_NEED_BYTE_SWAP + sensor_bias->axBias = mavlink_msg_sensor_bias_get_axBias(msg); + sensor_bias->ayBias = mavlink_msg_sensor_bias_get_ayBias(msg); + sensor_bias->azBias = mavlink_msg_sensor_bias_get_azBias(msg); + sensor_bias->gxBias = mavlink_msg_sensor_bias_get_gxBias(msg); + sensor_bias->gyBias = mavlink_msg_sensor_bias_get_gyBias(msg); + sensor_bias->gzBias = mavlink_msg_sensor_bias_get_gzBias(msg); +#else + memcpy(sensor_bias, _MAV_PAYLOAD(msg), 24); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_slugs_action.h b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_slugs_action.h new file mode 100644 index 0000000000..da56b98b5a --- /dev/null +++ b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_slugs_action.h @@ -0,0 +1,188 @@ +// MESSAGE SLUGS_ACTION PACKING + +#define MAVLINK_MSG_ID_SLUGS_ACTION 183 + +typedef struct __mavlink_slugs_action_t +{ + uint8_t target; ///< The system reporting the action + uint8_t actionId; ///< Action ID. See apDefinitions.h in the SLUGS /clib directory for the ID names + uint16_t actionVal; ///< Value associated with the action +} mavlink_slugs_action_t; + +#define MAVLINK_MSG_ID_SLUGS_ACTION_LEN 4 +#define MAVLINK_MSG_ID_183_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_SLUGS_ACTION { \ + "SLUGS_ACTION", \ + 3, \ + { { "target", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_slugs_action_t, target) }, \ + { "actionId", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_slugs_action_t, actionId) }, \ + { "actionVal", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_slugs_action_t, actionVal) }, \ + } \ +} + + +/** + * @brief Pack a slugs_action message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target The system reporting the action + * @param actionId Action ID. See apDefinitions.h in the SLUGS /clib directory for the ID names + * @param actionVal Value associated with the action + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_slugs_action_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target, uint8_t actionId, uint16_t actionVal) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint8_t(buf, 1, actionId); + _mav_put_uint16_t(buf, 2, actionVal); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_slugs_action_t packet; + packet.target = target; + packet.actionId = actionId; + packet.actionVal = actionVal; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_SLUGS_ACTION; + return mavlink_finalize_message(msg, system_id, component_id, 4); +} + +/** + * @brief Pack a slugs_action message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system reporting the action + * @param actionId Action ID. See apDefinitions.h in the SLUGS /clib directory for the ID names + * @param actionVal Value associated with the action + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_slugs_action_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,uint8_t actionId,uint16_t actionVal) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint8_t(buf, 1, actionId); + _mav_put_uint16_t(buf, 2, actionVal); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_slugs_action_t packet; + packet.target = target; + packet.actionId = actionId; + packet.actionVal = actionVal; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_SLUGS_ACTION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4); +} + +/** + * @brief Encode a slugs_action struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param slugs_action C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_slugs_action_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_slugs_action_t* slugs_action) +{ + return mavlink_msg_slugs_action_pack(system_id, component_id, msg, slugs_action->target, slugs_action->actionId, slugs_action->actionVal); +} + +/** + * @brief Send a slugs_action message + * @param chan MAVLink channel to send the message + * + * @param target The system reporting the action + * @param actionId Action ID. See apDefinitions.h in the SLUGS /clib directory for the ID names + * @param actionVal Value associated with the action + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_slugs_action_send(mavlink_channel_t chan, uint8_t target, uint8_t actionId, uint16_t actionVal) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, target); + _mav_put_uint8_t(buf, 1, actionId); + _mav_put_uint16_t(buf, 2, actionVal); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SLUGS_ACTION, buf, 4); +#else + mavlink_slugs_action_t packet; + packet.target = target; + packet.actionId = actionId; + packet.actionVal = actionVal; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SLUGS_ACTION, (const char *)&packet, 4); +#endif +} + +#endif + +// MESSAGE SLUGS_ACTION UNPACKING + + +/** + * @brief Get field target from slugs_action message + * + * @return The system reporting the action + */ +static inline uint8_t mavlink_msg_slugs_action_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field actionId from slugs_action message + * + * @return Action ID. See apDefinitions.h in the SLUGS /clib directory for the ID names + */ +static inline uint8_t mavlink_msg_slugs_action_get_actionId(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field actionVal from slugs_action message + * + * @return Value associated with the action + */ +static inline uint16_t mavlink_msg_slugs_action_get_actionVal(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Decode a slugs_action message into a struct + * + * @param msg The message to decode + * @param slugs_action C-struct to decode the message contents into + */ +static inline void mavlink_msg_slugs_action_decode(const mavlink_message_t* msg, mavlink_slugs_action_t* slugs_action) +{ +#if MAVLINK_NEED_BYTE_SWAP + slugs_action->target = mavlink_msg_slugs_action_get_target(msg); + slugs_action->actionId = mavlink_msg_slugs_action_get_actionId(msg); + slugs_action->actionVal = mavlink_msg_slugs_action_get_actionVal(msg); +#else + memcpy(slugs_action, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_slugs_navigation.h b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_slugs_navigation.h new file mode 100644 index 0000000000..b81bde72ff --- /dev/null +++ b/mavlink/include/mavlink/v0.9/slugs/mavlink_msg_slugs_navigation.h @@ -0,0 +1,320 @@ +// MESSAGE SLUGS_NAVIGATION PACKING + +#define MAVLINK_MSG_ID_SLUGS_NAVIGATION 176 + +typedef struct __mavlink_slugs_navigation_t +{ + float u_m; ///< Measured Airspeed prior to the Nav Filter + float phi_c; ///< Commanded Roll + float theta_c; ///< Commanded Pitch + float psiDot_c; ///< Commanded Turn rate + float ay_body; ///< Y component of the body acceleration + float totalDist; ///< Total Distance to Run on this leg of Navigation + float dist2Go; ///< Remaining distance to Run on this leg of Navigation + uint8_t fromWP; ///< Origin WP + uint8_t toWP; ///< Destination WP +} mavlink_slugs_navigation_t; + +#define MAVLINK_MSG_ID_SLUGS_NAVIGATION_LEN 30 +#define MAVLINK_MSG_ID_176_LEN 30 + + + +#define MAVLINK_MESSAGE_INFO_SLUGS_NAVIGATION { \ + "SLUGS_NAVIGATION", \ + 9, \ + { { "u_m", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_slugs_navigation_t, u_m) }, \ + { "phi_c", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_slugs_navigation_t, phi_c) }, \ + { "theta_c", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_slugs_navigation_t, theta_c) }, \ + { "psiDot_c", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_slugs_navigation_t, psiDot_c) }, \ + { "ay_body", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_slugs_navigation_t, ay_body) }, \ + { "totalDist", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_slugs_navigation_t, totalDist) }, \ + { "dist2Go", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_slugs_navigation_t, dist2Go) }, \ + { "fromWP", NULL, MAVLINK_TYPE_UINT8_T, 0, 28, offsetof(mavlink_slugs_navigation_t, fromWP) }, \ + { "toWP", NULL, MAVLINK_TYPE_UINT8_T, 0, 29, offsetof(mavlink_slugs_navigation_t, toWP) }, \ + } \ +} + + +/** + * @brief Pack a slugs_navigation message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param u_m Measured Airspeed prior to the Nav Filter + * @param phi_c Commanded Roll + * @param theta_c Commanded Pitch + * @param psiDot_c Commanded Turn rate + * @param ay_body Y component of the body acceleration + * @param totalDist Total Distance to Run on this leg of Navigation + * @param dist2Go Remaining distance to Run on this leg of Navigation + * @param fromWP Origin WP + * @param toWP Destination WP + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_slugs_navigation_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float u_m, float phi_c, float theta_c, float psiDot_c, float ay_body, float totalDist, float dist2Go, uint8_t fromWP, uint8_t toWP) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_float(buf, 0, u_m); + _mav_put_float(buf, 4, phi_c); + _mav_put_float(buf, 8, theta_c); + _mav_put_float(buf, 12, psiDot_c); + _mav_put_float(buf, 16, ay_body); + _mav_put_float(buf, 20, totalDist); + _mav_put_float(buf, 24, dist2Go); + _mav_put_uint8_t(buf, 28, fromWP); + _mav_put_uint8_t(buf, 29, toWP); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 30); +#else + mavlink_slugs_navigation_t packet; + packet.u_m = u_m; + packet.phi_c = phi_c; + packet.theta_c = theta_c; + packet.psiDot_c = psiDot_c; + packet.ay_body = ay_body; + packet.totalDist = totalDist; + packet.dist2Go = dist2Go; + packet.fromWP = fromWP; + packet.toWP = toWP; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 30); +#endif + + msg->msgid = MAVLINK_MSG_ID_SLUGS_NAVIGATION; + return mavlink_finalize_message(msg, system_id, component_id, 30); +} + +/** + * @brief Pack a slugs_navigation message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param u_m Measured Airspeed prior to the Nav Filter + * @param phi_c Commanded Roll + * @param theta_c Commanded Pitch + * @param psiDot_c Commanded Turn rate + * @param ay_body Y component of the body acceleration + * @param totalDist Total Distance to Run on this leg of Navigation + * @param dist2Go Remaining distance to Run on this leg of Navigation + * @param fromWP Origin WP + * @param toWP Destination WP + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_slugs_navigation_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float u_m,float phi_c,float theta_c,float psiDot_c,float ay_body,float totalDist,float dist2Go,uint8_t fromWP,uint8_t toWP) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_float(buf, 0, u_m); + _mav_put_float(buf, 4, phi_c); + _mav_put_float(buf, 8, theta_c); + _mav_put_float(buf, 12, psiDot_c); + _mav_put_float(buf, 16, ay_body); + _mav_put_float(buf, 20, totalDist); + _mav_put_float(buf, 24, dist2Go); + _mav_put_uint8_t(buf, 28, fromWP); + _mav_put_uint8_t(buf, 29, toWP); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 30); +#else + mavlink_slugs_navigation_t packet; + packet.u_m = u_m; + packet.phi_c = phi_c; + packet.theta_c = theta_c; + packet.psiDot_c = psiDot_c; + packet.ay_body = ay_body; + packet.totalDist = totalDist; + packet.dist2Go = dist2Go; + packet.fromWP = fromWP; + packet.toWP = toWP; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 30); +#endif + + msg->msgid = MAVLINK_MSG_ID_SLUGS_NAVIGATION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 30); +} + +/** + * @brief Encode a slugs_navigation struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param slugs_navigation C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_slugs_navigation_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_slugs_navigation_t* slugs_navigation) +{ + return mavlink_msg_slugs_navigation_pack(system_id, component_id, msg, slugs_navigation->u_m, slugs_navigation->phi_c, slugs_navigation->theta_c, slugs_navigation->psiDot_c, slugs_navigation->ay_body, slugs_navigation->totalDist, slugs_navigation->dist2Go, slugs_navigation->fromWP, slugs_navigation->toWP); +} + +/** + * @brief Send a slugs_navigation message + * @param chan MAVLink channel to send the message + * + * @param u_m Measured Airspeed prior to the Nav Filter + * @param phi_c Commanded Roll + * @param theta_c Commanded Pitch + * @param psiDot_c Commanded Turn rate + * @param ay_body Y component of the body acceleration + * @param totalDist Total Distance to Run on this leg of Navigation + * @param dist2Go Remaining distance to Run on this leg of Navigation + * @param fromWP Origin WP + * @param toWP Destination WP + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_slugs_navigation_send(mavlink_channel_t chan, float u_m, float phi_c, float theta_c, float psiDot_c, float ay_body, float totalDist, float dist2Go, uint8_t fromWP, uint8_t toWP) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_float(buf, 0, u_m); + _mav_put_float(buf, 4, phi_c); + _mav_put_float(buf, 8, theta_c); + _mav_put_float(buf, 12, psiDot_c); + _mav_put_float(buf, 16, ay_body); + _mav_put_float(buf, 20, totalDist); + _mav_put_float(buf, 24, dist2Go); + _mav_put_uint8_t(buf, 28, fromWP); + _mav_put_uint8_t(buf, 29, toWP); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SLUGS_NAVIGATION, buf, 30); +#else + mavlink_slugs_navigation_t packet; + packet.u_m = u_m; + packet.phi_c = phi_c; + packet.theta_c = theta_c; + packet.psiDot_c = psiDot_c; + packet.ay_body = ay_body; + packet.totalDist = totalDist; + packet.dist2Go = dist2Go; + packet.fromWP = fromWP; + packet.toWP = toWP; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SLUGS_NAVIGATION, (const char *)&packet, 30); +#endif +} + +#endif + +// MESSAGE SLUGS_NAVIGATION UNPACKING + + +/** + * @brief Get field u_m from slugs_navigation message + * + * @return Measured Airspeed prior to the Nav Filter + */ +static inline float mavlink_msg_slugs_navigation_get_u_m(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field phi_c from slugs_navigation message + * + * @return Commanded Roll + */ +static inline float mavlink_msg_slugs_navigation_get_phi_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field theta_c from slugs_navigation message + * + * @return Commanded Pitch + */ +static inline float mavlink_msg_slugs_navigation_get_theta_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field psiDot_c from slugs_navigation message + * + * @return Commanded Turn rate + */ +static inline float mavlink_msg_slugs_navigation_get_psiDot_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field ay_body from slugs_navigation message + * + * @return Y component of the body acceleration + */ +static inline float mavlink_msg_slugs_navigation_get_ay_body(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field totalDist from slugs_navigation message + * + * @return Total Distance to Run on this leg of Navigation + */ +static inline float mavlink_msg_slugs_navigation_get_totalDist(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field dist2Go from slugs_navigation message + * + * @return Remaining distance to Run on this leg of Navigation + */ +static inline float mavlink_msg_slugs_navigation_get_dist2Go(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field fromWP from slugs_navigation message + * + * @return Origin WP + */ +static inline uint8_t mavlink_msg_slugs_navigation_get_fromWP(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 28); +} + +/** + * @brief Get field toWP from slugs_navigation message + * + * @return Destination WP + */ +static inline uint8_t mavlink_msg_slugs_navigation_get_toWP(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 29); +} + +/** + * @brief Decode a slugs_navigation message into a struct + * + * @param msg The message to decode + * @param slugs_navigation C-struct to decode the message contents into + */ +static inline void mavlink_msg_slugs_navigation_decode(const mavlink_message_t* msg, mavlink_slugs_navigation_t* slugs_navigation) +{ +#if MAVLINK_NEED_BYTE_SWAP + slugs_navigation->u_m = mavlink_msg_slugs_navigation_get_u_m(msg); + slugs_navigation->phi_c = mavlink_msg_slugs_navigation_get_phi_c(msg); + slugs_navigation->theta_c = mavlink_msg_slugs_navigation_get_theta_c(msg); + slugs_navigation->psiDot_c = mavlink_msg_slugs_navigation_get_psiDot_c(msg); + slugs_navigation->ay_body = mavlink_msg_slugs_navigation_get_ay_body(msg); + slugs_navigation->totalDist = mavlink_msg_slugs_navigation_get_totalDist(msg); + slugs_navigation->dist2Go = mavlink_msg_slugs_navigation_get_dist2Go(msg); + slugs_navigation->fromWP = mavlink_msg_slugs_navigation_get_fromWP(msg); + slugs_navigation->toWP = mavlink_msg_slugs_navigation_get_toWP(msg); +#else + memcpy(slugs_navigation, _MAV_PAYLOAD(msg), 30); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/slugs/slugs.h b/mavlink/include/mavlink/v0.9/slugs/slugs.h new file mode 100644 index 0000000000..27f4e10bee --- /dev/null +++ b/mavlink/include/mavlink/v0.9/slugs/slugs.h @@ -0,0 +1,62 @@ +/** @file + * @brief MAVLink comm protocol generated from slugs.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef SLUGS_H +#define SLUGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {3, 4, 8, 14, 8, 28, 3, 32, 0, 2, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 19, 2, 23, 21, 0, 37, 26, 101, 26, 16, 32, 32, 37, 32, 11, 17, 17, 16, 18, 36, 4, 4, 2, 2, 4, 2, 2, 3, 14, 12, 18, 16, 8, 27, 25, 18, 18, 24, 24, 0, 0, 0, 26, 16, 36, 5, 6, 56, 26, 21, 18, 0, 0, 18, 20, 20, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 10, 24, 18, 0, 0, 30, 24, 0, 7, 13, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 14, 14, 51, 5} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {72, 39, 190, 92, 191, 217, 104, 119, 0, 219, 60, 186, 10, 0, 0, 0, 0, 0, 0, 0, 89, 159, 162, 121, 0, 149, 222, 110, 179, 136, 66, 126, 185, 147, 112, 252, 162, 215, 229, 128, 9, 106, 101, 213, 4, 229, 21, 214, 215, 14, 206, 50, 157, 126, 108, 213, 95, 5, 127, 0, 0, 0, 57, 126, 130, 119, 193, 191, 236, 158, 143, 0, 0, 104, 123, 131, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 232, 168, 2, 0, 0, 120, 167, 0, 16, 2, 52, 0, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 224, 60, 106, 7} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, MAVLINK_MESSAGE_INFO_BOOT, MAVLINK_MESSAGE_INFO_SYSTEM_TIME, MAVLINK_MESSAGE_INFO_PING, MAVLINK_MESSAGE_INFO_SYSTEM_TIME_UTC, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK, MAVLINK_MESSAGE_INFO_AUTH_KEY, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_ACTION_ACK, MAVLINK_MESSAGE_INFO_ACTION, MAVLINK_MESSAGE_INFO_SET_MODE, MAVLINK_MESSAGE_INFO_SET_NAV_MODE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST, MAVLINK_MESSAGE_INFO_PARAM_VALUE, MAVLINK_MESSAGE_INFO_PARAM_SET, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_GPS_RAW_INT, MAVLINK_MESSAGE_INFO_SCALED_IMU, MAVLINK_MESSAGE_INFO_GPS_STATUS, MAVLINK_MESSAGE_INFO_RAW_IMU, MAVLINK_MESSAGE_INFO_RAW_PRESSURE, MAVLINK_MESSAGE_INFO_ATTITUDE, MAVLINK_MESSAGE_INFO_LOCAL_POSITION, MAVLINK_MESSAGE_INFO_GPS_RAW, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION, MAVLINK_MESSAGE_INFO_SYS_STATUS, MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW, MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED, MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW, MAVLINK_MESSAGE_INFO_SCALED_PRESSURE, MAVLINK_MESSAGE_INFO_WAYPOINT, MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST, MAVLINK_MESSAGE_INFO_WAYPOINT_SET_CURRENT, MAVLINK_MESSAGE_INFO_WAYPOINT_CURRENT, MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST_LIST, MAVLINK_MESSAGE_INFO_WAYPOINT_COUNT, MAVLINK_MESSAGE_INFO_WAYPOINT_CLEAR_ALL, MAVLINK_MESSAGE_INFO_WAYPOINT_REACHED, MAVLINK_MESSAGE_INFO_WAYPOINT_ACK, MAVLINK_MESSAGE_INFO_GPS_SET_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_GPS_LOCAL_ORIGIN_SET, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT_SET, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_CONTROL_STATUS, MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT, MAVLINK_MESSAGE_INFO_POSITION_TARGET, MAVLINK_MESSAGE_INFO_STATE_CORRECTION, MAVLINK_MESSAGE_INFO_SET_ALTITUDE, MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM, MAVLINK_MESSAGE_INFO_HIL_STATE, MAVLINK_MESSAGE_INFO_HIL_CONTROLS, MAVLINK_MESSAGE_INFO_MANUAL_CONTROL, MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT, MAVLINK_MESSAGE_INFO_VFR_HUD, MAVLINK_MESSAGE_INFO_COMMAND, MAVLINK_MESSAGE_INFO_COMMAND_ACK, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OPTICAL_FLOW, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OBJECT_DETECTION_EVENT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_CPU_LOAD, MAVLINK_MESSAGE_INFO_AIR_DATA, MAVLINK_MESSAGE_INFO_SENSOR_BIAS, MAVLINK_MESSAGE_INFO_DIAGNOSTIC, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_SLUGS_NAVIGATION, MAVLINK_MESSAGE_INFO_DATA_LOG, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_GPS_DATE_TIME, MAVLINK_MESSAGE_INFO_MID_LVL_CMDS, MAVLINK_MESSAGE_INFO_CTRL_SRFC_PT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_SLUGS_ACTION, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_DEBUG_VECT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT, MAVLINK_MESSAGE_INFO_STATUSTEXT, MAVLINK_MESSAGE_INFO_DEBUG} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_SLUGS + +#include "../common/common.h" + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +// ENUM DEFINITIONS + + + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_cpu_load.h" +#include "./mavlink_msg_air_data.h" +#include "./mavlink_msg_sensor_bias.h" +#include "./mavlink_msg_diagnostic.h" +#include "./mavlink_msg_slugs_navigation.h" +#include "./mavlink_msg_data_log.h" +#include "./mavlink_msg_gps_date_time.h" +#include "./mavlink_msg_mid_lvl_cmds.h" +#include "./mavlink_msg_ctrl_srfc_pt.h" +#include "./mavlink_msg_slugs_action.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // SLUGS_H diff --git a/mavlink/include/mavlink/v0.9/slugs/testsuite.h b/mavlink/include/mavlink/v0.9/slugs/testsuite.h new file mode 100644 index 0000000000..d1596a8164 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/slugs/testsuite.h @@ -0,0 +1,552 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from slugs.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef SLUGS_TESTSUITE_H +#define SLUGS_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL +static void mavlink_test_common(uint8_t, uint8_t, mavlink_message_t *last_msg); +static void mavlink_test_slugs(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_test_common(system_id, component_id, last_msg); + mavlink_test_slugs(system_id, component_id, last_msg); +} +#endif + +#include "../common/testsuite.h" + + +static void mavlink_test_cpu_load(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_cpu_load_t packet_in = { + 5, + 72, + 17339, + }; + mavlink_cpu_load_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.sensLoad = packet_in.sensLoad; + packet1.ctrlLoad = packet_in.ctrlLoad; + packet1.batVolt = packet_in.batVolt; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_cpu_load_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_cpu_load_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_cpu_load_pack(system_id, component_id, &msg , packet1.sensLoad , packet1.ctrlLoad , packet1.batVolt ); + mavlink_msg_cpu_load_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_cpu_load_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.sensLoad , packet1.ctrlLoad , packet1.batVolt ); + mavlink_msg_cpu_load_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; imsgid = MAVLINK_MSG_ID_TEST_TYPES; + return mavlink_finalize_message(msg, system_id, component_id, 179); +} + +/** + * @brief Pack a test_types message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param c char + * @param s string + * @param u8 uint8_t + * @param u16 uint16_t + * @param u32 uint32_t + * @param u64 uint64_t + * @param s8 int8_t + * @param s16 int16_t + * @param s32 int32_t + * @param s64 int64_t + * @param f float + * @param d double + * @param u8_array uint8_t_array + * @param u16_array uint16_t_array + * @param u32_array uint32_t_array + * @param u64_array uint64_t_array + * @param s8_array int8_t_array + * @param s16_array int16_t_array + * @param s32_array int32_t_array + * @param s64_array int64_t_array + * @param f_array float_array + * @param d_array double_array + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_test_types_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + char c,const char *s,uint8_t u8,uint16_t u16,uint32_t u32,uint64_t u64,int8_t s8,int16_t s16,int32_t s32,int64_t s64,float f,double d,const uint8_t *u8_array,const uint16_t *u16_array,const uint32_t *u32_array,const uint64_t *u64_array,const int8_t *s8_array,const int16_t *s16_array,const int32_t *s32_array,const int64_t *s64_array,const float *f_array,const double *d_array) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[179]; + _mav_put_char(buf, 0, c); + _mav_put_uint8_t(buf, 11, u8); + _mav_put_uint16_t(buf, 12, u16); + _mav_put_uint32_t(buf, 14, u32); + _mav_put_uint64_t(buf, 18, u64); + _mav_put_int8_t(buf, 26, s8); + _mav_put_int16_t(buf, 27, s16); + _mav_put_int32_t(buf, 29, s32); + _mav_put_int64_t(buf, 33, s64); + _mav_put_float(buf, 41, f); + _mav_put_double(buf, 45, d); + _mav_put_char_array(buf, 1, s, 10); + _mav_put_uint8_t_array(buf, 53, u8_array, 3); + _mav_put_uint16_t_array(buf, 56, u16_array, 3); + _mav_put_uint32_t_array(buf, 62, u32_array, 3); + _mav_put_uint64_t_array(buf, 74, u64_array, 3); + _mav_put_int8_t_array(buf, 98, s8_array, 3); + _mav_put_int16_t_array(buf, 101, s16_array, 3); + _mav_put_int32_t_array(buf, 107, s32_array, 3); + _mav_put_int64_t_array(buf, 119, s64_array, 3); + _mav_put_float_array(buf, 143, f_array, 3); + _mav_put_double_array(buf, 155, d_array, 3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 179); +#else + mavlink_test_types_t packet; + packet.c = c; + packet.u8 = u8; + packet.u16 = u16; + packet.u32 = u32; + packet.u64 = u64; + packet.s8 = s8; + packet.s16 = s16; + packet.s32 = s32; + packet.s64 = s64; + packet.f = f; + packet.d = d; + mav_array_memcpy(packet.s, s, sizeof(char)*10); + mav_array_memcpy(packet.u8_array, u8_array, sizeof(uint8_t)*3); + mav_array_memcpy(packet.u16_array, u16_array, sizeof(uint16_t)*3); + mav_array_memcpy(packet.u32_array, u32_array, sizeof(uint32_t)*3); + mav_array_memcpy(packet.u64_array, u64_array, sizeof(uint64_t)*3); + mav_array_memcpy(packet.s8_array, s8_array, sizeof(int8_t)*3); + mav_array_memcpy(packet.s16_array, s16_array, sizeof(int16_t)*3); + mav_array_memcpy(packet.s32_array, s32_array, sizeof(int32_t)*3); + mav_array_memcpy(packet.s64_array, s64_array, sizeof(int64_t)*3); + mav_array_memcpy(packet.f_array, f_array, sizeof(float)*3); + mav_array_memcpy(packet.d_array, d_array, sizeof(double)*3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 179); +#endif + + msg->msgid = MAVLINK_MSG_ID_TEST_TYPES; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 179); +} + +/** + * @brief Encode a test_types struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param test_types C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_test_types_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_test_types_t* test_types) +{ + return mavlink_msg_test_types_pack(system_id, component_id, msg, test_types->c, test_types->s, test_types->u8, test_types->u16, test_types->u32, test_types->u64, test_types->s8, test_types->s16, test_types->s32, test_types->s64, test_types->f, test_types->d, test_types->u8_array, test_types->u16_array, test_types->u32_array, test_types->u64_array, test_types->s8_array, test_types->s16_array, test_types->s32_array, test_types->s64_array, test_types->f_array, test_types->d_array); +} + +/** + * @brief Send a test_types message + * @param chan MAVLink channel to send the message + * + * @param c char + * @param s string + * @param u8 uint8_t + * @param u16 uint16_t + * @param u32 uint32_t + * @param u64 uint64_t + * @param s8 int8_t + * @param s16 int16_t + * @param s32 int32_t + * @param s64 int64_t + * @param f float + * @param d double + * @param u8_array uint8_t_array + * @param u16_array uint16_t_array + * @param u32_array uint32_t_array + * @param u64_array uint64_t_array + * @param s8_array int8_t_array + * @param s16_array int16_t_array + * @param s32_array int32_t_array + * @param s64_array int64_t_array + * @param f_array float_array + * @param d_array double_array + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_test_types_send(mavlink_channel_t chan, char c, const char *s, uint8_t u8, uint16_t u16, uint32_t u32, uint64_t u64, int8_t s8, int16_t s16, int32_t s32, int64_t s64, float f, double d, const uint8_t *u8_array, const uint16_t *u16_array, const uint32_t *u32_array, const uint64_t *u64_array, const int8_t *s8_array, const int16_t *s16_array, const int32_t *s32_array, const int64_t *s64_array, const float *f_array, const double *d_array) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[179]; + _mav_put_char(buf, 0, c); + _mav_put_uint8_t(buf, 11, u8); + _mav_put_uint16_t(buf, 12, u16); + _mav_put_uint32_t(buf, 14, u32); + _mav_put_uint64_t(buf, 18, u64); + _mav_put_int8_t(buf, 26, s8); + _mav_put_int16_t(buf, 27, s16); + _mav_put_int32_t(buf, 29, s32); + _mav_put_int64_t(buf, 33, s64); + _mav_put_float(buf, 41, f); + _mav_put_double(buf, 45, d); + _mav_put_char_array(buf, 1, s, 10); + _mav_put_uint8_t_array(buf, 53, u8_array, 3); + _mav_put_uint16_t_array(buf, 56, u16_array, 3); + _mav_put_uint32_t_array(buf, 62, u32_array, 3); + _mav_put_uint64_t_array(buf, 74, u64_array, 3); + _mav_put_int8_t_array(buf, 98, s8_array, 3); + _mav_put_int16_t_array(buf, 101, s16_array, 3); + _mav_put_int32_t_array(buf, 107, s32_array, 3); + _mav_put_int64_t_array(buf, 119, s64_array, 3); + _mav_put_float_array(buf, 143, f_array, 3); + _mav_put_double_array(buf, 155, d_array, 3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_TEST_TYPES, buf, 179); +#else + mavlink_test_types_t packet; + packet.c = c; + packet.u8 = u8; + packet.u16 = u16; + packet.u32 = u32; + packet.u64 = u64; + packet.s8 = s8; + packet.s16 = s16; + packet.s32 = s32; + packet.s64 = s64; + packet.f = f; + packet.d = d; + mav_array_memcpy(packet.s, s, sizeof(char)*10); + mav_array_memcpy(packet.u8_array, u8_array, sizeof(uint8_t)*3); + mav_array_memcpy(packet.u16_array, u16_array, sizeof(uint16_t)*3); + mav_array_memcpy(packet.u32_array, u32_array, sizeof(uint32_t)*3); + mav_array_memcpy(packet.u64_array, u64_array, sizeof(uint64_t)*3); + mav_array_memcpy(packet.s8_array, s8_array, sizeof(int8_t)*3); + mav_array_memcpy(packet.s16_array, s16_array, sizeof(int16_t)*3); + mav_array_memcpy(packet.s32_array, s32_array, sizeof(int32_t)*3); + mav_array_memcpy(packet.s64_array, s64_array, sizeof(int64_t)*3); + mav_array_memcpy(packet.f_array, f_array, sizeof(float)*3); + mav_array_memcpy(packet.d_array, d_array, sizeof(double)*3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_TEST_TYPES, (const char *)&packet, 179); +#endif +} + +#endif + +// MESSAGE TEST_TYPES UNPACKING + + +/** + * @brief Get field c from test_types message + * + * @return char + */ +static inline char mavlink_msg_test_types_get_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_char(msg, 0); +} + +/** + * @brief Get field s from test_types message + * + * @return string + */ +static inline uint16_t mavlink_msg_test_types_get_s(const mavlink_message_t* msg, char *s) +{ + return _MAV_RETURN_char_array(msg, s, 10, 1); +} + +/** + * @brief Get field u8 from test_types message + * + * @return uint8_t + */ +static inline uint8_t mavlink_msg_test_types_get_u8(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 11); +} + +/** + * @brief Get field u16 from test_types message + * + * @return uint16_t + */ +static inline uint16_t mavlink_msg_test_types_get_u16(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 12); +} + +/** + * @brief Get field u32 from test_types message + * + * @return uint32_t + */ +static inline uint32_t mavlink_msg_test_types_get_u32(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 14); +} + +/** + * @brief Get field u64 from test_types message + * + * @return uint64_t + */ +static inline uint64_t mavlink_msg_test_types_get_u64(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 18); +} + +/** + * @brief Get field s8 from test_types message + * + * @return int8_t + */ +static inline int8_t mavlink_msg_test_types_get_s8(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int8_t(msg, 26); +} + +/** + * @brief Get field s16 from test_types message + * + * @return int16_t + */ +static inline int16_t mavlink_msg_test_types_get_s16(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 27); +} + +/** + * @brief Get field s32 from test_types message + * + * @return int32_t + */ +static inline int32_t mavlink_msg_test_types_get_s32(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 29); +} + +/** + * @brief Get field s64 from test_types message + * + * @return int64_t + */ +static inline int64_t mavlink_msg_test_types_get_s64(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int64_t(msg, 33); +} + +/** + * @brief Get field f from test_types message + * + * @return float + */ +static inline float mavlink_msg_test_types_get_f(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 41); +} + +/** + * @brief Get field d from test_types message + * + * @return double + */ +static inline double mavlink_msg_test_types_get_d(const mavlink_message_t* msg) +{ + return _MAV_RETURN_double(msg, 45); +} + +/** + * @brief Get field u8_array from test_types message + * + * @return uint8_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u8_array(const mavlink_message_t* msg, uint8_t *u8_array) +{ + return _MAV_RETURN_uint8_t_array(msg, u8_array, 3, 53); +} + +/** + * @brief Get field u16_array from test_types message + * + * @return uint16_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u16_array(const mavlink_message_t* msg, uint16_t *u16_array) +{ + return _MAV_RETURN_uint16_t_array(msg, u16_array, 3, 56); +} + +/** + * @brief Get field u32_array from test_types message + * + * @return uint32_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u32_array(const mavlink_message_t* msg, uint32_t *u32_array) +{ + return _MAV_RETURN_uint32_t_array(msg, u32_array, 3, 62); +} + +/** + * @brief Get field u64_array from test_types message + * + * @return uint64_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u64_array(const mavlink_message_t* msg, uint64_t *u64_array) +{ + return _MAV_RETURN_uint64_t_array(msg, u64_array, 3, 74); +} + +/** + * @brief Get field s8_array from test_types message + * + * @return int8_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s8_array(const mavlink_message_t* msg, int8_t *s8_array) +{ + return _MAV_RETURN_int8_t_array(msg, s8_array, 3, 98); +} + +/** + * @brief Get field s16_array from test_types message + * + * @return int16_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s16_array(const mavlink_message_t* msg, int16_t *s16_array) +{ + return _MAV_RETURN_int16_t_array(msg, s16_array, 3, 101); +} + +/** + * @brief Get field s32_array from test_types message + * + * @return int32_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s32_array(const mavlink_message_t* msg, int32_t *s32_array) +{ + return _MAV_RETURN_int32_t_array(msg, s32_array, 3, 107); +} + +/** + * @brief Get field s64_array from test_types message + * + * @return int64_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s64_array(const mavlink_message_t* msg, int64_t *s64_array) +{ + return _MAV_RETURN_int64_t_array(msg, s64_array, 3, 119); +} + +/** + * @brief Get field f_array from test_types message + * + * @return float_array + */ +static inline uint16_t mavlink_msg_test_types_get_f_array(const mavlink_message_t* msg, float *f_array) +{ + return _MAV_RETURN_float_array(msg, f_array, 3, 143); +} + +/** + * @brief Get field d_array from test_types message + * + * @return double_array + */ +static inline uint16_t mavlink_msg_test_types_get_d_array(const mavlink_message_t* msg, double *d_array) +{ + return _MAV_RETURN_double_array(msg, d_array, 3, 155); +} + +/** + * @brief Decode a test_types message into a struct + * + * @param msg The message to decode + * @param test_types C-struct to decode the message contents into + */ +static inline void mavlink_msg_test_types_decode(const mavlink_message_t* msg, mavlink_test_types_t* test_types) +{ +#if MAVLINK_NEED_BYTE_SWAP + test_types->c = mavlink_msg_test_types_get_c(msg); + mavlink_msg_test_types_get_s(msg, test_types->s); + test_types->u8 = mavlink_msg_test_types_get_u8(msg); + test_types->u16 = mavlink_msg_test_types_get_u16(msg); + test_types->u32 = mavlink_msg_test_types_get_u32(msg); + test_types->u64 = mavlink_msg_test_types_get_u64(msg); + test_types->s8 = mavlink_msg_test_types_get_s8(msg); + test_types->s16 = mavlink_msg_test_types_get_s16(msg); + test_types->s32 = mavlink_msg_test_types_get_s32(msg); + test_types->s64 = mavlink_msg_test_types_get_s64(msg); + test_types->f = mavlink_msg_test_types_get_f(msg); + test_types->d = mavlink_msg_test_types_get_d(msg); + mavlink_msg_test_types_get_u8_array(msg, test_types->u8_array); + mavlink_msg_test_types_get_u16_array(msg, test_types->u16_array); + mavlink_msg_test_types_get_u32_array(msg, test_types->u32_array); + mavlink_msg_test_types_get_u64_array(msg, test_types->u64_array); + mavlink_msg_test_types_get_s8_array(msg, test_types->s8_array); + mavlink_msg_test_types_get_s16_array(msg, test_types->s16_array); + mavlink_msg_test_types_get_s32_array(msg, test_types->s32_array); + mavlink_msg_test_types_get_s64_array(msg, test_types->s64_array); + mavlink_msg_test_types_get_f_array(msg, test_types->f_array); + mavlink_msg_test_types_get_d_array(msg, test_types->d_array); +#else + memcpy(test_types, _MAV_PAYLOAD(msg), 179); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/test/test.h b/mavlink/include/mavlink/v0.9/test/test.h new file mode 100644 index 0000000000..cfcf4753e7 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/test/test.h @@ -0,0 +1,53 @@ +/** @file + * @brief MAVLink comm protocol generated from test.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef TEST_H +#define TEST_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_TEST_TYPES, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_TEST + + + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 3 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 3 +#endif + +// ENUM DEFINITIONS + + + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_test_types.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // TEST_H diff --git a/mavlink/include/mavlink/v0.9/test/testsuite.h b/mavlink/include/mavlink/v0.9/test/testsuite.h new file mode 100644 index 0000000000..9b0fc041b5 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/test/testsuite.h @@ -0,0 +1,120 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from test.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef TEST_TESTSUITE_H +#define TEST_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL + +static void mavlink_test_test(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + + mavlink_test_test(system_id, component_id, last_msg); +} +#endif + + + + +static void mavlink_test_test_types(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_test_types_t packet_in = { + 'A', + "BCDEFGHIJ", + 230, + 17859, + 963498192, + 93372036854776941ULL, + 211, + 18639, + 963498972, + 93372036854777886LL, + 304.0, + 438.0, + { 228, 229, 230 }, + { 20147, 20148, 20149 }, + { 963500688, 963500689, 963500690 }, + { 93372036854780469, 93372036854780470, 93372036854780471 }, + { 171, 172, 173 }, + { 22487, 22488, 22489 }, + { 963503028, 963503029, 963503030 }, + { 93372036854783304, 93372036854783305, 93372036854783306 }, + { 1018.0, 1019.0, 1020.0 }, + { 1208.0, 1209.0, 1210.0 }, + }; + mavlink_test_types_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.c = packet_in.c; + packet1.u8 = packet_in.u8; + packet1.u16 = packet_in.u16; + packet1.u32 = packet_in.u32; + packet1.u64 = packet_in.u64; + packet1.s8 = packet_in.s8; + packet1.s16 = packet_in.s16; + packet1.s32 = packet_in.s32; + packet1.s64 = packet_in.s64; + packet1.f = packet_in.f; + packet1.d = packet_in.d; + + mav_array_memcpy(packet1.s, packet_in.s, sizeof(char)*10); + mav_array_memcpy(packet1.u8_array, packet_in.u8_array, sizeof(uint8_t)*3); + mav_array_memcpy(packet1.u16_array, packet_in.u16_array, sizeof(uint16_t)*3); + mav_array_memcpy(packet1.u32_array, packet_in.u32_array, sizeof(uint32_t)*3); + mav_array_memcpy(packet1.u64_array, packet_in.u64_array, sizeof(uint64_t)*3); + mav_array_memcpy(packet1.s8_array, packet_in.s8_array, sizeof(int8_t)*3); + mav_array_memcpy(packet1.s16_array, packet_in.s16_array, sizeof(int16_t)*3); + mav_array_memcpy(packet1.s32_array, packet_in.s32_array, sizeof(int32_t)*3); + mav_array_memcpy(packet1.s64_array, packet_in.s64_array, sizeof(int64_t)*3); + mav_array_memcpy(packet1.f_array, packet_in.f_array, sizeof(float)*3); + mav_array_memcpy(packet1.d_array, packet_in.d_array, sizeof(double)*3); + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_test_types_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_test_types_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_test_types_pack(system_id, component_id, &msg , packet1.c , packet1.s , packet1.u8 , packet1.u16 , packet1.u32 , packet1.u64 , packet1.s8 , packet1.s16 , packet1.s32 , packet1.s64 , packet1.f , packet1.d , packet1.u8_array , packet1.u16_array , packet1.u32_array , packet1.u64_array , packet1.s8_array , packet1.s16_array , packet1.s32_array , packet1.s64_array , packet1.f_array , packet1.d_array ); + mavlink_msg_test_types_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_test_types_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.c , packet1.s , packet1.u8 , packet1.u16 , packet1.u32 , packet1.u64 , packet1.s8 , packet1.s16 , packet1.s32 , packet1.s64 , packet1.f , packet1.d , packet1.u8_array , packet1.u16_array , packet1.u32_array , packet1.u64_array , packet1.s8_array , packet1.s16_array , packet1.s32_array , packet1.s64_array , packet1.f_array , packet1.d_array ); + mavlink_msg_test_types_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; imsgid = MAVLINK_MSG_ID_NAV_FILTER_BIAS; + return mavlink_finalize_message(msg, system_id, component_id, 32); +} + +/** + * @brief Pack a nav_filter_bias message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (microseconds) + * @param accel_0 b_f[0] + * @param accel_1 b_f[1] + * @param accel_2 b_f[2] + * @param gyro_0 b_f[0] + * @param gyro_1 b_f[1] + * @param gyro_2 b_f[2] + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_nav_filter_bias_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float accel_0,float accel_1,float accel_2,float gyro_0,float gyro_1,float gyro_2) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, accel_0); + _mav_put_float(buf, 12, accel_1); + _mav_put_float(buf, 16, accel_2); + _mav_put_float(buf, 20, gyro_0); + _mav_put_float(buf, 24, gyro_1); + _mav_put_float(buf, 28, gyro_2); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_nav_filter_bias_t packet; + packet.usec = usec; + packet.accel_0 = accel_0; + packet.accel_1 = accel_1; + packet.accel_2 = accel_2; + packet.gyro_0 = gyro_0; + packet.gyro_1 = gyro_1; + packet.gyro_2 = gyro_2; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAV_FILTER_BIAS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32); +} + +/** + * @brief Encode a nav_filter_bias struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param nav_filter_bias C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_nav_filter_bias_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_nav_filter_bias_t* nav_filter_bias) +{ + return mavlink_msg_nav_filter_bias_pack(system_id, component_id, msg, nav_filter_bias->usec, nav_filter_bias->accel_0, nav_filter_bias->accel_1, nav_filter_bias->accel_2, nav_filter_bias->gyro_0, nav_filter_bias->gyro_1, nav_filter_bias->gyro_2); +} + +/** + * @brief Send a nav_filter_bias message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (microseconds) + * @param accel_0 b_f[0] + * @param accel_1 b_f[1] + * @param accel_2 b_f[2] + * @param gyro_0 b_f[0] + * @param gyro_1 b_f[1] + * @param gyro_2 b_f[2] + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_nav_filter_bias_send(mavlink_channel_t chan, uint64_t usec, float accel_0, float accel_1, float accel_2, float gyro_0, float gyro_1, float gyro_2) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, accel_0); + _mav_put_float(buf, 12, accel_1); + _mav_put_float(buf, 16, accel_2); + _mav_put_float(buf, 20, gyro_0); + _mav_put_float(buf, 24, gyro_1); + _mav_put_float(buf, 28, gyro_2); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAV_FILTER_BIAS, buf, 32); +#else + mavlink_nav_filter_bias_t packet; + packet.usec = usec; + packet.accel_0 = accel_0; + packet.accel_1 = accel_1; + packet.accel_2 = accel_2; + packet.gyro_0 = gyro_0; + packet.gyro_1 = gyro_1; + packet.gyro_2 = gyro_2; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAV_FILTER_BIAS, (const char *)&packet, 32); +#endif +} + +#endif + +// MESSAGE NAV_FILTER_BIAS UNPACKING + + +/** + * @brief Get field usec from nav_filter_bias message + * + * @return Timestamp (microseconds) + */ +static inline uint64_t mavlink_msg_nav_filter_bias_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field accel_0 from nav_filter_bias message + * + * @return b_f[0] + */ +static inline float mavlink_msg_nav_filter_bias_get_accel_0(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field accel_1 from nav_filter_bias message + * + * @return b_f[1] + */ +static inline float mavlink_msg_nav_filter_bias_get_accel_1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field accel_2 from nav_filter_bias message + * + * @return b_f[2] + */ +static inline float mavlink_msg_nav_filter_bias_get_accel_2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field gyro_0 from nav_filter_bias message + * + * @return b_f[0] + */ +static inline float mavlink_msg_nav_filter_bias_get_gyro_0(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field gyro_1 from nav_filter_bias message + * + * @return b_f[1] + */ +static inline float mavlink_msg_nav_filter_bias_get_gyro_1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field gyro_2 from nav_filter_bias message + * + * @return b_f[2] + */ +static inline float mavlink_msg_nav_filter_bias_get_gyro_2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Decode a nav_filter_bias message into a struct + * + * @param msg The message to decode + * @param nav_filter_bias C-struct to decode the message contents into + */ +static inline void mavlink_msg_nav_filter_bias_decode(const mavlink_message_t* msg, mavlink_nav_filter_bias_t* nav_filter_bias) +{ +#if MAVLINK_NEED_BYTE_SWAP + nav_filter_bias->usec = mavlink_msg_nav_filter_bias_get_usec(msg); + nav_filter_bias->accel_0 = mavlink_msg_nav_filter_bias_get_accel_0(msg); + nav_filter_bias->accel_1 = mavlink_msg_nav_filter_bias_get_accel_1(msg); + nav_filter_bias->accel_2 = mavlink_msg_nav_filter_bias_get_accel_2(msg); + nav_filter_bias->gyro_0 = mavlink_msg_nav_filter_bias_get_gyro_0(msg); + nav_filter_bias->gyro_1 = mavlink_msg_nav_filter_bias_get_gyro_1(msg); + nav_filter_bias->gyro_2 = mavlink_msg_nav_filter_bias_get_gyro_2(msg); +#else + memcpy(nav_filter_bias, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ualberta/mavlink_msg_radio_calibration.h b/mavlink/include/mavlink/v0.9/ualberta/mavlink_msg_radio_calibration.h new file mode 100644 index 0000000000..3feb7c8a59 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ualberta/mavlink_msg_radio_calibration.h @@ -0,0 +1,259 @@ +// MESSAGE RADIO_CALIBRATION PACKING + +#define MAVLINK_MSG_ID_RADIO_CALIBRATION 221 + +typedef struct __mavlink_radio_calibration_t +{ + uint16_t aileron[3]; ///< Aileron setpoints: left, center, right + uint16_t elevator[3]; ///< Elevator setpoints: nose down, center, nose up + uint16_t rudder[3]; ///< Rudder setpoints: nose left, center, nose right + uint16_t gyro[2]; ///< Tail gyro mode/gain setpoints: heading hold, rate mode + uint16_t pitch[5]; ///< Pitch curve setpoints (every 25%) + uint16_t throttle[5]; ///< Throttle curve setpoints (every 25%) +} mavlink_radio_calibration_t; + +#define MAVLINK_MSG_ID_RADIO_CALIBRATION_LEN 42 +#define MAVLINK_MSG_ID_221_LEN 42 + +#define MAVLINK_MSG_RADIO_CALIBRATION_FIELD_AILERON_LEN 3 +#define MAVLINK_MSG_RADIO_CALIBRATION_FIELD_ELEVATOR_LEN 3 +#define MAVLINK_MSG_RADIO_CALIBRATION_FIELD_RUDDER_LEN 3 +#define MAVLINK_MSG_RADIO_CALIBRATION_FIELD_GYRO_LEN 2 +#define MAVLINK_MSG_RADIO_CALIBRATION_FIELD_PITCH_LEN 5 +#define MAVLINK_MSG_RADIO_CALIBRATION_FIELD_THROTTLE_LEN 5 + +#define MAVLINK_MESSAGE_INFO_RADIO_CALIBRATION { \ + "RADIO_CALIBRATION", \ + 6, \ + { { "aileron", NULL, MAVLINK_TYPE_UINT16_T, 3, 0, offsetof(mavlink_radio_calibration_t, aileron) }, \ + { "elevator", NULL, MAVLINK_TYPE_UINT16_T, 3, 6, offsetof(mavlink_radio_calibration_t, elevator) }, \ + { "rudder", NULL, MAVLINK_TYPE_UINT16_T, 3, 12, offsetof(mavlink_radio_calibration_t, rudder) }, \ + { "gyro", NULL, MAVLINK_TYPE_UINT16_T, 2, 18, offsetof(mavlink_radio_calibration_t, gyro) }, \ + { "pitch", NULL, MAVLINK_TYPE_UINT16_T, 5, 22, offsetof(mavlink_radio_calibration_t, pitch) }, \ + { "throttle", NULL, MAVLINK_TYPE_UINT16_T, 5, 32, offsetof(mavlink_radio_calibration_t, throttle) }, \ + } \ +} + + +/** + * @brief Pack a radio_calibration message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param aileron Aileron setpoints: left, center, right + * @param elevator Elevator setpoints: nose down, center, nose up + * @param rudder Rudder setpoints: nose left, center, nose right + * @param gyro Tail gyro mode/gain setpoints: heading hold, rate mode + * @param pitch Pitch curve setpoints (every 25%) + * @param throttle Throttle curve setpoints (every 25%) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_radio_calibration_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const uint16_t *aileron, const uint16_t *elevator, const uint16_t *rudder, const uint16_t *gyro, const uint16_t *pitch, const uint16_t *throttle) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + + _mav_put_uint16_t_array(buf, 0, aileron, 3); + _mav_put_uint16_t_array(buf, 6, elevator, 3); + _mav_put_uint16_t_array(buf, 12, rudder, 3); + _mav_put_uint16_t_array(buf, 18, gyro, 2); + _mav_put_uint16_t_array(buf, 22, pitch, 5); + _mav_put_uint16_t_array(buf, 32, throttle, 5); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 42); +#else + mavlink_radio_calibration_t packet; + + mav_array_memcpy(packet.aileron, aileron, sizeof(uint16_t)*3); + mav_array_memcpy(packet.elevator, elevator, sizeof(uint16_t)*3); + mav_array_memcpy(packet.rudder, rudder, sizeof(uint16_t)*3); + mav_array_memcpy(packet.gyro, gyro, sizeof(uint16_t)*2); + mav_array_memcpy(packet.pitch, pitch, sizeof(uint16_t)*5); + mav_array_memcpy(packet.throttle, throttle, sizeof(uint16_t)*5); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 42); +#endif + + msg->msgid = MAVLINK_MSG_ID_RADIO_CALIBRATION; + return mavlink_finalize_message(msg, system_id, component_id, 42); +} + +/** + * @brief Pack a radio_calibration message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param aileron Aileron setpoints: left, center, right + * @param elevator Elevator setpoints: nose down, center, nose up + * @param rudder Rudder setpoints: nose left, center, nose right + * @param gyro Tail gyro mode/gain setpoints: heading hold, rate mode + * @param pitch Pitch curve setpoints (every 25%) + * @param throttle Throttle curve setpoints (every 25%) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_radio_calibration_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const uint16_t *aileron,const uint16_t *elevator,const uint16_t *rudder,const uint16_t *gyro,const uint16_t *pitch,const uint16_t *throttle) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + + _mav_put_uint16_t_array(buf, 0, aileron, 3); + _mav_put_uint16_t_array(buf, 6, elevator, 3); + _mav_put_uint16_t_array(buf, 12, rudder, 3); + _mav_put_uint16_t_array(buf, 18, gyro, 2); + _mav_put_uint16_t_array(buf, 22, pitch, 5); + _mav_put_uint16_t_array(buf, 32, throttle, 5); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 42); +#else + mavlink_radio_calibration_t packet; + + mav_array_memcpy(packet.aileron, aileron, sizeof(uint16_t)*3); + mav_array_memcpy(packet.elevator, elevator, sizeof(uint16_t)*3); + mav_array_memcpy(packet.rudder, rudder, sizeof(uint16_t)*3); + mav_array_memcpy(packet.gyro, gyro, sizeof(uint16_t)*2); + mav_array_memcpy(packet.pitch, pitch, sizeof(uint16_t)*5); + mav_array_memcpy(packet.throttle, throttle, sizeof(uint16_t)*5); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 42); +#endif + + msg->msgid = MAVLINK_MSG_ID_RADIO_CALIBRATION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 42); +} + +/** + * @brief Encode a radio_calibration struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param radio_calibration C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_radio_calibration_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_radio_calibration_t* radio_calibration) +{ + return mavlink_msg_radio_calibration_pack(system_id, component_id, msg, radio_calibration->aileron, radio_calibration->elevator, radio_calibration->rudder, radio_calibration->gyro, radio_calibration->pitch, radio_calibration->throttle); +} + +/** + * @brief Send a radio_calibration message + * @param chan MAVLink channel to send the message + * + * @param aileron Aileron setpoints: left, center, right + * @param elevator Elevator setpoints: nose down, center, nose up + * @param rudder Rudder setpoints: nose left, center, nose right + * @param gyro Tail gyro mode/gain setpoints: heading hold, rate mode + * @param pitch Pitch curve setpoints (every 25%) + * @param throttle Throttle curve setpoints (every 25%) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_radio_calibration_send(mavlink_channel_t chan, const uint16_t *aileron, const uint16_t *elevator, const uint16_t *rudder, const uint16_t *gyro, const uint16_t *pitch, const uint16_t *throttle) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + + _mav_put_uint16_t_array(buf, 0, aileron, 3); + _mav_put_uint16_t_array(buf, 6, elevator, 3); + _mav_put_uint16_t_array(buf, 12, rudder, 3); + _mav_put_uint16_t_array(buf, 18, gyro, 2); + _mav_put_uint16_t_array(buf, 22, pitch, 5); + _mav_put_uint16_t_array(buf, 32, throttle, 5); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RADIO_CALIBRATION, buf, 42); +#else + mavlink_radio_calibration_t packet; + + mav_array_memcpy(packet.aileron, aileron, sizeof(uint16_t)*3); + mav_array_memcpy(packet.elevator, elevator, sizeof(uint16_t)*3); + mav_array_memcpy(packet.rudder, rudder, sizeof(uint16_t)*3); + mav_array_memcpy(packet.gyro, gyro, sizeof(uint16_t)*2); + mav_array_memcpy(packet.pitch, pitch, sizeof(uint16_t)*5); + mav_array_memcpy(packet.throttle, throttle, sizeof(uint16_t)*5); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RADIO_CALIBRATION, (const char *)&packet, 42); +#endif +} + +#endif + +// MESSAGE RADIO_CALIBRATION UNPACKING + + +/** + * @brief Get field aileron from radio_calibration message + * + * @return Aileron setpoints: left, center, right + */ +static inline uint16_t mavlink_msg_radio_calibration_get_aileron(const mavlink_message_t* msg, uint16_t *aileron) +{ + return _MAV_RETURN_uint16_t_array(msg, aileron, 3, 0); +} + +/** + * @brief Get field elevator from radio_calibration message + * + * @return Elevator setpoints: nose down, center, nose up + */ +static inline uint16_t mavlink_msg_radio_calibration_get_elevator(const mavlink_message_t* msg, uint16_t *elevator) +{ + return _MAV_RETURN_uint16_t_array(msg, elevator, 3, 6); +} + +/** + * @brief Get field rudder from radio_calibration message + * + * @return Rudder setpoints: nose left, center, nose right + */ +static inline uint16_t mavlink_msg_radio_calibration_get_rudder(const mavlink_message_t* msg, uint16_t *rudder) +{ + return _MAV_RETURN_uint16_t_array(msg, rudder, 3, 12); +} + +/** + * @brief Get field gyro from radio_calibration message + * + * @return Tail gyro mode/gain setpoints: heading hold, rate mode + */ +static inline uint16_t mavlink_msg_radio_calibration_get_gyro(const mavlink_message_t* msg, uint16_t *gyro) +{ + return _MAV_RETURN_uint16_t_array(msg, gyro, 2, 18); +} + +/** + * @brief Get field pitch from radio_calibration message + * + * @return Pitch curve setpoints (every 25%) + */ +static inline uint16_t mavlink_msg_radio_calibration_get_pitch(const mavlink_message_t* msg, uint16_t *pitch) +{ + return _MAV_RETURN_uint16_t_array(msg, pitch, 5, 22); +} + +/** + * @brief Get field throttle from radio_calibration message + * + * @return Throttle curve setpoints (every 25%) + */ +static inline uint16_t mavlink_msg_radio_calibration_get_throttle(const mavlink_message_t* msg, uint16_t *throttle) +{ + return _MAV_RETURN_uint16_t_array(msg, throttle, 5, 32); +} + +/** + * @brief Decode a radio_calibration message into a struct + * + * @param msg The message to decode + * @param radio_calibration C-struct to decode the message contents into + */ +static inline void mavlink_msg_radio_calibration_decode(const mavlink_message_t* msg, mavlink_radio_calibration_t* radio_calibration) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_radio_calibration_get_aileron(msg, radio_calibration->aileron); + mavlink_msg_radio_calibration_get_elevator(msg, radio_calibration->elevator); + mavlink_msg_radio_calibration_get_rudder(msg, radio_calibration->rudder); + mavlink_msg_radio_calibration_get_gyro(msg, radio_calibration->gyro); + mavlink_msg_radio_calibration_get_pitch(msg, radio_calibration->pitch); + mavlink_msg_radio_calibration_get_throttle(msg, radio_calibration->throttle); +#else + memcpy(radio_calibration, _MAV_PAYLOAD(msg), 42); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ualberta/mavlink_msg_ualberta_sys_status.h b/mavlink/include/mavlink/v0.9/ualberta/mavlink_msg_ualberta_sys_status.h new file mode 100644 index 0000000000..511ca6b0db --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ualberta/mavlink_msg_ualberta_sys_status.h @@ -0,0 +1,188 @@ +// MESSAGE UALBERTA_SYS_STATUS PACKING + +#define MAVLINK_MSG_ID_UALBERTA_SYS_STATUS 222 + +typedef struct __mavlink_ualberta_sys_status_t +{ + uint8_t mode; ///< System mode, see UALBERTA_AUTOPILOT_MODE ENUM + uint8_t nav_mode; ///< Navigation mode, see UALBERTA_NAV_MODE ENUM + uint8_t pilot; ///< Pilot mode, see UALBERTA_PILOT_MODE +} mavlink_ualberta_sys_status_t; + +#define MAVLINK_MSG_ID_UALBERTA_SYS_STATUS_LEN 3 +#define MAVLINK_MSG_ID_222_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_UALBERTA_SYS_STATUS { \ + "UALBERTA_SYS_STATUS", \ + 3, \ + { { "mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_ualberta_sys_status_t, mode) }, \ + { "nav_mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_ualberta_sys_status_t, nav_mode) }, \ + { "pilot", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_ualberta_sys_status_t, pilot) }, \ + } \ +} + + +/** + * @brief Pack a ualberta_sys_status message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param mode System mode, see UALBERTA_AUTOPILOT_MODE ENUM + * @param nav_mode Navigation mode, see UALBERTA_NAV_MODE ENUM + * @param pilot Pilot mode, see UALBERTA_PILOT_MODE + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ualberta_sys_status_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t mode, uint8_t nav_mode, uint8_t pilot) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, mode); + _mav_put_uint8_t(buf, 1, nav_mode); + _mav_put_uint8_t(buf, 2, pilot); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_ualberta_sys_status_t packet; + packet.mode = mode; + packet.nav_mode = nav_mode; + packet.pilot = pilot; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_UALBERTA_SYS_STATUS; + return mavlink_finalize_message(msg, system_id, component_id, 3); +} + +/** + * @brief Pack a ualberta_sys_status message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param mode System mode, see UALBERTA_AUTOPILOT_MODE ENUM + * @param nav_mode Navigation mode, see UALBERTA_NAV_MODE ENUM + * @param pilot Pilot mode, see UALBERTA_PILOT_MODE + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ualberta_sys_status_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t mode,uint8_t nav_mode,uint8_t pilot) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, mode); + _mav_put_uint8_t(buf, 1, nav_mode); + _mav_put_uint8_t(buf, 2, pilot); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_ualberta_sys_status_t packet; + packet.mode = mode; + packet.nav_mode = nav_mode; + packet.pilot = pilot; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_UALBERTA_SYS_STATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3); +} + +/** + * @brief Encode a ualberta_sys_status struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param ualberta_sys_status C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_ualberta_sys_status_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_ualberta_sys_status_t* ualberta_sys_status) +{ + return mavlink_msg_ualberta_sys_status_pack(system_id, component_id, msg, ualberta_sys_status->mode, ualberta_sys_status->nav_mode, ualberta_sys_status->pilot); +} + +/** + * @brief Send a ualberta_sys_status message + * @param chan MAVLink channel to send the message + * + * @param mode System mode, see UALBERTA_AUTOPILOT_MODE ENUM + * @param nav_mode Navigation mode, see UALBERTA_NAV_MODE ENUM + * @param pilot Pilot mode, see UALBERTA_PILOT_MODE + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_ualberta_sys_status_send(mavlink_channel_t chan, uint8_t mode, uint8_t nav_mode, uint8_t pilot) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, mode); + _mav_put_uint8_t(buf, 1, nav_mode); + _mav_put_uint8_t(buf, 2, pilot); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_UALBERTA_SYS_STATUS, buf, 3); +#else + mavlink_ualberta_sys_status_t packet; + packet.mode = mode; + packet.nav_mode = nav_mode; + packet.pilot = pilot; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_UALBERTA_SYS_STATUS, (const char *)&packet, 3); +#endif +} + +#endif + +// MESSAGE UALBERTA_SYS_STATUS UNPACKING + + +/** + * @brief Get field mode from ualberta_sys_status message + * + * @return System mode, see UALBERTA_AUTOPILOT_MODE ENUM + */ +static inline uint8_t mavlink_msg_ualberta_sys_status_get_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field nav_mode from ualberta_sys_status message + * + * @return Navigation mode, see UALBERTA_NAV_MODE ENUM + */ +static inline uint8_t mavlink_msg_ualberta_sys_status_get_nav_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field pilot from ualberta_sys_status message + * + * @return Pilot mode, see UALBERTA_PILOT_MODE + */ +static inline uint8_t mavlink_msg_ualberta_sys_status_get_pilot(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a ualberta_sys_status message into a struct + * + * @param msg The message to decode + * @param ualberta_sys_status C-struct to decode the message contents into + */ +static inline void mavlink_msg_ualberta_sys_status_decode(const mavlink_message_t* msg, mavlink_ualberta_sys_status_t* ualberta_sys_status) +{ +#if MAVLINK_NEED_BYTE_SWAP + ualberta_sys_status->mode = mavlink_msg_ualberta_sys_status_get_mode(msg); + ualberta_sys_status->nav_mode = mavlink_msg_ualberta_sys_status_get_nav_mode(msg); + ualberta_sys_status->pilot = mavlink_msg_ualberta_sys_status_get_pilot(msg); +#else + memcpy(ualberta_sys_status, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v0.9/ualberta/testsuite.h b/mavlink/include/mavlink/v0.9/ualberta/testsuite.h new file mode 100644 index 0000000000..79a6a004a4 --- /dev/null +++ b/mavlink/include/mavlink/v0.9/ualberta/testsuite.h @@ -0,0 +1,192 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from ualberta.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef UALBERTA_TESTSUITE_H +#define UALBERTA_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL +static void mavlink_test_common(uint8_t, uint8_t, mavlink_message_t *last_msg); +static void mavlink_test_ualberta(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_test_common(system_id, component_id, last_msg); + mavlink_test_ualberta(system_id, component_id, last_msg); +} +#endif + +#include "../common/testsuite.h" + + +static void mavlink_test_nav_filter_bias(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_nav_filter_bias_t packet_in = { + 93372036854775807ULL, + 73.0, + 101.0, + 129.0, + 157.0, + 185.0, + 213.0, + }; + mavlink_nav_filter_bias_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.usec = packet_in.usec; + packet1.accel_0 = packet_in.accel_0; + packet1.accel_1 = packet_in.accel_1; + packet1.accel_2 = packet_in.accel_2; + packet1.gyro_0 = packet_in.gyro_0; + packet1.gyro_1 = packet_in.gyro_1; + packet1.gyro_2 = packet_in.gyro_2; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_nav_filter_bias_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_nav_filter_bias_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_nav_filter_bias_pack(system_id, component_id, &msg , packet1.usec , packet1.accel_0 , packet1.accel_1 , packet1.accel_2 , packet1.gyro_0 , packet1.gyro_1 , packet1.gyro_2 ); + mavlink_msg_nav_filter_bias_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_nav_filter_bias_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.usec , packet1.accel_0 , packet1.accel_1 , packet1.accel_2 , packet1.gyro_0 , packet1.gyro_1 , packet1.gyro_2 ); + mavlink_msg_nav_filter_bias_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; i 0 radius in meters to pass by WP. Positive value for clockwise orbit, negative value for counter-clockwise orbit. Allows trajectory control.| Desired yaw angle at MISSION (rotary wing)| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_UNLIM=17, /* Loiter around this MISSION an unlimited amount of time |Empty| Empty| Radius around MISSION, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_TURNS=18, /* Loiter around this MISSION for X turns |Turns| Empty| Radius around MISSION, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_TIME=19, /* Loiter around this MISSION for X seconds |Seconds (decimal)| Empty| Radius around MISSION, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_RETURN_TO_LAUNCH=20, /* Return to launch location |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_NAV_LAND=21, /* Land at location |Empty| Empty| Empty| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_TAKEOFF=22, /* Takeoff from ground / hand |Minimum pitch (if airspeed sensor present), desired pitch without sensor| Empty| Empty| Yaw angle (if magnetometer present), ignored without magnetometer| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_ROI=80, /* Sets the region of interest (ROI) for a sensor set or the vehicle itself. This can then be used by the vehicles control system to control the vehicle attitude and the attitude of various sensors such as cameras. |Region of intereset mode. (see MAV_ROI enum)| MISSION index/ target ID. (see MAV_ROI enum)| ROI index (allows a vehicle to manage multiple ROI's)| Empty| x the location of the fixed ROI (see MAV_FRAME)| y| z| */ + MAV_CMD_NAV_PATHPLANNING=81, /* Control autonomous path planning on the MAV. |0: Disable local obstacle avoidance / local path planning (without resetting map), 1: Enable local path planning, 2: Enable and reset local path planning| 0: Disable full path planning (without resetting map), 1: Enable, 2: Enable and reset map/occupancy grid, 3: Enable and reset planned route, but not occupancy grid| Empty| Yaw angle at goal, in compass degrees, [0..360]| Latitude/X of goal| Longitude/Y of goal| Altitude/Z of goal| */ + MAV_CMD_NAV_LAST=95, /* NOP - This command is only used to mark the upper limit of the NAV/ACTION commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_DELAY=112, /* Delay mission state machine. |Delay in seconds (decimal)| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_CHANGE_ALT=113, /* Ascend/descend at rate. Delay mission state machine until desired altitude reached. |Descent / Ascend rate (m/s)| Empty| Empty| Empty| Empty| Empty| Finish Altitude| */ + MAV_CMD_CONDITION_DISTANCE=114, /* Delay mission state machine until within desired distance of next NAV point. |Distance (meters)| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_YAW=115, /* Reach a certain target angle. |target angle: [0-360], 0 is north| speed during yaw change:[deg per second]| direction: negative: counter clockwise, positive: clockwise [-1,1]| relative offset or absolute angle: [ 1,0]| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_LAST=159, /* NOP - This command is only used to mark the upper limit of the CONDITION commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_MODE=176, /* Set system mode. |Mode, as defined by ENUM MAV_MODE| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_JUMP=177, /* Jump to the desired command in the mission list. Repeat this action only the specified number of times |Sequence number| Repeat count| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_CHANGE_SPEED=178, /* Change speed and/or throttle set points. |Speed type (0=Airspeed, 1=Ground Speed)| Speed (m/s, -1 indicates no change)| Throttle ( Percent, -1 indicates no change)| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_HOME=179, /* Changes the home location either to the current location or a specified location. |Use current (1=use current location, 0=use specified location)| Empty| Empty| Empty| Latitude| Longitude| Altitude| */ + MAV_CMD_DO_SET_PARAMETER=180, /* Set a system parameter. Caution! Use of this command requires knowledge of the numeric enumeration value of the parameter. |Parameter number| Parameter value| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_RELAY=181, /* Set a relay to a condition. |Relay number| Setting (1=on, 0=off, others possible depending on system hardware)| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_REPEAT_RELAY=182, /* Cycle a relay on and off for a desired number of cyles with a desired period. |Relay number| Cycle count| Cycle time (seconds, decimal)| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_SERVO=183, /* Set a servo to a desired PWM value. |Servo number| PWM (microseconds, 1000 to 2000 typical)| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_REPEAT_SERVO=184, /* Cycle a between its nominal setting and a desired PWM for a desired number of cycles with a desired period. |Servo number| PWM (microseconds, 1000 to 2000 typical)| Cycle count| Cycle time (seconds)| Empty| Empty| Empty| */ + MAV_CMD_DO_CONTROL_VIDEO=200, /* Control onboard camera system. |Camera ID (-1 for all)| Transmission: 0: disabled, 1: enabled compressed, 2: enabled raw| Transmission mode: 0: video stream, >0: single images every n seconds (decimal)| Recording: 0: disabled, 1: enabled compressed, 2: enabled raw| Empty| Empty| Empty| */ + MAV_CMD_DO_DIGICAM_CONFIGURE=202, /* Mission command to configure an on-board camera controller system. |Modes: P, TV, AV, M, Etc| Shutter speed: Divisor number for one second| Aperture: F stop number| ISO number e.g. 80, 100, 200, Etc| Exposure type enumerator| Command Identity| Main engine cut-off time before camera trigger in seconds/10 (0 means no cut-off)| */ + MAV_CMD_DO_DIGICAM_CONTROL=203, /* Mission command to control an on-board camera controller system. |Session control e.g. show/hide lens| Zoom's absolute position| Zooming step value to offset zoom from the current position| Focus Locking, Unlocking or Re-locking| Shooting Command| Command Identity| Empty| */ + MAV_CMD_DO_MOUNT_CONFIGURE=204, /* Mission command to configure a camera or antenna mount |Mount operation mode (see MAV_MOUNT_MODE enum)| stabilize roll? (1 = yes, 0 = no)| stabilize pitch? (1 = yes, 0 = no)| stabilize yaw? (1 = yes, 0 = no)| Empty| Empty| Empty| */ + MAV_CMD_DO_MOUNT_CONTROL=205, /* Mission command to control a camera or antenna mount |pitch(deg*100) or lat, depending on mount mode.| roll(deg*100) or lon depending on mount mode| yaw(deg*100) or alt (in cm) depending on mount mode| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_LAST=240, /* NOP - This command is only used to mark the upper limit of the DO commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_PREFLIGHT_CALIBRATION=241, /* Trigger calibration. This command will be only accepted if in pre-flight mode. |Gyro calibration: 0: no, 1: yes| Magnetometer calibration: 0: no, 1: yes| Ground pressure: 0: no, 1: yes| Radio calibration: 0: no, 1: yes| Empty| Empty| Empty| */ + MAV_CMD_PREFLIGHT_SET_SENSOR_OFFSETS=242, /* Set sensor offsets. This command will be only accepted if in pre-flight mode. |Sensor to adjust the offsets for: 0: gyros, 1: accelerometer, 2: magnetometer, 3: barometer, 4: optical flow| X axis offset (or generic dimension 1), in the sensor's raw units| Y axis offset (or generic dimension 2), in the sensor's raw units| Z axis offset (or generic dimension 3), in the sensor's raw units| Generic dimension 4, in the sensor's raw units| Generic dimension 5, in the sensor's raw units| Generic dimension 6, in the sensor's raw units| */ + MAV_CMD_PREFLIGHT_STORAGE=245, /* Request storage of different parameter values and logs. This command will be only accepted if in pre-flight mode. |Parameter storage: 0: READ FROM FLASH/EEPROM, 1: WRITE CURRENT TO FLASH/EEPROM| Mission storage: 0: READ FROM FLASH/EEPROM, 1: WRITE CURRENT TO FLASH/EEPROM| Reserved| Reserved| Empty| Empty| Empty| */ + MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN=246, /* Request the reboot or shutdown of system components. |0: Do nothing for autopilot, 1: Reboot autopilot, 2: Shutdown autopilot.| 0: Do nothing for onboard computer, 1: Reboot onboard computer, 2: Shutdown onboard computer.| Reserved| Reserved| Empty| Empty| Empty| */ + MAV_CMD_OVERRIDE_GOTO=252, /* Hold / continue the current action |MAV_GOTO_DO_HOLD: hold MAV_GOTO_DO_CONTINUE: continue with next item in mission plan| MAV_GOTO_HOLD_AT_CURRENT_POSITION: Hold at current position MAV_GOTO_HOLD_AT_SPECIFIED_POSITION: hold at specified position| MAV_FRAME coordinate frame of hold point| Desired yaw angle in degrees| Latitude / X position| Longitude / Y position| Altitude / Z position| */ + MAV_CMD_MISSION_START=300, /* start running a mission |first_item: the first mission item to run| last_item: the last mission item to run (after this item is run, the mission ends)| */ + MAV_CMD_COMPONENT_ARM_DISARM=400, /* Arms / Disarms a component |1 to arm, 0 to disarm| */ + MAV_CMD_ENUM_END=401, /* | */ +}; +#endif + +/** @brief */ +#ifndef HAVE_ENUM_FENCE_ACTION +#define HAVE_ENUM_FENCE_ACTION +enum FENCE_ACTION +{ + FENCE_ACTION_NONE=0, /* Disable fenced mode | */ + FENCE_ACTION_GUIDED=1, /* Switched to guided mode to return point (fence point 0) | */ + FENCE_ACTION_ENUM_END=2, /* | */ +}; +#endif + +/** @brief */ +#ifndef HAVE_ENUM_FENCE_BREACH +#define HAVE_ENUM_FENCE_BREACH +enum FENCE_BREACH +{ + FENCE_BREACH_NONE=0, /* No last fence breach | */ + FENCE_BREACH_MINALT=1, /* Breached minimum altitude | */ + FENCE_BREACH_MAXALT=2, /* Breached minimum altitude | */ + FENCE_BREACH_BOUNDARY=3, /* Breached fence boundary | */ + FENCE_BREACH_ENUM_END=4, /* | */ +}; +#endif + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_sensor_offsets.h" +#include "./mavlink_msg_set_mag_offsets.h" +#include "./mavlink_msg_meminfo.h" +#include "./mavlink_msg_ap_adc.h" +#include "./mavlink_msg_digicam_configure.h" +#include "./mavlink_msg_digicam_control.h" +#include "./mavlink_msg_mount_configure.h" +#include "./mavlink_msg_mount_control.h" +#include "./mavlink_msg_mount_status.h" +#include "./mavlink_msg_fence_point.h" +#include "./mavlink_msg_fence_fetch_point.h" +#include "./mavlink_msg_fence_status.h" +#include "./mavlink_msg_ahrs.h" +#include "./mavlink_msg_simstate.h" +#include "./mavlink_msg_hwstatus.h" +#include "./mavlink_msg_radio.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // ARDUPILOTMEGA_H diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink.h new file mode 100644 index 0000000000..551938f044 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink.h @@ -0,0 +1,27 @@ +/** @file + * @brief MAVLink comm protocol built from ardupilotmega.xml + * @see http://pixhawk.ethz.ch/software/mavlink + */ +#ifndef MAVLINK_H +#define MAVLINK_H + +#ifndef MAVLINK_STX +#define MAVLINK_STX 254 +#endif + +#ifndef MAVLINK_ENDIAN +#define MAVLINK_ENDIAN MAVLINK_LITTLE_ENDIAN +#endif + +#ifndef MAVLINK_ALIGNED_FIELDS +#define MAVLINK_ALIGNED_FIELDS 1 +#endif + +#ifndef MAVLINK_CRC_EXTRA +#define MAVLINK_CRC_EXTRA 1 +#endif + +#include "version.h" +#include "ardupilotmega.h" + +#endif // MAVLINK_H diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_ahrs.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_ahrs.h new file mode 100644 index 0000000000..a59f89aeeb --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_ahrs.h @@ -0,0 +1,276 @@ +// MESSAGE AHRS PACKING + +#define MAVLINK_MSG_ID_AHRS 163 + +typedef struct __mavlink_ahrs_t +{ + float omegaIx; ///< X gyro drift estimate rad/s + float omegaIy; ///< Y gyro drift estimate rad/s + float omegaIz; ///< Z gyro drift estimate rad/s + float accel_weight; ///< average accel_weight + float renorm_val; ///< average renormalisation value + float error_rp; ///< average error_roll_pitch value + float error_yaw; ///< average error_yaw value +} mavlink_ahrs_t; + +#define MAVLINK_MSG_ID_AHRS_LEN 28 +#define MAVLINK_MSG_ID_163_LEN 28 + + + +#define MAVLINK_MESSAGE_INFO_AHRS { \ + "AHRS", \ + 7, \ + { { "omegaIx", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_ahrs_t, omegaIx) }, \ + { "omegaIy", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_ahrs_t, omegaIy) }, \ + { "omegaIz", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_ahrs_t, omegaIz) }, \ + { "accel_weight", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_ahrs_t, accel_weight) }, \ + { "renorm_val", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_ahrs_t, renorm_val) }, \ + { "error_rp", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_ahrs_t, error_rp) }, \ + { "error_yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_ahrs_t, error_yaw) }, \ + } \ +} + + +/** + * @brief Pack a ahrs message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param omegaIx X gyro drift estimate rad/s + * @param omegaIy Y gyro drift estimate rad/s + * @param omegaIz Z gyro drift estimate rad/s + * @param accel_weight average accel_weight + * @param renorm_val average renormalisation value + * @param error_rp average error_roll_pitch value + * @param error_yaw average error_yaw value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ahrs_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float omegaIx, float omegaIy, float omegaIz, float accel_weight, float renorm_val, float error_rp, float error_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_float(buf, 0, omegaIx); + _mav_put_float(buf, 4, omegaIy); + _mav_put_float(buf, 8, omegaIz); + _mav_put_float(buf, 12, accel_weight); + _mav_put_float(buf, 16, renorm_val); + _mav_put_float(buf, 20, error_rp); + _mav_put_float(buf, 24, error_yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_ahrs_t packet; + packet.omegaIx = omegaIx; + packet.omegaIy = omegaIy; + packet.omegaIz = omegaIz; + packet.accel_weight = accel_weight; + packet.renorm_val = renorm_val; + packet.error_rp = error_rp; + packet.error_yaw = error_yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_AHRS; + return mavlink_finalize_message(msg, system_id, component_id, 28, 127); +} + +/** + * @brief Pack a ahrs message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param omegaIx X gyro drift estimate rad/s + * @param omegaIy Y gyro drift estimate rad/s + * @param omegaIz Z gyro drift estimate rad/s + * @param accel_weight average accel_weight + * @param renorm_val average renormalisation value + * @param error_rp average error_roll_pitch value + * @param error_yaw average error_yaw value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ahrs_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float omegaIx,float omegaIy,float omegaIz,float accel_weight,float renorm_val,float error_rp,float error_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_float(buf, 0, omegaIx); + _mav_put_float(buf, 4, omegaIy); + _mav_put_float(buf, 8, omegaIz); + _mav_put_float(buf, 12, accel_weight); + _mav_put_float(buf, 16, renorm_val); + _mav_put_float(buf, 20, error_rp); + _mav_put_float(buf, 24, error_yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_ahrs_t packet; + packet.omegaIx = omegaIx; + packet.omegaIy = omegaIy; + packet.omegaIz = omegaIz; + packet.accel_weight = accel_weight; + packet.renorm_val = renorm_val; + packet.error_rp = error_rp; + packet.error_yaw = error_yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_AHRS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 28, 127); +} + +/** + * @brief Encode a ahrs struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param ahrs C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_ahrs_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_ahrs_t* ahrs) +{ + return mavlink_msg_ahrs_pack(system_id, component_id, msg, ahrs->omegaIx, ahrs->omegaIy, ahrs->omegaIz, ahrs->accel_weight, ahrs->renorm_val, ahrs->error_rp, ahrs->error_yaw); +} + +/** + * @brief Send a ahrs message + * @param chan MAVLink channel to send the message + * + * @param omegaIx X gyro drift estimate rad/s + * @param omegaIy Y gyro drift estimate rad/s + * @param omegaIz Z gyro drift estimate rad/s + * @param accel_weight average accel_weight + * @param renorm_val average renormalisation value + * @param error_rp average error_roll_pitch value + * @param error_yaw average error_yaw value + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_ahrs_send(mavlink_channel_t chan, float omegaIx, float omegaIy, float omegaIz, float accel_weight, float renorm_val, float error_rp, float error_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_float(buf, 0, omegaIx); + _mav_put_float(buf, 4, omegaIy); + _mav_put_float(buf, 8, omegaIz); + _mav_put_float(buf, 12, accel_weight); + _mav_put_float(buf, 16, renorm_val); + _mav_put_float(buf, 20, error_rp); + _mav_put_float(buf, 24, error_yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AHRS, buf, 28, 127); +#else + mavlink_ahrs_t packet; + packet.omegaIx = omegaIx; + packet.omegaIy = omegaIy; + packet.omegaIz = omegaIz; + packet.accel_weight = accel_weight; + packet.renorm_val = renorm_val; + packet.error_rp = error_rp; + packet.error_yaw = error_yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AHRS, (const char *)&packet, 28, 127); +#endif +} + +#endif + +// MESSAGE AHRS UNPACKING + + +/** + * @brief Get field omegaIx from ahrs message + * + * @return X gyro drift estimate rad/s + */ +static inline float mavlink_msg_ahrs_get_omegaIx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field omegaIy from ahrs message + * + * @return Y gyro drift estimate rad/s + */ +static inline float mavlink_msg_ahrs_get_omegaIy(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field omegaIz from ahrs message + * + * @return Z gyro drift estimate rad/s + */ +static inline float mavlink_msg_ahrs_get_omegaIz(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field accel_weight from ahrs message + * + * @return average accel_weight + */ +static inline float mavlink_msg_ahrs_get_accel_weight(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field renorm_val from ahrs message + * + * @return average renormalisation value + */ +static inline float mavlink_msg_ahrs_get_renorm_val(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field error_rp from ahrs message + * + * @return average error_roll_pitch value + */ +static inline float mavlink_msg_ahrs_get_error_rp(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field error_yaw from ahrs message + * + * @return average error_yaw value + */ +static inline float mavlink_msg_ahrs_get_error_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Decode a ahrs message into a struct + * + * @param msg The message to decode + * @param ahrs C-struct to decode the message contents into + */ +static inline void mavlink_msg_ahrs_decode(const mavlink_message_t* msg, mavlink_ahrs_t* ahrs) +{ +#if MAVLINK_NEED_BYTE_SWAP + ahrs->omegaIx = mavlink_msg_ahrs_get_omegaIx(msg); + ahrs->omegaIy = mavlink_msg_ahrs_get_omegaIy(msg); + ahrs->omegaIz = mavlink_msg_ahrs_get_omegaIz(msg); + ahrs->accel_weight = mavlink_msg_ahrs_get_accel_weight(msg); + ahrs->renorm_val = mavlink_msg_ahrs_get_renorm_val(msg); + ahrs->error_rp = mavlink_msg_ahrs_get_error_rp(msg); + ahrs->error_yaw = mavlink_msg_ahrs_get_error_yaw(msg); +#else + memcpy(ahrs, _MAV_PAYLOAD(msg), 28); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_ap_adc.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_ap_adc.h new file mode 100644 index 0000000000..ea640c4fb0 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_ap_adc.h @@ -0,0 +1,254 @@ +// MESSAGE AP_ADC PACKING + +#define MAVLINK_MSG_ID_AP_ADC 153 + +typedef struct __mavlink_ap_adc_t +{ + uint16_t adc1; ///< ADC output 1 + uint16_t adc2; ///< ADC output 2 + uint16_t adc3; ///< ADC output 3 + uint16_t adc4; ///< ADC output 4 + uint16_t adc5; ///< ADC output 5 + uint16_t adc6; ///< ADC output 6 +} mavlink_ap_adc_t; + +#define MAVLINK_MSG_ID_AP_ADC_LEN 12 +#define MAVLINK_MSG_ID_153_LEN 12 + + + +#define MAVLINK_MESSAGE_INFO_AP_ADC { \ + "AP_ADC", \ + 6, \ + { { "adc1", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_ap_adc_t, adc1) }, \ + { "adc2", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_ap_adc_t, adc2) }, \ + { "adc3", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_ap_adc_t, adc3) }, \ + { "adc4", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_ap_adc_t, adc4) }, \ + { "adc5", NULL, MAVLINK_TYPE_UINT16_T, 0, 8, offsetof(mavlink_ap_adc_t, adc5) }, \ + { "adc6", NULL, MAVLINK_TYPE_UINT16_T, 0, 10, offsetof(mavlink_ap_adc_t, adc6) }, \ + } \ +} + + +/** + * @brief Pack a ap_adc message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param adc1 ADC output 1 + * @param adc2 ADC output 2 + * @param adc3 ADC output 3 + * @param adc4 ADC output 4 + * @param adc5 ADC output 5 + * @param adc6 ADC output 6 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ap_adc_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t adc1, uint16_t adc2, uint16_t adc3, uint16_t adc4, uint16_t adc5, uint16_t adc6) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint16_t(buf, 0, adc1); + _mav_put_uint16_t(buf, 2, adc2); + _mav_put_uint16_t(buf, 4, adc3); + _mav_put_uint16_t(buf, 6, adc4); + _mav_put_uint16_t(buf, 8, adc5); + _mav_put_uint16_t(buf, 10, adc6); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_ap_adc_t packet; + packet.adc1 = adc1; + packet.adc2 = adc2; + packet.adc3 = adc3; + packet.adc4 = adc4; + packet.adc5 = adc5; + packet.adc6 = adc6; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_AP_ADC; + return mavlink_finalize_message(msg, system_id, component_id, 12, 188); +} + +/** + * @brief Pack a ap_adc message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param adc1 ADC output 1 + * @param adc2 ADC output 2 + * @param adc3 ADC output 3 + * @param adc4 ADC output 4 + * @param adc5 ADC output 5 + * @param adc6 ADC output 6 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ap_adc_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t adc1,uint16_t adc2,uint16_t adc3,uint16_t adc4,uint16_t adc5,uint16_t adc6) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint16_t(buf, 0, adc1); + _mav_put_uint16_t(buf, 2, adc2); + _mav_put_uint16_t(buf, 4, adc3); + _mav_put_uint16_t(buf, 6, adc4); + _mav_put_uint16_t(buf, 8, adc5); + _mav_put_uint16_t(buf, 10, adc6); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_ap_adc_t packet; + packet.adc1 = adc1; + packet.adc2 = adc2; + packet.adc3 = adc3; + packet.adc4 = adc4; + packet.adc5 = adc5; + packet.adc6 = adc6; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_AP_ADC; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12, 188); +} + +/** + * @brief Encode a ap_adc struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param ap_adc C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_ap_adc_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_ap_adc_t* ap_adc) +{ + return mavlink_msg_ap_adc_pack(system_id, component_id, msg, ap_adc->adc1, ap_adc->adc2, ap_adc->adc3, ap_adc->adc4, ap_adc->adc5, ap_adc->adc6); +} + +/** + * @brief Send a ap_adc message + * @param chan MAVLink channel to send the message + * + * @param adc1 ADC output 1 + * @param adc2 ADC output 2 + * @param adc3 ADC output 3 + * @param adc4 ADC output 4 + * @param adc5 ADC output 5 + * @param adc6 ADC output 6 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_ap_adc_send(mavlink_channel_t chan, uint16_t adc1, uint16_t adc2, uint16_t adc3, uint16_t adc4, uint16_t adc5, uint16_t adc6) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint16_t(buf, 0, adc1); + _mav_put_uint16_t(buf, 2, adc2); + _mav_put_uint16_t(buf, 4, adc3); + _mav_put_uint16_t(buf, 6, adc4); + _mav_put_uint16_t(buf, 8, adc5); + _mav_put_uint16_t(buf, 10, adc6); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AP_ADC, buf, 12, 188); +#else + mavlink_ap_adc_t packet; + packet.adc1 = adc1; + packet.adc2 = adc2; + packet.adc3 = adc3; + packet.adc4 = adc4; + packet.adc5 = adc5; + packet.adc6 = adc6; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AP_ADC, (const char *)&packet, 12, 188); +#endif +} + +#endif + +// MESSAGE AP_ADC UNPACKING + + +/** + * @brief Get field adc1 from ap_adc message + * + * @return ADC output 1 + */ +static inline uint16_t mavlink_msg_ap_adc_get_adc1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field adc2 from ap_adc message + * + * @return ADC output 2 + */ +static inline uint16_t mavlink_msg_ap_adc_get_adc2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Get field adc3 from ap_adc message + * + * @return ADC output 3 + */ +static inline uint16_t mavlink_msg_ap_adc_get_adc3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field adc4 from ap_adc message + * + * @return ADC output 4 + */ +static inline uint16_t mavlink_msg_ap_adc_get_adc4(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field adc5 from ap_adc message + * + * @return ADC output 5 + */ +static inline uint16_t mavlink_msg_ap_adc_get_adc5(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Get field adc6 from ap_adc message + * + * @return ADC output 6 + */ +static inline uint16_t mavlink_msg_ap_adc_get_adc6(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 10); +} + +/** + * @brief Decode a ap_adc message into a struct + * + * @param msg The message to decode + * @param ap_adc C-struct to decode the message contents into + */ +static inline void mavlink_msg_ap_adc_decode(const mavlink_message_t* msg, mavlink_ap_adc_t* ap_adc) +{ +#if MAVLINK_NEED_BYTE_SWAP + ap_adc->adc1 = mavlink_msg_ap_adc_get_adc1(msg); + ap_adc->adc2 = mavlink_msg_ap_adc_get_adc2(msg); + ap_adc->adc3 = mavlink_msg_ap_adc_get_adc3(msg); + ap_adc->adc4 = mavlink_msg_ap_adc_get_adc4(msg); + ap_adc->adc5 = mavlink_msg_ap_adc_get_adc5(msg); + ap_adc->adc6 = mavlink_msg_ap_adc_get_adc6(msg); +#else + memcpy(ap_adc, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_digicam_configure.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_digicam_configure.h new file mode 100644 index 0000000000..cc49c50255 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_digicam_configure.h @@ -0,0 +1,364 @@ +// MESSAGE DIGICAM_CONFIGURE PACKING + +#define MAVLINK_MSG_ID_DIGICAM_CONFIGURE 154 + +typedef struct __mavlink_digicam_configure_t +{ + float extra_value; ///< Correspondent value to given extra_param + uint16_t shutter_speed; ///< Divisor number //e.g. 1000 means 1/1000 (0 means ignore) + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t mode; ///< Mode enumeration from 1 to N //P, TV, AV, M, Etc (0 means ignore) + uint8_t aperture; ///< F stop number x 10 //e.g. 28 means 2.8 (0 means ignore) + uint8_t iso; ///< ISO enumeration from 1 to N //e.g. 80, 100, 200, Etc (0 means ignore) + uint8_t exposure_type; ///< Exposure type enumeration from 1 to N (0 means ignore) + uint8_t command_id; ///< Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + uint8_t engine_cut_off; ///< Main engine cut-off time before camera trigger in seconds/10 (0 means no cut-off) + uint8_t extra_param; ///< Extra parameters enumeration (0 means ignore) +} mavlink_digicam_configure_t; + +#define MAVLINK_MSG_ID_DIGICAM_CONFIGURE_LEN 15 +#define MAVLINK_MSG_ID_154_LEN 15 + + + +#define MAVLINK_MESSAGE_INFO_DIGICAM_CONFIGURE { \ + "DIGICAM_CONFIGURE", \ + 11, \ + { { "extra_value", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_digicam_configure_t, extra_value) }, \ + { "shutter_speed", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_digicam_configure_t, shutter_speed) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_digicam_configure_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 7, offsetof(mavlink_digicam_configure_t, target_component) }, \ + { "mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_digicam_configure_t, mode) }, \ + { "aperture", NULL, MAVLINK_TYPE_UINT8_T, 0, 9, offsetof(mavlink_digicam_configure_t, aperture) }, \ + { "iso", NULL, MAVLINK_TYPE_UINT8_T, 0, 10, offsetof(mavlink_digicam_configure_t, iso) }, \ + { "exposure_type", NULL, MAVLINK_TYPE_UINT8_T, 0, 11, offsetof(mavlink_digicam_configure_t, exposure_type) }, \ + { "command_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 12, offsetof(mavlink_digicam_configure_t, command_id) }, \ + { "engine_cut_off", NULL, MAVLINK_TYPE_UINT8_T, 0, 13, offsetof(mavlink_digicam_configure_t, engine_cut_off) }, \ + { "extra_param", NULL, MAVLINK_TYPE_UINT8_T, 0, 14, offsetof(mavlink_digicam_configure_t, extra_param) }, \ + } \ +} + + +/** + * @brief Pack a digicam_configure message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param mode Mode enumeration from 1 to N //P, TV, AV, M, Etc (0 means ignore) + * @param shutter_speed Divisor number //e.g. 1000 means 1/1000 (0 means ignore) + * @param aperture F stop number x 10 //e.g. 28 means 2.8 (0 means ignore) + * @param iso ISO enumeration from 1 to N //e.g. 80, 100, 200, Etc (0 means ignore) + * @param exposure_type Exposure type enumeration from 1 to N (0 means ignore) + * @param command_id Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + * @param engine_cut_off Main engine cut-off time before camera trigger in seconds/10 (0 means no cut-off) + * @param extra_param Extra parameters enumeration (0 means ignore) + * @param extra_value Correspondent value to given extra_param + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_digicam_configure_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t mode, uint16_t shutter_speed, uint8_t aperture, uint8_t iso, uint8_t exposure_type, uint8_t command_id, uint8_t engine_cut_off, uint8_t extra_param, float extra_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_float(buf, 0, extra_value); + _mav_put_uint16_t(buf, 4, shutter_speed); + _mav_put_uint8_t(buf, 6, target_system); + _mav_put_uint8_t(buf, 7, target_component); + _mav_put_uint8_t(buf, 8, mode); + _mav_put_uint8_t(buf, 9, aperture); + _mav_put_uint8_t(buf, 10, iso); + _mav_put_uint8_t(buf, 11, exposure_type); + _mav_put_uint8_t(buf, 12, command_id); + _mav_put_uint8_t(buf, 13, engine_cut_off); + _mav_put_uint8_t(buf, 14, extra_param); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 15); +#else + mavlink_digicam_configure_t packet; + packet.extra_value = extra_value; + packet.shutter_speed = shutter_speed; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mode = mode; + packet.aperture = aperture; + packet.iso = iso; + packet.exposure_type = exposure_type; + packet.command_id = command_id; + packet.engine_cut_off = engine_cut_off; + packet.extra_param = extra_param; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 15); +#endif + + msg->msgid = MAVLINK_MSG_ID_DIGICAM_CONFIGURE; + return mavlink_finalize_message(msg, system_id, component_id, 15, 84); +} + +/** + * @brief Pack a digicam_configure message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param mode Mode enumeration from 1 to N //P, TV, AV, M, Etc (0 means ignore) + * @param shutter_speed Divisor number //e.g. 1000 means 1/1000 (0 means ignore) + * @param aperture F stop number x 10 //e.g. 28 means 2.8 (0 means ignore) + * @param iso ISO enumeration from 1 to N //e.g. 80, 100, 200, Etc (0 means ignore) + * @param exposure_type Exposure type enumeration from 1 to N (0 means ignore) + * @param command_id Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + * @param engine_cut_off Main engine cut-off time before camera trigger in seconds/10 (0 means no cut-off) + * @param extra_param Extra parameters enumeration (0 means ignore) + * @param extra_value Correspondent value to given extra_param + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_digicam_configure_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t mode,uint16_t shutter_speed,uint8_t aperture,uint8_t iso,uint8_t exposure_type,uint8_t command_id,uint8_t engine_cut_off,uint8_t extra_param,float extra_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_float(buf, 0, extra_value); + _mav_put_uint16_t(buf, 4, shutter_speed); + _mav_put_uint8_t(buf, 6, target_system); + _mav_put_uint8_t(buf, 7, target_component); + _mav_put_uint8_t(buf, 8, mode); + _mav_put_uint8_t(buf, 9, aperture); + _mav_put_uint8_t(buf, 10, iso); + _mav_put_uint8_t(buf, 11, exposure_type); + _mav_put_uint8_t(buf, 12, command_id); + _mav_put_uint8_t(buf, 13, engine_cut_off); + _mav_put_uint8_t(buf, 14, extra_param); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 15); +#else + mavlink_digicam_configure_t packet; + packet.extra_value = extra_value; + packet.shutter_speed = shutter_speed; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mode = mode; + packet.aperture = aperture; + packet.iso = iso; + packet.exposure_type = exposure_type; + packet.command_id = command_id; + packet.engine_cut_off = engine_cut_off; + packet.extra_param = extra_param; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 15); +#endif + + msg->msgid = MAVLINK_MSG_ID_DIGICAM_CONFIGURE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 15, 84); +} + +/** + * @brief Encode a digicam_configure struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param digicam_configure C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_digicam_configure_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_digicam_configure_t* digicam_configure) +{ + return mavlink_msg_digicam_configure_pack(system_id, component_id, msg, digicam_configure->target_system, digicam_configure->target_component, digicam_configure->mode, digicam_configure->shutter_speed, digicam_configure->aperture, digicam_configure->iso, digicam_configure->exposure_type, digicam_configure->command_id, digicam_configure->engine_cut_off, digicam_configure->extra_param, digicam_configure->extra_value); +} + +/** + * @brief Send a digicam_configure message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param mode Mode enumeration from 1 to N //P, TV, AV, M, Etc (0 means ignore) + * @param shutter_speed Divisor number //e.g. 1000 means 1/1000 (0 means ignore) + * @param aperture F stop number x 10 //e.g. 28 means 2.8 (0 means ignore) + * @param iso ISO enumeration from 1 to N //e.g. 80, 100, 200, Etc (0 means ignore) + * @param exposure_type Exposure type enumeration from 1 to N (0 means ignore) + * @param command_id Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + * @param engine_cut_off Main engine cut-off time before camera trigger in seconds/10 (0 means no cut-off) + * @param extra_param Extra parameters enumeration (0 means ignore) + * @param extra_value Correspondent value to given extra_param + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_digicam_configure_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t mode, uint16_t shutter_speed, uint8_t aperture, uint8_t iso, uint8_t exposure_type, uint8_t command_id, uint8_t engine_cut_off, uint8_t extra_param, float extra_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_float(buf, 0, extra_value); + _mav_put_uint16_t(buf, 4, shutter_speed); + _mav_put_uint8_t(buf, 6, target_system); + _mav_put_uint8_t(buf, 7, target_component); + _mav_put_uint8_t(buf, 8, mode); + _mav_put_uint8_t(buf, 9, aperture); + _mav_put_uint8_t(buf, 10, iso); + _mav_put_uint8_t(buf, 11, exposure_type); + _mav_put_uint8_t(buf, 12, command_id); + _mav_put_uint8_t(buf, 13, engine_cut_off); + _mav_put_uint8_t(buf, 14, extra_param); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DIGICAM_CONFIGURE, buf, 15, 84); +#else + mavlink_digicam_configure_t packet; + packet.extra_value = extra_value; + packet.shutter_speed = shutter_speed; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mode = mode; + packet.aperture = aperture; + packet.iso = iso; + packet.exposure_type = exposure_type; + packet.command_id = command_id; + packet.engine_cut_off = engine_cut_off; + packet.extra_param = extra_param; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DIGICAM_CONFIGURE, (const char *)&packet, 15, 84); +#endif +} + +#endif + +// MESSAGE DIGICAM_CONFIGURE UNPACKING + + +/** + * @brief Get field target_system from digicam_configure message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_digicam_configure_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Get field target_component from digicam_configure message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_digicam_configure_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 7); +} + +/** + * @brief Get field mode from digicam_configure message + * + * @return Mode enumeration from 1 to N //P, TV, AV, M, Etc (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_configure_get_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Get field shutter_speed from digicam_configure message + * + * @return Divisor number //e.g. 1000 means 1/1000 (0 means ignore) + */ +static inline uint16_t mavlink_msg_digicam_configure_get_shutter_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field aperture from digicam_configure message + * + * @return F stop number x 10 //e.g. 28 means 2.8 (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_configure_get_aperture(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 9); +} + +/** + * @brief Get field iso from digicam_configure message + * + * @return ISO enumeration from 1 to N //e.g. 80, 100, 200, Etc (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_configure_get_iso(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 10); +} + +/** + * @brief Get field exposure_type from digicam_configure message + * + * @return Exposure type enumeration from 1 to N (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_configure_get_exposure_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 11); +} + +/** + * @brief Get field command_id from digicam_configure message + * + * @return Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + */ +static inline uint8_t mavlink_msg_digicam_configure_get_command_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 12); +} + +/** + * @brief Get field engine_cut_off from digicam_configure message + * + * @return Main engine cut-off time before camera trigger in seconds/10 (0 means no cut-off) + */ +static inline uint8_t mavlink_msg_digicam_configure_get_engine_cut_off(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 13); +} + +/** + * @brief Get field extra_param from digicam_configure message + * + * @return Extra parameters enumeration (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_configure_get_extra_param(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 14); +} + +/** + * @brief Get field extra_value from digicam_configure message + * + * @return Correspondent value to given extra_param + */ +static inline float mavlink_msg_digicam_configure_get_extra_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Decode a digicam_configure message into a struct + * + * @param msg The message to decode + * @param digicam_configure C-struct to decode the message contents into + */ +static inline void mavlink_msg_digicam_configure_decode(const mavlink_message_t* msg, mavlink_digicam_configure_t* digicam_configure) +{ +#if MAVLINK_NEED_BYTE_SWAP + digicam_configure->extra_value = mavlink_msg_digicam_configure_get_extra_value(msg); + digicam_configure->shutter_speed = mavlink_msg_digicam_configure_get_shutter_speed(msg); + digicam_configure->target_system = mavlink_msg_digicam_configure_get_target_system(msg); + digicam_configure->target_component = mavlink_msg_digicam_configure_get_target_component(msg); + digicam_configure->mode = mavlink_msg_digicam_configure_get_mode(msg); + digicam_configure->aperture = mavlink_msg_digicam_configure_get_aperture(msg); + digicam_configure->iso = mavlink_msg_digicam_configure_get_iso(msg); + digicam_configure->exposure_type = mavlink_msg_digicam_configure_get_exposure_type(msg); + digicam_configure->command_id = mavlink_msg_digicam_configure_get_command_id(msg); + digicam_configure->engine_cut_off = mavlink_msg_digicam_configure_get_engine_cut_off(msg); + digicam_configure->extra_param = mavlink_msg_digicam_configure_get_extra_param(msg); +#else + memcpy(digicam_configure, _MAV_PAYLOAD(msg), 15); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_digicam_control.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_digicam_control.h new file mode 100644 index 0000000000..a3b4878c43 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_digicam_control.h @@ -0,0 +1,342 @@ +// MESSAGE DIGICAM_CONTROL PACKING + +#define MAVLINK_MSG_ID_DIGICAM_CONTROL 155 + +typedef struct __mavlink_digicam_control_t +{ + float extra_value; ///< Correspondent value to given extra_param + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t session; ///< 0: stop, 1: start or keep it up //Session control e.g. show/hide lens + uint8_t zoom_pos; ///< 1 to N //Zoom's absolute position (0 means ignore) + int8_t zoom_step; ///< -100 to 100 //Zooming step value to offset zoom from the current position + uint8_t focus_lock; ///< 0: unlock focus or keep unlocked, 1: lock focus or keep locked, 3: re-lock focus + uint8_t shot; ///< 0: ignore, 1: shot or start filming + uint8_t command_id; ///< Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + uint8_t extra_param; ///< Extra parameters enumeration (0 means ignore) +} mavlink_digicam_control_t; + +#define MAVLINK_MSG_ID_DIGICAM_CONTROL_LEN 13 +#define MAVLINK_MSG_ID_155_LEN 13 + + + +#define MAVLINK_MESSAGE_INFO_DIGICAM_CONTROL { \ + "DIGICAM_CONTROL", \ + 10, \ + { { "extra_value", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_digicam_control_t, extra_value) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_digicam_control_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_digicam_control_t, target_component) }, \ + { "session", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_digicam_control_t, session) }, \ + { "zoom_pos", NULL, MAVLINK_TYPE_UINT8_T, 0, 7, offsetof(mavlink_digicam_control_t, zoom_pos) }, \ + { "zoom_step", NULL, MAVLINK_TYPE_INT8_T, 0, 8, offsetof(mavlink_digicam_control_t, zoom_step) }, \ + { "focus_lock", NULL, MAVLINK_TYPE_UINT8_T, 0, 9, offsetof(mavlink_digicam_control_t, focus_lock) }, \ + { "shot", NULL, MAVLINK_TYPE_UINT8_T, 0, 10, offsetof(mavlink_digicam_control_t, shot) }, \ + { "command_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 11, offsetof(mavlink_digicam_control_t, command_id) }, \ + { "extra_param", NULL, MAVLINK_TYPE_UINT8_T, 0, 12, offsetof(mavlink_digicam_control_t, extra_param) }, \ + } \ +} + + +/** + * @brief Pack a digicam_control message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param session 0: stop, 1: start or keep it up //Session control e.g. show/hide lens + * @param zoom_pos 1 to N //Zoom's absolute position (0 means ignore) + * @param zoom_step -100 to 100 //Zooming step value to offset zoom from the current position + * @param focus_lock 0: unlock focus or keep unlocked, 1: lock focus or keep locked, 3: re-lock focus + * @param shot 0: ignore, 1: shot or start filming + * @param command_id Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + * @param extra_param Extra parameters enumeration (0 means ignore) + * @param extra_value Correspondent value to given extra_param + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_digicam_control_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t session, uint8_t zoom_pos, int8_t zoom_step, uint8_t focus_lock, uint8_t shot, uint8_t command_id, uint8_t extra_param, float extra_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_float(buf, 0, extra_value); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + _mav_put_uint8_t(buf, 6, session); + _mav_put_uint8_t(buf, 7, zoom_pos); + _mav_put_int8_t(buf, 8, zoom_step); + _mav_put_uint8_t(buf, 9, focus_lock); + _mav_put_uint8_t(buf, 10, shot); + _mav_put_uint8_t(buf, 11, command_id); + _mav_put_uint8_t(buf, 12, extra_param); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 13); +#else + mavlink_digicam_control_t packet; + packet.extra_value = extra_value; + packet.target_system = target_system; + packet.target_component = target_component; + packet.session = session; + packet.zoom_pos = zoom_pos; + packet.zoom_step = zoom_step; + packet.focus_lock = focus_lock; + packet.shot = shot; + packet.command_id = command_id; + packet.extra_param = extra_param; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 13); +#endif + + msg->msgid = MAVLINK_MSG_ID_DIGICAM_CONTROL; + return mavlink_finalize_message(msg, system_id, component_id, 13, 22); +} + +/** + * @brief Pack a digicam_control message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param session 0: stop, 1: start or keep it up //Session control e.g. show/hide lens + * @param zoom_pos 1 to N //Zoom's absolute position (0 means ignore) + * @param zoom_step -100 to 100 //Zooming step value to offset zoom from the current position + * @param focus_lock 0: unlock focus or keep unlocked, 1: lock focus or keep locked, 3: re-lock focus + * @param shot 0: ignore, 1: shot or start filming + * @param command_id Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + * @param extra_param Extra parameters enumeration (0 means ignore) + * @param extra_value Correspondent value to given extra_param + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_digicam_control_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t session,uint8_t zoom_pos,int8_t zoom_step,uint8_t focus_lock,uint8_t shot,uint8_t command_id,uint8_t extra_param,float extra_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_float(buf, 0, extra_value); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + _mav_put_uint8_t(buf, 6, session); + _mav_put_uint8_t(buf, 7, zoom_pos); + _mav_put_int8_t(buf, 8, zoom_step); + _mav_put_uint8_t(buf, 9, focus_lock); + _mav_put_uint8_t(buf, 10, shot); + _mav_put_uint8_t(buf, 11, command_id); + _mav_put_uint8_t(buf, 12, extra_param); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 13); +#else + mavlink_digicam_control_t packet; + packet.extra_value = extra_value; + packet.target_system = target_system; + packet.target_component = target_component; + packet.session = session; + packet.zoom_pos = zoom_pos; + packet.zoom_step = zoom_step; + packet.focus_lock = focus_lock; + packet.shot = shot; + packet.command_id = command_id; + packet.extra_param = extra_param; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 13); +#endif + + msg->msgid = MAVLINK_MSG_ID_DIGICAM_CONTROL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 13, 22); +} + +/** + * @brief Encode a digicam_control struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param digicam_control C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_digicam_control_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_digicam_control_t* digicam_control) +{ + return mavlink_msg_digicam_control_pack(system_id, component_id, msg, digicam_control->target_system, digicam_control->target_component, digicam_control->session, digicam_control->zoom_pos, digicam_control->zoom_step, digicam_control->focus_lock, digicam_control->shot, digicam_control->command_id, digicam_control->extra_param, digicam_control->extra_value); +} + +/** + * @brief Send a digicam_control message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param session 0: stop, 1: start or keep it up //Session control e.g. show/hide lens + * @param zoom_pos 1 to N //Zoom's absolute position (0 means ignore) + * @param zoom_step -100 to 100 //Zooming step value to offset zoom from the current position + * @param focus_lock 0: unlock focus or keep unlocked, 1: lock focus or keep locked, 3: re-lock focus + * @param shot 0: ignore, 1: shot or start filming + * @param command_id Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + * @param extra_param Extra parameters enumeration (0 means ignore) + * @param extra_value Correspondent value to given extra_param + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_digicam_control_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t session, uint8_t zoom_pos, int8_t zoom_step, uint8_t focus_lock, uint8_t shot, uint8_t command_id, uint8_t extra_param, float extra_value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_float(buf, 0, extra_value); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + _mav_put_uint8_t(buf, 6, session); + _mav_put_uint8_t(buf, 7, zoom_pos); + _mav_put_int8_t(buf, 8, zoom_step); + _mav_put_uint8_t(buf, 9, focus_lock); + _mav_put_uint8_t(buf, 10, shot); + _mav_put_uint8_t(buf, 11, command_id); + _mav_put_uint8_t(buf, 12, extra_param); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DIGICAM_CONTROL, buf, 13, 22); +#else + mavlink_digicam_control_t packet; + packet.extra_value = extra_value; + packet.target_system = target_system; + packet.target_component = target_component; + packet.session = session; + packet.zoom_pos = zoom_pos; + packet.zoom_step = zoom_step; + packet.focus_lock = focus_lock; + packet.shot = shot; + packet.command_id = command_id; + packet.extra_param = extra_param; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DIGICAM_CONTROL, (const char *)&packet, 13, 22); +#endif +} + +#endif + +// MESSAGE DIGICAM_CONTROL UNPACKING + + +/** + * @brief Get field target_system from digicam_control message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_digicam_control_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field target_component from digicam_control message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_digicam_control_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field session from digicam_control message + * + * @return 0: stop, 1: start or keep it up //Session control e.g. show/hide lens + */ +static inline uint8_t mavlink_msg_digicam_control_get_session(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Get field zoom_pos from digicam_control message + * + * @return 1 to N //Zoom's absolute position (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_control_get_zoom_pos(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 7); +} + +/** + * @brief Get field zoom_step from digicam_control message + * + * @return -100 to 100 //Zooming step value to offset zoom from the current position + */ +static inline int8_t mavlink_msg_digicam_control_get_zoom_step(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int8_t(msg, 8); +} + +/** + * @brief Get field focus_lock from digicam_control message + * + * @return 0: unlock focus or keep unlocked, 1: lock focus or keep locked, 3: re-lock focus + */ +static inline uint8_t mavlink_msg_digicam_control_get_focus_lock(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 9); +} + +/** + * @brief Get field shot from digicam_control message + * + * @return 0: ignore, 1: shot or start filming + */ +static inline uint8_t mavlink_msg_digicam_control_get_shot(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 10); +} + +/** + * @brief Get field command_id from digicam_control message + * + * @return Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once + */ +static inline uint8_t mavlink_msg_digicam_control_get_command_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 11); +} + +/** + * @brief Get field extra_param from digicam_control message + * + * @return Extra parameters enumeration (0 means ignore) + */ +static inline uint8_t mavlink_msg_digicam_control_get_extra_param(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 12); +} + +/** + * @brief Get field extra_value from digicam_control message + * + * @return Correspondent value to given extra_param + */ +static inline float mavlink_msg_digicam_control_get_extra_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Decode a digicam_control message into a struct + * + * @param msg The message to decode + * @param digicam_control C-struct to decode the message contents into + */ +static inline void mavlink_msg_digicam_control_decode(const mavlink_message_t* msg, mavlink_digicam_control_t* digicam_control) +{ +#if MAVLINK_NEED_BYTE_SWAP + digicam_control->extra_value = mavlink_msg_digicam_control_get_extra_value(msg); + digicam_control->target_system = mavlink_msg_digicam_control_get_target_system(msg); + digicam_control->target_component = mavlink_msg_digicam_control_get_target_component(msg); + digicam_control->session = mavlink_msg_digicam_control_get_session(msg); + digicam_control->zoom_pos = mavlink_msg_digicam_control_get_zoom_pos(msg); + digicam_control->zoom_step = mavlink_msg_digicam_control_get_zoom_step(msg); + digicam_control->focus_lock = mavlink_msg_digicam_control_get_focus_lock(msg); + digicam_control->shot = mavlink_msg_digicam_control_get_shot(msg); + digicam_control->command_id = mavlink_msg_digicam_control_get_command_id(msg); + digicam_control->extra_param = mavlink_msg_digicam_control_get_extra_param(msg); +#else + memcpy(digicam_control, _MAV_PAYLOAD(msg), 13); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_fence_fetch_point.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_fence_fetch_point.h new file mode 100644 index 0000000000..c1e405b0a5 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_fence_fetch_point.h @@ -0,0 +1,188 @@ +// MESSAGE FENCE_FETCH_POINT PACKING + +#define MAVLINK_MSG_ID_FENCE_FETCH_POINT 161 + +typedef struct __mavlink_fence_fetch_point_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t idx; ///< point index (first point is 1, 0 is for return point) +} mavlink_fence_fetch_point_t; + +#define MAVLINK_MSG_ID_FENCE_FETCH_POINT_LEN 3 +#define MAVLINK_MSG_ID_161_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_FENCE_FETCH_POINT { \ + "FENCE_FETCH_POINT", \ + 3, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_fence_fetch_point_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_fence_fetch_point_t, target_component) }, \ + { "idx", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_fence_fetch_point_t, idx) }, \ + } \ +} + + +/** + * @brief Pack a fence_fetch_point message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param idx point index (first point is 1, 0 is for return point) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_fence_fetch_point_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t idx) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, idx); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_fence_fetch_point_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.idx = idx; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_FENCE_FETCH_POINT; + return mavlink_finalize_message(msg, system_id, component_id, 3, 68); +} + +/** + * @brief Pack a fence_fetch_point message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param idx point index (first point is 1, 0 is for return point) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_fence_fetch_point_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t idx) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, idx); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_fence_fetch_point_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.idx = idx; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_FENCE_FETCH_POINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3, 68); +} + +/** + * @brief Encode a fence_fetch_point struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param fence_fetch_point C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_fence_fetch_point_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_fence_fetch_point_t* fence_fetch_point) +{ + return mavlink_msg_fence_fetch_point_pack(system_id, component_id, msg, fence_fetch_point->target_system, fence_fetch_point->target_component, fence_fetch_point->idx); +} + +/** + * @brief Send a fence_fetch_point message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param idx point index (first point is 1, 0 is for return point) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_fence_fetch_point_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t idx) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, idx); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FENCE_FETCH_POINT, buf, 3, 68); +#else + mavlink_fence_fetch_point_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.idx = idx; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FENCE_FETCH_POINT, (const char *)&packet, 3, 68); +#endif +} + +#endif + +// MESSAGE FENCE_FETCH_POINT UNPACKING + + +/** + * @brief Get field target_system from fence_fetch_point message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_fence_fetch_point_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from fence_fetch_point message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_fence_fetch_point_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field idx from fence_fetch_point message + * + * @return point index (first point is 1, 0 is for return point) + */ +static inline uint8_t mavlink_msg_fence_fetch_point_get_idx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a fence_fetch_point message into a struct + * + * @param msg The message to decode + * @param fence_fetch_point C-struct to decode the message contents into + */ +static inline void mavlink_msg_fence_fetch_point_decode(const mavlink_message_t* msg, mavlink_fence_fetch_point_t* fence_fetch_point) +{ +#if MAVLINK_NEED_BYTE_SWAP + fence_fetch_point->target_system = mavlink_msg_fence_fetch_point_get_target_system(msg); + fence_fetch_point->target_component = mavlink_msg_fence_fetch_point_get_target_component(msg); + fence_fetch_point->idx = mavlink_msg_fence_fetch_point_get_idx(msg); +#else + memcpy(fence_fetch_point, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_fence_point.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_fence_point.h new file mode 100644 index 0000000000..b31319c749 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_fence_point.h @@ -0,0 +1,254 @@ +// MESSAGE FENCE_POINT PACKING + +#define MAVLINK_MSG_ID_FENCE_POINT 160 + +typedef struct __mavlink_fence_point_t +{ + float lat; ///< Latitude of point + float lng; ///< Longitude of point + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t idx; ///< point index (first point is 1, 0 is for return point) + uint8_t count; ///< total number of points (for sanity checking) +} mavlink_fence_point_t; + +#define MAVLINK_MSG_ID_FENCE_POINT_LEN 12 +#define MAVLINK_MSG_ID_160_LEN 12 + + + +#define MAVLINK_MESSAGE_INFO_FENCE_POINT { \ + "FENCE_POINT", \ + 6, \ + { { "lat", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_fence_point_t, lat) }, \ + { "lng", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_fence_point_t, lng) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_fence_point_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 9, offsetof(mavlink_fence_point_t, target_component) }, \ + { "idx", NULL, MAVLINK_TYPE_UINT8_T, 0, 10, offsetof(mavlink_fence_point_t, idx) }, \ + { "count", NULL, MAVLINK_TYPE_UINT8_T, 0, 11, offsetof(mavlink_fence_point_t, count) }, \ + } \ +} + + +/** + * @brief Pack a fence_point message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param idx point index (first point is 1, 0 is for return point) + * @param count total number of points (for sanity checking) + * @param lat Latitude of point + * @param lng Longitude of point + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_fence_point_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t idx, uint8_t count, float lat, float lng) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_float(buf, 0, lat); + _mav_put_float(buf, 4, lng); + _mav_put_uint8_t(buf, 8, target_system); + _mav_put_uint8_t(buf, 9, target_component); + _mav_put_uint8_t(buf, 10, idx); + _mav_put_uint8_t(buf, 11, count); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_fence_point_t packet; + packet.lat = lat; + packet.lng = lng; + packet.target_system = target_system; + packet.target_component = target_component; + packet.idx = idx; + packet.count = count; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_FENCE_POINT; + return mavlink_finalize_message(msg, system_id, component_id, 12, 78); +} + +/** + * @brief Pack a fence_point message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param idx point index (first point is 1, 0 is for return point) + * @param count total number of points (for sanity checking) + * @param lat Latitude of point + * @param lng Longitude of point + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_fence_point_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t idx,uint8_t count,float lat,float lng) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_float(buf, 0, lat); + _mav_put_float(buf, 4, lng); + _mav_put_uint8_t(buf, 8, target_system); + _mav_put_uint8_t(buf, 9, target_component); + _mav_put_uint8_t(buf, 10, idx); + _mav_put_uint8_t(buf, 11, count); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_fence_point_t packet; + packet.lat = lat; + packet.lng = lng; + packet.target_system = target_system; + packet.target_component = target_component; + packet.idx = idx; + packet.count = count; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_FENCE_POINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12, 78); +} + +/** + * @brief Encode a fence_point struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param fence_point C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_fence_point_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_fence_point_t* fence_point) +{ + return mavlink_msg_fence_point_pack(system_id, component_id, msg, fence_point->target_system, fence_point->target_component, fence_point->idx, fence_point->count, fence_point->lat, fence_point->lng); +} + +/** + * @brief Send a fence_point message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param idx point index (first point is 1, 0 is for return point) + * @param count total number of points (for sanity checking) + * @param lat Latitude of point + * @param lng Longitude of point + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_fence_point_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t idx, uint8_t count, float lat, float lng) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_float(buf, 0, lat); + _mav_put_float(buf, 4, lng); + _mav_put_uint8_t(buf, 8, target_system); + _mav_put_uint8_t(buf, 9, target_component); + _mav_put_uint8_t(buf, 10, idx); + _mav_put_uint8_t(buf, 11, count); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FENCE_POINT, buf, 12, 78); +#else + mavlink_fence_point_t packet; + packet.lat = lat; + packet.lng = lng; + packet.target_system = target_system; + packet.target_component = target_component; + packet.idx = idx; + packet.count = count; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FENCE_POINT, (const char *)&packet, 12, 78); +#endif +} + +#endif + +// MESSAGE FENCE_POINT UNPACKING + + +/** + * @brief Get field target_system from fence_point message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_fence_point_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Get field target_component from fence_point message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_fence_point_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 9); +} + +/** + * @brief Get field idx from fence_point message + * + * @return point index (first point is 1, 0 is for return point) + */ +static inline uint8_t mavlink_msg_fence_point_get_idx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 10); +} + +/** + * @brief Get field count from fence_point message + * + * @return total number of points (for sanity checking) + */ +static inline uint8_t mavlink_msg_fence_point_get_count(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 11); +} + +/** + * @brief Get field lat from fence_point message + * + * @return Latitude of point + */ +static inline float mavlink_msg_fence_point_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field lng from fence_point message + * + * @return Longitude of point + */ +static inline float mavlink_msg_fence_point_get_lng(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Decode a fence_point message into a struct + * + * @param msg The message to decode + * @param fence_point C-struct to decode the message contents into + */ +static inline void mavlink_msg_fence_point_decode(const mavlink_message_t* msg, mavlink_fence_point_t* fence_point) +{ +#if MAVLINK_NEED_BYTE_SWAP + fence_point->lat = mavlink_msg_fence_point_get_lat(msg); + fence_point->lng = mavlink_msg_fence_point_get_lng(msg); + fence_point->target_system = mavlink_msg_fence_point_get_target_system(msg); + fence_point->target_component = mavlink_msg_fence_point_get_target_component(msg); + fence_point->idx = mavlink_msg_fence_point_get_idx(msg); + fence_point->count = mavlink_msg_fence_point_get_count(msg); +#else + memcpy(fence_point, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_fence_status.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_fence_status.h new file mode 100644 index 0000000000..ce3e7ee67b --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_fence_status.h @@ -0,0 +1,210 @@ +// MESSAGE FENCE_STATUS PACKING + +#define MAVLINK_MSG_ID_FENCE_STATUS 162 + +typedef struct __mavlink_fence_status_t +{ + uint32_t breach_time; ///< time of last breach in milliseconds since boot + uint16_t breach_count; ///< number of fence breaches + uint8_t breach_status; ///< 0 if currently inside fence, 1 if outside + uint8_t breach_type; ///< last breach type (see FENCE_BREACH_* enum) +} mavlink_fence_status_t; + +#define MAVLINK_MSG_ID_FENCE_STATUS_LEN 8 +#define MAVLINK_MSG_ID_162_LEN 8 + + + +#define MAVLINK_MESSAGE_INFO_FENCE_STATUS { \ + "FENCE_STATUS", \ + 4, \ + { { "breach_time", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_fence_status_t, breach_time) }, \ + { "breach_count", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_fence_status_t, breach_count) }, \ + { "breach_status", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_fence_status_t, breach_status) }, \ + { "breach_type", NULL, MAVLINK_TYPE_UINT8_T, 0, 7, offsetof(mavlink_fence_status_t, breach_type) }, \ + } \ +} + + +/** + * @brief Pack a fence_status message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param breach_status 0 if currently inside fence, 1 if outside + * @param breach_count number of fence breaches + * @param breach_type last breach type (see FENCE_BREACH_* enum) + * @param breach_time time of last breach in milliseconds since boot + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_fence_status_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t breach_status, uint16_t breach_count, uint8_t breach_type, uint32_t breach_time) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint32_t(buf, 0, breach_time); + _mav_put_uint16_t(buf, 4, breach_count); + _mav_put_uint8_t(buf, 6, breach_status); + _mav_put_uint8_t(buf, 7, breach_type); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_fence_status_t packet; + packet.breach_time = breach_time; + packet.breach_count = breach_count; + packet.breach_status = breach_status; + packet.breach_type = breach_type; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_FENCE_STATUS; + return mavlink_finalize_message(msg, system_id, component_id, 8, 189); +} + +/** + * @brief Pack a fence_status message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param breach_status 0 if currently inside fence, 1 if outside + * @param breach_count number of fence breaches + * @param breach_type last breach type (see FENCE_BREACH_* enum) + * @param breach_time time of last breach in milliseconds since boot + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_fence_status_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t breach_status,uint16_t breach_count,uint8_t breach_type,uint32_t breach_time) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint32_t(buf, 0, breach_time); + _mav_put_uint16_t(buf, 4, breach_count); + _mav_put_uint8_t(buf, 6, breach_status); + _mav_put_uint8_t(buf, 7, breach_type); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_fence_status_t packet; + packet.breach_time = breach_time; + packet.breach_count = breach_count; + packet.breach_status = breach_status; + packet.breach_type = breach_type; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_FENCE_STATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 8, 189); +} + +/** + * @brief Encode a fence_status struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param fence_status C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_fence_status_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_fence_status_t* fence_status) +{ + return mavlink_msg_fence_status_pack(system_id, component_id, msg, fence_status->breach_status, fence_status->breach_count, fence_status->breach_type, fence_status->breach_time); +} + +/** + * @brief Send a fence_status message + * @param chan MAVLink channel to send the message + * + * @param breach_status 0 if currently inside fence, 1 if outside + * @param breach_count number of fence breaches + * @param breach_type last breach type (see FENCE_BREACH_* enum) + * @param breach_time time of last breach in milliseconds since boot + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_fence_status_send(mavlink_channel_t chan, uint8_t breach_status, uint16_t breach_count, uint8_t breach_type, uint32_t breach_time) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_uint32_t(buf, 0, breach_time); + _mav_put_uint16_t(buf, 4, breach_count); + _mav_put_uint8_t(buf, 6, breach_status); + _mav_put_uint8_t(buf, 7, breach_type); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FENCE_STATUS, buf, 8, 189); +#else + mavlink_fence_status_t packet; + packet.breach_time = breach_time; + packet.breach_count = breach_count; + packet.breach_status = breach_status; + packet.breach_type = breach_type; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FENCE_STATUS, (const char *)&packet, 8, 189); +#endif +} + +#endif + +// MESSAGE FENCE_STATUS UNPACKING + + +/** + * @brief Get field breach_status from fence_status message + * + * @return 0 if currently inside fence, 1 if outside + */ +static inline uint8_t mavlink_msg_fence_status_get_breach_status(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Get field breach_count from fence_status message + * + * @return number of fence breaches + */ +static inline uint16_t mavlink_msg_fence_status_get_breach_count(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field breach_type from fence_status message + * + * @return last breach type (see FENCE_BREACH_* enum) + */ +static inline uint8_t mavlink_msg_fence_status_get_breach_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 7); +} + +/** + * @brief Get field breach_time from fence_status message + * + * @return time of last breach in milliseconds since boot + */ +static inline uint32_t mavlink_msg_fence_status_get_breach_time(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Decode a fence_status message into a struct + * + * @param msg The message to decode + * @param fence_status C-struct to decode the message contents into + */ +static inline void mavlink_msg_fence_status_decode(const mavlink_message_t* msg, mavlink_fence_status_t* fence_status) +{ +#if MAVLINK_NEED_BYTE_SWAP + fence_status->breach_time = mavlink_msg_fence_status_get_breach_time(msg); + fence_status->breach_count = mavlink_msg_fence_status_get_breach_count(msg); + fence_status->breach_status = mavlink_msg_fence_status_get_breach_status(msg); + fence_status->breach_type = mavlink_msg_fence_status_get_breach_type(msg); +#else + memcpy(fence_status, _MAV_PAYLOAD(msg), 8); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_hwstatus.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_hwstatus.h new file mode 100644 index 0000000000..952e65951b --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_hwstatus.h @@ -0,0 +1,166 @@ +// MESSAGE HWSTATUS PACKING + +#define MAVLINK_MSG_ID_HWSTATUS 165 + +typedef struct __mavlink_hwstatus_t +{ + uint16_t Vcc; ///< board voltage (mV) + uint8_t I2Cerr; ///< I2C error count +} mavlink_hwstatus_t; + +#define MAVLINK_MSG_ID_HWSTATUS_LEN 3 +#define MAVLINK_MSG_ID_165_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_HWSTATUS { \ + "HWSTATUS", \ + 2, \ + { { "Vcc", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_hwstatus_t, Vcc) }, \ + { "I2Cerr", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_hwstatus_t, I2Cerr) }, \ + } \ +} + + +/** + * @brief Pack a hwstatus message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param Vcc board voltage (mV) + * @param I2Cerr I2C error count + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hwstatus_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t Vcc, uint8_t I2Cerr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, Vcc); + _mav_put_uint8_t(buf, 2, I2Cerr); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_hwstatus_t packet; + packet.Vcc = Vcc; + packet.I2Cerr = I2Cerr; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_HWSTATUS; + return mavlink_finalize_message(msg, system_id, component_id, 3, 21); +} + +/** + * @brief Pack a hwstatus message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param Vcc board voltage (mV) + * @param I2Cerr I2C error count + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hwstatus_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t Vcc,uint8_t I2Cerr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, Vcc); + _mav_put_uint8_t(buf, 2, I2Cerr); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_hwstatus_t packet; + packet.Vcc = Vcc; + packet.I2Cerr = I2Cerr; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_HWSTATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3, 21); +} + +/** + * @brief Encode a hwstatus struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param hwstatus C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_hwstatus_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_hwstatus_t* hwstatus) +{ + return mavlink_msg_hwstatus_pack(system_id, component_id, msg, hwstatus->Vcc, hwstatus->I2Cerr); +} + +/** + * @brief Send a hwstatus message + * @param chan MAVLink channel to send the message + * + * @param Vcc board voltage (mV) + * @param I2Cerr I2C error count + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_hwstatus_send(mavlink_channel_t chan, uint16_t Vcc, uint8_t I2Cerr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, Vcc); + _mav_put_uint8_t(buf, 2, I2Cerr); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HWSTATUS, buf, 3, 21); +#else + mavlink_hwstatus_t packet; + packet.Vcc = Vcc; + packet.I2Cerr = I2Cerr; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HWSTATUS, (const char *)&packet, 3, 21); +#endif +} + +#endif + +// MESSAGE HWSTATUS UNPACKING + + +/** + * @brief Get field Vcc from hwstatus message + * + * @return board voltage (mV) + */ +static inline uint16_t mavlink_msg_hwstatus_get_Vcc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field I2Cerr from hwstatus message + * + * @return I2C error count + */ +static inline uint8_t mavlink_msg_hwstatus_get_I2Cerr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a hwstatus message into a struct + * + * @param msg The message to decode + * @param hwstatus C-struct to decode the message contents into + */ +static inline void mavlink_msg_hwstatus_decode(const mavlink_message_t* msg, mavlink_hwstatus_t* hwstatus) +{ +#if MAVLINK_NEED_BYTE_SWAP + hwstatus->Vcc = mavlink_msg_hwstatus_get_Vcc(msg); + hwstatus->I2Cerr = mavlink_msg_hwstatus_get_I2Cerr(msg); +#else + memcpy(hwstatus, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_meminfo.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_meminfo.h new file mode 100644 index 0000000000..a095a804f3 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_meminfo.h @@ -0,0 +1,166 @@ +// MESSAGE MEMINFO PACKING + +#define MAVLINK_MSG_ID_MEMINFO 152 + +typedef struct __mavlink_meminfo_t +{ + uint16_t brkval; ///< heap top + uint16_t freemem; ///< free memory +} mavlink_meminfo_t; + +#define MAVLINK_MSG_ID_MEMINFO_LEN 4 +#define MAVLINK_MSG_ID_152_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_MEMINFO { \ + "MEMINFO", \ + 2, \ + { { "brkval", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_meminfo_t, brkval) }, \ + { "freemem", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_meminfo_t, freemem) }, \ + } \ +} + + +/** + * @brief Pack a meminfo message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param brkval heap top + * @param freemem free memory + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_meminfo_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t brkval, uint16_t freemem) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, brkval); + _mav_put_uint16_t(buf, 2, freemem); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_meminfo_t packet; + packet.brkval = brkval; + packet.freemem = freemem; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_MEMINFO; + return mavlink_finalize_message(msg, system_id, component_id, 4, 208); +} + +/** + * @brief Pack a meminfo message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param brkval heap top + * @param freemem free memory + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_meminfo_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t brkval,uint16_t freemem) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, brkval); + _mav_put_uint16_t(buf, 2, freemem); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_meminfo_t packet; + packet.brkval = brkval; + packet.freemem = freemem; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_MEMINFO; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4, 208); +} + +/** + * @brief Encode a meminfo struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param meminfo C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_meminfo_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_meminfo_t* meminfo) +{ + return mavlink_msg_meminfo_pack(system_id, component_id, msg, meminfo->brkval, meminfo->freemem); +} + +/** + * @brief Send a meminfo message + * @param chan MAVLink channel to send the message + * + * @param brkval heap top + * @param freemem free memory + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_meminfo_send(mavlink_channel_t chan, uint16_t brkval, uint16_t freemem) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, brkval); + _mav_put_uint16_t(buf, 2, freemem); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MEMINFO, buf, 4, 208); +#else + mavlink_meminfo_t packet; + packet.brkval = brkval; + packet.freemem = freemem; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MEMINFO, (const char *)&packet, 4, 208); +#endif +} + +#endif + +// MESSAGE MEMINFO UNPACKING + + +/** + * @brief Get field brkval from meminfo message + * + * @return heap top + */ +static inline uint16_t mavlink_msg_meminfo_get_brkval(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field freemem from meminfo message + * + * @return free memory + */ +static inline uint16_t mavlink_msg_meminfo_get_freemem(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Decode a meminfo message into a struct + * + * @param msg The message to decode + * @param meminfo C-struct to decode the message contents into + */ +static inline void mavlink_msg_meminfo_decode(const mavlink_message_t* msg, mavlink_meminfo_t* meminfo) +{ +#if MAVLINK_NEED_BYTE_SWAP + meminfo->brkval = mavlink_msg_meminfo_get_brkval(msg); + meminfo->freemem = mavlink_msg_meminfo_get_freemem(msg); +#else + memcpy(meminfo, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_mount_configure.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_mount_configure.h new file mode 100644 index 0000000000..051a718379 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_mount_configure.h @@ -0,0 +1,254 @@ +// MESSAGE MOUNT_CONFIGURE PACKING + +#define MAVLINK_MSG_ID_MOUNT_CONFIGURE 156 + +typedef struct __mavlink_mount_configure_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t mount_mode; ///< mount operating mode (see MAV_MOUNT_MODE enum) + uint8_t stab_roll; ///< (1 = yes, 0 = no) + uint8_t stab_pitch; ///< (1 = yes, 0 = no) + uint8_t stab_yaw; ///< (1 = yes, 0 = no) +} mavlink_mount_configure_t; + +#define MAVLINK_MSG_ID_MOUNT_CONFIGURE_LEN 6 +#define MAVLINK_MSG_ID_156_LEN 6 + + + +#define MAVLINK_MESSAGE_INFO_MOUNT_CONFIGURE { \ + "MOUNT_CONFIGURE", \ + 6, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_mount_configure_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_mount_configure_t, target_component) }, \ + { "mount_mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_mount_configure_t, mount_mode) }, \ + { "stab_roll", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_mount_configure_t, stab_roll) }, \ + { "stab_pitch", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_mount_configure_t, stab_pitch) }, \ + { "stab_yaw", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_mount_configure_t, stab_yaw) }, \ + } \ +} + + +/** + * @brief Pack a mount_configure message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param mount_mode mount operating mode (see MAV_MOUNT_MODE enum) + * @param stab_roll (1 = yes, 0 = no) + * @param stab_pitch (1 = yes, 0 = no) + * @param stab_yaw (1 = yes, 0 = no) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mount_configure_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t mount_mode, uint8_t stab_roll, uint8_t stab_pitch, uint8_t stab_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, mount_mode); + _mav_put_uint8_t(buf, 3, stab_roll); + _mav_put_uint8_t(buf, 4, stab_pitch); + _mav_put_uint8_t(buf, 5, stab_yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_mount_configure_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mount_mode = mount_mode; + packet.stab_roll = stab_roll; + packet.stab_pitch = stab_pitch; + packet.stab_yaw = stab_yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_MOUNT_CONFIGURE; + return mavlink_finalize_message(msg, system_id, component_id, 6, 19); +} + +/** + * @brief Pack a mount_configure message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param mount_mode mount operating mode (see MAV_MOUNT_MODE enum) + * @param stab_roll (1 = yes, 0 = no) + * @param stab_pitch (1 = yes, 0 = no) + * @param stab_yaw (1 = yes, 0 = no) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mount_configure_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t mount_mode,uint8_t stab_roll,uint8_t stab_pitch,uint8_t stab_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, mount_mode); + _mav_put_uint8_t(buf, 3, stab_roll); + _mav_put_uint8_t(buf, 4, stab_pitch); + _mav_put_uint8_t(buf, 5, stab_yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_mount_configure_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mount_mode = mount_mode; + packet.stab_roll = stab_roll; + packet.stab_pitch = stab_pitch; + packet.stab_yaw = stab_yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_MOUNT_CONFIGURE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 6, 19); +} + +/** + * @brief Encode a mount_configure struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mount_configure C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mount_configure_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mount_configure_t* mount_configure) +{ + return mavlink_msg_mount_configure_pack(system_id, component_id, msg, mount_configure->target_system, mount_configure->target_component, mount_configure->mount_mode, mount_configure->stab_roll, mount_configure->stab_pitch, mount_configure->stab_yaw); +} + +/** + * @brief Send a mount_configure message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param mount_mode mount operating mode (see MAV_MOUNT_MODE enum) + * @param stab_roll (1 = yes, 0 = no) + * @param stab_pitch (1 = yes, 0 = no) + * @param stab_yaw (1 = yes, 0 = no) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mount_configure_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t mount_mode, uint8_t stab_roll, uint8_t stab_pitch, uint8_t stab_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, mount_mode); + _mav_put_uint8_t(buf, 3, stab_roll); + _mav_put_uint8_t(buf, 4, stab_pitch); + _mav_put_uint8_t(buf, 5, stab_yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MOUNT_CONFIGURE, buf, 6, 19); +#else + mavlink_mount_configure_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.mount_mode = mount_mode; + packet.stab_roll = stab_roll; + packet.stab_pitch = stab_pitch; + packet.stab_yaw = stab_yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MOUNT_CONFIGURE, (const char *)&packet, 6, 19); +#endif +} + +#endif + +// MESSAGE MOUNT_CONFIGURE UNPACKING + + +/** + * @brief Get field target_system from mount_configure message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mount_configure_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from mount_configure message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mount_configure_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field mount_mode from mount_configure message + * + * @return mount operating mode (see MAV_MOUNT_MODE enum) + */ +static inline uint8_t mavlink_msg_mount_configure_get_mount_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field stab_roll from mount_configure message + * + * @return (1 = yes, 0 = no) + */ +static inline uint8_t mavlink_msg_mount_configure_get_stab_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field stab_pitch from mount_configure message + * + * @return (1 = yes, 0 = no) + */ +static inline uint8_t mavlink_msg_mount_configure_get_stab_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field stab_yaw from mount_configure message + * + * @return (1 = yes, 0 = no) + */ +static inline uint8_t mavlink_msg_mount_configure_get_stab_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Decode a mount_configure message into a struct + * + * @param msg The message to decode + * @param mount_configure C-struct to decode the message contents into + */ +static inline void mavlink_msg_mount_configure_decode(const mavlink_message_t* msg, mavlink_mount_configure_t* mount_configure) +{ +#if MAVLINK_NEED_BYTE_SWAP + mount_configure->target_system = mavlink_msg_mount_configure_get_target_system(msg); + mount_configure->target_component = mavlink_msg_mount_configure_get_target_component(msg); + mount_configure->mount_mode = mavlink_msg_mount_configure_get_mount_mode(msg); + mount_configure->stab_roll = mavlink_msg_mount_configure_get_stab_roll(msg); + mount_configure->stab_pitch = mavlink_msg_mount_configure_get_stab_pitch(msg); + mount_configure->stab_yaw = mavlink_msg_mount_configure_get_stab_yaw(msg); +#else + memcpy(mount_configure, _MAV_PAYLOAD(msg), 6); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_mount_control.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_mount_control.h new file mode 100644 index 0000000000..a519922997 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_mount_control.h @@ -0,0 +1,254 @@ +// MESSAGE MOUNT_CONTROL PACKING + +#define MAVLINK_MSG_ID_MOUNT_CONTROL 157 + +typedef struct __mavlink_mount_control_t +{ + int32_t input_a; ///< pitch(deg*100) or lat, depending on mount mode + int32_t input_b; ///< roll(deg*100) or lon depending on mount mode + int32_t input_c; ///< yaw(deg*100) or alt (in cm) depending on mount mode + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t save_position; ///< if "1" it will save current trimmed position on EEPROM (just valid for NEUTRAL and LANDING) +} mavlink_mount_control_t; + +#define MAVLINK_MSG_ID_MOUNT_CONTROL_LEN 15 +#define MAVLINK_MSG_ID_157_LEN 15 + + + +#define MAVLINK_MESSAGE_INFO_MOUNT_CONTROL { \ + "MOUNT_CONTROL", \ + 6, \ + { { "input_a", NULL, MAVLINK_TYPE_INT32_T, 0, 0, offsetof(mavlink_mount_control_t, input_a) }, \ + { "input_b", NULL, MAVLINK_TYPE_INT32_T, 0, 4, offsetof(mavlink_mount_control_t, input_b) }, \ + { "input_c", NULL, MAVLINK_TYPE_INT32_T, 0, 8, offsetof(mavlink_mount_control_t, input_c) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 12, offsetof(mavlink_mount_control_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 13, offsetof(mavlink_mount_control_t, target_component) }, \ + { "save_position", NULL, MAVLINK_TYPE_UINT8_T, 0, 14, offsetof(mavlink_mount_control_t, save_position) }, \ + } \ +} + + +/** + * @brief Pack a mount_control message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param input_a pitch(deg*100) or lat, depending on mount mode + * @param input_b roll(deg*100) or lon depending on mount mode + * @param input_c yaw(deg*100) or alt (in cm) depending on mount mode + * @param save_position if "1" it will save current trimmed position on EEPROM (just valid for NEUTRAL and LANDING) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mount_control_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, int32_t input_a, int32_t input_b, int32_t input_c, uint8_t save_position) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_int32_t(buf, 0, input_a); + _mav_put_int32_t(buf, 4, input_b); + _mav_put_int32_t(buf, 8, input_c); + _mav_put_uint8_t(buf, 12, target_system); + _mav_put_uint8_t(buf, 13, target_component); + _mav_put_uint8_t(buf, 14, save_position); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 15); +#else + mavlink_mount_control_t packet; + packet.input_a = input_a; + packet.input_b = input_b; + packet.input_c = input_c; + packet.target_system = target_system; + packet.target_component = target_component; + packet.save_position = save_position; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 15); +#endif + + msg->msgid = MAVLINK_MSG_ID_MOUNT_CONTROL; + return mavlink_finalize_message(msg, system_id, component_id, 15, 21); +} + +/** + * @brief Pack a mount_control message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param input_a pitch(deg*100) or lat, depending on mount mode + * @param input_b roll(deg*100) or lon depending on mount mode + * @param input_c yaw(deg*100) or alt (in cm) depending on mount mode + * @param save_position if "1" it will save current trimmed position on EEPROM (just valid for NEUTRAL and LANDING) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mount_control_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,int32_t input_a,int32_t input_b,int32_t input_c,uint8_t save_position) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_int32_t(buf, 0, input_a); + _mav_put_int32_t(buf, 4, input_b); + _mav_put_int32_t(buf, 8, input_c); + _mav_put_uint8_t(buf, 12, target_system); + _mav_put_uint8_t(buf, 13, target_component); + _mav_put_uint8_t(buf, 14, save_position); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 15); +#else + mavlink_mount_control_t packet; + packet.input_a = input_a; + packet.input_b = input_b; + packet.input_c = input_c; + packet.target_system = target_system; + packet.target_component = target_component; + packet.save_position = save_position; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 15); +#endif + + msg->msgid = MAVLINK_MSG_ID_MOUNT_CONTROL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 15, 21); +} + +/** + * @brief Encode a mount_control struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mount_control C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mount_control_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mount_control_t* mount_control) +{ + return mavlink_msg_mount_control_pack(system_id, component_id, msg, mount_control->target_system, mount_control->target_component, mount_control->input_a, mount_control->input_b, mount_control->input_c, mount_control->save_position); +} + +/** + * @brief Send a mount_control message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param input_a pitch(deg*100) or lat, depending on mount mode + * @param input_b roll(deg*100) or lon depending on mount mode + * @param input_c yaw(deg*100) or alt (in cm) depending on mount mode + * @param save_position if "1" it will save current trimmed position on EEPROM (just valid for NEUTRAL and LANDING) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mount_control_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, int32_t input_a, int32_t input_b, int32_t input_c, uint8_t save_position) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_int32_t(buf, 0, input_a); + _mav_put_int32_t(buf, 4, input_b); + _mav_put_int32_t(buf, 8, input_c); + _mav_put_uint8_t(buf, 12, target_system); + _mav_put_uint8_t(buf, 13, target_component); + _mav_put_uint8_t(buf, 14, save_position); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MOUNT_CONTROL, buf, 15, 21); +#else + mavlink_mount_control_t packet; + packet.input_a = input_a; + packet.input_b = input_b; + packet.input_c = input_c; + packet.target_system = target_system; + packet.target_component = target_component; + packet.save_position = save_position; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MOUNT_CONTROL, (const char *)&packet, 15, 21); +#endif +} + +#endif + +// MESSAGE MOUNT_CONTROL UNPACKING + + +/** + * @brief Get field target_system from mount_control message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mount_control_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 12); +} + +/** + * @brief Get field target_component from mount_control message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mount_control_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 13); +} + +/** + * @brief Get field input_a from mount_control message + * + * @return pitch(deg*100) or lat, depending on mount mode + */ +static inline int32_t mavlink_msg_mount_control_get_input_a(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 0); +} + +/** + * @brief Get field input_b from mount_control message + * + * @return roll(deg*100) or lon depending on mount mode + */ +static inline int32_t mavlink_msg_mount_control_get_input_b(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 4); +} + +/** + * @brief Get field input_c from mount_control message + * + * @return yaw(deg*100) or alt (in cm) depending on mount mode + */ +static inline int32_t mavlink_msg_mount_control_get_input_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 8); +} + +/** + * @brief Get field save_position from mount_control message + * + * @return if "1" it will save current trimmed position on EEPROM (just valid for NEUTRAL and LANDING) + */ +static inline uint8_t mavlink_msg_mount_control_get_save_position(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 14); +} + +/** + * @brief Decode a mount_control message into a struct + * + * @param msg The message to decode + * @param mount_control C-struct to decode the message contents into + */ +static inline void mavlink_msg_mount_control_decode(const mavlink_message_t* msg, mavlink_mount_control_t* mount_control) +{ +#if MAVLINK_NEED_BYTE_SWAP + mount_control->input_a = mavlink_msg_mount_control_get_input_a(msg); + mount_control->input_b = mavlink_msg_mount_control_get_input_b(msg); + mount_control->input_c = mavlink_msg_mount_control_get_input_c(msg); + mount_control->target_system = mavlink_msg_mount_control_get_target_system(msg); + mount_control->target_component = mavlink_msg_mount_control_get_target_component(msg); + mount_control->save_position = mavlink_msg_mount_control_get_save_position(msg); +#else + memcpy(mount_control, _MAV_PAYLOAD(msg), 15); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_mount_status.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_mount_status.h new file mode 100644 index 0000000000..edc188ebd4 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_mount_status.h @@ -0,0 +1,232 @@ +// MESSAGE MOUNT_STATUS PACKING + +#define MAVLINK_MSG_ID_MOUNT_STATUS 158 + +typedef struct __mavlink_mount_status_t +{ + int32_t pointing_a; ///< pitch(deg*100) or lat, depending on mount mode + int32_t pointing_b; ///< roll(deg*100) or lon depending on mount mode + int32_t pointing_c; ///< yaw(deg*100) or alt (in cm) depending on mount mode + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_mount_status_t; + +#define MAVLINK_MSG_ID_MOUNT_STATUS_LEN 14 +#define MAVLINK_MSG_ID_158_LEN 14 + + + +#define MAVLINK_MESSAGE_INFO_MOUNT_STATUS { \ + "MOUNT_STATUS", \ + 5, \ + { { "pointing_a", NULL, MAVLINK_TYPE_INT32_T, 0, 0, offsetof(mavlink_mount_status_t, pointing_a) }, \ + { "pointing_b", NULL, MAVLINK_TYPE_INT32_T, 0, 4, offsetof(mavlink_mount_status_t, pointing_b) }, \ + { "pointing_c", NULL, MAVLINK_TYPE_INT32_T, 0, 8, offsetof(mavlink_mount_status_t, pointing_c) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 12, offsetof(mavlink_mount_status_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 13, offsetof(mavlink_mount_status_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a mount_status message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param pointing_a pitch(deg*100) or lat, depending on mount mode + * @param pointing_b roll(deg*100) or lon depending on mount mode + * @param pointing_c yaw(deg*100) or alt (in cm) depending on mount mode + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mount_status_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, int32_t pointing_a, int32_t pointing_b, int32_t pointing_c) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_int32_t(buf, 0, pointing_a); + _mav_put_int32_t(buf, 4, pointing_b); + _mav_put_int32_t(buf, 8, pointing_c); + _mav_put_uint8_t(buf, 12, target_system); + _mav_put_uint8_t(buf, 13, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_mount_status_t packet; + packet.pointing_a = pointing_a; + packet.pointing_b = pointing_b; + packet.pointing_c = pointing_c; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_MOUNT_STATUS; + return mavlink_finalize_message(msg, system_id, component_id, 14, 134); +} + +/** + * @brief Pack a mount_status message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param pointing_a pitch(deg*100) or lat, depending on mount mode + * @param pointing_b roll(deg*100) or lon depending on mount mode + * @param pointing_c yaw(deg*100) or alt (in cm) depending on mount mode + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mount_status_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,int32_t pointing_a,int32_t pointing_b,int32_t pointing_c) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_int32_t(buf, 0, pointing_a); + _mav_put_int32_t(buf, 4, pointing_b); + _mav_put_int32_t(buf, 8, pointing_c); + _mav_put_uint8_t(buf, 12, target_system); + _mav_put_uint8_t(buf, 13, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_mount_status_t packet; + packet.pointing_a = pointing_a; + packet.pointing_b = pointing_b; + packet.pointing_c = pointing_c; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_MOUNT_STATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 14, 134); +} + +/** + * @brief Encode a mount_status struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mount_status C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mount_status_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mount_status_t* mount_status) +{ + return mavlink_msg_mount_status_pack(system_id, component_id, msg, mount_status->target_system, mount_status->target_component, mount_status->pointing_a, mount_status->pointing_b, mount_status->pointing_c); +} + +/** + * @brief Send a mount_status message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param pointing_a pitch(deg*100) or lat, depending on mount mode + * @param pointing_b roll(deg*100) or lon depending on mount mode + * @param pointing_c yaw(deg*100) or alt (in cm) depending on mount mode + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mount_status_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, int32_t pointing_a, int32_t pointing_b, int32_t pointing_c) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_int32_t(buf, 0, pointing_a); + _mav_put_int32_t(buf, 4, pointing_b); + _mav_put_int32_t(buf, 8, pointing_c); + _mav_put_uint8_t(buf, 12, target_system); + _mav_put_uint8_t(buf, 13, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MOUNT_STATUS, buf, 14, 134); +#else + mavlink_mount_status_t packet; + packet.pointing_a = pointing_a; + packet.pointing_b = pointing_b; + packet.pointing_c = pointing_c; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MOUNT_STATUS, (const char *)&packet, 14, 134); +#endif +} + +#endif + +// MESSAGE MOUNT_STATUS UNPACKING + + +/** + * @brief Get field target_system from mount_status message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mount_status_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 12); +} + +/** + * @brief Get field target_component from mount_status message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mount_status_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 13); +} + +/** + * @brief Get field pointing_a from mount_status message + * + * @return pitch(deg*100) or lat, depending on mount mode + */ +static inline int32_t mavlink_msg_mount_status_get_pointing_a(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 0); +} + +/** + * @brief Get field pointing_b from mount_status message + * + * @return roll(deg*100) or lon depending on mount mode + */ +static inline int32_t mavlink_msg_mount_status_get_pointing_b(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 4); +} + +/** + * @brief Get field pointing_c from mount_status message + * + * @return yaw(deg*100) or alt (in cm) depending on mount mode + */ +static inline int32_t mavlink_msg_mount_status_get_pointing_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 8); +} + +/** + * @brief Decode a mount_status message into a struct + * + * @param msg The message to decode + * @param mount_status C-struct to decode the message contents into + */ +static inline void mavlink_msg_mount_status_decode(const mavlink_message_t* msg, mavlink_mount_status_t* mount_status) +{ +#if MAVLINK_NEED_BYTE_SWAP + mount_status->pointing_a = mavlink_msg_mount_status_get_pointing_a(msg); + mount_status->pointing_b = mavlink_msg_mount_status_get_pointing_b(msg); + mount_status->pointing_c = mavlink_msg_mount_status_get_pointing_c(msg); + mount_status->target_system = mavlink_msg_mount_status_get_target_system(msg); + mount_status->target_component = mavlink_msg_mount_status_get_target_component(msg); +#else + memcpy(mount_status, _MAV_PAYLOAD(msg), 14); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_radio.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_radio.h new file mode 100644 index 0000000000..0f3d03c0a6 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_radio.h @@ -0,0 +1,276 @@ +// MESSAGE RADIO PACKING + +#define MAVLINK_MSG_ID_RADIO 166 + +typedef struct __mavlink_radio_t +{ + uint16_t rxerrors; ///< receive errors + uint16_t fixed; ///< count of error corrected packets + uint8_t rssi; ///< local signal strength + uint8_t remrssi; ///< remote signal strength + uint8_t txbuf; ///< how full the tx buffer is as a percentage + uint8_t noise; ///< background noise level + uint8_t remnoise; ///< remote background noise level +} mavlink_radio_t; + +#define MAVLINK_MSG_ID_RADIO_LEN 9 +#define MAVLINK_MSG_ID_166_LEN 9 + + + +#define MAVLINK_MESSAGE_INFO_RADIO { \ + "RADIO", \ + 7, \ + { { "rxerrors", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_radio_t, rxerrors) }, \ + { "fixed", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_radio_t, fixed) }, \ + { "rssi", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_radio_t, rssi) }, \ + { "remrssi", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_radio_t, remrssi) }, \ + { "txbuf", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_radio_t, txbuf) }, \ + { "noise", NULL, MAVLINK_TYPE_UINT8_T, 0, 7, offsetof(mavlink_radio_t, noise) }, \ + { "remnoise", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_radio_t, remnoise) }, \ + } \ +} + + +/** + * @brief Pack a radio message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param rssi local signal strength + * @param remrssi remote signal strength + * @param txbuf how full the tx buffer is as a percentage + * @param noise background noise level + * @param remnoise remote background noise level + * @param rxerrors receive errors + * @param fixed count of error corrected packets + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_radio_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t rssi, uint8_t remrssi, uint8_t txbuf, uint8_t noise, uint8_t remnoise, uint16_t rxerrors, uint16_t fixed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint16_t(buf, 0, rxerrors); + _mav_put_uint16_t(buf, 2, fixed); + _mav_put_uint8_t(buf, 4, rssi); + _mav_put_uint8_t(buf, 5, remrssi); + _mav_put_uint8_t(buf, 6, txbuf); + _mav_put_uint8_t(buf, 7, noise); + _mav_put_uint8_t(buf, 8, remnoise); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 9); +#else + mavlink_radio_t packet; + packet.rxerrors = rxerrors; + packet.fixed = fixed; + packet.rssi = rssi; + packet.remrssi = remrssi; + packet.txbuf = txbuf; + packet.noise = noise; + packet.remnoise = remnoise; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 9); +#endif + + msg->msgid = MAVLINK_MSG_ID_RADIO; + return mavlink_finalize_message(msg, system_id, component_id, 9, 21); +} + +/** + * @brief Pack a radio message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param rssi local signal strength + * @param remrssi remote signal strength + * @param txbuf how full the tx buffer is as a percentage + * @param noise background noise level + * @param remnoise remote background noise level + * @param rxerrors receive errors + * @param fixed count of error corrected packets + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_radio_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t rssi,uint8_t remrssi,uint8_t txbuf,uint8_t noise,uint8_t remnoise,uint16_t rxerrors,uint16_t fixed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint16_t(buf, 0, rxerrors); + _mav_put_uint16_t(buf, 2, fixed); + _mav_put_uint8_t(buf, 4, rssi); + _mav_put_uint8_t(buf, 5, remrssi); + _mav_put_uint8_t(buf, 6, txbuf); + _mav_put_uint8_t(buf, 7, noise); + _mav_put_uint8_t(buf, 8, remnoise); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 9); +#else + mavlink_radio_t packet; + packet.rxerrors = rxerrors; + packet.fixed = fixed; + packet.rssi = rssi; + packet.remrssi = remrssi; + packet.txbuf = txbuf; + packet.noise = noise; + packet.remnoise = remnoise; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 9); +#endif + + msg->msgid = MAVLINK_MSG_ID_RADIO; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 9, 21); +} + +/** + * @brief Encode a radio struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param radio C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_radio_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_radio_t* radio) +{ + return mavlink_msg_radio_pack(system_id, component_id, msg, radio->rssi, radio->remrssi, radio->txbuf, radio->noise, radio->remnoise, radio->rxerrors, radio->fixed); +} + +/** + * @brief Send a radio message + * @param chan MAVLink channel to send the message + * + * @param rssi local signal strength + * @param remrssi remote signal strength + * @param txbuf how full the tx buffer is as a percentage + * @param noise background noise level + * @param remnoise remote background noise level + * @param rxerrors receive errors + * @param fixed count of error corrected packets + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_radio_send(mavlink_channel_t chan, uint8_t rssi, uint8_t remrssi, uint8_t txbuf, uint8_t noise, uint8_t remnoise, uint16_t rxerrors, uint16_t fixed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint16_t(buf, 0, rxerrors); + _mav_put_uint16_t(buf, 2, fixed); + _mav_put_uint8_t(buf, 4, rssi); + _mav_put_uint8_t(buf, 5, remrssi); + _mav_put_uint8_t(buf, 6, txbuf); + _mav_put_uint8_t(buf, 7, noise); + _mav_put_uint8_t(buf, 8, remnoise); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RADIO, buf, 9, 21); +#else + mavlink_radio_t packet; + packet.rxerrors = rxerrors; + packet.fixed = fixed; + packet.rssi = rssi; + packet.remrssi = remrssi; + packet.txbuf = txbuf; + packet.noise = noise; + packet.remnoise = remnoise; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RADIO, (const char *)&packet, 9, 21); +#endif +} + +#endif + +// MESSAGE RADIO UNPACKING + + +/** + * @brief Get field rssi from radio message + * + * @return local signal strength + */ +static inline uint8_t mavlink_msg_radio_get_rssi(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field remrssi from radio message + * + * @return remote signal strength + */ +static inline uint8_t mavlink_msg_radio_get_remrssi(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field txbuf from radio message + * + * @return how full the tx buffer is as a percentage + */ +static inline uint8_t mavlink_msg_radio_get_txbuf(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Get field noise from radio message + * + * @return background noise level + */ +static inline uint8_t mavlink_msg_radio_get_noise(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 7); +} + +/** + * @brief Get field remnoise from radio message + * + * @return remote background noise level + */ +static inline uint8_t mavlink_msg_radio_get_remnoise(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Get field rxerrors from radio message + * + * @return receive errors + */ +static inline uint16_t mavlink_msg_radio_get_rxerrors(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field fixed from radio message + * + * @return count of error corrected packets + */ +static inline uint16_t mavlink_msg_radio_get_fixed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Decode a radio message into a struct + * + * @param msg The message to decode + * @param radio C-struct to decode the message contents into + */ +static inline void mavlink_msg_radio_decode(const mavlink_message_t* msg, mavlink_radio_t* radio) +{ +#if MAVLINK_NEED_BYTE_SWAP + radio->rxerrors = mavlink_msg_radio_get_rxerrors(msg); + radio->fixed = mavlink_msg_radio_get_fixed(msg); + radio->rssi = mavlink_msg_radio_get_rssi(msg); + radio->remrssi = mavlink_msg_radio_get_remrssi(msg); + radio->txbuf = mavlink_msg_radio_get_txbuf(msg); + radio->noise = mavlink_msg_radio_get_noise(msg); + radio->remnoise = mavlink_msg_radio_get_remnoise(msg); +#else + memcpy(radio, _MAV_PAYLOAD(msg), 9); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_sensor_offsets.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_sensor_offsets.h new file mode 100644 index 0000000000..56fb52d96d --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_sensor_offsets.h @@ -0,0 +1,386 @@ +// MESSAGE SENSOR_OFFSETS PACKING + +#define MAVLINK_MSG_ID_SENSOR_OFFSETS 150 + +typedef struct __mavlink_sensor_offsets_t +{ + float mag_declination; ///< magnetic declination (radians) + int32_t raw_press; ///< raw pressure from barometer + int32_t raw_temp; ///< raw temperature from barometer + float gyro_cal_x; ///< gyro X calibration + float gyro_cal_y; ///< gyro Y calibration + float gyro_cal_z; ///< gyro Z calibration + float accel_cal_x; ///< accel X calibration + float accel_cal_y; ///< accel Y calibration + float accel_cal_z; ///< accel Z calibration + int16_t mag_ofs_x; ///< magnetometer X offset + int16_t mag_ofs_y; ///< magnetometer Y offset + int16_t mag_ofs_z; ///< magnetometer Z offset +} mavlink_sensor_offsets_t; + +#define MAVLINK_MSG_ID_SENSOR_OFFSETS_LEN 42 +#define MAVLINK_MSG_ID_150_LEN 42 + + + +#define MAVLINK_MESSAGE_INFO_SENSOR_OFFSETS { \ + "SENSOR_OFFSETS", \ + 12, \ + { { "mag_declination", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_sensor_offsets_t, mag_declination) }, \ + { "raw_press", NULL, MAVLINK_TYPE_INT32_T, 0, 4, offsetof(mavlink_sensor_offsets_t, raw_press) }, \ + { "raw_temp", NULL, MAVLINK_TYPE_INT32_T, 0, 8, offsetof(mavlink_sensor_offsets_t, raw_temp) }, \ + { "gyro_cal_x", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_sensor_offsets_t, gyro_cal_x) }, \ + { "gyro_cal_y", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_sensor_offsets_t, gyro_cal_y) }, \ + { "gyro_cal_z", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_sensor_offsets_t, gyro_cal_z) }, \ + { "accel_cal_x", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_sensor_offsets_t, accel_cal_x) }, \ + { "accel_cal_y", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_sensor_offsets_t, accel_cal_y) }, \ + { "accel_cal_z", NULL, MAVLINK_TYPE_FLOAT, 0, 32, offsetof(mavlink_sensor_offsets_t, accel_cal_z) }, \ + { "mag_ofs_x", NULL, MAVLINK_TYPE_INT16_T, 0, 36, offsetof(mavlink_sensor_offsets_t, mag_ofs_x) }, \ + { "mag_ofs_y", NULL, MAVLINK_TYPE_INT16_T, 0, 38, offsetof(mavlink_sensor_offsets_t, mag_ofs_y) }, \ + { "mag_ofs_z", NULL, MAVLINK_TYPE_INT16_T, 0, 40, offsetof(mavlink_sensor_offsets_t, mag_ofs_z) }, \ + } \ +} + + +/** + * @brief Pack a sensor_offsets message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param mag_ofs_x magnetometer X offset + * @param mag_ofs_y magnetometer Y offset + * @param mag_ofs_z magnetometer Z offset + * @param mag_declination magnetic declination (radians) + * @param raw_press raw pressure from barometer + * @param raw_temp raw temperature from barometer + * @param gyro_cal_x gyro X calibration + * @param gyro_cal_y gyro Y calibration + * @param gyro_cal_z gyro Z calibration + * @param accel_cal_x accel X calibration + * @param accel_cal_y accel Y calibration + * @param accel_cal_z accel Z calibration + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sensor_offsets_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + int16_t mag_ofs_x, int16_t mag_ofs_y, int16_t mag_ofs_z, float mag_declination, int32_t raw_press, int32_t raw_temp, float gyro_cal_x, float gyro_cal_y, float gyro_cal_z, float accel_cal_x, float accel_cal_y, float accel_cal_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + _mav_put_float(buf, 0, mag_declination); + _mav_put_int32_t(buf, 4, raw_press); + _mav_put_int32_t(buf, 8, raw_temp); + _mav_put_float(buf, 12, gyro_cal_x); + _mav_put_float(buf, 16, gyro_cal_y); + _mav_put_float(buf, 20, gyro_cal_z); + _mav_put_float(buf, 24, accel_cal_x); + _mav_put_float(buf, 28, accel_cal_y); + _mav_put_float(buf, 32, accel_cal_z); + _mav_put_int16_t(buf, 36, mag_ofs_x); + _mav_put_int16_t(buf, 38, mag_ofs_y); + _mav_put_int16_t(buf, 40, mag_ofs_z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 42); +#else + mavlink_sensor_offsets_t packet; + packet.mag_declination = mag_declination; + packet.raw_press = raw_press; + packet.raw_temp = raw_temp; + packet.gyro_cal_x = gyro_cal_x; + packet.gyro_cal_y = gyro_cal_y; + packet.gyro_cal_z = gyro_cal_z; + packet.accel_cal_x = accel_cal_x; + packet.accel_cal_y = accel_cal_y; + packet.accel_cal_z = accel_cal_z; + packet.mag_ofs_x = mag_ofs_x; + packet.mag_ofs_y = mag_ofs_y; + packet.mag_ofs_z = mag_ofs_z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 42); +#endif + + msg->msgid = MAVLINK_MSG_ID_SENSOR_OFFSETS; + return mavlink_finalize_message(msg, system_id, component_id, 42, 134); +} + +/** + * @brief Pack a sensor_offsets message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param mag_ofs_x magnetometer X offset + * @param mag_ofs_y magnetometer Y offset + * @param mag_ofs_z magnetometer Z offset + * @param mag_declination magnetic declination (radians) + * @param raw_press raw pressure from barometer + * @param raw_temp raw temperature from barometer + * @param gyro_cal_x gyro X calibration + * @param gyro_cal_y gyro Y calibration + * @param gyro_cal_z gyro Z calibration + * @param accel_cal_x accel X calibration + * @param accel_cal_y accel Y calibration + * @param accel_cal_z accel Z calibration + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sensor_offsets_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + int16_t mag_ofs_x,int16_t mag_ofs_y,int16_t mag_ofs_z,float mag_declination,int32_t raw_press,int32_t raw_temp,float gyro_cal_x,float gyro_cal_y,float gyro_cal_z,float accel_cal_x,float accel_cal_y,float accel_cal_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + _mav_put_float(buf, 0, mag_declination); + _mav_put_int32_t(buf, 4, raw_press); + _mav_put_int32_t(buf, 8, raw_temp); + _mav_put_float(buf, 12, gyro_cal_x); + _mav_put_float(buf, 16, gyro_cal_y); + _mav_put_float(buf, 20, gyro_cal_z); + _mav_put_float(buf, 24, accel_cal_x); + _mav_put_float(buf, 28, accel_cal_y); + _mav_put_float(buf, 32, accel_cal_z); + _mav_put_int16_t(buf, 36, mag_ofs_x); + _mav_put_int16_t(buf, 38, mag_ofs_y); + _mav_put_int16_t(buf, 40, mag_ofs_z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 42); +#else + mavlink_sensor_offsets_t packet; + packet.mag_declination = mag_declination; + packet.raw_press = raw_press; + packet.raw_temp = raw_temp; + packet.gyro_cal_x = gyro_cal_x; + packet.gyro_cal_y = gyro_cal_y; + packet.gyro_cal_z = gyro_cal_z; + packet.accel_cal_x = accel_cal_x; + packet.accel_cal_y = accel_cal_y; + packet.accel_cal_z = accel_cal_z; + packet.mag_ofs_x = mag_ofs_x; + packet.mag_ofs_y = mag_ofs_y; + packet.mag_ofs_z = mag_ofs_z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 42); +#endif + + msg->msgid = MAVLINK_MSG_ID_SENSOR_OFFSETS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 42, 134); +} + +/** + * @brief Encode a sensor_offsets struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param sensor_offsets C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_sensor_offsets_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_sensor_offsets_t* sensor_offsets) +{ + return mavlink_msg_sensor_offsets_pack(system_id, component_id, msg, sensor_offsets->mag_ofs_x, sensor_offsets->mag_ofs_y, sensor_offsets->mag_ofs_z, sensor_offsets->mag_declination, sensor_offsets->raw_press, sensor_offsets->raw_temp, sensor_offsets->gyro_cal_x, sensor_offsets->gyro_cal_y, sensor_offsets->gyro_cal_z, sensor_offsets->accel_cal_x, sensor_offsets->accel_cal_y, sensor_offsets->accel_cal_z); +} + +/** + * @brief Send a sensor_offsets message + * @param chan MAVLink channel to send the message + * + * @param mag_ofs_x magnetometer X offset + * @param mag_ofs_y magnetometer Y offset + * @param mag_ofs_z magnetometer Z offset + * @param mag_declination magnetic declination (radians) + * @param raw_press raw pressure from barometer + * @param raw_temp raw temperature from barometer + * @param gyro_cal_x gyro X calibration + * @param gyro_cal_y gyro Y calibration + * @param gyro_cal_z gyro Z calibration + * @param accel_cal_x accel X calibration + * @param accel_cal_y accel Y calibration + * @param accel_cal_z accel Z calibration + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_sensor_offsets_send(mavlink_channel_t chan, int16_t mag_ofs_x, int16_t mag_ofs_y, int16_t mag_ofs_z, float mag_declination, int32_t raw_press, int32_t raw_temp, float gyro_cal_x, float gyro_cal_y, float gyro_cal_z, float accel_cal_x, float accel_cal_y, float accel_cal_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + _mav_put_float(buf, 0, mag_declination); + _mav_put_int32_t(buf, 4, raw_press); + _mav_put_int32_t(buf, 8, raw_temp); + _mav_put_float(buf, 12, gyro_cal_x); + _mav_put_float(buf, 16, gyro_cal_y); + _mav_put_float(buf, 20, gyro_cal_z); + _mav_put_float(buf, 24, accel_cal_x); + _mav_put_float(buf, 28, accel_cal_y); + _mav_put_float(buf, 32, accel_cal_z); + _mav_put_int16_t(buf, 36, mag_ofs_x); + _mav_put_int16_t(buf, 38, mag_ofs_y); + _mav_put_int16_t(buf, 40, mag_ofs_z); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SENSOR_OFFSETS, buf, 42, 134); +#else + mavlink_sensor_offsets_t packet; + packet.mag_declination = mag_declination; + packet.raw_press = raw_press; + packet.raw_temp = raw_temp; + packet.gyro_cal_x = gyro_cal_x; + packet.gyro_cal_y = gyro_cal_y; + packet.gyro_cal_z = gyro_cal_z; + packet.accel_cal_x = accel_cal_x; + packet.accel_cal_y = accel_cal_y; + packet.accel_cal_z = accel_cal_z; + packet.mag_ofs_x = mag_ofs_x; + packet.mag_ofs_y = mag_ofs_y; + packet.mag_ofs_z = mag_ofs_z; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SENSOR_OFFSETS, (const char *)&packet, 42, 134); +#endif +} + +#endif + +// MESSAGE SENSOR_OFFSETS UNPACKING + + +/** + * @brief Get field mag_ofs_x from sensor_offsets message + * + * @return magnetometer X offset + */ +static inline int16_t mavlink_msg_sensor_offsets_get_mag_ofs_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 36); +} + +/** + * @brief Get field mag_ofs_y from sensor_offsets message + * + * @return magnetometer Y offset + */ +static inline int16_t mavlink_msg_sensor_offsets_get_mag_ofs_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 38); +} + +/** + * @brief Get field mag_ofs_z from sensor_offsets message + * + * @return magnetometer Z offset + */ +static inline int16_t mavlink_msg_sensor_offsets_get_mag_ofs_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 40); +} + +/** + * @brief Get field mag_declination from sensor_offsets message + * + * @return magnetic declination (radians) + */ +static inline float mavlink_msg_sensor_offsets_get_mag_declination(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field raw_press from sensor_offsets message + * + * @return raw pressure from barometer + */ +static inline int32_t mavlink_msg_sensor_offsets_get_raw_press(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 4); +} + +/** + * @brief Get field raw_temp from sensor_offsets message + * + * @return raw temperature from barometer + */ +static inline int32_t mavlink_msg_sensor_offsets_get_raw_temp(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 8); +} + +/** + * @brief Get field gyro_cal_x from sensor_offsets message + * + * @return gyro X calibration + */ +static inline float mavlink_msg_sensor_offsets_get_gyro_cal_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field gyro_cal_y from sensor_offsets message + * + * @return gyro Y calibration + */ +static inline float mavlink_msg_sensor_offsets_get_gyro_cal_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field gyro_cal_z from sensor_offsets message + * + * @return gyro Z calibration + */ +static inline float mavlink_msg_sensor_offsets_get_gyro_cal_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field accel_cal_x from sensor_offsets message + * + * @return accel X calibration + */ +static inline float mavlink_msg_sensor_offsets_get_accel_cal_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field accel_cal_y from sensor_offsets message + * + * @return accel Y calibration + */ +static inline float mavlink_msg_sensor_offsets_get_accel_cal_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field accel_cal_z from sensor_offsets message + * + * @return accel Z calibration + */ +static inline float mavlink_msg_sensor_offsets_get_accel_cal_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 32); +} + +/** + * @brief Decode a sensor_offsets message into a struct + * + * @param msg The message to decode + * @param sensor_offsets C-struct to decode the message contents into + */ +static inline void mavlink_msg_sensor_offsets_decode(const mavlink_message_t* msg, mavlink_sensor_offsets_t* sensor_offsets) +{ +#if MAVLINK_NEED_BYTE_SWAP + sensor_offsets->mag_declination = mavlink_msg_sensor_offsets_get_mag_declination(msg); + sensor_offsets->raw_press = mavlink_msg_sensor_offsets_get_raw_press(msg); + sensor_offsets->raw_temp = mavlink_msg_sensor_offsets_get_raw_temp(msg); + sensor_offsets->gyro_cal_x = mavlink_msg_sensor_offsets_get_gyro_cal_x(msg); + sensor_offsets->gyro_cal_y = mavlink_msg_sensor_offsets_get_gyro_cal_y(msg); + sensor_offsets->gyro_cal_z = mavlink_msg_sensor_offsets_get_gyro_cal_z(msg); + sensor_offsets->accel_cal_x = mavlink_msg_sensor_offsets_get_accel_cal_x(msg); + sensor_offsets->accel_cal_y = mavlink_msg_sensor_offsets_get_accel_cal_y(msg); + sensor_offsets->accel_cal_z = mavlink_msg_sensor_offsets_get_accel_cal_z(msg); + sensor_offsets->mag_ofs_x = mavlink_msg_sensor_offsets_get_mag_ofs_x(msg); + sensor_offsets->mag_ofs_y = mavlink_msg_sensor_offsets_get_mag_ofs_y(msg); + sensor_offsets->mag_ofs_z = mavlink_msg_sensor_offsets_get_mag_ofs_z(msg); +#else + memcpy(sensor_offsets, _MAV_PAYLOAD(msg), 42); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_set_mag_offsets.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_set_mag_offsets.h new file mode 100644 index 0000000000..4c13fd1863 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_set_mag_offsets.h @@ -0,0 +1,232 @@ +// MESSAGE SET_MAG_OFFSETS PACKING + +#define MAVLINK_MSG_ID_SET_MAG_OFFSETS 151 + +typedef struct __mavlink_set_mag_offsets_t +{ + int16_t mag_ofs_x; ///< magnetometer X offset + int16_t mag_ofs_y; ///< magnetometer Y offset + int16_t mag_ofs_z; ///< magnetometer Z offset + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_set_mag_offsets_t; + +#define MAVLINK_MSG_ID_SET_MAG_OFFSETS_LEN 8 +#define MAVLINK_MSG_ID_151_LEN 8 + + + +#define MAVLINK_MESSAGE_INFO_SET_MAG_OFFSETS { \ + "SET_MAG_OFFSETS", \ + 5, \ + { { "mag_ofs_x", NULL, MAVLINK_TYPE_INT16_T, 0, 0, offsetof(mavlink_set_mag_offsets_t, mag_ofs_x) }, \ + { "mag_ofs_y", NULL, MAVLINK_TYPE_INT16_T, 0, 2, offsetof(mavlink_set_mag_offsets_t, mag_ofs_y) }, \ + { "mag_ofs_z", NULL, MAVLINK_TYPE_INT16_T, 0, 4, offsetof(mavlink_set_mag_offsets_t, mag_ofs_z) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_set_mag_offsets_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 7, offsetof(mavlink_set_mag_offsets_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a set_mag_offsets message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param mag_ofs_x magnetometer X offset + * @param mag_ofs_y magnetometer Y offset + * @param mag_ofs_z magnetometer Z offset + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_mag_offsets_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, int16_t mag_ofs_x, int16_t mag_ofs_y, int16_t mag_ofs_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_int16_t(buf, 0, mag_ofs_x); + _mav_put_int16_t(buf, 2, mag_ofs_y); + _mav_put_int16_t(buf, 4, mag_ofs_z); + _mav_put_uint8_t(buf, 6, target_system); + _mav_put_uint8_t(buf, 7, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_set_mag_offsets_t packet; + packet.mag_ofs_x = mag_ofs_x; + packet.mag_ofs_y = mag_ofs_y; + packet.mag_ofs_z = mag_ofs_z; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_MAG_OFFSETS; + return mavlink_finalize_message(msg, system_id, component_id, 8, 219); +} + +/** + * @brief Pack a set_mag_offsets message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param mag_ofs_x magnetometer X offset + * @param mag_ofs_y magnetometer Y offset + * @param mag_ofs_z magnetometer Z offset + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_mag_offsets_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,int16_t mag_ofs_x,int16_t mag_ofs_y,int16_t mag_ofs_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_int16_t(buf, 0, mag_ofs_x); + _mav_put_int16_t(buf, 2, mag_ofs_y); + _mav_put_int16_t(buf, 4, mag_ofs_z); + _mav_put_uint8_t(buf, 6, target_system); + _mav_put_uint8_t(buf, 7, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 8); +#else + mavlink_set_mag_offsets_t packet; + packet.mag_ofs_x = mag_ofs_x; + packet.mag_ofs_y = mag_ofs_y; + packet.mag_ofs_z = mag_ofs_z; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 8); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_MAG_OFFSETS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 8, 219); +} + +/** + * @brief Encode a set_mag_offsets struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_mag_offsets C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_mag_offsets_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_mag_offsets_t* set_mag_offsets) +{ + return mavlink_msg_set_mag_offsets_pack(system_id, component_id, msg, set_mag_offsets->target_system, set_mag_offsets->target_component, set_mag_offsets->mag_ofs_x, set_mag_offsets->mag_ofs_y, set_mag_offsets->mag_ofs_z); +} + +/** + * @brief Send a set_mag_offsets message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param mag_ofs_x magnetometer X offset + * @param mag_ofs_y magnetometer Y offset + * @param mag_ofs_z magnetometer Z offset + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_mag_offsets_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, int16_t mag_ofs_x, int16_t mag_ofs_y, int16_t mag_ofs_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[8]; + _mav_put_int16_t(buf, 0, mag_ofs_x); + _mav_put_int16_t(buf, 2, mag_ofs_y); + _mav_put_int16_t(buf, 4, mag_ofs_z); + _mav_put_uint8_t(buf, 6, target_system); + _mav_put_uint8_t(buf, 7, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_MAG_OFFSETS, buf, 8, 219); +#else + mavlink_set_mag_offsets_t packet; + packet.mag_ofs_x = mag_ofs_x; + packet.mag_ofs_y = mag_ofs_y; + packet.mag_ofs_z = mag_ofs_z; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_MAG_OFFSETS, (const char *)&packet, 8, 219); +#endif +} + +#endif + +// MESSAGE SET_MAG_OFFSETS UNPACKING + + +/** + * @brief Get field target_system from set_mag_offsets message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_set_mag_offsets_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Get field target_component from set_mag_offsets message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_set_mag_offsets_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 7); +} + +/** + * @brief Get field mag_ofs_x from set_mag_offsets message + * + * @return magnetometer X offset + */ +static inline int16_t mavlink_msg_set_mag_offsets_get_mag_ofs_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 0); +} + +/** + * @brief Get field mag_ofs_y from set_mag_offsets message + * + * @return magnetometer Y offset + */ +static inline int16_t mavlink_msg_set_mag_offsets_get_mag_ofs_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 2); +} + +/** + * @brief Get field mag_ofs_z from set_mag_offsets message + * + * @return magnetometer Z offset + */ +static inline int16_t mavlink_msg_set_mag_offsets_get_mag_ofs_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 4); +} + +/** + * @brief Decode a set_mag_offsets message into a struct + * + * @param msg The message to decode + * @param set_mag_offsets C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_mag_offsets_decode(const mavlink_message_t* msg, mavlink_set_mag_offsets_t* set_mag_offsets) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_mag_offsets->mag_ofs_x = mavlink_msg_set_mag_offsets_get_mag_ofs_x(msg); + set_mag_offsets->mag_ofs_y = mavlink_msg_set_mag_offsets_get_mag_ofs_y(msg); + set_mag_offsets->mag_ofs_z = mavlink_msg_set_mag_offsets_get_mag_ofs_z(msg); + set_mag_offsets->target_system = mavlink_msg_set_mag_offsets_get_target_system(msg); + set_mag_offsets->target_component = mavlink_msg_set_mag_offsets_get_target_component(msg); +#else + memcpy(set_mag_offsets, _MAV_PAYLOAD(msg), 8); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_simstate.h b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_simstate.h new file mode 100644 index 0000000000..dfcddfc2b6 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_simstate.h @@ -0,0 +1,320 @@ +// MESSAGE SIMSTATE PACKING + +#define MAVLINK_MSG_ID_SIMSTATE 164 + +typedef struct __mavlink_simstate_t +{ + float roll; ///< Roll angle (rad) + float pitch; ///< Pitch angle (rad) + float yaw; ///< Yaw angle (rad) + float xacc; ///< X acceleration m/s/s + float yacc; ///< Y acceleration m/s/s + float zacc; ///< Z acceleration m/s/s + float xgyro; ///< Angular speed around X axis rad/s + float ygyro; ///< Angular speed around Y axis rad/s + float zgyro; ///< Angular speed around Z axis rad/s +} mavlink_simstate_t; + +#define MAVLINK_MSG_ID_SIMSTATE_LEN 36 +#define MAVLINK_MSG_ID_164_LEN 36 + + + +#define MAVLINK_MESSAGE_INFO_SIMSTATE { \ + "SIMSTATE", \ + 9, \ + { { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_simstate_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_simstate_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_simstate_t, yaw) }, \ + { "xacc", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_simstate_t, xacc) }, \ + { "yacc", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_simstate_t, yacc) }, \ + { "zacc", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_simstate_t, zacc) }, \ + { "xgyro", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_simstate_t, xgyro) }, \ + { "ygyro", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_simstate_t, ygyro) }, \ + { "zgyro", NULL, MAVLINK_TYPE_FLOAT, 0, 32, offsetof(mavlink_simstate_t, zgyro) }, \ + } \ +} + + +/** + * @brief Pack a simstate message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param xacc X acceleration m/s/s + * @param yacc Y acceleration m/s/s + * @param zacc Z acceleration m/s/s + * @param xgyro Angular speed around X axis rad/s + * @param ygyro Angular speed around Y axis rad/s + * @param zgyro Angular speed around Z axis rad/s + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_simstate_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float roll, float pitch, float yaw, float xacc, float yacc, float zacc, float xgyro, float ygyro, float zgyro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, xacc); + _mav_put_float(buf, 16, yacc); + _mav_put_float(buf, 20, zacc); + _mav_put_float(buf, 24, xgyro); + _mav_put_float(buf, 28, ygyro); + _mav_put_float(buf, 32, zgyro); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_simstate_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_SIMSTATE; + return mavlink_finalize_message(msg, system_id, component_id, 36, 42); +} + +/** + * @brief Pack a simstate message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param xacc X acceleration m/s/s + * @param yacc Y acceleration m/s/s + * @param zacc Z acceleration m/s/s + * @param xgyro Angular speed around X axis rad/s + * @param ygyro Angular speed around Y axis rad/s + * @param zgyro Angular speed around Z axis rad/s + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_simstate_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float roll,float pitch,float yaw,float xacc,float yacc,float zacc,float xgyro,float ygyro,float zgyro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, xacc); + _mav_put_float(buf, 16, yacc); + _mav_put_float(buf, 20, zacc); + _mav_put_float(buf, 24, xgyro); + _mav_put_float(buf, 28, ygyro); + _mav_put_float(buf, 32, zgyro); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_simstate_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_SIMSTATE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 36, 42); +} + +/** + * @brief Encode a simstate struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param simstate C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_simstate_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_simstate_t* simstate) +{ + return mavlink_msg_simstate_pack(system_id, component_id, msg, simstate->roll, simstate->pitch, simstate->yaw, simstate->xacc, simstate->yacc, simstate->zacc, simstate->xgyro, simstate->ygyro, simstate->zgyro); +} + +/** + * @brief Send a simstate message + * @param chan MAVLink channel to send the message + * + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param xacc X acceleration m/s/s + * @param yacc Y acceleration m/s/s + * @param zacc Z acceleration m/s/s + * @param xgyro Angular speed around X axis rad/s + * @param ygyro Angular speed around Y axis rad/s + * @param zgyro Angular speed around Z axis rad/s + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_simstate_send(mavlink_channel_t chan, float roll, float pitch, float yaw, float xacc, float yacc, float zacc, float xgyro, float ygyro, float zgyro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, xacc); + _mav_put_float(buf, 16, yacc); + _mav_put_float(buf, 20, zacc); + _mav_put_float(buf, 24, xgyro); + _mav_put_float(buf, 28, ygyro); + _mav_put_float(buf, 32, zgyro); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SIMSTATE, buf, 36, 42); +#else + mavlink_simstate_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SIMSTATE, (const char *)&packet, 36, 42); +#endif +} + +#endif + +// MESSAGE SIMSTATE UNPACKING + + +/** + * @brief Get field roll from simstate message + * + * @return Roll angle (rad) + */ +static inline float mavlink_msg_simstate_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field pitch from simstate message + * + * @return Pitch angle (rad) + */ +static inline float mavlink_msg_simstate_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field yaw from simstate message + * + * @return Yaw angle (rad) + */ +static inline float mavlink_msg_simstate_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field xacc from simstate message + * + * @return X acceleration m/s/s + */ +static inline float mavlink_msg_simstate_get_xacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field yacc from simstate message + * + * @return Y acceleration m/s/s + */ +static inline float mavlink_msg_simstate_get_yacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field zacc from simstate message + * + * @return Z acceleration m/s/s + */ +static inline float mavlink_msg_simstate_get_zacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field xgyro from simstate message + * + * @return Angular speed around X axis rad/s + */ +static inline float mavlink_msg_simstate_get_xgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field ygyro from simstate message + * + * @return Angular speed around Y axis rad/s + */ +static inline float mavlink_msg_simstate_get_ygyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field zgyro from simstate message + * + * @return Angular speed around Z axis rad/s + */ +static inline float mavlink_msg_simstate_get_zgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 32); +} + +/** + * @brief Decode a simstate message into a struct + * + * @param msg The message to decode + * @param simstate C-struct to decode the message contents into + */ +static inline void mavlink_msg_simstate_decode(const mavlink_message_t* msg, mavlink_simstate_t* simstate) +{ +#if MAVLINK_NEED_BYTE_SWAP + simstate->roll = mavlink_msg_simstate_get_roll(msg); + simstate->pitch = mavlink_msg_simstate_get_pitch(msg); + simstate->yaw = mavlink_msg_simstate_get_yaw(msg); + simstate->xacc = mavlink_msg_simstate_get_xacc(msg); + simstate->yacc = mavlink_msg_simstate_get_yacc(msg); + simstate->zacc = mavlink_msg_simstate_get_zacc(msg); + simstate->xgyro = mavlink_msg_simstate_get_xgyro(msg); + simstate->ygyro = mavlink_msg_simstate_get_ygyro(msg); + simstate->zgyro = mavlink_msg_simstate_get_zgyro(msg); +#else + memcpy(simstate, _MAV_PAYLOAD(msg), 36); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ardupilotmega/testsuite.h b/mavlink/include/mavlink/v1.0/ardupilotmega/testsuite.h new file mode 100644 index 0000000000..aa83889d66 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ardupilotmega/testsuite.h @@ -0,0 +1,908 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from ardupilotmega.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef ARDUPILOTMEGA_TESTSUITE_H +#define ARDUPILOTMEGA_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL +static void mavlink_test_common(uint8_t, uint8_t, mavlink_message_t *last_msg); +static void mavlink_test_ardupilotmega(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_test_common(system_id, component_id, last_msg); + mavlink_test_ardupilotmega(system_id, component_id, last_msg); +} +#endif + +#include "../common/testsuite.h" + + +static void mavlink_test_sensor_offsets(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_sensor_offsets_t packet_in = { + 17.0, + 963497672, + 963497880, + 101.0, + 129.0, + 157.0, + 185.0, + 213.0, + 241.0, + 19107, + 19211, + 19315, + }; + mavlink_sensor_offsets_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.mag_declination = packet_in.mag_declination; + packet1.raw_press = packet_in.raw_press; + packet1.raw_temp = packet_in.raw_temp; + packet1.gyro_cal_x = packet_in.gyro_cal_x; + packet1.gyro_cal_y = packet_in.gyro_cal_y; + packet1.gyro_cal_z = packet_in.gyro_cal_z; + packet1.accel_cal_x = packet_in.accel_cal_x; + packet1.accel_cal_y = packet_in.accel_cal_y; + packet1.accel_cal_z = packet_in.accel_cal_z; + packet1.mag_ofs_x = packet_in.mag_ofs_x; + packet1.mag_ofs_y = packet_in.mag_ofs_y; + packet1.mag_ofs_z = packet_in.mag_ofs_z; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_sensor_offsets_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_sensor_offsets_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_sensor_offsets_pack(system_id, component_id, &msg , packet1.mag_ofs_x , packet1.mag_ofs_y , packet1.mag_ofs_z , packet1.mag_declination , packet1.raw_press , packet1.raw_temp , packet1.gyro_cal_x , packet1.gyro_cal_y , packet1.gyro_cal_z , packet1.accel_cal_x , packet1.accel_cal_y , packet1.accel_cal_z ); + mavlink_msg_sensor_offsets_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_sensor_offsets_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.mag_ofs_x , packet1.mag_ofs_y , packet1.mag_ofs_z , packet1.mag_declination , packet1.raw_press , packet1.raw_temp , packet1.gyro_cal_x , packet1.gyro_cal_y , packet1.gyro_cal_z , packet1.accel_cal_x , packet1.accel_cal_y , packet1.accel_cal_z ); + mavlink_msg_sensor_offsets_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; i>8) ^ (tmp<<8) ^ (tmp <<3) ^ (tmp>>4); +} + +/** + * @brief Initiliaze the buffer for the X.25 CRC + * + * @param crcAccum the 16 bit X.25 CRC + */ +static inline void crc_init(uint16_t* crcAccum) +{ + *crcAccum = X25_INIT_CRC; +} + + +/** + * @brief Calculates the X.25 checksum on a byte buffer + * + * @param pBuffer buffer containing the byte array to hash + * @param length length of the byte array + * @return the checksum over the buffer bytes + **/ +static inline uint16_t crc_calculate(const uint8_t* pBuffer, uint16_t length) +{ + uint16_t crcTmp; + crc_init(&crcTmp); + while (length--) { + crc_accumulate(*pBuffer++, &crcTmp); + } + return crcTmp; +} + +/** + * @brief Accumulate the X.25 CRC by adding an array of bytes + * + * The checksum function adds the hash of one char at a time to the + * 16 bit checksum (uint16_t). + * + * @param data new bytes to hash + * @param crcAccum the already accumulated checksum + **/ +static inline void crc_accumulate_buffer(uint16_t *crcAccum, const char *pBuffer, uint8_t length) +{ + const uint8_t *p = (const uint8_t *)pBuffer; + while (length--) { + crc_accumulate(*p++, crcAccum); + } +} + + + + +#endif /* _CHECKSUM_H_ */ + +#ifdef __cplusplus +} +#endif diff --git a/mavlink/include/mavlink/v1.0/common/common.h b/mavlink/include/mavlink/v1.0/common/common.h new file mode 100644 index 0000000000..7c017f39f5 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/common.h @@ -0,0 +1,489 @@ +/** @file + * @brief MAVLink comm protocol generated from common.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef COMMON_H +#define COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {9, 31, 12, 0, 14, 28, 3, 32, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 20, 2, 25, 23, 30, 101, 22, 26, 16, 14, 28, 32, 28, 28, 22, 22, 21, 6, 6, 37, 4, 4, 2, 2, 4, 2, 2, 3, 13, 12, 19, 17, 15, 15, 27, 25, 18, 18, 20, 20, 9, 54, 26, 0, 36, 0, 6, 4, 0, 21, 18, 0, 0, 0, 20, 0, 33, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 56, 42, 33, 0, 0, 0, 0, 0, 0, 0, 26, 32, 32, 20, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 30, 18, 18, 51, 9, 0} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {50, 124, 137, 0, 237, 217, 104, 119, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 214, 159, 220, 168, 24, 23, 170, 144, 67, 115, 39, 246, 185, 104, 237, 244, 222, 212, 9, 254, 230, 28, 28, 132, 221, 232, 11, 153, 41, 39, 214, 223, 141, 33, 15, 3, 100, 24, 239, 238, 30, 200, 183, 0, 130, 0, 148, 21, 0, 52, 124, 0, 0, 0, 20, 0, 152, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 183, 63, 54, 0, 0, 0, 0, 0, 0, 0, 175, 102, 158, 208, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 49, 170, 44, 83, 46, 0} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, MAVLINK_MESSAGE_INFO_SYS_STATUS, MAVLINK_MESSAGE_INFO_SYSTEM_TIME, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PING, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK, MAVLINK_MESSAGE_INFO_AUTH_KEY, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_SET_MODE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST, MAVLINK_MESSAGE_INFO_PARAM_VALUE, MAVLINK_MESSAGE_INFO_PARAM_SET, MAVLINK_MESSAGE_INFO_GPS_RAW_INT, MAVLINK_MESSAGE_INFO_GPS_STATUS, MAVLINK_MESSAGE_INFO_SCALED_IMU, MAVLINK_MESSAGE_INFO_RAW_IMU, MAVLINK_MESSAGE_INFO_RAW_PRESSURE, MAVLINK_MESSAGE_INFO_SCALED_PRESSURE, MAVLINK_MESSAGE_INFO_ATTITUDE, MAVLINK_MESSAGE_INFO_ATTITUDE_QUATERNION, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_NED, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT, MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED, MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW, MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW, MAVLINK_MESSAGE_INFO_MISSION_REQUEST_PARTIAL_LIST, MAVLINK_MESSAGE_INFO_MISSION_WRITE_PARTIAL_LIST, MAVLINK_MESSAGE_INFO_MISSION_ITEM, MAVLINK_MESSAGE_INFO_MISSION_REQUEST, MAVLINK_MESSAGE_INFO_MISSION_SET_CURRENT, MAVLINK_MESSAGE_INFO_MISSION_CURRENT, MAVLINK_MESSAGE_INFO_MISSION_REQUEST_LIST, MAVLINK_MESSAGE_INFO_MISSION_COUNT, MAVLINK_MESSAGE_INFO_MISSION_CLEAR_ALL, MAVLINK_MESSAGE_INFO_MISSION_ITEM_REACHED, MAVLINK_MESSAGE_INFO_MISSION_ACK, MAVLINK_MESSAGE_INFO_SET_GPS_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_GPS_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_SET_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_SETPOINT_INT, MAVLINK_MESSAGE_INFO_SET_GLOBAL_POSITION_SETPOINT_INT, MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_SET_QUAD_MOTORS_SETPOINT, MAVLINK_MESSAGE_INFO_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_STATE_CORRECTION, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM, MAVLINK_MESSAGE_INFO_DATA_STREAM, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_MANUAL_CONTROL, MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_VFR_HUD, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_COMMAND_LONG, MAVLINK_MESSAGE_INFO_COMMAND_ACK, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET, MAVLINK_MESSAGE_INFO_HIL_STATE, MAVLINK_MESSAGE_INFO_HIL_CONTROLS, MAVLINK_MESSAGE_INFO_HIL_RC_INPUTS_RAW, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OPTICAL_FLOW, MAVLINK_MESSAGE_INFO_GLOBAL_VISION_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VISION_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VISION_SPEED_ESTIMATE, MAVLINK_MESSAGE_INFO_VICON_POSITION_ESTIMATE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_MEMORY_VECT, MAVLINK_MESSAGE_INFO_DEBUG_VECT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT, MAVLINK_MESSAGE_INFO_STATUSTEXT, MAVLINK_MESSAGE_INFO_DEBUG, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_COMMON + + + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 3 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 3 +#endif + +// ENUM DEFINITIONS + + +/** @brief Micro air vehicle / autopilot classes. This identifies the individual model. */ +#ifndef HAVE_ENUM_MAV_AUTOPILOT +#define HAVE_ENUM_MAV_AUTOPILOT +enum MAV_AUTOPILOT +{ + MAV_AUTOPILOT_GENERIC=0, /* Generic autopilot, full support for everything | */ + MAV_AUTOPILOT_PIXHAWK=1, /* PIXHAWK autopilot, http://pixhawk.ethz.ch | */ + MAV_AUTOPILOT_SLUGS=2, /* SLUGS autopilot, http://slugsuav.soe.ucsc.edu | */ + MAV_AUTOPILOT_ARDUPILOTMEGA=3, /* ArduPilotMega / ArduCopter, http://diydrones.com | */ + MAV_AUTOPILOT_OPENPILOT=4, /* OpenPilot, http://openpilot.org | */ + MAV_AUTOPILOT_GENERIC_WAYPOINTS_ONLY=5, /* Generic autopilot only supporting simple waypoints | */ + MAV_AUTOPILOT_GENERIC_WAYPOINTS_AND_SIMPLE_NAVIGATION_ONLY=6, /* Generic autopilot supporting waypoints and other simple navigation commands | */ + MAV_AUTOPILOT_GENERIC_MISSION_FULL=7, /* Generic autopilot supporting the full mission command set | */ + MAV_AUTOPILOT_INVALID=8, /* No valid autopilot, e.g. a GCS or other MAVLink component | */ + MAV_AUTOPILOT_PPZ=9, /* PPZ UAV - http://nongnu.org/paparazzi | */ + MAV_AUTOPILOT_UDB=10, /* UAV Dev Board | */ + MAV_AUTOPILOT_FP=11, /* FlexiPilot | */ + MAV_AUTOPILOT_ENUM_END=12, /* | */ +}; +#endif + +/** @brief */ +#ifndef HAVE_ENUM_MAV_TYPE +#define HAVE_ENUM_MAV_TYPE +enum MAV_TYPE +{ + MAV_TYPE_GENERIC=0, /* Generic micro air vehicle. | */ + MAV_TYPE_FIXED_WING=1, /* Fixed wing aircraft. | */ + MAV_TYPE_QUADROTOR=2, /* Quadrotor | */ + MAV_TYPE_COAXIAL=3, /* Coaxial helicopter | */ + MAV_TYPE_HELICOPTER=4, /* Normal helicopter with tail rotor. | */ + MAV_TYPE_ANTENNA_TRACKER=5, /* Ground installation | */ + MAV_TYPE_GCS=6, /* Operator control unit / ground control station | */ + MAV_TYPE_AIRSHIP=7, /* Airship, controlled | */ + MAV_TYPE_FREE_BALLOON=8, /* Free balloon, uncontrolled | */ + MAV_TYPE_ROCKET=9, /* Rocket | */ + MAV_TYPE_GROUND_ROVER=10, /* Ground rover | */ + MAV_TYPE_SURFACE_BOAT=11, /* Surface vessel, boat, ship | */ + MAV_TYPE_SUBMARINE=12, /* Submarine | */ + MAV_TYPE_HEXAROTOR=13, /* Hexarotor | */ + MAV_TYPE_OCTOROTOR=14, /* Octorotor | */ + MAV_TYPE_TRICOPTER=15, /* Octorotor | */ + MAV_TYPE_FLAPPING_WING=16, /* Flapping wing | */ + MAV_TYPE_KITE=17, /* Flapping wing | */ + MAV_TYPE_ENUM_END=18, /* | */ +}; +#endif + +/** @brief These flags encode the MAV mode. */ +#ifndef HAVE_ENUM_MAV_MODE_FLAG +#define HAVE_ENUM_MAV_MODE_FLAG +enum MAV_MODE_FLAG +{ + MAV_MODE_FLAG_CUSTOM_MODE_ENABLED=1, /* 0b00000001 Reserved for future use. | */ + MAV_MODE_FLAG_TEST_ENABLED=2, /* 0b00000010 system has a test mode enabled. This flag is intended for temporary system tests and should not be used for stable implementations. | */ + MAV_MODE_FLAG_AUTO_ENABLED=4, /* 0b00000100 autonomous mode enabled, system finds its own goal positions. Guided flag can be set or not, depends on the actual implementation. | */ + MAV_MODE_FLAG_GUIDED_ENABLED=8, /* 0b00001000 guided mode enabled, system flies MISSIONs / mission items. | */ + MAV_MODE_FLAG_STABILIZE_ENABLED=16, /* 0b00010000 system stabilizes electronically its attitude (and optionally position). It needs however further control inputs to move around. | */ + MAV_MODE_FLAG_HIL_ENABLED=32, /* 0b00100000 hardware in the loop simulation. All motors / actuators are blocked, but internal software is full operational. | */ + MAV_MODE_FLAG_MANUAL_INPUT_ENABLED=64, /* 0b01000000 remote control input is enabled. | */ + MAV_MODE_FLAG_SAFETY_ARMED=128, /* 0b10000000 MAV safety set to armed. Motors are enabled / running / can start. Ready to fly. | */ + MAV_MODE_FLAG_ENUM_END=129, /* | */ +}; +#endif + +/** @brief These values encode the bit positions of the decode position. These values can be used to read the value of a flag bit by combining the base_mode variable with AND with the flag position value. The result will be either 0 or 1, depending on if the flag is set or not. */ +#ifndef HAVE_ENUM_MAV_MODE_FLAG_DECODE_POSITION +#define HAVE_ENUM_MAV_MODE_FLAG_DECODE_POSITION +enum MAV_MODE_FLAG_DECODE_POSITION +{ + MAV_MODE_FLAG_DECODE_POSITION_CUSTOM_MODE=1, /* Eighth bit: 00000001 | */ + MAV_MODE_FLAG_DECODE_POSITION_TEST=2, /* Seventh bit: 00000010 | */ + MAV_MODE_FLAG_DECODE_POSITION_AUTO=4, /* Sixt bit: 00000100 | */ + MAV_MODE_FLAG_DECODE_POSITION_GUIDED=8, /* Fifth bit: 00001000 | */ + MAV_MODE_FLAG_DECODE_POSITION_STABILIZE=16, /* Fourth bit: 00010000 | */ + MAV_MODE_FLAG_DECODE_POSITION_HIL=32, /* Third bit: 00100000 | */ + MAV_MODE_FLAG_DECODE_POSITION_MANUAL=64, /* Second bit: 01000000 | */ + MAV_MODE_FLAG_DECODE_POSITION_SAFETY=128, /* First bit: 10000000 | */ + MAV_MODE_FLAG_DECODE_POSITION_ENUM_END=129, /* | */ +}; +#endif + +/** @brief Override command, pauses current mission execution and moves immediately to a position */ +#ifndef HAVE_ENUM_MAV_GOTO +#define HAVE_ENUM_MAV_GOTO +enum MAV_GOTO +{ + MAV_GOTO_DO_HOLD=0, /* Hold at the current position. | */ + MAV_GOTO_DO_CONTINUE=1, /* Continue with the next item in mission execution. | */ + MAV_GOTO_HOLD_AT_CURRENT_POSITION=2, /* Hold at the current position of the system | */ + MAV_GOTO_HOLD_AT_SPECIFIED_POSITION=3, /* Hold at the position specified in the parameters of the DO_HOLD action | */ + MAV_GOTO_ENUM_END=4, /* | */ +}; +#endif + +/** @brief These defines are predefined OR-combined mode flags. There is no need to use values from this enum, but it + simplifies the use of the mode flags. Note that manual input is enabled in all modes as a safety override. */ +#ifndef HAVE_ENUM_MAV_MODE +#define HAVE_ENUM_MAV_MODE +enum MAV_MODE +{ + MAV_MODE_PREFLIGHT=0, /* System is not ready to fly, booting, calibrating, etc. No flag is set. | */ + MAV_MODE_MANUAL_DISARMED=64, /* System is allowed to be active, under manual (RC) control, no stabilization | */ + MAV_MODE_TEST_DISARMED=66, /* UNDEFINED mode. This solely depends on the autopilot - use with caution, intended for developers only. | */ + MAV_MODE_STABILIZE_DISARMED=80, /* System is allowed to be active, under assisted RC control. | */ + MAV_MODE_GUIDED_DISARMED=88, /* System is allowed to be active, under autonomous control, manual setpoint | */ + MAV_MODE_AUTO_DISARMED=92, /* System is allowed to be active, under autonomous control and navigation (the trajectory is decided onboard and not pre-programmed by MISSIONs) | */ + MAV_MODE_MANUAL_ARMED=192, /* System is allowed to be active, under manual (RC) control, no stabilization | */ + MAV_MODE_TEST_ARMED=194, /* UNDEFINED mode. This solely depends on the autopilot - use with caution, intended for developers only. | */ + MAV_MODE_STABILIZE_ARMED=208, /* System is allowed to be active, under assisted RC control. | */ + MAV_MODE_GUIDED_ARMED=216, /* System is allowed to be active, under autonomous control, manual setpoint | */ + MAV_MODE_AUTO_ARMED=220, /* System is allowed to be active, under autonomous control and navigation (the trajectory is decided onboard and not pre-programmed by MISSIONs) | */ + MAV_MODE_ENUM_END=221, /* | */ +}; +#endif + +/** @brief */ +#ifndef HAVE_ENUM_MAV_STATE +#define HAVE_ENUM_MAV_STATE +enum MAV_STATE +{ + MAV_STATE_UNINIT=0, /* Uninitialized system, state is unknown. | */ + MAV_STATE_BOOT=1, /* System is booting up. | */ + MAV_STATE_CALIBRATING=2, /* System is calibrating and not flight-ready. | */ + MAV_STATE_STANDBY=3, /* System is grounded and on standby. It can be launched any time. | */ + MAV_STATE_ACTIVE=4, /* System is active and might be already airborne. Motors are engaged. | */ + MAV_STATE_CRITICAL=5, /* System is in a non-normal flight mode. It can however still navigate. | */ + MAV_STATE_EMERGENCY=6, /* System is in a non-normal flight mode. It lost control over parts or over the whole airframe. It is in mayday and going down. | */ + MAV_STATE_POWEROFF=7, /* System just initialized its power-down sequence, will shut down now. | */ + MAV_STATE_ENUM_END=8, /* | */ +}; +#endif + +/** @brief */ +#ifndef HAVE_ENUM_MAV_COMPONENT +#define HAVE_ENUM_MAV_COMPONENT +enum MAV_COMPONENT +{ + MAV_COMP_ID_ALL=0, /* | */ + MAV_COMP_ID_CAMERA=100, /* | */ + MAV_COMP_ID_SERVO1=140, /* | */ + MAV_COMP_ID_SERVO2=141, /* | */ + MAV_COMP_ID_SERVO3=142, /* | */ + MAV_COMP_ID_SERVO4=143, /* | */ + MAV_COMP_ID_SERVO5=144, /* | */ + MAV_COMP_ID_SERVO6=145, /* | */ + MAV_COMP_ID_SERVO7=146, /* | */ + MAV_COMP_ID_SERVO8=147, /* | */ + MAV_COMP_ID_SERVO9=148, /* | */ + MAV_COMP_ID_SERVO10=149, /* | */ + MAV_COMP_ID_SERVO11=150, /* | */ + MAV_COMP_ID_SERVO12=151, /* | */ + MAV_COMP_ID_SERVO13=152, /* | */ + MAV_COMP_ID_SERVO14=153, /* | */ + MAV_COMP_ID_MAPPER=180, /* | */ + MAV_COMP_ID_MISSIONPLANNER=190, /* | */ + MAV_COMP_ID_PATHPLANNER=195, /* | */ + MAV_COMP_ID_IMU=200, /* | */ + MAV_COMP_ID_IMU_2=201, /* | */ + MAV_COMP_ID_IMU_3=202, /* | */ + MAV_COMP_ID_GPS=220, /* | */ + MAV_COMP_ID_UDP_BRIDGE=240, /* | */ + MAV_COMP_ID_UART_BRIDGE=241, /* | */ + MAV_COMP_ID_SYSTEM_CONTROL=250, /* | */ + MAV_COMPONENT_ENUM_END=251, /* | */ +}; +#endif + +/** @brief */ +#ifndef HAVE_ENUM_MAV_FRAME +#define HAVE_ENUM_MAV_FRAME +enum MAV_FRAME +{ + MAV_FRAME_GLOBAL=0, /* Global coordinate frame, WGS84 coordinate system. First value / x: latitude, second value / y: longitude, third value / z: positive altitude over mean sea level (MSL) | */ + MAV_FRAME_LOCAL_NED=1, /* Local coordinate frame, Z-up (x: north, y: east, z: down). | */ + MAV_FRAME_MISSION=2, /* NOT a coordinate frame, indicates a mission command. | */ + MAV_FRAME_GLOBAL_RELATIVE_ALT=3, /* Global coordinate frame, WGS84 coordinate system, relative altitude over ground with respect to the home position. First value / x: latitude, second value / y: longitude, third value / z: positive altitude with 0 being at the altitude of the home location. | */ + MAV_FRAME_LOCAL_ENU=4, /* Local coordinate frame, Z-down (x: east, y: north, z: up) | */ + MAV_FRAME_ENUM_END=5, /* | */ +}; +#endif + +/** @brief */ +#ifndef HAVE_ENUM_MAVLINK_DATA_STREAM_TYPE +#define HAVE_ENUM_MAVLINK_DATA_STREAM_TYPE +enum MAVLINK_DATA_STREAM_TYPE +{ + MAVLINK_DATA_STREAM_IMG_JPEG=1, /* | */ + MAVLINK_DATA_STREAM_IMG_BMP=2, /* | */ + MAVLINK_DATA_STREAM_IMG_RAW8U=3, /* | */ + MAVLINK_DATA_STREAM_IMG_RAW32U=4, /* | */ + MAVLINK_DATA_STREAM_IMG_PGM=5, /* | */ + MAVLINK_DATA_STREAM_IMG_PNG=6, /* | */ + MAVLINK_DATA_STREAM_TYPE_ENUM_END=7, /* | */ +}; +#endif + +/** @brief Commands to be executed by the MAV. They can be executed on user request, or as part of a mission script. If the action is used in a mission, the parameter mapping to the waypoint/mission message is as follows: Param 1, Param 2, Param 3, Param 4, X: Param 5, Y:Param 6, Z:Param 7. This command list is similar what ARINC 424 is for commercial aircraft: A data format how to interpret waypoint/mission data. */ +#ifndef HAVE_ENUM_MAV_CMD +#define HAVE_ENUM_MAV_CMD +enum MAV_CMD +{ + MAV_CMD_NAV_WAYPOINT=16, /* Navigate to MISSION. |Hold time in decimal seconds. (ignored by fixed wing, time to stay at MISSION for rotary wing)| Acceptance radius in meters (if the sphere with this radius is hit, the MISSION counts as reached)| 0 to pass through the WP, if > 0 radius in meters to pass by WP. Positive value for clockwise orbit, negative value for counter-clockwise orbit. Allows trajectory control.| Desired yaw angle at MISSION (rotary wing)| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_UNLIM=17, /* Loiter around this MISSION an unlimited amount of time |Empty| Empty| Radius around MISSION, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_TURNS=18, /* Loiter around this MISSION for X turns |Turns| Empty| Radius around MISSION, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_TIME=19, /* Loiter around this MISSION for X seconds |Seconds (decimal)| Empty| Radius around MISSION, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_RETURN_TO_LAUNCH=20, /* Return to launch location |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_NAV_LAND=21, /* Land at location |Empty| Empty| Empty| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_TAKEOFF=22, /* Takeoff from ground / hand |Minimum pitch (if airspeed sensor present), desired pitch without sensor| Empty| Empty| Yaw angle (if magnetometer present), ignored without magnetometer| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_ROI=80, /* Sets the region of interest (ROI) for a sensor set or the vehicle itself. This can then be used by the vehicles control system to control the vehicle attitude and the attitude of various sensors such as cameras. |Region of intereset mode. (see MAV_ROI enum)| MISSION index/ target ID. (see MAV_ROI enum)| ROI index (allows a vehicle to manage multiple ROI's)| Empty| x the location of the fixed ROI (see MAV_FRAME)| y| z| */ + MAV_CMD_NAV_PATHPLANNING=81, /* Control autonomous path planning on the MAV. |0: Disable local obstacle avoidance / local path planning (without resetting map), 1: Enable local path planning, 2: Enable and reset local path planning| 0: Disable full path planning (without resetting map), 1: Enable, 2: Enable and reset map/occupancy grid, 3: Enable and reset planned route, but not occupancy grid| Empty| Yaw angle at goal, in compass degrees, [0..360]| Latitude/X of goal| Longitude/Y of goal| Altitude/Z of goal| */ + MAV_CMD_NAV_LAST=95, /* NOP - This command is only used to mark the upper limit of the NAV/ACTION commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_DELAY=112, /* Delay mission state machine. |Delay in seconds (decimal)| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_CHANGE_ALT=113, /* Ascend/descend at rate. Delay mission state machine until desired altitude reached. |Descent / Ascend rate (m/s)| Empty| Empty| Empty| Empty| Empty| Finish Altitude| */ + MAV_CMD_CONDITION_DISTANCE=114, /* Delay mission state machine until within desired distance of next NAV point. |Distance (meters)| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_YAW=115, /* Reach a certain target angle. |target angle: [0-360], 0 is north| speed during yaw change:[deg per second]| direction: negative: counter clockwise, positive: clockwise [-1,1]| relative offset or absolute angle: [ 1,0]| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_LAST=159, /* NOP - This command is only used to mark the upper limit of the CONDITION commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_MODE=176, /* Set system mode. |Mode, as defined by ENUM MAV_MODE| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_JUMP=177, /* Jump to the desired command in the mission list. Repeat this action only the specified number of times |Sequence number| Repeat count| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_CHANGE_SPEED=178, /* Change speed and/or throttle set points. |Speed type (0=Airspeed, 1=Ground Speed)| Speed (m/s, -1 indicates no change)| Throttle ( Percent, -1 indicates no change)| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_HOME=179, /* Changes the home location either to the current location or a specified location. |Use current (1=use current location, 0=use specified location)| Empty| Empty| Empty| Latitude| Longitude| Altitude| */ + MAV_CMD_DO_SET_PARAMETER=180, /* Set a system parameter. Caution! Use of this command requires knowledge of the numeric enumeration value of the parameter. |Parameter number| Parameter value| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_RELAY=181, /* Set a relay to a condition. |Relay number| Setting (1=on, 0=off, others possible depending on system hardware)| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_REPEAT_RELAY=182, /* Cycle a relay on and off for a desired number of cyles with a desired period. |Relay number| Cycle count| Cycle time (seconds, decimal)| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_SERVO=183, /* Set a servo to a desired PWM value. |Servo number| PWM (microseconds, 1000 to 2000 typical)| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_REPEAT_SERVO=184, /* Cycle a between its nominal setting and a desired PWM for a desired number of cycles with a desired period. |Servo number| PWM (microseconds, 1000 to 2000 typical)| Cycle count| Cycle time (seconds)| Empty| Empty| Empty| */ + MAV_CMD_DO_CONTROL_VIDEO=200, /* Control onboard camera system. |Camera ID (-1 for all)| Transmission: 0: disabled, 1: enabled compressed, 2: enabled raw| Transmission mode: 0: video stream, >0: single images every n seconds (decimal)| Recording: 0: disabled, 1: enabled compressed, 2: enabled raw| Empty| Empty| Empty| */ + MAV_CMD_DO_LAST=240, /* NOP - This command is only used to mark the upper limit of the DO commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_PREFLIGHT_CALIBRATION=241, /* Trigger calibration. This command will be only accepted if in pre-flight mode. |Gyro calibration: 0: no, 1: yes| Magnetometer calibration: 0: no, 1: yes| Ground pressure: 0: no, 1: yes| Radio calibration: 0: no, 1: yes| Empty| Empty| Empty| */ + MAV_CMD_PREFLIGHT_SET_SENSOR_OFFSETS=242, /* Set sensor offsets. This command will be only accepted if in pre-flight mode. |Sensor to adjust the offsets for: 0: gyros, 1: accelerometer, 2: magnetometer, 3: barometer, 4: optical flow| X axis offset (or generic dimension 1), in the sensor's raw units| Y axis offset (or generic dimension 2), in the sensor's raw units| Z axis offset (or generic dimension 3), in the sensor's raw units| Generic dimension 4, in the sensor's raw units| Generic dimension 5, in the sensor's raw units| Generic dimension 6, in the sensor's raw units| */ + MAV_CMD_PREFLIGHT_STORAGE=245, /* Request storage of different parameter values and logs. This command will be only accepted if in pre-flight mode. |Parameter storage: 0: READ FROM FLASH/EEPROM, 1: WRITE CURRENT TO FLASH/EEPROM| Mission storage: 0: READ FROM FLASH/EEPROM, 1: WRITE CURRENT TO FLASH/EEPROM| Reserved| Reserved| Empty| Empty| Empty| */ + MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN=246, /* Request the reboot or shutdown of system components. |0: Do nothing for autopilot, 1: Reboot autopilot, 2: Shutdown autopilot.| 0: Do nothing for onboard computer, 1: Reboot onboard computer, 2: Shutdown onboard computer.| Reserved| Reserved| Empty| Empty| Empty| */ + MAV_CMD_OVERRIDE_GOTO=252, /* Hold / continue the current action |MAV_GOTO_DO_HOLD: hold MAV_GOTO_DO_CONTINUE: continue with next item in mission plan| MAV_GOTO_HOLD_AT_CURRENT_POSITION: Hold at current position MAV_GOTO_HOLD_AT_SPECIFIED_POSITION: hold at specified position| MAV_FRAME coordinate frame of hold point| Desired yaw angle in degrees| Latitude / X position| Longitude / Y position| Altitude / Z position| */ + MAV_CMD_MISSION_START=300, /* start running a mission |first_item: the first mission item to run| last_item: the last mission item to run (after this item is run, the mission ends)| */ + MAV_CMD_COMPONENT_ARM_DISARM=400, /* Arms / Disarms a component |1 to arm, 0 to disarm| */ + MAV_CMD_ENUM_END=401, /* | */ +}; +#endif + +/** @brief Data stream IDs. A data stream is not a fixed set of messages, but rather a + recommendation to the autopilot software. Individual autopilots may or may not obey + the recommended messages. */ +#ifndef HAVE_ENUM_MAV_DATA_STREAM +#define HAVE_ENUM_MAV_DATA_STREAM +enum MAV_DATA_STREAM +{ + MAV_DATA_STREAM_ALL=0, /* Enable all data streams | */ + MAV_DATA_STREAM_RAW_SENSORS=1, /* Enable IMU_RAW, GPS_RAW, GPS_STATUS packets. | */ + MAV_DATA_STREAM_EXTENDED_STATUS=2, /* Enable GPS_STATUS, CONTROL_STATUS, AUX_STATUS | */ + MAV_DATA_STREAM_RC_CHANNELS=3, /* Enable RC_CHANNELS_SCALED, RC_CHANNELS_RAW, SERVO_OUTPUT_RAW | */ + MAV_DATA_STREAM_RAW_CONTROLLER=4, /* Enable ATTITUDE_CONTROLLER_OUTPUT, POSITION_CONTROLLER_OUTPUT, NAV_CONTROLLER_OUTPUT. | */ + MAV_DATA_STREAM_POSITION=6, /* Enable LOCAL_POSITION, GLOBAL_POSITION/GLOBAL_POSITION_INT messages. | */ + MAV_DATA_STREAM_EXTRA1=10, /* Dependent on the autopilot | */ + MAV_DATA_STREAM_EXTRA2=11, /* Dependent on the autopilot | */ + MAV_DATA_STREAM_EXTRA3=12, /* Dependent on the autopilot | */ + MAV_DATA_STREAM_ENUM_END=13, /* | */ +}; +#endif + +/** @brief The ROI (region of interest) for the vehicle. This can be + be used by the vehicle for camera/vehicle attitude alignment (see + MAV_CMD_NAV_ROI). */ +#ifndef HAVE_ENUM_MAV_ROI +#define HAVE_ENUM_MAV_ROI +enum MAV_ROI +{ + MAV_ROI_NONE=0, /* No region of interest. | */ + MAV_ROI_WPNEXT=1, /* Point toward next MISSION. | */ + MAV_ROI_WPINDEX=2, /* Point toward given MISSION. | */ + MAV_ROI_LOCATION=3, /* Point toward fixed location. | */ + MAV_ROI_TARGET=4, /* Point toward of given id. | */ + MAV_ROI_ENUM_END=5, /* | */ +}; +#endif + +/** @brief ACK / NACK / ERROR values as a result of MAV_CMDs and for mission item transmission. */ +#ifndef HAVE_ENUM_MAV_CMD_ACK +#define HAVE_ENUM_MAV_CMD_ACK +enum MAV_CMD_ACK +{ + MAV_CMD_ACK_OK=1, /* Command / mission item is ok. | */ + MAV_CMD_ACK_ERR_FAIL=2, /* Generic error message if none of the other reasons fails or if no detailed error reporting is implemented. | */ + MAV_CMD_ACK_ERR_ACCESS_DENIED=3, /* The system is refusing to accept this command from this source / communication partner. | */ + MAV_CMD_ACK_ERR_NOT_SUPPORTED=4, /* Command or mission item is not supported, other commands would be accepted. | */ + MAV_CMD_ACK_ERR_COORDINATE_FRAME_NOT_SUPPORTED=5, /* The coordinate frame of this command / mission item is not supported. | */ + MAV_CMD_ACK_ERR_COORDINATES_OUT_OF_RANGE=6, /* The coordinate frame of this command is ok, but he coordinate values exceed the safety limits of this system. This is a generic error, please use the more specific error messages below if possible. | */ + MAV_CMD_ACK_ERR_X_LAT_OUT_OF_RANGE=7, /* The X or latitude value is out of range. | */ + MAV_CMD_ACK_ERR_Y_LON_OUT_OF_RANGE=8, /* The Y or longitude value is out of range. | */ + MAV_CMD_ACK_ERR_Z_ALT_OUT_OF_RANGE=9, /* The Z or altitude value is out of range. | */ + MAV_CMD_ACK_ENUM_END=10, /* | */ +}; +#endif + +/** @brief type of a mavlink parameter */ +#ifndef HAVE_ENUM_MAV_VAR +#define HAVE_ENUM_MAV_VAR +enum MAV_VAR +{ + MAV_VAR_FLOAT=0, /* 32 bit float | */ + MAV_VAR_UINT8=1, /* 8 bit unsigned integer | */ + MAV_VAR_INT8=2, /* 8 bit signed integer | */ + MAV_VAR_UINT16=3, /* 16 bit unsigned integer | */ + MAV_VAR_INT16=4, /* 16 bit signed integer | */ + MAV_VAR_UINT32=5, /* 32 bit unsigned integer | */ + MAV_VAR_INT32=6, /* 32 bit signed integer | */ + MAV_VAR_ENUM_END=7, /* | */ +}; +#endif + +/** @brief result from a mavlink command */ +#ifndef HAVE_ENUM_MAV_RESULT +#define HAVE_ENUM_MAV_RESULT +enum MAV_RESULT +{ + MAV_RESULT_ACCEPTED=0, /* Command ACCEPTED and EXECUTED | */ + MAV_RESULT_TEMPORARILY_REJECTED=1, /* Command TEMPORARY REJECTED/DENIED | */ + MAV_RESULT_DENIED=2, /* Command PERMANENTLY DENIED | */ + MAV_RESULT_UNSUPPORTED=3, /* Command UNKNOWN/UNSUPPORTED | */ + MAV_RESULT_FAILED=4, /* Command executed, but failed | */ + MAV_RESULT_ENUM_END=5, /* | */ +}; +#endif + +/** @brief result in a mavlink mission ack */ +#ifndef HAVE_ENUM_MAV_MISSION_RESULT +#define HAVE_ENUM_MAV_MISSION_RESULT +enum MAV_MISSION_RESULT +{ + MAV_MISSION_ACCEPTED=0, /* mission accepted OK | */ + MAV_MISSION_ERROR=1, /* generic error / not accepting mission commands at all right now | */ + MAV_MISSION_UNSUPPORTED_FRAME=2, /* coordinate frame is not supported | */ + MAV_MISSION_UNSUPPORTED=3, /* command is not supported | */ + MAV_MISSION_NO_SPACE=4, /* mission item exceeds storage space | */ + MAV_MISSION_INVALID=5, /* one of the parameters has an invalid value | */ + MAV_MISSION_INVALID_PARAM1=6, /* param1 has an invalid value | */ + MAV_MISSION_INVALID_PARAM2=7, /* param2 has an invalid value | */ + MAV_MISSION_INVALID_PARAM3=8, /* param3 has an invalid value | */ + MAV_MISSION_INVALID_PARAM4=9, /* param4 has an invalid value | */ + MAV_MISSION_INVALID_PARAM5_X=10, /* x/param5 has an invalid value | */ + MAV_MISSION_INVALID_PARAM6_Y=11, /* y/param6 has an invalid value | */ + MAV_MISSION_INVALID_PARAM7=12, /* param7 has an invalid value | */ + MAV_MISSION_INVALID_SEQUENCE=13, /* received waypoint out of sequence | */ + MAV_MISSION_DENIED=14, /* not accepting any mission commands from this communication partner | */ + MAV_MISSION_RESULT_ENUM_END=15, /* | */ +}; +#endif + +/** @brief Indicates the severity level, generally used for status messages to indicate their relative urgency. Based on RFC-5424 using expanded definitions at: http://www.kiwisyslog.com/kb/info:-syslog-message-levels/. */ +#ifndef HAVE_ENUM_MAV_SEVERITY +#define HAVE_ENUM_MAV_SEVERITY +enum MAV_SEVERITY +{ + MAV_SEVERITY_EMERGENCY=0, /* System is unusable. This is a "panic" condition. | */ + MAV_SEVERITY_ALERT=1, /* Action should be taken immediately. Indicates error in non-critical systems. | */ + MAV_SEVERITY_CRITICAL=2, /* Action must be taken immediately. Indicates failure in a primary system. | */ + MAV_SEVERITY_ERROR=3, /* Indicates an error in secondary/redundant systems. | */ + MAV_SEVERITY_WARNING=4, /* Indicates about a possible future error if this is not resolved within a given timeframe. Example would be a low battery warning. | */ + MAV_SEVERITY_NOTICE=5, /* An unusual event has occured, though not an error condition. This should be investigated for the root cause. | */ + MAV_SEVERITY_INFO=6, /* Normal operational messages. Useful for logging. No action is required for these messages. | */ + MAV_SEVERITY_DEBUG=7, /* Useful non-operational messages that can assist in debugging. These should not occur during normal operation. | */ + MAV_SEVERITY_ENUM_END=8, /* | */ +}; +#endif + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_heartbeat.h" +#include "./mavlink_msg_sys_status.h" +#include "./mavlink_msg_system_time.h" +#include "./mavlink_msg_ping.h" +#include "./mavlink_msg_change_operator_control.h" +#include "./mavlink_msg_change_operator_control_ack.h" +#include "./mavlink_msg_auth_key.h" +#include "./mavlink_msg_set_mode.h" +#include "./mavlink_msg_param_request_read.h" +#include "./mavlink_msg_param_request_list.h" +#include "./mavlink_msg_param_value.h" +#include "./mavlink_msg_param_set.h" +#include "./mavlink_msg_gps_raw_int.h" +#include "./mavlink_msg_gps_status.h" +#include "./mavlink_msg_scaled_imu.h" +#include "./mavlink_msg_raw_imu.h" +#include "./mavlink_msg_raw_pressure.h" +#include "./mavlink_msg_scaled_pressure.h" +#include "./mavlink_msg_attitude.h" +#include "./mavlink_msg_attitude_quaternion.h" +#include "./mavlink_msg_local_position_ned.h" +#include "./mavlink_msg_global_position_int.h" +#include "./mavlink_msg_rc_channels_scaled.h" +#include "./mavlink_msg_rc_channels_raw.h" +#include "./mavlink_msg_servo_output_raw.h" +#include "./mavlink_msg_mission_request_partial_list.h" +#include "./mavlink_msg_mission_write_partial_list.h" +#include "./mavlink_msg_mission_item.h" +#include "./mavlink_msg_mission_request.h" +#include "./mavlink_msg_mission_set_current.h" +#include "./mavlink_msg_mission_current.h" +#include "./mavlink_msg_mission_request_list.h" +#include "./mavlink_msg_mission_count.h" +#include "./mavlink_msg_mission_clear_all.h" +#include "./mavlink_msg_mission_item_reached.h" +#include "./mavlink_msg_mission_ack.h" +#include "./mavlink_msg_set_gps_global_origin.h" +#include "./mavlink_msg_gps_global_origin.h" +#include "./mavlink_msg_set_local_position_setpoint.h" +#include "./mavlink_msg_local_position_setpoint.h" +#include "./mavlink_msg_global_position_setpoint_int.h" +#include "./mavlink_msg_set_global_position_setpoint_int.h" +#include "./mavlink_msg_safety_set_allowed_area.h" +#include "./mavlink_msg_safety_allowed_area.h" +#include "./mavlink_msg_set_roll_pitch_yaw_thrust.h" +#include "./mavlink_msg_set_roll_pitch_yaw_speed_thrust.h" +#include "./mavlink_msg_roll_pitch_yaw_thrust_setpoint.h" +#include "./mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint.h" +#include "./mavlink_msg_set_quad_motors_setpoint.h" +#include "./mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust.h" +#include "./mavlink_msg_nav_controller_output.h" +#include "./mavlink_msg_state_correction.h" +#include "./mavlink_msg_request_data_stream.h" +#include "./mavlink_msg_data_stream.h" +#include "./mavlink_msg_manual_control.h" +#include "./mavlink_msg_rc_channels_override.h" +#include "./mavlink_msg_vfr_hud.h" +#include "./mavlink_msg_command_long.h" +#include "./mavlink_msg_command_ack.h" +#include "./mavlink_msg_local_position_ned_system_global_offset.h" +#include "./mavlink_msg_hil_state.h" +#include "./mavlink_msg_hil_controls.h" +#include "./mavlink_msg_hil_rc_inputs_raw.h" +#include "./mavlink_msg_optical_flow.h" +#include "./mavlink_msg_global_vision_position_estimate.h" +#include "./mavlink_msg_vision_position_estimate.h" +#include "./mavlink_msg_vision_speed_estimate.h" +#include "./mavlink_msg_vicon_position_estimate.h" +#include "./mavlink_msg_memory_vect.h" +#include "./mavlink_msg_debug_vect.h" +#include "./mavlink_msg_named_value_float.h" +#include "./mavlink_msg_named_value_int.h" +#include "./mavlink_msg_statustext.h" +#include "./mavlink_msg_debug.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // COMMON_H diff --git a/mavlink/include/mavlink/v1.0/common/mavlink.h b/mavlink/include/mavlink/v1.0/common/mavlink.h new file mode 100644 index 0000000000..17b7329709 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink.h @@ -0,0 +1,27 @@ +/** @file + * @brief MAVLink comm protocol built from common.xml + * @see http://pixhawk.ethz.ch/software/mavlink + */ +#ifndef MAVLINK_H +#define MAVLINK_H + +#ifndef MAVLINK_STX +#define MAVLINK_STX 254 +#endif + +#ifndef MAVLINK_ENDIAN +#define MAVLINK_ENDIAN MAVLINK_LITTLE_ENDIAN +#endif + +#ifndef MAVLINK_ALIGNED_FIELDS +#define MAVLINK_ALIGNED_FIELDS 1 +#endif + +#ifndef MAVLINK_CRC_EXTRA +#define MAVLINK_CRC_EXTRA 1 +#endif + +#include "version.h" +#include "common.h" + +#endif // MAVLINK_H diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_attitude.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_attitude.h new file mode 100644 index 0000000000..9074a1d80f --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_attitude.h @@ -0,0 +1,276 @@ +// MESSAGE ATTITUDE PACKING + +#define MAVLINK_MSG_ID_ATTITUDE 30 + +typedef struct __mavlink_attitude_t +{ + uint32_t time_boot_ms; ///< Timestamp (milliseconds since system boot) + float roll; ///< Roll angle (rad) + float pitch; ///< Pitch angle (rad) + float yaw; ///< Yaw angle (rad) + float rollspeed; ///< Roll angular speed (rad/s) + float pitchspeed; ///< Pitch angular speed (rad/s) + float yawspeed; ///< Yaw angular speed (rad/s) +} mavlink_attitude_t; + +#define MAVLINK_MSG_ID_ATTITUDE_LEN 28 +#define MAVLINK_MSG_ID_30_LEN 28 + + + +#define MAVLINK_MESSAGE_INFO_ATTITUDE { \ + "ATTITUDE", \ + 7, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_attitude_t, time_boot_ms) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_attitude_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_attitude_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_attitude_t, yaw) }, \ + { "rollspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_attitude_t, rollspeed) }, \ + { "pitchspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_attitude_t, pitchspeed) }, \ + { "yawspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_attitude_t, yawspeed) }, \ + } \ +} + + +/** + * @brief Pack a attitude message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_attitude_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, float roll, float pitch, float yaw, float rollspeed, float pitchspeed, float yawspeed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, roll); + _mav_put_float(buf, 8, pitch); + _mav_put_float(buf, 12, yaw); + _mav_put_float(buf, 16, rollspeed); + _mav_put_float(buf, 20, pitchspeed); + _mav_put_float(buf, 24, yawspeed); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_attitude_t packet; + packet.time_boot_ms = time_boot_ms; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_ATTITUDE; + return mavlink_finalize_message(msg, system_id, component_id, 28, 39); +} + +/** + * @brief Pack a attitude message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_attitude_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,float roll,float pitch,float yaw,float rollspeed,float pitchspeed,float yawspeed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, roll); + _mav_put_float(buf, 8, pitch); + _mav_put_float(buf, 12, yaw); + _mav_put_float(buf, 16, rollspeed); + _mav_put_float(buf, 20, pitchspeed); + _mav_put_float(buf, 24, yawspeed); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_attitude_t packet; + packet.time_boot_ms = time_boot_ms; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_ATTITUDE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 28, 39); +} + +/** + * @brief Encode a attitude struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param attitude C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_attitude_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_attitude_t* attitude) +{ + return mavlink_msg_attitude_pack(system_id, component_id, msg, attitude->time_boot_ms, attitude->roll, attitude->pitch, attitude->yaw, attitude->rollspeed, attitude->pitchspeed, attitude->yawspeed); +} + +/** + * @brief Send a attitude message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_attitude_send(mavlink_channel_t chan, uint32_t time_boot_ms, float roll, float pitch, float yaw, float rollspeed, float pitchspeed, float yawspeed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, roll); + _mav_put_float(buf, 8, pitch); + _mav_put_float(buf, 12, yaw); + _mav_put_float(buf, 16, rollspeed); + _mav_put_float(buf, 20, pitchspeed); + _mav_put_float(buf, 24, yawspeed); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ATTITUDE, buf, 28, 39); +#else + mavlink_attitude_t packet; + packet.time_boot_ms = time_boot_ms; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ATTITUDE, (const char *)&packet, 28, 39); +#endif +} + +#endif + +// MESSAGE ATTITUDE UNPACKING + + +/** + * @brief Get field time_boot_ms from attitude message + * + * @return Timestamp (milliseconds since system boot) + */ +static inline uint32_t mavlink_msg_attitude_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field roll from attitude message + * + * @return Roll angle (rad) + */ +static inline float mavlink_msg_attitude_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field pitch from attitude message + * + * @return Pitch angle (rad) + */ +static inline float mavlink_msg_attitude_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field yaw from attitude message + * + * @return Yaw angle (rad) + */ +static inline float mavlink_msg_attitude_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field rollspeed from attitude message + * + * @return Roll angular speed (rad/s) + */ +static inline float mavlink_msg_attitude_get_rollspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field pitchspeed from attitude message + * + * @return Pitch angular speed (rad/s) + */ +static inline float mavlink_msg_attitude_get_pitchspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field yawspeed from attitude message + * + * @return Yaw angular speed (rad/s) + */ +static inline float mavlink_msg_attitude_get_yawspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Decode a attitude message into a struct + * + * @param msg The message to decode + * @param attitude C-struct to decode the message contents into + */ +static inline void mavlink_msg_attitude_decode(const mavlink_message_t* msg, mavlink_attitude_t* attitude) +{ +#if MAVLINK_NEED_BYTE_SWAP + attitude->time_boot_ms = mavlink_msg_attitude_get_time_boot_ms(msg); + attitude->roll = mavlink_msg_attitude_get_roll(msg); + attitude->pitch = mavlink_msg_attitude_get_pitch(msg); + attitude->yaw = mavlink_msg_attitude_get_yaw(msg); + attitude->rollspeed = mavlink_msg_attitude_get_rollspeed(msg); + attitude->pitchspeed = mavlink_msg_attitude_get_pitchspeed(msg); + attitude->yawspeed = mavlink_msg_attitude_get_yawspeed(msg); +#else + memcpy(attitude, _MAV_PAYLOAD(msg), 28); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_attitude_quaternion.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_attitude_quaternion.h new file mode 100644 index 0000000000..5560488655 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_attitude_quaternion.h @@ -0,0 +1,298 @@ +// MESSAGE ATTITUDE_QUATERNION PACKING + +#define MAVLINK_MSG_ID_ATTITUDE_QUATERNION 31 + +typedef struct __mavlink_attitude_quaternion_t +{ + uint32_t time_boot_ms; ///< Timestamp (milliseconds since system boot) + float q1; ///< Quaternion component 1 + float q2; ///< Quaternion component 2 + float q3; ///< Quaternion component 3 + float q4; ///< Quaternion component 4 + float rollspeed; ///< Roll angular speed (rad/s) + float pitchspeed; ///< Pitch angular speed (rad/s) + float yawspeed; ///< Yaw angular speed (rad/s) +} mavlink_attitude_quaternion_t; + +#define MAVLINK_MSG_ID_ATTITUDE_QUATERNION_LEN 32 +#define MAVLINK_MSG_ID_31_LEN 32 + + + +#define MAVLINK_MESSAGE_INFO_ATTITUDE_QUATERNION { \ + "ATTITUDE_QUATERNION", \ + 8, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_attitude_quaternion_t, time_boot_ms) }, \ + { "q1", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_attitude_quaternion_t, q1) }, \ + { "q2", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_attitude_quaternion_t, q2) }, \ + { "q3", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_attitude_quaternion_t, q3) }, \ + { "q4", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_attitude_quaternion_t, q4) }, \ + { "rollspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_attitude_quaternion_t, rollspeed) }, \ + { "pitchspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_attitude_quaternion_t, pitchspeed) }, \ + { "yawspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_attitude_quaternion_t, yawspeed) }, \ + } \ +} + + +/** + * @brief Pack a attitude_quaternion message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param q1 Quaternion component 1 + * @param q2 Quaternion component 2 + * @param q3 Quaternion component 3 + * @param q4 Quaternion component 4 + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_attitude_quaternion_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, float q1, float q2, float q3, float q4, float rollspeed, float pitchspeed, float yawspeed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, q1); + _mav_put_float(buf, 8, q2); + _mav_put_float(buf, 12, q3); + _mav_put_float(buf, 16, q4); + _mav_put_float(buf, 20, rollspeed); + _mav_put_float(buf, 24, pitchspeed); + _mav_put_float(buf, 28, yawspeed); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_attitude_quaternion_t packet; + packet.time_boot_ms = time_boot_ms; + packet.q1 = q1; + packet.q2 = q2; + packet.q3 = q3; + packet.q4 = q4; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_ATTITUDE_QUATERNION; + return mavlink_finalize_message(msg, system_id, component_id, 32, 246); +} + +/** + * @brief Pack a attitude_quaternion message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param q1 Quaternion component 1 + * @param q2 Quaternion component 2 + * @param q3 Quaternion component 3 + * @param q4 Quaternion component 4 + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_attitude_quaternion_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,float q1,float q2,float q3,float q4,float rollspeed,float pitchspeed,float yawspeed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, q1); + _mav_put_float(buf, 8, q2); + _mav_put_float(buf, 12, q3); + _mav_put_float(buf, 16, q4); + _mav_put_float(buf, 20, rollspeed); + _mav_put_float(buf, 24, pitchspeed); + _mav_put_float(buf, 28, yawspeed); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_attitude_quaternion_t packet; + packet.time_boot_ms = time_boot_ms; + packet.q1 = q1; + packet.q2 = q2; + packet.q3 = q3; + packet.q4 = q4; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_ATTITUDE_QUATERNION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32, 246); +} + +/** + * @brief Encode a attitude_quaternion struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param attitude_quaternion C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_attitude_quaternion_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_attitude_quaternion_t* attitude_quaternion) +{ + return mavlink_msg_attitude_quaternion_pack(system_id, component_id, msg, attitude_quaternion->time_boot_ms, attitude_quaternion->q1, attitude_quaternion->q2, attitude_quaternion->q3, attitude_quaternion->q4, attitude_quaternion->rollspeed, attitude_quaternion->pitchspeed, attitude_quaternion->yawspeed); +} + +/** + * @brief Send a attitude_quaternion message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param q1 Quaternion component 1 + * @param q2 Quaternion component 2 + * @param q3 Quaternion component 3 + * @param q4 Quaternion component 4 + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_attitude_quaternion_send(mavlink_channel_t chan, uint32_t time_boot_ms, float q1, float q2, float q3, float q4, float rollspeed, float pitchspeed, float yawspeed) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, q1); + _mav_put_float(buf, 8, q2); + _mav_put_float(buf, 12, q3); + _mav_put_float(buf, 16, q4); + _mav_put_float(buf, 20, rollspeed); + _mav_put_float(buf, 24, pitchspeed); + _mav_put_float(buf, 28, yawspeed); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ATTITUDE_QUATERNION, buf, 32, 246); +#else + mavlink_attitude_quaternion_t packet; + packet.time_boot_ms = time_boot_ms; + packet.q1 = q1; + packet.q2 = q2; + packet.q3 = q3; + packet.q4 = q4; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ATTITUDE_QUATERNION, (const char *)&packet, 32, 246); +#endif +} + +#endif + +// MESSAGE ATTITUDE_QUATERNION UNPACKING + + +/** + * @brief Get field time_boot_ms from attitude_quaternion message + * + * @return Timestamp (milliseconds since system boot) + */ +static inline uint32_t mavlink_msg_attitude_quaternion_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field q1 from attitude_quaternion message + * + * @return Quaternion component 1 + */ +static inline float mavlink_msg_attitude_quaternion_get_q1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field q2 from attitude_quaternion message + * + * @return Quaternion component 2 + */ +static inline float mavlink_msg_attitude_quaternion_get_q2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field q3 from attitude_quaternion message + * + * @return Quaternion component 3 + */ +static inline float mavlink_msg_attitude_quaternion_get_q3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field q4 from attitude_quaternion message + * + * @return Quaternion component 4 + */ +static inline float mavlink_msg_attitude_quaternion_get_q4(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field rollspeed from attitude_quaternion message + * + * @return Roll angular speed (rad/s) + */ +static inline float mavlink_msg_attitude_quaternion_get_rollspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field pitchspeed from attitude_quaternion message + * + * @return Pitch angular speed (rad/s) + */ +static inline float mavlink_msg_attitude_quaternion_get_pitchspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field yawspeed from attitude_quaternion message + * + * @return Yaw angular speed (rad/s) + */ +static inline float mavlink_msg_attitude_quaternion_get_yawspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Decode a attitude_quaternion message into a struct + * + * @param msg The message to decode + * @param attitude_quaternion C-struct to decode the message contents into + */ +static inline void mavlink_msg_attitude_quaternion_decode(const mavlink_message_t* msg, mavlink_attitude_quaternion_t* attitude_quaternion) +{ +#if MAVLINK_NEED_BYTE_SWAP + attitude_quaternion->time_boot_ms = mavlink_msg_attitude_quaternion_get_time_boot_ms(msg); + attitude_quaternion->q1 = mavlink_msg_attitude_quaternion_get_q1(msg); + attitude_quaternion->q2 = mavlink_msg_attitude_quaternion_get_q2(msg); + attitude_quaternion->q3 = mavlink_msg_attitude_quaternion_get_q3(msg); + attitude_quaternion->q4 = mavlink_msg_attitude_quaternion_get_q4(msg); + attitude_quaternion->rollspeed = mavlink_msg_attitude_quaternion_get_rollspeed(msg); + attitude_quaternion->pitchspeed = mavlink_msg_attitude_quaternion_get_pitchspeed(msg); + attitude_quaternion->yawspeed = mavlink_msg_attitude_quaternion_get_yawspeed(msg); +#else + memcpy(attitude_quaternion, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_auth_key.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_auth_key.h new file mode 100644 index 0000000000..baa119fde1 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_auth_key.h @@ -0,0 +1,144 @@ +// MESSAGE AUTH_KEY PACKING + +#define MAVLINK_MSG_ID_AUTH_KEY 7 + +typedef struct __mavlink_auth_key_t +{ + char key[32]; ///< key +} mavlink_auth_key_t; + +#define MAVLINK_MSG_ID_AUTH_KEY_LEN 32 +#define MAVLINK_MSG_ID_7_LEN 32 + +#define MAVLINK_MSG_AUTH_KEY_FIELD_KEY_LEN 32 + +#define MAVLINK_MESSAGE_INFO_AUTH_KEY { \ + "AUTH_KEY", \ + 1, \ + { { "key", NULL, MAVLINK_TYPE_CHAR, 32, 0, offsetof(mavlink_auth_key_t, key) }, \ + } \ +} + + +/** + * @brief Pack a auth_key message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param key key + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_auth_key_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const char *key) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + + _mav_put_char_array(buf, 0, key, 32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_auth_key_t packet; + + mav_array_memcpy(packet.key, key, sizeof(char)*32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_AUTH_KEY; + return mavlink_finalize_message(msg, system_id, component_id, 32, 119); +} + +/** + * @brief Pack a auth_key message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param key key + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_auth_key_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const char *key) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + + _mav_put_char_array(buf, 0, key, 32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_auth_key_t packet; + + mav_array_memcpy(packet.key, key, sizeof(char)*32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_AUTH_KEY; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32, 119); +} + +/** + * @brief Encode a auth_key struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param auth_key C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_auth_key_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_auth_key_t* auth_key) +{ + return mavlink_msg_auth_key_pack(system_id, component_id, msg, auth_key->key); +} + +/** + * @brief Send a auth_key message + * @param chan MAVLink channel to send the message + * + * @param key key + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_auth_key_send(mavlink_channel_t chan, const char *key) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + + _mav_put_char_array(buf, 0, key, 32); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AUTH_KEY, buf, 32, 119); +#else + mavlink_auth_key_t packet; + + mav_array_memcpy(packet.key, key, sizeof(char)*32); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AUTH_KEY, (const char *)&packet, 32, 119); +#endif +} + +#endif + +// MESSAGE AUTH_KEY UNPACKING + + +/** + * @brief Get field key from auth_key message + * + * @return key + */ +static inline uint16_t mavlink_msg_auth_key_get_key(const mavlink_message_t* msg, char *key) +{ + return _MAV_RETURN_char_array(msg, key, 32, 0); +} + +/** + * @brief Decode a auth_key message into a struct + * + * @param msg The message to decode + * @param auth_key C-struct to decode the message contents into + */ +static inline void mavlink_msg_auth_key_decode(const mavlink_message_t* msg, mavlink_auth_key_t* auth_key) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_auth_key_get_key(msg, auth_key->key); +#else + memcpy(auth_key, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_change_operator_control.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_change_operator_control.h new file mode 100644 index 0000000000..a558510084 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_change_operator_control.h @@ -0,0 +1,204 @@ +// MESSAGE CHANGE_OPERATOR_CONTROL PACKING + +#define MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL 5 + +typedef struct __mavlink_change_operator_control_t +{ + uint8_t target_system; ///< System the GCS requests control for + uint8_t control_request; ///< 0: request control of this MAV, 1: Release control of this MAV + uint8_t version; ///< 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. + char passkey[25]; ///< Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" +} mavlink_change_operator_control_t; + +#define MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_LEN 28 +#define MAVLINK_MSG_ID_5_LEN 28 + +#define MAVLINK_MSG_CHANGE_OPERATOR_CONTROL_FIELD_PASSKEY_LEN 25 + +#define MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL { \ + "CHANGE_OPERATOR_CONTROL", \ + 4, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_change_operator_control_t, target_system) }, \ + { "control_request", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_change_operator_control_t, control_request) }, \ + { "version", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_change_operator_control_t, version) }, \ + { "passkey", NULL, MAVLINK_TYPE_CHAR, 25, 3, offsetof(mavlink_change_operator_control_t, passkey) }, \ + } \ +} + + +/** + * @brief Pack a change_operator_control message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System the GCS requests control for + * @param control_request 0: request control of this MAV, 1: Release control of this MAV + * @param version 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. + * @param passkey Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_change_operator_control_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t control_request, uint8_t version, const char *passkey) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, control_request); + _mav_put_uint8_t(buf, 2, version); + _mav_put_char_array(buf, 3, passkey, 25); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_change_operator_control_t packet; + packet.target_system = target_system; + packet.control_request = control_request; + packet.version = version; + mav_array_memcpy(packet.passkey, passkey, sizeof(char)*25); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL; + return mavlink_finalize_message(msg, system_id, component_id, 28, 217); +} + +/** + * @brief Pack a change_operator_control message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System the GCS requests control for + * @param control_request 0: request control of this MAV, 1: Release control of this MAV + * @param version 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. + * @param passkey Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_change_operator_control_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t control_request,uint8_t version,const char *passkey) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, control_request); + _mav_put_uint8_t(buf, 2, version); + _mav_put_char_array(buf, 3, passkey, 25); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_change_operator_control_t packet; + packet.target_system = target_system; + packet.control_request = control_request; + packet.version = version; + mav_array_memcpy(packet.passkey, passkey, sizeof(char)*25); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 28, 217); +} + +/** + * @brief Encode a change_operator_control struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param change_operator_control C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_change_operator_control_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_change_operator_control_t* change_operator_control) +{ + return mavlink_msg_change_operator_control_pack(system_id, component_id, msg, change_operator_control->target_system, change_operator_control->control_request, change_operator_control->version, change_operator_control->passkey); +} + +/** + * @brief Send a change_operator_control message + * @param chan MAVLink channel to send the message + * + * @param target_system System the GCS requests control for + * @param control_request 0: request control of this MAV, 1: Release control of this MAV + * @param version 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. + * @param passkey Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_change_operator_control_send(mavlink_channel_t chan, uint8_t target_system, uint8_t control_request, uint8_t version, const char *passkey) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, control_request); + _mav_put_uint8_t(buf, 2, version); + _mav_put_char_array(buf, 3, passkey, 25); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL, buf, 28, 217); +#else + mavlink_change_operator_control_t packet; + packet.target_system = target_system; + packet.control_request = control_request; + packet.version = version; + mav_array_memcpy(packet.passkey, passkey, sizeof(char)*25); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL, (const char *)&packet, 28, 217); +#endif +} + +#endif + +// MESSAGE CHANGE_OPERATOR_CONTROL UNPACKING + + +/** + * @brief Get field target_system from change_operator_control message + * + * @return System the GCS requests control for + */ +static inline uint8_t mavlink_msg_change_operator_control_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field control_request from change_operator_control message + * + * @return 0: request control of this MAV, 1: Release control of this MAV + */ +static inline uint8_t mavlink_msg_change_operator_control_get_control_request(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field version from change_operator_control message + * + * @return 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. + */ +static inline uint8_t mavlink_msg_change_operator_control_get_version(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field passkey from change_operator_control message + * + * @return Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" + */ +static inline uint16_t mavlink_msg_change_operator_control_get_passkey(const mavlink_message_t* msg, char *passkey) +{ + return _MAV_RETURN_char_array(msg, passkey, 25, 3); +} + +/** + * @brief Decode a change_operator_control message into a struct + * + * @param msg The message to decode + * @param change_operator_control C-struct to decode the message contents into + */ +static inline void mavlink_msg_change_operator_control_decode(const mavlink_message_t* msg, mavlink_change_operator_control_t* change_operator_control) +{ +#if MAVLINK_NEED_BYTE_SWAP + change_operator_control->target_system = mavlink_msg_change_operator_control_get_target_system(msg); + change_operator_control->control_request = mavlink_msg_change_operator_control_get_control_request(msg); + change_operator_control->version = mavlink_msg_change_operator_control_get_version(msg); + mavlink_msg_change_operator_control_get_passkey(msg, change_operator_control->passkey); +#else + memcpy(change_operator_control, _MAV_PAYLOAD(msg), 28); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_change_operator_control_ack.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_change_operator_control_ack.h new file mode 100644 index 0000000000..1d89a0f787 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_change_operator_control_ack.h @@ -0,0 +1,188 @@ +// MESSAGE CHANGE_OPERATOR_CONTROL_ACK PACKING + +#define MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK 6 + +typedef struct __mavlink_change_operator_control_ack_t +{ + uint8_t gcs_system_id; ///< ID of the GCS this message + uint8_t control_request; ///< 0: request control of this MAV, 1: Release control of this MAV + uint8_t ack; ///< 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control +} mavlink_change_operator_control_ack_t; + +#define MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK_LEN 3 +#define MAVLINK_MSG_ID_6_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK { \ + "CHANGE_OPERATOR_CONTROL_ACK", \ + 3, \ + { { "gcs_system_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_change_operator_control_ack_t, gcs_system_id) }, \ + { "control_request", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_change_operator_control_ack_t, control_request) }, \ + { "ack", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_change_operator_control_ack_t, ack) }, \ + } \ +} + + +/** + * @brief Pack a change_operator_control_ack message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param gcs_system_id ID of the GCS this message + * @param control_request 0: request control of this MAV, 1: Release control of this MAV + * @param ack 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_change_operator_control_ack_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t gcs_system_id, uint8_t control_request, uint8_t ack) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, gcs_system_id); + _mav_put_uint8_t(buf, 1, control_request); + _mav_put_uint8_t(buf, 2, ack); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_change_operator_control_ack_t packet; + packet.gcs_system_id = gcs_system_id; + packet.control_request = control_request; + packet.ack = ack; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK; + return mavlink_finalize_message(msg, system_id, component_id, 3, 104); +} + +/** + * @brief Pack a change_operator_control_ack message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param gcs_system_id ID of the GCS this message + * @param control_request 0: request control of this MAV, 1: Release control of this MAV + * @param ack 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_change_operator_control_ack_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t gcs_system_id,uint8_t control_request,uint8_t ack) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, gcs_system_id); + _mav_put_uint8_t(buf, 1, control_request); + _mav_put_uint8_t(buf, 2, ack); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_change_operator_control_ack_t packet; + packet.gcs_system_id = gcs_system_id; + packet.control_request = control_request; + packet.ack = ack; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3, 104); +} + +/** + * @brief Encode a change_operator_control_ack struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param change_operator_control_ack C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_change_operator_control_ack_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_change_operator_control_ack_t* change_operator_control_ack) +{ + return mavlink_msg_change_operator_control_ack_pack(system_id, component_id, msg, change_operator_control_ack->gcs_system_id, change_operator_control_ack->control_request, change_operator_control_ack->ack); +} + +/** + * @brief Send a change_operator_control_ack message + * @param chan MAVLink channel to send the message + * + * @param gcs_system_id ID of the GCS this message + * @param control_request 0: request control of this MAV, 1: Release control of this MAV + * @param ack 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_change_operator_control_ack_send(mavlink_channel_t chan, uint8_t gcs_system_id, uint8_t control_request, uint8_t ack) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, gcs_system_id); + _mav_put_uint8_t(buf, 1, control_request); + _mav_put_uint8_t(buf, 2, ack); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK, buf, 3, 104); +#else + mavlink_change_operator_control_ack_t packet; + packet.gcs_system_id = gcs_system_id; + packet.control_request = control_request; + packet.ack = ack; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK, (const char *)&packet, 3, 104); +#endif +} + +#endif + +// MESSAGE CHANGE_OPERATOR_CONTROL_ACK UNPACKING + + +/** + * @brief Get field gcs_system_id from change_operator_control_ack message + * + * @return ID of the GCS this message + */ +static inline uint8_t mavlink_msg_change_operator_control_ack_get_gcs_system_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field control_request from change_operator_control_ack message + * + * @return 0: request control of this MAV, 1: Release control of this MAV + */ +static inline uint8_t mavlink_msg_change_operator_control_ack_get_control_request(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field ack from change_operator_control_ack message + * + * @return 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control + */ +static inline uint8_t mavlink_msg_change_operator_control_ack_get_ack(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a change_operator_control_ack message into a struct + * + * @param msg The message to decode + * @param change_operator_control_ack C-struct to decode the message contents into + */ +static inline void mavlink_msg_change_operator_control_ack_decode(const mavlink_message_t* msg, mavlink_change_operator_control_ack_t* change_operator_control_ack) +{ +#if MAVLINK_NEED_BYTE_SWAP + change_operator_control_ack->gcs_system_id = mavlink_msg_change_operator_control_ack_get_gcs_system_id(msg); + change_operator_control_ack->control_request = mavlink_msg_change_operator_control_ack_get_control_request(msg); + change_operator_control_ack->ack = mavlink_msg_change_operator_control_ack_get_ack(msg); +#else + memcpy(change_operator_control_ack, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_command_ack.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_command_ack.h new file mode 100644 index 0000000000..df6e9b9e3b --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_command_ack.h @@ -0,0 +1,166 @@ +// MESSAGE COMMAND_ACK PACKING + +#define MAVLINK_MSG_ID_COMMAND_ACK 77 + +typedef struct __mavlink_command_ack_t +{ + uint16_t command; ///< Command ID, as defined by MAV_CMD enum. + uint8_t result; ///< See MAV_RESULT enum +} mavlink_command_ack_t; + +#define MAVLINK_MSG_ID_COMMAND_ACK_LEN 3 +#define MAVLINK_MSG_ID_77_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_COMMAND_ACK { \ + "COMMAND_ACK", \ + 2, \ + { { "command", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_command_ack_t, command) }, \ + { "result", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_command_ack_t, result) }, \ + } \ +} + + +/** + * @brief Pack a command_ack message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param command Command ID, as defined by MAV_CMD enum. + * @param result See MAV_RESULT enum + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_command_ack_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t command, uint8_t result) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, command); + _mav_put_uint8_t(buf, 2, result); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_command_ack_t packet; + packet.command = command; + packet.result = result; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_COMMAND_ACK; + return mavlink_finalize_message(msg, system_id, component_id, 3, 143); +} + +/** + * @brief Pack a command_ack message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param command Command ID, as defined by MAV_CMD enum. + * @param result See MAV_RESULT enum + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_command_ack_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t command,uint8_t result) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, command); + _mav_put_uint8_t(buf, 2, result); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_command_ack_t packet; + packet.command = command; + packet.result = result; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_COMMAND_ACK; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3, 143); +} + +/** + * @brief Encode a command_ack struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param command_ack C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_command_ack_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_command_ack_t* command_ack) +{ + return mavlink_msg_command_ack_pack(system_id, component_id, msg, command_ack->command, command_ack->result); +} + +/** + * @brief Send a command_ack message + * @param chan MAVLink channel to send the message + * + * @param command Command ID, as defined by MAV_CMD enum. + * @param result See MAV_RESULT enum + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_command_ack_send(mavlink_channel_t chan, uint16_t command, uint8_t result) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, command); + _mav_put_uint8_t(buf, 2, result); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_COMMAND_ACK, buf, 3, 143); +#else + mavlink_command_ack_t packet; + packet.command = command; + packet.result = result; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_COMMAND_ACK, (const char *)&packet, 3, 143); +#endif +} + +#endif + +// MESSAGE COMMAND_ACK UNPACKING + + +/** + * @brief Get field command from command_ack message + * + * @return Command ID, as defined by MAV_CMD enum. + */ +static inline uint16_t mavlink_msg_command_ack_get_command(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field result from command_ack message + * + * @return See MAV_RESULT enum + */ +static inline uint8_t mavlink_msg_command_ack_get_result(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a command_ack message into a struct + * + * @param msg The message to decode + * @param command_ack C-struct to decode the message contents into + */ +static inline void mavlink_msg_command_ack_decode(const mavlink_message_t* msg, mavlink_command_ack_t* command_ack) +{ +#if MAVLINK_NEED_BYTE_SWAP + command_ack->command = mavlink_msg_command_ack_get_command(msg); + command_ack->result = mavlink_msg_command_ack_get_result(msg); +#else + memcpy(command_ack, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_command_long.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_command_long.h new file mode 100644 index 0000000000..54ca77eaa2 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_command_long.h @@ -0,0 +1,364 @@ +// MESSAGE COMMAND_LONG PACKING + +#define MAVLINK_MSG_ID_COMMAND_LONG 76 + +typedef struct __mavlink_command_long_t +{ + float param1; ///< Parameter 1, as defined by MAV_CMD enum. + float param2; ///< Parameter 2, as defined by MAV_CMD enum. + float param3; ///< Parameter 3, as defined by MAV_CMD enum. + float param4; ///< Parameter 4, as defined by MAV_CMD enum. + float param5; ///< Parameter 5, as defined by MAV_CMD enum. + float param6; ///< Parameter 6, as defined by MAV_CMD enum. + float param7; ///< Parameter 7, as defined by MAV_CMD enum. + uint16_t command; ///< Command ID, as defined by MAV_CMD enum. + uint8_t target_system; ///< System which should execute the command + uint8_t target_component; ///< Component which should execute the command, 0 for all components + uint8_t confirmation; ///< 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) +} mavlink_command_long_t; + +#define MAVLINK_MSG_ID_COMMAND_LONG_LEN 33 +#define MAVLINK_MSG_ID_76_LEN 33 + + + +#define MAVLINK_MESSAGE_INFO_COMMAND_LONG { \ + "COMMAND_LONG", \ + 11, \ + { { "param1", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_command_long_t, param1) }, \ + { "param2", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_command_long_t, param2) }, \ + { "param3", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_command_long_t, param3) }, \ + { "param4", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_command_long_t, param4) }, \ + { "param5", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_command_long_t, param5) }, \ + { "param6", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_command_long_t, param6) }, \ + { "param7", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_command_long_t, param7) }, \ + { "command", NULL, MAVLINK_TYPE_UINT16_T, 0, 28, offsetof(mavlink_command_long_t, command) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 30, offsetof(mavlink_command_long_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 31, offsetof(mavlink_command_long_t, target_component) }, \ + { "confirmation", NULL, MAVLINK_TYPE_UINT8_T, 0, 32, offsetof(mavlink_command_long_t, confirmation) }, \ + } \ +} + + +/** + * @brief Pack a command_long message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System which should execute the command + * @param target_component Component which should execute the command, 0 for all components + * @param command Command ID, as defined by MAV_CMD enum. + * @param confirmation 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) + * @param param1 Parameter 1, as defined by MAV_CMD enum. + * @param param2 Parameter 2, as defined by MAV_CMD enum. + * @param param3 Parameter 3, as defined by MAV_CMD enum. + * @param param4 Parameter 4, as defined by MAV_CMD enum. + * @param param5 Parameter 5, as defined by MAV_CMD enum. + * @param param6 Parameter 6, as defined by MAV_CMD enum. + * @param param7 Parameter 7, as defined by MAV_CMD enum. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_command_long_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint16_t command, uint8_t confirmation, float param1, float param2, float param3, float param4, float param5, float param6, float param7) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[33]; + _mav_put_float(buf, 0, param1); + _mav_put_float(buf, 4, param2); + _mav_put_float(buf, 8, param3); + _mav_put_float(buf, 12, param4); + _mav_put_float(buf, 16, param5); + _mav_put_float(buf, 20, param6); + _mav_put_float(buf, 24, param7); + _mav_put_uint16_t(buf, 28, command); + _mav_put_uint8_t(buf, 30, target_system); + _mav_put_uint8_t(buf, 31, target_component); + _mav_put_uint8_t(buf, 32, confirmation); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 33); +#else + mavlink_command_long_t packet; + packet.param1 = param1; + packet.param2 = param2; + packet.param3 = param3; + packet.param4 = param4; + packet.param5 = param5; + packet.param6 = param6; + packet.param7 = param7; + packet.command = command; + packet.target_system = target_system; + packet.target_component = target_component; + packet.confirmation = confirmation; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 33); +#endif + + msg->msgid = MAVLINK_MSG_ID_COMMAND_LONG; + return mavlink_finalize_message(msg, system_id, component_id, 33, 152); +} + +/** + * @brief Pack a command_long message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System which should execute the command + * @param target_component Component which should execute the command, 0 for all components + * @param command Command ID, as defined by MAV_CMD enum. + * @param confirmation 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) + * @param param1 Parameter 1, as defined by MAV_CMD enum. + * @param param2 Parameter 2, as defined by MAV_CMD enum. + * @param param3 Parameter 3, as defined by MAV_CMD enum. + * @param param4 Parameter 4, as defined by MAV_CMD enum. + * @param param5 Parameter 5, as defined by MAV_CMD enum. + * @param param6 Parameter 6, as defined by MAV_CMD enum. + * @param param7 Parameter 7, as defined by MAV_CMD enum. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_command_long_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint16_t command,uint8_t confirmation,float param1,float param2,float param3,float param4,float param5,float param6,float param7) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[33]; + _mav_put_float(buf, 0, param1); + _mav_put_float(buf, 4, param2); + _mav_put_float(buf, 8, param3); + _mav_put_float(buf, 12, param4); + _mav_put_float(buf, 16, param5); + _mav_put_float(buf, 20, param6); + _mav_put_float(buf, 24, param7); + _mav_put_uint16_t(buf, 28, command); + _mav_put_uint8_t(buf, 30, target_system); + _mav_put_uint8_t(buf, 31, target_component); + _mav_put_uint8_t(buf, 32, confirmation); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 33); +#else + mavlink_command_long_t packet; + packet.param1 = param1; + packet.param2 = param2; + packet.param3 = param3; + packet.param4 = param4; + packet.param5 = param5; + packet.param6 = param6; + packet.param7 = param7; + packet.command = command; + packet.target_system = target_system; + packet.target_component = target_component; + packet.confirmation = confirmation; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 33); +#endif + + msg->msgid = MAVLINK_MSG_ID_COMMAND_LONG; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 33, 152); +} + +/** + * @brief Encode a command_long struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param command_long C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_command_long_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_command_long_t* command_long) +{ + return mavlink_msg_command_long_pack(system_id, component_id, msg, command_long->target_system, command_long->target_component, command_long->command, command_long->confirmation, command_long->param1, command_long->param2, command_long->param3, command_long->param4, command_long->param5, command_long->param6, command_long->param7); +} + +/** + * @brief Send a command_long message + * @param chan MAVLink channel to send the message + * + * @param target_system System which should execute the command + * @param target_component Component which should execute the command, 0 for all components + * @param command Command ID, as defined by MAV_CMD enum. + * @param confirmation 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) + * @param param1 Parameter 1, as defined by MAV_CMD enum. + * @param param2 Parameter 2, as defined by MAV_CMD enum. + * @param param3 Parameter 3, as defined by MAV_CMD enum. + * @param param4 Parameter 4, as defined by MAV_CMD enum. + * @param param5 Parameter 5, as defined by MAV_CMD enum. + * @param param6 Parameter 6, as defined by MAV_CMD enum. + * @param param7 Parameter 7, as defined by MAV_CMD enum. + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_command_long_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint16_t command, uint8_t confirmation, float param1, float param2, float param3, float param4, float param5, float param6, float param7) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[33]; + _mav_put_float(buf, 0, param1); + _mav_put_float(buf, 4, param2); + _mav_put_float(buf, 8, param3); + _mav_put_float(buf, 12, param4); + _mav_put_float(buf, 16, param5); + _mav_put_float(buf, 20, param6); + _mav_put_float(buf, 24, param7); + _mav_put_uint16_t(buf, 28, command); + _mav_put_uint8_t(buf, 30, target_system); + _mav_put_uint8_t(buf, 31, target_component); + _mav_put_uint8_t(buf, 32, confirmation); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_COMMAND_LONG, buf, 33, 152); +#else + mavlink_command_long_t packet; + packet.param1 = param1; + packet.param2 = param2; + packet.param3 = param3; + packet.param4 = param4; + packet.param5 = param5; + packet.param6 = param6; + packet.param7 = param7; + packet.command = command; + packet.target_system = target_system; + packet.target_component = target_component; + packet.confirmation = confirmation; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_COMMAND_LONG, (const char *)&packet, 33, 152); +#endif +} + +#endif + +// MESSAGE COMMAND_LONG UNPACKING + + +/** + * @brief Get field target_system from command_long message + * + * @return System which should execute the command + */ +static inline uint8_t mavlink_msg_command_long_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 30); +} + +/** + * @brief Get field target_component from command_long message + * + * @return Component which should execute the command, 0 for all components + */ +static inline uint8_t mavlink_msg_command_long_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 31); +} + +/** + * @brief Get field command from command_long message + * + * @return Command ID, as defined by MAV_CMD enum. + */ +static inline uint16_t mavlink_msg_command_long_get_command(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 28); +} + +/** + * @brief Get field confirmation from command_long message + * + * @return 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) + */ +static inline uint8_t mavlink_msg_command_long_get_confirmation(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 32); +} + +/** + * @brief Get field param1 from command_long message + * + * @return Parameter 1, as defined by MAV_CMD enum. + */ +static inline float mavlink_msg_command_long_get_param1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field param2 from command_long message + * + * @return Parameter 2, as defined by MAV_CMD enum. + */ +static inline float mavlink_msg_command_long_get_param2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field param3 from command_long message + * + * @return Parameter 3, as defined by MAV_CMD enum. + */ +static inline float mavlink_msg_command_long_get_param3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field param4 from command_long message + * + * @return Parameter 4, as defined by MAV_CMD enum. + */ +static inline float mavlink_msg_command_long_get_param4(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field param5 from command_long message + * + * @return Parameter 5, as defined by MAV_CMD enum. + */ +static inline float mavlink_msg_command_long_get_param5(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field param6 from command_long message + * + * @return Parameter 6, as defined by MAV_CMD enum. + */ +static inline float mavlink_msg_command_long_get_param6(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field param7 from command_long message + * + * @return Parameter 7, as defined by MAV_CMD enum. + */ +static inline float mavlink_msg_command_long_get_param7(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Decode a command_long message into a struct + * + * @param msg The message to decode + * @param command_long C-struct to decode the message contents into + */ +static inline void mavlink_msg_command_long_decode(const mavlink_message_t* msg, mavlink_command_long_t* command_long) +{ +#if MAVLINK_NEED_BYTE_SWAP + command_long->param1 = mavlink_msg_command_long_get_param1(msg); + command_long->param2 = mavlink_msg_command_long_get_param2(msg); + command_long->param3 = mavlink_msg_command_long_get_param3(msg); + command_long->param4 = mavlink_msg_command_long_get_param4(msg); + command_long->param5 = mavlink_msg_command_long_get_param5(msg); + command_long->param6 = mavlink_msg_command_long_get_param6(msg); + command_long->param7 = mavlink_msg_command_long_get_param7(msg); + command_long->command = mavlink_msg_command_long_get_command(msg); + command_long->target_system = mavlink_msg_command_long_get_target_system(msg); + command_long->target_component = mavlink_msg_command_long_get_target_component(msg); + command_long->confirmation = mavlink_msg_command_long_get_confirmation(msg); +#else + memcpy(command_long, _MAV_PAYLOAD(msg), 33); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_data_stream.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_data_stream.h new file mode 100644 index 0000000000..e5ec290452 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_data_stream.h @@ -0,0 +1,188 @@ +// MESSAGE DATA_STREAM PACKING + +#define MAVLINK_MSG_ID_DATA_STREAM 67 + +typedef struct __mavlink_data_stream_t +{ + uint16_t message_rate; ///< The requested interval between two messages of this type + uint8_t stream_id; ///< The ID of the requested data stream + uint8_t on_off; ///< 1 stream is enabled, 0 stream is stopped. +} mavlink_data_stream_t; + +#define MAVLINK_MSG_ID_DATA_STREAM_LEN 4 +#define MAVLINK_MSG_ID_67_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_DATA_STREAM { \ + "DATA_STREAM", \ + 3, \ + { { "message_rate", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_data_stream_t, message_rate) }, \ + { "stream_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_data_stream_t, stream_id) }, \ + { "on_off", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_data_stream_t, on_off) }, \ + } \ +} + + +/** + * @brief Pack a data_stream message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param stream_id The ID of the requested data stream + * @param message_rate The requested interval between two messages of this type + * @param on_off 1 stream is enabled, 0 stream is stopped. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_data_stream_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t stream_id, uint16_t message_rate, uint8_t on_off) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, message_rate); + _mav_put_uint8_t(buf, 2, stream_id); + _mav_put_uint8_t(buf, 3, on_off); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_data_stream_t packet; + packet.message_rate = message_rate; + packet.stream_id = stream_id; + packet.on_off = on_off; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_DATA_STREAM; + return mavlink_finalize_message(msg, system_id, component_id, 4, 21); +} + +/** + * @brief Pack a data_stream message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param stream_id The ID of the requested data stream + * @param message_rate The requested interval between two messages of this type + * @param on_off 1 stream is enabled, 0 stream is stopped. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_data_stream_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t stream_id,uint16_t message_rate,uint8_t on_off) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, message_rate); + _mav_put_uint8_t(buf, 2, stream_id); + _mav_put_uint8_t(buf, 3, on_off); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_data_stream_t packet; + packet.message_rate = message_rate; + packet.stream_id = stream_id; + packet.on_off = on_off; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_DATA_STREAM; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4, 21); +} + +/** + * @brief Encode a data_stream struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param data_stream C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_data_stream_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_data_stream_t* data_stream) +{ + return mavlink_msg_data_stream_pack(system_id, component_id, msg, data_stream->stream_id, data_stream->message_rate, data_stream->on_off); +} + +/** + * @brief Send a data_stream message + * @param chan MAVLink channel to send the message + * + * @param stream_id The ID of the requested data stream + * @param message_rate The requested interval between two messages of this type + * @param on_off 1 stream is enabled, 0 stream is stopped. + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_data_stream_send(mavlink_channel_t chan, uint8_t stream_id, uint16_t message_rate, uint8_t on_off) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, message_rate); + _mav_put_uint8_t(buf, 2, stream_id); + _mav_put_uint8_t(buf, 3, on_off); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DATA_STREAM, buf, 4, 21); +#else + mavlink_data_stream_t packet; + packet.message_rate = message_rate; + packet.stream_id = stream_id; + packet.on_off = on_off; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DATA_STREAM, (const char *)&packet, 4, 21); +#endif +} + +#endif + +// MESSAGE DATA_STREAM UNPACKING + + +/** + * @brief Get field stream_id from data_stream message + * + * @return The ID of the requested data stream + */ +static inline uint8_t mavlink_msg_data_stream_get_stream_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field message_rate from data_stream message + * + * @return The requested interval between two messages of this type + */ +static inline uint16_t mavlink_msg_data_stream_get_message_rate(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field on_off from data_stream message + * + * @return 1 stream is enabled, 0 stream is stopped. + */ +static inline uint8_t mavlink_msg_data_stream_get_on_off(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Decode a data_stream message into a struct + * + * @param msg The message to decode + * @param data_stream C-struct to decode the message contents into + */ +static inline void mavlink_msg_data_stream_decode(const mavlink_message_t* msg, mavlink_data_stream_t* data_stream) +{ +#if MAVLINK_NEED_BYTE_SWAP + data_stream->message_rate = mavlink_msg_data_stream_get_message_rate(msg); + data_stream->stream_id = mavlink_msg_data_stream_get_stream_id(msg); + data_stream->on_off = mavlink_msg_data_stream_get_on_off(msg); +#else + memcpy(data_stream, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_debug.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_debug.h new file mode 100644 index 0000000000..5ff88e6a8a --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_debug.h @@ -0,0 +1,188 @@ +// MESSAGE DEBUG PACKING + +#define MAVLINK_MSG_ID_DEBUG 254 + +typedef struct __mavlink_debug_t +{ + uint32_t time_boot_ms; ///< Timestamp (milliseconds since system boot) + float value; ///< DEBUG value + uint8_t ind; ///< index of debug variable +} mavlink_debug_t; + +#define MAVLINK_MSG_ID_DEBUG_LEN 9 +#define MAVLINK_MSG_ID_254_LEN 9 + + + +#define MAVLINK_MESSAGE_INFO_DEBUG { \ + "DEBUG", \ + 3, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_debug_t, time_boot_ms) }, \ + { "value", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_debug_t, value) }, \ + { "ind", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_debug_t, ind) }, \ + } \ +} + + +/** + * @brief Pack a debug message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param ind index of debug variable + * @param value DEBUG value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_debug_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, uint8_t ind, float value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, value); + _mav_put_uint8_t(buf, 8, ind); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 9); +#else + mavlink_debug_t packet; + packet.time_boot_ms = time_boot_ms; + packet.value = value; + packet.ind = ind; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 9); +#endif + + msg->msgid = MAVLINK_MSG_ID_DEBUG; + return mavlink_finalize_message(msg, system_id, component_id, 9, 46); +} + +/** + * @brief Pack a debug message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param ind index of debug variable + * @param value DEBUG value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_debug_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,uint8_t ind,float value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, value); + _mav_put_uint8_t(buf, 8, ind); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 9); +#else + mavlink_debug_t packet; + packet.time_boot_ms = time_boot_ms; + packet.value = value; + packet.ind = ind; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 9); +#endif + + msg->msgid = MAVLINK_MSG_ID_DEBUG; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 9, 46); +} + +/** + * @brief Encode a debug struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param debug C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_debug_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_debug_t* debug) +{ + return mavlink_msg_debug_pack(system_id, component_id, msg, debug->time_boot_ms, debug->ind, debug->value); +} + +/** + * @brief Send a debug message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param ind index of debug variable + * @param value DEBUG value + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_debug_send(mavlink_channel_t chan, uint32_t time_boot_ms, uint8_t ind, float value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, value); + _mav_put_uint8_t(buf, 8, ind); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DEBUG, buf, 9, 46); +#else + mavlink_debug_t packet; + packet.time_boot_ms = time_boot_ms; + packet.value = value; + packet.ind = ind; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DEBUG, (const char *)&packet, 9, 46); +#endif +} + +#endif + +// MESSAGE DEBUG UNPACKING + + +/** + * @brief Get field time_boot_ms from debug message + * + * @return Timestamp (milliseconds since system boot) + */ +static inline uint32_t mavlink_msg_debug_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field ind from debug message + * + * @return index of debug variable + */ +static inline uint8_t mavlink_msg_debug_get_ind(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Get field value from debug message + * + * @return DEBUG value + */ +static inline float mavlink_msg_debug_get_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Decode a debug message into a struct + * + * @param msg The message to decode + * @param debug C-struct to decode the message contents into + */ +static inline void mavlink_msg_debug_decode(const mavlink_message_t* msg, mavlink_debug_t* debug) +{ +#if MAVLINK_NEED_BYTE_SWAP + debug->time_boot_ms = mavlink_msg_debug_get_time_boot_ms(msg); + debug->value = mavlink_msg_debug_get_value(msg); + debug->ind = mavlink_msg_debug_get_ind(msg); +#else + memcpy(debug, _MAV_PAYLOAD(msg), 9); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_debug_vect.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_debug_vect.h new file mode 100644 index 0000000000..0b443a0611 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_debug_vect.h @@ -0,0 +1,226 @@ +// MESSAGE DEBUG_VECT PACKING + +#define MAVLINK_MSG_ID_DEBUG_VECT 250 + +typedef struct __mavlink_debug_vect_t +{ + uint64_t time_usec; ///< Timestamp + float x; ///< x + float y; ///< y + float z; ///< z + char name[10]; ///< Name +} mavlink_debug_vect_t; + +#define MAVLINK_MSG_ID_DEBUG_VECT_LEN 30 +#define MAVLINK_MSG_ID_250_LEN 30 + +#define MAVLINK_MSG_DEBUG_VECT_FIELD_NAME_LEN 10 + +#define MAVLINK_MESSAGE_INFO_DEBUG_VECT { \ + "DEBUG_VECT", \ + 5, \ + { { "time_usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_debug_vect_t, time_usec) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_debug_vect_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_debug_vect_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_debug_vect_t, z) }, \ + { "name", NULL, MAVLINK_TYPE_CHAR, 10, 20, offsetof(mavlink_debug_vect_t, name) }, \ + } \ +} + + +/** + * @brief Pack a debug_vect message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param name Name + * @param time_usec Timestamp + * @param x x + * @param y y + * @param z z + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_debug_vect_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const char *name, uint64_t time_usec, float x, float y, float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_char_array(buf, 20, name, 10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 30); +#else + mavlink_debug_vect_t packet; + packet.time_usec = time_usec; + packet.x = x; + packet.y = y; + packet.z = z; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 30); +#endif + + msg->msgid = MAVLINK_MSG_ID_DEBUG_VECT; + return mavlink_finalize_message(msg, system_id, component_id, 30, 49); +} + +/** + * @brief Pack a debug_vect message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param name Name + * @param time_usec Timestamp + * @param x x + * @param y y + * @param z z + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_debug_vect_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const char *name,uint64_t time_usec,float x,float y,float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_char_array(buf, 20, name, 10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 30); +#else + mavlink_debug_vect_t packet; + packet.time_usec = time_usec; + packet.x = x; + packet.y = y; + packet.z = z; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 30); +#endif + + msg->msgid = MAVLINK_MSG_ID_DEBUG_VECT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 30, 49); +} + +/** + * @brief Encode a debug_vect struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param debug_vect C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_debug_vect_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_debug_vect_t* debug_vect) +{ + return mavlink_msg_debug_vect_pack(system_id, component_id, msg, debug_vect->name, debug_vect->time_usec, debug_vect->x, debug_vect->y, debug_vect->z); +} + +/** + * @brief Send a debug_vect message + * @param chan MAVLink channel to send the message + * + * @param name Name + * @param time_usec Timestamp + * @param x x + * @param y y + * @param z z + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_debug_vect_send(mavlink_channel_t chan, const char *name, uint64_t time_usec, float x, float y, float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_char_array(buf, 20, name, 10); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DEBUG_VECT, buf, 30, 49); +#else + mavlink_debug_vect_t packet; + packet.time_usec = time_usec; + packet.x = x; + packet.y = y; + packet.z = z; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DEBUG_VECT, (const char *)&packet, 30, 49); +#endif +} + +#endif + +// MESSAGE DEBUG_VECT UNPACKING + + +/** + * @brief Get field name from debug_vect message + * + * @return Name + */ +static inline uint16_t mavlink_msg_debug_vect_get_name(const mavlink_message_t* msg, char *name) +{ + return _MAV_RETURN_char_array(msg, name, 10, 20); +} + +/** + * @brief Get field time_usec from debug_vect message + * + * @return Timestamp + */ +static inline uint64_t mavlink_msg_debug_vect_get_time_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field x from debug_vect message + * + * @return x + */ +static inline float mavlink_msg_debug_vect_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field y from debug_vect message + * + * @return y + */ +static inline float mavlink_msg_debug_vect_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field z from debug_vect message + * + * @return z + */ +static inline float mavlink_msg_debug_vect_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Decode a debug_vect message into a struct + * + * @param msg The message to decode + * @param debug_vect C-struct to decode the message contents into + */ +static inline void mavlink_msg_debug_vect_decode(const mavlink_message_t* msg, mavlink_debug_vect_t* debug_vect) +{ +#if MAVLINK_NEED_BYTE_SWAP + debug_vect->time_usec = mavlink_msg_debug_vect_get_time_usec(msg); + debug_vect->x = mavlink_msg_debug_vect_get_x(msg); + debug_vect->y = mavlink_msg_debug_vect_get_y(msg); + debug_vect->z = mavlink_msg_debug_vect_get_z(msg); + mavlink_msg_debug_vect_get_name(msg, debug_vect->name); +#else + memcpy(debug_vect, _MAV_PAYLOAD(msg), 30); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_global_position_int.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_global_position_int.h new file mode 100644 index 0000000000..780f562c5b --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_global_position_int.h @@ -0,0 +1,320 @@ +// MESSAGE GLOBAL_POSITION_INT PACKING + +#define MAVLINK_MSG_ID_GLOBAL_POSITION_INT 33 + +typedef struct __mavlink_global_position_int_t +{ + uint32_t time_boot_ms; ///< Timestamp (milliseconds since system boot) + int32_t lat; ///< Latitude, expressed as * 1E7 + int32_t lon; ///< Longitude, expressed as * 1E7 + int32_t alt; ///< Altitude in meters, expressed as * 1000 (millimeters), above MSL + int32_t relative_alt; ///< Altitude above ground in meters, expressed as * 1000 (millimeters) + int16_t vx; ///< Ground X Speed (Latitude), expressed as m/s * 100 + int16_t vy; ///< Ground Y Speed (Longitude), expressed as m/s * 100 + int16_t vz; ///< Ground Z Speed (Altitude), expressed as m/s * 100 + uint16_t hdg; ///< Compass heading in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 +} mavlink_global_position_int_t; + +#define MAVLINK_MSG_ID_GLOBAL_POSITION_INT_LEN 28 +#define MAVLINK_MSG_ID_33_LEN 28 + + + +#define MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT { \ + "GLOBAL_POSITION_INT", \ + 9, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_global_position_int_t, time_boot_ms) }, \ + { "lat", NULL, MAVLINK_TYPE_INT32_T, 0, 4, offsetof(mavlink_global_position_int_t, lat) }, \ + { "lon", NULL, MAVLINK_TYPE_INT32_T, 0, 8, offsetof(mavlink_global_position_int_t, lon) }, \ + { "alt", NULL, MAVLINK_TYPE_INT32_T, 0, 12, offsetof(mavlink_global_position_int_t, alt) }, \ + { "relative_alt", NULL, MAVLINK_TYPE_INT32_T, 0, 16, offsetof(mavlink_global_position_int_t, relative_alt) }, \ + { "vx", NULL, MAVLINK_TYPE_INT16_T, 0, 20, offsetof(mavlink_global_position_int_t, vx) }, \ + { "vy", NULL, MAVLINK_TYPE_INT16_T, 0, 22, offsetof(mavlink_global_position_int_t, vy) }, \ + { "vz", NULL, MAVLINK_TYPE_INT16_T, 0, 24, offsetof(mavlink_global_position_int_t, vz) }, \ + { "hdg", NULL, MAVLINK_TYPE_UINT16_T, 0, 26, offsetof(mavlink_global_position_int_t, hdg) }, \ + } \ +} + + +/** + * @brief Pack a global_position_int message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param lat Latitude, expressed as * 1E7 + * @param lon Longitude, expressed as * 1E7 + * @param alt Altitude in meters, expressed as * 1000 (millimeters), above MSL + * @param relative_alt Altitude above ground in meters, expressed as * 1000 (millimeters) + * @param vx Ground X Speed (Latitude), expressed as m/s * 100 + * @param vy Ground Y Speed (Longitude), expressed as m/s * 100 + * @param vz Ground Z Speed (Altitude), expressed as m/s * 100 + * @param hdg Compass heading in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_global_position_int_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, int32_t lat, int32_t lon, int32_t alt, int32_t relative_alt, int16_t vx, int16_t vy, int16_t vz, uint16_t hdg) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_int32_t(buf, 4, lat); + _mav_put_int32_t(buf, 8, lon); + _mav_put_int32_t(buf, 12, alt); + _mav_put_int32_t(buf, 16, relative_alt); + _mav_put_int16_t(buf, 20, vx); + _mav_put_int16_t(buf, 22, vy); + _mav_put_int16_t(buf, 24, vz); + _mav_put_uint16_t(buf, 26, hdg); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_global_position_int_t packet; + packet.time_boot_ms = time_boot_ms; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.relative_alt = relative_alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + packet.hdg = hdg; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_GLOBAL_POSITION_INT; + return mavlink_finalize_message(msg, system_id, component_id, 28, 104); +} + +/** + * @brief Pack a global_position_int message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param lat Latitude, expressed as * 1E7 + * @param lon Longitude, expressed as * 1E7 + * @param alt Altitude in meters, expressed as * 1000 (millimeters), above MSL + * @param relative_alt Altitude above ground in meters, expressed as * 1000 (millimeters) + * @param vx Ground X Speed (Latitude), expressed as m/s * 100 + * @param vy Ground Y Speed (Longitude), expressed as m/s * 100 + * @param vz Ground Z Speed (Altitude), expressed as m/s * 100 + * @param hdg Compass heading in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_global_position_int_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,int32_t lat,int32_t lon,int32_t alt,int32_t relative_alt,int16_t vx,int16_t vy,int16_t vz,uint16_t hdg) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_int32_t(buf, 4, lat); + _mav_put_int32_t(buf, 8, lon); + _mav_put_int32_t(buf, 12, alt); + _mav_put_int32_t(buf, 16, relative_alt); + _mav_put_int16_t(buf, 20, vx); + _mav_put_int16_t(buf, 22, vy); + _mav_put_int16_t(buf, 24, vz); + _mav_put_uint16_t(buf, 26, hdg); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_global_position_int_t packet; + packet.time_boot_ms = time_boot_ms; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.relative_alt = relative_alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + packet.hdg = hdg; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_GLOBAL_POSITION_INT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 28, 104); +} + +/** + * @brief Encode a global_position_int struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param global_position_int C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_global_position_int_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_global_position_int_t* global_position_int) +{ + return mavlink_msg_global_position_int_pack(system_id, component_id, msg, global_position_int->time_boot_ms, global_position_int->lat, global_position_int->lon, global_position_int->alt, global_position_int->relative_alt, global_position_int->vx, global_position_int->vy, global_position_int->vz, global_position_int->hdg); +} + +/** + * @brief Send a global_position_int message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param lat Latitude, expressed as * 1E7 + * @param lon Longitude, expressed as * 1E7 + * @param alt Altitude in meters, expressed as * 1000 (millimeters), above MSL + * @param relative_alt Altitude above ground in meters, expressed as * 1000 (millimeters) + * @param vx Ground X Speed (Latitude), expressed as m/s * 100 + * @param vy Ground Y Speed (Longitude), expressed as m/s * 100 + * @param vz Ground Z Speed (Altitude), expressed as m/s * 100 + * @param hdg Compass heading in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_global_position_int_send(mavlink_channel_t chan, uint32_t time_boot_ms, int32_t lat, int32_t lon, int32_t alt, int32_t relative_alt, int16_t vx, int16_t vy, int16_t vz, uint16_t hdg) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_int32_t(buf, 4, lat); + _mav_put_int32_t(buf, 8, lon); + _mav_put_int32_t(buf, 12, alt); + _mav_put_int32_t(buf, 16, relative_alt); + _mav_put_int16_t(buf, 20, vx); + _mav_put_int16_t(buf, 22, vy); + _mav_put_int16_t(buf, 24, vz); + _mav_put_uint16_t(buf, 26, hdg); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GLOBAL_POSITION_INT, buf, 28, 104); +#else + mavlink_global_position_int_t packet; + packet.time_boot_ms = time_boot_ms; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.relative_alt = relative_alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + packet.hdg = hdg; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GLOBAL_POSITION_INT, (const char *)&packet, 28, 104); +#endif +} + +#endif + +// MESSAGE GLOBAL_POSITION_INT UNPACKING + + +/** + * @brief Get field time_boot_ms from global_position_int message + * + * @return Timestamp (milliseconds since system boot) + */ +static inline uint32_t mavlink_msg_global_position_int_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field lat from global_position_int message + * + * @return Latitude, expressed as * 1E7 + */ +static inline int32_t mavlink_msg_global_position_int_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 4); +} + +/** + * @brief Get field lon from global_position_int message + * + * @return Longitude, expressed as * 1E7 + */ +static inline int32_t mavlink_msg_global_position_int_get_lon(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 8); +} + +/** + * @brief Get field alt from global_position_int message + * + * @return Altitude in meters, expressed as * 1000 (millimeters), above MSL + */ +static inline int32_t mavlink_msg_global_position_int_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 12); +} + +/** + * @brief Get field relative_alt from global_position_int message + * + * @return Altitude above ground in meters, expressed as * 1000 (millimeters) + */ +static inline int32_t mavlink_msg_global_position_int_get_relative_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 16); +} + +/** + * @brief Get field vx from global_position_int message + * + * @return Ground X Speed (Latitude), expressed as m/s * 100 + */ +static inline int16_t mavlink_msg_global_position_int_get_vx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 20); +} + +/** + * @brief Get field vy from global_position_int message + * + * @return Ground Y Speed (Longitude), expressed as m/s * 100 + */ +static inline int16_t mavlink_msg_global_position_int_get_vy(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 22); +} + +/** + * @brief Get field vz from global_position_int message + * + * @return Ground Z Speed (Altitude), expressed as m/s * 100 + */ +static inline int16_t mavlink_msg_global_position_int_get_vz(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 24); +} + +/** + * @brief Get field hdg from global_position_int message + * + * @return Compass heading in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 + */ +static inline uint16_t mavlink_msg_global_position_int_get_hdg(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 26); +} + +/** + * @brief Decode a global_position_int message into a struct + * + * @param msg The message to decode + * @param global_position_int C-struct to decode the message contents into + */ +static inline void mavlink_msg_global_position_int_decode(const mavlink_message_t* msg, mavlink_global_position_int_t* global_position_int) +{ +#if MAVLINK_NEED_BYTE_SWAP + global_position_int->time_boot_ms = mavlink_msg_global_position_int_get_time_boot_ms(msg); + global_position_int->lat = mavlink_msg_global_position_int_get_lat(msg); + global_position_int->lon = mavlink_msg_global_position_int_get_lon(msg); + global_position_int->alt = mavlink_msg_global_position_int_get_alt(msg); + global_position_int->relative_alt = mavlink_msg_global_position_int_get_relative_alt(msg); + global_position_int->vx = mavlink_msg_global_position_int_get_vx(msg); + global_position_int->vy = mavlink_msg_global_position_int_get_vy(msg); + global_position_int->vz = mavlink_msg_global_position_int_get_vz(msg); + global_position_int->hdg = mavlink_msg_global_position_int_get_hdg(msg); +#else + memcpy(global_position_int, _MAV_PAYLOAD(msg), 28); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_global_position_setpoint_int.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_global_position_setpoint_int.h new file mode 100644 index 0000000000..853b85daeb --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_global_position_setpoint_int.h @@ -0,0 +1,232 @@ +// MESSAGE GLOBAL_POSITION_SETPOINT_INT PACKING + +#define MAVLINK_MSG_ID_GLOBAL_POSITION_SETPOINT_INT 52 + +typedef struct __mavlink_global_position_setpoint_int_t +{ + int32_t latitude; ///< WGS84 Latitude position in degrees * 1E7 + int32_t longitude; ///< WGS84 Longitude position in degrees * 1E7 + int32_t altitude; ///< WGS84 Altitude in meters * 1000 (positive for up) + int16_t yaw; ///< Desired yaw angle in degrees * 100 + uint8_t coordinate_frame; ///< Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT +} mavlink_global_position_setpoint_int_t; + +#define MAVLINK_MSG_ID_GLOBAL_POSITION_SETPOINT_INT_LEN 15 +#define MAVLINK_MSG_ID_52_LEN 15 + + + +#define MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_SETPOINT_INT { \ + "GLOBAL_POSITION_SETPOINT_INT", \ + 5, \ + { { "latitude", NULL, MAVLINK_TYPE_INT32_T, 0, 0, offsetof(mavlink_global_position_setpoint_int_t, latitude) }, \ + { "longitude", NULL, MAVLINK_TYPE_INT32_T, 0, 4, offsetof(mavlink_global_position_setpoint_int_t, longitude) }, \ + { "altitude", NULL, MAVLINK_TYPE_INT32_T, 0, 8, offsetof(mavlink_global_position_setpoint_int_t, altitude) }, \ + { "yaw", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_global_position_setpoint_int_t, yaw) }, \ + { "coordinate_frame", NULL, MAVLINK_TYPE_UINT8_T, 0, 14, offsetof(mavlink_global_position_setpoint_int_t, coordinate_frame) }, \ + } \ +} + + +/** + * @brief Pack a global_position_setpoint_int message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param coordinate_frame Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT + * @param latitude WGS84 Latitude position in degrees * 1E7 + * @param longitude WGS84 Longitude position in degrees * 1E7 + * @param altitude WGS84 Altitude in meters * 1000 (positive for up) + * @param yaw Desired yaw angle in degrees * 100 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_global_position_setpoint_int_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t coordinate_frame, int32_t latitude, int32_t longitude, int32_t altitude, int16_t yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + _mav_put_int16_t(buf, 12, yaw); + _mav_put_uint8_t(buf, 14, coordinate_frame); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 15); +#else + mavlink_global_position_setpoint_int_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + packet.yaw = yaw; + packet.coordinate_frame = coordinate_frame; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 15); +#endif + + msg->msgid = MAVLINK_MSG_ID_GLOBAL_POSITION_SETPOINT_INT; + return mavlink_finalize_message(msg, system_id, component_id, 15, 141); +} + +/** + * @brief Pack a global_position_setpoint_int message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param coordinate_frame Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT + * @param latitude WGS84 Latitude position in degrees * 1E7 + * @param longitude WGS84 Longitude position in degrees * 1E7 + * @param altitude WGS84 Altitude in meters * 1000 (positive for up) + * @param yaw Desired yaw angle in degrees * 100 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_global_position_setpoint_int_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t coordinate_frame,int32_t latitude,int32_t longitude,int32_t altitude,int16_t yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + _mav_put_int16_t(buf, 12, yaw); + _mav_put_uint8_t(buf, 14, coordinate_frame); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 15); +#else + mavlink_global_position_setpoint_int_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + packet.yaw = yaw; + packet.coordinate_frame = coordinate_frame; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 15); +#endif + + msg->msgid = MAVLINK_MSG_ID_GLOBAL_POSITION_SETPOINT_INT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 15, 141); +} + +/** + * @brief Encode a global_position_setpoint_int struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param global_position_setpoint_int C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_global_position_setpoint_int_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_global_position_setpoint_int_t* global_position_setpoint_int) +{ + return mavlink_msg_global_position_setpoint_int_pack(system_id, component_id, msg, global_position_setpoint_int->coordinate_frame, global_position_setpoint_int->latitude, global_position_setpoint_int->longitude, global_position_setpoint_int->altitude, global_position_setpoint_int->yaw); +} + +/** + * @brief Send a global_position_setpoint_int message + * @param chan MAVLink channel to send the message + * + * @param coordinate_frame Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT + * @param latitude WGS84 Latitude position in degrees * 1E7 + * @param longitude WGS84 Longitude position in degrees * 1E7 + * @param altitude WGS84 Altitude in meters * 1000 (positive for up) + * @param yaw Desired yaw angle in degrees * 100 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_global_position_setpoint_int_send(mavlink_channel_t chan, uint8_t coordinate_frame, int32_t latitude, int32_t longitude, int32_t altitude, int16_t yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + _mav_put_int16_t(buf, 12, yaw); + _mav_put_uint8_t(buf, 14, coordinate_frame); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GLOBAL_POSITION_SETPOINT_INT, buf, 15, 141); +#else + mavlink_global_position_setpoint_int_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + packet.yaw = yaw; + packet.coordinate_frame = coordinate_frame; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GLOBAL_POSITION_SETPOINT_INT, (const char *)&packet, 15, 141); +#endif +} + +#endif + +// MESSAGE GLOBAL_POSITION_SETPOINT_INT UNPACKING + + +/** + * @brief Get field coordinate_frame from global_position_setpoint_int message + * + * @return Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT + */ +static inline uint8_t mavlink_msg_global_position_setpoint_int_get_coordinate_frame(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 14); +} + +/** + * @brief Get field latitude from global_position_setpoint_int message + * + * @return WGS84 Latitude position in degrees * 1E7 + */ +static inline int32_t mavlink_msg_global_position_setpoint_int_get_latitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 0); +} + +/** + * @brief Get field longitude from global_position_setpoint_int message + * + * @return WGS84 Longitude position in degrees * 1E7 + */ +static inline int32_t mavlink_msg_global_position_setpoint_int_get_longitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 4); +} + +/** + * @brief Get field altitude from global_position_setpoint_int message + * + * @return WGS84 Altitude in meters * 1000 (positive for up) + */ +static inline int32_t mavlink_msg_global_position_setpoint_int_get_altitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 8); +} + +/** + * @brief Get field yaw from global_position_setpoint_int message + * + * @return Desired yaw angle in degrees * 100 + */ +static inline int16_t mavlink_msg_global_position_setpoint_int_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Decode a global_position_setpoint_int message into a struct + * + * @param msg The message to decode + * @param global_position_setpoint_int C-struct to decode the message contents into + */ +static inline void mavlink_msg_global_position_setpoint_int_decode(const mavlink_message_t* msg, mavlink_global_position_setpoint_int_t* global_position_setpoint_int) +{ +#if MAVLINK_NEED_BYTE_SWAP + global_position_setpoint_int->latitude = mavlink_msg_global_position_setpoint_int_get_latitude(msg); + global_position_setpoint_int->longitude = mavlink_msg_global_position_setpoint_int_get_longitude(msg); + global_position_setpoint_int->altitude = mavlink_msg_global_position_setpoint_int_get_altitude(msg); + global_position_setpoint_int->yaw = mavlink_msg_global_position_setpoint_int_get_yaw(msg); + global_position_setpoint_int->coordinate_frame = mavlink_msg_global_position_setpoint_int_get_coordinate_frame(msg); +#else + memcpy(global_position_setpoint_int, _MAV_PAYLOAD(msg), 15); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_global_vision_position_estimate.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_global_vision_position_estimate.h new file mode 100644 index 0000000000..e4617702bd --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_global_vision_position_estimate.h @@ -0,0 +1,276 @@ +// MESSAGE GLOBAL_VISION_POSITION_ESTIMATE PACKING + +#define MAVLINK_MSG_ID_GLOBAL_VISION_POSITION_ESTIMATE 101 + +typedef struct __mavlink_global_vision_position_estimate_t +{ + uint64_t usec; ///< Timestamp (milliseconds) + float x; ///< Global X position + float y; ///< Global Y position + float z; ///< Global Z position + float roll; ///< Roll angle in rad + float pitch; ///< Pitch angle in rad + float yaw; ///< Yaw angle in rad +} mavlink_global_vision_position_estimate_t; + +#define MAVLINK_MSG_ID_GLOBAL_VISION_POSITION_ESTIMATE_LEN 32 +#define MAVLINK_MSG_ID_101_LEN 32 + + + +#define MAVLINK_MESSAGE_INFO_GLOBAL_VISION_POSITION_ESTIMATE { \ + "GLOBAL_VISION_POSITION_ESTIMATE", \ + 7, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_global_vision_position_estimate_t, usec) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_global_vision_position_estimate_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_global_vision_position_estimate_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_global_vision_position_estimate_t, z) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_global_vision_position_estimate_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_global_vision_position_estimate_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_global_vision_position_estimate_t, yaw) }, \ + } \ +} + + +/** + * @brief Pack a global_vision_position_estimate message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_global_vision_position_estimate_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_global_vision_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_GLOBAL_VISION_POSITION_ESTIMATE; + return mavlink_finalize_message(msg, system_id, component_id, 32, 102); +} + +/** + * @brief Pack a global_vision_position_estimate message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_global_vision_position_estimate_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float x,float y,float z,float roll,float pitch,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_global_vision_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_GLOBAL_VISION_POSITION_ESTIMATE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32, 102); +} + +/** + * @brief Encode a global_vision_position_estimate struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param global_vision_position_estimate C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_global_vision_position_estimate_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_global_vision_position_estimate_t* global_vision_position_estimate) +{ + return mavlink_msg_global_vision_position_estimate_pack(system_id, component_id, msg, global_vision_position_estimate->usec, global_vision_position_estimate->x, global_vision_position_estimate->y, global_vision_position_estimate->z, global_vision_position_estimate->roll, global_vision_position_estimate->pitch, global_vision_position_estimate->yaw); +} + +/** + * @brief Send a global_vision_position_estimate message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_global_vision_position_estimate_send(mavlink_channel_t chan, uint64_t usec, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GLOBAL_VISION_POSITION_ESTIMATE, buf, 32, 102); +#else + mavlink_global_vision_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GLOBAL_VISION_POSITION_ESTIMATE, (const char *)&packet, 32, 102); +#endif +} + +#endif + +// MESSAGE GLOBAL_VISION_POSITION_ESTIMATE UNPACKING + + +/** + * @brief Get field usec from global_vision_position_estimate message + * + * @return Timestamp (milliseconds) + */ +static inline uint64_t mavlink_msg_global_vision_position_estimate_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field x from global_vision_position_estimate message + * + * @return Global X position + */ +static inline float mavlink_msg_global_vision_position_estimate_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field y from global_vision_position_estimate message + * + * @return Global Y position + */ +static inline float mavlink_msg_global_vision_position_estimate_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field z from global_vision_position_estimate message + * + * @return Global Z position + */ +static inline float mavlink_msg_global_vision_position_estimate_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field roll from global_vision_position_estimate message + * + * @return Roll angle in rad + */ +static inline float mavlink_msg_global_vision_position_estimate_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field pitch from global_vision_position_estimate message + * + * @return Pitch angle in rad + */ +static inline float mavlink_msg_global_vision_position_estimate_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field yaw from global_vision_position_estimate message + * + * @return Yaw angle in rad + */ +static inline float mavlink_msg_global_vision_position_estimate_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Decode a global_vision_position_estimate message into a struct + * + * @param msg The message to decode + * @param global_vision_position_estimate C-struct to decode the message contents into + */ +static inline void mavlink_msg_global_vision_position_estimate_decode(const mavlink_message_t* msg, mavlink_global_vision_position_estimate_t* global_vision_position_estimate) +{ +#if MAVLINK_NEED_BYTE_SWAP + global_vision_position_estimate->usec = mavlink_msg_global_vision_position_estimate_get_usec(msg); + global_vision_position_estimate->x = mavlink_msg_global_vision_position_estimate_get_x(msg); + global_vision_position_estimate->y = mavlink_msg_global_vision_position_estimate_get_y(msg); + global_vision_position_estimate->z = mavlink_msg_global_vision_position_estimate_get_z(msg); + global_vision_position_estimate->roll = mavlink_msg_global_vision_position_estimate_get_roll(msg); + global_vision_position_estimate->pitch = mavlink_msg_global_vision_position_estimate_get_pitch(msg); + global_vision_position_estimate->yaw = mavlink_msg_global_vision_position_estimate_get_yaw(msg); +#else + memcpy(global_vision_position_estimate, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_gps_global_origin.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_gps_global_origin.h new file mode 100644 index 0000000000..2084718b5d --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_gps_global_origin.h @@ -0,0 +1,188 @@ +// MESSAGE GPS_GLOBAL_ORIGIN PACKING + +#define MAVLINK_MSG_ID_GPS_GLOBAL_ORIGIN 49 + +typedef struct __mavlink_gps_global_origin_t +{ + int32_t latitude; ///< Latitude (WGS84), expressed as * 1E7 + int32_t longitude; ///< Longitude (WGS84), expressed as * 1E7 + int32_t altitude; ///< Altitude(WGS84), expressed as * 1000 +} mavlink_gps_global_origin_t; + +#define MAVLINK_MSG_ID_GPS_GLOBAL_ORIGIN_LEN 12 +#define MAVLINK_MSG_ID_49_LEN 12 + + + +#define MAVLINK_MESSAGE_INFO_GPS_GLOBAL_ORIGIN { \ + "GPS_GLOBAL_ORIGIN", \ + 3, \ + { { "latitude", NULL, MAVLINK_TYPE_INT32_T, 0, 0, offsetof(mavlink_gps_global_origin_t, latitude) }, \ + { "longitude", NULL, MAVLINK_TYPE_INT32_T, 0, 4, offsetof(mavlink_gps_global_origin_t, longitude) }, \ + { "altitude", NULL, MAVLINK_TYPE_INT32_T, 0, 8, offsetof(mavlink_gps_global_origin_t, altitude) }, \ + } \ +} + + +/** + * @brief Pack a gps_global_origin message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param latitude Latitude (WGS84), expressed as * 1E7 + * @param longitude Longitude (WGS84), expressed as * 1E7 + * @param altitude Altitude(WGS84), expressed as * 1000 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_global_origin_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + int32_t latitude, int32_t longitude, int32_t altitude) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_gps_global_origin_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_GLOBAL_ORIGIN; + return mavlink_finalize_message(msg, system_id, component_id, 12, 39); +} + +/** + * @brief Pack a gps_global_origin message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param latitude Latitude (WGS84), expressed as * 1E7 + * @param longitude Longitude (WGS84), expressed as * 1E7 + * @param altitude Altitude(WGS84), expressed as * 1000 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_global_origin_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + int32_t latitude,int32_t longitude,int32_t altitude) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_gps_global_origin_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_GLOBAL_ORIGIN; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12, 39); +} + +/** + * @brief Encode a gps_global_origin struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param gps_global_origin C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_gps_global_origin_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_gps_global_origin_t* gps_global_origin) +{ + return mavlink_msg_gps_global_origin_pack(system_id, component_id, msg, gps_global_origin->latitude, gps_global_origin->longitude, gps_global_origin->altitude); +} + +/** + * @brief Send a gps_global_origin message + * @param chan MAVLink channel to send the message + * + * @param latitude Latitude (WGS84), expressed as * 1E7 + * @param longitude Longitude (WGS84), expressed as * 1E7 + * @param altitude Altitude(WGS84), expressed as * 1000 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_gps_global_origin_send(mavlink_channel_t chan, int32_t latitude, int32_t longitude, int32_t altitude) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_GLOBAL_ORIGIN, buf, 12, 39); +#else + mavlink_gps_global_origin_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_GLOBAL_ORIGIN, (const char *)&packet, 12, 39); +#endif +} + +#endif + +// MESSAGE GPS_GLOBAL_ORIGIN UNPACKING + + +/** + * @brief Get field latitude from gps_global_origin message + * + * @return Latitude (WGS84), expressed as * 1E7 + */ +static inline int32_t mavlink_msg_gps_global_origin_get_latitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 0); +} + +/** + * @brief Get field longitude from gps_global_origin message + * + * @return Longitude (WGS84), expressed as * 1E7 + */ +static inline int32_t mavlink_msg_gps_global_origin_get_longitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 4); +} + +/** + * @brief Get field altitude from gps_global_origin message + * + * @return Altitude(WGS84), expressed as * 1000 + */ +static inline int32_t mavlink_msg_gps_global_origin_get_altitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 8); +} + +/** + * @brief Decode a gps_global_origin message into a struct + * + * @param msg The message to decode + * @param gps_global_origin C-struct to decode the message contents into + */ +static inline void mavlink_msg_gps_global_origin_decode(const mavlink_message_t* msg, mavlink_gps_global_origin_t* gps_global_origin) +{ +#if MAVLINK_NEED_BYTE_SWAP + gps_global_origin->latitude = mavlink_msg_gps_global_origin_get_latitude(msg); + gps_global_origin->longitude = mavlink_msg_gps_global_origin_get_longitude(msg); + gps_global_origin->altitude = mavlink_msg_gps_global_origin_get_altitude(msg); +#else + memcpy(gps_global_origin, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_gps_raw_int.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_gps_raw_int.h new file mode 100644 index 0000000000..57ec973763 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_gps_raw_int.h @@ -0,0 +1,342 @@ +// MESSAGE GPS_RAW_INT PACKING + +#define MAVLINK_MSG_ID_GPS_RAW_INT 24 + +typedef struct __mavlink_gps_raw_int_t +{ + uint64_t time_usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + int32_t lat; ///< Latitude in 1E7 degrees + int32_t lon; ///< Longitude in 1E7 degrees + int32_t alt; ///< Altitude in 1E3 meters (millimeters) above MSL + uint16_t eph; ///< GPS HDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 + uint16_t epv; ///< GPS VDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 + uint16_t vel; ///< GPS ground speed (m/s * 100). If unknown, set to: 65535 + uint16_t cog; ///< Course over ground (NOT heading, but direction of movement) in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 + uint8_t fix_type; ///< 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + uint8_t satellites_visible; ///< Number of satellites visible. If unknown, set to 255 +} mavlink_gps_raw_int_t; + +#define MAVLINK_MSG_ID_GPS_RAW_INT_LEN 30 +#define MAVLINK_MSG_ID_24_LEN 30 + + + +#define MAVLINK_MESSAGE_INFO_GPS_RAW_INT { \ + "GPS_RAW_INT", \ + 10, \ + { { "time_usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_gps_raw_int_t, time_usec) }, \ + { "lat", NULL, MAVLINK_TYPE_INT32_T, 0, 8, offsetof(mavlink_gps_raw_int_t, lat) }, \ + { "lon", NULL, MAVLINK_TYPE_INT32_T, 0, 12, offsetof(mavlink_gps_raw_int_t, lon) }, \ + { "alt", NULL, MAVLINK_TYPE_INT32_T, 0, 16, offsetof(mavlink_gps_raw_int_t, alt) }, \ + { "eph", NULL, MAVLINK_TYPE_UINT16_T, 0, 20, offsetof(mavlink_gps_raw_int_t, eph) }, \ + { "epv", NULL, MAVLINK_TYPE_UINT16_T, 0, 22, offsetof(mavlink_gps_raw_int_t, epv) }, \ + { "vel", NULL, MAVLINK_TYPE_UINT16_T, 0, 24, offsetof(mavlink_gps_raw_int_t, vel) }, \ + { "cog", NULL, MAVLINK_TYPE_UINT16_T, 0, 26, offsetof(mavlink_gps_raw_int_t, cog) }, \ + { "fix_type", NULL, MAVLINK_TYPE_UINT8_T, 0, 28, offsetof(mavlink_gps_raw_int_t, fix_type) }, \ + { "satellites_visible", NULL, MAVLINK_TYPE_UINT8_T, 0, 29, offsetof(mavlink_gps_raw_int_t, satellites_visible) }, \ + } \ +} + + +/** + * @brief Pack a gps_raw_int message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param fix_type 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + * @param lat Latitude in 1E7 degrees + * @param lon Longitude in 1E7 degrees + * @param alt Altitude in 1E3 meters (millimeters) above MSL + * @param eph GPS HDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 + * @param epv GPS VDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 + * @param vel GPS ground speed (m/s * 100). If unknown, set to: 65535 + * @param cog Course over ground (NOT heading, but direction of movement) in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 + * @param satellites_visible Number of satellites visible. If unknown, set to 255 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_raw_int_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time_usec, uint8_t fix_type, int32_t lat, int32_t lon, int32_t alt, uint16_t eph, uint16_t epv, uint16_t vel, uint16_t cog, uint8_t satellites_visible) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_int32_t(buf, 8, lat); + _mav_put_int32_t(buf, 12, lon); + _mav_put_int32_t(buf, 16, alt); + _mav_put_uint16_t(buf, 20, eph); + _mav_put_uint16_t(buf, 22, epv); + _mav_put_uint16_t(buf, 24, vel); + _mav_put_uint16_t(buf, 26, cog); + _mav_put_uint8_t(buf, 28, fix_type); + _mav_put_uint8_t(buf, 29, satellites_visible); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 30); +#else + mavlink_gps_raw_int_t packet; + packet.time_usec = time_usec; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.eph = eph; + packet.epv = epv; + packet.vel = vel; + packet.cog = cog; + packet.fix_type = fix_type; + packet.satellites_visible = satellites_visible; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 30); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_RAW_INT; + return mavlink_finalize_message(msg, system_id, component_id, 30, 24); +} + +/** + * @brief Pack a gps_raw_int message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param fix_type 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + * @param lat Latitude in 1E7 degrees + * @param lon Longitude in 1E7 degrees + * @param alt Altitude in 1E3 meters (millimeters) above MSL + * @param eph GPS HDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 + * @param epv GPS VDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 + * @param vel GPS ground speed (m/s * 100). If unknown, set to: 65535 + * @param cog Course over ground (NOT heading, but direction of movement) in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 + * @param satellites_visible Number of satellites visible. If unknown, set to 255 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_raw_int_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time_usec,uint8_t fix_type,int32_t lat,int32_t lon,int32_t alt,uint16_t eph,uint16_t epv,uint16_t vel,uint16_t cog,uint8_t satellites_visible) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_int32_t(buf, 8, lat); + _mav_put_int32_t(buf, 12, lon); + _mav_put_int32_t(buf, 16, alt); + _mav_put_uint16_t(buf, 20, eph); + _mav_put_uint16_t(buf, 22, epv); + _mav_put_uint16_t(buf, 24, vel); + _mav_put_uint16_t(buf, 26, cog); + _mav_put_uint8_t(buf, 28, fix_type); + _mav_put_uint8_t(buf, 29, satellites_visible); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 30); +#else + mavlink_gps_raw_int_t packet; + packet.time_usec = time_usec; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.eph = eph; + packet.epv = epv; + packet.vel = vel; + packet.cog = cog; + packet.fix_type = fix_type; + packet.satellites_visible = satellites_visible; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 30); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_RAW_INT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 30, 24); +} + +/** + * @brief Encode a gps_raw_int struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param gps_raw_int C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_gps_raw_int_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_gps_raw_int_t* gps_raw_int) +{ + return mavlink_msg_gps_raw_int_pack(system_id, component_id, msg, gps_raw_int->time_usec, gps_raw_int->fix_type, gps_raw_int->lat, gps_raw_int->lon, gps_raw_int->alt, gps_raw_int->eph, gps_raw_int->epv, gps_raw_int->vel, gps_raw_int->cog, gps_raw_int->satellites_visible); +} + +/** + * @brief Send a gps_raw_int message + * @param chan MAVLink channel to send the message + * + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param fix_type 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + * @param lat Latitude in 1E7 degrees + * @param lon Longitude in 1E7 degrees + * @param alt Altitude in 1E3 meters (millimeters) above MSL + * @param eph GPS HDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 + * @param epv GPS VDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 + * @param vel GPS ground speed (m/s * 100). If unknown, set to: 65535 + * @param cog Course over ground (NOT heading, but direction of movement) in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 + * @param satellites_visible Number of satellites visible. If unknown, set to 255 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_gps_raw_int_send(mavlink_channel_t chan, uint64_t time_usec, uint8_t fix_type, int32_t lat, int32_t lon, int32_t alt, uint16_t eph, uint16_t epv, uint16_t vel, uint16_t cog, uint8_t satellites_visible) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_int32_t(buf, 8, lat); + _mav_put_int32_t(buf, 12, lon); + _mav_put_int32_t(buf, 16, alt); + _mav_put_uint16_t(buf, 20, eph); + _mav_put_uint16_t(buf, 22, epv); + _mav_put_uint16_t(buf, 24, vel); + _mav_put_uint16_t(buf, 26, cog); + _mav_put_uint8_t(buf, 28, fix_type); + _mav_put_uint8_t(buf, 29, satellites_visible); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_RAW_INT, buf, 30, 24); +#else + mavlink_gps_raw_int_t packet; + packet.time_usec = time_usec; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.eph = eph; + packet.epv = epv; + packet.vel = vel; + packet.cog = cog; + packet.fix_type = fix_type; + packet.satellites_visible = satellites_visible; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_RAW_INT, (const char *)&packet, 30, 24); +#endif +} + +#endif + +// MESSAGE GPS_RAW_INT UNPACKING + + +/** + * @brief Get field time_usec from gps_raw_int message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_gps_raw_int_get_time_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field fix_type from gps_raw_int message + * + * @return 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. + */ +static inline uint8_t mavlink_msg_gps_raw_int_get_fix_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 28); +} + +/** + * @brief Get field lat from gps_raw_int message + * + * @return Latitude in 1E7 degrees + */ +static inline int32_t mavlink_msg_gps_raw_int_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 8); +} + +/** + * @brief Get field lon from gps_raw_int message + * + * @return Longitude in 1E7 degrees + */ +static inline int32_t mavlink_msg_gps_raw_int_get_lon(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 12); +} + +/** + * @brief Get field alt from gps_raw_int message + * + * @return Altitude in 1E3 meters (millimeters) above MSL + */ +static inline int32_t mavlink_msg_gps_raw_int_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 16); +} + +/** + * @brief Get field eph from gps_raw_int message + * + * @return GPS HDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 + */ +static inline uint16_t mavlink_msg_gps_raw_int_get_eph(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 20); +} + +/** + * @brief Get field epv from gps_raw_int message + * + * @return GPS VDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 + */ +static inline uint16_t mavlink_msg_gps_raw_int_get_epv(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 22); +} + +/** + * @brief Get field vel from gps_raw_int message + * + * @return GPS ground speed (m/s * 100). If unknown, set to: 65535 + */ +static inline uint16_t mavlink_msg_gps_raw_int_get_vel(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 24); +} + +/** + * @brief Get field cog from gps_raw_int message + * + * @return Course over ground (NOT heading, but direction of movement) in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 + */ +static inline uint16_t mavlink_msg_gps_raw_int_get_cog(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 26); +} + +/** + * @brief Get field satellites_visible from gps_raw_int message + * + * @return Number of satellites visible. If unknown, set to 255 + */ +static inline uint8_t mavlink_msg_gps_raw_int_get_satellites_visible(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 29); +} + +/** + * @brief Decode a gps_raw_int message into a struct + * + * @param msg The message to decode + * @param gps_raw_int C-struct to decode the message contents into + */ +static inline void mavlink_msg_gps_raw_int_decode(const mavlink_message_t* msg, mavlink_gps_raw_int_t* gps_raw_int) +{ +#if MAVLINK_NEED_BYTE_SWAP + gps_raw_int->time_usec = mavlink_msg_gps_raw_int_get_time_usec(msg); + gps_raw_int->lat = mavlink_msg_gps_raw_int_get_lat(msg); + gps_raw_int->lon = mavlink_msg_gps_raw_int_get_lon(msg); + gps_raw_int->alt = mavlink_msg_gps_raw_int_get_alt(msg); + gps_raw_int->eph = mavlink_msg_gps_raw_int_get_eph(msg); + gps_raw_int->epv = mavlink_msg_gps_raw_int_get_epv(msg); + gps_raw_int->vel = mavlink_msg_gps_raw_int_get_vel(msg); + gps_raw_int->cog = mavlink_msg_gps_raw_int_get_cog(msg); + gps_raw_int->fix_type = mavlink_msg_gps_raw_int_get_fix_type(msg); + gps_raw_int->satellites_visible = mavlink_msg_gps_raw_int_get_satellites_visible(msg); +#else + memcpy(gps_raw_int, _MAV_PAYLOAD(msg), 30); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_gps_status.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_gps_status.h new file mode 100644 index 0000000000..bd3257f889 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_gps_status.h @@ -0,0 +1,252 @@ +// MESSAGE GPS_STATUS PACKING + +#define MAVLINK_MSG_ID_GPS_STATUS 25 + +typedef struct __mavlink_gps_status_t +{ + uint8_t satellites_visible; ///< Number of satellites visible + uint8_t satellite_prn[20]; ///< Global satellite ID + uint8_t satellite_used[20]; ///< 0: Satellite not used, 1: used for localization + uint8_t satellite_elevation[20]; ///< Elevation (0: right on top of receiver, 90: on the horizon) of satellite + uint8_t satellite_azimuth[20]; ///< Direction of satellite, 0: 0 deg, 255: 360 deg. + uint8_t satellite_snr[20]; ///< Signal to noise ratio of satellite +} mavlink_gps_status_t; + +#define MAVLINK_MSG_ID_GPS_STATUS_LEN 101 +#define MAVLINK_MSG_ID_25_LEN 101 + +#define MAVLINK_MSG_GPS_STATUS_FIELD_SATELLITE_PRN_LEN 20 +#define MAVLINK_MSG_GPS_STATUS_FIELD_SATELLITE_USED_LEN 20 +#define MAVLINK_MSG_GPS_STATUS_FIELD_SATELLITE_ELEVATION_LEN 20 +#define MAVLINK_MSG_GPS_STATUS_FIELD_SATELLITE_AZIMUTH_LEN 20 +#define MAVLINK_MSG_GPS_STATUS_FIELD_SATELLITE_SNR_LEN 20 + +#define MAVLINK_MESSAGE_INFO_GPS_STATUS { \ + "GPS_STATUS", \ + 6, \ + { { "satellites_visible", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_gps_status_t, satellites_visible) }, \ + { "satellite_prn", NULL, MAVLINK_TYPE_UINT8_T, 20, 1, offsetof(mavlink_gps_status_t, satellite_prn) }, \ + { "satellite_used", NULL, MAVLINK_TYPE_UINT8_T, 20, 21, offsetof(mavlink_gps_status_t, satellite_used) }, \ + { "satellite_elevation", NULL, MAVLINK_TYPE_UINT8_T, 20, 41, offsetof(mavlink_gps_status_t, satellite_elevation) }, \ + { "satellite_azimuth", NULL, MAVLINK_TYPE_UINT8_T, 20, 61, offsetof(mavlink_gps_status_t, satellite_azimuth) }, \ + { "satellite_snr", NULL, MAVLINK_TYPE_UINT8_T, 20, 81, offsetof(mavlink_gps_status_t, satellite_snr) }, \ + } \ +} + + +/** + * @brief Pack a gps_status message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param satellites_visible Number of satellites visible + * @param satellite_prn Global satellite ID + * @param satellite_used 0: Satellite not used, 1: used for localization + * @param satellite_elevation Elevation (0: right on top of receiver, 90: on the horizon) of satellite + * @param satellite_azimuth Direction of satellite, 0: 0 deg, 255: 360 deg. + * @param satellite_snr Signal to noise ratio of satellite + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_status_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t satellites_visible, const uint8_t *satellite_prn, const uint8_t *satellite_used, const uint8_t *satellite_elevation, const uint8_t *satellite_azimuth, const uint8_t *satellite_snr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[101]; + _mav_put_uint8_t(buf, 0, satellites_visible); + _mav_put_uint8_t_array(buf, 1, satellite_prn, 20); + _mav_put_uint8_t_array(buf, 21, satellite_used, 20); + _mav_put_uint8_t_array(buf, 41, satellite_elevation, 20); + _mav_put_uint8_t_array(buf, 61, satellite_azimuth, 20); + _mav_put_uint8_t_array(buf, 81, satellite_snr, 20); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 101); +#else + mavlink_gps_status_t packet; + packet.satellites_visible = satellites_visible; + mav_array_memcpy(packet.satellite_prn, satellite_prn, sizeof(uint8_t)*20); + mav_array_memcpy(packet.satellite_used, satellite_used, sizeof(uint8_t)*20); + mav_array_memcpy(packet.satellite_elevation, satellite_elevation, sizeof(uint8_t)*20); + mav_array_memcpy(packet.satellite_azimuth, satellite_azimuth, sizeof(uint8_t)*20); + mav_array_memcpy(packet.satellite_snr, satellite_snr, sizeof(uint8_t)*20); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 101); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_STATUS; + return mavlink_finalize_message(msg, system_id, component_id, 101, 23); +} + +/** + * @brief Pack a gps_status message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param satellites_visible Number of satellites visible + * @param satellite_prn Global satellite ID + * @param satellite_used 0: Satellite not used, 1: used for localization + * @param satellite_elevation Elevation (0: right on top of receiver, 90: on the horizon) of satellite + * @param satellite_azimuth Direction of satellite, 0: 0 deg, 255: 360 deg. + * @param satellite_snr Signal to noise ratio of satellite + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_status_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t satellites_visible,const uint8_t *satellite_prn,const uint8_t *satellite_used,const uint8_t *satellite_elevation,const uint8_t *satellite_azimuth,const uint8_t *satellite_snr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[101]; + _mav_put_uint8_t(buf, 0, satellites_visible); + _mav_put_uint8_t_array(buf, 1, satellite_prn, 20); + _mav_put_uint8_t_array(buf, 21, satellite_used, 20); + _mav_put_uint8_t_array(buf, 41, satellite_elevation, 20); + _mav_put_uint8_t_array(buf, 61, satellite_azimuth, 20); + _mav_put_uint8_t_array(buf, 81, satellite_snr, 20); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 101); +#else + mavlink_gps_status_t packet; + packet.satellites_visible = satellites_visible; + mav_array_memcpy(packet.satellite_prn, satellite_prn, sizeof(uint8_t)*20); + mav_array_memcpy(packet.satellite_used, satellite_used, sizeof(uint8_t)*20); + mav_array_memcpy(packet.satellite_elevation, satellite_elevation, sizeof(uint8_t)*20); + mav_array_memcpy(packet.satellite_azimuth, satellite_azimuth, sizeof(uint8_t)*20); + mav_array_memcpy(packet.satellite_snr, satellite_snr, sizeof(uint8_t)*20); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 101); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_STATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 101, 23); +} + +/** + * @brief Encode a gps_status struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param gps_status C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_gps_status_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_gps_status_t* gps_status) +{ + return mavlink_msg_gps_status_pack(system_id, component_id, msg, gps_status->satellites_visible, gps_status->satellite_prn, gps_status->satellite_used, gps_status->satellite_elevation, gps_status->satellite_azimuth, gps_status->satellite_snr); +} + +/** + * @brief Send a gps_status message + * @param chan MAVLink channel to send the message + * + * @param satellites_visible Number of satellites visible + * @param satellite_prn Global satellite ID + * @param satellite_used 0: Satellite not used, 1: used for localization + * @param satellite_elevation Elevation (0: right on top of receiver, 90: on the horizon) of satellite + * @param satellite_azimuth Direction of satellite, 0: 0 deg, 255: 360 deg. + * @param satellite_snr Signal to noise ratio of satellite + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_gps_status_send(mavlink_channel_t chan, uint8_t satellites_visible, const uint8_t *satellite_prn, const uint8_t *satellite_used, const uint8_t *satellite_elevation, const uint8_t *satellite_azimuth, const uint8_t *satellite_snr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[101]; + _mav_put_uint8_t(buf, 0, satellites_visible); + _mav_put_uint8_t_array(buf, 1, satellite_prn, 20); + _mav_put_uint8_t_array(buf, 21, satellite_used, 20); + _mav_put_uint8_t_array(buf, 41, satellite_elevation, 20); + _mav_put_uint8_t_array(buf, 61, satellite_azimuth, 20); + _mav_put_uint8_t_array(buf, 81, satellite_snr, 20); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_STATUS, buf, 101, 23); +#else + mavlink_gps_status_t packet; + packet.satellites_visible = satellites_visible; + mav_array_memcpy(packet.satellite_prn, satellite_prn, sizeof(uint8_t)*20); + mav_array_memcpy(packet.satellite_used, satellite_used, sizeof(uint8_t)*20); + mav_array_memcpy(packet.satellite_elevation, satellite_elevation, sizeof(uint8_t)*20); + mav_array_memcpy(packet.satellite_azimuth, satellite_azimuth, sizeof(uint8_t)*20); + mav_array_memcpy(packet.satellite_snr, satellite_snr, sizeof(uint8_t)*20); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_STATUS, (const char *)&packet, 101, 23); +#endif +} + +#endif + +// MESSAGE GPS_STATUS UNPACKING + + +/** + * @brief Get field satellites_visible from gps_status message + * + * @return Number of satellites visible + */ +static inline uint8_t mavlink_msg_gps_status_get_satellites_visible(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field satellite_prn from gps_status message + * + * @return Global satellite ID + */ +static inline uint16_t mavlink_msg_gps_status_get_satellite_prn(const mavlink_message_t* msg, uint8_t *satellite_prn) +{ + return _MAV_RETURN_uint8_t_array(msg, satellite_prn, 20, 1); +} + +/** + * @brief Get field satellite_used from gps_status message + * + * @return 0: Satellite not used, 1: used for localization + */ +static inline uint16_t mavlink_msg_gps_status_get_satellite_used(const mavlink_message_t* msg, uint8_t *satellite_used) +{ + return _MAV_RETURN_uint8_t_array(msg, satellite_used, 20, 21); +} + +/** + * @brief Get field satellite_elevation from gps_status message + * + * @return Elevation (0: right on top of receiver, 90: on the horizon) of satellite + */ +static inline uint16_t mavlink_msg_gps_status_get_satellite_elevation(const mavlink_message_t* msg, uint8_t *satellite_elevation) +{ + return _MAV_RETURN_uint8_t_array(msg, satellite_elevation, 20, 41); +} + +/** + * @brief Get field satellite_azimuth from gps_status message + * + * @return Direction of satellite, 0: 0 deg, 255: 360 deg. + */ +static inline uint16_t mavlink_msg_gps_status_get_satellite_azimuth(const mavlink_message_t* msg, uint8_t *satellite_azimuth) +{ + return _MAV_RETURN_uint8_t_array(msg, satellite_azimuth, 20, 61); +} + +/** + * @brief Get field satellite_snr from gps_status message + * + * @return Signal to noise ratio of satellite + */ +static inline uint16_t mavlink_msg_gps_status_get_satellite_snr(const mavlink_message_t* msg, uint8_t *satellite_snr) +{ + return _MAV_RETURN_uint8_t_array(msg, satellite_snr, 20, 81); +} + +/** + * @brief Decode a gps_status message into a struct + * + * @param msg The message to decode + * @param gps_status C-struct to decode the message contents into + */ +static inline void mavlink_msg_gps_status_decode(const mavlink_message_t* msg, mavlink_gps_status_t* gps_status) +{ +#if MAVLINK_NEED_BYTE_SWAP + gps_status->satellites_visible = mavlink_msg_gps_status_get_satellites_visible(msg); + mavlink_msg_gps_status_get_satellite_prn(msg, gps_status->satellite_prn); + mavlink_msg_gps_status_get_satellite_used(msg, gps_status->satellite_used); + mavlink_msg_gps_status_get_satellite_elevation(msg, gps_status->satellite_elevation); + mavlink_msg_gps_status_get_satellite_azimuth(msg, gps_status->satellite_azimuth); + mavlink_msg_gps_status_get_satellite_snr(msg, gps_status->satellite_snr); +#else + memcpy(gps_status, _MAV_PAYLOAD(msg), 101); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_heartbeat.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_heartbeat.h new file mode 100644 index 0000000000..599ea0bc5e --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_heartbeat.h @@ -0,0 +1,251 @@ +// MESSAGE HEARTBEAT PACKING + +#define MAVLINK_MSG_ID_HEARTBEAT 0 + +typedef struct __mavlink_heartbeat_t +{ + uint32_t custom_mode; ///< A bitfield for use for autopilot-specific flags. + uint8_t type; ///< Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + uint8_t autopilot; ///< Autopilot type / class. defined in MAV_AUTOPILOT ENUM + uint8_t base_mode; ///< System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h + uint8_t system_status; ///< System status flag, see MAV_STATE ENUM + uint8_t mavlink_version; ///< MAVLink version, not writable by user, gets added by protocol because of magic data type: uint8_t_mavlink_version +} mavlink_heartbeat_t; + +#define MAVLINK_MSG_ID_HEARTBEAT_LEN 9 +#define MAVLINK_MSG_ID_0_LEN 9 + + + +#define MAVLINK_MESSAGE_INFO_HEARTBEAT { \ + "HEARTBEAT", \ + 6, \ + { { "custom_mode", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_heartbeat_t, custom_mode) }, \ + { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_heartbeat_t, type) }, \ + { "autopilot", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_heartbeat_t, autopilot) }, \ + { "base_mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_heartbeat_t, base_mode) }, \ + { "system_status", NULL, MAVLINK_TYPE_UINT8_T, 0, 7, offsetof(mavlink_heartbeat_t, system_status) }, \ + { "mavlink_version", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_heartbeat_t, mavlink_version) }, \ + } \ +} + + +/** + * @brief Pack a heartbeat message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + * @param autopilot Autopilot type / class. defined in MAV_AUTOPILOT ENUM + * @param base_mode System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h + * @param custom_mode A bitfield for use for autopilot-specific flags. + * @param system_status System status flag, see MAV_STATE ENUM + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_heartbeat_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t type, uint8_t autopilot, uint8_t base_mode, uint32_t custom_mode, uint8_t system_status) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint32_t(buf, 0, custom_mode); + _mav_put_uint8_t(buf, 4, type); + _mav_put_uint8_t(buf, 5, autopilot); + _mav_put_uint8_t(buf, 6, base_mode); + _mav_put_uint8_t(buf, 7, system_status); + _mav_put_uint8_t(buf, 8, 3); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 9); +#else + mavlink_heartbeat_t packet; + packet.custom_mode = custom_mode; + packet.type = type; + packet.autopilot = autopilot; + packet.base_mode = base_mode; + packet.system_status = system_status; + packet.mavlink_version = 3; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 9); +#endif + + msg->msgid = MAVLINK_MSG_ID_HEARTBEAT; + return mavlink_finalize_message(msg, system_id, component_id, 9, 50); +} + +/** + * @brief Pack a heartbeat message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + * @param autopilot Autopilot type / class. defined in MAV_AUTOPILOT ENUM + * @param base_mode System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h + * @param custom_mode A bitfield for use for autopilot-specific flags. + * @param system_status System status flag, see MAV_STATE ENUM + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_heartbeat_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t type,uint8_t autopilot,uint8_t base_mode,uint32_t custom_mode,uint8_t system_status) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint32_t(buf, 0, custom_mode); + _mav_put_uint8_t(buf, 4, type); + _mav_put_uint8_t(buf, 5, autopilot); + _mav_put_uint8_t(buf, 6, base_mode); + _mav_put_uint8_t(buf, 7, system_status); + _mav_put_uint8_t(buf, 8, 3); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 9); +#else + mavlink_heartbeat_t packet; + packet.custom_mode = custom_mode; + packet.type = type; + packet.autopilot = autopilot; + packet.base_mode = base_mode; + packet.system_status = system_status; + packet.mavlink_version = 3; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 9); +#endif + + msg->msgid = MAVLINK_MSG_ID_HEARTBEAT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 9, 50); +} + +/** + * @brief Encode a heartbeat struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param heartbeat C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_heartbeat_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_heartbeat_t* heartbeat) +{ + return mavlink_msg_heartbeat_pack(system_id, component_id, msg, heartbeat->type, heartbeat->autopilot, heartbeat->base_mode, heartbeat->custom_mode, heartbeat->system_status); +} + +/** + * @brief Send a heartbeat message + * @param chan MAVLink channel to send the message + * + * @param type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + * @param autopilot Autopilot type / class. defined in MAV_AUTOPILOT ENUM + * @param base_mode System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h + * @param custom_mode A bitfield for use for autopilot-specific flags. + * @param system_status System status flag, see MAV_STATE ENUM + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_heartbeat_send(mavlink_channel_t chan, uint8_t type, uint8_t autopilot, uint8_t base_mode, uint32_t custom_mode, uint8_t system_status) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint32_t(buf, 0, custom_mode); + _mav_put_uint8_t(buf, 4, type); + _mav_put_uint8_t(buf, 5, autopilot); + _mav_put_uint8_t(buf, 6, base_mode); + _mav_put_uint8_t(buf, 7, system_status); + _mav_put_uint8_t(buf, 8, 3); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HEARTBEAT, buf, 9, 50); +#else + mavlink_heartbeat_t packet; + packet.custom_mode = custom_mode; + packet.type = type; + packet.autopilot = autopilot; + packet.base_mode = base_mode; + packet.system_status = system_status; + packet.mavlink_version = 3; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HEARTBEAT, (const char *)&packet, 9, 50); +#endif +} + +#endif + +// MESSAGE HEARTBEAT UNPACKING + + +/** + * @brief Get field type from heartbeat message + * + * @return Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + */ +static inline uint8_t mavlink_msg_heartbeat_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field autopilot from heartbeat message + * + * @return Autopilot type / class. defined in MAV_AUTOPILOT ENUM + */ +static inline uint8_t mavlink_msg_heartbeat_get_autopilot(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field base_mode from heartbeat message + * + * @return System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h + */ +static inline uint8_t mavlink_msg_heartbeat_get_base_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Get field custom_mode from heartbeat message + * + * @return A bitfield for use for autopilot-specific flags. + */ +static inline uint32_t mavlink_msg_heartbeat_get_custom_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field system_status from heartbeat message + * + * @return System status flag, see MAV_STATE ENUM + */ +static inline uint8_t mavlink_msg_heartbeat_get_system_status(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 7); +} + +/** + * @brief Get field mavlink_version from heartbeat message + * + * @return MAVLink version, not writable by user, gets added by protocol because of magic data type: uint8_t_mavlink_version + */ +static inline uint8_t mavlink_msg_heartbeat_get_mavlink_version(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Decode a heartbeat message into a struct + * + * @param msg The message to decode + * @param heartbeat C-struct to decode the message contents into + */ +static inline void mavlink_msg_heartbeat_decode(const mavlink_message_t* msg, mavlink_heartbeat_t* heartbeat) +{ +#if MAVLINK_NEED_BYTE_SWAP + heartbeat->custom_mode = mavlink_msg_heartbeat_get_custom_mode(msg); + heartbeat->type = mavlink_msg_heartbeat_get_type(msg); + heartbeat->autopilot = mavlink_msg_heartbeat_get_autopilot(msg); + heartbeat->base_mode = mavlink_msg_heartbeat_get_base_mode(msg); + heartbeat->system_status = mavlink_msg_heartbeat_get_system_status(msg); + heartbeat->mavlink_version = mavlink_msg_heartbeat_get_mavlink_version(msg); +#else + memcpy(heartbeat, _MAV_PAYLOAD(msg), 9); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_hil_controls.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_hil_controls.h new file mode 100644 index 0000000000..41a9bc9498 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_hil_controls.h @@ -0,0 +1,364 @@ +// MESSAGE HIL_CONTROLS PACKING + +#define MAVLINK_MSG_ID_HIL_CONTROLS 91 + +typedef struct __mavlink_hil_controls_t +{ + uint64_t time_usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + float roll_ailerons; ///< Control output -1 .. 1 + float pitch_elevator; ///< Control output -1 .. 1 + float yaw_rudder; ///< Control output -1 .. 1 + float throttle; ///< Throttle 0 .. 1 + float aux1; ///< Aux 1, -1 .. 1 + float aux2; ///< Aux 2, -1 .. 1 + float aux3; ///< Aux 3, -1 .. 1 + float aux4; ///< Aux 4, -1 .. 1 + uint8_t mode; ///< System mode (MAV_MODE) + uint8_t nav_mode; ///< Navigation mode (MAV_NAV_MODE) +} mavlink_hil_controls_t; + +#define MAVLINK_MSG_ID_HIL_CONTROLS_LEN 42 +#define MAVLINK_MSG_ID_91_LEN 42 + + + +#define MAVLINK_MESSAGE_INFO_HIL_CONTROLS { \ + "HIL_CONTROLS", \ + 11, \ + { { "time_usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_hil_controls_t, time_usec) }, \ + { "roll_ailerons", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_hil_controls_t, roll_ailerons) }, \ + { "pitch_elevator", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_hil_controls_t, pitch_elevator) }, \ + { "yaw_rudder", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_hil_controls_t, yaw_rudder) }, \ + { "throttle", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_hil_controls_t, throttle) }, \ + { "aux1", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_hil_controls_t, aux1) }, \ + { "aux2", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_hil_controls_t, aux2) }, \ + { "aux3", NULL, MAVLINK_TYPE_FLOAT, 0, 32, offsetof(mavlink_hil_controls_t, aux3) }, \ + { "aux4", NULL, MAVLINK_TYPE_FLOAT, 0, 36, offsetof(mavlink_hil_controls_t, aux4) }, \ + { "mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 40, offsetof(mavlink_hil_controls_t, mode) }, \ + { "nav_mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 41, offsetof(mavlink_hil_controls_t, nav_mode) }, \ + } \ +} + + +/** + * @brief Pack a hil_controls message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll_ailerons Control output -1 .. 1 + * @param pitch_elevator Control output -1 .. 1 + * @param yaw_rudder Control output -1 .. 1 + * @param throttle Throttle 0 .. 1 + * @param aux1 Aux 1, -1 .. 1 + * @param aux2 Aux 2, -1 .. 1 + * @param aux3 Aux 3, -1 .. 1 + * @param aux4 Aux 4, -1 .. 1 + * @param mode System mode (MAV_MODE) + * @param nav_mode Navigation mode (MAV_NAV_MODE) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hil_controls_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time_usec, float roll_ailerons, float pitch_elevator, float yaw_rudder, float throttle, float aux1, float aux2, float aux3, float aux4, uint8_t mode, uint8_t nav_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_float(buf, 8, roll_ailerons); + _mav_put_float(buf, 12, pitch_elevator); + _mav_put_float(buf, 16, yaw_rudder); + _mav_put_float(buf, 20, throttle); + _mav_put_float(buf, 24, aux1); + _mav_put_float(buf, 28, aux2); + _mav_put_float(buf, 32, aux3); + _mav_put_float(buf, 36, aux4); + _mav_put_uint8_t(buf, 40, mode); + _mav_put_uint8_t(buf, 41, nav_mode); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 42); +#else + mavlink_hil_controls_t packet; + packet.time_usec = time_usec; + packet.roll_ailerons = roll_ailerons; + packet.pitch_elevator = pitch_elevator; + packet.yaw_rudder = yaw_rudder; + packet.throttle = throttle; + packet.aux1 = aux1; + packet.aux2 = aux2; + packet.aux3 = aux3; + packet.aux4 = aux4; + packet.mode = mode; + packet.nav_mode = nav_mode; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 42); +#endif + + msg->msgid = MAVLINK_MSG_ID_HIL_CONTROLS; + return mavlink_finalize_message(msg, system_id, component_id, 42, 63); +} + +/** + * @brief Pack a hil_controls message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll_ailerons Control output -1 .. 1 + * @param pitch_elevator Control output -1 .. 1 + * @param yaw_rudder Control output -1 .. 1 + * @param throttle Throttle 0 .. 1 + * @param aux1 Aux 1, -1 .. 1 + * @param aux2 Aux 2, -1 .. 1 + * @param aux3 Aux 3, -1 .. 1 + * @param aux4 Aux 4, -1 .. 1 + * @param mode System mode (MAV_MODE) + * @param nav_mode Navigation mode (MAV_NAV_MODE) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hil_controls_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time_usec,float roll_ailerons,float pitch_elevator,float yaw_rudder,float throttle,float aux1,float aux2,float aux3,float aux4,uint8_t mode,uint8_t nav_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_float(buf, 8, roll_ailerons); + _mav_put_float(buf, 12, pitch_elevator); + _mav_put_float(buf, 16, yaw_rudder); + _mav_put_float(buf, 20, throttle); + _mav_put_float(buf, 24, aux1); + _mav_put_float(buf, 28, aux2); + _mav_put_float(buf, 32, aux3); + _mav_put_float(buf, 36, aux4); + _mav_put_uint8_t(buf, 40, mode); + _mav_put_uint8_t(buf, 41, nav_mode); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 42); +#else + mavlink_hil_controls_t packet; + packet.time_usec = time_usec; + packet.roll_ailerons = roll_ailerons; + packet.pitch_elevator = pitch_elevator; + packet.yaw_rudder = yaw_rudder; + packet.throttle = throttle; + packet.aux1 = aux1; + packet.aux2 = aux2; + packet.aux3 = aux3; + packet.aux4 = aux4; + packet.mode = mode; + packet.nav_mode = nav_mode; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 42); +#endif + + msg->msgid = MAVLINK_MSG_ID_HIL_CONTROLS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 42, 63); +} + +/** + * @brief Encode a hil_controls struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param hil_controls C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_hil_controls_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_hil_controls_t* hil_controls) +{ + return mavlink_msg_hil_controls_pack(system_id, component_id, msg, hil_controls->time_usec, hil_controls->roll_ailerons, hil_controls->pitch_elevator, hil_controls->yaw_rudder, hil_controls->throttle, hil_controls->aux1, hil_controls->aux2, hil_controls->aux3, hil_controls->aux4, hil_controls->mode, hil_controls->nav_mode); +} + +/** + * @brief Send a hil_controls message + * @param chan MAVLink channel to send the message + * + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll_ailerons Control output -1 .. 1 + * @param pitch_elevator Control output -1 .. 1 + * @param yaw_rudder Control output -1 .. 1 + * @param throttle Throttle 0 .. 1 + * @param aux1 Aux 1, -1 .. 1 + * @param aux2 Aux 2, -1 .. 1 + * @param aux3 Aux 3, -1 .. 1 + * @param aux4 Aux 4, -1 .. 1 + * @param mode System mode (MAV_MODE) + * @param nav_mode Navigation mode (MAV_NAV_MODE) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_hil_controls_send(mavlink_channel_t chan, uint64_t time_usec, float roll_ailerons, float pitch_elevator, float yaw_rudder, float throttle, float aux1, float aux2, float aux3, float aux4, uint8_t mode, uint8_t nav_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_float(buf, 8, roll_ailerons); + _mav_put_float(buf, 12, pitch_elevator); + _mav_put_float(buf, 16, yaw_rudder); + _mav_put_float(buf, 20, throttle); + _mav_put_float(buf, 24, aux1); + _mav_put_float(buf, 28, aux2); + _mav_put_float(buf, 32, aux3); + _mav_put_float(buf, 36, aux4); + _mav_put_uint8_t(buf, 40, mode); + _mav_put_uint8_t(buf, 41, nav_mode); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HIL_CONTROLS, buf, 42, 63); +#else + mavlink_hil_controls_t packet; + packet.time_usec = time_usec; + packet.roll_ailerons = roll_ailerons; + packet.pitch_elevator = pitch_elevator; + packet.yaw_rudder = yaw_rudder; + packet.throttle = throttle; + packet.aux1 = aux1; + packet.aux2 = aux2; + packet.aux3 = aux3; + packet.aux4 = aux4; + packet.mode = mode; + packet.nav_mode = nav_mode; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HIL_CONTROLS, (const char *)&packet, 42, 63); +#endif +} + +#endif + +// MESSAGE HIL_CONTROLS UNPACKING + + +/** + * @brief Get field time_usec from hil_controls message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_hil_controls_get_time_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field roll_ailerons from hil_controls message + * + * @return Control output -1 .. 1 + */ +static inline float mavlink_msg_hil_controls_get_roll_ailerons(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field pitch_elevator from hil_controls message + * + * @return Control output -1 .. 1 + */ +static inline float mavlink_msg_hil_controls_get_pitch_elevator(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field yaw_rudder from hil_controls message + * + * @return Control output -1 .. 1 + */ +static inline float mavlink_msg_hil_controls_get_yaw_rudder(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field throttle from hil_controls message + * + * @return Throttle 0 .. 1 + */ +static inline float mavlink_msg_hil_controls_get_throttle(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field aux1 from hil_controls message + * + * @return Aux 1, -1 .. 1 + */ +static inline float mavlink_msg_hil_controls_get_aux1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field aux2 from hil_controls message + * + * @return Aux 2, -1 .. 1 + */ +static inline float mavlink_msg_hil_controls_get_aux2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field aux3 from hil_controls message + * + * @return Aux 3, -1 .. 1 + */ +static inline float mavlink_msg_hil_controls_get_aux3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 32); +} + +/** + * @brief Get field aux4 from hil_controls message + * + * @return Aux 4, -1 .. 1 + */ +static inline float mavlink_msg_hil_controls_get_aux4(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 36); +} + +/** + * @brief Get field mode from hil_controls message + * + * @return System mode (MAV_MODE) + */ +static inline uint8_t mavlink_msg_hil_controls_get_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 40); +} + +/** + * @brief Get field nav_mode from hil_controls message + * + * @return Navigation mode (MAV_NAV_MODE) + */ +static inline uint8_t mavlink_msg_hil_controls_get_nav_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 41); +} + +/** + * @brief Decode a hil_controls message into a struct + * + * @param msg The message to decode + * @param hil_controls C-struct to decode the message contents into + */ +static inline void mavlink_msg_hil_controls_decode(const mavlink_message_t* msg, mavlink_hil_controls_t* hil_controls) +{ +#if MAVLINK_NEED_BYTE_SWAP + hil_controls->time_usec = mavlink_msg_hil_controls_get_time_usec(msg); + hil_controls->roll_ailerons = mavlink_msg_hil_controls_get_roll_ailerons(msg); + hil_controls->pitch_elevator = mavlink_msg_hil_controls_get_pitch_elevator(msg); + hil_controls->yaw_rudder = mavlink_msg_hil_controls_get_yaw_rudder(msg); + hil_controls->throttle = mavlink_msg_hil_controls_get_throttle(msg); + hil_controls->aux1 = mavlink_msg_hil_controls_get_aux1(msg); + hil_controls->aux2 = mavlink_msg_hil_controls_get_aux2(msg); + hil_controls->aux3 = mavlink_msg_hil_controls_get_aux3(msg); + hil_controls->aux4 = mavlink_msg_hil_controls_get_aux4(msg); + hil_controls->mode = mavlink_msg_hil_controls_get_mode(msg); + hil_controls->nav_mode = mavlink_msg_hil_controls_get_nav_mode(msg); +#else + memcpy(hil_controls, _MAV_PAYLOAD(msg), 42); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_hil_rc_inputs_raw.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_hil_rc_inputs_raw.h new file mode 100644 index 0000000000..7ac0853d31 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_hil_rc_inputs_raw.h @@ -0,0 +1,430 @@ +// MESSAGE HIL_RC_INPUTS_RAW PACKING + +#define MAVLINK_MSG_ID_HIL_RC_INPUTS_RAW 92 + +typedef struct __mavlink_hil_rc_inputs_raw_t +{ + uint64_t time_usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + uint16_t chan1_raw; ///< RC channel 1 value, in microseconds + uint16_t chan2_raw; ///< RC channel 2 value, in microseconds + uint16_t chan3_raw; ///< RC channel 3 value, in microseconds + uint16_t chan4_raw; ///< RC channel 4 value, in microseconds + uint16_t chan5_raw; ///< RC channel 5 value, in microseconds + uint16_t chan6_raw; ///< RC channel 6 value, in microseconds + uint16_t chan7_raw; ///< RC channel 7 value, in microseconds + uint16_t chan8_raw; ///< RC channel 8 value, in microseconds + uint16_t chan9_raw; ///< RC channel 9 value, in microseconds + uint16_t chan10_raw; ///< RC channel 10 value, in microseconds + uint16_t chan11_raw; ///< RC channel 11 value, in microseconds + uint16_t chan12_raw; ///< RC channel 12 value, in microseconds + uint8_t rssi; ///< Receive signal strength indicator, 0: 0%, 255: 100% +} mavlink_hil_rc_inputs_raw_t; + +#define MAVLINK_MSG_ID_HIL_RC_INPUTS_RAW_LEN 33 +#define MAVLINK_MSG_ID_92_LEN 33 + + + +#define MAVLINK_MESSAGE_INFO_HIL_RC_INPUTS_RAW { \ + "HIL_RC_INPUTS_RAW", \ + 14, \ + { { "time_usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_hil_rc_inputs_raw_t, time_usec) }, \ + { "chan1_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 8, offsetof(mavlink_hil_rc_inputs_raw_t, chan1_raw) }, \ + { "chan2_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 10, offsetof(mavlink_hil_rc_inputs_raw_t, chan2_raw) }, \ + { "chan3_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 12, offsetof(mavlink_hil_rc_inputs_raw_t, chan3_raw) }, \ + { "chan4_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 14, offsetof(mavlink_hil_rc_inputs_raw_t, chan4_raw) }, \ + { "chan5_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 16, offsetof(mavlink_hil_rc_inputs_raw_t, chan5_raw) }, \ + { "chan6_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 18, offsetof(mavlink_hil_rc_inputs_raw_t, chan6_raw) }, \ + { "chan7_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 20, offsetof(mavlink_hil_rc_inputs_raw_t, chan7_raw) }, \ + { "chan8_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 22, offsetof(mavlink_hil_rc_inputs_raw_t, chan8_raw) }, \ + { "chan9_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 24, offsetof(mavlink_hil_rc_inputs_raw_t, chan9_raw) }, \ + { "chan10_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 26, offsetof(mavlink_hil_rc_inputs_raw_t, chan10_raw) }, \ + { "chan11_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 28, offsetof(mavlink_hil_rc_inputs_raw_t, chan11_raw) }, \ + { "chan12_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 30, offsetof(mavlink_hil_rc_inputs_raw_t, chan12_raw) }, \ + { "rssi", NULL, MAVLINK_TYPE_UINT8_T, 0, 32, offsetof(mavlink_hil_rc_inputs_raw_t, rssi) }, \ + } \ +} + + +/** + * @brief Pack a hil_rc_inputs_raw message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + * @param chan9_raw RC channel 9 value, in microseconds + * @param chan10_raw RC channel 10 value, in microseconds + * @param chan11_raw RC channel 11 value, in microseconds + * @param chan12_raw RC channel 12 value, in microseconds + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time_usec, uint16_t chan1_raw, uint16_t chan2_raw, uint16_t chan3_raw, uint16_t chan4_raw, uint16_t chan5_raw, uint16_t chan6_raw, uint16_t chan7_raw, uint16_t chan8_raw, uint16_t chan9_raw, uint16_t chan10_raw, uint16_t chan11_raw, uint16_t chan12_raw, uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[33]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_uint16_t(buf, 8, chan1_raw); + _mav_put_uint16_t(buf, 10, chan2_raw); + _mav_put_uint16_t(buf, 12, chan3_raw); + _mav_put_uint16_t(buf, 14, chan4_raw); + _mav_put_uint16_t(buf, 16, chan5_raw); + _mav_put_uint16_t(buf, 18, chan6_raw); + _mav_put_uint16_t(buf, 20, chan7_raw); + _mav_put_uint16_t(buf, 22, chan8_raw); + _mav_put_uint16_t(buf, 24, chan9_raw); + _mav_put_uint16_t(buf, 26, chan10_raw); + _mav_put_uint16_t(buf, 28, chan11_raw); + _mav_put_uint16_t(buf, 30, chan12_raw); + _mav_put_uint8_t(buf, 32, rssi); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 33); +#else + mavlink_hil_rc_inputs_raw_t packet; + packet.time_usec = time_usec; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + packet.chan9_raw = chan9_raw; + packet.chan10_raw = chan10_raw; + packet.chan11_raw = chan11_raw; + packet.chan12_raw = chan12_raw; + packet.rssi = rssi; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 33); +#endif + + msg->msgid = MAVLINK_MSG_ID_HIL_RC_INPUTS_RAW; + return mavlink_finalize_message(msg, system_id, component_id, 33, 54); +} + +/** + * @brief Pack a hil_rc_inputs_raw message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + * @param chan9_raw RC channel 9 value, in microseconds + * @param chan10_raw RC channel 10 value, in microseconds + * @param chan11_raw RC channel 11 value, in microseconds + * @param chan12_raw RC channel 12 value, in microseconds + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time_usec,uint16_t chan1_raw,uint16_t chan2_raw,uint16_t chan3_raw,uint16_t chan4_raw,uint16_t chan5_raw,uint16_t chan6_raw,uint16_t chan7_raw,uint16_t chan8_raw,uint16_t chan9_raw,uint16_t chan10_raw,uint16_t chan11_raw,uint16_t chan12_raw,uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[33]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_uint16_t(buf, 8, chan1_raw); + _mav_put_uint16_t(buf, 10, chan2_raw); + _mav_put_uint16_t(buf, 12, chan3_raw); + _mav_put_uint16_t(buf, 14, chan4_raw); + _mav_put_uint16_t(buf, 16, chan5_raw); + _mav_put_uint16_t(buf, 18, chan6_raw); + _mav_put_uint16_t(buf, 20, chan7_raw); + _mav_put_uint16_t(buf, 22, chan8_raw); + _mav_put_uint16_t(buf, 24, chan9_raw); + _mav_put_uint16_t(buf, 26, chan10_raw); + _mav_put_uint16_t(buf, 28, chan11_raw); + _mav_put_uint16_t(buf, 30, chan12_raw); + _mav_put_uint8_t(buf, 32, rssi); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 33); +#else + mavlink_hil_rc_inputs_raw_t packet; + packet.time_usec = time_usec; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + packet.chan9_raw = chan9_raw; + packet.chan10_raw = chan10_raw; + packet.chan11_raw = chan11_raw; + packet.chan12_raw = chan12_raw; + packet.rssi = rssi; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 33); +#endif + + msg->msgid = MAVLINK_MSG_ID_HIL_RC_INPUTS_RAW; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 33, 54); +} + +/** + * @brief Encode a hil_rc_inputs_raw struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param hil_rc_inputs_raw C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_hil_rc_inputs_raw_t* hil_rc_inputs_raw) +{ + return mavlink_msg_hil_rc_inputs_raw_pack(system_id, component_id, msg, hil_rc_inputs_raw->time_usec, hil_rc_inputs_raw->chan1_raw, hil_rc_inputs_raw->chan2_raw, hil_rc_inputs_raw->chan3_raw, hil_rc_inputs_raw->chan4_raw, hil_rc_inputs_raw->chan5_raw, hil_rc_inputs_raw->chan6_raw, hil_rc_inputs_raw->chan7_raw, hil_rc_inputs_raw->chan8_raw, hil_rc_inputs_raw->chan9_raw, hil_rc_inputs_raw->chan10_raw, hil_rc_inputs_raw->chan11_raw, hil_rc_inputs_raw->chan12_raw, hil_rc_inputs_raw->rssi); +} + +/** + * @brief Send a hil_rc_inputs_raw message + * @param chan MAVLink channel to send the message + * + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + * @param chan9_raw RC channel 9 value, in microseconds + * @param chan10_raw RC channel 10 value, in microseconds + * @param chan11_raw RC channel 11 value, in microseconds + * @param chan12_raw RC channel 12 value, in microseconds + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_hil_rc_inputs_raw_send(mavlink_channel_t chan, uint64_t time_usec, uint16_t chan1_raw, uint16_t chan2_raw, uint16_t chan3_raw, uint16_t chan4_raw, uint16_t chan5_raw, uint16_t chan6_raw, uint16_t chan7_raw, uint16_t chan8_raw, uint16_t chan9_raw, uint16_t chan10_raw, uint16_t chan11_raw, uint16_t chan12_raw, uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[33]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_uint16_t(buf, 8, chan1_raw); + _mav_put_uint16_t(buf, 10, chan2_raw); + _mav_put_uint16_t(buf, 12, chan3_raw); + _mav_put_uint16_t(buf, 14, chan4_raw); + _mav_put_uint16_t(buf, 16, chan5_raw); + _mav_put_uint16_t(buf, 18, chan6_raw); + _mav_put_uint16_t(buf, 20, chan7_raw); + _mav_put_uint16_t(buf, 22, chan8_raw); + _mav_put_uint16_t(buf, 24, chan9_raw); + _mav_put_uint16_t(buf, 26, chan10_raw); + _mav_put_uint16_t(buf, 28, chan11_raw); + _mav_put_uint16_t(buf, 30, chan12_raw); + _mav_put_uint8_t(buf, 32, rssi); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HIL_RC_INPUTS_RAW, buf, 33, 54); +#else + mavlink_hil_rc_inputs_raw_t packet; + packet.time_usec = time_usec; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + packet.chan9_raw = chan9_raw; + packet.chan10_raw = chan10_raw; + packet.chan11_raw = chan11_raw; + packet.chan12_raw = chan12_raw; + packet.rssi = rssi; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HIL_RC_INPUTS_RAW, (const char *)&packet, 33, 54); +#endif +} + +#endif + +// MESSAGE HIL_RC_INPUTS_RAW UNPACKING + + +/** + * @brief Get field time_usec from hil_rc_inputs_raw message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_hil_rc_inputs_raw_get_time_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field chan1_raw from hil_rc_inputs_raw message + * + * @return RC channel 1 value, in microseconds + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_get_chan1_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Get field chan2_raw from hil_rc_inputs_raw message + * + * @return RC channel 2 value, in microseconds + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_get_chan2_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 10); +} + +/** + * @brief Get field chan3_raw from hil_rc_inputs_raw message + * + * @return RC channel 3 value, in microseconds + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_get_chan3_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 12); +} + +/** + * @brief Get field chan4_raw from hil_rc_inputs_raw message + * + * @return RC channel 4 value, in microseconds + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_get_chan4_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 14); +} + +/** + * @brief Get field chan5_raw from hil_rc_inputs_raw message + * + * @return RC channel 5 value, in microseconds + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_get_chan5_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 16); +} + +/** + * @brief Get field chan6_raw from hil_rc_inputs_raw message + * + * @return RC channel 6 value, in microseconds + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_get_chan6_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 18); +} + +/** + * @brief Get field chan7_raw from hil_rc_inputs_raw message + * + * @return RC channel 7 value, in microseconds + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_get_chan7_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 20); +} + +/** + * @brief Get field chan8_raw from hil_rc_inputs_raw message + * + * @return RC channel 8 value, in microseconds + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_get_chan8_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 22); +} + +/** + * @brief Get field chan9_raw from hil_rc_inputs_raw message + * + * @return RC channel 9 value, in microseconds + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_get_chan9_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 24); +} + +/** + * @brief Get field chan10_raw from hil_rc_inputs_raw message + * + * @return RC channel 10 value, in microseconds + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_get_chan10_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 26); +} + +/** + * @brief Get field chan11_raw from hil_rc_inputs_raw message + * + * @return RC channel 11 value, in microseconds + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_get_chan11_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 28); +} + +/** + * @brief Get field chan12_raw from hil_rc_inputs_raw message + * + * @return RC channel 12 value, in microseconds + */ +static inline uint16_t mavlink_msg_hil_rc_inputs_raw_get_chan12_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 30); +} + +/** + * @brief Get field rssi from hil_rc_inputs_raw message + * + * @return Receive signal strength indicator, 0: 0%, 255: 100% + */ +static inline uint8_t mavlink_msg_hil_rc_inputs_raw_get_rssi(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 32); +} + +/** + * @brief Decode a hil_rc_inputs_raw message into a struct + * + * @param msg The message to decode + * @param hil_rc_inputs_raw C-struct to decode the message contents into + */ +static inline void mavlink_msg_hil_rc_inputs_raw_decode(const mavlink_message_t* msg, mavlink_hil_rc_inputs_raw_t* hil_rc_inputs_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP + hil_rc_inputs_raw->time_usec = mavlink_msg_hil_rc_inputs_raw_get_time_usec(msg); + hil_rc_inputs_raw->chan1_raw = mavlink_msg_hil_rc_inputs_raw_get_chan1_raw(msg); + hil_rc_inputs_raw->chan2_raw = mavlink_msg_hil_rc_inputs_raw_get_chan2_raw(msg); + hil_rc_inputs_raw->chan3_raw = mavlink_msg_hil_rc_inputs_raw_get_chan3_raw(msg); + hil_rc_inputs_raw->chan4_raw = mavlink_msg_hil_rc_inputs_raw_get_chan4_raw(msg); + hil_rc_inputs_raw->chan5_raw = mavlink_msg_hil_rc_inputs_raw_get_chan5_raw(msg); + hil_rc_inputs_raw->chan6_raw = mavlink_msg_hil_rc_inputs_raw_get_chan6_raw(msg); + hil_rc_inputs_raw->chan7_raw = mavlink_msg_hil_rc_inputs_raw_get_chan7_raw(msg); + hil_rc_inputs_raw->chan8_raw = mavlink_msg_hil_rc_inputs_raw_get_chan8_raw(msg); + hil_rc_inputs_raw->chan9_raw = mavlink_msg_hil_rc_inputs_raw_get_chan9_raw(msg); + hil_rc_inputs_raw->chan10_raw = mavlink_msg_hil_rc_inputs_raw_get_chan10_raw(msg); + hil_rc_inputs_raw->chan11_raw = mavlink_msg_hil_rc_inputs_raw_get_chan11_raw(msg); + hil_rc_inputs_raw->chan12_raw = mavlink_msg_hil_rc_inputs_raw_get_chan12_raw(msg); + hil_rc_inputs_raw->rssi = mavlink_msg_hil_rc_inputs_raw_get_rssi(msg); +#else + memcpy(hil_rc_inputs_raw, _MAV_PAYLOAD(msg), 33); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_hil_state.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_hil_state.h new file mode 100644 index 0000000000..1447812956 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_hil_state.h @@ -0,0 +1,474 @@ +// MESSAGE HIL_STATE PACKING + +#define MAVLINK_MSG_ID_HIL_STATE 90 + +typedef struct __mavlink_hil_state_t +{ + uint64_t time_usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + float roll; ///< Roll angle (rad) + float pitch; ///< Pitch angle (rad) + float yaw; ///< Yaw angle (rad) + float rollspeed; ///< Roll angular speed (rad/s) + float pitchspeed; ///< Pitch angular speed (rad/s) + float yawspeed; ///< Yaw angular speed (rad/s) + int32_t lat; ///< Latitude, expressed as * 1E7 + int32_t lon; ///< Longitude, expressed as * 1E7 + int32_t alt; ///< Altitude in meters, expressed as * 1000 (millimeters) + int16_t vx; ///< Ground X Speed (Latitude), expressed as m/s * 100 + int16_t vy; ///< Ground Y Speed (Longitude), expressed as m/s * 100 + int16_t vz; ///< Ground Z Speed (Altitude), expressed as m/s * 100 + int16_t xacc; ///< X acceleration (mg) + int16_t yacc; ///< Y acceleration (mg) + int16_t zacc; ///< Z acceleration (mg) +} mavlink_hil_state_t; + +#define MAVLINK_MSG_ID_HIL_STATE_LEN 56 +#define MAVLINK_MSG_ID_90_LEN 56 + + + +#define MAVLINK_MESSAGE_INFO_HIL_STATE { \ + "HIL_STATE", \ + 16, \ + { { "time_usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_hil_state_t, time_usec) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_hil_state_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_hil_state_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_hil_state_t, yaw) }, \ + { "rollspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_hil_state_t, rollspeed) }, \ + { "pitchspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_hil_state_t, pitchspeed) }, \ + { "yawspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_hil_state_t, yawspeed) }, \ + { "lat", NULL, MAVLINK_TYPE_INT32_T, 0, 32, offsetof(mavlink_hil_state_t, lat) }, \ + { "lon", NULL, MAVLINK_TYPE_INT32_T, 0, 36, offsetof(mavlink_hil_state_t, lon) }, \ + { "alt", NULL, MAVLINK_TYPE_INT32_T, 0, 40, offsetof(mavlink_hil_state_t, alt) }, \ + { "vx", NULL, MAVLINK_TYPE_INT16_T, 0, 44, offsetof(mavlink_hil_state_t, vx) }, \ + { "vy", NULL, MAVLINK_TYPE_INT16_T, 0, 46, offsetof(mavlink_hil_state_t, vy) }, \ + { "vz", NULL, MAVLINK_TYPE_INT16_T, 0, 48, offsetof(mavlink_hil_state_t, vz) }, \ + { "xacc", NULL, MAVLINK_TYPE_INT16_T, 0, 50, offsetof(mavlink_hil_state_t, xacc) }, \ + { "yacc", NULL, MAVLINK_TYPE_INT16_T, 0, 52, offsetof(mavlink_hil_state_t, yacc) }, \ + { "zacc", NULL, MAVLINK_TYPE_INT16_T, 0, 54, offsetof(mavlink_hil_state_t, zacc) }, \ + } \ +} + + +/** + * @brief Pack a hil_state message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + * @param lat Latitude, expressed as * 1E7 + * @param lon Longitude, expressed as * 1E7 + * @param alt Altitude in meters, expressed as * 1000 (millimeters) + * @param vx Ground X Speed (Latitude), expressed as m/s * 100 + * @param vy Ground Y Speed (Longitude), expressed as m/s * 100 + * @param vz Ground Z Speed (Altitude), expressed as m/s * 100 + * @param xacc X acceleration (mg) + * @param yacc Y acceleration (mg) + * @param zacc Z acceleration (mg) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hil_state_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time_usec, float roll, float pitch, float yaw, float rollspeed, float pitchspeed, float yawspeed, int32_t lat, int32_t lon, int32_t alt, int16_t vx, int16_t vy, int16_t vz, int16_t xacc, int16_t yacc, int16_t zacc) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[56]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_float(buf, 8, roll); + _mav_put_float(buf, 12, pitch); + _mav_put_float(buf, 16, yaw); + _mav_put_float(buf, 20, rollspeed); + _mav_put_float(buf, 24, pitchspeed); + _mav_put_float(buf, 28, yawspeed); + _mav_put_int32_t(buf, 32, lat); + _mav_put_int32_t(buf, 36, lon); + _mav_put_int32_t(buf, 40, alt); + _mav_put_int16_t(buf, 44, vx); + _mav_put_int16_t(buf, 46, vy); + _mav_put_int16_t(buf, 48, vz); + _mav_put_int16_t(buf, 50, xacc); + _mav_put_int16_t(buf, 52, yacc); + _mav_put_int16_t(buf, 54, zacc); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 56); +#else + mavlink_hil_state_t packet; + packet.time_usec = time_usec; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 56); +#endif + + msg->msgid = MAVLINK_MSG_ID_HIL_STATE; + return mavlink_finalize_message(msg, system_id, component_id, 56, 183); +} + +/** + * @brief Pack a hil_state message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + * @param lat Latitude, expressed as * 1E7 + * @param lon Longitude, expressed as * 1E7 + * @param alt Altitude in meters, expressed as * 1000 (millimeters) + * @param vx Ground X Speed (Latitude), expressed as m/s * 100 + * @param vy Ground Y Speed (Longitude), expressed as m/s * 100 + * @param vz Ground Z Speed (Altitude), expressed as m/s * 100 + * @param xacc X acceleration (mg) + * @param yacc Y acceleration (mg) + * @param zacc Z acceleration (mg) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hil_state_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time_usec,float roll,float pitch,float yaw,float rollspeed,float pitchspeed,float yawspeed,int32_t lat,int32_t lon,int32_t alt,int16_t vx,int16_t vy,int16_t vz,int16_t xacc,int16_t yacc,int16_t zacc) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[56]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_float(buf, 8, roll); + _mav_put_float(buf, 12, pitch); + _mav_put_float(buf, 16, yaw); + _mav_put_float(buf, 20, rollspeed); + _mav_put_float(buf, 24, pitchspeed); + _mav_put_float(buf, 28, yawspeed); + _mav_put_int32_t(buf, 32, lat); + _mav_put_int32_t(buf, 36, lon); + _mav_put_int32_t(buf, 40, alt); + _mav_put_int16_t(buf, 44, vx); + _mav_put_int16_t(buf, 46, vy); + _mav_put_int16_t(buf, 48, vz); + _mav_put_int16_t(buf, 50, xacc); + _mav_put_int16_t(buf, 52, yacc); + _mav_put_int16_t(buf, 54, zacc); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 56); +#else + mavlink_hil_state_t packet; + packet.time_usec = time_usec; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 56); +#endif + + msg->msgid = MAVLINK_MSG_ID_HIL_STATE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 56, 183); +} + +/** + * @brief Encode a hil_state struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param hil_state C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_hil_state_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_hil_state_t* hil_state) +{ + return mavlink_msg_hil_state_pack(system_id, component_id, msg, hil_state->time_usec, hil_state->roll, hil_state->pitch, hil_state->yaw, hil_state->rollspeed, hil_state->pitchspeed, hil_state->yawspeed, hil_state->lat, hil_state->lon, hil_state->alt, hil_state->vx, hil_state->vy, hil_state->vz, hil_state->xacc, hil_state->yacc, hil_state->zacc); +} + +/** + * @brief Send a hil_state message + * @param chan MAVLink channel to send the message + * + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param rollspeed Roll angular speed (rad/s) + * @param pitchspeed Pitch angular speed (rad/s) + * @param yawspeed Yaw angular speed (rad/s) + * @param lat Latitude, expressed as * 1E7 + * @param lon Longitude, expressed as * 1E7 + * @param alt Altitude in meters, expressed as * 1000 (millimeters) + * @param vx Ground X Speed (Latitude), expressed as m/s * 100 + * @param vy Ground Y Speed (Longitude), expressed as m/s * 100 + * @param vz Ground Z Speed (Altitude), expressed as m/s * 100 + * @param xacc X acceleration (mg) + * @param yacc Y acceleration (mg) + * @param zacc Z acceleration (mg) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_hil_state_send(mavlink_channel_t chan, uint64_t time_usec, float roll, float pitch, float yaw, float rollspeed, float pitchspeed, float yawspeed, int32_t lat, int32_t lon, int32_t alt, int16_t vx, int16_t vy, int16_t vz, int16_t xacc, int16_t yacc, int16_t zacc) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[56]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_float(buf, 8, roll); + _mav_put_float(buf, 12, pitch); + _mav_put_float(buf, 16, yaw); + _mav_put_float(buf, 20, rollspeed); + _mav_put_float(buf, 24, pitchspeed); + _mav_put_float(buf, 28, yawspeed); + _mav_put_int32_t(buf, 32, lat); + _mav_put_int32_t(buf, 36, lon); + _mav_put_int32_t(buf, 40, alt); + _mav_put_int16_t(buf, 44, vx); + _mav_put_int16_t(buf, 46, vy); + _mav_put_int16_t(buf, 48, vz); + _mav_put_int16_t(buf, 50, xacc); + _mav_put_int16_t(buf, 52, yacc); + _mav_put_int16_t(buf, 54, zacc); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HIL_STATE, buf, 56, 183); +#else + mavlink_hil_state_t packet; + packet.time_usec = time_usec; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.rollspeed = rollspeed; + packet.pitchspeed = pitchspeed; + packet.yawspeed = yawspeed; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HIL_STATE, (const char *)&packet, 56, 183); +#endif +} + +#endif + +// MESSAGE HIL_STATE UNPACKING + + +/** + * @brief Get field time_usec from hil_state message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_hil_state_get_time_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field roll from hil_state message + * + * @return Roll angle (rad) + */ +static inline float mavlink_msg_hil_state_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field pitch from hil_state message + * + * @return Pitch angle (rad) + */ +static inline float mavlink_msg_hil_state_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field yaw from hil_state message + * + * @return Yaw angle (rad) + */ +static inline float mavlink_msg_hil_state_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field rollspeed from hil_state message + * + * @return Roll angular speed (rad/s) + */ +static inline float mavlink_msg_hil_state_get_rollspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field pitchspeed from hil_state message + * + * @return Pitch angular speed (rad/s) + */ +static inline float mavlink_msg_hil_state_get_pitchspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field yawspeed from hil_state message + * + * @return Yaw angular speed (rad/s) + */ +static inline float mavlink_msg_hil_state_get_yawspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field lat from hil_state message + * + * @return Latitude, expressed as * 1E7 + */ +static inline int32_t mavlink_msg_hil_state_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 32); +} + +/** + * @brief Get field lon from hil_state message + * + * @return Longitude, expressed as * 1E7 + */ +static inline int32_t mavlink_msg_hil_state_get_lon(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 36); +} + +/** + * @brief Get field alt from hil_state message + * + * @return Altitude in meters, expressed as * 1000 (millimeters) + */ +static inline int32_t mavlink_msg_hil_state_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 40); +} + +/** + * @brief Get field vx from hil_state message + * + * @return Ground X Speed (Latitude), expressed as m/s * 100 + */ +static inline int16_t mavlink_msg_hil_state_get_vx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 44); +} + +/** + * @brief Get field vy from hil_state message + * + * @return Ground Y Speed (Longitude), expressed as m/s * 100 + */ +static inline int16_t mavlink_msg_hil_state_get_vy(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 46); +} + +/** + * @brief Get field vz from hil_state message + * + * @return Ground Z Speed (Altitude), expressed as m/s * 100 + */ +static inline int16_t mavlink_msg_hil_state_get_vz(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 48); +} + +/** + * @brief Get field xacc from hil_state message + * + * @return X acceleration (mg) + */ +static inline int16_t mavlink_msg_hil_state_get_xacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 50); +} + +/** + * @brief Get field yacc from hil_state message + * + * @return Y acceleration (mg) + */ +static inline int16_t mavlink_msg_hil_state_get_yacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 52); +} + +/** + * @brief Get field zacc from hil_state message + * + * @return Z acceleration (mg) + */ +static inline int16_t mavlink_msg_hil_state_get_zacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 54); +} + +/** + * @brief Decode a hil_state message into a struct + * + * @param msg The message to decode + * @param hil_state C-struct to decode the message contents into + */ +static inline void mavlink_msg_hil_state_decode(const mavlink_message_t* msg, mavlink_hil_state_t* hil_state) +{ +#if MAVLINK_NEED_BYTE_SWAP + hil_state->time_usec = mavlink_msg_hil_state_get_time_usec(msg); + hil_state->roll = mavlink_msg_hil_state_get_roll(msg); + hil_state->pitch = mavlink_msg_hil_state_get_pitch(msg); + hil_state->yaw = mavlink_msg_hil_state_get_yaw(msg); + hil_state->rollspeed = mavlink_msg_hil_state_get_rollspeed(msg); + hil_state->pitchspeed = mavlink_msg_hil_state_get_pitchspeed(msg); + hil_state->yawspeed = mavlink_msg_hil_state_get_yawspeed(msg); + hil_state->lat = mavlink_msg_hil_state_get_lat(msg); + hil_state->lon = mavlink_msg_hil_state_get_lon(msg); + hil_state->alt = mavlink_msg_hil_state_get_alt(msg); + hil_state->vx = mavlink_msg_hil_state_get_vx(msg); + hil_state->vy = mavlink_msg_hil_state_get_vy(msg); + hil_state->vz = mavlink_msg_hil_state_get_vz(msg); + hil_state->xacc = mavlink_msg_hil_state_get_xacc(msg); + hil_state->yacc = mavlink_msg_hil_state_get_yacc(msg); + hil_state->zacc = mavlink_msg_hil_state_get_zacc(msg); +#else + memcpy(hil_state, _MAV_PAYLOAD(msg), 56); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_local_position_ned.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_local_position_ned.h new file mode 100644 index 0000000000..fe0a791fc5 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_local_position_ned.h @@ -0,0 +1,276 @@ +// MESSAGE LOCAL_POSITION_NED PACKING + +#define MAVLINK_MSG_ID_LOCAL_POSITION_NED 32 + +typedef struct __mavlink_local_position_ned_t +{ + uint32_t time_boot_ms; ///< Timestamp (milliseconds since system boot) + float x; ///< X Position + float y; ///< Y Position + float z; ///< Z Position + float vx; ///< X Speed + float vy; ///< Y Speed + float vz; ///< Z Speed +} mavlink_local_position_ned_t; + +#define MAVLINK_MSG_ID_LOCAL_POSITION_NED_LEN 28 +#define MAVLINK_MSG_ID_32_LEN 28 + + + +#define MAVLINK_MESSAGE_INFO_LOCAL_POSITION_NED { \ + "LOCAL_POSITION_NED", \ + 7, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_local_position_ned_t, time_boot_ms) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_local_position_ned_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_local_position_ned_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_local_position_ned_t, z) }, \ + { "vx", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_local_position_ned_t, vx) }, \ + { "vy", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_local_position_ned_t, vy) }, \ + { "vz", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_local_position_ned_t, vz) }, \ + } \ +} + + +/** + * @brief Pack a local_position_ned message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param vx X Speed + * @param vy Y Speed + * @param vz Z Speed + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_local_position_ned_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, float x, float y, float z, float vx, float vy, float vz) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, x); + _mav_put_float(buf, 8, y); + _mav_put_float(buf, 12, z); + _mav_put_float(buf, 16, vx); + _mav_put_float(buf, 20, vy); + _mav_put_float(buf, 24, vz); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_local_position_ned_t packet; + packet.time_boot_ms = time_boot_ms; + packet.x = x; + packet.y = y; + packet.z = z; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_LOCAL_POSITION_NED; + return mavlink_finalize_message(msg, system_id, component_id, 28, 185); +} + +/** + * @brief Pack a local_position_ned message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param vx X Speed + * @param vy Y Speed + * @param vz Z Speed + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_local_position_ned_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,float x,float y,float z,float vx,float vy,float vz) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, x); + _mav_put_float(buf, 8, y); + _mav_put_float(buf, 12, z); + _mav_put_float(buf, 16, vx); + _mav_put_float(buf, 20, vy); + _mav_put_float(buf, 24, vz); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_local_position_ned_t packet; + packet.time_boot_ms = time_boot_ms; + packet.x = x; + packet.y = y; + packet.z = z; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_LOCAL_POSITION_NED; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 28, 185); +} + +/** + * @brief Encode a local_position_ned struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param local_position_ned C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_local_position_ned_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_local_position_ned_t* local_position_ned) +{ + return mavlink_msg_local_position_ned_pack(system_id, component_id, msg, local_position_ned->time_boot_ms, local_position_ned->x, local_position_ned->y, local_position_ned->z, local_position_ned->vx, local_position_ned->vy, local_position_ned->vz); +} + +/** + * @brief Send a local_position_ned message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param vx X Speed + * @param vy Y Speed + * @param vz Z Speed + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_local_position_ned_send(mavlink_channel_t chan, uint32_t time_boot_ms, float x, float y, float z, float vx, float vy, float vz) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, x); + _mav_put_float(buf, 8, y); + _mav_put_float(buf, 12, z); + _mav_put_float(buf, 16, vx); + _mav_put_float(buf, 20, vy); + _mav_put_float(buf, 24, vz); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LOCAL_POSITION_NED, buf, 28, 185); +#else + mavlink_local_position_ned_t packet; + packet.time_boot_ms = time_boot_ms; + packet.x = x; + packet.y = y; + packet.z = z; + packet.vx = vx; + packet.vy = vy; + packet.vz = vz; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LOCAL_POSITION_NED, (const char *)&packet, 28, 185); +#endif +} + +#endif + +// MESSAGE LOCAL_POSITION_NED UNPACKING + + +/** + * @brief Get field time_boot_ms from local_position_ned message + * + * @return Timestamp (milliseconds since system boot) + */ +static inline uint32_t mavlink_msg_local_position_ned_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field x from local_position_ned message + * + * @return X Position + */ +static inline float mavlink_msg_local_position_ned_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field y from local_position_ned message + * + * @return Y Position + */ +static inline float mavlink_msg_local_position_ned_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field z from local_position_ned message + * + * @return Z Position + */ +static inline float mavlink_msg_local_position_ned_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field vx from local_position_ned message + * + * @return X Speed + */ +static inline float mavlink_msg_local_position_ned_get_vx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field vy from local_position_ned message + * + * @return Y Speed + */ +static inline float mavlink_msg_local_position_ned_get_vy(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field vz from local_position_ned message + * + * @return Z Speed + */ +static inline float mavlink_msg_local_position_ned_get_vz(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Decode a local_position_ned message into a struct + * + * @param msg The message to decode + * @param local_position_ned C-struct to decode the message contents into + */ +static inline void mavlink_msg_local_position_ned_decode(const mavlink_message_t* msg, mavlink_local_position_ned_t* local_position_ned) +{ +#if MAVLINK_NEED_BYTE_SWAP + local_position_ned->time_boot_ms = mavlink_msg_local_position_ned_get_time_boot_ms(msg); + local_position_ned->x = mavlink_msg_local_position_ned_get_x(msg); + local_position_ned->y = mavlink_msg_local_position_ned_get_y(msg); + local_position_ned->z = mavlink_msg_local_position_ned_get_z(msg); + local_position_ned->vx = mavlink_msg_local_position_ned_get_vx(msg); + local_position_ned->vy = mavlink_msg_local_position_ned_get_vy(msg); + local_position_ned->vz = mavlink_msg_local_position_ned_get_vz(msg); +#else + memcpy(local_position_ned, _MAV_PAYLOAD(msg), 28); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_local_position_ned_system_global_offset.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_local_position_ned_system_global_offset.h new file mode 100644 index 0000000000..ac1941db09 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_local_position_ned_system_global_offset.h @@ -0,0 +1,276 @@ +// MESSAGE LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET PACKING + +#define MAVLINK_MSG_ID_LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET 89 + +typedef struct __mavlink_local_position_ned_system_global_offset_t +{ + uint32_t time_boot_ms; ///< Timestamp (milliseconds since system boot) + float x; ///< X Position + float y; ///< Y Position + float z; ///< Z Position + float roll; ///< Roll + float pitch; ///< Pitch + float yaw; ///< Yaw +} mavlink_local_position_ned_system_global_offset_t; + +#define MAVLINK_MSG_ID_LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET_LEN 28 +#define MAVLINK_MSG_ID_89_LEN 28 + + + +#define MAVLINK_MESSAGE_INFO_LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET { \ + "LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET", \ + 7, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_local_position_ned_system_global_offset_t, time_boot_ms) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_local_position_ned_system_global_offset_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_local_position_ned_system_global_offset_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_local_position_ned_system_global_offset_t, z) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_local_position_ned_system_global_offset_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_local_position_ned_system_global_offset_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_local_position_ned_system_global_offset_t, yaw) }, \ + } \ +} + + +/** + * @brief Pack a local_position_ned_system_global_offset message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param roll Roll + * @param pitch Pitch + * @param yaw Yaw + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_local_position_ned_system_global_offset_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, x); + _mav_put_float(buf, 8, y); + _mav_put_float(buf, 12, z); + _mav_put_float(buf, 16, roll); + _mav_put_float(buf, 20, pitch); + _mav_put_float(buf, 24, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_local_position_ned_system_global_offset_t packet; + packet.time_boot_ms = time_boot_ms; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET; + return mavlink_finalize_message(msg, system_id, component_id, 28, 231); +} + +/** + * @brief Pack a local_position_ned_system_global_offset message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param roll Roll + * @param pitch Pitch + * @param yaw Yaw + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_local_position_ned_system_global_offset_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,float x,float y,float z,float roll,float pitch,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, x); + _mav_put_float(buf, 8, y); + _mav_put_float(buf, 12, z); + _mav_put_float(buf, 16, roll); + _mav_put_float(buf, 20, pitch); + _mav_put_float(buf, 24, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 28); +#else + mavlink_local_position_ned_system_global_offset_t packet; + packet.time_boot_ms = time_boot_ms; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 28, 231); +} + +/** + * @brief Encode a local_position_ned_system_global_offset struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param local_position_ned_system_global_offset C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_local_position_ned_system_global_offset_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_local_position_ned_system_global_offset_t* local_position_ned_system_global_offset) +{ + return mavlink_msg_local_position_ned_system_global_offset_pack(system_id, component_id, msg, local_position_ned_system_global_offset->time_boot_ms, local_position_ned_system_global_offset->x, local_position_ned_system_global_offset->y, local_position_ned_system_global_offset->z, local_position_ned_system_global_offset->roll, local_position_ned_system_global_offset->pitch, local_position_ned_system_global_offset->yaw); +} + +/** + * @brief Send a local_position_ned_system_global_offset message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param roll Roll + * @param pitch Pitch + * @param yaw Yaw + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_local_position_ned_system_global_offset_send(mavlink_channel_t chan, uint32_t time_boot_ms, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, x); + _mav_put_float(buf, 8, y); + _mav_put_float(buf, 12, z); + _mav_put_float(buf, 16, roll); + _mav_put_float(buf, 20, pitch); + _mav_put_float(buf, 24, yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET, buf, 28, 231); +#else + mavlink_local_position_ned_system_global_offset_t packet; + packet.time_boot_ms = time_boot_ms; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET, (const char *)&packet, 28, 231); +#endif +} + +#endif + +// MESSAGE LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET UNPACKING + + +/** + * @brief Get field time_boot_ms from local_position_ned_system_global_offset message + * + * @return Timestamp (milliseconds since system boot) + */ +static inline uint32_t mavlink_msg_local_position_ned_system_global_offset_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field x from local_position_ned_system_global_offset message + * + * @return X Position + */ +static inline float mavlink_msg_local_position_ned_system_global_offset_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field y from local_position_ned_system_global_offset message + * + * @return Y Position + */ +static inline float mavlink_msg_local_position_ned_system_global_offset_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field z from local_position_ned_system_global_offset message + * + * @return Z Position + */ +static inline float mavlink_msg_local_position_ned_system_global_offset_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field roll from local_position_ned_system_global_offset message + * + * @return Roll + */ +static inline float mavlink_msg_local_position_ned_system_global_offset_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field pitch from local_position_ned_system_global_offset message + * + * @return Pitch + */ +static inline float mavlink_msg_local_position_ned_system_global_offset_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field yaw from local_position_ned_system_global_offset message + * + * @return Yaw + */ +static inline float mavlink_msg_local_position_ned_system_global_offset_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Decode a local_position_ned_system_global_offset message into a struct + * + * @param msg The message to decode + * @param local_position_ned_system_global_offset C-struct to decode the message contents into + */ +static inline void mavlink_msg_local_position_ned_system_global_offset_decode(const mavlink_message_t* msg, mavlink_local_position_ned_system_global_offset_t* local_position_ned_system_global_offset) +{ +#if MAVLINK_NEED_BYTE_SWAP + local_position_ned_system_global_offset->time_boot_ms = mavlink_msg_local_position_ned_system_global_offset_get_time_boot_ms(msg); + local_position_ned_system_global_offset->x = mavlink_msg_local_position_ned_system_global_offset_get_x(msg); + local_position_ned_system_global_offset->y = mavlink_msg_local_position_ned_system_global_offset_get_y(msg); + local_position_ned_system_global_offset->z = mavlink_msg_local_position_ned_system_global_offset_get_z(msg); + local_position_ned_system_global_offset->roll = mavlink_msg_local_position_ned_system_global_offset_get_roll(msg); + local_position_ned_system_global_offset->pitch = mavlink_msg_local_position_ned_system_global_offset_get_pitch(msg); + local_position_ned_system_global_offset->yaw = mavlink_msg_local_position_ned_system_global_offset_get_yaw(msg); +#else + memcpy(local_position_ned_system_global_offset, _MAV_PAYLOAD(msg), 28); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_local_position_setpoint.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_local_position_setpoint.h new file mode 100644 index 0000000000..9ab87d0daf --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_local_position_setpoint.h @@ -0,0 +1,232 @@ +// MESSAGE LOCAL_POSITION_SETPOINT PACKING + +#define MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT 51 + +typedef struct __mavlink_local_position_setpoint_t +{ + float x; ///< x position + float y; ///< y position + float z; ///< z position + float yaw; ///< Desired yaw angle + uint8_t coordinate_frame; ///< Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU +} mavlink_local_position_setpoint_t; + +#define MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT_LEN 17 +#define MAVLINK_MSG_ID_51_LEN 17 + + + +#define MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT { \ + "LOCAL_POSITION_SETPOINT", \ + 5, \ + { { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_local_position_setpoint_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_local_position_setpoint_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_local_position_setpoint_t, z) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_local_position_setpoint_t, yaw) }, \ + { "coordinate_frame", NULL, MAVLINK_TYPE_UINT8_T, 0, 16, offsetof(mavlink_local_position_setpoint_t, coordinate_frame) }, \ + } \ +} + + +/** + * @brief Pack a local_position_setpoint message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param coordinate_frame Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU + * @param x x position + * @param y y position + * @param z z position + * @param yaw Desired yaw angle + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_local_position_setpoint_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t coordinate_frame, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[17]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + _mav_put_uint8_t(buf, 16, coordinate_frame); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 17); +#else + mavlink_local_position_setpoint_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + packet.coordinate_frame = coordinate_frame; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 17); +#endif + + msg->msgid = MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT; + return mavlink_finalize_message(msg, system_id, component_id, 17, 223); +} + +/** + * @brief Pack a local_position_setpoint message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param coordinate_frame Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU + * @param x x position + * @param y y position + * @param z z position + * @param yaw Desired yaw angle + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_local_position_setpoint_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t coordinate_frame,float x,float y,float z,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[17]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + _mav_put_uint8_t(buf, 16, coordinate_frame); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 17); +#else + mavlink_local_position_setpoint_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + packet.coordinate_frame = coordinate_frame; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 17); +#endif + + msg->msgid = MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 17, 223); +} + +/** + * @brief Encode a local_position_setpoint struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param local_position_setpoint C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_local_position_setpoint_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_local_position_setpoint_t* local_position_setpoint) +{ + return mavlink_msg_local_position_setpoint_pack(system_id, component_id, msg, local_position_setpoint->coordinate_frame, local_position_setpoint->x, local_position_setpoint->y, local_position_setpoint->z, local_position_setpoint->yaw); +} + +/** + * @brief Send a local_position_setpoint message + * @param chan MAVLink channel to send the message + * + * @param coordinate_frame Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU + * @param x x position + * @param y y position + * @param z z position + * @param yaw Desired yaw angle + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_local_position_setpoint_send(mavlink_channel_t chan, uint8_t coordinate_frame, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[17]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + _mav_put_uint8_t(buf, 16, coordinate_frame); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT, buf, 17, 223); +#else + mavlink_local_position_setpoint_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + packet.coordinate_frame = coordinate_frame; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT, (const char *)&packet, 17, 223); +#endif +} + +#endif + +// MESSAGE LOCAL_POSITION_SETPOINT UNPACKING + + +/** + * @brief Get field coordinate_frame from local_position_setpoint message + * + * @return Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU + */ +static inline uint8_t mavlink_msg_local_position_setpoint_get_coordinate_frame(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 16); +} + +/** + * @brief Get field x from local_position_setpoint message + * + * @return x position + */ +static inline float mavlink_msg_local_position_setpoint_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field y from local_position_setpoint message + * + * @return y position + */ +static inline float mavlink_msg_local_position_setpoint_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field z from local_position_setpoint message + * + * @return z position + */ +static inline float mavlink_msg_local_position_setpoint_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field yaw from local_position_setpoint message + * + * @return Desired yaw angle + */ +static inline float mavlink_msg_local_position_setpoint_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Decode a local_position_setpoint message into a struct + * + * @param msg The message to decode + * @param local_position_setpoint C-struct to decode the message contents into + */ +static inline void mavlink_msg_local_position_setpoint_decode(const mavlink_message_t* msg, mavlink_local_position_setpoint_t* local_position_setpoint) +{ +#if MAVLINK_NEED_BYTE_SWAP + local_position_setpoint->x = mavlink_msg_local_position_setpoint_get_x(msg); + local_position_setpoint->y = mavlink_msg_local_position_setpoint_get_y(msg); + local_position_setpoint->z = mavlink_msg_local_position_setpoint_get_z(msg); + local_position_setpoint->yaw = mavlink_msg_local_position_setpoint_get_yaw(msg); + local_position_setpoint->coordinate_frame = mavlink_msg_local_position_setpoint_get_coordinate_frame(msg); +#else + memcpy(local_position_setpoint, _MAV_PAYLOAD(msg), 17); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_manual_control.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_manual_control.h new file mode 100644 index 0000000000..93adce265b --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_manual_control.h @@ -0,0 +1,320 @@ +// MESSAGE MANUAL_CONTROL PACKING + +#define MAVLINK_MSG_ID_MANUAL_CONTROL 69 + +typedef struct __mavlink_manual_control_t +{ + float roll; ///< roll + float pitch; ///< pitch + float yaw; ///< yaw + float thrust; ///< thrust + uint8_t target; ///< The system to be controlled + uint8_t roll_manual; ///< roll control enabled auto:0, manual:1 + uint8_t pitch_manual; ///< pitch auto:0, manual:1 + uint8_t yaw_manual; ///< yaw auto:0, manual:1 + uint8_t thrust_manual; ///< thrust auto:0, manual:1 +} mavlink_manual_control_t; + +#define MAVLINK_MSG_ID_MANUAL_CONTROL_LEN 21 +#define MAVLINK_MSG_ID_69_LEN 21 + + + +#define MAVLINK_MESSAGE_INFO_MANUAL_CONTROL { \ + "MANUAL_CONTROL", \ + 9, \ + { { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_manual_control_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_manual_control_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_manual_control_t, yaw) }, \ + { "thrust", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_manual_control_t, thrust) }, \ + { "target", NULL, MAVLINK_TYPE_UINT8_T, 0, 16, offsetof(mavlink_manual_control_t, target) }, \ + { "roll_manual", NULL, MAVLINK_TYPE_UINT8_T, 0, 17, offsetof(mavlink_manual_control_t, roll_manual) }, \ + { "pitch_manual", NULL, MAVLINK_TYPE_UINT8_T, 0, 18, offsetof(mavlink_manual_control_t, pitch_manual) }, \ + { "yaw_manual", NULL, MAVLINK_TYPE_UINT8_T, 0, 19, offsetof(mavlink_manual_control_t, yaw_manual) }, \ + { "thrust_manual", NULL, MAVLINK_TYPE_UINT8_T, 0, 20, offsetof(mavlink_manual_control_t, thrust_manual) }, \ + } \ +} + + +/** + * @brief Pack a manual_control message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target The system to be controlled + * @param roll roll + * @param pitch pitch + * @param yaw yaw + * @param thrust thrust + * @param roll_manual roll control enabled auto:0, manual:1 + * @param pitch_manual pitch auto:0, manual:1 + * @param yaw_manual yaw auto:0, manual:1 + * @param thrust_manual thrust auto:0, manual:1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_manual_control_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target, float roll, float pitch, float yaw, float thrust, uint8_t roll_manual, uint8_t pitch_manual, uint8_t yaw_manual, uint8_t thrust_manual) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, thrust); + _mav_put_uint8_t(buf, 16, target); + _mav_put_uint8_t(buf, 17, roll_manual); + _mav_put_uint8_t(buf, 18, pitch_manual); + _mav_put_uint8_t(buf, 19, yaw_manual); + _mav_put_uint8_t(buf, 20, thrust_manual); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 21); +#else + mavlink_manual_control_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + packet.target = target; + packet.roll_manual = roll_manual; + packet.pitch_manual = pitch_manual; + packet.yaw_manual = yaw_manual; + packet.thrust_manual = thrust_manual; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 21); +#endif + + msg->msgid = MAVLINK_MSG_ID_MANUAL_CONTROL; + return mavlink_finalize_message(msg, system_id, component_id, 21, 52); +} + +/** + * @brief Pack a manual_control message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system to be controlled + * @param roll roll + * @param pitch pitch + * @param yaw yaw + * @param thrust thrust + * @param roll_manual roll control enabled auto:0, manual:1 + * @param pitch_manual pitch auto:0, manual:1 + * @param yaw_manual yaw auto:0, manual:1 + * @param thrust_manual thrust auto:0, manual:1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_manual_control_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,float roll,float pitch,float yaw,float thrust,uint8_t roll_manual,uint8_t pitch_manual,uint8_t yaw_manual,uint8_t thrust_manual) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, thrust); + _mav_put_uint8_t(buf, 16, target); + _mav_put_uint8_t(buf, 17, roll_manual); + _mav_put_uint8_t(buf, 18, pitch_manual); + _mav_put_uint8_t(buf, 19, yaw_manual); + _mav_put_uint8_t(buf, 20, thrust_manual); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 21); +#else + mavlink_manual_control_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + packet.target = target; + packet.roll_manual = roll_manual; + packet.pitch_manual = pitch_manual; + packet.yaw_manual = yaw_manual; + packet.thrust_manual = thrust_manual; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 21); +#endif + + msg->msgid = MAVLINK_MSG_ID_MANUAL_CONTROL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 21, 52); +} + +/** + * @brief Encode a manual_control struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param manual_control C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_manual_control_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_manual_control_t* manual_control) +{ + return mavlink_msg_manual_control_pack(system_id, component_id, msg, manual_control->target, manual_control->roll, manual_control->pitch, manual_control->yaw, manual_control->thrust, manual_control->roll_manual, manual_control->pitch_manual, manual_control->yaw_manual, manual_control->thrust_manual); +} + +/** + * @brief Send a manual_control message + * @param chan MAVLink channel to send the message + * + * @param target The system to be controlled + * @param roll roll + * @param pitch pitch + * @param yaw yaw + * @param thrust thrust + * @param roll_manual roll control enabled auto:0, manual:1 + * @param pitch_manual pitch auto:0, manual:1 + * @param yaw_manual yaw auto:0, manual:1 + * @param thrust_manual thrust auto:0, manual:1 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_manual_control_send(mavlink_channel_t chan, uint8_t target, float roll, float pitch, float yaw, float thrust, uint8_t roll_manual, uint8_t pitch_manual, uint8_t yaw_manual, uint8_t thrust_manual) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, thrust); + _mav_put_uint8_t(buf, 16, target); + _mav_put_uint8_t(buf, 17, roll_manual); + _mav_put_uint8_t(buf, 18, pitch_manual); + _mav_put_uint8_t(buf, 19, yaw_manual); + _mav_put_uint8_t(buf, 20, thrust_manual); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MANUAL_CONTROL, buf, 21, 52); +#else + mavlink_manual_control_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + packet.target = target; + packet.roll_manual = roll_manual; + packet.pitch_manual = pitch_manual; + packet.yaw_manual = yaw_manual; + packet.thrust_manual = thrust_manual; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MANUAL_CONTROL, (const char *)&packet, 21, 52); +#endif +} + +#endif + +// MESSAGE MANUAL_CONTROL UNPACKING + + +/** + * @brief Get field target from manual_control message + * + * @return The system to be controlled + */ +static inline uint8_t mavlink_msg_manual_control_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 16); +} + +/** + * @brief Get field roll from manual_control message + * + * @return roll + */ +static inline float mavlink_msg_manual_control_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field pitch from manual_control message + * + * @return pitch + */ +static inline float mavlink_msg_manual_control_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field yaw from manual_control message + * + * @return yaw + */ +static inline float mavlink_msg_manual_control_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field thrust from manual_control message + * + * @return thrust + */ +static inline float mavlink_msg_manual_control_get_thrust(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field roll_manual from manual_control message + * + * @return roll control enabled auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_manual_control_get_roll_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 17); +} + +/** + * @brief Get field pitch_manual from manual_control message + * + * @return pitch auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_manual_control_get_pitch_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 18); +} + +/** + * @brief Get field yaw_manual from manual_control message + * + * @return yaw auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_manual_control_get_yaw_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 19); +} + +/** + * @brief Get field thrust_manual from manual_control message + * + * @return thrust auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_manual_control_get_thrust_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 20); +} + +/** + * @brief Decode a manual_control message into a struct + * + * @param msg The message to decode + * @param manual_control C-struct to decode the message contents into + */ +static inline void mavlink_msg_manual_control_decode(const mavlink_message_t* msg, mavlink_manual_control_t* manual_control) +{ +#if MAVLINK_NEED_BYTE_SWAP + manual_control->roll = mavlink_msg_manual_control_get_roll(msg); + manual_control->pitch = mavlink_msg_manual_control_get_pitch(msg); + manual_control->yaw = mavlink_msg_manual_control_get_yaw(msg); + manual_control->thrust = mavlink_msg_manual_control_get_thrust(msg); + manual_control->target = mavlink_msg_manual_control_get_target(msg); + manual_control->roll_manual = mavlink_msg_manual_control_get_roll_manual(msg); + manual_control->pitch_manual = mavlink_msg_manual_control_get_pitch_manual(msg); + manual_control->yaw_manual = mavlink_msg_manual_control_get_yaw_manual(msg); + manual_control->thrust_manual = mavlink_msg_manual_control_get_thrust_manual(msg); +#else + memcpy(manual_control, _MAV_PAYLOAD(msg), 21); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_memory_vect.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_memory_vect.h new file mode 100644 index 0000000000..a61c13019b --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_memory_vect.h @@ -0,0 +1,204 @@ +// MESSAGE MEMORY_VECT PACKING + +#define MAVLINK_MSG_ID_MEMORY_VECT 249 + +typedef struct __mavlink_memory_vect_t +{ + uint16_t address; ///< Starting address of the debug variables + uint8_t ver; ///< Version code of the type variable. 0=unknown, type ignored and assumed int16_t. 1=as below + uint8_t type; ///< Type code of the memory variables. for ver = 1: 0=16 x int16_t, 1=16 x uint16_t, 2=16 x Q15, 3=16 x 1Q14 + int8_t value[32]; ///< Memory contents at specified address +} mavlink_memory_vect_t; + +#define MAVLINK_MSG_ID_MEMORY_VECT_LEN 36 +#define MAVLINK_MSG_ID_249_LEN 36 + +#define MAVLINK_MSG_MEMORY_VECT_FIELD_VALUE_LEN 32 + +#define MAVLINK_MESSAGE_INFO_MEMORY_VECT { \ + "MEMORY_VECT", \ + 4, \ + { { "address", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_memory_vect_t, address) }, \ + { "ver", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_memory_vect_t, ver) }, \ + { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_memory_vect_t, type) }, \ + { "value", NULL, MAVLINK_TYPE_INT8_T, 32, 4, offsetof(mavlink_memory_vect_t, value) }, \ + } \ +} + + +/** + * @brief Pack a memory_vect message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param address Starting address of the debug variables + * @param ver Version code of the type variable. 0=unknown, type ignored and assumed int16_t. 1=as below + * @param type Type code of the memory variables. for ver = 1: 0=16 x int16_t, 1=16 x uint16_t, 2=16 x Q15, 3=16 x 1Q14 + * @param value Memory contents at specified address + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_memory_vect_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t address, uint8_t ver, uint8_t type, const int8_t *value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_uint16_t(buf, 0, address); + _mav_put_uint8_t(buf, 2, ver); + _mav_put_uint8_t(buf, 3, type); + _mav_put_int8_t_array(buf, 4, value, 32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_memory_vect_t packet; + packet.address = address; + packet.ver = ver; + packet.type = type; + mav_array_memcpy(packet.value, value, sizeof(int8_t)*32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_MEMORY_VECT; + return mavlink_finalize_message(msg, system_id, component_id, 36, 204); +} + +/** + * @brief Pack a memory_vect message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param address Starting address of the debug variables + * @param ver Version code of the type variable. 0=unknown, type ignored and assumed int16_t. 1=as below + * @param type Type code of the memory variables. for ver = 1: 0=16 x int16_t, 1=16 x uint16_t, 2=16 x Q15, 3=16 x 1Q14 + * @param value Memory contents at specified address + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_memory_vect_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t address,uint8_t ver,uint8_t type,const int8_t *value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_uint16_t(buf, 0, address); + _mav_put_uint8_t(buf, 2, ver); + _mav_put_uint8_t(buf, 3, type); + _mav_put_int8_t_array(buf, 4, value, 32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_memory_vect_t packet; + packet.address = address; + packet.ver = ver; + packet.type = type; + mav_array_memcpy(packet.value, value, sizeof(int8_t)*32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_MEMORY_VECT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 36, 204); +} + +/** + * @brief Encode a memory_vect struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param memory_vect C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_memory_vect_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_memory_vect_t* memory_vect) +{ + return mavlink_msg_memory_vect_pack(system_id, component_id, msg, memory_vect->address, memory_vect->ver, memory_vect->type, memory_vect->value); +} + +/** + * @brief Send a memory_vect message + * @param chan MAVLink channel to send the message + * + * @param address Starting address of the debug variables + * @param ver Version code of the type variable. 0=unknown, type ignored and assumed int16_t. 1=as below + * @param type Type code of the memory variables. for ver = 1: 0=16 x int16_t, 1=16 x uint16_t, 2=16 x Q15, 3=16 x 1Q14 + * @param value Memory contents at specified address + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_memory_vect_send(mavlink_channel_t chan, uint16_t address, uint8_t ver, uint8_t type, const int8_t *value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_uint16_t(buf, 0, address); + _mav_put_uint8_t(buf, 2, ver); + _mav_put_uint8_t(buf, 3, type); + _mav_put_int8_t_array(buf, 4, value, 32); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MEMORY_VECT, buf, 36, 204); +#else + mavlink_memory_vect_t packet; + packet.address = address; + packet.ver = ver; + packet.type = type; + mav_array_memcpy(packet.value, value, sizeof(int8_t)*32); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MEMORY_VECT, (const char *)&packet, 36, 204); +#endif +} + +#endif + +// MESSAGE MEMORY_VECT UNPACKING + + +/** + * @brief Get field address from memory_vect message + * + * @return Starting address of the debug variables + */ +static inline uint16_t mavlink_msg_memory_vect_get_address(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field ver from memory_vect message + * + * @return Version code of the type variable. 0=unknown, type ignored and assumed int16_t. 1=as below + */ +static inline uint8_t mavlink_msg_memory_vect_get_ver(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field type from memory_vect message + * + * @return Type code of the memory variables. for ver = 1: 0=16 x int16_t, 1=16 x uint16_t, 2=16 x Q15, 3=16 x 1Q14 + */ +static inline uint8_t mavlink_msg_memory_vect_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field value from memory_vect message + * + * @return Memory contents at specified address + */ +static inline uint16_t mavlink_msg_memory_vect_get_value(const mavlink_message_t* msg, int8_t *value) +{ + return _MAV_RETURN_int8_t_array(msg, value, 32, 4); +} + +/** + * @brief Decode a memory_vect message into a struct + * + * @param msg The message to decode + * @param memory_vect C-struct to decode the message contents into + */ +static inline void mavlink_msg_memory_vect_decode(const mavlink_message_t* msg, mavlink_memory_vect_t* memory_vect) +{ +#if MAVLINK_NEED_BYTE_SWAP + memory_vect->address = mavlink_msg_memory_vect_get_address(msg); + memory_vect->ver = mavlink_msg_memory_vect_get_ver(msg); + memory_vect->type = mavlink_msg_memory_vect_get_type(msg); + mavlink_msg_memory_vect_get_value(msg, memory_vect->value); +#else + memcpy(memory_vect, _MAV_PAYLOAD(msg), 36); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_ack.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_ack.h new file mode 100644 index 0000000000..92eca79d1c --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_ack.h @@ -0,0 +1,188 @@ +// MESSAGE MISSION_ACK PACKING + +#define MAVLINK_MSG_ID_MISSION_ACK 47 + +typedef struct __mavlink_mission_ack_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t type; ///< See MAV_MISSION_RESULT enum +} mavlink_mission_ack_t; + +#define MAVLINK_MSG_ID_MISSION_ACK_LEN 3 +#define MAVLINK_MSG_ID_47_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_MISSION_ACK { \ + "MISSION_ACK", \ + 3, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_mission_ack_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_mission_ack_t, target_component) }, \ + { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_mission_ack_t, type) }, \ + } \ +} + + +/** + * @brief Pack a mission_ack message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param type See MAV_MISSION_RESULT enum + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_ack_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t type) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, type); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_mission_ack_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.type = type; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_ACK; + return mavlink_finalize_message(msg, system_id, component_id, 3, 153); +} + +/** + * @brief Pack a mission_ack message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param type See MAV_MISSION_RESULT enum + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_ack_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t type) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, type); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_mission_ack_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.type = type; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_ACK; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3, 153); +} + +/** + * @brief Encode a mission_ack struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mission_ack C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mission_ack_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mission_ack_t* mission_ack) +{ + return mavlink_msg_mission_ack_pack(system_id, component_id, msg, mission_ack->target_system, mission_ack->target_component, mission_ack->type); +} + +/** + * @brief Send a mission_ack message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param type See MAV_MISSION_RESULT enum + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mission_ack_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t type) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + _mav_put_uint8_t(buf, 2, type); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_ACK, buf, 3, 153); +#else + mavlink_mission_ack_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + packet.type = type; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_ACK, (const char *)&packet, 3, 153); +#endif +} + +#endif + +// MESSAGE MISSION_ACK UNPACKING + + +/** + * @brief Get field target_system from mission_ack message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mission_ack_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from mission_ack message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mission_ack_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field type from mission_ack message + * + * @return See MAV_MISSION_RESULT enum + */ +static inline uint8_t mavlink_msg_mission_ack_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a mission_ack message into a struct + * + * @param msg The message to decode + * @param mission_ack C-struct to decode the message contents into + */ +static inline void mavlink_msg_mission_ack_decode(const mavlink_message_t* msg, mavlink_mission_ack_t* mission_ack) +{ +#if MAVLINK_NEED_BYTE_SWAP + mission_ack->target_system = mavlink_msg_mission_ack_get_target_system(msg); + mission_ack->target_component = mavlink_msg_mission_ack_get_target_component(msg); + mission_ack->type = mavlink_msg_mission_ack_get_type(msg); +#else + memcpy(mission_ack, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_clear_all.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_clear_all.h new file mode 100644 index 0000000000..602852f7e3 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_clear_all.h @@ -0,0 +1,166 @@ +// MESSAGE MISSION_CLEAR_ALL PACKING + +#define MAVLINK_MSG_ID_MISSION_CLEAR_ALL 45 + +typedef struct __mavlink_mission_clear_all_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_mission_clear_all_t; + +#define MAVLINK_MSG_ID_MISSION_CLEAR_ALL_LEN 2 +#define MAVLINK_MSG_ID_45_LEN 2 + + + +#define MAVLINK_MESSAGE_INFO_MISSION_CLEAR_ALL { \ + "MISSION_CLEAR_ALL", \ + 2, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_mission_clear_all_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_mission_clear_all_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a mission_clear_all message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_clear_all_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_mission_clear_all_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_CLEAR_ALL; + return mavlink_finalize_message(msg, system_id, component_id, 2, 232); +} + +/** + * @brief Pack a mission_clear_all message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_clear_all_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_mission_clear_all_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_CLEAR_ALL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 2, 232); +} + +/** + * @brief Encode a mission_clear_all struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mission_clear_all C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mission_clear_all_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mission_clear_all_t* mission_clear_all) +{ + return mavlink_msg_mission_clear_all_pack(system_id, component_id, msg, mission_clear_all->target_system, mission_clear_all->target_component); +} + +/** + * @brief Send a mission_clear_all message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mission_clear_all_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_CLEAR_ALL, buf, 2, 232); +#else + mavlink_mission_clear_all_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_CLEAR_ALL, (const char *)&packet, 2, 232); +#endif +} + +#endif + +// MESSAGE MISSION_CLEAR_ALL UNPACKING + + +/** + * @brief Get field target_system from mission_clear_all message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mission_clear_all_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from mission_clear_all message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mission_clear_all_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Decode a mission_clear_all message into a struct + * + * @param msg The message to decode + * @param mission_clear_all C-struct to decode the message contents into + */ +static inline void mavlink_msg_mission_clear_all_decode(const mavlink_message_t* msg, mavlink_mission_clear_all_t* mission_clear_all) +{ +#if MAVLINK_NEED_BYTE_SWAP + mission_clear_all->target_system = mavlink_msg_mission_clear_all_get_target_system(msg); + mission_clear_all->target_component = mavlink_msg_mission_clear_all_get_target_component(msg); +#else + memcpy(mission_clear_all, _MAV_PAYLOAD(msg), 2); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_count.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_count.h new file mode 100644 index 0000000000..61d8b221c3 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_count.h @@ -0,0 +1,188 @@ +// MESSAGE MISSION_COUNT PACKING + +#define MAVLINK_MSG_ID_MISSION_COUNT 44 + +typedef struct __mavlink_mission_count_t +{ + uint16_t count; ///< Number of mission items in the sequence + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_mission_count_t; + +#define MAVLINK_MSG_ID_MISSION_COUNT_LEN 4 +#define MAVLINK_MSG_ID_44_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_MISSION_COUNT { \ + "MISSION_COUNT", \ + 3, \ + { { "count", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_mission_count_t, count) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_mission_count_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_mission_count_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a mission_count message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param count Number of mission items in the sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_count_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint16_t count) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, count); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_mission_count_t packet; + packet.count = count; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_COUNT; + return mavlink_finalize_message(msg, system_id, component_id, 4, 221); +} + +/** + * @brief Pack a mission_count message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param count Number of mission items in the sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_count_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint16_t count) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, count); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_mission_count_t packet; + packet.count = count; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_COUNT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4, 221); +} + +/** + * @brief Encode a mission_count struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mission_count C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mission_count_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mission_count_t* mission_count) +{ + return mavlink_msg_mission_count_pack(system_id, component_id, msg, mission_count->target_system, mission_count->target_component, mission_count->count); +} + +/** + * @brief Send a mission_count message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param count Number of mission items in the sequence + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mission_count_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint16_t count) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, count); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_COUNT, buf, 4, 221); +#else + mavlink_mission_count_t packet; + packet.count = count; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_COUNT, (const char *)&packet, 4, 221); +#endif +} + +#endif + +// MESSAGE MISSION_COUNT UNPACKING + + +/** + * @brief Get field target_system from mission_count message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mission_count_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field target_component from mission_count message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mission_count_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field count from mission_count message + * + * @return Number of mission items in the sequence + */ +static inline uint16_t mavlink_msg_mission_count_get_count(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Decode a mission_count message into a struct + * + * @param msg The message to decode + * @param mission_count C-struct to decode the message contents into + */ +static inline void mavlink_msg_mission_count_decode(const mavlink_message_t* msg, mavlink_mission_count_t* mission_count) +{ +#if MAVLINK_NEED_BYTE_SWAP + mission_count->count = mavlink_msg_mission_count_get_count(msg); + mission_count->target_system = mavlink_msg_mission_count_get_target_system(msg); + mission_count->target_component = mavlink_msg_mission_count_get_target_component(msg); +#else + memcpy(mission_count, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_current.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_current.h new file mode 100644 index 0000000000..99370f8353 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_current.h @@ -0,0 +1,144 @@ +// MESSAGE MISSION_CURRENT PACKING + +#define MAVLINK_MSG_ID_MISSION_CURRENT 42 + +typedef struct __mavlink_mission_current_t +{ + uint16_t seq; ///< Sequence +} mavlink_mission_current_t; + +#define MAVLINK_MSG_ID_MISSION_CURRENT_LEN 2 +#define MAVLINK_MSG_ID_42_LEN 2 + + + +#define MAVLINK_MESSAGE_INFO_MISSION_CURRENT { \ + "MISSION_CURRENT", \ + 1, \ + { { "seq", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_mission_current_t, seq) }, \ + } \ +} + + +/** + * @brief Pack a mission_current message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_current_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint16_t(buf, 0, seq); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_mission_current_t packet; + packet.seq = seq; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_CURRENT; + return mavlink_finalize_message(msg, system_id, component_id, 2, 28); +} + +/** + * @brief Pack a mission_current message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_current_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint16_t(buf, 0, seq); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_mission_current_t packet; + packet.seq = seq; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_CURRENT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 2, 28); +} + +/** + * @brief Encode a mission_current struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mission_current C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mission_current_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mission_current_t* mission_current) +{ + return mavlink_msg_mission_current_pack(system_id, component_id, msg, mission_current->seq); +} + +/** + * @brief Send a mission_current message + * @param chan MAVLink channel to send the message + * + * @param seq Sequence + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mission_current_send(mavlink_channel_t chan, uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint16_t(buf, 0, seq); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_CURRENT, buf, 2, 28); +#else + mavlink_mission_current_t packet; + packet.seq = seq; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_CURRENT, (const char *)&packet, 2, 28); +#endif +} + +#endif + +// MESSAGE MISSION_CURRENT UNPACKING + + +/** + * @brief Get field seq from mission_current message + * + * @return Sequence + */ +static inline uint16_t mavlink_msg_mission_current_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Decode a mission_current message into a struct + * + * @param msg The message to decode + * @param mission_current C-struct to decode the message contents into + */ +static inline void mavlink_msg_mission_current_decode(const mavlink_message_t* msg, mavlink_mission_current_t* mission_current) +{ +#if MAVLINK_NEED_BYTE_SWAP + mission_current->seq = mavlink_msg_mission_current_get_seq(msg); +#else + memcpy(mission_current, _MAV_PAYLOAD(msg), 2); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_item.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_item.h new file mode 100644 index 0000000000..d2c66d4daa --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_item.h @@ -0,0 +1,430 @@ +// MESSAGE MISSION_ITEM PACKING + +#define MAVLINK_MSG_ID_MISSION_ITEM 39 + +typedef struct __mavlink_mission_item_t +{ + float param1; ///< PARAM1 / For NAV command MISSIONs: Radius in which the MISSION is accepted as reached, in meters + float param2; ///< PARAM2 / For NAV command MISSIONs: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds + float param3; ///< PARAM3 / For LOITER command MISSIONs: Orbit to circle around the MISSION, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. + float param4; ///< PARAM4 / For NAV and LOITER command MISSIONs: Yaw orientation in degrees, [0..360] 0 = NORTH + float x; ///< PARAM5 / local: x position, global: latitude + float y; ///< PARAM6 / y position: global: longitude + float z; ///< PARAM7 / z position: global: altitude + uint16_t seq; ///< Sequence + uint16_t command; ///< The scheduled action for the MISSION. see MAV_CMD in common.xml MAVLink specs + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t frame; ///< The coordinate system of the MISSION. see MAV_FRAME in mavlink_types.h + uint8_t current; ///< false:0, true:1 + uint8_t autocontinue; ///< autocontinue to next wp +} mavlink_mission_item_t; + +#define MAVLINK_MSG_ID_MISSION_ITEM_LEN 37 +#define MAVLINK_MSG_ID_39_LEN 37 + + + +#define MAVLINK_MESSAGE_INFO_MISSION_ITEM { \ + "MISSION_ITEM", \ + 14, \ + { { "param1", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_mission_item_t, param1) }, \ + { "param2", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_mission_item_t, param2) }, \ + { "param3", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_mission_item_t, param3) }, \ + { "param4", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_mission_item_t, param4) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_mission_item_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_mission_item_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_mission_item_t, z) }, \ + { "seq", NULL, MAVLINK_TYPE_UINT16_T, 0, 28, offsetof(mavlink_mission_item_t, seq) }, \ + { "command", NULL, MAVLINK_TYPE_UINT16_T, 0, 30, offsetof(mavlink_mission_item_t, command) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 32, offsetof(mavlink_mission_item_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 33, offsetof(mavlink_mission_item_t, target_component) }, \ + { "frame", NULL, MAVLINK_TYPE_UINT8_T, 0, 34, offsetof(mavlink_mission_item_t, frame) }, \ + { "current", NULL, MAVLINK_TYPE_UINT8_T, 0, 35, offsetof(mavlink_mission_item_t, current) }, \ + { "autocontinue", NULL, MAVLINK_TYPE_UINT8_T, 0, 36, offsetof(mavlink_mission_item_t, autocontinue) }, \ + } \ +} + + +/** + * @brief Pack a mission_item message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @param frame The coordinate system of the MISSION. see MAV_FRAME in mavlink_types.h + * @param command The scheduled action for the MISSION. see MAV_CMD in common.xml MAVLink specs + * @param current false:0, true:1 + * @param autocontinue autocontinue to next wp + * @param param1 PARAM1 / For NAV command MISSIONs: Radius in which the MISSION is accepted as reached, in meters + * @param param2 PARAM2 / For NAV command MISSIONs: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds + * @param param3 PARAM3 / For LOITER command MISSIONs: Orbit to circle around the MISSION, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. + * @param param4 PARAM4 / For NAV and LOITER command MISSIONs: Yaw orientation in degrees, [0..360] 0 = NORTH + * @param x PARAM5 / local: x position, global: latitude + * @param y PARAM6 / y position: global: longitude + * @param z PARAM7 / z position: global: altitude + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_item_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint16_t seq, uint8_t frame, uint16_t command, uint8_t current, uint8_t autocontinue, float param1, float param2, float param3, float param4, float x, float y, float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[37]; + _mav_put_float(buf, 0, param1); + _mav_put_float(buf, 4, param2); + _mav_put_float(buf, 8, param3); + _mav_put_float(buf, 12, param4); + _mav_put_float(buf, 16, x); + _mav_put_float(buf, 20, y); + _mav_put_float(buf, 24, z); + _mav_put_uint16_t(buf, 28, seq); + _mav_put_uint16_t(buf, 30, command); + _mav_put_uint8_t(buf, 32, target_system); + _mav_put_uint8_t(buf, 33, target_component); + _mav_put_uint8_t(buf, 34, frame); + _mav_put_uint8_t(buf, 35, current); + _mav_put_uint8_t(buf, 36, autocontinue); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 37); +#else + mavlink_mission_item_t packet; + packet.param1 = param1; + packet.param2 = param2; + packet.param3 = param3; + packet.param4 = param4; + packet.x = x; + packet.y = y; + packet.z = z; + packet.seq = seq; + packet.command = command; + packet.target_system = target_system; + packet.target_component = target_component; + packet.frame = frame; + packet.current = current; + packet.autocontinue = autocontinue; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 37); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_ITEM; + return mavlink_finalize_message(msg, system_id, component_id, 37, 254); +} + +/** + * @brief Pack a mission_item message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @param frame The coordinate system of the MISSION. see MAV_FRAME in mavlink_types.h + * @param command The scheduled action for the MISSION. see MAV_CMD in common.xml MAVLink specs + * @param current false:0, true:1 + * @param autocontinue autocontinue to next wp + * @param param1 PARAM1 / For NAV command MISSIONs: Radius in which the MISSION is accepted as reached, in meters + * @param param2 PARAM2 / For NAV command MISSIONs: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds + * @param param3 PARAM3 / For LOITER command MISSIONs: Orbit to circle around the MISSION, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. + * @param param4 PARAM4 / For NAV and LOITER command MISSIONs: Yaw orientation in degrees, [0..360] 0 = NORTH + * @param x PARAM5 / local: x position, global: latitude + * @param y PARAM6 / y position: global: longitude + * @param z PARAM7 / z position: global: altitude + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_item_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint16_t seq,uint8_t frame,uint16_t command,uint8_t current,uint8_t autocontinue,float param1,float param2,float param3,float param4,float x,float y,float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[37]; + _mav_put_float(buf, 0, param1); + _mav_put_float(buf, 4, param2); + _mav_put_float(buf, 8, param3); + _mav_put_float(buf, 12, param4); + _mav_put_float(buf, 16, x); + _mav_put_float(buf, 20, y); + _mav_put_float(buf, 24, z); + _mav_put_uint16_t(buf, 28, seq); + _mav_put_uint16_t(buf, 30, command); + _mav_put_uint8_t(buf, 32, target_system); + _mav_put_uint8_t(buf, 33, target_component); + _mav_put_uint8_t(buf, 34, frame); + _mav_put_uint8_t(buf, 35, current); + _mav_put_uint8_t(buf, 36, autocontinue); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 37); +#else + mavlink_mission_item_t packet; + packet.param1 = param1; + packet.param2 = param2; + packet.param3 = param3; + packet.param4 = param4; + packet.x = x; + packet.y = y; + packet.z = z; + packet.seq = seq; + packet.command = command; + packet.target_system = target_system; + packet.target_component = target_component; + packet.frame = frame; + packet.current = current; + packet.autocontinue = autocontinue; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 37); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_ITEM; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 37, 254); +} + +/** + * @brief Encode a mission_item struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mission_item C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mission_item_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mission_item_t* mission_item) +{ + return mavlink_msg_mission_item_pack(system_id, component_id, msg, mission_item->target_system, mission_item->target_component, mission_item->seq, mission_item->frame, mission_item->command, mission_item->current, mission_item->autocontinue, mission_item->param1, mission_item->param2, mission_item->param3, mission_item->param4, mission_item->x, mission_item->y, mission_item->z); +} + +/** + * @brief Send a mission_item message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @param frame The coordinate system of the MISSION. see MAV_FRAME in mavlink_types.h + * @param command The scheduled action for the MISSION. see MAV_CMD in common.xml MAVLink specs + * @param current false:0, true:1 + * @param autocontinue autocontinue to next wp + * @param param1 PARAM1 / For NAV command MISSIONs: Radius in which the MISSION is accepted as reached, in meters + * @param param2 PARAM2 / For NAV command MISSIONs: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds + * @param param3 PARAM3 / For LOITER command MISSIONs: Orbit to circle around the MISSION, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. + * @param param4 PARAM4 / For NAV and LOITER command MISSIONs: Yaw orientation in degrees, [0..360] 0 = NORTH + * @param x PARAM5 / local: x position, global: latitude + * @param y PARAM6 / y position: global: longitude + * @param z PARAM7 / z position: global: altitude + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mission_item_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint16_t seq, uint8_t frame, uint16_t command, uint8_t current, uint8_t autocontinue, float param1, float param2, float param3, float param4, float x, float y, float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[37]; + _mav_put_float(buf, 0, param1); + _mav_put_float(buf, 4, param2); + _mav_put_float(buf, 8, param3); + _mav_put_float(buf, 12, param4); + _mav_put_float(buf, 16, x); + _mav_put_float(buf, 20, y); + _mav_put_float(buf, 24, z); + _mav_put_uint16_t(buf, 28, seq); + _mav_put_uint16_t(buf, 30, command); + _mav_put_uint8_t(buf, 32, target_system); + _mav_put_uint8_t(buf, 33, target_component); + _mav_put_uint8_t(buf, 34, frame); + _mav_put_uint8_t(buf, 35, current); + _mav_put_uint8_t(buf, 36, autocontinue); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_ITEM, buf, 37, 254); +#else + mavlink_mission_item_t packet; + packet.param1 = param1; + packet.param2 = param2; + packet.param3 = param3; + packet.param4 = param4; + packet.x = x; + packet.y = y; + packet.z = z; + packet.seq = seq; + packet.command = command; + packet.target_system = target_system; + packet.target_component = target_component; + packet.frame = frame; + packet.current = current; + packet.autocontinue = autocontinue; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_ITEM, (const char *)&packet, 37, 254); +#endif +} + +#endif + +// MESSAGE MISSION_ITEM UNPACKING + + +/** + * @brief Get field target_system from mission_item message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mission_item_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 32); +} + +/** + * @brief Get field target_component from mission_item message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mission_item_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 33); +} + +/** + * @brief Get field seq from mission_item message + * + * @return Sequence + */ +static inline uint16_t mavlink_msg_mission_item_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 28); +} + +/** + * @brief Get field frame from mission_item message + * + * @return The coordinate system of the MISSION. see MAV_FRAME in mavlink_types.h + */ +static inline uint8_t mavlink_msg_mission_item_get_frame(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 34); +} + +/** + * @brief Get field command from mission_item message + * + * @return The scheduled action for the MISSION. see MAV_CMD in common.xml MAVLink specs + */ +static inline uint16_t mavlink_msg_mission_item_get_command(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 30); +} + +/** + * @brief Get field current from mission_item message + * + * @return false:0, true:1 + */ +static inline uint8_t mavlink_msg_mission_item_get_current(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 35); +} + +/** + * @brief Get field autocontinue from mission_item message + * + * @return autocontinue to next wp + */ +static inline uint8_t mavlink_msg_mission_item_get_autocontinue(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 36); +} + +/** + * @brief Get field param1 from mission_item message + * + * @return PARAM1 / For NAV command MISSIONs: Radius in which the MISSION is accepted as reached, in meters + */ +static inline float mavlink_msg_mission_item_get_param1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field param2 from mission_item message + * + * @return PARAM2 / For NAV command MISSIONs: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds + */ +static inline float mavlink_msg_mission_item_get_param2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field param3 from mission_item message + * + * @return PARAM3 / For LOITER command MISSIONs: Orbit to circle around the MISSION, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. + */ +static inline float mavlink_msg_mission_item_get_param3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field param4 from mission_item message + * + * @return PARAM4 / For NAV and LOITER command MISSIONs: Yaw orientation in degrees, [0..360] 0 = NORTH + */ +static inline float mavlink_msg_mission_item_get_param4(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field x from mission_item message + * + * @return PARAM5 / local: x position, global: latitude + */ +static inline float mavlink_msg_mission_item_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field y from mission_item message + * + * @return PARAM6 / y position: global: longitude + */ +static inline float mavlink_msg_mission_item_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field z from mission_item message + * + * @return PARAM7 / z position: global: altitude + */ +static inline float mavlink_msg_mission_item_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Decode a mission_item message into a struct + * + * @param msg The message to decode + * @param mission_item C-struct to decode the message contents into + */ +static inline void mavlink_msg_mission_item_decode(const mavlink_message_t* msg, mavlink_mission_item_t* mission_item) +{ +#if MAVLINK_NEED_BYTE_SWAP + mission_item->param1 = mavlink_msg_mission_item_get_param1(msg); + mission_item->param2 = mavlink_msg_mission_item_get_param2(msg); + mission_item->param3 = mavlink_msg_mission_item_get_param3(msg); + mission_item->param4 = mavlink_msg_mission_item_get_param4(msg); + mission_item->x = mavlink_msg_mission_item_get_x(msg); + mission_item->y = mavlink_msg_mission_item_get_y(msg); + mission_item->z = mavlink_msg_mission_item_get_z(msg); + mission_item->seq = mavlink_msg_mission_item_get_seq(msg); + mission_item->command = mavlink_msg_mission_item_get_command(msg); + mission_item->target_system = mavlink_msg_mission_item_get_target_system(msg); + mission_item->target_component = mavlink_msg_mission_item_get_target_component(msg); + mission_item->frame = mavlink_msg_mission_item_get_frame(msg); + mission_item->current = mavlink_msg_mission_item_get_current(msg); + mission_item->autocontinue = mavlink_msg_mission_item_get_autocontinue(msg); +#else + memcpy(mission_item, _MAV_PAYLOAD(msg), 37); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_item_reached.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_item_reached.h new file mode 100644 index 0000000000..171f9857e8 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_item_reached.h @@ -0,0 +1,144 @@ +// MESSAGE MISSION_ITEM_REACHED PACKING + +#define MAVLINK_MSG_ID_MISSION_ITEM_REACHED 46 + +typedef struct __mavlink_mission_item_reached_t +{ + uint16_t seq; ///< Sequence +} mavlink_mission_item_reached_t; + +#define MAVLINK_MSG_ID_MISSION_ITEM_REACHED_LEN 2 +#define MAVLINK_MSG_ID_46_LEN 2 + + + +#define MAVLINK_MESSAGE_INFO_MISSION_ITEM_REACHED { \ + "MISSION_ITEM_REACHED", \ + 1, \ + { { "seq", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_mission_item_reached_t, seq) }, \ + } \ +} + + +/** + * @brief Pack a mission_item_reached message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_item_reached_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint16_t(buf, 0, seq); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_mission_item_reached_t packet; + packet.seq = seq; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_ITEM_REACHED; + return mavlink_finalize_message(msg, system_id, component_id, 2, 11); +} + +/** + * @brief Pack a mission_item_reached message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_item_reached_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint16_t(buf, 0, seq); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_mission_item_reached_t packet; + packet.seq = seq; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_ITEM_REACHED; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 2, 11); +} + +/** + * @brief Encode a mission_item_reached struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mission_item_reached C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mission_item_reached_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mission_item_reached_t* mission_item_reached) +{ + return mavlink_msg_mission_item_reached_pack(system_id, component_id, msg, mission_item_reached->seq); +} + +/** + * @brief Send a mission_item_reached message + * @param chan MAVLink channel to send the message + * + * @param seq Sequence + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mission_item_reached_send(mavlink_channel_t chan, uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint16_t(buf, 0, seq); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_ITEM_REACHED, buf, 2, 11); +#else + mavlink_mission_item_reached_t packet; + packet.seq = seq; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_ITEM_REACHED, (const char *)&packet, 2, 11); +#endif +} + +#endif + +// MESSAGE MISSION_ITEM_REACHED UNPACKING + + +/** + * @brief Get field seq from mission_item_reached message + * + * @return Sequence + */ +static inline uint16_t mavlink_msg_mission_item_reached_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Decode a mission_item_reached message into a struct + * + * @param msg The message to decode + * @param mission_item_reached C-struct to decode the message contents into + */ +static inline void mavlink_msg_mission_item_reached_decode(const mavlink_message_t* msg, mavlink_mission_item_reached_t* mission_item_reached) +{ +#if MAVLINK_NEED_BYTE_SWAP + mission_item_reached->seq = mavlink_msg_mission_item_reached_get_seq(msg); +#else + memcpy(mission_item_reached, _MAV_PAYLOAD(msg), 2); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_request.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_request.h new file mode 100644 index 0000000000..cde0a0cfb9 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_request.h @@ -0,0 +1,188 @@ +// MESSAGE MISSION_REQUEST PACKING + +#define MAVLINK_MSG_ID_MISSION_REQUEST 40 + +typedef struct __mavlink_mission_request_t +{ + uint16_t seq; ///< Sequence + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_mission_request_t; + +#define MAVLINK_MSG_ID_MISSION_REQUEST_LEN 4 +#define MAVLINK_MSG_ID_40_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_MISSION_REQUEST { \ + "MISSION_REQUEST", \ + 3, \ + { { "seq", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_mission_request_t, seq) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_mission_request_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_mission_request_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a mission_request message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_request_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, seq); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_mission_request_t packet; + packet.seq = seq; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_REQUEST; + return mavlink_finalize_message(msg, system_id, component_id, 4, 230); +} + +/** + * @brief Pack a mission_request message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_request_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, seq); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_mission_request_t packet; + packet.seq = seq; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_REQUEST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4, 230); +} + +/** + * @brief Encode a mission_request struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mission_request C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mission_request_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mission_request_t* mission_request) +{ + return mavlink_msg_mission_request_pack(system_id, component_id, msg, mission_request->target_system, mission_request->target_component, mission_request->seq); +} + +/** + * @brief Send a mission_request message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mission_request_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, seq); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_REQUEST, buf, 4, 230); +#else + mavlink_mission_request_t packet; + packet.seq = seq; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_REQUEST, (const char *)&packet, 4, 230); +#endif +} + +#endif + +// MESSAGE MISSION_REQUEST UNPACKING + + +/** + * @brief Get field target_system from mission_request message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mission_request_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field target_component from mission_request message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mission_request_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field seq from mission_request message + * + * @return Sequence + */ +static inline uint16_t mavlink_msg_mission_request_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Decode a mission_request message into a struct + * + * @param msg The message to decode + * @param mission_request C-struct to decode the message contents into + */ +static inline void mavlink_msg_mission_request_decode(const mavlink_message_t* msg, mavlink_mission_request_t* mission_request) +{ +#if MAVLINK_NEED_BYTE_SWAP + mission_request->seq = mavlink_msg_mission_request_get_seq(msg); + mission_request->target_system = mavlink_msg_mission_request_get_target_system(msg); + mission_request->target_component = mavlink_msg_mission_request_get_target_component(msg); +#else + memcpy(mission_request, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_request_list.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_request_list.h new file mode 100644 index 0000000000..1ada635b55 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_request_list.h @@ -0,0 +1,166 @@ +// MESSAGE MISSION_REQUEST_LIST PACKING + +#define MAVLINK_MSG_ID_MISSION_REQUEST_LIST 43 + +typedef struct __mavlink_mission_request_list_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_mission_request_list_t; + +#define MAVLINK_MSG_ID_MISSION_REQUEST_LIST_LEN 2 +#define MAVLINK_MSG_ID_43_LEN 2 + + + +#define MAVLINK_MESSAGE_INFO_MISSION_REQUEST_LIST { \ + "MISSION_REQUEST_LIST", \ + 2, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_mission_request_list_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_mission_request_list_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a mission_request_list message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_request_list_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_mission_request_list_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_REQUEST_LIST; + return mavlink_finalize_message(msg, system_id, component_id, 2, 132); +} + +/** + * @brief Pack a mission_request_list message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_request_list_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_mission_request_list_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_REQUEST_LIST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 2, 132); +} + +/** + * @brief Encode a mission_request_list struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mission_request_list C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mission_request_list_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mission_request_list_t* mission_request_list) +{ + return mavlink_msg_mission_request_list_pack(system_id, component_id, msg, mission_request_list->target_system, mission_request_list->target_component); +} + +/** + * @brief Send a mission_request_list message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mission_request_list_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_REQUEST_LIST, buf, 2, 132); +#else + mavlink_mission_request_list_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_REQUEST_LIST, (const char *)&packet, 2, 132); +#endif +} + +#endif + +// MESSAGE MISSION_REQUEST_LIST UNPACKING + + +/** + * @brief Get field target_system from mission_request_list message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mission_request_list_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from mission_request_list message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mission_request_list_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Decode a mission_request_list message into a struct + * + * @param msg The message to decode + * @param mission_request_list C-struct to decode the message contents into + */ +static inline void mavlink_msg_mission_request_list_decode(const mavlink_message_t* msg, mavlink_mission_request_list_t* mission_request_list) +{ +#if MAVLINK_NEED_BYTE_SWAP + mission_request_list->target_system = mavlink_msg_mission_request_list_get_target_system(msg); + mission_request_list->target_component = mavlink_msg_mission_request_list_get_target_component(msg); +#else + memcpy(mission_request_list, _MAV_PAYLOAD(msg), 2); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_request_partial_list.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_request_partial_list.h new file mode 100644 index 0000000000..76fd43befa --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_request_partial_list.h @@ -0,0 +1,210 @@ +// MESSAGE MISSION_REQUEST_PARTIAL_LIST PACKING + +#define MAVLINK_MSG_ID_MISSION_REQUEST_PARTIAL_LIST 37 + +typedef struct __mavlink_mission_request_partial_list_t +{ + int16_t start_index; ///< Start index, 0 by default + int16_t end_index; ///< End index, -1 by default (-1: send list to end). Else a valid index of the list + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_mission_request_partial_list_t; + +#define MAVLINK_MSG_ID_MISSION_REQUEST_PARTIAL_LIST_LEN 6 +#define MAVLINK_MSG_ID_37_LEN 6 + + + +#define MAVLINK_MESSAGE_INFO_MISSION_REQUEST_PARTIAL_LIST { \ + "MISSION_REQUEST_PARTIAL_LIST", \ + 4, \ + { { "start_index", NULL, MAVLINK_TYPE_INT16_T, 0, 0, offsetof(mavlink_mission_request_partial_list_t, start_index) }, \ + { "end_index", NULL, MAVLINK_TYPE_INT16_T, 0, 2, offsetof(mavlink_mission_request_partial_list_t, end_index) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_mission_request_partial_list_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_mission_request_partial_list_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a mission_request_partial_list message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param start_index Start index, 0 by default + * @param end_index End index, -1 by default (-1: send list to end). Else a valid index of the list + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_request_partial_list_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, int16_t start_index, int16_t end_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_int16_t(buf, 0, start_index); + _mav_put_int16_t(buf, 2, end_index); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_mission_request_partial_list_t packet; + packet.start_index = start_index; + packet.end_index = end_index; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_REQUEST_PARTIAL_LIST; + return mavlink_finalize_message(msg, system_id, component_id, 6, 212); +} + +/** + * @brief Pack a mission_request_partial_list message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param start_index Start index, 0 by default + * @param end_index End index, -1 by default (-1: send list to end). Else a valid index of the list + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_request_partial_list_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,int16_t start_index,int16_t end_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_int16_t(buf, 0, start_index); + _mav_put_int16_t(buf, 2, end_index); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_mission_request_partial_list_t packet; + packet.start_index = start_index; + packet.end_index = end_index; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_REQUEST_PARTIAL_LIST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 6, 212); +} + +/** + * @brief Encode a mission_request_partial_list struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mission_request_partial_list C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mission_request_partial_list_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mission_request_partial_list_t* mission_request_partial_list) +{ + return mavlink_msg_mission_request_partial_list_pack(system_id, component_id, msg, mission_request_partial_list->target_system, mission_request_partial_list->target_component, mission_request_partial_list->start_index, mission_request_partial_list->end_index); +} + +/** + * @brief Send a mission_request_partial_list message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param start_index Start index, 0 by default + * @param end_index End index, -1 by default (-1: send list to end). Else a valid index of the list + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mission_request_partial_list_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, int16_t start_index, int16_t end_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_int16_t(buf, 0, start_index); + _mav_put_int16_t(buf, 2, end_index); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_REQUEST_PARTIAL_LIST, buf, 6, 212); +#else + mavlink_mission_request_partial_list_t packet; + packet.start_index = start_index; + packet.end_index = end_index; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_REQUEST_PARTIAL_LIST, (const char *)&packet, 6, 212); +#endif +} + +#endif + +// MESSAGE MISSION_REQUEST_PARTIAL_LIST UNPACKING + + +/** + * @brief Get field target_system from mission_request_partial_list message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mission_request_partial_list_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field target_component from mission_request_partial_list message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mission_request_partial_list_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field start_index from mission_request_partial_list message + * + * @return Start index, 0 by default + */ +static inline int16_t mavlink_msg_mission_request_partial_list_get_start_index(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 0); +} + +/** + * @brief Get field end_index from mission_request_partial_list message + * + * @return End index, -1 by default (-1: send list to end). Else a valid index of the list + */ +static inline int16_t mavlink_msg_mission_request_partial_list_get_end_index(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 2); +} + +/** + * @brief Decode a mission_request_partial_list message into a struct + * + * @param msg The message to decode + * @param mission_request_partial_list C-struct to decode the message contents into + */ +static inline void mavlink_msg_mission_request_partial_list_decode(const mavlink_message_t* msg, mavlink_mission_request_partial_list_t* mission_request_partial_list) +{ +#if MAVLINK_NEED_BYTE_SWAP + mission_request_partial_list->start_index = mavlink_msg_mission_request_partial_list_get_start_index(msg); + mission_request_partial_list->end_index = mavlink_msg_mission_request_partial_list_get_end_index(msg); + mission_request_partial_list->target_system = mavlink_msg_mission_request_partial_list_get_target_system(msg); + mission_request_partial_list->target_component = mavlink_msg_mission_request_partial_list_get_target_component(msg); +#else + memcpy(mission_request_partial_list, _MAV_PAYLOAD(msg), 6); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_set_current.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_set_current.h new file mode 100644 index 0000000000..de0dbcd75d --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_set_current.h @@ -0,0 +1,188 @@ +// MESSAGE MISSION_SET_CURRENT PACKING + +#define MAVLINK_MSG_ID_MISSION_SET_CURRENT 41 + +typedef struct __mavlink_mission_set_current_t +{ + uint16_t seq; ///< Sequence + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_mission_set_current_t; + +#define MAVLINK_MSG_ID_MISSION_SET_CURRENT_LEN 4 +#define MAVLINK_MSG_ID_41_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_MISSION_SET_CURRENT { \ + "MISSION_SET_CURRENT", \ + 3, \ + { { "seq", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_mission_set_current_t, seq) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_mission_set_current_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_mission_set_current_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a mission_set_current message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_set_current_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, seq); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_mission_set_current_t packet; + packet.seq = seq; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_SET_CURRENT; + return mavlink_finalize_message(msg, system_id, component_id, 4, 28); +} + +/** + * @brief Pack a mission_set_current message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_set_current_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, seq); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_mission_set_current_t packet; + packet.seq = seq; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_SET_CURRENT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4, 28); +} + +/** + * @brief Encode a mission_set_current struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mission_set_current C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mission_set_current_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mission_set_current_t* mission_set_current) +{ + return mavlink_msg_mission_set_current_pack(system_id, component_id, msg, mission_set_current->target_system, mission_set_current->target_component, mission_set_current->seq); +} + +/** + * @brief Send a mission_set_current message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param seq Sequence + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mission_set_current_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint16_t seq) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, seq); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_SET_CURRENT, buf, 4, 28); +#else + mavlink_mission_set_current_t packet; + packet.seq = seq; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_SET_CURRENT, (const char *)&packet, 4, 28); +#endif +} + +#endif + +// MESSAGE MISSION_SET_CURRENT UNPACKING + + +/** + * @brief Get field target_system from mission_set_current message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mission_set_current_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field target_component from mission_set_current message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mission_set_current_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field seq from mission_set_current message + * + * @return Sequence + */ +static inline uint16_t mavlink_msg_mission_set_current_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Decode a mission_set_current message into a struct + * + * @param msg The message to decode + * @param mission_set_current C-struct to decode the message contents into + */ +static inline void mavlink_msg_mission_set_current_decode(const mavlink_message_t* msg, mavlink_mission_set_current_t* mission_set_current) +{ +#if MAVLINK_NEED_BYTE_SWAP + mission_set_current->seq = mavlink_msg_mission_set_current_get_seq(msg); + mission_set_current->target_system = mavlink_msg_mission_set_current_get_target_system(msg); + mission_set_current->target_component = mavlink_msg_mission_set_current_get_target_component(msg); +#else + memcpy(mission_set_current, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_write_partial_list.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_write_partial_list.h new file mode 100644 index 0000000000..0e77569cfc --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_mission_write_partial_list.h @@ -0,0 +1,210 @@ +// MESSAGE MISSION_WRITE_PARTIAL_LIST PACKING + +#define MAVLINK_MSG_ID_MISSION_WRITE_PARTIAL_LIST 38 + +typedef struct __mavlink_mission_write_partial_list_t +{ + int16_t start_index; ///< Start index, 0 by default and smaller / equal to the largest index of the current onboard list. + int16_t end_index; ///< End index, equal or greater than start index. + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_mission_write_partial_list_t; + +#define MAVLINK_MSG_ID_MISSION_WRITE_PARTIAL_LIST_LEN 6 +#define MAVLINK_MSG_ID_38_LEN 6 + + + +#define MAVLINK_MESSAGE_INFO_MISSION_WRITE_PARTIAL_LIST { \ + "MISSION_WRITE_PARTIAL_LIST", \ + 4, \ + { { "start_index", NULL, MAVLINK_TYPE_INT16_T, 0, 0, offsetof(mavlink_mission_write_partial_list_t, start_index) }, \ + { "end_index", NULL, MAVLINK_TYPE_INT16_T, 0, 2, offsetof(mavlink_mission_write_partial_list_t, end_index) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_mission_write_partial_list_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_mission_write_partial_list_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a mission_write_partial_list message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param start_index Start index, 0 by default and smaller / equal to the largest index of the current onboard list. + * @param end_index End index, equal or greater than start index. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_write_partial_list_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, int16_t start_index, int16_t end_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_int16_t(buf, 0, start_index); + _mav_put_int16_t(buf, 2, end_index); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_mission_write_partial_list_t packet; + packet.start_index = start_index; + packet.end_index = end_index; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_WRITE_PARTIAL_LIST; + return mavlink_finalize_message(msg, system_id, component_id, 6, 9); +} + +/** + * @brief Pack a mission_write_partial_list message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param start_index Start index, 0 by default and smaller / equal to the largest index of the current onboard list. + * @param end_index End index, equal or greater than start index. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mission_write_partial_list_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,int16_t start_index,int16_t end_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_int16_t(buf, 0, start_index); + _mav_put_int16_t(buf, 2, end_index); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_mission_write_partial_list_t packet; + packet.start_index = start_index; + packet.end_index = end_index; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_MISSION_WRITE_PARTIAL_LIST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 6, 9); +} + +/** + * @brief Encode a mission_write_partial_list struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mission_write_partial_list C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mission_write_partial_list_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mission_write_partial_list_t* mission_write_partial_list) +{ + return mavlink_msg_mission_write_partial_list_pack(system_id, component_id, msg, mission_write_partial_list->target_system, mission_write_partial_list->target_component, mission_write_partial_list->start_index, mission_write_partial_list->end_index); +} + +/** + * @brief Send a mission_write_partial_list message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param start_index Start index, 0 by default and smaller / equal to the largest index of the current onboard list. + * @param end_index End index, equal or greater than start index. + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mission_write_partial_list_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, int16_t start_index, int16_t end_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_int16_t(buf, 0, start_index); + _mav_put_int16_t(buf, 2, end_index); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_WRITE_PARTIAL_LIST, buf, 6, 9); +#else + mavlink_mission_write_partial_list_t packet; + packet.start_index = start_index; + packet.end_index = end_index; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MISSION_WRITE_PARTIAL_LIST, (const char *)&packet, 6, 9); +#endif +} + +#endif + +// MESSAGE MISSION_WRITE_PARTIAL_LIST UNPACKING + + +/** + * @brief Get field target_system from mission_write_partial_list message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_mission_write_partial_list_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field target_component from mission_write_partial_list message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_mission_write_partial_list_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field start_index from mission_write_partial_list message + * + * @return Start index, 0 by default and smaller / equal to the largest index of the current onboard list. + */ +static inline int16_t mavlink_msg_mission_write_partial_list_get_start_index(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 0); +} + +/** + * @brief Get field end_index from mission_write_partial_list message + * + * @return End index, equal or greater than start index. + */ +static inline int16_t mavlink_msg_mission_write_partial_list_get_end_index(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 2); +} + +/** + * @brief Decode a mission_write_partial_list message into a struct + * + * @param msg The message to decode + * @param mission_write_partial_list C-struct to decode the message contents into + */ +static inline void mavlink_msg_mission_write_partial_list_decode(const mavlink_message_t* msg, mavlink_mission_write_partial_list_t* mission_write_partial_list) +{ +#if MAVLINK_NEED_BYTE_SWAP + mission_write_partial_list->start_index = mavlink_msg_mission_write_partial_list_get_start_index(msg); + mission_write_partial_list->end_index = mavlink_msg_mission_write_partial_list_get_end_index(msg); + mission_write_partial_list->target_system = mavlink_msg_mission_write_partial_list_get_target_system(msg); + mission_write_partial_list->target_component = mavlink_msg_mission_write_partial_list_get_target_component(msg); +#else + memcpy(mission_write_partial_list, _MAV_PAYLOAD(msg), 6); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_named_value_float.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_named_value_float.h new file mode 100644 index 0000000000..23a819e2c9 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_named_value_float.h @@ -0,0 +1,182 @@ +// MESSAGE NAMED_VALUE_FLOAT PACKING + +#define MAVLINK_MSG_ID_NAMED_VALUE_FLOAT 251 + +typedef struct __mavlink_named_value_float_t +{ + uint32_t time_boot_ms; ///< Timestamp (milliseconds since system boot) + float value; ///< Floating point value + char name[10]; ///< Name of the debug variable +} mavlink_named_value_float_t; + +#define MAVLINK_MSG_ID_NAMED_VALUE_FLOAT_LEN 18 +#define MAVLINK_MSG_ID_251_LEN 18 + +#define MAVLINK_MSG_NAMED_VALUE_FLOAT_FIELD_NAME_LEN 10 + +#define MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT { \ + "NAMED_VALUE_FLOAT", \ + 3, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_named_value_float_t, time_boot_ms) }, \ + { "value", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_named_value_float_t, value) }, \ + { "name", NULL, MAVLINK_TYPE_CHAR, 10, 8, offsetof(mavlink_named_value_float_t, name) }, \ + } \ +} + + +/** + * @brief Pack a named_value_float message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param name Name of the debug variable + * @param value Floating point value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_named_value_float_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, const char *name, float value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, value); + _mav_put_char_array(buf, 8, name, 10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_named_value_float_t packet; + packet.time_boot_ms = time_boot_ms; + packet.value = value; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAMED_VALUE_FLOAT; + return mavlink_finalize_message(msg, system_id, component_id, 18, 170); +} + +/** + * @brief Pack a named_value_float message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param name Name of the debug variable + * @param value Floating point value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_named_value_float_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,const char *name,float value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, value); + _mav_put_char_array(buf, 8, name, 10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_named_value_float_t packet; + packet.time_boot_ms = time_boot_ms; + packet.value = value; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAMED_VALUE_FLOAT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18, 170); +} + +/** + * @brief Encode a named_value_float struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param named_value_float C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_named_value_float_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_named_value_float_t* named_value_float) +{ + return mavlink_msg_named_value_float_pack(system_id, component_id, msg, named_value_float->time_boot_ms, named_value_float->name, named_value_float->value); +} + +/** + * @brief Send a named_value_float message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param name Name of the debug variable + * @param value Floating point value + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_named_value_float_send(mavlink_channel_t chan, uint32_t time_boot_ms, const char *name, float value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, value); + _mav_put_char_array(buf, 8, name, 10); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAMED_VALUE_FLOAT, buf, 18, 170); +#else + mavlink_named_value_float_t packet; + packet.time_boot_ms = time_boot_ms; + packet.value = value; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAMED_VALUE_FLOAT, (const char *)&packet, 18, 170); +#endif +} + +#endif + +// MESSAGE NAMED_VALUE_FLOAT UNPACKING + + +/** + * @brief Get field time_boot_ms from named_value_float message + * + * @return Timestamp (milliseconds since system boot) + */ +static inline uint32_t mavlink_msg_named_value_float_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field name from named_value_float message + * + * @return Name of the debug variable + */ +static inline uint16_t mavlink_msg_named_value_float_get_name(const mavlink_message_t* msg, char *name) +{ + return _MAV_RETURN_char_array(msg, name, 10, 8); +} + +/** + * @brief Get field value from named_value_float message + * + * @return Floating point value + */ +static inline float mavlink_msg_named_value_float_get_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Decode a named_value_float message into a struct + * + * @param msg The message to decode + * @param named_value_float C-struct to decode the message contents into + */ +static inline void mavlink_msg_named_value_float_decode(const mavlink_message_t* msg, mavlink_named_value_float_t* named_value_float) +{ +#if MAVLINK_NEED_BYTE_SWAP + named_value_float->time_boot_ms = mavlink_msg_named_value_float_get_time_boot_ms(msg); + named_value_float->value = mavlink_msg_named_value_float_get_value(msg); + mavlink_msg_named_value_float_get_name(msg, named_value_float->name); +#else + memcpy(named_value_float, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_named_value_int.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_named_value_int.h new file mode 100644 index 0000000000..3c67dff03f --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_named_value_int.h @@ -0,0 +1,182 @@ +// MESSAGE NAMED_VALUE_INT PACKING + +#define MAVLINK_MSG_ID_NAMED_VALUE_INT 252 + +typedef struct __mavlink_named_value_int_t +{ + uint32_t time_boot_ms; ///< Timestamp (milliseconds since system boot) + int32_t value; ///< Signed integer value + char name[10]; ///< Name of the debug variable +} mavlink_named_value_int_t; + +#define MAVLINK_MSG_ID_NAMED_VALUE_INT_LEN 18 +#define MAVLINK_MSG_ID_252_LEN 18 + +#define MAVLINK_MSG_NAMED_VALUE_INT_FIELD_NAME_LEN 10 + +#define MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT { \ + "NAMED_VALUE_INT", \ + 3, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_named_value_int_t, time_boot_ms) }, \ + { "value", NULL, MAVLINK_TYPE_INT32_T, 0, 4, offsetof(mavlink_named_value_int_t, value) }, \ + { "name", NULL, MAVLINK_TYPE_CHAR, 10, 8, offsetof(mavlink_named_value_int_t, name) }, \ + } \ +} + + +/** + * @brief Pack a named_value_int message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param name Name of the debug variable + * @param value Signed integer value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_named_value_int_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, const char *name, int32_t value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_int32_t(buf, 4, value); + _mav_put_char_array(buf, 8, name, 10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_named_value_int_t packet; + packet.time_boot_ms = time_boot_ms; + packet.value = value; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAMED_VALUE_INT; + return mavlink_finalize_message(msg, system_id, component_id, 18, 44); +} + +/** + * @brief Pack a named_value_int message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param name Name of the debug variable + * @param value Signed integer value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_named_value_int_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,const char *name,int32_t value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_int32_t(buf, 4, value); + _mav_put_char_array(buf, 8, name, 10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_named_value_int_t packet; + packet.time_boot_ms = time_boot_ms; + packet.value = value; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAMED_VALUE_INT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18, 44); +} + +/** + * @brief Encode a named_value_int struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param named_value_int C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_named_value_int_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_named_value_int_t* named_value_int) +{ + return mavlink_msg_named_value_int_pack(system_id, component_id, msg, named_value_int->time_boot_ms, named_value_int->name, named_value_int->value); +} + +/** + * @brief Send a named_value_int message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param name Name of the debug variable + * @param value Signed integer value + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_named_value_int_send(mavlink_channel_t chan, uint32_t time_boot_ms, const char *name, int32_t value) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_int32_t(buf, 4, value); + _mav_put_char_array(buf, 8, name, 10); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAMED_VALUE_INT, buf, 18, 44); +#else + mavlink_named_value_int_t packet; + packet.time_boot_ms = time_boot_ms; + packet.value = value; + mav_array_memcpy(packet.name, name, sizeof(char)*10); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAMED_VALUE_INT, (const char *)&packet, 18, 44); +#endif +} + +#endif + +// MESSAGE NAMED_VALUE_INT UNPACKING + + +/** + * @brief Get field time_boot_ms from named_value_int message + * + * @return Timestamp (milliseconds since system boot) + */ +static inline uint32_t mavlink_msg_named_value_int_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field name from named_value_int message + * + * @return Name of the debug variable + */ +static inline uint16_t mavlink_msg_named_value_int_get_name(const mavlink_message_t* msg, char *name) +{ + return _MAV_RETURN_char_array(msg, name, 10, 8); +} + +/** + * @brief Get field value from named_value_int message + * + * @return Signed integer value + */ +static inline int32_t mavlink_msg_named_value_int_get_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 4); +} + +/** + * @brief Decode a named_value_int message into a struct + * + * @param msg The message to decode + * @param named_value_int C-struct to decode the message contents into + */ +static inline void mavlink_msg_named_value_int_decode(const mavlink_message_t* msg, mavlink_named_value_int_t* named_value_int) +{ +#if MAVLINK_NEED_BYTE_SWAP + named_value_int->time_boot_ms = mavlink_msg_named_value_int_get_time_boot_ms(msg); + named_value_int->value = mavlink_msg_named_value_int_get_value(msg); + mavlink_msg_named_value_int_get_name(msg, named_value_int->name); +#else + memcpy(named_value_int, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_nav_controller_output.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_nav_controller_output.h new file mode 100644 index 0000000000..028afdabc6 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_nav_controller_output.h @@ -0,0 +1,298 @@ +// MESSAGE NAV_CONTROLLER_OUTPUT PACKING + +#define MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT 62 + +typedef struct __mavlink_nav_controller_output_t +{ + float nav_roll; ///< Current desired roll in degrees + float nav_pitch; ///< Current desired pitch in degrees + float alt_error; ///< Current altitude error in meters + float aspd_error; ///< Current airspeed error in meters/second + float xtrack_error; ///< Current crosstrack error on x-y plane in meters + int16_t nav_bearing; ///< Current desired heading in degrees + int16_t target_bearing; ///< Bearing to current MISSION/target in degrees + uint16_t wp_dist; ///< Distance to active MISSION in meters +} mavlink_nav_controller_output_t; + +#define MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT_LEN 26 +#define MAVLINK_MSG_ID_62_LEN 26 + + + +#define MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT { \ + "NAV_CONTROLLER_OUTPUT", \ + 8, \ + { { "nav_roll", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_nav_controller_output_t, nav_roll) }, \ + { "nav_pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_nav_controller_output_t, nav_pitch) }, \ + { "alt_error", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_nav_controller_output_t, alt_error) }, \ + { "aspd_error", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_nav_controller_output_t, aspd_error) }, \ + { "xtrack_error", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_nav_controller_output_t, xtrack_error) }, \ + { "nav_bearing", NULL, MAVLINK_TYPE_INT16_T, 0, 20, offsetof(mavlink_nav_controller_output_t, nav_bearing) }, \ + { "target_bearing", NULL, MAVLINK_TYPE_INT16_T, 0, 22, offsetof(mavlink_nav_controller_output_t, target_bearing) }, \ + { "wp_dist", NULL, MAVLINK_TYPE_UINT16_T, 0, 24, offsetof(mavlink_nav_controller_output_t, wp_dist) }, \ + } \ +} + + +/** + * @brief Pack a nav_controller_output message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param nav_roll Current desired roll in degrees + * @param nav_pitch Current desired pitch in degrees + * @param nav_bearing Current desired heading in degrees + * @param target_bearing Bearing to current MISSION/target in degrees + * @param wp_dist Distance to active MISSION in meters + * @param alt_error Current altitude error in meters + * @param aspd_error Current airspeed error in meters/second + * @param xtrack_error Current crosstrack error on x-y plane in meters + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_nav_controller_output_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float nav_roll, float nav_pitch, int16_t nav_bearing, int16_t target_bearing, uint16_t wp_dist, float alt_error, float aspd_error, float xtrack_error) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_float(buf, 0, nav_roll); + _mav_put_float(buf, 4, nav_pitch); + _mav_put_float(buf, 8, alt_error); + _mav_put_float(buf, 12, aspd_error); + _mav_put_float(buf, 16, xtrack_error); + _mav_put_int16_t(buf, 20, nav_bearing); + _mav_put_int16_t(buf, 22, target_bearing); + _mav_put_uint16_t(buf, 24, wp_dist); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_nav_controller_output_t packet; + packet.nav_roll = nav_roll; + packet.nav_pitch = nav_pitch; + packet.alt_error = alt_error; + packet.aspd_error = aspd_error; + packet.xtrack_error = xtrack_error; + packet.nav_bearing = nav_bearing; + packet.target_bearing = target_bearing; + packet.wp_dist = wp_dist; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT; + return mavlink_finalize_message(msg, system_id, component_id, 26, 183); +} + +/** + * @brief Pack a nav_controller_output message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param nav_roll Current desired roll in degrees + * @param nav_pitch Current desired pitch in degrees + * @param nav_bearing Current desired heading in degrees + * @param target_bearing Bearing to current MISSION/target in degrees + * @param wp_dist Distance to active MISSION in meters + * @param alt_error Current altitude error in meters + * @param aspd_error Current airspeed error in meters/second + * @param xtrack_error Current crosstrack error on x-y plane in meters + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_nav_controller_output_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float nav_roll,float nav_pitch,int16_t nav_bearing,int16_t target_bearing,uint16_t wp_dist,float alt_error,float aspd_error,float xtrack_error) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_float(buf, 0, nav_roll); + _mav_put_float(buf, 4, nav_pitch); + _mav_put_float(buf, 8, alt_error); + _mav_put_float(buf, 12, aspd_error); + _mav_put_float(buf, 16, xtrack_error); + _mav_put_int16_t(buf, 20, nav_bearing); + _mav_put_int16_t(buf, 22, target_bearing); + _mav_put_uint16_t(buf, 24, wp_dist); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_nav_controller_output_t packet; + packet.nav_roll = nav_roll; + packet.nav_pitch = nav_pitch; + packet.alt_error = alt_error; + packet.aspd_error = aspd_error; + packet.xtrack_error = xtrack_error; + packet.nav_bearing = nav_bearing; + packet.target_bearing = target_bearing; + packet.wp_dist = wp_dist; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 26, 183); +} + +/** + * @brief Encode a nav_controller_output struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param nav_controller_output C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_nav_controller_output_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_nav_controller_output_t* nav_controller_output) +{ + return mavlink_msg_nav_controller_output_pack(system_id, component_id, msg, nav_controller_output->nav_roll, nav_controller_output->nav_pitch, nav_controller_output->nav_bearing, nav_controller_output->target_bearing, nav_controller_output->wp_dist, nav_controller_output->alt_error, nav_controller_output->aspd_error, nav_controller_output->xtrack_error); +} + +/** + * @brief Send a nav_controller_output message + * @param chan MAVLink channel to send the message + * + * @param nav_roll Current desired roll in degrees + * @param nav_pitch Current desired pitch in degrees + * @param nav_bearing Current desired heading in degrees + * @param target_bearing Bearing to current MISSION/target in degrees + * @param wp_dist Distance to active MISSION in meters + * @param alt_error Current altitude error in meters + * @param aspd_error Current airspeed error in meters/second + * @param xtrack_error Current crosstrack error on x-y plane in meters + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_nav_controller_output_send(mavlink_channel_t chan, float nav_roll, float nav_pitch, int16_t nav_bearing, int16_t target_bearing, uint16_t wp_dist, float alt_error, float aspd_error, float xtrack_error) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_float(buf, 0, nav_roll); + _mav_put_float(buf, 4, nav_pitch); + _mav_put_float(buf, 8, alt_error); + _mav_put_float(buf, 12, aspd_error); + _mav_put_float(buf, 16, xtrack_error); + _mav_put_int16_t(buf, 20, nav_bearing); + _mav_put_int16_t(buf, 22, target_bearing); + _mav_put_uint16_t(buf, 24, wp_dist); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT, buf, 26, 183); +#else + mavlink_nav_controller_output_t packet; + packet.nav_roll = nav_roll; + packet.nav_pitch = nav_pitch; + packet.alt_error = alt_error; + packet.aspd_error = aspd_error; + packet.xtrack_error = xtrack_error; + packet.nav_bearing = nav_bearing; + packet.target_bearing = target_bearing; + packet.wp_dist = wp_dist; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT, (const char *)&packet, 26, 183); +#endif +} + +#endif + +// MESSAGE NAV_CONTROLLER_OUTPUT UNPACKING + + +/** + * @brief Get field nav_roll from nav_controller_output message + * + * @return Current desired roll in degrees + */ +static inline float mavlink_msg_nav_controller_output_get_nav_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field nav_pitch from nav_controller_output message + * + * @return Current desired pitch in degrees + */ +static inline float mavlink_msg_nav_controller_output_get_nav_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field nav_bearing from nav_controller_output message + * + * @return Current desired heading in degrees + */ +static inline int16_t mavlink_msg_nav_controller_output_get_nav_bearing(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 20); +} + +/** + * @brief Get field target_bearing from nav_controller_output message + * + * @return Bearing to current MISSION/target in degrees + */ +static inline int16_t mavlink_msg_nav_controller_output_get_target_bearing(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 22); +} + +/** + * @brief Get field wp_dist from nav_controller_output message + * + * @return Distance to active MISSION in meters + */ +static inline uint16_t mavlink_msg_nav_controller_output_get_wp_dist(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 24); +} + +/** + * @brief Get field alt_error from nav_controller_output message + * + * @return Current altitude error in meters + */ +static inline float mavlink_msg_nav_controller_output_get_alt_error(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field aspd_error from nav_controller_output message + * + * @return Current airspeed error in meters/second + */ +static inline float mavlink_msg_nav_controller_output_get_aspd_error(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field xtrack_error from nav_controller_output message + * + * @return Current crosstrack error on x-y plane in meters + */ +static inline float mavlink_msg_nav_controller_output_get_xtrack_error(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Decode a nav_controller_output message into a struct + * + * @param msg The message to decode + * @param nav_controller_output C-struct to decode the message contents into + */ +static inline void mavlink_msg_nav_controller_output_decode(const mavlink_message_t* msg, mavlink_nav_controller_output_t* nav_controller_output) +{ +#if MAVLINK_NEED_BYTE_SWAP + nav_controller_output->nav_roll = mavlink_msg_nav_controller_output_get_nav_roll(msg); + nav_controller_output->nav_pitch = mavlink_msg_nav_controller_output_get_nav_pitch(msg); + nav_controller_output->alt_error = mavlink_msg_nav_controller_output_get_alt_error(msg); + nav_controller_output->aspd_error = mavlink_msg_nav_controller_output_get_aspd_error(msg); + nav_controller_output->xtrack_error = mavlink_msg_nav_controller_output_get_xtrack_error(msg); + nav_controller_output->nav_bearing = mavlink_msg_nav_controller_output_get_nav_bearing(msg); + nav_controller_output->target_bearing = mavlink_msg_nav_controller_output_get_target_bearing(msg); + nav_controller_output->wp_dist = mavlink_msg_nav_controller_output_get_wp_dist(msg); +#else + memcpy(nav_controller_output, _MAV_PAYLOAD(msg), 26); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_optical_flow.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_optical_flow.h new file mode 100644 index 0000000000..b277cab512 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_optical_flow.h @@ -0,0 +1,298 @@ +// MESSAGE OPTICAL_FLOW PACKING + +#define MAVLINK_MSG_ID_OPTICAL_FLOW 100 + +typedef struct __mavlink_optical_flow_t +{ + uint64_t time_usec; ///< Timestamp (UNIX) + float flow_comp_m_x; ///< Flow in meters in x-sensor direction, angular-speed compensated + float flow_comp_m_y; ///< Flow in meters in y-sensor direction, angular-speed compensated + float ground_distance; ///< Ground distance in meters. Positive value: distance known. Negative value: Unknown distance + int16_t flow_x; ///< Flow in pixels in x-sensor direction + int16_t flow_y; ///< Flow in pixels in y-sensor direction + uint8_t sensor_id; ///< Sensor ID + uint8_t quality; ///< Optical flow quality / confidence. 0: bad, 255: maximum quality +} mavlink_optical_flow_t; + +#define MAVLINK_MSG_ID_OPTICAL_FLOW_LEN 26 +#define MAVLINK_MSG_ID_100_LEN 26 + + + +#define MAVLINK_MESSAGE_INFO_OPTICAL_FLOW { \ + "OPTICAL_FLOW", \ + 8, \ + { { "time_usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_optical_flow_t, time_usec) }, \ + { "flow_comp_m_x", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_optical_flow_t, flow_comp_m_x) }, \ + { "flow_comp_m_y", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_optical_flow_t, flow_comp_m_y) }, \ + { "ground_distance", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_optical_flow_t, ground_distance) }, \ + { "flow_x", NULL, MAVLINK_TYPE_INT16_T, 0, 20, offsetof(mavlink_optical_flow_t, flow_x) }, \ + { "flow_y", NULL, MAVLINK_TYPE_INT16_T, 0, 22, offsetof(mavlink_optical_flow_t, flow_y) }, \ + { "sensor_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 24, offsetof(mavlink_optical_flow_t, sensor_id) }, \ + { "quality", NULL, MAVLINK_TYPE_UINT8_T, 0, 25, offsetof(mavlink_optical_flow_t, quality) }, \ + } \ +} + + +/** + * @brief Pack a optical_flow message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_usec Timestamp (UNIX) + * @param sensor_id Sensor ID + * @param flow_x Flow in pixels in x-sensor direction + * @param flow_y Flow in pixels in y-sensor direction + * @param flow_comp_m_x Flow in meters in x-sensor direction, angular-speed compensated + * @param flow_comp_m_y Flow in meters in y-sensor direction, angular-speed compensated + * @param quality Optical flow quality / confidence. 0: bad, 255: maximum quality + * @param ground_distance Ground distance in meters. Positive value: distance known. Negative value: Unknown distance + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_optical_flow_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time_usec, uint8_t sensor_id, int16_t flow_x, int16_t flow_y, float flow_comp_m_x, float flow_comp_m_y, uint8_t quality, float ground_distance) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_float(buf, 8, flow_comp_m_x); + _mav_put_float(buf, 12, flow_comp_m_y); + _mav_put_float(buf, 16, ground_distance); + _mav_put_int16_t(buf, 20, flow_x); + _mav_put_int16_t(buf, 22, flow_y); + _mav_put_uint8_t(buf, 24, sensor_id); + _mav_put_uint8_t(buf, 25, quality); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_optical_flow_t packet; + packet.time_usec = time_usec; + packet.flow_comp_m_x = flow_comp_m_x; + packet.flow_comp_m_y = flow_comp_m_y; + packet.ground_distance = ground_distance; + packet.flow_x = flow_x; + packet.flow_y = flow_y; + packet.sensor_id = sensor_id; + packet.quality = quality; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_OPTICAL_FLOW; + return mavlink_finalize_message(msg, system_id, component_id, 26, 175); +} + +/** + * @brief Pack a optical_flow message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_usec Timestamp (UNIX) + * @param sensor_id Sensor ID + * @param flow_x Flow in pixels in x-sensor direction + * @param flow_y Flow in pixels in y-sensor direction + * @param flow_comp_m_x Flow in meters in x-sensor direction, angular-speed compensated + * @param flow_comp_m_y Flow in meters in y-sensor direction, angular-speed compensated + * @param quality Optical flow quality / confidence. 0: bad, 255: maximum quality + * @param ground_distance Ground distance in meters. Positive value: distance known. Negative value: Unknown distance + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_optical_flow_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time_usec,uint8_t sensor_id,int16_t flow_x,int16_t flow_y,float flow_comp_m_x,float flow_comp_m_y,uint8_t quality,float ground_distance) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_float(buf, 8, flow_comp_m_x); + _mav_put_float(buf, 12, flow_comp_m_y); + _mav_put_float(buf, 16, ground_distance); + _mav_put_int16_t(buf, 20, flow_x); + _mav_put_int16_t(buf, 22, flow_y); + _mav_put_uint8_t(buf, 24, sensor_id); + _mav_put_uint8_t(buf, 25, quality); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_optical_flow_t packet; + packet.time_usec = time_usec; + packet.flow_comp_m_x = flow_comp_m_x; + packet.flow_comp_m_y = flow_comp_m_y; + packet.ground_distance = ground_distance; + packet.flow_x = flow_x; + packet.flow_y = flow_y; + packet.sensor_id = sensor_id; + packet.quality = quality; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_OPTICAL_FLOW; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 26, 175); +} + +/** + * @brief Encode a optical_flow struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param optical_flow C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_optical_flow_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_optical_flow_t* optical_flow) +{ + return mavlink_msg_optical_flow_pack(system_id, component_id, msg, optical_flow->time_usec, optical_flow->sensor_id, optical_flow->flow_x, optical_flow->flow_y, optical_flow->flow_comp_m_x, optical_flow->flow_comp_m_y, optical_flow->quality, optical_flow->ground_distance); +} + +/** + * @brief Send a optical_flow message + * @param chan MAVLink channel to send the message + * + * @param time_usec Timestamp (UNIX) + * @param sensor_id Sensor ID + * @param flow_x Flow in pixels in x-sensor direction + * @param flow_y Flow in pixels in y-sensor direction + * @param flow_comp_m_x Flow in meters in x-sensor direction, angular-speed compensated + * @param flow_comp_m_y Flow in meters in y-sensor direction, angular-speed compensated + * @param quality Optical flow quality / confidence. 0: bad, 255: maximum quality + * @param ground_distance Ground distance in meters. Positive value: distance known. Negative value: Unknown distance + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_optical_flow_send(mavlink_channel_t chan, uint64_t time_usec, uint8_t sensor_id, int16_t flow_x, int16_t flow_y, float flow_comp_m_x, float flow_comp_m_y, uint8_t quality, float ground_distance) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_float(buf, 8, flow_comp_m_x); + _mav_put_float(buf, 12, flow_comp_m_y); + _mav_put_float(buf, 16, ground_distance); + _mav_put_int16_t(buf, 20, flow_x); + _mav_put_int16_t(buf, 22, flow_y); + _mav_put_uint8_t(buf, 24, sensor_id); + _mav_put_uint8_t(buf, 25, quality); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OPTICAL_FLOW, buf, 26, 175); +#else + mavlink_optical_flow_t packet; + packet.time_usec = time_usec; + packet.flow_comp_m_x = flow_comp_m_x; + packet.flow_comp_m_y = flow_comp_m_y; + packet.ground_distance = ground_distance; + packet.flow_x = flow_x; + packet.flow_y = flow_y; + packet.sensor_id = sensor_id; + packet.quality = quality; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OPTICAL_FLOW, (const char *)&packet, 26, 175); +#endif +} + +#endif + +// MESSAGE OPTICAL_FLOW UNPACKING + + +/** + * @brief Get field time_usec from optical_flow message + * + * @return Timestamp (UNIX) + */ +static inline uint64_t mavlink_msg_optical_flow_get_time_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field sensor_id from optical_flow message + * + * @return Sensor ID + */ +static inline uint8_t mavlink_msg_optical_flow_get_sensor_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 24); +} + +/** + * @brief Get field flow_x from optical_flow message + * + * @return Flow in pixels in x-sensor direction + */ +static inline int16_t mavlink_msg_optical_flow_get_flow_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 20); +} + +/** + * @brief Get field flow_y from optical_flow message + * + * @return Flow in pixels in y-sensor direction + */ +static inline int16_t mavlink_msg_optical_flow_get_flow_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 22); +} + +/** + * @brief Get field flow_comp_m_x from optical_flow message + * + * @return Flow in meters in x-sensor direction, angular-speed compensated + */ +static inline float mavlink_msg_optical_flow_get_flow_comp_m_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field flow_comp_m_y from optical_flow message + * + * @return Flow in meters in y-sensor direction, angular-speed compensated + */ +static inline float mavlink_msg_optical_flow_get_flow_comp_m_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field quality from optical_flow message + * + * @return Optical flow quality / confidence. 0: bad, 255: maximum quality + */ +static inline uint8_t mavlink_msg_optical_flow_get_quality(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 25); +} + +/** + * @brief Get field ground_distance from optical_flow message + * + * @return Ground distance in meters. Positive value: distance known. Negative value: Unknown distance + */ +static inline float mavlink_msg_optical_flow_get_ground_distance(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Decode a optical_flow message into a struct + * + * @param msg The message to decode + * @param optical_flow C-struct to decode the message contents into + */ +static inline void mavlink_msg_optical_flow_decode(const mavlink_message_t* msg, mavlink_optical_flow_t* optical_flow) +{ +#if MAVLINK_NEED_BYTE_SWAP + optical_flow->time_usec = mavlink_msg_optical_flow_get_time_usec(msg); + optical_flow->flow_comp_m_x = mavlink_msg_optical_flow_get_flow_comp_m_x(msg); + optical_flow->flow_comp_m_y = mavlink_msg_optical_flow_get_flow_comp_m_y(msg); + optical_flow->ground_distance = mavlink_msg_optical_flow_get_ground_distance(msg); + optical_flow->flow_x = mavlink_msg_optical_flow_get_flow_x(msg); + optical_flow->flow_y = mavlink_msg_optical_flow_get_flow_y(msg); + optical_flow->sensor_id = mavlink_msg_optical_flow_get_sensor_id(msg); + optical_flow->quality = mavlink_msg_optical_flow_get_quality(msg); +#else + memcpy(optical_flow, _MAV_PAYLOAD(msg), 26); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_param_request_list.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_param_request_list.h new file mode 100644 index 0000000000..125df80c85 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_param_request_list.h @@ -0,0 +1,166 @@ +// MESSAGE PARAM_REQUEST_LIST PACKING + +#define MAVLINK_MSG_ID_PARAM_REQUEST_LIST 21 + +typedef struct __mavlink_param_request_list_t +{ + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_param_request_list_t; + +#define MAVLINK_MSG_ID_PARAM_REQUEST_LIST_LEN 2 +#define MAVLINK_MSG_ID_21_LEN 2 + + + +#define MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST { \ + "PARAM_REQUEST_LIST", \ + 2, \ + { { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_param_request_list_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_param_request_list_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a param_request_list message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_request_list_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_param_request_list_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_REQUEST_LIST; + return mavlink_finalize_message(msg, system_id, component_id, 2, 159); +} + +/** + * @brief Pack a param_request_list message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_request_list_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 2); +#else + mavlink_param_request_list_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 2); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_REQUEST_LIST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 2, 159); +} + +/** + * @brief Encode a param_request_list struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param param_request_list C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_param_request_list_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_param_request_list_t* param_request_list) +{ + return mavlink_msg_param_request_list_pack(system_id, component_id, msg, param_request_list->target_system, param_request_list->target_component); +} + +/** + * @brief Send a param_request_list message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_param_request_list_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[2]; + _mav_put_uint8_t(buf, 0, target_system); + _mav_put_uint8_t(buf, 1, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_REQUEST_LIST, buf, 2, 159); +#else + mavlink_param_request_list_t packet; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_REQUEST_LIST, (const char *)&packet, 2, 159); +#endif +} + +#endif + +// MESSAGE PARAM_REQUEST_LIST UNPACKING + + +/** + * @brief Get field target_system from param_request_list message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_param_request_list_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field target_component from param_request_list message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_param_request_list_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Decode a param_request_list message into a struct + * + * @param msg The message to decode + * @param param_request_list C-struct to decode the message contents into + */ +static inline void mavlink_msg_param_request_list_decode(const mavlink_message_t* msg, mavlink_param_request_list_t* param_request_list) +{ +#if MAVLINK_NEED_BYTE_SWAP + param_request_list->target_system = mavlink_msg_param_request_list_get_target_system(msg); + param_request_list->target_component = mavlink_msg_param_request_list_get_target_component(msg); +#else + memcpy(param_request_list, _MAV_PAYLOAD(msg), 2); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_param_request_read.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_param_request_read.h new file mode 100644 index 0000000000..61d00f62d1 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_param_request_read.h @@ -0,0 +1,204 @@ +// MESSAGE PARAM_REQUEST_READ PACKING + +#define MAVLINK_MSG_ID_PARAM_REQUEST_READ 20 + +typedef struct __mavlink_param_request_read_t +{ + int16_t param_index; ///< Parameter index. Send -1 to use the param ID field as identifier + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + char param_id[16]; ///< Onboard parameter id +} mavlink_param_request_read_t; + +#define MAVLINK_MSG_ID_PARAM_REQUEST_READ_LEN 20 +#define MAVLINK_MSG_ID_20_LEN 20 + +#define MAVLINK_MSG_PARAM_REQUEST_READ_FIELD_PARAM_ID_LEN 16 + +#define MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ { \ + "PARAM_REQUEST_READ", \ + 4, \ + { { "param_index", NULL, MAVLINK_TYPE_INT16_T, 0, 0, offsetof(mavlink_param_request_read_t, param_index) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_param_request_read_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_param_request_read_t, target_component) }, \ + { "param_id", NULL, MAVLINK_TYPE_CHAR, 16, 4, offsetof(mavlink_param_request_read_t, param_id) }, \ + } \ +} + + +/** + * @brief Pack a param_request_read message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param param_id Onboard parameter id + * @param param_index Parameter index. Send -1 to use the param ID field as identifier + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_request_read_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, const char *param_id, int16_t param_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_int16_t(buf, 0, param_index); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + _mav_put_char_array(buf, 4, param_id, 16); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_param_request_read_t packet; + packet.param_index = param_index; + packet.target_system = target_system; + packet.target_component = target_component; + mav_array_memcpy(packet.param_id, param_id, sizeof(char)*16); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_REQUEST_READ; + return mavlink_finalize_message(msg, system_id, component_id, 20, 214); +} + +/** + * @brief Pack a param_request_read message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param param_id Onboard parameter id + * @param param_index Parameter index. Send -1 to use the param ID field as identifier + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_request_read_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,const char *param_id,int16_t param_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_int16_t(buf, 0, param_index); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + _mav_put_char_array(buf, 4, param_id, 16); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_param_request_read_t packet; + packet.param_index = param_index; + packet.target_system = target_system; + packet.target_component = target_component; + mav_array_memcpy(packet.param_id, param_id, sizeof(char)*16); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_REQUEST_READ; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 20, 214); +} + +/** + * @brief Encode a param_request_read struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param param_request_read C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_param_request_read_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_param_request_read_t* param_request_read) +{ + return mavlink_msg_param_request_read_pack(system_id, component_id, msg, param_request_read->target_system, param_request_read->target_component, param_request_read->param_id, param_request_read->param_index); +} + +/** + * @brief Send a param_request_read message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param param_id Onboard parameter id + * @param param_index Parameter index. Send -1 to use the param ID field as identifier + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_param_request_read_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, const char *param_id, int16_t param_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_int16_t(buf, 0, param_index); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + _mav_put_char_array(buf, 4, param_id, 16); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_REQUEST_READ, buf, 20, 214); +#else + mavlink_param_request_read_t packet; + packet.param_index = param_index; + packet.target_system = target_system; + packet.target_component = target_component; + mav_array_memcpy(packet.param_id, param_id, sizeof(char)*16); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_REQUEST_READ, (const char *)&packet, 20, 214); +#endif +} + +#endif + +// MESSAGE PARAM_REQUEST_READ UNPACKING + + +/** + * @brief Get field target_system from param_request_read message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_param_request_read_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field target_component from param_request_read message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_param_request_read_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field param_id from param_request_read message + * + * @return Onboard parameter id + */ +static inline uint16_t mavlink_msg_param_request_read_get_param_id(const mavlink_message_t* msg, char *param_id) +{ + return _MAV_RETURN_char_array(msg, param_id, 16, 4); +} + +/** + * @brief Get field param_index from param_request_read message + * + * @return Parameter index. Send -1 to use the param ID field as identifier + */ +static inline int16_t mavlink_msg_param_request_read_get_param_index(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 0); +} + +/** + * @brief Decode a param_request_read message into a struct + * + * @param msg The message to decode + * @param param_request_read C-struct to decode the message contents into + */ +static inline void mavlink_msg_param_request_read_decode(const mavlink_message_t* msg, mavlink_param_request_read_t* param_request_read) +{ +#if MAVLINK_NEED_BYTE_SWAP + param_request_read->param_index = mavlink_msg_param_request_read_get_param_index(msg); + param_request_read->target_system = mavlink_msg_param_request_read_get_target_system(msg); + param_request_read->target_component = mavlink_msg_param_request_read_get_target_component(msg); + mavlink_msg_param_request_read_get_param_id(msg, param_request_read->param_id); +#else + memcpy(param_request_read, _MAV_PAYLOAD(msg), 20); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_param_set.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_param_set.h new file mode 100644 index 0000000000..a7e895f18d --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_param_set.h @@ -0,0 +1,226 @@ +// MESSAGE PARAM_SET PACKING + +#define MAVLINK_MSG_ID_PARAM_SET 23 + +typedef struct __mavlink_param_set_t +{ + float param_value; ///< Onboard parameter value + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + char param_id[16]; ///< Onboard parameter id + uint8_t param_type; ///< Onboard parameter type: see MAV_VAR enum +} mavlink_param_set_t; + +#define MAVLINK_MSG_ID_PARAM_SET_LEN 23 +#define MAVLINK_MSG_ID_23_LEN 23 + +#define MAVLINK_MSG_PARAM_SET_FIELD_PARAM_ID_LEN 16 + +#define MAVLINK_MESSAGE_INFO_PARAM_SET { \ + "PARAM_SET", \ + 5, \ + { { "param_value", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_param_set_t, param_value) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_param_set_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_param_set_t, target_component) }, \ + { "param_id", NULL, MAVLINK_TYPE_CHAR, 16, 6, offsetof(mavlink_param_set_t, param_id) }, \ + { "param_type", NULL, MAVLINK_TYPE_UINT8_T, 0, 22, offsetof(mavlink_param_set_t, param_type) }, \ + } \ +} + + +/** + * @brief Pack a param_set message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param param_id Onboard parameter id + * @param param_value Onboard parameter value + * @param param_type Onboard parameter type: see MAV_VAR enum + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_set_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, const char *param_id, float param_value, uint8_t param_type) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[23]; + _mav_put_float(buf, 0, param_value); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + _mav_put_uint8_t(buf, 22, param_type); + _mav_put_char_array(buf, 6, param_id, 16); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 23); +#else + mavlink_param_set_t packet; + packet.param_value = param_value; + packet.target_system = target_system; + packet.target_component = target_component; + packet.param_type = param_type; + mav_array_memcpy(packet.param_id, param_id, sizeof(char)*16); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 23); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_SET; + return mavlink_finalize_message(msg, system_id, component_id, 23, 168); +} + +/** + * @brief Pack a param_set message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param param_id Onboard parameter id + * @param param_value Onboard parameter value + * @param param_type Onboard parameter type: see MAV_VAR enum + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_set_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,const char *param_id,float param_value,uint8_t param_type) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[23]; + _mav_put_float(buf, 0, param_value); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + _mav_put_uint8_t(buf, 22, param_type); + _mav_put_char_array(buf, 6, param_id, 16); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 23); +#else + mavlink_param_set_t packet; + packet.param_value = param_value; + packet.target_system = target_system; + packet.target_component = target_component; + packet.param_type = param_type; + mav_array_memcpy(packet.param_id, param_id, sizeof(char)*16); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 23); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_SET; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 23, 168); +} + +/** + * @brief Encode a param_set struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param param_set C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_param_set_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_param_set_t* param_set) +{ + return mavlink_msg_param_set_pack(system_id, component_id, msg, param_set->target_system, param_set->target_component, param_set->param_id, param_set->param_value, param_set->param_type); +} + +/** + * @brief Send a param_set message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param param_id Onboard parameter id + * @param param_value Onboard parameter value + * @param param_type Onboard parameter type: see MAV_VAR enum + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_param_set_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, const char *param_id, float param_value, uint8_t param_type) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[23]; + _mav_put_float(buf, 0, param_value); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, target_component); + _mav_put_uint8_t(buf, 22, param_type); + _mav_put_char_array(buf, 6, param_id, 16); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_SET, buf, 23, 168); +#else + mavlink_param_set_t packet; + packet.param_value = param_value; + packet.target_system = target_system; + packet.target_component = target_component; + packet.param_type = param_type; + mav_array_memcpy(packet.param_id, param_id, sizeof(char)*16); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_SET, (const char *)&packet, 23, 168); +#endif +} + +#endif + +// MESSAGE PARAM_SET UNPACKING + + +/** + * @brief Get field target_system from param_set message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_param_set_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field target_component from param_set message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_param_set_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field param_id from param_set message + * + * @return Onboard parameter id + */ +static inline uint16_t mavlink_msg_param_set_get_param_id(const mavlink_message_t* msg, char *param_id) +{ + return _MAV_RETURN_char_array(msg, param_id, 16, 6); +} + +/** + * @brief Get field param_value from param_set message + * + * @return Onboard parameter value + */ +static inline float mavlink_msg_param_set_get_param_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field param_type from param_set message + * + * @return Onboard parameter type: see MAV_VAR enum + */ +static inline uint8_t mavlink_msg_param_set_get_param_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 22); +} + +/** + * @brief Decode a param_set message into a struct + * + * @param msg The message to decode + * @param param_set C-struct to decode the message contents into + */ +static inline void mavlink_msg_param_set_decode(const mavlink_message_t* msg, mavlink_param_set_t* param_set) +{ +#if MAVLINK_NEED_BYTE_SWAP + param_set->param_value = mavlink_msg_param_set_get_param_value(msg); + param_set->target_system = mavlink_msg_param_set_get_target_system(msg); + param_set->target_component = mavlink_msg_param_set_get_target_component(msg); + mavlink_msg_param_set_get_param_id(msg, param_set->param_id); + param_set->param_type = mavlink_msg_param_set_get_param_type(msg); +#else + memcpy(param_set, _MAV_PAYLOAD(msg), 23); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_param_value.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_param_value.h new file mode 100644 index 0000000000..4e16a56318 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_param_value.h @@ -0,0 +1,226 @@ +// MESSAGE PARAM_VALUE PACKING + +#define MAVLINK_MSG_ID_PARAM_VALUE 22 + +typedef struct __mavlink_param_value_t +{ + float param_value; ///< Onboard parameter value + uint16_t param_count; ///< Total number of onboard parameters + uint16_t param_index; ///< Index of this onboard parameter + char param_id[16]; ///< Onboard parameter id + uint8_t param_type; ///< Onboard parameter type: see MAV_VAR enum +} mavlink_param_value_t; + +#define MAVLINK_MSG_ID_PARAM_VALUE_LEN 25 +#define MAVLINK_MSG_ID_22_LEN 25 + +#define MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN 16 + +#define MAVLINK_MESSAGE_INFO_PARAM_VALUE { \ + "PARAM_VALUE", \ + 5, \ + { { "param_value", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_param_value_t, param_value) }, \ + { "param_count", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_param_value_t, param_count) }, \ + { "param_index", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_param_value_t, param_index) }, \ + { "param_id", NULL, MAVLINK_TYPE_CHAR, 16, 8, offsetof(mavlink_param_value_t, param_id) }, \ + { "param_type", NULL, MAVLINK_TYPE_UINT8_T, 0, 24, offsetof(mavlink_param_value_t, param_type) }, \ + } \ +} + + +/** + * @brief Pack a param_value message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param param_id Onboard parameter id + * @param param_value Onboard parameter value + * @param param_type Onboard parameter type: see MAV_VAR enum + * @param param_count Total number of onboard parameters + * @param param_index Index of this onboard parameter + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_value_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const char *param_id, float param_value, uint8_t param_type, uint16_t param_count, uint16_t param_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[25]; + _mav_put_float(buf, 0, param_value); + _mav_put_uint16_t(buf, 4, param_count); + _mav_put_uint16_t(buf, 6, param_index); + _mav_put_uint8_t(buf, 24, param_type); + _mav_put_char_array(buf, 8, param_id, 16); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 25); +#else + mavlink_param_value_t packet; + packet.param_value = param_value; + packet.param_count = param_count; + packet.param_index = param_index; + packet.param_type = param_type; + mav_array_memcpy(packet.param_id, param_id, sizeof(char)*16); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 25); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_VALUE; + return mavlink_finalize_message(msg, system_id, component_id, 25, 220); +} + +/** + * @brief Pack a param_value message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param param_id Onboard parameter id + * @param param_value Onboard parameter value + * @param param_type Onboard parameter type: see MAV_VAR enum + * @param param_count Total number of onboard parameters + * @param param_index Index of this onboard parameter + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_param_value_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const char *param_id,float param_value,uint8_t param_type,uint16_t param_count,uint16_t param_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[25]; + _mav_put_float(buf, 0, param_value); + _mav_put_uint16_t(buf, 4, param_count); + _mav_put_uint16_t(buf, 6, param_index); + _mav_put_uint8_t(buf, 24, param_type); + _mav_put_char_array(buf, 8, param_id, 16); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 25); +#else + mavlink_param_value_t packet; + packet.param_value = param_value; + packet.param_count = param_count; + packet.param_index = param_index; + packet.param_type = param_type; + mav_array_memcpy(packet.param_id, param_id, sizeof(char)*16); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 25); +#endif + + msg->msgid = MAVLINK_MSG_ID_PARAM_VALUE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 25, 220); +} + +/** + * @brief Encode a param_value struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param param_value C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_param_value_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_param_value_t* param_value) +{ + return mavlink_msg_param_value_pack(system_id, component_id, msg, param_value->param_id, param_value->param_value, param_value->param_type, param_value->param_count, param_value->param_index); +} + +/** + * @brief Send a param_value message + * @param chan MAVLink channel to send the message + * + * @param param_id Onboard parameter id + * @param param_value Onboard parameter value + * @param param_type Onboard parameter type: see MAV_VAR enum + * @param param_count Total number of onboard parameters + * @param param_index Index of this onboard parameter + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_param_value_send(mavlink_channel_t chan, const char *param_id, float param_value, uint8_t param_type, uint16_t param_count, uint16_t param_index) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[25]; + _mav_put_float(buf, 0, param_value); + _mav_put_uint16_t(buf, 4, param_count); + _mav_put_uint16_t(buf, 6, param_index); + _mav_put_uint8_t(buf, 24, param_type); + _mav_put_char_array(buf, 8, param_id, 16); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_VALUE, buf, 25, 220); +#else + mavlink_param_value_t packet; + packet.param_value = param_value; + packet.param_count = param_count; + packet.param_index = param_index; + packet.param_type = param_type; + mav_array_memcpy(packet.param_id, param_id, sizeof(char)*16); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PARAM_VALUE, (const char *)&packet, 25, 220); +#endif +} + +#endif + +// MESSAGE PARAM_VALUE UNPACKING + + +/** + * @brief Get field param_id from param_value message + * + * @return Onboard parameter id + */ +static inline uint16_t mavlink_msg_param_value_get_param_id(const mavlink_message_t* msg, char *param_id) +{ + return _MAV_RETURN_char_array(msg, param_id, 16, 8); +} + +/** + * @brief Get field param_value from param_value message + * + * @return Onboard parameter value + */ +static inline float mavlink_msg_param_value_get_param_value(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field param_type from param_value message + * + * @return Onboard parameter type: see MAV_VAR enum + */ +static inline uint8_t mavlink_msg_param_value_get_param_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 24); +} + +/** + * @brief Get field param_count from param_value message + * + * @return Total number of onboard parameters + */ +static inline uint16_t mavlink_msg_param_value_get_param_count(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field param_index from param_value message + * + * @return Index of this onboard parameter + */ +static inline uint16_t mavlink_msg_param_value_get_param_index(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Decode a param_value message into a struct + * + * @param msg The message to decode + * @param param_value C-struct to decode the message contents into + */ +static inline void mavlink_msg_param_value_decode(const mavlink_message_t* msg, mavlink_param_value_t* param_value) +{ +#if MAVLINK_NEED_BYTE_SWAP + param_value->param_value = mavlink_msg_param_value_get_param_value(msg); + param_value->param_count = mavlink_msg_param_value_get_param_count(msg); + param_value->param_index = mavlink_msg_param_value_get_param_index(msg); + mavlink_msg_param_value_get_param_id(msg, param_value->param_id); + param_value->param_type = mavlink_msg_param_value_get_param_type(msg); +#else + memcpy(param_value, _MAV_PAYLOAD(msg), 25); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_ping.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_ping.h new file mode 100644 index 0000000000..3ed1b9d7c4 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_ping.h @@ -0,0 +1,210 @@ +// MESSAGE PING PACKING + +#define MAVLINK_MSG_ID_PING 4 + +typedef struct __mavlink_ping_t +{ + uint64_t time_usec; ///< Unix timestamp in microseconds + uint32_t seq; ///< PING sequence + uint8_t target_system; ///< 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system + uint8_t target_component; ///< 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system +} mavlink_ping_t; + +#define MAVLINK_MSG_ID_PING_LEN 14 +#define MAVLINK_MSG_ID_4_LEN 14 + + + +#define MAVLINK_MESSAGE_INFO_PING { \ + "PING", \ + 4, \ + { { "time_usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_ping_t, time_usec) }, \ + { "seq", NULL, MAVLINK_TYPE_UINT32_T, 0, 8, offsetof(mavlink_ping_t, seq) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 12, offsetof(mavlink_ping_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 13, offsetof(mavlink_ping_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a ping message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_usec Unix timestamp in microseconds + * @param seq PING sequence + * @param target_system 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system + * @param target_component 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ping_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time_usec, uint32_t seq, uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_uint32_t(buf, 8, seq); + _mav_put_uint8_t(buf, 12, target_system); + _mav_put_uint8_t(buf, 13, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_ping_t packet; + packet.time_usec = time_usec; + packet.seq = seq; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_PING; + return mavlink_finalize_message(msg, system_id, component_id, 14, 237); +} + +/** + * @brief Pack a ping message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_usec Unix timestamp in microseconds + * @param seq PING sequence + * @param target_system 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system + * @param target_component 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ping_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time_usec,uint32_t seq,uint8_t target_system,uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_uint32_t(buf, 8, seq); + _mav_put_uint8_t(buf, 12, target_system); + _mav_put_uint8_t(buf, 13, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_ping_t packet; + packet.time_usec = time_usec; + packet.seq = seq; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_PING; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 14, 237); +} + +/** + * @brief Encode a ping struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param ping C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_ping_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_ping_t* ping) +{ + return mavlink_msg_ping_pack(system_id, component_id, msg, ping->time_usec, ping->seq, ping->target_system, ping->target_component); +} + +/** + * @brief Send a ping message + * @param chan MAVLink channel to send the message + * + * @param time_usec Unix timestamp in microseconds + * @param seq PING sequence + * @param target_system 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system + * @param target_component 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_ping_send(mavlink_channel_t chan, uint64_t time_usec, uint32_t seq, uint8_t target_system, uint8_t target_component) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_uint32_t(buf, 8, seq); + _mav_put_uint8_t(buf, 12, target_system); + _mav_put_uint8_t(buf, 13, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PING, buf, 14, 237); +#else + mavlink_ping_t packet; + packet.time_usec = time_usec; + packet.seq = seq; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PING, (const char *)&packet, 14, 237); +#endif +} + +#endif + +// MESSAGE PING UNPACKING + + +/** + * @brief Get field time_usec from ping message + * + * @return Unix timestamp in microseconds + */ +static inline uint64_t mavlink_msg_ping_get_time_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field seq from ping message + * + * @return PING sequence + */ +static inline uint32_t mavlink_msg_ping_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 8); +} + +/** + * @brief Get field target_system from ping message + * + * @return 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system + */ +static inline uint8_t mavlink_msg_ping_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 12); +} + +/** + * @brief Get field target_component from ping message + * + * @return 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system + */ +static inline uint8_t mavlink_msg_ping_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 13); +} + +/** + * @brief Decode a ping message into a struct + * + * @param msg The message to decode + * @param ping C-struct to decode the message contents into + */ +static inline void mavlink_msg_ping_decode(const mavlink_message_t* msg, mavlink_ping_t* ping) +{ +#if MAVLINK_NEED_BYTE_SWAP + ping->time_usec = mavlink_msg_ping_get_time_usec(msg); + ping->seq = mavlink_msg_ping_get_seq(msg); + ping->target_system = mavlink_msg_ping_get_target_system(msg); + ping->target_component = mavlink_msg_ping_get_target_component(msg); +#else + memcpy(ping, _MAV_PAYLOAD(msg), 14); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_raw_imu.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_raw_imu.h new file mode 100644 index 0000000000..1c1d483886 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_raw_imu.h @@ -0,0 +1,342 @@ +// MESSAGE RAW_IMU PACKING + +#define MAVLINK_MSG_ID_RAW_IMU 27 + +typedef struct __mavlink_raw_imu_t +{ + uint64_t time_usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + int16_t xacc; ///< X acceleration (raw) + int16_t yacc; ///< Y acceleration (raw) + int16_t zacc; ///< Z acceleration (raw) + int16_t xgyro; ///< Angular speed around X axis (raw) + int16_t ygyro; ///< Angular speed around Y axis (raw) + int16_t zgyro; ///< Angular speed around Z axis (raw) + int16_t xmag; ///< X Magnetic field (raw) + int16_t ymag; ///< Y Magnetic field (raw) + int16_t zmag; ///< Z Magnetic field (raw) +} mavlink_raw_imu_t; + +#define MAVLINK_MSG_ID_RAW_IMU_LEN 26 +#define MAVLINK_MSG_ID_27_LEN 26 + + + +#define MAVLINK_MESSAGE_INFO_RAW_IMU { \ + "RAW_IMU", \ + 10, \ + { { "time_usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_raw_imu_t, time_usec) }, \ + { "xacc", NULL, MAVLINK_TYPE_INT16_T, 0, 8, offsetof(mavlink_raw_imu_t, xacc) }, \ + { "yacc", NULL, MAVLINK_TYPE_INT16_T, 0, 10, offsetof(mavlink_raw_imu_t, yacc) }, \ + { "zacc", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_raw_imu_t, zacc) }, \ + { "xgyro", NULL, MAVLINK_TYPE_INT16_T, 0, 14, offsetof(mavlink_raw_imu_t, xgyro) }, \ + { "ygyro", NULL, MAVLINK_TYPE_INT16_T, 0, 16, offsetof(mavlink_raw_imu_t, ygyro) }, \ + { "zgyro", NULL, MAVLINK_TYPE_INT16_T, 0, 18, offsetof(mavlink_raw_imu_t, zgyro) }, \ + { "xmag", NULL, MAVLINK_TYPE_INT16_T, 0, 20, offsetof(mavlink_raw_imu_t, xmag) }, \ + { "ymag", NULL, MAVLINK_TYPE_INT16_T, 0, 22, offsetof(mavlink_raw_imu_t, ymag) }, \ + { "zmag", NULL, MAVLINK_TYPE_INT16_T, 0, 24, offsetof(mavlink_raw_imu_t, zmag) }, \ + } \ +} + + +/** + * @brief Pack a raw_imu message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param xacc X acceleration (raw) + * @param yacc Y acceleration (raw) + * @param zacc Z acceleration (raw) + * @param xgyro Angular speed around X axis (raw) + * @param ygyro Angular speed around Y axis (raw) + * @param zgyro Angular speed around Z axis (raw) + * @param xmag X Magnetic field (raw) + * @param ymag Y Magnetic field (raw) + * @param zmag Z Magnetic field (raw) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_raw_imu_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time_usec, int16_t xacc, int16_t yacc, int16_t zacc, int16_t xgyro, int16_t ygyro, int16_t zgyro, int16_t xmag, int16_t ymag, int16_t zmag) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_int16_t(buf, 8, xacc); + _mav_put_int16_t(buf, 10, yacc); + _mav_put_int16_t(buf, 12, zacc); + _mav_put_int16_t(buf, 14, xgyro); + _mav_put_int16_t(buf, 16, ygyro); + _mav_put_int16_t(buf, 18, zgyro); + _mav_put_int16_t(buf, 20, xmag); + _mav_put_int16_t(buf, 22, ymag); + _mav_put_int16_t(buf, 24, zmag); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_raw_imu_t packet; + packet.time_usec = time_usec; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + packet.xmag = xmag; + packet.ymag = ymag; + packet.zmag = zmag; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_RAW_IMU; + return mavlink_finalize_message(msg, system_id, component_id, 26, 144); +} + +/** + * @brief Pack a raw_imu message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param xacc X acceleration (raw) + * @param yacc Y acceleration (raw) + * @param zacc Z acceleration (raw) + * @param xgyro Angular speed around X axis (raw) + * @param ygyro Angular speed around Y axis (raw) + * @param zgyro Angular speed around Z axis (raw) + * @param xmag X Magnetic field (raw) + * @param ymag Y Magnetic field (raw) + * @param zmag Z Magnetic field (raw) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_raw_imu_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time_usec,int16_t xacc,int16_t yacc,int16_t zacc,int16_t xgyro,int16_t ygyro,int16_t zgyro,int16_t xmag,int16_t ymag,int16_t zmag) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_int16_t(buf, 8, xacc); + _mav_put_int16_t(buf, 10, yacc); + _mav_put_int16_t(buf, 12, zacc); + _mav_put_int16_t(buf, 14, xgyro); + _mav_put_int16_t(buf, 16, ygyro); + _mav_put_int16_t(buf, 18, zgyro); + _mav_put_int16_t(buf, 20, xmag); + _mav_put_int16_t(buf, 22, ymag); + _mav_put_int16_t(buf, 24, zmag); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_raw_imu_t packet; + packet.time_usec = time_usec; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + packet.xmag = xmag; + packet.ymag = ymag; + packet.zmag = zmag; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_RAW_IMU; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 26, 144); +} + +/** + * @brief Encode a raw_imu struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param raw_imu C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_raw_imu_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_raw_imu_t* raw_imu) +{ + return mavlink_msg_raw_imu_pack(system_id, component_id, msg, raw_imu->time_usec, raw_imu->xacc, raw_imu->yacc, raw_imu->zacc, raw_imu->xgyro, raw_imu->ygyro, raw_imu->zgyro, raw_imu->xmag, raw_imu->ymag, raw_imu->zmag); +} + +/** + * @brief Send a raw_imu message + * @param chan MAVLink channel to send the message + * + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param xacc X acceleration (raw) + * @param yacc Y acceleration (raw) + * @param zacc Z acceleration (raw) + * @param xgyro Angular speed around X axis (raw) + * @param ygyro Angular speed around Y axis (raw) + * @param zgyro Angular speed around Z axis (raw) + * @param xmag X Magnetic field (raw) + * @param ymag Y Magnetic field (raw) + * @param zmag Z Magnetic field (raw) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_raw_imu_send(mavlink_channel_t chan, uint64_t time_usec, int16_t xacc, int16_t yacc, int16_t zacc, int16_t xgyro, int16_t ygyro, int16_t zgyro, int16_t xmag, int16_t ymag, int16_t zmag) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_int16_t(buf, 8, xacc); + _mav_put_int16_t(buf, 10, yacc); + _mav_put_int16_t(buf, 12, zacc); + _mav_put_int16_t(buf, 14, xgyro); + _mav_put_int16_t(buf, 16, ygyro); + _mav_put_int16_t(buf, 18, zgyro); + _mav_put_int16_t(buf, 20, xmag); + _mav_put_int16_t(buf, 22, ymag); + _mav_put_int16_t(buf, 24, zmag); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RAW_IMU, buf, 26, 144); +#else + mavlink_raw_imu_t packet; + packet.time_usec = time_usec; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + packet.xmag = xmag; + packet.ymag = ymag; + packet.zmag = zmag; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RAW_IMU, (const char *)&packet, 26, 144); +#endif +} + +#endif + +// MESSAGE RAW_IMU UNPACKING + + +/** + * @brief Get field time_usec from raw_imu message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_raw_imu_get_time_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field xacc from raw_imu message + * + * @return X acceleration (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_xacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 8); +} + +/** + * @brief Get field yacc from raw_imu message + * + * @return Y acceleration (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_yacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 10); +} + +/** + * @brief Get field zacc from raw_imu message + * + * @return Z acceleration (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_zacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Get field xgyro from raw_imu message + * + * @return Angular speed around X axis (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_xgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 14); +} + +/** + * @brief Get field ygyro from raw_imu message + * + * @return Angular speed around Y axis (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_ygyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 16); +} + +/** + * @brief Get field zgyro from raw_imu message + * + * @return Angular speed around Z axis (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_zgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 18); +} + +/** + * @brief Get field xmag from raw_imu message + * + * @return X Magnetic field (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_xmag(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 20); +} + +/** + * @brief Get field ymag from raw_imu message + * + * @return Y Magnetic field (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_ymag(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 22); +} + +/** + * @brief Get field zmag from raw_imu message + * + * @return Z Magnetic field (raw) + */ +static inline int16_t mavlink_msg_raw_imu_get_zmag(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 24); +} + +/** + * @brief Decode a raw_imu message into a struct + * + * @param msg The message to decode + * @param raw_imu C-struct to decode the message contents into + */ +static inline void mavlink_msg_raw_imu_decode(const mavlink_message_t* msg, mavlink_raw_imu_t* raw_imu) +{ +#if MAVLINK_NEED_BYTE_SWAP + raw_imu->time_usec = mavlink_msg_raw_imu_get_time_usec(msg); + raw_imu->xacc = mavlink_msg_raw_imu_get_xacc(msg); + raw_imu->yacc = mavlink_msg_raw_imu_get_yacc(msg); + raw_imu->zacc = mavlink_msg_raw_imu_get_zacc(msg); + raw_imu->xgyro = mavlink_msg_raw_imu_get_xgyro(msg); + raw_imu->ygyro = mavlink_msg_raw_imu_get_ygyro(msg); + raw_imu->zgyro = mavlink_msg_raw_imu_get_zgyro(msg); + raw_imu->xmag = mavlink_msg_raw_imu_get_xmag(msg); + raw_imu->ymag = mavlink_msg_raw_imu_get_ymag(msg); + raw_imu->zmag = mavlink_msg_raw_imu_get_zmag(msg); +#else + memcpy(raw_imu, _MAV_PAYLOAD(msg), 26); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_raw_pressure.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_raw_pressure.h new file mode 100644 index 0000000000..f3e4e84046 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_raw_pressure.h @@ -0,0 +1,232 @@ +// MESSAGE RAW_PRESSURE PACKING + +#define MAVLINK_MSG_ID_RAW_PRESSURE 28 + +typedef struct __mavlink_raw_pressure_t +{ + uint64_t time_usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + int16_t press_abs; ///< Absolute pressure (raw) + int16_t press_diff1; ///< Differential pressure 1 (raw) + int16_t press_diff2; ///< Differential pressure 2 (raw) + int16_t temperature; ///< Raw Temperature measurement (raw) +} mavlink_raw_pressure_t; + +#define MAVLINK_MSG_ID_RAW_PRESSURE_LEN 16 +#define MAVLINK_MSG_ID_28_LEN 16 + + + +#define MAVLINK_MESSAGE_INFO_RAW_PRESSURE { \ + "RAW_PRESSURE", \ + 5, \ + { { "time_usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_raw_pressure_t, time_usec) }, \ + { "press_abs", NULL, MAVLINK_TYPE_INT16_T, 0, 8, offsetof(mavlink_raw_pressure_t, press_abs) }, \ + { "press_diff1", NULL, MAVLINK_TYPE_INT16_T, 0, 10, offsetof(mavlink_raw_pressure_t, press_diff1) }, \ + { "press_diff2", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_raw_pressure_t, press_diff2) }, \ + { "temperature", NULL, MAVLINK_TYPE_INT16_T, 0, 14, offsetof(mavlink_raw_pressure_t, temperature) }, \ + } \ +} + + +/** + * @brief Pack a raw_pressure message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param press_abs Absolute pressure (raw) + * @param press_diff1 Differential pressure 1 (raw) + * @param press_diff2 Differential pressure 2 (raw) + * @param temperature Raw Temperature measurement (raw) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_raw_pressure_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time_usec, int16_t press_abs, int16_t press_diff1, int16_t press_diff2, int16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_int16_t(buf, 8, press_abs); + _mav_put_int16_t(buf, 10, press_diff1); + _mav_put_int16_t(buf, 12, press_diff2); + _mav_put_int16_t(buf, 14, temperature); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_raw_pressure_t packet; + packet.time_usec = time_usec; + packet.press_abs = press_abs; + packet.press_diff1 = press_diff1; + packet.press_diff2 = press_diff2; + packet.temperature = temperature; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_RAW_PRESSURE; + return mavlink_finalize_message(msg, system_id, component_id, 16, 67); +} + +/** + * @brief Pack a raw_pressure message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param press_abs Absolute pressure (raw) + * @param press_diff1 Differential pressure 1 (raw) + * @param press_diff2 Differential pressure 2 (raw) + * @param temperature Raw Temperature measurement (raw) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_raw_pressure_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time_usec,int16_t press_abs,int16_t press_diff1,int16_t press_diff2,int16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_int16_t(buf, 8, press_abs); + _mav_put_int16_t(buf, 10, press_diff1); + _mav_put_int16_t(buf, 12, press_diff2); + _mav_put_int16_t(buf, 14, temperature); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_raw_pressure_t packet; + packet.time_usec = time_usec; + packet.press_abs = press_abs; + packet.press_diff1 = press_diff1; + packet.press_diff2 = press_diff2; + packet.temperature = temperature; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_RAW_PRESSURE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 16, 67); +} + +/** + * @brief Encode a raw_pressure struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param raw_pressure C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_raw_pressure_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_raw_pressure_t* raw_pressure) +{ + return mavlink_msg_raw_pressure_pack(system_id, component_id, msg, raw_pressure->time_usec, raw_pressure->press_abs, raw_pressure->press_diff1, raw_pressure->press_diff2, raw_pressure->temperature); +} + +/** + * @brief Send a raw_pressure message + * @param chan MAVLink channel to send the message + * + * @param time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param press_abs Absolute pressure (raw) + * @param press_diff1 Differential pressure 1 (raw) + * @param press_diff2 Differential pressure 2 (raw) + * @param temperature Raw Temperature measurement (raw) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_raw_pressure_send(mavlink_channel_t chan, uint64_t time_usec, int16_t press_abs, int16_t press_diff1, int16_t press_diff2, int16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_uint64_t(buf, 0, time_usec); + _mav_put_int16_t(buf, 8, press_abs); + _mav_put_int16_t(buf, 10, press_diff1); + _mav_put_int16_t(buf, 12, press_diff2); + _mav_put_int16_t(buf, 14, temperature); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RAW_PRESSURE, buf, 16, 67); +#else + mavlink_raw_pressure_t packet; + packet.time_usec = time_usec; + packet.press_abs = press_abs; + packet.press_diff1 = press_diff1; + packet.press_diff2 = press_diff2; + packet.temperature = temperature; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RAW_PRESSURE, (const char *)&packet, 16, 67); +#endif +} + +#endif + +// MESSAGE RAW_PRESSURE UNPACKING + + +/** + * @brief Get field time_usec from raw_pressure message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint64_t mavlink_msg_raw_pressure_get_time_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field press_abs from raw_pressure message + * + * @return Absolute pressure (raw) + */ +static inline int16_t mavlink_msg_raw_pressure_get_press_abs(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 8); +} + +/** + * @brief Get field press_diff1 from raw_pressure message + * + * @return Differential pressure 1 (raw) + */ +static inline int16_t mavlink_msg_raw_pressure_get_press_diff1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 10); +} + +/** + * @brief Get field press_diff2 from raw_pressure message + * + * @return Differential pressure 2 (raw) + */ +static inline int16_t mavlink_msg_raw_pressure_get_press_diff2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Get field temperature from raw_pressure message + * + * @return Raw Temperature measurement (raw) + */ +static inline int16_t mavlink_msg_raw_pressure_get_temperature(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 14); +} + +/** + * @brief Decode a raw_pressure message into a struct + * + * @param msg The message to decode + * @param raw_pressure C-struct to decode the message contents into + */ +static inline void mavlink_msg_raw_pressure_decode(const mavlink_message_t* msg, mavlink_raw_pressure_t* raw_pressure) +{ +#if MAVLINK_NEED_BYTE_SWAP + raw_pressure->time_usec = mavlink_msg_raw_pressure_get_time_usec(msg); + raw_pressure->press_abs = mavlink_msg_raw_pressure_get_press_abs(msg); + raw_pressure->press_diff1 = mavlink_msg_raw_pressure_get_press_diff1(msg); + raw_pressure->press_diff2 = mavlink_msg_raw_pressure_get_press_diff2(msg); + raw_pressure->temperature = mavlink_msg_raw_pressure_get_temperature(msg); +#else + memcpy(raw_pressure, _MAV_PAYLOAD(msg), 16); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_rc_channels_override.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_rc_channels_override.h new file mode 100644 index 0000000000..d719c7fca2 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_rc_channels_override.h @@ -0,0 +1,342 @@ +// MESSAGE RC_CHANNELS_OVERRIDE PACKING + +#define MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE 70 + +typedef struct __mavlink_rc_channels_override_t +{ + uint16_t chan1_raw; ///< RC channel 1 value, in microseconds + uint16_t chan2_raw; ///< RC channel 2 value, in microseconds + uint16_t chan3_raw; ///< RC channel 3 value, in microseconds + uint16_t chan4_raw; ///< RC channel 4 value, in microseconds + uint16_t chan5_raw; ///< RC channel 5 value, in microseconds + uint16_t chan6_raw; ///< RC channel 6 value, in microseconds + uint16_t chan7_raw; ///< RC channel 7 value, in microseconds + uint16_t chan8_raw; ///< RC channel 8 value, in microseconds + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_rc_channels_override_t; + +#define MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE_LEN 18 +#define MAVLINK_MSG_ID_70_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE { \ + "RC_CHANNELS_OVERRIDE", \ + 10, \ + { { "chan1_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_rc_channels_override_t, chan1_raw) }, \ + { "chan2_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_rc_channels_override_t, chan2_raw) }, \ + { "chan3_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_rc_channels_override_t, chan3_raw) }, \ + { "chan4_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_rc_channels_override_t, chan4_raw) }, \ + { "chan5_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 8, offsetof(mavlink_rc_channels_override_t, chan5_raw) }, \ + { "chan6_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 10, offsetof(mavlink_rc_channels_override_t, chan6_raw) }, \ + { "chan7_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 12, offsetof(mavlink_rc_channels_override_t, chan7_raw) }, \ + { "chan8_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 14, offsetof(mavlink_rc_channels_override_t, chan8_raw) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 16, offsetof(mavlink_rc_channels_override_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 17, offsetof(mavlink_rc_channels_override_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a rc_channels_override message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_rc_channels_override_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint16_t chan1_raw, uint16_t chan2_raw, uint16_t chan3_raw, uint16_t chan4_raw, uint16_t chan5_raw, uint16_t chan6_raw, uint16_t chan7_raw, uint16_t chan8_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint16_t(buf, 0, chan1_raw); + _mav_put_uint16_t(buf, 2, chan2_raw); + _mav_put_uint16_t(buf, 4, chan3_raw); + _mav_put_uint16_t(buf, 6, chan4_raw); + _mav_put_uint16_t(buf, 8, chan5_raw); + _mav_put_uint16_t(buf, 10, chan6_raw); + _mav_put_uint16_t(buf, 12, chan7_raw); + _mav_put_uint16_t(buf, 14, chan8_raw); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_rc_channels_override_t packet; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE; + return mavlink_finalize_message(msg, system_id, component_id, 18, 124); +} + +/** + * @brief Pack a rc_channels_override message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_rc_channels_override_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint16_t chan1_raw,uint16_t chan2_raw,uint16_t chan3_raw,uint16_t chan4_raw,uint16_t chan5_raw,uint16_t chan6_raw,uint16_t chan7_raw,uint16_t chan8_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint16_t(buf, 0, chan1_raw); + _mav_put_uint16_t(buf, 2, chan2_raw); + _mav_put_uint16_t(buf, 4, chan3_raw); + _mav_put_uint16_t(buf, 6, chan4_raw); + _mav_put_uint16_t(buf, 8, chan5_raw); + _mav_put_uint16_t(buf, 10, chan6_raw); + _mav_put_uint16_t(buf, 12, chan7_raw); + _mav_put_uint16_t(buf, 14, chan8_raw); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_rc_channels_override_t packet; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18, 124); +} + +/** + * @brief Encode a rc_channels_override struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param rc_channels_override C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_rc_channels_override_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_rc_channels_override_t* rc_channels_override) +{ + return mavlink_msg_rc_channels_override_pack(system_id, component_id, msg, rc_channels_override->target_system, rc_channels_override->target_component, rc_channels_override->chan1_raw, rc_channels_override->chan2_raw, rc_channels_override->chan3_raw, rc_channels_override->chan4_raw, rc_channels_override->chan5_raw, rc_channels_override->chan6_raw, rc_channels_override->chan7_raw, rc_channels_override->chan8_raw); +} + +/** + * @brief Send a rc_channels_override message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_rc_channels_override_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint16_t chan1_raw, uint16_t chan2_raw, uint16_t chan3_raw, uint16_t chan4_raw, uint16_t chan5_raw, uint16_t chan6_raw, uint16_t chan7_raw, uint16_t chan8_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_uint16_t(buf, 0, chan1_raw); + _mav_put_uint16_t(buf, 2, chan2_raw); + _mav_put_uint16_t(buf, 4, chan3_raw); + _mav_put_uint16_t(buf, 6, chan4_raw); + _mav_put_uint16_t(buf, 8, chan5_raw); + _mav_put_uint16_t(buf, 10, chan6_raw); + _mav_put_uint16_t(buf, 12, chan7_raw); + _mav_put_uint16_t(buf, 14, chan8_raw); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE, buf, 18, 124); +#else + mavlink_rc_channels_override_t packet; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE, (const char *)&packet, 18, 124); +#endif +} + +#endif + +// MESSAGE RC_CHANNELS_OVERRIDE UNPACKING + + +/** + * @brief Get field target_system from rc_channels_override message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_rc_channels_override_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 16); +} + +/** + * @brief Get field target_component from rc_channels_override message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_rc_channels_override_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 17); +} + +/** + * @brief Get field chan1_raw from rc_channels_override message + * + * @return RC channel 1 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan1_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field chan2_raw from rc_channels_override message + * + * @return RC channel 2 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan2_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Get field chan3_raw from rc_channels_override message + * + * @return RC channel 3 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan3_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field chan4_raw from rc_channels_override message + * + * @return RC channel 4 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan4_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field chan5_raw from rc_channels_override message + * + * @return RC channel 5 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan5_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Get field chan6_raw from rc_channels_override message + * + * @return RC channel 6 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan6_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 10); +} + +/** + * @brief Get field chan7_raw from rc_channels_override message + * + * @return RC channel 7 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan7_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 12); +} + +/** + * @brief Get field chan8_raw from rc_channels_override message + * + * @return RC channel 8 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_override_get_chan8_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 14); +} + +/** + * @brief Decode a rc_channels_override message into a struct + * + * @param msg The message to decode + * @param rc_channels_override C-struct to decode the message contents into + */ +static inline void mavlink_msg_rc_channels_override_decode(const mavlink_message_t* msg, mavlink_rc_channels_override_t* rc_channels_override) +{ +#if MAVLINK_NEED_BYTE_SWAP + rc_channels_override->chan1_raw = mavlink_msg_rc_channels_override_get_chan1_raw(msg); + rc_channels_override->chan2_raw = mavlink_msg_rc_channels_override_get_chan2_raw(msg); + rc_channels_override->chan3_raw = mavlink_msg_rc_channels_override_get_chan3_raw(msg); + rc_channels_override->chan4_raw = mavlink_msg_rc_channels_override_get_chan4_raw(msg); + rc_channels_override->chan5_raw = mavlink_msg_rc_channels_override_get_chan5_raw(msg); + rc_channels_override->chan6_raw = mavlink_msg_rc_channels_override_get_chan6_raw(msg); + rc_channels_override->chan7_raw = mavlink_msg_rc_channels_override_get_chan7_raw(msg); + rc_channels_override->chan8_raw = mavlink_msg_rc_channels_override_get_chan8_raw(msg); + rc_channels_override->target_system = mavlink_msg_rc_channels_override_get_target_system(msg); + rc_channels_override->target_component = mavlink_msg_rc_channels_override_get_target_component(msg); +#else + memcpy(rc_channels_override, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_rc_channels_raw.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_rc_channels_raw.h new file mode 100644 index 0000000000..a5b28021d5 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_rc_channels_raw.h @@ -0,0 +1,364 @@ +// MESSAGE RC_CHANNELS_RAW PACKING + +#define MAVLINK_MSG_ID_RC_CHANNELS_RAW 35 + +typedef struct __mavlink_rc_channels_raw_t +{ + uint32_t time_boot_ms; ///< Timestamp (milliseconds since system boot) + uint16_t chan1_raw; ///< RC channel 1 value, in microseconds + uint16_t chan2_raw; ///< RC channel 2 value, in microseconds + uint16_t chan3_raw; ///< RC channel 3 value, in microseconds + uint16_t chan4_raw; ///< RC channel 4 value, in microseconds + uint16_t chan5_raw; ///< RC channel 5 value, in microseconds + uint16_t chan6_raw; ///< RC channel 6 value, in microseconds + uint16_t chan7_raw; ///< RC channel 7 value, in microseconds + uint16_t chan8_raw; ///< RC channel 8 value, in microseconds + uint8_t port; ///< Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + uint8_t rssi; ///< Receive signal strength indicator, 0: 0%, 255: 100% +} mavlink_rc_channels_raw_t; + +#define MAVLINK_MSG_ID_RC_CHANNELS_RAW_LEN 22 +#define MAVLINK_MSG_ID_35_LEN 22 + + + +#define MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW { \ + "RC_CHANNELS_RAW", \ + 11, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_rc_channels_raw_t, time_boot_ms) }, \ + { "chan1_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_rc_channels_raw_t, chan1_raw) }, \ + { "chan2_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_rc_channels_raw_t, chan2_raw) }, \ + { "chan3_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 8, offsetof(mavlink_rc_channels_raw_t, chan3_raw) }, \ + { "chan4_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 10, offsetof(mavlink_rc_channels_raw_t, chan4_raw) }, \ + { "chan5_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 12, offsetof(mavlink_rc_channels_raw_t, chan5_raw) }, \ + { "chan6_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 14, offsetof(mavlink_rc_channels_raw_t, chan6_raw) }, \ + { "chan7_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 16, offsetof(mavlink_rc_channels_raw_t, chan7_raw) }, \ + { "chan8_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 18, offsetof(mavlink_rc_channels_raw_t, chan8_raw) }, \ + { "port", NULL, MAVLINK_TYPE_UINT8_T, 0, 20, offsetof(mavlink_rc_channels_raw_t, port) }, \ + { "rssi", NULL, MAVLINK_TYPE_UINT8_T, 0, 21, offsetof(mavlink_rc_channels_raw_t, rssi) }, \ + } \ +} + + +/** + * @brief Pack a rc_channels_raw message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param port Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_rc_channels_raw_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, uint8_t port, uint16_t chan1_raw, uint16_t chan2_raw, uint16_t chan3_raw, uint16_t chan4_raw, uint16_t chan5_raw, uint16_t chan6_raw, uint16_t chan7_raw, uint16_t chan8_raw, uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[22]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_uint16_t(buf, 4, chan1_raw); + _mav_put_uint16_t(buf, 6, chan2_raw); + _mav_put_uint16_t(buf, 8, chan3_raw); + _mav_put_uint16_t(buf, 10, chan4_raw); + _mav_put_uint16_t(buf, 12, chan5_raw); + _mav_put_uint16_t(buf, 14, chan6_raw); + _mav_put_uint16_t(buf, 16, chan7_raw); + _mav_put_uint16_t(buf, 18, chan8_raw); + _mav_put_uint8_t(buf, 20, port); + _mav_put_uint8_t(buf, 21, rssi); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 22); +#else + mavlink_rc_channels_raw_t packet; + packet.time_boot_ms = time_boot_ms; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + packet.port = port; + packet.rssi = rssi; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 22); +#endif + + msg->msgid = MAVLINK_MSG_ID_RC_CHANNELS_RAW; + return mavlink_finalize_message(msg, system_id, component_id, 22, 244); +} + +/** + * @brief Pack a rc_channels_raw message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param port Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_rc_channels_raw_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,uint8_t port,uint16_t chan1_raw,uint16_t chan2_raw,uint16_t chan3_raw,uint16_t chan4_raw,uint16_t chan5_raw,uint16_t chan6_raw,uint16_t chan7_raw,uint16_t chan8_raw,uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[22]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_uint16_t(buf, 4, chan1_raw); + _mav_put_uint16_t(buf, 6, chan2_raw); + _mav_put_uint16_t(buf, 8, chan3_raw); + _mav_put_uint16_t(buf, 10, chan4_raw); + _mav_put_uint16_t(buf, 12, chan5_raw); + _mav_put_uint16_t(buf, 14, chan6_raw); + _mav_put_uint16_t(buf, 16, chan7_raw); + _mav_put_uint16_t(buf, 18, chan8_raw); + _mav_put_uint8_t(buf, 20, port); + _mav_put_uint8_t(buf, 21, rssi); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 22); +#else + mavlink_rc_channels_raw_t packet; + packet.time_boot_ms = time_boot_ms; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + packet.port = port; + packet.rssi = rssi; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 22); +#endif + + msg->msgid = MAVLINK_MSG_ID_RC_CHANNELS_RAW; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 22, 244); +} + +/** + * @brief Encode a rc_channels_raw struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param rc_channels_raw C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_rc_channels_raw_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_rc_channels_raw_t* rc_channels_raw) +{ + return mavlink_msg_rc_channels_raw_pack(system_id, component_id, msg, rc_channels_raw->time_boot_ms, rc_channels_raw->port, rc_channels_raw->chan1_raw, rc_channels_raw->chan2_raw, rc_channels_raw->chan3_raw, rc_channels_raw->chan4_raw, rc_channels_raw->chan5_raw, rc_channels_raw->chan6_raw, rc_channels_raw->chan7_raw, rc_channels_raw->chan8_raw, rc_channels_raw->rssi); +} + +/** + * @brief Send a rc_channels_raw message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param port Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + * @param chan1_raw RC channel 1 value, in microseconds + * @param chan2_raw RC channel 2 value, in microseconds + * @param chan3_raw RC channel 3 value, in microseconds + * @param chan4_raw RC channel 4 value, in microseconds + * @param chan5_raw RC channel 5 value, in microseconds + * @param chan6_raw RC channel 6 value, in microseconds + * @param chan7_raw RC channel 7 value, in microseconds + * @param chan8_raw RC channel 8 value, in microseconds + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_rc_channels_raw_send(mavlink_channel_t chan, uint32_t time_boot_ms, uint8_t port, uint16_t chan1_raw, uint16_t chan2_raw, uint16_t chan3_raw, uint16_t chan4_raw, uint16_t chan5_raw, uint16_t chan6_raw, uint16_t chan7_raw, uint16_t chan8_raw, uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[22]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_uint16_t(buf, 4, chan1_raw); + _mav_put_uint16_t(buf, 6, chan2_raw); + _mav_put_uint16_t(buf, 8, chan3_raw); + _mav_put_uint16_t(buf, 10, chan4_raw); + _mav_put_uint16_t(buf, 12, chan5_raw); + _mav_put_uint16_t(buf, 14, chan6_raw); + _mav_put_uint16_t(buf, 16, chan7_raw); + _mav_put_uint16_t(buf, 18, chan8_raw); + _mav_put_uint8_t(buf, 20, port); + _mav_put_uint8_t(buf, 21, rssi); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RC_CHANNELS_RAW, buf, 22, 244); +#else + mavlink_rc_channels_raw_t packet; + packet.time_boot_ms = time_boot_ms; + packet.chan1_raw = chan1_raw; + packet.chan2_raw = chan2_raw; + packet.chan3_raw = chan3_raw; + packet.chan4_raw = chan4_raw; + packet.chan5_raw = chan5_raw; + packet.chan6_raw = chan6_raw; + packet.chan7_raw = chan7_raw; + packet.chan8_raw = chan8_raw; + packet.port = port; + packet.rssi = rssi; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RC_CHANNELS_RAW, (const char *)&packet, 22, 244); +#endif +} + +#endif + +// MESSAGE RC_CHANNELS_RAW UNPACKING + + +/** + * @brief Get field time_boot_ms from rc_channels_raw message + * + * @return Timestamp (milliseconds since system boot) + */ +static inline uint32_t mavlink_msg_rc_channels_raw_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field port from rc_channels_raw message + * + * @return Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + */ +static inline uint8_t mavlink_msg_rc_channels_raw_get_port(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 20); +} + +/** + * @brief Get field chan1_raw from rc_channels_raw message + * + * @return RC channel 1 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan1_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field chan2_raw from rc_channels_raw message + * + * @return RC channel 2 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan2_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field chan3_raw from rc_channels_raw message + * + * @return RC channel 3 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan3_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Get field chan4_raw from rc_channels_raw message + * + * @return RC channel 4 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan4_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 10); +} + +/** + * @brief Get field chan5_raw from rc_channels_raw message + * + * @return RC channel 5 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan5_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 12); +} + +/** + * @brief Get field chan6_raw from rc_channels_raw message + * + * @return RC channel 6 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan6_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 14); +} + +/** + * @brief Get field chan7_raw from rc_channels_raw message + * + * @return RC channel 7 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan7_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 16); +} + +/** + * @brief Get field chan8_raw from rc_channels_raw message + * + * @return RC channel 8 value, in microseconds + */ +static inline uint16_t mavlink_msg_rc_channels_raw_get_chan8_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 18); +} + +/** + * @brief Get field rssi from rc_channels_raw message + * + * @return Receive signal strength indicator, 0: 0%, 255: 100% + */ +static inline uint8_t mavlink_msg_rc_channels_raw_get_rssi(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 21); +} + +/** + * @brief Decode a rc_channels_raw message into a struct + * + * @param msg The message to decode + * @param rc_channels_raw C-struct to decode the message contents into + */ +static inline void mavlink_msg_rc_channels_raw_decode(const mavlink_message_t* msg, mavlink_rc_channels_raw_t* rc_channels_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP + rc_channels_raw->time_boot_ms = mavlink_msg_rc_channels_raw_get_time_boot_ms(msg); + rc_channels_raw->chan1_raw = mavlink_msg_rc_channels_raw_get_chan1_raw(msg); + rc_channels_raw->chan2_raw = mavlink_msg_rc_channels_raw_get_chan2_raw(msg); + rc_channels_raw->chan3_raw = mavlink_msg_rc_channels_raw_get_chan3_raw(msg); + rc_channels_raw->chan4_raw = mavlink_msg_rc_channels_raw_get_chan4_raw(msg); + rc_channels_raw->chan5_raw = mavlink_msg_rc_channels_raw_get_chan5_raw(msg); + rc_channels_raw->chan6_raw = mavlink_msg_rc_channels_raw_get_chan6_raw(msg); + rc_channels_raw->chan7_raw = mavlink_msg_rc_channels_raw_get_chan7_raw(msg); + rc_channels_raw->chan8_raw = mavlink_msg_rc_channels_raw_get_chan8_raw(msg); + rc_channels_raw->port = mavlink_msg_rc_channels_raw_get_port(msg); + rc_channels_raw->rssi = mavlink_msg_rc_channels_raw_get_rssi(msg); +#else + memcpy(rc_channels_raw, _MAV_PAYLOAD(msg), 22); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_rc_channels_scaled.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_rc_channels_scaled.h new file mode 100644 index 0000000000..23c14c03d7 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_rc_channels_scaled.h @@ -0,0 +1,364 @@ +// MESSAGE RC_CHANNELS_SCALED PACKING + +#define MAVLINK_MSG_ID_RC_CHANNELS_SCALED 34 + +typedef struct __mavlink_rc_channels_scaled_t +{ + uint32_t time_boot_ms; ///< Timestamp (milliseconds since system boot) + int16_t chan1_scaled; ///< RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan2_scaled; ///< RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan3_scaled; ///< RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan4_scaled; ///< RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan5_scaled; ///< RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan6_scaled; ///< RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan7_scaled; ///< RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + int16_t chan8_scaled; ///< RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + uint8_t port; ///< Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + uint8_t rssi; ///< Receive signal strength indicator, 0: 0%, 255: 100% +} mavlink_rc_channels_scaled_t; + +#define MAVLINK_MSG_ID_RC_CHANNELS_SCALED_LEN 22 +#define MAVLINK_MSG_ID_34_LEN 22 + + + +#define MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED { \ + "RC_CHANNELS_SCALED", \ + 11, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_rc_channels_scaled_t, time_boot_ms) }, \ + { "chan1_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 4, offsetof(mavlink_rc_channels_scaled_t, chan1_scaled) }, \ + { "chan2_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 6, offsetof(mavlink_rc_channels_scaled_t, chan2_scaled) }, \ + { "chan3_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 8, offsetof(mavlink_rc_channels_scaled_t, chan3_scaled) }, \ + { "chan4_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 10, offsetof(mavlink_rc_channels_scaled_t, chan4_scaled) }, \ + { "chan5_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_rc_channels_scaled_t, chan5_scaled) }, \ + { "chan6_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 14, offsetof(mavlink_rc_channels_scaled_t, chan6_scaled) }, \ + { "chan7_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 16, offsetof(mavlink_rc_channels_scaled_t, chan7_scaled) }, \ + { "chan8_scaled", NULL, MAVLINK_TYPE_INT16_T, 0, 18, offsetof(mavlink_rc_channels_scaled_t, chan8_scaled) }, \ + { "port", NULL, MAVLINK_TYPE_UINT8_T, 0, 20, offsetof(mavlink_rc_channels_scaled_t, port) }, \ + { "rssi", NULL, MAVLINK_TYPE_UINT8_T, 0, 21, offsetof(mavlink_rc_channels_scaled_t, rssi) }, \ + } \ +} + + +/** + * @brief Pack a rc_channels_scaled message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param port Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + * @param chan1_scaled RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan2_scaled RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan3_scaled RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan4_scaled RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan5_scaled RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan6_scaled RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan7_scaled RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan8_scaled RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_rc_channels_scaled_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, uint8_t port, int16_t chan1_scaled, int16_t chan2_scaled, int16_t chan3_scaled, int16_t chan4_scaled, int16_t chan5_scaled, int16_t chan6_scaled, int16_t chan7_scaled, int16_t chan8_scaled, uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[22]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_int16_t(buf, 4, chan1_scaled); + _mav_put_int16_t(buf, 6, chan2_scaled); + _mav_put_int16_t(buf, 8, chan3_scaled); + _mav_put_int16_t(buf, 10, chan4_scaled); + _mav_put_int16_t(buf, 12, chan5_scaled); + _mav_put_int16_t(buf, 14, chan6_scaled); + _mav_put_int16_t(buf, 16, chan7_scaled); + _mav_put_int16_t(buf, 18, chan8_scaled); + _mav_put_uint8_t(buf, 20, port); + _mav_put_uint8_t(buf, 21, rssi); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 22); +#else + mavlink_rc_channels_scaled_t packet; + packet.time_boot_ms = time_boot_ms; + packet.chan1_scaled = chan1_scaled; + packet.chan2_scaled = chan2_scaled; + packet.chan3_scaled = chan3_scaled; + packet.chan4_scaled = chan4_scaled; + packet.chan5_scaled = chan5_scaled; + packet.chan6_scaled = chan6_scaled; + packet.chan7_scaled = chan7_scaled; + packet.chan8_scaled = chan8_scaled; + packet.port = port; + packet.rssi = rssi; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 22); +#endif + + msg->msgid = MAVLINK_MSG_ID_RC_CHANNELS_SCALED; + return mavlink_finalize_message(msg, system_id, component_id, 22, 237); +} + +/** + * @brief Pack a rc_channels_scaled message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param port Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + * @param chan1_scaled RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan2_scaled RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan3_scaled RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan4_scaled RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan5_scaled RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan6_scaled RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan7_scaled RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan8_scaled RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_rc_channels_scaled_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,uint8_t port,int16_t chan1_scaled,int16_t chan2_scaled,int16_t chan3_scaled,int16_t chan4_scaled,int16_t chan5_scaled,int16_t chan6_scaled,int16_t chan7_scaled,int16_t chan8_scaled,uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[22]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_int16_t(buf, 4, chan1_scaled); + _mav_put_int16_t(buf, 6, chan2_scaled); + _mav_put_int16_t(buf, 8, chan3_scaled); + _mav_put_int16_t(buf, 10, chan4_scaled); + _mav_put_int16_t(buf, 12, chan5_scaled); + _mav_put_int16_t(buf, 14, chan6_scaled); + _mav_put_int16_t(buf, 16, chan7_scaled); + _mav_put_int16_t(buf, 18, chan8_scaled); + _mav_put_uint8_t(buf, 20, port); + _mav_put_uint8_t(buf, 21, rssi); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 22); +#else + mavlink_rc_channels_scaled_t packet; + packet.time_boot_ms = time_boot_ms; + packet.chan1_scaled = chan1_scaled; + packet.chan2_scaled = chan2_scaled; + packet.chan3_scaled = chan3_scaled; + packet.chan4_scaled = chan4_scaled; + packet.chan5_scaled = chan5_scaled; + packet.chan6_scaled = chan6_scaled; + packet.chan7_scaled = chan7_scaled; + packet.chan8_scaled = chan8_scaled; + packet.port = port; + packet.rssi = rssi; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 22); +#endif + + msg->msgid = MAVLINK_MSG_ID_RC_CHANNELS_SCALED; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 22, 237); +} + +/** + * @brief Encode a rc_channels_scaled struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param rc_channels_scaled C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_rc_channels_scaled_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_rc_channels_scaled_t* rc_channels_scaled) +{ + return mavlink_msg_rc_channels_scaled_pack(system_id, component_id, msg, rc_channels_scaled->time_boot_ms, rc_channels_scaled->port, rc_channels_scaled->chan1_scaled, rc_channels_scaled->chan2_scaled, rc_channels_scaled->chan3_scaled, rc_channels_scaled->chan4_scaled, rc_channels_scaled->chan5_scaled, rc_channels_scaled->chan6_scaled, rc_channels_scaled->chan7_scaled, rc_channels_scaled->chan8_scaled, rc_channels_scaled->rssi); +} + +/** + * @brief Send a rc_channels_scaled message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param port Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + * @param chan1_scaled RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan2_scaled RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan3_scaled RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan4_scaled RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan5_scaled RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan6_scaled RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan7_scaled RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param chan8_scaled RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + * @param rssi Receive signal strength indicator, 0: 0%, 255: 100% + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_rc_channels_scaled_send(mavlink_channel_t chan, uint32_t time_boot_ms, uint8_t port, int16_t chan1_scaled, int16_t chan2_scaled, int16_t chan3_scaled, int16_t chan4_scaled, int16_t chan5_scaled, int16_t chan6_scaled, int16_t chan7_scaled, int16_t chan8_scaled, uint8_t rssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[22]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_int16_t(buf, 4, chan1_scaled); + _mav_put_int16_t(buf, 6, chan2_scaled); + _mav_put_int16_t(buf, 8, chan3_scaled); + _mav_put_int16_t(buf, 10, chan4_scaled); + _mav_put_int16_t(buf, 12, chan5_scaled); + _mav_put_int16_t(buf, 14, chan6_scaled); + _mav_put_int16_t(buf, 16, chan7_scaled); + _mav_put_int16_t(buf, 18, chan8_scaled); + _mav_put_uint8_t(buf, 20, port); + _mav_put_uint8_t(buf, 21, rssi); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RC_CHANNELS_SCALED, buf, 22, 237); +#else + mavlink_rc_channels_scaled_t packet; + packet.time_boot_ms = time_boot_ms; + packet.chan1_scaled = chan1_scaled; + packet.chan2_scaled = chan2_scaled; + packet.chan3_scaled = chan3_scaled; + packet.chan4_scaled = chan4_scaled; + packet.chan5_scaled = chan5_scaled; + packet.chan6_scaled = chan6_scaled; + packet.chan7_scaled = chan7_scaled; + packet.chan8_scaled = chan8_scaled; + packet.port = port; + packet.rssi = rssi; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RC_CHANNELS_SCALED, (const char *)&packet, 22, 237); +#endif +} + +#endif + +// MESSAGE RC_CHANNELS_SCALED UNPACKING + + +/** + * @brief Get field time_boot_ms from rc_channels_scaled message + * + * @return Timestamp (milliseconds since system boot) + */ +static inline uint32_t mavlink_msg_rc_channels_scaled_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field port from rc_channels_scaled message + * + * @return Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + */ +static inline uint8_t mavlink_msg_rc_channels_scaled_get_port(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 20); +} + +/** + * @brief Get field chan1_scaled from rc_channels_scaled message + * + * @return RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan1_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 4); +} + +/** + * @brief Get field chan2_scaled from rc_channels_scaled message + * + * @return RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan2_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 6); +} + +/** + * @brief Get field chan3_scaled from rc_channels_scaled message + * + * @return RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan3_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 8); +} + +/** + * @brief Get field chan4_scaled from rc_channels_scaled message + * + * @return RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan4_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 10); +} + +/** + * @brief Get field chan5_scaled from rc_channels_scaled message + * + * @return RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan5_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Get field chan6_scaled from rc_channels_scaled message + * + * @return RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan6_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 14); +} + +/** + * @brief Get field chan7_scaled from rc_channels_scaled message + * + * @return RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan7_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 16); +} + +/** + * @brief Get field chan8_scaled from rc_channels_scaled message + * + * @return RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 + */ +static inline int16_t mavlink_msg_rc_channels_scaled_get_chan8_scaled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 18); +} + +/** + * @brief Get field rssi from rc_channels_scaled message + * + * @return Receive signal strength indicator, 0: 0%, 255: 100% + */ +static inline uint8_t mavlink_msg_rc_channels_scaled_get_rssi(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 21); +} + +/** + * @brief Decode a rc_channels_scaled message into a struct + * + * @param msg The message to decode + * @param rc_channels_scaled C-struct to decode the message contents into + */ +static inline void mavlink_msg_rc_channels_scaled_decode(const mavlink_message_t* msg, mavlink_rc_channels_scaled_t* rc_channels_scaled) +{ +#if MAVLINK_NEED_BYTE_SWAP + rc_channels_scaled->time_boot_ms = mavlink_msg_rc_channels_scaled_get_time_boot_ms(msg); + rc_channels_scaled->chan1_scaled = mavlink_msg_rc_channels_scaled_get_chan1_scaled(msg); + rc_channels_scaled->chan2_scaled = mavlink_msg_rc_channels_scaled_get_chan2_scaled(msg); + rc_channels_scaled->chan3_scaled = mavlink_msg_rc_channels_scaled_get_chan3_scaled(msg); + rc_channels_scaled->chan4_scaled = mavlink_msg_rc_channels_scaled_get_chan4_scaled(msg); + rc_channels_scaled->chan5_scaled = mavlink_msg_rc_channels_scaled_get_chan5_scaled(msg); + rc_channels_scaled->chan6_scaled = mavlink_msg_rc_channels_scaled_get_chan6_scaled(msg); + rc_channels_scaled->chan7_scaled = mavlink_msg_rc_channels_scaled_get_chan7_scaled(msg); + rc_channels_scaled->chan8_scaled = mavlink_msg_rc_channels_scaled_get_chan8_scaled(msg); + rc_channels_scaled->port = mavlink_msg_rc_channels_scaled_get_port(msg); + rc_channels_scaled->rssi = mavlink_msg_rc_channels_scaled_get_rssi(msg); +#else + memcpy(rc_channels_scaled, _MAV_PAYLOAD(msg), 22); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_request_data_stream.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_request_data_stream.h new file mode 100644 index 0000000000..d8653ad109 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_request_data_stream.h @@ -0,0 +1,232 @@ +// MESSAGE REQUEST_DATA_STREAM PACKING + +#define MAVLINK_MSG_ID_REQUEST_DATA_STREAM 66 + +typedef struct __mavlink_request_data_stream_t +{ + uint16_t req_message_rate; ///< The requested interval between two messages of this type + uint8_t target_system; ///< The target requested to send the message stream. + uint8_t target_component; ///< The target requested to send the message stream. + uint8_t req_stream_id; ///< The ID of the requested data stream + uint8_t start_stop; ///< 1 to start sending, 0 to stop sending. +} mavlink_request_data_stream_t; + +#define MAVLINK_MSG_ID_REQUEST_DATA_STREAM_LEN 6 +#define MAVLINK_MSG_ID_66_LEN 6 + + + +#define MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM { \ + "REQUEST_DATA_STREAM", \ + 5, \ + { { "req_message_rate", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_request_data_stream_t, req_message_rate) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_request_data_stream_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_request_data_stream_t, target_component) }, \ + { "req_stream_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_request_data_stream_t, req_stream_id) }, \ + { "start_stop", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_request_data_stream_t, start_stop) }, \ + } \ +} + + +/** + * @brief Pack a request_data_stream message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system The target requested to send the message stream. + * @param target_component The target requested to send the message stream. + * @param req_stream_id The ID of the requested data stream + * @param req_message_rate The requested interval between two messages of this type + * @param start_stop 1 to start sending, 0 to stop sending. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_request_data_stream_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t req_stream_id, uint16_t req_message_rate, uint8_t start_stop) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint16_t(buf, 0, req_message_rate); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + _mav_put_uint8_t(buf, 4, req_stream_id); + _mav_put_uint8_t(buf, 5, start_stop); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_request_data_stream_t packet; + packet.req_message_rate = req_message_rate; + packet.target_system = target_system; + packet.target_component = target_component; + packet.req_stream_id = req_stream_id; + packet.start_stop = start_stop; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_REQUEST_DATA_STREAM; + return mavlink_finalize_message(msg, system_id, component_id, 6, 148); +} + +/** + * @brief Pack a request_data_stream message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system The target requested to send the message stream. + * @param target_component The target requested to send the message stream. + * @param req_stream_id The ID of the requested data stream + * @param req_message_rate The requested interval between two messages of this type + * @param start_stop 1 to start sending, 0 to stop sending. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_request_data_stream_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t req_stream_id,uint16_t req_message_rate,uint8_t start_stop) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint16_t(buf, 0, req_message_rate); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + _mav_put_uint8_t(buf, 4, req_stream_id); + _mav_put_uint8_t(buf, 5, start_stop); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_request_data_stream_t packet; + packet.req_message_rate = req_message_rate; + packet.target_system = target_system; + packet.target_component = target_component; + packet.req_stream_id = req_stream_id; + packet.start_stop = start_stop; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_REQUEST_DATA_STREAM; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 6, 148); +} + +/** + * @brief Encode a request_data_stream struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param request_data_stream C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_request_data_stream_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_request_data_stream_t* request_data_stream) +{ + return mavlink_msg_request_data_stream_pack(system_id, component_id, msg, request_data_stream->target_system, request_data_stream->target_component, request_data_stream->req_stream_id, request_data_stream->req_message_rate, request_data_stream->start_stop); +} + +/** + * @brief Send a request_data_stream message + * @param chan MAVLink channel to send the message + * + * @param target_system The target requested to send the message stream. + * @param target_component The target requested to send the message stream. + * @param req_stream_id The ID of the requested data stream + * @param req_message_rate The requested interval between two messages of this type + * @param start_stop 1 to start sending, 0 to stop sending. + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_request_data_stream_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t req_stream_id, uint16_t req_message_rate, uint8_t start_stop) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint16_t(buf, 0, req_message_rate); + _mav_put_uint8_t(buf, 2, target_system); + _mav_put_uint8_t(buf, 3, target_component); + _mav_put_uint8_t(buf, 4, req_stream_id); + _mav_put_uint8_t(buf, 5, start_stop); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_REQUEST_DATA_STREAM, buf, 6, 148); +#else + mavlink_request_data_stream_t packet; + packet.req_message_rate = req_message_rate; + packet.target_system = target_system; + packet.target_component = target_component; + packet.req_stream_id = req_stream_id; + packet.start_stop = start_stop; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_REQUEST_DATA_STREAM, (const char *)&packet, 6, 148); +#endif +} + +#endif + +// MESSAGE REQUEST_DATA_STREAM UNPACKING + + +/** + * @brief Get field target_system from request_data_stream message + * + * @return The target requested to send the message stream. + */ +static inline uint8_t mavlink_msg_request_data_stream_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field target_component from request_data_stream message + * + * @return The target requested to send the message stream. + */ +static inline uint8_t mavlink_msg_request_data_stream_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field req_stream_id from request_data_stream message + * + * @return The ID of the requested data stream + */ +static inline uint8_t mavlink_msg_request_data_stream_get_req_stream_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field req_message_rate from request_data_stream message + * + * @return The requested interval between two messages of this type + */ +static inline uint16_t mavlink_msg_request_data_stream_get_req_message_rate(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field start_stop from request_data_stream message + * + * @return 1 to start sending, 0 to stop sending. + */ +static inline uint8_t mavlink_msg_request_data_stream_get_start_stop(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Decode a request_data_stream message into a struct + * + * @param msg The message to decode + * @param request_data_stream C-struct to decode the message contents into + */ +static inline void mavlink_msg_request_data_stream_decode(const mavlink_message_t* msg, mavlink_request_data_stream_t* request_data_stream) +{ +#if MAVLINK_NEED_BYTE_SWAP + request_data_stream->req_message_rate = mavlink_msg_request_data_stream_get_req_message_rate(msg); + request_data_stream->target_system = mavlink_msg_request_data_stream_get_target_system(msg); + request_data_stream->target_component = mavlink_msg_request_data_stream_get_target_component(msg); + request_data_stream->req_stream_id = mavlink_msg_request_data_stream_get_req_stream_id(msg); + request_data_stream->start_stop = mavlink_msg_request_data_stream_get_start_stop(msg); +#else + memcpy(request_data_stream, _MAV_PAYLOAD(msg), 6); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint.h new file mode 100644 index 0000000000..5751badc3e --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint.h @@ -0,0 +1,232 @@ +// MESSAGE ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT PACKING + +#define MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT 59 + +typedef struct __mavlink_roll_pitch_yaw_speed_thrust_setpoint_t +{ + uint32_t time_boot_ms; ///< Timestamp in milliseconds since system boot + float roll_speed; ///< Desired roll angular speed in rad/s + float pitch_speed; ///< Desired pitch angular speed in rad/s + float yaw_speed; ///< Desired yaw angular speed in rad/s + float thrust; ///< Collective thrust, normalized to 0 .. 1 +} mavlink_roll_pitch_yaw_speed_thrust_setpoint_t; + +#define MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT_LEN 20 +#define MAVLINK_MSG_ID_59_LEN 20 + + + +#define MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT { \ + "ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT", \ + 5, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_roll_pitch_yaw_speed_thrust_setpoint_t, time_boot_ms) }, \ + { "roll_speed", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_roll_pitch_yaw_speed_thrust_setpoint_t, roll_speed) }, \ + { "pitch_speed", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_roll_pitch_yaw_speed_thrust_setpoint_t, pitch_speed) }, \ + { "yaw_speed", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_roll_pitch_yaw_speed_thrust_setpoint_t, yaw_speed) }, \ + { "thrust", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_roll_pitch_yaw_speed_thrust_setpoint_t, thrust) }, \ + } \ +} + + +/** + * @brief Pack a roll_pitch_yaw_speed_thrust_setpoint message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp in milliseconds since system boot + * @param roll_speed Desired roll angular speed in rad/s + * @param pitch_speed Desired pitch angular speed in rad/s + * @param yaw_speed Desired yaw angular speed in rad/s + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, float roll_speed, float pitch_speed, float yaw_speed, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, roll_speed); + _mav_put_float(buf, 8, pitch_speed); + _mav_put_float(buf, 12, yaw_speed); + _mav_put_float(buf, 16, thrust); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_roll_pitch_yaw_speed_thrust_setpoint_t packet; + packet.time_boot_ms = time_boot_ms; + packet.roll_speed = roll_speed; + packet.pitch_speed = pitch_speed; + packet.yaw_speed = yaw_speed; + packet.thrust = thrust; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT; + return mavlink_finalize_message(msg, system_id, component_id, 20, 238); +} + +/** + * @brief Pack a roll_pitch_yaw_speed_thrust_setpoint message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp in milliseconds since system boot + * @param roll_speed Desired roll angular speed in rad/s + * @param pitch_speed Desired pitch angular speed in rad/s + * @param yaw_speed Desired yaw angular speed in rad/s + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,float roll_speed,float pitch_speed,float yaw_speed,float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, roll_speed); + _mav_put_float(buf, 8, pitch_speed); + _mav_put_float(buf, 12, yaw_speed); + _mav_put_float(buf, 16, thrust); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_roll_pitch_yaw_speed_thrust_setpoint_t packet; + packet.time_boot_ms = time_boot_ms; + packet.roll_speed = roll_speed; + packet.pitch_speed = pitch_speed; + packet.yaw_speed = yaw_speed; + packet.thrust = thrust; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 20, 238); +} + +/** + * @brief Encode a roll_pitch_yaw_speed_thrust_setpoint struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param roll_pitch_yaw_speed_thrust_setpoint C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_roll_pitch_yaw_speed_thrust_setpoint_t* roll_pitch_yaw_speed_thrust_setpoint) +{ + return mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_pack(system_id, component_id, msg, roll_pitch_yaw_speed_thrust_setpoint->time_boot_ms, roll_pitch_yaw_speed_thrust_setpoint->roll_speed, roll_pitch_yaw_speed_thrust_setpoint->pitch_speed, roll_pitch_yaw_speed_thrust_setpoint->yaw_speed, roll_pitch_yaw_speed_thrust_setpoint->thrust); +} + +/** + * @brief Send a roll_pitch_yaw_speed_thrust_setpoint message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp in milliseconds since system boot + * @param roll_speed Desired roll angular speed in rad/s + * @param pitch_speed Desired pitch angular speed in rad/s + * @param yaw_speed Desired yaw angular speed in rad/s + * @param thrust Collective thrust, normalized to 0 .. 1 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_send(mavlink_channel_t chan, uint32_t time_boot_ms, float roll_speed, float pitch_speed, float yaw_speed, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, roll_speed); + _mav_put_float(buf, 8, pitch_speed); + _mav_put_float(buf, 12, yaw_speed); + _mav_put_float(buf, 16, thrust); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, buf, 20, 238); +#else + mavlink_roll_pitch_yaw_speed_thrust_setpoint_t packet; + packet.time_boot_ms = time_boot_ms; + packet.roll_speed = roll_speed; + packet.pitch_speed = pitch_speed; + packet.yaw_speed = yaw_speed; + packet.thrust = thrust; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, (const char *)&packet, 20, 238); +#endif +} + +#endif + +// MESSAGE ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT UNPACKING + + +/** + * @brief Get field time_boot_ms from roll_pitch_yaw_speed_thrust_setpoint message + * + * @return Timestamp in milliseconds since system boot + */ +static inline uint32_t mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field roll_speed from roll_pitch_yaw_speed_thrust_setpoint message + * + * @return Desired roll angular speed in rad/s + */ +static inline float mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_roll_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field pitch_speed from roll_pitch_yaw_speed_thrust_setpoint message + * + * @return Desired pitch angular speed in rad/s + */ +static inline float mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_pitch_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field yaw_speed from roll_pitch_yaw_speed_thrust_setpoint message + * + * @return Desired yaw angular speed in rad/s + */ +static inline float mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_yaw_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field thrust from roll_pitch_yaw_speed_thrust_setpoint message + * + * @return Collective thrust, normalized to 0 .. 1 + */ +static inline float mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_thrust(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Decode a roll_pitch_yaw_speed_thrust_setpoint message into a struct + * + * @param msg The message to decode + * @param roll_pitch_yaw_speed_thrust_setpoint C-struct to decode the message contents into + */ +static inline void mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_decode(const mavlink_message_t* msg, mavlink_roll_pitch_yaw_speed_thrust_setpoint_t* roll_pitch_yaw_speed_thrust_setpoint) +{ +#if MAVLINK_NEED_BYTE_SWAP + roll_pitch_yaw_speed_thrust_setpoint->time_boot_ms = mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_time_boot_ms(msg); + roll_pitch_yaw_speed_thrust_setpoint->roll_speed = mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_roll_speed(msg); + roll_pitch_yaw_speed_thrust_setpoint->pitch_speed = mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_pitch_speed(msg); + roll_pitch_yaw_speed_thrust_setpoint->yaw_speed = mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_yaw_speed(msg); + roll_pitch_yaw_speed_thrust_setpoint->thrust = mavlink_msg_roll_pitch_yaw_speed_thrust_setpoint_get_thrust(msg); +#else + memcpy(roll_pitch_yaw_speed_thrust_setpoint, _MAV_PAYLOAD(msg), 20); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_roll_pitch_yaw_thrust_setpoint.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_roll_pitch_yaw_thrust_setpoint.h new file mode 100644 index 0000000000..a9f6ad0caa --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_roll_pitch_yaw_thrust_setpoint.h @@ -0,0 +1,232 @@ +// MESSAGE ROLL_PITCH_YAW_THRUST_SETPOINT PACKING + +#define MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT 58 + +typedef struct __mavlink_roll_pitch_yaw_thrust_setpoint_t +{ + uint32_t time_boot_ms; ///< Timestamp in milliseconds since system boot + float roll; ///< Desired roll angle in radians + float pitch; ///< Desired pitch angle in radians + float yaw; ///< Desired yaw angle in radians + float thrust; ///< Collective thrust, normalized to 0 .. 1 +} mavlink_roll_pitch_yaw_thrust_setpoint_t; + +#define MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT_LEN 20 +#define MAVLINK_MSG_ID_58_LEN 20 + + + +#define MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT { \ + "ROLL_PITCH_YAW_THRUST_SETPOINT", \ + 5, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_roll_pitch_yaw_thrust_setpoint_t, time_boot_ms) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_roll_pitch_yaw_thrust_setpoint_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_roll_pitch_yaw_thrust_setpoint_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_roll_pitch_yaw_thrust_setpoint_t, yaw) }, \ + { "thrust", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_roll_pitch_yaw_thrust_setpoint_t, thrust) }, \ + } \ +} + + +/** + * @brief Pack a roll_pitch_yaw_thrust_setpoint message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp in milliseconds since system boot + * @param roll Desired roll angle in radians + * @param pitch Desired pitch angle in radians + * @param yaw Desired yaw angle in radians + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_roll_pitch_yaw_thrust_setpoint_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, float roll, float pitch, float yaw, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, roll); + _mav_put_float(buf, 8, pitch); + _mav_put_float(buf, 12, yaw); + _mav_put_float(buf, 16, thrust); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_roll_pitch_yaw_thrust_setpoint_t packet; + packet.time_boot_ms = time_boot_ms; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT; + return mavlink_finalize_message(msg, system_id, component_id, 20, 239); +} + +/** + * @brief Pack a roll_pitch_yaw_thrust_setpoint message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp in milliseconds since system boot + * @param roll Desired roll angle in radians + * @param pitch Desired pitch angle in radians + * @param yaw Desired yaw angle in radians + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_roll_pitch_yaw_thrust_setpoint_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,float roll,float pitch,float yaw,float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, roll); + _mav_put_float(buf, 8, pitch); + _mav_put_float(buf, 12, yaw); + _mav_put_float(buf, 16, thrust); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_roll_pitch_yaw_thrust_setpoint_t packet; + packet.time_boot_ms = time_boot_ms; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 20, 239); +} + +/** + * @brief Encode a roll_pitch_yaw_thrust_setpoint struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param roll_pitch_yaw_thrust_setpoint C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_roll_pitch_yaw_thrust_setpoint_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_roll_pitch_yaw_thrust_setpoint_t* roll_pitch_yaw_thrust_setpoint) +{ + return mavlink_msg_roll_pitch_yaw_thrust_setpoint_pack(system_id, component_id, msg, roll_pitch_yaw_thrust_setpoint->time_boot_ms, roll_pitch_yaw_thrust_setpoint->roll, roll_pitch_yaw_thrust_setpoint->pitch, roll_pitch_yaw_thrust_setpoint->yaw, roll_pitch_yaw_thrust_setpoint->thrust); +} + +/** + * @brief Send a roll_pitch_yaw_thrust_setpoint message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp in milliseconds since system boot + * @param roll Desired roll angle in radians + * @param pitch Desired pitch angle in radians + * @param yaw Desired yaw angle in radians + * @param thrust Collective thrust, normalized to 0 .. 1 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_roll_pitch_yaw_thrust_setpoint_send(mavlink_channel_t chan, uint32_t time_boot_ms, float roll, float pitch, float yaw, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, roll); + _mav_put_float(buf, 8, pitch); + _mav_put_float(buf, 12, yaw); + _mav_put_float(buf, 16, thrust); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT, buf, 20, 239); +#else + mavlink_roll_pitch_yaw_thrust_setpoint_t packet; + packet.time_boot_ms = time_boot_ms; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT, (const char *)&packet, 20, 239); +#endif +} + +#endif + +// MESSAGE ROLL_PITCH_YAW_THRUST_SETPOINT UNPACKING + + +/** + * @brief Get field time_boot_ms from roll_pitch_yaw_thrust_setpoint message + * + * @return Timestamp in milliseconds since system boot + */ +static inline uint32_t mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field roll from roll_pitch_yaw_thrust_setpoint message + * + * @return Desired roll angle in radians + */ +static inline float mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field pitch from roll_pitch_yaw_thrust_setpoint message + * + * @return Desired pitch angle in radians + */ +static inline float mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field yaw from roll_pitch_yaw_thrust_setpoint message + * + * @return Desired yaw angle in radians + */ +static inline float mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field thrust from roll_pitch_yaw_thrust_setpoint message + * + * @return Collective thrust, normalized to 0 .. 1 + */ +static inline float mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_thrust(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Decode a roll_pitch_yaw_thrust_setpoint message into a struct + * + * @param msg The message to decode + * @param roll_pitch_yaw_thrust_setpoint C-struct to decode the message contents into + */ +static inline void mavlink_msg_roll_pitch_yaw_thrust_setpoint_decode(const mavlink_message_t* msg, mavlink_roll_pitch_yaw_thrust_setpoint_t* roll_pitch_yaw_thrust_setpoint) +{ +#if MAVLINK_NEED_BYTE_SWAP + roll_pitch_yaw_thrust_setpoint->time_boot_ms = mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_time_boot_ms(msg); + roll_pitch_yaw_thrust_setpoint->roll = mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_roll(msg); + roll_pitch_yaw_thrust_setpoint->pitch = mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_pitch(msg); + roll_pitch_yaw_thrust_setpoint->yaw = mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_yaw(msg); + roll_pitch_yaw_thrust_setpoint->thrust = mavlink_msg_roll_pitch_yaw_thrust_setpoint_get_thrust(msg); +#else + memcpy(roll_pitch_yaw_thrust_setpoint, _MAV_PAYLOAD(msg), 20); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_safety_allowed_area.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_safety_allowed_area.h new file mode 100644 index 0000000000..aae6fd206a --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_safety_allowed_area.h @@ -0,0 +1,276 @@ +// MESSAGE SAFETY_ALLOWED_AREA PACKING + +#define MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA 55 + +typedef struct __mavlink_safety_allowed_area_t +{ + float p1x; ///< x position 1 / Latitude 1 + float p1y; ///< y position 1 / Longitude 1 + float p1z; ///< z position 1 / Altitude 1 + float p2x; ///< x position 2 / Latitude 2 + float p2y; ///< y position 2 / Longitude 2 + float p2z; ///< z position 2 / Altitude 2 + uint8_t frame; ///< Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. +} mavlink_safety_allowed_area_t; + +#define MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA_LEN 25 +#define MAVLINK_MSG_ID_55_LEN 25 + + + +#define MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA { \ + "SAFETY_ALLOWED_AREA", \ + 7, \ + { { "p1x", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_safety_allowed_area_t, p1x) }, \ + { "p1y", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_safety_allowed_area_t, p1y) }, \ + { "p1z", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_safety_allowed_area_t, p1z) }, \ + { "p2x", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_safety_allowed_area_t, p2x) }, \ + { "p2y", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_safety_allowed_area_t, p2y) }, \ + { "p2z", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_safety_allowed_area_t, p2z) }, \ + { "frame", NULL, MAVLINK_TYPE_UINT8_T, 0, 24, offsetof(mavlink_safety_allowed_area_t, frame) }, \ + } \ +} + + +/** + * @brief Pack a safety_allowed_area message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param frame Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + * @param p1x x position 1 / Latitude 1 + * @param p1y y position 1 / Longitude 1 + * @param p1z z position 1 / Altitude 1 + * @param p2x x position 2 / Latitude 2 + * @param p2y y position 2 / Longitude 2 + * @param p2z z position 2 / Altitude 2 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_safety_allowed_area_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t frame, float p1x, float p1y, float p1z, float p2x, float p2y, float p2z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[25]; + _mav_put_float(buf, 0, p1x); + _mav_put_float(buf, 4, p1y); + _mav_put_float(buf, 8, p1z); + _mav_put_float(buf, 12, p2x); + _mav_put_float(buf, 16, p2y); + _mav_put_float(buf, 20, p2z); + _mav_put_uint8_t(buf, 24, frame); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 25); +#else + mavlink_safety_allowed_area_t packet; + packet.p1x = p1x; + packet.p1y = p1y; + packet.p1z = p1z; + packet.p2x = p2x; + packet.p2y = p2y; + packet.p2z = p2z; + packet.frame = frame; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 25); +#endif + + msg->msgid = MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA; + return mavlink_finalize_message(msg, system_id, component_id, 25, 3); +} + +/** + * @brief Pack a safety_allowed_area message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param frame Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + * @param p1x x position 1 / Latitude 1 + * @param p1y y position 1 / Longitude 1 + * @param p1z z position 1 / Altitude 1 + * @param p2x x position 2 / Latitude 2 + * @param p2y y position 2 / Longitude 2 + * @param p2z z position 2 / Altitude 2 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_safety_allowed_area_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t frame,float p1x,float p1y,float p1z,float p2x,float p2y,float p2z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[25]; + _mav_put_float(buf, 0, p1x); + _mav_put_float(buf, 4, p1y); + _mav_put_float(buf, 8, p1z); + _mav_put_float(buf, 12, p2x); + _mav_put_float(buf, 16, p2y); + _mav_put_float(buf, 20, p2z); + _mav_put_uint8_t(buf, 24, frame); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 25); +#else + mavlink_safety_allowed_area_t packet; + packet.p1x = p1x; + packet.p1y = p1y; + packet.p1z = p1z; + packet.p2x = p2x; + packet.p2y = p2y; + packet.p2z = p2z; + packet.frame = frame; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 25); +#endif + + msg->msgid = MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 25, 3); +} + +/** + * @brief Encode a safety_allowed_area struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param safety_allowed_area C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_safety_allowed_area_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_safety_allowed_area_t* safety_allowed_area) +{ + return mavlink_msg_safety_allowed_area_pack(system_id, component_id, msg, safety_allowed_area->frame, safety_allowed_area->p1x, safety_allowed_area->p1y, safety_allowed_area->p1z, safety_allowed_area->p2x, safety_allowed_area->p2y, safety_allowed_area->p2z); +} + +/** + * @brief Send a safety_allowed_area message + * @param chan MAVLink channel to send the message + * + * @param frame Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + * @param p1x x position 1 / Latitude 1 + * @param p1y y position 1 / Longitude 1 + * @param p1z z position 1 / Altitude 1 + * @param p2x x position 2 / Latitude 2 + * @param p2y y position 2 / Longitude 2 + * @param p2z z position 2 / Altitude 2 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_safety_allowed_area_send(mavlink_channel_t chan, uint8_t frame, float p1x, float p1y, float p1z, float p2x, float p2y, float p2z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[25]; + _mav_put_float(buf, 0, p1x); + _mav_put_float(buf, 4, p1y); + _mav_put_float(buf, 8, p1z); + _mav_put_float(buf, 12, p2x); + _mav_put_float(buf, 16, p2y); + _mav_put_float(buf, 20, p2z); + _mav_put_uint8_t(buf, 24, frame); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA, buf, 25, 3); +#else + mavlink_safety_allowed_area_t packet; + packet.p1x = p1x; + packet.p1y = p1y; + packet.p1z = p1z; + packet.p2x = p2x; + packet.p2y = p2y; + packet.p2z = p2z; + packet.frame = frame; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA, (const char *)&packet, 25, 3); +#endif +} + +#endif + +// MESSAGE SAFETY_ALLOWED_AREA UNPACKING + + +/** + * @brief Get field frame from safety_allowed_area message + * + * @return Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + */ +static inline uint8_t mavlink_msg_safety_allowed_area_get_frame(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 24); +} + +/** + * @brief Get field p1x from safety_allowed_area message + * + * @return x position 1 / Latitude 1 + */ +static inline float mavlink_msg_safety_allowed_area_get_p1x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field p1y from safety_allowed_area message + * + * @return y position 1 / Longitude 1 + */ +static inline float mavlink_msg_safety_allowed_area_get_p1y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field p1z from safety_allowed_area message + * + * @return z position 1 / Altitude 1 + */ +static inline float mavlink_msg_safety_allowed_area_get_p1z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field p2x from safety_allowed_area message + * + * @return x position 2 / Latitude 2 + */ +static inline float mavlink_msg_safety_allowed_area_get_p2x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field p2y from safety_allowed_area message + * + * @return y position 2 / Longitude 2 + */ +static inline float mavlink_msg_safety_allowed_area_get_p2y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field p2z from safety_allowed_area message + * + * @return z position 2 / Altitude 2 + */ +static inline float mavlink_msg_safety_allowed_area_get_p2z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Decode a safety_allowed_area message into a struct + * + * @param msg The message to decode + * @param safety_allowed_area C-struct to decode the message contents into + */ +static inline void mavlink_msg_safety_allowed_area_decode(const mavlink_message_t* msg, mavlink_safety_allowed_area_t* safety_allowed_area) +{ +#if MAVLINK_NEED_BYTE_SWAP + safety_allowed_area->p1x = mavlink_msg_safety_allowed_area_get_p1x(msg); + safety_allowed_area->p1y = mavlink_msg_safety_allowed_area_get_p1y(msg); + safety_allowed_area->p1z = mavlink_msg_safety_allowed_area_get_p1z(msg); + safety_allowed_area->p2x = mavlink_msg_safety_allowed_area_get_p2x(msg); + safety_allowed_area->p2y = mavlink_msg_safety_allowed_area_get_p2y(msg); + safety_allowed_area->p2z = mavlink_msg_safety_allowed_area_get_p2z(msg); + safety_allowed_area->frame = mavlink_msg_safety_allowed_area_get_frame(msg); +#else + memcpy(safety_allowed_area, _MAV_PAYLOAD(msg), 25); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_safety_set_allowed_area.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_safety_set_allowed_area.h new file mode 100644 index 0000000000..8fb410c2d6 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_safety_set_allowed_area.h @@ -0,0 +1,320 @@ +// MESSAGE SAFETY_SET_ALLOWED_AREA PACKING + +#define MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA 54 + +typedef struct __mavlink_safety_set_allowed_area_t +{ + float p1x; ///< x position 1 / Latitude 1 + float p1y; ///< y position 1 / Longitude 1 + float p1z; ///< z position 1 / Altitude 1 + float p2x; ///< x position 2 / Latitude 2 + float p2y; ///< y position 2 / Longitude 2 + float p2z; ///< z position 2 / Altitude 2 + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t frame; ///< Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. +} mavlink_safety_set_allowed_area_t; + +#define MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA_LEN 27 +#define MAVLINK_MSG_ID_54_LEN 27 + + + +#define MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA { \ + "SAFETY_SET_ALLOWED_AREA", \ + 9, \ + { { "p1x", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_safety_set_allowed_area_t, p1x) }, \ + { "p1y", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_safety_set_allowed_area_t, p1y) }, \ + { "p1z", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_safety_set_allowed_area_t, p1z) }, \ + { "p2x", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_safety_set_allowed_area_t, p2x) }, \ + { "p2y", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_safety_set_allowed_area_t, p2y) }, \ + { "p2z", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_safety_set_allowed_area_t, p2z) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 24, offsetof(mavlink_safety_set_allowed_area_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 25, offsetof(mavlink_safety_set_allowed_area_t, target_component) }, \ + { "frame", NULL, MAVLINK_TYPE_UINT8_T, 0, 26, offsetof(mavlink_safety_set_allowed_area_t, frame) }, \ + } \ +} + + +/** + * @brief Pack a safety_set_allowed_area message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param frame Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + * @param p1x x position 1 / Latitude 1 + * @param p1y y position 1 / Longitude 1 + * @param p1z z position 1 / Altitude 1 + * @param p2x x position 2 / Latitude 2 + * @param p2y y position 2 / Longitude 2 + * @param p2z z position 2 / Altitude 2 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_safety_set_allowed_area_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t frame, float p1x, float p1y, float p1z, float p2x, float p2y, float p2z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[27]; + _mav_put_float(buf, 0, p1x); + _mav_put_float(buf, 4, p1y); + _mav_put_float(buf, 8, p1z); + _mav_put_float(buf, 12, p2x); + _mav_put_float(buf, 16, p2y); + _mav_put_float(buf, 20, p2z); + _mav_put_uint8_t(buf, 24, target_system); + _mav_put_uint8_t(buf, 25, target_component); + _mav_put_uint8_t(buf, 26, frame); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 27); +#else + mavlink_safety_set_allowed_area_t packet; + packet.p1x = p1x; + packet.p1y = p1y; + packet.p1z = p1z; + packet.p2x = p2x; + packet.p2y = p2y; + packet.p2z = p2z; + packet.target_system = target_system; + packet.target_component = target_component; + packet.frame = frame; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 27); +#endif + + msg->msgid = MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA; + return mavlink_finalize_message(msg, system_id, component_id, 27, 15); +} + +/** + * @brief Pack a safety_set_allowed_area message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param frame Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + * @param p1x x position 1 / Latitude 1 + * @param p1y y position 1 / Longitude 1 + * @param p1z z position 1 / Altitude 1 + * @param p2x x position 2 / Latitude 2 + * @param p2y y position 2 / Longitude 2 + * @param p2z z position 2 / Altitude 2 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_safety_set_allowed_area_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t frame,float p1x,float p1y,float p1z,float p2x,float p2y,float p2z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[27]; + _mav_put_float(buf, 0, p1x); + _mav_put_float(buf, 4, p1y); + _mav_put_float(buf, 8, p1z); + _mav_put_float(buf, 12, p2x); + _mav_put_float(buf, 16, p2y); + _mav_put_float(buf, 20, p2z); + _mav_put_uint8_t(buf, 24, target_system); + _mav_put_uint8_t(buf, 25, target_component); + _mav_put_uint8_t(buf, 26, frame); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 27); +#else + mavlink_safety_set_allowed_area_t packet; + packet.p1x = p1x; + packet.p1y = p1y; + packet.p1z = p1z; + packet.p2x = p2x; + packet.p2y = p2y; + packet.p2z = p2z; + packet.target_system = target_system; + packet.target_component = target_component; + packet.frame = frame; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 27); +#endif + + msg->msgid = MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 27, 15); +} + +/** + * @brief Encode a safety_set_allowed_area struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param safety_set_allowed_area C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_safety_set_allowed_area_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_safety_set_allowed_area_t* safety_set_allowed_area) +{ + return mavlink_msg_safety_set_allowed_area_pack(system_id, component_id, msg, safety_set_allowed_area->target_system, safety_set_allowed_area->target_component, safety_set_allowed_area->frame, safety_set_allowed_area->p1x, safety_set_allowed_area->p1y, safety_set_allowed_area->p1z, safety_set_allowed_area->p2x, safety_set_allowed_area->p2y, safety_set_allowed_area->p2z); +} + +/** + * @brief Send a safety_set_allowed_area message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param frame Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + * @param p1x x position 1 / Latitude 1 + * @param p1y y position 1 / Longitude 1 + * @param p1z z position 1 / Altitude 1 + * @param p2x x position 2 / Latitude 2 + * @param p2y y position 2 / Longitude 2 + * @param p2z z position 2 / Altitude 2 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_safety_set_allowed_area_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t frame, float p1x, float p1y, float p1z, float p2x, float p2y, float p2z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[27]; + _mav_put_float(buf, 0, p1x); + _mav_put_float(buf, 4, p1y); + _mav_put_float(buf, 8, p1z); + _mav_put_float(buf, 12, p2x); + _mav_put_float(buf, 16, p2y); + _mav_put_float(buf, 20, p2z); + _mav_put_uint8_t(buf, 24, target_system); + _mav_put_uint8_t(buf, 25, target_component); + _mav_put_uint8_t(buf, 26, frame); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA, buf, 27, 15); +#else + mavlink_safety_set_allowed_area_t packet; + packet.p1x = p1x; + packet.p1y = p1y; + packet.p1z = p1z; + packet.p2x = p2x; + packet.p2y = p2y; + packet.p2z = p2z; + packet.target_system = target_system; + packet.target_component = target_component; + packet.frame = frame; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA, (const char *)&packet, 27, 15); +#endif +} + +#endif + +// MESSAGE SAFETY_SET_ALLOWED_AREA UNPACKING + + +/** + * @brief Get field target_system from safety_set_allowed_area message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_safety_set_allowed_area_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 24); +} + +/** + * @brief Get field target_component from safety_set_allowed_area message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_safety_set_allowed_area_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 25); +} + +/** + * @brief Get field frame from safety_set_allowed_area message + * + * @return Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. + */ +static inline uint8_t mavlink_msg_safety_set_allowed_area_get_frame(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 26); +} + +/** + * @brief Get field p1x from safety_set_allowed_area message + * + * @return x position 1 / Latitude 1 + */ +static inline float mavlink_msg_safety_set_allowed_area_get_p1x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field p1y from safety_set_allowed_area message + * + * @return y position 1 / Longitude 1 + */ +static inline float mavlink_msg_safety_set_allowed_area_get_p1y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field p1z from safety_set_allowed_area message + * + * @return z position 1 / Altitude 1 + */ +static inline float mavlink_msg_safety_set_allowed_area_get_p1z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field p2x from safety_set_allowed_area message + * + * @return x position 2 / Latitude 2 + */ +static inline float mavlink_msg_safety_set_allowed_area_get_p2x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field p2y from safety_set_allowed_area message + * + * @return y position 2 / Longitude 2 + */ +static inline float mavlink_msg_safety_set_allowed_area_get_p2y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field p2z from safety_set_allowed_area message + * + * @return z position 2 / Altitude 2 + */ +static inline float mavlink_msg_safety_set_allowed_area_get_p2z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Decode a safety_set_allowed_area message into a struct + * + * @param msg The message to decode + * @param safety_set_allowed_area C-struct to decode the message contents into + */ +static inline void mavlink_msg_safety_set_allowed_area_decode(const mavlink_message_t* msg, mavlink_safety_set_allowed_area_t* safety_set_allowed_area) +{ +#if MAVLINK_NEED_BYTE_SWAP + safety_set_allowed_area->p1x = mavlink_msg_safety_set_allowed_area_get_p1x(msg); + safety_set_allowed_area->p1y = mavlink_msg_safety_set_allowed_area_get_p1y(msg); + safety_set_allowed_area->p1z = mavlink_msg_safety_set_allowed_area_get_p1z(msg); + safety_set_allowed_area->p2x = mavlink_msg_safety_set_allowed_area_get_p2x(msg); + safety_set_allowed_area->p2y = mavlink_msg_safety_set_allowed_area_get_p2y(msg); + safety_set_allowed_area->p2z = mavlink_msg_safety_set_allowed_area_get_p2z(msg); + safety_set_allowed_area->target_system = mavlink_msg_safety_set_allowed_area_get_target_system(msg); + safety_set_allowed_area->target_component = mavlink_msg_safety_set_allowed_area_get_target_component(msg); + safety_set_allowed_area->frame = mavlink_msg_safety_set_allowed_area_get_frame(msg); +#else + memcpy(safety_set_allowed_area, _MAV_PAYLOAD(msg), 27); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_scaled_imu.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_scaled_imu.h new file mode 100644 index 0000000000..8ff098f39f --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_scaled_imu.h @@ -0,0 +1,342 @@ +// MESSAGE SCALED_IMU PACKING + +#define MAVLINK_MSG_ID_SCALED_IMU 26 + +typedef struct __mavlink_scaled_imu_t +{ + uint32_t time_boot_ms; ///< Timestamp (milliseconds since system boot) + int16_t xacc; ///< X acceleration (mg) + int16_t yacc; ///< Y acceleration (mg) + int16_t zacc; ///< Z acceleration (mg) + int16_t xgyro; ///< Angular speed around X axis (millirad /sec) + int16_t ygyro; ///< Angular speed around Y axis (millirad /sec) + int16_t zgyro; ///< Angular speed around Z axis (millirad /sec) + int16_t xmag; ///< X Magnetic field (milli tesla) + int16_t ymag; ///< Y Magnetic field (milli tesla) + int16_t zmag; ///< Z Magnetic field (milli tesla) +} mavlink_scaled_imu_t; + +#define MAVLINK_MSG_ID_SCALED_IMU_LEN 22 +#define MAVLINK_MSG_ID_26_LEN 22 + + + +#define MAVLINK_MESSAGE_INFO_SCALED_IMU { \ + "SCALED_IMU", \ + 10, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_scaled_imu_t, time_boot_ms) }, \ + { "xacc", NULL, MAVLINK_TYPE_INT16_T, 0, 4, offsetof(mavlink_scaled_imu_t, xacc) }, \ + { "yacc", NULL, MAVLINK_TYPE_INT16_T, 0, 6, offsetof(mavlink_scaled_imu_t, yacc) }, \ + { "zacc", NULL, MAVLINK_TYPE_INT16_T, 0, 8, offsetof(mavlink_scaled_imu_t, zacc) }, \ + { "xgyro", NULL, MAVLINK_TYPE_INT16_T, 0, 10, offsetof(mavlink_scaled_imu_t, xgyro) }, \ + { "ygyro", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_scaled_imu_t, ygyro) }, \ + { "zgyro", NULL, MAVLINK_TYPE_INT16_T, 0, 14, offsetof(mavlink_scaled_imu_t, zgyro) }, \ + { "xmag", NULL, MAVLINK_TYPE_INT16_T, 0, 16, offsetof(mavlink_scaled_imu_t, xmag) }, \ + { "ymag", NULL, MAVLINK_TYPE_INT16_T, 0, 18, offsetof(mavlink_scaled_imu_t, ymag) }, \ + { "zmag", NULL, MAVLINK_TYPE_INT16_T, 0, 20, offsetof(mavlink_scaled_imu_t, zmag) }, \ + } \ +} + + +/** + * @brief Pack a scaled_imu message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param xacc X acceleration (mg) + * @param yacc Y acceleration (mg) + * @param zacc Z acceleration (mg) + * @param xgyro Angular speed around X axis (millirad /sec) + * @param ygyro Angular speed around Y axis (millirad /sec) + * @param zgyro Angular speed around Z axis (millirad /sec) + * @param xmag X Magnetic field (milli tesla) + * @param ymag Y Magnetic field (milli tesla) + * @param zmag Z Magnetic field (milli tesla) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_scaled_imu_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, int16_t xacc, int16_t yacc, int16_t zacc, int16_t xgyro, int16_t ygyro, int16_t zgyro, int16_t xmag, int16_t ymag, int16_t zmag) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[22]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_int16_t(buf, 4, xacc); + _mav_put_int16_t(buf, 6, yacc); + _mav_put_int16_t(buf, 8, zacc); + _mav_put_int16_t(buf, 10, xgyro); + _mav_put_int16_t(buf, 12, ygyro); + _mav_put_int16_t(buf, 14, zgyro); + _mav_put_int16_t(buf, 16, xmag); + _mav_put_int16_t(buf, 18, ymag); + _mav_put_int16_t(buf, 20, zmag); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 22); +#else + mavlink_scaled_imu_t packet; + packet.time_boot_ms = time_boot_ms; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + packet.xmag = xmag; + packet.ymag = ymag; + packet.zmag = zmag; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 22); +#endif + + msg->msgid = MAVLINK_MSG_ID_SCALED_IMU; + return mavlink_finalize_message(msg, system_id, component_id, 22, 170); +} + +/** + * @brief Pack a scaled_imu message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param xacc X acceleration (mg) + * @param yacc Y acceleration (mg) + * @param zacc Z acceleration (mg) + * @param xgyro Angular speed around X axis (millirad /sec) + * @param ygyro Angular speed around Y axis (millirad /sec) + * @param zgyro Angular speed around Z axis (millirad /sec) + * @param xmag X Magnetic field (milli tesla) + * @param ymag Y Magnetic field (milli tesla) + * @param zmag Z Magnetic field (milli tesla) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_scaled_imu_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,int16_t xacc,int16_t yacc,int16_t zacc,int16_t xgyro,int16_t ygyro,int16_t zgyro,int16_t xmag,int16_t ymag,int16_t zmag) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[22]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_int16_t(buf, 4, xacc); + _mav_put_int16_t(buf, 6, yacc); + _mav_put_int16_t(buf, 8, zacc); + _mav_put_int16_t(buf, 10, xgyro); + _mav_put_int16_t(buf, 12, ygyro); + _mav_put_int16_t(buf, 14, zgyro); + _mav_put_int16_t(buf, 16, xmag); + _mav_put_int16_t(buf, 18, ymag); + _mav_put_int16_t(buf, 20, zmag); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 22); +#else + mavlink_scaled_imu_t packet; + packet.time_boot_ms = time_boot_ms; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + packet.xmag = xmag; + packet.ymag = ymag; + packet.zmag = zmag; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 22); +#endif + + msg->msgid = MAVLINK_MSG_ID_SCALED_IMU; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 22, 170); +} + +/** + * @brief Encode a scaled_imu struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param scaled_imu C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_scaled_imu_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_scaled_imu_t* scaled_imu) +{ + return mavlink_msg_scaled_imu_pack(system_id, component_id, msg, scaled_imu->time_boot_ms, scaled_imu->xacc, scaled_imu->yacc, scaled_imu->zacc, scaled_imu->xgyro, scaled_imu->ygyro, scaled_imu->zgyro, scaled_imu->xmag, scaled_imu->ymag, scaled_imu->zmag); +} + +/** + * @brief Send a scaled_imu message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp (milliseconds since system boot) + * @param xacc X acceleration (mg) + * @param yacc Y acceleration (mg) + * @param zacc Z acceleration (mg) + * @param xgyro Angular speed around X axis (millirad /sec) + * @param ygyro Angular speed around Y axis (millirad /sec) + * @param zgyro Angular speed around Z axis (millirad /sec) + * @param xmag X Magnetic field (milli tesla) + * @param ymag Y Magnetic field (milli tesla) + * @param zmag Z Magnetic field (milli tesla) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_scaled_imu_send(mavlink_channel_t chan, uint32_t time_boot_ms, int16_t xacc, int16_t yacc, int16_t zacc, int16_t xgyro, int16_t ygyro, int16_t zgyro, int16_t xmag, int16_t ymag, int16_t zmag) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[22]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_int16_t(buf, 4, xacc); + _mav_put_int16_t(buf, 6, yacc); + _mav_put_int16_t(buf, 8, zacc); + _mav_put_int16_t(buf, 10, xgyro); + _mav_put_int16_t(buf, 12, ygyro); + _mav_put_int16_t(buf, 14, zgyro); + _mav_put_int16_t(buf, 16, xmag); + _mav_put_int16_t(buf, 18, ymag); + _mav_put_int16_t(buf, 20, zmag); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SCALED_IMU, buf, 22, 170); +#else + mavlink_scaled_imu_t packet; + packet.time_boot_ms = time_boot_ms; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + packet.xmag = xmag; + packet.ymag = ymag; + packet.zmag = zmag; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SCALED_IMU, (const char *)&packet, 22, 170); +#endif +} + +#endif + +// MESSAGE SCALED_IMU UNPACKING + + +/** + * @brief Get field time_boot_ms from scaled_imu message + * + * @return Timestamp (milliseconds since system boot) + */ +static inline uint32_t mavlink_msg_scaled_imu_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field xacc from scaled_imu message + * + * @return X acceleration (mg) + */ +static inline int16_t mavlink_msg_scaled_imu_get_xacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 4); +} + +/** + * @brief Get field yacc from scaled_imu message + * + * @return Y acceleration (mg) + */ +static inline int16_t mavlink_msg_scaled_imu_get_yacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 6); +} + +/** + * @brief Get field zacc from scaled_imu message + * + * @return Z acceleration (mg) + */ +static inline int16_t mavlink_msg_scaled_imu_get_zacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 8); +} + +/** + * @brief Get field xgyro from scaled_imu message + * + * @return Angular speed around X axis (millirad /sec) + */ +static inline int16_t mavlink_msg_scaled_imu_get_xgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 10); +} + +/** + * @brief Get field ygyro from scaled_imu message + * + * @return Angular speed around Y axis (millirad /sec) + */ +static inline int16_t mavlink_msg_scaled_imu_get_ygyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Get field zgyro from scaled_imu message + * + * @return Angular speed around Z axis (millirad /sec) + */ +static inline int16_t mavlink_msg_scaled_imu_get_zgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 14); +} + +/** + * @brief Get field xmag from scaled_imu message + * + * @return X Magnetic field (milli tesla) + */ +static inline int16_t mavlink_msg_scaled_imu_get_xmag(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 16); +} + +/** + * @brief Get field ymag from scaled_imu message + * + * @return Y Magnetic field (milli tesla) + */ +static inline int16_t mavlink_msg_scaled_imu_get_ymag(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 18); +} + +/** + * @brief Get field zmag from scaled_imu message + * + * @return Z Magnetic field (milli tesla) + */ +static inline int16_t mavlink_msg_scaled_imu_get_zmag(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 20); +} + +/** + * @brief Decode a scaled_imu message into a struct + * + * @param msg The message to decode + * @param scaled_imu C-struct to decode the message contents into + */ +static inline void mavlink_msg_scaled_imu_decode(const mavlink_message_t* msg, mavlink_scaled_imu_t* scaled_imu) +{ +#if MAVLINK_NEED_BYTE_SWAP + scaled_imu->time_boot_ms = mavlink_msg_scaled_imu_get_time_boot_ms(msg); + scaled_imu->xacc = mavlink_msg_scaled_imu_get_xacc(msg); + scaled_imu->yacc = mavlink_msg_scaled_imu_get_yacc(msg); + scaled_imu->zacc = mavlink_msg_scaled_imu_get_zacc(msg); + scaled_imu->xgyro = mavlink_msg_scaled_imu_get_xgyro(msg); + scaled_imu->ygyro = mavlink_msg_scaled_imu_get_ygyro(msg); + scaled_imu->zgyro = mavlink_msg_scaled_imu_get_zgyro(msg); + scaled_imu->xmag = mavlink_msg_scaled_imu_get_xmag(msg); + scaled_imu->ymag = mavlink_msg_scaled_imu_get_ymag(msg); + scaled_imu->zmag = mavlink_msg_scaled_imu_get_zmag(msg); +#else + memcpy(scaled_imu, _MAV_PAYLOAD(msg), 22); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_scaled_pressure.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_scaled_pressure.h new file mode 100644 index 0000000000..dac1e0b9a6 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_scaled_pressure.h @@ -0,0 +1,210 @@ +// MESSAGE SCALED_PRESSURE PACKING + +#define MAVLINK_MSG_ID_SCALED_PRESSURE 29 + +typedef struct __mavlink_scaled_pressure_t +{ + uint32_t time_boot_ms; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot) + float press_abs; ///< Absolute pressure (hectopascal) + float press_diff; ///< Differential pressure 1 (hectopascal) + int16_t temperature; ///< Temperature measurement (0.01 degrees celsius) +} mavlink_scaled_pressure_t; + +#define MAVLINK_MSG_ID_SCALED_PRESSURE_LEN 14 +#define MAVLINK_MSG_ID_29_LEN 14 + + + +#define MAVLINK_MESSAGE_INFO_SCALED_PRESSURE { \ + "SCALED_PRESSURE", \ + 4, \ + { { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_scaled_pressure_t, time_boot_ms) }, \ + { "press_abs", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_scaled_pressure_t, press_abs) }, \ + { "press_diff", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_scaled_pressure_t, press_diff) }, \ + { "temperature", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_scaled_pressure_t, temperature) }, \ + } \ +} + + +/** + * @brief Pack a scaled_pressure message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_boot_ms Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param press_abs Absolute pressure (hectopascal) + * @param press_diff Differential pressure 1 (hectopascal) + * @param temperature Temperature measurement (0.01 degrees celsius) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_scaled_pressure_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_boot_ms, float press_abs, float press_diff, int16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, press_abs); + _mav_put_float(buf, 8, press_diff); + _mav_put_int16_t(buf, 12, temperature); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_scaled_pressure_t packet; + packet.time_boot_ms = time_boot_ms; + packet.press_abs = press_abs; + packet.press_diff = press_diff; + packet.temperature = temperature; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_SCALED_PRESSURE; + return mavlink_finalize_message(msg, system_id, component_id, 14, 115); +} + +/** + * @brief Pack a scaled_pressure message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_boot_ms Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param press_abs Absolute pressure (hectopascal) + * @param press_diff Differential pressure 1 (hectopascal) + * @param temperature Temperature measurement (0.01 degrees celsius) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_scaled_pressure_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_boot_ms,float press_abs,float press_diff,int16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, press_abs); + _mav_put_float(buf, 8, press_diff); + _mav_put_int16_t(buf, 12, temperature); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 14); +#else + mavlink_scaled_pressure_t packet; + packet.time_boot_ms = time_boot_ms; + packet.press_abs = press_abs; + packet.press_diff = press_diff; + packet.temperature = temperature; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 14); +#endif + + msg->msgid = MAVLINK_MSG_ID_SCALED_PRESSURE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 14, 115); +} + +/** + * @brief Encode a scaled_pressure struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param scaled_pressure C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_scaled_pressure_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_scaled_pressure_t* scaled_pressure) +{ + return mavlink_msg_scaled_pressure_pack(system_id, component_id, msg, scaled_pressure->time_boot_ms, scaled_pressure->press_abs, scaled_pressure->press_diff, scaled_pressure->temperature); +} + +/** + * @brief Send a scaled_pressure message + * @param chan MAVLink channel to send the message + * + * @param time_boot_ms Timestamp (microseconds since UNIX epoch or microseconds since system boot) + * @param press_abs Absolute pressure (hectopascal) + * @param press_diff Differential pressure 1 (hectopascal) + * @param temperature Temperature measurement (0.01 degrees celsius) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_scaled_pressure_send(mavlink_channel_t chan, uint32_t time_boot_ms, float press_abs, float press_diff, int16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[14]; + _mav_put_uint32_t(buf, 0, time_boot_ms); + _mav_put_float(buf, 4, press_abs); + _mav_put_float(buf, 8, press_diff); + _mav_put_int16_t(buf, 12, temperature); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SCALED_PRESSURE, buf, 14, 115); +#else + mavlink_scaled_pressure_t packet; + packet.time_boot_ms = time_boot_ms; + packet.press_abs = press_abs; + packet.press_diff = press_diff; + packet.temperature = temperature; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SCALED_PRESSURE, (const char *)&packet, 14, 115); +#endif +} + +#endif + +// MESSAGE SCALED_PRESSURE UNPACKING + + +/** + * @brief Get field time_boot_ms from scaled_pressure message + * + * @return Timestamp (microseconds since UNIX epoch or microseconds since system boot) + */ +static inline uint32_t mavlink_msg_scaled_pressure_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field press_abs from scaled_pressure message + * + * @return Absolute pressure (hectopascal) + */ +static inline float mavlink_msg_scaled_pressure_get_press_abs(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field press_diff from scaled_pressure message + * + * @return Differential pressure 1 (hectopascal) + */ +static inline float mavlink_msg_scaled_pressure_get_press_diff(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field temperature from scaled_pressure message + * + * @return Temperature measurement (0.01 degrees celsius) + */ +static inline int16_t mavlink_msg_scaled_pressure_get_temperature(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Decode a scaled_pressure message into a struct + * + * @param msg The message to decode + * @param scaled_pressure C-struct to decode the message contents into + */ +static inline void mavlink_msg_scaled_pressure_decode(const mavlink_message_t* msg, mavlink_scaled_pressure_t* scaled_pressure) +{ +#if MAVLINK_NEED_BYTE_SWAP + scaled_pressure->time_boot_ms = mavlink_msg_scaled_pressure_get_time_boot_ms(msg); + scaled_pressure->press_abs = mavlink_msg_scaled_pressure_get_press_abs(msg); + scaled_pressure->press_diff = mavlink_msg_scaled_pressure_get_press_diff(msg); + scaled_pressure->temperature = mavlink_msg_scaled_pressure_get_temperature(msg); +#else + memcpy(scaled_pressure, _MAV_PAYLOAD(msg), 14); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_servo_output_raw.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_servo_output_raw.h new file mode 100644 index 0000000000..34a58cd763 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_servo_output_raw.h @@ -0,0 +1,342 @@ +// MESSAGE SERVO_OUTPUT_RAW PACKING + +#define MAVLINK_MSG_ID_SERVO_OUTPUT_RAW 36 + +typedef struct __mavlink_servo_output_raw_t +{ + uint32_t time_usec; ///< Timestamp (since UNIX epoch or microseconds since system boot) + uint16_t servo1_raw; ///< Servo output 1 value, in microseconds + uint16_t servo2_raw; ///< Servo output 2 value, in microseconds + uint16_t servo3_raw; ///< Servo output 3 value, in microseconds + uint16_t servo4_raw; ///< Servo output 4 value, in microseconds + uint16_t servo5_raw; ///< Servo output 5 value, in microseconds + uint16_t servo6_raw; ///< Servo output 6 value, in microseconds + uint16_t servo7_raw; ///< Servo output 7 value, in microseconds + uint16_t servo8_raw; ///< Servo output 8 value, in microseconds + uint8_t port; ///< Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. +} mavlink_servo_output_raw_t; + +#define MAVLINK_MSG_ID_SERVO_OUTPUT_RAW_LEN 21 +#define MAVLINK_MSG_ID_36_LEN 21 + + + +#define MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW { \ + "SERVO_OUTPUT_RAW", \ + 10, \ + { { "time_usec", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_servo_output_raw_t, time_usec) }, \ + { "servo1_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_servo_output_raw_t, servo1_raw) }, \ + { "servo2_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_servo_output_raw_t, servo2_raw) }, \ + { "servo3_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 8, offsetof(mavlink_servo_output_raw_t, servo3_raw) }, \ + { "servo4_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 10, offsetof(mavlink_servo_output_raw_t, servo4_raw) }, \ + { "servo5_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 12, offsetof(mavlink_servo_output_raw_t, servo5_raw) }, \ + { "servo6_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 14, offsetof(mavlink_servo_output_raw_t, servo6_raw) }, \ + { "servo7_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 16, offsetof(mavlink_servo_output_raw_t, servo7_raw) }, \ + { "servo8_raw", NULL, MAVLINK_TYPE_UINT16_T, 0, 18, offsetof(mavlink_servo_output_raw_t, servo8_raw) }, \ + { "port", NULL, MAVLINK_TYPE_UINT8_T, 0, 20, offsetof(mavlink_servo_output_raw_t, port) }, \ + } \ +} + + +/** + * @brief Pack a servo_output_raw message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_usec Timestamp (since UNIX epoch or microseconds since system boot) + * @param port Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + * @param servo1_raw Servo output 1 value, in microseconds + * @param servo2_raw Servo output 2 value, in microseconds + * @param servo3_raw Servo output 3 value, in microseconds + * @param servo4_raw Servo output 4 value, in microseconds + * @param servo5_raw Servo output 5 value, in microseconds + * @param servo6_raw Servo output 6 value, in microseconds + * @param servo7_raw Servo output 7 value, in microseconds + * @param servo8_raw Servo output 8 value, in microseconds + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_servo_output_raw_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t time_usec, uint8_t port, uint16_t servo1_raw, uint16_t servo2_raw, uint16_t servo3_raw, uint16_t servo4_raw, uint16_t servo5_raw, uint16_t servo6_raw, uint16_t servo7_raw, uint16_t servo8_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_uint32_t(buf, 0, time_usec); + _mav_put_uint16_t(buf, 4, servo1_raw); + _mav_put_uint16_t(buf, 6, servo2_raw); + _mav_put_uint16_t(buf, 8, servo3_raw); + _mav_put_uint16_t(buf, 10, servo4_raw); + _mav_put_uint16_t(buf, 12, servo5_raw); + _mav_put_uint16_t(buf, 14, servo6_raw); + _mav_put_uint16_t(buf, 16, servo7_raw); + _mav_put_uint16_t(buf, 18, servo8_raw); + _mav_put_uint8_t(buf, 20, port); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 21); +#else + mavlink_servo_output_raw_t packet; + packet.time_usec = time_usec; + packet.servo1_raw = servo1_raw; + packet.servo2_raw = servo2_raw; + packet.servo3_raw = servo3_raw; + packet.servo4_raw = servo4_raw; + packet.servo5_raw = servo5_raw; + packet.servo6_raw = servo6_raw; + packet.servo7_raw = servo7_raw; + packet.servo8_raw = servo8_raw; + packet.port = port; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 21); +#endif + + msg->msgid = MAVLINK_MSG_ID_SERVO_OUTPUT_RAW; + return mavlink_finalize_message(msg, system_id, component_id, 21, 222); +} + +/** + * @brief Pack a servo_output_raw message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_usec Timestamp (since UNIX epoch or microseconds since system boot) + * @param port Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + * @param servo1_raw Servo output 1 value, in microseconds + * @param servo2_raw Servo output 2 value, in microseconds + * @param servo3_raw Servo output 3 value, in microseconds + * @param servo4_raw Servo output 4 value, in microseconds + * @param servo5_raw Servo output 5 value, in microseconds + * @param servo6_raw Servo output 6 value, in microseconds + * @param servo7_raw Servo output 7 value, in microseconds + * @param servo8_raw Servo output 8 value, in microseconds + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_servo_output_raw_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t time_usec,uint8_t port,uint16_t servo1_raw,uint16_t servo2_raw,uint16_t servo3_raw,uint16_t servo4_raw,uint16_t servo5_raw,uint16_t servo6_raw,uint16_t servo7_raw,uint16_t servo8_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_uint32_t(buf, 0, time_usec); + _mav_put_uint16_t(buf, 4, servo1_raw); + _mav_put_uint16_t(buf, 6, servo2_raw); + _mav_put_uint16_t(buf, 8, servo3_raw); + _mav_put_uint16_t(buf, 10, servo4_raw); + _mav_put_uint16_t(buf, 12, servo5_raw); + _mav_put_uint16_t(buf, 14, servo6_raw); + _mav_put_uint16_t(buf, 16, servo7_raw); + _mav_put_uint16_t(buf, 18, servo8_raw); + _mav_put_uint8_t(buf, 20, port); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 21); +#else + mavlink_servo_output_raw_t packet; + packet.time_usec = time_usec; + packet.servo1_raw = servo1_raw; + packet.servo2_raw = servo2_raw; + packet.servo3_raw = servo3_raw; + packet.servo4_raw = servo4_raw; + packet.servo5_raw = servo5_raw; + packet.servo6_raw = servo6_raw; + packet.servo7_raw = servo7_raw; + packet.servo8_raw = servo8_raw; + packet.port = port; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 21); +#endif + + msg->msgid = MAVLINK_MSG_ID_SERVO_OUTPUT_RAW; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 21, 222); +} + +/** + * @brief Encode a servo_output_raw struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param servo_output_raw C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_servo_output_raw_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_servo_output_raw_t* servo_output_raw) +{ + return mavlink_msg_servo_output_raw_pack(system_id, component_id, msg, servo_output_raw->time_usec, servo_output_raw->port, servo_output_raw->servo1_raw, servo_output_raw->servo2_raw, servo_output_raw->servo3_raw, servo_output_raw->servo4_raw, servo_output_raw->servo5_raw, servo_output_raw->servo6_raw, servo_output_raw->servo7_raw, servo_output_raw->servo8_raw); +} + +/** + * @brief Send a servo_output_raw message + * @param chan MAVLink channel to send the message + * + * @param time_usec Timestamp (since UNIX epoch or microseconds since system boot) + * @param port Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + * @param servo1_raw Servo output 1 value, in microseconds + * @param servo2_raw Servo output 2 value, in microseconds + * @param servo3_raw Servo output 3 value, in microseconds + * @param servo4_raw Servo output 4 value, in microseconds + * @param servo5_raw Servo output 5 value, in microseconds + * @param servo6_raw Servo output 6 value, in microseconds + * @param servo7_raw Servo output 7 value, in microseconds + * @param servo8_raw Servo output 8 value, in microseconds + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_servo_output_raw_send(mavlink_channel_t chan, uint32_t time_usec, uint8_t port, uint16_t servo1_raw, uint16_t servo2_raw, uint16_t servo3_raw, uint16_t servo4_raw, uint16_t servo5_raw, uint16_t servo6_raw, uint16_t servo7_raw, uint16_t servo8_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_uint32_t(buf, 0, time_usec); + _mav_put_uint16_t(buf, 4, servo1_raw); + _mav_put_uint16_t(buf, 6, servo2_raw); + _mav_put_uint16_t(buf, 8, servo3_raw); + _mav_put_uint16_t(buf, 10, servo4_raw); + _mav_put_uint16_t(buf, 12, servo5_raw); + _mav_put_uint16_t(buf, 14, servo6_raw); + _mav_put_uint16_t(buf, 16, servo7_raw); + _mav_put_uint16_t(buf, 18, servo8_raw); + _mav_put_uint8_t(buf, 20, port); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SERVO_OUTPUT_RAW, buf, 21, 222); +#else + mavlink_servo_output_raw_t packet; + packet.time_usec = time_usec; + packet.servo1_raw = servo1_raw; + packet.servo2_raw = servo2_raw; + packet.servo3_raw = servo3_raw; + packet.servo4_raw = servo4_raw; + packet.servo5_raw = servo5_raw; + packet.servo6_raw = servo6_raw; + packet.servo7_raw = servo7_raw; + packet.servo8_raw = servo8_raw; + packet.port = port; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SERVO_OUTPUT_RAW, (const char *)&packet, 21, 222); +#endif +} + +#endif + +// MESSAGE SERVO_OUTPUT_RAW UNPACKING + + +/** + * @brief Get field time_usec from servo_output_raw message + * + * @return Timestamp (since UNIX epoch or microseconds since system boot) + */ +static inline uint32_t mavlink_msg_servo_output_raw_get_time_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field port from servo_output_raw message + * + * @return Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. + */ +static inline uint8_t mavlink_msg_servo_output_raw_get_port(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 20); +} + +/** + * @brief Get field servo1_raw from servo_output_raw message + * + * @return Servo output 1 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo1_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field servo2_raw from servo_output_raw message + * + * @return Servo output 2 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo2_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field servo3_raw from servo_output_raw message + * + * @return Servo output 3 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo3_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Get field servo4_raw from servo_output_raw message + * + * @return Servo output 4 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo4_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 10); +} + +/** + * @brief Get field servo5_raw from servo_output_raw message + * + * @return Servo output 5 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo5_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 12); +} + +/** + * @brief Get field servo6_raw from servo_output_raw message + * + * @return Servo output 6 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo6_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 14); +} + +/** + * @brief Get field servo7_raw from servo_output_raw message + * + * @return Servo output 7 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo7_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 16); +} + +/** + * @brief Get field servo8_raw from servo_output_raw message + * + * @return Servo output 8 value, in microseconds + */ +static inline uint16_t mavlink_msg_servo_output_raw_get_servo8_raw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 18); +} + +/** + * @brief Decode a servo_output_raw message into a struct + * + * @param msg The message to decode + * @param servo_output_raw C-struct to decode the message contents into + */ +static inline void mavlink_msg_servo_output_raw_decode(const mavlink_message_t* msg, mavlink_servo_output_raw_t* servo_output_raw) +{ +#if MAVLINK_NEED_BYTE_SWAP + servo_output_raw->time_usec = mavlink_msg_servo_output_raw_get_time_usec(msg); + servo_output_raw->servo1_raw = mavlink_msg_servo_output_raw_get_servo1_raw(msg); + servo_output_raw->servo2_raw = mavlink_msg_servo_output_raw_get_servo2_raw(msg); + servo_output_raw->servo3_raw = mavlink_msg_servo_output_raw_get_servo3_raw(msg); + servo_output_raw->servo4_raw = mavlink_msg_servo_output_raw_get_servo4_raw(msg); + servo_output_raw->servo5_raw = mavlink_msg_servo_output_raw_get_servo5_raw(msg); + servo_output_raw->servo6_raw = mavlink_msg_servo_output_raw_get_servo6_raw(msg); + servo_output_raw->servo7_raw = mavlink_msg_servo_output_raw_get_servo7_raw(msg); + servo_output_raw->servo8_raw = mavlink_msg_servo_output_raw_get_servo8_raw(msg); + servo_output_raw->port = mavlink_msg_servo_output_raw_get_port(msg); +#else + memcpy(servo_output_raw, _MAV_PAYLOAD(msg), 21); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_global_position_setpoint_int.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_global_position_setpoint_int.h new file mode 100644 index 0000000000..5b706fb506 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_global_position_setpoint_int.h @@ -0,0 +1,232 @@ +// MESSAGE SET_GLOBAL_POSITION_SETPOINT_INT PACKING + +#define MAVLINK_MSG_ID_SET_GLOBAL_POSITION_SETPOINT_INT 53 + +typedef struct __mavlink_set_global_position_setpoint_int_t +{ + int32_t latitude; ///< WGS84 Latitude position in degrees * 1E7 + int32_t longitude; ///< WGS84 Longitude position in degrees * 1E7 + int32_t altitude; ///< WGS84 Altitude in meters * 1000 (positive for up) + int16_t yaw; ///< Desired yaw angle in degrees * 100 + uint8_t coordinate_frame; ///< Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT +} mavlink_set_global_position_setpoint_int_t; + +#define MAVLINK_MSG_ID_SET_GLOBAL_POSITION_SETPOINT_INT_LEN 15 +#define MAVLINK_MSG_ID_53_LEN 15 + + + +#define MAVLINK_MESSAGE_INFO_SET_GLOBAL_POSITION_SETPOINT_INT { \ + "SET_GLOBAL_POSITION_SETPOINT_INT", \ + 5, \ + { { "latitude", NULL, MAVLINK_TYPE_INT32_T, 0, 0, offsetof(mavlink_set_global_position_setpoint_int_t, latitude) }, \ + { "longitude", NULL, MAVLINK_TYPE_INT32_T, 0, 4, offsetof(mavlink_set_global_position_setpoint_int_t, longitude) }, \ + { "altitude", NULL, MAVLINK_TYPE_INT32_T, 0, 8, offsetof(mavlink_set_global_position_setpoint_int_t, altitude) }, \ + { "yaw", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_set_global_position_setpoint_int_t, yaw) }, \ + { "coordinate_frame", NULL, MAVLINK_TYPE_UINT8_T, 0, 14, offsetof(mavlink_set_global_position_setpoint_int_t, coordinate_frame) }, \ + } \ +} + + +/** + * @brief Pack a set_global_position_setpoint_int message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param coordinate_frame Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT + * @param latitude WGS84 Latitude position in degrees * 1E7 + * @param longitude WGS84 Longitude position in degrees * 1E7 + * @param altitude WGS84 Altitude in meters * 1000 (positive for up) + * @param yaw Desired yaw angle in degrees * 100 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_global_position_setpoint_int_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t coordinate_frame, int32_t latitude, int32_t longitude, int32_t altitude, int16_t yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + _mav_put_int16_t(buf, 12, yaw); + _mav_put_uint8_t(buf, 14, coordinate_frame); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 15); +#else + mavlink_set_global_position_setpoint_int_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + packet.yaw = yaw; + packet.coordinate_frame = coordinate_frame; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 15); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_GLOBAL_POSITION_SETPOINT_INT; + return mavlink_finalize_message(msg, system_id, component_id, 15, 33); +} + +/** + * @brief Pack a set_global_position_setpoint_int message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param coordinate_frame Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT + * @param latitude WGS84 Latitude position in degrees * 1E7 + * @param longitude WGS84 Longitude position in degrees * 1E7 + * @param altitude WGS84 Altitude in meters * 1000 (positive for up) + * @param yaw Desired yaw angle in degrees * 100 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_global_position_setpoint_int_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t coordinate_frame,int32_t latitude,int32_t longitude,int32_t altitude,int16_t yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + _mav_put_int16_t(buf, 12, yaw); + _mav_put_uint8_t(buf, 14, coordinate_frame); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 15); +#else + mavlink_set_global_position_setpoint_int_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + packet.yaw = yaw; + packet.coordinate_frame = coordinate_frame; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 15); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_GLOBAL_POSITION_SETPOINT_INT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 15, 33); +} + +/** + * @brief Encode a set_global_position_setpoint_int struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_global_position_setpoint_int C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_global_position_setpoint_int_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_global_position_setpoint_int_t* set_global_position_setpoint_int) +{ + return mavlink_msg_set_global_position_setpoint_int_pack(system_id, component_id, msg, set_global_position_setpoint_int->coordinate_frame, set_global_position_setpoint_int->latitude, set_global_position_setpoint_int->longitude, set_global_position_setpoint_int->altitude, set_global_position_setpoint_int->yaw); +} + +/** + * @brief Send a set_global_position_setpoint_int message + * @param chan MAVLink channel to send the message + * + * @param coordinate_frame Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT + * @param latitude WGS84 Latitude position in degrees * 1E7 + * @param longitude WGS84 Longitude position in degrees * 1E7 + * @param altitude WGS84 Altitude in meters * 1000 (positive for up) + * @param yaw Desired yaw angle in degrees * 100 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_global_position_setpoint_int_send(mavlink_channel_t chan, uint8_t coordinate_frame, int32_t latitude, int32_t longitude, int32_t altitude, int16_t yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[15]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + _mav_put_int16_t(buf, 12, yaw); + _mav_put_uint8_t(buf, 14, coordinate_frame); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_GLOBAL_POSITION_SETPOINT_INT, buf, 15, 33); +#else + mavlink_set_global_position_setpoint_int_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + packet.yaw = yaw; + packet.coordinate_frame = coordinate_frame; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_GLOBAL_POSITION_SETPOINT_INT, (const char *)&packet, 15, 33); +#endif +} + +#endif + +// MESSAGE SET_GLOBAL_POSITION_SETPOINT_INT UNPACKING + + +/** + * @brief Get field coordinate_frame from set_global_position_setpoint_int message + * + * @return Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT + */ +static inline uint8_t mavlink_msg_set_global_position_setpoint_int_get_coordinate_frame(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 14); +} + +/** + * @brief Get field latitude from set_global_position_setpoint_int message + * + * @return WGS84 Latitude position in degrees * 1E7 + */ +static inline int32_t mavlink_msg_set_global_position_setpoint_int_get_latitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 0); +} + +/** + * @brief Get field longitude from set_global_position_setpoint_int message + * + * @return WGS84 Longitude position in degrees * 1E7 + */ +static inline int32_t mavlink_msg_set_global_position_setpoint_int_get_longitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 4); +} + +/** + * @brief Get field altitude from set_global_position_setpoint_int message + * + * @return WGS84 Altitude in meters * 1000 (positive for up) + */ +static inline int32_t mavlink_msg_set_global_position_setpoint_int_get_altitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 8); +} + +/** + * @brief Get field yaw from set_global_position_setpoint_int message + * + * @return Desired yaw angle in degrees * 100 + */ +static inline int16_t mavlink_msg_set_global_position_setpoint_int_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Decode a set_global_position_setpoint_int message into a struct + * + * @param msg The message to decode + * @param set_global_position_setpoint_int C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_global_position_setpoint_int_decode(const mavlink_message_t* msg, mavlink_set_global_position_setpoint_int_t* set_global_position_setpoint_int) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_global_position_setpoint_int->latitude = mavlink_msg_set_global_position_setpoint_int_get_latitude(msg); + set_global_position_setpoint_int->longitude = mavlink_msg_set_global_position_setpoint_int_get_longitude(msg); + set_global_position_setpoint_int->altitude = mavlink_msg_set_global_position_setpoint_int_get_altitude(msg); + set_global_position_setpoint_int->yaw = mavlink_msg_set_global_position_setpoint_int_get_yaw(msg); + set_global_position_setpoint_int->coordinate_frame = mavlink_msg_set_global_position_setpoint_int_get_coordinate_frame(msg); +#else + memcpy(set_global_position_setpoint_int, _MAV_PAYLOAD(msg), 15); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_gps_global_origin.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_gps_global_origin.h new file mode 100644 index 0000000000..af404b1108 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_gps_global_origin.h @@ -0,0 +1,210 @@ +// MESSAGE SET_GPS_GLOBAL_ORIGIN PACKING + +#define MAVLINK_MSG_ID_SET_GPS_GLOBAL_ORIGIN 48 + +typedef struct __mavlink_set_gps_global_origin_t +{ + int32_t latitude; ///< global position * 1E7 + int32_t longitude; ///< global position * 1E7 + int32_t altitude; ///< global position * 1000 + uint8_t target_system; ///< System ID +} mavlink_set_gps_global_origin_t; + +#define MAVLINK_MSG_ID_SET_GPS_GLOBAL_ORIGIN_LEN 13 +#define MAVLINK_MSG_ID_48_LEN 13 + + + +#define MAVLINK_MESSAGE_INFO_SET_GPS_GLOBAL_ORIGIN { \ + "SET_GPS_GLOBAL_ORIGIN", \ + 4, \ + { { "latitude", NULL, MAVLINK_TYPE_INT32_T, 0, 0, offsetof(mavlink_set_gps_global_origin_t, latitude) }, \ + { "longitude", NULL, MAVLINK_TYPE_INT32_T, 0, 4, offsetof(mavlink_set_gps_global_origin_t, longitude) }, \ + { "altitude", NULL, MAVLINK_TYPE_INT32_T, 0, 8, offsetof(mavlink_set_gps_global_origin_t, altitude) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 12, offsetof(mavlink_set_gps_global_origin_t, target_system) }, \ + } \ +} + + +/** + * @brief Pack a set_gps_global_origin message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param latitude global position * 1E7 + * @param longitude global position * 1E7 + * @param altitude global position * 1000 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_gps_global_origin_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, int32_t latitude, int32_t longitude, int32_t altitude) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + _mav_put_uint8_t(buf, 12, target_system); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 13); +#else + mavlink_set_gps_global_origin_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + packet.target_system = target_system; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 13); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_GPS_GLOBAL_ORIGIN; + return mavlink_finalize_message(msg, system_id, component_id, 13, 41); +} + +/** + * @brief Pack a set_gps_global_origin message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param latitude global position * 1E7 + * @param longitude global position * 1E7 + * @param altitude global position * 1000 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_gps_global_origin_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,int32_t latitude,int32_t longitude,int32_t altitude) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + _mav_put_uint8_t(buf, 12, target_system); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 13); +#else + mavlink_set_gps_global_origin_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + packet.target_system = target_system; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 13); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_GPS_GLOBAL_ORIGIN; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 13, 41); +} + +/** + * @brief Encode a set_gps_global_origin struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_gps_global_origin C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_gps_global_origin_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_gps_global_origin_t* set_gps_global_origin) +{ + return mavlink_msg_set_gps_global_origin_pack(system_id, component_id, msg, set_gps_global_origin->target_system, set_gps_global_origin->latitude, set_gps_global_origin->longitude, set_gps_global_origin->altitude); +} + +/** + * @brief Send a set_gps_global_origin message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param latitude global position * 1E7 + * @param longitude global position * 1E7 + * @param altitude global position * 1000 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_gps_global_origin_send(mavlink_channel_t chan, uint8_t target_system, int32_t latitude, int32_t longitude, int32_t altitude) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_int32_t(buf, 0, latitude); + _mav_put_int32_t(buf, 4, longitude); + _mav_put_int32_t(buf, 8, altitude); + _mav_put_uint8_t(buf, 12, target_system); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_GPS_GLOBAL_ORIGIN, buf, 13, 41); +#else + mavlink_set_gps_global_origin_t packet; + packet.latitude = latitude; + packet.longitude = longitude; + packet.altitude = altitude; + packet.target_system = target_system; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_GPS_GLOBAL_ORIGIN, (const char *)&packet, 13, 41); +#endif +} + +#endif + +// MESSAGE SET_GPS_GLOBAL_ORIGIN UNPACKING + + +/** + * @brief Get field target_system from set_gps_global_origin message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_set_gps_global_origin_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 12); +} + +/** + * @brief Get field latitude from set_gps_global_origin message + * + * @return global position * 1E7 + */ +static inline int32_t mavlink_msg_set_gps_global_origin_get_latitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 0); +} + +/** + * @brief Get field longitude from set_gps_global_origin message + * + * @return global position * 1E7 + */ +static inline int32_t mavlink_msg_set_gps_global_origin_get_longitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 4); +} + +/** + * @brief Get field altitude from set_gps_global_origin message + * + * @return global position * 1000 + */ +static inline int32_t mavlink_msg_set_gps_global_origin_get_altitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 8); +} + +/** + * @brief Decode a set_gps_global_origin message into a struct + * + * @param msg The message to decode + * @param set_gps_global_origin C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_gps_global_origin_decode(const mavlink_message_t* msg, mavlink_set_gps_global_origin_t* set_gps_global_origin) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_gps_global_origin->latitude = mavlink_msg_set_gps_global_origin_get_latitude(msg); + set_gps_global_origin->longitude = mavlink_msg_set_gps_global_origin_get_longitude(msg); + set_gps_global_origin->altitude = mavlink_msg_set_gps_global_origin_get_altitude(msg); + set_gps_global_origin->target_system = mavlink_msg_set_gps_global_origin_get_target_system(msg); +#else + memcpy(set_gps_global_origin, _MAV_PAYLOAD(msg), 13); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_local_position_setpoint.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_local_position_setpoint.h new file mode 100644 index 0000000000..233e07d65c --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_local_position_setpoint.h @@ -0,0 +1,276 @@ +// MESSAGE SET_LOCAL_POSITION_SETPOINT PACKING + +#define MAVLINK_MSG_ID_SET_LOCAL_POSITION_SETPOINT 50 + +typedef struct __mavlink_set_local_position_setpoint_t +{ + float x; ///< x position + float y; ///< y position + float z; ///< z position + float yaw; ///< Desired yaw angle + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID + uint8_t coordinate_frame; ///< Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU +} mavlink_set_local_position_setpoint_t; + +#define MAVLINK_MSG_ID_SET_LOCAL_POSITION_SETPOINT_LEN 19 +#define MAVLINK_MSG_ID_50_LEN 19 + + + +#define MAVLINK_MESSAGE_INFO_SET_LOCAL_POSITION_SETPOINT { \ + "SET_LOCAL_POSITION_SETPOINT", \ + 7, \ + { { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_set_local_position_setpoint_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_set_local_position_setpoint_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_set_local_position_setpoint_t, z) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_set_local_position_setpoint_t, yaw) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 16, offsetof(mavlink_set_local_position_setpoint_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 17, offsetof(mavlink_set_local_position_setpoint_t, target_component) }, \ + { "coordinate_frame", NULL, MAVLINK_TYPE_UINT8_T, 0, 18, offsetof(mavlink_set_local_position_setpoint_t, coordinate_frame) }, \ + } \ +} + + +/** + * @brief Pack a set_local_position_setpoint message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param coordinate_frame Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU + * @param x x position + * @param y y position + * @param z z position + * @param yaw Desired yaw angle + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_local_position_setpoint_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, uint8_t coordinate_frame, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[19]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + _mav_put_uint8_t(buf, 18, coordinate_frame); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 19); +#else + mavlink_set_local_position_setpoint_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + packet.target_system = target_system; + packet.target_component = target_component; + packet.coordinate_frame = coordinate_frame; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 19); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_LOCAL_POSITION_SETPOINT; + return mavlink_finalize_message(msg, system_id, component_id, 19, 214); +} + +/** + * @brief Pack a set_local_position_setpoint message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param coordinate_frame Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU + * @param x x position + * @param y y position + * @param z z position + * @param yaw Desired yaw angle + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_local_position_setpoint_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,uint8_t coordinate_frame,float x,float y,float z,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[19]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + _mav_put_uint8_t(buf, 18, coordinate_frame); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 19); +#else + mavlink_set_local_position_setpoint_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + packet.target_system = target_system; + packet.target_component = target_component; + packet.coordinate_frame = coordinate_frame; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 19); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_LOCAL_POSITION_SETPOINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 19, 214); +} + +/** + * @brief Encode a set_local_position_setpoint struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_local_position_setpoint C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_local_position_setpoint_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_local_position_setpoint_t* set_local_position_setpoint) +{ + return mavlink_msg_set_local_position_setpoint_pack(system_id, component_id, msg, set_local_position_setpoint->target_system, set_local_position_setpoint->target_component, set_local_position_setpoint->coordinate_frame, set_local_position_setpoint->x, set_local_position_setpoint->y, set_local_position_setpoint->z, set_local_position_setpoint->yaw); +} + +/** + * @brief Send a set_local_position_setpoint message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param coordinate_frame Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU + * @param x x position + * @param y y position + * @param z z position + * @param yaw Desired yaw angle + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_local_position_setpoint_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, uint8_t coordinate_frame, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[19]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + _mav_put_uint8_t(buf, 18, coordinate_frame); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_LOCAL_POSITION_SETPOINT, buf, 19, 214); +#else + mavlink_set_local_position_setpoint_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + packet.target_system = target_system; + packet.target_component = target_component; + packet.coordinate_frame = coordinate_frame; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_LOCAL_POSITION_SETPOINT, (const char *)&packet, 19, 214); +#endif +} + +#endif + +// MESSAGE SET_LOCAL_POSITION_SETPOINT UNPACKING + + +/** + * @brief Get field target_system from set_local_position_setpoint message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_set_local_position_setpoint_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 16); +} + +/** + * @brief Get field target_component from set_local_position_setpoint message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_set_local_position_setpoint_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 17); +} + +/** + * @brief Get field coordinate_frame from set_local_position_setpoint message + * + * @return Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU + */ +static inline uint8_t mavlink_msg_set_local_position_setpoint_get_coordinate_frame(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 18); +} + +/** + * @brief Get field x from set_local_position_setpoint message + * + * @return x position + */ +static inline float mavlink_msg_set_local_position_setpoint_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field y from set_local_position_setpoint message + * + * @return y position + */ +static inline float mavlink_msg_set_local_position_setpoint_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field z from set_local_position_setpoint message + * + * @return z position + */ +static inline float mavlink_msg_set_local_position_setpoint_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field yaw from set_local_position_setpoint message + * + * @return Desired yaw angle + */ +static inline float mavlink_msg_set_local_position_setpoint_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Decode a set_local_position_setpoint message into a struct + * + * @param msg The message to decode + * @param set_local_position_setpoint C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_local_position_setpoint_decode(const mavlink_message_t* msg, mavlink_set_local_position_setpoint_t* set_local_position_setpoint) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_local_position_setpoint->x = mavlink_msg_set_local_position_setpoint_get_x(msg); + set_local_position_setpoint->y = mavlink_msg_set_local_position_setpoint_get_y(msg); + set_local_position_setpoint->z = mavlink_msg_set_local_position_setpoint_get_z(msg); + set_local_position_setpoint->yaw = mavlink_msg_set_local_position_setpoint_get_yaw(msg); + set_local_position_setpoint->target_system = mavlink_msg_set_local_position_setpoint_get_target_system(msg); + set_local_position_setpoint->target_component = mavlink_msg_set_local_position_setpoint_get_target_component(msg); + set_local_position_setpoint->coordinate_frame = mavlink_msg_set_local_position_setpoint_get_coordinate_frame(msg); +#else + memcpy(set_local_position_setpoint, _MAV_PAYLOAD(msg), 19); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_mode.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_mode.h new file mode 100644 index 0000000000..fec21ab137 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_mode.h @@ -0,0 +1,188 @@ +// MESSAGE SET_MODE PACKING + +#define MAVLINK_MSG_ID_SET_MODE 11 + +typedef struct __mavlink_set_mode_t +{ + uint32_t custom_mode; ///< The new autopilot-specific mode. This field can be ignored by an autopilot. + uint8_t target_system; ///< The system setting the mode + uint8_t base_mode; ///< The new base mode +} mavlink_set_mode_t; + +#define MAVLINK_MSG_ID_SET_MODE_LEN 6 +#define MAVLINK_MSG_ID_11_LEN 6 + + + +#define MAVLINK_MESSAGE_INFO_SET_MODE { \ + "SET_MODE", \ + 3, \ + { { "custom_mode", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_set_mode_t, custom_mode) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_set_mode_t, target_system) }, \ + { "base_mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_set_mode_t, base_mode) }, \ + } \ +} + + +/** + * @brief Pack a set_mode message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system The system setting the mode + * @param base_mode The new base mode + * @param custom_mode The new autopilot-specific mode. This field can be ignored by an autopilot. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_mode_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t base_mode, uint32_t custom_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint32_t(buf, 0, custom_mode); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, base_mode); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_set_mode_t packet; + packet.custom_mode = custom_mode; + packet.target_system = target_system; + packet.base_mode = base_mode; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_MODE; + return mavlink_finalize_message(msg, system_id, component_id, 6, 89); +} + +/** + * @brief Pack a set_mode message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system The system setting the mode + * @param base_mode The new base mode + * @param custom_mode The new autopilot-specific mode. This field can be ignored by an autopilot. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_mode_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t base_mode,uint32_t custom_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint32_t(buf, 0, custom_mode); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, base_mode); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_set_mode_t packet; + packet.custom_mode = custom_mode; + packet.target_system = target_system; + packet.base_mode = base_mode; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_MODE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 6, 89); +} + +/** + * @brief Encode a set_mode struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_mode C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_mode_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_mode_t* set_mode) +{ + return mavlink_msg_set_mode_pack(system_id, component_id, msg, set_mode->target_system, set_mode->base_mode, set_mode->custom_mode); +} + +/** + * @brief Send a set_mode message + * @param chan MAVLink channel to send the message + * + * @param target_system The system setting the mode + * @param base_mode The new base mode + * @param custom_mode The new autopilot-specific mode. This field can be ignored by an autopilot. + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_mode_send(mavlink_channel_t chan, uint8_t target_system, uint8_t base_mode, uint32_t custom_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint32_t(buf, 0, custom_mode); + _mav_put_uint8_t(buf, 4, target_system); + _mav_put_uint8_t(buf, 5, base_mode); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_MODE, buf, 6, 89); +#else + mavlink_set_mode_t packet; + packet.custom_mode = custom_mode; + packet.target_system = target_system; + packet.base_mode = base_mode; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_MODE, (const char *)&packet, 6, 89); +#endif +} + +#endif + +// MESSAGE SET_MODE UNPACKING + + +/** + * @brief Get field target_system from set_mode message + * + * @return The system setting the mode + */ +static inline uint8_t mavlink_msg_set_mode_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field base_mode from set_mode message + * + * @return The new base mode + */ +static inline uint8_t mavlink_msg_set_mode_get_base_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field custom_mode from set_mode message + * + * @return The new autopilot-specific mode. This field can be ignored by an autopilot. + */ +static inline uint32_t mavlink_msg_set_mode_get_custom_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Decode a set_mode message into a struct + * + * @param msg The message to decode + * @param set_mode C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_mode_decode(const mavlink_message_t* msg, mavlink_set_mode_t* set_mode) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_mode->custom_mode = mavlink_msg_set_mode_get_custom_mode(msg); + set_mode->target_system = mavlink_msg_set_mode_get_target_system(msg); + set_mode->base_mode = mavlink_msg_set_mode_get_base_mode(msg); +#else + memcpy(set_mode, _MAV_PAYLOAD(msg), 6); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_quad_motors_setpoint.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_quad_motors_setpoint.h new file mode 100644 index 0000000000..40ff8998ec --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_quad_motors_setpoint.h @@ -0,0 +1,232 @@ +// MESSAGE SET_QUAD_MOTORS_SETPOINT PACKING + +#define MAVLINK_MSG_ID_SET_QUAD_MOTORS_SETPOINT 60 + +typedef struct __mavlink_set_quad_motors_setpoint_t +{ + uint16_t motor_front_nw; ///< Front motor in + configuration, front left motor in x configuration + uint16_t motor_right_ne; ///< Right motor in + configuration, front right motor in x configuration + uint16_t motor_back_se; ///< Back motor in + configuration, back right motor in x configuration + uint16_t motor_left_sw; ///< Left motor in + configuration, back left motor in x configuration + uint8_t target_system; ///< System ID of the system that should set these motor commands +} mavlink_set_quad_motors_setpoint_t; + +#define MAVLINK_MSG_ID_SET_QUAD_MOTORS_SETPOINT_LEN 9 +#define MAVLINK_MSG_ID_60_LEN 9 + + + +#define MAVLINK_MESSAGE_INFO_SET_QUAD_MOTORS_SETPOINT { \ + "SET_QUAD_MOTORS_SETPOINT", \ + 5, \ + { { "motor_front_nw", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_set_quad_motors_setpoint_t, motor_front_nw) }, \ + { "motor_right_ne", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_set_quad_motors_setpoint_t, motor_right_ne) }, \ + { "motor_back_se", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_set_quad_motors_setpoint_t, motor_back_se) }, \ + { "motor_left_sw", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_set_quad_motors_setpoint_t, motor_left_sw) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_set_quad_motors_setpoint_t, target_system) }, \ + } \ +} + + +/** + * @brief Pack a set_quad_motors_setpoint message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID of the system that should set these motor commands + * @param motor_front_nw Front motor in + configuration, front left motor in x configuration + * @param motor_right_ne Right motor in + configuration, front right motor in x configuration + * @param motor_back_se Back motor in + configuration, back right motor in x configuration + * @param motor_left_sw Left motor in + configuration, back left motor in x configuration + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_quad_motors_setpoint_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint16_t motor_front_nw, uint16_t motor_right_ne, uint16_t motor_back_se, uint16_t motor_left_sw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint16_t(buf, 0, motor_front_nw); + _mav_put_uint16_t(buf, 2, motor_right_ne); + _mav_put_uint16_t(buf, 4, motor_back_se); + _mav_put_uint16_t(buf, 6, motor_left_sw); + _mav_put_uint8_t(buf, 8, target_system); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 9); +#else + mavlink_set_quad_motors_setpoint_t packet; + packet.motor_front_nw = motor_front_nw; + packet.motor_right_ne = motor_right_ne; + packet.motor_back_se = motor_back_se; + packet.motor_left_sw = motor_left_sw; + packet.target_system = target_system; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 9); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_QUAD_MOTORS_SETPOINT; + return mavlink_finalize_message(msg, system_id, component_id, 9, 30); +} + +/** + * @brief Pack a set_quad_motors_setpoint message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID of the system that should set these motor commands + * @param motor_front_nw Front motor in + configuration, front left motor in x configuration + * @param motor_right_ne Right motor in + configuration, front right motor in x configuration + * @param motor_back_se Back motor in + configuration, back right motor in x configuration + * @param motor_left_sw Left motor in + configuration, back left motor in x configuration + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_quad_motors_setpoint_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint16_t motor_front_nw,uint16_t motor_right_ne,uint16_t motor_back_se,uint16_t motor_left_sw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint16_t(buf, 0, motor_front_nw); + _mav_put_uint16_t(buf, 2, motor_right_ne); + _mav_put_uint16_t(buf, 4, motor_back_se); + _mav_put_uint16_t(buf, 6, motor_left_sw); + _mav_put_uint8_t(buf, 8, target_system); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 9); +#else + mavlink_set_quad_motors_setpoint_t packet; + packet.motor_front_nw = motor_front_nw; + packet.motor_right_ne = motor_right_ne; + packet.motor_back_se = motor_back_se; + packet.motor_left_sw = motor_left_sw; + packet.target_system = target_system; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 9); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_QUAD_MOTORS_SETPOINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 9, 30); +} + +/** + * @brief Encode a set_quad_motors_setpoint struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_quad_motors_setpoint C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_quad_motors_setpoint_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_quad_motors_setpoint_t* set_quad_motors_setpoint) +{ + return mavlink_msg_set_quad_motors_setpoint_pack(system_id, component_id, msg, set_quad_motors_setpoint->target_system, set_quad_motors_setpoint->motor_front_nw, set_quad_motors_setpoint->motor_right_ne, set_quad_motors_setpoint->motor_back_se, set_quad_motors_setpoint->motor_left_sw); +} + +/** + * @brief Send a set_quad_motors_setpoint message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID of the system that should set these motor commands + * @param motor_front_nw Front motor in + configuration, front left motor in x configuration + * @param motor_right_ne Right motor in + configuration, front right motor in x configuration + * @param motor_back_se Back motor in + configuration, back right motor in x configuration + * @param motor_left_sw Left motor in + configuration, back left motor in x configuration + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_quad_motors_setpoint_send(mavlink_channel_t chan, uint8_t target_system, uint16_t motor_front_nw, uint16_t motor_right_ne, uint16_t motor_back_se, uint16_t motor_left_sw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint16_t(buf, 0, motor_front_nw); + _mav_put_uint16_t(buf, 2, motor_right_ne); + _mav_put_uint16_t(buf, 4, motor_back_se); + _mav_put_uint16_t(buf, 6, motor_left_sw); + _mav_put_uint8_t(buf, 8, target_system); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_QUAD_MOTORS_SETPOINT, buf, 9, 30); +#else + mavlink_set_quad_motors_setpoint_t packet; + packet.motor_front_nw = motor_front_nw; + packet.motor_right_ne = motor_right_ne; + packet.motor_back_se = motor_back_se; + packet.motor_left_sw = motor_left_sw; + packet.target_system = target_system; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_QUAD_MOTORS_SETPOINT, (const char *)&packet, 9, 30); +#endif +} + +#endif + +// MESSAGE SET_QUAD_MOTORS_SETPOINT UNPACKING + + +/** + * @brief Get field target_system from set_quad_motors_setpoint message + * + * @return System ID of the system that should set these motor commands + */ +static inline uint8_t mavlink_msg_set_quad_motors_setpoint_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Get field motor_front_nw from set_quad_motors_setpoint message + * + * @return Front motor in + configuration, front left motor in x configuration + */ +static inline uint16_t mavlink_msg_set_quad_motors_setpoint_get_motor_front_nw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field motor_right_ne from set_quad_motors_setpoint message + * + * @return Right motor in + configuration, front right motor in x configuration + */ +static inline uint16_t mavlink_msg_set_quad_motors_setpoint_get_motor_right_ne(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Get field motor_back_se from set_quad_motors_setpoint message + * + * @return Back motor in + configuration, back right motor in x configuration + */ +static inline uint16_t mavlink_msg_set_quad_motors_setpoint_get_motor_back_se(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field motor_left_sw from set_quad_motors_setpoint message + * + * @return Left motor in + configuration, back left motor in x configuration + */ +static inline uint16_t mavlink_msg_set_quad_motors_setpoint_get_motor_left_sw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Decode a set_quad_motors_setpoint message into a struct + * + * @param msg The message to decode + * @param set_quad_motors_setpoint C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_quad_motors_setpoint_decode(const mavlink_message_t* msg, mavlink_set_quad_motors_setpoint_t* set_quad_motors_setpoint) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_quad_motors_setpoint->motor_front_nw = mavlink_msg_set_quad_motors_setpoint_get_motor_front_nw(msg); + set_quad_motors_setpoint->motor_right_ne = mavlink_msg_set_quad_motors_setpoint_get_motor_right_ne(msg); + set_quad_motors_setpoint->motor_back_se = mavlink_msg_set_quad_motors_setpoint_get_motor_back_se(msg); + set_quad_motors_setpoint->motor_left_sw = mavlink_msg_set_quad_motors_setpoint_get_motor_left_sw(msg); + set_quad_motors_setpoint->target_system = mavlink_msg_set_quad_motors_setpoint_get_target_system(msg); +#else + memcpy(set_quad_motors_setpoint, _MAV_PAYLOAD(msg), 9); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust.h new file mode 100644 index 0000000000..c3ea8de408 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust.h @@ -0,0 +1,236 @@ +// MESSAGE SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST PACKING + +#define MAVLINK_MSG_ID_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST 61 + +typedef struct __mavlink_set_quad_swarm_roll_pitch_yaw_thrust_t +{ + int16_t roll[6]; ///< Desired roll angle in radians, scaled to int16 for 6 quadrotors: 0..5 + int16_t pitch[6]; ///< Desired pitch angle in radians, scaled to int16 for 6 quadrotors: 0..5 + int16_t yaw[6]; ///< Desired yaw angle in radians, scaled to int16 for 6 quadrotors: 0..5 + uint16_t thrust[6]; ///< Collective thrust, scaled to uint16 for 6 quadrotors: 0..5 + uint8_t target_systems[6]; ///< System IDs for 6 quadrotors: 0..5, the ID's are the MAVLink IDs +} mavlink_set_quad_swarm_roll_pitch_yaw_thrust_t; + +#define MAVLINK_MSG_ID_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST_LEN 54 +#define MAVLINK_MSG_ID_61_LEN 54 + +#define MAVLINK_MSG_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST_FIELD_ROLL_LEN 6 +#define MAVLINK_MSG_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST_FIELD_PITCH_LEN 6 +#define MAVLINK_MSG_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST_FIELD_YAW_LEN 6 +#define MAVLINK_MSG_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST_FIELD_THRUST_LEN 6 +#define MAVLINK_MSG_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST_FIELD_TARGET_SYSTEMS_LEN 6 + +#define MAVLINK_MESSAGE_INFO_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST { \ + "SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST", \ + 5, \ + { { "roll", NULL, MAVLINK_TYPE_INT16_T, 6, 0, offsetof(mavlink_set_quad_swarm_roll_pitch_yaw_thrust_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_INT16_T, 6, 12, offsetof(mavlink_set_quad_swarm_roll_pitch_yaw_thrust_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_INT16_T, 6, 24, offsetof(mavlink_set_quad_swarm_roll_pitch_yaw_thrust_t, yaw) }, \ + { "thrust", NULL, MAVLINK_TYPE_UINT16_T, 6, 36, offsetof(mavlink_set_quad_swarm_roll_pitch_yaw_thrust_t, thrust) }, \ + { "target_systems", NULL, MAVLINK_TYPE_UINT8_T, 6, 48, offsetof(mavlink_set_quad_swarm_roll_pitch_yaw_thrust_t, target_systems) }, \ + } \ +} + + +/** + * @brief Pack a set_quad_swarm_roll_pitch_yaw_thrust message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_systems System IDs for 6 quadrotors: 0..5, the ID's are the MAVLink IDs + * @param roll Desired roll angle in radians, scaled to int16 for 6 quadrotors: 0..5 + * @param pitch Desired pitch angle in radians, scaled to int16 for 6 quadrotors: 0..5 + * @param yaw Desired yaw angle in radians, scaled to int16 for 6 quadrotors: 0..5 + * @param thrust Collective thrust, scaled to uint16 for 6 quadrotors: 0..5 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const uint8_t *target_systems, const int16_t *roll, const int16_t *pitch, const int16_t *yaw, const uint16_t *thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[54]; + + _mav_put_int16_t_array(buf, 0, roll, 6); + _mav_put_int16_t_array(buf, 12, pitch, 6); + _mav_put_int16_t_array(buf, 24, yaw, 6); + _mav_put_uint16_t_array(buf, 36, thrust, 6); + _mav_put_uint8_t_array(buf, 48, target_systems, 6); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 54); +#else + mavlink_set_quad_swarm_roll_pitch_yaw_thrust_t packet; + + mav_array_memcpy(packet.roll, roll, sizeof(int16_t)*6); + mav_array_memcpy(packet.pitch, pitch, sizeof(int16_t)*6); + mav_array_memcpy(packet.yaw, yaw, sizeof(int16_t)*6); + mav_array_memcpy(packet.thrust, thrust, sizeof(uint16_t)*6); + mav_array_memcpy(packet.target_systems, target_systems, sizeof(uint8_t)*6); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 54); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST; + return mavlink_finalize_message(msg, system_id, component_id, 54, 200); +} + +/** + * @brief Pack a set_quad_swarm_roll_pitch_yaw_thrust message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_systems System IDs for 6 quadrotors: 0..5, the ID's are the MAVLink IDs + * @param roll Desired roll angle in radians, scaled to int16 for 6 quadrotors: 0..5 + * @param pitch Desired pitch angle in radians, scaled to int16 for 6 quadrotors: 0..5 + * @param yaw Desired yaw angle in radians, scaled to int16 for 6 quadrotors: 0..5 + * @param thrust Collective thrust, scaled to uint16 for 6 quadrotors: 0..5 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const uint8_t *target_systems,const int16_t *roll,const int16_t *pitch,const int16_t *yaw,const uint16_t *thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[54]; + + _mav_put_int16_t_array(buf, 0, roll, 6); + _mav_put_int16_t_array(buf, 12, pitch, 6); + _mav_put_int16_t_array(buf, 24, yaw, 6); + _mav_put_uint16_t_array(buf, 36, thrust, 6); + _mav_put_uint8_t_array(buf, 48, target_systems, 6); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 54); +#else + mavlink_set_quad_swarm_roll_pitch_yaw_thrust_t packet; + + mav_array_memcpy(packet.roll, roll, sizeof(int16_t)*6); + mav_array_memcpy(packet.pitch, pitch, sizeof(int16_t)*6); + mav_array_memcpy(packet.yaw, yaw, sizeof(int16_t)*6); + mav_array_memcpy(packet.thrust, thrust, sizeof(uint16_t)*6); + mav_array_memcpy(packet.target_systems, target_systems, sizeof(uint8_t)*6); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 54); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 54, 200); +} + +/** + * @brief Encode a set_quad_swarm_roll_pitch_yaw_thrust struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_quad_swarm_roll_pitch_yaw_thrust C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_quad_swarm_roll_pitch_yaw_thrust_t* set_quad_swarm_roll_pitch_yaw_thrust) +{ + return mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_pack(system_id, component_id, msg, set_quad_swarm_roll_pitch_yaw_thrust->target_systems, set_quad_swarm_roll_pitch_yaw_thrust->roll, set_quad_swarm_roll_pitch_yaw_thrust->pitch, set_quad_swarm_roll_pitch_yaw_thrust->yaw, set_quad_swarm_roll_pitch_yaw_thrust->thrust); +} + +/** + * @brief Send a set_quad_swarm_roll_pitch_yaw_thrust message + * @param chan MAVLink channel to send the message + * + * @param target_systems System IDs for 6 quadrotors: 0..5, the ID's are the MAVLink IDs + * @param roll Desired roll angle in radians, scaled to int16 for 6 quadrotors: 0..5 + * @param pitch Desired pitch angle in radians, scaled to int16 for 6 quadrotors: 0..5 + * @param yaw Desired yaw angle in radians, scaled to int16 for 6 quadrotors: 0..5 + * @param thrust Collective thrust, scaled to uint16 for 6 quadrotors: 0..5 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_send(mavlink_channel_t chan, const uint8_t *target_systems, const int16_t *roll, const int16_t *pitch, const int16_t *yaw, const uint16_t *thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[54]; + + _mav_put_int16_t_array(buf, 0, roll, 6); + _mav_put_int16_t_array(buf, 12, pitch, 6); + _mav_put_int16_t_array(buf, 24, yaw, 6); + _mav_put_uint16_t_array(buf, 36, thrust, 6); + _mav_put_uint8_t_array(buf, 48, target_systems, 6); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST, buf, 54, 200); +#else + mavlink_set_quad_swarm_roll_pitch_yaw_thrust_t packet; + + mav_array_memcpy(packet.roll, roll, sizeof(int16_t)*6); + mav_array_memcpy(packet.pitch, pitch, sizeof(int16_t)*6); + mav_array_memcpy(packet.yaw, yaw, sizeof(int16_t)*6); + mav_array_memcpy(packet.thrust, thrust, sizeof(uint16_t)*6); + mav_array_memcpy(packet.target_systems, target_systems, sizeof(uint8_t)*6); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST, (const char *)&packet, 54, 200); +#endif +} + +#endif + +// MESSAGE SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST UNPACKING + + +/** + * @brief Get field target_systems from set_quad_swarm_roll_pitch_yaw_thrust message + * + * @return System IDs for 6 quadrotors: 0..5, the ID's are the MAVLink IDs + */ +static inline uint16_t mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_get_target_systems(const mavlink_message_t* msg, uint8_t *target_systems) +{ + return _MAV_RETURN_uint8_t_array(msg, target_systems, 6, 48); +} + +/** + * @brief Get field roll from set_quad_swarm_roll_pitch_yaw_thrust message + * + * @return Desired roll angle in radians, scaled to int16 for 6 quadrotors: 0..5 + */ +static inline uint16_t mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_get_roll(const mavlink_message_t* msg, int16_t *roll) +{ + return _MAV_RETURN_int16_t_array(msg, roll, 6, 0); +} + +/** + * @brief Get field pitch from set_quad_swarm_roll_pitch_yaw_thrust message + * + * @return Desired pitch angle in radians, scaled to int16 for 6 quadrotors: 0..5 + */ +static inline uint16_t mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_get_pitch(const mavlink_message_t* msg, int16_t *pitch) +{ + return _MAV_RETURN_int16_t_array(msg, pitch, 6, 12); +} + +/** + * @brief Get field yaw from set_quad_swarm_roll_pitch_yaw_thrust message + * + * @return Desired yaw angle in radians, scaled to int16 for 6 quadrotors: 0..5 + */ +static inline uint16_t mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_get_yaw(const mavlink_message_t* msg, int16_t *yaw) +{ + return _MAV_RETURN_int16_t_array(msg, yaw, 6, 24); +} + +/** + * @brief Get field thrust from set_quad_swarm_roll_pitch_yaw_thrust message + * + * @return Collective thrust, scaled to uint16 for 6 quadrotors: 0..5 + */ +static inline uint16_t mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_get_thrust(const mavlink_message_t* msg, uint16_t *thrust) +{ + return _MAV_RETURN_uint16_t_array(msg, thrust, 6, 36); +} + +/** + * @brief Decode a set_quad_swarm_roll_pitch_yaw_thrust message into a struct + * + * @param msg The message to decode + * @param set_quad_swarm_roll_pitch_yaw_thrust C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_decode(const mavlink_message_t* msg, mavlink_set_quad_swarm_roll_pitch_yaw_thrust_t* set_quad_swarm_roll_pitch_yaw_thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_get_roll(msg, set_quad_swarm_roll_pitch_yaw_thrust->roll); + mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_get_pitch(msg, set_quad_swarm_roll_pitch_yaw_thrust->pitch); + mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_get_yaw(msg, set_quad_swarm_roll_pitch_yaw_thrust->yaw); + mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_get_thrust(msg, set_quad_swarm_roll_pitch_yaw_thrust->thrust); + mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_get_target_systems(msg, set_quad_swarm_roll_pitch_yaw_thrust->target_systems); +#else + memcpy(set_quad_swarm_roll_pitch_yaw_thrust, _MAV_PAYLOAD(msg), 54); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_roll_pitch_yaw_speed_thrust.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_roll_pitch_yaw_speed_thrust.h new file mode 100644 index 0000000000..b79a7e9f2f --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_roll_pitch_yaw_speed_thrust.h @@ -0,0 +1,254 @@ +// MESSAGE SET_ROLL_PITCH_YAW_SPEED_THRUST PACKING + +#define MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST 57 + +typedef struct __mavlink_set_roll_pitch_yaw_speed_thrust_t +{ + float roll_speed; ///< Desired roll angular speed in rad/s + float pitch_speed; ///< Desired pitch angular speed in rad/s + float yaw_speed; ///< Desired yaw angular speed in rad/s + float thrust; ///< Collective thrust, normalized to 0 .. 1 + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_set_roll_pitch_yaw_speed_thrust_t; + +#define MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST_LEN 18 +#define MAVLINK_MSG_ID_57_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST { \ + "SET_ROLL_PITCH_YAW_SPEED_THRUST", \ + 6, \ + { { "roll_speed", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_set_roll_pitch_yaw_speed_thrust_t, roll_speed) }, \ + { "pitch_speed", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_set_roll_pitch_yaw_speed_thrust_t, pitch_speed) }, \ + { "yaw_speed", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_set_roll_pitch_yaw_speed_thrust_t, yaw_speed) }, \ + { "thrust", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_set_roll_pitch_yaw_speed_thrust_t, thrust) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 16, offsetof(mavlink_set_roll_pitch_yaw_speed_thrust_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 17, offsetof(mavlink_set_roll_pitch_yaw_speed_thrust_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a set_roll_pitch_yaw_speed_thrust message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param roll_speed Desired roll angular speed in rad/s + * @param pitch_speed Desired pitch angular speed in rad/s + * @param yaw_speed Desired yaw angular speed in rad/s + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_roll_pitch_yaw_speed_thrust_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, float roll_speed, float pitch_speed, float yaw_speed, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, roll_speed); + _mav_put_float(buf, 4, pitch_speed); + _mav_put_float(buf, 8, yaw_speed); + _mav_put_float(buf, 12, thrust); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_set_roll_pitch_yaw_speed_thrust_t packet; + packet.roll_speed = roll_speed; + packet.pitch_speed = pitch_speed; + packet.yaw_speed = yaw_speed; + packet.thrust = thrust; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST; + return mavlink_finalize_message(msg, system_id, component_id, 18, 24); +} + +/** + * @brief Pack a set_roll_pitch_yaw_speed_thrust message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param roll_speed Desired roll angular speed in rad/s + * @param pitch_speed Desired pitch angular speed in rad/s + * @param yaw_speed Desired yaw angular speed in rad/s + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_roll_pitch_yaw_speed_thrust_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,float roll_speed,float pitch_speed,float yaw_speed,float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, roll_speed); + _mav_put_float(buf, 4, pitch_speed); + _mav_put_float(buf, 8, yaw_speed); + _mav_put_float(buf, 12, thrust); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_set_roll_pitch_yaw_speed_thrust_t packet; + packet.roll_speed = roll_speed; + packet.pitch_speed = pitch_speed; + packet.yaw_speed = yaw_speed; + packet.thrust = thrust; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18, 24); +} + +/** + * @brief Encode a set_roll_pitch_yaw_speed_thrust struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_roll_pitch_yaw_speed_thrust C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_roll_pitch_yaw_speed_thrust_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_roll_pitch_yaw_speed_thrust_t* set_roll_pitch_yaw_speed_thrust) +{ + return mavlink_msg_set_roll_pitch_yaw_speed_thrust_pack(system_id, component_id, msg, set_roll_pitch_yaw_speed_thrust->target_system, set_roll_pitch_yaw_speed_thrust->target_component, set_roll_pitch_yaw_speed_thrust->roll_speed, set_roll_pitch_yaw_speed_thrust->pitch_speed, set_roll_pitch_yaw_speed_thrust->yaw_speed, set_roll_pitch_yaw_speed_thrust->thrust); +} + +/** + * @brief Send a set_roll_pitch_yaw_speed_thrust message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param roll_speed Desired roll angular speed in rad/s + * @param pitch_speed Desired pitch angular speed in rad/s + * @param yaw_speed Desired yaw angular speed in rad/s + * @param thrust Collective thrust, normalized to 0 .. 1 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_roll_pitch_yaw_speed_thrust_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, float roll_speed, float pitch_speed, float yaw_speed, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, roll_speed); + _mav_put_float(buf, 4, pitch_speed); + _mav_put_float(buf, 8, yaw_speed); + _mav_put_float(buf, 12, thrust); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST, buf, 18, 24); +#else + mavlink_set_roll_pitch_yaw_speed_thrust_t packet; + packet.roll_speed = roll_speed; + packet.pitch_speed = pitch_speed; + packet.yaw_speed = yaw_speed; + packet.thrust = thrust; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST, (const char *)&packet, 18, 24); +#endif +} + +#endif + +// MESSAGE SET_ROLL_PITCH_YAW_SPEED_THRUST UNPACKING + + +/** + * @brief Get field target_system from set_roll_pitch_yaw_speed_thrust message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 16); +} + +/** + * @brief Get field target_component from set_roll_pitch_yaw_speed_thrust message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 17); +} + +/** + * @brief Get field roll_speed from set_roll_pitch_yaw_speed_thrust message + * + * @return Desired roll angular speed in rad/s + */ +static inline float mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_roll_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field pitch_speed from set_roll_pitch_yaw_speed_thrust message + * + * @return Desired pitch angular speed in rad/s + */ +static inline float mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_pitch_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field yaw_speed from set_roll_pitch_yaw_speed_thrust message + * + * @return Desired yaw angular speed in rad/s + */ +static inline float mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_yaw_speed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field thrust from set_roll_pitch_yaw_speed_thrust message + * + * @return Collective thrust, normalized to 0 .. 1 + */ +static inline float mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_thrust(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Decode a set_roll_pitch_yaw_speed_thrust message into a struct + * + * @param msg The message to decode + * @param set_roll_pitch_yaw_speed_thrust C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_roll_pitch_yaw_speed_thrust_decode(const mavlink_message_t* msg, mavlink_set_roll_pitch_yaw_speed_thrust_t* set_roll_pitch_yaw_speed_thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_roll_pitch_yaw_speed_thrust->roll_speed = mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_roll_speed(msg); + set_roll_pitch_yaw_speed_thrust->pitch_speed = mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_pitch_speed(msg); + set_roll_pitch_yaw_speed_thrust->yaw_speed = mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_yaw_speed(msg); + set_roll_pitch_yaw_speed_thrust->thrust = mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_thrust(msg); + set_roll_pitch_yaw_speed_thrust->target_system = mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_target_system(msg); + set_roll_pitch_yaw_speed_thrust->target_component = mavlink_msg_set_roll_pitch_yaw_speed_thrust_get_target_component(msg); +#else + memcpy(set_roll_pitch_yaw_speed_thrust, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_roll_pitch_yaw_thrust.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_roll_pitch_yaw_thrust.h new file mode 100644 index 0000000000..8cd573a26c --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_set_roll_pitch_yaw_thrust.h @@ -0,0 +1,254 @@ +// MESSAGE SET_ROLL_PITCH_YAW_THRUST PACKING + +#define MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST 56 + +typedef struct __mavlink_set_roll_pitch_yaw_thrust_t +{ + float roll; ///< Desired roll angle in radians + float pitch; ///< Desired pitch angle in radians + float yaw; ///< Desired yaw angle in radians + float thrust; ///< Collective thrust, normalized to 0 .. 1 + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_set_roll_pitch_yaw_thrust_t; + +#define MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST_LEN 18 +#define MAVLINK_MSG_ID_56_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST { \ + "SET_ROLL_PITCH_YAW_THRUST", \ + 6, \ + { { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_set_roll_pitch_yaw_thrust_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_set_roll_pitch_yaw_thrust_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_set_roll_pitch_yaw_thrust_t, yaw) }, \ + { "thrust", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_set_roll_pitch_yaw_thrust_t, thrust) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 16, offsetof(mavlink_set_roll_pitch_yaw_thrust_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 17, offsetof(mavlink_set_roll_pitch_yaw_thrust_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a set_roll_pitch_yaw_thrust message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param roll Desired roll angle in radians + * @param pitch Desired pitch angle in radians + * @param yaw Desired yaw angle in radians + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_roll_pitch_yaw_thrust_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, float roll, float pitch, float yaw, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, thrust); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_set_roll_pitch_yaw_thrust_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST; + return mavlink_finalize_message(msg, system_id, component_id, 18, 100); +} + +/** + * @brief Pack a set_roll_pitch_yaw_thrust message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param roll Desired roll angle in radians + * @param pitch Desired pitch angle in radians + * @param yaw Desired yaw angle in radians + * @param thrust Collective thrust, normalized to 0 .. 1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_roll_pitch_yaw_thrust_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,float roll,float pitch,float yaw,float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, thrust); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_set_roll_pitch_yaw_thrust_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18, 100); +} + +/** + * @brief Encode a set_roll_pitch_yaw_thrust struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_roll_pitch_yaw_thrust C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_roll_pitch_yaw_thrust_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_roll_pitch_yaw_thrust_t* set_roll_pitch_yaw_thrust) +{ + return mavlink_msg_set_roll_pitch_yaw_thrust_pack(system_id, component_id, msg, set_roll_pitch_yaw_thrust->target_system, set_roll_pitch_yaw_thrust->target_component, set_roll_pitch_yaw_thrust->roll, set_roll_pitch_yaw_thrust->pitch, set_roll_pitch_yaw_thrust->yaw, set_roll_pitch_yaw_thrust->thrust); +} + +/** + * @brief Send a set_roll_pitch_yaw_thrust message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param roll Desired roll angle in radians + * @param pitch Desired pitch angle in radians + * @param yaw Desired yaw angle in radians + * @param thrust Collective thrust, normalized to 0 .. 1 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_roll_pitch_yaw_thrust_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, float roll, float pitch, float yaw, float thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, thrust); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST, buf, 18, 100); +#else + mavlink_set_roll_pitch_yaw_thrust_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST, (const char *)&packet, 18, 100); +#endif +} + +#endif + +// MESSAGE SET_ROLL_PITCH_YAW_THRUST UNPACKING + + +/** + * @brief Get field target_system from set_roll_pitch_yaw_thrust message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_set_roll_pitch_yaw_thrust_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 16); +} + +/** + * @brief Get field target_component from set_roll_pitch_yaw_thrust message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_set_roll_pitch_yaw_thrust_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 17); +} + +/** + * @brief Get field roll from set_roll_pitch_yaw_thrust message + * + * @return Desired roll angle in radians + */ +static inline float mavlink_msg_set_roll_pitch_yaw_thrust_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field pitch from set_roll_pitch_yaw_thrust message + * + * @return Desired pitch angle in radians + */ +static inline float mavlink_msg_set_roll_pitch_yaw_thrust_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field yaw from set_roll_pitch_yaw_thrust message + * + * @return Desired yaw angle in radians + */ +static inline float mavlink_msg_set_roll_pitch_yaw_thrust_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field thrust from set_roll_pitch_yaw_thrust message + * + * @return Collective thrust, normalized to 0 .. 1 + */ +static inline float mavlink_msg_set_roll_pitch_yaw_thrust_get_thrust(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Decode a set_roll_pitch_yaw_thrust message into a struct + * + * @param msg The message to decode + * @param set_roll_pitch_yaw_thrust C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_roll_pitch_yaw_thrust_decode(const mavlink_message_t* msg, mavlink_set_roll_pitch_yaw_thrust_t* set_roll_pitch_yaw_thrust) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_roll_pitch_yaw_thrust->roll = mavlink_msg_set_roll_pitch_yaw_thrust_get_roll(msg); + set_roll_pitch_yaw_thrust->pitch = mavlink_msg_set_roll_pitch_yaw_thrust_get_pitch(msg); + set_roll_pitch_yaw_thrust->yaw = mavlink_msg_set_roll_pitch_yaw_thrust_get_yaw(msg); + set_roll_pitch_yaw_thrust->thrust = mavlink_msg_set_roll_pitch_yaw_thrust_get_thrust(msg); + set_roll_pitch_yaw_thrust->target_system = mavlink_msg_set_roll_pitch_yaw_thrust_get_target_system(msg); + set_roll_pitch_yaw_thrust->target_component = mavlink_msg_set_roll_pitch_yaw_thrust_get_target_component(msg); +#else + memcpy(set_roll_pitch_yaw_thrust, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_state_correction.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_state_correction.h new file mode 100644 index 0000000000..0f4f1f5e22 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_state_correction.h @@ -0,0 +1,320 @@ +// MESSAGE STATE_CORRECTION PACKING + +#define MAVLINK_MSG_ID_STATE_CORRECTION 64 + +typedef struct __mavlink_state_correction_t +{ + float xErr; ///< x position error + float yErr; ///< y position error + float zErr; ///< z position error + float rollErr; ///< roll error (radians) + float pitchErr; ///< pitch error (radians) + float yawErr; ///< yaw error (radians) + float vxErr; ///< x velocity + float vyErr; ///< y velocity + float vzErr; ///< z velocity +} mavlink_state_correction_t; + +#define MAVLINK_MSG_ID_STATE_CORRECTION_LEN 36 +#define MAVLINK_MSG_ID_64_LEN 36 + + + +#define MAVLINK_MESSAGE_INFO_STATE_CORRECTION { \ + "STATE_CORRECTION", \ + 9, \ + { { "xErr", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_state_correction_t, xErr) }, \ + { "yErr", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_state_correction_t, yErr) }, \ + { "zErr", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_state_correction_t, zErr) }, \ + { "rollErr", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_state_correction_t, rollErr) }, \ + { "pitchErr", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_state_correction_t, pitchErr) }, \ + { "yawErr", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_state_correction_t, yawErr) }, \ + { "vxErr", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_state_correction_t, vxErr) }, \ + { "vyErr", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_state_correction_t, vyErr) }, \ + { "vzErr", NULL, MAVLINK_TYPE_FLOAT, 0, 32, offsetof(mavlink_state_correction_t, vzErr) }, \ + } \ +} + + +/** + * @brief Pack a state_correction message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param xErr x position error + * @param yErr y position error + * @param zErr z position error + * @param rollErr roll error (radians) + * @param pitchErr pitch error (radians) + * @param yawErr yaw error (radians) + * @param vxErr x velocity + * @param vyErr y velocity + * @param vzErr z velocity + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_state_correction_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float xErr, float yErr, float zErr, float rollErr, float pitchErr, float yawErr, float vxErr, float vyErr, float vzErr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, xErr); + _mav_put_float(buf, 4, yErr); + _mav_put_float(buf, 8, zErr); + _mav_put_float(buf, 12, rollErr); + _mav_put_float(buf, 16, pitchErr); + _mav_put_float(buf, 20, yawErr); + _mav_put_float(buf, 24, vxErr); + _mav_put_float(buf, 28, vyErr); + _mav_put_float(buf, 32, vzErr); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_state_correction_t packet; + packet.xErr = xErr; + packet.yErr = yErr; + packet.zErr = zErr; + packet.rollErr = rollErr; + packet.pitchErr = pitchErr; + packet.yawErr = yawErr; + packet.vxErr = vxErr; + packet.vyErr = vyErr; + packet.vzErr = vzErr; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_STATE_CORRECTION; + return mavlink_finalize_message(msg, system_id, component_id, 36, 130); +} + +/** + * @brief Pack a state_correction message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param xErr x position error + * @param yErr y position error + * @param zErr z position error + * @param rollErr roll error (radians) + * @param pitchErr pitch error (radians) + * @param yawErr yaw error (radians) + * @param vxErr x velocity + * @param vyErr y velocity + * @param vzErr z velocity + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_state_correction_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float xErr,float yErr,float zErr,float rollErr,float pitchErr,float yawErr,float vxErr,float vyErr,float vzErr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, xErr); + _mav_put_float(buf, 4, yErr); + _mav_put_float(buf, 8, zErr); + _mav_put_float(buf, 12, rollErr); + _mav_put_float(buf, 16, pitchErr); + _mav_put_float(buf, 20, yawErr); + _mav_put_float(buf, 24, vxErr); + _mav_put_float(buf, 28, vyErr); + _mav_put_float(buf, 32, vzErr); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 36); +#else + mavlink_state_correction_t packet; + packet.xErr = xErr; + packet.yErr = yErr; + packet.zErr = zErr; + packet.rollErr = rollErr; + packet.pitchErr = pitchErr; + packet.yawErr = yawErr; + packet.vxErr = vxErr; + packet.vyErr = vyErr; + packet.vzErr = vzErr; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_STATE_CORRECTION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 36, 130); +} + +/** + * @brief Encode a state_correction struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param state_correction C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_state_correction_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_state_correction_t* state_correction) +{ + return mavlink_msg_state_correction_pack(system_id, component_id, msg, state_correction->xErr, state_correction->yErr, state_correction->zErr, state_correction->rollErr, state_correction->pitchErr, state_correction->yawErr, state_correction->vxErr, state_correction->vyErr, state_correction->vzErr); +} + +/** + * @brief Send a state_correction message + * @param chan MAVLink channel to send the message + * + * @param xErr x position error + * @param yErr y position error + * @param zErr z position error + * @param rollErr roll error (radians) + * @param pitchErr pitch error (radians) + * @param yawErr yaw error (radians) + * @param vxErr x velocity + * @param vyErr y velocity + * @param vzErr z velocity + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_state_correction_send(mavlink_channel_t chan, float xErr, float yErr, float zErr, float rollErr, float pitchErr, float yawErr, float vxErr, float vyErr, float vzErr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, xErr); + _mav_put_float(buf, 4, yErr); + _mav_put_float(buf, 8, zErr); + _mav_put_float(buf, 12, rollErr); + _mav_put_float(buf, 16, pitchErr); + _mav_put_float(buf, 20, yawErr); + _mav_put_float(buf, 24, vxErr); + _mav_put_float(buf, 28, vyErr); + _mav_put_float(buf, 32, vzErr); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_STATE_CORRECTION, buf, 36, 130); +#else + mavlink_state_correction_t packet; + packet.xErr = xErr; + packet.yErr = yErr; + packet.zErr = zErr; + packet.rollErr = rollErr; + packet.pitchErr = pitchErr; + packet.yawErr = yawErr; + packet.vxErr = vxErr; + packet.vyErr = vyErr; + packet.vzErr = vzErr; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_STATE_CORRECTION, (const char *)&packet, 36, 130); +#endif +} + +#endif + +// MESSAGE STATE_CORRECTION UNPACKING + + +/** + * @brief Get field xErr from state_correction message + * + * @return x position error + */ +static inline float mavlink_msg_state_correction_get_xErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field yErr from state_correction message + * + * @return y position error + */ +static inline float mavlink_msg_state_correction_get_yErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field zErr from state_correction message + * + * @return z position error + */ +static inline float mavlink_msg_state_correction_get_zErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field rollErr from state_correction message + * + * @return roll error (radians) + */ +static inline float mavlink_msg_state_correction_get_rollErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field pitchErr from state_correction message + * + * @return pitch error (radians) + */ +static inline float mavlink_msg_state_correction_get_pitchErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field yawErr from state_correction message + * + * @return yaw error (radians) + */ +static inline float mavlink_msg_state_correction_get_yawErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field vxErr from state_correction message + * + * @return x velocity + */ +static inline float mavlink_msg_state_correction_get_vxErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field vyErr from state_correction message + * + * @return y velocity + */ +static inline float mavlink_msg_state_correction_get_vyErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field vzErr from state_correction message + * + * @return z velocity + */ +static inline float mavlink_msg_state_correction_get_vzErr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 32); +} + +/** + * @brief Decode a state_correction message into a struct + * + * @param msg The message to decode + * @param state_correction C-struct to decode the message contents into + */ +static inline void mavlink_msg_state_correction_decode(const mavlink_message_t* msg, mavlink_state_correction_t* state_correction) +{ +#if MAVLINK_NEED_BYTE_SWAP + state_correction->xErr = mavlink_msg_state_correction_get_xErr(msg); + state_correction->yErr = mavlink_msg_state_correction_get_yErr(msg); + state_correction->zErr = mavlink_msg_state_correction_get_zErr(msg); + state_correction->rollErr = mavlink_msg_state_correction_get_rollErr(msg); + state_correction->pitchErr = mavlink_msg_state_correction_get_pitchErr(msg); + state_correction->yawErr = mavlink_msg_state_correction_get_yawErr(msg); + state_correction->vxErr = mavlink_msg_state_correction_get_vxErr(msg); + state_correction->vyErr = mavlink_msg_state_correction_get_vyErr(msg); + state_correction->vzErr = mavlink_msg_state_correction_get_vzErr(msg); +#else + memcpy(state_correction, _MAV_PAYLOAD(msg), 36); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_statustext.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_statustext.h new file mode 100644 index 0000000000..7c65d448f4 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_statustext.h @@ -0,0 +1,160 @@ +// MESSAGE STATUSTEXT PACKING + +#define MAVLINK_MSG_ID_STATUSTEXT 253 + +typedef struct __mavlink_statustext_t +{ + uint8_t severity; ///< Severity of status. Relies on the definitions within RFC-5424. See enum MAV_SEVERITY. + char text[50]; ///< Status text message, without null termination character +} mavlink_statustext_t; + +#define MAVLINK_MSG_ID_STATUSTEXT_LEN 51 +#define MAVLINK_MSG_ID_253_LEN 51 + +#define MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN 50 + +#define MAVLINK_MESSAGE_INFO_STATUSTEXT { \ + "STATUSTEXT", \ + 2, \ + { { "severity", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_statustext_t, severity) }, \ + { "text", NULL, MAVLINK_TYPE_CHAR, 50, 1, offsetof(mavlink_statustext_t, text) }, \ + } \ +} + + +/** + * @brief Pack a statustext message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param severity Severity of status. Relies on the definitions within RFC-5424. See enum MAV_SEVERITY. + * @param text Status text message, without null termination character + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_statustext_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t severity, const char *text) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[51]; + _mav_put_uint8_t(buf, 0, severity); + _mav_put_char_array(buf, 1, text, 50); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 51); +#else + mavlink_statustext_t packet; + packet.severity = severity; + mav_array_memcpy(packet.text, text, sizeof(char)*50); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 51); +#endif + + msg->msgid = MAVLINK_MSG_ID_STATUSTEXT; + return mavlink_finalize_message(msg, system_id, component_id, 51, 83); +} + +/** + * @brief Pack a statustext message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param severity Severity of status. Relies on the definitions within RFC-5424. See enum MAV_SEVERITY. + * @param text Status text message, without null termination character + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_statustext_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t severity,const char *text) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[51]; + _mav_put_uint8_t(buf, 0, severity); + _mav_put_char_array(buf, 1, text, 50); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 51); +#else + mavlink_statustext_t packet; + packet.severity = severity; + mav_array_memcpy(packet.text, text, sizeof(char)*50); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 51); +#endif + + msg->msgid = MAVLINK_MSG_ID_STATUSTEXT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 51, 83); +} + +/** + * @brief Encode a statustext struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param statustext C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_statustext_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_statustext_t* statustext) +{ + return mavlink_msg_statustext_pack(system_id, component_id, msg, statustext->severity, statustext->text); +} + +/** + * @brief Send a statustext message + * @param chan MAVLink channel to send the message + * + * @param severity Severity of status. Relies on the definitions within RFC-5424. See enum MAV_SEVERITY. + * @param text Status text message, without null termination character + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_statustext_send(mavlink_channel_t chan, uint8_t severity, const char *text) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[51]; + _mav_put_uint8_t(buf, 0, severity); + _mav_put_char_array(buf, 1, text, 50); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_STATUSTEXT, buf, 51, 83); +#else + mavlink_statustext_t packet; + packet.severity = severity; + mav_array_memcpy(packet.text, text, sizeof(char)*50); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_STATUSTEXT, (const char *)&packet, 51, 83); +#endif +} + +#endif + +// MESSAGE STATUSTEXT UNPACKING + + +/** + * @brief Get field severity from statustext message + * + * @return Severity of status. Relies on the definitions within RFC-5424. See enum MAV_SEVERITY. + */ +static inline uint8_t mavlink_msg_statustext_get_severity(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field text from statustext message + * + * @return Status text message, without null termination character + */ +static inline uint16_t mavlink_msg_statustext_get_text(const mavlink_message_t* msg, char *text) +{ + return _MAV_RETURN_char_array(msg, text, 50, 1); +} + +/** + * @brief Decode a statustext message into a struct + * + * @param msg The message to decode + * @param statustext C-struct to decode the message contents into + */ +static inline void mavlink_msg_statustext_decode(const mavlink_message_t* msg, mavlink_statustext_t* statustext) +{ +#if MAVLINK_NEED_BYTE_SWAP + statustext->severity = mavlink_msg_statustext_get_severity(msg); + mavlink_msg_statustext_get_text(msg, statustext->text); +#else + memcpy(statustext, _MAV_PAYLOAD(msg), 51); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_sys_status.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_sys_status.h new file mode 100644 index 0000000000..ef09a652f8 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_sys_status.h @@ -0,0 +1,408 @@ +// MESSAGE SYS_STATUS PACKING + +#define MAVLINK_MSG_ID_SYS_STATUS 1 + +typedef struct __mavlink_sys_status_t +{ + uint32_t onboard_control_sensors_present; ///< Bitmask showing which onboard controllers and sensors are present. Value of 0: not present. Value of 1: present. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + uint32_t onboard_control_sensors_enabled; ///< Bitmask showing which onboard controllers and sensors are enabled: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + uint32_t onboard_control_sensors_health; ///< Bitmask showing which onboard controllers and sensors are operational or have an error: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + uint16_t load; ///< Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 + uint16_t voltage_battery; ///< Battery voltage, in millivolts (1 = 1 millivolt) + int16_t current_battery; ///< Battery current, in 10*milliamperes (1 = 10 milliampere), -1: autopilot does not measure the current + uint16_t drop_rate_comm; ///< Communication drops in percent, (0%: 0, 100%: 10'000), (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) + uint16_t errors_comm; ///< Communication errors (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) + uint16_t errors_count1; ///< Autopilot-specific errors + uint16_t errors_count2; ///< Autopilot-specific errors + uint16_t errors_count3; ///< Autopilot-specific errors + uint16_t errors_count4; ///< Autopilot-specific errors + int8_t battery_remaining; ///< Remaining battery energy: (0%: 0, 100%: 100), -1: autopilot estimate the remaining battery +} mavlink_sys_status_t; + +#define MAVLINK_MSG_ID_SYS_STATUS_LEN 31 +#define MAVLINK_MSG_ID_1_LEN 31 + + + +#define MAVLINK_MESSAGE_INFO_SYS_STATUS { \ + "SYS_STATUS", \ + 13, \ + { { "onboard_control_sensors_present", "0x%04x", MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_sys_status_t, onboard_control_sensors_present) }, \ + { "onboard_control_sensors_enabled", "0x%04x", MAVLINK_TYPE_UINT32_T, 0, 4, offsetof(mavlink_sys_status_t, onboard_control_sensors_enabled) }, \ + { "onboard_control_sensors_health", "0x%04x", MAVLINK_TYPE_UINT32_T, 0, 8, offsetof(mavlink_sys_status_t, onboard_control_sensors_health) }, \ + { "load", NULL, MAVLINK_TYPE_UINT16_T, 0, 12, offsetof(mavlink_sys_status_t, load) }, \ + { "voltage_battery", NULL, MAVLINK_TYPE_UINT16_T, 0, 14, offsetof(mavlink_sys_status_t, voltage_battery) }, \ + { "current_battery", NULL, MAVLINK_TYPE_INT16_T, 0, 16, offsetof(mavlink_sys_status_t, current_battery) }, \ + { "drop_rate_comm", NULL, MAVLINK_TYPE_UINT16_T, 0, 18, offsetof(mavlink_sys_status_t, drop_rate_comm) }, \ + { "errors_comm", NULL, MAVLINK_TYPE_UINT16_T, 0, 20, offsetof(mavlink_sys_status_t, errors_comm) }, \ + { "errors_count1", NULL, MAVLINK_TYPE_UINT16_T, 0, 22, offsetof(mavlink_sys_status_t, errors_count1) }, \ + { "errors_count2", NULL, MAVLINK_TYPE_UINT16_T, 0, 24, offsetof(mavlink_sys_status_t, errors_count2) }, \ + { "errors_count3", NULL, MAVLINK_TYPE_UINT16_T, 0, 26, offsetof(mavlink_sys_status_t, errors_count3) }, \ + { "errors_count4", NULL, MAVLINK_TYPE_UINT16_T, 0, 28, offsetof(mavlink_sys_status_t, errors_count4) }, \ + { "battery_remaining", NULL, MAVLINK_TYPE_INT8_T, 0, 30, offsetof(mavlink_sys_status_t, battery_remaining) }, \ + } \ +} + + +/** + * @brief Pack a sys_status message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param onboard_control_sensors_present Bitmask showing which onboard controllers and sensors are present. Value of 0: not present. Value of 1: present. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + * @param onboard_control_sensors_enabled Bitmask showing which onboard controllers and sensors are enabled: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + * @param onboard_control_sensors_health Bitmask showing which onboard controllers and sensors are operational or have an error: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + * @param load Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 + * @param voltage_battery Battery voltage, in millivolts (1 = 1 millivolt) + * @param current_battery Battery current, in 10*milliamperes (1 = 10 milliampere), -1: autopilot does not measure the current + * @param battery_remaining Remaining battery energy: (0%: 0, 100%: 100), -1: autopilot estimate the remaining battery + * @param drop_rate_comm Communication drops in percent, (0%: 0, 100%: 10'000), (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) + * @param errors_comm Communication errors (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) + * @param errors_count1 Autopilot-specific errors + * @param errors_count2 Autopilot-specific errors + * @param errors_count3 Autopilot-specific errors + * @param errors_count4 Autopilot-specific errors + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sys_status_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint32_t onboard_control_sensors_present, uint32_t onboard_control_sensors_enabled, uint32_t onboard_control_sensors_health, uint16_t load, uint16_t voltage_battery, int16_t current_battery, int8_t battery_remaining, uint16_t drop_rate_comm, uint16_t errors_comm, uint16_t errors_count1, uint16_t errors_count2, uint16_t errors_count3, uint16_t errors_count4) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[31]; + _mav_put_uint32_t(buf, 0, onboard_control_sensors_present); + _mav_put_uint32_t(buf, 4, onboard_control_sensors_enabled); + _mav_put_uint32_t(buf, 8, onboard_control_sensors_health); + _mav_put_uint16_t(buf, 12, load); + _mav_put_uint16_t(buf, 14, voltage_battery); + _mav_put_int16_t(buf, 16, current_battery); + _mav_put_uint16_t(buf, 18, drop_rate_comm); + _mav_put_uint16_t(buf, 20, errors_comm); + _mav_put_uint16_t(buf, 22, errors_count1); + _mav_put_uint16_t(buf, 24, errors_count2); + _mav_put_uint16_t(buf, 26, errors_count3); + _mav_put_uint16_t(buf, 28, errors_count4); + _mav_put_int8_t(buf, 30, battery_remaining); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 31); +#else + mavlink_sys_status_t packet; + packet.onboard_control_sensors_present = onboard_control_sensors_present; + packet.onboard_control_sensors_enabled = onboard_control_sensors_enabled; + packet.onboard_control_sensors_health = onboard_control_sensors_health; + packet.load = load; + packet.voltage_battery = voltage_battery; + packet.current_battery = current_battery; + packet.drop_rate_comm = drop_rate_comm; + packet.errors_comm = errors_comm; + packet.errors_count1 = errors_count1; + packet.errors_count2 = errors_count2; + packet.errors_count3 = errors_count3; + packet.errors_count4 = errors_count4; + packet.battery_remaining = battery_remaining; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 31); +#endif + + msg->msgid = MAVLINK_MSG_ID_SYS_STATUS; + return mavlink_finalize_message(msg, system_id, component_id, 31, 124); +} + +/** + * @brief Pack a sys_status message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param onboard_control_sensors_present Bitmask showing which onboard controllers and sensors are present. Value of 0: not present. Value of 1: present. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + * @param onboard_control_sensors_enabled Bitmask showing which onboard controllers and sensors are enabled: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + * @param onboard_control_sensors_health Bitmask showing which onboard controllers and sensors are operational or have an error: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + * @param load Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 + * @param voltage_battery Battery voltage, in millivolts (1 = 1 millivolt) + * @param current_battery Battery current, in 10*milliamperes (1 = 10 milliampere), -1: autopilot does not measure the current + * @param battery_remaining Remaining battery energy: (0%: 0, 100%: 100), -1: autopilot estimate the remaining battery + * @param drop_rate_comm Communication drops in percent, (0%: 0, 100%: 10'000), (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) + * @param errors_comm Communication errors (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) + * @param errors_count1 Autopilot-specific errors + * @param errors_count2 Autopilot-specific errors + * @param errors_count3 Autopilot-specific errors + * @param errors_count4 Autopilot-specific errors + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sys_status_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint32_t onboard_control_sensors_present,uint32_t onboard_control_sensors_enabled,uint32_t onboard_control_sensors_health,uint16_t load,uint16_t voltage_battery,int16_t current_battery,int8_t battery_remaining,uint16_t drop_rate_comm,uint16_t errors_comm,uint16_t errors_count1,uint16_t errors_count2,uint16_t errors_count3,uint16_t errors_count4) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[31]; + _mav_put_uint32_t(buf, 0, onboard_control_sensors_present); + _mav_put_uint32_t(buf, 4, onboard_control_sensors_enabled); + _mav_put_uint32_t(buf, 8, onboard_control_sensors_health); + _mav_put_uint16_t(buf, 12, load); + _mav_put_uint16_t(buf, 14, voltage_battery); + _mav_put_int16_t(buf, 16, current_battery); + _mav_put_uint16_t(buf, 18, drop_rate_comm); + _mav_put_uint16_t(buf, 20, errors_comm); + _mav_put_uint16_t(buf, 22, errors_count1); + _mav_put_uint16_t(buf, 24, errors_count2); + _mav_put_uint16_t(buf, 26, errors_count3); + _mav_put_uint16_t(buf, 28, errors_count4); + _mav_put_int8_t(buf, 30, battery_remaining); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 31); +#else + mavlink_sys_status_t packet; + packet.onboard_control_sensors_present = onboard_control_sensors_present; + packet.onboard_control_sensors_enabled = onboard_control_sensors_enabled; + packet.onboard_control_sensors_health = onboard_control_sensors_health; + packet.load = load; + packet.voltage_battery = voltage_battery; + packet.current_battery = current_battery; + packet.drop_rate_comm = drop_rate_comm; + packet.errors_comm = errors_comm; + packet.errors_count1 = errors_count1; + packet.errors_count2 = errors_count2; + packet.errors_count3 = errors_count3; + packet.errors_count4 = errors_count4; + packet.battery_remaining = battery_remaining; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 31); +#endif + + msg->msgid = MAVLINK_MSG_ID_SYS_STATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 31, 124); +} + +/** + * @brief Encode a sys_status struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param sys_status C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_sys_status_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_sys_status_t* sys_status) +{ + return mavlink_msg_sys_status_pack(system_id, component_id, msg, sys_status->onboard_control_sensors_present, sys_status->onboard_control_sensors_enabled, sys_status->onboard_control_sensors_health, sys_status->load, sys_status->voltage_battery, sys_status->current_battery, sys_status->battery_remaining, sys_status->drop_rate_comm, sys_status->errors_comm, sys_status->errors_count1, sys_status->errors_count2, sys_status->errors_count3, sys_status->errors_count4); +} + +/** + * @brief Send a sys_status message + * @param chan MAVLink channel to send the message + * + * @param onboard_control_sensors_present Bitmask showing which onboard controllers and sensors are present. Value of 0: not present. Value of 1: present. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + * @param onboard_control_sensors_enabled Bitmask showing which onboard controllers and sensors are enabled: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + * @param onboard_control_sensors_health Bitmask showing which onboard controllers and sensors are operational or have an error: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + * @param load Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 + * @param voltage_battery Battery voltage, in millivolts (1 = 1 millivolt) + * @param current_battery Battery current, in 10*milliamperes (1 = 10 milliampere), -1: autopilot does not measure the current + * @param battery_remaining Remaining battery energy: (0%: 0, 100%: 100), -1: autopilot estimate the remaining battery + * @param drop_rate_comm Communication drops in percent, (0%: 0, 100%: 10'000), (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) + * @param errors_comm Communication errors (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) + * @param errors_count1 Autopilot-specific errors + * @param errors_count2 Autopilot-specific errors + * @param errors_count3 Autopilot-specific errors + * @param errors_count4 Autopilot-specific errors + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_sys_status_send(mavlink_channel_t chan, uint32_t onboard_control_sensors_present, uint32_t onboard_control_sensors_enabled, uint32_t onboard_control_sensors_health, uint16_t load, uint16_t voltage_battery, int16_t current_battery, int8_t battery_remaining, uint16_t drop_rate_comm, uint16_t errors_comm, uint16_t errors_count1, uint16_t errors_count2, uint16_t errors_count3, uint16_t errors_count4) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[31]; + _mav_put_uint32_t(buf, 0, onboard_control_sensors_present); + _mav_put_uint32_t(buf, 4, onboard_control_sensors_enabled); + _mav_put_uint32_t(buf, 8, onboard_control_sensors_health); + _mav_put_uint16_t(buf, 12, load); + _mav_put_uint16_t(buf, 14, voltage_battery); + _mav_put_int16_t(buf, 16, current_battery); + _mav_put_uint16_t(buf, 18, drop_rate_comm); + _mav_put_uint16_t(buf, 20, errors_comm); + _mav_put_uint16_t(buf, 22, errors_count1); + _mav_put_uint16_t(buf, 24, errors_count2); + _mav_put_uint16_t(buf, 26, errors_count3); + _mav_put_uint16_t(buf, 28, errors_count4); + _mav_put_int8_t(buf, 30, battery_remaining); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SYS_STATUS, buf, 31, 124); +#else + mavlink_sys_status_t packet; + packet.onboard_control_sensors_present = onboard_control_sensors_present; + packet.onboard_control_sensors_enabled = onboard_control_sensors_enabled; + packet.onboard_control_sensors_health = onboard_control_sensors_health; + packet.load = load; + packet.voltage_battery = voltage_battery; + packet.current_battery = current_battery; + packet.drop_rate_comm = drop_rate_comm; + packet.errors_comm = errors_comm; + packet.errors_count1 = errors_count1; + packet.errors_count2 = errors_count2; + packet.errors_count3 = errors_count3; + packet.errors_count4 = errors_count4; + packet.battery_remaining = battery_remaining; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SYS_STATUS, (const char *)&packet, 31, 124); +#endif +} + +#endif + +// MESSAGE SYS_STATUS UNPACKING + + +/** + * @brief Get field onboard_control_sensors_present from sys_status message + * + * @return Bitmask showing which onboard controllers and sensors are present. Value of 0: not present. Value of 1: present. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + */ +static inline uint32_t mavlink_msg_sys_status_get_onboard_control_sensors_present(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field onboard_control_sensors_enabled from sys_status message + * + * @return Bitmask showing which onboard controllers and sensors are enabled: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + */ +static inline uint32_t mavlink_msg_sys_status_get_onboard_control_sensors_enabled(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 4); +} + +/** + * @brief Get field onboard_control_sensors_health from sys_status message + * + * @return Bitmask showing which onboard controllers and sensors are operational or have an error: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control + */ +static inline uint32_t mavlink_msg_sys_status_get_onboard_control_sensors_health(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 8); +} + +/** + * @brief Get field load from sys_status message + * + * @return Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 + */ +static inline uint16_t mavlink_msg_sys_status_get_load(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 12); +} + +/** + * @brief Get field voltage_battery from sys_status message + * + * @return Battery voltage, in millivolts (1 = 1 millivolt) + */ +static inline uint16_t mavlink_msg_sys_status_get_voltage_battery(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 14); +} + +/** + * @brief Get field current_battery from sys_status message + * + * @return Battery current, in 10*milliamperes (1 = 10 milliampere), -1: autopilot does not measure the current + */ +static inline int16_t mavlink_msg_sys_status_get_current_battery(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 16); +} + +/** + * @brief Get field battery_remaining from sys_status message + * + * @return Remaining battery energy: (0%: 0, 100%: 100), -1: autopilot estimate the remaining battery + */ +static inline int8_t mavlink_msg_sys_status_get_battery_remaining(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int8_t(msg, 30); +} + +/** + * @brief Get field drop_rate_comm from sys_status message + * + * @return Communication drops in percent, (0%: 0, 100%: 10'000), (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) + */ +static inline uint16_t mavlink_msg_sys_status_get_drop_rate_comm(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 18); +} + +/** + * @brief Get field errors_comm from sys_status message + * + * @return Communication errors (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) + */ +static inline uint16_t mavlink_msg_sys_status_get_errors_comm(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 20); +} + +/** + * @brief Get field errors_count1 from sys_status message + * + * @return Autopilot-specific errors + */ +static inline uint16_t mavlink_msg_sys_status_get_errors_count1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 22); +} + +/** + * @brief Get field errors_count2 from sys_status message + * + * @return Autopilot-specific errors + */ +static inline uint16_t mavlink_msg_sys_status_get_errors_count2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 24); +} + +/** + * @brief Get field errors_count3 from sys_status message + * + * @return Autopilot-specific errors + */ +static inline uint16_t mavlink_msg_sys_status_get_errors_count3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 26); +} + +/** + * @brief Get field errors_count4 from sys_status message + * + * @return Autopilot-specific errors + */ +static inline uint16_t mavlink_msg_sys_status_get_errors_count4(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 28); +} + +/** + * @brief Decode a sys_status message into a struct + * + * @param msg The message to decode + * @param sys_status C-struct to decode the message contents into + */ +static inline void mavlink_msg_sys_status_decode(const mavlink_message_t* msg, mavlink_sys_status_t* sys_status) +{ +#if MAVLINK_NEED_BYTE_SWAP + sys_status->onboard_control_sensors_present = mavlink_msg_sys_status_get_onboard_control_sensors_present(msg); + sys_status->onboard_control_sensors_enabled = mavlink_msg_sys_status_get_onboard_control_sensors_enabled(msg); + sys_status->onboard_control_sensors_health = mavlink_msg_sys_status_get_onboard_control_sensors_health(msg); + sys_status->load = mavlink_msg_sys_status_get_load(msg); + sys_status->voltage_battery = mavlink_msg_sys_status_get_voltage_battery(msg); + sys_status->current_battery = mavlink_msg_sys_status_get_current_battery(msg); + sys_status->drop_rate_comm = mavlink_msg_sys_status_get_drop_rate_comm(msg); + sys_status->errors_comm = mavlink_msg_sys_status_get_errors_comm(msg); + sys_status->errors_count1 = mavlink_msg_sys_status_get_errors_count1(msg); + sys_status->errors_count2 = mavlink_msg_sys_status_get_errors_count2(msg); + sys_status->errors_count3 = mavlink_msg_sys_status_get_errors_count3(msg); + sys_status->errors_count4 = mavlink_msg_sys_status_get_errors_count4(msg); + sys_status->battery_remaining = mavlink_msg_sys_status_get_battery_remaining(msg); +#else + memcpy(sys_status, _MAV_PAYLOAD(msg), 31); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_system_time.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_system_time.h new file mode 100644 index 0000000000..c24808d1a2 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_system_time.h @@ -0,0 +1,166 @@ +// MESSAGE SYSTEM_TIME PACKING + +#define MAVLINK_MSG_ID_SYSTEM_TIME 2 + +typedef struct __mavlink_system_time_t +{ + uint64_t time_unix_usec; ///< Timestamp of the master clock in microseconds since UNIX epoch. + uint32_t time_boot_ms; ///< Timestamp of the component clock since boot time in milliseconds. +} mavlink_system_time_t; + +#define MAVLINK_MSG_ID_SYSTEM_TIME_LEN 12 +#define MAVLINK_MSG_ID_2_LEN 12 + + + +#define MAVLINK_MESSAGE_INFO_SYSTEM_TIME { \ + "SYSTEM_TIME", \ + 2, \ + { { "time_unix_usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_system_time_t, time_unix_usec) }, \ + { "time_boot_ms", NULL, MAVLINK_TYPE_UINT32_T, 0, 8, offsetof(mavlink_system_time_t, time_boot_ms) }, \ + } \ +} + + +/** + * @brief Pack a system_time message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param time_unix_usec Timestamp of the master clock in microseconds since UNIX epoch. + * @param time_boot_ms Timestamp of the component clock since boot time in milliseconds. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_system_time_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t time_unix_usec, uint32_t time_boot_ms) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint64_t(buf, 0, time_unix_usec); + _mav_put_uint32_t(buf, 8, time_boot_ms); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_system_time_t packet; + packet.time_unix_usec = time_unix_usec; + packet.time_boot_ms = time_boot_ms; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_SYSTEM_TIME; + return mavlink_finalize_message(msg, system_id, component_id, 12, 137); +} + +/** + * @brief Pack a system_time message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param time_unix_usec Timestamp of the master clock in microseconds since UNIX epoch. + * @param time_boot_ms Timestamp of the component clock since boot time in milliseconds. + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_system_time_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t time_unix_usec,uint32_t time_boot_ms) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint64_t(buf, 0, time_unix_usec); + _mav_put_uint32_t(buf, 8, time_boot_ms); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_system_time_t packet; + packet.time_unix_usec = time_unix_usec; + packet.time_boot_ms = time_boot_ms; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_SYSTEM_TIME; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12, 137); +} + +/** + * @brief Encode a system_time struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param system_time C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_system_time_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_system_time_t* system_time) +{ + return mavlink_msg_system_time_pack(system_id, component_id, msg, system_time->time_unix_usec, system_time->time_boot_ms); +} + +/** + * @brief Send a system_time message + * @param chan MAVLink channel to send the message + * + * @param time_unix_usec Timestamp of the master clock in microseconds since UNIX epoch. + * @param time_boot_ms Timestamp of the component clock since boot time in milliseconds. + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_system_time_send(mavlink_channel_t chan, uint64_t time_unix_usec, uint32_t time_boot_ms) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint64_t(buf, 0, time_unix_usec); + _mav_put_uint32_t(buf, 8, time_boot_ms); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SYSTEM_TIME, buf, 12, 137); +#else + mavlink_system_time_t packet; + packet.time_unix_usec = time_unix_usec; + packet.time_boot_ms = time_boot_ms; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SYSTEM_TIME, (const char *)&packet, 12, 137); +#endif +} + +#endif + +// MESSAGE SYSTEM_TIME UNPACKING + + +/** + * @brief Get field time_unix_usec from system_time message + * + * @return Timestamp of the master clock in microseconds since UNIX epoch. + */ +static inline uint64_t mavlink_msg_system_time_get_time_unix_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field time_boot_ms from system_time message + * + * @return Timestamp of the component clock since boot time in milliseconds. + */ +static inline uint32_t mavlink_msg_system_time_get_time_boot_ms(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 8); +} + +/** + * @brief Decode a system_time message into a struct + * + * @param msg The message to decode + * @param system_time C-struct to decode the message contents into + */ +static inline void mavlink_msg_system_time_decode(const mavlink_message_t* msg, mavlink_system_time_t* system_time) +{ +#if MAVLINK_NEED_BYTE_SWAP + system_time->time_unix_usec = mavlink_msg_system_time_get_time_unix_usec(msg); + system_time->time_boot_ms = mavlink_msg_system_time_get_time_boot_ms(msg); +#else + memcpy(system_time, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_vfr_hud.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_vfr_hud.h new file mode 100644 index 0000000000..d7c1afe410 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_vfr_hud.h @@ -0,0 +1,254 @@ +// MESSAGE VFR_HUD PACKING + +#define MAVLINK_MSG_ID_VFR_HUD 74 + +typedef struct __mavlink_vfr_hud_t +{ + float airspeed; ///< Current airspeed in m/s + float groundspeed; ///< Current ground speed in m/s + float alt; ///< Current altitude (MSL), in meters + float climb; ///< Current climb rate in meters/second + int16_t heading; ///< Current heading in degrees, in compass units (0..360, 0=north) + uint16_t throttle; ///< Current throttle setting in integer percent, 0 to 100 +} mavlink_vfr_hud_t; + +#define MAVLINK_MSG_ID_VFR_HUD_LEN 20 +#define MAVLINK_MSG_ID_74_LEN 20 + + + +#define MAVLINK_MESSAGE_INFO_VFR_HUD { \ + "VFR_HUD", \ + 6, \ + { { "airspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_vfr_hud_t, airspeed) }, \ + { "groundspeed", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_vfr_hud_t, groundspeed) }, \ + { "alt", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_vfr_hud_t, alt) }, \ + { "climb", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_vfr_hud_t, climb) }, \ + { "heading", NULL, MAVLINK_TYPE_INT16_T, 0, 16, offsetof(mavlink_vfr_hud_t, heading) }, \ + { "throttle", NULL, MAVLINK_TYPE_UINT16_T, 0, 18, offsetof(mavlink_vfr_hud_t, throttle) }, \ + } \ +} + + +/** + * @brief Pack a vfr_hud message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param airspeed Current airspeed in m/s + * @param groundspeed Current ground speed in m/s + * @param heading Current heading in degrees, in compass units (0..360, 0=north) + * @param throttle Current throttle setting in integer percent, 0 to 100 + * @param alt Current altitude (MSL), in meters + * @param climb Current climb rate in meters/second + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vfr_hud_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float airspeed, float groundspeed, int16_t heading, uint16_t throttle, float alt, float climb) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_float(buf, 0, airspeed); + _mav_put_float(buf, 4, groundspeed); + _mav_put_float(buf, 8, alt); + _mav_put_float(buf, 12, climb); + _mav_put_int16_t(buf, 16, heading); + _mav_put_uint16_t(buf, 18, throttle); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_vfr_hud_t packet; + packet.airspeed = airspeed; + packet.groundspeed = groundspeed; + packet.alt = alt; + packet.climb = climb; + packet.heading = heading; + packet.throttle = throttle; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_VFR_HUD; + return mavlink_finalize_message(msg, system_id, component_id, 20, 20); +} + +/** + * @brief Pack a vfr_hud message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param airspeed Current airspeed in m/s + * @param groundspeed Current ground speed in m/s + * @param heading Current heading in degrees, in compass units (0..360, 0=north) + * @param throttle Current throttle setting in integer percent, 0 to 100 + * @param alt Current altitude (MSL), in meters + * @param climb Current climb rate in meters/second + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vfr_hud_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float airspeed,float groundspeed,int16_t heading,uint16_t throttle,float alt,float climb) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_float(buf, 0, airspeed); + _mav_put_float(buf, 4, groundspeed); + _mav_put_float(buf, 8, alt); + _mav_put_float(buf, 12, climb); + _mav_put_int16_t(buf, 16, heading); + _mav_put_uint16_t(buf, 18, throttle); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_vfr_hud_t packet; + packet.airspeed = airspeed; + packet.groundspeed = groundspeed; + packet.alt = alt; + packet.climb = climb; + packet.heading = heading; + packet.throttle = throttle; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_VFR_HUD; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 20, 20); +} + +/** + * @brief Encode a vfr_hud struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param vfr_hud C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_vfr_hud_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_vfr_hud_t* vfr_hud) +{ + return mavlink_msg_vfr_hud_pack(system_id, component_id, msg, vfr_hud->airspeed, vfr_hud->groundspeed, vfr_hud->heading, vfr_hud->throttle, vfr_hud->alt, vfr_hud->climb); +} + +/** + * @brief Send a vfr_hud message + * @param chan MAVLink channel to send the message + * + * @param airspeed Current airspeed in m/s + * @param groundspeed Current ground speed in m/s + * @param heading Current heading in degrees, in compass units (0..360, 0=north) + * @param throttle Current throttle setting in integer percent, 0 to 100 + * @param alt Current altitude (MSL), in meters + * @param climb Current climb rate in meters/second + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_vfr_hud_send(mavlink_channel_t chan, float airspeed, float groundspeed, int16_t heading, uint16_t throttle, float alt, float climb) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_float(buf, 0, airspeed); + _mav_put_float(buf, 4, groundspeed); + _mav_put_float(buf, 8, alt); + _mav_put_float(buf, 12, climb); + _mav_put_int16_t(buf, 16, heading); + _mav_put_uint16_t(buf, 18, throttle); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VFR_HUD, buf, 20, 20); +#else + mavlink_vfr_hud_t packet; + packet.airspeed = airspeed; + packet.groundspeed = groundspeed; + packet.alt = alt; + packet.climb = climb; + packet.heading = heading; + packet.throttle = throttle; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VFR_HUD, (const char *)&packet, 20, 20); +#endif +} + +#endif + +// MESSAGE VFR_HUD UNPACKING + + +/** + * @brief Get field airspeed from vfr_hud message + * + * @return Current airspeed in m/s + */ +static inline float mavlink_msg_vfr_hud_get_airspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field groundspeed from vfr_hud message + * + * @return Current ground speed in m/s + */ +static inline float mavlink_msg_vfr_hud_get_groundspeed(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field heading from vfr_hud message + * + * @return Current heading in degrees, in compass units (0..360, 0=north) + */ +static inline int16_t mavlink_msg_vfr_hud_get_heading(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 16); +} + +/** + * @brief Get field throttle from vfr_hud message + * + * @return Current throttle setting in integer percent, 0 to 100 + */ +static inline uint16_t mavlink_msg_vfr_hud_get_throttle(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 18); +} + +/** + * @brief Get field alt from vfr_hud message + * + * @return Current altitude (MSL), in meters + */ +static inline float mavlink_msg_vfr_hud_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field climb from vfr_hud message + * + * @return Current climb rate in meters/second + */ +static inline float mavlink_msg_vfr_hud_get_climb(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Decode a vfr_hud message into a struct + * + * @param msg The message to decode + * @param vfr_hud C-struct to decode the message contents into + */ +static inline void mavlink_msg_vfr_hud_decode(const mavlink_message_t* msg, mavlink_vfr_hud_t* vfr_hud) +{ +#if MAVLINK_NEED_BYTE_SWAP + vfr_hud->airspeed = mavlink_msg_vfr_hud_get_airspeed(msg); + vfr_hud->groundspeed = mavlink_msg_vfr_hud_get_groundspeed(msg); + vfr_hud->alt = mavlink_msg_vfr_hud_get_alt(msg); + vfr_hud->climb = mavlink_msg_vfr_hud_get_climb(msg); + vfr_hud->heading = mavlink_msg_vfr_hud_get_heading(msg); + vfr_hud->throttle = mavlink_msg_vfr_hud_get_throttle(msg); +#else + memcpy(vfr_hud, _MAV_PAYLOAD(msg), 20); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_vicon_position_estimate.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_vicon_position_estimate.h new file mode 100644 index 0000000000..ecb565684d --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_vicon_position_estimate.h @@ -0,0 +1,276 @@ +// MESSAGE VICON_POSITION_ESTIMATE PACKING + +#define MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE 104 + +typedef struct __mavlink_vicon_position_estimate_t +{ + uint64_t usec; ///< Timestamp (milliseconds) + float x; ///< Global X position + float y; ///< Global Y position + float z; ///< Global Z position + float roll; ///< Roll angle in rad + float pitch; ///< Pitch angle in rad + float yaw; ///< Yaw angle in rad +} mavlink_vicon_position_estimate_t; + +#define MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE_LEN 32 +#define MAVLINK_MSG_ID_104_LEN 32 + + + +#define MAVLINK_MESSAGE_INFO_VICON_POSITION_ESTIMATE { \ + "VICON_POSITION_ESTIMATE", \ + 7, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_vicon_position_estimate_t, usec) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_vicon_position_estimate_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_vicon_position_estimate_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_vicon_position_estimate_t, z) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_vicon_position_estimate_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_vicon_position_estimate_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_vicon_position_estimate_t, yaw) }, \ + } \ +} + + +/** + * @brief Pack a vicon_position_estimate message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vicon_position_estimate_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_vicon_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE; + return mavlink_finalize_message(msg, system_id, component_id, 32, 56); +} + +/** + * @brief Pack a vicon_position_estimate message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vicon_position_estimate_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float x,float y,float z,float roll,float pitch,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_vicon_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32, 56); +} + +/** + * @brief Encode a vicon_position_estimate struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param vicon_position_estimate C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_vicon_position_estimate_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_vicon_position_estimate_t* vicon_position_estimate) +{ + return mavlink_msg_vicon_position_estimate_pack(system_id, component_id, msg, vicon_position_estimate->usec, vicon_position_estimate->x, vicon_position_estimate->y, vicon_position_estimate->z, vicon_position_estimate->roll, vicon_position_estimate->pitch, vicon_position_estimate->yaw); +} + +/** + * @brief Send a vicon_position_estimate message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_vicon_position_estimate_send(mavlink_channel_t chan, uint64_t usec, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE, buf, 32, 56); +#else + mavlink_vicon_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE, (const char *)&packet, 32, 56); +#endif +} + +#endif + +// MESSAGE VICON_POSITION_ESTIMATE UNPACKING + + +/** + * @brief Get field usec from vicon_position_estimate message + * + * @return Timestamp (milliseconds) + */ +static inline uint64_t mavlink_msg_vicon_position_estimate_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field x from vicon_position_estimate message + * + * @return Global X position + */ +static inline float mavlink_msg_vicon_position_estimate_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field y from vicon_position_estimate message + * + * @return Global Y position + */ +static inline float mavlink_msg_vicon_position_estimate_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field z from vicon_position_estimate message + * + * @return Global Z position + */ +static inline float mavlink_msg_vicon_position_estimate_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field roll from vicon_position_estimate message + * + * @return Roll angle in rad + */ +static inline float mavlink_msg_vicon_position_estimate_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field pitch from vicon_position_estimate message + * + * @return Pitch angle in rad + */ +static inline float mavlink_msg_vicon_position_estimate_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field yaw from vicon_position_estimate message + * + * @return Yaw angle in rad + */ +static inline float mavlink_msg_vicon_position_estimate_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Decode a vicon_position_estimate message into a struct + * + * @param msg The message to decode + * @param vicon_position_estimate C-struct to decode the message contents into + */ +static inline void mavlink_msg_vicon_position_estimate_decode(const mavlink_message_t* msg, mavlink_vicon_position_estimate_t* vicon_position_estimate) +{ +#if MAVLINK_NEED_BYTE_SWAP + vicon_position_estimate->usec = mavlink_msg_vicon_position_estimate_get_usec(msg); + vicon_position_estimate->x = mavlink_msg_vicon_position_estimate_get_x(msg); + vicon_position_estimate->y = mavlink_msg_vicon_position_estimate_get_y(msg); + vicon_position_estimate->z = mavlink_msg_vicon_position_estimate_get_z(msg); + vicon_position_estimate->roll = mavlink_msg_vicon_position_estimate_get_roll(msg); + vicon_position_estimate->pitch = mavlink_msg_vicon_position_estimate_get_pitch(msg); + vicon_position_estimate->yaw = mavlink_msg_vicon_position_estimate_get_yaw(msg); +#else + memcpy(vicon_position_estimate, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_vision_position_estimate.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_vision_position_estimate.h new file mode 100644 index 0000000000..041caf7a07 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_vision_position_estimate.h @@ -0,0 +1,276 @@ +// MESSAGE VISION_POSITION_ESTIMATE PACKING + +#define MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE 102 + +typedef struct __mavlink_vision_position_estimate_t +{ + uint64_t usec; ///< Timestamp (milliseconds) + float x; ///< Global X position + float y; ///< Global Y position + float z; ///< Global Z position + float roll; ///< Roll angle in rad + float pitch; ///< Pitch angle in rad + float yaw; ///< Yaw angle in rad +} mavlink_vision_position_estimate_t; + +#define MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE_LEN 32 +#define MAVLINK_MSG_ID_102_LEN 32 + + + +#define MAVLINK_MESSAGE_INFO_VISION_POSITION_ESTIMATE { \ + "VISION_POSITION_ESTIMATE", \ + 7, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_vision_position_estimate_t, usec) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_vision_position_estimate_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_vision_position_estimate_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_vision_position_estimate_t, z) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_vision_position_estimate_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_vision_position_estimate_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_vision_position_estimate_t, yaw) }, \ + } \ +} + + +/** + * @brief Pack a vision_position_estimate message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vision_position_estimate_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_vision_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE; + return mavlink_finalize_message(msg, system_id, component_id, 32, 158); +} + +/** + * @brief Pack a vision_position_estimate message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vision_position_estimate_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float x,float y,float z,float roll,float pitch,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_vision_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32, 158); +} + +/** + * @brief Encode a vision_position_estimate struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param vision_position_estimate C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_vision_position_estimate_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_vision_position_estimate_t* vision_position_estimate) +{ + return mavlink_msg_vision_position_estimate_pack(system_id, component_id, msg, vision_position_estimate->usec, vision_position_estimate->x, vision_position_estimate->y, vision_position_estimate->z, vision_position_estimate->roll, vision_position_estimate->pitch, vision_position_estimate->yaw); +} + +/** + * @brief Send a vision_position_estimate message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (milliseconds) + * @param x Global X position + * @param y Global Y position + * @param z Global Z position + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_vision_position_estimate_send(mavlink_channel_t chan, uint64_t usec, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + _mav_put_float(buf, 20, roll); + _mav_put_float(buf, 24, pitch); + _mav_put_float(buf, 28, yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE, buf, 32, 158); +#else + mavlink_vision_position_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE, (const char *)&packet, 32, 158); +#endif +} + +#endif + +// MESSAGE VISION_POSITION_ESTIMATE UNPACKING + + +/** + * @brief Get field usec from vision_position_estimate message + * + * @return Timestamp (milliseconds) + */ +static inline uint64_t mavlink_msg_vision_position_estimate_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field x from vision_position_estimate message + * + * @return Global X position + */ +static inline float mavlink_msg_vision_position_estimate_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field y from vision_position_estimate message + * + * @return Global Y position + */ +static inline float mavlink_msg_vision_position_estimate_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field z from vision_position_estimate message + * + * @return Global Z position + */ +static inline float mavlink_msg_vision_position_estimate_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field roll from vision_position_estimate message + * + * @return Roll angle in rad + */ +static inline float mavlink_msg_vision_position_estimate_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field pitch from vision_position_estimate message + * + * @return Pitch angle in rad + */ +static inline float mavlink_msg_vision_position_estimate_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field yaw from vision_position_estimate message + * + * @return Yaw angle in rad + */ +static inline float mavlink_msg_vision_position_estimate_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Decode a vision_position_estimate message into a struct + * + * @param msg The message to decode + * @param vision_position_estimate C-struct to decode the message contents into + */ +static inline void mavlink_msg_vision_position_estimate_decode(const mavlink_message_t* msg, mavlink_vision_position_estimate_t* vision_position_estimate) +{ +#if MAVLINK_NEED_BYTE_SWAP + vision_position_estimate->usec = mavlink_msg_vision_position_estimate_get_usec(msg); + vision_position_estimate->x = mavlink_msg_vision_position_estimate_get_x(msg); + vision_position_estimate->y = mavlink_msg_vision_position_estimate_get_y(msg); + vision_position_estimate->z = mavlink_msg_vision_position_estimate_get_z(msg); + vision_position_estimate->roll = mavlink_msg_vision_position_estimate_get_roll(msg); + vision_position_estimate->pitch = mavlink_msg_vision_position_estimate_get_pitch(msg); + vision_position_estimate->yaw = mavlink_msg_vision_position_estimate_get_yaw(msg); +#else + memcpy(vision_position_estimate, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/mavlink_msg_vision_speed_estimate.h b/mavlink/include/mavlink/v1.0/common/mavlink_msg_vision_speed_estimate.h new file mode 100644 index 0000000000..3e30b9247a --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/mavlink_msg_vision_speed_estimate.h @@ -0,0 +1,210 @@ +// MESSAGE VISION_SPEED_ESTIMATE PACKING + +#define MAVLINK_MSG_ID_VISION_SPEED_ESTIMATE 103 + +typedef struct __mavlink_vision_speed_estimate_t +{ + uint64_t usec; ///< Timestamp (milliseconds) + float x; ///< Global X speed + float y; ///< Global Y speed + float z; ///< Global Z speed +} mavlink_vision_speed_estimate_t; + +#define MAVLINK_MSG_ID_VISION_SPEED_ESTIMATE_LEN 20 +#define MAVLINK_MSG_ID_103_LEN 20 + + + +#define MAVLINK_MESSAGE_INFO_VISION_SPEED_ESTIMATE { \ + "VISION_SPEED_ESTIMATE", \ + 4, \ + { { "usec", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_vision_speed_estimate_t, usec) }, \ + { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_vision_speed_estimate_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_vision_speed_estimate_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_vision_speed_estimate_t, z) }, \ + } \ +} + + +/** + * @brief Pack a vision_speed_estimate message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param usec Timestamp (milliseconds) + * @param x Global X speed + * @param y Global Y speed + * @param z Global Z speed + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vision_speed_estimate_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t usec, float x, float y, float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_vision_speed_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_VISION_SPEED_ESTIMATE; + return mavlink_finalize_message(msg, system_id, component_id, 20, 208); +} + +/** + * @brief Pack a vision_speed_estimate message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (milliseconds) + * @param x Global X speed + * @param y Global Y speed + * @param z Global Z speed + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_vision_speed_estimate_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float x,float y,float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_vision_speed_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_VISION_SPEED_ESTIMATE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 20, 208); +} + +/** + * @brief Encode a vision_speed_estimate struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param vision_speed_estimate C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_vision_speed_estimate_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_vision_speed_estimate_t* vision_speed_estimate) +{ + return mavlink_msg_vision_speed_estimate_pack(system_id, component_id, msg, vision_speed_estimate->usec, vision_speed_estimate->x, vision_speed_estimate->y, vision_speed_estimate->z); +} + +/** + * @brief Send a vision_speed_estimate message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (milliseconds) + * @param x Global X speed + * @param y Global Y speed + * @param z Global Z speed + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_vision_speed_estimate_send(mavlink_channel_t chan, uint64_t usec, float x, float y, float z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, x); + _mav_put_float(buf, 12, y); + _mav_put_float(buf, 16, z); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VISION_SPEED_ESTIMATE, buf, 20, 208); +#else + mavlink_vision_speed_estimate_t packet; + packet.usec = usec; + packet.x = x; + packet.y = y; + packet.z = z; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_VISION_SPEED_ESTIMATE, (const char *)&packet, 20, 208); +#endif +} + +#endif + +// MESSAGE VISION_SPEED_ESTIMATE UNPACKING + + +/** + * @brief Get field usec from vision_speed_estimate message + * + * @return Timestamp (milliseconds) + */ +static inline uint64_t mavlink_msg_vision_speed_estimate_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field x from vision_speed_estimate message + * + * @return Global X speed + */ +static inline float mavlink_msg_vision_speed_estimate_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field y from vision_speed_estimate message + * + * @return Global Y speed + */ +static inline float mavlink_msg_vision_speed_estimate_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field z from vision_speed_estimate message + * + * @return Global Z speed + */ +static inline float mavlink_msg_vision_speed_estimate_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Decode a vision_speed_estimate message into a struct + * + * @param msg The message to decode + * @param vision_speed_estimate C-struct to decode the message contents into + */ +static inline void mavlink_msg_vision_speed_estimate_decode(const mavlink_message_t* msg, mavlink_vision_speed_estimate_t* vision_speed_estimate) +{ +#if MAVLINK_NEED_BYTE_SWAP + vision_speed_estimate->usec = mavlink_msg_vision_speed_estimate_get_usec(msg); + vision_speed_estimate->x = mavlink_msg_vision_speed_estimate_get_x(msg); + vision_speed_estimate->y = mavlink_msg_vision_speed_estimate_get_y(msg); + vision_speed_estimate->z = mavlink_msg_vision_speed_estimate_get_z(msg); +#else + memcpy(vision_speed_estimate, _MAV_PAYLOAD(msg), 20); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/common/testsuite.h b/mavlink/include/mavlink/v1.0/common/testsuite.h new file mode 100644 index 0000000000..5459a61a5a --- /dev/null +++ b/mavlink/include/mavlink/v1.0/common/testsuite.h @@ -0,0 +1,4024 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from common.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef COMMON_TESTSUITE_H +#define COMMON_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL + +static void mavlink_test_common(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + + mavlink_test_common(system_id, component_id, last_msg); +} +#endif + + + + +static void mavlink_test_heartbeat(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_heartbeat_t packet_in = { + 963497464, + 17, + 84, + 151, + 218, + 3, + }; + mavlink_heartbeat_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.custom_mode = packet_in.custom_mode; + packet1.type = packet_in.type; + packet1.autopilot = packet_in.autopilot; + packet1.base_mode = packet_in.base_mode; + packet1.system_status = packet_in.system_status; + packet1.mavlink_version = packet_in.mavlink_version; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_heartbeat_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_heartbeat_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_heartbeat_pack(system_id, component_id, &msg , packet1.type , packet1.autopilot , packet1.base_mode , packet1.custom_mode , packet1.system_status ); + mavlink_msg_heartbeat_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_heartbeat_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.type , packet1.autopilot , packet1.base_mode , packet1.custom_mode , packet1.system_status ); + mavlink_msg_heartbeat_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; imagic = MAVLINK_STX; + msg->len = length; + msg->sysid = system_id; + msg->compid = component_id; + // One sequence number per component + msg->seq = mavlink_get_channel_status(chan)->current_tx_seq; + mavlink_get_channel_status(chan)->current_tx_seq = mavlink_get_channel_status(chan)->current_tx_seq+1; + checksum = crc_calculate((uint8_t*)&msg->len, length + MAVLINK_CORE_HEADER_LEN); +#if MAVLINK_CRC_EXTRA + crc_accumulate(crc_extra, &checksum); +#endif + mavlink_ck_a(msg) = (uint8_t)(checksum & 0xFF); + mavlink_ck_b(msg) = (uint8_t)(checksum >> 8); + + return length + MAVLINK_NUM_NON_PAYLOAD_BYTES; +} + + +/** + * @brief Finalize a MAVLink message with MAVLINK_COMM_0 as default channel + */ +#if MAVLINK_CRC_EXTRA +MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t length, uint8_t crc_extra) +{ + return mavlink_finalize_message_chan(msg, system_id, component_id, MAVLINK_COMM_0, length, crc_extra); +} +#else +MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t length) +{ + return mavlink_finalize_message_chan(msg, system_id, component_id, MAVLINK_COMM_0, length); +} +#endif + +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS +MAVLINK_HELPER void _mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len); + +/** + * @brief Finalize a MAVLink message with channel assignment and send + */ +#if MAVLINK_CRC_EXTRA +MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet, + uint8_t length, uint8_t crc_extra) +#else +MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet, uint8_t length) +#endif +{ + uint16_t checksum; + uint8_t buf[MAVLINK_NUM_HEADER_BYTES]; + uint8_t ck[2]; + mavlink_status_t *status = mavlink_get_channel_status(chan); + buf[0] = MAVLINK_STX; + buf[1] = length; + buf[2] = status->current_tx_seq; + buf[3] = mavlink_system.sysid; + buf[4] = mavlink_system.compid; + buf[5] = msgid; + status->current_tx_seq++; + checksum = crc_calculate((uint8_t*)&buf[1], MAVLINK_CORE_HEADER_LEN); + crc_accumulate_buffer(&checksum, packet, length); +#if MAVLINK_CRC_EXTRA + crc_accumulate(crc_extra, &checksum); +#endif + ck[0] = (uint8_t)(checksum & 0xFF); + ck[1] = (uint8_t)(checksum >> 8); + + MAVLINK_START_UART_SEND(chan, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)length); + _mavlink_send_uart(chan, (const char *)buf, MAVLINK_NUM_HEADER_BYTES); + _mavlink_send_uart(chan, packet, length); + _mavlink_send_uart(chan, (const char *)ck, 2); + MAVLINK_END_UART_SEND(chan, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)length); +} +#endif // MAVLINK_USE_CONVENIENCE_FUNCTIONS + +/** + * @brief Pack a message to send it over a serial byte stream + */ +MAVLINK_HELPER uint16_t mavlink_msg_to_send_buffer(uint8_t *buffer, const mavlink_message_t *msg) +{ + memcpy(buffer, (const uint8_t *)&msg->magic, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)msg->len); + return MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)msg->len; +} + +union __mavlink_bitfield { + uint8_t uint8; + int8_t int8; + uint16_t uint16; + int16_t int16; + uint32_t uint32; + int32_t int32; +}; + + +MAVLINK_HELPER void mavlink_start_checksum(mavlink_message_t* msg) +{ + crc_init(&msg->checksum); +} + +MAVLINK_HELPER void mavlink_update_checksum(mavlink_message_t* msg, uint8_t c) +{ + crc_accumulate(c, &msg->checksum); +} + +/** + * This is a convenience function which handles the complete MAVLink parsing. + * the function will parse one byte at a time and return the complete packet once + * it could be successfully decoded. Checksum and other failures will be silently + * ignored. + * + * @param chan ID of the current channel. This allows to parse different channels with this function. + * a channel is not a physical message channel like a serial port, but a logic partition of + * the communication streams in this case. COMM_NB is the limit for the number of channels + * on MCU (e.g. ARM7), while COMM_NB_HIGH is the limit for the number of channels in Linux/Windows + * @param c The char to barse + * + * @param returnMsg NULL if no message could be decoded, the message data else + * @return 0 if no message could be decoded, 1 else + * + * A typical use scenario of this function call is: + * + * @code + * #include // For fixed-width uint8_t type + * + * mavlink_message_t msg; + * int chan = 0; + * + * + * while(serial.bytesAvailable > 0) + * { + * uint8_t byte = serial.getNextByte(); + * if (mavlink_parse_char(chan, byte, &msg)) + * { + * printf("Received message with ID %d, sequence: %d from component %d of system %d", msg.msgid, msg.seq, msg.compid, msg.sysid); + * } + * } + * + * + * @endcode + */ +MAVLINK_HELPER uint8_t mavlink_parse_char(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status) +{ + /* + default message crc function. You can override this per-system to + put this data in a different memory segment + */ +#if MAVLINK_CRC_EXTRA +#ifndef MAVLINK_MESSAGE_CRC + static const uint8_t mavlink_message_crcs[256] = MAVLINK_MESSAGE_CRCS; +#define MAVLINK_MESSAGE_CRC(msgid) mavlink_message_crcs[msgid] +#endif +#endif + + mavlink_message_t* rxmsg = mavlink_get_channel_buffer(chan); ///< The currently decoded message + mavlink_status_t* status = mavlink_get_channel_status(chan); ///< The current decode status + int bufferIndex = 0; + + status->msg_received = 0; + + switch (status->parse_state) + { + case MAVLINK_PARSE_STATE_UNINIT: + case MAVLINK_PARSE_STATE_IDLE: + if (c == MAVLINK_STX) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; + rxmsg->len = 0; + rxmsg->magic = c; + mavlink_start_checksum(rxmsg); + } + break; + + case MAVLINK_PARSE_STATE_GOT_STX: + if (status->msg_received +/* Support shorter buffers than the + default maximum packet size */ +#if (MAVLINK_MAX_PAYLOAD_LEN < 255) + || c > MAVLINK_MAX_PAYLOAD_LEN +#endif + ) + { + status->buffer_overrun++; + status->parse_error++; + status->msg_received = 0; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + } + else + { + // NOT counting STX, LENGTH, SEQ, SYSID, COMPID, MSGID, CRC1 and CRC2 + rxmsg->len = c; + status->packet_idx = 0; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_LENGTH; + } + break; + + case MAVLINK_PARSE_STATE_GOT_LENGTH: + rxmsg->seq = c; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_SEQ; + break; + + case MAVLINK_PARSE_STATE_GOT_SEQ: + rxmsg->sysid = c; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_SYSID; + break; + + case MAVLINK_PARSE_STATE_GOT_SYSID: + rxmsg->compid = c; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_COMPID; + break; + + case MAVLINK_PARSE_STATE_GOT_COMPID: + rxmsg->msgid = c; + mavlink_update_checksum(rxmsg, c); + if (rxmsg->len == 0) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD; + } + else + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_MSGID; + } + break; + + case MAVLINK_PARSE_STATE_GOT_MSGID: + _MAV_PAYLOAD_NON_CONST(rxmsg)[status->packet_idx++] = (char)c; + mavlink_update_checksum(rxmsg, c); + if (status->packet_idx == rxmsg->len) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD; + } + break; + + case MAVLINK_PARSE_STATE_GOT_PAYLOAD: +#if MAVLINK_CRC_EXTRA + mavlink_update_checksum(rxmsg, MAVLINK_MESSAGE_CRC(rxmsg->msgid)); +#endif + if (c != (rxmsg->checksum & 0xFF)) { + // Check first checksum byte + status->parse_error++; + status->msg_received = 0; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + if (c == MAVLINK_STX) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; + rxmsg->len = 0; + mavlink_start_checksum(rxmsg); + } + } + else + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_CRC1; + _MAV_PAYLOAD_NON_CONST(rxmsg)[status->packet_idx] = (char)c; + } + break; + + case MAVLINK_PARSE_STATE_GOT_CRC1: + if (c != (rxmsg->checksum >> 8)) { + // Check second checksum byte + status->parse_error++; + status->msg_received = 0; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + if (c == MAVLINK_STX) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; + rxmsg->len = 0; + mavlink_start_checksum(rxmsg); + } + } + else + { + // Successfully got message + status->msg_received = 1; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + _MAV_PAYLOAD_NON_CONST(rxmsg)[status->packet_idx+1] = (char)c; + memcpy(r_message, rxmsg, sizeof(mavlink_message_t)); + } + break; + } + + bufferIndex++; + // If a message has been sucessfully decoded, check index + if (status->msg_received == 1) + { + //while(status->current_seq != rxmsg->seq) + //{ + // status->packet_rx_drop_count++; + // status->current_seq++; + //} + status->current_rx_seq = rxmsg->seq; + // Initial condition: If no packet has been received so far, drop count is undefined + if (status->packet_rx_success_count == 0) status->packet_rx_drop_count = 0; + // Count this packet as received + status->packet_rx_success_count++; + } + + r_mavlink_status->current_rx_seq = status->current_rx_seq+1; + r_mavlink_status->packet_rx_success_count = status->packet_rx_success_count; + r_mavlink_status->packet_rx_drop_count = status->parse_error; + status->parse_error = 0; + return status->msg_received; +} + +/** + * @brief Put a bitfield of length 1-32 bit into the buffer + * + * @param b the value to add, will be encoded in the bitfield + * @param bits number of bits to use to encode b, e.g. 1 for boolean, 2, 3, etc. + * @param packet_index the position in the packet (the index of the first byte to use) + * @param bit_index the position in the byte (the index of the first bit to use) + * @param buffer packet buffer to write into + * @return new position of the last used byte in the buffer + */ +MAVLINK_HELPER uint8_t put_bitfield_n_by_index(int32_t b, uint8_t bits, uint8_t packet_index, uint8_t bit_index, uint8_t* r_bit_index, uint8_t* buffer) +{ + uint16_t bits_remain = bits; + // Transform number into network order + int32_t v; + uint8_t i_bit_index, i_byte_index, curr_bits_n; +#if MAVLINK_NEED_BYTE_SWAP + union { + int32_t i; + uint8_t b[4]; + } bin, bout; + bin.i = b; + bout.b[0] = bin.b[3]; + bout.b[1] = bin.b[2]; + bout.b[2] = bin.b[1]; + bout.b[3] = bin.b[0]; + v = bout.i; +#else + v = b; +#endif + + // buffer in + // 01100000 01000000 00000000 11110001 + // buffer out + // 11110001 00000000 01000000 01100000 + + // Existing partly filled byte (four free slots) + // 0111xxxx + + // Mask n free bits + // 00001111 = 2^0 + 2^1 + 2^2 + 2^3 = 2^n - 1 + // = ((uint32_t)(1 << n)) - 1; // = 2^n - 1 + + // Shift n bits into the right position + // out = in >> n; + + // Mask and shift bytes + i_bit_index = bit_index; + i_byte_index = packet_index; + if (bit_index > 0) + { + // If bits were available at start, they were available + // in the byte before the current index + i_byte_index--; + } + + // While bits have not been packed yet + while (bits_remain > 0) + { + // Bits still have to be packed + // there can be more than 8 bits, so + // we might have to pack them into more than one byte + + // First pack everything we can into the current 'open' byte + //curr_bits_n = bits_remain << 3; // Equals bits_remain mod 8 + //FIXME + if (bits_remain <= (uint8_t)(8 - i_bit_index)) + { + // Enough space + curr_bits_n = (uint8_t)bits_remain; + } + else + { + curr_bits_n = (8 - i_bit_index); + } + + // Pack these n bits into the current byte + // Mask out whatever was at that position with ones (xxx11111) + buffer[i_byte_index] &= (0xFF >> (8 - curr_bits_n)); + // Put content to this position, by masking out the non-used part + buffer[i_byte_index] |= ((0x00 << curr_bits_n) & v); + + // Increment the bit index + i_bit_index += curr_bits_n; + + // Now proceed to the next byte, if necessary + bits_remain -= curr_bits_n; + if (bits_remain > 0) + { + // Offer another 8 bits / one byte + i_byte_index++; + i_bit_index = 0; + } + } + + *r_bit_index = i_bit_index; + // If a partly filled byte is present, mark this as consumed + if (i_bit_index != 7) i_byte_index++; + return i_byte_index - packet_index; +} + +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +// To make MAVLink work on your MCU, define comm_send_ch() if you wish +// to send 1 byte at a time, or MAVLINK_SEND_UART_BYTES() to send a +// whole packet at a time + +/* + +#include "mavlink_types.h" + +void comm_send_ch(mavlink_channel_t chan, uint8_t ch) +{ + if (chan == MAVLINK_COMM_0) + { + uart0_transmit(ch); + } + if (chan == MAVLINK_COMM_1) + { + uart1_transmit(ch); + } +} + */ + +MAVLINK_HELPER void _mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len) +{ +#ifdef MAVLINK_SEND_UART_BYTES + /* this is the more efficient approach, if the platform + defines it */ + MAVLINK_SEND_UART_BYTES(chan, (uint8_t *)buf, len); +#else + /* fallback to one byte at a time */ + uint16_t i; + for (i = 0; i < len; i++) { + comm_send_ch(chan, (uint8_t)buf[i]); + } +#endif +} +#endif // MAVLINK_USE_CONVENIENCE_FUNCTIONS + +#endif /* _MAVLINK_HELPERS_H_ */ diff --git a/mavlink/include/mavlink/v1.0/mavlink_protobuf_manager.hpp b/mavlink/include/mavlink/v1.0/mavlink_protobuf_manager.hpp new file mode 100644 index 0000000000..fd3ddd026f --- /dev/null +++ b/mavlink/include/mavlink/v1.0/mavlink_protobuf_manager.hpp @@ -0,0 +1,377 @@ +#ifndef MAVLINKPROTOBUFMANAGER_HPP +#define MAVLINKPROTOBUFMANAGER_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace mavlink +{ + +class ProtobufManager +{ +public: + ProtobufManager() + : mRegisteredTypeCount(0) + , mStreamID(0) + , mVerbose(false) + , kExtendedHeaderSize(MAVLINK_EXTENDED_HEADER_LEN) + , kExtendedPayloadMaxSize(MAVLINK_MAX_EXTENDED_PAYLOAD_LEN) + { + // register GLOverlay + { + std::tr1::shared_ptr msg(new px::GLOverlay); + registerType(msg); + } + + // register ObstacleList + { + std::tr1::shared_ptr msg(new px::ObstacleList); + registerType(msg); + } + + // register ObstacleMap + { + std::tr1::shared_ptr msg(new px::ObstacleMap); + registerType(msg); + } + + // register Path + { + std::tr1::shared_ptr msg(new px::Path); + registerType(msg); + } + + // register PointCloudXYZI + { + std::tr1::shared_ptr msg(new px::PointCloudXYZI); + registerType(msg); + } + + // register PointCloudXYZRGB + { + std::tr1::shared_ptr msg(new px::PointCloudXYZRGB); + registerType(msg); + } + + // register RGBDImage + { + std::tr1::shared_ptr msg(new px::RGBDImage); + registerType(msg); + } + + srand(time(NULL)); + mStreamID = rand() + 1; + } + + bool fragmentMessage(uint8_t system_id, uint8_t component_id, + uint8_t target_system, uint8_t target_component, + const google::protobuf::Message& protobuf_msg, + std::vector& fragments) const + { + TypeMap::const_iterator it = mTypeMap.find(protobuf_msg.GetTypeName()); + if (it == mTypeMap.end()) + { + std::cout << "# WARNING: Protobuf message with type " + << protobuf_msg.GetTypeName() << " is not registered." + << std::endl; + return false; + } + + uint8_t typecode = it->second; + + std::string data = protobuf_msg.SerializeAsString(); + + int fragmentCount = (protobuf_msg.ByteSize() + kExtendedPayloadMaxSize - 1) / kExtendedPayloadMaxSize; + unsigned int offset = 0; + + for (int i = 0; i < fragmentCount; ++i) + { + mavlink_extended_message_t fragment; + + // write extended header data + uint8_t* payload = reinterpret_cast(fragment.base_msg.payload64); + unsigned int length = 0; + uint8_t flags = 0; + + if (i < fragmentCount - 1) + { + length = kExtendedPayloadMaxSize; + flags |= 0x1; + } + else + { + length = protobuf_msg.ByteSize() - kExtendedPayloadMaxSize * (fragmentCount - 1); + } + + memcpy(payload, &target_system, 1); + memcpy(payload + 1, &target_component, 1); + memcpy(payload + 2, &typecode, 1); + memcpy(payload + 3, &length, 4); + memcpy(payload + 7, &mStreamID, 2); + memcpy(payload + 9, &offset, 4); + memcpy(payload + 13, &flags, 1); + + fragment.base_msg.msgid = MAVLINK_MSG_ID_EXTENDED_MESSAGE; + mavlink_finalize_message(&fragment.base_msg, system_id, component_id, kExtendedHeaderSize, 0); + + // write extended payload data + fragment.extended_payload_len = length; + memcpy(fragment.extended_payload, &data[offset], length); + + fragments.push_back(fragment); + offset += length; + } + + if (mVerbose) + { + std::cerr << "# INFO: Split extended message with size " + << protobuf_msg.ByteSize() << " into " + << fragmentCount << " fragments." << std::endl; + } + + return true; + } + + bool cacheFragment(mavlink_extended_message_t& msg) + { + if (!validFragment(msg)) + { + if (mVerbose) + { + std::cerr << "# WARNING: Message is not a valid fragment. " + << "Dropping message..." << std::endl; + } + return false; + } + + // read extended header + uint8_t* payload = reinterpret_cast(msg.base_msg.payload64); + uint8_t typecode = 0; + unsigned int length = 0; + unsigned short streamID = 0; + unsigned int offset = 0; + uint8_t flags = 0; + + memcpy(&typecode, payload + 2, 1); + memcpy(&length, payload + 3, 4); + memcpy(&streamID, payload + 7, 2); + memcpy(&offset, payload + 9, 4); + memcpy(&flags, payload + 13, 1); + + if (typecode >= mTypeMap.size()) + { + std::cout << "# WARNING: Protobuf message with type code " + << static_cast(typecode) << " is not registered." << std::endl; + return false; + } + + bool reassemble = false; + + FragmentQueue::iterator it = mFragmentQueue.find(streamID); + if (it == mFragmentQueue.end()) + { + if (offset == 0) + { + mFragmentQueue[streamID].push_back(msg); + + if ((flags & 0x1) != 0x1) + { + reassemble = true; + } + + if (mVerbose) + { + std::cerr << "# INFO: Added fragment to new queue." + << std::endl; + } + } + else + { + if (mVerbose) + { + std::cerr << "# WARNING: Message is not a valid fragment. " + << "Dropping message..." << std::endl; + } + } + } + else + { + std::deque& queue = it->second; + + if (queue.empty()) + { + if (offset == 0) + { + queue.push_back(msg); + + if ((flags & 0x1) != 0x1) + { + reassemble = true; + } + } + else + { + if (mVerbose) + { + std::cerr << "# WARNING: Message is not a valid fragment. " + << "Dropping message..." << std::endl; + } + } + } + else + { + if (fragmentDataSize(queue.back()) + fragmentOffset(queue.back()) != offset) + { + if (mVerbose) + { + std::cerr << "# WARNING: Previous fragment(s) have been lost. " + << "Dropping message and clearing queue..." << std::endl; + } + queue.clear(); + } + else + { + queue.push_back(msg); + + if ((flags & 0x1) != 0x1) + { + reassemble = true; + } + } + } + } + + if (reassemble) + { + std::deque& queue = mFragmentQueue[streamID]; + + std::string data; + for (size_t i = 0; i < queue.size(); ++i) + { + mavlink_extended_message_t& mavlink_msg = queue.at(i); + + data.append(reinterpret_cast(&mavlink_msg.extended_payload[0]), + static_cast(mavlink_msg.extended_payload_len)); + } + + mMessages.at(typecode)->ParseFromString(data); + + mMessageAvailable.at(typecode) = true; + + queue.clear(); + + if (mVerbose) + { + std::cerr << "# INFO: Reassembled fragments for message with typename " + << mMessages.at(typecode)->GetTypeName() << " and size " + << mMessages.at(typecode)->ByteSize() + << "." << std::endl; + } + } + + return true; + } + + bool getMessage(std::tr1::shared_ptr& msg) + { + for (size_t i = 0; i < mMessageAvailable.size(); ++i) + { + if (mMessageAvailable.at(i)) + { + msg = mMessages.at(i); + mMessageAvailable.at(i) = false; + + return true; + } + } + + return false; + } + +private: + void registerType(const std::tr1::shared_ptr& msg) + { + mTypeMap[msg->GetTypeName()] = mRegisteredTypeCount; + ++mRegisteredTypeCount; + mMessages.push_back(msg); + mMessageAvailable.push_back(false); + } + + bool validFragment(const mavlink_extended_message_t& msg) const + { + if (msg.base_msg.magic != MAVLINK_STX || + msg.base_msg.len != kExtendedHeaderSize || + msg.base_msg.msgid != MAVLINK_MSG_ID_EXTENDED_MESSAGE) + { + return false; + } + + uint16_t checksum; + checksum = crc_calculate(reinterpret_cast(&msg.base_msg.len), MAVLINK_CORE_HEADER_LEN); + crc_accumulate_buffer(&checksum, reinterpret_cast(&msg.base_msg.payload64), kExtendedHeaderSize); +#if MAVLINK_CRC_EXTRA + static const uint8_t mavlink_message_crcs[256] = MAVLINK_MESSAGE_CRCS; + crc_accumulate(mavlink_message_crcs[msg.base_msg.msgid], &checksum); +#endif + + if (mavlink_ck_a(&(msg.base_msg)) != (uint8_t)(checksum & 0xFF) && + mavlink_ck_b(&(msg.base_msg)) != (uint8_t)(checksum >> 8)) + { + return false; + } + + return true; + } + + unsigned int fragmentDataSize(const mavlink_extended_message_t& msg) const + { + const uint8_t* payload = reinterpret_cast(msg.base_msg.payload64); + + return *(reinterpret_cast(payload + 3)); + } + + unsigned int fragmentOffset(const mavlink_extended_message_t& msg) const + { + const uint8_t* payload = reinterpret_cast(msg.base_msg.payload64); + + return *(reinterpret_cast(payload + 9)); + } + + int mRegisteredTypeCount; + unsigned short mStreamID; + bool mVerbose; + + typedef std::map TypeMap; + TypeMap mTypeMap; + std::vector< std::tr1::shared_ptr > mMessages; + std::vector mMessageAvailable; + + typedef std::map > FragmentQueue; + FragmentQueue mFragmentQueue; + + const int kExtendedHeaderSize; + /** + * Extended header structure + * ========================= + * byte 0 - target_system + * byte 1 - target_component + * byte 2 - extended message id (type code) + * bytes 3-6 - extended payload size in bytes + * byte 7-8 - stream ID + * byte 9-12 - fragment offset + * byte 13 - fragment flags (bit 0 - 1=more fragments, 0=last fragment) + */ + + const int kExtendedPayloadMaxSize; +}; + +} + +#endif diff --git a/mavlink/include/mavlink/v1.0/mavlink_types.h b/mavlink/include/mavlink/v1.0/mavlink_types.h new file mode 100644 index 0000000000..5fbde97f73 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/mavlink_types.h @@ -0,0 +1,158 @@ +#ifndef MAVLINK_TYPES_H_ +#define MAVLINK_TYPES_H_ + +#include + +#ifndef MAVLINK_MAX_PAYLOAD_LEN +// it is possible to override this, but be careful! +#define MAVLINK_MAX_PAYLOAD_LEN 255 ///< Maximum payload length +#endif + +#define MAVLINK_CORE_HEADER_LEN 5 ///< Length of core header (of the comm. layer): message length (1 byte) + message sequence (1 byte) + message system id (1 byte) + message component id (1 byte) + message type id (1 byte) +#define MAVLINK_NUM_HEADER_BYTES (MAVLINK_CORE_HEADER_LEN + 1) ///< Length of all header bytes, including core and checksum +#define MAVLINK_NUM_CHECKSUM_BYTES 2 +#define MAVLINK_NUM_NON_PAYLOAD_BYTES (MAVLINK_NUM_HEADER_BYTES + MAVLINK_NUM_CHECKSUM_BYTES) + +#define MAVLINK_MAX_PACKET_LEN (MAVLINK_MAX_PAYLOAD_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES) ///< Maximum packet length + +#define MAVLINK_MSG_ID_EXTENDED_MESSAGE 255 +#define MAVLINK_EXTENDED_HEADER_LEN 14 + +#if (defined _MSC_VER) | ((defined __APPLE__) & (defined __MACH__)) | (defined __linux__) + /* full fledged 32bit++ OS */ + #define MAVLINK_MAX_EXTENDED_PACKET_LEN 65507 +#else + /* small microcontrollers */ + #define MAVLINK_MAX_EXTENDED_PACKET_LEN 2048 +#endif + +#define MAVLINK_MAX_EXTENDED_PAYLOAD_LEN (MAVLINK_MAX_EXTENDED_PACKET_LEN - MAVLINK_EXTENDED_HEADER_LEN - MAVLINK_NUM_NON_PAYLOAD_BYTES) + +typedef struct param_union { + union { + float param_float; + int32_t param_int32; + uint32_t param_uint32; + uint8_t param_uint8; + uint8_t bytes[4]; + }; + uint8_t type; +} mavlink_param_union_t; + +typedef struct __mavlink_system { + uint8_t sysid; ///< Used by the MAVLink message_xx_send() convenience function + uint8_t compid; ///< Used by the MAVLink message_xx_send() convenience function + uint8_t type; ///< Unused, can be used by user to store the system's type + uint8_t state; ///< Unused, can be used by user to store the system's state + uint8_t mode; ///< Unused, can be used by user to store the system's mode + uint8_t nav_mode; ///< Unused, can be used by user to store the system's navigation mode +} mavlink_system_t; + +typedef struct __mavlink_message { + uint16_t checksum; /// sent at end of packet + uint8_t magic; ///< protocol magic marker + uint8_t len; ///< Length of payload + uint8_t seq; ///< Sequence of packet + uint8_t sysid; ///< ID of message sender system/aircraft + uint8_t compid; ///< ID of the message sender component + uint8_t msgid; ///< ID of message in payload + uint64_t payload64[(MAVLINK_MAX_PAYLOAD_LEN+MAVLINK_NUM_CHECKSUM_BYTES+7)/8]; +} mavlink_message_t; + + +typedef struct __mavlink_extended_message { + mavlink_message_t base_msg; + int32_t extended_payload_len; ///< Length of extended payload if any + uint8_t extended_payload[MAVLINK_MAX_EXTENDED_PAYLOAD_LEN]; +} mavlink_extended_message_t; + + +typedef enum { + MAVLINK_TYPE_CHAR = 0, + MAVLINK_TYPE_UINT8_T = 1, + MAVLINK_TYPE_INT8_T = 2, + MAVLINK_TYPE_UINT16_T = 3, + MAVLINK_TYPE_INT16_T = 4, + MAVLINK_TYPE_UINT32_T = 5, + MAVLINK_TYPE_INT32_T = 6, + MAVLINK_TYPE_UINT64_T = 7, + MAVLINK_TYPE_INT64_T = 8, + MAVLINK_TYPE_FLOAT = 9, + MAVLINK_TYPE_DOUBLE = 10 +} mavlink_message_type_t; + +#define MAVLINK_MAX_FIELDS 64 + +typedef struct __mavlink_field_info { + const char *name; // name of this field + const char *print_format; // printing format hint, or NULL + mavlink_message_type_t type; // type of this field + unsigned int array_length; // if non-zero, field is an array + unsigned int wire_offset; // offset of each field in the payload + unsigned int structure_offset; // offset in a C structure +} mavlink_field_info_t; + +// note that in this structure the order of fields is the order +// in the XML file, not necessary the wire order +typedef struct __mavlink_message_info { + const char *name; // name of the message + unsigned num_fields; // how many fields in this message + mavlink_field_info_t fields[MAVLINK_MAX_FIELDS]; // field information +} mavlink_message_info_t; + +#define _MAV_PAYLOAD(msg) ((const char *)(&((msg)->payload64[0]))) +#define _MAV_PAYLOAD_NON_CONST(msg) ((char *)(&((msg)->payload64[0]))) + +// checksum is immediately after the payload bytes +#define mavlink_ck_a(msg) *((msg)->len + (uint8_t *)_MAV_PAYLOAD_NON_CONST(msg)) +#define mavlink_ck_b(msg) *(((msg)->len+(uint16_t)1) + (uint8_t *)_MAV_PAYLOAD_NON_CONST(msg)) + +typedef enum { + MAVLINK_COMM_0, + MAVLINK_COMM_1, + MAVLINK_COMM_2, + MAVLINK_COMM_3 +} mavlink_channel_t; + +/* + * applications can set MAVLINK_COMM_NUM_BUFFERS to the maximum number + * of buffers they will use. If more are used, then the result will be + * a stack overrun + */ +#ifndef MAVLINK_COMM_NUM_BUFFERS +#if (defined linux) | (defined __linux) | (defined __MACH__) | (defined _WIN32) +# define MAVLINK_COMM_NUM_BUFFERS 16 +#else +# define MAVLINK_COMM_NUM_BUFFERS 4 +#endif +#endif + +typedef enum { + MAVLINK_PARSE_STATE_UNINIT=0, + MAVLINK_PARSE_STATE_IDLE, + MAVLINK_PARSE_STATE_GOT_STX, + MAVLINK_PARSE_STATE_GOT_SEQ, + MAVLINK_PARSE_STATE_GOT_LENGTH, + MAVLINK_PARSE_STATE_GOT_SYSID, + MAVLINK_PARSE_STATE_GOT_COMPID, + MAVLINK_PARSE_STATE_GOT_MSGID, + MAVLINK_PARSE_STATE_GOT_PAYLOAD, + MAVLINK_PARSE_STATE_GOT_CRC1 +} mavlink_parse_state_t; ///< The state machine for the comm parser + +typedef struct __mavlink_status { + uint8_t msg_received; ///< Number of received messages + uint8_t buffer_overrun; ///< Number of buffer overruns + uint8_t parse_error; ///< Number of parse errors + mavlink_parse_state_t parse_state; ///< Parsing state machine + uint8_t packet_idx; ///< Index in current packet + uint8_t current_rx_seq; ///< Sequence number of last packet received + uint8_t current_tx_seq; ///< Sequence number of last packet sent + uint16_t packet_rx_success_count; ///< Received packets + uint16_t packet_rx_drop_count; ///< Number of packet drops +} mavlink_status_t; + +#define MAVLINK_BIG_ENDIAN 0 +#define MAVLINK_LITTLE_ENDIAN 1 + +#endif /* MAVLINK_TYPES_H_ */ diff --git a/mavlink/include/mavlink/v1.0/minimal/mavlink.h b/mavlink/include/mavlink/v1.0/minimal/mavlink.h new file mode 100644 index 0000000000..0a759b6185 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/minimal/mavlink.h @@ -0,0 +1,27 @@ +/** @file + * @brief MAVLink comm protocol built from minimal.xml + * @see http://pixhawk.ethz.ch/software/mavlink + */ +#ifndef MAVLINK_H +#define MAVLINK_H + +#ifndef MAVLINK_STX +#define MAVLINK_STX 254 +#endif + +#ifndef MAVLINK_ENDIAN +#define MAVLINK_ENDIAN MAVLINK_LITTLE_ENDIAN +#endif + +#ifndef MAVLINK_ALIGNED_FIELDS +#define MAVLINK_ALIGNED_FIELDS 1 +#endif + +#ifndef MAVLINK_CRC_EXTRA +#define MAVLINK_CRC_EXTRA 1 +#endif + +#include "version.h" +#include "minimal.h" + +#endif // MAVLINK_H diff --git a/mavlink/include/mavlink/v1.0/minimal/mavlink_msg_heartbeat.h b/mavlink/include/mavlink/v1.0/minimal/mavlink_msg_heartbeat.h new file mode 100644 index 0000000000..3503387070 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/minimal/mavlink_msg_heartbeat.h @@ -0,0 +1,251 @@ +// MESSAGE HEARTBEAT PACKING + +#define MAVLINK_MSG_ID_HEARTBEAT 0 + +typedef struct __mavlink_heartbeat_t +{ + uint32_t custom_mode; ///< A bitfield for use for autopilot-specific flags. + uint8_t type; ///< Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + uint8_t autopilot; ///< Autopilot type / class. defined in MAV_AUTOPILOT ENUM + uint8_t base_mode; ///< System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h + uint8_t system_status; ///< System status flag, see MAV_STATE ENUM + uint8_t mavlink_version; ///< MAVLink version +} mavlink_heartbeat_t; + +#define MAVLINK_MSG_ID_HEARTBEAT_LEN 9 +#define MAVLINK_MSG_ID_0_LEN 9 + + + +#define MAVLINK_MESSAGE_INFO_HEARTBEAT { \ + "HEARTBEAT", \ + 6, \ + { { "custom_mode", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_heartbeat_t, custom_mode) }, \ + { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_heartbeat_t, type) }, \ + { "autopilot", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_heartbeat_t, autopilot) }, \ + { "base_mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_heartbeat_t, base_mode) }, \ + { "system_status", NULL, MAVLINK_TYPE_UINT8_T, 0, 7, offsetof(mavlink_heartbeat_t, system_status) }, \ + { "mavlink_version", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_heartbeat_t, mavlink_version) }, \ + } \ +} + + +/** + * @brief Pack a heartbeat message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + * @param autopilot Autopilot type / class. defined in MAV_AUTOPILOT ENUM + * @param base_mode System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h + * @param custom_mode A bitfield for use for autopilot-specific flags. + * @param system_status System status flag, see MAV_STATE ENUM + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_heartbeat_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t type, uint8_t autopilot, uint8_t base_mode, uint32_t custom_mode, uint8_t system_status) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint32_t(buf, 0, custom_mode); + _mav_put_uint8_t(buf, 4, type); + _mav_put_uint8_t(buf, 5, autopilot); + _mav_put_uint8_t(buf, 6, base_mode); + _mav_put_uint8_t(buf, 7, system_status); + _mav_put_uint8_t(buf, 8, 2); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 9); +#else + mavlink_heartbeat_t packet; + packet.custom_mode = custom_mode; + packet.type = type; + packet.autopilot = autopilot; + packet.base_mode = base_mode; + packet.system_status = system_status; + packet.mavlink_version = 2; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 9); +#endif + + msg->msgid = MAVLINK_MSG_ID_HEARTBEAT; + return mavlink_finalize_message(msg, system_id, component_id, 9, 50); +} + +/** + * @brief Pack a heartbeat message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + * @param autopilot Autopilot type / class. defined in MAV_AUTOPILOT ENUM + * @param base_mode System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h + * @param custom_mode A bitfield for use for autopilot-specific flags. + * @param system_status System status flag, see MAV_STATE ENUM + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_heartbeat_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t type,uint8_t autopilot,uint8_t base_mode,uint32_t custom_mode,uint8_t system_status) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint32_t(buf, 0, custom_mode); + _mav_put_uint8_t(buf, 4, type); + _mav_put_uint8_t(buf, 5, autopilot); + _mav_put_uint8_t(buf, 6, base_mode); + _mav_put_uint8_t(buf, 7, system_status); + _mav_put_uint8_t(buf, 8, 2); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 9); +#else + mavlink_heartbeat_t packet; + packet.custom_mode = custom_mode; + packet.type = type; + packet.autopilot = autopilot; + packet.base_mode = base_mode; + packet.system_status = system_status; + packet.mavlink_version = 2; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 9); +#endif + + msg->msgid = MAVLINK_MSG_ID_HEARTBEAT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 9, 50); +} + +/** + * @brief Encode a heartbeat struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param heartbeat C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_heartbeat_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_heartbeat_t* heartbeat) +{ + return mavlink_msg_heartbeat_pack(system_id, component_id, msg, heartbeat->type, heartbeat->autopilot, heartbeat->base_mode, heartbeat->custom_mode, heartbeat->system_status); +} + +/** + * @brief Send a heartbeat message + * @param chan MAVLink channel to send the message + * + * @param type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + * @param autopilot Autopilot type / class. defined in MAV_AUTOPILOT ENUM + * @param base_mode System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h + * @param custom_mode A bitfield for use for autopilot-specific flags. + * @param system_status System status flag, see MAV_STATE ENUM + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_heartbeat_send(mavlink_channel_t chan, uint8_t type, uint8_t autopilot, uint8_t base_mode, uint32_t custom_mode, uint8_t system_status) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[9]; + _mav_put_uint32_t(buf, 0, custom_mode); + _mav_put_uint8_t(buf, 4, type); + _mav_put_uint8_t(buf, 5, autopilot); + _mav_put_uint8_t(buf, 6, base_mode); + _mav_put_uint8_t(buf, 7, system_status); + _mav_put_uint8_t(buf, 8, 2); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HEARTBEAT, buf, 9, 50); +#else + mavlink_heartbeat_t packet; + packet.custom_mode = custom_mode; + packet.type = type; + packet.autopilot = autopilot; + packet.base_mode = base_mode; + packet.system_status = system_status; + packet.mavlink_version = 2; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HEARTBEAT, (const char *)&packet, 9, 50); +#endif +} + +#endif + +// MESSAGE HEARTBEAT UNPACKING + + +/** + * @brief Get field type from heartbeat message + * + * @return Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) + */ +static inline uint8_t mavlink_msg_heartbeat_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field autopilot from heartbeat message + * + * @return Autopilot type / class. defined in MAV_AUTOPILOT ENUM + */ +static inline uint8_t mavlink_msg_heartbeat_get_autopilot(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field base_mode from heartbeat message + * + * @return System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h + */ +static inline uint8_t mavlink_msg_heartbeat_get_base_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Get field custom_mode from heartbeat message + * + * @return A bitfield for use for autopilot-specific flags. + */ +static inline uint32_t mavlink_msg_heartbeat_get_custom_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field system_status from heartbeat message + * + * @return System status flag, see MAV_STATE ENUM + */ +static inline uint8_t mavlink_msg_heartbeat_get_system_status(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 7); +} + +/** + * @brief Get field mavlink_version from heartbeat message + * + * @return MAVLink version + */ +static inline uint8_t mavlink_msg_heartbeat_get_mavlink_version(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Decode a heartbeat message into a struct + * + * @param msg The message to decode + * @param heartbeat C-struct to decode the message contents into + */ +static inline void mavlink_msg_heartbeat_decode(const mavlink_message_t* msg, mavlink_heartbeat_t* heartbeat) +{ +#if MAVLINK_NEED_BYTE_SWAP + heartbeat->custom_mode = mavlink_msg_heartbeat_get_custom_mode(msg); + heartbeat->type = mavlink_msg_heartbeat_get_type(msg); + heartbeat->autopilot = mavlink_msg_heartbeat_get_autopilot(msg); + heartbeat->base_mode = mavlink_msg_heartbeat_get_base_mode(msg); + heartbeat->system_status = mavlink_msg_heartbeat_get_system_status(msg); + heartbeat->mavlink_version = mavlink_msg_heartbeat_get_mavlink_version(msg); +#else + memcpy(heartbeat, _MAV_PAYLOAD(msg), 9); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/minimal/minimal.h b/mavlink/include/mavlink/v1.0/minimal/minimal.h new file mode 100644 index 0000000000..30c6c1cdc6 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/minimal/minimal.h @@ -0,0 +1,150 @@ +/** @file + * @brief MAVLink comm protocol generated from minimal.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef MINIMAL_H +#define MINIMAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_MINIMAL + + + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +// ENUM DEFINITIONS + + +/** @brief Micro air vehicle / autopilot classes. This identifies the individual model. */ +#ifndef HAVE_ENUM_MAV_AUTOPILOT +#define HAVE_ENUM_MAV_AUTOPILOT +enum MAV_AUTOPILOT +{ + MAV_AUTOPILOT_GENERIC=0, /* Generic autopilot, full support for everything | */ + MAV_AUTOPILOT_PIXHAWK=1, /* PIXHAWK autopilot, http://pixhawk.ethz.ch | */ + MAV_AUTOPILOT_SLUGS=2, /* SLUGS autopilot, http://slugsuav.soe.ucsc.edu | */ + MAV_AUTOPILOT_ARDUPILOTMEGA=3, /* ArduPilotMega / ArduCopter, http://diydrones.com | */ + MAV_AUTOPILOT_OPENPILOT=4, /* OpenPilot, http://openpilot.org | */ + MAV_AUTOPILOT_GENERIC_WAYPOINTS_ONLY=5, /* Generic autopilot only supporting simple waypoints | */ + MAV_AUTOPILOT_GENERIC_WAYPOINTS_AND_SIMPLE_NAVIGATION_ONLY=6, /* Generic autopilot supporting waypoints and other simple navigation commands | */ + MAV_AUTOPILOT_GENERIC_MISSION_FULL=7, /* Generic autopilot supporting the full mission command set | */ + MAV_AUTOPILOT_INVALID=8, /* No valid autopilot, e.g. a GCS or other MAVLink component | */ + MAV_AUTOPILOT_PPZ=9, /* PPZ UAV - http://nongnu.org/paparazzi | */ + MAV_AUTOPILOT_UDB=10, /* UAV Dev Board | */ + MAV_AUTOPILOT_FP=11, /* FlexiPilot | */ + MAV_AUTOPILOT_ENUM_END=12, /* | */ +}; +#endif + +/** @brief */ +#ifndef HAVE_ENUM_MAV_TYPE +#define HAVE_ENUM_MAV_TYPE +enum MAV_TYPE +{ + MAV_TYPE_GENERIC=0, /* Generic micro air vehicle. | */ + MAV_TYPE_FIXED_WING=1, /* Fixed wing aircraft. | */ + MAV_TYPE_QUADROTOR=2, /* Quadrotor | */ + MAV_TYPE_COAXIAL=3, /* Coaxial helicopter | */ + MAV_TYPE_HELICOPTER=4, /* Normal helicopter with tail rotor. | */ + MAV_TYPE_ANTENNA_TRACKER=5, /* Ground installation | */ + MAV_TYPE_GCS=6, /* Operator control unit / ground control station | */ + MAV_TYPE_AIRSHIP=7, /* Airship, controlled | */ + MAV_TYPE_FREE_BALLOON=8, /* Free balloon, uncontrolled | */ + MAV_TYPE_ROCKET=9, /* Rocket | */ + MAV_TYPE_GROUND_ROVER=10, /* Ground rover | */ + MAV_TYPE_SURFACE_BOAT=11, /* Surface vessel, boat, ship | */ + MAV_TYPE_SUBMARINE=12, /* Submarine | */ + MAV_TYPE_HEXAROTOR=13, /* Hexarotor | */ + MAV_TYPE_OCTOROTOR=14, /* Octorotor | */ + MAV_TYPE_TRICOPTER=15, /* Octorotor | */ + MAV_TYPE_FLAPPING_WING=16, /* Flapping wing | */ + MAV_TYPE_ENUM_END=17, /* | */ +}; +#endif + +/** @brief These flags encode the MAV mode. */ +#ifndef HAVE_ENUM_MAV_MODE_FLAG +#define HAVE_ENUM_MAV_MODE_FLAG +enum MAV_MODE_FLAG +{ + MAV_MODE_FLAG_CUSTOM_MODE_ENABLED=1, /* 0b00000001 Reserved for future use. | */ + MAV_MODE_FLAG_TEST_ENABLED=2, /* 0b00000010 system has a test mode enabled. This flag is intended for temporary system tests and should not be used for stable implementations. | */ + MAV_MODE_FLAG_AUTO_ENABLED=4, /* 0b00000100 autonomous mode enabled, system finds its own goal positions. Guided flag can be set or not, depends on the actual implementation. | */ + MAV_MODE_FLAG_GUIDED_ENABLED=8, /* 0b00001000 guided mode enabled, system flies MISSIONs / mission items. | */ + MAV_MODE_FLAG_STABILIZE_ENABLED=16, /* 0b00010000 system stabilizes electronically its attitude (and optionally position). It needs however further control inputs to move around. | */ + MAV_MODE_FLAG_HIL_ENABLED=32, /* 0b00100000 hardware in the loop simulation. All motors / actuators are blocked, but internal software is full operational. | */ + MAV_MODE_FLAG_MANUAL_INPUT_ENABLED=64, /* 0b01000000 remote control input is enabled. | */ + MAV_MODE_FLAG_SAFETY_ARMED=128, /* 0b10000000 MAV safety set to armed. Motors are enabled / running / can start. Ready to fly. | */ + MAV_MODE_FLAG_ENUM_END=129, /* | */ +}; +#endif + +/** @brief These values encode the bit positions of the decode position. These values can be used to read the value of a flag bit by combining the base_mode variable with AND with the flag position value. The result will be either 0 or 1, depending on if the flag is set or not. */ +#ifndef HAVE_ENUM_MAV_MODE_FLAG_DECODE_POSITION +#define HAVE_ENUM_MAV_MODE_FLAG_DECODE_POSITION +enum MAV_MODE_FLAG_DECODE_POSITION +{ + MAV_MODE_FLAG_DECODE_POSITION_CUSTOM_MODE=1, /* Eighth bit: 00000001 | */ + MAV_MODE_FLAG_DECODE_POSITION_TEST=2, /* Seventh bit: 00000010 | */ + MAV_MODE_FLAG_DECODE_POSITION_AUTO=4, /* Sixt bit: 00000100 | */ + MAV_MODE_FLAG_DECODE_POSITION_GUIDED=8, /* Fifth bit: 00001000 | */ + MAV_MODE_FLAG_DECODE_POSITION_STABILIZE=16, /* Fourth bit: 00010000 | */ + MAV_MODE_FLAG_DECODE_POSITION_HIL=32, /* Third bit: 00100000 | */ + MAV_MODE_FLAG_DECODE_POSITION_MANUAL=64, /* Second bit: 01000000 | */ + MAV_MODE_FLAG_DECODE_POSITION_SAFETY=128, /* First bit: 10000000 | */ + MAV_MODE_FLAG_DECODE_POSITION_ENUM_END=129, /* | */ +}; +#endif + +/** @brief */ +#ifndef HAVE_ENUM_MAV_STATE +#define HAVE_ENUM_MAV_STATE +enum MAV_STATE +{ + MAV_STATE_UNINIT=0, /* Uninitialized system, state is unknown. | */ + MAV_STATE_BOOT=1, /* System is booting up. | */ + MAV_STATE_CALIBRATING=2, /* System is calibrating and not flight-ready. | */ + MAV_STATE_STANDBY=3, /* System is grounded and on standby. It can be launched any time. | */ + MAV_STATE_ACTIVE=4, /* System is active and might be already airborne. Motors are engaged. | */ + MAV_STATE_CRITICAL=5, /* System is in a non-normal flight mode. It can however still navigate. | */ + MAV_STATE_EMERGENCY=6, /* System is in a non-normal flight mode. It lost control over parts or over the whole airframe. It is in mayday and going down. | */ + MAV_STATE_POWEROFF=7, /* System just initialized its power-down sequence, will shut down now. | */ + MAV_STATE_ENUM_END=8, /* | */ +}; +#endif + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_heartbeat.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // MINIMAL_H diff --git a/mavlink/include/mavlink/v1.0/minimal/testsuite.h b/mavlink/include/mavlink/v1.0/minimal/testsuite.h new file mode 100644 index 0000000000..1758c912cf --- /dev/null +++ b/mavlink/include/mavlink/v1.0/minimal/testsuite.h @@ -0,0 +1,88 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from minimal.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef MINIMAL_TESTSUITE_H +#define MINIMAL_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL + +static void mavlink_test_minimal(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + + mavlink_test_minimal(system_id, component_id, last_msg); +} +#endif + + + + +static void mavlink_test_heartbeat(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_heartbeat_t packet_in = { + 963497464, + 17, + 84, + 151, + 218, + 2, + }; + mavlink_heartbeat_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.custom_mode = packet_in.custom_mode; + packet1.type = packet_in.type; + packet1.autopilot = packet_in.autopilot; + packet1.base_mode = packet_in.base_mode; + packet1.system_status = packet_in.system_status; + packet1.mavlink_version = packet_in.mavlink_version; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_heartbeat_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_heartbeat_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_heartbeat_pack(system_id, component_id, &msg , packet1.type , packet1.autopilot , packet1.base_mode , packet1.custom_mode , packet1.system_status ); + mavlink_msg_heartbeat_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_heartbeat_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.type , packet1.autopilot , packet1.base_mode , packet1.custom_mode , packet1.system_status ); + mavlink_msg_heartbeat_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; imsgid = MAVLINK_MSG_ID_ATTITUDE_CONTROL; + return mavlink_finalize_message(msg, system_id, component_id, 21, 254); +} + +/** + * @brief Pack a attitude_control message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system to be controlled + * @param roll roll + * @param pitch pitch + * @param yaw yaw + * @param thrust thrust + * @param roll_manual roll control enabled auto:0, manual:1 + * @param pitch_manual pitch auto:0, manual:1 + * @param yaw_manual yaw auto:0, manual:1 + * @param thrust_manual thrust auto:0, manual:1 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_attitude_control_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,float roll,float pitch,float yaw,float thrust,uint8_t roll_manual,uint8_t pitch_manual,uint8_t yaw_manual,uint8_t thrust_manual) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, thrust); + _mav_put_uint8_t(buf, 16, target); + _mav_put_uint8_t(buf, 17, roll_manual); + _mav_put_uint8_t(buf, 18, pitch_manual); + _mav_put_uint8_t(buf, 19, yaw_manual); + _mav_put_uint8_t(buf, 20, thrust_manual); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 21); +#else + mavlink_attitude_control_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + packet.target = target; + packet.roll_manual = roll_manual; + packet.pitch_manual = pitch_manual; + packet.yaw_manual = yaw_manual; + packet.thrust_manual = thrust_manual; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 21); +#endif + + msg->msgid = MAVLINK_MSG_ID_ATTITUDE_CONTROL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 21, 254); +} + +/** + * @brief Encode a attitude_control struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param attitude_control C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_attitude_control_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_attitude_control_t* attitude_control) +{ + return mavlink_msg_attitude_control_pack(system_id, component_id, msg, attitude_control->target, attitude_control->roll, attitude_control->pitch, attitude_control->yaw, attitude_control->thrust, attitude_control->roll_manual, attitude_control->pitch_manual, attitude_control->yaw_manual, attitude_control->thrust_manual); +} + +/** + * @brief Send a attitude_control message + * @param chan MAVLink channel to send the message + * + * @param target The system to be controlled + * @param roll roll + * @param pitch pitch + * @param yaw yaw + * @param thrust thrust + * @param roll_manual roll control enabled auto:0, manual:1 + * @param pitch_manual pitch auto:0, manual:1 + * @param yaw_manual yaw auto:0, manual:1 + * @param thrust_manual thrust auto:0, manual:1 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_attitude_control_send(mavlink_channel_t chan, uint8_t target, float roll, float pitch, float yaw, float thrust, uint8_t roll_manual, uint8_t pitch_manual, uint8_t yaw_manual, uint8_t thrust_manual) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[21]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, thrust); + _mav_put_uint8_t(buf, 16, target); + _mav_put_uint8_t(buf, 17, roll_manual); + _mav_put_uint8_t(buf, 18, pitch_manual); + _mav_put_uint8_t(buf, 19, yaw_manual); + _mav_put_uint8_t(buf, 20, thrust_manual); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ATTITUDE_CONTROL, buf, 21, 254); +#else + mavlink_attitude_control_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.thrust = thrust; + packet.target = target; + packet.roll_manual = roll_manual; + packet.pitch_manual = pitch_manual; + packet.yaw_manual = yaw_manual; + packet.thrust_manual = thrust_manual; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ATTITUDE_CONTROL, (const char *)&packet, 21, 254); +#endif +} + +#endif + +// MESSAGE ATTITUDE_CONTROL UNPACKING + + +/** + * @brief Get field target from attitude_control message + * + * @return The system to be controlled + */ +static inline uint8_t mavlink_msg_attitude_control_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 16); +} + +/** + * @brief Get field roll from attitude_control message + * + * @return roll + */ +static inline float mavlink_msg_attitude_control_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field pitch from attitude_control message + * + * @return pitch + */ +static inline float mavlink_msg_attitude_control_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field yaw from attitude_control message + * + * @return yaw + */ +static inline float mavlink_msg_attitude_control_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field thrust from attitude_control message + * + * @return thrust + */ +static inline float mavlink_msg_attitude_control_get_thrust(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field roll_manual from attitude_control message + * + * @return roll control enabled auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_attitude_control_get_roll_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 17); +} + +/** + * @brief Get field pitch_manual from attitude_control message + * + * @return pitch auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_attitude_control_get_pitch_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 18); +} + +/** + * @brief Get field yaw_manual from attitude_control message + * + * @return yaw auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_attitude_control_get_yaw_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 19); +} + +/** + * @brief Get field thrust_manual from attitude_control message + * + * @return thrust auto:0, manual:1 + */ +static inline uint8_t mavlink_msg_attitude_control_get_thrust_manual(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 20); +} + +/** + * @brief Decode a attitude_control message into a struct + * + * @param msg The message to decode + * @param attitude_control C-struct to decode the message contents into + */ +static inline void mavlink_msg_attitude_control_decode(const mavlink_message_t* msg, mavlink_attitude_control_t* attitude_control) +{ +#if MAVLINK_NEED_BYTE_SWAP + attitude_control->roll = mavlink_msg_attitude_control_get_roll(msg); + attitude_control->pitch = mavlink_msg_attitude_control_get_pitch(msg); + attitude_control->yaw = mavlink_msg_attitude_control_get_yaw(msg); + attitude_control->thrust = mavlink_msg_attitude_control_get_thrust(msg); + attitude_control->target = mavlink_msg_attitude_control_get_target(msg); + attitude_control->roll_manual = mavlink_msg_attitude_control_get_roll_manual(msg); + attitude_control->pitch_manual = mavlink_msg_attitude_control_get_pitch_manual(msg); + attitude_control->yaw_manual = mavlink_msg_attitude_control_get_yaw_manual(msg); + attitude_control->thrust_manual = mavlink_msg_attitude_control_get_thrust_manual(msg); +#else + memcpy(attitude_control, _MAV_PAYLOAD(msg), 21); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_brief_feature.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_brief_feature.h new file mode 100644 index 0000000000..cde782b484 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_brief_feature.h @@ -0,0 +1,292 @@ +// MESSAGE BRIEF_FEATURE PACKING + +#define MAVLINK_MSG_ID_BRIEF_FEATURE 195 + +typedef struct __mavlink_brief_feature_t +{ + float x; ///< x position in m + float y; ///< y position in m + float z; ///< z position in m + float response; ///< Harris operator response at this location + uint16_t size; ///< Size in pixels + uint16_t orientation; ///< Orientation + uint8_t orientation_assignment; ///< Orientation assignment 0: false, 1:true + uint8_t descriptor[32]; ///< Descriptor +} mavlink_brief_feature_t; + +#define MAVLINK_MSG_ID_BRIEF_FEATURE_LEN 53 +#define MAVLINK_MSG_ID_195_LEN 53 + +#define MAVLINK_MSG_BRIEF_FEATURE_FIELD_DESCRIPTOR_LEN 32 + +#define MAVLINK_MESSAGE_INFO_BRIEF_FEATURE { \ + "BRIEF_FEATURE", \ + 8, \ + { { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_brief_feature_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_brief_feature_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_brief_feature_t, z) }, \ + { "response", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_brief_feature_t, response) }, \ + { "size", NULL, MAVLINK_TYPE_UINT16_T, 0, 16, offsetof(mavlink_brief_feature_t, size) }, \ + { "orientation", NULL, MAVLINK_TYPE_UINT16_T, 0, 18, offsetof(mavlink_brief_feature_t, orientation) }, \ + { "orientation_assignment", NULL, MAVLINK_TYPE_UINT8_T, 0, 20, offsetof(mavlink_brief_feature_t, orientation_assignment) }, \ + { "descriptor", NULL, MAVLINK_TYPE_UINT8_T, 32, 21, offsetof(mavlink_brief_feature_t, descriptor) }, \ + } \ +} + + +/** + * @brief Pack a brief_feature message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param x x position in m + * @param y y position in m + * @param z z position in m + * @param orientation_assignment Orientation assignment 0: false, 1:true + * @param size Size in pixels + * @param orientation Orientation + * @param descriptor Descriptor + * @param response Harris operator response at this location + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_brief_feature_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float x, float y, float z, uint8_t orientation_assignment, uint16_t size, uint16_t orientation, const uint8_t *descriptor, float response) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[53]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, response); + _mav_put_uint16_t(buf, 16, size); + _mav_put_uint16_t(buf, 18, orientation); + _mav_put_uint8_t(buf, 20, orientation_assignment); + _mav_put_uint8_t_array(buf, 21, descriptor, 32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 53); +#else + mavlink_brief_feature_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.response = response; + packet.size = size; + packet.orientation = orientation; + packet.orientation_assignment = orientation_assignment; + mav_array_memcpy(packet.descriptor, descriptor, sizeof(uint8_t)*32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 53); +#endif + + msg->msgid = MAVLINK_MSG_ID_BRIEF_FEATURE; + return mavlink_finalize_message(msg, system_id, component_id, 53, 88); +} + +/** + * @brief Pack a brief_feature message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param x x position in m + * @param y y position in m + * @param z z position in m + * @param orientation_assignment Orientation assignment 0: false, 1:true + * @param size Size in pixels + * @param orientation Orientation + * @param descriptor Descriptor + * @param response Harris operator response at this location + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_brief_feature_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float x,float y,float z,uint8_t orientation_assignment,uint16_t size,uint16_t orientation,const uint8_t *descriptor,float response) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[53]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, response); + _mav_put_uint16_t(buf, 16, size); + _mav_put_uint16_t(buf, 18, orientation); + _mav_put_uint8_t(buf, 20, orientation_assignment); + _mav_put_uint8_t_array(buf, 21, descriptor, 32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 53); +#else + mavlink_brief_feature_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.response = response; + packet.size = size; + packet.orientation = orientation; + packet.orientation_assignment = orientation_assignment; + mav_array_memcpy(packet.descriptor, descriptor, sizeof(uint8_t)*32); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 53); +#endif + + msg->msgid = MAVLINK_MSG_ID_BRIEF_FEATURE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 53, 88); +} + +/** + * @brief Encode a brief_feature struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param brief_feature C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_brief_feature_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_brief_feature_t* brief_feature) +{ + return mavlink_msg_brief_feature_pack(system_id, component_id, msg, brief_feature->x, brief_feature->y, brief_feature->z, brief_feature->orientation_assignment, brief_feature->size, brief_feature->orientation, brief_feature->descriptor, brief_feature->response); +} + +/** + * @brief Send a brief_feature message + * @param chan MAVLink channel to send the message + * + * @param x x position in m + * @param y y position in m + * @param z z position in m + * @param orientation_assignment Orientation assignment 0: false, 1:true + * @param size Size in pixels + * @param orientation Orientation + * @param descriptor Descriptor + * @param response Harris operator response at this location + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_brief_feature_send(mavlink_channel_t chan, float x, float y, float z, uint8_t orientation_assignment, uint16_t size, uint16_t orientation, const uint8_t *descriptor, float response) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[53]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, response); + _mav_put_uint16_t(buf, 16, size); + _mav_put_uint16_t(buf, 18, orientation); + _mav_put_uint8_t(buf, 20, orientation_assignment); + _mav_put_uint8_t_array(buf, 21, descriptor, 32); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_BRIEF_FEATURE, buf, 53, 88); +#else + mavlink_brief_feature_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.response = response; + packet.size = size; + packet.orientation = orientation; + packet.orientation_assignment = orientation_assignment; + mav_array_memcpy(packet.descriptor, descriptor, sizeof(uint8_t)*32); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_BRIEF_FEATURE, (const char *)&packet, 53, 88); +#endif +} + +#endif + +// MESSAGE BRIEF_FEATURE UNPACKING + + +/** + * @brief Get field x from brief_feature message + * + * @return x position in m + */ +static inline float mavlink_msg_brief_feature_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field y from brief_feature message + * + * @return y position in m + */ +static inline float mavlink_msg_brief_feature_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field z from brief_feature message + * + * @return z position in m + */ +static inline float mavlink_msg_brief_feature_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field orientation_assignment from brief_feature message + * + * @return Orientation assignment 0: false, 1:true + */ +static inline uint8_t mavlink_msg_brief_feature_get_orientation_assignment(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 20); +} + +/** + * @brief Get field size from brief_feature message + * + * @return Size in pixels + */ +static inline uint16_t mavlink_msg_brief_feature_get_size(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 16); +} + +/** + * @brief Get field orientation from brief_feature message + * + * @return Orientation + */ +static inline uint16_t mavlink_msg_brief_feature_get_orientation(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 18); +} + +/** + * @brief Get field descriptor from brief_feature message + * + * @return Descriptor + */ +static inline uint16_t mavlink_msg_brief_feature_get_descriptor(const mavlink_message_t* msg, uint8_t *descriptor) +{ + return _MAV_RETURN_uint8_t_array(msg, descriptor, 32, 21); +} + +/** + * @brief Get field response from brief_feature message + * + * @return Harris operator response at this location + */ +static inline float mavlink_msg_brief_feature_get_response(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Decode a brief_feature message into a struct + * + * @param msg The message to decode + * @param brief_feature C-struct to decode the message contents into + */ +static inline void mavlink_msg_brief_feature_decode(const mavlink_message_t* msg, mavlink_brief_feature_t* brief_feature) +{ +#if MAVLINK_NEED_BYTE_SWAP + brief_feature->x = mavlink_msg_brief_feature_get_x(msg); + brief_feature->y = mavlink_msg_brief_feature_get_y(msg); + brief_feature->z = mavlink_msg_brief_feature_get_z(msg); + brief_feature->response = mavlink_msg_brief_feature_get_response(msg); + brief_feature->size = mavlink_msg_brief_feature_get_size(msg); + brief_feature->orientation = mavlink_msg_brief_feature_get_orientation(msg); + brief_feature->orientation_assignment = mavlink_msg_brief_feature_get_orientation_assignment(msg); + mavlink_msg_brief_feature_get_descriptor(msg, brief_feature->descriptor); +#else + memcpy(brief_feature, _MAV_PAYLOAD(msg), 53); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_data_transmission_handshake.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_data_transmission_handshake.h new file mode 100644 index 0000000000..d3ca73f12d --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_data_transmission_handshake.h @@ -0,0 +1,276 @@ +// MESSAGE DATA_TRANSMISSION_HANDSHAKE PACKING + +#define MAVLINK_MSG_ID_DATA_TRANSMISSION_HANDSHAKE 193 + +typedef struct __mavlink_data_transmission_handshake_t +{ + uint32_t size; ///< total data size in bytes (set on ACK only) + uint16_t width; ///< Width of a matrix or image + uint16_t height; ///< Height of a matrix or image + uint8_t type; ///< type of requested/acknowledged data (as defined in ENUM DATA_TYPES in mavlink/include/mavlink_types.h) + uint8_t packets; ///< number of packets beeing sent (set on ACK only) + uint8_t payload; ///< payload size per packet (normally 253 byte, see DATA field size in message ENCAPSULATED_DATA) (set on ACK only) + uint8_t jpg_quality; ///< JPEG quality out of [1,100] +} mavlink_data_transmission_handshake_t; + +#define MAVLINK_MSG_ID_DATA_TRANSMISSION_HANDSHAKE_LEN 12 +#define MAVLINK_MSG_ID_193_LEN 12 + + + +#define MAVLINK_MESSAGE_INFO_DATA_TRANSMISSION_HANDSHAKE { \ + "DATA_TRANSMISSION_HANDSHAKE", \ + 7, \ + { { "size", NULL, MAVLINK_TYPE_UINT32_T, 0, 0, offsetof(mavlink_data_transmission_handshake_t, size) }, \ + { "width", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_data_transmission_handshake_t, width) }, \ + { "height", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_data_transmission_handshake_t, height) }, \ + { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_data_transmission_handshake_t, type) }, \ + { "packets", NULL, MAVLINK_TYPE_UINT8_T, 0, 9, offsetof(mavlink_data_transmission_handshake_t, packets) }, \ + { "payload", NULL, MAVLINK_TYPE_UINT8_T, 0, 10, offsetof(mavlink_data_transmission_handshake_t, payload) }, \ + { "jpg_quality", NULL, MAVLINK_TYPE_UINT8_T, 0, 11, offsetof(mavlink_data_transmission_handshake_t, jpg_quality) }, \ + } \ +} + + +/** + * @brief Pack a data_transmission_handshake message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param type type of requested/acknowledged data (as defined in ENUM DATA_TYPES in mavlink/include/mavlink_types.h) + * @param size total data size in bytes (set on ACK only) + * @param width Width of a matrix or image + * @param height Height of a matrix or image + * @param packets number of packets beeing sent (set on ACK only) + * @param payload payload size per packet (normally 253 byte, see DATA field size in message ENCAPSULATED_DATA) (set on ACK only) + * @param jpg_quality JPEG quality out of [1,100] + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_data_transmission_handshake_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t type, uint32_t size, uint16_t width, uint16_t height, uint8_t packets, uint8_t payload, uint8_t jpg_quality) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint32_t(buf, 0, size); + _mav_put_uint16_t(buf, 4, width); + _mav_put_uint16_t(buf, 6, height); + _mav_put_uint8_t(buf, 8, type); + _mav_put_uint8_t(buf, 9, packets); + _mav_put_uint8_t(buf, 10, payload); + _mav_put_uint8_t(buf, 11, jpg_quality); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_data_transmission_handshake_t packet; + packet.size = size; + packet.width = width; + packet.height = height; + packet.type = type; + packet.packets = packets; + packet.payload = payload; + packet.jpg_quality = jpg_quality; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_DATA_TRANSMISSION_HANDSHAKE; + return mavlink_finalize_message(msg, system_id, component_id, 12, 23); +} + +/** + * @brief Pack a data_transmission_handshake message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param type type of requested/acknowledged data (as defined in ENUM DATA_TYPES in mavlink/include/mavlink_types.h) + * @param size total data size in bytes (set on ACK only) + * @param width Width of a matrix or image + * @param height Height of a matrix or image + * @param packets number of packets beeing sent (set on ACK only) + * @param payload payload size per packet (normally 253 byte, see DATA field size in message ENCAPSULATED_DATA) (set on ACK only) + * @param jpg_quality JPEG quality out of [1,100] + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_data_transmission_handshake_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t type,uint32_t size,uint16_t width,uint16_t height,uint8_t packets,uint8_t payload,uint8_t jpg_quality) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint32_t(buf, 0, size); + _mav_put_uint16_t(buf, 4, width); + _mav_put_uint16_t(buf, 6, height); + _mav_put_uint8_t(buf, 8, type); + _mav_put_uint8_t(buf, 9, packets); + _mav_put_uint8_t(buf, 10, payload); + _mav_put_uint8_t(buf, 11, jpg_quality); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_data_transmission_handshake_t packet; + packet.size = size; + packet.width = width; + packet.height = height; + packet.type = type; + packet.packets = packets; + packet.payload = payload; + packet.jpg_quality = jpg_quality; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_DATA_TRANSMISSION_HANDSHAKE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12, 23); +} + +/** + * @brief Encode a data_transmission_handshake struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param data_transmission_handshake C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_data_transmission_handshake_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_data_transmission_handshake_t* data_transmission_handshake) +{ + return mavlink_msg_data_transmission_handshake_pack(system_id, component_id, msg, data_transmission_handshake->type, data_transmission_handshake->size, data_transmission_handshake->width, data_transmission_handshake->height, data_transmission_handshake->packets, data_transmission_handshake->payload, data_transmission_handshake->jpg_quality); +} + +/** + * @brief Send a data_transmission_handshake message + * @param chan MAVLink channel to send the message + * + * @param type type of requested/acknowledged data (as defined in ENUM DATA_TYPES in mavlink/include/mavlink_types.h) + * @param size total data size in bytes (set on ACK only) + * @param width Width of a matrix or image + * @param height Height of a matrix or image + * @param packets number of packets beeing sent (set on ACK only) + * @param payload payload size per packet (normally 253 byte, see DATA field size in message ENCAPSULATED_DATA) (set on ACK only) + * @param jpg_quality JPEG quality out of [1,100] + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_data_transmission_handshake_send(mavlink_channel_t chan, uint8_t type, uint32_t size, uint16_t width, uint16_t height, uint8_t packets, uint8_t payload, uint8_t jpg_quality) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_uint32_t(buf, 0, size); + _mav_put_uint16_t(buf, 4, width); + _mav_put_uint16_t(buf, 6, height); + _mav_put_uint8_t(buf, 8, type); + _mav_put_uint8_t(buf, 9, packets); + _mav_put_uint8_t(buf, 10, payload); + _mav_put_uint8_t(buf, 11, jpg_quality); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DATA_TRANSMISSION_HANDSHAKE, buf, 12, 23); +#else + mavlink_data_transmission_handshake_t packet; + packet.size = size; + packet.width = width; + packet.height = height; + packet.type = type; + packet.packets = packets; + packet.payload = payload; + packet.jpg_quality = jpg_quality; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DATA_TRANSMISSION_HANDSHAKE, (const char *)&packet, 12, 23); +#endif +} + +#endif + +// MESSAGE DATA_TRANSMISSION_HANDSHAKE UNPACKING + + +/** + * @brief Get field type from data_transmission_handshake message + * + * @return type of requested/acknowledged data (as defined in ENUM DATA_TYPES in mavlink/include/mavlink_types.h) + */ +static inline uint8_t mavlink_msg_data_transmission_handshake_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Get field size from data_transmission_handshake message + * + * @return total data size in bytes (set on ACK only) + */ +static inline uint32_t mavlink_msg_data_transmission_handshake_get_size(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 0); +} + +/** + * @brief Get field width from data_transmission_handshake message + * + * @return Width of a matrix or image + */ +static inline uint16_t mavlink_msg_data_transmission_handshake_get_width(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field height from data_transmission_handshake message + * + * @return Height of a matrix or image + */ +static inline uint16_t mavlink_msg_data_transmission_handshake_get_height(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field packets from data_transmission_handshake message + * + * @return number of packets beeing sent (set on ACK only) + */ +static inline uint8_t mavlink_msg_data_transmission_handshake_get_packets(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 9); +} + +/** + * @brief Get field payload from data_transmission_handshake message + * + * @return payload size per packet (normally 253 byte, see DATA field size in message ENCAPSULATED_DATA) (set on ACK only) + */ +static inline uint8_t mavlink_msg_data_transmission_handshake_get_payload(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 10); +} + +/** + * @brief Get field jpg_quality from data_transmission_handshake message + * + * @return JPEG quality out of [1,100] + */ +static inline uint8_t mavlink_msg_data_transmission_handshake_get_jpg_quality(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 11); +} + +/** + * @brief Decode a data_transmission_handshake message into a struct + * + * @param msg The message to decode + * @param data_transmission_handshake C-struct to decode the message contents into + */ +static inline void mavlink_msg_data_transmission_handshake_decode(const mavlink_message_t* msg, mavlink_data_transmission_handshake_t* data_transmission_handshake) +{ +#if MAVLINK_NEED_BYTE_SWAP + data_transmission_handshake->size = mavlink_msg_data_transmission_handshake_get_size(msg); + data_transmission_handshake->width = mavlink_msg_data_transmission_handshake_get_width(msg); + data_transmission_handshake->height = mavlink_msg_data_transmission_handshake_get_height(msg); + data_transmission_handshake->type = mavlink_msg_data_transmission_handshake_get_type(msg); + data_transmission_handshake->packets = mavlink_msg_data_transmission_handshake_get_packets(msg); + data_transmission_handshake->payload = mavlink_msg_data_transmission_handshake_get_payload(msg); + data_transmission_handshake->jpg_quality = mavlink_msg_data_transmission_handshake_get_jpg_quality(msg); +#else + memcpy(data_transmission_handshake, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_encapsulated_data.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_encapsulated_data.h new file mode 100644 index 0000000000..e07be29528 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_encapsulated_data.h @@ -0,0 +1,160 @@ +// MESSAGE ENCAPSULATED_DATA PACKING + +#define MAVLINK_MSG_ID_ENCAPSULATED_DATA 194 + +typedef struct __mavlink_encapsulated_data_t +{ + uint16_t seqnr; ///< sequence number (starting with 0 on every transmission) + uint8_t data[253]; ///< image data bytes +} mavlink_encapsulated_data_t; + +#define MAVLINK_MSG_ID_ENCAPSULATED_DATA_LEN 255 +#define MAVLINK_MSG_ID_194_LEN 255 + +#define MAVLINK_MSG_ENCAPSULATED_DATA_FIELD_DATA_LEN 253 + +#define MAVLINK_MESSAGE_INFO_ENCAPSULATED_DATA { \ + "ENCAPSULATED_DATA", \ + 2, \ + { { "seqnr", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_encapsulated_data_t, seqnr) }, \ + { "data", NULL, MAVLINK_TYPE_UINT8_T, 253, 2, offsetof(mavlink_encapsulated_data_t, data) }, \ + } \ +} + + +/** + * @brief Pack a encapsulated_data message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param seqnr sequence number (starting with 0 on every transmission) + * @param data image data bytes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_encapsulated_data_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t seqnr, const uint8_t *data) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[255]; + _mav_put_uint16_t(buf, 0, seqnr); + _mav_put_uint8_t_array(buf, 2, data, 253); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 255); +#else + mavlink_encapsulated_data_t packet; + packet.seqnr = seqnr; + mav_array_memcpy(packet.data, data, sizeof(uint8_t)*253); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 255); +#endif + + msg->msgid = MAVLINK_MSG_ID_ENCAPSULATED_DATA; + return mavlink_finalize_message(msg, system_id, component_id, 255, 223); +} + +/** + * @brief Pack a encapsulated_data message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param seqnr sequence number (starting with 0 on every transmission) + * @param data image data bytes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_encapsulated_data_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t seqnr,const uint8_t *data) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[255]; + _mav_put_uint16_t(buf, 0, seqnr); + _mav_put_uint8_t_array(buf, 2, data, 253); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 255); +#else + mavlink_encapsulated_data_t packet; + packet.seqnr = seqnr; + mav_array_memcpy(packet.data, data, sizeof(uint8_t)*253); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 255); +#endif + + msg->msgid = MAVLINK_MSG_ID_ENCAPSULATED_DATA; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 255, 223); +} + +/** + * @brief Encode a encapsulated_data struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param encapsulated_data C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_encapsulated_data_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_encapsulated_data_t* encapsulated_data) +{ + return mavlink_msg_encapsulated_data_pack(system_id, component_id, msg, encapsulated_data->seqnr, encapsulated_data->data); +} + +/** + * @brief Send a encapsulated_data message + * @param chan MAVLink channel to send the message + * + * @param seqnr sequence number (starting with 0 on every transmission) + * @param data image data bytes + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_encapsulated_data_send(mavlink_channel_t chan, uint16_t seqnr, const uint8_t *data) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[255]; + _mav_put_uint16_t(buf, 0, seqnr); + _mav_put_uint8_t_array(buf, 2, data, 253); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ENCAPSULATED_DATA, buf, 255, 223); +#else + mavlink_encapsulated_data_t packet; + packet.seqnr = seqnr; + mav_array_memcpy(packet.data, data, sizeof(uint8_t)*253); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_ENCAPSULATED_DATA, (const char *)&packet, 255, 223); +#endif +} + +#endif + +// MESSAGE ENCAPSULATED_DATA UNPACKING + + +/** + * @brief Get field seqnr from encapsulated_data message + * + * @return sequence number (starting with 0 on every transmission) + */ +static inline uint16_t mavlink_msg_encapsulated_data_get_seqnr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field data from encapsulated_data message + * + * @return image data bytes + */ +static inline uint16_t mavlink_msg_encapsulated_data_get_data(const mavlink_message_t* msg, uint8_t *data) +{ + return _MAV_RETURN_uint8_t_array(msg, data, 253, 2); +} + +/** + * @brief Decode a encapsulated_data message into a struct + * + * @param msg The message to decode + * @param encapsulated_data C-struct to decode the message contents into + */ +static inline void mavlink_msg_encapsulated_data_decode(const mavlink_message_t* msg, mavlink_encapsulated_data_t* encapsulated_data) +{ +#if MAVLINK_NEED_BYTE_SWAP + encapsulated_data->seqnr = mavlink_msg_encapsulated_data_get_seqnr(msg); + mavlink_msg_encapsulated_data_get_data(msg, encapsulated_data->data); +#else + memcpy(encapsulated_data, _MAV_PAYLOAD(msg), 255); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_image_available.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_image_available.h new file mode 100644 index 0000000000..913fcd94c1 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_image_available.h @@ -0,0 +1,628 @@ +// MESSAGE IMAGE_AVAILABLE PACKING + +#define MAVLINK_MSG_ID_IMAGE_AVAILABLE 154 + +typedef struct __mavlink_image_available_t +{ + uint64_t cam_id; ///< Camera id + uint64_t timestamp; ///< Timestamp + uint64_t valid_until; ///< Until which timestamp this buffer will stay valid + uint32_t img_seq; ///< The image sequence number + uint32_t img_buf_index; ///< Position of the image in the buffer, starts with 0 + uint32_t key; ///< Shared memory area key + uint32_t exposure; ///< Exposure time, in microseconds + float gain; ///< Camera gain + float roll; ///< Roll angle in rad + float pitch; ///< Pitch angle in rad + float yaw; ///< Yaw angle in rad + float local_z; ///< Local frame Z coordinate (height over ground) + float lat; ///< GPS X coordinate + float lon; ///< GPS Y coordinate + float alt; ///< Global frame altitude + float ground_x; ///< Ground truth X + float ground_y; ///< Ground truth Y + float ground_z; ///< Ground truth Z + uint16_t width; ///< Image width + uint16_t height; ///< Image height + uint16_t depth; ///< Image depth + uint8_t cam_no; ///< Camera # (starts with 0) + uint8_t channels; ///< Image channels +} mavlink_image_available_t; + +#define MAVLINK_MSG_ID_IMAGE_AVAILABLE_LEN 92 +#define MAVLINK_MSG_ID_154_LEN 92 + + + +#define MAVLINK_MESSAGE_INFO_IMAGE_AVAILABLE { \ + "IMAGE_AVAILABLE", \ + 23, \ + { { "cam_id", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_image_available_t, cam_id) }, \ + { "timestamp", NULL, MAVLINK_TYPE_UINT64_T, 0, 8, offsetof(mavlink_image_available_t, timestamp) }, \ + { "valid_until", NULL, MAVLINK_TYPE_UINT64_T, 0, 16, offsetof(mavlink_image_available_t, valid_until) }, \ + { "img_seq", NULL, MAVLINK_TYPE_UINT32_T, 0, 24, offsetof(mavlink_image_available_t, img_seq) }, \ + { "img_buf_index", NULL, MAVLINK_TYPE_UINT32_T, 0, 28, offsetof(mavlink_image_available_t, img_buf_index) }, \ + { "key", NULL, MAVLINK_TYPE_UINT32_T, 0, 32, offsetof(mavlink_image_available_t, key) }, \ + { "exposure", NULL, MAVLINK_TYPE_UINT32_T, 0, 36, offsetof(mavlink_image_available_t, exposure) }, \ + { "gain", NULL, MAVLINK_TYPE_FLOAT, 0, 40, offsetof(mavlink_image_available_t, gain) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 44, offsetof(mavlink_image_available_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 48, offsetof(mavlink_image_available_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 52, offsetof(mavlink_image_available_t, yaw) }, \ + { "local_z", NULL, MAVLINK_TYPE_FLOAT, 0, 56, offsetof(mavlink_image_available_t, local_z) }, \ + { "lat", NULL, MAVLINK_TYPE_FLOAT, 0, 60, offsetof(mavlink_image_available_t, lat) }, \ + { "lon", NULL, MAVLINK_TYPE_FLOAT, 0, 64, offsetof(mavlink_image_available_t, lon) }, \ + { "alt", NULL, MAVLINK_TYPE_FLOAT, 0, 68, offsetof(mavlink_image_available_t, alt) }, \ + { "ground_x", NULL, MAVLINK_TYPE_FLOAT, 0, 72, offsetof(mavlink_image_available_t, ground_x) }, \ + { "ground_y", NULL, MAVLINK_TYPE_FLOAT, 0, 76, offsetof(mavlink_image_available_t, ground_y) }, \ + { "ground_z", NULL, MAVLINK_TYPE_FLOAT, 0, 80, offsetof(mavlink_image_available_t, ground_z) }, \ + { "width", NULL, MAVLINK_TYPE_UINT16_T, 0, 84, offsetof(mavlink_image_available_t, width) }, \ + { "height", NULL, MAVLINK_TYPE_UINT16_T, 0, 86, offsetof(mavlink_image_available_t, height) }, \ + { "depth", NULL, MAVLINK_TYPE_UINT16_T, 0, 88, offsetof(mavlink_image_available_t, depth) }, \ + { "cam_no", NULL, MAVLINK_TYPE_UINT8_T, 0, 90, offsetof(mavlink_image_available_t, cam_no) }, \ + { "channels", NULL, MAVLINK_TYPE_UINT8_T, 0, 91, offsetof(mavlink_image_available_t, channels) }, \ + } \ +} + + +/** + * @brief Pack a image_available message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param cam_id Camera id + * @param cam_no Camera # (starts with 0) + * @param timestamp Timestamp + * @param valid_until Until which timestamp this buffer will stay valid + * @param img_seq The image sequence number + * @param img_buf_index Position of the image in the buffer, starts with 0 + * @param width Image width + * @param height Image height + * @param depth Image depth + * @param channels Image channels + * @param key Shared memory area key + * @param exposure Exposure time, in microseconds + * @param gain Camera gain + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @param local_z Local frame Z coordinate (height over ground) + * @param lat GPS X coordinate + * @param lon GPS Y coordinate + * @param alt Global frame altitude + * @param ground_x Ground truth X + * @param ground_y Ground truth Y + * @param ground_z Ground truth Z + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_image_available_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t cam_id, uint8_t cam_no, uint64_t timestamp, uint64_t valid_until, uint32_t img_seq, uint32_t img_buf_index, uint16_t width, uint16_t height, uint16_t depth, uint8_t channels, uint32_t key, uint32_t exposure, float gain, float roll, float pitch, float yaw, float local_z, float lat, float lon, float alt, float ground_x, float ground_y, float ground_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[92]; + _mav_put_uint64_t(buf, 0, cam_id); + _mav_put_uint64_t(buf, 8, timestamp); + _mav_put_uint64_t(buf, 16, valid_until); + _mav_put_uint32_t(buf, 24, img_seq); + _mav_put_uint32_t(buf, 28, img_buf_index); + _mav_put_uint32_t(buf, 32, key); + _mav_put_uint32_t(buf, 36, exposure); + _mav_put_float(buf, 40, gain); + _mav_put_float(buf, 44, roll); + _mav_put_float(buf, 48, pitch); + _mav_put_float(buf, 52, yaw); + _mav_put_float(buf, 56, local_z); + _mav_put_float(buf, 60, lat); + _mav_put_float(buf, 64, lon); + _mav_put_float(buf, 68, alt); + _mav_put_float(buf, 72, ground_x); + _mav_put_float(buf, 76, ground_y); + _mav_put_float(buf, 80, ground_z); + _mav_put_uint16_t(buf, 84, width); + _mav_put_uint16_t(buf, 86, height); + _mav_put_uint16_t(buf, 88, depth); + _mav_put_uint8_t(buf, 90, cam_no); + _mav_put_uint8_t(buf, 91, channels); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 92); +#else + mavlink_image_available_t packet; + packet.cam_id = cam_id; + packet.timestamp = timestamp; + packet.valid_until = valid_until; + packet.img_seq = img_seq; + packet.img_buf_index = img_buf_index; + packet.key = key; + packet.exposure = exposure; + packet.gain = gain; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.local_z = local_z; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.ground_x = ground_x; + packet.ground_y = ground_y; + packet.ground_z = ground_z; + packet.width = width; + packet.height = height; + packet.depth = depth; + packet.cam_no = cam_no; + packet.channels = channels; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 92); +#endif + + msg->msgid = MAVLINK_MSG_ID_IMAGE_AVAILABLE; + return mavlink_finalize_message(msg, system_id, component_id, 92, 224); +} + +/** + * @brief Pack a image_available message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param cam_id Camera id + * @param cam_no Camera # (starts with 0) + * @param timestamp Timestamp + * @param valid_until Until which timestamp this buffer will stay valid + * @param img_seq The image sequence number + * @param img_buf_index Position of the image in the buffer, starts with 0 + * @param width Image width + * @param height Image height + * @param depth Image depth + * @param channels Image channels + * @param key Shared memory area key + * @param exposure Exposure time, in microseconds + * @param gain Camera gain + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @param local_z Local frame Z coordinate (height over ground) + * @param lat GPS X coordinate + * @param lon GPS Y coordinate + * @param alt Global frame altitude + * @param ground_x Ground truth X + * @param ground_y Ground truth Y + * @param ground_z Ground truth Z + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_image_available_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t cam_id,uint8_t cam_no,uint64_t timestamp,uint64_t valid_until,uint32_t img_seq,uint32_t img_buf_index,uint16_t width,uint16_t height,uint16_t depth,uint8_t channels,uint32_t key,uint32_t exposure,float gain,float roll,float pitch,float yaw,float local_z,float lat,float lon,float alt,float ground_x,float ground_y,float ground_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[92]; + _mav_put_uint64_t(buf, 0, cam_id); + _mav_put_uint64_t(buf, 8, timestamp); + _mav_put_uint64_t(buf, 16, valid_until); + _mav_put_uint32_t(buf, 24, img_seq); + _mav_put_uint32_t(buf, 28, img_buf_index); + _mav_put_uint32_t(buf, 32, key); + _mav_put_uint32_t(buf, 36, exposure); + _mav_put_float(buf, 40, gain); + _mav_put_float(buf, 44, roll); + _mav_put_float(buf, 48, pitch); + _mav_put_float(buf, 52, yaw); + _mav_put_float(buf, 56, local_z); + _mav_put_float(buf, 60, lat); + _mav_put_float(buf, 64, lon); + _mav_put_float(buf, 68, alt); + _mav_put_float(buf, 72, ground_x); + _mav_put_float(buf, 76, ground_y); + _mav_put_float(buf, 80, ground_z); + _mav_put_uint16_t(buf, 84, width); + _mav_put_uint16_t(buf, 86, height); + _mav_put_uint16_t(buf, 88, depth); + _mav_put_uint8_t(buf, 90, cam_no); + _mav_put_uint8_t(buf, 91, channels); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 92); +#else + mavlink_image_available_t packet; + packet.cam_id = cam_id; + packet.timestamp = timestamp; + packet.valid_until = valid_until; + packet.img_seq = img_seq; + packet.img_buf_index = img_buf_index; + packet.key = key; + packet.exposure = exposure; + packet.gain = gain; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.local_z = local_z; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.ground_x = ground_x; + packet.ground_y = ground_y; + packet.ground_z = ground_z; + packet.width = width; + packet.height = height; + packet.depth = depth; + packet.cam_no = cam_no; + packet.channels = channels; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 92); +#endif + + msg->msgid = MAVLINK_MSG_ID_IMAGE_AVAILABLE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 92, 224); +} + +/** + * @brief Encode a image_available struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param image_available C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_image_available_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_image_available_t* image_available) +{ + return mavlink_msg_image_available_pack(system_id, component_id, msg, image_available->cam_id, image_available->cam_no, image_available->timestamp, image_available->valid_until, image_available->img_seq, image_available->img_buf_index, image_available->width, image_available->height, image_available->depth, image_available->channels, image_available->key, image_available->exposure, image_available->gain, image_available->roll, image_available->pitch, image_available->yaw, image_available->local_z, image_available->lat, image_available->lon, image_available->alt, image_available->ground_x, image_available->ground_y, image_available->ground_z); +} + +/** + * @brief Send a image_available message + * @param chan MAVLink channel to send the message + * + * @param cam_id Camera id + * @param cam_no Camera # (starts with 0) + * @param timestamp Timestamp + * @param valid_until Until which timestamp this buffer will stay valid + * @param img_seq The image sequence number + * @param img_buf_index Position of the image in the buffer, starts with 0 + * @param width Image width + * @param height Image height + * @param depth Image depth + * @param channels Image channels + * @param key Shared memory area key + * @param exposure Exposure time, in microseconds + * @param gain Camera gain + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @param local_z Local frame Z coordinate (height over ground) + * @param lat GPS X coordinate + * @param lon GPS Y coordinate + * @param alt Global frame altitude + * @param ground_x Ground truth X + * @param ground_y Ground truth Y + * @param ground_z Ground truth Z + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_image_available_send(mavlink_channel_t chan, uint64_t cam_id, uint8_t cam_no, uint64_t timestamp, uint64_t valid_until, uint32_t img_seq, uint32_t img_buf_index, uint16_t width, uint16_t height, uint16_t depth, uint8_t channels, uint32_t key, uint32_t exposure, float gain, float roll, float pitch, float yaw, float local_z, float lat, float lon, float alt, float ground_x, float ground_y, float ground_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[92]; + _mav_put_uint64_t(buf, 0, cam_id); + _mav_put_uint64_t(buf, 8, timestamp); + _mav_put_uint64_t(buf, 16, valid_until); + _mav_put_uint32_t(buf, 24, img_seq); + _mav_put_uint32_t(buf, 28, img_buf_index); + _mav_put_uint32_t(buf, 32, key); + _mav_put_uint32_t(buf, 36, exposure); + _mav_put_float(buf, 40, gain); + _mav_put_float(buf, 44, roll); + _mav_put_float(buf, 48, pitch); + _mav_put_float(buf, 52, yaw); + _mav_put_float(buf, 56, local_z); + _mav_put_float(buf, 60, lat); + _mav_put_float(buf, 64, lon); + _mav_put_float(buf, 68, alt); + _mav_put_float(buf, 72, ground_x); + _mav_put_float(buf, 76, ground_y); + _mav_put_float(buf, 80, ground_z); + _mav_put_uint16_t(buf, 84, width); + _mav_put_uint16_t(buf, 86, height); + _mav_put_uint16_t(buf, 88, depth); + _mav_put_uint8_t(buf, 90, cam_no); + _mav_put_uint8_t(buf, 91, channels); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_IMAGE_AVAILABLE, buf, 92, 224); +#else + mavlink_image_available_t packet; + packet.cam_id = cam_id; + packet.timestamp = timestamp; + packet.valid_until = valid_until; + packet.img_seq = img_seq; + packet.img_buf_index = img_buf_index; + packet.key = key; + packet.exposure = exposure; + packet.gain = gain; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.local_z = local_z; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.ground_x = ground_x; + packet.ground_y = ground_y; + packet.ground_z = ground_z; + packet.width = width; + packet.height = height; + packet.depth = depth; + packet.cam_no = cam_no; + packet.channels = channels; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_IMAGE_AVAILABLE, (const char *)&packet, 92, 224); +#endif +} + +#endif + +// MESSAGE IMAGE_AVAILABLE UNPACKING + + +/** + * @brief Get field cam_id from image_available message + * + * @return Camera id + */ +static inline uint64_t mavlink_msg_image_available_get_cam_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field cam_no from image_available message + * + * @return Camera # (starts with 0) + */ +static inline uint8_t mavlink_msg_image_available_get_cam_no(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 90); +} + +/** + * @brief Get field timestamp from image_available message + * + * @return Timestamp + */ +static inline uint64_t mavlink_msg_image_available_get_timestamp(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 8); +} + +/** + * @brief Get field valid_until from image_available message + * + * @return Until which timestamp this buffer will stay valid + */ +static inline uint64_t mavlink_msg_image_available_get_valid_until(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 16); +} + +/** + * @brief Get field img_seq from image_available message + * + * @return The image sequence number + */ +static inline uint32_t mavlink_msg_image_available_get_img_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 24); +} + +/** + * @brief Get field img_buf_index from image_available message + * + * @return Position of the image in the buffer, starts with 0 + */ +static inline uint32_t mavlink_msg_image_available_get_img_buf_index(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 28); +} + +/** + * @brief Get field width from image_available message + * + * @return Image width + */ +static inline uint16_t mavlink_msg_image_available_get_width(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 84); +} + +/** + * @brief Get field height from image_available message + * + * @return Image height + */ +static inline uint16_t mavlink_msg_image_available_get_height(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 86); +} + +/** + * @brief Get field depth from image_available message + * + * @return Image depth + */ +static inline uint16_t mavlink_msg_image_available_get_depth(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 88); +} + +/** + * @brief Get field channels from image_available message + * + * @return Image channels + */ +static inline uint8_t mavlink_msg_image_available_get_channels(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 91); +} + +/** + * @brief Get field key from image_available message + * + * @return Shared memory area key + */ +static inline uint32_t mavlink_msg_image_available_get_key(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 32); +} + +/** + * @brief Get field exposure from image_available message + * + * @return Exposure time, in microseconds + */ +static inline uint32_t mavlink_msg_image_available_get_exposure(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 36); +} + +/** + * @brief Get field gain from image_available message + * + * @return Camera gain + */ +static inline float mavlink_msg_image_available_get_gain(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 40); +} + +/** + * @brief Get field roll from image_available message + * + * @return Roll angle in rad + */ +static inline float mavlink_msg_image_available_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 44); +} + +/** + * @brief Get field pitch from image_available message + * + * @return Pitch angle in rad + */ +static inline float mavlink_msg_image_available_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 48); +} + +/** + * @brief Get field yaw from image_available message + * + * @return Yaw angle in rad + */ +static inline float mavlink_msg_image_available_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 52); +} + +/** + * @brief Get field local_z from image_available message + * + * @return Local frame Z coordinate (height over ground) + */ +static inline float mavlink_msg_image_available_get_local_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 56); +} + +/** + * @brief Get field lat from image_available message + * + * @return GPS X coordinate + */ +static inline float mavlink_msg_image_available_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 60); +} + +/** + * @brief Get field lon from image_available message + * + * @return GPS Y coordinate + */ +static inline float mavlink_msg_image_available_get_lon(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 64); +} + +/** + * @brief Get field alt from image_available message + * + * @return Global frame altitude + */ +static inline float mavlink_msg_image_available_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 68); +} + +/** + * @brief Get field ground_x from image_available message + * + * @return Ground truth X + */ +static inline float mavlink_msg_image_available_get_ground_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 72); +} + +/** + * @brief Get field ground_y from image_available message + * + * @return Ground truth Y + */ +static inline float mavlink_msg_image_available_get_ground_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 76); +} + +/** + * @brief Get field ground_z from image_available message + * + * @return Ground truth Z + */ +static inline float mavlink_msg_image_available_get_ground_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 80); +} + +/** + * @brief Decode a image_available message into a struct + * + * @param msg The message to decode + * @param image_available C-struct to decode the message contents into + */ +static inline void mavlink_msg_image_available_decode(const mavlink_message_t* msg, mavlink_image_available_t* image_available) +{ +#if MAVLINK_NEED_BYTE_SWAP + image_available->cam_id = mavlink_msg_image_available_get_cam_id(msg); + image_available->timestamp = mavlink_msg_image_available_get_timestamp(msg); + image_available->valid_until = mavlink_msg_image_available_get_valid_until(msg); + image_available->img_seq = mavlink_msg_image_available_get_img_seq(msg); + image_available->img_buf_index = mavlink_msg_image_available_get_img_buf_index(msg); + image_available->key = mavlink_msg_image_available_get_key(msg); + image_available->exposure = mavlink_msg_image_available_get_exposure(msg); + image_available->gain = mavlink_msg_image_available_get_gain(msg); + image_available->roll = mavlink_msg_image_available_get_roll(msg); + image_available->pitch = mavlink_msg_image_available_get_pitch(msg); + image_available->yaw = mavlink_msg_image_available_get_yaw(msg); + image_available->local_z = mavlink_msg_image_available_get_local_z(msg); + image_available->lat = mavlink_msg_image_available_get_lat(msg); + image_available->lon = mavlink_msg_image_available_get_lon(msg); + image_available->alt = mavlink_msg_image_available_get_alt(msg); + image_available->ground_x = mavlink_msg_image_available_get_ground_x(msg); + image_available->ground_y = mavlink_msg_image_available_get_ground_y(msg); + image_available->ground_z = mavlink_msg_image_available_get_ground_z(msg); + image_available->width = mavlink_msg_image_available_get_width(msg); + image_available->height = mavlink_msg_image_available_get_height(msg); + image_available->depth = mavlink_msg_image_available_get_depth(msg); + image_available->cam_no = mavlink_msg_image_available_get_cam_no(msg); + image_available->channels = mavlink_msg_image_available_get_channels(msg); +#else + memcpy(image_available, _MAV_PAYLOAD(msg), 92); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_image_trigger_control.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_image_trigger_control.h new file mode 100644 index 0000000000..deb05769a1 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_image_trigger_control.h @@ -0,0 +1,144 @@ +// MESSAGE IMAGE_TRIGGER_CONTROL PACKING + +#define MAVLINK_MSG_ID_IMAGE_TRIGGER_CONTROL 153 + +typedef struct __mavlink_image_trigger_control_t +{ + uint8_t enable; ///< 0 to disable, 1 to enable +} mavlink_image_trigger_control_t; + +#define MAVLINK_MSG_ID_IMAGE_TRIGGER_CONTROL_LEN 1 +#define MAVLINK_MSG_ID_153_LEN 1 + + + +#define MAVLINK_MESSAGE_INFO_IMAGE_TRIGGER_CONTROL { \ + "IMAGE_TRIGGER_CONTROL", \ + 1, \ + { { "enable", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_image_trigger_control_t, enable) }, \ + } \ +} + + +/** + * @brief Pack a image_trigger_control message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param enable 0 to disable, 1 to enable + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_image_trigger_control_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t enable) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[1]; + _mav_put_uint8_t(buf, 0, enable); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 1); +#else + mavlink_image_trigger_control_t packet; + packet.enable = enable; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 1); +#endif + + msg->msgid = MAVLINK_MSG_ID_IMAGE_TRIGGER_CONTROL; + return mavlink_finalize_message(msg, system_id, component_id, 1, 95); +} + +/** + * @brief Pack a image_trigger_control message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param enable 0 to disable, 1 to enable + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_image_trigger_control_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t enable) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[1]; + _mav_put_uint8_t(buf, 0, enable); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 1); +#else + mavlink_image_trigger_control_t packet; + packet.enable = enable; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 1); +#endif + + msg->msgid = MAVLINK_MSG_ID_IMAGE_TRIGGER_CONTROL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 1, 95); +} + +/** + * @brief Encode a image_trigger_control struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param image_trigger_control C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_image_trigger_control_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_image_trigger_control_t* image_trigger_control) +{ + return mavlink_msg_image_trigger_control_pack(system_id, component_id, msg, image_trigger_control->enable); +} + +/** + * @brief Send a image_trigger_control message + * @param chan MAVLink channel to send the message + * + * @param enable 0 to disable, 1 to enable + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_image_trigger_control_send(mavlink_channel_t chan, uint8_t enable) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[1]; + _mav_put_uint8_t(buf, 0, enable); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_IMAGE_TRIGGER_CONTROL, buf, 1, 95); +#else + mavlink_image_trigger_control_t packet; + packet.enable = enable; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_IMAGE_TRIGGER_CONTROL, (const char *)&packet, 1, 95); +#endif +} + +#endif + +// MESSAGE IMAGE_TRIGGER_CONTROL UNPACKING + + +/** + * @brief Get field enable from image_trigger_control message + * + * @return 0 to disable, 1 to enable + */ +static inline uint8_t mavlink_msg_image_trigger_control_get_enable(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Decode a image_trigger_control message into a struct + * + * @param msg The message to decode + * @param image_trigger_control C-struct to decode the message contents into + */ +static inline void mavlink_msg_image_trigger_control_decode(const mavlink_message_t* msg, mavlink_image_trigger_control_t* image_trigger_control) +{ +#if MAVLINK_NEED_BYTE_SWAP + image_trigger_control->enable = mavlink_msg_image_trigger_control_get_enable(msg); +#else + memcpy(image_trigger_control, _MAV_PAYLOAD(msg), 1); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_image_triggered.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_image_triggered.h new file mode 100644 index 0000000000..557d748e12 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_image_triggered.h @@ -0,0 +1,386 @@ +// MESSAGE IMAGE_TRIGGERED PACKING + +#define MAVLINK_MSG_ID_IMAGE_TRIGGERED 152 + +typedef struct __mavlink_image_triggered_t +{ + uint64_t timestamp; ///< Timestamp + uint32_t seq; ///< IMU seq + float roll; ///< Roll angle in rad + float pitch; ///< Pitch angle in rad + float yaw; ///< Yaw angle in rad + float local_z; ///< Local frame Z coordinate (height over ground) + float lat; ///< GPS X coordinate + float lon; ///< GPS Y coordinate + float alt; ///< Global frame altitude + float ground_x; ///< Ground truth X + float ground_y; ///< Ground truth Y + float ground_z; ///< Ground truth Z +} mavlink_image_triggered_t; + +#define MAVLINK_MSG_ID_IMAGE_TRIGGERED_LEN 52 +#define MAVLINK_MSG_ID_152_LEN 52 + + + +#define MAVLINK_MESSAGE_INFO_IMAGE_TRIGGERED { \ + "IMAGE_TRIGGERED", \ + 12, \ + { { "timestamp", NULL, MAVLINK_TYPE_UINT64_T, 0, 0, offsetof(mavlink_image_triggered_t, timestamp) }, \ + { "seq", NULL, MAVLINK_TYPE_UINT32_T, 0, 8, offsetof(mavlink_image_triggered_t, seq) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_image_triggered_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_image_triggered_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_image_triggered_t, yaw) }, \ + { "local_z", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_image_triggered_t, local_z) }, \ + { "lat", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_image_triggered_t, lat) }, \ + { "lon", NULL, MAVLINK_TYPE_FLOAT, 0, 32, offsetof(mavlink_image_triggered_t, lon) }, \ + { "alt", NULL, MAVLINK_TYPE_FLOAT, 0, 36, offsetof(mavlink_image_triggered_t, alt) }, \ + { "ground_x", NULL, MAVLINK_TYPE_FLOAT, 0, 40, offsetof(mavlink_image_triggered_t, ground_x) }, \ + { "ground_y", NULL, MAVLINK_TYPE_FLOAT, 0, 44, offsetof(mavlink_image_triggered_t, ground_y) }, \ + { "ground_z", NULL, MAVLINK_TYPE_FLOAT, 0, 48, offsetof(mavlink_image_triggered_t, ground_z) }, \ + } \ +} + + +/** + * @brief Pack a image_triggered message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param timestamp Timestamp + * @param seq IMU seq + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @param local_z Local frame Z coordinate (height over ground) + * @param lat GPS X coordinate + * @param lon GPS Y coordinate + * @param alt Global frame altitude + * @param ground_x Ground truth X + * @param ground_y Ground truth Y + * @param ground_z Ground truth Z + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_image_triggered_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint64_t timestamp, uint32_t seq, float roll, float pitch, float yaw, float local_z, float lat, float lon, float alt, float ground_x, float ground_y, float ground_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[52]; + _mav_put_uint64_t(buf, 0, timestamp); + _mav_put_uint32_t(buf, 8, seq); + _mav_put_float(buf, 12, roll); + _mav_put_float(buf, 16, pitch); + _mav_put_float(buf, 20, yaw); + _mav_put_float(buf, 24, local_z); + _mav_put_float(buf, 28, lat); + _mav_put_float(buf, 32, lon); + _mav_put_float(buf, 36, alt); + _mav_put_float(buf, 40, ground_x); + _mav_put_float(buf, 44, ground_y); + _mav_put_float(buf, 48, ground_z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 52); +#else + mavlink_image_triggered_t packet; + packet.timestamp = timestamp; + packet.seq = seq; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.local_z = local_z; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.ground_x = ground_x; + packet.ground_y = ground_y; + packet.ground_z = ground_z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 52); +#endif + + msg->msgid = MAVLINK_MSG_ID_IMAGE_TRIGGERED; + return mavlink_finalize_message(msg, system_id, component_id, 52, 86); +} + +/** + * @brief Pack a image_triggered message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param timestamp Timestamp + * @param seq IMU seq + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @param local_z Local frame Z coordinate (height over ground) + * @param lat GPS X coordinate + * @param lon GPS Y coordinate + * @param alt Global frame altitude + * @param ground_x Ground truth X + * @param ground_y Ground truth Y + * @param ground_z Ground truth Z + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_image_triggered_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t timestamp,uint32_t seq,float roll,float pitch,float yaw,float local_z,float lat,float lon,float alt,float ground_x,float ground_y,float ground_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[52]; + _mav_put_uint64_t(buf, 0, timestamp); + _mav_put_uint32_t(buf, 8, seq); + _mav_put_float(buf, 12, roll); + _mav_put_float(buf, 16, pitch); + _mav_put_float(buf, 20, yaw); + _mav_put_float(buf, 24, local_z); + _mav_put_float(buf, 28, lat); + _mav_put_float(buf, 32, lon); + _mav_put_float(buf, 36, alt); + _mav_put_float(buf, 40, ground_x); + _mav_put_float(buf, 44, ground_y); + _mav_put_float(buf, 48, ground_z); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 52); +#else + mavlink_image_triggered_t packet; + packet.timestamp = timestamp; + packet.seq = seq; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.local_z = local_z; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.ground_x = ground_x; + packet.ground_y = ground_y; + packet.ground_z = ground_z; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 52); +#endif + + msg->msgid = MAVLINK_MSG_ID_IMAGE_TRIGGERED; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 52, 86); +} + +/** + * @brief Encode a image_triggered struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param image_triggered C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_image_triggered_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_image_triggered_t* image_triggered) +{ + return mavlink_msg_image_triggered_pack(system_id, component_id, msg, image_triggered->timestamp, image_triggered->seq, image_triggered->roll, image_triggered->pitch, image_triggered->yaw, image_triggered->local_z, image_triggered->lat, image_triggered->lon, image_triggered->alt, image_triggered->ground_x, image_triggered->ground_y, image_triggered->ground_z); +} + +/** + * @brief Send a image_triggered message + * @param chan MAVLink channel to send the message + * + * @param timestamp Timestamp + * @param seq IMU seq + * @param roll Roll angle in rad + * @param pitch Pitch angle in rad + * @param yaw Yaw angle in rad + * @param local_z Local frame Z coordinate (height over ground) + * @param lat GPS X coordinate + * @param lon GPS Y coordinate + * @param alt Global frame altitude + * @param ground_x Ground truth X + * @param ground_y Ground truth Y + * @param ground_z Ground truth Z + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_image_triggered_send(mavlink_channel_t chan, uint64_t timestamp, uint32_t seq, float roll, float pitch, float yaw, float local_z, float lat, float lon, float alt, float ground_x, float ground_y, float ground_z) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[52]; + _mav_put_uint64_t(buf, 0, timestamp); + _mav_put_uint32_t(buf, 8, seq); + _mav_put_float(buf, 12, roll); + _mav_put_float(buf, 16, pitch); + _mav_put_float(buf, 20, yaw); + _mav_put_float(buf, 24, local_z); + _mav_put_float(buf, 28, lat); + _mav_put_float(buf, 32, lon); + _mav_put_float(buf, 36, alt); + _mav_put_float(buf, 40, ground_x); + _mav_put_float(buf, 44, ground_y); + _mav_put_float(buf, 48, ground_z); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_IMAGE_TRIGGERED, buf, 52, 86); +#else + mavlink_image_triggered_t packet; + packet.timestamp = timestamp; + packet.seq = seq; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.local_z = local_z; + packet.lat = lat; + packet.lon = lon; + packet.alt = alt; + packet.ground_x = ground_x; + packet.ground_y = ground_y; + packet.ground_z = ground_z; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_IMAGE_TRIGGERED, (const char *)&packet, 52, 86); +#endif +} + +#endif + +// MESSAGE IMAGE_TRIGGERED UNPACKING + + +/** + * @brief Get field timestamp from image_triggered message + * + * @return Timestamp + */ +static inline uint64_t mavlink_msg_image_triggered_get_timestamp(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field seq from image_triggered message + * + * @return IMU seq + */ +static inline uint32_t mavlink_msg_image_triggered_get_seq(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 8); +} + +/** + * @brief Get field roll from image_triggered message + * + * @return Roll angle in rad + */ +static inline float mavlink_msg_image_triggered_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field pitch from image_triggered message + * + * @return Pitch angle in rad + */ +static inline float mavlink_msg_image_triggered_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field yaw from image_triggered message + * + * @return Yaw angle in rad + */ +static inline float mavlink_msg_image_triggered_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field local_z from image_triggered message + * + * @return Local frame Z coordinate (height over ground) + */ +static inline float mavlink_msg_image_triggered_get_local_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field lat from image_triggered message + * + * @return GPS X coordinate + */ +static inline float mavlink_msg_image_triggered_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field lon from image_triggered message + * + * @return GPS Y coordinate + */ +static inline float mavlink_msg_image_triggered_get_lon(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 32); +} + +/** + * @brief Get field alt from image_triggered message + * + * @return Global frame altitude + */ +static inline float mavlink_msg_image_triggered_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 36); +} + +/** + * @brief Get field ground_x from image_triggered message + * + * @return Ground truth X + */ +static inline float mavlink_msg_image_triggered_get_ground_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 40); +} + +/** + * @brief Get field ground_y from image_triggered message + * + * @return Ground truth Y + */ +static inline float mavlink_msg_image_triggered_get_ground_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 44); +} + +/** + * @brief Get field ground_z from image_triggered message + * + * @return Ground truth Z + */ +static inline float mavlink_msg_image_triggered_get_ground_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 48); +} + +/** + * @brief Decode a image_triggered message into a struct + * + * @param msg The message to decode + * @param image_triggered C-struct to decode the message contents into + */ +static inline void mavlink_msg_image_triggered_decode(const mavlink_message_t* msg, mavlink_image_triggered_t* image_triggered) +{ +#if MAVLINK_NEED_BYTE_SWAP + image_triggered->timestamp = mavlink_msg_image_triggered_get_timestamp(msg); + image_triggered->seq = mavlink_msg_image_triggered_get_seq(msg); + image_triggered->roll = mavlink_msg_image_triggered_get_roll(msg); + image_triggered->pitch = mavlink_msg_image_triggered_get_pitch(msg); + image_triggered->yaw = mavlink_msg_image_triggered_get_yaw(msg); + image_triggered->local_z = mavlink_msg_image_triggered_get_local_z(msg); + image_triggered->lat = mavlink_msg_image_triggered_get_lat(msg); + image_triggered->lon = mavlink_msg_image_triggered_get_lon(msg); + image_triggered->alt = mavlink_msg_image_triggered_get_alt(msg); + image_triggered->ground_x = mavlink_msg_image_triggered_get_ground_x(msg); + image_triggered->ground_y = mavlink_msg_image_triggered_get_ground_y(msg); + image_triggered->ground_z = mavlink_msg_image_triggered_get_ground_z(msg); +#else + memcpy(image_triggered, _MAV_PAYLOAD(msg), 52); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_marker.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_marker.h new file mode 100644 index 0000000000..0c8cc6f189 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_marker.h @@ -0,0 +1,276 @@ +// MESSAGE MARKER PACKING + +#define MAVLINK_MSG_ID_MARKER 171 + +typedef struct __mavlink_marker_t +{ + float x; ///< x position + float y; ///< y position + float z; ///< z position + float roll; ///< roll orientation + float pitch; ///< pitch orientation + float yaw; ///< yaw orientation + uint16_t id; ///< ID +} mavlink_marker_t; + +#define MAVLINK_MSG_ID_MARKER_LEN 26 +#define MAVLINK_MSG_ID_171_LEN 26 + + + +#define MAVLINK_MESSAGE_INFO_MARKER { \ + "MARKER", \ + 7, \ + { { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_marker_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_marker_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_marker_t, z) }, \ + { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_marker_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_marker_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_marker_t, yaw) }, \ + { "id", NULL, MAVLINK_TYPE_UINT16_T, 0, 24, offsetof(mavlink_marker_t, id) }, \ + } \ +} + + +/** + * @brief Pack a marker message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param id ID + * @param x x position + * @param y y position + * @param z z position + * @param roll roll orientation + * @param pitch pitch orientation + * @param yaw yaw orientation + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_marker_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t id, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, roll); + _mav_put_float(buf, 16, pitch); + _mav_put_float(buf, 20, yaw); + _mav_put_uint16_t(buf, 24, id); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_marker_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.id = id; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_MARKER; + return mavlink_finalize_message(msg, system_id, component_id, 26, 249); +} + +/** + * @brief Pack a marker message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param id ID + * @param x x position + * @param y y position + * @param z z position + * @param roll roll orientation + * @param pitch pitch orientation + * @param yaw yaw orientation + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_marker_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t id,float x,float y,float z,float roll,float pitch,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, roll); + _mav_put_float(buf, 16, pitch); + _mav_put_float(buf, 20, yaw); + _mav_put_uint16_t(buf, 24, id); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 26); +#else + mavlink_marker_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.id = id; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 26); +#endif + + msg->msgid = MAVLINK_MSG_ID_MARKER; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 26, 249); +} + +/** + * @brief Encode a marker struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param marker C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_marker_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_marker_t* marker) +{ + return mavlink_msg_marker_pack(system_id, component_id, msg, marker->id, marker->x, marker->y, marker->z, marker->roll, marker->pitch, marker->yaw); +} + +/** + * @brief Send a marker message + * @param chan MAVLink channel to send the message + * + * @param id ID + * @param x x position + * @param y y position + * @param z z position + * @param roll roll orientation + * @param pitch pitch orientation + * @param yaw yaw orientation + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_marker_send(mavlink_channel_t chan, uint16_t id, float x, float y, float z, float roll, float pitch, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[26]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, roll); + _mav_put_float(buf, 16, pitch); + _mav_put_float(buf, 20, yaw); + _mav_put_uint16_t(buf, 24, id); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MARKER, buf, 26, 249); +#else + mavlink_marker_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.id = id; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MARKER, (const char *)&packet, 26, 249); +#endif +} + +#endif + +// MESSAGE MARKER UNPACKING + + +/** + * @brief Get field id from marker message + * + * @return ID + */ +static inline uint16_t mavlink_msg_marker_get_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 24); +} + +/** + * @brief Get field x from marker message + * + * @return x position + */ +static inline float mavlink_msg_marker_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field y from marker message + * + * @return y position + */ +static inline float mavlink_msg_marker_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field z from marker message + * + * @return z position + */ +static inline float mavlink_msg_marker_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field roll from marker message + * + * @return roll orientation + */ +static inline float mavlink_msg_marker_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field pitch from marker message + * + * @return pitch orientation + */ +static inline float mavlink_msg_marker_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field yaw from marker message + * + * @return yaw orientation + */ +static inline float mavlink_msg_marker_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Decode a marker message into a struct + * + * @param msg The message to decode + * @param marker C-struct to decode the message contents into + */ +static inline void mavlink_msg_marker_decode(const mavlink_message_t* msg, mavlink_marker_t* marker) +{ +#if MAVLINK_NEED_BYTE_SWAP + marker->x = mavlink_msg_marker_get_x(msg); + marker->y = mavlink_msg_marker_get_y(msg); + marker->z = mavlink_msg_marker_get_z(msg); + marker->roll = mavlink_msg_marker_get_roll(msg); + marker->pitch = mavlink_msg_marker_get_pitch(msg); + marker->yaw = mavlink_msg_marker_get_yaw(msg); + marker->id = mavlink_msg_marker_get_id(msg); +#else + memcpy(marker, _MAV_PAYLOAD(msg), 26); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_pattern_detected.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_pattern_detected.h new file mode 100644 index 0000000000..907246b207 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_pattern_detected.h @@ -0,0 +1,204 @@ +// MESSAGE PATTERN_DETECTED PACKING + +#define MAVLINK_MSG_ID_PATTERN_DETECTED 190 + +typedef struct __mavlink_pattern_detected_t +{ + float confidence; ///< Confidence of detection + uint8_t type; ///< 0: Pattern, 1: Letter + char file[100]; ///< Pattern file name + uint8_t detected; ///< Accepted as true detection, 0 no, 1 yes +} mavlink_pattern_detected_t; + +#define MAVLINK_MSG_ID_PATTERN_DETECTED_LEN 106 +#define MAVLINK_MSG_ID_190_LEN 106 + +#define MAVLINK_MSG_PATTERN_DETECTED_FIELD_FILE_LEN 100 + +#define MAVLINK_MESSAGE_INFO_PATTERN_DETECTED { \ + "PATTERN_DETECTED", \ + 4, \ + { { "confidence", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_pattern_detected_t, confidence) }, \ + { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_pattern_detected_t, type) }, \ + { "file", NULL, MAVLINK_TYPE_CHAR, 100, 5, offsetof(mavlink_pattern_detected_t, file) }, \ + { "detected", NULL, MAVLINK_TYPE_UINT8_T, 0, 105, offsetof(mavlink_pattern_detected_t, detected) }, \ + } \ +} + + +/** + * @brief Pack a pattern_detected message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param type 0: Pattern, 1: Letter + * @param confidence Confidence of detection + * @param file Pattern file name + * @param detected Accepted as true detection, 0 no, 1 yes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_pattern_detected_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t type, float confidence, const char *file, uint8_t detected) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[106]; + _mav_put_float(buf, 0, confidence); + _mav_put_uint8_t(buf, 4, type); + _mav_put_uint8_t(buf, 105, detected); + _mav_put_char_array(buf, 5, file, 100); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 106); +#else + mavlink_pattern_detected_t packet; + packet.confidence = confidence; + packet.type = type; + packet.detected = detected; + mav_array_memcpy(packet.file, file, sizeof(char)*100); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 106); +#endif + + msg->msgid = MAVLINK_MSG_ID_PATTERN_DETECTED; + return mavlink_finalize_message(msg, system_id, component_id, 106, 90); +} + +/** + * @brief Pack a pattern_detected message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param type 0: Pattern, 1: Letter + * @param confidence Confidence of detection + * @param file Pattern file name + * @param detected Accepted as true detection, 0 no, 1 yes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_pattern_detected_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t type,float confidence,const char *file,uint8_t detected) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[106]; + _mav_put_float(buf, 0, confidence); + _mav_put_uint8_t(buf, 4, type); + _mav_put_uint8_t(buf, 105, detected); + _mav_put_char_array(buf, 5, file, 100); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 106); +#else + mavlink_pattern_detected_t packet; + packet.confidence = confidence; + packet.type = type; + packet.detected = detected; + mav_array_memcpy(packet.file, file, sizeof(char)*100); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 106); +#endif + + msg->msgid = MAVLINK_MSG_ID_PATTERN_DETECTED; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 106, 90); +} + +/** + * @brief Encode a pattern_detected struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param pattern_detected C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_pattern_detected_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_pattern_detected_t* pattern_detected) +{ + return mavlink_msg_pattern_detected_pack(system_id, component_id, msg, pattern_detected->type, pattern_detected->confidence, pattern_detected->file, pattern_detected->detected); +} + +/** + * @brief Send a pattern_detected message + * @param chan MAVLink channel to send the message + * + * @param type 0: Pattern, 1: Letter + * @param confidence Confidence of detection + * @param file Pattern file name + * @param detected Accepted as true detection, 0 no, 1 yes + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_pattern_detected_send(mavlink_channel_t chan, uint8_t type, float confidence, const char *file, uint8_t detected) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[106]; + _mav_put_float(buf, 0, confidence); + _mav_put_uint8_t(buf, 4, type); + _mav_put_uint8_t(buf, 105, detected); + _mav_put_char_array(buf, 5, file, 100); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PATTERN_DETECTED, buf, 106, 90); +#else + mavlink_pattern_detected_t packet; + packet.confidence = confidence; + packet.type = type; + packet.detected = detected; + mav_array_memcpy(packet.file, file, sizeof(char)*100); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PATTERN_DETECTED, (const char *)&packet, 106, 90); +#endif +} + +#endif + +// MESSAGE PATTERN_DETECTED UNPACKING + + +/** + * @brief Get field type from pattern_detected message + * + * @return 0: Pattern, 1: Letter + */ +static inline uint8_t mavlink_msg_pattern_detected_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field confidence from pattern_detected message + * + * @return Confidence of detection + */ +static inline float mavlink_msg_pattern_detected_get_confidence(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field file from pattern_detected message + * + * @return Pattern file name + */ +static inline uint16_t mavlink_msg_pattern_detected_get_file(const mavlink_message_t* msg, char *file) +{ + return _MAV_RETURN_char_array(msg, file, 100, 5); +} + +/** + * @brief Get field detected from pattern_detected message + * + * @return Accepted as true detection, 0 no, 1 yes + */ +static inline uint8_t mavlink_msg_pattern_detected_get_detected(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 105); +} + +/** + * @brief Decode a pattern_detected message into a struct + * + * @param msg The message to decode + * @param pattern_detected C-struct to decode the message contents into + */ +static inline void mavlink_msg_pattern_detected_decode(const mavlink_message_t* msg, mavlink_pattern_detected_t* pattern_detected) +{ +#if MAVLINK_NEED_BYTE_SWAP + pattern_detected->confidence = mavlink_msg_pattern_detected_get_confidence(msg); + pattern_detected->type = mavlink_msg_pattern_detected_get_type(msg); + mavlink_msg_pattern_detected_get_file(msg, pattern_detected->file); + pattern_detected->detected = mavlink_msg_pattern_detected_get_detected(msg); +#else + memcpy(pattern_detected, _MAV_PAYLOAD(msg), 106); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_point_of_interest.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_point_of_interest.h new file mode 100644 index 0000000000..eec8d40691 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_point_of_interest.h @@ -0,0 +1,292 @@ +// MESSAGE POINT_OF_INTEREST PACKING + +#define MAVLINK_MSG_ID_POINT_OF_INTEREST 191 + +typedef struct __mavlink_point_of_interest_t +{ + float x; ///< X Position + float y; ///< Y Position + float z; ///< Z Position + uint16_t timeout; ///< 0: no timeout, >1: timeout in seconds + uint8_t type; ///< 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + uint8_t color; ///< 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + uint8_t coordinate_system; ///< 0: global, 1:local + char name[26]; ///< POI name +} mavlink_point_of_interest_t; + +#define MAVLINK_MSG_ID_POINT_OF_INTEREST_LEN 43 +#define MAVLINK_MSG_ID_191_LEN 43 + +#define MAVLINK_MSG_POINT_OF_INTEREST_FIELD_NAME_LEN 26 + +#define MAVLINK_MESSAGE_INFO_POINT_OF_INTEREST { \ + "POINT_OF_INTEREST", \ + 8, \ + { { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_point_of_interest_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_point_of_interest_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_point_of_interest_t, z) }, \ + { "timeout", NULL, MAVLINK_TYPE_UINT16_T, 0, 12, offsetof(mavlink_point_of_interest_t, timeout) }, \ + { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 14, offsetof(mavlink_point_of_interest_t, type) }, \ + { "color", NULL, MAVLINK_TYPE_UINT8_T, 0, 15, offsetof(mavlink_point_of_interest_t, color) }, \ + { "coordinate_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 16, offsetof(mavlink_point_of_interest_t, coordinate_system) }, \ + { "name", NULL, MAVLINK_TYPE_CHAR, 26, 17, offsetof(mavlink_point_of_interest_t, name) }, \ + } \ +} + + +/** + * @brief Pack a point_of_interest message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param type 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + * @param color 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + * @param coordinate_system 0: global, 1:local + * @param timeout 0: no timeout, >1: timeout in seconds + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param name POI name + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_point_of_interest_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t type, uint8_t color, uint8_t coordinate_system, uint16_t timeout, float x, float y, float z, const char *name) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[43]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_uint16_t(buf, 12, timeout); + _mav_put_uint8_t(buf, 14, type); + _mav_put_uint8_t(buf, 15, color); + _mav_put_uint8_t(buf, 16, coordinate_system); + _mav_put_char_array(buf, 17, name, 26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 43); +#else + mavlink_point_of_interest_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.timeout = timeout; + packet.type = type; + packet.color = color; + packet.coordinate_system = coordinate_system; + mav_array_memcpy(packet.name, name, sizeof(char)*26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 43); +#endif + + msg->msgid = MAVLINK_MSG_ID_POINT_OF_INTEREST; + return mavlink_finalize_message(msg, system_id, component_id, 43, 95); +} + +/** + * @brief Pack a point_of_interest message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param type 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + * @param color 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + * @param coordinate_system 0: global, 1:local + * @param timeout 0: no timeout, >1: timeout in seconds + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param name POI name + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_point_of_interest_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t type,uint8_t color,uint8_t coordinate_system,uint16_t timeout,float x,float y,float z,const char *name) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[43]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_uint16_t(buf, 12, timeout); + _mav_put_uint8_t(buf, 14, type); + _mav_put_uint8_t(buf, 15, color); + _mav_put_uint8_t(buf, 16, coordinate_system); + _mav_put_char_array(buf, 17, name, 26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 43); +#else + mavlink_point_of_interest_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.timeout = timeout; + packet.type = type; + packet.color = color; + packet.coordinate_system = coordinate_system; + mav_array_memcpy(packet.name, name, sizeof(char)*26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 43); +#endif + + msg->msgid = MAVLINK_MSG_ID_POINT_OF_INTEREST; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 43, 95); +} + +/** + * @brief Encode a point_of_interest struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param point_of_interest C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_point_of_interest_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_point_of_interest_t* point_of_interest) +{ + return mavlink_msg_point_of_interest_pack(system_id, component_id, msg, point_of_interest->type, point_of_interest->color, point_of_interest->coordinate_system, point_of_interest->timeout, point_of_interest->x, point_of_interest->y, point_of_interest->z, point_of_interest->name); +} + +/** + * @brief Send a point_of_interest message + * @param chan MAVLink channel to send the message + * + * @param type 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + * @param color 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + * @param coordinate_system 0: global, 1:local + * @param timeout 0: no timeout, >1: timeout in seconds + * @param x X Position + * @param y Y Position + * @param z Z Position + * @param name POI name + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_point_of_interest_send(mavlink_channel_t chan, uint8_t type, uint8_t color, uint8_t coordinate_system, uint16_t timeout, float x, float y, float z, const char *name) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[43]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_uint16_t(buf, 12, timeout); + _mav_put_uint8_t(buf, 14, type); + _mav_put_uint8_t(buf, 15, color); + _mav_put_uint8_t(buf, 16, coordinate_system); + _mav_put_char_array(buf, 17, name, 26); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POINT_OF_INTEREST, buf, 43, 95); +#else + mavlink_point_of_interest_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.timeout = timeout; + packet.type = type; + packet.color = color; + packet.coordinate_system = coordinate_system; + mav_array_memcpy(packet.name, name, sizeof(char)*26); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POINT_OF_INTEREST, (const char *)&packet, 43, 95); +#endif +} + +#endif + +// MESSAGE POINT_OF_INTEREST UNPACKING + + +/** + * @brief Get field type from point_of_interest message + * + * @return 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + */ +static inline uint8_t mavlink_msg_point_of_interest_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 14); +} + +/** + * @brief Get field color from point_of_interest message + * + * @return 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + */ +static inline uint8_t mavlink_msg_point_of_interest_get_color(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 15); +} + +/** + * @brief Get field coordinate_system from point_of_interest message + * + * @return 0: global, 1:local + */ +static inline uint8_t mavlink_msg_point_of_interest_get_coordinate_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 16); +} + +/** + * @brief Get field timeout from point_of_interest message + * + * @return 0: no timeout, >1: timeout in seconds + */ +static inline uint16_t mavlink_msg_point_of_interest_get_timeout(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 12); +} + +/** + * @brief Get field x from point_of_interest message + * + * @return X Position + */ +static inline float mavlink_msg_point_of_interest_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field y from point_of_interest message + * + * @return Y Position + */ +static inline float mavlink_msg_point_of_interest_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field z from point_of_interest message + * + * @return Z Position + */ +static inline float mavlink_msg_point_of_interest_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field name from point_of_interest message + * + * @return POI name + */ +static inline uint16_t mavlink_msg_point_of_interest_get_name(const mavlink_message_t* msg, char *name) +{ + return _MAV_RETURN_char_array(msg, name, 26, 17); +} + +/** + * @brief Decode a point_of_interest message into a struct + * + * @param msg The message to decode + * @param point_of_interest C-struct to decode the message contents into + */ +static inline void mavlink_msg_point_of_interest_decode(const mavlink_message_t* msg, mavlink_point_of_interest_t* point_of_interest) +{ +#if MAVLINK_NEED_BYTE_SWAP + point_of_interest->x = mavlink_msg_point_of_interest_get_x(msg); + point_of_interest->y = mavlink_msg_point_of_interest_get_y(msg); + point_of_interest->z = mavlink_msg_point_of_interest_get_z(msg); + point_of_interest->timeout = mavlink_msg_point_of_interest_get_timeout(msg); + point_of_interest->type = mavlink_msg_point_of_interest_get_type(msg); + point_of_interest->color = mavlink_msg_point_of_interest_get_color(msg); + point_of_interest->coordinate_system = mavlink_msg_point_of_interest_get_coordinate_system(msg); + mavlink_msg_point_of_interest_get_name(msg, point_of_interest->name); +#else + memcpy(point_of_interest, _MAV_PAYLOAD(msg), 43); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_point_of_interest_connection.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_point_of_interest_connection.h new file mode 100644 index 0000000000..f83630093e --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_point_of_interest_connection.h @@ -0,0 +1,358 @@ +// MESSAGE POINT_OF_INTEREST_CONNECTION PACKING + +#define MAVLINK_MSG_ID_POINT_OF_INTEREST_CONNECTION 192 + +typedef struct __mavlink_point_of_interest_connection_t +{ + float xp1; ///< X1 Position + float yp1; ///< Y1 Position + float zp1; ///< Z1 Position + float xp2; ///< X2 Position + float yp2; ///< Y2 Position + float zp2; ///< Z2 Position + uint16_t timeout; ///< 0: no timeout, >1: timeout in seconds + uint8_t type; ///< 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + uint8_t color; ///< 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + uint8_t coordinate_system; ///< 0: global, 1:local + char name[26]; ///< POI connection name +} mavlink_point_of_interest_connection_t; + +#define MAVLINK_MSG_ID_POINT_OF_INTEREST_CONNECTION_LEN 55 +#define MAVLINK_MSG_ID_192_LEN 55 + +#define MAVLINK_MSG_POINT_OF_INTEREST_CONNECTION_FIELD_NAME_LEN 26 + +#define MAVLINK_MESSAGE_INFO_POINT_OF_INTEREST_CONNECTION { \ + "POINT_OF_INTEREST_CONNECTION", \ + 11, \ + { { "xp1", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_point_of_interest_connection_t, xp1) }, \ + { "yp1", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_point_of_interest_connection_t, yp1) }, \ + { "zp1", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_point_of_interest_connection_t, zp1) }, \ + { "xp2", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_point_of_interest_connection_t, xp2) }, \ + { "yp2", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_point_of_interest_connection_t, yp2) }, \ + { "zp2", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_point_of_interest_connection_t, zp2) }, \ + { "timeout", NULL, MAVLINK_TYPE_UINT16_T, 0, 24, offsetof(mavlink_point_of_interest_connection_t, timeout) }, \ + { "type", NULL, MAVLINK_TYPE_UINT8_T, 0, 26, offsetof(mavlink_point_of_interest_connection_t, type) }, \ + { "color", NULL, MAVLINK_TYPE_UINT8_T, 0, 27, offsetof(mavlink_point_of_interest_connection_t, color) }, \ + { "coordinate_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 28, offsetof(mavlink_point_of_interest_connection_t, coordinate_system) }, \ + { "name", NULL, MAVLINK_TYPE_CHAR, 26, 29, offsetof(mavlink_point_of_interest_connection_t, name) }, \ + } \ +} + + +/** + * @brief Pack a point_of_interest_connection message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param type 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + * @param color 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + * @param coordinate_system 0: global, 1:local + * @param timeout 0: no timeout, >1: timeout in seconds + * @param xp1 X1 Position + * @param yp1 Y1 Position + * @param zp1 Z1 Position + * @param xp2 X2 Position + * @param yp2 Y2 Position + * @param zp2 Z2 Position + * @param name POI connection name + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_point_of_interest_connection_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t type, uint8_t color, uint8_t coordinate_system, uint16_t timeout, float xp1, float yp1, float zp1, float xp2, float yp2, float zp2, const char *name) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[55]; + _mav_put_float(buf, 0, xp1); + _mav_put_float(buf, 4, yp1); + _mav_put_float(buf, 8, zp1); + _mav_put_float(buf, 12, xp2); + _mav_put_float(buf, 16, yp2); + _mav_put_float(buf, 20, zp2); + _mav_put_uint16_t(buf, 24, timeout); + _mav_put_uint8_t(buf, 26, type); + _mav_put_uint8_t(buf, 27, color); + _mav_put_uint8_t(buf, 28, coordinate_system); + _mav_put_char_array(buf, 29, name, 26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 55); +#else + mavlink_point_of_interest_connection_t packet; + packet.xp1 = xp1; + packet.yp1 = yp1; + packet.zp1 = zp1; + packet.xp2 = xp2; + packet.yp2 = yp2; + packet.zp2 = zp2; + packet.timeout = timeout; + packet.type = type; + packet.color = color; + packet.coordinate_system = coordinate_system; + mav_array_memcpy(packet.name, name, sizeof(char)*26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 55); +#endif + + msg->msgid = MAVLINK_MSG_ID_POINT_OF_INTEREST_CONNECTION; + return mavlink_finalize_message(msg, system_id, component_id, 55, 36); +} + +/** + * @brief Pack a point_of_interest_connection message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param type 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + * @param color 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + * @param coordinate_system 0: global, 1:local + * @param timeout 0: no timeout, >1: timeout in seconds + * @param xp1 X1 Position + * @param yp1 Y1 Position + * @param zp1 Z1 Position + * @param xp2 X2 Position + * @param yp2 Y2 Position + * @param zp2 Z2 Position + * @param name POI connection name + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_point_of_interest_connection_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t type,uint8_t color,uint8_t coordinate_system,uint16_t timeout,float xp1,float yp1,float zp1,float xp2,float yp2,float zp2,const char *name) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[55]; + _mav_put_float(buf, 0, xp1); + _mav_put_float(buf, 4, yp1); + _mav_put_float(buf, 8, zp1); + _mav_put_float(buf, 12, xp2); + _mav_put_float(buf, 16, yp2); + _mav_put_float(buf, 20, zp2); + _mav_put_uint16_t(buf, 24, timeout); + _mav_put_uint8_t(buf, 26, type); + _mav_put_uint8_t(buf, 27, color); + _mav_put_uint8_t(buf, 28, coordinate_system); + _mav_put_char_array(buf, 29, name, 26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 55); +#else + mavlink_point_of_interest_connection_t packet; + packet.xp1 = xp1; + packet.yp1 = yp1; + packet.zp1 = zp1; + packet.xp2 = xp2; + packet.yp2 = yp2; + packet.zp2 = zp2; + packet.timeout = timeout; + packet.type = type; + packet.color = color; + packet.coordinate_system = coordinate_system; + mav_array_memcpy(packet.name, name, sizeof(char)*26); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 55); +#endif + + msg->msgid = MAVLINK_MSG_ID_POINT_OF_INTEREST_CONNECTION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 55, 36); +} + +/** + * @brief Encode a point_of_interest_connection struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param point_of_interest_connection C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_point_of_interest_connection_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_point_of_interest_connection_t* point_of_interest_connection) +{ + return mavlink_msg_point_of_interest_connection_pack(system_id, component_id, msg, point_of_interest_connection->type, point_of_interest_connection->color, point_of_interest_connection->coordinate_system, point_of_interest_connection->timeout, point_of_interest_connection->xp1, point_of_interest_connection->yp1, point_of_interest_connection->zp1, point_of_interest_connection->xp2, point_of_interest_connection->yp2, point_of_interest_connection->zp2, point_of_interest_connection->name); +} + +/** + * @brief Send a point_of_interest_connection message + * @param chan MAVLink channel to send the message + * + * @param type 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + * @param color 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + * @param coordinate_system 0: global, 1:local + * @param timeout 0: no timeout, >1: timeout in seconds + * @param xp1 X1 Position + * @param yp1 Y1 Position + * @param zp1 Z1 Position + * @param xp2 X2 Position + * @param yp2 Y2 Position + * @param zp2 Z2 Position + * @param name POI connection name + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_point_of_interest_connection_send(mavlink_channel_t chan, uint8_t type, uint8_t color, uint8_t coordinate_system, uint16_t timeout, float xp1, float yp1, float zp1, float xp2, float yp2, float zp2, const char *name) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[55]; + _mav_put_float(buf, 0, xp1); + _mav_put_float(buf, 4, yp1); + _mav_put_float(buf, 8, zp1); + _mav_put_float(buf, 12, xp2); + _mav_put_float(buf, 16, yp2); + _mav_put_float(buf, 20, zp2); + _mav_put_uint16_t(buf, 24, timeout); + _mav_put_uint8_t(buf, 26, type); + _mav_put_uint8_t(buf, 27, color); + _mav_put_uint8_t(buf, 28, coordinate_system); + _mav_put_char_array(buf, 29, name, 26); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POINT_OF_INTEREST_CONNECTION, buf, 55, 36); +#else + mavlink_point_of_interest_connection_t packet; + packet.xp1 = xp1; + packet.yp1 = yp1; + packet.zp1 = zp1; + packet.xp2 = xp2; + packet.yp2 = yp2; + packet.zp2 = zp2; + packet.timeout = timeout; + packet.type = type; + packet.color = color; + packet.coordinate_system = coordinate_system; + mav_array_memcpy(packet.name, name, sizeof(char)*26); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POINT_OF_INTEREST_CONNECTION, (const char *)&packet, 55, 36); +#endif +} + +#endif + +// MESSAGE POINT_OF_INTEREST_CONNECTION UNPACKING + + +/** + * @brief Get field type from point_of_interest_connection message + * + * @return 0: Notice, 1: Warning, 2: Critical, 3: Emergency, 4: Debug + */ +static inline uint8_t mavlink_msg_point_of_interest_connection_get_type(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 26); +} + +/** + * @brief Get field color from point_of_interest_connection message + * + * @return 0: blue, 1: yellow, 2: red, 3: orange, 4: green, 5: magenta + */ +static inline uint8_t mavlink_msg_point_of_interest_connection_get_color(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 27); +} + +/** + * @brief Get field coordinate_system from point_of_interest_connection message + * + * @return 0: global, 1:local + */ +static inline uint8_t mavlink_msg_point_of_interest_connection_get_coordinate_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 28); +} + +/** + * @brief Get field timeout from point_of_interest_connection message + * + * @return 0: no timeout, >1: timeout in seconds + */ +static inline uint16_t mavlink_msg_point_of_interest_connection_get_timeout(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 24); +} + +/** + * @brief Get field xp1 from point_of_interest_connection message + * + * @return X1 Position + */ +static inline float mavlink_msg_point_of_interest_connection_get_xp1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field yp1 from point_of_interest_connection message + * + * @return Y1 Position + */ +static inline float mavlink_msg_point_of_interest_connection_get_yp1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field zp1 from point_of_interest_connection message + * + * @return Z1 Position + */ +static inline float mavlink_msg_point_of_interest_connection_get_zp1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field xp2 from point_of_interest_connection message + * + * @return X2 Position + */ +static inline float mavlink_msg_point_of_interest_connection_get_xp2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field yp2 from point_of_interest_connection message + * + * @return Y2 Position + */ +static inline float mavlink_msg_point_of_interest_connection_get_yp2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field zp2 from point_of_interest_connection message + * + * @return Z2 Position + */ +static inline float mavlink_msg_point_of_interest_connection_get_zp2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field name from point_of_interest_connection message + * + * @return POI connection name + */ +static inline uint16_t mavlink_msg_point_of_interest_connection_get_name(const mavlink_message_t* msg, char *name) +{ + return _MAV_RETURN_char_array(msg, name, 26, 29); +} + +/** + * @brief Decode a point_of_interest_connection message into a struct + * + * @param msg The message to decode + * @param point_of_interest_connection C-struct to decode the message contents into + */ +static inline void mavlink_msg_point_of_interest_connection_decode(const mavlink_message_t* msg, mavlink_point_of_interest_connection_t* point_of_interest_connection) +{ +#if MAVLINK_NEED_BYTE_SWAP + point_of_interest_connection->xp1 = mavlink_msg_point_of_interest_connection_get_xp1(msg); + point_of_interest_connection->yp1 = mavlink_msg_point_of_interest_connection_get_yp1(msg); + point_of_interest_connection->zp1 = mavlink_msg_point_of_interest_connection_get_zp1(msg); + point_of_interest_connection->xp2 = mavlink_msg_point_of_interest_connection_get_xp2(msg); + point_of_interest_connection->yp2 = mavlink_msg_point_of_interest_connection_get_yp2(msg); + point_of_interest_connection->zp2 = mavlink_msg_point_of_interest_connection_get_zp2(msg); + point_of_interest_connection->timeout = mavlink_msg_point_of_interest_connection_get_timeout(msg); + point_of_interest_connection->type = mavlink_msg_point_of_interest_connection_get_type(msg); + point_of_interest_connection->color = mavlink_msg_point_of_interest_connection_get_color(msg); + point_of_interest_connection->coordinate_system = mavlink_msg_point_of_interest_connection_get_coordinate_system(msg); + mavlink_msg_point_of_interest_connection_get_name(msg, point_of_interest_connection->name); +#else + memcpy(point_of_interest_connection, _MAV_PAYLOAD(msg), 55); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_position_control_setpoint.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_position_control_setpoint.h new file mode 100644 index 0000000000..495fb884cf --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_position_control_setpoint.h @@ -0,0 +1,232 @@ +// MESSAGE POSITION_CONTROL_SETPOINT PACKING + +#define MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT 170 + +typedef struct __mavlink_position_control_setpoint_t +{ + float x; ///< x position + float y; ///< y position + float z; ///< z position + float yaw; ///< yaw orientation in radians, 0 = NORTH + uint16_t id; ///< ID of waypoint, 0 for plain position +} mavlink_position_control_setpoint_t; + +#define MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT_LEN 18 +#define MAVLINK_MSG_ID_170_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_POSITION_CONTROL_SETPOINT { \ + "POSITION_CONTROL_SETPOINT", \ + 5, \ + { { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_position_control_setpoint_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_position_control_setpoint_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_position_control_setpoint_t, z) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_position_control_setpoint_t, yaw) }, \ + { "id", NULL, MAVLINK_TYPE_UINT16_T, 0, 16, offsetof(mavlink_position_control_setpoint_t, id) }, \ + } \ +} + + +/** + * @brief Pack a position_control_setpoint message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param id ID of waypoint, 0 for plain position + * @param x x position + * @param y y position + * @param z z position + * @param yaw yaw orientation in radians, 0 = NORTH + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_position_control_setpoint_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t id, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + _mav_put_uint16_t(buf, 16, id); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_position_control_setpoint_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + packet.id = id; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT; + return mavlink_finalize_message(msg, system_id, component_id, 18, 28); +} + +/** + * @brief Pack a position_control_setpoint message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param id ID of waypoint, 0 for plain position + * @param x x position + * @param y y position + * @param z z position + * @param yaw yaw orientation in radians, 0 = NORTH + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_position_control_setpoint_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t id,float x,float y,float z,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + _mav_put_uint16_t(buf, 16, id); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_position_control_setpoint_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + packet.id = id; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18, 28); +} + +/** + * @brief Encode a position_control_setpoint struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param position_control_setpoint C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_position_control_setpoint_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_position_control_setpoint_t* position_control_setpoint) +{ + return mavlink_msg_position_control_setpoint_pack(system_id, component_id, msg, position_control_setpoint->id, position_control_setpoint->x, position_control_setpoint->y, position_control_setpoint->z, position_control_setpoint->yaw); +} + +/** + * @brief Send a position_control_setpoint message + * @param chan MAVLink channel to send the message + * + * @param id ID of waypoint, 0 for plain position + * @param x x position + * @param y y position + * @param z z position + * @param yaw yaw orientation in radians, 0 = NORTH + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_position_control_setpoint_send(mavlink_channel_t chan, uint16_t id, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + _mav_put_uint16_t(buf, 16, id); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT, buf, 18, 28); +#else + mavlink_position_control_setpoint_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + packet.id = id; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_POSITION_CONTROL_SETPOINT, (const char *)&packet, 18, 28); +#endif +} + +#endif + +// MESSAGE POSITION_CONTROL_SETPOINT UNPACKING + + +/** + * @brief Get field id from position_control_setpoint message + * + * @return ID of waypoint, 0 for plain position + */ +static inline uint16_t mavlink_msg_position_control_setpoint_get_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 16); +} + +/** + * @brief Get field x from position_control_setpoint message + * + * @return x position + */ +static inline float mavlink_msg_position_control_setpoint_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field y from position_control_setpoint message + * + * @return y position + */ +static inline float mavlink_msg_position_control_setpoint_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field z from position_control_setpoint message + * + * @return z position + */ +static inline float mavlink_msg_position_control_setpoint_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field yaw from position_control_setpoint message + * + * @return yaw orientation in radians, 0 = NORTH + */ +static inline float mavlink_msg_position_control_setpoint_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Decode a position_control_setpoint message into a struct + * + * @param msg The message to decode + * @param position_control_setpoint C-struct to decode the message contents into + */ +static inline void mavlink_msg_position_control_setpoint_decode(const mavlink_message_t* msg, mavlink_position_control_setpoint_t* position_control_setpoint) +{ +#if MAVLINK_NEED_BYTE_SWAP + position_control_setpoint->x = mavlink_msg_position_control_setpoint_get_x(msg); + position_control_setpoint->y = mavlink_msg_position_control_setpoint_get_y(msg); + position_control_setpoint->z = mavlink_msg_position_control_setpoint_get_z(msg); + position_control_setpoint->yaw = mavlink_msg_position_control_setpoint_get_yaw(msg); + position_control_setpoint->id = mavlink_msg_position_control_setpoint_get_id(msg); +#else + memcpy(position_control_setpoint, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_raw_aux.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_raw_aux.h new file mode 100644 index 0000000000..507e0f2f9b --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_raw_aux.h @@ -0,0 +1,276 @@ +// MESSAGE RAW_AUX PACKING + +#define MAVLINK_MSG_ID_RAW_AUX 172 + +typedef struct __mavlink_raw_aux_t +{ + int32_t baro; ///< Barometric pressure (hecto Pascal) + uint16_t adc1; ///< ADC1 (J405 ADC3, LPC2148 AD0.6) + uint16_t adc2; ///< ADC2 (J405 ADC5, LPC2148 AD0.2) + uint16_t adc3; ///< ADC3 (J405 ADC6, LPC2148 AD0.1) + uint16_t adc4; ///< ADC4 (J405 ADC7, LPC2148 AD1.3) + uint16_t vbat; ///< Battery voltage + int16_t temp; ///< Temperature (degrees celcius) +} mavlink_raw_aux_t; + +#define MAVLINK_MSG_ID_RAW_AUX_LEN 16 +#define MAVLINK_MSG_ID_172_LEN 16 + + + +#define MAVLINK_MESSAGE_INFO_RAW_AUX { \ + "RAW_AUX", \ + 7, \ + { { "baro", NULL, MAVLINK_TYPE_INT32_T, 0, 0, offsetof(mavlink_raw_aux_t, baro) }, \ + { "adc1", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_raw_aux_t, adc1) }, \ + { "adc2", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_raw_aux_t, adc2) }, \ + { "adc3", NULL, MAVLINK_TYPE_UINT16_T, 0, 8, offsetof(mavlink_raw_aux_t, adc3) }, \ + { "adc4", NULL, MAVLINK_TYPE_UINT16_T, 0, 10, offsetof(mavlink_raw_aux_t, adc4) }, \ + { "vbat", NULL, MAVLINK_TYPE_UINT16_T, 0, 12, offsetof(mavlink_raw_aux_t, vbat) }, \ + { "temp", NULL, MAVLINK_TYPE_INT16_T, 0, 14, offsetof(mavlink_raw_aux_t, temp) }, \ + } \ +} + + +/** + * @brief Pack a raw_aux message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param adc1 ADC1 (J405 ADC3, LPC2148 AD0.6) + * @param adc2 ADC2 (J405 ADC5, LPC2148 AD0.2) + * @param adc3 ADC3 (J405 ADC6, LPC2148 AD0.1) + * @param adc4 ADC4 (J405 ADC7, LPC2148 AD1.3) + * @param vbat Battery voltage + * @param temp Temperature (degrees celcius) + * @param baro Barometric pressure (hecto Pascal) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_raw_aux_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t adc1, uint16_t adc2, uint16_t adc3, uint16_t adc4, uint16_t vbat, int16_t temp, int32_t baro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_int32_t(buf, 0, baro); + _mav_put_uint16_t(buf, 4, adc1); + _mav_put_uint16_t(buf, 6, adc2); + _mav_put_uint16_t(buf, 8, adc3); + _mav_put_uint16_t(buf, 10, adc4); + _mav_put_uint16_t(buf, 12, vbat); + _mav_put_int16_t(buf, 14, temp); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_raw_aux_t packet; + packet.baro = baro; + packet.adc1 = adc1; + packet.adc2 = adc2; + packet.adc3 = adc3; + packet.adc4 = adc4; + packet.vbat = vbat; + packet.temp = temp; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_RAW_AUX; + return mavlink_finalize_message(msg, system_id, component_id, 16, 182); +} + +/** + * @brief Pack a raw_aux message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param adc1 ADC1 (J405 ADC3, LPC2148 AD0.6) + * @param adc2 ADC2 (J405 ADC5, LPC2148 AD0.2) + * @param adc3 ADC3 (J405 ADC6, LPC2148 AD0.1) + * @param adc4 ADC4 (J405 ADC7, LPC2148 AD1.3) + * @param vbat Battery voltage + * @param temp Temperature (degrees celcius) + * @param baro Barometric pressure (hecto Pascal) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_raw_aux_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t adc1,uint16_t adc2,uint16_t adc3,uint16_t adc4,uint16_t vbat,int16_t temp,int32_t baro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_int32_t(buf, 0, baro); + _mav_put_uint16_t(buf, 4, adc1); + _mav_put_uint16_t(buf, 6, adc2); + _mav_put_uint16_t(buf, 8, adc3); + _mav_put_uint16_t(buf, 10, adc4); + _mav_put_uint16_t(buf, 12, vbat); + _mav_put_int16_t(buf, 14, temp); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 16); +#else + mavlink_raw_aux_t packet; + packet.baro = baro; + packet.adc1 = adc1; + packet.adc2 = adc2; + packet.adc3 = adc3; + packet.adc4 = adc4; + packet.vbat = vbat; + packet.temp = temp; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 16); +#endif + + msg->msgid = MAVLINK_MSG_ID_RAW_AUX; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 16, 182); +} + +/** + * @brief Encode a raw_aux struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param raw_aux C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_raw_aux_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_raw_aux_t* raw_aux) +{ + return mavlink_msg_raw_aux_pack(system_id, component_id, msg, raw_aux->adc1, raw_aux->adc2, raw_aux->adc3, raw_aux->adc4, raw_aux->vbat, raw_aux->temp, raw_aux->baro); +} + +/** + * @brief Send a raw_aux message + * @param chan MAVLink channel to send the message + * + * @param adc1 ADC1 (J405 ADC3, LPC2148 AD0.6) + * @param adc2 ADC2 (J405 ADC5, LPC2148 AD0.2) + * @param adc3 ADC3 (J405 ADC6, LPC2148 AD0.1) + * @param adc4 ADC4 (J405 ADC7, LPC2148 AD1.3) + * @param vbat Battery voltage + * @param temp Temperature (degrees celcius) + * @param baro Barometric pressure (hecto Pascal) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_raw_aux_send(mavlink_channel_t chan, uint16_t adc1, uint16_t adc2, uint16_t adc3, uint16_t adc4, uint16_t vbat, int16_t temp, int32_t baro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[16]; + _mav_put_int32_t(buf, 0, baro); + _mav_put_uint16_t(buf, 4, adc1); + _mav_put_uint16_t(buf, 6, adc2); + _mav_put_uint16_t(buf, 8, adc3); + _mav_put_uint16_t(buf, 10, adc4); + _mav_put_uint16_t(buf, 12, vbat); + _mav_put_int16_t(buf, 14, temp); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RAW_AUX, buf, 16, 182); +#else + mavlink_raw_aux_t packet; + packet.baro = baro; + packet.adc1 = adc1; + packet.adc2 = adc2; + packet.adc3 = adc3; + packet.adc4 = adc4; + packet.vbat = vbat; + packet.temp = temp; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RAW_AUX, (const char *)&packet, 16, 182); +#endif +} + +#endif + +// MESSAGE RAW_AUX UNPACKING + + +/** + * @brief Get field adc1 from raw_aux message + * + * @return ADC1 (J405 ADC3, LPC2148 AD0.6) + */ +static inline uint16_t mavlink_msg_raw_aux_get_adc1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field adc2 from raw_aux message + * + * @return ADC2 (J405 ADC5, LPC2148 AD0.2) + */ +static inline uint16_t mavlink_msg_raw_aux_get_adc2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field adc3 from raw_aux message + * + * @return ADC3 (J405 ADC6, LPC2148 AD0.1) + */ +static inline uint16_t mavlink_msg_raw_aux_get_adc3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Get field adc4 from raw_aux message + * + * @return ADC4 (J405 ADC7, LPC2148 AD1.3) + */ +static inline uint16_t mavlink_msg_raw_aux_get_adc4(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 10); +} + +/** + * @brief Get field vbat from raw_aux message + * + * @return Battery voltage + */ +static inline uint16_t mavlink_msg_raw_aux_get_vbat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 12); +} + +/** + * @brief Get field temp from raw_aux message + * + * @return Temperature (degrees celcius) + */ +static inline int16_t mavlink_msg_raw_aux_get_temp(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 14); +} + +/** + * @brief Get field baro from raw_aux message + * + * @return Barometric pressure (hecto Pascal) + */ +static inline int32_t mavlink_msg_raw_aux_get_baro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 0); +} + +/** + * @brief Decode a raw_aux message into a struct + * + * @param msg The message to decode + * @param raw_aux C-struct to decode the message contents into + */ +static inline void mavlink_msg_raw_aux_decode(const mavlink_message_t* msg, mavlink_raw_aux_t* raw_aux) +{ +#if MAVLINK_NEED_BYTE_SWAP + raw_aux->baro = mavlink_msg_raw_aux_get_baro(msg); + raw_aux->adc1 = mavlink_msg_raw_aux_get_adc1(msg); + raw_aux->adc2 = mavlink_msg_raw_aux_get_adc2(msg); + raw_aux->adc3 = mavlink_msg_raw_aux_get_adc3(msg); + raw_aux->adc4 = mavlink_msg_raw_aux_get_adc4(msg); + raw_aux->vbat = mavlink_msg_raw_aux_get_vbat(msg); + raw_aux->temp = mavlink_msg_raw_aux_get_temp(msg); +#else + memcpy(raw_aux, _MAV_PAYLOAD(msg), 16); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_set_cam_shutter.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_set_cam_shutter.h new file mode 100644 index 0000000000..698625b7e1 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_set_cam_shutter.h @@ -0,0 +1,254 @@ +// MESSAGE SET_CAM_SHUTTER PACKING + +#define MAVLINK_MSG_ID_SET_CAM_SHUTTER 151 + +typedef struct __mavlink_set_cam_shutter_t +{ + float gain; ///< Camera gain + uint16_t interval; ///< Shutter interval, in microseconds + uint16_t exposure; ///< Exposure time, in microseconds + uint8_t cam_no; ///< Camera id + uint8_t cam_mode; ///< Camera mode: 0 = auto, 1 = manual + uint8_t trigger_pin; ///< Trigger pin, 0-3 for PtGrey FireFly +} mavlink_set_cam_shutter_t; + +#define MAVLINK_MSG_ID_SET_CAM_SHUTTER_LEN 11 +#define MAVLINK_MSG_ID_151_LEN 11 + + + +#define MAVLINK_MESSAGE_INFO_SET_CAM_SHUTTER { \ + "SET_CAM_SHUTTER", \ + 6, \ + { { "gain", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_set_cam_shutter_t, gain) }, \ + { "interval", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_set_cam_shutter_t, interval) }, \ + { "exposure", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_set_cam_shutter_t, exposure) }, \ + { "cam_no", NULL, MAVLINK_TYPE_UINT8_T, 0, 8, offsetof(mavlink_set_cam_shutter_t, cam_no) }, \ + { "cam_mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 9, offsetof(mavlink_set_cam_shutter_t, cam_mode) }, \ + { "trigger_pin", NULL, MAVLINK_TYPE_UINT8_T, 0, 10, offsetof(mavlink_set_cam_shutter_t, trigger_pin) }, \ + } \ +} + + +/** + * @brief Pack a set_cam_shutter message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param cam_no Camera id + * @param cam_mode Camera mode: 0 = auto, 1 = manual + * @param trigger_pin Trigger pin, 0-3 for PtGrey FireFly + * @param interval Shutter interval, in microseconds + * @param exposure Exposure time, in microseconds + * @param gain Camera gain + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_cam_shutter_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t cam_no, uint8_t cam_mode, uint8_t trigger_pin, uint16_t interval, uint16_t exposure, float gain) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[11]; + _mav_put_float(buf, 0, gain); + _mav_put_uint16_t(buf, 4, interval); + _mav_put_uint16_t(buf, 6, exposure); + _mav_put_uint8_t(buf, 8, cam_no); + _mav_put_uint8_t(buf, 9, cam_mode); + _mav_put_uint8_t(buf, 10, trigger_pin); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 11); +#else + mavlink_set_cam_shutter_t packet; + packet.gain = gain; + packet.interval = interval; + packet.exposure = exposure; + packet.cam_no = cam_no; + packet.cam_mode = cam_mode; + packet.trigger_pin = trigger_pin; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 11); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_CAM_SHUTTER; + return mavlink_finalize_message(msg, system_id, component_id, 11, 108); +} + +/** + * @brief Pack a set_cam_shutter message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param cam_no Camera id + * @param cam_mode Camera mode: 0 = auto, 1 = manual + * @param trigger_pin Trigger pin, 0-3 for PtGrey FireFly + * @param interval Shutter interval, in microseconds + * @param exposure Exposure time, in microseconds + * @param gain Camera gain + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_cam_shutter_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t cam_no,uint8_t cam_mode,uint8_t trigger_pin,uint16_t interval,uint16_t exposure,float gain) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[11]; + _mav_put_float(buf, 0, gain); + _mav_put_uint16_t(buf, 4, interval); + _mav_put_uint16_t(buf, 6, exposure); + _mav_put_uint8_t(buf, 8, cam_no); + _mav_put_uint8_t(buf, 9, cam_mode); + _mav_put_uint8_t(buf, 10, trigger_pin); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 11); +#else + mavlink_set_cam_shutter_t packet; + packet.gain = gain; + packet.interval = interval; + packet.exposure = exposure; + packet.cam_no = cam_no; + packet.cam_mode = cam_mode; + packet.trigger_pin = trigger_pin; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 11); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_CAM_SHUTTER; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 11, 108); +} + +/** + * @brief Encode a set_cam_shutter struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_cam_shutter C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_cam_shutter_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_cam_shutter_t* set_cam_shutter) +{ + return mavlink_msg_set_cam_shutter_pack(system_id, component_id, msg, set_cam_shutter->cam_no, set_cam_shutter->cam_mode, set_cam_shutter->trigger_pin, set_cam_shutter->interval, set_cam_shutter->exposure, set_cam_shutter->gain); +} + +/** + * @brief Send a set_cam_shutter message + * @param chan MAVLink channel to send the message + * + * @param cam_no Camera id + * @param cam_mode Camera mode: 0 = auto, 1 = manual + * @param trigger_pin Trigger pin, 0-3 for PtGrey FireFly + * @param interval Shutter interval, in microseconds + * @param exposure Exposure time, in microseconds + * @param gain Camera gain + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_cam_shutter_send(mavlink_channel_t chan, uint8_t cam_no, uint8_t cam_mode, uint8_t trigger_pin, uint16_t interval, uint16_t exposure, float gain) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[11]; + _mav_put_float(buf, 0, gain); + _mav_put_uint16_t(buf, 4, interval); + _mav_put_uint16_t(buf, 6, exposure); + _mav_put_uint8_t(buf, 8, cam_no); + _mav_put_uint8_t(buf, 9, cam_mode); + _mav_put_uint8_t(buf, 10, trigger_pin); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_CAM_SHUTTER, buf, 11, 108); +#else + mavlink_set_cam_shutter_t packet; + packet.gain = gain; + packet.interval = interval; + packet.exposure = exposure; + packet.cam_no = cam_no; + packet.cam_mode = cam_mode; + packet.trigger_pin = trigger_pin; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_CAM_SHUTTER, (const char *)&packet, 11, 108); +#endif +} + +#endif + +// MESSAGE SET_CAM_SHUTTER UNPACKING + + +/** + * @brief Get field cam_no from set_cam_shutter message + * + * @return Camera id + */ +static inline uint8_t mavlink_msg_set_cam_shutter_get_cam_no(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 8); +} + +/** + * @brief Get field cam_mode from set_cam_shutter message + * + * @return Camera mode: 0 = auto, 1 = manual + */ +static inline uint8_t mavlink_msg_set_cam_shutter_get_cam_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 9); +} + +/** + * @brief Get field trigger_pin from set_cam_shutter message + * + * @return Trigger pin, 0-3 for PtGrey FireFly + */ +static inline uint8_t mavlink_msg_set_cam_shutter_get_trigger_pin(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 10); +} + +/** + * @brief Get field interval from set_cam_shutter message + * + * @return Shutter interval, in microseconds + */ +static inline uint16_t mavlink_msg_set_cam_shutter_get_interval(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field exposure from set_cam_shutter message + * + * @return Exposure time, in microseconds + */ +static inline uint16_t mavlink_msg_set_cam_shutter_get_exposure(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field gain from set_cam_shutter message + * + * @return Camera gain + */ +static inline float mavlink_msg_set_cam_shutter_get_gain(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Decode a set_cam_shutter message into a struct + * + * @param msg The message to decode + * @param set_cam_shutter C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_cam_shutter_decode(const mavlink_message_t* msg, mavlink_set_cam_shutter_t* set_cam_shutter) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_cam_shutter->gain = mavlink_msg_set_cam_shutter_get_gain(msg); + set_cam_shutter->interval = mavlink_msg_set_cam_shutter_get_interval(msg); + set_cam_shutter->exposure = mavlink_msg_set_cam_shutter_get_exposure(msg); + set_cam_shutter->cam_no = mavlink_msg_set_cam_shutter_get_cam_no(msg); + set_cam_shutter->cam_mode = mavlink_msg_set_cam_shutter_get_cam_mode(msg); + set_cam_shutter->trigger_pin = mavlink_msg_set_cam_shutter_get_trigger_pin(msg); +#else + memcpy(set_cam_shutter, _MAV_PAYLOAD(msg), 11); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_set_position_control_offset.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_set_position_control_offset.h new file mode 100644 index 0000000000..27c08b7c9c --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_set_position_control_offset.h @@ -0,0 +1,254 @@ +// MESSAGE SET_POSITION_CONTROL_OFFSET PACKING + +#define MAVLINK_MSG_ID_SET_POSITION_CONTROL_OFFSET 160 + +typedef struct __mavlink_set_position_control_offset_t +{ + float x; ///< x position offset + float y; ///< y position offset + float z; ///< z position offset + float yaw; ///< yaw orientation offset in radians, 0 = NORTH + uint8_t target_system; ///< System ID + uint8_t target_component; ///< Component ID +} mavlink_set_position_control_offset_t; + +#define MAVLINK_MSG_ID_SET_POSITION_CONTROL_OFFSET_LEN 18 +#define MAVLINK_MSG_ID_160_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_SET_POSITION_CONTROL_OFFSET { \ + "SET_POSITION_CONTROL_OFFSET", \ + 6, \ + { { "x", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_set_position_control_offset_t, x) }, \ + { "y", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_set_position_control_offset_t, y) }, \ + { "z", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_set_position_control_offset_t, z) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_set_position_control_offset_t, yaw) }, \ + { "target_system", NULL, MAVLINK_TYPE_UINT8_T, 0, 16, offsetof(mavlink_set_position_control_offset_t, target_system) }, \ + { "target_component", NULL, MAVLINK_TYPE_UINT8_T, 0, 17, offsetof(mavlink_set_position_control_offset_t, target_component) }, \ + } \ +} + + +/** + * @brief Pack a set_position_control_offset message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system System ID + * @param target_component Component ID + * @param x x position offset + * @param y y position offset + * @param z z position offset + * @param yaw yaw orientation offset in radians, 0 = NORTH + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_position_control_offset_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system, uint8_t target_component, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_set_position_control_offset_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_POSITION_CONTROL_OFFSET; + return mavlink_finalize_message(msg, system_id, component_id, 18, 22); +} + +/** + * @brief Pack a set_position_control_offset message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system System ID + * @param target_component Component ID + * @param x x position offset + * @param y y position offset + * @param z z position offset + * @param yaw yaw orientation offset in radians, 0 = NORTH + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_set_position_control_offset_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system,uint8_t target_component,float x,float y,float z,float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_set_position_control_offset_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + packet.target_system = target_system; + packet.target_component = target_component; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_SET_POSITION_CONTROL_OFFSET; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18, 22); +} + +/** + * @brief Encode a set_position_control_offset struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param set_position_control_offset C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_set_position_control_offset_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_set_position_control_offset_t* set_position_control_offset) +{ + return mavlink_msg_set_position_control_offset_pack(system_id, component_id, msg, set_position_control_offset->target_system, set_position_control_offset->target_component, set_position_control_offset->x, set_position_control_offset->y, set_position_control_offset->z, set_position_control_offset->yaw); +} + +/** + * @brief Send a set_position_control_offset message + * @param chan MAVLink channel to send the message + * + * @param target_system System ID + * @param target_component Component ID + * @param x x position offset + * @param y y position offset + * @param z z position offset + * @param yaw yaw orientation offset in radians, 0 = NORTH + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_set_position_control_offset_send(mavlink_channel_t chan, uint8_t target_system, uint8_t target_component, float x, float y, float z, float yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, x); + _mav_put_float(buf, 4, y); + _mav_put_float(buf, 8, z); + _mav_put_float(buf, 12, yaw); + _mav_put_uint8_t(buf, 16, target_system); + _mav_put_uint8_t(buf, 17, target_component); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_POSITION_CONTROL_OFFSET, buf, 18, 22); +#else + mavlink_set_position_control_offset_t packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.yaw = yaw; + packet.target_system = target_system; + packet.target_component = target_component; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SET_POSITION_CONTROL_OFFSET, (const char *)&packet, 18, 22); +#endif +} + +#endif + +// MESSAGE SET_POSITION_CONTROL_OFFSET UNPACKING + + +/** + * @brief Get field target_system from set_position_control_offset message + * + * @return System ID + */ +static inline uint8_t mavlink_msg_set_position_control_offset_get_target_system(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 16); +} + +/** + * @brief Get field target_component from set_position_control_offset message + * + * @return Component ID + */ +static inline uint8_t mavlink_msg_set_position_control_offset_get_target_component(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 17); +} + +/** + * @brief Get field x from set_position_control_offset message + * + * @return x position offset + */ +static inline float mavlink_msg_set_position_control_offset_get_x(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field y from set_position_control_offset message + * + * @return y position offset + */ +static inline float mavlink_msg_set_position_control_offset_get_y(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field z from set_position_control_offset message + * + * @return z position offset + */ +static inline float mavlink_msg_set_position_control_offset_get_z(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field yaw from set_position_control_offset message + * + * @return yaw orientation offset in radians, 0 = NORTH + */ +static inline float mavlink_msg_set_position_control_offset_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Decode a set_position_control_offset message into a struct + * + * @param msg The message to decode + * @param set_position_control_offset C-struct to decode the message contents into + */ +static inline void mavlink_msg_set_position_control_offset_decode(const mavlink_message_t* msg, mavlink_set_position_control_offset_t* set_position_control_offset) +{ +#if MAVLINK_NEED_BYTE_SWAP + set_position_control_offset->x = mavlink_msg_set_position_control_offset_get_x(msg); + set_position_control_offset->y = mavlink_msg_set_position_control_offset_get_y(msg); + set_position_control_offset->z = mavlink_msg_set_position_control_offset_get_z(msg); + set_position_control_offset->yaw = mavlink_msg_set_position_control_offset_get_yaw(msg); + set_position_control_offset->target_system = mavlink_msg_set_position_control_offset_get_target_system(msg); + set_position_control_offset->target_component = mavlink_msg_set_position_control_offset_get_target_component(msg); +#else + memcpy(set_position_control_offset, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_watchdog_command.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_watchdog_command.h new file mode 100644 index 0000000000..240f69e727 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_watchdog_command.h @@ -0,0 +1,210 @@ +// MESSAGE WATCHDOG_COMMAND PACKING + +#define MAVLINK_MSG_ID_WATCHDOG_COMMAND 183 + +typedef struct __mavlink_watchdog_command_t +{ + uint16_t watchdog_id; ///< Watchdog ID + uint16_t process_id; ///< Process ID + uint8_t target_system_id; ///< Target system ID + uint8_t command_id; ///< Command ID +} mavlink_watchdog_command_t; + +#define MAVLINK_MSG_ID_WATCHDOG_COMMAND_LEN 6 +#define MAVLINK_MSG_ID_183_LEN 6 + + + +#define MAVLINK_MESSAGE_INFO_WATCHDOG_COMMAND { \ + "WATCHDOG_COMMAND", \ + 4, \ + { { "watchdog_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_watchdog_command_t, watchdog_id) }, \ + { "process_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_watchdog_command_t, process_id) }, \ + { "target_system_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_watchdog_command_t, target_system_id) }, \ + { "command_id", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_watchdog_command_t, command_id) }, \ + } \ +} + + +/** + * @brief Pack a watchdog_command message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target_system_id Target system ID + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param command_id Command ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_command_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target_system_id, uint16_t watchdog_id, uint16_t process_id, uint8_t command_id) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_id); + _mav_put_uint8_t(buf, 4, target_system_id); + _mav_put_uint8_t(buf, 5, command_id); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_watchdog_command_t packet; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.target_system_id = target_system_id; + packet.command_id = command_id; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_COMMAND; + return mavlink_finalize_message(msg, system_id, component_id, 6, 162); +} + +/** + * @brief Pack a watchdog_command message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target_system_id Target system ID + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param command_id Command ID + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_command_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target_system_id,uint16_t watchdog_id,uint16_t process_id,uint8_t command_id) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_id); + _mav_put_uint8_t(buf, 4, target_system_id); + _mav_put_uint8_t(buf, 5, command_id); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 6); +#else + mavlink_watchdog_command_t packet; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.target_system_id = target_system_id; + packet.command_id = command_id; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 6); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_COMMAND; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 6, 162); +} + +/** + * @brief Encode a watchdog_command struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param watchdog_command C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_watchdog_command_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_watchdog_command_t* watchdog_command) +{ + return mavlink_msg_watchdog_command_pack(system_id, component_id, msg, watchdog_command->target_system_id, watchdog_command->watchdog_id, watchdog_command->process_id, watchdog_command->command_id); +} + +/** + * @brief Send a watchdog_command message + * @param chan MAVLink channel to send the message + * + * @param target_system_id Target system ID + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param command_id Command ID + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_watchdog_command_send(mavlink_channel_t chan, uint8_t target_system_id, uint16_t watchdog_id, uint16_t process_id, uint8_t command_id) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[6]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_id); + _mav_put_uint8_t(buf, 4, target_system_id); + _mav_put_uint8_t(buf, 5, command_id); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_COMMAND, buf, 6, 162); +#else + mavlink_watchdog_command_t packet; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.target_system_id = target_system_id; + packet.command_id = command_id; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_COMMAND, (const char *)&packet, 6, 162); +#endif +} + +#endif + +// MESSAGE WATCHDOG_COMMAND UNPACKING + + +/** + * @brief Get field target_system_id from watchdog_command message + * + * @return Target system ID + */ +static inline uint8_t mavlink_msg_watchdog_command_get_target_system_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field watchdog_id from watchdog_command message + * + * @return Watchdog ID + */ +static inline uint16_t mavlink_msg_watchdog_command_get_watchdog_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field process_id from watchdog_command message + * + * @return Process ID + */ +static inline uint16_t mavlink_msg_watchdog_command_get_process_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Get field command_id from watchdog_command message + * + * @return Command ID + */ +static inline uint8_t mavlink_msg_watchdog_command_get_command_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Decode a watchdog_command message into a struct + * + * @param msg The message to decode + * @param watchdog_command C-struct to decode the message contents into + */ +static inline void mavlink_msg_watchdog_command_decode(const mavlink_message_t* msg, mavlink_watchdog_command_t* watchdog_command) +{ +#if MAVLINK_NEED_BYTE_SWAP + watchdog_command->watchdog_id = mavlink_msg_watchdog_command_get_watchdog_id(msg); + watchdog_command->process_id = mavlink_msg_watchdog_command_get_process_id(msg); + watchdog_command->target_system_id = mavlink_msg_watchdog_command_get_target_system_id(msg); + watchdog_command->command_id = mavlink_msg_watchdog_command_get_command_id(msg); +#else + memcpy(watchdog_command, _MAV_PAYLOAD(msg), 6); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_watchdog_heartbeat.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_watchdog_heartbeat.h new file mode 100644 index 0000000000..f1fe5eb86a --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_watchdog_heartbeat.h @@ -0,0 +1,166 @@ +// MESSAGE WATCHDOG_HEARTBEAT PACKING + +#define MAVLINK_MSG_ID_WATCHDOG_HEARTBEAT 180 + +typedef struct __mavlink_watchdog_heartbeat_t +{ + uint16_t watchdog_id; ///< Watchdog ID + uint16_t process_count; ///< Number of processes +} mavlink_watchdog_heartbeat_t; + +#define MAVLINK_MSG_ID_WATCHDOG_HEARTBEAT_LEN 4 +#define MAVLINK_MSG_ID_180_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_WATCHDOG_HEARTBEAT { \ + "WATCHDOG_HEARTBEAT", \ + 2, \ + { { "watchdog_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_watchdog_heartbeat_t, watchdog_id) }, \ + { "process_count", NULL, MAVLINK_TYPE_UINT16_T, 0, 2, offsetof(mavlink_watchdog_heartbeat_t, process_count) }, \ + } \ +} + + +/** + * @brief Pack a watchdog_heartbeat message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param watchdog_id Watchdog ID + * @param process_count Number of processes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_heartbeat_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t watchdog_id, uint16_t process_count) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_count); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_watchdog_heartbeat_t packet; + packet.watchdog_id = watchdog_id; + packet.process_count = process_count; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_HEARTBEAT; + return mavlink_finalize_message(msg, system_id, component_id, 4, 153); +} + +/** + * @brief Pack a watchdog_heartbeat message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param watchdog_id Watchdog ID + * @param process_count Number of processes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_heartbeat_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t watchdog_id,uint16_t process_count) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_count); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_watchdog_heartbeat_t packet; + packet.watchdog_id = watchdog_id; + packet.process_count = process_count; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_HEARTBEAT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4, 153); +} + +/** + * @brief Encode a watchdog_heartbeat struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param watchdog_heartbeat C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_watchdog_heartbeat_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_watchdog_heartbeat_t* watchdog_heartbeat) +{ + return mavlink_msg_watchdog_heartbeat_pack(system_id, component_id, msg, watchdog_heartbeat->watchdog_id, watchdog_heartbeat->process_count); +} + +/** + * @brief Send a watchdog_heartbeat message + * @param chan MAVLink channel to send the message + * + * @param watchdog_id Watchdog ID + * @param process_count Number of processes + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_watchdog_heartbeat_send(mavlink_channel_t chan, uint16_t watchdog_id, uint16_t process_count) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, watchdog_id); + _mav_put_uint16_t(buf, 2, process_count); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_HEARTBEAT, buf, 4, 153); +#else + mavlink_watchdog_heartbeat_t packet; + packet.watchdog_id = watchdog_id; + packet.process_count = process_count; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_HEARTBEAT, (const char *)&packet, 4, 153); +#endif +} + +#endif + +// MESSAGE WATCHDOG_HEARTBEAT UNPACKING + + +/** + * @brief Get field watchdog_id from watchdog_heartbeat message + * + * @return Watchdog ID + */ +static inline uint16_t mavlink_msg_watchdog_heartbeat_get_watchdog_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field process_count from watchdog_heartbeat message + * + * @return Number of processes + */ +static inline uint16_t mavlink_msg_watchdog_heartbeat_get_process_count(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 2); +} + +/** + * @brief Decode a watchdog_heartbeat message into a struct + * + * @param msg The message to decode + * @param watchdog_heartbeat C-struct to decode the message contents into + */ +static inline void mavlink_msg_watchdog_heartbeat_decode(const mavlink_message_t* msg, mavlink_watchdog_heartbeat_t* watchdog_heartbeat) +{ +#if MAVLINK_NEED_BYTE_SWAP + watchdog_heartbeat->watchdog_id = mavlink_msg_watchdog_heartbeat_get_watchdog_id(msg); + watchdog_heartbeat->process_count = mavlink_msg_watchdog_heartbeat_get_process_count(msg); +#else + memcpy(watchdog_heartbeat, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_watchdog_process_info.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_watchdog_process_info.h new file mode 100644 index 0000000000..7ba3ddf037 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_watchdog_process_info.h @@ -0,0 +1,227 @@ +// MESSAGE WATCHDOG_PROCESS_INFO PACKING + +#define MAVLINK_MSG_ID_WATCHDOG_PROCESS_INFO 181 + +typedef struct __mavlink_watchdog_process_info_t +{ + int32_t timeout; ///< Timeout (seconds) + uint16_t watchdog_id; ///< Watchdog ID + uint16_t process_id; ///< Process ID + char name[100]; ///< Process name + char arguments[147]; ///< Process arguments +} mavlink_watchdog_process_info_t; + +#define MAVLINK_MSG_ID_WATCHDOG_PROCESS_INFO_LEN 255 +#define MAVLINK_MSG_ID_181_LEN 255 + +#define MAVLINK_MSG_WATCHDOG_PROCESS_INFO_FIELD_NAME_LEN 100 +#define MAVLINK_MSG_WATCHDOG_PROCESS_INFO_FIELD_ARGUMENTS_LEN 147 + +#define MAVLINK_MESSAGE_INFO_WATCHDOG_PROCESS_INFO { \ + "WATCHDOG_PROCESS_INFO", \ + 5, \ + { { "timeout", NULL, MAVLINK_TYPE_INT32_T, 0, 0, offsetof(mavlink_watchdog_process_info_t, timeout) }, \ + { "watchdog_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_watchdog_process_info_t, watchdog_id) }, \ + { "process_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_watchdog_process_info_t, process_id) }, \ + { "name", NULL, MAVLINK_TYPE_CHAR, 100, 8, offsetof(mavlink_watchdog_process_info_t, name) }, \ + { "arguments", NULL, MAVLINK_TYPE_CHAR, 147, 108, offsetof(mavlink_watchdog_process_info_t, arguments) }, \ + } \ +} + + +/** + * @brief Pack a watchdog_process_info message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param name Process name + * @param arguments Process arguments + * @param timeout Timeout (seconds) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_process_info_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t watchdog_id, uint16_t process_id, const char *name, const char *arguments, int32_t timeout) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[255]; + _mav_put_int32_t(buf, 0, timeout); + _mav_put_uint16_t(buf, 4, watchdog_id); + _mav_put_uint16_t(buf, 6, process_id); + _mav_put_char_array(buf, 8, name, 100); + _mav_put_char_array(buf, 108, arguments, 147); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 255); +#else + mavlink_watchdog_process_info_t packet; + packet.timeout = timeout; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + mav_array_memcpy(packet.name, name, sizeof(char)*100); + mav_array_memcpy(packet.arguments, arguments, sizeof(char)*147); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 255); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_PROCESS_INFO; + return mavlink_finalize_message(msg, system_id, component_id, 255, 16); +} + +/** + * @brief Pack a watchdog_process_info message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param name Process name + * @param arguments Process arguments + * @param timeout Timeout (seconds) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_process_info_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t watchdog_id,uint16_t process_id,const char *name,const char *arguments,int32_t timeout) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[255]; + _mav_put_int32_t(buf, 0, timeout); + _mav_put_uint16_t(buf, 4, watchdog_id); + _mav_put_uint16_t(buf, 6, process_id); + _mav_put_char_array(buf, 8, name, 100); + _mav_put_char_array(buf, 108, arguments, 147); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 255); +#else + mavlink_watchdog_process_info_t packet; + packet.timeout = timeout; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + mav_array_memcpy(packet.name, name, sizeof(char)*100); + mav_array_memcpy(packet.arguments, arguments, sizeof(char)*147); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 255); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_PROCESS_INFO; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 255, 16); +} + +/** + * @brief Encode a watchdog_process_info struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param watchdog_process_info C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_watchdog_process_info_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_watchdog_process_info_t* watchdog_process_info) +{ + return mavlink_msg_watchdog_process_info_pack(system_id, component_id, msg, watchdog_process_info->watchdog_id, watchdog_process_info->process_id, watchdog_process_info->name, watchdog_process_info->arguments, watchdog_process_info->timeout); +} + +/** + * @brief Send a watchdog_process_info message + * @param chan MAVLink channel to send the message + * + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param name Process name + * @param arguments Process arguments + * @param timeout Timeout (seconds) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_watchdog_process_info_send(mavlink_channel_t chan, uint16_t watchdog_id, uint16_t process_id, const char *name, const char *arguments, int32_t timeout) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[255]; + _mav_put_int32_t(buf, 0, timeout); + _mav_put_uint16_t(buf, 4, watchdog_id); + _mav_put_uint16_t(buf, 6, process_id); + _mav_put_char_array(buf, 8, name, 100); + _mav_put_char_array(buf, 108, arguments, 147); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_PROCESS_INFO, buf, 255, 16); +#else + mavlink_watchdog_process_info_t packet; + packet.timeout = timeout; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + mav_array_memcpy(packet.name, name, sizeof(char)*100); + mav_array_memcpy(packet.arguments, arguments, sizeof(char)*147); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_PROCESS_INFO, (const char *)&packet, 255, 16); +#endif +} + +#endif + +// MESSAGE WATCHDOG_PROCESS_INFO UNPACKING + + +/** + * @brief Get field watchdog_id from watchdog_process_info message + * + * @return Watchdog ID + */ +static inline uint16_t mavlink_msg_watchdog_process_info_get_watchdog_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field process_id from watchdog_process_info message + * + * @return Process ID + */ +static inline uint16_t mavlink_msg_watchdog_process_info_get_process_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field name from watchdog_process_info message + * + * @return Process name + */ +static inline uint16_t mavlink_msg_watchdog_process_info_get_name(const mavlink_message_t* msg, char *name) +{ + return _MAV_RETURN_char_array(msg, name, 100, 8); +} + +/** + * @brief Get field arguments from watchdog_process_info message + * + * @return Process arguments + */ +static inline uint16_t mavlink_msg_watchdog_process_info_get_arguments(const mavlink_message_t* msg, char *arguments) +{ + return _MAV_RETURN_char_array(msg, arguments, 147, 108); +} + +/** + * @brief Get field timeout from watchdog_process_info message + * + * @return Timeout (seconds) + */ +static inline int32_t mavlink_msg_watchdog_process_info_get_timeout(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 0); +} + +/** + * @brief Decode a watchdog_process_info message into a struct + * + * @param msg The message to decode + * @param watchdog_process_info C-struct to decode the message contents into + */ +static inline void mavlink_msg_watchdog_process_info_decode(const mavlink_message_t* msg, mavlink_watchdog_process_info_t* watchdog_process_info) +{ +#if MAVLINK_NEED_BYTE_SWAP + watchdog_process_info->timeout = mavlink_msg_watchdog_process_info_get_timeout(msg); + watchdog_process_info->watchdog_id = mavlink_msg_watchdog_process_info_get_watchdog_id(msg); + watchdog_process_info->process_id = mavlink_msg_watchdog_process_info_get_process_id(msg); + mavlink_msg_watchdog_process_info_get_name(msg, watchdog_process_info->name); + mavlink_msg_watchdog_process_info_get_arguments(msg, watchdog_process_info->arguments); +#else + memcpy(watchdog_process_info, _MAV_PAYLOAD(msg), 255); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_watchdog_process_status.h b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_watchdog_process_status.h new file mode 100644 index 0000000000..5795c63283 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/mavlink_msg_watchdog_process_status.h @@ -0,0 +1,254 @@ +// MESSAGE WATCHDOG_PROCESS_STATUS PACKING + +#define MAVLINK_MSG_ID_WATCHDOG_PROCESS_STATUS 182 + +typedef struct __mavlink_watchdog_process_status_t +{ + int32_t pid; ///< PID + uint16_t watchdog_id; ///< Watchdog ID + uint16_t process_id; ///< Process ID + uint16_t crashes; ///< Number of crashes + uint8_t state; ///< Is running / finished / suspended / crashed + uint8_t muted; ///< Is muted +} mavlink_watchdog_process_status_t; + +#define MAVLINK_MSG_ID_WATCHDOG_PROCESS_STATUS_LEN 12 +#define MAVLINK_MSG_ID_182_LEN 12 + + + +#define MAVLINK_MESSAGE_INFO_WATCHDOG_PROCESS_STATUS { \ + "WATCHDOG_PROCESS_STATUS", \ + 6, \ + { { "pid", NULL, MAVLINK_TYPE_INT32_T, 0, 0, offsetof(mavlink_watchdog_process_status_t, pid) }, \ + { "watchdog_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 4, offsetof(mavlink_watchdog_process_status_t, watchdog_id) }, \ + { "process_id", NULL, MAVLINK_TYPE_UINT16_T, 0, 6, offsetof(mavlink_watchdog_process_status_t, process_id) }, \ + { "crashes", NULL, MAVLINK_TYPE_UINT16_T, 0, 8, offsetof(mavlink_watchdog_process_status_t, crashes) }, \ + { "state", NULL, MAVLINK_TYPE_UINT8_T, 0, 10, offsetof(mavlink_watchdog_process_status_t, state) }, \ + { "muted", NULL, MAVLINK_TYPE_UINT8_T, 0, 11, offsetof(mavlink_watchdog_process_status_t, muted) }, \ + } \ +} + + +/** + * @brief Pack a watchdog_process_status message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param state Is running / finished / suspended / crashed + * @param muted Is muted + * @param pid PID + * @param crashes Number of crashes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_process_status_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t watchdog_id, uint16_t process_id, uint8_t state, uint8_t muted, int32_t pid, uint16_t crashes) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_int32_t(buf, 0, pid); + _mav_put_uint16_t(buf, 4, watchdog_id); + _mav_put_uint16_t(buf, 6, process_id); + _mav_put_uint16_t(buf, 8, crashes); + _mav_put_uint8_t(buf, 10, state); + _mav_put_uint8_t(buf, 11, muted); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_watchdog_process_status_t packet; + packet.pid = pid; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.crashes = crashes; + packet.state = state; + packet.muted = muted; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_PROCESS_STATUS; + return mavlink_finalize_message(msg, system_id, component_id, 12, 29); +} + +/** + * @brief Pack a watchdog_process_status message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param state Is running / finished / suspended / crashed + * @param muted Is muted + * @param pid PID + * @param crashes Number of crashes + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_watchdog_process_status_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t watchdog_id,uint16_t process_id,uint8_t state,uint8_t muted,int32_t pid,uint16_t crashes) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_int32_t(buf, 0, pid); + _mav_put_uint16_t(buf, 4, watchdog_id); + _mav_put_uint16_t(buf, 6, process_id); + _mav_put_uint16_t(buf, 8, crashes); + _mav_put_uint8_t(buf, 10, state); + _mav_put_uint8_t(buf, 11, muted); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_watchdog_process_status_t packet; + packet.pid = pid; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.crashes = crashes; + packet.state = state; + packet.muted = muted; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_WATCHDOG_PROCESS_STATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12, 29); +} + +/** + * @brief Encode a watchdog_process_status struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param watchdog_process_status C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_watchdog_process_status_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_watchdog_process_status_t* watchdog_process_status) +{ + return mavlink_msg_watchdog_process_status_pack(system_id, component_id, msg, watchdog_process_status->watchdog_id, watchdog_process_status->process_id, watchdog_process_status->state, watchdog_process_status->muted, watchdog_process_status->pid, watchdog_process_status->crashes); +} + +/** + * @brief Send a watchdog_process_status message + * @param chan MAVLink channel to send the message + * + * @param watchdog_id Watchdog ID + * @param process_id Process ID + * @param state Is running / finished / suspended / crashed + * @param muted Is muted + * @param pid PID + * @param crashes Number of crashes + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_watchdog_process_status_send(mavlink_channel_t chan, uint16_t watchdog_id, uint16_t process_id, uint8_t state, uint8_t muted, int32_t pid, uint16_t crashes) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_int32_t(buf, 0, pid); + _mav_put_uint16_t(buf, 4, watchdog_id); + _mav_put_uint16_t(buf, 6, process_id); + _mav_put_uint16_t(buf, 8, crashes); + _mav_put_uint8_t(buf, 10, state); + _mav_put_uint8_t(buf, 11, muted); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_PROCESS_STATUS, buf, 12, 29); +#else + mavlink_watchdog_process_status_t packet; + packet.pid = pid; + packet.watchdog_id = watchdog_id; + packet.process_id = process_id; + packet.crashes = crashes; + packet.state = state; + packet.muted = muted; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_WATCHDOG_PROCESS_STATUS, (const char *)&packet, 12, 29); +#endif +} + +#endif + +// MESSAGE WATCHDOG_PROCESS_STATUS UNPACKING + + +/** + * @brief Get field watchdog_id from watchdog_process_status message + * + * @return Watchdog ID + */ +static inline uint16_t mavlink_msg_watchdog_process_status_get_watchdog_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 4); +} + +/** + * @brief Get field process_id from watchdog_process_status message + * + * @return Process ID + */ +static inline uint16_t mavlink_msg_watchdog_process_status_get_process_id(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 6); +} + +/** + * @brief Get field state from watchdog_process_status message + * + * @return Is running / finished / suspended / crashed + */ +static inline uint8_t mavlink_msg_watchdog_process_status_get_state(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 10); +} + +/** + * @brief Get field muted from watchdog_process_status message + * + * @return Is muted + */ +static inline uint8_t mavlink_msg_watchdog_process_status_get_muted(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 11); +} + +/** + * @brief Get field pid from watchdog_process_status message + * + * @return PID + */ +static inline int32_t mavlink_msg_watchdog_process_status_get_pid(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 0); +} + +/** + * @brief Get field crashes from watchdog_process_status message + * + * @return Number of crashes + */ +static inline uint16_t mavlink_msg_watchdog_process_status_get_crashes(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Decode a watchdog_process_status message into a struct + * + * @param msg The message to decode + * @param watchdog_process_status C-struct to decode the message contents into + */ +static inline void mavlink_msg_watchdog_process_status_decode(const mavlink_message_t* msg, mavlink_watchdog_process_status_t* watchdog_process_status) +{ +#if MAVLINK_NEED_BYTE_SWAP + watchdog_process_status->pid = mavlink_msg_watchdog_process_status_get_pid(msg); + watchdog_process_status->watchdog_id = mavlink_msg_watchdog_process_status_get_watchdog_id(msg); + watchdog_process_status->process_id = mavlink_msg_watchdog_process_status_get_process_id(msg); + watchdog_process_status->crashes = mavlink_msg_watchdog_process_status_get_crashes(msg); + watchdog_process_status->state = mavlink_msg_watchdog_process_status_get_state(msg); + watchdog_process_status->muted = mavlink_msg_watchdog_process_status_get_muted(msg); +#else + memcpy(watchdog_process_status, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/pixhawk/pixhawk.h b/mavlink/include/mavlink/v1.0/pixhawk/pixhawk.h new file mode 100644 index 0000000000..f98852ac97 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/pixhawk.h @@ -0,0 +1,127 @@ +/** @file + * @brief MAVLink comm protocol generated from pixhawk.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef PIXHAWK_H +#define PIXHAWK_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {9, 31, 12, 0, 14, 28, 3, 32, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 20, 2, 25, 23, 30, 101, 22, 26, 16, 14, 28, 32, 28, 28, 22, 22, 21, 6, 6, 37, 4, 4, 2, 2, 4, 2, 2, 3, 13, 12, 19, 17, 15, 15, 27, 25, 18, 18, 20, 20, 9, 54, 26, 0, 36, 0, 6, 4, 0, 21, 18, 0, 0, 0, 20, 0, 33, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 56, 42, 33, 0, 0, 0, 0, 0, 0, 0, 26, 32, 32, 20, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 52, 1, 92, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 26, 16, 0, 0, 0, 0, 0, 0, 0, 4, 255, 12, 6, 0, 0, 0, 0, 0, 0, 106, 43, 55, 12, 255, 53, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 30, 18, 18, 51, 9, 0} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {50, 124, 137, 0, 237, 217, 104, 119, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 214, 159, 220, 168, 24, 23, 170, 144, 67, 115, 39, 246, 185, 104, 237, 244, 222, 212, 9, 254, 230, 28, 28, 132, 221, 232, 11, 153, 41, 39, 214, 223, 141, 33, 15, 3, 100, 24, 239, 238, 30, 200, 183, 0, 130, 0, 148, 21, 0, 52, 124, 0, 0, 0, 20, 0, 152, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 183, 63, 54, 0, 0, 0, 0, 0, 0, 0, 175, 102, 158, 208, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 86, 95, 224, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 249, 182, 0, 0, 0, 0, 0, 0, 0, 153, 16, 29, 162, 0, 0, 0, 0, 0, 0, 90, 95, 36, 23, 223, 88, 0, 0, 0, 0, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 49, 170, 44, 83, 46, 0} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, MAVLINK_MESSAGE_INFO_SYS_STATUS, MAVLINK_MESSAGE_INFO_SYSTEM_TIME, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PING, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK, MAVLINK_MESSAGE_INFO_AUTH_KEY, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_SET_MODE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST, MAVLINK_MESSAGE_INFO_PARAM_VALUE, MAVLINK_MESSAGE_INFO_PARAM_SET, MAVLINK_MESSAGE_INFO_GPS_RAW_INT, MAVLINK_MESSAGE_INFO_GPS_STATUS, MAVLINK_MESSAGE_INFO_SCALED_IMU, MAVLINK_MESSAGE_INFO_RAW_IMU, MAVLINK_MESSAGE_INFO_RAW_PRESSURE, MAVLINK_MESSAGE_INFO_SCALED_PRESSURE, MAVLINK_MESSAGE_INFO_ATTITUDE, MAVLINK_MESSAGE_INFO_ATTITUDE_QUATERNION, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_NED, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT, MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED, MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW, MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW, MAVLINK_MESSAGE_INFO_MISSION_REQUEST_PARTIAL_LIST, MAVLINK_MESSAGE_INFO_MISSION_WRITE_PARTIAL_LIST, MAVLINK_MESSAGE_INFO_MISSION_ITEM, MAVLINK_MESSAGE_INFO_MISSION_REQUEST, MAVLINK_MESSAGE_INFO_MISSION_SET_CURRENT, MAVLINK_MESSAGE_INFO_MISSION_CURRENT, MAVLINK_MESSAGE_INFO_MISSION_REQUEST_LIST, MAVLINK_MESSAGE_INFO_MISSION_COUNT, MAVLINK_MESSAGE_INFO_MISSION_CLEAR_ALL, MAVLINK_MESSAGE_INFO_MISSION_ITEM_REACHED, MAVLINK_MESSAGE_INFO_MISSION_ACK, MAVLINK_MESSAGE_INFO_SET_GPS_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_GPS_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_SET_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_SETPOINT_INT, MAVLINK_MESSAGE_INFO_SET_GLOBAL_POSITION_SETPOINT_INT, MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_SET_QUAD_MOTORS_SETPOINT, MAVLINK_MESSAGE_INFO_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_STATE_CORRECTION, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM, MAVLINK_MESSAGE_INFO_DATA_STREAM, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_MANUAL_CONTROL, MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_VFR_HUD, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_COMMAND_LONG, MAVLINK_MESSAGE_INFO_COMMAND_ACK, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET, MAVLINK_MESSAGE_INFO_HIL_STATE, MAVLINK_MESSAGE_INFO_HIL_CONTROLS, MAVLINK_MESSAGE_INFO_HIL_RC_INPUTS_RAW, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OPTICAL_FLOW, MAVLINK_MESSAGE_INFO_GLOBAL_VISION_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VISION_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VISION_SPEED_ESTIMATE, MAVLINK_MESSAGE_INFO_VICON_POSITION_ESTIMATE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_SET_CAM_SHUTTER, MAVLINK_MESSAGE_INFO_IMAGE_TRIGGERED, MAVLINK_MESSAGE_INFO_IMAGE_TRIGGER_CONTROL, MAVLINK_MESSAGE_INFO_IMAGE_AVAILABLE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_SET_POSITION_CONTROL_OFFSET, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_POSITION_CONTROL_SETPOINT, MAVLINK_MESSAGE_INFO_MARKER, MAVLINK_MESSAGE_INFO_RAW_AUX, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_WATCHDOG_HEARTBEAT, MAVLINK_MESSAGE_INFO_WATCHDOG_PROCESS_INFO, MAVLINK_MESSAGE_INFO_WATCHDOG_PROCESS_STATUS, MAVLINK_MESSAGE_INFO_WATCHDOG_COMMAND, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PATTERN_DETECTED, MAVLINK_MESSAGE_INFO_POINT_OF_INTEREST, MAVLINK_MESSAGE_INFO_POINT_OF_INTEREST_CONNECTION, MAVLINK_MESSAGE_INFO_DATA_TRANSMISSION_HANDSHAKE, MAVLINK_MESSAGE_INFO_ENCAPSULATED_DATA, MAVLINK_MESSAGE_INFO_BRIEF_FEATURE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_ATTITUDE_CONTROL, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_MEMORY_VECT, MAVLINK_MESSAGE_INFO_DEBUG_VECT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT, MAVLINK_MESSAGE_INFO_STATUSTEXT, MAVLINK_MESSAGE_INFO_DEBUG, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_PIXHAWK + +#include "../common/common.h" + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +// ENUM DEFINITIONS + + +/** @brief Content Types for data transmission handshake */ +#ifndef HAVE_ENUM_DATA_TYPES +#define HAVE_ENUM_DATA_TYPES +enum DATA_TYPES +{ + DATA_TYPE_JPEG_IMAGE=1, /* | */ + DATA_TYPE_RAW_IMAGE=2, /* | */ + DATA_TYPE_KINECT=3, /* | */ + DATA_TYPES_ENUM_END=4, /* | */ +}; +#endif + +/** @brief */ +#ifndef HAVE_ENUM_MAV_CMD +#define HAVE_ENUM_MAV_CMD +enum MAV_CMD +{ + MAV_CMD_NAV_WAYPOINT=16, /* Navigate to MISSION. |Hold time in decimal seconds. (ignored by fixed wing, time to stay at MISSION for rotary wing)| Acceptance radius in meters (if the sphere with this radius is hit, the MISSION counts as reached)| 0 to pass through the WP, if > 0 radius in meters to pass by WP. Positive value for clockwise orbit, negative value for counter-clockwise orbit. Allows trajectory control.| Desired yaw angle at MISSION (rotary wing)| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_UNLIM=17, /* Loiter around this MISSION an unlimited amount of time |Empty| Empty| Radius around MISSION, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_TURNS=18, /* Loiter around this MISSION for X turns |Turns| Empty| Radius around MISSION, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_LOITER_TIME=19, /* Loiter around this MISSION for X seconds |Seconds (decimal)| Empty| Radius around MISSION, in meters. If positive loiter clockwise, else counter-clockwise| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_RETURN_TO_LAUNCH=20, /* Return to launch location |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_NAV_LAND=21, /* Land at location |Empty| Empty| Empty| Desired yaw angle.| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_TAKEOFF=22, /* Takeoff from ground / hand |Minimum pitch (if airspeed sensor present), desired pitch without sensor| Empty| Empty| Yaw angle (if magnetometer present), ignored without magnetometer| Latitude| Longitude| Altitude| */ + MAV_CMD_NAV_ROI=80, /* Sets the region of interest (ROI) for a sensor set or the vehicle itself. This can then be used by the vehicles control system to control the vehicle attitude and the attitude of various sensors such as cameras. |Region of intereset mode. (see MAV_ROI enum)| MISSION index/ target ID. (see MAV_ROI enum)| ROI index (allows a vehicle to manage multiple ROI's)| Empty| x the location of the fixed ROI (see MAV_FRAME)| y| z| */ + MAV_CMD_NAV_PATHPLANNING=81, /* Control autonomous path planning on the MAV. |0: Disable local obstacle avoidance / local path planning (without resetting map), 1: Enable local path planning, 2: Enable and reset local path planning| 0: Disable full path planning (without resetting map), 1: Enable, 2: Enable and reset map/occupancy grid, 3: Enable and reset planned route, but not occupancy grid| Empty| Yaw angle at goal, in compass degrees, [0..360]| Latitude/X of goal| Longitude/Y of goal| Altitude/Z of goal| */ + MAV_CMD_NAV_LAST=95, /* NOP - This command is only used to mark the upper limit of the NAV/ACTION commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_DELAY=112, /* Delay mission state machine. |Delay in seconds (decimal)| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_CHANGE_ALT=113, /* Ascend/descend at rate. Delay mission state machine until desired altitude reached. |Descent / Ascend rate (m/s)| Empty| Empty| Empty| Empty| Empty| Finish Altitude| */ + MAV_CMD_CONDITION_DISTANCE=114, /* Delay mission state machine until within desired distance of next NAV point. |Distance (meters)| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_YAW=115, /* Reach a certain target angle. |target angle: [0-360], 0 is north| speed during yaw change:[deg per second]| direction: negative: counter clockwise, positive: clockwise [-1,1]| relative offset or absolute angle: [ 1,0]| Empty| Empty| Empty| */ + MAV_CMD_CONDITION_LAST=159, /* NOP - This command is only used to mark the upper limit of the CONDITION commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_MODE=176, /* Set system mode. |Mode, as defined by ENUM MAV_MODE| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_JUMP=177, /* Jump to the desired command in the mission list. Repeat this action only the specified number of times |Sequence number| Repeat count| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_CHANGE_SPEED=178, /* Change speed and/or throttle set points. |Speed type (0=Airspeed, 1=Ground Speed)| Speed (m/s, -1 indicates no change)| Throttle ( Percent, -1 indicates no change)| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_HOME=179, /* Changes the home location either to the current location or a specified location. |Use current (1=use current location, 0=use specified location)| Empty| Empty| Empty| Latitude| Longitude| Altitude| */ + MAV_CMD_DO_SET_PARAMETER=180, /* Set a system parameter. Caution! Use of this command requires knowledge of the numeric enumeration value of the parameter. |Parameter number| Parameter value| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_RELAY=181, /* Set a relay to a condition. |Relay number| Setting (1=on, 0=off, others possible depending on system hardware)| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_REPEAT_RELAY=182, /* Cycle a relay on and off for a desired number of cyles with a desired period. |Relay number| Cycle count| Cycle time (seconds, decimal)| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_SET_SERVO=183, /* Set a servo to a desired PWM value. |Servo number| PWM (microseconds, 1000 to 2000 typical)| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_DO_REPEAT_SERVO=184, /* Cycle a between its nominal setting and a desired PWM for a desired number of cycles with a desired period. |Servo number| PWM (microseconds, 1000 to 2000 typical)| Cycle count| Cycle time (seconds)| Empty| Empty| Empty| */ + MAV_CMD_DO_CONTROL_VIDEO=200, /* Control onboard camera system. |Camera ID (-1 for all)| Transmission: 0: disabled, 1: enabled compressed, 2: enabled raw| Transmission mode: 0: video stream, >0: single images every n seconds (decimal)| Recording: 0: disabled, 1: enabled compressed, 2: enabled raw| Empty| Empty| Empty| */ + MAV_CMD_DO_LAST=240, /* NOP - This command is only used to mark the upper limit of the DO commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ + MAV_CMD_PREFLIGHT_CALIBRATION=241, /* Trigger calibration. This command will be only accepted if in pre-flight mode. |Gyro calibration: 0: no, 1: yes| Magnetometer calibration: 0: no, 1: yes| Ground pressure: 0: no, 1: yes| Radio calibration: 0: no, 1: yes| Empty| Empty| Empty| */ + MAV_CMD_PREFLIGHT_SET_SENSOR_OFFSETS=242, /* Set sensor offsets. This command will be only accepted if in pre-flight mode. |Sensor to adjust the offsets for: 0: gyros, 1: accelerometer, 2: magnetometer, 3: barometer, 4: optical flow| X axis offset (or generic dimension 1), in the sensor's raw units| Y axis offset (or generic dimension 2), in the sensor's raw units| Z axis offset (or generic dimension 3), in the sensor's raw units| Generic dimension 4, in the sensor's raw units| Generic dimension 5, in the sensor's raw units| Generic dimension 6, in the sensor's raw units| */ + MAV_CMD_PREFLIGHT_STORAGE=245, /* Request storage of different parameter values and logs. This command will be only accepted if in pre-flight mode. |Parameter storage: 0: READ FROM FLASH/EEPROM, 1: WRITE CURRENT TO FLASH/EEPROM| Mission storage: 0: READ FROM FLASH/EEPROM, 1: WRITE CURRENT TO FLASH/EEPROM| Reserved| Reserved| Empty| Empty| Empty| */ + MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN=246, /* Request the reboot or shutdown of system components. |0: Do nothing for autopilot, 1: Reboot autopilot, 2: Shutdown autopilot.| 0: Do nothing for onboard computer, 1: Reboot onboard computer, 2: Shutdown onboard computer.| Reserved| Reserved| Empty| Empty| Empty| */ + MAV_CMD_OVERRIDE_GOTO=252, /* Hold / continue the current action |MAV_GOTO_DO_HOLD: hold MAV_GOTO_DO_CONTINUE: continue with next item in mission plan| MAV_GOTO_HOLD_AT_CURRENT_POSITION: Hold at current position MAV_GOTO_HOLD_AT_SPECIFIED_POSITION: hold at specified position| MAV_FRAME coordinate frame of hold point| Desired yaw angle in degrees| Latitude / X position| Longitude / Y position| Altitude / Z position| */ + MAV_CMD_MISSION_START=300, /* start running a mission |first_item: the first mission item to run| last_item: the last mission item to run (after this item is run, the mission ends)| */ + MAV_CMD_COMPONENT_ARM_DISARM=400, /* Arms / Disarms a component |1 to arm, 0 to disarm| */ + MAV_CMD_ENUM_END=401, /* | */ + MAV_CMD_DO_START_SEARCH=10001, /* Starts a search |1 to arm, 0 to disarm| */ + MAV_CMD_DO_FINISH_SEARCH=10002, /* Starts a search |1 to arm, 0 to disarm| */ + MAV_CMD_NAV_SWEEP=10003, /* Starts a search |1 to arm, 0 to disarm| */ +}; +#endif + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_set_cam_shutter.h" +#include "./mavlink_msg_image_triggered.h" +#include "./mavlink_msg_image_trigger_control.h" +#include "./mavlink_msg_image_available.h" +#include "./mavlink_msg_set_position_control_offset.h" +#include "./mavlink_msg_position_control_setpoint.h" +#include "./mavlink_msg_marker.h" +#include "./mavlink_msg_raw_aux.h" +#include "./mavlink_msg_watchdog_heartbeat.h" +#include "./mavlink_msg_watchdog_process_info.h" +#include "./mavlink_msg_watchdog_process_status.h" +#include "./mavlink_msg_watchdog_command.h" +#include "./mavlink_msg_pattern_detected.h" +#include "./mavlink_msg_point_of_interest.h" +#include "./mavlink_msg_point_of_interest_connection.h" +#include "./mavlink_msg_data_transmission_handshake.h" +#include "./mavlink_msg_encapsulated_data.h" +#include "./mavlink_msg_brief_feature.h" +#include "./mavlink_msg_attitude_control.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // PIXHAWK_H diff --git a/mavlink/include/mavlink/v1.0/pixhawk/pixhawk.pb.h b/mavlink/include/mavlink/v1.0/pixhawk/pixhawk.pb.h new file mode 100644 index 0000000000..7556606e98 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/pixhawk.pb.h @@ -0,0 +1,3663 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: pixhawk.proto + +#ifndef PROTOBUF_pixhawk_2eproto__INCLUDED +#define PROTOBUF_pixhawk_2eproto__INCLUDED + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 2004000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 2004001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace px { + +// Internal implementation detail -- do not call these. +void protobuf_AddDesc_pixhawk_2eproto(); +void protobuf_AssignDesc_pixhawk_2eproto(); +void protobuf_ShutdownFile_pixhawk_2eproto(); + +class HeaderInfo; +class GLOverlay; +class Obstacle; +class ObstacleList; +class ObstacleMap; +class Path; +class PointCloudXYZI; +class PointCloudXYZI_PointXYZI; +class PointCloudXYZRGB; +class PointCloudXYZRGB_PointXYZRGB; +class RGBDImage; +class Waypoint; + +enum GLOverlay_CoordinateFrameType { + GLOverlay_CoordinateFrameType_GLOBAL = 0, + GLOverlay_CoordinateFrameType_LOCAL = 1 +}; +bool GLOverlay_CoordinateFrameType_IsValid(int value); +const GLOverlay_CoordinateFrameType GLOverlay_CoordinateFrameType_CoordinateFrameType_MIN = GLOverlay_CoordinateFrameType_GLOBAL; +const GLOverlay_CoordinateFrameType GLOverlay_CoordinateFrameType_CoordinateFrameType_MAX = GLOverlay_CoordinateFrameType_LOCAL; +const int GLOverlay_CoordinateFrameType_CoordinateFrameType_ARRAYSIZE = GLOverlay_CoordinateFrameType_CoordinateFrameType_MAX + 1; + +const ::google::protobuf::EnumDescriptor* GLOverlay_CoordinateFrameType_descriptor(); +inline const ::std::string& GLOverlay_CoordinateFrameType_Name(GLOverlay_CoordinateFrameType value) { + return ::google::protobuf::internal::NameOfEnum( + GLOverlay_CoordinateFrameType_descriptor(), value); +} +inline bool GLOverlay_CoordinateFrameType_Parse( + const ::std::string& name, GLOverlay_CoordinateFrameType* value) { + return ::google::protobuf::internal::ParseNamedEnum( + GLOverlay_CoordinateFrameType_descriptor(), name, value); +} +enum GLOverlay_Mode { + GLOverlay_Mode_POINTS = 0, + GLOverlay_Mode_LINES = 1, + GLOverlay_Mode_LINE_STRIP = 2, + GLOverlay_Mode_LINE_LOOP = 3, + GLOverlay_Mode_TRIANGLES = 4, + GLOverlay_Mode_TRIANGLE_STRIP = 5, + GLOverlay_Mode_TRIANGLE_FAN = 6, + GLOverlay_Mode_QUADS = 7, + GLOverlay_Mode_QUAD_STRIP = 8, + GLOverlay_Mode_POLYGON = 9, + GLOverlay_Mode_SOLID_CIRCLE = 10, + GLOverlay_Mode_WIRE_CIRCLE = 11, + GLOverlay_Mode_SOLID_CUBE = 12, + GLOverlay_Mode_WIRE_CUBE = 13 +}; +bool GLOverlay_Mode_IsValid(int value); +const GLOverlay_Mode GLOverlay_Mode_Mode_MIN = GLOverlay_Mode_POINTS; +const GLOverlay_Mode GLOverlay_Mode_Mode_MAX = GLOverlay_Mode_WIRE_CUBE; +const int GLOverlay_Mode_Mode_ARRAYSIZE = GLOverlay_Mode_Mode_MAX + 1; + +const ::google::protobuf::EnumDescriptor* GLOverlay_Mode_descriptor(); +inline const ::std::string& GLOverlay_Mode_Name(GLOverlay_Mode value) { + return ::google::protobuf::internal::NameOfEnum( + GLOverlay_Mode_descriptor(), value); +} +inline bool GLOverlay_Mode_Parse( + const ::std::string& name, GLOverlay_Mode* value) { + return ::google::protobuf::internal::ParseNamedEnum( + GLOverlay_Mode_descriptor(), name, value); +} +enum GLOverlay_Identifier { + GLOverlay_Identifier_END = 14, + GLOverlay_Identifier_VERTEX2F = 15, + GLOverlay_Identifier_VERTEX3F = 16, + GLOverlay_Identifier_ROTATEF = 17, + GLOverlay_Identifier_TRANSLATEF = 18, + GLOverlay_Identifier_SCALEF = 19, + GLOverlay_Identifier_PUSH_MATRIX = 20, + GLOverlay_Identifier_POP_MATRIX = 21, + GLOverlay_Identifier_COLOR3F = 22, + GLOverlay_Identifier_COLOR4F = 23, + GLOverlay_Identifier_POINTSIZE = 24, + GLOverlay_Identifier_LINEWIDTH = 25 +}; +bool GLOverlay_Identifier_IsValid(int value); +const GLOverlay_Identifier GLOverlay_Identifier_Identifier_MIN = GLOverlay_Identifier_END; +const GLOverlay_Identifier GLOverlay_Identifier_Identifier_MAX = GLOverlay_Identifier_LINEWIDTH; +const int GLOverlay_Identifier_Identifier_ARRAYSIZE = GLOverlay_Identifier_Identifier_MAX + 1; + +const ::google::protobuf::EnumDescriptor* GLOverlay_Identifier_descriptor(); +inline const ::std::string& GLOverlay_Identifier_Name(GLOverlay_Identifier value) { + return ::google::protobuf::internal::NameOfEnum( + GLOverlay_Identifier_descriptor(), value); +} +inline bool GLOverlay_Identifier_Parse( + const ::std::string& name, GLOverlay_Identifier* value) { + return ::google::protobuf::internal::ParseNamedEnum( + GLOverlay_Identifier_descriptor(), name, value); +} +// =================================================================== + +class HeaderInfo : public ::google::protobuf::Message { + public: + HeaderInfo(); + virtual ~HeaderInfo(); + + HeaderInfo(const HeaderInfo& from); + + inline HeaderInfo& operator=(const HeaderInfo& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const HeaderInfo& default_instance(); + + void Swap(HeaderInfo* other); + + // implements Message ---------------------------------------------- + + HeaderInfo* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const HeaderInfo& from); + void MergeFrom(const HeaderInfo& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required int32 source_sysid = 1; + inline bool has_source_sysid() const; + inline void clear_source_sysid(); + static const int kSourceSysidFieldNumber = 1; + inline ::google::protobuf::int32 source_sysid() const; + inline void set_source_sysid(::google::protobuf::int32 value); + + // required int32 source_compid = 2; + inline bool has_source_compid() const; + inline void clear_source_compid(); + static const int kSourceCompidFieldNumber = 2; + inline ::google::protobuf::int32 source_compid() const; + inline void set_source_compid(::google::protobuf::int32 value); + + // required double timestamp = 3; + inline bool has_timestamp() const; + inline void clear_timestamp(); + static const int kTimestampFieldNumber = 3; + inline double timestamp() const; + inline void set_timestamp(double value); + + // @@protoc_insertion_point(class_scope:px.HeaderInfo) + private: + inline void set_has_source_sysid(); + inline void clear_has_source_sysid(); + inline void set_has_source_compid(); + inline void clear_has_source_compid(); + inline void set_has_timestamp(); + inline void clear_has_timestamp(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::int32 source_sysid_; + ::google::protobuf::int32 source_compid_; + double timestamp_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static HeaderInfo* default_instance_; +}; +// ------------------------------------------------------------------- + +class GLOverlay : public ::google::protobuf::Message { + public: + GLOverlay(); + virtual ~GLOverlay(); + + GLOverlay(const GLOverlay& from); + + inline GLOverlay& operator=(const GLOverlay& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const GLOverlay& default_instance(); + + void Swap(GLOverlay* other); + + // implements Message ---------------------------------------------- + + GLOverlay* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const GLOverlay& from); + void MergeFrom(const GLOverlay& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef GLOverlay_CoordinateFrameType CoordinateFrameType; + static const CoordinateFrameType GLOBAL = GLOverlay_CoordinateFrameType_GLOBAL; + static const CoordinateFrameType LOCAL = GLOverlay_CoordinateFrameType_LOCAL; + static inline bool CoordinateFrameType_IsValid(int value) { + return GLOverlay_CoordinateFrameType_IsValid(value); + } + static const CoordinateFrameType CoordinateFrameType_MIN = + GLOverlay_CoordinateFrameType_CoordinateFrameType_MIN; + static const CoordinateFrameType CoordinateFrameType_MAX = + GLOverlay_CoordinateFrameType_CoordinateFrameType_MAX; + static const int CoordinateFrameType_ARRAYSIZE = + GLOverlay_CoordinateFrameType_CoordinateFrameType_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + CoordinateFrameType_descriptor() { + return GLOverlay_CoordinateFrameType_descriptor(); + } + static inline const ::std::string& CoordinateFrameType_Name(CoordinateFrameType value) { + return GLOverlay_CoordinateFrameType_Name(value); + } + static inline bool CoordinateFrameType_Parse(const ::std::string& name, + CoordinateFrameType* value) { + return GLOverlay_CoordinateFrameType_Parse(name, value); + } + + typedef GLOverlay_Mode Mode; + static const Mode POINTS = GLOverlay_Mode_POINTS; + static const Mode LINES = GLOverlay_Mode_LINES; + static const Mode LINE_STRIP = GLOverlay_Mode_LINE_STRIP; + static const Mode LINE_LOOP = GLOverlay_Mode_LINE_LOOP; + static const Mode TRIANGLES = GLOverlay_Mode_TRIANGLES; + static const Mode TRIANGLE_STRIP = GLOverlay_Mode_TRIANGLE_STRIP; + static const Mode TRIANGLE_FAN = GLOverlay_Mode_TRIANGLE_FAN; + static const Mode QUADS = GLOverlay_Mode_QUADS; + static const Mode QUAD_STRIP = GLOverlay_Mode_QUAD_STRIP; + static const Mode POLYGON = GLOverlay_Mode_POLYGON; + static const Mode SOLID_CIRCLE = GLOverlay_Mode_SOLID_CIRCLE; + static const Mode WIRE_CIRCLE = GLOverlay_Mode_WIRE_CIRCLE; + static const Mode SOLID_CUBE = GLOverlay_Mode_SOLID_CUBE; + static const Mode WIRE_CUBE = GLOverlay_Mode_WIRE_CUBE; + static inline bool Mode_IsValid(int value) { + return GLOverlay_Mode_IsValid(value); + } + static const Mode Mode_MIN = + GLOverlay_Mode_Mode_MIN; + static const Mode Mode_MAX = + GLOverlay_Mode_Mode_MAX; + static const int Mode_ARRAYSIZE = + GLOverlay_Mode_Mode_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + Mode_descriptor() { + return GLOverlay_Mode_descriptor(); + } + static inline const ::std::string& Mode_Name(Mode value) { + return GLOverlay_Mode_Name(value); + } + static inline bool Mode_Parse(const ::std::string& name, + Mode* value) { + return GLOverlay_Mode_Parse(name, value); + } + + typedef GLOverlay_Identifier Identifier; + static const Identifier END = GLOverlay_Identifier_END; + static const Identifier VERTEX2F = GLOverlay_Identifier_VERTEX2F; + static const Identifier VERTEX3F = GLOverlay_Identifier_VERTEX3F; + static const Identifier ROTATEF = GLOverlay_Identifier_ROTATEF; + static const Identifier TRANSLATEF = GLOverlay_Identifier_TRANSLATEF; + static const Identifier SCALEF = GLOverlay_Identifier_SCALEF; + static const Identifier PUSH_MATRIX = GLOverlay_Identifier_PUSH_MATRIX; + static const Identifier POP_MATRIX = GLOverlay_Identifier_POP_MATRIX; + static const Identifier COLOR3F = GLOverlay_Identifier_COLOR3F; + static const Identifier COLOR4F = GLOverlay_Identifier_COLOR4F; + static const Identifier POINTSIZE = GLOverlay_Identifier_POINTSIZE; + static const Identifier LINEWIDTH = GLOverlay_Identifier_LINEWIDTH; + static inline bool Identifier_IsValid(int value) { + return GLOverlay_Identifier_IsValid(value); + } + static const Identifier Identifier_MIN = + GLOverlay_Identifier_Identifier_MIN; + static const Identifier Identifier_MAX = + GLOverlay_Identifier_Identifier_MAX; + static const int Identifier_ARRAYSIZE = + GLOverlay_Identifier_Identifier_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + Identifier_descriptor() { + return GLOverlay_Identifier_descriptor(); + } + static inline const ::std::string& Identifier_Name(Identifier value) { + return GLOverlay_Identifier_Name(value); + } + static inline bool Identifier_Parse(const ::std::string& name, + Identifier* value) { + return GLOverlay_Identifier_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // optional string name = 2; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 2; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + + // optional .px.GLOverlay.CoordinateFrameType coordinateFrameType = 3; + inline bool has_coordinateframetype() const; + inline void clear_coordinateframetype(); + static const int kCoordinateFrameTypeFieldNumber = 3; + inline ::px::GLOverlay_CoordinateFrameType coordinateframetype() const; + inline void set_coordinateframetype(::px::GLOverlay_CoordinateFrameType value); + + // optional double origin_x = 4; + inline bool has_origin_x() const; + inline void clear_origin_x(); + static const int kOriginXFieldNumber = 4; + inline double origin_x() const; + inline void set_origin_x(double value); + + // optional double origin_y = 5; + inline bool has_origin_y() const; + inline void clear_origin_y(); + static const int kOriginYFieldNumber = 5; + inline double origin_y() const; + inline void set_origin_y(double value); + + // optional double origin_z = 6; + inline bool has_origin_z() const; + inline void clear_origin_z(); + static const int kOriginZFieldNumber = 6; + inline double origin_z() const; + inline void set_origin_z(double value); + + // optional bytes data = 7; + inline bool has_data() const; + inline void clear_data(); + static const int kDataFieldNumber = 7; + inline const ::std::string& data() const; + inline void set_data(const ::std::string& value); + inline void set_data(const char* value); + inline void set_data(const void* value, size_t size); + inline ::std::string* mutable_data(); + inline ::std::string* release_data(); + + // @@protoc_insertion_point(class_scope:px.GLOverlay) + private: + inline void set_has_header(); + inline void clear_has_header(); + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_coordinateframetype(); + inline void clear_has_coordinateframetype(); + inline void set_has_origin_x(); + inline void clear_has_origin_x(); + inline void set_has_origin_y(); + inline void clear_has_origin_y(); + inline void set_has_origin_z(); + inline void clear_has_origin_z(); + inline void set_has_data(); + inline void clear_has_data(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::std::string* name_; + double origin_x_; + double origin_y_; + double origin_z_; + ::std::string* data_; + int coordinateframetype_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static GLOverlay* default_instance_; +}; +// ------------------------------------------------------------------- + +class Obstacle : public ::google::protobuf::Message { + public: + Obstacle(); + virtual ~Obstacle(); + + Obstacle(const Obstacle& from); + + inline Obstacle& operator=(const Obstacle& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const Obstacle& default_instance(); + + void Swap(Obstacle* other); + + // implements Message ---------------------------------------------- + + Obstacle* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const Obstacle& from); + void MergeFrom(const Obstacle& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional float x = 1; + inline bool has_x() const; + inline void clear_x(); + static const int kXFieldNumber = 1; + inline float x() const; + inline void set_x(float value); + + // optional float y = 2; + inline bool has_y() const; + inline void clear_y(); + static const int kYFieldNumber = 2; + inline float y() const; + inline void set_y(float value); + + // optional float z = 3; + inline bool has_z() const; + inline void clear_z(); + static const int kZFieldNumber = 3; + inline float z() const; + inline void set_z(float value); + + // optional float length = 4; + inline bool has_length() const; + inline void clear_length(); + static const int kLengthFieldNumber = 4; + inline float length() const; + inline void set_length(float value); + + // optional float width = 5; + inline bool has_width() const; + inline void clear_width(); + static const int kWidthFieldNumber = 5; + inline float width() const; + inline void set_width(float value); + + // optional float height = 6; + inline bool has_height() const; + inline void clear_height(); + static const int kHeightFieldNumber = 6; + inline float height() const; + inline void set_height(float value); + + // @@protoc_insertion_point(class_scope:px.Obstacle) + private: + inline void set_has_x(); + inline void clear_has_x(); + inline void set_has_y(); + inline void clear_has_y(); + inline void set_has_z(); + inline void clear_has_z(); + inline void set_has_length(); + inline void clear_has_length(); + inline void set_has_width(); + inline void clear_has_width(); + inline void set_has_height(); + inline void clear_has_height(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + float x_; + float y_; + float z_; + float length_; + float width_; + float height_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static Obstacle* default_instance_; +}; +// ------------------------------------------------------------------- + +class ObstacleList : public ::google::protobuf::Message { + public: + ObstacleList(); + virtual ~ObstacleList(); + + ObstacleList(const ObstacleList& from); + + inline ObstacleList& operator=(const ObstacleList& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ObstacleList& default_instance(); + + void Swap(ObstacleList* other); + + // implements Message ---------------------------------------------- + + ObstacleList* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ObstacleList& from); + void MergeFrom(const ObstacleList& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // repeated .px.Obstacle obstacles = 2; + inline int obstacles_size() const; + inline void clear_obstacles(); + static const int kObstaclesFieldNumber = 2; + inline const ::px::Obstacle& obstacles(int index) const; + inline ::px::Obstacle* mutable_obstacles(int index); + inline ::px::Obstacle* add_obstacles(); + inline const ::google::protobuf::RepeatedPtrField< ::px::Obstacle >& + obstacles() const; + inline ::google::protobuf::RepeatedPtrField< ::px::Obstacle >* + mutable_obstacles(); + + // @@protoc_insertion_point(class_scope:px.ObstacleList) + private: + inline void set_has_header(); + inline void clear_has_header(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::google::protobuf::RepeatedPtrField< ::px::Obstacle > obstacles_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static ObstacleList* default_instance_; +}; +// ------------------------------------------------------------------- + +class ObstacleMap : public ::google::protobuf::Message { + public: + ObstacleMap(); + virtual ~ObstacleMap(); + + ObstacleMap(const ObstacleMap& from); + + inline ObstacleMap& operator=(const ObstacleMap& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ObstacleMap& default_instance(); + + void Swap(ObstacleMap* other); + + // implements Message ---------------------------------------------- + + ObstacleMap* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ObstacleMap& from); + void MergeFrom(const ObstacleMap& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // required int32 type = 2; + inline bool has_type() const; + inline void clear_type(); + static const int kTypeFieldNumber = 2; + inline ::google::protobuf::int32 type() const; + inline void set_type(::google::protobuf::int32 value); + + // optional float resolution = 3; + inline bool has_resolution() const; + inline void clear_resolution(); + static const int kResolutionFieldNumber = 3; + inline float resolution() const; + inline void set_resolution(float value); + + // optional int32 rows = 4; + inline bool has_rows() const; + inline void clear_rows(); + static const int kRowsFieldNumber = 4; + inline ::google::protobuf::int32 rows() const; + inline void set_rows(::google::protobuf::int32 value); + + // optional int32 cols = 5; + inline bool has_cols() const; + inline void clear_cols(); + static const int kColsFieldNumber = 5; + inline ::google::protobuf::int32 cols() const; + inline void set_cols(::google::protobuf::int32 value); + + // optional int32 mapR0 = 6; + inline bool has_mapr0() const; + inline void clear_mapr0(); + static const int kMapR0FieldNumber = 6; + inline ::google::protobuf::int32 mapr0() const; + inline void set_mapr0(::google::protobuf::int32 value); + + // optional int32 mapC0 = 7; + inline bool has_mapc0() const; + inline void clear_mapc0(); + static const int kMapC0FieldNumber = 7; + inline ::google::protobuf::int32 mapc0() const; + inline void set_mapc0(::google::protobuf::int32 value); + + // optional int32 arrayR0 = 8; + inline bool has_arrayr0() const; + inline void clear_arrayr0(); + static const int kArrayR0FieldNumber = 8; + inline ::google::protobuf::int32 arrayr0() const; + inline void set_arrayr0(::google::protobuf::int32 value); + + // optional int32 arrayC0 = 9; + inline bool has_arrayc0() const; + inline void clear_arrayc0(); + static const int kArrayC0FieldNumber = 9; + inline ::google::protobuf::int32 arrayc0() const; + inline void set_arrayc0(::google::protobuf::int32 value); + + // optional bytes data = 10; + inline bool has_data() const; + inline void clear_data(); + static const int kDataFieldNumber = 10; + inline const ::std::string& data() const; + inline void set_data(const ::std::string& value); + inline void set_data(const char* value); + inline void set_data(const void* value, size_t size); + inline ::std::string* mutable_data(); + inline ::std::string* release_data(); + + // @@protoc_insertion_point(class_scope:px.ObstacleMap) + private: + inline void set_has_header(); + inline void clear_has_header(); + inline void set_has_type(); + inline void clear_has_type(); + inline void set_has_resolution(); + inline void clear_has_resolution(); + inline void set_has_rows(); + inline void clear_has_rows(); + inline void set_has_cols(); + inline void clear_has_cols(); + inline void set_has_mapr0(); + inline void clear_has_mapr0(); + inline void set_has_mapc0(); + inline void clear_has_mapc0(); + inline void set_has_arrayr0(); + inline void clear_has_arrayr0(); + inline void set_has_arrayc0(); + inline void clear_has_arrayc0(); + inline void set_has_data(); + inline void clear_has_data(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::google::protobuf::int32 type_; + float resolution_; + ::google::protobuf::int32 rows_; + ::google::protobuf::int32 cols_; + ::google::protobuf::int32 mapr0_; + ::google::protobuf::int32 mapc0_; + ::google::protobuf::int32 arrayr0_; + ::google::protobuf::int32 arrayc0_; + ::std::string* data_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(10 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static ObstacleMap* default_instance_; +}; +// ------------------------------------------------------------------- + +class Path : public ::google::protobuf::Message { + public: + Path(); + virtual ~Path(); + + Path(const Path& from); + + inline Path& operator=(const Path& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const Path& default_instance(); + + void Swap(Path* other); + + // implements Message ---------------------------------------------- + + Path* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const Path& from); + void MergeFrom(const Path& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // repeated .px.Waypoint waypoints = 2; + inline int waypoints_size() const; + inline void clear_waypoints(); + static const int kWaypointsFieldNumber = 2; + inline const ::px::Waypoint& waypoints(int index) const; + inline ::px::Waypoint* mutable_waypoints(int index); + inline ::px::Waypoint* add_waypoints(); + inline const ::google::protobuf::RepeatedPtrField< ::px::Waypoint >& + waypoints() const; + inline ::google::protobuf::RepeatedPtrField< ::px::Waypoint >* + mutable_waypoints(); + + // @@protoc_insertion_point(class_scope:px.Path) + private: + inline void set_has_header(); + inline void clear_has_header(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::google::protobuf::RepeatedPtrField< ::px::Waypoint > waypoints_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static Path* default_instance_; +}; +// ------------------------------------------------------------------- + +class PointCloudXYZI_PointXYZI : public ::google::protobuf::Message { + public: + PointCloudXYZI_PointXYZI(); + virtual ~PointCloudXYZI_PointXYZI(); + + PointCloudXYZI_PointXYZI(const PointCloudXYZI_PointXYZI& from); + + inline PointCloudXYZI_PointXYZI& operator=(const PointCloudXYZI_PointXYZI& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const PointCloudXYZI_PointXYZI& default_instance(); + + void Swap(PointCloudXYZI_PointXYZI* other); + + // implements Message ---------------------------------------------- + + PointCloudXYZI_PointXYZI* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const PointCloudXYZI_PointXYZI& from); + void MergeFrom(const PointCloudXYZI_PointXYZI& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required float x = 1; + inline bool has_x() const; + inline void clear_x(); + static const int kXFieldNumber = 1; + inline float x() const; + inline void set_x(float value); + + // required float y = 2; + inline bool has_y() const; + inline void clear_y(); + static const int kYFieldNumber = 2; + inline float y() const; + inline void set_y(float value); + + // required float z = 3; + inline bool has_z() const; + inline void clear_z(); + static const int kZFieldNumber = 3; + inline float z() const; + inline void set_z(float value); + + // required float intensity = 4; + inline bool has_intensity() const; + inline void clear_intensity(); + static const int kIntensityFieldNumber = 4; + inline float intensity() const; + inline void set_intensity(float value); + + // @@protoc_insertion_point(class_scope:px.PointCloudXYZI.PointXYZI) + private: + inline void set_has_x(); + inline void clear_has_x(); + inline void set_has_y(); + inline void clear_has_y(); + inline void set_has_z(); + inline void clear_has_z(); + inline void set_has_intensity(); + inline void clear_has_intensity(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + float x_; + float y_; + float z_; + float intensity_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static PointCloudXYZI_PointXYZI* default_instance_; +}; +// ------------------------------------------------------------------- + +class PointCloudXYZI : public ::google::protobuf::Message { + public: + PointCloudXYZI(); + virtual ~PointCloudXYZI(); + + PointCloudXYZI(const PointCloudXYZI& from); + + inline PointCloudXYZI& operator=(const PointCloudXYZI& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const PointCloudXYZI& default_instance(); + + void Swap(PointCloudXYZI* other); + + // implements Message ---------------------------------------------- + + PointCloudXYZI* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const PointCloudXYZI& from); + void MergeFrom(const PointCloudXYZI& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef PointCloudXYZI_PointXYZI PointXYZI; + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // repeated .px.PointCloudXYZI.PointXYZI points = 2; + inline int points_size() const; + inline void clear_points(); + static const int kPointsFieldNumber = 2; + inline const ::px::PointCloudXYZI_PointXYZI& points(int index) const; + inline ::px::PointCloudXYZI_PointXYZI* mutable_points(int index); + inline ::px::PointCloudXYZI_PointXYZI* add_points(); + inline const ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZI_PointXYZI >& + points() const; + inline ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZI_PointXYZI >* + mutable_points(); + + // @@protoc_insertion_point(class_scope:px.PointCloudXYZI) + private: + inline void set_has_header(); + inline void clear_has_header(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZI_PointXYZI > points_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static PointCloudXYZI* default_instance_; +}; +// ------------------------------------------------------------------- + +class PointCloudXYZRGB_PointXYZRGB : public ::google::protobuf::Message { + public: + PointCloudXYZRGB_PointXYZRGB(); + virtual ~PointCloudXYZRGB_PointXYZRGB(); + + PointCloudXYZRGB_PointXYZRGB(const PointCloudXYZRGB_PointXYZRGB& from); + + inline PointCloudXYZRGB_PointXYZRGB& operator=(const PointCloudXYZRGB_PointXYZRGB& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const PointCloudXYZRGB_PointXYZRGB& default_instance(); + + void Swap(PointCloudXYZRGB_PointXYZRGB* other); + + // implements Message ---------------------------------------------- + + PointCloudXYZRGB_PointXYZRGB* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const PointCloudXYZRGB_PointXYZRGB& from); + void MergeFrom(const PointCloudXYZRGB_PointXYZRGB& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required float x = 1; + inline bool has_x() const; + inline void clear_x(); + static const int kXFieldNumber = 1; + inline float x() const; + inline void set_x(float value); + + // required float y = 2; + inline bool has_y() const; + inline void clear_y(); + static const int kYFieldNumber = 2; + inline float y() const; + inline void set_y(float value); + + // required float z = 3; + inline bool has_z() const; + inline void clear_z(); + static const int kZFieldNumber = 3; + inline float z() const; + inline void set_z(float value); + + // required float rgb = 4; + inline bool has_rgb() const; + inline void clear_rgb(); + static const int kRgbFieldNumber = 4; + inline float rgb() const; + inline void set_rgb(float value); + + // @@protoc_insertion_point(class_scope:px.PointCloudXYZRGB.PointXYZRGB) + private: + inline void set_has_x(); + inline void clear_has_x(); + inline void set_has_y(); + inline void clear_has_y(); + inline void set_has_z(); + inline void clear_has_z(); + inline void set_has_rgb(); + inline void clear_has_rgb(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + float x_; + float y_; + float z_; + float rgb_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static PointCloudXYZRGB_PointXYZRGB* default_instance_; +}; +// ------------------------------------------------------------------- + +class PointCloudXYZRGB : public ::google::protobuf::Message { + public: + PointCloudXYZRGB(); + virtual ~PointCloudXYZRGB(); + + PointCloudXYZRGB(const PointCloudXYZRGB& from); + + inline PointCloudXYZRGB& operator=(const PointCloudXYZRGB& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const PointCloudXYZRGB& default_instance(); + + void Swap(PointCloudXYZRGB* other); + + // implements Message ---------------------------------------------- + + PointCloudXYZRGB* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const PointCloudXYZRGB& from); + void MergeFrom(const PointCloudXYZRGB& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef PointCloudXYZRGB_PointXYZRGB PointXYZRGB; + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // repeated .px.PointCloudXYZRGB.PointXYZRGB points = 2; + inline int points_size() const; + inline void clear_points(); + static const int kPointsFieldNumber = 2; + inline const ::px::PointCloudXYZRGB_PointXYZRGB& points(int index) const; + inline ::px::PointCloudXYZRGB_PointXYZRGB* mutable_points(int index); + inline ::px::PointCloudXYZRGB_PointXYZRGB* add_points(); + inline const ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZRGB_PointXYZRGB >& + points() const; + inline ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZRGB_PointXYZRGB >* + mutable_points(); + + // @@protoc_insertion_point(class_scope:px.PointCloudXYZRGB) + private: + inline void set_has_header(); + inline void clear_has_header(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZRGB_PointXYZRGB > points_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static PointCloudXYZRGB* default_instance_; +}; +// ------------------------------------------------------------------- + +class RGBDImage : public ::google::protobuf::Message { + public: + RGBDImage(); + virtual ~RGBDImage(); + + RGBDImage(const RGBDImage& from); + + inline RGBDImage& operator=(const RGBDImage& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RGBDImage& default_instance(); + + void Swap(RGBDImage* other); + + // implements Message ---------------------------------------------- + + RGBDImage* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RGBDImage& from); + void MergeFrom(const RGBDImage& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // required uint32 cols = 2; + inline bool has_cols() const; + inline void clear_cols(); + static const int kColsFieldNumber = 2; + inline ::google::protobuf::uint32 cols() const; + inline void set_cols(::google::protobuf::uint32 value); + + // required uint32 rows = 3; + inline bool has_rows() const; + inline void clear_rows(); + static const int kRowsFieldNumber = 3; + inline ::google::protobuf::uint32 rows() const; + inline void set_rows(::google::protobuf::uint32 value); + + // required uint32 step1 = 4; + inline bool has_step1() const; + inline void clear_step1(); + static const int kStep1FieldNumber = 4; + inline ::google::protobuf::uint32 step1() const; + inline void set_step1(::google::protobuf::uint32 value); + + // required uint32 type1 = 5; + inline bool has_type1() const; + inline void clear_type1(); + static const int kType1FieldNumber = 5; + inline ::google::protobuf::uint32 type1() const; + inline void set_type1(::google::protobuf::uint32 value); + + // required bytes imageData1 = 6; + inline bool has_imagedata1() const; + inline void clear_imagedata1(); + static const int kImageData1FieldNumber = 6; + inline const ::std::string& imagedata1() const; + inline void set_imagedata1(const ::std::string& value); + inline void set_imagedata1(const char* value); + inline void set_imagedata1(const void* value, size_t size); + inline ::std::string* mutable_imagedata1(); + inline ::std::string* release_imagedata1(); + + // required uint32 step2 = 7; + inline bool has_step2() const; + inline void clear_step2(); + static const int kStep2FieldNumber = 7; + inline ::google::protobuf::uint32 step2() const; + inline void set_step2(::google::protobuf::uint32 value); + + // required uint32 type2 = 8; + inline bool has_type2() const; + inline void clear_type2(); + static const int kType2FieldNumber = 8; + inline ::google::protobuf::uint32 type2() const; + inline void set_type2(::google::protobuf::uint32 value); + + // required bytes imageData2 = 9; + inline bool has_imagedata2() const; + inline void clear_imagedata2(); + static const int kImageData2FieldNumber = 9; + inline const ::std::string& imagedata2() const; + inline void set_imagedata2(const ::std::string& value); + inline void set_imagedata2(const char* value); + inline void set_imagedata2(const void* value, size_t size); + inline ::std::string* mutable_imagedata2(); + inline ::std::string* release_imagedata2(); + + // optional uint32 camera_config = 10; + inline bool has_camera_config() const; + inline void clear_camera_config(); + static const int kCameraConfigFieldNumber = 10; + inline ::google::protobuf::uint32 camera_config() const; + inline void set_camera_config(::google::protobuf::uint32 value); + + // optional uint32 camera_type = 11; + inline bool has_camera_type() const; + inline void clear_camera_type(); + static const int kCameraTypeFieldNumber = 11; + inline ::google::protobuf::uint32 camera_type() const; + inline void set_camera_type(::google::protobuf::uint32 value); + + // optional float roll = 12; + inline bool has_roll() const; + inline void clear_roll(); + static const int kRollFieldNumber = 12; + inline float roll() const; + inline void set_roll(float value); + + // optional float pitch = 13; + inline bool has_pitch() const; + inline void clear_pitch(); + static const int kPitchFieldNumber = 13; + inline float pitch() const; + inline void set_pitch(float value); + + // optional float yaw = 14; + inline bool has_yaw() const; + inline void clear_yaw(); + static const int kYawFieldNumber = 14; + inline float yaw() const; + inline void set_yaw(float value); + + // optional float lon = 15; + inline bool has_lon() const; + inline void clear_lon(); + static const int kLonFieldNumber = 15; + inline float lon() const; + inline void set_lon(float value); + + // optional float lat = 16; + inline bool has_lat() const; + inline void clear_lat(); + static const int kLatFieldNumber = 16; + inline float lat() const; + inline void set_lat(float value); + + // optional float alt = 17; + inline bool has_alt() const; + inline void clear_alt(); + static const int kAltFieldNumber = 17; + inline float alt() const; + inline void set_alt(float value); + + // optional float ground_x = 18; + inline bool has_ground_x() const; + inline void clear_ground_x(); + static const int kGroundXFieldNumber = 18; + inline float ground_x() const; + inline void set_ground_x(float value); + + // optional float ground_y = 19; + inline bool has_ground_y() const; + inline void clear_ground_y(); + static const int kGroundYFieldNumber = 19; + inline float ground_y() const; + inline void set_ground_y(float value); + + // optional float ground_z = 20; + inline bool has_ground_z() const; + inline void clear_ground_z(); + static const int kGroundZFieldNumber = 20; + inline float ground_z() const; + inline void set_ground_z(float value); + + // repeated float camera_matrix = 21; + inline int camera_matrix_size() const; + inline void clear_camera_matrix(); + static const int kCameraMatrixFieldNumber = 21; + inline float camera_matrix(int index) const; + inline void set_camera_matrix(int index, float value); + inline void add_camera_matrix(float value); + inline const ::google::protobuf::RepeatedField< float >& + camera_matrix() const; + inline ::google::protobuf::RepeatedField< float >* + mutable_camera_matrix(); + + // @@protoc_insertion_point(class_scope:px.RGBDImage) + private: + inline void set_has_header(); + inline void clear_has_header(); + inline void set_has_cols(); + inline void clear_has_cols(); + inline void set_has_rows(); + inline void clear_has_rows(); + inline void set_has_step1(); + inline void clear_has_step1(); + inline void set_has_type1(); + inline void clear_has_type1(); + inline void set_has_imagedata1(); + inline void clear_has_imagedata1(); + inline void set_has_step2(); + inline void clear_has_step2(); + inline void set_has_type2(); + inline void clear_has_type2(); + inline void set_has_imagedata2(); + inline void clear_has_imagedata2(); + inline void set_has_camera_config(); + inline void clear_has_camera_config(); + inline void set_has_camera_type(); + inline void clear_has_camera_type(); + inline void set_has_roll(); + inline void clear_has_roll(); + inline void set_has_pitch(); + inline void clear_has_pitch(); + inline void set_has_yaw(); + inline void clear_has_yaw(); + inline void set_has_lon(); + inline void clear_has_lon(); + inline void set_has_lat(); + inline void clear_has_lat(); + inline void set_has_alt(); + inline void clear_has_alt(); + inline void set_has_ground_x(); + inline void clear_has_ground_x(); + inline void set_has_ground_y(); + inline void clear_has_ground_y(); + inline void set_has_ground_z(); + inline void clear_has_ground_z(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::google::protobuf::uint32 cols_; + ::google::protobuf::uint32 rows_; + ::google::protobuf::uint32 step1_; + ::google::protobuf::uint32 type1_; + ::std::string* imagedata1_; + ::google::protobuf::uint32 step2_; + ::google::protobuf::uint32 type2_; + ::std::string* imagedata2_; + ::google::protobuf::uint32 camera_config_; + ::google::protobuf::uint32 camera_type_; + float roll_; + float pitch_; + float yaw_; + float lon_; + float lat_; + float alt_; + float ground_x_; + float ground_y_; + ::google::protobuf::RepeatedField< float > camera_matrix_; + float ground_z_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(21 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static RGBDImage* default_instance_; +}; +// ------------------------------------------------------------------- + +class Waypoint : public ::google::protobuf::Message { + public: + Waypoint(); + virtual ~Waypoint(); + + Waypoint(const Waypoint& from); + + inline Waypoint& operator=(const Waypoint& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const Waypoint& default_instance(); + + void Swap(Waypoint* other); + + // implements Message ---------------------------------------------- + + Waypoint* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const Waypoint& from); + void MergeFrom(const Waypoint& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required double x = 1; + inline bool has_x() const; + inline void clear_x(); + static const int kXFieldNumber = 1; + inline double x() const; + inline void set_x(double value); + + // required double y = 2; + inline bool has_y() const; + inline void clear_y(); + static const int kYFieldNumber = 2; + inline double y() const; + inline void set_y(double value); + + // optional double z = 3; + inline bool has_z() const; + inline void clear_z(); + static const int kZFieldNumber = 3; + inline double z() const; + inline void set_z(double value); + + // optional double roll = 4; + inline bool has_roll() const; + inline void clear_roll(); + static const int kRollFieldNumber = 4; + inline double roll() const; + inline void set_roll(double value); + + // optional double pitch = 5; + inline bool has_pitch() const; + inline void clear_pitch(); + static const int kPitchFieldNumber = 5; + inline double pitch() const; + inline void set_pitch(double value); + + // optional double yaw = 6; + inline bool has_yaw() const; + inline void clear_yaw(); + static const int kYawFieldNumber = 6; + inline double yaw() const; + inline void set_yaw(double value); + + // @@protoc_insertion_point(class_scope:px.Waypoint) + private: + inline void set_has_x(); + inline void clear_has_x(); + inline void set_has_y(); + inline void clear_has_y(); + inline void set_has_z(); + inline void clear_has_z(); + inline void set_has_roll(); + inline void clear_has_roll(); + inline void set_has_pitch(); + inline void clear_has_pitch(); + inline void set_has_yaw(); + inline void clear_has_yaw(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + double x_; + double y_; + double z_; + double roll_; + double pitch_; + double yaw_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static Waypoint* default_instance_; +}; +// =================================================================== + + +// =================================================================== + +// HeaderInfo + +// required int32 source_sysid = 1; +inline bool HeaderInfo::has_source_sysid() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void HeaderInfo::set_has_source_sysid() { + _has_bits_[0] |= 0x00000001u; +} +inline void HeaderInfo::clear_has_source_sysid() { + _has_bits_[0] &= ~0x00000001u; +} +inline void HeaderInfo::clear_source_sysid() { + source_sysid_ = 0; + clear_has_source_sysid(); +} +inline ::google::protobuf::int32 HeaderInfo::source_sysid() const { + return source_sysid_; +} +inline void HeaderInfo::set_source_sysid(::google::protobuf::int32 value) { + set_has_source_sysid(); + source_sysid_ = value; +} + +// required int32 source_compid = 2; +inline bool HeaderInfo::has_source_compid() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void HeaderInfo::set_has_source_compid() { + _has_bits_[0] |= 0x00000002u; +} +inline void HeaderInfo::clear_has_source_compid() { + _has_bits_[0] &= ~0x00000002u; +} +inline void HeaderInfo::clear_source_compid() { + source_compid_ = 0; + clear_has_source_compid(); +} +inline ::google::protobuf::int32 HeaderInfo::source_compid() const { + return source_compid_; +} +inline void HeaderInfo::set_source_compid(::google::protobuf::int32 value) { + set_has_source_compid(); + source_compid_ = value; +} + +// required double timestamp = 3; +inline bool HeaderInfo::has_timestamp() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void HeaderInfo::set_has_timestamp() { + _has_bits_[0] |= 0x00000004u; +} +inline void HeaderInfo::clear_has_timestamp() { + _has_bits_[0] &= ~0x00000004u; +} +inline void HeaderInfo::clear_timestamp() { + timestamp_ = 0; + clear_has_timestamp(); +} +inline double HeaderInfo::timestamp() const { + return timestamp_; +} +inline void HeaderInfo::set_timestamp(double value) { + set_has_timestamp(); + timestamp_ = value; +} + +// ------------------------------------------------------------------- + +// GLOverlay + +// required .px.HeaderInfo header = 1; +inline bool GLOverlay::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void GLOverlay::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void GLOverlay::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void GLOverlay::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& GLOverlay::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* GLOverlay::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* GLOverlay::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// optional string name = 2; +inline bool GLOverlay::has_name() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void GLOverlay::set_has_name() { + _has_bits_[0] |= 0x00000002u; +} +inline void GLOverlay::clear_has_name() { + _has_bits_[0] &= ~0x00000002u; +} +inline void GLOverlay::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& GLOverlay::name() const { + return *name_; +} +inline void GLOverlay::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void GLOverlay::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void GLOverlay::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* GLOverlay::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* GLOverlay::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// optional .px.GLOverlay.CoordinateFrameType coordinateFrameType = 3; +inline bool GLOverlay::has_coordinateframetype() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void GLOverlay::set_has_coordinateframetype() { + _has_bits_[0] |= 0x00000004u; +} +inline void GLOverlay::clear_has_coordinateframetype() { + _has_bits_[0] &= ~0x00000004u; +} +inline void GLOverlay::clear_coordinateframetype() { + coordinateframetype_ = 0; + clear_has_coordinateframetype(); +} +inline ::px::GLOverlay_CoordinateFrameType GLOverlay::coordinateframetype() const { + return static_cast< ::px::GLOverlay_CoordinateFrameType >(coordinateframetype_); +} +inline void GLOverlay::set_coordinateframetype(::px::GLOverlay_CoordinateFrameType value) { + GOOGLE_DCHECK(::px::GLOverlay_CoordinateFrameType_IsValid(value)); + set_has_coordinateframetype(); + coordinateframetype_ = value; +} + +// optional double origin_x = 4; +inline bool GLOverlay::has_origin_x() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void GLOverlay::set_has_origin_x() { + _has_bits_[0] |= 0x00000008u; +} +inline void GLOverlay::clear_has_origin_x() { + _has_bits_[0] &= ~0x00000008u; +} +inline void GLOverlay::clear_origin_x() { + origin_x_ = 0; + clear_has_origin_x(); +} +inline double GLOverlay::origin_x() const { + return origin_x_; +} +inline void GLOverlay::set_origin_x(double value) { + set_has_origin_x(); + origin_x_ = value; +} + +// optional double origin_y = 5; +inline bool GLOverlay::has_origin_y() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void GLOverlay::set_has_origin_y() { + _has_bits_[0] |= 0x00000010u; +} +inline void GLOverlay::clear_has_origin_y() { + _has_bits_[0] &= ~0x00000010u; +} +inline void GLOverlay::clear_origin_y() { + origin_y_ = 0; + clear_has_origin_y(); +} +inline double GLOverlay::origin_y() const { + return origin_y_; +} +inline void GLOverlay::set_origin_y(double value) { + set_has_origin_y(); + origin_y_ = value; +} + +// optional double origin_z = 6; +inline bool GLOverlay::has_origin_z() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void GLOverlay::set_has_origin_z() { + _has_bits_[0] |= 0x00000020u; +} +inline void GLOverlay::clear_has_origin_z() { + _has_bits_[0] &= ~0x00000020u; +} +inline void GLOverlay::clear_origin_z() { + origin_z_ = 0; + clear_has_origin_z(); +} +inline double GLOverlay::origin_z() const { + return origin_z_; +} +inline void GLOverlay::set_origin_z(double value) { + set_has_origin_z(); + origin_z_ = value; +} + +// optional bytes data = 7; +inline bool GLOverlay::has_data() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void GLOverlay::set_has_data() { + _has_bits_[0] |= 0x00000040u; +} +inline void GLOverlay::clear_has_data() { + _has_bits_[0] &= ~0x00000040u; +} +inline void GLOverlay::clear_data() { + if (data_ != &::google::protobuf::internal::kEmptyString) { + data_->clear(); + } + clear_has_data(); +} +inline const ::std::string& GLOverlay::data() const { + return *data_; +} +inline void GLOverlay::set_data(const ::std::string& value) { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + data_->assign(value); +} +inline void GLOverlay::set_data(const char* value) { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + data_->assign(value); +} +inline void GLOverlay::set_data(const void* value, size_t size) { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + data_->assign(reinterpret_cast(value), size); +} +inline ::std::string* GLOverlay::mutable_data() { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + return data_; +} +inline ::std::string* GLOverlay::release_data() { + clear_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = data_; + data_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// ------------------------------------------------------------------- + +// Obstacle + +// optional float x = 1; +inline bool Obstacle::has_x() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void Obstacle::set_has_x() { + _has_bits_[0] |= 0x00000001u; +} +inline void Obstacle::clear_has_x() { + _has_bits_[0] &= ~0x00000001u; +} +inline void Obstacle::clear_x() { + x_ = 0; + clear_has_x(); +} +inline float Obstacle::x() const { + return x_; +} +inline void Obstacle::set_x(float value) { + set_has_x(); + x_ = value; +} + +// optional float y = 2; +inline bool Obstacle::has_y() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void Obstacle::set_has_y() { + _has_bits_[0] |= 0x00000002u; +} +inline void Obstacle::clear_has_y() { + _has_bits_[0] &= ~0x00000002u; +} +inline void Obstacle::clear_y() { + y_ = 0; + clear_has_y(); +} +inline float Obstacle::y() const { + return y_; +} +inline void Obstacle::set_y(float value) { + set_has_y(); + y_ = value; +} + +// optional float z = 3; +inline bool Obstacle::has_z() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void Obstacle::set_has_z() { + _has_bits_[0] |= 0x00000004u; +} +inline void Obstacle::clear_has_z() { + _has_bits_[0] &= ~0x00000004u; +} +inline void Obstacle::clear_z() { + z_ = 0; + clear_has_z(); +} +inline float Obstacle::z() const { + return z_; +} +inline void Obstacle::set_z(float value) { + set_has_z(); + z_ = value; +} + +// optional float length = 4; +inline bool Obstacle::has_length() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void Obstacle::set_has_length() { + _has_bits_[0] |= 0x00000008u; +} +inline void Obstacle::clear_has_length() { + _has_bits_[0] &= ~0x00000008u; +} +inline void Obstacle::clear_length() { + length_ = 0; + clear_has_length(); +} +inline float Obstacle::length() const { + return length_; +} +inline void Obstacle::set_length(float value) { + set_has_length(); + length_ = value; +} + +// optional float width = 5; +inline bool Obstacle::has_width() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void Obstacle::set_has_width() { + _has_bits_[0] |= 0x00000010u; +} +inline void Obstacle::clear_has_width() { + _has_bits_[0] &= ~0x00000010u; +} +inline void Obstacle::clear_width() { + width_ = 0; + clear_has_width(); +} +inline float Obstacle::width() const { + return width_; +} +inline void Obstacle::set_width(float value) { + set_has_width(); + width_ = value; +} + +// optional float height = 6; +inline bool Obstacle::has_height() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void Obstacle::set_has_height() { + _has_bits_[0] |= 0x00000020u; +} +inline void Obstacle::clear_has_height() { + _has_bits_[0] &= ~0x00000020u; +} +inline void Obstacle::clear_height() { + height_ = 0; + clear_has_height(); +} +inline float Obstacle::height() const { + return height_; +} +inline void Obstacle::set_height(float value) { + set_has_height(); + height_ = value; +} + +// ------------------------------------------------------------------- + +// ObstacleList + +// required .px.HeaderInfo header = 1; +inline bool ObstacleList::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ObstacleList::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void ObstacleList::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ObstacleList::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& ObstacleList::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* ObstacleList::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* ObstacleList::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// repeated .px.Obstacle obstacles = 2; +inline int ObstacleList::obstacles_size() const { + return obstacles_.size(); +} +inline void ObstacleList::clear_obstacles() { + obstacles_.Clear(); +} +inline const ::px::Obstacle& ObstacleList::obstacles(int index) const { + return obstacles_.Get(index); +} +inline ::px::Obstacle* ObstacleList::mutable_obstacles(int index) { + return obstacles_.Mutable(index); +} +inline ::px::Obstacle* ObstacleList::add_obstacles() { + return obstacles_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::px::Obstacle >& +ObstacleList::obstacles() const { + return obstacles_; +} +inline ::google::protobuf::RepeatedPtrField< ::px::Obstacle >* +ObstacleList::mutable_obstacles() { + return &obstacles_; +} + +// ------------------------------------------------------------------- + +// ObstacleMap + +// required .px.HeaderInfo header = 1; +inline bool ObstacleMap::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ObstacleMap::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void ObstacleMap::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ObstacleMap::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& ObstacleMap::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* ObstacleMap::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* ObstacleMap::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// required int32 type = 2; +inline bool ObstacleMap::has_type() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void ObstacleMap::set_has_type() { + _has_bits_[0] |= 0x00000002u; +} +inline void ObstacleMap::clear_has_type() { + _has_bits_[0] &= ~0x00000002u; +} +inline void ObstacleMap::clear_type() { + type_ = 0; + clear_has_type(); +} +inline ::google::protobuf::int32 ObstacleMap::type() const { + return type_; +} +inline void ObstacleMap::set_type(::google::protobuf::int32 value) { + set_has_type(); + type_ = value; +} + +// optional float resolution = 3; +inline bool ObstacleMap::has_resolution() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void ObstacleMap::set_has_resolution() { + _has_bits_[0] |= 0x00000004u; +} +inline void ObstacleMap::clear_has_resolution() { + _has_bits_[0] &= ~0x00000004u; +} +inline void ObstacleMap::clear_resolution() { + resolution_ = 0; + clear_has_resolution(); +} +inline float ObstacleMap::resolution() const { + return resolution_; +} +inline void ObstacleMap::set_resolution(float value) { + set_has_resolution(); + resolution_ = value; +} + +// optional int32 rows = 4; +inline bool ObstacleMap::has_rows() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void ObstacleMap::set_has_rows() { + _has_bits_[0] |= 0x00000008u; +} +inline void ObstacleMap::clear_has_rows() { + _has_bits_[0] &= ~0x00000008u; +} +inline void ObstacleMap::clear_rows() { + rows_ = 0; + clear_has_rows(); +} +inline ::google::protobuf::int32 ObstacleMap::rows() const { + return rows_; +} +inline void ObstacleMap::set_rows(::google::protobuf::int32 value) { + set_has_rows(); + rows_ = value; +} + +// optional int32 cols = 5; +inline bool ObstacleMap::has_cols() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void ObstacleMap::set_has_cols() { + _has_bits_[0] |= 0x00000010u; +} +inline void ObstacleMap::clear_has_cols() { + _has_bits_[0] &= ~0x00000010u; +} +inline void ObstacleMap::clear_cols() { + cols_ = 0; + clear_has_cols(); +} +inline ::google::protobuf::int32 ObstacleMap::cols() const { + return cols_; +} +inline void ObstacleMap::set_cols(::google::protobuf::int32 value) { + set_has_cols(); + cols_ = value; +} + +// optional int32 mapR0 = 6; +inline bool ObstacleMap::has_mapr0() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void ObstacleMap::set_has_mapr0() { + _has_bits_[0] |= 0x00000020u; +} +inline void ObstacleMap::clear_has_mapr0() { + _has_bits_[0] &= ~0x00000020u; +} +inline void ObstacleMap::clear_mapr0() { + mapr0_ = 0; + clear_has_mapr0(); +} +inline ::google::protobuf::int32 ObstacleMap::mapr0() const { + return mapr0_; +} +inline void ObstacleMap::set_mapr0(::google::protobuf::int32 value) { + set_has_mapr0(); + mapr0_ = value; +} + +// optional int32 mapC0 = 7; +inline bool ObstacleMap::has_mapc0() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void ObstacleMap::set_has_mapc0() { + _has_bits_[0] |= 0x00000040u; +} +inline void ObstacleMap::clear_has_mapc0() { + _has_bits_[0] &= ~0x00000040u; +} +inline void ObstacleMap::clear_mapc0() { + mapc0_ = 0; + clear_has_mapc0(); +} +inline ::google::protobuf::int32 ObstacleMap::mapc0() const { + return mapc0_; +} +inline void ObstacleMap::set_mapc0(::google::protobuf::int32 value) { + set_has_mapc0(); + mapc0_ = value; +} + +// optional int32 arrayR0 = 8; +inline bool ObstacleMap::has_arrayr0() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void ObstacleMap::set_has_arrayr0() { + _has_bits_[0] |= 0x00000080u; +} +inline void ObstacleMap::clear_has_arrayr0() { + _has_bits_[0] &= ~0x00000080u; +} +inline void ObstacleMap::clear_arrayr0() { + arrayr0_ = 0; + clear_has_arrayr0(); +} +inline ::google::protobuf::int32 ObstacleMap::arrayr0() const { + return arrayr0_; +} +inline void ObstacleMap::set_arrayr0(::google::protobuf::int32 value) { + set_has_arrayr0(); + arrayr0_ = value; +} + +// optional int32 arrayC0 = 9; +inline bool ObstacleMap::has_arrayc0() const { + return (_has_bits_[0] & 0x00000100u) != 0; +} +inline void ObstacleMap::set_has_arrayc0() { + _has_bits_[0] |= 0x00000100u; +} +inline void ObstacleMap::clear_has_arrayc0() { + _has_bits_[0] &= ~0x00000100u; +} +inline void ObstacleMap::clear_arrayc0() { + arrayc0_ = 0; + clear_has_arrayc0(); +} +inline ::google::protobuf::int32 ObstacleMap::arrayc0() const { + return arrayc0_; +} +inline void ObstacleMap::set_arrayc0(::google::protobuf::int32 value) { + set_has_arrayc0(); + arrayc0_ = value; +} + +// optional bytes data = 10; +inline bool ObstacleMap::has_data() const { + return (_has_bits_[0] & 0x00000200u) != 0; +} +inline void ObstacleMap::set_has_data() { + _has_bits_[0] |= 0x00000200u; +} +inline void ObstacleMap::clear_has_data() { + _has_bits_[0] &= ~0x00000200u; +} +inline void ObstacleMap::clear_data() { + if (data_ != &::google::protobuf::internal::kEmptyString) { + data_->clear(); + } + clear_has_data(); +} +inline const ::std::string& ObstacleMap::data() const { + return *data_; +} +inline void ObstacleMap::set_data(const ::std::string& value) { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + data_->assign(value); +} +inline void ObstacleMap::set_data(const char* value) { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + data_->assign(value); +} +inline void ObstacleMap::set_data(const void* value, size_t size) { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + data_->assign(reinterpret_cast(value), size); +} +inline ::std::string* ObstacleMap::mutable_data() { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + return data_; +} +inline ::std::string* ObstacleMap::release_data() { + clear_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = data_; + data_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// ------------------------------------------------------------------- + +// Path + +// required .px.HeaderInfo header = 1; +inline bool Path::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void Path::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void Path::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void Path::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& Path::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* Path::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* Path::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// repeated .px.Waypoint waypoints = 2; +inline int Path::waypoints_size() const { + return waypoints_.size(); +} +inline void Path::clear_waypoints() { + waypoints_.Clear(); +} +inline const ::px::Waypoint& Path::waypoints(int index) const { + return waypoints_.Get(index); +} +inline ::px::Waypoint* Path::mutable_waypoints(int index) { + return waypoints_.Mutable(index); +} +inline ::px::Waypoint* Path::add_waypoints() { + return waypoints_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::px::Waypoint >& +Path::waypoints() const { + return waypoints_; +} +inline ::google::protobuf::RepeatedPtrField< ::px::Waypoint >* +Path::mutable_waypoints() { + return &waypoints_; +} + +// ------------------------------------------------------------------- + +// PointCloudXYZI_PointXYZI + +// required float x = 1; +inline bool PointCloudXYZI_PointXYZI::has_x() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void PointCloudXYZI_PointXYZI::set_has_x() { + _has_bits_[0] |= 0x00000001u; +} +inline void PointCloudXYZI_PointXYZI::clear_has_x() { + _has_bits_[0] &= ~0x00000001u; +} +inline void PointCloudXYZI_PointXYZI::clear_x() { + x_ = 0; + clear_has_x(); +} +inline float PointCloudXYZI_PointXYZI::x() const { + return x_; +} +inline void PointCloudXYZI_PointXYZI::set_x(float value) { + set_has_x(); + x_ = value; +} + +// required float y = 2; +inline bool PointCloudXYZI_PointXYZI::has_y() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void PointCloudXYZI_PointXYZI::set_has_y() { + _has_bits_[0] |= 0x00000002u; +} +inline void PointCloudXYZI_PointXYZI::clear_has_y() { + _has_bits_[0] &= ~0x00000002u; +} +inline void PointCloudXYZI_PointXYZI::clear_y() { + y_ = 0; + clear_has_y(); +} +inline float PointCloudXYZI_PointXYZI::y() const { + return y_; +} +inline void PointCloudXYZI_PointXYZI::set_y(float value) { + set_has_y(); + y_ = value; +} + +// required float z = 3; +inline bool PointCloudXYZI_PointXYZI::has_z() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void PointCloudXYZI_PointXYZI::set_has_z() { + _has_bits_[0] |= 0x00000004u; +} +inline void PointCloudXYZI_PointXYZI::clear_has_z() { + _has_bits_[0] &= ~0x00000004u; +} +inline void PointCloudXYZI_PointXYZI::clear_z() { + z_ = 0; + clear_has_z(); +} +inline float PointCloudXYZI_PointXYZI::z() const { + return z_; +} +inline void PointCloudXYZI_PointXYZI::set_z(float value) { + set_has_z(); + z_ = value; +} + +// required float intensity = 4; +inline bool PointCloudXYZI_PointXYZI::has_intensity() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void PointCloudXYZI_PointXYZI::set_has_intensity() { + _has_bits_[0] |= 0x00000008u; +} +inline void PointCloudXYZI_PointXYZI::clear_has_intensity() { + _has_bits_[0] &= ~0x00000008u; +} +inline void PointCloudXYZI_PointXYZI::clear_intensity() { + intensity_ = 0; + clear_has_intensity(); +} +inline float PointCloudXYZI_PointXYZI::intensity() const { + return intensity_; +} +inline void PointCloudXYZI_PointXYZI::set_intensity(float value) { + set_has_intensity(); + intensity_ = value; +} + +// ------------------------------------------------------------------- + +// PointCloudXYZI + +// required .px.HeaderInfo header = 1; +inline bool PointCloudXYZI::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void PointCloudXYZI::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void PointCloudXYZI::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void PointCloudXYZI::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& PointCloudXYZI::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* PointCloudXYZI::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* PointCloudXYZI::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// repeated .px.PointCloudXYZI.PointXYZI points = 2; +inline int PointCloudXYZI::points_size() const { + return points_.size(); +} +inline void PointCloudXYZI::clear_points() { + points_.Clear(); +} +inline const ::px::PointCloudXYZI_PointXYZI& PointCloudXYZI::points(int index) const { + return points_.Get(index); +} +inline ::px::PointCloudXYZI_PointXYZI* PointCloudXYZI::mutable_points(int index) { + return points_.Mutable(index); +} +inline ::px::PointCloudXYZI_PointXYZI* PointCloudXYZI::add_points() { + return points_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZI_PointXYZI >& +PointCloudXYZI::points() const { + return points_; +} +inline ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZI_PointXYZI >* +PointCloudXYZI::mutable_points() { + return &points_; +} + +// ------------------------------------------------------------------- + +// PointCloudXYZRGB_PointXYZRGB + +// required float x = 1; +inline bool PointCloudXYZRGB_PointXYZRGB::has_x() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_has_x() { + _has_bits_[0] |= 0x00000001u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_has_x() { + _has_bits_[0] &= ~0x00000001u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_x() { + x_ = 0; + clear_has_x(); +} +inline float PointCloudXYZRGB_PointXYZRGB::x() const { + return x_; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_x(float value) { + set_has_x(); + x_ = value; +} + +// required float y = 2; +inline bool PointCloudXYZRGB_PointXYZRGB::has_y() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_has_y() { + _has_bits_[0] |= 0x00000002u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_has_y() { + _has_bits_[0] &= ~0x00000002u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_y() { + y_ = 0; + clear_has_y(); +} +inline float PointCloudXYZRGB_PointXYZRGB::y() const { + return y_; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_y(float value) { + set_has_y(); + y_ = value; +} + +// required float z = 3; +inline bool PointCloudXYZRGB_PointXYZRGB::has_z() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_has_z() { + _has_bits_[0] |= 0x00000004u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_has_z() { + _has_bits_[0] &= ~0x00000004u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_z() { + z_ = 0; + clear_has_z(); +} +inline float PointCloudXYZRGB_PointXYZRGB::z() const { + return z_; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_z(float value) { + set_has_z(); + z_ = value; +} + +// required float rgb = 4; +inline bool PointCloudXYZRGB_PointXYZRGB::has_rgb() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_has_rgb() { + _has_bits_[0] |= 0x00000008u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_has_rgb() { + _has_bits_[0] &= ~0x00000008u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_rgb() { + rgb_ = 0; + clear_has_rgb(); +} +inline float PointCloudXYZRGB_PointXYZRGB::rgb() const { + return rgb_; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_rgb(float value) { + set_has_rgb(); + rgb_ = value; +} + +// ------------------------------------------------------------------- + +// PointCloudXYZRGB + +// required .px.HeaderInfo header = 1; +inline bool PointCloudXYZRGB::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void PointCloudXYZRGB::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void PointCloudXYZRGB::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void PointCloudXYZRGB::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& PointCloudXYZRGB::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* PointCloudXYZRGB::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* PointCloudXYZRGB::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// repeated .px.PointCloudXYZRGB.PointXYZRGB points = 2; +inline int PointCloudXYZRGB::points_size() const { + return points_.size(); +} +inline void PointCloudXYZRGB::clear_points() { + points_.Clear(); +} +inline const ::px::PointCloudXYZRGB_PointXYZRGB& PointCloudXYZRGB::points(int index) const { + return points_.Get(index); +} +inline ::px::PointCloudXYZRGB_PointXYZRGB* PointCloudXYZRGB::mutable_points(int index) { + return points_.Mutable(index); +} +inline ::px::PointCloudXYZRGB_PointXYZRGB* PointCloudXYZRGB::add_points() { + return points_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZRGB_PointXYZRGB >& +PointCloudXYZRGB::points() const { + return points_; +} +inline ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZRGB_PointXYZRGB >* +PointCloudXYZRGB::mutable_points() { + return &points_; +} + +// ------------------------------------------------------------------- + +// RGBDImage + +// required .px.HeaderInfo header = 1; +inline bool RGBDImage::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RGBDImage::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void RGBDImage::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RGBDImage::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& RGBDImage::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* RGBDImage::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* RGBDImage::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// required uint32 cols = 2; +inline bool RGBDImage::has_cols() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void RGBDImage::set_has_cols() { + _has_bits_[0] |= 0x00000002u; +} +inline void RGBDImage::clear_has_cols() { + _has_bits_[0] &= ~0x00000002u; +} +inline void RGBDImage::clear_cols() { + cols_ = 0u; + clear_has_cols(); +} +inline ::google::protobuf::uint32 RGBDImage::cols() const { + return cols_; +} +inline void RGBDImage::set_cols(::google::protobuf::uint32 value) { + set_has_cols(); + cols_ = value; +} + +// required uint32 rows = 3; +inline bool RGBDImage::has_rows() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void RGBDImage::set_has_rows() { + _has_bits_[0] |= 0x00000004u; +} +inline void RGBDImage::clear_has_rows() { + _has_bits_[0] &= ~0x00000004u; +} +inline void RGBDImage::clear_rows() { + rows_ = 0u; + clear_has_rows(); +} +inline ::google::protobuf::uint32 RGBDImage::rows() const { + return rows_; +} +inline void RGBDImage::set_rows(::google::protobuf::uint32 value) { + set_has_rows(); + rows_ = value; +} + +// required uint32 step1 = 4; +inline bool RGBDImage::has_step1() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void RGBDImage::set_has_step1() { + _has_bits_[0] |= 0x00000008u; +} +inline void RGBDImage::clear_has_step1() { + _has_bits_[0] &= ~0x00000008u; +} +inline void RGBDImage::clear_step1() { + step1_ = 0u; + clear_has_step1(); +} +inline ::google::protobuf::uint32 RGBDImage::step1() const { + return step1_; +} +inline void RGBDImage::set_step1(::google::protobuf::uint32 value) { + set_has_step1(); + step1_ = value; +} + +// required uint32 type1 = 5; +inline bool RGBDImage::has_type1() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void RGBDImage::set_has_type1() { + _has_bits_[0] |= 0x00000010u; +} +inline void RGBDImage::clear_has_type1() { + _has_bits_[0] &= ~0x00000010u; +} +inline void RGBDImage::clear_type1() { + type1_ = 0u; + clear_has_type1(); +} +inline ::google::protobuf::uint32 RGBDImage::type1() const { + return type1_; +} +inline void RGBDImage::set_type1(::google::protobuf::uint32 value) { + set_has_type1(); + type1_ = value; +} + +// required bytes imageData1 = 6; +inline bool RGBDImage::has_imagedata1() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void RGBDImage::set_has_imagedata1() { + _has_bits_[0] |= 0x00000020u; +} +inline void RGBDImage::clear_has_imagedata1() { + _has_bits_[0] &= ~0x00000020u; +} +inline void RGBDImage::clear_imagedata1() { + if (imagedata1_ != &::google::protobuf::internal::kEmptyString) { + imagedata1_->clear(); + } + clear_has_imagedata1(); +} +inline const ::std::string& RGBDImage::imagedata1() const { + return *imagedata1_; +} +inline void RGBDImage::set_imagedata1(const ::std::string& value) { + set_has_imagedata1(); + if (imagedata1_ == &::google::protobuf::internal::kEmptyString) { + imagedata1_ = new ::std::string; + } + imagedata1_->assign(value); +} +inline void RGBDImage::set_imagedata1(const char* value) { + set_has_imagedata1(); + if (imagedata1_ == &::google::protobuf::internal::kEmptyString) { + imagedata1_ = new ::std::string; + } + imagedata1_->assign(value); +} +inline void RGBDImage::set_imagedata1(const void* value, size_t size) { + set_has_imagedata1(); + if (imagedata1_ == &::google::protobuf::internal::kEmptyString) { + imagedata1_ = new ::std::string; + } + imagedata1_->assign(reinterpret_cast(value), size); +} +inline ::std::string* RGBDImage::mutable_imagedata1() { + set_has_imagedata1(); + if (imagedata1_ == &::google::protobuf::internal::kEmptyString) { + imagedata1_ = new ::std::string; + } + return imagedata1_; +} +inline ::std::string* RGBDImage::release_imagedata1() { + clear_has_imagedata1(); + if (imagedata1_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = imagedata1_; + imagedata1_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required uint32 step2 = 7; +inline bool RGBDImage::has_step2() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void RGBDImage::set_has_step2() { + _has_bits_[0] |= 0x00000040u; +} +inline void RGBDImage::clear_has_step2() { + _has_bits_[0] &= ~0x00000040u; +} +inline void RGBDImage::clear_step2() { + step2_ = 0u; + clear_has_step2(); +} +inline ::google::protobuf::uint32 RGBDImage::step2() const { + return step2_; +} +inline void RGBDImage::set_step2(::google::protobuf::uint32 value) { + set_has_step2(); + step2_ = value; +} + +// required uint32 type2 = 8; +inline bool RGBDImage::has_type2() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void RGBDImage::set_has_type2() { + _has_bits_[0] |= 0x00000080u; +} +inline void RGBDImage::clear_has_type2() { + _has_bits_[0] &= ~0x00000080u; +} +inline void RGBDImage::clear_type2() { + type2_ = 0u; + clear_has_type2(); +} +inline ::google::protobuf::uint32 RGBDImage::type2() const { + return type2_; +} +inline void RGBDImage::set_type2(::google::protobuf::uint32 value) { + set_has_type2(); + type2_ = value; +} + +// required bytes imageData2 = 9; +inline bool RGBDImage::has_imagedata2() const { + return (_has_bits_[0] & 0x00000100u) != 0; +} +inline void RGBDImage::set_has_imagedata2() { + _has_bits_[0] |= 0x00000100u; +} +inline void RGBDImage::clear_has_imagedata2() { + _has_bits_[0] &= ~0x00000100u; +} +inline void RGBDImage::clear_imagedata2() { + if (imagedata2_ != &::google::protobuf::internal::kEmptyString) { + imagedata2_->clear(); + } + clear_has_imagedata2(); +} +inline const ::std::string& RGBDImage::imagedata2() const { + return *imagedata2_; +} +inline void RGBDImage::set_imagedata2(const ::std::string& value) { + set_has_imagedata2(); + if (imagedata2_ == &::google::protobuf::internal::kEmptyString) { + imagedata2_ = new ::std::string; + } + imagedata2_->assign(value); +} +inline void RGBDImage::set_imagedata2(const char* value) { + set_has_imagedata2(); + if (imagedata2_ == &::google::protobuf::internal::kEmptyString) { + imagedata2_ = new ::std::string; + } + imagedata2_->assign(value); +} +inline void RGBDImage::set_imagedata2(const void* value, size_t size) { + set_has_imagedata2(); + if (imagedata2_ == &::google::protobuf::internal::kEmptyString) { + imagedata2_ = new ::std::string; + } + imagedata2_->assign(reinterpret_cast(value), size); +} +inline ::std::string* RGBDImage::mutable_imagedata2() { + set_has_imagedata2(); + if (imagedata2_ == &::google::protobuf::internal::kEmptyString) { + imagedata2_ = new ::std::string; + } + return imagedata2_; +} +inline ::std::string* RGBDImage::release_imagedata2() { + clear_has_imagedata2(); + if (imagedata2_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = imagedata2_; + imagedata2_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// optional uint32 camera_config = 10; +inline bool RGBDImage::has_camera_config() const { + return (_has_bits_[0] & 0x00000200u) != 0; +} +inline void RGBDImage::set_has_camera_config() { + _has_bits_[0] |= 0x00000200u; +} +inline void RGBDImage::clear_has_camera_config() { + _has_bits_[0] &= ~0x00000200u; +} +inline void RGBDImage::clear_camera_config() { + camera_config_ = 0u; + clear_has_camera_config(); +} +inline ::google::protobuf::uint32 RGBDImage::camera_config() const { + return camera_config_; +} +inline void RGBDImage::set_camera_config(::google::protobuf::uint32 value) { + set_has_camera_config(); + camera_config_ = value; +} + +// optional uint32 camera_type = 11; +inline bool RGBDImage::has_camera_type() const { + return (_has_bits_[0] & 0x00000400u) != 0; +} +inline void RGBDImage::set_has_camera_type() { + _has_bits_[0] |= 0x00000400u; +} +inline void RGBDImage::clear_has_camera_type() { + _has_bits_[0] &= ~0x00000400u; +} +inline void RGBDImage::clear_camera_type() { + camera_type_ = 0u; + clear_has_camera_type(); +} +inline ::google::protobuf::uint32 RGBDImage::camera_type() const { + return camera_type_; +} +inline void RGBDImage::set_camera_type(::google::protobuf::uint32 value) { + set_has_camera_type(); + camera_type_ = value; +} + +// optional float roll = 12; +inline bool RGBDImage::has_roll() const { + return (_has_bits_[0] & 0x00000800u) != 0; +} +inline void RGBDImage::set_has_roll() { + _has_bits_[0] |= 0x00000800u; +} +inline void RGBDImage::clear_has_roll() { + _has_bits_[0] &= ~0x00000800u; +} +inline void RGBDImage::clear_roll() { + roll_ = 0; + clear_has_roll(); +} +inline float RGBDImage::roll() const { + return roll_; +} +inline void RGBDImage::set_roll(float value) { + set_has_roll(); + roll_ = value; +} + +// optional float pitch = 13; +inline bool RGBDImage::has_pitch() const { + return (_has_bits_[0] & 0x00001000u) != 0; +} +inline void RGBDImage::set_has_pitch() { + _has_bits_[0] |= 0x00001000u; +} +inline void RGBDImage::clear_has_pitch() { + _has_bits_[0] &= ~0x00001000u; +} +inline void RGBDImage::clear_pitch() { + pitch_ = 0; + clear_has_pitch(); +} +inline float RGBDImage::pitch() const { + return pitch_; +} +inline void RGBDImage::set_pitch(float value) { + set_has_pitch(); + pitch_ = value; +} + +// optional float yaw = 14; +inline bool RGBDImage::has_yaw() const { + return (_has_bits_[0] & 0x00002000u) != 0; +} +inline void RGBDImage::set_has_yaw() { + _has_bits_[0] |= 0x00002000u; +} +inline void RGBDImage::clear_has_yaw() { + _has_bits_[0] &= ~0x00002000u; +} +inline void RGBDImage::clear_yaw() { + yaw_ = 0; + clear_has_yaw(); +} +inline float RGBDImage::yaw() const { + return yaw_; +} +inline void RGBDImage::set_yaw(float value) { + set_has_yaw(); + yaw_ = value; +} + +// optional float lon = 15; +inline bool RGBDImage::has_lon() const { + return (_has_bits_[0] & 0x00004000u) != 0; +} +inline void RGBDImage::set_has_lon() { + _has_bits_[0] |= 0x00004000u; +} +inline void RGBDImage::clear_has_lon() { + _has_bits_[0] &= ~0x00004000u; +} +inline void RGBDImage::clear_lon() { + lon_ = 0; + clear_has_lon(); +} +inline float RGBDImage::lon() const { + return lon_; +} +inline void RGBDImage::set_lon(float value) { + set_has_lon(); + lon_ = value; +} + +// optional float lat = 16; +inline bool RGBDImage::has_lat() const { + return (_has_bits_[0] & 0x00008000u) != 0; +} +inline void RGBDImage::set_has_lat() { + _has_bits_[0] |= 0x00008000u; +} +inline void RGBDImage::clear_has_lat() { + _has_bits_[0] &= ~0x00008000u; +} +inline void RGBDImage::clear_lat() { + lat_ = 0; + clear_has_lat(); +} +inline float RGBDImage::lat() const { + return lat_; +} +inline void RGBDImage::set_lat(float value) { + set_has_lat(); + lat_ = value; +} + +// optional float alt = 17; +inline bool RGBDImage::has_alt() const { + return (_has_bits_[0] & 0x00010000u) != 0; +} +inline void RGBDImage::set_has_alt() { + _has_bits_[0] |= 0x00010000u; +} +inline void RGBDImage::clear_has_alt() { + _has_bits_[0] &= ~0x00010000u; +} +inline void RGBDImage::clear_alt() { + alt_ = 0; + clear_has_alt(); +} +inline float RGBDImage::alt() const { + return alt_; +} +inline void RGBDImage::set_alt(float value) { + set_has_alt(); + alt_ = value; +} + +// optional float ground_x = 18; +inline bool RGBDImage::has_ground_x() const { + return (_has_bits_[0] & 0x00020000u) != 0; +} +inline void RGBDImage::set_has_ground_x() { + _has_bits_[0] |= 0x00020000u; +} +inline void RGBDImage::clear_has_ground_x() { + _has_bits_[0] &= ~0x00020000u; +} +inline void RGBDImage::clear_ground_x() { + ground_x_ = 0; + clear_has_ground_x(); +} +inline float RGBDImage::ground_x() const { + return ground_x_; +} +inline void RGBDImage::set_ground_x(float value) { + set_has_ground_x(); + ground_x_ = value; +} + +// optional float ground_y = 19; +inline bool RGBDImage::has_ground_y() const { + return (_has_bits_[0] & 0x00040000u) != 0; +} +inline void RGBDImage::set_has_ground_y() { + _has_bits_[0] |= 0x00040000u; +} +inline void RGBDImage::clear_has_ground_y() { + _has_bits_[0] &= ~0x00040000u; +} +inline void RGBDImage::clear_ground_y() { + ground_y_ = 0; + clear_has_ground_y(); +} +inline float RGBDImage::ground_y() const { + return ground_y_; +} +inline void RGBDImage::set_ground_y(float value) { + set_has_ground_y(); + ground_y_ = value; +} + +// optional float ground_z = 20; +inline bool RGBDImage::has_ground_z() const { + return (_has_bits_[0] & 0x00080000u) != 0; +} +inline void RGBDImage::set_has_ground_z() { + _has_bits_[0] |= 0x00080000u; +} +inline void RGBDImage::clear_has_ground_z() { + _has_bits_[0] &= ~0x00080000u; +} +inline void RGBDImage::clear_ground_z() { + ground_z_ = 0; + clear_has_ground_z(); +} +inline float RGBDImage::ground_z() const { + return ground_z_; +} +inline void RGBDImage::set_ground_z(float value) { + set_has_ground_z(); + ground_z_ = value; +} + +// repeated float camera_matrix = 21; +inline int RGBDImage::camera_matrix_size() const { + return camera_matrix_.size(); +} +inline void RGBDImage::clear_camera_matrix() { + camera_matrix_.Clear(); +} +inline float RGBDImage::camera_matrix(int index) const { + return camera_matrix_.Get(index); +} +inline void RGBDImage::set_camera_matrix(int index, float value) { + camera_matrix_.Set(index, value); +} +inline void RGBDImage::add_camera_matrix(float value) { + camera_matrix_.Add(value); +} +inline const ::google::protobuf::RepeatedField< float >& +RGBDImage::camera_matrix() const { + return camera_matrix_; +} +inline ::google::protobuf::RepeatedField< float >* +RGBDImage::mutable_camera_matrix() { + return &camera_matrix_; +} + +// ------------------------------------------------------------------- + +// Waypoint + +// required double x = 1; +inline bool Waypoint::has_x() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void Waypoint::set_has_x() { + _has_bits_[0] |= 0x00000001u; +} +inline void Waypoint::clear_has_x() { + _has_bits_[0] &= ~0x00000001u; +} +inline void Waypoint::clear_x() { + x_ = 0; + clear_has_x(); +} +inline double Waypoint::x() const { + return x_; +} +inline void Waypoint::set_x(double value) { + set_has_x(); + x_ = value; +} + +// required double y = 2; +inline bool Waypoint::has_y() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void Waypoint::set_has_y() { + _has_bits_[0] |= 0x00000002u; +} +inline void Waypoint::clear_has_y() { + _has_bits_[0] &= ~0x00000002u; +} +inline void Waypoint::clear_y() { + y_ = 0; + clear_has_y(); +} +inline double Waypoint::y() const { + return y_; +} +inline void Waypoint::set_y(double value) { + set_has_y(); + y_ = value; +} + +// optional double z = 3; +inline bool Waypoint::has_z() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void Waypoint::set_has_z() { + _has_bits_[0] |= 0x00000004u; +} +inline void Waypoint::clear_has_z() { + _has_bits_[0] &= ~0x00000004u; +} +inline void Waypoint::clear_z() { + z_ = 0; + clear_has_z(); +} +inline double Waypoint::z() const { + return z_; +} +inline void Waypoint::set_z(double value) { + set_has_z(); + z_ = value; +} + +// optional double roll = 4; +inline bool Waypoint::has_roll() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void Waypoint::set_has_roll() { + _has_bits_[0] |= 0x00000008u; +} +inline void Waypoint::clear_has_roll() { + _has_bits_[0] &= ~0x00000008u; +} +inline void Waypoint::clear_roll() { + roll_ = 0; + clear_has_roll(); +} +inline double Waypoint::roll() const { + return roll_; +} +inline void Waypoint::set_roll(double value) { + set_has_roll(); + roll_ = value; +} + +// optional double pitch = 5; +inline bool Waypoint::has_pitch() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void Waypoint::set_has_pitch() { + _has_bits_[0] |= 0x00000010u; +} +inline void Waypoint::clear_has_pitch() { + _has_bits_[0] &= ~0x00000010u; +} +inline void Waypoint::clear_pitch() { + pitch_ = 0; + clear_has_pitch(); +} +inline double Waypoint::pitch() const { + return pitch_; +} +inline void Waypoint::set_pitch(double value) { + set_has_pitch(); + pitch_ = value; +} + +// optional double yaw = 6; +inline bool Waypoint::has_yaw() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void Waypoint::set_has_yaw() { + _has_bits_[0] |= 0x00000020u; +} +inline void Waypoint::clear_has_yaw() { + _has_bits_[0] &= ~0x00000020u; +} +inline void Waypoint::clear_yaw() { + yaw_ = 0; + clear_has_yaw(); +} +inline double Waypoint::yaw() const { + return yaw_; +} +inline void Waypoint::set_yaw(double value) { + set_has_yaw(); + yaw_ = value; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace px + +#ifndef SWIG +namespace google { +namespace protobuf { + +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::px::GLOverlay_CoordinateFrameType>() { + return ::px::GLOverlay_CoordinateFrameType_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::px::GLOverlay_Mode>() { + return ::px::GLOverlay_Mode_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::px::GLOverlay_Identifier>() { + return ::px::GLOverlay_Identifier_descriptor(); +} + +} // namespace google +} // namespace protobuf +#endif // SWIG + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_pixhawk_2eproto__INCLUDED diff --git a/mavlink/include/mavlink/v1.0/pixhawk/testsuite.h b/mavlink/include/mavlink/v1.0/pixhawk/testsuite.h new file mode 100644 index 0000000000..54a7ae5ba6 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/pixhawk/testsuite.h @@ -0,0 +1,1098 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from pixhawk.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef PIXHAWK_TESTSUITE_H +#define PIXHAWK_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL +static void mavlink_test_common(uint8_t, uint8_t, mavlink_message_t *last_msg); +static void mavlink_test_pixhawk(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_test_common(system_id, component_id, last_msg); + mavlink_test_pixhawk(system_id, component_id, last_msg); +} +#endif + +#include "../common/testsuite.h" + + +static void mavlink_test_set_cam_shutter(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_set_cam_shutter_t packet_in = { + 17.0, + 17443, + 17547, + 29, + 96, + 163, + }; + mavlink_set_cam_shutter_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.gain = packet_in.gain; + packet1.interval = packet_in.interval; + packet1.exposure = packet_in.exposure; + packet1.cam_no = packet_in.cam_no; + packet1.cam_mode = packet_in.cam_mode; + packet1.trigger_pin = packet_in.trigger_pin; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_set_cam_shutter_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_set_cam_shutter_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_set_cam_shutter_pack(system_id, component_id, &msg , packet1.cam_no , packet1.cam_mode , packet1.trigger_pin , packet1.interval , packet1.exposure , packet1.gain ); + mavlink_msg_set_cam_shutter_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_set_cam_shutter_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.cam_no , packet1.cam_mode , packet1.trigger_pin , packet1.interval , packet1.exposure , packet1.gain ); + mavlink_msg_set_cam_shutter_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; ilen + MAVLINK_NUM_NON_PAYLOAD_BYTES; +} + +#if MAVLINK_NEED_BYTE_SWAP +static inline void byte_swap_2(char *dst, const char *src) +{ + dst[0] = src[1]; + dst[1] = src[0]; +} +static inline void byte_swap_4(char *dst, const char *src) +{ + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; +} +static inline void byte_swap_8(char *dst, const char *src) +{ + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; +} +#elif !MAVLINK_ALIGNED_FIELDS +static inline void byte_copy_2(char *dst, const char *src) +{ + dst[0] = src[0]; + dst[1] = src[1]; +} +static inline void byte_copy_4(char *dst, const char *src) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} +static inline void byte_copy_8(char *dst, const char *src) +{ + memcpy(dst, src, 8); +} +#endif + +#define _mav_put_uint8_t(buf, wire_offset, b) buf[wire_offset] = (uint8_t)b +#define _mav_put_int8_t(buf, wire_offset, b) buf[wire_offset] = (int8_t)b +#define _mav_put_char(buf, wire_offset, b) buf[wire_offset] = b + +#if MAVLINK_NEED_BYTE_SWAP +#define _mav_put_uint16_t(buf, wire_offset, b) byte_swap_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_int16_t(buf, wire_offset, b) byte_swap_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint32_t(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_int32_t(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint64_t(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_int64_t(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_float(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_double(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b) +#elif !MAVLINK_ALIGNED_FIELDS +#define _mav_put_uint16_t(buf, wire_offset, b) byte_copy_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_int16_t(buf, wire_offset, b) byte_copy_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint32_t(buf, wire_offset, b) byte_copy_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_int32_t(buf, wire_offset, b) byte_copy_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint64_t(buf, wire_offset, b) byte_copy_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_int64_t(buf, wire_offset, b) byte_copy_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_float(buf, wire_offset, b) byte_copy_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_double(buf, wire_offset, b) byte_copy_8(&buf[wire_offset], (const char *)&b) +#else +#define _mav_put_uint16_t(buf, wire_offset, b) *(uint16_t *)&buf[wire_offset] = b +#define _mav_put_int16_t(buf, wire_offset, b) *(int16_t *)&buf[wire_offset] = b +#define _mav_put_uint32_t(buf, wire_offset, b) *(uint32_t *)&buf[wire_offset] = b +#define _mav_put_int32_t(buf, wire_offset, b) *(int32_t *)&buf[wire_offset] = b +#define _mav_put_uint64_t(buf, wire_offset, b) *(uint64_t *)&buf[wire_offset] = b +#define _mav_put_int64_t(buf, wire_offset, b) *(int64_t *)&buf[wire_offset] = b +#define _mav_put_float(buf, wire_offset, b) *(float *)&buf[wire_offset] = b +#define _mav_put_double(buf, wire_offset, b) *(double *)&buf[wire_offset] = b +#endif + +/* + like memcpy(), but if src is NULL, do a memset to zero +*/ +static void mav_array_memcpy(void *dest, const void *src, size_t n) +{ + if (src == NULL) { + memset(dest, 0, n); + } else { + memcpy(dest, src, n); + } +} + +/* + * Place a char array into a buffer + */ +static inline void _mav_put_char_array(char *buf, uint8_t wire_offset, const char *b, uint8_t array_length) +{ + mav_array_memcpy(&buf[wire_offset], b, array_length); + +} + +/* + * Place a uint8_t array into a buffer + */ +static inline void _mav_put_uint8_t_array(char *buf, uint8_t wire_offset, const uint8_t *b, uint8_t array_length) +{ + mav_array_memcpy(&buf[wire_offset], b, array_length); + +} + +/* + * Place a int8_t array into a buffer + */ +static inline void _mav_put_int8_t_array(char *buf, uint8_t wire_offset, const int8_t *b, uint8_t array_length) +{ + mav_array_memcpy(&buf[wire_offset], b, array_length); + +} + +#if MAVLINK_NEED_BYTE_SWAP +#define _MAV_PUT_ARRAY(TYPE, V) \ +static inline void _mav_put_ ## TYPE ##_array(char *buf, uint8_t wire_offset, const TYPE *b, uint8_t array_length) \ +{ \ + if (b == NULL) { \ + memset(&buf[wire_offset], 0, array_length*sizeof(TYPE)); \ + } else { \ + uint16_t i; \ + for (i=0; imsgid = MAVLINK_MSG_ID_CMD_AIRSPEED_ACK; + return mavlink_finalize_message(msg, system_id, component_id, 5, 243); +} + +/** + * @brief Pack a cmd_airspeed_ack message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param spCmd commanded airspeed + * @param ack 0:ack, 1:nack + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_cmd_airspeed_ack_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float spCmd,uint8_t ack) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[5]; + _mav_put_float(buf, 0, spCmd); + _mav_put_uint8_t(buf, 4, ack); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 5); +#else + mavlink_cmd_airspeed_ack_t packet; + packet.spCmd = spCmd; + packet.ack = ack; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 5); +#endif + + msg->msgid = MAVLINK_MSG_ID_CMD_AIRSPEED_ACK; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 5, 243); +} + +/** + * @brief Encode a cmd_airspeed_ack struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param cmd_airspeed_ack C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_cmd_airspeed_ack_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_cmd_airspeed_ack_t* cmd_airspeed_ack) +{ + return mavlink_msg_cmd_airspeed_ack_pack(system_id, component_id, msg, cmd_airspeed_ack->spCmd, cmd_airspeed_ack->ack); +} + +/** + * @brief Send a cmd_airspeed_ack message + * @param chan MAVLink channel to send the message + * + * @param spCmd commanded airspeed + * @param ack 0:ack, 1:nack + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_cmd_airspeed_ack_send(mavlink_channel_t chan, float spCmd, uint8_t ack) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[5]; + _mav_put_float(buf, 0, spCmd); + _mav_put_uint8_t(buf, 4, ack); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CMD_AIRSPEED_ACK, buf, 5, 243); +#else + mavlink_cmd_airspeed_ack_t packet; + packet.spCmd = spCmd; + packet.ack = ack; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CMD_AIRSPEED_ACK, (const char *)&packet, 5, 243); +#endif +} + +#endif + +// MESSAGE CMD_AIRSPEED_ACK UNPACKING + + +/** + * @brief Get field spCmd from cmd_airspeed_ack message + * + * @return commanded airspeed + */ +static inline float mavlink_msg_cmd_airspeed_ack_get_spCmd(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field ack from cmd_airspeed_ack message + * + * @return 0:ack, 1:nack + */ +static inline uint8_t mavlink_msg_cmd_airspeed_ack_get_ack(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Decode a cmd_airspeed_ack message into a struct + * + * @param msg The message to decode + * @param cmd_airspeed_ack C-struct to decode the message contents into + */ +static inline void mavlink_msg_cmd_airspeed_ack_decode(const mavlink_message_t* msg, mavlink_cmd_airspeed_ack_t* cmd_airspeed_ack) +{ +#if MAVLINK_NEED_BYTE_SWAP + cmd_airspeed_ack->spCmd = mavlink_msg_cmd_airspeed_ack_get_spCmd(msg); + cmd_airspeed_ack->ack = mavlink_msg_cmd_airspeed_ack_get_ack(msg); +#else + memcpy(cmd_airspeed_ack, _MAV_PAYLOAD(msg), 5); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_cmd_airspeed_chng.h b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_cmd_airspeed_chng.h new file mode 100644 index 0000000000..d5b21b8d79 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_cmd_airspeed_chng.h @@ -0,0 +1,166 @@ +// MESSAGE CMD_AIRSPEED_CHNG PACKING + +#define MAVLINK_MSG_ID_CMD_AIRSPEED_CHNG 192 + +typedef struct __mavlink_cmd_airspeed_chng_t +{ + float spCmd; ///< commanded airspeed + uint8_t target; ///< Target ID +} mavlink_cmd_airspeed_chng_t; + +#define MAVLINK_MSG_ID_CMD_AIRSPEED_CHNG_LEN 5 +#define MAVLINK_MSG_ID_192_LEN 5 + + + +#define MAVLINK_MESSAGE_INFO_CMD_AIRSPEED_CHNG { \ + "CMD_AIRSPEED_CHNG", \ + 2, \ + { { "spCmd", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_cmd_airspeed_chng_t, spCmd) }, \ + { "target", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_cmd_airspeed_chng_t, target) }, \ + } \ +} + + +/** + * @brief Pack a cmd_airspeed_chng message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target Target ID + * @param spCmd commanded airspeed + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_cmd_airspeed_chng_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target, float spCmd) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[5]; + _mav_put_float(buf, 0, spCmd); + _mav_put_uint8_t(buf, 4, target); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 5); +#else + mavlink_cmd_airspeed_chng_t packet; + packet.spCmd = spCmd; + packet.target = target; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 5); +#endif + + msg->msgid = MAVLINK_MSG_ID_CMD_AIRSPEED_CHNG; + return mavlink_finalize_message(msg, system_id, component_id, 5, 209); +} + +/** + * @brief Pack a cmd_airspeed_chng message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target Target ID + * @param spCmd commanded airspeed + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_cmd_airspeed_chng_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,float spCmd) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[5]; + _mav_put_float(buf, 0, spCmd); + _mav_put_uint8_t(buf, 4, target); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 5); +#else + mavlink_cmd_airspeed_chng_t packet; + packet.spCmd = spCmd; + packet.target = target; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 5); +#endif + + msg->msgid = MAVLINK_MSG_ID_CMD_AIRSPEED_CHNG; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 5, 209); +} + +/** + * @brief Encode a cmd_airspeed_chng struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param cmd_airspeed_chng C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_cmd_airspeed_chng_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_cmd_airspeed_chng_t* cmd_airspeed_chng) +{ + return mavlink_msg_cmd_airspeed_chng_pack(system_id, component_id, msg, cmd_airspeed_chng->target, cmd_airspeed_chng->spCmd); +} + +/** + * @brief Send a cmd_airspeed_chng message + * @param chan MAVLink channel to send the message + * + * @param target Target ID + * @param spCmd commanded airspeed + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_cmd_airspeed_chng_send(mavlink_channel_t chan, uint8_t target, float spCmd) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[5]; + _mav_put_float(buf, 0, spCmd); + _mav_put_uint8_t(buf, 4, target); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CMD_AIRSPEED_CHNG, buf, 5, 209); +#else + mavlink_cmd_airspeed_chng_t packet; + packet.spCmd = spCmd; + packet.target = target; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CMD_AIRSPEED_CHNG, (const char *)&packet, 5, 209); +#endif +} + +#endif + +// MESSAGE CMD_AIRSPEED_CHNG UNPACKING + + +/** + * @brief Get field target from cmd_airspeed_chng message + * + * @return Target ID + */ +static inline uint8_t mavlink_msg_cmd_airspeed_chng_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field spCmd from cmd_airspeed_chng message + * + * @return commanded airspeed + */ +static inline float mavlink_msg_cmd_airspeed_chng_get_spCmd(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Decode a cmd_airspeed_chng message into a struct + * + * @param msg The message to decode + * @param cmd_airspeed_chng C-struct to decode the message contents into + */ +static inline void mavlink_msg_cmd_airspeed_chng_decode(const mavlink_message_t* msg, mavlink_cmd_airspeed_chng_t* cmd_airspeed_chng) +{ +#if MAVLINK_NEED_BYTE_SWAP + cmd_airspeed_chng->spCmd = mavlink_msg_cmd_airspeed_chng_get_spCmd(msg); + cmd_airspeed_chng->target = mavlink_msg_cmd_airspeed_chng_get_target(msg); +#else + memcpy(cmd_airspeed_chng, _MAV_PAYLOAD(msg), 5); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_filt_rot_vel.h b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_filt_rot_vel.h new file mode 100644 index 0000000000..f5fef06f04 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_filt_rot_vel.h @@ -0,0 +1,144 @@ +// MESSAGE FILT_ROT_VEL PACKING + +#define MAVLINK_MSG_ID_FILT_ROT_VEL 184 + +typedef struct __mavlink_filt_rot_vel_t +{ + float rotVel[3]; ///< rotational velocity +} mavlink_filt_rot_vel_t; + +#define MAVLINK_MSG_ID_FILT_ROT_VEL_LEN 12 +#define MAVLINK_MSG_ID_184_LEN 12 + +#define MAVLINK_MSG_FILT_ROT_VEL_FIELD_ROTVEL_LEN 3 + +#define MAVLINK_MESSAGE_INFO_FILT_ROT_VEL { \ + "FILT_ROT_VEL", \ + 1, \ + { { "rotVel", NULL, MAVLINK_TYPE_FLOAT, 3, 0, offsetof(mavlink_filt_rot_vel_t, rotVel) }, \ + } \ +} + + +/** + * @brief Pack a filt_rot_vel message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param rotVel rotational velocity + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_filt_rot_vel_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const float *rotVel) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + + _mav_put_float_array(buf, 0, rotVel, 3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_filt_rot_vel_t packet; + + mav_array_memcpy(packet.rotVel, rotVel, sizeof(float)*3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_FILT_ROT_VEL; + return mavlink_finalize_message(msg, system_id, component_id, 12, 79); +} + +/** + * @brief Pack a filt_rot_vel message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param rotVel rotational velocity + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_filt_rot_vel_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const float *rotVel) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + + _mav_put_float_array(buf, 0, rotVel, 3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_filt_rot_vel_t packet; + + mav_array_memcpy(packet.rotVel, rotVel, sizeof(float)*3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_FILT_ROT_VEL; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12, 79); +} + +/** + * @brief Encode a filt_rot_vel struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param filt_rot_vel C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_filt_rot_vel_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_filt_rot_vel_t* filt_rot_vel) +{ + return mavlink_msg_filt_rot_vel_pack(system_id, component_id, msg, filt_rot_vel->rotVel); +} + +/** + * @brief Send a filt_rot_vel message + * @param chan MAVLink channel to send the message + * + * @param rotVel rotational velocity + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_filt_rot_vel_send(mavlink_channel_t chan, const float *rotVel) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + + _mav_put_float_array(buf, 0, rotVel, 3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FILT_ROT_VEL, buf, 12, 79); +#else + mavlink_filt_rot_vel_t packet; + + mav_array_memcpy(packet.rotVel, rotVel, sizeof(float)*3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_FILT_ROT_VEL, (const char *)&packet, 12, 79); +#endif +} + +#endif + +// MESSAGE FILT_ROT_VEL UNPACKING + + +/** + * @brief Get field rotVel from filt_rot_vel message + * + * @return rotational velocity + */ +static inline uint16_t mavlink_msg_filt_rot_vel_get_rotVel(const mavlink_message_t* msg, float *rotVel) +{ + return _MAV_RETURN_float_array(msg, rotVel, 3, 0); +} + +/** + * @brief Decode a filt_rot_vel message into a struct + * + * @param msg The message to decode + * @param filt_rot_vel C-struct to decode the message contents into + */ +static inline void mavlink_msg_filt_rot_vel_decode(const mavlink_message_t* msg, mavlink_filt_rot_vel_t* filt_rot_vel) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_filt_rot_vel_get_rotVel(msg, filt_rot_vel->rotVel); +#else + memcpy(filt_rot_vel, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_llc_out.h b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_llc_out.h new file mode 100644 index 0000000000..5ee3d5a19f --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_llc_out.h @@ -0,0 +1,167 @@ +// MESSAGE LLC_OUT PACKING + +#define MAVLINK_MSG_ID_LLC_OUT 186 + +typedef struct __mavlink_llc_out_t +{ + int16_t servoOut[4]; ///< Servo signal + int16_t MotorOut[2]; ///< motor signal +} mavlink_llc_out_t; + +#define MAVLINK_MSG_ID_LLC_OUT_LEN 12 +#define MAVLINK_MSG_ID_186_LEN 12 + +#define MAVLINK_MSG_LLC_OUT_FIELD_SERVOOUT_LEN 4 +#define MAVLINK_MSG_LLC_OUT_FIELD_MOTOROUT_LEN 2 + +#define MAVLINK_MESSAGE_INFO_LLC_OUT { \ + "LLC_OUT", \ + 2, \ + { { "servoOut", NULL, MAVLINK_TYPE_INT16_T, 4, 0, offsetof(mavlink_llc_out_t, servoOut) }, \ + { "MotorOut", NULL, MAVLINK_TYPE_INT16_T, 2, 8, offsetof(mavlink_llc_out_t, MotorOut) }, \ + } \ +} + + +/** + * @brief Pack a llc_out message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param servoOut Servo signal + * @param MotorOut motor signal + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_llc_out_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const int16_t *servoOut, const int16_t *MotorOut) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + + _mav_put_int16_t_array(buf, 0, servoOut, 4); + _mav_put_int16_t_array(buf, 8, MotorOut, 2); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_llc_out_t packet; + + mav_array_memcpy(packet.servoOut, servoOut, sizeof(int16_t)*4); + mav_array_memcpy(packet.MotorOut, MotorOut, sizeof(int16_t)*2); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_LLC_OUT; + return mavlink_finalize_message(msg, system_id, component_id, 12, 5); +} + +/** + * @brief Pack a llc_out message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param servoOut Servo signal + * @param MotorOut motor signal + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_llc_out_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const int16_t *servoOut,const int16_t *MotorOut) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + + _mav_put_int16_t_array(buf, 0, servoOut, 4); + _mav_put_int16_t_array(buf, 8, MotorOut, 2); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_llc_out_t packet; + + mav_array_memcpy(packet.servoOut, servoOut, sizeof(int16_t)*4); + mav_array_memcpy(packet.MotorOut, MotorOut, sizeof(int16_t)*2); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_LLC_OUT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12, 5); +} + +/** + * @brief Encode a llc_out struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param llc_out C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_llc_out_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_llc_out_t* llc_out) +{ + return mavlink_msg_llc_out_pack(system_id, component_id, msg, llc_out->servoOut, llc_out->MotorOut); +} + +/** + * @brief Send a llc_out message + * @param chan MAVLink channel to send the message + * + * @param servoOut Servo signal + * @param MotorOut motor signal + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_llc_out_send(mavlink_channel_t chan, const int16_t *servoOut, const int16_t *MotorOut) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + + _mav_put_int16_t_array(buf, 0, servoOut, 4); + _mav_put_int16_t_array(buf, 8, MotorOut, 2); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LLC_OUT, buf, 12, 5); +#else + mavlink_llc_out_t packet; + + mav_array_memcpy(packet.servoOut, servoOut, sizeof(int16_t)*4); + mav_array_memcpy(packet.MotorOut, MotorOut, sizeof(int16_t)*2); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_LLC_OUT, (const char *)&packet, 12, 5); +#endif +} + +#endif + +// MESSAGE LLC_OUT UNPACKING + + +/** + * @brief Get field servoOut from llc_out message + * + * @return Servo signal + */ +static inline uint16_t mavlink_msg_llc_out_get_servoOut(const mavlink_message_t* msg, int16_t *servoOut) +{ + return _MAV_RETURN_int16_t_array(msg, servoOut, 4, 0); +} + +/** + * @brief Get field MotorOut from llc_out message + * + * @return motor signal + */ +static inline uint16_t mavlink_msg_llc_out_get_MotorOut(const mavlink_message_t* msg, int16_t *MotorOut) +{ + return _MAV_RETURN_int16_t_array(msg, MotorOut, 2, 8); +} + +/** + * @brief Decode a llc_out message into a struct + * + * @param msg The message to decode + * @param llc_out C-struct to decode the message contents into + */ +static inline void mavlink_msg_llc_out_decode(const mavlink_message_t* msg, mavlink_llc_out_t* llc_out) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_llc_out_get_servoOut(msg, llc_out->servoOut); + mavlink_msg_llc_out_get_MotorOut(msg, llc_out->MotorOut); +#else + memcpy(llc_out, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_air_temp.h b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_air_temp.h new file mode 100644 index 0000000000..60cf018454 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_air_temp.h @@ -0,0 +1,144 @@ +// MESSAGE OBS_AIR_TEMP PACKING + +#define MAVLINK_MSG_ID_OBS_AIR_TEMP 183 + +typedef struct __mavlink_obs_air_temp_t +{ + float airT; ///< Air Temperatur +} mavlink_obs_air_temp_t; + +#define MAVLINK_MSG_ID_OBS_AIR_TEMP_LEN 4 +#define MAVLINK_MSG_ID_183_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_OBS_AIR_TEMP { \ + "OBS_AIR_TEMP", \ + 1, \ + { { "airT", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_obs_air_temp_t, airT) }, \ + } \ +} + + +/** + * @brief Pack a obs_air_temp message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param airT Air Temperatur + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_air_temp_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float airT) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_float(buf, 0, airT); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_obs_air_temp_t packet; + packet.airT = airT; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_AIR_TEMP; + return mavlink_finalize_message(msg, system_id, component_id, 4, 248); +} + +/** + * @brief Pack a obs_air_temp message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param airT Air Temperatur + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_air_temp_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float airT) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_float(buf, 0, airT); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_obs_air_temp_t packet; + packet.airT = airT; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_AIR_TEMP; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4, 248); +} + +/** + * @brief Encode a obs_air_temp struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param obs_air_temp C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_obs_air_temp_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_obs_air_temp_t* obs_air_temp) +{ + return mavlink_msg_obs_air_temp_pack(system_id, component_id, msg, obs_air_temp->airT); +} + +/** + * @brief Send a obs_air_temp message + * @param chan MAVLink channel to send the message + * + * @param airT Air Temperatur + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_obs_air_temp_send(mavlink_channel_t chan, float airT) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_float(buf, 0, airT); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_AIR_TEMP, buf, 4, 248); +#else + mavlink_obs_air_temp_t packet; + packet.airT = airT; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_AIR_TEMP, (const char *)&packet, 4, 248); +#endif +} + +#endif + +// MESSAGE OBS_AIR_TEMP UNPACKING + + +/** + * @brief Get field airT from obs_air_temp message + * + * @return Air Temperatur + */ +static inline float mavlink_msg_obs_air_temp_get_airT(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Decode a obs_air_temp message into a struct + * + * @param msg The message to decode + * @param obs_air_temp C-struct to decode the message contents into + */ +static inline void mavlink_msg_obs_air_temp_decode(const mavlink_message_t* msg, mavlink_obs_air_temp_t* obs_air_temp) +{ +#if MAVLINK_NEED_BYTE_SWAP + obs_air_temp->airT = mavlink_msg_obs_air_temp_get_airT(msg); +#else + memcpy(obs_air_temp, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_air_velocity.h b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_air_velocity.h new file mode 100644 index 0000000000..ef56c5c617 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_air_velocity.h @@ -0,0 +1,188 @@ +// MESSAGE OBS_AIR_VELOCITY PACKING + +#define MAVLINK_MSG_ID_OBS_AIR_VELOCITY 178 + +typedef struct __mavlink_obs_air_velocity_t +{ + float magnitude; ///< Air speed + float aoa; ///< angle of attack + float slip; ///< slip angle +} mavlink_obs_air_velocity_t; + +#define MAVLINK_MSG_ID_OBS_AIR_VELOCITY_LEN 12 +#define MAVLINK_MSG_ID_178_LEN 12 + + + +#define MAVLINK_MESSAGE_INFO_OBS_AIR_VELOCITY { \ + "OBS_AIR_VELOCITY", \ + 3, \ + { { "magnitude", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_obs_air_velocity_t, magnitude) }, \ + { "aoa", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_obs_air_velocity_t, aoa) }, \ + { "slip", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_obs_air_velocity_t, slip) }, \ + } \ +} + + +/** + * @brief Pack a obs_air_velocity message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param magnitude Air speed + * @param aoa angle of attack + * @param slip slip angle + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_air_velocity_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float magnitude, float aoa, float slip) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_float(buf, 0, magnitude); + _mav_put_float(buf, 4, aoa); + _mav_put_float(buf, 8, slip); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_obs_air_velocity_t packet; + packet.magnitude = magnitude; + packet.aoa = aoa; + packet.slip = slip; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_AIR_VELOCITY; + return mavlink_finalize_message(msg, system_id, component_id, 12, 32); +} + +/** + * @brief Pack a obs_air_velocity message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param magnitude Air speed + * @param aoa angle of attack + * @param slip slip angle + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_air_velocity_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float magnitude,float aoa,float slip) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_float(buf, 0, magnitude); + _mav_put_float(buf, 4, aoa); + _mav_put_float(buf, 8, slip); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_obs_air_velocity_t packet; + packet.magnitude = magnitude; + packet.aoa = aoa; + packet.slip = slip; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_AIR_VELOCITY; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12, 32); +} + +/** + * @brief Encode a obs_air_velocity struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param obs_air_velocity C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_obs_air_velocity_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_obs_air_velocity_t* obs_air_velocity) +{ + return mavlink_msg_obs_air_velocity_pack(system_id, component_id, msg, obs_air_velocity->magnitude, obs_air_velocity->aoa, obs_air_velocity->slip); +} + +/** + * @brief Send a obs_air_velocity message + * @param chan MAVLink channel to send the message + * + * @param magnitude Air speed + * @param aoa angle of attack + * @param slip slip angle + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_obs_air_velocity_send(mavlink_channel_t chan, float magnitude, float aoa, float slip) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_float(buf, 0, magnitude); + _mav_put_float(buf, 4, aoa); + _mav_put_float(buf, 8, slip); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_AIR_VELOCITY, buf, 12, 32); +#else + mavlink_obs_air_velocity_t packet; + packet.magnitude = magnitude; + packet.aoa = aoa; + packet.slip = slip; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_AIR_VELOCITY, (const char *)&packet, 12, 32); +#endif +} + +#endif + +// MESSAGE OBS_AIR_VELOCITY UNPACKING + + +/** + * @brief Get field magnitude from obs_air_velocity message + * + * @return Air speed + */ +static inline float mavlink_msg_obs_air_velocity_get_magnitude(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field aoa from obs_air_velocity message + * + * @return angle of attack + */ +static inline float mavlink_msg_obs_air_velocity_get_aoa(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field slip from obs_air_velocity message + * + * @return slip angle + */ +static inline float mavlink_msg_obs_air_velocity_get_slip(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Decode a obs_air_velocity message into a struct + * + * @param msg The message to decode + * @param obs_air_velocity C-struct to decode the message contents into + */ +static inline void mavlink_msg_obs_air_velocity_decode(const mavlink_message_t* msg, mavlink_obs_air_velocity_t* obs_air_velocity) +{ +#if MAVLINK_NEED_BYTE_SWAP + obs_air_velocity->magnitude = mavlink_msg_obs_air_velocity_get_magnitude(msg); + obs_air_velocity->aoa = mavlink_msg_obs_air_velocity_get_aoa(msg); + obs_air_velocity->slip = mavlink_msg_obs_air_velocity_get_slip(msg); +#else + memcpy(obs_air_velocity, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_attitude.h b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_attitude.h new file mode 100644 index 0000000000..7a3e6d0ba4 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_attitude.h @@ -0,0 +1,144 @@ +// MESSAGE OBS_ATTITUDE PACKING + +#define MAVLINK_MSG_ID_OBS_ATTITUDE 174 + +typedef struct __mavlink_obs_attitude_t +{ + double quat[4]; ///< Quaternion re;im +} mavlink_obs_attitude_t; + +#define MAVLINK_MSG_ID_OBS_ATTITUDE_LEN 32 +#define MAVLINK_MSG_ID_174_LEN 32 + +#define MAVLINK_MSG_OBS_ATTITUDE_FIELD_QUAT_LEN 4 + +#define MAVLINK_MESSAGE_INFO_OBS_ATTITUDE { \ + "OBS_ATTITUDE", \ + 1, \ + { { "quat", NULL, MAVLINK_TYPE_DOUBLE, 4, 0, offsetof(mavlink_obs_attitude_t, quat) }, \ + } \ +} + + +/** + * @brief Pack a obs_attitude message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param quat Quaternion re;im + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_attitude_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const double *quat) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + + _mav_put_double_array(buf, 0, quat, 4); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_obs_attitude_t packet; + + mav_array_memcpy(packet.quat, quat, sizeof(double)*4); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_ATTITUDE; + return mavlink_finalize_message(msg, system_id, component_id, 32, 146); +} + +/** + * @brief Pack a obs_attitude message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param quat Quaternion re;im + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_attitude_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const double *quat) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + + _mav_put_double_array(buf, 0, quat, 4); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_obs_attitude_t packet; + + mav_array_memcpy(packet.quat, quat, sizeof(double)*4); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_ATTITUDE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32, 146); +} + +/** + * @brief Encode a obs_attitude struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param obs_attitude C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_obs_attitude_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_obs_attitude_t* obs_attitude) +{ + return mavlink_msg_obs_attitude_pack(system_id, component_id, msg, obs_attitude->quat); +} + +/** + * @brief Send a obs_attitude message + * @param chan MAVLink channel to send the message + * + * @param quat Quaternion re;im + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_obs_attitude_send(mavlink_channel_t chan, const double *quat) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + + _mav_put_double_array(buf, 0, quat, 4); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_ATTITUDE, buf, 32, 146); +#else + mavlink_obs_attitude_t packet; + + mav_array_memcpy(packet.quat, quat, sizeof(double)*4); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_ATTITUDE, (const char *)&packet, 32, 146); +#endif +} + +#endif + +// MESSAGE OBS_ATTITUDE UNPACKING + + +/** + * @brief Get field quat from obs_attitude message + * + * @return Quaternion re;im + */ +static inline uint16_t mavlink_msg_obs_attitude_get_quat(const mavlink_message_t* msg, double *quat) +{ + return _MAV_RETURN_double_array(msg, quat, 4, 0); +} + +/** + * @brief Decode a obs_attitude message into a struct + * + * @param msg The message to decode + * @param obs_attitude C-struct to decode the message contents into + */ +static inline void mavlink_msg_obs_attitude_decode(const mavlink_message_t* msg, mavlink_obs_attitude_t* obs_attitude) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_obs_attitude_get_quat(msg, obs_attitude->quat); +#else + memcpy(obs_attitude, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_bias.h b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_bias.h new file mode 100644 index 0000000000..565ab0cd86 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_bias.h @@ -0,0 +1,167 @@ +// MESSAGE OBS_BIAS PACKING + +#define MAVLINK_MSG_ID_OBS_BIAS 180 + +typedef struct __mavlink_obs_bias_t +{ + float accBias[3]; ///< accelerometer bias + float gyroBias[3]; ///< gyroscope bias +} mavlink_obs_bias_t; + +#define MAVLINK_MSG_ID_OBS_BIAS_LEN 24 +#define MAVLINK_MSG_ID_180_LEN 24 + +#define MAVLINK_MSG_OBS_BIAS_FIELD_ACCBIAS_LEN 3 +#define MAVLINK_MSG_OBS_BIAS_FIELD_GYROBIAS_LEN 3 + +#define MAVLINK_MESSAGE_INFO_OBS_BIAS { \ + "OBS_BIAS", \ + 2, \ + { { "accBias", NULL, MAVLINK_TYPE_FLOAT, 3, 0, offsetof(mavlink_obs_bias_t, accBias) }, \ + { "gyroBias", NULL, MAVLINK_TYPE_FLOAT, 3, 12, offsetof(mavlink_obs_bias_t, gyroBias) }, \ + } \ +} + + +/** + * @brief Pack a obs_bias message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param accBias accelerometer bias + * @param gyroBias gyroscope bias + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_bias_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const float *accBias, const float *gyroBias) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + + _mav_put_float_array(buf, 0, accBias, 3); + _mav_put_float_array(buf, 12, gyroBias, 3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_obs_bias_t packet; + + mav_array_memcpy(packet.accBias, accBias, sizeof(float)*3); + mav_array_memcpy(packet.gyroBias, gyroBias, sizeof(float)*3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_BIAS; + return mavlink_finalize_message(msg, system_id, component_id, 24, 159); +} + +/** + * @brief Pack a obs_bias message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param accBias accelerometer bias + * @param gyroBias gyroscope bias + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_bias_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const float *accBias,const float *gyroBias) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + + _mav_put_float_array(buf, 0, accBias, 3); + _mav_put_float_array(buf, 12, gyroBias, 3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_obs_bias_t packet; + + mav_array_memcpy(packet.accBias, accBias, sizeof(float)*3); + mav_array_memcpy(packet.gyroBias, gyroBias, sizeof(float)*3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_BIAS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 24, 159); +} + +/** + * @brief Encode a obs_bias struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param obs_bias C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_obs_bias_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_obs_bias_t* obs_bias) +{ + return mavlink_msg_obs_bias_pack(system_id, component_id, msg, obs_bias->accBias, obs_bias->gyroBias); +} + +/** + * @brief Send a obs_bias message + * @param chan MAVLink channel to send the message + * + * @param accBias accelerometer bias + * @param gyroBias gyroscope bias + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_obs_bias_send(mavlink_channel_t chan, const float *accBias, const float *gyroBias) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + + _mav_put_float_array(buf, 0, accBias, 3); + _mav_put_float_array(buf, 12, gyroBias, 3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_BIAS, buf, 24, 159); +#else + mavlink_obs_bias_t packet; + + mav_array_memcpy(packet.accBias, accBias, sizeof(float)*3); + mav_array_memcpy(packet.gyroBias, gyroBias, sizeof(float)*3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_BIAS, (const char *)&packet, 24, 159); +#endif +} + +#endif + +// MESSAGE OBS_BIAS UNPACKING + + +/** + * @brief Get field accBias from obs_bias message + * + * @return accelerometer bias + */ +static inline uint16_t mavlink_msg_obs_bias_get_accBias(const mavlink_message_t* msg, float *accBias) +{ + return _MAV_RETURN_float_array(msg, accBias, 3, 0); +} + +/** + * @brief Get field gyroBias from obs_bias message + * + * @return gyroscope bias + */ +static inline uint16_t mavlink_msg_obs_bias_get_gyroBias(const mavlink_message_t* msg, float *gyroBias) +{ + return _MAV_RETURN_float_array(msg, gyroBias, 3, 12); +} + +/** + * @brief Decode a obs_bias message into a struct + * + * @param msg The message to decode + * @param obs_bias C-struct to decode the message contents into + */ +static inline void mavlink_msg_obs_bias_decode(const mavlink_message_t* msg, mavlink_obs_bias_t* obs_bias) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_obs_bias_get_accBias(msg, obs_bias->accBias); + mavlink_msg_obs_bias_get_gyroBias(msg, obs_bias->gyroBias); +#else + memcpy(obs_bias, _MAV_PAYLOAD(msg), 24); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_position.h b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_position.h new file mode 100644 index 0000000000..e886c8c24f --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_position.h @@ -0,0 +1,188 @@ +// MESSAGE OBS_POSITION PACKING + +#define MAVLINK_MSG_ID_OBS_POSITION 170 + +typedef struct __mavlink_obs_position_t +{ + int32_t lon; ///< Longitude expressed in 1E7 + int32_t lat; ///< Latitude expressed in 1E7 + int32_t alt; ///< Altitude expressed in milimeters +} mavlink_obs_position_t; + +#define MAVLINK_MSG_ID_OBS_POSITION_LEN 12 +#define MAVLINK_MSG_ID_170_LEN 12 + + + +#define MAVLINK_MESSAGE_INFO_OBS_POSITION { \ + "OBS_POSITION", \ + 3, \ + { { "lon", NULL, MAVLINK_TYPE_INT32_T, 0, 0, offsetof(mavlink_obs_position_t, lon) }, \ + { "lat", NULL, MAVLINK_TYPE_INT32_T, 0, 4, offsetof(mavlink_obs_position_t, lat) }, \ + { "alt", NULL, MAVLINK_TYPE_INT32_T, 0, 8, offsetof(mavlink_obs_position_t, alt) }, \ + } \ +} + + +/** + * @brief Pack a obs_position message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param lon Longitude expressed in 1E7 + * @param lat Latitude expressed in 1E7 + * @param alt Altitude expressed in milimeters + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_position_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + int32_t lon, int32_t lat, int32_t alt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_int32_t(buf, 0, lon); + _mav_put_int32_t(buf, 4, lat); + _mav_put_int32_t(buf, 8, alt); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_obs_position_t packet; + packet.lon = lon; + packet.lat = lat; + packet.alt = alt; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_POSITION; + return mavlink_finalize_message(msg, system_id, component_id, 12, 15); +} + +/** + * @brief Pack a obs_position message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param lon Longitude expressed in 1E7 + * @param lat Latitude expressed in 1E7 + * @param alt Altitude expressed in milimeters + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_position_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + int32_t lon,int32_t lat,int32_t alt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_int32_t(buf, 0, lon); + _mav_put_int32_t(buf, 4, lat); + _mav_put_int32_t(buf, 8, alt); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_obs_position_t packet; + packet.lon = lon; + packet.lat = lat; + packet.alt = alt; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_POSITION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12, 15); +} + +/** + * @brief Encode a obs_position struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param obs_position C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_obs_position_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_obs_position_t* obs_position) +{ + return mavlink_msg_obs_position_pack(system_id, component_id, msg, obs_position->lon, obs_position->lat, obs_position->alt); +} + +/** + * @brief Send a obs_position message + * @param chan MAVLink channel to send the message + * + * @param lon Longitude expressed in 1E7 + * @param lat Latitude expressed in 1E7 + * @param alt Altitude expressed in milimeters + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_obs_position_send(mavlink_channel_t chan, int32_t lon, int32_t lat, int32_t alt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + _mav_put_int32_t(buf, 0, lon); + _mav_put_int32_t(buf, 4, lat); + _mav_put_int32_t(buf, 8, alt); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_POSITION, buf, 12, 15); +#else + mavlink_obs_position_t packet; + packet.lon = lon; + packet.lat = lat; + packet.alt = alt; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_POSITION, (const char *)&packet, 12, 15); +#endif +} + +#endif + +// MESSAGE OBS_POSITION UNPACKING + + +/** + * @brief Get field lon from obs_position message + * + * @return Longitude expressed in 1E7 + */ +static inline int32_t mavlink_msg_obs_position_get_lon(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 0); +} + +/** + * @brief Get field lat from obs_position message + * + * @return Latitude expressed in 1E7 + */ +static inline int32_t mavlink_msg_obs_position_get_lat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 4); +} + +/** + * @brief Get field alt from obs_position message + * + * @return Altitude expressed in milimeters + */ +static inline int32_t mavlink_msg_obs_position_get_alt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 8); +} + +/** + * @brief Decode a obs_position message into a struct + * + * @param msg The message to decode + * @param obs_position C-struct to decode the message contents into + */ +static inline void mavlink_msg_obs_position_decode(const mavlink_message_t* msg, mavlink_obs_position_t* obs_position) +{ +#if MAVLINK_NEED_BYTE_SWAP + obs_position->lon = mavlink_msg_obs_position_get_lon(msg); + obs_position->lat = mavlink_msg_obs_position_get_lat(msg); + obs_position->alt = mavlink_msg_obs_position_get_alt(msg); +#else + memcpy(obs_position, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_qff.h b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_qff.h new file mode 100644 index 0000000000..4ab10ca07c --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_qff.h @@ -0,0 +1,144 @@ +// MESSAGE OBS_QFF PACKING + +#define MAVLINK_MSG_ID_OBS_QFF 182 + +typedef struct __mavlink_obs_qff_t +{ + float qff; ///< Wind +} mavlink_obs_qff_t; + +#define MAVLINK_MSG_ID_OBS_QFF_LEN 4 +#define MAVLINK_MSG_ID_182_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_OBS_QFF { \ + "OBS_QFF", \ + 1, \ + { { "qff", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_obs_qff_t, qff) }, \ + } \ +} + + +/** + * @brief Pack a obs_qff message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param qff Wind + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_qff_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float qff) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_float(buf, 0, qff); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_obs_qff_t packet; + packet.qff = qff; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_QFF; + return mavlink_finalize_message(msg, system_id, component_id, 4, 24); +} + +/** + * @brief Pack a obs_qff message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param qff Wind + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_qff_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float qff) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_float(buf, 0, qff); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_obs_qff_t packet; + packet.qff = qff; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_QFF; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4, 24); +} + +/** + * @brief Encode a obs_qff struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param obs_qff C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_obs_qff_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_obs_qff_t* obs_qff) +{ + return mavlink_msg_obs_qff_pack(system_id, component_id, msg, obs_qff->qff); +} + +/** + * @brief Send a obs_qff message + * @param chan MAVLink channel to send the message + * + * @param qff Wind + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_obs_qff_send(mavlink_channel_t chan, float qff) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_float(buf, 0, qff); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_QFF, buf, 4, 24); +#else + mavlink_obs_qff_t packet; + packet.qff = qff; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_QFF, (const char *)&packet, 4, 24); +#endif +} + +#endif + +// MESSAGE OBS_QFF UNPACKING + + +/** + * @brief Get field qff from obs_qff message + * + * @return Wind + */ +static inline float mavlink_msg_obs_qff_get_qff(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Decode a obs_qff message into a struct + * + * @param msg The message to decode + * @param obs_qff C-struct to decode the message contents into + */ +static inline void mavlink_msg_obs_qff_decode(const mavlink_message_t* msg, mavlink_obs_qff_t* obs_qff) +{ +#if MAVLINK_NEED_BYTE_SWAP + obs_qff->qff = mavlink_msg_obs_qff_get_qff(msg); +#else + memcpy(obs_qff, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_velocity.h b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_velocity.h new file mode 100644 index 0000000000..e5ace9f85e --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_velocity.h @@ -0,0 +1,144 @@ +// MESSAGE OBS_VELOCITY PACKING + +#define MAVLINK_MSG_ID_OBS_VELOCITY 172 + +typedef struct __mavlink_obs_velocity_t +{ + float vel[3]; ///< Velocity +} mavlink_obs_velocity_t; + +#define MAVLINK_MSG_ID_OBS_VELOCITY_LEN 12 +#define MAVLINK_MSG_ID_172_LEN 12 + +#define MAVLINK_MSG_OBS_VELOCITY_FIELD_VEL_LEN 3 + +#define MAVLINK_MESSAGE_INFO_OBS_VELOCITY { \ + "OBS_VELOCITY", \ + 1, \ + { { "vel", NULL, MAVLINK_TYPE_FLOAT, 3, 0, offsetof(mavlink_obs_velocity_t, vel) }, \ + } \ +} + + +/** + * @brief Pack a obs_velocity message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param vel Velocity + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_velocity_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const float *vel) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + + _mav_put_float_array(buf, 0, vel, 3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_obs_velocity_t packet; + + mav_array_memcpy(packet.vel, vel, sizeof(float)*3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_VELOCITY; + return mavlink_finalize_message(msg, system_id, component_id, 12, 108); +} + +/** + * @brief Pack a obs_velocity message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param vel Velocity + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_velocity_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const float *vel) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + + _mav_put_float_array(buf, 0, vel, 3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_obs_velocity_t packet; + + mav_array_memcpy(packet.vel, vel, sizeof(float)*3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_VELOCITY; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12, 108); +} + +/** + * @brief Encode a obs_velocity struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param obs_velocity C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_obs_velocity_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_obs_velocity_t* obs_velocity) +{ + return mavlink_msg_obs_velocity_pack(system_id, component_id, msg, obs_velocity->vel); +} + +/** + * @brief Send a obs_velocity message + * @param chan MAVLink channel to send the message + * + * @param vel Velocity + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_obs_velocity_send(mavlink_channel_t chan, const float *vel) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + + _mav_put_float_array(buf, 0, vel, 3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_VELOCITY, buf, 12, 108); +#else + mavlink_obs_velocity_t packet; + + mav_array_memcpy(packet.vel, vel, sizeof(float)*3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_VELOCITY, (const char *)&packet, 12, 108); +#endif +} + +#endif + +// MESSAGE OBS_VELOCITY UNPACKING + + +/** + * @brief Get field vel from obs_velocity message + * + * @return Velocity + */ +static inline uint16_t mavlink_msg_obs_velocity_get_vel(const mavlink_message_t* msg, float *vel) +{ + return _MAV_RETURN_float_array(msg, vel, 3, 0); +} + +/** + * @brief Decode a obs_velocity message into a struct + * + * @param msg The message to decode + * @param obs_velocity C-struct to decode the message contents into + */ +static inline void mavlink_msg_obs_velocity_decode(const mavlink_message_t* msg, mavlink_obs_velocity_t* obs_velocity) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_obs_velocity_get_vel(msg, obs_velocity->vel); +#else + memcpy(obs_velocity, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_wind.h b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_wind.h new file mode 100644 index 0000000000..6011a1caad --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_obs_wind.h @@ -0,0 +1,144 @@ +// MESSAGE OBS_WIND PACKING + +#define MAVLINK_MSG_ID_OBS_WIND 176 + +typedef struct __mavlink_obs_wind_t +{ + float wind[3]; ///< Wind +} mavlink_obs_wind_t; + +#define MAVLINK_MSG_ID_OBS_WIND_LEN 12 +#define MAVLINK_MSG_ID_176_LEN 12 + +#define MAVLINK_MSG_OBS_WIND_FIELD_WIND_LEN 3 + +#define MAVLINK_MESSAGE_INFO_OBS_WIND { \ + "OBS_WIND", \ + 1, \ + { { "wind", NULL, MAVLINK_TYPE_FLOAT, 3, 0, offsetof(mavlink_obs_wind_t, wind) }, \ + } \ +} + + +/** + * @brief Pack a obs_wind message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param wind Wind + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_wind_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const float *wind) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + + _mav_put_float_array(buf, 0, wind, 3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_obs_wind_t packet; + + mav_array_memcpy(packet.wind, wind, sizeof(float)*3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_WIND; + return mavlink_finalize_message(msg, system_id, component_id, 12, 16); +} + +/** + * @brief Pack a obs_wind message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param wind Wind + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_obs_wind_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const float *wind) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + + _mav_put_float_array(buf, 0, wind, 3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 12); +#else + mavlink_obs_wind_t packet; + + mav_array_memcpy(packet.wind, wind, sizeof(float)*3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 12); +#endif + + msg->msgid = MAVLINK_MSG_ID_OBS_WIND; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 12, 16); +} + +/** + * @brief Encode a obs_wind struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param obs_wind C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_obs_wind_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_obs_wind_t* obs_wind) +{ + return mavlink_msg_obs_wind_pack(system_id, component_id, msg, obs_wind->wind); +} + +/** + * @brief Send a obs_wind message + * @param chan MAVLink channel to send the message + * + * @param wind Wind + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_obs_wind_send(mavlink_channel_t chan, const float *wind) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[12]; + + _mav_put_float_array(buf, 0, wind, 3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_WIND, buf, 12, 16); +#else + mavlink_obs_wind_t packet; + + mav_array_memcpy(packet.wind, wind, sizeof(float)*3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_OBS_WIND, (const char *)&packet, 12, 16); +#endif +} + +#endif + +// MESSAGE OBS_WIND UNPACKING + + +/** + * @brief Get field wind from obs_wind message + * + * @return Wind + */ +static inline uint16_t mavlink_msg_obs_wind_get_wind(const mavlink_message_t* msg, float *wind) +{ + return _MAV_RETURN_float_array(msg, wind, 3, 0); +} + +/** + * @brief Decode a obs_wind message into a struct + * + * @param msg The message to decode + * @param obs_wind C-struct to decode the message contents into + */ +static inline void mavlink_msg_obs_wind_decode(const mavlink_message_t* msg, mavlink_obs_wind_t* obs_wind) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_obs_wind_get_wind(msg, obs_wind->wind); +#else + memcpy(obs_wind, _MAV_PAYLOAD(msg), 12); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_pm_elec.h b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_pm_elec.h new file mode 100644 index 0000000000..d194dae9bc --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_pm_elec.h @@ -0,0 +1,182 @@ +// MESSAGE PM_ELEC PACKING + +#define MAVLINK_MSG_ID_PM_ELEC 188 + +typedef struct __mavlink_pm_elec_t +{ + float PwCons; ///< current power consumption + float BatStat; ///< battery status + float PwGen[3]; ///< Power generation from each module +} mavlink_pm_elec_t; + +#define MAVLINK_MSG_ID_PM_ELEC_LEN 20 +#define MAVLINK_MSG_ID_188_LEN 20 + +#define MAVLINK_MSG_PM_ELEC_FIELD_PWGEN_LEN 3 + +#define MAVLINK_MESSAGE_INFO_PM_ELEC { \ + "PM_ELEC", \ + 3, \ + { { "PwCons", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_pm_elec_t, PwCons) }, \ + { "BatStat", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_pm_elec_t, BatStat) }, \ + { "PwGen", NULL, MAVLINK_TYPE_FLOAT, 3, 8, offsetof(mavlink_pm_elec_t, PwGen) }, \ + } \ +} + + +/** + * @brief Pack a pm_elec message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param PwCons current power consumption + * @param BatStat battery status + * @param PwGen Power generation from each module + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_pm_elec_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float PwCons, float BatStat, const float *PwGen) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_float(buf, 0, PwCons); + _mav_put_float(buf, 4, BatStat); + _mav_put_float_array(buf, 8, PwGen, 3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_pm_elec_t packet; + packet.PwCons = PwCons; + packet.BatStat = BatStat; + mav_array_memcpy(packet.PwGen, PwGen, sizeof(float)*3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_PM_ELEC; + return mavlink_finalize_message(msg, system_id, component_id, 20, 170); +} + +/** + * @brief Pack a pm_elec message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param PwCons current power consumption + * @param BatStat battery status + * @param PwGen Power generation from each module + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_pm_elec_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float PwCons,float BatStat,const float *PwGen) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_float(buf, 0, PwCons); + _mav_put_float(buf, 4, BatStat); + _mav_put_float_array(buf, 8, PwGen, 3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 20); +#else + mavlink_pm_elec_t packet; + packet.PwCons = PwCons; + packet.BatStat = BatStat; + mav_array_memcpy(packet.PwGen, PwGen, sizeof(float)*3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 20); +#endif + + msg->msgid = MAVLINK_MSG_ID_PM_ELEC; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 20, 170); +} + +/** + * @brief Encode a pm_elec struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param pm_elec C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_pm_elec_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_pm_elec_t* pm_elec) +{ + return mavlink_msg_pm_elec_pack(system_id, component_id, msg, pm_elec->PwCons, pm_elec->BatStat, pm_elec->PwGen); +} + +/** + * @brief Send a pm_elec message + * @param chan MAVLink channel to send the message + * + * @param PwCons current power consumption + * @param BatStat battery status + * @param PwGen Power generation from each module + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_pm_elec_send(mavlink_channel_t chan, float PwCons, float BatStat, const float *PwGen) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[20]; + _mav_put_float(buf, 0, PwCons); + _mav_put_float(buf, 4, BatStat); + _mav_put_float_array(buf, 8, PwGen, 3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PM_ELEC, buf, 20, 170); +#else + mavlink_pm_elec_t packet; + packet.PwCons = PwCons; + packet.BatStat = BatStat; + mav_array_memcpy(packet.PwGen, PwGen, sizeof(float)*3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_PM_ELEC, (const char *)&packet, 20, 170); +#endif +} + +#endif + +// MESSAGE PM_ELEC UNPACKING + + +/** + * @brief Get field PwCons from pm_elec message + * + * @return current power consumption + */ +static inline float mavlink_msg_pm_elec_get_PwCons(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field BatStat from pm_elec message + * + * @return battery status + */ +static inline float mavlink_msg_pm_elec_get_BatStat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field PwGen from pm_elec message + * + * @return Power generation from each module + */ +static inline uint16_t mavlink_msg_pm_elec_get_PwGen(const mavlink_message_t* msg, float *PwGen) +{ + return _MAV_RETURN_float_array(msg, PwGen, 3, 8); +} + +/** + * @brief Decode a pm_elec message into a struct + * + * @param msg The message to decode + * @param pm_elec C-struct to decode the message contents into + */ +static inline void mavlink_msg_pm_elec_decode(const mavlink_message_t* msg, mavlink_pm_elec_t* pm_elec) +{ +#if MAVLINK_NEED_BYTE_SWAP + pm_elec->PwCons = mavlink_msg_pm_elec_get_PwCons(msg); + pm_elec->BatStat = mavlink_msg_pm_elec_get_BatStat(msg); + mavlink_msg_pm_elec_get_PwGen(msg, pm_elec->PwGen); +#else + memcpy(pm_elec, _MAV_PAYLOAD(msg), 20); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_sys_stat.h b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_sys_stat.h new file mode 100644 index 0000000000..597fdf911f --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/mavlink_msg_sys_stat.h @@ -0,0 +1,210 @@ +// MESSAGE SYS_Stat PACKING + +#define MAVLINK_MSG_ID_SYS_Stat 190 + +typedef struct __mavlink_sys_stat_t +{ + uint8_t gps; ///< gps status + uint8_t act; ///< actuator status + uint8_t mod; ///< module status + uint8_t commRssi; ///< module status +} mavlink_sys_stat_t; + +#define MAVLINK_MSG_ID_SYS_Stat_LEN 4 +#define MAVLINK_MSG_ID_190_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_SYS_Stat { \ + "SYS_Stat", \ + 4, \ + { { "gps", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_sys_stat_t, gps) }, \ + { "act", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_sys_stat_t, act) }, \ + { "mod", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_sys_stat_t, mod) }, \ + { "commRssi", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_sys_stat_t, commRssi) }, \ + } \ +} + + +/** + * @brief Pack a sys_stat message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param gps gps status + * @param act actuator status + * @param mod module status + * @param commRssi module status + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sys_stat_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t gps, uint8_t act, uint8_t mod, uint8_t commRssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, gps); + _mav_put_uint8_t(buf, 1, act); + _mav_put_uint8_t(buf, 2, mod); + _mav_put_uint8_t(buf, 3, commRssi); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_sys_stat_t packet; + packet.gps = gps; + packet.act = act; + packet.mod = mod; + packet.commRssi = commRssi; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_SYS_Stat; + return mavlink_finalize_message(msg, system_id, component_id, 4, 157); +} + +/** + * @brief Pack a sys_stat message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param gps gps status + * @param act actuator status + * @param mod module status + * @param commRssi module status + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sys_stat_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t gps,uint8_t act,uint8_t mod,uint8_t commRssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, gps); + _mav_put_uint8_t(buf, 1, act); + _mav_put_uint8_t(buf, 2, mod); + _mav_put_uint8_t(buf, 3, commRssi); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_sys_stat_t packet; + packet.gps = gps; + packet.act = act; + packet.mod = mod; + packet.commRssi = commRssi; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_SYS_Stat; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4, 157); +} + +/** + * @brief Encode a sys_stat struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param sys_stat C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_sys_stat_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_sys_stat_t* sys_stat) +{ + return mavlink_msg_sys_stat_pack(system_id, component_id, msg, sys_stat->gps, sys_stat->act, sys_stat->mod, sys_stat->commRssi); +} + +/** + * @brief Send a sys_stat message + * @param chan MAVLink channel to send the message + * + * @param gps gps status + * @param act actuator status + * @param mod module status + * @param commRssi module status + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_sys_stat_send(mavlink_channel_t chan, uint8_t gps, uint8_t act, uint8_t mod, uint8_t commRssi) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint8_t(buf, 0, gps); + _mav_put_uint8_t(buf, 1, act); + _mav_put_uint8_t(buf, 2, mod); + _mav_put_uint8_t(buf, 3, commRssi); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SYS_Stat, buf, 4, 157); +#else + mavlink_sys_stat_t packet; + packet.gps = gps; + packet.act = act; + packet.mod = mod; + packet.commRssi = commRssi; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SYS_Stat, (const char *)&packet, 4, 157); +#endif +} + +#endif + +// MESSAGE SYS_Stat UNPACKING + + +/** + * @brief Get field gps from sys_stat message + * + * @return gps status + */ +static inline uint8_t mavlink_msg_sys_stat_get_gps(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field act from sys_stat message + * + * @return actuator status + */ +static inline uint8_t mavlink_msg_sys_stat_get_act(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field mod from sys_stat message + * + * @return module status + */ +static inline uint8_t mavlink_msg_sys_stat_get_mod(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field commRssi from sys_stat message + * + * @return module status + */ +static inline uint8_t mavlink_msg_sys_stat_get_commRssi(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Decode a sys_stat message into a struct + * + * @param msg The message to decode + * @param sys_stat C-struct to decode the message contents into + */ +static inline void mavlink_msg_sys_stat_decode(const mavlink_message_t* msg, mavlink_sys_stat_t* sys_stat) +{ +#if MAVLINK_NEED_BYTE_SWAP + sys_stat->gps = mavlink_msg_sys_stat_get_gps(msg); + sys_stat->act = mavlink_msg_sys_stat_get_act(msg); + sys_stat->mod = mavlink_msg_sys_stat_get_mod(msg); + sys_stat->commRssi = mavlink_msg_sys_stat_get_commRssi(msg); +#else + memcpy(sys_stat, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/sensesoar/sensesoar.h b/mavlink/include/mavlink/v1.0/sensesoar/sensesoar.h new file mode 100644 index 0000000000..5a6022d59f --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/sensesoar.h @@ -0,0 +1,77 @@ +/** @file + * @brief MAVLink comm protocol generated from sensesoar.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef SENSESOAR_H +#define SENSESOAR_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {9, 31, 12, 0, 14, 28, 3, 32, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 20, 2, 25, 23, 30, 101, 22, 26, 16, 14, 28, 32, 28, 28, 22, 22, 21, 6, 6, 37, 4, 4, 2, 2, 4, 2, 2, 3, 13, 12, 19, 17, 15, 15, 27, 25, 18, 18, 20, 20, 9, 54, 26, 0, 36, 0, 6, 4, 0, 21, 18, 0, 0, 0, 20, 0, 33, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 56, 42, 33, 0, 0, 0, 0, 0, 0, 0, 26, 32, 32, 20, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 32, 0, 12, 0, 12, 0, 24, 0, 4, 4, 12, 0, 12, 0, 20, 0, 4, 0, 5, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 30, 18, 18, 51, 9, 0} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {50, 124, 137, 0, 237, 217, 104, 119, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 214, 159, 220, 168, 24, 23, 170, 144, 67, 115, 39, 246, 185, 104, 237, 244, 222, 212, 9, 254, 230, 28, 28, 132, 221, 232, 11, 153, 41, 39, 214, 223, 141, 33, 15, 3, 100, 24, 239, 238, 30, 200, 183, 0, 130, 0, 148, 21, 0, 52, 124, 0, 0, 0, 20, 0, 152, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 183, 63, 54, 0, 0, 0, 0, 0, 0, 0, 175, 102, 158, 208, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 108, 0, 146, 0, 16, 0, 32, 0, 159, 0, 24, 248, 79, 0, 5, 0, 170, 0, 157, 0, 209, 0, 243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 49, 170, 44, 83, 46, 0} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, MAVLINK_MESSAGE_INFO_SYS_STATUS, MAVLINK_MESSAGE_INFO_SYSTEM_TIME, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PING, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK, MAVLINK_MESSAGE_INFO_AUTH_KEY, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_SET_MODE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST, MAVLINK_MESSAGE_INFO_PARAM_VALUE, MAVLINK_MESSAGE_INFO_PARAM_SET, MAVLINK_MESSAGE_INFO_GPS_RAW_INT, MAVLINK_MESSAGE_INFO_GPS_STATUS, MAVLINK_MESSAGE_INFO_SCALED_IMU, MAVLINK_MESSAGE_INFO_RAW_IMU, MAVLINK_MESSAGE_INFO_RAW_PRESSURE, MAVLINK_MESSAGE_INFO_SCALED_PRESSURE, MAVLINK_MESSAGE_INFO_ATTITUDE, MAVLINK_MESSAGE_INFO_ATTITUDE_QUATERNION, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_NED, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT, MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED, MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW, MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW, MAVLINK_MESSAGE_INFO_MISSION_REQUEST_PARTIAL_LIST, MAVLINK_MESSAGE_INFO_MISSION_WRITE_PARTIAL_LIST, MAVLINK_MESSAGE_INFO_MISSION_ITEM, MAVLINK_MESSAGE_INFO_MISSION_REQUEST, MAVLINK_MESSAGE_INFO_MISSION_SET_CURRENT, MAVLINK_MESSAGE_INFO_MISSION_CURRENT, MAVLINK_MESSAGE_INFO_MISSION_REQUEST_LIST, MAVLINK_MESSAGE_INFO_MISSION_COUNT, MAVLINK_MESSAGE_INFO_MISSION_CLEAR_ALL, MAVLINK_MESSAGE_INFO_MISSION_ITEM_REACHED, MAVLINK_MESSAGE_INFO_MISSION_ACK, MAVLINK_MESSAGE_INFO_SET_GPS_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_GPS_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_SET_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_SETPOINT_INT, MAVLINK_MESSAGE_INFO_SET_GLOBAL_POSITION_SETPOINT_INT, MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_SET_QUAD_MOTORS_SETPOINT, MAVLINK_MESSAGE_INFO_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_STATE_CORRECTION, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM, MAVLINK_MESSAGE_INFO_DATA_STREAM, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_MANUAL_CONTROL, MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_VFR_HUD, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_COMMAND_LONG, MAVLINK_MESSAGE_INFO_COMMAND_ACK, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET, MAVLINK_MESSAGE_INFO_HIL_STATE, MAVLINK_MESSAGE_INFO_HIL_CONTROLS, MAVLINK_MESSAGE_INFO_HIL_RC_INPUTS_RAW, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OPTICAL_FLOW, MAVLINK_MESSAGE_INFO_GLOBAL_VISION_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VISION_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VISION_SPEED_ESTIMATE, MAVLINK_MESSAGE_INFO_VICON_POSITION_ESTIMATE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OBS_POSITION, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OBS_VELOCITY, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OBS_ATTITUDE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OBS_WIND, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OBS_AIR_VELOCITY, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OBS_BIAS, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OBS_QFF, MAVLINK_MESSAGE_INFO_OBS_AIR_TEMP, MAVLINK_MESSAGE_INFO_FILT_ROT_VEL, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_LLC_OUT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PM_ELEC, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_SYS_Stat, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_CMD_AIRSPEED_CHNG, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_CMD_AIRSPEED_ACK, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_MEMORY_VECT, MAVLINK_MESSAGE_INFO_DEBUG_VECT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT, MAVLINK_MESSAGE_INFO_STATUSTEXT, MAVLINK_MESSAGE_INFO_DEBUG, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_SENSESOAR + +#include "../common/common.h" + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +// ENUM DEFINITIONS + + +/** @brief Different flight modes */ +#ifndef HAVE_ENUM_SENSESOAR_MODE +#define HAVE_ENUM_SENSESOAR_MODE +enum SENSESOAR_MODE +{ + SENSESOAR_MODE_GLIDING=1, /* | */ + SENSESOAR_MODE_AUTONOMOUS=2, /* | */ + SENSESOAR_MODE_MANUAL=3, /* | */ + SENSESOAR_MODE_ENUM_END=4, /* | */ +}; +#endif + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_obs_position.h" +#include "./mavlink_msg_obs_velocity.h" +#include "./mavlink_msg_obs_attitude.h" +#include "./mavlink_msg_obs_wind.h" +#include "./mavlink_msg_obs_air_velocity.h" +#include "./mavlink_msg_obs_bias.h" +#include "./mavlink_msg_obs_qff.h" +#include "./mavlink_msg_obs_air_temp.h" +#include "./mavlink_msg_filt_rot_vel.h" +#include "./mavlink_msg_llc_out.h" +#include "./mavlink_msg_pm_elec.h" +#include "./mavlink_msg_sys_stat.h" +#include "./mavlink_msg_cmd_airspeed_chng.h" +#include "./mavlink_msg_cmd_airspeed_ack.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // SENSESOAR_H diff --git a/mavlink/include/mavlink/v1.0/sensesoar/testsuite.h b/mavlink/include/mavlink/v1.0/sensesoar/testsuite.h new file mode 100644 index 0000000000..4c8f73c5b7 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/sensesoar/testsuite.h @@ -0,0 +1,676 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from sensesoar.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef SENSESOAR_TESTSUITE_H +#define SENSESOAR_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL +static void mavlink_test_common(uint8_t, uint8_t, mavlink_message_t *last_msg); +static void mavlink_test_sensesoar(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_test_common(system_id, component_id, last_msg); + mavlink_test_sensesoar(system_id, component_id, last_msg); +} +#endif + +#include "../common/testsuite.h" + + +static void mavlink_test_obs_position(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_obs_position_t packet_in = { + 963497464, + 963497672, + 963497880, + }; + mavlink_obs_position_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.lon = packet_in.lon; + packet1.lat = packet_in.lat; + packet1.alt = packet_in.alt; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_obs_position_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_obs_position_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_obs_position_pack(system_id, component_id, &msg , packet1.lon , packet1.lat , packet1.alt ); + mavlink_msg_obs_position_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_obs_position_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.lon , packet1.lat , packet1.alt ); + mavlink_msg_obs_position_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; imsgid = MAVLINK_MSG_ID_AIR_DATA; + return mavlink_finalize_message(msg, system_id, component_id, 10, 232); +} + +/** + * @brief Pack a air_data message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param dynamicPressure Dynamic pressure (Pa) + * @param staticPressure Static pressure (Pa) + * @param temperature Board temperature + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_air_data_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float dynamicPressure,float staticPressure,uint16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[10]; + _mav_put_float(buf, 0, dynamicPressure); + _mav_put_float(buf, 4, staticPressure); + _mav_put_uint16_t(buf, 8, temperature); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 10); +#else + mavlink_air_data_t packet; + packet.dynamicPressure = dynamicPressure; + packet.staticPressure = staticPressure; + packet.temperature = temperature; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 10); +#endif + + msg->msgid = MAVLINK_MSG_ID_AIR_DATA; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 10, 232); +} + +/** + * @brief Encode a air_data struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param air_data C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_air_data_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_air_data_t* air_data) +{ + return mavlink_msg_air_data_pack(system_id, component_id, msg, air_data->dynamicPressure, air_data->staticPressure, air_data->temperature); +} + +/** + * @brief Send a air_data message + * @param chan MAVLink channel to send the message + * + * @param dynamicPressure Dynamic pressure (Pa) + * @param staticPressure Static pressure (Pa) + * @param temperature Board temperature + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_air_data_send(mavlink_channel_t chan, float dynamicPressure, float staticPressure, uint16_t temperature) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[10]; + _mav_put_float(buf, 0, dynamicPressure); + _mav_put_float(buf, 4, staticPressure); + _mav_put_uint16_t(buf, 8, temperature); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AIR_DATA, buf, 10, 232); +#else + mavlink_air_data_t packet; + packet.dynamicPressure = dynamicPressure; + packet.staticPressure = staticPressure; + packet.temperature = temperature; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_AIR_DATA, (const char *)&packet, 10, 232); +#endif +} + +#endif + +// MESSAGE AIR_DATA UNPACKING + + +/** + * @brief Get field dynamicPressure from air_data message + * + * @return Dynamic pressure (Pa) + */ +static inline float mavlink_msg_air_data_get_dynamicPressure(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field staticPressure from air_data message + * + * @return Static pressure (Pa) + */ +static inline float mavlink_msg_air_data_get_staticPressure(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field temperature from air_data message + * + * @return Board temperature + */ +static inline uint16_t mavlink_msg_air_data_get_temperature(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 8); +} + +/** + * @brief Decode a air_data message into a struct + * + * @param msg The message to decode + * @param air_data C-struct to decode the message contents into + */ +static inline void mavlink_msg_air_data_decode(const mavlink_message_t* msg, mavlink_air_data_t* air_data) +{ +#if MAVLINK_NEED_BYTE_SWAP + air_data->dynamicPressure = mavlink_msg_air_data_get_dynamicPressure(msg); + air_data->staticPressure = mavlink_msg_air_data_get_staticPressure(msg); + air_data->temperature = mavlink_msg_air_data_get_temperature(msg); +#else + memcpy(air_data, _MAV_PAYLOAD(msg), 10); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_cpu_load.h b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_cpu_load.h new file mode 100644 index 0000000000..5f86c7091e --- /dev/null +++ b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_cpu_load.h @@ -0,0 +1,188 @@ +// MESSAGE CPU_LOAD PACKING + +#define MAVLINK_MSG_ID_CPU_LOAD 170 + +typedef struct __mavlink_cpu_load_t +{ + uint16_t batVolt; ///< Battery Voltage in millivolts + uint8_t sensLoad; ///< Sensor DSC Load + uint8_t ctrlLoad; ///< Control DSC Load +} mavlink_cpu_load_t; + +#define MAVLINK_MSG_ID_CPU_LOAD_LEN 4 +#define MAVLINK_MSG_ID_170_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_CPU_LOAD { \ + "CPU_LOAD", \ + 3, \ + { { "batVolt", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_cpu_load_t, batVolt) }, \ + { "sensLoad", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_cpu_load_t, sensLoad) }, \ + { "ctrlLoad", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_cpu_load_t, ctrlLoad) }, \ + } \ +} + + +/** + * @brief Pack a cpu_load message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param sensLoad Sensor DSC Load + * @param ctrlLoad Control DSC Load + * @param batVolt Battery Voltage in millivolts + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_cpu_load_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t sensLoad, uint8_t ctrlLoad, uint16_t batVolt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, batVolt); + _mav_put_uint8_t(buf, 2, sensLoad); + _mav_put_uint8_t(buf, 3, ctrlLoad); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_cpu_load_t packet; + packet.batVolt = batVolt; + packet.sensLoad = sensLoad; + packet.ctrlLoad = ctrlLoad; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_CPU_LOAD; + return mavlink_finalize_message(msg, system_id, component_id, 4, 75); +} + +/** + * @brief Pack a cpu_load message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param sensLoad Sensor DSC Load + * @param ctrlLoad Control DSC Load + * @param batVolt Battery Voltage in millivolts + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_cpu_load_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t sensLoad,uint8_t ctrlLoad,uint16_t batVolt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, batVolt); + _mav_put_uint8_t(buf, 2, sensLoad); + _mav_put_uint8_t(buf, 3, ctrlLoad); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_cpu_load_t packet; + packet.batVolt = batVolt; + packet.sensLoad = sensLoad; + packet.ctrlLoad = ctrlLoad; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_CPU_LOAD; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4, 75); +} + +/** + * @brief Encode a cpu_load struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param cpu_load C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_cpu_load_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_cpu_load_t* cpu_load) +{ + return mavlink_msg_cpu_load_pack(system_id, component_id, msg, cpu_load->sensLoad, cpu_load->ctrlLoad, cpu_load->batVolt); +} + +/** + * @brief Send a cpu_load message + * @param chan MAVLink channel to send the message + * + * @param sensLoad Sensor DSC Load + * @param ctrlLoad Control DSC Load + * @param batVolt Battery Voltage in millivolts + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_cpu_load_send(mavlink_channel_t chan, uint8_t sensLoad, uint8_t ctrlLoad, uint16_t batVolt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, batVolt); + _mav_put_uint8_t(buf, 2, sensLoad); + _mav_put_uint8_t(buf, 3, ctrlLoad); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CPU_LOAD, buf, 4, 75); +#else + mavlink_cpu_load_t packet; + packet.batVolt = batVolt; + packet.sensLoad = sensLoad; + packet.ctrlLoad = ctrlLoad; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CPU_LOAD, (const char *)&packet, 4, 75); +#endif +} + +#endif + +// MESSAGE CPU_LOAD UNPACKING + + +/** + * @brief Get field sensLoad from cpu_load message + * + * @return Sensor DSC Load + */ +static inline uint8_t mavlink_msg_cpu_load_get_sensLoad(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field ctrlLoad from cpu_load message + * + * @return Control DSC Load + */ +static inline uint8_t mavlink_msg_cpu_load_get_ctrlLoad(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field batVolt from cpu_load message + * + * @return Battery Voltage in millivolts + */ +static inline uint16_t mavlink_msg_cpu_load_get_batVolt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Decode a cpu_load message into a struct + * + * @param msg The message to decode + * @param cpu_load C-struct to decode the message contents into + */ +static inline void mavlink_msg_cpu_load_decode(const mavlink_message_t* msg, mavlink_cpu_load_t* cpu_load) +{ +#if MAVLINK_NEED_BYTE_SWAP + cpu_load->batVolt = mavlink_msg_cpu_load_get_batVolt(msg); + cpu_load->sensLoad = mavlink_msg_cpu_load_get_sensLoad(msg); + cpu_load->ctrlLoad = mavlink_msg_cpu_load_get_ctrlLoad(msg); +#else + memcpy(cpu_load, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_ctrl_srfc_pt.h b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_ctrl_srfc_pt.h new file mode 100644 index 0000000000..e506ed18fd --- /dev/null +++ b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_ctrl_srfc_pt.h @@ -0,0 +1,166 @@ +// MESSAGE CTRL_SRFC_PT PACKING + +#define MAVLINK_MSG_ID_CTRL_SRFC_PT 181 + +typedef struct __mavlink_ctrl_srfc_pt_t +{ + uint16_t bitfieldPt; ///< Bitfield containing the PT configuration + uint8_t target; ///< The system setting the commands +} mavlink_ctrl_srfc_pt_t; + +#define MAVLINK_MSG_ID_CTRL_SRFC_PT_LEN 3 +#define MAVLINK_MSG_ID_181_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_CTRL_SRFC_PT { \ + "CTRL_SRFC_PT", \ + 2, \ + { { "bitfieldPt", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_ctrl_srfc_pt_t, bitfieldPt) }, \ + { "target", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_ctrl_srfc_pt_t, target) }, \ + } \ +} + + +/** + * @brief Pack a ctrl_srfc_pt message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target The system setting the commands + * @param bitfieldPt Bitfield containing the PT configuration + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ctrl_srfc_pt_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target, uint16_t bitfieldPt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, bitfieldPt); + _mav_put_uint8_t(buf, 2, target); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_ctrl_srfc_pt_t packet; + packet.bitfieldPt = bitfieldPt; + packet.target = target; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_CTRL_SRFC_PT; + return mavlink_finalize_message(msg, system_id, component_id, 3, 104); +} + +/** + * @brief Pack a ctrl_srfc_pt message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system setting the commands + * @param bitfieldPt Bitfield containing the PT configuration + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ctrl_srfc_pt_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,uint16_t bitfieldPt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, bitfieldPt); + _mav_put_uint8_t(buf, 2, target); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_ctrl_srfc_pt_t packet; + packet.bitfieldPt = bitfieldPt; + packet.target = target; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_CTRL_SRFC_PT; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3, 104); +} + +/** + * @brief Encode a ctrl_srfc_pt struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param ctrl_srfc_pt C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_ctrl_srfc_pt_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_ctrl_srfc_pt_t* ctrl_srfc_pt) +{ + return mavlink_msg_ctrl_srfc_pt_pack(system_id, component_id, msg, ctrl_srfc_pt->target, ctrl_srfc_pt->bitfieldPt); +} + +/** + * @brief Send a ctrl_srfc_pt message + * @param chan MAVLink channel to send the message + * + * @param target The system setting the commands + * @param bitfieldPt Bitfield containing the PT configuration + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_ctrl_srfc_pt_send(mavlink_channel_t chan, uint8_t target, uint16_t bitfieldPt) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, bitfieldPt); + _mav_put_uint8_t(buf, 2, target); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CTRL_SRFC_PT, buf, 3, 104); +#else + mavlink_ctrl_srfc_pt_t packet; + packet.bitfieldPt = bitfieldPt; + packet.target = target; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_CTRL_SRFC_PT, (const char *)&packet, 3, 104); +#endif +} + +#endif + +// MESSAGE CTRL_SRFC_PT UNPACKING + + +/** + * @brief Get field target from ctrl_srfc_pt message + * + * @return The system setting the commands + */ +static inline uint8_t mavlink_msg_ctrl_srfc_pt_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field bitfieldPt from ctrl_srfc_pt message + * + * @return Bitfield containing the PT configuration + */ +static inline uint16_t mavlink_msg_ctrl_srfc_pt_get_bitfieldPt(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Decode a ctrl_srfc_pt message into a struct + * + * @param msg The message to decode + * @param ctrl_srfc_pt C-struct to decode the message contents into + */ +static inline void mavlink_msg_ctrl_srfc_pt_decode(const mavlink_message_t* msg, mavlink_ctrl_srfc_pt_t* ctrl_srfc_pt) +{ +#if MAVLINK_NEED_BYTE_SWAP + ctrl_srfc_pt->bitfieldPt = mavlink_msg_ctrl_srfc_pt_get_bitfieldPt(msg); + ctrl_srfc_pt->target = mavlink_msg_ctrl_srfc_pt_get_target(msg); +#else + memcpy(ctrl_srfc_pt, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_data_log.h b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_data_log.h new file mode 100644 index 0000000000..49e340704d --- /dev/null +++ b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_data_log.h @@ -0,0 +1,254 @@ +// MESSAGE DATA_LOG PACKING + +#define MAVLINK_MSG_ID_DATA_LOG 177 + +typedef struct __mavlink_data_log_t +{ + float fl_1; ///< Log value 1 + float fl_2; ///< Log value 2 + float fl_3; ///< Log value 3 + float fl_4; ///< Log value 4 + float fl_5; ///< Log value 5 + float fl_6; ///< Log value 6 +} mavlink_data_log_t; + +#define MAVLINK_MSG_ID_DATA_LOG_LEN 24 +#define MAVLINK_MSG_ID_177_LEN 24 + + + +#define MAVLINK_MESSAGE_INFO_DATA_LOG { \ + "DATA_LOG", \ + 6, \ + { { "fl_1", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_data_log_t, fl_1) }, \ + { "fl_2", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_data_log_t, fl_2) }, \ + { "fl_3", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_data_log_t, fl_3) }, \ + { "fl_4", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_data_log_t, fl_4) }, \ + { "fl_5", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_data_log_t, fl_5) }, \ + { "fl_6", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_data_log_t, fl_6) }, \ + } \ +} + + +/** + * @brief Pack a data_log message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param fl_1 Log value 1 + * @param fl_2 Log value 2 + * @param fl_3 Log value 3 + * @param fl_4 Log value 4 + * @param fl_5 Log value 5 + * @param fl_6 Log value 6 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_data_log_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float fl_1, float fl_2, float fl_3, float fl_4, float fl_5, float fl_6) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_float(buf, 0, fl_1); + _mav_put_float(buf, 4, fl_2); + _mav_put_float(buf, 8, fl_3); + _mav_put_float(buf, 12, fl_4); + _mav_put_float(buf, 16, fl_5); + _mav_put_float(buf, 20, fl_6); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_data_log_t packet; + packet.fl_1 = fl_1; + packet.fl_2 = fl_2; + packet.fl_3 = fl_3; + packet.fl_4 = fl_4; + packet.fl_5 = fl_5; + packet.fl_6 = fl_6; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_DATA_LOG; + return mavlink_finalize_message(msg, system_id, component_id, 24, 167); +} + +/** + * @brief Pack a data_log message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param fl_1 Log value 1 + * @param fl_2 Log value 2 + * @param fl_3 Log value 3 + * @param fl_4 Log value 4 + * @param fl_5 Log value 5 + * @param fl_6 Log value 6 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_data_log_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float fl_1,float fl_2,float fl_3,float fl_4,float fl_5,float fl_6) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_float(buf, 0, fl_1); + _mav_put_float(buf, 4, fl_2); + _mav_put_float(buf, 8, fl_3); + _mav_put_float(buf, 12, fl_4); + _mav_put_float(buf, 16, fl_5); + _mav_put_float(buf, 20, fl_6); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_data_log_t packet; + packet.fl_1 = fl_1; + packet.fl_2 = fl_2; + packet.fl_3 = fl_3; + packet.fl_4 = fl_4; + packet.fl_5 = fl_5; + packet.fl_6 = fl_6; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_DATA_LOG; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 24, 167); +} + +/** + * @brief Encode a data_log struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param data_log C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_data_log_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_data_log_t* data_log) +{ + return mavlink_msg_data_log_pack(system_id, component_id, msg, data_log->fl_1, data_log->fl_2, data_log->fl_3, data_log->fl_4, data_log->fl_5, data_log->fl_6); +} + +/** + * @brief Send a data_log message + * @param chan MAVLink channel to send the message + * + * @param fl_1 Log value 1 + * @param fl_2 Log value 2 + * @param fl_3 Log value 3 + * @param fl_4 Log value 4 + * @param fl_5 Log value 5 + * @param fl_6 Log value 6 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_data_log_send(mavlink_channel_t chan, float fl_1, float fl_2, float fl_3, float fl_4, float fl_5, float fl_6) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_float(buf, 0, fl_1); + _mav_put_float(buf, 4, fl_2); + _mav_put_float(buf, 8, fl_3); + _mav_put_float(buf, 12, fl_4); + _mav_put_float(buf, 16, fl_5); + _mav_put_float(buf, 20, fl_6); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DATA_LOG, buf, 24, 167); +#else + mavlink_data_log_t packet; + packet.fl_1 = fl_1; + packet.fl_2 = fl_2; + packet.fl_3 = fl_3; + packet.fl_4 = fl_4; + packet.fl_5 = fl_5; + packet.fl_6 = fl_6; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DATA_LOG, (const char *)&packet, 24, 167); +#endif +} + +#endif + +// MESSAGE DATA_LOG UNPACKING + + +/** + * @brief Get field fl_1 from data_log message + * + * @return Log value 1 + */ +static inline float mavlink_msg_data_log_get_fl_1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field fl_2 from data_log message + * + * @return Log value 2 + */ +static inline float mavlink_msg_data_log_get_fl_2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field fl_3 from data_log message + * + * @return Log value 3 + */ +static inline float mavlink_msg_data_log_get_fl_3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field fl_4 from data_log message + * + * @return Log value 4 + */ +static inline float mavlink_msg_data_log_get_fl_4(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field fl_5 from data_log message + * + * @return Log value 5 + */ +static inline float mavlink_msg_data_log_get_fl_5(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field fl_6 from data_log message + * + * @return Log value 6 + */ +static inline float mavlink_msg_data_log_get_fl_6(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Decode a data_log message into a struct + * + * @param msg The message to decode + * @param data_log C-struct to decode the message contents into + */ +static inline void mavlink_msg_data_log_decode(const mavlink_message_t* msg, mavlink_data_log_t* data_log) +{ +#if MAVLINK_NEED_BYTE_SWAP + data_log->fl_1 = mavlink_msg_data_log_get_fl_1(msg); + data_log->fl_2 = mavlink_msg_data_log_get_fl_2(msg); + data_log->fl_3 = mavlink_msg_data_log_get_fl_3(msg); + data_log->fl_4 = mavlink_msg_data_log_get_fl_4(msg); + data_log->fl_5 = mavlink_msg_data_log_get_fl_5(msg); + data_log->fl_6 = mavlink_msg_data_log_get_fl_6(msg); +#else + memcpy(data_log, _MAV_PAYLOAD(msg), 24); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_diagnostic.h b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_diagnostic.h new file mode 100644 index 0000000000..ef77e5f085 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_diagnostic.h @@ -0,0 +1,254 @@ +// MESSAGE DIAGNOSTIC PACKING + +#define MAVLINK_MSG_ID_DIAGNOSTIC 173 + +typedef struct __mavlink_diagnostic_t +{ + float diagFl1; ///< Diagnostic float 1 + float diagFl2; ///< Diagnostic float 2 + float diagFl3; ///< Diagnostic float 3 + int16_t diagSh1; ///< Diagnostic short 1 + int16_t diagSh2; ///< Diagnostic short 2 + int16_t diagSh3; ///< Diagnostic short 3 +} mavlink_diagnostic_t; + +#define MAVLINK_MSG_ID_DIAGNOSTIC_LEN 18 +#define MAVLINK_MSG_ID_173_LEN 18 + + + +#define MAVLINK_MESSAGE_INFO_DIAGNOSTIC { \ + "DIAGNOSTIC", \ + 6, \ + { { "diagFl1", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_diagnostic_t, diagFl1) }, \ + { "diagFl2", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_diagnostic_t, diagFl2) }, \ + { "diagFl3", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_diagnostic_t, diagFl3) }, \ + { "diagSh1", NULL, MAVLINK_TYPE_INT16_T, 0, 12, offsetof(mavlink_diagnostic_t, diagSh1) }, \ + { "diagSh2", NULL, MAVLINK_TYPE_INT16_T, 0, 14, offsetof(mavlink_diagnostic_t, diagSh2) }, \ + { "diagSh3", NULL, MAVLINK_TYPE_INT16_T, 0, 16, offsetof(mavlink_diagnostic_t, diagSh3) }, \ + } \ +} + + +/** + * @brief Pack a diagnostic message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param diagFl1 Diagnostic float 1 + * @param diagFl2 Diagnostic float 2 + * @param diagFl3 Diagnostic float 3 + * @param diagSh1 Diagnostic short 1 + * @param diagSh2 Diagnostic short 2 + * @param diagSh3 Diagnostic short 3 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_diagnostic_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float diagFl1, float diagFl2, float diagFl3, int16_t diagSh1, int16_t diagSh2, int16_t diagSh3) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, diagFl1); + _mav_put_float(buf, 4, diagFl2); + _mav_put_float(buf, 8, diagFl3); + _mav_put_int16_t(buf, 12, diagSh1); + _mav_put_int16_t(buf, 14, diagSh2); + _mav_put_int16_t(buf, 16, diagSh3); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_diagnostic_t packet; + packet.diagFl1 = diagFl1; + packet.diagFl2 = diagFl2; + packet.diagFl3 = diagFl3; + packet.diagSh1 = diagSh1; + packet.diagSh2 = diagSh2; + packet.diagSh3 = diagSh3; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_DIAGNOSTIC; + return mavlink_finalize_message(msg, system_id, component_id, 18, 2); +} + +/** + * @brief Pack a diagnostic message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param diagFl1 Diagnostic float 1 + * @param diagFl2 Diagnostic float 2 + * @param diagFl3 Diagnostic float 3 + * @param diagSh1 Diagnostic short 1 + * @param diagSh2 Diagnostic short 2 + * @param diagSh3 Diagnostic short 3 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_diagnostic_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float diagFl1,float diagFl2,float diagFl3,int16_t diagSh1,int16_t diagSh2,int16_t diagSh3) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, diagFl1); + _mav_put_float(buf, 4, diagFl2); + _mav_put_float(buf, 8, diagFl3); + _mav_put_int16_t(buf, 12, diagSh1); + _mav_put_int16_t(buf, 14, diagSh2); + _mav_put_int16_t(buf, 16, diagSh3); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 18); +#else + mavlink_diagnostic_t packet; + packet.diagFl1 = diagFl1; + packet.diagFl2 = diagFl2; + packet.diagFl3 = diagFl3; + packet.diagSh1 = diagSh1; + packet.diagSh2 = diagSh2; + packet.diagSh3 = diagSh3; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 18); +#endif + + msg->msgid = MAVLINK_MSG_ID_DIAGNOSTIC; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 18, 2); +} + +/** + * @brief Encode a diagnostic struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param diagnostic C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_diagnostic_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_diagnostic_t* diagnostic) +{ + return mavlink_msg_diagnostic_pack(system_id, component_id, msg, diagnostic->diagFl1, diagnostic->diagFl2, diagnostic->diagFl3, diagnostic->diagSh1, diagnostic->diagSh2, diagnostic->diagSh3); +} + +/** + * @brief Send a diagnostic message + * @param chan MAVLink channel to send the message + * + * @param diagFl1 Diagnostic float 1 + * @param diagFl2 Diagnostic float 2 + * @param diagFl3 Diagnostic float 3 + * @param diagSh1 Diagnostic short 1 + * @param diagSh2 Diagnostic short 2 + * @param diagSh3 Diagnostic short 3 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_diagnostic_send(mavlink_channel_t chan, float diagFl1, float diagFl2, float diagFl3, int16_t diagSh1, int16_t diagSh2, int16_t diagSh3) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[18]; + _mav_put_float(buf, 0, diagFl1); + _mav_put_float(buf, 4, diagFl2); + _mav_put_float(buf, 8, diagFl3); + _mav_put_int16_t(buf, 12, diagSh1); + _mav_put_int16_t(buf, 14, diagSh2); + _mav_put_int16_t(buf, 16, diagSh3); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DIAGNOSTIC, buf, 18, 2); +#else + mavlink_diagnostic_t packet; + packet.diagFl1 = diagFl1; + packet.diagFl2 = diagFl2; + packet.diagFl3 = diagFl3; + packet.diagSh1 = diagSh1; + packet.diagSh2 = diagSh2; + packet.diagSh3 = diagSh3; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DIAGNOSTIC, (const char *)&packet, 18, 2); +#endif +} + +#endif + +// MESSAGE DIAGNOSTIC UNPACKING + + +/** + * @brief Get field diagFl1 from diagnostic message + * + * @return Diagnostic float 1 + */ +static inline float mavlink_msg_diagnostic_get_diagFl1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field diagFl2 from diagnostic message + * + * @return Diagnostic float 2 + */ +static inline float mavlink_msg_diagnostic_get_diagFl2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field diagFl3 from diagnostic message + * + * @return Diagnostic float 3 + */ +static inline float mavlink_msg_diagnostic_get_diagFl3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field diagSh1 from diagnostic message + * + * @return Diagnostic short 1 + */ +static inline int16_t mavlink_msg_diagnostic_get_diagSh1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 12); +} + +/** + * @brief Get field diagSh2 from diagnostic message + * + * @return Diagnostic short 2 + */ +static inline int16_t mavlink_msg_diagnostic_get_diagSh2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 14); +} + +/** + * @brief Get field diagSh3 from diagnostic message + * + * @return Diagnostic short 3 + */ +static inline int16_t mavlink_msg_diagnostic_get_diagSh3(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 16); +} + +/** + * @brief Decode a diagnostic message into a struct + * + * @param msg The message to decode + * @param diagnostic C-struct to decode the message contents into + */ +static inline void mavlink_msg_diagnostic_decode(const mavlink_message_t* msg, mavlink_diagnostic_t* diagnostic) +{ +#if MAVLINK_NEED_BYTE_SWAP + diagnostic->diagFl1 = mavlink_msg_diagnostic_get_diagFl1(msg); + diagnostic->diagFl2 = mavlink_msg_diagnostic_get_diagFl2(msg); + diagnostic->diagFl3 = mavlink_msg_diagnostic_get_diagFl3(msg); + diagnostic->diagSh1 = mavlink_msg_diagnostic_get_diagSh1(msg); + diagnostic->diagSh2 = mavlink_msg_diagnostic_get_diagSh2(msg); + diagnostic->diagSh3 = mavlink_msg_diagnostic_get_diagSh3(msg); +#else + memcpy(diagnostic, _MAV_PAYLOAD(msg), 18); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_gps_date_time.h b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_gps_date_time.h new file mode 100644 index 0000000000..62b33d475a --- /dev/null +++ b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_gps_date_time.h @@ -0,0 +1,276 @@ +// MESSAGE GPS_DATE_TIME PACKING + +#define MAVLINK_MSG_ID_GPS_DATE_TIME 179 + +typedef struct __mavlink_gps_date_time_t +{ + uint8_t year; ///< Year reported by Gps + uint8_t month; ///< Month reported by Gps + uint8_t day; ///< Day reported by Gps + uint8_t hour; ///< Hour reported by Gps + uint8_t min; ///< Min reported by Gps + uint8_t sec; ///< Sec reported by Gps + uint8_t visSat; ///< Visible sattelites reported by Gps +} mavlink_gps_date_time_t; + +#define MAVLINK_MSG_ID_GPS_DATE_TIME_LEN 7 +#define MAVLINK_MSG_ID_179_LEN 7 + + + +#define MAVLINK_MESSAGE_INFO_GPS_DATE_TIME { \ + "GPS_DATE_TIME", \ + 7, \ + { { "year", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_gps_date_time_t, year) }, \ + { "month", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_gps_date_time_t, month) }, \ + { "day", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_gps_date_time_t, day) }, \ + { "hour", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_gps_date_time_t, hour) }, \ + { "min", NULL, MAVLINK_TYPE_UINT8_T, 0, 4, offsetof(mavlink_gps_date_time_t, min) }, \ + { "sec", NULL, MAVLINK_TYPE_UINT8_T, 0, 5, offsetof(mavlink_gps_date_time_t, sec) }, \ + { "visSat", NULL, MAVLINK_TYPE_UINT8_T, 0, 6, offsetof(mavlink_gps_date_time_t, visSat) }, \ + } \ +} + + +/** + * @brief Pack a gps_date_time message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param year Year reported by Gps + * @param month Month reported by Gps + * @param day Day reported by Gps + * @param hour Hour reported by Gps + * @param min Min reported by Gps + * @param sec Sec reported by Gps + * @param visSat Visible sattelites reported by Gps + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_date_time_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec, uint8_t visSat) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[7]; + _mav_put_uint8_t(buf, 0, year); + _mav_put_uint8_t(buf, 1, month); + _mav_put_uint8_t(buf, 2, day); + _mav_put_uint8_t(buf, 3, hour); + _mav_put_uint8_t(buf, 4, min); + _mav_put_uint8_t(buf, 5, sec); + _mav_put_uint8_t(buf, 6, visSat); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 7); +#else + mavlink_gps_date_time_t packet; + packet.year = year; + packet.month = month; + packet.day = day; + packet.hour = hour; + packet.min = min; + packet.sec = sec; + packet.visSat = visSat; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 7); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_DATE_TIME; + return mavlink_finalize_message(msg, system_id, component_id, 7, 16); +} + +/** + * @brief Pack a gps_date_time message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param year Year reported by Gps + * @param month Month reported by Gps + * @param day Day reported by Gps + * @param hour Hour reported by Gps + * @param min Min reported by Gps + * @param sec Sec reported by Gps + * @param visSat Visible sattelites reported by Gps + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_gps_date_time_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t year,uint8_t month,uint8_t day,uint8_t hour,uint8_t min,uint8_t sec,uint8_t visSat) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[7]; + _mav_put_uint8_t(buf, 0, year); + _mav_put_uint8_t(buf, 1, month); + _mav_put_uint8_t(buf, 2, day); + _mav_put_uint8_t(buf, 3, hour); + _mav_put_uint8_t(buf, 4, min); + _mav_put_uint8_t(buf, 5, sec); + _mav_put_uint8_t(buf, 6, visSat); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 7); +#else + mavlink_gps_date_time_t packet; + packet.year = year; + packet.month = month; + packet.day = day; + packet.hour = hour; + packet.min = min; + packet.sec = sec; + packet.visSat = visSat; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 7); +#endif + + msg->msgid = MAVLINK_MSG_ID_GPS_DATE_TIME; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 7, 16); +} + +/** + * @brief Encode a gps_date_time struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param gps_date_time C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_gps_date_time_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_gps_date_time_t* gps_date_time) +{ + return mavlink_msg_gps_date_time_pack(system_id, component_id, msg, gps_date_time->year, gps_date_time->month, gps_date_time->day, gps_date_time->hour, gps_date_time->min, gps_date_time->sec, gps_date_time->visSat); +} + +/** + * @brief Send a gps_date_time message + * @param chan MAVLink channel to send the message + * + * @param year Year reported by Gps + * @param month Month reported by Gps + * @param day Day reported by Gps + * @param hour Hour reported by Gps + * @param min Min reported by Gps + * @param sec Sec reported by Gps + * @param visSat Visible sattelites reported by Gps + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_gps_date_time_send(mavlink_channel_t chan, uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec, uint8_t visSat) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[7]; + _mav_put_uint8_t(buf, 0, year); + _mav_put_uint8_t(buf, 1, month); + _mav_put_uint8_t(buf, 2, day); + _mav_put_uint8_t(buf, 3, hour); + _mav_put_uint8_t(buf, 4, min); + _mav_put_uint8_t(buf, 5, sec); + _mav_put_uint8_t(buf, 6, visSat); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_DATE_TIME, buf, 7, 16); +#else + mavlink_gps_date_time_t packet; + packet.year = year; + packet.month = month; + packet.day = day; + packet.hour = hour; + packet.min = min; + packet.sec = sec; + packet.visSat = visSat; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_GPS_DATE_TIME, (const char *)&packet, 7, 16); +#endif +} + +#endif + +// MESSAGE GPS_DATE_TIME UNPACKING + + +/** + * @brief Get field year from gps_date_time message + * + * @return Year reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_year(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field month from gps_date_time message + * + * @return Month reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_month(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field day from gps_date_time message + * + * @return Day reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_day(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field hour from gps_date_time message + * + * @return Hour reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_hour(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field min from gps_date_time message + * + * @return Min reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_min(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 4); +} + +/** + * @brief Get field sec from gps_date_time message + * + * @return Sec reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_sec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 5); +} + +/** + * @brief Get field visSat from gps_date_time message + * + * @return Visible sattelites reported by Gps + */ +static inline uint8_t mavlink_msg_gps_date_time_get_visSat(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 6); +} + +/** + * @brief Decode a gps_date_time message into a struct + * + * @param msg The message to decode + * @param gps_date_time C-struct to decode the message contents into + */ +static inline void mavlink_msg_gps_date_time_decode(const mavlink_message_t* msg, mavlink_gps_date_time_t* gps_date_time) +{ +#if MAVLINK_NEED_BYTE_SWAP + gps_date_time->year = mavlink_msg_gps_date_time_get_year(msg); + gps_date_time->month = mavlink_msg_gps_date_time_get_month(msg); + gps_date_time->day = mavlink_msg_gps_date_time_get_day(msg); + gps_date_time->hour = mavlink_msg_gps_date_time_get_hour(msg); + gps_date_time->min = mavlink_msg_gps_date_time_get_min(msg); + gps_date_time->sec = mavlink_msg_gps_date_time_get_sec(msg); + gps_date_time->visSat = mavlink_msg_gps_date_time_get_visSat(msg); +#else + memcpy(gps_date_time, _MAV_PAYLOAD(msg), 7); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_mid_lvl_cmds.h b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_mid_lvl_cmds.h new file mode 100644 index 0000000000..6542ab1dec --- /dev/null +++ b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_mid_lvl_cmds.h @@ -0,0 +1,210 @@ +// MESSAGE MID_LVL_CMDS PACKING + +#define MAVLINK_MSG_ID_MID_LVL_CMDS 180 + +typedef struct __mavlink_mid_lvl_cmds_t +{ + float hCommand; ///< Commanded Airspeed + float uCommand; ///< Log value 2 + float rCommand; ///< Log value 3 + uint8_t target; ///< The system setting the commands +} mavlink_mid_lvl_cmds_t; + +#define MAVLINK_MSG_ID_MID_LVL_CMDS_LEN 13 +#define MAVLINK_MSG_ID_180_LEN 13 + + + +#define MAVLINK_MESSAGE_INFO_MID_LVL_CMDS { \ + "MID_LVL_CMDS", \ + 4, \ + { { "hCommand", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_mid_lvl_cmds_t, hCommand) }, \ + { "uCommand", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_mid_lvl_cmds_t, uCommand) }, \ + { "rCommand", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_mid_lvl_cmds_t, rCommand) }, \ + { "target", NULL, MAVLINK_TYPE_UINT8_T, 0, 12, offsetof(mavlink_mid_lvl_cmds_t, target) }, \ + } \ +} + + +/** + * @brief Pack a mid_lvl_cmds message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target The system setting the commands + * @param hCommand Commanded Airspeed + * @param uCommand Log value 2 + * @param rCommand Log value 3 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mid_lvl_cmds_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target, float hCommand, float uCommand, float rCommand) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_float(buf, 0, hCommand); + _mav_put_float(buf, 4, uCommand); + _mav_put_float(buf, 8, rCommand); + _mav_put_uint8_t(buf, 12, target); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 13); +#else + mavlink_mid_lvl_cmds_t packet; + packet.hCommand = hCommand; + packet.uCommand = uCommand; + packet.rCommand = rCommand; + packet.target = target; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 13); +#endif + + msg->msgid = MAVLINK_MSG_ID_MID_LVL_CMDS; + return mavlink_finalize_message(msg, system_id, component_id, 13, 146); +} + +/** + * @brief Pack a mid_lvl_cmds message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system setting the commands + * @param hCommand Commanded Airspeed + * @param uCommand Log value 2 + * @param rCommand Log value 3 + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_mid_lvl_cmds_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,float hCommand,float uCommand,float rCommand) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_float(buf, 0, hCommand); + _mav_put_float(buf, 4, uCommand); + _mav_put_float(buf, 8, rCommand); + _mav_put_uint8_t(buf, 12, target); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 13); +#else + mavlink_mid_lvl_cmds_t packet; + packet.hCommand = hCommand; + packet.uCommand = uCommand; + packet.rCommand = rCommand; + packet.target = target; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 13); +#endif + + msg->msgid = MAVLINK_MSG_ID_MID_LVL_CMDS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 13, 146); +} + +/** + * @brief Encode a mid_lvl_cmds struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param mid_lvl_cmds C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_mid_lvl_cmds_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_mid_lvl_cmds_t* mid_lvl_cmds) +{ + return mavlink_msg_mid_lvl_cmds_pack(system_id, component_id, msg, mid_lvl_cmds->target, mid_lvl_cmds->hCommand, mid_lvl_cmds->uCommand, mid_lvl_cmds->rCommand); +} + +/** + * @brief Send a mid_lvl_cmds message + * @param chan MAVLink channel to send the message + * + * @param target The system setting the commands + * @param hCommand Commanded Airspeed + * @param uCommand Log value 2 + * @param rCommand Log value 3 + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_mid_lvl_cmds_send(mavlink_channel_t chan, uint8_t target, float hCommand, float uCommand, float rCommand) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[13]; + _mav_put_float(buf, 0, hCommand); + _mav_put_float(buf, 4, uCommand); + _mav_put_float(buf, 8, rCommand); + _mav_put_uint8_t(buf, 12, target); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MID_LVL_CMDS, buf, 13, 146); +#else + mavlink_mid_lvl_cmds_t packet; + packet.hCommand = hCommand; + packet.uCommand = uCommand; + packet.rCommand = rCommand; + packet.target = target; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_MID_LVL_CMDS, (const char *)&packet, 13, 146); +#endif +} + +#endif + +// MESSAGE MID_LVL_CMDS UNPACKING + + +/** + * @brief Get field target from mid_lvl_cmds message + * + * @return The system setting the commands + */ +static inline uint8_t mavlink_msg_mid_lvl_cmds_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 12); +} + +/** + * @brief Get field hCommand from mid_lvl_cmds message + * + * @return Commanded Airspeed + */ +static inline float mavlink_msg_mid_lvl_cmds_get_hCommand(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field uCommand from mid_lvl_cmds message + * + * @return Log value 2 + */ +static inline float mavlink_msg_mid_lvl_cmds_get_uCommand(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field rCommand from mid_lvl_cmds message + * + * @return Log value 3 + */ +static inline float mavlink_msg_mid_lvl_cmds_get_rCommand(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Decode a mid_lvl_cmds message into a struct + * + * @param msg The message to decode + * @param mid_lvl_cmds C-struct to decode the message contents into + */ +static inline void mavlink_msg_mid_lvl_cmds_decode(const mavlink_message_t* msg, mavlink_mid_lvl_cmds_t* mid_lvl_cmds) +{ +#if MAVLINK_NEED_BYTE_SWAP + mid_lvl_cmds->hCommand = mavlink_msg_mid_lvl_cmds_get_hCommand(msg); + mid_lvl_cmds->uCommand = mavlink_msg_mid_lvl_cmds_get_uCommand(msg); + mid_lvl_cmds->rCommand = mavlink_msg_mid_lvl_cmds_get_rCommand(msg); + mid_lvl_cmds->target = mavlink_msg_mid_lvl_cmds_get_target(msg); +#else + memcpy(mid_lvl_cmds, _MAV_PAYLOAD(msg), 13); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_sensor_bias.h b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_sensor_bias.h new file mode 100644 index 0000000000..7dec47ed3a --- /dev/null +++ b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_sensor_bias.h @@ -0,0 +1,254 @@ +// MESSAGE SENSOR_BIAS PACKING + +#define MAVLINK_MSG_ID_SENSOR_BIAS 172 + +typedef struct __mavlink_sensor_bias_t +{ + float axBias; ///< Accelerometer X bias (m/s) + float ayBias; ///< Accelerometer Y bias (m/s) + float azBias; ///< Accelerometer Z bias (m/s) + float gxBias; ///< Gyro X bias (rad/s) + float gyBias; ///< Gyro Y bias (rad/s) + float gzBias; ///< Gyro Z bias (rad/s) +} mavlink_sensor_bias_t; + +#define MAVLINK_MSG_ID_SENSOR_BIAS_LEN 24 +#define MAVLINK_MSG_ID_172_LEN 24 + + + +#define MAVLINK_MESSAGE_INFO_SENSOR_BIAS { \ + "SENSOR_BIAS", \ + 6, \ + { { "axBias", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_sensor_bias_t, axBias) }, \ + { "ayBias", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_sensor_bias_t, ayBias) }, \ + { "azBias", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_sensor_bias_t, azBias) }, \ + { "gxBias", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_sensor_bias_t, gxBias) }, \ + { "gyBias", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_sensor_bias_t, gyBias) }, \ + { "gzBias", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_sensor_bias_t, gzBias) }, \ + } \ +} + + +/** + * @brief Pack a sensor_bias message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param axBias Accelerometer X bias (m/s) + * @param ayBias Accelerometer Y bias (m/s) + * @param azBias Accelerometer Z bias (m/s) + * @param gxBias Gyro X bias (rad/s) + * @param gyBias Gyro Y bias (rad/s) + * @param gzBias Gyro Z bias (rad/s) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sensor_bias_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float axBias, float ayBias, float azBias, float gxBias, float gyBias, float gzBias) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_float(buf, 0, axBias); + _mav_put_float(buf, 4, ayBias); + _mav_put_float(buf, 8, azBias); + _mav_put_float(buf, 12, gxBias); + _mav_put_float(buf, 16, gyBias); + _mav_put_float(buf, 20, gzBias); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_sensor_bias_t packet; + packet.axBias = axBias; + packet.ayBias = ayBias; + packet.azBias = azBias; + packet.gxBias = gxBias; + packet.gyBias = gyBias; + packet.gzBias = gzBias; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_SENSOR_BIAS; + return mavlink_finalize_message(msg, system_id, component_id, 24, 168); +} + +/** + * @brief Pack a sensor_bias message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param axBias Accelerometer X bias (m/s) + * @param ayBias Accelerometer Y bias (m/s) + * @param azBias Accelerometer Z bias (m/s) + * @param gxBias Gyro X bias (rad/s) + * @param gyBias Gyro Y bias (rad/s) + * @param gzBias Gyro Z bias (rad/s) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_sensor_bias_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float axBias,float ayBias,float azBias,float gxBias,float gyBias,float gzBias) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_float(buf, 0, axBias); + _mav_put_float(buf, 4, ayBias); + _mav_put_float(buf, 8, azBias); + _mav_put_float(buf, 12, gxBias); + _mav_put_float(buf, 16, gyBias); + _mav_put_float(buf, 20, gzBias); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 24); +#else + mavlink_sensor_bias_t packet; + packet.axBias = axBias; + packet.ayBias = ayBias; + packet.azBias = azBias; + packet.gxBias = gxBias; + packet.gyBias = gyBias; + packet.gzBias = gzBias; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 24); +#endif + + msg->msgid = MAVLINK_MSG_ID_SENSOR_BIAS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 24, 168); +} + +/** + * @brief Encode a sensor_bias struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param sensor_bias C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_sensor_bias_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_sensor_bias_t* sensor_bias) +{ + return mavlink_msg_sensor_bias_pack(system_id, component_id, msg, sensor_bias->axBias, sensor_bias->ayBias, sensor_bias->azBias, sensor_bias->gxBias, sensor_bias->gyBias, sensor_bias->gzBias); +} + +/** + * @brief Send a sensor_bias message + * @param chan MAVLink channel to send the message + * + * @param axBias Accelerometer X bias (m/s) + * @param ayBias Accelerometer Y bias (m/s) + * @param azBias Accelerometer Z bias (m/s) + * @param gxBias Gyro X bias (rad/s) + * @param gyBias Gyro Y bias (rad/s) + * @param gzBias Gyro Z bias (rad/s) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_sensor_bias_send(mavlink_channel_t chan, float axBias, float ayBias, float azBias, float gxBias, float gyBias, float gzBias) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[24]; + _mav_put_float(buf, 0, axBias); + _mav_put_float(buf, 4, ayBias); + _mav_put_float(buf, 8, azBias); + _mav_put_float(buf, 12, gxBias); + _mav_put_float(buf, 16, gyBias); + _mav_put_float(buf, 20, gzBias); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SENSOR_BIAS, buf, 24, 168); +#else + mavlink_sensor_bias_t packet; + packet.axBias = axBias; + packet.ayBias = ayBias; + packet.azBias = azBias; + packet.gxBias = gxBias; + packet.gyBias = gyBias; + packet.gzBias = gzBias; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SENSOR_BIAS, (const char *)&packet, 24, 168); +#endif +} + +#endif + +// MESSAGE SENSOR_BIAS UNPACKING + + +/** + * @brief Get field axBias from sensor_bias message + * + * @return Accelerometer X bias (m/s) + */ +static inline float mavlink_msg_sensor_bias_get_axBias(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field ayBias from sensor_bias message + * + * @return Accelerometer Y bias (m/s) + */ +static inline float mavlink_msg_sensor_bias_get_ayBias(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field azBias from sensor_bias message + * + * @return Accelerometer Z bias (m/s) + */ +static inline float mavlink_msg_sensor_bias_get_azBias(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field gxBias from sensor_bias message + * + * @return Gyro X bias (rad/s) + */ +static inline float mavlink_msg_sensor_bias_get_gxBias(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field gyBias from sensor_bias message + * + * @return Gyro Y bias (rad/s) + */ +static inline float mavlink_msg_sensor_bias_get_gyBias(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field gzBias from sensor_bias message + * + * @return Gyro Z bias (rad/s) + */ +static inline float mavlink_msg_sensor_bias_get_gzBias(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Decode a sensor_bias message into a struct + * + * @param msg The message to decode + * @param sensor_bias C-struct to decode the message contents into + */ +static inline void mavlink_msg_sensor_bias_decode(const mavlink_message_t* msg, mavlink_sensor_bias_t* sensor_bias) +{ +#if MAVLINK_NEED_BYTE_SWAP + sensor_bias->axBias = mavlink_msg_sensor_bias_get_axBias(msg); + sensor_bias->ayBias = mavlink_msg_sensor_bias_get_ayBias(msg); + sensor_bias->azBias = mavlink_msg_sensor_bias_get_azBias(msg); + sensor_bias->gxBias = mavlink_msg_sensor_bias_get_gxBias(msg); + sensor_bias->gyBias = mavlink_msg_sensor_bias_get_gyBias(msg); + sensor_bias->gzBias = mavlink_msg_sensor_bias_get_gzBias(msg); +#else + memcpy(sensor_bias, _MAV_PAYLOAD(msg), 24); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_slugs_action.h b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_slugs_action.h new file mode 100644 index 0000000000..84b87a308e --- /dev/null +++ b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_slugs_action.h @@ -0,0 +1,188 @@ +// MESSAGE SLUGS_ACTION PACKING + +#define MAVLINK_MSG_ID_SLUGS_ACTION 183 + +typedef struct __mavlink_slugs_action_t +{ + uint16_t actionVal; ///< Value associated with the action + uint8_t target; ///< The system reporting the action + uint8_t actionId; ///< Action ID. See apDefinitions.h in the SLUGS /clib directory for the ID names +} mavlink_slugs_action_t; + +#define MAVLINK_MSG_ID_SLUGS_ACTION_LEN 4 +#define MAVLINK_MSG_ID_183_LEN 4 + + + +#define MAVLINK_MESSAGE_INFO_SLUGS_ACTION { \ + "SLUGS_ACTION", \ + 3, \ + { { "actionVal", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_slugs_action_t, actionVal) }, \ + { "target", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_slugs_action_t, target) }, \ + { "actionId", NULL, MAVLINK_TYPE_UINT8_T, 0, 3, offsetof(mavlink_slugs_action_t, actionId) }, \ + } \ +} + + +/** + * @brief Pack a slugs_action message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param target The system reporting the action + * @param actionId Action ID. See apDefinitions.h in the SLUGS /clib directory for the ID names + * @param actionVal Value associated with the action + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_slugs_action_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t target, uint8_t actionId, uint16_t actionVal) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, actionVal); + _mav_put_uint8_t(buf, 2, target); + _mav_put_uint8_t(buf, 3, actionId); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_slugs_action_t packet; + packet.actionVal = actionVal; + packet.target = target; + packet.actionId = actionId; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_SLUGS_ACTION; + return mavlink_finalize_message(msg, system_id, component_id, 4, 65); +} + +/** + * @brief Pack a slugs_action message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param target The system reporting the action + * @param actionId Action ID. See apDefinitions.h in the SLUGS /clib directory for the ID names + * @param actionVal Value associated with the action + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_slugs_action_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t target,uint8_t actionId,uint16_t actionVal) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, actionVal); + _mav_put_uint8_t(buf, 2, target); + _mav_put_uint8_t(buf, 3, actionId); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 4); +#else + mavlink_slugs_action_t packet; + packet.actionVal = actionVal; + packet.target = target; + packet.actionId = actionId; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 4); +#endif + + msg->msgid = MAVLINK_MSG_ID_SLUGS_ACTION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 4, 65); +} + +/** + * @brief Encode a slugs_action struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param slugs_action C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_slugs_action_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_slugs_action_t* slugs_action) +{ + return mavlink_msg_slugs_action_pack(system_id, component_id, msg, slugs_action->target, slugs_action->actionId, slugs_action->actionVal); +} + +/** + * @brief Send a slugs_action message + * @param chan MAVLink channel to send the message + * + * @param target The system reporting the action + * @param actionId Action ID. See apDefinitions.h in the SLUGS /clib directory for the ID names + * @param actionVal Value associated with the action + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_slugs_action_send(mavlink_channel_t chan, uint8_t target, uint8_t actionId, uint16_t actionVal) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[4]; + _mav_put_uint16_t(buf, 0, actionVal); + _mav_put_uint8_t(buf, 2, target); + _mav_put_uint8_t(buf, 3, actionId); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SLUGS_ACTION, buf, 4, 65); +#else + mavlink_slugs_action_t packet; + packet.actionVal = actionVal; + packet.target = target; + packet.actionId = actionId; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SLUGS_ACTION, (const char *)&packet, 4, 65); +#endif +} + +#endif + +// MESSAGE SLUGS_ACTION UNPACKING + + +/** + * @brief Get field target from slugs_action message + * + * @return The system reporting the action + */ +static inline uint8_t mavlink_msg_slugs_action_get_target(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Get field actionId from slugs_action message + * + * @return Action ID. See apDefinitions.h in the SLUGS /clib directory for the ID names + */ +static inline uint8_t mavlink_msg_slugs_action_get_actionId(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 3); +} + +/** + * @brief Get field actionVal from slugs_action message + * + * @return Value associated with the action + */ +static inline uint16_t mavlink_msg_slugs_action_get_actionVal(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Decode a slugs_action message into a struct + * + * @param msg The message to decode + * @param slugs_action C-struct to decode the message contents into + */ +static inline void mavlink_msg_slugs_action_decode(const mavlink_message_t* msg, mavlink_slugs_action_t* slugs_action) +{ +#if MAVLINK_NEED_BYTE_SWAP + slugs_action->actionVal = mavlink_msg_slugs_action_get_actionVal(msg); + slugs_action->target = mavlink_msg_slugs_action_get_target(msg); + slugs_action->actionId = mavlink_msg_slugs_action_get_actionId(msg); +#else + memcpy(slugs_action, _MAV_PAYLOAD(msg), 4); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_slugs_navigation.h b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_slugs_navigation.h new file mode 100644 index 0000000000..b29a889975 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/slugs/mavlink_msg_slugs_navigation.h @@ -0,0 +1,320 @@ +// MESSAGE SLUGS_NAVIGATION PACKING + +#define MAVLINK_MSG_ID_SLUGS_NAVIGATION 176 + +typedef struct __mavlink_slugs_navigation_t +{ + float u_m; ///< Measured Airspeed prior to the Nav Filter + float phi_c; ///< Commanded Roll + float theta_c; ///< Commanded Pitch + float psiDot_c; ///< Commanded Turn rate + float ay_body; ///< Y component of the body acceleration + float totalDist; ///< Total Distance to Run on this leg of Navigation + float dist2Go; ///< Remaining distance to Run on this leg of Navigation + uint8_t fromWP; ///< Origin WP + uint8_t toWP; ///< Destination WP +} mavlink_slugs_navigation_t; + +#define MAVLINK_MSG_ID_SLUGS_NAVIGATION_LEN 30 +#define MAVLINK_MSG_ID_176_LEN 30 + + + +#define MAVLINK_MESSAGE_INFO_SLUGS_NAVIGATION { \ + "SLUGS_NAVIGATION", \ + 9, \ + { { "u_m", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_slugs_navigation_t, u_m) }, \ + { "phi_c", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_slugs_navigation_t, phi_c) }, \ + { "theta_c", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_slugs_navigation_t, theta_c) }, \ + { "psiDot_c", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_slugs_navigation_t, psiDot_c) }, \ + { "ay_body", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_slugs_navigation_t, ay_body) }, \ + { "totalDist", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_slugs_navigation_t, totalDist) }, \ + { "dist2Go", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_slugs_navigation_t, dist2Go) }, \ + { "fromWP", NULL, MAVLINK_TYPE_UINT8_T, 0, 28, offsetof(mavlink_slugs_navigation_t, fromWP) }, \ + { "toWP", NULL, MAVLINK_TYPE_UINT8_T, 0, 29, offsetof(mavlink_slugs_navigation_t, toWP) }, \ + } \ +} + + +/** + * @brief Pack a slugs_navigation message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param u_m Measured Airspeed prior to the Nav Filter + * @param phi_c Commanded Roll + * @param theta_c Commanded Pitch + * @param psiDot_c Commanded Turn rate + * @param ay_body Y component of the body acceleration + * @param totalDist Total Distance to Run on this leg of Navigation + * @param dist2Go Remaining distance to Run on this leg of Navigation + * @param fromWP Origin WP + * @param toWP Destination WP + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_slugs_navigation_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float u_m, float phi_c, float theta_c, float psiDot_c, float ay_body, float totalDist, float dist2Go, uint8_t fromWP, uint8_t toWP) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_float(buf, 0, u_m); + _mav_put_float(buf, 4, phi_c); + _mav_put_float(buf, 8, theta_c); + _mav_put_float(buf, 12, psiDot_c); + _mav_put_float(buf, 16, ay_body); + _mav_put_float(buf, 20, totalDist); + _mav_put_float(buf, 24, dist2Go); + _mav_put_uint8_t(buf, 28, fromWP); + _mav_put_uint8_t(buf, 29, toWP); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 30); +#else + mavlink_slugs_navigation_t packet; + packet.u_m = u_m; + packet.phi_c = phi_c; + packet.theta_c = theta_c; + packet.psiDot_c = psiDot_c; + packet.ay_body = ay_body; + packet.totalDist = totalDist; + packet.dist2Go = dist2Go; + packet.fromWP = fromWP; + packet.toWP = toWP; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 30); +#endif + + msg->msgid = MAVLINK_MSG_ID_SLUGS_NAVIGATION; + return mavlink_finalize_message(msg, system_id, component_id, 30, 120); +} + +/** + * @brief Pack a slugs_navigation message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param u_m Measured Airspeed prior to the Nav Filter + * @param phi_c Commanded Roll + * @param theta_c Commanded Pitch + * @param psiDot_c Commanded Turn rate + * @param ay_body Y component of the body acceleration + * @param totalDist Total Distance to Run on this leg of Navigation + * @param dist2Go Remaining distance to Run on this leg of Navigation + * @param fromWP Origin WP + * @param toWP Destination WP + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_slugs_navigation_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float u_m,float phi_c,float theta_c,float psiDot_c,float ay_body,float totalDist,float dist2Go,uint8_t fromWP,uint8_t toWP) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_float(buf, 0, u_m); + _mav_put_float(buf, 4, phi_c); + _mav_put_float(buf, 8, theta_c); + _mav_put_float(buf, 12, psiDot_c); + _mav_put_float(buf, 16, ay_body); + _mav_put_float(buf, 20, totalDist); + _mav_put_float(buf, 24, dist2Go); + _mav_put_uint8_t(buf, 28, fromWP); + _mav_put_uint8_t(buf, 29, toWP); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 30); +#else + mavlink_slugs_navigation_t packet; + packet.u_m = u_m; + packet.phi_c = phi_c; + packet.theta_c = theta_c; + packet.psiDot_c = psiDot_c; + packet.ay_body = ay_body; + packet.totalDist = totalDist; + packet.dist2Go = dist2Go; + packet.fromWP = fromWP; + packet.toWP = toWP; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 30); +#endif + + msg->msgid = MAVLINK_MSG_ID_SLUGS_NAVIGATION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 30, 120); +} + +/** + * @brief Encode a slugs_navigation struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param slugs_navigation C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_slugs_navigation_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_slugs_navigation_t* slugs_navigation) +{ + return mavlink_msg_slugs_navigation_pack(system_id, component_id, msg, slugs_navigation->u_m, slugs_navigation->phi_c, slugs_navigation->theta_c, slugs_navigation->psiDot_c, slugs_navigation->ay_body, slugs_navigation->totalDist, slugs_navigation->dist2Go, slugs_navigation->fromWP, slugs_navigation->toWP); +} + +/** + * @brief Send a slugs_navigation message + * @param chan MAVLink channel to send the message + * + * @param u_m Measured Airspeed prior to the Nav Filter + * @param phi_c Commanded Roll + * @param theta_c Commanded Pitch + * @param psiDot_c Commanded Turn rate + * @param ay_body Y component of the body acceleration + * @param totalDist Total Distance to Run on this leg of Navigation + * @param dist2Go Remaining distance to Run on this leg of Navigation + * @param fromWP Origin WP + * @param toWP Destination WP + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_slugs_navigation_send(mavlink_channel_t chan, float u_m, float phi_c, float theta_c, float psiDot_c, float ay_body, float totalDist, float dist2Go, uint8_t fromWP, uint8_t toWP) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[30]; + _mav_put_float(buf, 0, u_m); + _mav_put_float(buf, 4, phi_c); + _mav_put_float(buf, 8, theta_c); + _mav_put_float(buf, 12, psiDot_c); + _mav_put_float(buf, 16, ay_body); + _mav_put_float(buf, 20, totalDist); + _mav_put_float(buf, 24, dist2Go); + _mav_put_uint8_t(buf, 28, fromWP); + _mav_put_uint8_t(buf, 29, toWP); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SLUGS_NAVIGATION, buf, 30, 120); +#else + mavlink_slugs_navigation_t packet; + packet.u_m = u_m; + packet.phi_c = phi_c; + packet.theta_c = theta_c; + packet.psiDot_c = psiDot_c; + packet.ay_body = ay_body; + packet.totalDist = totalDist; + packet.dist2Go = dist2Go; + packet.fromWP = fromWP; + packet.toWP = toWP; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SLUGS_NAVIGATION, (const char *)&packet, 30, 120); +#endif +} + +#endif + +// MESSAGE SLUGS_NAVIGATION UNPACKING + + +/** + * @brief Get field u_m from slugs_navigation message + * + * @return Measured Airspeed prior to the Nav Filter + */ +static inline float mavlink_msg_slugs_navigation_get_u_m(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field phi_c from slugs_navigation message + * + * @return Commanded Roll + */ +static inline float mavlink_msg_slugs_navigation_get_phi_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field theta_c from slugs_navigation message + * + * @return Commanded Pitch + */ +static inline float mavlink_msg_slugs_navigation_get_theta_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field psiDot_c from slugs_navigation message + * + * @return Commanded Turn rate + */ +static inline float mavlink_msg_slugs_navigation_get_psiDot_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field ay_body from slugs_navigation message + * + * @return Y component of the body acceleration + */ +static inline float mavlink_msg_slugs_navigation_get_ay_body(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field totalDist from slugs_navigation message + * + * @return Total Distance to Run on this leg of Navigation + */ +static inline float mavlink_msg_slugs_navigation_get_totalDist(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field dist2Go from slugs_navigation message + * + * @return Remaining distance to Run on this leg of Navigation + */ +static inline float mavlink_msg_slugs_navigation_get_dist2Go(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field fromWP from slugs_navigation message + * + * @return Origin WP + */ +static inline uint8_t mavlink_msg_slugs_navigation_get_fromWP(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 28); +} + +/** + * @brief Get field toWP from slugs_navigation message + * + * @return Destination WP + */ +static inline uint8_t mavlink_msg_slugs_navigation_get_toWP(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 29); +} + +/** + * @brief Decode a slugs_navigation message into a struct + * + * @param msg The message to decode + * @param slugs_navigation C-struct to decode the message contents into + */ +static inline void mavlink_msg_slugs_navigation_decode(const mavlink_message_t* msg, mavlink_slugs_navigation_t* slugs_navigation) +{ +#if MAVLINK_NEED_BYTE_SWAP + slugs_navigation->u_m = mavlink_msg_slugs_navigation_get_u_m(msg); + slugs_navigation->phi_c = mavlink_msg_slugs_navigation_get_phi_c(msg); + slugs_navigation->theta_c = mavlink_msg_slugs_navigation_get_theta_c(msg); + slugs_navigation->psiDot_c = mavlink_msg_slugs_navigation_get_psiDot_c(msg); + slugs_navigation->ay_body = mavlink_msg_slugs_navigation_get_ay_body(msg); + slugs_navigation->totalDist = mavlink_msg_slugs_navigation_get_totalDist(msg); + slugs_navigation->dist2Go = mavlink_msg_slugs_navigation_get_dist2Go(msg); + slugs_navigation->fromWP = mavlink_msg_slugs_navigation_get_fromWP(msg); + slugs_navigation->toWP = mavlink_msg_slugs_navigation_get_toWP(msg); +#else + memcpy(slugs_navigation, _MAV_PAYLOAD(msg), 30); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/slugs/slugs.h b/mavlink/include/mavlink/v1.0/slugs/slugs.h new file mode 100644 index 0000000000..b943624b53 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/slugs/slugs.h @@ -0,0 +1,62 @@ +/** @file + * @brief MAVLink comm protocol generated from slugs.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef SLUGS_H +#define SLUGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {9, 31, 12, 0, 14, 28, 3, 32, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 20, 2, 25, 23, 30, 101, 22, 26, 16, 14, 28, 32, 28, 28, 22, 22, 21, 6, 6, 37, 4, 4, 2, 2, 4, 2, 2, 3, 13, 12, 19, 17, 15, 15, 27, 25, 18, 18, 20, 20, 9, 54, 26, 0, 36, 0, 6, 4, 0, 21, 18, 0, 0, 0, 20, 0, 33, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 56, 42, 33, 0, 0, 0, 0, 0, 0, 0, 26, 32, 32, 20, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 10, 24, 18, 0, 0, 30, 24, 0, 7, 13, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 30, 18, 18, 51, 9, 0} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {50, 124, 137, 0, 237, 217, 104, 119, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 214, 159, 220, 168, 24, 23, 170, 144, 67, 115, 39, 246, 185, 104, 237, 244, 222, 212, 9, 254, 230, 28, 28, 132, 221, 232, 11, 153, 41, 39, 214, 223, 141, 33, 15, 3, 100, 24, 239, 238, 30, 200, 183, 0, 130, 0, 148, 21, 0, 52, 124, 0, 0, 0, 20, 0, 152, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 183, 63, 54, 0, 0, 0, 0, 0, 0, 0, 175, 102, 158, 208, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 232, 168, 2, 0, 0, 120, 167, 0, 16, 146, 104, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 49, 170, 44, 83, 46, 0} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, MAVLINK_MESSAGE_INFO_SYS_STATUS, MAVLINK_MESSAGE_INFO_SYSTEM_TIME, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PING, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK, MAVLINK_MESSAGE_INFO_AUTH_KEY, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_SET_MODE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST, MAVLINK_MESSAGE_INFO_PARAM_VALUE, MAVLINK_MESSAGE_INFO_PARAM_SET, MAVLINK_MESSAGE_INFO_GPS_RAW_INT, MAVLINK_MESSAGE_INFO_GPS_STATUS, MAVLINK_MESSAGE_INFO_SCALED_IMU, MAVLINK_MESSAGE_INFO_RAW_IMU, MAVLINK_MESSAGE_INFO_RAW_PRESSURE, MAVLINK_MESSAGE_INFO_SCALED_PRESSURE, MAVLINK_MESSAGE_INFO_ATTITUDE, MAVLINK_MESSAGE_INFO_ATTITUDE_QUATERNION, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_NED, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT, MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED, MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW, MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW, MAVLINK_MESSAGE_INFO_MISSION_REQUEST_PARTIAL_LIST, MAVLINK_MESSAGE_INFO_MISSION_WRITE_PARTIAL_LIST, MAVLINK_MESSAGE_INFO_MISSION_ITEM, MAVLINK_MESSAGE_INFO_MISSION_REQUEST, MAVLINK_MESSAGE_INFO_MISSION_SET_CURRENT, MAVLINK_MESSAGE_INFO_MISSION_CURRENT, MAVLINK_MESSAGE_INFO_MISSION_REQUEST_LIST, MAVLINK_MESSAGE_INFO_MISSION_COUNT, MAVLINK_MESSAGE_INFO_MISSION_CLEAR_ALL, MAVLINK_MESSAGE_INFO_MISSION_ITEM_REACHED, MAVLINK_MESSAGE_INFO_MISSION_ACK, MAVLINK_MESSAGE_INFO_SET_GPS_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_GPS_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_SET_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_SETPOINT_INT, MAVLINK_MESSAGE_INFO_SET_GLOBAL_POSITION_SETPOINT_INT, MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_SET_QUAD_MOTORS_SETPOINT, MAVLINK_MESSAGE_INFO_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_STATE_CORRECTION, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM, MAVLINK_MESSAGE_INFO_DATA_STREAM, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_MANUAL_CONTROL, MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_VFR_HUD, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_COMMAND_LONG, MAVLINK_MESSAGE_INFO_COMMAND_ACK, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_NED_SYSTEM_GLOBAL_OFFSET, MAVLINK_MESSAGE_INFO_HIL_STATE, MAVLINK_MESSAGE_INFO_HIL_CONTROLS, MAVLINK_MESSAGE_INFO_HIL_RC_INPUTS_RAW, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_OPTICAL_FLOW, MAVLINK_MESSAGE_INFO_GLOBAL_VISION_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VISION_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VISION_SPEED_ESTIMATE, MAVLINK_MESSAGE_INFO_VICON_POSITION_ESTIMATE, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_CPU_LOAD, MAVLINK_MESSAGE_INFO_AIR_DATA, MAVLINK_MESSAGE_INFO_SENSOR_BIAS, MAVLINK_MESSAGE_INFO_DIAGNOSTIC, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_SLUGS_NAVIGATION, MAVLINK_MESSAGE_INFO_DATA_LOG, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_GPS_DATE_TIME, MAVLINK_MESSAGE_INFO_MID_LVL_CMDS, MAVLINK_MESSAGE_INFO_CTRL_SRFC_PT, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_SLUGS_ACTION, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, MAVLINK_MESSAGE_INFO_MEMORY_VECT, MAVLINK_MESSAGE_INFO_DEBUG_VECT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT, MAVLINK_MESSAGE_INFO_STATUSTEXT, MAVLINK_MESSAGE_INFO_DEBUG, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_SLUGS + +#include "../common/common.h" + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 2 +#endif + +// ENUM DEFINITIONS + + + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_cpu_load.h" +#include "./mavlink_msg_air_data.h" +#include "./mavlink_msg_sensor_bias.h" +#include "./mavlink_msg_diagnostic.h" +#include "./mavlink_msg_slugs_navigation.h" +#include "./mavlink_msg_data_log.h" +#include "./mavlink_msg_gps_date_time.h" +#include "./mavlink_msg_mid_lvl_cmds.h" +#include "./mavlink_msg_ctrl_srfc_pt.h" +#include "./mavlink_msg_slugs_action.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // SLUGS_H diff --git a/mavlink/include/mavlink/v1.0/slugs/testsuite.h b/mavlink/include/mavlink/v1.0/slugs/testsuite.h new file mode 100644 index 0000000000..4593235a4a --- /dev/null +++ b/mavlink/include/mavlink/v1.0/slugs/testsuite.h @@ -0,0 +1,552 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from slugs.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef SLUGS_TESTSUITE_H +#define SLUGS_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL +static void mavlink_test_common(uint8_t, uint8_t, mavlink_message_t *last_msg); +static void mavlink_test_slugs(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_test_common(system_id, component_id, last_msg); + mavlink_test_slugs(system_id, component_id, last_msg); +} +#endif + +#include "../common/testsuite.h" + + +static void mavlink_test_cpu_load(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_cpu_load_t packet_in = { + 17235, + 139, + 206, + }; + mavlink_cpu_load_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.batVolt = packet_in.batVolt; + packet1.sensLoad = packet_in.sensLoad; + packet1.ctrlLoad = packet_in.ctrlLoad; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_cpu_load_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_cpu_load_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_cpu_load_pack(system_id, component_id, &msg , packet1.sensLoad , packet1.ctrlLoad , packet1.batVolt ); + mavlink_msg_cpu_load_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_cpu_load_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.sensLoad , packet1.ctrlLoad , packet1.batVolt ); + mavlink_msg_cpu_load_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; imsgid = MAVLINK_MSG_ID_TEST_TYPES; + return mavlink_finalize_message(msg, system_id, component_id, 179, 103); +} + +/** + * @brief Pack a test_types message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param c char + * @param s string + * @param u8 uint8_t + * @param u16 uint16_t + * @param u32 uint32_t + * @param u64 uint64_t + * @param s8 int8_t + * @param s16 int16_t + * @param s32 int32_t + * @param s64 int64_t + * @param f float + * @param d double + * @param u8_array uint8_t_array + * @param u16_array uint16_t_array + * @param u32_array uint32_t_array + * @param u64_array uint64_t_array + * @param s8_array int8_t_array + * @param s16_array int16_t_array + * @param s32_array int32_t_array + * @param s64_array int64_t_array + * @param f_array float_array + * @param d_array double_array + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_test_types_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + char c,const char *s,uint8_t u8,uint16_t u16,uint32_t u32,uint64_t u64,int8_t s8,int16_t s16,int32_t s32,int64_t s64,float f,double d,const uint8_t *u8_array,const uint16_t *u16_array,const uint32_t *u32_array,const uint64_t *u64_array,const int8_t *s8_array,const int16_t *s16_array,const int32_t *s32_array,const int64_t *s64_array,const float *f_array,const double *d_array) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[179]; + _mav_put_uint64_t(buf, 0, u64); + _mav_put_int64_t(buf, 8, s64); + _mav_put_double(buf, 16, d); + _mav_put_uint32_t(buf, 96, u32); + _mav_put_int32_t(buf, 100, s32); + _mav_put_float(buf, 104, f); + _mav_put_uint16_t(buf, 144, u16); + _mav_put_int16_t(buf, 146, s16); + _mav_put_char(buf, 160, c); + _mav_put_uint8_t(buf, 171, u8); + _mav_put_int8_t(buf, 172, s8); + _mav_put_uint64_t_array(buf, 24, u64_array, 3); + _mav_put_int64_t_array(buf, 48, s64_array, 3); + _mav_put_double_array(buf, 72, d_array, 3); + _mav_put_uint32_t_array(buf, 108, u32_array, 3); + _mav_put_int32_t_array(buf, 120, s32_array, 3); + _mav_put_float_array(buf, 132, f_array, 3); + _mav_put_uint16_t_array(buf, 148, u16_array, 3); + _mav_put_int16_t_array(buf, 154, s16_array, 3); + _mav_put_char_array(buf, 161, s, 10); + _mav_put_uint8_t_array(buf, 173, u8_array, 3); + _mav_put_int8_t_array(buf, 176, s8_array, 3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 179); +#else + mavlink_test_types_t packet; + packet.u64 = u64; + packet.s64 = s64; + packet.d = d; + packet.u32 = u32; + packet.s32 = s32; + packet.f = f; + packet.u16 = u16; + packet.s16 = s16; + packet.c = c; + packet.u8 = u8; + packet.s8 = s8; + mav_array_memcpy(packet.u64_array, u64_array, sizeof(uint64_t)*3); + mav_array_memcpy(packet.s64_array, s64_array, sizeof(int64_t)*3); + mav_array_memcpy(packet.d_array, d_array, sizeof(double)*3); + mav_array_memcpy(packet.u32_array, u32_array, sizeof(uint32_t)*3); + mav_array_memcpy(packet.s32_array, s32_array, sizeof(int32_t)*3); + mav_array_memcpy(packet.f_array, f_array, sizeof(float)*3); + mav_array_memcpy(packet.u16_array, u16_array, sizeof(uint16_t)*3); + mav_array_memcpy(packet.s16_array, s16_array, sizeof(int16_t)*3); + mav_array_memcpy(packet.s, s, sizeof(char)*10); + mav_array_memcpy(packet.u8_array, u8_array, sizeof(uint8_t)*3); + mav_array_memcpy(packet.s8_array, s8_array, sizeof(int8_t)*3); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 179); +#endif + + msg->msgid = MAVLINK_MSG_ID_TEST_TYPES; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 179, 103); +} + +/** + * @brief Encode a test_types struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param test_types C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_test_types_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_test_types_t* test_types) +{ + return mavlink_msg_test_types_pack(system_id, component_id, msg, test_types->c, test_types->s, test_types->u8, test_types->u16, test_types->u32, test_types->u64, test_types->s8, test_types->s16, test_types->s32, test_types->s64, test_types->f, test_types->d, test_types->u8_array, test_types->u16_array, test_types->u32_array, test_types->u64_array, test_types->s8_array, test_types->s16_array, test_types->s32_array, test_types->s64_array, test_types->f_array, test_types->d_array); +} + +/** + * @brief Send a test_types message + * @param chan MAVLink channel to send the message + * + * @param c char + * @param s string + * @param u8 uint8_t + * @param u16 uint16_t + * @param u32 uint32_t + * @param u64 uint64_t + * @param s8 int8_t + * @param s16 int16_t + * @param s32 int32_t + * @param s64 int64_t + * @param f float + * @param d double + * @param u8_array uint8_t_array + * @param u16_array uint16_t_array + * @param u32_array uint32_t_array + * @param u64_array uint64_t_array + * @param s8_array int8_t_array + * @param s16_array int16_t_array + * @param s32_array int32_t_array + * @param s64_array int64_t_array + * @param f_array float_array + * @param d_array double_array + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_test_types_send(mavlink_channel_t chan, char c, const char *s, uint8_t u8, uint16_t u16, uint32_t u32, uint64_t u64, int8_t s8, int16_t s16, int32_t s32, int64_t s64, float f, double d, const uint8_t *u8_array, const uint16_t *u16_array, const uint32_t *u32_array, const uint64_t *u64_array, const int8_t *s8_array, const int16_t *s16_array, const int32_t *s32_array, const int64_t *s64_array, const float *f_array, const double *d_array) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[179]; + _mav_put_uint64_t(buf, 0, u64); + _mav_put_int64_t(buf, 8, s64); + _mav_put_double(buf, 16, d); + _mav_put_uint32_t(buf, 96, u32); + _mav_put_int32_t(buf, 100, s32); + _mav_put_float(buf, 104, f); + _mav_put_uint16_t(buf, 144, u16); + _mav_put_int16_t(buf, 146, s16); + _mav_put_char(buf, 160, c); + _mav_put_uint8_t(buf, 171, u8); + _mav_put_int8_t(buf, 172, s8); + _mav_put_uint64_t_array(buf, 24, u64_array, 3); + _mav_put_int64_t_array(buf, 48, s64_array, 3); + _mav_put_double_array(buf, 72, d_array, 3); + _mav_put_uint32_t_array(buf, 108, u32_array, 3); + _mav_put_int32_t_array(buf, 120, s32_array, 3); + _mav_put_float_array(buf, 132, f_array, 3); + _mav_put_uint16_t_array(buf, 148, u16_array, 3); + _mav_put_int16_t_array(buf, 154, s16_array, 3); + _mav_put_char_array(buf, 161, s, 10); + _mav_put_uint8_t_array(buf, 173, u8_array, 3); + _mav_put_int8_t_array(buf, 176, s8_array, 3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_TEST_TYPES, buf, 179, 103); +#else + mavlink_test_types_t packet; + packet.u64 = u64; + packet.s64 = s64; + packet.d = d; + packet.u32 = u32; + packet.s32 = s32; + packet.f = f; + packet.u16 = u16; + packet.s16 = s16; + packet.c = c; + packet.u8 = u8; + packet.s8 = s8; + mav_array_memcpy(packet.u64_array, u64_array, sizeof(uint64_t)*3); + mav_array_memcpy(packet.s64_array, s64_array, sizeof(int64_t)*3); + mav_array_memcpy(packet.d_array, d_array, sizeof(double)*3); + mav_array_memcpy(packet.u32_array, u32_array, sizeof(uint32_t)*3); + mav_array_memcpy(packet.s32_array, s32_array, sizeof(int32_t)*3); + mav_array_memcpy(packet.f_array, f_array, sizeof(float)*3); + mav_array_memcpy(packet.u16_array, u16_array, sizeof(uint16_t)*3); + mav_array_memcpy(packet.s16_array, s16_array, sizeof(int16_t)*3); + mav_array_memcpy(packet.s, s, sizeof(char)*10); + mav_array_memcpy(packet.u8_array, u8_array, sizeof(uint8_t)*3); + mav_array_memcpy(packet.s8_array, s8_array, sizeof(int8_t)*3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_TEST_TYPES, (const char *)&packet, 179, 103); +#endif +} + +#endif + +// MESSAGE TEST_TYPES UNPACKING + + +/** + * @brief Get field c from test_types message + * + * @return char + */ +static inline char mavlink_msg_test_types_get_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_char(msg, 160); +} + +/** + * @brief Get field s from test_types message + * + * @return string + */ +static inline uint16_t mavlink_msg_test_types_get_s(const mavlink_message_t* msg, char *s) +{ + return _MAV_RETURN_char_array(msg, s, 10, 161); +} + +/** + * @brief Get field u8 from test_types message + * + * @return uint8_t + */ +static inline uint8_t mavlink_msg_test_types_get_u8(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 171); +} + +/** + * @brief Get field u16 from test_types message + * + * @return uint16_t + */ +static inline uint16_t mavlink_msg_test_types_get_u16(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 144); +} + +/** + * @brief Get field u32 from test_types message + * + * @return uint32_t + */ +static inline uint32_t mavlink_msg_test_types_get_u32(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 96); +} + +/** + * @brief Get field u64 from test_types message + * + * @return uint64_t + */ +static inline uint64_t mavlink_msg_test_types_get_u64(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field s8 from test_types message + * + * @return int8_t + */ +static inline int8_t mavlink_msg_test_types_get_s8(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int8_t(msg, 172); +} + +/** + * @brief Get field s16 from test_types message + * + * @return int16_t + */ +static inline int16_t mavlink_msg_test_types_get_s16(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 146); +} + +/** + * @brief Get field s32 from test_types message + * + * @return int32_t + */ +static inline int32_t mavlink_msg_test_types_get_s32(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 100); +} + +/** + * @brief Get field s64 from test_types message + * + * @return int64_t + */ +static inline int64_t mavlink_msg_test_types_get_s64(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int64_t(msg, 8); +} + +/** + * @brief Get field f from test_types message + * + * @return float + */ +static inline float mavlink_msg_test_types_get_f(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 104); +} + +/** + * @brief Get field d from test_types message + * + * @return double + */ +static inline double mavlink_msg_test_types_get_d(const mavlink_message_t* msg) +{ + return _MAV_RETURN_double(msg, 16); +} + +/** + * @brief Get field u8_array from test_types message + * + * @return uint8_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u8_array(const mavlink_message_t* msg, uint8_t *u8_array) +{ + return _MAV_RETURN_uint8_t_array(msg, u8_array, 3, 173); +} + +/** + * @brief Get field u16_array from test_types message + * + * @return uint16_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u16_array(const mavlink_message_t* msg, uint16_t *u16_array) +{ + return _MAV_RETURN_uint16_t_array(msg, u16_array, 3, 148); +} + +/** + * @brief Get field u32_array from test_types message + * + * @return uint32_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u32_array(const mavlink_message_t* msg, uint32_t *u32_array) +{ + return _MAV_RETURN_uint32_t_array(msg, u32_array, 3, 108); +} + +/** + * @brief Get field u64_array from test_types message + * + * @return uint64_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u64_array(const mavlink_message_t* msg, uint64_t *u64_array) +{ + return _MAV_RETURN_uint64_t_array(msg, u64_array, 3, 24); +} + +/** + * @brief Get field s8_array from test_types message + * + * @return int8_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s8_array(const mavlink_message_t* msg, int8_t *s8_array) +{ + return _MAV_RETURN_int8_t_array(msg, s8_array, 3, 176); +} + +/** + * @brief Get field s16_array from test_types message + * + * @return int16_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s16_array(const mavlink_message_t* msg, int16_t *s16_array) +{ + return _MAV_RETURN_int16_t_array(msg, s16_array, 3, 154); +} + +/** + * @brief Get field s32_array from test_types message + * + * @return int32_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s32_array(const mavlink_message_t* msg, int32_t *s32_array) +{ + return _MAV_RETURN_int32_t_array(msg, s32_array, 3, 120); +} + +/** + * @brief Get field s64_array from test_types message + * + * @return int64_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s64_array(const mavlink_message_t* msg, int64_t *s64_array) +{ + return _MAV_RETURN_int64_t_array(msg, s64_array, 3, 48); +} + +/** + * @brief Get field f_array from test_types message + * + * @return float_array + */ +static inline uint16_t mavlink_msg_test_types_get_f_array(const mavlink_message_t* msg, float *f_array) +{ + return _MAV_RETURN_float_array(msg, f_array, 3, 132); +} + +/** + * @brief Get field d_array from test_types message + * + * @return double_array + */ +static inline uint16_t mavlink_msg_test_types_get_d_array(const mavlink_message_t* msg, double *d_array) +{ + return _MAV_RETURN_double_array(msg, d_array, 3, 72); +} + +/** + * @brief Decode a test_types message into a struct + * + * @param msg The message to decode + * @param test_types C-struct to decode the message contents into + */ +static inline void mavlink_msg_test_types_decode(const mavlink_message_t* msg, mavlink_test_types_t* test_types) +{ +#if MAVLINK_NEED_BYTE_SWAP + test_types->u64 = mavlink_msg_test_types_get_u64(msg); + test_types->s64 = mavlink_msg_test_types_get_s64(msg); + test_types->d = mavlink_msg_test_types_get_d(msg); + mavlink_msg_test_types_get_u64_array(msg, test_types->u64_array); + mavlink_msg_test_types_get_s64_array(msg, test_types->s64_array); + mavlink_msg_test_types_get_d_array(msg, test_types->d_array); + test_types->u32 = mavlink_msg_test_types_get_u32(msg); + test_types->s32 = mavlink_msg_test_types_get_s32(msg); + test_types->f = mavlink_msg_test_types_get_f(msg); + mavlink_msg_test_types_get_u32_array(msg, test_types->u32_array); + mavlink_msg_test_types_get_s32_array(msg, test_types->s32_array); + mavlink_msg_test_types_get_f_array(msg, test_types->f_array); + test_types->u16 = mavlink_msg_test_types_get_u16(msg); + test_types->s16 = mavlink_msg_test_types_get_s16(msg); + mavlink_msg_test_types_get_u16_array(msg, test_types->u16_array); + mavlink_msg_test_types_get_s16_array(msg, test_types->s16_array); + test_types->c = mavlink_msg_test_types_get_c(msg); + mavlink_msg_test_types_get_s(msg, test_types->s); + test_types->u8 = mavlink_msg_test_types_get_u8(msg); + test_types->s8 = mavlink_msg_test_types_get_s8(msg); + mavlink_msg_test_types_get_u8_array(msg, test_types->u8_array); + mavlink_msg_test_types_get_s8_array(msg, test_types->s8_array); +#else + memcpy(test_types, _MAV_PAYLOAD(msg), 179); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/test/test.h b/mavlink/include/mavlink/v1.0/test/test.h new file mode 100644 index 0000000000..ff552d5149 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/test/test.h @@ -0,0 +1,53 @@ +/** @file + * @brief MAVLink comm protocol generated from test.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef TEST_H +#define TEST_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_TEST_TYPES, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}, {"EMPTY",0,{{"","",MAVLINK_TYPE_CHAR,0,0,0}}}} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_TEST + + + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 3 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 3 +#endif + +// ENUM DEFINITIONS + + + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_test_types.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // TEST_H diff --git a/mavlink/include/mavlink/v1.0/test/testsuite.h b/mavlink/include/mavlink/v1.0/test/testsuite.h new file mode 100644 index 0000000000..658e1ae071 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/test/testsuite.h @@ -0,0 +1,120 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from test.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef TEST_TESTSUITE_H +#define TEST_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL + +static void mavlink_test_test(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + + mavlink_test_test(system_id, component_id, last_msg); +} +#endif + + + + +static void mavlink_test_test_types(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_test_types_t packet_in = { + 93372036854775807ULL, + 93372036854776311LL, + 235.0, + { 93372036854777319, 93372036854777320, 93372036854777321 }, + { 93372036854778831, 93372036854778832, 93372036854778833 }, + { 627.0, 628.0, 629.0 }, + 963502456, + 963502664, + 745.0, + { 963503080, 963503081, 963503082 }, + { 963503704, 963503705, 963503706 }, + { 941.0, 942.0, 943.0 }, + 24723, + 24827, + { 24931, 24932, 24933 }, + { 25243, 25244, 25245 }, + 'E', + "FGHIJKLMN", + 198, + 9, + { 76, 77, 78 }, + { 21, 22, 23 }, + }; + mavlink_test_types_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.u64 = packet_in.u64; + packet1.s64 = packet_in.s64; + packet1.d = packet_in.d; + packet1.u32 = packet_in.u32; + packet1.s32 = packet_in.s32; + packet1.f = packet_in.f; + packet1.u16 = packet_in.u16; + packet1.s16 = packet_in.s16; + packet1.c = packet_in.c; + packet1.u8 = packet_in.u8; + packet1.s8 = packet_in.s8; + + mav_array_memcpy(packet1.u64_array, packet_in.u64_array, sizeof(uint64_t)*3); + mav_array_memcpy(packet1.s64_array, packet_in.s64_array, sizeof(int64_t)*3); + mav_array_memcpy(packet1.d_array, packet_in.d_array, sizeof(double)*3); + mav_array_memcpy(packet1.u32_array, packet_in.u32_array, sizeof(uint32_t)*3); + mav_array_memcpy(packet1.s32_array, packet_in.s32_array, sizeof(int32_t)*3); + mav_array_memcpy(packet1.f_array, packet_in.f_array, sizeof(float)*3); + mav_array_memcpy(packet1.u16_array, packet_in.u16_array, sizeof(uint16_t)*3); + mav_array_memcpy(packet1.s16_array, packet_in.s16_array, sizeof(int16_t)*3); + mav_array_memcpy(packet1.s, packet_in.s, sizeof(char)*10); + mav_array_memcpy(packet1.u8_array, packet_in.u8_array, sizeof(uint8_t)*3); + mav_array_memcpy(packet1.s8_array, packet_in.s8_array, sizeof(int8_t)*3); + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_test_types_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_test_types_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_test_types_pack(system_id, component_id, &msg , packet1.c , packet1.s , packet1.u8 , packet1.u16 , packet1.u32 , packet1.u64 , packet1.s8 , packet1.s16 , packet1.s32 , packet1.s64 , packet1.f , packet1.d , packet1.u8_array , packet1.u16_array , packet1.u32_array , packet1.u64_array , packet1.s8_array , packet1.s16_array , packet1.s32_array , packet1.s64_array , packet1.f_array , packet1.d_array ); + mavlink_msg_test_types_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_test_types_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.c , packet1.s , packet1.u8 , packet1.u16 , packet1.u32 , packet1.u64 , packet1.s8 , packet1.s16 , packet1.s32 , packet1.s64 , packet1.f , packet1.d , packet1.u8_array , packet1.u16_array , packet1.u32_array , packet1.u64_array , packet1.s8_array , packet1.s16_array , packet1.s32_array , packet1.s64_array , packet1.f_array , packet1.d_array ); + mavlink_msg_test_types_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; imsgid = MAVLINK_MSG_ID_NAV_FILTER_BIAS; + return mavlink_finalize_message(msg, system_id, component_id, 32, 34); +} + +/** + * @brief Pack a nav_filter_bias message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param usec Timestamp (microseconds) + * @param accel_0 b_f[0] + * @param accel_1 b_f[1] + * @param accel_2 b_f[2] + * @param gyro_0 b_f[0] + * @param gyro_1 b_f[1] + * @param gyro_2 b_f[2] + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_nav_filter_bias_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint64_t usec,float accel_0,float accel_1,float accel_2,float gyro_0,float gyro_1,float gyro_2) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, accel_0); + _mav_put_float(buf, 12, accel_1); + _mav_put_float(buf, 16, accel_2); + _mav_put_float(buf, 20, gyro_0); + _mav_put_float(buf, 24, gyro_1); + _mav_put_float(buf, 28, gyro_2); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 32); +#else + mavlink_nav_filter_bias_t packet; + packet.usec = usec; + packet.accel_0 = accel_0; + packet.accel_1 = accel_1; + packet.accel_2 = accel_2; + packet.gyro_0 = gyro_0; + packet.gyro_1 = gyro_1; + packet.gyro_2 = gyro_2; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 32); +#endif + + msg->msgid = MAVLINK_MSG_ID_NAV_FILTER_BIAS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 32, 34); +} + +/** + * @brief Encode a nav_filter_bias struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param nav_filter_bias C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_nav_filter_bias_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_nav_filter_bias_t* nav_filter_bias) +{ + return mavlink_msg_nav_filter_bias_pack(system_id, component_id, msg, nav_filter_bias->usec, nav_filter_bias->accel_0, nav_filter_bias->accel_1, nav_filter_bias->accel_2, nav_filter_bias->gyro_0, nav_filter_bias->gyro_1, nav_filter_bias->gyro_2); +} + +/** + * @brief Send a nav_filter_bias message + * @param chan MAVLink channel to send the message + * + * @param usec Timestamp (microseconds) + * @param accel_0 b_f[0] + * @param accel_1 b_f[1] + * @param accel_2 b_f[2] + * @param gyro_0 b_f[0] + * @param gyro_1 b_f[1] + * @param gyro_2 b_f[2] + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_nav_filter_bias_send(mavlink_channel_t chan, uint64_t usec, float accel_0, float accel_1, float accel_2, float gyro_0, float gyro_1, float gyro_2) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[32]; + _mav_put_uint64_t(buf, 0, usec); + _mav_put_float(buf, 8, accel_0); + _mav_put_float(buf, 12, accel_1); + _mav_put_float(buf, 16, accel_2); + _mav_put_float(buf, 20, gyro_0); + _mav_put_float(buf, 24, gyro_1); + _mav_put_float(buf, 28, gyro_2); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAV_FILTER_BIAS, buf, 32, 34); +#else + mavlink_nav_filter_bias_t packet; + packet.usec = usec; + packet.accel_0 = accel_0; + packet.accel_1 = accel_1; + packet.accel_2 = accel_2; + packet.gyro_0 = gyro_0; + packet.gyro_1 = gyro_1; + packet.gyro_2 = gyro_2; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_NAV_FILTER_BIAS, (const char *)&packet, 32, 34); +#endif +} + +#endif + +// MESSAGE NAV_FILTER_BIAS UNPACKING + + +/** + * @brief Get field usec from nav_filter_bias message + * + * @return Timestamp (microseconds) + */ +static inline uint64_t mavlink_msg_nav_filter_bias_get_usec(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field accel_0 from nav_filter_bias message + * + * @return b_f[0] + */ +static inline float mavlink_msg_nav_filter_bias_get_accel_0(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field accel_1 from nav_filter_bias message + * + * @return b_f[1] + */ +static inline float mavlink_msg_nav_filter_bias_get_accel_1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field accel_2 from nav_filter_bias message + * + * @return b_f[2] + */ +static inline float mavlink_msg_nav_filter_bias_get_accel_2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field gyro_0 from nav_filter_bias message + * + * @return b_f[0] + */ +static inline float mavlink_msg_nav_filter_bias_get_gyro_0(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field gyro_1 from nav_filter_bias message + * + * @return b_f[1] + */ +static inline float mavlink_msg_nav_filter_bias_get_gyro_1(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field gyro_2 from nav_filter_bias message + * + * @return b_f[2] + */ +static inline float mavlink_msg_nav_filter_bias_get_gyro_2(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Decode a nav_filter_bias message into a struct + * + * @param msg The message to decode + * @param nav_filter_bias C-struct to decode the message contents into + */ +static inline void mavlink_msg_nav_filter_bias_decode(const mavlink_message_t* msg, mavlink_nav_filter_bias_t* nav_filter_bias) +{ +#if MAVLINK_NEED_BYTE_SWAP + nav_filter_bias->usec = mavlink_msg_nav_filter_bias_get_usec(msg); + nav_filter_bias->accel_0 = mavlink_msg_nav_filter_bias_get_accel_0(msg); + nav_filter_bias->accel_1 = mavlink_msg_nav_filter_bias_get_accel_1(msg); + nav_filter_bias->accel_2 = mavlink_msg_nav_filter_bias_get_accel_2(msg); + nav_filter_bias->gyro_0 = mavlink_msg_nav_filter_bias_get_gyro_0(msg); + nav_filter_bias->gyro_1 = mavlink_msg_nav_filter_bias_get_gyro_1(msg); + nav_filter_bias->gyro_2 = mavlink_msg_nav_filter_bias_get_gyro_2(msg); +#else + memcpy(nav_filter_bias, _MAV_PAYLOAD(msg), 32); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ualberta/mavlink_msg_radio_calibration.h b/mavlink/include/mavlink/v1.0/ualberta/mavlink_msg_radio_calibration.h new file mode 100644 index 0000000000..7227036788 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ualberta/mavlink_msg_radio_calibration.h @@ -0,0 +1,259 @@ +// MESSAGE RADIO_CALIBRATION PACKING + +#define MAVLINK_MSG_ID_RADIO_CALIBRATION 221 + +typedef struct __mavlink_radio_calibration_t +{ + uint16_t aileron[3]; ///< Aileron setpoints: left, center, right + uint16_t elevator[3]; ///< Elevator setpoints: nose down, center, nose up + uint16_t rudder[3]; ///< Rudder setpoints: nose left, center, nose right + uint16_t gyro[2]; ///< Tail gyro mode/gain setpoints: heading hold, rate mode + uint16_t pitch[5]; ///< Pitch curve setpoints (every 25%) + uint16_t throttle[5]; ///< Throttle curve setpoints (every 25%) +} mavlink_radio_calibration_t; + +#define MAVLINK_MSG_ID_RADIO_CALIBRATION_LEN 42 +#define MAVLINK_MSG_ID_221_LEN 42 + +#define MAVLINK_MSG_RADIO_CALIBRATION_FIELD_AILERON_LEN 3 +#define MAVLINK_MSG_RADIO_CALIBRATION_FIELD_ELEVATOR_LEN 3 +#define MAVLINK_MSG_RADIO_CALIBRATION_FIELD_RUDDER_LEN 3 +#define MAVLINK_MSG_RADIO_CALIBRATION_FIELD_GYRO_LEN 2 +#define MAVLINK_MSG_RADIO_CALIBRATION_FIELD_PITCH_LEN 5 +#define MAVLINK_MSG_RADIO_CALIBRATION_FIELD_THROTTLE_LEN 5 + +#define MAVLINK_MESSAGE_INFO_RADIO_CALIBRATION { \ + "RADIO_CALIBRATION", \ + 6, \ + { { "aileron", NULL, MAVLINK_TYPE_UINT16_T, 3, 0, offsetof(mavlink_radio_calibration_t, aileron) }, \ + { "elevator", NULL, MAVLINK_TYPE_UINT16_T, 3, 6, offsetof(mavlink_radio_calibration_t, elevator) }, \ + { "rudder", NULL, MAVLINK_TYPE_UINT16_T, 3, 12, offsetof(mavlink_radio_calibration_t, rudder) }, \ + { "gyro", NULL, MAVLINK_TYPE_UINT16_T, 2, 18, offsetof(mavlink_radio_calibration_t, gyro) }, \ + { "pitch", NULL, MAVLINK_TYPE_UINT16_T, 5, 22, offsetof(mavlink_radio_calibration_t, pitch) }, \ + { "throttle", NULL, MAVLINK_TYPE_UINT16_T, 5, 32, offsetof(mavlink_radio_calibration_t, throttle) }, \ + } \ +} + + +/** + * @brief Pack a radio_calibration message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param aileron Aileron setpoints: left, center, right + * @param elevator Elevator setpoints: nose down, center, nose up + * @param rudder Rudder setpoints: nose left, center, nose right + * @param gyro Tail gyro mode/gain setpoints: heading hold, rate mode + * @param pitch Pitch curve setpoints (every 25%) + * @param throttle Throttle curve setpoints (every 25%) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_radio_calibration_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + const uint16_t *aileron, const uint16_t *elevator, const uint16_t *rudder, const uint16_t *gyro, const uint16_t *pitch, const uint16_t *throttle) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + + _mav_put_uint16_t_array(buf, 0, aileron, 3); + _mav_put_uint16_t_array(buf, 6, elevator, 3); + _mav_put_uint16_t_array(buf, 12, rudder, 3); + _mav_put_uint16_t_array(buf, 18, gyro, 2); + _mav_put_uint16_t_array(buf, 22, pitch, 5); + _mav_put_uint16_t_array(buf, 32, throttle, 5); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 42); +#else + mavlink_radio_calibration_t packet; + + mav_array_memcpy(packet.aileron, aileron, sizeof(uint16_t)*3); + mav_array_memcpy(packet.elevator, elevator, sizeof(uint16_t)*3); + mav_array_memcpy(packet.rudder, rudder, sizeof(uint16_t)*3); + mav_array_memcpy(packet.gyro, gyro, sizeof(uint16_t)*2); + mav_array_memcpy(packet.pitch, pitch, sizeof(uint16_t)*5); + mav_array_memcpy(packet.throttle, throttle, sizeof(uint16_t)*5); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 42); +#endif + + msg->msgid = MAVLINK_MSG_ID_RADIO_CALIBRATION; + return mavlink_finalize_message(msg, system_id, component_id, 42, 71); +} + +/** + * @brief Pack a radio_calibration message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param aileron Aileron setpoints: left, center, right + * @param elevator Elevator setpoints: nose down, center, nose up + * @param rudder Rudder setpoints: nose left, center, nose right + * @param gyro Tail gyro mode/gain setpoints: heading hold, rate mode + * @param pitch Pitch curve setpoints (every 25%) + * @param throttle Throttle curve setpoints (every 25%) + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_radio_calibration_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + const uint16_t *aileron,const uint16_t *elevator,const uint16_t *rudder,const uint16_t *gyro,const uint16_t *pitch,const uint16_t *throttle) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + + _mav_put_uint16_t_array(buf, 0, aileron, 3); + _mav_put_uint16_t_array(buf, 6, elevator, 3); + _mav_put_uint16_t_array(buf, 12, rudder, 3); + _mav_put_uint16_t_array(buf, 18, gyro, 2); + _mav_put_uint16_t_array(buf, 22, pitch, 5); + _mav_put_uint16_t_array(buf, 32, throttle, 5); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 42); +#else + mavlink_radio_calibration_t packet; + + mav_array_memcpy(packet.aileron, aileron, sizeof(uint16_t)*3); + mav_array_memcpy(packet.elevator, elevator, sizeof(uint16_t)*3); + mav_array_memcpy(packet.rudder, rudder, sizeof(uint16_t)*3); + mav_array_memcpy(packet.gyro, gyro, sizeof(uint16_t)*2); + mav_array_memcpy(packet.pitch, pitch, sizeof(uint16_t)*5); + mav_array_memcpy(packet.throttle, throttle, sizeof(uint16_t)*5); + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 42); +#endif + + msg->msgid = MAVLINK_MSG_ID_RADIO_CALIBRATION; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 42, 71); +} + +/** + * @brief Encode a radio_calibration struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param radio_calibration C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_radio_calibration_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_radio_calibration_t* radio_calibration) +{ + return mavlink_msg_radio_calibration_pack(system_id, component_id, msg, radio_calibration->aileron, radio_calibration->elevator, radio_calibration->rudder, radio_calibration->gyro, radio_calibration->pitch, radio_calibration->throttle); +} + +/** + * @brief Send a radio_calibration message + * @param chan MAVLink channel to send the message + * + * @param aileron Aileron setpoints: left, center, right + * @param elevator Elevator setpoints: nose down, center, nose up + * @param rudder Rudder setpoints: nose left, center, nose right + * @param gyro Tail gyro mode/gain setpoints: heading hold, rate mode + * @param pitch Pitch curve setpoints (every 25%) + * @param throttle Throttle curve setpoints (every 25%) + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_radio_calibration_send(mavlink_channel_t chan, const uint16_t *aileron, const uint16_t *elevator, const uint16_t *rudder, const uint16_t *gyro, const uint16_t *pitch, const uint16_t *throttle) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[42]; + + _mav_put_uint16_t_array(buf, 0, aileron, 3); + _mav_put_uint16_t_array(buf, 6, elevator, 3); + _mav_put_uint16_t_array(buf, 12, rudder, 3); + _mav_put_uint16_t_array(buf, 18, gyro, 2); + _mav_put_uint16_t_array(buf, 22, pitch, 5); + _mav_put_uint16_t_array(buf, 32, throttle, 5); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RADIO_CALIBRATION, buf, 42, 71); +#else + mavlink_radio_calibration_t packet; + + mav_array_memcpy(packet.aileron, aileron, sizeof(uint16_t)*3); + mav_array_memcpy(packet.elevator, elevator, sizeof(uint16_t)*3); + mav_array_memcpy(packet.rudder, rudder, sizeof(uint16_t)*3); + mav_array_memcpy(packet.gyro, gyro, sizeof(uint16_t)*2); + mav_array_memcpy(packet.pitch, pitch, sizeof(uint16_t)*5); + mav_array_memcpy(packet.throttle, throttle, sizeof(uint16_t)*5); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_RADIO_CALIBRATION, (const char *)&packet, 42, 71); +#endif +} + +#endif + +// MESSAGE RADIO_CALIBRATION UNPACKING + + +/** + * @brief Get field aileron from radio_calibration message + * + * @return Aileron setpoints: left, center, right + */ +static inline uint16_t mavlink_msg_radio_calibration_get_aileron(const mavlink_message_t* msg, uint16_t *aileron) +{ + return _MAV_RETURN_uint16_t_array(msg, aileron, 3, 0); +} + +/** + * @brief Get field elevator from radio_calibration message + * + * @return Elevator setpoints: nose down, center, nose up + */ +static inline uint16_t mavlink_msg_radio_calibration_get_elevator(const mavlink_message_t* msg, uint16_t *elevator) +{ + return _MAV_RETURN_uint16_t_array(msg, elevator, 3, 6); +} + +/** + * @brief Get field rudder from radio_calibration message + * + * @return Rudder setpoints: nose left, center, nose right + */ +static inline uint16_t mavlink_msg_radio_calibration_get_rudder(const mavlink_message_t* msg, uint16_t *rudder) +{ + return _MAV_RETURN_uint16_t_array(msg, rudder, 3, 12); +} + +/** + * @brief Get field gyro from radio_calibration message + * + * @return Tail gyro mode/gain setpoints: heading hold, rate mode + */ +static inline uint16_t mavlink_msg_radio_calibration_get_gyro(const mavlink_message_t* msg, uint16_t *gyro) +{ + return _MAV_RETURN_uint16_t_array(msg, gyro, 2, 18); +} + +/** + * @brief Get field pitch from radio_calibration message + * + * @return Pitch curve setpoints (every 25%) + */ +static inline uint16_t mavlink_msg_radio_calibration_get_pitch(const mavlink_message_t* msg, uint16_t *pitch) +{ + return _MAV_RETURN_uint16_t_array(msg, pitch, 5, 22); +} + +/** + * @brief Get field throttle from radio_calibration message + * + * @return Throttle curve setpoints (every 25%) + */ +static inline uint16_t mavlink_msg_radio_calibration_get_throttle(const mavlink_message_t* msg, uint16_t *throttle) +{ + return _MAV_RETURN_uint16_t_array(msg, throttle, 5, 32); +} + +/** + * @brief Decode a radio_calibration message into a struct + * + * @param msg The message to decode + * @param radio_calibration C-struct to decode the message contents into + */ +static inline void mavlink_msg_radio_calibration_decode(const mavlink_message_t* msg, mavlink_radio_calibration_t* radio_calibration) +{ +#if MAVLINK_NEED_BYTE_SWAP + mavlink_msg_radio_calibration_get_aileron(msg, radio_calibration->aileron); + mavlink_msg_radio_calibration_get_elevator(msg, radio_calibration->elevator); + mavlink_msg_radio_calibration_get_rudder(msg, radio_calibration->rudder); + mavlink_msg_radio_calibration_get_gyro(msg, radio_calibration->gyro); + mavlink_msg_radio_calibration_get_pitch(msg, radio_calibration->pitch); + mavlink_msg_radio_calibration_get_throttle(msg, radio_calibration->throttle); +#else + memcpy(radio_calibration, _MAV_PAYLOAD(msg), 42); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ualberta/mavlink_msg_ualberta_sys_status.h b/mavlink/include/mavlink/v1.0/ualberta/mavlink_msg_ualberta_sys_status.h new file mode 100644 index 0000000000..176469d25a --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ualberta/mavlink_msg_ualberta_sys_status.h @@ -0,0 +1,188 @@ +// MESSAGE UALBERTA_SYS_STATUS PACKING + +#define MAVLINK_MSG_ID_UALBERTA_SYS_STATUS 222 + +typedef struct __mavlink_ualberta_sys_status_t +{ + uint8_t mode; ///< System mode, see UALBERTA_AUTOPILOT_MODE ENUM + uint8_t nav_mode; ///< Navigation mode, see UALBERTA_NAV_MODE ENUM + uint8_t pilot; ///< Pilot mode, see UALBERTA_PILOT_MODE +} mavlink_ualberta_sys_status_t; + +#define MAVLINK_MSG_ID_UALBERTA_SYS_STATUS_LEN 3 +#define MAVLINK_MSG_ID_222_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_UALBERTA_SYS_STATUS { \ + "UALBERTA_SYS_STATUS", \ + 3, \ + { { "mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 0, offsetof(mavlink_ualberta_sys_status_t, mode) }, \ + { "nav_mode", NULL, MAVLINK_TYPE_UINT8_T, 0, 1, offsetof(mavlink_ualberta_sys_status_t, nav_mode) }, \ + { "pilot", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_ualberta_sys_status_t, pilot) }, \ + } \ +} + + +/** + * @brief Pack a ualberta_sys_status message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param mode System mode, see UALBERTA_AUTOPILOT_MODE ENUM + * @param nav_mode Navigation mode, see UALBERTA_NAV_MODE ENUM + * @param pilot Pilot mode, see UALBERTA_PILOT_MODE + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ualberta_sys_status_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint8_t mode, uint8_t nav_mode, uint8_t pilot) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, mode); + _mav_put_uint8_t(buf, 1, nav_mode); + _mav_put_uint8_t(buf, 2, pilot); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_ualberta_sys_status_t packet; + packet.mode = mode; + packet.nav_mode = nav_mode; + packet.pilot = pilot; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_UALBERTA_SYS_STATUS; + return mavlink_finalize_message(msg, system_id, component_id, 3, 15); +} + +/** + * @brief Pack a ualberta_sys_status message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param mode System mode, see UALBERTA_AUTOPILOT_MODE ENUM + * @param nav_mode Navigation mode, see UALBERTA_NAV_MODE ENUM + * @param pilot Pilot mode, see UALBERTA_PILOT_MODE + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_ualberta_sys_status_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint8_t mode,uint8_t nav_mode,uint8_t pilot) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, mode); + _mav_put_uint8_t(buf, 1, nav_mode); + _mav_put_uint8_t(buf, 2, pilot); + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, 3); +#else + mavlink_ualberta_sys_status_t packet; + packet.mode = mode; + packet.nav_mode = nav_mode; + packet.pilot = pilot; + + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_UALBERTA_SYS_STATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3, 15); +} + +/** + * @brief Encode a ualberta_sys_status struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param ualberta_sys_status C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_ualberta_sys_status_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_ualberta_sys_status_t* ualberta_sys_status) +{ + return mavlink_msg_ualberta_sys_status_pack(system_id, component_id, msg, ualberta_sys_status->mode, ualberta_sys_status->nav_mode, ualberta_sys_status->pilot); +} + +/** + * @brief Send a ualberta_sys_status message + * @param chan MAVLink channel to send the message + * + * @param mode System mode, see UALBERTA_AUTOPILOT_MODE ENUM + * @param nav_mode Navigation mode, see UALBERTA_NAV_MODE ENUM + * @param pilot Pilot mode, see UALBERTA_PILOT_MODE + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_ualberta_sys_status_send(mavlink_channel_t chan, uint8_t mode, uint8_t nav_mode, uint8_t pilot) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint8_t(buf, 0, mode); + _mav_put_uint8_t(buf, 1, nav_mode); + _mav_put_uint8_t(buf, 2, pilot); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_UALBERTA_SYS_STATUS, buf, 3, 15); +#else + mavlink_ualberta_sys_status_t packet; + packet.mode = mode; + packet.nav_mode = nav_mode; + packet.pilot = pilot; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_UALBERTA_SYS_STATUS, (const char *)&packet, 3, 15); +#endif +} + +#endif + +// MESSAGE UALBERTA_SYS_STATUS UNPACKING + + +/** + * @brief Get field mode from ualberta_sys_status message + * + * @return System mode, see UALBERTA_AUTOPILOT_MODE ENUM + */ +static inline uint8_t mavlink_msg_ualberta_sys_status_get_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 0); +} + +/** + * @brief Get field nav_mode from ualberta_sys_status message + * + * @return Navigation mode, see UALBERTA_NAV_MODE ENUM + */ +static inline uint8_t mavlink_msg_ualberta_sys_status_get_nav_mode(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 1); +} + +/** + * @brief Get field pilot from ualberta_sys_status message + * + * @return Pilot mode, see UALBERTA_PILOT_MODE + */ +static inline uint8_t mavlink_msg_ualberta_sys_status_get_pilot(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a ualberta_sys_status message into a struct + * + * @param msg The message to decode + * @param ualberta_sys_status C-struct to decode the message contents into + */ +static inline void mavlink_msg_ualberta_sys_status_decode(const mavlink_message_t* msg, mavlink_ualberta_sys_status_t* ualberta_sys_status) +{ +#if MAVLINK_NEED_BYTE_SWAP + ualberta_sys_status->mode = mavlink_msg_ualberta_sys_status_get_mode(msg); + ualberta_sys_status->nav_mode = mavlink_msg_ualberta_sys_status_get_nav_mode(msg); + ualberta_sys_status->pilot = mavlink_msg_ualberta_sys_status_get_pilot(msg); +#else + memcpy(ualberta_sys_status, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/mavlink/include/mavlink/v1.0/ualberta/testsuite.h b/mavlink/include/mavlink/v1.0/ualberta/testsuite.h new file mode 100644 index 0000000000..79a6a004a4 --- /dev/null +++ b/mavlink/include/mavlink/v1.0/ualberta/testsuite.h @@ -0,0 +1,192 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from ualberta.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef UALBERTA_TESTSUITE_H +#define UALBERTA_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL +static void mavlink_test_common(uint8_t, uint8_t, mavlink_message_t *last_msg); +static void mavlink_test_ualberta(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_test_common(system_id, component_id, last_msg); + mavlink_test_ualberta(system_id, component_id, last_msg); +} +#endif + +#include "../common/testsuite.h" + + +static void mavlink_test_nav_filter_bias(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_nav_filter_bias_t packet_in = { + 93372036854775807ULL, + 73.0, + 101.0, + 129.0, + 157.0, + 185.0, + 213.0, + }; + mavlink_nav_filter_bias_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.usec = packet_in.usec; + packet1.accel_0 = packet_in.accel_0; + packet1.accel_1 = packet_in.accel_1; + packet1.accel_2 = packet_in.accel_2; + packet1.gyro_0 = packet_in.gyro_0; + packet1.gyro_1 = packet_in.gyro_1; + packet1.gyro_2 = packet_in.gyro_2; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_nav_filter_bias_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_nav_filter_bias_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_nav_filter_bias_pack(system_id, component_id, &msg , packet1.usec , packet1.accel_0 , packet1.accel_1 , packet1.accel_2 , packet1.gyro_0 , packet1.gyro_1 , packet1.gyro_2 ); + mavlink_msg_nav_filter_bias_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_nav_filter_bias_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.usec , packet1.accel_0 , packet1.accel_1 , packet1.accel_2 , packet1.gyro_0 , packet1.gyro_1 , packet1.gyro_2 ); + mavlink_msg_nav_filter_bias_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; i + +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace px { + +namespace { + +const ::google::protobuf::Descriptor* HeaderInfo_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + HeaderInfo_reflection_ = NULL; +const ::google::protobuf::Descriptor* GLOverlay_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + GLOverlay_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* GLOverlay_CoordinateFrameType_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* GLOverlay_Mode_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* GLOverlay_Identifier_descriptor_ = NULL; +const ::google::protobuf::Descriptor* Obstacle_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + Obstacle_reflection_ = NULL; +const ::google::protobuf::Descriptor* ObstacleList_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ObstacleList_reflection_ = NULL; +const ::google::protobuf::Descriptor* ObstacleMap_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ObstacleMap_reflection_ = NULL; +const ::google::protobuf::Descriptor* Path_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + Path_reflection_ = NULL; +const ::google::protobuf::Descriptor* PointCloudXYZI_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + PointCloudXYZI_reflection_ = NULL; +const ::google::protobuf::Descriptor* PointCloudXYZI_PointXYZI_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + PointCloudXYZI_PointXYZI_reflection_ = NULL; +const ::google::protobuf::Descriptor* PointCloudXYZRGB_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + PointCloudXYZRGB_reflection_ = NULL; +const ::google::protobuf::Descriptor* PointCloudXYZRGB_PointXYZRGB_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + PointCloudXYZRGB_PointXYZRGB_reflection_ = NULL; +const ::google::protobuf::Descriptor* RGBDImage_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RGBDImage_reflection_ = NULL; +const ::google::protobuf::Descriptor* Waypoint_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + Waypoint_reflection_ = NULL; + +} // namespace + + +void protobuf_AssignDesc_pixhawk_2eproto() { + protobuf_AddDesc_pixhawk_2eproto(); + const ::google::protobuf::FileDescriptor* file = + ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( + "pixhawk.proto"); + GOOGLE_CHECK(file != NULL); + HeaderInfo_descriptor_ = file->message_type(0); + static const int HeaderInfo_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HeaderInfo, source_sysid_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HeaderInfo, source_compid_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HeaderInfo, timestamp_), + }; + HeaderInfo_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + HeaderInfo_descriptor_, + HeaderInfo::default_instance_, + HeaderInfo_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HeaderInfo, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HeaderInfo, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(HeaderInfo)); + GLOverlay_descriptor_ = file->message_type(1); + static const int GLOverlay_offsets_[7] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, coordinateframetype_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, origin_x_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, origin_y_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, origin_z_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, data_), + }; + GLOverlay_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + GLOverlay_descriptor_, + GLOverlay::default_instance_, + GLOverlay_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(GLOverlay)); + GLOverlay_CoordinateFrameType_descriptor_ = GLOverlay_descriptor_->enum_type(0); + GLOverlay_Mode_descriptor_ = GLOverlay_descriptor_->enum_type(1); + GLOverlay_Identifier_descriptor_ = GLOverlay_descriptor_->enum_type(2); + Obstacle_descriptor_ = file->message_type(2); + static const int Obstacle_offsets_[6] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, x_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, y_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, z_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, length_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, width_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, height_), + }; + Obstacle_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + Obstacle_descriptor_, + Obstacle::default_instance_, + Obstacle_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(Obstacle)); + ObstacleList_descriptor_ = file->message_type(3); + static const int ObstacleList_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleList, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleList, obstacles_), + }; + ObstacleList_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ObstacleList_descriptor_, + ObstacleList::default_instance_, + ObstacleList_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleList, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleList, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ObstacleList)); + ObstacleMap_descriptor_ = file->message_type(4); + static const int ObstacleMap_offsets_[10] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, type_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, resolution_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, rows_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, cols_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, mapr0_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, mapc0_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, arrayr0_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, arrayc0_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, data_), + }; + ObstacleMap_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ObstacleMap_descriptor_, + ObstacleMap::default_instance_, + ObstacleMap_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ObstacleMap)); + Path_descriptor_ = file->message_type(5); + static const int Path_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Path, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Path, waypoints_), + }; + Path_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + Path_descriptor_, + Path::default_instance_, + Path_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Path, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Path, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(Path)); + PointCloudXYZI_descriptor_ = file->message_type(6); + static const int PointCloudXYZI_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI, points_), + }; + PointCloudXYZI_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + PointCloudXYZI_descriptor_, + PointCloudXYZI::default_instance_, + PointCloudXYZI_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(PointCloudXYZI)); + PointCloudXYZI_PointXYZI_descriptor_ = PointCloudXYZI_descriptor_->nested_type(0); + static const int PointCloudXYZI_PointXYZI_offsets_[4] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI_PointXYZI, x_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI_PointXYZI, y_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI_PointXYZI, z_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI_PointXYZI, intensity_), + }; + PointCloudXYZI_PointXYZI_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + PointCloudXYZI_PointXYZI_descriptor_, + PointCloudXYZI_PointXYZI::default_instance_, + PointCloudXYZI_PointXYZI_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI_PointXYZI, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI_PointXYZI, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(PointCloudXYZI_PointXYZI)); + PointCloudXYZRGB_descriptor_ = file->message_type(7); + static const int PointCloudXYZRGB_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB, points_), + }; + PointCloudXYZRGB_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + PointCloudXYZRGB_descriptor_, + PointCloudXYZRGB::default_instance_, + PointCloudXYZRGB_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(PointCloudXYZRGB)); + PointCloudXYZRGB_PointXYZRGB_descriptor_ = PointCloudXYZRGB_descriptor_->nested_type(0); + static const int PointCloudXYZRGB_PointXYZRGB_offsets_[4] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB_PointXYZRGB, x_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB_PointXYZRGB, y_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB_PointXYZRGB, z_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB_PointXYZRGB, rgb_), + }; + PointCloudXYZRGB_PointXYZRGB_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + PointCloudXYZRGB_PointXYZRGB_descriptor_, + PointCloudXYZRGB_PointXYZRGB::default_instance_, + PointCloudXYZRGB_PointXYZRGB_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB_PointXYZRGB, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB_PointXYZRGB, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(PointCloudXYZRGB_PointXYZRGB)); + RGBDImage_descriptor_ = file->message_type(8); + static const int RGBDImage_offsets_[21] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, cols_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, rows_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, step1_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, type1_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, imagedata1_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, step2_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, type2_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, imagedata2_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, camera_config_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, camera_type_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, roll_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, pitch_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, yaw_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, lon_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, lat_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, alt_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, ground_x_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, ground_y_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, ground_z_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, camera_matrix_), + }; + RGBDImage_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RGBDImage_descriptor_, + RGBDImage::default_instance_, + RGBDImage_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RGBDImage)); + Waypoint_descriptor_ = file->message_type(9); + static const int Waypoint_offsets_[6] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, x_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, y_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, z_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, roll_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, pitch_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, yaw_), + }; + Waypoint_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + Waypoint_descriptor_, + Waypoint::default_instance_, + Waypoint_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(Waypoint)); +} + +namespace { + +GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); +inline void protobuf_AssignDescriptorsOnce() { + ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, + &protobuf_AssignDesc_pixhawk_2eproto); +} + +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + HeaderInfo_descriptor_, &HeaderInfo::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + GLOverlay_descriptor_, &GLOverlay::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + Obstacle_descriptor_, &Obstacle::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ObstacleList_descriptor_, &ObstacleList::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ObstacleMap_descriptor_, &ObstacleMap::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + Path_descriptor_, &Path::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + PointCloudXYZI_descriptor_, &PointCloudXYZI::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + PointCloudXYZI_PointXYZI_descriptor_, &PointCloudXYZI_PointXYZI::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + PointCloudXYZRGB_descriptor_, &PointCloudXYZRGB::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + PointCloudXYZRGB_PointXYZRGB_descriptor_, &PointCloudXYZRGB_PointXYZRGB::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RGBDImage_descriptor_, &RGBDImage::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + Waypoint_descriptor_, &Waypoint::default_instance()); +} + +} // namespace + +void protobuf_ShutdownFile_pixhawk_2eproto() { + delete HeaderInfo::default_instance_; + delete HeaderInfo_reflection_; + delete GLOverlay::default_instance_; + delete GLOverlay_reflection_; + delete Obstacle::default_instance_; + delete Obstacle_reflection_; + delete ObstacleList::default_instance_; + delete ObstacleList_reflection_; + delete ObstacleMap::default_instance_; + delete ObstacleMap_reflection_; + delete Path::default_instance_; + delete Path_reflection_; + delete PointCloudXYZI::default_instance_; + delete PointCloudXYZI_reflection_; + delete PointCloudXYZI_PointXYZI::default_instance_; + delete PointCloudXYZI_PointXYZI_reflection_; + delete PointCloudXYZRGB::default_instance_; + delete PointCloudXYZRGB_reflection_; + delete PointCloudXYZRGB_PointXYZRGB::default_instance_; + delete PointCloudXYZRGB_PointXYZRGB_reflection_; + delete RGBDImage::default_instance_; + delete RGBDImage_reflection_; + delete Waypoint::default_instance_; + delete Waypoint_reflection_; +} + +void protobuf_AddDesc_pixhawk_2eproto() { + static bool already_here = false; + if (already_here) return; + already_here = true; + GOOGLE_PROTOBUF_VERIFY_VERSION; + + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + "\n\rpixhawk.proto\022\002px\"L\n\nHeaderInfo\022\024\n\014sou" + "rce_sysid\030\001 \002(\005\022\025\n\rsource_compid\030\002 \002(\005\022\021" + "\n\ttimestamp\030\003 \002(\001\"\377\004\n\tGLOverlay\022\036\n\006heade" + "r\030\001 \002(\0132\016.px.HeaderInfo\022\014\n\004name\030\002 \001(\t\022>\n" + "\023coordinateFrameType\030\003 \001(\0162!.px.GLOverla" + "y.CoordinateFrameType\022\020\n\010origin_x\030\004 \001(\001\022" + "\020\n\010origin_y\030\005 \001(\001\022\020\n\010origin_z\030\006 \001(\001\022\014\n\004d" + "ata\030\007 \001(\014\",\n\023CoordinateFrameType\022\n\n\006GLOB" + "AL\020\000\022\t\n\005LOCAL\020\001\"\333\001\n\004Mode\022\n\n\006POINTS\020\000\022\t\n\005" + "LINES\020\001\022\016\n\nLINE_STRIP\020\002\022\r\n\tLINE_LOOP\020\003\022\r" + "\n\tTRIANGLES\020\004\022\022\n\016TRIANGLE_STRIP\020\005\022\020\n\014TRI" + "ANGLE_FAN\020\006\022\t\n\005QUADS\020\007\022\016\n\nQUAD_STRIP\020\010\022\013" + "\n\007POLYGON\020\t\022\020\n\014SOLID_CIRCLE\020\n\022\017\n\013WIRE_CI" + "RCLE\020\013\022\016\n\nSOLID_CUBE\020\014\022\r\n\tWIRE_CUBE\020\r\"\263\001" + "\n\nIdentifier\022\007\n\003END\020\016\022\014\n\010VERTEX2F\020\017\022\014\n\010V" + "ERTEX3F\020\020\022\013\n\007ROTATEF\020\021\022\016\n\nTRANSLATEF\020\022\022\n" + "\n\006SCALEF\020\023\022\017\n\013PUSH_MATRIX\020\024\022\016\n\nPOP_MATRI" + "X\020\025\022\013\n\007COLOR3F\020\026\022\013\n\007COLOR4F\020\027\022\r\n\tPOINTSI" + "ZE\020\030\022\r\n\tLINEWIDTH\020\031\"Z\n\010Obstacle\022\t\n\001x\030\001 \001" + "(\002\022\t\n\001y\030\002 \001(\002\022\t\n\001z\030\003 \001(\002\022\016\n\006length\030\004 \001(\002" + "\022\r\n\005width\030\005 \001(\002\022\016\n\006height\030\006 \001(\002\"O\n\014Obsta" + "cleList\022\036\n\006header\030\001 \002(\0132\016.px.HeaderInfo\022" + "\037\n\tobstacles\030\002 \003(\0132\014.px.Obstacle\"\271\001\n\013Obs" + "tacleMap\022\036\n\006header\030\001 \002(\0132\016.px.HeaderInfo" + "\022\014\n\004type\030\002 \002(\005\022\022\n\nresolution\030\003 \001(\002\022\014\n\004ro" + "ws\030\004 \001(\005\022\014\n\004cols\030\005 \001(\005\022\r\n\005mapR0\030\006 \001(\005\022\r\n" + "\005mapC0\030\007 \001(\005\022\017\n\007arrayR0\030\010 \001(\005\022\017\n\007arrayC0" + "\030\t \001(\005\022\014\n\004data\030\n \001(\014\"G\n\004Path\022\036\n\006header\030\001" + " \002(\0132\016.px.HeaderInfo\022\037\n\twaypoints\030\002 \003(\0132" + "\014.px.Waypoint\"\237\001\n\016PointCloudXYZI\022\036\n\006head" + "er\030\001 \002(\0132\016.px.HeaderInfo\022,\n\006points\030\002 \003(\013" + "2\034.px.PointCloudXYZI.PointXYZI\032\?\n\tPointX" + "YZI\022\t\n\001x\030\001 \002(\002\022\t\n\001y\030\002 \002(\002\022\t\n\001z\030\003 \002(\002\022\021\n\t" + "intensity\030\004 \002(\002\"\241\001\n\020PointCloudXYZRGB\022\036\n\006" + "header\030\001 \002(\0132\016.px.HeaderInfo\0220\n\006points\030\002" + " \003(\0132 .px.PointCloudXYZRGB.PointXYZRGB\032;" + "\n\013PointXYZRGB\022\t\n\001x\030\001 \002(\002\022\t\n\001y\030\002 \002(\002\022\t\n\001z" + "\030\003 \002(\002\022\013\n\003rgb\030\004 \002(\002\"\365\002\n\tRGBDImage\022\036\n\006hea" + "der\030\001 \002(\0132\016.px.HeaderInfo\022\014\n\004cols\030\002 \002(\r\022" + "\014\n\004rows\030\003 \002(\r\022\r\n\005step1\030\004 \002(\r\022\r\n\005type1\030\005 " + "\002(\r\022\022\n\nimageData1\030\006 \002(\014\022\r\n\005step2\030\007 \002(\r\022\r" + "\n\005type2\030\010 \002(\r\022\022\n\nimageData2\030\t \002(\014\022\025\n\rcam" + "era_config\030\n \001(\r\022\023\n\013camera_type\030\013 \001(\r\022\014\n" + "\004roll\030\014 \001(\002\022\r\n\005pitch\030\r \001(\002\022\013\n\003yaw\030\016 \001(\002\022" + "\013\n\003lon\030\017 \001(\002\022\013\n\003lat\030\020 \001(\002\022\013\n\003alt\030\021 \001(\002\022\020" + "\n\010ground_x\030\022 \001(\002\022\020\n\010ground_y\030\023 \001(\002\022\020\n\010gr" + "ound_z\030\024 \001(\002\022\025\n\rcamera_matrix\030\025 \003(\002\"U\n\010W" + "aypoint\022\t\n\001x\030\001 \002(\001\022\t\n\001y\030\002 \002(\001\022\t\n\001z\030\003 \001(\001" + "\022\014\n\004roll\030\004 \001(\001\022\r\n\005pitch\030\005 \001(\001\022\013\n\003yaw\030\006 \001" + "(\001", 1962); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "pixhawk.proto", &protobuf_RegisterTypes); + HeaderInfo::default_instance_ = new HeaderInfo(); + GLOverlay::default_instance_ = new GLOverlay(); + Obstacle::default_instance_ = new Obstacle(); + ObstacleList::default_instance_ = new ObstacleList(); + ObstacleMap::default_instance_ = new ObstacleMap(); + Path::default_instance_ = new Path(); + PointCloudXYZI::default_instance_ = new PointCloudXYZI(); + PointCloudXYZI_PointXYZI::default_instance_ = new PointCloudXYZI_PointXYZI(); + PointCloudXYZRGB::default_instance_ = new PointCloudXYZRGB(); + PointCloudXYZRGB_PointXYZRGB::default_instance_ = new PointCloudXYZRGB_PointXYZRGB(); + RGBDImage::default_instance_ = new RGBDImage(); + Waypoint::default_instance_ = new Waypoint(); + HeaderInfo::default_instance_->InitAsDefaultInstance(); + GLOverlay::default_instance_->InitAsDefaultInstance(); + Obstacle::default_instance_->InitAsDefaultInstance(); + ObstacleList::default_instance_->InitAsDefaultInstance(); + ObstacleMap::default_instance_->InitAsDefaultInstance(); + Path::default_instance_->InitAsDefaultInstance(); + PointCloudXYZI::default_instance_->InitAsDefaultInstance(); + PointCloudXYZI_PointXYZI::default_instance_->InitAsDefaultInstance(); + PointCloudXYZRGB::default_instance_->InitAsDefaultInstance(); + PointCloudXYZRGB_PointXYZRGB::default_instance_->InitAsDefaultInstance(); + RGBDImage::default_instance_->InitAsDefaultInstance(); + Waypoint::default_instance_->InitAsDefaultInstance(); + ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_pixhawk_2eproto); +} + +// Force AddDescriptors() to be called at static initialization time. +struct StaticDescriptorInitializer_pixhawk_2eproto { + StaticDescriptorInitializer_pixhawk_2eproto() { + protobuf_AddDesc_pixhawk_2eproto(); + } +} static_descriptor_initializer_pixhawk_2eproto_; + + +// =================================================================== + +#ifndef _MSC_VER +const int HeaderInfo::kSourceSysidFieldNumber; +const int HeaderInfo::kSourceCompidFieldNumber; +const int HeaderInfo::kTimestampFieldNumber; +#endif // !_MSC_VER + +HeaderInfo::HeaderInfo() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void HeaderInfo::InitAsDefaultInstance() { +} + +HeaderInfo::HeaderInfo(const HeaderInfo& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void HeaderInfo::SharedCtor() { + _cached_size_ = 0; + source_sysid_ = 0; + source_compid_ = 0; + timestamp_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +HeaderInfo::~HeaderInfo() { + SharedDtor(); +} + +void HeaderInfo::SharedDtor() { + if (this != default_instance_) { + } +} + +void HeaderInfo::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* HeaderInfo::descriptor() { + protobuf_AssignDescriptorsOnce(); + return HeaderInfo_descriptor_; +} + +const HeaderInfo& HeaderInfo::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +HeaderInfo* HeaderInfo::default_instance_ = NULL; + +HeaderInfo* HeaderInfo::New() const { + return new HeaderInfo; +} + +void HeaderInfo::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + source_sysid_ = 0; + source_compid_ = 0; + timestamp_ = 0; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool HeaderInfo::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required int32 source_sysid = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &source_sysid_))); + set_has_source_sysid(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_source_compid; + break; + } + + // required int32 source_compid = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_source_compid: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &source_compid_))); + set_has_source_compid(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(25)) goto parse_timestamp; + break; + } + + // required double timestamp = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_timestamp: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, ×tamp_))); + set_has_timestamp(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void HeaderInfo::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required int32 source_sysid = 1; + if (has_source_sysid()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->source_sysid(), output); + } + + // required int32 source_compid = 2; + if (has_source_compid()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->source_compid(), output); + } + + // required double timestamp = 3; + if (has_timestamp()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(3, this->timestamp(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* HeaderInfo::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required int32 source_sysid = 1; + if (has_source_sysid()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->source_sysid(), target); + } + + // required int32 source_compid = 2; + if (has_source_compid()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->source_compid(), target); + } + + // required double timestamp = 3; + if (has_timestamp()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(3, this->timestamp(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int HeaderInfo::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required int32 source_sysid = 1; + if (has_source_sysid()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->source_sysid()); + } + + // required int32 source_compid = 2; + if (has_source_compid()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->source_compid()); + } + + // required double timestamp = 3; + if (has_timestamp()) { + total_size += 1 + 8; + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void HeaderInfo::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const HeaderInfo* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void HeaderInfo::MergeFrom(const HeaderInfo& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_source_sysid()) { + set_source_sysid(from.source_sysid()); + } + if (from.has_source_compid()) { + set_source_compid(from.source_compid()); + } + if (from.has_timestamp()) { + set_timestamp(from.timestamp()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void HeaderInfo::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void HeaderInfo::CopyFrom(const HeaderInfo& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool HeaderInfo::IsInitialized() const { + if ((_has_bits_[0] & 0x00000007) != 0x00000007) return false; + + return true; +} + +void HeaderInfo::Swap(HeaderInfo* other) { + if (other != this) { + std::swap(source_sysid_, other->source_sysid_); + std::swap(source_compid_, other->source_compid_); + std::swap(timestamp_, other->timestamp_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata HeaderInfo::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = HeaderInfo_descriptor_; + metadata.reflection = HeaderInfo_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* GLOverlay_CoordinateFrameType_descriptor() { + protobuf_AssignDescriptorsOnce(); + return GLOverlay_CoordinateFrameType_descriptor_; +} +bool GLOverlay_CoordinateFrameType_IsValid(int value) { + switch(value) { + case 0: + case 1: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const GLOverlay_CoordinateFrameType GLOverlay::GLOBAL; +const GLOverlay_CoordinateFrameType GLOverlay::LOCAL; +const GLOverlay_CoordinateFrameType GLOverlay::CoordinateFrameType_MIN; +const GLOverlay_CoordinateFrameType GLOverlay::CoordinateFrameType_MAX; +const int GLOverlay::CoordinateFrameType_ARRAYSIZE; +#endif // _MSC_VER +const ::google::protobuf::EnumDescriptor* GLOverlay_Mode_descriptor() { + protobuf_AssignDescriptorsOnce(); + return GLOverlay_Mode_descriptor_; +} +bool GLOverlay_Mode_IsValid(int value) { + switch(value) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const GLOverlay_Mode GLOverlay::POINTS; +const GLOverlay_Mode GLOverlay::LINES; +const GLOverlay_Mode GLOverlay::LINE_STRIP; +const GLOverlay_Mode GLOverlay::LINE_LOOP; +const GLOverlay_Mode GLOverlay::TRIANGLES; +const GLOverlay_Mode GLOverlay::TRIANGLE_STRIP; +const GLOverlay_Mode GLOverlay::TRIANGLE_FAN; +const GLOverlay_Mode GLOverlay::QUADS; +const GLOverlay_Mode GLOverlay::QUAD_STRIP; +const GLOverlay_Mode GLOverlay::POLYGON; +const GLOverlay_Mode GLOverlay::SOLID_CIRCLE; +const GLOverlay_Mode GLOverlay::WIRE_CIRCLE; +const GLOverlay_Mode GLOverlay::SOLID_CUBE; +const GLOverlay_Mode GLOverlay::WIRE_CUBE; +const GLOverlay_Mode GLOverlay::Mode_MIN; +const GLOverlay_Mode GLOverlay::Mode_MAX; +const int GLOverlay::Mode_ARRAYSIZE; +#endif // _MSC_VER +const ::google::protobuf::EnumDescriptor* GLOverlay_Identifier_descriptor() { + protobuf_AssignDescriptorsOnce(); + return GLOverlay_Identifier_descriptor_; +} +bool GLOverlay_Identifier_IsValid(int value) { + switch(value) { + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const GLOverlay_Identifier GLOverlay::END; +const GLOverlay_Identifier GLOverlay::VERTEX2F; +const GLOverlay_Identifier GLOverlay::VERTEX3F; +const GLOverlay_Identifier GLOverlay::ROTATEF; +const GLOverlay_Identifier GLOverlay::TRANSLATEF; +const GLOverlay_Identifier GLOverlay::SCALEF; +const GLOverlay_Identifier GLOverlay::PUSH_MATRIX; +const GLOverlay_Identifier GLOverlay::POP_MATRIX; +const GLOverlay_Identifier GLOverlay::COLOR3F; +const GLOverlay_Identifier GLOverlay::COLOR4F; +const GLOverlay_Identifier GLOverlay::POINTSIZE; +const GLOverlay_Identifier GLOverlay::LINEWIDTH; +const GLOverlay_Identifier GLOverlay::Identifier_MIN; +const GLOverlay_Identifier GLOverlay::Identifier_MAX; +const int GLOverlay::Identifier_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int GLOverlay::kHeaderFieldNumber; +const int GLOverlay::kNameFieldNumber; +const int GLOverlay::kCoordinateFrameTypeFieldNumber; +const int GLOverlay::kOriginXFieldNumber; +const int GLOverlay::kOriginYFieldNumber; +const int GLOverlay::kOriginZFieldNumber; +const int GLOverlay::kDataFieldNumber; +#endif // !_MSC_VER + +GLOverlay::GLOverlay() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void GLOverlay::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +GLOverlay::GLOverlay(const GLOverlay& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void GLOverlay::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + coordinateframetype_ = 0; + origin_x_ = 0; + origin_y_ = 0; + origin_z_ = 0; + data_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +GLOverlay::~GLOverlay() { + SharedDtor(); +} + +void GLOverlay::SharedDtor() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (data_ != &::google::protobuf::internal::kEmptyString) { + delete data_; + } + if (this != default_instance_) { + delete header_; + } +} + +void GLOverlay::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* GLOverlay::descriptor() { + protobuf_AssignDescriptorsOnce(); + return GLOverlay_descriptor_; +} + +const GLOverlay& GLOverlay::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +GLOverlay* GLOverlay::default_instance_ = NULL; + +GLOverlay* GLOverlay::New() const { + return new GLOverlay; +} + +void GLOverlay::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + coordinateframetype_ = 0; + origin_x_ = 0; + origin_y_ = 0; + origin_z_ = 0; + if (has_data()) { + if (data_ != &::google::protobuf::internal::kEmptyString) { + data_->clear(); + } + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool GLOverlay::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_name; + break; + } + + // optional string name = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_name: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(24)) goto parse_coordinateFrameType; + break; + } + + // optional .px.GLOverlay.CoordinateFrameType coordinateFrameType = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_coordinateFrameType: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::px::GLOverlay_CoordinateFrameType_IsValid(value)) { + set_coordinateframetype(static_cast< ::px::GLOverlay_CoordinateFrameType >(value)); + } else { + mutable_unknown_fields()->AddVarint(3, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(33)) goto parse_origin_x; + break; + } + + // optional double origin_x = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_origin_x: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &origin_x_))); + set_has_origin_x(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(41)) goto parse_origin_y; + break; + } + + // optional double origin_y = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_origin_y: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &origin_y_))); + set_has_origin_y(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(49)) goto parse_origin_z; + break; + } + + // optional double origin_z = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_origin_z: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &origin_z_))); + set_has_origin_z(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(58)) goto parse_data; + break; + } + + // optional bytes data = 7; + case 7: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_data: + DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( + input, this->mutable_data())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void GLOverlay::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // optional string name = 2; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->name(), output); + } + + // optional .px.GLOverlay.CoordinateFrameType coordinateFrameType = 3; + if (has_coordinateframetype()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 3, this->coordinateframetype(), output); + } + + // optional double origin_x = 4; + if (has_origin_x()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(4, this->origin_x(), output); + } + + // optional double origin_y = 5; + if (has_origin_y()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(5, this->origin_y(), output); + } + + // optional double origin_z = 6; + if (has_origin_z()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->origin_z(), output); + } + + // optional bytes data = 7; + if (has_data()) { + ::google::protobuf::internal::WireFormatLite::WriteBytes( + 7, this->data(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* GLOverlay::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // optional string name = 2; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->name(), target); + } + + // optional .px.GLOverlay.CoordinateFrameType coordinateFrameType = 3; + if (has_coordinateframetype()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 3, this->coordinateframetype(), target); + } + + // optional double origin_x = 4; + if (has_origin_x()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(4, this->origin_x(), target); + } + + // optional double origin_y = 5; + if (has_origin_y()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(5, this->origin_y(), target); + } + + // optional double origin_z = 6; + if (has_origin_z()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->origin_z(), target); + } + + // optional bytes data = 7; + if (has_data()) { + target = + ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( + 7, this->data(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int GLOverlay::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + // optional string name = 2; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + // optional .px.GLOverlay.CoordinateFrameType coordinateFrameType = 3; + if (has_coordinateframetype()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->coordinateframetype()); + } + + // optional double origin_x = 4; + if (has_origin_x()) { + total_size += 1 + 8; + } + + // optional double origin_y = 5; + if (has_origin_y()) { + total_size += 1 + 8; + } + + // optional double origin_z = 6; + if (has_origin_z()) { + total_size += 1 + 8; + } + + // optional bytes data = 7; + if (has_data()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::BytesSize( + this->data()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void GLOverlay::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const GLOverlay* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void GLOverlay::MergeFrom(const GLOverlay& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + if (from.has_name()) { + set_name(from.name()); + } + if (from.has_coordinateframetype()) { + set_coordinateframetype(from.coordinateframetype()); + } + if (from.has_origin_x()) { + set_origin_x(from.origin_x()); + } + if (from.has_origin_y()) { + set_origin_y(from.origin_y()); + } + if (from.has_origin_z()) { + set_origin_z(from.origin_z()); + } + if (from.has_data()) { + set_data(from.data()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void GLOverlay::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void GLOverlay::CopyFrom(const GLOverlay& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool GLOverlay::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + return true; +} + +void GLOverlay::Swap(GLOverlay* other) { + if (other != this) { + std::swap(header_, other->header_); + std::swap(name_, other->name_); + std::swap(coordinateframetype_, other->coordinateframetype_); + std::swap(origin_x_, other->origin_x_); + std::swap(origin_y_, other->origin_y_); + std::swap(origin_z_, other->origin_z_); + std::swap(data_, other->data_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata GLOverlay::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = GLOverlay_descriptor_; + metadata.reflection = GLOverlay_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int Obstacle::kXFieldNumber; +const int Obstacle::kYFieldNumber; +const int Obstacle::kZFieldNumber; +const int Obstacle::kLengthFieldNumber; +const int Obstacle::kWidthFieldNumber; +const int Obstacle::kHeightFieldNumber; +#endif // !_MSC_VER + +Obstacle::Obstacle() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void Obstacle::InitAsDefaultInstance() { +} + +Obstacle::Obstacle(const Obstacle& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void Obstacle::SharedCtor() { + _cached_size_ = 0; + x_ = 0; + y_ = 0; + z_ = 0; + length_ = 0; + width_ = 0; + height_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +Obstacle::~Obstacle() { + SharedDtor(); +} + +void Obstacle::SharedDtor() { + if (this != default_instance_) { + } +} + +void Obstacle::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* Obstacle::descriptor() { + protobuf_AssignDescriptorsOnce(); + return Obstacle_descriptor_; +} + +const Obstacle& Obstacle::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +Obstacle* Obstacle::default_instance_ = NULL; + +Obstacle* Obstacle::New() const { + return new Obstacle; +} + +void Obstacle::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + x_ = 0; + y_ = 0; + z_ = 0; + length_ = 0; + width_ = 0; + height_ = 0; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool Obstacle::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional float x = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &x_))); + set_has_x(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(21)) goto parse_y; + break; + } + + // optional float y = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_y: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &y_))); + set_has_y(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(29)) goto parse_z; + break; + } + + // optional float z = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_z: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &z_))); + set_has_z(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(37)) goto parse_length; + break; + } + + // optional float length = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_length: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &length_))); + set_has_length(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(45)) goto parse_width; + break; + } + + // optional float width = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_width: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &width_))); + set_has_width(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(53)) goto parse_height; + break; + } + + // optional float height = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_height: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &height_))); + set_has_height(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void Obstacle::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional float x = 1; + if (has_x()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->x(), output); + } + + // optional float y = 2; + if (has_y()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(2, this->y(), output); + } + + // optional float z = 3; + if (has_z()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->z(), output); + } + + // optional float length = 4; + if (has_length()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(4, this->length(), output); + } + + // optional float width = 5; + if (has_width()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(5, this->width(), output); + } + + // optional float height = 6; + if (has_height()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(6, this->height(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* Obstacle::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional float x = 1; + if (has_x()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(1, this->x(), target); + } + + // optional float y = 2; + if (has_y()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(2, this->y(), target); + } + + // optional float z = 3; + if (has_z()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(3, this->z(), target); + } + + // optional float length = 4; + if (has_length()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(4, this->length(), target); + } + + // optional float width = 5; + if (has_width()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(5, this->width(), target); + } + + // optional float height = 6; + if (has_height()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(6, this->height(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int Obstacle::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional float x = 1; + if (has_x()) { + total_size += 1 + 4; + } + + // optional float y = 2; + if (has_y()) { + total_size += 1 + 4; + } + + // optional float z = 3; + if (has_z()) { + total_size += 1 + 4; + } + + // optional float length = 4; + if (has_length()) { + total_size += 1 + 4; + } + + // optional float width = 5; + if (has_width()) { + total_size += 1 + 4; + } + + // optional float height = 6; + if (has_height()) { + total_size += 1 + 4; + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void Obstacle::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const Obstacle* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void Obstacle::MergeFrom(const Obstacle& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_x()) { + set_x(from.x()); + } + if (from.has_y()) { + set_y(from.y()); + } + if (from.has_z()) { + set_z(from.z()); + } + if (from.has_length()) { + set_length(from.length()); + } + if (from.has_width()) { + set_width(from.width()); + } + if (from.has_height()) { + set_height(from.height()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void Obstacle::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Obstacle::CopyFrom(const Obstacle& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Obstacle::IsInitialized() const { + + return true; +} + +void Obstacle::Swap(Obstacle* other) { + if (other != this) { + std::swap(x_, other->x_); + std::swap(y_, other->y_); + std::swap(z_, other->z_); + std::swap(length_, other->length_); + std::swap(width_, other->width_); + std::swap(height_, other->height_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata Obstacle::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = Obstacle_descriptor_; + metadata.reflection = Obstacle_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ObstacleList::kHeaderFieldNumber; +const int ObstacleList::kObstaclesFieldNumber; +#endif // !_MSC_VER + +ObstacleList::ObstacleList() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ObstacleList::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +ObstacleList::ObstacleList(const ObstacleList& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ObstacleList::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ObstacleList::~ObstacleList() { + SharedDtor(); +} + +void ObstacleList::SharedDtor() { + if (this != default_instance_) { + delete header_; + } +} + +void ObstacleList::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ObstacleList::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ObstacleList_descriptor_; +} + +const ObstacleList& ObstacleList::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +ObstacleList* ObstacleList::default_instance_ = NULL; + +ObstacleList* ObstacleList::New() const { + return new ObstacleList; +} + +void ObstacleList::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + } + obstacles_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ObstacleList::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_obstacles; + break; + } + + // repeated .px.Obstacle obstacles = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_obstacles: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_obstacles())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_obstacles; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ObstacleList::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // repeated .px.Obstacle obstacles = 2; + for (int i = 0; i < this->obstacles_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->obstacles(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ObstacleList::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // repeated .px.Obstacle obstacles = 2; + for (int i = 0; i < this->obstacles_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->obstacles(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ObstacleList::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + } + // repeated .px.Obstacle obstacles = 2; + total_size += 1 * this->obstacles_size(); + for (int i = 0; i < this->obstacles_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->obstacles(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ObstacleList::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ObstacleList* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ObstacleList::MergeFrom(const ObstacleList& from) { + GOOGLE_CHECK_NE(&from, this); + obstacles_.MergeFrom(from.obstacles_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ObstacleList::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ObstacleList::CopyFrom(const ObstacleList& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ObstacleList::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + return true; +} + +void ObstacleList::Swap(ObstacleList* other) { + if (other != this) { + std::swap(header_, other->header_); + obstacles_.Swap(&other->obstacles_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ObstacleList::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ObstacleList_descriptor_; + metadata.reflection = ObstacleList_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ObstacleMap::kHeaderFieldNumber; +const int ObstacleMap::kTypeFieldNumber; +const int ObstacleMap::kResolutionFieldNumber; +const int ObstacleMap::kRowsFieldNumber; +const int ObstacleMap::kColsFieldNumber; +const int ObstacleMap::kMapR0FieldNumber; +const int ObstacleMap::kMapC0FieldNumber; +const int ObstacleMap::kArrayR0FieldNumber; +const int ObstacleMap::kArrayC0FieldNumber; +const int ObstacleMap::kDataFieldNumber; +#endif // !_MSC_VER + +ObstacleMap::ObstacleMap() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ObstacleMap::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +ObstacleMap::ObstacleMap(const ObstacleMap& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ObstacleMap::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + type_ = 0; + resolution_ = 0; + rows_ = 0; + cols_ = 0; + mapr0_ = 0; + mapc0_ = 0; + arrayr0_ = 0; + arrayc0_ = 0; + data_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ObstacleMap::~ObstacleMap() { + SharedDtor(); +} + +void ObstacleMap::SharedDtor() { + if (data_ != &::google::protobuf::internal::kEmptyString) { + delete data_; + } + if (this != default_instance_) { + delete header_; + } +} + +void ObstacleMap::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ObstacleMap::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ObstacleMap_descriptor_; +} + +const ObstacleMap& ObstacleMap::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +ObstacleMap* ObstacleMap::default_instance_ = NULL; + +ObstacleMap* ObstacleMap::New() const { + return new ObstacleMap; +} + +void ObstacleMap::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + type_ = 0; + resolution_ = 0; + rows_ = 0; + cols_ = 0; + mapr0_ = 0; + mapc0_ = 0; + arrayr0_ = 0; + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + arrayc0_ = 0; + if (has_data()) { + if (data_ != &::google::protobuf::internal::kEmptyString) { + data_->clear(); + } + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ObstacleMap::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_type; + break; + } + + // required int32 type = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_type: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &type_))); + set_has_type(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(29)) goto parse_resolution; + break; + } + + // optional float resolution = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_resolution: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &resolution_))); + set_has_resolution(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(32)) goto parse_rows; + break; + } + + // optional int32 rows = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_rows: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &rows_))); + set_has_rows(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(40)) goto parse_cols; + break; + } + + // optional int32 cols = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_cols: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &cols_))); + set_has_cols(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(48)) goto parse_mapR0; + break; + } + + // optional int32 mapR0 = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_mapR0: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &mapr0_))); + set_has_mapr0(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(56)) goto parse_mapC0; + break; + } + + // optional int32 mapC0 = 7; + case 7: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_mapC0: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &mapc0_))); + set_has_mapc0(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(64)) goto parse_arrayR0; + break; + } + + // optional int32 arrayR0 = 8; + case 8: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_arrayR0: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &arrayr0_))); + set_has_arrayr0(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(72)) goto parse_arrayC0; + break; + } + + // optional int32 arrayC0 = 9; + case 9: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_arrayC0: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &arrayc0_))); + set_has_arrayc0(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(82)) goto parse_data; + break; + } + + // optional bytes data = 10; + case 10: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_data: + DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( + input, this->mutable_data())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ObstacleMap::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // required int32 type = 2; + if (has_type()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->type(), output); + } + + // optional float resolution = 3; + if (has_resolution()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->resolution(), output); + } + + // optional int32 rows = 4; + if (has_rows()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(4, this->rows(), output); + } + + // optional int32 cols = 5; + if (has_cols()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(5, this->cols(), output); + } + + // optional int32 mapR0 = 6; + if (has_mapr0()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(6, this->mapr0(), output); + } + + // optional int32 mapC0 = 7; + if (has_mapc0()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(7, this->mapc0(), output); + } + + // optional int32 arrayR0 = 8; + if (has_arrayr0()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(8, this->arrayr0(), output); + } + + // optional int32 arrayC0 = 9; + if (has_arrayc0()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(9, this->arrayc0(), output); + } + + // optional bytes data = 10; + if (has_data()) { + ::google::protobuf::internal::WireFormatLite::WriteBytes( + 10, this->data(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ObstacleMap::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // required int32 type = 2; + if (has_type()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->type(), target); + } + + // optional float resolution = 3; + if (has_resolution()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(3, this->resolution(), target); + } + + // optional int32 rows = 4; + if (has_rows()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(4, this->rows(), target); + } + + // optional int32 cols = 5; + if (has_cols()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(5, this->cols(), target); + } + + // optional int32 mapR0 = 6; + if (has_mapr0()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(6, this->mapr0(), target); + } + + // optional int32 mapC0 = 7; + if (has_mapc0()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(7, this->mapc0(), target); + } + + // optional int32 arrayR0 = 8; + if (has_arrayr0()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(8, this->arrayr0(), target); + } + + // optional int32 arrayC0 = 9; + if (has_arrayc0()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(9, this->arrayc0(), target); + } + + // optional bytes data = 10; + if (has_data()) { + target = + ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( + 10, this->data(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ObstacleMap::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + // required int32 type = 2; + if (has_type()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->type()); + } + + // optional float resolution = 3; + if (has_resolution()) { + total_size += 1 + 4; + } + + // optional int32 rows = 4; + if (has_rows()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->rows()); + } + + // optional int32 cols = 5; + if (has_cols()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->cols()); + } + + // optional int32 mapR0 = 6; + if (has_mapr0()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->mapr0()); + } + + // optional int32 mapC0 = 7; + if (has_mapc0()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->mapc0()); + } + + // optional int32 arrayR0 = 8; + if (has_arrayr0()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->arrayr0()); + } + + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + // optional int32 arrayC0 = 9; + if (has_arrayc0()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->arrayc0()); + } + + // optional bytes data = 10; + if (has_data()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::BytesSize( + this->data()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ObstacleMap::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ObstacleMap* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ObstacleMap::MergeFrom(const ObstacleMap& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + if (from.has_type()) { + set_type(from.type()); + } + if (from.has_resolution()) { + set_resolution(from.resolution()); + } + if (from.has_rows()) { + set_rows(from.rows()); + } + if (from.has_cols()) { + set_cols(from.cols()); + } + if (from.has_mapr0()) { + set_mapr0(from.mapr0()); + } + if (from.has_mapc0()) { + set_mapc0(from.mapc0()); + } + if (from.has_arrayr0()) { + set_arrayr0(from.arrayr0()); + } + } + if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) { + if (from.has_arrayc0()) { + set_arrayc0(from.arrayc0()); + } + if (from.has_data()) { + set_data(from.data()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ObstacleMap::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ObstacleMap::CopyFrom(const ObstacleMap& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ObstacleMap::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + return true; +} + +void ObstacleMap::Swap(ObstacleMap* other) { + if (other != this) { + std::swap(header_, other->header_); + std::swap(type_, other->type_); + std::swap(resolution_, other->resolution_); + std::swap(rows_, other->rows_); + std::swap(cols_, other->cols_); + std::swap(mapr0_, other->mapr0_); + std::swap(mapc0_, other->mapc0_); + std::swap(arrayr0_, other->arrayr0_); + std::swap(arrayc0_, other->arrayc0_); + std::swap(data_, other->data_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ObstacleMap::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ObstacleMap_descriptor_; + metadata.reflection = ObstacleMap_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int Path::kHeaderFieldNumber; +const int Path::kWaypointsFieldNumber; +#endif // !_MSC_VER + +Path::Path() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void Path::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +Path::Path(const Path& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void Path::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +Path::~Path() { + SharedDtor(); +} + +void Path::SharedDtor() { + if (this != default_instance_) { + delete header_; + } +} + +void Path::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* Path::descriptor() { + protobuf_AssignDescriptorsOnce(); + return Path_descriptor_; +} + +const Path& Path::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +Path* Path::default_instance_ = NULL; + +Path* Path::New() const { + return new Path; +} + +void Path::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + } + waypoints_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool Path::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_waypoints; + break; + } + + // repeated .px.Waypoint waypoints = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_waypoints: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_waypoints())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_waypoints; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void Path::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // repeated .px.Waypoint waypoints = 2; + for (int i = 0; i < this->waypoints_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->waypoints(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* Path::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // repeated .px.Waypoint waypoints = 2; + for (int i = 0; i < this->waypoints_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->waypoints(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int Path::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + } + // repeated .px.Waypoint waypoints = 2; + total_size += 1 * this->waypoints_size(); + for (int i = 0; i < this->waypoints_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->waypoints(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void Path::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const Path* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void Path::MergeFrom(const Path& from) { + GOOGLE_CHECK_NE(&from, this); + waypoints_.MergeFrom(from.waypoints_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void Path::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Path::CopyFrom(const Path& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Path::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + for (int i = 0; i < waypoints_size(); i++) { + if (!this->waypoints(i).IsInitialized()) return false; + } + return true; +} + +void Path::Swap(Path* other) { + if (other != this) { + std::swap(header_, other->header_); + waypoints_.Swap(&other->waypoints_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata Path::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = Path_descriptor_; + metadata.reflection = Path_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int PointCloudXYZI_PointXYZI::kXFieldNumber; +const int PointCloudXYZI_PointXYZI::kYFieldNumber; +const int PointCloudXYZI_PointXYZI::kZFieldNumber; +const int PointCloudXYZI_PointXYZI::kIntensityFieldNumber; +#endif // !_MSC_VER + +PointCloudXYZI_PointXYZI::PointCloudXYZI_PointXYZI() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void PointCloudXYZI_PointXYZI::InitAsDefaultInstance() { +} + +PointCloudXYZI_PointXYZI::PointCloudXYZI_PointXYZI(const PointCloudXYZI_PointXYZI& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void PointCloudXYZI_PointXYZI::SharedCtor() { + _cached_size_ = 0; + x_ = 0; + y_ = 0; + z_ = 0; + intensity_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +PointCloudXYZI_PointXYZI::~PointCloudXYZI_PointXYZI() { + SharedDtor(); +} + +void PointCloudXYZI_PointXYZI::SharedDtor() { + if (this != default_instance_) { + } +} + +void PointCloudXYZI_PointXYZI::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* PointCloudXYZI_PointXYZI::descriptor() { + protobuf_AssignDescriptorsOnce(); + return PointCloudXYZI_PointXYZI_descriptor_; +} + +const PointCloudXYZI_PointXYZI& PointCloudXYZI_PointXYZI::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +PointCloudXYZI_PointXYZI* PointCloudXYZI_PointXYZI::default_instance_ = NULL; + +PointCloudXYZI_PointXYZI* PointCloudXYZI_PointXYZI::New() const { + return new PointCloudXYZI_PointXYZI; +} + +void PointCloudXYZI_PointXYZI::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + x_ = 0; + y_ = 0; + z_ = 0; + intensity_ = 0; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool PointCloudXYZI_PointXYZI::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required float x = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &x_))); + set_has_x(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(21)) goto parse_y; + break; + } + + // required float y = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_y: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &y_))); + set_has_y(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(29)) goto parse_z; + break; + } + + // required float z = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_z: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &z_))); + set_has_z(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(37)) goto parse_intensity; + break; + } + + // required float intensity = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_intensity: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &intensity_))); + set_has_intensity(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void PointCloudXYZI_PointXYZI::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required float x = 1; + if (has_x()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->x(), output); + } + + // required float y = 2; + if (has_y()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(2, this->y(), output); + } + + // required float z = 3; + if (has_z()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->z(), output); + } + + // required float intensity = 4; + if (has_intensity()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(4, this->intensity(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* PointCloudXYZI_PointXYZI::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required float x = 1; + if (has_x()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(1, this->x(), target); + } + + // required float y = 2; + if (has_y()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(2, this->y(), target); + } + + // required float z = 3; + if (has_z()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(3, this->z(), target); + } + + // required float intensity = 4; + if (has_intensity()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(4, this->intensity(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int PointCloudXYZI_PointXYZI::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required float x = 1; + if (has_x()) { + total_size += 1 + 4; + } + + // required float y = 2; + if (has_y()) { + total_size += 1 + 4; + } + + // required float z = 3; + if (has_z()) { + total_size += 1 + 4; + } + + // required float intensity = 4; + if (has_intensity()) { + total_size += 1 + 4; + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void PointCloudXYZI_PointXYZI::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const PointCloudXYZI_PointXYZI* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void PointCloudXYZI_PointXYZI::MergeFrom(const PointCloudXYZI_PointXYZI& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_x()) { + set_x(from.x()); + } + if (from.has_y()) { + set_y(from.y()); + } + if (from.has_z()) { + set_z(from.z()); + } + if (from.has_intensity()) { + set_intensity(from.intensity()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void PointCloudXYZI_PointXYZI::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void PointCloudXYZI_PointXYZI::CopyFrom(const PointCloudXYZI_PointXYZI& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool PointCloudXYZI_PointXYZI::IsInitialized() const { + if ((_has_bits_[0] & 0x0000000f) != 0x0000000f) return false; + + return true; +} + +void PointCloudXYZI_PointXYZI::Swap(PointCloudXYZI_PointXYZI* other) { + if (other != this) { + std::swap(x_, other->x_); + std::swap(y_, other->y_); + std::swap(z_, other->z_); + std::swap(intensity_, other->intensity_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata PointCloudXYZI_PointXYZI::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = PointCloudXYZI_PointXYZI_descriptor_; + metadata.reflection = PointCloudXYZI_PointXYZI_reflection_; + return metadata; +} + + +// ------------------------------------------------------------------- + +#ifndef _MSC_VER +const int PointCloudXYZI::kHeaderFieldNumber; +const int PointCloudXYZI::kPointsFieldNumber; +#endif // !_MSC_VER + +PointCloudXYZI::PointCloudXYZI() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void PointCloudXYZI::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +PointCloudXYZI::PointCloudXYZI(const PointCloudXYZI& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void PointCloudXYZI::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +PointCloudXYZI::~PointCloudXYZI() { + SharedDtor(); +} + +void PointCloudXYZI::SharedDtor() { + if (this != default_instance_) { + delete header_; + } +} + +void PointCloudXYZI::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* PointCloudXYZI::descriptor() { + protobuf_AssignDescriptorsOnce(); + return PointCloudXYZI_descriptor_; +} + +const PointCloudXYZI& PointCloudXYZI::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +PointCloudXYZI* PointCloudXYZI::default_instance_ = NULL; + +PointCloudXYZI* PointCloudXYZI::New() const { + return new PointCloudXYZI; +} + +void PointCloudXYZI::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + } + points_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool PointCloudXYZI::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_points; + break; + } + + // repeated .px.PointCloudXYZI.PointXYZI points = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_points: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_points())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_points; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void PointCloudXYZI::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // repeated .px.PointCloudXYZI.PointXYZI points = 2; + for (int i = 0; i < this->points_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->points(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* PointCloudXYZI::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // repeated .px.PointCloudXYZI.PointXYZI points = 2; + for (int i = 0; i < this->points_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->points(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int PointCloudXYZI::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + } + // repeated .px.PointCloudXYZI.PointXYZI points = 2; + total_size += 1 * this->points_size(); + for (int i = 0; i < this->points_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->points(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void PointCloudXYZI::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const PointCloudXYZI* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void PointCloudXYZI::MergeFrom(const PointCloudXYZI& from) { + GOOGLE_CHECK_NE(&from, this); + points_.MergeFrom(from.points_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void PointCloudXYZI::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void PointCloudXYZI::CopyFrom(const PointCloudXYZI& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool PointCloudXYZI::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + for (int i = 0; i < points_size(); i++) { + if (!this->points(i).IsInitialized()) return false; + } + return true; +} + +void PointCloudXYZI::Swap(PointCloudXYZI* other) { + if (other != this) { + std::swap(header_, other->header_); + points_.Swap(&other->points_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata PointCloudXYZI::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = PointCloudXYZI_descriptor_; + metadata.reflection = PointCloudXYZI_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int PointCloudXYZRGB_PointXYZRGB::kXFieldNumber; +const int PointCloudXYZRGB_PointXYZRGB::kYFieldNumber; +const int PointCloudXYZRGB_PointXYZRGB::kZFieldNumber; +const int PointCloudXYZRGB_PointXYZRGB::kRgbFieldNumber; +#endif // !_MSC_VER + +PointCloudXYZRGB_PointXYZRGB::PointCloudXYZRGB_PointXYZRGB() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void PointCloudXYZRGB_PointXYZRGB::InitAsDefaultInstance() { +} + +PointCloudXYZRGB_PointXYZRGB::PointCloudXYZRGB_PointXYZRGB(const PointCloudXYZRGB_PointXYZRGB& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void PointCloudXYZRGB_PointXYZRGB::SharedCtor() { + _cached_size_ = 0; + x_ = 0; + y_ = 0; + z_ = 0; + rgb_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +PointCloudXYZRGB_PointXYZRGB::~PointCloudXYZRGB_PointXYZRGB() { + SharedDtor(); +} + +void PointCloudXYZRGB_PointXYZRGB::SharedDtor() { + if (this != default_instance_) { + } +} + +void PointCloudXYZRGB_PointXYZRGB::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* PointCloudXYZRGB_PointXYZRGB::descriptor() { + protobuf_AssignDescriptorsOnce(); + return PointCloudXYZRGB_PointXYZRGB_descriptor_; +} + +const PointCloudXYZRGB_PointXYZRGB& PointCloudXYZRGB_PointXYZRGB::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +PointCloudXYZRGB_PointXYZRGB* PointCloudXYZRGB_PointXYZRGB::default_instance_ = NULL; + +PointCloudXYZRGB_PointXYZRGB* PointCloudXYZRGB_PointXYZRGB::New() const { + return new PointCloudXYZRGB_PointXYZRGB; +} + +void PointCloudXYZRGB_PointXYZRGB::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + x_ = 0; + y_ = 0; + z_ = 0; + rgb_ = 0; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool PointCloudXYZRGB_PointXYZRGB::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required float x = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &x_))); + set_has_x(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(21)) goto parse_y; + break; + } + + // required float y = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_y: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &y_))); + set_has_y(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(29)) goto parse_z; + break; + } + + // required float z = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_z: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &z_))); + set_has_z(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(37)) goto parse_rgb; + break; + } + + // required float rgb = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_rgb: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &rgb_))); + set_has_rgb(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void PointCloudXYZRGB_PointXYZRGB::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required float x = 1; + if (has_x()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->x(), output); + } + + // required float y = 2; + if (has_y()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(2, this->y(), output); + } + + // required float z = 3; + if (has_z()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->z(), output); + } + + // required float rgb = 4; + if (has_rgb()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(4, this->rgb(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* PointCloudXYZRGB_PointXYZRGB::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required float x = 1; + if (has_x()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(1, this->x(), target); + } + + // required float y = 2; + if (has_y()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(2, this->y(), target); + } + + // required float z = 3; + if (has_z()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(3, this->z(), target); + } + + // required float rgb = 4; + if (has_rgb()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(4, this->rgb(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int PointCloudXYZRGB_PointXYZRGB::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required float x = 1; + if (has_x()) { + total_size += 1 + 4; + } + + // required float y = 2; + if (has_y()) { + total_size += 1 + 4; + } + + // required float z = 3; + if (has_z()) { + total_size += 1 + 4; + } + + // required float rgb = 4; + if (has_rgb()) { + total_size += 1 + 4; + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void PointCloudXYZRGB_PointXYZRGB::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const PointCloudXYZRGB_PointXYZRGB* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void PointCloudXYZRGB_PointXYZRGB::MergeFrom(const PointCloudXYZRGB_PointXYZRGB& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_x()) { + set_x(from.x()); + } + if (from.has_y()) { + set_y(from.y()); + } + if (from.has_z()) { + set_z(from.z()); + } + if (from.has_rgb()) { + set_rgb(from.rgb()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void PointCloudXYZRGB_PointXYZRGB::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void PointCloudXYZRGB_PointXYZRGB::CopyFrom(const PointCloudXYZRGB_PointXYZRGB& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool PointCloudXYZRGB_PointXYZRGB::IsInitialized() const { + if ((_has_bits_[0] & 0x0000000f) != 0x0000000f) return false; + + return true; +} + +void PointCloudXYZRGB_PointXYZRGB::Swap(PointCloudXYZRGB_PointXYZRGB* other) { + if (other != this) { + std::swap(x_, other->x_); + std::swap(y_, other->y_); + std::swap(z_, other->z_); + std::swap(rgb_, other->rgb_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata PointCloudXYZRGB_PointXYZRGB::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = PointCloudXYZRGB_PointXYZRGB_descriptor_; + metadata.reflection = PointCloudXYZRGB_PointXYZRGB_reflection_; + return metadata; +} + + +// ------------------------------------------------------------------- + +#ifndef _MSC_VER +const int PointCloudXYZRGB::kHeaderFieldNumber; +const int PointCloudXYZRGB::kPointsFieldNumber; +#endif // !_MSC_VER + +PointCloudXYZRGB::PointCloudXYZRGB() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void PointCloudXYZRGB::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +PointCloudXYZRGB::PointCloudXYZRGB(const PointCloudXYZRGB& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void PointCloudXYZRGB::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +PointCloudXYZRGB::~PointCloudXYZRGB() { + SharedDtor(); +} + +void PointCloudXYZRGB::SharedDtor() { + if (this != default_instance_) { + delete header_; + } +} + +void PointCloudXYZRGB::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* PointCloudXYZRGB::descriptor() { + protobuf_AssignDescriptorsOnce(); + return PointCloudXYZRGB_descriptor_; +} + +const PointCloudXYZRGB& PointCloudXYZRGB::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +PointCloudXYZRGB* PointCloudXYZRGB::default_instance_ = NULL; + +PointCloudXYZRGB* PointCloudXYZRGB::New() const { + return new PointCloudXYZRGB; +} + +void PointCloudXYZRGB::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + } + points_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool PointCloudXYZRGB::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_points; + break; + } + + // repeated .px.PointCloudXYZRGB.PointXYZRGB points = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_points: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_points())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_points; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void PointCloudXYZRGB::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // repeated .px.PointCloudXYZRGB.PointXYZRGB points = 2; + for (int i = 0; i < this->points_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->points(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* PointCloudXYZRGB::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // repeated .px.PointCloudXYZRGB.PointXYZRGB points = 2; + for (int i = 0; i < this->points_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->points(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int PointCloudXYZRGB::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + } + // repeated .px.PointCloudXYZRGB.PointXYZRGB points = 2; + total_size += 1 * this->points_size(); + for (int i = 0; i < this->points_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->points(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void PointCloudXYZRGB::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const PointCloudXYZRGB* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void PointCloudXYZRGB::MergeFrom(const PointCloudXYZRGB& from) { + GOOGLE_CHECK_NE(&from, this); + points_.MergeFrom(from.points_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void PointCloudXYZRGB::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void PointCloudXYZRGB::CopyFrom(const PointCloudXYZRGB& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool PointCloudXYZRGB::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + for (int i = 0; i < points_size(); i++) { + if (!this->points(i).IsInitialized()) return false; + } + return true; +} + +void PointCloudXYZRGB::Swap(PointCloudXYZRGB* other) { + if (other != this) { + std::swap(header_, other->header_); + points_.Swap(&other->points_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata PointCloudXYZRGB::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = PointCloudXYZRGB_descriptor_; + metadata.reflection = PointCloudXYZRGB_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int RGBDImage::kHeaderFieldNumber; +const int RGBDImage::kColsFieldNumber; +const int RGBDImage::kRowsFieldNumber; +const int RGBDImage::kStep1FieldNumber; +const int RGBDImage::kType1FieldNumber; +const int RGBDImage::kImageData1FieldNumber; +const int RGBDImage::kStep2FieldNumber; +const int RGBDImage::kType2FieldNumber; +const int RGBDImage::kImageData2FieldNumber; +const int RGBDImage::kCameraConfigFieldNumber; +const int RGBDImage::kCameraTypeFieldNumber; +const int RGBDImage::kRollFieldNumber; +const int RGBDImage::kPitchFieldNumber; +const int RGBDImage::kYawFieldNumber; +const int RGBDImage::kLonFieldNumber; +const int RGBDImage::kLatFieldNumber; +const int RGBDImage::kAltFieldNumber; +const int RGBDImage::kGroundXFieldNumber; +const int RGBDImage::kGroundYFieldNumber; +const int RGBDImage::kGroundZFieldNumber; +const int RGBDImage::kCameraMatrixFieldNumber; +#endif // !_MSC_VER + +RGBDImage::RGBDImage() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RGBDImage::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +RGBDImage::RGBDImage(const RGBDImage& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RGBDImage::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + cols_ = 0u; + rows_ = 0u; + step1_ = 0u; + type1_ = 0u; + imagedata1_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + step2_ = 0u; + type2_ = 0u; + imagedata2_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + camera_config_ = 0u; + camera_type_ = 0u; + roll_ = 0; + pitch_ = 0; + yaw_ = 0; + lon_ = 0; + lat_ = 0; + alt_ = 0; + ground_x_ = 0; + ground_y_ = 0; + ground_z_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RGBDImage::~RGBDImage() { + SharedDtor(); +} + +void RGBDImage::SharedDtor() { + if (imagedata1_ != &::google::protobuf::internal::kEmptyString) { + delete imagedata1_; + } + if (imagedata2_ != &::google::protobuf::internal::kEmptyString) { + delete imagedata2_; + } + if (this != default_instance_) { + delete header_; + } +} + +void RGBDImage::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RGBDImage::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RGBDImage_descriptor_; +} + +const RGBDImage& RGBDImage::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +RGBDImage* RGBDImage::default_instance_ = NULL; + +RGBDImage* RGBDImage::New() const { + return new RGBDImage; +} + +void RGBDImage::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + cols_ = 0u; + rows_ = 0u; + step1_ = 0u; + type1_ = 0u; + if (has_imagedata1()) { + if (imagedata1_ != &::google::protobuf::internal::kEmptyString) { + imagedata1_->clear(); + } + } + step2_ = 0u; + type2_ = 0u; + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + if (has_imagedata2()) { + if (imagedata2_ != &::google::protobuf::internal::kEmptyString) { + imagedata2_->clear(); + } + } + camera_config_ = 0u; + camera_type_ = 0u; + roll_ = 0; + pitch_ = 0; + yaw_ = 0; + lon_ = 0; + lat_ = 0; + } + if (_has_bits_[16 / 32] & (0xffu << (16 % 32))) { + alt_ = 0; + ground_x_ = 0; + ground_y_ = 0; + ground_z_ = 0; + } + camera_matrix_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RGBDImage::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_cols; + break; + } + + // required uint32 cols = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_cols: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &cols_))); + set_has_cols(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(24)) goto parse_rows; + break; + } + + // required uint32 rows = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_rows: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &rows_))); + set_has_rows(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(32)) goto parse_step1; + break; + } + + // required uint32 step1 = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_step1: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &step1_))); + set_has_step1(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(40)) goto parse_type1; + break; + } + + // required uint32 type1 = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_type1: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &type1_))); + set_has_type1(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(50)) goto parse_imageData1; + break; + } + + // required bytes imageData1 = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_imageData1: + DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( + input, this->mutable_imagedata1())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(56)) goto parse_step2; + break; + } + + // required uint32 step2 = 7; + case 7: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_step2: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &step2_))); + set_has_step2(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(64)) goto parse_type2; + break; + } + + // required uint32 type2 = 8; + case 8: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_type2: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &type2_))); + set_has_type2(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(74)) goto parse_imageData2; + break; + } + + // required bytes imageData2 = 9; + case 9: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_imageData2: + DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( + input, this->mutable_imagedata2())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(80)) goto parse_camera_config; + break; + } + + // optional uint32 camera_config = 10; + case 10: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_camera_config: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &camera_config_))); + set_has_camera_config(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(88)) goto parse_camera_type; + break; + } + + // optional uint32 camera_type = 11; + case 11: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_camera_type: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &camera_type_))); + set_has_camera_type(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(101)) goto parse_roll; + break; + } + + // optional float roll = 12; + case 12: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_roll: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &roll_))); + set_has_roll(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(109)) goto parse_pitch; + break; + } + + // optional float pitch = 13; + case 13: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_pitch: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &pitch_))); + set_has_pitch(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(117)) goto parse_yaw; + break; + } + + // optional float yaw = 14; + case 14: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_yaw: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &yaw_))); + set_has_yaw(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(125)) goto parse_lon; + break; + } + + // optional float lon = 15; + case 15: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_lon: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &lon_))); + set_has_lon(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(133)) goto parse_lat; + break; + } + + // optional float lat = 16; + case 16: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_lat: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &lat_))); + set_has_lat(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(141)) goto parse_alt; + break; + } + + // optional float alt = 17; + case 17: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_alt: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &alt_))); + set_has_alt(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(149)) goto parse_ground_x; + break; + } + + // optional float ground_x = 18; + case 18: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_ground_x: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &ground_x_))); + set_has_ground_x(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(157)) goto parse_ground_y; + break; + } + + // optional float ground_y = 19; + case 19: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_ground_y: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &ground_y_))); + set_has_ground_y(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(165)) goto parse_ground_z; + break; + } + + // optional float ground_z = 20; + case 20: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_ground_z: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &ground_z_))); + set_has_ground_z(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(173)) goto parse_camera_matrix; + break; + } + + // repeated float camera_matrix = 21; + case 21: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_camera_matrix: + DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + 2, 173, input, this->mutable_camera_matrix()))); + } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) + == ::google::protobuf::internal::WireFormatLite:: + WIRETYPE_LENGTH_DELIMITED) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, this->mutable_camera_matrix()))); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(173)) goto parse_camera_matrix; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RGBDImage::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // required uint32 cols = 2; + if (has_cols()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(2, this->cols(), output); + } + + // required uint32 rows = 3; + if (has_rows()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(3, this->rows(), output); + } + + // required uint32 step1 = 4; + if (has_step1()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(4, this->step1(), output); + } + + // required uint32 type1 = 5; + if (has_type1()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(5, this->type1(), output); + } + + // required bytes imageData1 = 6; + if (has_imagedata1()) { + ::google::protobuf::internal::WireFormatLite::WriteBytes( + 6, this->imagedata1(), output); + } + + // required uint32 step2 = 7; + if (has_step2()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(7, this->step2(), output); + } + + // required uint32 type2 = 8; + if (has_type2()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(8, this->type2(), output); + } + + // required bytes imageData2 = 9; + if (has_imagedata2()) { + ::google::protobuf::internal::WireFormatLite::WriteBytes( + 9, this->imagedata2(), output); + } + + // optional uint32 camera_config = 10; + if (has_camera_config()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(10, this->camera_config(), output); + } + + // optional uint32 camera_type = 11; + if (has_camera_type()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(11, this->camera_type(), output); + } + + // optional float roll = 12; + if (has_roll()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(12, this->roll(), output); + } + + // optional float pitch = 13; + if (has_pitch()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(13, this->pitch(), output); + } + + // optional float yaw = 14; + if (has_yaw()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(14, this->yaw(), output); + } + + // optional float lon = 15; + if (has_lon()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(15, this->lon(), output); + } + + // optional float lat = 16; + if (has_lat()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(16, this->lat(), output); + } + + // optional float alt = 17; + if (has_alt()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(17, this->alt(), output); + } + + // optional float ground_x = 18; + if (has_ground_x()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(18, this->ground_x(), output); + } + + // optional float ground_y = 19; + if (has_ground_y()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(19, this->ground_y(), output); + } + + // optional float ground_z = 20; + if (has_ground_z()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(20, this->ground_z(), output); + } + + // repeated float camera_matrix = 21; + for (int i = 0; i < this->camera_matrix_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteFloat( + 21, this->camera_matrix(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RGBDImage::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // required uint32 cols = 2; + if (has_cols()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(2, this->cols(), target); + } + + // required uint32 rows = 3; + if (has_rows()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(3, this->rows(), target); + } + + // required uint32 step1 = 4; + if (has_step1()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(4, this->step1(), target); + } + + // required uint32 type1 = 5; + if (has_type1()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(5, this->type1(), target); + } + + // required bytes imageData1 = 6; + if (has_imagedata1()) { + target = + ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( + 6, this->imagedata1(), target); + } + + // required uint32 step2 = 7; + if (has_step2()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(7, this->step2(), target); + } + + // required uint32 type2 = 8; + if (has_type2()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(8, this->type2(), target); + } + + // required bytes imageData2 = 9; + if (has_imagedata2()) { + target = + ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( + 9, this->imagedata2(), target); + } + + // optional uint32 camera_config = 10; + if (has_camera_config()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(10, this->camera_config(), target); + } + + // optional uint32 camera_type = 11; + if (has_camera_type()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(11, this->camera_type(), target); + } + + // optional float roll = 12; + if (has_roll()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(12, this->roll(), target); + } + + // optional float pitch = 13; + if (has_pitch()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(13, this->pitch(), target); + } + + // optional float yaw = 14; + if (has_yaw()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(14, this->yaw(), target); + } + + // optional float lon = 15; + if (has_lon()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(15, this->lon(), target); + } + + // optional float lat = 16; + if (has_lat()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(16, this->lat(), target); + } + + // optional float alt = 17; + if (has_alt()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(17, this->alt(), target); + } + + // optional float ground_x = 18; + if (has_ground_x()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(18, this->ground_x(), target); + } + + // optional float ground_y = 19; + if (has_ground_y()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(19, this->ground_y(), target); + } + + // optional float ground_z = 20; + if (has_ground_z()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(20, this->ground_z(), target); + } + + // repeated float camera_matrix = 21; + for (int i = 0; i < this->camera_matrix_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteFloatToArray(21, this->camera_matrix(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RGBDImage::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + // required uint32 cols = 2; + if (has_cols()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->cols()); + } + + // required uint32 rows = 3; + if (has_rows()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->rows()); + } + + // required uint32 step1 = 4; + if (has_step1()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->step1()); + } + + // required uint32 type1 = 5; + if (has_type1()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->type1()); + } + + // required bytes imageData1 = 6; + if (has_imagedata1()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::BytesSize( + this->imagedata1()); + } + + // required uint32 step2 = 7; + if (has_step2()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->step2()); + } + + // required uint32 type2 = 8; + if (has_type2()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->type2()); + } + + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + // required bytes imageData2 = 9; + if (has_imagedata2()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::BytesSize( + this->imagedata2()); + } + + // optional uint32 camera_config = 10; + if (has_camera_config()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->camera_config()); + } + + // optional uint32 camera_type = 11; + if (has_camera_type()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->camera_type()); + } + + // optional float roll = 12; + if (has_roll()) { + total_size += 1 + 4; + } + + // optional float pitch = 13; + if (has_pitch()) { + total_size += 1 + 4; + } + + // optional float yaw = 14; + if (has_yaw()) { + total_size += 1 + 4; + } + + // optional float lon = 15; + if (has_lon()) { + total_size += 1 + 4; + } + + // optional float lat = 16; + if (has_lat()) { + total_size += 2 + 4; + } + + } + if (_has_bits_[16 / 32] & (0xffu << (16 % 32))) { + // optional float alt = 17; + if (has_alt()) { + total_size += 2 + 4; + } + + // optional float ground_x = 18; + if (has_ground_x()) { + total_size += 2 + 4; + } + + // optional float ground_y = 19; + if (has_ground_y()) { + total_size += 2 + 4; + } + + // optional float ground_z = 20; + if (has_ground_z()) { + total_size += 2 + 4; + } + + } + // repeated float camera_matrix = 21; + { + int data_size = 0; + data_size = 4 * this->camera_matrix_size(); + total_size += 2 * this->camera_matrix_size() + data_size; + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RGBDImage::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RGBDImage* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RGBDImage::MergeFrom(const RGBDImage& from) { + GOOGLE_CHECK_NE(&from, this); + camera_matrix_.MergeFrom(from.camera_matrix_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + if (from.has_cols()) { + set_cols(from.cols()); + } + if (from.has_rows()) { + set_rows(from.rows()); + } + if (from.has_step1()) { + set_step1(from.step1()); + } + if (from.has_type1()) { + set_type1(from.type1()); + } + if (from.has_imagedata1()) { + set_imagedata1(from.imagedata1()); + } + if (from.has_step2()) { + set_step2(from.step2()); + } + if (from.has_type2()) { + set_type2(from.type2()); + } + } + if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) { + if (from.has_imagedata2()) { + set_imagedata2(from.imagedata2()); + } + if (from.has_camera_config()) { + set_camera_config(from.camera_config()); + } + if (from.has_camera_type()) { + set_camera_type(from.camera_type()); + } + if (from.has_roll()) { + set_roll(from.roll()); + } + if (from.has_pitch()) { + set_pitch(from.pitch()); + } + if (from.has_yaw()) { + set_yaw(from.yaw()); + } + if (from.has_lon()) { + set_lon(from.lon()); + } + if (from.has_lat()) { + set_lat(from.lat()); + } + } + if (from._has_bits_[16 / 32] & (0xffu << (16 % 32))) { + if (from.has_alt()) { + set_alt(from.alt()); + } + if (from.has_ground_x()) { + set_ground_x(from.ground_x()); + } + if (from.has_ground_y()) { + set_ground_y(from.ground_y()); + } + if (from.has_ground_z()) { + set_ground_z(from.ground_z()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RGBDImage::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RGBDImage::CopyFrom(const RGBDImage& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RGBDImage::IsInitialized() const { + if ((_has_bits_[0] & 0x000001ff) != 0x000001ff) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + return true; +} + +void RGBDImage::Swap(RGBDImage* other) { + if (other != this) { + std::swap(header_, other->header_); + std::swap(cols_, other->cols_); + std::swap(rows_, other->rows_); + std::swap(step1_, other->step1_); + std::swap(type1_, other->type1_); + std::swap(imagedata1_, other->imagedata1_); + std::swap(step2_, other->step2_); + std::swap(type2_, other->type2_); + std::swap(imagedata2_, other->imagedata2_); + std::swap(camera_config_, other->camera_config_); + std::swap(camera_type_, other->camera_type_); + std::swap(roll_, other->roll_); + std::swap(pitch_, other->pitch_); + std::swap(yaw_, other->yaw_); + std::swap(lon_, other->lon_); + std::swap(lat_, other->lat_); + std::swap(alt_, other->alt_); + std::swap(ground_x_, other->ground_x_); + std::swap(ground_y_, other->ground_y_); + std::swap(ground_z_, other->ground_z_); + camera_matrix_.Swap(&other->camera_matrix_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RGBDImage::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RGBDImage_descriptor_; + metadata.reflection = RGBDImage_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int Waypoint::kXFieldNumber; +const int Waypoint::kYFieldNumber; +const int Waypoint::kZFieldNumber; +const int Waypoint::kRollFieldNumber; +const int Waypoint::kPitchFieldNumber; +const int Waypoint::kYawFieldNumber; +#endif // !_MSC_VER + +Waypoint::Waypoint() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void Waypoint::InitAsDefaultInstance() { +} + +Waypoint::Waypoint(const Waypoint& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void Waypoint::SharedCtor() { + _cached_size_ = 0; + x_ = 0; + y_ = 0; + z_ = 0; + roll_ = 0; + pitch_ = 0; + yaw_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +Waypoint::~Waypoint() { + SharedDtor(); +} + +void Waypoint::SharedDtor() { + if (this != default_instance_) { + } +} + +void Waypoint::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* Waypoint::descriptor() { + protobuf_AssignDescriptorsOnce(); + return Waypoint_descriptor_; +} + +const Waypoint& Waypoint::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +Waypoint* Waypoint::default_instance_ = NULL; + +Waypoint* Waypoint::New() const { + return new Waypoint; +} + +void Waypoint::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + x_ = 0; + y_ = 0; + z_ = 0; + roll_ = 0; + pitch_ = 0; + yaw_ = 0; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool Waypoint::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required double x = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &x_))); + set_has_x(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(17)) goto parse_y; + break; + } + + // required double y = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_y: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &y_))); + set_has_y(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(25)) goto parse_z; + break; + } + + // optional double z = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_z: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &z_))); + set_has_z(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(33)) goto parse_roll; + break; + } + + // optional double roll = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_roll: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &roll_))); + set_has_roll(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(41)) goto parse_pitch; + break; + } + + // optional double pitch = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_pitch: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &pitch_))); + set_has_pitch(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(49)) goto parse_yaw; + break; + } + + // optional double yaw = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_yaw: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &yaw_))); + set_has_yaw(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void Waypoint::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required double x = 1; + if (has_x()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(1, this->x(), output); + } + + // required double y = 2; + if (has_y()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(2, this->y(), output); + } + + // optional double z = 3; + if (has_z()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(3, this->z(), output); + } + + // optional double roll = 4; + if (has_roll()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(4, this->roll(), output); + } + + // optional double pitch = 5; + if (has_pitch()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(5, this->pitch(), output); + } + + // optional double yaw = 6; + if (has_yaw()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->yaw(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* Waypoint::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required double x = 1; + if (has_x()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(1, this->x(), target); + } + + // required double y = 2; + if (has_y()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(2, this->y(), target); + } + + // optional double z = 3; + if (has_z()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(3, this->z(), target); + } + + // optional double roll = 4; + if (has_roll()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(4, this->roll(), target); + } + + // optional double pitch = 5; + if (has_pitch()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(5, this->pitch(), target); + } + + // optional double yaw = 6; + if (has_yaw()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->yaw(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int Waypoint::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required double x = 1; + if (has_x()) { + total_size += 1 + 8; + } + + // required double y = 2; + if (has_y()) { + total_size += 1 + 8; + } + + // optional double z = 3; + if (has_z()) { + total_size += 1 + 8; + } + + // optional double roll = 4; + if (has_roll()) { + total_size += 1 + 8; + } + + // optional double pitch = 5; + if (has_pitch()) { + total_size += 1 + 8; + } + + // optional double yaw = 6; + if (has_yaw()) { + total_size += 1 + 8; + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void Waypoint::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const Waypoint* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void Waypoint::MergeFrom(const Waypoint& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_x()) { + set_x(from.x()); + } + if (from.has_y()) { + set_y(from.y()); + } + if (from.has_z()) { + set_z(from.z()); + } + if (from.has_roll()) { + set_roll(from.roll()); + } + if (from.has_pitch()) { + set_pitch(from.pitch()); + } + if (from.has_yaw()) { + set_yaw(from.yaw()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void Waypoint::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Waypoint::CopyFrom(const Waypoint& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Waypoint::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + return true; +} + +void Waypoint::Swap(Waypoint* other) { + if (other != this) { + std::swap(x_, other->x_); + std::swap(y_, other->y_); + std::swap(z_, other->z_); + std::swap(roll_, other->roll_); + std::swap(pitch_, other->pitch_); + std::swap(yaw_, other->yaw_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata Waypoint::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = Waypoint_descriptor_; + metadata.reflection = Waypoint_reflection_; + return metadata; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace px + +// @@protoc_insertion_point(global_scope) diff --git a/mavlink/share/pyshared/pymavlink/.gitignore b/mavlink/share/pyshared/pymavlink/.gitignore new file mode 100644 index 0000000000..3d395ecda4 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/.gitignore @@ -0,0 +1,13 @@ +apidocs/ +*.zip +*.pyc +send.sh +generator/C/include/ardupilotmega +generator/C/include/common +generator/C/include/pixhawk +generator/C/include/minimal +generator/C/include/ualberta +generator/C/include/slugs +testmav0.9* +testmav1.0* +Debug/ diff --git a/mavlink/share/pyshared/pymavlink/APM_Mavtest/APM_Mavtest.pde b/mavlink/share/pyshared/pymavlink/APM_Mavtest/APM_Mavtest.pde new file mode 100644 index 0000000000..b903b5c169 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/APM_Mavtest/APM_Mavtest.pde @@ -0,0 +1,55 @@ +/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: t -*- + +/* + send all possible mavlink messages + Andrew Tridgell July 2011 +*/ + +// AVR runtime +#include +#include +#include +#include + +// Libraries +#include +#include +#include +#include "mavtest.h" + +FastSerialPort0(Serial); // FTDI/console +FastSerialPort1(Serial1); // GPS port +FastSerialPort3(Serial3); // Telemetry port + +#define SERIAL0_BAUD 115200 +#define SERIAL3_BAUD 115200 + +void setup() { + Serial.begin(SERIAL0_BAUD, 128, 128); + Serial3.begin(SERIAL3_BAUD, 128, 128); + mavlink_comm_0_port = &Serial; + mavlink_comm_1_port = &Serial3; +} + + + +void loop() +{ + Serial.println("Starting MAVLink test generator\n"); + while (1) { + mavlink_msg_heartbeat_send( + MAVLINK_COMM_0, + mavlink_system.type, + MAV_AUTOPILOT_ARDUPILOTMEGA); + + mavlink_msg_heartbeat_send( + MAVLINK_COMM_1, + mavlink_system.type, + MAV_AUTOPILOT_ARDUPILOTMEGA); + + mavtest_generate_outputs(MAVLINK_COMM_0); + mavtest_generate_outputs(MAVLINK_COMM_1); + delay(500); + } +} + diff --git a/mavlink/share/pyshared/pymavlink/APM_Mavtest/Makefile b/mavlink/share/pyshared/pymavlink/APM_Mavtest/Makefile new file mode 100644 index 0000000000..7ca38b1a26 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/APM_Mavtest/Makefile @@ -0,0 +1,10 @@ +# +# Trivial makefile for building APM +# + +# +# Select 'mega' for the original APM, or 'mega2560' for the V2 APM. +# +BOARD = mega2560 + +include ../libraries/AP_Common/Arduino.mk diff --git a/mavlink/share/pyshared/pymavlink/README.txt b/mavlink/share/pyshared/pymavlink/README.txt new file mode 100644 index 0000000000..386013e114 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/README.txt @@ -0,0 +1,4 @@ +This is a python implementation of the MAVLink protocol. + +Please see http://www.qgroundcontrol.org/mavlink/pymavlink for +documentation diff --git a/mavlink/share/pyshared/pymavlink/examples/apmsetrate.py b/mavlink/share/pyshared/pymavlink/examples/apmsetrate.py new file mode 100644 index 0000000000..d7d82256c7 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/apmsetrate.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python + +''' +set stream rate on an APM +''' + +import sys, struct, time, os + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +from optparse import OptionParser +parser = OptionParser("apmsetrate.py [options]") + +parser.add_option("--baudrate", dest="baudrate", type='int', + help="master port baud rate", default=115200) +parser.add_option("--device", dest="device", default=None, help="serial device") +parser.add_option("--rate", dest="rate", default=4, type='int', help="requested stream rate") +parser.add_option("--source-system", dest='SOURCE_SYSTEM', type='int', + default=255, help='MAVLink source system for this GCS') +parser.add_option("--showmessages", dest="showmessages", action='store_true', + help="show incoming messages", default=False) +parser.add_option("--mav10", action='store_true', default=False, help="Use MAVLink protocol 1.0") +(opts, args) = parser.parse_args() + +if opts.mav10: + os.environ['MAVLINK10'] = '1' + import mavlink10 as mavlink +else: + import mavlink +import mavutil + +if opts.device is None: + print("You must specify a serial device") + sys.exit(1) + +def wait_heartbeat(m): + '''wait for a heartbeat so we know the target system IDs''' + print("Waiting for APM heartbeat") + m.wait_heartbeat() + print("Heartbeat from APM (system %u component %u)" % (m.target_system, m.target_system)) + +def show_messages(m): + '''show incoming mavlink messages''' + while True: + msg = m.recv_match(blocking=True) + if not msg: + return + if msg.get_type() == "BAD_DATA": + if mavutil.all_printable(msg.data): + sys.stdout.write(msg.data) + sys.stdout.flush() + else: + print(msg) + +# create a mavlink serial instance +master = mavutil.mavlink_connection(opts.device, baud=opts.baudrate) + +# wait for the heartbeat msg to find the system ID +wait_heartbeat(master) + +print("Sending all stream request for rate %u" % opts.rate) +for i in range(0, 3): + master.mav.request_data_stream_send(master.target_system, master.target_component, + mavlink.MAV_DATA_STREAM_ALL, opts.rate, 1) +if opts.showmessages: + show_messages(master) diff --git a/mavlink/share/pyshared/pymavlink/examples/bwtest.py b/mavlink/share/pyshared/pymavlink/examples/bwtest.py new file mode 100644 index 0000000000..de56d4f8c6 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/bwtest.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python + +''' +check bandwidth of link +''' + +import sys, struct, time, os + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +import mavutil + +from optparse import OptionParser +parser = OptionParser("bwtest.py [options]") + +parser.add_option("--baudrate", dest="baudrate", type='int', + help="master port baud rate", default=115200) +parser.add_option("--device", dest="device", default=None, help="serial device") +(opts, args) = parser.parse_args() + +if opts.device is None: + print("You must specify a serial device") + sys.exit(1) + +# create a mavlink serial instance +master = mavutil.mavlink_connection(opts.device, baud=opts.baudrate) + +t1 = time.time() + +counts = {} + +bytes_sent = 0 +bytes_recv = 0 + +while True: + master.mav.heartbeat_send(1, 1) + master.mav.sys_status_send(1, 2, 3, 4, 5, 6, 7) + master.mav.gps_raw_send(1, 2, 3, 4, 5, 6, 7, 8, 9) + master.mav.attitude_send(1, 2, 3, 4, 5, 6, 7) + master.mav.vfr_hud_send(1, 2, 3, 4, 5, 6) + while master.port.inWaiting() > 0: + m = master.recv_msg() + if m == None: break + if m.get_type() not in counts: + counts[m.get_type()] = 0 + counts[m.get_type()] += 1 + t2 = time.time() + if t2 - t1 > 1.0: + print("%u sent, %u received, %u errors bwin=%.1f kB/s bwout=%.1f kB/s" % ( + master.mav.total_packets_sent, + master.mav.total_packets_received, + master.mav.total_receive_errors, + 0.001*(master.mav.total_bytes_received-bytes_recv)/(t2-t1), + 0.001*(master.mav.total_bytes_sent-bytes_sent)/(t2-t1))) + bytes_sent = master.mav.total_bytes_sent + bytes_recv = master.mav.total_bytes_received + t1 = t2 diff --git a/mavlink/share/pyshared/pymavlink/examples/flightmodes.py b/mavlink/share/pyshared/pymavlink/examples/flightmodes.py new file mode 100644 index 0000000000..03d7e2c47c --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/flightmodes.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +''' +show changes in flight modes +''' + +import sys, time, os + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +from optparse import OptionParser +parser = OptionParser("flightmodes.py [options]") +parser.add_option("--mav10", action='store_true', default=False, help="Use MAVLink protocol 1.0") + +(opts, args) = parser.parse_args() + +if opts.mav10: + os.environ['MAVLINK10'] = '1' +import mavutil + +if len(args) < 1: + print("Usage: flightmodes.py [options] ") + sys.exit(1) + +def flight_modes(logfile): + '''show flight modes for a log file''' + print("Processing log %s" % filename) + mlog = mavutil.mavlink_connection(filename) + + mode = -1 + nav_mode = -1 + + filesize = os.path.getsize(filename) + + while True: + m = mlog.recv_match(type='SYS_STATUS', + condition='SYS_STATUS.mode != %u or SYS_STATUS.nav_mode != %u' % (mode, nav_mode)) + if m is None: + return + mode = m.mode + nav_mode = m.nav_mode + pct = (100.0 * mlog.f.tell()) / filesize + print('%s MAV.flightmode=%-12s mode=%u nav_mode=%u (MAV.timestamp=%u %u%%)' % ( + time.asctime(time.localtime(m._timestamp)), + mlog.flightmode, + mode, nav_mode, m._timestamp, pct)) + +for filename in args: + flight_modes(filename) + + diff --git a/mavlink/share/pyshared/pymavlink/examples/flighttime.py b/mavlink/share/pyshared/pymavlink/examples/flighttime.py new file mode 100644 index 0000000000..81cd38c94d --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/flighttime.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +''' +work out total flight time for a mavlink log +''' + +import sys, time, os + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +from optparse import OptionParser +parser = OptionParser("flighttime.py [options]") +parser.add_option("--mav10", action='store_true', default=False, help="Use MAVLink protocol 1.0") + +(opts, args) = parser.parse_args() + +if opts.mav10: + os.environ['MAVLINK10'] = '1' +import mavutil + +if len(args) < 1: + print("Usage: flighttime.py [options] ") + sys.exit(1) + +def flight_time(logfile): + '''work out flight time for a log file''' + print("Processing log %s" % filename) + mlog = mavutil.mavlink_connection(filename) + + in_air = False + start_time = 0.0 + total_time = 0.0 + t = None + + while True: + m = mlog.recv_match(type='VFR_HUD') + if m is None: + if in_air: + total_time += time.mktime(t) - start_time + if total_time > 0: + print("Flight time : %u:%02u" % (int(total_time)/60, int(total_time)%60)) + return total_time + t = time.localtime(m._timestamp) + if m.groundspeed > 3.0 and not in_air: + print("In air at %s" % time.asctime(t)) + in_air = True + start_time = time.mktime(t) + elif m.groundspeed < 3.0 and in_air: + print("On ground at %s" % time.asctime(t)) + in_air = False + total_time += time.mktime(t) - start_time + return total_time + +total = 0.0 +for filename in args: + total += flight_time(filename) + +print("Total time in air: %u:%02u" % (int(total)/60, int(total)%60)) diff --git a/mavlink/share/pyshared/pymavlink/examples/gpslock.py b/mavlink/share/pyshared/pymavlink/examples/gpslock.py new file mode 100644 index 0000000000..f15b290725 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/gpslock.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python + +''' +show GPS lock events in a MAVLink log +''' + +import sys, time, os + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +from optparse import OptionParser +parser = OptionParser("gpslock.py [options]") +parser.add_option("--mav10", action='store_true', default=False, help="Use MAVLink protocol 1.0") + +(opts, args) = parser.parse_args() + +if opts.mav10: + os.environ['MAVLINK10'] = '1' +import mavutil + +if len(args) < 1: + print("Usage: gpslock.py [options] ") + sys.exit(1) + +def lock_time(logfile): + '''work out gps lock times for a log file''' + print("Processing log %s" % filename) + mlog = mavutil.mavlink_connection(filename) + + locked = False + start_time = 0.0 + total_time = 0.0 + t = None + m = mlog.recv_match(type='GPS_RAW') + unlock_time = time.mktime(time.localtime(m._timestamp)) + + while True: + m = mlog.recv_match(type='GPS_RAW') + if m is None: + if locked: + total_time += time.mktime(t) - start_time + if total_time > 0: + print("Lock time : %u:%02u" % (int(total_time)/60, int(total_time)%60)) + return total_time + t = time.localtime(m._timestamp) + if m.fix_type == 2 and not locked: + print("Locked at %s after %u seconds" % (time.asctime(t), + time.mktime(t) - unlock_time)) + locked = True + start_time = time.mktime(t) + elif m.fix_type == 1 and locked: + print("Lost GPS lock at %s" % time.asctime(t)) + locked = False + total_time += time.mktime(t) - start_time + unlock_time = time.mktime(t) + elif m.fix_type == 0 and locked: + print("Lost protocol lock at %s" % time.asctime(t)) + locked = False + total_time += time.mktime(t) - start_time + unlock_time = time.mktime(t) + return total_time + +total = 0.0 +for filename in args: + total += lock_time(filename) + +print("Total time locked: %u:%02u" % (int(total)/60, int(total)%60)) diff --git a/mavlink/share/pyshared/pymavlink/examples/magfit.py b/mavlink/share/pyshared/pymavlink/examples/magfit.py new file mode 100644 index 0000000000..7bfda796b4 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/magfit.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python + +''' +fit best estimate of magnetometer offsets +''' + +import sys, time, os, math + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +from optparse import OptionParser +parser = OptionParser("magfit.py [options]") +parser.add_option("--no-timestamps",dest="notimestamps", action='store_true', help="Log doesn't have timestamps") +parser.add_option("--condition",dest="condition", default=None, help="select packets by condition") +parser.add_option("--noise", type='float', default=0, help="noise to add") +parser.add_option("--mav10", action='store_true', default=False, help="Use MAVLink protocol 1.0") + +(opts, args) = parser.parse_args() + +if opts.mav10: + os.environ['MAVLINK10'] = '1' +import mavutil +from rotmat import Vector3 + +if len(args) < 1: + print("Usage: magfit.py [options] ") + sys.exit(1) + +def noise(): + '''a noise vector''' + from random import gauss + v = Vector3(gauss(0, 1), gauss(0, 1), gauss(0, 1)) + v.normalize() + return v * opts.noise + +def select_data(data): + ret = [] + counts = {} + for d in data: + mag = d + key = "%u:%u:%u" % (mag.x/20,mag.y/20,mag.z/20) + if key in counts: + counts[key] += 1 + else: + counts[key] = 1 + if counts[key] < 3: + ret.append(d) + print(len(data), len(ret)) + return ret + +def radius(mag, offsets): + '''return radius give data point and offsets''' + return (mag + offsets).length() + +def radius_cmp(a, b, offsets): + '''return radius give data point and offsets''' + diff = radius(a, offsets) - radius(b, offsets) + if diff > 0: + return 1 + if diff < 0: + return -1 + return 0 + +def sphere_error(p, data): + from scipy import sqrt + x,y,z,r = p + ofs = Vector3(x,y,z) + ret = [] + for d in data: + mag = d + err = r - radius(mag, ofs) + ret.append(err) + return ret + +def fit_data(data): + import numpy, scipy + from scipy import optimize + + p0 = [0.0, 0.0, 0.0, 0.0] + p1, ier = optimize.leastsq(sphere_error, p0[:], args=(data)) + if not ier in [1, 2, 3, 4]: + raise RuntimeError("Unable to find solution") + return (Vector3(p1[0], p1[1], p1[2]), p1[3]) + +def magfit(logfile): + '''find best magnetometer offset fit to a log file''' + + print("Processing log %s" % filename) + mlog = mavutil.mavlink_connection(filename, notimestamps=opts.notimestamps) + + data = [] + + last_t = 0 + offsets = Vector3(0,0,0) + + # now gather all the data + while True: + m = mlog.recv_match(condition=opts.condition) + if m is None: + break + if m.get_type() == "SENSOR_OFFSETS": + # update current offsets + offsets = Vector3(m.mag_ofs_x, m.mag_ofs_y, m.mag_ofs_z) + if m.get_type() == "RAW_IMU": + mag = Vector3(m.xmag, m.ymag, m.zmag) + # add data point after subtracting the current offsets + data.append(mag - offsets + noise()) + + print("Extracted %u data points" % len(data)) + print("Current offsets: %s" % offsets) + + data = select_data(data) + + # do an initial fit with all data + (offsets, field_strength) = fit_data(data) + + for count in range(3): + # sort the data by the radius + data.sort(lambda a,b : radius_cmp(a,b,offsets)) + + print("Fit %u : %s field_strength=%6.1f to %6.1f" % ( + count, offsets, + radius(data[0], offsets), radius(data[-1], offsets))) + + # discard outliers, keep the middle 3/4 + data = data[len(data)/8:-len(data)/8] + + # fit again + (offsets, field_strength) = fit_data(data) + + print("Final : %s field_strength=%6.1f to %6.1f" % ( + offsets, + radius(data[0], offsets), radius(data[-1], offsets))) + +total = 0.0 +for filename in args: + magfit(filename) diff --git a/mavlink/share/pyshared/pymavlink/examples/magfit_delta.py b/mavlink/share/pyshared/pymavlink/examples/magfit_delta.py new file mode 100644 index 0000000000..87d2dbb7f0 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/magfit_delta.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python + +''' +fit best estimate of magnetometer offsets using the algorithm from +Bill Premerlani +''' + +import sys, time, os, math + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +# command line option handling +from optparse import OptionParser +parser = OptionParser("magfit_delta.py [options]") +parser.add_option("--no-timestamps",dest="notimestamps", action='store_true', help="Log doesn't have timestamps") +parser.add_option("--condition",dest="condition", default=None, help="select packets by condition") +parser.add_option("--mav10", action='store_true', default=False, help="Use MAVLink protocol 1.0") +parser.add_option("--verbose", action='store_true', default=False, help="verbose offset output") +parser.add_option("--gain", type='float', default=0.01, help="algorithm gain") +parser.add_option("--noise", type='float', default=0, help="noise to add") +parser.add_option("--max-change", type='float', default=10, help="max step change") +parser.add_option("--min-diff", type='float', default=50, help="min mag vector delta") +parser.add_option("--history", type='int', default=20, help="how many points to keep") +parser.add_option("--repeat", type='int', default=1, help="number of repeats through the data") + +(opts, args) = parser.parse_args() + +if opts.mav10: + os.environ['MAVLINK10'] = '1' +import mavutil +from rotmat import Vector3, Matrix3 + +if len(args) < 1: + print("Usage: magfit_delta.py [options] ") + sys.exit(1) + +def noise(): + '''a noise vector''' + from random import gauss + v = Vector3(gauss(0, 1), gauss(0, 1), gauss(0, 1)) + v.normalize() + return v * opts.noise + +def find_offsets(data, ofs): + '''find mag offsets by applying Bills "offsets revisited" algorithm + on the data + + This is an implementation of the algorithm from: + http://gentlenav.googlecode.com/files/MagnetometerOffsetNullingRevisited.pdf + ''' + + # a limit on the maximum change in each step + max_change = opts.max_change + + # the gain factor for the algorithm + gain = opts.gain + + data2 = [] + for d in data: + d = d.copy() + noise() + d.x = float(int(d.x + 0.5)) + d.y = float(int(d.y + 0.5)) + d.z = float(int(d.z + 0.5)) + data2.append(d) + data = data2 + + history_idx = 0 + mag_history = data[0:opts.history] + + for i in range(opts.history, len(data)): + B1 = mag_history[history_idx] + ofs + B2 = data[i] + ofs + + diff = B2 - B1 + diff_length = diff.length() + if diff_length <= opts.min_diff: + # the mag vector hasn't changed enough - we don't get any + # information from this + history_idx = (history_idx+1) % opts.history + continue + + mag_history[history_idx] = data[i] + history_idx = (history_idx+1) % opts.history + + # equation 6 of Bills paper + delta = diff * (gain * (B2.length() - B1.length()) / diff_length) + + # limit the change from any one reading. This is to prevent + # single crazy readings from throwing off the offsets for a long + # time + delta_length = delta.length() + if max_change != 0 and delta_length > max_change: + delta *= max_change / delta_length + + # set the new offsets + ofs = ofs - delta + + if opts.verbose: + print ofs + return ofs + + +def magfit(logfile): + '''find best magnetometer offset fit to a log file''' + + print("Processing log %s" % filename) + + # open the log file + mlog = mavutil.mavlink_connection(filename, notimestamps=opts.notimestamps) + + data = [] + mag = None + offsets = Vector3(0,0,0) + + # now gather all the data + while True: + # get the next MAVLink message in the log + m = mlog.recv_match(condition=opts.condition) + if m is None: + break + if m.get_type() == "SENSOR_OFFSETS": + # update offsets that were used during this flight + offsets = Vector3(m.mag_ofs_x, m.mag_ofs_y, m.mag_ofs_z) + if m.get_type() == "RAW_IMU" and offsets != None: + # extract one mag vector, removing the offsets that were + # used during that flight to get the raw sensor values + mag = Vector3(m.xmag, m.ymag, m.zmag) - offsets + data.append(mag) + + print("Extracted %u data points" % len(data)) + print("Current offsets: %s" % offsets) + + # run the fitting algorithm + ofs = offsets + ofs = Vector3(0,0,0) + for r in range(opts.repeat): + ofs = find_offsets(data, ofs) + print('Loop %u offsets %s' % (r, ofs)) + sys.stdout.flush() + print("New offsets: %s" % ofs) + +total = 0.0 +for filename in args: + magfit(filename) diff --git a/mavlink/share/pyshared/pymavlink/examples/magfit_gps.py b/mavlink/share/pyshared/pymavlink/examples/magfit_gps.py new file mode 100644 index 0000000000..30ba458062 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/magfit_gps.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python + +''' +fit best estimate of magnetometer offsets +''' + +import sys, time, os, math + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +from optparse import OptionParser +parser = OptionParser("magfit.py [options]") +parser.add_option("--no-timestamps",dest="notimestamps", action='store_true', help="Log doesn't have timestamps") +parser.add_option("--mav10", action='store_true', default=False, help="Use MAVLink protocol 1.0") +parser.add_option("--minspeed", type='float', default=5.0, help="minimum ground speed to use") + +(opts, args) = parser.parse_args() + +if opts.mav10: + os.environ['MAVLINK10'] = '1' +import mavutil + +if len(args) < 1: + print("Usage: magfit.py [options] ") + sys.exit(1) + +class vec3(object): + def __init__(self, x, y, z): + self.x = x + self.y = y + self.z = z + def __str__(self): + return "%.1f %.1f %.1f" % (self.x, self.y, self.z) + +def heading_error1(parm, data): + from math import sin, cos, atan2, degrees + from numpy import dot + xofs,yofs,zofs,a1,a2,a3,a4,a5,a6,a7,a8,a9,declination = parm + + ret = [] + for d in data: + x = d[0] + xofs + y = d[1] + yofs + z = d[2] + zofs + r = d[3] + p = d[4] + h = d[5] + + headX = x*cos(p) + y*sin(r)*sin(p) + z*cos(r)*sin(p) + headY = y*cos(r) - z*sin(r) + heading = degrees(atan2(-headY,headX)) + declination + if heading < 0: + heading += 360 + herror = h - heading + if herror > 180: + herror -= 360 + if herror < -180: + herror += 360 + ret.append(herror) + return ret + +def heading_error(parm, data): + from math import sin, cos, atan2, degrees + from numpy import dot + xofs,yofs,zofs,a1,a2,a3,a4,a5,a6,a7,a8,a9,declination = parm + + a = [[1.0,a2,a3],[a4,a5,a6],[a7,a8,a9]] + + ret = [] + for d in data: + x = d[0] + xofs + y = d[1] + yofs + z = d[2] + zofs + r = d[3] + p = d[4] + h = d[5] + mv = [x, y, z] + mv2 = dot(a, mv) + x = mv2[0] + y = mv2[1] + z = mv2[2] + + headX = x*cos(p) + y*sin(r)*sin(p) + z*cos(r)*sin(p) + headY = y*cos(r) - z*sin(r) + heading = degrees(atan2(-headY,headX)) + declination + if heading < 0: + heading += 360 + herror = h - heading + if herror > 180: + herror -= 360 + if herror < -180: + herror += 360 + ret.append(herror) + return ret + +def fit_data(data): + import numpy, scipy + from scipy import optimize + + p0 = [0.0, 0.0, 0.0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0] + p1, ier = optimize.leastsq(heading_error1, p0[:], args=(data)) + +# p0 = p1[:] +# p1, ier = optimize.leastsq(heading_error, p0[:], args=(data)) + + print(p1) + if not ier in [1, 2, 3, 4]: + raise RuntimeError("Unable to find solution") + return p1 + +def magfit(logfile): + '''find best magnetometer offset fit to a log file''' + print("Processing log %s" % filename) + mlog = mavutil.mavlink_connection(filename, notimestamps=opts.notimestamps) + + flying = False + gps_heading = 0.0 + + data = [] + + # get the current mag offsets + m = mlog.recv_match(type='SENSOR_OFFSETS') + offsets = vec3(m.mag_ofs_x, m.mag_ofs_y, m.mag_ofs_z) + + attitude = mlog.recv_match(type='ATTITUDE') + + # now gather all the data + while True: + m = mlog.recv_match() + if m is None: + break + if m.get_type() == "GPS_RAW": + # flying if groundspeed more than 5 m/s + flying = (m.v > opts.minspeed and m.fix_type == 2) + gps_heading = m.hdg + if m.get_type() == "ATTITUDE": + attitude = m + if m.get_type() == "SENSOR_OFFSETS": + # update current offsets + offsets = vec3(m.mag_ofs_x, m.mag_ofs_y, m.mag_ofs_z) + if not flying: + continue + if m.get_type() == "RAW_IMU": + data.append((m.xmag - offsets.x, m.ymag - offsets.y, m.zmag - offsets.z, attitude.roll, attitude.pitch, gps_heading)) + print("Extracted %u data points" % len(data)) + print("Current offsets: %s" % offsets) + ofs2 = fit_data(data) + print("Declination estimate: %.1f" % ofs2[-1]) + new_offsets = vec3(ofs2[0], ofs2[1], ofs2[2]) + a = [[ofs2[3], ofs2[4], ofs2[5]], + [ofs2[6], ofs2[7], ofs2[8]], + [ofs2[9], ofs2[10], ofs2[11]]] + print(a) + print("New offsets : %s" % new_offsets) + +total = 0.0 +for filename in args: + magfit(filename) diff --git a/mavlink/share/pyshared/pymavlink/examples/magtest.py b/mavlink/share/pyshared/pymavlink/examples/magtest.py new file mode 100644 index 0000000000..8b910f8fd3 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/magtest.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python + +''' +rotate APMs on bench to test magnetometers + +''' + +import sys, os, time +from math import radians + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +import mavlink, mavutil + +from optparse import OptionParser +parser = OptionParser("rotate.py [options]") + +parser.add_option("--device1", dest="device1", default=None, help="mavlink device1") +parser.add_option("--device2", dest="device2", default=None, help="mavlink device2") +parser.add_option("--baudrate", dest="baudrate", type='int', + help="master port baud rate", default=115200) +(opts, args) = parser.parse_args() + +if opts.device1 is None or opts.device2 is None: + print("You must specify a mavlink device") + sys.exit(1) + +def set_attitude(rc3, rc4): + global mav1, mav2 + values = [ 65535 ] * 8 + values[2] = rc3 + values[3] = rc4 + mav1.mav.rc_channels_override_send(mav1.target_system, mav1.target_component, *values) + mav2.mav.rc_channels_override_send(mav2.target_system, mav2.target_component, *values) + + +# create a mavlink instance +mav1 = mavutil.mavlink_connection(opts.device1, baud=opts.baudrate) + +# create a mavlink instance +mav2 = mavutil.mavlink_connection(opts.device2, baud=opts.baudrate) + +print("Waiting for HEARTBEAT") +mav1.wait_heartbeat() +mav2.wait_heartbeat() +print("Heartbeat from APM (system %u component %u)" % (mav1.target_system, mav1.target_system)) +print("Heartbeat from APM (system %u component %u)" % (mav2.target_system, mav2.target_system)) + +print("Waiting for MANUAL mode") +mav1.recv_match(type='SYS_STATUS', condition='SYS_STATUS.mode==2 and SYS_STATUS.nav_mode==4', blocking=True) +mav2.recv_match(type='SYS_STATUS', condition='SYS_STATUS.mode==2 and SYS_STATUS.nav_mode==4', blocking=True) + +print("Setting declination") +mav1.mav.param_set_send(mav1.target_system, mav1.target_component, + 'COMPASS_DEC', radians(12.33)) +mav2.mav.param_set_send(mav2.target_system, mav2.target_component, + 'COMPASS_DEC', radians(12.33)) + + +set_attitude(1060, 1160) + +event = mavutil.periodic_event(30) +pevent = mavutil.periodic_event(0.3) +rc3_min = 1060 +rc3_max = 1850 +rc4_min = 1080 +rc4_max = 1500 +rc3 = rc3_min +rc4 = 1160 +delta3 = 2 +delta4 = 1 +use_pitch = 1 + +MAV_ACTION_CALIBRATE_GYRO = 17 +mav1.mav.action_send(mav1.target_system, mav1.target_component, MAV_ACTION_CALIBRATE_GYRO) +mav2.mav.action_send(mav2.target_system, mav2.target_component, MAV_ACTION_CALIBRATE_GYRO) + +print("Waiting for gyro calibration") +mav1.recv_match(type='ACTION_ACK') +mav2.recv_match(type='ACTION_ACK') + +print("Resetting mag offsets") +mav1.mav.set_mag_offsets_send(mav1.target_system, mav1.target_component, 0, 0, 0) +mav2.mav.set_mag_offsets_send(mav2.target_system, mav2.target_component, 0, 0, 0) + +def TrueHeading(SERVO_OUTPUT_RAW): + p = float(SERVO_OUTPUT_RAW.servo3_raw - rc3_min) / (rc3_max - rc3_min) + return 172 + p*(326 - 172) + +while True: + mav1.recv_msg() + mav2.recv_msg() + if event.trigger(): + if not use_pitch: + rc4 = 1160 + set_attitude(rc3, rc4) + rc3 += delta3 + if rc3 > rc3_max or rc3 < rc3_min: + delta3 = -delta3 + use_pitch ^= 1 + rc4 += delta4 + if rc4 > rc4_max or rc4 < rc4_min: + delta4 = -delta4 + if pevent.trigger(): + print "hdg1: %3u hdg2: %3u ofs1: %4u, %4u, %4u ofs2: %4u, %4u, %4u" % ( + mav1.messages['VFR_HUD'].heading, + mav2.messages['VFR_HUD'].heading, + mav1.messages['SENSOR_OFFSETS'].mag_ofs_x, + mav1.messages['SENSOR_OFFSETS'].mag_ofs_y, + mav1.messages['SENSOR_OFFSETS'].mag_ofs_z, + mav2.messages['SENSOR_OFFSETS'].mag_ofs_x, + mav2.messages['SENSOR_OFFSETS'].mag_ofs_y, + mav2.messages['SENSOR_OFFSETS'].mag_ofs_z, + ) + time.sleep(0.01) + +# 314M 326G +# 160M 172G + diff --git a/mavlink/share/pyshared/pymavlink/examples/mavgraph.py b/mavlink/share/pyshared/pymavlink/examples/mavgraph.py new file mode 100644 index 0000000000..e19856487a --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/mavgraph.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python +''' +graph a MAVLink log file +Andrew Tridgell August 2011 +''' + +import sys, struct, time, os, datetime +import math, re +import pylab, pytz, matplotlib +from math import * + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +from mavextra import * + +locator = None +formatter = None + +def plotit(x, y, fields, colors=[]): + '''plot a set of graphs using date for x axis''' + global locator, formatter + pylab.ion() + fig = pylab.figure(num=1, figsize=(12,6)) + ax1 = fig.gca() + ax2 = None + xrange = 0.0 + for i in range(0, len(fields)): + if len(x[i]) == 0: continue + if x[i][-1] - x[i][0] > xrange: + xrange = x[i][-1] - x[i][0] + xrange *= 24 * 60 * 60 + if formatter is None: + if xrange < 1000: + formatter = matplotlib.dates.DateFormatter('%H:%M:%S') + else: + formatter = matplotlib.dates.DateFormatter('%H:%M') + interval = 1 + intervals = [ 1, 2, 5, 10, 15, 30, 60, 120, 240, 300, 600, + 900, 1800, 3600, 7200, 5*3600, 10*3600, 24*3600 ] + for interval in intervals: + if xrange / interval < 15: + break + locator = matplotlib.dates.SecondLocator(interval=interval) + ax1.xaxis.set_major_locator(locator) + ax1.xaxis.set_major_formatter(formatter) + empty = True + ax1_labels = [] + ax2_labels = [] + for i in range(0, len(fields)): + if len(x[i]) == 0: + print("Failed to find any values for field %s" % fields[i]) + continue + if i < len(colors): + color = colors[i] + else: + color = 'red' + (tz, tzdst) = time.tzname + if axes[i] == 2: + if ax2 == None: + ax2 = ax1.twinx() + ax = ax2 + ax2.xaxis.set_major_locator(locator) + ax2.xaxis.set_major_formatter(formatter) + label = fields[i] + if label.endswith(":2"): + label = label[:-2] + ax2_labels.append(label) + else: + ax1_labels.append(fields[i]) + ax = ax1 + ax.plot_date(x[i], y[i], color=color, label=fields[i], + linestyle='-', marker='None', tz=None) + pylab.draw() + empty = False + if ax1_labels != []: + ax1.legend(ax1_labels,loc=opts.legend) + if ax2_labels != []: + ax2.legend(ax2_labels,loc=opts.legend2) + if empty: + print("No data to graph") + return + + +from optparse import OptionParser +parser = OptionParser("mavgraph.py [options] ") + +parser.add_option("--no-timestamps",dest="notimestamps", action='store_true', help="Log doesn't have timestamps") +parser.add_option("--planner",dest="planner", action='store_true', help="use planner file format") +parser.add_option("--condition",dest="condition", default=None, help="select packets by a condition") +parser.add_option("--labels",dest="labels", default=None, help="comma separated field labels") +parser.add_option("--mav10", action='store_true', default=False, help="Use MAVLink protocol 1.0") +parser.add_option("--legend", default='upper left', help="default legend position") +parser.add_option("--legend2", default='upper right', help="default legend2 position") +(opts, args) = parser.parse_args() + +if opts.mav10: + os.environ['MAVLINK10'] = '1' +import mavutil + +if len(args) < 2: + print("Usage: mavlogdump.py [options] ") + sys.exit(1) + +filenames = [] +fields = [] +for f in args: + if os.path.exists(f): + filenames.append(f) + else: + fields.append(f) +msg_types = set() +multiplier = [] +field_types = [] + +colors = [ 'red', 'green', 'blue', 'orange', 'olive', 'black', 'grey' ] + +# work out msg types we are interested in +x = [] +y = [] +axes = [] +first_only = [] +re_caps = re.compile('[A-Z_]+') +for f in fields: + caps = set(re.findall(re_caps, f)) + msg_types = msg_types.union(caps) + field_types.append(caps) + y.append([]) + x.append([]) + axes.append(1) + first_only.append(False) + +def add_data(t, msg, vars): + '''add some data''' + mtype = msg.get_type() + if mtype not in msg_types: + return + for i in range(0, len(fields)): + if mtype not in field_types[i]: + continue + f = fields[i] + if f.endswith(":2"): + axes[i] = 2 + f = f[:-2] + if f.endswith(":1"): + first_only[i] = True + f = f[:-2] + v = mavutil.evaluate_expression(f, vars) + if v is None: + continue + y[i].append(v) + x[i].append(t) + +def process_file(filename): + '''process one file''' + print("Processing %s" % filename) + mlog = mavutil.mavlink_connection(filename, notimestamps=opts.notimestamps) + vars = {} + + while True: + msg = mlog.recv_match(opts.condition) + if msg is None: break + tdays = (msg._timestamp - time.timezone) / (24 * 60 * 60) + tdays += 719163 # pylab wants it since 0001-01-01 + add_data(tdays, msg, mlog.messages) + +if len(filenames) == 0: + print("No files to process") + sys.exit(1) + +if opts.labels is not None: + labels = opts.labels.split(',') + if len(labels) != len(fields)*len(filenames): + print("Number of labels (%u) must match number of fields (%u)" % ( + len(labels), len(fields)*len(filenames))) + sys.exit(1) +else: + labels = None + +for fi in range(0, len(filenames)): + f = filenames[fi] + process_file(f) + for i in range(0, len(x)): + if first_only[i] and fi != 0: + x[i] = [] + y[i] = [] + if labels: + lab = labels[fi*len(fields):(fi+1)*len(fields)] + else: + lab = fields[:] + plotit(x, y, lab, colors=colors[fi*len(fields):]) + for i in range(0, len(x)): + x[i] = [] + y[i] = [] +pylab.show() +raw_input('press enter to exit....') diff --git a/mavlink/share/pyshared/pymavlink/examples/mavlogdump.py b/mavlink/share/pyshared/pymavlink/examples/mavlogdump.py new file mode 100644 index 0000000000..f4cdc56bfa --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/mavlogdump.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python + +''' +example program that dumps a Mavlink log file. The log file is +assumed to be in the format that qgroundcontrol uses, which consists +of a series of MAVLink packets, each with a 64 bit timestamp +header. The timestamp is in microseconds since 1970 (unix epoch) +''' + +import sys, time, os, struct + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +from optparse import OptionParser +parser = OptionParser("mavlogdump.py [options]") + +parser.add_option("--no-timestamps",dest="notimestamps", action='store_true', help="Log doesn't have timestamps") +parser.add_option("--planner",dest="planner", action='store_true', help="use planner file format") +parser.add_option("--robust",dest="robust", action='store_true', help="Enable robust parsing (skip over bad data)") +parser.add_option("-f", "--follow",dest="follow", action='store_true', help="keep waiting for more data at end of file") +parser.add_option("--condition",dest="condition", default=None, help="select packets by condition") +parser.add_option("-q", "--quiet", dest="quiet", action='store_true', help="don't display packets") +parser.add_option("-o", "--output", default=None, help="output matching packets to give file") +parser.add_option("--mav10", action='store_true', default=False, help="Use MAVLink protocol 1.0") +parser.add_option("--types", default=None, help="types of messages (comma separated)") +(opts, args) = parser.parse_args() + +if opts.mav10: + os.environ['MAVLINK10'] = '1' +import mavutil + +if len(args) < 1: + print("Usage: mavlogdump.py [options] ") + sys.exit(1) + +filename = args[0] +mlog = mavutil.mavlink_connection(filename, planner_format=opts.planner, + notimestamps=opts.notimestamps, + robust_parsing=opts.robust) + +output = None +if opts.output: + output = mavutil.mavlogfile(opts.output, write=True) + +types = opts.types +if types is not None: + types = types.split(',') + +while True: + m = mlog.recv_match(condition=opts.condition, blocking=opts.follow) + if m is None: + break + if types is not None and m.get_type() not in types: + continue + if output: + timestamp = getattr(m, '_timestamp', None) + if timestamp: + output.write(struct.pack('>Q', timestamp*1.0e6)) + output.write(m.get_msgbuf().tostring()) + if opts.quiet: + continue + print("%s.%02u: %s" % ( + time.strftime("%Y-%m-%d %H:%M:%S", + time.localtime(m._timestamp)), + int(m._timestamp*100.0)%100, m)) + diff --git a/mavlink/share/pyshared/pymavlink/examples/mavparms.py b/mavlink/share/pyshared/pymavlink/examples/mavparms.py new file mode 100644 index 0000000000..702fbd9e1a --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/mavparms.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +''' +extract mavlink parameter values +''' + +import sys, time, os + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +from optparse import OptionParser +parser = OptionParser("mavparms.py [options]") +parser.add_option("--mav10", action='store_true', default=False, help="Use MAVLink protocol 1.0") + +(opts, args) = parser.parse_args() + +if opts.mav10: + os.environ['MAVLINK10'] = '1' +import mavutil + +if len(args) < 1: + print("Usage: mavparms.py [options] ") + sys.exit(1) + +parms = {} + +def mavparms(logfile): + '''extract mavlink parameters''' + mlog = mavutil.mavlink_connection(filename) + + while True: + m = mlog.recv_match(type='PARAM_VALUE') + if m is None: + return + pname = str(m.param_id).strip() + if len(pname) > 0: + parms[pname] = m.param_value + +total = 0.0 +for filename in args: + mavparms(filename) + +keys = parms.keys() +keys.sort() +for p in keys: + print("%-15s %.6f" % (p, parms[p])) + diff --git a/mavlink/share/pyshared/pymavlink/examples/mavtest.py b/mavlink/share/pyshared/pymavlink/examples/mavtest.py new file mode 100644 index 0000000000..3c385e48a6 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/mavtest.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python + +import sys, os + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +import mavlink + +class fifo(object): + def __init__(self): + self.buf = [] + def write(self, data): + self.buf += data + return len(data) + def read(self): + return self.buf.pop(0) + +f = fifo() + +# create a mavlink instance, which will do IO on file object 'f' +mav = mavlink.MAVLink(f) + +# set the WP_RADIUS parameter on the MAV at the end of the link +mav.param_set_send(7, 1, "WP_RADIUS", 101) + +# alternatively, produce a MAVLink_param_set object +# this can be sent via your own transport if you like +m = mav.param_set_encode(7, 1, "WP_RADIUS", 101) + +# get the encoded message as a buffer +b = m.get_msgbuf() + +# decode an incoming message +m2 = mav.decode(b) + +# show what fields it has +print("Got a message with id %u and fields %s" % (m2.get_msgId(), m2.get_fieldnames())) + +# print out the fields +print(m2) diff --git a/mavlink/share/pyshared/pymavlink/examples/mavtester.py b/mavlink/share/pyshared/pymavlink/examples/mavtester.py new file mode 100644 index 0000000000..8b5284f3fc --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/mavtester.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +''' +test mavlink messages +''' + +import sys, struct, time, os +from curses import ascii + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +import mavlink, mavtest, mavutil + +from optparse import OptionParser +parser = OptionParser("mavtester.py [options]") + +parser.add_option("--baudrate", dest="baudrate", type='int', + help="master port baud rate", default=115200) +parser.add_option("--device", dest="device", default=None, help="serial device") +parser.add_option("--source-system", dest='SOURCE_SYSTEM', type='int', + default=255, help='MAVLink source system for this GCS') +(opts, args) = parser.parse_args() + +if opts.device is None: + print("You must specify a serial device") + sys.exit(1) + +def wait_heartbeat(m): + '''wait for a heartbeat so we know the target system IDs''' + print("Waiting for APM heartbeat") + msg = m.recv_match(type='HEARTBEAT', blocking=True) + print("Heartbeat from APM (system %u component %u)" % (m.target_system, m.target_system)) + +# create a mavlink serial instance +master = mavutil.mavlink_connection(opts.device, baud=opts.baudrate, source_system=opts.SOURCE_SYSTEM) + +# wait for the heartbeat msg to find the system ID +wait_heartbeat(master) + +print("Sending all message types") +mavtest.generate_outputs(master.mav) + diff --git a/mavlink/share/pyshared/pymavlink/examples/mavtogpx.py b/mavlink/share/pyshared/pymavlink/examples/mavtogpx.py new file mode 100644 index 0000000000..92d3cb51c5 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/mavtogpx.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python + +''' +example program to extract GPS data from a mavlink log, and create a GPX +file, for loading into google earth +''' + +import sys, struct, time, os + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +from optparse import OptionParser +parser = OptionParser("mavtogpx.py [options]") +parser.add_option("--condition",dest="condition", default=None, help="select packets by a condition") +parser.add_option("--nofixcheck", default=False, action='store_true', help="don't check for GPS fix") +parser.add_option("--mav10", action='store_true', default=False, help="Use MAVLink protocol 1.0") +(opts, args) = parser.parse_args() + +if opts.mav10: + os.environ['MAVLINK10'] = '1' +import mavutil + +if len(args) < 1: + print("Usage: mavtogpx.py ") + sys.exit(1) + +def mav_to_gpx(infilename, outfilename): + '''convert a mavlink log file to a GPX file''' + + mlog = mavutil.mavlink_connection(infilename) + outf = open(outfilename, mode='w') + + def process_packet(m): + t = time.localtime(m._timestamp) + outf.write(''' + %s + + %s + %s + 3d + +''' % (m.lat, m.lon, m.alt, + time.strftime("%Y-%m-%dT%H:%M:%SZ", t), + m.hdg, m.v)) + + def add_header(): + outf.write(''' + + + +''') + + def add_footer(): + outf.write(''' + + +''') + + add_header() + + count=0 + while True: + m = mlog.recv_match(type='GPS_RAW', condition=opts.condition) + if m is None: break + if m.fix_type != 2 and not opts.nofixcheck: + continue + if m.lat == 0.0 or m.lon == 0.0: + continue + process_packet(m) + count += 1 + add_footer() + print("Created %s with %u points" % (outfilename, count)) + + +for infilename in args: + outfilename = infilename + '.gpx' + mav_to_gpx(infilename, outfilename) diff --git a/mavlink/share/pyshared/pymavlink/examples/rotmat.py b/mavlink/share/pyshared/pymavlink/examples/rotmat.py new file mode 100644 index 0000000000..6d54059495 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/rotmat.py @@ -0,0 +1,269 @@ +#!/usr/bin/env python +# +# vector3 and rotation matrix classes +# This follows the conventions in the ArduPilot code, +# and is essentially a python version of the AP_Math library +# +# Andrew Tridgell, March 2012 +# +# 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 Street, Fifth Floor, Boston, MA 02110-1301 USA + +'''rotation matrix class +''' + +from math import sin, cos, sqrt, asin, atan2, pi, radians, acos + +class Vector3: + '''a vector''' + def __init__(self, x=None, y=None, z=None): + if x != None and y != None and z != None: + self.x = float(x) + self.y = float(y) + self.z = float(z) + elif x != None and len(x) == 3: + self.x = float(x[0]) + self.y = float(x[1]) + self.z = float(x[2]) + elif x != None: + raise ValueError('bad initialiser') + else: + self.x = float(0) + self.y = float(0) + self.z = float(0) + + def __repr__(self): + return 'Vector3(%.2f, %.2f, %.2f)' % (self.x, + self.y, + self.z) + + def __add__(self, v): + return Vector3(self.x + v.x, + self.y + v.y, + self.z + v.z) + + __radd__ = __add__ + + def __sub__(self, v): + return Vector3(self.x - v.x, + self.y - v.y, + self.z - v.z) + + def __neg__(self): + return Vector3(-self.x, -self.y, -self.z) + + def __rsub__(self, v): + return Vector3(v.x - self.x, + v.y - self.y, + v.z - self.z) + + def __mul__(self, v): + if isinstance(v, Vector3): + '''dot product''' + return self.x*v.x + self.y*v.y + self.z*v.z + return Vector3(self.x * v, + self.y * v, + self.z * v) + + __rmul__ = __mul__ + + def __div__(self, v): + return Vector3(self.x / v, + self.y / v, + self.z / v) + + def __mod__(self, v): + '''cross product''' + return Vector3(self.y*v.z - self.z*v.y, + self.z*v.x - self.x*v.z, + self.x*v.y - self.y*v.x) + + def __copy__(self): + return Vector3(self.x, self.y, self.z) + + copy = __copy__ + + def length(self): + return sqrt(self.x**2 + self.y**2 + self.z**2) + + def zero(self): + self.x = self.y = self.z = 0 + + def angle(self, v): + '''return the angle between this vector and another vector''' + return acos(self * v) / (self.length() * v.length()) + + def normalized(self): + return self / self.length() + + def normalize(self): + v = self.normalized() + self.x = v.x + self.y = v.y + self.z = v.z + +class Matrix3: + '''a 3x3 matrix, intended as a rotation matrix''' + def __init__(self, a=None, b=None, c=None): + if a is not None and b is not None and c is not None: + self.a = a.copy() + self.b = b.copy() + self.c = c.copy() + else: + self.identity() + + def __repr__(self): + return 'Matrix3((%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f))' % ( + self.a.x, self.a.y, self.a.z, + self.b.x, self.b.y, self.b.z, + self.c.x, self.c.y, self.c.z) + + def identity(self): + self.a = Vector3(1,0,0) + self.b = Vector3(0,1,0) + self.c = Vector3(0,0,1) + + def transposed(self): + return Matrix3(Vector3(self.a.x, self.b.x, self.c.x), + Vector3(self.a.y, self.b.y, self.c.y), + Vector3(self.a.z, self.b.z, self.c.z)) + + + def from_euler(self, roll, pitch, yaw): + '''fill the matrix from Euler angles in radians''' + cp = cos(pitch) + sp = sin(pitch) + sr = sin(roll) + cr = cos(roll) + sy = sin(yaw) + cy = cos(yaw) + + self.a.x = cp * cy + self.a.y = (sr * sp * cy) - (cr * sy) + self.a.z = (cr * sp * cy) + (sr * sy) + self.b.x = cp * sy + self.b.y = (sr * sp * sy) + (cr * cy) + self.b.z = (cr * sp * sy) - (sr * cy) + self.c.x = -sp + self.c.y = sr * cp + self.c.z = cr * cp + + + def to_euler(self): + '''find Euler angles for the matrix''' + if self.c.x >= 1.0: + pitch = pi + elif self.c.x <= -1.0: + pitch = -pi + else: + pitch = -asin(self.c.x) + roll = atan2(self.c.y, self.c.z) + yaw = atan2(self.b.x, self.a.x) + return (roll, pitch, yaw) + + def __add__(self, m): + return Matrix3(self.a + m.a, self.b + m.b, self.c + m.c) + + __radd__ = __add__ + + def __sub__(self, m): + return Matrix3(self.a - m.a, self.b - m.b, self.c - m.c) + + def __rsub__(self, m): + return Matrix3(m.a - self.a, m.b - self.b, m.c - self.c) + + def __mul__(self, other): + if isinstance(other, Vector3): + v = other + return Vector3(self.a.x * v.x + self.a.y * v.y + self.a.z * v.z, + self.b.x * v.x + self.b.y * v.y + self.b.z * v.z, + self.c.x * v.x + self.c.y * v.y + self.c.z * v.z) + elif isinstance(other, Matrix3): + m = other + return Matrix3(Vector3(self.a.x * m.a.x + self.a.y * m.b.x + self.a.z * m.c.x, + self.a.x * m.a.y + self.a.y * m.b.y + self.a.z * m.c.y, + self.a.x * m.a.z + self.a.y * m.b.z + self.a.z * m.c.z), + Vector3(self.b.x * m.a.x + self.b.y * m.b.x + self.b.z * m.c.x, + self.b.x * m.a.y + self.b.y * m.b.y + self.b.z * m.c.y, + self.b.x * m.a.z + self.b.y * m.b.z + self.b.z * m.c.z), + Vector3(self.c.x * m.a.x + self.c.y * m.b.x + self.c.z * m.c.x, + self.c.x * m.a.y + self.c.y * m.b.y + self.c.z * m.c.y, + self.c.x * m.a.z + self.c.y * m.b.z + self.c.z * m.c.z)) + v = other + return Matrix3(self.a * v, self.b * v, self.c * v) + + def __div__(self, v): + return Matrix3(self.a / v, self.b / v, self.c / v) + + def __neg__(self): + return Matrix3(-self.a, -self.b, -self.c) + + def __copy__(self): + return Matrix3(self.a, self.b, self.c) + + copy = __copy__ + + def rotate(self, g): + '''rotate the matrix by a given amount on 3 axes''' + temp_matrix = Matrix3() + a = self.a + b = self.b + c = self.c + temp_matrix.a.x = a.y * g.z - a.z * g.y + temp_matrix.a.y = a.z * g.x - a.x * g.z + temp_matrix.a.z = a.x * g.y - a.y * g.x + temp_matrix.b.x = b.y * g.z - b.z * g.y + temp_matrix.b.y = b.z * g.x - b.x * g.z + temp_matrix.b.z = b.x * g.y - b.y * g.x + temp_matrix.c.x = c.y * g.z - c.z * g.y + temp_matrix.c.y = c.z * g.x - c.x * g.z + temp_matrix.c.z = c.x * g.y - c.y * g.x + self.a += temp_matrix.a + self.b += temp_matrix.b + self.c += temp_matrix.c + + def normalize(self): + '''re-normalise a rotation matrix''' + error = self.a * self.b + t0 = self.a - (self.b * (0.5 * error)) + t1 = self.b - (self.a * (0.5 * error)) + t2 = t0 % t1 + self.a = t0 * (1.0 / t0.length()) + self.b = t1 * (1.0 / t1.length()) + self.c = t2 * (1.0 / t2.length()) + + def trace(self): + '''the trace of the matrix''' + return self.a.x + self.b.y + self.c.z + +def test_euler(): + '''check that from_euler() and to_euler() are consistent''' + m = Matrix3() + from math import radians, degrees + for r in range(-179, 179, 3): + for p in range(-89, 89, 3): + for y in range(-179, 179, 3): + m.from_euler(radians(r), radians(p), radians(y)) + (r2, p2, y2) = m.to_euler() + v1 = Vector3(r,p,y) + v2 = Vector3(degrees(r2),degrees(p2),degrees(y2)) + diff = v1 - v2 + if diff.length() > 1.0e-12: + print('EULER ERROR:', v1, v2, diff.length()) + +if __name__ == "__main__": + import doctest + doctest.testmod() + test_euler() + diff --git a/mavlink/share/pyshared/pymavlink/examples/sigloss.py b/mavlink/share/pyshared/pymavlink/examples/sigloss.py new file mode 100644 index 0000000000..feb189d97e --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/sigloss.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +''' +show times when signal is lost +''' + +import sys, time, os + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +from optparse import OptionParser +parser = OptionParser("sigloss.py [options]") +parser.add_option("--no-timestamps",dest="notimestamps", action='store_true', help="Log doesn't have timestamps") +parser.add_option("--planner",dest="planner", action='store_true', help="use planner file format") +parser.add_option("--robust",dest="robust", action='store_true', help="Enable robust parsing (skip over bad data)") +parser.add_option("--mav10", action='store_true', default=False, help="Use MAVLink protocol 1.0") +parser.add_option("--deltat", type='float', default=1.0, help="loss threshold in seconds") + +(opts, args) = parser.parse_args() + +if opts.mav10: + os.environ['MAVLINK10'] = '1' +import mavutil + +if len(args) < 1: + print("Usage: sigloss.py [options] ") + sys.exit(1) + +def sigloss(logfile): + '''work out signal loss times for a log file''' + print("Processing log %s" % filename) + mlog = mavutil.mavlink_connection(filename, + planner_format=opts.planner, + notimestamps=opts.notimestamps, + robust_parsing=opts.robust) + + last_t = 0 + + while True: + m = mlog.recv_match() + if m is None: + return + if opts.notimestamps: + if not 'usec' in m._fieldnames: + continue + t = m.usec / 1.0e6 + else: + t = m._timestamp + if last_t != 0: + if t - last_t > opts.deltat: + print("Sig lost for %.1fs at %s" % (t-last_t, time.asctime(time.localtime(t)))) + last_t = t + +total = 0.0 +for filename in args: + sigloss(filename) diff --git a/mavlink/share/pyshared/pymavlink/examples/wptogpx.py b/mavlink/share/pyshared/pymavlink/examples/wptogpx.py new file mode 100644 index 0000000000..306f20af25 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/examples/wptogpx.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python + +''' +example program to extract GPS data from a waypoint file, and create a GPX +file, for loading into google earth +''' + +import sys, struct, time, os + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +from optparse import OptionParser +parser = OptionParser("wptogpx.py [options]") +(opts, args) = parser.parse_args() + +import mavutil, mavwp + +if len(args) < 1: + print("Usage: wptogpx.py ") + sys.exit(1) + +def wp_to_gpx(infilename, outfilename): + '''convert a wp file to a GPX file''' + + wp = mavwp.MAVWPLoader() + wp.load(infilename) + outf = open(outfilename, mode='w') + + def process_wp(w, i): + t = time.localtime(i) + outf.write(''' + %s + WP %u + +''' % (w.x, w.y, w.z, i)) + + def add_header(): + outf.write(''' + +''') + + def add_footer(): + outf.write(''' + +''') + + add_header() + + count = 0 + for i in range(wp.count()): + w = wp.wp(i) + if w.frame == 3: + w.z += wp.wp(0).z + if w.command == 16: + process_wp(w, i) + count += 1 + add_footer() + print("Created %s with %u points" % (outfilename, count)) + + +for infilename in args: + outfilename = infilename + '.gpx' + wp_to_gpx(infilename, outfilename) diff --git a/mavlink/share/pyshared/pymavlink/fgFDM.py b/mavlink/share/pyshared/pymavlink/fgFDM.py new file mode 100644 index 0000000000..f390e0a939 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/fgFDM.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python +# parse and construct FlightGear NET FDM packets +# Andrew Tridgell, November 2011 +# released under GNU GPL version 2 or later + +import struct, math + +class fgFDMError(Exception): + '''fgFDM error class''' + def __init__(self, msg): + Exception.__init__(self, msg) + self.message = 'fgFDMError: ' + msg + +class fgFDMVariable(object): + '''represent a single fgFDM variable''' + def __init__(self, index, arraylength, units): + self.index = index + self.arraylength = arraylength + self.units = units + +class fgFDMVariableList(object): + '''represent a list of fgFDM variable''' + def __init__(self): + self.vars = {} + self._nextidx = 0 + + def add(self, varname, arraylength=1, units=None): + self.vars[varname] = fgFDMVariable(self._nextidx, arraylength, units=units) + self._nextidx += arraylength + +class fgFDM(object): + '''a flightgear native FDM parser/generator''' + def __init__(self): + '''init a fgFDM object''' + self.FG_NET_FDM_VERSION = 24 + self.pack_string = '>I 4x 3d 6f 11f 3f 2f I 4I 4f 4f 4f 4f 4f 4f 4f 4f 4f I 4f I 3I 3f 3f 3f I i f 10f' + self.values = [0]*98 + + self.FG_MAX_ENGINES = 4 + self.FG_MAX_WHEELS = 3 + self.FG_MAX_TANKS = 4 + + # supported unit mappings + self.unitmap = { + ('radians', 'degrees') : math.degrees(1), + ('rps', 'dps') : math.degrees(1), + ('feet', 'meters') : 0.3048, + ('fps', 'mps') : 0.3048, + ('knots', 'mps') : 0.514444444, + ('knots', 'fps') : 0.514444444/0.3048, + ('fpss', 'mpss') : 0.3048, + ('seconds', 'minutes') : 60, + ('seconds', 'hours') : 3600, + } + + # build a mapping between variable name and index in the values array + # note that the order of this initialisation is critical - it must + # match the wire structure + self.mapping = fgFDMVariableList() + self.mapping.add('version') + + # position + self.mapping.add('longitude', units='radians') # geodetic (radians) + self.mapping.add('latitude', units='radians') # geodetic (radians) + self.mapping.add('altitude', units='meters') # above sea level (meters) + self.mapping.add('agl', units='meters') # above ground level (meters) + + # attitude + self.mapping.add('phi', units='radians') # roll (radians) + self.mapping.add('theta', units='radians') # pitch (radians) + self.mapping.add('psi', units='radians') # yaw or true heading (radians) + self.mapping.add('alpha', units='radians') # angle of attack (radians) + self.mapping.add('beta', units='radians') # side slip angle (radians) + + # Velocities + self.mapping.add('phidot', units='rps') # roll rate (radians/sec) + self.mapping.add('thetadot', units='rps') # pitch rate (radians/sec) + self.mapping.add('psidot', units='rps') # yaw rate (radians/sec) + self.mapping.add('vcas', units='fps') # calibrated airspeed + self.mapping.add('climb_rate', units='fps') # feet per second + self.mapping.add('v_north', units='fps') # north velocity in local/body frame, fps + self.mapping.add('v_east', units='fps') # east velocity in local/body frame, fps + self.mapping.add('v_down', units='fps') # down/vertical velocity in local/body frame, fps + self.mapping.add('v_wind_body_north', units='fps') # north velocity in local/body frame + self.mapping.add('v_wind_body_east', units='fps') # east velocity in local/body frame + self.mapping.add('v_wind_body_down', units='fps') # down/vertical velocity in local/body + + # Accelerations + self.mapping.add('A_X_pilot', units='fpss') # X accel in body frame ft/sec^2 + self.mapping.add('A_Y_pilot', units='fpss') # Y accel in body frame ft/sec^2 + self.mapping.add('A_Z_pilot', units='fpss') # Z accel in body frame ft/sec^2 + + # Stall + self.mapping.add('stall_warning') # 0.0 - 1.0 indicating the amount of stall + self.mapping.add('slip_deg', units='degrees') # slip ball deflection + + # Engine status + self.mapping.add('num_engines') # Number of valid engines + self.mapping.add('eng_state', self.FG_MAX_ENGINES) # Engine state (off, cranking, running) + self.mapping.add('rpm', self.FG_MAX_ENGINES) # Engine RPM rev/min + self.mapping.add('fuel_flow', self.FG_MAX_ENGINES) # Fuel flow gallons/hr + self.mapping.add('fuel_px', self.FG_MAX_ENGINES) # Fuel pressure psi + self.mapping.add('egt', self.FG_MAX_ENGINES) # Exhuast gas temp deg F + self.mapping.add('cht', self.FG_MAX_ENGINES) # Cylinder head temp deg F + self.mapping.add('mp_osi', self.FG_MAX_ENGINES) # Manifold pressure + self.mapping.add('tit', self.FG_MAX_ENGINES) # Turbine Inlet Temperature + self.mapping.add('oil_temp', self.FG_MAX_ENGINES) # Oil temp deg F + self.mapping.add('oil_px', self.FG_MAX_ENGINES) # Oil pressure psi + + # Consumables + self.mapping.add('num_tanks') # Max number of fuel tanks + self.mapping.add('fuel_quantity', self.FG_MAX_TANKS) + + # Gear status + self.mapping.add('num_wheels') + self.mapping.add('wow', self.FG_MAX_WHEELS) + self.mapping.add('gear_pos', self.FG_MAX_WHEELS) + self.mapping.add('gear_steer', self.FG_MAX_WHEELS) + self.mapping.add('gear_compression', self.FG_MAX_WHEELS) + + # Environment + self.mapping.add('cur_time', units='seconds') # current unix time + self.mapping.add('warp', units='seconds') # offset in seconds to unix time + self.mapping.add('visibility', units='meters') # visibility in meters (for env. effects) + + # Control surface positions (normalized values) + self.mapping.add('elevator') + self.mapping.add('elevator_trim_tab') + self.mapping.add('left_flap') + self.mapping.add('right_flap') + self.mapping.add('left_aileron') + self.mapping.add('right_aileron') + self.mapping.add('rudder') + self.mapping.add('nose_wheel') + self.mapping.add('speedbrake') + self.mapping.add('spoilers') + + self._packet_size = struct.calcsize(self.pack_string) + + self.set('version', self.FG_NET_FDM_VERSION) + + if len(self.values) != self.mapping._nextidx: + raise fgFDMError('Invalid variable list in initialisation') + + def packet_size(self): + '''return expected size of FG FDM packets''' + return self._packet_size + + def convert(self, value, fromunits, tounits): + '''convert a value from one set of units to another''' + if fromunits == tounits: + return value + if (fromunits,tounits) in self.unitmap: + return value * self.unitmap[(fromunits,tounits)] + if (tounits,fromunits) in self.unitmap: + return value / self.unitmap[(tounits,fromunits)] + raise fgFDMError("unknown unit mapping (%s,%s)" % (fromunits, tounits)) + + + def units(self, varname): + '''return the default units of a variable''' + if not varname in self.mapping.vars: + raise fgFDMError('Unknown variable %s' % varname) + return self.mapping.vars[varname].units + + + def variables(self): + '''return a list of available variables''' + return sorted(self.mapping.vars.keys(), + key = lambda v : self.mapping.vars[v].index) + + + def get(self, varname, idx=0, units=None): + '''get a variable value''' + if not varname in self.mapping.vars: + raise fgFDMError('Unknown variable %s' % varname) + if idx >= self.mapping.vars[varname].arraylength: + raise fgFDMError('index of %s beyond end of array idx=%u arraylength=%u' % ( + varname, idx, self.mapping.vars[varname].arraylength)) + value = self.values[self.mapping.vars[varname].index + idx] + if units: + value = self.convert(value, self.mapping.vars[varname].units, units) + return value + + def set(self, varname, value, idx=0, units=None): + '''set a variable value''' + if not varname in self.mapping.vars: + raise fgFDMError('Unknown variable %s' % varname) + if idx >= self.mapping.vars[varname].arraylength: + raise fgFDMError('index of %s beyond end of array idx=%u arraylength=%u' % ( + varname, idx, self.mapping.vars[varname].arraylength)) + if units: + value = self.convert(value, units, self.mapping.vars[varname].units) + self.values[self.mapping.vars[varname].index + idx] = value + + def parse(self, buf): + '''parse a FD FDM buffer''' + try: + t = struct.unpack(self.pack_string, buf) + except struct.error, msg: + raise fgFDMError('unable to parse - %s' % msg) + self.values = list(t) + + def pack(self): + '''pack a FD FDM buffer from current values''' + for i in range(len(self.values)): + if math.isnan(self.values[i]): + self.values[i] = 0 + return struct.pack(self.pack_string, *self.values) diff --git a/mavlink/share/pyshared/pymavlink/generator/.gitignore b/mavlink/share/pyshared/pymavlink/generator/.gitignore new file mode 100644 index 0000000000..0d20b6487c --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/checksum.h b/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/checksum.h new file mode 100644 index 0000000000..b70991f5ab --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/checksum.h @@ -0,0 +1,89 @@ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _CHECKSUM_H_ +#define _CHECKSUM_H_ + + +/** + * + * CALCULATE THE CHECKSUM + * + */ + +#define X25_INIT_CRC 0xffff +#define X25_VALIDATE_CRC 0xf0b8 + +/** + * @brief Accumulate the X.25 CRC by adding one char at a time. + * + * The checksum function adds the hash of one char at a time to the + * 16 bit checksum (uint16_t). + * + * @param data new char to hash + * @param crcAccum the already accumulated checksum + **/ +static inline void crc_accumulate(uint8_t data, uint16_t *crcAccum) +{ + /*Accumulate one byte of data into the CRC*/ + uint8_t tmp; + + tmp = data ^ (uint8_t)(*crcAccum &0xff); + tmp ^= (tmp<<4); + *crcAccum = (*crcAccum>>8) ^ (tmp<<8) ^ (tmp <<3) ^ (tmp>>4); +} + +/** + * @brief Initiliaze the buffer for the X.25 CRC + * + * @param crcAccum the 16 bit X.25 CRC + */ +static inline void crc_init(uint16_t* crcAccum) +{ + *crcAccum = X25_INIT_CRC; +} + + +/** + * @brief Calculates the X.25 checksum on a byte buffer + * + * @param pBuffer buffer containing the byte array to hash + * @param length length of the byte array + * @return the checksum over the buffer bytes + **/ +static inline uint16_t crc_calculate(uint8_t* pBuffer, uint16_t length) +{ + uint16_t crcTmp; + crc_init(&crcTmp); + while (length--) { + crc_accumulate(*pBuffer++, &crcTmp); + } + return crcTmp; +} + +/** + * @brief Accumulate the X.25 CRC by adding an array of bytes + * + * The checksum function adds the hash of one char at a time to the + * 16 bit checksum (uint16_t). + * + * @param data new bytes to hash + * @param crcAccum the already accumulated checksum + **/ +static inline void crc_accumulate_buffer(uint16_t *crcAccum, const char *pBuffer, uint8_t length) +{ + const uint8_t *p = (const uint8_t *)pBuffer; + while (length--) { + crc_accumulate(*p++, crcAccum); + } +} + + + + +#endif /* _CHECKSUM_H_ */ + +#ifdef __cplusplus +} +#endif diff --git a/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/mavlink_helpers.h b/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/mavlink_helpers.h new file mode 100644 index 0000000000..98250e1ac8 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/mavlink_helpers.h @@ -0,0 +1,488 @@ +#ifndef _MAVLINK_HELPERS_H_ +#define _MAVLINK_HELPERS_H_ + +#include "string.h" +#include "checksum.h" +#include "mavlink_types.h" + +#ifndef MAVLINK_HELPER +#define MAVLINK_HELPER +#endif + +/* + internal function to give access to the channel status for each channel + */ +MAVLINK_HELPER mavlink_status_t* mavlink_get_channel_status(uint8_t chan) +{ + static mavlink_status_t m_mavlink_status[MAVLINK_COMM_NUM_BUFFERS]; + return &m_mavlink_status[chan]; +} + +/** + * @brief Finalize a MAVLink message with channel assignment + * + * This function calculates the checksum and sets length and aircraft id correctly. + * It assumes that the message id and the payload are already correctly set. This function + * can also be used if the message header has already been written before (as in mavlink_msg_xxx_pack + * instead of mavlink_msg_xxx_pack_headerless), it just introduces little extra overhead. + * + * @param msg Message to finalize + * @param system_id Id of the sending (this) system, 1-127 + * @param length Message length + */ +#if MAVLINK_CRC_EXTRA +MAVLINK_HELPER uint16_t mavlink_finalize_message_chan(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t chan, uint8_t length, uint8_t crc_extra) +#else +MAVLINK_HELPER uint16_t mavlink_finalize_message_chan(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t chan, uint8_t length) +#endif +{ + // This code part is the same for all messages; + uint16_t checksum; + msg->magic = MAVLINK_STX; + msg->len = length; + msg->sysid = system_id; + msg->compid = component_id; + // One sequence number per component + msg->seq = mavlink_get_channel_status(chan)->current_tx_seq; + mavlink_get_channel_status(chan)->current_tx_seq = mavlink_get_channel_status(chan)->current_tx_seq+1; + checksum = crc_calculate((uint8_t*)&msg->len, length + MAVLINK_CORE_HEADER_LEN); +#if MAVLINK_CRC_EXTRA + crc_accumulate(crc_extra, &checksum); +#endif + mavlink_ck_a(msg) = (uint8_t)(checksum & 0xFF); + mavlink_ck_b(msg) = (uint8_t)(checksum >> 8); + + return length + MAVLINK_NUM_NON_PAYLOAD_BYTES; +} + + +/** + * @brief Finalize a MAVLink message with MAVLINK_COMM_0 as default channel + */ +#if MAVLINK_CRC_EXTRA +MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t length, uint8_t crc_extra) +{ + return mavlink_finalize_message_chan(msg, system_id, component_id, MAVLINK_COMM_0, length, crc_extra); +} +#else +MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t length) +{ + return mavlink_finalize_message_chan(msg, system_id, component_id, MAVLINK_COMM_0, length); +} +#endif + +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS +MAVLINK_HELPER void _mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len); + +/** + * @brief Finalize a MAVLink message with channel assignment and send + */ +#if MAVLINK_CRC_EXTRA +MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet, + uint8_t length, uint8_t crc_extra) +#else +MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet, uint8_t length) +#endif +{ + uint16_t checksum; + uint8_t buf[MAVLINK_NUM_HEADER_BYTES]; + uint8_t ck[2]; + mavlink_status_t *status = mavlink_get_channel_status(chan); + buf[0] = MAVLINK_STX; + buf[1] = length; + buf[2] = status->current_tx_seq; + buf[3] = mavlink_system.sysid; + buf[4] = mavlink_system.compid; + buf[5] = msgid; + status->current_tx_seq++; + checksum = crc_calculate((uint8_t*)&buf[1], MAVLINK_CORE_HEADER_LEN); + crc_accumulate_buffer(&checksum, packet, length); +#if MAVLINK_CRC_EXTRA + crc_accumulate(crc_extra, &checksum); +#endif + ck[0] = (uint8_t)(checksum & 0xFF); + ck[1] = (uint8_t)(checksum >> 8); + + MAVLINK_START_UART_SEND(chan, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)length); + _mavlink_send_uart(chan, (const char *)buf, MAVLINK_NUM_HEADER_BYTES); + _mavlink_send_uart(chan, packet, length); + _mavlink_send_uart(chan, (const char *)ck, 2); + MAVLINK_END_UART_SEND(chan, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)length); +} +#endif // MAVLINK_USE_CONVENIENCE_FUNCTIONS + +/** + * @brief Pack a message to send it over a serial byte stream + */ +MAVLINK_HELPER uint16_t mavlink_msg_to_send_buffer(uint8_t *buffer, const mavlink_message_t *msg) +{ + memcpy(buffer, (uint8_t *)&msg->magic, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)msg->len); + return MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)msg->len; +} + +union __mavlink_bitfield { + uint8_t uint8; + int8_t int8; + uint16_t uint16; + int16_t int16; + uint32_t uint32; + int32_t int32; +}; + + +MAVLINK_HELPER void mavlink_start_checksum(mavlink_message_t* msg) +{ + crc_init(&msg->checksum); +} + +MAVLINK_HELPER void mavlink_update_checksum(mavlink_message_t* msg, uint8_t c) +{ + crc_accumulate(c, &msg->checksum); +} + +/** + * This is a convenience function which handles the complete MAVLink parsing. + * the function will parse one byte at a time and return the complete packet once + * it could be successfully decoded. Checksum and other failures will be silently + * ignored. + * + * @param chan ID of the current channel. This allows to parse different channels with this function. + * a channel is not a physical message channel like a serial port, but a logic partition of + * the communication streams in this case. COMM_NB is the limit for the number of channels + * on MCU (e.g. ARM7), while COMM_NB_HIGH is the limit for the number of channels in Linux/Windows + * @param c The char to barse + * + * @param returnMsg NULL if no message could be decoded, the message data else + * @return 0 if no message could be decoded, 1 else + * + * A typical use scenario of this function call is: + * + * @code + * #include // For fixed-width uint8_t type + * + * mavlink_message_t msg; + * int chan = 0; + * + * + * while(serial.bytesAvailable > 0) + * { + * uint8_t byte = serial.getNextByte(); + * if (mavlink_parse_char(chan, byte, &msg)) + * { + * printf("Received message with ID %d, sequence: %d from component %d of system %d", msg.msgid, msg.seq, msg.compid, msg.sysid); + * } + * } + * + * + * @endcode + */ +MAVLINK_HELPER uint8_t mavlink_parse_char(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status) +{ + static mavlink_message_t m_mavlink_message[MAVLINK_COMM_NUM_BUFFERS]; + + /* + default message crc function. You can override this per-system to + put this data in a different memory segment + */ +#if MAVLINK_CRC_EXTRA +#ifndef MAVLINK_MESSAGE_CRC + static const uint8_t mavlink_message_crcs[256] = MAVLINK_MESSAGE_CRCS; +#define MAVLINK_MESSAGE_CRC(msgid) mavlink_message_crcs[msgid] +#endif +#endif + + mavlink_message_t* rxmsg = &m_mavlink_message[chan]; ///< The currently decoded message + mavlink_status_t* status = mavlink_get_channel_status(chan); ///< The current decode status + int bufferIndex = 0; + + status->msg_received = 0; + + switch (status->parse_state) + { + case MAVLINK_PARSE_STATE_UNINIT: + case MAVLINK_PARSE_STATE_IDLE: + if (c == MAVLINK_STX) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; + rxmsg->len = 0; + mavlink_start_checksum(rxmsg); + } + break; + + case MAVLINK_PARSE_STATE_GOT_STX: + if (status->msg_received + /* Support shorter buffers than the + default maximum packet size */ +#if (MAVLINK_MAX_PAYLOAD_LEN < 255) + || c > MAVLINK_MAX_PAYLOAD_LEN +#endif + ) + { + status->buffer_overrun++; + status->parse_error++; + status->msg_received = 0; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + } + else + { + // NOT counting STX, LENGTH, SEQ, SYSID, COMPID, MSGID, CRC1 and CRC2 + rxmsg->len = c; + status->packet_idx = 0; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_LENGTH; + } + break; + + case MAVLINK_PARSE_STATE_GOT_LENGTH: + rxmsg->seq = c; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_SEQ; + break; + + case MAVLINK_PARSE_STATE_GOT_SEQ: + rxmsg->sysid = c; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_SYSID; + break; + + case MAVLINK_PARSE_STATE_GOT_SYSID: + rxmsg->compid = c; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_COMPID; + break; + + case MAVLINK_PARSE_STATE_GOT_COMPID: + rxmsg->msgid = c; + mavlink_update_checksum(rxmsg, c); + if (rxmsg->len == 0) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD; + } + else + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_MSGID; + } + break; + + case MAVLINK_PARSE_STATE_GOT_MSGID: + _MAV_PAYLOAD(rxmsg)[status->packet_idx++] = (char)c; + mavlink_update_checksum(rxmsg, c); + if (status->packet_idx == rxmsg->len) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD; + } + break; + + case MAVLINK_PARSE_STATE_GOT_PAYLOAD: +#if MAVLINK_CRC_EXTRA + mavlink_update_checksum(rxmsg, MAVLINK_MESSAGE_CRC(rxmsg->msgid)); +#endif + if (c != (rxmsg->checksum & 0xFF)) { + // Check first checksum byte + status->parse_error++; + status->msg_received = 0; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + if (c == MAVLINK_STX) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; + rxmsg->len = 0; + mavlink_start_checksum(rxmsg); + } + } + else + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_CRC1; + } + break; + + case MAVLINK_PARSE_STATE_GOT_CRC1: + if (c != (rxmsg->checksum >> 8)) { + // Check second checksum byte + status->parse_error++; + status->msg_received = 0; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + if (c == MAVLINK_STX) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; + rxmsg->len = 0; + mavlink_start_checksum(rxmsg); + } + } + else + { + // Successfully got message + status->msg_received = 1; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + memcpy(r_message, rxmsg, sizeof(mavlink_message_t)); + } + break; + } + + bufferIndex++; + // If a message has been sucessfully decoded, check index + if (status->msg_received == 1) + { + //while(status->current_seq != rxmsg->seq) + //{ + // status->packet_rx_drop_count++; + // status->current_seq++; + //} + status->current_rx_seq = rxmsg->seq; + // Initial condition: If no packet has been received so far, drop count is undefined + if (status->packet_rx_success_count == 0) status->packet_rx_drop_count = 0; + // Count this packet as received + status->packet_rx_success_count++; + } + + r_mavlink_status->current_rx_seq = status->current_rx_seq+1; + r_mavlink_status->packet_rx_success_count = status->packet_rx_success_count; + r_mavlink_status->packet_rx_drop_count = status->parse_error; + status->parse_error = 0; + return status->msg_received; +} + +/** + * @brief Put a bitfield of length 1-32 bit into the buffer + * + * @param b the value to add, will be encoded in the bitfield + * @param bits number of bits to use to encode b, e.g. 1 for boolean, 2, 3, etc. + * @param packet_index the position in the packet (the index of the first byte to use) + * @param bit_index the position in the byte (the index of the first bit to use) + * @param buffer packet buffer to write into + * @return new position of the last used byte in the buffer + */ +MAVLINK_HELPER uint8_t put_bitfield_n_by_index(int32_t b, uint8_t bits, uint8_t packet_index, uint8_t bit_index, uint8_t* r_bit_index, uint8_t* buffer) +{ + uint16_t bits_remain = bits; + // Transform number into network order + int32_t v; + uint8_t i_bit_index, i_byte_index, curr_bits_n; +#if MAVLINK_NEED_BYTE_SWAP + union { + int32_t i; + uint8_t b[4]; + } bin, bout; + bin.i = b; + bout.b[0] = bin.b[3]; + bout.b[1] = bin.b[2]; + bout.b[2] = bin.b[1]; + bout.b[3] = bin.b[0]; + v = bout.i; +#else + v = b; +#endif + + // buffer in + // 01100000 01000000 00000000 11110001 + // buffer out + // 11110001 00000000 01000000 01100000 + + // Existing partly filled byte (four free slots) + // 0111xxxx + + // Mask n free bits + // 00001111 = 2^0 + 2^1 + 2^2 + 2^3 = 2^n - 1 + // = ((uint32_t)(1 << n)) - 1; // = 2^n - 1 + + // Shift n bits into the right position + // out = in >> n; + + // Mask and shift bytes + i_bit_index = bit_index; + i_byte_index = packet_index; + if (bit_index > 0) + { + // If bits were available at start, they were available + // in the byte before the current index + i_byte_index--; + } + + // While bits have not been packed yet + while (bits_remain > 0) + { + // Bits still have to be packed + // there can be more than 8 bits, so + // we might have to pack them into more than one byte + + // First pack everything we can into the current 'open' byte + //curr_bits_n = bits_remain << 3; // Equals bits_remain mod 8 + //FIXME + if (bits_remain <= (uint8_t)(8 - i_bit_index)) + { + // Enough space + curr_bits_n = (uint8_t)bits_remain; + } + else + { + curr_bits_n = (8 - i_bit_index); + } + + // Pack these n bits into the current byte + // Mask out whatever was at that position with ones (xxx11111) + buffer[i_byte_index] &= (0xFF >> (8 - curr_bits_n)); + // Put content to this position, by masking out the non-used part + buffer[i_byte_index] |= ((0x00 << curr_bits_n) & v); + + // Increment the bit index + i_bit_index += curr_bits_n; + + // Now proceed to the next byte, if necessary + bits_remain -= curr_bits_n; + if (bits_remain > 0) + { + // Offer another 8 bits / one byte + i_byte_index++; + i_bit_index = 0; + } + } + + *r_bit_index = i_bit_index; + // If a partly filled byte is present, mark this as consumed + if (i_bit_index != 7) i_byte_index++; + return i_byte_index - packet_index; +} + +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +// To make MAVLink work on your MCU, define comm_send_ch() if you wish +// to send 1 byte at a time, or MAVLINK_SEND_UART_BYTES() to send a +// whole packet at a time + +/* + +#include "mavlink_types.h" + +void comm_send_ch(mavlink_channel_t chan, uint8_t ch) +{ + if (chan == MAVLINK_COMM_0) + { + uart0_transmit(ch); + } + if (chan == MAVLINK_COMM_1) + { + uart1_transmit(ch); + } +} + */ + +MAVLINK_HELPER void _mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len) +{ +#ifdef MAVLINK_SEND_UART_BYTES + /* this is the more efficient approach, if the platform + defines it */ + MAVLINK_SEND_UART_BYTES(chan, (uint8_t *)buf, len); +#else + /* fallback to one byte at a time */ + uint16_t i; + for (i = 0; i < len; i++) { + comm_send_ch(chan, (uint8_t)buf[i]); + } +#endif +} +#endif // MAVLINK_USE_CONVENIENCE_FUNCTIONS + +#endif /* _MAVLINK_HELPERS_H_ */ diff --git a/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/mavlink_types.h b/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/mavlink_types.h new file mode 100644 index 0000000000..630cb84b77 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/mavlink_types.h @@ -0,0 +1,300 @@ +#ifndef MAVLINK_TYPES_H_ +#define MAVLINK_TYPES_H_ + +#include "inttypes.h" + +enum MAV_CLASS +{ + MAV_CLASS_GENERIC = 0, ///< Generic autopilot, full support for everything + MAV_CLASS_PIXHAWK = 1, ///< PIXHAWK autopilot, http://pixhawk.ethz.ch + MAV_CLASS_SLUGS = 2, ///< SLUGS autopilot, http://slugsuav.soe.ucsc.edu + MAV_CLASS_ARDUPILOTMEGA = 3, ///< ArduPilotMega / ArduCopter, http://diydrones.com + MAV_CLASS_OPENPILOT = 4, ///< OpenPilot, http://openpilot.org + MAV_CLASS_GENERIC_MISSION_WAYPOINTS_ONLY = 5, ///< Generic autopilot only supporting simple waypoints + MAV_CLASS_GENERIC_MISSION_NAVIGATION_ONLY = 6, ///< Generic autopilot supporting waypoints and other simple navigation commands + MAV_CLASS_GENERIC_MISSION_FULL = 7, ///< Generic autopilot supporting the full mission command set + MAV_CLASS_NONE = 8, ///< No valid autopilot + MAV_CLASS_NB ///< Number of autopilot classes +}; + +enum MAV_ACTION +{ + MAV_ACTION_HOLD = 0, + MAV_ACTION_MOTORS_START = 1, + MAV_ACTION_LAUNCH = 2, + MAV_ACTION_RETURN = 3, + MAV_ACTION_EMCY_LAND = 4, + MAV_ACTION_EMCY_KILL = 5, + MAV_ACTION_CONFIRM_KILL = 6, + MAV_ACTION_CONTINUE = 7, + MAV_ACTION_MOTORS_STOP = 8, + MAV_ACTION_HALT = 9, + MAV_ACTION_SHUTDOWN = 10, + MAV_ACTION_REBOOT = 11, + MAV_ACTION_SET_MANUAL = 12, + MAV_ACTION_SET_AUTO = 13, + MAV_ACTION_STORAGE_READ = 14, + MAV_ACTION_STORAGE_WRITE = 15, + MAV_ACTION_CALIBRATE_RC = 16, + MAV_ACTION_CALIBRATE_GYRO = 17, + MAV_ACTION_CALIBRATE_MAG = 18, + MAV_ACTION_CALIBRATE_ACC = 19, + MAV_ACTION_CALIBRATE_PRESSURE = 20, + MAV_ACTION_REC_START = 21, + MAV_ACTION_REC_PAUSE = 22, + MAV_ACTION_REC_STOP = 23, + MAV_ACTION_TAKEOFF = 24, + MAV_ACTION_NAVIGATE = 25, + MAV_ACTION_LAND = 26, + MAV_ACTION_LOITER = 27, + MAV_ACTION_SET_ORIGIN = 28, + MAV_ACTION_RELAY_ON = 29, + MAV_ACTION_RELAY_OFF = 30, + MAV_ACTION_GET_IMAGE = 31, + MAV_ACTION_VIDEO_START = 32, + MAV_ACTION_VIDEO_STOP = 33, + MAV_ACTION_RESET_MAP = 34, + MAV_ACTION_RESET_PLAN = 35, + MAV_ACTION_DELAY_BEFORE_COMMAND = 36, + MAV_ACTION_ASCEND_AT_RATE = 37, + MAV_ACTION_CHANGE_MODE = 38, + MAV_ACTION_LOITER_MAX_TURNS = 39, + MAV_ACTION_LOITER_MAX_TIME = 40, + MAV_ACTION_START_HILSIM = 41, + MAV_ACTION_STOP_HILSIM = 42, + MAV_ACTION_NB ///< Number of MAV actions +}; + +enum MAV_MODE +{ + MAV_MODE_UNINIT = 0, ///< System is in undefined state + MAV_MODE_LOCKED = 1, ///< Motors are blocked, system is safe + MAV_MODE_MANUAL = 2, ///< System is allowed to be active, under manual (RC) control + MAV_MODE_GUIDED = 3, ///< System is allowed to be active, under autonomous control, manual setpoint + MAV_MODE_AUTO = 4, ///< System is allowed to be active, under autonomous control and navigation + MAV_MODE_TEST1 = 5, ///< Generic test mode, for custom use + MAV_MODE_TEST2 = 6, ///< Generic test mode, for custom use + MAV_MODE_TEST3 = 7, ///< Generic test mode, for custom use + MAV_MODE_READY = 8, ///< System is ready, motors are unblocked, but controllers are inactive + MAV_MODE_RC_TRAINING = 9 ///< System is blocked, only RC valued are read and reported back +}; + +enum MAV_STATE +{ + MAV_STATE_UNINIT = 0, + MAV_STATE_BOOT, + MAV_STATE_CALIBRATING, + MAV_STATE_STANDBY, + MAV_STATE_ACTIVE, + MAV_STATE_CRITICAL, + MAV_STATE_EMERGENCY, + MAV_STATE_HILSIM, + MAV_STATE_POWEROFF +}; + +enum MAV_NAV +{ + MAV_NAV_GROUNDED = 0, + MAV_NAV_LIFTOFF, + MAV_NAV_HOLD, + MAV_NAV_WAYPOINT, + MAV_NAV_VECTOR, + MAV_NAV_RETURNING, + MAV_NAV_LANDING, + MAV_NAV_LOST, + MAV_NAV_LOITER, + MAV_NAV_FREE_DRIFT +}; + +enum MAV_TYPE +{ + MAV_GENERIC = 0, + MAV_FIXED_WING = 1, + MAV_QUADROTOR = 2, + MAV_COAXIAL = 3, + MAV_HELICOPTER = 4, + MAV_GROUND = 5, + OCU = 6, + MAV_AIRSHIP = 7, + MAV_FREE_BALLOON = 8, + MAV_ROCKET = 9, + UGV_GROUND_ROVER = 10, + UGV_SURFACE_SHIP = 11 +}; + +enum MAV_AUTOPILOT_TYPE +{ + MAV_AUTOPILOT_GENERIC = 0, + MAV_AUTOPILOT_PIXHAWK = 1, + MAV_AUTOPILOT_SLUGS = 2, + MAV_AUTOPILOT_ARDUPILOTMEGA = 3, + MAV_AUTOPILOT_NONE = 4 +}; + +enum MAV_COMPONENT +{ + MAV_COMP_ID_GPS, + MAV_COMP_ID_WAYPOINTPLANNER, + MAV_COMP_ID_BLOBTRACKER, + MAV_COMP_ID_PATHPLANNER, + MAV_COMP_ID_AIRSLAM, + MAV_COMP_ID_MAPPER, + MAV_COMP_ID_CAMERA, + MAV_COMP_ID_RADIO = 68, + MAV_COMP_ID_IMU = 200, + MAV_COMP_ID_IMU_2 = 201, + MAV_COMP_ID_IMU_3 = 202, + MAV_COMP_ID_UDP_BRIDGE = 240, + MAV_COMP_ID_UART_BRIDGE = 241, + MAV_COMP_ID_SYSTEM_CONTROL = 250 +}; + +enum MAV_FRAME +{ + MAV_FRAME_GLOBAL = 0, + MAV_FRAME_LOCAL = 1, + MAV_FRAME_MISSION = 2, + MAV_FRAME_GLOBAL_RELATIVE_ALT = 3, + MAV_FRAME_LOCAL_ENU = 4 +}; + +enum MAVLINK_DATA_STREAM_TYPE +{ + MAVLINK_DATA_STREAM_IMG_JPEG, + MAVLINK_DATA_STREAM_IMG_BMP, + MAVLINK_DATA_STREAM_IMG_RAW8U, + MAVLINK_DATA_STREAM_IMG_RAW32U, + MAVLINK_DATA_STREAM_IMG_PGM, + MAVLINK_DATA_STREAM_IMG_PNG +}; + +#ifndef MAVLINK_MAX_PAYLOAD_LEN +// it is possible to override this, but be careful! +#define MAVLINK_MAX_PAYLOAD_LEN 255 ///< Maximum payload length +#endif + +#define MAVLINK_CORE_HEADER_LEN 5 ///< Length of core header (of the comm. layer): message length (1 byte) + message sequence (1 byte) + message system id (1 byte) + message component id (1 byte) + message type id (1 byte) +#define MAVLINK_NUM_HEADER_BYTES (MAVLINK_CORE_HEADER_LEN + 1) ///< Length of all header bytes, including core and checksum +#define MAVLINK_NUM_CHECKSUM_BYTES 2 +#define MAVLINK_NUM_NON_PAYLOAD_BYTES (MAVLINK_NUM_HEADER_BYTES + MAVLINK_NUM_CHECKSUM_BYTES) + +#define MAVLINK_MAX_PACKET_LEN (MAVLINK_MAX_PAYLOAD_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES) ///< Maximum packet length + +typedef struct param_union { + union { + float param_float; + int32_t param_int32; + uint32_t param_uint32; + }; + uint8_t type; +} mavlink_param_union_t; + +typedef struct __mavlink_system { + uint8_t sysid; ///< Used by the MAVLink message_xx_send() convenience function + uint8_t compid; ///< Used by the MAVLink message_xx_send() convenience function + uint8_t type; ///< Unused, can be used by user to store the system's type + uint8_t state; ///< Unused, can be used by user to store the system's state + uint8_t mode; ///< Unused, can be used by user to store the system's mode + uint8_t nav_mode; ///< Unused, can be used by user to store the system's navigation mode +} mavlink_system_t; + +typedef struct __mavlink_message { + uint16_t checksum; /// sent at end of packet + uint8_t magic; ///< protocol magic marker + uint8_t len; ///< Length of payload + uint8_t seq; ///< Sequence of packet + uint8_t sysid; ///< ID of message sender system/aircraft + uint8_t compid; ///< ID of the message sender component + uint8_t msgid; ///< ID of message in payload + uint64_t payload64[(MAVLINK_MAX_PAYLOAD_LEN+MAVLINK_NUM_CHECKSUM_BYTES+7)/8]; +} mavlink_message_t; + +typedef enum { + MAVLINK_TYPE_CHAR = 0, + MAVLINK_TYPE_UINT8_T = 1, + MAVLINK_TYPE_INT8_T = 2, + MAVLINK_TYPE_UINT16_T = 3, + MAVLINK_TYPE_INT16_T = 4, + MAVLINK_TYPE_UINT32_T = 5, + MAVLINK_TYPE_INT32_T = 6, + MAVLINK_TYPE_UINT64_T = 7, + MAVLINK_TYPE_INT64_T = 8, + MAVLINK_TYPE_FLOAT = 9, + MAVLINK_TYPE_DOUBLE = 10 +} mavlink_message_type_t; + +#define MAVLINK_MAX_FIELDS 64 + +typedef struct __mavlink_field_info { + const char *name; // name of this field + const char *print_format; // printing format hint, or NULL + mavlink_message_type_t type; // type of this field + unsigned array_length; // if non-zero, field is an array + unsigned wire_offset; // offset of each field in the payload + unsigned structure_offset; // offset in a C structure +} mavlink_field_info_t; + +// note that in this structure the order of fields is the order +// in the XML file, not necessary the wire order +typedef struct __mavlink_message_info { + const char *name; // name of the message + unsigned num_fields; // how many fields in this message + mavlink_field_info_t fields[MAVLINK_MAX_FIELDS]; // field information +} mavlink_message_info_t; + +#define _MAV_PAYLOAD(msg) ((char *)(&(msg)->payload64[0])) +#define _MAV_PAYLOAD_NON_CONST(msg) ((char *)(&((msg)->payload64[0]))) + +// checksum is immediately after the payload bytes +#define mavlink_ck_a(msg) *(msg->len + (uint8_t *)_MAV_PAYLOAD(msg)) +#define mavlink_ck_b(msg) *((msg->len+(uint16_t)1) + (uint8_t *)_MAV_PAYLOAD(msg)) + +typedef enum { + MAVLINK_COMM_0, + MAVLINK_COMM_1, + MAVLINK_COMM_2, + MAVLINK_COMM_3 +} mavlink_channel_t; + +/* + * applications can set MAVLINK_COMM_NUM_BUFFERS to the maximum number + * of buffers they will use. If more are used, then the result will be + * a stack overrun + */ +#ifndef MAVLINK_COMM_NUM_BUFFERS +#if (defined linux) | (defined __linux) | (defined __MACH__) | (defined _WIN32) +# define MAVLINK_COMM_NUM_BUFFERS 16 +#else +# define MAVLINK_COMM_NUM_BUFFERS 4 +#endif +#endif + +typedef enum { + MAVLINK_PARSE_STATE_UNINIT=0, + MAVLINK_PARSE_STATE_IDLE, + MAVLINK_PARSE_STATE_GOT_STX, + MAVLINK_PARSE_STATE_GOT_SEQ, + MAVLINK_PARSE_STATE_GOT_LENGTH, + MAVLINK_PARSE_STATE_GOT_SYSID, + MAVLINK_PARSE_STATE_GOT_COMPID, + MAVLINK_PARSE_STATE_GOT_MSGID, + MAVLINK_PARSE_STATE_GOT_PAYLOAD, + MAVLINK_PARSE_STATE_GOT_CRC1 +} mavlink_parse_state_t; ///< The state machine for the comm parser + +typedef struct __mavlink_status { + uint8_t msg_received; ///< Number of received messages + uint8_t buffer_overrun; ///< Number of buffer overruns + uint8_t parse_error; ///< Number of parse errors + mavlink_parse_state_t parse_state; ///< Parsing state machine + uint8_t packet_idx; ///< Index in current packet + uint8_t current_rx_seq; ///< Sequence number of last packet received + uint8_t current_tx_seq; ///< Sequence number of last packet sent + uint16_t packet_rx_success_count; ///< Received packets + uint16_t packet_rx_drop_count; ///< Number of packet drops +} mavlink_status_t; + +#define MAVLINK_BIG_ENDIAN 0 +#define MAVLINK_LITTLE_ENDIAN 1 + +#endif /* MAVLINK_TYPES_H_ */ diff --git a/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/protocol.h b/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/protocol.h new file mode 100644 index 0000000000..05195c3691 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/protocol.h @@ -0,0 +1,319 @@ +#ifndef _MAVLINK_PROTOCOL_H_ +#define _MAVLINK_PROTOCOL_H_ + +#include "string.h" +#include "mavlink_types.h" + +/* + If you want MAVLink on a system that is native big-endian, + you need to define NATIVE_BIG_ENDIAN +*/ +#ifdef NATIVE_BIG_ENDIAN +# define MAVLINK_NEED_BYTE_SWAP (MAVLINK_ENDIAN == MAVLINK_LITTLE_ENDIAN) +#else +# define MAVLINK_NEED_BYTE_SWAP (MAVLINK_ENDIAN != MAVLINK_LITTLE_ENDIAN) +#endif + +#ifndef MAVLINK_STACK_BUFFER +#define MAVLINK_STACK_BUFFER 0 +#endif + +#ifndef MAVLINK_AVOID_GCC_STACK_BUG +# define MAVLINK_AVOID_GCC_STACK_BUG defined(__GNUC__) +#endif + +#ifndef MAVLINK_ASSERT +#define MAVLINK_ASSERT(x) +#endif + +#ifndef MAVLINK_START_UART_SEND +#define MAVLINK_START_UART_SEND(chan, length) +#endif + +#ifndef MAVLINK_END_UART_SEND +#define MAVLINK_END_UART_SEND(chan, length) +#endif + +#ifdef MAVLINK_SEPARATE_HELPERS +#define MAVLINK_HELPER +#else +#define MAVLINK_HELPER static inline +#include "mavlink_helpers.h" +#endif // MAVLINK_SEPARATE_HELPERS + +/* always include the prototypes to ensure we don't get out of sync */ +MAVLINK_HELPER mavlink_status_t* mavlink_get_channel_status(uint8_t chan); +#if MAVLINK_CRC_EXTRA +MAVLINK_HELPER uint16_t mavlink_finalize_message_chan(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t chan, uint8_t length, uint8_t crc_extra); +MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t length, uint8_t crc_extra); +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS +MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet, + uint8_t length, uint8_t crc_extra); +#endif +#else +MAVLINK_HELPER uint16_t mavlink_finalize_message_chan(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t chan, uint8_t length); +MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t length); +MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet, uint8_t length); +#endif // MAVLINK_CRC_EXTRA +MAVLINK_HELPER uint16_t mavlink_msg_to_send_buffer(uint8_t *buffer, const mavlink_message_t *msg); +MAVLINK_HELPER void mavlink_start_checksum(mavlink_message_t* msg); +MAVLINK_HELPER void mavlink_update_checksum(mavlink_message_t* msg, uint8_t c); +MAVLINK_HELPER uint8_t mavlink_parse_char(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status); +MAVLINK_HELPER uint8_t put_bitfield_n_by_index(int32_t b, uint8_t bits, uint8_t packet_index, uint8_t bit_index, + uint8_t* r_bit_index, uint8_t* buffer); +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS +MAVLINK_HELPER void _mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len); +#endif + +/** + * @brief Get the required buffer size for this message + */ +static inline uint16_t mavlink_msg_get_send_buffer_length(const mavlink_message_t* msg) +{ + return msg->len + MAVLINK_NUM_NON_PAYLOAD_BYTES; +} + +#if MAVLINK_NEED_BYTE_SWAP +static inline void byte_swap_2(char *dst, const char *src) +{ + dst[0] = src[1]; + dst[1] = src[0]; +} +static inline void byte_swap_4(char *dst, const char *src) +{ + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; +} +static inline void byte_swap_8(char *dst, const char *src) +{ + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; +} +#elif !MAVLINK_ALIGNED_FIELDS +static inline void byte_copy_2(char *dst, const char *src) +{ + dst[0] = src[0]; + dst[1] = src[1]; +} +static inline void byte_copy_4(char *dst, const char *src) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} +static inline void byte_copy_8(char *dst, const char *src) +{ + memcpy(dst, src, 8); +} +#endif + +#define _mav_put_uint8_t(buf, wire_offset, b) buf[wire_offset] = (uint8_t)b +#define _mav_put_int8_t(buf, wire_offset, b) buf[wire_offset] = (int8_t)b +#define _mav_put_char(buf, wire_offset, b) buf[wire_offset] = b + +#if MAVLINK_NEED_BYTE_SWAP +#define _mav_put_uint16_t(buf, wire_offset, b) byte_swap_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_int16_t(buf, wire_offset, b) byte_swap_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint32_t(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_int32_t(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint64_t(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_int64_t(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_float(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_double(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b) +#elif !MAVLINK_ALIGNED_FIELDS +#define _mav_put_uint16_t(buf, wire_offset, b) byte_copy_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_int16_t(buf, wire_offset, b) byte_copy_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint32_t(buf, wire_offset, b) byte_copy_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_int32_t(buf, wire_offset, b) byte_copy_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint64_t(buf, wire_offset, b) byte_copy_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_int64_t(buf, wire_offset, b) byte_copy_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_float(buf, wire_offset, b) byte_copy_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_double(buf, wire_offset, b) byte_copy_8(&buf[wire_offset], (const char *)&b) +#else +#define _mav_put_uint16_t(buf, wire_offset, b) *(uint16_t *)&buf[wire_offset] = b +#define _mav_put_int16_t(buf, wire_offset, b) *(int16_t *)&buf[wire_offset] = b +#define _mav_put_uint32_t(buf, wire_offset, b) *(uint32_t *)&buf[wire_offset] = b +#define _mav_put_int32_t(buf, wire_offset, b) *(int32_t *)&buf[wire_offset] = b +#define _mav_put_uint64_t(buf, wire_offset, b) *(uint64_t *)&buf[wire_offset] = b +#define _mav_put_int64_t(buf, wire_offset, b) *(int64_t *)&buf[wire_offset] = b +#define _mav_put_float(buf, wire_offset, b) *(float *)&buf[wire_offset] = b +#define _mav_put_double(buf, wire_offset, b) *(double *)&buf[wire_offset] = b +#endif + +/* + like memcpy(), but if src is NULL, do a memset to zero + */ +static void mav_array_memcpy(void *dest, const void *src, size_t n) +{ + if (src == NULL) { + memset(dest, 0, n); + } else { + memcpy(dest, src, n); + } +} + +/* + * Place a char array into a buffer + */ +static inline void _mav_put_char_array(char *buf, uint8_t wire_offset, const char *b, uint8_t array_length) +{ + mav_array_memcpy(&buf[wire_offset], b, array_length); +} + +/* + * Place a uint8_t array into a buffer + */ +static inline void _mav_put_uint8_t_array(char *buf, uint8_t wire_offset, const uint8_t *b, uint8_t array_length) +{ + mav_array_memcpy(&buf[wire_offset], b, array_length); +} + +/* + * Place a int8_t array into a buffer + */ +static inline void _mav_put_int8_t_array(char *buf, uint8_t wire_offset, const int8_t *b, uint8_t array_length) +{ + mav_array_memcpy(&buf[wire_offset], b, array_length); +} + +#if MAVLINK_NEED_BYTE_SWAP +#define _MAV_PUT_ARRAY(TYPE, V) \ +static inline void _mav_put_ ## TYPE ##_array(char *buf, uint8_t wire_offset, const TYPE *b, uint8_t array_length) \ +{ \ + if (b == NULL) { \ + memset(&buf[wire_offset], 0, array_length*sizeof(TYPE)); \ + } else { \ + uint16_t i; \ + for (i=0; imsgid = MAVLINK_MSG_ID_TEST_TYPES; + return mavlink_finalize_message(msg, system_id, component_id, 179); +} + +/** + * @brief Pack a test_types message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param c char + * @param s string + * @param u8 uint8_t + * @param u16 uint16_t + * @param u32 uint32_t + * @param u64 uint64_t + * @param s8 int8_t + * @param s16 int16_t + * @param s32 int32_t + * @param s64 int64_t + * @param f float + * @param d double + * @param u8_array uint8_t_array + * @param u16_array uint16_t_array + * @param u32_array uint32_t_array + * @param u64_array uint64_t_array + * @param s8_array int8_t_array + * @param s16_array int16_t_array + * @param s32_array int32_t_array + * @param s64_array int64_t_array + * @param f_array float_array + * @param d_array double_array + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_test_types_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + char c,const char *s,uint8_t u8,uint16_t u16,uint32_t u32,uint64_t u64,int8_t s8,int16_t s16,int32_t s32,int64_t s64,float f,double d,const uint8_t *u8_array,const uint16_t *u16_array,const uint32_t *u32_array,const uint64_t *u64_array,const int8_t *s8_array,const int16_t *s16_array,const int32_t *s32_array,const int64_t *s64_array,const float *f_array,const double *d_array) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[179]; + _mav_put_char(buf, 0, c); + _mav_put_uint8_t(buf, 11, u8); + _mav_put_uint16_t(buf, 12, u16); + _mav_put_uint32_t(buf, 14, u32); + _mav_put_uint64_t(buf, 18, u64); + _mav_put_int8_t(buf, 26, s8); + _mav_put_int16_t(buf, 27, s16); + _mav_put_int32_t(buf, 29, s32); + _mav_put_int64_t(buf, 33, s64); + _mav_put_float(buf, 41, f); + _mav_put_double(buf, 45, d); + _mav_put_char_array(buf, 1, s, 10); + _mav_put_uint8_t_array(buf, 53, u8_array, 3); + _mav_put_uint16_t_array(buf, 56, u16_array, 3); + _mav_put_uint32_t_array(buf, 62, u32_array, 3); + _mav_put_uint64_t_array(buf, 74, u64_array, 3); + _mav_put_int8_t_array(buf, 98, s8_array, 3); + _mav_put_int16_t_array(buf, 101, s16_array, 3); + _mav_put_int32_t_array(buf, 107, s32_array, 3); + _mav_put_int64_t_array(buf, 119, s64_array, 3); + _mav_put_float_array(buf, 143, f_array, 3); + _mav_put_double_array(buf, 155, d_array, 3); + memcpy(_MAV_PAYLOAD(msg), buf, 179); +#else + mavlink_test_types_t packet; + packet.c = c; + packet.u8 = u8; + packet.u16 = u16; + packet.u32 = u32; + packet.u64 = u64; + packet.s8 = s8; + packet.s16 = s16; + packet.s32 = s32; + packet.s64 = s64; + packet.f = f; + packet.d = d; + mav_array_memcpy(packet.s, s, sizeof(char)*10); + mav_array_memcpy(packet.u8_array, u8_array, sizeof(uint8_t)*3); + mav_array_memcpy(packet.u16_array, u16_array, sizeof(uint16_t)*3); + mav_array_memcpy(packet.u32_array, u32_array, sizeof(uint32_t)*3); + mav_array_memcpy(packet.u64_array, u64_array, sizeof(uint64_t)*3); + mav_array_memcpy(packet.s8_array, s8_array, sizeof(int8_t)*3); + mav_array_memcpy(packet.s16_array, s16_array, sizeof(int16_t)*3); + mav_array_memcpy(packet.s32_array, s32_array, sizeof(int32_t)*3); + mav_array_memcpy(packet.s64_array, s64_array, sizeof(int64_t)*3); + mav_array_memcpy(packet.f_array, f_array, sizeof(float)*3); + mav_array_memcpy(packet.d_array, d_array, sizeof(double)*3); + memcpy(_MAV_PAYLOAD(msg), &packet, 179); +#endif + + msg->msgid = MAVLINK_MSG_ID_TEST_TYPES; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 179); +} + +/** + * @brief Encode a test_types struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param test_types C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_test_types_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_test_types_t* test_types) +{ + return mavlink_msg_test_types_pack(system_id, component_id, msg, test_types->c, test_types->s, test_types->u8, test_types->u16, test_types->u32, test_types->u64, test_types->s8, test_types->s16, test_types->s32, test_types->s64, test_types->f, test_types->d, test_types->u8_array, test_types->u16_array, test_types->u32_array, test_types->u64_array, test_types->s8_array, test_types->s16_array, test_types->s32_array, test_types->s64_array, test_types->f_array, test_types->d_array); +} + +/** + * @brief Send a test_types message + * @param chan MAVLink channel to send the message + * + * @param c char + * @param s string + * @param u8 uint8_t + * @param u16 uint16_t + * @param u32 uint32_t + * @param u64 uint64_t + * @param s8 int8_t + * @param s16 int16_t + * @param s32 int32_t + * @param s64 int64_t + * @param f float + * @param d double + * @param u8_array uint8_t_array + * @param u16_array uint16_t_array + * @param u32_array uint32_t_array + * @param u64_array uint64_t_array + * @param s8_array int8_t_array + * @param s16_array int16_t_array + * @param s32_array int32_t_array + * @param s64_array int64_t_array + * @param f_array float_array + * @param d_array double_array + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_test_types_send(mavlink_channel_t chan, char c, const char *s, uint8_t u8, uint16_t u16, uint32_t u32, uint64_t u64, int8_t s8, int16_t s16, int32_t s32, int64_t s64, float f, double d, const uint8_t *u8_array, const uint16_t *u16_array, const uint32_t *u32_array, const uint64_t *u64_array, const int8_t *s8_array, const int16_t *s16_array, const int32_t *s32_array, const int64_t *s64_array, const float *f_array, const double *d_array) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[179]; + _mav_put_char(buf, 0, c); + _mav_put_uint8_t(buf, 11, u8); + _mav_put_uint16_t(buf, 12, u16); + _mav_put_uint32_t(buf, 14, u32); + _mav_put_uint64_t(buf, 18, u64); + _mav_put_int8_t(buf, 26, s8); + _mav_put_int16_t(buf, 27, s16); + _mav_put_int32_t(buf, 29, s32); + _mav_put_int64_t(buf, 33, s64); + _mav_put_float(buf, 41, f); + _mav_put_double(buf, 45, d); + _mav_put_char_array(buf, 1, s, 10); + _mav_put_uint8_t_array(buf, 53, u8_array, 3); + _mav_put_uint16_t_array(buf, 56, u16_array, 3); + _mav_put_uint32_t_array(buf, 62, u32_array, 3); + _mav_put_uint64_t_array(buf, 74, u64_array, 3); + _mav_put_int8_t_array(buf, 98, s8_array, 3); + _mav_put_int16_t_array(buf, 101, s16_array, 3); + _mav_put_int32_t_array(buf, 107, s32_array, 3); + _mav_put_int64_t_array(buf, 119, s64_array, 3); + _mav_put_float_array(buf, 143, f_array, 3); + _mav_put_double_array(buf, 155, d_array, 3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_TEST_TYPES, buf, 179); +#else + mavlink_test_types_t packet; + packet.c = c; + packet.u8 = u8; + packet.u16 = u16; + packet.u32 = u32; + packet.u64 = u64; + packet.s8 = s8; + packet.s16 = s16; + packet.s32 = s32; + packet.s64 = s64; + packet.f = f; + packet.d = d; + mav_array_memcpy(packet.s, s, sizeof(char)*10); + mav_array_memcpy(packet.u8_array, u8_array, sizeof(uint8_t)*3); + mav_array_memcpy(packet.u16_array, u16_array, sizeof(uint16_t)*3); + mav_array_memcpy(packet.u32_array, u32_array, sizeof(uint32_t)*3); + mav_array_memcpy(packet.u64_array, u64_array, sizeof(uint64_t)*3); + mav_array_memcpy(packet.s8_array, s8_array, sizeof(int8_t)*3); + mav_array_memcpy(packet.s16_array, s16_array, sizeof(int16_t)*3); + mav_array_memcpy(packet.s32_array, s32_array, sizeof(int32_t)*3); + mav_array_memcpy(packet.s64_array, s64_array, sizeof(int64_t)*3); + mav_array_memcpy(packet.f_array, f_array, sizeof(float)*3); + mav_array_memcpy(packet.d_array, d_array, sizeof(double)*3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_TEST_TYPES, (const char *)&packet, 179); +#endif +} + +#endif + +// MESSAGE TEST_TYPES UNPACKING + + +/** + * @brief Get field c from test_types message + * + * @return char + */ +static inline char mavlink_msg_test_types_get_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_char(msg, 0); +} + +/** + * @brief Get field s from test_types message + * + * @return string + */ +static inline uint16_t mavlink_msg_test_types_get_s(const mavlink_message_t* msg, char *s) +{ + return _MAV_RETURN_char_array(msg, s, 10, 1); +} + +/** + * @brief Get field u8 from test_types message + * + * @return uint8_t + */ +static inline uint8_t mavlink_msg_test_types_get_u8(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 11); +} + +/** + * @brief Get field u16 from test_types message + * + * @return uint16_t + */ +static inline uint16_t mavlink_msg_test_types_get_u16(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 12); +} + +/** + * @brief Get field u32 from test_types message + * + * @return uint32_t + */ +static inline uint32_t mavlink_msg_test_types_get_u32(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 14); +} + +/** + * @brief Get field u64 from test_types message + * + * @return uint64_t + */ +static inline uint64_t mavlink_msg_test_types_get_u64(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 18); +} + +/** + * @brief Get field s8 from test_types message + * + * @return int8_t + */ +static inline int8_t mavlink_msg_test_types_get_s8(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int8_t(msg, 26); +} + +/** + * @brief Get field s16 from test_types message + * + * @return int16_t + */ +static inline int16_t mavlink_msg_test_types_get_s16(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 27); +} + +/** + * @brief Get field s32 from test_types message + * + * @return int32_t + */ +static inline int32_t mavlink_msg_test_types_get_s32(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 29); +} + +/** + * @brief Get field s64 from test_types message + * + * @return int64_t + */ +static inline int64_t mavlink_msg_test_types_get_s64(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int64_t(msg, 33); +} + +/** + * @brief Get field f from test_types message + * + * @return float + */ +static inline float mavlink_msg_test_types_get_f(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 41); +} + +/** + * @brief Get field d from test_types message + * + * @return double + */ +static inline double mavlink_msg_test_types_get_d(const mavlink_message_t* msg) +{ + return _MAV_RETURN_double(msg, 45); +} + +/** + * @brief Get field u8_array from test_types message + * + * @return uint8_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u8_array(const mavlink_message_t* msg, uint8_t *u8_array) +{ + return _MAV_RETURN_uint8_t_array(msg, u8_array, 3, 53); +} + +/** + * @brief Get field u16_array from test_types message + * + * @return uint16_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u16_array(const mavlink_message_t* msg, uint16_t *u16_array) +{ + return _MAV_RETURN_uint16_t_array(msg, u16_array, 3, 56); +} + +/** + * @brief Get field u32_array from test_types message + * + * @return uint32_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u32_array(const mavlink_message_t* msg, uint32_t *u32_array) +{ + return _MAV_RETURN_uint32_t_array(msg, u32_array, 3, 62); +} + +/** + * @brief Get field u64_array from test_types message + * + * @return uint64_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u64_array(const mavlink_message_t* msg, uint64_t *u64_array) +{ + return _MAV_RETURN_uint64_t_array(msg, u64_array, 3, 74); +} + +/** + * @brief Get field s8_array from test_types message + * + * @return int8_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s8_array(const mavlink_message_t* msg, int8_t *s8_array) +{ + return _MAV_RETURN_int8_t_array(msg, s8_array, 3, 98); +} + +/** + * @brief Get field s16_array from test_types message + * + * @return int16_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s16_array(const mavlink_message_t* msg, int16_t *s16_array) +{ + return _MAV_RETURN_int16_t_array(msg, s16_array, 3, 101); +} + +/** + * @brief Get field s32_array from test_types message + * + * @return int32_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s32_array(const mavlink_message_t* msg, int32_t *s32_array) +{ + return _MAV_RETURN_int32_t_array(msg, s32_array, 3, 107); +} + +/** + * @brief Get field s64_array from test_types message + * + * @return int64_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s64_array(const mavlink_message_t* msg, int64_t *s64_array) +{ + return _MAV_RETURN_int64_t_array(msg, s64_array, 3, 119); +} + +/** + * @brief Get field f_array from test_types message + * + * @return float_array + */ +static inline uint16_t mavlink_msg_test_types_get_f_array(const mavlink_message_t* msg, float *f_array) +{ + return _MAV_RETURN_float_array(msg, f_array, 3, 143); +} + +/** + * @brief Get field d_array from test_types message + * + * @return double_array + */ +static inline uint16_t mavlink_msg_test_types_get_d_array(const mavlink_message_t* msg, double *d_array) +{ + return _MAV_RETURN_double_array(msg, d_array, 3, 155); +} + +/** + * @brief Decode a test_types message into a struct + * + * @param msg The message to decode + * @param test_types C-struct to decode the message contents into + */ +static inline void mavlink_msg_test_types_decode(const mavlink_message_t* msg, mavlink_test_types_t* test_types) +{ +#if MAVLINK_NEED_BYTE_SWAP + test_types->c = mavlink_msg_test_types_get_c(msg); + mavlink_msg_test_types_get_s(msg, test_types->s); + test_types->u8 = mavlink_msg_test_types_get_u8(msg); + test_types->u16 = mavlink_msg_test_types_get_u16(msg); + test_types->u32 = mavlink_msg_test_types_get_u32(msg); + test_types->u64 = mavlink_msg_test_types_get_u64(msg); + test_types->s8 = mavlink_msg_test_types_get_s8(msg); + test_types->s16 = mavlink_msg_test_types_get_s16(msg); + test_types->s32 = mavlink_msg_test_types_get_s32(msg); + test_types->s64 = mavlink_msg_test_types_get_s64(msg); + test_types->f = mavlink_msg_test_types_get_f(msg); + test_types->d = mavlink_msg_test_types_get_d(msg); + mavlink_msg_test_types_get_u8_array(msg, test_types->u8_array); + mavlink_msg_test_types_get_u16_array(msg, test_types->u16_array); + mavlink_msg_test_types_get_u32_array(msg, test_types->u32_array); + mavlink_msg_test_types_get_u64_array(msg, test_types->u64_array); + mavlink_msg_test_types_get_s8_array(msg, test_types->s8_array); + mavlink_msg_test_types_get_s16_array(msg, test_types->s16_array); + mavlink_msg_test_types_get_s32_array(msg, test_types->s32_array); + mavlink_msg_test_types_get_s64_array(msg, test_types->s64_array); + mavlink_msg_test_types_get_f_array(msg, test_types->f_array); + mavlink_msg_test_types_get_d_array(msg, test_types->d_array); +#else + memcpy(test_types, _MAV_PAYLOAD(msg), 179); +#endif +} diff --git a/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/test/test.h b/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/test/test.h new file mode 100644 index 0000000000..23ee65986d --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/test/test.h @@ -0,0 +1,53 @@ +/** @file + * @brief MAVLink comm protocol generated from test.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef TEST_H +#define TEST_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_TEST_TYPES, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_TEST + + + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 3 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 3 +#endif + +// ENUM DEFINITIONS + + + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_test_types.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // TEST_H diff --git a/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/test/testsuite.h b/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/test/testsuite.h new file mode 100644 index 0000000000..9b0fc041b5 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/include_v0.9/test/testsuite.h @@ -0,0 +1,120 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from test.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef TEST_TESTSUITE_H +#define TEST_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL + +static void mavlink_test_test(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + + mavlink_test_test(system_id, component_id, last_msg); +} +#endif + + + + +static void mavlink_test_test_types(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_test_types_t packet_in = { + 'A', + "BCDEFGHIJ", + 230, + 17859, + 963498192, + 93372036854776941ULL, + 211, + 18639, + 963498972, + 93372036854777886LL, + 304.0, + 438.0, + { 228, 229, 230 }, + { 20147, 20148, 20149 }, + { 963500688, 963500689, 963500690 }, + { 93372036854780469, 93372036854780470, 93372036854780471 }, + { 171, 172, 173 }, + { 22487, 22488, 22489 }, + { 963503028, 963503029, 963503030 }, + { 93372036854783304, 93372036854783305, 93372036854783306 }, + { 1018.0, 1019.0, 1020.0 }, + { 1208.0, 1209.0, 1210.0 }, + }; + mavlink_test_types_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.c = packet_in.c; + packet1.u8 = packet_in.u8; + packet1.u16 = packet_in.u16; + packet1.u32 = packet_in.u32; + packet1.u64 = packet_in.u64; + packet1.s8 = packet_in.s8; + packet1.s16 = packet_in.s16; + packet1.s32 = packet_in.s32; + packet1.s64 = packet_in.s64; + packet1.f = packet_in.f; + packet1.d = packet_in.d; + + mav_array_memcpy(packet1.s, packet_in.s, sizeof(char)*10); + mav_array_memcpy(packet1.u8_array, packet_in.u8_array, sizeof(uint8_t)*3); + mav_array_memcpy(packet1.u16_array, packet_in.u16_array, sizeof(uint16_t)*3); + mav_array_memcpy(packet1.u32_array, packet_in.u32_array, sizeof(uint32_t)*3); + mav_array_memcpy(packet1.u64_array, packet_in.u64_array, sizeof(uint64_t)*3); + mav_array_memcpy(packet1.s8_array, packet_in.s8_array, sizeof(int8_t)*3); + mav_array_memcpy(packet1.s16_array, packet_in.s16_array, sizeof(int16_t)*3); + mav_array_memcpy(packet1.s32_array, packet_in.s32_array, sizeof(int32_t)*3); + mav_array_memcpy(packet1.s64_array, packet_in.s64_array, sizeof(int64_t)*3); + mav_array_memcpy(packet1.f_array, packet_in.f_array, sizeof(float)*3); + mav_array_memcpy(packet1.d_array, packet_in.d_array, sizeof(double)*3); + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_test_types_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_test_types_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_test_types_pack(system_id, component_id, &msg , packet1.c , packet1.s , packet1.u8 , packet1.u16 , packet1.u32 , packet1.u64 , packet1.s8 , packet1.s16 , packet1.s32 , packet1.s64 , packet1.f , packet1.d , packet1.u8_array , packet1.u16_array , packet1.u32_array , packet1.u64_array , packet1.s8_array , packet1.s16_array , packet1.s32_array , packet1.s64_array , packet1.f_array , packet1.d_array ); + mavlink_msg_test_types_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_test_types_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.c , packet1.s , packet1.u8 , packet1.u16 , packet1.u32 , packet1.u64 , packet1.s8 , packet1.s16 , packet1.s32 , packet1.s64 , packet1.f , packet1.d , packet1.u8_array , packet1.u16_array , packet1.u32_array , packet1.u64_array , packet1.s8_array , packet1.s16_array , packet1.s32_array , packet1.s64_array , packet1.f_array , packet1.d_array ); + mavlink_msg_test_types_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; i>8) ^ (tmp<<8) ^ (tmp <<3) ^ (tmp>>4); +} + +/** + * @brief Initiliaze the buffer for the X.25 CRC + * + * @param crcAccum the 16 bit X.25 CRC + */ +static inline void crc_init(uint16_t* crcAccum) +{ + *crcAccum = X25_INIT_CRC; +} + + +/** + * @brief Calculates the X.25 checksum on a byte buffer + * + * @param pBuffer buffer containing the byte array to hash + * @param length length of the byte array + * @return the checksum over the buffer bytes + **/ +static inline uint16_t crc_calculate(const uint8_t* pBuffer, uint16_t length) +{ + uint16_t crcTmp; + crc_init(&crcTmp); + while (length--) { + crc_accumulate(*pBuffer++, &crcTmp); + } + return crcTmp; +} + +/** + * @brief Accumulate the X.25 CRC by adding an array of bytes + * + * The checksum function adds the hash of one char at a time to the + * 16 bit checksum (uint16_t). + * + * @param data new bytes to hash + * @param crcAccum the already accumulated checksum + **/ +static inline void crc_accumulate_buffer(uint16_t *crcAccum, const char *pBuffer, uint8_t length) +{ + const uint8_t *p = (const uint8_t *)pBuffer; + while (length--) { + crc_accumulate(*p++, crcAccum); + } +} + + + + +#endif /* _CHECKSUM_H_ */ + +#ifdef __cplusplus +} +#endif diff --git a/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/mavlink_helpers.h b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/mavlink_helpers.h new file mode 100644 index 0000000000..39d6930e5b --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/mavlink_helpers.h @@ -0,0 +1,507 @@ +#ifndef _MAVLINK_HELPERS_H_ +#define _MAVLINK_HELPERS_H_ + +#include "string.h" +#include "checksum.h" +#include "mavlink_types.h" + +#ifndef MAVLINK_HELPER +#define MAVLINK_HELPER +#endif + +/* + internal function to give access to the channel status for each channel + */ +MAVLINK_HELPER mavlink_status_t* mavlink_get_channel_status(uint8_t chan) +{ + static mavlink_status_t m_mavlink_status[MAVLINK_COMM_NUM_BUFFERS]; + return &m_mavlink_status[chan]; +} + +/* + internal function to give access to the channel buffer for each channel + */ +MAVLINK_HELPER mavlink_message_t* mavlink_get_channel_buffer(uint8_t chan) +{ + +#if MAVLINK_EXTERNAL_RX_BUFFER + // No m_mavlink_message array defined in function, + // has to be defined externally +#ifndef m_mavlink_message +#error ERROR: IF #define MAVLINK_EXTERNAL_RX_BUFFER IS SET, THE BUFFER HAS TO BE ALLOCATED OUTSIDE OF THIS FUNCTION (mavlink_message_t m_mavlink_buffer[MAVLINK_COMM_NUM_BUFFERS];) +#endif +#else + static mavlink_message_t m_mavlink_buffer[MAVLINK_COMM_NUM_BUFFERS]; +#endif + return &m_mavlink_buffer[chan]; +} + +/** + * @brief Finalize a MAVLink message with channel assignment + * + * This function calculates the checksum and sets length and aircraft id correctly. + * It assumes that the message id and the payload are already correctly set. This function + * can also be used if the message header has already been written before (as in mavlink_msg_xxx_pack + * instead of mavlink_msg_xxx_pack_headerless), it just introduces little extra overhead. + * + * @param msg Message to finalize + * @param system_id Id of the sending (this) system, 1-127 + * @param length Message length + */ +#if MAVLINK_CRC_EXTRA +MAVLINK_HELPER uint16_t mavlink_finalize_message_chan(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t chan, uint8_t length, uint8_t crc_extra) +#else +MAVLINK_HELPER uint16_t mavlink_finalize_message_chan(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t chan, uint8_t length) +#endif +{ + // This code part is the same for all messages; + uint16_t checksum; + msg->magic = MAVLINK_STX; + msg->len = length; + msg->sysid = system_id; + msg->compid = component_id; + // One sequence number per component + msg->seq = mavlink_get_channel_status(chan)->current_tx_seq; + mavlink_get_channel_status(chan)->current_tx_seq = mavlink_get_channel_status(chan)->current_tx_seq+1; + checksum = crc_calculate((uint8_t*)&msg->len, length + MAVLINK_CORE_HEADER_LEN); +#if MAVLINK_CRC_EXTRA + crc_accumulate(crc_extra, &checksum); +#endif + mavlink_ck_a(msg) = (uint8_t)(checksum & 0xFF); + mavlink_ck_b(msg) = (uint8_t)(checksum >> 8); + + return length + MAVLINK_NUM_NON_PAYLOAD_BYTES; +} + + +/** + * @brief Finalize a MAVLink message with MAVLINK_COMM_0 as default channel + */ +#if MAVLINK_CRC_EXTRA +MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t length, uint8_t crc_extra) +{ + return mavlink_finalize_message_chan(msg, system_id, component_id, MAVLINK_COMM_0, length, crc_extra); +} +#else +MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t length) +{ + return mavlink_finalize_message_chan(msg, system_id, component_id, MAVLINK_COMM_0, length); +} +#endif + +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS +MAVLINK_HELPER void _mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len); + +/** + * @brief Finalize a MAVLink message with channel assignment and send + */ +#if MAVLINK_CRC_EXTRA +MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet, + uint8_t length, uint8_t crc_extra) +#else +MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet, uint8_t length) +#endif +{ + uint16_t checksum; + uint8_t buf[MAVLINK_NUM_HEADER_BYTES]; + uint8_t ck[2]; + mavlink_status_t *status = mavlink_get_channel_status(chan); + buf[0] = MAVLINK_STX; + buf[1] = length; + buf[2] = status->current_tx_seq; + buf[3] = mavlink_system.sysid; + buf[4] = mavlink_system.compid; + buf[5] = msgid; + status->current_tx_seq++; + checksum = crc_calculate((uint8_t*)&buf[1], MAVLINK_CORE_HEADER_LEN); + crc_accumulate_buffer(&checksum, packet, length); +#if MAVLINK_CRC_EXTRA + crc_accumulate(crc_extra, &checksum); +#endif + ck[0] = (uint8_t)(checksum & 0xFF); + ck[1] = (uint8_t)(checksum >> 8); + + MAVLINK_START_UART_SEND(chan, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)length); + _mavlink_send_uart(chan, (const char *)buf, MAVLINK_NUM_HEADER_BYTES); + _mavlink_send_uart(chan, packet, length); + _mavlink_send_uart(chan, (const char *)ck, 2); + MAVLINK_END_UART_SEND(chan, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)length); +} +#endif // MAVLINK_USE_CONVENIENCE_FUNCTIONS + +/** + * @brief Pack a message to send it over a serial byte stream + */ +MAVLINK_HELPER uint16_t mavlink_msg_to_send_buffer(uint8_t *buffer, const mavlink_message_t *msg) +{ + memcpy(buffer, (const uint8_t *)&msg->magic, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)msg->len); + return MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)msg->len; +} + +union __mavlink_bitfield { + uint8_t uint8; + int8_t int8; + uint16_t uint16; + int16_t int16; + uint32_t uint32; + int32_t int32; +}; + + +MAVLINK_HELPER void mavlink_start_checksum(mavlink_message_t* msg) +{ + crc_init(&msg->checksum); +} + +MAVLINK_HELPER void mavlink_update_checksum(mavlink_message_t* msg, uint8_t c) +{ + crc_accumulate(c, &msg->checksum); +} + +/** + * This is a convenience function which handles the complete MAVLink parsing. + * the function will parse one byte at a time and return the complete packet once + * it could be successfully decoded. Checksum and other failures will be silently + * ignored. + * + * @param chan ID of the current channel. This allows to parse different channels with this function. + * a channel is not a physical message channel like a serial port, but a logic partition of + * the communication streams in this case. COMM_NB is the limit for the number of channels + * on MCU (e.g. ARM7), while COMM_NB_HIGH is the limit for the number of channels in Linux/Windows + * @param c The char to barse + * + * @param returnMsg NULL if no message could be decoded, the message data else + * @return 0 if no message could be decoded, 1 else + * + * A typical use scenario of this function call is: + * + * @code + * #include // For fixed-width uint8_t type + * + * mavlink_message_t msg; + * int chan = 0; + * + * + * while(serial.bytesAvailable > 0) + * { + * uint8_t byte = serial.getNextByte(); + * if (mavlink_parse_char(chan, byte, &msg)) + * { + * printf("Received message with ID %d, sequence: %d from component %d of system %d", msg.msgid, msg.seq, msg.compid, msg.sysid); + * } + * } + * + * + * @endcode + */ +MAVLINK_HELPER uint8_t mavlink_parse_char(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status) +{ + /* + default message crc function. You can override this per-system to + put this data in a different memory segment + */ +#if MAVLINK_CRC_EXTRA +#ifndef MAVLINK_MESSAGE_CRC + static const uint8_t mavlink_message_crcs[256] = MAVLINK_MESSAGE_CRCS; +#define MAVLINK_MESSAGE_CRC(msgid) mavlink_message_crcs[msgid] +#endif +#endif + + mavlink_message_t* rxmsg = mavlink_get_channel_buffer(chan); ///< The currently decoded message + mavlink_status_t* status = mavlink_get_channel_status(chan); ///< The current decode status + int bufferIndex = 0; + + status->msg_received = 0; + + switch (status->parse_state) + { + case MAVLINK_PARSE_STATE_UNINIT: + case MAVLINK_PARSE_STATE_IDLE: + if (c == MAVLINK_STX) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; + rxmsg->len = 0; + rxmsg->magic = c; + mavlink_start_checksum(rxmsg); + } + break; + + case MAVLINK_PARSE_STATE_GOT_STX: + if (status->msg_received +/* Support shorter buffers than the + default maximum packet size */ +#if (MAVLINK_MAX_PAYLOAD_LEN < 255) + || c > MAVLINK_MAX_PAYLOAD_LEN +#endif + ) + { + status->buffer_overrun++; + status->parse_error++; + status->msg_received = 0; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + } + else + { + // NOT counting STX, LENGTH, SEQ, SYSID, COMPID, MSGID, CRC1 and CRC2 + rxmsg->len = c; + status->packet_idx = 0; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_LENGTH; + } + break; + + case MAVLINK_PARSE_STATE_GOT_LENGTH: + rxmsg->seq = c; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_SEQ; + break; + + case MAVLINK_PARSE_STATE_GOT_SEQ: + rxmsg->sysid = c; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_SYSID; + break; + + case MAVLINK_PARSE_STATE_GOT_SYSID: + rxmsg->compid = c; + mavlink_update_checksum(rxmsg, c); + status->parse_state = MAVLINK_PARSE_STATE_GOT_COMPID; + break; + + case MAVLINK_PARSE_STATE_GOT_COMPID: + rxmsg->msgid = c; + mavlink_update_checksum(rxmsg, c); + if (rxmsg->len == 0) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD; + } + else + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_MSGID; + } + break; + + case MAVLINK_PARSE_STATE_GOT_MSGID: + _MAV_PAYLOAD_NON_CONST(rxmsg)[status->packet_idx++] = (char)c; + mavlink_update_checksum(rxmsg, c); + if (status->packet_idx == rxmsg->len) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD; + } + break; + + case MAVLINK_PARSE_STATE_GOT_PAYLOAD: +#if MAVLINK_CRC_EXTRA + mavlink_update_checksum(rxmsg, MAVLINK_MESSAGE_CRC(rxmsg->msgid)); +#endif + if (c != (rxmsg->checksum & 0xFF)) { + // Check first checksum byte + status->parse_error++; + status->msg_received = 0; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + if (c == MAVLINK_STX) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; + rxmsg->len = 0; + mavlink_start_checksum(rxmsg); + } + } + else + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_CRC1; + _MAV_PAYLOAD_NON_CONST(rxmsg)[status->packet_idx] = (char)c; + } + break; + + case MAVLINK_PARSE_STATE_GOT_CRC1: + if (c != (rxmsg->checksum >> 8)) { + // Check second checksum byte + status->parse_error++; + status->msg_received = 0; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + if (c == MAVLINK_STX) + { + status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; + rxmsg->len = 0; + mavlink_start_checksum(rxmsg); + } + } + else + { + // Successfully got message + status->msg_received = 1; + status->parse_state = MAVLINK_PARSE_STATE_IDLE; + _MAV_PAYLOAD_NON_CONST(rxmsg)[status->packet_idx+1] = (char)c; + memcpy(r_message, rxmsg, sizeof(mavlink_message_t)); + } + break; + } + + bufferIndex++; + // If a message has been sucessfully decoded, check index + if (status->msg_received == 1) + { + //while(status->current_seq != rxmsg->seq) + //{ + // status->packet_rx_drop_count++; + // status->current_seq++; + //} + status->current_rx_seq = rxmsg->seq; + // Initial condition: If no packet has been received so far, drop count is undefined + if (status->packet_rx_success_count == 0) status->packet_rx_drop_count = 0; + // Count this packet as received + status->packet_rx_success_count++; + } + + r_mavlink_status->current_rx_seq = status->current_rx_seq+1; + r_mavlink_status->packet_rx_success_count = status->packet_rx_success_count; + r_mavlink_status->packet_rx_drop_count = status->parse_error; + status->parse_error = 0; + return status->msg_received; +} + +/** + * @brief Put a bitfield of length 1-32 bit into the buffer + * + * @param b the value to add, will be encoded in the bitfield + * @param bits number of bits to use to encode b, e.g. 1 for boolean, 2, 3, etc. + * @param packet_index the position in the packet (the index of the first byte to use) + * @param bit_index the position in the byte (the index of the first bit to use) + * @param buffer packet buffer to write into + * @return new position of the last used byte in the buffer + */ +MAVLINK_HELPER uint8_t put_bitfield_n_by_index(int32_t b, uint8_t bits, uint8_t packet_index, uint8_t bit_index, uint8_t* r_bit_index, uint8_t* buffer) +{ + uint16_t bits_remain = bits; + // Transform number into network order + int32_t v; + uint8_t i_bit_index, i_byte_index, curr_bits_n; +#if MAVLINK_NEED_BYTE_SWAP + union { + int32_t i; + uint8_t b[4]; + } bin, bout; + bin.i = b; + bout.b[0] = bin.b[3]; + bout.b[1] = bin.b[2]; + bout.b[2] = bin.b[1]; + bout.b[3] = bin.b[0]; + v = bout.i; +#else + v = b; +#endif + + // buffer in + // 01100000 01000000 00000000 11110001 + // buffer out + // 11110001 00000000 01000000 01100000 + + // Existing partly filled byte (four free slots) + // 0111xxxx + + // Mask n free bits + // 00001111 = 2^0 + 2^1 + 2^2 + 2^3 = 2^n - 1 + // = ((uint32_t)(1 << n)) - 1; // = 2^n - 1 + + // Shift n bits into the right position + // out = in >> n; + + // Mask and shift bytes + i_bit_index = bit_index; + i_byte_index = packet_index; + if (bit_index > 0) + { + // If bits were available at start, they were available + // in the byte before the current index + i_byte_index--; + } + + // While bits have not been packed yet + while (bits_remain > 0) + { + // Bits still have to be packed + // there can be more than 8 bits, so + // we might have to pack them into more than one byte + + // First pack everything we can into the current 'open' byte + //curr_bits_n = bits_remain << 3; // Equals bits_remain mod 8 + //FIXME + if (bits_remain <= (uint8_t)(8 - i_bit_index)) + { + // Enough space + curr_bits_n = (uint8_t)bits_remain; + } + else + { + curr_bits_n = (8 - i_bit_index); + } + + // Pack these n bits into the current byte + // Mask out whatever was at that position with ones (xxx11111) + buffer[i_byte_index] &= (0xFF >> (8 - curr_bits_n)); + // Put content to this position, by masking out the non-used part + buffer[i_byte_index] |= ((0x00 << curr_bits_n) & v); + + // Increment the bit index + i_bit_index += curr_bits_n; + + // Now proceed to the next byte, if necessary + bits_remain -= curr_bits_n; + if (bits_remain > 0) + { + // Offer another 8 bits / one byte + i_byte_index++; + i_bit_index = 0; + } + } + + *r_bit_index = i_bit_index; + // If a partly filled byte is present, mark this as consumed + if (i_bit_index != 7) i_byte_index++; + return i_byte_index - packet_index; +} + +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +// To make MAVLink work on your MCU, define comm_send_ch() if you wish +// to send 1 byte at a time, or MAVLINK_SEND_UART_BYTES() to send a +// whole packet at a time + +/* + +#include "mavlink_types.h" + +void comm_send_ch(mavlink_channel_t chan, uint8_t ch) +{ + if (chan == MAVLINK_COMM_0) + { + uart0_transmit(ch); + } + if (chan == MAVLINK_COMM_1) + { + uart1_transmit(ch); + } +} + */ + +MAVLINK_HELPER void _mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len) +{ +#ifdef MAVLINK_SEND_UART_BYTES + /* this is the more efficient approach, if the platform + defines it */ + MAVLINK_SEND_UART_BYTES(chan, (uint8_t *)buf, len); +#else + /* fallback to one byte at a time */ + uint16_t i; + for (i = 0; i < len; i++) { + comm_send_ch(chan, (uint8_t)buf[i]); + } +#endif +} +#endif // MAVLINK_USE_CONVENIENCE_FUNCTIONS + +#endif /* _MAVLINK_HELPERS_H_ */ diff --git a/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/mavlink_protobuf_manager.hpp b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/mavlink_protobuf_manager.hpp new file mode 100644 index 0000000000..fd3ddd026f --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/mavlink_protobuf_manager.hpp @@ -0,0 +1,377 @@ +#ifndef MAVLINKPROTOBUFMANAGER_HPP +#define MAVLINKPROTOBUFMANAGER_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace mavlink +{ + +class ProtobufManager +{ +public: + ProtobufManager() + : mRegisteredTypeCount(0) + , mStreamID(0) + , mVerbose(false) + , kExtendedHeaderSize(MAVLINK_EXTENDED_HEADER_LEN) + , kExtendedPayloadMaxSize(MAVLINK_MAX_EXTENDED_PAYLOAD_LEN) + { + // register GLOverlay + { + std::tr1::shared_ptr msg(new px::GLOverlay); + registerType(msg); + } + + // register ObstacleList + { + std::tr1::shared_ptr msg(new px::ObstacleList); + registerType(msg); + } + + // register ObstacleMap + { + std::tr1::shared_ptr msg(new px::ObstacleMap); + registerType(msg); + } + + // register Path + { + std::tr1::shared_ptr msg(new px::Path); + registerType(msg); + } + + // register PointCloudXYZI + { + std::tr1::shared_ptr msg(new px::PointCloudXYZI); + registerType(msg); + } + + // register PointCloudXYZRGB + { + std::tr1::shared_ptr msg(new px::PointCloudXYZRGB); + registerType(msg); + } + + // register RGBDImage + { + std::tr1::shared_ptr msg(new px::RGBDImage); + registerType(msg); + } + + srand(time(NULL)); + mStreamID = rand() + 1; + } + + bool fragmentMessage(uint8_t system_id, uint8_t component_id, + uint8_t target_system, uint8_t target_component, + const google::protobuf::Message& protobuf_msg, + std::vector& fragments) const + { + TypeMap::const_iterator it = mTypeMap.find(protobuf_msg.GetTypeName()); + if (it == mTypeMap.end()) + { + std::cout << "# WARNING: Protobuf message with type " + << protobuf_msg.GetTypeName() << " is not registered." + << std::endl; + return false; + } + + uint8_t typecode = it->second; + + std::string data = protobuf_msg.SerializeAsString(); + + int fragmentCount = (protobuf_msg.ByteSize() + kExtendedPayloadMaxSize - 1) / kExtendedPayloadMaxSize; + unsigned int offset = 0; + + for (int i = 0; i < fragmentCount; ++i) + { + mavlink_extended_message_t fragment; + + // write extended header data + uint8_t* payload = reinterpret_cast(fragment.base_msg.payload64); + unsigned int length = 0; + uint8_t flags = 0; + + if (i < fragmentCount - 1) + { + length = kExtendedPayloadMaxSize; + flags |= 0x1; + } + else + { + length = protobuf_msg.ByteSize() - kExtendedPayloadMaxSize * (fragmentCount - 1); + } + + memcpy(payload, &target_system, 1); + memcpy(payload + 1, &target_component, 1); + memcpy(payload + 2, &typecode, 1); + memcpy(payload + 3, &length, 4); + memcpy(payload + 7, &mStreamID, 2); + memcpy(payload + 9, &offset, 4); + memcpy(payload + 13, &flags, 1); + + fragment.base_msg.msgid = MAVLINK_MSG_ID_EXTENDED_MESSAGE; + mavlink_finalize_message(&fragment.base_msg, system_id, component_id, kExtendedHeaderSize, 0); + + // write extended payload data + fragment.extended_payload_len = length; + memcpy(fragment.extended_payload, &data[offset], length); + + fragments.push_back(fragment); + offset += length; + } + + if (mVerbose) + { + std::cerr << "# INFO: Split extended message with size " + << protobuf_msg.ByteSize() << " into " + << fragmentCount << " fragments." << std::endl; + } + + return true; + } + + bool cacheFragment(mavlink_extended_message_t& msg) + { + if (!validFragment(msg)) + { + if (mVerbose) + { + std::cerr << "# WARNING: Message is not a valid fragment. " + << "Dropping message..." << std::endl; + } + return false; + } + + // read extended header + uint8_t* payload = reinterpret_cast(msg.base_msg.payload64); + uint8_t typecode = 0; + unsigned int length = 0; + unsigned short streamID = 0; + unsigned int offset = 0; + uint8_t flags = 0; + + memcpy(&typecode, payload + 2, 1); + memcpy(&length, payload + 3, 4); + memcpy(&streamID, payload + 7, 2); + memcpy(&offset, payload + 9, 4); + memcpy(&flags, payload + 13, 1); + + if (typecode >= mTypeMap.size()) + { + std::cout << "# WARNING: Protobuf message with type code " + << static_cast(typecode) << " is not registered." << std::endl; + return false; + } + + bool reassemble = false; + + FragmentQueue::iterator it = mFragmentQueue.find(streamID); + if (it == mFragmentQueue.end()) + { + if (offset == 0) + { + mFragmentQueue[streamID].push_back(msg); + + if ((flags & 0x1) != 0x1) + { + reassemble = true; + } + + if (mVerbose) + { + std::cerr << "# INFO: Added fragment to new queue." + << std::endl; + } + } + else + { + if (mVerbose) + { + std::cerr << "# WARNING: Message is not a valid fragment. " + << "Dropping message..." << std::endl; + } + } + } + else + { + std::deque& queue = it->second; + + if (queue.empty()) + { + if (offset == 0) + { + queue.push_back(msg); + + if ((flags & 0x1) != 0x1) + { + reassemble = true; + } + } + else + { + if (mVerbose) + { + std::cerr << "# WARNING: Message is not a valid fragment. " + << "Dropping message..." << std::endl; + } + } + } + else + { + if (fragmentDataSize(queue.back()) + fragmentOffset(queue.back()) != offset) + { + if (mVerbose) + { + std::cerr << "# WARNING: Previous fragment(s) have been lost. " + << "Dropping message and clearing queue..." << std::endl; + } + queue.clear(); + } + else + { + queue.push_back(msg); + + if ((flags & 0x1) != 0x1) + { + reassemble = true; + } + } + } + } + + if (reassemble) + { + std::deque& queue = mFragmentQueue[streamID]; + + std::string data; + for (size_t i = 0; i < queue.size(); ++i) + { + mavlink_extended_message_t& mavlink_msg = queue.at(i); + + data.append(reinterpret_cast(&mavlink_msg.extended_payload[0]), + static_cast(mavlink_msg.extended_payload_len)); + } + + mMessages.at(typecode)->ParseFromString(data); + + mMessageAvailable.at(typecode) = true; + + queue.clear(); + + if (mVerbose) + { + std::cerr << "# INFO: Reassembled fragments for message with typename " + << mMessages.at(typecode)->GetTypeName() << " and size " + << mMessages.at(typecode)->ByteSize() + << "." << std::endl; + } + } + + return true; + } + + bool getMessage(std::tr1::shared_ptr& msg) + { + for (size_t i = 0; i < mMessageAvailable.size(); ++i) + { + if (mMessageAvailable.at(i)) + { + msg = mMessages.at(i); + mMessageAvailable.at(i) = false; + + return true; + } + } + + return false; + } + +private: + void registerType(const std::tr1::shared_ptr& msg) + { + mTypeMap[msg->GetTypeName()] = mRegisteredTypeCount; + ++mRegisteredTypeCount; + mMessages.push_back(msg); + mMessageAvailable.push_back(false); + } + + bool validFragment(const mavlink_extended_message_t& msg) const + { + if (msg.base_msg.magic != MAVLINK_STX || + msg.base_msg.len != kExtendedHeaderSize || + msg.base_msg.msgid != MAVLINK_MSG_ID_EXTENDED_MESSAGE) + { + return false; + } + + uint16_t checksum; + checksum = crc_calculate(reinterpret_cast(&msg.base_msg.len), MAVLINK_CORE_HEADER_LEN); + crc_accumulate_buffer(&checksum, reinterpret_cast(&msg.base_msg.payload64), kExtendedHeaderSize); +#if MAVLINK_CRC_EXTRA + static const uint8_t mavlink_message_crcs[256] = MAVLINK_MESSAGE_CRCS; + crc_accumulate(mavlink_message_crcs[msg.base_msg.msgid], &checksum); +#endif + + if (mavlink_ck_a(&(msg.base_msg)) != (uint8_t)(checksum & 0xFF) && + mavlink_ck_b(&(msg.base_msg)) != (uint8_t)(checksum >> 8)) + { + return false; + } + + return true; + } + + unsigned int fragmentDataSize(const mavlink_extended_message_t& msg) const + { + const uint8_t* payload = reinterpret_cast(msg.base_msg.payload64); + + return *(reinterpret_cast(payload + 3)); + } + + unsigned int fragmentOffset(const mavlink_extended_message_t& msg) const + { + const uint8_t* payload = reinterpret_cast(msg.base_msg.payload64); + + return *(reinterpret_cast(payload + 9)); + } + + int mRegisteredTypeCount; + unsigned short mStreamID; + bool mVerbose; + + typedef std::map TypeMap; + TypeMap mTypeMap; + std::vector< std::tr1::shared_ptr > mMessages; + std::vector mMessageAvailable; + + typedef std::map > FragmentQueue; + FragmentQueue mFragmentQueue; + + const int kExtendedHeaderSize; + /** + * Extended header structure + * ========================= + * byte 0 - target_system + * byte 1 - target_component + * byte 2 - extended message id (type code) + * bytes 3-6 - extended payload size in bytes + * byte 7-8 - stream ID + * byte 9-12 - fragment offset + * byte 13 - fragment flags (bit 0 - 1=more fragments, 0=last fragment) + */ + + const int kExtendedPayloadMaxSize; +}; + +} + +#endif diff --git a/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/mavlink_types.h b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/mavlink_types.h new file mode 100644 index 0000000000..5fbde97f73 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/mavlink_types.h @@ -0,0 +1,158 @@ +#ifndef MAVLINK_TYPES_H_ +#define MAVLINK_TYPES_H_ + +#include + +#ifndef MAVLINK_MAX_PAYLOAD_LEN +// it is possible to override this, but be careful! +#define MAVLINK_MAX_PAYLOAD_LEN 255 ///< Maximum payload length +#endif + +#define MAVLINK_CORE_HEADER_LEN 5 ///< Length of core header (of the comm. layer): message length (1 byte) + message sequence (1 byte) + message system id (1 byte) + message component id (1 byte) + message type id (1 byte) +#define MAVLINK_NUM_HEADER_BYTES (MAVLINK_CORE_HEADER_LEN + 1) ///< Length of all header bytes, including core and checksum +#define MAVLINK_NUM_CHECKSUM_BYTES 2 +#define MAVLINK_NUM_NON_PAYLOAD_BYTES (MAVLINK_NUM_HEADER_BYTES + MAVLINK_NUM_CHECKSUM_BYTES) + +#define MAVLINK_MAX_PACKET_LEN (MAVLINK_MAX_PAYLOAD_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES) ///< Maximum packet length + +#define MAVLINK_MSG_ID_EXTENDED_MESSAGE 255 +#define MAVLINK_EXTENDED_HEADER_LEN 14 + +#if (defined _MSC_VER) | ((defined __APPLE__) & (defined __MACH__)) | (defined __linux__) + /* full fledged 32bit++ OS */ + #define MAVLINK_MAX_EXTENDED_PACKET_LEN 65507 +#else + /* small microcontrollers */ + #define MAVLINK_MAX_EXTENDED_PACKET_LEN 2048 +#endif + +#define MAVLINK_MAX_EXTENDED_PAYLOAD_LEN (MAVLINK_MAX_EXTENDED_PACKET_LEN - MAVLINK_EXTENDED_HEADER_LEN - MAVLINK_NUM_NON_PAYLOAD_BYTES) + +typedef struct param_union { + union { + float param_float; + int32_t param_int32; + uint32_t param_uint32; + uint8_t param_uint8; + uint8_t bytes[4]; + }; + uint8_t type; +} mavlink_param_union_t; + +typedef struct __mavlink_system { + uint8_t sysid; ///< Used by the MAVLink message_xx_send() convenience function + uint8_t compid; ///< Used by the MAVLink message_xx_send() convenience function + uint8_t type; ///< Unused, can be used by user to store the system's type + uint8_t state; ///< Unused, can be used by user to store the system's state + uint8_t mode; ///< Unused, can be used by user to store the system's mode + uint8_t nav_mode; ///< Unused, can be used by user to store the system's navigation mode +} mavlink_system_t; + +typedef struct __mavlink_message { + uint16_t checksum; /// sent at end of packet + uint8_t magic; ///< protocol magic marker + uint8_t len; ///< Length of payload + uint8_t seq; ///< Sequence of packet + uint8_t sysid; ///< ID of message sender system/aircraft + uint8_t compid; ///< ID of the message sender component + uint8_t msgid; ///< ID of message in payload + uint64_t payload64[(MAVLINK_MAX_PAYLOAD_LEN+MAVLINK_NUM_CHECKSUM_BYTES+7)/8]; +} mavlink_message_t; + + +typedef struct __mavlink_extended_message { + mavlink_message_t base_msg; + int32_t extended_payload_len; ///< Length of extended payload if any + uint8_t extended_payload[MAVLINK_MAX_EXTENDED_PAYLOAD_LEN]; +} mavlink_extended_message_t; + + +typedef enum { + MAVLINK_TYPE_CHAR = 0, + MAVLINK_TYPE_UINT8_T = 1, + MAVLINK_TYPE_INT8_T = 2, + MAVLINK_TYPE_UINT16_T = 3, + MAVLINK_TYPE_INT16_T = 4, + MAVLINK_TYPE_UINT32_T = 5, + MAVLINK_TYPE_INT32_T = 6, + MAVLINK_TYPE_UINT64_T = 7, + MAVLINK_TYPE_INT64_T = 8, + MAVLINK_TYPE_FLOAT = 9, + MAVLINK_TYPE_DOUBLE = 10 +} mavlink_message_type_t; + +#define MAVLINK_MAX_FIELDS 64 + +typedef struct __mavlink_field_info { + const char *name; // name of this field + const char *print_format; // printing format hint, or NULL + mavlink_message_type_t type; // type of this field + unsigned int array_length; // if non-zero, field is an array + unsigned int wire_offset; // offset of each field in the payload + unsigned int structure_offset; // offset in a C structure +} mavlink_field_info_t; + +// note that in this structure the order of fields is the order +// in the XML file, not necessary the wire order +typedef struct __mavlink_message_info { + const char *name; // name of the message + unsigned num_fields; // how many fields in this message + mavlink_field_info_t fields[MAVLINK_MAX_FIELDS]; // field information +} mavlink_message_info_t; + +#define _MAV_PAYLOAD(msg) ((const char *)(&((msg)->payload64[0]))) +#define _MAV_PAYLOAD_NON_CONST(msg) ((char *)(&((msg)->payload64[0]))) + +// checksum is immediately after the payload bytes +#define mavlink_ck_a(msg) *((msg)->len + (uint8_t *)_MAV_PAYLOAD_NON_CONST(msg)) +#define mavlink_ck_b(msg) *(((msg)->len+(uint16_t)1) + (uint8_t *)_MAV_PAYLOAD_NON_CONST(msg)) + +typedef enum { + MAVLINK_COMM_0, + MAVLINK_COMM_1, + MAVLINK_COMM_2, + MAVLINK_COMM_3 +} mavlink_channel_t; + +/* + * applications can set MAVLINK_COMM_NUM_BUFFERS to the maximum number + * of buffers they will use. If more are used, then the result will be + * a stack overrun + */ +#ifndef MAVLINK_COMM_NUM_BUFFERS +#if (defined linux) | (defined __linux) | (defined __MACH__) | (defined _WIN32) +# define MAVLINK_COMM_NUM_BUFFERS 16 +#else +# define MAVLINK_COMM_NUM_BUFFERS 4 +#endif +#endif + +typedef enum { + MAVLINK_PARSE_STATE_UNINIT=0, + MAVLINK_PARSE_STATE_IDLE, + MAVLINK_PARSE_STATE_GOT_STX, + MAVLINK_PARSE_STATE_GOT_SEQ, + MAVLINK_PARSE_STATE_GOT_LENGTH, + MAVLINK_PARSE_STATE_GOT_SYSID, + MAVLINK_PARSE_STATE_GOT_COMPID, + MAVLINK_PARSE_STATE_GOT_MSGID, + MAVLINK_PARSE_STATE_GOT_PAYLOAD, + MAVLINK_PARSE_STATE_GOT_CRC1 +} mavlink_parse_state_t; ///< The state machine for the comm parser + +typedef struct __mavlink_status { + uint8_t msg_received; ///< Number of received messages + uint8_t buffer_overrun; ///< Number of buffer overruns + uint8_t parse_error; ///< Number of parse errors + mavlink_parse_state_t parse_state; ///< Parsing state machine + uint8_t packet_idx; ///< Index in current packet + uint8_t current_rx_seq; ///< Sequence number of last packet received + uint8_t current_tx_seq; ///< Sequence number of last packet sent + uint16_t packet_rx_success_count; ///< Received packets + uint16_t packet_rx_drop_count; ///< Number of packet drops +} mavlink_status_t; + +#define MAVLINK_BIG_ENDIAN 0 +#define MAVLINK_LITTLE_ENDIAN 1 + +#endif /* MAVLINK_TYPES_H_ */ diff --git a/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/pixhawk/pixhawk.pb.h b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/pixhawk/pixhawk.pb.h new file mode 100644 index 0000000000..7556606e98 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/pixhawk/pixhawk.pb.h @@ -0,0 +1,3663 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: pixhawk.proto + +#ifndef PROTOBUF_pixhawk_2eproto__INCLUDED +#define PROTOBUF_pixhawk_2eproto__INCLUDED + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 2004000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 2004001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace px { + +// Internal implementation detail -- do not call these. +void protobuf_AddDesc_pixhawk_2eproto(); +void protobuf_AssignDesc_pixhawk_2eproto(); +void protobuf_ShutdownFile_pixhawk_2eproto(); + +class HeaderInfo; +class GLOverlay; +class Obstacle; +class ObstacleList; +class ObstacleMap; +class Path; +class PointCloudXYZI; +class PointCloudXYZI_PointXYZI; +class PointCloudXYZRGB; +class PointCloudXYZRGB_PointXYZRGB; +class RGBDImage; +class Waypoint; + +enum GLOverlay_CoordinateFrameType { + GLOverlay_CoordinateFrameType_GLOBAL = 0, + GLOverlay_CoordinateFrameType_LOCAL = 1 +}; +bool GLOverlay_CoordinateFrameType_IsValid(int value); +const GLOverlay_CoordinateFrameType GLOverlay_CoordinateFrameType_CoordinateFrameType_MIN = GLOverlay_CoordinateFrameType_GLOBAL; +const GLOverlay_CoordinateFrameType GLOverlay_CoordinateFrameType_CoordinateFrameType_MAX = GLOverlay_CoordinateFrameType_LOCAL; +const int GLOverlay_CoordinateFrameType_CoordinateFrameType_ARRAYSIZE = GLOverlay_CoordinateFrameType_CoordinateFrameType_MAX + 1; + +const ::google::protobuf::EnumDescriptor* GLOverlay_CoordinateFrameType_descriptor(); +inline const ::std::string& GLOverlay_CoordinateFrameType_Name(GLOverlay_CoordinateFrameType value) { + return ::google::protobuf::internal::NameOfEnum( + GLOverlay_CoordinateFrameType_descriptor(), value); +} +inline bool GLOverlay_CoordinateFrameType_Parse( + const ::std::string& name, GLOverlay_CoordinateFrameType* value) { + return ::google::protobuf::internal::ParseNamedEnum( + GLOverlay_CoordinateFrameType_descriptor(), name, value); +} +enum GLOverlay_Mode { + GLOverlay_Mode_POINTS = 0, + GLOverlay_Mode_LINES = 1, + GLOverlay_Mode_LINE_STRIP = 2, + GLOverlay_Mode_LINE_LOOP = 3, + GLOverlay_Mode_TRIANGLES = 4, + GLOverlay_Mode_TRIANGLE_STRIP = 5, + GLOverlay_Mode_TRIANGLE_FAN = 6, + GLOverlay_Mode_QUADS = 7, + GLOverlay_Mode_QUAD_STRIP = 8, + GLOverlay_Mode_POLYGON = 9, + GLOverlay_Mode_SOLID_CIRCLE = 10, + GLOverlay_Mode_WIRE_CIRCLE = 11, + GLOverlay_Mode_SOLID_CUBE = 12, + GLOverlay_Mode_WIRE_CUBE = 13 +}; +bool GLOverlay_Mode_IsValid(int value); +const GLOverlay_Mode GLOverlay_Mode_Mode_MIN = GLOverlay_Mode_POINTS; +const GLOverlay_Mode GLOverlay_Mode_Mode_MAX = GLOverlay_Mode_WIRE_CUBE; +const int GLOverlay_Mode_Mode_ARRAYSIZE = GLOverlay_Mode_Mode_MAX + 1; + +const ::google::protobuf::EnumDescriptor* GLOverlay_Mode_descriptor(); +inline const ::std::string& GLOverlay_Mode_Name(GLOverlay_Mode value) { + return ::google::protobuf::internal::NameOfEnum( + GLOverlay_Mode_descriptor(), value); +} +inline bool GLOverlay_Mode_Parse( + const ::std::string& name, GLOverlay_Mode* value) { + return ::google::protobuf::internal::ParseNamedEnum( + GLOverlay_Mode_descriptor(), name, value); +} +enum GLOverlay_Identifier { + GLOverlay_Identifier_END = 14, + GLOverlay_Identifier_VERTEX2F = 15, + GLOverlay_Identifier_VERTEX3F = 16, + GLOverlay_Identifier_ROTATEF = 17, + GLOverlay_Identifier_TRANSLATEF = 18, + GLOverlay_Identifier_SCALEF = 19, + GLOverlay_Identifier_PUSH_MATRIX = 20, + GLOverlay_Identifier_POP_MATRIX = 21, + GLOverlay_Identifier_COLOR3F = 22, + GLOverlay_Identifier_COLOR4F = 23, + GLOverlay_Identifier_POINTSIZE = 24, + GLOverlay_Identifier_LINEWIDTH = 25 +}; +bool GLOverlay_Identifier_IsValid(int value); +const GLOverlay_Identifier GLOverlay_Identifier_Identifier_MIN = GLOverlay_Identifier_END; +const GLOverlay_Identifier GLOverlay_Identifier_Identifier_MAX = GLOverlay_Identifier_LINEWIDTH; +const int GLOverlay_Identifier_Identifier_ARRAYSIZE = GLOverlay_Identifier_Identifier_MAX + 1; + +const ::google::protobuf::EnumDescriptor* GLOverlay_Identifier_descriptor(); +inline const ::std::string& GLOverlay_Identifier_Name(GLOverlay_Identifier value) { + return ::google::protobuf::internal::NameOfEnum( + GLOverlay_Identifier_descriptor(), value); +} +inline bool GLOverlay_Identifier_Parse( + const ::std::string& name, GLOverlay_Identifier* value) { + return ::google::protobuf::internal::ParseNamedEnum( + GLOverlay_Identifier_descriptor(), name, value); +} +// =================================================================== + +class HeaderInfo : public ::google::protobuf::Message { + public: + HeaderInfo(); + virtual ~HeaderInfo(); + + HeaderInfo(const HeaderInfo& from); + + inline HeaderInfo& operator=(const HeaderInfo& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const HeaderInfo& default_instance(); + + void Swap(HeaderInfo* other); + + // implements Message ---------------------------------------------- + + HeaderInfo* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const HeaderInfo& from); + void MergeFrom(const HeaderInfo& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required int32 source_sysid = 1; + inline bool has_source_sysid() const; + inline void clear_source_sysid(); + static const int kSourceSysidFieldNumber = 1; + inline ::google::protobuf::int32 source_sysid() const; + inline void set_source_sysid(::google::protobuf::int32 value); + + // required int32 source_compid = 2; + inline bool has_source_compid() const; + inline void clear_source_compid(); + static const int kSourceCompidFieldNumber = 2; + inline ::google::protobuf::int32 source_compid() const; + inline void set_source_compid(::google::protobuf::int32 value); + + // required double timestamp = 3; + inline bool has_timestamp() const; + inline void clear_timestamp(); + static const int kTimestampFieldNumber = 3; + inline double timestamp() const; + inline void set_timestamp(double value); + + // @@protoc_insertion_point(class_scope:px.HeaderInfo) + private: + inline void set_has_source_sysid(); + inline void clear_has_source_sysid(); + inline void set_has_source_compid(); + inline void clear_has_source_compid(); + inline void set_has_timestamp(); + inline void clear_has_timestamp(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::int32 source_sysid_; + ::google::protobuf::int32 source_compid_; + double timestamp_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static HeaderInfo* default_instance_; +}; +// ------------------------------------------------------------------- + +class GLOverlay : public ::google::protobuf::Message { + public: + GLOverlay(); + virtual ~GLOverlay(); + + GLOverlay(const GLOverlay& from); + + inline GLOverlay& operator=(const GLOverlay& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const GLOverlay& default_instance(); + + void Swap(GLOverlay* other); + + // implements Message ---------------------------------------------- + + GLOverlay* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const GLOverlay& from); + void MergeFrom(const GLOverlay& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef GLOverlay_CoordinateFrameType CoordinateFrameType; + static const CoordinateFrameType GLOBAL = GLOverlay_CoordinateFrameType_GLOBAL; + static const CoordinateFrameType LOCAL = GLOverlay_CoordinateFrameType_LOCAL; + static inline bool CoordinateFrameType_IsValid(int value) { + return GLOverlay_CoordinateFrameType_IsValid(value); + } + static const CoordinateFrameType CoordinateFrameType_MIN = + GLOverlay_CoordinateFrameType_CoordinateFrameType_MIN; + static const CoordinateFrameType CoordinateFrameType_MAX = + GLOverlay_CoordinateFrameType_CoordinateFrameType_MAX; + static const int CoordinateFrameType_ARRAYSIZE = + GLOverlay_CoordinateFrameType_CoordinateFrameType_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + CoordinateFrameType_descriptor() { + return GLOverlay_CoordinateFrameType_descriptor(); + } + static inline const ::std::string& CoordinateFrameType_Name(CoordinateFrameType value) { + return GLOverlay_CoordinateFrameType_Name(value); + } + static inline bool CoordinateFrameType_Parse(const ::std::string& name, + CoordinateFrameType* value) { + return GLOverlay_CoordinateFrameType_Parse(name, value); + } + + typedef GLOverlay_Mode Mode; + static const Mode POINTS = GLOverlay_Mode_POINTS; + static const Mode LINES = GLOverlay_Mode_LINES; + static const Mode LINE_STRIP = GLOverlay_Mode_LINE_STRIP; + static const Mode LINE_LOOP = GLOverlay_Mode_LINE_LOOP; + static const Mode TRIANGLES = GLOverlay_Mode_TRIANGLES; + static const Mode TRIANGLE_STRIP = GLOverlay_Mode_TRIANGLE_STRIP; + static const Mode TRIANGLE_FAN = GLOverlay_Mode_TRIANGLE_FAN; + static const Mode QUADS = GLOverlay_Mode_QUADS; + static const Mode QUAD_STRIP = GLOverlay_Mode_QUAD_STRIP; + static const Mode POLYGON = GLOverlay_Mode_POLYGON; + static const Mode SOLID_CIRCLE = GLOverlay_Mode_SOLID_CIRCLE; + static const Mode WIRE_CIRCLE = GLOverlay_Mode_WIRE_CIRCLE; + static const Mode SOLID_CUBE = GLOverlay_Mode_SOLID_CUBE; + static const Mode WIRE_CUBE = GLOverlay_Mode_WIRE_CUBE; + static inline bool Mode_IsValid(int value) { + return GLOverlay_Mode_IsValid(value); + } + static const Mode Mode_MIN = + GLOverlay_Mode_Mode_MIN; + static const Mode Mode_MAX = + GLOverlay_Mode_Mode_MAX; + static const int Mode_ARRAYSIZE = + GLOverlay_Mode_Mode_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + Mode_descriptor() { + return GLOverlay_Mode_descriptor(); + } + static inline const ::std::string& Mode_Name(Mode value) { + return GLOverlay_Mode_Name(value); + } + static inline bool Mode_Parse(const ::std::string& name, + Mode* value) { + return GLOverlay_Mode_Parse(name, value); + } + + typedef GLOverlay_Identifier Identifier; + static const Identifier END = GLOverlay_Identifier_END; + static const Identifier VERTEX2F = GLOverlay_Identifier_VERTEX2F; + static const Identifier VERTEX3F = GLOverlay_Identifier_VERTEX3F; + static const Identifier ROTATEF = GLOverlay_Identifier_ROTATEF; + static const Identifier TRANSLATEF = GLOverlay_Identifier_TRANSLATEF; + static const Identifier SCALEF = GLOverlay_Identifier_SCALEF; + static const Identifier PUSH_MATRIX = GLOverlay_Identifier_PUSH_MATRIX; + static const Identifier POP_MATRIX = GLOverlay_Identifier_POP_MATRIX; + static const Identifier COLOR3F = GLOverlay_Identifier_COLOR3F; + static const Identifier COLOR4F = GLOverlay_Identifier_COLOR4F; + static const Identifier POINTSIZE = GLOverlay_Identifier_POINTSIZE; + static const Identifier LINEWIDTH = GLOverlay_Identifier_LINEWIDTH; + static inline bool Identifier_IsValid(int value) { + return GLOverlay_Identifier_IsValid(value); + } + static const Identifier Identifier_MIN = + GLOverlay_Identifier_Identifier_MIN; + static const Identifier Identifier_MAX = + GLOverlay_Identifier_Identifier_MAX; + static const int Identifier_ARRAYSIZE = + GLOverlay_Identifier_Identifier_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + Identifier_descriptor() { + return GLOverlay_Identifier_descriptor(); + } + static inline const ::std::string& Identifier_Name(Identifier value) { + return GLOverlay_Identifier_Name(value); + } + static inline bool Identifier_Parse(const ::std::string& name, + Identifier* value) { + return GLOverlay_Identifier_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // optional string name = 2; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 2; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + + // optional .px.GLOverlay.CoordinateFrameType coordinateFrameType = 3; + inline bool has_coordinateframetype() const; + inline void clear_coordinateframetype(); + static const int kCoordinateFrameTypeFieldNumber = 3; + inline ::px::GLOverlay_CoordinateFrameType coordinateframetype() const; + inline void set_coordinateframetype(::px::GLOverlay_CoordinateFrameType value); + + // optional double origin_x = 4; + inline bool has_origin_x() const; + inline void clear_origin_x(); + static const int kOriginXFieldNumber = 4; + inline double origin_x() const; + inline void set_origin_x(double value); + + // optional double origin_y = 5; + inline bool has_origin_y() const; + inline void clear_origin_y(); + static const int kOriginYFieldNumber = 5; + inline double origin_y() const; + inline void set_origin_y(double value); + + // optional double origin_z = 6; + inline bool has_origin_z() const; + inline void clear_origin_z(); + static const int kOriginZFieldNumber = 6; + inline double origin_z() const; + inline void set_origin_z(double value); + + // optional bytes data = 7; + inline bool has_data() const; + inline void clear_data(); + static const int kDataFieldNumber = 7; + inline const ::std::string& data() const; + inline void set_data(const ::std::string& value); + inline void set_data(const char* value); + inline void set_data(const void* value, size_t size); + inline ::std::string* mutable_data(); + inline ::std::string* release_data(); + + // @@protoc_insertion_point(class_scope:px.GLOverlay) + private: + inline void set_has_header(); + inline void clear_has_header(); + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_coordinateframetype(); + inline void clear_has_coordinateframetype(); + inline void set_has_origin_x(); + inline void clear_has_origin_x(); + inline void set_has_origin_y(); + inline void clear_has_origin_y(); + inline void set_has_origin_z(); + inline void clear_has_origin_z(); + inline void set_has_data(); + inline void clear_has_data(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::std::string* name_; + double origin_x_; + double origin_y_; + double origin_z_; + ::std::string* data_; + int coordinateframetype_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static GLOverlay* default_instance_; +}; +// ------------------------------------------------------------------- + +class Obstacle : public ::google::protobuf::Message { + public: + Obstacle(); + virtual ~Obstacle(); + + Obstacle(const Obstacle& from); + + inline Obstacle& operator=(const Obstacle& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const Obstacle& default_instance(); + + void Swap(Obstacle* other); + + // implements Message ---------------------------------------------- + + Obstacle* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const Obstacle& from); + void MergeFrom(const Obstacle& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional float x = 1; + inline bool has_x() const; + inline void clear_x(); + static const int kXFieldNumber = 1; + inline float x() const; + inline void set_x(float value); + + // optional float y = 2; + inline bool has_y() const; + inline void clear_y(); + static const int kYFieldNumber = 2; + inline float y() const; + inline void set_y(float value); + + // optional float z = 3; + inline bool has_z() const; + inline void clear_z(); + static const int kZFieldNumber = 3; + inline float z() const; + inline void set_z(float value); + + // optional float length = 4; + inline bool has_length() const; + inline void clear_length(); + static const int kLengthFieldNumber = 4; + inline float length() const; + inline void set_length(float value); + + // optional float width = 5; + inline bool has_width() const; + inline void clear_width(); + static const int kWidthFieldNumber = 5; + inline float width() const; + inline void set_width(float value); + + // optional float height = 6; + inline bool has_height() const; + inline void clear_height(); + static const int kHeightFieldNumber = 6; + inline float height() const; + inline void set_height(float value); + + // @@protoc_insertion_point(class_scope:px.Obstacle) + private: + inline void set_has_x(); + inline void clear_has_x(); + inline void set_has_y(); + inline void clear_has_y(); + inline void set_has_z(); + inline void clear_has_z(); + inline void set_has_length(); + inline void clear_has_length(); + inline void set_has_width(); + inline void clear_has_width(); + inline void set_has_height(); + inline void clear_has_height(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + float x_; + float y_; + float z_; + float length_; + float width_; + float height_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static Obstacle* default_instance_; +}; +// ------------------------------------------------------------------- + +class ObstacleList : public ::google::protobuf::Message { + public: + ObstacleList(); + virtual ~ObstacleList(); + + ObstacleList(const ObstacleList& from); + + inline ObstacleList& operator=(const ObstacleList& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ObstacleList& default_instance(); + + void Swap(ObstacleList* other); + + // implements Message ---------------------------------------------- + + ObstacleList* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ObstacleList& from); + void MergeFrom(const ObstacleList& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // repeated .px.Obstacle obstacles = 2; + inline int obstacles_size() const; + inline void clear_obstacles(); + static const int kObstaclesFieldNumber = 2; + inline const ::px::Obstacle& obstacles(int index) const; + inline ::px::Obstacle* mutable_obstacles(int index); + inline ::px::Obstacle* add_obstacles(); + inline const ::google::protobuf::RepeatedPtrField< ::px::Obstacle >& + obstacles() const; + inline ::google::protobuf::RepeatedPtrField< ::px::Obstacle >* + mutable_obstacles(); + + // @@protoc_insertion_point(class_scope:px.ObstacleList) + private: + inline void set_has_header(); + inline void clear_has_header(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::google::protobuf::RepeatedPtrField< ::px::Obstacle > obstacles_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static ObstacleList* default_instance_; +}; +// ------------------------------------------------------------------- + +class ObstacleMap : public ::google::protobuf::Message { + public: + ObstacleMap(); + virtual ~ObstacleMap(); + + ObstacleMap(const ObstacleMap& from); + + inline ObstacleMap& operator=(const ObstacleMap& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ObstacleMap& default_instance(); + + void Swap(ObstacleMap* other); + + // implements Message ---------------------------------------------- + + ObstacleMap* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ObstacleMap& from); + void MergeFrom(const ObstacleMap& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // required int32 type = 2; + inline bool has_type() const; + inline void clear_type(); + static const int kTypeFieldNumber = 2; + inline ::google::protobuf::int32 type() const; + inline void set_type(::google::protobuf::int32 value); + + // optional float resolution = 3; + inline bool has_resolution() const; + inline void clear_resolution(); + static const int kResolutionFieldNumber = 3; + inline float resolution() const; + inline void set_resolution(float value); + + // optional int32 rows = 4; + inline bool has_rows() const; + inline void clear_rows(); + static const int kRowsFieldNumber = 4; + inline ::google::protobuf::int32 rows() const; + inline void set_rows(::google::protobuf::int32 value); + + // optional int32 cols = 5; + inline bool has_cols() const; + inline void clear_cols(); + static const int kColsFieldNumber = 5; + inline ::google::protobuf::int32 cols() const; + inline void set_cols(::google::protobuf::int32 value); + + // optional int32 mapR0 = 6; + inline bool has_mapr0() const; + inline void clear_mapr0(); + static const int kMapR0FieldNumber = 6; + inline ::google::protobuf::int32 mapr0() const; + inline void set_mapr0(::google::protobuf::int32 value); + + // optional int32 mapC0 = 7; + inline bool has_mapc0() const; + inline void clear_mapc0(); + static const int kMapC0FieldNumber = 7; + inline ::google::protobuf::int32 mapc0() const; + inline void set_mapc0(::google::protobuf::int32 value); + + // optional int32 arrayR0 = 8; + inline bool has_arrayr0() const; + inline void clear_arrayr0(); + static const int kArrayR0FieldNumber = 8; + inline ::google::protobuf::int32 arrayr0() const; + inline void set_arrayr0(::google::protobuf::int32 value); + + // optional int32 arrayC0 = 9; + inline bool has_arrayc0() const; + inline void clear_arrayc0(); + static const int kArrayC0FieldNumber = 9; + inline ::google::protobuf::int32 arrayc0() const; + inline void set_arrayc0(::google::protobuf::int32 value); + + // optional bytes data = 10; + inline bool has_data() const; + inline void clear_data(); + static const int kDataFieldNumber = 10; + inline const ::std::string& data() const; + inline void set_data(const ::std::string& value); + inline void set_data(const char* value); + inline void set_data(const void* value, size_t size); + inline ::std::string* mutable_data(); + inline ::std::string* release_data(); + + // @@protoc_insertion_point(class_scope:px.ObstacleMap) + private: + inline void set_has_header(); + inline void clear_has_header(); + inline void set_has_type(); + inline void clear_has_type(); + inline void set_has_resolution(); + inline void clear_has_resolution(); + inline void set_has_rows(); + inline void clear_has_rows(); + inline void set_has_cols(); + inline void clear_has_cols(); + inline void set_has_mapr0(); + inline void clear_has_mapr0(); + inline void set_has_mapc0(); + inline void clear_has_mapc0(); + inline void set_has_arrayr0(); + inline void clear_has_arrayr0(); + inline void set_has_arrayc0(); + inline void clear_has_arrayc0(); + inline void set_has_data(); + inline void clear_has_data(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::google::protobuf::int32 type_; + float resolution_; + ::google::protobuf::int32 rows_; + ::google::protobuf::int32 cols_; + ::google::protobuf::int32 mapr0_; + ::google::protobuf::int32 mapc0_; + ::google::protobuf::int32 arrayr0_; + ::google::protobuf::int32 arrayc0_; + ::std::string* data_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(10 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static ObstacleMap* default_instance_; +}; +// ------------------------------------------------------------------- + +class Path : public ::google::protobuf::Message { + public: + Path(); + virtual ~Path(); + + Path(const Path& from); + + inline Path& operator=(const Path& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const Path& default_instance(); + + void Swap(Path* other); + + // implements Message ---------------------------------------------- + + Path* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const Path& from); + void MergeFrom(const Path& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // repeated .px.Waypoint waypoints = 2; + inline int waypoints_size() const; + inline void clear_waypoints(); + static const int kWaypointsFieldNumber = 2; + inline const ::px::Waypoint& waypoints(int index) const; + inline ::px::Waypoint* mutable_waypoints(int index); + inline ::px::Waypoint* add_waypoints(); + inline const ::google::protobuf::RepeatedPtrField< ::px::Waypoint >& + waypoints() const; + inline ::google::protobuf::RepeatedPtrField< ::px::Waypoint >* + mutable_waypoints(); + + // @@protoc_insertion_point(class_scope:px.Path) + private: + inline void set_has_header(); + inline void clear_has_header(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::google::protobuf::RepeatedPtrField< ::px::Waypoint > waypoints_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static Path* default_instance_; +}; +// ------------------------------------------------------------------- + +class PointCloudXYZI_PointXYZI : public ::google::protobuf::Message { + public: + PointCloudXYZI_PointXYZI(); + virtual ~PointCloudXYZI_PointXYZI(); + + PointCloudXYZI_PointXYZI(const PointCloudXYZI_PointXYZI& from); + + inline PointCloudXYZI_PointXYZI& operator=(const PointCloudXYZI_PointXYZI& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const PointCloudXYZI_PointXYZI& default_instance(); + + void Swap(PointCloudXYZI_PointXYZI* other); + + // implements Message ---------------------------------------------- + + PointCloudXYZI_PointXYZI* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const PointCloudXYZI_PointXYZI& from); + void MergeFrom(const PointCloudXYZI_PointXYZI& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required float x = 1; + inline bool has_x() const; + inline void clear_x(); + static const int kXFieldNumber = 1; + inline float x() const; + inline void set_x(float value); + + // required float y = 2; + inline bool has_y() const; + inline void clear_y(); + static const int kYFieldNumber = 2; + inline float y() const; + inline void set_y(float value); + + // required float z = 3; + inline bool has_z() const; + inline void clear_z(); + static const int kZFieldNumber = 3; + inline float z() const; + inline void set_z(float value); + + // required float intensity = 4; + inline bool has_intensity() const; + inline void clear_intensity(); + static const int kIntensityFieldNumber = 4; + inline float intensity() const; + inline void set_intensity(float value); + + // @@protoc_insertion_point(class_scope:px.PointCloudXYZI.PointXYZI) + private: + inline void set_has_x(); + inline void clear_has_x(); + inline void set_has_y(); + inline void clear_has_y(); + inline void set_has_z(); + inline void clear_has_z(); + inline void set_has_intensity(); + inline void clear_has_intensity(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + float x_; + float y_; + float z_; + float intensity_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static PointCloudXYZI_PointXYZI* default_instance_; +}; +// ------------------------------------------------------------------- + +class PointCloudXYZI : public ::google::protobuf::Message { + public: + PointCloudXYZI(); + virtual ~PointCloudXYZI(); + + PointCloudXYZI(const PointCloudXYZI& from); + + inline PointCloudXYZI& operator=(const PointCloudXYZI& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const PointCloudXYZI& default_instance(); + + void Swap(PointCloudXYZI* other); + + // implements Message ---------------------------------------------- + + PointCloudXYZI* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const PointCloudXYZI& from); + void MergeFrom(const PointCloudXYZI& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef PointCloudXYZI_PointXYZI PointXYZI; + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // repeated .px.PointCloudXYZI.PointXYZI points = 2; + inline int points_size() const; + inline void clear_points(); + static const int kPointsFieldNumber = 2; + inline const ::px::PointCloudXYZI_PointXYZI& points(int index) const; + inline ::px::PointCloudXYZI_PointXYZI* mutable_points(int index); + inline ::px::PointCloudXYZI_PointXYZI* add_points(); + inline const ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZI_PointXYZI >& + points() const; + inline ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZI_PointXYZI >* + mutable_points(); + + // @@protoc_insertion_point(class_scope:px.PointCloudXYZI) + private: + inline void set_has_header(); + inline void clear_has_header(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZI_PointXYZI > points_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static PointCloudXYZI* default_instance_; +}; +// ------------------------------------------------------------------- + +class PointCloudXYZRGB_PointXYZRGB : public ::google::protobuf::Message { + public: + PointCloudXYZRGB_PointXYZRGB(); + virtual ~PointCloudXYZRGB_PointXYZRGB(); + + PointCloudXYZRGB_PointXYZRGB(const PointCloudXYZRGB_PointXYZRGB& from); + + inline PointCloudXYZRGB_PointXYZRGB& operator=(const PointCloudXYZRGB_PointXYZRGB& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const PointCloudXYZRGB_PointXYZRGB& default_instance(); + + void Swap(PointCloudXYZRGB_PointXYZRGB* other); + + // implements Message ---------------------------------------------- + + PointCloudXYZRGB_PointXYZRGB* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const PointCloudXYZRGB_PointXYZRGB& from); + void MergeFrom(const PointCloudXYZRGB_PointXYZRGB& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required float x = 1; + inline bool has_x() const; + inline void clear_x(); + static const int kXFieldNumber = 1; + inline float x() const; + inline void set_x(float value); + + // required float y = 2; + inline bool has_y() const; + inline void clear_y(); + static const int kYFieldNumber = 2; + inline float y() const; + inline void set_y(float value); + + // required float z = 3; + inline bool has_z() const; + inline void clear_z(); + static const int kZFieldNumber = 3; + inline float z() const; + inline void set_z(float value); + + // required float rgb = 4; + inline bool has_rgb() const; + inline void clear_rgb(); + static const int kRgbFieldNumber = 4; + inline float rgb() const; + inline void set_rgb(float value); + + // @@protoc_insertion_point(class_scope:px.PointCloudXYZRGB.PointXYZRGB) + private: + inline void set_has_x(); + inline void clear_has_x(); + inline void set_has_y(); + inline void clear_has_y(); + inline void set_has_z(); + inline void clear_has_z(); + inline void set_has_rgb(); + inline void clear_has_rgb(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + float x_; + float y_; + float z_; + float rgb_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static PointCloudXYZRGB_PointXYZRGB* default_instance_; +}; +// ------------------------------------------------------------------- + +class PointCloudXYZRGB : public ::google::protobuf::Message { + public: + PointCloudXYZRGB(); + virtual ~PointCloudXYZRGB(); + + PointCloudXYZRGB(const PointCloudXYZRGB& from); + + inline PointCloudXYZRGB& operator=(const PointCloudXYZRGB& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const PointCloudXYZRGB& default_instance(); + + void Swap(PointCloudXYZRGB* other); + + // implements Message ---------------------------------------------- + + PointCloudXYZRGB* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const PointCloudXYZRGB& from); + void MergeFrom(const PointCloudXYZRGB& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef PointCloudXYZRGB_PointXYZRGB PointXYZRGB; + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // repeated .px.PointCloudXYZRGB.PointXYZRGB points = 2; + inline int points_size() const; + inline void clear_points(); + static const int kPointsFieldNumber = 2; + inline const ::px::PointCloudXYZRGB_PointXYZRGB& points(int index) const; + inline ::px::PointCloudXYZRGB_PointXYZRGB* mutable_points(int index); + inline ::px::PointCloudXYZRGB_PointXYZRGB* add_points(); + inline const ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZRGB_PointXYZRGB >& + points() const; + inline ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZRGB_PointXYZRGB >* + mutable_points(); + + // @@protoc_insertion_point(class_scope:px.PointCloudXYZRGB) + private: + inline void set_has_header(); + inline void clear_has_header(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZRGB_PointXYZRGB > points_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static PointCloudXYZRGB* default_instance_; +}; +// ------------------------------------------------------------------- + +class RGBDImage : public ::google::protobuf::Message { + public: + RGBDImage(); + virtual ~RGBDImage(); + + RGBDImage(const RGBDImage& from); + + inline RGBDImage& operator=(const RGBDImage& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RGBDImage& default_instance(); + + void Swap(RGBDImage* other); + + // implements Message ---------------------------------------------- + + RGBDImage* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RGBDImage& from); + void MergeFrom(const RGBDImage& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .px.HeaderInfo header = 1; + inline bool has_header() const; + inline void clear_header(); + static const int kHeaderFieldNumber = 1; + inline const ::px::HeaderInfo& header() const; + inline ::px::HeaderInfo* mutable_header(); + inline ::px::HeaderInfo* release_header(); + + // required uint32 cols = 2; + inline bool has_cols() const; + inline void clear_cols(); + static const int kColsFieldNumber = 2; + inline ::google::protobuf::uint32 cols() const; + inline void set_cols(::google::protobuf::uint32 value); + + // required uint32 rows = 3; + inline bool has_rows() const; + inline void clear_rows(); + static const int kRowsFieldNumber = 3; + inline ::google::protobuf::uint32 rows() const; + inline void set_rows(::google::protobuf::uint32 value); + + // required uint32 step1 = 4; + inline bool has_step1() const; + inline void clear_step1(); + static const int kStep1FieldNumber = 4; + inline ::google::protobuf::uint32 step1() const; + inline void set_step1(::google::protobuf::uint32 value); + + // required uint32 type1 = 5; + inline bool has_type1() const; + inline void clear_type1(); + static const int kType1FieldNumber = 5; + inline ::google::protobuf::uint32 type1() const; + inline void set_type1(::google::protobuf::uint32 value); + + // required bytes imageData1 = 6; + inline bool has_imagedata1() const; + inline void clear_imagedata1(); + static const int kImageData1FieldNumber = 6; + inline const ::std::string& imagedata1() const; + inline void set_imagedata1(const ::std::string& value); + inline void set_imagedata1(const char* value); + inline void set_imagedata1(const void* value, size_t size); + inline ::std::string* mutable_imagedata1(); + inline ::std::string* release_imagedata1(); + + // required uint32 step2 = 7; + inline bool has_step2() const; + inline void clear_step2(); + static const int kStep2FieldNumber = 7; + inline ::google::protobuf::uint32 step2() const; + inline void set_step2(::google::protobuf::uint32 value); + + // required uint32 type2 = 8; + inline bool has_type2() const; + inline void clear_type2(); + static const int kType2FieldNumber = 8; + inline ::google::protobuf::uint32 type2() const; + inline void set_type2(::google::protobuf::uint32 value); + + // required bytes imageData2 = 9; + inline bool has_imagedata2() const; + inline void clear_imagedata2(); + static const int kImageData2FieldNumber = 9; + inline const ::std::string& imagedata2() const; + inline void set_imagedata2(const ::std::string& value); + inline void set_imagedata2(const char* value); + inline void set_imagedata2(const void* value, size_t size); + inline ::std::string* mutable_imagedata2(); + inline ::std::string* release_imagedata2(); + + // optional uint32 camera_config = 10; + inline bool has_camera_config() const; + inline void clear_camera_config(); + static const int kCameraConfigFieldNumber = 10; + inline ::google::protobuf::uint32 camera_config() const; + inline void set_camera_config(::google::protobuf::uint32 value); + + // optional uint32 camera_type = 11; + inline bool has_camera_type() const; + inline void clear_camera_type(); + static const int kCameraTypeFieldNumber = 11; + inline ::google::protobuf::uint32 camera_type() const; + inline void set_camera_type(::google::protobuf::uint32 value); + + // optional float roll = 12; + inline bool has_roll() const; + inline void clear_roll(); + static const int kRollFieldNumber = 12; + inline float roll() const; + inline void set_roll(float value); + + // optional float pitch = 13; + inline bool has_pitch() const; + inline void clear_pitch(); + static const int kPitchFieldNumber = 13; + inline float pitch() const; + inline void set_pitch(float value); + + // optional float yaw = 14; + inline bool has_yaw() const; + inline void clear_yaw(); + static const int kYawFieldNumber = 14; + inline float yaw() const; + inline void set_yaw(float value); + + // optional float lon = 15; + inline bool has_lon() const; + inline void clear_lon(); + static const int kLonFieldNumber = 15; + inline float lon() const; + inline void set_lon(float value); + + // optional float lat = 16; + inline bool has_lat() const; + inline void clear_lat(); + static const int kLatFieldNumber = 16; + inline float lat() const; + inline void set_lat(float value); + + // optional float alt = 17; + inline bool has_alt() const; + inline void clear_alt(); + static const int kAltFieldNumber = 17; + inline float alt() const; + inline void set_alt(float value); + + // optional float ground_x = 18; + inline bool has_ground_x() const; + inline void clear_ground_x(); + static const int kGroundXFieldNumber = 18; + inline float ground_x() const; + inline void set_ground_x(float value); + + // optional float ground_y = 19; + inline bool has_ground_y() const; + inline void clear_ground_y(); + static const int kGroundYFieldNumber = 19; + inline float ground_y() const; + inline void set_ground_y(float value); + + // optional float ground_z = 20; + inline bool has_ground_z() const; + inline void clear_ground_z(); + static const int kGroundZFieldNumber = 20; + inline float ground_z() const; + inline void set_ground_z(float value); + + // repeated float camera_matrix = 21; + inline int camera_matrix_size() const; + inline void clear_camera_matrix(); + static const int kCameraMatrixFieldNumber = 21; + inline float camera_matrix(int index) const; + inline void set_camera_matrix(int index, float value); + inline void add_camera_matrix(float value); + inline const ::google::protobuf::RepeatedField< float >& + camera_matrix() const; + inline ::google::protobuf::RepeatedField< float >* + mutable_camera_matrix(); + + // @@protoc_insertion_point(class_scope:px.RGBDImage) + private: + inline void set_has_header(); + inline void clear_has_header(); + inline void set_has_cols(); + inline void clear_has_cols(); + inline void set_has_rows(); + inline void clear_has_rows(); + inline void set_has_step1(); + inline void clear_has_step1(); + inline void set_has_type1(); + inline void clear_has_type1(); + inline void set_has_imagedata1(); + inline void clear_has_imagedata1(); + inline void set_has_step2(); + inline void clear_has_step2(); + inline void set_has_type2(); + inline void clear_has_type2(); + inline void set_has_imagedata2(); + inline void clear_has_imagedata2(); + inline void set_has_camera_config(); + inline void clear_has_camera_config(); + inline void set_has_camera_type(); + inline void clear_has_camera_type(); + inline void set_has_roll(); + inline void clear_has_roll(); + inline void set_has_pitch(); + inline void clear_has_pitch(); + inline void set_has_yaw(); + inline void clear_has_yaw(); + inline void set_has_lon(); + inline void clear_has_lon(); + inline void set_has_lat(); + inline void clear_has_lat(); + inline void set_has_alt(); + inline void clear_has_alt(); + inline void set_has_ground_x(); + inline void clear_has_ground_x(); + inline void set_has_ground_y(); + inline void clear_has_ground_y(); + inline void set_has_ground_z(); + inline void clear_has_ground_z(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::px::HeaderInfo* header_; + ::google::protobuf::uint32 cols_; + ::google::protobuf::uint32 rows_; + ::google::protobuf::uint32 step1_; + ::google::protobuf::uint32 type1_; + ::std::string* imagedata1_; + ::google::protobuf::uint32 step2_; + ::google::protobuf::uint32 type2_; + ::std::string* imagedata2_; + ::google::protobuf::uint32 camera_config_; + ::google::protobuf::uint32 camera_type_; + float roll_; + float pitch_; + float yaw_; + float lon_; + float lat_; + float alt_; + float ground_x_; + float ground_y_; + ::google::protobuf::RepeatedField< float > camera_matrix_; + float ground_z_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(21 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static RGBDImage* default_instance_; +}; +// ------------------------------------------------------------------- + +class Waypoint : public ::google::protobuf::Message { + public: + Waypoint(); + virtual ~Waypoint(); + + Waypoint(const Waypoint& from); + + inline Waypoint& operator=(const Waypoint& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const Waypoint& default_instance(); + + void Swap(Waypoint* other); + + // implements Message ---------------------------------------------- + + Waypoint* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const Waypoint& from); + void MergeFrom(const Waypoint& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required double x = 1; + inline bool has_x() const; + inline void clear_x(); + static const int kXFieldNumber = 1; + inline double x() const; + inline void set_x(double value); + + // required double y = 2; + inline bool has_y() const; + inline void clear_y(); + static const int kYFieldNumber = 2; + inline double y() const; + inline void set_y(double value); + + // optional double z = 3; + inline bool has_z() const; + inline void clear_z(); + static const int kZFieldNumber = 3; + inline double z() const; + inline void set_z(double value); + + // optional double roll = 4; + inline bool has_roll() const; + inline void clear_roll(); + static const int kRollFieldNumber = 4; + inline double roll() const; + inline void set_roll(double value); + + // optional double pitch = 5; + inline bool has_pitch() const; + inline void clear_pitch(); + static const int kPitchFieldNumber = 5; + inline double pitch() const; + inline void set_pitch(double value); + + // optional double yaw = 6; + inline bool has_yaw() const; + inline void clear_yaw(); + static const int kYawFieldNumber = 6; + inline double yaw() const; + inline void set_yaw(double value); + + // @@protoc_insertion_point(class_scope:px.Waypoint) + private: + inline void set_has_x(); + inline void clear_has_x(); + inline void set_has_y(); + inline void clear_has_y(); + inline void set_has_z(); + inline void clear_has_z(); + inline void set_has_roll(); + inline void clear_has_roll(); + inline void set_has_pitch(); + inline void clear_has_pitch(); + inline void set_has_yaw(); + inline void clear_has_yaw(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + double x_; + double y_; + double z_; + double roll_; + double pitch_; + double yaw_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32]; + + friend void protobuf_AddDesc_pixhawk_2eproto(); + friend void protobuf_AssignDesc_pixhawk_2eproto(); + friend void protobuf_ShutdownFile_pixhawk_2eproto(); + + void InitAsDefaultInstance(); + static Waypoint* default_instance_; +}; +// =================================================================== + + +// =================================================================== + +// HeaderInfo + +// required int32 source_sysid = 1; +inline bool HeaderInfo::has_source_sysid() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void HeaderInfo::set_has_source_sysid() { + _has_bits_[0] |= 0x00000001u; +} +inline void HeaderInfo::clear_has_source_sysid() { + _has_bits_[0] &= ~0x00000001u; +} +inline void HeaderInfo::clear_source_sysid() { + source_sysid_ = 0; + clear_has_source_sysid(); +} +inline ::google::protobuf::int32 HeaderInfo::source_sysid() const { + return source_sysid_; +} +inline void HeaderInfo::set_source_sysid(::google::protobuf::int32 value) { + set_has_source_sysid(); + source_sysid_ = value; +} + +// required int32 source_compid = 2; +inline bool HeaderInfo::has_source_compid() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void HeaderInfo::set_has_source_compid() { + _has_bits_[0] |= 0x00000002u; +} +inline void HeaderInfo::clear_has_source_compid() { + _has_bits_[0] &= ~0x00000002u; +} +inline void HeaderInfo::clear_source_compid() { + source_compid_ = 0; + clear_has_source_compid(); +} +inline ::google::protobuf::int32 HeaderInfo::source_compid() const { + return source_compid_; +} +inline void HeaderInfo::set_source_compid(::google::protobuf::int32 value) { + set_has_source_compid(); + source_compid_ = value; +} + +// required double timestamp = 3; +inline bool HeaderInfo::has_timestamp() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void HeaderInfo::set_has_timestamp() { + _has_bits_[0] |= 0x00000004u; +} +inline void HeaderInfo::clear_has_timestamp() { + _has_bits_[0] &= ~0x00000004u; +} +inline void HeaderInfo::clear_timestamp() { + timestamp_ = 0; + clear_has_timestamp(); +} +inline double HeaderInfo::timestamp() const { + return timestamp_; +} +inline void HeaderInfo::set_timestamp(double value) { + set_has_timestamp(); + timestamp_ = value; +} + +// ------------------------------------------------------------------- + +// GLOverlay + +// required .px.HeaderInfo header = 1; +inline bool GLOverlay::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void GLOverlay::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void GLOverlay::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void GLOverlay::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& GLOverlay::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* GLOverlay::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* GLOverlay::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// optional string name = 2; +inline bool GLOverlay::has_name() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void GLOverlay::set_has_name() { + _has_bits_[0] |= 0x00000002u; +} +inline void GLOverlay::clear_has_name() { + _has_bits_[0] &= ~0x00000002u; +} +inline void GLOverlay::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& GLOverlay::name() const { + return *name_; +} +inline void GLOverlay::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void GLOverlay::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void GLOverlay::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* GLOverlay::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* GLOverlay::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// optional .px.GLOverlay.CoordinateFrameType coordinateFrameType = 3; +inline bool GLOverlay::has_coordinateframetype() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void GLOverlay::set_has_coordinateframetype() { + _has_bits_[0] |= 0x00000004u; +} +inline void GLOverlay::clear_has_coordinateframetype() { + _has_bits_[0] &= ~0x00000004u; +} +inline void GLOverlay::clear_coordinateframetype() { + coordinateframetype_ = 0; + clear_has_coordinateframetype(); +} +inline ::px::GLOverlay_CoordinateFrameType GLOverlay::coordinateframetype() const { + return static_cast< ::px::GLOverlay_CoordinateFrameType >(coordinateframetype_); +} +inline void GLOverlay::set_coordinateframetype(::px::GLOverlay_CoordinateFrameType value) { + GOOGLE_DCHECK(::px::GLOverlay_CoordinateFrameType_IsValid(value)); + set_has_coordinateframetype(); + coordinateframetype_ = value; +} + +// optional double origin_x = 4; +inline bool GLOverlay::has_origin_x() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void GLOverlay::set_has_origin_x() { + _has_bits_[0] |= 0x00000008u; +} +inline void GLOverlay::clear_has_origin_x() { + _has_bits_[0] &= ~0x00000008u; +} +inline void GLOverlay::clear_origin_x() { + origin_x_ = 0; + clear_has_origin_x(); +} +inline double GLOverlay::origin_x() const { + return origin_x_; +} +inline void GLOverlay::set_origin_x(double value) { + set_has_origin_x(); + origin_x_ = value; +} + +// optional double origin_y = 5; +inline bool GLOverlay::has_origin_y() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void GLOverlay::set_has_origin_y() { + _has_bits_[0] |= 0x00000010u; +} +inline void GLOverlay::clear_has_origin_y() { + _has_bits_[0] &= ~0x00000010u; +} +inline void GLOverlay::clear_origin_y() { + origin_y_ = 0; + clear_has_origin_y(); +} +inline double GLOverlay::origin_y() const { + return origin_y_; +} +inline void GLOverlay::set_origin_y(double value) { + set_has_origin_y(); + origin_y_ = value; +} + +// optional double origin_z = 6; +inline bool GLOverlay::has_origin_z() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void GLOverlay::set_has_origin_z() { + _has_bits_[0] |= 0x00000020u; +} +inline void GLOverlay::clear_has_origin_z() { + _has_bits_[0] &= ~0x00000020u; +} +inline void GLOverlay::clear_origin_z() { + origin_z_ = 0; + clear_has_origin_z(); +} +inline double GLOverlay::origin_z() const { + return origin_z_; +} +inline void GLOverlay::set_origin_z(double value) { + set_has_origin_z(); + origin_z_ = value; +} + +// optional bytes data = 7; +inline bool GLOverlay::has_data() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void GLOverlay::set_has_data() { + _has_bits_[0] |= 0x00000040u; +} +inline void GLOverlay::clear_has_data() { + _has_bits_[0] &= ~0x00000040u; +} +inline void GLOverlay::clear_data() { + if (data_ != &::google::protobuf::internal::kEmptyString) { + data_->clear(); + } + clear_has_data(); +} +inline const ::std::string& GLOverlay::data() const { + return *data_; +} +inline void GLOverlay::set_data(const ::std::string& value) { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + data_->assign(value); +} +inline void GLOverlay::set_data(const char* value) { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + data_->assign(value); +} +inline void GLOverlay::set_data(const void* value, size_t size) { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + data_->assign(reinterpret_cast(value), size); +} +inline ::std::string* GLOverlay::mutable_data() { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + return data_; +} +inline ::std::string* GLOverlay::release_data() { + clear_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = data_; + data_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// ------------------------------------------------------------------- + +// Obstacle + +// optional float x = 1; +inline bool Obstacle::has_x() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void Obstacle::set_has_x() { + _has_bits_[0] |= 0x00000001u; +} +inline void Obstacle::clear_has_x() { + _has_bits_[0] &= ~0x00000001u; +} +inline void Obstacle::clear_x() { + x_ = 0; + clear_has_x(); +} +inline float Obstacle::x() const { + return x_; +} +inline void Obstacle::set_x(float value) { + set_has_x(); + x_ = value; +} + +// optional float y = 2; +inline bool Obstacle::has_y() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void Obstacle::set_has_y() { + _has_bits_[0] |= 0x00000002u; +} +inline void Obstacle::clear_has_y() { + _has_bits_[0] &= ~0x00000002u; +} +inline void Obstacle::clear_y() { + y_ = 0; + clear_has_y(); +} +inline float Obstacle::y() const { + return y_; +} +inline void Obstacle::set_y(float value) { + set_has_y(); + y_ = value; +} + +// optional float z = 3; +inline bool Obstacle::has_z() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void Obstacle::set_has_z() { + _has_bits_[0] |= 0x00000004u; +} +inline void Obstacle::clear_has_z() { + _has_bits_[0] &= ~0x00000004u; +} +inline void Obstacle::clear_z() { + z_ = 0; + clear_has_z(); +} +inline float Obstacle::z() const { + return z_; +} +inline void Obstacle::set_z(float value) { + set_has_z(); + z_ = value; +} + +// optional float length = 4; +inline bool Obstacle::has_length() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void Obstacle::set_has_length() { + _has_bits_[0] |= 0x00000008u; +} +inline void Obstacle::clear_has_length() { + _has_bits_[0] &= ~0x00000008u; +} +inline void Obstacle::clear_length() { + length_ = 0; + clear_has_length(); +} +inline float Obstacle::length() const { + return length_; +} +inline void Obstacle::set_length(float value) { + set_has_length(); + length_ = value; +} + +// optional float width = 5; +inline bool Obstacle::has_width() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void Obstacle::set_has_width() { + _has_bits_[0] |= 0x00000010u; +} +inline void Obstacle::clear_has_width() { + _has_bits_[0] &= ~0x00000010u; +} +inline void Obstacle::clear_width() { + width_ = 0; + clear_has_width(); +} +inline float Obstacle::width() const { + return width_; +} +inline void Obstacle::set_width(float value) { + set_has_width(); + width_ = value; +} + +// optional float height = 6; +inline bool Obstacle::has_height() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void Obstacle::set_has_height() { + _has_bits_[0] |= 0x00000020u; +} +inline void Obstacle::clear_has_height() { + _has_bits_[0] &= ~0x00000020u; +} +inline void Obstacle::clear_height() { + height_ = 0; + clear_has_height(); +} +inline float Obstacle::height() const { + return height_; +} +inline void Obstacle::set_height(float value) { + set_has_height(); + height_ = value; +} + +// ------------------------------------------------------------------- + +// ObstacleList + +// required .px.HeaderInfo header = 1; +inline bool ObstacleList::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ObstacleList::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void ObstacleList::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ObstacleList::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& ObstacleList::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* ObstacleList::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* ObstacleList::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// repeated .px.Obstacle obstacles = 2; +inline int ObstacleList::obstacles_size() const { + return obstacles_.size(); +} +inline void ObstacleList::clear_obstacles() { + obstacles_.Clear(); +} +inline const ::px::Obstacle& ObstacleList::obstacles(int index) const { + return obstacles_.Get(index); +} +inline ::px::Obstacle* ObstacleList::mutable_obstacles(int index) { + return obstacles_.Mutable(index); +} +inline ::px::Obstacle* ObstacleList::add_obstacles() { + return obstacles_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::px::Obstacle >& +ObstacleList::obstacles() const { + return obstacles_; +} +inline ::google::protobuf::RepeatedPtrField< ::px::Obstacle >* +ObstacleList::mutable_obstacles() { + return &obstacles_; +} + +// ------------------------------------------------------------------- + +// ObstacleMap + +// required .px.HeaderInfo header = 1; +inline bool ObstacleMap::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ObstacleMap::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void ObstacleMap::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ObstacleMap::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& ObstacleMap::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* ObstacleMap::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* ObstacleMap::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// required int32 type = 2; +inline bool ObstacleMap::has_type() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void ObstacleMap::set_has_type() { + _has_bits_[0] |= 0x00000002u; +} +inline void ObstacleMap::clear_has_type() { + _has_bits_[0] &= ~0x00000002u; +} +inline void ObstacleMap::clear_type() { + type_ = 0; + clear_has_type(); +} +inline ::google::protobuf::int32 ObstacleMap::type() const { + return type_; +} +inline void ObstacleMap::set_type(::google::protobuf::int32 value) { + set_has_type(); + type_ = value; +} + +// optional float resolution = 3; +inline bool ObstacleMap::has_resolution() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void ObstacleMap::set_has_resolution() { + _has_bits_[0] |= 0x00000004u; +} +inline void ObstacleMap::clear_has_resolution() { + _has_bits_[0] &= ~0x00000004u; +} +inline void ObstacleMap::clear_resolution() { + resolution_ = 0; + clear_has_resolution(); +} +inline float ObstacleMap::resolution() const { + return resolution_; +} +inline void ObstacleMap::set_resolution(float value) { + set_has_resolution(); + resolution_ = value; +} + +// optional int32 rows = 4; +inline bool ObstacleMap::has_rows() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void ObstacleMap::set_has_rows() { + _has_bits_[0] |= 0x00000008u; +} +inline void ObstacleMap::clear_has_rows() { + _has_bits_[0] &= ~0x00000008u; +} +inline void ObstacleMap::clear_rows() { + rows_ = 0; + clear_has_rows(); +} +inline ::google::protobuf::int32 ObstacleMap::rows() const { + return rows_; +} +inline void ObstacleMap::set_rows(::google::protobuf::int32 value) { + set_has_rows(); + rows_ = value; +} + +// optional int32 cols = 5; +inline bool ObstacleMap::has_cols() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void ObstacleMap::set_has_cols() { + _has_bits_[0] |= 0x00000010u; +} +inline void ObstacleMap::clear_has_cols() { + _has_bits_[0] &= ~0x00000010u; +} +inline void ObstacleMap::clear_cols() { + cols_ = 0; + clear_has_cols(); +} +inline ::google::protobuf::int32 ObstacleMap::cols() const { + return cols_; +} +inline void ObstacleMap::set_cols(::google::protobuf::int32 value) { + set_has_cols(); + cols_ = value; +} + +// optional int32 mapR0 = 6; +inline bool ObstacleMap::has_mapr0() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void ObstacleMap::set_has_mapr0() { + _has_bits_[0] |= 0x00000020u; +} +inline void ObstacleMap::clear_has_mapr0() { + _has_bits_[0] &= ~0x00000020u; +} +inline void ObstacleMap::clear_mapr0() { + mapr0_ = 0; + clear_has_mapr0(); +} +inline ::google::protobuf::int32 ObstacleMap::mapr0() const { + return mapr0_; +} +inline void ObstacleMap::set_mapr0(::google::protobuf::int32 value) { + set_has_mapr0(); + mapr0_ = value; +} + +// optional int32 mapC0 = 7; +inline bool ObstacleMap::has_mapc0() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void ObstacleMap::set_has_mapc0() { + _has_bits_[0] |= 0x00000040u; +} +inline void ObstacleMap::clear_has_mapc0() { + _has_bits_[0] &= ~0x00000040u; +} +inline void ObstacleMap::clear_mapc0() { + mapc0_ = 0; + clear_has_mapc0(); +} +inline ::google::protobuf::int32 ObstacleMap::mapc0() const { + return mapc0_; +} +inline void ObstacleMap::set_mapc0(::google::protobuf::int32 value) { + set_has_mapc0(); + mapc0_ = value; +} + +// optional int32 arrayR0 = 8; +inline bool ObstacleMap::has_arrayr0() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void ObstacleMap::set_has_arrayr0() { + _has_bits_[0] |= 0x00000080u; +} +inline void ObstacleMap::clear_has_arrayr0() { + _has_bits_[0] &= ~0x00000080u; +} +inline void ObstacleMap::clear_arrayr0() { + arrayr0_ = 0; + clear_has_arrayr0(); +} +inline ::google::protobuf::int32 ObstacleMap::arrayr0() const { + return arrayr0_; +} +inline void ObstacleMap::set_arrayr0(::google::protobuf::int32 value) { + set_has_arrayr0(); + arrayr0_ = value; +} + +// optional int32 arrayC0 = 9; +inline bool ObstacleMap::has_arrayc0() const { + return (_has_bits_[0] & 0x00000100u) != 0; +} +inline void ObstacleMap::set_has_arrayc0() { + _has_bits_[0] |= 0x00000100u; +} +inline void ObstacleMap::clear_has_arrayc0() { + _has_bits_[0] &= ~0x00000100u; +} +inline void ObstacleMap::clear_arrayc0() { + arrayc0_ = 0; + clear_has_arrayc0(); +} +inline ::google::protobuf::int32 ObstacleMap::arrayc0() const { + return arrayc0_; +} +inline void ObstacleMap::set_arrayc0(::google::protobuf::int32 value) { + set_has_arrayc0(); + arrayc0_ = value; +} + +// optional bytes data = 10; +inline bool ObstacleMap::has_data() const { + return (_has_bits_[0] & 0x00000200u) != 0; +} +inline void ObstacleMap::set_has_data() { + _has_bits_[0] |= 0x00000200u; +} +inline void ObstacleMap::clear_has_data() { + _has_bits_[0] &= ~0x00000200u; +} +inline void ObstacleMap::clear_data() { + if (data_ != &::google::protobuf::internal::kEmptyString) { + data_->clear(); + } + clear_has_data(); +} +inline const ::std::string& ObstacleMap::data() const { + return *data_; +} +inline void ObstacleMap::set_data(const ::std::string& value) { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + data_->assign(value); +} +inline void ObstacleMap::set_data(const char* value) { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + data_->assign(value); +} +inline void ObstacleMap::set_data(const void* value, size_t size) { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + data_->assign(reinterpret_cast(value), size); +} +inline ::std::string* ObstacleMap::mutable_data() { + set_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + data_ = new ::std::string; + } + return data_; +} +inline ::std::string* ObstacleMap::release_data() { + clear_has_data(); + if (data_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = data_; + data_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// ------------------------------------------------------------------- + +// Path + +// required .px.HeaderInfo header = 1; +inline bool Path::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void Path::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void Path::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void Path::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& Path::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* Path::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* Path::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// repeated .px.Waypoint waypoints = 2; +inline int Path::waypoints_size() const { + return waypoints_.size(); +} +inline void Path::clear_waypoints() { + waypoints_.Clear(); +} +inline const ::px::Waypoint& Path::waypoints(int index) const { + return waypoints_.Get(index); +} +inline ::px::Waypoint* Path::mutable_waypoints(int index) { + return waypoints_.Mutable(index); +} +inline ::px::Waypoint* Path::add_waypoints() { + return waypoints_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::px::Waypoint >& +Path::waypoints() const { + return waypoints_; +} +inline ::google::protobuf::RepeatedPtrField< ::px::Waypoint >* +Path::mutable_waypoints() { + return &waypoints_; +} + +// ------------------------------------------------------------------- + +// PointCloudXYZI_PointXYZI + +// required float x = 1; +inline bool PointCloudXYZI_PointXYZI::has_x() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void PointCloudXYZI_PointXYZI::set_has_x() { + _has_bits_[0] |= 0x00000001u; +} +inline void PointCloudXYZI_PointXYZI::clear_has_x() { + _has_bits_[0] &= ~0x00000001u; +} +inline void PointCloudXYZI_PointXYZI::clear_x() { + x_ = 0; + clear_has_x(); +} +inline float PointCloudXYZI_PointXYZI::x() const { + return x_; +} +inline void PointCloudXYZI_PointXYZI::set_x(float value) { + set_has_x(); + x_ = value; +} + +// required float y = 2; +inline bool PointCloudXYZI_PointXYZI::has_y() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void PointCloudXYZI_PointXYZI::set_has_y() { + _has_bits_[0] |= 0x00000002u; +} +inline void PointCloudXYZI_PointXYZI::clear_has_y() { + _has_bits_[0] &= ~0x00000002u; +} +inline void PointCloudXYZI_PointXYZI::clear_y() { + y_ = 0; + clear_has_y(); +} +inline float PointCloudXYZI_PointXYZI::y() const { + return y_; +} +inline void PointCloudXYZI_PointXYZI::set_y(float value) { + set_has_y(); + y_ = value; +} + +// required float z = 3; +inline bool PointCloudXYZI_PointXYZI::has_z() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void PointCloudXYZI_PointXYZI::set_has_z() { + _has_bits_[0] |= 0x00000004u; +} +inline void PointCloudXYZI_PointXYZI::clear_has_z() { + _has_bits_[0] &= ~0x00000004u; +} +inline void PointCloudXYZI_PointXYZI::clear_z() { + z_ = 0; + clear_has_z(); +} +inline float PointCloudXYZI_PointXYZI::z() const { + return z_; +} +inline void PointCloudXYZI_PointXYZI::set_z(float value) { + set_has_z(); + z_ = value; +} + +// required float intensity = 4; +inline bool PointCloudXYZI_PointXYZI::has_intensity() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void PointCloudXYZI_PointXYZI::set_has_intensity() { + _has_bits_[0] |= 0x00000008u; +} +inline void PointCloudXYZI_PointXYZI::clear_has_intensity() { + _has_bits_[0] &= ~0x00000008u; +} +inline void PointCloudXYZI_PointXYZI::clear_intensity() { + intensity_ = 0; + clear_has_intensity(); +} +inline float PointCloudXYZI_PointXYZI::intensity() const { + return intensity_; +} +inline void PointCloudXYZI_PointXYZI::set_intensity(float value) { + set_has_intensity(); + intensity_ = value; +} + +// ------------------------------------------------------------------- + +// PointCloudXYZI + +// required .px.HeaderInfo header = 1; +inline bool PointCloudXYZI::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void PointCloudXYZI::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void PointCloudXYZI::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void PointCloudXYZI::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& PointCloudXYZI::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* PointCloudXYZI::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* PointCloudXYZI::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// repeated .px.PointCloudXYZI.PointXYZI points = 2; +inline int PointCloudXYZI::points_size() const { + return points_.size(); +} +inline void PointCloudXYZI::clear_points() { + points_.Clear(); +} +inline const ::px::PointCloudXYZI_PointXYZI& PointCloudXYZI::points(int index) const { + return points_.Get(index); +} +inline ::px::PointCloudXYZI_PointXYZI* PointCloudXYZI::mutable_points(int index) { + return points_.Mutable(index); +} +inline ::px::PointCloudXYZI_PointXYZI* PointCloudXYZI::add_points() { + return points_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZI_PointXYZI >& +PointCloudXYZI::points() const { + return points_; +} +inline ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZI_PointXYZI >* +PointCloudXYZI::mutable_points() { + return &points_; +} + +// ------------------------------------------------------------------- + +// PointCloudXYZRGB_PointXYZRGB + +// required float x = 1; +inline bool PointCloudXYZRGB_PointXYZRGB::has_x() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_has_x() { + _has_bits_[0] |= 0x00000001u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_has_x() { + _has_bits_[0] &= ~0x00000001u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_x() { + x_ = 0; + clear_has_x(); +} +inline float PointCloudXYZRGB_PointXYZRGB::x() const { + return x_; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_x(float value) { + set_has_x(); + x_ = value; +} + +// required float y = 2; +inline bool PointCloudXYZRGB_PointXYZRGB::has_y() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_has_y() { + _has_bits_[0] |= 0x00000002u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_has_y() { + _has_bits_[0] &= ~0x00000002u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_y() { + y_ = 0; + clear_has_y(); +} +inline float PointCloudXYZRGB_PointXYZRGB::y() const { + return y_; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_y(float value) { + set_has_y(); + y_ = value; +} + +// required float z = 3; +inline bool PointCloudXYZRGB_PointXYZRGB::has_z() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_has_z() { + _has_bits_[0] |= 0x00000004u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_has_z() { + _has_bits_[0] &= ~0x00000004u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_z() { + z_ = 0; + clear_has_z(); +} +inline float PointCloudXYZRGB_PointXYZRGB::z() const { + return z_; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_z(float value) { + set_has_z(); + z_ = value; +} + +// required float rgb = 4; +inline bool PointCloudXYZRGB_PointXYZRGB::has_rgb() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_has_rgb() { + _has_bits_[0] |= 0x00000008u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_has_rgb() { + _has_bits_[0] &= ~0x00000008u; +} +inline void PointCloudXYZRGB_PointXYZRGB::clear_rgb() { + rgb_ = 0; + clear_has_rgb(); +} +inline float PointCloudXYZRGB_PointXYZRGB::rgb() const { + return rgb_; +} +inline void PointCloudXYZRGB_PointXYZRGB::set_rgb(float value) { + set_has_rgb(); + rgb_ = value; +} + +// ------------------------------------------------------------------- + +// PointCloudXYZRGB + +// required .px.HeaderInfo header = 1; +inline bool PointCloudXYZRGB::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void PointCloudXYZRGB::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void PointCloudXYZRGB::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void PointCloudXYZRGB::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& PointCloudXYZRGB::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* PointCloudXYZRGB::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* PointCloudXYZRGB::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// repeated .px.PointCloudXYZRGB.PointXYZRGB points = 2; +inline int PointCloudXYZRGB::points_size() const { + return points_.size(); +} +inline void PointCloudXYZRGB::clear_points() { + points_.Clear(); +} +inline const ::px::PointCloudXYZRGB_PointXYZRGB& PointCloudXYZRGB::points(int index) const { + return points_.Get(index); +} +inline ::px::PointCloudXYZRGB_PointXYZRGB* PointCloudXYZRGB::mutable_points(int index) { + return points_.Mutable(index); +} +inline ::px::PointCloudXYZRGB_PointXYZRGB* PointCloudXYZRGB::add_points() { + return points_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZRGB_PointXYZRGB >& +PointCloudXYZRGB::points() const { + return points_; +} +inline ::google::protobuf::RepeatedPtrField< ::px::PointCloudXYZRGB_PointXYZRGB >* +PointCloudXYZRGB::mutable_points() { + return &points_; +} + +// ------------------------------------------------------------------- + +// RGBDImage + +// required .px.HeaderInfo header = 1; +inline bool RGBDImage::has_header() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RGBDImage::set_has_header() { + _has_bits_[0] |= 0x00000001u; +} +inline void RGBDImage::clear_has_header() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RGBDImage::clear_header() { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + clear_has_header(); +} +inline const ::px::HeaderInfo& RGBDImage::header() const { + return header_ != NULL ? *header_ : *default_instance_->header_; +} +inline ::px::HeaderInfo* RGBDImage::mutable_header() { + set_has_header(); + if (header_ == NULL) header_ = new ::px::HeaderInfo; + return header_; +} +inline ::px::HeaderInfo* RGBDImage::release_header() { + clear_has_header(); + ::px::HeaderInfo* temp = header_; + header_ = NULL; + return temp; +} + +// required uint32 cols = 2; +inline bool RGBDImage::has_cols() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void RGBDImage::set_has_cols() { + _has_bits_[0] |= 0x00000002u; +} +inline void RGBDImage::clear_has_cols() { + _has_bits_[0] &= ~0x00000002u; +} +inline void RGBDImage::clear_cols() { + cols_ = 0u; + clear_has_cols(); +} +inline ::google::protobuf::uint32 RGBDImage::cols() const { + return cols_; +} +inline void RGBDImage::set_cols(::google::protobuf::uint32 value) { + set_has_cols(); + cols_ = value; +} + +// required uint32 rows = 3; +inline bool RGBDImage::has_rows() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void RGBDImage::set_has_rows() { + _has_bits_[0] |= 0x00000004u; +} +inline void RGBDImage::clear_has_rows() { + _has_bits_[0] &= ~0x00000004u; +} +inline void RGBDImage::clear_rows() { + rows_ = 0u; + clear_has_rows(); +} +inline ::google::protobuf::uint32 RGBDImage::rows() const { + return rows_; +} +inline void RGBDImage::set_rows(::google::protobuf::uint32 value) { + set_has_rows(); + rows_ = value; +} + +// required uint32 step1 = 4; +inline bool RGBDImage::has_step1() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void RGBDImage::set_has_step1() { + _has_bits_[0] |= 0x00000008u; +} +inline void RGBDImage::clear_has_step1() { + _has_bits_[0] &= ~0x00000008u; +} +inline void RGBDImage::clear_step1() { + step1_ = 0u; + clear_has_step1(); +} +inline ::google::protobuf::uint32 RGBDImage::step1() const { + return step1_; +} +inline void RGBDImage::set_step1(::google::protobuf::uint32 value) { + set_has_step1(); + step1_ = value; +} + +// required uint32 type1 = 5; +inline bool RGBDImage::has_type1() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void RGBDImage::set_has_type1() { + _has_bits_[0] |= 0x00000010u; +} +inline void RGBDImage::clear_has_type1() { + _has_bits_[0] &= ~0x00000010u; +} +inline void RGBDImage::clear_type1() { + type1_ = 0u; + clear_has_type1(); +} +inline ::google::protobuf::uint32 RGBDImage::type1() const { + return type1_; +} +inline void RGBDImage::set_type1(::google::protobuf::uint32 value) { + set_has_type1(); + type1_ = value; +} + +// required bytes imageData1 = 6; +inline bool RGBDImage::has_imagedata1() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void RGBDImage::set_has_imagedata1() { + _has_bits_[0] |= 0x00000020u; +} +inline void RGBDImage::clear_has_imagedata1() { + _has_bits_[0] &= ~0x00000020u; +} +inline void RGBDImage::clear_imagedata1() { + if (imagedata1_ != &::google::protobuf::internal::kEmptyString) { + imagedata1_->clear(); + } + clear_has_imagedata1(); +} +inline const ::std::string& RGBDImage::imagedata1() const { + return *imagedata1_; +} +inline void RGBDImage::set_imagedata1(const ::std::string& value) { + set_has_imagedata1(); + if (imagedata1_ == &::google::protobuf::internal::kEmptyString) { + imagedata1_ = new ::std::string; + } + imagedata1_->assign(value); +} +inline void RGBDImage::set_imagedata1(const char* value) { + set_has_imagedata1(); + if (imagedata1_ == &::google::protobuf::internal::kEmptyString) { + imagedata1_ = new ::std::string; + } + imagedata1_->assign(value); +} +inline void RGBDImage::set_imagedata1(const void* value, size_t size) { + set_has_imagedata1(); + if (imagedata1_ == &::google::protobuf::internal::kEmptyString) { + imagedata1_ = new ::std::string; + } + imagedata1_->assign(reinterpret_cast(value), size); +} +inline ::std::string* RGBDImage::mutable_imagedata1() { + set_has_imagedata1(); + if (imagedata1_ == &::google::protobuf::internal::kEmptyString) { + imagedata1_ = new ::std::string; + } + return imagedata1_; +} +inline ::std::string* RGBDImage::release_imagedata1() { + clear_has_imagedata1(); + if (imagedata1_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = imagedata1_; + imagedata1_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required uint32 step2 = 7; +inline bool RGBDImage::has_step2() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void RGBDImage::set_has_step2() { + _has_bits_[0] |= 0x00000040u; +} +inline void RGBDImage::clear_has_step2() { + _has_bits_[0] &= ~0x00000040u; +} +inline void RGBDImage::clear_step2() { + step2_ = 0u; + clear_has_step2(); +} +inline ::google::protobuf::uint32 RGBDImage::step2() const { + return step2_; +} +inline void RGBDImage::set_step2(::google::protobuf::uint32 value) { + set_has_step2(); + step2_ = value; +} + +// required uint32 type2 = 8; +inline bool RGBDImage::has_type2() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void RGBDImage::set_has_type2() { + _has_bits_[0] |= 0x00000080u; +} +inline void RGBDImage::clear_has_type2() { + _has_bits_[0] &= ~0x00000080u; +} +inline void RGBDImage::clear_type2() { + type2_ = 0u; + clear_has_type2(); +} +inline ::google::protobuf::uint32 RGBDImage::type2() const { + return type2_; +} +inline void RGBDImage::set_type2(::google::protobuf::uint32 value) { + set_has_type2(); + type2_ = value; +} + +// required bytes imageData2 = 9; +inline bool RGBDImage::has_imagedata2() const { + return (_has_bits_[0] & 0x00000100u) != 0; +} +inline void RGBDImage::set_has_imagedata2() { + _has_bits_[0] |= 0x00000100u; +} +inline void RGBDImage::clear_has_imagedata2() { + _has_bits_[0] &= ~0x00000100u; +} +inline void RGBDImage::clear_imagedata2() { + if (imagedata2_ != &::google::protobuf::internal::kEmptyString) { + imagedata2_->clear(); + } + clear_has_imagedata2(); +} +inline const ::std::string& RGBDImage::imagedata2() const { + return *imagedata2_; +} +inline void RGBDImage::set_imagedata2(const ::std::string& value) { + set_has_imagedata2(); + if (imagedata2_ == &::google::protobuf::internal::kEmptyString) { + imagedata2_ = new ::std::string; + } + imagedata2_->assign(value); +} +inline void RGBDImage::set_imagedata2(const char* value) { + set_has_imagedata2(); + if (imagedata2_ == &::google::protobuf::internal::kEmptyString) { + imagedata2_ = new ::std::string; + } + imagedata2_->assign(value); +} +inline void RGBDImage::set_imagedata2(const void* value, size_t size) { + set_has_imagedata2(); + if (imagedata2_ == &::google::protobuf::internal::kEmptyString) { + imagedata2_ = new ::std::string; + } + imagedata2_->assign(reinterpret_cast(value), size); +} +inline ::std::string* RGBDImage::mutable_imagedata2() { + set_has_imagedata2(); + if (imagedata2_ == &::google::protobuf::internal::kEmptyString) { + imagedata2_ = new ::std::string; + } + return imagedata2_; +} +inline ::std::string* RGBDImage::release_imagedata2() { + clear_has_imagedata2(); + if (imagedata2_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = imagedata2_; + imagedata2_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// optional uint32 camera_config = 10; +inline bool RGBDImage::has_camera_config() const { + return (_has_bits_[0] & 0x00000200u) != 0; +} +inline void RGBDImage::set_has_camera_config() { + _has_bits_[0] |= 0x00000200u; +} +inline void RGBDImage::clear_has_camera_config() { + _has_bits_[0] &= ~0x00000200u; +} +inline void RGBDImage::clear_camera_config() { + camera_config_ = 0u; + clear_has_camera_config(); +} +inline ::google::protobuf::uint32 RGBDImage::camera_config() const { + return camera_config_; +} +inline void RGBDImage::set_camera_config(::google::protobuf::uint32 value) { + set_has_camera_config(); + camera_config_ = value; +} + +// optional uint32 camera_type = 11; +inline bool RGBDImage::has_camera_type() const { + return (_has_bits_[0] & 0x00000400u) != 0; +} +inline void RGBDImage::set_has_camera_type() { + _has_bits_[0] |= 0x00000400u; +} +inline void RGBDImage::clear_has_camera_type() { + _has_bits_[0] &= ~0x00000400u; +} +inline void RGBDImage::clear_camera_type() { + camera_type_ = 0u; + clear_has_camera_type(); +} +inline ::google::protobuf::uint32 RGBDImage::camera_type() const { + return camera_type_; +} +inline void RGBDImage::set_camera_type(::google::protobuf::uint32 value) { + set_has_camera_type(); + camera_type_ = value; +} + +// optional float roll = 12; +inline bool RGBDImage::has_roll() const { + return (_has_bits_[0] & 0x00000800u) != 0; +} +inline void RGBDImage::set_has_roll() { + _has_bits_[0] |= 0x00000800u; +} +inline void RGBDImage::clear_has_roll() { + _has_bits_[0] &= ~0x00000800u; +} +inline void RGBDImage::clear_roll() { + roll_ = 0; + clear_has_roll(); +} +inline float RGBDImage::roll() const { + return roll_; +} +inline void RGBDImage::set_roll(float value) { + set_has_roll(); + roll_ = value; +} + +// optional float pitch = 13; +inline bool RGBDImage::has_pitch() const { + return (_has_bits_[0] & 0x00001000u) != 0; +} +inline void RGBDImage::set_has_pitch() { + _has_bits_[0] |= 0x00001000u; +} +inline void RGBDImage::clear_has_pitch() { + _has_bits_[0] &= ~0x00001000u; +} +inline void RGBDImage::clear_pitch() { + pitch_ = 0; + clear_has_pitch(); +} +inline float RGBDImage::pitch() const { + return pitch_; +} +inline void RGBDImage::set_pitch(float value) { + set_has_pitch(); + pitch_ = value; +} + +// optional float yaw = 14; +inline bool RGBDImage::has_yaw() const { + return (_has_bits_[0] & 0x00002000u) != 0; +} +inline void RGBDImage::set_has_yaw() { + _has_bits_[0] |= 0x00002000u; +} +inline void RGBDImage::clear_has_yaw() { + _has_bits_[0] &= ~0x00002000u; +} +inline void RGBDImage::clear_yaw() { + yaw_ = 0; + clear_has_yaw(); +} +inline float RGBDImage::yaw() const { + return yaw_; +} +inline void RGBDImage::set_yaw(float value) { + set_has_yaw(); + yaw_ = value; +} + +// optional float lon = 15; +inline bool RGBDImage::has_lon() const { + return (_has_bits_[0] & 0x00004000u) != 0; +} +inline void RGBDImage::set_has_lon() { + _has_bits_[0] |= 0x00004000u; +} +inline void RGBDImage::clear_has_lon() { + _has_bits_[0] &= ~0x00004000u; +} +inline void RGBDImage::clear_lon() { + lon_ = 0; + clear_has_lon(); +} +inline float RGBDImage::lon() const { + return lon_; +} +inline void RGBDImage::set_lon(float value) { + set_has_lon(); + lon_ = value; +} + +// optional float lat = 16; +inline bool RGBDImage::has_lat() const { + return (_has_bits_[0] & 0x00008000u) != 0; +} +inline void RGBDImage::set_has_lat() { + _has_bits_[0] |= 0x00008000u; +} +inline void RGBDImage::clear_has_lat() { + _has_bits_[0] &= ~0x00008000u; +} +inline void RGBDImage::clear_lat() { + lat_ = 0; + clear_has_lat(); +} +inline float RGBDImage::lat() const { + return lat_; +} +inline void RGBDImage::set_lat(float value) { + set_has_lat(); + lat_ = value; +} + +// optional float alt = 17; +inline bool RGBDImage::has_alt() const { + return (_has_bits_[0] & 0x00010000u) != 0; +} +inline void RGBDImage::set_has_alt() { + _has_bits_[0] |= 0x00010000u; +} +inline void RGBDImage::clear_has_alt() { + _has_bits_[0] &= ~0x00010000u; +} +inline void RGBDImage::clear_alt() { + alt_ = 0; + clear_has_alt(); +} +inline float RGBDImage::alt() const { + return alt_; +} +inline void RGBDImage::set_alt(float value) { + set_has_alt(); + alt_ = value; +} + +// optional float ground_x = 18; +inline bool RGBDImage::has_ground_x() const { + return (_has_bits_[0] & 0x00020000u) != 0; +} +inline void RGBDImage::set_has_ground_x() { + _has_bits_[0] |= 0x00020000u; +} +inline void RGBDImage::clear_has_ground_x() { + _has_bits_[0] &= ~0x00020000u; +} +inline void RGBDImage::clear_ground_x() { + ground_x_ = 0; + clear_has_ground_x(); +} +inline float RGBDImage::ground_x() const { + return ground_x_; +} +inline void RGBDImage::set_ground_x(float value) { + set_has_ground_x(); + ground_x_ = value; +} + +// optional float ground_y = 19; +inline bool RGBDImage::has_ground_y() const { + return (_has_bits_[0] & 0x00040000u) != 0; +} +inline void RGBDImage::set_has_ground_y() { + _has_bits_[0] |= 0x00040000u; +} +inline void RGBDImage::clear_has_ground_y() { + _has_bits_[0] &= ~0x00040000u; +} +inline void RGBDImage::clear_ground_y() { + ground_y_ = 0; + clear_has_ground_y(); +} +inline float RGBDImage::ground_y() const { + return ground_y_; +} +inline void RGBDImage::set_ground_y(float value) { + set_has_ground_y(); + ground_y_ = value; +} + +// optional float ground_z = 20; +inline bool RGBDImage::has_ground_z() const { + return (_has_bits_[0] & 0x00080000u) != 0; +} +inline void RGBDImage::set_has_ground_z() { + _has_bits_[0] |= 0x00080000u; +} +inline void RGBDImage::clear_has_ground_z() { + _has_bits_[0] &= ~0x00080000u; +} +inline void RGBDImage::clear_ground_z() { + ground_z_ = 0; + clear_has_ground_z(); +} +inline float RGBDImage::ground_z() const { + return ground_z_; +} +inline void RGBDImage::set_ground_z(float value) { + set_has_ground_z(); + ground_z_ = value; +} + +// repeated float camera_matrix = 21; +inline int RGBDImage::camera_matrix_size() const { + return camera_matrix_.size(); +} +inline void RGBDImage::clear_camera_matrix() { + camera_matrix_.Clear(); +} +inline float RGBDImage::camera_matrix(int index) const { + return camera_matrix_.Get(index); +} +inline void RGBDImage::set_camera_matrix(int index, float value) { + camera_matrix_.Set(index, value); +} +inline void RGBDImage::add_camera_matrix(float value) { + camera_matrix_.Add(value); +} +inline const ::google::protobuf::RepeatedField< float >& +RGBDImage::camera_matrix() const { + return camera_matrix_; +} +inline ::google::protobuf::RepeatedField< float >* +RGBDImage::mutable_camera_matrix() { + return &camera_matrix_; +} + +// ------------------------------------------------------------------- + +// Waypoint + +// required double x = 1; +inline bool Waypoint::has_x() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void Waypoint::set_has_x() { + _has_bits_[0] |= 0x00000001u; +} +inline void Waypoint::clear_has_x() { + _has_bits_[0] &= ~0x00000001u; +} +inline void Waypoint::clear_x() { + x_ = 0; + clear_has_x(); +} +inline double Waypoint::x() const { + return x_; +} +inline void Waypoint::set_x(double value) { + set_has_x(); + x_ = value; +} + +// required double y = 2; +inline bool Waypoint::has_y() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void Waypoint::set_has_y() { + _has_bits_[0] |= 0x00000002u; +} +inline void Waypoint::clear_has_y() { + _has_bits_[0] &= ~0x00000002u; +} +inline void Waypoint::clear_y() { + y_ = 0; + clear_has_y(); +} +inline double Waypoint::y() const { + return y_; +} +inline void Waypoint::set_y(double value) { + set_has_y(); + y_ = value; +} + +// optional double z = 3; +inline bool Waypoint::has_z() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void Waypoint::set_has_z() { + _has_bits_[0] |= 0x00000004u; +} +inline void Waypoint::clear_has_z() { + _has_bits_[0] &= ~0x00000004u; +} +inline void Waypoint::clear_z() { + z_ = 0; + clear_has_z(); +} +inline double Waypoint::z() const { + return z_; +} +inline void Waypoint::set_z(double value) { + set_has_z(); + z_ = value; +} + +// optional double roll = 4; +inline bool Waypoint::has_roll() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void Waypoint::set_has_roll() { + _has_bits_[0] |= 0x00000008u; +} +inline void Waypoint::clear_has_roll() { + _has_bits_[0] &= ~0x00000008u; +} +inline void Waypoint::clear_roll() { + roll_ = 0; + clear_has_roll(); +} +inline double Waypoint::roll() const { + return roll_; +} +inline void Waypoint::set_roll(double value) { + set_has_roll(); + roll_ = value; +} + +// optional double pitch = 5; +inline bool Waypoint::has_pitch() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void Waypoint::set_has_pitch() { + _has_bits_[0] |= 0x00000010u; +} +inline void Waypoint::clear_has_pitch() { + _has_bits_[0] &= ~0x00000010u; +} +inline void Waypoint::clear_pitch() { + pitch_ = 0; + clear_has_pitch(); +} +inline double Waypoint::pitch() const { + return pitch_; +} +inline void Waypoint::set_pitch(double value) { + set_has_pitch(); + pitch_ = value; +} + +// optional double yaw = 6; +inline bool Waypoint::has_yaw() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void Waypoint::set_has_yaw() { + _has_bits_[0] |= 0x00000020u; +} +inline void Waypoint::clear_has_yaw() { + _has_bits_[0] &= ~0x00000020u; +} +inline void Waypoint::clear_yaw() { + yaw_ = 0; + clear_has_yaw(); +} +inline double Waypoint::yaw() const { + return yaw_; +} +inline void Waypoint::set_yaw(double value) { + set_has_yaw(); + yaw_ = value; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace px + +#ifndef SWIG +namespace google { +namespace protobuf { + +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::px::GLOverlay_CoordinateFrameType>() { + return ::px::GLOverlay_CoordinateFrameType_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::px::GLOverlay_Mode>() { + return ::px::GLOverlay_Mode_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::px::GLOverlay_Identifier>() { + return ::px::GLOverlay_Identifier_descriptor(); +} + +} // namespace google +} // namespace protobuf +#endif // SWIG + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_pixhawk_2eproto__INCLUDED diff --git a/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/protocol.h b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/protocol.h new file mode 100644 index 0000000000..7b3e3c0bd2 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/protocol.h @@ -0,0 +1,322 @@ +#ifndef _MAVLINK_PROTOCOL_H_ +#define _MAVLINK_PROTOCOL_H_ + +#include "string.h" +#include "mavlink_types.h" + +/* + If you want MAVLink on a system that is native big-endian, + you need to define NATIVE_BIG_ENDIAN +*/ +#ifdef NATIVE_BIG_ENDIAN +# define MAVLINK_NEED_BYTE_SWAP (MAVLINK_ENDIAN == MAVLINK_LITTLE_ENDIAN) +#else +# define MAVLINK_NEED_BYTE_SWAP (MAVLINK_ENDIAN != MAVLINK_LITTLE_ENDIAN) +#endif + +#ifndef MAVLINK_STACK_BUFFER +#define MAVLINK_STACK_BUFFER 0 +#endif + +#ifndef MAVLINK_AVOID_GCC_STACK_BUG +# define MAVLINK_AVOID_GCC_STACK_BUG defined(__GNUC__) +#endif + +#ifndef MAVLINK_ASSERT +#define MAVLINK_ASSERT(x) +#endif + +#ifndef MAVLINK_START_UART_SEND +#define MAVLINK_START_UART_SEND(chan, length) +#endif + +#ifndef MAVLINK_END_UART_SEND +#define MAVLINK_END_UART_SEND(chan, length) +#endif + +#ifdef MAVLINK_SEPARATE_HELPERS +#define MAVLINK_HELPER +#else +#define MAVLINK_HELPER static inline +#include "mavlink_helpers.h" +#endif // MAVLINK_SEPARATE_HELPERS + +/* always include the prototypes to ensure we don't get out of sync */ +MAVLINK_HELPER mavlink_status_t* mavlink_get_channel_status(uint8_t chan); +#if MAVLINK_CRC_EXTRA +MAVLINK_HELPER uint16_t mavlink_finalize_message_chan(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t chan, uint8_t length, uint8_t crc_extra); +MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t length, uint8_t crc_extra); +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS +MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet, + uint8_t length, uint8_t crc_extra); +#endif +#else +MAVLINK_HELPER uint16_t mavlink_finalize_message_chan(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t chan, uint8_t length); +MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, + uint8_t length); +MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet, uint8_t length); +#endif // MAVLINK_CRC_EXTRA +MAVLINK_HELPER uint16_t mavlink_msg_to_send_buffer(uint8_t *buffer, const mavlink_message_t *msg); +MAVLINK_HELPER void mavlink_start_checksum(mavlink_message_t* msg); +MAVLINK_HELPER void mavlink_update_checksum(mavlink_message_t* msg, uint8_t c); +MAVLINK_HELPER uint8_t mavlink_parse_char(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status); +MAVLINK_HELPER uint8_t put_bitfield_n_by_index(int32_t b, uint8_t bits, uint8_t packet_index, uint8_t bit_index, + uint8_t* r_bit_index, uint8_t* buffer); +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS +MAVLINK_HELPER void _mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len); +#endif + +/** + * @brief Get the required buffer size for this message + */ +static inline uint16_t mavlink_msg_get_send_buffer_length(const mavlink_message_t* msg) +{ + return msg->len + MAVLINK_NUM_NON_PAYLOAD_BYTES; +} + +#if MAVLINK_NEED_BYTE_SWAP +static inline void byte_swap_2(char *dst, const char *src) +{ + dst[0] = src[1]; + dst[1] = src[0]; +} +static inline void byte_swap_4(char *dst, const char *src) +{ + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; +} +static inline void byte_swap_8(char *dst, const char *src) +{ + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; +} +#elif !MAVLINK_ALIGNED_FIELDS +static inline void byte_copy_2(char *dst, const char *src) +{ + dst[0] = src[0]; + dst[1] = src[1]; +} +static inline void byte_copy_4(char *dst, const char *src) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} +static inline void byte_copy_8(char *dst, const char *src) +{ + memcpy(dst, src, 8); +} +#endif + +#define _mav_put_uint8_t(buf, wire_offset, b) buf[wire_offset] = (uint8_t)b +#define _mav_put_int8_t(buf, wire_offset, b) buf[wire_offset] = (int8_t)b +#define _mav_put_char(buf, wire_offset, b) buf[wire_offset] = b + +#if MAVLINK_NEED_BYTE_SWAP +#define _mav_put_uint16_t(buf, wire_offset, b) byte_swap_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_int16_t(buf, wire_offset, b) byte_swap_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint32_t(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_int32_t(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint64_t(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_int64_t(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_float(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_double(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b) +#elif !MAVLINK_ALIGNED_FIELDS +#define _mav_put_uint16_t(buf, wire_offset, b) byte_copy_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_int16_t(buf, wire_offset, b) byte_copy_2(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint32_t(buf, wire_offset, b) byte_copy_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_int32_t(buf, wire_offset, b) byte_copy_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_uint64_t(buf, wire_offset, b) byte_copy_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_int64_t(buf, wire_offset, b) byte_copy_8(&buf[wire_offset], (const char *)&b) +#define _mav_put_float(buf, wire_offset, b) byte_copy_4(&buf[wire_offset], (const char *)&b) +#define _mav_put_double(buf, wire_offset, b) byte_copy_8(&buf[wire_offset], (const char *)&b) +#else +#define _mav_put_uint16_t(buf, wire_offset, b) *(uint16_t *)&buf[wire_offset] = b +#define _mav_put_int16_t(buf, wire_offset, b) *(int16_t *)&buf[wire_offset] = b +#define _mav_put_uint32_t(buf, wire_offset, b) *(uint32_t *)&buf[wire_offset] = b +#define _mav_put_int32_t(buf, wire_offset, b) *(int32_t *)&buf[wire_offset] = b +#define _mav_put_uint64_t(buf, wire_offset, b) *(uint64_t *)&buf[wire_offset] = b +#define _mav_put_int64_t(buf, wire_offset, b) *(int64_t *)&buf[wire_offset] = b +#define _mav_put_float(buf, wire_offset, b) *(float *)&buf[wire_offset] = b +#define _mav_put_double(buf, wire_offset, b) *(double *)&buf[wire_offset] = b +#endif + +/* + like memcpy(), but if src is NULL, do a memset to zero +*/ +static void mav_array_memcpy(void *dest, const void *src, size_t n) +{ + if (src == NULL) { + memset(dest, 0, n); + } else { + memcpy(dest, src, n); + } +} + +/* + * Place a char array into a buffer + */ +static inline void _mav_put_char_array(char *buf, uint8_t wire_offset, const char *b, uint8_t array_length) +{ + mav_array_memcpy(&buf[wire_offset], b, array_length); + +} + +/* + * Place a uint8_t array into a buffer + */ +static inline void _mav_put_uint8_t_array(char *buf, uint8_t wire_offset, const uint8_t *b, uint8_t array_length) +{ + mav_array_memcpy(&buf[wire_offset], b, array_length); + +} + +/* + * Place a int8_t array into a buffer + */ +static inline void _mav_put_int8_t_array(char *buf, uint8_t wire_offset, const int8_t *b, uint8_t array_length) +{ + mav_array_memcpy(&buf[wire_offset], b, array_length); + +} + +#if MAVLINK_NEED_BYTE_SWAP +#define _MAV_PUT_ARRAY(TYPE, V) \ +static inline void _mav_put_ ## TYPE ##_array(char *buf, uint8_t wire_offset, const TYPE *b, uint8_t array_length) \ +{ \ + if (b == NULL) { \ + memset(&buf[wire_offset], 0, array_length*sizeof(TYPE)); \ + } else { \ + uint16_t i; \ + for (i=0; imsgid = MAVLINK_MSG_ID_TEST_TYPES; + return mavlink_finalize_message(msg, system_id, component_id, 179, 103); +} + +/** + * @brief Pack a test_types message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param c char + * @param s string + * @param u8 uint8_t + * @param u16 uint16_t + * @param u32 uint32_t + * @param u64 uint64_t + * @param s8 int8_t + * @param s16 int16_t + * @param s32 int32_t + * @param s64 int64_t + * @param f float + * @param d double + * @param u8_array uint8_t_array + * @param u16_array uint16_t_array + * @param u32_array uint32_t_array + * @param u64_array uint64_t_array + * @param s8_array int8_t_array + * @param s16_array int16_t_array + * @param s32_array int32_t_array + * @param s64_array int64_t_array + * @param f_array float_array + * @param d_array double_array + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_test_types_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + char c,const char *s,uint8_t u8,uint16_t u16,uint32_t u32,uint64_t u64,int8_t s8,int16_t s16,int32_t s32,int64_t s64,float f,double d,const uint8_t *u8_array,const uint16_t *u16_array,const uint32_t *u32_array,const uint64_t *u64_array,const int8_t *s8_array,const int16_t *s16_array,const int32_t *s32_array,const int64_t *s64_array,const float *f_array,const double *d_array) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[179]; + _mav_put_uint64_t(buf, 0, u64); + _mav_put_int64_t(buf, 8, s64); + _mav_put_double(buf, 16, d); + _mav_put_uint32_t(buf, 96, u32); + _mav_put_int32_t(buf, 100, s32); + _mav_put_float(buf, 104, f); + _mav_put_uint16_t(buf, 144, u16); + _mav_put_int16_t(buf, 146, s16); + _mav_put_char(buf, 160, c); + _mav_put_uint8_t(buf, 171, u8); + _mav_put_int8_t(buf, 172, s8); + _mav_put_uint64_t_array(buf, 24, u64_array, 3); + _mav_put_int64_t_array(buf, 48, s64_array, 3); + _mav_put_double_array(buf, 72, d_array, 3); + _mav_put_uint32_t_array(buf, 108, u32_array, 3); + _mav_put_int32_t_array(buf, 120, s32_array, 3); + _mav_put_float_array(buf, 132, f_array, 3); + _mav_put_uint16_t_array(buf, 148, u16_array, 3); + _mav_put_int16_t_array(buf, 154, s16_array, 3); + _mav_put_char_array(buf, 161, s, 10); + _mav_put_uint8_t_array(buf, 173, u8_array, 3); + _mav_put_int8_t_array(buf, 176, s8_array, 3); + memcpy(_MAV_PAYLOAD(msg), buf, 179); +#else + mavlink_test_types_t packet; + packet.u64 = u64; + packet.s64 = s64; + packet.d = d; + packet.u32 = u32; + packet.s32 = s32; + packet.f = f; + packet.u16 = u16; + packet.s16 = s16; + packet.c = c; + packet.u8 = u8; + packet.s8 = s8; + mav_array_memcpy(packet.u64_array, u64_array, sizeof(uint64_t)*3); + mav_array_memcpy(packet.s64_array, s64_array, sizeof(int64_t)*3); + mav_array_memcpy(packet.d_array, d_array, sizeof(double)*3); + mav_array_memcpy(packet.u32_array, u32_array, sizeof(uint32_t)*3); + mav_array_memcpy(packet.s32_array, s32_array, sizeof(int32_t)*3); + mav_array_memcpy(packet.f_array, f_array, sizeof(float)*3); + mav_array_memcpy(packet.u16_array, u16_array, sizeof(uint16_t)*3); + mav_array_memcpy(packet.s16_array, s16_array, sizeof(int16_t)*3); + mav_array_memcpy(packet.s, s, sizeof(char)*10); + mav_array_memcpy(packet.u8_array, u8_array, sizeof(uint8_t)*3); + mav_array_memcpy(packet.s8_array, s8_array, sizeof(int8_t)*3); + memcpy(_MAV_PAYLOAD(msg), &packet, 179); +#endif + + msg->msgid = MAVLINK_MSG_ID_TEST_TYPES; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 179, 103); +} + +/** + * @brief Encode a test_types struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param test_types C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_test_types_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_test_types_t* test_types) +{ + return mavlink_msg_test_types_pack(system_id, component_id, msg, test_types->c, test_types->s, test_types->u8, test_types->u16, test_types->u32, test_types->u64, test_types->s8, test_types->s16, test_types->s32, test_types->s64, test_types->f, test_types->d, test_types->u8_array, test_types->u16_array, test_types->u32_array, test_types->u64_array, test_types->s8_array, test_types->s16_array, test_types->s32_array, test_types->s64_array, test_types->f_array, test_types->d_array); +} + +/** + * @brief Send a test_types message + * @param chan MAVLink channel to send the message + * + * @param c char + * @param s string + * @param u8 uint8_t + * @param u16 uint16_t + * @param u32 uint32_t + * @param u64 uint64_t + * @param s8 int8_t + * @param s16 int16_t + * @param s32 int32_t + * @param s64 int64_t + * @param f float + * @param d double + * @param u8_array uint8_t_array + * @param u16_array uint16_t_array + * @param u32_array uint32_t_array + * @param u64_array uint64_t_array + * @param s8_array int8_t_array + * @param s16_array int16_t_array + * @param s32_array int32_t_array + * @param s64_array int64_t_array + * @param f_array float_array + * @param d_array double_array + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_test_types_send(mavlink_channel_t chan, char c, const char *s, uint8_t u8, uint16_t u16, uint32_t u32, uint64_t u64, int8_t s8, int16_t s16, int32_t s32, int64_t s64, float f, double d, const uint8_t *u8_array, const uint16_t *u16_array, const uint32_t *u32_array, const uint64_t *u64_array, const int8_t *s8_array, const int16_t *s16_array, const int32_t *s32_array, const int64_t *s64_array, const float *f_array, const double *d_array) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[179]; + _mav_put_uint64_t(buf, 0, u64); + _mav_put_int64_t(buf, 8, s64); + _mav_put_double(buf, 16, d); + _mav_put_uint32_t(buf, 96, u32); + _mav_put_int32_t(buf, 100, s32); + _mav_put_float(buf, 104, f); + _mav_put_uint16_t(buf, 144, u16); + _mav_put_int16_t(buf, 146, s16); + _mav_put_char(buf, 160, c); + _mav_put_uint8_t(buf, 171, u8); + _mav_put_int8_t(buf, 172, s8); + _mav_put_uint64_t_array(buf, 24, u64_array, 3); + _mav_put_int64_t_array(buf, 48, s64_array, 3); + _mav_put_double_array(buf, 72, d_array, 3); + _mav_put_uint32_t_array(buf, 108, u32_array, 3); + _mav_put_int32_t_array(buf, 120, s32_array, 3); + _mav_put_float_array(buf, 132, f_array, 3); + _mav_put_uint16_t_array(buf, 148, u16_array, 3); + _mav_put_int16_t_array(buf, 154, s16_array, 3); + _mav_put_char_array(buf, 161, s, 10); + _mav_put_uint8_t_array(buf, 173, u8_array, 3); + _mav_put_int8_t_array(buf, 176, s8_array, 3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_TEST_TYPES, buf, 179, 103); +#else + mavlink_test_types_t packet; + packet.u64 = u64; + packet.s64 = s64; + packet.d = d; + packet.u32 = u32; + packet.s32 = s32; + packet.f = f; + packet.u16 = u16; + packet.s16 = s16; + packet.c = c; + packet.u8 = u8; + packet.s8 = s8; + mav_array_memcpy(packet.u64_array, u64_array, sizeof(uint64_t)*3); + mav_array_memcpy(packet.s64_array, s64_array, sizeof(int64_t)*3); + mav_array_memcpy(packet.d_array, d_array, sizeof(double)*3); + mav_array_memcpy(packet.u32_array, u32_array, sizeof(uint32_t)*3); + mav_array_memcpy(packet.s32_array, s32_array, sizeof(int32_t)*3); + mav_array_memcpy(packet.f_array, f_array, sizeof(float)*3); + mav_array_memcpy(packet.u16_array, u16_array, sizeof(uint16_t)*3); + mav_array_memcpy(packet.s16_array, s16_array, sizeof(int16_t)*3); + mav_array_memcpy(packet.s, s, sizeof(char)*10); + mav_array_memcpy(packet.u8_array, u8_array, sizeof(uint8_t)*3); + mav_array_memcpy(packet.s8_array, s8_array, sizeof(int8_t)*3); + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_TEST_TYPES, (const char *)&packet, 179, 103); +#endif +} + +#endif + +// MESSAGE TEST_TYPES UNPACKING + + +/** + * @brief Get field c from test_types message + * + * @return char + */ +static inline char mavlink_msg_test_types_get_c(const mavlink_message_t* msg) +{ + return _MAV_RETURN_char(msg, 160); +} + +/** + * @brief Get field s from test_types message + * + * @return string + */ +static inline uint16_t mavlink_msg_test_types_get_s(const mavlink_message_t* msg, char *s) +{ + return _MAV_RETURN_char_array(msg, s, 10, 161); +} + +/** + * @brief Get field u8 from test_types message + * + * @return uint8_t + */ +static inline uint8_t mavlink_msg_test_types_get_u8(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 171); +} + +/** + * @brief Get field u16 from test_types message + * + * @return uint16_t + */ +static inline uint16_t mavlink_msg_test_types_get_u16(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 144); +} + +/** + * @brief Get field u32 from test_types message + * + * @return uint32_t + */ +static inline uint32_t mavlink_msg_test_types_get_u32(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint32_t(msg, 96); +} + +/** + * @brief Get field u64 from test_types message + * + * @return uint64_t + */ +static inline uint64_t mavlink_msg_test_types_get_u64(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint64_t(msg, 0); +} + +/** + * @brief Get field s8 from test_types message + * + * @return int8_t + */ +static inline int8_t mavlink_msg_test_types_get_s8(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int8_t(msg, 172); +} + +/** + * @brief Get field s16 from test_types message + * + * @return int16_t + */ +static inline int16_t mavlink_msg_test_types_get_s16(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int16_t(msg, 146); +} + +/** + * @brief Get field s32 from test_types message + * + * @return int32_t + */ +static inline int32_t mavlink_msg_test_types_get_s32(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int32_t(msg, 100); +} + +/** + * @brief Get field s64 from test_types message + * + * @return int64_t + */ +static inline int64_t mavlink_msg_test_types_get_s64(const mavlink_message_t* msg) +{ + return _MAV_RETURN_int64_t(msg, 8); +} + +/** + * @brief Get field f from test_types message + * + * @return float + */ +static inline float mavlink_msg_test_types_get_f(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 104); +} + +/** + * @brief Get field d from test_types message + * + * @return double + */ +static inline double mavlink_msg_test_types_get_d(const mavlink_message_t* msg) +{ + return _MAV_RETURN_double(msg, 16); +} + +/** + * @brief Get field u8_array from test_types message + * + * @return uint8_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u8_array(const mavlink_message_t* msg, uint8_t *u8_array) +{ + return _MAV_RETURN_uint8_t_array(msg, u8_array, 3, 173); +} + +/** + * @brief Get field u16_array from test_types message + * + * @return uint16_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u16_array(const mavlink_message_t* msg, uint16_t *u16_array) +{ + return _MAV_RETURN_uint16_t_array(msg, u16_array, 3, 148); +} + +/** + * @brief Get field u32_array from test_types message + * + * @return uint32_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u32_array(const mavlink_message_t* msg, uint32_t *u32_array) +{ + return _MAV_RETURN_uint32_t_array(msg, u32_array, 3, 108); +} + +/** + * @brief Get field u64_array from test_types message + * + * @return uint64_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_u64_array(const mavlink_message_t* msg, uint64_t *u64_array) +{ + return _MAV_RETURN_uint64_t_array(msg, u64_array, 3, 24); +} + +/** + * @brief Get field s8_array from test_types message + * + * @return int8_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s8_array(const mavlink_message_t* msg, int8_t *s8_array) +{ + return _MAV_RETURN_int8_t_array(msg, s8_array, 3, 176); +} + +/** + * @brief Get field s16_array from test_types message + * + * @return int16_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s16_array(const mavlink_message_t* msg, int16_t *s16_array) +{ + return _MAV_RETURN_int16_t_array(msg, s16_array, 3, 154); +} + +/** + * @brief Get field s32_array from test_types message + * + * @return int32_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s32_array(const mavlink_message_t* msg, int32_t *s32_array) +{ + return _MAV_RETURN_int32_t_array(msg, s32_array, 3, 120); +} + +/** + * @brief Get field s64_array from test_types message + * + * @return int64_t_array + */ +static inline uint16_t mavlink_msg_test_types_get_s64_array(const mavlink_message_t* msg, int64_t *s64_array) +{ + return _MAV_RETURN_int64_t_array(msg, s64_array, 3, 48); +} + +/** + * @brief Get field f_array from test_types message + * + * @return float_array + */ +static inline uint16_t mavlink_msg_test_types_get_f_array(const mavlink_message_t* msg, float *f_array) +{ + return _MAV_RETURN_float_array(msg, f_array, 3, 132); +} + +/** + * @brief Get field d_array from test_types message + * + * @return double_array + */ +static inline uint16_t mavlink_msg_test_types_get_d_array(const mavlink_message_t* msg, double *d_array) +{ + return _MAV_RETURN_double_array(msg, d_array, 3, 72); +} + +/** + * @brief Decode a test_types message into a struct + * + * @param msg The message to decode + * @param test_types C-struct to decode the message contents into + */ +static inline void mavlink_msg_test_types_decode(const mavlink_message_t* msg, mavlink_test_types_t* test_types) +{ +#if MAVLINK_NEED_BYTE_SWAP + test_types->u64 = mavlink_msg_test_types_get_u64(msg); + test_types->s64 = mavlink_msg_test_types_get_s64(msg); + test_types->d = mavlink_msg_test_types_get_d(msg); + mavlink_msg_test_types_get_u64_array(msg, test_types->u64_array); + mavlink_msg_test_types_get_s64_array(msg, test_types->s64_array); + mavlink_msg_test_types_get_d_array(msg, test_types->d_array); + test_types->u32 = mavlink_msg_test_types_get_u32(msg); + test_types->s32 = mavlink_msg_test_types_get_s32(msg); + test_types->f = mavlink_msg_test_types_get_f(msg); + mavlink_msg_test_types_get_u32_array(msg, test_types->u32_array); + mavlink_msg_test_types_get_s32_array(msg, test_types->s32_array); + mavlink_msg_test_types_get_f_array(msg, test_types->f_array); + test_types->u16 = mavlink_msg_test_types_get_u16(msg); + test_types->s16 = mavlink_msg_test_types_get_s16(msg); + mavlink_msg_test_types_get_u16_array(msg, test_types->u16_array); + mavlink_msg_test_types_get_s16_array(msg, test_types->s16_array); + test_types->c = mavlink_msg_test_types_get_c(msg); + mavlink_msg_test_types_get_s(msg, test_types->s); + test_types->u8 = mavlink_msg_test_types_get_u8(msg); + test_types->s8 = mavlink_msg_test_types_get_s8(msg); + mavlink_msg_test_types_get_u8_array(msg, test_types->u8_array); + mavlink_msg_test_types_get_s8_array(msg, test_types->s8_array); +#else + memcpy(test_types, _MAV_PAYLOAD(msg), 179); +#endif +} diff --git a/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/test/test.h b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/test/test.h new file mode 100644 index 0000000000..4dc04f889f --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/test/test.h @@ -0,0 +1,53 @@ +/** @file + * @brief MAVLink comm protocol generated from test.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef TEST_H +#define TEST_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_TEST_TYPES, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_TEST + + + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION 3 +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION 3 +#endif + +// ENUM DEFINITIONS + + + +// MESSAGE DEFINITIONS +#include "./mavlink_msg_test_types.h" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // TEST_H diff --git a/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/test/testsuite.h b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/test/testsuite.h new file mode 100644 index 0000000000..658e1ae071 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/include_v1.0/test/testsuite.h @@ -0,0 +1,120 @@ +/** @file + * @brief MAVLink comm protocol testsuite generated from test.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef TEST_TESTSUITE_H +#define TEST_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL + +static void mavlink_test_test(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + + mavlink_test_test(system_id, component_id, last_msg); +} +#endif + + + + +static void mavlink_test_test_types(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_test_types_t packet_in = { + 93372036854775807ULL, + 93372036854776311LL, + 235.0, + { 93372036854777319, 93372036854777320, 93372036854777321 }, + { 93372036854778831, 93372036854778832, 93372036854778833 }, + { 627.0, 628.0, 629.0 }, + 963502456, + 963502664, + 745.0, + { 963503080, 963503081, 963503082 }, + { 963503704, 963503705, 963503706 }, + { 941.0, 942.0, 943.0 }, + 24723, + 24827, + { 24931, 24932, 24933 }, + { 25243, 25244, 25245 }, + 'E', + "FGHIJKLMN", + 198, + 9, + { 76, 77, 78 }, + { 21, 22, 23 }, + }; + mavlink_test_types_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.u64 = packet_in.u64; + packet1.s64 = packet_in.s64; + packet1.d = packet_in.d; + packet1.u32 = packet_in.u32; + packet1.s32 = packet_in.s32; + packet1.f = packet_in.f; + packet1.u16 = packet_in.u16; + packet1.s16 = packet_in.s16; + packet1.c = packet_in.c; + packet1.u8 = packet_in.u8; + packet1.s8 = packet_in.s8; + + mav_array_memcpy(packet1.u64_array, packet_in.u64_array, sizeof(uint64_t)*3); + mav_array_memcpy(packet1.s64_array, packet_in.s64_array, sizeof(int64_t)*3); + mav_array_memcpy(packet1.d_array, packet_in.d_array, sizeof(double)*3); + mav_array_memcpy(packet1.u32_array, packet_in.u32_array, sizeof(uint32_t)*3); + mav_array_memcpy(packet1.s32_array, packet_in.s32_array, sizeof(int32_t)*3); + mav_array_memcpy(packet1.f_array, packet_in.f_array, sizeof(float)*3); + mav_array_memcpy(packet1.u16_array, packet_in.u16_array, sizeof(uint16_t)*3); + mav_array_memcpy(packet1.s16_array, packet_in.s16_array, sizeof(int16_t)*3); + mav_array_memcpy(packet1.s, packet_in.s, sizeof(char)*10); + mav_array_memcpy(packet1.u8_array, packet_in.u8_array, sizeof(uint8_t)*3); + mav_array_memcpy(packet1.s8_array, packet_in.s8_array, sizeof(int8_t)*3); + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_test_types_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_test_types_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_test_types_pack(system_id, component_id, &msg , packet1.c , packet1.s , packet1.u8 , packet1.u16 , packet1.u32 , packet1.u64 , packet1.s8 , packet1.s16 , packet1.s32 , packet1.s64 , packet1.f , packet1.d , packet1.u8_array , packet1.u16_array , packet1.u32_array , packet1.u64_array , packet1.s8_array , packet1.s16_array , packet1.s32_array , packet1.s64_array , packet1.f_array , packet1.d_array ); + mavlink_msg_test_types_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_test_types_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.c , packet1.s , packet1.u8 , packet1.u16 , packet1.u32 , packet1.u64 , packet1.s8 , packet1.s16 , packet1.s32 , packet1.s64 , packet1.f , packet1.d , packet1.u8_array , packet1.u16_array , packet1.u32_array , packet1.u64_array , packet1.s8_array , packet1.s16_array , packet1.s32_array , packet1.s64_array , packet1.f_array , packet1.d_array ); + mavlink_msg_test_types_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; i + +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace px { + +namespace { + +const ::google::protobuf::Descriptor* HeaderInfo_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + HeaderInfo_reflection_ = NULL; +const ::google::protobuf::Descriptor* GLOverlay_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + GLOverlay_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* GLOverlay_CoordinateFrameType_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* GLOverlay_Mode_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* GLOverlay_Identifier_descriptor_ = NULL; +const ::google::protobuf::Descriptor* Obstacle_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + Obstacle_reflection_ = NULL; +const ::google::protobuf::Descriptor* ObstacleList_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ObstacleList_reflection_ = NULL; +const ::google::protobuf::Descriptor* ObstacleMap_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ObstacleMap_reflection_ = NULL; +const ::google::protobuf::Descriptor* Path_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + Path_reflection_ = NULL; +const ::google::protobuf::Descriptor* PointCloudXYZI_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + PointCloudXYZI_reflection_ = NULL; +const ::google::protobuf::Descriptor* PointCloudXYZI_PointXYZI_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + PointCloudXYZI_PointXYZI_reflection_ = NULL; +const ::google::protobuf::Descriptor* PointCloudXYZRGB_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + PointCloudXYZRGB_reflection_ = NULL; +const ::google::protobuf::Descriptor* PointCloudXYZRGB_PointXYZRGB_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + PointCloudXYZRGB_PointXYZRGB_reflection_ = NULL; +const ::google::protobuf::Descriptor* RGBDImage_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RGBDImage_reflection_ = NULL; +const ::google::protobuf::Descriptor* Waypoint_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + Waypoint_reflection_ = NULL; + +} // namespace + + +void protobuf_AssignDesc_pixhawk_2eproto() { + protobuf_AddDesc_pixhawk_2eproto(); + const ::google::protobuf::FileDescriptor* file = + ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( + "pixhawk.proto"); + GOOGLE_CHECK(file != NULL); + HeaderInfo_descriptor_ = file->message_type(0); + static const int HeaderInfo_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HeaderInfo, source_sysid_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HeaderInfo, source_compid_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HeaderInfo, timestamp_), + }; + HeaderInfo_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + HeaderInfo_descriptor_, + HeaderInfo::default_instance_, + HeaderInfo_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HeaderInfo, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HeaderInfo, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(HeaderInfo)); + GLOverlay_descriptor_ = file->message_type(1); + static const int GLOverlay_offsets_[7] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, coordinateframetype_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, origin_x_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, origin_y_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, origin_z_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, data_), + }; + GLOverlay_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + GLOverlay_descriptor_, + GLOverlay::default_instance_, + GLOverlay_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GLOverlay, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(GLOverlay)); + GLOverlay_CoordinateFrameType_descriptor_ = GLOverlay_descriptor_->enum_type(0); + GLOverlay_Mode_descriptor_ = GLOverlay_descriptor_->enum_type(1); + GLOverlay_Identifier_descriptor_ = GLOverlay_descriptor_->enum_type(2); + Obstacle_descriptor_ = file->message_type(2); + static const int Obstacle_offsets_[6] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, x_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, y_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, z_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, length_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, width_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, height_), + }; + Obstacle_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + Obstacle_descriptor_, + Obstacle::default_instance_, + Obstacle_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Obstacle, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(Obstacle)); + ObstacleList_descriptor_ = file->message_type(3); + static const int ObstacleList_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleList, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleList, obstacles_), + }; + ObstacleList_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ObstacleList_descriptor_, + ObstacleList::default_instance_, + ObstacleList_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleList, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleList, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ObstacleList)); + ObstacleMap_descriptor_ = file->message_type(4); + static const int ObstacleMap_offsets_[10] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, type_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, resolution_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, rows_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, cols_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, mapr0_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, mapc0_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, arrayr0_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, arrayc0_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, data_), + }; + ObstacleMap_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ObstacleMap_descriptor_, + ObstacleMap::default_instance_, + ObstacleMap_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ObstacleMap, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ObstacleMap)); + Path_descriptor_ = file->message_type(5); + static const int Path_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Path, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Path, waypoints_), + }; + Path_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + Path_descriptor_, + Path::default_instance_, + Path_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Path, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Path, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(Path)); + PointCloudXYZI_descriptor_ = file->message_type(6); + static const int PointCloudXYZI_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI, points_), + }; + PointCloudXYZI_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + PointCloudXYZI_descriptor_, + PointCloudXYZI::default_instance_, + PointCloudXYZI_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(PointCloudXYZI)); + PointCloudXYZI_PointXYZI_descriptor_ = PointCloudXYZI_descriptor_->nested_type(0); + static const int PointCloudXYZI_PointXYZI_offsets_[4] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI_PointXYZI, x_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI_PointXYZI, y_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI_PointXYZI, z_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI_PointXYZI, intensity_), + }; + PointCloudXYZI_PointXYZI_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + PointCloudXYZI_PointXYZI_descriptor_, + PointCloudXYZI_PointXYZI::default_instance_, + PointCloudXYZI_PointXYZI_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI_PointXYZI, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZI_PointXYZI, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(PointCloudXYZI_PointXYZI)); + PointCloudXYZRGB_descriptor_ = file->message_type(7); + static const int PointCloudXYZRGB_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB, points_), + }; + PointCloudXYZRGB_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + PointCloudXYZRGB_descriptor_, + PointCloudXYZRGB::default_instance_, + PointCloudXYZRGB_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(PointCloudXYZRGB)); + PointCloudXYZRGB_PointXYZRGB_descriptor_ = PointCloudXYZRGB_descriptor_->nested_type(0); + static const int PointCloudXYZRGB_PointXYZRGB_offsets_[4] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB_PointXYZRGB, x_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB_PointXYZRGB, y_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB_PointXYZRGB, z_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB_PointXYZRGB, rgb_), + }; + PointCloudXYZRGB_PointXYZRGB_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + PointCloudXYZRGB_PointXYZRGB_descriptor_, + PointCloudXYZRGB_PointXYZRGB::default_instance_, + PointCloudXYZRGB_PointXYZRGB_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB_PointXYZRGB, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(PointCloudXYZRGB_PointXYZRGB, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(PointCloudXYZRGB_PointXYZRGB)); + RGBDImage_descriptor_ = file->message_type(8); + static const int RGBDImage_offsets_[21] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, header_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, cols_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, rows_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, step1_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, type1_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, imagedata1_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, step2_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, type2_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, imagedata2_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, camera_config_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, camera_type_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, roll_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, pitch_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, yaw_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, lon_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, lat_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, alt_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, ground_x_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, ground_y_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, ground_z_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, camera_matrix_), + }; + RGBDImage_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RGBDImage_descriptor_, + RGBDImage::default_instance_, + RGBDImage_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RGBDImage, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RGBDImage)); + Waypoint_descriptor_ = file->message_type(9); + static const int Waypoint_offsets_[6] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, x_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, y_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, z_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, roll_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, pitch_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, yaw_), + }; + Waypoint_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + Waypoint_descriptor_, + Waypoint::default_instance_, + Waypoint_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Waypoint, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(Waypoint)); +} + +namespace { + +GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); +inline void protobuf_AssignDescriptorsOnce() { + ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, + &protobuf_AssignDesc_pixhawk_2eproto); +} + +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + HeaderInfo_descriptor_, &HeaderInfo::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + GLOverlay_descriptor_, &GLOverlay::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + Obstacle_descriptor_, &Obstacle::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ObstacleList_descriptor_, &ObstacleList::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ObstacleMap_descriptor_, &ObstacleMap::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + Path_descriptor_, &Path::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + PointCloudXYZI_descriptor_, &PointCloudXYZI::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + PointCloudXYZI_PointXYZI_descriptor_, &PointCloudXYZI_PointXYZI::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + PointCloudXYZRGB_descriptor_, &PointCloudXYZRGB::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + PointCloudXYZRGB_PointXYZRGB_descriptor_, &PointCloudXYZRGB_PointXYZRGB::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RGBDImage_descriptor_, &RGBDImage::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + Waypoint_descriptor_, &Waypoint::default_instance()); +} + +} // namespace + +void protobuf_ShutdownFile_pixhawk_2eproto() { + delete HeaderInfo::default_instance_; + delete HeaderInfo_reflection_; + delete GLOverlay::default_instance_; + delete GLOverlay_reflection_; + delete Obstacle::default_instance_; + delete Obstacle_reflection_; + delete ObstacleList::default_instance_; + delete ObstacleList_reflection_; + delete ObstacleMap::default_instance_; + delete ObstacleMap_reflection_; + delete Path::default_instance_; + delete Path_reflection_; + delete PointCloudXYZI::default_instance_; + delete PointCloudXYZI_reflection_; + delete PointCloudXYZI_PointXYZI::default_instance_; + delete PointCloudXYZI_PointXYZI_reflection_; + delete PointCloudXYZRGB::default_instance_; + delete PointCloudXYZRGB_reflection_; + delete PointCloudXYZRGB_PointXYZRGB::default_instance_; + delete PointCloudXYZRGB_PointXYZRGB_reflection_; + delete RGBDImage::default_instance_; + delete RGBDImage_reflection_; + delete Waypoint::default_instance_; + delete Waypoint_reflection_; +} + +void protobuf_AddDesc_pixhawk_2eproto() { + static bool already_here = false; + if (already_here) return; + already_here = true; + GOOGLE_PROTOBUF_VERIFY_VERSION; + + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + "\n\rpixhawk.proto\022\002px\"L\n\nHeaderInfo\022\024\n\014sou" + "rce_sysid\030\001 \002(\005\022\025\n\rsource_compid\030\002 \002(\005\022\021" + "\n\ttimestamp\030\003 \002(\001\"\377\004\n\tGLOverlay\022\036\n\006heade" + "r\030\001 \002(\0132\016.px.HeaderInfo\022\014\n\004name\030\002 \001(\t\022>\n" + "\023coordinateFrameType\030\003 \001(\0162!.px.GLOverla" + "y.CoordinateFrameType\022\020\n\010origin_x\030\004 \001(\001\022" + "\020\n\010origin_y\030\005 \001(\001\022\020\n\010origin_z\030\006 \001(\001\022\014\n\004d" + "ata\030\007 \001(\014\",\n\023CoordinateFrameType\022\n\n\006GLOB" + "AL\020\000\022\t\n\005LOCAL\020\001\"\333\001\n\004Mode\022\n\n\006POINTS\020\000\022\t\n\005" + "LINES\020\001\022\016\n\nLINE_STRIP\020\002\022\r\n\tLINE_LOOP\020\003\022\r" + "\n\tTRIANGLES\020\004\022\022\n\016TRIANGLE_STRIP\020\005\022\020\n\014TRI" + "ANGLE_FAN\020\006\022\t\n\005QUADS\020\007\022\016\n\nQUAD_STRIP\020\010\022\013" + "\n\007POLYGON\020\t\022\020\n\014SOLID_CIRCLE\020\n\022\017\n\013WIRE_CI" + "RCLE\020\013\022\016\n\nSOLID_CUBE\020\014\022\r\n\tWIRE_CUBE\020\r\"\263\001" + "\n\nIdentifier\022\007\n\003END\020\016\022\014\n\010VERTEX2F\020\017\022\014\n\010V" + "ERTEX3F\020\020\022\013\n\007ROTATEF\020\021\022\016\n\nTRANSLATEF\020\022\022\n" + "\n\006SCALEF\020\023\022\017\n\013PUSH_MATRIX\020\024\022\016\n\nPOP_MATRI" + "X\020\025\022\013\n\007COLOR3F\020\026\022\013\n\007COLOR4F\020\027\022\r\n\tPOINTSI" + "ZE\020\030\022\r\n\tLINEWIDTH\020\031\"Z\n\010Obstacle\022\t\n\001x\030\001 \001" + "(\002\022\t\n\001y\030\002 \001(\002\022\t\n\001z\030\003 \001(\002\022\016\n\006length\030\004 \001(\002" + "\022\r\n\005width\030\005 \001(\002\022\016\n\006height\030\006 \001(\002\"O\n\014Obsta" + "cleList\022\036\n\006header\030\001 \002(\0132\016.px.HeaderInfo\022" + "\037\n\tobstacles\030\002 \003(\0132\014.px.Obstacle\"\271\001\n\013Obs" + "tacleMap\022\036\n\006header\030\001 \002(\0132\016.px.HeaderInfo" + "\022\014\n\004type\030\002 \002(\005\022\022\n\nresolution\030\003 \001(\002\022\014\n\004ro" + "ws\030\004 \001(\005\022\014\n\004cols\030\005 \001(\005\022\r\n\005mapR0\030\006 \001(\005\022\r\n" + "\005mapC0\030\007 \001(\005\022\017\n\007arrayR0\030\010 \001(\005\022\017\n\007arrayC0" + "\030\t \001(\005\022\014\n\004data\030\n \001(\014\"G\n\004Path\022\036\n\006header\030\001" + " \002(\0132\016.px.HeaderInfo\022\037\n\twaypoints\030\002 \003(\0132" + "\014.px.Waypoint\"\237\001\n\016PointCloudXYZI\022\036\n\006head" + "er\030\001 \002(\0132\016.px.HeaderInfo\022,\n\006points\030\002 \003(\013" + "2\034.px.PointCloudXYZI.PointXYZI\032\?\n\tPointX" + "YZI\022\t\n\001x\030\001 \002(\002\022\t\n\001y\030\002 \002(\002\022\t\n\001z\030\003 \002(\002\022\021\n\t" + "intensity\030\004 \002(\002\"\241\001\n\020PointCloudXYZRGB\022\036\n\006" + "header\030\001 \002(\0132\016.px.HeaderInfo\0220\n\006points\030\002" + " \003(\0132 .px.PointCloudXYZRGB.PointXYZRGB\032;" + "\n\013PointXYZRGB\022\t\n\001x\030\001 \002(\002\022\t\n\001y\030\002 \002(\002\022\t\n\001z" + "\030\003 \002(\002\022\013\n\003rgb\030\004 \002(\002\"\365\002\n\tRGBDImage\022\036\n\006hea" + "der\030\001 \002(\0132\016.px.HeaderInfo\022\014\n\004cols\030\002 \002(\r\022" + "\014\n\004rows\030\003 \002(\r\022\r\n\005step1\030\004 \002(\r\022\r\n\005type1\030\005 " + "\002(\r\022\022\n\nimageData1\030\006 \002(\014\022\r\n\005step2\030\007 \002(\r\022\r" + "\n\005type2\030\010 \002(\r\022\022\n\nimageData2\030\t \002(\014\022\025\n\rcam" + "era_config\030\n \001(\r\022\023\n\013camera_type\030\013 \001(\r\022\014\n" + "\004roll\030\014 \001(\002\022\r\n\005pitch\030\r \001(\002\022\013\n\003yaw\030\016 \001(\002\022" + "\013\n\003lon\030\017 \001(\002\022\013\n\003lat\030\020 \001(\002\022\013\n\003alt\030\021 \001(\002\022\020" + "\n\010ground_x\030\022 \001(\002\022\020\n\010ground_y\030\023 \001(\002\022\020\n\010gr" + "ound_z\030\024 \001(\002\022\025\n\rcamera_matrix\030\025 \003(\002\"U\n\010W" + "aypoint\022\t\n\001x\030\001 \002(\001\022\t\n\001y\030\002 \002(\001\022\t\n\001z\030\003 \001(\001" + "\022\014\n\004roll\030\004 \001(\001\022\r\n\005pitch\030\005 \001(\001\022\013\n\003yaw\030\006 \001" + "(\001", 1962); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "pixhawk.proto", &protobuf_RegisterTypes); + HeaderInfo::default_instance_ = new HeaderInfo(); + GLOverlay::default_instance_ = new GLOverlay(); + Obstacle::default_instance_ = new Obstacle(); + ObstacleList::default_instance_ = new ObstacleList(); + ObstacleMap::default_instance_ = new ObstacleMap(); + Path::default_instance_ = new Path(); + PointCloudXYZI::default_instance_ = new PointCloudXYZI(); + PointCloudXYZI_PointXYZI::default_instance_ = new PointCloudXYZI_PointXYZI(); + PointCloudXYZRGB::default_instance_ = new PointCloudXYZRGB(); + PointCloudXYZRGB_PointXYZRGB::default_instance_ = new PointCloudXYZRGB_PointXYZRGB(); + RGBDImage::default_instance_ = new RGBDImage(); + Waypoint::default_instance_ = new Waypoint(); + HeaderInfo::default_instance_->InitAsDefaultInstance(); + GLOverlay::default_instance_->InitAsDefaultInstance(); + Obstacle::default_instance_->InitAsDefaultInstance(); + ObstacleList::default_instance_->InitAsDefaultInstance(); + ObstacleMap::default_instance_->InitAsDefaultInstance(); + Path::default_instance_->InitAsDefaultInstance(); + PointCloudXYZI::default_instance_->InitAsDefaultInstance(); + PointCloudXYZI_PointXYZI::default_instance_->InitAsDefaultInstance(); + PointCloudXYZRGB::default_instance_->InitAsDefaultInstance(); + PointCloudXYZRGB_PointXYZRGB::default_instance_->InitAsDefaultInstance(); + RGBDImage::default_instance_->InitAsDefaultInstance(); + Waypoint::default_instance_->InitAsDefaultInstance(); + ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_pixhawk_2eproto); +} + +// Force AddDescriptors() to be called at static initialization time. +struct StaticDescriptorInitializer_pixhawk_2eproto { + StaticDescriptorInitializer_pixhawk_2eproto() { + protobuf_AddDesc_pixhawk_2eproto(); + } +} static_descriptor_initializer_pixhawk_2eproto_; + + +// =================================================================== + +#ifndef _MSC_VER +const int HeaderInfo::kSourceSysidFieldNumber; +const int HeaderInfo::kSourceCompidFieldNumber; +const int HeaderInfo::kTimestampFieldNumber; +#endif // !_MSC_VER + +HeaderInfo::HeaderInfo() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void HeaderInfo::InitAsDefaultInstance() { +} + +HeaderInfo::HeaderInfo(const HeaderInfo& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void HeaderInfo::SharedCtor() { + _cached_size_ = 0; + source_sysid_ = 0; + source_compid_ = 0; + timestamp_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +HeaderInfo::~HeaderInfo() { + SharedDtor(); +} + +void HeaderInfo::SharedDtor() { + if (this != default_instance_) { + } +} + +void HeaderInfo::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* HeaderInfo::descriptor() { + protobuf_AssignDescriptorsOnce(); + return HeaderInfo_descriptor_; +} + +const HeaderInfo& HeaderInfo::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +HeaderInfo* HeaderInfo::default_instance_ = NULL; + +HeaderInfo* HeaderInfo::New() const { + return new HeaderInfo; +} + +void HeaderInfo::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + source_sysid_ = 0; + source_compid_ = 0; + timestamp_ = 0; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool HeaderInfo::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required int32 source_sysid = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &source_sysid_))); + set_has_source_sysid(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_source_compid; + break; + } + + // required int32 source_compid = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_source_compid: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &source_compid_))); + set_has_source_compid(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(25)) goto parse_timestamp; + break; + } + + // required double timestamp = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_timestamp: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, ×tamp_))); + set_has_timestamp(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void HeaderInfo::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required int32 source_sysid = 1; + if (has_source_sysid()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->source_sysid(), output); + } + + // required int32 source_compid = 2; + if (has_source_compid()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->source_compid(), output); + } + + // required double timestamp = 3; + if (has_timestamp()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(3, this->timestamp(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* HeaderInfo::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required int32 source_sysid = 1; + if (has_source_sysid()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->source_sysid(), target); + } + + // required int32 source_compid = 2; + if (has_source_compid()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->source_compid(), target); + } + + // required double timestamp = 3; + if (has_timestamp()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(3, this->timestamp(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int HeaderInfo::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required int32 source_sysid = 1; + if (has_source_sysid()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->source_sysid()); + } + + // required int32 source_compid = 2; + if (has_source_compid()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->source_compid()); + } + + // required double timestamp = 3; + if (has_timestamp()) { + total_size += 1 + 8; + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void HeaderInfo::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const HeaderInfo* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void HeaderInfo::MergeFrom(const HeaderInfo& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_source_sysid()) { + set_source_sysid(from.source_sysid()); + } + if (from.has_source_compid()) { + set_source_compid(from.source_compid()); + } + if (from.has_timestamp()) { + set_timestamp(from.timestamp()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void HeaderInfo::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void HeaderInfo::CopyFrom(const HeaderInfo& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool HeaderInfo::IsInitialized() const { + if ((_has_bits_[0] & 0x00000007) != 0x00000007) return false; + + return true; +} + +void HeaderInfo::Swap(HeaderInfo* other) { + if (other != this) { + std::swap(source_sysid_, other->source_sysid_); + std::swap(source_compid_, other->source_compid_); + std::swap(timestamp_, other->timestamp_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata HeaderInfo::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = HeaderInfo_descriptor_; + metadata.reflection = HeaderInfo_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* GLOverlay_CoordinateFrameType_descriptor() { + protobuf_AssignDescriptorsOnce(); + return GLOverlay_CoordinateFrameType_descriptor_; +} +bool GLOverlay_CoordinateFrameType_IsValid(int value) { + switch(value) { + case 0: + case 1: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const GLOverlay_CoordinateFrameType GLOverlay::GLOBAL; +const GLOverlay_CoordinateFrameType GLOverlay::LOCAL; +const GLOverlay_CoordinateFrameType GLOverlay::CoordinateFrameType_MIN; +const GLOverlay_CoordinateFrameType GLOverlay::CoordinateFrameType_MAX; +const int GLOverlay::CoordinateFrameType_ARRAYSIZE; +#endif // _MSC_VER +const ::google::protobuf::EnumDescriptor* GLOverlay_Mode_descriptor() { + protobuf_AssignDescriptorsOnce(); + return GLOverlay_Mode_descriptor_; +} +bool GLOverlay_Mode_IsValid(int value) { + switch(value) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const GLOverlay_Mode GLOverlay::POINTS; +const GLOverlay_Mode GLOverlay::LINES; +const GLOverlay_Mode GLOverlay::LINE_STRIP; +const GLOverlay_Mode GLOverlay::LINE_LOOP; +const GLOverlay_Mode GLOverlay::TRIANGLES; +const GLOverlay_Mode GLOverlay::TRIANGLE_STRIP; +const GLOverlay_Mode GLOverlay::TRIANGLE_FAN; +const GLOverlay_Mode GLOverlay::QUADS; +const GLOverlay_Mode GLOverlay::QUAD_STRIP; +const GLOverlay_Mode GLOverlay::POLYGON; +const GLOverlay_Mode GLOverlay::SOLID_CIRCLE; +const GLOverlay_Mode GLOverlay::WIRE_CIRCLE; +const GLOverlay_Mode GLOverlay::SOLID_CUBE; +const GLOverlay_Mode GLOverlay::WIRE_CUBE; +const GLOverlay_Mode GLOverlay::Mode_MIN; +const GLOverlay_Mode GLOverlay::Mode_MAX; +const int GLOverlay::Mode_ARRAYSIZE; +#endif // _MSC_VER +const ::google::protobuf::EnumDescriptor* GLOverlay_Identifier_descriptor() { + protobuf_AssignDescriptorsOnce(); + return GLOverlay_Identifier_descriptor_; +} +bool GLOverlay_Identifier_IsValid(int value) { + switch(value) { + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const GLOverlay_Identifier GLOverlay::END; +const GLOverlay_Identifier GLOverlay::VERTEX2F; +const GLOverlay_Identifier GLOverlay::VERTEX3F; +const GLOverlay_Identifier GLOverlay::ROTATEF; +const GLOverlay_Identifier GLOverlay::TRANSLATEF; +const GLOverlay_Identifier GLOverlay::SCALEF; +const GLOverlay_Identifier GLOverlay::PUSH_MATRIX; +const GLOverlay_Identifier GLOverlay::POP_MATRIX; +const GLOverlay_Identifier GLOverlay::COLOR3F; +const GLOverlay_Identifier GLOverlay::COLOR4F; +const GLOverlay_Identifier GLOverlay::POINTSIZE; +const GLOverlay_Identifier GLOverlay::LINEWIDTH; +const GLOverlay_Identifier GLOverlay::Identifier_MIN; +const GLOverlay_Identifier GLOverlay::Identifier_MAX; +const int GLOverlay::Identifier_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int GLOverlay::kHeaderFieldNumber; +const int GLOverlay::kNameFieldNumber; +const int GLOverlay::kCoordinateFrameTypeFieldNumber; +const int GLOverlay::kOriginXFieldNumber; +const int GLOverlay::kOriginYFieldNumber; +const int GLOverlay::kOriginZFieldNumber; +const int GLOverlay::kDataFieldNumber; +#endif // !_MSC_VER + +GLOverlay::GLOverlay() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void GLOverlay::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +GLOverlay::GLOverlay(const GLOverlay& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void GLOverlay::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + coordinateframetype_ = 0; + origin_x_ = 0; + origin_y_ = 0; + origin_z_ = 0; + data_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +GLOverlay::~GLOverlay() { + SharedDtor(); +} + +void GLOverlay::SharedDtor() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (data_ != &::google::protobuf::internal::kEmptyString) { + delete data_; + } + if (this != default_instance_) { + delete header_; + } +} + +void GLOverlay::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* GLOverlay::descriptor() { + protobuf_AssignDescriptorsOnce(); + return GLOverlay_descriptor_; +} + +const GLOverlay& GLOverlay::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +GLOverlay* GLOverlay::default_instance_ = NULL; + +GLOverlay* GLOverlay::New() const { + return new GLOverlay; +} + +void GLOverlay::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + coordinateframetype_ = 0; + origin_x_ = 0; + origin_y_ = 0; + origin_z_ = 0; + if (has_data()) { + if (data_ != &::google::protobuf::internal::kEmptyString) { + data_->clear(); + } + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool GLOverlay::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_name; + break; + } + + // optional string name = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_name: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(24)) goto parse_coordinateFrameType; + break; + } + + // optional .px.GLOverlay.CoordinateFrameType coordinateFrameType = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_coordinateFrameType: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::px::GLOverlay_CoordinateFrameType_IsValid(value)) { + set_coordinateframetype(static_cast< ::px::GLOverlay_CoordinateFrameType >(value)); + } else { + mutable_unknown_fields()->AddVarint(3, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(33)) goto parse_origin_x; + break; + } + + // optional double origin_x = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_origin_x: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &origin_x_))); + set_has_origin_x(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(41)) goto parse_origin_y; + break; + } + + // optional double origin_y = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_origin_y: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &origin_y_))); + set_has_origin_y(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(49)) goto parse_origin_z; + break; + } + + // optional double origin_z = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_origin_z: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &origin_z_))); + set_has_origin_z(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(58)) goto parse_data; + break; + } + + // optional bytes data = 7; + case 7: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_data: + DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( + input, this->mutable_data())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void GLOverlay::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // optional string name = 2; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->name(), output); + } + + // optional .px.GLOverlay.CoordinateFrameType coordinateFrameType = 3; + if (has_coordinateframetype()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 3, this->coordinateframetype(), output); + } + + // optional double origin_x = 4; + if (has_origin_x()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(4, this->origin_x(), output); + } + + // optional double origin_y = 5; + if (has_origin_y()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(5, this->origin_y(), output); + } + + // optional double origin_z = 6; + if (has_origin_z()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->origin_z(), output); + } + + // optional bytes data = 7; + if (has_data()) { + ::google::protobuf::internal::WireFormatLite::WriteBytes( + 7, this->data(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* GLOverlay::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // optional string name = 2; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->name(), target); + } + + // optional .px.GLOverlay.CoordinateFrameType coordinateFrameType = 3; + if (has_coordinateframetype()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 3, this->coordinateframetype(), target); + } + + // optional double origin_x = 4; + if (has_origin_x()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(4, this->origin_x(), target); + } + + // optional double origin_y = 5; + if (has_origin_y()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(5, this->origin_y(), target); + } + + // optional double origin_z = 6; + if (has_origin_z()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->origin_z(), target); + } + + // optional bytes data = 7; + if (has_data()) { + target = + ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( + 7, this->data(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int GLOverlay::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + // optional string name = 2; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + // optional .px.GLOverlay.CoordinateFrameType coordinateFrameType = 3; + if (has_coordinateframetype()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->coordinateframetype()); + } + + // optional double origin_x = 4; + if (has_origin_x()) { + total_size += 1 + 8; + } + + // optional double origin_y = 5; + if (has_origin_y()) { + total_size += 1 + 8; + } + + // optional double origin_z = 6; + if (has_origin_z()) { + total_size += 1 + 8; + } + + // optional bytes data = 7; + if (has_data()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::BytesSize( + this->data()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void GLOverlay::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const GLOverlay* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void GLOverlay::MergeFrom(const GLOverlay& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + if (from.has_name()) { + set_name(from.name()); + } + if (from.has_coordinateframetype()) { + set_coordinateframetype(from.coordinateframetype()); + } + if (from.has_origin_x()) { + set_origin_x(from.origin_x()); + } + if (from.has_origin_y()) { + set_origin_y(from.origin_y()); + } + if (from.has_origin_z()) { + set_origin_z(from.origin_z()); + } + if (from.has_data()) { + set_data(from.data()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void GLOverlay::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void GLOverlay::CopyFrom(const GLOverlay& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool GLOverlay::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + return true; +} + +void GLOverlay::Swap(GLOverlay* other) { + if (other != this) { + std::swap(header_, other->header_); + std::swap(name_, other->name_); + std::swap(coordinateframetype_, other->coordinateframetype_); + std::swap(origin_x_, other->origin_x_); + std::swap(origin_y_, other->origin_y_); + std::swap(origin_z_, other->origin_z_); + std::swap(data_, other->data_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata GLOverlay::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = GLOverlay_descriptor_; + metadata.reflection = GLOverlay_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int Obstacle::kXFieldNumber; +const int Obstacle::kYFieldNumber; +const int Obstacle::kZFieldNumber; +const int Obstacle::kLengthFieldNumber; +const int Obstacle::kWidthFieldNumber; +const int Obstacle::kHeightFieldNumber; +#endif // !_MSC_VER + +Obstacle::Obstacle() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void Obstacle::InitAsDefaultInstance() { +} + +Obstacle::Obstacle(const Obstacle& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void Obstacle::SharedCtor() { + _cached_size_ = 0; + x_ = 0; + y_ = 0; + z_ = 0; + length_ = 0; + width_ = 0; + height_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +Obstacle::~Obstacle() { + SharedDtor(); +} + +void Obstacle::SharedDtor() { + if (this != default_instance_) { + } +} + +void Obstacle::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* Obstacle::descriptor() { + protobuf_AssignDescriptorsOnce(); + return Obstacle_descriptor_; +} + +const Obstacle& Obstacle::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +Obstacle* Obstacle::default_instance_ = NULL; + +Obstacle* Obstacle::New() const { + return new Obstacle; +} + +void Obstacle::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + x_ = 0; + y_ = 0; + z_ = 0; + length_ = 0; + width_ = 0; + height_ = 0; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool Obstacle::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional float x = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &x_))); + set_has_x(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(21)) goto parse_y; + break; + } + + // optional float y = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_y: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &y_))); + set_has_y(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(29)) goto parse_z; + break; + } + + // optional float z = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_z: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &z_))); + set_has_z(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(37)) goto parse_length; + break; + } + + // optional float length = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_length: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &length_))); + set_has_length(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(45)) goto parse_width; + break; + } + + // optional float width = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_width: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &width_))); + set_has_width(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(53)) goto parse_height; + break; + } + + // optional float height = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_height: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &height_))); + set_has_height(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void Obstacle::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional float x = 1; + if (has_x()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->x(), output); + } + + // optional float y = 2; + if (has_y()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(2, this->y(), output); + } + + // optional float z = 3; + if (has_z()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->z(), output); + } + + // optional float length = 4; + if (has_length()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(4, this->length(), output); + } + + // optional float width = 5; + if (has_width()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(5, this->width(), output); + } + + // optional float height = 6; + if (has_height()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(6, this->height(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* Obstacle::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional float x = 1; + if (has_x()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(1, this->x(), target); + } + + // optional float y = 2; + if (has_y()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(2, this->y(), target); + } + + // optional float z = 3; + if (has_z()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(3, this->z(), target); + } + + // optional float length = 4; + if (has_length()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(4, this->length(), target); + } + + // optional float width = 5; + if (has_width()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(5, this->width(), target); + } + + // optional float height = 6; + if (has_height()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(6, this->height(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int Obstacle::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional float x = 1; + if (has_x()) { + total_size += 1 + 4; + } + + // optional float y = 2; + if (has_y()) { + total_size += 1 + 4; + } + + // optional float z = 3; + if (has_z()) { + total_size += 1 + 4; + } + + // optional float length = 4; + if (has_length()) { + total_size += 1 + 4; + } + + // optional float width = 5; + if (has_width()) { + total_size += 1 + 4; + } + + // optional float height = 6; + if (has_height()) { + total_size += 1 + 4; + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void Obstacle::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const Obstacle* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void Obstacle::MergeFrom(const Obstacle& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_x()) { + set_x(from.x()); + } + if (from.has_y()) { + set_y(from.y()); + } + if (from.has_z()) { + set_z(from.z()); + } + if (from.has_length()) { + set_length(from.length()); + } + if (from.has_width()) { + set_width(from.width()); + } + if (from.has_height()) { + set_height(from.height()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void Obstacle::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Obstacle::CopyFrom(const Obstacle& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Obstacle::IsInitialized() const { + + return true; +} + +void Obstacle::Swap(Obstacle* other) { + if (other != this) { + std::swap(x_, other->x_); + std::swap(y_, other->y_); + std::swap(z_, other->z_); + std::swap(length_, other->length_); + std::swap(width_, other->width_); + std::swap(height_, other->height_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata Obstacle::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = Obstacle_descriptor_; + metadata.reflection = Obstacle_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ObstacleList::kHeaderFieldNumber; +const int ObstacleList::kObstaclesFieldNumber; +#endif // !_MSC_VER + +ObstacleList::ObstacleList() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ObstacleList::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +ObstacleList::ObstacleList(const ObstacleList& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ObstacleList::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ObstacleList::~ObstacleList() { + SharedDtor(); +} + +void ObstacleList::SharedDtor() { + if (this != default_instance_) { + delete header_; + } +} + +void ObstacleList::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ObstacleList::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ObstacleList_descriptor_; +} + +const ObstacleList& ObstacleList::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +ObstacleList* ObstacleList::default_instance_ = NULL; + +ObstacleList* ObstacleList::New() const { + return new ObstacleList; +} + +void ObstacleList::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + } + obstacles_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ObstacleList::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_obstacles; + break; + } + + // repeated .px.Obstacle obstacles = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_obstacles: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_obstacles())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_obstacles; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ObstacleList::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // repeated .px.Obstacle obstacles = 2; + for (int i = 0; i < this->obstacles_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->obstacles(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ObstacleList::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // repeated .px.Obstacle obstacles = 2; + for (int i = 0; i < this->obstacles_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->obstacles(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ObstacleList::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + } + // repeated .px.Obstacle obstacles = 2; + total_size += 1 * this->obstacles_size(); + for (int i = 0; i < this->obstacles_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->obstacles(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ObstacleList::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ObstacleList* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ObstacleList::MergeFrom(const ObstacleList& from) { + GOOGLE_CHECK_NE(&from, this); + obstacles_.MergeFrom(from.obstacles_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ObstacleList::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ObstacleList::CopyFrom(const ObstacleList& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ObstacleList::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + return true; +} + +void ObstacleList::Swap(ObstacleList* other) { + if (other != this) { + std::swap(header_, other->header_); + obstacles_.Swap(&other->obstacles_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ObstacleList::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ObstacleList_descriptor_; + metadata.reflection = ObstacleList_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ObstacleMap::kHeaderFieldNumber; +const int ObstacleMap::kTypeFieldNumber; +const int ObstacleMap::kResolutionFieldNumber; +const int ObstacleMap::kRowsFieldNumber; +const int ObstacleMap::kColsFieldNumber; +const int ObstacleMap::kMapR0FieldNumber; +const int ObstacleMap::kMapC0FieldNumber; +const int ObstacleMap::kArrayR0FieldNumber; +const int ObstacleMap::kArrayC0FieldNumber; +const int ObstacleMap::kDataFieldNumber; +#endif // !_MSC_VER + +ObstacleMap::ObstacleMap() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ObstacleMap::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +ObstacleMap::ObstacleMap(const ObstacleMap& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ObstacleMap::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + type_ = 0; + resolution_ = 0; + rows_ = 0; + cols_ = 0; + mapr0_ = 0; + mapc0_ = 0; + arrayr0_ = 0; + arrayc0_ = 0; + data_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ObstacleMap::~ObstacleMap() { + SharedDtor(); +} + +void ObstacleMap::SharedDtor() { + if (data_ != &::google::protobuf::internal::kEmptyString) { + delete data_; + } + if (this != default_instance_) { + delete header_; + } +} + +void ObstacleMap::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ObstacleMap::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ObstacleMap_descriptor_; +} + +const ObstacleMap& ObstacleMap::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +ObstacleMap* ObstacleMap::default_instance_ = NULL; + +ObstacleMap* ObstacleMap::New() const { + return new ObstacleMap; +} + +void ObstacleMap::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + type_ = 0; + resolution_ = 0; + rows_ = 0; + cols_ = 0; + mapr0_ = 0; + mapc0_ = 0; + arrayr0_ = 0; + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + arrayc0_ = 0; + if (has_data()) { + if (data_ != &::google::protobuf::internal::kEmptyString) { + data_->clear(); + } + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ObstacleMap::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_type; + break; + } + + // required int32 type = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_type: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &type_))); + set_has_type(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(29)) goto parse_resolution; + break; + } + + // optional float resolution = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_resolution: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &resolution_))); + set_has_resolution(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(32)) goto parse_rows; + break; + } + + // optional int32 rows = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_rows: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &rows_))); + set_has_rows(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(40)) goto parse_cols; + break; + } + + // optional int32 cols = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_cols: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &cols_))); + set_has_cols(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(48)) goto parse_mapR0; + break; + } + + // optional int32 mapR0 = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_mapR0: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &mapr0_))); + set_has_mapr0(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(56)) goto parse_mapC0; + break; + } + + // optional int32 mapC0 = 7; + case 7: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_mapC0: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &mapc0_))); + set_has_mapc0(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(64)) goto parse_arrayR0; + break; + } + + // optional int32 arrayR0 = 8; + case 8: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_arrayR0: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &arrayr0_))); + set_has_arrayr0(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(72)) goto parse_arrayC0; + break; + } + + // optional int32 arrayC0 = 9; + case 9: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_arrayC0: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &arrayc0_))); + set_has_arrayc0(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(82)) goto parse_data; + break; + } + + // optional bytes data = 10; + case 10: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_data: + DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( + input, this->mutable_data())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ObstacleMap::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // required int32 type = 2; + if (has_type()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->type(), output); + } + + // optional float resolution = 3; + if (has_resolution()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->resolution(), output); + } + + // optional int32 rows = 4; + if (has_rows()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(4, this->rows(), output); + } + + // optional int32 cols = 5; + if (has_cols()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(5, this->cols(), output); + } + + // optional int32 mapR0 = 6; + if (has_mapr0()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(6, this->mapr0(), output); + } + + // optional int32 mapC0 = 7; + if (has_mapc0()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(7, this->mapc0(), output); + } + + // optional int32 arrayR0 = 8; + if (has_arrayr0()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(8, this->arrayr0(), output); + } + + // optional int32 arrayC0 = 9; + if (has_arrayc0()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(9, this->arrayc0(), output); + } + + // optional bytes data = 10; + if (has_data()) { + ::google::protobuf::internal::WireFormatLite::WriteBytes( + 10, this->data(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ObstacleMap::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // required int32 type = 2; + if (has_type()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->type(), target); + } + + // optional float resolution = 3; + if (has_resolution()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(3, this->resolution(), target); + } + + // optional int32 rows = 4; + if (has_rows()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(4, this->rows(), target); + } + + // optional int32 cols = 5; + if (has_cols()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(5, this->cols(), target); + } + + // optional int32 mapR0 = 6; + if (has_mapr0()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(6, this->mapr0(), target); + } + + // optional int32 mapC0 = 7; + if (has_mapc0()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(7, this->mapc0(), target); + } + + // optional int32 arrayR0 = 8; + if (has_arrayr0()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(8, this->arrayr0(), target); + } + + // optional int32 arrayC0 = 9; + if (has_arrayc0()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(9, this->arrayc0(), target); + } + + // optional bytes data = 10; + if (has_data()) { + target = + ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( + 10, this->data(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ObstacleMap::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + // required int32 type = 2; + if (has_type()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->type()); + } + + // optional float resolution = 3; + if (has_resolution()) { + total_size += 1 + 4; + } + + // optional int32 rows = 4; + if (has_rows()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->rows()); + } + + // optional int32 cols = 5; + if (has_cols()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->cols()); + } + + // optional int32 mapR0 = 6; + if (has_mapr0()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->mapr0()); + } + + // optional int32 mapC0 = 7; + if (has_mapc0()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->mapc0()); + } + + // optional int32 arrayR0 = 8; + if (has_arrayr0()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->arrayr0()); + } + + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + // optional int32 arrayC0 = 9; + if (has_arrayc0()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->arrayc0()); + } + + // optional bytes data = 10; + if (has_data()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::BytesSize( + this->data()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ObstacleMap::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ObstacleMap* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ObstacleMap::MergeFrom(const ObstacleMap& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + if (from.has_type()) { + set_type(from.type()); + } + if (from.has_resolution()) { + set_resolution(from.resolution()); + } + if (from.has_rows()) { + set_rows(from.rows()); + } + if (from.has_cols()) { + set_cols(from.cols()); + } + if (from.has_mapr0()) { + set_mapr0(from.mapr0()); + } + if (from.has_mapc0()) { + set_mapc0(from.mapc0()); + } + if (from.has_arrayr0()) { + set_arrayr0(from.arrayr0()); + } + } + if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) { + if (from.has_arrayc0()) { + set_arrayc0(from.arrayc0()); + } + if (from.has_data()) { + set_data(from.data()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ObstacleMap::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ObstacleMap::CopyFrom(const ObstacleMap& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ObstacleMap::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + return true; +} + +void ObstacleMap::Swap(ObstacleMap* other) { + if (other != this) { + std::swap(header_, other->header_); + std::swap(type_, other->type_); + std::swap(resolution_, other->resolution_); + std::swap(rows_, other->rows_); + std::swap(cols_, other->cols_); + std::swap(mapr0_, other->mapr0_); + std::swap(mapc0_, other->mapc0_); + std::swap(arrayr0_, other->arrayr0_); + std::swap(arrayc0_, other->arrayc0_); + std::swap(data_, other->data_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ObstacleMap::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ObstacleMap_descriptor_; + metadata.reflection = ObstacleMap_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int Path::kHeaderFieldNumber; +const int Path::kWaypointsFieldNumber; +#endif // !_MSC_VER + +Path::Path() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void Path::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +Path::Path(const Path& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void Path::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +Path::~Path() { + SharedDtor(); +} + +void Path::SharedDtor() { + if (this != default_instance_) { + delete header_; + } +} + +void Path::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* Path::descriptor() { + protobuf_AssignDescriptorsOnce(); + return Path_descriptor_; +} + +const Path& Path::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +Path* Path::default_instance_ = NULL; + +Path* Path::New() const { + return new Path; +} + +void Path::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + } + waypoints_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool Path::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_waypoints; + break; + } + + // repeated .px.Waypoint waypoints = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_waypoints: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_waypoints())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_waypoints; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void Path::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // repeated .px.Waypoint waypoints = 2; + for (int i = 0; i < this->waypoints_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->waypoints(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* Path::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // repeated .px.Waypoint waypoints = 2; + for (int i = 0; i < this->waypoints_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->waypoints(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int Path::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + } + // repeated .px.Waypoint waypoints = 2; + total_size += 1 * this->waypoints_size(); + for (int i = 0; i < this->waypoints_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->waypoints(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void Path::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const Path* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void Path::MergeFrom(const Path& from) { + GOOGLE_CHECK_NE(&from, this); + waypoints_.MergeFrom(from.waypoints_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void Path::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Path::CopyFrom(const Path& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Path::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + for (int i = 0; i < waypoints_size(); i++) { + if (!this->waypoints(i).IsInitialized()) return false; + } + return true; +} + +void Path::Swap(Path* other) { + if (other != this) { + std::swap(header_, other->header_); + waypoints_.Swap(&other->waypoints_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata Path::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = Path_descriptor_; + metadata.reflection = Path_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int PointCloudXYZI_PointXYZI::kXFieldNumber; +const int PointCloudXYZI_PointXYZI::kYFieldNumber; +const int PointCloudXYZI_PointXYZI::kZFieldNumber; +const int PointCloudXYZI_PointXYZI::kIntensityFieldNumber; +#endif // !_MSC_VER + +PointCloudXYZI_PointXYZI::PointCloudXYZI_PointXYZI() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void PointCloudXYZI_PointXYZI::InitAsDefaultInstance() { +} + +PointCloudXYZI_PointXYZI::PointCloudXYZI_PointXYZI(const PointCloudXYZI_PointXYZI& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void PointCloudXYZI_PointXYZI::SharedCtor() { + _cached_size_ = 0; + x_ = 0; + y_ = 0; + z_ = 0; + intensity_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +PointCloudXYZI_PointXYZI::~PointCloudXYZI_PointXYZI() { + SharedDtor(); +} + +void PointCloudXYZI_PointXYZI::SharedDtor() { + if (this != default_instance_) { + } +} + +void PointCloudXYZI_PointXYZI::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* PointCloudXYZI_PointXYZI::descriptor() { + protobuf_AssignDescriptorsOnce(); + return PointCloudXYZI_PointXYZI_descriptor_; +} + +const PointCloudXYZI_PointXYZI& PointCloudXYZI_PointXYZI::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +PointCloudXYZI_PointXYZI* PointCloudXYZI_PointXYZI::default_instance_ = NULL; + +PointCloudXYZI_PointXYZI* PointCloudXYZI_PointXYZI::New() const { + return new PointCloudXYZI_PointXYZI; +} + +void PointCloudXYZI_PointXYZI::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + x_ = 0; + y_ = 0; + z_ = 0; + intensity_ = 0; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool PointCloudXYZI_PointXYZI::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required float x = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &x_))); + set_has_x(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(21)) goto parse_y; + break; + } + + // required float y = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_y: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &y_))); + set_has_y(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(29)) goto parse_z; + break; + } + + // required float z = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_z: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &z_))); + set_has_z(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(37)) goto parse_intensity; + break; + } + + // required float intensity = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_intensity: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &intensity_))); + set_has_intensity(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void PointCloudXYZI_PointXYZI::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required float x = 1; + if (has_x()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->x(), output); + } + + // required float y = 2; + if (has_y()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(2, this->y(), output); + } + + // required float z = 3; + if (has_z()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->z(), output); + } + + // required float intensity = 4; + if (has_intensity()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(4, this->intensity(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* PointCloudXYZI_PointXYZI::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required float x = 1; + if (has_x()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(1, this->x(), target); + } + + // required float y = 2; + if (has_y()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(2, this->y(), target); + } + + // required float z = 3; + if (has_z()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(3, this->z(), target); + } + + // required float intensity = 4; + if (has_intensity()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(4, this->intensity(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int PointCloudXYZI_PointXYZI::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required float x = 1; + if (has_x()) { + total_size += 1 + 4; + } + + // required float y = 2; + if (has_y()) { + total_size += 1 + 4; + } + + // required float z = 3; + if (has_z()) { + total_size += 1 + 4; + } + + // required float intensity = 4; + if (has_intensity()) { + total_size += 1 + 4; + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void PointCloudXYZI_PointXYZI::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const PointCloudXYZI_PointXYZI* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void PointCloudXYZI_PointXYZI::MergeFrom(const PointCloudXYZI_PointXYZI& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_x()) { + set_x(from.x()); + } + if (from.has_y()) { + set_y(from.y()); + } + if (from.has_z()) { + set_z(from.z()); + } + if (from.has_intensity()) { + set_intensity(from.intensity()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void PointCloudXYZI_PointXYZI::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void PointCloudXYZI_PointXYZI::CopyFrom(const PointCloudXYZI_PointXYZI& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool PointCloudXYZI_PointXYZI::IsInitialized() const { + if ((_has_bits_[0] & 0x0000000f) != 0x0000000f) return false; + + return true; +} + +void PointCloudXYZI_PointXYZI::Swap(PointCloudXYZI_PointXYZI* other) { + if (other != this) { + std::swap(x_, other->x_); + std::swap(y_, other->y_); + std::swap(z_, other->z_); + std::swap(intensity_, other->intensity_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata PointCloudXYZI_PointXYZI::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = PointCloudXYZI_PointXYZI_descriptor_; + metadata.reflection = PointCloudXYZI_PointXYZI_reflection_; + return metadata; +} + + +// ------------------------------------------------------------------- + +#ifndef _MSC_VER +const int PointCloudXYZI::kHeaderFieldNumber; +const int PointCloudXYZI::kPointsFieldNumber; +#endif // !_MSC_VER + +PointCloudXYZI::PointCloudXYZI() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void PointCloudXYZI::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +PointCloudXYZI::PointCloudXYZI(const PointCloudXYZI& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void PointCloudXYZI::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +PointCloudXYZI::~PointCloudXYZI() { + SharedDtor(); +} + +void PointCloudXYZI::SharedDtor() { + if (this != default_instance_) { + delete header_; + } +} + +void PointCloudXYZI::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* PointCloudXYZI::descriptor() { + protobuf_AssignDescriptorsOnce(); + return PointCloudXYZI_descriptor_; +} + +const PointCloudXYZI& PointCloudXYZI::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +PointCloudXYZI* PointCloudXYZI::default_instance_ = NULL; + +PointCloudXYZI* PointCloudXYZI::New() const { + return new PointCloudXYZI; +} + +void PointCloudXYZI::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + } + points_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool PointCloudXYZI::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_points; + break; + } + + // repeated .px.PointCloudXYZI.PointXYZI points = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_points: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_points())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_points; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void PointCloudXYZI::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // repeated .px.PointCloudXYZI.PointXYZI points = 2; + for (int i = 0; i < this->points_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->points(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* PointCloudXYZI::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // repeated .px.PointCloudXYZI.PointXYZI points = 2; + for (int i = 0; i < this->points_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->points(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int PointCloudXYZI::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + } + // repeated .px.PointCloudXYZI.PointXYZI points = 2; + total_size += 1 * this->points_size(); + for (int i = 0; i < this->points_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->points(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void PointCloudXYZI::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const PointCloudXYZI* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void PointCloudXYZI::MergeFrom(const PointCloudXYZI& from) { + GOOGLE_CHECK_NE(&from, this); + points_.MergeFrom(from.points_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void PointCloudXYZI::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void PointCloudXYZI::CopyFrom(const PointCloudXYZI& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool PointCloudXYZI::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + for (int i = 0; i < points_size(); i++) { + if (!this->points(i).IsInitialized()) return false; + } + return true; +} + +void PointCloudXYZI::Swap(PointCloudXYZI* other) { + if (other != this) { + std::swap(header_, other->header_); + points_.Swap(&other->points_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata PointCloudXYZI::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = PointCloudXYZI_descriptor_; + metadata.reflection = PointCloudXYZI_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int PointCloudXYZRGB_PointXYZRGB::kXFieldNumber; +const int PointCloudXYZRGB_PointXYZRGB::kYFieldNumber; +const int PointCloudXYZRGB_PointXYZRGB::kZFieldNumber; +const int PointCloudXYZRGB_PointXYZRGB::kRgbFieldNumber; +#endif // !_MSC_VER + +PointCloudXYZRGB_PointXYZRGB::PointCloudXYZRGB_PointXYZRGB() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void PointCloudXYZRGB_PointXYZRGB::InitAsDefaultInstance() { +} + +PointCloudXYZRGB_PointXYZRGB::PointCloudXYZRGB_PointXYZRGB(const PointCloudXYZRGB_PointXYZRGB& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void PointCloudXYZRGB_PointXYZRGB::SharedCtor() { + _cached_size_ = 0; + x_ = 0; + y_ = 0; + z_ = 0; + rgb_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +PointCloudXYZRGB_PointXYZRGB::~PointCloudXYZRGB_PointXYZRGB() { + SharedDtor(); +} + +void PointCloudXYZRGB_PointXYZRGB::SharedDtor() { + if (this != default_instance_) { + } +} + +void PointCloudXYZRGB_PointXYZRGB::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* PointCloudXYZRGB_PointXYZRGB::descriptor() { + protobuf_AssignDescriptorsOnce(); + return PointCloudXYZRGB_PointXYZRGB_descriptor_; +} + +const PointCloudXYZRGB_PointXYZRGB& PointCloudXYZRGB_PointXYZRGB::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +PointCloudXYZRGB_PointXYZRGB* PointCloudXYZRGB_PointXYZRGB::default_instance_ = NULL; + +PointCloudXYZRGB_PointXYZRGB* PointCloudXYZRGB_PointXYZRGB::New() const { + return new PointCloudXYZRGB_PointXYZRGB; +} + +void PointCloudXYZRGB_PointXYZRGB::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + x_ = 0; + y_ = 0; + z_ = 0; + rgb_ = 0; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool PointCloudXYZRGB_PointXYZRGB::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required float x = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &x_))); + set_has_x(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(21)) goto parse_y; + break; + } + + // required float y = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_y: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &y_))); + set_has_y(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(29)) goto parse_z; + break; + } + + // required float z = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_z: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &z_))); + set_has_z(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(37)) goto parse_rgb; + break; + } + + // required float rgb = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_rgb: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &rgb_))); + set_has_rgb(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void PointCloudXYZRGB_PointXYZRGB::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required float x = 1; + if (has_x()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->x(), output); + } + + // required float y = 2; + if (has_y()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(2, this->y(), output); + } + + // required float z = 3; + if (has_z()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->z(), output); + } + + // required float rgb = 4; + if (has_rgb()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(4, this->rgb(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* PointCloudXYZRGB_PointXYZRGB::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required float x = 1; + if (has_x()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(1, this->x(), target); + } + + // required float y = 2; + if (has_y()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(2, this->y(), target); + } + + // required float z = 3; + if (has_z()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(3, this->z(), target); + } + + // required float rgb = 4; + if (has_rgb()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(4, this->rgb(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int PointCloudXYZRGB_PointXYZRGB::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required float x = 1; + if (has_x()) { + total_size += 1 + 4; + } + + // required float y = 2; + if (has_y()) { + total_size += 1 + 4; + } + + // required float z = 3; + if (has_z()) { + total_size += 1 + 4; + } + + // required float rgb = 4; + if (has_rgb()) { + total_size += 1 + 4; + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void PointCloudXYZRGB_PointXYZRGB::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const PointCloudXYZRGB_PointXYZRGB* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void PointCloudXYZRGB_PointXYZRGB::MergeFrom(const PointCloudXYZRGB_PointXYZRGB& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_x()) { + set_x(from.x()); + } + if (from.has_y()) { + set_y(from.y()); + } + if (from.has_z()) { + set_z(from.z()); + } + if (from.has_rgb()) { + set_rgb(from.rgb()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void PointCloudXYZRGB_PointXYZRGB::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void PointCloudXYZRGB_PointXYZRGB::CopyFrom(const PointCloudXYZRGB_PointXYZRGB& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool PointCloudXYZRGB_PointXYZRGB::IsInitialized() const { + if ((_has_bits_[0] & 0x0000000f) != 0x0000000f) return false; + + return true; +} + +void PointCloudXYZRGB_PointXYZRGB::Swap(PointCloudXYZRGB_PointXYZRGB* other) { + if (other != this) { + std::swap(x_, other->x_); + std::swap(y_, other->y_); + std::swap(z_, other->z_); + std::swap(rgb_, other->rgb_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata PointCloudXYZRGB_PointXYZRGB::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = PointCloudXYZRGB_PointXYZRGB_descriptor_; + metadata.reflection = PointCloudXYZRGB_PointXYZRGB_reflection_; + return metadata; +} + + +// ------------------------------------------------------------------- + +#ifndef _MSC_VER +const int PointCloudXYZRGB::kHeaderFieldNumber; +const int PointCloudXYZRGB::kPointsFieldNumber; +#endif // !_MSC_VER + +PointCloudXYZRGB::PointCloudXYZRGB() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void PointCloudXYZRGB::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +PointCloudXYZRGB::PointCloudXYZRGB(const PointCloudXYZRGB& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void PointCloudXYZRGB::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +PointCloudXYZRGB::~PointCloudXYZRGB() { + SharedDtor(); +} + +void PointCloudXYZRGB::SharedDtor() { + if (this != default_instance_) { + delete header_; + } +} + +void PointCloudXYZRGB::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* PointCloudXYZRGB::descriptor() { + protobuf_AssignDescriptorsOnce(); + return PointCloudXYZRGB_descriptor_; +} + +const PointCloudXYZRGB& PointCloudXYZRGB::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +PointCloudXYZRGB* PointCloudXYZRGB::default_instance_ = NULL; + +PointCloudXYZRGB* PointCloudXYZRGB::New() const { + return new PointCloudXYZRGB; +} + +void PointCloudXYZRGB::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + } + points_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool PointCloudXYZRGB::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_points; + break; + } + + // repeated .px.PointCloudXYZRGB.PointXYZRGB points = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_points: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_points())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_points; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void PointCloudXYZRGB::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // repeated .px.PointCloudXYZRGB.PointXYZRGB points = 2; + for (int i = 0; i < this->points_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->points(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* PointCloudXYZRGB::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // repeated .px.PointCloudXYZRGB.PointXYZRGB points = 2; + for (int i = 0; i < this->points_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->points(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int PointCloudXYZRGB::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + } + // repeated .px.PointCloudXYZRGB.PointXYZRGB points = 2; + total_size += 1 * this->points_size(); + for (int i = 0; i < this->points_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->points(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void PointCloudXYZRGB::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const PointCloudXYZRGB* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void PointCloudXYZRGB::MergeFrom(const PointCloudXYZRGB& from) { + GOOGLE_CHECK_NE(&from, this); + points_.MergeFrom(from.points_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void PointCloudXYZRGB::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void PointCloudXYZRGB::CopyFrom(const PointCloudXYZRGB& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool PointCloudXYZRGB::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + for (int i = 0; i < points_size(); i++) { + if (!this->points(i).IsInitialized()) return false; + } + return true; +} + +void PointCloudXYZRGB::Swap(PointCloudXYZRGB* other) { + if (other != this) { + std::swap(header_, other->header_); + points_.Swap(&other->points_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata PointCloudXYZRGB::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = PointCloudXYZRGB_descriptor_; + metadata.reflection = PointCloudXYZRGB_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int RGBDImage::kHeaderFieldNumber; +const int RGBDImage::kColsFieldNumber; +const int RGBDImage::kRowsFieldNumber; +const int RGBDImage::kStep1FieldNumber; +const int RGBDImage::kType1FieldNumber; +const int RGBDImage::kImageData1FieldNumber; +const int RGBDImage::kStep2FieldNumber; +const int RGBDImage::kType2FieldNumber; +const int RGBDImage::kImageData2FieldNumber; +const int RGBDImage::kCameraConfigFieldNumber; +const int RGBDImage::kCameraTypeFieldNumber; +const int RGBDImage::kRollFieldNumber; +const int RGBDImage::kPitchFieldNumber; +const int RGBDImage::kYawFieldNumber; +const int RGBDImage::kLonFieldNumber; +const int RGBDImage::kLatFieldNumber; +const int RGBDImage::kAltFieldNumber; +const int RGBDImage::kGroundXFieldNumber; +const int RGBDImage::kGroundYFieldNumber; +const int RGBDImage::kGroundZFieldNumber; +const int RGBDImage::kCameraMatrixFieldNumber; +#endif // !_MSC_VER + +RGBDImage::RGBDImage() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RGBDImage::InitAsDefaultInstance() { + header_ = const_cast< ::px::HeaderInfo*>(&::px::HeaderInfo::default_instance()); +} + +RGBDImage::RGBDImage(const RGBDImage& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RGBDImage::SharedCtor() { + _cached_size_ = 0; + header_ = NULL; + cols_ = 0u; + rows_ = 0u; + step1_ = 0u; + type1_ = 0u; + imagedata1_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + step2_ = 0u; + type2_ = 0u; + imagedata2_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + camera_config_ = 0u; + camera_type_ = 0u; + roll_ = 0; + pitch_ = 0; + yaw_ = 0; + lon_ = 0; + lat_ = 0; + alt_ = 0; + ground_x_ = 0; + ground_y_ = 0; + ground_z_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RGBDImage::~RGBDImage() { + SharedDtor(); +} + +void RGBDImage::SharedDtor() { + if (imagedata1_ != &::google::protobuf::internal::kEmptyString) { + delete imagedata1_; + } + if (imagedata2_ != &::google::protobuf::internal::kEmptyString) { + delete imagedata2_; + } + if (this != default_instance_) { + delete header_; + } +} + +void RGBDImage::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RGBDImage::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RGBDImage_descriptor_; +} + +const RGBDImage& RGBDImage::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +RGBDImage* RGBDImage::default_instance_ = NULL; + +RGBDImage* RGBDImage::New() const { + return new RGBDImage; +} + +void RGBDImage::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_header()) { + if (header_ != NULL) header_->::px::HeaderInfo::Clear(); + } + cols_ = 0u; + rows_ = 0u; + step1_ = 0u; + type1_ = 0u; + if (has_imagedata1()) { + if (imagedata1_ != &::google::protobuf::internal::kEmptyString) { + imagedata1_->clear(); + } + } + step2_ = 0u; + type2_ = 0u; + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + if (has_imagedata2()) { + if (imagedata2_ != &::google::protobuf::internal::kEmptyString) { + imagedata2_->clear(); + } + } + camera_config_ = 0u; + camera_type_ = 0u; + roll_ = 0; + pitch_ = 0; + yaw_ = 0; + lon_ = 0; + lat_ = 0; + } + if (_has_bits_[16 / 32] & (0xffu << (16 % 32))) { + alt_ = 0; + ground_x_ = 0; + ground_y_ = 0; + ground_z_ = 0; + } + camera_matrix_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RGBDImage::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .px.HeaderInfo header = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_header())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_cols; + break; + } + + // required uint32 cols = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_cols: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &cols_))); + set_has_cols(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(24)) goto parse_rows; + break; + } + + // required uint32 rows = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_rows: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &rows_))); + set_has_rows(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(32)) goto parse_step1; + break; + } + + // required uint32 step1 = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_step1: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &step1_))); + set_has_step1(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(40)) goto parse_type1; + break; + } + + // required uint32 type1 = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_type1: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &type1_))); + set_has_type1(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(50)) goto parse_imageData1; + break; + } + + // required bytes imageData1 = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_imageData1: + DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( + input, this->mutable_imagedata1())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(56)) goto parse_step2; + break; + } + + // required uint32 step2 = 7; + case 7: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_step2: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &step2_))); + set_has_step2(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(64)) goto parse_type2; + break; + } + + // required uint32 type2 = 8; + case 8: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_type2: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &type2_))); + set_has_type2(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(74)) goto parse_imageData2; + break; + } + + // required bytes imageData2 = 9; + case 9: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_imageData2: + DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( + input, this->mutable_imagedata2())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(80)) goto parse_camera_config; + break; + } + + // optional uint32 camera_config = 10; + case 10: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_camera_config: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &camera_config_))); + set_has_camera_config(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(88)) goto parse_camera_type; + break; + } + + // optional uint32 camera_type = 11; + case 11: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_camera_type: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &camera_type_))); + set_has_camera_type(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(101)) goto parse_roll; + break; + } + + // optional float roll = 12; + case 12: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_roll: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &roll_))); + set_has_roll(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(109)) goto parse_pitch; + break; + } + + // optional float pitch = 13; + case 13: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_pitch: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &pitch_))); + set_has_pitch(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(117)) goto parse_yaw; + break; + } + + // optional float yaw = 14; + case 14: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_yaw: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &yaw_))); + set_has_yaw(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(125)) goto parse_lon; + break; + } + + // optional float lon = 15; + case 15: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_lon: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &lon_))); + set_has_lon(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(133)) goto parse_lat; + break; + } + + // optional float lat = 16; + case 16: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_lat: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &lat_))); + set_has_lat(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(141)) goto parse_alt; + break; + } + + // optional float alt = 17; + case 17: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_alt: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &alt_))); + set_has_alt(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(149)) goto parse_ground_x; + break; + } + + // optional float ground_x = 18; + case 18: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_ground_x: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &ground_x_))); + set_has_ground_x(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(157)) goto parse_ground_y; + break; + } + + // optional float ground_y = 19; + case 19: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_ground_y: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &ground_y_))); + set_has_ground_y(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(165)) goto parse_ground_z; + break; + } + + // optional float ground_z = 20; + case 20: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_ground_z: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &ground_z_))); + set_has_ground_z(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(173)) goto parse_camera_matrix; + break; + } + + // repeated float camera_matrix = 21; + case 21: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_camera_matrix: + DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + 2, 173, input, this->mutable_camera_matrix()))); + } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) + == ::google::protobuf::internal::WireFormatLite:: + WIRETYPE_LENGTH_DELIMITED) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, this->mutable_camera_matrix()))); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(173)) goto parse_camera_matrix; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RGBDImage::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->header(), output); + } + + // required uint32 cols = 2; + if (has_cols()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(2, this->cols(), output); + } + + // required uint32 rows = 3; + if (has_rows()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(3, this->rows(), output); + } + + // required uint32 step1 = 4; + if (has_step1()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(4, this->step1(), output); + } + + // required uint32 type1 = 5; + if (has_type1()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(5, this->type1(), output); + } + + // required bytes imageData1 = 6; + if (has_imagedata1()) { + ::google::protobuf::internal::WireFormatLite::WriteBytes( + 6, this->imagedata1(), output); + } + + // required uint32 step2 = 7; + if (has_step2()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(7, this->step2(), output); + } + + // required uint32 type2 = 8; + if (has_type2()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(8, this->type2(), output); + } + + // required bytes imageData2 = 9; + if (has_imagedata2()) { + ::google::protobuf::internal::WireFormatLite::WriteBytes( + 9, this->imagedata2(), output); + } + + // optional uint32 camera_config = 10; + if (has_camera_config()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(10, this->camera_config(), output); + } + + // optional uint32 camera_type = 11; + if (has_camera_type()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(11, this->camera_type(), output); + } + + // optional float roll = 12; + if (has_roll()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(12, this->roll(), output); + } + + // optional float pitch = 13; + if (has_pitch()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(13, this->pitch(), output); + } + + // optional float yaw = 14; + if (has_yaw()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(14, this->yaw(), output); + } + + // optional float lon = 15; + if (has_lon()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(15, this->lon(), output); + } + + // optional float lat = 16; + if (has_lat()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(16, this->lat(), output); + } + + // optional float alt = 17; + if (has_alt()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(17, this->alt(), output); + } + + // optional float ground_x = 18; + if (has_ground_x()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(18, this->ground_x(), output); + } + + // optional float ground_y = 19; + if (has_ground_y()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(19, this->ground_y(), output); + } + + // optional float ground_z = 20; + if (has_ground_z()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(20, this->ground_z(), output); + } + + // repeated float camera_matrix = 21; + for (int i = 0; i < this->camera_matrix_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteFloat( + 21, this->camera_matrix(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RGBDImage::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .px.HeaderInfo header = 1; + if (has_header()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->header(), target); + } + + // required uint32 cols = 2; + if (has_cols()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(2, this->cols(), target); + } + + // required uint32 rows = 3; + if (has_rows()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(3, this->rows(), target); + } + + // required uint32 step1 = 4; + if (has_step1()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(4, this->step1(), target); + } + + // required uint32 type1 = 5; + if (has_type1()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(5, this->type1(), target); + } + + // required bytes imageData1 = 6; + if (has_imagedata1()) { + target = + ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( + 6, this->imagedata1(), target); + } + + // required uint32 step2 = 7; + if (has_step2()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(7, this->step2(), target); + } + + // required uint32 type2 = 8; + if (has_type2()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(8, this->type2(), target); + } + + // required bytes imageData2 = 9; + if (has_imagedata2()) { + target = + ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( + 9, this->imagedata2(), target); + } + + // optional uint32 camera_config = 10; + if (has_camera_config()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(10, this->camera_config(), target); + } + + // optional uint32 camera_type = 11; + if (has_camera_type()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(11, this->camera_type(), target); + } + + // optional float roll = 12; + if (has_roll()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(12, this->roll(), target); + } + + // optional float pitch = 13; + if (has_pitch()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(13, this->pitch(), target); + } + + // optional float yaw = 14; + if (has_yaw()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(14, this->yaw(), target); + } + + // optional float lon = 15; + if (has_lon()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(15, this->lon(), target); + } + + // optional float lat = 16; + if (has_lat()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(16, this->lat(), target); + } + + // optional float alt = 17; + if (has_alt()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(17, this->alt(), target); + } + + // optional float ground_x = 18; + if (has_ground_x()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(18, this->ground_x(), target); + } + + // optional float ground_y = 19; + if (has_ground_y()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(19, this->ground_y(), target); + } + + // optional float ground_z = 20; + if (has_ground_z()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(20, this->ground_z(), target); + } + + // repeated float camera_matrix = 21; + for (int i = 0; i < this->camera_matrix_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteFloatToArray(21, this->camera_matrix(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RGBDImage::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .px.HeaderInfo header = 1; + if (has_header()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->header()); + } + + // required uint32 cols = 2; + if (has_cols()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->cols()); + } + + // required uint32 rows = 3; + if (has_rows()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->rows()); + } + + // required uint32 step1 = 4; + if (has_step1()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->step1()); + } + + // required uint32 type1 = 5; + if (has_type1()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->type1()); + } + + // required bytes imageData1 = 6; + if (has_imagedata1()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::BytesSize( + this->imagedata1()); + } + + // required uint32 step2 = 7; + if (has_step2()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->step2()); + } + + // required uint32 type2 = 8; + if (has_type2()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->type2()); + } + + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + // required bytes imageData2 = 9; + if (has_imagedata2()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::BytesSize( + this->imagedata2()); + } + + // optional uint32 camera_config = 10; + if (has_camera_config()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->camera_config()); + } + + // optional uint32 camera_type = 11; + if (has_camera_type()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->camera_type()); + } + + // optional float roll = 12; + if (has_roll()) { + total_size += 1 + 4; + } + + // optional float pitch = 13; + if (has_pitch()) { + total_size += 1 + 4; + } + + // optional float yaw = 14; + if (has_yaw()) { + total_size += 1 + 4; + } + + // optional float lon = 15; + if (has_lon()) { + total_size += 1 + 4; + } + + // optional float lat = 16; + if (has_lat()) { + total_size += 2 + 4; + } + + } + if (_has_bits_[16 / 32] & (0xffu << (16 % 32))) { + // optional float alt = 17; + if (has_alt()) { + total_size += 2 + 4; + } + + // optional float ground_x = 18; + if (has_ground_x()) { + total_size += 2 + 4; + } + + // optional float ground_y = 19; + if (has_ground_y()) { + total_size += 2 + 4; + } + + // optional float ground_z = 20; + if (has_ground_z()) { + total_size += 2 + 4; + } + + } + // repeated float camera_matrix = 21; + { + int data_size = 0; + data_size = 4 * this->camera_matrix_size(); + total_size += 2 * this->camera_matrix_size() + data_size; + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RGBDImage::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RGBDImage* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RGBDImage::MergeFrom(const RGBDImage& from) { + GOOGLE_CHECK_NE(&from, this); + camera_matrix_.MergeFrom(from.camera_matrix_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_header()) { + mutable_header()->::px::HeaderInfo::MergeFrom(from.header()); + } + if (from.has_cols()) { + set_cols(from.cols()); + } + if (from.has_rows()) { + set_rows(from.rows()); + } + if (from.has_step1()) { + set_step1(from.step1()); + } + if (from.has_type1()) { + set_type1(from.type1()); + } + if (from.has_imagedata1()) { + set_imagedata1(from.imagedata1()); + } + if (from.has_step2()) { + set_step2(from.step2()); + } + if (from.has_type2()) { + set_type2(from.type2()); + } + } + if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) { + if (from.has_imagedata2()) { + set_imagedata2(from.imagedata2()); + } + if (from.has_camera_config()) { + set_camera_config(from.camera_config()); + } + if (from.has_camera_type()) { + set_camera_type(from.camera_type()); + } + if (from.has_roll()) { + set_roll(from.roll()); + } + if (from.has_pitch()) { + set_pitch(from.pitch()); + } + if (from.has_yaw()) { + set_yaw(from.yaw()); + } + if (from.has_lon()) { + set_lon(from.lon()); + } + if (from.has_lat()) { + set_lat(from.lat()); + } + } + if (from._has_bits_[16 / 32] & (0xffu << (16 % 32))) { + if (from.has_alt()) { + set_alt(from.alt()); + } + if (from.has_ground_x()) { + set_ground_x(from.ground_x()); + } + if (from.has_ground_y()) { + set_ground_y(from.ground_y()); + } + if (from.has_ground_z()) { + set_ground_z(from.ground_z()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RGBDImage::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RGBDImage::CopyFrom(const RGBDImage& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RGBDImage::IsInitialized() const { + if ((_has_bits_[0] & 0x000001ff) != 0x000001ff) return false; + + if (has_header()) { + if (!this->header().IsInitialized()) return false; + } + return true; +} + +void RGBDImage::Swap(RGBDImage* other) { + if (other != this) { + std::swap(header_, other->header_); + std::swap(cols_, other->cols_); + std::swap(rows_, other->rows_); + std::swap(step1_, other->step1_); + std::swap(type1_, other->type1_); + std::swap(imagedata1_, other->imagedata1_); + std::swap(step2_, other->step2_); + std::swap(type2_, other->type2_); + std::swap(imagedata2_, other->imagedata2_); + std::swap(camera_config_, other->camera_config_); + std::swap(camera_type_, other->camera_type_); + std::swap(roll_, other->roll_); + std::swap(pitch_, other->pitch_); + std::swap(yaw_, other->yaw_); + std::swap(lon_, other->lon_); + std::swap(lat_, other->lat_); + std::swap(alt_, other->alt_); + std::swap(ground_x_, other->ground_x_); + std::swap(ground_y_, other->ground_y_); + std::swap(ground_z_, other->ground_z_); + camera_matrix_.Swap(&other->camera_matrix_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RGBDImage::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RGBDImage_descriptor_; + metadata.reflection = RGBDImage_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int Waypoint::kXFieldNumber; +const int Waypoint::kYFieldNumber; +const int Waypoint::kZFieldNumber; +const int Waypoint::kRollFieldNumber; +const int Waypoint::kPitchFieldNumber; +const int Waypoint::kYawFieldNumber; +#endif // !_MSC_VER + +Waypoint::Waypoint() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void Waypoint::InitAsDefaultInstance() { +} + +Waypoint::Waypoint(const Waypoint& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void Waypoint::SharedCtor() { + _cached_size_ = 0; + x_ = 0; + y_ = 0; + z_ = 0; + roll_ = 0; + pitch_ = 0; + yaw_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +Waypoint::~Waypoint() { + SharedDtor(); +} + +void Waypoint::SharedDtor() { + if (this != default_instance_) { + } +} + +void Waypoint::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* Waypoint::descriptor() { + protobuf_AssignDescriptorsOnce(); + return Waypoint_descriptor_; +} + +const Waypoint& Waypoint::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_pixhawk_2eproto(); return *default_instance_; +} + +Waypoint* Waypoint::default_instance_ = NULL; + +Waypoint* Waypoint::New() const { + return new Waypoint; +} + +void Waypoint::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + x_ = 0; + y_ = 0; + z_ = 0; + roll_ = 0; + pitch_ = 0; + yaw_ = 0; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool Waypoint::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required double x = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &x_))); + set_has_x(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(17)) goto parse_y; + break; + } + + // required double y = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_y: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &y_))); + set_has_y(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(25)) goto parse_z; + break; + } + + // optional double z = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_z: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &z_))); + set_has_z(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(33)) goto parse_roll; + break; + } + + // optional double roll = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_roll: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &roll_))); + set_has_roll(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(41)) goto parse_pitch; + break; + } + + // optional double pitch = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_pitch: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &pitch_))); + set_has_pitch(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(49)) goto parse_yaw; + break; + } + + // optional double yaw = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_yaw: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &yaw_))); + set_has_yaw(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void Waypoint::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required double x = 1; + if (has_x()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(1, this->x(), output); + } + + // required double y = 2; + if (has_y()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(2, this->y(), output); + } + + // optional double z = 3; + if (has_z()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(3, this->z(), output); + } + + // optional double roll = 4; + if (has_roll()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(4, this->roll(), output); + } + + // optional double pitch = 5; + if (has_pitch()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(5, this->pitch(), output); + } + + // optional double yaw = 6; + if (has_yaw()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->yaw(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* Waypoint::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required double x = 1; + if (has_x()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(1, this->x(), target); + } + + // required double y = 2; + if (has_y()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(2, this->y(), target); + } + + // optional double z = 3; + if (has_z()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(3, this->z(), target); + } + + // optional double roll = 4; + if (has_roll()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(4, this->roll(), target); + } + + // optional double pitch = 5; + if (has_pitch()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(5, this->pitch(), target); + } + + // optional double yaw = 6; + if (has_yaw()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->yaw(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int Waypoint::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required double x = 1; + if (has_x()) { + total_size += 1 + 8; + } + + // required double y = 2; + if (has_y()) { + total_size += 1 + 8; + } + + // optional double z = 3; + if (has_z()) { + total_size += 1 + 8; + } + + // optional double roll = 4; + if (has_roll()) { + total_size += 1 + 8; + } + + // optional double pitch = 5; + if (has_pitch()) { + total_size += 1 + 8; + } + + // optional double yaw = 6; + if (has_yaw()) { + total_size += 1 + 8; + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void Waypoint::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const Waypoint* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void Waypoint::MergeFrom(const Waypoint& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_x()) { + set_x(from.x()); + } + if (from.has_y()) { + set_y(from.y()); + } + if (from.has_z()) { + set_z(from.z()); + } + if (from.has_roll()) { + set_roll(from.roll()); + } + if (from.has_pitch()) { + set_pitch(from.pitch()); + } + if (from.has_yaw()) { + set_yaw(from.yaw()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void Waypoint::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Waypoint::CopyFrom(const Waypoint& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Waypoint::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + return true; +} + +void Waypoint::Swap(Waypoint* other) { + if (other != this) { + std::swap(x_, other->x_); + std::swap(y_, other->y_); + std::swap(z_, other->z_); + std::swap(roll_, other->roll_); + std::swap(pitch_, other->pitch_); + std::swap(yaw_, other->yaw_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata Waypoint::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = Waypoint_descriptor_; + metadata.reflection = Waypoint_reflection_; + return metadata; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace px + +// @@protoc_insertion_point(global_scope) diff --git a/mavlink/share/pyshared/pymavlink/generator/C/test/posix/.gitignore b/mavlink/share/pyshared/pymavlink/generator/C/test/posix/.gitignore new file mode 100644 index 0000000000..7c98650ccf --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/test/posix/.gitignore @@ -0,0 +1,3 @@ +/testmav0.9 +/testmav1.0 +/testmav1.0_nonstrict diff --git a/mavlink/share/pyshared/pymavlink/generator/C/test/posix/Makefile b/mavlink/share/pyshared/pymavlink/generator/C/test/posix/Makefile new file mode 100644 index 0000000000..693150fb77 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/test/posix/Makefile @@ -0,0 +1,31 @@ +CFLAGS = -g -Wall -Werror -Os +TESTPROTOCOL = common +ALLPROTOCOLS = minimal test common pixhawk ardupilotmega slugs ualberta + +all: + for p in ${ALLPROTOCOLS}; do make -f Makefile build TESTPROTOCOL=$$p; done + +test: + for p in ${ALLPROTOCOLS}; do make -f Makefile testprogs TESTPROTOCOL=$$p || exit 1; done + +valgrindtest: + for p in ${ALLPROTOCOLS}; do make -f Makefile valgrindprogs TESTPROTOCOL=$$p || exit 1; done + +build: testmav0.9_${TESTPROTOCOL} testmav1.0_${TESTPROTOCOL} + +testprogs: testmav0.9_${TESTPROTOCOL} testmav1.0_${TESTPROTOCOL} + ./testmav0.9_${TESTPROTOCOL} + ./testmav1.0_${TESTPROTOCOL} + +valgrindprogs: testmav0.9_${TESTPROTOCOL} testmav1.0_${TESTPROTOCOL} + valgrind -q ./testmav0.9_${TESTPROTOCOL} + valgrind -q ./testmav1.0_${TESTPROTOCOL} + +clean: + rm -rf *.o *~ testmav1.0* testmav0.9* + +testmav1.0_${TESTPROTOCOL}: testmav.c + $(CC) $(CFLAGS) -I../../include_v1.0 -I../../include_v1.0/${TESTPROTOCOL} -o $@ testmav.c + +testmav0.9_${TESTPROTOCOL}: testmav.c + $(CC) $(CFLAGS) -I../../include_v0.9 -I../../include_v0.9/${TESTPROTOCOL} -o $@ testmav.c diff --git a/mavlink/share/pyshared/pymavlink/generator/C/test/posix/testmav.c b/mavlink/share/pyshared/pymavlink/generator/C/test/posix/testmav.c new file mode 100644 index 0000000000..2fd7fa378b --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/test/posix/testmav.c @@ -0,0 +1,159 @@ +/* + simple MAVLink testsuite for C + */ +#include +#include +#include +#include +#include + +#define MAVLINK_USE_CONVENIENCE_FUNCTIONS +#define MAVLINK_COMM_NUM_BUFFERS 2 + +// this trick allows us to make mavlink_message_t as small as possible +// for this dialect, which saves some memory +#include +#define MAVLINK_MAX_PAYLOAD_LEN MAVLINK_MAX_DIALECT_PAYLOAD_SIZE + +#include +static mavlink_system_t mavlink_system = {42,11,}; + +#define MAVLINK_ASSERT(x) assert(x) +static void comm_send_ch(mavlink_channel_t chan, uint8_t c); + +static mavlink_message_t last_msg; + +#include +#include + +static unsigned chan_counts[MAVLINK_COMM_NUM_BUFFERS]; + +static const unsigned message_lengths[] = MAVLINK_MESSAGE_LENGTHS; +static unsigned error_count; + +static const mavlink_message_info_t message_info[256] = MAVLINK_MESSAGE_INFO; + +static void print_one_field(mavlink_message_t *msg, const mavlink_field_info_t *f, int idx) +{ +#define PRINT_FORMAT(f, def) (f->print_format?f->print_format:def) + switch (f->type) { + case MAVLINK_TYPE_CHAR: + printf(PRINT_FORMAT(f, "%c"), _MAV_RETURN_char(msg, f->wire_offset+idx*1)); + break; + case MAVLINK_TYPE_UINT8_T: + printf(PRINT_FORMAT(f, "%u"), _MAV_RETURN_uint8_t(msg, f->wire_offset+idx*1)); + break; + case MAVLINK_TYPE_INT8_T: + printf(PRINT_FORMAT(f, "%d"), _MAV_RETURN_int8_t(msg, f->wire_offset+idx*1)); + break; + case MAVLINK_TYPE_UINT16_T: + printf(PRINT_FORMAT(f, "%u"), _MAV_RETURN_uint16_t(msg, f->wire_offset+idx*2)); + break; + case MAVLINK_TYPE_INT16_T: + printf(PRINT_FORMAT(f, "%d"), _MAV_RETURN_int16_t(msg, f->wire_offset+idx*2)); + break; + case MAVLINK_TYPE_UINT32_T: + printf(PRINT_FORMAT(f, "%lu"), (unsigned long)_MAV_RETURN_uint32_t(msg, f->wire_offset+idx*4)); + break; + case MAVLINK_TYPE_INT32_T: + printf(PRINT_FORMAT(f, "%ld"), (long)_MAV_RETURN_int32_t(msg, f->wire_offset+idx*4)); + break; + case MAVLINK_TYPE_UINT64_T: + printf(PRINT_FORMAT(f, "%llu"), (unsigned long long)_MAV_RETURN_uint64_t(msg, f->wire_offset+idx*8)); + break; + case MAVLINK_TYPE_INT64_T: + printf(PRINT_FORMAT(f, "%lld"), (long long)_MAV_RETURN_int64_t(msg, f->wire_offset+idx*8)); + break; + case MAVLINK_TYPE_FLOAT: + printf(PRINT_FORMAT(f, "%f"), (double)_MAV_RETURN_float(msg, f->wire_offset+idx*4)); + break; + case MAVLINK_TYPE_DOUBLE: + printf(PRINT_FORMAT(f, "%f"), _MAV_RETURN_double(msg, f->wire_offset+idx*8)); + break; + } +} + +static void print_field(mavlink_message_t *msg, const mavlink_field_info_t *f) +{ + printf("%s: ", f->name); + if (f->array_length == 0) { + print_one_field(msg, f, 0); + printf(" "); + } else { + unsigned i; + /* print an array */ + if (f->type == MAVLINK_TYPE_CHAR) { + printf("'%.*s'", f->array_length, + f->wire_offset+(const char *)_MAV_PAYLOAD(msg)); + + } else { + printf("[ "); + for (i=0; iarray_length; i++) { + print_one_field(msg, f, i); + if (i < f->array_length) { + printf(", "); + } + } + printf("]"); + } + } + printf(" "); +} + +static void print_message(mavlink_message_t *msg) +{ + const mavlink_message_info_t *m = &message_info[msg->msgid]; + const mavlink_field_info_t *f = m->fields; + unsigned i; + printf("%s { ", m->name); + for (i=0; inum_fields; i++) { + print_field(msg, &f[i]); + } + printf("}\n"); +} + +static void comm_send_ch(mavlink_channel_t chan, uint8_t c) +{ + mavlink_status_t status; + if (mavlink_parse_char(chan, c, &last_msg, &status)) { + print_message(&last_msg); + chan_counts[chan]++; + /* channel 0 gets 3 messages per message, because of + the channel defaults for _pack() and _encode() */ + if (chan == MAVLINK_COMM_0 && status.current_rx_seq != (uint8_t)(chan_counts[chan]*3)) { + printf("Channel 0 sequence mismatch error at packet %u (rx_seq=%u)\n", + chan_counts[chan], status.current_rx_seq); + error_count++; + } else if (chan > MAVLINK_COMM_0 && status.current_rx_seq != (uint8_t)chan_counts[chan]) { + printf("Channel %u sequence mismatch error at packet %u (rx_seq=%u)\n", + (unsigned)chan, chan_counts[chan], status.current_rx_seq); + error_count++; + } + if (message_lengths[last_msg.msgid] != last_msg.len) { + printf("Incorrect message length %u for message %u - expected %u\n", + (unsigned)last_msg.len, (unsigned)last_msg.msgid, message_lengths[last_msg.msgid]); + error_count++; + } + } + if (status.packet_rx_drop_count != 0) { + printf("Parse error at packet %u\n", chan_counts[chan]); + error_count++; + } +} + +int main(void) +{ + mavlink_channel_t chan; + mavlink_test_all(11, 10, &last_msg); + for (chan=MAVLINK_COMM_0; chan<=MAVLINK_COMM_1; chan++) { + printf("Received %u messages on channel %u OK\n", + chan_counts[chan], (unsigned)chan); + } + if (error_count != 0) { + printf("Error count %u\n", error_count); + exit(1); + } + printf("No errors detected\n"); + return 0; +} + diff --git a/mavlink/share/pyshared/pymavlink/generator/C/test/windows/stdafx.cpp b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/stdafx.cpp new file mode 100644 index 0000000000..98b4abf058 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// testmav.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/mavlink/share/pyshared/pymavlink/generator/C/test/windows/stdafx.h b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/stdafx.h new file mode 100644 index 0000000000..47a0d0252b --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/mavlink/share/pyshared/pymavlink/generator/C/test/windows/targetver.h b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/targetver.h new file mode 100644 index 0000000000..90e767bfce --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/mavlink/share/pyshared/pymavlink/generator/C/test/windows/testmav.cpp b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/testmav.cpp new file mode 100644 index 0000000000..aa83cacedd --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/testmav.cpp @@ -0,0 +1,154 @@ +// testmav.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include "stdio.h" +#include "stdint.h" +#include "stddef.h" +#include "assert.h" + + +#define MAVLINK_USE_CONVENIENCE_FUNCTIONS +#define MAVLINK_COMM_NUM_BUFFERS 2 + +#include +static mavlink_system_t mavlink_system = {42,11,}; + +#define MAVLINK_ASSERT(x) assert(x) +static void comm_send_ch(mavlink_channel_t chan, uint8_t c); + +static mavlink_message_t last_msg; + +#include +#include + +static unsigned chan_counts[MAVLINK_COMM_NUM_BUFFERS]; + +static const unsigned message_lengths[] = MAVLINK_MESSAGE_LENGTHS; +static unsigned error_count; + +static const mavlink_message_info_t message_info[256] = MAVLINK_MESSAGE_INFO; + +static void print_one_field(mavlink_message_t *msg, const mavlink_field_info_t *f, int idx) +{ +#define PRINT_FORMAT(f, def) (f->print_format?f->print_format:def) + switch (f->type) { + case MAVLINK_TYPE_CHAR: + printf(PRINT_FORMAT(f, "%c"), _MAV_RETURN_char(msg, f->wire_offset+idx*1)); + break; + case MAVLINK_TYPE_UINT8_T: + printf(PRINT_FORMAT(f, "%u"), _MAV_RETURN_uint8_t(msg, f->wire_offset+idx*1)); + break; + case MAVLINK_TYPE_INT8_T: + printf(PRINT_FORMAT(f, "%d"), _MAV_RETURN_int8_t(msg, f->wire_offset+idx*1)); + break; + case MAVLINK_TYPE_UINT16_T: + printf(PRINT_FORMAT(f, "%u"), _MAV_RETURN_uint16_t(msg, f->wire_offset+idx*2)); + break; + case MAVLINK_TYPE_INT16_T: + printf(PRINT_FORMAT(f, "%d"), _MAV_RETURN_int16_t(msg, f->wire_offset+idx*2)); + break; + case MAVLINK_TYPE_UINT32_T: + printf(PRINT_FORMAT(f, "%lu"), (unsigned long)_MAV_RETURN_uint32_t(msg, f->wire_offset+idx*4)); + break; + case MAVLINK_TYPE_INT32_T: + printf(PRINT_FORMAT(f, "%ld"), (long)_MAV_RETURN_int32_t(msg, f->wire_offset+idx*4)); + break; + case MAVLINK_TYPE_UINT64_T: + printf(PRINT_FORMAT(f, "%llu"), (unsigned long long)_MAV_RETURN_uint64_t(msg, f->wire_offset+idx*8)); + break; + case MAVLINK_TYPE_INT64_T: + printf(PRINT_FORMAT(f, "%lld"), (long long)_MAV_RETURN_int64_t(msg, f->wire_offset+idx*8)); + break; + case MAVLINK_TYPE_FLOAT: + printf(PRINT_FORMAT(f, "%f"), (double)_MAV_RETURN_float(msg, f->wire_offset+idx*4)); + break; + case MAVLINK_TYPE_DOUBLE: + printf(PRINT_FORMAT(f, "%f"), _MAV_RETURN_double(msg, f->wire_offset+idx*8)); + break; + } +} + +static void print_field(mavlink_message_t *msg, const mavlink_field_info_t *f) +{ + printf("%s: ", f->name); + if (f->array_length == 0) { + print_one_field(msg, f, 0); + printf(" "); + } else { + unsigned i; + /* print an array */ + if (f->type == MAVLINK_TYPE_CHAR) { + printf("'%.*s'", f->array_length, + f->wire_offset+(const char *)_MAV_PAYLOAD(msg)); + + } else { + printf("[ "); + for (i=0; iarray_length; i++) { + print_one_field(msg, f, i); + if (i < f->array_length) { + printf(", "); + } + } + printf("]"); + } + } + printf(" "); +} + +static void print_message(mavlink_message_t *msg) +{ + const mavlink_message_info_t *m = &message_info[msg->msgid]; + const mavlink_field_info_t *f = m->fields; + unsigned i; + printf("%s { ", m->name); + for (i=0; inum_fields; i++) { + print_field(msg, &f[i]); + } + printf("}\n"); +} + +static void comm_send_ch(mavlink_channel_t chan, uint8_t c) +{ + mavlink_status_t status; + if (mavlink_parse_char(chan, c, &last_msg, &status)) { + print_message(&last_msg); + chan_counts[chan]++; + /* channel 0 gets 3 messages per message, because of + the channel defaults for _pack() and _encode() */ + if (chan == MAVLINK_COMM_0 && status.current_rx_seq != (uint8_t)(chan_counts[chan]*3)) { + printf("Channel 0 sequence mismatch error at packet %u (rx_seq=%u)\n", + chan_counts[chan], status.current_rx_seq); + error_count++; + } else if (chan > MAVLINK_COMM_0 && status.current_rx_seq != (uint8_t)chan_counts[chan]) { + printf("Channel %u sequence mismatch error at packet %u (rx_seq=%u)\n", + (unsigned)chan, chan_counts[chan], status.current_rx_seq); + error_count++; + } + if (message_lengths[last_msg.msgid] != last_msg.len) { + printf("Incorrect message length %u for message %u - expected %u\n", + (unsigned)last_msg.len, (unsigned)last_msg.msgid, message_lengths[last_msg.msgid]); + error_count++; + } + } + if (status.packet_rx_drop_count != 0) { + printf("Parse error at packet %u\n", chan_counts[chan]); + error_count++; + } +} + +int _tmain(int argc, _TCHAR* argv[]) +{ + int chan; + mavlink_test_all(11, 10, &last_msg); + for (chan=MAVLINK_COMM_0; chan<=MAVLINK_COMM_1; chan++) { + printf("Received %u messages on channel %u OK\n", + chan_counts[chan], (unsigned)chan); + } + if (error_count != 0) { + printf("Error count %u\n", error_count); + return(1); + } + printf("No errors detected\n"); + return 0; +} diff --git a/mavlink/share/pyshared/pymavlink/generator/C/test/windows/testmav.sln b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/testmav.sln new file mode 100644 index 0000000000..37a3056979 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/testmav.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testmav", "testmav\testmav.vcxproj", "{02C30EBC-DF41-4C36-B2F3-79BED7E6EF9F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {02C30EBC-DF41-4C36-B2F3-79BED7E6EF9F}.Debug|Win32.ActiveCfg = Debug|Win32 + {02C30EBC-DF41-4C36-B2F3-79BED7E6EF9F}.Debug|Win32.Build.0 = Debug|Win32 + {02C30EBC-DF41-4C36-B2F3-79BED7E6EF9F}.Release|Win32.ActiveCfg = Release|Win32 + {02C30EBC-DF41-4C36-B2F3-79BED7E6EF9F}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/mavlink/share/pyshared/pymavlink/generator/C/test/windows/testmav.suo b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/testmav.suo new file mode 100644 index 0000000000..9b2e18cff6 Binary files /dev/null and b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/testmav.suo differ diff --git a/mavlink/share/pyshared/pymavlink/generator/C/test/windows/testmav.vcxproj b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/testmav.vcxproj new file mode 100644 index 0000000000..7181b3a41f --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/C/test/windows/testmav.vcxproj @@ -0,0 +1,91 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {02C30EBC-DF41-4C36-B2F3-79BED7E6EF9F} + Win32Proj + testmav + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + E:\pymavlink\generator\C\include_v1.0 + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mavlink/share/pyshared/pymavlink/generator/gen_MatrixPilot.py b/mavlink/share/pyshared/pymavlink/generator/gen_MatrixPilot.py new file mode 100644 index 0000000000..165c1b343b --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/gen_MatrixPilot.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +''' +Use mavgen.py matrixpilot.xml definitions to generate +C and Python MAVLink routines for sending and parsing the protocol +This python script is soley for MatrixPilot MAVLink impoementation + +Copyright Pete Hollands 2011 +Released under GNU GPL version 3 or later +''' + +import os, sys, glob, re +from shutil import copy +from mavgen import mavgen + +# allow import from the parent directory, where mavutil.py is +# Under Windows, this script must be run from a DOS command window +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +class options: + """ a class to simulate the options of mavgen OptionsParser""" + def __init__(self, lang, output, wire_protocol): + self.language = lang + self.wire_protocol = wire_protocol + self.output = output + +def remove_include_files(target_directory): + search_pattern = target_directory+'/*.h' + print "search pattern is", search_pattern + files_to_remove = glob.glob(search_pattern) + for afile in files_to_remove : + try: + print "removing", afile + os.remove(afile) + except: + print "error while trying to remove", afile + +def copy_include_files(source_directory,target_directory): + search_pattern = source_directory+'/*.h' + files_to_copy = glob.glob(search_pattern) + for afile in files_to_copy: + basename = os.path.basename(afile) + print "Copying ...", basename + copy(afile, target_directory) + +protocol = "1.0" + +xml_directory = './message_definitions/v'+protocol +print "xml_directory is", xml_directory +xml_file_names = [] +xml_file_names.append(xml_directory+"/"+"matrixpilot.xml") + +for xml_file in xml_file_names: + print "xml file is ", xml_file + opts = options(lang = "C", output = "C/include_v"+protocol, \ + wire_protocol=protocol) + args = [] + args.append(xml_file) + mavgen(opts, args) + xml_file_base = os.path.basename(xml_file) + xml_file_base = re.sub("\.xml","", xml_file_base) + print "xml_file_base is", xml_file_base + opts = options(lang = "python", \ + output="python/mavlink_"+xml_file_base+"_v"+protocol+".py", \ + wire_protocol=protocol) + mavgen(opts,args) + +mavlink_directory_list = ["common","matrixpilot"] +for mavlink_directory in mavlink_directory_list : + # Look specifically for MatrixPilot directory structure + target_directory = "../../../../MAVLink/include/"+mavlink_directory + source_directory = "C/include_v"+protocol+"/"+mavlink_directory + if os.access(source_directory, os.R_OK): + if os.access(target_directory, os.W_OK): + print "Preparing to copy over files..." + print "About to remove all files in",target_directory + print "OK to continue ?[Yes / No]: ", + line = sys.stdin.readline() + if line == "Yes\n" or line == "yes\n" \ + or line == "Y\n" or line == "y\n": + print "passed" + remove_include_files(target_directory) + copy_include_files(source_directory,target_directory) + print "Finished copying over include files" + else : + print "Your answer is No. Exiting Program" + sys.exit() + else : + print "Cannot find " + target_directory + "in MatrixPilot" + sys.exit() + else: + print "Could not find files to copy at", source_directory + print "Exiting Program." + sys.exit() diff --git a/mavlink/share/pyshared/pymavlink/generator/gen_all.py b/mavlink/share/pyshared/pymavlink/generator/gen_all.py new file mode 100644 index 0000000000..5b24f85cbb --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/gen_all.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +''' +Use mavgen.py on all available MAVLink XML definitions to generate +C and Python MAVLink routines for sending and parsing the protocol + +Copyright Pete Hollands 2011 +Released under GNU GPL version 3 or later +''' + +import os, sys, glob, re +from mavgen import mavgen + +# allow import from the parent directory, where mavutil.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +class options: + """ a class to simulate the options of mavgen OptionsParser""" + def __init__(self, lang, output, wire_protocol): + self.language = lang + self.wire_protocol = wire_protocol + self.output = output + +protocols = [ '0.9', '1.0' ] + +for protocol in protocols : + xml_directory = './message_definitions/v'+protocol + print "xml_directory is", xml_directory + xml_file_names = glob.glob(xml_directory+'/*.xml') + + for xml_file in xml_file_names: + print "xml file is ", xml_file + opts = options(lang = "C", output = "C/include_v"+protocol, \ + wire_protocol=protocol) + args = [] + args.append(xml_file) + mavgen(opts, args) + xml_file_base = os.path.basename(xml_file) + xml_file_base = re.sub("\.xml","", xml_file_base) + print "xml_file_base is", xml_file_base + opts = options(lang = "python", \ + output="python/mavlink_"+xml_file_base+"_v"+protocol+".py", \ + wire_protocol=protocol) + mavgen(opts,args) diff --git a/mavlink/share/pyshared/pymavlink/generator/gen_all.sh b/mavlink/share/pyshared/pymavlink/generator/gen_all.sh new file mode 100644 index 0000000000..e8dafedc58 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/gen_all.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +for protocol in 0.9 1.0; do + for xml in message_definitions/v$protocol/*.xml; do + base=$(basename $xml .xml) + ./mavgen.py --lang=C --wire-protocol=$protocol --output=C/include_v$protocol $xml || exit 1 + ./mavgen.py --lang=python --wire-protocol=$protocol --output=python/mavlink_${base}_v$protocol.py $xml || exit 1 + done +done + +cp -f python/mavlink_ardupilotmega_v0.9.py ../mavlink.py +cp -f python/mavlink_ardupilotmega_v1.0.py ../mavlinkv10.py diff --git a/mavlink/share/pyshared/pymavlink/generator/mavgen.py b/mavlink/share/pyshared/pymavlink/generator/mavgen.py new file mode 100644 index 0000000000..05f71f778d --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/mavgen.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +''' +parse a MAVLink protocol XML file and generate a python implementation + +Copyright Andrew Tridgell 2011 +Released under GNU GPL version 3 or later +''' + +def mavgen(opts, args) : + """Generate mavlink message formatters and parsers (C and Python ) using options + and args where args are a list of xml files. This function allows python + scripts under Windows to control mavgen using the same interface as + shell scripts under Unix""" + import sys, textwrap, os + + import mavparse + import mavgen_python + import mavgen_c + + xml = [] + + for fname in args: + print("Parsing %s" % fname) + xml.append(mavparse.MAVXML(fname, opts.wire_protocol)) + + # expand includes + for x in xml[:]: + for i in x.include: + fname = os.path.join(os.path.dirname(x.filename), i) + print("Parsing %s" % fname) + xml.append(mavparse.MAVXML(fname, opts.wire_protocol)) + + # include message lengths and CRCs too + for idx in range(0, 256): + if x.message_lengths[idx] == 0: + x.message_lengths[idx] = xml[-1].message_lengths[idx] + x.message_crcs[idx] = xml[-1].message_crcs[idx] + x.message_names[idx] = xml[-1].message_names[idx] + + # work out max payload size across all includes + largest_payload = 0 + for x in xml: + if x.largest_payload > largest_payload: + largest_payload = x.largest_payload + for x in xml: + x.largest_payload = largest_payload + + if mavparse.check_duplicates(xml): + sys.exit(1) + + print("Found %u MAVLink message types in %u XML files" % ( + mavparse.total_msgs(xml), len(xml))) + + if opts.language == 'python': + mavgen_python.generate(opts.output, xml) + elif opts.language == 'C': + mavgen_c.generate(opts.output, xml) + else: + print("Unsupported language %s" % opts.language) + + +if __name__=="__main__": + import sys, textwrap, os + + from optparse import OptionParser + + # allow import from the parent directory, where mavutil.py is + sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + + import mavparse + import mavgen_python + import mavgen_c + + parser = OptionParser("%prog [options] ") + parser.add_option("-o", "--output", dest="output", default="mavlink", help="output directory.") + parser.add_option("--lang", dest="language", default="python", help="language of generated code: 'Python' or 'C' [default: %default]") + parser.add_option("--wire-protocol", dest="wire_protocol", default=mavparse.PROTOCOL_0_9, help="MAVLink protocol version: '0.9' or '1.0'. [default: %default]") + (opts, args) = parser.parse_args() + + if len(args) < 1: + parser.error("You must supply at least one MAVLink XML protocol definition") + mavgen(opts, args) diff --git a/mavlink/share/pyshared/pymavlink/generator/mavgen_c.py b/mavlink/share/pyshared/pymavlink/generator/mavgen_c.py new file mode 100644 index 0000000000..255919f0d4 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/mavgen_c.py @@ -0,0 +1,581 @@ +#!/usr/bin/env python +''' +parse a MAVLink protocol XML file and generate a C implementation + +Copyright Andrew Tridgell 2011 +Released under GNU GPL version 3 or later +''' + +import sys, textwrap, os, time +import mavparse, mavtemplate + +t = mavtemplate.MAVTemplate() + +def generate_version_h(directory, xml): + '''generate version.h''' + f = open(os.path.join(directory, "version.h"), mode='w') + t.write(f,''' +/** @file + * @brief MAVLink comm protocol built from ${basename}.xml + * @see http://pixhawk.ethz.ch/software/mavlink + */ +#ifndef MAVLINK_VERSION_H +#define MAVLINK_VERSION_H + +#define MAVLINK_BUILD_DATE "${parse_time}" +#define MAVLINK_WIRE_PROTOCOL_VERSION "${wire_protocol_version}" +#define MAVLINK_MAX_DIALECT_PAYLOAD_SIZE ${largest_payload} + +#endif // MAVLINK_VERSION_H +''', xml) + f.close() + +def generate_mavlink_h(directory, xml): + '''generate mavlink.h''' + f = open(os.path.join(directory, "mavlink.h"), mode='w') + t.write(f,''' +/** @file + * @brief MAVLink comm protocol built from ${basename}.xml + * @see http://pixhawk.ethz.ch/software/mavlink + */ +#ifndef MAVLINK_H +#define MAVLINK_H + +#ifndef MAVLINK_STX +#define MAVLINK_STX ${protocol_marker} +#endif + +#ifndef MAVLINK_ENDIAN +#define MAVLINK_ENDIAN ${mavlink_endian} +#endif + +#ifndef MAVLINK_ALIGNED_FIELDS +#define MAVLINK_ALIGNED_FIELDS ${aligned_fields_define} +#endif + +#ifndef MAVLINK_CRC_EXTRA +#define MAVLINK_CRC_EXTRA ${crc_extra_define} +#endif + +#include "version.h" +#include "${basename}.h" + +#endif // MAVLINK_H +''', xml) + f.close() + +def generate_main_h(directory, xml): + '''generate main header per XML file''' + f = open(os.path.join(directory, xml.basename + ".h"), mode='w') + t.write(f, ''' +/** @file + * @brief MAVLink comm protocol generated from ${basename}.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef ${basename_upper}_H +#define ${basename_upper}_H + +#ifdef __cplusplus +extern "C" { +#endif + +// MESSAGE LENGTHS AND CRCS + +#ifndef MAVLINK_MESSAGE_LENGTHS +#define MAVLINK_MESSAGE_LENGTHS {${message_lengths_array}} +#endif + +#ifndef MAVLINK_MESSAGE_CRCS +#define MAVLINK_MESSAGE_CRCS {${message_crcs_array}} +#endif + +#ifndef MAVLINK_MESSAGE_INFO +#define MAVLINK_MESSAGE_INFO {${message_info_array}} +#endif + +#include "../protocol.h" + +#define MAVLINK_ENABLED_${basename_upper} + +${{include_list:#include "../${base}/${base}.h" +}} + +// MAVLINK VERSION + +#ifndef MAVLINK_VERSION +#define MAVLINK_VERSION ${version} +#endif + +#if (MAVLINK_VERSION == 0) +#undef MAVLINK_VERSION +#define MAVLINK_VERSION ${version} +#endif + +// ENUM DEFINITIONS + +${{enum: +/** @brief ${description} */ +#ifndef HAVE_ENUM_${name} +#define HAVE_ENUM_${name} +enum ${name} +{ +${{entry: ${name}=${value}, /* ${description} |${{param:${description}| }} */ +}} +}; +#endif +}} + +// MESSAGE DEFINITIONS +${{message:#include "./mavlink_msg_${name_lower}.h" +}} + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // ${basename_upper}_H +''', xml) + + f.close() + + +def generate_message_h(directory, m): + '''generate per-message header for a XML file''' + f = open(os.path.join(directory, 'mavlink_msg_%s.h' % m.name_lower), mode='w') + t.write(f, ''' +// MESSAGE ${name} PACKING + +#define MAVLINK_MSG_ID_${name} ${id} + +typedef struct __mavlink_${name_lower}_t +{ +${{ordered_fields: ${type} ${name}${array_suffix}; ///< ${description} +}} +} mavlink_${name_lower}_t; + +#define MAVLINK_MSG_ID_${name}_LEN ${wire_length} +#define MAVLINK_MSG_ID_${id}_LEN ${wire_length} + +${{array_fields:#define MAVLINK_MSG_${msg_name}_FIELD_${name_upper}_LEN ${array_length} +}} + +#define MAVLINK_MESSAGE_INFO_${name} { \\ + "${name}", \\ + ${num_fields}, \\ + { ${{ordered_fields: { "${name}", ${c_print_format}, MAVLINK_TYPE_${type_upper}, ${array_length}, ${wire_offset}, offsetof(mavlink_${name_lower}_t, ${name}) }, \\ + }} } \\ +} + + +/** + * @brief Pack a ${name_lower} message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * +${{arg_fields: * @param ${name} ${description} +}} + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_${name_lower}_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + ${{arg_fields: ${array_const}${type} ${array_prefix}${name},}}) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[${wire_length}]; +${{scalar_fields: _mav_put_${type}(buf, ${wire_offset}, ${putname}); +}} +${{array_fields: _mav_put_${type}_array(buf, ${wire_offset}, ${name}, ${array_length}); +}} + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, ${wire_length}); +#else + mavlink_${name_lower}_t packet; +${{scalar_fields: packet.${name} = ${putname}; +}} +${{array_fields: mav_array_memcpy(packet.${name}, ${name}, sizeof(${type})*${array_length}); +}} + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, ${wire_length}); +#endif + + msg->msgid = MAVLINK_MSG_ID_${name}; + return mavlink_finalize_message(msg, system_id, component_id, ${wire_length}${crc_extra_arg}); +} + +/** + * @brief Pack a ${name_lower} message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into +${{arg_fields: * @param ${name} ${description} +}} + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_${name_lower}_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + ${{arg_fields:${array_const}${type} ${array_prefix}${name},}}) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[${wire_length}]; +${{scalar_fields: _mav_put_${type}(buf, ${wire_offset}, ${putname}); +}} +${{array_fields: _mav_put_${type}_array(buf, ${wire_offset}, ${name}, ${array_length}); +}} + memcpy(_MAV_PAYLOAD_NON_CONST(msg), buf, ${wire_length}); +#else + mavlink_${name_lower}_t packet; +${{scalar_fields: packet.${name} = ${putname}; +}} +${{array_fields: mav_array_memcpy(packet.${name}, ${name}, sizeof(${type})*${array_length}); +}} + memcpy(_MAV_PAYLOAD_NON_CONST(msg), &packet, ${wire_length}); +#endif + + msg->msgid = MAVLINK_MSG_ID_${name}; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, ${wire_length}${crc_extra_arg}); +} + +/** + * @brief Encode a ${name_lower} struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param ${name_lower} C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_${name_lower}_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_${name_lower}_t* ${name_lower}) +{ + return mavlink_msg_${name_lower}_pack(system_id, component_id, msg,${{arg_fields: ${name_lower}->${name},}}); +} + +/** + * @brief Send a ${name_lower} message + * @param chan MAVLink channel to send the message + * +${{arg_fields: * @param ${name} ${description} +}} + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_${name_lower}_send(mavlink_channel_t chan,${{arg_fields: ${array_const}${type} ${array_prefix}${name},}}) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[${wire_length}]; +${{scalar_fields: _mav_put_${type}(buf, ${wire_offset}, ${putname}); +}} +${{array_fields: _mav_put_${type}_array(buf, ${wire_offset}, ${name}, ${array_length}); +}} + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_${name}, buf, ${wire_length}${crc_extra_arg}); +#else + mavlink_${name_lower}_t packet; +${{scalar_fields: packet.${name} = ${putname}; +}} +${{array_fields: mav_array_memcpy(packet.${name}, ${name}, sizeof(${type})*${array_length}); +}} + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_${name}, (const char *)&packet, ${wire_length}${crc_extra_arg}); +#endif +} + +#endif + +// MESSAGE ${name} UNPACKING + +${{fields: +/** + * @brief Get field ${name} from ${name_lower} message + * + * @return ${description} + */ +static inline ${return_type} mavlink_msg_${name_lower}_get_${name}(const mavlink_message_t* msg${get_arg}) +{ + return _MAV_RETURN_${type}${array_tag}(msg, ${array_return_arg} ${wire_offset}); +} +}} + +/** + * @brief Decode a ${name_lower} message into a struct + * + * @param msg The message to decode + * @param ${name_lower} C-struct to decode the message contents into + */ +static inline void mavlink_msg_${name_lower}_decode(const mavlink_message_t* msg, mavlink_${name_lower}_t* ${name_lower}) +{ +#if MAVLINK_NEED_BYTE_SWAP +${{ordered_fields: ${decode_left}mavlink_msg_${name_lower}_get_${name}(msg${decode_right}); +}} +#else + memcpy(${name_lower}, _MAV_PAYLOAD(msg), ${wire_length}); +#endif +} +''', m) + f.close() + + +def generate_testsuite_h(directory, xml): + '''generate testsuite.h per XML file''' + f = open(os.path.join(directory, "testsuite.h"), mode='w') + t.write(f, ''' +/** @file + * @brief MAVLink comm protocol testsuite generated from ${basename}.xml + * @see http://qgroundcontrol.org/mavlink/ + */ +#ifndef ${basename_upper}_TESTSUITE_H +#define ${basename_upper}_TESTSUITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAVLINK_TEST_ALL +#define MAVLINK_TEST_ALL +${{include_list:static void mavlink_test_${base}(uint8_t, uint8_t, mavlink_message_t *last_msg); +}} +static void mavlink_test_${basename}(uint8_t, uint8_t, mavlink_message_t *last_msg); + +static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ +${{include_list: mavlink_test_${base}(system_id, component_id, last_msg); +}} + mavlink_test_${basename}(system_id, component_id, last_msg); +} +#endif + +${{include_list:#include "../${base}/testsuite.h" +}} + +${{message: +static void mavlink_test_${name_lower}(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_${name_lower}_t packet_in = { + ${{ordered_fields:${c_test_value}, + }}}; + mavlink_${name_lower}_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + ${{scalar_fields: packet1.${name} = packet_in.${name}; + }} + ${{array_fields: mav_array_memcpy(packet1.${name}, packet_in.${name}, sizeof(${type})*${array_length}); + }} + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_${name_lower}_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_${name_lower}_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_${name_lower}_pack(system_id, component_id, &msg ${{arg_fields:, packet1.${name} }}); + mavlink_msg_${name_lower}_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_${name_lower}_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg ${{arg_fields:, packet1.${name} }}); + mavlink_msg_${name_lower}_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; i= 1 and self.buf[0] != ${protocol_marker}: + magic = self.buf[0] + self.buf = self.buf[1:] + if self.robust_parsing: + m = MAVLink_bad_data(chr(magic), "Bad prefix") + if self.callback: + self.callback(m, *self.callback_args, **self.callback_kwargs) + self.expected_length = 6 + self.total_receive_errors += 1 + return m + if self.have_prefix_error: + return None + self.have_prefix_error = True + self.total_receive_errors += 1 + raise MAVError("invalid MAVLink prefix '%s'" % magic) + self.have_prefix_error = False + if len(self.buf) >= 2: + (magic, self.expected_length) = struct.unpack('BB', self.buf[0:2]) + self.expected_length += 8 + if self.expected_length >= 8 and len(self.buf) >= self.expected_length: + mbuf = self.buf[0:self.expected_length] + self.buf = self.buf[self.expected_length:] + self.expected_length = 6 + if self.robust_parsing: + try: + m = self.decode(mbuf) + self.total_packets_received += 1 + except MAVError as reason: + m = MAVLink_bad_data(mbuf, reason.message) + self.total_receive_errors += 1 + else: + m = self.decode(mbuf) + self.total_packets_received += 1 + if self.callback: + self.callback(m, *self.callback_args, **self.callback_kwargs) + return m + return None + + def parse_buffer(self, s): + '''input some data bytes, possibly returning a list of new messages''' + m = self.parse_char(s) + if m is None: + return None + ret = [m] + while True: + m = self.parse_char("") + if m is None: + return ret + ret.append(m) + return ret + + def decode(self, msgbuf): + '''decode a buffer as a MAVLink message''' + # decode the header + try: + magic, mlen, seq, srcSystem, srcComponent, msgId = struct.unpack('cBBBBB', msgbuf[:6]) + except struct.error as emsg: + raise MAVError('Unable to unpack MAVLink header: %s' % emsg) + if ord(magic) != ${protocol_marker}: + raise MAVError("invalid MAVLink prefix '%s'" % magic) + if mlen != len(msgbuf)-8: + raise MAVError('invalid MAVLink message length. Got %u expected %u, msgId=%u' % (len(msgbuf)-8, mlen, msgId)) + + if not msgId in mavlink_map: + raise MAVError('unknown MAVLink message ID %u' % msgId) + + # decode the payload + (fmt, type, order_map, crc_extra) = mavlink_map[msgId] + + # decode the checksum + try: + crc, = struct.unpack(' self.enum[-1].highest_value): + self.enum[-1].highest_value = value + self.enum[-1].entry.append(MAVEnumEntry(attrs['name'], value)) + elif in_element == "mavlink.enums.enum.entry.param": + check_attrs(attrs, ['index'], 'enum param') + self.enum[-1].entry[-1].param.append(MAVEnumParam(attrs['index'])) + + def end_element(name): + in_element = '.'.join(in_element_list) + if in_element == "mavlink.enums.enum": + # add a ENUM_END + self.enum[-1].entry.append(MAVEnumEntry("%s_ENUM_END" % self.enum[-1].name, + self.enum[-1].highest_value+1, end_marker=True)) + in_element_list.pop() + + def char_data(data): + in_element = '.'.join(in_element_list) + if in_element == "mavlink.messages.message.description": + self.message[-1].description += data + elif in_element == "mavlink.messages.message.field": + self.message[-1].fields[-1].description += data + elif in_element == "mavlink.enums.enum.description": + self.enum[-1].description += data + elif in_element == "mavlink.enums.enum.entry.description": + self.enum[-1].entry[-1].description += data + elif in_element == "mavlink.enums.enum.entry.param": + self.enum[-1].entry[-1].param[-1].description += data + elif in_element == "mavlink.version": + self.version = int(data) + elif in_element == "mavlink.include": + self.include.append(data) + + f = open(filename, mode='rb') + p = xml.parsers.expat.ParserCreate() + p.StartElementHandler = start_element + p.EndElementHandler = end_element + p.CharacterDataHandler = char_data + p.ParseFile(f) + f.close() + + self.message_lengths = [ 0 ] * 256 + self.message_crcs = [ 0 ] * 256 + self.message_names = [ None ] * 256 + self.largest_payload = 0 + + for m in self.message: + m.wire_length = 0 + m.fieldnames = [] + m.ordered_fieldnames = [] + if self.sort_fields: + m.ordered_fields = sorted(m.fields, + key=operator.attrgetter('type_length'), + reverse=True) + else: + m.ordered_fields = m.fields + for f in m.fields: + m.fieldnames.append(f.name) + for f in m.ordered_fields: + f.wire_offset = m.wire_length + m.wire_length += f.wire_length + m.ordered_fieldnames.append(f.name) + f.set_test_value() + m.num_fields = len(m.fieldnames) + if m.num_fields > 64: + raise MAVParseError("num_fields=%u : Maximum number of field names allowed is" % ( + m.num_fields, 64)) + m.crc_extra = message_checksum(m) + self.message_lengths[m.id] = m.wire_length + self.message_names[m.id] = m.name + self.message_crcs[m.id] = m.crc_extra + if m.wire_length > self.largest_payload: + self.largest_payload = m.wire_length + + if m.wire_length+8 > 64: + print("Note: message %s is longer than 64 bytes long (%u bytes), which can cause fragmentation since many radio modems use 64 bytes as maximum air transfer unit." % (m.name, m.wire_length+8)) + + def __str__(self): + return "MAVXML for %s from %s (%u message, %u enums)" % ( + self.basename, self.filename, len(self.message), len(self.enum)) + + +def message_checksum(msg): + '''calculate a 8-bit checksum of the key fields of a message, so we + can detect incompatible XML changes''' + crc = mavutil.x25crc(msg.name + ' ') + for f in msg.ordered_fields: + crc.accumulate(f.type + ' ') + crc.accumulate(f.name + ' ') + if f.array_length: + crc.accumulate(chr(f.array_length)) + return (crc.crc&0xFF) ^ (crc.crc>>8) + +def merge_enums(xml): + '''merge enums between XML files''' + emap = {} + for x in xml: + newenums = [] + for enum in x.enum: + if enum.name in emap: + emap[enum.name].entry.pop() # remove end marker + emap[enum.name].entry.extend(enum.entry) + print("Merged enum %s" % enum.name) + else: + newenums.append(enum) + emap[enum.name] = enum + x.enum = newenums + # sort by value + for e in emap: + emap[e].entry = sorted(emap[e].entry, + key=operator.attrgetter('value'), + reverse=False) + + +def check_duplicates(xml): + '''check for duplicate message IDs''' + + merge_enums(xml) + + msgmap = {} + enummap = {} + for x in xml: + for m in x.message: + if m.id in msgmap: + print("ERROR: Duplicate message id %u for %s (%s:%u) also used by %s" % ( + m.id, m.name, + x.filename, m.linenumber, + msgmap[m.id])) + return True + fieldset = set() + for f in m.fields: + if f.name in fieldset: + print("ERROR: Duplicate field %s in message %s (%s:%u)" % ( + f.name, m.name, + x.filename, m.linenumber)) + return True + fieldset.add(f.name) + msgmap[m.id] = '%s (%s:%u)' % (m.name, x.filename, m.linenumber) + for enum in x.enum: + for entry in enum.entry: + s1 = "%s.%s" % (enum.name, entry.name) + s2 = "%s.%s" % (enum.name, entry.value) + if s1 in enummap or s2 in enummap: + print("ERROR: Duplicate enums %s/%s at %s:%u and %s" % ( + s1, entry.value, x.filename, enum.linenumber, + enummap.get(s1) or enummap.get(s2))) + return True + enummap[s1] = "%s:%u" % (x.filename, enum.linenumber) + enummap[s2] = "%s:%u" % (x.filename, enum.linenumber) + + return False + + + +def total_msgs(xml): + '''count total number of msgs''' + count = 0 + for x in xml: + count += len(x.message) + return count + +def mkdir_p(dir): + try: + os.makedirs(dir) + except OSError as exc: + if exc.errno == errno.EEXIST: + pass + else: raise + +# check version consistent +# add test.xml +# finish test suite +# printf style error macro, if defined call errors diff --git a/mavlink/share/pyshared/pymavlink/generator/mavtemplate.py b/mavlink/share/pyshared/pymavlink/generator/mavtemplate.py new file mode 100644 index 0000000000..6ef0153150 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/mavtemplate.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +''' +simple templating system for mavlink generator + +Copyright Andrew Tridgell 2011 +Released under GNU GPL version 3 or later +''' + +from mavparse import MAVParseError + +class MAVTemplate(object): + '''simple templating system''' + def __init__(self, + start_var_token="${", + end_var_token="}", + start_rep_token="${{", + end_rep_token="}}", + trim_leading_lf=True, + checkmissing=True): + self.start_var_token = start_var_token + self.end_var_token = end_var_token + self.start_rep_token = start_rep_token + self.end_rep_token = end_rep_token + self.trim_leading_lf = trim_leading_lf + self.checkmissing = checkmissing + + def find_end(self, text, start_token, end_token): + '''find the of a token. + Returns the offset in the string immediately after the matching end_token''' + if not text.startswith(start_token): + raise MAVParseError("invalid token start") + offset = len(start_token) + nesting = 1 + while nesting > 0: + idx1 = text[offset:].find(start_token) + idx2 = text[offset:].find(end_token) + if idx1 == -1 and idx2 == -1: + raise MAVParseError("token nesting error") + if idx1 == -1 or idx1 > idx2: + offset += idx2 + len(end_token) + nesting -= 1 + else: + offset += idx1 + len(start_token) + nesting += 1 + return offset + + def find_var_end(self, text): + '''find the of a variable''' + return self.find_end(text, self.start_var_token, self.end_var_token) + + def find_rep_end(self, text): + '''find the of a repitition''' + return self.find_end(text, self.start_rep_token, self.end_rep_token) + + def substitute(self, text, subvars={}, + trim_leading_lf=None, checkmissing=None): + '''substitute variables in a string''' + + if trim_leading_lf is None: + trim_leading_lf = self.trim_leading_lf + if checkmissing is None: + checkmissing = self.checkmissing + + # handle repititions + while True: + subidx = text.find(self.start_rep_token) + if subidx == -1: + break + endidx = self.find_rep_end(text[subidx:]) + if endidx == -1: + raise MAVParseError("missing end macro in %s" % text[subidx:]) + part1 = text[0:subidx] + part2 = text[subidx+len(self.start_rep_token):subidx+(endidx-len(self.end_rep_token))] + part3 = text[subidx+endidx:] + a = part2.split(':') + field_name = a[0] + rest = ':'.join(a[1:]) + v = getattr(subvars, field_name, None) + if v is None: + raise MAVParseError('unable to find field %s' % field_name) + t1 = part1 + for f in v: + t1 += self.substitute(rest, f, trim_leading_lf=False, checkmissing=False) + if len(v) != 0 and t1[-1] in ["\n", ","]: + t1 = t1[:-1] + t1 += part3 + text = t1 + + if trim_leading_lf: + if text[0] == '\n': + text = text[1:] + while True: + idx = text.find(self.start_var_token) + if idx == -1: + return text + endidx = text[idx:].find(self.end_var_token) + if endidx == -1: + raise MAVParseError('missing end of variable: %s' % text[idx:idx+10]) + varname = text[idx+2:idx+endidx] + if isinstance(subvars, dict): + if not varname in subvars: + if checkmissing: + raise MAVParseError("unknown variable in '%s%s%s'" % ( + self.start_var_token, varname, self.end_var_token)) + return text[0:idx+endidx] + self.substitute(text[idx+endidx:], subvars, + trim_leading_lf=False, checkmissing=False) + value = subvars[varname] + else: + value = getattr(subvars, varname, None) + if value is None: + if checkmissing: + raise MAVParseError("unknown variable in '%s%s%s'" % ( + self.start_var_token, varname, self.end_var_token)) + return text[0:idx+endidx] + self.substitute(text[idx+endidx:], subvars, + trim_leading_lf=False, checkmissing=False) + text = text.replace("%s%s%s" % (self.start_var_token, varname, self.end_var_token), str(value)) + return text + + def write(self, file, text, subvars={}, trim_leading_lf=True): + '''write to a file with variable substitution''' + file.write(self.substitute(text, subvars=subvars, trim_leading_lf=trim_leading_lf)) diff --git a/mavlink/share/pyshared/pymavlink/generator/mavtestgen.py b/mavlink/share/pyshared/pymavlink/generator/mavtestgen.py new file mode 100644 index 0000000000..faffa1c194 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/generator/mavtestgen.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +''' +generate a MAVLink test suite + +Copyright Andrew Tridgell 2011 +Released under GNU GPL version 3 or later +''' + +import sys, textwrap +from optparse import OptionParser + +# mavparse is up a directory level +sys.path.append('..') +import mavparse + +def gen_value(f, i, language): + '''generate a test value for the ith field of a message''' + type = f.type + + # could be an array + if type.find("[") != -1: + aidx = type.find("[") + basetype = type[0:aidx] + if basetype == "array": + basetype = "int8_t" + if language == 'C': + return '(const %s *)"%s%u"' % (basetype, f.name, i) + return '"%s%u"' % (f.name, i) + + if type == 'float': + return 17.0 + i*7 + if type == 'char': + return 'A' + i + if type == 'int8_t': + return 5 + i + if type in ['int8_t', 'uint8_t']: + return 5 + i + if type in ['uint8_t_mavlink_version']: + return 2 + if type in ['int16_t', 'uint16_t']: + return 17235 + i*52 + if type in ['int32_t', 'uint32_t']: + v = 963497464 + i*52 + if language == 'C': + return "%sL" % v + return v + if type in ['int64_t', 'uint64_t']: + v = 9223372036854775807 + i*63 + if language == 'C': + return "%sLL" % v + return v + + + +def generate_methods_python(outf, msgs): + outf.write(""" +''' +MAVLink protocol test implementation (auto-generated by mavtestgen.py) + +Generated from: %s + +Note: this file has been auto-generated. DO NOT EDIT +''' + +import mavlink + +def generate_outputs(mav): + '''generate all message types as outputs''' +""") + for m in msgs: + if m.name == "HEARTBEAT": continue + outf.write("\tmav.%s_send(" % m.name.lower()) + for i in range(0, len(m.fields)): + f = m.fields[i] + outf.write("%s=%s" % (f.name, gen_value(f, i, 'py'))) + if i != len(m.fields)-1: + outf.write(",") + outf.write(")\n") + + +def generate_methods_C(outf, msgs): + outf.write(""" +/* +MAVLink protocol test implementation (auto-generated by mavtestgen.py) + +Generated from: %s + +Note: this file has been auto-generated. DO NOT EDIT +*/ + +static void mavtest_generate_outputs(mavlink_channel_t chan) +{ +""") + for m in msgs: + if m.name == "HEARTBEAT": continue + outf.write("\tmavlink_msg_%s_send(chan," % m.name.lower()) + for i in range(0, len(m.fields)): + f = m.fields[i] + outf.write("%s" % gen_value(f, i, 'C')) + if i != len(m.fields)-1: + outf.write(",") + outf.write(");\n") + outf.write("}\n") + + + +###################################################################### +'''main program''' + +parser = OptionParser("%prog [options] ") +parser.add_option("-o", "--output", dest="output", default="mavtest", help="output folder [default: %default]") +(opts, args) = parser.parse_args() + +if len(args) < 1: + parser.error("You must supply at least one MAVLink XML protocol definition") + + +msgs = [] +enums = [] + +for fname in args: + (m, e) = mavparse.parse_mavlink_xml(fname) + msgs.extend(m) + enums.extend(e) + + +if mavparse.check_duplicates(msgs): + sys.exit(1) + +print("Found %u MAVLink message types" % len(msgs)) + +print("Generating python %s" % (opts.output+'.py')) +outf = open(opts.output + '.py', "w") +generate_methods_python(outf, msgs) +outf.close() + +print("Generating C %s" % (opts.output+'.h')) +outf = open(opts.output + '.h', "w") +generate_methods_C(outf, msgs) +outf.close() + +print("Generated %s OK" % opts.output) diff --git a/mavlink/share/pyshared/pymavlink/mavextra.py b/mavlink/share/pyshared/pymavlink/mavextra.py new file mode 100644 index 0000000000..5395f6036d --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/mavextra.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python +''' +useful extra functions for use by mavlink clients + +Copyright Andrew Tridgell 2011 +Released under GNU GPL version 3 or later +''' + +from math import * + + +def kmh(mps): + '''convert m/s to Km/h''' + return mps*3.6 + +def altitude(press_abs, ground_press=955.0, ground_temp=30): + '''calculate barometric altitude''' + return log(ground_press/press_abs)*(ground_temp+273.15)*29271.267*0.001 + + +def mag_heading(RAW_IMU, ATTITUDE, declination=0, SENSOR_OFFSETS=None, ofs=None): + '''calculate heading from raw magnetometer''' + mag_x = RAW_IMU.xmag + mag_y = RAW_IMU.ymag + mag_z = RAW_IMU.zmag + if SENSOR_OFFSETS is not None and ofs is not None: + mag_x += ofs[0] - SENSOR_OFFSETS.mag_ofs_x + mag_y += ofs[1] - SENSOR_OFFSETS.mag_ofs_y + mag_z += ofs[2] - SENSOR_OFFSETS.mag_ofs_z + + headX = mag_x*cos(ATTITUDE.pitch) + mag_y*sin(ATTITUDE.roll)*sin(ATTITUDE.pitch) + mag_z*cos(ATTITUDE.roll)*sin(ATTITUDE.pitch) + headY = mag_y*cos(ATTITUDE.roll) - mag_z*sin(ATTITUDE.roll) + heading = degrees(atan2(-headY,headX)) + declination + if heading < 0: + heading += 360 + return heading + +def mag_field(RAW_IMU, SENSOR_OFFSETS=None, ofs=None): + '''calculate magnetic field strength from raw magnetometer''' + mag_x = RAW_IMU.xmag + mag_y = RAW_IMU.ymag + mag_z = RAW_IMU.zmag + if SENSOR_OFFSETS is not None and ofs is not None: + mag_x += ofs[0] - SENSOR_OFFSETS.mag_ofs_x + mag_y += ofs[1] - SENSOR_OFFSETS.mag_ofs_y + mag_z += ofs[2] - SENSOR_OFFSETS.mag_ofs_z + return sqrt(mag_x**2 + mag_y**2 + mag_z**2) + +def angle_diff(angle1, angle2): + '''show the difference between two angles in degrees''' + ret = angle1 - angle2 + if ret > 180: + ret -= 360; + if ret < -180: + ret += 360 + return ret + + +lowpass_data = {} + +def lowpass(var, key, factor): + '''a simple lowpass filter''' + global lowpass_data + if not key in lowpass_data: + lowpass_data[key] = var + else: + lowpass_data[key] = factor*lowpass_data[key] + (1.0 - factor)*var + return lowpass_data[key] + +last_delta = {} + +def delta(var, key): + '''calculate slope''' + global last_delta + dv = 0 + if key in last_delta: + dv = var - last_delta[key] + last_delta[key] = var + return dv + +def delta_angle(var, key): + '''calculate slope of an angle''' + global last_delta + dv = 0 + if key in last_delta: + dv = var - last_delta[key] + last_delta[key] = var + if dv > 180: + dv -= 360 + if dv < -180: + dv += 360 + return dv + +def roll_estimate(RAW_IMU,smooth=0.7): + '''estimate roll from accelerometer''' + rx = lowpass(RAW_IMU.xacc,'rx',smooth) + ry = lowpass(RAW_IMU.yacc,'ry',smooth) + rz = lowpass(RAW_IMU.zacc,'rz',smooth) + return degrees(-asin(ry/sqrt(rx**2+ry**2+rz**2))) + +def pitch_estimate(RAW_IMU, smooth=0.7): + '''estimate pitch from accelerometer''' + rx = lowpass(RAW_IMU.xacc,'rx',smooth) + ry = lowpass(RAW_IMU.yacc,'ry',smooth) + rz = lowpass(RAW_IMU.zacc,'rz',smooth) + return degrees(asin(rx/sqrt(rx**2+ry**2+rz**2))) + +def gravity(RAW_IMU, SENSOR_OFFSETS=None, ofs=None, smooth=0.7): + '''estimate pitch from accelerometer''' + rx = RAW_IMU.xacc + ry = RAW_IMU.yacc + rz = RAW_IMU.zacc+45 + if SENSOR_OFFSETS is not None and ofs is not None: + rx += ofs[0] - SENSOR_OFFSETS.accel_cal_x + ry += ofs[1] - SENSOR_OFFSETS.accel_cal_y + rz += ofs[2] - SENSOR_OFFSETS.accel_cal_z + return lowpass(sqrt(rx**2+ry**2+rz**2)*0.01,'_gravity',smooth) + + + +def pitch_sim(SIMSTATE, GPS_RAW): + '''estimate pitch from SIMSTATE accels''' + xacc = SIMSTATE.xacc - lowpass(delta(GPS_RAW.v,"v")*6.6, "v", 0.9) + zacc = SIMSTATE.zacc + zacc += SIMSTATE.ygyro * GPS_RAW.v; + if xacc/zacc >= 1: + return 0 + if xacc/zacc <= -1: + return -0 + return degrees(-asin(xacc/zacc)) + +def distance_two(GPS_RAW1, GPS_RAW2): + '''distance between two points''' + lat1 = radians(GPS_RAW1.lat) + lat2 = radians(GPS_RAW2.lat) + lon1 = radians(GPS_RAW1.lon) + lon2 = radians(GPS_RAW2.lon) + dLat = lat2 - lat1 + dLon = lon2 - lon1 + + a = sin(0.5*dLat) * sin(0.5*dLat) + sin(0.5*dLon) * sin(0.5*dLon) * cos(lat1) * cos(lat2) + c = 2.0 * atan2(sqrt(a), sqrt(1.0-a)) + return 6371 * 1000 * c + + +first_fix = None + +def distance_home(GPS_RAW): + '''distance from first fix point''' + global first_fix + if first_fix == None or first_fix.fix_type < 2: + first_fix = GPS_RAW + return 0 + return distance_two(GPS_RAW, first_fix) diff --git a/mavlink/share/pyshared/pymavlink/mavlink.py b/mavlink/share/pyshared/pymavlink/mavlink.py new file mode 100644 index 0000000000..3287a921d9 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/mavlink.py @@ -0,0 +1,4930 @@ +''' +MAVLink protocol implementation (auto-generated by mavgen.py) + +Generated from: ardupilotmega.xml,common.xml + +Note: this file has been auto-generated. DO NOT EDIT +''' + +import struct, array, mavutil, time + +WIRE_PROTOCOL_VERSION = "0.9" + +class MAVLink_header(object): + '''MAVLink message header''' + def __init__(self, msgId, mlen=0, seq=0, srcSystem=0, srcComponent=0): + self.mlen = mlen + self.seq = seq + self.srcSystem = srcSystem + self.srcComponent = srcComponent + self.msgId = msgId + + def pack(self): + return struct.pack('BBBBBB', 85, self.mlen, self.seq, + self.srcSystem, self.srcComponent, self.msgId) + +class MAVLink_message(object): + '''base MAVLink message class''' + def __init__(self, msgId, name): + self._header = MAVLink_header(msgId) + self._payload = None + self._msgbuf = None + self._crc = None + self._fieldnames = [] + self._type = name + + def get_msgbuf(self): + return self._msgbuf + + def get_header(self): + return self._header + + def get_payload(self): + return self._payload + + def get_crc(self): + return self._crc + + def get_fieldnames(self): + return self._fieldnames + + def get_type(self): + return self._type + + def get_msgId(self): + return self._header.msgId + + def get_srcSystem(self): + return self._header.srcSystem + + def get_srcComponent(self): + return self._header.srcComponent + + def get_seq(self): + return self._header.seq + + def __str__(self): + ret = '%s {' % self._type + for a in self._fieldnames: + v = getattr(self, a) + ret += '%s : %s, ' % (a, v) + ret = ret[0:-2] + '}' + return ret + + def pack(self, mav, crc_extra, payload): + self._payload = payload + self._header = MAVLink_header(self._header.msgId, len(payload), mav.seq, + mav.srcSystem, mav.srcComponent) + self._msgbuf = self._header.pack() + payload + crc = mavutil.x25crc(self._msgbuf[1:]) + if False: # using CRC extra + crc.accumulate(chr(crc_extra)) + self._crc = crc.crc + self._msgbuf += struct.pack('hhhfiiffffff', self.mag_ofs_x, self.mag_ofs_y, self.mag_ofs_z, self.mag_declination, self.raw_press, self.raw_temp, self.gyro_cal_x, self.gyro_cal_y, self.gyro_cal_z, self.accel_cal_x, self.accel_cal_y, self.accel_cal_z)) + +class MAVLink_set_mag_offsets_message(MAVLink_message): + ''' + set the magnetometer offsets + ''' + def __init__(self, target_system, target_component, mag_ofs_x, mag_ofs_y, mag_ofs_z): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SET_MAG_OFFSETS, 'SET_MAG_OFFSETS') + self._fieldnames = ['target_system', 'target_component', 'mag_ofs_x', 'mag_ofs_y', 'mag_ofs_z'] + self.target_system = target_system + self.target_component = target_component + self.mag_ofs_x = mag_ofs_x + self.mag_ofs_y = mag_ofs_y + self.mag_ofs_z = mag_ofs_z + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 29, struct.pack('>BBhhh', self.target_system, self.target_component, self.mag_ofs_x, self.mag_ofs_y, self.mag_ofs_z)) + +class MAVLink_meminfo_message(MAVLink_message): + ''' + state of APM memory + ''' + def __init__(self, brkval, freemem): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_MEMINFO, 'MEMINFO') + self._fieldnames = ['brkval', 'freemem'] + self.brkval = brkval + self.freemem = freemem + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 208, struct.pack('>HH', self.brkval, self.freemem)) + +class MAVLink_ap_adc_message(MAVLink_message): + ''' + raw ADC output + ''' + def __init__(self, adc1, adc2, adc3, adc4, adc5, adc6): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_AP_ADC, 'AP_ADC') + self._fieldnames = ['adc1', 'adc2', 'adc3', 'adc4', 'adc5', 'adc6'] + self.adc1 = adc1 + self.adc2 = adc2 + self.adc3 = adc3 + self.adc4 = adc4 + self.adc5 = adc5 + self.adc6 = adc6 + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 188, struct.pack('>HHHHHH', self.adc1, self.adc2, self.adc3, self.adc4, self.adc5, self.adc6)) + +class MAVLink_digicam_configure_message(MAVLink_message): + ''' + Configure on-board Camera Control System. + ''' + def __init__(self, target_system, target_component, mode, shutter_speed, aperture, iso, exposure_type, command_id, engine_cut_off, extra_param, extra_value): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_DIGICAM_CONFIGURE, 'DIGICAM_CONFIGURE') + self._fieldnames = ['target_system', 'target_component', 'mode', 'shutter_speed', 'aperture', 'iso', 'exposure_type', 'command_id', 'engine_cut_off', 'extra_param', 'extra_value'] + self.target_system = target_system + self.target_component = target_component + self.mode = mode + self.shutter_speed = shutter_speed + self.aperture = aperture + self.iso = iso + self.exposure_type = exposure_type + self.command_id = command_id + self.engine_cut_off = engine_cut_off + self.extra_param = extra_param + self.extra_value = extra_value + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 118, struct.pack('>BBBHBBBBBBf', self.target_system, self.target_component, self.mode, self.shutter_speed, self.aperture, self.iso, self.exposure_type, self.command_id, self.engine_cut_off, self.extra_param, self.extra_value)) + +class MAVLink_digicam_control_message(MAVLink_message): + ''' + Control on-board Camera Control System to take shots. + ''' + def __init__(self, target_system, target_component, session, zoom_pos, zoom_step, focus_lock, shot, command_id, extra_param, extra_value): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_DIGICAM_CONTROL, 'DIGICAM_CONTROL') + self._fieldnames = ['target_system', 'target_component', 'session', 'zoom_pos', 'zoom_step', 'focus_lock', 'shot', 'command_id', 'extra_param', 'extra_value'] + self.target_system = target_system + self.target_component = target_component + self.session = session + self.zoom_pos = zoom_pos + self.zoom_step = zoom_step + self.focus_lock = focus_lock + self.shot = shot + self.command_id = command_id + self.extra_param = extra_param + self.extra_value = extra_value + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 242, struct.pack('>BBBBbBBBBf', self.target_system, self.target_component, self.session, self.zoom_pos, self.zoom_step, self.focus_lock, self.shot, self.command_id, self.extra_param, self.extra_value)) + +class MAVLink_mount_configure_message(MAVLink_message): + ''' + Message to configure a camera mount, directional antenna, etc. + ''' + def __init__(self, target_system, target_component, mount_mode, stab_roll, stab_pitch, stab_yaw): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_MOUNT_CONFIGURE, 'MOUNT_CONFIGURE') + self._fieldnames = ['target_system', 'target_component', 'mount_mode', 'stab_roll', 'stab_pitch', 'stab_yaw'] + self.target_system = target_system + self.target_component = target_component + self.mount_mode = mount_mode + self.stab_roll = stab_roll + self.stab_pitch = stab_pitch + self.stab_yaw = stab_yaw + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 19, struct.pack('>BBBBBB', self.target_system, self.target_component, self.mount_mode, self.stab_roll, self.stab_pitch, self.stab_yaw)) + +class MAVLink_mount_control_message(MAVLink_message): + ''' + Message to control a camera mount, directional antenna, etc. + ''' + def __init__(self, target_system, target_component, input_a, input_b, input_c, save_position): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_MOUNT_CONTROL, 'MOUNT_CONTROL') + self._fieldnames = ['target_system', 'target_component', 'input_a', 'input_b', 'input_c', 'save_position'] + self.target_system = target_system + self.target_component = target_component + self.input_a = input_a + self.input_b = input_b + self.input_c = input_c + self.save_position = save_position + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 97, struct.pack('>BBiiiB', self.target_system, self.target_component, self.input_a, self.input_b, self.input_c, self.save_position)) + +class MAVLink_mount_status_message(MAVLink_message): + ''' + Message with some status from APM to GCS about camera or + antenna mount + ''' + def __init__(self, target_system, target_component, pointing_a, pointing_b, pointing_c): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_MOUNT_STATUS, 'MOUNT_STATUS') + self._fieldnames = ['target_system', 'target_component', 'pointing_a', 'pointing_b', 'pointing_c'] + self.target_system = target_system + self.target_component = target_component + self.pointing_a = pointing_a + self.pointing_b = pointing_b + self.pointing_c = pointing_c + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 233, struct.pack('>BBiii', self.target_system, self.target_component, self.pointing_a, self.pointing_b, self.pointing_c)) + +class MAVLink_fence_point_message(MAVLink_message): + ''' + A fence point. Used to set a point when from GCS + -> MAV. Also used to return a point from MAV -> GCS + ''' + def __init__(self, target_system, target_component, idx, count, lat, lng): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_FENCE_POINT, 'FENCE_POINT') + self._fieldnames = ['target_system', 'target_component', 'idx', 'count', 'lat', 'lng'] + self.target_system = target_system + self.target_component = target_component + self.idx = idx + self.count = count + self.lat = lat + self.lng = lng + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 18, struct.pack('>BBBBff', self.target_system, self.target_component, self.idx, self.count, self.lat, self.lng)) + +class MAVLink_fence_fetch_point_message(MAVLink_message): + ''' + Request a current fence point from MAV + ''' + def __init__(self, target_system, target_component, idx): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_FENCE_FETCH_POINT, 'FENCE_FETCH_POINT') + self._fieldnames = ['target_system', 'target_component', 'idx'] + self.target_system = target_system + self.target_component = target_component + self.idx = idx + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 68, struct.pack('>BBB', self.target_system, self.target_component, self.idx)) + +class MAVLink_fence_status_message(MAVLink_message): + ''' + Status of geo-fencing. Sent in extended status + stream when fencing enabled + ''' + def __init__(self, breach_status, breach_count, breach_type, breach_time): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_FENCE_STATUS, 'FENCE_STATUS') + self._fieldnames = ['breach_status', 'breach_count', 'breach_type', 'breach_time'] + self.breach_status = breach_status + self.breach_count = breach_count + self.breach_type = breach_type + self.breach_time = breach_time + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 136, struct.pack('>BHBI', self.breach_status, self.breach_count, self.breach_type, self.breach_time)) + +class MAVLink_ahrs_message(MAVLink_message): + ''' + Status of DCM attitude estimator + ''' + def __init__(self, omegaIx, omegaIy, omegaIz, accel_weight, renorm_val, error_rp, error_yaw): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_AHRS, 'AHRS') + self._fieldnames = ['omegaIx', 'omegaIy', 'omegaIz', 'accel_weight', 'renorm_val', 'error_rp', 'error_yaw'] + self.omegaIx = omegaIx + self.omegaIy = omegaIy + self.omegaIz = omegaIz + self.accel_weight = accel_weight + self.renorm_val = renorm_val + self.error_rp = error_rp + self.error_yaw = error_yaw + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 127, struct.pack('>fffffff', self.omegaIx, self.omegaIy, self.omegaIz, self.accel_weight, self.renorm_val, self.error_rp, self.error_yaw)) + +class MAVLink_simstate_message(MAVLink_message): + ''' + Status of simulation environment, if used + ''' + def __init__(self, roll, pitch, yaw, xacc, yacc, zacc, xgyro, ygyro, zgyro): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SIMSTATE, 'SIMSTATE') + self._fieldnames = ['roll', 'pitch', 'yaw', 'xacc', 'yacc', 'zacc', 'xgyro', 'ygyro', 'zgyro'] + self.roll = roll + self.pitch = pitch + self.yaw = yaw + self.xacc = xacc + self.yacc = yacc + self.zacc = zacc + self.xgyro = xgyro + self.ygyro = ygyro + self.zgyro = zgyro + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 42, struct.pack('>fffffffff', self.roll, self.pitch, self.yaw, self.xacc, self.yacc, self.zacc, self.xgyro, self.ygyro, self.zgyro)) + +class MAVLink_hwstatus_message(MAVLink_message): + ''' + Status of key hardware + ''' + def __init__(self, Vcc, I2Cerr): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_HWSTATUS, 'HWSTATUS') + self._fieldnames = ['Vcc', 'I2Cerr'] + self.Vcc = Vcc + self.I2Cerr = I2Cerr + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 21, struct.pack('>HB', self.Vcc, self.I2Cerr)) + +class MAVLink_radio_message(MAVLink_message): + ''' + Status generated by radio + ''' + def __init__(self, rssi, remrssi, txbuf, noise, remnoise, rxerrors, fixed): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_RADIO, 'RADIO') + self._fieldnames = ['rssi', 'remrssi', 'txbuf', 'noise', 'remnoise', 'rxerrors', 'fixed'] + self.rssi = rssi + self.remrssi = remrssi + self.txbuf = txbuf + self.noise = noise + self.remnoise = remnoise + self.rxerrors = rxerrors + self.fixed = fixed + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 93, struct.pack('>BBBBBHH', self.rssi, self.remrssi, self.txbuf, self.noise, self.remnoise, self.rxerrors, self.fixed)) + +class MAVLink_heartbeat_message(MAVLink_message): + ''' + The heartbeat message shows that a system is present and + responding. The type of the MAV and Autopilot hardware allow + the receiving system to treat further messages from this + system appropriate (e.g. by laying out the user interface + based on the autopilot). + ''' + def __init__(self, type, autopilot, mavlink_version): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_HEARTBEAT, 'HEARTBEAT') + self._fieldnames = ['type', 'autopilot', 'mavlink_version'] + self.type = type + self.autopilot = autopilot + self.mavlink_version = mavlink_version + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 72, struct.pack('>BBB', self.type, self.autopilot, self.mavlink_version)) + +class MAVLink_boot_message(MAVLink_message): + ''' + The boot message indicates that a system is starting. The + onboard software version allows to keep track of onboard + soft/firmware revisions. + ''' + def __init__(self, version): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_BOOT, 'BOOT') + self._fieldnames = ['version'] + self.version = version + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 39, struct.pack('>I', self.version)) + +class MAVLink_system_time_message(MAVLink_message): + ''' + The system time is the time of the master clock, typically the + computer clock of the main onboard computer. + ''' + def __init__(self, time_usec): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SYSTEM_TIME, 'SYSTEM_TIME') + self._fieldnames = ['time_usec'] + self.time_usec = time_usec + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 190, struct.pack('>Q', self.time_usec)) + +class MAVLink_ping_message(MAVLink_message): + ''' + A ping message either requesting or responding to a ping. This + allows to measure the system latencies, including serial port, + radio modem and UDP connections. + ''' + def __init__(self, seq, target_system, target_component, time): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_PING, 'PING') + self._fieldnames = ['seq', 'target_system', 'target_component', 'time'] + self.seq = seq + self.target_system = target_system + self.target_component = target_component + self.time = time + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 92, struct.pack('>IBBQ', self.seq, self.target_system, self.target_component, self.time)) + +class MAVLink_system_time_utc_message(MAVLink_message): + ''' + UTC date and time from GPS module + ''' + def __init__(self, utc_date, utc_time): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SYSTEM_TIME_UTC, 'SYSTEM_TIME_UTC') + self._fieldnames = ['utc_date', 'utc_time'] + self.utc_date = utc_date + self.utc_time = utc_time + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 191, struct.pack('>II', self.utc_date, self.utc_time)) + +class MAVLink_change_operator_control_message(MAVLink_message): + ''' + Request to control this MAV + ''' + def __init__(self, target_system, control_request, version, passkey): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL, 'CHANGE_OPERATOR_CONTROL') + self._fieldnames = ['target_system', 'control_request', 'version', 'passkey'] + self.target_system = target_system + self.control_request = control_request + self.version = version + self.passkey = passkey + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 217, struct.pack('>BBB25s', self.target_system, self.control_request, self.version, self.passkey)) + +class MAVLink_change_operator_control_ack_message(MAVLink_message): + ''' + Accept / deny control of this MAV + ''' + def __init__(self, gcs_system_id, control_request, ack): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK, 'CHANGE_OPERATOR_CONTROL_ACK') + self._fieldnames = ['gcs_system_id', 'control_request', 'ack'] + self.gcs_system_id = gcs_system_id + self.control_request = control_request + self.ack = ack + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 104, struct.pack('>BBB', self.gcs_system_id, self.control_request, self.ack)) + +class MAVLink_auth_key_message(MAVLink_message): + ''' + Emit an encrypted signature / key identifying this system. + PLEASE NOTE: This protocol has been kept simple, so + transmitting the key requires an encrypted channel for true + safety. + ''' + def __init__(self, key): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_AUTH_KEY, 'AUTH_KEY') + self._fieldnames = ['key'] + self.key = key + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 119, struct.pack('>32s', self.key)) + +class MAVLink_action_ack_message(MAVLink_message): + ''' + This message acknowledges an action. IMPORTANT: The + acknowledgement can be also negative, e.g. the MAV rejects a + reset message because it is in-flight. The action ids are + defined in ENUM MAV_ACTION in mavlink/include/mavlink_types.h + ''' + def __init__(self, action, result): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_ACTION_ACK, 'ACTION_ACK') + self._fieldnames = ['action', 'result'] + self.action = action + self.result = result + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 219, struct.pack('>BB', self.action, self.result)) + +class MAVLink_action_message(MAVLink_message): + ''' + An action message allows to execute a certain onboard action. + These include liftoff, land, storing parameters too EEPROM, + shutddown, etc. The action ids are defined in ENUM MAV_ACTION + in mavlink/include/mavlink_types.h + ''' + def __init__(self, target, target_component, action): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_ACTION, 'ACTION') + self._fieldnames = ['target', 'target_component', 'action'] + self.target = target + self.target_component = target_component + self.action = action + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 60, struct.pack('>BBB', self.target, self.target_component, self.action)) + +class MAVLink_set_mode_message(MAVLink_message): + ''' + Set the system mode, as defined by enum MAV_MODE in + mavlink/include/mavlink_types.h. There is no target component + id as the mode is by definition for the overall aircraft, not + only for one component. + ''' + def __init__(self, target, mode): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SET_MODE, 'SET_MODE') + self._fieldnames = ['target', 'mode'] + self.target = target + self.mode = mode + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 186, struct.pack('>BB', self.target, self.mode)) + +class MAVLink_set_nav_mode_message(MAVLink_message): + ''' + Set the system navigation mode, as defined by enum + MAV_NAV_MODE in mavlink/include/mavlink_types.h. The + navigation mode applies to the whole aircraft and thus all + components. + ''' + def __init__(self, target, nav_mode): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SET_NAV_MODE, 'SET_NAV_MODE') + self._fieldnames = ['target', 'nav_mode'] + self.target = target + self.nav_mode = nav_mode + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 10, struct.pack('>BB', self.target, self.nav_mode)) + +class MAVLink_param_request_read_message(MAVLink_message): + ''' + Request to read the onboard parameter with the param_id string + id. Onboard parameters are stored as key[const char*] -> + value[float]. This allows to send a parameter to any other + component (such as the GCS) without the need of previous + knowledge of possible parameter names. Thus the same GCS can + store different parameters for different autopilots. See also + http://qgroundcontrol.org/parameter_interface for a full + documentation of QGroundControl and IMU code. + ''' + def __init__(self, target_system, target_component, param_id, param_index): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_PARAM_REQUEST_READ, 'PARAM_REQUEST_READ') + self._fieldnames = ['target_system', 'target_component', 'param_id', 'param_index'] + self.target_system = target_system + self.target_component = target_component + self.param_id = param_id + self.param_index = param_index + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 89, struct.pack('>BB15sh', self.target_system, self.target_component, self.param_id, self.param_index)) + +class MAVLink_param_request_list_message(MAVLink_message): + ''' + Request all parameters of this component. After his request, + all parameters are emitted. + ''' + def __init__(self, target_system, target_component): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_PARAM_REQUEST_LIST, 'PARAM_REQUEST_LIST') + self._fieldnames = ['target_system', 'target_component'] + self.target_system = target_system + self.target_component = target_component + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 159, struct.pack('>BB', self.target_system, self.target_component)) + +class MAVLink_param_value_message(MAVLink_message): + ''' + Emit the value of a onboard parameter. The inclusion of + param_count and param_index in the message allows the + recipient to keep track of received parameters and allows him + to re-request missing parameters after a loss or timeout. + ''' + def __init__(self, param_id, param_value, param_count, param_index): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_PARAM_VALUE, 'PARAM_VALUE') + self._fieldnames = ['param_id', 'param_value', 'param_count', 'param_index'] + self.param_id = param_id + self.param_value = param_value + self.param_count = param_count + self.param_index = param_index + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 162, struct.pack('>15sfHH', self.param_id, self.param_value, self.param_count, self.param_index)) + +class MAVLink_param_set_message(MAVLink_message): + ''' + Set a parameter value TEMPORARILY to RAM. It will be reset to + default on system reboot. Send the ACTION + MAV_ACTION_STORAGE_WRITE to PERMANENTLY write the RAM contents + to EEPROM. IMPORTANT: The receiving component should + acknowledge the new parameter value by sending a param_value + message to all communication partners. This will also ensure + that multiple GCS all have an up-to-date list of all + parameters. If the sending GCS did not receive a PARAM_VALUE + message within its timeout time, it should re-send the + PARAM_SET message. + ''' + def __init__(self, target_system, target_component, param_id, param_value): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_PARAM_SET, 'PARAM_SET') + self._fieldnames = ['target_system', 'target_component', 'param_id', 'param_value'] + self.target_system = target_system + self.target_component = target_component + self.param_id = param_id + self.param_value = param_value + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 121, struct.pack('>BB15sf', self.target_system, self.target_component, self.param_id, self.param_value)) + +class MAVLink_gps_raw_int_message(MAVLink_message): + ''' + The global position, as returned by the Global Positioning + System (GPS). This is NOT the global position estimate of the + sytem, but rather a RAW sensor value. See message + GLOBAL_POSITION for the global position estimate. Coordinate + frame is right-handed, Z-axis up (GPS frame) + ''' + def __init__(self, usec, fix_type, lat, lon, alt, eph, epv, v, hdg): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_GPS_RAW_INT, 'GPS_RAW_INT') + self._fieldnames = ['usec', 'fix_type', 'lat', 'lon', 'alt', 'eph', 'epv', 'v', 'hdg'] + self.usec = usec + self.fix_type = fix_type + self.lat = lat + self.lon = lon + self.alt = alt + self.eph = eph + self.epv = epv + self.v = v + self.hdg = hdg + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 149, struct.pack('>QBiiiffff', self.usec, self.fix_type, self.lat, self.lon, self.alt, self.eph, self.epv, self.v, self.hdg)) + +class MAVLink_scaled_imu_message(MAVLink_message): + ''' + The RAW IMU readings for the usual 9DOF sensor setup. This + message should contain the scaled values to the described + units + ''' + def __init__(self, usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SCALED_IMU, 'SCALED_IMU') + self._fieldnames = ['usec', 'xacc', 'yacc', 'zacc', 'xgyro', 'ygyro', 'zgyro', 'xmag', 'ymag', 'zmag'] + self.usec = usec + self.xacc = xacc + self.yacc = yacc + self.zacc = zacc + self.xgyro = xgyro + self.ygyro = ygyro + self.zgyro = zgyro + self.xmag = xmag + self.ymag = ymag + self.zmag = zmag + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 222, struct.pack('>Qhhhhhhhhh', self.usec, self.xacc, self.yacc, self.zacc, self.xgyro, self.ygyro, self.zgyro, self.xmag, self.ymag, self.zmag)) + +class MAVLink_gps_status_message(MAVLink_message): + ''' + The positioning status, as reported by GPS. This message is + intended to display status information about each satellite + visible to the receiver. See message GLOBAL_POSITION for the + global position estimate. This message can contain information + for up to 20 satellites. + ''' + def __init__(self, satellites_visible, satellite_prn, satellite_used, satellite_elevation, satellite_azimuth, satellite_snr): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_GPS_STATUS, 'GPS_STATUS') + self._fieldnames = ['satellites_visible', 'satellite_prn', 'satellite_used', 'satellite_elevation', 'satellite_azimuth', 'satellite_snr'] + self.satellites_visible = satellites_visible + self.satellite_prn = satellite_prn + self.satellite_used = satellite_used + self.satellite_elevation = satellite_elevation + self.satellite_azimuth = satellite_azimuth + self.satellite_snr = satellite_snr + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 110, struct.pack('>B20s20s20s20s20s', self.satellites_visible, self.satellite_prn, self.satellite_used, self.satellite_elevation, self.satellite_azimuth, self.satellite_snr)) + +class MAVLink_raw_imu_message(MAVLink_message): + ''' + The RAW IMU readings for the usual 9DOF sensor setup. This + message should always contain the true raw values without any + scaling to allow data capture and system debugging. + ''' + def __init__(self, usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_RAW_IMU, 'RAW_IMU') + self._fieldnames = ['usec', 'xacc', 'yacc', 'zacc', 'xgyro', 'ygyro', 'zgyro', 'xmag', 'ymag', 'zmag'] + self.usec = usec + self.xacc = xacc + self.yacc = yacc + self.zacc = zacc + self.xgyro = xgyro + self.ygyro = ygyro + self.zgyro = zgyro + self.xmag = xmag + self.ymag = ymag + self.zmag = zmag + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 179, struct.pack('>Qhhhhhhhhh', self.usec, self.xacc, self.yacc, self.zacc, self.xgyro, self.ygyro, self.zgyro, self.xmag, self.ymag, self.zmag)) + +class MAVLink_raw_pressure_message(MAVLink_message): + ''' + The RAW pressure readings for the typical setup of one + absolute pressure and one differential pressure sensor. The + sensor values should be the raw, UNSCALED ADC values. + ''' + def __init__(self, usec, press_abs, press_diff1, press_diff2, temperature): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_RAW_PRESSURE, 'RAW_PRESSURE') + self._fieldnames = ['usec', 'press_abs', 'press_diff1', 'press_diff2', 'temperature'] + self.usec = usec + self.press_abs = press_abs + self.press_diff1 = press_diff1 + self.press_diff2 = press_diff2 + self.temperature = temperature + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 136, struct.pack('>Qhhhh', self.usec, self.press_abs, self.press_diff1, self.press_diff2, self.temperature)) + +class MAVLink_scaled_pressure_message(MAVLink_message): + ''' + The pressure readings for the typical setup of one absolute + and differential pressure sensor. The units are as specified + in each field. + ''' + def __init__(self, usec, press_abs, press_diff, temperature): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SCALED_PRESSURE, 'SCALED_PRESSURE') + self._fieldnames = ['usec', 'press_abs', 'press_diff', 'temperature'] + self.usec = usec + self.press_abs = press_abs + self.press_diff = press_diff + self.temperature = temperature + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 229, struct.pack('>Qffh', self.usec, self.press_abs, self.press_diff, self.temperature)) + +class MAVLink_attitude_message(MAVLink_message): + ''' + The attitude in the aeronautical frame (right-handed, Z-down, + X-front, Y-right). + ''' + def __init__(self, usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_ATTITUDE, 'ATTITUDE') + self._fieldnames = ['usec', 'roll', 'pitch', 'yaw', 'rollspeed', 'pitchspeed', 'yawspeed'] + self.usec = usec + self.roll = roll + self.pitch = pitch + self.yaw = yaw + self.rollspeed = rollspeed + self.pitchspeed = pitchspeed + self.yawspeed = yawspeed + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 66, struct.pack('>Qffffff', self.usec, self.roll, self.pitch, self.yaw, self.rollspeed, self.pitchspeed, self.yawspeed)) + +class MAVLink_local_position_message(MAVLink_message): + ''' + The filtered local position (e.g. fused computer vision and + accelerometers). Coordinate frame is right-handed, Z-axis down + (aeronautical frame) + ''' + def __init__(self, usec, x, y, z, vx, vy, vz): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_LOCAL_POSITION, 'LOCAL_POSITION') + self._fieldnames = ['usec', 'x', 'y', 'z', 'vx', 'vy', 'vz'] + self.usec = usec + self.x = x + self.y = y + self.z = z + self.vx = vx + self.vy = vy + self.vz = vz + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 126, struct.pack('>Qffffff', self.usec, self.x, self.y, self.z, self.vx, self.vy, self.vz)) + +class MAVLink_global_position_message(MAVLink_message): + ''' + The filtered global position (e.g. fused GPS and + accelerometers). Coordinate frame is right-handed, Z-axis up + (GPS frame) + ''' + def __init__(self, usec, lat, lon, alt, vx, vy, vz): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_GLOBAL_POSITION, 'GLOBAL_POSITION') + self._fieldnames = ['usec', 'lat', 'lon', 'alt', 'vx', 'vy', 'vz'] + self.usec = usec + self.lat = lat + self.lon = lon + self.alt = alt + self.vx = vx + self.vy = vy + self.vz = vz + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 147, struct.pack('>Qffffff', self.usec, self.lat, self.lon, self.alt, self.vx, self.vy, self.vz)) + +class MAVLink_gps_raw_message(MAVLink_message): + ''' + The global position, as returned by the Global Positioning + System (GPS). This is NOT the global position estimate of the + sytem, but rather a RAW sensor value. See message + GLOBAL_POSITION for the global position estimate. Coordinate + frame is right-handed, Z-axis up (GPS frame) + ''' + def __init__(self, usec, fix_type, lat, lon, alt, eph, epv, v, hdg): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_GPS_RAW, 'GPS_RAW') + self._fieldnames = ['usec', 'fix_type', 'lat', 'lon', 'alt', 'eph', 'epv', 'v', 'hdg'] + self.usec = usec + self.fix_type = fix_type + self.lat = lat + self.lon = lon + self.alt = alt + self.eph = eph + self.epv = epv + self.v = v + self.hdg = hdg + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 185, struct.pack('>QBfffffff', self.usec, self.fix_type, self.lat, self.lon, self.alt, self.eph, self.epv, self.v, self.hdg)) + +class MAVLink_sys_status_message(MAVLink_message): + ''' + The general system state. If the system is following the + MAVLink standard, the system state is mainly defined by three + orthogonal states/modes: The system mode, which is either + LOCKED (motors shut down and locked), MANUAL (system under RC + control), GUIDED (system with autonomous position control, + position setpoint controlled manually) or AUTO (system guided + by path/waypoint planner). The NAV_MODE defined the current + flight state: LIFTOFF (often an open-loop maneuver), LANDING, + WAYPOINTS or VECTOR. This represents the internal navigation + state machine. The system status shows wether the system is + currently active or not and if an emergency occured. During + the CRITICAL and EMERGENCY states the MAV is still considered + to be active, but should start emergency procedures + autonomously. After a failure occured it should first move + from active to critical to allow manual intervention and then + move to emergency after a certain timeout. + ''' + def __init__(self, mode, nav_mode, status, load, vbat, battery_remaining, packet_drop): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SYS_STATUS, 'SYS_STATUS') + self._fieldnames = ['mode', 'nav_mode', 'status', 'load', 'vbat', 'battery_remaining', 'packet_drop'] + self.mode = mode + self.nav_mode = nav_mode + self.status = status + self.load = load + self.vbat = vbat + self.battery_remaining = battery_remaining + self.packet_drop = packet_drop + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 112, struct.pack('>BBBHHHH', self.mode, self.nav_mode, self.status, self.load, self.vbat, self.battery_remaining, self.packet_drop)) + +class MAVLink_rc_channels_raw_message(MAVLink_message): + ''' + The RAW values of the RC channels received. The standard PPM + modulation is as follows: 1000 microseconds: 0%, 2000 + microseconds: 100%. Individual receivers/transmitters might + violate this specification. + ''' + def __init__(self, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw, rssi): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_RC_CHANNELS_RAW, 'RC_CHANNELS_RAW') + self._fieldnames = ['chan1_raw', 'chan2_raw', 'chan3_raw', 'chan4_raw', 'chan5_raw', 'chan6_raw', 'chan7_raw', 'chan8_raw', 'rssi'] + self.chan1_raw = chan1_raw + self.chan2_raw = chan2_raw + self.chan3_raw = chan3_raw + self.chan4_raw = chan4_raw + self.chan5_raw = chan5_raw + self.chan6_raw = chan6_raw + self.chan7_raw = chan7_raw + self.chan8_raw = chan8_raw + self.rssi = rssi + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 252, struct.pack('>HHHHHHHHB', self.chan1_raw, self.chan2_raw, self.chan3_raw, self.chan4_raw, self.chan5_raw, self.chan6_raw, self.chan7_raw, self.chan8_raw, self.rssi)) + +class MAVLink_rc_channels_scaled_message(MAVLink_message): + ''' + The scaled values of the RC channels received. (-100%) -10000, + (0%) 0, (100%) 10000 + ''' + def __init__(self, chan1_scaled, chan2_scaled, chan3_scaled, chan4_scaled, chan5_scaled, chan6_scaled, chan7_scaled, chan8_scaled, rssi): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_RC_CHANNELS_SCALED, 'RC_CHANNELS_SCALED') + self._fieldnames = ['chan1_scaled', 'chan2_scaled', 'chan3_scaled', 'chan4_scaled', 'chan5_scaled', 'chan6_scaled', 'chan7_scaled', 'chan8_scaled', 'rssi'] + self.chan1_scaled = chan1_scaled + self.chan2_scaled = chan2_scaled + self.chan3_scaled = chan3_scaled + self.chan4_scaled = chan4_scaled + self.chan5_scaled = chan5_scaled + self.chan6_scaled = chan6_scaled + self.chan7_scaled = chan7_scaled + self.chan8_scaled = chan8_scaled + self.rssi = rssi + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 162, struct.pack('>hhhhhhhhB', self.chan1_scaled, self.chan2_scaled, self.chan3_scaled, self.chan4_scaled, self.chan5_scaled, self.chan6_scaled, self.chan7_scaled, self.chan8_scaled, self.rssi)) + +class MAVLink_servo_output_raw_message(MAVLink_message): + ''' + The RAW values of the servo outputs (for RC input from the + remote, use the RC_CHANNELS messages). The standard PPM + modulation is as follows: 1000 microseconds: 0%, 2000 + microseconds: 100%. + ''' + def __init__(self, servo1_raw, servo2_raw, servo3_raw, servo4_raw, servo5_raw, servo6_raw, servo7_raw, servo8_raw): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SERVO_OUTPUT_RAW, 'SERVO_OUTPUT_RAW') + self._fieldnames = ['servo1_raw', 'servo2_raw', 'servo3_raw', 'servo4_raw', 'servo5_raw', 'servo6_raw', 'servo7_raw', 'servo8_raw'] + self.servo1_raw = servo1_raw + self.servo2_raw = servo2_raw + self.servo3_raw = servo3_raw + self.servo4_raw = servo4_raw + self.servo5_raw = servo5_raw + self.servo6_raw = servo6_raw + self.servo7_raw = servo7_raw + self.servo8_raw = servo8_raw + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 215, struct.pack('>HHHHHHHH', self.servo1_raw, self.servo2_raw, self.servo3_raw, self.servo4_raw, self.servo5_raw, self.servo6_raw, self.servo7_raw, self.servo8_raw)) + +class MAVLink_waypoint_message(MAVLink_message): + ''' + Message encoding a waypoint. This message is emitted to + announce the presence of a waypoint and to set a waypoint + on the system. The waypoint can be either in x, y, z meters + (type: LOCAL) or x:lat, y:lon, z:altitude. Local frame is + Z-down, right handed, global frame is Z-up, right handed + ''' + def __init__(self, target_system, target_component, seq, frame, command, current, autocontinue, param1, param2, param3, param4, x, y, z): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_WAYPOINT, 'WAYPOINT') + self._fieldnames = ['target_system', 'target_component', 'seq', 'frame', 'command', 'current', 'autocontinue', 'param1', 'param2', 'param3', 'param4', 'x', 'y', 'z'] + self.target_system = target_system + self.target_component = target_component + self.seq = seq + self.frame = frame + self.command = command + self.current = current + self.autocontinue = autocontinue + self.param1 = param1 + self.param2 = param2 + self.param3 = param3 + self.param4 = param4 + self.x = x + self.y = y + self.z = z + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 128, struct.pack('>BBHBBBBfffffff', self.target_system, self.target_component, self.seq, self.frame, self.command, self.current, self.autocontinue, self.param1, self.param2, self.param3, self.param4, self.x, self.y, self.z)) + +class MAVLink_waypoint_request_message(MAVLink_message): + ''' + Request the information of the waypoint with the sequence + number seq. The response of the system to this message should + be a WAYPOINT message. + ''' + def __init__(self, target_system, target_component, seq): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_WAYPOINT_REQUEST, 'WAYPOINT_REQUEST') + self._fieldnames = ['target_system', 'target_component', 'seq'] + self.target_system = target_system + self.target_component = target_component + self.seq = seq + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 9, struct.pack('>BBH', self.target_system, self.target_component, self.seq)) + +class MAVLink_waypoint_set_current_message(MAVLink_message): + ''' + Set the waypoint with sequence number seq as current waypoint. + This means that the MAV will continue to this waypoint on the + shortest path (not following the waypoints in-between). + ''' + def __init__(self, target_system, target_component, seq): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_WAYPOINT_SET_CURRENT, 'WAYPOINT_SET_CURRENT') + self._fieldnames = ['target_system', 'target_component', 'seq'] + self.target_system = target_system + self.target_component = target_component + self.seq = seq + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 106, struct.pack('>BBH', self.target_system, self.target_component, self.seq)) + +class MAVLink_waypoint_current_message(MAVLink_message): + ''' + Message that announces the sequence number of the current + active waypoint. The MAV will fly towards this waypoint. + ''' + def __init__(self, seq): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_WAYPOINT_CURRENT, 'WAYPOINT_CURRENT') + self._fieldnames = ['seq'] + self.seq = seq + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 101, struct.pack('>H', self.seq)) + +class MAVLink_waypoint_request_list_message(MAVLink_message): + ''' + Request the overall list of waypoints from the + system/component. + ''' + def __init__(self, target_system, target_component): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_WAYPOINT_REQUEST_LIST, 'WAYPOINT_REQUEST_LIST') + self._fieldnames = ['target_system', 'target_component'] + self.target_system = target_system + self.target_component = target_component + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 213, struct.pack('>BB', self.target_system, self.target_component)) + +class MAVLink_waypoint_count_message(MAVLink_message): + ''' + This message is emitted as response to WAYPOINT_REQUEST_LIST + by the MAV. The GCS can then request the individual waypoints + based on the knowledge of the total number of waypoints. + ''' + def __init__(self, target_system, target_component, count): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_WAYPOINT_COUNT, 'WAYPOINT_COUNT') + self._fieldnames = ['target_system', 'target_component', 'count'] + self.target_system = target_system + self.target_component = target_component + self.count = count + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 4, struct.pack('>BBH', self.target_system, self.target_component, self.count)) + +class MAVLink_waypoint_clear_all_message(MAVLink_message): + ''' + Delete all waypoints at once. + ''' + def __init__(self, target_system, target_component): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_WAYPOINT_CLEAR_ALL, 'WAYPOINT_CLEAR_ALL') + self._fieldnames = ['target_system', 'target_component'] + self.target_system = target_system + self.target_component = target_component + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 229, struct.pack('>BB', self.target_system, self.target_component)) + +class MAVLink_waypoint_reached_message(MAVLink_message): + ''' + A certain waypoint has been reached. The system will either + hold this position (or circle on the orbit) or (if the + autocontinue on the WP was set) continue to the next waypoint. + ''' + def __init__(self, seq): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_WAYPOINT_REACHED, 'WAYPOINT_REACHED') + self._fieldnames = ['seq'] + self.seq = seq + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 21, struct.pack('>H', self.seq)) + +class MAVLink_waypoint_ack_message(MAVLink_message): + ''' + Ack message during waypoint handling. The type field states if + this message is a positive ack (type=0) or if an error + happened (type=non-zero). + ''' + def __init__(self, target_system, target_component, type): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_WAYPOINT_ACK, 'WAYPOINT_ACK') + self._fieldnames = ['target_system', 'target_component', 'type'] + self.target_system = target_system + self.target_component = target_component + self.type = type + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 214, struct.pack('>BBB', self.target_system, self.target_component, self.type)) + +class MAVLink_gps_set_global_origin_message(MAVLink_message): + ''' + As local waypoints exist, the global waypoint reference allows + to transform between the local coordinate frame and the global + (GPS) coordinate frame. This can be necessary when e.g. in- + and outdoor settings are connected and the MAV should move + from in- to outdoor. + ''' + def __init__(self, target_system, target_component, latitude, longitude, altitude): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_GPS_SET_GLOBAL_ORIGIN, 'GPS_SET_GLOBAL_ORIGIN') + self._fieldnames = ['target_system', 'target_component', 'latitude', 'longitude', 'altitude'] + self.target_system = target_system + self.target_component = target_component + self.latitude = latitude + self.longitude = longitude + self.altitude = altitude + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 215, struct.pack('>BBiii', self.target_system, self.target_component, self.latitude, self.longitude, self.altitude)) + +class MAVLink_gps_local_origin_set_message(MAVLink_message): + ''' + Once the MAV sets a new GPS-Local correspondence, this message + announces the origin (0,0,0) position + ''' + def __init__(self, latitude, longitude, altitude): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_GPS_LOCAL_ORIGIN_SET, 'GPS_LOCAL_ORIGIN_SET') + self._fieldnames = ['latitude', 'longitude', 'altitude'] + self.latitude = latitude + self.longitude = longitude + self.altitude = altitude + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 14, struct.pack('>iii', self.latitude, self.longitude, self.altitude)) + +class MAVLink_local_position_setpoint_set_message(MAVLink_message): + ''' + Set the setpoint for a local position controller. This is the + position in local coordinates the MAV should fly to. This + message is sent by the path/waypoint planner to the onboard + position controller. As some MAVs have a degree of freedom in + yaw (e.g. all helicopters/quadrotors), the desired yaw angle + is part of the message. + ''' + def __init__(self, target_system, target_component, x, y, z, yaw): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT_SET, 'LOCAL_POSITION_SETPOINT_SET') + self._fieldnames = ['target_system', 'target_component', 'x', 'y', 'z', 'yaw'] + self.target_system = target_system + self.target_component = target_component + self.x = x + self.y = y + self.z = z + self.yaw = yaw + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 206, struct.pack('>BBffff', self.target_system, self.target_component, self.x, self.y, self.z, self.yaw)) + +class MAVLink_local_position_setpoint_message(MAVLink_message): + ''' + Transmit the current local setpoint of the controller to other + MAVs (collision avoidance) and to the GCS. + ''' + def __init__(self, x, y, z, yaw): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT, 'LOCAL_POSITION_SETPOINT') + self._fieldnames = ['x', 'y', 'z', 'yaw'] + self.x = x + self.y = y + self.z = z + self.yaw = yaw + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 50, struct.pack('>ffff', self.x, self.y, self.z, self.yaw)) + +class MAVLink_control_status_message(MAVLink_message): + ''' + + ''' + def __init__(self, position_fix, vision_fix, gps_fix, ahrs_health, control_att, control_pos_xy, control_pos_z, control_pos_yaw): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_CONTROL_STATUS, 'CONTROL_STATUS') + self._fieldnames = ['position_fix', 'vision_fix', 'gps_fix', 'ahrs_health', 'control_att', 'control_pos_xy', 'control_pos_z', 'control_pos_yaw'] + self.position_fix = position_fix + self.vision_fix = vision_fix + self.gps_fix = gps_fix + self.ahrs_health = ahrs_health + self.control_att = control_att + self.control_pos_xy = control_pos_xy + self.control_pos_z = control_pos_z + self.control_pos_yaw = control_pos_yaw + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 157, struct.pack('>BBBBBBBB', self.position_fix, self.vision_fix, self.gps_fix, self.ahrs_health, self.control_att, self.control_pos_xy, self.control_pos_z, self.control_pos_yaw)) + +class MAVLink_safety_set_allowed_area_message(MAVLink_message): + ''' + Set a safety zone (volume), which is defined by two corners of + a cube. This message can be used to tell the MAV which + setpoints/waypoints to accept and which to reject. Safety + areas are often enforced by national or competition + regulations. + ''' + def __init__(self, target_system, target_component, frame, p1x, p1y, p1z, p2x, p2y, p2z): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA, 'SAFETY_SET_ALLOWED_AREA') + self._fieldnames = ['target_system', 'target_component', 'frame', 'p1x', 'p1y', 'p1z', 'p2x', 'p2y', 'p2z'] + self.target_system = target_system + self.target_component = target_component + self.frame = frame + self.p1x = p1x + self.p1y = p1y + self.p1z = p1z + self.p2x = p2x + self.p2y = p2y + self.p2z = p2z + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 126, struct.pack('>BBBffffff', self.target_system, self.target_component, self.frame, self.p1x, self.p1y, self.p1z, self.p2x, self.p2y, self.p2z)) + +class MAVLink_safety_allowed_area_message(MAVLink_message): + ''' + Read out the safety zone the MAV currently assumes. + ''' + def __init__(self, frame, p1x, p1y, p1z, p2x, p2y, p2z): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA, 'SAFETY_ALLOWED_AREA') + self._fieldnames = ['frame', 'p1x', 'p1y', 'p1z', 'p2x', 'p2y', 'p2z'] + self.frame = frame + self.p1x = p1x + self.p1y = p1y + self.p1z = p1z + self.p2x = p2x + self.p2y = p2y + self.p2z = p2z + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 108, struct.pack('>Bffffff', self.frame, self.p1x, self.p1y, self.p1z, self.p2x, self.p2y, self.p2z)) + +class MAVLink_set_roll_pitch_yaw_thrust_message(MAVLink_message): + ''' + Set roll, pitch and yaw. + ''' + def __init__(self, target_system, target_component, roll, pitch, yaw, thrust): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST, 'SET_ROLL_PITCH_YAW_THRUST') + self._fieldnames = ['target_system', 'target_component', 'roll', 'pitch', 'yaw', 'thrust'] + self.target_system = target_system + self.target_component = target_component + self.roll = roll + self.pitch = pitch + self.yaw = yaw + self.thrust = thrust + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 213, struct.pack('>BBffff', self.target_system, self.target_component, self.roll, self.pitch, self.yaw, self.thrust)) + +class MAVLink_set_roll_pitch_yaw_speed_thrust_message(MAVLink_message): + ''' + Set roll, pitch and yaw. + ''' + def __init__(self, target_system, target_component, roll_speed, pitch_speed, yaw_speed, thrust): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST, 'SET_ROLL_PITCH_YAW_SPEED_THRUST') + self._fieldnames = ['target_system', 'target_component', 'roll_speed', 'pitch_speed', 'yaw_speed', 'thrust'] + self.target_system = target_system + self.target_component = target_component + self.roll_speed = roll_speed + self.pitch_speed = pitch_speed + self.yaw_speed = yaw_speed + self.thrust = thrust + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 95, struct.pack('>BBffff', self.target_system, self.target_component, self.roll_speed, self.pitch_speed, self.yaw_speed, self.thrust)) + +class MAVLink_roll_pitch_yaw_thrust_setpoint_message(MAVLink_message): + ''' + Setpoint in roll, pitch, yaw currently active on the system. + ''' + def __init__(self, time_us, roll, pitch, yaw, thrust): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT, 'ROLL_PITCH_YAW_THRUST_SETPOINT') + self._fieldnames = ['time_us', 'roll', 'pitch', 'yaw', 'thrust'] + self.time_us = time_us + self.roll = roll + self.pitch = pitch + self.yaw = yaw + self.thrust = thrust + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 5, struct.pack('>Qffff', self.time_us, self.roll, self.pitch, self.yaw, self.thrust)) + +class MAVLink_roll_pitch_yaw_speed_thrust_setpoint_message(MAVLink_message): + ''' + Setpoint in rollspeed, pitchspeed, yawspeed currently active + on the system. + ''' + def __init__(self, time_us, roll_speed, pitch_speed, yaw_speed, thrust): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, 'ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT') + self._fieldnames = ['time_us', 'roll_speed', 'pitch_speed', 'yaw_speed', 'thrust'] + self.time_us = time_us + self.roll_speed = roll_speed + self.pitch_speed = pitch_speed + self.yaw_speed = yaw_speed + self.thrust = thrust + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 127, struct.pack('>Qffff', self.time_us, self.roll_speed, self.pitch_speed, self.yaw_speed, self.thrust)) + +class MAVLink_nav_controller_output_message(MAVLink_message): + ''' + Outputs of the APM navigation controller. The primary use of + this message is to check the response and signs of the + controller before actual flight and to assist with tuning + controller parameters + ''' + def __init__(self, nav_roll, nav_pitch, nav_bearing, target_bearing, wp_dist, alt_error, aspd_error, xtrack_error): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT, 'NAV_CONTROLLER_OUTPUT') + self._fieldnames = ['nav_roll', 'nav_pitch', 'nav_bearing', 'target_bearing', 'wp_dist', 'alt_error', 'aspd_error', 'xtrack_error'] + self.nav_roll = nav_roll + self.nav_pitch = nav_pitch + self.nav_bearing = nav_bearing + self.target_bearing = target_bearing + self.wp_dist = wp_dist + self.alt_error = alt_error + self.aspd_error = aspd_error + self.xtrack_error = xtrack_error + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 57, struct.pack('>ffhhHfff', self.nav_roll, self.nav_pitch, self.nav_bearing, self.target_bearing, self.wp_dist, self.alt_error, self.aspd_error, self.xtrack_error)) + +class MAVLink_position_target_message(MAVLink_message): + ''' + The goal position of the system. This position is the input to + any navigation or path planning algorithm and does NOT + represent the current controller setpoint. + ''' + def __init__(self, x, y, z, yaw): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_POSITION_TARGET, 'POSITION_TARGET') + self._fieldnames = ['x', 'y', 'z', 'yaw'] + self.x = x + self.y = y + self.z = z + self.yaw = yaw + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 126, struct.pack('>ffff', self.x, self.y, self.z, self.yaw)) + +class MAVLink_state_correction_message(MAVLink_message): + ''' + Corrects the systems state by adding an error correction term + to the position and velocity, and by rotating the attitude by + a correction angle. + ''' + def __init__(self, xErr, yErr, zErr, rollErr, pitchErr, yawErr, vxErr, vyErr, vzErr): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_STATE_CORRECTION, 'STATE_CORRECTION') + self._fieldnames = ['xErr', 'yErr', 'zErr', 'rollErr', 'pitchErr', 'yawErr', 'vxErr', 'vyErr', 'vzErr'] + self.xErr = xErr + self.yErr = yErr + self.zErr = zErr + self.rollErr = rollErr + self.pitchErr = pitchErr + self.yawErr = yawErr + self.vxErr = vxErr + self.vyErr = vyErr + self.vzErr = vzErr + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 130, struct.pack('>fffffffff', self.xErr, self.yErr, self.zErr, self.rollErr, self.pitchErr, self.yawErr, self.vxErr, self.vyErr, self.vzErr)) + +class MAVLink_set_altitude_message(MAVLink_message): + ''' + + ''' + def __init__(self, target, mode): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_SET_ALTITUDE, 'SET_ALTITUDE') + self._fieldnames = ['target', 'mode'] + self.target = target + self.mode = mode + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 119, struct.pack('>BI', self.target, self.mode)) + +class MAVLink_request_data_stream_message(MAVLink_message): + ''' + + ''' + def __init__(self, target_system, target_component, req_stream_id, req_message_rate, start_stop): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_REQUEST_DATA_STREAM, 'REQUEST_DATA_STREAM') + self._fieldnames = ['target_system', 'target_component', 'req_stream_id', 'req_message_rate', 'start_stop'] + self.target_system = target_system + self.target_component = target_component + self.req_stream_id = req_stream_id + self.req_message_rate = req_message_rate + self.start_stop = start_stop + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 193, struct.pack('>BBBHB', self.target_system, self.target_component, self.req_stream_id, self.req_message_rate, self.start_stop)) + +class MAVLink_hil_state_message(MAVLink_message): + ''' + This packet is useful for high throughput + applications such as hardware in the loop simulations. + ''' + def __init__(self, usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed, lat, lon, alt, vx, vy, vz, xacc, yacc, zacc): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_HIL_STATE, 'HIL_STATE') + self._fieldnames = ['usec', 'roll', 'pitch', 'yaw', 'rollspeed', 'pitchspeed', 'yawspeed', 'lat', 'lon', 'alt', 'vx', 'vy', 'vz', 'xacc', 'yacc', 'zacc'] + self.usec = usec + self.roll = roll + self.pitch = pitch + self.yaw = yaw + self.rollspeed = rollspeed + self.pitchspeed = pitchspeed + self.yawspeed = yawspeed + self.lat = lat + self.lon = lon + self.alt = alt + self.vx = vx + self.vy = vy + self.vz = vz + self.xacc = xacc + self.yacc = yacc + self.zacc = zacc + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 191, struct.pack('>Qffffffiiihhhhhh', self.usec, self.roll, self.pitch, self.yaw, self.rollspeed, self.pitchspeed, self.yawspeed, self.lat, self.lon, self.alt, self.vx, self.vy, self.vz, self.xacc, self.yacc, self.zacc)) + +class MAVLink_hil_controls_message(MAVLink_message): + ''' + Hardware in the loop control outputs + ''' + def __init__(self, time_us, roll_ailerons, pitch_elevator, yaw_rudder, throttle, mode, nav_mode): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_HIL_CONTROLS, 'HIL_CONTROLS') + self._fieldnames = ['time_us', 'roll_ailerons', 'pitch_elevator', 'yaw_rudder', 'throttle', 'mode', 'nav_mode'] + self.time_us = time_us + self.roll_ailerons = roll_ailerons + self.pitch_elevator = pitch_elevator + self.yaw_rudder = yaw_rudder + self.throttle = throttle + self.mode = mode + self.nav_mode = nav_mode + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 236, struct.pack('>QffffBB', self.time_us, self.roll_ailerons, self.pitch_elevator, self.yaw_rudder, self.throttle, self.mode, self.nav_mode)) + +class MAVLink_manual_control_message(MAVLink_message): + ''' + + ''' + def __init__(self, target, roll, pitch, yaw, thrust, roll_manual, pitch_manual, yaw_manual, thrust_manual): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_MANUAL_CONTROL, 'MANUAL_CONTROL') + self._fieldnames = ['target', 'roll', 'pitch', 'yaw', 'thrust', 'roll_manual', 'pitch_manual', 'yaw_manual', 'thrust_manual'] + self.target = target + self.roll = roll + self.pitch = pitch + self.yaw = yaw + self.thrust = thrust + self.roll_manual = roll_manual + self.pitch_manual = pitch_manual + self.yaw_manual = yaw_manual + self.thrust_manual = thrust_manual + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 158, struct.pack('>BffffBBBB', self.target, self.roll, self.pitch, self.yaw, self.thrust, self.roll_manual, self.pitch_manual, self.yaw_manual, self.thrust_manual)) + +class MAVLink_rc_channels_override_message(MAVLink_message): + ''' + The RAW values of the RC channels sent to the MAV to override + info received from the RC radio. A value of -1 means no change + to that channel. A value of 0 means control of that channel + should be released back to the RC radio. The standard PPM + modulation is as follows: 1000 microseconds: 0%, 2000 + microseconds: 100%. Individual receivers/transmitters might + violate this specification. + ''' + def __init__(self, target_system, target_component, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE, 'RC_CHANNELS_OVERRIDE') + self._fieldnames = ['target_system', 'target_component', 'chan1_raw', 'chan2_raw', 'chan3_raw', 'chan4_raw', 'chan5_raw', 'chan6_raw', 'chan7_raw', 'chan8_raw'] + self.target_system = target_system + self.target_component = target_component + self.chan1_raw = chan1_raw + self.chan2_raw = chan2_raw + self.chan3_raw = chan3_raw + self.chan4_raw = chan4_raw + self.chan5_raw = chan5_raw + self.chan6_raw = chan6_raw + self.chan7_raw = chan7_raw + self.chan8_raw = chan8_raw + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 143, struct.pack('>BBHHHHHHHH', self.target_system, self.target_component, self.chan1_raw, self.chan2_raw, self.chan3_raw, self.chan4_raw, self.chan5_raw, self.chan6_raw, self.chan7_raw, self.chan8_raw)) + +class MAVLink_global_position_int_message(MAVLink_message): + ''' + The filtered global position (e.g. fused GPS and + accelerometers). The position is in GPS-frame (right-handed, + Z-up) + ''' + def __init__(self, lat, lon, alt, vx, vy, vz): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_GLOBAL_POSITION_INT, 'GLOBAL_POSITION_INT') + self._fieldnames = ['lat', 'lon', 'alt', 'vx', 'vy', 'vz'] + self.lat = lat + self.lon = lon + self.alt = alt + self.vx = vx + self.vy = vy + self.vz = vz + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 104, struct.pack('>iiihhh', self.lat, self.lon, self.alt, self.vx, self.vy, self.vz)) + +class MAVLink_vfr_hud_message(MAVLink_message): + ''' + Metrics typically displayed on a HUD for fixed wing aircraft + ''' + def __init__(self, airspeed, groundspeed, heading, throttle, alt, climb): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_VFR_HUD, 'VFR_HUD') + self._fieldnames = ['airspeed', 'groundspeed', 'heading', 'throttle', 'alt', 'climb'] + self.airspeed = airspeed + self.groundspeed = groundspeed + self.heading = heading + self.throttle = throttle + self.alt = alt + self.climb = climb + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 123, struct.pack('>ffhHff', self.airspeed, self.groundspeed, self.heading, self.throttle, self.alt, self.climb)) + +class MAVLink_command_message(MAVLink_message): + ''' + Send a command with up to four parameters to the MAV + ''' + def __init__(self, target_system, target_component, command, confirmation, param1, param2, param3, param4): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_COMMAND, 'COMMAND') + self._fieldnames = ['target_system', 'target_component', 'command', 'confirmation', 'param1', 'param2', 'param3', 'param4'] + self.target_system = target_system + self.target_component = target_component + self.command = command + self.confirmation = confirmation + self.param1 = param1 + self.param2 = param2 + self.param3 = param3 + self.param4 = param4 + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 131, struct.pack('>BBBBffff', self.target_system, self.target_component, self.command, self.confirmation, self.param1, self.param2, self.param3, self.param4)) + +class MAVLink_command_ack_message(MAVLink_message): + ''' + Report status of a command. Includes feedback wether the + command was executed + ''' + def __init__(self, command, result): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_COMMAND_ACK, 'COMMAND_ACK') + self._fieldnames = ['command', 'result'] + self.command = command + self.result = result + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 8, struct.pack('>ff', self.command, self.result)) + +class MAVLink_optical_flow_message(MAVLink_message): + ''' + Optical flow from a flow sensor (e.g. optical mouse sensor) + ''' + def __init__(self, time, sensor_id, flow_x, flow_y, quality, ground_distance): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_OPTICAL_FLOW, 'OPTICAL_FLOW') + self._fieldnames = ['time', 'sensor_id', 'flow_x', 'flow_y', 'quality', 'ground_distance'] + self.time = time + self.sensor_id = sensor_id + self.flow_x = flow_x + self.flow_y = flow_y + self.quality = quality + self.ground_distance = ground_distance + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 174, struct.pack('>QBhhBf', self.time, self.sensor_id, self.flow_x, self.flow_y, self.quality, self.ground_distance)) + +class MAVLink_object_detection_event_message(MAVLink_message): + ''' + Object has been detected + ''' + def __init__(self, time, object_id, type, name, quality, bearing, distance): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_OBJECT_DETECTION_EVENT, 'OBJECT_DETECTION_EVENT') + self._fieldnames = ['time', 'object_id', 'type', 'name', 'quality', 'bearing', 'distance'] + self.time = time + self.object_id = object_id + self.type = type + self.name = name + self.quality = quality + self.bearing = bearing + self.distance = distance + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 155, struct.pack('>IHB20sBff', self.time, self.object_id, self.type, self.name, self.quality, self.bearing, self.distance)) + +class MAVLink_debug_vect_message(MAVLink_message): + ''' + + ''' + def __init__(self, name, usec, x, y, z): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_DEBUG_VECT, 'DEBUG_VECT') + self._fieldnames = ['name', 'usec', 'x', 'y', 'z'] + self.name = name + self.usec = usec + self.x = x + self.y = y + self.z = z + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 178, struct.pack('>10sQfff', self.name, self.usec, self.x, self.y, self.z)) + +class MAVLink_named_value_float_message(MAVLink_message): + ''' + Send a key-value pair as float. The use of this message is + discouraged for normal packets, but a quite efficient way for + testing new messages and getting experimental debug output. + ''' + def __init__(self, name, value): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_NAMED_VALUE_FLOAT, 'NAMED_VALUE_FLOAT') + self._fieldnames = ['name', 'value'] + self.name = name + self.value = value + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 224, struct.pack('>10sf', self.name, self.value)) + +class MAVLink_named_value_int_message(MAVLink_message): + ''' + Send a key-value pair as integer. The use of this message is + discouraged for normal packets, but a quite efficient way for + testing new messages and getting experimental debug output. + ''' + def __init__(self, name, value): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_NAMED_VALUE_INT, 'NAMED_VALUE_INT') + self._fieldnames = ['name', 'value'] + self.name = name + self.value = value + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 60, struct.pack('>10si', self.name, self.value)) + +class MAVLink_statustext_message(MAVLink_message): + ''' + Status text message. These messages are printed in yellow in + the COMM console of QGroundControl. WARNING: They consume + quite some bandwidth, so use only for important status and + error messages. If implemented wisely, these messages are + buffered on the MCU and sent only at a limited rate (e.g. 10 + Hz). + ''' + def __init__(self, severity, text): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_STATUSTEXT, 'STATUSTEXT') + self._fieldnames = ['severity', 'text'] + self.severity = severity + self.text = text + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 106, struct.pack('>B50s', self.severity, self.text)) + +class MAVLink_debug_message(MAVLink_message): + ''' + Send a debug value. The index is used to discriminate between + values. These values show up in the plot of QGroundControl as + DEBUG N. + ''' + def __init__(self, ind, value): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_DEBUG, 'DEBUG') + self._fieldnames = ['ind', 'value'] + self.ind = ind + self.value = value + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 7, struct.pack('>Bf', self.ind, self.value)) + + +mavlink_map = { + MAVLINK_MSG_ID_SENSOR_OFFSETS : ( '>hhhfiiffffff', MAVLink_sensor_offsets_message, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 143 ), + MAVLINK_MSG_ID_SET_MAG_OFFSETS : ( '>BBhhh', MAVLink_set_mag_offsets_message, [0, 1, 2, 3, 4], 29 ), + MAVLINK_MSG_ID_MEMINFO : ( '>HH', MAVLink_meminfo_message, [0, 1], 208 ), + MAVLINK_MSG_ID_AP_ADC : ( '>HHHHHH', MAVLink_ap_adc_message, [0, 1, 2, 3, 4, 5], 188 ), + MAVLINK_MSG_ID_DIGICAM_CONFIGURE : ( '>BBBHBBBBBBf', MAVLink_digicam_configure_message, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 118 ), + MAVLINK_MSG_ID_DIGICAM_CONTROL : ( '>BBBBbBBBBf', MAVLink_digicam_control_message, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 242 ), + MAVLINK_MSG_ID_MOUNT_CONFIGURE : ( '>BBBBBB', MAVLink_mount_configure_message, [0, 1, 2, 3, 4, 5], 19 ), + MAVLINK_MSG_ID_MOUNT_CONTROL : ( '>BBiiiB', MAVLink_mount_control_message, [0, 1, 2, 3, 4, 5], 97 ), + MAVLINK_MSG_ID_MOUNT_STATUS : ( '>BBiii', MAVLink_mount_status_message, [0, 1, 2, 3, 4], 233 ), + MAVLINK_MSG_ID_FENCE_POINT : ( '>BBBBff', MAVLink_fence_point_message, [0, 1, 2, 3, 4, 5], 18 ), + MAVLINK_MSG_ID_FENCE_FETCH_POINT : ( '>BBB', MAVLink_fence_fetch_point_message, [0, 1, 2], 68 ), + MAVLINK_MSG_ID_FENCE_STATUS : ( '>BHBI', MAVLink_fence_status_message, [0, 1, 2, 3], 136 ), + MAVLINK_MSG_ID_AHRS : ( '>fffffff', MAVLink_ahrs_message, [0, 1, 2, 3, 4, 5, 6], 127 ), + MAVLINK_MSG_ID_SIMSTATE : ( '>fffffffff', MAVLink_simstate_message, [0, 1, 2, 3, 4, 5, 6, 7, 8], 42 ), + MAVLINK_MSG_ID_HWSTATUS : ( '>HB', MAVLink_hwstatus_message, [0, 1], 21 ), + MAVLINK_MSG_ID_RADIO : ( '>BBBBBHH', MAVLink_radio_message, [0, 1, 2, 3, 4, 5, 6], 93 ), + MAVLINK_MSG_ID_HEARTBEAT : ( '>BBB', MAVLink_heartbeat_message, [0, 1, 2], 72 ), + MAVLINK_MSG_ID_BOOT : ( '>I', MAVLink_boot_message, [0], 39 ), + MAVLINK_MSG_ID_SYSTEM_TIME : ( '>Q', MAVLink_system_time_message, [0], 190 ), + MAVLINK_MSG_ID_PING : ( '>IBBQ', MAVLink_ping_message, [0, 1, 2, 3], 92 ), + MAVLINK_MSG_ID_SYSTEM_TIME_UTC : ( '>II', MAVLink_system_time_utc_message, [0, 1], 191 ), + MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL : ( '>BBB25s', MAVLink_change_operator_control_message, [0, 1, 2, 3], 217 ), + MAVLINK_MSG_ID_CHANGE_OPERATOR_CONTROL_ACK : ( '>BBB', MAVLink_change_operator_control_ack_message, [0, 1, 2], 104 ), + MAVLINK_MSG_ID_AUTH_KEY : ( '>32s', MAVLink_auth_key_message, [0], 119 ), + MAVLINK_MSG_ID_ACTION_ACK : ( '>BB', MAVLink_action_ack_message, [0, 1], 219 ), + MAVLINK_MSG_ID_ACTION : ( '>BBB', MAVLink_action_message, [0, 1, 2], 60 ), + MAVLINK_MSG_ID_SET_MODE : ( '>BB', MAVLink_set_mode_message, [0, 1], 186 ), + MAVLINK_MSG_ID_SET_NAV_MODE : ( '>BB', MAVLink_set_nav_mode_message, [0, 1], 10 ), + MAVLINK_MSG_ID_PARAM_REQUEST_READ : ( '>BB15sh', MAVLink_param_request_read_message, [0, 1, 2, 3], 89 ), + MAVLINK_MSG_ID_PARAM_REQUEST_LIST : ( '>BB', MAVLink_param_request_list_message, [0, 1], 159 ), + MAVLINK_MSG_ID_PARAM_VALUE : ( '>15sfHH', MAVLink_param_value_message, [0, 1, 2, 3], 162 ), + MAVLINK_MSG_ID_PARAM_SET : ( '>BB15sf', MAVLink_param_set_message, [0, 1, 2, 3], 121 ), + MAVLINK_MSG_ID_GPS_RAW_INT : ( '>QBiiiffff', MAVLink_gps_raw_int_message, [0, 1, 2, 3, 4, 5, 6, 7, 8], 149 ), + MAVLINK_MSG_ID_SCALED_IMU : ( '>Qhhhhhhhhh', MAVLink_scaled_imu_message, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 222 ), + MAVLINK_MSG_ID_GPS_STATUS : ( '>B20s20s20s20s20s', MAVLink_gps_status_message, [0, 1, 2, 3, 4, 5], 110 ), + MAVLINK_MSG_ID_RAW_IMU : ( '>Qhhhhhhhhh', MAVLink_raw_imu_message, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 179 ), + MAVLINK_MSG_ID_RAW_PRESSURE : ( '>Qhhhh', MAVLink_raw_pressure_message, [0, 1, 2, 3, 4], 136 ), + MAVLINK_MSG_ID_SCALED_PRESSURE : ( '>Qffh', MAVLink_scaled_pressure_message, [0, 1, 2, 3], 229 ), + MAVLINK_MSG_ID_ATTITUDE : ( '>Qffffff', MAVLink_attitude_message, [0, 1, 2, 3, 4, 5, 6], 66 ), + MAVLINK_MSG_ID_LOCAL_POSITION : ( '>Qffffff', MAVLink_local_position_message, [0, 1, 2, 3, 4, 5, 6], 126 ), + MAVLINK_MSG_ID_GLOBAL_POSITION : ( '>Qffffff', MAVLink_global_position_message, [0, 1, 2, 3, 4, 5, 6], 147 ), + MAVLINK_MSG_ID_GPS_RAW : ( '>QBfffffff', MAVLink_gps_raw_message, [0, 1, 2, 3, 4, 5, 6, 7, 8], 185 ), + MAVLINK_MSG_ID_SYS_STATUS : ( '>BBBHHHH', MAVLink_sys_status_message, [0, 1, 2, 3, 4, 5, 6], 112 ), + MAVLINK_MSG_ID_RC_CHANNELS_RAW : ( '>HHHHHHHHB', MAVLink_rc_channels_raw_message, [0, 1, 2, 3, 4, 5, 6, 7, 8], 252 ), + MAVLINK_MSG_ID_RC_CHANNELS_SCALED : ( '>hhhhhhhhB', MAVLink_rc_channels_scaled_message, [0, 1, 2, 3, 4, 5, 6, 7, 8], 162 ), + MAVLINK_MSG_ID_SERVO_OUTPUT_RAW : ( '>HHHHHHHH', MAVLink_servo_output_raw_message, [0, 1, 2, 3, 4, 5, 6, 7], 215 ), + MAVLINK_MSG_ID_WAYPOINT : ( '>BBHBBBBfffffff', MAVLink_waypoint_message, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 128 ), + MAVLINK_MSG_ID_WAYPOINT_REQUEST : ( '>BBH', MAVLink_waypoint_request_message, [0, 1, 2], 9 ), + MAVLINK_MSG_ID_WAYPOINT_SET_CURRENT : ( '>BBH', MAVLink_waypoint_set_current_message, [0, 1, 2], 106 ), + MAVLINK_MSG_ID_WAYPOINT_CURRENT : ( '>H', MAVLink_waypoint_current_message, [0], 101 ), + MAVLINK_MSG_ID_WAYPOINT_REQUEST_LIST : ( '>BB', MAVLink_waypoint_request_list_message, [0, 1], 213 ), + MAVLINK_MSG_ID_WAYPOINT_COUNT : ( '>BBH', MAVLink_waypoint_count_message, [0, 1, 2], 4 ), + MAVLINK_MSG_ID_WAYPOINT_CLEAR_ALL : ( '>BB', MAVLink_waypoint_clear_all_message, [0, 1], 229 ), + MAVLINK_MSG_ID_WAYPOINT_REACHED : ( '>H', MAVLink_waypoint_reached_message, [0], 21 ), + MAVLINK_MSG_ID_WAYPOINT_ACK : ( '>BBB', MAVLink_waypoint_ack_message, [0, 1, 2], 214 ), + MAVLINK_MSG_ID_GPS_SET_GLOBAL_ORIGIN : ( '>BBiii', MAVLink_gps_set_global_origin_message, [0, 1, 2, 3, 4], 215 ), + MAVLINK_MSG_ID_GPS_LOCAL_ORIGIN_SET : ( '>iii', MAVLink_gps_local_origin_set_message, [0, 1, 2], 14 ), + MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT_SET : ( '>BBffff', MAVLink_local_position_setpoint_set_message, [0, 1, 2, 3, 4, 5], 206 ), + MAVLINK_MSG_ID_LOCAL_POSITION_SETPOINT : ( '>ffff', MAVLink_local_position_setpoint_message, [0, 1, 2, 3], 50 ), + MAVLINK_MSG_ID_CONTROL_STATUS : ( '>BBBBBBBB', MAVLink_control_status_message, [0, 1, 2, 3, 4, 5, 6, 7], 157 ), + MAVLINK_MSG_ID_SAFETY_SET_ALLOWED_AREA : ( '>BBBffffff', MAVLink_safety_set_allowed_area_message, [0, 1, 2, 3, 4, 5, 6, 7, 8], 126 ), + MAVLINK_MSG_ID_SAFETY_ALLOWED_AREA : ( '>Bffffff', MAVLink_safety_allowed_area_message, [0, 1, 2, 3, 4, 5, 6], 108 ), + MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_THRUST : ( '>BBffff', MAVLink_set_roll_pitch_yaw_thrust_message, [0, 1, 2, 3, 4, 5], 213 ), + MAVLINK_MSG_ID_SET_ROLL_PITCH_YAW_SPEED_THRUST : ( '>BBffff', MAVLink_set_roll_pitch_yaw_speed_thrust_message, [0, 1, 2, 3, 4, 5], 95 ), + MAVLINK_MSG_ID_ROLL_PITCH_YAW_THRUST_SETPOINT : ( '>Qffff', MAVLink_roll_pitch_yaw_thrust_setpoint_message, [0, 1, 2, 3, 4], 5 ), + MAVLINK_MSG_ID_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT : ( '>Qffff', MAVLink_roll_pitch_yaw_speed_thrust_setpoint_message, [0, 1, 2, 3, 4], 127 ), + MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT : ( '>ffhhHfff', MAVLink_nav_controller_output_message, [0, 1, 2, 3, 4, 5, 6, 7], 57 ), + MAVLINK_MSG_ID_POSITION_TARGET : ( '>ffff', MAVLink_position_target_message, [0, 1, 2, 3], 126 ), + MAVLINK_MSG_ID_STATE_CORRECTION : ( '>fffffffff', MAVLink_state_correction_message, [0, 1, 2, 3, 4, 5, 6, 7, 8], 130 ), + MAVLINK_MSG_ID_SET_ALTITUDE : ( '>BI', MAVLink_set_altitude_message, [0, 1], 119 ), + MAVLINK_MSG_ID_REQUEST_DATA_STREAM : ( '>BBBHB', MAVLink_request_data_stream_message, [0, 1, 2, 3, 4], 193 ), + MAVLINK_MSG_ID_HIL_STATE : ( '>Qffffffiiihhhhhh', MAVLink_hil_state_message, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 191 ), + MAVLINK_MSG_ID_HIL_CONTROLS : ( '>QffffBB', MAVLink_hil_controls_message, [0, 1, 2, 3, 4, 5, 6], 236 ), + MAVLINK_MSG_ID_MANUAL_CONTROL : ( '>BffffBBBB', MAVLink_manual_control_message, [0, 1, 2, 3, 4, 5, 6, 7, 8], 158 ), + MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE : ( '>BBHHHHHHHH', MAVLink_rc_channels_override_message, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 143 ), + MAVLINK_MSG_ID_GLOBAL_POSITION_INT : ( '>iiihhh', MAVLink_global_position_int_message, [0, 1, 2, 3, 4, 5], 104 ), + MAVLINK_MSG_ID_VFR_HUD : ( '>ffhHff', MAVLink_vfr_hud_message, [0, 1, 2, 3, 4, 5], 123 ), + MAVLINK_MSG_ID_COMMAND : ( '>BBBBffff', MAVLink_command_message, [0, 1, 2, 3, 4, 5, 6, 7], 131 ), + MAVLINK_MSG_ID_COMMAND_ACK : ( '>ff', MAVLink_command_ack_message, [0, 1], 8 ), + MAVLINK_MSG_ID_OPTICAL_FLOW : ( '>QBhhBf', MAVLink_optical_flow_message, [0, 1, 2, 3, 4, 5], 174 ), + MAVLINK_MSG_ID_OBJECT_DETECTION_EVENT : ( '>IHB20sBff', MAVLink_object_detection_event_message, [0, 1, 2, 3, 4, 5, 6], 155 ), + MAVLINK_MSG_ID_DEBUG_VECT : ( '>10sQfff', MAVLink_debug_vect_message, [0, 1, 2, 3, 4], 178 ), + MAVLINK_MSG_ID_NAMED_VALUE_FLOAT : ( '>10sf', MAVLink_named_value_float_message, [0, 1], 224 ), + MAVLINK_MSG_ID_NAMED_VALUE_INT : ( '>10si', MAVLink_named_value_int_message, [0, 1], 60 ), + MAVLINK_MSG_ID_STATUSTEXT : ( '>B50s', MAVLink_statustext_message, [0, 1], 106 ), + MAVLINK_MSG_ID_DEBUG : ( '>Bf', MAVLink_debug_message, [0, 1], 7 ), +} + +class MAVError(Exception): + '''MAVLink error class''' + def __init__(self, msg): + Exception.__init__(self, msg) + self.message = msg + +class MAVString(str): + '''NUL terminated string''' + def __init__(self, s): + str.__init__(self) + def __str__(self): + i = self.find(chr(0)) + if i == -1: + return self[:] + return self[0:i] + +class MAVLink_bad_data(MAVLink_message): + ''' + a piece of bad data in a mavlink stream + ''' + def __init__(self, data, reason): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_BAD_DATA, 'BAD_DATA') + self._fieldnames = ['data', 'reason'] + self.data = data + self.reason = reason + self._msgbuf = data + +class MAVLink(object): + '''MAVLink protocol handling class''' + def __init__(self, file, srcSystem=0, srcComponent=0): + self.seq = 0 + self.file = file + self.srcSystem = srcSystem + self.srcComponent = srcComponent + self.callback = None + self.callback_args = None + self.callback_kwargs = None + self.buf = array.array('B') + self.expected_length = 6 + self.have_prefix_error = False + self.robust_parsing = False + self.protocol_marker = 85 + self.little_endian = False + self.crc_extra = False + self.sort_fields = False + self.total_packets_sent = 0 + self.total_bytes_sent = 0 + self.total_packets_received = 0 + self.total_bytes_received = 0 + self.total_receive_errors = 0 + self.startup_time = time.time() + + def set_callback(self, callback, *args, **kwargs): + self.callback = callback + self.callback_args = args + self.callback_kwargs = kwargs + + def send(self, mavmsg): + '''send a MAVLink message''' + buf = mavmsg.pack(self) + self.file.write(buf) + self.seq = (self.seq + 1) % 255 + self.total_packets_sent += 1 + self.total_bytes_sent += len(buf) + + def bytes_needed(self): + '''return number of bytes needed for next parsing stage''' + ret = self.expected_length - len(self.buf) + if ret <= 0: + return 1 + return ret + + def parse_char(self, c): + '''input some data bytes, possibly returning a new message''' + if isinstance(c, str): + self.buf.fromstring(c) + else: + self.buf.extend(c) + self.total_bytes_received += len(c) + if len(self.buf) >= 1 and self.buf[0] != 85: + magic = self.buf[0] + self.buf = self.buf[1:] + if self.robust_parsing: + m = MAVLink_bad_data(chr(magic), "Bad prefix") + if self.callback: + self.callback(m, *self.callback_args, **self.callback_kwargs) + self.expected_length = 6 + self.total_receive_errors += 1 + return m + if self.have_prefix_error: + return None + self.have_prefix_error = True + self.total_receive_errors += 1 + raise MAVError("invalid MAVLink prefix '%s'" % magic) + self.have_prefix_error = False + if len(self.buf) >= 2: + (magic, self.expected_length) = struct.unpack('BB', self.buf[0:2]) + self.expected_length += 8 + if self.expected_length >= 8 and len(self.buf) >= self.expected_length: + mbuf = self.buf[0:self.expected_length] + self.buf = self.buf[self.expected_length:] + self.expected_length = 6 + if self.robust_parsing: + try: + m = self.decode(mbuf) + self.total_packets_received += 1 + except MAVError as reason: + m = MAVLink_bad_data(mbuf, reason.message) + self.total_receive_errors += 1 + else: + m = self.decode(mbuf) + self.total_packets_received += 1 + if self.callback: + self.callback(m, *self.callback_args, **self.callback_kwargs) + return m + return None + + def parse_buffer(self, s): + '''input some data bytes, possibly returning a list of new messages''' + m = self.parse_char(s) + if m is None: + return None + ret = [m] + while True: + m = self.parse_char("") + if m is None: + return ret + ret.append(m) + return ret + + def decode(self, msgbuf): + '''decode a buffer as a MAVLink message''' + # decode the header + try: + magic, mlen, seq, srcSystem, srcComponent, msgId = struct.unpack('cBBBBB', msgbuf[:6]) + except struct.error as emsg: + raise MAVError('Unable to unpack MAVLink header: %s' % emsg) + if ord(magic) != 85: + raise MAVError("invalid MAVLink prefix '%s'" % magic) + if mlen != len(msgbuf)-8: + raise MAVError('invalid MAVLink message length. Got %u expected %u, msgId=%u' % (len(msgbuf)-8, mlen, msgId)) + + if not msgId in mavlink_map: + raise MAVError('unknown MAVLink message ID %u' % msgId) + + # decode the payload + (fmt, type, order_map, crc_extra) = mavlink_map[msgId] + + # decode the checksum + try: + crc, = struct.unpack(' MAV. + Also used to return a point from MAV -> GCS + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + idx : point index (first point is 1, 0 is for return point) (uint8_t) + count : total number of points (for sanity checking) (uint8_t) + lat : Latitude of point (float) + lng : Longitude of point (float) + + ''' + msg = MAVLink_fence_point_message(target_system, target_component, idx, count, lat, lng) + msg.pack(self) + return msg + + def fence_point_send(self, target_system, target_component, idx, count, lat, lng): + ''' + A fence point. Used to set a point when from GCS -> MAV. + Also used to return a point from MAV -> GCS + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + idx : point index (first point is 1, 0 is for return point) (uint8_t) + count : total number of points (for sanity checking) (uint8_t) + lat : Latitude of point (float) + lng : Longitude of point (float) + + ''' + return self.send(self.fence_point_encode(target_system, target_component, idx, count, lat, lng)) + + def fence_fetch_point_encode(self, target_system, target_component, idx): + ''' + Request a current fence point from MAV + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + idx : point index (first point is 1, 0 is for return point) (uint8_t) + + ''' + msg = MAVLink_fence_fetch_point_message(target_system, target_component, idx) + msg.pack(self) + return msg + + def fence_fetch_point_send(self, target_system, target_component, idx): + ''' + Request a current fence point from MAV + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + idx : point index (first point is 1, 0 is for return point) (uint8_t) + + ''' + return self.send(self.fence_fetch_point_encode(target_system, target_component, idx)) + + def fence_status_encode(self, breach_status, breach_count, breach_type, breach_time): + ''' + Status of geo-fencing. Sent in extended status stream when + fencing enabled + + breach_status : 0 if currently inside fence, 1 if outside (uint8_t) + breach_count : number of fence breaches (uint16_t) + breach_type : last breach type (see FENCE_BREACH_* enum) (uint8_t) + breach_time : time of last breach in milliseconds since boot (uint32_t) + + ''' + msg = MAVLink_fence_status_message(breach_status, breach_count, breach_type, breach_time) + msg.pack(self) + return msg + + def fence_status_send(self, breach_status, breach_count, breach_type, breach_time): + ''' + Status of geo-fencing. Sent in extended status stream when + fencing enabled + + breach_status : 0 if currently inside fence, 1 if outside (uint8_t) + breach_count : number of fence breaches (uint16_t) + breach_type : last breach type (see FENCE_BREACH_* enum) (uint8_t) + breach_time : time of last breach in milliseconds since boot (uint32_t) + + ''' + return self.send(self.fence_status_encode(breach_status, breach_count, breach_type, breach_time)) + + def ahrs_encode(self, omegaIx, omegaIy, omegaIz, accel_weight, renorm_val, error_rp, error_yaw): + ''' + Status of DCM attitude estimator + + omegaIx : X gyro drift estimate rad/s (float) + omegaIy : Y gyro drift estimate rad/s (float) + omegaIz : Z gyro drift estimate rad/s (float) + accel_weight : average accel_weight (float) + renorm_val : average renormalisation value (float) + error_rp : average error_roll_pitch value (float) + error_yaw : average error_yaw value (float) + + ''' + msg = MAVLink_ahrs_message(omegaIx, omegaIy, omegaIz, accel_weight, renorm_val, error_rp, error_yaw) + msg.pack(self) + return msg + + def ahrs_send(self, omegaIx, omegaIy, omegaIz, accel_weight, renorm_val, error_rp, error_yaw): + ''' + Status of DCM attitude estimator + + omegaIx : X gyro drift estimate rad/s (float) + omegaIy : Y gyro drift estimate rad/s (float) + omegaIz : Z gyro drift estimate rad/s (float) + accel_weight : average accel_weight (float) + renorm_val : average renormalisation value (float) + error_rp : average error_roll_pitch value (float) + error_yaw : average error_yaw value (float) + + ''' + return self.send(self.ahrs_encode(omegaIx, omegaIy, omegaIz, accel_weight, renorm_val, error_rp, error_yaw)) + + def simstate_encode(self, roll, pitch, yaw, xacc, yacc, zacc, xgyro, ygyro, zgyro): + ''' + Status of simulation environment, if used + + roll : Roll angle (rad) (float) + pitch : Pitch angle (rad) (float) + yaw : Yaw angle (rad) (float) + xacc : X acceleration m/s/s (float) + yacc : Y acceleration m/s/s (float) + zacc : Z acceleration m/s/s (float) + xgyro : Angular speed around X axis rad/s (float) + ygyro : Angular speed around Y axis rad/s (float) + zgyro : Angular speed around Z axis rad/s (float) + + ''' + msg = MAVLink_simstate_message(roll, pitch, yaw, xacc, yacc, zacc, xgyro, ygyro, zgyro) + msg.pack(self) + return msg + + def simstate_send(self, roll, pitch, yaw, xacc, yacc, zacc, xgyro, ygyro, zgyro): + ''' + Status of simulation environment, if used + + roll : Roll angle (rad) (float) + pitch : Pitch angle (rad) (float) + yaw : Yaw angle (rad) (float) + xacc : X acceleration m/s/s (float) + yacc : Y acceleration m/s/s (float) + zacc : Z acceleration m/s/s (float) + xgyro : Angular speed around X axis rad/s (float) + ygyro : Angular speed around Y axis rad/s (float) + zgyro : Angular speed around Z axis rad/s (float) + + ''' + return self.send(self.simstate_encode(roll, pitch, yaw, xacc, yacc, zacc, xgyro, ygyro, zgyro)) + + def hwstatus_encode(self, Vcc, I2Cerr): + ''' + Status of key hardware + + Vcc : board voltage (mV) (uint16_t) + I2Cerr : I2C error count (uint8_t) + + ''' + msg = MAVLink_hwstatus_message(Vcc, I2Cerr) + msg.pack(self) + return msg + + def hwstatus_send(self, Vcc, I2Cerr): + ''' + Status of key hardware + + Vcc : board voltage (mV) (uint16_t) + I2Cerr : I2C error count (uint8_t) + + ''' + return self.send(self.hwstatus_encode(Vcc, I2Cerr)) + + def radio_encode(self, rssi, remrssi, txbuf, noise, remnoise, rxerrors, fixed): + ''' + Status generated by radio + + rssi : local signal strength (uint8_t) + remrssi : remote signal strength (uint8_t) + txbuf : how full the tx buffer is as a percentage (uint8_t) + noise : background noise level (uint8_t) + remnoise : remote background noise level (uint8_t) + rxerrors : receive errors (uint16_t) + fixed : count of error corrected packets (uint16_t) + + ''' + msg = MAVLink_radio_message(rssi, remrssi, txbuf, noise, remnoise, rxerrors, fixed) + msg.pack(self) + return msg + + def radio_send(self, rssi, remrssi, txbuf, noise, remnoise, rxerrors, fixed): + ''' + Status generated by radio + + rssi : local signal strength (uint8_t) + remrssi : remote signal strength (uint8_t) + txbuf : how full the tx buffer is as a percentage (uint8_t) + noise : background noise level (uint8_t) + remnoise : remote background noise level (uint8_t) + rxerrors : receive errors (uint16_t) + fixed : count of error corrected packets (uint16_t) + + ''' + return self.send(self.radio_encode(rssi, remrssi, txbuf, noise, remnoise, rxerrors, fixed)) + + def heartbeat_encode(self, type, autopilot, mavlink_version=2): + ''' + The heartbeat message shows that a system is present and responding. + The type of the MAV and Autopilot hardware allow the + receiving system to treat further messages from this + system appropriate (e.g. by laying out the user + interface based on the autopilot). + + type : Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) (uint8_t) + autopilot : Type of the Autopilot: 0: Generic, 1: PIXHAWK, 2: SLUGS, 3: Ardupilot (up to 15 types), defined in MAV_AUTOPILOT_TYPE ENUM (uint8_t) + mavlink_version : MAVLink version (uint8_t) + + ''' + msg = MAVLink_heartbeat_message(type, autopilot, mavlink_version) + msg.pack(self) + return msg + + def heartbeat_send(self, type, autopilot, mavlink_version=2): + ''' + The heartbeat message shows that a system is present and responding. + The type of the MAV and Autopilot hardware allow the + receiving system to treat further messages from this + system appropriate (e.g. by laying out the user + interface based on the autopilot). + + type : Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) (uint8_t) + autopilot : Type of the Autopilot: 0: Generic, 1: PIXHAWK, 2: SLUGS, 3: Ardupilot (up to 15 types), defined in MAV_AUTOPILOT_TYPE ENUM (uint8_t) + mavlink_version : MAVLink version (uint8_t) + + ''' + return self.send(self.heartbeat_encode(type, autopilot, mavlink_version)) + + def boot_encode(self, version): + ''' + The boot message indicates that a system is starting. The onboard + software version allows to keep track of onboard + soft/firmware revisions. + + version : The onboard software version (uint32_t) + + ''' + msg = MAVLink_boot_message(version) + msg.pack(self) + return msg + + def boot_send(self, version): + ''' + The boot message indicates that a system is starting. The onboard + software version allows to keep track of onboard + soft/firmware revisions. + + version : The onboard software version (uint32_t) + + ''' + return self.send(self.boot_encode(version)) + + def system_time_encode(self, time_usec): + ''' + The system time is the time of the master clock, typically the + computer clock of the main onboard computer. + + time_usec : Timestamp of the master clock in microseconds since UNIX epoch. (uint64_t) + + ''' + msg = MAVLink_system_time_message(time_usec) + msg.pack(self) + return msg + + def system_time_send(self, time_usec): + ''' + The system time is the time of the master clock, typically the + computer clock of the main onboard computer. + + time_usec : Timestamp of the master clock in microseconds since UNIX epoch. (uint64_t) + + ''' + return self.send(self.system_time_encode(time_usec)) + + def ping_encode(self, seq, target_system, target_component, time): + ''' + A ping message either requesting or responding to a ping. This allows + to measure the system latencies, including serial + port, radio modem and UDP connections. + + seq : PING sequence (uint32_t) + target_system : 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system (uint8_t) + target_component : 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system (uint8_t) + time : Unix timestamp in microseconds (uint64_t) + + ''' + msg = MAVLink_ping_message(seq, target_system, target_component, time) + msg.pack(self) + return msg + + def ping_send(self, seq, target_system, target_component, time): + ''' + A ping message either requesting or responding to a ping. This allows + to measure the system latencies, including serial + port, radio modem and UDP connections. + + seq : PING sequence (uint32_t) + target_system : 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system (uint8_t) + target_component : 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system (uint8_t) + time : Unix timestamp in microseconds (uint64_t) + + ''' + return self.send(self.ping_encode(seq, target_system, target_component, time)) + + def system_time_utc_encode(self, utc_date, utc_time): + ''' + UTC date and time from GPS module + + utc_date : GPS UTC date ddmmyy (uint32_t) + utc_time : GPS UTC time hhmmss (uint32_t) + + ''' + msg = MAVLink_system_time_utc_message(utc_date, utc_time) + msg.pack(self) + return msg + + def system_time_utc_send(self, utc_date, utc_time): + ''' + UTC date and time from GPS module + + utc_date : GPS UTC date ddmmyy (uint32_t) + utc_time : GPS UTC time hhmmss (uint32_t) + + ''' + return self.send(self.system_time_utc_encode(utc_date, utc_time)) + + def change_operator_control_encode(self, target_system, control_request, version, passkey): + ''' + Request to control this MAV + + target_system : System the GCS requests control for (uint8_t) + control_request : 0: request control of this MAV, 1: Release control of this MAV (uint8_t) + version : 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. (uint8_t) + passkey : Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" (char) + + ''' + msg = MAVLink_change_operator_control_message(target_system, control_request, version, passkey) + msg.pack(self) + return msg + + def change_operator_control_send(self, target_system, control_request, version, passkey): + ''' + Request to control this MAV + + target_system : System the GCS requests control for (uint8_t) + control_request : 0: request control of this MAV, 1: Release control of this MAV (uint8_t) + version : 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. (uint8_t) + passkey : Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" (char) + + ''' + return self.send(self.change_operator_control_encode(target_system, control_request, version, passkey)) + + def change_operator_control_ack_encode(self, gcs_system_id, control_request, ack): + ''' + Accept / deny control of this MAV + + gcs_system_id : ID of the GCS this message (uint8_t) + control_request : 0: request control of this MAV, 1: Release control of this MAV (uint8_t) + ack : 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control (uint8_t) + + ''' + msg = MAVLink_change_operator_control_ack_message(gcs_system_id, control_request, ack) + msg.pack(self) + return msg + + def change_operator_control_ack_send(self, gcs_system_id, control_request, ack): + ''' + Accept / deny control of this MAV + + gcs_system_id : ID of the GCS this message (uint8_t) + control_request : 0: request control of this MAV, 1: Release control of this MAV (uint8_t) + ack : 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control (uint8_t) + + ''' + return self.send(self.change_operator_control_ack_encode(gcs_system_id, control_request, ack)) + + def auth_key_encode(self, key): + ''' + Emit an encrypted signature / key identifying this system. PLEASE + NOTE: This protocol has been kept simple, so + transmitting the key requires an encrypted channel for + true safety. + + key : key (char) + + ''' + msg = MAVLink_auth_key_message(key) + msg.pack(self) + return msg + + def auth_key_send(self, key): + ''' + Emit an encrypted signature / key identifying this system. PLEASE + NOTE: This protocol has been kept simple, so + transmitting the key requires an encrypted channel for + true safety. + + key : key (char) + + ''' + return self.send(self.auth_key_encode(key)) + + def action_ack_encode(self, action, result): + ''' + This message acknowledges an action. IMPORTANT: The acknowledgement + can be also negative, e.g. the MAV rejects a reset + message because it is in-flight. The action ids are + defined in ENUM MAV_ACTION in + mavlink/include/mavlink_types.h + + action : The action id (uint8_t) + result : 0: Action DENIED, 1: Action executed (uint8_t) + + ''' + msg = MAVLink_action_ack_message(action, result) + msg.pack(self) + return msg + + def action_ack_send(self, action, result): + ''' + This message acknowledges an action. IMPORTANT: The acknowledgement + can be also negative, e.g. the MAV rejects a reset + message because it is in-flight. The action ids are + defined in ENUM MAV_ACTION in + mavlink/include/mavlink_types.h + + action : The action id (uint8_t) + result : 0: Action DENIED, 1: Action executed (uint8_t) + + ''' + return self.send(self.action_ack_encode(action, result)) + + def action_encode(self, target, target_component, action): + ''' + An action message allows to execute a certain onboard action. These + include liftoff, land, storing parameters too EEPROM, + shutddown, etc. The action ids are defined in ENUM + MAV_ACTION in mavlink/include/mavlink_types.h + + target : The system executing the action (uint8_t) + target_component : The component executing the action (uint8_t) + action : The action id (uint8_t) + + ''' + msg = MAVLink_action_message(target, target_component, action) + msg.pack(self) + return msg + + def action_send(self, target, target_component, action): + ''' + An action message allows to execute a certain onboard action. These + include liftoff, land, storing parameters too EEPROM, + shutddown, etc. The action ids are defined in ENUM + MAV_ACTION in mavlink/include/mavlink_types.h + + target : The system executing the action (uint8_t) + target_component : The component executing the action (uint8_t) + action : The action id (uint8_t) + + ''' + return self.send(self.action_encode(target, target_component, action)) + + def set_mode_encode(self, target, mode): + ''' + Set the system mode, as defined by enum MAV_MODE in + mavlink/include/mavlink_types.h. There is no target + component id as the mode is by definition for the + overall aircraft, not only for one component. + + target : The system setting the mode (uint8_t) + mode : The new mode (uint8_t) + + ''' + msg = MAVLink_set_mode_message(target, mode) + msg.pack(self) + return msg + + def set_mode_send(self, target, mode): + ''' + Set the system mode, as defined by enum MAV_MODE in + mavlink/include/mavlink_types.h. There is no target + component id as the mode is by definition for the + overall aircraft, not only for one component. + + target : The system setting the mode (uint8_t) + mode : The new mode (uint8_t) + + ''' + return self.send(self.set_mode_encode(target, mode)) + + def set_nav_mode_encode(self, target, nav_mode): + ''' + Set the system navigation mode, as defined by enum MAV_NAV_MODE in + mavlink/include/mavlink_types.h. The navigation mode + applies to the whole aircraft and thus all components. + + target : The system setting the mode (uint8_t) + nav_mode : The new navigation mode (uint8_t) + + ''' + msg = MAVLink_set_nav_mode_message(target, nav_mode) + msg.pack(self) + return msg + + def set_nav_mode_send(self, target, nav_mode): + ''' + Set the system navigation mode, as defined by enum MAV_NAV_MODE in + mavlink/include/mavlink_types.h. The navigation mode + applies to the whole aircraft and thus all components. + + target : The system setting the mode (uint8_t) + nav_mode : The new navigation mode (uint8_t) + + ''' + return self.send(self.set_nav_mode_encode(target, nav_mode)) + + def param_request_read_encode(self, target_system, target_component, param_id, param_index): + ''' + Request to read the onboard parameter with the param_id string id. + Onboard parameters are stored as key[const char*] -> + value[float]. This allows to send a parameter to any + other component (such as the GCS) without the need of + previous knowledge of possible parameter names. Thus + the same GCS can store different parameters for + different autopilots. See also + http://qgroundcontrol.org/parameter_interface for a + full documentation of QGroundControl and IMU code. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + param_id : Onboard parameter id (int8_t) + param_index : Parameter index. Send -1 to use the param ID field as identifier (int16_t) + + ''' + msg = MAVLink_param_request_read_message(target_system, target_component, param_id, param_index) + msg.pack(self) + return msg + + def param_request_read_send(self, target_system, target_component, param_id, param_index): + ''' + Request to read the onboard parameter with the param_id string id. + Onboard parameters are stored as key[const char*] -> + value[float]. This allows to send a parameter to any + other component (such as the GCS) without the need of + previous knowledge of possible parameter names. Thus + the same GCS can store different parameters for + different autopilots. See also + http://qgroundcontrol.org/parameter_interface for a + full documentation of QGroundControl and IMU code. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + param_id : Onboard parameter id (int8_t) + param_index : Parameter index. Send -1 to use the param ID field as identifier (int16_t) + + ''' + return self.send(self.param_request_read_encode(target_system, target_component, param_id, param_index)) + + def param_request_list_encode(self, target_system, target_component): + ''' + Request all parameters of this component. After his request, all + parameters are emitted. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + + ''' + msg = MAVLink_param_request_list_message(target_system, target_component) + msg.pack(self) + return msg + + def param_request_list_send(self, target_system, target_component): + ''' + Request all parameters of this component. After his request, all + parameters are emitted. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + + ''' + return self.send(self.param_request_list_encode(target_system, target_component)) + + def param_value_encode(self, param_id, param_value, param_count, param_index): + ''' + Emit the value of a onboard parameter. The inclusion of param_count + and param_index in the message allows the recipient to + keep track of received parameters and allows him to + re-request missing parameters after a loss or timeout. + + param_id : Onboard parameter id (int8_t) + param_value : Onboard parameter value (float) + param_count : Total number of onboard parameters (uint16_t) + param_index : Index of this onboard parameter (uint16_t) + + ''' + msg = MAVLink_param_value_message(param_id, param_value, param_count, param_index) + msg.pack(self) + return msg + + def param_value_send(self, param_id, param_value, param_count, param_index): + ''' + Emit the value of a onboard parameter. The inclusion of param_count + and param_index in the message allows the recipient to + keep track of received parameters and allows him to + re-request missing parameters after a loss or timeout. + + param_id : Onboard parameter id (int8_t) + param_value : Onboard parameter value (float) + param_count : Total number of onboard parameters (uint16_t) + param_index : Index of this onboard parameter (uint16_t) + + ''' + return self.send(self.param_value_encode(param_id, param_value, param_count, param_index)) + + def param_set_encode(self, target_system, target_component, param_id, param_value): + ''' + Set a parameter value TEMPORARILY to RAM. It will be reset to default + on system reboot. Send the ACTION + MAV_ACTION_STORAGE_WRITE to PERMANENTLY write the RAM + contents to EEPROM. IMPORTANT: The receiving component + should acknowledge the new parameter value by sending + a param_value message to all communication partners. + This will also ensure that multiple GCS all have an + up-to-date list of all parameters. If the sending GCS + did not receive a PARAM_VALUE message within its + timeout time, it should re-send the PARAM_SET message. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + param_id : Onboard parameter id (int8_t) + param_value : Onboard parameter value (float) + + ''' + msg = MAVLink_param_set_message(target_system, target_component, param_id, param_value) + msg.pack(self) + return msg + + def param_set_send(self, target_system, target_component, param_id, param_value): + ''' + Set a parameter value TEMPORARILY to RAM. It will be reset to default + on system reboot. Send the ACTION + MAV_ACTION_STORAGE_WRITE to PERMANENTLY write the RAM + contents to EEPROM. IMPORTANT: The receiving component + should acknowledge the new parameter value by sending + a param_value message to all communication partners. + This will also ensure that multiple GCS all have an + up-to-date list of all parameters. If the sending GCS + did not receive a PARAM_VALUE message within its + timeout time, it should re-send the PARAM_SET message. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + param_id : Onboard parameter id (int8_t) + param_value : Onboard parameter value (float) + + ''' + return self.send(self.param_set_encode(target_system, target_component, param_id, param_value)) + + def gps_raw_int_encode(self, usec, fix_type, lat, lon, alt, eph, epv, v, hdg): + ''' + The global position, as returned by the Global Positioning System + (GPS). This is NOT the global position estimate of the + sytem, but rather a RAW sensor value. See message + GLOBAL_POSITION for the global position estimate. + Coordinate frame is right-handed, Z-axis up (GPS + frame) + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + fix_type : 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. (uint8_t) + lat : Latitude in 1E7 degrees (int32_t) + lon : Longitude in 1E7 degrees (int32_t) + alt : Altitude in 1E3 meters (millimeters) (int32_t) + eph : GPS HDOP (float) + epv : GPS VDOP (float) + v : GPS ground speed (m/s) (float) + hdg : Compass heading in degrees, 0..360 degrees (float) + + ''' + msg = MAVLink_gps_raw_int_message(usec, fix_type, lat, lon, alt, eph, epv, v, hdg) + msg.pack(self) + return msg + + def gps_raw_int_send(self, usec, fix_type, lat, lon, alt, eph, epv, v, hdg): + ''' + The global position, as returned by the Global Positioning System + (GPS). This is NOT the global position estimate of the + sytem, but rather a RAW sensor value. See message + GLOBAL_POSITION for the global position estimate. + Coordinate frame is right-handed, Z-axis up (GPS + frame) + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + fix_type : 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. (uint8_t) + lat : Latitude in 1E7 degrees (int32_t) + lon : Longitude in 1E7 degrees (int32_t) + alt : Altitude in 1E3 meters (millimeters) (int32_t) + eph : GPS HDOP (float) + epv : GPS VDOP (float) + v : GPS ground speed (m/s) (float) + hdg : Compass heading in degrees, 0..360 degrees (float) + + ''' + return self.send(self.gps_raw_int_encode(usec, fix_type, lat, lon, alt, eph, epv, v, hdg)) + + def scaled_imu_encode(self, usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag): + ''' + The RAW IMU readings for the usual 9DOF sensor setup. This message + should contain the scaled values to the described + units + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + xacc : X acceleration (mg) (int16_t) + yacc : Y acceleration (mg) (int16_t) + zacc : Z acceleration (mg) (int16_t) + xgyro : Angular speed around X axis (millirad /sec) (int16_t) + ygyro : Angular speed around Y axis (millirad /sec) (int16_t) + zgyro : Angular speed around Z axis (millirad /sec) (int16_t) + xmag : X Magnetic field (milli tesla) (int16_t) + ymag : Y Magnetic field (milli tesla) (int16_t) + zmag : Z Magnetic field (milli tesla) (int16_t) + + ''' + msg = MAVLink_scaled_imu_message(usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag) + msg.pack(self) + return msg + + def scaled_imu_send(self, usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag): + ''' + The RAW IMU readings for the usual 9DOF sensor setup. This message + should contain the scaled values to the described + units + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + xacc : X acceleration (mg) (int16_t) + yacc : Y acceleration (mg) (int16_t) + zacc : Z acceleration (mg) (int16_t) + xgyro : Angular speed around X axis (millirad /sec) (int16_t) + ygyro : Angular speed around Y axis (millirad /sec) (int16_t) + zgyro : Angular speed around Z axis (millirad /sec) (int16_t) + xmag : X Magnetic field (milli tesla) (int16_t) + ymag : Y Magnetic field (milli tesla) (int16_t) + zmag : Z Magnetic field (milli tesla) (int16_t) + + ''' + return self.send(self.scaled_imu_encode(usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag)) + + def gps_status_encode(self, satellites_visible, satellite_prn, satellite_used, satellite_elevation, satellite_azimuth, satellite_snr): + ''' + The positioning status, as reported by GPS. This message is intended + to display status information about each satellite + visible to the receiver. See message GLOBAL_POSITION + for the global position estimate. This message can + contain information for up to 20 satellites. + + satellites_visible : Number of satellites visible (uint8_t) + satellite_prn : Global satellite ID (int8_t) + satellite_used : 0: Satellite not used, 1: used for localization (int8_t) + satellite_elevation : Elevation (0: right on top of receiver, 90: on the horizon) of satellite (int8_t) + satellite_azimuth : Direction of satellite, 0: 0 deg, 255: 360 deg. (int8_t) + satellite_snr : Signal to noise ratio of satellite (int8_t) + + ''' + msg = MAVLink_gps_status_message(satellites_visible, satellite_prn, satellite_used, satellite_elevation, satellite_azimuth, satellite_snr) + msg.pack(self) + return msg + + def gps_status_send(self, satellites_visible, satellite_prn, satellite_used, satellite_elevation, satellite_azimuth, satellite_snr): + ''' + The positioning status, as reported by GPS. This message is intended + to display status information about each satellite + visible to the receiver. See message GLOBAL_POSITION + for the global position estimate. This message can + contain information for up to 20 satellites. + + satellites_visible : Number of satellites visible (uint8_t) + satellite_prn : Global satellite ID (int8_t) + satellite_used : 0: Satellite not used, 1: used for localization (int8_t) + satellite_elevation : Elevation (0: right on top of receiver, 90: on the horizon) of satellite (int8_t) + satellite_azimuth : Direction of satellite, 0: 0 deg, 255: 360 deg. (int8_t) + satellite_snr : Signal to noise ratio of satellite (int8_t) + + ''' + return self.send(self.gps_status_encode(satellites_visible, satellite_prn, satellite_used, satellite_elevation, satellite_azimuth, satellite_snr)) + + def raw_imu_encode(self, usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag): + ''' + The RAW IMU readings for the usual 9DOF sensor setup. This message + should always contain the true raw values without any + scaling to allow data capture and system debugging. + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + xacc : X acceleration (raw) (int16_t) + yacc : Y acceleration (raw) (int16_t) + zacc : Z acceleration (raw) (int16_t) + xgyro : Angular speed around X axis (raw) (int16_t) + ygyro : Angular speed around Y axis (raw) (int16_t) + zgyro : Angular speed around Z axis (raw) (int16_t) + xmag : X Magnetic field (raw) (int16_t) + ymag : Y Magnetic field (raw) (int16_t) + zmag : Z Magnetic field (raw) (int16_t) + + ''' + msg = MAVLink_raw_imu_message(usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag) + msg.pack(self) + return msg + + def raw_imu_send(self, usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag): + ''' + The RAW IMU readings for the usual 9DOF sensor setup. This message + should always contain the true raw values without any + scaling to allow data capture and system debugging. + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + xacc : X acceleration (raw) (int16_t) + yacc : Y acceleration (raw) (int16_t) + zacc : Z acceleration (raw) (int16_t) + xgyro : Angular speed around X axis (raw) (int16_t) + ygyro : Angular speed around Y axis (raw) (int16_t) + zgyro : Angular speed around Z axis (raw) (int16_t) + xmag : X Magnetic field (raw) (int16_t) + ymag : Y Magnetic field (raw) (int16_t) + zmag : Z Magnetic field (raw) (int16_t) + + ''' + return self.send(self.raw_imu_encode(usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag)) + + def raw_pressure_encode(self, usec, press_abs, press_diff1, press_diff2, temperature): + ''' + The RAW pressure readings for the typical setup of one absolute + pressure and one differential pressure sensor. The + sensor values should be the raw, UNSCALED ADC values. + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + press_abs : Absolute pressure (raw) (int16_t) + press_diff1 : Differential pressure 1 (raw) (int16_t) + press_diff2 : Differential pressure 2 (raw) (int16_t) + temperature : Raw Temperature measurement (raw) (int16_t) + + ''' + msg = MAVLink_raw_pressure_message(usec, press_abs, press_diff1, press_diff2, temperature) + msg.pack(self) + return msg + + def raw_pressure_send(self, usec, press_abs, press_diff1, press_diff2, temperature): + ''' + The RAW pressure readings for the typical setup of one absolute + pressure and one differential pressure sensor. The + sensor values should be the raw, UNSCALED ADC values. + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + press_abs : Absolute pressure (raw) (int16_t) + press_diff1 : Differential pressure 1 (raw) (int16_t) + press_diff2 : Differential pressure 2 (raw) (int16_t) + temperature : Raw Temperature measurement (raw) (int16_t) + + ''' + return self.send(self.raw_pressure_encode(usec, press_abs, press_diff1, press_diff2, temperature)) + + def scaled_pressure_encode(self, usec, press_abs, press_diff, temperature): + ''' + The pressure readings for the typical setup of one absolute and + differential pressure sensor. The units are as + specified in each field. + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + press_abs : Absolute pressure (hectopascal) (float) + press_diff : Differential pressure 1 (hectopascal) (float) + temperature : Temperature measurement (0.01 degrees celsius) (int16_t) + + ''' + msg = MAVLink_scaled_pressure_message(usec, press_abs, press_diff, temperature) + msg.pack(self) + return msg + + def scaled_pressure_send(self, usec, press_abs, press_diff, temperature): + ''' + The pressure readings for the typical setup of one absolute and + differential pressure sensor. The units are as + specified in each field. + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + press_abs : Absolute pressure (hectopascal) (float) + press_diff : Differential pressure 1 (hectopascal) (float) + temperature : Temperature measurement (0.01 degrees celsius) (int16_t) + + ''' + return self.send(self.scaled_pressure_encode(usec, press_abs, press_diff, temperature)) + + def attitude_encode(self, usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed): + ''' + The attitude in the aeronautical frame (right-handed, Z-down, X-front, + Y-right). + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + roll : Roll angle (rad) (float) + pitch : Pitch angle (rad) (float) + yaw : Yaw angle (rad) (float) + rollspeed : Roll angular speed (rad/s) (float) + pitchspeed : Pitch angular speed (rad/s) (float) + yawspeed : Yaw angular speed (rad/s) (float) + + ''' + msg = MAVLink_attitude_message(usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed) + msg.pack(self) + return msg + + def attitude_send(self, usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed): + ''' + The attitude in the aeronautical frame (right-handed, Z-down, X-front, + Y-right). + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + roll : Roll angle (rad) (float) + pitch : Pitch angle (rad) (float) + yaw : Yaw angle (rad) (float) + rollspeed : Roll angular speed (rad/s) (float) + pitchspeed : Pitch angular speed (rad/s) (float) + yawspeed : Yaw angular speed (rad/s) (float) + + ''' + return self.send(self.attitude_encode(usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed)) + + def local_position_encode(self, usec, x, y, z, vx, vy, vz): + ''' + The filtered local position (e.g. fused computer vision and + accelerometers). Coordinate frame is right-handed, + Z-axis down (aeronautical frame) + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + x : X Position (float) + y : Y Position (float) + z : Z Position (float) + vx : X Speed (float) + vy : Y Speed (float) + vz : Z Speed (float) + + ''' + msg = MAVLink_local_position_message(usec, x, y, z, vx, vy, vz) + msg.pack(self) + return msg + + def local_position_send(self, usec, x, y, z, vx, vy, vz): + ''' + The filtered local position (e.g. fused computer vision and + accelerometers). Coordinate frame is right-handed, + Z-axis down (aeronautical frame) + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + x : X Position (float) + y : Y Position (float) + z : Z Position (float) + vx : X Speed (float) + vy : Y Speed (float) + vz : Z Speed (float) + + ''' + return self.send(self.local_position_encode(usec, x, y, z, vx, vy, vz)) + + def global_position_encode(self, usec, lat, lon, alt, vx, vy, vz): + ''' + The filtered global position (e.g. fused GPS and accelerometers). + Coordinate frame is right-handed, Z-axis up (GPS + frame) + + usec : Timestamp (microseconds since unix epoch) (uint64_t) + lat : Latitude, in degrees (float) + lon : Longitude, in degrees (float) + alt : Absolute altitude, in meters (float) + vx : X Speed (in Latitude direction, positive: going north) (float) + vy : Y Speed (in Longitude direction, positive: going east) (float) + vz : Z Speed (in Altitude direction, positive: going up) (float) + + ''' + msg = MAVLink_global_position_message(usec, lat, lon, alt, vx, vy, vz) + msg.pack(self) + return msg + + def global_position_send(self, usec, lat, lon, alt, vx, vy, vz): + ''' + The filtered global position (e.g. fused GPS and accelerometers). + Coordinate frame is right-handed, Z-axis up (GPS + frame) + + usec : Timestamp (microseconds since unix epoch) (uint64_t) + lat : Latitude, in degrees (float) + lon : Longitude, in degrees (float) + alt : Absolute altitude, in meters (float) + vx : X Speed (in Latitude direction, positive: going north) (float) + vy : Y Speed (in Longitude direction, positive: going east) (float) + vz : Z Speed (in Altitude direction, positive: going up) (float) + + ''' + return self.send(self.global_position_encode(usec, lat, lon, alt, vx, vy, vz)) + + def gps_raw_encode(self, usec, fix_type, lat, lon, alt, eph, epv, v, hdg): + ''' + The global position, as returned by the Global Positioning System + (GPS). This is NOT the global position estimate of the + sytem, but rather a RAW sensor value. See message + GLOBAL_POSITION for the global position estimate. + Coordinate frame is right-handed, Z-axis up (GPS + frame) + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + fix_type : 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. (uint8_t) + lat : Latitude in degrees (float) + lon : Longitude in degrees (float) + alt : Altitude in meters (float) + eph : GPS HDOP (float) + epv : GPS VDOP (float) + v : GPS ground speed (float) + hdg : Compass heading in degrees, 0..360 degrees (float) + + ''' + msg = MAVLink_gps_raw_message(usec, fix_type, lat, lon, alt, eph, epv, v, hdg) + msg.pack(self) + return msg + + def gps_raw_send(self, usec, fix_type, lat, lon, alt, eph, epv, v, hdg): + ''' + The global position, as returned by the Global Positioning System + (GPS). This is NOT the global position estimate of the + sytem, but rather a RAW sensor value. See message + GLOBAL_POSITION for the global position estimate. + Coordinate frame is right-handed, Z-axis up (GPS + frame) + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + fix_type : 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. (uint8_t) + lat : Latitude in degrees (float) + lon : Longitude in degrees (float) + alt : Altitude in meters (float) + eph : GPS HDOP (float) + epv : GPS VDOP (float) + v : GPS ground speed (float) + hdg : Compass heading in degrees, 0..360 degrees (float) + + ''' + return self.send(self.gps_raw_encode(usec, fix_type, lat, lon, alt, eph, epv, v, hdg)) + + def sys_status_encode(self, mode, nav_mode, status, load, vbat, battery_remaining, packet_drop): + ''' + The general system state. If the system is following the MAVLink + standard, the system state is mainly defined by three + orthogonal states/modes: The system mode, which is + either LOCKED (motors shut down and locked), MANUAL + (system under RC control), GUIDED (system with + autonomous position control, position setpoint + controlled manually) or AUTO (system guided by + path/waypoint planner). The NAV_MODE defined the + current flight state: LIFTOFF (often an open-loop + maneuver), LANDING, WAYPOINTS or VECTOR. This + represents the internal navigation state machine. The + system status shows wether the system is currently + active or not and if an emergency occured. During the + CRITICAL and EMERGENCY states the MAV is still + considered to be active, but should start emergency + procedures autonomously. After a failure occured it + should first move from active to critical to allow + manual intervention and then move to emergency after a + certain timeout. + + mode : System mode, see MAV_MODE ENUM in mavlink/include/mavlink_types.h (uint8_t) + nav_mode : Navigation mode, see MAV_NAV_MODE ENUM (uint8_t) + status : System status flag, see MAV_STATUS ENUM (uint8_t) + load : Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 (uint16_t) + vbat : Battery voltage, in millivolts (1 = 1 millivolt) (uint16_t) + battery_remaining : Remaining battery energy: (0%: 0, 100%: 1000) (uint16_t) + packet_drop : Dropped packets (packets that were corrupted on reception on the MAV) (uint16_t) + + ''' + msg = MAVLink_sys_status_message(mode, nav_mode, status, load, vbat, battery_remaining, packet_drop) + msg.pack(self) + return msg + + def sys_status_send(self, mode, nav_mode, status, load, vbat, battery_remaining, packet_drop): + ''' + The general system state. If the system is following the MAVLink + standard, the system state is mainly defined by three + orthogonal states/modes: The system mode, which is + either LOCKED (motors shut down and locked), MANUAL + (system under RC control), GUIDED (system with + autonomous position control, position setpoint + controlled manually) or AUTO (system guided by + path/waypoint planner). The NAV_MODE defined the + current flight state: LIFTOFF (often an open-loop + maneuver), LANDING, WAYPOINTS or VECTOR. This + represents the internal navigation state machine. The + system status shows wether the system is currently + active or not and if an emergency occured. During the + CRITICAL and EMERGENCY states the MAV is still + considered to be active, but should start emergency + procedures autonomously. After a failure occured it + should first move from active to critical to allow + manual intervention and then move to emergency after a + certain timeout. + + mode : System mode, see MAV_MODE ENUM in mavlink/include/mavlink_types.h (uint8_t) + nav_mode : Navigation mode, see MAV_NAV_MODE ENUM (uint8_t) + status : System status flag, see MAV_STATUS ENUM (uint8_t) + load : Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 (uint16_t) + vbat : Battery voltage, in millivolts (1 = 1 millivolt) (uint16_t) + battery_remaining : Remaining battery energy: (0%: 0, 100%: 1000) (uint16_t) + packet_drop : Dropped packets (packets that were corrupted on reception on the MAV) (uint16_t) + + ''' + return self.send(self.sys_status_encode(mode, nav_mode, status, load, vbat, battery_remaining, packet_drop)) + + def rc_channels_raw_encode(self, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw, rssi): + ''' + The RAW values of the RC channels received. The standard PPM + modulation is as follows: 1000 microseconds: 0%, 2000 + microseconds: 100%. Individual receivers/transmitters + might violate this specification. + + chan1_raw : RC channel 1 value, in microseconds (uint16_t) + chan2_raw : RC channel 2 value, in microseconds (uint16_t) + chan3_raw : RC channel 3 value, in microseconds (uint16_t) + chan4_raw : RC channel 4 value, in microseconds (uint16_t) + chan5_raw : RC channel 5 value, in microseconds (uint16_t) + chan6_raw : RC channel 6 value, in microseconds (uint16_t) + chan7_raw : RC channel 7 value, in microseconds (uint16_t) + chan8_raw : RC channel 8 value, in microseconds (uint16_t) + rssi : Receive signal strength indicator, 0: 0%, 255: 100% (uint8_t) + + ''' + msg = MAVLink_rc_channels_raw_message(chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw, rssi) + msg.pack(self) + return msg + + def rc_channels_raw_send(self, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw, rssi): + ''' + The RAW values of the RC channels received. The standard PPM + modulation is as follows: 1000 microseconds: 0%, 2000 + microseconds: 100%. Individual receivers/transmitters + might violate this specification. + + chan1_raw : RC channel 1 value, in microseconds (uint16_t) + chan2_raw : RC channel 2 value, in microseconds (uint16_t) + chan3_raw : RC channel 3 value, in microseconds (uint16_t) + chan4_raw : RC channel 4 value, in microseconds (uint16_t) + chan5_raw : RC channel 5 value, in microseconds (uint16_t) + chan6_raw : RC channel 6 value, in microseconds (uint16_t) + chan7_raw : RC channel 7 value, in microseconds (uint16_t) + chan8_raw : RC channel 8 value, in microseconds (uint16_t) + rssi : Receive signal strength indicator, 0: 0%, 255: 100% (uint8_t) + + ''' + return self.send(self.rc_channels_raw_encode(chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw, rssi)) + + def rc_channels_scaled_encode(self, chan1_scaled, chan2_scaled, chan3_scaled, chan4_scaled, chan5_scaled, chan6_scaled, chan7_scaled, chan8_scaled, rssi): + ''' + The scaled values of the RC channels received. (-100%) -10000, (0%) 0, + (100%) 10000 + + chan1_scaled : RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan2_scaled : RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan3_scaled : RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan4_scaled : RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan5_scaled : RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan6_scaled : RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan7_scaled : RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan8_scaled : RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + rssi : Receive signal strength indicator, 0: 0%, 255: 100% (uint8_t) + + ''' + msg = MAVLink_rc_channels_scaled_message(chan1_scaled, chan2_scaled, chan3_scaled, chan4_scaled, chan5_scaled, chan6_scaled, chan7_scaled, chan8_scaled, rssi) + msg.pack(self) + return msg + + def rc_channels_scaled_send(self, chan1_scaled, chan2_scaled, chan3_scaled, chan4_scaled, chan5_scaled, chan6_scaled, chan7_scaled, chan8_scaled, rssi): + ''' + The scaled values of the RC channels received. (-100%) -10000, (0%) 0, + (100%) 10000 + + chan1_scaled : RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan2_scaled : RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan3_scaled : RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan4_scaled : RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan5_scaled : RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan6_scaled : RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan7_scaled : RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan8_scaled : RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + rssi : Receive signal strength indicator, 0: 0%, 255: 100% (uint8_t) + + ''' + return self.send(self.rc_channels_scaled_encode(chan1_scaled, chan2_scaled, chan3_scaled, chan4_scaled, chan5_scaled, chan6_scaled, chan7_scaled, chan8_scaled, rssi)) + + def servo_output_raw_encode(self, servo1_raw, servo2_raw, servo3_raw, servo4_raw, servo5_raw, servo6_raw, servo7_raw, servo8_raw): + ''' + The RAW values of the servo outputs (for RC input from the remote, use + the RC_CHANNELS messages). The standard PPM modulation + is as follows: 1000 microseconds: 0%, 2000 + microseconds: 100%. + + servo1_raw : Servo output 1 value, in microseconds (uint16_t) + servo2_raw : Servo output 2 value, in microseconds (uint16_t) + servo3_raw : Servo output 3 value, in microseconds (uint16_t) + servo4_raw : Servo output 4 value, in microseconds (uint16_t) + servo5_raw : Servo output 5 value, in microseconds (uint16_t) + servo6_raw : Servo output 6 value, in microseconds (uint16_t) + servo7_raw : Servo output 7 value, in microseconds (uint16_t) + servo8_raw : Servo output 8 value, in microseconds (uint16_t) + + ''' + msg = MAVLink_servo_output_raw_message(servo1_raw, servo2_raw, servo3_raw, servo4_raw, servo5_raw, servo6_raw, servo7_raw, servo8_raw) + msg.pack(self) + return msg + + def servo_output_raw_send(self, servo1_raw, servo2_raw, servo3_raw, servo4_raw, servo5_raw, servo6_raw, servo7_raw, servo8_raw): + ''' + The RAW values of the servo outputs (for RC input from the remote, use + the RC_CHANNELS messages). The standard PPM modulation + is as follows: 1000 microseconds: 0%, 2000 + microseconds: 100%. + + servo1_raw : Servo output 1 value, in microseconds (uint16_t) + servo2_raw : Servo output 2 value, in microseconds (uint16_t) + servo3_raw : Servo output 3 value, in microseconds (uint16_t) + servo4_raw : Servo output 4 value, in microseconds (uint16_t) + servo5_raw : Servo output 5 value, in microseconds (uint16_t) + servo6_raw : Servo output 6 value, in microseconds (uint16_t) + servo7_raw : Servo output 7 value, in microseconds (uint16_t) + servo8_raw : Servo output 8 value, in microseconds (uint16_t) + + ''' + return self.send(self.servo_output_raw_encode(servo1_raw, servo2_raw, servo3_raw, servo4_raw, servo5_raw, servo6_raw, servo7_raw, servo8_raw)) + + def waypoint_encode(self, target_system, target_component, seq, frame, command, current, autocontinue, param1, param2, param3, param4, x, y, z): + ''' + Message encoding a waypoint. This message is emitted to announce + the presence of a waypoint and to set a waypoint on + the system. The waypoint can be either in x, y, z + meters (type: LOCAL) or x:lat, y:lon, z:altitude. + Local frame is Z-down, right handed, global frame is + Z-up, right handed + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + seq : Sequence (uint16_t) + frame : The coordinate system of the waypoint. see MAV_FRAME in mavlink_types.h (uint8_t) + command : The scheduled action for the waypoint. see MAV_COMMAND in common.xml MAVLink specs (uint8_t) + current : false:0, true:1 (uint8_t) + autocontinue : autocontinue to next wp (uint8_t) + param1 : PARAM1 / For NAV command waypoints: Radius in which the waypoint is accepted as reached, in meters (float) + param2 : PARAM2 / For NAV command waypoints: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds (float) + param3 : PARAM3 / For LOITER command waypoints: Orbit to circle around the waypoint, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. (float) + param4 : PARAM4 / For NAV and LOITER command waypoints: Yaw orientation in degrees, [0..360] 0 = NORTH (float) + x : PARAM5 / local: x position, global: latitude (float) + y : PARAM6 / y position: global: longitude (float) + z : PARAM7 / z position: global: altitude (float) + + ''' + msg = MAVLink_waypoint_message(target_system, target_component, seq, frame, command, current, autocontinue, param1, param2, param3, param4, x, y, z) + msg.pack(self) + return msg + + def waypoint_send(self, target_system, target_component, seq, frame, command, current, autocontinue, param1, param2, param3, param4, x, y, z): + ''' + Message encoding a waypoint. This message is emitted to announce + the presence of a waypoint and to set a waypoint on + the system. The waypoint can be either in x, y, z + meters (type: LOCAL) or x:lat, y:lon, z:altitude. + Local frame is Z-down, right handed, global frame is + Z-up, right handed + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + seq : Sequence (uint16_t) + frame : The coordinate system of the waypoint. see MAV_FRAME in mavlink_types.h (uint8_t) + command : The scheduled action for the waypoint. see MAV_COMMAND in common.xml MAVLink specs (uint8_t) + current : false:0, true:1 (uint8_t) + autocontinue : autocontinue to next wp (uint8_t) + param1 : PARAM1 / For NAV command waypoints: Radius in which the waypoint is accepted as reached, in meters (float) + param2 : PARAM2 / For NAV command waypoints: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds (float) + param3 : PARAM3 / For LOITER command waypoints: Orbit to circle around the waypoint, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. (float) + param4 : PARAM4 / For NAV and LOITER command waypoints: Yaw orientation in degrees, [0..360] 0 = NORTH (float) + x : PARAM5 / local: x position, global: latitude (float) + y : PARAM6 / y position: global: longitude (float) + z : PARAM7 / z position: global: altitude (float) + + ''' + return self.send(self.waypoint_encode(target_system, target_component, seq, frame, command, current, autocontinue, param1, param2, param3, param4, x, y, z)) + + def waypoint_request_encode(self, target_system, target_component, seq): + ''' + Request the information of the waypoint with the sequence number seq. + The response of the system to this message should be a + WAYPOINT message. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + seq : Sequence (uint16_t) + + ''' + msg = MAVLink_waypoint_request_message(target_system, target_component, seq) + msg.pack(self) + return msg + + def waypoint_request_send(self, target_system, target_component, seq): + ''' + Request the information of the waypoint with the sequence number seq. + The response of the system to this message should be a + WAYPOINT message. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + seq : Sequence (uint16_t) + + ''' + return self.send(self.waypoint_request_encode(target_system, target_component, seq)) + + def waypoint_set_current_encode(self, target_system, target_component, seq): + ''' + Set the waypoint with sequence number seq as current waypoint. This + means that the MAV will continue to this waypoint on + the shortest path (not following the waypoints in- + between). + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + seq : Sequence (uint16_t) + + ''' + msg = MAVLink_waypoint_set_current_message(target_system, target_component, seq) + msg.pack(self) + return msg + + def waypoint_set_current_send(self, target_system, target_component, seq): + ''' + Set the waypoint with sequence number seq as current waypoint. This + means that the MAV will continue to this waypoint on + the shortest path (not following the waypoints in- + between). + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + seq : Sequence (uint16_t) + + ''' + return self.send(self.waypoint_set_current_encode(target_system, target_component, seq)) + + def waypoint_current_encode(self, seq): + ''' + Message that announces the sequence number of the current active + waypoint. The MAV will fly towards this waypoint. + + seq : Sequence (uint16_t) + + ''' + msg = MAVLink_waypoint_current_message(seq) + msg.pack(self) + return msg + + def waypoint_current_send(self, seq): + ''' + Message that announces the sequence number of the current active + waypoint. The MAV will fly towards this waypoint. + + seq : Sequence (uint16_t) + + ''' + return self.send(self.waypoint_current_encode(seq)) + + def waypoint_request_list_encode(self, target_system, target_component): + ''' + Request the overall list of waypoints from the system/component. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + + ''' + msg = MAVLink_waypoint_request_list_message(target_system, target_component) + msg.pack(self) + return msg + + def waypoint_request_list_send(self, target_system, target_component): + ''' + Request the overall list of waypoints from the system/component. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + + ''' + return self.send(self.waypoint_request_list_encode(target_system, target_component)) + + def waypoint_count_encode(self, target_system, target_component, count): + ''' + This message is emitted as response to WAYPOINT_REQUEST_LIST by the + MAV. The GCS can then request the individual waypoints + based on the knowledge of the total number of + waypoints. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + count : Number of Waypoints in the Sequence (uint16_t) + + ''' + msg = MAVLink_waypoint_count_message(target_system, target_component, count) + msg.pack(self) + return msg + + def waypoint_count_send(self, target_system, target_component, count): + ''' + This message is emitted as response to WAYPOINT_REQUEST_LIST by the + MAV. The GCS can then request the individual waypoints + based on the knowledge of the total number of + waypoints. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + count : Number of Waypoints in the Sequence (uint16_t) + + ''' + return self.send(self.waypoint_count_encode(target_system, target_component, count)) + + def waypoint_clear_all_encode(self, target_system, target_component): + ''' + Delete all waypoints at once. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + + ''' + msg = MAVLink_waypoint_clear_all_message(target_system, target_component) + msg.pack(self) + return msg + + def waypoint_clear_all_send(self, target_system, target_component): + ''' + Delete all waypoints at once. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + + ''' + return self.send(self.waypoint_clear_all_encode(target_system, target_component)) + + def waypoint_reached_encode(self, seq): + ''' + A certain waypoint has been reached. The system will either hold this + position (or circle on the orbit) or (if the + autocontinue on the WP was set) continue to the next + waypoint. + + seq : Sequence (uint16_t) + + ''' + msg = MAVLink_waypoint_reached_message(seq) + msg.pack(self) + return msg + + def waypoint_reached_send(self, seq): + ''' + A certain waypoint has been reached. The system will either hold this + position (or circle on the orbit) or (if the + autocontinue on the WP was set) continue to the next + waypoint. + + seq : Sequence (uint16_t) + + ''' + return self.send(self.waypoint_reached_encode(seq)) + + def waypoint_ack_encode(self, target_system, target_component, type): + ''' + Ack message during waypoint handling. The type field states if this + message is a positive ack (type=0) or if an error + happened (type=non-zero). + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + type : 0: OK, 1: Error (uint8_t) + + ''' + msg = MAVLink_waypoint_ack_message(target_system, target_component, type) + msg.pack(self) + return msg + + def waypoint_ack_send(self, target_system, target_component, type): + ''' + Ack message during waypoint handling. The type field states if this + message is a positive ack (type=0) or if an error + happened (type=non-zero). + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + type : 0: OK, 1: Error (uint8_t) + + ''' + return self.send(self.waypoint_ack_encode(target_system, target_component, type)) + + def gps_set_global_origin_encode(self, target_system, target_component, latitude, longitude, altitude): + ''' + As local waypoints exist, the global waypoint reference allows to + transform between the local coordinate frame and the + global (GPS) coordinate frame. This can be necessary + when e.g. in- and outdoor settings are connected and + the MAV should move from in- to outdoor. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + latitude : global position * 1E7 (int32_t) + longitude : global position * 1E7 (int32_t) + altitude : global position * 1000 (int32_t) + + ''' + msg = MAVLink_gps_set_global_origin_message(target_system, target_component, latitude, longitude, altitude) + msg.pack(self) + return msg + + def gps_set_global_origin_send(self, target_system, target_component, latitude, longitude, altitude): + ''' + As local waypoints exist, the global waypoint reference allows to + transform between the local coordinate frame and the + global (GPS) coordinate frame. This can be necessary + when e.g. in- and outdoor settings are connected and + the MAV should move from in- to outdoor. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + latitude : global position * 1E7 (int32_t) + longitude : global position * 1E7 (int32_t) + altitude : global position * 1000 (int32_t) + + ''' + return self.send(self.gps_set_global_origin_encode(target_system, target_component, latitude, longitude, altitude)) + + def gps_local_origin_set_encode(self, latitude, longitude, altitude): + ''' + Once the MAV sets a new GPS-Local correspondence, this message + announces the origin (0,0,0) position + + latitude : Latitude (WGS84), expressed as * 1E7 (int32_t) + longitude : Longitude (WGS84), expressed as * 1E7 (int32_t) + altitude : Altitude(WGS84), expressed as * 1000 (int32_t) + + ''' + msg = MAVLink_gps_local_origin_set_message(latitude, longitude, altitude) + msg.pack(self) + return msg + + def gps_local_origin_set_send(self, latitude, longitude, altitude): + ''' + Once the MAV sets a new GPS-Local correspondence, this message + announces the origin (0,0,0) position + + latitude : Latitude (WGS84), expressed as * 1E7 (int32_t) + longitude : Longitude (WGS84), expressed as * 1E7 (int32_t) + altitude : Altitude(WGS84), expressed as * 1000 (int32_t) + + ''' + return self.send(self.gps_local_origin_set_encode(latitude, longitude, altitude)) + + def local_position_setpoint_set_encode(self, target_system, target_component, x, y, z, yaw): + ''' + Set the setpoint for a local position controller. This is the position + in local coordinates the MAV should fly to. This + message is sent by the path/waypoint planner to the + onboard position controller. As some MAVs have a + degree of freedom in yaw (e.g. all + helicopters/quadrotors), the desired yaw angle is part + of the message. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + x : x position (float) + y : y position (float) + z : z position (float) + yaw : Desired yaw angle (float) + + ''' + msg = MAVLink_local_position_setpoint_set_message(target_system, target_component, x, y, z, yaw) + msg.pack(self) + return msg + + def local_position_setpoint_set_send(self, target_system, target_component, x, y, z, yaw): + ''' + Set the setpoint for a local position controller. This is the position + in local coordinates the MAV should fly to. This + message is sent by the path/waypoint planner to the + onboard position controller. As some MAVs have a + degree of freedom in yaw (e.g. all + helicopters/quadrotors), the desired yaw angle is part + of the message. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + x : x position (float) + y : y position (float) + z : z position (float) + yaw : Desired yaw angle (float) + + ''' + return self.send(self.local_position_setpoint_set_encode(target_system, target_component, x, y, z, yaw)) + + def local_position_setpoint_encode(self, x, y, z, yaw): + ''' + Transmit the current local setpoint of the controller to other MAVs + (collision avoidance) and to the GCS. + + x : x position (float) + y : y position (float) + z : z position (float) + yaw : Desired yaw angle (float) + + ''' + msg = MAVLink_local_position_setpoint_message(x, y, z, yaw) + msg.pack(self) + return msg + + def local_position_setpoint_send(self, x, y, z, yaw): + ''' + Transmit the current local setpoint of the controller to other MAVs + (collision avoidance) and to the GCS. + + x : x position (float) + y : y position (float) + z : z position (float) + yaw : Desired yaw angle (float) + + ''' + return self.send(self.local_position_setpoint_encode(x, y, z, yaw)) + + def control_status_encode(self, position_fix, vision_fix, gps_fix, ahrs_health, control_att, control_pos_xy, control_pos_z, control_pos_yaw): + ''' + + + position_fix : Position fix: 0: lost, 2: 2D position fix, 3: 3D position fix (uint8_t) + vision_fix : Vision position fix: 0: lost, 1: 2D local position hold, 2: 2D global position fix, 3: 3D global position fix (uint8_t) + gps_fix : GPS position fix: 0: no reception, 1: Minimum 1 satellite, but no position fix, 2: 2D position fix, 3: 3D position fix (uint8_t) + ahrs_health : Attitude estimation health: 0: poor, 255: excellent (uint8_t) + control_att : 0: Attitude control disabled, 1: enabled (uint8_t) + control_pos_xy : 0: X, Y position control disabled, 1: enabled (uint8_t) + control_pos_z : 0: Z position control disabled, 1: enabled (uint8_t) + control_pos_yaw : 0: Yaw angle control disabled, 1: enabled (uint8_t) + + ''' + msg = MAVLink_control_status_message(position_fix, vision_fix, gps_fix, ahrs_health, control_att, control_pos_xy, control_pos_z, control_pos_yaw) + msg.pack(self) + return msg + + def control_status_send(self, position_fix, vision_fix, gps_fix, ahrs_health, control_att, control_pos_xy, control_pos_z, control_pos_yaw): + ''' + + + position_fix : Position fix: 0: lost, 2: 2D position fix, 3: 3D position fix (uint8_t) + vision_fix : Vision position fix: 0: lost, 1: 2D local position hold, 2: 2D global position fix, 3: 3D global position fix (uint8_t) + gps_fix : GPS position fix: 0: no reception, 1: Minimum 1 satellite, but no position fix, 2: 2D position fix, 3: 3D position fix (uint8_t) + ahrs_health : Attitude estimation health: 0: poor, 255: excellent (uint8_t) + control_att : 0: Attitude control disabled, 1: enabled (uint8_t) + control_pos_xy : 0: X, Y position control disabled, 1: enabled (uint8_t) + control_pos_z : 0: Z position control disabled, 1: enabled (uint8_t) + control_pos_yaw : 0: Yaw angle control disabled, 1: enabled (uint8_t) + + ''' + return self.send(self.control_status_encode(position_fix, vision_fix, gps_fix, ahrs_health, control_att, control_pos_xy, control_pos_z, control_pos_yaw)) + + def safety_set_allowed_area_encode(self, target_system, target_component, frame, p1x, p1y, p1z, p2x, p2y, p2z): + ''' + Set a safety zone (volume), which is defined by two corners of a cube. + This message can be used to tell the MAV which + setpoints/waypoints to accept and which to reject. + Safety areas are often enforced by national or + competition regulations. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + frame : Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. (uint8_t) + p1x : x position 1 / Latitude 1 (float) + p1y : y position 1 / Longitude 1 (float) + p1z : z position 1 / Altitude 1 (float) + p2x : x position 2 / Latitude 2 (float) + p2y : y position 2 / Longitude 2 (float) + p2z : z position 2 / Altitude 2 (float) + + ''' + msg = MAVLink_safety_set_allowed_area_message(target_system, target_component, frame, p1x, p1y, p1z, p2x, p2y, p2z) + msg.pack(self) + return msg + + def safety_set_allowed_area_send(self, target_system, target_component, frame, p1x, p1y, p1z, p2x, p2y, p2z): + ''' + Set a safety zone (volume), which is defined by two corners of a cube. + This message can be used to tell the MAV which + setpoints/waypoints to accept and which to reject. + Safety areas are often enforced by national or + competition regulations. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + frame : Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. (uint8_t) + p1x : x position 1 / Latitude 1 (float) + p1y : y position 1 / Longitude 1 (float) + p1z : z position 1 / Altitude 1 (float) + p2x : x position 2 / Latitude 2 (float) + p2y : y position 2 / Longitude 2 (float) + p2z : z position 2 / Altitude 2 (float) + + ''' + return self.send(self.safety_set_allowed_area_encode(target_system, target_component, frame, p1x, p1y, p1z, p2x, p2y, p2z)) + + def safety_allowed_area_encode(self, frame, p1x, p1y, p1z, p2x, p2y, p2z): + ''' + Read out the safety zone the MAV currently assumes. + + frame : Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. (uint8_t) + p1x : x position 1 / Latitude 1 (float) + p1y : y position 1 / Longitude 1 (float) + p1z : z position 1 / Altitude 1 (float) + p2x : x position 2 / Latitude 2 (float) + p2y : y position 2 / Longitude 2 (float) + p2z : z position 2 / Altitude 2 (float) + + ''' + msg = MAVLink_safety_allowed_area_message(frame, p1x, p1y, p1z, p2x, p2y, p2z) + msg.pack(self) + return msg + + def safety_allowed_area_send(self, frame, p1x, p1y, p1z, p2x, p2y, p2z): + ''' + Read out the safety zone the MAV currently assumes. + + frame : Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. (uint8_t) + p1x : x position 1 / Latitude 1 (float) + p1y : y position 1 / Longitude 1 (float) + p1z : z position 1 / Altitude 1 (float) + p2x : x position 2 / Latitude 2 (float) + p2y : y position 2 / Longitude 2 (float) + p2z : z position 2 / Altitude 2 (float) + + ''' + return self.send(self.safety_allowed_area_encode(frame, p1x, p1y, p1z, p2x, p2y, p2z)) + + def set_roll_pitch_yaw_thrust_encode(self, target_system, target_component, roll, pitch, yaw, thrust): + ''' + Set roll, pitch and yaw. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + roll : Desired roll angle in radians (float) + pitch : Desired pitch angle in radians (float) + yaw : Desired yaw angle in radians (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + msg = MAVLink_set_roll_pitch_yaw_thrust_message(target_system, target_component, roll, pitch, yaw, thrust) + msg.pack(self) + return msg + + def set_roll_pitch_yaw_thrust_send(self, target_system, target_component, roll, pitch, yaw, thrust): + ''' + Set roll, pitch and yaw. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + roll : Desired roll angle in radians (float) + pitch : Desired pitch angle in radians (float) + yaw : Desired yaw angle in radians (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + return self.send(self.set_roll_pitch_yaw_thrust_encode(target_system, target_component, roll, pitch, yaw, thrust)) + + def set_roll_pitch_yaw_speed_thrust_encode(self, target_system, target_component, roll_speed, pitch_speed, yaw_speed, thrust): + ''' + Set roll, pitch and yaw. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + roll_speed : Desired roll angular speed in rad/s (float) + pitch_speed : Desired pitch angular speed in rad/s (float) + yaw_speed : Desired yaw angular speed in rad/s (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + msg = MAVLink_set_roll_pitch_yaw_speed_thrust_message(target_system, target_component, roll_speed, pitch_speed, yaw_speed, thrust) + msg.pack(self) + return msg + + def set_roll_pitch_yaw_speed_thrust_send(self, target_system, target_component, roll_speed, pitch_speed, yaw_speed, thrust): + ''' + Set roll, pitch and yaw. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + roll_speed : Desired roll angular speed in rad/s (float) + pitch_speed : Desired pitch angular speed in rad/s (float) + yaw_speed : Desired yaw angular speed in rad/s (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + return self.send(self.set_roll_pitch_yaw_speed_thrust_encode(target_system, target_component, roll_speed, pitch_speed, yaw_speed, thrust)) + + def roll_pitch_yaw_thrust_setpoint_encode(self, time_us, roll, pitch, yaw, thrust): + ''' + Setpoint in roll, pitch, yaw currently active on the system. + + time_us : Timestamp in micro seconds since unix epoch (uint64_t) + roll : Desired roll angle in radians (float) + pitch : Desired pitch angle in radians (float) + yaw : Desired yaw angle in radians (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + msg = MAVLink_roll_pitch_yaw_thrust_setpoint_message(time_us, roll, pitch, yaw, thrust) + msg.pack(self) + return msg + + def roll_pitch_yaw_thrust_setpoint_send(self, time_us, roll, pitch, yaw, thrust): + ''' + Setpoint in roll, pitch, yaw currently active on the system. + + time_us : Timestamp in micro seconds since unix epoch (uint64_t) + roll : Desired roll angle in radians (float) + pitch : Desired pitch angle in radians (float) + yaw : Desired yaw angle in radians (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + return self.send(self.roll_pitch_yaw_thrust_setpoint_encode(time_us, roll, pitch, yaw, thrust)) + + def roll_pitch_yaw_speed_thrust_setpoint_encode(self, time_us, roll_speed, pitch_speed, yaw_speed, thrust): + ''' + Setpoint in rollspeed, pitchspeed, yawspeed currently active on the + system. + + time_us : Timestamp in micro seconds since unix epoch (uint64_t) + roll_speed : Desired roll angular speed in rad/s (float) + pitch_speed : Desired pitch angular speed in rad/s (float) + yaw_speed : Desired yaw angular speed in rad/s (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + msg = MAVLink_roll_pitch_yaw_speed_thrust_setpoint_message(time_us, roll_speed, pitch_speed, yaw_speed, thrust) + msg.pack(self) + return msg + + def roll_pitch_yaw_speed_thrust_setpoint_send(self, time_us, roll_speed, pitch_speed, yaw_speed, thrust): + ''' + Setpoint in rollspeed, pitchspeed, yawspeed currently active on the + system. + + time_us : Timestamp in micro seconds since unix epoch (uint64_t) + roll_speed : Desired roll angular speed in rad/s (float) + pitch_speed : Desired pitch angular speed in rad/s (float) + yaw_speed : Desired yaw angular speed in rad/s (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + return self.send(self.roll_pitch_yaw_speed_thrust_setpoint_encode(time_us, roll_speed, pitch_speed, yaw_speed, thrust)) + + def nav_controller_output_encode(self, nav_roll, nav_pitch, nav_bearing, target_bearing, wp_dist, alt_error, aspd_error, xtrack_error): + ''' + Outputs of the APM navigation controller. The primary use of this + message is to check the response and signs of the + controller before actual flight and to assist with + tuning controller parameters + + nav_roll : Current desired roll in degrees (float) + nav_pitch : Current desired pitch in degrees (float) + nav_bearing : Current desired heading in degrees (int16_t) + target_bearing : Bearing to current waypoint/target in degrees (int16_t) + wp_dist : Distance to active waypoint in meters (uint16_t) + alt_error : Current altitude error in meters (float) + aspd_error : Current airspeed error in meters/second (float) + xtrack_error : Current crosstrack error on x-y plane in meters (float) + + ''' + msg = MAVLink_nav_controller_output_message(nav_roll, nav_pitch, nav_bearing, target_bearing, wp_dist, alt_error, aspd_error, xtrack_error) + msg.pack(self) + return msg + + def nav_controller_output_send(self, nav_roll, nav_pitch, nav_bearing, target_bearing, wp_dist, alt_error, aspd_error, xtrack_error): + ''' + Outputs of the APM navigation controller. The primary use of this + message is to check the response and signs of the + controller before actual flight and to assist with + tuning controller parameters + + nav_roll : Current desired roll in degrees (float) + nav_pitch : Current desired pitch in degrees (float) + nav_bearing : Current desired heading in degrees (int16_t) + target_bearing : Bearing to current waypoint/target in degrees (int16_t) + wp_dist : Distance to active waypoint in meters (uint16_t) + alt_error : Current altitude error in meters (float) + aspd_error : Current airspeed error in meters/second (float) + xtrack_error : Current crosstrack error on x-y plane in meters (float) + + ''' + return self.send(self.nav_controller_output_encode(nav_roll, nav_pitch, nav_bearing, target_bearing, wp_dist, alt_error, aspd_error, xtrack_error)) + + def position_target_encode(self, x, y, z, yaw): + ''' + The goal position of the system. This position is the input to any + navigation or path planning algorithm and does NOT + represent the current controller setpoint. + + x : x position (float) + y : y position (float) + z : z position (float) + yaw : yaw orientation in radians, 0 = NORTH (float) + + ''' + msg = MAVLink_position_target_message(x, y, z, yaw) + msg.pack(self) + return msg + + def position_target_send(self, x, y, z, yaw): + ''' + The goal position of the system. This position is the input to any + navigation or path planning algorithm and does NOT + represent the current controller setpoint. + + x : x position (float) + y : y position (float) + z : z position (float) + yaw : yaw orientation in radians, 0 = NORTH (float) + + ''' + return self.send(self.position_target_encode(x, y, z, yaw)) + + def state_correction_encode(self, xErr, yErr, zErr, rollErr, pitchErr, yawErr, vxErr, vyErr, vzErr): + ''' + Corrects the systems state by adding an error correction term to the + position and velocity, and by rotating the attitude by + a correction angle. + + xErr : x position error (float) + yErr : y position error (float) + zErr : z position error (float) + rollErr : roll error (radians) (float) + pitchErr : pitch error (radians) (float) + yawErr : yaw error (radians) (float) + vxErr : x velocity (float) + vyErr : y velocity (float) + vzErr : z velocity (float) + + ''' + msg = MAVLink_state_correction_message(xErr, yErr, zErr, rollErr, pitchErr, yawErr, vxErr, vyErr, vzErr) + msg.pack(self) + return msg + + def state_correction_send(self, xErr, yErr, zErr, rollErr, pitchErr, yawErr, vxErr, vyErr, vzErr): + ''' + Corrects the systems state by adding an error correction term to the + position and velocity, and by rotating the attitude by + a correction angle. + + xErr : x position error (float) + yErr : y position error (float) + zErr : z position error (float) + rollErr : roll error (radians) (float) + pitchErr : pitch error (radians) (float) + yawErr : yaw error (radians) (float) + vxErr : x velocity (float) + vyErr : y velocity (float) + vzErr : z velocity (float) + + ''' + return self.send(self.state_correction_encode(xErr, yErr, zErr, rollErr, pitchErr, yawErr, vxErr, vyErr, vzErr)) + + def set_altitude_encode(self, target, mode): + ''' + + + target : The system setting the altitude (uint8_t) + mode : The new altitude in meters (uint32_t) + + ''' + msg = MAVLink_set_altitude_message(target, mode) + msg.pack(self) + return msg + + def set_altitude_send(self, target, mode): + ''' + + + target : The system setting the altitude (uint8_t) + mode : The new altitude in meters (uint32_t) + + ''' + return self.send(self.set_altitude_encode(target, mode)) + + def request_data_stream_encode(self, target_system, target_component, req_stream_id, req_message_rate, start_stop): + ''' + + + target_system : The target requested to send the message stream. (uint8_t) + target_component : The target requested to send the message stream. (uint8_t) + req_stream_id : The ID of the requested message type (uint8_t) + req_message_rate : Update rate in Hertz (uint16_t) + start_stop : 1 to start sending, 0 to stop sending. (uint8_t) + + ''' + msg = MAVLink_request_data_stream_message(target_system, target_component, req_stream_id, req_message_rate, start_stop) + msg.pack(self) + return msg + + def request_data_stream_send(self, target_system, target_component, req_stream_id, req_message_rate, start_stop): + ''' + + + target_system : The target requested to send the message stream. (uint8_t) + target_component : The target requested to send the message stream. (uint8_t) + req_stream_id : The ID of the requested message type (uint8_t) + req_message_rate : Update rate in Hertz (uint16_t) + start_stop : 1 to start sending, 0 to stop sending. (uint8_t) + + ''' + return self.send(self.request_data_stream_encode(target_system, target_component, req_stream_id, req_message_rate, start_stop)) + + def hil_state_encode(self, usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed, lat, lon, alt, vx, vy, vz, xacc, yacc, zacc): + ''' + This packet is useful for high throughput applications + such as hardware in the loop simulations. + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + roll : Roll angle (rad) (float) + pitch : Pitch angle (rad) (float) + yaw : Yaw angle (rad) (float) + rollspeed : Roll angular speed (rad/s) (float) + pitchspeed : Pitch angular speed (rad/s) (float) + yawspeed : Yaw angular speed (rad/s) (float) + lat : Latitude, expressed as * 1E7 (int32_t) + lon : Longitude, expressed as * 1E7 (int32_t) + alt : Altitude in meters, expressed as * 1000 (millimeters) (int32_t) + vx : Ground X Speed (Latitude), expressed as m/s * 100 (int16_t) + vy : Ground Y Speed (Longitude), expressed as m/s * 100 (int16_t) + vz : Ground Z Speed (Altitude), expressed as m/s * 100 (int16_t) + xacc : X acceleration (mg) (int16_t) + yacc : Y acceleration (mg) (int16_t) + zacc : Z acceleration (mg) (int16_t) + + ''' + msg = MAVLink_hil_state_message(usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed, lat, lon, alt, vx, vy, vz, xacc, yacc, zacc) + msg.pack(self) + return msg + + def hil_state_send(self, usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed, lat, lon, alt, vx, vy, vz, xacc, yacc, zacc): + ''' + This packet is useful for high throughput applications + such as hardware in the loop simulations. + + usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + roll : Roll angle (rad) (float) + pitch : Pitch angle (rad) (float) + yaw : Yaw angle (rad) (float) + rollspeed : Roll angular speed (rad/s) (float) + pitchspeed : Pitch angular speed (rad/s) (float) + yawspeed : Yaw angular speed (rad/s) (float) + lat : Latitude, expressed as * 1E7 (int32_t) + lon : Longitude, expressed as * 1E7 (int32_t) + alt : Altitude in meters, expressed as * 1000 (millimeters) (int32_t) + vx : Ground X Speed (Latitude), expressed as m/s * 100 (int16_t) + vy : Ground Y Speed (Longitude), expressed as m/s * 100 (int16_t) + vz : Ground Z Speed (Altitude), expressed as m/s * 100 (int16_t) + xacc : X acceleration (mg) (int16_t) + yacc : Y acceleration (mg) (int16_t) + zacc : Z acceleration (mg) (int16_t) + + ''' + return self.send(self.hil_state_encode(usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed, lat, lon, alt, vx, vy, vz, xacc, yacc, zacc)) + + def hil_controls_encode(self, time_us, roll_ailerons, pitch_elevator, yaw_rudder, throttle, mode, nav_mode): + ''' + Hardware in the loop control outputs + + time_us : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + roll_ailerons : Control output -3 .. 1 (float) + pitch_elevator : Control output -1 .. 1 (float) + yaw_rudder : Control output -1 .. 1 (float) + throttle : Throttle 0 .. 1 (float) + mode : System mode (MAV_MODE) (uint8_t) + nav_mode : Navigation mode (MAV_NAV_MODE) (uint8_t) + + ''' + msg = MAVLink_hil_controls_message(time_us, roll_ailerons, pitch_elevator, yaw_rudder, throttle, mode, nav_mode) + msg.pack(self) + return msg + + def hil_controls_send(self, time_us, roll_ailerons, pitch_elevator, yaw_rudder, throttle, mode, nav_mode): + ''' + Hardware in the loop control outputs + + time_us : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + roll_ailerons : Control output -3 .. 1 (float) + pitch_elevator : Control output -1 .. 1 (float) + yaw_rudder : Control output -1 .. 1 (float) + throttle : Throttle 0 .. 1 (float) + mode : System mode (MAV_MODE) (uint8_t) + nav_mode : Navigation mode (MAV_NAV_MODE) (uint8_t) + + ''' + return self.send(self.hil_controls_encode(time_us, roll_ailerons, pitch_elevator, yaw_rudder, throttle, mode, nav_mode)) + + def manual_control_encode(self, target, roll, pitch, yaw, thrust, roll_manual, pitch_manual, yaw_manual, thrust_manual): + ''' + + + target : The system to be controlled (uint8_t) + roll : roll (float) + pitch : pitch (float) + yaw : yaw (float) + thrust : thrust (float) + roll_manual : roll control enabled auto:0, manual:1 (uint8_t) + pitch_manual : pitch auto:0, manual:1 (uint8_t) + yaw_manual : yaw auto:0, manual:1 (uint8_t) + thrust_manual : thrust auto:0, manual:1 (uint8_t) + + ''' + msg = MAVLink_manual_control_message(target, roll, pitch, yaw, thrust, roll_manual, pitch_manual, yaw_manual, thrust_manual) + msg.pack(self) + return msg + + def manual_control_send(self, target, roll, pitch, yaw, thrust, roll_manual, pitch_manual, yaw_manual, thrust_manual): + ''' + + + target : The system to be controlled (uint8_t) + roll : roll (float) + pitch : pitch (float) + yaw : yaw (float) + thrust : thrust (float) + roll_manual : roll control enabled auto:0, manual:1 (uint8_t) + pitch_manual : pitch auto:0, manual:1 (uint8_t) + yaw_manual : yaw auto:0, manual:1 (uint8_t) + thrust_manual : thrust auto:0, manual:1 (uint8_t) + + ''' + return self.send(self.manual_control_encode(target, roll, pitch, yaw, thrust, roll_manual, pitch_manual, yaw_manual, thrust_manual)) + + def rc_channels_override_encode(self, target_system, target_component, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw): + ''' + The RAW values of the RC channels sent to the MAV to override info + received from the RC radio. A value of -1 means no + change to that channel. A value of 0 means control of + that channel should be released back to the RC radio. + The standard PPM modulation is as follows: 1000 + microseconds: 0%, 2000 microseconds: 100%. Individual + receivers/transmitters might violate this + specification. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + chan1_raw : RC channel 1 value, in microseconds (uint16_t) + chan2_raw : RC channel 2 value, in microseconds (uint16_t) + chan3_raw : RC channel 3 value, in microseconds (uint16_t) + chan4_raw : RC channel 4 value, in microseconds (uint16_t) + chan5_raw : RC channel 5 value, in microseconds (uint16_t) + chan6_raw : RC channel 6 value, in microseconds (uint16_t) + chan7_raw : RC channel 7 value, in microseconds (uint16_t) + chan8_raw : RC channel 8 value, in microseconds (uint16_t) + + ''' + msg = MAVLink_rc_channels_override_message(target_system, target_component, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw) + msg.pack(self) + return msg + + def rc_channels_override_send(self, target_system, target_component, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw): + ''' + The RAW values of the RC channels sent to the MAV to override info + received from the RC radio. A value of -1 means no + change to that channel. A value of 0 means control of + that channel should be released back to the RC radio. + The standard PPM modulation is as follows: 1000 + microseconds: 0%, 2000 microseconds: 100%. Individual + receivers/transmitters might violate this + specification. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + chan1_raw : RC channel 1 value, in microseconds (uint16_t) + chan2_raw : RC channel 2 value, in microseconds (uint16_t) + chan3_raw : RC channel 3 value, in microseconds (uint16_t) + chan4_raw : RC channel 4 value, in microseconds (uint16_t) + chan5_raw : RC channel 5 value, in microseconds (uint16_t) + chan6_raw : RC channel 6 value, in microseconds (uint16_t) + chan7_raw : RC channel 7 value, in microseconds (uint16_t) + chan8_raw : RC channel 8 value, in microseconds (uint16_t) + + ''' + return self.send(self.rc_channels_override_encode(target_system, target_component, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw)) + + def global_position_int_encode(self, lat, lon, alt, vx, vy, vz): + ''' + The filtered global position (e.g. fused GPS and accelerometers). The + position is in GPS-frame (right-handed, Z-up) + + lat : Latitude, expressed as * 1E7 (int32_t) + lon : Longitude, expressed as * 1E7 (int32_t) + alt : Altitude in meters, expressed as * 1000 (millimeters) (int32_t) + vx : Ground X Speed (Latitude), expressed as m/s * 100 (int16_t) + vy : Ground Y Speed (Longitude), expressed as m/s * 100 (int16_t) + vz : Ground Z Speed (Altitude), expressed as m/s * 100 (int16_t) + + ''' + msg = MAVLink_global_position_int_message(lat, lon, alt, vx, vy, vz) + msg.pack(self) + return msg + + def global_position_int_send(self, lat, lon, alt, vx, vy, vz): + ''' + The filtered global position (e.g. fused GPS and accelerometers). The + position is in GPS-frame (right-handed, Z-up) + + lat : Latitude, expressed as * 1E7 (int32_t) + lon : Longitude, expressed as * 1E7 (int32_t) + alt : Altitude in meters, expressed as * 1000 (millimeters) (int32_t) + vx : Ground X Speed (Latitude), expressed as m/s * 100 (int16_t) + vy : Ground Y Speed (Longitude), expressed as m/s * 100 (int16_t) + vz : Ground Z Speed (Altitude), expressed as m/s * 100 (int16_t) + + ''' + return self.send(self.global_position_int_encode(lat, lon, alt, vx, vy, vz)) + + def vfr_hud_encode(self, airspeed, groundspeed, heading, throttle, alt, climb): + ''' + Metrics typically displayed on a HUD for fixed wing aircraft + + airspeed : Current airspeed in m/s (float) + groundspeed : Current ground speed in m/s (float) + heading : Current heading in degrees, in compass units (0..360, 0=north) (int16_t) + throttle : Current throttle setting in integer percent, 0 to 100 (uint16_t) + alt : Current altitude (MSL), in meters (float) + climb : Current climb rate in meters/second (float) + + ''' + msg = MAVLink_vfr_hud_message(airspeed, groundspeed, heading, throttle, alt, climb) + msg.pack(self) + return msg + + def vfr_hud_send(self, airspeed, groundspeed, heading, throttle, alt, climb): + ''' + Metrics typically displayed on a HUD for fixed wing aircraft + + airspeed : Current airspeed in m/s (float) + groundspeed : Current ground speed in m/s (float) + heading : Current heading in degrees, in compass units (0..360, 0=north) (int16_t) + throttle : Current throttle setting in integer percent, 0 to 100 (uint16_t) + alt : Current altitude (MSL), in meters (float) + climb : Current climb rate in meters/second (float) + + ''' + return self.send(self.vfr_hud_encode(airspeed, groundspeed, heading, throttle, alt, climb)) + + def command_encode(self, target_system, target_component, command, confirmation, param1, param2, param3, param4): + ''' + Send a command with up to four parameters to the MAV + + target_system : System which should execute the command (uint8_t) + target_component : Component which should execute the command, 0 for all components (uint8_t) + command : Command ID, as defined by MAV_CMD enum. (uint8_t) + confirmation : 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) (uint8_t) + param1 : Parameter 1, as defined by MAV_CMD enum. (float) + param2 : Parameter 2, as defined by MAV_CMD enum. (float) + param3 : Parameter 3, as defined by MAV_CMD enum. (float) + param4 : Parameter 4, as defined by MAV_CMD enum. (float) + + ''' + msg = MAVLink_command_message(target_system, target_component, command, confirmation, param1, param2, param3, param4) + msg.pack(self) + return msg + + def command_send(self, target_system, target_component, command, confirmation, param1, param2, param3, param4): + ''' + Send a command with up to four parameters to the MAV + + target_system : System which should execute the command (uint8_t) + target_component : Component which should execute the command, 0 for all components (uint8_t) + command : Command ID, as defined by MAV_CMD enum. (uint8_t) + confirmation : 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) (uint8_t) + param1 : Parameter 1, as defined by MAV_CMD enum. (float) + param2 : Parameter 2, as defined by MAV_CMD enum. (float) + param3 : Parameter 3, as defined by MAV_CMD enum. (float) + param4 : Parameter 4, as defined by MAV_CMD enum. (float) + + ''' + return self.send(self.command_encode(target_system, target_component, command, confirmation, param1, param2, param3, param4)) + + def command_ack_encode(self, command, result): + ''' + Report status of a command. Includes feedback wether the command was + executed + + command : Current airspeed in m/s (float) + result : 1: Action ACCEPTED and EXECUTED, 1: Action TEMPORARY REJECTED/DENIED, 2: Action PERMANENTLY DENIED, 3: Action UNKNOWN/UNSUPPORTED, 4: Requesting CONFIRMATION (float) + + ''' + msg = MAVLink_command_ack_message(command, result) + msg.pack(self) + return msg + + def command_ack_send(self, command, result): + ''' + Report status of a command. Includes feedback wether the command was + executed + + command : Current airspeed in m/s (float) + result : 1: Action ACCEPTED and EXECUTED, 1: Action TEMPORARY REJECTED/DENIED, 2: Action PERMANENTLY DENIED, 3: Action UNKNOWN/UNSUPPORTED, 4: Requesting CONFIRMATION (float) + + ''' + return self.send(self.command_ack_encode(command, result)) + + def optical_flow_encode(self, time, sensor_id, flow_x, flow_y, quality, ground_distance): + ''' + Optical flow from a flow sensor (e.g. optical mouse sensor) + + time : Timestamp (UNIX) (uint64_t) + sensor_id : Sensor ID (uint8_t) + flow_x : Flow in pixels in x-sensor direction (int16_t) + flow_y : Flow in pixels in y-sensor direction (int16_t) + quality : Optical flow quality / confidence. 0: bad, 255: maximum quality (uint8_t) + ground_distance : Ground distance in meters (float) + + ''' + msg = MAVLink_optical_flow_message(time, sensor_id, flow_x, flow_y, quality, ground_distance) + msg.pack(self) + return msg + + def optical_flow_send(self, time, sensor_id, flow_x, flow_y, quality, ground_distance): + ''' + Optical flow from a flow sensor (e.g. optical mouse sensor) + + time : Timestamp (UNIX) (uint64_t) + sensor_id : Sensor ID (uint8_t) + flow_x : Flow in pixels in x-sensor direction (int16_t) + flow_y : Flow in pixels in y-sensor direction (int16_t) + quality : Optical flow quality / confidence. 0: bad, 255: maximum quality (uint8_t) + ground_distance : Ground distance in meters (float) + + ''' + return self.send(self.optical_flow_encode(time, sensor_id, flow_x, flow_y, quality, ground_distance)) + + def object_detection_event_encode(self, time, object_id, type, name, quality, bearing, distance): + ''' + Object has been detected + + time : Timestamp in milliseconds since system boot (uint32_t) + object_id : Object ID (uint16_t) + type : Object type: 0: image, 1: letter, 2: ground vehicle, 3: air vehicle, 4: surface vehicle, 5: sub-surface vehicle, 6: human, 7: animal (uint8_t) + name : Name of the object as defined by the detector (char) + quality : Detection quality / confidence. 0: bad, 255: maximum confidence (uint8_t) + bearing : Angle of the object with respect to the body frame in NED coordinates in radians. 0: front (float) + distance : Ground distance in meters (float) + + ''' + msg = MAVLink_object_detection_event_message(time, object_id, type, name, quality, bearing, distance) + msg.pack(self) + return msg + + def object_detection_event_send(self, time, object_id, type, name, quality, bearing, distance): + ''' + Object has been detected + + time : Timestamp in milliseconds since system boot (uint32_t) + object_id : Object ID (uint16_t) + type : Object type: 0: image, 1: letter, 2: ground vehicle, 3: air vehicle, 4: surface vehicle, 5: sub-surface vehicle, 6: human, 7: animal (uint8_t) + name : Name of the object as defined by the detector (char) + quality : Detection quality / confidence. 0: bad, 255: maximum confidence (uint8_t) + bearing : Angle of the object with respect to the body frame in NED coordinates in radians. 0: front (float) + distance : Ground distance in meters (float) + + ''' + return self.send(self.object_detection_event_encode(time, object_id, type, name, quality, bearing, distance)) + + def debug_vect_encode(self, name, usec, x, y, z): + ''' + + + name : Name (char) + usec : Timestamp (uint64_t) + x : x (float) + y : y (float) + z : z (float) + + ''' + msg = MAVLink_debug_vect_message(name, usec, x, y, z) + msg.pack(self) + return msg + + def debug_vect_send(self, name, usec, x, y, z): + ''' + + + name : Name (char) + usec : Timestamp (uint64_t) + x : x (float) + y : y (float) + z : z (float) + + ''' + return self.send(self.debug_vect_encode(name, usec, x, y, z)) + + def named_value_float_encode(self, name, value): + ''' + Send a key-value pair as float. The use of this message is discouraged + for normal packets, but a quite efficient way for + testing new messages and getting experimental debug + output. + + name : Name of the debug variable (char) + value : Floating point value (float) + + ''' + msg = MAVLink_named_value_float_message(name, value) + msg.pack(self) + return msg + + def named_value_float_send(self, name, value): + ''' + Send a key-value pair as float. The use of this message is discouraged + for normal packets, but a quite efficient way for + testing new messages and getting experimental debug + output. + + name : Name of the debug variable (char) + value : Floating point value (float) + + ''' + return self.send(self.named_value_float_encode(name, value)) + + def named_value_int_encode(self, name, value): + ''' + Send a key-value pair as integer. The use of this message is + discouraged for normal packets, but a quite efficient + way for testing new messages and getting experimental + debug output. + + name : Name of the debug variable (char) + value : Signed integer value (int32_t) + + ''' + msg = MAVLink_named_value_int_message(name, value) + msg.pack(self) + return msg + + def named_value_int_send(self, name, value): + ''' + Send a key-value pair as integer. The use of this message is + discouraged for normal packets, but a quite efficient + way for testing new messages and getting experimental + debug output. + + name : Name of the debug variable (char) + value : Signed integer value (int32_t) + + ''' + return self.send(self.named_value_int_encode(name, value)) + + def statustext_encode(self, severity, text): + ''' + Status text message. These messages are printed in yellow in the COMM + console of QGroundControl. WARNING: They consume quite + some bandwidth, so use only for important status and + error messages. If implemented wisely, these messages + are buffered on the MCU and sent only at a limited + rate (e.g. 10 Hz). + + severity : Severity of status, 0 = info message, 255 = critical fault (uint8_t) + text : Status text message, without null termination character (int8_t) + + ''' + msg = MAVLink_statustext_message(severity, text) + msg.pack(self) + return msg + + def statustext_send(self, severity, text): + ''' + Status text message. These messages are printed in yellow in the COMM + console of QGroundControl. WARNING: They consume quite + some bandwidth, so use only for important status and + error messages. If implemented wisely, these messages + are buffered on the MCU and sent only at a limited + rate (e.g. 10 Hz). + + severity : Severity of status, 0 = info message, 255 = critical fault (uint8_t) + text : Status text message, without null termination character (int8_t) + + ''' + return self.send(self.statustext_encode(severity, text)) + + def debug_encode(self, ind, value): + ''' + Send a debug value. The index is used to discriminate between values. + These values show up in the plot of QGroundControl as + DEBUG N. + + ind : index of debug variable (uint8_t) + value : DEBUG value (float) + + ''' + msg = MAVLink_debug_message(ind, value) + msg.pack(self) + return msg + + def debug_send(self, ind, value): + ''' + Send a debug value. The index is used to discriminate between values. + These values show up in the plot of QGroundControl as + DEBUG N. + + ind : index of debug variable (uint8_t) + value : DEBUG value (float) + + ''' + return self.send(self.debug_encode(ind, value)) + diff --git a/mavlink/share/pyshared/pymavlink/mavlinkv10.py b/mavlink/share/pyshared/pymavlink/mavlinkv10.py new file mode 100644 index 0000000000..a87e8e9046 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/mavlinkv10.py @@ -0,0 +1,5394 @@ +''' +MAVLink protocol implementation (auto-generated by mavgen.py) + +Generated from: ardupilotmega.xml,common.xml + +Note: this file has been auto-generated. DO NOT EDIT +''' + +import struct, array, mavutil, time + +WIRE_PROTOCOL_VERSION = "1.0" + +class MAVLink_header(object): + '''MAVLink message header''' + def __init__(self, msgId, mlen=0, seq=0, srcSystem=0, srcComponent=0): + self.mlen = mlen + self.seq = seq + self.srcSystem = srcSystem + self.srcComponent = srcComponent + self.msgId = msgId + + def pack(self): + return struct.pack('BBBBBB', 254, self.mlen, self.seq, + self.srcSystem, self.srcComponent, self.msgId) + +class MAVLink_message(object): + '''base MAVLink message class''' + def __init__(self, msgId, name): + self._header = MAVLink_header(msgId) + self._payload = None + self._msgbuf = None + self._crc = None + self._fieldnames = [] + self._type = name + + def get_msgbuf(self): + return self._msgbuf + + def get_header(self): + return self._header + + def get_payload(self): + return self._payload + + def get_crc(self): + return self._crc + + def get_fieldnames(self): + return self._fieldnames + + def get_type(self): + return self._type + + def get_msgId(self): + return self._header.msgId + + def get_srcSystem(self): + return self._header.srcSystem + + def get_srcComponent(self): + return self._header.srcComponent + + def get_seq(self): + return self._header.seq + + def __str__(self): + ret = '%s {' % self._type + for a in self._fieldnames: + v = getattr(self, a) + ret += '%s : %s, ' % (a, v) + ret = ret[0:-2] + '}' + return ret + + def pack(self, mav, crc_extra, payload): + self._payload = payload + self._header = MAVLink_header(self._header.msgId, len(payload), mav.seq, + mav.srcSystem, mav.srcComponent) + self._msgbuf = self._header.pack() + payload + crc = mavutil.x25crc(self._msgbuf[1:]) + if True: # using CRC extra + crc.accumulate(chr(crc_extra)) + self._crc = crc.crc + self._msgbuf += struct.pack(' MAV. Also used to return a point from MAV -> GCS + ''' + def __init__(self, target_system, target_component, idx, count, lat, lng): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_FENCE_POINT, 'FENCE_POINT') + self._fieldnames = ['target_system', 'target_component', 'idx', 'count', 'lat', 'lng'] + self.target_system = target_system + self.target_component = target_component + self.idx = idx + self.count = count + self.lat = lat + self.lng = lng + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 78, struct.pack(' + value[float]. This allows to send a parameter to any other + component (such as the GCS) without the need of previous + knowledge of possible parameter names. Thus the same GCS can + store different parameters for different autopilots. See also + http://qgroundcontrol.org/parameter_interface for a full + documentation of QGroundControl and IMU code. + ''' + def __init__(self, target_system, target_component, param_id, param_index): + MAVLink_message.__init__(self, MAVLINK_MSG_ID_PARAM_REQUEST_READ, 'PARAM_REQUEST_READ') + self._fieldnames = ['target_system', 'target_component', 'param_id', 'param_index'] + self.target_system = target_system + self.target_component = target_component + self.param_id = param_id + self.param_index = param_index + + def pack(self, mav): + return MAVLink_message.pack(self, mav, 214, struct.pack('= 1 and self.buf[0] != 254: + magic = self.buf[0] + self.buf = self.buf[1:] + if self.robust_parsing: + m = MAVLink_bad_data(chr(magic), "Bad prefix") + if self.callback: + self.callback(m, *self.callback_args, **self.callback_kwargs) + self.expected_length = 6 + self.total_receive_errors += 1 + return m + if self.have_prefix_error: + return None + self.have_prefix_error = True + self.total_receive_errors += 1 + raise MAVError("invalid MAVLink prefix '%s'" % magic) + self.have_prefix_error = False + if len(self.buf) >= 2: + (magic, self.expected_length) = struct.unpack('BB', self.buf[0:2]) + self.expected_length += 8 + if self.expected_length >= 8 and len(self.buf) >= self.expected_length: + mbuf = self.buf[0:self.expected_length] + self.buf = self.buf[self.expected_length:] + self.expected_length = 6 + if self.robust_parsing: + try: + m = self.decode(mbuf) + self.total_packets_received += 1 + except MAVError as reason: + m = MAVLink_bad_data(mbuf, reason.message) + self.total_receive_errors += 1 + else: + m = self.decode(mbuf) + self.total_packets_received += 1 + if self.callback: + self.callback(m, *self.callback_args, **self.callback_kwargs) + return m + return None + + def parse_buffer(self, s): + '''input some data bytes, possibly returning a list of new messages''' + m = self.parse_char(s) + if m is None: + return None + ret = [m] + while True: + m = self.parse_char("") + if m is None: + return ret + ret.append(m) + return ret + + def decode(self, msgbuf): + '''decode a buffer as a MAVLink message''' + # decode the header + try: + magic, mlen, seq, srcSystem, srcComponent, msgId = struct.unpack('cBBBBB', msgbuf[:6]) + except struct.error as emsg: + raise MAVError('Unable to unpack MAVLink header: %s' % emsg) + if ord(magic) != 254: + raise MAVError("invalid MAVLink prefix '%s'" % magic) + if mlen != len(msgbuf)-8: + raise MAVError('invalid MAVLink message length. Got %u expected %u, msgId=%u' % (len(msgbuf)-8, mlen, msgId)) + + if not msgId in mavlink_map: + raise MAVError('unknown MAVLink message ID %u' % msgId) + + # decode the payload + (fmt, type, order_map, crc_extra) = mavlink_map[msgId] + + # decode the checksum + try: + crc, = struct.unpack(' MAV. + Also used to return a point from MAV -> GCS + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + idx : point index (first point is 1, 0 is for return point) (uint8_t) + count : total number of points (for sanity checking) (uint8_t) + lat : Latitude of point (float) + lng : Longitude of point (float) + + ''' + msg = MAVLink_fence_point_message(target_system, target_component, idx, count, lat, lng) + msg.pack(self) + return msg + + def fence_point_send(self, target_system, target_component, idx, count, lat, lng): + ''' + A fence point. Used to set a point when from GCS -> MAV. + Also used to return a point from MAV -> GCS + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + idx : point index (first point is 1, 0 is for return point) (uint8_t) + count : total number of points (for sanity checking) (uint8_t) + lat : Latitude of point (float) + lng : Longitude of point (float) + + ''' + return self.send(self.fence_point_encode(target_system, target_component, idx, count, lat, lng)) + + def fence_fetch_point_encode(self, target_system, target_component, idx): + ''' + Request a current fence point from MAV + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + idx : point index (first point is 1, 0 is for return point) (uint8_t) + + ''' + msg = MAVLink_fence_fetch_point_message(target_system, target_component, idx) + msg.pack(self) + return msg + + def fence_fetch_point_send(self, target_system, target_component, idx): + ''' + Request a current fence point from MAV + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + idx : point index (first point is 1, 0 is for return point) (uint8_t) + + ''' + return self.send(self.fence_fetch_point_encode(target_system, target_component, idx)) + + def fence_status_encode(self, breach_status, breach_count, breach_type, breach_time): + ''' + Status of geo-fencing. Sent in extended status stream when + fencing enabled + + breach_status : 0 if currently inside fence, 1 if outside (uint8_t) + breach_count : number of fence breaches (uint16_t) + breach_type : last breach type (see FENCE_BREACH_* enum) (uint8_t) + breach_time : time of last breach in milliseconds since boot (uint32_t) + + ''' + msg = MAVLink_fence_status_message(breach_status, breach_count, breach_type, breach_time) + msg.pack(self) + return msg + + def fence_status_send(self, breach_status, breach_count, breach_type, breach_time): + ''' + Status of geo-fencing. Sent in extended status stream when + fencing enabled + + breach_status : 0 if currently inside fence, 1 if outside (uint8_t) + breach_count : number of fence breaches (uint16_t) + breach_type : last breach type (see FENCE_BREACH_* enum) (uint8_t) + breach_time : time of last breach in milliseconds since boot (uint32_t) + + ''' + return self.send(self.fence_status_encode(breach_status, breach_count, breach_type, breach_time)) + + def ahrs_encode(self, omegaIx, omegaIy, omegaIz, accel_weight, renorm_val, error_rp, error_yaw): + ''' + Status of DCM attitude estimator + + omegaIx : X gyro drift estimate rad/s (float) + omegaIy : Y gyro drift estimate rad/s (float) + omegaIz : Z gyro drift estimate rad/s (float) + accel_weight : average accel_weight (float) + renorm_val : average renormalisation value (float) + error_rp : average error_roll_pitch value (float) + error_yaw : average error_yaw value (float) + + ''' + msg = MAVLink_ahrs_message(omegaIx, omegaIy, omegaIz, accel_weight, renorm_val, error_rp, error_yaw) + msg.pack(self) + return msg + + def ahrs_send(self, omegaIx, omegaIy, omegaIz, accel_weight, renorm_val, error_rp, error_yaw): + ''' + Status of DCM attitude estimator + + omegaIx : X gyro drift estimate rad/s (float) + omegaIy : Y gyro drift estimate rad/s (float) + omegaIz : Z gyro drift estimate rad/s (float) + accel_weight : average accel_weight (float) + renorm_val : average renormalisation value (float) + error_rp : average error_roll_pitch value (float) + error_yaw : average error_yaw value (float) + + ''' + return self.send(self.ahrs_encode(omegaIx, omegaIy, omegaIz, accel_weight, renorm_val, error_rp, error_yaw)) + + def simstate_encode(self, roll, pitch, yaw, xacc, yacc, zacc, xgyro, ygyro, zgyro): + ''' + Status of simulation environment, if used + + roll : Roll angle (rad) (float) + pitch : Pitch angle (rad) (float) + yaw : Yaw angle (rad) (float) + xacc : X acceleration m/s/s (float) + yacc : Y acceleration m/s/s (float) + zacc : Z acceleration m/s/s (float) + xgyro : Angular speed around X axis rad/s (float) + ygyro : Angular speed around Y axis rad/s (float) + zgyro : Angular speed around Z axis rad/s (float) + + ''' + msg = MAVLink_simstate_message(roll, pitch, yaw, xacc, yacc, zacc, xgyro, ygyro, zgyro) + msg.pack(self) + return msg + + def simstate_send(self, roll, pitch, yaw, xacc, yacc, zacc, xgyro, ygyro, zgyro): + ''' + Status of simulation environment, if used + + roll : Roll angle (rad) (float) + pitch : Pitch angle (rad) (float) + yaw : Yaw angle (rad) (float) + xacc : X acceleration m/s/s (float) + yacc : Y acceleration m/s/s (float) + zacc : Z acceleration m/s/s (float) + xgyro : Angular speed around X axis rad/s (float) + ygyro : Angular speed around Y axis rad/s (float) + zgyro : Angular speed around Z axis rad/s (float) + + ''' + return self.send(self.simstate_encode(roll, pitch, yaw, xacc, yacc, zacc, xgyro, ygyro, zgyro)) + + def hwstatus_encode(self, Vcc, I2Cerr): + ''' + Status of key hardware + + Vcc : board voltage (mV) (uint16_t) + I2Cerr : I2C error count (uint8_t) + + ''' + msg = MAVLink_hwstatus_message(Vcc, I2Cerr) + msg.pack(self) + return msg + + def hwstatus_send(self, Vcc, I2Cerr): + ''' + Status of key hardware + + Vcc : board voltage (mV) (uint16_t) + I2Cerr : I2C error count (uint8_t) + + ''' + return self.send(self.hwstatus_encode(Vcc, I2Cerr)) + + def radio_encode(self, rssi, remrssi, txbuf, noise, remnoise, rxerrors, fixed): + ''' + Status generated by radio + + rssi : local signal strength (uint8_t) + remrssi : remote signal strength (uint8_t) + txbuf : how full the tx buffer is as a percentage (uint8_t) + noise : background noise level (uint8_t) + remnoise : remote background noise level (uint8_t) + rxerrors : receive errors (uint16_t) + fixed : count of error corrected packets (uint16_t) + + ''' + msg = MAVLink_radio_message(rssi, remrssi, txbuf, noise, remnoise, rxerrors, fixed) + msg.pack(self) + return msg + + def radio_send(self, rssi, remrssi, txbuf, noise, remnoise, rxerrors, fixed): + ''' + Status generated by radio + + rssi : local signal strength (uint8_t) + remrssi : remote signal strength (uint8_t) + txbuf : how full the tx buffer is as a percentage (uint8_t) + noise : background noise level (uint8_t) + remnoise : remote background noise level (uint8_t) + rxerrors : receive errors (uint16_t) + fixed : count of error corrected packets (uint16_t) + + ''' + return self.send(self.radio_encode(rssi, remrssi, txbuf, noise, remnoise, rxerrors, fixed)) + + def heartbeat_encode(self, type, autopilot, base_mode, custom_mode, system_status, mavlink_version=3): + ''' + The heartbeat message shows that a system is present and responding. + The type of the MAV and Autopilot hardware allow the + receiving system to treat further messages from this + system appropriate (e.g. by laying out the user + interface based on the autopilot). + + type : Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) (uint8_t) + autopilot : Autopilot type / class. defined in MAV_CLASS ENUM (uint8_t) + base_mode : System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h (uint8_t) + custom_mode : Navigation mode bitfield, see MAV_AUTOPILOT_CUSTOM_MODE ENUM for some examples. This field is autopilot-specific. (uint32_t) + system_status : System status flag, see MAV_STATUS ENUM (uint8_t) + mavlink_version : MAVLink version (uint8_t) + + ''' + msg = MAVLink_heartbeat_message(type, autopilot, base_mode, custom_mode, system_status, mavlink_version) + msg.pack(self) + return msg + + def heartbeat_send(self, type, autopilot, base_mode, custom_mode, system_status, mavlink_version=3): + ''' + The heartbeat message shows that a system is present and responding. + The type of the MAV and Autopilot hardware allow the + receiving system to treat further messages from this + system appropriate (e.g. by laying out the user + interface based on the autopilot). + + type : Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM) (uint8_t) + autopilot : Autopilot type / class. defined in MAV_CLASS ENUM (uint8_t) + base_mode : System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h (uint8_t) + custom_mode : Navigation mode bitfield, see MAV_AUTOPILOT_CUSTOM_MODE ENUM for some examples. This field is autopilot-specific. (uint32_t) + system_status : System status flag, see MAV_STATUS ENUM (uint8_t) + mavlink_version : MAVLink version (uint8_t) + + ''' + return self.send(self.heartbeat_encode(type, autopilot, base_mode, custom_mode, system_status, mavlink_version)) + + def sys_status_encode(self, onboard_control_sensors_present, onboard_control_sensors_enabled, onboard_control_sensors_health, load, voltage_battery, current_battery, battery_remaining, drop_rate_comm, errors_comm, errors_count1, errors_count2, errors_count3, errors_count4): + ''' + The general system state. If the system is following the MAVLink + standard, the system state is mainly defined by three + orthogonal states/modes: The system mode, which is + either LOCKED (motors shut down and locked), MANUAL + (system under RC control), GUIDED (system with + autonomous position control, position setpoint + controlled manually) or AUTO (system guided by + path/waypoint planner). The NAV_MODE defined the + current flight state: LIFTOFF (often an open-loop + maneuver), LANDING, WAYPOINTS or VECTOR. This + represents the internal navigation state machine. The + system status shows wether the system is currently + active or not and if an emergency occured. During the + CRITICAL and EMERGENCY states the MAV is still + considered to be active, but should start emergency + procedures autonomously. After a failure occured it + should first move from active to critical to allow + manual intervention and then move to emergency after a + certain timeout. + + onboard_control_sensors_present : Bitmask showing which onboard controllers and sensors are present. Value of 0: not present. Value of 1: present. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control (uint32_t) + onboard_control_sensors_enabled : Bitmask showing which onboard controllers and sensors are enabled: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control (uint32_t) + onboard_control_sensors_health : Bitmask showing which onboard controllers and sensors are operational or have an error: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control (uint32_t) + load : Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 (uint16_t) + voltage_battery : Battery voltage, in millivolts (1 = 1 millivolt) (uint16_t) + current_battery : Battery current, in 10*milliamperes (1 = 10 milliampere), -1: autopilot does not measure the current (int16_t) + battery_remaining : Remaining battery energy: (0%: 0, 100%: 100), -1: autopilot estimate the remaining battery (int8_t) + drop_rate_comm : Communication drops in percent, (0%: 0, 100%: 10'000), (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) (uint16_t) + errors_comm : Communication errors (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) (uint16_t) + errors_count1 : Autopilot-specific errors (uint16_t) + errors_count2 : Autopilot-specific errors (uint16_t) + errors_count3 : Autopilot-specific errors (uint16_t) + errors_count4 : Autopilot-specific errors (uint16_t) + + ''' + msg = MAVLink_sys_status_message(onboard_control_sensors_present, onboard_control_sensors_enabled, onboard_control_sensors_health, load, voltage_battery, current_battery, battery_remaining, drop_rate_comm, errors_comm, errors_count1, errors_count2, errors_count3, errors_count4) + msg.pack(self) + return msg + + def sys_status_send(self, onboard_control_sensors_present, onboard_control_sensors_enabled, onboard_control_sensors_health, load, voltage_battery, current_battery, battery_remaining, drop_rate_comm, errors_comm, errors_count1, errors_count2, errors_count3, errors_count4): + ''' + The general system state. If the system is following the MAVLink + standard, the system state is mainly defined by three + orthogonal states/modes: The system mode, which is + either LOCKED (motors shut down and locked), MANUAL + (system under RC control), GUIDED (system with + autonomous position control, position setpoint + controlled manually) or AUTO (system guided by + path/waypoint planner). The NAV_MODE defined the + current flight state: LIFTOFF (often an open-loop + maneuver), LANDING, WAYPOINTS or VECTOR. This + represents the internal navigation state machine. The + system status shows wether the system is currently + active or not and if an emergency occured. During the + CRITICAL and EMERGENCY states the MAV is still + considered to be active, but should start emergency + procedures autonomously. After a failure occured it + should first move from active to critical to allow + manual intervention and then move to emergency after a + certain timeout. + + onboard_control_sensors_present : Bitmask showing which onboard controllers and sensors are present. Value of 0: not present. Value of 1: present. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control (uint32_t) + onboard_control_sensors_enabled : Bitmask showing which onboard controllers and sensors are enabled: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control (uint32_t) + onboard_control_sensors_health : Bitmask showing which onboard controllers and sensors are operational or have an error: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control (uint32_t) + load : Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000 (uint16_t) + voltage_battery : Battery voltage, in millivolts (1 = 1 millivolt) (uint16_t) + current_battery : Battery current, in 10*milliamperes (1 = 10 milliampere), -1: autopilot does not measure the current (int16_t) + battery_remaining : Remaining battery energy: (0%: 0, 100%: 100), -1: autopilot estimate the remaining battery (int8_t) + drop_rate_comm : Communication drops in percent, (0%: 0, 100%: 10'000), (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) (uint16_t) + errors_comm : Communication errors (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV) (uint16_t) + errors_count1 : Autopilot-specific errors (uint16_t) + errors_count2 : Autopilot-specific errors (uint16_t) + errors_count3 : Autopilot-specific errors (uint16_t) + errors_count4 : Autopilot-specific errors (uint16_t) + + ''' + return self.send(self.sys_status_encode(onboard_control_sensors_present, onboard_control_sensors_enabled, onboard_control_sensors_health, load, voltage_battery, current_battery, battery_remaining, drop_rate_comm, errors_comm, errors_count1, errors_count2, errors_count3, errors_count4)) + + def system_time_encode(self, time_unix_usec, time_boot_ms): + ''' + The system time is the time of the master clock, typically the + computer clock of the main onboard computer. + + time_unix_usec : Timestamp of the master clock in microseconds since UNIX epoch. (uint64_t) + time_boot_ms : Timestamp of the component clock since boot time in milliseconds. (uint32_t) + + ''' + msg = MAVLink_system_time_message(time_unix_usec, time_boot_ms) + msg.pack(self) + return msg + + def system_time_send(self, time_unix_usec, time_boot_ms): + ''' + The system time is the time of the master clock, typically the + computer clock of the main onboard computer. + + time_unix_usec : Timestamp of the master clock in microseconds since UNIX epoch. (uint64_t) + time_boot_ms : Timestamp of the component clock since boot time in milliseconds. (uint32_t) + + ''' + return self.send(self.system_time_encode(time_unix_usec, time_boot_ms)) + + def ping_encode(self, time_usec, seq, target_system, target_component): + ''' + A ping message either requesting or responding to a ping. This allows + to measure the system latencies, including serial + port, radio modem and UDP connections. + + time_usec : Unix timestamp in microseconds (uint64_t) + seq : PING sequence (uint32_t) + target_system : 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system (uint8_t) + target_component : 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system (uint8_t) + + ''' + msg = MAVLink_ping_message(time_usec, seq, target_system, target_component) + msg.pack(self) + return msg + + def ping_send(self, time_usec, seq, target_system, target_component): + ''' + A ping message either requesting or responding to a ping. This allows + to measure the system latencies, including serial + port, radio modem and UDP connections. + + time_usec : Unix timestamp in microseconds (uint64_t) + seq : PING sequence (uint32_t) + target_system : 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system (uint8_t) + target_component : 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system (uint8_t) + + ''' + return self.send(self.ping_encode(time_usec, seq, target_system, target_component)) + + def change_operator_control_encode(self, target_system, control_request, version, passkey): + ''' + Request to control this MAV + + target_system : System the GCS requests control for (uint8_t) + control_request : 0: request control of this MAV, 1: Release control of this MAV (uint8_t) + version : 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. (uint8_t) + passkey : Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" (char) + + ''' + msg = MAVLink_change_operator_control_message(target_system, control_request, version, passkey) + msg.pack(self) + return msg + + def change_operator_control_send(self, target_system, control_request, version, passkey): + ''' + Request to control this MAV + + target_system : System the GCS requests control for (uint8_t) + control_request : 0: request control of this MAV, 1: Release control of this MAV (uint8_t) + version : 0: key as plaintext, 1-255: future, different hashing/encryption variants. The GCS should in general use the safest mode possible initially and then gradually move down the encryption level if it gets a NACK message indicating an encryption mismatch. (uint8_t) + passkey : Password / Key, depending on version plaintext or encrypted. 25 or less characters, NULL terminated. The characters may involve A-Z, a-z, 0-9, and "!?,.-" (char) + + ''' + return self.send(self.change_operator_control_encode(target_system, control_request, version, passkey)) + + def change_operator_control_ack_encode(self, gcs_system_id, control_request, ack): + ''' + Accept / deny control of this MAV + + gcs_system_id : ID of the GCS this message (uint8_t) + control_request : 0: request control of this MAV, 1: Release control of this MAV (uint8_t) + ack : 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control (uint8_t) + + ''' + msg = MAVLink_change_operator_control_ack_message(gcs_system_id, control_request, ack) + msg.pack(self) + return msg + + def change_operator_control_ack_send(self, gcs_system_id, control_request, ack): + ''' + Accept / deny control of this MAV + + gcs_system_id : ID of the GCS this message (uint8_t) + control_request : 0: request control of this MAV, 1: Release control of this MAV (uint8_t) + ack : 0: ACK, 1: NACK: Wrong passkey, 2: NACK: Unsupported passkey encryption method, 3: NACK: Already under control (uint8_t) + + ''' + return self.send(self.change_operator_control_ack_encode(gcs_system_id, control_request, ack)) + + def auth_key_encode(self, key): + ''' + Emit an encrypted signature / key identifying this system. PLEASE + NOTE: This protocol has been kept simple, so + transmitting the key requires an encrypted channel for + true safety. + + key : key (char) + + ''' + msg = MAVLink_auth_key_message(key) + msg.pack(self) + return msg + + def auth_key_send(self, key): + ''' + Emit an encrypted signature / key identifying this system. PLEASE + NOTE: This protocol has been kept simple, so + transmitting the key requires an encrypted channel for + true safety. + + key : key (char) + + ''' + return self.send(self.auth_key_encode(key)) + + def set_mode_encode(self, target_system, base_mode, custom_mode): + ''' + Set the system mode, as defined by enum MAV_MODE. There is no target + component id as the mode is by definition for the + overall aircraft, not only for one component. + + target_system : The system setting the mode (uint8_t) + base_mode : The new base mode (uint8_t) + custom_mode : The new autopilot-specific mode. This field can be ignored by an autopilot. (uint32_t) + + ''' + msg = MAVLink_set_mode_message(target_system, base_mode, custom_mode) + msg.pack(self) + return msg + + def set_mode_send(self, target_system, base_mode, custom_mode): + ''' + Set the system mode, as defined by enum MAV_MODE. There is no target + component id as the mode is by definition for the + overall aircraft, not only for one component. + + target_system : The system setting the mode (uint8_t) + base_mode : The new base mode (uint8_t) + custom_mode : The new autopilot-specific mode. This field can be ignored by an autopilot. (uint32_t) + + ''' + return self.send(self.set_mode_encode(target_system, base_mode, custom_mode)) + + def param_request_read_encode(self, target_system, target_component, param_id, param_index): + ''' + Request to read the onboard parameter with the param_id string id. + Onboard parameters are stored as key[const char*] -> + value[float]. This allows to send a parameter to any + other component (such as the GCS) without the need of + previous knowledge of possible parameter names. Thus + the same GCS can store different parameters for + different autopilots. See also + http://qgroundcontrol.org/parameter_interface for a + full documentation of QGroundControl and IMU code. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + param_id : Onboard parameter id (char) + param_index : Parameter index. Send -1 to use the param ID field as identifier (int16_t) + + ''' + msg = MAVLink_param_request_read_message(target_system, target_component, param_id, param_index) + msg.pack(self) + return msg + + def param_request_read_send(self, target_system, target_component, param_id, param_index): + ''' + Request to read the onboard parameter with the param_id string id. + Onboard parameters are stored as key[const char*] -> + value[float]. This allows to send a parameter to any + other component (such as the GCS) without the need of + previous knowledge of possible parameter names. Thus + the same GCS can store different parameters for + different autopilots. See also + http://qgroundcontrol.org/parameter_interface for a + full documentation of QGroundControl and IMU code. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + param_id : Onboard parameter id (char) + param_index : Parameter index. Send -1 to use the param ID field as identifier (int16_t) + + ''' + return self.send(self.param_request_read_encode(target_system, target_component, param_id, param_index)) + + def param_request_list_encode(self, target_system, target_component): + ''' + Request all parameters of this component. After his request, all + parameters are emitted. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + + ''' + msg = MAVLink_param_request_list_message(target_system, target_component) + msg.pack(self) + return msg + + def param_request_list_send(self, target_system, target_component): + ''' + Request all parameters of this component. After his request, all + parameters are emitted. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + + ''' + return self.send(self.param_request_list_encode(target_system, target_component)) + + def param_value_encode(self, param_id, param_value, param_type, param_count, param_index): + ''' + Emit the value of a onboard parameter. The inclusion of param_count + and param_index in the message allows the recipient to + keep track of received parameters and allows him to + re-request missing parameters after a loss or timeout. + + param_id : Onboard parameter id (char) + param_value : Onboard parameter value (float) + param_type : Onboard parameter type: see MAV_VAR enum (uint8_t) + param_count : Total number of onboard parameters (uint16_t) + param_index : Index of this onboard parameter (uint16_t) + + ''' + msg = MAVLink_param_value_message(param_id, param_value, param_type, param_count, param_index) + msg.pack(self) + return msg + + def param_value_send(self, param_id, param_value, param_type, param_count, param_index): + ''' + Emit the value of a onboard parameter. The inclusion of param_count + and param_index in the message allows the recipient to + keep track of received parameters and allows him to + re-request missing parameters after a loss or timeout. + + param_id : Onboard parameter id (char) + param_value : Onboard parameter value (float) + param_type : Onboard parameter type: see MAV_VAR enum (uint8_t) + param_count : Total number of onboard parameters (uint16_t) + param_index : Index of this onboard parameter (uint16_t) + + ''' + return self.send(self.param_value_encode(param_id, param_value, param_type, param_count, param_index)) + + def param_set_encode(self, target_system, target_component, param_id, param_value, param_type): + ''' + Set a parameter value TEMPORARILY to RAM. It will be reset to default + on system reboot. Send the ACTION + MAV_ACTION_STORAGE_WRITE to PERMANENTLY write the RAM + contents to EEPROM. IMPORTANT: The receiving component + should acknowledge the new parameter value by sending + a param_value message to all communication partners. + This will also ensure that multiple GCS all have an + up-to-date list of all parameters. If the sending GCS + did not receive a PARAM_VALUE message within its + timeout time, it should re-send the PARAM_SET message. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + param_id : Onboard parameter id (char) + param_value : Onboard parameter value (float) + param_type : Onboard parameter type: see MAV_VAR enum (uint8_t) + + ''' + msg = MAVLink_param_set_message(target_system, target_component, param_id, param_value, param_type) + msg.pack(self) + return msg + + def param_set_send(self, target_system, target_component, param_id, param_value, param_type): + ''' + Set a parameter value TEMPORARILY to RAM. It will be reset to default + on system reboot. Send the ACTION + MAV_ACTION_STORAGE_WRITE to PERMANENTLY write the RAM + contents to EEPROM. IMPORTANT: The receiving component + should acknowledge the new parameter value by sending + a param_value message to all communication partners. + This will also ensure that multiple GCS all have an + up-to-date list of all parameters. If the sending GCS + did not receive a PARAM_VALUE message within its + timeout time, it should re-send the PARAM_SET message. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + param_id : Onboard parameter id (char) + param_value : Onboard parameter value (float) + param_type : Onboard parameter type: see MAV_VAR enum (uint8_t) + + ''' + return self.send(self.param_set_encode(target_system, target_component, param_id, param_value, param_type)) + + def gps_raw_int_encode(self, time_usec, fix_type, lat, lon, alt, eph, epv, vel, cog, satellites_visible): + ''' + The global position, as returned by the Global Positioning System + (GPS). This is NOT the global position + estimate of the sytem, but rather a RAW sensor value. + See message GLOBAL_POSITION for the global position + estimate. Coordinate frame is right-handed, Z-axis up + (GPS frame) + + time_usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + fix_type : 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. (uint8_t) + lat : Latitude in 1E7 degrees (int32_t) + lon : Longitude in 1E7 degrees (int32_t) + alt : Altitude in 1E3 meters (millimeters) above MSL (int32_t) + eph : GPS HDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 (uint16_t) + epv : GPS VDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 (uint16_t) + vel : GPS ground speed (m/s * 100). If unknown, set to: 65535 (uint16_t) + cog : Course over ground (NOT heading, but direction of movement) in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 (uint16_t) + satellites_visible : Number of satellites visible. If unknown, set to 255 (uint8_t) + + ''' + msg = MAVLink_gps_raw_int_message(time_usec, fix_type, lat, lon, alt, eph, epv, vel, cog, satellites_visible) + msg.pack(self) + return msg + + def gps_raw_int_send(self, time_usec, fix_type, lat, lon, alt, eph, epv, vel, cog, satellites_visible): + ''' + The global position, as returned by the Global Positioning System + (GPS). This is NOT the global position + estimate of the sytem, but rather a RAW sensor value. + See message GLOBAL_POSITION for the global position + estimate. Coordinate frame is right-handed, Z-axis up + (GPS frame) + + time_usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + fix_type : 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. (uint8_t) + lat : Latitude in 1E7 degrees (int32_t) + lon : Longitude in 1E7 degrees (int32_t) + alt : Altitude in 1E3 meters (millimeters) above MSL (int32_t) + eph : GPS HDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 (uint16_t) + epv : GPS VDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535 (uint16_t) + vel : GPS ground speed (m/s * 100). If unknown, set to: 65535 (uint16_t) + cog : Course over ground (NOT heading, but direction of movement) in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 (uint16_t) + satellites_visible : Number of satellites visible. If unknown, set to 255 (uint8_t) + + ''' + return self.send(self.gps_raw_int_encode(time_usec, fix_type, lat, lon, alt, eph, epv, vel, cog, satellites_visible)) + + def gps_status_encode(self, satellites_visible, satellite_prn, satellite_used, satellite_elevation, satellite_azimuth, satellite_snr): + ''' + The positioning status, as reported by GPS. This message is intended + to display status information about each satellite + visible to the receiver. See message GLOBAL_POSITION + for the global position estimate. This message can + contain information for up to 20 satellites. + + satellites_visible : Number of satellites visible (uint8_t) + satellite_prn : Global satellite ID (uint8_t) + satellite_used : 0: Satellite not used, 1: used for localization (uint8_t) + satellite_elevation : Elevation (0: right on top of receiver, 90: on the horizon) of satellite (uint8_t) + satellite_azimuth : Direction of satellite, 0: 0 deg, 255: 360 deg. (uint8_t) + satellite_snr : Signal to noise ratio of satellite (uint8_t) + + ''' + msg = MAVLink_gps_status_message(satellites_visible, satellite_prn, satellite_used, satellite_elevation, satellite_azimuth, satellite_snr) + msg.pack(self) + return msg + + def gps_status_send(self, satellites_visible, satellite_prn, satellite_used, satellite_elevation, satellite_azimuth, satellite_snr): + ''' + The positioning status, as reported by GPS. This message is intended + to display status information about each satellite + visible to the receiver. See message GLOBAL_POSITION + for the global position estimate. This message can + contain information for up to 20 satellites. + + satellites_visible : Number of satellites visible (uint8_t) + satellite_prn : Global satellite ID (uint8_t) + satellite_used : 0: Satellite not used, 1: used for localization (uint8_t) + satellite_elevation : Elevation (0: right on top of receiver, 90: on the horizon) of satellite (uint8_t) + satellite_azimuth : Direction of satellite, 0: 0 deg, 255: 360 deg. (uint8_t) + satellite_snr : Signal to noise ratio of satellite (uint8_t) + + ''' + return self.send(self.gps_status_encode(satellites_visible, satellite_prn, satellite_used, satellite_elevation, satellite_azimuth, satellite_snr)) + + def scaled_imu_encode(self, time_boot_ms, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag): + ''' + The RAW IMU readings for the usual 9DOF sensor setup. This message + should contain the scaled values to the described + units + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + xacc : X acceleration (mg) (int16_t) + yacc : Y acceleration (mg) (int16_t) + zacc : Z acceleration (mg) (int16_t) + xgyro : Angular speed around X axis (millirad /sec) (int16_t) + ygyro : Angular speed around Y axis (millirad /sec) (int16_t) + zgyro : Angular speed around Z axis (millirad /sec) (int16_t) + xmag : X Magnetic field (milli tesla) (int16_t) + ymag : Y Magnetic field (milli tesla) (int16_t) + zmag : Z Magnetic field (milli tesla) (int16_t) + + ''' + msg = MAVLink_scaled_imu_message(time_boot_ms, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag) + msg.pack(self) + return msg + + def scaled_imu_send(self, time_boot_ms, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag): + ''' + The RAW IMU readings for the usual 9DOF sensor setup. This message + should contain the scaled values to the described + units + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + xacc : X acceleration (mg) (int16_t) + yacc : Y acceleration (mg) (int16_t) + zacc : Z acceleration (mg) (int16_t) + xgyro : Angular speed around X axis (millirad /sec) (int16_t) + ygyro : Angular speed around Y axis (millirad /sec) (int16_t) + zgyro : Angular speed around Z axis (millirad /sec) (int16_t) + xmag : X Magnetic field (milli tesla) (int16_t) + ymag : Y Magnetic field (milli tesla) (int16_t) + zmag : Z Magnetic field (milli tesla) (int16_t) + + ''' + return self.send(self.scaled_imu_encode(time_boot_ms, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag)) + + def raw_imu_encode(self, time_usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag): + ''' + The RAW IMU readings for the usual 9DOF sensor setup. This message + should always contain the true raw values without any + scaling to allow data capture and system debugging. + + time_usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + xacc : X acceleration (raw) (int16_t) + yacc : Y acceleration (raw) (int16_t) + zacc : Z acceleration (raw) (int16_t) + xgyro : Angular speed around X axis (raw) (int16_t) + ygyro : Angular speed around Y axis (raw) (int16_t) + zgyro : Angular speed around Z axis (raw) (int16_t) + xmag : X Magnetic field (raw) (int16_t) + ymag : Y Magnetic field (raw) (int16_t) + zmag : Z Magnetic field (raw) (int16_t) + + ''' + msg = MAVLink_raw_imu_message(time_usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag) + msg.pack(self) + return msg + + def raw_imu_send(self, time_usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag): + ''' + The RAW IMU readings for the usual 9DOF sensor setup. This message + should always contain the true raw values without any + scaling to allow data capture and system debugging. + + time_usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + xacc : X acceleration (raw) (int16_t) + yacc : Y acceleration (raw) (int16_t) + zacc : Z acceleration (raw) (int16_t) + xgyro : Angular speed around X axis (raw) (int16_t) + ygyro : Angular speed around Y axis (raw) (int16_t) + zgyro : Angular speed around Z axis (raw) (int16_t) + xmag : X Magnetic field (raw) (int16_t) + ymag : Y Magnetic field (raw) (int16_t) + zmag : Z Magnetic field (raw) (int16_t) + + ''' + return self.send(self.raw_imu_encode(time_usec, xacc, yacc, zacc, xgyro, ygyro, zgyro, xmag, ymag, zmag)) + + def raw_pressure_encode(self, time_usec, press_abs, press_diff1, press_diff2, temperature): + ''' + The RAW pressure readings for the typical setup of one absolute + pressure and one differential pressure sensor. The + sensor values should be the raw, UNSCALED ADC values. + + time_usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + press_abs : Absolute pressure (raw) (int16_t) + press_diff1 : Differential pressure 1 (raw) (int16_t) + press_diff2 : Differential pressure 2 (raw) (int16_t) + temperature : Raw Temperature measurement (raw) (int16_t) + + ''' + msg = MAVLink_raw_pressure_message(time_usec, press_abs, press_diff1, press_diff2, temperature) + msg.pack(self) + return msg + + def raw_pressure_send(self, time_usec, press_abs, press_diff1, press_diff2, temperature): + ''' + The RAW pressure readings for the typical setup of one absolute + pressure and one differential pressure sensor. The + sensor values should be the raw, UNSCALED ADC values. + + time_usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + press_abs : Absolute pressure (raw) (int16_t) + press_diff1 : Differential pressure 1 (raw) (int16_t) + press_diff2 : Differential pressure 2 (raw) (int16_t) + temperature : Raw Temperature measurement (raw) (int16_t) + + ''' + return self.send(self.raw_pressure_encode(time_usec, press_abs, press_diff1, press_diff2, temperature)) + + def scaled_pressure_encode(self, time_boot_ms, press_abs, press_diff, temperature): + ''' + The pressure readings for the typical setup of one absolute and + differential pressure sensor. The units are as + specified in each field. + + time_boot_ms : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint32_t) + press_abs : Absolute pressure (hectopascal) (float) + press_diff : Differential pressure 1 (hectopascal) (float) + temperature : Temperature measurement (0.01 degrees celsius) (int16_t) + + ''' + msg = MAVLink_scaled_pressure_message(time_boot_ms, press_abs, press_diff, temperature) + msg.pack(self) + return msg + + def scaled_pressure_send(self, time_boot_ms, press_abs, press_diff, temperature): + ''' + The pressure readings for the typical setup of one absolute and + differential pressure sensor. The units are as + specified in each field. + + time_boot_ms : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint32_t) + press_abs : Absolute pressure (hectopascal) (float) + press_diff : Differential pressure 1 (hectopascal) (float) + temperature : Temperature measurement (0.01 degrees celsius) (int16_t) + + ''' + return self.send(self.scaled_pressure_encode(time_boot_ms, press_abs, press_diff, temperature)) + + def attitude_encode(self, time_boot_ms, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed): + ''' + The attitude in the aeronautical frame (right-handed, Z-down, X-front, + Y-right). + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + roll : Roll angle (rad) (float) + pitch : Pitch angle (rad) (float) + yaw : Yaw angle (rad) (float) + rollspeed : Roll angular speed (rad/s) (float) + pitchspeed : Pitch angular speed (rad/s) (float) + yawspeed : Yaw angular speed (rad/s) (float) + + ''' + msg = MAVLink_attitude_message(time_boot_ms, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed) + msg.pack(self) + return msg + + def attitude_send(self, time_boot_ms, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed): + ''' + The attitude in the aeronautical frame (right-handed, Z-down, X-front, + Y-right). + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + roll : Roll angle (rad) (float) + pitch : Pitch angle (rad) (float) + yaw : Yaw angle (rad) (float) + rollspeed : Roll angular speed (rad/s) (float) + pitchspeed : Pitch angular speed (rad/s) (float) + yawspeed : Yaw angular speed (rad/s) (float) + + ''' + return self.send(self.attitude_encode(time_boot_ms, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed)) + + def attitude_quaternion_encode(self, time_boot_ms, q1, q2, q3, q4, rollspeed, pitchspeed, yawspeed): + ''' + The attitude in the aeronautical frame (right-handed, Z-down, X-front, + Y-right), expressed as quaternion. + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + q1 : Quaternion component 1 (float) + q2 : Quaternion component 2 (float) + q3 : Quaternion component 3 (float) + q4 : Quaternion component 4 (float) + rollspeed : Roll angular speed (rad/s) (float) + pitchspeed : Pitch angular speed (rad/s) (float) + yawspeed : Yaw angular speed (rad/s) (float) + + ''' + msg = MAVLink_attitude_quaternion_message(time_boot_ms, q1, q2, q3, q4, rollspeed, pitchspeed, yawspeed) + msg.pack(self) + return msg + + def attitude_quaternion_send(self, time_boot_ms, q1, q2, q3, q4, rollspeed, pitchspeed, yawspeed): + ''' + The attitude in the aeronautical frame (right-handed, Z-down, X-front, + Y-right), expressed as quaternion. + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + q1 : Quaternion component 1 (float) + q2 : Quaternion component 2 (float) + q3 : Quaternion component 3 (float) + q4 : Quaternion component 4 (float) + rollspeed : Roll angular speed (rad/s) (float) + pitchspeed : Pitch angular speed (rad/s) (float) + yawspeed : Yaw angular speed (rad/s) (float) + + ''' + return self.send(self.attitude_quaternion_encode(time_boot_ms, q1, q2, q3, q4, rollspeed, pitchspeed, yawspeed)) + + def local_position_ned_encode(self, time_boot_ms, x, y, z, vx, vy, vz): + ''' + The filtered local position (e.g. fused computer vision and + accelerometers). Coordinate frame is right-handed, + Z-axis down (aeronautical frame, NED / north-east-down + convention) + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + x : X Position (float) + y : Y Position (float) + z : Z Position (float) + vx : X Speed (float) + vy : Y Speed (float) + vz : Z Speed (float) + + ''' + msg = MAVLink_local_position_ned_message(time_boot_ms, x, y, z, vx, vy, vz) + msg.pack(self) + return msg + + def local_position_ned_send(self, time_boot_ms, x, y, z, vx, vy, vz): + ''' + The filtered local position (e.g. fused computer vision and + accelerometers). Coordinate frame is right-handed, + Z-axis down (aeronautical frame, NED / north-east-down + convention) + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + x : X Position (float) + y : Y Position (float) + z : Z Position (float) + vx : X Speed (float) + vy : Y Speed (float) + vz : Z Speed (float) + + ''' + return self.send(self.local_position_ned_encode(time_boot_ms, x, y, z, vx, vy, vz)) + + def global_position_int_encode(self, time_boot_ms, lat, lon, alt, relative_alt, vx, vy, vz, hdg): + ''' + The filtered global position (e.g. fused GPS and accelerometers). The + position is in GPS-frame (right-handed, Z-up). It + is designed as scaled integer message since the + resolution of float is not sufficient. + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + lat : Latitude, expressed as * 1E7 (int32_t) + lon : Longitude, expressed as * 1E7 (int32_t) + alt : Altitude in meters, expressed as * 1000 (millimeters), above MSL (int32_t) + relative_alt : Altitude above ground in meters, expressed as * 1000 (millimeters) (int32_t) + vx : Ground X Speed (Latitude), expressed as m/s * 100 (int16_t) + vy : Ground Y Speed (Longitude), expressed as m/s * 100 (int16_t) + vz : Ground Z Speed (Altitude), expressed as m/s * 100 (int16_t) + hdg : Compass heading in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 (uint16_t) + + ''' + msg = MAVLink_global_position_int_message(time_boot_ms, lat, lon, alt, relative_alt, vx, vy, vz, hdg) + msg.pack(self) + return msg + + def global_position_int_send(self, time_boot_ms, lat, lon, alt, relative_alt, vx, vy, vz, hdg): + ''' + The filtered global position (e.g. fused GPS and accelerometers). The + position is in GPS-frame (right-handed, Z-up). It + is designed as scaled integer message since the + resolution of float is not sufficient. + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + lat : Latitude, expressed as * 1E7 (int32_t) + lon : Longitude, expressed as * 1E7 (int32_t) + alt : Altitude in meters, expressed as * 1000 (millimeters), above MSL (int32_t) + relative_alt : Altitude above ground in meters, expressed as * 1000 (millimeters) (int32_t) + vx : Ground X Speed (Latitude), expressed as m/s * 100 (int16_t) + vy : Ground Y Speed (Longitude), expressed as m/s * 100 (int16_t) + vz : Ground Z Speed (Altitude), expressed as m/s * 100 (int16_t) + hdg : Compass heading in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535 (uint16_t) + + ''' + return self.send(self.global_position_int_encode(time_boot_ms, lat, lon, alt, relative_alt, vx, vy, vz, hdg)) + + def rc_channels_scaled_encode(self, time_boot_ms, port, chan1_scaled, chan2_scaled, chan3_scaled, chan4_scaled, chan5_scaled, chan6_scaled, chan7_scaled, chan8_scaled, rssi): + ''' + The scaled values of the RC channels received. (-100%) -10000, (0%) 0, + (100%) 10000 + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + port : Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. (uint8_t) + chan1_scaled : RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan2_scaled : RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan3_scaled : RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan4_scaled : RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan5_scaled : RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan6_scaled : RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan7_scaled : RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan8_scaled : RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + rssi : Receive signal strength indicator, 0: 0%, 255: 100% (uint8_t) + + ''' + msg = MAVLink_rc_channels_scaled_message(time_boot_ms, port, chan1_scaled, chan2_scaled, chan3_scaled, chan4_scaled, chan5_scaled, chan6_scaled, chan7_scaled, chan8_scaled, rssi) + msg.pack(self) + return msg + + def rc_channels_scaled_send(self, time_boot_ms, port, chan1_scaled, chan2_scaled, chan3_scaled, chan4_scaled, chan5_scaled, chan6_scaled, chan7_scaled, chan8_scaled, rssi): + ''' + The scaled values of the RC channels received. (-100%) -10000, (0%) 0, + (100%) 10000 + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + port : Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. (uint8_t) + chan1_scaled : RC channel 1 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan2_scaled : RC channel 2 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan3_scaled : RC channel 3 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan4_scaled : RC channel 4 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan5_scaled : RC channel 5 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan6_scaled : RC channel 6 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan7_scaled : RC channel 7 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + chan8_scaled : RC channel 8 value scaled, (-100%) -10000, (0%) 0, (100%) 10000 (int16_t) + rssi : Receive signal strength indicator, 0: 0%, 255: 100% (uint8_t) + + ''' + return self.send(self.rc_channels_scaled_encode(time_boot_ms, port, chan1_scaled, chan2_scaled, chan3_scaled, chan4_scaled, chan5_scaled, chan6_scaled, chan7_scaled, chan8_scaled, rssi)) + + def rc_channels_raw_encode(self, time_boot_ms, port, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw, rssi): + ''' + The RAW values of the RC channels received. The standard PPM + modulation is as follows: 1000 microseconds: 0%, 2000 + microseconds: 100%. Individual receivers/transmitters + might violate this specification. + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + port : Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. (uint8_t) + chan1_raw : RC channel 1 value, in microseconds (uint16_t) + chan2_raw : RC channel 2 value, in microseconds (uint16_t) + chan3_raw : RC channel 3 value, in microseconds (uint16_t) + chan4_raw : RC channel 4 value, in microseconds (uint16_t) + chan5_raw : RC channel 5 value, in microseconds (uint16_t) + chan6_raw : RC channel 6 value, in microseconds (uint16_t) + chan7_raw : RC channel 7 value, in microseconds (uint16_t) + chan8_raw : RC channel 8 value, in microseconds (uint16_t) + rssi : Receive signal strength indicator, 0: 0%, 255: 100% (uint8_t) + + ''' + msg = MAVLink_rc_channels_raw_message(time_boot_ms, port, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw, rssi) + msg.pack(self) + return msg + + def rc_channels_raw_send(self, time_boot_ms, port, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw, rssi): + ''' + The RAW values of the RC channels received. The standard PPM + modulation is as follows: 1000 microseconds: 0%, 2000 + microseconds: 100%. Individual receivers/transmitters + might violate this specification. + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + port : Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. (uint8_t) + chan1_raw : RC channel 1 value, in microseconds (uint16_t) + chan2_raw : RC channel 2 value, in microseconds (uint16_t) + chan3_raw : RC channel 3 value, in microseconds (uint16_t) + chan4_raw : RC channel 4 value, in microseconds (uint16_t) + chan5_raw : RC channel 5 value, in microseconds (uint16_t) + chan6_raw : RC channel 6 value, in microseconds (uint16_t) + chan7_raw : RC channel 7 value, in microseconds (uint16_t) + chan8_raw : RC channel 8 value, in microseconds (uint16_t) + rssi : Receive signal strength indicator, 0: 0%, 255: 100% (uint8_t) + + ''' + return self.send(self.rc_channels_raw_encode(time_boot_ms, port, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw, rssi)) + + def servo_output_raw_encode(self, time_usec, port, servo1_raw, servo2_raw, servo3_raw, servo4_raw, servo5_raw, servo6_raw, servo7_raw, servo8_raw): + ''' + The RAW values of the servo outputs (for RC input from the remote, use + the RC_CHANNELS messages). The standard PPM modulation + is as follows: 1000 microseconds: 0%, 2000 + microseconds: 100%. + + time_usec : Timestamp (since UNIX epoch or microseconds since system boot) (uint32_t) + port : Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. (uint8_t) + servo1_raw : Servo output 1 value, in microseconds (uint16_t) + servo2_raw : Servo output 2 value, in microseconds (uint16_t) + servo3_raw : Servo output 3 value, in microseconds (uint16_t) + servo4_raw : Servo output 4 value, in microseconds (uint16_t) + servo5_raw : Servo output 5 value, in microseconds (uint16_t) + servo6_raw : Servo output 6 value, in microseconds (uint16_t) + servo7_raw : Servo output 7 value, in microseconds (uint16_t) + servo8_raw : Servo output 8 value, in microseconds (uint16_t) + + ''' + msg = MAVLink_servo_output_raw_message(time_usec, port, servo1_raw, servo2_raw, servo3_raw, servo4_raw, servo5_raw, servo6_raw, servo7_raw, servo8_raw) + msg.pack(self) + return msg + + def servo_output_raw_send(self, time_usec, port, servo1_raw, servo2_raw, servo3_raw, servo4_raw, servo5_raw, servo6_raw, servo7_raw, servo8_raw): + ''' + The RAW values of the servo outputs (for RC input from the remote, use + the RC_CHANNELS messages). The standard PPM modulation + is as follows: 1000 microseconds: 0%, 2000 + microseconds: 100%. + + time_usec : Timestamp (since UNIX epoch or microseconds since system boot) (uint32_t) + port : Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos. (uint8_t) + servo1_raw : Servo output 1 value, in microseconds (uint16_t) + servo2_raw : Servo output 2 value, in microseconds (uint16_t) + servo3_raw : Servo output 3 value, in microseconds (uint16_t) + servo4_raw : Servo output 4 value, in microseconds (uint16_t) + servo5_raw : Servo output 5 value, in microseconds (uint16_t) + servo6_raw : Servo output 6 value, in microseconds (uint16_t) + servo7_raw : Servo output 7 value, in microseconds (uint16_t) + servo8_raw : Servo output 8 value, in microseconds (uint16_t) + + ''' + return self.send(self.servo_output_raw_encode(time_usec, port, servo1_raw, servo2_raw, servo3_raw, servo4_raw, servo5_raw, servo6_raw, servo7_raw, servo8_raw)) + + def mission_request_partial_list_encode(self, target_system, target_component, start_index, end_index): + ''' + Request the overall list of MISSIONs from the system/component. + http://qgroundcontrol.org/mavlink/waypoint_protocol + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + start_index : Start index, 0 by default (int16_t) + end_index : End index, -1 by default (-1: send list to end). Else a valid index of the list (int16_t) + + ''' + msg = MAVLink_mission_request_partial_list_message(target_system, target_component, start_index, end_index) + msg.pack(self) + return msg + + def mission_request_partial_list_send(self, target_system, target_component, start_index, end_index): + ''' + Request the overall list of MISSIONs from the system/component. + http://qgroundcontrol.org/mavlink/waypoint_protocol + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + start_index : Start index, 0 by default (int16_t) + end_index : End index, -1 by default (-1: send list to end). Else a valid index of the list (int16_t) + + ''' + return self.send(self.mission_request_partial_list_encode(target_system, target_component, start_index, end_index)) + + def mission_write_partial_list_encode(self, target_system, target_component, start_index, end_index): + ''' + This message is sent to the MAV to write a partial list. If start + index == end index, only one item will be transmitted + / updated. If the start index is NOT 0 and above the + current list size, this request should be REJECTED! + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + start_index : Start index, 0 by default and smaller / equal to the largest index of the current onboard list. (int16_t) + end_index : End index, equal or greater than start index. (int16_t) + + ''' + msg = MAVLink_mission_write_partial_list_message(target_system, target_component, start_index, end_index) + msg.pack(self) + return msg + + def mission_write_partial_list_send(self, target_system, target_component, start_index, end_index): + ''' + This message is sent to the MAV to write a partial list. If start + index == end index, only one item will be transmitted + / updated. If the start index is NOT 0 and above the + current list size, this request should be REJECTED! + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + start_index : Start index, 0 by default and smaller / equal to the largest index of the current onboard list. (int16_t) + end_index : End index, equal or greater than start index. (int16_t) + + ''' + return self.send(self.mission_write_partial_list_encode(target_system, target_component, start_index, end_index)) + + def mission_item_encode(self, target_system, target_component, seq, frame, command, current, autocontinue, param1, param2, param3, param4, x, y, z): + ''' + Message encoding a mission item. This message is emitted to announce + the presence of a mission item and to set a mission + item on the system. The mission item can be either in + x, y, z meters (type: LOCAL) or x:lat, y:lon, + z:altitude. Local frame is Z-down, right handed (NED), + global frame is Z-up, right handed (ENU). + http://qgroundcontrol.org/mavlink/waypoint_protocol + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + seq : Sequence (uint16_t) + frame : The coordinate system of the MISSION. see MAV_FRAME in mavlink_types.h (uint8_t) + command : The scheduled action for the MISSION. see MAV_CMD in common.xml MAVLink specs (uint16_t) + current : false:0, true:1 (uint8_t) + autocontinue : autocontinue to next wp (uint8_t) + param1 : PARAM1 / For NAV command MISSIONs: Radius in which the MISSION is accepted as reached, in meters (float) + param2 : PARAM2 / For NAV command MISSIONs: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds (float) + param3 : PARAM3 / For LOITER command MISSIONs: Orbit to circle around the MISSION, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. (float) + param4 : PARAM4 / For NAV and LOITER command MISSIONs: Yaw orientation in degrees, [0..360] 0 = NORTH (float) + x : PARAM5 / local: x position, global: latitude (float) + y : PARAM6 / y position: global: longitude (float) + z : PARAM7 / z position: global: altitude (float) + + ''' + msg = MAVLink_mission_item_message(target_system, target_component, seq, frame, command, current, autocontinue, param1, param2, param3, param4, x, y, z) + msg.pack(self) + return msg + + def mission_item_send(self, target_system, target_component, seq, frame, command, current, autocontinue, param1, param2, param3, param4, x, y, z): + ''' + Message encoding a mission item. This message is emitted to announce + the presence of a mission item and to set a mission + item on the system. The mission item can be either in + x, y, z meters (type: LOCAL) or x:lat, y:lon, + z:altitude. Local frame is Z-down, right handed (NED), + global frame is Z-up, right handed (ENU). + http://qgroundcontrol.org/mavlink/waypoint_protocol + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + seq : Sequence (uint16_t) + frame : The coordinate system of the MISSION. see MAV_FRAME in mavlink_types.h (uint8_t) + command : The scheduled action for the MISSION. see MAV_CMD in common.xml MAVLink specs (uint16_t) + current : false:0, true:1 (uint8_t) + autocontinue : autocontinue to next wp (uint8_t) + param1 : PARAM1 / For NAV command MISSIONs: Radius in which the MISSION is accepted as reached, in meters (float) + param2 : PARAM2 / For NAV command MISSIONs: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds (float) + param3 : PARAM3 / For LOITER command MISSIONs: Orbit to circle around the MISSION, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise. (float) + param4 : PARAM4 / For NAV and LOITER command MISSIONs: Yaw orientation in degrees, [0..360] 0 = NORTH (float) + x : PARAM5 / local: x position, global: latitude (float) + y : PARAM6 / y position: global: longitude (float) + z : PARAM7 / z position: global: altitude (float) + + ''' + return self.send(self.mission_item_encode(target_system, target_component, seq, frame, command, current, autocontinue, param1, param2, param3, param4, x, y, z)) + + def mission_request_encode(self, target_system, target_component, seq): + ''' + Request the information of the mission item with the sequence number + seq. The response of the system to this message should + be a MISSION_ITEM message. + http://qgroundcontrol.org/mavlink/waypoint_protocol + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + seq : Sequence (uint16_t) + + ''' + msg = MAVLink_mission_request_message(target_system, target_component, seq) + msg.pack(self) + return msg + + def mission_request_send(self, target_system, target_component, seq): + ''' + Request the information of the mission item with the sequence number + seq. The response of the system to this message should + be a MISSION_ITEM message. + http://qgroundcontrol.org/mavlink/waypoint_protocol + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + seq : Sequence (uint16_t) + + ''' + return self.send(self.mission_request_encode(target_system, target_component, seq)) + + def mission_set_current_encode(self, target_system, target_component, seq): + ''' + Set the mission item with sequence number seq as current item. This + means that the MAV will continue to this mission item + on the shortest path (not following the mission items + in-between). + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + seq : Sequence (uint16_t) + + ''' + msg = MAVLink_mission_set_current_message(target_system, target_component, seq) + msg.pack(self) + return msg + + def mission_set_current_send(self, target_system, target_component, seq): + ''' + Set the mission item with sequence number seq as current item. This + means that the MAV will continue to this mission item + on the shortest path (not following the mission items + in-between). + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + seq : Sequence (uint16_t) + + ''' + return self.send(self.mission_set_current_encode(target_system, target_component, seq)) + + def mission_current_encode(self, seq): + ''' + Message that announces the sequence number of the current active + mission item. The MAV will fly towards this mission + item. + + seq : Sequence (uint16_t) + + ''' + msg = MAVLink_mission_current_message(seq) + msg.pack(self) + return msg + + def mission_current_send(self, seq): + ''' + Message that announces the sequence number of the current active + mission item. The MAV will fly towards this mission + item. + + seq : Sequence (uint16_t) + + ''' + return self.send(self.mission_current_encode(seq)) + + def mission_request_list_encode(self, target_system, target_component): + ''' + Request the overall list of mission items from the system/component. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + + ''' + msg = MAVLink_mission_request_list_message(target_system, target_component) + msg.pack(self) + return msg + + def mission_request_list_send(self, target_system, target_component): + ''' + Request the overall list of mission items from the system/component. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + + ''' + return self.send(self.mission_request_list_encode(target_system, target_component)) + + def mission_count_encode(self, target_system, target_component, count): + ''' + This message is emitted as response to MISSION_REQUEST_LIST by the MAV + and to initiate a write transaction. The GCS can then + request the individual mission item based on the + knowledge of the total number of MISSIONs. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + count : Number of mission items in the sequence (uint16_t) + + ''' + msg = MAVLink_mission_count_message(target_system, target_component, count) + msg.pack(self) + return msg + + def mission_count_send(self, target_system, target_component, count): + ''' + This message is emitted as response to MISSION_REQUEST_LIST by the MAV + and to initiate a write transaction. The GCS can then + request the individual mission item based on the + knowledge of the total number of MISSIONs. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + count : Number of mission items in the sequence (uint16_t) + + ''' + return self.send(self.mission_count_encode(target_system, target_component, count)) + + def mission_clear_all_encode(self, target_system, target_component): + ''' + Delete all mission items at once. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + + ''' + msg = MAVLink_mission_clear_all_message(target_system, target_component) + msg.pack(self) + return msg + + def mission_clear_all_send(self, target_system, target_component): + ''' + Delete all mission items at once. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + + ''' + return self.send(self.mission_clear_all_encode(target_system, target_component)) + + def mission_item_reached_encode(self, seq): + ''' + A certain mission item has been reached. The system will either hold + this position (or circle on the orbit) or (if the + autocontinue on the WP was set) continue to the next + MISSION. + + seq : Sequence (uint16_t) + + ''' + msg = MAVLink_mission_item_reached_message(seq) + msg.pack(self) + return msg + + def mission_item_reached_send(self, seq): + ''' + A certain mission item has been reached. The system will either hold + this position (or circle on the orbit) or (if the + autocontinue on the WP was set) continue to the next + MISSION. + + seq : Sequence (uint16_t) + + ''' + return self.send(self.mission_item_reached_encode(seq)) + + def mission_ack_encode(self, target_system, target_component, type): + ''' + Ack message during MISSION handling. The type field states if this + message is a positive ack (type=0) or if an error + happened (type=non-zero). + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + type : See MAV_MISSION_RESULT enum (uint8_t) + + ''' + msg = MAVLink_mission_ack_message(target_system, target_component, type) + msg.pack(self) + return msg + + def mission_ack_send(self, target_system, target_component, type): + ''' + Ack message during MISSION handling. The type field states if this + message is a positive ack (type=0) or if an error + happened (type=non-zero). + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + type : See MAV_MISSION_RESULT enum (uint8_t) + + ''' + return self.send(self.mission_ack_encode(target_system, target_component, type)) + + def set_gps_global_origin_encode(self, target_system, latitude, longitude, altitude): + ''' + As local MISSIONs exist, the global MISSION reference allows to + transform between the local coordinate frame and the + global (GPS) coordinate frame. This can be necessary + when e.g. in- and outdoor settings are connected and + the MAV should move from in- to outdoor. + + target_system : System ID (uint8_t) + latitude : global position * 1E7 (int32_t) + longitude : global position * 1E7 (int32_t) + altitude : global position * 1000 (int32_t) + + ''' + msg = MAVLink_set_gps_global_origin_message(target_system, latitude, longitude, altitude) + msg.pack(self) + return msg + + def set_gps_global_origin_send(self, target_system, latitude, longitude, altitude): + ''' + As local MISSIONs exist, the global MISSION reference allows to + transform between the local coordinate frame and the + global (GPS) coordinate frame. This can be necessary + when e.g. in- and outdoor settings are connected and + the MAV should move from in- to outdoor. + + target_system : System ID (uint8_t) + latitude : global position * 1E7 (int32_t) + longitude : global position * 1E7 (int32_t) + altitude : global position * 1000 (int32_t) + + ''' + return self.send(self.set_gps_global_origin_encode(target_system, latitude, longitude, altitude)) + + def gps_global_origin_encode(self, latitude, longitude, altitude): + ''' + Once the MAV sets a new GPS-Local correspondence, this message + announces the origin (0,0,0) position + + latitude : Latitude (WGS84), expressed as * 1E7 (int32_t) + longitude : Longitude (WGS84), expressed as * 1E7 (int32_t) + altitude : Altitude(WGS84), expressed as * 1000 (int32_t) + + ''' + msg = MAVLink_gps_global_origin_message(latitude, longitude, altitude) + msg.pack(self) + return msg + + def gps_global_origin_send(self, latitude, longitude, altitude): + ''' + Once the MAV sets a new GPS-Local correspondence, this message + announces the origin (0,0,0) position + + latitude : Latitude (WGS84), expressed as * 1E7 (int32_t) + longitude : Longitude (WGS84), expressed as * 1E7 (int32_t) + altitude : Altitude(WGS84), expressed as * 1000 (int32_t) + + ''' + return self.send(self.gps_global_origin_encode(latitude, longitude, altitude)) + + def set_local_position_setpoint_encode(self, target_system, target_component, coordinate_frame, x, y, z, yaw): + ''' + Set the setpoint for a local position controller. This is the position + in local coordinates the MAV should fly to. This + message is sent by the path/MISSION planner to the + onboard position controller. As some MAVs have a + degree of freedom in yaw (e.g. all + helicopters/quadrotors), the desired yaw angle is part + of the message. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + coordinate_frame : Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU (uint8_t) + x : x position (float) + y : y position (float) + z : z position (float) + yaw : Desired yaw angle (float) + + ''' + msg = MAVLink_set_local_position_setpoint_message(target_system, target_component, coordinate_frame, x, y, z, yaw) + msg.pack(self) + return msg + + def set_local_position_setpoint_send(self, target_system, target_component, coordinate_frame, x, y, z, yaw): + ''' + Set the setpoint for a local position controller. This is the position + in local coordinates the MAV should fly to. This + message is sent by the path/MISSION planner to the + onboard position controller. As some MAVs have a + degree of freedom in yaw (e.g. all + helicopters/quadrotors), the desired yaw angle is part + of the message. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + coordinate_frame : Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU (uint8_t) + x : x position (float) + y : y position (float) + z : z position (float) + yaw : Desired yaw angle (float) + + ''' + return self.send(self.set_local_position_setpoint_encode(target_system, target_component, coordinate_frame, x, y, z, yaw)) + + def local_position_setpoint_encode(self, coordinate_frame, x, y, z, yaw): + ''' + Transmit the current local setpoint of the controller to other MAVs + (collision avoidance) and to the GCS. + + coordinate_frame : Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU (uint8_t) + x : x position (float) + y : y position (float) + z : z position (float) + yaw : Desired yaw angle (float) + + ''' + msg = MAVLink_local_position_setpoint_message(coordinate_frame, x, y, z, yaw) + msg.pack(self) + return msg + + def local_position_setpoint_send(self, coordinate_frame, x, y, z, yaw): + ''' + Transmit the current local setpoint of the controller to other MAVs + (collision avoidance) and to the GCS. + + coordinate_frame : Coordinate frame - valid values are only MAV_FRAME_LOCAL_NED or MAV_FRAME_LOCAL_ENU (uint8_t) + x : x position (float) + y : y position (float) + z : z position (float) + yaw : Desired yaw angle (float) + + ''' + return self.send(self.local_position_setpoint_encode(coordinate_frame, x, y, z, yaw)) + + def global_position_setpoint_int_encode(self, coordinate_frame, latitude, longitude, altitude, yaw): + ''' + Transmit the current local setpoint of the controller to other MAVs + (collision avoidance) and to the GCS. + + coordinate_frame : Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT (uint8_t) + latitude : WGS84 Latitude position in degrees * 1E7 (int32_t) + longitude : WGS84 Longitude position in degrees * 1E7 (int32_t) + altitude : WGS84 Altitude in meters * 1000 (positive for up) (int32_t) + yaw : Desired yaw angle in degrees * 100 (int16_t) + + ''' + msg = MAVLink_global_position_setpoint_int_message(coordinate_frame, latitude, longitude, altitude, yaw) + msg.pack(self) + return msg + + def global_position_setpoint_int_send(self, coordinate_frame, latitude, longitude, altitude, yaw): + ''' + Transmit the current local setpoint of the controller to other MAVs + (collision avoidance) and to the GCS. + + coordinate_frame : Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT (uint8_t) + latitude : WGS84 Latitude position in degrees * 1E7 (int32_t) + longitude : WGS84 Longitude position in degrees * 1E7 (int32_t) + altitude : WGS84 Altitude in meters * 1000 (positive for up) (int32_t) + yaw : Desired yaw angle in degrees * 100 (int16_t) + + ''' + return self.send(self.global_position_setpoint_int_encode(coordinate_frame, latitude, longitude, altitude, yaw)) + + def set_global_position_setpoint_int_encode(self, coordinate_frame, latitude, longitude, altitude, yaw): + ''' + Set the current global position setpoint. + + coordinate_frame : Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT (uint8_t) + latitude : WGS84 Latitude position in degrees * 1E7 (int32_t) + longitude : WGS84 Longitude position in degrees * 1E7 (int32_t) + altitude : WGS84 Altitude in meters * 1000 (positive for up) (int32_t) + yaw : Desired yaw angle in degrees * 100 (int16_t) + + ''' + msg = MAVLink_set_global_position_setpoint_int_message(coordinate_frame, latitude, longitude, altitude, yaw) + msg.pack(self) + return msg + + def set_global_position_setpoint_int_send(self, coordinate_frame, latitude, longitude, altitude, yaw): + ''' + Set the current global position setpoint. + + coordinate_frame : Coordinate frame - valid values are only MAV_FRAME_GLOBAL or MAV_FRAME_GLOBAL_RELATIVE_ALT (uint8_t) + latitude : WGS84 Latitude position in degrees * 1E7 (int32_t) + longitude : WGS84 Longitude position in degrees * 1E7 (int32_t) + altitude : WGS84 Altitude in meters * 1000 (positive for up) (int32_t) + yaw : Desired yaw angle in degrees * 100 (int16_t) + + ''' + return self.send(self.set_global_position_setpoint_int_encode(coordinate_frame, latitude, longitude, altitude, yaw)) + + def safety_set_allowed_area_encode(self, target_system, target_component, frame, p1x, p1y, p1z, p2x, p2y, p2z): + ''' + Set a safety zone (volume), which is defined by two corners of a cube. + This message can be used to tell the MAV which + setpoints/MISSIONs to accept and which to reject. + Safety areas are often enforced by national or + competition regulations. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + frame : Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. (uint8_t) + p1x : x position 1 / Latitude 1 (float) + p1y : y position 1 / Longitude 1 (float) + p1z : z position 1 / Altitude 1 (float) + p2x : x position 2 / Latitude 2 (float) + p2y : y position 2 / Longitude 2 (float) + p2z : z position 2 / Altitude 2 (float) + + ''' + msg = MAVLink_safety_set_allowed_area_message(target_system, target_component, frame, p1x, p1y, p1z, p2x, p2y, p2z) + msg.pack(self) + return msg + + def safety_set_allowed_area_send(self, target_system, target_component, frame, p1x, p1y, p1z, p2x, p2y, p2z): + ''' + Set a safety zone (volume), which is defined by two corners of a cube. + This message can be used to tell the MAV which + setpoints/MISSIONs to accept and which to reject. + Safety areas are often enforced by national or + competition regulations. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + frame : Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. (uint8_t) + p1x : x position 1 / Latitude 1 (float) + p1y : y position 1 / Longitude 1 (float) + p1z : z position 1 / Altitude 1 (float) + p2x : x position 2 / Latitude 2 (float) + p2y : y position 2 / Longitude 2 (float) + p2z : z position 2 / Altitude 2 (float) + + ''' + return self.send(self.safety_set_allowed_area_encode(target_system, target_component, frame, p1x, p1y, p1z, p2x, p2y, p2z)) + + def safety_allowed_area_encode(self, frame, p1x, p1y, p1z, p2x, p2y, p2z): + ''' + Read out the safety zone the MAV currently assumes. + + frame : Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. (uint8_t) + p1x : x position 1 / Latitude 1 (float) + p1y : y position 1 / Longitude 1 (float) + p1z : z position 1 / Altitude 1 (float) + p2x : x position 2 / Latitude 2 (float) + p2y : y position 2 / Longitude 2 (float) + p2z : z position 2 / Altitude 2 (float) + + ''' + msg = MAVLink_safety_allowed_area_message(frame, p1x, p1y, p1z, p2x, p2y, p2z) + msg.pack(self) + return msg + + def safety_allowed_area_send(self, frame, p1x, p1y, p1z, p2x, p2y, p2z): + ''' + Read out the safety zone the MAV currently assumes. + + frame : Coordinate frame, as defined by MAV_FRAME enum in mavlink_types.h. Can be either global, GPS, right-handed with Z axis up or local, right handed, Z axis down. (uint8_t) + p1x : x position 1 / Latitude 1 (float) + p1y : y position 1 / Longitude 1 (float) + p1z : z position 1 / Altitude 1 (float) + p2x : x position 2 / Latitude 2 (float) + p2y : y position 2 / Longitude 2 (float) + p2z : z position 2 / Altitude 2 (float) + + ''' + return self.send(self.safety_allowed_area_encode(frame, p1x, p1y, p1z, p2x, p2y, p2z)) + + def set_roll_pitch_yaw_thrust_encode(self, target_system, target_component, roll, pitch, yaw, thrust): + ''' + Set roll, pitch and yaw. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + roll : Desired roll angle in radians (float) + pitch : Desired pitch angle in radians (float) + yaw : Desired yaw angle in radians (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + msg = MAVLink_set_roll_pitch_yaw_thrust_message(target_system, target_component, roll, pitch, yaw, thrust) + msg.pack(self) + return msg + + def set_roll_pitch_yaw_thrust_send(self, target_system, target_component, roll, pitch, yaw, thrust): + ''' + Set roll, pitch and yaw. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + roll : Desired roll angle in radians (float) + pitch : Desired pitch angle in radians (float) + yaw : Desired yaw angle in radians (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + return self.send(self.set_roll_pitch_yaw_thrust_encode(target_system, target_component, roll, pitch, yaw, thrust)) + + def set_roll_pitch_yaw_speed_thrust_encode(self, target_system, target_component, roll_speed, pitch_speed, yaw_speed, thrust): + ''' + Set roll, pitch and yaw. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + roll_speed : Desired roll angular speed in rad/s (float) + pitch_speed : Desired pitch angular speed in rad/s (float) + yaw_speed : Desired yaw angular speed in rad/s (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + msg = MAVLink_set_roll_pitch_yaw_speed_thrust_message(target_system, target_component, roll_speed, pitch_speed, yaw_speed, thrust) + msg.pack(self) + return msg + + def set_roll_pitch_yaw_speed_thrust_send(self, target_system, target_component, roll_speed, pitch_speed, yaw_speed, thrust): + ''' + Set roll, pitch and yaw. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + roll_speed : Desired roll angular speed in rad/s (float) + pitch_speed : Desired pitch angular speed in rad/s (float) + yaw_speed : Desired yaw angular speed in rad/s (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + return self.send(self.set_roll_pitch_yaw_speed_thrust_encode(target_system, target_component, roll_speed, pitch_speed, yaw_speed, thrust)) + + def roll_pitch_yaw_thrust_setpoint_encode(self, time_boot_ms, roll, pitch, yaw, thrust): + ''' + Setpoint in roll, pitch, yaw currently active on the system. + + time_boot_ms : Timestamp in milliseconds since system boot (uint32_t) + roll : Desired roll angle in radians (float) + pitch : Desired pitch angle in radians (float) + yaw : Desired yaw angle in radians (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + msg = MAVLink_roll_pitch_yaw_thrust_setpoint_message(time_boot_ms, roll, pitch, yaw, thrust) + msg.pack(self) + return msg + + def roll_pitch_yaw_thrust_setpoint_send(self, time_boot_ms, roll, pitch, yaw, thrust): + ''' + Setpoint in roll, pitch, yaw currently active on the system. + + time_boot_ms : Timestamp in milliseconds since system boot (uint32_t) + roll : Desired roll angle in radians (float) + pitch : Desired pitch angle in radians (float) + yaw : Desired yaw angle in radians (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + return self.send(self.roll_pitch_yaw_thrust_setpoint_encode(time_boot_ms, roll, pitch, yaw, thrust)) + + def roll_pitch_yaw_speed_thrust_setpoint_encode(self, time_boot_ms, roll_speed, pitch_speed, yaw_speed, thrust): + ''' + Setpoint in rollspeed, pitchspeed, yawspeed currently active on the + system. + + time_boot_ms : Timestamp in milliseconds since system boot (uint32_t) + roll_speed : Desired roll angular speed in rad/s (float) + pitch_speed : Desired pitch angular speed in rad/s (float) + yaw_speed : Desired yaw angular speed in rad/s (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + msg = MAVLink_roll_pitch_yaw_speed_thrust_setpoint_message(time_boot_ms, roll_speed, pitch_speed, yaw_speed, thrust) + msg.pack(self) + return msg + + def roll_pitch_yaw_speed_thrust_setpoint_send(self, time_boot_ms, roll_speed, pitch_speed, yaw_speed, thrust): + ''' + Setpoint in rollspeed, pitchspeed, yawspeed currently active on the + system. + + time_boot_ms : Timestamp in milliseconds since system boot (uint32_t) + roll_speed : Desired roll angular speed in rad/s (float) + pitch_speed : Desired pitch angular speed in rad/s (float) + yaw_speed : Desired yaw angular speed in rad/s (float) + thrust : Collective thrust, normalized to 0 .. 1 (float) + + ''' + return self.send(self.roll_pitch_yaw_speed_thrust_setpoint_encode(time_boot_ms, roll_speed, pitch_speed, yaw_speed, thrust)) + + def nav_controller_output_encode(self, nav_roll, nav_pitch, nav_bearing, target_bearing, wp_dist, alt_error, aspd_error, xtrack_error): + ''' + Outputs of the APM navigation controller. The primary use of this + message is to check the response and signs + of the controller before actual flight and to assist + with tuning controller parameters + + nav_roll : Current desired roll in degrees (float) + nav_pitch : Current desired pitch in degrees (float) + nav_bearing : Current desired heading in degrees (int16_t) + target_bearing : Bearing to current MISSION/target in degrees (int16_t) + wp_dist : Distance to active MISSION in meters (uint16_t) + alt_error : Current altitude error in meters (float) + aspd_error : Current airspeed error in meters/second (float) + xtrack_error : Current crosstrack error on x-y plane in meters (float) + + ''' + msg = MAVLink_nav_controller_output_message(nav_roll, nav_pitch, nav_bearing, target_bearing, wp_dist, alt_error, aspd_error, xtrack_error) + msg.pack(self) + return msg + + def nav_controller_output_send(self, nav_roll, nav_pitch, nav_bearing, target_bearing, wp_dist, alt_error, aspd_error, xtrack_error): + ''' + Outputs of the APM navigation controller. The primary use of this + message is to check the response and signs + of the controller before actual flight and to assist + with tuning controller parameters + + nav_roll : Current desired roll in degrees (float) + nav_pitch : Current desired pitch in degrees (float) + nav_bearing : Current desired heading in degrees (int16_t) + target_bearing : Bearing to current MISSION/target in degrees (int16_t) + wp_dist : Distance to active MISSION in meters (uint16_t) + alt_error : Current altitude error in meters (float) + aspd_error : Current airspeed error in meters/second (float) + xtrack_error : Current crosstrack error on x-y plane in meters (float) + + ''' + return self.send(self.nav_controller_output_encode(nav_roll, nav_pitch, nav_bearing, target_bearing, wp_dist, alt_error, aspd_error, xtrack_error)) + + def state_correction_encode(self, xErr, yErr, zErr, rollErr, pitchErr, yawErr, vxErr, vyErr, vzErr): + ''' + Corrects the systems state by adding an error correction term to the + position and velocity, and by rotating the attitude by + a correction angle. + + xErr : x position error (float) + yErr : y position error (float) + zErr : z position error (float) + rollErr : roll error (radians) (float) + pitchErr : pitch error (radians) (float) + yawErr : yaw error (radians) (float) + vxErr : x velocity (float) + vyErr : y velocity (float) + vzErr : z velocity (float) + + ''' + msg = MAVLink_state_correction_message(xErr, yErr, zErr, rollErr, pitchErr, yawErr, vxErr, vyErr, vzErr) + msg.pack(self) + return msg + + def state_correction_send(self, xErr, yErr, zErr, rollErr, pitchErr, yawErr, vxErr, vyErr, vzErr): + ''' + Corrects the systems state by adding an error correction term to the + position and velocity, and by rotating the attitude by + a correction angle. + + xErr : x position error (float) + yErr : y position error (float) + zErr : z position error (float) + rollErr : roll error (radians) (float) + pitchErr : pitch error (radians) (float) + yawErr : yaw error (radians) (float) + vxErr : x velocity (float) + vyErr : y velocity (float) + vzErr : z velocity (float) + + ''' + return self.send(self.state_correction_encode(xErr, yErr, zErr, rollErr, pitchErr, yawErr, vxErr, vyErr, vzErr)) + + def request_data_stream_encode(self, target_system, target_component, req_stream_id, req_message_rate, start_stop): + ''' + + + target_system : The target requested to send the message stream. (uint8_t) + target_component : The target requested to send the message stream. (uint8_t) + req_stream_id : The ID of the requested data stream (uint8_t) + req_message_rate : The requested interval between two messages of this type (uint16_t) + start_stop : 1 to start sending, 0 to stop sending. (uint8_t) + + ''' + msg = MAVLink_request_data_stream_message(target_system, target_component, req_stream_id, req_message_rate, start_stop) + msg.pack(self) + return msg + + def request_data_stream_send(self, target_system, target_component, req_stream_id, req_message_rate, start_stop): + ''' + + + target_system : The target requested to send the message stream. (uint8_t) + target_component : The target requested to send the message stream. (uint8_t) + req_stream_id : The ID of the requested data stream (uint8_t) + req_message_rate : The requested interval between two messages of this type (uint16_t) + start_stop : 1 to start sending, 0 to stop sending. (uint8_t) + + ''' + return self.send(self.request_data_stream_encode(target_system, target_component, req_stream_id, req_message_rate, start_stop)) + + def data_stream_encode(self, stream_id, message_rate, on_off): + ''' + + + stream_id : The ID of the requested data stream (uint8_t) + message_rate : The requested interval between two messages of this type (uint16_t) + on_off : 1 stream is enabled, 0 stream is stopped. (uint8_t) + + ''' + msg = MAVLink_data_stream_message(stream_id, message_rate, on_off) + msg.pack(self) + return msg + + def data_stream_send(self, stream_id, message_rate, on_off): + ''' + + + stream_id : The ID of the requested data stream (uint8_t) + message_rate : The requested interval between two messages of this type (uint16_t) + on_off : 1 stream is enabled, 0 stream is stopped. (uint8_t) + + ''' + return self.send(self.data_stream_encode(stream_id, message_rate, on_off)) + + def manual_control_encode(self, target, roll, pitch, yaw, thrust, roll_manual, pitch_manual, yaw_manual, thrust_manual): + ''' + + + target : The system to be controlled (uint8_t) + roll : roll (float) + pitch : pitch (float) + yaw : yaw (float) + thrust : thrust (float) + roll_manual : roll control enabled auto:0, manual:1 (uint8_t) + pitch_manual : pitch auto:0, manual:1 (uint8_t) + yaw_manual : yaw auto:0, manual:1 (uint8_t) + thrust_manual : thrust auto:0, manual:1 (uint8_t) + + ''' + msg = MAVLink_manual_control_message(target, roll, pitch, yaw, thrust, roll_manual, pitch_manual, yaw_manual, thrust_manual) + msg.pack(self) + return msg + + def manual_control_send(self, target, roll, pitch, yaw, thrust, roll_manual, pitch_manual, yaw_manual, thrust_manual): + ''' + + + target : The system to be controlled (uint8_t) + roll : roll (float) + pitch : pitch (float) + yaw : yaw (float) + thrust : thrust (float) + roll_manual : roll control enabled auto:0, manual:1 (uint8_t) + pitch_manual : pitch auto:0, manual:1 (uint8_t) + yaw_manual : yaw auto:0, manual:1 (uint8_t) + thrust_manual : thrust auto:0, manual:1 (uint8_t) + + ''' + return self.send(self.manual_control_encode(target, roll, pitch, yaw, thrust, roll_manual, pitch_manual, yaw_manual, thrust_manual)) + + def rc_channels_override_encode(self, target_system, target_component, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw): + ''' + The RAW values of the RC channels sent to the MAV to override info + received from the RC radio. A value of -1 means no + change to that channel. A value of 0 means control of + that channel should be released back to the RC radio. + The standard PPM modulation is as follows: 1000 + microseconds: 0%, 2000 microseconds: 100%. Individual + receivers/transmitters might violate this + specification. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + chan1_raw : RC channel 1 value, in microseconds (uint16_t) + chan2_raw : RC channel 2 value, in microseconds (uint16_t) + chan3_raw : RC channel 3 value, in microseconds (uint16_t) + chan4_raw : RC channel 4 value, in microseconds (uint16_t) + chan5_raw : RC channel 5 value, in microseconds (uint16_t) + chan6_raw : RC channel 6 value, in microseconds (uint16_t) + chan7_raw : RC channel 7 value, in microseconds (uint16_t) + chan8_raw : RC channel 8 value, in microseconds (uint16_t) + + ''' + msg = MAVLink_rc_channels_override_message(target_system, target_component, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw) + msg.pack(self) + return msg + + def rc_channels_override_send(self, target_system, target_component, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw): + ''' + The RAW values of the RC channels sent to the MAV to override info + received from the RC radio. A value of -1 means no + change to that channel. A value of 0 means control of + that channel should be released back to the RC radio. + The standard PPM modulation is as follows: 1000 + microseconds: 0%, 2000 microseconds: 100%. Individual + receivers/transmitters might violate this + specification. + + target_system : System ID (uint8_t) + target_component : Component ID (uint8_t) + chan1_raw : RC channel 1 value, in microseconds (uint16_t) + chan2_raw : RC channel 2 value, in microseconds (uint16_t) + chan3_raw : RC channel 3 value, in microseconds (uint16_t) + chan4_raw : RC channel 4 value, in microseconds (uint16_t) + chan5_raw : RC channel 5 value, in microseconds (uint16_t) + chan6_raw : RC channel 6 value, in microseconds (uint16_t) + chan7_raw : RC channel 7 value, in microseconds (uint16_t) + chan8_raw : RC channel 8 value, in microseconds (uint16_t) + + ''' + return self.send(self.rc_channels_override_encode(target_system, target_component, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw)) + + def vfr_hud_encode(self, airspeed, groundspeed, heading, throttle, alt, climb): + ''' + Metrics typically displayed on a HUD for fixed wing aircraft + + airspeed : Current airspeed in m/s (float) + groundspeed : Current ground speed in m/s (float) + heading : Current heading in degrees, in compass units (0..360, 0=north) (int16_t) + throttle : Current throttle setting in integer percent, 0 to 100 (uint16_t) + alt : Current altitude (MSL), in meters (float) + climb : Current climb rate in meters/second (float) + + ''' + msg = MAVLink_vfr_hud_message(airspeed, groundspeed, heading, throttle, alt, climb) + msg.pack(self) + return msg + + def vfr_hud_send(self, airspeed, groundspeed, heading, throttle, alt, climb): + ''' + Metrics typically displayed on a HUD for fixed wing aircraft + + airspeed : Current airspeed in m/s (float) + groundspeed : Current ground speed in m/s (float) + heading : Current heading in degrees, in compass units (0..360, 0=north) (int16_t) + throttle : Current throttle setting in integer percent, 0 to 100 (uint16_t) + alt : Current altitude (MSL), in meters (float) + climb : Current climb rate in meters/second (float) + + ''' + return self.send(self.vfr_hud_encode(airspeed, groundspeed, heading, throttle, alt, climb)) + + def command_long_encode(self, target_system, target_component, command, confirmation, param1, param2, param3, param4, param5, param6, param7): + ''' + Send a command with up to four parameters to the MAV + + target_system : System which should execute the command (uint8_t) + target_component : Component which should execute the command, 0 for all components (uint8_t) + command : Command ID, as defined by MAV_CMD enum. (uint16_t) + confirmation : 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) (uint8_t) + param1 : Parameter 1, as defined by MAV_CMD enum. (float) + param2 : Parameter 2, as defined by MAV_CMD enum. (float) + param3 : Parameter 3, as defined by MAV_CMD enum. (float) + param4 : Parameter 4, as defined by MAV_CMD enum. (float) + param5 : Parameter 5, as defined by MAV_CMD enum. (float) + param6 : Parameter 6, as defined by MAV_CMD enum. (float) + param7 : Parameter 7, as defined by MAV_CMD enum. (float) + + ''' + msg = MAVLink_command_long_message(target_system, target_component, command, confirmation, param1, param2, param3, param4, param5, param6, param7) + msg.pack(self) + return msg + + def command_long_send(self, target_system, target_component, command, confirmation, param1, param2, param3, param4, param5, param6, param7): + ''' + Send a command with up to four parameters to the MAV + + target_system : System which should execute the command (uint8_t) + target_component : Component which should execute the command, 0 for all components (uint8_t) + command : Command ID, as defined by MAV_CMD enum. (uint16_t) + confirmation : 0: First transmission of this command. 1-255: Confirmation transmissions (e.g. for kill command) (uint8_t) + param1 : Parameter 1, as defined by MAV_CMD enum. (float) + param2 : Parameter 2, as defined by MAV_CMD enum. (float) + param3 : Parameter 3, as defined by MAV_CMD enum. (float) + param4 : Parameter 4, as defined by MAV_CMD enum. (float) + param5 : Parameter 5, as defined by MAV_CMD enum. (float) + param6 : Parameter 6, as defined by MAV_CMD enum. (float) + param7 : Parameter 7, as defined by MAV_CMD enum. (float) + + ''' + return self.send(self.command_long_encode(target_system, target_component, command, confirmation, param1, param2, param3, param4, param5, param6, param7)) + + def command_ack_encode(self, command, result): + ''' + Report status of a command. Includes feedback wether the command was + executed + + command : Command ID, as defined by MAV_CMD enum. (uint16_t) + result : See MAV_RESULT enum (uint8_t) + + ''' + msg = MAVLink_command_ack_message(command, result) + msg.pack(self) + return msg + + def command_ack_send(self, command, result): + ''' + Report status of a command. Includes feedback wether the command was + executed + + command : Command ID, as defined by MAV_CMD enum. (uint16_t) + result : See MAV_RESULT enum (uint8_t) + + ''' + return self.send(self.command_ack_encode(command, result)) + + def hil_state_encode(self, time_usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed, lat, lon, alt, vx, vy, vz, xacc, yacc, zacc): + ''' + Sent from simulation to autopilot. This packet is useful for high + throughput applications such as + hardware in the loop simulations. + + time_usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + roll : Roll angle (rad) (float) + pitch : Pitch angle (rad) (float) + yaw : Yaw angle (rad) (float) + rollspeed : Roll angular speed (rad/s) (float) + pitchspeed : Pitch angular speed (rad/s) (float) + yawspeed : Yaw angular speed (rad/s) (float) + lat : Latitude, expressed as * 1E7 (int32_t) + lon : Longitude, expressed as * 1E7 (int32_t) + alt : Altitude in meters, expressed as * 1000 (millimeters) (int32_t) + vx : Ground X Speed (Latitude), expressed as m/s * 100 (int16_t) + vy : Ground Y Speed (Longitude), expressed as m/s * 100 (int16_t) + vz : Ground Z Speed (Altitude), expressed as m/s * 100 (int16_t) + xacc : X acceleration (mg) (int16_t) + yacc : Y acceleration (mg) (int16_t) + zacc : Z acceleration (mg) (int16_t) + + ''' + msg = MAVLink_hil_state_message(time_usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed, lat, lon, alt, vx, vy, vz, xacc, yacc, zacc) + msg.pack(self) + return msg + + def hil_state_send(self, time_usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed, lat, lon, alt, vx, vy, vz, xacc, yacc, zacc): + ''' + Sent from simulation to autopilot. This packet is useful for high + throughput applications such as + hardware in the loop simulations. + + time_usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + roll : Roll angle (rad) (float) + pitch : Pitch angle (rad) (float) + yaw : Yaw angle (rad) (float) + rollspeed : Roll angular speed (rad/s) (float) + pitchspeed : Pitch angular speed (rad/s) (float) + yawspeed : Yaw angular speed (rad/s) (float) + lat : Latitude, expressed as * 1E7 (int32_t) + lon : Longitude, expressed as * 1E7 (int32_t) + alt : Altitude in meters, expressed as * 1000 (millimeters) (int32_t) + vx : Ground X Speed (Latitude), expressed as m/s * 100 (int16_t) + vy : Ground Y Speed (Longitude), expressed as m/s * 100 (int16_t) + vz : Ground Z Speed (Altitude), expressed as m/s * 100 (int16_t) + xacc : X acceleration (mg) (int16_t) + yacc : Y acceleration (mg) (int16_t) + zacc : Z acceleration (mg) (int16_t) + + ''' + return self.send(self.hil_state_encode(time_usec, roll, pitch, yaw, rollspeed, pitchspeed, yawspeed, lat, lon, alt, vx, vy, vz, xacc, yacc, zacc)) + + def hil_controls_encode(self, time_usec, roll_ailerons, pitch_elevator, yaw_rudder, throttle, aux1, aux2, aux3, aux4, mode, nav_mode): + ''' + Sent from autopilot to simulation. Hardware in the loop control + outputs + + time_usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + roll_ailerons : Control output -1 .. 1 (float) + pitch_elevator : Control output -1 .. 1 (float) + yaw_rudder : Control output -1 .. 1 (float) + throttle : Throttle 0 .. 1 (float) + aux1 : Aux 1, -1 .. 1 (float) + aux2 : Aux 2, -1 .. 1 (float) + aux3 : Aux 3, -1 .. 1 (float) + aux4 : Aux 4, -1 .. 1 (float) + mode : System mode (MAV_MODE) (uint8_t) + nav_mode : Navigation mode (MAV_NAV_MODE) (uint8_t) + + ''' + msg = MAVLink_hil_controls_message(time_usec, roll_ailerons, pitch_elevator, yaw_rudder, throttle, aux1, aux2, aux3, aux4, mode, nav_mode) + msg.pack(self) + return msg + + def hil_controls_send(self, time_usec, roll_ailerons, pitch_elevator, yaw_rudder, throttle, aux1, aux2, aux3, aux4, mode, nav_mode): + ''' + Sent from autopilot to simulation. Hardware in the loop control + outputs + + time_usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + roll_ailerons : Control output -1 .. 1 (float) + pitch_elevator : Control output -1 .. 1 (float) + yaw_rudder : Control output -1 .. 1 (float) + throttle : Throttle 0 .. 1 (float) + aux1 : Aux 1, -1 .. 1 (float) + aux2 : Aux 2, -1 .. 1 (float) + aux3 : Aux 3, -1 .. 1 (float) + aux4 : Aux 4, -1 .. 1 (float) + mode : System mode (MAV_MODE) (uint8_t) + nav_mode : Navigation mode (MAV_NAV_MODE) (uint8_t) + + ''' + return self.send(self.hil_controls_encode(time_usec, roll_ailerons, pitch_elevator, yaw_rudder, throttle, aux1, aux2, aux3, aux4, mode, nav_mode)) + + def hil_rc_inputs_raw_encode(self, time_usec, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw, chan9_raw, chan10_raw, chan11_raw, chan12_raw, rssi): + ''' + Sent from simulation to autopilot. The RAW values of the RC channels + received. The standard PPM modulation is as follows: + 1000 microseconds: 0%, 2000 microseconds: 100%. + Individual receivers/transmitters might violate this + specification. + + time_usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + chan1_raw : RC channel 1 value, in microseconds (uint16_t) + chan2_raw : RC channel 2 value, in microseconds (uint16_t) + chan3_raw : RC channel 3 value, in microseconds (uint16_t) + chan4_raw : RC channel 4 value, in microseconds (uint16_t) + chan5_raw : RC channel 5 value, in microseconds (uint16_t) + chan6_raw : RC channel 6 value, in microseconds (uint16_t) + chan7_raw : RC channel 7 value, in microseconds (uint16_t) + chan8_raw : RC channel 8 value, in microseconds (uint16_t) + chan9_raw : RC channel 9 value, in microseconds (uint16_t) + chan10_raw : RC channel 10 value, in microseconds (uint16_t) + chan11_raw : RC channel 11 value, in microseconds (uint16_t) + chan12_raw : RC channel 12 value, in microseconds (uint16_t) + rssi : Receive signal strength indicator, 0: 0%, 255: 100% (uint8_t) + + ''' + msg = MAVLink_hil_rc_inputs_raw_message(time_usec, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw, chan9_raw, chan10_raw, chan11_raw, chan12_raw, rssi) + msg.pack(self) + return msg + + def hil_rc_inputs_raw_send(self, time_usec, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw, chan9_raw, chan10_raw, chan11_raw, chan12_raw, rssi): + ''' + Sent from simulation to autopilot. The RAW values of the RC channels + received. The standard PPM modulation is as follows: + 1000 microseconds: 0%, 2000 microseconds: 100%. + Individual receivers/transmitters might violate this + specification. + + time_usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t) + chan1_raw : RC channel 1 value, in microseconds (uint16_t) + chan2_raw : RC channel 2 value, in microseconds (uint16_t) + chan3_raw : RC channel 3 value, in microseconds (uint16_t) + chan4_raw : RC channel 4 value, in microseconds (uint16_t) + chan5_raw : RC channel 5 value, in microseconds (uint16_t) + chan6_raw : RC channel 6 value, in microseconds (uint16_t) + chan7_raw : RC channel 7 value, in microseconds (uint16_t) + chan8_raw : RC channel 8 value, in microseconds (uint16_t) + chan9_raw : RC channel 9 value, in microseconds (uint16_t) + chan10_raw : RC channel 10 value, in microseconds (uint16_t) + chan11_raw : RC channel 11 value, in microseconds (uint16_t) + chan12_raw : RC channel 12 value, in microseconds (uint16_t) + rssi : Receive signal strength indicator, 0: 0%, 255: 100% (uint8_t) + + ''' + return self.send(self.hil_rc_inputs_raw_encode(time_usec, chan1_raw, chan2_raw, chan3_raw, chan4_raw, chan5_raw, chan6_raw, chan7_raw, chan8_raw, chan9_raw, chan10_raw, chan11_raw, chan12_raw, rssi)) + + def optical_flow_encode(self, time_usec, sensor_id, flow_x, flow_y, quality, ground_distance): + ''' + Optical flow from a flow sensor (e.g. optical mouse sensor) + + time_usec : Timestamp (UNIX) (uint64_t) + sensor_id : Sensor ID (uint8_t) + flow_x : Flow in pixels in x-sensor direction (int16_t) + flow_y : Flow in pixels in y-sensor direction (int16_t) + quality : Optical flow quality / confidence. 0: bad, 255: maximum quality (uint8_t) + ground_distance : Ground distance in meters (float) + + ''' + msg = MAVLink_optical_flow_message(time_usec, sensor_id, flow_x, flow_y, quality, ground_distance) + msg.pack(self) + return msg + + def optical_flow_send(self, time_usec, sensor_id, flow_x, flow_y, quality, ground_distance): + ''' + Optical flow from a flow sensor (e.g. optical mouse sensor) + + time_usec : Timestamp (UNIX) (uint64_t) + sensor_id : Sensor ID (uint8_t) + flow_x : Flow in pixels in x-sensor direction (int16_t) + flow_y : Flow in pixels in y-sensor direction (int16_t) + quality : Optical flow quality / confidence. 0: bad, 255: maximum quality (uint8_t) + ground_distance : Ground distance in meters (float) + + ''' + return self.send(self.optical_flow_encode(time_usec, sensor_id, flow_x, flow_y, quality, ground_distance)) + + def global_vision_position_estimate_encode(self, usec, x, y, z, roll, pitch, yaw): + ''' + + + usec : Timestamp (milliseconds) (uint64_t) + x : Global X position (float) + y : Global Y position (float) + z : Global Z position (float) + roll : Roll angle in rad (float) + pitch : Pitch angle in rad (float) + yaw : Yaw angle in rad (float) + + ''' + msg = MAVLink_global_vision_position_estimate_message(usec, x, y, z, roll, pitch, yaw) + msg.pack(self) + return msg + + def global_vision_position_estimate_send(self, usec, x, y, z, roll, pitch, yaw): + ''' + + + usec : Timestamp (milliseconds) (uint64_t) + x : Global X position (float) + y : Global Y position (float) + z : Global Z position (float) + roll : Roll angle in rad (float) + pitch : Pitch angle in rad (float) + yaw : Yaw angle in rad (float) + + ''' + return self.send(self.global_vision_position_estimate_encode(usec, x, y, z, roll, pitch, yaw)) + + def vision_position_estimate_encode(self, usec, x, y, z, roll, pitch, yaw): + ''' + + + usec : Timestamp (milliseconds) (uint64_t) + x : Global X position (float) + y : Global Y position (float) + z : Global Z position (float) + roll : Roll angle in rad (float) + pitch : Pitch angle in rad (float) + yaw : Yaw angle in rad (float) + + ''' + msg = MAVLink_vision_position_estimate_message(usec, x, y, z, roll, pitch, yaw) + msg.pack(self) + return msg + + def vision_position_estimate_send(self, usec, x, y, z, roll, pitch, yaw): + ''' + + + usec : Timestamp (milliseconds) (uint64_t) + x : Global X position (float) + y : Global Y position (float) + z : Global Z position (float) + roll : Roll angle in rad (float) + pitch : Pitch angle in rad (float) + yaw : Yaw angle in rad (float) + + ''' + return self.send(self.vision_position_estimate_encode(usec, x, y, z, roll, pitch, yaw)) + + def vision_speed_estimate_encode(self, usec, x, y, z): + ''' + + + usec : Timestamp (milliseconds) (uint64_t) + x : Global X speed (float) + y : Global Y speed (float) + z : Global Z speed (float) + + ''' + msg = MAVLink_vision_speed_estimate_message(usec, x, y, z) + msg.pack(self) + return msg + + def vision_speed_estimate_send(self, usec, x, y, z): + ''' + + + usec : Timestamp (milliseconds) (uint64_t) + x : Global X speed (float) + y : Global Y speed (float) + z : Global Z speed (float) + + ''' + return self.send(self.vision_speed_estimate_encode(usec, x, y, z)) + + def vicon_position_estimate_encode(self, usec, x, y, z, roll, pitch, yaw): + ''' + + + usec : Timestamp (milliseconds) (uint64_t) + x : Global X position (float) + y : Global Y position (float) + z : Global Z position (float) + roll : Roll angle in rad (float) + pitch : Pitch angle in rad (float) + yaw : Yaw angle in rad (float) + + ''' + msg = MAVLink_vicon_position_estimate_message(usec, x, y, z, roll, pitch, yaw) + msg.pack(self) + return msg + + def vicon_position_estimate_send(self, usec, x, y, z, roll, pitch, yaw): + ''' + + + usec : Timestamp (milliseconds) (uint64_t) + x : Global X position (float) + y : Global Y position (float) + z : Global Z position (float) + roll : Roll angle in rad (float) + pitch : Pitch angle in rad (float) + yaw : Yaw angle in rad (float) + + ''' + return self.send(self.vicon_position_estimate_encode(usec, x, y, z, roll, pitch, yaw)) + + def memory_vect_encode(self, address, ver, type, value): + ''' + Send raw controller memory. The use of this message is discouraged for + normal packets, but a quite efficient way for testing + new messages and getting experimental debug output. + + address : Starting address of the debug variables (uint16_t) + ver : Version code of the type variable. 0=unknown, type ignored and assumed int16_t. 1=as below (uint8_t) + type : Type code of the memory variables. for ver = 1: 0=16 x int16_t, 1=16 x uint16_t, 2=16 x Q15, 3=16 x 1Q14 (uint8_t) + value : Memory contents at specified address (int8_t) + + ''' + msg = MAVLink_memory_vect_message(address, ver, type, value) + msg.pack(self) + return msg + + def memory_vect_send(self, address, ver, type, value): + ''' + Send raw controller memory. The use of this message is discouraged for + normal packets, but a quite efficient way for testing + new messages and getting experimental debug output. + + address : Starting address of the debug variables (uint16_t) + ver : Version code of the type variable. 0=unknown, type ignored and assumed int16_t. 1=as below (uint8_t) + type : Type code of the memory variables. for ver = 1: 0=16 x int16_t, 1=16 x uint16_t, 2=16 x Q15, 3=16 x 1Q14 (uint8_t) + value : Memory contents at specified address (int8_t) + + ''' + return self.send(self.memory_vect_encode(address, ver, type, value)) + + def debug_vect_encode(self, name, time_usec, x, y, z): + ''' + + + name : Name (char) + time_usec : Timestamp (uint64_t) + x : x (float) + y : y (float) + z : z (float) + + ''' + msg = MAVLink_debug_vect_message(name, time_usec, x, y, z) + msg.pack(self) + return msg + + def debug_vect_send(self, name, time_usec, x, y, z): + ''' + + + name : Name (char) + time_usec : Timestamp (uint64_t) + x : x (float) + y : y (float) + z : z (float) + + ''' + return self.send(self.debug_vect_encode(name, time_usec, x, y, z)) + + def named_value_float_encode(self, time_boot_ms, name, value): + ''' + Send a key-value pair as float. The use of this message is discouraged + for normal packets, but a quite efficient way for + testing new messages and getting experimental debug + output. + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + name : Name of the debug variable (char) + value : Floating point value (float) + + ''' + msg = MAVLink_named_value_float_message(time_boot_ms, name, value) + msg.pack(self) + return msg + + def named_value_float_send(self, time_boot_ms, name, value): + ''' + Send a key-value pair as float. The use of this message is discouraged + for normal packets, but a quite efficient way for + testing new messages and getting experimental debug + output. + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + name : Name of the debug variable (char) + value : Floating point value (float) + + ''' + return self.send(self.named_value_float_encode(time_boot_ms, name, value)) + + def named_value_int_encode(self, time_boot_ms, name, value): + ''' + Send a key-value pair as integer. The use of this message is + discouraged for normal packets, but a quite efficient + way for testing new messages and getting experimental + debug output. + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + name : Name of the debug variable (char) + value : Signed integer value (int32_t) + + ''' + msg = MAVLink_named_value_int_message(time_boot_ms, name, value) + msg.pack(self) + return msg + + def named_value_int_send(self, time_boot_ms, name, value): + ''' + Send a key-value pair as integer. The use of this message is + discouraged for normal packets, but a quite efficient + way for testing new messages and getting experimental + debug output. + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + name : Name of the debug variable (char) + value : Signed integer value (int32_t) + + ''' + return self.send(self.named_value_int_encode(time_boot_ms, name, value)) + + def statustext_encode(self, severity, text): + ''' + Status text message. These messages are printed in yellow in the COMM + console of QGroundControl. WARNING: They consume quite + some bandwidth, so use only for important status and + error messages. If implemented wisely, these messages + are buffered on the MCU and sent only at a limited + rate (e.g. 10 Hz). + + severity : Severity of status, 0 = info message, 255 = critical fault (uint8_t) + text : Status text message, without null termination character (char) + + ''' + msg = MAVLink_statustext_message(severity, text) + msg.pack(self) + return msg + + def statustext_send(self, severity, text): + ''' + Status text message. These messages are printed in yellow in the COMM + console of QGroundControl. WARNING: They consume quite + some bandwidth, so use only for important status and + error messages. If implemented wisely, these messages + are buffered on the MCU and sent only at a limited + rate (e.g. 10 Hz). + + severity : Severity of status, 0 = info message, 255 = critical fault (uint8_t) + text : Status text message, without null termination character (char) + + ''' + return self.send(self.statustext_encode(severity, text)) + + def debug_encode(self, time_boot_ms, ind, value): + ''' + Send a debug value. The index is used to discriminate between values. + These values show up in the plot of QGroundControl as + DEBUG N. + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + ind : index of debug variable (uint8_t) + value : DEBUG value (float) + + ''' + msg = MAVLink_debug_message(time_boot_ms, ind, value) + msg.pack(self) + return msg + + def debug_send(self, time_boot_ms, ind, value): + ''' + Send a debug value. The index is used to discriminate between values. + These values show up in the plot of QGroundControl as + DEBUG N. + + time_boot_ms : Timestamp (milliseconds since system boot) (uint32_t) + ind : index of debug variable (uint8_t) + value : DEBUG value (float) + + ''' + return self.send(self.debug_encode(time_boot_ms, ind, value)) + + def extended_message_encode(self, target_system, target_component, protocol_flags): + ''' + Extended message spacer. + + target_system : System which should execute the command (uint8_t) + target_component : Component which should execute the command, 0 for all components (uint8_t) + protocol_flags : Retransmission / ACK flags (uint8_t) + + ''' + msg = MAVLink_extended_message_message(target_system, target_component, protocol_flags) + msg.pack(self) + return msg + + def extended_message_send(self, target_system, target_component, protocol_flags): + ''' + Extended message spacer. + + target_system : System which should execute the command (uint8_t) + target_component : Component which should execute the command, 0 for all components (uint8_t) + protocol_flags : Retransmission / ACK flags (uint8_t) + + ''' + return self.send(self.extended_message_encode(target_system, target_component, protocol_flags)) + diff --git a/mavlink/share/pyshared/pymavlink/mavutil.py b/mavlink/share/pyshared/pymavlink/mavutil.py new file mode 100644 index 0000000000..c0f625214d --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/mavutil.py @@ -0,0 +1,678 @@ +#!/usr/bin/env python +''' +mavlink python utility functions + +Copyright Andrew Tridgell 2011 +Released under GNU GPL version 3 or later +''' + +import socket, math, struct, time, os, fnmatch, array, sys, errno +from math import * +from mavextra import * + +if os.getenv('MAVLINK10'): + import mavlinkv10 as mavlink +else: + import mavlink + +def evaluate_expression(expression, vars): + '''evaluation an expression''' + try: + v = eval(expression, globals(), vars) + except NameError: + return None + return v + +def evaluate_condition(condition, vars): + '''evaluation a conditional (boolean) statement''' + if condition is None: + return True + v = evaluate_expression(condition, vars) + if v is None: + return False + return v + + +class mavfile(object): + '''a generic mavlink port''' + def __init__(self, fd, address, source_system=255, notimestamps=False): + self.fd = fd + self.address = address + self.messages = { 'MAV' : self } + if mavlink.WIRE_PROTOCOL_VERSION == "1.0": + self.messages['HOME'] = mavlink.MAVLink_gps_raw_int_message(0,0,0,0,0,0,0,0,0,0) + mavlink.MAVLink_waypoint_message = mavlink.MAVLink_mission_item_message + else: + self.messages['HOME'] = mavlink.MAVLink_gps_raw_message(0,0,0,0,0,0,0,0,0) + self.params = {} + self.mav = None + self.target_system = 0 + self.target_component = 0 + self.mav = mavlink.MAVLink(self, srcSystem=source_system) + self.mav.robust_parsing = True + self.logfile = None + self.logfile_raw = None + self.param_fetch_in_progress = False + self.param_fetch_complete = False + self.start_time = time.time() + self.flightmode = "UNKNOWN" + self.timestamp = 0 + self.message_hooks = [] + self.idle_hooks = [] + self.usec = 0 + self.notimestamps = notimestamps + self._timestamp = None + + def recv(self, n=None): + '''default recv method''' + raise RuntimeError('no recv() method supplied') + + def close(self, n=None): + '''default close method''' + raise RuntimeError('no close() method supplied') + + def write(self, buf): + '''default write method''' + raise RuntimeError('no write() method supplied') + + def pre_message(self): + '''default pre message call''' + return + + def post_message(self, msg): + '''default post message call''' + msg._timestamp = time.time() + type = msg.get_type() + self.messages[type] = msg + + if self._timestamp is not None: + if self.notimestamps: + if 'usec' in msg.__dict__: + self.usec = msg.usec / 1.0e6 + msg._timestamp = self.usec + else: + msg._timestamp = self._timestamp + + self.timestamp = msg._timestamp + if type == 'HEARTBEAT': + self.target_system = msg.get_srcSystem() + self.target_component = msg.get_srcComponent() + if mavlink.WIRE_PROTOCOL_VERSION == '1.0': + self.flightmode = mode_string_v10(msg) + elif type == 'PARAM_VALUE': + self.params[str(msg.param_id)] = msg.param_value + if msg.param_index+1 == msg.param_count: + self.param_fetch_in_progress = False + self.param_fetch_complete = True + elif type == 'SYS_STATUS' and mavlink.WIRE_PROTOCOL_VERSION == '0.9': + self.flightmode = mode_string_v09(msg) + elif type == 'GPS_RAW': + if self.messages['HOME'].fix_type < 2: + self.messages['HOME'] = msg + for hook in self.message_hooks: + hook(self, msg) + + + def recv_msg(self): + '''message receive routine''' + self.pre_message() + while True: + n = self.mav.bytes_needed() + s = self.recv(n) + if len(s) == 0 and len(self.mav.buf) == 0: + return None + if self.logfile_raw: + self.logfile_raw.write(str(s)) + msg = self.mav.parse_char(s) + if msg: + self.post_message(msg) + return msg + + def recv_match(self, condition=None, type=None, blocking=False): + '''recv the next MAVLink message that matches the given condition''' + while True: + m = self.recv_msg() + if m is None: + if blocking: + for hook in self.idle_hooks: + hook(self) + time.sleep(0.01) + continue + return None + if type is not None and type != m.get_type(): + continue + if not evaluate_condition(condition, self.messages): + continue + return m + + def setup_logfile(self, logfile, mode='w'): + '''start logging to the given logfile, with timestamps''' + self.logfile = open(logfile, mode=mode) + + def setup_logfile_raw(self, logfile, mode='w'): + '''start logging raw bytes to the given logfile, without timestamps''' + self.logfile_raw = open(logfile, mode=mode) + + def wait_heartbeat(self, blocking=True): + '''wait for a heartbeat so we know the target system IDs''' + return self.recv_match(type='HEARTBEAT', blocking=blocking) + + def param_fetch_all(self): + '''initiate fetch of all parameters''' + if time.time() - getattr(self, 'param_fetch_start', 0) < 2.0: + # don't fetch too often + return + self.param_fetch_start = time.time() + self.param_fetch_in_progress = True + self.mav.param_request_list_send(self.target_system, self.target_component) + + def time_since(self, mtype): + '''return the time since the last message of type mtype was received''' + if not mtype in self.messages: + return time.time() - self.start_time + return time.time() - self.messages[mtype]._timestamp + + def param_set_send(self, parm_name, parm_value, parm_type=None): + '''wrapper for parameter set''' + if mavlink.WIRE_PROTOCOL_VERSION == '1.0': + if parm_type == None: + parm_type = mavlink.MAV_VAR_FLOAT + self.mav.param_set_send(self.target_system, self.target_component, + parm_name, parm_value, parm_type) + else: + self.mav.param_set_send(self.target_system, self.target_component, + parm_name, parm_value) + + def waypoint_request_list_send(self): + '''wrapper for waypoint_request_list_send''' + if mavlink.WIRE_PROTOCOL_VERSION == '1.0': + self.mav.mission_request_list_send(self.target_system, self.target_component) + else: + self.mav.waypoint_request_list_send(self.target_system, self.target_component) + + def waypoint_clear_all_send(self): + '''wrapper for waypoint_clear_all_send''' + if mavlink.WIRE_PROTOCOL_VERSION == '1.0': + self.mav.mission_clear_all_send(self.target_system, self.target_component) + else: + self.mav.waypoint_clear_all_send(self.target_system, self.target_component) + + def waypoint_request_send(self, seq): + '''wrapper for waypoint_request_send''' + if mavlink.WIRE_PROTOCOL_VERSION == '1.0': + self.mav.mission_request_send(self.target_system, self.target_component, seq) + else: + self.mav.waypoint_request_send(self.target_system, self.target_component, seq) + + def waypoint_set_current_send(self, seq): + '''wrapper for waypoint_set_current_send''' + if mavlink.WIRE_PROTOCOL_VERSION == '1.0': + self.mav.mission_set_current_send(self.target_system, self.target_component, seq) + else: + self.mav.waypoint_set_current_send(self.target_system, self.target_component, seq) + + def waypoint_count_send(self, seq): + '''wrapper for waypoint_count_send''' + if mavlink.WIRE_PROTOCOL_VERSION == '1.0': + self.mav.mission_count_send(self.target_system, self.target_component, seq) + else: + self.mav.waypoint_count_send(self.target_system, self.target_component, seq) + + +class mavserial(mavfile): + '''a serial mavlink port''' + def __init__(self, device, baud=115200, autoreconnect=False, source_system=255): + import serial + self.baud = baud + self.device = device + self.autoreconnect = autoreconnect + self.port = serial.Serial(self.device, self.baud, timeout=0, + dsrdtr=False, rtscts=False, xonxoff=False) + + try: + fd = self.port.fileno() + except Exception: + fd = None + mavfile.__init__(self, fd, device, source_system=source_system) + + def close(self): + self.port.close() + + def recv(self,n=None): + if n is None: + n = self.mav.bytes_needed() + if self.fd is None: + waiting = self.port.inWaiting() + if waiting < n: + n = waiting + return self.port.read(n) + + def write(self, buf): + try: + return self.port.write(buf) + except OSError: + if self.autoreconnect: + self.reset() + return -1 + + def reset(self): + import serial + self.port.close() + while True: + try: + self.port = serial.Serial(self.device, self.baud, timeout=1, + dsrdtr=False, rtscts=False, xonxoff=False) + try: + self.fd = self.port.fileno() + except Exception: + self.fd = None + return + except Exception: + print("Failed to reopen %s" % self.device) + time.sleep(1) + + +class mavudp(mavfile): + '''a UDP mavlink socket''' + def __init__(self, device, input=True, source_system=255): + a = device.split(':') + if len(a) != 2: + print("UDP ports must be specified as host:port") + sys.exit(1) + self.port = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.udp_server = input + if input: + self.port.bind((a[0], int(a[1]))) + else: + self.destination_addr = (a[0], int(a[1])) + self.port.setblocking(0) + self.last_address = None + mavfile.__init__(self, self.port.fileno(), device, source_system=source_system) + + def close(self): + self.port.close() + + def recv(self,n=None): + try: + data, self.last_address = self.port.recvfrom(300) + except socket.error as e: + if e.errno in [ errno.EAGAIN, errno.EWOULDBLOCK ]: + return "" + raise + return data + + def write(self, buf): + try: + if self.udp_server: + if self.last_address: + self.port.sendto(buf, self.last_address) + else: + self.port.sendto(buf, self.destination_addr) + except socket.error: + pass + + def recv_msg(self): + '''message receive routine for UDP link''' + self.pre_message() + s = self.recv() + if len(s) == 0: + return None + msg = self.mav.parse_buffer(s) + if msg is not None: + for m in msg: + self.post_message(m) + return msg[0] + return None + + +class mavtcp(mavfile): + '''a TCP mavlink socket''' + def __init__(self, device, source_system=255): + a = device.split(':') + if len(a) != 2: + print("TCP ports must be specified as host:port") + sys.exit(1) + self.port = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.destination_addr = (a[0], int(a[1])) + self.port.connect(self.destination_addr) + self.port.setblocking(0) + self.port.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) + mavfile.__init__(self, self.port.fileno(), device, source_system=source_system) + + def close(self): + self.port.close() + + def recv(self,n=None): + if n is None: + n = self.mav.bytes_needed() + try: + data = self.port.recv(n) + except socket.error as e: + if e.errno in [ errno.EAGAIN, errno.EWOULDBLOCK ]: + return "" + raise + return data + + def write(self, buf): + try: + self.port.send(buf) + except socket.error: + pass + + +class mavlogfile(mavfile): + '''a MAVLink logfile reader/writer''' + def __init__(self, filename, planner_format=None, + write=False, append=False, + robust_parsing=True, notimestamps=False, source_system=255): + self.filename = filename + self.writeable = write + self.robust_parsing = robust_parsing + self.planner_format = planner_format + self._two64 = math.pow(2.0, 63) + mode = 'rb' + if self.writeable: + if append: + mode = 'ab' + else: + mode = 'wb' + self.f = open(filename, mode) + self.filesize = os.path.getsize(filename) + self.percent = 0 + mavfile.__init__(self, None, filename, source_system=source_system, notimestamps=notimestamps) + if self.notimestamps: + self._timestamp = 0 + else: + self._timestamp = time.time() + + def close(self): + self.f.close() + + def recv(self,n=None): + if n is None: + n = self.mav.bytes_needed() + return self.f.read(n) + + def write(self, buf): + self.f.write(buf) + + def pre_message(self): + '''read timestamp if needed''' + # read the timestamp + self.percent = (100.0 * self.f.tell()) / self.filesize + if self.notimestamps: + return + if self.planner_format: + tbuf = self.f.read(21) + if len(tbuf) != 21 or tbuf[0] != '-' or tbuf[20] != ':': + raise RuntimeError('bad planner timestamp %s' % tbuf) + hnsec = self._two64 + float(tbuf[0:20]) + t = hnsec * 1.0e-7 # convert to seconds + t -= 719163 * 24 * 60 * 60 # convert to 1970 base + else: + tbuf = self.f.read(8) + if len(tbuf) != 8: + return + (tusec,) = struct.unpack('>Q', tbuf) + t = tusec * 1.0e-6 + self._timestamp = t + + def post_message(self, msg): + '''add timestamp to message''' + # read the timestamp + super(mavlogfile, self).post_message(msg) + if self.planner_format: + self.f.read(1) # trailing newline + self.timestamp = msg._timestamp + +class mavchildexec(mavfile): + '''a MAVLink child processes reader/writer''' + def __init__(self, filename, source_system=255): + from subprocess import Popen, PIPE + import fcntl + + self.filename = filename + self.child = Popen(filename, shell=True, stdout=PIPE, stdin=PIPE) + self.fd = self.child.stdout.fileno() + + fl = fcntl.fcntl(self.fd, fcntl.F_GETFL) + fcntl.fcntl(self.fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) + + fl = fcntl.fcntl(self.child.stdout.fileno(), fcntl.F_GETFL) + fcntl.fcntl(self.child.stdout.fileno(), fcntl.F_SETFL, fl | os.O_NONBLOCK) + + mavfile.__init__(self, self.fd, filename, source_system=source_system) + + def close(self): + self.child.close() + + def recv(self,n=None): + try: + x = self.child.stdout.read(1) + except Exception: + return '' + return x + + def write(self, buf): + self.child.stdin.write(buf) + + +def mavlink_connection(device, baud=115200, source_system=255, + planner_format=None, write=False, append=False, + robust_parsing=True, notimestamps=False, input=True): + '''make a serial or UDP mavlink connection''' + if device.startswith('tcp:'): + return mavtcp(device[4:], source_system=source_system) + if device.startswith('udp:'): + return mavudp(device[4:], input=input, source_system=source_system) + if device.find(':') != -1 and not device.endswith('log'): + return mavudp(device, source_system=source_system, input=input) + if os.path.isfile(device): + if device.endswith(".elf"): + return mavchildexec(device, source_system=source_system) + else: + return mavlogfile(device, planner_format=planner_format, write=write, + append=append, robust_parsing=robust_parsing, notimestamps=notimestamps, + source_system=source_system) + return mavserial(device, baud=baud, source_system=source_system) + +class periodic_event(object): + '''a class for fixed frequency events''' + def __init__(self, frequency): + self.frequency = float(frequency) + self.last_time = time.time() + + def force(self): + '''force immediate triggering''' + self.last_time = 0 + + def trigger(self): + '''return True if we should trigger now''' + tnow = time.time() + if self.last_time + (1.0/self.frequency) <= tnow: + self.last_time = tnow + return True + return False + + +try: + from curses import ascii + have_ascii = True +except: + have_ascii = False + +def is_printable(c): + '''see if a character is printable''' + global have_ascii + if have_ascii: + return ascii.isprint(c) + if isinstance(c, int): + ic = c + else: + ic = ord(c) + return ic >= 32 and ic <= 126 + +def all_printable(buf): + '''see if a string is all printable''' + for c in buf: + if not is_printable(c) and not c in ['\r', '\n', '\t']: + return False + return True + +class SerialPort(object): + '''auto-detected serial port''' + def __init__(self, device, description=None, hwid=None): + self.device = device + self.description = description + self.hwid = hwid + + def __str__(self): + ret = self.device + if self.description is not None: + ret += " : " + self.description + if self.hwid is not None: + ret += " : " + self.hwid + return ret + +def auto_detect_serial_win32(preferred_list=['*']): + '''try to auto-detect serial ports on win32''' + try: + import scanwin32 + list = sorted(scanwin32.comports()) + except: + return [] + ret = [] + for order, port, desc, hwid in list: + for preferred in preferred_list: + if fnmatch.fnmatch(desc, preferred) or fnmatch.fnmatch(hwid, preferred): + ret.append(SerialPort(port, description=desc, hwid=hwid)) + if len(ret) > 0: + return ret + # now the rest + for order, port, desc, hwid in list: + ret.append(SerialPort(port, description=desc, hwid=hwid)) + return ret + + + + +def auto_detect_serial_unix(preferred_list=['*']): + '''try to auto-detect serial ports on win32''' + import glob + glist = glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') + glob.glob('/dev/serial/by-id/*') + ret = [] + # try preferred ones first + for d in glist: + for preferred in preferred_list: + if fnmatch.fnmatch(d, preferred): + ret.append(SerialPort(d)) + if len(ret) > 0: + return ret + # now the rest + for d in glist: + ret.append(SerialPort(d)) + return ret + + + +def auto_detect_serial(preferred_list=['*']): + '''try to auto-detect serial port''' + # see if + if os.name == 'nt': + return auto_detect_serial_win32(preferred_list=preferred_list) + return auto_detect_serial_unix(preferred_list=preferred_list) + +def mode_string_v09(msg): + '''mode string for 0.9 protocol''' + mode = msg.mode + nav_mode = msg.nav_mode + + MAV_MODE_UNINIT = 0 + MAV_MODE_MANUAL = 2 + MAV_MODE_GUIDED = 3 + MAV_MODE_AUTO = 4 + MAV_MODE_TEST1 = 5 + MAV_MODE_TEST2 = 6 + MAV_MODE_TEST3 = 7 + + MAV_NAV_GROUNDED = 0 + MAV_NAV_LIFTOFF = 1 + MAV_NAV_HOLD = 2 + MAV_NAV_WAYPOINT = 3 + MAV_NAV_VECTOR = 4 + MAV_NAV_RETURNING = 5 + MAV_NAV_LANDING = 6 + MAV_NAV_LOST = 7 + MAV_NAV_LOITER = 8 + + cmode = (mode, nav_mode) + mapping = { + (MAV_MODE_UNINIT, MAV_NAV_GROUNDED) : "INITIALISING", + (MAV_MODE_MANUAL, MAV_NAV_VECTOR) : "MANUAL", + (MAV_MODE_TEST3, MAV_NAV_VECTOR) : "CIRCLE", + (MAV_MODE_GUIDED, MAV_NAV_VECTOR) : "GUIDED", + (MAV_MODE_TEST1, MAV_NAV_VECTOR) : "STABILIZE", + (MAV_MODE_TEST2, MAV_NAV_LIFTOFF) : "FBWA", + (MAV_MODE_AUTO, MAV_NAV_WAYPOINT) : "AUTO", + (MAV_MODE_AUTO, MAV_NAV_RETURNING) : "RTL", + (MAV_MODE_AUTO, MAV_NAV_LOITER) : "LOITER", + (MAV_MODE_AUTO, MAV_NAV_LIFTOFF) : "TAKEOFF", + (MAV_MODE_AUTO, MAV_NAV_LANDING) : "LANDING", + (MAV_MODE_AUTO, MAV_NAV_HOLD) : "LOITER", + (MAV_MODE_GUIDED, MAV_NAV_VECTOR) : "GUIDED", + (MAV_MODE_GUIDED, MAV_NAV_WAYPOINT) : "GUIDED", + (100, MAV_NAV_VECTOR) : "STABILIZE", + (101, MAV_NAV_VECTOR) : "ACRO", + (102, MAV_NAV_VECTOR) : "ALT_HOLD", + (107, MAV_NAV_VECTOR) : "CIRCLE", + (109, MAV_NAV_VECTOR) : "LAND", + } + if cmode in mapping: + return mapping[cmode] + return "Mode(%s,%s)" % cmode + +def mode_string_v10(msg): + '''mode string for 1.0 protocol, from heartbeat''' + if not msg.base_mode & mavlink.MAV_MODE_FLAG_CUSTOM_MODE_ENABLED: + return "Mode(0x%08x)" % msg.base_mode + mapping = { + 0 : 'MANUAL', + 1 : 'CIRCLE', + 2 : 'STABILIZE', + 5 : 'FBWA', + 6 : 'FBWB', + 7 : 'FBWC', + 10 : 'AUTO', + 11 : 'RTL', + 12 : 'LOITER', + 13 : 'TAKEOFF', + 14 : 'LAND', + 15 : 'GUIDED', + 16 : 'INITIALISING' + } + if msg.custom_mode in mapping: + return mapping[msg.custom_mode] + return "Mode(%u)" % msg.custom_mode + + + +class x25crc(object): + '''x25 CRC - based on checksum.h from mavlink library''' + def __init__(self, buf=''): + self.crc = 0xffff + self.accumulate(buf) + + def accumulate(self, buf): + '''add in some more bytes''' + bytes = array.array('B') + if isinstance(buf, array.array): + bytes.extend(buf) + else: + bytes.fromstring(buf) + accum = self.crc + for b in bytes: + tmp = b ^ (accum & 0xff) + tmp = (tmp ^ (tmp<<4)) & 0xFF + accum = (accum>>8) ^ (tmp<<8) ^ (tmp<<3) ^ (tmp>>4) + accum = accum & 0xFFFF + self.crc = accum diff --git a/mavlink/share/pyshared/pymavlink/mavwp.py b/mavlink/share/pyshared/pymavlink/mavwp.py new file mode 100644 index 0000000000..6fd1e10e2b --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/mavwp.py @@ -0,0 +1,200 @@ +''' +module for loading/saving waypoints +''' + +import os + +if os.getenv('MAVLINK10'): + import mavlinkv10 as mavlink +else: + import mavlink + +class MAVWPError(Exception): + '''MAVLink WP error class''' + def __init__(self, msg): + Exception.__init__(self, msg) + self.message = msg + +class MAVWPLoader(object): + '''MAVLink waypoint loader''' + def __init__(self, target_system=0, target_component=0): + self.wpoints = [] + self.target_system = target_system + self.target_component = target_component + + + def count(self): + '''return number of waypoints''' + return len(self.wpoints) + + def wp(self, i): + '''return a waypoint''' + return self.wpoints[i] + + def add(self, w): + '''add a waypoint''' + w.seq = self.count() + self.wpoints.append(w) + + def remove(self, w): + '''remove a waypoint''' + self.wpoints.remove(w) + + def clear(self): + '''clear waypoint list''' + self.wpoints = [] + + def _read_waypoint_v100(self, line): + '''read a version 100 waypoint''' + cmdmap = { + 2 : mavlink.MAV_CMD_NAV_TAKEOFF, + 3 : mavlink.MAV_CMD_NAV_RETURN_TO_LAUNCH, + 4 : mavlink.MAV_CMD_NAV_LAND, + 24: mavlink.MAV_CMD_NAV_TAKEOFF, + 26: mavlink.MAV_CMD_NAV_LAND, + 25: mavlink.MAV_CMD_NAV_WAYPOINT , + 27: mavlink.MAV_CMD_NAV_LOITER_UNLIM + } + a = line.split() + if len(a) != 13: + raise MAVWPError("invalid waypoint line with %u values" % len(a)) + w = mavlink.MAVLink_waypoint_message(self.target_system, self.target_component, + int(a[0]), # seq + int(a[1]), # frame + int(a[2]), # action + int(a[7]), # current + int(a[12]), # autocontinue + float(a[5]), # param1, + float(a[6]), # param2, + float(a[3]), # param3 + float(a[4]), # param4 + float(a[9]), # x, latitude + float(a[8]), # y, longitude + float(a[10]) # z + ) + if not w.command in cmdmap: + raise MAVWPError("Unknown v100 waypoint action %u" % w.command) + + w.command = cmdmap[w.command] + return w + + def _read_waypoint_v110(self, line): + '''read a version 110 waypoint''' + a = line.split() + if len(a) != 12: + raise MAVWPError("invalid waypoint line with %u values" % len(a)) + w = mavlink.MAVLink_waypoint_message(self.target_system, self.target_component, + int(a[0]), # seq + int(a[2]), # frame + int(a[3]), # command + int(a[1]), # current + int(a[11]), # autocontinue + float(a[4]), # param1, + float(a[5]), # param2, + float(a[6]), # param3 + float(a[7]), # param4 + float(a[8]), # x (latitude) + float(a[9]), # y (longitude) + float(a[10]) # z (altitude) + ) + return w + + + def load(self, filename): + '''load waypoints from a file. + returns number of waypoints loaded''' + f = open(filename, mode='r') + version_line = f.readline().strip() + if version_line == "QGC WPL 100": + readfn = self._read_waypoint_v100 + elif version_line == "QGC WPL 110": + readfn = self._read_waypoint_v110 + else: + f.close() + raise MAVWPError("Unsupported waypoint format '%s'" % version_line) + + self.clear() + + for line in f: + if line.startswith('#'): + continue + line = line.strip() + if not line: + continue + w = readfn(line) + if w is not None: + self.add(w) + f.close() + return len(self.wpoints) + + + def save(self, filename): + '''save waypoints to a file''' + f = open(filename, mode='w') + f.write("QGC WPL 110\n") + for w in self.wpoints: + f.write("%u\t%u\t%u\t%u\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%u\n" % ( + w.seq, w.current, w.frame, w.command, + w.param1, w.param2, w.param3, w.param4, + w.x, w.y, w.z, w.autocontinue)) + f.close() + + +class MAVFenceError(Exception): + '''MAVLink fence error class''' + def __init__(self, msg): + Exception.__init__(self, msg) + self.message = msg + +class MAVFenceLoader(object): + '''MAVLink geo-fence loader''' + def __init__(self, target_system=0, target_component=0): + self.points = [] + self.target_system = target_system + self.target_component = target_component + + def count(self): + '''return number of points''' + return len(self.points) + + def point(self, i): + '''return a point''' + return self.points[i] + + def add(self, p): + '''add a point''' + self.points.append(p) + + def clear(self): + '''clear point list''' + self.points = [] + + def load(self, filename): + '''load points from a file. + returns number of points loaded''' + f = open(filename, mode='r') + self.clear() + for line in f: + if line.startswith('#'): + continue + line = line.strip() + if not line: + continue + a = line.split() + if len(a) != 2: + raise MAVFenceError("invalid fence point line: %s" % line) + p = mavlink.MAVLink_fence_point_message(self.target_system, self.target_component, + self.count(), 0, float(a[0]), float(a[1])) + self.add(p) + f.close() + for i in range(self.count()): + self.points[i].count = self.count() + return len(self.points) + + + def save(self, filename): + '''save fence points to a file''' + f = open(filename, mode='w') + for p in self.points: + f.write("%f\t%f\n" % (p.lat, p.lng)) + f.close() diff --git a/mavlink/share/pyshared/pymavlink/scanwin32.py b/mavlink/share/pyshared/pymavlink/scanwin32.py new file mode 100644 index 0000000000..f90ed5f4d8 --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/scanwin32.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python + +# this is taken from the pySerial documentation at +# http://pyserial.sourceforge.net/examples.html +import ctypes +import re + +def ValidHandle(value): + if value == 0: + raise ctypes.WinError() + return value + +NULL = 0 +HDEVINFO = ctypes.c_int +BOOL = ctypes.c_int +CHAR = ctypes.c_char +PCTSTR = ctypes.c_char_p +HWND = ctypes.c_uint +DWORD = ctypes.c_ulong +PDWORD = ctypes.POINTER(DWORD) +ULONG = ctypes.c_ulong +ULONG_PTR = ctypes.POINTER(ULONG) +#~ PBYTE = ctypes.c_char_p +PBYTE = ctypes.c_void_p + +class GUID(ctypes.Structure): + _fields_ = [ + ('Data1', ctypes.c_ulong), + ('Data2', ctypes.c_ushort), + ('Data3', ctypes.c_ushort), + ('Data4', ctypes.c_ubyte*8), + ] + def __str__(self): + return "{%08x-%04x-%04x-%s-%s}" % ( + self.Data1, + self.Data2, + self.Data3, + ''.join(["%02x" % d for d in self.Data4[:2]]), + ''.join(["%02x" % d for d in self.Data4[2:]]), + ) + +class SP_DEVINFO_DATA(ctypes.Structure): + _fields_ = [ + ('cbSize', DWORD), + ('ClassGuid', GUID), + ('DevInst', DWORD), + ('Reserved', ULONG_PTR), + ] + def __str__(self): + return "ClassGuid:%s DevInst:%s" % (self.ClassGuid, self.DevInst) +PSP_DEVINFO_DATA = ctypes.POINTER(SP_DEVINFO_DATA) + +class SP_DEVICE_INTERFACE_DATA(ctypes.Structure): + _fields_ = [ + ('cbSize', DWORD), + ('InterfaceClassGuid', GUID), + ('Flags', DWORD), + ('Reserved', ULONG_PTR), + ] + def __str__(self): + return "InterfaceClassGuid:%s Flags:%s" % (self.InterfaceClassGuid, self.Flags) + +PSP_DEVICE_INTERFACE_DATA = ctypes.POINTER(SP_DEVICE_INTERFACE_DATA) + +PSP_DEVICE_INTERFACE_DETAIL_DATA = ctypes.c_void_p + +class dummy(ctypes.Structure): + _fields_=[("d1", DWORD), ("d2", CHAR)] + _pack_ = 1 +SIZEOF_SP_DEVICE_INTERFACE_DETAIL_DATA_A = ctypes.sizeof(dummy) + +SetupDiDestroyDeviceInfoList = ctypes.windll.setupapi.SetupDiDestroyDeviceInfoList +SetupDiDestroyDeviceInfoList.argtypes = [HDEVINFO] +SetupDiDestroyDeviceInfoList.restype = BOOL + +SetupDiGetClassDevs = ctypes.windll.setupapi.SetupDiGetClassDevsA +SetupDiGetClassDevs.argtypes = [ctypes.POINTER(GUID), PCTSTR, HWND, DWORD] +SetupDiGetClassDevs.restype = ValidHandle # HDEVINFO + +SetupDiEnumDeviceInterfaces = ctypes.windll.setupapi.SetupDiEnumDeviceInterfaces +SetupDiEnumDeviceInterfaces.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, ctypes.POINTER(GUID), DWORD, PSP_DEVICE_INTERFACE_DATA] +SetupDiEnumDeviceInterfaces.restype = BOOL + +SetupDiGetDeviceInterfaceDetail = ctypes.windll.setupapi.SetupDiGetDeviceInterfaceDetailA +SetupDiGetDeviceInterfaceDetail.argtypes = [HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA, DWORD, PDWORD, PSP_DEVINFO_DATA] +SetupDiGetDeviceInterfaceDetail.restype = BOOL + +SetupDiGetDeviceRegistryProperty = ctypes.windll.setupapi.SetupDiGetDeviceRegistryPropertyA +SetupDiGetDeviceRegistryProperty.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD] +SetupDiGetDeviceRegistryProperty.restype = BOOL + + +GUID_CLASS_COMPORT = GUID(0x86e0d1e0L, 0x8089, 0x11d0, + (ctypes.c_ubyte*8)(0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73)) + +DIGCF_PRESENT = 2 +DIGCF_DEVICEINTERFACE = 16 +INVALID_HANDLE_VALUE = 0 +ERROR_INSUFFICIENT_BUFFER = 122 +SPDRP_HARDWAREID = 1 +SPDRP_FRIENDLYNAME = 12 +SPDRP_LOCATION_INFORMATION = 13 +ERROR_NO_MORE_ITEMS = 259 + +def comports(available_only=True): + """This generator scans the device registry for com ports and yields + (order, port, desc, hwid). If available_only is true only return currently + existing ports. Order is a helper to get sorted lists. it can be ignored + otherwise.""" + flags = DIGCF_DEVICEINTERFACE + if available_only: + flags |= DIGCF_PRESENT + g_hdi = SetupDiGetClassDevs(ctypes.byref(GUID_CLASS_COMPORT), None, NULL, flags); + #~ for i in range(256): + for dwIndex in range(256): + did = SP_DEVICE_INTERFACE_DATA() + did.cbSize = ctypes.sizeof(did) + + if not SetupDiEnumDeviceInterfaces( + g_hdi, + None, + ctypes.byref(GUID_CLASS_COMPORT), + dwIndex, + ctypes.byref(did) + ): + if ctypes.GetLastError() != ERROR_NO_MORE_ITEMS: + raise ctypes.WinError() + break + + dwNeeded = DWORD() + # get the size + if not SetupDiGetDeviceInterfaceDetail( + g_hdi, + ctypes.byref(did), + None, 0, ctypes.byref(dwNeeded), + None + ): + # Ignore ERROR_INSUFFICIENT_BUFFER + if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: + raise ctypes.WinError() + # allocate buffer + class SP_DEVICE_INTERFACE_DETAIL_DATA_A(ctypes.Structure): + _fields_ = [ + ('cbSize', DWORD), + ('DevicePath', CHAR*(dwNeeded.value - ctypes.sizeof(DWORD))), + ] + def __str__(self): + return "DevicePath:%s" % (self.DevicePath,) + idd = SP_DEVICE_INTERFACE_DETAIL_DATA_A() + idd.cbSize = SIZEOF_SP_DEVICE_INTERFACE_DETAIL_DATA_A + devinfo = SP_DEVINFO_DATA() + devinfo.cbSize = ctypes.sizeof(devinfo) + if not SetupDiGetDeviceInterfaceDetail( + g_hdi, + ctypes.byref(did), + ctypes.byref(idd), dwNeeded, None, + ctypes.byref(devinfo) + ): + raise ctypes.WinError() + + # hardware ID + szHardwareID = ctypes.create_string_buffer(250) + if not SetupDiGetDeviceRegistryProperty( + g_hdi, + ctypes.byref(devinfo), + SPDRP_HARDWAREID, + None, + ctypes.byref(szHardwareID), ctypes.sizeof(szHardwareID) - 1, + None + ): + # Ignore ERROR_INSUFFICIENT_BUFFER + if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: + raise ctypes.WinError() + + # friendly name + szFriendlyName = ctypes.create_string_buffer(1024) + if not SetupDiGetDeviceRegistryProperty( + g_hdi, + ctypes.byref(devinfo), + SPDRP_FRIENDLYNAME, + None, + ctypes.byref(szFriendlyName), ctypes.sizeof(szFriendlyName) - 1, + None + ): + # Ignore ERROR_INSUFFICIENT_BUFFER + if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: + #~ raise ctypes.WinError() + # not getting friendly name for com0com devices, try something else + szFriendlyName = ctypes.create_string_buffer(1024) + if SetupDiGetDeviceRegistryProperty( + g_hdi, + ctypes.byref(devinfo), + SPDRP_LOCATION_INFORMATION, + None, + ctypes.byref(szFriendlyName), ctypes.sizeof(szFriendlyName) - 1, + None + ): + port_name = "\\\\.\\" + szFriendlyName.value + order = None + else: + port_name = szFriendlyName.value + order = None + else: + try: + m = re.search(r"\((.*?(\d+))\)", szFriendlyName.value) + #~ print szFriendlyName.value, m.groups() + port_name = m.group(1) + order = int(m.group(2)) + except AttributeError, msg: + port_name = szFriendlyName.value + order = None + yield order, port_name, szFriendlyName.value, szHardwareID.value + + SetupDiDestroyDeviceInfoList(g_hdi) + + +if __name__ == '__main__': + import serial + print "-"*78 + print "Serial ports" + print "-"*78 + for order, port, desc, hwid in sorted(comports()): + print "%-10s: %s (%s) ->" % (port, desc, hwid), + try: + serial.Serial(port) # test open + except serial.serialutil.SerialException: + print "can't be openend" + else: + print "Ready" + print + # list of all ports the system knows + print "-"*78 + print "All serial ports (registry)" + print "-"*78 + for order, port, desc, hwid in sorted(comports(False)): + print "%-10s: %s (%s)" % (port, desc, hwid) diff --git a/mavlink/share/pyshared/pymavlink/tools/images/gtk-quit.gif b/mavlink/share/pyshared/pymavlink/tools/images/gtk-quit.gif new file mode 100644 index 0000000000..3cce0867b9 Binary files /dev/null and b/mavlink/share/pyshared/pymavlink/tools/images/gtk-quit.gif differ diff --git a/mavlink/share/pyshared/pymavlink/tools/images/media-playback-pause.gif b/mavlink/share/pyshared/pymavlink/tools/images/media-playback-pause.gif new file mode 100644 index 0000000000..4dc439b786 Binary files /dev/null and b/mavlink/share/pyshared/pymavlink/tools/images/media-playback-pause.gif differ diff --git a/mavlink/share/pyshared/pymavlink/tools/images/media-playback-start.gif b/mavlink/share/pyshared/pymavlink/tools/images/media-playback-start.gif new file mode 100644 index 0000000000..ec41363995 Binary files /dev/null and b/mavlink/share/pyshared/pymavlink/tools/images/media-playback-start.gif differ diff --git a/mavlink/share/pyshared/pymavlink/tools/images/media-playback-stop.gif b/mavlink/share/pyshared/pymavlink/tools/images/media-playback-stop.gif new file mode 100644 index 0000000000..306271a89e Binary files /dev/null and b/mavlink/share/pyshared/pymavlink/tools/images/media-playback-stop.gif differ diff --git a/mavlink/share/pyshared/pymavlink/tools/images/media-seek-backward.gif b/mavlink/share/pyshared/pymavlink/tools/images/media-seek-backward.gif new file mode 100644 index 0000000000..23fcf6d823 Binary files /dev/null and b/mavlink/share/pyshared/pymavlink/tools/images/media-seek-backward.gif differ diff --git a/mavlink/share/pyshared/pymavlink/tools/images/media-seek-forward.gif b/mavlink/share/pyshared/pymavlink/tools/images/media-seek-forward.gif new file mode 100644 index 0000000000..3439c54fd2 Binary files /dev/null and b/mavlink/share/pyshared/pymavlink/tools/images/media-seek-forward.gif differ diff --git a/mavlink/share/pyshared/pymavlink/tools/images/player_end.gif b/mavlink/share/pyshared/pymavlink/tools/images/player_end.gif new file mode 100644 index 0000000000..9496957d22 Binary files /dev/null and b/mavlink/share/pyshared/pymavlink/tools/images/player_end.gif differ diff --git a/mavlink/share/pyshared/pymavlink/tools/mavplayback.py b/mavlink/share/pyshared/pymavlink/tools/mavplayback.py new file mode 100644 index 0000000000..50a6fd45dd --- /dev/null +++ b/mavlink/share/pyshared/pymavlink/tools/mavplayback.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python + +''' +play back a mavlink log as a FlightGear FG NET stream, and as a +realtime mavlink stream + +Useful for visualising flights +''' + +import sys, time, os, struct +import Tkinter + +# allow import from the parent directory, where mavlink.py is +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) + +import fgFDM + +from optparse import OptionParser +parser = OptionParser("mavplayback.py [options]") + +parser.add_option("--planner",dest="planner", action='store_true', help="use planner file format") +parser.add_option("--condition",dest="condition", default=None, help="select packets by condition") +parser.add_option("--gpsalt", action='store_true', default=False, help="Use GPS altitude") +parser.add_option("--mav10", action='store_true', default=False, help="Use MAVLink protocol 1.0") +parser.add_option("--out", help="MAVLink output port (IP:port)", + action='append', default=['127.0.0.1:14550']) +parser.add_option("--fgout", action='append', default=['127.0.0.1:5503'], + help="flightgear FDM NET output (IP:port)") +parser.add_option("--baudrate", type='int', default=57600, help='baud rate') +(opts, args) = parser.parse_args() + +if opts.mav10: + os.environ['MAVLINK10'] = '1' +import mavutil + +if len(args) < 1: + parser.print_help() + sys.exit(1) + +filename = args[0] + + +def LoadImage(filename): + '''return an image from the images/ directory''' + app_dir = os.path.dirname(os.path.realpath(__file__)) + path = os.path.join(app_dir, 'images', filename) + return Tkinter.PhotoImage(file=path) + + +class App(): + def __init__(self, filename): + self.root = Tkinter.Tk() + + self.filesize = os.path.getsize(filename) + self.filepos = 0.0 + + self.mlog = mavutil.mavlink_connection(filename, planner_format=opts.planner, + robust_parsing=True) + self.mout = [] + for m in opts.out: + self.mout.append(mavutil.mavlink_connection(m, input=False, baud=opts.baudrate)) + + self.fgout = [] + for f in opts.fgout: + self.fgout.append(mavutil.mavudp(f, input=False)) + + self.fdm = fgFDM.fgFDM() + + self.msg = self.mlog.recv_match(condition=opts.condition) + if self.msg is None: + sys.exit(1) + self.last_timestamp = getattr(self.msg, '_timestamp') + + self.paused = False + + self.topframe = Tkinter.Frame(self.root) + self.topframe.pack(side=Tkinter.TOP) + + self.frame = Tkinter.Frame(self.root) + self.frame.pack(side=Tkinter.LEFT) + + self.slider = Tkinter.Scale(self.topframe, from_=0, to=1.0, resolution=0.01, + orient=Tkinter.HORIZONTAL, command=self.slew) + self.slider.pack(side=Tkinter.LEFT) + + self.clock = Tkinter.Label(self.topframe,text="") + self.clock.pack(side=Tkinter.RIGHT) + + self.playback = Tkinter.Spinbox(self.topframe, from_=0, to=20, increment=0.1, width=3) + self.playback.pack(side=Tkinter.BOTTOM) + self.playback.delete(0, "end") + self.playback.insert(0, 1) + + self.buttons = {} + self.button('quit', 'gtk-quit.gif', self.frame.quit) + self.button('pause', 'media-playback-pause.gif', self.pause) + self.button('rewind', 'media-seek-backward.gif', self.rewind) + self.button('forward', 'media-seek-forward.gif', self.forward) + self.button('status', 'Status', self.status) + self.flightmode = Tkinter.Label(self.frame,text="") + self.flightmode.pack(side=Tkinter.RIGHT) + + self.next_message() + self.root.mainloop() + + def button(self, name, filename, command): + '''add a button''' + try: + img = LoadImage(filename) + b = Tkinter.Button(self.frame, image=img, command=command) + b.image = img + except Exception: + b = Tkinter.Button(self.frame, text=filename, command=command) + b.pack(side=Tkinter.LEFT) + self.buttons[name] = b + + + def pause(self): + '''pause playback''' + self.paused = not self.paused + + def rewind(self): + '''rewind 10%''' + pos = int(self.mlog.f.tell() - 0.1*self.filesize) + if pos < 0: + pos = 0 + self.mlog.f.seek(pos) + self.find_message() + + def forward(self): + '''forward 10%''' + pos = int(self.mlog.f.tell() + 0.1*self.filesize) + if pos > self.filesize: + pos = self.filesize - 2048 + self.mlog.f.seek(pos) + self.find_message() + + def status(self): + '''show status''' + for m in sorted(self.mlog.messages.keys()): + print(str(self.mlog.messages[m])) + + + + def find_message(self): + '''find the next valid message''' + while True: + self.msg = self.mlog.recv_match(condition=opts.condition) + if self.msg is not None and self.msg.get_type() != 'BAD_DATA': + break + if self.mlog.f.tell() > self.filesize - 10: + self.paused = True + break + self.last_timestamp = getattr(self.msg, '_timestamp') + + def slew(self, value): + '''move to a given position in the file''' + if float(value) != self.filepos: + pos = float(value) * self.filesize + self.mlog.f.seek(int(pos)) + self.find_message() + + + def next_message(self): + '''called as each msg is ready''' + + msg = self.msg + if msg is None: + self.paused = True + + if self.paused: + self.root.after(100, self.next_message) + return + + speed = float(self.playback.get()) + timestamp = getattr(msg, '_timestamp') + + now = time.strftime("%H:%M:%S", time.localtime(timestamp)) + self.clock.configure(text=now) + + if speed == 0.0: + self.root.after(200, self.next_message) + else: + self.root.after(int(1000*(timestamp - self.last_timestamp) / speed), self.next_message) + self.last_timestamp = timestamp + + while True: + self.msg = self.mlog.recv_match(condition=opts.condition) + if self.msg is None and self.mlog.f.tell() > self.filesize - 10: + self.paused = True + return + if self.msg is not None and self.msg.get_type() != "BAD_DATA": + break + + pos = float(self.mlog.f.tell()) / self.filesize + self.slider.set(pos) + self.filepos = self.slider.get() + + if msg.get_type() != "BAD_DATA": + for m in self.mout: + m.write(msg.get_msgbuf().tostring()) + + if msg.get_type() == "GPS_RAW": + self.fdm.set('latitude', msg.lat, units='degrees') + self.fdm.set('longitude', msg.lon, units='degrees') + if opts.gpsalt: + self.fdm.set('altitude', msg.alt, units='meters') + + if msg.get_type() == "VFR_HUD": + if not opts.gpsalt: + self.fdm.set('altitude', msg.alt, units='meters') + self.fdm.set('num_engines', 1) + self.fdm.set('vcas', msg.airspeed, units='mps') + + if msg.get_type() == "ATTITUDE": + self.fdm.set('phi', msg.roll, units='radians') + self.fdm.set('theta', msg.pitch, units='radians') + self.fdm.set('psi', msg.yaw, units='radians') + self.fdm.set('phidot', msg.rollspeed, units='rps') + self.fdm.set('thetadot', msg.pitchspeed, units='rps') + self.fdm.set('psidot', msg.yawspeed, units='rps') + + if msg.get_type() == "RC_CHANNELS_SCALED": + self.fdm.set("right_aileron", msg.chan1_scaled*0.0001) + self.fdm.set("left_aileron", -msg.chan1_scaled*0.0001) + self.fdm.set("rudder", msg.chan4_scaled*0.0001) + self.fdm.set("elevator", msg.chan2_scaled*0.0001) + self.fdm.set('rpm', msg.chan3_scaled*0.01) + + if msg.get_type() == 'STATUSTEXT': + print("APM: %s" % msg.text) + + if msg.get_type() == 'SYS_STATUS': + self.flightmode.configure(text=self.mlog.flightmode) + + if msg.get_type() == "BAD_DATA": + if mavutil.all_printable(msg.data): + sys.stdout.write(msg.data) + sys.stdout.flush() + + if self.fdm.get('latitude') != 0: + for f in self.fgout: + f.write(self.fdm.pack()) + + +app=App(filename) diff --git a/nuttx/.version b/nuttx/.version new file mode 100755 index 0000000000..b001d07f7d --- /dev/null +++ b/nuttx/.version @@ -0,0 +1,6 @@ +#!/bin/bash + +CONFIG_VERSION_STRING="0.0" +CONFIG_VERSION_MAJOR=0 +CONFIG_VERSION_MINOR=0 +CONFIG_VERSION_BUILD=0 diff --git a/nuttx/COPYING b/nuttx/COPYING new file mode 100644 index 0000000000..82d3a8a58a --- /dev/null +++ b/nuttx/COPYING @@ -0,0 +1,179 @@ +COPYING -- Describes the terms under which Nuttx is distributed. A +copy of the BSD-style licensing is included in this file. In my +words -- I believe that you should free to use NuttX in any +environment, private, private, commercial, open, closed, etc. +provided only that you repect the modest copyright notices as +described in license (below). Please feel free to contact me if you +have any licensing concerns. + +NuttX +^^^^^^ + +License for NuttX in general (authorship of individual files may vary): +/************************************************************************* + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *************************************************************************/ + +FAT Long File Names +^^^^^^^^^^^^^^^^^^^ + + NOTE: If CONFIG_FAT_LFN is defined in your NuttX configuration file, then + there may be some legal, patent issues. The following was extracted from + the entry "File Allocation Table from Wikipedia, the free encyclopedia: + + "On December 3, 2003 Microsoft announced it would be offering licenses + for use of its FAT specification and 'associated intellectual property', + at the cost of a US$0.25 royalty per unit sold, with a $250,000 maximum + royalty per license agreement. + + o "U.S. Patent 5,745,902 (http://www.google.com/patents?vid=5745902) - + Method and system for accessing a file using file names having + different file name formats. ... + o "U.S. Patent 5,579,517 (http://www.google.com/patents?vid=5579517) - + Common name space for long and short filenames. ... + o "U.S. Patent 5,758,352 (http://www.google.com/patents?vid=5758352) - + Common name space for long and short filenames. ... + o "U.S. Patent 6,286,013 (http://www.google.com/patents?vid=6286013) - + Method and system for providing a common name space for long and + short file names in an operating system. ... + + "Many technical commentators have concluded that these patents only cover + FAT implementations that include support for long filenames, and that + removable solid state media and consumer devices only using short names + would be unaffected. ..." + + So you have been forewarned: Use the long filename at your own risk! + +uIP +^^^ + +Many lower-level networking components of NuttX derive from uIP which +has a similar BSD style license: + + Copyright (c) 2001-2003, Adam Dunkels. + All rights reserved. + +IGMP +^^^^ + +IGMP support, if enabled in uIP, adds additional logic by Steve Reynolds: + + Copyright (c) 2002 CITEL Technologies Ltd. + All rights reserved. + +The HID Parser in drivers/usbhost +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Adapted from the LUFA Library (MIT license): + + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + dean [at] fourwalledcubicle [dot] com, www.lufa-lib.org + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. + +Certain functions in the NuttX C-library derive from other BSD-compatible +sources: + +fs/nfs: +^^^^^^^ + + NFS: + + Copyright (c) 1989, 1991, 1993, 1995 The Regents of the University of + California. All rights reserved. + + and RPC also has: + + Copyright (c) 2004 The Regents of the University of Michigan. + Copyright (c) 2004 Weston Andros Adamson . + Copyright (c) 2004 Marius Aamodt Eriksen . + + The University of Michigan uses a modified BSD license equivalent to + the NuttX license. The University of California code uses the original + BSD license and requires that I state the following: + + "This product includes software developed by the University of + California, Berkeley and its contributors." + +strtod(): +^^^^^^^^ + + Copyright (C) 2002 Michael Ringgaard. All rights reserved. + Copyright (C) 2006-2007 H. Peter Anvin. + +dtoa(): +^^^^^^ + + If you enable floating point conversions with CONFIG_LIBC_FLOATINGPOINT, + then some files with an unmodified BSD license will be included. That + license is similar to the above (modified) BSD license, but has an + additional requirement that I state the following: + + "This product includes software developed by the University of + California, Berkeley and its contributors." + +Documents/rss.gif +^^^^^^^^^^^^^^^^^ + + Licensed under Creative Commons Attribution-Share Alike 2.5 Generic + license: + + You are free: + + * to share – to copy, distribute and transmit the work + * to remix – to adapt the work + + Under the following conditions: + + * attribution – You must attribute the work in the manner specified + by the author or licensor (but not in any way that suggests that + they endorse you or your use of the work). + * share alike – If you alter, transform, or build upon this work, + you may distribute the resulting work only under the same or + similar license to this one. diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog new file mode 100644 index 0000000000..9d2f5ea6b0 --- /dev/null +++ b/nuttx/ChangeLog @@ -0,0 +1,3123 @@ +0.1.0 2007-03-09 Gregory Nutt + + * Initial Release + * Support for Linux user mode simulation and TI + TMS320C5471 (Arm7) provided + +0.1.1 2007-03-14 Gregory Nutt + + * Corrected an error in interrupt level context switching + for C5471 + * Added fgets() and gets() logic; verified c5471 console read. + * Corrected error in reading from the C5471 serial port: + Improper use of semaphore can cause deadlock. + * Fixed an error in the memory cleanup: The idle task + cannot take sempahores (because it must always be ready + to run). + * Tasks can now accept a configurable maximum number of + input parameters (argc) + * _task_init() was divided into separate functions that + require fewer parameters. This was necessary to keep + the stack usage down for the 8051/2 (which has only + 256 bytes of stack). + * Attempts to use C5471 console from interrupt handlers + can cause errors. Added a special path for this case. + * Refuse calls to sem_wait and sem_trywait from interrupt + handlers. This was happening because interrupt handlers + were calling printf-like functions. + * Added strtok() and strtok_r() + * Added a simple shell called nsh (see examples/nsh). + * Platform support for 8052 is complete but not stable + when the timer interrupt is enabled. Seems to be an + issue when SP enters indirect address space. + * Documentation updates + +0.1.2 2007-03-19 Gregory Nutt + + * Add dirent.h, opendir(), readdir(), closedir(), etc. + * Add strerror() + * Added 'ls' command to nsh + * Added C5471 watchdog driver + * Fixed another bug where free() is called from IDLE task. + Can't do this; the caller must be able to wait for access + to memory. + * Fixed bugs associated with debug output: + Cannot do dbg() in middle of context switch logic. + because it may require use of semaphores and cause + additional context switches. lldbg() is safe. + * Interrupt must be disabled throughout all context switches. + * Separated C5471 serial driver; a shareable part is + in drivers/. ; the C5471 specific part is in arch/C5471. + serial.h defines the interface. + * Fixed mq_receive() and mq_send(): bad memcpy() + * Fixed C5471 signal deliver logic: use of dbg() and + other actions by use signal handler can alter errno. + need to protect errno during signal handling. + * Fixed uninitialized variable in filesystem that could + cause various problems + * Added a test for roundrobin scheduler. + +0.2.1 2007-03-22 Gregory Nutt + + * Fix error in handing signed decimal in vsprintf(). + * Major restructuring of header files to get closer to + POSIX compliance. + * Eliminate compilation warnings that crept into recent check-ins + * Add kill() + * Added support for POSIX timers + * Some Documentation updates + * Added support for the Neuros OSD / DM320 + +0.2.2 2007-03-26 Gregory Nutt + * Created the configs/ directory; separated board configuration + from processor architecture logic + * Add memory leak detection test to examples/ostest + * Corrected memory leak in OS pthread join logic + * Corrected memory leaks in examples/ostest due to failures + to join or detach from pthreads. + * Added pthread_once(), pthread_kill(), pthread_sigmask() + * Added pthread_barrierattr_*() APIs + * Added pthread_barrier_init(), pthread_barrier_destroy(), and + pthread_barrier_wait(); + * Added pthread barrier test + * Added protection so that errno cannot be modified from + interrupt handling. + * sched_setparam(), sched_setscheduler() now correctly set + errno; pthread_setscheduler() now returns the correct errno. + * Added pthread_setschedprio(). + * Added directories to hold board-specific header files + * Added directories to hold board-specific drivers + +0.2.3 2007-03-29 Gregory Nutt + + * mq_receive and mq_send now return errno's appropriately + * mq_receive and mq_send are now correctly awakened by signals. + * Fixed an unmatched sched_lock/unlock pair in task_delete(). + * sched_lock must be called in _exit() because operation of + task_delete() can cause pending tasks to be merged and a + context switch to occur. + * Added mq_timedreceive() and mq_timedsend() + * signal mask is now inherited by both child tasks and threads. + * Improved sharebility of stdout among pthreads (only). Nothing + was broken, but by moving the mutual exclusion logic to a + higher level, the printf output is more readable. + * Fixed a bug in file system cleanup: A list was being deleted + before the buffers contained in the list. + * Fixed a bug in the wait-for-message-queue-not-empty logic. + * Added a test of timed mqueue operations; detected and corrected + some mqueue errors. + * Identified and corrected a race condition associated with + pthread_join. In the failure condition, memory was being + deallocated while still in use. + +0.2.4 2007-04-28 Gregory Nutt + + * Verified c5471 build under Cygwin on WinXP + * Makesystem changes to better support different SoCs. + * Made arch/c5471/include and arch/dm320/include identical in + preparation for merging into arch/arm + * Logic from arch/c5471 and arch/dm320 combined into arch/arm. + arch/c5471 and arch/dm320 are deprecated and will be removed + when the new c5471 and dm320 logic is verified. + +0.2.5 2007-05-19 Gregory Nutt + + * Corrected some build/configuration issues introduced with the + last release. + * Added support for the NXP 214x processor on the mcu123.com lpc214x + development board (untested) + * Added support for block devices. + * Simulated target now exports a VFAT filesystem + * Begin support for VFAT filesystem (missing functionality) + * Added mount() and umount() + * Fix bug in memcmp return value + * Fix errors in timeslice calculation (several places) + * Added missing irqrestore() in timer_deleteall(). + * close() was not closing the underlying device. + * Added fsync() + * Added strspn() and strcspn() + +0.2.6 2007-05-26 Gregory Nutt + + * Added unlink(), mkdir(), rmdir(), and rename() + * Fixed several serious FAT errors with oflags handling (&& instead of &) + * Added FAT support for unlink(), mkdir(), rmdir(), and rename + * Added FAT support for opendir(), closedir(), readdir(), seekdir(), + telldir(), rewindir(). + * Fixed ARM compilation errors introduced in 0.2.5 (that is what I get + for only testing on the simulation). + +0.2.7 2007-06-09 Gregory Nutt + + * Added stat() to fs layer and to FAT + * Fixed reference counting errors associated with mounted filesystems + * Added fat_getattrib() and fat_setattrib() + * Added statfs() to fs layer and to FAT + * Correct file name extension in tools/zipme.sh + * Fix error in dependencies in 8051/2 Makefile + * sched/Makefile: Don't build sleep() or usleep() if signals are disabled + * sched/sched_setparam.c: Remove redundant disabling of interrupts + * sched/usleep.c: Fixed nsec calculation + * lib/lib_strcspn.c: Function incorrectly named strspn(). + * examples/ostest/main.c: Errors in SDCC version of a memcpy() call + * examples/ostest/sighand.c: Don't call fflush() if streams are disabled + * include/limits.h, include/time.h, sched/clock_internal.h: A support for + using selectable system timer frequency. + * Fixed error in mountpoint related conditional compilation introduced + in 0.2.5 + * Restructured some Makefiles to better handle enabling and disabling + NuttX features without having so much conditional compilation in the + source files. + * tools/mkconfig.c: No longer depends on asprintf() and _GNU_SOURCE and + so should now build in non-GNU, non-GLIBC environments. + * include/nuttx/compiler.h: Fix for using SDCC with the Z80. + * include/assert.h & arch/pjrc-8051/src/up_assert.c: SDCC does support + __FILE__and __LINE__ (not tested) + * examples/ostest/barrier.c: Don't call usleep() when signals are + disabled. + +0.2.8 2007-07-02 Gregory Nutt + * tools/Makefile.mkconfig: Under Cygwin, executable has a different name + * tools/mkdeps.sh & arch/arm/src/Makefile: Corrected a problem makeing dependencies + * tools/zipme.sh: Force directory name to be nuttx-xx.yy.zz + * fs/fs_opendir.c: Correct errors in semaphore usage that can cause deadlock. + * lib/lib_getopt.c: Added getopt() support + * examples/nsh/: NSH now supports cat, mount, umount, and mkdir. ls supports + -l -s, and -R + * Added basic OS support to manage environment variables: environment + storage, cloning on task creation, sharing on pthread creation, destruction + on thread/task exit. + * Add environment variables APIs: environ, getenv, putenv, clearenv, setenv, + unsetenv + * Correct an error in realloc() when the block is extended "down" in memory. + In this case, the old memory contents need to be copied to the new location + and an allocated bit was not being set. + * examples/ostest/: Added an environment variable test. + * examples/nsh/: Break into several files. + * lib/: Added strrchr, basename, dirname + * examples/nsh/: Add cp, rm, rmdir, set, unset commands. echo will now print + environment variables. + +0.3.0 2007-11-06 Gregory Nutt + + * Imported uIP into the tree (see + http://www.sics.se/~adam/uip/index.php/Main_Page) + * Adding socket(), bind(), connect() + * Added snprintf() + * Added send() and sendto(); integrate write() and close() with socket descriptors. + * Added recv() and recvfrom(). + * Added getsockopt() and setsockopt() + * Documentation updated to address socket interfaces. + * Implemented receive timeouts via setsockopt(SO_RCVTIMEO). + * Provide support for multiple network devices + * Implement socket ioctl() calls to set addresses + * Added listen() and accept() + * Added DM90x0 Ethernet driver + * ARP timer is now built into the network layer + * Basic client functionality verified: TCP socket(), bind(), connect(), recv(), send(). + +0.3.1 2007-11-19 Gregory Nutt + + * Separated net/uip/uip.c into several functions in several files. + * Corrected a TCP problem where packets were dropped because there was no + recv() in place but the packet was being ACKed. There are still TCP + recv buffering issues, but this is part of a larger buffering issue. + * Basic server functionality verified: TCP listen(), accept() + * Fix DM90x0 driver problem that caused TX overruns + * Add strncmp() + * Added TCP/IP read-ahead buffer to minimize failed ACKs and packet loss. + +0.3.2 2007-11-23 Gregory Nutt + + * Add strcat() and strncat() + * Integrated uIP micro webserver + * Corrected a serious bug in TCP queue management + * Fix leak in socket close logic + * Add TX notification to driver so that it can respond faster to + the availability of TX data. + * Moved urgent data info into device structure. + * TCP and ICMP protocols can now be disabled. + * Added UDP test in examples/udp + * Verified/debugged UDP socket(), bind(), sendto() and recvfrom() logic + using examples/udp + * recvfrom() and accept() now correctly return the remote address. + * Fixed computation error in ntohl(). + +0.3.3 2007-11-28 Gregory Nutt + + * Removed unused uIP files + * sched/, mm/, and net/ subsystem debug can not be selectively enabled/disabled + * Correct socket close logic: needs to disconnect TCP socket on close + * uIP webserver now seems to be fully functional + * fs/ and lib/ subystem debug can not be selectively enabled/disabled + * Added vsnprintf + * Integrated uIP telnetd + * Add missing logic to read-ahead buffer logic + * examples/nettest uses larger buffers + * Improved ACK handling in send() to better handler deferred acknowledgements + and polling intervals. Greatly improves send performance. + +0.3.4 2007-12-10 Gregory Nutt + + * Added and partially verified DHCP server logic (netutils/dhcpd) + * Fix BROADCAST=y compilation problems + * Fix UDP recvfrom timeout bug + * Correct processing of input UDP broadcast packets. + * Verfied basic DHCP client functionality (netutils/dhcpc) + * Implemented send() timeout logic + * Added and verified a TELNETD front end to NSH (examples/nsh) + * Add a skeleton Ethernet device driver (drivers/net/skeleton.c) + * Added C5471 Ethernet device driver (arch/arm/src/c5471/c5471_ethernet.c) + * Found and fixed several problems in uIP when compiled for ARM with optimization. + +0.3.5 2007-12-18 Gregory Nutt + + * Added inet_ntoa() and ether_ntoa() + * Added netdev_foreach() to support traversal of registered network devices + * Added support for 'ifconfig' command to NSH (examples/nsh) + * Moved MAC and Ethernet definitions to net/ethernet.h + * Fix sim and DM90x0 compilation errors introduced in 0.3.4 + * Fixed errors in C5471 configuration files for examples/uip + * Modified DHCPC (netutils/dhcpc) so that it should work in environments where + there are more than one DHCPD server. + * NSH ifconfig command now shows uIP status as well (examples/nsh) + +0.3.6 2008-01-06 Gregory Nutt + + * Changes for use with SDCC compiler + * Added a simulated z80 target + * Fix deadlock errors when using stdio but with no buffering + * Add support for Pascal P-Code interpreter + +0.3.6.1 2008-01-07 Gregory Nutt + + * The initial 0.3.6 release including an error that prevented + building successfully if the Pascal add-on was + was not present. + +0.3.7 2008-01-31 Gregory Nutt + + * Added support for the Zilog Z16F using the Zilog Z16F2800100ZCOG + Development Kit. + * Add support toolchains that do not support making of dependencies + * Fix Cygwin build with spaces in directory names + * Name make system changes to deal with non-GNU toolchains (i.e., Zilog) + * Add support for Windows native toolchains that cannot follow Cygwin soft links + * Modified serial driver interface to handle hardware with non-16550A-like + interrupt architecture (like the Z16F) + * Added a "dumb" serial console driver to simplify OS bringup + * Corrected a bug that caused the errno value of one task to be clobbered + when a different task exits. Affects all architectures. + +0.3.8 2008-02-10 Gregory Nutt + + * Added a test case to verify the Pascal P-Code interpreter + * Added /dev/zero + * 'errno' is now defined to be *get_errno_ptr() with no name conflicts + * Added lseek() and fseek() + * Integrated Pascal interpreter test case on the simulation platform. Needs + pascal-0.1.1. + * Add Pascal test case on the z16f platform. Needs pascal-0.1.2 (does not + yet work due to some tool issues). + * C buffered I/O fixes: + - Fix fflush() return value, + - Add correct fflush behavior when the FILE argument is null. + - Add logic to a correctly handle read/write access on the same FILE + - fseek() flushes read/write data when before moving the file pointer + - When read data is flushed, reposition the file pointer to account for + buffered, but unread data + * Pascal P-Code files are now standardized to big-endian for portability + * Fix a build problem with z80 and SDCC 2.7.0 (format of a map file changed) + (see bug 1887170) + * Pascal P-Code runtime now compiles with the SDCC toolchain. + * Added a generic CAN driver. This driver is untested as of this writing. + * Corrected DM320 UART configuration problem + +0.3.9 2008-03-09 Gregory Nutt + + * Began adding support for the ZiLOG Z8Encore! microcontroller for the Z8Encore000ZCO + development board and the Z8F6403 part. + * Fix broken 'clean' target on z80sim configurations + * Re-structure arch/z80 to provide support for all ZiLOG 8-bit microcontrollers (ez8 + in particular for now). + * Add support for TRS80-Model 3 based on the xtrs emulation (http://www.tim-mann.org/xtrs.html) + Per patch from Jacques Pelletier. + * In all shell scripts, change #!/bin/sh to #!/bin/bash to resolve problems in + Ubuntu where /bin/sh is a link to dash. + * Z8Encore! port verified on ZDS-II instruction set/chip simulator. + +0.3.10 2008-05-15 Gregory Nutt + + * Add support for the ZiLOG EZ80Acclaim microcontrooler (EZ80F91 chip). + * Add configuration for the ZiLOG z8f64200100kit development kit, Z8F6423 part. + * Add configuration for the ZiLOG ez80f0910200kitg development kit, EZ80F091 part. + * Correct critical list handling errors in task shutdown logic: One in timer + deletion logic (timer_delete.c) and one in stream logic (lib_init.c) reported + by kwonsk. + +0.3.11 2008-06-01 Gregory Nutt + + * Add support for recursive mutexes. + * Eliminate a memory leak: contained watchdog instance was not being + deleted with a POSIX timer was deleted reported by kwonsk. + * Eliminate a deadlock condition in opendir() reported by kwonsk. + * Fix several FAT filesystem problems reported by kwonsk (Changes not yet + verified). + * Host simulator no longer uses Linux system calls directly; Now works with Cygwin. + * Fix an error that occurs when a POSIX timer is deleted by the timer signal handler. + * Add logic to allow the examples/ostest to be run repetitively as an endurance test. + * Add a ramdisk block driver + +0.3.12 2008-08-10 Gregory Nutt + + * Improved solution to POSIX timer lifetime controls bug fixed in 0.3.11. + * Add test for recursive mutexes + * Correct bug in recursive mutex logic + * Add mkfifo() + * Add pipe() and test for both pipes and fifos + * Attempts to open a FIFO will now block until there is at least one writer + * Add test/Fixed errors in FIFO reader/writer interlocks + * Removed limitation: task_create() was only dup'ing 3 file descriptors (now + dups all open file descriptors). + * Added a test for redirection of stdio through pipes + * Fixed error in dup and dup2: Must call open/close methods in fs/driver so that + driver can correctly maintain open reference counts. + * Same issue on closing file descriptors in exit() + * Fixed in error in stdio flush logic. Needed ssize_t vs size_t for error + check. + * Moved all FAT related files from fs to fs/fat + * Implemented mkfatfs(), a non-standard API to create a FAT filesystem on a + block device (not yet tested). + * Added a test for mkfatfs() on a RAM disk in examples/mount and verified + basic mkfatfs functionality for FAT12. + +0.3.13 2008-09-01 Gregory Nutt + + * NSH: Added mkfatfs, mkfifo, sleep, usleep and nice commands + * Fixed problem with console input in Cygwin-based simulator; NSH now works + with simulator. + * NSH will now execute commands in background + * sched_get_priority_max/min returned error on SCHED_RR + * Removed duplicate getenv() implementation in /lib + * Correct detection of End-of-File in fgets + * NSH: Implemented sh and crude script handler + * Fix prototype of read() and write(). Need to use ssize_t and size_t, not + int and unsigned int. + * NSH now supports redirection of command output + * NSH can now use both telnet and serial front ends together + * NSH: $variable can be used for any command value + * Fixed an error in opendir() that could cause an assertion to fail + inappropriately. + * Correct an error in the FAT that caused files opened for writing with + O_APPEND to fail. The file was not being properly positioned to the + end of the file in that case. + * NSH now supports last exit status $? + * NSH now supports if-then[-else]-fi construct + * NSH now supports comments beginning with '#' + * NSH now supports commands to inspect and modify memory + * NSH cat command now supports multiple files on command line + * Add chdir() and getcwd() + * Fix error in getopt() when called with argc==1 + * Fix error in stat() when used on the root directory + * NSH: Add cd and pwd commands and current working directory to all NSH + commands that refer to paths. + * Fix errors and warnings introduced into Linux sim build because of recent + Cygwin-based sim changes + * NSH: Add mem command to display heap usage + * Added telnet NSH configuration for Neuros OSD. + * Basic integration of concurrent telnet/serial NSH functional on Neuros + OSD. + * Fixed a critical bug that affects the way that environment variables are + shared amongst pthreads. + * uIP port enhance to support multi-threaded, concurrent socket access. So, + for example, one thread can be reading from a socket while another is + writing to the socket. + +0.3.14 2008-09-08 Gregory Nutt + * FAT FS now uses position variable in struct file. This simplifies operations + like ftell(). + * fseek() needs to discard bytes buffered by ungetc(). + * Corrected ftell() return value. + * Added fsetpos() and fgetpos(). + * NSH: Now supports 'test' and '[' commands + * Correct error in send() timeout logic. + * Correct error in multi-threaded socket handling in send() and sendto(). + Outgoing data could overwrite incoming data. + * Add support to uIP for application access to ICMP protocol stacks; Add + ping request logic. + * NSH: Add ping command + * Correct IP checksum calculation in ICMP and UDP message send logic. + * NSH: Created an HTML document and a more detailed README file describing NSH. + * Added basic TFTP client logic (netutils/tftpc). + * NSH: Add get and put commands to support TFTP get and put operations. + * NSH: Added a mkrd command that will create a RAMDISK that can be formatted + and mounted. + * Corrected a critical bug that prevent recvfrom from receiving packets from + any remote UDP port. + * NSH: Add hexadecimal dump command (xd) + * Fixed several critical bugs with regard to fat reading and writing and FAT12 + accesses. Basically the FAT FS only worked with my tiny test files and test + cases. A lot of stronger FAT tested is needed!! + * Fixed another FAT bug in implementation of FAT lseek; this prohibit correct + random access to large files. + +0.3.15 2008-09-20 Gregory Nutt + * Added support for ROMFS filesystem. + * Added a simple test the ROMFS filesystem (examples/romfs) + * NSH: Use ROMFS to provide an option for a start-up script at /etc/init.d/rcS + * Add definition of BIOC_XIPBASE ioctl and implement in RAM disk block driver. + This is a low level requirement for eXecute In Place (XIP) support. + * Add a FIOC_MMAP to perform memory mapping of a file and implemented the + ioctl command in the ROMFS filesystem. This is a requirement for eXecute + In Place (XIP) support. + * Add mmap() API with restricted capability (only for XIP support) + * Extend ROMFS test at /examples/romfs to verify mmap() and XIP support. + * Add support for Intel Hex format output using objcopy + * Completed the basic port of the NXP LPC2148 on the mcu123.com board. + The basic port includes successful booting, timer interrupts, serial console, + succesfully passing the examples/ostest, and a NuttShell (NSH) configuration. + * ARM architectures now support drivers/lowconsole.c + +0.3.16 2008-10-10 Gregory Nutt + * Added header files defining a common USB device controller architecture + * Added USB device side driver for the LPC214x + * Correct the frequency of system timer interrupts in the NXP LPC214x port + (off by 20x in nuttx-0.3.15) + * Add an option to set aside a separate stack for interrupt handling (ARM only). + This is useful when memory is constrained, there are multiple tasks, and + the interrupt stack requirement is high (as when USB is enabled). + * Added USB serial class device side driver (emulates Prolific PL2303 + serial-to-USB adaptor) + * Add LPC214x USB serial configuration; Add examples/usbserial test + * Added USB device side driver for the DM320 (untested at initial release) + * Fixed an error in a previous (post 0.3.15) check-in that broke the LPC214x + system timer. + * Fixed serial driver bugs related to (1) open counts and (2) recognizing + O_NONBLOCK on read. + * Fixed an error in read(); it was not setting the errno on errors returned + from the driver. + +0.3.17 2008-10-28 Gregory Nutt + * Incorporate patch "[2164503] nuttx-0.3.16 does not build for ARM with USB disabled" + * Reduced the amount of memory reserved for USB serial control requests. It + was unnecessarily large. + * Added LPC214x SPI1 driver to interface with MMC on mcu123.com board. + * Added a simple SPI-based MMC/SD block driver + * NSH: Add LPC214x-specific support to NSH; NSH now mounts any SD cards in the slot. + * FAT: Fix access to unaligned 32-bit values in partion table (start sector & size) + * Fixed a problem with a un-initialized variable in the USB serial driver. + * Added USB storage NXP LPC214x configuration + * Added a test for USB storage under examples/usbstorage + * Fixed a bug in the LPC214x USB driver: It was not properly clearing a HALTed + endpoints (other than EP) on receipt of CLEAR FEATURES request. + * Added USB storage class device side driver (BBB) + * Fixed a bug in the LPC214x USB driver: It was not properly handling request buffers + larger then the endpoint's max packet (DM320 driver also fixed, untested) + * Added logic to the USB device interface: A bit is needed to force the driver to + to terminate an IN transfer with a short packet (zero-length if necessary). + * Fix an error in the NXP LPC214x USB device driver that was causing corruption of + the request queue (M320 driver also fixed, untested) + * Correct another error in the NXP LPC214x USB device driver that caused read failures + when the request buffer size was larger than maxpacket. + * Numerous corrections/extensions to the USB tracing logic included in 0.3.16 (but + not integrated until 0.3.17) + * Fixed another bug in the NXP LPC214x USB device driver: After a stalled endpoint + is resumed (view CLEAR FEATURE), we must restart the IN (outgoing) queue. + +0.3.18 2008-11-16 Gregory Nutt + * Added port for the STMicro STR71x processor and configuration for the Olimex STR-P711 + board (STR71x testing is stalled because I have been unable to get OpenOCD to + communicate with my JTAG wiggler on Linux). + * Fix race condition workaround delay in LPC214X SPI logic. This was also the cause of the + very bad MMC/SD performance. + * Began port of the Hitachi SH-1 using the SH-1/US7032EVB1 board + * Re-built all configurations that use SDCC and Zilog toolchains to make sure they still + build (they didn't, but they do now). + * Fixed several erroneous "list empty" checks in the CAN driver. + * Hitachi SH-1 passes (reduced) examples/ostest; the examples/nsh test still fails. + There are remaining instabilities that make the port un-usable. The nature of these is + not understood; the behavior is that certain SH-1 instructions stop working as advertised. + This could be a silicon problem, some pipeline issue that is not handled properly by the + gcc 3.4.5 toolchain (which has very limit SH-1 support to begin with), or perhaps with the + CMON debugger. At any rate, I have exhausted all of the energy that I am willing to put + into this cool old processor for the time being. + * Renamed configuration item CONFIG_PROC_STACK_SIZE as CONFIG_IDLETHREAD_STACKSIZE: It now + only controls the size of the stack for the IDLE thread. Added CONFIG_USERMAIN_STACKSIZE: + This is the size of stack used with the user_start() thread is created. The two stacks + no longer have to be the same. + * Add a loop device that converts a file into a block device. + * Each NSH command can not be disabled through a configuration setting. All of these + settings make the configuration of NSH potentially complex but also allow it to squeeze + into very small memory footprints. + * Added a block to character (BCH) driver. This is kind of the reverse of the loop + device; it allows you access a block device like a character device. + * Added strcasecmp() and strncasecmp() + * NSH: Added the 'dd' command + * NSH: Added the 'losetup' command + * Fixed a FAT bug: After recent changes, it would mount a (invalid) FAT file system + even if the medium is not formatted! + * Corrected two important errors in FAT lseek implementation: (1) the sectors-per-cluster + value was being reset to "1" and (2) important lseek logic was omitted when the seek + position was zero. + * Fixed a bug in getopt(). It would fail if on certain combinations of terminal argument + types. + +0.3.19 2008-11-26 Gregory Nutt + * Add poll() and select() APIs (in the initial check-in, these work only with character devices) + * Add poll() methods to /dev/null, /dev/zero, pipes, fifos, and serial drivers. + * Add examples/poll for testing poll() and select() + * Fix hostile behavior of getc, fgetc, getchar, etc.: the serial driver was waiting for a + full buffer of read data before return. This means that getc would stall when it needed + to refill the input buffer. The old behavior (read full blocks) might be useful in other + contexts, so it is still available within the driver as a configuration option. + * Implement poll() and select() support for TCP/IP sockets + * Fixed an important bug in the TCP/IP buffering logic. When TCP/IP read-ahead is enabled + and not recv() is in-place when a TCP/IP packet is received, the packet is placed into + a read-ahead buffer. However, the old contents of the read-ahead buffer were not being + cleared and old data would contaminate the newly received buffer. + * Implemented support for connection backlog. The size of the backlog is specified by the + second argument of the standard listen() API. Hooks are provided to support poll()/select() + waiting for connections, with a subsequent call to accept() to use the backlogged connection. + * Fixed a minor bug in accept(). It should allow the address and addresslen values to be NULL + * Added first-cut definition for a framebuffer interface (and simulated framebuffer for testing + purposes only) + * Added fixed precision math support + * Added some color converson routines into what may become a real graphics library someday. + * Added a framebuffer driver for the DM320 (untested on initial check-in) + * Network: add support for outgoing multicast addresses + * Added some rasterizers to the graphics library + +0.4.0 2008-12-06 Gregory Nutt + * Initial release of a tiny windowing system for NuttX + * Add fixed precision sin() and cos() (not well tested at initial check-in) + * Add an X11-based simulated framebuffer driver + * The simulated target now has an option (CONFIG_SIM_WALLTIME) that will let the simulation + run in more-or-less realtime. + * Added more extensive window support: frames, toolbars, etc. + * Added support for bitmap fonts + * Integrated the new font support with a font test in examples/nx + * Add documentation for NX graphics subsystem + +0.4.1 2009-02-06 Gregory Nutt + * Added board support for the ZiLog eZ80Acclaim! ez80f910200zco Development Kit. + * Fixed several compilation errors in fixed precision math library when built + against toolchains that do not support 64-bit type 'long long'. + * Fix errors in some function prototypes in dirent.h + * Add eZ80F91 EMAC driver + * Fix recvfrom() compilation error: only noted under ZDS + * Updated all ARM Make.def files to work with gcc 2.4.2 (However, there are + still some build issues associated with that toolchain in use of arm-elf-objcopy + -- see the TODO.txt list for details) + * Fix problems with Z16F and eZ80 compilation introduced with recent changes. + +0.4.2 2009-02-28 Gregory Nutt + + * M16C: Add support for the Renesas M16C MCU and the SKP16C26 StarterKit. However, + the target cannot be built because the GNU m16c-elf-ld link fails with + the following message: + + m32c-elf-ld: BFD (GNU Binutils) 2.19 assertion fail /home/Owner/projects/nuttx/buildroot/toolchain_build_m32c/binutils-2.19/bfd/elf32-m32c.c:482 + + Where the reference line is: + + /* If the symbol is out of range for a 16-bit address, + we must have allocated a plt entry. */ + BFD_ASSERT (*plt_offset != (bfd_vma) -1); + + No workaround is known at this time. This is a show stopper for M16C. + + * eZ80Acclaim!: Fix interrupt vectors positioning; they were being positioned + wrong by 64 bytes (Kevin Franzen). + * eZ80Acclaim!: Corrected some stack handling errors during interrupt handling + context save and restore (Kevin Franzen). + * eZ80Acclaim!: Corrected vector intialization logic (Kevin Franzen). + * eZ80Acclaim!: Corrected overflow problem in the calculation of UART baud rate + divisor, the system timer divisor, and the EMAC poll timer. + * eZ80Acclaim!: Fixed GPIO pin configuration get serial output + * eZ80Acclaim!: Correct stack overflow in ostest example configuration + * eZ80Acclaim!: Fixed restoration of interrupts state on interrupt level context swith. + +0.4.3 2009-03-04 Gregory Nutt + + * z8Encore! and eZ80Acclaim!: Fixed the serial driver initialization sequence + * eZ80Acclaim!: Fixed error in vector table: Missing space set aside for the + "unused" vectors. As a result, all vectors above timer4 were skewed. + * eZ80Acclaim!: Fixed logic error in UART interrupt handler. + * Many fixes in FAT file system and in NSH for correct compilation with ZDS-II + * eZ80Acclaim!: Added and verified a NuttShell (NSH) configuration. + * eZ80Acclaim!: Correct endian-ness; defconfig files said BIG endian. + * Restructured parts of the uIP port for correct compilation with ZDS-II + * eZ80Acclaim!: Complete basic integration of the eZ80F91 EMAC driver. The + driver is basically functional and should mature prior to the 0.4.3 release. + * Implemented priority inheritance logic for POSIX semaphores. Because the pthread + mutexes are built on semaphores, they will have this property as well. + +0.4.4 2009-03-29 Gregory Nutt + + * examples/nsh: A debug option was left on that can (and does) cause + infinite loops and stack overflows. + * net/uip: Correct calculation of checksum on ICMP ping response. + * examples/dchpd: Added a tiny DHCP server example + * net/uip: Correct UDP bind behavior. It should select a valid port number + if it receives a port number of zero. + * netutils/dhcpd: Corrrect for ZDS compiler. Fix issue with re-use of a + port number. Fixed a number of broadcast-related problems. + * eZ80Acclaim!: Add a tiny webserver configuration + * eZ80Acclaim!: Fixed an important bug in the EMAC Tx timeout logic. It was + always timing out when the load was heavy and worse, for some reason, + resetting the Tx function caused unexpected registers to be reset in + the Rcv function was well. + * Z80: Patch incorported: "[2696648] Z80: interrupt flag stored in parity bit" + (submitted by JPelletier). The is the same fix that was needed for the + eZ80 and fixed in 0.4.2. + * netutils: Added logic to support a simple wget() function + * examples/wget: Added a test for wget() (untested -- see NOTE) + * lib/strncasecmp: Fix cut'n'paste error in function name. + * NSH: Added wget command (untested -- see NOTE). + * examples/sendmail: A simple sendmail example (untested -- see NOTE) + + NOTE: Features related to wget and sendmail are not tested on the target platform + in this release and, hence, most likely have problems. I don't have the correct network + setup to perform that testing now (I'm in a hotel). + +0.4.5 2009-04-19 Gregory Nutt + + * Add an enumeration argument to the SPI chip select and status methods so + that the interface can handle more than one device. + * eZ80Acclaim!: Add a generic SPI driver for all eZ80 boards. + * Add a setmode() method to the SPI interface to handle parts with differing + mode requirements. + * include/nuttx/i2c.h: Defined a standard I2C interface + * eZ80Acclaim!: Add an I2C driver. + * eZ8Encore!: Add an I2C driver. + * Add support for the Freescale i.MX1/L architecture and a configuration for + the Freescale MX1ADS development board. + * examples/helloxx: Added a simple C++ hello world example + * include/css: Added std header files + * libxx: New C++-only directory provides support for minimal C++ applications + +0.4.6 2009-05-19 Gregory Nutt + + * Change SPI interface so that is can accomodate interfaces where the + number of bits per word is greater an 8 (such as with many 9-bit display + interfaces). -- this might have broken a few things which will need to + be retested! + * arch/arm/src/imx: Added i.MX SPI driver + * SPI: Add a method to set the number of bits per word. Also add an + alternative interface for so that (eventually) I can phase the sndblock + and recvblock methods and replace them with a single exchange method + * Build: objcopy fails with toolchains that use newer GCC and binutils. The + following arguments need to be included in the objcopy command line "-R .note + -R .note.gnu.build-id -R .comment" This has been fixed in arch/arm/src/Makefile, + but other architectures may have the same problem. Thanks to Dave Marples + for verifying this. + * configs/eagle100/ostest: Added support for the MicroMint Eagle100 board. + This board has a Luminary LM3S6918 Cortex-M3. Added a configuration to build + examples/ostest. + * arch/arm/src/lpc214x: Add configuration option to enable fast GPIO (vs. + legacy, "slow" GPIO) for LPC214x. + * arch/arm: Restructured the arch/arm directory structure to better support ARM + and Cortex-M3. + * sched/: pthread_create() must return a (non-negated) errno value on failure. + * configs/eagle100/nsh: Add a NuttShell (NSH) configuration for the Eagle-100 + +0.4.7 2009-05-29 Gregory Nutt + + * arch/arm/src/lm3s: Added an Ethernet driver for the LM3S6918 + * configs/eagle100/nettest: Added an examples/nettest configuration for the + Micromint Eagle100 board. + * Documentation/NuttxPortingGuide.html: Added a section on NuttX device drivers. + * configs/eagle100/httpd: Added an examples/uip configuration for the + Micromint Eagle100 board. + * arch/arm/src/lm3s: Added an SSI driver for the LM3S6918 + * examples/nsh: Added MMC/SD support for the LM3S6918 + * arch/arm/src/lm3s: Fix logic for setting and clearing output GPIOs (critical + fix!). + * drivers/mmcsd: Found numerous errors in current MMC/SD SPI driver. Bad frequency + calculation based on CSD settings, inappropriate timeouts, odd code that looks like + a bad search and replace. Also needs support for SDHC ver 2.x. New MMC/SD is + largely redesigned and probably non-functional in the first check-in. + * drivers/mmcsd: Changes verified on 4Gb Kingston microSHDC card and on a 2Gb + SanDisk microSDC card on the Eagle100 platform. + * fs/fat: With the 4Gb card, the first tests of FAT32 were (finally) performed. + Found and corrected a problem that prevented use of FAT32: It was not updating + the sector cache before checking the FAT32 FSINFO sector. + * configs/eagle100/*/Make.defs: Added configuration options that should make + it possible to build NuttX for the Eagle100 using CodeSourcery 2009q1 toolchain + and the devkitARM GNU toolchain. + * configs/mcu123-lpc214x/src: Corrected some logic in the LPC2148 SPI receive block + logic. Re-verified SDC ver1.x support with 1Gb Toshiba SDC, 1Gb PNY SDC, and + 4Gb Kingston SDHC. There are CMD0 issues with the 2Gb SanDisk SDC on this board. + * fs/fs_mount.c: Corrected error handling that could cause a deadlock on certain + mount() failures. + +0.4.8 2009-06-13 Gregory Nutt + + * lib/lib_*stream.c: Extend internal stream logic to support incoming streams. + * arch/arm/src/str71x: Serial output is now correct and timer interrupts are + working. The test at configs/olimex-strp711/ostest passes. This means that + the basic STR-P711 port is complete. + * configs/olimex-strp711/nsh: Add and verified a NuttShell (NSH) configuration + for the STR-P711. + * arch/arm/str71x/str71x_serial.c: The STR711 interrupt driven serial driver + finally works after some extradinary measures to handle missed interrupts. + NSH is fully functional on the Olimex STR-P711 board. + * example/nsh: Moved architecture specific files from NSH directory to board- + specific directories. + * config/olimex-strp711/src/up_nsh.c: Add an NSH board specific directory for + for the Olimex STR7P11 board. + * Fixed build of LM3X6918 using the CodeSourcery Windows native toolchain. There + were lots of issues with Cygwin paths and Cygwin symbolic links. These changes + may work with the devarmKIT as well, but that remains untested. + * The NXP LPC2148 and STR711 targets can now also be built using the CodeSourcery + or devkitARM Windows native toolchains. + +0.4.9 2009-06-26 Gregory Nutt + + * Add strtoll() and strtoull(); Add macros for atol() and atoll(). + * dup() and dup2() will now clone socket descriptors + * All socket descriptors are now cloned when a new task is started via + task_create(). + * Add configuration options to suppress or eliminate cloning of file + and/or socket descriptors when a new task is started by task_create(): + CONFIG_FDCLONE_DISABLE, CONFIG_FDCLONE_STDIO, CONFIG_SDCLONE_DISABLE. + * Use of C++ reserved word 'private' in C header files causes problems + for C++ that include them. + * Added 'binfmt' support to allow execution of programs in a file system, + binding to NuttX symbols. A custom format call NXFLAT is used; this + derives from http://xflat.sourceforge.net. At present is supports on + XIP execution from ROMFS file systems. Initial check-in is untested + and probably breaks many builds. + * examples/lib: Added qsort() + * examples/nxflat: Added support for symbol tables + * Correct logic that creates compiler include paths. On Cygwin, the + include paths for Cygwin-based GCC were being converted to windows + native paths. That causes many problems -- breaking dependencies + for one. + * Fixed an important bug in ROMFS. The initial XIP offset was set + incorrectly so if sector zero was read first, there was a bad read. + I don't know how it worked before. + * arch/arm/src/common/up_use_stack.c. Fixed a fatal stack setup error. + This file has been around for a long time, but I don't think it has + every been used before (i.e., prior to the NXFLAT logic) + +0.4.10 2009-08-08 Gregory Nutt + + * lib/: Added some basic regex-subset, pattern matching functions + * lib/: Greatly simplified mktime() and gmtime_r(). The Gregorian and + Julian time calculations were interesting, but not necessary in the + typical embeddd system. + * sched/: Added gettimeofday(). This implementation is simply a thin + wrapper around clock_gettimer(). + * lib/: Add gmtime(), localtime(), and strftime() + * binfmt/: Add exec(). This is just a wrapper that executes both + load_ and exec_module() in a more familiar manner. It is not consistent + with more standard exec() functions, however, because (1) it returns + and (2) it requires symbol table arguments. + * lib/: Add fileno() + * examples/ostest: Several of the tests used a big, hard-coded stack size + when creating test threads (16Kb stacksize). The stack size should + be controlled by the .config file or the OSTest won't work on platforms + with memory constraints. + * netutils/thttpd: An initial port of Jeff Poskanzer's THTTPD HTTP server. + See http://acme.com/software/thttpd/. + * examples/thttpd: A basic test program for THTTPD + * configs/eagle100/thttpd: A build configuration for THTTPD on the Micromint + Eagle-100 LMS6918 (Cortex-M3) board. + * configs/ntosd-dm320/thttpd: A build configuration for THTTPD on the Neuros + DM320 platform. + * lib/: Added strstr() and strpbrk(). + * net/recvfrom.c and net/accept(): Sockets now support some non-blocking + operations, specifically for (1) TCP/IP read operations when read-ahead + buffering is enabled, and (2) TCP/IP accept() operations when TCP/IP + connection backlog is enabled. + * fs/fs_fcntl.c and net/net_vfcntl.c: Minimal support provided for fcntl(). + It can, at least, be used to mark sockets as blocking or non-blocking. + * net/net_close.c: Fix bug in close(). If reference count not set to zero + then uip_tcpfree() will assert when DEBUG is enabled. + * net/accept.c: Fix bug in accept(). The logic expected parts of the + return address structure to be initialized or it would return an error. + +0.4.11 2009-09-16 Gregory Nutt + + * fs/fs_read.c and fs/fs_write.c. read() and write() to socket is the + same as recv() and send() with flags = 0. Fixed! + * net/recvfrom.c: Fix errors in return value from non-blocking socket read. + * lib/lib_strcasecmp.c and lib/lib_strncasecmp.c. Use of post-incremented + argument to macro caused strcasecmp() and strncasecmp() to fail. + * lib/lib_strstr.c: Length of substring off by one causes false alarm + sub-string matches. + * arch/arm/src/lm3s/lm3s_ethernet.c: Fix errors in LMS6918 FIFO length + handling. (1) The incorrect size of the Ethernet header was being + subtracted on outgoing messages (4 vs 14), which caused outgoing messages to + be a little too long. (2) The size of incoming FIFO messages is 6 bytes + larger than it expected (2 for the length and 4 for the FCS). The unhandled + extra two bytes of length cause the driver to sometimes read one too many + words from the received FIFO (corrupting the next queued receive packet, + if any). + * net/net_poll.c and net/uip/uip_tcpbacklog.c. Fixed an important race condition + bug in polling for connections. The logic worked if the poll was inplace + before the connection was received; but the poll failed to awaken if the + connection was already pending in the backlog when poll() was called. + * net/net_close.c. Fixed another important TCP/IP race condition bug: If + the host closes the TCP connection just before the target calls close(), then + the close operation may hang indefinitely! + * net/net_tcppoll.c. Removed an unnecessary check for outstanding, un-ACKed + data. The NuttX socket layer keeps track of ACKs and doesn't need this check; + removing the check should improve write throughput + * Add DEBUG configuration option to enable debug console output without disabling + optimization (and vice versa) + * Changed lots of occurrences of debug macro dbg() to lldbg(). dbg() uses + stdout to output debug data. That works fine unless (1) the dbg() macro + is interrupt logic and the interrupted task has redirected stdout! Most + changes were in uIP. + * net/uip/uip_tcpinput.c. Connection reference count was not being set correctly + when a socket is created by accepting a new connection. Since the reference + count is bad, such sockets are not successfully duplicated when being passed + to new tasks. + * net/net_clone.c. Similarly, after a socket is cloned, its reference count + was not being initialized. + * lib/lib_strstr.c. Improperly incremented pointer could cause comparison + failures. + * net/. Connection reference count must always be set to zero before calling + uip_tcpfree() or it could trigger a DEBUGASSERT that verifies that the + reference count is zero before freeing a connection structure. + * net/uip/uip_listen.c. uip_accept() consulted the wrong list to find the + listener on a socket. The previous logic worked most of the time, but + occasionally picked the wrong listener. + * net/net_close.c and net/net_sockets.c. Sockets were not being closed + when a task exits. If many server tasks are created and exit without closing + sockets (such as with CGI tasks), then eventually, you will run out of sockets. + * netutils/thttpd. Basic functionality of THTTPD is complete. This includes + serving up files from a file system and executing NXFLAT-based CGI programs + and pipe the stdout back to the HTTP client. + +0.4.12 2009-10-17 Gregory Nutt + + * arch/arm/src/stm32 and configs/stm3210e-eval. Added basic support for the + STMicro STM32, Cortex-M3 MCU. The specific port is to the STMicro STM3210E-EVAL + development board based around the STM32F103ZET6 MCU. + * configs/stm3210e-eval/RIDE. Added a basic STMicro RIDE7 project that can be + used to perform basic STM32 board bring-up (due to RIDE7 size limitations, it + cannot be used for the full NuttX bring-up). + * configs/stm3210e-eval/ostest. The STM32 now passes the basic NuttX OS test + at examples/ostest. The rest should be a piece of cake. + * configs/stm3210e-eval/nsh. Added NuttShell (NSH) example. + * configs/stm3210e-eval/src/stm32102e-internal.h. Fix on-board LED GPIO definitions. + * arch/arm/src/stm32/src/stm32/stm32_dma.c. Added DMA channel support for the STM32 + * arch/arm/src/stm32/src/stm32/stm32_spi.c. Added a DMA-based SPI driver for the STM32. + * arch/arm/src/stm32/src/stm32/stm32_serial.c. Finished interrupt-driven, + USART console driver. This makes NSH work perfectly. + * Things left to do for the STM32 deferred to the 0.4.13 release: USB device driver, + LCD driver and NX bringup on the eval board's display and MicroSD support. An SPI + driver was included in the 0.4.12 release, but is not yet tested. + +0.4.13 2009-11-04 Gregory Nutt + + * include/nuttx/mtd.h. Added a simple interface definition to support some + FLASH, EEPROM, NVRAM, etc. devices. + * driver/mtd/m25px.c. Added a driver for SPI based FLASH parts M25P64 and M25P128. + * configs/stm3210e-eval/usbserial. Add a USB serial configuration for the STM32. + Depends on the STM32 USB driver. + * arch/arm/src/cortexm3/up_switchcontext.S & up_svccall.c. Made an improvement + to context switching. There are two types of context switches: interrupt + context switches and background/user context switches. This change should + improve the performance of those background/user context switches by a factor + of about two. + * arch/arm/src/stm32/: fix several typos in the serial logic. It turns out + that these typose don't make any difference as long as you use only one + serial port and all uarts are configured the same. But the typos are bugs + waiting to happen in any other configuration. + * arch/arm/src/stm32/: You have to configure CTS/RTS function pins for USART + 2 and USART 3 even if you are not using flow control. + * arch/arm/src/stm32/stm32_usbdev.c: Added a USB device-side driver for the + STM32. NOTE: This is an early release of the USB driver. There is at least + one known issue. The examples/usbserial test only executes correctly under + certain conditions (see the full bug description in the TODO list). + * arch/arm/src/stm32/stm32_rcc.c: Fixed an error in clock initialization. + On some boards (none of mine), the HSE (high speed external clock) delay + loop times out if the optimization level is high. The STM32 then falls + back to the HSI (internal clock), and the system clock is too slow by a + factor of 11.1%. This was fixed by simply add the volatile storage class + to the timeout loop counter + * arch/arm/src/stm32/stm32_irq.c: Fixed a critical bug in the interrupt + control logic. The wrong register was being used for interrupts in a + certain range. Worked fine until you try to use an interrupt in that + range! + +4.14 2009-12-02 Gregory Nutt + + * arch/arm/src/stm32/stm32_gpio.c: Add support for configure an input GPIO + to generate an EXTI interrupt. + * config/stm3210e-eval/src/up_buttons.c: Add support for on-board buttons. + * include/nuttx/rwbuffer.h: Add generic support for read-ahead buffering + and write buffering that can be used in any block driver. + * include/nuttx/wqueue.h: Added a generic worker thread that can used to + defer processing from an interrupt to a task. + * include/nuttx/sdio.h: Defines a generic SD/SDIO interface can can be + bound to a MMC/SD driver to provide SDIO-based MMC/SD support. + * drivers/mmcsd/mmcsd_sdio.c: Provides an SDIO-based MMC/SD driver. + * arch/arm/src/stm32/stm32_sdio.c: Provides an STM32 implementation of + the SDIO interface defined in include/nuttx/sdio.h. + * fs/fs_mount.c: Correct error handling logic. If the bind() method + fails, then a reserved node is left in the tree. This causes subsequent + attempts to mount at the location to fail (reporting that the node + already exists). This is a problem for block drivers for removable + media: The bind method could fail repeatedly until media is inserted. + * arch/arm/src/stm32/chip.h & stm32_dma.c: Fixed several definitions + that can cause compilation errors when DMA2 is enabled. + * arch/arm/src/stm32/stm32_dma.c: Integrated and debugged STM32 DMA + functionality that was added in 0.4.12. + * configs/stm3210e-eval/usbstorage: Add a configuration to exercise + the STM32 with the USB mass storage device class example + (examples/usbstorage). + * configs/mcu123-lpc214x/up_usbstrg: Move LPC-specific code from + examples/usbstorage to configs/mcu123-lpc214x. + * configs/stm321e-eval/up_usbstrg: Add STM32-specific logic for the + examples/usbstorage test. + * arch/arm/src/stm32/stm32_usbdev.c: Fix bugs in STM32 USB device-side + driver: (1) Need to disconnect after reset received, (2) Status setup + to recover from stall on TX endpoint. + +5.0 2009-12-21 Gregory Nutt + + * arch/hc: Adding framework to support m68hc11/12 + * configs/demo9s12ne64: Configuration to support Freescale DEMO9S12NE64 + development board (MC9S12NE64 m68hcs12 processor). + * drivers/mtd/ftl.c: A FLASH translation layer (FTL) has been implemented. + This layer will convert a FLASH MTD interface into a block driver that + can be used with any file system. Good performance of this layer will + depend upon functioning write buffer support! + NOTE: FTL support is untested as of the initial check-in. + * Numerous minor changes for m68hc12 to eliminate compilation errors and + warnings due to the fact that it uses 16-bit integer types and for casts + between uint32 (32-bits) and an mc68hc12 pointer (16-bits). + * sys/types: Size of off_t and blkcnt_t should not depend on size of + int in the architecture; Removed non-standard type STATUS + * include/: Added header files stdint.h, stdbool.h, cxx/cstdint, and + cxx/cstdbool + * Changed ALL references to non-standard fixed-size types (like uint32, + ubyte, etc.) to standard types (like uint32_t, uint8_t, etc.) from + stdint.h. Use type bool and {true, false} from stdbool. This effected + most of the files in the system! Almost all configurations have been + re-built and many have been re-verified in order to get confidence in + these changes. + * graphics/ and examples/nx: Fix numerous build errors that have been + introduced lately. NXGL has suffered some bit-rot from not being used + in some of the most recent ports. + * The misc/pascal NuttX add-on package has been updated to use the new + standard types from stdint.h and stdbool.h and re-integrated with NuttX. + The released pascal-2.0 will be the first version that contains the + compatible changes. + * arch/arm/src/lm3s/lm3s_ethernet.c: Fixed an important bug in the LM3S + Ethernet driver: If full packet is received, the packet-too-big check + will fail because it needs to subtract 6 from the packet size (to + account for the 2-byte packet length and the 4-byte packet FCS in the + FIFO). + * net/accept.c: Fixed a bad assertion (only happens when debug is enabled). + * net/send.c net/uip/uip_tcpseqno.c: Fixed a critical error in the TCP/IP + logic. The NuttX port of uIP imcludes logic to send data ahead without + waiting for ACKs from the recipient; this greatly improves throughput. + However, the packet sequence number was not being updated correctly and, + as a result, packets were not be ACKed by the recipient and transfers + would sometimes stall. This is a very important bug fix (in fact, I + don't understand how TCP/IP worked at all without this fix???) + * include/nuttx/arch.h and arch/*/common/up_udelay.c: Change argument + of up_udelay() to type useconds_t to avoid warnings when sizeof(int) + is 16-bits. + * drivers/mmcsd/*: Add casts in constant expressions to avoid warnings + when sizeof(int) is 16-bits. + +5.1 2010-01-30 Gregory Nutt + + * arch/arm/src/lpc313x and arch/arm/include/lpc313x: Added framework + to support the NXP LPC3131. + * Add configs/ea3131. The LPC3131 port for the Embedded Artist EA3131 + (LPC3131) is code complete and waiting for me to get hardware in + hand. + * arch/arm/src/sam3u, arch/arm/include/sam3u, and configs/sam3u-ek - + Added the basic framework needed to begin a port for the SAM3U-EK + development board. + * lib/lib_crc32.c: Add CRC32 logic by Gary S. Brown to lib/. This is + the larger (but faster) table look-up version of the CRC32 algorithm. + * confgs/ea3131/tools: Added a tool to create a image suitable for + use with the LPC313x bootloader. + * configs/sam3u-3k/ostest: Completed verification of the basic NuttX + OS test for the SAM3U. + * arch/arm/src/common/up_createstack: stack was always been cleared + when it was allocated. This is a good feature for monitoring the + stack during debug, but really hurts thread start-up performance. + Clearing is now done if CONFIG_DEBUG=y only. Changes was only made + for arm, but really should be made for all architectures. + * configs/sam3u/nsh: Added NSH configuration for SAM3U + +5.2 2010-03-18 Gregory Nutt + + * arch/arm/src/sam3u/sam3u_pio.c: Fix an address calculation error + that caused ports B & C to get mapped to the PIOA base address. + This is an important bugfix! (a patch is available) + * arch/arm/src/lpc313x/lpc313x_boot.c: Fix an error in the vector + initialization was causing a memory fault. + * lib/lib_strtod.c: Add strtod() + * lpc3131/ea3131: Several bring fixes submitted by David Hewson. The + lpc3131 is almost there! Thanks David! + * arch/arm/src/arm/up_head.S: Corrected backward conditional compilation + that selects if vectors are located at 0x0000:0000 or 0xffff:f000. + This fixes the last show stopper bug in the lpc313x bring-up. + * configs/ea3131/nsh: Added a NuttShell (NSH) configuration for the + EA3131. + +5.3 2010-04-11 Gregory Nutt + + * arch/arm/src/lpc313x/lpc313x_usbdev.c: USB driver for the LPC313x + contributed by David Hewson. + * configs/ea3131/src/up_ubstrgc.c, configs/ea3131/usbserial, + configs/ea3131/usbstorage: USB storage and USB serial example support + contributed by David Hewson. + * Several important compilation error fixes in lpc313x and (dualspeed) USB + code also contributed by David Hewson. + * arch/arm/src/sam3u/sam3u_dmac.c: DMA support for the AT90SAM3U. + * arch/arm/src/sam3u/sam3u_hsmci.c: SD memory card support for AT90SAM3U + (Neither the DMA nor the HSMCI driver are functional on the initial checkin). + * drivers/usbdev: Several important fixes to the USB mass storage driver + submitted by David Hewson. + * configs/olimex-lpc2378, arch/arm/include/lpc2378, and arch/arm/src/lpc2378 - + Basic port of the NXP 2378 on the Olimex board contributed by + Rommel Marcelo. + * arch/arm/src/sam3u/sam3u_internal.h: Fixed a critical bug in the AT91SAM3U + PIO decoding. No PIOs greater than 15 could be used on any port! Obviously, + no one has been using this port. + +5.4 2010-04-23 Gregory Nutt + + * include/nuttx/lcd.h: Defines an LCD interface. + * graphics/nxglib/fb and lcd: Support LCD and framebuffer rasterizers for NX. + * configs/sam3u-ek/src/up_lcd.c: LCD driver for LCD on SAM3U-EK development + board. + * configs/sam3u-ek/nx: NX graphics configuration for the SAM3U-EK + +5.5 2010-05-09 Gregory Nutt + + * drivers/net/enc28j60.c: Microchip ENC28J60 SPI Ethernet chip driver. + (untested on original check-in). + * configs/olimex-str7p11/nettest: examples/nettest configuration using + the ENC28J60 driver on the Olimex STMicro STR-P711. + (unverified on original check-in) + * configs/olimex-str7p11/src/up_enc28j60.c: Add ENC28J60 initialization + logic. + * configs/olimex-str7p11/src/up_spi.c: Fixed some bugs; added support + for ENC28J60. + * arch/arm/src/str7x/str7x_xti.c: Add basic XTI support (external + interrupts). + * arch/arm/src/lm3s and arch/arm/include/lm3s: Add definitions for + LM3S6965 + * configs/lm3s6965-ek: Add configuration for Stellaris LM3S6965 + Evaluation Kit (including basic examples/ostest configuration) + * lib/lib_dtoa.c and lib/lib_dtoa.c: printf will not print floating + point values if you select CONFIG_LIBC_FLOATINGPOINT in your + configuration file. Contributed by Yolande Cates. NOTE: these + floating point operations have not been well tested and may not + be portable to all floating point implementations. + * configs/lm3s6965-ek/nsh: Added NuttShell (NSH) configuration for + the LM3S6965 Evaluation Kit. Includes both serial and telnet + interfaces. + * net/net_close.c: Correct a UDP reference counting error + +5.6 2010-06-05 Gregory Nutt + + * drivers/lcd/p14201.c: Driver for RiT P14201 series 128x96 4-bit OLED. + * configs/lm3s6965-ek/nx: NX graphics configuration for the LM3S6965 + Ethernet Evaluation Kit. + * graphics/: Numerous fixes to get the P14201 4-bpp grayscale display + working (there may still be some minor issues .. see the TODO list). + * arch/arm/include/lpc17xx and arch/arm/src/lpc17xxx: Began port for + NXP LPC1768. As of the 5.6 release, there is a complete set of + LPC17xx header files defining all bits in all LPC17xx registers, + but little else (I still do not have hardware in hand). + * drivers/mtd/m25px.c: Add support for M25P1 flash part (See NOTE) + * include/nuttx/i2c.h: Extended I2C interface definition to handle + multiple transfers (See NOTE). + * include/nuttx/usbdev.h: Corrected an important macro definition + needed to correctly handle USB null packet transfers (See NOTE). + * arch/arm/src/lpc313x: New drivers: I2C and SPI. Plus several + important LPC313x USB bug fixes (See NOTE). + + NOTE: Contributed by David Hewson. + +5.7 2010-06-22 Gregory Nutt + + * configs/nucleus2g: Add ostest configuration for the Nucleus 2G + LPC1768 board from 2G Engineering (http://www.2g-eng.com/) + * arch/arm/src/lpc17xx: Added basic LPC17xx boot-up logic, + interrupt handling, and GPIO configuration. + * configs/nucleus2g/ostest: Completed bring-up of LPC1768 on + the Nucleus2G board using the examples/ostest + * configs/nucleus2g/nsh: Added and verified a NuttShell (NSH) + configuration for the LPC1768 on the Nucleus2G board. + +5.8 2010-07-18 Gregory Nutt + + * configs/nucleus2g/src/up_nsh.c and up_ssp.c: Add support + for SPI-based MMC/SD cards and integrate into the NSH example. + * arch/arm/src/lm3s/lm3s_vectors.S: Correct vectors for GPIOC & D + interrupts. + * arch/arm/src/lpc17xx/lp17_clockconfig.c: Power was not being + provided to GPIO module. This is a critical bugfix! + * arch/arm/src/lpc17xx/lpc17_serial.c: Improved logic to handle + missed TX interrupts. + * arch/arm/src/lpc17xx/lpc17_ssp.c: Fix a hard fault during SSP + initialization. + * configs/nucleus2g/src/up_led.c: Change how LEDs are controlled + so that they can be used both for NuttX instrumentation and + by application software. + * include/net/uip/igmp.h and uip-igmp.h: Add header files ini + preparation for NuttX IGMP support + * net/uip/uip_igmp*.c: Add IGMP support (untested on initial + checkin). + * examples/igmp: Add a trivial test for IGMP (much more is needed) + * configs/nucleus2g/usbserial and usbstorage: Add USB configurations + for testing purposes. + * arch/arm/src/common/up_internal.h, cortexm3/up_assert.c, + */*_vectors.S: Correct compilations errors when CONFIG_ARCH_INTERRUPTSTACK + is enabled (feature still not tested) + +5.9 2010-08-25 Gregory Nutt + + * examples/nsh/nsh_telnetd.c: Fix compilation errors that happen + when both DHCPC and TELNETD are enabled in the Nuttshell. + * graphics/nxglib/fb/nxglib_moverectangle.c: Fix a logic error + that caused an uninitialized variable warning. I still don't + have a test to prove that the changes are correct. + * configs/olimex-lpc2378: Add support for the CodeSourcery toolchain + under Linux (contributed by Alan Carvalho de Assis). + * arch/arm/src/lpc17xx/lpc17_gpio.c: Fix an important GPIO configuration + bug: When attempting to set no pull-up or pull-down (floating), + it would, instead, select pull-down. + * arch/arm/src/lm3s/lm3s_gpioirq.c: Fix warning for returning a value + from functions returning void (contributed by Tiago Maluta). + * netutils/dhcpc/dhcpc.c: lease_time was not in host order + * examples/uip/main.c: if DHCPC is selected, this example now shows + the assigned IP address. + * arch/arm/src/lm3s and arch/arm/include/lm3s: Definitions for the + TI LM3S9B96 contributed by Tiago Maluta. + * arch/arm/src/lm3s/lm3s_gioirq.c: Fix a logic error in the address + table lookup. + * arch/arm/src/lm3s/lm3s_gioirq.c: Also needs to enable the global + GPIO interrupts. + * arch/arm/src/lm3s/lm3s_internal.h and lm3s_gpio.c: Fixed the encoding + of GPIO port number that limited support for GPIO ports to 8 + * sched/pg_*.c and *.c and include/nuttx/page.h: Implemented the + common, core logic for on-demand paging. See + http://www.nuttx.org/NuttXDemandPaging.html for details. + * drivers/usbdev/usbdev_serial.c: Correct compilation errors that + occur if CONFIG_USBDEV_DUALSPEED is selected. + * configs/ea3131/pgnsh: Add an NSH configuration with on-demand paging + enabled. This is not expected to be a functionality configuration (at + least not yet); it was created in order to debug the on-demand paging + feature. + * configs/ntosd-dm320/*/Make.defs: Codesourcery and devkitARM toolchains + now supported for the Neuros OSD. + * configs/ntosd-dm320 and arch/arm/src/dm320: Add support for the + Neuros production OSD (changes contributed by bf.nuttx). + +5.10 2010-09-07 Gregory Nutt + + * configs/ea3131/locked: Create logic to support a two pass build + process: The first pass forces critical logic into the locked text + region, the second pass builds the NuttX executable more-or-less as + normal. + * Makefile, arch/arm/src/Makefile, configs/ea3131: Add logic to + support a two-pass final link. This logic is only in place in + the arch/arm/src/Makefile for now. + * arch/arm/src/lpc17xx/lpc17_internal.h: Add missing parentheses in + macros definitions (patch submitted by Tiago Maluta). + * Documents/NuttxPortingGuide.html, configs/README.txt, etc. - + Replaced CONFIG_EXAMPLE with CONFIG_APP_DIR (see documents for + desciption). This allows NuttX application code to be built + outside of the examples/ directory. + + For people who have their own configurations and/or Makefiles, + you will need to make a couple of changes: + + - Replace all occurrences of CONFIG_EXAMPLE=foobar with + CONFIG_APP_DIR=examples/foobar in all of the configuration + files. + - Replace any occurrences of examples/$(CONFIG_EXAMPLE) with + $(CONFIG_APP_DIR) + - Replace any occurrences of lib$(CONFIG_EXAMPLE)$(LIBEXT) + with libapp$(LIBEXT) in your Makefiles. + - Check any other occurrences of CONFIG_EXAMPLE. + + * arch/arm/src/lpc313x/lpc313x_spi.c: Fix compilation error when + when CONFIG_DEBUG is enabled. + * arch/arm/src/lm3s and arch/arm/include/lm3s: Support for the + lm3s8962 contributed by Larry Arnold. + * configs/lm328962-ek: Support for the TI/Stellaris EKC-LM3S8962 + board (also contributed by Larry Arnold). + * arch/arm/src/lpc313x/lpc313x_boot.c: The call to lpc313x_boardinitialized() + should not be conditioned on CONFIG_ARCH_LEDs being defined! + * arch/arm/src/lpc313x/: APB0 and APB1 cannot lie in different + sections; they are too close together. + * arch/arm/src/lpc313x/lpc13x_boot.c: Resetting all of the clocking + had a side effect of wiping out the first 6 words of memory where the + interrupt vectors are located (and also not resetting the fractional + dividers). This is not usually noticeable because the IRQ vectors + are after this point, but really causes problems if you want to handle + data and prefectch aborts which are within this zeroed region. + +5.11 2010-10-01 Gregory Nutt + + * configs/ea3131/src/up_fillpage.c: Added new configuration item + CONFIG_PAGING_BINPATH. If CONFIG_PAGING_BINPATH is defined, then it + is the full path to a file on a mounted file system that contains + a binary image of the NuttX executable. Pages will be filled by + reading from offsets into this file that correspond to virtual + fault addresses. up_fillpage.c implements logic to perform page + files using the CONFIG_PAGING_BINPATH file. + * configs/mbed: Add configuration to support the mbed.org LPC1768 + board (Contributed by Dave Marples). + * sched/sem_wait.c and sem_waitirq.c: Eliminate a race condition + that can occur when a semaphore wait is interrupt by a signal. + (see email thread: http://tech.groups.yahoo.com/group/nuttx/message/530) + * drivers/mtd/at45db.c: Add a driver for the Atmel AT45DB161D 4Mbit + SPI FLASH part (untested on initial check-in). + * arch/arm/src/lm3s and arch/arm/include/lm3s: Corrections for the + lm3s8962 port contributed by Larry Arnold. That port is purported + to work correctly with these changes in place. + * examples/ostest/prioinherit.c: Need to reinitialize globals if + test is ran repeatedly in a loop. + * configs/ez80f910200zco: Updated to used ZDS-II 4.11.1 + +5.12 2010-10-26 Gregory Nutt + + * arch/avr: Add a place to support AVR family processors. + * arch/avr/include/avr32 and arch/avr/src/avr32: Add support for AVR32 + (all of the AVR32 is a work in progress). + * arch/avr/include/at32uc3 and arch/avr/src/at32uc3: Add support + for the AVR32 UC3A/B family of AVR32 MCUs. + * confgs/avr32dev1: Add support for the Atmel AVR32DEV1 board featuring + the AT32UC3B0256 MCU. This board is produced by www.mcuzone.com. + * include/stdlib.h, lib/Makefile, lib/lib_abs.c, lib/lib_labs.c, + lib_labs.c, lib_llabs.c, lib_imaxabs.c: Add abs(), labs(), llabs(), and + imaxabs(). + * Add include/inttypes.h + * arch/hc/src/mc9s12ne64: This hcs12 port grew a few more files. But it + is still a long way from complete. + * arch/*/src/*/*_sigdeliver.c: Fixed a serious error in the signal + trampoline logic. Essentially, interrupts are re-enabled while the + signal handler executes, but the logic to re-disable the interrupts + before returning from the signal handler trampoline was missing. Under + certain circumstances, this can cause stack corruption. This was + discovered by David Hewson on an ARM9 platform, but since the code + has been leveraged, the bug has been propogated from ARM to Cortex-M3, + AVR32, M16C, SH1, ZNEO, eZ80, Z8, and Z80 -- almost every architecture. + The correction has been incorporated for all architectures but only + verified on a few. + +5.13 2010-11-09 Gregory Nutt + + * lib/lib_strnlen.c: Added POSIX 2008 strnlen() function. Contributed + by Michael Hrabanek. + * Fix wild, consistent naming error. For some reason, I called the at32uc3* + parts at91uc* everywhere. Fixed by changing lots of files and directories. + * configs/avr32dev1/ostest: The AVR32 port now successfully passes the + examples/ostest. We have a good AVR32 port! + * configs/avr32dev1/nsh: Added a configuration to support the NuttShell + (NSH). As of this writing, here is a problem receiving serial data (this + is, very likely, my hardware setup). + * lib/lib_open.c: Fix an error in fdopen when a valid file desciptor does + not refer to an open file. + * configs/olimex-lpc1766stk: Add support for the Olimex LPC1766-STK + development board. The OS test and NSH configurations (only) have been + verified. + +5.14 2010-11-27 Gregory Nutt + + * configs/olimex-lpc1766stk/nettest: Add examples/nettest configuration to + verify the LPC17xx Ethernet driver currently under development. + * arch/arm/src/lpc17xx/lpc17xx_ethernet.c/.h: Began development of + the LPC17xx Ethernet driver. Driver in CVS functional after 2010-11-23. + * sched/timer_settime.c: Fix an error in set-up of a one-shot POSIX timer. It + was using the repititive timer value (which is zero in the one-shot case), + always resulting in a 10Ms timer! Found and fixed by Wilton Tong. + * arch/arm/src/lpc17xx/lpc17_vector.S, stm32/stm32_vector.S, lm3s/lm3s_vector.S, + sam3u/sam3u_vector.S: Fixed a hard fault problem that can occur if certain + types of interrupts are pending at the time another interrupt returns + (SYSTICK). This has not been verified on all plaforms, but is a critical + fixed that is needed by all Cortex-M3 NuttX users. + * configs/olimex-lpc1766stk/thttpd: Add a THTTPD configuration for the + Olimex LPC2766-STK board. Verified successfully. + * net/uip/uip_tcpappsend.c: Correct an important logic bug in some uIP state + data the is used to manage retransmissions. The uIP logic was incompatible + with the retransmission logic of net/send.c in one place. The final error + was that the final packet in a sequence of packets was too large! In the + THTTPD example, this would leave some garbage at the bottom of the display + (or worse). I don't know why I haven't see this bug before??? + * net/uip/uip_tcpinput.c: The change to uip_tcpappsend.c unmasked an + additional error in the TCP sequence number handling. This sympom was that + the send() function would hang with outstanding, unacknowledged data (with + no re-transmit requests). The was due to differences in sequence number + handling in send() and in uip_tcpinput.c; uip_tcpinput.c thought (incorrectly) + that all of the bytes were acknowledged; send.c knew that they were not. + +5.15 2010-12-12 Gregory Nutt + + * net/uip/uip_tcpaddsend.c and net/send.c: Another place where the TCP sequence + number problem "fixed" in 5.14 might occur. + * net/send.c: Check if the destination IP address is in the ARP table. If + not, then don't consider the packet sent. It won't be, an ARP packet will go + out instead. This improves behavior, for example, on the first GET request + from a browser. + * arch/arm/src/lpc17xx/lpc17_emacram.h and lpc17_allocateheap.c: The Ethernet + logic was using all of AHB SRAM Bank0 for Ethernet packet buffers (16Kb). An + option was added to limit the amount of SRAM used for packet buffering and to + re-use any extra Bank0 memory for heap. configs/olimex-lpc1766stk/nettest + now uses only 8Kb at the beginning of Bank0; the 8Kb at the end of Bank0 is + included in the heap + * arch/arm/src/lpc17xx/lpc17_ssp.c: Fix compilation errors when SSP1 is + selected. + * configs/olimex-lpc1766stk/nsh: Enable network and SD/MMC card support in + NSH. Networking and telnetd interface as well as SPI-based microSD are + now functional. + * examples/nsh/nsh_netinit.c: Fix NSH bug. If CONFIG_NET is selected, but + CONFIG_EXAMPLES_NSH_TELNETD is not selected, then the network is never + initialized and bad things happen if you try to ping. + * drivers/lcd: Add header files for the Phillips PCF8833 LCD controller and + for the Epson S1D15G10 LCD controller. A driver for the Nokia 6100 LCD is + coming. + * include/nuttx/spi.h and almost all other SPI files: Added an optional + cmddata() method to the SPI interface. Some devices require an additional + out-of-band bit to specify if the next word sent to the device is a command + or data. This is typical, for example, in "9-bit" displays where the 9th bit + is the CMD/DATA bit. The cmddata method provides selection of command or data. + * drivers/lcd/p14201.c: Now uses the cmddata() method of the SPI interface. + * arch/arm/src/lpc17xx/lpc17_usbdev.c: LPC17xx USB driver now appears to + to be fully functional. examples/usbstorage configuration verified (the + examples/usbserial configuration is untested). + * drivers/usbdev/usbserial.c and usbstorage.c: All USB class drivers need + to call DEV_CONNECT() when they are ready to be enumerated. That is, + (1) initially when bound to the USB driver, and (2) after a USB reset. + * drivers/lcd/nokia6100.c: A driver for the Nokia 6100 LCD. This driver + has not be verified as of the initial check-in. + * configs/olimex-lpc1766stk/nx: A NX graphics configuration for the Olimex + LPC1766-STK board using the Nokia 6100 LCD driver. This configuration has + not been verified as of the initial check-in. + * include/nuttx/spi.h: the SPI_SETBITS macro was calling the setmode method. + This is a very important bug-fix in some usages. + +5.16 2011-01-10 Gregory Nutt + + * include/nuttx/usb: Created new directory. Moved all usb-related header + files to this new directory. Created a skeleton for a new USB host header + file + * drivers/usbhost: Add USB host "registry" where connect devices can be + matched with the correct USB class driver. + * arc/arc/src/lpc17xx/lpc17_usbhost.c: Add a simple USB host driver for + the NXP lpc17xx. + * drivers/usbhost: Add generic USB device enumeration logic. + * drivers/usbhost: Add a USB host class driver for the (Bulk-Only) USB + Mass Storage Class. + +5.17 2011-01-19 Gregory Nutt + + * include/nuttx/usb: rename usb_storage.h to storage.h. + * arch/arm/src/lpc17xx/lpc17_usbhost.c: Add support for low-speed devices. + * drivers/usbhost/usbhost_skeleton.c: Template for new class drivers + * include/nuttx/usb/hid.h and drivers/usbhost/usbhost_hidkbd.c: New + files for HID keyboard support. + * arch/arm/src/lpc17xx/lpc17_usbhost.c: Will now handle multiple + concurrent transfers on different endpoints (still only one TD per + endpoint). All methods are protected from re-entrancy; lots of re- + structuring in preparation for interrupt endpoint support. + * arch/arm/src/lpc17xx/lpc17_usbhost.c: Add support for periodic + interrupt transfers. + * examples/hidkbd: Added a simple test for the USB host HID keyboard + class driver. + * configs/olimex-lpc1766stk/hidkbd: Added a configuration to build the + USB host HID keyboard class driver test for the LPC17xx. + * Ran the tool CppCheck (http://sourceforge.net/apps/mediawiki/cppcheck) and + fixed several errors in the code identified by the tool. + +5.18 2011-02-27 Gregory Nutt + + * Incorporate several uIP patches from http://gitweb.aeruder.net/?p=uip.git;a=summary. + - Lost SYNACK causes connection reset + - Fix missing UDP stats for sent/received packets + - Added support for Cygwin as development/test platform. + * configs/demo9s12ne64: Integrate new buildroot-1.9 m8s12x toolchain. + * 'uname -o' is used throughout the build logic in bash scripts and also in + Make.defs files in order to distinguish between Cygwin and Linux. However, + the -o option is not standard and is not supported under, for example, OS-X or + Solaris. This was solved by changing all 'uname -o' references to the more + complex: 'uname -o 2>/dev/null || echo "Other"' + * drivers/usbhost/usbhost_enumerate.c: Add logic to get the VID and PID. This + is necessary in order to support vendor-specific USB devices. + * examplex/wlan, configs/olimex-lpc1766stk/wlan, drivers/usbhost/usbhost_rtl8187.c, + Add infrastructure to support RTL18187 wireless USB. + * configs/nucleus2g: backed out USB host changes... wrong board. + * Renamed arc/hc/include/mc9s12ne64 and src/mc9s12ne64 to m9s12. That name is + shorter and more general. + * The NuttX repository has been converted to SVN and can now be found here + http://nuttx.svn.sourceforge.net/viewvc/nuttx/ + * configs/mbed/hidkbd: Added USB host support for the mbed LPC1768 board; add + a USB host HID keyboard configuraion. + * drivers/usbhost/hid_parser.c: Leverages the LUFA HID parser written by + Dean Camera. + * examples/nsh: Correct an usage of getopt(): If you stop calling getopt() + before all parameters are parsed, you can leave getopt() in a strange state. + * include/nuttx/fb.h: Restore missing RGB type that was accidentally removed + when Nokia 6100 support was added. + * Rename arch/pjrc-8051 to arch/8051 + * configs/ne64badge: Add a configuration for the Future Electronics Group + NE64 Badge development board (Freescale MC9S12NE64) + * Changes contributed by Uros Platise: + - Add support for the STM32F103RET6 + - configs/vsn: Support for the ISOTEL NetClamps VSN V1.2 ready2go sensor + network platform + * arch/hc, configs/ne64badge: Development is complete for the Freescale + mc9s12ne64 on the Future Electronics Group NE64 /PoE Badge board. Howeve, + this port remains untested until I figure out this BDM / Code Warrior + and paged build thing + * Added a new 'kill' command to NSH that will support sending signals to + running NuttX tasks. + +5.19 2011-03-12 Gregory Nutt + + * arch/arm/stm32/stm32_idle.c: During idle times, the STM32 now uses the + WFI instruction to sleep in a reduced power mode until the next interrupt + occurs (Contributed by Uros Platise). + * NSH: 'mem' command renamed to 'free'. Output is now more similar to the + Linux 'free' command. + * NSH: Correct a redirection bug in NSH. The following would not work; it + resulted in a hang after the 'cat /dev/fifo': + + nsh> mkfile /dev/fifo + nsh> cd /tmp # /tmp is a mounted RAM disk + nsh> cat /dev/fifo > test.txt & + nsh> echo "This is a test" > /dev/fifo + + The error was caused because (1) there was a path that resulted in stdout + being closed (the "hang") and also (2) the 'cat' command was always outputting + to stdout, not to the redirected file descriptor. Now: + + nsh> cat test.txt + This is a test + + * drivers/pipes/pipe_common.c: Driver open method was not returning an EINTR + error when it received a signal. Instead, it just re-started the wait. This + makes it impossible to kill a background pipe operation from NSH. + * include/stdint.h: Correct some errors in conditional compilation (submitted + by Johannes Hampel). + * arch/arm/lpc17xx/lp17_idle.c: Uses the same logic as the STM32: uses the + WFI instruction to sleep in a reduced power mode until the next interrupt + occurs. + * configs/olimex-lpc1766stk: Added an LED encoded to indicate if the LPC1766 + is in sleeping. + * examples/mm: This is a simplified version of the "built-in" memory manager + test of mm/mm_test.c. It is simplified because it does not have access to + the internals of the memory manager as does mm/mm_test.c, but it has the + advantage that it runs in the actual NuttX tasking environment (the + mm/mm_test.c only runs in a PC simulation environment). + * drivers/mmcsd_sdio.c/h: Several corrections submitted by Uros Platise. + * arch/x86: Provide support for x86 architectures. Support for the i486 + architecture under QEMU is provided under arch/x86/include/i486, + arch/x86/include/qemu, arch/x86/src/i486, and arch/x86/src/qemu. + * configs/qemu-i486: "Board" support configurations for verifying the QEME + i486 port. + * arch/arm/src/stm32/stm32_spi.c: Correct base address of SPI3 (reported by + Uros Platise). + * drivers/mmcsd/mmcsd_sdio.c: Correct a loop termination condition (also + reported by Uros Platise). + * drivers/mtd/ramtron.c: Driver for SPI-based RAMTRON NVRAM devices FM25V10 + (and others). Contributed by Uros Platise. + * examples/nsh and tools/mkromfsimg.sh: Add support for platform-specific + ROMFS-based NSH start-up scripts. + * drivers/serial/uart_16550.c and include/nuttx/serial/uart_16550.h: Support + for a generic 16550 UART. + * configure/qemu-i486/nsh: QEMU NSH example. + * ../apps: The apps directory add-on was created by Uros Platise. It + supports a set of end-user applications than can be executed on top of + NSH. Think of it this way: In a buckled-up embedded application, your + end-user programs will probably have their own dedicated start-up logic. + But, during development, you might want to have you applications + available and executable from the NSH command line. This apps/ addon + (and NSH hooks) was contributed by Uros to accomplish just that. + * sched/sched_waitpid() and include/sys/wait.h: Provides a simple and + very incomplete implementation of waitpid(). waitpid() is only available + if CONFIG_SCHED_WAITPID is defined in your configuration file. + * sched/atexit.c and sched/exit.c: The atexit function is not frequently + used. In order to save a few bytes, it is now conditioned on + CONFIG_SCHED_ATEXIT. It your application is currently using atexit(), + you will need to add CONFIG_SCHED_ATEXIT to your configuration file. + * drivers/net/slip.c: Add a SLIP driver (untested on initial check-in). + * configs/olimex-lpc1766stk/slip-httpd: An example that uses SLIP to + provide a serial-port based THTTPD web server. + +6.0 2011-03-21 Gregory Nutt + + * lib/lib_fopen(): fopen() was not returning the correct errno value + when the underlying open() failed. + * include/net/uip/uip-arch.h: The uIP interface has been extended + slightly so that drivers can be concurrenly filling and sending + packet buffers. This capability was needed by the SLIP driver. + * drivers/net/slip.c: Several corrections and some re-design of + of the driver. + * apps/ChangeLog.txt: the apps/ directory now has its own ChangeLog. + * configs/vsn: + - IDLE LED blinking fix + - Added board power off function + * arch/arm/src/stm32/stm32_gpio.c and stm32_internal.h: Fixed + PullUp/Down Input Configuration. + * arch/arm/src/lpc17xx/lpc17_serial.h: Now supports Auto-RTS and + Auto-CTS modes. This is needed to support SLIP. + * drivers/net/slip.c: SLIP is now basically functional on the + LPC17xx with some caveats as described in the TODO list under + LPC17xx. + * arch/x86/include/i486/irq.h: Fix irqrestore() macro... it was not + correctly re-enabling interrupts. + * arch/x86/src: Fix numerous problems with i486/QEMU context + switching. Basically, the logic was missing the cases to handle + the differing stack frames when a priority change occurs and when + no priority change occurs. + * configs/qemu-i486/ostest and nsh: The QEMU i486 port is complete. + it now passes the OS test and supports the NuttShell (NSH). + * misc/drivers: Created a new directory to hold non-BSD licensed + drivers that may be added into NuttX via an installation script. + * drivers/usbhost/usbhost_rtl8187.c: A decision was made to + incorporate code taken from the Linux kernel. That changes the + licensing on this module to GPL. To avoid licensing contamination, + this driver was moved to misc/drivers/rtl8187x *prior* to adding + any of the GPL logic. There is an INSTALL.sh script at the location + where the GPL driver(s) can be re-installed into the NuttX source + tree. By re-installing the driver, you agree to the GPL licsensing + and all of its implications. + * Makefile, apps/Makefile, tools/configure.sh: add logic to copy + configs///appdir to apps/.config and to simply the + application configuration logic. + * examples/nsh and apps/nshlib: Move the core NuttShell (NSH) logic + out of the exemples directory and into the apps/ directory where + it belongs. + * apps/Makefile and configs/*/appconfig: Use '=' as the delimiter + instead of '/' so that sub-directories in apps/ can be used. + * apps/vsn: Move all VSN apps to apps/vsn. + * nuttx/examples moved to apps/examples + +6.1 2011-04-11 Gregory Nutt + + * arch/arm/include/lpc17xx/irq.h and arch/arm/src/lpc17xx/lpc17_gpio*.c: + Fix several bugs in the GPIO interrupt logic. Submited by + Decio Renno. + * Initialization for the CONFIG_APPS_DIR is now supported during the + earlier, 'context' build phase. + * arch/arm/src/lpc17_gpioint.c: Finish coding of the LPC17xx GPIO + interrupt logic. + * net/netdev_unregister.c: Add capability to un-register a network + device. + * drivers/mmcsd/mmcsd_sdio.c: extra effort to correctly handle cases + without the SDcard (but one issue still exists in STM32) + * arch/arm/src/stm32/stm32_tim.*: Added basic timer support TIM1..TIM8 + with output PWMs and interrupt logic + * config/vsn/src: added basic support for Sensor Interface (GPIO and + PWM Power Output, and the sif utility program) + * fs/: Reorgnize header so that file systems can be built outside + of the nuttx source tree + * apps/namedapp/binfs.c: Create a tiny filesystem that can be used + to show the internal named apps under /bin. + * fs/fs_opendir.c: Correct an error that occurs when a file system is + mounted in the root directory. This was discovered while mounting + the named app's /bin directory. + * lib/: Move all source files into a subdirectory of lib/ named after + the header file in which the library function is prototyped. + * sched/ and lib/pthread/: Move pthread attribute-related interfaces + from sched/ to lib/pthread where they more appropriately belong. + * sched/ and lib/semaphore/: Move some semaphore-related interfaces + from sched/ to lib/pthread where they more appropriately belong. + * syscall/: The beginnings of an optional syscall kernal interface. + * tools/mksyscall.c: Add a tool that will auto-generate syscall proxies + and stubs from a comma-separated-value (CSV) data file. + * arch/arm/src/cortexm3/mpu.h: Add a header file describing the Cortex-M3 + MPU registers. + * Numerous modifications to the build system. Various people have reported + build problems since the re-organization and release of NuttX-6.0. I am + unable to replicate the build problems in my environment, but the changes + have be incorporated in hope of correcting the build issues in other + environments. + * drivers/i2c/st_lis331dl.c: I2C-based driver for the LIS331DL MEMS + motion sensor. Contributed by Uros Platise. + * Makefile: The NuttX build system will now supported building NuttX as two + separately linked images: (1) a kernel-mode RTOS image, and (2) a user- + mode application image that communicates to the RTOS kernel via system + calls. A lot more still must be done. + * user_initialize(): Eliminated the user_initialize() initialization hook. + It is difficult to maintain and redundant: Board level initialization + an up_initialize() provide the same kind of capability. + * arch/*/include/*/type.h: On some compilers, char defaults as unsigned. + Explicitly add signed to integer types if signed is what is required. + * arch/*: For all architectures -- Global register state save structure + (usually called current_regs) should be marked volatile; Added general + capability to support nested interrupts (not fully realized for all + architectures). + * sched/task_create.c: Add support for starting kernel-mode thread. + * drivers/usbdev/usbdev_serial.c: Fix reported by Sheref Younan. USB + was being reset after serial driver was closed. As a result, you could + no reopen the serial driver. + * configs/lpcxpresso-lpc1768: Add a board configuration for the Embedded + Artists LPCXpresso LPC1768 board. + +6.2 2011-05-06 Gregory Nutt + + * arch/arm/src/lpc17xx/lpc17_gpioint.c: Correct errors in logic that maps + and IRQ number into a register bit number. + * Makefile: Fix an error introduced in the top-level Makefile in NuttX-6.1. + This error only shows up if you have a /tftpboot directory. Then the + make will fail with an obscure error about not being able to stat pass2. + * configs/lpcxpresso-lpc1768/nsh: Add an NSH configuration for the + LPCXpresso board. + * configs/*/ld.script: Removed 'sh_link not set for section .ARM.edix' for + a few of the builds. In you have this warning, it can be removed with the + following change to the ld.script file: + + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : { + - __exidx_start = ABSOLUTE(.); + *(.ARM.exidx*) + - __exidx_end = ABSOLUTE(.); + } >sram + + __exidx_end = ABSOLUTE(.); + + * arch/arm/src/lpc17xx: Correct some typos/bugs in configuration of LPC17xx + UART2 and UART3. + * nuttx/clock.h: Replace all references to the global variable g_system_timer + with clock_systemtimer() (currently just a macro that that returns g_system_timer). + * lib/string/strrch.c: Would fail if the searched-for character were the first + character in the string. + * tools/version.sh and mkversion.c: Tools to manage a NuttX version number + file + * sched/clock_getutc() and lib/time/lib_time.c: Add support for 1 second UTC + interface. + * net/net_dup2.c and include/nuttx/net.h: The conditional compilation for + '#if CONFIG_NFILE_DESCRIPTOR > 0' was wrong in both of these files. It should + be '#if CONFIG_NFILE_DESCRIPTORS > 0'. This causes a dup2() failure in THTTPD + and a failure to get a CGI page. The consequence can be a very serious bug! + * configs/lpcxpresso-lpc1768/usbstorage, thttpd, and dhcpd: Add an USB storage, + THTTPD web server, and DHCP server configurations for the NXP LPCXpresso board. + * drivers/lcd/ug-9664hswag01.c and ssd1305.h: Add support for Univision UG-9664HSWAG01 + OLED with Solomon Systech SD1305 LCD controller. + * configs/lpcxpresso-lpc1668/nx: Add a NX graphics configuration for the LPCXPRESO + board. + * graphics/nxglib/nxglib_nonintersecting.c: Fix some single bit errors in + calculation of non-intersecting regions. This was causing an anomaly + in examples/nx in column 0. + * drivers/mtd/rammtd.c: Added a RAM based MTD driver. This RAM driver simulates + FLASH and is useful for testing purposes. + * arch/arm/src/arm/up_head.S: Fix backward conditional compilation. This cause + the configs/mx1ads configuration to fail to build but does not appear to affect + any other ARM9 build. + * fs/nxffs: Adding a tiny, wear-leveling FLASH file system for NuttX. This + file system is intended to be small and will have some limitations. The + implementation is incomplete on initial checkin. + * apps/examples/nxffs and configs/sim/nxffs: Add a test a a configuration that + will be used to verify NXFFS. + * fs/fat/fs_fat32.c and fs_fat32util.c: Incorpated two bugs with fixed provided + by Sheref Younan. Thanks! + * fs/nxffs: After a couple of weeks of testing and bug fixes, NXFSS appears + stable and functional. + +6.3 2011-05-15 Gregory Nutt + + * Remove clock_getutc(). It is replaces with clock_gettime(CLOCK_ACTIVETIME). + Add other RTC related changes provided by Uros Platise. + * arch/arm/src/stm32/stm32_flash.c: Add support for access to on-chip STM32 + FLASH; beginning of integration with NXFFS (Uros Platise). + * arch/mips: Added directory structure for PIC32 support + * configs/pcblogic-pic32mx: Add directory structure for PCB Logic PIC32MX board + * apps/include: Move include/apps to apps/include. A symbolic link is created at + build time + * Makefile: Removed support for Pascal pcode interpreter. Support for that + interpreter has been moved to apps/interpreter/Makefile. + * tools/mkdep.sh: Should not report an error if there are no files on the command + line. This happens normally in certain configurations. + * drivers/usbhost: Sheref Younan reported an error in the error handling when + connection to a USB device fails. In certain fail cases, the logic would try + to free the device class instance twice, the first was okay, but the second + caused a crash. + * graphics/nxbe/nxbe_colormap.c: Fix error noted by Bassem Fahmy. The function + nxbe_colormap was change to nxbe_configure... apparently "search-and-replace" + error. This error was not noticed before because most NX platforms do not use + colormapping. + * arch/rgmp and configs/rgmp. Add architecture support and build + configuration for RGMP. RGMP is a project for running GPOS and + RTOS simultaneously on multi-processor platforms. See + http://rgmp.sourceforge.net/wiki/index.php/Main_Page for further + information about RGMP. + * lib/stdio/lib_fclose.c: Must flush all buffered data when the file is closed. + Instead, it was discarding the buffered data. + * lib/stdio: All output stream logic was modified to support CONFIG_STDIO_LINEBUFFER. + If standard C buffered I/O is enabled (CONFIG_STDIO_BUFFER_SIZE > 0), then this + option may be added to force automatic, line-oriented flushing the output buffer + for putc(), fputc(), putchar(), puts(), fputs(), printf(), fprintf(), and vfprintf(). + When a newline is encountered in the output string, the output buffer will be + flushed. This (slightly) increases the NuttX footprint but supports the kind of + behavior that people expect for printf. + +6.4 2011-06-06 Gregory Nutt + + * lib/drivers/cc1101: Add initial, functional CC1101 wireless driver + (contributed by Uros Platise) + * arch/mips and configs/pcblogic-pic32mx: The MicroChip PIC32MX port is now + code complete and ready to begin testing. Unfortunately, it looks like + testing will be delayed due to tool issues (My PICkit 2 will not work the + the MPLAB debugger on PIC32; I will need to get a PICkit 3). + * drivers/net/e1000.c/h: A PCI-based E1000 Ethernet driver submitted + by Yu Qiang. + * lib/net/lib_inetaddr.c: An implementation of the inet_addr() function + submitted by Yu Qiang. + * arch/arm/src/lpc31xx and arch/arm/include/lpc31xx: Renamed from lpc313x + to make name space for other famiy members. + * arch/arm/*/lpc31xx: Added support for the LPC315x family (untested). + * sched/task_exithook.c: Functionality performed when a task exits or is + deleted has been moved to a common file task_exithook.c. Now exit() + functionality (like flushing I/O and calling registered atexit() + functions, etc.) will be performed when a task is deleted as well. + * mm/: Added support for CONFIG_MM_SMALL. Each memory allocation has a + small allocation overhead. The size of that overhead is normally + determined by the "width" of the address support by the MCU. MCUs + that support 16-bit addressability have smaller overhead than devices + that support 32-bit addressability. However, there are many MCUs + that support 32-bit addressability *but* have internal SRAM of size + less than or equal to 64Kb. In this case, CONFIG_MM_SMALL can be + defined so that those MCUs will also benefit from the smaller, 16- + bit-based allocation overhead. + * lib/string/lib_strndup.c: Add standard strndup() library function. + * net/getsockname.c: Added standard getsockname() to return the local + address associated with a socket. + * lib/stdio/lib_asprintf.c: Add asprintf() + * configs/olimex-lpc1766stk/ftpc: Add a configuration to support + testing of the FTP client shell. + * fd/fs_fdopen.c and net/net_checksd.c: Add support so that fdopen may + be used with socket descriptors. + * net/recvfrom.c: Fix an error found in receiving small files via FTP: + The small file is received a buffered in the readahead buffer, then the + socket is disconnected. When the app calls recvfrom, the socket is + already disconnected and the buffered data is stranded. Now, recvfrom + will continue to return success after the socket is disconnected until + the readahead buffer is drained. + * olimex-lp1766stk/ftpc/defconfig: Many configurations have the MTU + (CONFIG_NET_BUFSIZE) set to very small numbers, less then the minimum + MTU size that must be supported -- 576. This can cause problems in + some networks: CONFIG_NET_BUFSIZE should be set to at least 576 in + all defconfig files. This has only been fixed in this defconfig file. + +6.5 2011-06-21 Gregory Nutt + + * arch/avr/src/avr and arch/avr/include/avr: Adds general support for + the Atmel 8-bit AVR family. + * arch/avr/src/atmega and arch/avr/include/atmega: Adds support for the + Atmel AVR ATMega family. + * arch/avr/src/at90usb and arch/avr/include/at90usb: Adds support for the + Atmel AVR AT90USB family. + * configs/micropendous3: Adds a board configuration for the Opendous + Micropendous 3 board. This board may be populated with several different + members of the Atmel AVR AT90USB family. + * configs/amber: This is a placehold for the Atmel ATMega128 Amber Web + Server from SoC Robotics. Not much present in this directory on initial + check-in. + * configs/teensy: Adds a board configuration for the PJRC Teensy++ 2.0 board + that features an Atmel AT90USB1286 MCU. + * fs/fat: Offsets, sector numbers, etc. need to be off_t, not size_t. size_t + is intended to be the maximum size of a memory object, not a file offset. This + does not make any difference except on systems (like the AVR) where size_t + is only 16-bits. + +6.6 2011-07-11 Gregory Nutt + + * drivers/mtd/ramtron.c, net/net_checksd.c, fs/fs_fdopen.c, and include/nuttx/mii.h: + Several structural changes made to get a clean compile under the ez80 ZDS-II + toolchain (no design changes). + * drivers/usbhost/usbhost_storage.c: Incorpated bugfixes reported by Sheref H. + Younan: (1) Read capacity logic read largest block, not the number of blocks + and was, therefore, off by one, and (2) Some devices stall of get Max LUN request + if they support only a single LUN. Logic now assumes a single LUN if the get + Max LUN request fails. + * include/nuttx/arch.h, lib/stdio/lib_libvsprintf.c, lib/stdio/lib_fputs.c: Add + a new configuration option to support extracting strings from FLASH or EEPROM + or other memories where the string data cannot be accessed by simply de-referencing + a string pointer. + * arch/sim/src/up_romgetc.c: Used to test the basic logic to access strings + without directly de-referencing a string pointer. + * arch/avr/src/avr/up_romget.c: Used to access strings that lie in the first + 64Kb of FLASH (But I still haven't figured out how to get strings to reside in + FLASH without using the PROGMEM attribute). + * configs/teensy/src/up_spi.c: Correct reading of SD CD and WP pins (was reading + the wrong register. AVR SPI now appears to be functional. + * arch/avr/src/at90usb/at90usb_usbdev.c: Correct USB initialization. Interrupts + were being enabled BEFORE the interrupt handler was attached. + * configs/sure-pic32mx: Add a configuration for the Sure Electronics, "Advanced USB + Storage Demo Board," Model DB-DP11215 (http://www.sureelectronics.net/goods.php?id=1168). + This board features the MicroChip PIC32MX440F512H MCU. (Untested on initial + check-in). + * configs/stm3210e-eval/nsh2: Add another NSH configuration for the STM32 with + some different properties. + * CONFIG_NSH_CONDEV: Add a configuration option to allow using a different character + device (such a a different UART) for the NSH interface. This allows, for example, + debug output to come from the console device while using another device for NSH. + There are some issues on initial check-in: NuttX doesn't have termios and the + console device has special properties that make using NSH awkward. Examples: + No CR-LF expansion, no character echoing, no command line editting. + * arch/arm/src/stm32/stm32_lowputc.c and stm32_serial.c. Correct seversl bugs + involving serial port configuration. These bugs are only critical if you + are trying to using multiple UARTs on STM32. + * configs/stm3210e-eval/src/up_lcd.c: Add a driver for the STM3210E-EVAL's LCD. + * configs/stm3210e-eval/nx: Add NX configuration for the STM3210E-EVAL. + * configs/nuttx/arch.h (and arch/arm/src/stm32, configs/*/src/up_buttons.c): + Standardize interfaces exported for button support and button interrupts. + * configs/stm3210e-eval/src/up_buttons.c: Add interrupting button support. + Also fixes a few errors in STM3210E-EVAL button decoding. + * configs/stm3210e-eval/buttons: Add a configuration to exercise STM3210E-EVAL + buttons. + * arch/arm/src/stm32/stm32_gpio.c: GPIO interrupt handling for pin + numbers were being aliased: 5-9 together and 10-15 together. Extended + the logic to peform decoding of GPIO interrupts and unique dispatching + for all 16 pins. + * configs/stm3210e-eval/nxtext: Add a configuration for the apps/examples/nxtext + example. This example focuses on placing text on the background while + pop-up windows occur. Text should continue to update normally with or without + the popup windows present. + * arch/arm/src/common/up_checkstack.c: ARM stack overflow checking submitted + by Hal Glenn. + * arch/arm/src/lpc17xx: Changes to compile successfully with no serial console + (also submitted by Hal Glenn). + * graphics/nxfonts/nxfonts_convert.c: Fixed a critical bug that caused + when renderer some fonts with bits-per-pixel > 8 + * graphics/nxbe/nxbe_move.c: Fixed an error in the graphics move logic (This + was a previously untested interface). Basically, there is some confusion + between use of (x,y) as a relative offset or as an absolute position. + * graphics/nxbe/nxbe_close.c: Fixed an important graphics system bug: + When a window is closed, the display was not being updated. The old + window graphic was left on the display for a time. + +6.7 2011-08-02 Gregory Nutt + + * Makefile: Added a export target that will bundle up all of the NuttX + libraries, header files, and the startup object into an export-able + tarball. + * arch/arm/src/lpc17xx/lpc17_can.h: Correct some typos in the CAN + register definitions. + * drivers/serial/serialirq.c: Correct an error that can occur if the + serial RX buffer becomes full. Data is now discarded in that case; + before, leaving data in the hardware would cause infinite interrupts + one most MCUs since you must read the data in order to clear the + interrupt. + * arch/arm/src/lpc17xx/lpc17_can.c: Added a CAN driver contributed by + Li Zhuoyi (Lzyy). + * include/stddefs.h and sys/types: Added type wchar_t. + * fs/fat/fat_fat32dirent.c: Move all FAT directory operations to this + new file; Implement VFAT long file name support. + * fs/fat/fat_fat32dirent.c: The configuration CONFIG_FAT_LCNAMES has + been around for some time but never tested until now. This setting + will mimic the NT 8.3 file name behavior: File names or extensions + may be all upper or all lower case (but not mixed). If + CONFIG_FAT_LCNAMES is not selected, all filenames are strictly upper + case. + * configs/stm3210e-eval/nsh2: Console is back on UART1; Added + examplex/nx as an NSH "built-in" command as a demonstration. + * fs/fat/fs_fat32dirent.c: Fix an important bug in the directory + allocation (fat_allocatedirentry()). I looks like it could be + initializing the wrong sectors! NOTE: This function was in + fs_fat32utils.c in earlier releases. + * arch/arm/src/stm32_sdio.c: Correct an important DMA-related bug; + SDIO transfer completion events and DMA completion eventes were + not being coordinated correctly. + * configs/stm3210e-eval/nsh2: Enable FAT long file name support + * sched/sem_timedwait.c: Add the standard sem_timedwait() interface. + * graphics/nxfonts/nxfonts_getfont.c, nxfonts_bitmap.c, + Makefile.source, and include/nuttx/nxfonts.h: Support for multiple + fonts included. A new interface, nxf_getfonthandle() takes a font + ID and returns a handle that is now used at all other font interfaces + to specify which of the multiple fonts to use. + * arch/arm/src/lpc17xx/lpc17_syscon.h: Fix typo (reported by Li Zhuoyi). + * configs/stm3210e-eval/nsh2: Extended to support two new commands: + 'msconn' will connect the USB mass storage device; 'msdis' will + disconnect the USB storage device. + * tools/bdf-converter.c. This C file is used to build the bdf-converter + program. The bdf-converter program be used to convert fonts in Bitmap + Distribution Format (BDF) into fonts that can be used in the NX graphics + system. + * include/nuttx/nx: Move all NX header files from include/nuttx to + include/nuttx/nx. + * drivers/usbdev/usbdev_usbstorage.c and arch/arm/src/stm32/stm32_usbdev.c: + Correct a memory leak when the USB mass storage driver is connected and + then disconnected from the target. The write requests were not being + freed. NOTE that the unregister logic in the STM32 needed to call + stm32_reset() in order to return the write requests to the USB mass + storage driver; it is possible that a similar but could exist for other + architectures. + * graphics/nxfonts/nxfonts_*.h: Add serveral more new fonts + * arch/z80/src/ez80/ez80_serial.c: Fix some errors in serial driver + setup for UART1 (submitted by Paul Osmialowski). + * drivers/input/tsc2007.c and include/nuttx/input/*: Add a generic NuttX + touchscreen interface. Add a driver for the TI TSC2007 touchscreen + controller. + * graphics/nxglib/lcd and fb: Add low level routines to set single pixels. + * lib/math/lib_b16atan2.c: Add a fixed precision atan2() function + * graphics/nxglib/nxglib_splitline.c: Add logic to divide a wide line into + trapezoidal components. + * graphics/nxmu/nx_drawline.c, graphics/nxsu/nx_drawline.c, + graphics/nxtk/nxtk_drawlinewindow.c, graphics/nxtk/nxtk_drawlinetoolbar.c: + Add new line drawing interfaces (untested). + +6.8 2011-08-19 Gregory Nutt + + * arch/arm/src/lpc17xx/chip.h: Fix some chip memory configuration errors + for the LPC1764, LPC1756, and LPC1754 (submitted by Li Zhuoy (Lzyy)) + * arch/arm/src/lpc17xx/lpc17_can.h: Revised CAN driver submitted by + Li Zhuoy (Lzyy). The driver now supports both CAN1 and CAN2. + * arch/arm/sim/up_lcd.c: Add a simulated LCD driver. + * configs/stm3210e-eval/nxlines: Added a configuration to build + examples/nxlines. + * arch/graphics: Used apps/examples/nxlines to (finally) verify the NX + trapezoid drawing functions and (wide) line drawing functions. + * arch/rgmp and configs/rgmp. Yu Qiang has ported RGMP to the OMAP4430 (arm) + pandaboard and release the new RGMP 0.3 version. The main changes are: (1) + Separate configs/rgmp/x86 and configs/rgmp/arm configuration directory, and + (2) Extract architecture dependent code in arch/rgmp/include and + arch/rgmp/src into corresponding x86/ and arm/ directories. + * arch/arm/src/kinetis, arch/arm/include/kinetis, configs/kwikstick-k40: + Add a directory structure to support the port to the Kinetis KwikStik-K40. + There is no real substance in the initial check-in; only the directory + structure and skeleton files (Code complete on 8/15/11). + * arch/arm/include/armv7-m, arch/arm/src/armv7-m, etc.: Rename all cortexm3 + directories and files to armv7-m; Change name of of all CORTEXM3 constants + to ARMV7M. This is a major namespace change needed to cleanly support the + ARM Cortex-M4 which is also in the ARMv7 M Series (specifically, ARMv7E-M). + * sched/sig_initialize.c, sig_received.c, and mq_waitirq.c. Fixed several + critical bugs related to signal handling initialization and for signals + the wake up tasks that are waiting to send or receive message queues. In + the first two files, errors would prevent proper allocation of signal-related + structures from interrupt handlers. In the second, there was missing + "clean-up" logic after a signal occurred, leaving the message queue in + a bad state and resulting in PANICs. All are important. (submitted by + hkwilton). + * arch/arm/src/kinetis: Added header files defining all Kinetis registers + and bit fields within all Kinetis registers. + * configs/twr-k60n512: Add support for the Kinetis K60 Tower board + (TWR-K60N512). + * drivers/can.c: Fixed a semaphore overflow problem in the CAN driver + (reported by Li Zhouy (Lzyy)). + * 8/18/2011: The basic port to the FreeScale Kinetics TWR-K60N512 board is + now functional. + * confgs/twr-k60n512: Add Kinetics TWR-K60N512 NSH configuration. + * drivers/analog and include/nuttx/analog: Add ADC driver infrastructure + and TI ADS1255 driver developed and submitted by Li Zhouy (Lzyy)). + * arch/arm/stm32/stm32_sdio.h and drivers/mmcsd/mmcsd.c: Add logic to + multiplex usage of the GPIO pins (contributed by Uros Platise). + * configs/twr-k60n512/nsh: Added and verified a NuttShell (NSH) + configuration for the Freescale, Kinetis TWR-K60N512 board. + +6.9 2011-09-11 Gregory Nutt + + * arch/arm/src/kinetis/kinetis_sdhc.c: SDHC driver for Kinetis parts. + Initially check-in is just a crude port of the STM32 SDIO driver. + Much more work is needed. + * graphics/, include/nuttx/nx: Add new NX interfaces for drawing + circles -- both circular outlines and filled circles. + * graphic/nxglib/nxglib_spitline.c: Add a "fudge factor" that eliminates + some problems for rendering nearly horizontal, wide lines. Hmm... + but I suspect this fudge factor also leads to new problems rendering + very thin, nearly horizontal lines. More tuning is needed. + * drivers/analog, include/nuttx/analog, arch/arch/src/lpcxx: (1) Add + updates to the ADS1255 driver, (2) fix errors from my last merge (sorry), + (3) Add DAC infrastructure, (4) add AD5410 DAC driver, and (5) add + LPC17xx ADC and DAC drivers. All contributed by Li Zhuoyi (Lzyy). + * tools/mkexport.sh: Extended the script that implements the top-level + 'make export' logic. The script now also finds and bundles up all of + the architecture-specific header files as well. + * drivers/arch/arm/src/stm32/stm32_i2c.c: Add a reset to the I2C + initialization logic to prevent spurious interrupts when the I2C + interrupts are enabled (submitted by Uros Platise). + * Scripts/makefiles/documents. Several adjustments, corrections and + typo fixes so that NuttX will build correctly on FreeBSD using the + ASH shell (submitted by Kurt Lidl). + * drivers/mtd/flash_eraseall.c: Add a callable function that accepts + the path to a block driver and then erases the underlying FLASH memory + (assuming that the block driver is an MTD driver wrapped in the FTL + layer). Hmmm... this is probably not the best long term solution; + flash_eraseall() should be a user-callable function that operates + one driver interfaces; not an internal, OS function that operates + on directly on block drivers. + * drivers/bch: Fixed some important bugs in the BCH driver (noted by + Li Zhuoyi (Lzyy)). This would have effected any large reads or writes + (larger than the hardware sector size). + * arch/*/src/Makefile: Use of -print-libgcc-file-name to get path to + libgcc.a may select the wrong libgcc.a if a multilib toolchain (like + CodeSourcery) is used. This can be a serious problem and can cause + crashes on Cortex-M3 if the ARM libgcc is used, for example. The fix + is to include ARCHCPUFLAGS on the gcc command line when asking it to + -print-libgcc-file-name. + * lib/time/lib_gmtimer.c: Correct several calculations that could lead + to errors in dates. + * drivers/pm: Add the beginnings of a NuttX power management sub-system. + * arch/arm/src/stm32/stm32_irq.c: Fix a error introduced in 6.8. + Timeout calculation uses clock_settime() instead of clock_gettime(). + Pretty gross error, but actually it works with the side effect of setting + a bad time. + * drivers/mtd/at24xx.c: Driver for I2C-based at24cxx EEPROM submitted by + Li Zhuoyi (Lzyy). + * arch/arm/src/lpc17xx/lpc17_i2c.c: I2C driver for the NXP LPC17xx family + submitted by Li Zhuoyi (Lzyy) + * arch/arm/src/stm32_i2c.c: Correct two issues with the STM32 I2C driver: + (1) Clocking needs to be based on PCLK1, not HCLK and fast speed settings + need some additional bits; and (2) Correct a hang that will occur on + I2C1 if FSMC is also enabled. + * drivers/sensors/lm75.c and include/nuttx/sensors/lm75.h: Add an LM-75 + temperature sensor driver. + * configs/stm3210e-eval/src/up_lm75.c: Add support for the LM-75 on the + STMicro STM3210E-EVAL board. + * sched/clock_gettime.c: Correct an error in the tv_nsec calculation + that happens only config CONFIG_RTC is enabled. + * arch/arm/src/stm32/stm32_i2c.c: Correct some bugs related to waiting + for the I2C STOP condition to be cleared. + +6.10 2011-10-06 Gregory Nutt + + * lib/stdio/lib_fopen.c: Fix an error in fopen(); the file pointer was not + being positioned at the end of the file when the "a" and "a+" modes are + used. There are other issues with the "a+" modes (see the top-level TODO + list). + * drivers/usbdev/cdc_serial.c and include/nuttx/usb/cdc.h and cdc_serial.h: + Add support for the CDC ACM serial device class. + * fs/fat/fs_fat32.c: Fix a critical bug in the write logic: It a tiny write + cross a sector boundary, then two sector writes will occur. The first part + in the first sector may be written to the wrong sector number. + * fs/fat/fs_fat32util.c: Fix a stray write into the FAT (always sector 964 on + FAT32). This bug will cause some lost chains. I'm sure this bug could + corrupt files but at present, the only thing I have seen is that before + fixing this bug, the Windows chkdsk utility would report these lost chains. + * arch/arm/src/stm32/stm32_i2c.c: Driver can now operate in a faster polled + mode (at the expense of using more cpu cycles). + * arch/arm/src/stm32/stm32_i2c.c: Add trace debug capability. Enabled with + CONFIG_I2C_TRACE. + * arch/arm/src/stm32/stm32_i2c.c: Fix another bug where I2C conflicts with FSMC + being enabled. That time at the tail end of the transaction where there is + an unfinished stop condition. + * sched/mq_timedreceive.c and sched/mq_timedsend.c: The count of threads + waiting on the message queues was not being decremented after a timeout. + This would cause the accounting logic to become out of sync and the, perhaps, + an assertion to be triggered. This is an important bug and fixes a + potential crash when using mq_timedreceived() and mq_timedsend(). + * sched/mq_sndinternal.c: Related to the above, the send logic was incrementing + the wrong counter when it waited as part of the mq_timedsend.c logic. + * fs/fat: Fix an error in the long file name logic: If the long file name + is an even multiple of 13 bytes in length, then it should not include a + NULL terminating character. Fix contributed by Kaushal Parikh. + * configs/sim/nx11: Created a separate configuration to build the NX + example using the a simulated framebuffer driver on an X11 window. This + example has been verified on Ubuntu 9.09 (it does not work on Cygwin). + * arch/sim/src/up_touchscreen.c and up_x11eventloop.c: Adds support for a + simulated NuttX touchscreen device using mouse/pointer feedback from an + x11 window. + * configs/sim/touchscreen: Adds a configuration to verify the simulated + touchscreen driver (Does not work on Cygwin). + * configs/sam3u/touchscreen: This is the configuration that I plan to use + to verify the SAM3U-EK touchscreen driver. However, as of this writing, + there is no touchscreen driver for the board. + * CONFIG_RTC_HIRES: Add an option to support either a high-resolution RTC + that completely replaces the system timer tick but may overflow and lose + time when the MCU is off and also for a low-resolution (1 sec/tick) RTC + that can run until 2106 with no overflow. But in this latter case, higher + resolution time must come from the system timer. + * CONFIG_SYSTEM_UTC: Removed support for the UTC system timer. It just + doesn't do enough to be worth the CPU cycles or the complexity. + * CONFIG_SYSTEM_TIME16: Added support for an optional 64-bit system timer. + * fs/fat/fs_fat32util.c: Add support for FAT date/time stamps; Enabled via + CONFIG_FS_FATTIME. + * arch/arm/src/sam3u/sam3u_spi.c: Add an SPI driver for the AT91SAM3U. + * drivers/input/ads7843e.c and include/nuttx/input/ads7843e.h: Add a + driver for the TI ADS7843E touchscreen controller. + * fs/nxffs/nxffs_open.c: Fix an error when a file is open for writing; since + the file will get deleted it is already exists, there must be a check if + there are other open references to the file. + * arch/arm/src/stm32/stm32_sdio.c: Fixed an error where during SDHC + initialization interrupts were not being re-enabled. Caused more subtle + errors than you would think. + * arch/arm/src/stm32/stm32_i2c.c: Fixed an error where I2C timeouts appeared + to be successful transfers. + * configs/sim/nsh2: Add another simulated NSH configuration. This one + supports X11 graphics, C++, and exercises graphic functions as built-in + commands. + +6.11 2011-11-12 Gregory Nutt + + * arch/arm/stm32/Make.defs: Don't build stm32_rtc.c if CONFIG_RTC is not + selected. Doing so will cause errors if other configuration dependencies + are not met. + * configs/stm3210e-eval/src/up_lcd.c: Color corrections for SPFD5408B LCD + do not work with R61580 LCD. + * configs/pic32-starterkit: Beginning of a configuration for the Microchip + PIC32 Ethernet Starter Kit. Hmmm.. I don't have a clue how to test this + with no serial port?! + * lib/stdio/lib_fclose.c: fclose() always returns an error (EOF) when it + closes a read-only file. This is because it calls flush() which will + fail on read-only files. No harm is done other that a bad value is + returned. + * arch/sim/src/Makefile: Correct build issue for sim/nsh2 target. Old + libboard.a was not being cleaned. + * arch/mips/src/pic32mx/pic32mx-gpio*.c: Add GPIO support for the PIC32MX. + * configs/sure-pic32mx/src/up_leds.c and up_buttons.c: Add button and LED + support for the Sure Electronics PIC32MX board. + * configs/ea3152: Add a configuration for the Embedded Artists LPC3152 + daughter board (with the same base-board used with configs/ea3131) + * graphics/nxmu/nx_getrectangle.c, graphics/nxsu/nx_getrectangle.c, + graphics/mxtk/nx_getwindow.c, graphics/nxmu/nx_gettoobar.c: New + interfaces to read from graphics memory + * graphics/nxbe/nxbe_bitmap.c: Fix an error in the error handling that + can cause valid bitmaps to fail to render. + * include/nuttx/rgbcolors.h: Fix errors in some 16- and 8-bit color + conversion macros. + * tools/incdir.sh: Fix issues when g++ is used as the compiler. It was + not being recognized and handled properly. + * graphics/nxsu/nx_releasebkgd.c: Fix a bad cast that was causing + problems with the background window was released. + * fs/nxffs/nxffs_pack.c: Correct a critical bug in the NXFFS file system: + When repacking the filesystem, there was a missing check to see if an + inode structure would fit at the end of a block. This is a rare case + if the block size is large, but can be common for tiny block sizes + and results in a crash and file system corruption. + * fs/nxffs/nxffs_initialize.c: Fix an initialize error. If the FLASH + is full on power-up, NXFFS will fail to initialize correctly. + * fs/nxffs/nxffs_write.c and nxffs_pack.c: Fix an error that can occur + when attempt to write to FLASH volume that is completely full but + has no value inodes on it. + * drivers/mtd/at24xx.c: Now supports a configurable block size that + supports using "clusters" of AT24 pages as blocks. This allows bigger + block sizes and more efficient use of EEPROM when the AT24 is used to + support a file system (such as NXFFS). (Contributed by Hal Glenn). + * include/nuttx/rgbcolors.h: More fixes to RGB color conversion + macros. + * arch/arm/src/common/up_createstack.c and up_usestack.c: For ARM EABI + the stack must be aligned to 8-byte boundaries. This is necessary for + passing aligned floating point values under EABI. Fix contributed by + David Sidrane. + * Numerous changes and fixes to the PIC32 interrupt handing logic. The + PIC32 port is almost complete but still not ready for prime time. + +6.12 2011-12-06 Gregory Nutt + + * fs/fat/fs_fat32util.c and fs_fat32.h: Logic extended to look in up to + four partitions for a valid FAT file system. + * drivers/input/tsc2007.c: Add support for 8-bit conversions; make sure + that A/D converters are active before requesting conversions. + * drivers/mmcsd0/mmcsd_sdio.c: Increase capacity variable from size_t + to uin64_t (if available) so that SD cards with capacities greater + than 4Gb can be supported. + * fs/fat/fs_fat32dirent.c: The root directory structure is different + from other directories. When formatted by Windows, it is not initialized + at all. Some additional special handling is required to initialize the + root directory entry to interoperate correctly with windows. + * fs/fat/fs_fat32util.c: In fat_systime2fattime(void) should be + clock_gettime() and not clock_gettime(). Also, there is a place where + FAT date is used instead of FAT time. (Thanks to David Sidrane). + * arch/arm/src/stm32 and arch/arm/include/stm32: Add support for the + STM32F40xxx family of MCUs. + * configs/stm3240g-eval: Add framework for the STMicro STM3240G-EVAL + board. + * include/sys/types.h: wchar_t is a builtin type in C++ and its + declaration can cause errors with certain C++ compilers. + * sched/sig_timedwait.c: Fix signal handling when the returned info + is NULL. Before this change, it would derefence a NULL pointer + in this case. + * graphics/nxfonts/nxfonts_sans17x22.h and nxfonts_sans20x26.h: Add + some very small sans serif fonts. + * graphics/nxfonts/nxfonts_sans17x23b.h and nxfonts_sans20x27b.h: Add + corresponding sans serif bold fonts. + * drivers/input/ads7843e.c and tsc2007.c: Fix some errors in the poll + setup error checking that was cloned into both drivers. + * sched/mq_notify.c: Set errno appropriately on failures. There are + still several message queue functions that do not set errno! + * arch/arm/src/stm32: Fixes to several STM32F40xxx files (contributed by + Mikhail Bychek). + * configs/stm3210e-eval/src/up_lcd.c: Fix banding problem on the R61580 + LCD + * configs/stm3240g-eval/ostest: The basic STM32F40xx bringup is functional + (11/12/06) for the STM3240G-EVAL board and passes the OS test. + * configs/stm3240g-eval/nsh: Adds a NuttShell (NSH) configure for the + STM3240G-EVAL board. + +6.13 2011-12-26 Gregory Nutt + + * arch/arm/src/stm32/stm32f40xxx_dma.c: Add DMA support for the STM32 F4 + family (untested on initial check-in) + * arch/arm/src/armv7-m/up_fpu.c: Add logic for saving an restoring VFP + floating point registers on context switches (but also disable the FPU + because CodeSourcery doesn't support hard flowing point!) + * arch/arm/src/stm32/chip/stm32_eth.h: Add Ethernet register definitions + for the STM32 F4. + * arch/arm/srcm/stm32/stm32_eth.c: Adds an Ethernet driver for the STM32 F4. + * arch/arm/srcm/stm32/stm32_dac.c and stm32_adc.c: "Skeleton" files for STM32 + DAC and ADC drivers. The actual logic will come later. + * arch/arm/srcm/stm32/stm32_eth.c: There may be a few more lurking bugs, but + the STM32 Ethernet driver appears to be fully functional on the STM3240G-EVAL. + * arch/arm/srcm/stm32/stm32_eth.c: Fix an error in clearing abnormal interrupt + events. + * configs/stm3240g-eval/dhcpd: Add a DCHP daemon configuration for the + STM3240G-EVAL board. + * configs/stm3240g-eval/nettest: Add a network test configuration for the + STM3240G-EVAL board. + * arch/arm/srcm/stm32/stm32_rtc.c, stm32f10xxx_rtc.c, and stm32f40xxx_rtc: + Broke out separate drivers to handle the very different RTC implementations + in the STM32 F1 and F4 family. + * arch/arm/srcm/stm32/stm32f10xxx_rtc.c: STM32 F4 RTC is functional (12/14/2011) + * net/uip-arp.c: Fix compilation issue with CONFIG_NET_ARP_IPIN + * include/nuttx/pwm.h and drivers/pwm.c: Add an interface definition and a + "upper half" driver for PWM output. + * arch/arm/src/stm32/stm32_pwm.c: Added a PWM "lower half" driver for the + STM32. The initial check-in is little more than a framework for the driver. + * arch/arm/src/stm32/stm32_usbdev.c: Corrected two CRITICAL errors in the USB + device-side driver: (1) Handling of data overrun condition was wrong. When + there was no further memory to accept further OUT endpoint data, the driver + would hang with infinite interrupts; (2) the logic in setting toggle bits + was not correct. However, this driver has functioned for a long time until + the particular condition that revealed the bug occurred. My impression is + that this latter bugfix also fixes some STM32 USB performance problems. + * configs/hymini-stm32v: A configuration for the HY-Mini STM32v board contributed + by Laurent Latil. Theses changes also include support for the STM32F103VCT6. + * arch/configs/stm3240g-eval/src/up_pwm.c: Add hooks needed to use the new + apps/examples/pwm test of the STM32 PWM driver. + * drivers/mtd/mp25x.c: Add ability to use different SPI modes and different + manufacturers codes. Fix a error in the wait for not busy (submitted by + Mohammad Elwakeel. + * arch/arm/src/stm32/stm32_can.c: Add a low-level STM32 CAN driver. (Initial + check is incomplete). Add loopback support to the driver. + * arch/arm/src/stm32/stm32_adc.c: The ADC is now functional. A more complete + driver would require DMA support. I have some questions still about the + accuracy of the timer-driven sampling. + * configs/sure-pic32mx/nsh: The PIC32 port is (finally) functional. Add an + NSH configuration for the Sure PIC32MX board. + * configs/sure-pic32mx/*/defconfig. Calibrated all PIC32 delay loops. + * configs/pcblogic-pic32mx/nsh: Add an NSH configuration for the PCBLogic + PIC32 board. + * Both PIC32 OS test and NSH configurations have now been verified. + +6.14 2012-01-15 Gregory Nutt + + * tools/Makefile.export, mkexport.sh, and configure.sh: Changes submitted + by Mike Smith to support configuration and 'make export' on MAC OS. + * arch/arm/src/stm32/stm32_gpio.c: Disabled interrupts while configuring + GPIO pins so that we have exclusive access to the GPIO configuration + registers. + * arch/mips/src/pic32mx/pic32mx_usbdev.c: Add a USB device-side driver + for the PIC32MX family. + * arch/arm/src/stm32/stm32_gpio.c: Correct an error in some of the GPIO + initialization logic. Fix submitted by Mike Smith. + * configs/olimex-lpc1766stk/src/up_leds.c: Add new interfaces so that is + CONFIG_ARCH_LEDS are not set, the LEDs may be controlled from application + logic. + * configs/olimex-lpc1766stk/src/up_buttons.c: Add support for the buttons + on the Olimex LPC1766-STK board. + * Makefile: Added 'apps_clean' and 'apps_distclean' target to simplify + managing the state of the application directory while in the NuttX directory + * Documentation/NuttXGettingStarted.html: Added a "Getting Started" Guide + for NuttX. At present, this is just a stub and it refers to the NuttX + top-level README.txt file which is the only, real "Getting Started" Guide + that exists at the time being. + * arch/arm/src/lpc17xx/lpc17_gpioint.c: Correct an value used as the lower + end of an IRQ number range test. + * arch/arm/src/lpc17xx/lpc17_gpio.c: Fix a integer flow problem in shift. + This error would prevent pins > 15 from being used as interrupt sources. + * arch/arm/src/stm32/stm32_can.c: The CAN driver has been verified in + loopback mode on the STM3240G-EVAL board. + * configs/stm3240g-eval/src/up_adc.c: Complete coding of ADC support for the + potentiometer on board the STM3240G-EVAL. + * arch/arm/src/lpc17_can.c: Several CAN driver improvements. Adds support for + testing in loopback mode. now uses all three transmit buffers for better + performance. + * confgs/olimex-lpc1766stk/nsh: Now supports the CAN loopback test as an + optional "built-in" application. + * sched/irq_attach.c: Fix an issue with disabling interrupts when they are + detached. For the PIC32, this can't be done because there is a 1-to-many + relationship between vector numbers and interrupt numbers or different. + Added a new configuration option CONFIG_ARCH_VECNOTIRQ to at least flag + the architectures that have this issue and to (at least) avoid doing + something too wrong. + * drivers/can.c: Fix a test for buffer full in the generic, "upper half", + can driver. + * arch/arm/src/lm3s: Add support for the LM3S6432S2E (Contributed by Mike Smith) + * configs/lm3s6432-s2: Add support for the TI RDK-S2E (LM3S6432S2E) board + (Contributed by Mike Smith) + * configs/stm3240g-eval/src: Add APIs support to support user access to the + LEDs + * arch/arm/src/lpc17xx/lpc17_can.c: Add logic to change the CAN bit rate based + on the NuttX configuration. + * arch/arm/src/lpc17xx/lpc17_can.c: PCLK divisor is now a configuration + option. + * arch/arm/src/stm32/stm32_serial.c and stm32_lowputc.c: Support for + UART4-5 and USART6 added by Mike Smith. Also includes a more flexible + way of managing UART pin configurations. + * include/nuttx/pwm.h, drivers/pwm.c, arch/arm/src/stm32/stm32_pwm.c: Add + support for pulse count in order to better support stepper motors. + * arch/arm/src/stm32/stm32_dumpgpio.c: Checking wrong register to see if + GPIO is enabled. Also not adding the GPIO base address to several offsets. + * configs/stm32f4discovery: Port to the STMicro STM32F4Discovery board + (Contributed by Mike Smith). + * fs/fat/fs_fat32util.c: On a failure to recognize a FAT file system, the + mount logic should return -EINVAL, not -ENODEV. + * arch/arm/src/stm32/stm32_tim.c: Support for STM32 F4 32-bit timers + (Contributed by Mikhail Bychek) + * lib/stdio/lib_vsprintf.c: Add support for fixed-size fields with floating + point numbers (Contributed by Mikhail Bychek) + +6.15 2012-02-12 Gregory Nutt + + * arch/arm/src/stm32/stm32_pwm.c: Pulse count was limited to 128; now is + (essentially) unlimited. + * configs/stm3240g-eval/include/board.h: Input frequencies wrong for all but + one APB2 timer. + * arch/mips/src/pic32mx/pic32mx-ethernet.c: The PIC32 Ethernet driver is + code complete, but still untested. + * confgs/sim/*/Make.defs and arch/sim/src/Makefile: Add support for building + a 32-bit executable on a 64-bit Linux target. + * configs/sure-pic32mx/src/up_leds.c: Correct GPIOs used for LEDs. The wrong + pins were being used. + * arch/arm/src/stm32/chip/stm32f10xxx_gpio.h: Correct offset to one AFIO EXICR + register. + * arch/arm/src/lpc17xx/lpc17_can.c: Added "advanced" configuration options + to specify the CAN TSEG1 and TSEG2 clock counts specifically. + * include/nuttx/can.h and drivers/can.c: Add support for extended (29-bit) + CAN IDs. + * arch/arm/src/lpc17xx/lpc17_can.c: Add support for extended (29-bit) CAN IDs. + * arch/arm/src/stm32/stm32_can.c: Add support for extended (29-bit) CAN IDs. + * include/nuttx/power/pm.h: Move include/nuttx/pm.h into a sub-directory named + power. + * drivers/power: Rename the drivers/pm directory to power + * include/power/battery.h and drivers/battery.c: Add the interface definitions + for an upper and lower half battery driver. Add the implementation of the + common upper half battery driver. + * drivers/power/max1704x.c: Add a driver for MAX17040x battery "fuel gauge" + * arch/arm/src/stm32/stm32_i2c.c: Add support for I2C3 + * drivers/usbdev/: Lots of name changes: cdc_serial->cdcacm, usbstrg->usbmsc, + usbser->pl2303 + * drivers/usbdev/composite: Fleshed out support for a composite USB device. + * drivers/stm3210e-eval/composite and drivers/stm3210e-eval/src/up_composite.c: + Add a configuration test the USB composite device. + * include/nuttx/usb/usb.h, drivers/usbdev/composite_descriptors.c, and + drivers/usbdev/cdcacm_descriptors.c: Add support for the USB Interface + Association Descriptor (IAD) + * arch/arm/src/stm32/stm32_i2c.c: Correct a typo in STM32 I2C3 support + (submitted by Mike Smith) + * arch/*/src/Makefile: Candidate solution for dependency issue in the board + sub-directory: By making libboard.a a "phony" target, libboard.a should + always rebuilt (the end result is worth the small increase in build time) + (submitted by Mike Smith). + * include/net/psock.h: Added a new low level socket interface that allows the + OS to use the socket interface without having a socket descriptor. + * include/net/psock.h: Removed psock.h. The new interfaces are moved into + nuttx/net.h which already has similar logic. + * include/nuttx/usb/usb.h: Can't use 'class' as a field name in USB structures. + This upsets C++ if usb.h is included. 'class' -> 'classid' in this header + file and all places that referenced 'class' + * drivers/usbdev/usbmsc.c: Fixed some backward conditional compilation. + * sched/on_exit.c: Add support for the on_exit() function., + * sched/exit.c, task_exithook.c, task_delete.c, sched_releasetcb.c: Move + the logic that closes file descriptors sooner in the task shutdown sequence. + When drivers are closed, they may need to do things that require a fully + up-and-running task. Some things cannot be done later when the task is + crippled. + * lib/dirent: Moved readdir_r() and telldir() from lib/misc to this new + directory where they belong. + * lib/termios. Implemented tcsetattr() and tcgetattr(). + * lib/stdio/lib_fgets.c: The old fgets includes some terminal related + functionality: It handles VT-100 commands, includes a command line editor + and echo characters back to the terminal. This old, overloaded fgets() + was renamed readline() and moved to apps/system/readline. The version + of fgets() in lib/stdio was them simplified and stripped down so that it + *only* gets a string -- as its description implies. + * arch/arm/src/lpc214x/lpc214x_usbdev.c: Add corrections suggested by + David Hewson many, many months ago. + * configs/mcu123-lpc214x/composite and configs/mcu123-lpc214x/src/up_composite.c: + Add a configuration to test the USB composite device. + * configs/stm3240g-eval/Telnetd: Add a configuration for testing the + Telnet daemon. + * configs/stm3240g-eval/nsh2: This is another NSH configuration. It differs + from the original nsh configuration because it does not have an RS-232 + console (only a Telnet console) and SDIO is enabled. This configuration is + required because the STM3240G-EVAL board cannot simultaneously support + RS-232 and SDIO due to pin conflicts. + * lib/string/lib_strcasestr.c: Add strcasestr(). + * lib/stdio/lib_avsprintf.c: Add avsprintf(). + * lib/net/lib_inetntop.c: Add inet_ntop(). + * lib/net/lib_inetpton.c: Add inet_pton(). + * include/pthread.h: Correct PTHREAD_MUTEX_INITIALIZER. + * fs/fat/fs_fatfs.c: Fix an error in the FAT statfs() implementation that + was causing some block counts to be reported incorrectly (reported by + David Sidrane). + * drivers/ramlog.c: Add a character driver that can substitute + for /dev/console and or be used for logging debug output when there + is no serial port available (such as when a Telnet console is used). + * lib/stdio/lib_syslogstream: Add a stream object that will be used to + re-direct all debug output to the RAM log if CONFIG_SYSLOG and + CONFIG_RAMLOG_SYSLOG are defined. + * lib/misc/lib_dbg.c: Add an interface enabled with CONFIG_DEBUG_ENABLE that + can be used to turn debug output on and off. + +6.16 2012-03-10 Gregory Nutt + + * drivers/sensors/qencoder.c and include/nuttx/sensors/qencoder.h: Add an + implementation for a quadrature encoder upper half driver. + * arch/arm/src/stm32/stm32_qencoder.c/.h: Add a initial implementation of + a lower-half quadrature encoder driver for the STM32. On initial check-in, + this is little more than a "skeleton" file. + * Various files: CAN ISO-11783 support contributed by Gary Teravskis. + * net/recv.c and net/recvfrom.c: Correct a bug in return value: The the peer + gracefully closes the connections, needs to return zero and not ENOTCONN. + * arch/arm/src/stm32/stm32_eth.c: Fix an error in the STM32 ethernet driver. + The received buffer size must be two bytes larger to account for the two byte + checksum that is appended to the packet. Otherwise, the last two bytes of + real data in the packet will get clobbered. + * arch/arm/src/stm32f40xx_dma.c: The STM32 F4 DMA has (finally) been verified + * arch/arm/src/stm32_sdio.c: STM32 F4 SDIO DMA is now supported + * configs/stm3240g-eval/nsh/defconfig: This configuration now supports SDIO + with DMA (see configs/stm3240g-eval/README.txt for some issues). + * arch/arm/src/armv7-m/up_vectors.S and arch/arm/src/armv7-m/up_vectors.S: New, + streamlined Cortex-M exception handling (with FPU supported). Contributed byh + Mike Smith + * net/accept.c, connect.c,and net_monitor.c: Correct an error in the accept + logic. After a new connection is made via accept(), monitoring for losses + of TCP connection must be set up (just as with connect()). The new file + net_monitor.c holds the common TCP connection monitoring logic used by both + the accecpt() and connect() logic. Contributed by Max Nekludov. + * net/recvfrom.c and net/uip/uip_tcpcallback.c: Fix a leak in the TCP + read-ahead logic. This is a *critical* bug fix! + * net/uip/uip_tcpinput.c: Correct an error in the TCP stack. It was + incrementing the received sequence number BEFORE determining if the + incoming data could be handled. If the data was dropped (usually because + there is insufficient buffering space), then no ACK will be sent and the + sequence number will be wrong. The end consequence of the bad sequence + number was that the when the dropped packet was re-transmitted, it was + was ignored because its sequence number looked wrong. Fix was, obviously, + to only increment the recevied sequence number if the TCP data was + accepted. + * configs/stm3240g-eval, configs/stm32f40discovery, and arch/*/src/Makefile: + Add changes to support building with the Atollic "Lite" toolchain. + * fs/fs_select.c: Correct select(), in the case of loss of network + connection (POLLHUP), select() must report a read-ready event. This + is how the standard select() interface is supposed to work: In the case + of loss-of-connection, select() reports read-ready. The next time you + read from the socket, you detect the end-of-connection event. Change + submitted by Max Nekludov. + * arch/arm/src/armv7-m/up_fpu.S and arch/arm/src/stm32/stm32_vectors.S: Fix + lazy FPU register saving with CONFIG_ARCH_FPU is set in the configuration. + * arch/arm/src/armv7-m: Lazy saving of floating point registers on context + switches now seems to be functional. + * net/uip/uip_tcpinput.c: Fix a TCP protocol error reported by Max Nekludov. + * configs/stm3240g-eval, configs/stm32f40discovery: Add changes to support + building with the Atollic "Pro" toolchain. + * Makefile: Use the more common .hex extension for Intel hex files instead of + more precise .ihx extension. This change has ripple effects to many build- + related scripts and programs and could cause some short-term problems. + * configs/stm3240g-eval/, arch/arm/src/stm32/up_allocateheap.c: Add support + for the 16-mbit SRAM on-board the STM3240G-EVAL board. + * drivers/usbdev/cdcacm.c and include/nuttx/usbdev/cdcacm.h: The CDC/ACM + driver can now be dynamically connected and disconnected from the host + under software control. + * include/nuttx/arch.h, configs/stm3240g-eval/src/up_cxxinitialize.c, and + configs/stm3240g-eval/src/up_cxxinitialize.c: Add support for C++ static + initializers. + * net/setsockopt.c, net/getsockopt.c, net/bind.c, net/socket.c: Add more + low level, thread-independent socket interfaces for use within the OS. + Some of these are currently used by the FTP controlling terminal. More will + be used to support the NFS file system currenly underwork. + * include/nuttx/net/: Major re-organization of networking headerf files. + Moved all non-standard, NuttX-specific header files from include/net and + include/nuttx into include/nuttx/net. + * arch/mips/src/pic32mx/pic32mx_usbdev.c: The PIC32 USB driver now appears to + be fully functional. + * configs/sure-pic32mx/usbnsh and configs/sure-pic32mx/src: Add support for + NSH using only USB serial I/O to support the console. This is useful on + devices that have USB, but no serial port. + * arch/mips/src/pic32mx/pic32mx_spi.c: Add a PIC32 SPI driver. Initial + checkin is primitive, incomplete (lacks interrupt logic), and untested. + * configs/pic32-startkit/nsh: Completed verification of the PIC32 Ethernet + Starter Kit port. Added and verified the NuttShell (NSH) on the PIC32 + Ethernet Starter Kit. I can now (finally) claim to have complete the + basic port to this board. + * configs/pic32-startkit/nsh/up_usbdev, up_nsh.c, and up_usbterm.c: Verified + the USB (device) driver on the PIC32 Ethernet Starter Kit. + * arch/mips/src/pic32mx/pic32mx_ethernet.c: Verified the PIC32 Ethernet + driver on the PIC32 Starter Kit. Status: It is occasionally functional + but not stable enough for use. + * arch/arm/include/stm32, arch/arm/src/stm32: Add general support for + the STM32 F2 family. Contributed by Gary Teravskis, + * configs/stm3220g-eval: Add support for the STMicro STM3220G-EVAL board. + Contributed by Gary Teravskis, + +6.17 2012-04-14 Gregory Nutt + + * configs/sure-pic32mx: Add support for the Sure DB-DP11212 PIC32 General + Purpose Demo Board + * arch/arm/src/stm32/stm32_usbhost.c/.h: Add files that will (eventually) + hold an STM32 USB host driver (the initial check-in is the NuttX LPC17 + USB host driver with name changes only). + * arch/arm/src/stm32/chip/stm32_otgfs.h: STM32 USB OTG FS register + definitions (not complete on initial check-in). + * net/connect.c: Add another low level, thread-independent socket interface + for use within the OS. + * arch/mips/src/pic32mx/pic32mx_ethernet.c: The PIC32 Ethernet driver + is now stable on the PIC32 Starter Kit. + * configs/pic32-starterkit/nsh2: Add a PIC32 Ethernet Starter Kit NSH + configuration that has no serial console; all interaction is done via + Telnet. + * net/netdev_sem.c: Correct a deadlock condition by making a seamphore + recursive. To my knowledge this deadlock only occurs when running the + NSH command ifconfig over Telnet. In that case the function netdev_foreach + takes the network device semaphore, but so does the telnet logic causing + the deadlock. + * arch/arm/src/stm32/stm32_pm*.c: Add basic STM32 power management logic + that will eventually be used to implement low power states. + * arch/arm/src/stm32/stm32f*0xx_rcc.c: In order to use CAN2, both CAN1 and + CAN2 clocking must be enabled. + * arch/mips/src/pic32mx/picm32mx-usbdev.c: Several stall-related fixes so that + the USB device driver can used the the mass storage class (which does a LOT + of stalling as part of its normal protocol). The PIC32 USB Mass Storage + device is, however, still non-functional when debug is OFF. + * include/nuttx/fs: Move all file-system related files from include/nuttx to + include/nuttx/fs. + * include/nuttx/serial: Move all serial-driver related files from include/nuttx to + include/nuttx/serial. + * include/nuttx/clock.h and sched/clock_initialize.c: Add a new OS interface + called clock_sychronize() that can be used to re-synchronize the NuttX + system time with a hardware RTC. This function is called normally at power + up but may also need to be called when recovering from certain low-power + usage states where the system time is no longer accurate. + * arch/arm/src/calypso and arch/arm/include/calypso: Support for the TI "Calypso" + phone processor. Contributed by Denis Carilki and includes the work of Denis, + Alan Carvalho de Assis, and Stefan Richter. + * configs/compal_e88 and configs/compal_e99: Support for Compal e88 and e99 phones + Contributed by Denis Carilki and includes the work of Denis, Alan Carvalho de + Assis, and Stefan Richter. + * arch/arm/src/lpc17xx: Several fixes for error that have crept in for the LPC17xx + DAC. Contributed by by Lzyy. + * graphics/nxconsole: Add a character driver that can be used as a console output + device for text output (still under development on initial check-in). + * graphics/nxmu: Fix several compilation errors that have crept into the multi- + user NX server because of lack of use. + * graphics/nxconsole: The NX text console is basically function (in multi- + user NX mode only). + * arch/arm/src/stm32/stm32_i2c.c: Correct a bug in the STM32 I2C driver. The + behavior of I2C status bits seems to be different between F1 and F4. + * configs/stm3210e-eval/nxconsole: New STM32 F1 configuration that runs the + NuttShell (NSH) within an NX window. + * graphics/nxconsole/nxcon_sem.c: Add protection from re-entrance with debug + is enabled. + * include/nuttx/ascii.h and vt100.h: Header files to centralize ASCII and + VT100 escape sequence definitions. + * graphics/nxconsole/nxcon_vt100.c: Add add framework to support VT100 escape + sequences in NxConsole. + * fs/fs_read.c: Fix read() return value for attempt to read from write-only + file or device. Was returning EBADF, should return EACCES. + * graphics/nxconsole.c: NxConsole now supports backspace and a cursor. + * Kconfig and arch/sim/Kconfig: Beginnings of support for a NuttX + configuration tool. Currently using the kconfig parser 'kconfig-frontend' + available at http://ymorin.is-a-geek.org/projects/kconfig-frontends + (version 3.3.0-1 is also available in the NuttX SVN at + trunk/misc/tools/kconfig-frontends-3.3.0-1.tar.gz). Contributed by Lzyy. + * */Kconfig: Added skeleton Kconfig files to all directories that + may need them. + * include/nuttx/math.h: Moved include/math.h to include/nuttx/math.h + because it conflicts too often with the system math.h (and people aren't + inclined to read the documentation on how to handle this). Now, if + CONFIG_ARCH_MATH_H=y is defined, the top-level makefile will copy + the redirecting math.h header file from include/nuttx/math.h to + include/math.h. So for the architectures that define CONFIG_ARCH_MATH_H=y, + include/math.h will be in place as it was before; for the architectures + that don't select CONFIG_ARCH_MATH_H, the redirecting math.h header + file will stay out-of-the-way in include/nuttx/. + * Kconfig, sched/Kconfig, lib/Kconfig, libxx/Kconfig, arch/sim/Kconfig, + drivers/Kconfig, drivers/mtd/Kconfig, drivers/input/Kconfig + drivers/analog/Kconfig, drivers/lcd/Kconfig: Updated kernel + configuration support provided by Lzyy. + * Kconfig: Many more Kconfig updates (no longer tracking in the ChangeLog) + * arch/arm/src/Makefile, arch/x86/src/Makefile, arch/avr/src/Makefile, + arch/mips/src/Makefile, arch/sim/src/Makefile, arch/hc/src/Makefile, + arch/sh/src/Makefile: The libgcc.a in newer versions of GCC now + have an dependency on an external implementation of abort(). This + required modification to the Makefiles that do the final link: Now + libgcc.a must be included within the group of libraries that are + search recursively. + * arch/arm/srm/stm32/stm32_otgfsdev.c: A USB OTG FS device-side driver + for the STM32 F4 (and maybe F2 and F1 connectivity line). + * tools/cmpconfig.c: A tool for comparing two configuration files. + * include/nuttx/usb/usbdev.h, drivers/usbdev/*, arch/*/src/*/*usb*.c: + Extend the USB device side interface so that EP0 OUT data can be passed + with OUT SETUP requests. + * include/nuttx/watchdog.h: Add the definition of a standard watchdog + driver interface. + * drivers/watchdog.c: The "upper half" watchdog timer driver. + +6.18 2012-05-19 Gregory Nutt + + * Kconfig: Continued Kconfig file updates (no longer tracking on a per-file + basis in the ChangeLog) + * arch/arm/src/stm32/stm32_iwdog.c and stm32_wwdog.c: Add the STM32 IWDG + and WWDIG watchdog timer driver. + * configs/stm3240g-eval/src/up_lcd.c: Add LCD from for the STM3240G-EVAL (the + initial check-in is just a stm3210e-eval driver with renaming). + * sched/sched_setscheduler.c: Correct successful return value (Contributed + by Richard Cochran). + * include/fcntl.h and lib/stdio: Ignore CONFIG_STDIO_LINEBUFFER is the + file was opened in binary mode. + * lib/stdio/lib_fopen.c: Correct an error in parsing open mode string. The + plus sign may not appear right after the basic mode. For example, "r+", "rb+", + and "r+b" are all valid open strings and mean the same thing. + * lib/stdio/lib_fopen.c: Correct return errno value from f_open() and + f_fdopen() if the open mode string is invalid. + * drivers/serial/serial.c: Do not disable Rx interrupts on each byte. + Rather, only disable Rx interrupts when the Rx ring buffer may be empty. + * include/nuttx/usb/audio.h: USB Audio 1.0 definitions (in progress). + * arch/arm/src/stm32/stm32fxx_dma.c: STM32 F4 DMA now supports circular + buffer mode (contributed by Mike Smith) + * arch/arm/src/stm32/stm32_serial.c: The serial driver can now support + Rx DMA into a circular buffer (contributed by Mike Smith) + * configs/pic32mx7mmb: Beginning of a configuration for the Mikroelektronka + PIC32MX7 Multimedia Board (MMB). + * net/recvfrom.c: Fix a compilation problem. Some UDP logic was conditioned + on TCP, not UDP. + * drivers/usbdev/cdcacm.c: Fix an infinite loop that occurs when the serial + device is unregisters. + * arch/arm/src/stm32/stm32_otgfs.c: The driver needs to reset the software (in + order to flush the requests) and to disable the software connection when the + device is unregistered. + * include/sys/prctl.h, sched/prctl.c, include/pthread.h: Add interfaces to + support getting and setting of the thread or task name. + * configs/ubw32: Added a configuration to support the Sparkfun UBW32 PIC32 board. + * configs/ubw32/nsh: Added an NSH configuration for the Sparkfun UBW32 PIC32 board. + * configs/ubw32/up_buttons.c: Added button support for Bit Whacker board. + * configs/stm3240g-eval/nxconsole: Added a configuration to run the NSH + shell in an NX window for the STM3240G-EVAL board. + * include/cxx/cunistd: C++ header file to make sure that everything in + unistd.h is in the std:: namespace. + * configs/sim/nxwm: Added a configuration for testing the NuttX Window Manager + (NxWM) + * fs/fs_fcntl.h: On success, always returned OK. However, some fcntl commands + require returning other values on success. + * Various files. Fix warnings about variables that were initialized by not used. + * configs/sim/*/defconfig: Changes to build a 32-bit simulation on a 32-bit + platform did not make into all of the Make.defs files. + * graphics/nxmu/nx_move.c: Wrong opcode was being used in the server message; + Also there was an error in the offset calculation. + * graphics/nxglib/fb/nxglib_moverectangle.c: Offset argument is really a + position, not an offset. + * graphics/nxtk/nxtk_drawframe.c: Framed windows are now drawn in three + colors (instead of just two). + * drivers/input/stmpe811_*: Added a driver to support the STMicro STMPE811 + IO Expander and touchscreen driver. + * configs/stm3240g-eval/nxwm: Added to configuration for testing the NxWM + window manager on the STM3240G-EVAL board. + * graphics/nxtk/nxtk_toolbarbounds.c: Added an interface to get the toolbar + bounding box. + * graphics/nxtk/nxtk_drawframe.c: Fix an error in drawing the window frame. + * NX, NxConsole: Replace CONFIG_NXCONSOLE_NOGETRUN to CONFIG_LCD_GETRUN. The + inability to read from the LCD is a property of the LCD, not of NxConsole. + Then add CONFIG_NX_WRITEONLY which is the more generic way of saying that + no NX component should try to read from the underlying graphic device (LCD + or other). + * configs/stm3240g-eval/src/up_stmpe811.c: Add board-specific support for the + the STMPE811 I/O expander on the STM3240G-EVAL board. Verfied that the + STM3240G-EVAL touchscreen is now fully functional. + * include/cxx/cfcntl: Added std:: header file. + * graphics/nxbe/nxbe_filltrapezoid.c and graphics/nxglib/fb/nxglib_filltrapezoid.c: + Fix several errors in the trapezoid fill logic. + * include/nuttx/input/touchscreen.h, configs/hymini-stm32, configs/stm3240g-evel, + * configs/sam3u-ek, configs/sim, arch/sim/src/up_touchscreen.c, and + apps/examples/touchscreen: Standardize the board-specific, touchscreen + initialization interfaces. + * drivers/input/stmpe811_base.c and configs/stm3240g-eval: The STMPE811-based + touchscreen seems to work better with edge (vs. level) interrupts + * drivers/input/stmpe811_tsc.c: Fix some status checks so that the touchscreen + interrupt handling logic does not read data if the fifo is not at the + threshold level. + * include/nuttx/wqueue.h: Add macro work_available() to determine if the + previously scheduled work has completed. + * drivers/stmpe811_tsc.c: Correct errors: (1) Since all interrupt logic is done on + the worker thread, disabling interrupts does not provide protected; Need to + disable pre-emption. (2) Fix handling of touch ID and (2) add some logic to + prevent certain kinds of data overrun. + * include/nx/nxtk.h and graphics/nx/nxtk/nxtk_internal.h: Move setting + of configuration defaults from the internal header file to a place where + other logic can use the defaults. + * graphics/nxtk/nxtk_events.c: Fixed an important but in the logic that + translates the mouse/touchscreen position data for framed windows and toolbars. + * drivers/input/stmpe811_tsc.c, tsc2007.c, and ads7843e.c: Need to keep track of + when if positional data is valid. When the touch is released, the X/Y position + of the release must be the same as the X/Y position of the last touch (se that + the release occurs in the same window as the last touch). + * graphics/nxtk/nxtk_events.c: Fix an error in mouse/touchscreen input logic: + Was autoraising the window AFTER processing the mouse press. This raises havoc + if the result of processing the mouse click was to raise some other window! + * graphics/nxtk/nxtk_events.c: I had to disable the whole autoraise feature + for multi-user case because it does not work correctly. In a scenario where (1) there + are multiple queued touchscreen events for the same window and (2) the result of the + first input was to switch windows, then the autoraise implementation will cause the + window to revert to the previous window. Not good behavior. + * sched/sched_mergepending.c: Add task switching instrumentation. There is a case + here where instrumentation was missing. Contributed by Petri Tanskanen. + * CONFIG_STMPE811_THRESHX, CONFIG_STMPE811_THRESHX, and drivers/stmpe811_tsc.c: Add some + thresholding controls to all slow down processing of touchscreen samples. + This is a problem with NX in multi-user mode: touchscreen data gets sent + via a message and when the message queue gets full the sender blocks and + touch events are lost. Basic data overrun. The badly effects touchscreen + human factors. + * include/sched.h: Fix a typo (missing semicolon) in prototype of on_exit(); + * sched/on_exit.c and include/nuttx/sched.h: Fix some old typos that caused + compilation errors when CONFIG_SCHED_ONEXIT is defined. + * configs/stm3240g-eval/nxwm/defconfig: The default NxWM now uses the STMPE811 + touchscreen. + * include/cxx/csched: Added + * graphic/nxmu/nxmu_sendserver.c, nxmu_sendwindow.c, and nxmu_sendclient.c: + Refactor NX messaging logic in preparation for a new message control + feature. + * graphics/nxtk, graphics/nxmu, include/nuttx/nx: Add a new window communication + to support blocking and flushing of client window messages. If there are + stale, queue window messages at the time that a window is destroyed, very bad + things happen. + +6.19 2012-06-15 Gregory Nutt + + * graphics/nxconsole/nxcon_kbdin.c: If selected, the NxConsole will take + input from the NX keyboard input callback. If this option is set, then + the interface nxcon_kdbin() is enabled. That interface may be driven by + window callback functions so that keyboard input *only* goes to the top + window. If CONFIG_NXCONSOLE_NXKBDIN is not selected, then the NxConsole + will receive its input from stdin (/dev/console). This works great but + cannot be shared between different windows. Chaos will ensue if you + try to support multiple NxConsole windows without CONFIG_NXCONSOLE_NXKBDIN + * graphics/nxmu/nx_kbdin.c: Fix pointer argument. This is a error + introduced in changes leading up to the 6.18 release. This error will + cause crashes or perhaps simply not work when you try to handle window + keyboard data in multi-user mode. + * graphics/nxconsole/nxcon_kdbind.c: Fixed unmatched sem_wait and sem_post. + Fix some conditional compilation that included a few too many lines of code. + * drivers/input/stmpe811_tsc.c and stmpe811.h: Add a timeout to catch missed + pen up events. Now the STM3240G-EVAL touchscreen works very smoothly. + * configs/stm3240g-eval/nxwm/defconfig: Enable support for NxConsole keyboard + input. Increasing spacing of icons. + * configs/stm3240g-eval/nxwm/defconfig: Use a larger font for the calculator. + * include/nuttx/lcd/ssd1289.h, drivers/lcd/ssd1289.c and .h: Generic LCD + driver for LCDs based on the Solomon Systech SSD1289 LCD driver. This + of this as a template for an LCD driver that will have to be cusomized + for your particular LCD hardware. + * configs/stm32f4discovery/src/up_extmem.c and up_ssd1289.c: Add support to + STM32F4Discovery for than an external, SSD1289-based LCD. + * configs/stm32f4discovery/nxlines: Add an STM32F4Discovery configuration + to thest the SSD1289-based LCD. + * configs/stm3240g-eval/src: Add USB GPIO initialization logic needed + in board-specific boot logic. + * configs/stm32f4discovery/src: Add USB GPIO initialization logic needed + in board-specific boot logic. + * drivers/usbdev/pl2303.c and cdcacm.c: Fix the request size used for sending + packets. It was not using the maximum request size, but instead the previous + request size. As a result, packets get smaller, and smaller, and ... This + is an important USB serial fix. + * arch/arc/src/stm32_otgfsdev.c: Bug fix: Don't process TXFE if we have + already processed an XFRC interrupt. We have already done what needs + to done in that case. + * arch/arc/src/stm32_otgfsdev.c: Fixed some status settings in queuing of write + messages. Added a "hack" to work around missing TxFIFO empty interrupts. The + hack is basically to poll for space in the TxFIFO instead of of setting up + the interrupt. + * arch/arm/src/stm32/stm32f2* and chip/stm32f2*: Update all STM32 F2 file so + that they are equivalent to F4 files. This is kind of a maintenance nightmare. + * configs/stm3220g-eval/: Update existing configurations to the same level + as the corresponding STM3240G-EVAL configurations. This adds FSMC SRAM, + touchscreen, and LCD support. + * configs/stm3220g-eval/: Add a NxWM configuration for the STM3220G-EVAL. + * stmpe11*: Fix a massive naming problem. All references to STMPE11 should be + STMPE812. + * arch/arm/src/stm32/stm32_otgfsdev.c: Need to enabled USB reset interrupt + (contributed by Erik Van Der Zalm). + * sched/sleep.c: Fix the return value from sleep(). The correct behavior is + to return the number of unwaited seconds; the implementation was always + returning zero. + * sched/usleep.c and include/unistd.h: Was a void function, but should return + 0 on success. usleep() needs to check the return value from sigtimedwait(). + sigtimewait() returns the signal number that awakened it and an error (EAGAIN) + if the timeout expired (normal case). + * sched/sig_timedwait.c: Fix sigtimedwait() return value. On a timeout, it was + setting the 8-bit si_signo field to -1 and eded up reported successfully awakened + by signal 255! Now detects the timeout and errors -1 with errno == EGAIN. If + sigtimedwait() is awakened by an unblocked signal, but it is not one of the + signals in the waited-for set, it will return -1 with errno == EINTR. + * arch/arm/src/stm32_i2c.c: Fix STM32 F2 I2C. It is apparently bug-for-bug + compatible with the F4 and needs the same work-around for the missing BTF + signal that was needed for the F4. + * drivers/lcd/ssd1289.*: Fix some of the initial register settings. + * configs/stm32f4discovery/src/up_ssd1289.c: FSMC address bit 16 is used to + distinguish command and data. But FSMC address bits 0-24 correspond to ARM + address bits 1-25, se we need to set bit 17 in order generate output on + FSMC_A16. + * arch/arm/src/lm3s/lm3s_epi.h and lm3s_timer.h: LM3S header files + (contributed by Max Neklyudov). + * arch/arm/src/stm32/stm32_irq.c: Some of the interrupt priorities were + not be initialized (F2 and F4 only). Thus, the very high numbered + interrupts (like UART6) and cause nested interrupts. This leads to + some very difficult to debug crashes. Fix contributed by Mike Smith. + * arch/mips/src/pic32/pic32_head.S and pic32_config.h and + configs/pic32mx7mmb/include/board.h: Extended PIC32 device configuration + capabilities and change board.h to support unique clocking requirements + of the Mikroelektronika PIC32MX7 MMB. That board now works! + * configs/pic32mx7mmb/nsh: Added and verify a NuttShell configuration + for the Mikroelektronika PIC32MX7 MMB board. + * arch/mips/pic32/pic32mx-ethernet.c: Fix logic that guesses PHY address; + the search loop missed the PHY address needed by the Mikroelektronika + PIC32MX7 MMB board. + * configs/pic32mx7mmb/nsh: Configuration now supports a network by default. + * configs/pic32mx7mmb/src: Add support for the MMC/SD slot on board + the Mikroelektronika PIC32MX7 MMB board (not working on initial check-in). + * arch/mips/src/pic32/pic32mx-spi.c: Add support for very low-level, + register access debug output. + * configs//pic32mx7mmb/include/board.h: Reduced peripheral clock to + 4MHz to match other PIC32 configurations. + * configs/pic32mx7mmb/src/up_nsh.c: SD card needs to operate in SPI + mode 2. + * configs/pic32mx7mmb/nsh/defconfig: MMC/SD card support is now + enabled by default in the PIC32MX7 MMB board configuration. + * configs/pic32mx7mmb/nsh/defconfig: Verified the USB Mass Storage + Class (MSC) using MMC/SD card as the logical unit. Updated the default + PIC32MX7 MMB board configuration so that USB and the mass storage class + are enabled by default. + * drivers/lcd/mio283qt2.c and include/nuttx/lcd/mio283qt2.h: Add generic + support for the MIO283QT2 LCD. + * configs/pic32mx7mmb/src/up_mio283qt2.c: Add support for the MIO283QT2 + LCD on the PIC32MX7 MMB board. + * configs/pic32mx7mmb/src/up_touchscreen.c: Add an ADC-based touchscreen + driver for the PIC32MX7 MMB board. Kind of works, but needs more + verification and tuning. + * arch/mips/src/common/up_idle.c: Strange but important fix. For some still- + unknown reason, interrupts are left in an unhealthy state in the IDLE + when the work queue is enabled. This is partially because some interrupt + related logic is not built in that case. Simply disabling then re- + enabling interrupts restores the proper state. + * graphics/nxglib/lcd/nxglib_filltrapezoid.c and fb/nxglib_filltrapezoid.c: + Fix an error when the trapezoid is only 1 line high. In this case, a + divide by zero error would occur. The fix is to draw the 1 line high + trapezoid as a run. + * drivers/usbdev/pl2303.c: Fix a cut'n'paste error that snuck into + the PL2303 emulation driver several months back. + +6.20 2012-07-12 Gregory Nutt + + * configs/stm3210e-eval/src and arch/arm/src/stm32/: Add beginnings of + power management support for the STM32 and the STM3210E-EVAL board, in + particular. + * Documentation/NfsHowTo.html: Add a How-To document for the new NFS + client feature. + * arch/mips/include/pic32mx and arch/mips/src/pic32mx: Add support for the + PIC32MX1 and PIC32MX2 families. + * configs/mirtoo: Add a board configuration to support the DTX1-4000L + "Mirtoo" module from http://www.dimitech.com/ + * tools/pic32mx: All of the duplicate directories containing the same + same PIC32 tools were move to this single location. + * configs/mirtoo: The basic Mirtoo port is now functional. + * configs/mirtoo/ostest: Added support for the microchipOpen toolchain + (see http://sourceforge.net/projects/microchipopen/). + * configs/mirtoo/nsh: Added a NuttShell (NSH) configuration for + the Mirtoo module. + * configs/mirtoo/scripts: Move all Mirtoo linker scripts to a common + directory. + * arch/mips/src/pic32mx/pic32mx-gpio.c: All digital inputs were being + configured as outputs. This is a *critical* bug fix and needs to be + incorporated by any PIC32 users. + * drivers/mtd/sst25.c: Added a driver for the SST 25 SPI-based FLASH + parts. + * configs/mirtoo/src/up_nsh.c: The Mirtoo NSH configuration can now + mount the SST 25 devices so that it can be used for a FAT file system. + There are are, however, some NSH memory usage issues if this configuration + enabled now. Some tuning is still needed. + * configs/mirtoo/nxffs: Add an alternative NSH configure for the Mirtoo + module for testing the on-module SST 25 chip using the NXFFS file system. + * arch/arm/src/lpc43xx and arch/arm/include/lpc43xx: The NXP LPC43xx port + is slowly evolving in these directories. + * configs/stm3210e-eval/pm: Add a new configuration for testing STM32 power + management. + * configs/stm3210e-eval/scripts: Moved all of the duplicate ST3210-EVAL + linker scripts into one set of linker scripts at this location. + * configs/stm3210e-eval/src/up_buttons.c, up_lcd.c, and up_pm.c: New logic + for testing STM32 power management. + * configs/lincoln60: Add a configuration to support the Micromint Lincoln60 + board. + * configs/ekk-lm3s3b96: Add a configuration to support the TI/Stellaris + EKK-LM3S3B96 development board. Contributed by Jose Pablo Rojas V. + * arch/arm/src/lpc43xx/chip: Created header files for *all* (really) + lpc43xx registers and all bit-fields. + * configs/lpc4330-xplorer: Added a configuration for the NXP LPC43XX + Xplorer board. This is just to facilitate testing of the LPC43xx + port but will, with any luck, become proper board support for that + board. + * arch/arm/src/lm3s/lm3s_syscontrol.c: Fix an optimization related problem + by adding a volatile qualifier to a timing loop. Oddly, the consequence + of the bug is that when debug was off, the LM3S platform too a long time + to boot. It now boots rapidly whether debug is on or off. + * arch/*/include/limits.h: Change all values in all limits.h for all + architectures to signed decimal; the hex values were not sign extending + appropriate in most uses (reported by Lorenz Meier). + * arch/arm/src/stm32/chip/stm32f103/7vc_pinmap: Fix typographical error in + two pinmap definition files. + * lib/net/lib_inetntoa.c: Fix typographical error that cause compilation + failure on platforms that do not support passing of structures as + parameters. + * arch/arm/*/lpc43xx and configs/lpc4330-xplorer and code complete and + ready for testing. Hopefully, verified LPC43xx support will appear + in NuttX-6.20. + * include/nuttx/stdarg.h: If CONFIG_ARCH_STDARG_H=y is defined, the top-level + makefile will copy the generic (GCC-only) stdarg.h header file from + include/nuttx/stdarg.h to include/stdarg.h. So for the architectures + that cannot use their GCC toolchain's stdarg.h file, they can use this + alternative by defining CONFIG_ARCH_STDARG_H=y. If CONFIG_ARCH_STDARG_H, + is not defined, then the redirecting stdarg.h header file will stay + out-of-the-way in include/nuttx/. + * configs/lpc4330-xplorer/nsh: Add an NSH configuration for the LPC4330 + Xplorer board. + +6.21 2012-xx-xx Gregory Nutt + + * configs/lpc4330-xplorer/up_nsh.c: Add support for a basic SPIFI block + driver for use by NSH. Does not work! Crashes on first SPIFI write. + * configs/lpc4330-xplorer/*/defconfig: Calibrate delay loops (this is + based on the current "slow" 72MHz M4 clock and will need to be + re-calibrated when this is increased). + * configs/stm3220g-eval/include/board.h and configs/stm3240g-eval/include/board.h: + The SDIOCLK frequency in the F2 and F4 derives for PLL48CLK and not HCLK + so that the SDIOCLK input frequency should always be 48MHz. + * sched/os_internal.h, sched_setupidlefiles.c, sched_setuptaskfiles.c, and + sched_setupidlefiles.c: Detangle some conditional compilation. Allow for + a perverse configuration that has socket descriptors and streams but no file + descriptors (sure, why not?). + * sched/: Stylistic clean-up of all files. Some of these files are pretty old + and do not follow current NuttX coding standards in detail. + * fs/: More stylistic file clean-up. + * mm/: More stylistic file clean-up. + * drivers/ and drivers/serial/: More stylistic file clean-up. + * arch/arm/src/lpc43xx/lpc43_clockconfig.c: Fix PLL1 bit manipulation logic. + Critical bugfix! This would often cause the LPC43xx to fail to boot. + * arch/arm/src/lpc43xx/lpc43_rgu.c: The soft reset logic called from the + beginning of __start seems cause problems. A magic delay seems to improve + the logic some. But I suspect that real fix is to get rid of all of the + soft reset logic. This would also be a critical bugfix if I believed + that it really fixed all of the issues. + * arch/arm/src/lpc43xx/chip/lpc43_cgu.h: Fix a bit mask in the PLL1 + control register. Critical bugfix. + * arch/arm/src/lpc43xx/lpc43_clockconfig.c and configs/lpc4330-xplorer/include/board.h: + Implement PLL1 ramp-up logic; Now the LPC43xx is running at 204MHz. + * configs/lpc4330-xplorer/*/defconfig: Re-calibrated delay loops using + the 204MHz clock. The LPC43xx ripping rips! This calibration was performed + with symbols enabled and all optimization disabled. It will need to be + better recalibrated again down the road. + * arch/arm/src/stm32/stm32_exti.c: Renamed to rch/arm/src/stm32/stm32_exti_gpio.c + to make a little room in the file name space. + * arch/arm/src/stm32/stm32_exti_alarm.c: Add initial logic to attached the + RTC alarm EXTI interrupt. This is work be performed mostly by Diego Sanchez. + * include/: More stylistic file clean-up. + * arch/arm/src/lpc43xx/lpc43_spifi.c, lpc43_spifi.h, and chip/lpc43_spifi.h: Add + logic to configure and initialize the SPIFI device (does not yet work). + * configs/lpc4330-xplorer/include/board.h: Reduce SPI SCLK value. + * arch/arm/src/lpc43xx/lpc43_spifi.c, lpc43_spifi.h, and chip/lpc43_spifi.h: + Logic completely redesigned. It now creates an MTD driver to access SPIFI... + but the driver still does not work. + * arch/arm/src/stm32 and arch/arm/include/stm32: Make name of RTC ALARM interrupt + common on STM32 F1,2,4 + * arch/arm/src/stm32 and arch/arm/include/stm32: Add add support for the + STM32F100x "Value Line" devices. This includes changes to stm32F10xx_rcc.c that + add the ability to run the chip off the internal oscillator. There is no open + board configuration for this part yet (the STM32VLDiscovery would be a candidate). + Contributed by Mike Smith. + * arch/arm/src/stm32: Fixed typos in conditional compilation in the CAN and DMA + and some pin configuration. This would have caused problems for STM32 F107xx. + Typos noted by Mike Smith. + * arch/arm/src/lpc43xx/lpc43_serial.c: Add support for certain RS-485 features + * lib/termios/lib_cfsetispeed.c, lib_cfsetospeed.c, lib_tcflush.c: Add + simple implementations of cfsetispeed(), cfsetospeed(), and tcflush(). + * include/sys/str_tty.h, lib/lib_setspeed.c, lib_getspeed.c, and lib_resetspeed.c: + Add APIs to support setting non-standard BAUD values not supported by POSIX + termios. These are non-standard interfaces but have a precedence: There are + similar interfaces in AIX. + * include/sys/str_tty.h, lib/lib_setspeed.c, lib_getspeed.c, and lib_resetspeed.c: + Sigh... removed. We don't need any more almost standard interfaces! (SVN + revision 4968 if you want the short-lived code). + * include/termios.h and lib/termios/*: Open the existing, standard termios + interfaces to permit some non-standard baud settings. The new termios definitions + still supports the POSIX standard except that it does not strictly enforce + baud rate settings, permitting some non-portable, but useful baud rate settings + (this is what the short-lived AIX-like interfaces would have accomplished as well). + * include/termios.h and lib/termios/*: Redesigned yet again (this is getting + painful. NuttX now supports the BOTHER baud setting just as Linux does. termios + Bxxx definitions are again encoded; cf[set|get][o|i]speed now deal with only the + encoded values. If the encode baud is set to BOTHER, then the values in the (non- + standard) c_ispeed and c_ospeed baud values may be accessed directly. + * arch/arm/src/stm32/stm32_serial.c: Add minimal termios support for the STM32 + (BOTHER style baud settings only). Contributed by Mike Smith. + * configs/lpc4343-xplorer/src: Clean up SPIFI-library based build to that it + actually works. + * arch/arm/src/lpc43xx/lpc43_spifi.c: Add support for verification to writes. + Add debug option to dump buffers. Several bugfixes... almost works. + * include/termios.h, lib/termios/*, and arch/arm/src/stm32/stm32_serial.c: : + BOTHER is gone again. + * arch/arm/src/stm32/stm32_sdio.c and chip/stm32f20xx_pinmap.h: STM32 F2 SDIO + fixes from Gary Teravskis and Scott Rondestvedt. + * include/termios.h and lib/termios/*: Replace cfsetispeed and cfsetospeed with + cfsetspeed (with definitions for the input/outputs in termios.h). Same for + cfgetispeed and cfgetospeed. + * configs/stm32f4discovery/src and configs/stm32f4discovery/pm: Add a power + management configuration for the STM32F4Discovery and supporting logic. This + check-in also includes some fixes for the F4 RTC alarm logic. + * drivers/input/pga11x.c and include/nuttx/input/pga11x.h: Add support for the + TI PGA112/3/6/7 amplifier/multiplexer parts. + * configs/mirtoo/README.txt, nsh/defconfig, and nxffs/defconfig: Add support + for the PGA117 on the Mirtoo module. + * drivers/analog/pga11x.c and include/nuttx/analog/pga11x.h: These belong in + the analog subdirectories, not input. + * configs/compal_e99/src/ssd1783.c and /ssd1783.h: Drivers for the SSD1783 + LCD found in the Motorola C155 telephone. The driver is specific to the C155 + because it uses the uwire transport. Contributed by Denis Carilki and + Alan Carvalho de Assis. + * drivers/power/pm_changestate.c. Correct a case where interrupts were not + being re-enabled. Found by Diego Sanchez. + * configs/mirtoo/nxffs/defconfig: This Mirtoo NXFFS configuration now uses the + open Pinguino toolchain by default. This is necessary because the free C32 + toolchain does not support any optimization and the unoptimized NXFFS image + hits the PIC32MX2 FLASH size (128K). There is plenty of room to grow using + the Pinguino toolchain with -O2 optimization. + * configs/mirtoo/src/up_adc.c. This is just a stub for now, but this is + where Mirtoo ADC logic will eventually need to go. + * arch/mips/src/pic32mx/pic32mx-gpio.c: Now supports the PIC32MX1/2 ANSEL + IOPORT register. + * lib/string/lib_memchr.c: Add support for memchr() (contributed by Mike Smith) + * lib/string/lib_memccpy.c: Add support for memcpy() + * arch/arm/src/lpc17xx/lpc17_serial.c: Now supports ioctl commands to change + the baud using tcsetattr() (contributed by Chris Taglia). + * arch/*/src/*_serial.c: Fix ioctl method return values. Theses methods + should return a negated errno value; they should not set the errno + variable. + * sched/on_exit.c, sched/task_exithook.c, and include/nuttx/sched.c: Add + support for multiple registered on_exit() functions if CONFIG_SCHED_ONEXIT_MAX + is defined. + * drivers/syslog/ramlog.c: Move the RAM SYSLOG device into drivers/syslog + so that it will be in the same directory as some new SYSLOGing devices + in the works. + * include/nuttx/syslog.h and drivers/syslog/ramlog.c: The SYSLOG putc function + now has a common name that is independent of the device that provides the + SYSLOG. + * include/nuttx/syslog.h and drivers/syslog/syslog.c: This is a new, generic + SYSLOG device that can redirect debug output to any character device or file. + So you can log debug output to a file or you can put the console on /dev/ttyS0 + and the debug output on /dev/ttyS1. + * arch/arm/src/lpc43xxl/lpc43_spifi.c: Correct an addressing error in the LPC43 + SPIFI MTD driver + * drivers/syslog/syslog.c and fs/fs_syslog.c: Moved the generic syslog logic + from drivers/syslog to fs/ where is belongs. Especially after realizing that + the syslog logic is going to have to some internal FS operations in order + to realize a totally thread-independent SYSLOG interface. + * arch/arm/src/stm32/stm32*_rcc.c and .h: If CONFIG_PM is defined, add a + function called stm32_clockenable() that can be used by PM logic to re-start + the PLL after re-awakening from deep sleep modes. + * fs/fs_foreachinode.c and fs/fs_foreachmountpoint.c: All logic to traverse + inodes and mountpoints in the NuttX psuedo-file system. + diff --git a/nuttx/Kconfig b/nuttx/Kconfig new file mode 100644 index 0000000000..7a8ba9bf28 --- /dev/null +++ b/nuttx/Kconfig @@ -0,0 +1,289 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +mainmenu "Nuttx/$ARCH Configuration" + +config APPSDIR + string + option env="APPSDIR" + +# This is a temporary kludge to let the build system know that we are using the new +# configuration system + +config NUTTX_NEWCONFIG + bool + default y + +menu "General Setup" +config EXPERIMENTAL + bool "Prompt for development and/or incomplete code/drivers" + +menu "Build Configuration" +config APPS_DIR + string "Application directory" + default "../apps" + ---help--- + Identifies the directory that builds the + application to link with NuttX. Default: ../apps This symbol must be assigned + to the path to the application build directory *relative* to + the NuttX top build direcory. If you had an application + directory and the NuttX directory each in separate directory + trees like this: + + build + |-nuttx + | | + | `- Makefile + `-application + | + `- Makefile + + Then you would set CONFIG_APPS_DIR=../application. + + The application direction must contain Makefile and this make + file must support the following targets: + + libapps$(LIBEXT) (usually libapps.a). libapps.a is a static + library ( an archive) that contains all of application object + files. + + clean. Do whatever is appropriate to clean the application + directories for a fresh build. + + distclean. Clean everthing -- auto-generated files, symbolic + links etc. -- so that the directory contents are the same as + the contents in your configuration management system. + This is only done when you change the NuttX configuration. + + depend. Make or update the application build dependencies. + + When this application is invoked it will receive the setting TOPDIR like: + + $(MAKE) -C $(CONFIG_APPS_DIR) TOPDIR="$(TOPDIR)" + + TOPDIR is the full path to the NuttX directory. It can be used, for + example, to include makefile fragments (e.g., .config or Make.defs) + or to set up include file paths. + +config BUILD_2PASS + bool "Two pass build" + default n + ---help--- + Enables the two pass build options. + + Two-pass build options. If the 2 pass build option is selected, then these + options configure the make system build a extra link object. This link object + is assumed to be an incremental (relative) link object, but could be a static + library (archive) (some modification to this Makefile would be required if + CONFIG_PASS1_TARGET generates an archive). Pass 1 1ncremental (relative) link + objects should be put into the processor-specific source directory (where other + link objects will be created). If the pass1 obect is an archive, it could + go anywhere. + +if BUILD_2PASS +config PASS1_TARGET + string "Pass one target" + default "" + ---help--- + The name of the first pass build target. This + can be specific build target, a special build target (all, default, etc.) + or may just be left undefined. + +config PASS1_BUILDIR + string "Pass one build directory" + default "build" + ---help--- + The path, relative to the top NuttX build + directory to directory that contains the Makefile to build the + first pass object. The Makefile must support the following targets: + The special target CONFIG_PASS1_TARGET (if defined) + and the usual depend, clean, and distclean targets. + +config PASS1_OBJECT + string "Pass one object" + default "" + ---help--- + May be used to include an extra, pass1 object + into the final link. This would probably be the object generated + from the CONFIG_PASS1_TARGET. It may be available at link time + in the arch//src directory. + +config NUTTX_KERNEL + bool "NuttX kernel build" + default n + ---help--- + Builds NuttX as a separately compiled kernel. +endif +endmenu + +menu "Binary Output Formats" + +config RRLOAD_BINARY + bool "rrload binary format" + default n + ---help--- + Create nuttx.rr in the rrload binary format used with + BSPs from www.ridgerun.com using the tools/mkimage.sh script. + +config INTELHEX_BINARY + bool "Intel HEX binary format" + default n + ---help--- + Create the nuttx.hex in the Intel HEX binary format that is + used with many different loaders. This option will use the GNU objcopy program + and should not be selected if you are not using the GNU toolchain. + +config MOTOROLA_SREC + bool "Motorola S-Record binary format" + default n + ---help--- + Create the nuttx.srec in the Motorola S-Record binary format that is + used with many different loaders. This option will use the GNU objcopy program + and should not be selected if you are not using the GNU toolchain. + +config RAW_BINARY + bool "Raw binary format" + default n + ---help--- + Create the nuttx.bin in the raw binary format that is used with many + different loaders using the GNU objcopy program. This option + should not be selected if you are not using the GNU toolchain. +endmenu + +menu "Debug Options" + +config DEBUG + bool "Enable debug output" + default n + ---help--- + enables built-in debug options + +if DEBUG +config DEBUG_VERBOSE + bool "Enable debug verbose output" + default n + ---help--- + enables verbose debug output + +config DEBUG_ENABLE + bool "Enable debug controls" + default n + ---help--- + Support an interface to enable or disable debug output. + +config DEBUG_SCHED + bool "Enable scheduler debug output" + default n + ---help--- + Enable OS debug output (disabled by default) + +config DEBUG_MM + bool "Enable memory manager debug output" + default n + ---help--- + Enable memory management debug output (disabled by default) + +config DEBUG_NET + bool "Enable network debug output" + default n + ---help--- + Enable network debug output (disabled by default) + +config DEBUG_USB + bool "Enable USB debug output" + default n + ---help--- + Enable usb debug output (disabled by default) + +config DEBUG_FS + bool "Enable file system debug output" + default n + ---help--- + Enable file system debug output (disabled by default) + +config DEBUG_LIB + bool "Enable C library debug output" + default n + ---help--- + Enable C library debug output (disabled by default) + +config DEBUG_BINFMT + bool "Enable binary loader debug output" + default n + ---help--- + Enable binary loader debug output (disabled by default) + +config DEBUG_GRAPHICS + bool "Enable graphics debug output" + default n + ---help--- + Enable NX graphics debug output (disabled by default) + +config DEBUG_I2C + bool "Enable I2C debug output" + default n + ---help--- + Enable I2C driver debug output (disabled by default) + +config DEBUG_SPI + bool "Enable SPI debug output" + default n + ---help--- + Enable I2C driver debug output (disabled by default) + +config DEBUG_WATCHDOG + bool "Enable watchdog timer debug output" + default n + ---help--- + Enable watchdog timer debug output (disabled by default) + +endif + +config DEBUG_SYMBOLS + bool "Enable debug symbols" + default n + ---help--- + Build without optimization and with debug symbols (needed + for use with a debugger). +endmenu +endmenu + +menu "System Type" +source "arch/Kconfig" +endmenu + +menu "Board Selection" +source "configs/Kconfig" +endmenu + +menu "Kernel Features" +source sched/Kconfig +endmenu + +menu "Device Drivers" +source drivers/Kconfig +endmenu + +menu "Networking support" +source net/Kconfig +endmenu + +menu "File systems" +source fs/Kconfig +endmenu + +menu "Memory management" +source mm/Kconfig +endmenu + +menu "Library routines" +source lib/Kconfig +source libxx/Kconfig +endmenu + +menu "Application configuration" +source "$APPSDIR/Kconfig" +endmenu + diff --git a/nuttx/Makefile b/nuttx/Makefile new file mode 100644 index 0000000000..ea83d69ee2 --- /dev/null +++ b/nuttx/Makefile @@ -0,0 +1,635 @@ +############################################################################ +# Makefile +# +# Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +TOPDIR := ${shell pwd | sed -e 's/ /\\ /g'} +-include ${TOPDIR}/.config +-include ${TOPDIR}/Make.defs + +# Default tools + +ifeq ($(DIRLINK),) +DIRLINK = $(TOPDIR)/tools/link.sh +DIRUNLINK = $(TOPDIR)/tools/unlink.sh +endif + +# This define is passed as EXTRADEFINES for kernel-mode builds. It is also passed +# during PASS1 (but not PASS2) context and depend targets. + +KDEFINE = ${shell $(TOPDIR)/tools/define.sh $(CC) __KERNEL__} + +# Process architecture and board-specific directories + +ARCH_DIR = arch/$(CONFIG_ARCH) +ARCH_SRC = $(ARCH_DIR)/src +ARCH_INC = $(ARCH_DIR)/include +BOARD_DIR = configs/$(CONFIG_ARCH_BOARD) + +# Add-on directories. These may or may not be in place in the +# NuttX source tree (they must be specifically installed) +# +# CONFIG_APPS_DIR can be over-ridden from the command line or in the .config file. +# The default value of CONFIG_APPS_DIR is ../apps. Ultimately, the application +# will be built if APPDIR is defined. APPDIR will be defined if a directory containing +# a Makefile is found at the path provided by CONFIG_APPS_DIR + +ifeq ($(CONFIG_APPS_DIR),) +CONFIG_APPS_DIR = ../apps +endif +APPDIR := ${shell if [ -r $(CONFIG_APPS_DIR)/Makefile ]; then echo "$(CONFIG_APPS_DIR)"; fi} + +# All add-on directories. +# +# NUTTX_ADDONS is the list of directories built into the NuttX kernel. +# USER_ADDONS is the list of directories that will be built into the user application + +NUTTX_ADDONS := $(NX_DIR) +USER_ADDONS := + +ifeq ($(CONFIG_NUTTX_KERNEL),y) +USER_ADDONS += $(APPDIR) +else +NUTTX_ADDONS += $(APPDIR) +endif + +# Lists of build directories. +# +# FSDIRS depend on file descriptor support; NONFSDIRS do not (except for parts +# of FSDIRS). We will exclude FSDIRS from the build if file descriptor +# support is disabled +# CONTEXTDIRS include directories that have special, one-time pre-build +# requirements. Normally this includes things like auto-generation of +# configuration specific files or creation of configurable symbolic links +# USERDIRS - When NuttX is build is a monolithic kernel, this provides the +# list of directories that must be built +# OTHERDIRS - These are directories that are not built but probably should +# be cleaned to prevent garbarge from collecting in them when changing +# configurations. + +NONFSDIRS = sched $(ARCH_SRC) $(NUTTX_ADDONS) +FSDIRS = fs drivers binfmt +CONTEXTDIRS = $(APPDIR) +USERDIRS = + +ifeq ($(CONFIG_NUTTX_KERNEL),y) + +NONFSDIRS += syscall +CONTEXTDIRS += syscall +USERDIRS += syscall lib mm $(USER_ADDONS) +ifeq ($(CONFIG_HAVE_CXX),y) +USERDIRS += libxx +endif + +else + +NONFSDIRS += lib mm +OTHERDIRS += syscall $(USER_ADDONS) +ifeq ($(CONFIG_HAVE_CXX),y) +NONFSDIRS += libxx +else +OTHERDIRS += libxx +endif + +endif + +ifeq ($(CONFIG_NX),y) +NONFSDIRS += graphics +CONTEXTDIRS += graphics +else +OTHERDIRS += graphics +endif + +# CLEANDIRS are the directories that will clean in. These are +# all directories that we know about. +# KERNDEPDIRS are the directories in which we will build target dependencies. +# If NuttX and applications are built separately (CONFIG_NUTTX_KERNEL), +# then this holds only the directories containing kernel files. +# USERDEPDIRS. If NuttX and applications are built separately (CONFIG_NUTTX_KERNEL), +# then this holds only the directories containing user files. + +CLEANDIRS = $(NONFSDIRS) $(FSDIRS) $(USERDIRS) $(OTHERDIRS) +KERNDEPDIRS = $(NONFSDIRS) +USERDEPDIRS = $(USERDIRS) + +# Add file system directories to KERNDEPDIRS (they are already in CLEANDIRS) + +ifeq ($(CONFIG_NFILE_DESCRIPTORS),0) +ifeq ($(CONFIG_NET),y) +ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0) +KERNDEPDIRS += fs +endif +KERNDEPDIRS += drivers +endif +else +KERNDEPDIRS += $(FSDIRS) +endif + +# Add networking directories to KERNDEPDIRS and CLEANDIRS + +ifeq ($(CONFIG_NET),y) +KERNDEPDIRS += net +endif +CLEANDIRS += net + +# +# Extra objects used in the final link. +# +# Pass 1 1ncremental (relative) link objects should be put into the +# processor-specific source directory (where other link objects will +# be created). If the pass1 obect is an archive, it could go anywhere. + +ifeq ($(CONFIG_BUILD_2PASS),y) +EXTRA_OBJS += $(CONFIG_PASS1_OBJECT) +endif + +# NUTTXLIBS is the list of NuttX libraries that is passed to the +# processor-specific Makefile to build the final NuttX target. +# Libraries in FSDIRS are excluded if file descriptor support +# is disabled. +# USERLIBS is the list of libraries used to build the final user-space +# application + +NUTTXLIBS = sched/libsched$(LIBEXT) $(ARCH_SRC)/libarch$(LIBEXT) +USERLIBS = + +# Add libraries for syscall support. The C library will be needed by +# both the kernel- and user-space builds. For now, the memory manager (mm) +# is placed in user space (only). + +ifeq ($(CONFIG_NUTTX_KERNEL),y) +NUTTXLIBS += syscall/libstubs$(LIBEXT) lib/libklib$(LIBEXT) +USERLIBS += syscall/libproxies$(LIBEXT) lib/libulib$(LIBEXT) mm/libmm$(LIBEXT) +else +NUTTXLIBS += mm/libmm$(LIBEXT) lib/liblib$(LIBEXT) +endif + +# Add libraries for C++ support. CXX, CXXFLAGS, and COMPILEXX must +# be defined in Make.defs for this to work! + +ifeq ($(CONFIG_HAVE_CXX),y) +ifeq ($(CONFIG_NUTTX_KERNEL),y) +USERLIBS += libxx/liblibxx$(LIBEXT) +else +NUTTXLIBS += libxx/liblibxx$(LIBEXT) +endif +endif + +# Add library for application support. + +ifneq ($(APPDIR),) +ifeq ($(CONFIG_NUTTX_KERNEL),y) +USERLIBS += $(APPDIR)/libapps$(LIBEXT) +else +NUTTXLIBS += $(APPDIR)/libapps$(LIBEXT) +endif +endif + +# Add libraries for network support + +ifeq ($(CONFIG_NET),y) +NUTTXLIBS += net/libnet$(LIBEXT) +endif + +# Add libraries for file system support + +ifeq ($(CONFIG_NFILE_DESCRIPTORS),0) +ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0) +NUTTXLIBS += fs/libfs$(LIBEXT) +endif +ifeq ($(CONFIG_NET),y) +NUTTXLIBS += drivers/libdrivers$(LIBEXT) +endif +else +NUTTXLIBS += fs/libfs$(LIBEXT) drivers/libdrivers$(LIBEXT) binfmt/libbinfmt$(LIBEXT) +endif + +# Add libraries for the NX graphics sub-system + +ifneq ($(NX_DIR),) +NUTTXLIBS += $(NX_DIR)/libnx$(LIBEXT) +endif + +ifeq ($(CONFIG_NX),y) +NUTTXLIBS += graphics/libgraphics$(LIBEXT) +endif + +# This is the name of the final target (relative to the top level directorty) + +BIN = nuttx$(EXEEXT) + +all: $(BIN) +.PHONY: context clean_context check_context export subdir_clean clean subdir_distclean distclean apps_clean apps_distclean + +# Target used to copy include/nuttx/math.h. If CONFIG_ARCH_MATH_H is +# defined, then there is an architecture specific math.h header file +# that will be included indirectly from include/math.h. But first, we +# have to copy math.h from include/nuttx/. to include/. + +ifeq ($(CONFIG_ARCH_MATH_H),y) +include/math.h: include/nuttx/math.h + @cp -f include/nuttx/math.h include/math.h +else +include/math.h: +endif + +# Target used to copy include/nuttx/stdarg.h. If CONFIG_ARCH_STDARG_H is +# defined, then there is an architecture specific stdarg.h header file +# that will be included indirectly from include/stdarg.h. But first, we +# have to copy stdarg.h from include/nuttx/. to include/. + +ifeq ($(CONFIG_ARCH_STDARG_H),y) +include/stdarg.h: include/nuttx/stdarg.h + @cp -f include/nuttx/stdarg.h include/stdarg.h +else +include/stdarg.h: +endif + +# Targets used to build include/nuttx/version.h. Creation of version.h is +# part of the overall NuttX configuration sequency. Notice that the +# tools/mkversion tool is cuilt and used to create include/nuttx/version.h + +tools/mkversion: + @$(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)" mkversion + +$(TOPDIR)/.version: + @if [ ! -f .version ]; then \ + echo "No .version file found, creating one"; \ + tools/version.sh -v 0.0 -b 0 .version; \ + chmod 755 .version; \ + fi + +include/nuttx/version.h: $(TOPDIR)/.version tools/mkversion + @tools/mkversion $(TOPDIR) > include/nuttx/version.h + +# Targets used to build include/nuttx/config.h. Creation of config.h is +# part of the overall NuttX configuration sequency. Notice that the +# tools/mkconfig tool is cuilt and used to create include/nuttx/config.h + +tools/mkconfig: + @$(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)" mkconfig + +include/nuttx/config.h: $(TOPDIR)/.config tools/mkconfig + @tools/mkconfig $(TOPDIR) > include/nuttx/config.h + +# dirlinks, and helpers +# +# Directories links. Most of establishing the NuttX configuration involves +# setting up symbolic links with 'generic' directory names to specific, +# configured directories. +# +# Link the apps/include directory to include/apps + +include/apps: Make.defs +ifneq ($(APPDIR),) + @if [ -d $(TOPDIR)/$(APPDIR)/include ]; then \ + $(DIRLINK) $(TOPDIR)/$(APPDIR)/include include/apps; \ + fi +endif + +# Link the arch//include directory to include/arch + +include/arch: Make.defs + @$(DIRLINK) $(TOPDIR)/$(ARCH_DIR)/include include/arch + +# Link the configs//include directory to include/arch/board + +include/arch/board: include/arch Make.defs include/arch + @$(DIRLINK) $(TOPDIR)/$(BOARD_DIR)/include include/arch/board + +# Link the configs//src dir to arch//src/board + +$(ARCH_SRC)/board: Make.defs + @$(DIRLINK) $(TOPDIR)/$(BOARD_DIR)/src $(ARCH_SRC)/board + +# Link arch//include/ to arch//include/chip + +$(ARCH_SRC)/chip: Make.defs +ifneq ($(CONFIG_ARCH_CHIP),) + @$(DIRLINK) $(TOPDIR)/$(ARCH_SRC)/$(CONFIG_ARCH_CHIP) $(ARCH_SRC)/chip +endif + +# Link arch//src/ to arch//src/chip + +include/arch/chip: include/arch Make.defs +ifneq ($(CONFIG_ARCH_CHIP),) + @$(DIRLINK) $(TOPDIR)/$(ARCH_INC)/$(CONFIG_ARCH_CHIP) include/arch/chip +endif + +dirlinks: include/arch include/arch/board include/arch/chip $(ARCH_SRC)/board $(ARCH_SRC)/chip include/apps + +# context +# +# The context target is invoked on each target build to assure that NuttX is +# properly configured. The basic configuration steps include creation of the +# the config.h and version.h header files in the include/nuttx directory and +# the establishment of symbolic links to configured directories. + +context: check_context include/nuttx/config.h include/nuttx/version.h include/math.h include/stdarg.h dirlinks + @for dir in $(CONTEXTDIRS) ; do \ + $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" context; \ + done + +# clean_context +# +# This is part of the distclean target. It removes all of the header files +# and symbolic links created by the context target. + +clean_context: + @rm -f include/nuttx/config.h + @rm -f include/nuttx/version.h + @rm -f include/math.h + @rm -f include/stdarg.h + @$(DIRUNLINK) include/arch/board + @$(DIRUNLINK) include/arch/chip + @$(DIRUNLINK) include/arch + @$(DIRUNLINK) $(ARCH_SRC)/board + @$(DIRUNLINK) $(ARCH_SRC)/chip + @$(DIRUNLINK) include/apps + +# check_context +# +# This target checks if NuttX has been configured. NuttX is configured using +# the script tools/configure.sh. That script will install certain files in +# the top-level NuttX build directory. This target verifies that those +# configuration files have been installed and that NuttX is ready to be built. + +check_context: + @if [ ! -e ${TOPDIR}/.config -o ! -e ${TOPDIR}/Make.defs ]; then \ + echo "" ; echo "Nuttx has not been configured:" ; \ + echo " cd tools; ./configure.sh " ; echo "" ; \ + exit 1 ; \ + fi + +# Archive targets. The target build sequency will first create a series of +# libraries, one per configured source file directory. The final NuttX +# execution will then be built from those libraries. The following targets +# built those libraries. +# +# Possible kernel-mode builds + +lib/libklib$(LIBEXT): context + @$(MAKE) -C lib TOPDIR="$(TOPDIR)" libklib$(LIBEXT) EXTRADEFINES=$(KDEFINE) + +sched/libsched$(LIBEXT): context + @$(MAKE) -C sched TOPDIR="$(TOPDIR)" libsched$(LIBEXT) EXTRADEFINES=$(KDEFINE) + +$(ARCH_SRC)/libarch$(LIBEXT): context + @$(MAKE) -C $(ARCH_SRC) TOPDIR="$(TOPDIR)" libarch$(LIBEXT) EXTRADEFINES=$(KDEFINE) + +net/libnet$(LIBEXT): context + @$(MAKE) -C net TOPDIR="$(TOPDIR)" libnet$(LIBEXT) EXTRADEFINES=$(KDEFINE) + +fs/libfs$(LIBEXT): context + @$(MAKE) -C fs TOPDIR="$(TOPDIR)" libfs$(LIBEXT) EXTRADEFINES=$(KDEFINE) + +drivers/libdrivers$(LIBEXT): context + @$(MAKE) -C drivers TOPDIR="$(TOPDIR)" libdrivers$(LIBEXT) EXTRADEFINES=$(KDEFINE) + +binfmt/libbinfmt$(LIBEXT): context + @$(MAKE) -C binfmt TOPDIR="$(TOPDIR)" libbinfmt$(LIBEXT) EXTRADEFINES=$(KDEFINE) + +graphics/libgraphics$(LIBEXT): context + @$(MAKE) -C graphics TOPDIR="$(TOPDIR)" libgraphics$(LIBEXT) EXTRADEFINES=$(KDEFINE) + +syscall/libstubs$(LIBEXT): context + @$(MAKE) -C syscall TOPDIR="$(TOPDIR)" libstubs$(LIBEXT) EXTRADEFINES=$(KDEFINE) + +# Possible user-mode builds + +lib/libulib$(LIBEXT): context + @$(MAKE) -C lib TOPDIR="$(TOPDIR)" libulib$(LIBEXT) + +libxx/liblibxx$(LIBEXT): context + @$(MAKE) -C libxx TOPDIR="$(TOPDIR)" liblibxx$(LIBEXT) + +mm/libmm$(LIBEXT): context + @$(MAKE) -C mm TOPDIR="$(TOPDIR)" libmm$(LIBEXT) EXTRADEFINES=$(KDEFINE) + +$(APPDIR)/libapps$(LIBEXT): context + @$(MAKE) -C $(APPDIR) TOPDIR="$(TOPDIR)" libapps$(LIBEXT) + +syscall/libproxies$(LIBEXT): context + @$(MAKE) -C syscall TOPDIR="$(TOPDIR)" libproxies$(LIBEXT) + +# Possible non-kernel builds + +lib/liblib$(LIBEXT): context + @$(MAKE) -C lib TOPDIR="$(TOPDIR)" liblib$(LIBEXT) + +# pass1 and pass2 +# +# If the 2 pass build option is selected, then this pass1 target is +# configured to built before the pass2 target. This pass1 target may, as an +# example, build an extra link object (CONFIG_PASS1_OBJECT) which may be an +# incremental (relative) link object, but could be a static library (archive); +# some modification to this Makefile would be required if CONFIG_PASS1_OBJECT +# is an archive. Exactly what is performed during pass1 or what it generates +# is unknown to this makefule unless CONFIG_PASS1_OBJECT is defined. + +pass1deps: context pass1dep $(USERLIBS) + +pass1: pass1deps +ifeq ($(CONFIG_BUILD_2PASS),y) + @if [ -z "$(CONFIG_PASS1_BUILDIR)" ]; then \ + echo "ERROR: CONFIG_PASS1_BUILDIR not defined"; \ + exit 1; \ + fi + @if [ ! -d "$(CONFIG_PASS1_BUILDIR)" ]; then \ + echo "ERROR: CONFIG_PASS1_BUILDIR does not exist"; \ + exit 1; \ + fi + @if [ ! -f "$(CONFIG_PASS1_BUILDIR)/Makefile" ]; then \ + echo "ERROR: No Makefile in CONFIG_PASS1_BUILDIR"; \ + exit 1; \ + fi + @$(MAKE) -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$(TOPDIR)" LINKLIBS="$(NUTTXLIBS)" USERLIBS="$(USERLIBS)" "$(CONFIG_PASS1_TARGET)" +endif + +pass2deps: context pass2dep $(NUTTXLIBS) + +pass2: pass2deps + @$(MAKE) -C $(ARCH_SRC) TOPDIR="$(TOPDIR)" EXTRA_OBJS="$(EXTRA_OBJS)" LINKLIBS="$(NUTTXLIBS)" EXTRADEFINES=$(KDEFINE) $(BIN) + @if [ -w /tftpboot ] ; then \ + cp -f $(BIN) /tftpboot/$(BIN).${CONFIG_ARCH}; \ + fi +ifeq ($(CONFIG_RRLOAD_BINARY),y) + @echo "MK: $(BIN).rr" + @$(TOPDIR)/tools/mkimage.sh --Prefix $(CROSSDEV) $(BIN) $(BIN).rr + @if [ -w /tftpboot ] ; then \ + cp -f $(BIN).rr /tftpboot/$\(BIN).rr.$(CONFIG_ARCH); \ + fi +endif +ifeq ($(CONFIG_INTELHEX_BINARY),y) + @echo "CP: $(BIN).hex" + @$(OBJCOPY) $(OBJCOPYARGS) -O ihex $(BIN) $(BIN).hex +endif +ifeq ($(CONFIG_MOTOROLA_SREC),y) + @echo "CP: $(BIN).srec" + @$(OBJCOPY) $(OBJCOPYARGS) -O srec $(BIN) $(BIN).srec +endif +ifeq ($(CONFIG_RAW_BINARY),y) + @echo "CP: $(BIN).bin" + @$(OBJCOPY) $(OBJCOPYARGS) -O binary $(BIN) $(BIN).bin +endif + +# $(BIN) +# +# Create the final NuttX executable in a two pass build process. In the +# normal case, all pass1 and pass2 dependencies are created then pass1 +# and pass2 targets are built. However, in some cases, you may need to build +# pass1 depenencies and pass1 first, then build pass2 dependencies and pass2. +# in that case, execute 'make pass1 pass2' from the command line. + +$(BIN): pass1deps pass2deps pass1 pass2 + +# download +# +# This is a helper target that will rebuild NuttX and download it to the target +# system in one step. The operation of this target depends completely upon +# implementation of the DOWNLOAD command in the user Make.defs file. It will +# generate an error an error if the DOWNLOAD command is not defined. + +download: $(BIN) + $(call DOWNLOAD, $<) + +# pass1dep: Create pass1 build dependencies +# pass2dep: Create pass2 build dependencies + +pass1dep: context + @for dir in $(USERDEPDIRS) ; do \ + $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" depend ; \ + done + +pass2dep: context + @for dir in $(KERNDEPDIRS) ; do \ + $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" EXTRADEFINES=$(KDEFINE) depend; \ + done + +# Configuration targets +# +# These targets depend on the kconfig-frontends packages. To use these, you +# must first download and install the kconfig-frontends package from this +# location: http://ymorin.is-a-geek.org/projects/kconfig-frontends. See +# misc/tools/README.txt for additional information. + +config: + @APPSDIR=${CONFIG_APPS_DIR} conf Kconfig + +oldconfig: + @APPSDIR=${CONFIG_APPS_DIR} conf --oldconfig Kconfig + +menuconfig: + @APPSDIR=${CONFIG_APPS_DIR} mconf Kconfig + +# export +# +# The export target will package the NuttX libraries and header files into +# an exportable package. Caveats: (1) These needs some extension for the KERNEL +# build; it needs to receive USERLIBS and create a libuser.a). (2) The logic +# in tools/mkexport.sh only supports GCC and, for example, explicitly assumes +# that the archiver is 'ar' + +export: pass2deps + @tools/mkexport.sh -w$(WINTOOL) -t "$(TOPDIR)" -l "$(NUTTXLIBS)" + +# General housekeeping targets: dependencies, cleaning, etc. +# +# depend: Create both PASS1 and PASS2 dependencies +# clean: Removes derived object files, archives, executables, and +# temporary files, but retains the configuration and context +# files and directories. +# distclean: Does 'clean' then also removes all configuration and context +# files. This essentially restores the directory structure +# to its original, unconfigured stated. + +depend: pass1dep pass2dep + +subdir_clean: + @for dir in $(CLEANDIRS) ; do \ + if [ -e $$dir/Makefile ]; then \ + $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" clean ; \ + fi \ + done + @$(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)" clean + @$(MAKE) -C mm -f Makefile.test TOPDIR="$(TOPDIR)" clean +ifeq ($(CONFIG_BUILD_2PASS),y) + @$(MAKE) -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$(TOPDIR)" clean +endif + +clean: subdir_clean + @rm -f $(BIN) nuttx.* mm_test *.map _SAVED_APPS_config *~ + @rm -f nuttx-export* + +subdir_distclean: + @for dir in $(CLEANDIRS) ; do \ + if [ -e $$dir/Makefile ]; then \ + $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" distclean ; \ + fi \ + done + +distclean: clean subdir_distclean clean_context +ifeq ($(CONFIG_BUILD_2PASS),y) + @$(MAKE) -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$(TOPDIR)" distclean +endif + @rm -f Make.defs setenv.sh .config + +# Application housekeeping targets. The APPDIR variable refers to the user +# application directory. A sample apps/ directory is included with NuttX, +# however, this is not treated as part of NuttX and may be replaced with a +# different application directory. For the most part, the application +# directory is treated like any other build directory in this script. However, +# as a convenience, the following targets are included to support housekeeping +# functions in the user application directory from the NuttX build directory. +# +# apps_clean: Perform the clean operation only in the user application +# directory +# apps_distclean: Perform the distclean operation only in the user application +# directory. Note that the apps/.config file is preserved +# so that this is not a "full" distclean but more of a +# configuration "reset." + +apps_clean: +ifneq ($(APPDIR),) + @$(MAKE) -C "$(TOPDIR)/$(APPDIR)" TOPDIR="$(TOPDIR)" clean +endif + +apps_distclean: +ifneq ($(APPDIR),) + @cp "$(TOPDIR)/$(APPDIR)/.config" _SAVED_APPS_config || \ + { echo "Copy of $(APPDIR)/.config failed" ; exit 1 ; } + @$(MAKE) -C "$(TOPDIR)/$(APPDIR)" TOPDIR="$(TOPDIR)" distclean + @mv _SAVED_APPS_config "$(TOPDIR)/$(APPDIR)/.config" || \ + { echo "Copy of _SAVED_APPS_config failed" ; exit 1 ; } +endif + diff --git a/nuttx/README.txt b/nuttx/README.txt new file mode 100644 index 0000000000..28b4fba032 --- /dev/null +++ b/nuttx/README.txt @@ -0,0 +1,844 @@ +README +^^^^^^ + + o Installation + - Installing Cygwin + - Download and Unpack + - Semi-Optional apps/ Package + - Installation Directories with Spaces in the Path + - Notes about Header Files + o Configuring NuttX + - Instantiating "Canned" Configurations + - NuttX Configuration Tool + o Toolchains + - Cross-Development Toolchains + - NuttX Buildroot Toolchain + o Shells + o Building NuttX + - Building + - Re-building + - Build Targets + o Cygwin Build Problems + - Strange Path Problems + - Window Native Toolchain Issues + o Documentation + +INSTALLATION +^^^^^^^^^^^^ + +Installing Cygwin +----------------- + + NuttX may be installed and built on a Linux system or on a Windows + system if Cygwin is installed. Installing Cygwin on your Windows PC + is simple, but time consuming. See http://www.cygwin.com/ for + installation instructions. Basically you just need to download a + tiny setup.exe program and it does the real, internet installation + for you. + + Some Cygwin installation tips: + + 1. Install at C:\cygwin + + 2. Install EVERYTHING: "Only the minimal base packages from the + Cygwin distribution are installed by default. Clicking on categories + and packages in the setup.exe package installation screen will + provide you with the ability to control what is installed or updated. + Clicking on the "Default" field next to the "All" category will + provide you with the opportunity to install every Cygwin package. + Be advised that this will download and install hundreds of megabytes + to your computer." + + If you use the "default" installation, you will be missing many + of the Cygwin utilities that you will need to build NuttX. The + build will fail in numerous places because of missing packages. + + After installing Cygwin, you will get lots of links for installed + tools and shells. I use the RXVT native shell. It is fast and reliable + and does not require you to run the Cygwin X server (which is neither + fast nor reliable). The rest of these instructions assume that you + are at a bash command line prompt in either Linux or in Cygwin shell. + +Download and Unpack +------------------- + + Download and unpack the NuttX tarball. If you are reading this, then + you have probably already done that. After unpacking, you will end + up with a directory called nuttx-version (where version is the NuttX + version number). You might want to rename that directory nuttx to + match the various instructions in the documentation and some scripts + in the source tree. + +Semi-Optional apps/ Package +--------------------------- + + All NuttX libraries and example code used to be in included within + the NuttX source tree. As of NuttX-6.0, this application code was + moved into a separate tarball, the apps tarball. If you are just + beginning with NuttX, then you will want to download the versioned + apps tarball along with the NuttX tarball. If you already have your + own product application directory, then you may not need the apps + tarball. + + It is call "Semi-optional" because if you don't have some apps/ + directory, NuttX will *fail* to build! + + Download the unpack the apps tarball in the same directly where you + unpacked the NuttX tarball. After you unpack the apps tarball, you + will have a new directory called apps-version (where the version + should exactly match the version of the NuttX tarball). Again, you + might want to rename the directory to simply apps/ to match what + you read in the documentation + + After unpacking the apps tarball, you will have two directories side + by side like this: + + | + +----+----+ + | | + nuttx/ apps/ + + This is important because the NuttX build will expect to find the + apps directory in that (default) location. )That default location + can be changed by editing your NuttX configuration file, but that + is another story). + +Installation Directories with Spaces in the Path +------------------------------------------------ + + The nuttx build directory should reside in a path that contains no + spaces in any higher level directory name. For example, under + Cygwin, your home directory might be formed from your first and last + names like: "/home/First Last". That will cause strange errors when + the make system tries to build. + + [Actually, that problem is probably not to difficult to fix. Some + Makefiles probably just need some paths within double quotes] + + I work around spaces in the home directory name, by creating a + new directory that does not contain any spaces, such as /home/nuttx. + Then I install NuttX in /home/nuttx and always build from + /home/nuttx/nuttx. + +Notes about Header Files +------------------------ + + Other C-Library Header Files. + + Some toolchains are built with header files extracted from a C-library + distribution (such as newlib). These header files must *not* be used + with NuttX because NuttX provides its own, built-in C-Library. For + toolchains that do include built-in header files from a foreign C- + Library, NuttX must be compiled without using the standard header files + that are distributed with your toolchain. This prevents including + conflicting, incompatible header files (such as stdio.h). + + Header Files Provided by Your Toolchain. + + Certain header files, such as setjmp.h, stdarg.h, and math.h, may still + be needed from your toolchain and your compiler may not, however, be able + to find these if you compile NuttX without using standard header file. + If that is the case, one solution is to copy those header file from + your toolchain into the NuttX include directory. + + Duplicated Header Files. + + There are also a few header files that can be found in the nuttx/include + directory which are duplicated by the header files from your toolchain. + stdint.h and stdbool.h are examples. If you prefer to use the stdint.h + and stdbool.h header files from your toolchain, those could be copied + into the nuttx/include/ directory. Using most other header files from + your toolchain would probably cause errors. + + math.h + + Even though you should not use a foreign C-Library, you may still need + to use other, external libraries with NuttX. In particular, you may + need to use the math library, libm.a. The math libary header file, + math.h, is a special case. If you do nothing, the standard math.h + header file that is provided with your toolchain will be used. + + If you have a custom, architecture specific math.h header file, then + that header file should be placed at arch//include/math.h. There + is a stub math.h header file located at include/nuttx/math.h. This stub + header file can be used to "redirect" the inclusion to an architecture- + specific math.h header file. If you add an architecture specific math.h + header file then you should also define CONFIG_ARCH_MATH_H=y in your + NuttX Configuration file. If CONFIG_ARCH_MATH_H is selected, then the + top-level Makefile will copy the stub math.h header file from + include/nuttx/matn.h to include/math.h where it will become the system + math.h header file. The stub math.h header file does nothing other + than to include that archicture-specific math.h header file as the + system math.h header file. + + stdarg.h + + In most cases, the correct version of stdarg.h is the version provided with your toolchain. However, sometimes there are issues with with using your toolchains stdarg.h. For example, it may attempt to draw in header files that do not exist in NuttX or perhaps the header files that is uses are not compatible with the NuttX header files. In those cases, you can use an architecture-specific stdarg.h header file by defining CONFIG_ARCH_STDARG_H=y. + See the discussion above for the math.h header. This setting works exactly + the same for the stdarg.h header file. + +CONFIGURING NUTTX +^^^^^^^^^^^^^^^^^ + +Instantiating "Canned" Configurations +------------------------------------- + +"Canned" NuttX configuration files are retained in: + + configs// + +Where is the name of your development board and . +Configuring NuttX requires only copying three files from the +to the directly where you installed NuttX (TOPDIR): + + Copy configs///Make.def to ${TOPDIR}/Make.defs + + Make.defs describes the rules needed by you tool chain to compile + and link code. You may need to modify this file to match the + specific needs of your toolchain. + + Copy configs///setenv.sh to ${TOPDIR}/setenv.sh + + setenv.sh is an optional convenience file that I use to set + the PATH variable to the toolchain binaries. You may chose to + use setenv.sh or not. If you use it, then it may need to be + modified to include the path to your toolchain binaries. + + Copy configs///defconfig to ${TOPDIR}/.config + + The defconfig file holds the actual build configuration. This + file is included by all other make files to determine what is + included in the build and what is not. This file is also used + to generate a C configuration header at include/nuttx/config.h. + +General information about configuring NuttX can be found in: + + ${TOPDIR}/configs/README.txt + ${TOPDIR}/configs//README.txt + +There is a configuration script in the tools/ directory that makes this +easier. It is used as follows: + + cd ${TOPDIR}/tools + ./configure.sh / + + +NuttX Configuration Tool +------------------------ + + An automated tool is under development to support re-configuration + of NuttX. This tool, however, is not yet quite ready for general + usage. + + This automated tool is based on the kconfig-frontends application + available at http://ymorin.is-a-geek.org/projects/kconfig-frontends + (A snapshot of this tool is also available at ../misc/tools). This + application provides a tool called 'mconf' that is used by the NuttX + top-level Makefile. The following make target is provided: + + make menuconfig + + This make target will bring up NuttX configuration menus. The + 'menuconfig' target depends on two things: + + 1. The Kconfig configuration data files that appear in almost all + NuttX directories. These data files are the part that is still + under development (patches are welcome!). The Kconfig files + contain configuration information for the configuration settings + relevant to the directory in which the Kconfig file resides. + + NOTE: For a description of the syntax of this configuration file, + see ../misc/tools/kconfig-language.txt. + + 2. The 'mconf' tool. 'mconf' is part of the kconfig-frontends + package. You can download that package from the website + http://ymorin.is-a-geek.org/projects/kconfig-frontends or you + can use the snapshot in ../misc/tools. + + Building may be as simple as 'configure; make; make install' + but there may be some build complexities, especially if you + are building under Cygwin. See the more detailed build + instructions at ../misc/tools/README.txt + + The 'make install' step will, by default, install the 'mconf' + tool at /usr/local/bin/mconf. Where ever you choose to + install 'mconf', make certain that your PATH variable includes + a path to that installation directory. + +TOOLCHAINS +^^^^^^^^^^ + +Cross-Development Toolchains +---------------------------- + + In order to build NuttX for your board, you will have to obtain a cross- + compiler to generate code for your target CPU. For each board, + configuration, there is a README.txt file (at configs//README.txt). + That README file contains suggestions and information about appropriate + tools and development environments for use with your board. + + In any case, the script, setenv.sh that was deposited in the top- + level directory when NuttX was configured should be edited to set + the path to where you installed the toolchain. The use of setenv.sh + is optional but can save a lot of confusion in the future. + +NuttX Buildroot Toolchain +------------------------- + + For many configurations, a DIY set of tools is available for NuttX. These + tools can be downloaded from the NuttX SourceForge file repository. After + unpacking the buildroot tarball, you can find instructions for building + the tools in the buildroot/configs/README.txt file. + + Check the README.txt file in the configuration director for your board + to see if you can use the buildroot toolchain with your board (this + README.txt file is located in configs//README.txt). + + This toolchain is available for both the Linux and Cygwin development + environments. + + Advantages: (1) NuttX header files are built into the tool chain, + and (2) related support tools like NXFLAT tools and the ROMFS + genromfs tools can be built into your toolchain. + + Disadvantages: This tool chain is not was well supported as some other + toolchains. GNU tools are not my priority and so the buildroot tools + often get behind. For example, the is still no EABI support in the + NuttX buildroot toolchain for ARM. + +SHELLS +^^^^^^ + + The NuttX build relies on some shell scripts. Some are inline in the + Makefiles and many are exectuble scripts in the tools/. directory. The + scripts were all developed using bash and many contain bash shell + dependencies. + + Most of the scripts begin with #!/bin/bash to specifically select the + bash shell. Some still have #!/bin/sh but I haven't heard any complaints + so these must not have bash dependencies. + + There are two shell issues that I have heard of: + + 1. Linux where /bin/sh refers to an incompatible shell (like ksh or csh). + + In this case, bash is probably avaiable and the #!/bin/bash at the + beginning of the file should do the job. If any scripts with #!/bin/sh + fail, try changing that ti #!/bin/bash and let me know about the change. + + 2. FreeBSD with the Bourne Shell and no bash shell. + + The other, reverse case has also been reported on FreeBSD setups that + have the Bourne shell, but not bash. In this base, #!/bin/bash fails + but #!/bin/sh works okay. My recommendation in this case is to create + a symbolic link at /bin/bash that refers to the Bourne shell. + + There may still be issues, however, with certain the bash-centric scripts + that will require modifications. + +BUILDING NUTTX +^^^^^^^^^^^^^^ + +Building +-------- + + NuttX builds in-place in the source tree. You do not need to create + any special build directories. Assuming that your Make.defs is setup + properly for your tool chain and that setenv.sh contains the path to where + your cross-development tools are installed, the following steps are all that + are required to build NuttX: + + cd ${TOPDIR} + . ./setenv.sh + make + + At least one configuration (eagle100) requires additional command line + arguments on the make command. Read ${TOPDIR}/configs//README.txt + to see if that applies to your target. + +Re-building +----------- + + Re-building is normally simple -- just type make again. + + But there are some things that can "get you" when you use the Cygwin + development environment with Windows native tools. The native Windows + tools do not understand Cygwin's symbolic links, so the NuttX make system + does something weird: It copies the configuration directories instead of + linking to them (it could, perhaps, use the NTFS 'mklink' command, but it + doesn't). + + A consequence of this is that you can easily get confused when you edit + a file in one of the linked (i.e., copied) directories, re-build NuttX, + and then not see your changes when you run the program. That is because + build is still using the version of the file in the copied directory, not + your modified file! To work around this annoying behavior, do the + following when you re-build: + + make clean_context all + + This 'make' command will remove of the copied directories, re-copy them, + then make NuttX. + +Build Targets +------------- + + Below is a summary of the build targets available in the top-level + NuttX Makefile: + + all + + The default target builds the NuttX executable in the selected output + formats. + + clean + + Removes derived object files, archives, executables, and temporary + files, but retains the configuration and context files and directories. + + distclean + + Does 'clean' then also removes all configuration and context files. + This essentially restores the directory structure to its original, + unconfigured stated. + + Application housekeeping targets. The APPDIR variable refers to the user + application directory. A sample apps/ directory is included with NuttX, + however, this is not treated as part of NuttX and may be replaced with a + different application directory. For the most part, the application + directory is treated like any other build directory in the Makefile script. + However, as a convenience, the following targets are included to support + housekeeping functions in the user application directory from the NuttX + build directory. + + apps_clean + + Perform the clean operation only in the user application directory + + apps_distclean + + Perform the distclean operation only in the user application directory. + The apps/.config file is preserved so that this is not a "full" distclean + but more of a configuration "reset." + + export + + The export target will package the NuttX libraries and header files into + an exportable package. Caveats: (1) These needs some extension for the KERNEL + build. (2) The logic in tools/mkexport.sh only supports GCC and, for example, + explicitly assumes that the archiver is 'ar' + + download + + This is a helper target that will rebuild NuttX and download it to the target + system in one step. The operation of this target depends completely upon + implementation of the DOWNLOAD command in the user Make.defs file. It will + generate an error an error if the DOWNLOAD command is not defined. + + The following targets are used internally by the make logic but can be invoked + from the command under certain conditions if necessary. + + depend + + Create build dependencies. (NOTE: There is currently no support for build + dependencies under Cygwin using Windows-native toolchains.) + + context + + The context target is invoked on each target build to assure that NuttX is + properly configured. The basic configuration steps include creation of the + the config.h and version.h header files in the include/nuttx directory and + the establishment of symbolic links to configured directories. + + clean_context + + This is part of the distclean target. It removes all of the header files + and symbolic links created by the context target. + +CYGWIN BUILD PROBLEMS +^^^^^^^^^^^^^^^^^^^^^ + +Strange Path Problems +--------------------- + +If you see strange behavior when building under Cygwin then you may have +a problem with your PATH variable. For example, if you see failures to +locate files that are clearly present, that may mean that you are using +the wrong version of a tool. For example, you may not be using Cygwin's +'make' program at /usr/bin/make. Try: + + $ which make + /usr/bin/make + +When you install some toolchains (such as Yargarto or CodeSourcery tools), +they may modify your PATH variable to include a path to their binaries. +At that location, they make have GNUWin32 versions of the tools. So you +might actually be using a version of make that does not understand Cygwin +paths. + +The solution is either: + +1. Edit your PATH to remove the path to the GNUWin32 tools, or +2. Put /usr/local/bin, /usr/bin, and /bin at the front of your path: + + $ export PATH=/usr/local/bin:/usr/bin:/bin:$PATH + +Window Native Toolchain Issues +------------------------------ + + There are many popular Windows native toolchains that may be used with NuttX. + Examples include CodeSourcery (for Windows), devkitARM, and several vendor- + provied toolchains. There are several limitations with using a and Windows + based toolchain in a Cygwin environment. The three biggest are: + + 1. The Windows toolchain cannot follow Cygwin paths. Path conversions are + performed automatically in the Cygwin makefiles using the 'cygpath' utility + but you might easily find some new path problems. If so, check out 'cygpath -w' + + 2. Windows toolchains cannot follow Cygwin symbolic links. Many symbolic links + are used in Nuttx (e.g., include/arch). The make system works around these + problems for the Windows tools by copying directories instead of linking them. + But this can also cause some confusion for you: For example, you may edit + a file in a "linked" directory and find that your changes had no effect. + That is because you are building the copy of the file in the "fake" symbolic + directory. If you use a Windows toolchain, you should get in the habit of + making like this: + + make clean_context all + + An alias in your .bashrc file might make that less painful. The rebuild + is not a long as you might think because there is no dependency checking + if you are using a native Windows toolchain. That bring us to #3: + + 3. Dependencies are not made when using Windows versions of the GCC. This is + because the dependencies are generated using Windows pathes which do not + work with the Cygwin make. + + Support has been added for making dependencies with the windows-native toolchains. + That support can be enabled by modifying your Make.defs file as follows: + + - MKDEP = $(TOPDIR)/tools/mknulldeps.sh + + MKDEP = $(TOPDIR)/tools/mkdeps.sh --winpaths "$(TOPDIR)" + + If you have problems with the dependency build (for example, if you are not + building on C:), then you may need to modify tools/mkdeps.sh + +General Pre-built Toolchain Issues + + To continue with the list of "Window Native Toolchain Issues" we can add + the following. These, however, are really just issues that you will have + if you use any pre-built toolchain (vs. building the NuttX toolchain from + the NuttX buildroot package): + + There may be incompatibilities with header files, libraries, and compiler + built-in functions at detailed below. For the most part, these issues + are handled in the existing make logic. But if you are breaking new ground, + then you may incounter these: + + 4. Header Files. Most pre-built toolchains will build with a foreign C + library (usually newlib, but maybe uClibc or glibc if you are using a + Linux toolchain). This means that the header files from the foreign + C library will be built into the toolchain. So if you "include ", + you will get the stdio.h from the incompatible, foreign C library and + not the nuttx stdio.h (at nuttx/include/stdio.h) that you wanted. + + This can cause really confusion in the buildds and you must always be + sure the -nostdinc is included in the CFLAGS. That will assure that + you take the include files only from + + 5. Libraries. What was said above header files applies to libraries. + You do not want to include code from the libraries of any foreign + C libraries built into your toolchain. If this happens you will get + perplexing errors about undefined sysmbols. To avoid these errors, + you will need to add -nostdlib to your CFLAGS flags to assure that + you only take code from the NuttX libraries. + + This, however, may causes other issues for libraries in the toolchain + that you do want (like libgcc.a or libm.a). These are special-cased + in most Makefiles, but you could still run into issues of missing + libraries. + + 6. Built-Ins. Some compilers target a particular operating system. + Many people would, for example, like to use the same toolchain to + develop Linux and NuttX software. Compilers built for other + operating systems may generate incompatible built-in logic and, + for this reason, -fno-builtin should also be included in your + C flags + + And finally you may not be able to use NXFLAT. + + 7. NXFLAT. If you use a pre-built toolchain, you will lose all support + for NXFLAT. NXFLAT is a binary format described in + Documentation/NuttXNxFlat.html. It may be possible to build + standalone versions of the NXFLAT tools; there are a few examples + of this in the misc/buildroot/configs directory. However, it + is possible that there could be interoperability issues with + your toolchain since they will be using different versions of + binutials and possibly different ABIs. + +DOCUMENTATION +^^^^^^^^^^^^^ + +Additional information can be found in the Documentation/ directory and +also in README files that are scattered throughout the source tree. The +documentation is in HTML and can be access by loading the following file +into your Web browser: + + Documentation/index.html + +NuttX documentation is also available online at http://www.nuttx.org. + +Below is a guide to the available README files in the NuttX source tree: + +nuttx + | + |- arch/ + | | + | |- arm/ + | | `- src + | | `- lpc214x/README.txt + | |- avr/ + | | `- README.txt + | |- sh/ + | | |- include/ + | | | |-m16c/README.txt + | | | |-sh1/README.txt + | | | `-README.txt + | | |- src/ + | | | |-common/README.txt + | | | |-m16c/README.txt + | | | |-sh1/README.txt + | | | `-README.txt + | |- x86/ + | | |- include/ + | | | `-README.txt + | | `- src/ + | | `-README.txt + | `- z80/ + | | `- src/ + | | `- z80/README.txt + | `- README.txt + |- configs/ + | |- amber/ + | | `- README.txt + | |- avr32dev1/ + | | `- README.txt + | |- c5471evm/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- compal_e88 + | | `- README.txt + | |- compal_e99 + | | `- README.txt + | |- demo0s12ne64/ + | | `- README.txt + | |- ea3131/ + | | `- README.txt + | |- ea3152/ + | | `- README.txt + | |- eagle100/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- ekk-lm3s9b96/ + | | `- README.txt + | |- ez80f910200kitg/ + | | |- ostest/README.txt + | | `- README.txt + | |- ez80f910200zco/ + | | |- dhcpd/README.txt + | | |- httpd/README.txt + | | |- nettest/README.txt + | | |- nsh/README.txt + | | |- ostest/README.txt + | | |- poll/README.txt + | | `- README.txt + | |- hymini-stm32v/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- lincoln60/ + | | `- README.txt + | |- kwikstik-k40/ + | | `- README.txt + | |- lm3s6432-s2e/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- lm3s6965-ek/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- lm3s8962-ek/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- lpcxpresso-lpc1768/ + | | `- README.txt + | |- lpc4330-xplorer/ + | | `- README.txt + | |- m68332evb/ + | | |- include/README.txt + | | `- src/README.txt + | |- mbed/ + | | `- README.txt + | |- mcu123-lpc214x/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- micropendous3/ + | | `- README.txt + | |- mirtoo/ + | | `- README.txt + | |- mx1ads/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- ne63badge/ + | | `- README.txt + | |- ntosd-dm320/ + | | |- doc/README.txt + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- nucleus2g/ + | | `- README.txt + | |- olimex-lpc1766stk/ + | | `- README.txt + | |- olimex-lpc2378/ + | | |- include/README.txt + | | `- README.txt + | |- olimex-strp711/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- pcblogic-pic32mx/ + | | `- README.txt + | |- pic32-starterkit/ + | | `- README.txt + | |- pjrc-8051/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- qemu-i486/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- rgmp/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- sam3u-ek/ + | | `- README.txt + | |- sim/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- skp16c26/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- stm3210e-eval/ + | | |- include/README.txt + | | |- RIDE/README.txt + | | |- src/README.txt + | | `- README.txt + | |- stm3220g-eval/ + | | `- README.txt + | |- stm3240g-eval/ + | | `- README.txt + | |- stm32f4discovery/ + | | `- README.txt + | |- sure-pic32mx/ + | | `- README.txt + | |- teensy/ + | | `- README.txt + | |- twr-k60n512/ + | | `- README.txt + | |- us7032evb1/ + | | |- bin/README.txt + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- vsn/ + | | |- src/README.txt + | | `- README.txt + | |- xtrs/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- z16f2800100zcog/ + | | |- ostest/README.txt + | | |- pashello/README.txt + | | `- README.txt + | |- z80sim/ + | | |- include/README.txt + | | |- src/README.txt + | | `- README.txt + | |- z8encore000zco/ + | | |- ostest/README.txt + | | `- README.txt + | |- z8f64200100kit/ + | | |- ostest/README.txt + | | `- README.txt + | `- README.txt + |- drivers/ + | |- lcd/ + | | `- README.txt + | |- sercomm/ + | | `- README.txt + | |- syslog/ + | | `- README.txt + | `- README.txt + |- fs/ + | |- mmap/ + | | `- README.txt + | `- nxffs/ + | `- README.txt + |- graphics/ + | `- README.txt + |- lib/ + | `- README.txt + |- libxx/ + | `- README.txt + |- syscall/ + | `- README.txt + `- tools/ + `- README.txt + +apps + |- examples/ + | |- pashello/README.txt + | `- README.txt + |- graphics/ + | `- tiff/README.txt + |- interpreters/ + | |- ficl + | | `- README.txt + | `- README.txt + |- modbus/ + | `- README.txt + |- netutils/ + | |- ftpc + | | `- README.txt + | |- telnetd + | | `- README.txt + | `- README.txt + |- nshlib/ + | `- README.txt + |- system/ + | |- i2c/README.txt + | |- free/README.txt + | `- install + | `- README.txt + |- vsn/ + | |- poweroff + | | `- README.txt + | |- ramtron + | | `- README.txt + | |- sdcard + | | `- README.txt + | `- sysinfo + | `- README.txt + `- README.txt diff --git a/nuttx/ReleaseNotes b/nuttx/ReleaseNotes new file mode 100644 index 0000000000..8c6ae0ccb8 --- /dev/null +++ b/nuttx/ReleaseNotes @@ -0,0 +1,3001 @@ +NuttX-0.1.0 +^^^^^^^^^^^ + +This is the initial. This initial includes the complete NuttX RTOS +with support for the Linux user mode simulation and the TI TMS320C5471 +(Arm7) processor. Partial support for the 87C52 is included. + +This release has been verified on both the Linux user-mode and C5471 +platforms using the test program under examples/ostest. Test results +for the C5471 can be found in arch/c5471/doc/test-results.txt. + +This tarball contains a complete CVS snapshot from March 9,2007. + +NuttX-0.1.1 +^^^^^^^^^^^ + +This is the second release of NuttX. This release includes the following. +See the ChangeLog for more detailed description of the changes. + +(1) General OS bugfixes (see the ChangeLog for details), +(2) bugfixes for the TI TMS320C5471 (Arm7) platform (see + the ChangeLog) +(3) Complete support for the 87C52. (However, the 87C52 + release is not stable enough for general usage). +(4) Added the beginning of a shell call NuttShell (nsh) + +This release has been verified on the Linux user-mode platform, the +Spectrum Digital TMS320C5471 EVM, and the PJRC 87C52 development board +using the test program under examples/ostest. + +STATUS: The development status remains as ALPHA until further testing +is performed. + +This tarball contains a complete CVS snapshot from March 14, 2007. + +NuttX-0.1.2 +^^^^^^^^^^^ + +This is the third release of NuttX. This release is +primarily a bugfix release with minimal new features. See +the ChangeLog for a more detailed description of the +changes. + +(1) Several important OS and ARM7 bugfixes, +(2) opendir(), closedir(), readdir(), etc. added +(3) Added C5471 watchdog timer. +(4) Created a shareable, serial driver. +(5) Added 'ls' command to NuttShell (nsh) +(6) Added a test of the round robin scheduler + +This release has been verified on the Linux user-mode +platform, the Spectrum Digital TMS320C5471 EVM using the +test program under examples/ostest. + +This tarball contains a CVS snapshot from March 19, 2007. + +NuttX-0.2.1 +^^^^^^^^^^^ + +This is the fourth release of NuttX. This release adds adds +support for a new platform, restructures many header files, +and adds a few new features: + +(1) Support for Neuros OSD / DM320 +(2) Restructuring of header files for better POSIX compliance +(3) Added kill() +(4) Added POSIX timers +(5) bugfixes and documentation updates + +This release has been verified on the Linux user-mode +platform, the Spectrum Digital TMS320C5471 EVM, and the +Neuros OSD using the test program under examples/ostest. Because +of the stability of these tests, the project status +has been upgraded to 'beta.' + +This tarball contains a complete CVS snapshot from March 22, 2007. + +NuttX-0.2.2 +^^^^^^^^^^^^ + +This is the fifth release of NuttX. There is no major new +functionality in this release. This release adds support +for new pthread barrier APIs, changes the directory +structure, to better handle different board configurations +using the same processor architecture, and corrects a few +defects. + +See the ChangeLog for a complete list of changes. + +This release has been verified on the Linux user-mode +platform and the Neuros OSD using the test program under +examples/ostest. There are no known, critical defects but +the project development status remains at 'beta' status +pending further test and evaluation. + +This tarball contains a complete CVS snapshot from +March 26, 2007. + +NuttX-0.2.3 +^^^^^^^^^^^^ + +This is the sixth release of NuttX. This release is +primarily a bugfix release. Numerous problems were fixed +as detailed in the change log. New functionality includes +support for timed message queues. + +See the ChangeLog for a complete list of changes. + +This release has been verified on the Linux user-mode +platform and the Neuros OSD using the test program under +examples/ostest. The results of the testing is available in +the source tree under configs/ntosd-dm320/doc/test-results. +There are no known, critical defects but the project +development status remains at 'beta' status pending further +test and evaluation. + +This tarball contains a complete CVS snapshot from March 29, +2007. + +NuttX-0.2.4 +^^^^^^^^^^^^ + +This is the 7th release of NuttX. This release is only to roll out +build changes to better support different SoC's that use the same +processor architecture. In particular, the two existing ARM architectures, +c5471 and DM320 were combined into a single ARM directory. This was done +in preparation for an LPC2148 port that is currently in progress. There +is NO new functionality or significant bugfixes in this release. + +See the ChangeLog for a complete list of changes. + +This release has been verified on the Linux user-mode platform +and the Neuros OSD using the test program under examples/ostest. +The results of the testing is available in the source tree under +configs/ntosd-dm320/doc/test-results and under configs/sim/doc/test-results. +There are no known, critical defects but the project development status +remains at 'beta' status pending further test and evaluation. + +This tarball contains a complete CVS snapshot from April 28, 2007. + +NuttX-0.2.5 +^^^^^^^^^^^^ + +This is the 8th release of NuttX. This release includes: + +(1) Several bug fixes +(2) Initial support for FAT filesystems. Testing has not + been exhaustive and some functionality is missing + (mkdir, stat, unlink chmod, and rename functionality is + not yet implemented). +(3) Support for the NXP lpc2148 processor is included but + is untested as of this writing. The current + implementation includes only support for serial console + and timer interrupt. + +See the ChangeLog for a complete list of changes. + +This release has been verified only on the Linux user-mode +platform. + +This tarball contains a complete CVS snapshot from May 19, +2007. + +NuttX-0.2.6 +^^^^^^^^^^^ + +This is the 9th release of NuttX. This is primarily a +bugfix release to correct a number of problems introduced +with the 0.2.5 release. This release does include some FAT +filesystem extensions including unlink(), mkdir(), rmdir(), +rename(), opendir(), closedir(), readdir(), seekdir(), +telldir(), rewindir(). There are some pending FAT changes +that did not make it into this release including stat(), +truncate(), and long file names. + +See the ChangeLog for a complete list of changes. + +This release has been verified only on the Linux user-mode platform. + +This tarball contains a complete CVS snapshot from May 26, 2007. + +NuttX-0.2.7 +^^^^^^^^^^^ + +This is the 10th release of NuttX. This is primarily a bugfix +release to correct a number of problems reported to me (thanks +Didier!). This release does include the final changes complete the +FAT filesystem logic including stat(), statfs(), and non-standard +APIs to manage FAT attributes. At present, FAT long file names and +file truncate() are still not supported. + +See the ChangeLog for a complete list of changes. + +This release has been verified only on the Linux user-mode platform. + +This tarball contains a complete CVS snapshot from June 9, 2007. + +NuttX-0.2.8 +^^^^^^^^^^^ + +This is the 11th release of NuttX. This release: +(1) corrects important bugs in opendir() and realloc() +(2) adds support for environment variables +(3) adds several new C library interfaces +(4) extends several example programs + +See the ChangeLog for a complete list of changes. + +This release has been verified only on the Linux user-mode platform. + +This tarball contains a complete CVS snapshot from July 2, 2007. + +NuttX-0.3.0 +^^^^^^^^^^^ + +This is the 12th release of NuttX. This release includes the initial +integration of a network subsystem and the uIP TCP/IP stack into NuttX +(see http://www.sics.se/~adam/uip/index.php/Main_Page). Also included +is a device driver for the Davicom DM90x0 Ethernet controller. + +This integration is very preliminary. Only a small portion of the +network functionality has been integrated and there are a number of +open issues (see the TODO file). The network subsystem is pre-alpha +at this point in time. I expect that it will stabilize and mature +over the next few releases. + +The baseline functionality of NuttX continues to mature and remains at +post-beta (as long as the network is not used). + +See the ChangeLog for a complete list of changes. + +This release has been verified only on the Neuros OSD (DM320 ARM9) +platform using the DM90x0 driver. + +This tarball contains a complete CVS snapshot from November 6, 2007. + +NuttX-0.3.1 +^^^^^^^^^^^ + +This is the 13th release of NuttX and the second release containing +the integration of a network subsystem and the uIP TCP/IP, UDP, and +ICMP stacks into NuttX (see http://www.sics.se/~adam/uip/index.php/Main_Page). + +Many network-related problems have been fixed and the implementation +has matured significantly. However, the level of network reliability +is probably still at the pre-alpha or early level. It is sufficiently +complete that you may begin to perform some network integration and +is expected to achieve beta level of reliability over the next few +releases. + +The baseline functionality of NuttX continues to mature and remains at +post-beta (as long as the network is not used). + +See the ChangeLog for a complete list of changes. + +This release has been verified only on the Neuros OSD (DM320 ARM9) +platform using the DM90x0 driver. + +This tarball contains a complete CVS snapshot from November 19, 2007. + +NuttX-0.3.2 +^^^^^^^^^^^ + +This is the 14th release of NuttX and the 3rd release containing +the integration of a network subsystem and the uIP TCP/IP, UDP, and +ICMP stacks into NuttX (see http://www.sics.se/~adam/uip/index.php/Main_Page). + +Many network-related problems have been fixed and the implementation +has matured significantly. This release consists of: + +o TCP-related bug-fixes +o TCP performance improvements +o Initial UDP integration +o Initial uIP micro webserver integration + +See the ChangeLog for a complete list of changes. + +The level of network reliability is at alpha level is expected to +achieve beta level of reliability over the next few releases. + +The baseline functionality of NuttX continues to mature and remains at +post-beta. + +This release has been verified only on the Neuros OSD (DM320 ARM9) +platform using the DM90x0 driver. + +This tarball contains a complete CVS snapshot from November 23, 2007. + +NuttX-0.3.3 +^^^^^^^^^^^ + +This is the 15th release of NuttX and the 4th release containing +the integration of a network subsystem and the uIP TCP/IP, UDP, and +ICMP stacks into NuttX (see http://www.sics.se/~adam/uip/index.php/Main_Page). + +Many network-related problems have been fixed and the implementation +has matured significantly. This release consists of: + +o TCP-related bug-fixes for disconnecting sockets +o Correction of some TCP read-ahead logic +o TCP performance improvements +o Misc. additions and cleanup (See the ChangeLog for a complete list of + changes). + +The level of network reliability is at an early beta release level. The +baseline functionality of NuttX continues to mature and remains at +post-beta. Open network-related issues include only: + +o Some minor unimplemented BSD socket functionality, +o Thread safety issues: the same socket cannot be used concurrently on + different threads. +o Pending design changes necessary to support multiple network interfaces. +o IPv6 support is incomplete. + +This release has been verified only on the Neuros OSD (DM320 ARM9) +platform using the DM90x0 driver. Any feedback for improving the network +reliability/performance would be greatly appreciated. + +This tarball contains a complete CVS snapshot from November 28, 2007. + +NuttX-0.3.4 +^^^^^^^^^^^ + +This is the 16th release of NuttX and the 5th release containing +the integration of a network subsystem and the uIP TCP/IP, UDP, and +ICMP stacks into NuttX (see http://www.sics.se/~adam/uip/index.php/Main_Page). + +This release is primarily a bug-fix release. New features include +only: + +o TELNET front-end to NSH, +o DHCPC server functionality, and +o C5471 Ethernet driver. + +Numerous network related problems were fixed related to DHCPC, UDP +input processing, UDP broadcast, send timeouts, and bad compilation when +uIP is compiled at high levels of optimization. + +The level of network reliability is at a strong beta release level. The +baseline functionality of NuttX continues to mature and remains at +post-beta or production level. + +Parts of this release were verified only on the Neuros OSD (DM320 ARM9) +platform using the DM90x0 Ethernet driver and other parts on the Spectrum +Digital C5471 EVM using the C5471 Ethernet driver. Any feedback about bugs +or suggestions for improving the network reliability/performance would be +greatly appreciated. + +This tarball contains a complete CVS snapshot from December 10, 2007. + +NuttX-0.3.5 +^^^^^^^^^^^ + +This is the 17th release of NuttX this release is primarily a bug-fix +release and intended to synchronize with the current CVS contents. See +the ChangeLog for a detailed list of changes and fixes. + +This release were verified only on the Spectrum Digital C5471 EVM using +the C5471 Ethernet driver. Any feedback about bugs or suggestions for +improvement would be greatly appreciated. + +This tarball contains a complete CVS snapshot from December 18, 2007. + +NuttX-0.3.6 +^^^^^^^^^^^ + +This is the 18th release of NuttX. This release contains on a few +changes. The primary purpose of this release is to synchronize with +the release of the pascal-0.1.0 add-on package. + +This release of NuttX includes the following changes: + +* Fixes for use with SDCC compiler +* Added a simulated z80 target (arch/z80) +* Fix deadlock errors when using stdio but with no buffering +* Add support for the add-on Pascal P-Code interpreter (pcode/) + (see the pascal-0.1.0 package) + +This release were verified only on the simulated Z80 and and host +simulation targets. As usual, any feedback about bugs or suggestions +for improvement would be greatly appreciated. + +This tarball contains a complete CVS snapshot from January 6, 2007. + +==== + +There was an error in the initial 0.3.6 release that prevented +a successful build unless the Pascal add-on was present. The +tarball was patched to include the fix. Make sure that you download +the nuttx-0.3.6.1.tar.gz version to avoid this problem. + +NuttX-0.3.7 +^^^^^^^^^^^ + +This is the 19th release of NuttX. This release includes the +preliminary port of NuttX to the ZiLOG z16f 16-bit microcontroller. +This port was verified using the ZiLOG z16f2800100zcog Development +and the ZiLOG ZDS-II toolchain. See http://www.zilog.com for +further information. + +I emphasize that this is a preliminary release of the z16f port and +is only alpha or, perhaps, pre-alpha quality as of this writing. +There are a list of known issues in the TODO file in the root of +the NuttX directory. The overall quality of NuttX (excluding the +z16f port) continues to improve beyond the late beta level. + +The z16f port required numerous changes to NuttX to handle: + +* NEAR and FAR addressing, and +* Use of a Windows native toolchain in a Cygwin build environment. + +In addition to the z16f port, at least one very critical bug was +found and corrected in NuttX: The thread-specific errno value of one +task was being randomly trashed when a different thread exited. + +This release were verified on the ZiLOG z16f2800100zcog, Neuros OSD +(ARM9), and the simulation platforms. As usual, any feedback about bugs +or suggestions for improvement would be greatly appreciated. + +This tarball contains a complete CVS snapshot from January 31, 2008. + +NuttX-0.3.8 +^^^^^^^^^^^ + +This is the 20th release of NuttX. This is a minor bugfix release. +It corrects a few minor problems, adds a few minor features, and +continues the integration of the ZiLOG Z18F and of the Pascal P-Code +add-on. This release is synchronized with the release of Pascal-0.1.2. + +This tarball contains a complete CVS snapshot from February 10, 2008. + +NuttX-0.3.9 +^^^^^^^^^^^ + +This is the 21st release of NuttX. This is a minor future enhancement +release. This release includes support for the ZiLOG Z8Encore! micro- +controller. Also included is the initial framework for support for +the Z80, XTRS platform (http://www.tim-mann.org/xtrs.html). + +This released has been verified only on the ZiLOG ZDS-II Z8Encore! +chip simulation. + +This tarball contains a complete CVS snapshot from March 9, 2008. + +NuttX-0.3.10 +^^^^^^^^^^^^ + +This is the 22nd release of NuttX. This is an important bug fix +release. This release incorporates fixes to correct critical list +handling errors in task shutdown logic: One in timer deletion logic +(timer_delete.c) and one in stream logic (lib_init.c). This release +also includes support to ZiLOG EZ80Acclaim microcontroller (EZ80F91 +chip) and configurations for the ZiLOG z8f64200100kit (Z8F6423) and +ez80f0910200kitg (EZ80F091) development kit. + +NuttX-0.3.11 +^^^^^^^^^^^^ + +This is the 23rd release of NuttX. This is another important bugfix +release. This releases fixes several bugs: + +* Two POSIX timer bugs: a memory leak as well a fatal sequencing error. +* Several FAT filesystem errors. +* A deadlock that can occur in opendir() + +A few new features were also added: + +* Support for recursive mutexes +* Added a RAM disk block driver +* The host simulator no longer uses direct Linux system calls and + now also works on Cygwin. +* The OS test was strengthen and now runs as an endurance test + +These changes were verified only on the Host simulator under Cygwin. +Please report any errors to me. + +This tarball contains a complete CVS snapshot from June 1, 2008. + +NuttX-0.3.12 +^^^^^^^^^^^^ + +This is the 24th release of NuttX. This release includes some minor +bugfixes as well as a few new features. Bugs fixed include: + +* Corrected an error in recursive mutex implementation. +* task_create() was only dup()ing the first three file descriptors. +* Fixed driver open reference counting errors in dup(), dup2(), and exit(). +* Fixed error handling logic in fflush(). + +New features were also added: + +* Pipes and pipe() API +* FIFOs and mkfifo() API +* mkfatfs() API can be used to format FAT file systems. + +These changes were verified only on the Host simulator under Cygwin. +Please report any errors to me. + +This tarball contains a complete CVS snapshot from August 10, 2008. + +NuttX-0.3.13 +^^^^^^^^^^^^ + +This is the 25th release of NuttX. This release includes some +important bugfixes as well as a few new features. Bugs fixed +include: + +* Fixed problems with Cygwin-based console input. NSH now works + with the Cygwin simulator. +* sched_get_priority_max/min returned error on SCHED_RR +* Corrected detection of End-of-File in fgets() +* Fixed an error in opendir() that could cause an assertion to fail + inappropriately. +* Corrected an error in the FAT that caused files opened for writing + with O_APPEND to fail. +* Fix error in getopt() when called with argc==1 +* Fix error in stat() when used on the root directory +* Fixed a critical bug that effects the way that environment variables + are shared among pthreads. +* uIP port now supports multi-threaded, concurrent socket access. + So, for example, one thread can be reading from a socket while + another is writing to the socket. + +New features were also added: + +* New OS APIs: chdir() and getcwd() +* The Nuttx shell (NSH) has been extended in many ways. + - New commands: mkfatfs, mkfifo, sleep, usleep, nice, sh, cd, and pwd + - New memory inspection commands and heap usage commands + - New capabilities: + - Execution of commands in background + - Execution of simple scripts + - Redirection of command output + - Last command status ($?) + - Now supports if-then[-else]-fi construct + - Other features as noted in the ChangeLog. + +These changes were verified only on the Host simulator under Cygwin +and under Linux and also on the Neuros OSD (ARM9). Please report +any errors to me. + +This tarball contains a complete CVS snapshot from September 1, 2008. + +nutt-0.3.14 +^^^^^^^^^^^ + +This is the 26th release of NuttX. This release includes some +important bugfixes as well as a few new features. Critical bugs +fixed include: + +FAT FS: + * Fixed several critical bugs with regard to fat reading and + writing and FAT12 accesses. Basically the FAT FS only worked + with my tiny test files and test cases. A lot of stronger FAT + tested is still needed! + * Fixed another FAT bug in implementation of FAT lseek(); + this prohibited correct random access to large files. + +Network: + * Corrected a critical bug that may prevent recvfrom from receiving + packets from most remote UDP port numbers. + * Corrected an error in multi-threaded socket handling in send() and + sendto(). Outgoing data could overwrite incoming data. + * Corrected IP checksum calculation in ICMP and UDP message send logic. + * Corrected an error in send() timeout logic. + +New features were also added: + +Network: + * Added support for application access to ICMP protocol stacks + * Added ping request logic (net/uip). + * Added basic TFTP client logic (netutils/tftpc). + +NuttShell (NSH): + * New commands: 'test', '[', 'ping', 'mkrd', 'xd', and TFTP 'get' and 'put' + See the new NuttShell User Guide for additional information. + +Other less critical bugs were also fixed and other less important +features were were added. See the ChangeLog for details. + +These changes were verified only on the Neuros OSD (ARM9). Please +report any errors to me. + +This tarball contains a complete CVS snapshot from September 8, 2008. + +nutt-0.3.15 +^^^^^^^^^^^ + +This is the 27th release of NuttX. This release includes some new features: + +* Adds support for the ROMFS filesystem +* ROMFS supports mmap() to provide eXecute In Place (XIP) capability +* NuttShell (NSH) can be configured to use ROMFS to provide a tiny read-only + filesystem with a startup script in /etc. +* Completed the basic port of the NXP LPC2148 on the mcu123.com board. + The basic port includes successful booting, timer interrupts, + serial console, successfully passing the examples/ostest, and a + NuttShell (NSH) configuration. + +These changes were verified only on the mcu123.com NXP LPC2148 +board. Please report any errors to me. + +This tarball contains a complete CVS snapshot from September 20, 2008. + +nutt-0.3.16 +^^^^^^^^^^^ + +This is the 28th release of NuttX. This release includes the first +support for USB in NuttX. A set of USB APIs were added to support +USB device controller drivers and bindings to USB device class +drivers. The form of the interface was inspired by the Linux Gadget APIs. + +At present USB device controller drivers are included for: + * The NXP LPC214x. This driver has been verified and is an early alpha + stage in quality. + * TI DM320. Coding for this driver is complete but it is completely + untested as of this release. + +A controller-independent class driver is also included for: + * USB serial class device driver (emulates the Prolific PL2303 + serial-to-USB adapter). This driver has only been verified with + the Linux host PL2303 driver. + +Other new features include: + * Add an option to set aside a separate stack for interrupt + handling (ARM only). This is useful when memory is constrained, + there are multiple tasks, and the interrupt stack requirement + is high (as when USB is enabled). + +A few bugs were also fixed: + * Fixed the frequency of system timer interrupts in the NXP LPC214x port + (off by 20x in nuttx-0.3.15) + * Fixed serial driver bugs related to (1) open counts and (2) recognizing + O_NONBLOCK on read. + * Fixed an error in read(); it was not setting the errno on errors returned + from the driver. + +These changes were verified only on the mcu123.com NXP LPC2148 board +using with a Linux host. Please report any errors to me. + +This tarball contains a complete CVS snapshot from October 10, 2008. + +UPDATE +^^^^^^ +This release does not build for the ARM target when USB is disabled. +Here is the fix: + +Index: arch/arm/src/common/up_internal.h +=================================================================== +RCS file: /cvsroot/nuttx/nuttx/arch/arm/src/common/up_internal.h,v +retrieving revision 1.13 +diff -u -r1.13 up_internal.h +--- arch/arm/src/common/up_internal.h 6 Oct 2008 16:20:52 -0000 1.13 ++++ arch/arm/src/common/up_internal.h 13 Oct 2008 20:48:21 -0000 +@@ -200,7 +200,8 @@ + extern void up_usbinitialize(void); + extern void up_usbuninitialize(void); + #else +-# define up_netinitialize() ++# define up_usbinitialize() ++# define up_usbuninitialize() + #endif + + #endif /* __ASSEMBLY__ */ + +NuttX-0.3.17 +^^^^^^^^^^^^ + +This is the 29th release of NuttX. This release includes the +additional support for USB in NuttX. The following new features +were added: + +* Added support for SPI-based MMC/SD cards (with an SPI driver + for the NXP LPC214x). +* Added USB storage class device side driver (BBB) +* Added an example that demonstrates the USB storage class by + exporting the SPI based MMC/SD card on the NXP LPC214x. + +This is an early alpha release of these drivers. At present they +only work with debug features enabled so there are probably some +race conditions that occur only with debug features disabled. +(Anyone out there with a USB analyzer? I would love to know what +is happening.) + +Several important bugs were also fixed in the FAT file system, USB +serial driver and NXP LPC214x USB controller driver. (See the ChangeLog +for details.) + +These changes were verified only on the mcu123.com NXP LPC2148 board +using a Linux development environment. USB testing was performed +using both a Linux host and a WinXP host. Please report any errors +to me. + +This tarball contains a complete CVS snapshot from October 28, 2008. + +NuttX-0.3.18 +^^^^^^^^^^^^ + +This is the 30th release of NuttX. This release includes two +partially completed ports, several new features, and a couple of +important bug fixes. The two partially completed ports are: + + * The STMicro STR71x processor and configuration for the Olimex + STR-P711 board. + * The Hitachi SH-1 using the SH1_LCEVB1 (SH-1/US7032EVB1) board + +Progress on these ports is stalled (as detailed in the ChangeLog). + +The new features focus primarily on management of block devices and +extensions of the NuttShell (NSH). These include: + + * A loop device that converts a file into a block device. + * A block to character (BCH) driver that allow access a block device as + if it were character device. + * Added strcasecmp() and strncasecmp() libc functions. + * Added the 'dd' and 'losetup' commands to NSH. These commands + (along with mkfatfs and mount), give good management of filesystems + on the target. + +Several bugs were fixed, the most important of which are: + + * Fixed a race condition workaround delay in LPC214X SPI logic. + This was also the cause of some bad MMC/SD performance on that + platform. + + * Fixed a recently introduced FAT file system problem: It would + mount a (invalid) FAT file system even if the medium is not formatted! + + * Corrected two other important errors in the FAT lseek() implementation: + 1 - The sectors-per-cluster value was being reset to "1". + 2 - Important lseek logic was omitted when the seek position was zero. + +The FAT filesystem has had many bugs fixed in it and, I think, is +now maturing and becoming stable. + +These changes were verified only on the mcu123.com NXP LPC2148 +board, the Hitachi SH1_LCEVB1 board, and the Linux simulator, all +using a Linux development environment. Please report any errors +to me. + +This tarball contains a complete CVS snapshot from November 16, 2008. + +NuttX-0.3.19 +^^^^^^^^^^^^ + +This is the 31st release of NuttX. This release includes the +following new feature: + + * Add poll() and select() APIs that may be used to monitor for + data availability on character devices or TCP/IP sockets. + * Implemented support TCP/IP connection backlog. This allows + select() to wake-up on new connections to a listener socket. + * Added definition of a framebuffer driver and implement framebuffer + drivers for the simulated platform and the TI DM320 (untested + as of the initial check-in). + * Partially developed a graphics framework based on the framebuffer + drivers, however, this will not be ready for use for a few more + releases. Currently this includes only a few color conversion + routines and some rasterizing functions. A tiny windowing system + is under development but not ready for check-in yet. + * Added support for fixed precision math. + * Added support for outgoing multicast packets. + +Several bugs were fixed, the most important of which are: + + * Fixed an important bug in the TCP/IP buffering logic. When + TCP/IP read-ahead is enabled and not recv() is in-place when a + TCP/IP packet is received, the packet is placed into a read-ahead + buffer. However, the old contents of the read-ahead buffer + were not being cleared and old data would contaminate the newly + received buffer. + + * Changed the behavior of the serial driver read. It now returns + data as it is available rather than waiting for the full requested + read size. This makes functions like fgetc() work much more + smoothly. + +These changes were verified only on the Neuros OSD (ARM9) using a +Linux development environment. Please report any errors to me. + +This tarball contains a complete CVS snapshot from November 26, 2008. + +NuttX-0.4.0 +^^^^^^^^^^^ + +This is the 32nd release of NuttX. This release adds graphics +support and a tiny windowing subsystem. That new graphics subsystem +is documented at http://nuttx.sourceforge.net/NXGraphicsSubsystem.html. +No other substantial changes were made. + +These changes were verified only on the NuttX simulation platform +with X11 windows simulating a device framebuffer. Please report any +errors to me. + +The version number was bumped up to 0.4.0 in part to reflect the +new graphics subsystem, but also to recognize the NuttX is approaching +complete functionality. In the 0.3.x versions, network support was +added, Pascal P-code runtime support was added, FAT and ROMFS +filesystems were added, MMC/SD and USB device support were added. +There were also numerous extensions to the NuttShell, NuttX APIs, +and architecture ports. + +This tarball contains a complete CVS snapshot from December 6, 2008. + +NuttX-0.4.1 +^^^^^^^^^^^ + +This is the 33rd release of NuttX. This is a minor bugfix release. +The primary reason for this release is to correct numerous build +errors that have accumulated for the ZiLOG ZDS-II based targets. +All ZDS-II targets now build correctly (but have not been re-tested). +In addition to platform-specific build failures, this release also +adds the following features which were not tested as of the time +of the release: + + * Board support for the ZiLog ez80Acclaim! ez80f910200zco Development Kit + * ZiLOG eZ80F91 EMAC driver + +These changes were verified only on the NuttX simulation platform. +Please report any errors to me. + +This tarball contains a complete CVS snapshot from February 6, 2009. + +NuttX-0.4.2 +^^^^^^^^^^^ + +This is the 34th release of NuttX. This release adds no new OS +features but does include support for two new architectures: + + * ez80Acclaim! Basic support has been integrated and verified + for the ez80f910200zcog-d board (eZ80F91-based). That basic + support includes timer interrupts and serial console. Ongoing + work includes an EMAC driver that should be integrated for the + next release nuttx-0.4.2. eZ80Acclaim! support has been in the + code base for some time, but has only just been integrated due + to toolchain issues. + + * Renesas M16C/20. Support for the Renesas SKP16C20 board has + been included in the NuttX source tree. However, as the + eZ80Acclaim!, testing and integration of that port is stalled + due to toolchain issues. + +These changes were verified only on the ZiLOG eZ80910200zcog-d +board. Please report any errors to me. + +This tarball contains a complete CVS snapshot from February 28, 2009. + +NuttX-0.4.3 +^^^^^^^^^^^ + +This is the 35th release of NuttX. This release one important new +OS feature and corrects and extends the eZ80 port: + + * Priority Inheritance. The basic NuttX waiting logic was extended + to support priority inheritance. See the NuttX User Manual for + further information: + http://www.nuttx.org/NuttxUserGuide.html#priorityinheritance. + + * ez80Acclaim! Corrected several critical, show-stopping bugs on that + platform including: + - Errors in the serial driver interrupts. + - An error in the eZ80 table. + * eZ80Acclaim!: Completed integration of the eZ80F91 EMAC driver. + +These changes were verified only on the ZiLOG eZ80910200zcog-d board +and on Cygwin-based simulation platform in various configurations. +Please report any errors to me. + +This tarball contains a complete CVS snapshot from March 13, 2009. + +NuttX-0.4.4 +^^^^^^^^^^^ + +This is the 36th release of NuttX. This release focuses on bugfixes +and extending and verifying certain networking features. + + * Important bugs were fixed in NSH, UDP checksum calculation, UDP + bind() behavior for port==0, the eZ80Acclaim! EMAC driver, Z80 + interrupt handling, and in the C libraries. + + * Testing was extended to further verify the tiny webserver, + DHCPD, wget(), and sendmail. + +See the Changelog for a detailed description of these changes. + +These changes were verified only on the ZiLOG eZ80910200zcog-d board +using the ZDS-II toolchain in Cygwin-based environment. Please +report any errors to me. + +This tarball contains a complete CVS snapshot from March 29, 2009. + +NuttX-0.4.5 +^^^^^^^^^^^ + +This is the 37th release of NuttX. This release focuses on a few new features. + + * The basic port for the Freescale ARM920T i.MX1 processor on the + Freescale MX1ADS board. Coding is complete for this port, but + it is has not yet fully integrated + * Extended I2C and SPI interface definitions + * Add basic support for C++ applications. Very simple C++ + applications can now be built against NuttX without any external + libraries. At present, only the most primitive C++ programs + are supported, but it is hoped that this support will be extended + in future releases. + +See the Changelog for a detailed description of these changes. + +This tarball contains a complete CVS snapshot from April 19, 2009. + +NuttX-0.4.6 +^^^^^^^^^^^ + +This is the 38th release of NuttX. The release features support +for the Micromint Eagle-100 development board. This board is based +around, the Luminary LM3S6918 MCU. This is the first ARM Cortex-M3 +architecture supported by Nuttx. This initial, basic port includes +timer and serial console with configurations to execute the NuttX +OS test and to run the NuttShell (NSH). Work is still underway on +this port and current plans are to have I2C, SSI, MMC/SD, and and +Ethernet driver in the 0.4.7 release. + +Additional work was done on the MXADS i.MX1 port, however, that +work has been set aside until I complete work on the Eagle-100 (I +also need to come up with a 3V power supply). + +Other changes in this release include: Extensions to the SPI interface +definition in order to handle 9-bit interfaces to displays. Several +bugs were fixed (see the ChangeLog for a complete list of changes). + +This tarball contains a complete CVS snapshot from May 19, 2009. + +NuttX-0.4.7 +^^^^^^^^^^^ + +This is the 39th release of NuttX. This release focuses on cleaning +up and extending the Eagle100/LM3S6918 port released in nuttx-0.4.6 +and on improved MMC/SD support. New features include: + + * Improved reliably and additional drivers for the Eagle-100 board + (LM3S6918 ARM Cortex-M3). Additional drivers include Ethernet, + SSI, and support for the on-board LEDs and microSD cards. + + * The SPI-based MMC/SD driver was extended to support SDHC Version + 2.xx cards. + +In addition, this release includes several important bugfixes for +the LM3S6918, the LPC2148, the SPI-based MMC/SD driver, and to +FAT32. See the ChangeLog for details of these bugfixes. + +This tarball contains a complete CVS snapshot from May 29, 2009. + +NuttX-0.4.8 +^^^^^^^^^^^ + +This is the 40th release of NuttX. This release adds: + + * Support for the Olimex STRP711 board. That board is based on + the STMicro STR711 MCU (ARM7TDMI). Integration is complete on + the basic port (boot logic, system time, serial console). Two + configurations have been verified: (1) The board boots and + passes the OS test with console output visible on UART0, and + the NuttShell (NSH) is fully functional with interrupt driven + serial console. An SPI driver is available but untested (because + the Olimex card slot appears to accept only MMC cards; I have + only SD cards). Additional needed: USB and driver, MMC + integration. + + * Support for the CodeSourcery and devkitARM Windows-native GNU + toolchains. Makefiles have been modified for the LM3S6918, + LPC2148, and STR711 to support these toolchains under Cygwin. + +This tarball contains a complete CVS snapshot from June 13, 2009. + +NuttX-0.4.9 +^^^^^^^^^^^ + +This is the 41st release of NuttX. This release adds: + + * Support for a new binary format call NXFLAT that can be used to + execute separately linked programs in place in a file system. + See http://www.nuttx.org/NuttXNxFlat.html. + + * Several important bugs were files related to networking and ROMFS. + See the ChangeLog for a complete list. + +This tarball contains a complete CVS snapshot from June 26, 2009. + +NuttX-0.4.10 +^^^^^^^^^^^ + +This is the 42nd release of NuttX. This released focused on the +port of Jeff Poskanzer's THTTPD HTTP server (see +http://acme.com/software/thttpd/). As of the 0.4.10 release, that +port is still not fully complete and functional. However, numerous +related bug-fixes and functional additions for THTTPD were added: + + * Several new standard C-library functions (fileno, strstr, + strpbrk, fcntl). + * Improved and extended timing APIs (mktime, gmtime, gmtime_r, + gettimeofday, localtime, localtime_r, and strftime) + * Networking enhancements: recvfrom() and accept() now work with + non-blocking sockets. + * NXFLAT extensions (exec) + * Pattern matching logic. + * And miscellaneous bug fixes (see the ChangeLog for details). + +This tarball contains a complete CVS snapshot from August 8, 2009. + +NuttX-0.4.11 +^^^^^^^^^^^^ + +This is the 43rd release of NuttX. This release of NuttX incorporates +the verified port of Jeff Poskanzer's THTTPD HTTP server (see +http://acme.com/software/thttpd/). Many of the key features of +THTTPD have been tested on the Micromint Eagle-100 development board +(Cortex-M3). These tests verify: + + * Serving of files from any file system + * Execution of CGI executable. This release supports execution + of NXFLAT executables on a ROMFS file system + (http://www.nuttx.org/NuttXNxFlat.html) + +A standard CGI interface is used: Information is pasted to the CGI +program via POST commands and via environment variables. CGI socket +I/O is redirected to stdin and stdout so that the CGI program only +need to printf() to send its content back to the HTTP client. + +Another value to this THTTPD integration effort has been that THTTPD +has provided a very good test bed for finding NuttX networking bugs. +Several very critical networking bugs have been fixed with this +0.4.11 release (see the ChangeLog for details). Networking throughput +has also been greatly improved. Anyone using NuttX networking +should consider upgrading to this release. + +This tarball contains a complete CVS snapshot from September 16, 2009 + +NuttX-0.4.12 +^^^^^^^^^^^^ + +This is the 44th release of NuttX. This release adds basic support +for the STMicro STM32, Cortex-M3 MCU. The specific port is to the +STMicro STM3210E-EVAL development board based around the STM32F103ZET6 +MCU. Some highlights of this port: + + * This basic port includes boot-up logic, interrupt driven serial + console, and system timer interrupts. + * Includes a basic STMicro RIDE7 project that can be used to + perform basic STM32 board bring-up (due to RIDE7 size limitations, + it cannot be used for the full NuttX bring-up). + * Working, Tested Configurations: the NuttX OS test and the + NuttShell (NSH) example. + +This basic STM32 port will be extended in the 0.4.13 NuttX release. +Functionality needed for complete STM32 support includes: USB +device driver, LCD driver and NX bringup on the development board's +display and MicroSD support. An SPI driver and a DMA support was +included in this 0.4.12 release, but is not yet tested. + +This tarball contains a complete CVS snapshot from October 17, 2009 + +NuttX-0.4.13 +^^^^^^^^^^^^ + +This is the 45th release of NuttX. The release extends the support +for the STMicro STM32 microcontroller. Minimal support for the +STM3210E-EVAL development board based around the STM32F103ZET6 MCU +was released in NuttX-0.4.12. This release adds: + + * A simple interface definition to support some FLASH, EEPROM, + NVRAM, etc. devices. + * Verified SPI operation using driver for SPI based FLASH parts + M25P64 and M25P128. + * Improved Cortex-M3 context switching. This should improve + context switching performance be 2x in certain cases. + * Added a USB device-side driver for the STM32. This is an early + release of a very complex driver; some bugs are expected. + * The USB driver has been verified against the USB serial device + class driver. There is at least one known outstanding issue + (see the full bug description in the TODO list). + +This release also corrects some important bugs in the early STM32 release: + + * Fixed several errors the prevented operation of NuttX on an + STM32 development board using USART2 as the serial console. + * Fixed and optimization-dependent race condition in the clock + initialization. + * Fixed a critical bug in the interrupt control logic that could + cause interrupt operations to failed used for interrupts in a + certain range. + +This tarball contains a complete CVS snapshot from November 4, 2009 + +NuttX-4.14 +^^^^^^^^^^ + +This is the 46th release of NuttX. The release extends the support +for the STMicro STM32 microcontroller. Minimal support for the +STM3210E-EVAL development board based around the STM32F103ZET6 MCU +was released in NuttX-0.4.12 and extended in Nuttx-0.4.13 to include +initial USB support. This completes the STM32F103ZET6 and adds: + +New Generic RTOS Features: + + * Added generic support that can be included in any block driver + to provide read-ahead buffering and write buffering for improved + driver performance. + * Added a generic worker thread that can used to defer processing + from an interrupt to a task. + * Defined a generic SD/SDIO interface can can be bound to a MMC/SD + or SDIO driver to provide SDIO support. + * Implemented a an SDIO-based MMC/SD driver using this new SDIO + interface. + +New STM32 Features: + + * Add support to configure an STM32 input GPIO to generate an + EXTI interrupt. + * Added support for buttons on the STM3210E-EVAL board. + * Implemented an STM32 version of the common the SDIO interface. + * Added a configuration to exercise the STM32 with the USB mass + storage device class example. + +This release also corrects some important bugs in the early STM32 release: + + * Correct error handling in the mount() logic. + * Fixed several STM32 DMA-related issues. Integrated and debugged + STM32 DMA functionality that was added in 0.4.12. + * Fixed several bugs in the STM32 USB device-side driver. + +NOTE: This version, 4.14, is equivalent to what would have been +called 0.4.14 to follow 0.4.13. The zero has been eliminated from +the front of the version number to avoid confusion about the state +of development: Some have interpreted the leading zero to mean +that the code is in some way unstable. That was not the intent. +Beginning in January 2010, I will switch to the 2010.nn versioning +as many others have done to avoid such confusion. + +This tarball contains a complete CVS snapshot from December 2, 2009 + +NuttX-5.0 +^^^^^^^^^ + +This is 47th release of NuttX and the successor to nuttx-4.14. This +major revision number has been incremented to indicate that an +incompatibility with previous nuttx releases has been introduced. +This version adopts standard fixed width integer names as specified +by the ANSI C99 standard. The core logic of NuttX is older than +that standard and did not conform to it. + +If you have applications running on NuttX-4.14, those applications +should continue to build and execute without problem on NuttX-5.0. +However, if you have device drivers or other OS-internal logic, you +will probably have to make some minor changes to your code to use +this version. Below is a summary of those changes: + + * If you include sys/types.h to get the non-standard, fixed width + integer types (uint32, uint16, ubyte, etc.), that is no longer + necessary. + * Instead, you will need to include stdint.h where the new fixed + width integer types are defined (uint32_t, uint16_t, uint8_t, etc). + * You will have to change all occurrences of the following types: + + uint32 -> uint32_t + uint16 -> uint16_t + ubyte -> uint8_t + uint8 -> uint8_t + sint32 -> int32_t + sint16 -> int16_t + sint8 -> int8_t + + * In addition, the non-standard type 'boolean' must replaced with + the standard type 'bool'. The type definition for 'bool' is in + stdbool.h + +This change in typing caused small changes to many, many files. It +was verified that all configurations in the release still build +correctly (other than the SDCC-based configurations). Regression +testing was performed on a few configurations, but it is possible +that minor build issues still exist. (If you encounter any, please +let me know and I will help you to fix them.) + +In the course of the regression testing, several important bugs +unrelated to the type changes were found and corrected. + + * Fixed an important error in the RX FIFO handling logic of the + LM3S6918 Ethernet driver. + * Corrected the handling of TCP sequence numbers in the TCP stack. + * And other less important bugs as detailed in the ChangeLog. + +The primary focus of this release was standards compatibility, but +a few new features were added including a (1) Flash Translation +Layer (FTL) that will support filesystems on a FLASH device and (2) +partial ports for the STM32F107VC and HCS12 C9S12NE64 MCUs. Those +ports are very incomplete as of this writing. + +This tarball contains a complete CVS snapshot from December 21, 2009 + +NuttX-5.1 +^^^^^^^^^ + +This is the 48th release of NuttX. This release adds support for +two new MCU architectures in various states of development: + +* AT91SAM3U (http://www.atmel.com/products/at91/sam3landing.asp?family_id=605) + + This release adds support for the SAM3U-EK development board with + the AT91SAM3U4E MCU + (http://www.atmel.com/dyn/products/product_card_mcu.asp?part_id=4562). + As with most NuttX architecture releases, the release will be + rolled out in two parts: A basic port and an extended port. + + NuttX-5.1 includes the basic port for the SAM3U-EK board. This + release passes the NuttX OS test and is proven to have a valid + OS implementation. It supports the basic boot-up, serial console + and timer interrupts. A configuration to support the NuttShell + is also included. + + The extended port will also include support for SDIO-based SD + cards and USB device (and possible LCD support). These extensions + may or may not happen by the Nuttx 5.2 release as my plate is + kind of full now. + +* LPC3131 (http://ics.nxp.com/products/lpc3000/lpc313x.lpc314x.lpc315x/) + + This release also adds the complete implementation of the basic + port for the NXP LPC3131 MCU on the Embedded Artists EA3131 board + (http://www.embeddedartists.com/products/kits/lpc3131_kit.php). + That port, unfortunately has stalled due to tools issues. Those + tool issues have been resolved and I am confident that the verified + basic port will be available in NuttX-5.2. + + The extended release will follow and should include SDIO-based + SD card support and device USB. + +A few additional features and bugfixes of a minor nature were also +incorporated as detailed in the ChangeLog. + +NuttX-5.2 +^^^^^^^^^ + +This is the 49th release of NuttX. This release completes the +verification of the basic port for the NXP LPC3131 MCU on the +Embedded Artists EA3131 board +(http://www.embeddedartists.com/products/kits/lpc3131_kit.php). +This basic port includes basic boot-up, serial console, and timer +interrupts. This port has been verified on the using the NuttX OS +test and includes a working implementation of the NuttShell (NSH). + +An extended release will follow and should include SDIO-based SD +card support and device USB. + +NuttX-5.3 +^^^^^^^^^ + +This is the 50th release of NuttX. This release support for one new +architecture: + + * A basic port for the NXP LPC2378 MCU on the Olimex-LPC2378 + development board was contributed by Rommel Marcelo. + +And extensions to two existing architectures: + + * David Hewson contributed a dual-speed (full/high) USB device-side + driver for the NXP LPC3131 on the Embedded Artists EA3131 + development board. + + * A DMA driver and a high speed MCI driver for the Atmel AT91SAM3U + are included (but not fully tested in this release). + +Two important bugfix was also included: + + * An important fix to the USB mass storage driver was contributed + by David Hewson. + * A serious error in the AT91SAM3U PIO handling was fixed. + +NuttX-5.4 +^^^^^^^^^ + +This is the 51st release of NuttX. This release includes one new, +important extension to th NX graphics system (See +http://www.nuttx.org/NXGraphicsSubsystem.html). + +NX was develop a couple years back on hardware that supported only +framebuffer devices, that is, video hardware with video memory +directly converts the memory content to video. However, most MCUs +that NuttX focuses on do not support such video memory; rather, +that typically only support LCDs via parallel or serial interfaces. + +This release of NuttX extends NX so that now renders directly to +the LCD device via its serial or parallel interface. No in-memory +copy of the screen memory need be maintained so this solution should +also work in MCUs with very limited SRAM. + +This initial release of this feature includes the verified NX +extensions plus a driver for the HX8347, 16-bit parallel LCD. This +LCD supports 16-bit RGB (5:6:5). + +NuttX-5.5 +^^^^^^^^^ + +This is the 52nd release of NuttX. This release includes one new +port, some new drivers and some important bugfixes: + + * NuttX was ported to the Luminary/TI LM3S6965 Ethernet Evaluation + Kit. At present, that port includes an OS test configuration + and a NuttShell (NSH) configuration with Telnet support. + + MMC/SD and Networking support are provided but not thoroughly + verified in this release: Current development efforts are focused + on porting the NuttX window system (NX) to work with the + Evaluation Kits OLED display. + + * A NuttX Ethernet driver for the Microchip ENC28J60 SPI Ethernet + chip is available in the source tree (but has not yet been fully + verified because I haven't properly connected it to hardware + yet). + + * The Olimex STR-P711 NuttX port was extended to support the + ENC28J60 and some new networking configurations were added. + The ENC28J60 has not been tested on the STR-P711, however, + because of hardware issues (I don't think the USB powered board + provides enough power for the ENC28J60 and I don't have the + right wall wart yet). + + Along the way, external interrupt support (XTI) was added to + the STMicro STR-P711 port and some important bugs were fixed + in the STR-P711 SPI driver. + + * Added (optional) floating point support for printf(). + (Contributed by Yolande Cates.) + + * Corrected an important UDP reference counting error. It was + not a serious error, but it trigger an assertion was IS a serious + error. + +NuttX-5.6 +^^^^^^^^^ + +This is the 53rd release of NuttX. This release includes one several +new drivers for existing NuttX ports: + + * This port adds support for the RiT displays P14201 4-bpp, + greyscale OLED. 4-bpp greyscale support was integrated into + the NX graphics sub-system and verified using the TI/Luminary + LP3S6965 Ethernet Evaluation Kit. + + * The M25Px driver was extended for the M24P1 FLASH part (see NOTE). + + * An I2C driver and (basic) SPI driver were added for the NXP + LPC313x port. The I2C interface definition was extended to + efficiently handle multiple I2C transfers. + (Contributed by David Hewson.) + +As well as a few, important USB-related bugfixes (See the ChangeLog +for details). + +This release also includes the beginnings of a port for the NXP +LPC1768 MCU. However, it is too early for that port to be useful +(stay tuned for a future announce of the availability of the LPC1768 +port). + +NuttX-5.7 +^^^^^^^^^ + +This is the 54th release of NuttX. This release adds basic support +for one new ARM Cortex-M3 architecture: + + * Added support for NXP LPC1768 MCU as provided on the Nucleus + 2G board from 2G Engineering (http://www.2g-eng.com). + * Some initial files for the LPC17xx family were released in NuttX + 5.6, but the first functional release for the NXP LPC1768/Nucleus2G + occurred with NuttX 5.7. + * That initial basic release included timer interrupts and a + serial console and was verified using the NuttX OS test. + * That release includes a verified NuttShell (NSH) configuration + (see the http://www.nuttx.org/NuttShell.html). + * Also included are unverified SPI and USB device drivers. + +Further efforts include: + (1) development of a DMA support library + (2) SPI-based MMC/SD support + (3) verification of the USB driver + +Watch for announcement of the completed LPC1768 port expected in +NuttX-5.8. + +NuttX-5.8 +^^^^^^^^^ + +This is the 55th release of NuttX. This includes several important +bugfixes: + + * Corrects some interrupt vectoring for the TI/Stellarix LM3S + port + * Correct initialization logic for NXP LPC17xxx NuttX ports: + Power was not being provided to the GPIO module! + * Corrected (but did not verify) implementation of the optional + interrupt stack feature (all Cortex M3 architectures). + * Correct a HardFault in the LPC17xx SSP driver. + +Additional minor fixes are also included as detailed in the ChangeLog. + +Several new features have been fully developed and included in this +release, but full verification of most of these new features has +been blocked for a variety of issues: + + * Added microSD support for the NuttShell (NSH) configuration in + the Nucleus2G LPC1768 port. For reasons that have not yet been + determined, I have not successfully accessed the microSD card + as of this writing. + * Two USB configurations were also added for the Nucleus2G board: + One to support the USB serial device and one for the USB mass + storage device. Some testing of the USB driver was performed, + but full verification is stalled for an OTG style USB cable. + * LEDs now work correctly on the Nucleus2G LPC1768 board. + * The NuttX/uIP networking subsystem now supports IGMPv2 client. + IGMP (Internet Group Multicast Protocol) network "appliances" + to join into multicast groups. Outbound traffic to enter and + leave multicast groups has been verified, but full verification + will require a switch capable of multicast. Issues associated + with the receipt of multicast packets are likely. + +NuttX-5.9 +^^^^^^^^^ + +This is the 56th release of NuttX. This release is difficult to +categorize; NuttX-5.9 was really released because there were too +many changes accumulating in CVS -- a few important, some unfinished +implementations, and a couple of important bugfixes. + + * By far biggest change in this release is the complete implementation + of on-demand paging support. This feature will allow you to + execute large programs on a mass storage device (such as SPI + FLASH) in a small RAM. All of the core on-demand paging logic + was completed (see http://www.nuttx.org/NuttXDemandPaging.html) + and support was implemented for the ARM-9 family. A test + configuration is in place for the NXP LPC3131. It has been + verified that this new logic does not interfere with normal + fixed-page ARM9 operation, but otherwise this new on-demand + paging feature is untested. + * Add support for the CodeSourcery toolchain to the Olimex-lpc2378 + port and for the Neuros OSD port. + * The Neuros OSD port has been updated to work with the production + v1.0 OSD (previously it only worked with the development board). + * And some miscellaneous feature enhancements as detailed in the + ChangeLog. + +This includes several important bugfixes: + + * NXP LPC17xx - Fixed a critical bug in the GPIO configuration + logic: When attempting to set no pull-up or pull-down (floating), + it would, instead, select pull-down. + + * TI/Luminary LM3Sxxxx - Fixed: + (1) A logic error in an address table lookup. + (2) GPIO port encoding the limited support to only 8 GPIO ports. + + * Corrected the lease time in the DHCPC implementation: It was + not in host byte order. + + * And several other less important bugs as documented in the + ChangeLog: Warnings, cornercase compilation problems, etc. + +NuttX-5.10 +^^^^^^^^^^ + +This is the 57th release of NuttX. This release includes a combination +of some new features as well as several bugfixes. New features +include: + + * TI/Luminary Stellaris LM3S9B96: + Header file changes contributed by Tiago Maluta. + * TI/Luminary Stellaris LM3S8962: + Header file changes and support for the Stellaris LM3S8962 + Ethernet+CAN Evaluation Board contributed by Larry Arnold. + * On-Demand Paging Support: + The basic logic for the On-Demand Paging feature is complete, + implemented for the NXP LPC3131, and partially tested. See + http://www.nuttx.org/NuttXDemandPaging.html. Some additional + test infrastructure will be needed in order to complete the + verification. See configs/ea3131/README.txt for details. + * Two Pass Build Support: + The make system now supports a two pass build where a relocatable, + partially linked object is created on the first pass and that + object is linked with the NuttX libraries to produce the final + executable on the second pass. This two pass build is currently + only used to support the On-Demand paging feature: The first + pass link forces critical logic into the locked text region; + the second pass builds the NuttX executable more-or-less as + normal. + * CONFIG_APP_DIR: + Generalized the way in which applications are built and linked + with NuttX. The new configuration CONFIG_APP_DIR replaces + CONFIG_EXAMPLE. CONFIG_EXAMPLE used to identify the sub-directory + within the NuttX examples/ directory that held the example + application to be built. That made it awkward to configure to + build an application that resides outside of the NuttX examples/ + directory. CONFIG_APP_DIR is more general; it can be used to + refer to any directory containing the application to be built. + + For people who have their own configurations and/or Makefiles, + you will need to make a couple of changes: + + - Replace all occurrences of CONFIG_EXAMPLE=foobar with + CONFIG_APP_DIR=examples/foobar in all of the configuration + files. + - Replace any occurrences of examples/$(CONFIG_EXAMPLE) with + $(CONFIG_APP_DIR) + - Replace any occurrences of lib$(CONFIG_EXAMPLE)$(LIBEXT) + with libapp$(LIBEXT) in your Makefiles. + - Check any other occurrences of CONFIG_EXAMPLE. + + * Several bugfixes are included as well as code changes to eliminate + some warnings. See the ChangeLog for details. + +NuttX-5.11 +^^^^^^^^^^ + +This is the 58th release of NuttX. This is a bugfix release. + + * One very important bug fixes a race condition that can occur + using semaphores that can be awakened by signals. Under this + particular race condition, a task could hang waiting for a + semaphore. + * Corrections to lm3s8962 port contributed by Larry Arnold. That + port is purported to work correctly with these changes in place. + +Plus less critical bugfixes as detailed in the ChangeLog. New features +include: + + * A new configuration to support the mbed.org LPC1768 board. + (Contributed by Dave Marples.) + * A driver for the Atmel AT45DB161D 4Mbit SPI FLASH part + +NuttX-5.12 +^^^^^^^^^^ + +This is the 59th release of NuttX. This is a critical bugfix release. + + * Fixed an important error in the signal trampoline logic. + Essentially, interrupts are re-enabled while the signal handler + executes, but the logic to re-disable the interrupts before + returning from the signal handler trampoline was missing. Under + certain circumstances, this can cause stack corruption. This + was discovered by David Hewson on an ARM9 platform, but since + the code has been leveraged, the bug has been propagated from + ARM to Cortex-M3, AVR32, M16C, SH1, ZNEO, eZ80, Z8, and Z80 -- + almost every architecture. The correction has been incorporated + for all architectures but only verified on a few. + +Other notable changes in NuttX-5.12: + + * A complete port for the AVR32 (AT32UC3B0256) is incorporated + in the source tree. Testing of this port is underway now. This + release was made before verifying this port in order to get the + important bugfix in place. + + * Other miscellaneous bugfix and enhancements as noted in the + ChangeLog. + +NuttX-5.13 +^^^^^^^^^^ + +This is the 60th release of NuttX. Headlines for this release +include: + + * AVR32, www.mcuzone.com AVR32DEV1 + + The port for the www.mcuzone.com AVRDEV1 board based on the + Atmel AT32UC3B0256 MCU was (almost) fully integrated. The port + now successfully passes the NuttX OS test (examples/ostest). + A NuttShell (NSH) configuration is in place (see the NSH User + Guide at http://www.nuttx.org/NuttShell.html). Testing of that + NSH configuration, however, has been postponed (because it got + bumped by the Olimex LPC1766-STK port -- see below) + + Current Status: I think I have a hardware problem with my serial + port setup. There is a good chance that the NSH port is complete + and functional, but I am not yet able to demonstrate that. At + present, I get nothing coming in the serial RXD line (probably + because the pins are configured wrong or I have the MAX232 + connected wrong). + + A complete port will include drivers for additional AVR32 UC3 + devices -- like SPI and USB --- and will be available in a + later release, time permitting. + + * LPC1766, Olimex LPC1766-STK + + Support for the Olimex-LPC1766 is newly added to NuttX and is + still undergoing development, test, and integration. Verified + configurations for the NuttX OS test and for the NuttShell (NSH, + see the NSH User Guide at http://www.nuttx.org/NuttShell.html. + Additional USB configurations are in the release as well, but + they have not yet been verified. Goals for NuttX-5.14 include: + (1) An Ethernet driver, (2) Verified USB support, and (3) SD + card support. + + * Additional changes and bugfixes as detailed in the ChangeLog. + +NuttX-5.14 +^^^^^^^^^^ + +The 61st release of NuttX, NuttX-5.14, was made on November 27, +2010. This release includes multiple, important bugfixes as well +as a new driver for the NXP LPC1766. + +Important bugfixes include: + + * Cortex-M3 Hard Fault. Fixed a hard fault problem that can occur + if certain types of interrupts are pending at the time another + interrupt returns. This problem has only been observed on the + LPC1766 (returning from a SYSTICK interrupt with a pending + Ethernet interrupt). However, it is assumed that all Cortex-M3 + ports could have this as a latent bug. + + * TCP/IP Sequence Number Bug. Corrected errors some important + logic in the way that sequence numbers are managed when send() + sends out packets before a previous packet has been acknowledged. + Some of that send() logic was incompatible with logic in the + uIP layer. Errors seen include: (1) The final final packet in + a sequence of packets might be too large! In the THTTPD example, + this might leave some garbage at the bottom of the display. Or + (2) send() might hang with outstanding, unacknowledged data + (and with no re-transmission requests). This was due to + differences in sequence number handling in send() and in + uip_tcpinput.c; uip_tcpinput.c thought (incorrectly) that all + of the bytes were acknowledged; send.c knew that they were not. + + * One-Shot POSIX Timer Bug. Fixed an error in set-up of a one-shot + POSIX timer. It was using the repetitive timer value (which + is zero in the one-shot case), always resulting in a 10Ms timer! + Found and fixed by Wilton Tong. + +Additional support has been included for the Olimex-LPC1766. Support +for that board was added to NuttX 5.13. This release extends that +support with an Ethernet driver. Verified configurations are now +available for the NuttX OS test, for the NuttShell (NSH, see +http://www.nuttx.org/NuttShell.html), for the NuttX network test, +and for the THTTPD webserver. (Additional USB configurations are +in the release as well, but those have not yet been verified. Goals +for NuttX-5.15 (and beyond) include: (1) Verified USB support, (2) +SD card support, and (3) LCD support. + +NuttX-5.15 +^^^^^^^^^^ + +The 62nd release of NuttX, NuttX-5.15, was made on December 12, +2010. This release includes several bugfixes as well as feature +enhancements, primarily for the Olimex LPC1766-STK board. + +Important bugfixes included: + + * Additional fixes needed with the TCP sequence number problem + "fixed" in NuttX-5.14. + * In the send() logic, now checks if the destination IP address + is in the ARP table before sending the packet; an ARP request + will go out instead. This improves behavior, for example, on + the first on the first GET request from a browser + * All USB class drivers need to call DEV_CONNECT() when they are + ready to be enumerated. That is, (1) initially when bound to + the USB driver, and (2) after a USB reset. + * The SPI_SETBITS macro was calling the SPI setmode method. + * And several other bug fixes of lower importance (see the + ChangeLog for details). + +And feature enhancements: + + * The LPC176x Ethernet driver was using all of AHB SRAM Bank0 for + Ethernet packet buffers (16Kb). An option was added to limit + the amount of SRAM used for packet buffering and to re-use any + extra Bank0 memory for heap. + + * Enabled networking and SD/MMC card support in the Olimex + LPC1766-STK NuttShell (NSH) configuration. + + * The LPC176x USB driver is now fully fully functional. + * Added an optional cmddata() method to the SPI interface. Some + devices require an additional out-of-band bit to specify if the + next word sent to the device is a command or data. The cmddata + method provides selection of command or data. + + * A driver for the Nokia 6100 LCD (with either the Phillips PCF8833 + LCD controller and for the Epson S1D15G10 LCD controller) and + an NX graphics configuration for the Olimex LPC1766-STK have + been added. However, neither the LCD driver nor the NX + configuration have been verified as of the this release. + +NuttX-5.16 +^^^^^^^^^^ + +The 63rd release of NuttX, Version 5.16, was made on January 10, +2010 and is available for download from the SourceForge website. +This release includes initial support for USB host in NuttX. The +USB host infrastructure is new to NuttX. This initial USB host release +is probably only beta quality; it is expected the some bugs remain +in the logic and that the functionality requires extension. + +Below is a summary of the NuttX USB host implementation as extracted +from the NuttX Porting Guide: + + 6.3.9 USB Host-Side Drivers + * include/nuttx/usb/usbhost.h. All structures and APIs needed to + work with USB host-side drivers are provided in this header + file. + * struct usbhost_driver_s. Each USB host controller driver must + implement an instance of struct usbhost_driver_s. This structure + is defined in include/nuttx/usb/usbhost.h. Examples: + arch/arm/src/lpc17xx/lpc17_usbhost.c. + * struct usbhost_class_s. Each USB host class driver must implement + an instance of struct usbhost_class_s. This structure is also + defined in include/nuttx/usb/usbhost.h. Examples: + drivers/usbhost/usbhost_storage.c + * USB Host Class Driver Registry. The NuttX USB host infrastructure + includes a registry. During its initialization, each USB host + class driver must call the interface, usbhost_registerclass() + in order add its interface to the registry. Later, when a USB + device is connected, the USB host controller will look up the + USB host class driver that is needed to support the connected + device in this registry. Examples: drivers/usbhost/usbhost_registry.c, + drivers/usbhost/usbhost_registerclass.c, and + drivers/usbhost/usbhost_findclass.c, + * Detection and Enumeration of Connected Devices. Each USB host + device controller supports two methods that are used to detect + and enumeration newly connected devices (and also detect + disconnected devices): + + int (*wait)(FAR struct usbhost_driver_s *drvr, bool connected); + Wait for a device to be connected or disconnected. + + int (*enumerate)(FAR struct usbhost_driver_s *drvr); + Enumerate the connected device. As part of this enumeration + process, the driver will (1) get the device's configuration + descriptor, (2) extract the class ID info from the configuration + descriptor, (3) call usbhost_findclass() to find the class + that supports this device, (4) call the create() method on + the struct usbhost_registry_s interface to get a class instance, + and finally (5) call the connect() method of the struct + usbhost_class_s interface. After that, the class is in charge + of the sequence of operations. + * Binding USB Host-Side Drivers. USB host-side controller drivers + are not normally directly accessed by user code, but are usually + bound to another, higher level USB host class driver. The class + driver exports the standard NuttX device interface so that the + connected USB device can be accessed just as with other, similar, + on-board devices. For example, the USB host mass storage class + driver (drivers/usbhost/usbhost_storage.c) will register a + standard, NuttX block driver interface (like /dev/sda) that can + be used to mount a file system just as with any other other + block driver instance. In general, the binding sequence is: + + 1. Each USB host class driver includes an initialization entry + point that is called from the application at initialization + time. This driver calls usbhost_registerclass() during this + initialization in order to makes itself available in the + event the the device that it supports is connected. Examples: + The function usbhost_storageinit() in the file + drivers/usbhost/usbhost_storage.c + 2. Each application must include a waiter thread thread that + (1) calls the USB host controller driver's wait() to detect + the connection of a device, and then (2) call the USB host + controller driver's enumerate method to bind the registered + USB host class driver to the USB host controller driver. + Examples: The function nsh_waiter() in the file + configs/nucleus2g/src/up_nsh.c and the function nsh_waiter() + in the file configs/olimex-lpc1766stk/src/up_nsh.c. + 3. As part of its operation during the binding operation, the + USB host class driver will register an instances of a standard + NuttX driver under the /dev directory. To repeat the above + example, the USB host mass storage class driver + (drivers/usbhost/usbhost_storage.c) will register a standard, + NuttX block driver interface (like /dev/sda) that can be + used to mount a file system just as with any other other + block driver instance. Examples: See the call to + register_blockdriver() in the function usbhost_initvolume() + in the file drivers/usbhost/usbhost_storage.c. + +NuttX-5.17 +^^^^^^^^^^ + +The 64th release of NuttX, Version 5.17, was made on January 19, +2011 and is available for download from the SourceForge website. +This release follows close on the heels of the 5.16 release and +extends the USB host capabilities first introduced in that version. + + * The LPC17xx USB host controller driver was extended to (1) add + support for low-speed devices, (2) handle multiple concurrent + transfers on different endpoints (still only one TD per endpoint), + and (3) handle periodic interrupt endpoint types. + + * Add a USB host HID keyboard class driver. Now you can connect + a standard USB keyboard to NuttX and receive keyboard input for + an application. + +And other changes as detailed in the ChangeLog. + +NuttX-5.18 +^^^^^^^^^^ + +The 65th release of NuttX, Version 5.18, was made on February 27, +2011 and is available for download from the SourceForge website. +This is first release from the new NuttX SVN repository. This +release is made primarily to keep the release tarball in synchronization +with SVN. Many smaller changes have been made as identified in the +ChangeLog. Headlines include: + + * Incorporate several important uIP patches -- including the well + known patch to handle missing SYNACK. + * The Freescale mc8s12ne64 port is code complete but testing has + not yet begun due to toolchain issues. Added support for the + Future Electronics Group NE64 Badge board. + * Added support for a new STM32 board, the ISOTEL NetClamps VSN + V1.2 ready2go sensor network platform. This board is based on + a STM32F103RET6 and includes some interesting power saving/clock + control extensions. + * USB host support expanded to handle vendor specific USB devices. + * Incorporated the LUFA HID parser. + * Various bugfix as detailed in the ChangeLog + +NuttX-5.19 +^^^^^^^^^^ + +The 66th release of NuttX, Version 5.19, was made on March 12, 2011 +and is available for download from the SourceForge website. This +release includes several new features in various states of integration +and maturity: + + * 486SX QEMU port. This port supports the Intel 486SX architecture + using the QEMU simulator. Initial functionality is in place a + partially tested. There are still some outstanding issues with + timer interrupts. + * Platform specific application support. A new apps/ directory + appears in this port. This apps/ directory provides a mechanism + for applications using NuttX to have a highly customized + initialization process. It supports a set of end-user applications + than can be executed (1) standalone so you can have a fully + customized application startup, or (2) on top of NSH. Think + of it this way: In a buckled-up embedded application, your + end-user programs will probably have their own dedicated start-up + logic. But, during development, you might want to have you + applications available and executable from the NSH command line. + This apps/ add-on (and NSH hooks) was contributed by Uros to + accomplish just that. + * NSH was also extended to support application specific ROMFS + /etc/init.d/rcS start-up scripts. This feature, as well, as + all of the above-mentioned apps/ directory support was contributed + by Uros Platise + * Additional NSH improvements and bug fixes. See the Changelog + for details. + * This release also provides a new SLIP network driver. This + driver should support point-to-point network communications to + a host using TCP/IP or UDP. This driver is code complete, but + not tested in this release. + * New RAMTRON FRAM driver (contributed by Uros Platise) + * New generic 16550 UART driver. + * Cortex-M3 Power improvements: Waits for Interrupt (WFI) in idle + loop for reduced power consumption (LPC17xx and STM32 only - + contributed by Uros Platise)) + * New waitpid() system interface. + * Additional bugfixes: pipes, stdint.h, STM32 SDIO and SPI drivers + +NuttX-6.0 +^^^^^^^^^ + +The 67th release of NuttX, Version 6.0, was made on March 21, 2011 +and is available for download from the SourceForge website. The +version number of this release was bumped from 5.19 to 6.0. A +change in the major revision number is used to reflect an incompatibility +with previous versions. In this release, the NuttX core OS +functionality has been separated from NuttX application-related +functionality. These are provided as separate tarballs: + + * nuttx-6.0.tar.gz, and + * apps-6.0.tar.gz + +The purpose of this separation is both to better organize and +modularize the NuttX source tree, but also to provide better support +for incorporation of end-user applications with Nuttx. + +The incompatibility results from the changes to the board configuration +logic needed to supported the separable application. The major +changes to the configuration include: + + * CONFIG_APPS_DIR - This should not be set. The default is + ../apps. This should only be set if you have a custom, + product-specific application directory in some different location. + + * appconfig - Each board configuration now requires a new file + called 'appconfig.' As its name suggests, this file provides + new configuration information needed by the logic in ../apps. + +In addition to this major reorganization in the directory structure, +this release also includes some important extensions to existing +features and some important bugfixes. These include: + + * The SLIP driver was been well debugged and significantly + re-designed. Now you can have an Ethernet connection to you + board even if you have no Ethernet hardware. How cool is that? + + * The QEMU i486 port is now functional. It has also been reported + to work on the Bifferboard (see http://bifferos.bizhat.com/). + + * And extensions to the uIP driver interface, and + + * Bug fixes to fopen() and STM32 GPIO configuration + +Please see the ChangeLog for details. + +NuttX-6.1 +^^^^^^^^^ + +The 68th release of NuttX, Version 6.1, was made on April 10, 2011 +and is available for download from the SourceForge website. The +6.0 release introduced a detach-able application environment to +build applications outside of the NuttX source tree. The primary +purpose of this release is to correct numerous build problems +introduced by that architectural change: + + * In many newer environments, NuttX produced strange Makefile + errors but built correctly in older environments. A fix provided + by Rafael Noronha was incorporated and is reported to fix those + build problems. + * The apps/ directory build system would not handle Windows-native + toolchains due to obscure path formatting issues. + * And other problems as detailed in the Changelog. + +Many additional changes were made in the 6.1 release for another +major architectural change: NuttX will now build as a separately +linked microkernel. In this build option the RTOS builds as a +kernel, applications build separately and interface with kernel via +system calls. Applications run in user mode and kernel logic users +in kernel-mode. This provides a secure environment for NuttX. This +feature is fully coded in NuttX-6.1, but has not been tested due +to higher priority tasks that have arisen. + +Related to this change, support for the Cortex-M3 memory protection +unit (MPU) has been integrated with the NuttX kernel build to provide +an even higher level of security. + +NOTE: This kernel build is an option; the default build configuration +is still the standard, flat, unsecured RTOS as in previous releases. + +Additional new features in this release: + + * Support for LPC17xx GPIO interrupts (with much support from + Decio Renno). + * Basic timer support for STM32 (Contributed by Uros Platise) + * A binfs file system. This is a tiny pseudo file system that + lets named applications to be viewed and accessed in NSH under + the /bin directory. + * An I2C-based driver for the LIS331DL MEMS motion sensor. + (Contributed by Uros Platise.) + * A configuration for the Embedded Artists LPCXpresso LPC1768 board. + * The user_initialize() interface has been removed. + +And several bugfix associated with SD drivers, opendir(), signed +8-bit types (int8_t), and USB serial device. See the ChangeLog for +details. + +NuttX-6.2 +^^^^^^^^^ + +The 69th release of NuttX, Version 6.2, was made on May 6, 2011 and +is available for download from the SourceForge website. The 6.2 +release includes several new features: + + * NXFFS: The obvious new feature is NXFFS, the NuttX wear-leveling + FLASH file system. This new file system is intended to be + small for the MCU usage and has some limitations. No formal + documentation of NXFFS yet exists. See the fs/nxffs/README.txt + file for details (see + http://nuttx.svn.sourceforge.net/viewvc/nuttx/trunk/nuttx/fs/nxffs/README.txt?view=log) + * Support for NXP LPCXpresso LPC1768 board on the Embedded + Artists base board. The Code Red toolchain is supported under + either Linux or Windows. Verified configurations include + dhcpd, nsh, nx, ostest, thttpd, and usbstorage. + * Support for the Univision UG-9664HSWAG01 OLED with Solomon + Systech SD1305 LCD controller. + * A new RAM MTD driver with FLASH simulation capability. + * A version.h file is now automatically generated so that C code + can now be version aware. + +In addition to these new feature, several important bugfixes are +included in this release correcting problems with dup2(), LPC17xx +GPIO interrupts, LPC17xx UART2/3, the FAT file system, build issues, +and strrch(). See the ChangeLog for more details. + +NuttX-6.3 +^^^^^^^^^ + +The 70th release of NuttX follows only a nines days after the release +of version 6.2. It was released on May 15, 2011. This special +back-to-back release was made so that the current released version +of NuttX will correspond to the initial release from the RGMP +project. + +This release adds architecture support and build configuration for +RGMP. RGMP is a project for running GPOS and RTOS simultaneously +on multi-processor platforms. See +http://rgmp.sourceforge.net/wiki/index.php/Main_Page for further +information about RGMP. + +This release also includes support for STM32 FLASH, build improvements, +and initial, incomplete support for the MicroChip PIC32MX MCU. Bug +fixes are included for some build problems, USB host class driver +error handling, NX graphics color mapping, and problems with C +standard I/O buffer flushing. See the ChangeLog for further details. + +NuttX-6.4 +^^^^^^^^^ + +The 71st release of NuttX, Version 6.4, was made on June 6, 2011 +and is available for download from the SourceForge website. The +6.4 release includes several new features: + + * A new, full-featured FTP client. This client may be used as a library + for automated FTP or via an FTP client shell. The FTP shell + supports the following commands: cd, chmod, get, help, idle, + login, ls, quit, mkdir, noop, put, pwd, rename, rhelp, rm, + rmdir, size, time, and up. A configuration is available for + the NXP LPC17xx to demonstrate this functionality. + * A functional C1101 wireless driver (contributed by Uros Platise) + * A PCI-based E1000 Ethernet driver (contributed by Yu Qiang) + * New C library functions: inet_addr() (contributed by Yu Qiang), + strndup(), asprintf() + * Reduced memory allocation overhead for MCUs with small heaps (<64Kb). + * fdopen() now works with socket descriptors allowing standard + buffered C functions to be used for network communications. + * The NSH ifconfig command can now be used to set or change the + IP address (contributed by Yu Qiang) + +This release also includes some completed but untested functionality. + + * The MicroChip PIC32MX port is now code complete and ready to + begin testing. Unfortunately, testing will be delayed due to + tool issues. + * Support for the NXP LPC315x MCUs. + +Additional miscellaneous enhancements and bug fixes to task_delete(), +recvfrom(), and other changes as noted in the ChangeLog. + +NuttX-6.5 +^^^^^^^^^ + +The 72nd release of NuttX, Version 6.5, was made on June 21, 2011 +and is available for download from the SourceForge website. The +6.5 release is all about support for the Atmel 8-bit AVR family. +I have been interested in the AVR family for some time but because +of the severe SRAM constraints and because of the availability of +many tiny schedulers for the AVR, it has not been "on the radar +screen." However, I have recently become interested because of +interest expressed by members of the forum and because of the +availability of newer, larger capacity AVR parts (that I don't have +yet). + +This release includes support for the following AVR boards. As +with any initial support for new architectures, there are some +incomplete areas and a few caveats that need to be stated. Here +they are, ordered from the least to the most complete: + + * SoC Robotics Amber Web Server (ATMega128). + + This port of NuttX to the Amber Web Server from SoC Robotics + (http://www.soc-robotics.com/index.htm). Is only partially in + place. The Amber Web Server is based on an Atmel ATMega128 + (128Kb FLASH but only 4Kb of SRAM). + + STATUS: Work on this port has stalled due to toolchain issues. It + is complete, but untested. + + * Micropendous 3 AT9USB647 + + This port of NuttX to the Opendous Micropendous 3 board. The + Micropendous3 may be populated with an AT90USB646, 647, 1286, + or 1287. See http://code.google.com/p/opendous/. I have only + the AT90USB647 version for testing. This version has very + limited memory resources: 64Kb of FLASH and 4Kb of SRAM. + + STATUS: The basic port was released in NuttX-6.5. This basic + port consists only of a "Hello, World!!" example that demonstrates + initialization of the OS, creation of a simple task, and serial + console output. The tiny SRAM limits what you can do with the + AT90USB647 (see issues below). + + * PJRC Teensy++ 2.0 AT9USB1286 + + This is a port of NuttX to the PJRC Teensy++ 2.0 board. This + board was developed by PJRC (http://pjrc.com/teensy/). The + Teensy++ 2.0 is based on an Atmel AT90USB1286 MCU with 128Kb + of FLASH and 8Kb of SRAM; a little more room to move than the + AT90USB647. + + STATUS: The basic port was released in NuttX-6.5. This basic + port consists of a "Hello, World!!" example and also slightly + simplified NuttShell (NSH) configuration (see the NSH User Guide + at http://www.nuttx.org/NuttShell.html). + + An SPI driver and a USB device driver exist for the AT90USB as + well as a USB mass storage configuration. However, this + configuration is not fully debugged as of the NuttX-6.5 release. + +AVR-specific issues. The basic AVR port is solid and biggest issue +for using AVR is its tiny SRAM memory and its Harvard architecture. +Because of the Harvard architecture, constant data that resides to +flash is inaccessible using "normal" memory reads and writes (only +SRAM data can be accessed "normally"). Special AVR instructions +are available for accessing data in FLASH, but these have not been +integrated into the normal, general purpose OS. + +Most NuttX test applications are console-oriented with lots of +strings used for printf and debug output. These strings are all +stored in SRAM now due to these data accessing issues and even the +smallest console-oriented applications can quickly fill a 4-8Kb +memory. So, in order for the AVR port to be useful, one of two +things would need to be done: + +1. Don't use console applications that required lots of strings. + The basic AVR port is solid and your typical deeply embedded + application should work fine. + +2. Create a special version of printf that knows how to access + strings that reside in FLASH (or EEPROM). + +NuttX-6.6 +^^^^^^^^^ + +The 73rd release of NuttX, Version 6.6, was made on July 11, 2011 +and is available for download from the SourceForge website. The +6.6 release adds several smaller features but is mostly a bugfix +release. + +Bugfixes include + + * Fixed several NX Graphics bugs: Rendering fonts at >8 bits-per-pixel, + graphics move logic, and display artifacts that appear when a + window is closed. + * Corrections to the USB host mass storage class driver + * STM32 bugfixes: serial driver, GPIO interrupt handling + * LPC17xx: Changes for a success compilation with no console. + * Corrections to the Teensy AT90USB SD driver + * Changes for a clean compilation under the ZDS-II toolchain. + +Minor features: + + * Add logic to extract printf strings from FLASH (but there are + still printf issues for that target) + * Added a configuration for the Sure Electronics PIC32MX board. + However, higher priority tasks have stopped work on that + configuration. + * Added several new configurations for the STMicro STM3210E-EVAL + board. + * Added support for the STM3210E-EVAL board: (1) LCD in either + landscape or portrait mode, and (2) interrupting buttons. + * Added a configuration option to use different serial ports for + debug and for the NSH serial console (there are some issues + with CR-LF expansion and character echo if NSH is not run on + the console). + * Standardized the button press and button interrupt interfaces + so that they are common across all boards. + * Added a new graphics example that focuses on placing text on + the background while pop-up windows occur. Text should continue + to update normally with or without the popup windows present. + * Added ARM stack checking logic. + +See the ChangeLog for a detailed description of these changes. + +NuttX-6.7 +^^^^^^^^^ + +The 74th release of NuttX, Version 6.7, was made on August 2, 2011 +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.7.tar.gz and +apps-6.7.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). Changes in this release are summarized +below: + + * New OS APIs: Add the standard sem_timedwait() interface. + * FAT File System: Adds (optional) support for VFAT long file + names. + * USB: Now the mass storage device can be connected when needed + and disconnected when not needed (or re-connected as a different + kind of device). + * Touchscreen Support: Defined a new NuttX touchscreen interface. + Added a driver for the TI TSC2007 touchscreen controller chip. + * NX Fonts: Add support for multiple fonts; developed a tool to + convert open source fonts into NuttX format; Converted and + installed nine new, high quality fontsets. + * NX Graphics: Add new NX APIs to support drawing of wide lines + in any orientation. Added new low level routines to set + individual pixel more efficiently. + * Build system: Added a export target that will bundle up all + of the NuttX libraries, header files, and the startup object + into an exportable tarball. + * LPC17xx: A CAN driver was contributed by Li Zhuoyi (Lzyy). + * STM32: New NX-related configurations to exercise text and + graphic image displays. + * C Library: Added a fixed precision atan2() math function. + * Bugfixes: Serial RX overrun error, FAT upper/lower NT 8.3 name + handling fixed. FAT directory allocation and initialization + bug. STM32 SDIO DMA race condition bug. eZ80 UART1 serial + driver errors (Paul Osmialowski) + +NuttX-6.8 +^^^^^^^^^ + +The 75th release of NuttX, Version 6.8, was made on August 19, 2011 +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.8.tar.gz and +apps-6.8.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). Changes in this release are summarized +below: + + * NuttX has been ported to run on the Freescale Cortex-M4 "Kinetis" + boards. Two board ports are available for (1) the Kinetis + KwikStik-K40 and (2) the Kinetis TWR-K60N512 tower. + * Support for RGMP 0.3. This version of RGMP now runs on the + OMAP4430 (arm) pandaboard + * LPC17xx CAN driver extended to support both CAN1 and CAN2 + (submitted by Li Zhuoy (Lzzy)) + * Fixed several critical bugs related to signal handling + initialization and for signals the wake up tasks that are waiting + to send or receive message queues.Both are important. (submitted + by hkwilton). + * drivers/can.c: Fixed a semaphore overflow problem in the CAN + driver (reported by Li Zhouy (Lzzy)). + * Added a new ADC driver infrastructure and TI ADS1255 driver + both developed and submitted by Li Zhouy (Lzzy)). + +See the Changelog for additional changes included in this release. + +NuttX-6.9 +^^^^^^^^^ + +The 76th release of NuttX, Version 6.9, was made on September 11, 2011 +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.9.tar.gz and +apps-6.9.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). + +This release includes a few new features and several important bug fixes. +The new features (some still incomplete) include: + + * Analog Support/ NXP LPC17xx: New DAC sub-system including ADC and DAC + drivers for the LPC17xx. Extensions to the ADS1255 driver. + (Contributed by Li Zhuoyi (Lzyy)) + + * Power Management: Added a new NuttX power management sub-system for + controlling and coordinating reduced power states. At present, only + verified in a simulation environment. + + * I2C Test Tool: A new application was added that can be used to + verify and debug I2C interfaces from the NuttShell (NSH) command + line. + + * NuttShell (NSH): In addition to the I2C test tool, a date command + is now supported (if CONFIG_RTC is defined) that can be used to + read and set the RTC. + + * NXP LPC17xx: I2C and DAC driver for the NXP LPC17xx family submitted by Li Zhuoyi + (Lzyy) + + * Kinetis Cortex-M4: Added a SDHC driver for the Kinetis parts. + Complete debug of the Kinetis SDHC driver was not completed, however, + do to some higher priority tasks that forced me to stop work. + + * Other new drivers: Driver for I2C-based at24cxx EEPROM submitted by + Li Zhuoyi (Lzyy); Driver for the LM-75 temperature sensor. Support + for the LM-75 temperature sensor integrated into the SM3210E-EVAL + development board. + + * NuttX Graphics (NX): Added new NX interfaces for drawing circles, + both circle outlines and filled circles. + + * FLASH: Added a function that accepts the path to a block driver and + then erases the underlying FLASH memory + + * Build System: The Make export logic now also tries to track down all + architecture-specific header files and include these in the NuttX + export bundle as well. Various changes and modifications so that + NuttX wil build on FreeBSD using the ASH shell (submitted by Kurt Lidl). + +Bugfixes, order roughly on decreasing criticality include: + + * STM32 I2C Driver: Add resets, timeout, and other fixes to work + reliably with the I2C tool. Corrected a major error introduced in + NuttX 6.8. + + * BCH Driver. Several important bugs (noted by Li Zhuoyi (Lzyy)) + were fixed. + + * C Library: Fixed errors in gmtime() and gmtime_r() that could lead to + errors in date calculations. + + * Timing: Correct an error in the tv_nsec calculation that happens + only config CONFIG_RTC is enabled + + * Build System: Use of -print-libgcc-file-name to get path to + libgcc.a might select the wrong libgcc.a if a multilib toolchain + is used + +NuttX-6.10 +^^^^^^^^^^ + +The 77th release of NuttX, Version 6.10, was made on October 6, 2011 +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.10.tar.gz and +apps-6.10.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). + +This release corresponds with SVN release number: r4028 + +This release includes a few new features and several important bug fixes. +The new features (some still incomplete) include: + + * CDC ACM serial class device-side driver + + * RTC: Now supports hi-res and lo-res hardware RTC. The lo-res RTC + runs at 1Hz. + + * STM32 I2C driver. Now supports faster, polled mode of operation. + Added an I2C trace capability. + + * ADS7843E touchscreen driver. As used on the SAM3U-EK development + board. + + * AT91SAM3U SPI driver. To support the ADS7843E toucscreen + + * X11 Support on simulation target. Build errors in the X11 windows + for the simulated target have been correct. Added support for a + simulated touchscreen on the X11 window (based on mouse inputs). + + * System Timer. Added support for a 64-bit system timer. + + * TIFF Support. Added a TIFF library (currently used for storing + LCD screen shots). + + * LCD Support. Added a test to verify that we read and write correct + to LCD GRAM memory. + + * I2C tool. Extended to support to include a verify command and + repititions and auto-address increment for most commands. + + * USB terminal example. Line oriented serial bridge connects a host + USB serial terminal to a host UART serial terminal. + + * Build System. apps/ Makefile will now include external directories + in the application build. + +Bugfixes, order roughly on decreasing criticality include: + + * Message Queues. Correct errors in mq_timedsend() and + mq_timedrecieve(). + + * FAT. Writes that cross sector boundaries, stray write into the FAT, + and a FAT long file name issue + + * NXFFS. Added a missed error check. Files cannot be opened for + writing if they are already opened for reading. + + * Library: fopen() for append modse was not appending. + + * STM32 I2C driver. Correct another conflict between concurrent FSMC + and I2C1 accesses. Fixed some bad error detection logic. + + * STM32 SDHC driver. Interrupts were being left disabled. + +NuttX-6.11 +^^^^^^^^^^ + +The 78th release of NuttX, Version 6.11, was made on November 12, 2011 +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.11.tar.gz and +apps-6.11.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). + +This release corresponds with SVN release number: r4090 + +This release is a maintenance release that includes a few new features +and some important bugfixes. New features include: + + * NX Graphics: New interfaces to read from graphics memory + * Drivers: AT24 FLASH driver will now supports clustering of blocks + to achieve a larger, more usable block size for NXFFS. + * STM32: LCD color corrections + * PIC32: Board configuration for the Microchip PIC32 Ethernet Starter kit + (not yet verified), new GPIO support library, button and LED support + for the Sure Electronics PIC32MX board. A lot of progress has been + made on the PIC32 NuttX port, but it is still not ready for prime time. + * NXP LPC3152: Board configuration for the Embedded Artists EA3152. + +Bugfixes, order roughly on decreasing criticality include: + + * NXFFS: Corrected critical bugs in initialization, some full FLASH handling, + and errors in certain cases where the FLASH is repacked. + * ARM EABI: Fix stack aligment required for passing floating point values. + * Build system: Fix build issues when g++ is used as the compiler. + * NX Graphics: Bitmap error handling, correct RGB color conversion macros, + Error when the background window is released. + * STM32: RTC build fixes, LCD color corrections + * Simulation target: build fixes + * C Library: fclose() return value. + +See the change log for more detailed information. + +NuttX-6.12 +^^^^^^^^^^ + +The 79th release of NuttX, Version 6.12, was made on December 6, 2011 +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.12.tar.gz and +apps-6.12.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). + +This release corresponds with SVN release number: r4141 + +New features in this release include: + + * STM32. Basic support added for the STM32 F4 family. Board support + verified for the STMicro STM3250G-EVAL board. + * FAT. Enhanced partition handling. + * SDIO-Based SD Card support. Add support for large (>4Gb) devices + * Graphics. Added four new small sans serif fonts. + * Drivers. Fix a banding problem with the R61580 LCD. + +Bugfixes, order roughly on decreasing criticality include: + + * FAT. Fix errors in how the first entries in the root directory are + added. Fix errors in FAT date/time handling. + * Signals. Fix bug in certain sig_timedwait() error handling. + * Drivers. Fix cloned errors in poll() handling in several drivers. + * Message Queues. errno was not being set correctly by mq_notify(). + * C Library. wchar_t is a built-in type for C++ + +NuttX-6.13 +^^^^^^^^^^ + +The 80th release of NuttX, Version 6.13, was made on December 26, 2011 +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.13.tar.gz and +apps-6.13.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). + +This release corresponds with SVN release number: r4231 + +New features in this release include: + + * Drivers. New standard interface for PWM drivers and common + "upper half" PWM driver. Updated the MP25x driver to support + the Macronix MX25 chips (submitted by Mohammad Elwakeel). + * STM32 F1/F4. Added an Ethernet driver, ADC drivers, DAC driver, + PWM driver, CAN driver, F4 RTC driver, F4 DMA support, + logic for saving/restoring F4 FPU registers in context switches. + * STM32 Boards. Added STM3240G-EVAL DHPCD and nettest configuration. + Support for a new STM32 board, the HY-Mini STM32v board, was + contributed by Laurent Latil + * PIC32. The port to the Microchip PIC32MX is finally functional and + reliable. The NuttX PIC32 port has verified configurations for + the OS test and the NuttShell (NSH) both exist. + * Tests: New re-usable tests (in apps/examples) for PWM, ADC, and + CAN loopback. Several existing tests can now be built as NSH built-in + applicaitons (dhcpd, nettest, and all of the new tests). + +Bugfixes, order roughly on decreasing criticality include: + + * STM32: Correct handling of data overrun conditions. Existing logic + would hang with infinite interrupts when a data overrun occurred. + * DHCPD. Fix several problems using host order address where network + addresses expected (and vice versa). + +And several others. See the ChangeLog for more details. + +NuttX-6.14 +^^^^^^^^^^ + +The 81st release of NuttX, Version 6.14, was made on January 15, 2012, +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.14.tar.gz and +apps-6.14.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). + +This release corresponds with SVN release number: r4301 + +New features in this release include: + + * Drivers. The upper-half PWM driver will now support a pulse count (as + would be needed to control a stepper motor). + + * STM32. The CAN driver has been verified in loopback mode. ADC driver + support for the STM32 F4. Add support for UART4-5 and USART6 + (Contributed by Mike Smith). The PWM driver now supports a pulse + count for TIM1 and TIM8. Timer driver now supports the F4's 32-bit + timers (Contributed by Mikhail Bychek) + + * STM32F4Discovery. Support for the STM32F4-Discovery board contributed + by Mike Smith. + + * STM3240G-EVAL. Add support for user control of LEDs. + + * LPC17xx. Add support for loopback mode to CAN driver. CAN TX done + perations are now interrupt driver. Now supports configurable CAN bit + rate. + + * LPC1766-STK. Add support for on-board buttons. Add support for user + control of LEDs. + + * LM3S. Add support for the LM3S6432S2E on the TI RDK-S2E (Contributed + by Mike Smith) + + * PIC32MX. USB device-side driver (needs further testing). A partial + Ethernet driver is also in place. + + * Library. Support added for fixed floating point fieldwidths in output + formatting (Contributed by Mikhail Bychek) + + * Build. New targets apps_clean and apps_distclean to simplify working + with application diretories. + +Bugfixes include: + + * Drivers. Fixed a buffer-full test in the upper-half CAN driver. + + * STM32. GPIO initialize logic (submitted by Mike Smith). Fix the + debug logic that dumps the GPIO configuration. + + * LPC17xxx. Correct an integeter overlow in GPIO interrupt setup + (prevented pins > 15 from being used as interrupt sources). Correct + a value used in GPIO interrupt number range test. + + * FAT. Now returns the correct error value when it is unable to + recognize the file system. + + * Build. MAC OS build fixes (submitted by Mike Smith) + +And several others. See the ChangeLog for more details. + +NuttX-6.15 +^^^^^^^^^^ + +The 82nd release of NuttX, Version 6.15, was made on February 12, 2012, +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.15.tar.gz and +apps-6.15.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). + +This release corresponds with SVN release number: r4387 + +New features and extended functionality: + + * General Drivers: Add support for (29-bit) extended CAN IDs. Add an + infrastructure to support battery drivers. Add a driver for MAX17040x + battery "fuel gauge". Add support for Composite USB drivers (in + particular for a CDC/ACM with MSC USB composite driver). + + Added a new RAM logging driver. This will allow debug output into + a RAM buffer associated with a character driver at /dev/syslog. + Added the new command 'dmesg' to NSH that can be used to dump the + current contents of the log. This is useful for systems that do not + have the usual serial console (for example, if you only have a + Telnet console with NSH). + + * Networking: Add a lower level, primitive socket interface. Telnet + driver: + + A New Telnet daemon was created. It wraps a Telnet session within a + character driver that can serve as a "controlling terminal." The + Telnet session will then be inherited by tasks created from the + Telnet session and the stdin/stdout from the created task will + still go through the same Telnet connection. + + * STM32 Drivers. PWM driver pulse count was limited to 128; now is + (essentially) unlimited. Add support for (29-bit) extended CAN IDs. + Add support for I2C3. The SDIO driver is (mostly) verified on the + STM32 F4 platforms. + + * LPC17xx Drivers. Extended the CAN driver so that the TSEG1 and TSEG2 + bit times can be set via the NuttX configuration. Add support for + (29-bit) extended CAN IDs. + + * PIC32 Drivers. The PIC32 Ethernet driver is code complete (but still + untested). + + * FTPD. Add a new FTP server daemon. This is based loosely on + the hwport_ftpd library provided by Jaehyuk Cho. + + * Library: Add support for on_exit(). Implemented tcsetattr() and + tcgetattr(). Moved the old, too-smart fgets() to a new application + library function called readline(). Dumbed down the original fgets(). + Add strcasestr(), avsprintf(), inet_ntop(), and inet_pton(). + Add support to enable or disable debug output. + + * Build system: Support for building a 32-bit simulation executable on + a 64-bit Linux machine. Correct a dependency issue in the arch/*/src/board + directory. + +Bugfixes: + + * System: Correct PTHREAD_MUTEX_INITIALIZER + + * FAT: Fix an error in the FAT statfs() reported by David Sidrane. + + * STM32: Fix clock frequencies for APB2 timers. Correct AFIO register + offset. + + * PIC32. Correct GPIOs used for LEDs on the Sure PIC32MX board. + + * NSH. Wait for a USB connection if a USB serial class is used to + interface with the host. + +Additional bugfixes, name changes, and other differences as detailed in the +ChangeLog. + +NuttX-6.16 +^^^^^^^^^^ + +The 83rd release of NuttX, Version 6.16, was made on March 10, 2012, +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.16.tar.gz and +apps-6.16.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). + +This release corresponds with SVN release number: r4475 + +New features and extended functionality: + + * ARMv7M Support: Includes new, streamlined Cortex-M exception + handling provided by Mike Smith. Context switching support for the + Cortex-M4 FPU registers is now provided (in both "lazy" and "non-lazy" + modes) + + * General Drivers: Added a generic "upper half" Quadrature Encoder driver. + The USB CDC/ACM serial driver can now be dynamically connnected or + disconnected from the host (programmatically or using NSH commands). + + * STM32 Drivers: Added a "lower half" Quadrature Encoder driver. + Verified the STM32 F4 DMA driver; Added F4 DMA support to the existing + STM32 SDIO driver. + + * STM32 Board Support. Added support for the STM32 F2 family and + for the STM3220G-EVAL board (contributed by Gary Teravskis). + Support is now included for C++ static constructors (verified using + the Atollic toolchain). Added support for the SRAM available on the + STM3240G-EVAL board. + + * PIC32 Drivers. PIC32MX USB (device) driver is now functional. + The PIC32MX Ethernet driver not yet fully verified (and an + unverified SPI driver is also available). + + * Networking. Added a lower-level, thread-independent socket layer. + Parts of this layer were created in 6.15 to support the FTPD + controlling terminal; this support has been extended in order + to support an NFS file system (not yet released). + + * NuttShell (NSH). NSH will now support a USB serial connection for + the console (such as CDC/ACM). This is useful in environments + where there is no physical serial port on the board. + + * Build System. Reorgnaization of networking header files. + +Critical Bugfixes. The following bug fixes are considered critical: + + * Networking: Fixed a "leak" in the TCP/IP read-ahead buffering logic. + Corrected an error in TCP/IP sequence numbering/ACK logic which + occurred when read-ahead buffering memory is exhausted. + + * STM32 Drivers: Fixed an buffer sizing error in the STM32 Ethernet + driver. + +Additional Bugfixes: Other important bug fixes are listed below. See +the ChangeLog of a complete, detailed list of bug fixes. + + * Networking: Corrected recv()/recvfrom() return value. Added logic to + monitor for loss of connection after a new connection has been + established via accept() (Contributed by Max Nekludov). Add + logic to select() to correctly handle POLLHUP (Contributed by Max + Nekludov) + +Additional bugfixes, name changes, and other differences as detailed in the +ChangeLog. + +NuttX-6.17 +^^^^^^^^^^ + +The 84th release of NuttX, Version 6.17, was made on April 14, 2012, +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.17.tar.gz and +apps-6.17.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). + +This release corresponds with SVN release number: r4607 + +New features and extended functionality: + + * Networking: Additional low-level, thread-independent socket + interfaces (for NFS client support). + + * RTC: Added a new interface call clock_synchronize(). This function + will reload the system time from an RTC and is required when the + system re-awakens from certain deep-sleep modes. + + * Graphics: Add NxConsole. This is a character device driver that + wraps an NX window and can be re-directed for stdout. This allows, + for example, a pop-up graphics window that contains a NuttShell (NSH) + session. A test of NxConsole is available at apps/examples/nxconsole. + + * Watchdog Drivers: Added an interface definition an "upper half" + driver to support watchdog timers. + + * Calypso: Support for TI Calypso-based cellphones (as supported by + the Osmocom-BB project) was contributed by members of the Osmocom-BB + team. This includes configurations for the Compal e88 and e99 phones. + + * USB Device Interface: Needed to extend the USB device interface + because there was no mechanism for passing endpoint OUT data that + may need to accompany a setup request. + + * STM32 drivers: Added some power management controls for entering + reduced power consumption states. An OTG FS driver was completed + and partially verified (this driver seems to be functional but since + it has been test so lightly, it might better be listed in the + next section "Work in progress"). + + * PIC32 drivers: The PIC32 Ethernet driver is now stable. The PIC32 + USB device controller driver is now functional (but not yet stable). + + * PIC32 boards: Added support for the Sure DB-DP11212 PIC32 General + Purpose Demo Board. There is now a PIC32 Starter Kit that + provides NSH only through a Telnet connection. + + * Build System: Some header files were moved into include/nuttx. + The goal is to move any non-standard header files to include/nuttx + or include/arch. Moved include/math.h to include/nuttx/math.h; + this file is now only instantiated as the 'system' math.h if + CONFIG_ARCH_MATH_H=y is defined. + + * Tools: Added tools/cmpconfig.c, a tool for comparing two + configuration files. + +Work in progress. This release includes some partially completed +work that is still not ready for prime time. + + * NFS Client: Work is progressing on support for an NFS client + file system. This is a port of the BSD NFS client file system + that is being done by Jose Pablo Rojas V. + + * Automated Configuration: Automated configuration based on the + kconfig-frontends tool is being incorporated into the build + system. The configuration is still not complete enough for + general use in this release. + + * STM32 Drivers: Added files that will (eventually) hold an STM32 + OTG FS host driver. This is still a work in progress. + +Bugfixes: + + * Networking: Corrected a deadlock that only occurred when + executing the NSH 'ifconfig' command over Telnet. + + * File system: Fix incorrect return errno value from read() when + the file is opened write-only. + + * Graphics: Fix several compilation errors that have crept into the + multi-user NX server because of lack of use. + + * STM32: In order to use CAN2, both CAN1 and CAN2 clocking must be + enabled. Fixed a troublesome bug in the STM32 F4 I2C driver that + resulting in timeouts. + + * LPC17xx: Fixes for errors the crept in the LPC17xx DAC logic + Contributed by Lzyy). + + * Build System: Reordered the link command line to account for new + versions of libgcc.a that require symbols from the application + (abort()). + +NuttX-6.18 +^^^^^^^^^^ + +The 85th release of NuttX, Version 6.18, was made on May 19, 2012, +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.18.tar.gz and +apps-6.18.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). + +The majority of changes in this release are focused on supporting the +synchronized release of NxWM, the NuttX tiny window manager. That +window manager is released as part of the NxWidgets package, but depends +upon many of the changes in this NuttX release. + +This release corresponds with SVN release number: r4751 + +New features and extended functionality: + + * Drivers. Added a watchdog timer driver infrastructure. Add general + support for STMicro STMPE811 I/O Expander/touchscreen device. + + * STM32. Add support for the STM32 IWDG and WWDG watchodog timers. DMA + now supports cicular buffer mode; serial driver now uses circular + DMA to improve Rx performance (Contributed by Mike Smith). + + * STM3240G-EVAL Board. Add support for the LCD and for the STMPE811 + I/O Expander as a touchscreen controller. + + * PIC32 Boards. Board support for the Mikroelektronika PIC32MX7 + Multimedia Board (MMB) and for the Sparkfun UBW32 PIC32 board. + + * NX. Framed windows are now draw in three colors instead of just two. + Numerous other extensions needed to support NxWM (see the ChangeLog + for details). + + * Library. Add prctl() command that can be used to setting and getting + the names of threads. This (plus several other improvements and bug + fixes) are part of a larger effort to improve task monitoring + capabilities. + +Work in progress. This release includes some partially completed +work that is still not ready for prime time. + + * NFS Client. Work is progressing on support for an NFS client + file system. This is a port of the BSD NFS client file system + that is being done by Jose Pablo Rojas V. + + * Automated Configuration. Automated configuration based on the + kconfig-frontends tool is being incorporated into the build + system. The configuration is still not complete enough for + general use in this release. + + * STM32 Drivers. Added files that will (eventually) hold an STM32 + OTG FS host driver. This is still a work in progress. + +Bugfixes (see the change log for details) : + + * sched_setscheduler() return value (Contributed by Richard Cochran). + + * stdio. Ignore CONFIG_STDIO_LINEBUFFER if the file was opened in binary mode. + + * fopen(). Correct an error in parsing open mode string. + + * serial driver. Improved performance be reducing the amount of time + that Rx interrupts are disabled. + + * recvfrom(). Fix a compilation problem. + + * CDC/ACM device driver. Fix an infinite loop that occurs when the serial + device is unregistered. + + * STM32 OTG FS device driver. Numerous fixes and the driver is partially + functional but there are still some issues that become apparent when + debug output is disabled. + + * fcntl(). Always returned zero on success; however, some fcntl commands + need to return non-zero values on success. + + * graphics: Many multi-use mode fixes added to support NxWM (see the + ChangeLog for details). Auto-raise is temporarily disabled in multi- + user mode because it causes some problems with NxWM. + + * on_exit(): Fix compilation errors if CONFIG_SCHED_ONEXIT is enabled. + +NuttX-6.19 +^^^^^^^^^^ + +The 86th release of NuttX, Version 6.19, was made on June 15, 2012, +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.19.tar.gz and +apps-6.19.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). + +This release corresponds with SVN release number: r4847 + +This release features new support for a Network File System (NFS) client. +This feature allows a tiny, embedded MCU to mount a remote file system +exported by an NFS server and then to access the file system as it would +any local file system. Then the tiny MCU can effectively have terabytes +of storage! + +This might be useful for data collection, for MCU configuration information, +for software updates, for providing modular, loadable code modes, controlling +a "farm" of MCUs, ... there are many possibilities and opportunities for +innovation! + +The NuttShell (NSH) now supports the following command: + + nfsmount + +That command will mount the remote NFS server directory at + on the target machine. is the IP address of +the remote server. + +The NFS development was the graduation project of Jose Pablo Rojas V. who +is a student at the Instituto Tecnológico de Costa Rica (ITCR, or TEC). +A lot of effort went into understanding what a tiny, embedded NFS client should +do and getting the target resource usage to a bare minimum. Only around a +kilobyte or so of memory is required to run the NFS client (and most of that +for I/O buffers). Jose Pablo has spent several months living with NFS and +should be congratulated. + +Additional new features and extended functionality: + + * Drivers: SSD1289 LCD driver, MIO283QT2 LCD driver + + * LM3S: Additional register definition header files (contributed by Max + Neklyudov). + + * STM32 Boards: The STM32F4Discovery will now support an SSD1289 LCD, + The STM3220G-EVAL board support is now equivalent to the STM3240G-EVAL + board support. + + * PIC32 Boards: The Mikroelektronika PIC32MX7 MMB board port is now + functional, very complete, and stable. + + * Graphics: The NxConsole will now take keyboard input from the NX graphics + subsystem. This means that if there are multiple NxConsole windows, only + the top instance that has focus will receive the keyboard input. + + * apps/: Add the capability to use an arbitrary USB device as the console + (not necessarily /dev/console). Additional enhancements for USB consoles. + Added the 'mv' command. + +Work in progress. This release includes some partially completed +work that is still not ready for prime time. + + * Automated Configuration. Automated configuration based on the + kconfig-frontends tool is being incorporated into the build + system. The configuration is still not complete enough for + general use in this release. + + * STM32 Drivers. Added files that will (eventually) hold an STM32 + OTG FS host driver. This is still a work in progress. + +Bugfixes (see the change log for details) : + + * General: sleep() and usleep() return values, sig_timedwait() errno setting + on timeout. + * Drivers: STMPE811 touchscreen driver, USB PLC2303, USB CDC/ACM + * STM32: Several USB device controller driver fixes, F4 interrrupt priorities + (contributed by Mike Smith). + * Graphics: Keyboard input, fill trapezoid bug + +As well as other, less critical bugs (see the ChangeLog for details) + +NuttX-6.20 +^^^^^^^^^^ + +The 87th release of NuttX, Version 6.20, was made on July 12, 2012, +and is available for download from the SourceForge website. Note +that release consists of two tarballs: nuttx-6.20.tar.gz and +apps-6.20.tar.gz. Both may be needed (see the top-level nuttx/README.txt +file for build information). + +This release corresponds with SVN release number: r4937 + +Additional new features and extended functionality: + + * Power Management: An evolving power management example is being + created by Diego Sanchez. This effort currently involves on the + STM32 F1 but clearly demonstrates the NuttX power management + system which will automatically drive the system to lower power + usage states due to lack of use. + + * Drivers: Added a driver for the SST 25 SPI-based FLASH parts. + + * PIC32: Added support for the PIC32MX1 and PIC32MX2 families. + Added support for the microchipOpen and Pinguino toolchains. + + * NXP LPC43XX: Added support for the entire LPC43xx family + + * PIC32 boards: Added support for the DTX1-4000L "Mirtoo" module + from http://www.dimitech.com/ (PIC32MX2). + + * NXP LPC43XX Boards: Added support for NGX LPC4330-Xplorer board. + + * NXP LPC17XX Boards: Added support for Micromint Lincoln60 board + (LPC1769). + + * LM3S Boards: Add a configuration to support the TI/Stellaris + EKK-LM3S3B96 development board. Contributed by Jose Pablo Rojas V. + + * Library: NuttX now supports platform-specific stdarg.h header + files. + +Work in progress. This release includes some partially completed +work that is still not ready for prime time. + + * Automated Configuration. Automated configuration based on the + kconfig-frontends tool is being incorporated into the build + system. The configuration is still not complete enough for + general use in this release. + + * STM32 Drivers. Added files that will (eventually) hold an STM32 + OTG FS host driver. This is still a work in progress. + +Bugfixes (see the change log for details) : + + * PIC32: GPIO output configuration (critical bug) + * STM32: Typos in pin mapping files. + * LM3S: Fixed an optimization related but that caused slow start-up + times if optimization was disabled. + * Library: Fixed signed extension but in all limit.h files + (reported by Lorenz Meier). inet_ntoa compilation failure + on Z80. + +As well as other, less critical bugs (see the ChangeLog for details) diff --git a/nuttx/TODO b/nuttx/TODO new file mode 100644 index 0000000000..303950a088 --- /dev/null +++ b/nuttx/TODO @@ -0,0 +1,1920 @@ +NuttX TODO List (Last updated August 3, 2012) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This file summarizes known NuttX bugs, limitations, inconsistencies with +standards, things that could be improved, and ideas for enhancements. + +nuttx/ + + (5) Task/Scheduler (sched/) + (1) On-demand paging (sched/) + (1) Memory Managment (mm/) + (2) Signals (sched/, arch/) + (2) pthreads (sched/) + (2) C++ Support + (5) Binary loaders (binfmt/) + (17) Network (net/, drivers/net) + (3) USB (drivers/usbdev, drivers/usbhost) + (8) Libraries (lib/) + (10) File system/Generic drivers (fs/, drivers/) + (5) Graphics subystem (graphics/) + (1) Pascal add-on (pcode/) + (1) Documentation (Documentation/) + (6) Build system / Toolchains + (5) Linux/Cywgin simulation (arch/sim) + (5) ARM (arch/arm/) + (1) ARM/C5471 (arch/arm/src/c5471/) + (3) ARM/DM320 (arch/arm/src/dm320/) + (2) ARM/i.MX (arch/arm/src/imx/) + (3) ARM/LPC17xx (arch/arm/src/lpc17xx/) + (7) ARM/LPC214x (arch/arm/src/lpc214x/) + (2) ARM/LPC313x (arch/arm/src/lpc313x/) + (3) ARM/STR71x (arch/arm/src/str71x/) + (3) ARM/LM3S6918 (arch/arm/src/lm3s/) + (7) ARM/STM32 (arch/arm/src/stm32/) + (3) AVR (arch/avr) + (0) Intel x86 (arch/x86) + (4) 8051 / MCS51 (arch/8051/) + (3) MIPS/PIC32 (arch/mips) + (1) Hitachi/Renesas SH-1 (arch/sh/src/sh1) + (4) Renesas M16C/26 (arch/sh/src/m16c) + (10) z80/z8/ez80 (arch/z80/) + (8) z16 (arch/z16/) + (1) mc68hc1x (arch/hc) + +apps/ + + (5) Network Utilities (apps/netutils/) + (4) NuttShell (NSH) (apps/nshlib) + (1) System libraries apps/system (apps/system) + (5) Other Applications & Tests (apps/examples/) + +o Task/Scheduler (sched/) + ^^^^^^^^^^^^^^^^^^^^^^^ + + Title: CHILD PTHREAD TERMINATION + Description: When a tasks exits, shouldn't all of its child pthreads also be + terminated? + Status: Open + Priority: Medium, required for good emulation of process/pthread model. + + Title: MMAN.H + Description: Implement sys/mman.h and functions + Status: Open + Priority: Low + + Title: WAIT.H + Description: Implement sys/wait.h and functions. Consider implementing wait, + waitpid, waitid. At present, a parent has no information about + child tasks. + + Update: A simple but usable version of waitpid() has been included. + This version is not compliant with all specifications and can be + enabled with CONFIG_SCHED_WAITPID. + Status: Open + Priority: Low + + Title: MISSING ERRNO SETTINGS + Description: Several APIs do not set errno. Need to review all APIs. + Update: These are being fixed as they are encountered. There is + no accounting of how many interfaces have this problem. + Status: Open + Priority: Medium, required for standard compliance (but makes the + code bigger) + + Title: TICKLESS OS + Description: On a side note, I have thought about a tick-less timer for the OS + for a long time. Basically we could replace the periodic system + timer interrupt with a one-shot interval timer programmed for the + next interesting event time. That is one way to both reduce the + timer interrupt overhead and also to increase the accuracy of + delays. + + Current timer processing is in sched/sched_processtimer.c: + + 1) Calls clock_timer() which just increments a counter (the system + timer -- basically "up-time"). This is only used when code asks + for the current time. In a tickless OS, some substitute answer + for the question "What time is it?" would need to be developed. + You could use an RTC? Or maybe logic that gets the time until the + next interval expiration and computes the current time. The + solution is not too difficult, but depends on a hardware solution. + + 2) Calls wd_timer() which handles the link list of ordered events: + Each timer event is saved with the delta time to the next event + in the list. So an interval timer would be perfect to implement this. + + 3) sched_process_timeslice(). Then there is round-robin time-slicing. + + Status: Open + Priority: Low + +o On-demand paging (sched/) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: ON-DEMAND PAGE INCOMPLETE + Description: On-demand paging has recently been incorporated into the RTOS. + The design of this feature is described here: + http://www.nuttx.org/NuttXDemandPaging.html. + As of this writing, the basic feature implementation is + complete and much of the logic has been verified. The test + harness for the feature exists only for the NXP LPC3131 (see + configs/ea3131/pgnsh and locked directories). There are + some limitations of this testing so I still cannot say that + the feature is fully functional. + Status: Open + Priority: Medium-Low + +o Other core OS logic + ^^^^^^^^^^^^^^^^^^^ + + Title: GET_ENVIRON_PTR() + Description: get_environ_ptr() (sched/sched_getenvironptr.c) is not implemented. + The representation of the the environment strings selected for + NutX is not compatible with the operation. Some significant + re-design would be required to implement this funcion and that + effort is thought to be not worth the result. + Status: Open + Priority: Low -- There is no plan to implement this. + + Title: TIMER_GETOVERRUN() + Description: timer_getoverrun() (sched/timer_getoverrun.c) is not implemented. + Status: Open + Priority: Low -- There is no plan to implement this. + +o Memory Managment (mm/) + ^^^^^^^^^^^^^^^^^^^^^^ + + Title: FREE MEMORY ON TASK EXIT + Description: Add an option to free all memory allocated by a task when the + task exits. This is probably not be worth the overhead for a + deeply embedded system. + + There would be complexities with this implementation as well + because often one task allocates memory and then passes the + memory to another: The task that "owns" the memory may not + be the same as the task that allocated the memory. + + Update. From the NuttX forum: + ...there is a good reason why task A should never delete task B. + That is because you will strand memory resources. Another feature + lacking in most flat address space RTOSs is automatic memory + clean-up when a task exits. + + That behavior just comes for free in a process-based OS like Linux: + Each process has its own heap and when you tear down the process + environment, you naturally destroy the heap too. + + But RTOSs have only a single, shared heap. I have spent some time + thinking about how you could clean up memory required by a task + when a task exits. It is not so simple. It is not as simple as + just keeping memory allocated by a thread in a list then freeing + the list of allocations when the task exists. + + It is not that simple because you don't know how the memory is + being used. For example, if task A allocates memory that is used + by task B, then when task A exits, you would not want to free that + memory needed by task B. In a process-based system, you would + have to explicitly map shared memory (with reference counting) in + order to share memory. So the life of shared memory in that + environment is easily managed. + + I have thought that the way that this could be solved in NuttX + would be: (1) add links and reference counts to all memory allocated + by a thread. This would increase the memory allocation overhead! + (2) Keep the list head in the TCB, and (3) extend mmap() and munmap() + to include the shared memory operations (which would only manage + the reference counting and the life of the allocation). + + Then what about pthreads? Memory should not be freed until the last + pthread in the group exists. That could be done with an additional + reference count on the whole allocated memory list (just as streams + and file descriptors are now shared and persist until the last + pthread exits). + + I think that would work but to me is very unattractive and + inconsistent with the NuttX "small footprint" objective. ... + + Other issues: + - Memory free time would go up because you would have to remove + the memory from that list in free(). + - There are special cases inside the RTOS itself. For example, + if task A creates task B, then initial memory allocations for + task B are created by task A. Some special allocators would + be required to keep this memory on the correct list (or on + no list at all). + + Status: Open + Priority: Medium/Low, a good feature to prevent memory leaks but would + have negative impact on memory usage and code size. + +o Signals (sched/, arch/) + ^^^^^^^^^^^^^^^^^^^^^^^ + + Title: STANDARD SIGNALS + Description: 'Standard' signals and signal actions are not supported. + (e.g., SIGINT, SIGCHLD, SIGSEGV, etc). + Status: Open + Priority: Low, required by standards but not so critical for an + embedded system. + + Title: SIGEV_THREAD + Description: sig_notify() logic does not support SIGEV_THREAD; structure + struct sigevent does not provide required members sigev_notify_function + or sigev_notify_attributes. + Status: Low, there are alternative designs. However, these features + are required by the POSIX standard. + Priority: Low for now + +o pthreads (sched/) + ^^^^^^^^^^^^^^^^^ + + Title: CANCELLATION POINTS + Description: pthread_cancel(): Should implement cancellation points and + pthread_testcancel() + Status: Open + Priority: Low, probably not that useful + + Title: PTHREAD_PRIO_PROTECT + Description: Extended pthread_mutexattr_setprotocol() suport PTHREAD_PRIO_PROTECT: + "When a thread owns one or more mutexes initialized with the + PTHREAD_PRIO_PROTECT protocol, it shall execute at the higher of its + priority or the highest of the priority ceilings of all the mutexes + owned by this thread and initialized with this attribute, regardless of + whether other threads are blocked on any of these mutexes or not. + + "While a thread is holding a mutex which has been initialized with + the PTHREAD_PRIO_INHERIT or PTHREAD_PRIO_PROTECT protocol attributes, + it shall not be subject to being moved to the tail of the scheduling queue + at its priority in the event that its original priority is changed, + such as by a call to sched_setparam(). Likewise, when a thread unlocks + a mutex that has been initialized with the PTHREAD_PRIO_INHERIT or + PTHREAD_PRIO_PROTECT protocol attributes, it shall not be subject to + being moved to the tail of the scheduling queue at its priority in the + event that its original priority is changed." + Status: Open + Priority: Low -- about zero, probably not that useful. Priority inheritance is + already supported and is a much better solution. And it turns out + that priority protection is just about as complex as priority inheritance. + Exerpted from my post in a Linked-In discussion: + + "I started to implement this HLS/"PCP" semaphore in an RTOS that I + work with (http://www.nuttx.org) and I discovered after doing the + analysis and basic code framework that a complete solution for the + case of a counting semaphore is still quite complex -- essentially + as complex as is priority inheritance. + + "For example, suppose that a thread takes 3 different HLS semaphores + A, B, and C. Suppose that they are prioritized in that order with + A the lowest and C the highest. Suppose the thread takes 5 counts + from A, 3 counts from B, and 2 counts from C. What priority should + it run at? It would have to run at the priority of the highest + priority semaphore C. This means that the RTOS must maintain + internal information of the priority of every semaphore held by + the thread. + + "Now suppose it releases one count on semaphore B. How does the + RTOS know that it still holds 2 counts on B? With some complex + internal data structure. The RTOS would have to maintain internal + information about how many counts from each semaphore are held + by each thread. + + "How does the RTOS know that it should not decrement the priority + from the priority of C? Again, only with internal complexity. It + would have to know the priority of every semaphore held by + every thread. + + "Providing the HLS capability on a simple phread mutex would not + be such quite such a complex job if you allow only one mutex per + thread. However, the more general case seems almost as complex + as priority inheritance. I decided that the implementation does + not have value to me. I only wanted it for its reduced + complexity; in all other ways I believe that it is the inferior + solution. So I discarded a few hours of programming. Not a + big loss from the experience I gained." + +o C++ Support + ^^^^^^^^^^^ + + Title: USE OF SIZE_T IN NEW OPERATOR + Description: The argument of the 'new' operators should take a type of + size_t (see libxx/libxx_new.cxx and libxx/libxx_newa.cxx). But + size_t has an unknown underlying. In the nuttx sys/types.h + header file, size_t is typed as uint32_t (which is determined by + architecture-specific logic). But the C++ compiler may believe + that size_t is of a different type resulting in compilation errors + in the operator. Using the underlying integer type Instead of + size_t seems to resolve the compilation issues. + Status: Kind of open. There is a workaround. Setting CONFIG_CXX_NEWLONG=y + will define the operators with argument of type unsigned long; + Setting CONFIG_CXX_NEWLONG=n will define the operators with argument + of type unsigned int. But this is pretty ugly! A better solution + would be to get ahold of the compilers definition of size_t. + Priority: Low. + + Title: STATIC CONSTRUCTORS + Description: Need to call static constructors + Update: Static constructors are implemented for the STM32 F4 and + this will provide the model for all solutions. Basically, if + CONFIG_HAVE_CXXINITIALIZE=y is defined in the configuration, then + board-specific code must provide the interface up_cxxinitialize(). + up_cxxinitialize() is called from user_start() to initialize + all static class instances. This TODO item probably has to stay + open because this solution is only available on STM32 F4. + Status: Open + Priority: Low, depends on toolchain. Call to gcc's built-in static + constructor logic will probably have to be performed by + user logic in user_start(). + +o Binary loaders (binfmt/) + ^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: NXFLAT TESTS + Description: Not all of the NXFLAT test under apps/examples/nxflat are working. + Most simply do not compile yet. tests/mutex runs okay but + outputs garbage on completion. + Status: Open + Priority: High + + Title: ARM UP_GETPICBASE() + Description: The ARM up_getpicbase() does not seem to work. This means + the some features like wdog's might not work in NXFLAT modules. + Status: Open + Priority: Medium-High + + Title: READ-ONLY DATA IN RAM + Description: At present, all .rodata must be put into RAM. There is a + tentative design change that might allow .rodata to be placed + in FLASH (see Documentation/NuttXNxFlat.html). + Status: Open + Priority: Medium + + Title: GOT-RELATIVE FUNCTION POINTERS + Description: If the function pointer to a statically defined function is + taken, then GCC generates a relocation that cannot be handled + by NXFLAT. There is a solution described in Documentataion/NuttXNxFlat.html, + by that would require a compiler change (which we want to avoid). + The simple workaround is to make such functions global in scope. + Status: Open + Priority: Low (probably will not fix) + + Title: USE A HASH INSTEAD OF A STRING IN SYMBOL TABLES + Description: In the NXFLAT symbol tables... Using a 32-bit hash value instead + of a string to identify a symbol should result in a smaller footprint. + Status: Open + Priority: Low + + Title: WINDOWS-BASED TOOLCHAIN BUILD + Description: Windows build issue. Some of the configurations that use NXFLAT have + the linker script specified like this: + + NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat.ld -no-check-sections + + That will not work for windows-based tools because they require Windows + style paths. The solution is to do something like this: + + if ($(WINTOOL)y) + NXFLATLDSCRIPT=${cygpath -w $(TOPDIR)/binfmt/libnxflat/gnu-nxflat.ld} + else + NXFLATLDSCRIPT=$(TOPDIR)/binfmt/libnxflat/gnu-nxflat.ld + endif + + Then use + + NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T"$(NXFLATLDSCRIPT)" -no-check-sections + + Status: Open + Priority: There are too many references like the above. They will have + to get fixed as needed for Windows native tool builds. + +o Network (net/, drivers/net) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: SOCK_RAW/SOCK_PACKET + Description: Should implement SOCK_RAW, SOCK_PACKET + Status: Open + Priority: Low + + Tile: MULTIPLE NETWORK INTERFACE SUPPORT + Description: uIP polling issues / Multiple network interface support: + (1) Current logic will not support multiple ethernet drivers. + Each driver should poll on TCP connections connect on the + network supported by the driver; UDP polling should respond + with TX data only if the UDP packet is intended for the + the network supported by the driver. + (2) If there were multiple drivers, polling would occur at + double the rate. Fix by using bound IP address in TCP + connection (lipaddr) and verifying that it is in the subnet + served by the driver. + Status: Open + Priority: Medium, The feature is not important, but it is important + for NuttX to resolve the architectural issues. + + Title: SENDTO() AND MULTIPLE NETWORK INTERFACE SUPPORT + Description: sendto() and multiple network interface support: + When polled, would have to assure that the destination IP + is on the subnet served by the polling driver. + Status: Open + Priority: Medium, The feature is not important, but it is important + for NuttX to resolve the architectural issues. + + Title: IPv6 + Description: IPv6 support is incomplete. Adam Dunkels has recently announced + IPv6 support for uIP (currently only as part of Contiki). Those + changes need to be ported to NuttX. + Status: Open + Priority: Medium + + Title: LISTENING FOR UDP BROADCASTS + Description: Incoming UDP broadcast should only be accepted if listening on + INADDR_ANY(?) + Status: Open + Priority: Low + + Title: READ-AHEAD THROTTLING + Description: Read-ahead buffers capture incoming TCP data when no user + thread is recv-ing the data. Should add some driver call to + support throttling; when there is no listener for new data, the + driver should be throttled. Perhaps the driver should disable + RX interrupts when throttled and re-anable on each poll time. + recvfrom would, of course, have to un-throttle. + Status: Open + Priority: Medium + + Title: STANDARDIZE ETHERNET DRIVER STATISTICS + Description: Need to standardize collection of statistics from network + drivers. apps/nshlib ifconfig command should present + statistics. + Status: Open + Priority: Low + + Title: CONCURRENT TCP SEND OPERATIONS + Description: At present, there cannot be two concurrent active TCP send + operations in progress using the same socket. This is because + the uIP ACK logic will support only one transfer at a time. The + solution is simple: A mutex will be needed to make sure that each + send that is started is able to be the exclusive sender until all of + the data to be sent has been ACKed. + Status: Open. There is some temporary logic to apps/nshlib that does + this same fix and that temporary logic should be removed when + send() is fixed. + Priority: Medium-Low. This is an important issue for applications that + send on the same TCP socket from multiple threads. + + Title: UDP READ-AHEAD? + Description: TCP supports read-ahead buffering to handle the receipt of + TCP/IP packets when there is no read() in place. Should such + capability be useful for UDP? PRO: Would reduce packet loss + and enable support for poll()/select(). CON: UDP is inherently + lossy so why waste memory footprint? + Status: Open + Priority: Medium + + Title: NO POLL/SELECT ON UDP SOCKETS + Description: poll()/select() is not implemented for UDP sockets because they do + do not support read-ahead buffering. Therefore, there is never + a case where you can read from a UDP socket without blocking. + Status: Open, depends on UDP read-ahead support + Priority: Medium + + Title: POLL/SELECT ON TCP SOCKETS NEEDS READ-AHEAD + Description: poll()/select() only works for availability of buffered TCP + read data (when read-ahead is enabled). The way writing is + handled in uIP, all sockets must wait when send and cannot + be notifiied when they can send without waiting. + Status: Open, probably will not be fixed. + Priority: Medium... this does effect porting of applications that expect + different behavior from poll()/select() + + Title: SOCKETS DO NOT ALWAYS SUPPORT O_NONBLOCK + Description: sockets do not support all modes for O_NONBLOCK. Sockets + support only (1) TCP/IP non-blocking read operations when read-ahead + buffering is enabled, and (2) TCP/IP accept() operations when TCP/IP + connection backlog is enabled. + Status: Open + Priority: Low. + + Title: UNFINISHED CRYSTALLAN CS89X0 DRIVER + Description: I started coding a CrystalLan CS89x0 driver (drivers/net/cs89x0.c), + but never finished it. + Status: Open + Priority: Low unless you need it. + + Title: UNTESTED IGMPv2 + Description: Support for client-side IGMPv2 multicast has been added but not yet + tested (because I don't have a proper environment for multicast testing). + There are most likely errors that need to be fixed at least in the + receipt of multicast packets. + + In addition, an ethernet driver that needs to work with the IGMP logic + will have to include additional support for multicast MAC address tables. + Status: Open + Priority: Low unless you need it. + + Title: INTERFACES TO LEAVE/JOIN IGMP MULTICAST GROUP + Description: The interfaces used to leave/join IGMP multicast groups is non-standard. + RFC3678 (IGMPv3) suggests ioctl() commands to do this (SIOCSIPMSFILTER) but + also status that those APIs are historic. NuttX implements these ioctl + commands, but is non-standard because: (1) It does not support IGMPv3, and + (2) it looks up drivers by their device name (eg., "eth0") vs IP address. + + Linux uses setsockopt() to control multicast group membership using the + IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP options. It also looks up drivers + using IP addresses (It would require additional logic in NuttX to look up + drivers by IP address). See http://tldp.org/HOWTO/Multicast-HOWTO-6.html + Status: Open + Priority: Medium. All standards compatibility is important to NuttX. However, most + the mechanism for leaving and joining groups is hidden behind a wrapper + function so that little of this incompatibilities need be exposed. + + Title: CONFIGURATIONS WITH TINY MTUS + Description: Many configurations have the MTU (CONFIG_NET_BUFSIZE) set to very small + numbers, less then the minimum MTU size that must be supported -- 576. + This can cause problems in some networks: CONFIG_NET_BUFSIZE should + be set to at least 576 in all defconfig files. + + The symptoms of using very small MTU sizes can be very strange. With + Ubuntu 9.x and vsFtpd was that the total packet size did *not match* the + packet size in the IP header. This then caused a TCP checksum failure + and the packet was rejected. + Status: Open + Priority: Low... fix defconfig files as necessary. + + Title: UNFINISHED ENC28J60 DRIVER + Description: So far, I have not come up with a usable hardware platform to + verify the ENC28J60 Ethernet driver (drivers/net/enc28j60.c). + So it is untested. + Status: Open + Priority: Low unless you need it. + +o USB (drivers/usbdev, drivers/usbhost) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: USB STORAGE DRIVER DELAYS + Description: There is a workaround for a bug in drivers/usbdev/usbdev_storage.c. + that involves delays. This needs to be redesigned to eliminate these + delays. See logic conditioned on CONFIG_USBMSC_RACEWAR. + Status: Open + Priority: Medium + + Title: RTL8187 DRIVER IS UNFINISHED + Description: misc/drivers/usbhost_rtl8187.c is a work in progress. There is no RTL8187 + driver available yet. That is a work in progress it was abandoned because + it depends on having an 802.11g stack. + Status: Open + Priority: Low (Unless you need RTL8187 support). + + Title: EP0 OUT CLASS DATA + Description: There is no mechanism in place to handle EP0 OUT data transfers. + There are two aspects to this problem, neither are easy to fix + (only because of the number of drivers that would be impacted): + + 1. The class drivers only send EP0 write requests and these are + only queued on EP0 IN by this drivers. There is never a read + request queued on EP0 OUT. + 2. But EP0 OUT data could be buffered in a buffer in the driver + data structure. However, there is no method currently + defined in the USB device interface to obtain the EP0 data. + + Updates: (1) The USB device-to-class interface as been extended so + that EP0 OUT data can accompany the SETUP request sent to the + class drivers. (2) The logic in the STM32 F4 OTG FS device driver + has been extended to provide this data. Updates are still needed + to other drivers. + Status: Open + Priority: High for class drivers that need EP0 data. For example, the + CDC/ACM serial driver might need the line coding data (that + data is not used currenly, but it might be). + +o Libraries (lib/) + ^^^^^^^^^^^^^^^^ + + Title: ENVIRON + Description: The definition of environ in stdlib.h is bogus and will not + work as it should. This is because the underlying + representation of the environment is not an arry of pointers. + Status: Open + Priority: Medium + + Title: TERMIOS + Description: Need some minimal termios support... at a minimum, enough to + switch between raw and "normal" modes to support behavior like + that needed for readline(). + UPDATE: There is growing functionality in lib/termios/ and in the + ioctl methods of several MCU serial drivers (stm32, lpc43, lpc17, + pic32). However, as phrased, this bug cannot yet be closed since + this "growing functionality" does not address all termios.h + functionality and not all serial drivers support termios. + Status: Open + Priority: Low + + Title: DAYS OF THE WEEK + Description: strftime() and other timing functions do not handle days of the week. + Status: Open + Priority: Low + + Title: RESETTING GETOPT() + Description: There is an issue with the way that getopt() handles errors that + return '?'. + + 1. Does getopt() reset its global variables after returning '?' so + that it can be re-used? That would be required to support where + the caller terminates parsing before reaching the last parameter. + 2. Or is the client expected to continue parsing after getopt() + returns '?' and parse until the final parameter? + + The current getopt() implementation only supports #2. + Status: Open + Priority: Low + + Title: FERROR() AND CLEARERR() + Description: Not implemented: ferror() and clearerr() + Status: Open + Priority: Low + + Title: CONCURRENT STREAM READ/WRITE + Description: NuttX only supports a single file pointer so reads and writes + must be from the same position. This prohibits implementation + of behavior like that required for fopen() with the "a+" mode. + According to the fopen man page: + + "a+ Open for reading and appending (writing at end of file). + The file is created if it does not exist. The initial file + position for reading is at the beginning of the file, but + output is always appended to the end of the file." + + At present, the single NuttX file pointer is positioned to the + end of the file for both reading and writing. + Status: Open + Priority: Medium. This kind of operation is probably not very common in + deeply embedded systems but is required by standards. + + Title: DIVIDE BY ZERO + Description: This is bug 3468949 on the SourceForge website (submitted by + Philipp Klaus Krause): + "lib_strtod.c does contain divisions by zero in lines 70 and 96. + AFAIK, unlike for Java, division by zero is not a reliable way to + get infinity in C. AFAIK compilers are allowed e.g. give a compile- + time error, and some, such as sdcc, do. AFAIK, C implementations + are not even required to support infinity. In C99 the macro isinf() + could replace the first use of division by zero. Unfortunately, the + macro INFINITY from math.h probably can't replce the second division + by zero, since it will result in a compile-time diagnostic, if the + implementation does not support infinity." + Status: Open + Priority: + + Title: OLD dtoa NEEDS TO BE UPDATED + Description: This implementation of dtoa in lib/stdio is old and will not + work with some newer compilers. See + http://patrakov.blogspot.com/2009/03/dont-use-old-dtoac.html + Status: Open + Priority: ?? + +o File system / Generic drivers (fs/, drivers/) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + NOTE: The NXFFS file system has its own TODO list at nuttx/fs/nxffs/README.txt + + Title: CHMOD() AND TRUNCATE() + Description: Implement chmod(), truncate(). + Status: Open + Priority: Low + + Title: CAN POLL SUPPORT + Description: At present, the CAN driver does not support the poll() method. + See drivers/can.c + Status: Open + Priority: Low + + Title: REMOVING PIPES AND FIFOS + Description: There is no way to remove a FIFO or PIPE created in the + psuedo filesystem. Once created, they persist indefinitely + and cannot be unlinked. This is actually a more generic + issue: unlink does not work for anything in the psuedo- + filesystem. + Status: Open, but partially resolved: pipe buffer is at least freed + when there are not open references to the pipe/FIFO. + Priority: Medium + + Title: ROMFS CHECKSUMS + Description: The ROMFS file system does not verify checksums on either + volume header on on the individual files. + Status: Open + Priority: Low. I have mixed feelings about if NuttX should pay a + performance penalty for better data integrity. + + Title: SPI-BASED SD MULTIPLE BLOCK TRANSFERS + Description: The simple SPI based MMCS/SD driver in fs/mmcsd does not + yet handle multiple block transfers. + Status: Open + Priority: Medium-Low + + Title: READ-AHEAD/WRITE BUFFER UNTESTED + Description: Block driver read-ahead buffer and write buffer support is + implemented but not yet tested. + Status: Open + Priority: Low + + Title: SDIO-BASED SD READ-AHEAD/WRITE BUFFERING INCOMPLETE + Description: The drivers/mmcsd/mmcsd_sdio.c driver has hooks in place to + support read-ahead buffering and write buffering, but the logic + is incomplete and untested. + Status: Open + Priority: Low + + Title: SERIAL DRIVER DOES NOT RETURN WHEN SIGNAL RECEIVED + Description: The serial driver (drivers/serial) should return with an + error and errno=EINTR when an interrupt is received. However, + the serial driver just continues waiting: + + static void uart_takesem(FAR sem_t *sem) + { + while (sem_wait(sem) != 0) + { + ASSERT(*get_errno_ptr() == EINTR); + } + } + Status: Open + Priority Medium + + Title: POLLHUP SUPPORT + Description: All drivers that support the poll method should also report + POLLHUP event when the driver is closedd. + Status: Open + Priority: Medium-Low + + Title: CONFIG_RAMLOG_CONSOLE DOES NOT WORK + Description: When I enable CONFIG_RAMLOG_CONSOLE, the system does not come up + propertly (using configuration stm3240g-eval/nsh2). The problem + may be an assertion that is occuring before we have a console. + Status: Open + Priority: Medium + +o Graphics subystem (graphics/) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + See also the NxWidgets TODO list file for related issues. + + Title: UNTESTED GRAPHICS APIS + Description: Testing of all APIs is not complete. See + http://nuttx.sourceforge.net/NXGraphicsSubsystem.html#testcoverage + Status: Open + Priority: Medium + + Title: ITALIC FONTS / NEGATIVE FONT OFFSETS + Description: Font metric structure (in include/nuttx/nx/nxfont.h) should allow + negative X offsets. Negative x-offsets are necessary for certain + glyphs (and is very common in italic fonts). + For example Eth, icircumflex, idieresis, and oslash should have + offset=1 in the 40x49b font (these missing negative offsets are + NOTE'ed in the font header files). + Status: Open. The problem is that the x-offset is an unsigned bitfield + in the current structure. + Priority: Low. + + Title: RAW WINDOW AUTORAISE + Description: Auto-raise only applies to NXTK windows. Shouldn't it also apply + to raw windows as well? + Status: Open + Priority: Low + + Title: AUTO-RAISE DISABLED + Description: Auto-raise is currently disabled in NX multi-server mode. The + reason is complex: + - Most touchscreen controls send touch data a high rates + - In multi-server mode, touch events get queued in a message + queue. + - The logic that receives the messages performs the auto-raise. + But it can do stupid things after the first auto-raise as + it opperates on the stale data in the message queue. + I am thinking that auto-raise ought to be removed from NuttX + and moved out into a graphics layer (like NxWM) that knows + more about the appropriate context to do the autoraise. + Status: Open + Priority: Medium low + + Title: IMPROVED NXCONSOLE FONT CACHING + Description: Now each NxConsole instance has its own private font cache + whose size is determined by CONFIG_NXCONSOLE_MXCHARS. If there + are multiple NxConsole instances using the same font, each will + have a separate font cache. This is inefficient and wasteful + of memory: Each NxConsole instance should share a common font + cache. + Status: Open + Priority: Medium. Not important for day-to-day testing but would be + a critical improvement if NxConsole were to be used in a + product. + +o Pascal Add-On (pcode/) + ^^^^^^^^^^^^^^^^^^^^^^ + + Title: P-CODES IN MEMORY UNTESTED + Description: Need APIs to verify execution of P-Code from memory buffer. + Status: Open + Priority: Low + + Title: SMALLER LOADER AND OBJECT FORMAT + Description: Loader and object format may be too large for some small + memory systems. Consider ways to reduce memory footprint. + Status: Open + Priority: Medium + +o Documentation (Documentation/) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: DOCUMENT APIS USABLE FROM INTERRUPT HANDLERS + Description: Need to document which APIs can be used in interrupt + handlers (like mq_send and sem_post) and which cannot. + Status: Open + Priority: Low + +o Build system + ^^^^^^^^^^^^ + + Title: NUTTX CONFIGURATION TOOL + Description: Need a NuttX configuration tool. The number of configuration + settings has become quite large and difficult to manage manually. + Update: This task is essentially completed. But probably not for + all platforms and all features. When do we know that the the + features is complete and that we can switch to exclusive use of + the tool? + Status: Open + Priority: Medium-low + + Title: NATIVE WINDOWS BUILD + Description: At present, NuttX builds only under Linux or Cygwin. + Investigate the possibility of a native Windows build using + something like the GNUWin32 tools (coreutils+make+grep+sed+uname). + Status: Open + Priority: Low + + Title: WINDOWS DEPENDENCY GENERATION + Description: Dependency generation is currently disabled when a Windows native + toolchain is used. I think that the only issue is that all of the + Windows dependencies needed to be quoted in the Make.dep files. + Status: Open + Priority: Low -- unless some dependency-related build issues is discovered. + + Title: SETENV.H + Description: Logic in most setenv.sh files can create the following problem + on many platforms: + + $ . ./setenv.sh + basename: invalid option -- 'b' + Try `basename --help' for more information. + + The problem is that $0 is the current running shell which may include + a dash in front: + + $ echo $0 + -bash + + But often is just /bin/bash (and the problem does not occur. The fix + is: + + -if [ "$(basename $0)" = "setenv.sh" ]; then + +if [ "$_" = "$0" ] ; then + Status: Open + Priority: Low. Use of setenv.sh is optional and most platforms do not have + this problem. Scripts will be fixed one-at-a-time as is appropropriate. + + Title: MAKE EXPORT LIMITATIONS + Description: The top-level Makefile 'export' target that will bundle up all of the + NuttX libraries, header files, and the startup object into an export-able + tarball. This target uses the tools/mkexport.sh script. Issues: + + 1. This script assumes the host archiver ar may not be appropriate for + non-GCC toolchains + 2. For the kernel build, the user libraries should be built into some + libuser.a. The list of user libraries would have to accepted with + some new argument, perhaps -u. + Status: Open + Priority: Low. + + Title: KERNEL BUILD MODE ISSUES + Description: In the kernel build mode (where NuttX is built as a monlithic + kernel and user code must trap into the protected kernel via + syscalls), the single user mode cannot be supported. In this + built configuration, only the multiple user mode can be supported + with the NX server residing inside of the kernel space. In + this case, most of the user end functions in graphics/nxmu + must be moved to lib/nx and those functions must be built into + libuser.a to be linked with the user-space code. + Status: Open + Priority: Low -- the kernel build configuration is not fully fielded + yet. + +o Linux/Cywgin simulation (arch/sim) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: SIMULATED SERIAL DRIVER + Description: The simulated serial driver has some odd behavior. It + will stall for a long time on reads when the C stdio buffers are + being refilled. This only effects the behavior of things like + fgetc(). Workaround: Set CONFIG_STDIO_BUFFER_SIZE=0, suppressing + all C buffered I/O. + Status: Open + Priority: Low (because the simulator is only a test/development platform) + + Title: SIMULATOR NETWORKING SUPPORT + Description: I never did get networking to work on the sim Linux target. On Linux, + it tries to use the tap device (/dev/net/tun) to emulate an Ethernet + NIC, but I never got it correctly integrated with the NuttX networking. + NOTE: On Cygwin, the build uses the Cygwin WPCAP library and is, at + least, partially functional (it has never been rigorously tested). + Status: Open + Priority: Low (unless you want to test networking features on the simulation). + + Title: ROUND-ROBIN SCHEDULING IN THE SIMULATOR + Description: Since the simulation is not pre-emptible, you can't use round-robin + scheduling (no time slicing). Currently, the timer interrupts are + "faked" during IDLE loop processing and, as a result, there is no + task pre-emption because there are no asynchrous events. This could + probably be fixed if the "timer interrupt" were driver by Linux + signals. NOTE: You would also have to implement irqsave() and + irqrestore() to block and (conditionally) unblock the signal. + Status: Open + Priority: Low + + Title: NSH ISSUES ON THE SIMULATOR + Descripion: The NSH example has some odd behaviors. Mult-tasking -- for example, + execution of commands in background -- does not work normally. This + is due to the fact that NSH uses the system standard input for the + console. This means that the simulation is actually "frozen" all of + the time when NSH is waiting for input and background commands never + get the chance to run. + Status: Open + Priority: This will not be fixed. This is the normal behavior in the current + design of the simulator. "Real" platforms will behave correctly + because NSH will "sleep" when it waits for console inpu and other + tasks can run freely. + + Title: DOUBLE COMMAND ECHO + Description: In the NSH example, the host HOST echoes each command so after you + you enter a command, the command is repeated on the next line. This + is an artifact of the simulator only. + Status: Open + Priority: This will not be fixed. This is the normal behavior in the current + design of the simulator. "Real" platforms will behave correctly. + +o ARM (arch/arm/) + ^^^^^^^^^^^^^^^ + + Title: IMPROVED ARM INTERRUPT HANDLING + Description: ARM interrupt handling performance could be improved in some + ways. One easy way is to use a pointer to the context save + area in current_regs instead of using up_copystate so much. + see handling of 'current_regs" in arch/arm/src/armv7-m/* for + examples of how this might be done. + Status: Open + Priority: Low + + Title: IMPROVED ARM INTERRUPT HANDLING + Description: The ARM and Cortex-M3 interrupt handlers restores all regisers + upon return. This could be improved as well: If there is no + context switch, then the static registers need not be restored + because they will not be modified by the called C code. + (see arch/sh/src/sh1/sh1_vector.S for example) + Status: Open + Priority: Low + + Title: SVCALLS AND HARDFAULTS + Description: The Cortex-M3 user context switch logic uses SVCall instructions. + This user context switching time could be improved by eliminating + the SVCalls and developing assembly language implementations + of the context save and restore logic. + Also, because interrupts are always disabled when the SVCall is + executed, the SVC goes to the hard fault handler where it must + be handled as a special case. I recall seeing some controls + somewhere that will allow to suppress one hard fault. I don't + recall the control, but something like this should be used before + executing the SVCall so that it vectors directly to the SVC + handler. + Another, more standard option would be to use interrupt priority + levels to control interrupts. In that case, (1) The SVC would + be the highest priority interrupt (0), (2) irqsave() would set + the interrupt mask level to just above that, and (2) irqrestore + would restore the interrupt level. This would not be diffult, + but does affect a lot of files! + Status: Open + Priority: Low + + Title: ARM INTERRUPTS AND USER MODE + Description: The ARM interrupt handling (arch/arm/src/arm/up_vectors.S) returns + using 'ldmia sp, {r0-r15}^' My understanding is that this works + fine because everything is in kernel-mode. In an operating model + where applications run in user mode and interrupts/traps run in + kernel-mode, I think that there is a problem with this. This would + like be a problem, for example, if for a kernel build where NuttX + is built as a monolithic, protected kernel and user mode programs + trap into the kernel. + Status: Open + Priority: Low until I get around to implementng security or kernel mode for + the ARM platform. + + Title: CORTEX-M3 STACK OVERFLOW + Description: There is bit bit logic inf up_fullcontextrestore() that executes on + return from interrupts (and other context switches) that looks like: + + ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the stored CPSR value */ + msr cpsr, r1 /* Set the CPSR */ + + /* Now recover r0 and r1 */ + + ldr r0, [sp] + ldr r1, [sp, #4] + add sp, sp, #(2*4) + + /* Then return to the address at the stop of the stack, + * destroying the stack frame + */ + + ldr pc, [sp], #4 + + Under conditions of excessivley high interrupt conditions, many + nested interrupts can oocur just after the 'msr cpsr' instruction. + At that time, there are 4 bytes on the stack and, with each + interrupt, the stack pointer may increment and possibly overflow. + + This can happen only under conditions of continuous interrupts. + See this email thread: http://tech.groups.yahoo.com/group/nuttx/message/1261 + On suggested change is: + + ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the stored CPSR value */ + msr spsr_cxsf, r1 /* Set the CPSR */ + ldmia r0, {r0-r15}^ + + But this has not been proven to be a solution. + Status: Open + Priority: Low. The conditions of continous interrupts is really the problem. + If your design needs continous interrupts like this, please try + the above change and, please, submit a patch with the working fix. + +o ARM/C5471 (arch/arm/src/c5471/) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: UART RECONFIGURATION + Description: UART re-configuration is untested and conditionally compiled out. + Status: Open + Priority: Medium. ttyS1 is not configured, but not used; ttyS0 is configured + by the bootloader + +o ARM/DM320 (arch/arm/src/dm320/) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: DEBUG ISSUES + Description: config/ntos-dm320: It seems that when a lot of debug statements + are added, the system no longer boots. This is suspected to be + a stack problem: Making the stack bigger or removing arrays on + the stack seems to fix the problem (might also be the + bootloader overwriting memory) + Status: Open + Priority: Medium + + Title: USB DEVICE DRIVER UNTESTED + Description: A USB device controller driver was added but has never been tested. + Status: Open + Priority: Medium + + Title: FRAMEBUFFER DRIVER UNTESTED + Description: A framebuffer "driver" was added, however, it remains untested. + Status: Open + Priority: Medium + + Title: VIDEO ENCODER DRIVER + Description: In order to use the framebuffer "driver" additional video encoder + logic is required to setupt composite video output or to interface + with an LCD. + Status: Open + Priority: Medium (high if you need to use the framebuffer driver) + +o ARM/i.MX (arch/arm/src/imx/) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: PORT IS INCOMPLETE + Description: The basic port of the i.MX1 architecuture was never finished. The port + is incomplete (as of this writing, is still lacks a timer, interrupt + decoding, USB, network) and untested. + Status: Open + Priority: Medium (high if you need i.MX1/L support) + + Title: SPI METHODS ARE NOT THREAD SAFE + Description: SPI methods are not thread safe. Needs a semaphore to protect from re-entrancy. + Status: Open + Priority: Medium -- Will be very high if you do SPI access from multiple threads. + +o ARM/LPC17xx (arch/arm/src/lpc17xx/) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: USB DMA INCOMPLETE + Description: USB DMA not fully implemented. Partial logic is in place but it is + fragmentary and bogus. (Leveraged from the lpc214x) + Status: Open + Priority: Low + + Title: SSP DRIVER IMPROVEMENTS + Description: a) At present the SSP driver is polled. Should it be interrupt driven? + Look at arch/arm/src/imx/imx_spi.c -- that is a good example of an + interrupt driven SPI driver. Should be very easy to part that architecture + to the LPC. + b) See other SSP (SPI) driver issues listed under ARM/LPC214x. The LPC17xx + driver is a port of the LPC214x driver and probably has the same issues. + b) Other SSP driver improvements: Add support for multiple devices on the + SSP bus, use DMA data transfers + Status: Open + Priority: Medium + + Title: NOKIA LCD DRIVER NONFUNCTIONAL + Description: An LCD driver for the Olimex LPC1766STK has been developed. However, that + driver is not yet functional on the board: The backlight comes on, but + nothing is visible on the display. + Status: Open + Priority: Medium-Low (unless you need the display on the LPC1766STK!) + +o ARM/LPC214x (arch/arm/src/lpc214x/) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: VECTOR INTERRUPTS + Description: Should use Vector Interrupts + Status: Open + Priority: Low + + Title: USB DMA INCOMPLETE + Description: USB DMA not fully implemented. Partial logic is in place but it is + fragmentary and bogus. + Status: Open + Priority: Low + + Title: USB SERIAL DRIVER REPORTS WRONG ERROR + Description: USB Serial Driver reports wrong error when opened before the + USB is connected (reports EBADF instead of ENOTCONN) + Status: Open + Priority: Low + + Title: SPI DRIVER IMPROVEMENTS + Description: At present the SPI driver is polled. Should it be interrupt driven? + Look at arch/arm/src/imx/imx_spi.c -- that is a good example of an + interrupt driven SPI driver. Should be very easy to part that architecture + to the LPC. + Status: Open + Priority: Medium + + Title: SPI METHODS ARE NOT THREAD SAFE + Description: SPI methods are not thread safe. Needs a semaphore to protect from re-entrancy. + Status: Open + Priority: Medium -- Will be very high if you do SPI access from multiple threads. + + Title: SPI DRIVER DELAYS + Description: At present the SPI driver is polled -AND- there is a rather large, arbitrary, + delay in one of the block access routines. The purpose of the delay is to + avoid a race conditions. This begs for a re-design -OR- at a minimum, some + optimiation of the delay time. + Status: Open + Priority: Medium + + Title: 2GB SD CARD ISSUES + Desription: I am unable to initialize a 2Gb SanDisk microSD card (in adaptor) on the + the mcu123 board. The card fails to accept CMD0. Doesn't seem like a software + issue, but if anyone else sees the problem, I'd like to know. + Related: Fixes were recently made for the SDIO-based MMC/SD driver to + support 2Gb cards -- the blocksize was forced to 512 in all cases. The SPI- + based driver may also have this problem (but I don't think this would have + anything to do with CMD0). + Status: Open + Priority: Uncertain + + Title: USB BROKEN? + Description: I tried to bring up the new configuration at configs/mcu123-214x/composite, + and Linux failed to enumerate the device. I don't know if this is + a problem with the lpc214x USB driver (bit rot), or due to recent + changed (e.g., -r4359 is suspicious), or an incompatibility between the + Composite driver and the LPC214x USB driver. It will take more work + to find out which -- like checking if the other USB configurations are + also broken. + Status: Open + Priority: It would be high if the LPC2148 were a current, main stream architecture. + I am not aware of anyone using LPC2148 now so I think the priority has + to be low. + +o ARM/LPC313x (arch/arm/src/lpc313x/) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: PLATFORM-SPECIFIC LOGIC + Description: arch/arm/src/lpc313x/lpc313x_spi.c contains logic that is specific to the + Embedded Artist's ea3131 board. We need to abstract the assignment of SPI + chip selects and logic SPI functions (like SPIDEV_FLASH). My thoughts are: + - Remove lpc313x_spiselect and lpc313x_spistatus from lpc313x_internal.h + - Remove configs/ea3131/src/up_spi.c + - Add configurations CONFIG_LPC3131x_CSOUT1DEV, CONFIG_LPC3131x_CSOUT2DEV, + and CONFIG_LPC3131x_CSOUT3DEV that maps the lpc313x SPI chip selects to + SPIDEV_* values. + - Change arch/arm/src/lpc313x/lpc313x_spi.c to use those configuration + settings. + Status: Open + Priority: High if you want to use SPI on any board other than the ea3131. + + Title: SPI DRIVER + Description: arch/arm/src/lpc313x/lpc313x_spi.c may or may not be functional. It was + reported to be working, but I was unable to get it working with the + Atmel at45dbxx serial FLASH driver. + Status: Open + Priority: High if you need to use SPI. + +o ARM/STR71x (arch/arm/src/str71x/) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: UNVERIFIED MMC SUPPORT + Description: Verify SPI driver and integrate with MMC support. This effort is stalled + at the moment because the slot on the Olimex board only accepts MMC card; + I have no MMC cards, only SD cards which won't fit into the slot. + Status: Open + Priority: Medium + + Title: NO USB DRIVER + Description: Develop a USB driver and integrate with existing USB serial and storage + class drivers. + Status: Open + Priority: Medium + + Title: SPI METHODS ARE NOT THREAD SAFE + Description: SPI methods are not thread safe. Needs a semaphore to protect from re-entrancy. + Status: Open + Priority: Medium -- Will be very high if you do SPI access from multiple threads. + +o ARM/LM3S6918 (arch/arm/src/lm3s/) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: I2C DRIVER + Description: Still need to implement I2C + Status: Open + Priority: Low + + Title: SSI OVERRUNS + Description: Should terminate SSI/SPI transfer if an Rx FIFO overrun occurs. + Right now, if an Rx FIFO overrun occurs, the SSI driver hangs. + Status: Open + Priority: Medium, If the transfer is properly tuned, then there should not + be any Rx FIFO overruns. + + Title: THTTPD BUGS + Description: There are some lingering bugs in THTTPD, possibly race conditions. This + is covered above under Network Utilities, but is duplicated here + to point out that the LM3S suffers from this bug. + Status: Open. + UPDATE: I have found that increasing the size of the CGI program stack + from 1024 to 2048 (on the LM3S) eliminates the problem. So the most + likely cause is probably a stack overflow, not a hard sofware bug. + Priority: Probably Low + +o ARM/STM32 (arch/arm/src/stm32/) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: NOR FLASH DRIVER + Description: NOR Flash driver with FTL layer to support a file system. + Status: Open + Priority: Low + + Title: USBSERIAL ISSUES + Description A USB device-side driver is in place but not well tested. At + present, the apps/examples/usbserial test sometimes fails. The situation + that causes the failure is: + + - Host-side of the test started after the target side sends the + first serial message. + + The general failure is as follows: + + - The target message pends in the endpoint packet memory + - When the host-side of the test is stated, it correctly + reads this pending data. + - an EP correct transfer interrupt occurs and the next + pending outgoing message is setup + - But, the host never receives the next message + + If the host-side driver is started before the first target message + is sent, the driver works fine. + Status: Open + Priority: Medium-High + + Title: FSMC EXTERNAL MEMORY UNTESTED + Description: FSMC external memory support is untested + Status: Open + Priority: Low + + Title: DMA EXTENSIONS + Description: DMA logic needs to be extended. DMA2, Channel 5, will not work + because the DMA2 channels 4 & 5 share the same interrupt. + Status: Open + Priority: Low until someone needs DMA1, Channel 5 (ADC3, UART4_TX, TIM5_CH1, or + TIM8_CH2). + + Title: UNFINISHED DRIVERS + Description: The following drivers are incomplete: DAC. The following drivers + are untested: DMA on the F4, CAN. + Status: Open + Priority: Medium + + Title: F4 SDIO MULTI-BLOCK TRANSFER FAILURES + Description: If you use a large I/O buffer to access the file system, then the + MMCSD driver will perform multiple block SD transfers. With DMA + ON, this seems to result in CRC errors detected by the hardware + during the transfer. Workaround: CONFIG_MMCSD_MULTIBLOCK_DISABLE=y. + Status: Open + Priority: Medium + + Title: DMA BOUNDARY CROSSING + Description: I see this statement in the reference manual: "The burst + configuration has to be selected in order to respect the AHB protocol, + where bursts must not cross the 1 KB address boundary because the + minimum address space that can be allocated to a single slave + is 1 KB. This means that the 1 KB address boundary should not be crossed + by a burst block transfer, otherwise an AHB error would be generated, + that is not reported by the DMA registers." + + The implication is that there may be some unenforced alignment + requirements for some DMAs. There is nothing in the DMA driver to + prevent this now. + Status: Open + Priority: Low (I am not even sure if this is a problem yet). + + Status: Unfinished STM32 F4 OTG FS Host Driver + Description: A quick-n-dirty leverage of the the LPC17xx host driver was put into + the STM32 source to support development of the STM32 F4 OTG FS host + driver. It is non-functional and still waiting for STM32 F4 logic + to be added. Don't use it! + Status: Open + Priority: Low (unless you need a host driver). + +o AVR (arch/avr) + ^^^^^^^^^^^^^^ + + Title: AMBER WEB SERVER UNTESTED + Description: There is a port for the Amber Web Server ATMega128, however this is + completely untested due to the lack to compatible, functional test + equipment. + Status: Open + Priority: The priority might as well be low since there is nothing I can do about + it anyway. + + Title: STRINGS IN RAM + Description: Many printf-intensive examples (such as the OS test) cannot be executed + on most AVR platforms. The reason is because these tests/examples + generate a lot of string data. The build system currently places all + string data in RAM and the string data can easily overflow the tiny + SRAMs on these parts. A solution would be to put the string data + into the more abundant FLASH memory, but this would require modification + to the printf logic to access the strings from program memory. + Status: Open + Priority: Low. The AVR is probably not the architecuture that you want to use + for extensive string operations. + + Title: SPI AND USB DRIVERS UNTESTED + Description: An SPI driver and a USB device driver exist for the AT90USB (as well + as a USB mass storage example). However, this configuration is not + fully debugged as of the NuttX-6.5 release. + Update 7/11: (1) The SPI/SD driver has been verified, however, (2) I + believe that the current teensy/usbstorage configuration uses too + much SRAM for the system to behave sanely. A lower memory footprint + version of the mass storage driver will be required before this can + be debugged + Status: Open + Priority: Medium-High. + + Title: AVR32 PORT IS NOT FULLY TESTED + Description: A complete port for the AVR32 is provided and has been partially + debugged. There may still be some issues with the serial port + driver. + Status: Open + Priority: Medium + +o Intel x86 (arch/x86) + ^^^^^^^^^^^^^^^^^^^^ + +o 8051 / MCS51 (arch/8051/) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: STACK OVERFLOWS DURING INTERRUPT HANDLING + Description: Current status: + - Basic OS task management seems OK + - Fails when interrupts enabled. The stack pointer is around + 0x6e before the failure occurs. It looks like some issue + when the stack pointer moves from the directly to indirectly + addressable region (0x80 boundary). + - Work on the 8052 is temporarily on hold + Status: Open + Priority: Low, 8051 is a tough platform because of the tiny stack. + + Title: TIMER 0 AS SYSTEM TIMER + Description: Use timer 0 as system timer. Timer 2 is needed for second UART. + Logic is implemented, but there needs to be a system + configuration to change the ticks-per-second value to match the + timer interrupt rate + Status: Open + Priority: Low + + Title: OVERFLOWS DURING BUILD + Description: During build, there are several integer overflows reported: + sched/gmtime_r.c aroud lines 184 and 185 + sched/clock_initialize.c at line 107 + sched/pthread_create.c at 330 + apps/examples/ostest/barrier.c around lines 53 and 74 + apps/examples/ostest/sighand.c at 225 and 244 + driver/serial.c in usleep calls around 347 and 354 + Status: Open. Update: These were reviewed during the hcs12 port. The + hcs12 also has 16-bit integer types (if -mshort is in the CFLAGS). + I believe that the warnings in most of the above have been fixed + but this has not been verified on this platform). + Priority: Medium + + Title: DATA INITIALIZATION + Description Global data is not being initialized. Logic like that of SDCCs + crt0*.s needs to be incorporated into the system boot logic + Status: Open + Priority: Low -- only because there as so many other issues with 8051 + +o MIPS/PIC32(arch/mips) + ^^^^^^^^^^^^^^^^^^^^^ + + Title: PIC32 USB DRIVER DOES NOT WORK WITH MASS STORAGE CLASS + UPDATE: ** ONLY USING RAM DISK FOR EXPORTED VOLUME *** + Description: The PIC32 USB driver either crashes or hangs when used with + the mass storage class when trying to write files to the target + storage device. This usually works with debug on, but does not + work with debug OFF (implying some race condition?) + + Here are some details of what I see in debugging: + + 1. The USB MSC device completes processing of a read request + and returns the read request to the driver. + 2. Before the MSC device can even begin the wait for the next + driver, many packets come in at interrupt level. The MSC + device goes to sleep (on pthread_cond_wait) with all of the + read buffers ready (16 in my test case). + 3. The pthread_cond_wait() does not wake up. This implies + a problem with pthread_con_wait(?). But in other cases, + the MSC device does wake up, but then immediately crashes + because its stack is bad. + 4. If I force the pthread_cond_wait to wake up (by using + pthread_cond_timedwait instead), then the thread wakes + up and crashes with a bad stack. + + So far, I have no clue why this is failing. + + UPDATE: This bug was recorded using the PIC32 Ethernet + Starter kit with a RAM disk (that board has no SD card slot). + Howevever, using the USB mass storage device with the + Mikroelektronika using a real SD card, there is no such + problem -- the mass storage device seems quite stable. + + UPDATE: Hmmm.. retesting with the Mikroelectronka board + shows problems again. I think that there are some subtle + timing bugs whose effects can very from innocuous to severe. + Status: Open + Priority: Originally, High BUT reduced to very Low based on the + UPDATED comments. + + Title: PIC32 USB MASS STORAGE DEVICE FAILS TO RE-CONNECT + Description: Found using configuration configs/pic32mx7mmb/nsh. + In this configuratin, the NSH 'msconn' command will connect the + mass storage device to the host; the 'msdis' command will + disconnect the device. The first 'msconn' works perfectly. + However, when attempting to re-connect, the second 'msconn' + command does not command properly: Windows reports an + unrecognized device. Apparently, some state is being properly + reset when the mass storage device is disconnected. Shouldn't + be hard to fix. + Status: Open + Priority: Medium + + Title: POSSIBLE INTERRUPT CONTROL ISSUE + Description: There is a kludge in the file arch/mips/src/common/up_idle.c. + Basically, if there is nothing else going on in the IDLE loop, + you have to disable then re-enable interrupts. Logically nothing + changes, but if you don't do this interrupts will be be disabled + in the IDLE loop which is a very bad thing to happen. + + Some odd behavior in the interrupt setup on the IDLE loop is + not really a big concern, but what I do not understand is if + this behavior is occurring on all threads after all context + switches: Are interrupts always disabled until re-enabled? + This requires some further investigation at some point; it + may be nothing but may also be a symptom of some changes + required to the interrupt return logic (perhaps some CP0 + status hazard?) + Status: Open + Priority: Low. Puzzling and needs some investigation, but there there + is no known misbehavior. + +o Hitachi/Renesas SH-1 (arch/sh/src/sh1) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: SH-1 IS UNUSABLE + Description: There are instabilities that make the SH-1 port un-usable. The + nature of these is not understood; the behavior is that certain SH-1 + instructions stop working as advertised. I have seen the following + examples: + + 412b jmp @r1 - Set a return address in PR, i.e., it behaved like + 410b jsr @r1. Normally 412b works correctly, but in the failure + condition, it reliably set the PR. + 69F6 mov.l @r15+,r9 - wrote the value of R1 to @r15+. This behavior + does not correspond to any known SH-1 instruction + + This could be a silicon problem, some pipeline issue that is not + handled properly by the gcc 3.4.5 toolchain (which has very limit + SH-1 support to begin with), or perhaps with the CMON debugger. At + any rate, I have exhausted all of the energy that I am willing to put + into this cool old processor for the time being. + + Update: This bug will probably never be addressed now. I just + cleaned house and my old SH-1 was one of the things that went. + + Status: Open + Priority: Low -- because the SH-1, SH7032, is very old and only of historical + interest. + +o Renesas M16C/26 (arch/sh/src/m16c) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: M16C DOES NOT BUILD + Description: The M16C target cannot be built. The GNU m16c-elf-ld link fails with + the following message: + + m32c-elf-ld: BFD (GNU Binutils) 2.19 assertion fail /home/Owner/projects/nuttx/buildroot/toolchain_build_m32c/binutils-2.19/bfd/elf32-m32c.c:482 + + Where the reference line is: + + /* If the symbol is out of range for a 16-bit address, + we must have allocated a plt entry. */ + BFD_ASSERT (*plt_offset != (bfd_vma) -1); + + No workaround is known at this time. + Status: Open + Priority: High -- this is a show stopper for M16C. + + Title: M16C PORT UNTESTED + Description: Coding of the initial port is complete, but is untested. + Status: Open + Priority: Low + + Title: NO SERIAL CONNECTOR + Description: Serial drivers were developed for the M16C, however, the SKP16C26 + StarterKit has no serial connectors. + Status: Open + Priority: Low + + Title: UNIMPLEMENTED M16C DRIVERS + Description: Should implement SPI, I2C, Virual EEPROM, FLASH, RTC drivers + Status: Open + Priority: Medium + +o z80/z8/ez80 (arch/z80) + ^^^^^^^^^^^^^^^^^^^^^^^ + + Title: SDCC INTEGER OVERFLOWS + Description: The SDCC version the same problems with integer overflow during + compilation as described for pjrc-8051. At typical cause is code like + usleep(500*1000) which exceeds the range of a 16-bit integer. + Status: See pjrc-8051. These have probably been fixed but have not yet + been verified on these platforms. + Priority: See pjrc-8051 + + Title: Z80 SIMULATED CONSOLE + Description: The simulated Z80 serial console (configs/z80sim/src/z80_serial.c + + driver/serial.c) does not work. This is because there are + no interrupts in the simulation so there is never any serial + traffic. + Status: Open + Priority: Low -- the simulated console is not critical path and the designs + to solve the problem are complex. + + Title: ZDS-II LIBRARIAN WARNINGS + Description: ZDS-II Librarian complains that the source for the .obj file + is not in the library. + Status: Open + Priority: Low, thought to be cosmetic. I think this is a consequence of + replacing vs. inserting the library. + + Title: ZDS-II COMPILER PROBLEMS + Description: The ZDS-II compiler (version 4.10.1) fails with an internal error + while compiler mm/mm_initialize. This has been reported as + incident 81509. + + I have found the following workaround that I use to build for the + time being: + + --- mm/mm_initialize.c.SAVE 2008-02-13 08:06:46.833857700 -0600 + +++ mm/mm_initialize.c 2008-02-13 08:07:26.367608900 -0600 + @@ -94,8 +94,11 @@ + { + int i; + + +#if 0 /* DO NOT CHECK IN */ + CHECK_ALLOCNODE_SIZE; + CHECK_FREENODE_SIZE; + +#endif + + /* Set up global variables */ + + Status: Open + Priority: High + + Title: EZ8 PRIORITY INTERRUPTS + Description: Add support for prioritized ez8 interrupts. Currently logic supports + only nominal interrupt priority. + Status: Open + Priority: Low + + Title: Z8ENCORE ONLY VERIFIED ON SIMULATOR + Description: The z8Encore! port has only been verified on the ZDS-II instruction + set simulator. + Status: Open + Priority: Medium + + Title: XTRS CLEAN + Description: The XTRS target (configs/xtrs) has a clean problem. The clean + rule removes .asm files. This works because there are no .asm + files except in sub-directories that are provided from 'make clean' -- + except for XTRS: It has a .asm file in its src/ directory that + gets removed everytime clean is performd. + Status: Open + Priority: High if you happen to be working with XTRS. + + Title: SPI/I2C UNTESTED + Description: A "generic" SPI and I2C drivers have been coded for the eZ80Acclaim! + However, these remains untested since I have no SPI or I2C devices for + the board (yet). + Status: Open + Priority: Med + + Title: SPI METHODS ARE NOT THREAD SAFE + Description: SPI methods are not thread safe. Needs a semaphore to protect from re-entrancy. + Status: Open + Priority: Medium -- Will be very high if you do SPI access from multiple threads. + + Title: I2C UNTESTED + Description: A "generic" I2C driver has been coded for the eZ8Encore! + However, this remains untested since I have no I2C devices for + the board (yet). + Status: Open + Priority: Med + +o z16 (arch/z16) +^^^^^^^^^^^^^^^^ + + Title: ZDS-II LIBRARIAN WARNINGS + Description: ZDS-II Librarian complains that the source for the .obj file + is not in the library. + Status: Open + Priority: Low, thought to be cosmetic. I think this is a consequence of + replacing vs. inserting the library. + + Title: SERIAL DRIVER HANGS + Description: When the interrupt-driven serial driver is used, the system + hangs. This is because of TX ready (TRDE) interrupts that + get lost while interrupts are disabled. The existing + serial driver appears to be limited to hardware with a + latching, level-sensitive TX ready interrupt. + Status: Open + Priority: Medium. A polled, write-only serial driver is used in the + interim for system testing. + + Title: SYSTEM DELAYS + Description: The system delays do not appear to be correct with the + apps/examples/ostest/timedmqueue.c test. + Status: Open + Priority: Medium-High + + Title: PROBLEMS WHEN DEBUG DISABLED + Description: At present, the z16f port does not run properly when CONFIG_DEBUG + is disabled: The obvious symptom is that there is no printf() + output. I have isolated with problem to errors in optimization. + With -reduceopt on the command line, I can get the printf output. + However, there are still errors in the compiled code -- specifically + in sched/timer_create.c. + + I have submitted a bug report to ZiLOG for this (support incident + 81400). You can see the status of the bug report (and lots more + technical detail) here: + http://support.zilog.com/support/incident/incident_support.asp?iIncidentId=81400&iSiteId=1&chLanguageCode=ENG + + Summary of ZiLOG analysis: "This is a ZNEO compiler problem. ... [a] workaround + is to replace: + if ( !timerid || (clockid != 0) ) + By: + if ((clockid != 0) || !timerid)" + + Status: Open + Priority: Medium-High + + Title: PASCAL ADD-ON + Description: The pascal add-on does not work with the z16f (that is + configuration z16f2800100zcog/pashello). This appears to be + another ZDS-II error: when executing the instruction + SYSIO 0, WRITESTR a large case statement is executed. This + involves a call into the ZiLOG runtime library to __uwcase(). + __uwcase is passed a pointer to a structure containing jump + information. The cause of the failure appears to be that + the referenced switch data is bad. + This is submited as ZiLOG support incident 81459. + + Summary of ZiLOG analysis: "This is a ZNEO run time library problem. + One workaround is to replace the line 58 in uwcase.asm + + From: + ADD R9,#4 ; Skip handler + To: + ADD R9,#2 ; Skip handler + + And add uwcase.asm to the project. + + If the customer does not want to modify uwcase.asm then the other + workaround is to add a dummy case and make it same as default: + + case 0x8000: + default: + + This will make sure that uwcase is not called but ulcase is called." + Status: Open. Due to licensing issues, I cannot include the modified + uwcase in the NuttX code base. + Priority: Medium + + Title: USE SPOV + Description: Add support to maintain SPOV in context switching. This + improvement will provide protection against stack overflow + and make a safer system solution. + Status: Open + Priority: Low + + Title: PRIORITIZED INTERRUPTS + Description: Add support for prioritized interrupts. Currently logic supports + only nominal interrupt priority. + Status: Open + Priority: Low + + Title: ZDS-II COMPILER PROBLEMS + Description: The file drivers/mmcsd/mmcsd_sdio.c generates an internal compiler + error like: + + mmcsd\mmcsd_sdio.c + Internal Error(0503) On line 2504 of "MMCSD\MMCSD_SDIO.C" + File , Args(562,46) + + Status: Open. Recommended workaround: remove mmcsd_sdio.c from + drivers/mmcsd/Make.defs. There is no SDIO support for the Z16 anyway + Priority: Low + +o mc68hc1x (arch/hc) + ^^^^^^^^^^^^^^^^^^ + + Title: BANKED MODE + Description: There is no script for building in banked mode (more correctly, there + is a script, but logic inside the script has not yet been implemented). + It would be necessary to implement banked mode to able to access more + the 48Kb of FLASH. + Status: Open. + Priority: Medium/Low + +o Network Utilities (apps/netutils/) + + Title: UIP RESOLVER + Description: One critical part of netutils/ apps is untested: The uIP + resolver in netutils/resolv. The webclient code has been + tested on host using gethosbyname(), but still depends on the + untested resolve logic. + Status: Open + Priority: Medium, Important but not core NuttX functionality + + Title: PPP PORT + Description: Port PPP support from http://contiki.cvs.sourceforge.net/contiki/contiki-2.x/backyard/core/net/ppp/ + Status: Open + Priority: Low + + Title: UNVERIFIED THTTPD FEATURES + Description: Not all THTTPD features/options have been verified. In particular, there is no + test case of a CGI program receiving POST input. Only the configuration of + apps/examples/thttpd has been tested. + Status: Open + Priority: Medium + + Title: THE ARP ISSUES AGAIN + Description: The first GET received by THTTPD is not responded to. Refreshing the page + from the browser solves the problem and THTTPD works fine after thatg. I + believe that this is the duplicate of another bug: "Outgoing [uIP] packets are dropped + and overwritten by ARP packets if the destination IP has not been mapped to a MAC." + Status: Open + Priority: Medium + + Title: THTTPD WARNINGS + Description: If the network is enabled, but THTTPD is not configured, it spews out lots + of pointless warnings. This is kind of annoying and unprofessional; needs to + be fixed someday. + Status: Open. An annoyance, but not a real problem. + Priority: Low + +o NuttShell (NSH) (apps/nshlib) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: WGET UNTESTED + Description: The wget command has been incorporated into NSH, however + it is still untested as of this writing (only because I + have not had the correct network setup for the testing + yet). Since wget depends on the also untest uIP resolv/ + logic, it is like non-functional. + Status: Open + Priority: Med-High + + Title: IFCONFIG AND MULTIPLE NETWORK INTERFACES + Descripton: The ifconfig command will not behave correctly if an interface + is provided and there are multiple interfaces. It should only + show status for the single interface on the command line; it will + still show status for all interfaces. + Status: Open + Priority: Low (multiple network interfaces not fully supported yet anyway). + + Title: RUN NXFLAT PROGRAMS + Description: Add support to NSH to run NXFLAT programs from a ROMFS file system + Status: Open + Priority: Low (enhancement) + + Title: ARP COMMAND + Description: Add an ARP command so that we can see the contents of the ARP table. + Status: Open + Priority: Low (enhancement) + + Title: MOUNT w/NO PARAMETERS + Description: Feature request: "A 'mount' without arguments should probably list + mounted filesystems as in Linux. + + nsh> mount + nsh_romfsimg on /etc type romfs (ro) + /dev/mtdblock0 on /home type vfat (rw) + Status: Open + Priority: Low (enhancement) + + Title: DF COMMAND + Description: Feature request: "It would be convenient to list the free space + on a filesystem with something like 'df'. + + nsh> df + Filesystem 1K-blocks Used Available Use% Mounted on + nsh_romfsimg 8 8 0 100% /etc + /dev/mtdblock0 3584 16 3568 1% /home + Status: Open + Priority: Low (enhancement) + +o System libraries apps/system (apps/system) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: READLINE IMPLEMENTATION + Description: readline implementation does not use C-buffered I/O, but rather + talks to serial driver directly via read(). It includes VT-100 + specific editting commands. A more generic readline() should be + implemented. + Status: Open + Priority: Low (unless you are using mixed C-buffered I/O with readline and + fgetc, for example). + +o Other Applications & Tests (apps/examples/) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Title: EXAMPLES/PIPE ON CYGWIN + Description: The redirection test (part of examples/pipe) terminates + incorrectly on the Cywgin-based simulation platform (but works + fine on the Linux-based simulation platform). + Status: Open + Priority: Low + + Title: EXAMPLES/WGET UNTESTED + Description: examples/wget is untested on the target (it has been tested + on the host, but not in the target using the uIP resolv logic). + Status: Open + Priority: Med + + Title: EXAMPLES/SENDMAIL UNTESTED + Description: examples/sendmail is untested on the target (it has been tested + on the host, but not on the target. + Status: Open + Priority: Med + + Title: EXAMPLES/NX FONT CACHING + Description: The font caching logic in examples/nx is incomplete. Fonts are + added to the cache, but never removed. When the cache is full + it stops rendering. This is not a problem for the examples/nx + code because it uses so few fonts, but if the logic were + leveraged for more general purposes, it would be a problem. + Update: see examples/nxtext for some improved font cache handling. + Status: Open + Priority: Low. This is not really a problem becauses examples/nx works + fine with its bogus font caching. + + Title: EXAMPLES/NXTEXT ARTIFACTS + Description: examples/nxtext. Artifacts when the pop-up window is opened. + There are some artifacts that appear in the upper left hand + corner. These seems to be related to window creation. At + tiny artifact would not be surprising (the initial window + should like at (0,0) and be of size (1,1)), but sometimes + the artifact is larger. + Status: Open + Priority: Medium. diff --git a/nuttx/arch/Kconfig b/nuttx/arch/Kconfig new file mode 100644 index 0000000000..253151a3bc --- /dev/null +++ b/nuttx/arch/Kconfig @@ -0,0 +1,92 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +choice + prompt "CPU Architecture" + default ARCH_ARM + +config ARCH_8051 + bool "8051" + ---help--- + Intel 8051 architectures and derivaties + +config ARCH_ARM + bool "ARM" + ---help--- + The ARM architectures + +config ARCH_AVR + bool "AVR" + ---help--- + Atmel 9-bit bit AVR and 32-bit AVR32 architectures + +config ARCH_HC + bool "Freescale HC" + ---help--- + Freescale HC architectures (M9S12) + +config ARCH_MIPS + bool "MIPS" + ---help--- + MIPS architectures (PIC32) + +config ARCH_RGMP + bool "RGMP" + ---help--- + RTOS and GPOS on Multi-Processor (RGMP) architecture. See + http://rgmp.sourceforge.net/wiki/index.php/Main_Page. + +config ARCH_SH + bool "Rensas" + ---help--- + Renesas architectures (SH and M16C). + +config ARCH_SIM + bool "Simulation" + ---help--- + Linux/Cywgin user-mode simulation. + +config ARCH_X86 + bool "x86" + ---help--- + Intel x86 architectures. + +config ARCH_Z16 + bool "ZNEO" + ---help--- + ZiLOG ZNEO 16-bit architectures (z16f). + +config ARCH_Z80 + bool "z80" + ---help--- + ZiLOG 8-bit architectures (z80, ez80, z8). + +endchoice + +config ARCH + string + default "8051" if ARCH_8051 + default "arm" if ARCH_ARM + default "avr" if ARCH_AVR + default "hc" if ARCH_HC + default "mips" if ARCH_MIPS + default "rgmp" if ARCH_RGMP + default "sh" if ARCH_SH + default "sim" if ARCH_SIM + default "x86" if ARCH_X86 + default "z16" if ARCH_Z16 + default "z80" if ARCH_Z80 + +source arch/8051/Kconfig +source arch/arm/Kconfig +source arch/avr/Kconfig +source arch/hc/Kconfig +source arch/mips/Kconfig +source arch/rgmp/Kconfig +source arch/sh/Kconfig +source arch/sim/Kconfig +source arch/x86/Kconfig +source arch/z16/Kconfig +source arch/z80/Kconfig diff --git a/nuttx/arch/README.txt b/nuttx/arch/README.txt new file mode 100644 index 0000000000..67b99b255d --- /dev/null +++ b/nuttx/arch/README.txt @@ -0,0 +1,339 @@ +Architecture-Specific Code +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Table of Contents +^^^^^^^^^^^^^^^^^ + + o Architecture-Specific Code + o Summary of Files + o Supported Architectures + o Configuring NuttX + +Architecture-Specific Code +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The NuttX configuration consists of: + +o Processor architecture specific files. These are the files contained + in the arch// directory discussed in this README. + +o Chip/SoC specific files. Each processor processor architecture + is embedded in chip or System-on-a-Chip (SoC) architecture. The + full chip architecture includes the processor architecture plus + chip-specific interrupt logic, general purpose I/O (GIO) logic, and + specialized, internal peripherals (such as UARTs, USB, etc.). + + These chip-specific files are contained within chip-specific + sub-directories in the arch// directory and are selected + via the CONFIG_ARCH_name selection + +o Board specific files. In order to be usable, the chip must be + contained in a board environment. The board configuration defines + additional properties of the board including such things as + peripheral LEDs, external peripherals (such as network, USB, etc.). + + These board-specific configuration files can be found in the + configs// sub-directories. + +This README will address the processor architecture specific files +that are contained in the arch// directory. The file +include/nuttx/arch.h identifies all of the APIs that must +be provided by this architecture specific logic. (It also includes +arch//arch.h as described below). + +Directory Structure +^^^^^^^^^^^^^^^^^^^ + +The arch directory contains architecture specific logic. The complete +board port in is defined by the architecture-specific code in this +directory (plus the board-specific configurations in the config/ +subdirectory). Each architecture must provide a subdirectory +under arch/ with the following characteristics: + + + / + |-- include/ + | |--/ + | | `-- (chip-specific header files) + | |--/ + | |-- arch.h + | |-- irq.h + | `-- types.h + `-- src/ + |--/ + | `-- (chip-specific source files) + |--/ + |-- Makefile + `-- (architecture-specific source files) + +Summary of Files +^^^^^^^^^^^^^^^^ + +include// + This sub-directory contains chip-specific header files. + +include/arch.h + This is a hook for any architecture specific definitions that may + be needed by the system. It is included by include/nuttx/arch.h + +include/types.h + This provides architecture/toolchain-specific definitions for + standard types. This file should typedef: + + _int8_t, _uint8_t, _int16_t, _uint16_t, _int32_t, _uint32_t + + and if the architecture supports 64-bit integers. + + _int24_t, _uint24_t, int64_t, uint64_t + + NOTE that these type names have a leading underscore character. This + file will be included(indirectly) by include/stdint.h and typedef'ed to + the final name without the underscore character. This roundabout way of + doings things allows the stdint.h to be removed from the include/ + directory in the event that the user prefers to use the definitions + provided by their toolchain header files + + irqstate_t + + Must be defined to the be the size required to hold the interrupt + enable/disable state. + + This file will be included by include/sys/types.h and be made + available to all files. + +include/irq.h + This file needs to define some architecture specific functions (usually + inline if the compiler supports inlining) and structure. These include: + + - struct xcptcontext. This structures represents the saved context + of a thread. + + - irqstate_t irqsave(void) -- Used to disable all interrupts. + + - void irqrestore(irqstate_t flags) -- Used to restore interrupt + enables to the same state as before irqsave was called. + + This file must also define NR_IRQS, the total number of IRQs supported + by the board. + +src// + This sub-directory contains chip-specific source files. + +src/Makefile + This makefile will be executed to build the targets src/libup.a and + src/up_head.o. The up_head.o file holds the entry point into the system + (power-on reset entry point, for example). It will be used in + the final link with libup.a and other system archives to generate the + final executable. + +Supported Architectures +^^^^^^^^^^^^^^^^^^^^^^^ + +arch/sim - Linux/Cygwin simulation + A user-mode port of NuttX to the x86 Linux platform is available. + The purpose of this port is primarily to support OS feature development. + This port does not support interrupts or a real timer (and hence no + round robin scheduler) Otherwise, it is complete. + +arch/arm - ARM-based micro-controllers + This directory holds common ARM architectures. At present, this includes + the following subdirectories: + + arch/arm/include and arch/arm/src/common + Common ARM/Cortex-M3 logic. + + arch/arm/src/arm and arch/arm/include/arm + Common ARM-specific logic + + arch/arm/src/armv7-m and arch/arm/include/armv7-m + Common ARMv7-M logic (Cortex-M3 and Cortex-M4) + + arch/arm/include/c5471 and arch/arm/src/c5471 + TI TMS320C5471 (also called TMS320DM180 or just C5471). + NuttX operates on the ARM7 of this dual core processor. This port + complete, verified, and included in the NuttX release 0.1.1. + + arch/arm/include/calypso and arch/arm/src/calypso + TI "Calypso" MCU used in various cell phones (and, in particular, + by the Osmocom-bb project). Like the c5471, NuttX operates on the + ARM7 of this dual core processor. This port was contributed by + Denis Carilki and includes the work of Denis, Alan Carvalho de Assis, + and Stefan Richter. Calypso support first appeared in NuttX-6.17. + + arch/arm/include/dm320 and arch/arm/src/dm320 + TI TMS320DM320 (also called just DM320). + NuttX operates on the ARM9EJS of this dual core processor. This port + complete, verified, and included in the NuttX release 0.2.1. + + arch/arm/include/imx and arch/arm/src/imx + Freescale MC9328MX1 or i.MX1. This port uses the Freescale MX1ADS + development board with a GNU arm-elf toolchain* under either Linux or Cygwin. + STATUS: This port has stalled because of development tool issues. Coding + is complete on the basic port (timer, serial console, SPI). + + arch/arm/include/lm3s and arch/arm/src/lm3s + These directories contain support for the Luminary LMS family, particularly + for the LM3S6918. The initial, release of this port was included in NuttX version + 0.4.6. The current port includes timer, serial console, Ethernet, SSI, and microSD + support. There are working configurations the NuttX OS test, to run the NuttShell + (NSH), the NuttX networking test, and the uIP web server. + + arch/arm/include/lpc214x and arch/arm/src/lpc214x + These directories provide support for NXP LPC214x family of + ARM7TDMI processors. This port boots and passes the OS test (examples/ostest). + The port is complete and verifed. As of NuttX 0.3.17, the port includes: + timer interrupts, serial console, USB driver, and SPI-based MMC/SD card + support. A verifed NuttShell (NSH) configuration is also available. + + arch/arm/include/lpc2378 and arch/arm/src/lpc2378. + NXP LPC2378. Support is provided for the NXP LPC2378 MCU. This port was + contributed by Rommel Marcelo is was first released in NuttX-5.3. + STATUS: This port boots and passes the OS test (examples/ostest) and + includes a working implementation of the NuttShell (NSH). The port is + complete and verified. As of NuttX 5.3, the port includes only basic + timer interrupts and serial console support. + + arch/arm/include/lpc31xx and arch/arm/src/lpc31xx + These directories provide support for NXP LPC31xx family of + ARM926EJ-S processors. The port for the NXP LPC3131 was first + released in NuttX-5.1 (but was not functional until NuttX-5.2). + STATUS: The basic EA3131 port is complete and verified in NuttX-5.2 + This basic port includes basic boot-up, serial console, and timer + interrupts. This port was extended in NuttX 5.3 with a USB high + speed driver contributed by David Hewson. This port has been + verified using the NuttX OS test, USB serial and mass storage tests + and includes a working implementation of the NuttShell ((NSH)). + + This port was later extended to support additional members of the + LPC31xx family including, specifically, the LPC3152. + + arch/arm/include/sam3u and arch/arm/src/sam3u + Atmel AT91SAM3U. This port is for Atmel AT91SAM3U4E MCU. + STATUS: The basic AT91SAM3U port was released in NuttX version 5.1. + The basic port includes boot-up logic, interrupt driven serial + console, and system timer interrupts. That release passes the + NuttX OS test and is proven to have a valid OS implementation. A + onfiguration to support the NuttShell is also included. + + arch/arm/include/stm32 and arch/arm/src/stm32 + These directories contain support for the STMicro STM32 F1, F2, and + F4 families. + + STATUS: The basic STM32 F1 port was released in NuttX version 0.4.12. + and has continued to develop consistently over time. It now includes + support for the F2 and F4 families and a rich offering of peripheral + drivers. + + arch/arm/include/str71x and arch/arm/src/str71x + These directories provide support for the STMicro STR71x processors. + Coding is complete on the basic port (boot logic, system time, serial console), + but no testing has been performed due to some problems I am having with my + JTAG wiggler and OpenOCD on Linux. + +arch/avr + This directory is dedicated to ports to the Atmel AVR (8-bit) and AVR32 (32-bit) + MCU families. STATUS: Under development. + + arch/avr/include/avr and arch/avr/src/avr + Common support for all 8-bit VR MCUs + + arch/avr/include/atmega and arch/avr/src/atmega + Support specifically for the AVR ATMega family (specifically only for + the ATMega128 at the moment). + + arch/avr/include/at90usb and arch/avr/src/at90usb + Support specifically for the AVR AT90USB646, 647, 1286, and 1287 family. + + arch/avr/include/avr32 and arch/avr/src/avr32 + Common support for all AVR32 MCUs + + arch/avr/include/at32uc3 and arch/avr/src/at32uc3 + Support specifically for the AT32UC3Bxxx family (specifically only for + the AT32UC3B0256 at the moment). + +arch/hc + This directory is dedicated to ports to the Freescale HC family. + + arch/arm/include/m9s12 and arch/arm/src/m9s12 + These directories provide support for the Freescale mc9s12x family. + STATUS: Fragments of this port were first released in nuttx-5.0 and + the port was "code-complete" as nuttx-5.18. However, the final + verification effort has been stalled because of higher priority tasks. + +arch/m68322 + A work in progress. + STATUS: Stalled for the time being. + +arch/mips + This directory is dedicated to ports to the MIPS family. + + arch/mips/include/mips32 and arch/mips/src/mips32 + Common support for all MIPS32 architectures + + arch/mips/include/pic32mx and arch/mips/src/pic32mx + Support for all MicroChip PIC32MX architectures + +arch/rgmp + + RGMP stands for RTOS and GPOS on Multi-Processor. RGMP is a project + for running GPOS and RTOS simultaneously on multi-processor platforms. + You can port your favorite RTOS to RGMP together with an unmodified + Linux to form a hybrid operating system. This makes your application + able to use both RTOS and GPOS features. + + See http://rgmp.sourceforge.net/wiki/index.php/Main_Page for further + information about RGMP. + +arch/sh - SuperH and related Hitachi/Renesas microcontrollers + + arch/sh/include and arch/sh/src/common + Common SuperH logic. + + arch/sh/include/shs and arch/sh/src/sh1 + Support for the SH-1 processor. + +arch/8051 - 8051/52 microcontrollers + 8051 Microcontroller. This port is not quite ready for prime time. + +arch/x86 - Intel x86 architectures + This directory holds related, 32- and 64-bit architectures from Intel. + At present, this includes the following subdirectories: + + arch/x86/include and arch/x86/src/common + Common x86 logic. + + arch/x86/include/i486 and arch/x86/src/i486 + These directories hold definitions and logic appropriate for any + instantiation of the 32-bit i486 architecture. + + arch/x86/include/qemu and arch/x86/src/qemu + This is the implementation of NuttX on the QEMU x86 simulation. + +arch/z16 - ZiLOG 16-bit processors + This directory holds related, 16-bit architectures from ZiLOG. At + present, this includes the following subdirectories: + + arch/z16/include and arch/z16/src/common + Common microcontroller logic. + + arch/z16/include/z16f and arch/z16/src/z16f + ZiLOG z16f Microcontroller. + STATUS: Released in nuttx-0.3.7. Fully functional other than issues + addressed in ${TOPDIR}/TODO. + +arch/z80 - ZiLOG 8-bit microcontrollers + This directory holds related, 8-bit architectures from ZiLOG. At + present, this includes the following subdirectories: + + arch/z80/include and arch/z80/src/common + Common microcontroller logic. + + arch/z80/include/z80 and arch/z80/src/z80 + Classic ZiLOG z80 Microcontroller. + STATUS: Functional with no known defects. There are still several + OS features that have not yet been tested (e.g., networking). + + arch/z80/include/z8 and arch/z80/src/z8 + ZiLOG Z8Encore! Microcontroller + + arch/z80/include/ez80 and arch/z80/src/ez80 + ZiLOG ez80 Acclaim! Microcontroller diff --git a/nuttx/arch/arm/Kconfig b/nuttx/arch/arm/Kconfig new file mode 100644 index 0000000000..40dcb11059 --- /dev/null +++ b/nuttx/arch/arm/Kconfig @@ -0,0 +1,206 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +if ARCH_ARM +choice + prompt "ARM chip selection" + default ARCH_CHIP_STM32 + +config ARCH_CHIP_C5471 + bool "TMS320 C5471" + ---help--- + TI TMS320 C5471, A180, or DA180 (ARM7TDMI) + +config ARCH_CHIP_CALYPSO + bool "Calypso" + ---help--- + TI Calypso-based cell phones (ARM7TDMI) + +config ARCH_CHIP_DM320 + bool "TMS320 DM320" + ---help--- + TI DMS320 DM320 (ARM926EJS) + +config ARCH_CHIP_IMX + bool "Freescale iMX" + ---help--- + Freescale iMX architectures (ARM920T) + +config ARCH_CHIP_KINETIS + bool "Freescale Kinetis" + ---help--- + Freescale Kinetis Architectures (ARM Cortex-M4) + +config ARCH_CHIP_LM3S + bool "TI Stellaris" + ---help--- + TI Stellaris LMS3 architecutres (ARM Cortex-M3) + +config ARCH_CHIP_LPC17XX + bool "NXP LPC17xx" + ---help--- + NXP LPC17xx architectures (ARM Cortex-M3) + +config ARCH_CHIP_LPC214X + bool "NXP LPC214x" + ---help--- + NXP LPC2145x architectures (ARM7TDMI) + +config ARCH_CHIP_LPC2378 + bool "NXP LPC2378" + ---help--- + NXP LPC2145x architectures (ARM7TDMI) + +config ARCH_CHIP_LPC31XX + bool "NXP LPC31XX" + ---help--- + NPX LPC31XX architectures (ARM926EJS). + +config ARCH_CHIP_LPC43XX + bool "NXP LPC43XX" + ---help--- + NPX LPC43XX architectures (ARM Cortex-M4). + +config ARCH_CHIP_SAM3U + bool "Atmel AT91SAM3U" + ---help--- + Atmel AT91SAM3U architectures (ARM Cortex-M3) + +config ARCH_CHIP_STM32 + bool "STMicro STM32" + ---help--- + STMicro STM32 architectures (ARM Cortex-M3/4). + +config ARCH_CHIP_STR71X + bool "STMicro STR71x" + ---help--- + STMicro STR71x architectures (ARM7TDMI). + +endchoice + +config ARCH_ARM7TDMI + bool + default y if ARCH_CHIP_C5471 || ARCH_CHIP_CALYPSO || ARCH_CHIP_LPC214X || ARCH_CHIP_LPC2378 || ARCH_CHIP_STR71X + +config ARCH_ARM926EJS + bool + default y if ARCH_CHIP_DM320 || ARCH_CHIP_LPC31XX + +config ARCH_ARM920T + bool + default y if ARCH_CHIP_IMX + +config ARCH_CORTEXM + bool + default y if ARCH_CHIP_KINETIS || ARCH_CHIP_LM3S || ARCH_CHIP_LPC17XX || ARCH_CHIP_LPC43XX || ARCH_CHIP_SAM3U || ARCH_CHIP_STM32 + +config ARCH_FAMILY + string + default "arm" if ARCH_ARM7TDMI || ARCH_ARM926EJS || ARCH_ARM920T + default "armv7-m" if ARCH_CORTEXM + +config ARCH_CHIP + string + default "c5471" if ARCH_CHIP_C5471 + default "calypso" if ARCH_CHIP_CALYPSO + default "dm320" if ARCH_CHIP_DM320 + default "imx" if ARCH_CHIP_IMX + default "kinetis" if ARCH_CHIP_KINETIS + default "lm3s" if ARCH_CHIP_LM3S + default "lpc17x" if ARCH_CHIP_LPC17XX + default "lpc214x" if ARCH_CHIP_LPC214X + default "lpc2378" if ARCH_CHIP_LPC2378 + default "lpc31xx" if ARCH_CHIP_LPC31XX + default "lpc43xx" if ARCH_CHIP_LPC43XX + default "sam3u" if ARCH_CHIP_SAM3U + default "stm32" if ARCH_CHIP_STM32 + default "str71x" if ARCH_CHIP_STR71X + +config ARCH_STACKDUMP + bool "Dump stack on assertions" + default n + ---help--- + Enable to do stack dumps after assertions + +config ARCH_LEDS + bool "Use board LEDs to show state" + default y + ---help--- + Use LEDs to show state. Unique to boards that have LEDs + +config ARCH_INTERRUPTSTACK + bool "Use interrupt stack" + default y + ---help--- + This architecture supports an interrupt stack. If defined, this symbol + is the size of the interrupt stack in bytes. If not defined, the user + task stacks will be used during interrupt handling. + +config ARCH_IRQPRIO + bool "Interrupt priority" + default y if ARCH_CORTEXM + ---help--- + Select if your board supports interrupt prioritization. + +config ARCH_LOOPSPERMSEC + int "Delay loops per millisecond" + default 5000 + ---help--- + Delay loops nust be calibrated for correct operation. + +config ARCH_CALIBRATION + bool "Calibrate delay loop" + default n + ---help--- + Enables some built in instrumentation that causes a 100 second delay + during boot-up. This 100 second delay serves no purpose other than it + allows you to calibratre ARCH_LOOPSPERMSEC. You simply use a stop + watch to measure the 100 second delay then adjust ARCH_LOOPSPERMSEC until + the delay actually is 100 seconds. + +if ARCH_CHIP_C5471 +source arch/arm/src/c5471/Kconfig +endif +if ARCH_CHIP_CALYPSO +source arch/arm/src/calypso/Kconfig +endif +if ARCH_CHIP_DM320 +source arch/arm/src/dm320/Kconfig +endif +if ARCH_CHIP_IMX +source arch/arm/src/imx/Kconfig +endif +if ARCH_CHIP_KINETIS +source arch/arm/src/kinetis/Kconfig +endif +if ARCH_CHIP_LM3S +source arch/arm/src/lm3s/Kconfig +endif +if ARCH_CHIP_LPC17XX +source arch/arm/src/lpc17xx/Kconfig +endif +if ARCH_CHIP_LPC214X +source arch/arm/src/lpc214x/Kconfig +endif +if ARCH_CHIP_LPC2378 +source arch/arm/src/lpc2378/Kconfig +endif +if ARCH_CHIP_LPC31XX +source arch/arm/src/lpc31xx/Kconfig +endif +if ARCH_CHIP_LPC43XX +source arch/arm/src/lpc43xx/Kconfig +endif +if ARCH_CHIP_SAM3U +source arch/arm/src/sam3u/Kconfig +endif +if ARCH_CHIP_STM32 +source arch/arm/src/stm32/Kconfig +endif +if ARCH_CHIP_STR71X +source arch/arm/src/str71x/Kconfig +endif + +endif diff --git a/nuttx/arch/arm/include/arch.h b/nuttx/arch/arm/include/arch.h new file mode 100644 index 0000000000..dd750ad77a --- /dev/null +++ b/nuttx/arch/arm/include/arch.h @@ -0,0 +1,122 @@ +/**************************************************************************** + * arch/arm/include/arch.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, + * only indirectly through nuttx/arch.h + */ + +#ifndef __ARCH_ARM_INCLUDE_ARCH_H +#define __ARCH_ARM_INCLUDE_ARCH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#ifdef CONFIG_PIC + +/* This identifies the register the is used by the processor as the PIC base + * register. It is usually r9 or r10 + */ + +#define PIC_REG r10 +#define PIC_REG_STRING "r10" + +/* Macros to get and set the PIC base register. picbase is assumed to be + * of type (void*) and that it will fit into a uint32_t. These must be + * inline so that they will be compatible with the ABIs rules for + * preserving the PIC register + */ + +#define up_getpicbase(ppicbase) \ +do { \ + uint32_t picbase; \ + __asm__ \ + ( \ + "\tmov %0, " PIC_REG_STRING "\n\t" \ + : "=r"(picbase) \ + ); \ + *ppicbase = (FAR void*)picbase; \ +} while (0) + +#define up_setpicbase(picbase) \ +do { \ + uint32_t _picbase = (uint32_t)picbase; \ + __asm__ \ + ( \ + "\tmov " PIC_REG_STRING ", %0\n\t" \ + : : "r"(_picbase) : PIC_REG_STRING \ + ); \ +} while (0) + +#endif + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ARCH_ARM_INCLUDE_ARCH_H */ diff --git a/nuttx/arch/arm/include/arm/irq.h b/nuttx/arch/arm/include/arm/irq.h new file mode 100644 index 0000000000..6b4f05539a --- /dev/null +++ b/nuttx/arch/arm/include/arm/irq.h @@ -0,0 +1,231 @@ +/**************************************************************************** + * arch/arm/include/arm/irq.h + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_ARM_IRQ_H +#define __ARCH_ARM_INCLUDE_ARM_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* IRQ Stack Frame Format: + * + * Context is always saved/restored in the same way: + * + * (1) stmia rx, {r0-r14} + * (2) then the PC and CPSR + * + * This results in the following set of indices that + * can be used to access individual registers in the + * xcp.regs array: + */ + +#define REG_R0 (0) +#define REG_R1 (1) +#define REG_R2 (2) +#define REG_R3 (3) +#define REG_R4 (4) +#define REG_R5 (5) +#define REG_R6 (6) +#define REG_R7 (7) +#define REG_R8 (8) +#define REG_R9 (9) +#define REG_R10 (10) +#define REG_R11 (11) +#define REG_R12 (12) +#define REG_R13 (13) +#define REG_R14 (14) +#define REG_R15 (15) +#define REG_CPSR (16) + +#define XCPTCONTEXT_REGS (17) +#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS) + +#define REG_A1 REG_R0 +#define REG_A2 REG_R1 +#define REG_A3 REG_R2 +#define REG_A4 REG_R3 +#define REG_V1 REG_R4 +#define REG_V2 REG_R5 +#define REG_V3 REG_R6 +#define REG_V4 REG_R7 +#define REG_V5 REG_R8 +#define REG_V6 REG_R9 +#define REG_V7 REG_R10 +#define REG_SB REG_R9 +#define REG_SL REG_R10 +#define REG_FP REG_R11 +#define REG_IP REG_R12 +#define REG_SP REG_R13 +#define REG_LR REG_R14 +#define REG_PC REG_R15 + +/* The PIC register is usually R10. It can be R9 is stack checking is enabled + * or if the user changes it with -mpic-register on the GCC command line. + */ + +#define REG_PIC REG_R10 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This struct defines the way the registers are stored. We + * need to save: + * + * 1 CPSR + * 7 Static registers, v1-v7 (aka r4-r10) + * 1 Frame pointer, fp (aka r11) + * 1 Stack pointer, sp (aka r13) + * 1 Return address, lr (aka r14) + * --- + * 11 (XCPTCONTEXT_USER_REG) + * + * On interrupts, we also need to save: + * 4 Volatile registers, a1-a4 (aka r0-r3) + * 1 Scratch Register, ip (aka r12) + *--- + * 5 (XCPTCONTEXT_IRQ_REGS) + * + * For a total of 17 (XCPTCONTEXT_REGS) + */ + +#ifndef __ASSEMBLY__ +struct xcptcontext +{ + /* The following function pointer is non-zero if there + * are pending signals to be processed. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + void *sigdeliver; /* Actual type is sig_deliver_t */ + + /* These are saved copies of LR and CPSR used during + * signal processing. + */ + + uint32_t saved_pc; + uint32_t saved_cpsr; +#endif + + /* Register save area */ + + uint32_t regs[XCPTCONTEXT_REGS]; + + /* Extra fault address register saved for common paging logic. In the + * case of the prefetch abort, this value is the same as regs[REG_R15]; + * For the case of the data abort, this value is the value of the fault + * address register (FAR) at the time of data abort exception. + */ + +#ifdef CONFIG_PAGING + uintptr_t far; +#endif +}; +#endif + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Save the current interrupt enable state & disable IRQs */ + +static inline irqstate_t irqsave(void) +{ + unsigned int flags; + unsigned int temp; + __asm__ __volatile__ + ( + "\tmrs %0, cpsr\n" + "\torr %1, %0, #128\n" + "\tmsr cpsr_c, %1" + : "=r" (flags), "=r" (temp) + : + : "memory"); + return flags; +} + +/* Restore saved IRQ & FIQ state */ + +static inline void irqrestore(irqstate_t flags) +{ + __asm__ __volatile__ + ( + "msr cpsr_c, %0" + : + : "r" (flags) + : "memory"); +} +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_ARM_IRQ_H */ + diff --git a/nuttx/arch/arm/include/arm/syscall.h b/nuttx/arch/arm/include/arm/syscall.h new file mode 100644 index 0000000000..e06de1a3c2 --- /dev/null +++ b/nuttx/arch/arm/include/arm/syscall.h @@ -0,0 +1,243 @@ +/**************************************************************************** + * arch/arm/include/arm/syscall.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through include/syscall.h or include/sys/sycall.h + */ + +#ifndef __ARCH_ARM_INCLUDE_ARM_SYSCALL_H +#define __ARCH_ARM_INCLUDE_ARM_SYSCALL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#define SYS_syscall 0x900001 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* SWI with SYS_ call number and no parameters */ + +static inline uintptr_t sys_call0(unsigned int nbr) +{ + register long reg0 __asm__("r0") = (long)(nbr); + + __asm__ __volatile__ + ( + "swi %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0) + : "memory" + ); + + return reg0; +} + +/* SWI with SYS_ call number and one parameter */ + +static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1) +{ + register long reg0 __asm__("r0") = (long)(nbr); + register long reg1 __asm__("r1") = (long)(parm1); + + __asm__ __volatile__ + ( + "swi %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1) + : "memory" + ); + + return reg0; +} + +/* SWI with SYS_ call number and two parameters */ + +static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2) +{ + register long reg0 __asm__("r0") = (long)(nbr); + register long reg2 __asm__("r2") = (long)(parm2); + register long reg1 __asm__("r1") = (long)(parm1); + + __asm__ __volatile__ + ( + "swi %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2) + : "memory" + ); + + return reg0; +} + +/* SWI with SYS_ call number and three parameters */ + +static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3) +{ + register long reg0 __asm__("r0") = (long)(nbr); + register long reg3 __asm__("r3") = (long)(parm3); + register long reg2 __asm__("r2") = (long)(parm2); + register long reg1 __asm__("r1") = (long)(parm1); + + __asm__ __volatile__ + ( + "swi %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), "r"(reg3) + : "memory" + ); + + return reg0; +} + +/* SWI with SYS_ call number and four parameters */ + +static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3, + uintptr_t parm4) +{ + register long reg0 __asm__("r0") = (long)(nbr); + register long reg4 __asm__("r4") = (long)(parm4); + register long reg3 __asm__("r3") = (long)(parm3); + register long reg2 __asm__("r2") = (long)(parm2); + register long reg1 __asm__("r1") = (long)(parm1); + + __asm__ __volatile__ + ( + "swi %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), + "r"(reg3), "r"(reg4) + : "memory" + ); + + return reg0; +} + +/* SWI with SYS_ call number and five parameters */ + +static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3, + uintptr_t parm4, uintptr_t parm5) +{ + register long reg0 __asm__("r0") = (long)(nbr); + register long reg5 __asm__("r5") = (long)(parm5); + register long reg4 __asm__("r4") = (long)(parm4); + register long reg3 __asm__("r3") = (long)(parm3); + register long reg2 __asm__("r2") = (long)(parm2); + register long reg1 __asm__("r1") = (long)(parm1); + + __asm__ __volatile__ + ( + "swi %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), + "r"(reg3), "r"(reg4), "r"(reg5) + : "memory" + ); + + return reg0; +} + +/* SWI with SYS_ call number and six parameters */ + +static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3, + uintptr_t parm4, uintptr_t parm5, + uintptr_t parm6) +{ + register long reg0 __asm__("r0") = (long)(nbr); + register long reg6 __asm__("r6") = (long)(parm6); + register long reg5 __asm__("r5") = (long)(parm5); + register long reg4 __asm__("r4") = (long)(parm4); + register long reg3 __asm__("r3") = (long)(parm3); + register long reg2 __asm__("r2") = (long)(parm2); + register long reg1 __asm__("r1") = (long)(parm1); + + __asm__ __volatile__ + ( + "swi %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), + "r"(reg3), "r"(reg4), "r"(reg5), "r"(reg6) + : "memory" + ); + + return reg0; +} + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_INCLUDE_ARM_SYSCALL_H */ + diff --git a/nuttx/arch/arm/include/armv7-m/irq.h b/nuttx/arch/arm/include/armv7-m/irq.h new file mode 100644 index 0000000000..6cef85c02a --- /dev/null +++ b/nuttx/arch/arm/include/armv7-m/irq.h @@ -0,0 +1,306 @@ +/**************************************************************************** + * arch/arm/include/armv7-m/irq.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_H +#define __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#ifndef __ASSEMBLY__ +# include +#endif + +/* Included implementation-dependent register save structure layouts */ + +#ifdef CONFIG_ARMV7M_CMNVECTOR +# include +#else +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Alternate register names */ + +#define REG_A1 REG_R0 +#define REG_A2 REG_R1 +#define REG_A3 REG_R2 +#define REG_A4 REG_R3 +#define REG_V1 REG_R4 +#define REG_V2 REG_R5 +#define REG_V3 REG_R6 +#define REG_V4 REG_R7 +#define REG_V5 REG_R8 +#define REG_V6 REG_R9 +#define REG_V7 REG_R10 +#define REG_SB REG_R9 +#define REG_SL REG_R10 +#define REG_FP REG_R11 +#define REG_IP REG_R12 +#define REG_SP REG_R13 +#define REG_LR REG_R14 +#define REG_PC REG_R15 + +/* The PIC register is usually R10. It can be R9 is stack checking is enabled + * or if the user changes it with -mpic-register on the GCC command line. + */ + +#define REG_PIC REG_R10 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The following structure is included in the TCB and defines the complete + * state of the thread. + */ + +#ifndef __ASSEMBLY__ +struct xcptcontext +{ + /* The following function pointer is non-zero if there + * are pending signals to be processed. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + void *sigdeliver; /* Actual type is sig_deliver_t */ + + /* These are saved copies of LR, PRIMASK, and xPSR used during + * signal processing. + */ + + uint32_t saved_pc; + uint32_t saved_primask; + uint32_t saved_xpsr; +#endif + + /* Register save area */ + + uint32_t regs[XCPTCONTEXT_REGS]; +}; +#endif + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Disable IRQs */ + +static inline void irqdisable(void) +{ + __asm__ __volatile__ ("\tcpsid i\n"); +} + +/* Save the current primask state & disable IRQs */ + +static inline irqstate_t irqsave(void) +{ + unsigned short primask; + + /* Return the current value of primask register and set + * bit 0 of the primask register to disable interrupts + */ + + __asm__ __volatile__ + ( + "\tmrs %0, primask\n" + "\tcpsid i\n" + : "=r" (primask) + : + : "memory"); + return primask; +} + +/* Enable IRQs */ + +static inline void irqenable(void) +{ + __asm__ __volatile__ ("\tcpsie i\n"); +} + +/* Restore saved primask state */ + +static inline void irqrestore(irqstate_t primask) +{ + /* If bit 0 of the primask is 0, then we need to restore + * interupts. + */ + + __asm__ __volatile__ + ( + "\ttst %0, #1\n" + "\tbne 1f\n" + "\tcpsie i\n" + "1:\n" + : + : "r" (primask) + : "memory"); +} + +/* Get/set the primask register */ + +static inline uint8_t getprimask(void) +{ + uint32_t primask; + __asm__ __volatile__ + ( + "\tmrs %0, primask\n" + : "=r" (primask) + : + : "memory"); + return (uint8_t)primask; +} + +static inline void setprimask(uint32_t primask) +{ + __asm__ __volatile__ + ( + "\tmsr primask, %0\n" + : + : "r" (primask) + : "memory"); +} + +/* Get/set the basepri register */ + +static inline uint8_t getbasepri(void) +{ + uint32_t basepri; + __asm__ __volatile__ + ( + "\tmrs %0, basepri\n" + : "=r" (basepri) + : + : "memory"); + return (uint8_t)basepri; +} + +static inline void setbasepri(uint32_t basepri) +{ + __asm__ __volatile__ + ( + "\tmsr basepri, %0\n" + : + : "r" (basepri) + : "memory"); +} + +/* Get/set IPSR */ + +static inline uint32_t getipsr(void) +{ + uint32_t ipsr; + __asm__ __volatile__ + ( + "\tmrs %0, ipsr\n" + : "=r" (ipsr) + : + : "memory"); + return ipsr; +} + +static inline void setipsr(uint32_t ipsr) +{ + __asm__ __volatile__ + ( + "\tmsr ipsr, %0\n" + : + : "r" (ipsr) + : "memory"); +} + +/* Get/set CONTROL */ + +static inline uint32_t getcontrol(void) +{ + uint32_t control; + __asm__ __volatile__ + ( + "\tmrs %0, control\n" + : "=r" (control) + : + : "memory"); + return control; +} + +static inline void setcontrol(uint32_t control) +{ + __asm__ __volatile__ + ( + "\tmsr control, %0\n" + : + : "r" (control) + : "memory"); +} + +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_H */ + diff --git a/nuttx/arch/arm/include/armv7-m/irq_cmnvector.h b/nuttx/arch/arm/include/armv7-m/irq_cmnvector.h new file mode 100644 index 0000000000..e646731ebd --- /dev/null +++ b/nuttx/arch/arm/include/armv7-m/irq_cmnvector.h @@ -0,0 +1,164 @@ +/**************************************************************************** + * arch/arm/include/armv7-m/irq_cmnvector.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_CMNVECTOR_H +#define __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_CMNVECTOR_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* IRQ Stack Frame Format: */ + +/* The following additional registers are stored by the interrupt handling + * logic. + */ + +#define REG_R13 (0) /* R13 = SP at time of interrupt */ +#define REG_PRIMASK (1) /* PRIMASK */ +#define REG_R4 (2) /* R4 */ +#define REG_R5 (3) /* R5 */ +#define REG_R6 (4) /* R6 */ +#define REG_R7 (5) /* R7 */ +#define REG_R8 (6) /* R8 */ +#define REG_R9 (7) /* R9 */ +#define REG_R10 (8) /* R10 */ +#define REG_R11 (9) /* R11 */ +#define REG_EXC_RETURN (10) /* EXC_RETURN */ +#define SW_INT_REGS (11) + +#ifdef CONFIG_ARCH_FPU + +/* If the MCU supports a floating point unit, then it will be necessary + * to save the state of the non-volatile registers before calling code + * that may save and overwrite them. + */ + +# define REG_S16 (SW_INT_REGS+0) /* S16 */ +# define REG_S17 (SW_INT_REGS+1) /* S17 */ +# define REG_S18 (SW_INT_REGS+2) /* S18 */ +# define REG_S19 (SW_INT_REGS+3) /* S19 */ +# define REG_S20 (SW_INT_REGS+4) /* S20 */ +# define REG_S21 (SW_INT_REGS+5) /* S21 */ +# define REG_S22 (SW_INT_REGS+6) /* S22 */ +# define REG_S23 (SW_INT_REGS+7) /* S23 */ +# define REG_S24 (SW_INT_REGS+8) /* S24 */ +# define REG_S25 (SW_INT_REGS+9) /* S25 */ +# define REG_S26 (SW_INT_REGS+10) /* S26 */ +# define REG_S27 (SW_INT_REGS+11) /* S27 */ +# define REG_S28 (SW_INT_REGS+12) /* S28 */ +# define REG_S29 (SW_INT_REGS+13) /* S29 */ +# define REG_S30 (SW_INT_REGS+14) /* S30 */ +# define REG_S31 (SW_INT_REGS+15) /* S31 */ +# define SW_FPU_REGS (16) +#else +# define SW_FPU_REGS (0) +#endif + +/* The total number of registers saved by software */ + +#define SW_XCPT_REGS (SW_INT_REGS + SW_FPU_REGS) +#define SW_XCPT_SIZE (4 * SW_XCPT_REGS) + +/* On entry into an IRQ, the hardware automatically saves the following + * registers on the stack in this (address) order: + */ + +#define REG_R0 (SW_XCPT_REGS+0) /* R0 */ +#define REG_R1 (SW_XCPT_REGS+1) /* R1 */ +#define REG_R2 (SW_XCPT_REGS+2) /* R2 */ +#define REG_R3 (SW_XCPT_REGS+3) /* R3 */ +#define REG_R12 (SW_XCPT_REGS+4) /* R12 */ +#define REG_R14 (SW_XCPT_REGS+5) /* R14 = LR */ +#define REG_R15 (SW_XCPT_REGS+6) /* R15 = PC */ +#define REG_XPSR (SW_XCPT_REGS+7) /* xPSR */ +#define HW_INT_REGS (8) + +#ifdef CONFIG_ARCH_FPU + +/* If the FPU is enabled, the hardware also saves the volatile FP registers. + */ + +# define REG_S0 (SW_XCPT_REGS+8) /* S0 */ +# define REG_S1 (SW_XCPT_REGS+9) /* S1 */ +# define REG_S2 (SW_XCPT_REGS+10) /* S2 */ +# define REG_S3 (SW_XCPT_REGS+11) /* S3 */ +# define REG_S4 (SW_XCPT_REGS+12) /* S4 */ +# define REG_S5 (SW_XCPT_REGS+13) /* S5 */ +# define REG_S6 (SW_XCPT_REGS+14) /* S6 */ +# define REG_S7 (SW_XCPT_REGS+15) /* S7 */ +# define REG_S8 (SW_XCPT_REGS+16) /* S8 */ +# define REG_S9 (SW_XCPT_REGS+17) /* S9 */ +# define REG_S10 (SW_XCPT_REGS+18) /* S10 */ +# define REG_S11 (SW_XCPT_REGS+19) /* S11 */ +# define REG_S12 (SW_XCPT_REGS+20) /* S12 */ +# define REG_S13 (SW_XCPT_REGS+21) /* S13 */ +# define REG_S14 (SW_XCPT_REGS+22) /* S14 */ +# define REG_S15 (SW_XCPT_REGS+23) /* S15 */ +# define REG_FPSCR (SW_XCPT_REGS+24) /* FPSCR */ +# define REG_FPReserved (SW_XCPT_REGS+25) /* Reserved */ +# define HW_FPU_REGS (18) +#else +# define HW_FPU_REGS (0) +#endif + +#define HW_XCPT_REGS (HW_INT_REGS + HW_FPU_REGS) +#define HW_XCPT_SIZE (4 * HW_XCPT_REGS) + +#define XCPTCONTEXT_REGS (HW_XCPT_REGS + SW_XCPT_REGS) +#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_CMNVECTOR_H */ + diff --git a/nuttx/arch/arm/include/armv7-m/irq_lazyfpu.h b/nuttx/arch/arm/include/armv7-m/irq_lazyfpu.h new file mode 100644 index 0000000000..2c3600b7fa --- /dev/null +++ b/nuttx/arch/arm/include/armv7-m/irq_lazyfpu.h @@ -0,0 +1,182 @@ +/**************************************************************************** + * arch/arm/include/armv7-m/irq.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_LAZYFPU_H +#define __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_LAZYFPU_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* IRQ Stack Frame Format: */ + +/* The following additional registers are stored by the interrupt handling + * logic. + */ + +#define REG_R13 (0) /* R13 = SP at time of interrupt */ +#define REG_PRIMASK (1) /* PRIMASK */ +#define REG_R4 (2) /* R4 */ +#define REG_R5 (3) /* R5 */ +#define REG_R6 (4) /* R6 */ +#define REG_R7 (5) /* R7 */ +#define REG_R8 (6) /* R8 */ +#define REG_R9 (7) /* R9 */ +#define REG_R10 (8) /* R10 */ +#define REG_R11 (9) /* R11 */ + +#ifdef CONFIG_NUTTX_KERNEL +# define REG_EXC_RETURN (10) /* EXC_RETURN */ +# define SW_INT_REGS (11) +#else +# define SW_INT_REGS (10) +#endif + +/* If the MCU supports a floating point unit, then it will be necessary + * to save the state of the FPU status register and data registers on + * each context switch. These registers are not saved during interrupt + * level processing, however. So, as a consequence, floating point + * operations may NOT be performed in interrupt handlers. + * + * The FPU provides an extension register file containing 32 single- + * precision registers. These can be viewed as: + * + * - Sixteen 64-bit doubleword registers, D0-D15 + * - Thirty-two 32-bit single-word registers, S0-S31 + * S<2n> maps to the least significant half of D + * S<2n+1> maps to the most significant half of D. + */ + +#ifdef CONFIG_ARCH_FPU +# define REG_D0 (SW_INT_REGS+0) /* D0 */ +# define REG_S0 (SW_INT_REGS+0) /* S0 */ +# define REG_S1 (SW_INT_REGS+1) /* S1 */ +# define REG_D1 (SW_INT_REGS+2) /* D1 */ +# define REG_S2 (SW_INT_REGS+2) /* S2 */ +# define REG_S3 (SW_INT_REGS+3) /* S3 */ +# define REG_D2 (SW_INT_REGS+4) /* D2 */ +# define REG_S4 (SW_INT_REGS+4) /* S4 */ +# define REG_S5 (SW_INT_REGS+5) /* S5 */ +# define REG_D3 (SW_INT_REGS+6) /* D3 */ +# define REG_S6 (SW_INT_REGS+6) /* S6 */ +# define REG_S7 (SW_INT_REGS+7) /* S7 */ +# define REG_D4 (SW_INT_REGS+8) /* D4 */ +# define REG_S8 (SW_INT_REGS+8) /* S8 */ +# define REG_S9 (SW_INT_REGS+9) /* S9 */ +# define REG_D5 (SW_INT_REGS+10) /* D5 */ +# define REG_S10 (SW_INT_REGS+10) /* S10 */ +# define REG_S11 (SW_INT_REGS+11) /* S11 */ +# define REG_D6 (SW_INT_REGS+12) /* D6 */ +# define REG_S12 (SW_INT_REGS+12) /* S12 */ +# define REG_S13 (SW_INT_REGS+13) /* S13 */ +# define REG_D7 (SW_INT_REGS+14) /* D7 */ +# define REG_S14 (SW_INT_REGS+14) /* S14 */ +# define REG_S15 (SW_INT_REGS+15) /* S15 */ +# define REG_D8 (SW_INT_REGS+16) /* D8 */ +# define REG_S16 (SW_INT_REGS+16) /* S16 */ +# define REG_S17 (SW_INT_REGS+17) /* S17 */ +# define REG_D9 (SW_INT_REGS+18) /* D9 */ +# define REG_S18 (SW_INT_REGS+18) /* S18 */ +# define REG_S19 (SW_INT_REGS+19) /* S19 */ +# define REG_D10 (SW_INT_REGS+20) /* D10 */ +# define REG_S20 (SW_INT_REGS+20) /* S20 */ +# define REG_S21 (SW_INT_REGS+21) /* S21 */ +# define REG_D11 (SW_INT_REGS+22) /* D11 */ +# define REG_S22 (SW_INT_REGS+22) /* S22 */ +# define REG_S23 (SW_INT_REGS+23) /* S23 */ +# define REG_D12 (SW_INT_REGS+24) /* D12 */ +# define REG_S24 (SW_INT_REGS+24) /* S24 */ +# define REG_S25 (SW_INT_REGS+25) /* S25 */ +# define REG_D13 (SW_INT_REGS+26) /* D13 */ +# define REG_S26 (SW_INT_REGS+26) /* S26 */ +# define REG_S27 (SW_INT_REGS+27) /* S27 */ +# define REG_D14 (SW_INT_REGS+28) /* D14 */ +# define REG_S28 (SW_INT_REGS+28) /* S28 */ +# define REG_S29 (SW_INT_REGS+29) /* S29 */ +# define REG_D15 (SW_INT_REGS+30) /* D15 */ +# define REG_S30 (SW_INT_REGS+30) /* S30 */ +# define REG_S31 (SW_INT_REGS+31) /* S31 */ +# define REG_FPSCR (SW_INT_REGS+32) /* Floating point status and control */ +# define SW_FPU_REGS (33) +#else +# define SW_FPU_REGS (0) +#endif + +/* The total number of registers saved by software */ + +#define SW_XCPT_REGS (SW_INT_REGS + SW_FPU_REGS) +#define SW_XCPT_SIZE (4 * SW_XCPT_REGS) + +/* On entry into an IRQ, the hardware automatically saves the following + * registers on the stack in this (address) order: + */ + +#define REG_R0 (SW_XCPT_REGS+0) /* R0 */ +#define REG_R1 (SW_XCPT_REGS+1) /* R1 */ +#define REG_R2 (SW_XCPT_REGS+2) /* R2 */ +#define REG_R3 (SW_XCPT_REGS+3) /* R3 */ +#define REG_R12 (SW_XCPT_REGS+4) /* R12 */ +#define REG_R14 (SW_XCPT_REGS+5) /* R14 = LR */ +#define REG_R15 (SW_XCPT_REGS+6) /* R15 = PC */ +#define REG_XPSR (SW_XCPT_REGS+7) /* xPSR */ + +#define HW_XCPT_REGS (8) +#define HW_XCPT_SIZE (4 * HW_XCPT_REGS) + +#define XCPTCONTEXT_REGS (HW_XCPT_REGS + SW_XCPT_REGS) +#define XCPTCONTEXT_SIZE (HW_XCPT_SIZE + SW_XCPT_SIZE) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_LAZYFPU_H */ + diff --git a/nuttx/arch/arm/include/armv7-m/syscall.h b/nuttx/arch/arm/include/armv7-m/syscall.h new file mode 100644 index 0000000000..4c7b843021 --- /dev/null +++ b/nuttx/arch/arm/include/armv7-m/syscall.h @@ -0,0 +1,243 @@ +/**************************************************************************** + * arch/arm/include/armv7-m/syscall.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through include/syscall.h or include/sys/sycall.h + */ + +#ifndef __ARCH_ARM_INCLUDE_ARMV7_M_SYSCALL_H +#define __ARCH_ARM_INCLUDE_ARMV7_M_SYSCALL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Pro-processor Definitions + ****************************************************************************/ + +#define SYS_syscall 0x00 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* SVC call with SYS_ call number and no parameters */ + +static inline uintptr_t sys_call0(unsigned int nbr) +{ + register long reg0 __asm__("r0") = (long)(nbr); + + __asm__ __volatile__ + ( + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0) + : "memory" + ); + + return reg0; +} + +/* SVC call with SYS_ call number and one parameter */ + +static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1) +{ + register long reg0 __asm__("r0") = (long)(nbr); + register long reg1 __asm__("r1") = (long)(parm1); + + __asm__ __volatile__ + ( + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1) + : "memory" + ); + + return reg0; +} + +/* SVC call with SYS_ call number and two parameters */ + +static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2) +{ + register long reg0 __asm__("r0") = (long)(nbr); + register long reg2 __asm__("r2") = (long)(parm2); + register long reg1 __asm__("r1") = (long)(parm1); + + __asm__ __volatile__ + ( + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2) + : "memory" + ); + + return reg0; +} + +/* SVC call with SYS_ call number and three parameters */ + +static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3) +{ + register long reg0 __asm__("r0") = (long)(nbr); + register long reg3 __asm__("r3") = (long)(parm3); + register long reg2 __asm__("r2") = (long)(parm2); + register long reg1 __asm__("r1") = (long)(parm1); + + __asm__ __volatile__ + ( + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), "r"(reg3) + : "memory" + ); + + return reg0; +} + +/* SVC call with SYS_ call number and four parameters */ + +static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3, + uintptr_t parm4) +{ + register long reg0 __asm__("r0") = (long)(nbr); + register long reg4 __asm__("r4") = (long)(parm4); + register long reg3 __asm__("r3") = (long)(parm3); + register long reg2 __asm__("r2") = (long)(parm2); + register long reg1 __asm__("r1") = (long)(parm1); + + __asm__ __volatile__ + ( + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), + "r"(reg3), "r"(reg4) + : "memory" + ); + + return reg0; +} + +/* SVC call with SYS_ call number and five parameters */ + +static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3, + uintptr_t parm4, uintptr_t parm5) +{ + register long reg0 __asm__("r0") = (long)(nbr); + register long reg5 __asm__("r5") = (long)(parm5); + register long reg4 __asm__("r4") = (long)(parm4); + register long reg3 __asm__("r3") = (long)(parm3); + register long reg2 __asm__("r2") = (long)(parm2); + register long reg1 __asm__("r1") = (long)(parm1); + + __asm__ __volatile__ + ( + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), + "r"(reg3), "r"(reg4), "r"(reg5) + : "memory" + ); + + return reg0; +} + +/* SVC call with SYS_ call number and six parameters */ + +static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3, + uintptr_t parm4, uintptr_t parm5, + uintptr_t parm6) +{ + register long reg0 __asm__("r0") = (long)(nbr); + register long reg6 __asm__("r6") = (long)(parm6); + register long reg5 __asm__("r5") = (long)(parm5); + register long reg4 __asm__("r4") = (long)(parm4); + register long reg3 __asm__("r3") = (long)(parm3); + register long reg2 __asm__("r2") = (long)(parm2); + register long reg1 __asm__("r1") = (long)(parm1); + + __asm__ __volatile__ + ( + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), + "r"(reg3), "r"(reg4), "r"(reg5), "r"(reg6) + : "memory" + ); + + return reg0; +} + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_INCLUDE_ARMV7_M_SYSCALL_H */ + diff --git a/nuttx/arch/arm/include/irq.h b/nuttx/arch/arm/include/irq.h new file mode 100644 index 0000000000..71493a9fed --- /dev/null +++ b/nuttx/arch/arm/include/irq.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * arch/arm/include/irq.h + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_IRQ_H +#define __ARCH_ARM_INCLUDE_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Include NuttX-specific IRQ definitions */ + +#include + +/* Include chip-specific IRQ definitions (including IRQ numbers) */ + +#include + +/* Include ARM architecture-specific IRQ definitions (including register + * save structure and irqsave()/irqrestore() macros) + */ + +#if defined(CONFIG_ARCH_CORTEXM3) || defined(CONFIG_ARCH_CORTEXM4) +# include +#else +# include +#endif + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_IRQ_H */ + diff --git a/nuttx/arch/arm/include/limits.h b/nuttx/arch/arm/include/limits.h new file mode 100644 index 0000000000..a218d53bfb --- /dev/null +++ b/nuttx/arch/arm/include/limits.h @@ -0,0 +1,81 @@ +/**************************************************************************** + * arch/arm/include/limits.h + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_LIMITS_H +#define __ARCH_ARM_INCLUDE_LIMITS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define CHAR_BIT 8 +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 +#define UCHAR_MAX 0xff + +/* These could be different on machines where char is unsigned */ + +#define CHAR_MIN SCHAR_MIN +#define CHAR_MAX SCHAR_MAX + +#define SHRT_MIN 0x8000 +#define SHRT_MAX 0x7fff +#define USHRT_MAX 0xffff + +#define INT_MIN 0x80000000 +#define INT_MAX 0x7fffffff +#define UINT_MAX 0xffffffff + +/* These change on 32-bit and 64-bit platforms */ + +#define LONG_MAX 0x80000000 +#define LONG_MIN 0x7fffffff +#define ULONG_MAX 0xffffffff + +#define LLONG_MAX 0x8000000000000000 +#define LLONG_MIN 0x7fffffffffffffff +#define ULLONG_MAX 0xffffffffffffffff + +/* A pointer is 4 bytes */ + +#define PTR_MIN 0x80000000 +#define PTR_MAX 0x7fffffff +#define UPTR_MAX 0xffffffff + +#endif /* __ARCH_ARM_INCLUDE_LIMITS_H */ diff --git a/nuttx/arch/arm/include/math.h b/nuttx/arch/arm/include/math.h new file mode 100644 index 0000000000..ef08692432 --- /dev/null +++ b/nuttx/arch/arm/include/math.h @@ -0,0 +1,608 @@ +#ifndef _MATH_H_ + +#define _MATH_H_ + +//#include +#include +#include "_ansi.h" + +//#define _PARAMS(_x) _x + +_BEGIN_STD_C + +#if 0 +/* __dmath, __fmath, and __ldmath are only here for backwards compatibility + * in case any code used them. They are no longer used by Newlib, itself, + * other than legacy. */ +union __dmath +{ + double d; + __ULong i[2]; +}; + +union __fmath +{ + float f; + __ULong i[1]; +}; + +#if defined(_HAVE_LONG_DOUBLE) +union __ldmath +{ + long double ld; + __ULong i[4]; +}; +#endif +#endif + +/* Natural log of 2 */ +#define _M_LN2 0.693147180559945309417 + +#if defined(__GNUC__) && \ + ( (__GNUC__ >= 4) || \ + ( (__GNUC__ >= 3) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 3) ) ) + + /* gcc >= 3.3 implicitly defines builtins for HUGE_VALx values. */ + +# ifndef HUGE_VAL +# define HUGE_VAL (__builtin_huge_val()) +# endif + +# ifndef HUGE_VALF +# define HUGE_VALF (__builtin_huge_valf()) +# endif + +# ifndef HUGE_VALL +# define HUGE_VALL (__builtin_huge_vall()) +# endif + +# ifndef INFINITY +# define INFINITY (__builtin_inff()) +# endif + +# ifndef NAN +# define NAN (__builtin_nanf("")) +# endif + +#else /* !gcc >= 3.3 */ + + /* No builtins. Use fixed defines instead. (All 3 HUGE plus the INFINITY + * and NAN macros are required to be constant expressions. Using a variable-- + * even a static const--does not meet this requirement, as it cannot be + * evaluated at translation time.) + * The infinities are done using numbers that are far in excess of + * something that would be expected to be encountered in a floating-point + * implementation. (A more certain way uses values from float.h, but that is + * avoided because system includes are not supposed to include each other.) + * This method might produce warnings from some compilers. (It does in + * newer GCCs, but not for ones that would hit this #else.) If this happens, + * please report details to the Newlib mailing list. */ + + #ifndef HUGE_VAL + #define HUGE_VAL (1.0e999999999) + #endif + + #ifndef HUGE_VALF + #define HUGE_VALF (1.0e999999999F) + #endif + + #if !defined(HUGE_VALL) && defined(_HAVE_LONG_DOUBLE) + #define HUGE_VALL (1.0e999999999L) + #endif + + #if !defined(INFINITY) + #define INFINITY (HUGE_VALF) + #endif + + #if !defined(NAN) + #if defined(__GNUC__) && defined(__cplusplus) + /* Exception: older g++ versions warn about the divide by 0 used in the + * normal case (even though older gccs do not). This trick suppresses the + * warning, but causes errors for plain gcc, so is only used in the one + * special case. */ + static const union { __ULong __i[1]; float __d; } __Nanf = {0x7FC00000}; + #define NAN (__Nanf.__d) + #else + #define NAN (0.0F/0.0F) + #endif + #endif + +#endif /* !gcc >= 3.3 */ + +/* Reentrant ANSI C functions. */ + +#ifndef __math_68881 +extern double atan _PARAMS((double)); +extern double cos _PARAMS((double)); +extern double sin _PARAMS((double)); +extern double tan _PARAMS((double)); +extern double tanh _PARAMS((double)); +extern double frexp _PARAMS((double, int *)); +extern double modf _PARAMS((double, double *)); +extern double ceil _PARAMS((double)); +extern double fabs _PARAMS((double)); +extern double floor _PARAMS((double)); +#endif /* ! defined (__math_68881) */ + +/* Non reentrant ANSI C functions. */ + +#ifndef _REENT_ONLY +#ifndef __math_68881 +extern double acos _PARAMS((double)); +extern double asin _PARAMS((double)); +extern double atan2 _PARAMS((double, double)); +extern double cosh _PARAMS((double)); +extern double sinh _PARAMS((double)); +extern double exp _PARAMS((double)); +extern double ldexp _PARAMS((double, int)); +extern double log _PARAMS((double)); +extern double log10 _PARAMS((double)); +extern double pow _PARAMS((double, double)); +extern double sqrt _PARAMS((double)); +extern double fmod _PARAMS((double, double)); +#endif /* ! defined (__math_68881) */ +#endif /* ! defined (_REENT_ONLY) */ + +#if !defined(__STRICT_ANSI__) || defined(__cplusplus) || __STDC_VERSION__ >= 199901L + +/* ISO C99 types and macros. */ + +#ifndef FLT_EVAL_METHOD +#define FLT_EVAL_METHOD 0 +typedef float float_t; +typedef double double_t; +#endif /* FLT_EVAL_METHOD */ + +#define FP_NAN 0 +#define FP_INFINITE 1 +#define FP_ZERO 2 +#define FP_SUBNORMAL 3 +#define FP_NORMAL 4 + +#ifndef FP_ILOGB0 +# define FP_ILOGB0 (-INT_MAX) +#endif +#ifndef FP_ILOGBNAN +# define FP_ILOGBNAN INT_MAX +#endif + +#ifndef MATH_ERRNO +# define MATH_ERRNO 1 +#endif +#ifndef MATH_ERREXCEPT +# define MATH_ERREXCEPT 2 +#endif +#ifndef math_errhandling +# define math_errhandling MATH_ERRNO +#endif + +extern int __isinff (float x); +extern int __isinfd (double x); +extern int __isnanf (float x); +extern int __isnand (double x); +extern int __fpclassifyf (float x); +extern int __fpclassifyd (double x); +extern int __signbitf (float x); +extern int __signbitd (double x); + +#define fpclassify(__x) \ + ((sizeof(__x) == sizeof(float)) ? __fpclassifyf(__x) : \ + __fpclassifyd(__x)) + +#ifndef isfinite + #define isfinite(__y) \ + (__extension__ ({int __cy = fpclassify(__y); \ + __cy != FP_INFINITE && __cy != FP_NAN;})) +#endif + +/* Note: isinf and isnan were once functions in newlib that took double + * arguments. C99 specifies that these names are reserved for macros + * supporting multiple floating point types. Thus, they are + * now defined as macros. Implementations of the old functions + * taking double arguments still exist for compatibility purposes + * (prototypes for them are in ). */ +#ifndef isinf + #define isinf(y) (fpclassify(y) == FP_INFINITE) +#endif + +#ifndef isnan + #define isnan(y) (fpclassify(y) == FP_NAN) +#endif + +#define isnormal(y) (fpclassify(y) == FP_NORMAL) +#define signbit(__x) \ + ((sizeof(__x) == sizeof(float)) ? __signbitf(__x) : \ + __signbitd(__x)) + +#define isgreater(x,y) \ + (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered(__x,__y) && (__x > __y);})) +#define isgreaterequal(x,y) \ + (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered(__x,__y) && (__x >= __y);})) +#define isless(x,y) \ + (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered(__x,__y) && (__x < __y);})) +#define islessequal(x,y) \ + (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered(__x,__y) && (__x <= __y);})) +#define islessgreater(x,y) \ + (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered(__x,__y) && (__x < __y || __x > __y);})) + +#define isunordered(a,b) \ + (__extension__ ({__typeof__(a) __a = (a); __typeof__(b) __b = (b); \ + fpclassify(__a) == FP_NAN || fpclassify(__b) == FP_NAN;})) + +/* Non ANSI double precision functions. */ + +extern double infinity _PARAMS((void)); +extern double nan _PARAMS((const char *)); +extern int finite _PARAMS((double)); +extern double copysign _PARAMS((double, double)); +extern double logb _PARAMS((double)); +extern int ilogb _PARAMS((double)); + +extern double asinh _PARAMS((double)); +extern double cbrt _PARAMS((double)); +extern double nextafter _PARAMS((double, double)); +extern double rint _PARAMS((double)); +extern double scalbn _PARAMS((double, int)); + +extern double exp2 _PARAMS((double)); +extern double scalbln _PARAMS((double, long int)); +extern double tgamma _PARAMS((double)); +extern double nearbyint _PARAMS((double)); +extern long int lrint _PARAMS((double)); +extern _LONG_LONG_TYPE int llrint _PARAMS((double)); +extern double round _PARAMS((double)); +extern long int lround _PARAMS((double)); +extern long long int llround _PARAMS((double)); +extern double trunc _PARAMS((double)); +extern double remquo _PARAMS((double, double, int *)); +extern double fdim _PARAMS((double, double)); +extern double fmax _PARAMS((double, double)); +extern double fmin _PARAMS((double, double)); +extern double fma _PARAMS((double, double, double)); + +#ifndef __math_68881 +extern double log1p _PARAMS((double)); +extern double expm1 _PARAMS((double)); +#endif /* ! defined (__math_68881) */ + +#ifndef _REENT_ONLY +extern double acosh _PARAMS((double)); +extern double atanh _PARAMS((double)); +extern double remainder _PARAMS((double, double)); +extern double gamma _PARAMS((double)); +extern double lgamma _PARAMS((double)); +extern double erf _PARAMS((double)); +extern double erfc _PARAMS((double)); +extern double log2 _PARAMS((double)); +#if !defined(__cplusplus) +#define log2(x) (log (x) / _M_LN2) +#endif + +#ifndef __math_68881 +extern double hypot _PARAMS((double, double)); +#endif + +#endif /* ! defined (_REENT_ONLY) */ + +/* Single precision versions of ANSI functions. */ + +extern float atanf _PARAMS((float)); +extern float cosf _PARAMS((float)); +extern float sinf _PARAMS((float)); +extern float tanf _PARAMS((float)); +extern float tanhf _PARAMS((float)); +extern float frexpf _PARAMS((float, int *)); +extern float modff _PARAMS((float, float *)); +extern float ceilf _PARAMS((float)); +extern float fabsf _PARAMS((float)); +extern float floorf _PARAMS((float)); + +#ifndef _REENT_ONLY +extern float acosf _PARAMS((float)); +extern float asinf _PARAMS((float)); +extern float atan2f _PARAMS((float, float)); +extern float coshf _PARAMS((float)); +extern float sinhf _PARAMS((float)); +extern float expf _PARAMS((float)); +extern float ldexpf _PARAMS((float, int)); +extern float logf _PARAMS((float)); +extern float log10f _PARAMS((float)); +extern float powf _PARAMS((float, float)); +extern float sqrtf _PARAMS((float)); +extern float fmodf _PARAMS((float, float)); +#endif /* ! defined (_REENT_ONLY) */ + +/* Other single precision functions. */ + +extern float exp2f _PARAMS((float)); +extern float scalblnf _PARAMS((float, long int)); +extern float tgammaf _PARAMS((float)); +extern float nearbyintf _PARAMS((float)); +extern long int lrintf _PARAMS((float)); +extern _LONG_LONG_TYPE llrintf _PARAMS((float)); +extern float roundf _PARAMS((float)); +extern long int lroundf _PARAMS((float)); +extern long long int llroundf _PARAMS((float)); +extern float truncf _PARAMS((float)); +extern float remquof _PARAMS((float, float, int *)); +extern float fdimf _PARAMS((float, float)); +extern float fmaxf _PARAMS((float, float)); +extern float fminf _PARAMS((float, float)); +extern float fmaf _PARAMS((float, float, float)); + +extern float infinityf _PARAMS((void)); +extern float nanf _PARAMS((const char *)); +extern int finitef _PARAMS((float)); +extern float copysignf _PARAMS((float, float)); +extern float logbf _PARAMS((float)); +extern int ilogbf _PARAMS((float)); + +extern float asinhf _PARAMS((float)); +extern float cbrtf _PARAMS((float)); +extern float nextafterf _PARAMS((float, float)); +extern float rintf _PARAMS((float)); +extern float scalbnf _PARAMS((float, int)); +extern float log1pf _PARAMS((float)); +extern float expm1f _PARAMS((float)); + +#ifndef _REENT_ONLY +extern float acoshf _PARAMS((float)); +extern float atanhf _PARAMS((float)); +extern float remainderf _PARAMS((float, float)); +extern float gammaf _PARAMS((float)); +extern float lgammaf _PARAMS((float)); +extern float erff _PARAMS((float)); +extern float erfcf _PARAMS((float)); +extern float log2f _PARAMS((float)); +#if !defined(__cplusplus) +#define log2f(x) (logf (x) / (float_t) _M_LN2) +#endif +extern float hypotf _PARAMS((float, float)); +#endif /* ! defined (_REENT_ONLY) */ + +/* On platforms where long double equals double. */ +#ifdef _LDBL_EQ_DBL +/* Reentrant ANSI C functions. */ +#ifndef __math_68881 +extern long double atanl _PARAMS((long double)); +extern long double cosl _PARAMS((long double)); +extern long double sinl _PARAMS((long double)); +extern long double tanl _PARAMS((long double)); +extern long double tanhl _PARAMS((long double)); +extern long double frexpl _PARAMS((long double value, int *)); +extern long double modfl _PARAMS((long double, long double *)); +extern long double ceill _PARAMS((long double)); +extern long double fabsl _PARAMS((long double)); +extern long double floorl _PARAMS((long double)); +extern long double log1pl _PARAMS((long double)); +extern long double expm1l _PARAMS((long double)); +#endif /* ! defined (__math_68881) */ +/* Non reentrant ANSI C functions. */ +#ifndef _REENT_ONLY +#ifndef __math_68881 +extern long double acosl _PARAMS((long double)); +extern long double asinl _PARAMS((long double)); +extern long double atan2l _PARAMS((long double, long double)); +extern long double coshl _PARAMS((long double)); +extern long double sinhl _PARAMS((long double)); +extern long double expl _PARAMS((long double)); +extern long double ldexpl _PARAMS((long double, int)); +extern long double logl _PARAMS((long double)); +extern long double log10l _PARAMS((long double)); +extern long double powl _PARAMS((long double, long double)); +extern long double sqrtl _PARAMS((long double)); +extern long double fmodl _PARAMS((long double, long double)); +extern long double hypotl _PARAMS((long double, long double)); +#endif /* ! defined (__math_68881) */ +#endif /* ! defined (_REENT_ONLY) */ +extern long double copysignl _PARAMS((long double, long double)); +extern long double nanl _PARAMS((const char *)); +extern int ilogbl _PARAMS((long double)); +extern long double asinhl _PARAMS((long double)); +extern long double cbrtl _PARAMS((long double)); +extern long double nextafterl _PARAMS((long double, long double)); +extern long double rintl _PARAMS((long double)); +extern long double scalbnl _PARAMS((long double, int)); +extern long double exp2l _PARAMS((long double)); +extern long double scalblnl _PARAMS((long double, long)); +extern long double tgammal _PARAMS((long double)); +extern long double nearbyintl _PARAMS((long double)); +extern long int lrintl _PARAMS((long double)); +extern long long int llrintl _PARAMS((long double)); +extern long double roundl _PARAMS((long double)); +extern long lroundl _PARAMS((long double)); +extern _LONG_LONG_TYPE int llroundl _PARAMS((long double)); +extern long double truncl _PARAMS((long double)); +extern long double remquol _PARAMS((long double, long double, int *)); +extern long double fdiml _PARAMS((long double, long double)); +extern long double fmaxl _PARAMS((long double, long double)); +extern long double fminl _PARAMS((long double, long double)); +extern long double fmal _PARAMS((long double, long double, long double)); +#ifndef _REENT_ONLY +extern long double acoshl _PARAMS((long double)); +extern long double atanhl _PARAMS((long double)); +extern long double remainderl _PARAMS((long double, long double)); +extern long double lgammal _PARAMS((long double)); +extern long double erfl _PARAMS((long double)); +extern long double erfcl _PARAMS((long double)); +#endif /* ! defined (_REENT_ONLY) */ +#else /* !_LDBL_EQ_DBL */ +#ifdef __i386__ +/* Other long double precision functions. */ +extern _LONG_DOUBLE rintl _PARAMS((_LONG_DOUBLE)); +extern long int lrintl _PARAMS((_LONG_DOUBLE)); +extern _LONG_LONG_TYPE llrintl _PARAMS((_LONG_DOUBLE)); +#endif /* __i386__ */ +#endif /* !_LDBL_EQ_DBL */ + +#endif /* !defined (__STRICT_ANSI__) || defined(__cplusplus) || __STDC_VERSION__ >= 199901L */ + +#if !defined (__STRICT_ANSI__) || defined(__cplusplus) + +extern double drem _PARAMS((double, double)); +extern void sincos _PARAMS((double, double *, double *)); +extern double gamma_r _PARAMS((double, int *)); +extern double lgamma_r _PARAMS((double, int *)); + +extern double y0 _PARAMS((double)); +extern double y1 _PARAMS((double)); +extern double yn _PARAMS((int, double)); +extern double j0 _PARAMS((double)); +extern double j1 _PARAMS((double)); +extern double jn _PARAMS((int, double)); + +extern float dremf _PARAMS((float, float)); +extern void sincosf _PARAMS((float, float *, float *)); +extern float gammaf_r _PARAMS((float, int *)); +extern float lgammaf_r _PARAMS((float, int *)); + +extern float y0f _PARAMS((float)); +extern float y1f _PARAMS((float)); +extern float ynf _PARAMS((int, float)); +extern float j0f _PARAMS((float)); +extern float j1f _PARAMS((float)); +extern float jnf _PARAMS((int, float)); + +/* GNU extensions */ +# ifndef exp10 +extern double exp10 _PARAMS((double)); +# endif +# ifndef pow10 +extern double pow10 _PARAMS((double)); +# endif +# ifndef exp10f +extern float exp10f _PARAMS((float)); +# endif +# ifndef pow10f +extern float pow10f _PARAMS((float)); +# endif + +#endif /* !defined (__STRICT_ANSI__) || defined(__cplusplus) */ + +#ifndef __STRICT_ANSI__ + +/* The gamma functions use a global variable, signgam. */ +#ifndef _REENT_ONLY +#define signgam (*__signgam()) +extern int *__signgam _PARAMS((void)); +#endif /* ! defined (_REENT_ONLY) */ + +#define __signgam_r(ptr) _REENT_SIGNGAM(ptr) + +/* The exception structure passed to the matherr routine. */ +/* We have a problem when using C++ since `exception' is a reserved + name in C++. */ +#ifdef __cplusplus +struct __exception +#else +struct exception +#endif +{ + int type; + char *name; + double arg1; + double arg2; + double retval; + int err; +}; + +#ifdef __cplusplus +extern int matherr _PARAMS((struct __exception *e)); +#else +extern int matherr _PARAMS((struct exception *e)); +#endif + +/* Values for the type field of struct exception. */ + +#define DOMAIN 1 +#define SING 2 +#define OVERFLOW 3 +#define UNDERFLOW 4 +#define TLOSS 5 +#define PLOSS 6 + +/* Useful constants. */ + +#define MAXFLOAT 3.40282347e+38F + +#define M_E 2.7182818284590452354 +#define M_LOG2E 1.4426950408889634074 +#define M_LOG10E 0.43429448190325182765 +#define M_LN2 _M_LN2 +#define M_LN10 2.30258509299404568402 +#define M_PI 3.14159265358979323846 +#define M_TWOPI (M_PI * 2.0) +#define M_PI_2 1.57079632679489661923 +#define M_PI_4 0.78539816339744830962 +#define M_3PI_4 2.3561944901923448370E0 +#define M_SQRTPI 1.77245385090551602792981 +#define M_1_PI 0.31830988618379067154 +#define M_2_PI 0.63661977236758134308 +#define M_2_SQRTPI 1.12837916709551257390 +#define M_SQRT2 1.41421356237309504880 +#define M_SQRT1_2 0.70710678118654752440 +#define M_LN2LO 1.9082149292705877000E-10 +#define M_LN2HI 6.9314718036912381649E-1 +#define M_SQRT3 1.73205080756887719000 +#define M_IVLN10 0.43429448190325182765 /* 1 / log(10) */ +#define M_LOG2_E _M_LN2 +#define M_INVLN2 1.4426950408889633870E0 /* 1 / log(2) */ + + +#define M_E_F 2.7182818284590452354f +#define M_LOG2E_F 1.4426950408889634074f +#define M_LOG10E_F 0.43429448190325182765f +#define M_LN2_F _M_LN2_F +#define M_LN10_F 2.30258509299404568402f +#define M_PI_F 3.14159265358979323846f +#define M_TWOPI_F (M_PI_F * 2.0f) +#define M_PI_2_F 1.57079632679489661923f +#define M_PI_4_F 0.78539816339744830962f +#define M_3PI_4_F 2.3561944901923448370E0f +#define M_SQRTPI_F 1.77245385090551602792981f +#define M_1_PI_F 0.31830988618379067154f +#define M_2_PI_F 0.63661977236758134308f +#define M_2_SQRTPI_F 1.12837916709551257390f +#define M_SQRT2_F 1.41421356237309504880f +#define M_SQRT1_2_F 0.70710678118654752440f +#define M_LN2LO_F 1.9082149292705877000E-10f +#define M_LN2HI_F 6.9314718036912381649E-1f +#define M_SQRT3_F 1.73205080756887719000f +#define M_IVLN10_F 0.43429448190325182765f /* 1 / log(10) */ +#define M_LOG2_E_F _M_LN2_F +#define M_INVLN2_F 1.4426950408889633870E0f /* 1 / log(2) */ + +/* Global control over fdlibm error handling. */ + +enum __fdlibm_version +{ + __fdlibm_ieee = -1, + __fdlibm_svid, + __fdlibm_xopen, + __fdlibm_posix +}; + +#define _LIB_VERSION_TYPE enum __fdlibm_version +#define _LIB_VERSION __fdlib_version + +extern __IMPORT _LIB_VERSION_TYPE _LIB_VERSION; + +#define _IEEE_ __fdlibm_ieee +#define _SVID_ __fdlibm_svid +#define _XOPEN_ __fdlibm_xopen +#define _POSIX_ __fdlibm_posix + +#endif /* ! defined (__STRICT_ANSI__) */ + +_END_STD_C + +#ifdef __FAST_MATH__ +#include +#endif + +#endif /* _MATH_H_ */ diff --git a/nuttx/arch/arm/include/serial.h b/nuttx/arch/arm/include/serial.h new file mode 100644 index 0000000000..80eefb2b4a --- /dev/null +++ b/nuttx/arch/arm/include/serial.h @@ -0,0 +1,58 @@ +/**************************************************************************** + * arch/arm/include/serial.h + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_SERIAL_H +#define __ARCH_ARM_INCLUDE_SERIAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* __ARCH_ARM_INCLUDE_SERIAL_H */ diff --git a/nuttx/arch/arm/include/stdarg.h b/nuttx/arch/arm/include/stdarg.h new file mode 100644 index 0000000000..653d34a6ff --- /dev/null +++ b/nuttx/arch/arm/include/stdarg.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * arch/arm/include/stdarg.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_STDARG_H +#define __ARCH_ARM_INCLUDE_STDARG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* This should work with any modern gcc (newer than 3.4 or so) */ + +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +#define va_copy(d,s) __builtin_va_copy(d,s) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef __builtin_va_list va_list; + +#endif /* __ARCH_ARM_INCLUDE_STDARG_H */ diff --git a/nuttx/arch/arm/include/stm32/chip.h b/nuttx/arch/arm/include/stm32/chip.h new file mode 100644 index 0000000000..2bf1d79b45 --- /dev/null +++ b/nuttx/arch/arm/include/stm32/chip.h @@ -0,0 +1,550 @@ +/************************************************************************************ + * arch/arm/include/stm32/chip.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_STM32_CHIP_H +#define __ARCH_ARM_INCLUDE_STM32_CHIP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Get customizations for each supported chip and provide alternate function pin-mapping + * + * NOTE: Each GPIO pin may serve either for general purpose I/O or for a special + * alternate function (such as USART, CAN, USB, SDIO, etc.). That particular + * pin-mapping will depend on the package and STM32 family. If you are incorporating + * a new STM32 chip into NuttX, you will need to add the pin-mapping to a header file + * and to include that header file below. The chip-specific pin-mapping is defined in + * the chip datasheet. + */ + +#if defined(CONFIG_ARCH_CHIP_STM32F100C8) || defined(CONFIG_ARCH_CHIP_STM32F100CB) \ + || defined(CONFIG_ARCH_CHIP_STM32F100R8) || defined(CONFIG_ARCH_CHIP_STM32F100RB) \ + || defined(CONFIG_ARCH_CHIP_STM32F100V8) || defined(CONFIG_ARCH_CHIP_STM32F100VB) +# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F100x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# define CONFIG_STM32_MEDIUMDENSITY 1 /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# define CONFIG_STM32_VALUELINE 1 /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx families */ +# define STM32_NFSMC 0 /* FSMC */ +# define STM32_NATIM 1 /* One advanced timer TIM1 */ +# define STM32_NGTIM 3 /* 16-bit general timers TIM2,3,4 with DMA */ +# define STM32_NBTIM 0 /* No basic timers */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 2 /* SPI1-2 */ +# define STM32_NI2S 0 /* No I2S (?) */ +# define STM32_NUSART 3 /* USART1-3 */ +# define STM32_NI2C 2 /* I2C1-2 */ +# define STM32_NCAN 0 /* No CAN */ +# define STM32_NSDIO 0 /* No SDIO */ +# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */ +# define STM32_NGPIO 80 /* GPIOA-E */ +# define STM32_NADC 1 /* ADC1 */ +# define STM32_NDAC 2 /* DAC 1-2 */ +# define STM32_NCRC 1 /* CRC1 */ +# define STM32_NETHERNET 0 /* No ethernet */ +# define STM32_NRNG 0 /* No random number generator (RNG) */ +# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F103ZET6) +# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# define CONFIG_STM32_HIGHDENSITY 1 /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx families */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 1 /* One advanced timer TIM1 */ +# define STM32_NGTIM 4 /* 16-bit generall timers TIM2,3,4,5 with DMA */ +# define STM32_NBTIM 0 /* No basic timers */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 2 /* SPI1-2 */ +# define STM32_NI2S 0 /* No I2S (?) */ +# define STM32_NUSART 3 /* USART1-3 */ +# define STM32_NI2C 2 /* I2C1-2 */ +# define STM32_NCAN 1 /* CAN1 */ +# define STM32_NSDIO 1 /* SDIO */ +# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */ +# define STM32_NGPIO 112 /* GPIOA-G */ +# define STM32_NADC 1 /* ADC1 */ +# define STM32_NDAC 0 /* No DAC */ +# define STM32_NCRC 0 /* No CRC */ +# define STM32_NETHERNET 0 /* No ethernet */ +# define STM32_NRNG 0 /* No random number generator (RNG) */ +# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F103RET6) +# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# define CONFIG_STM32_HIGHDENSITY 1 /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 2 /* Two advanced timers TIM1 and TIM8 */ +# define STM32_NGTIM 4 /* 16-bit generall timers TIM2,3,4,5 with DMA */ +# define STM32_NBTIM 2 /* Two basic timers TIM6 and TIM7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 0 /* No I2S (?) */ +# define STM32_NUSART 5 /* USART1-5 */ +# define STM32_NI2C 2 /* I2C1-2 */ +# define STM32_NCAN 1 /* CAN1 */ +# define STM32_NSDIO 1 /* SDIO */ +# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */ +# define STM32_NGPIO 51 /* GPIOA-D */ +# define STM32_NADC 2 /* ADC1-2 */ +# define STM32_NDAC 2 /* DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NETHERNET 0 /* No ethernet */ +# define STM32_NRNG 0 /* No random number generator (RNG) */ +# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F103VCT6) +# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# define CONFIG_STM32_HIGHDENSITY 1 /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx families */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 2 /* Two advanced timers TIM1 and TIM8 */ +# define STM32_NGTIM 4 /* General timers TIM2,3,4,5 */ +# define STM32_NBTIM 2 /* Two basic timers TIM6 and TIM7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 0 /* No I2S (?) */ +# define STM32_NUSART 5 /* USART1-5 */ +# define STM32_NI2C 2 /* I2C1-2 */ +# define STM32_NCAN 1 /* bxCAN1 */ +# define STM32_NSDIO 1 /* SDIO */ +# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */ +# define STM32_NGPIO 80 /* GPIOA-E */ +# define STM32_NADC 3 /* ADC1-3 */ +# define STM32_NDAC 2 /* DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NTHERNET 0 /* No ethernet */ +# define STM32_NRNG 0 /* No random number generator (RNG) */ +# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F105VBT7) +# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# define CONFIG_STM32_CONNECTIVITYLINE 1 /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 1 /* One advanced timers TIM1 */ +# define STM32_NGTIM 4 /* 16-bit generall timers TIM2,3,4,5 with DMA */ +# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */ +# define STM32_NUSART 5 /* USART1-3, UART 4-5 */ +# define STM32_NI2C 2 /* I2C1-2 */ +# define STM32_NCAN 2 /* CAN1-2 */ +# define STM32_NSDIO 0 /* No SDIO */ +# define STM32_NUSBOTG 1 /* USB OTG FS/HS */ +# define STM32_NGPIO 80 /* GPIOA-E */ +# define STM32_NADC 2 /* ADC1-2*/ +# define STM32_NDAC 2 /* DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NETHERNET 0 /* 100/100 Ethernet MAC */ +# define STM32_NRNG 0 /* No random number generator (RNG) */ +# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F107VC) +# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# define CONFIG_STM32_CONNECTIVITYLINE 1 /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 1 /* One advanced timers TIM1 */ +# define STM32_NGTIM 4 /* 16-bit generall timers TIM2,3,4,5 with DMA */ +# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */ +# define STM32_NUSART 5 /* USART1-3, UART 4-5 */ +# define STM32_NI2C 1 /* I2C1 */ +# define STM32_NCAN 2 /* CAN1-2 */ +# define STM32_NSDIO 0 /* No SDIO */ +# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */ +# define STM32_NGPIO 80 /* GPIOA-E */ +# define STM32_NADC 2 /* ADC1-2*/ +# define STM32_NDAC 2 /* DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */ +# define STM32_NRNG 0 /* No random number generator (RNG) */ +# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F207IG) /* UFBGA-176 1024Kb FLASH 128Kb SRAM */ +# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# define CONFIG_STM32_STM32F20XX 1 /* STM32F205x and STM32F207x */ +# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */ +# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA + * 32-bit general timers TIM2 and 5 with DMA */ +# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */ +# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */ +# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */ +# define STM32_NI2C 3 /* I2C1-3 */ +# define STM32_NCAN 2 /* CAN1-2 */ +# define STM32_NSDIO 1 /* SDIO */ +# define STM32_NUSBOTG 1 /* USB OTG FS/HS */ +# define STM32_NGPIO 140 /* GPIOA-I */ +# define STM32_NADC 3 /* 12-bit ADC1-3, 24 channels */ +# define STM32_NDAC 2 /* 12-bit DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */ +# define STM32_NRNG 1 /* Random number generator (RNG) */ +# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F405RG) /* LQFP 64 10x10x1.4 1024Kb FLASH 192Kb SRAM */ +# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 0 /* No FSMC */ +# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */ +# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA + * 32-bit general timers TIM2 and 5 with DMA */ +# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */ +# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */ +# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */ +# define STM32_NI2C 3 /* I2C1-3 */ +# define STM32_NCAN 2 /* CAN1-2 */ +# define STM32_NSDIO 1 /* SDIO */ +# define STM32_NUSBOTG 1 /* USB OTG FS/HS */ +# define STM32_NGPIO 139 /* GPIOA-I */ +# define STM32_NADC 3 /* 12-bit ADC1-3, 16 channels */ +# define STM32_NDAC 2 /* 12-bit DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NETHERNET 0 /* No Ethernet MAC */ +# define STM32_NRNG 1 /* Random number generator (RNG) */ +# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F405VG) /* LQFP 100 14x14x1.4 1024Kb FLASH 192Kb SRAM */ +# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */ +# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA + * 32-bit general timers TIM2 and 5 with DMA */ +# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */ +# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */ +# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */ +# define STM32_NI2C 3 /* I2C1-3 */ +# define STM32_NCAN 2 /* CAN1-2 */ +# define STM32_NSDIO 1 /* SDIO */ +# define STM32_NUSBOTG 1 /* USB OTG FS/HS */ +# define STM32_NGPIO 139 /* GPIOA-I */ +# define STM32_NADC 3 /* 12-bit ADC1-3, 16 channels */ +# define STM32_NDAC 2 /* 12-bit DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NETHERNET 0 /* No Ethernet MAC */ +# define STM32_NRNG 1 /* Random number generator (RNG) */ +# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F405ZG) /* LQFP 144 20x20x1.4 1024Kb FLASH 192Kb SRAM */ +# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */ +# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA + * 32-bit general timers TIM2 and 5 with DMA */ +# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */ +# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */ +# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */ +# define STM32_NI2C 3 /* I2C1-3 */ +# define STM32_NCAN 2 /* CAN1-2 */ +# define STM32_NSDIO 1 /* SDIO */ +# define STM32_NUSBOTG 1 /* USB OTG FS/HS */ +# define STM32_NGPIO 139 /* GPIOA-I */ +# define STM32_NADC 3 /* 12-bit ADC1-3, 24 channels */ +# define STM32_NDAC 2 /* 12-bit DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NETHERNET 0 /* No Ethernet MAC */ +# define STM32_NRNG 1 /* Random number generator (RNG) */ +# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F407VE) /* LQFP-100 512Kb FLASH 192Kb SRAM */ +# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */ +# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA + * 32-bit general timers TIM2 and 5 with DMA */ +# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */ +# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */ +# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */ +# define STM32_NI2C 3 /* I2C1-3 */ +# define STM32_NCAN 2 /* CAN1-2 */ +# define STM32_NSDIO 1 /* SDIO */ +# define STM32_NUSBOTG 1 /* USB OTG FS/HS */ +# define STM32_NGPIO 139 /* GPIOA-I */ +# define STM32_NADC 3 /* 12-bit ADC1-3, 16 channels */ +# define STM32_NDAC 2 /* 12-bit DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */ +# define STM32_NRNG 1 /* Random number generator (RNG) */ +# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F407VG) /* LQFP-100 14x14x1.4 1024Kb FLASH 192Kb SRAM */ +# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */ +# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA + * 32-bit general timers TIM2 and 5 with DMA */ +# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */ +# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */ +# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */ +# define STM32_NI2C 3 /* I2C1-3 */ +# define STM32_NCAN 2 /* CAN1-2 */ +# define STM32_NSDIO 1 /* SDIO */ +# define STM32_NUSBOTG 1 /* USB OTG FS/HS */ +# define STM32_NGPIO 139 /* GPIOA-I */ +# define STM32_NADC 3 /* 12-bit ADC1-3, 16 channels */ +# define STM32_NDAC 2 /* 12-bit DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */ +# define STM32_NRNG 1 /* Random number generator (RNG) */ +# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F407ZE) /* LQFP-144 512Kb FLASH 192Kb SRAM */ +# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */ +# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA + * 32-bit general timers TIM2 and 5 with DMA */ +# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */ +# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */ +# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */ +# define STM32_NI2C 3 /* I2C1-3 */ +# define STM32_NCAN 2 /* CAN1-2 */ +# define STM32_NSDIO 1 /* SDIO */ +# define STM32_NUSBOTG 1 /* USB OTG FS/HS */ +# define STM32_NGPIO 139 /* GPIOA-I */ +# define STM32_NADC 3 /* 12-bit ADC1-3, 24 channels */ +# define STM32_NDAC 2 /* 12-bit DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */ +# define STM32_NRNG 1 /* Random number generator (RNG) */ +# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F407ZG) /* LQFP 144 20x20x1.4 1024Kb FLASH 192Kb SRAM */ +# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */ +# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA + * 32-bit general timers TIM2 and 5 with DMA */ +# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */ +# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */ +# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */ +# define STM32_NI2C 3 /* I2C1-3 */ +# define STM32_NCAN 2 /* CAN1-2 */ +# define STM32_NSDIO 1 /* SDIO */ +# define STM32_NUSBOTG 1 /* USB OTG FS/HS */ +# define STM32_NGPIO 139 /* GPIOA-I */ +# define STM32_NADC 3 /* 12-bit ADC1-3, 24 channels */ +# define STM32_NDAC 2 /* 12-bit DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */ +# define STM32_NRNG 1 /* Random number generator (RNG) */ +# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F407IE) /* LQFP 176 24x24x1.4 512Kb FLASH 192Kb SRAM */ +# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */ +# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA + * 32-bit general timers TIM2 and 5 with DMA */ +# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */ +# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */ +# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 (?) */ +# define STM32_NI2C 3 /* I2C1-3 */ +# define STM32_NCAN 2 /* CAN1-2 */ +# define STM32_NSDIO 1 /* SDIO */ +# define STM32_NUSBOTG 1 /* USB OTG FS/HS */ +# define STM32_NGPIO 139 /* GPIOA-I */ +# define STM32_NADC 3 /* 12-bit ADC1-3, 24 channels */ +# define STM32_NDAC 2 /* 12-bit DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */ +# define STM32_NRNG 1 /* Random number generator (RNG) */ +# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F407IG) /* BGA 176; LQFP 176 24x24x1.4 1024Kb FLASH 192Kb SRAM */ +# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 1 /* FSMC */ +# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */ +# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA + * 32-bit general timers TIM2 and 5 with DMA */ +# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */ +# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */ +# define STM32_NDMA 2 /* DMA1-2 */ +# define STM32_NSPI 3 /* SPI1-3 */ +# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */ +# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */ +# define STM32_NI2C 3 /* I2C1-3 */ +# define STM32_NCAN 2 /* CAN1-2 */ +# define STM32_NSDIO 1 /* SDIO */ +# define STM32_NUSBOTG 1 /* USB OTG FS/HS */ +# define STM32_NGPIO 139 /* GPIOA-I */ +# define STM32_NADC 3 /* 12-bit ADC1-3, 24 channels */ +# define STM32_NDAC 2 /* 12-bit DAC1-2 */ +# define STM32_NCRC 1 /* CRC */ +# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */ +# define STM32_NRNG 1 /* Random number generator (RNG) */ +# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */ + +#else +# error "Unsupported STM32 chip" +#endif + +#endif /* __ARCH_ARM_INCLUDE_STM32_CHIP_H */ + diff --git a/nuttx/arch/arm/include/stm32/irq.h b/nuttx/arch/arm/include/stm32/irq.h new file mode 100644 index 0000000000..8421834205 --- /dev/null +++ b/nuttx/arch/arm/include/stm32/irq.h @@ -0,0 +1,117 @@ +/************************************************************************************ + * arch/arm/include/stm32s/irq.h + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/* This file should never be included directed but, rather, + * only indirectly through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_STM32_IRQ_H +#define __ARCH_ARM_INCLUDE_STM32_IRQ_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/* IRQ numbers. The IRQ number corresponds vector number and hence map directly to + * bits in the NVIC. This does, however, waste several words of memory in the IRQ + * to handle mapping tables. + */ + +/* Processor Exceptions (vectors 0-15) */ + +#define STM32_IRQ_RESERVED (0) /* Reserved vector (only used with CONFIG_DEBUG) */ + /* Vector 0: Reset stack pointer value */ + /* Vector 1: Reset (not handler as an IRQ) */ +#define STM32_IRQ_NMI (2) /* Vector 2: Non-Maskable Interrupt (NMI) */ +#define STM32_IRQ_HARDFAULT (3) /* Vector 3: Hard fault */ +#define STM32_IRQ_MEMFAULT (4) /* Vector 4: Memory management (MPU) */ +#define STM32_IRQ_BUSFAULT (5) /* Vector 5: Bus fault */ +#define STM32_IRQ_USAGEFAULT (6) /* Vector 6: Usage fault */ +#define STM32_IRQ_SVCALL (11) /* Vector 11: SVC call */ +#define STM32_IRQ_DBGMONITOR (12) /* Vector 12: Debug Monitor */ + /* Vector 13: Reserved */ +#define STM32_IRQ_PENDSV (14) /* Vector 14: Pendable system service request */ +#define STM32_IRQ_SYSTICK (15) /* Vector 15: System tick */ + +/* External interrupts (vectors >= 16). These definitions are chip-specific */ + +#define STM32_IRQ_INTERRUPTS (16) /* Vector number of the first external interrupt */ + +#if defined(CONFIG_STM32_STM32F10XX) +# include +#elif defined(CONFIG_STM32_STM32F20XX) +# include +#elif defined(CONFIG_STM32_STM32F40XX) +# include +#else +# error "Unsupported STM32 chip" +#endif + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_STM32_IRQ_H */ + diff --git a/nuttx/arch/arm/include/stm32/stm32f10xxx_irq.h b/nuttx/arch/arm/include/stm32/stm32f10xxx_irq.h new file mode 100644 index 0000000000..e9c495b782 --- /dev/null +++ b/nuttx/arch/arm/include/stm32/stm32f10xxx_irq.h @@ -0,0 +1,281 @@ +/************************************************************************************ + * arch/arm/include/stm32s/stm32f10xxx_irq.h + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/* This file should never be included directed but, rather, + * only indirectly through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_STM32F10XXX_IRQ_H +#define __ARCH_ARM_INCLUDE_STM32F10XXX_IRQ_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/* IRQ numbers. The IRQ number corresponds vector number and hence map directly to + * bits in the NVIC. This does, however, waste several words of memory in the IRQ + * to handle mapping tables. + * + * Processor Exceptions (vectors 0-15). These common definitions can be found + * in nuttx/arch/arm/include/stm32/irq.h + * + * External interrupts (vectors >= 16) + */ + +#if defined(CONFIG_STM32_VALUELINE) && defined(CONFIG_STM32_MEDIUMDENSITY) +# define STM32_IRQ_WWDG (16) /* 0: Window Watchdog interrupt */ +# define STM32_IRQ_PVD (17) /* 1: PVD through EXTI Line detection interrupt */ +# define STM32_IRQ_TAMPER (18) /* 2: Tamper interrupt */ +# define STM32_IRQ_RTC (19) /* 3: RTC global interrupt */ +# define STM32_IRQ_FLASH (20) /* 4: Flash global interrupt */ +# define STM32_IRQ_RCC (21) /* 5: RCC global interrupt */ +# define STM32_IRQ_EXTI0 (22) /* 6: EXTI Line 0 interrupt */ +# define STM32_IRQ_EXTI1 (23) /* 7: EXTI Line 1 interrupt */ +# define STM32_IRQ_EXTI2 (24) /* 8: EXTI Line 2 interrupt */ +# define STM32_IRQ_EXTI3 (25) /* 9: EXTI Line 3 interrupt */ +# define STM32_IRQ_EXTI4 (26) /* 10: EXTI Line 4 interrupt */ +# define STM32_IRQ_DMA1CH1 (27) /* 11: DMA1 Channel 1 global interrupt */ +# define STM32_IRQ_DMA1CH2 (28) /* 12: DMA1 Channel 2 global interrupt */ +# define STM32_IRQ_DMA1CH3 (29) /* 13: DMA1 Channel 3 global interrupt */ +# define STM32_IRQ_DMA1CH4 (30) /* 14: DMA1 Channel 4 global interrupt */ +# define STM32_IRQ_DMA1CH5 (31) /* 15: DMA1 Channel 5 global interrupt */ +# define STM32_IRQ_DMA1CH6 (32) /* 16: DMA1 Channel 6 global interrupt */ +# define STM32_IRQ_DMA1CH7 (33) /* 17: DMA1 Channel 7 global interrupt */ +# define STM32_IRQ_ADC12 (34) /* 18: ADC1 and ADC2 global interrupt */ + /* 19-22: reserved */ +# define STM32_IRQ_EXTI95 (39) /* 23: EXTI Line[9:5] interrupts */ +# define STM32_IRQ_TIM1BRK (40) /* 24: TIM1 Break interrupt */ +# define STM32_IRQ_TIM1UP (41) /* 25: TIM1 Update interrupt (TIM16 global interrupt) */ +# define STM32_IRQ_TIM1TRGCOM (42) /* 26: TIM1 Trigger and Commutation interrupts (TIM17 global interrupt) */ +# define STM32_IRQ_TIM1CC (43) /* 27: TIM1 Capture Compare interrupt */ +# define STM32_IRQ_TIM2 (44) /* 28: TIM2 global interrupt */ +# define STM32_IRQ_TIM3 (45) /* 29: TIM3 global interrupt */ +# define STM32_IRQ_TIM4 (46) /* 30: TIM4 global interrupt */ +# define STM32_IRQ_I2C1EV (47) /* 31: I2C1 event interrupt */ +# define STM32_IRQ_I2C1ER (48) /* 32: I2C1 error interrupt */ +# define STM32_IRQ_I2C2EV (49) /* 33: I2C2 event interrupt */ +# define STM32_IRQ_I2C2ER (50) /* 34: I2C2 error interrupt */ +# define STM32_IRQ_SPI1 (51) /* 35: SPI1 global interrupt */ +# define STM32_IRQ_SPI2 (52) /* 36: SPI2 global interrupt */ +# define STM32_IRQ_USART1 (53) /* 37: USART1 global interrupt */ +# define STM32_IRQ_USART2 (54) /* 38: USART2 global interrupt */ +# define STM32_IRQ_USART3 (55) /* 39: USART3 global interrupt */ +# define STM32_IRQ_EXTI1510 (56) /* 40: EXTI Line[15:10] interrupts */ +# define STM32_IRQ_RTCALR (57) /* 41: RTC alarm through EXTI line interrupt */ +# define STM32_IRQ_CEC (58) /* 42: CEC global interrupt */ +# if defined(CONFIG_STM32_HIGHDENSITY) +# define STM32_IRQ_TIM12 (59) /* 43: TIM12 global interrupt */ +# define STM32_IRQ_TIM13 (60) /* 44: TIM13 global interrupt */ +# define STM32_IRQ_TIM14 (61) /* 45: TIM14 global interrupt */ + /* 46-47: reserved */ +# define STM32_IRQ_FSMC (64) /* 48: FSMC global interrupt */ + /* 49: reserved */ +# define STM32_IRQ_TIM5 (66) /* 50: TIM5 global interrupt */ +# define STM32_IRQ_SPI3 (67) /* 51: SPI1 global interrupt */ +# define STM32_IRQ_UART4 (68) /* 52: USART2 global interrupt */ +# define STM32_IRQ_UART5 (69) /* 53: USART3 global interrupt */ +# else + /* 43-53: reserved */ +# endif +# define STM32_IRQ_TIM6 (70) /* 54: TIM6 global interrupt */ +# define STM32_IRQ_TIM7 (71) /* 55: TIM7 global interrupt */ +# define STM32_IRQ_DMA2CH1 (72) /* 56: DMA2 Channel 1 global interrupt */ +# define STM32_IRQ_DMA2CH2 (73) /* 57: DMA2 Channel 2 global interrupt */ +# define STM32_IRQ_DMA2CH3 (74) /* 58: DMA2 Channel 3 global interrupt */ +# define STM32_IRQ_DMA2CH45 (75) /* 59: DMA2 Channel 4 global interrupt */ +# define NR_IRQS (76) +#elif defined(CONFIG_STM32_CONNECTIVITYLINE) +# define STM32_IRQ_WWDG (16) /* 0: Window Watchdog interrupt */ +# define STM32_IRQ_PVD (17) /* 1: PVD through EXTI Line detection interrupt */ +# define STM32_IRQ_TAMPER (18) /* 2: Tamper interrupt */ +# define STM32_IRQ_RTC (19) /* 3: RTC global interrupt */ +# define STM32_IRQ_FLASH (20) /* 4: Flash global interrupt */ +# define STM32_IRQ_RCC (21) /* 5: RCC global interrupt */ +# define STM32_IRQ_EXTI0 (22) /* 6: EXTI Line 0 interrupt */ +# define STM32_IRQ_EXTI1 (23) /* 7: EXTI Line 1 interrupt */ +# define STM32_IRQ_EXTI2 (24) /* 8: EXTI Line 2 interrupt */ +# define STM32_IRQ_EXTI3 (25) /* 9: EXTI Line 3 interrupt */ +# define STM32_IRQ_EXTI4 (26) /* 10: EXTI Line 4 interrupt */ +# define STM32_IRQ_DMA1CH1 (27) /* 11: DMA1 Channel 1 global interrupt */ +# define STM32_IRQ_DMA1CH2 (28) /* 12: DMA1 Channel 2 global interrupt */ +# define STM32_IRQ_DMA1CH3 (29) /* 13: DMA1 Channel 3 global interrupt */ +# define STM32_IRQ_DMA1CH4 (30) /* 14: DMA1 Channel 4 global interrupt */ +# define STM32_IRQ_DMA1CH5 (31) /* 15: DMA1 Channel 5 global interrupt */ +# define STM32_IRQ_DMA1CH6 (32) /* 16: DMA1 Channel 6 global interrupt */ +# define STM32_IRQ_DMA1CH7 (33) /* 17: DMA1 Channel 7 global interrupt */ +# define STM32_IRQ_ADC12 (34) /* 18: ADC1 and ADC2 global interrupt */ +# define STM32_IRQ_CAN1TX (35) /* 19: CAN1 TX interrupts */ +# define STM32_IRQ_CAN1RX0 (36) /* 20: CAN1 RX0 interrupts */ +# define STM32_IRQ_CAN1RX1 (37) /* 21: CAN1 RX1 interrupt */ +# define STM32_IRQ_CAN1SCE (38) /* 22: CAN1 SCE interrupt */ +# define STM32_IRQ_EXTI95 (39) /* 23: EXTI Line[9:5] interrupts */ +# define STM32_IRQ_TIM1BRK (40) /* 24: TIM1 Break interrupt */ +# define STM32_IRQ_TIM1UP (41) /* 25: TIM1 Update interrupt */ +# define STM32_IRQ_TIM1TRGCOM (42) /* 26: TIM1 Trigger and Commutation interrupts */ +# define STM32_IRQ_TIM1CC (43) /* 27: TIM1 Capture Compare interrupt */ +# define STM32_IRQ_TIM2 (44) /* 28: TIM2 global interrupt */ +# define STM32_IRQ_TIM3 (45) /* 29: TIM3 global interrupt */ +# define STM32_IRQ_TIM4 (46) /* 30: TIM4 global interrupt */ +# define STM32_IRQ_I2C1EV (47) /* 31: I2C1 event interrupt */ +# define STM32_IRQ_I2C1ER (48) /* 32: I2C1 error interrupt */ +# define STM32_IRQ_I2C2EV (49) /* 33: I2C2 event interrupt */ +# define STM32_IRQ_I2C2ER (50) /* 34: I2C2 error interrupt */ +# define STM32_IRQ_SPI1 (51) /* 35: SPI1 global interrupt */ +# define STM32_IRQ_SPI2 (52) /* 36: SPI2 global interrupt */ +# define STM32_IRQ_USART1 (53) /* 37: USART1 global interrupt */ +# define STM32_IRQ_USART2 (54) /* 38: USART2 global interrupt */ +# define STM32_IRQ_USART3 (55) /* 39: USART3 global interrupt */ +# define STM32_IRQ_EXTI1510 (56) /* 40: EXTI Line[15:10] interrupts */ +# define STM32_IRQ_RTCALRM (57) /* 41: RTC alarm through EXTI line interrupt */ +# define STM32_IRQ_OTGFSWKUP (58) /* 42: USB On-The-Go FS Wakeup through EXTI line interrupt */ + /* 43-49: Reserved */ +# define STM32_IRQ_TIM5 (66) /* 50: TIM5 global interrupt */ +# define STM32_IRQ_SPI3 (67) /* 51: SPI3 global interrupt */ +# define STM32_IRQ_UART4 (68) /* 52: UART4 global interrupt */ +# define STM32_IRQ_UART5 (69) /* 53: UART5 global interrupt */ +# define STM32_IRQ_TIM6 (70) /* 54: TIM6 global interrupt */ +# define STM32_IRQ_TIM7 (71) /* 55: TIM7 global interrupt */ +# define STM32_IRQ_DMA2CH1 (72) /* 56: DMA2 Channel 1 global interrupt */ +# define STM32_IRQ_DMA2CH2 (73) /* 57: DMA2 Channel 2 global interrupt */ +# define STM32_IRQ_DMA2CH3 (74) /* 58: DMA2 Channel 3 global interrupt */ +# define STM32_IRQ_DMA2CH4 (75) /* 59: DMA2 Channel 4 global interrupt */ +# define STM32_IRQ_DMA2CH5 (76) /* 60: DMA2 Channel 5 global interrupt */ +# define STM32_IRQ_ETH (77) /* 61: Ethernet global interrupt */ +# define STM32_IRQ_ETHWKUP (78) /* 62: Ethernet Wakeup through EXTI line interrupt */ +# define STM32_IRQ_CAN2TX (79) /* 63: CAN2 TX interrupts */ +# define STM32_IRQ_CAN2RX0 (70) /* 64: CAN2 RX0 interrupts */ +# define STM32_IRQ_CAN2RX1 (81) /* 65: CAN2 RX1 interrupt */ +# define STM32_IRQ_CAN2SCE (82) /* 66: CAN2 SCE interrupt */ +# define STM32_IRQ_OTGFS (83) /* 67: USB On The Go FS global interrupt */ +# define NR_IRQS (84) +#else +# define STM32_IRQ_WWDG (16) /* 0: Window Watchdog interrupt */ +# define STM32_IRQ_PVD (17) /* 1: PVD through EXTI Line detection interrupt */ +# define STM32_IRQ_TAMPER (18) /* 2: Tamper interrupt */ +# define STM32_IRQ_RTC (19) /* 3: RTC global interrupt */ +# define STM32_IRQ_FLASH (20) /* 4: Flash global interrupt */ +# define STM32_IRQ_RCC (21) /* 5: RCC global interrupt */ +# define STM32_IRQ_EXTI0 (22) /* 6: EXTI Line 0 interrupt */ +# define STM32_IRQ_EXTI1 (23) /* 7: EXTI Line 1 interrupt */ +# define STM32_IRQ_EXTI2 (24) /* 8: EXTI Line 2 interrupt */ +# define STM32_IRQ_EXTI3 (25) /* 9: EXTI Line 3 interrupt */ +# define STM32_IRQ_EXTI4 (26) /* 10: EXTI Line 4 interrupt */ +# define STM32_IRQ_DMA1CH1 (27) /* 11: DMA1 Channel 1 global interrupt */ +# define STM32_IRQ_DMA1CH2 (28) /* 12: DMA1 Channel 2 global interrupt */ +# define STM32_IRQ_DMA1CH3 (29) /* 13: DMA1 Channel 3 global interrupt */ +# define STM32_IRQ_DMA1CH4 (30) /* 14: DMA1 Channel 4 global interrupt */ +# define STM32_IRQ_DMA1CH5 (31) /* 15: DMA1 Channel 5 global interrupt */ +# define STM32_IRQ_DMA1CH6 (32) /* 16: DMA1 Channel 6 global interrupt */ +# define STM32_IRQ_DMA1CH7 (33) /* 17: DMA1 Channel 7 global interrupt */ +# define STM32_IRQ_ADC12 (34) /* 18: ADC1 and ADC2 global interrupt */ +# define STM32_IRQ_USBHPCANTX (35) /* 19: USB High Priority or CAN TX interrupts*/ +# define STM32_IRQ_USBLPCANRX0 (36) /* 20: USB Low Priority or CAN RX0 interrupts*/ +# define STM32_IRQ_CAN1RX1 (37) /* 21: CAN1 RX1 interrupt */ +# define STM32_IRQ_CAN1SCE (38) /* 22: CAN1 SCE interrupt */ +# define STM32_IRQ_EXTI95 (39) /* 23: EXTI Line[9:5] interrupts */ +# define STM32_IRQ_TIM1BRK (40) /* 24: TIM1 Break interrupt */ +# define STM32_IRQ_TIM1UP (41) /* 25: TIM1 Update interrupt */ +# define STM32_IRQ_TIM1TRGCOM (42) /* 26: TIM1 Trigger and Commutation interrupts */ +# define STM32_IRQ_TIM1CC (43) /* 27: TIM1 Capture Compare interrupt */ +# define STM32_IRQ_TIM2 (44) /* 28: TIM2 global interrupt */ +# define STM32_IRQ_TIM3 (45) /* 29: TIM3 global interrupt */ +# define STM32_IRQ_TIM4 (46) /* 30: TIM4 global interrupt */ +# define STM32_IRQ_I2C1EV (47) /* 31: I2C1 event interrupt */ +# define STM32_IRQ_I2C1ER (48) /* 32: I2C1 error interrupt */ +# define STM32_IRQ_I2C2EV (49) /* 33: I2C2 event interrupt */ +# define STM32_IRQ_I2C2ER (50) /* 34: I2C2 error interrupt */ +# define STM32_IRQ_SPI1 (51) /* 35: SPI1 global interrupt */ +# define STM32_IRQ_SPI2 (52) /* 36: SPI2 global interrupt */ +# define STM32_IRQ_USART1 (53) /* 37: USART1 global interrupt */ +# define STM32_IRQ_USART2 (54) /* 38: USART2 global interrupt */ +# define STM32_IRQ_USART3 (55) /* 39: USART3 global interrupt */ +# define STM32_IRQ_EXTI1510 (56) /* 40: EXTI Line[15:10] interrupts */ +# define STM32_IRQ_RTCALRM (57) /* 41: RTC alarm through EXTI line interrupt */ +# define STM32_IRQ_USBWKUP (58) /* 42: USB wakeup from suspend through EXTI line interrupt*/ +# define STM32_IRQ_TIM8BRK (59) /* 43: TIM8 Break interrupt */ +# define STM32_IRQ_TIM8UP (60) /* 44: TIM8 Update interrupt */ +# define STM32_IRQ_TIM8TRGCOM (61) /* 45: TIM8 Trigger and Commutation interrupts */ +# define STM32_IRQ_TIM8CC (62) /* 46: TIM8 Capture Compare interrupt */ +# define STM32_IRQ_ADC3 (63) /* 47: ADC3 global interrupt */ +# define STM32_IRQ_FSMC (64) /* 48: FSMC global interrupt */ +# define STM32_IRQ_SDIO (65) /* 49: SDIO global interrupt */ +# define STM32_IRQ_TIM5 (66) /* 50: TIM5 global interrupt */ +# define STM32_IRQ_SPI3 (67) /* 51: SPI3 global interrupt */ +# define STM32_IRQ_UART4 (68) /* 52: UART4 global interrupt */ +# define STM32_IRQ_UART5 (69) /* 53: UART5 global interrupt */ +# define STM32_IRQ_TIM6 (70) /* 54: TIM6 global interrupt */ +# define STM32_IRQ_TIM7 (71) /* 55: TIM7 global interrupt */ +# define STM32_IRQ_DMA2CH1 (72) /* 56: DMA2 Channel 1 global interrupt */ +# define STM32_IRQ_DMA2CH2 (73) /* 57: DMA2 Channel 2 global interrupt */ +# define STM32_IRQ_DMA2CH3 (74) /* 58: DMA2 Channel 3 global interrupt */ +# define STM32_IRQ_DMA2CH45 (75) /* 59: DMA2 Channel 4&5 global interrupt */ +# define NR_IRQS (76) +#endif + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_STM32F10XXX_IRQ_H */ + diff --git a/nuttx/arch/arm/include/stm32/stm32f20xxx_irq.h b/nuttx/arch/arm/include/stm32/stm32f20xxx_irq.h new file mode 100644 index 0000000000..d88c5d0704 --- /dev/null +++ b/nuttx/arch/arm/include/stm32/stm32f20xxx_irq.h @@ -0,0 +1,182 @@ +/**************************************************************************************************** + * arch/arm/include/stm32s/stm32f20xxx_irq.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly through nuttx/irq.h */ + +#ifndef __ARCH_ARM_INCLUDE_STM32F20XXX_IRQ_H +#define __ARCH_ARM_INCLUDE_STM32F20XXX_IRQ_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include +#include + +/**************************************************************************************************** + * Definitions + ****************************************************************************************************/ + +/* IRQ numbers. The IRQ number corresponds vector number and hence map directly to + * bits in the NVIC. This does, however, waste several words of memory in the IRQ + * to handle mapping tables. + * + * Processor Exceptions (vectors 0-15). These common definitions can be found + * in nuttx/arch/arm/include/stm32/irq.h + * + * External interrupts (vectors >= 16) + */ + +#define STM32_IRQ_WWDG (STM32_IRQ_INTERRUPTS+0) /* 0: Window Watchdog interrupt */ +#define STM32_IRQ_PVD (STM32_IRQ_INTERRUPTS+1) /* 1: PVD through EXTI Line detection interrupt */ +#define STM32_IRQ_TAMPER (STM32_IRQ_INTERRUPTS+2) /* 2: Tamper and time stamp interrupts */ +#define STM32_IRQ_TIMESTAMP (STM32_IRQ_INTERRUPTS+2) /* 2: Tamper and time stamp interrupts */ +#define STM32_IRQ_RTC_WKUP (STM32_IRQ_INTERRUPTS+3) /* 3: RTC global interrupt */ +#define STM32_IRQ_FLASH (STM32_IRQ_INTERRUPTS+4) /* 4: Flash global interrupt */ +#define STM32_IRQ_RCC (STM32_IRQ_INTERRUPTS+5) /* 5: RCC global interrupt */ +#define STM32_IRQ_EXTI0 (STM32_IRQ_INTERRUPTS+6) /* 6: EXTI Line 0 interrupt */ +#define STM32_IRQ_EXTI1 (STM32_IRQ_INTERRUPTS+7) /* 7: EXTI Line 1 interrupt */ +#define STM32_IRQ_EXTI2 (STM32_IRQ_INTERRUPTS+8) /* 8: EXTI Line 2 interrupt */ +#define STM32_IRQ_EXTI3 (STM32_IRQ_INTERRUPTS+9) /* 9: EXTI Line 3 interrupt */ +#define STM32_IRQ_EXTI4 (STM32_IRQ_INTERRUPTS+10) /* 10: EXTI Line 4 interrupt */ +#define STM32_IRQ_DMA1S0 (STM32_IRQ_INTERRUPTS+11) /* 11: DMA1 Stream 0 global interrupt */ +#define STM32_IRQ_DMA1S1 (STM32_IRQ_INTERRUPTS+12) /* 12: DMA1 Stream 1 global interrupt */ +#define STM32_IRQ_DMA1S2 (STM32_IRQ_INTERRUPTS+13) /* 13: DMA1 Stream 2 global interrupt */ +#define STM32_IRQ_DMA1S3 (STM32_IRQ_INTERRUPTS+14) /* 14: DMA1 Stream 3 global interrupt */ +#define STM32_IRQ_DMA1S4 (STM32_IRQ_INTERRUPTS+15) /* 15: DMA1 Stream 4 global interrupt */ +#define STM32_IRQ_DMA1S5 (STM32_IRQ_INTERRUPTS+16) /* 16: DMA1 Stream 5 global interrupt */ +#define STM32_IRQ_DMA1S6 (STM32_IRQ_INTERRUPTS+17) /* 17: DMA1 Stream 6 global interrupt */ +#define STM32_IRQ_ADC (STM32_IRQ_INTERRUPTS+18) /* 18: ADC1, ADC2, and ADC3 global interrupt */ +#define STM32_IRQ_CAN1TX (STM32_IRQ_INTERRUPTS+19) /* 19: CAN1 TX interrupts */ +#define STM32_IRQ_CAN1RX0 (STM32_IRQ_INTERRUPTS+20) /* 20: CAN1 RX0 interrupts */ +#define STM32_IRQ_CAN1RX1 (STM32_IRQ_INTERRUPTS+21) /* 21: CAN1 RX1 interrupt */ +#define STM32_IRQ_CAN1SCE (STM32_IRQ_INTERRUPTS+22) /* 22: CAN1 SCE interrupt */ +#define STM32_IRQ_EXTI95 (STM32_IRQ_INTERRUPTS+23) /* 23: EXTI Line[9:5] interrupts */ +#define STM32_IRQ_TIM1BRK (STM32_IRQ_INTERRUPTS+24) /* 24: TIM1 Break interrupt */ +#define STM32_IRQ_TIM9 (STM32_IRQ_INTERRUPTS+24) /* 24: TIM9 global interrupt */ +#define STM32_IRQ_TIM1UP (STM32_IRQ_INTERRUPTS+25) /* 25: TIM1 Update interrupt */ +#define STM32_IRQ_TIM10 (STM32_IRQ_INTERRUPTS+25) /* 25: TIM10 global interrupt */ +#define STM32_IRQ_TIM1TRGCOM (STM32_IRQ_INTERRUPTS+26) /* 26: TIM1 Trigger and Commutation interrupts */ +#define STM32_IRQ_TIM11 (STM32_IRQ_INTERRUPTS+26) /* 26: TIM11 global interrupt */ +#define STM32_IRQ_TIM1CC (STM32_IRQ_INTERRUPTS+27) /* 27: TIM1 Capture Compare interrupt */ +#define STM32_IRQ_TIM2 (STM32_IRQ_INTERRUPTS+28) /* 28: TIM2 global interrupt */ +#define STM32_IRQ_TIM3 (STM32_IRQ_INTERRUPTS+29) /* 29: TIM3 global interrupt */ +#define STM32_IRQ_TIM4 (STM32_IRQ_INTERRUPTS+30) /* 30: TIM4 global interrupt */ +#define STM32_IRQ_I2C1EV (STM32_IRQ_INTERRUPTS+31) /* 31: I2C1 event interrupt */ +#define STM32_IRQ_I2C1ER (STM32_IRQ_INTERRUPTS+32) /* 32: I2C1 error interrupt */ +#define STM32_IRQ_I2C2EV (STM32_IRQ_INTERRUPTS+33) /* 33: I2C2 event interrupt */ +#define STM32_IRQ_I2C2ER (STM32_IRQ_INTERRUPTS+34) /* 34: I2C2 error interrupt */ +#define STM32_IRQ_SPI1 (STM32_IRQ_INTERRUPTS+35) /* 35: SPI1 global interrupt */ +#define STM32_IRQ_SPI2 (STM32_IRQ_INTERRUPTS+36) /* 36: SPI2 global interrupt */ +#define STM32_IRQ_USART1 (STM32_IRQ_INTERRUPTS+37) /* 37: USART1 global interrupt */ +#define STM32_IRQ_USART2 (STM32_IRQ_INTERRUPTS+38) /* 38: USART2 global interrupt */ +#define STM32_IRQ_USART3 (STM32_IRQ_INTERRUPTS+39) /* 39: USART3 global interrupt */ +#define STM32_IRQ_EXTI1510 (STM32_IRQ_INTERRUPTS+40) /* 40: EXTI Line[15:10] interrupts */ +#define STM32_IRQ_RTCALRM (STM32_IRQ_INTERRUPTS+41) /* 41: RTC alarm through EXTI line interrupt */ +#define STM32_IRQ_OTGFSWKUP (STM32_IRQ_INTERRUPTS+42) /* 42: USB On-The-Go FS Wakeup through EXTI line interrupt */ +#define STM32_IRQ_TIM8BRK (STM32_IRQ_INTERRUPTS+43) /* 43: TIM8 Break interrupt */ +#define STM32_IRQ_TIM12 (STM32_IRQ_INTERRUPTS+43) /* 43: TIM12 global interrupt */ +#define STM32_IRQ_TIM8UP (STM32_IRQ_INTERRUPTS+44) /* 44: TIM8 Update interrupt */ +#define STM32_IRQ_TIM13 (STM32_IRQ_INTERRUPTS+44) /* 44: TIM13 global interrupt */ +#define STM32_IRQ_TIM8TRGCOM (STM32_IRQ_INTERRUPTS+45) /* 45: TIM8 Trigger and Commutation interrupts */ +#define STM32_IRQ_TIM14 (STM32_IRQ_INTERRUPTS+45) /* 45: TIM14 global interrupt */ +#define STM32_IRQ_TIM8CC (STM32_IRQ_INTERRUPTS+46) /* 46: TIM8 Capture Compare interrupt */ +#define STM32_IRQ_DMA1S7 (STM32_IRQ_INTERRUPTS+47) /* 47: DMA1 Stream 7 global interrupt */ +#define STM32_IRQ_FSMC (STM32_IRQ_INTERRUPTS+48) /* 48: FSMC global interrupt */ +#define STM32_IRQ_SDIO (STM32_IRQ_INTERRUPTS+49) /* 49: SDIO global interrupt */ +#define STM32_IRQ_TIM5 (STM32_IRQ_INTERRUPTS+50) /* 50: TIM5 global interrupt */ +#define STM32_IRQ_SPI3 (STM32_IRQ_INTERRUPTS+51) /* 51: SPI3 global interrupt */ +#define STM32_IRQ_UART4 (STM32_IRQ_INTERRUPTS+52) /* 52: UART4 global interrupt */ +#define STM32_IRQ_UART5 (STM32_IRQ_INTERRUPTS+53) /* 53: UART5 global interrupt */ +#define STM32_IRQ_TIM6 (STM32_IRQ_INTERRUPTS+54) /* 54: TIM6 global interrupt */ +#define STM32_IRQ_DAC (STM32_IRQ_INTERRUPTS+54) /* 54: DAC1 and DAC2 underrun error interrupts */ +#define STM32_IRQ_TIM7 (STM32_IRQ_INTERRUPTS+55) /* 55: TIM7 global interrupt */ +#define STM32_IRQ_DMA2S0 (STM32_IRQ_INTERRUPTS+56) /* 56: DMA2 Stream 0 global interrupt */ +#define STM32_IRQ_DMA2S1 (STM32_IRQ_INTERRUPTS+57) /* 57: DMA2 Stream 1 global interrupt */ +#define STM32_IRQ_DMA2S2 (STM32_IRQ_INTERRUPTS+58) /* 58: DMA2 Stream 2 global interrupt */ +#define STM32_IRQ_DMA2S3 (STM32_IRQ_INTERRUPTS+59) /* 59: DMA2 Stream 3 global interrupt */ +#define STM32_IRQ_DMA2S4 (STM32_IRQ_INTERRUPTS+60) /* 60: DMA2 Stream 4 global interrupt */ +#define STM32_IRQ_ETH (STM32_IRQ_INTERRUPTS+61) /* 61: Ethernet global interrupt */ +#define STM32_IRQ_ETHWKUP (STM32_IRQ_INTERRUPTS+62) /* 62: Ethernet Wakeup through EXTI line interrupt */ +#define STM32_IRQ_CAN2TX (STM32_IRQ_INTERRUPTS+63) /* 63: CAN2 TX interrupts */ +#define STM32_IRQ_CAN2RX0 (STM32_IRQ_INTERRUPTS+64) /* 64: CAN2 RX0 interrupts */ +#define STM32_IRQ_CAN2RX1 (STM32_IRQ_INTERRUPTS+65) /* 65: CAN2 RX1 interrupt */ +#define STM32_IRQ_CAN2SCE (STM32_IRQ_INTERRUPTS+66) /* 66: CAN2 SCE interrupt */ +#define STM32_IRQ_OTGFS (STM32_IRQ_INTERRUPTS+67) /* 67: USB On The Go FS global interrupt */ +#define STM32_IRQ_DMA2S5 (STM32_IRQ_INTERRUPTS+68) /* 68: DMA2 Stream 5 global interrupt */ +#define STM32_IRQ_DMA2S6 (STM32_IRQ_INTERRUPTS+69) /* 69: DMA2 Stream 6 global interrupt */ +#define STM32_IRQ_DMA2S7 (STM32_IRQ_INTERRUPTS+70) /* 70: DMA2 Stream 7 global interrupt */ +#define STM32_IRQ_USART6 (STM32_IRQ_INTERRUPTS+71) /* 71: USART6 global interrupt */ +#define STM32_IRQ_I2C3EV (STM32_IRQ_INTERRUPTS+72) /* 72: I2C3 event interrupt */ +#define STM32_IRQ_I2C3ER (STM32_IRQ_INTERRUPTS+73) /* 73: I2C3 error interrupt */ +#define STM32_IRQ_OTGHSEP1OUT (STM32_IRQ_INTERRUPTS+74) /* 74: USB On The Go HS End Point 1 Out global interrupt */ +#define STM32_IRQ_OTGHSEP1IN (STM32_IRQ_INTERRUPTS+75) /* 75: USB On The Go HS End Point 1 In global interrupt */ +#define STM32_IRQ_OTGHSWKUP (STM32_IRQ_INTERRUPTS+76) /* 76: USB On The Go HS Wakeup through EXTI interrupt */ +#define STM32_IRQ_OTGHS (STM32_IRQ_INTERRUPTS+77) /* 77: USB On The Go HS global interrupt */ +#define STM32_IRQ_DCMI (STM32_IRQ_INTERRUPTS+78) /* 78: DCMI global interrupt */ +#define STM32_IRQ_CRYP (STM32_IRQ_INTERRUPTS+79) /* 79: CRYP crypto global interrupt */ +#define STM32_IRQ_HASH (STM32_IRQ_INTERRUPTS+80) /* 80: Hash and Rng global interrupt */ +#define STM32_IRQ_RNG (STM32_IRQ_INTERRUPTS+80) /* 80: Hash and Rng global interrupt */ + +#define NR_IRQS (STM32_IRQ_INTERRUPTS+81) + +/**************************************************************************************************** + * Public Types + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public Data +****************************************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************************************** + * Public Functions + ****************************************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_STM32F40XXX_IRQ_H */ + diff --git a/nuttx/arch/arm/include/stm32/stm32f40xxx_irq.h b/nuttx/arch/arm/include/stm32/stm32f40xxx_irq.h new file mode 100644 index 0000000000..cd97b9c9df --- /dev/null +++ b/nuttx/arch/arm/include/stm32/stm32f40xxx_irq.h @@ -0,0 +1,185 @@ +/**************************************************************************************************** + * arch/arm/include/stm32s/stm32f40xxx_irq.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +/* This file should never be included directed but, rather, + * only indirectly through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_STM32F40XXX_IRQ_H +#define __ARCH_ARM_INCLUDE_STM32F40XXX_IRQ_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include +#include + +/**************************************************************************************************** + * Definitions + ****************************************************************************************************/ + +/* IRQ numbers. The IRQ number corresponds vector number and hence map directly to + * bits in the NVIC. This does, however, waste several words of memory in the IRQ + * to handle mapping tables. + * + * Processor Exceptions (vectors 0-15). These common definitions can be found + * in nuttx/arch/arm/include/stm32/irq.h + * + * External interrupts (vectors >= 16) + */ + +#define STM32_IRQ_WWDG (STM32_IRQ_INTERRUPTS+0) /* 0: Window Watchdog interrupt */ +#define STM32_IRQ_PVD (STM32_IRQ_INTERRUPTS+1) /* 1: PVD through EXTI Line detection interrupt */ +#define STM32_IRQ_TAMPER (STM32_IRQ_INTERRUPTS+2) /* 2: Tamper and time stamp interrupts */ +#define STM32_IRQ_TIMESTAMP (STM32_IRQ_INTERRUPTS+2) /* 2: Tamper and time stamp interrupts */ +#define STM32_IRQ_RTC_WKUP (STM32_IRQ_INTERRUPTS+3) /* 3: RTC global interrupt */ +#define STM32_IRQ_FLASH (STM32_IRQ_INTERRUPTS+4) /* 4: Flash global interrupt */ +#define STM32_IRQ_RCC (STM32_IRQ_INTERRUPTS+5) /* 5: RCC global interrupt */ +#define STM32_IRQ_EXTI0 (STM32_IRQ_INTERRUPTS+6) /* 6: EXTI Line 0 interrupt */ +#define STM32_IRQ_EXTI1 (STM32_IRQ_INTERRUPTS+7) /* 7: EXTI Line 1 interrupt */ +#define STM32_IRQ_EXTI2 (STM32_IRQ_INTERRUPTS+8) /* 8: EXTI Line 2 interrupt */ +#define STM32_IRQ_EXTI3 (STM32_IRQ_INTERRUPTS+9) /* 9: EXTI Line 3 interrupt */ +#define STM32_IRQ_EXTI4 (STM32_IRQ_INTERRUPTS+10) /* 10: EXTI Line 4 interrupt */ +#define STM32_IRQ_DMA1S0 (STM32_IRQ_INTERRUPTS+11) /* 11: DMA1 Stream 0 global interrupt */ +#define STM32_IRQ_DMA1S1 (STM32_IRQ_INTERRUPTS+12) /* 12: DMA1 Stream 1 global interrupt */ +#define STM32_IRQ_DMA1S2 (STM32_IRQ_INTERRUPTS+13) /* 13: DMA1 Stream 2 global interrupt */ +#define STM32_IRQ_DMA1S3 (STM32_IRQ_INTERRUPTS+14) /* 14: DMA1 Stream 3 global interrupt */ +#define STM32_IRQ_DMA1S4 (STM32_IRQ_INTERRUPTS+15) /* 15: DMA1 Stream 4 global interrupt */ +#define STM32_IRQ_DMA1S5 (STM32_IRQ_INTERRUPTS+16) /* 16: DMA1 Stream 5 global interrupt */ +#define STM32_IRQ_DMA1S6 (STM32_IRQ_INTERRUPTS+17) /* 17: DMA1 Stream 6 global interrupt */ +#define STM32_IRQ_ADC (STM32_IRQ_INTERRUPTS+18) /* 18: ADC1, ADC2, and ADC3 global interrupt */ +#define STM32_IRQ_CAN1TX (STM32_IRQ_INTERRUPTS+19) /* 19: CAN1 TX interrupts */ +#define STM32_IRQ_CAN1RX0 (STM32_IRQ_INTERRUPTS+20) /* 20: CAN1 RX0 interrupts */ +#define STM32_IRQ_CAN1RX1 (STM32_IRQ_INTERRUPTS+21) /* 21: CAN1 RX1 interrupt */ +#define STM32_IRQ_CAN1SCE (STM32_IRQ_INTERRUPTS+22) /* 22: CAN1 SCE interrupt */ +#define STM32_IRQ_EXTI95 (STM32_IRQ_INTERRUPTS+23) /* 23: EXTI Line[9:5] interrupts */ +#define STM32_IRQ_TIM1BRK (STM32_IRQ_INTERRUPTS+24) /* 24: TIM1 Break interrupt */ +#define STM32_IRQ_TIM9 (STM32_IRQ_INTERRUPTS+24) /* 24: TIM9 global interrupt */ +#define STM32_IRQ_TIM1UP (STM32_IRQ_INTERRUPTS+25) /* 25: TIM1 Update interrupt */ +#define STM32_IRQ_TIM10 (STM32_IRQ_INTERRUPTS+25) /* 25: TIM10 global interrupt */ +#define STM32_IRQ_TIM1TRGCOM (STM32_IRQ_INTERRUPTS+26) /* 26: TIM1 Trigger and Commutation interrupts */ +#define STM32_IRQ_TIM11 (STM32_IRQ_INTERRUPTS+26) /* 26: TIM11 global interrupt */ +#define STM32_IRQ_TIM1CC (STM32_IRQ_INTERRUPTS+27) /* 27: TIM1 Capture Compare interrupt */ +#define STM32_IRQ_TIM2 (STM32_IRQ_INTERRUPTS+28) /* 28: TIM2 global interrupt */ +#define STM32_IRQ_TIM3 (STM32_IRQ_INTERRUPTS+29) /* 29: TIM3 global interrupt */ +#define STM32_IRQ_TIM4 (STM32_IRQ_INTERRUPTS+30) /* 30: TIM4 global interrupt */ +#define STM32_IRQ_I2C1EV (STM32_IRQ_INTERRUPTS+31) /* 31: I2C1 event interrupt */ +#define STM32_IRQ_I2C1ER (STM32_IRQ_INTERRUPTS+32) /* 32: I2C1 error interrupt */ +#define STM32_IRQ_I2C2EV (STM32_IRQ_INTERRUPTS+33) /* 33: I2C2 event interrupt */ +#define STM32_IRQ_I2C2ER (STM32_IRQ_INTERRUPTS+34) /* 34: I2C2 error interrupt */ +#define STM32_IRQ_SPI1 (STM32_IRQ_INTERRUPTS+35) /* 35: SPI1 global interrupt */ +#define STM32_IRQ_SPI2 (STM32_IRQ_INTERRUPTS+36) /* 36: SPI2 global interrupt */ +#define STM32_IRQ_USART1 (STM32_IRQ_INTERRUPTS+37) /* 37: USART1 global interrupt */ +#define STM32_IRQ_USART2 (STM32_IRQ_INTERRUPTS+38) /* 38: USART2 global interrupt */ +#define STM32_IRQ_USART3 (STM32_IRQ_INTERRUPTS+39) /* 39: USART3 global interrupt */ +#define STM32_IRQ_EXTI1510 (STM32_IRQ_INTERRUPTS+40) /* 40: EXTI Line[15:10] interrupts */ +#define STM32_IRQ_RTCALRM (STM32_IRQ_INTERRUPTS+41) /* 41: RTC alarm through EXTI line interrupt */ +#define STM32_IRQ_OTGFSWKUP (STM32_IRQ_INTERRUPTS+42) /* 42: USB On-The-Go FS Wakeup through EXTI line interrupt */ +#define STM32_IRQ_TIM8BRK (STM32_IRQ_INTERRUPTS+43) /* 43: TIM8 Break interrupt */ +#define STM32_IRQ_TIM12 (STM32_IRQ_INTERRUPTS+43) /* 43: TIM12 global interrupt */ +#define STM32_IRQ_TIM8UP (STM32_IRQ_INTERRUPTS+44) /* 44: TIM8 Update interrupt */ +#define STM32_IRQ_TIM13 (STM32_IRQ_INTERRUPTS+44) /* 44: TIM13 global interrupt */ +#define STM32_IRQ_TIM8TRGCOM (STM32_IRQ_INTERRUPTS+45) /* 45: TIM8 Trigger and Commutation interrupts */ +#define STM32_IRQ_TIM14 (STM32_IRQ_INTERRUPTS+45) /* 45: TIM14 global interrupt */ +#define STM32_IRQ_TIM8CC (STM32_IRQ_INTERRUPTS+46) /* 46: TIM8 Capture Compare interrupt */ +#define STM32_IRQ_DMA1S7 (STM32_IRQ_INTERRUPTS+47) /* 47: DMA1 Stream 7 global interrupt */ +#define STM32_IRQ_FSMC (STM32_IRQ_INTERRUPTS+48) /* 48: FSMC global interrupt */ +#define STM32_IRQ_SDIO (STM32_IRQ_INTERRUPTS+49) /* 49: SDIO global interrupt */ +#define STM32_IRQ_TIM5 (STM32_IRQ_INTERRUPTS+50) /* 50: TIM5 global interrupt */ +#define STM32_IRQ_SPI3 (STM32_IRQ_INTERRUPTS+51) /* 51: SPI3 global interrupt */ +#define STM32_IRQ_UART4 (STM32_IRQ_INTERRUPTS+52) /* 52: UART4 global interrupt */ +#define STM32_IRQ_UART5 (STM32_IRQ_INTERRUPTS+53) /* 53: UART5 global interrupt */ +#define STM32_IRQ_TIM6 (STM32_IRQ_INTERRUPTS+54) /* 54: TIM6 global interrupt */ +#define STM32_IRQ_DAC (STM32_IRQ_INTERRUPTS+54) /* 54: DAC1 and DAC2 underrun error interrupts */ +#define STM32_IRQ_TIM7 (STM32_IRQ_INTERRUPTS+55) /* 55: TIM7 global interrupt */ +#define STM32_IRQ_DMA2S0 (STM32_IRQ_INTERRUPTS+56) /* 56: DMA2 Stream 0 global interrupt */ +#define STM32_IRQ_DMA2S1 (STM32_IRQ_INTERRUPTS+57) /* 57: DMA2 Stream 1 global interrupt */ +#define STM32_IRQ_DMA2S2 (STM32_IRQ_INTERRUPTS+58) /* 58: DMA2 Stream 2 global interrupt */ +#define STM32_IRQ_DMA2S3 (STM32_IRQ_INTERRUPTS+59) /* 59: DMA2 Stream 3 global interrupt */ +#define STM32_IRQ_DMA2S4 (STM32_IRQ_INTERRUPTS+60) /* 60: DMA2 Stream 4 global interrupt */ +#define STM32_IRQ_ETH (STM32_IRQ_INTERRUPTS+61) /* 61: Ethernet global interrupt */ +#define STM32_IRQ_ETHWKUP (STM32_IRQ_INTERRUPTS+62) /* 62: Ethernet Wakeup through EXTI line interrupt */ +#define STM32_IRQ_CAN2TX (STM32_IRQ_INTERRUPTS+63) /* 63: CAN2 TX interrupts */ +#define STM32_IRQ_CAN2RX0 (STM32_IRQ_INTERRUPTS+64) /* 64: CAN2 RX0 interrupts */ +#define STM32_IRQ_CAN2RX1 (STM32_IRQ_INTERRUPTS+65) /* 65: CAN2 RX1 interrupt */ +#define STM32_IRQ_CAN2SCE (STM32_IRQ_INTERRUPTS+66) /* 66: CAN2 SCE interrupt */ +#define STM32_IRQ_OTGFS (STM32_IRQ_INTERRUPTS+67) /* 67: USB On The Go FS global interrupt */ +#define STM32_IRQ_DMA2S5 (STM32_IRQ_INTERRUPTS+68) /* 68: DMA2 Stream 5 global interrupt */ +#define STM32_IRQ_DMA2S6 (STM32_IRQ_INTERRUPTS+69) /* 69: DMA2 Stream 6 global interrupt */ +#define STM32_IRQ_DMA2S7 (STM32_IRQ_INTERRUPTS+70) /* 70: DMA2 Stream 7 global interrupt */ +#define STM32_IRQ_USART6 (STM32_IRQ_INTERRUPTS+71) /* 71: USART6 global interrupt */ +#define STM32_IRQ_I2C3EV (STM32_IRQ_INTERRUPTS+72) /* 72: I2C3 event interrupt */ +#define STM32_IRQ_I2C3ER (STM32_IRQ_INTERRUPTS+73) /* 73: I2C3 error interrupt */ +#define STM32_IRQ_OTGHSEP1OUT (STM32_IRQ_INTERRUPTS+74) /* 74: USB On The Go HS End Point 1 Out global interrupt */ +#define STM32_IRQ_OTGHSEP1IN (STM32_IRQ_INTERRUPTS+75) /* 75: USB On The Go HS End Point 1 In global interrupt */ +#define STM32_IRQ_OTGHSWKUP (STM32_IRQ_INTERRUPTS+76) /* 76: USB On The Go HS Wakeup through EXTI interrupt */ +#define STM32_IRQ_OTGHS (STM32_IRQ_INTERRUPTS+77) /* 77: USB On The Go HS global interrupt */ +#define STM32_IRQ_DCMI (STM32_IRQ_INTERRUPTS+78) /* 78: DCMI global interrupt */ +#define STM32_IRQ_CRYP (STM32_IRQ_INTERRUPTS+79) /* 79: CRYP crypto global interrupt */ +#define STM32_IRQ_HASH (STM32_IRQ_INTERRUPTS+80) /* 80: Hash and Rng global interrupt */ +#define STM32_IRQ_RNG (STM32_IRQ_INTERRUPTS+80) /* 80: Hash and Rng global interrupt */ +#define STM32_IRQ_FPU (STM32_IRQ_INTERRUPTS+81) /* 81: FPU global interrupt */ + +#define NR_IRQS (STM32_IRQ_INTERRUPTS+82) + +/**************************************************************************************************** + * Public Types + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public Data + ****************************************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************************************** + * Public Functions + ****************************************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_STM32F40XXX_IRQ_H */ + diff --git a/nuttx/arch/arm/include/syscall.h b/nuttx/arch/arm/include/syscall.h new file mode 100644 index 0000000000..4c9eee63ef --- /dev/null +++ b/nuttx/arch/arm/include/syscall.h @@ -0,0 +1,90 @@ +/**************************************************************************** + * arch/arm/include/syscall.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through include/syscall.h or include/sys/sycall.h + */ + +#ifndef __ARCH_ARM_INCLUDE_SYSCALL_H +#define __ARCH_ARM_INCLUDE_SYSCALL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Include ARM architecture-specific syscall macros */ + +#if defined(CONFIG_ARCH_CORTEXM3) || defined(CONFIG_ARCH_CORTEXM4) +# include +#else +# include +#endif + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_SYSCALL_H */ + diff --git a/nuttx/arch/arm/include/types.h b/nuttx/arch/arm/include/types.h new file mode 100644 index 0000000000..c3471ca59b --- /dev/null +++ b/nuttx/arch/arm/include/types.h @@ -0,0 +1,101 @@ +/**************************************************************************** + * arch/arm/include/types.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through sys/types.h + */ + +#ifndef __ARCH_ARM_INCLUDE_TYPES_H +#define __ARCH_ARM_INCLUDE_TYPES_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Type Declarations + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* These are the sizes of the standard integer types. NOTE that these type + * names have a leading underscore character. This file will be included + * (indirectly) by include/stdint.h and typedef'ed to the final name without + * the underscore character. This roundabout way of doings things allows + * the stdint.h to be removed from the include/ directory in the event that + * the user prefers to use the definitions provided by their toolchain header + * files + */ + +typedef signed char _int8_t; +typedef unsigned char _uint8_t; + +typedef signed short _int16_t; +typedef unsigned short _uint16_t; + +typedef signed int _int32_t; +typedef unsigned int _uint32_t; + +typedef signed long long _int64_t; +typedef unsigned long long _uint64_t; +#define __INT64_DEFINED + +/* A pointer is 4 bytes */ + +typedef signed int _intptr_t; +typedef unsigned int _uintptr_t; + +/* This is the size of the interrupt state save returned by irqsave(). For + * ARM, a 32 register value is returned, for the thumb2, Cortex-M3, the 16-bit + * primask register value is returned, + */ + +#ifdef __thumb2__ +typedef unsigned short irqstate_t; +#else /* __thumb2__ */ +typedef unsigned int irqstate_t; +#endif /* __thumb2__ */ + +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#endif /* __ARCH_ARM_INCLUDE_TYPES_H */ diff --git a/nuttx/arch/arm/include/watchdog.h b/nuttx/arch/arm/include/watchdog.h new file mode 100644 index 0000000000..f70b8d2e9a --- /dev/null +++ b/nuttx/arch/arm/include/watchdog.h @@ -0,0 +1,61 @@ +/**************************************************************************** + * arch/arm/include/watchdog.h + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_WATCHDOG_H +#define __ARCH_ARM_INCLUDE_WATCHDOG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* __ARCH_ARM_INCLUDE_WATCHDOG_H */ diff --git a/nuttx/arch/arm/src/Makefile b/nuttx/arch/arm/src/Makefile new file mode 100644 index 0000000000..ef04153756 --- /dev/null +++ b/nuttx/arch/arm/src/Makefile @@ -0,0 +1,162 @@ +############################################################################ +# arch/arm/src/Makefile +# +# Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs +-include chip/Make.defs + +ARCH_SRCDIR = $(TOPDIR)/arch/$(CONFIG_ARCH)/src +ifeq ($(CONFIG_ARCH_CORTEXM3),y) # Cortex-M3 is ARMv7-M +ARCH_SUBDIR = armv7-m +else +ifeq ($(CONFIG_ARCH_CORTEXM4),y) # Cortex-M4 is ARMv7E-M +ARCH_SUBDIR = armv7-m +else +ARCH_SUBDIR = arm +endif +endif + +ifeq ($(WINTOOL),y) + NUTTX = "${shell cygpath -w $(TOPDIR)/nuttx}" + CFLAGS += -I "${shell cygpath -w $(ARCH_SRCDIR)/chip}" \ + -I "${shell cygpath -w $(ARCH_SRCDIR)/common}" \ + -I "${shell cygpath -w $(ARCH_SRCDIR)/$(ARCH_SUBDIR)}" \ + -I "${shell cygpath -w $(TOPDIR)/sched}" +else + NUTTX = $(TOPDIR)/nuttx + CFLAGS += -I$(ARCH_SRCDIR)/chip -I$(ARCH_SRCDIR)/common \ + -I$(ARCH_SRCDIR)/$(ARCH_SUBDIR) -I$(TOPDIR)/sched +endif + +HEAD_OBJ = $(HEAD_ASRC:.S=$(OBJEXT)) + +ASRCS = $(CHIP_ASRCS) $(CMN_ASRCS) +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +CSRCS = $(CHIP_CSRCS) $(CMN_CSRCS) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +LDFLAGS = $(ARCHSCRIPT) +EXTRA_LIBS ?= + +LINKLIBS = +ifeq ($(WINTOOL),y) + LIBPATHS = ${shell for path in $(LINKLIBS); do dir=`dirname $(TOPDIR)/$$path`;echo "-L\"`cygpath -w $$dir`\"";done} + LIBPATHS += -L"${shell cygpath -w $(BOARDDIR)}" +else + LIBPATHS = $(addprefix -L$(TOPDIR)/,$(dir $(LINKLIBS))) + LIBPATHS += -L"$(BOARDDIR)" +endif +LDLIBS = $(patsubst lib%,-l%,$(basename $(notdir $(LINKLIBS)))) + +BOARDDIR = $(TOPDIR)/arch/$(CONFIG_ARCH)/src/board + +LIBGCC = "${shell $(CC) $(ARCHCPUFLAGS) -print-libgcc-file-name}" + +VPATH = chip:common:$(ARCH_SUBDIR) + +all: $(HEAD_OBJ) libarch$(LIBEXT) + +.PHONY: board/libboard$(LIBEXT) + +$(AOBJS) $(HEAD_OBJ): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +libarch$(LIBEXT): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +board/libboard$(LIBEXT): + @$(MAKE) -C board TOPDIR="$(TOPDIR)" libboard$(LIBEXT) EXTRADEFINES=$(EXTRADEFINES) + +nuttx: $(HEAD_OBJ) board/libboard$(LIBEXT) + @echo "LD: nuttx" + @$(LD) --entry=__start $(LDFLAGS) $(LIBPATHS) -o $(NUTTX)$(EXEEXT) $(HEAD_OBJ) $(EXTRA_OBJS) \ + --start-group $(LDLIBS) -lboard $(EXTRA_LIBS) $(LIBGCC) --end-group +ifeq ($(CONFIG_BOOT_RUNFROMFLASH),y) + @export flashloc=`$(OBJDUMP) --all-headers $(NUTTX)$(EXEEXT) | grep _eronly | cut -d' ' -f1`; \ + $(OBJCOPY) $(OBJCOPYARGS) --adjust-section-vma=.data=0x$$flashloc $(NUTTX)$(EXEEXT) $(NUTTX).flashimage + @mv $(NUTTX).flashimage $(NUTTX)$(EXEEXT) +endif + @$(NM) $(NUTTX)$(EXEEXT) | \ + grep -v '\(compiled\)\|\(\$(OBJEXT)$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \ + sort > $(TOPDIR)/System.map + +# This is part of the top-level export target +# Note that there may not be a head object if layout is handled +# by the linker configuration. + +export_head: board/libboard$(LIBEXT) $(HEAD_OBJ) +ifneq ($(HEAD_OBJ),) + @if [ -d "$(EXPORT_DIR)/startup" ]; then \ + cp -f $(HEAD_OBJ) "$(EXPORT_DIR)/startup"; \ + else \ + echo "$(EXPORT_DIR)/startup does not exist"; \ + exit 1; \ + fi +endif + +# Dependencies + +.depend: Makefile chip/Make.defs $(SRCS) + @if [ -e board/Makefile ]; then \ + $(MAKE) -C board TOPDIR="$(TOPDIR)" depend ; \ + fi + @$(MKDEP) --dep-path chip --dep-path common --dep-path $(ARCH_SUBDIR) \ + $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @if [ -e board/Makefile ]; then \ + $(MAKE) -C board TOPDIR="$(TOPDIR)" clean ; \ + fi + @rm -f libarch$(LIBEXT) *~ .*.swp + $(call CLEAN) + +distclean: clean + @if [ -e board/Makefile ]; then \ + $(MAKE) -C board TOPDIR="$(TOPDIR)" distclean ; \ + fi + @rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/arch/arm/src/arm/arm.h b/nuttx/arch/arm/src/arm/arm.h new file mode 100644 index 0000000000..4332838149 --- /dev/null +++ b/nuttx/arch/arm/src/arm/arm.h @@ -0,0 +1,451 @@ +/************************************************************************************ + * arch/arm/src/arm/arm.h + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_COMMON_ARM_H +#define __ARCH_ARM_SRC_COMMON_ARM_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#undef CONFIG_ALIGNMENT_TRAP +#undef CONFIG_DCACHE_WRITETHROUGH +#undef CONFIG_CACHE_ROUND_ROBIN +#undef CONFIG_DCACHE_DISABLE +#undef CONFIG_ICACHE_DISABLE + +/* ARM9EJS **************************************************************************/ + +/* PSR bits */ + +#define MODE_MASK 0x0000001f /* Bits 0-4: Mode bits */ +# define USR26_MODE 0x00000000 /* 26-bit User mode */ +# define FIQ26_MODE 0x00000001 /* 26-bit FIQ mode */ +# define IRQ26_MODE 0x00000002 /* 26-bit IRQ mode */ +# define SVC26_MODE 0x00000003 /* 26-bit Supervisor mode */ +# define MODE32_BIT 0x00000010 /* Bit 4: 32-bit mode */ +# define USR_MODE 0x00000010 /* 32-bit User mode */ +# define FIQ_MODE 0x00000011 /* 32-bit FIQ mode */ +# define IRQ_MODE 0x00000012 /* 32-bit IRQ mode */ +# define SVC_MODE 0x00000013 /* 32-bit Supervisor mode */ +# define ABT_MODE 0x00000017 /* 32-bit Abort mode */ +# define UND_MODE 0x0000001b /* 32-bit Undefined mode */ +# define SYSTEM_MODE 0x0000001f /* 32-bit System mode */ +#define PSR_T_BIT 0x00000020 /* Bit 5: Thumb state */ +#define PSR_F_BIT 0x00000040 /* Bit 6: FIQ disable */ +#define PSR_I_BIT 0x00000080 /* Bit 7: IRQ disable */ + /* Bits 8-23: Reserved */ +#define PSR_J_BIT 0x01000000 /* Bit 24: Jazelle state bit */ + /* Bits 25-26: Reserved */ +#define PSR_Q_BIT 0x08000000 /* Bit 27: Sticky overflow */ +#define PSR_V_BIT 0x10000000 /* Bit 28: Overflow */ +#define PSR_C_BIT 0x20000000 /* Bit 29: Carry/Borrow/Extend */ +#define PSR_Z_BIT 0x40000000 /* Bit 30: Zero */ +#define PSR_N_BIT 0x80000000 /* Bit 31: Negative/Less than */ + +/* CR1 bits (CP#15 CR1) */ + +#define CR_M 0x00000001 /* MMU enable */ +#define CR_A 0x00000002 /* Alignment abort enable */ +#define CR_C 0x00000004 /* Dcache enable */ +#define CR_W 0x00000008 /* Write buffer enable */ +#define CR_P 0x00000010 /* 32-bit exception handler */ +#define CR_D 0x00000020 /* 32-bit data address range */ +#define CR_L 0x00000040 /* Implementation defined */ +#define CR_B 0x00000080 /* Big endian */ +#define CR_S 0x00000100 /* System MMU protection */ +#define CR_R 0x00000200 /* ROM MMU protection */ +#define CR_F 0x00000400 /* Implementation defined */ +#define CR_Z 0x00000800 /* Implementation defined */ +#define CR_I 0x00001000 /* Icache enable */ +#define CR_V 0x00002000 /* Vectors relocated to 0xffff0000 */ +#define CR_RR 0x00004000 /* Round Robin cache replacement */ +#define CR_L4 0x00008000 /* LDR pc can set T bit */ +#define CR_DT 0x00010000 +#define CR_IT 0x00040000 +#define CR_ST 0x00080000 +#define CR_FI 0x00200000 /* Fast interrupt (lower latency mode) */ +#define CR_U 0x00400000 /* Unaligned access operation */ +#define CR_XP 0x00800000 /* Extended page tables */ +#define CR_VE 0x01000000 /* Vectored interrupts */ + +/* The lowest 4-bits of the FSR register indicates the fault generated by + * the MMU. + */ + +#define FSR_MASK 15 /* Bits 0-3: Type of fault */ +#define FSR_VECTOR 0 /* Vector exception */ +#define FSR_ALIGN1 1 /* Alignment fault */ +#define FSR_TERMINAL 2 /* Terminal exception */ +#define FSR_ALIGN2 3 /* Alignment fault */ +#define FSR_LINESECT 4 /* External abort on linefetch for section translation */ +#define FSR_SECT 5 /* Section translation fault (unmapped virtual address) */ +#define FSR_LINEPAGE 6 /* External abort on linefetch for page translation */ +#define FSR_PAGE 7 /* Page translation fault (unmapped virtual address) */ +#define FSR_NLINESECT 8 /* External abort on non-linefetch for section translation */ +#define FSR_DOMSECT 9 /* Domain fault on section translation (i.e. accessing invalid domain) */ +#define FSR_NLINEPAGE 10 /* External abort on non-linefetch for page translation */ +#define FSR_DOMPAGE 11 /* Domain fault on page translation (i.e. accessing invalid domain) */ +#define FSR_EXTERN1 12 /* External abort on first level translation */ +#define FSR_PERMSECT 13 /* Permission fault on section (i.e. no permission to access virtual address) */ +#define FSR_EXTERN2 14 /* External abort on second level translation */ +#define FSR_PERMPAGE 15 /* Permission fault on page (i.e. no permission to access virtual address) */ + +#define FSR_DOM_SHIFT 4 /* Bits 4-7: Domain */ +#define FSR_DOM_MASK (15 << FSR_DOM_SHIFT) + +/* Hardware page table definitions. + * + * Level 1 Descriptor (PMD) + * + * Common definitions. + */ + +#define PMD_TYPE_MASK 0x00000003 /* Bits 1:0: Type of descriptor */ +#define PMD_TYPE_FAULT 0x00000000 +#define PMD_TYPE_COARSE 0x00000001 +#define PMD_TYPE_SECT 0x00000002 +#define PMD_TYPE_FINE 0x00000003 + /* Bits 3:2: Depends on descriptor */ +#define PMD_BIT4 0x00000010 /* Bit 4: Must be one */ +#define PMD_DOMAIN_MASK 0x000001e0 /* Bits 8:5: Domain control bits */ +#define PMD_DOMAIN(x) ((x) << 5) +#define PMD_PROTECTION 0x00000200 /* Bit 9: v5 only */ + /* Bits 31:10: Depend on descriptor */ + +/* Level 1 Section Descriptor. Section descriptors allow fast, single + * level mapping between 1Mb address regions. + */ + /* Bits 1:0: Type of mapping */ +#define PMD_SECT_BUFFERABLE 0x00000004 /* Bit 2: 1=bufferable */ +#define PMD_SECT_CACHEABLE 0x00000008 /* Bit 3: 1=cacheable */ + /* Bit 4: Common, must be one */ + /* Bits 8:5: Common domain control */ + /* Bit 9: Common protection */ +#define PMD_SECT_AP_MASK 0x00000c00 /* Bits 11:10: Access permission */ +#define PMD_SECT_AP_WRITE 0x00000400 +#define PMD_SECT_AP_READ 0x00000800 + /* Bits 19:20: Should be zero */ +#define PMD_SECT_TEX_MASK 0xfff00000 /* Bits 31:20: v5, Physical page */ +#define PMD_SECT_APX 0x00008000 /* Bit 15: v6 only */ +#define PMD_SECT_S 0x00010000 /* Bit 16: v6 only */ +#define PMD_SECT_nG 0x00020000 /* Bit 17: v6 only */ + +#define PMD_SECT_UNCACHED (0) +#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE) +#define PMD_SECT_WT (PMD_SECT_CACHEABLE) +#define PMD_SECT_WB (PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE) +#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1)|PMD_SECT_CACHEABLE) +#define PMD_SECT_WBWA (PMD_SECT_TEX(1)|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE) + +/* Level 1 Coarse Table Descriptor. Coarse Table Descriptors support + * two level mapping between 16Kb memory regions. + */ + /* Bits 1:0: Type of mapping */ + /* Bits 3:2: Should be zero */ + /* Bit 4: Common, must be one */ + /* Bits 8:5: Common domain control */ + /* Bits 9: Should be zero */ +#define PMD_COARSE_TEX_MASK 0xfffffc00 /* Bits 31:10: v5, Physical page */ + +/* Level 1 Fine Table Descriptor. Coarse Table Descriptors support + * two level mapping between 4Kb memory regions. + */ + + /* Bits 1:0: Type of mapping */ + /* Bits 3:2: Should be zero */ + /* Bit 4: Common, must be one */ + /* Bits 8:5: Common domain control */ + /* Bits 11:9: Should be zero */ +#define PMD_FINE_TEX_MASK 0xfffff000 /* Bits 31:12: v5, Physical page */ + +/* Level 2 Table Descriptor (PTE). A section descriptor provides the base address + * of a 1MB block of memory. The page table descriptors provide the base address of + * a page table that contains second-level descriptors. There are two sizes of page + * table: + * - Coarse page tables have 256 entries, splitting the 1MB that the table + * describes into 4KB blocks + * - Fine/tiny page tables have 1024 entries, splitting the 1MB that the table + * describes into 1KB blocks. + * + * The following definitions apply to all L2 tables: + */ + +#define PTE_TYPE_MASK (3 << 0) /* Bits: 1:0: Type of mapping */ +#define PTE_TYPE_FAULT (0 << 0) /* None */ +#define PTE_TYPE_LARGE (1 << 0) /* 64Kb of memory */ +#define PTE_TYPE_SMALL (2 << 0) /* 4Kb of memory */ +#define PTE_TYPE_TINY (3 << 0) /* 1Kb of memory (v5)*/ +#define PTE_BUFFERABLE (1 << 2) /* Bit 2: 1=bufferable */ +#define PTE_CACHEABLE (1 << 3) /* Bit 3: 1=cacheable */ + /* Bits 31:4: Depend on type */ + +/* Large page -- 64Kb */ + /* Bits: 1:0: Type of mapping */ + /* Bits: 3:2: Bufferable/cacheable */ +#define PTE_LARGE_AP_MASK (0xff << 4) /* Bits 11:4 Access permissions */ +#define PTE_LARGE_AP_UNO_SRO (0x00 << 4) +#define PTE_LARGE_AP_UNO_SRW (0x55 << 4) +#define PTE_LARGE_AP_URO_SRW (0xaa << 4) +#define PTE_LARGE_AP_URW_SRW (0xff << 4) + /* Bits 15:12: Should be zero */ +#define PTE_LARGE_TEX_MASK 0xffff0000 /* Bits 31:16: v5, Physical page */ + +/* Small page -- 4Kb */ + + /* Bits: 1:0: Type of mapping */ + /* Bits: 3:2: Bufferable/cacheable */ +#define PTE_SMALL_AP_MASK (0xff << 4) /* Bits: 11:4: Access permissions */ +#define PTE_SMALL_AP_UNO_SRO (0x00 << 4) +#define PTE_SMALL_AP_UNO_SRW (0x55 << 4) +#define PTE_SMALL_AP_URO_SRW (0xaa << 4) +#define PTE_SMALL_AP_URW_SRW (0xff << 4) +#define PTE_SMALL_TEX_MASK 0xfffff000 /* Bits: 31:12: Physical page */ + +#define PTE_SMALL_NPAGES 256 /* 256 Coarse PTE's per section */ + +/* Fine/Tiny page -- 1Kb */ + + /* Bits: 1:0: Type of mapping */ + /* Bits: 3:2: Bufferable/cacheable */ +#define PTE_EXT_AP_MASK (3 << 4) /* Bits: 5:4: Access persions */ +#define PTE_EXT_AP_UNO_SRO (0 << 4) +#define PTE_EXT_AP_UNO_SRW (1 << 4) +#define PTE_EXT_AP_URO_SRW (2 << 4) +#define PTE_EXT_AP_URW_SRW (3 << 4) + /* Bits: 9:6: Should be zero */ +#define PTE_TINY_TEX_MASK 0xfffffc00 /* Bits: 31:10: Physical page */ + +#define PTE_TINY_NPAGES 1024 /* 1024 Tiny PTE's per section */ + +/* Default MMU flags for RAM memory, IO, vector region */ + +#define MMU_ROMFLAGS \ + (PMD_TYPE_SECT|PMD_BIT4|PMD_SECT_AP_READ) + +#define MMU_MEMFLAGS \ + (PMD_TYPE_SECT|PMD_SECT_WB|PMD_BIT4|PMD_SECT_AP_WRITE|PMD_SECT_AP_READ) + +#define MMU_IOFLAGS \ + (PMD_TYPE_SECT|PMD_BIT4|PMD_SECT_AP_WRITE|PMD_SECT_AP_READ) + +#define MMU_L1_VECTORFLAGS (PMD_TYPE_COARSE|PMD_BIT4) +#define MMU_L2_VECTORFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRW) + +/* Mapped section size */ + +#define SECTION_SIZE (1 << 20) /* 1Mb */ + +/* CP15 register c2 contains a pointer to the base address of a paged table in + * physical memory. Only bits 14-31 of the page table address is retained there; + * The full 30-bit address is formed by ORing in bits 2-13 or the virtual address + * (MVA). As a consequence, the page table must be aligned to a 16Kb address in + * physical memory and could require up to 16Kb of memory. + */ + +#define PGTABLE_SIZE 0x00004000 + +/************************************************************************************ + * Inline Functions + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Get the current value of the CP15 C1 control register */ + +static inline unsigned int get_cp15c1(void) +{ + unsigned int retval; + __asm__ __volatile__ + ( + "\tmrc p15, 0, %0, c1, c0" + : "=r" (retval) + : + : "memory"); + return retval; +} + +/* Get the current value of the CP15 C2 page table pointer register */ + +static inline unsigned int get_cp15c2(void) +{ + unsigned int retval; + __asm__ __volatile__ + ( + "\tmrc p15, 0, %0, c2, c0" + : "=r" (retval) + : + : "memory"); + return retval; +} +/* Get the current value of the CP15 C3 domain access register */ + +static inline unsigned int get_cp15c3(void) +{ + unsigned int retval; + __asm__ __volatile__ + ( + "\tmrc p15, 0, %0, c3, c0" + : "=r" (retval) + : + : "memory"); + return retval; +} + +/* ARMv4/ARMv5 operation: Invalidate TLB + * ARM926EJ-S operation: Invalidate set-associative + * Data: Should be zero + */ + +static inline void tlb_invalidate(void) +{ + unsigned int sbz = 0; + __asm__ __volatile__ + ( + "\tmcr p15, 0, %0, c8, c7, 0" + : + : "r" (sbz) + : "memory"); +} + +/* ARMv4/ARMv5 operation: Invalidate TLB single entry (MVA) + * ARM926EJ-S operation: Invalidate single entry + * Data: MVA + */ + +static inline void tlb_invalidate_single(unsigned int mva) +{ + mva &= 0xfffffc00; + __asm__ __volatile__ + ( + "mcr p15, 0, %0, c8, c7, 1" + : + : "r" (mva) + : "memory"); +} + +/* ARMv4/ARMv5 operation: Invalidate instruction TLB + * ARM926EJ-S operation: Invalidate set-associative TLB + * Data: Should be zero + */ + +static inline void tlb_instr_invalidate(void) +{ + unsigned int sbz = 0; + __asm__ __volatile__ + ( + "\tmcr p15, 0, %0, c8, c5, 0" + : + : "r" (sbz) + : "memory"); +} + +/* ARMv4/ARMv5 operation: Invalidate instruction TLB single entry (MVA) + * ARM926EJ-S operation: Invalidate single entry + * Data: MVA + */ + +static inline void tlb_inst_invalidate_single(unsigned int mva) +{ + mva &= 0xfffffc00; + __asm__ __volatile__ + ( + "mcr p15, 0, %0, c8, c5, 1" + : + : "r" (mva) + : "memory"); +} + +/* ARMv4/ARMv5 operation: Invalidate data TLB + * ARM926EJ-S operation: Invalidate set-associative TLB + * Data: Should be zero + */ + +static inline void tlb_data_invalidate(void) +{ + unsigned int sbz = 0; + __asm__ __volatile__ + ( + "\tmcr p15, 0, %0, c8, c6, 0" + : + : "r" (sbz) + : "memory"); +} + +/* ARMv4/ARMv5 operation: Invalidate data TLB single entry (MVA) + * ARM926EJ-S operation: Invalidate single entry + * Data: MVA + */ + +static inline void tlb_data_invalidate_single(unsigned int mva) +{ + mva &= 0xfffffc00; + __asm__ __volatile__ + ( + "mcr p15, 0, %0, c8, c6, 1" + : + : "r" (mva) + : "memory"); +} + +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_ARM_SRC_COMMON_ARM_H */ diff --git a/nuttx/arch/arm/src/arm/pg_macros.h b/nuttx/arch/arm/src/arm/pg_macros.h new file mode 100644 index 0000000000..fc50f61460 --- /dev/null +++ b/nuttx/arch/arm/src/arm/pg_macros.h @@ -0,0 +1,522 @@ +/**************************************************************************** + * arch/arm/src/arm/pg_macros.h + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* Do not change this macro definition without making corresponding name + * changes in other files. This macro name is used in various places to + * assure that some file inclusion ordering dependencies are enforced. + */ + +#ifndef __ARCH_ARM_SRC_ARM_PG_MACROS_H +#define __ARCH_ARM_SRC_ARM_PG_MACROS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "arm.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifdef CONFIG_PAGING + +/* Sanity check -- we cannot be using a ROM page table and supporting on- + * demand paging. + */ + +#ifdef CONFIG_ARCH_ROMPGTABLE +# error "Cannot support both CONFIG_PAGING and CONFIG_ARCH_ROMPGTABLE" +#endif + +/* Virtual Page Table Location **********************************************/ + +/* Check if the virtual address of the page table has been defined. It should + * not be defined: architecture specific logic should suppress defining + * PGTABLE_BASE_VADDR unless: (1) it is defined in the NuttX configuration + * file, or (2) the page table is position in low memory (because the vectors + * are in high memory). + */ + +#ifndef PGTABLE_BASE_VADDR +# define PGTABLE_BASE_VADDR (PG_LOCKED_VBASE + PG_TEXT_VSIZE + PG_DATA_SIZE) + + /* Virtual base of the address of the L2 page tables need to recalculates + * using this new virtual base address of the L2 page table. + */ + +# undef PGTABLE_L2_FINE_VBASE +# define PGTABLE_L2_FINE_VBASE (PGTABLE_BASE_VADDR+PGTABLE_L2_FINE_OFFSET) + +# undef PGTABLE_L2_COARSE_VBASE +# define PGTABLE_L2_COARSE_VBASE (PGTABLE_BASE_VADDR+PGTABLE_L2_COARSE_OFFSET) +#endif + +/* Page Size Selections *****************************************************/ + +/* Create some friendly definitions to handle some differences between + * small and tiny pages. + */ + +#if CONFIG_PAGING_PAGESIZE == 1024 + + /* Base of the L2 page table (aligned to 4Kb byte boundaries) */ + +# define PGTABLE_L2_BASE_PADDR PGTABLE_L2_FINE_PBASE +# define PGTABLE_L2_BASE_VADDR PGTABLE_L2_FINE_VBASE + + /* Number of pages in an L2 table per L1 entry */ + +# define PTE_NPAGES PTE_TINY_NPAGES + + /* Mask to get the page table physical address from an L1 entry */ + +# define PG_L1_PADDRMASK PMD_FINE_TEX_MASK + + /* MMU Flags for each memory region */ + +# define MMU_L1_TEXTFLAGS (PMD_TYPE_FINE|PMD_BIT4) +# define MMU_L2_TEXTFLAGS (PTE_TYPE_TINY|PTE_EXT_AP_UNO_SRO|PTE_CACHEABLE) +# define MMU_L1_DATAFLAGS (PMD_TYPE_FINE|PMD_BIT4) +# define MMU_L2_DATAFLAGS (PTE_TYPE_TINY|PTE_EXT_AP_UNO_SRW|PTE_CACHEABLE|PTE_BUFFERABLE) +# define MMU_L2_ALLOCFLAGS (PTE_TYPE_TINY|PTE_EXT_AP_UNO_SRW) +# define MMU_L1_PGTABFLAGS (PMD_TYPE_FINE|PMD_BIT4) +# define MMU_L2_PGTABFLAGS (PTE_TYPE_TINY|PTE_EXT_AP_UNO_SRW) + +# define MMU_L2_VECTRWFLAGS (PTE_TYPE_TINY|PTE_EXT_AP_UNO_SRW) +# define MMU_L2_VECTROFLAGS (PTE_TYPE_TINY|PTE_EXT_AP_UNO_SRO|PTE_CACHEABLE) + +#elif CONFIG_PAGING_PAGESIZE == 4096 + + /* Base of the L2 page table (aligned to 1Kb byte boundaries) */ + +# define PGTABLE_L2_BASE_PADDR PGTABLE_L2_COARSE_PBASE +# define PGTABLE_L2_BASE_VADDR PGTABLE_L2_COARSE_VBASE + + /* Number of pages in an L2 table per L1 entry */ + +# define PTE_NPAGES PTE_SMALL_NPAGES + + /* Mask to get the page table physical address from an L1 entry */ + +# define PG_L1_PADDRMASK PMD_COARSE_TEX_MASK + + /* MMU Flags for each memory region. */ + +# define MMU_L1_TEXTFLAGS (PMD_TYPE_COARSE|PMD_BIT4) +# define MMU_L2_TEXTFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRO|PTE_CACHEABLE) +# define MMU_L1_DATAFLAGS (PMD_TYPE_COARSE|PMD_BIT4) +# define MMU_L2_DATAFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRW|PTE_CACHEABLE|PTE_BUFFERABLE) +# define MMU_L2_ALLOCFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRW) +# define MMU_L1_PGTABFLAGS (PMD_TYPE_COARSE|PMD_BIT4) +# define MMU_L2_PGTABFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRW) + +# define MMU_L2_VECTRWFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRW) +# define MMU_L2_VECTROFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRO|PTE_CACHEABLE) + +#else +# error "Need extended definitions for CONFIG_PAGING_PAGESIZE" +#endif + +#define PT_SIZE (4*PTE_NPAGES) + +/* Addresses of Memory Regions **********************************************/ + +/* We position the locked region PTEs at an offset into the first + * L2 page table. The L1 entry points to an 1Mb aligned virtual + * address. The actual L2 entry will be offset into the aligned + * L2 table. + * + * Coarse: PG_L1_PADDRMASK=0xfffffc00 + * OFFSET=(((a) & 0x000fffff) >> 12) << 2) + * Fine: PG_L1_PADDRMASK=0xfffff000 + * OFFSET=(((a) & 0x000fffff) >> 10) << 2) + */ + +#define PG_L1_LOCKED_PADDR (PGTABLE_BASE_PADDR + ((PG_LOCKED_VBASE >> 20) << 2)) +#define PG_L1_LOCKED_VADDR (PGTABLE_BASE_VADDR + ((PG_LOCKED_VBASE >> 20) << 2)) + +#define PG_L2_LOCKED_OFFSET (((PG_LOCKED_VBASE & 0x000fffff) >> PAGESHIFT) << 2) +#define PG_L2_LOCKED_PADDR (PGTABLE_L2_BASE_PADDR + PG_L2_LOCKED_OFFSET) +#define PG_L2_LOCKED_VADDR (PGTABLE_L2_BASE_VADDR + PG_L2_LOCKED_OFFSET) +#define PG_L2_LOCKED_SIZE (4*CONFIG_PAGING_NLOCKED) + +/* We position the paged region PTEs immediately after the locked + * region PTEs. NOTE that the size of the paged regions is much + * larger than the size of the physical paged region. That is the + * core of what the On-Demanding Paging feature provides. + */ + +#define PG_L1_PAGED_PADDR (PGTABLE_BASE_PADDR + ((PG_PAGED_VBASE >> 20) << 2)) +#define PG_L1_PAGED_VADDR (PGTABLE_BASE_VADDR + ((PG_PAGED_VBASE >> 20) << 2)) + +#define PG_L2_PAGED_PADDR (PG_L2_LOCKED_PADDR + PG_L2_LOCKED_SIZE) +#define PG_L2_PAGED_VADDR (PG_L2_LOCKED_VADDR + PG_L2_LOCKED_SIZE) +#define PG_L2_PAGED_SIZE (4*CONFIG_PAGING_NVPAGED) + +/* This describes the overall text region */ + +#define PG_L1_TEXT_PADDR PG_L1_LOCKED_PADDR +#define PG_L1_TEXT_VADDR PG_L1_LOCKED_VADDR + +#define PG_L2_TEXT_PADDR PG_L2_LOCKED_PADDR +#define PG_L2_TEXT_VADDR PG_L2_LOCKED_VADDR +#define PG_L2_TEXT_SIZE (PG_L2_LOCKED_SIZE + PG_L2_PAGED_SIZE) + +/* We position the data section PTEs just after the text region PTE's */ + +#define PG_L1_DATA_PADDR (PGTABLE_BASE_PADDR + ((PG_DATA_VBASE >> 20) << 2)) +#define PG_L1_DATA_VADDR (PGTABLE_BASE_VADDR + ((PG_DATA_VBASE >> 20) << 2)) + +#define PG_L2_DATA_PADDR (PG_L2_LOCKED_PADDR + PG_L2_TEXT_SIZE) +#define PG_L2_DATA_VADDR (PG_L2_LOCKED_VADDR + PG_L2_TEXT_SIZE) +#define PG_L2_DATA_SIZE (4*PG_DATA_NPAGES) + +/* Page Table Info **********************************************************/ + +/* The number of pages in the in the page table (PG_PGTABLE_NPAGES). We + * position the pagetable PTEs just after the data section PTEs. + */ + +#define PG_PGTABLE_NPAGES (PGTABLE_SIZE >> PAGESHIFT) +#define PG_L1_PGTABLE_PADDR (PGTABLE_BASE_PADDR + ((PGTABLE_BASE_VADDR >> 20) << 2)) +#define PG_L1_PGTABLE_VADDR (PGTABLE_BASE_VADDR + ((PGTABLE_BASE_VADDR >> 20) << 2)) + +#define PG_L2_PGTABLE_PADDR (PG_L2_DATA_PADDR + PG_L2_DATA_SIZE) +#define PG_L2_PGTABLE_VADDR (PG_L2_DATA_VADDR + PG_L2_DATA_SIZE) +#define PG_L2_PGTABLE_SIZE (4*PG_DATA_NPAGES) + +/* Vector Mapping ***********************************************************/ + +/* One page is required to map the vector table. The vector table could lie + * at virtual address zero (or at the start of RAM which is aliased to address + * zero on the ea3131) or at virtual address 0xfff00000. We only have logic + * here to support the former case. + * + * NOTE: If the vectors are at address zero, the page table will be + * forced to the highest RAM addresses. If the vectors are at 0xfff0000, + * then the page table is forced to the beginning of RAM. + * + * When the vectors are at the beginning of RAM, they will probably overlap + * the first page of the locked text region. In any other case, the + * configuration must set CONFIG_PAGING_VECPPAGE to provide the physical + * address of the page to use for the vectors. + * + * When the vectors overlap the first page of the locked text region (the + * only case in use so far), then the text page will be temporarily be made + * writable in order to copy the vectors. + * + * PG_VECT_PBASE - This the physical address of the page in memory to be + * mapped to the vector address. + * PG_L2_VECT_PADDR - This is the physical address of the L2 page table + * entry to use for the vector mapping. + * PG_L2_VECT_VADDR - This is the virtual address of the L2 page table + * entry to use for the vector mapping. + */ + +/* Case 1: The configuration tells us everything */ + +#if defined(CONFIG_PAGING_VECPPAGE) +# define PG_VECT_PBASE CONFIG_PAGING_VECPPAGE +# define PG_L2_VECT_PADDR CONFIG_PAGING_VECL2PADDR +# define PG_L2_VECT_VADDR CONFIG_PAGING_VECL2VADDR + +/* Case 2: Vectors are in low memory and the locked text region starts at + * the beginning of SRAM (which will be aliased to address 0x00000000). + * However, the beginning of SRAM may not be aligned to the beginning + * of the L2 page table (because the beginning of RAM is offset into + * the table. + */ + +#elif defined(CONFIG_ARCH_LOWVECTORS) && !defined(CONFIG_PAGING_LOCKED_PBASE) +# define PG_VECT_PBASE PG_LOCKED_PBASE +# define PG_L2_VECT_OFFSET (((PG_LOCKED_VBASE & 0x000fffff) >> PAGESHIFT) << 2) +# define PG_L2_VECT_PADDR (PGTABLE_L2_BASE_PADDR + PG_L2_VECT_OFFSET) +# define PG_L2_VECT_VADDR (PGTABLE_L2_BASE_VADDR + PG_L2_VECT_OFFSET) + +/* Case 3: High vectors or the locked region is not at the beginning or SRAM */ + +#else +# error "Logic missing for high vectors in this case" +#endif + +/* Page Usage ***************************************************************/ + +/* This is the total number of pages used in the text/data mapping: */ + +#define PG_TOTAL_NPPAGES (PG_TEXT_NPPAGES + PG_DATA_NPAGES + PG_PGTABLE_NPAGES) +#define PG_TOTAL_NVPAGES (PG_TEXT_NVPAGES + PG_DATA_NPAGES + PG_PGTABLE_NPAGES) +#define PG_TOTAL_PSIZE (PG_TOTAL_NPPAGES << PAGESHIFT) +#define PG_TOTAL_VSIZE (PG_TOTAL_NVPAGES << PAGESHIFT) + +/* Sanity check: */ + +#if PG_TOTAL_NPPAGES > PG_RAM_PAGES +# error "Total pages required exceeds RAM size" +#endif + +/* Page Management **********************************************************/ + +/* For page managment purposes, the following summarize the "heap" of + * free pages, operations on free pages and the L2 page table. + * + * PG_POOL_VA2L1OFFSET(va) - Given a virtual address, return the L1 table + * offset (in bytes). + * PG_POOL_VA2L1VADDR(va) - Given a virtual address, return the virtual + * address of the L1 table entry + * PG_POOL_L12PPTABLE(L1) - Given the value of an L1 table entry return + * the physical address of the start of the L2 + * page table + * PG_POOL_L12PPTABLE(L1) - Given the value of an L1 table entry return + * the virtual address of the start of the L2 + * page table. + * + * PG_POOL_L1VBASE - The virtual address of the start of the L1 + * page table range corresponding to the first + * virtual address of the paged text region. + * PG_POOL_L1VEND - The virtual address of the end+1 of the L1 + * page table range corresponding to the last + * virtual address+1 of the paged text region. + * + * PG_POOL_VA2L2NDX(va) - Converts a virtual address within the paged + * text region to the most compact possible + * representation. Each PAGESIZE of address + * corresponds to 1 index in the L2 page table; + * Index 0 corresponds to the first L2 page table + * entry for the first page in the virtual paged + * text address space. + * PG_POOL_NDX2VA(ndx) - Performs the opposite conversion.. convests + * an index into a virtual address in the paged + * text region (the address at the beginning of + * the page). + * PG_POOL_MAXL2NDX - This is the maximum value+1 of such an index. + * + * PG_POOL_PGPADDR(ndx) - Converts an page index into the corresponding + * (physical) address of the backing page memory. + * PG_POOL_PGVADDR(ndx) - Converts an page index into the corresponding + * (virtual)address of the backing page memory. + * + * These are used as follows: If a miss occurs at some virtual address, va, + * A new page index, ndx, is allocated. PG_POOL_PGPADDR(i) converts the index + * into the physical address of the page memory; PG_POOL_L2VADDR(va) converts + * the virtual address in the L2 page table there the new mapping will be + * written. + */ + +#define PG_POOL_VA2L1OFFSET(va) (((va) >> 20) << 2) +#define PG_POOL_VA2L1VADDR(va) (PGTABLE_BASE_VADDR + PG_POOL_VA2L1OFFSET(va)) +#define PG_POOL_L12PPTABLE(L1) ((L1) & PG_L1_PADDRMASK) +#define PG_POOL_L12VPTABLE(L1) (PG_POOL_L12PPTABLE(L1) - PGTABLE_BASE_PADDR + PGTABLE_BASE_VADDR) + +#define PG_POOL_L1VBASE (PGTABLE_BASE_VADDR + ((PG_PAGED_VBASE >> 20) << 2)) +#define PG_POOL_L1VEND (PG_POOL_L1VBASE + (CONFIG_PAGING_NVPAGED << 2)) + +#define PG_POOL_VA2L2NDX(va) (((va) - PG_PAGED_VBASE) >> PAGESHIFT) +#define PG_POOL_NDX2VA(ndx) (((ndx) << PAGESHIFT) + PG_PAGED_VBASE) +#define PG_POOL_MAXL2NDX PG_POOL_VA2L2NDX(PG_PAGED_VEND) + +#define PG_POOL_PGPADDR(ndx) (PG_PAGED_PBASE + ((ndx) << PAGESHIFT)) +#define PG_POOL_PGVADDR(ndx) (PG_PAGED_VBASE + ((ndx) << PAGESHIFT)) + +#endif /* CONFIG_PAGING */ + +/**************************************************************************** + * Assembly Macros + ****************************************************************************/ + +#ifdef __ASSEMBLY__ + +/**************************************************************************** + * Name: pg_l2map + * + * Description: + * Write several, contiguous L2 page table entries. npages entries will be + * written. This macro is used when CONFIG_PAGING is enable. This case, + * it is used asfollows: + * + * ldr r0, =PGTABLE_L2_BASE_PADDR <-- Address in L2 table + * ldr r1, =PG_LOCKED_PBASE <-- Physical page memory address + * ldr r2, =CONFIG_PAGING_NLOCKED <-- number of pages + * ldr r3, =MMUFLAGS <-- L2 MMU flags + * pg_l2map r0, r1, r2, r3, r4 + * + * Inputs: + * l2 - Physical or virtual start address in the L2 page table, depending + * upon the context. (modified) + * ppage - The physical address of the start of the region to span. Must + * be aligned to 1Mb section boundaries (modified) + * npages - Number of pages to write in the section (modified) + * mmuflags - L2 MMU FLAGS + * + * Scratch registers (modified): tmp + * l2 - Next address in the L2 page table. + * ppage - Start of next physical page + * npages - Loop counter + * tmp - scratch + * + * Assumptions: + * - The MMU is not yet enabled + * - The L2 page tables have been zeroed prior to calling this function + * - pg_l1span has been called to initialize the L1 table. + * + ****************************************************************************/ + +#ifdef CONFIG_PAGING + .macro pg_l2map, l2, ppage, npages, mmuflags, tmp + b 2f +1: + /* Write the one L2 entries. First, get tmp = (ppage | mmuflags), + * the value to write into the L2 PTE + */ + + orr \tmp, \ppage, \mmuflags + + /* Write value into table at the current table address + * (and increment the L2 page table address by 4) + */ + + str \tmp, [\l2], #4 + + /* Update the physical address that will correspond to the next + * table entry. + */ + + add \ppage, \ppage, #CONFIG_PAGING_PAGESIZE + + /* Decrement the number of pages written */ + + sub \npages, \npages, #1 +2: + /* Check if all of the pages have been written. If not, then + * loop and write the next PTE. + */ + cmp \npages, #0 + bgt 1b + .endm +#endif /* CONFIG_PAGING */ + +/**************************************************************************** + * Name: pg_l1span + * + * Description: + * Write several, contiguous unmapped coarse L1 page table entries. As + * many entries will be written as many as needed to span npages. This + * macro is used when CONFIG_PAGING is enable. This case, it is used as + * follows: + * + * ldr r0, =PG_L1_PGTABLE_PADDR <-- Address in the L1 table + * ldr r1, =PG_L2_PGTABLE_PADDR <-- Physical address of L2 page table + * ldr r2, =PG_PGTABLE_NPAGES <-- Total number of pages + * ldr r3, =PG_PGTABLE_NPAGE1 <-- Number of pages in the first PTE + * ldr r4, =MMU_L1_PGTABFLAGS <-- L1 MMU flags + * pg_l1span r0, r1, r2, r3, r4, r4 + * + * Inputs (unmodified unless noted): + * l1 - Physical or virtual address in the L1 table to begin writing (modified) + * l2 - Physical start address in the L2 page table (modified) + * npages - Number of pages to required to span that memory region (modified) + * ppage - The number of pages in page 1 (modified) + * mmuflags - L1 MMU flags to use + * + * Scratch registers (modified): l1, l2, npages, tmp + * l1 - Next L1 table address + * l2 - Physical start address of the next L2 page table + * npages - Loop counter + * ppage - After the first page, this will be the full number of pages. + * tmp - scratch + * + * Return: + * Nothing of interest. + * + * Assumptions: + * - The MMU is not yet enabled + * - The L2 page tables have been zeroed prior to calling this function + * + ****************************************************************************/ + +#ifdef CONFIG_PAGING + .macro pg_l1span, l1, l2, npages, ppage, mmuflags, tmp + b 2f +1: + /* Write the L1 table entry that refers to this (unmapped) coarse page + * table. + * + * tmp = (l2table | mmuflags), the value to write into the page table + */ + + orr \tmp, \l2, \mmuflags + + /* Write the value into the L1 table at the correct offset. + * (and increment the L1 table address by 4) + */ + + str \tmp, [\l1], #4 + + /* Update the L2 page table address for the next L1 table entry. */ + + add \l2, \l2, #PT_SIZE /* Next L2 page table start address */ + + /* Update the number of pages that we have account for (with + * non-mappings). NOTE that the first page may have fewer than + * the maximum entries per page table. + */ + + sub \npages, \npages, \ppage + mov \ppage, #PTE_NPAGES +2: + /* Check if all of the pages have been written. If not, then + * loop and write the next L1 entry. + */ + + cmp \npages, #0 + bgt 1b + .endm + +#endif /* CONFIG_PAGING */ +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_ARM_PG_MACROS_H */ diff --git a/nuttx/arch/arm/src/arm/up_allocpage.c b/nuttx/arch/arm/src/arm/up_allocpage.c new file mode 100755 index 0000000000..c2a31d09c0 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_allocpage.c @@ -0,0 +1,243 @@ +/**************************************************************************** + * arch/arm/src/arm/up_allocpage.c + * Allocate a new page and map it to the fault address of a task. + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#ifdef CONFIG_PAGING + +#include + +#include "pg_macros.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#if CONFIG_PAGING_NPPAGED < 256 +typedef uint8_t pgndx_t; +#elif CONFIG_PAGING_NPPAGED < 65536 +typedef uint16_t pgndx_t; +#else +typedef uint32_t pgndx_t; +#endif + +#if PG_POOL_MAXL1NDX < 256 +typedef uint8_t L1ndx_t; +#elif PG_POOL_MAXL1NDX < 65536 +typedef uint16_t L1ndx_t; +#else +typedef uint32_t L1ndx_t; +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Free pages in memory are managed by indices ranging from up to + * CONFIG_PAGING_NPAGED. Initially all pages are free so the page can be + * simply allocated in order: 0, 1, 2, ... . After all CONFIG_PAGING_NPAGED + * pages have be filled, then they are blindly freed and re-used in the + * same order 0, 1, 2, ... because we don't know any better. No smart "least + * recently used" kind of logic is supported. + */ + +static pgndx_t g_pgndx; + +/* After CONFIG_PAGING_NPAGED have been allocated, the pages will be re-used. + * In order to re-used the page, we will have un-map the page from its previous + * mapping. In order to that, we need to be able to map a physical address to + * to an index into the PTE where it was mapped. The following table supports + * this backward lookup - it is indexed by the page number index, and holds + * another index to the mapped virtual page. + */ + +static L1ndx_t g_ptemap[CONFIG_PAGING_NPPAGED]; + +/* The contents of g_ptemap[] are not valid until g_pgndx has wrapped at + * least one time. + */ + +static bool g_pgwrap; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocpage() + * + * Description: + * This architecture-specific function will set aside page in memory and map + * the page to its correct virtual address. Architecture-specific context + * information saved within the TCB will provide the function with the + * information needed to identify the virtual miss address. + * + * This function will return the allocated physical page address in vpage. + * The size of the underlying physical page is determined by the + * configuration setting CONFIG_PAGING_PAGESIZE. + * + * NOTE 1: This function must always return a page allocation. If all + * available pages are in-use (the typical case), then this function will + * select a page in-use, un-map it, and make it available. + * + * NOTE 2: If an in-use page is un-mapped, it may be necessary to flush the + * instruction cache in some architectures. + * + * NOTE 3: Allocating and filling a page is a two step process. up_allocpage() + * allocates the page, and up_fillpage() fills it with data from some non- + * volatile storage device. This distinction is made because up_allocpage() + * can probably be implemented in board-independent logic whereas up_fillpage() + * probably must be implemented as board-specific logic. + * + * NOTE 4: The initial mapping of vpage should be read-able and write- + * able (but not cached). No special actions will be required of + * up_fillpage() in order to write into this allocated page. + * + * Input Parameters: + * tcb - A reference to the task control block of the task that needs to + * have a page fill. Architecture-specific logic can retrieve page + * fault information from the architecture-specific context + * information in this TCB to perform the mapping. + * + * Returned Value: + * This function will return zero (OK) if the allocation was successful. + * A negated errno value may be returned if an error occurs. All errors, + * however, are fatal. + * + * Assumptions: + * - This function is called from the normal tasking context (but with + * interrupts disabled). The implementation must take whatever actions + * are necessary to assure that the operation is safe within this + * context. + * + ****************************************************************************/ + +int up_allocpage(FAR _TCB *tcb, FAR void **vpage) +{ + uintptr_t vaddr; + uintptr_t paddr; + uint32_t *pte; + unsigned int pgndx; + + /* Since interrupts are disabled, we don't need to anything special. */ + + DEBUGASSERT(tcb && vpage); + + /* Get the virtual address that caused the fault */ + + vaddr = tcb->xcp.far; + DEBUGASSERT(vaddr >= PG_PAGED_VBASE && vaddr < PG_PAGED_VEND); + + /* Allocate page memory to back up the mapping. Start by getting the + * index of the next page that we are going to allocate. + */ + + pgndx = g_pgndx++; + if (g_pgndx >= CONFIG_PAGING) + { + g_pgndx = 0; + g_pgwrap = true; + } + + /* Was this physical page previously mapped? If so, then we need to un-map + * it. + */ + + if (g_pgwrap) + { + /* Yes.. Get a pointer to the L2 entry corresponding to the previous + * mapping -- then zero it! + */ + + uintptr_t oldvaddr = PG_POOL_NDX2VA(g_ptemap[pgndx]); + pte = up_va2pte(oldvaddr); + *pte = 0; + + /* Invalidate the instruction TLB corresponding to the virtual address */ + + tlb_inst_invalidate_single(oldvaddr); + + /* I do not believe that it is necessary to flush the I-Cache in this + * case: The I-Cache uses a virtual address index and, hence, since the + * NuttX address space is flat, the cached instruction value should be + * correct even if the page mapping is no longer in place. + */ + } + + /* Then convert the index to a (physical) page address. */ + + paddr = PG_POOL_PGPADDR(pgndx); + + /* Now setup up the new mapping. Get a pointer to the L2 entry + * corresponding to the new mapping. Then set it map to the newly + * allocated page address. The inital mapping is read/write but + * non-cached (MMU_L2_ALLOCFLAGS) + */ + + pte = up_va2pte(vaddr); + *pte = (paddr | MMU_L2_ALLOCFLAGS); + + /* And save the new L1 index */ + + g_ptemap[pgndx] = PG_POOL_VA2L2NDX(vaddr); + + /* Finally, return the virtual address of allocated page */ + + *vpage = (void*)(vaddr & ~PAGEMASK); + return OK; +} + +#endif /* CONFIG_PAGING */ diff --git a/nuttx/arch/arm/src/arm/up_assert.c b/nuttx/arch/arm/src/arm/up_assert.c new file mode 100644 index 0000000000..f52dc1b946 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_assert.c @@ -0,0 +1,325 @@ +/**************************************************************************** + * arch/arm/src/arm/up_assert.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Output debug info if stack dump is selected -- even if + * debug is not selected. + */ + +#ifdef CONFIG_ARCH_STACKDUMP +# undef lldbg +# define lldbg lib_lowprintf +#endif + +/* The following is just intended to keep some ugliness out of the mainline + * code. We are going to print the task name if: + * + * CONFIG_TASK_NAME_SIZE > 0 && <-- The task has a name + * (defined(CONFIG_DEBUG) || <-- And the debug is enabled (lldbg used) + * defined(CONFIG_ARCH_STACKDUMP) <-- Or lib_lowprintf() is used + */ + +#undef CONFIG_PRINT_TASKNAME +#if CONFIG_TASK_NAME_SIZE > 0 && (defined(CONFIG_DEBUG) || defined(CONFIG_ARCH_STACKDUMP)) +# define CONFIG_PRINT_TASKNAME 1 +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_getsp + ****************************************************************************/ + +/* I don't know if the builtin to get SP is enabled */ + +static inline uint32_t up_getsp(void) +{ + uint32_t sp; + __asm__ + ( + "\tmov %0, sp\n\t" + : "=r"(sp) + ); + return sp; +} + +/**************************************************************************** + * Name: up_stackdump + ****************************************************************************/ + +#ifdef CONFIG_ARCH_STACKDUMP +static void up_stackdump(uint32_t sp, uint32_t stack_base) +{ + uint32_t stack ; + + for (stack = sp & ~0x1f; stack < stack_base; stack += 32) + { + uint32_t *ptr = (uint32_t*)stack; + lldbg("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", + stack, ptr[0], ptr[1], ptr[2], ptr[3], + ptr[4], ptr[5], ptr[6], ptr[7]); + } +} +#else +# define up_stackdump() +#endif + +/**************************************************************************** + * Name: up_registerdump + ****************************************************************************/ + +#ifdef CONFIG_ARCH_STACKDUMP +static inline void up_registerdump(void) +{ + /* Are user registers available from interrupt processing? */ + + if (current_regs) + { + int regs; + + /* Yes.. dump the interrupt registers */ + + for (regs = REG_R0; regs <= REG_R15; regs += 8) + { + uint32_t *ptr = (uint32_t*)¤t_regs[regs]; + lldbg("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n", + regs, ptr[0], ptr[1], ptr[2], ptr[3], + ptr[4], ptr[5], ptr[6], ptr[7]); + } + + lldbg("CPSR: %08x\n", current_regs[REG_CPSR]); + } +} +#else +# define up_registerdump() +#endif + +/**************************************************************************** + * Name: up_dumpstate + ****************************************************************************/ + +#ifdef CONFIG_ARCH_STACKDUMP +static void up_dumpstate(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + uint32_t sp = up_getsp(); + uint32_t ustackbase; + uint32_t ustacksize; +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + uint32_t istackbase; + uint32_t istacksize; +#endif + + /* Get the limits on the user stack memory */ + + if (rtcb->pid == 0) + { + ustackbase = g_heapbase - 4; + ustacksize = CONFIG_IDLETHREAD_STACKSIZE; + } + else + { + ustackbase = (uint32_t)rtcb->adj_stack_ptr; + ustacksize = (uint32_t)rtcb->adj_stack_size; + } + + /* Get the limits on the interrupt stack memory */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + istackbase = (uint32_t)&g_userstack; + istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4; + + /* Show interrupt stack info */ + + lldbg("sp: %08x\n", sp); + lldbg("IRQ stack:\n"); + lldbg(" base: %08x\n", istackbase); + lldbg(" size: %08x\n", istacksize); + + /* Does the current stack pointer lie within the interrupt + * stack? + */ + + if (sp <= istackbase && sp > istackbase - istacksize) + { + /* Yes.. dump the interrupt stack */ + + up_stackdump(sp, istackbase); + + /* Extract the user stack pointer which should lie + * at the base of the interrupt stack. + */ + + sp = g_userstack; + lldbg("sp: %08x\n", sp); + } + + /* Show user stack info */ + + lldbg("User stack:\n"); + lldbg(" base: %08x\n", ustackbase); + lldbg(" size: %08x\n", ustacksize); +#else + lldbg("sp: %08x\n", sp); + lldbg("stack base: %08x\n", ustackbase); + lldbg("stack size: %08x\n", ustacksize); +#endif + + /* Dump the user stack if the stack pointer lies within the allocated user + * stack memory. + */ + + if (sp > ustackbase || sp <= ustackbase - ustacksize) + { +#if !defined(CONFIG_ARCH_INTERRUPTSTACK) || CONFIG_ARCH_INTERRUPTSTACK < 4 + lldbg("ERROR: Stack pointer is not within allocated stack\n"); +#endif + } + else + { + up_stackdump(sp, ustackbase); + } + + /* Then dump the registers (if available) */ + + up_registerdump(); +} +#else +# define up_dumpstate() +#endif + +/**************************************************************************** + * Name: _up_assert + ****************************************************************************/ + +static void _up_assert(int errorcode) /* __attribute__ ((noreturn)) */ +{ + /* Are we in an interrupt handler or the idle task? */ + + if (current_regs || ((_TCB*)g_readytorun.head)->pid == 0) + { + (void)irqsave(); + for(;;) + { +#ifdef CONFIG_ARCH_LEDS + up_ledon(LED_PANIC); + up_mdelay(250); + up_ledoff(LED_PANIC); + up_mdelay(250); +#endif + } + } + else + { + exit(errorcode); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_assert + ****************************************************************************/ + +void up_assert(const uint8_t *filename, int lineno) +{ +#ifdef CONFIG_PRINT_TASKNAME + _TCB *rtcb = (_TCB*)g_readytorun.head; +#endif + + up_ledon(LED_ASSERTION); +#ifdef CONFIG_PRINT_TASKNAME + lldbg("Assertion failed at file:%s line: %d task: %s\n", + filename, lineno, rtcb->name); +#else + lldbg("Assertion failed at file:%s line: %d\n", + filename, lineno); +#endif + up_dumpstate(); + _up_assert(EXIT_FAILURE); +} + +/**************************************************************************** + * Name: up_assert_code + ****************************************************************************/ + +void up_assert_code(const uint8_t *filename, int lineno, int errorcode) +{ +#ifdef CONFIG_PRINT_TASKNAME + _TCB *rtcb = (_TCB*)g_readytorun.head; +#endif + + up_ledon(LED_ASSERTION); + +#ifdef CONFIG_PRINT_TASKNAME + lldbg("Assertion failed at file:%s line: %d task: %s error code: %d\n", + filename, lineno, rtcb->name, errorcode); +#else + lldbg("Assertion failed at file:%s line: %d error code: %d\n", + filename, lineno, errorcode); +#endif + up_dumpstate(); + _up_assert(errorcode); +} diff --git a/nuttx/arch/arm/src/arm/up_blocktask.c b/nuttx/arch/arm/src/arm/up_blocktask.c new file mode 100755 index 0000000000..36c8740d66 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_blocktask.c @@ -0,0 +1,167 @@ +/**************************************************************************** + * arch/arm/src/arm/up_blocktask.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_block_task + * + * Description: + * The currently executing task at the head of + * the ready to run list must be stopped. Save its context + * and move it to the inactive list specified by task_state. + * + * Inputs: + * tcb: Refers to a task in the ready-to-run list (normally + * the task at the head of the list). It most be + * stopped, its context saved and moved into one of the + * waiting task lists. It it was the task at the head + * of the ready-to-run list, then a context to the new + * ready to run task must be performed. + * task_state: Specifies which waiting task list should be + * hold the blocked task TCB. + * + ****************************************************************************/ + +void up_block_task(_TCB *tcb, tstate_t task_state) +{ + /* Verify that the context switch can be performed */ + + if ((tcb->task_state < FIRST_READY_TO_RUN_STATE) || + (tcb->task_state > LAST_READY_TO_RUN_STATE)) + { + PANIC(OSERR_BADBLOCKSTATE); + } + else + { + _TCB *rtcb = (_TCB*)g_readytorun.head; + bool switch_needed; + + /* Remove the tcb task from the ready-to-run list. If we + * are blocking the task at the head of the task list (the + * most likely case), then a context switch to the next + * ready-to-run task is needed. In this case, it should + * also be true that rtcb == tcb. + */ + + switch_needed = sched_removereadytorun(tcb); + + /* Add the task to the specified blocked task list */ + + sched_addblocked(tcb, (tstate_t)task_state); + + /* If there are any pending tasks, then add them to the g_readytorun + * task list now + */ + + if (g_pendingtasks.head) + { + switch_needed |= sched_mergepending(); + } + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + /* Are we in an interrupt handler? */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* Copy the user C context into the TCB at the (old) head of the + * g_readytorun Task list. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + + /* Then switch contexts */ + + up_fullcontextrestore(rtcb->xcp.regs); + } + } + } +} diff --git a/nuttx/arch/arm/src/arm/up_cache.S b/nuttx/arch/arm/src/arm/up_cache.S new file mode 100644 index 0000000000..05926fbb4f --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_cache.S @@ -0,0 +1,74 @@ +/**************************************************************************** + * arch/arm/src/arm/up_cache.S + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "up_internal.h" +#include "up_arch.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define CACHE_DLINESIZE 32 + +/**************************************************************************** + * Assembly Macros + ****************************************************************************/ + +/**************************************************************************** + * Name: up_flushicache + ****************************************************************************/ + +/* Esure coherency between the Icache and the Dcache in the region described + * by r0=start and r1=end. + */ + .globl up_flushicache + .type up_flushicache,%function +up_flushicache: + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 /* Clean D entry */ + mcr p15, 0, r0, c7, c5, 1 /* Invalidate I entry */ + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 /* Drain WB */ + mov pc, lr + .size up_flushicache, .-up_flushicache + .end + diff --git a/nuttx/arch/arm/src/arm/up_checkmapping.c b/nuttx/arch/arm/src/arm/up_checkmapping.c new file mode 100755 index 0000000000..370c94c9d5 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_checkmapping.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * arch/arm/src/arm/up_checkmapping.c + * Check if the current task's fault address has been mapped into the virtual + * address space. + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "up_internal.h" + +#ifdef CONFIG_PAGING + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_checkmapping() + * + * Description: + * The function up_checkmapping() returns an indication if the page fill + * still needs to performed or not. In certain conditions, the page fault + * may occur on several threads and be queued multiple times. This function + * will prevent the same page from be filled multiple times. + * + * Input Parameters: + * tcb - A reference to the task control block of the task that we believe + * needs to have a page fill. Architecture-specific logic can + * retrieve page fault information from the architecture-specific + * context information in this TCB and can consult processor resources + * (page tables or TLBs or ???) to determine if the fill still needs + * to be performed or not. + * + * Returned Value: + * This function will return true if the mapping is in place and false + * if the mapping is still needed. Errors encountered should be + * interpreted as fatal. + * + * Assumptions: + * - This function is called from the normal tasking context (but with + * interrupts disabled). The implementation must take whatever actions + * are necessary to assure that the operation is safe within this + * context. + * + ****************************************************************************/ + +bool up_checkmapping(FAR _TCB *tcb) +{ + uintptr_t vaddr; + uint32_t *pte; + + /* Since interrupts are disabled, we don't need to anything special. */ + + DEBUGASSERT(tcb); + + /* Get the virtual address that caused the fault */ + + vaddr = tcb->xcp.far; + DEBUGASSERT(vaddr >= PG_PAGED_VBASE && vaddr < PG_PAGED_VEND); + + /* Get the PTE associated with this virtual address */ + + pte = up_va2pte(vaddr); + + /* Return true if this virtual address is mapped. */ + + return (*pte != 0); +} + +#endif /* CONFIG_PAGING */ diff --git a/nuttx/arch/arm/src/arm/up_copystate.c b/nuttx/arch/arm/src/arm/up_copystate.c new file mode 100644 index 0000000000..44f027b328 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_copystate.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * arch/arm/src/arm/up_copystate.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_undefinedinsn + ****************************************************************************/ + +/* A little faster than most memcpy's */ + +void up_copystate(uint32_t *dest, uint32_t *src) +{ + int i; + + /* In the current ARM model, the state is always copied to and from the + * stack and TCB. + */ + + for (i = 0; i < XCPTCONTEXT_REGS; i++) + { + *dest++ = *src++; + } +} + diff --git a/nuttx/arch/arm/src/arm/up_dataabort.c b/nuttx/arch/arm/src/arm/up_dataabort.c new file mode 100644 index 0000000000..c36970c1be --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_dataabort.c @@ -0,0 +1,201 @@ +/**************************************************************************** + * arch/arm/src/arm/up_dataabort.c + * + * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "os_internal.h" +#include "up_internal.h" + +#ifdef CONFIG_PAGING +# include +# include "arm.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Output debug info if stack dump is selected -- even if + * debug is not selected. + */ + +#ifdef CONFIG_ARCH_STACKDUMP +# undef lldbg +# define lldbg lib_lowprintf +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_dataabort + * + * Input parameters: + * regs - The standard, ARM register save array. + * + * If CONFIG_PAGING is selected in the NuttX configuration file, then these + * additional input values are expected: + * + * far - Fault address register. On a data abort, the ARM MMU places the + * miss virtual address (MVA) into the FAR register. This is the address + * of the data which, when accessed, caused the fault. + * fsr - Fault status register. On a data a abort, the ARM MMU places an + * encoded four-bit value, the fault status, along with the four-bit + * encoded domain number, in the data FSR + * + * Description: + * This is the data abort exception handler. The ARM data abort exception + * occurs when a memory fault is detected during a data transfer. + * + ****************************************************************************/ + +#ifdef CONFIG_PAGING +void up_dataabort(uint32_t *regs, uint32_t far, uint32_t fsr) +{ + FAR _TCB *tcb = (FAR _TCB *)g_readytorun.head; +#ifdef CONFIG_PAGING + uint32_t *savestate; + + /* Save the saved processor context in current_regs where it can be accessed + * for register dumps and possibly context switching. + */ + + + savestate = (uint32_t*)current_regs; +#endif + current_regs = regs; + +#ifdef CONFIG_PAGING + /* In the NuttX on-demand paging implementation, only the read-only, .text + * section is paged. However, the ARM compiler generated PC-relative data + * fetches from within the .text sections. Also, it is customary to locate + * read-only data (.rodata) within the same section as .text so that it + * does not require copying to RAM. Misses in either of these case should + * cause a data abort. + * + * We are only interested in data aborts due to page translations faults. + * Sections should already be in place and permissions should already be + * be set correctly (to read-only) so any other data abort reason is a + * fatal error. + */ + + pglldbg("FSR: %08x FAR: %08x\n", fsr, far); + if ((fsr & FSR_MASK) != FSR_PAGE) + { + goto segfault; + } + + /* Check the (virtual) address of data that caused the data abort. When + * the exception occurred, this address was provided in the FAR register. + * (It has not yet been saved in the register context save area). + */ + + pgllvdbg("VBASE: %08x VEND: %08x\n", PG_PAGED_VBASE, PG_PAGED_VEND); + if (far < PG_PAGED_VBASE || far >= PG_PAGED_VEND) + { + goto segfault; + } + + /* Save the offending data address as the fault address in the TCB of + * the currently task. This fault address is also used by the prefetch + * abort handling; this will allow common paging logic for both + * prefetch and data aborts. + */ + + tcb->xcp.far = regs[REG_R15]; + + /* Call pg_miss() to schedule the page fill. A consequences of this + * call are: + * + * (1) The currently executing task will be blocked and saved on + * on the g_waitingforfill task list. + * (2) An interrupt-level context switch will occur so that when + * this function returns, it will return to a different task, + * most likely the page fill worker thread. + * (3) The page fill worker task has been signalled and should + * execute immediately when we return from this exception. + */ + + pg_miss(); + + /* Restore the previous value of current_regs. NULL would indicate that + * we are no longer in an interrupt handler. It will be non-NULL if we + * are returning from a nested interrupt. + */ + + current_regs = savestate; + return; + +segfault: +#endif + lldbg("Data abort. PC: %08x FAR: %08x FSR: %08x\n", regs[REG_PC], far, fsr); + PANIC(OSERR_ERREXCEPTION); +} + +#else /* CONFIG_PAGING */ + +void up_dataabort(uint32_t *regs) +{ + /* Save the saved processor context in current_regs where it can be accessed + * for register dumps and possibly context switching. + */ + + current_regs = regs; + + /* Crash -- possibly showing diagnost debug information. */ + + lldbg("Data abort. PC: %08x\n", regs[REG_PC]); + PANIC(OSERR_ERREXCEPTION); +} + +#endif /* CONFIG_PAGING */ diff --git a/nuttx/arch/arm/src/arm/up_doirq.c b/nuttx/arch/arm/src/arm/up_doirq.c new file mode 100644 index 0000000000..1f1c774738 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_doirq.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * arch/arm/src/arm/up_doirq.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void up_doirq(int irq, uint32_t *regs) +{ + up_ledon(LED_INIRQ); +#ifdef CONFIG_SUPPRESS_INTERRUPTS + PANIC(OSERR_ERREXCEPTION); +#else + uint32_t *savestate; + + /* Nested interrupts are not supported in this implementation. If you want + * implemented nested interrupts, you would have to (1) change the way that + * current regs is handled and (2) the design associated with + * CONFIG_ARCH_INTERRUPTSTACK. + */ + + /* Current regs non-zero indicates that we are processing an interrupt; + * current_regs is also used to manage interrupt level context switches. + */ + + savestate = (uint32_t*)current_regs; + current_regs = regs; + + /* Mask and acknowledge the interrupt */ + + up_maskack_irq(irq); + + /* Deliver the IRQ */ + + irq_dispatch(irq, regs); + + /* Restore the previous value of current_regs. NULL would indicate that + * we are no longer in an interrupt handler. It will be non-NULL if we + * are returning from a nested interrupt. + */ + + current_regs = savestate; + + /* Unmask the last interrupt (global interrupts are still disabled) */ + + up_enable_irq(irq); +#endif + up_ledoff(LED_INIRQ); +} diff --git a/nuttx/arch/arm/src/arm/up_fullcontextrestore.S b/nuttx/arch/arm/src/arm/up_fullcontextrestore.S new file mode 100644 index 0000000000..d0745ef5b4 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_fullcontextrestore.S @@ -0,0 +1,118 @@ +/************************************************************************** + * arch/arm/src/arm/up_fullcontextrestore.S + * + * Copyright (C) 2007, 2009-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************/ + +/************************************************************************** + * Included Files + **************************************************************************/ + +#include +#include "up_internal.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ + +/************************************************************************** + * Private Types + **************************************************************************/ + +/************************************************************************** + * Private Function Prototypes + **************************************************************************/ + +/************************************************************************** + * Global Variables + **************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/************************************************************************** + * Public Functions + **************************************************************************/ + +/************************************************************************** + * Name: up_fullcontextrestore + **************************************************************************/ + + .globl up_fullcontextrestore + .type up_fullcontextrestore, function +up_fullcontextrestore: + + /* On entry, a1 (r0) holds address of the register save area */ + + /* Recover all registers except for r0, r1, R15, and CPSR */ + + add r1, r0, #(4*REG_R2) /* Offset to REG_R2 storage */ + ldmia r1, {r2-r14} /* Recover registers */ + + /* Create a stack frame to hold the PC */ + + sub sp, sp, #(3*4) /* Frame for three registers */ + ldr r1, [r0, #(4*REG_R0)] /* Fetch the stored r0 value */ + str r1, [sp] /* Save it at the top of the stack */ + ldr r1, [r0, #(4*REG_R1)] /* Fetch the stored r1 value */ + str r1, [sp, #4] /* Save it in the stack */ + ldr r1, [r0, #(4*REG_PC)] /* Fetch the stored pc value */ + str r1, [sp, #8] /* Save it at the bottom of the frame */ + + /* Now we can restore the CPSR. We wait until we are completely + * finished with the context save data to do this. Restore the CPSR + * may re-enable and interrupts and we could be in a context + * where the save structure is only protected by interrupts being + * disabled. + */ + + ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the stored CPSR value */ + msr cpsr, r1 /* Set the CPSR */ + + /* Now recover r0 and r1 */ + + ldr r0, [sp] + ldr r1, [sp, #4] + add sp, sp, #(2*4) + + /* Then return to the address at the stop of the stack, + * destroying the stack frame + */ + + ldr pc, [sp], #4 + .size up_fullcontextrestore, . - up_fullcontextrestore + diff --git a/nuttx/arch/arm/src/arm/up_head.S b/nuttx/arch/arm/src/arm/up_head.S new file mode 100644 index 0000000000..c04dddf8aa --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_head.S @@ -0,0 +1,638 @@ +/**************************************************************************** + * arch/arm/src/arm/up_head.S + * + * Copyright (C) 2007, 2009-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "arm.h" +#include "chip.h" +#include "up_internal.h" +#include "up_arch.h" + +#ifdef CONFIG_PAGING +# include +# include "pg_macros.h" +#endif + +/********************************************************************************** + * Configuration + **********************************************************************************/ + +#undef ALIGNMENT_TRAP +#undef CPU_DCACHE_WRITETHROUGH +#undef CPU_CACHE_ROUND_ROBIN +#undef CPU_DCACHE_DISABLE +#undef CPU_ICACHE_DISABLE + +/* There are three operational memory configurations: + * + * 1. We execute in place in FLASH (CONFIG_BOOT_RUNFROMFLASH=y). In this case + * the boot logic must: + * + * - Configure SDRAM, + * - Initialize the .data section in RAM, and + * - Clear .bss section + */ + +#ifdef CONFIG_BOOT_RUNFROMFLASH +# error "Configuration not implemented" +# define CONFIG_SDRAM 1 + + /* Check for the identity mapping: For this configuration, this would be + * the case where the virtual beginning of FLASH is the same as the physical + * beginning of FLASH. + */ + +# if CONFIG_FLASH_START == CONFIG_FLASH_VSTART +# define CONFIG_IDENTITY_TEXTMAP 1 +# endif + +/* 2. We boot in FLASH but copy ourselves to DRAM from better performance. + * (CONFIG_BOOT_RUNFROMFLASH=n && CONFIG_BOOT_COPYTORAM=y). In this case + * the boot logic must: + * + * - Configure SDRAM, + * - Copy ourself to DRAM (after mapping it), and + * - Clear .bss section + * + * In this case, we assume that the logic within this file executes from FLASH. + */ + +#elif defined(CONFIG_BOOT_COPYTORAM) +# error "configuration not implemented +# define CONFIG_SDRAM 1 + + /* Check for the identity mapping: For this configuration, this would be + * the case where the virtual beginning of FLASH is the same as the physical + * beginning of FLASH. + */ + +# if CONFIG_FLASH_START == CONFIG_FLASH_VSTART +# define CONFIG_IDENTITY_TEXTMAP 1 +# endif + +/* 3. There is bootloader that copies us to DRAM (but probably not to the beginning) + * (CONFIG_BOOT_RUNFROMFLASH=n && CONFIG_BOOT_COPYTORAM=n). In this case SDRAM + * was initialized by the boot loader, and this boot logic must: + * + * - Clear .bss section + */ + +#else + + /* Check for the identity mapping: For this configuration, this would be + * the case where the virtual beginning of RAM is the same as the physical + * beginning of RAM. + */ + +# if CONFIG_DRAM_START == CONFIG_DRAM_VSTART +# define CONFIG_IDENTITY_TEXTMAP 1 +# endif + +#endif + +/* For each page table offset, the following provide (1) the physical address of + * the start of the page table and (2) the number of page table entries in the + * first page table. + * + * Coarse: PG_L1_PADDRMASK=0xfffffc00 + * NPAGE1=(256 -((a) & 0x000003ff) >> 2) NPAGE1=1-256 + * Fine: PG_L1_PADDRMASK=0xfffff000 + * NPAGE1=(1024 -((a) & 0x00000fff) >> 2) NPAGE1=1-1024 + */ + +#ifdef CONFIG_PAGING +# define PG_L2_TEXT_PBASE (PG_L2_TEXT_PADDR & PG_L1_PADDRMASK) +# define PG_L2_TEXT_NPAGE1 (PTE_NPAGES - ((PG_L2_TEXT_PADDR & ~PG_L1_PADDRMASK) >> 2)) +# define PG_L2_PGTABLE_PBASE (PG_L2_PGTABLE_PADDR & PG_L1_PADDRMASK) +# define PG_L2_PGTABLE_NPAGE1 (PTE_NPAGES - ((PG_L2_PGTABLE_PADDR & ~PG_L1_PADDRMASK) >> 2)) +# define PG_L2_DATA_PBASE (PG_L2_DATA_PADDR & PG_L1_PADDRMASK) +# define PG_L2_DATA_NPAGE1 (PTE_NPAGES - ((PG_L2_DATA_PADDR & ~PG_L1_PADDRMASK) >> 2)) +#endif + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* RX_NSECTIONS determines the number of 1Mb sections to map for the + * Read/eXecute address region. This is based on CONFIG_DRAM_SIZE. For most + * ARM9 architectures, CONFIG_DRAM_SIZE describes the size of installed SDRAM. + * But for other architectures, this might refer to the size of FLASH or + * SRAM regions. (bad choice of naming). + */ + +#define RX_NSECTIONS ((CONFIG_DRAM_SIZE+0x000fffff) >> 20) + +/**************************************************************************** + * Assembly Macros + ****************************************************************************/ + +/* The ARM9 L1 page table can be placed at the beginning or at the end of the + * RAM space. This decision is based on the placement of the vector area: + * If the vectors are place in low memory at address 0x0000 0000, then the + * page table is placed in high memory; if the vectors are placed in high + * memory at address 0xfff0 0000, then the page table is locating at the + * beginning of RAM. + * + * For the special case where (1) the program executes out of RAM, and (2) the + * page is located at the beginning of RAM, then the following macro can + * easily find the physical address of the section that includes the first + * part of the text region: Since the page table is closely related to the + * NuttX base address in this case, we can convert the page table base address + * to the base address of the section containing both. + */ + +#ifdef CONFIG_ARCH_LOWVECTORS + .macro mksection, section, pgtable + bic \section, \pgtable, #0x000ff000 + .endm +#endif + +/* This macro will modify r0, r1, r2 and r14 */ + +#ifdef CONFIG_DEBUG + .macro showprogress, code + mov r0, #\code + bl up_lowputc + .endm +#else + .macro showprogress, code + .endm +#endif + +/**************************************************************************** + * Name: __start + ****************************************************************************/ + +/* We assume the bootloader has already initialized most of the h/w for us + * and that only leaves us having to do some os specific things below. + */ + .text + .global __start + .type __start, #function +__start: + /* Make sure that we are in SVC mode with all IRQs disabled */ + + mov r0, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT) + msr cpsr_c, r0 + + /* Initialize DRAM using a macro provided by board-specific logic */ + +#ifdef CONFIG_SDRAM + config_sdram +#endif + /* Clear the 16K level 1 page table */ + + ldr r4, .LCppgtable /* r4=phys. page table */ +#ifndef CONFIG_ARCH_ROMPGTABLE + mov r0, r4 + mov r1, #0 + add r2, r0, #PGTABLE_SIZE +.Lpgtableclear: + str r1, [r0], #4 + str r1, [r0], #4 + str r1, [r0], #4 + str r1, [r0], #4 + teq r0, r2 + bne .Lpgtableclear + + /* Create identity mapping for first MB of the .text section to support + * this startup logic executing out of the physical address space. This + * identity mapping will be removed by .Lvstart (see below). Of course, + * we would only do this if the physical-virtual mapping is not already + * the identity mapping. + */ + +#ifndef CONFIG_IDENTITY_TEXTMAP + mksection r0, r4 /* r0=phys. base section */ + ldr r1, .LCmmuflags /* FLGS=MMU_MEMFLAGS */ + add r3, r1, r0 /* r3=flags + base */ + str r3, [r4, r0, lsr #18] /* identity mapping */ +#endif + +#ifdef CONFIG_PAGING + + /* Map the read-only .text region in place. This must be done + * before the MMU is enabled and the virtual addressing takes + * effect. First populate the L1 table for the locked and paged + * text regions. + * + * We could probably make the the pg_l1span and pg_l2map macros into + * call-able subroutines, but we would have to be carefully during + * this phase while we are operating in a physical address space. + * + * NOTE: That the value of r5 (L1 table base address) must be + * preserved through the following. + */ + + adr r0, .Ltxtspan + ldmia r0, {r0, r1, r2, r3, r5} + pg_l1span r0, r1, r2, r3, r5, r6 + + /* Then populate the L2 table for the locked text region only. */ + + adr r0, .Ltxtmap + ldmia r0, {r0, r1, r2, r3} + pg_l2map r0, r1, r2, r3, r5 + + /* Make sure that the page table is itself mapped and and read/write-able. + * First, populate the L1 table: + */ + + adr r0, .Lptabspan + ldmia r0, {r0, r1, r2, r3, r5} + pg_l1span r0, r1, r2, r3, r5, r6 + + /* Then populate the L2 table. */ + + adr r0, .Lptabmap + ldmia r0, {r0, r1, r2, r3} + pg_l2map r0, r1, r2, r3, r5 + +#else /* CONFIG_PAGING */ + + /* Create a virtual single section mapping for the first MB of the .text + * address space. Now, we have the first 1MB mapping to both phyical and + * virtual addresses. The rest of the .text mapping will be completed in + * .Lvstart once we have moved the physical mapping out of the way. + * + * Here we expect to have: + * r4 = Address of the base of the L1 table + */ + + ldr r2, .LCvpgtable /* r2=virt. page table */ + mksection r0, r2 /* r0=virt. base section */ + str r3, [r4, r0, lsr #18] /* identity mapping */ + + /* NOTE: No .data/.bss access should be attempted. This temporary mapping + * can only be assumed to cover the initial .text region. + */ + +#endif /* CONFIG_PAGING */ +#endif /* CONFIG_ARCH_ROMPGTABLE */ + + /* The following logic will set up the ARM920/ARM926 for normal operation. + * + * Here we expect to have: + * r4 = Address of the base of the L1 table + */ + + mov r0, #0 + mcr p15, 0, r0, c7, c7 /* Invalidate I,D caches */ + mcr p15, 0, r0, c7, c10, 4 /* Drain write buffer */ + mcr p15, 0, r0, c8, c7 /* Invalidate I,D TLBs */ + mcr p15, 0, r4, c2, c0 /* Load page table pointer */ + +#ifdef CPU_DCACHE_WRITETHROUGH + mov r0, #4 /* Disable write-back on caches explicitly */ + mcr p15, 7, r0, c15, c0, 0 +#endif + + /* Enable the MMU and caches + * lr = Resume at .Lvstart with the MMU enabled + */ + + ldr lr, .LCvstart /* Abs. virtual address */ + + mov r0, #0x1f /* Domains 0, 1 = client */ + mcr p15, 0, r0, c3, c0 /* Load domain access register */ + mrc p15, 0, r0, c1, c0 /* Get control register */ + + /* Clear bits (see arm.h) + * + * CR_R - ROM MMU protection + * CR_F - Implementation defined + * CR_Z - Implementation defined + * + * CR_A - Alignment abort enable + * CR_C - Dcache enable + * CR_W - Write buffer enable + * + * CR_I - Icache enable + */ + + bic r0, r0, #(CR_R|CR_F|CR_Z) + bic r0, r0, #(CR_A|CR_C|CR_W) + bic r0, r0, #(CR_I) + + /* Set bits (see arm.h) + * + * CR_M - MMU enable + * CR_P - 32-bit exception handler + * CR_D - 32-bit data address range + */ + + orr r0, r0, #(CR_M|CR_P|CR_D) + + /* In most architectures, vectors are relocated to 0xffff0000. + * -- but not all + * + * CR_S - System MMU protection + * CR_V - Vectors relocated to 0xffff0000 + */ + +#ifndef CONFIG_ARCH_LOWVECTORS + orr r0, r0, #(CR_S|CR_V) +#else + orr r0, r0, #(CR_S) +#endif + /* CR_RR - Round Robin cache replacement */ + +#ifdef CPU_CACHE_ROUND_ROBIN + orr r0, r0, #(CR_RR) +#endif + /* CR_C - Dcache enable */ + +#ifndef CPU_DCACHE_DISABLE + orr r0, r0, #(CR_C) +#endif + /* CR_C - Dcache enable */ + +#ifndef CPU_ICACHE_DISABLE + orr r0, r0, #(CR_I) +#endif + /* CR_A - Alignment abort enable */ + +#ifdef ALIGNMENT_TRAP + orr r0, r0, #(CR_A) +#endif + mcr p15, 0, r0, c1, c0, 0 /* write control reg */ + + /* Get TMP=2 Processor ID register */ + + mrc p15, 0, r1, c0, c0, 0 /* read id reg */ + mov r1,r1 /* Null-avoiding nop */ + mov r1,r1 /* Null-avoiding nop */ + + /* And "jump" to .Lvstart */ + + mov pc, lr + +/**************************************************************************** + * PC_Relative Data + ****************************************************************************/ + + /* Most addresses are all virtual address */ + + .type .LCvstart, %object +.LCvstart: + .long .Lvstart + +#ifndef CONFIG_ARCH_ROMPGTABLE + .type .LCmmuflags, %object +.LCmmuflags: + .long MMU_MEMFLAGS /* MMU flags for memory sections */ +#endif + + .type .LCppgtable, %object +.LCppgtable: + .long PGTABLE_BASE_PADDR /* Physical start of page table */ + +#ifndef CONFIG_ARCH_ROMPGTABLE + .type .LCvpgtable, %object +.LCvpgtable: + .long PGTABLE_BASE_VADDR /* Virtual start of page table */ +#endif + +#ifdef CONFIG_PAGING + +.Ltxtspan: + .long PG_L1_TEXT_PADDR /* Physical address in the L1 table */ + .long PG_L2_TEXT_PBASE /* Physical address of the start of the L2 page table */ + .long PG_TEXT_NVPAGES /* Total (virtual) text pages to be mapped */ + .long PG_L2_TEXT_NPAGE1 /* The number of text pages in the first page table */ + .long MMU_L1_TEXTFLAGS /* L1 MMU flags to use */ + +.Ltxtmap: + .long PG_L2_LOCKED_PADDR /* Physical address in the L2 table */ + .long PG_LOCKED_PBASE /* Physical address of locked base memory */ + .long CONFIG_PAGING_NLOCKED /* Number of pages in the locked region */ + .long MMU_L2_TEXTFLAGS /* L2 MMU flags to use */ + +.Lptabspan: + .long PG_L1_PGTABLE_PADDR /* Physical address in the L1 table */ + .long PG_L2_PGTABLE_PBASE /* Physical address of the start of the L2 page table */ + .long PG_PGTABLE_NPAGES /* Total mapped page table pages */ + .long PG_L2_PGTABLE_NPAGE1 /* The number of text pages in the first page table */ + .long MMU_L1_PGTABFLAGS /* L1 MMU flags to use */ + +.Lptabmap: + .long PG_L2_PGTABLE_PADDR /* Physical address in the L2 table */ + .long PGTABLE_BASE_PADDR /* Physical address of the page table memory */ + .long PG_PGTABLE_NPAGES /* Total mapped page table pages */ + .long MMU_L2_PGTABFLAGS /* L2 MMU flags to use */ + +#endif /* CONFIG_PAGING */ + .size __start, .-__start + +/**************************************************************************** + * Name: .Lvstart + ***************************************************************************/ + +/* The following is executed after the MMU has been enabled. This uses + * absolute addresses; this is not position independent. + */ + .align 5 + .local .Lvstart + .type .Lvstart, %function +.Lvstart: + + /* Remove the temporary mapping (if one was made). The following assumes + * that the total RAM size is > 1Mb and extends that initial mapping to + * cover additinal RAM sections. + */ + + +#ifndef CONFIG_ARCH_ROMPGTABLE +#ifndef CONFIG_IDENTITY_TEXTMAP + ldr r4, .LCvpgtable /* r4=virtual page table */ + ldr r1, .LCppgtable /* r1=phys. page table */ + mksection r3, r1 /* r2=phys. base addr */ + mov r0, #0 /* flags + base = 0 */ + str r0, [r4, r3, lsr #18] /* Undo identity mapping */ +#endif + +#if defined(CONFIG_PAGING) + /* Populate the L1 table for the data region */ + + adr r0, .Ldataspan + ldmia r0, {r0, r1, r2, r3, r4} + pg_l1span r0, r1, r2, r3, r4, r5 + + /* Populate the L2 table for the data region */ + + adr r0, .Ldatamap + ldmia r0, {r0, r1, r2, r3} + pg_l2map r0, r1, r2, r3, r4 + +#elif defined(CONFIG_BOOT_RUNFROMFLASH) +# error "Logic not implemented" +#else + /* Now setup the pagetables for our normal SDRAM mappings mapped region. + * We round NUTTX_START_VADDR down to the nearest megabyte boundary. + */ + + ldr r1, .LCmmuflags /* FLGS=MMU_MEMFLAGS */ + add r3, r3, r1 /* r3=flags + base */ + + add r0, r4, #(NUTTX_START_VADDR & 0xff000000) >> 18 + bic r2, r3, #0x00f00000 + str r2, [r0] + + add r0, r0, #(NUTTX_START_VADDR & 0x00f00000) >> 18 + str r3, [r0], #4 + + /* Now map the remaining RX_NSECTIONS-1 sections of the executable + * memory region. + */ + + .rept RX_NSECTIONS-1 + add r3, r3, #SECTION_SIZE + str r3, [r0], #4 + .endr + + /* If we are executing from RAM with a fixed page configuration, then + * we can assume that the above contiguous mapping included all of the + * .text, .data, .bss, heap, etc. But if we are executing from FLASH, + * then the RAM area is probably in a separate physical address region + * and will require a separate mapping. Or, if we are supporting on-demand + * paging of the .text region, then the RAM-based .data/.bss/heap section + * will still probably be located in a separate (virtual) address region. + */ + +#endif /* CONFIG_PAGING */ +#endif /* CONFIG_ARCH_ROMPGTABLE */ + + /* Zero BSS and set up the stack pointer */ + + adr r0, .Linitparms + ldmia r0, {r0, r1, sp} + + /* Clear the frame pointer and .bss */ + + mov fp, #0 + +.Lbssinit: + cmp r0, r1 /* Clear up to _bss_end_ */ + strcc fp, [r0],#4 + bcc .Lbssinit + + /* If the .data section is in a separate, unitialized address space, + * then we will also need to copy the initial values of of the .data + * section from the .text region into that .data region. This would + * be the case if we are executing from FLASH and the .data section + * lies in a different physical address region OR if we are support + * on-demand paging and the .data section lies in a different virtual + * address region. + */ + +#if defined(CONFIG_BOOT_RUNFROMFLASH) || defined(CONFIG_PAGING) + adr r3, .Ldatainit + ldmia r3, {r0, r1, r2} + +1: ldmia r0!, {r3 - r10} + stmia r1!, {r3 - r10} + cmp r1, r2 + blt 1b +#endif + + /* Perform early C-level, platform-specific initialization */ + + bl up_boot + + /* Finally branch to the OS entry point */ + + mov lr, #0 + b os_start + + /* Text-section constants: + * + * _sbss is the start of the BSS region (see ld.script) + * _ebss is the end of the BSS regsion (see ld.script) + * + * The idle task stack starts at the end of BSS and is of size + * CONFIG_IDLETHREAD_STACKSIZE. The heap continues from there until the + * end of memory. See g_heapbase below. + */ + +.Linitparms: + .long _sbss + .long _ebss + .long _ebss+CONFIG_IDLETHREAD_STACKSIZE-4 + +#ifdef CONFIG_PAGING + +.Ldataspan: + .long PG_L1_DATA_VADDR /* Virtual address in the L1 table */ + .long PG_L2_DATA_PBASE /* Physical address of the start of the L2 page table */ + .long PG_DATA_NPAGES /* Number of pages in the data region */ + .long PG_L2_DATA_NPAGE1 /* The number of text pages in the first page table */ + .long MMU_L1_DATAFLAGS /* L1 MMU flags to use */ + +.Ldatamap: + .long PG_L2_DATA_VADDR /* Virtual address in the L2 table */ + .long PG_DATA_PBASE /* Physical address of data memory */ + .long PG_DATA_NPAGES /* Number of pages in the data region */ + .long MMU_L2_DATAFLAGS /* L2 MMU flags to use */ + +#endif /* CONFIG_PAGING */ + +#if defined(CONFIG_BOOT_RUNFROMFLASH) || defined(CONFIG_PAGING) +.Ldatainit: + .long _eronly /* Where .data defaults are stored in FLASH */ + .long _sdata /* Where .data needs to reside in SDRAM */ + .long _edata +#endif + .size .Lvstart, .-.Lvstart + + /* Data section variables */ + + /* This global variable is unsigned long g_heapbase and is + * exported from here only because of its coupling to .Linitparms + * above. + */ + + .data + .align 4 + .globl g_heapbase + .type g_heapbase, object +g_heapbase: + .long _ebss+CONFIG_IDLETHREAD_STACKSIZE + .size g_heapbase, .-g_heapbase + .end + diff --git a/nuttx/arch/arm/src/arm/up_initialstate.c b/nuttx/arch/arm/src/arm/up_initialstate.c new file mode 100644 index 0000000000..4711c9f444 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_initialstate.c @@ -0,0 +1,146 @@ +/**************************************************************************** + * arch/arm/src/arm/up_initialstate.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "arm.h" +#include "up_internal.h" +#include "up_arch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_initial_state + * + * Description: + * A new thread is being started and a new TCB + * has been created. This function is called to initialize + * the processor specific portions of the new TCB. + * + * This function must setup the intial architecture registers + * and/or stack so that execution will begin at tcb->start + * on the next context switch. + * + ****************************************************************************/ + +void up_initial_state(_TCB *tcb) +{ + struct xcptcontext *xcp = &tcb->xcp; + uint32_t cpsr; + + /* Initialize the initial exception register context structure */ + + memset(xcp, 0, sizeof(struct xcptcontext)); + + /* Save the initial stack pointer */ + + xcp->regs[REG_SP] = (uint32_t)tcb->adj_stack_ptr; + + /* Save the task entry point */ + + xcp->regs[REG_PC] = (uint32_t)tcb->start; + + /* If this task is running PIC, then set the PIC base register to the + * address of the allocated D-Space region. + */ + +#ifdef CONFIG_PIC + if (tcb->dspace != NULL) + { + /* Set the PIC base register (probably R10) to the address of the + * alloacated D-Space region. + */ + + xcp->regs[REG_PIC] = (uint32_t)tcb->dspace->region; + } +#endif + + /* Set supervisor- or user-mode, depending on how NuttX is configured and + * what kind of thread is being started. Disable FIQs in any event + */ + +#ifdef CONFIG_NUTTX_KERNEL + if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL) + { + /* It is a kernel thread.. set supervisor mode */ + + cpsr = SVC_MODE | PSR_F_BIT; + } + else + { + /* It is a normal task or a pthread. Set user mode */ + + cpsr = USR_MODE | PSR_F_BIT; + } +#else + /* If the kernel build is not selected, then all threads run in + * supervisor-mode. + */ + + cpsr = SVC_MODE | PSR_F_BIT; +#endif + + /* Enable or disable interrupts, based on user configuration */ + +# ifdef CONFIG_SUPPRESS_INTERRUPTS + cpsr |= PSR_I_BIT; +# endif + + xcp->regs[REG_CPSR] = cpsr; +} + diff --git a/nuttx/arch/arm/src/arm/up_nommuhead.S b/nuttx/arch/arm/src/arm/up_nommuhead.S new file mode 100644 index 0000000000..aac95b73a4 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_nommuhead.S @@ -0,0 +1,167 @@ +/**************************************************************************** + * arch/arm/src/arm/up_nommuhead.S + * + * Copyright (C) 2007, 2009-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "arm.h" +#include "up_internal.h" +#include "up_arch.h" + +/**************************************************************************** + * Macros + ****************************************************************************/ + + /* This macro will modify r0, r1, r2 and r14 */ + +#ifdef CONFIG_DEBUG + .macro showprogress, code + mov r0, #\code + bl up_lowputc + .endm +#else + .macro showprogress, code + .endm +#endif + +/**************************************************************************** + * OS Entry Point + ****************************************************************************/ + +/* We assume the bootloader has already initialized most of the h/w for + * us and that only leaves us having to do some os specific things + * below. + */ + .text + .global __start + .type __start, #function +__start: + + /* First, setup initial processor mode */ + + mov r0, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT ) + msr cpsr, r0 + + showprogress 'A' + + /* Setup system stack (and get the BSS range) */ + + adr r0, LC0 + ldmia r0, {r4, r5, sp} + + /* Clear system BSS section */ + + mov r0, #0 +1: cmp r4, r5 + strcc r0, [r4], #4 + bcc 1b + + showprogress 'B' + + /* Copy system .data sections to new home in RAM. */ + +#ifdef CONFIG_BOOT_RUNFROMFLASH + + adr r3, LC2 + ldmia r3, {r0, r1, r2} + +1: ldmia r0!, {r3 - r10} + stmia r1!, {r3 - r10} + cmp r1, r2 + blt 1b + +#endif + + /* Perform early serial initialization */ + + mov fp, #0 +#ifdef USE_EARLYSERIALINIT + bl up_earlyserialinit +#endif + +#ifdef CONFIG_DEBUG + mov r0, #'C' + bl up_putc + mov r0, #'\n' + bl up_putc +#endif + /* Initialize onboard LEDs */ + +#ifdef CONFIG_ARCH_LEDS + bl up_ledinit +#endif + + /* Then jump to OS entry */ + + b os_start + + /* Variables: + * _sbss is the start of the BSS region (see ld.script) + * _ebss is the end of the BSS regsion (see ld.script) + * The idle task stack starts at the end of BSS and is + * of size CONFIG_IDLETHREAD_STACKSIZE. The heap continues + * from there until the end of memory. See g_heapbase + * below. + */ + +LC0: .long _sbss + .long _ebss + .long _ebss+CONFIG_IDLETHREAD_STACKSIZE-4 + +#ifdef CONFIG_BOOT_RUNFROMFLASH +LC2: .long _eronly /* Where .data defaults are stored in FLASH */ + .long _sdata /* Where .data needs to reside in SDRAM */ + .long _edata +#endif + .size __start, .-__start + + /* This global variable is unsigned long g_heapbase and is + * exported from here only because of its coupling to LCO + * above. + */ + + .data + .align 4 + .globl g_heapbase + .type g_heapbase, object +g_heapbase: + .long _ebss+CONFIG_IDLETHREAD_STACKSIZE + .size g_heapbase, .-g_heapbase + + .end + diff --git a/nuttx/arch/arm/src/arm/up_pginitialize.c b/nuttx/arch/arm/src/arm/up_pginitialize.c new file mode 100755 index 0000000000..1aea951134 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_pginitialize.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * arch/arm/src/arm/up_pginitialize.c + * Initialize the MMU for on-demand paging support. + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "up_internal.h" + +#ifdef CONFIG_PAGING + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_pginitialize() + * + * Description: + * Initialize the MMU for on-demand paging support.. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. This function will crash if any errors are detected during MMU + * initialization + * + * Assumptions: + * - Called early in the platform initialization sequence so that no special + * concurrency protection is required. + * + ****************************************************************************/ + +void up_pginitialize(void) +{ + /* None needed at present. This file is just retained in case the need + * arises in the future. Nothing calls up_pginitialize() now. If needed, + * if should be called early in up_boot.c to assure that all paging is + * ready. + */ +} + +#endif /* CONFIG_PAGING */ diff --git a/nuttx/arch/arm/src/arm/up_prefetchabort.c b/nuttx/arch/arm/src/arm/up_prefetchabort.c new file mode 100644 index 0000000000..ed3dd91d33 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_prefetchabort.c @@ -0,0 +1,154 @@ +/**************************************************************************** + * arch/arm/src/src/up_prefetchabort.c + * + * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#ifdef CONFIG_PAGING +# include +#endif + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Debug ********************************************************************/ + +/* Output debug info if stack dump is selected -- even if + * debug is not selected. + */ + +#ifdef CONFIG_ARCH_STACKDUMP +# undef lldbg +# define lldbg lib_lowprintf +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_prefetchabort + * + * Description; + * This is the prefetch abort exception handler. The ARM prefetch abort + * exception occurs when a memory fault is detected during an an + * instruction fetch. + * + ****************************************************************************/ + +void up_prefetchabort(uint32_t *regs) +{ +#ifdef CONFIG_PAGING + uint32_t *savestate; + + /* Save the saved processor context in current_regs where it can be accessed + * for register dumps and possibly context switching. + */ + + savestate = (uint32_t*)current_regs; +#endif + current_regs = regs; + +#ifdef CONFIG_PAGING + /* Get the (virtual) address of instruction that caused the prefetch abort. + * When the exception occurred, this address was provided in the lr register + * and this value was saved in the context save area as the PC at the + * REG_R15 index. + * + * Check to see if this miss address is within the configured range of + * virtual addresses. + */ + + pglldbg("VADDR: %08x VBASE: %08x VEND: %08x\n", + regs[REG_PC], PG_PAGED_VBASE, PG_PAGED_VEND); + + if (regs[REG_R15] >= PG_PAGED_VBASE && regs[REG_R15] < PG_PAGED_VEND) + { + /* Save the offending PC as the fault address in the TCB of the currently + * executing task. This value is, of course, already known in regs[REG_R15], + * but saving it in this location will allow common paging logic for both + * prefetch and data aborts. + */ + + FAR _TCB *tcb = (FAR _TCB *)g_readytorun.head; + tcb->xcp.far = regs[REG_R15]; + + /* Call pg_miss() to schedule the page fill. A consequences of this + * call are: + * + * (1) The currently executing task will be blocked and saved on + * on the g_waitingforfill task list. + * (2) An interrupt-level context switch will occur so that when + * this function returns, it will return to a different task, + * most likely the page fill worker thread. + * (3) The page fill worker task has been signalled and should + * execute immediately when we return from this exception. + */ + + pg_miss(); + + /* Restore the previous value of current_regs. NULL would indicate that + * we are no longer in an interrupt handler. It will be non-NULL if we + * are returning from a nested interrupt. + */ + + current_regs = savestate; + } + else +#endif + { + lldbg("Prefetch abort. PC: %08x\n", regs[REG_PC]); + PANIC(OSERR_ERREXCEPTION); + } +} diff --git a/nuttx/arch/arm/src/arm/up_releasepending.c b/nuttx/arch/arm/src/arm/up_releasepending.c new file mode 100755 index 0000000000..dcad401593 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_releasepending.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * arch/arm/src/arm/up_releasepending.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_release_pending + * + * Description: + * Release and ready-to-run tasks that have + * collected in the pending task list. This can call a + * context switch if a new task is placed at the head of + * the ready to run list. + * + ****************************************************************************/ + +void up_release_pending(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + + slldbg("From TCB=%p\n", rtcb); + + /* Merge the g_pendingtasks list into the g_readytorun task list */ + + /* sched_lock(); */ + if (sched_mergepending()) + { + /* The currently active task has changed! We will need to + * switch contexts. First check if we are operating in + * interrupt context: + */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + slldbg("New Active Task TCB=%p\n", rtcb); + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* Copy the exception context into the TCB of the task that + * was currently active. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task + * restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + slldbg("New Active Task TCB=%p\n", rtcb); + + /* Then switch contexts */ + + up_fullcontextrestore(rtcb->xcp.regs); + } + } +} diff --git a/nuttx/arch/arm/src/arm/up_reprioritizertr.c b/nuttx/arch/arm/src/arm/up_reprioritizertr.c new file mode 100755 index 0000000000..38bce2a72b --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_reprioritizertr.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * arch/arm/src/arm/up_reprioritizertr.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_reprioritize_rtr + * + * Description: + * Called when the priority of a running or + * ready-to-run task changes and the reprioritization will + * cause a context switch. Two cases: + * + * 1) The priority of the currently running task drops and the next + * task in the ready to run list has priority. + * 2) An idle, ready to run task's priority has been raised above the + * the priority of the current, running task and it now has the + * priority. + * + * Inputs: + * tcb: The TCB of the task that has been reprioritized + * priority: The new task priority + * + ****************************************************************************/ + +void up_reprioritize_rtr(_TCB *tcb, uint8_t priority) +{ + /* Verify that the caller is sane */ + + if (tcb->task_state < FIRST_READY_TO_RUN_STATE || + tcb->task_state > LAST_READY_TO_RUN_STATE +#if SCHED_PRIORITY_MIN > 0 + || priority < SCHED_PRIORITY_MIN +#endif +#if SCHED_PRIORITY_MAX < UINT8_MAX + || priority > SCHED_PRIORITY_MAX +#endif + ) + { + PANIC(OSERR_BADREPRIORITIZESTATE); + } + else + { + _TCB *rtcb = (_TCB*)g_readytorun.head; + bool switch_needed; + + slldbg("TCB=%p PRI=%d\n", tcb, priority); + + /* Remove the tcb task from the ready-to-run list. + * sched_removereadytorun will return true if we just + * remove the head of the ready to run list. + */ + + switch_needed = sched_removereadytorun(tcb); + + /* Setup up the new task priority */ + + tcb->sched_priority = (uint8_t)priority; + + /* Return the task to the specified blocked task list. + * sched_addreadytorun will return true if the task was + * added to the new list. We will need to perform a context + * switch only if the EXCLUSIVE or of the two calls is non-zero + * (i.e., one and only one the calls changes the head of the + * ready-to-run list). + */ + + switch_needed ^= sched_addreadytorun(tcb); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + /* If we are going to do a context switch, then now is the right + * time to add any pending tasks back into the ready-to-run list. + * task list now + */ + + if (g_pendingtasks.head) + { + sched_mergepending(); + } + + /* Are we in an interrupt handler? */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + slldbg("New Active Task TCB=%p\n", rtcb); + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* Copy the exception context into the TCB at the (old) head of the + * g_readytorun Task list. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + slldbg("New Active Task TCB=%p\n", rtcb); + + /* Then switch contexts */ + + up_fullcontextrestore(rtcb->xcp.regs); + } + } + } +} diff --git a/nuttx/arch/arm/src/arm/up_saveusercontext.S b/nuttx/arch/arm/src/arm/up_saveusercontext.S new file mode 100644 index 0000000000..8d154d1873 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_saveusercontext.S @@ -0,0 +1,119 @@ +/************************************************************************** + * arch/arm/src/arm/up_saveusercontext.S + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************/ + +/************************************************************************** + * Included Files + **************************************************************************/ + +#include +#include "up_internal.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ + +/************************************************************************** + * Private Types + **************************************************************************/ + +/************************************************************************** + * Private Function Prototypes + **************************************************************************/ + +/************************************************************************** + * Global Variables + **************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/************************************************************************** + * Public Functions + **************************************************************************/ + +/************************************************************************** + * Name: up_saveusercontext + **************************************************************************/ + + .text + .globl up_saveusercontext + .type up_saveusercontext, function +up_saveusercontext: + /* On entry, a1 (r0) holds address of struct xcptcontext. + * Offset to the user region. + */ + + /* Make sure that the return value will be non-zero (the + * value of the other volatile registers don't matter -- + * r1-r3, ip). This function is called throught the + * noraml C calling conventions and the values of these + * registers cannot be assumed at the point of setjmp + * return. + */ + + mov ip, #1 + str ip, [r0, #(4*REG_R0)] + + /* Save the volatile registers (plus r12 which really + * doesn't need to be saved) + */ + + add r1, r0, #(4*REG_R4) + stmia r1, {r4-r14} + + /* Save the current cpsr */ + + mrs r2, cpsr /* R3 = CPSR value */ + add r1, r0, #(4*REG_CPSR) + str r2, [r1] + + /* Finally save the return address as the PC so that we + * return to the exit from this function. + */ + + add r1, r0, #(4*REG_PC) + str lr, [r1] + + /* Return 0 */ + + mov r0, #0 /* Return value == 0 */ + mov pc, lr /* Return */ + .size up_saveusercontext, . - up_saveusercontext + diff --git a/nuttx/arch/arm/src/arm/up_schedulesigaction.c b/nuttx/arch/arm/src/arm/up_schedulesigaction.c new file mode 100644 index 0000000000..0dfb6e540f --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_schedulesigaction.c @@ -0,0 +1,204 @@ +/**************************************************************************** + * arch/arm/src/arm/up_schedulesigaction.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "arm.h" +#include "os_internal.h" +#include "up_internal.h" +#include "up_arch.h" + +#ifndef CONFIG_DISABLE_SIGNALS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_schedule_sigaction + * + * Description: + * This function is called by the OS when one or more + * signal handling actions have been queued for execution. + * The architecture specific code must configure things so + * that the 'igdeliver' callback is executed on the thread + * specified by 'tcb' as soon as possible. + * + * This function may be called from interrupt handling logic. + * + * This operation should not cause the task to be unblocked + * nor should it cause any immediate execution of sigdeliver. + * Typically, a few cases need to be considered: + * + * (1) This function may be called from an interrupt handler + * During interrupt processing, all xcptcontext structures + * should be valid for all tasks. That structure should + * be modified to invoke sigdeliver() either on return + * from (this) interrupt or on some subsequent context + * switch to the recipient task. + * (2) If not in an interrupt handler and the tcb is NOT + * the currently executing task, then again just modify + * the saved xcptcontext structure for the recipient + * task so it will invoke sigdeliver when that task is + * later resumed. + * (3) If not in an interrupt handler and the tcb IS the + * currently executing task -- just call the signal + * handler now. + * + ****************************************************************************/ + +void up_schedule_sigaction(_TCB *tcb, sig_deliver_t sigdeliver) +{ + /* Refuse to handle nested signal actions */ + + sdbg("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver); + + if (!tcb->xcp.sigdeliver) + { + irqstate_t flags; + + /* Make sure that interrupts are disabled */ + + flags = irqsave(); + + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ + + sdbg("rtcb=0x%p current_regs=0x%p\n", g_readytorun.head, current_regs); + + if (tcb == (_TCB*)g_readytorun.head) + { + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. + */ + + if (!current_regs) + { + /* In this case just deliver the signal now. */ + + sigdeliver(tcb); + } + + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following + * logic would fail in the strange case where we are in an + * interrupt handler, the thread is signalling itself, but + * a context switch to another task has occurred so that + * current_regs does not refer to the thread at g_readytorun.head! + */ + + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pc = current_regs[REG_PC]; + tcb->xcp.saved_cpsr = current_regs[REG_CPSR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + current_regs[REG_PC] = (uint32_t)up_sigdeliver; + current_regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + up_savestate(tcb->xcp.regs); + } + } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; + tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver; + tcb->xcp.regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT; + } + + irqrestore(flags); + } +} + +#endif /* !CONFIG_DISABLE_SIGNALS */ diff --git a/nuttx/arch/arm/src/arm/up_sigdeliver.c b/nuttx/arch/arm/src/arm/up_sigdeliver.c new file mode 100644 index 0000000000..f92f85e7e0 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_sigdeliver.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * arch/arm/src/arm/up_sigdeliver.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "os_internal.h" +#include "up_internal.h" +#include "up_arch.h" + +#ifndef CONFIG_DISABLE_SIGNALS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_sigdeliver + * + * Description: + * This is the a signal handling trampoline. When a signal action was + * posted. The task context was mucked with and forced to branch to this + * location with interrupts disabled. + * + ****************************************************************************/ + +void up_sigdeliver(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + uint32_t regs[XCPTCONTEXT_REGS]; + sig_deliver_t sigdeliver; + + /* Save the errno. This must be preserved throughout the signal handling + * so that the user code final gets the correct errno value (probably + * EINTR). + */ + + int saved_errno = rtcb->pterrno; + + up_ledon(LED_SIGNAL); + + sdbg("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", + rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); + ASSERT(rtcb->xcp.sigdeliver != NULL); + + /* Save the real return state on the stack. */ + + up_copystate(regs, rtcb->xcp.regs); + regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_CPSR] = rtcb->xcp.saved_cpsr; + + /* Get a local copy of the sigdeliver function pointer. we do this so that + * we can nullify the sigdeliver function pointer in the TCB and accept + * more signal deliveries while processing the current pending signals. + */ + + sigdeliver = rtcb->xcp.sigdeliver; + rtcb->xcp.sigdeliver = NULL; + + /* Then restore the task interrupt state */ + + irqrestore(regs[REG_CPSR]); + + /* Deliver the signals */ + + sigdeliver(rtcb); + + /* Output any debug messages BEFORE restoring errno (because they may + * alter errno), then disable interrupts again and restore the original + * errno that is needed by the user logic (it is probably EINTR). + */ + + sdbg("Resuming\n"); + (void)irqsave(); + rtcb->pterrno = saved_errno; + + /* Then restore the correct state for this thread of execution. */ + + up_ledoff(LED_SIGNAL); + up_fullcontextrestore(regs); +} + +#endif /* !CONFIG_DISABLE_SIGNALS */ + diff --git a/nuttx/arch/arm/src/arm/up_syscall.c b/nuttx/arch/arm/src/arm/up_syscall.c new file mode 100644 index 0000000000..f331a13146 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_syscall.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * arch/arm/src/arm/up_syscall.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Output debug info if stack dump is selected -- even if + * debug is not selected. + */ + +#ifdef CONFIG_ARCH_STACKDUMP +# undef lldbg +# define lldbg lib_lowprintf +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * vectors + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_syscall + * + * Description: + * SWI interrupts will vection here with insn=the SWI + * instruction and xcp=the interrupt context + * + * The handler may get the SWI number be de-referencing + * the return address saved in the xcp and decoding + * the SWI instruction + * + ****************************************************************************/ + +void up_syscall(uint32_t *regs) +{ + lldbg("Syscall from 0x%x\n", regs[REG_PC]); + current_regs = regs; + PANIC(OSERR_ERREXCEPTION); +} diff --git a/nuttx/arch/arm/src/arm/up_unblocktask.c b/nuttx/arch/arm/src/arm/up_unblocktask.c new file mode 100755 index 0000000000..73e292561f --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_unblocktask.c @@ -0,0 +1,159 @@ +/**************************************************************************** + * arch/arm/src/arm/up_unblocktask.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#include "clock_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_unblock_task + * + * Description: + * A task is currently in an inactive task list + * but has been prepped to execute. Move the TCB to the + * ready-to-run list, restore its context, and start execution. + * + * Inputs: + * tcb: Refers to the tcb to be unblocked. This tcb is + * in one of the waiting tasks lists. It must be moved to + * the ready-to-run list and, if it is the highest priority + * ready to run taks, executed. + * + ****************************************************************************/ + +void up_unblock_task(_TCB *tcb) +{ + /* Verify that the context switch can be performed */ + + if ((tcb->task_state < FIRST_BLOCKED_STATE) || + (tcb->task_state > LAST_BLOCKED_STATE)) + { + PANIC(OSERR_BADUNBLOCKSTATE); + } + else + { + _TCB *rtcb = (_TCB*)g_readytorun.head; + + /* Remove the task from the blocked task list */ + + sched_removeblocked(tcb); + + /* Reset its timeslice. This is only meaningful for round + * robin tasks but it doesn't here to do it for everything + */ + +#if CONFIG_RR_INTERVAL > 0 + tcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; +#endif + + /* Add the task in the correct location in the prioritized + * g_readytorun task list + */ + + if (sched_addreadytorun(tcb)) + { + /* The currently active task has changed! We need to do + * a context switch to the new task. + * + * Are we in an interrupt handler? + */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* We are not in an interrupt handler. Copy the user C context + * into the TCB of the task that was previously active. if + * up_saveusercontext returns a non-zero value, then this is really the + * previously running task restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the new task that is ready to + * run (probably tcb). This is the new rtcb at the head of the + * g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + + /* Then switch contexts */ + + up_fullcontextrestore(rtcb->xcp.regs); + } + } + } +} diff --git a/nuttx/arch/arm/src/arm/up_undefinedinsn.c b/nuttx/arch/arm/src/arm/up_undefinedinsn.c new file mode 100644 index 0000000000..4c50991b0f --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_undefinedinsn.c @@ -0,0 +1,81 @@ +/**************************************************************************** + * arch/arm/src/arm/up_undefinedinsn.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Output debug info if stack dump is selected -- even if + * debug is not selected. + */ + +#ifdef CONFIG_ARCH_STACKDUMP +# undef lldbg +# define lldbg lib_lowprintf +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_undefinedinsn + ****************************************************************************/ + +void up_undefinedinsn(uint32_t *regs) +{ + lldbg("Undefined instruction at 0x%x\n", regs[REG_PC]); + current_regs = regs; + PANIC(OSERR_UNDEFINEDINSN); +} diff --git a/nuttx/arch/arm/src/arm/up_va2pte.c b/nuttx/arch/arm/src/arm/up_va2pte.c new file mode 100755 index 0000000000..5f92ad8218 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_va2pte.c @@ -0,0 +1,121 @@ +/**************************************************************************** + * arch/arm/src/arm/up_va2pte.c + * Utility to map a virtual address to a L2 page table entry. + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "chip.h" +#include "pg_macros.h" +#include "up_internal.h" + +#ifdef CONFIG_PAGING + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_va2pte() + * + * Description: + * Convert a virtual address within the paged text region into a pointer to + * the corresponding page table entry. + * + * Input Parameters: + * vaddr - The virtual address within the paged text region. + * + * Returned Value: + * A pointer to the corresponding page table entry. + * + * Assumptions: + * - This function is called from the normal tasking context (but with + * interrupts disabled). The implementation must take whatever actions + * are necessary to assure that the operation is safe within this + * context. + * + ****************************************************************************/ + +uint32_t *up_va2pte(uintptr_t vaddr) +{ + uint32_t L1; + uint32_t *L2; + unsigned int ndx; + + /* The virtual address is expected to lie in the paged text region */ + + DEBUGASSERT(vaddr >= PG_PAGED_VBASE && vaddr < PG_PAGED_VEND); + + /* Get the L1 table entry associated with this virtual address */ + + L1 = *(uint32_t*)PG_POOL_VA2L1VADDR(vaddr); + + /* Get the address of the L2 page table from the L1 entry */ + + L2 = (uint32_t*)PG_POOL_L12VPTABLE(L1); + + /* Get the index into the L2 page table. Each L1 entry maps + * 256 x 4Kb or 1024 x 1Kb pages. + */ + + ndx = (vaddr & 0x000fffff) >> PAGESHIFT; + + /* Return true if this virtual address is mapped. */ + + return &L2[ndx]; +} + +#endif /* CONFIG_PAGING */ diff --git a/nuttx/arch/arm/src/arm/up_vectoraddrexcptn.S b/nuttx/arch/arm/src/arm/up_vectoraddrexcptn.S new file mode 100644 index 0000000000..e034c394f6 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_vectoraddrexcptn.S @@ -0,0 +1,83 @@ +/************************************************************************************ + * arch/arm/src/src/up_vectoraddrexceptn.S + * + * Copyright (C) 2008-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include "up_arch.h" + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/************************************************************************************ + * Global Data + ************************************************************************************/ + +/************************************************************************************ + * Assembly Macros + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + + .text + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + + .text + +/************************************************************************************ + * Name: up_vectoraddrexcption + * + * Description: + * Shouldn't happen. This exception handler is in a separate file from other + * vector handlers because some processors (e.g., lpc2148) do not support the + * the Address Exception vector. + * + ************************************************************************************/ + + .globl up_vectoraddrexcptn + .type up_vectoraddrexcptn, %function +up_vectoraddrexcptn: + b up_vectoraddrexcptn + .size up_vectoraddrexcptn, . - up_vectoraddrexcptn + .end diff --git a/nuttx/arch/arm/src/arm/up_vectors.S b/nuttx/arch/arm/src/arm/up_vectors.S new file mode 100644 index 0000000000..00c5d52b06 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_vectors.S @@ -0,0 +1,446 @@ +/************************************************************************************ + * arch/arm/src/arm/up_vectors.S + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +#include "arm.h" +#include "up_arch.h" + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/************************************************************************************ + * Global Data + ************************************************************************************/ + + .data +g_irqtmp: + .word 0 /* Saved lr */ + .word 0 /* Saved spsr */ +g_undeftmp: + .word 0 /* Saved lr */ + .word 0 /* Saved spsr */ +g_aborttmp: + .word 0 /* Saved lr */ + .word 0 /* Saved spsr */ + +/************************************************************************************ + * Assembly Macros + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + + .text + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + + .text + +/************************************************************************************ + * Name: up_vectorirq + * + * Description: + * Interrupt excetpion. Entered in IRQ mode with spsr = SVC CPSR, lr = SVC PC + * + ************************************************************************************/ + + .globl up_vectorirq + .type up_vectorirq, %function +up_vectorirq: + /* On entry, we are in IRQ mode. We are free to use + * the IRQ mode r13 and r14. + */ + + ldr r13, .Lirqtmp + sub lr, lr, #4 + str lr, [r13] @ save lr_IRQ + mrs lr, spsr + str lr, [r13, #4] @ save spsr_IRQ + + /* Then switch back to SVC mode */ + + bic lr, lr, #MODE_MASK /* Keep F and T bits */ + orr lr, lr, #(SVC_MODE | PSR_I_BIT) + msr cpsr_c, lr /* Switch to SVC mode */ + + /* Create a context structure. First set aside a stack frame + * and store r0-r12 into the frame. + */ + + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ + + /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */ + + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 + + /* Get the values for r15(pc) and CPSR in r3 and r4 */ + + ldr r0, .Lirqtmp /* Points to temp storage */ + ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ + + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + stmia r0, {r1-r4} + + /* Then call the IRQ handler with interrupts disabled. */ + + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + ldr sp, .Lirqstackbase /* SP = interrupt stack base */ + str r0, [sp] /* Save the user stack pointer */ + bl up_decodeirq /* Call the handler */ + ldr sp, [sp] /* Restore the user stack pointer */ +#else + bl up_decodeirq /* Call the handler */ +#endif + + /* Restore the CPSR, SVC modr registers and return */ +.Lnoirqset: + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr, r0 + ldmia sp, {r0-r15}^ /* Return */ + +.Lirqtmp: + .word g_irqtmp +#if CONFIG_ARCH_INTERRUPTSTACK > 3 +.Lirqstackbase: + .word up_stackbase +#endif + .size up_vectorirq, . - up_vectorirq + .align 5 + +/************************************************************************************ + * Function: up_vectorswi + * + * Description: + * SWI interrupt. We enter the SWI in SVC mode. + * + ************************************************************************************/ + + .globl up_vectorswi + .type up_vectorswi, %function +up_vectorswi: + + /* Create a context structure. First set aside a stack frame + * and store r0-r12 into the frame. + */ + + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ + + /* Get the correct values of r13(sp), r14(lr), r15(pc) + * and CPSR in r1-r4 */ + + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 /* R14 is altered on return from SWI */ + mov r3, r14 /* Save r14 as the PC as well */ + mrs r4, spsr /* Get the saved CPSR */ + + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + stmia r0, {r1-r4} + + /* Then call the SWI handler with interrupts disabled. + * void up_syscall(struct xcptcontext *xcp) + */ + + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ + bl up_syscall /* Call the handler */ + + /* Restore the CPSR, SVC modr registers and return */ + + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr, r0 + ldmia sp, {r0-r15}^ /* Return */ + .size up_vectorswi, . - up_vectorswi + + .align 5 + +/************************************************************************************ + * Name: up_vectordata + * + * Description: + * This is the data abort exception dispatcher. The ARM data abort exception occurs + * when a memory fault is detected during a data transfer. This handler saves the + * current processor state and gives control to data abort handler. This function + * is entered in ABORT mode with spsr = SVC CPSR, lr = SVC PC + * + ************************************************************************************/ + + .globl up_vectordata + .type up_vectordata, %function +up_vectordata: + /* On entry we are free to use the ABORT mode registers + * r13 and r14 + */ + + ldr r13, .Ldaborttmp /* Points to temp storage */ + sub lr, lr, #8 /* Fixup return */ + str lr, [r13] /* Save in temp storage */ + mrs lr, spsr /* Get SPSR */ + str lr, [r13, #4] /* Save in temp storage */ + + /* Then switch back to SVC mode */ + + bic lr, lr, #MODE_MASK /* Keep F and T bits */ + orr lr, lr, #(SVC_MODE | PSR_I_BIT) + msr cpsr_c, lr /* Switch to SVC mode */ + + /* Create a context structure. First set aside a stack frame + * and store r0-r12 into the frame. + */ + + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ + + /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */ + + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 + + /* Get the values for r15(pc) and CPSR in r3 and r4 */ + + ldr r0, .Ldaborttmp /* Points to temp storage */ + ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ + + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + stmia r0, {r1-r4} + + /* Then call the data abort handler with interrupts disabled. + * void up_dataabort(struct xcptcontext *xcp) + */ + + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ +#ifdef CONFIG_PAGING + mrc p15, 0, r2, c5, c0, 0 /* Get r2=FSR */ + mrc p15, 0, r1, c6, c0, 0 /* Get R1=FAR */ +#endif + bl up_dataabort /* Call the handler */ + + /* Restore the CPSR, SVC modr registers and return */ + + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr_cxsf, r0 + ldmia sp, {r0-r15}^ /* Return */ + +.Ldaborttmp: + .word g_aborttmp + .size up_vectordata, . - up_vectordata + + .align 5 + +/************************************************************************************ + * Name: up_vectorprefetch + * + * Description: + * This is the prefetch abort exception dispatcher. The ARM prefetch abort exception + * occurs when a memory fault is detected during an an instruction fetch. This + * handler saves the current processor state and gives control to prefetch abort + * handler. This function is entered in ABT mode with spsr = SVC CPSR, lr = SVC PC. + * + ************************************************************************************/ + + .globl up_vectorprefetch + .type up_vectorprefetch, %function +up_vectorprefetch: + /* On entry we are free to use the ABORT mode registers + * r13 and r14 + */ + + ldr r13, .Lpaborttmp /* Points to temp storage */ + sub lr, lr, #4 /* Fixup return */ + str lr, [r13] /* Save in temp storage */ + mrs lr, spsr /* Get SPSR */ + str lr, [r13, #4] /* Save in temp storage */ + + /* Then switch back to SVC mode */ + + bic lr, lr, #MODE_MASK /* Keep F and T bits */ + orr lr, lr, #(SVC_MODE | PSR_I_BIT) + msr cpsr_c, lr /* Switch to SVC mode */ + + /* Create a context structure. First set aside a stack frame + * and store r0-r12 into the frame. + */ + + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ + + /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */ + + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 + + /* Get the values for r15(pc) and CPSR in r3 and r4 */ + + ldr r0, .Lpaborttmp /* Points to temp storage */ + ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ + + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + stmia r0, {r1-r4} + + /* Then call the prefetch abort handler with interrupts disabled. + * void up_prefetchabort(struct xcptcontext *xcp) + */ + + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ + bl up_prefetchabort /* Call the handler */ + + /* Restore the CPSR, SVC modr registers and return */ + + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr_cxsf, r0 + ldmia sp, {r0-r15}^ /* Return */ + +.Lpaborttmp: + .word g_aborttmp + .size up_vectorprefetch, . - up_vectorprefetch + + .align 5 + +/************************************************************************************ + * Name: up_vectorundefinsn + * + * Description: + * Undefined instruction entry exception. Entered in UND mode, spsr = SVC CPSR, + * lr = SVC PC + * + ************************************************************************************/ + + .globl up_vectorundefinsn + .type up_vectorundefinsn, %function +up_vectorundefinsn: + /* On entry we are free to use the UND mode registers + * r13 and r14 + */ + + ldr r13, .Lundeftmp /* Points to temp storage */ + str lr, [r13] /* Save in temp storage */ + mrs lr, spsr /* Get SPSR */ + str lr, [r13, #4] /* Save in temp storage */ + + /* Then switch back to SVC mode */ + + bic lr, lr, #MODE_MASK /* Keep F and T bits */ + orr lr, lr, #(SVC_MODE | PSR_I_BIT) + msr cpsr_c, lr /* Switch to SVC mode */ + + /* Create a context structure. First set aside a stack frame + * and store r0-r12 into the frame. + */ + + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ + + /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */ + + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 + + /* Get the values for r15(pc) and CPSR in r3 and r4 */ + + ldr r0, .Lundeftmp /* Points to temp storage */ + ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ + + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + stmia r0, {r1-r4} + + /* Then call the undef insn handler with interrupts disabled. + * void up_undefinedinsn(struct xcptcontext *xcp) + */ + + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ + bl up_undefinedinsn /* Call the handler */ + + /* Restore the CPSR, SVC modr registers and return */ + + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr_cxsf, r0 + ldmia sp, {r0-r15}^ /* Return */ + +.Lundeftmp: + .word g_undeftmp + .size up_vectorundefinsn, . - up_vectorundefinsn + + .align 5 + +/************************************************************************************ + * Name: up_vectorfiq + * + * Description: + * Shouldn't happen + * + ************************************************************************************/ + + .globl up_vectorfiq + .type up_vectorfiq, %function +up_vectorfiq: + subs pc, lr, #4 + .size up_vectorfiq, . - up_vectorfiq + +/************************************************************************************ + * Name: up_interruptstack/g_userstack + ************************************************************************************/ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + .bss + .align 4 + .globl g_userstack + .type g_userstack, object +up_interruptstack: + .skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4) +g_userstack: +up_stackbase: + .skip 4 + .size g_userstack, 4 + .size up_interruptstack, (CONFIG_ARCH_INTERRUPTSTACK & ~3) +#endif + .end diff --git a/nuttx/arch/arm/src/arm/up_vectortab.S b/nuttx/arch/arm/src/arm/up_vectortab.S new file mode 100644 index 0000000000..a7972fa3c2 --- /dev/null +++ b/nuttx/arch/arm/src/arm/up_vectortab.S @@ -0,0 +1,103 @@ +/**************************************************************************** + * arch/arm/src/arm/up_vectortab.S + * + * Copyright (C) 2007, 2009-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Data + ****************************************************************************/ + +/**************************************************************************** + * Assembly Macros + ****************************************************************************/ + +/**************************************************************************** + * Name: _vector_start + * + * Description: + * Vector initialization block + ****************************************************************************/ + + .globl _vector_start + +/* These will be relocated to VECTOR_BASE. */ + +_vector_start: + ldr pc, .Lresethandler /* 0x00: Reset */ + ldr pc, .Lundefinedhandler /* 0x04: Undefined instruction */ + ldr pc, .Lswihandler /* 0x08: Software interrupt */ + ldr pc, .Lprefetchaborthandler /* 0x0c: Prefetch abort */ + ldr pc, .Ldataaborthandler /* 0x10: Data abort */ + ldr pc, .Laddrexcptnhandler /* 0x14: Address exception */ + ldr pc, .Lirqhandler /* 0x18: IRQ */ + ldr pc, .Lfiqhandler /* 0x1c: FIQ */ + + .globl __start + .globl up_vectorundefinsn + .globl up_vectorswi + .globl up_vectorprefetch + .globl up_vectordata + .globl up_vectoraddrexcptn + .globl up_vectorirq + .globl up_vectorfiq + +.Lresethandler: + .long __start +.Lundefinedhandler: + .long up_vectorundefinsn +.Lswihandler: + .long up_vectorswi +.Lprefetchaborthandler: + .long up_vectorprefetch +.Ldataaborthandler: + .long up_vectordata +.Laddrexcptnhandler: + .long up_vectoraddrexcptn +.Lirqhandler: + .long up_vectorirq +.Lfiqhandler: + .long up_vectorfiq + + .globl _vector_end +_vector_end: + .end diff --git a/nuttx/arch/arm/src/armv7-m/exc_return.h b/nuttx/arch/arm/src/armv7-m/exc_return.h new file mode 100644 index 0000000000..cffbd3e2ee --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/exc_return.h @@ -0,0 +1,117 @@ +/************************************************************************************ + * arch/arm/src/armv7-m/exc_return.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_COMMON_CORTEXM_EXC_RETURN_H +#define __ARCH_ARM_SRC_COMMON_CORTEXM_EXC_RETURN_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* The processor saves an EXC_RETURN value to the LR on exception entry. The + * exception mechanism relies on this value to detect when the processor has + * completed an exception handler. + * + * Bits [31:28] of an EXC_RETURN value are always 1. When the processor loads a + * value matching this pattern to the PC it detects that the operation is a not + * a normal branch operation and instead, that the exception is complete. + * Therefore, it starts the exception return sequence. + * + * Bits[4:0] of the EXC_RETURN value indicate the required return stack and eventual + * processor mode. The remaining bits of the EXC_RETURN value should be set to 1. + */ + +/* EXC_RETURN_BASE: Bits that are always set in an EXC_RETURN value. */ + +#define EXC_RETURN_BASE 0xffffffe1 + +/* EXC_RETURN_PROCESS_STACK: The exception saved (and will restore) the hardware + * context using the process stack pointer (if not set, the context was saved + * using the main stack pointer) + */ + +#define EXC_RETURN_PROCESS_STACK (1 << 2) + +/* EXC_RETURN_THREAD_MODE: The exception will return to thread mode (if not set, + * return stays in handler mode) + */ + +#define EXC_RETURN_THREAD_MODE (1 << 3) + +/* EXC_RETURN_STD_CONTEXT: The state saved on the stack does not include the + * volatile FP registers and FPSCR. If this bit is clear, the state does include + * these registers. + */ + +#define EXC_RETURN_STD_CONTEXT (1 << 4) + +/* EXC_RETURN_HANDLER: Return to handler mode. Exception return gets state from + * the main stack. Execution uses MSP after return. + */ + +#define EXC_RETURN_HANDLER 0xfffffff1 + +/* EXC_RETURN_PRIVTHR: Return to privileged thread mode. Exception return gets + * state from the main stack. Execution uses MSP after return. + */ + +#define EXC_RETURN_PRIVTHR 0xfffffff9 + +/* EXC_RETURN_UNPRIVTHR: Return to unprivileged thread mode. Exception return gets + * state from the process stack. Execution uses PSP after return. + */ + +#define EXC_RETURN_UNPRIVTHR 0xfffffffd + +/* In the kernel build is not selected, then all threads run in privileged thread + * mode. + */ + +#ifdef CONFIG_NUTTX_KERNEL +# define EXC_RETURN 0xfffffff9 +#endif + +/************************Th************************************************************ + * Inline Functions + ************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_COMMON_CORTEXM_EXC_RETURN_H */ + diff --git a/nuttx/arch/arm/src/armv7-m/memcpy.S b/nuttx/arch/arm/src/armv7-m/memcpy.S new file mode 100644 index 0000000000..c6d3ff649c --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/memcpy.S @@ -0,0 +1,351 @@ +@ +@ armv7m-optimised memcpy, apparently in the public domain +@ +@ Obtained via a posting on the Stellaris forum: +@ http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/473/t/44360.aspx +@ +@ Posted by rocksoft on Jul 24, 2008 10:19 AM +@ +@ Hi, +@ +@ I recently finished a "memcpy" replacement and thought it might be useful for others... +@ +@ I've put some instructions and the code here: +@ +@ http://www.rock-software.net/downloads/memcpy/ +@ +@ Hope it works for you as well as it did for me. +@ +@ Liam. +@ @ +@ ---------------------------------------------------------------------------- + +.syntax unified + +.thumb + +.cpu cortex-m3 + +@ ---------------------------------------------------------------------------- + + .global memcpy + + +@ ---------------------------------------------------------------------------- +@ Optimised "general" copy routine + +.text + +@ We have 16 possible alignment combinations of src and dst, this jump table directs the copy operation +@ Bits: Src=00, Dst=00 - Long to Long copy +@ Bits: Src=00, Dst=01 - Long to Byte before half word +@ Bits: Src=00, Dst=10 - Long to Half word +@ Bits: Src=00, Dst=11 - Long to Byte before long word +@ Bits: Src=01, Dst=00 - Byte before half word to long +@ Bits: Src=01, Dst=01 - Byte before half word to byte before half word - Same alignment +@ Bits: Src=01, Dst=10 - Byte before half word to half word +@ Bits: Src=01, Dst=11 - Byte before half word to byte before long word +@ Bits: Src=10, Dst=00 - Half word to long word +@ Bits: Src=10, Dst=01 - Half word to byte before half word +@ Bits: Src=10, Dst=10 - Half word to half word - Same Alignment +@ Bits: Src=10, Dst=11 - Half word to byte before long word +@ Bits: Src=11, Dst=00 - Byte before long word to long word +@ Bits: Src=11, Dst=01 - Byte before long word to byte before half word +@ Bits: Src=11, Dst=11 - Byte before long word to half word +@ Bits: Src=11, Dst=11 - Byte before long word to Byte before long word - Same alignment + +MEM_DataCopyTable: + .byte (MEM_DataCopy0 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy1 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy2 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy3 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy4 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy5 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy6 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy7 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy8 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy9 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy10 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy11 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy12 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy13 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy14 - MEM_DataCopyJump) >> 1 + .byte (MEM_DataCopy15 - MEM_DataCopyJump) >> 1 + + .align 2 + +@ ---------------------------------------------------------------------------- + +//#define 10 10 + +MEM_LongCopyTable: + .byte (MEM_LongCopyEnd - MEM_LongCopyJump) >> 1 @ 0 bytes left + .byte 0 @ 4 bytes left + .byte (1 * 10) >> 1 @ 8 bytes left + .byte (2 * 10) >> 1 @ 12 bytes left + .byte (3 * 10) >> 1 @ 16 bytes left + .byte (4 * 10) >> 1 @ 20 bytes left + .byte (5 * 10) >> 1 @ 24 bytes left + .byte (6 * 10) >> 1 @ 28 bytes left + .byte (7 * 10) >> 1 @ 32 bytes left + .byte (8 * 10) >> 1 @ 36 bytes left + + .align 2 + +@ ---------------------------------------------------------------------------- +@ r0 = destination, r1 = source, r2 = length + +.thumb_func + +memcpy: + push {r14} + + @ This allows the inner workings to "assume" a minimum amount of bytes + cmp r2, #4 + blt MEM_DataCopyBytes + + and r14, r0, #3 @ Get destination alignment bits + bfi r14, r1, #2, #2 @ Get source alignment bits + ldr r3, =MEM_DataCopyTable @ Jump table base + tbb [r3, r14] @ Perform jump on src/dst alignment bits +MEM_DataCopyJump: + + .align 4 + +@ ---------------------------------------------------------------------------- +@ Bits: Src=01, Dst=01 - Byte before half word to byte before half word - Same alignment +@ 3 bytes to read for long word aligning + +MEM_DataCopy5: + ldrb r3, [r1], #0x01 + strb r3, [r0], #0x01 + sub r2, r2, #0x01 + +@ ---------------------------------------------------------------------------- +@ Bits: Src=10, Dst=10 - Half word to half word - Same Alignment +@ 2 bytes to read for long word aligning + +MEM_DataCopy10: + ldrb r3, [r1], #0x01 + strb r3, [r0], #0x01 + sub r2, r2, #0x01 + +@ ---------------------------------------------------------------------------- +@ Bits: Src=11, Dst=11 - Byte before long word to Byte before long word - Same alignment +@ 1 bytes to read for long word aligning + +MEM_DataCopy15: + ldrb r3, [r1], #0x01 + strb r3, [r0], #0x01 + sub r2, r2, #0x01 + +@ ---------------------------------------------------------------------------- +@ Bits: Src=00, Dst=00 - Long to Long copy + +MEM_DataCopy0: + @ Save regs + push {r4-r12} + + cmp r2, #0x28 + blt MEM_DataCopy0_2 + +MEM_DataCopy0_1: + ldmia r1!, {r3-r12} + stmia r0!, {r3-r12} + sub r2, r2, #0x28 + cmp r2, #0x28 + bge MEM_DataCopy0_1 + +MEM_DataCopy0_2: + @ Copy remaining long words + ldr r14, =MEM_LongCopyTable + lsr r11, r2, #0x02 + tbb [r14, r11] + +MEM_LongCopyJump: + ldr.w r3, [r1], #0x04 @ 4 bytes remain + str.w r3, [r0], #0x04 + b MEM_LongCopyEnd + ldmia.w r1!, {r3-r4} @ 8 bytes remain + stmia.w r0!, {r3-r4} + b MEM_LongCopyEnd + ldmia.w r1!, {r3-r5} @ 12 bytes remain + stmia.w r0!, {r3-r5} + b MEM_LongCopyEnd + ldmia.w r1!, {r3-r6} @ 16 bytes remain + stmia.w r0!, {r3-r6} + b MEM_LongCopyEnd + ldmia.w r1!, {r3-r7} @ 20 bytes remain + stmia.w r0!, {r3-r7} + b MEM_LongCopyEnd + ldmia.w r1!, {r3-r8} @ 24 bytes remain + stmia.w r0!, {r3-r8} + b MEM_LongCopyEnd + ldmia.w r1!, {r3-r9} @ 28 bytes remain + stmia.w r0!, {r3-r9} + b MEM_LongCopyEnd + ldmia.w r1!, {r3-r10} @ 32 bytes remain + stmia.w r0!, {r3-r10} + b MEM_LongCopyEnd + ldmia.w r1!, {r3-r11} @ 36 bytes remain + stmia.w r0!, {r3-r11} + +MEM_LongCopyEnd: + pop {r4-r12} + and r2, r2, #0x03 @ All the longs have been copied + +@ ---------------------------------------------------------------------------- + +MEM_DataCopyBytes: + @ Deal with up to 3 remaining bytes + cmp r2, #0x00 + it eq + popeq {pc} + ldrb r3, [r1], #0x01 + strb r3, [r0], #0x01 + subs r2, r2, #0x01 + it eq + popeq {pc} + ldrb r3, [r1], #0x01 + strb r3, [r0], #0x01 + subs r2, r2, #0x01 + it eq + popeq {pc} + ldrb r3, [r1], #0x01 + strb r3, [r0], #0x01 + pop {pc} + + .align 4 + +@ ---------------------------------------------------------------------------- +@ Bits: Src=01, Dst=11 - Byte before half word to byte before long word +@ 3 bytes to read for long word aligning the source + +MEM_DataCopy7: + ldrb r3, [r1], #0x01 + strb r3, [r0], #0x01 + sub r2, r2, #0x01 + +@ ---------------------------------------------------------------------------- +@ Bits: Src=10, Dst=00 - Half word to long word +@ 2 bytes to read for long word aligning the source + +MEM_DataCopy8: + ldrb r3, [r1], #0x01 + strb r3, [r0], #0x01 + sub r2, r2, #0x01 + +@ ---------------------------------------------------------------------------- +@ Bits: Src=11, Dst=01 - Byte before long word to byte before half word +@ 1 byte to read for long word aligning the source + +MEM_DataCopy13: + ldrb r3, [r1], #0x01 + strb r3, [r0], #0x01 + sub r2, r2, #0x01 + +@ ---------------------------------------------------------------------------- +@ Bits: Src=00, Dst=10 - Long to Half word + +MEM_DataCopy2: + cmp r2, #0x28 + blt MEM_DataCopy2_1 + + @ Save regs + push {r4-r12} +MEM_DataCopy2_2: + ldmia r1!, {r3-r12} + + strh r3, [r0], #0x02 + + lsr r3, r3, #0x10 + bfi r3, r4, #0x10, #0x10 + lsr r4, r4, #0x10 + bfi r4, r5, #0x10, #0x10 + lsr r5, r5, #0x10 + bfi r5, r6, #0x10, #0x10 + lsr r6, r6, #0x10 + bfi r6, r7, #0x10, #0x10 + lsr r7, r7, #0x10 + bfi r7, r8, #0x10, #0x10 + lsr r8, r8, #0x10 + bfi r8, r9, #0x10, #0x10 + lsr r9, r9, #0x10 + bfi r9, r10, #0x10, #0x10 + lsr r10, r10, #0x10 + bfi r10, r11, #0x10, #0x10 + lsr r11, r11, #0x10 + bfi r11, r12, #0x10, #0x10 + stmia r0!, {r3-r11} + lsr r12, r12, #0x10 + strh r12, [r0], #0x02 + + sub r2, r2, #0x28 + cmp r2, #0x28 + bge MEM_DataCopy2_2 + pop {r4-r12} + +MEM_DataCopy2_1: @ Read longs and write 2 x half words + cmp r2, #4 + blt MEM_DataCopyBytes + ldr r3, [r1], #0x04 + strh r3, [r0], #0x02 + lsr r3, r3, #0x10 + strh r3, [r0], #0x02 + sub r2, r2, #0x04 + b MEM_DataCopy2 + +@ ---------------------------------------------------------------------------- +@ Bits: Src=01, Dst=00 - Byte before half word to long +@ Bits: Src=01, Dst=10 - Byte before half word to half word +@ 3 bytes to read for long word aligning the source + +MEM_DataCopy4: +MEM_DataCopy6: + @ Read B and write B + ldrb r3, [r1], #0x01 + strb r3, [r0], #0x01 + sub r2, r2, #0x01 + +@ ---------------------------------------------------------------------------- +@ Bits: Src=10, Dst=01 - Half word to byte before half word +@ Bits: Src=10, Dst=11 - Half word to byte before long word +@ 2 bytes to read for long word aligning the source + +MEM_DataCopy9: +MEM_DataCopy11: + ldrb r3, [r1], #0x01 + strb r3, [r0], #0x01 + sub r2, r2, #0x01 + +@ ---------------------------------------------------------------------------- +@ Bits: Src=11, Dst=00 - Byte before long word to long word +@ Bits: Src=11, Dst=11 - Byte before long word to half word +@ 1 byte to read for long word aligning the source + +MEM_DataCopy12: +MEM_DataCopy14: + @ Read B and write B + ldrb r3, [r1], #0x01 + strb r3, [r0], #0x01 + sub r2, r2, #0x01 + +@ ---------------------------------------------------------------------------- +@ Bits: Src=00, Dst=01 - Long to Byte before half word +@ Bits: Src=00, Dst=11 - Long to Byte before long word + +MEM_DataCopy1: @ Read longs, write B->H->B +MEM_DataCopy3: + cmp r2, #4 + blt MEM_DataCopyBytes + ldr r3, [r1], #0x04 + strb r3, [r0], #0x01 + lsr r3, r3, #0x08 + strh r3, [r0], #0x02 + lsr r3, r3, #0x10 + strb r3, [r0], #0x01 + sub r2, r2, #0x04 + b MEM_DataCopy3 + +@ ---------------------------------------------------------------------------- + diff --git a/nuttx/arch/arm/src/armv7-m/mpu.h b/nuttx/arch/arm/src/armv7-m/mpu.h new file mode 100644 index 0000000000..8d4cd18292 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/mpu.h @@ -0,0 +1,509 @@ +/************************************************************************************ + * arch/arm/src/armv7-m/mpu.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_COMMON_CORTEXM_MPU_H +#define __ARCH_ARM_SRC_COMMON_CORTEXM_MPU_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +# include +# include +# include + +# include "up_arch.h" +#endif + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* MPU Register Addresses */ + +#define MPU_TYPE 0xe000ed90 /* MPU Type Register */ +#define MPU_CTRL 0xe000ed94 /* MPU Control Register */ +#define MPU_RNR 0xe000ed98 /* MPU Region Number Register */ +#define MPU_RBAR 0xe000ed9c /* MPU Region Base Address Register */ +#define MPU_RASR 0xe000eda0 /* MPU Region Attribute and Size Register */ + +/* MPU Type Register Bit Definitions */ + +#define MPU_TYPE_SEPARATE (1 << 0) /* Bit 0: 0:unified or 1:separate memory maps */ +#define MPU_TYPE_DREGION_SHIFT (8) /* Bits 8-15: Number MPU data regsion */ +#define MPU_TYPE_DREGION_MASK (0xff << MPU_TYPE_DREGION_SHIFT) +#define MPU_TYPE_IREGION_SHIFT (16) /* Bits 16-23: Number MPU instruction regions */ +#define MPU_TYPE_IREGION_MASK (0xff << MPU_TYPE_IREGION_SHIFT) + +/* MPU Control Register Bit Definitions */ + +#define MPU_CTRL_ENABLE (1 << 0) /* Bit 0: Enable the MPU */ +#define MPU_CTRL_HFNMIENA (1 << 1) /* Bit 1: Enable MPU during hard fault, NMI, and FAULTMAS */ +#define MPU_CTRL_PRIVDEFENA (1 << 2) /* Bit 2: Enable privileged access to default memory map */ + +/* MPU Region Number Register Bit Definitions */ + +#define MPU_RNR_MASK (0xff) + +/* MPU Region Base Address Register Bit Definitions */ + +#define MPU_RBAR_REGION_SHIFT (0) /* Bits 0-3: MPU region */ +#define MPU_RBAR_REGION_MASK (15 << MPU_RBAR_REGION_SHIFT) +#define MPU_RBAR_VALID (1 << 4) /* Bit 4: MPU Region Number valid */ +#define MPU_RBAR_ADDR_MASK 0xffffffe0 /* Bits N-31: Region base addrese */ + +/* MPU Region Attributes and Size Register Bit Definitions */ + +#define MPU_RASR_ENABLE (1 << 0) /* Bit 0: Region enable */ +#define MPU_RASR_SIZE_SHIFT (1) /* Bits 1-5: Size of the MPU protection region */ +#define MPU_RASR_SIZE_MASK (31 << MPU_RASR_SIZE_SHIFT) +# define MPU_RASR_SIZE_LOG2(n) ((n-1) << MPU_RASR_SIZE_SHIFT) +#define MPU_RASR_SRD_SHIFT (8) /* Bits 8-15: Subregion disable */ +#define MPU_RASR_SRD_MASK (0xff << MPU_RASR_SRD_SHIFT) +# define MPU_RASR_SRD_0 (0x01 << MPU_RASR_SRD_SHIFT) +# define MPU_RASR_SRD_1 (0x02 << MPU_RASR_SRD_SHIFT) +# define MPU_RASR_SRD_2 (0x04 << MPU_RASR_SRD_SHIFT) +# define MPU_RASR_SRD_3 (0x08 << MPU_RASR_SRD_SHIFT) +# define MPU_RASR_SRD_4 (0x10 << MPU_RASR_SRD_SHIFT) +# define MPU_RASR_SRD_5 (0x20 << MPU_RASR_SRD_SHIFT) +# define MPU_RASR_SRD_6 (0x40 << MPU_RASR_SRD_SHIFT) +# define MPU_RASR_SRD_7 (0x80 << MPU_RASR_SRD_SHIFT) +#define MPU_RASR_ATTR_SHIFT (21) /* Bits 19-21: TEX Address Permisson */ +#define MPU_RASR_ATTR__MASK (7 << MPU_RASR_ATTR_SHIFT) +#define MPU_RASR_S (1 << 18) /* Bit 18: Shareable */ +#define MPU_RASR_C (1 << 17) /* Bit 17: Cacheable */ +#define MPU_RASR_B (1 << 16) /* Bit 16: Bufferable */ +#define MPU_RASR_AP_SHIFT (24) /* Bits 24-26: Access permission */ +#define MPU_RASR_AP_MASK (7 << MPU_RASR_AP_SHIFT) +# define MPU_RASR_AP_NONO (0 << MPU_RASR_AP_SHIFT) /* P:None U:None */ +# define MPU_RASR_AP_RWNO (1 << MPU_RASR_AP_SHIFT) /* P:RW U:None */ +# define MPU_RASR_AP_RWRO (2 << MPU_RASR_AP_SHIFT) /* P:RW U:RO */ +# define MPU_RASR_AP_RWRW (3 << MPU_RASR_AP_SHIFT) /* P:RW U:RW */ +# define MPU_RASR_AP_RONO (5 << MPU_RASR_AP_SHIFT) /* P:RO U:None */ +# define MPU_RASR_AP_RORO (6 << MPU_RASR_AP_SHIFT) /* P:RO U:RO */ +#define MPU_RASR_XN (1 << 28) /* Bit 28: Instruction access disable */ + +/************************************************************************************ + * Global Function Prototypes + ************************************************************************************/ + +#ifndef __ASSEMBLY__ +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: mpu_allocregion + * + * Description: + * Allocate the next region + * + ****************************************************************************/ + +EXTERN unsigned int mpu_allocregion(void); + +/**************************************************************************** + * Name: mpu_log2regionsize + * + * Description: + * Determine the smallest value of l2size (log base 2 size) such that the + * following is true: + * + * size <= (1 << l2size) + * + ****************************************************************************/ + +EXTERN uint8_t mpu_log2regionsize(size_t size); + +/**************************************************************************** + * Name: mpu_subregion + * + * Description: + * Given the size of the (1) memory to be mapped and (2) the log2 size + * of the mapping to use, determine the minimal sub-region set to span + * that memory region. + * + * Assumption: + * l2size has the same properties as the return value from + * mpu_log2regionsize() + * + ****************************************************************************/ + +EXTERN uint32_t mpu_subregion(size_t size, uint8_t l2size); + +/************************************************************************************ + * Inline Functions + ************************************************************************************/ + +/**************************************************************************** + * Name: mpu_showtype + * + * Description: + * Show the characteristics of the MPU + * + ****************************************************************************/ + +static inline void mpu_showtype(void) +{ +#ifdef CONFIG_DEBUG + uint32_t regval = getreg32(MPU_TYPE); + dbg("%s MPU Regions: data=%d instr=%d\n", + (regval & MPU_TYPE_SEPARATE) != 0 ? "Separate" : "Unified", + (regval & MPU_TYPE_DREGION_MASK) >> MPU_TYPE_DREGION_SHIFT, + (regval & MPU_TYPE_IREGION_MASK) >> MPU_TYPE_IREGION_SHIFT); +#endif +} + +/**************************************************************************** + * Name: mpu_control + * + * Description: + * Configure and enable (or disable) the MPU + * + ****************************************************************************/ + +static inline void mpu_control(bool enable, bool hfnmiena, bool privdefena) +{ + uint32_t regval = 0; + + if (enable) + { + regval |= MPU_CTRL_ENABLE; /* Enable the MPU */ + + if (hfnmiena) + { + regval |= MPU_CTRL_HFNMIENA; /* Enable MPU during hard fault, NMI, and FAULTMAS */ + } + + if (privdefena) + { + regval |= MPU_CTRL_PRIVDEFENA; /* Enable privileged access to default memory map */ + } + } + + putreg32(regval, MPU_CTRL); +} + +/**************************************************************************** + * Name: mpu_userflash + * + * Description: + * Configure a region for user program flash + * + ****************************************************************************/ + +static inline void mpu_userflash(uintptr_t base, size_t size) +{ + unsigned int region = mpu_allocregion(); + uint32_t regval; + uint8_t l2size; + uint8_t subregions; + + /* Select the region */ + + putreg32(region, MPU_RNR); + + /* Select the region base address */ + + putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR); + + /* Select the region size and the sub-region map */ + + l2size = mpu_log2regionsize(size); + subregions = mpu_subregion(size, l2size); + + /* The configure the region */ + + regval = MPU_RASR_ENABLE | /* Enable region */ + MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */ + ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */ + MPU_RASR_C | /* Cacheable */ + MPU_RASR_AP_RORO; /* P:RO U:RO */ + putreg32(regval, MPU_RASR); +} + +/**************************************************************************** + * Name: mpu_privflash + * + * Description: + * Configure a region for privileged program flash + * + ****************************************************************************/ + +static inline void mpu_privflash(uintptr_t base, size_t size) +{ + unsigned int region = mpu_allocregion(); + uint32_t regval; + uint8_t l2size; + uint8_t subregions; + + /* Select the region */ + + putreg32(mpu_allocregion(), MPU_RNR); + + /* Select the region base address */ + + putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR); + + /* Select the region size and the sub-region map */ + + l2size = mpu_log2regionsize(size); + subregions = mpu_subregion(size, l2size); + + /* The configure the region */ + + regval = MPU_RASR_ENABLE | /* Enable region */ + MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */ + ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */ + MPU_RASR_C | /* Cacheable */ + MPU_RASR_AP_RONO; /* P:RO U:None */ + putreg32(regval, MPU_RASR); +} + +/**************************************************************************** + * Name: mpu_userintsram + * + * Description: + * Configure a region as user internal SRAM + * + ****************************************************************************/ + +static inline void mpu_userintsram(uintptr_t base, size_t size) +{ + unsigned int region = mpu_allocregion(); + uint32_t regval; + uint8_t l2size; + uint8_t subregions; + + /* Select the region */ + + putreg32(region, MPU_RNR); + + /* Select the region base address */ + + putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR); + + /* Select the region size and the sub-region map */ + + l2size = mpu_log2regionsize(size); + subregions = mpu_subregion(size, l2size); + + /* The configure the region */ + + regval = MPU_RASR_ENABLE | /* Enable region */ + MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */ + ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */ + MPU_RASR_S | /* Shareable */ + MPU_RASR_C | /* Cacheable */ + MPU_RASR_AP_RWRW; /* P:RW U:RW */ + putreg32(regval, MPU_RASR); +} + +/**************************************************************************** + * Name: mpu_privintsram + * + * Description: + * Configure a region as privileged internal SRAM + * + ****************************************************************************/ + +static inline void mpu_privintsram(uintptr_t base, size_t size) +{ + unsigned int region = mpu_allocregion(); + uint32_t regval; + uint8_t l2size; + uint8_t subregions; + + /* Select the region */ + + putreg32(region, MPU_RNR); + + /* Select the region base address */ + + putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR); + + /* Select the region size and the sub-region map */ + + l2size = mpu_log2regionsize(size); + subregions = mpu_subregion(size, l2size); + + /* The configure the region */ + + regval = MPU_RASR_ENABLE | /* Enable region */ + MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */ + ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */ + MPU_RASR_S | /* Shareable */ + MPU_RASR_C | /* Cacheable */ + MPU_RASR_AP_RWNO; /* P:RW U:None */ + putreg32(regval, MPU_RASR); +} + +/**************************************************************************** + * Name: mpu_userextsram + * + * Description: + * Configure a region as user external SRAM + * + ****************************************************************************/ + +static inline void mpu_userextsram(uintptr_t base, size_t size) +{ + unsigned int region = mpu_allocregion(); + uint32_t regval; + uint8_t l2size; + uint8_t subregions; + + /* Select the region */ + + putreg32(region, MPU_RNR); + + /* Select the region base address */ + + putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR); + + /* Select the region size and the sub-region map */ + + l2size = mpu_log2regionsize(size); + subregions = mpu_subregion(size, l2size); + + /* The configure the region */ + + regval = MPU_RASR_ENABLE | /* Enable region */ + MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */ + ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */ + MPU_RASR_S | /* Shareable */ + MPU_RASR_C | /* Cacheable */ + MPU_RASR_B | /* Bufferable */ + MPU_RASR_AP_RWRW; /* P:RW U:RW */ + putreg32(regval, MPU_RASR); +} + +/**************************************************************************** + * Name: mpu_privextsram + * + * Description: + * Configure a region as privileged external SRAM + * + ****************************************************************************/ + +static inline void mpu_privextsram(uintptr_t base, size_t size) +{ + unsigned int region = mpu_allocregion(); + uint32_t regval; + uint8_t l2size; + uint8_t subregions; + + /* Select the region */ + + putreg32(region, MPU_RNR); + + /* Select the region base address */ + + putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR); + + /* Select the region size and the sub-region map */ + + l2size = mpu_log2regionsize(size); + subregions = mpu_subregion(size, l2size); + + /* The configure the region */ + + regval = MPU_RASR_ENABLE | /* Enable region */ + MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */ + ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */ + MPU_RASR_S | /* Shareable */ + MPU_RASR_C | /* Cacheable */ + MPU_RASR_B | /* Bufferable */ + MPU_RASR_AP_RWNO; /* P:RW U:None */ + putreg32(regval, MPU_RASR); +} + +/**************************************************************************** + * Name: mpu_peripheral + * + * Description: + * Configure a region as privileged periperal address space + * + ****************************************************************************/ + +static inline void mpu_peripheral(uintptr_t base, size_t size) +{ + unsigned int region = mpu_allocregion(); + uint32_t regval; + uint8_t l2size; + uint8_t subregions; + + /* Select the region */ + + putreg32(region, MPU_RNR); + + /* Select the region base address */ + + putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR); + + /* Select the region size and the sub-region map */ + + l2size = mpu_log2regionsize(size); + subregions = mpu_subregion(size, l2size); + + /* The configure the region */ + + regval = MPU_RASR_ENABLE | /* Enable region */ + MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */ + ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */ + MPU_RASR_S | /* Shareable */ + MPU_RASR_B | /* Bufferable */ + MPU_RASR_AP_RWNO | /* P:RW U:None */ + MPU_RASR_XN | /* Instruction access disable */ + + putreg32(regval, MPU_RASR); +} + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_COMMON_CORTEXM_MPU_H */ + diff --git a/nuttx/arch/arm/src/armv7-m/nvic.h b/nuttx/arch/arm/src/armv7-m/nvic.h new file mode 100644 index 0000000000..1d30c5f7c2 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/nvic.h @@ -0,0 +1,531 @@ +/******************************************************************************************** + * arch/arm/src/armv7-m/nvic.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_COMMON_ARMV7_M_NVIC_H +#define __ARCH_ARM_SRC_COMMON_ARMV7_M_NVIC_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include + +/******************************************************************************************** + * Pre-processor Definitions + ********************************************************************************************/ + +/* NVIC base address ************************************************************************/ + +#define ARMV7M_NVIC_BASE 0xe000e000 + +/* NVIC register offsets ********************************************************************/ + +#define NVIC_ICTR_OFFSET 0x0004 /* Interrupt controller type register */ +#define NVIC_SYSTICK_CTRL_OFFSET 0x0010 /* SysTick control and status register */ +#define NVIC_SYSTICK_RELOAD_OFFSET 0x0014 /* SysTick reload value register */ +#define NVIC_SYSTICK_CURRENT_OFFSET 0x0018 /* SysTick current value register */ +#define NVIC_SYSTICK_CALIB_OFFSET 0x001c /* SysTick calibration value register */ + +#define NVIC_IRQ_ENABLE_OFFSET(n) (0x0100 + 4*((n) >> 5)) +#define NVIC_IRQ0_31_ENABLE_OFFSET 0x0100 /* IRQ 0-31 set enable register */ +#define NVIC_IRQ32_63_ENABLE_OFFSET 0x0104 /* IRQ 32-63 set enable register */ +#define NVIC_IRQ64_95_ENABLE_OFFSET 0x0108 /* IRQ 64-95 set enable register */ +#define NVIC_IRQ96_127_ENABLE_OFFSET 0x010c /* IRQ 96-127 set enable register */ +#define NVIC_IRQ128_159_ENABLE_OFFSET 0x0110 /* IRQ 128-159 set enable register */ +#define NVIC_IRQ160_191_ENABLE_OFFSET 0x0114 /* IRQ 160-191 set enable register */ +#define NVIC_IRQ192_223_ENABLE_OFFSET 0x0118 /* IRQ 192-223 set enable register */ +#define NVIC_IRQ224_239_ENABLE_OFFSET 0x011c /* IRQ 224-239 set enable register */ + +#define NVIC_IRQ_CLEAR_OFFSET(n) (0x0180 + 4*((n) >> 5)) +#define NVIC_IRQ0_31_CLEAR_OFFSET 0x0180 /* IRQ 0-31 clear enable register */ +#define NVIC_IRQ32_63_CLEAR_OFFSET 0x0184 /* IRQ 32-63 clear enable register */ +#define NVIC_IRQ64_95_CLEAR_OFFSET 0x0188 /* IRQ 64-95 clear enable register */ +#define NVIC_IRQ96_127_CLEAR_OFFSET 0x018c /* IRQ 96-127 clear enable register */ +#define NVIC_IRQ128_159_CLEAR_OFFSET 0x0190 /* IRQ 128-159 clear enable register */ +#define NVIC_IRQ160_191_CLEAR_OFFSET 0x0194 /* IRQ 160-191 clear enable register */ +#define NVIC_IRQ192_223_CLEAR_OFFSET 0x0198 /* IRQ 192-223 clear enable register */ +#define NVIC_IRQ224_239_CLEAR_OFFSET 0x019c /* IRQ 224-2391 clear enable register */ + +#define NVIC_IRQ_PEND_OFFSET(n) (0x0200 + 4*((n) >> 5)) +#define NVIC_IRQ0_31_PEND_OFFSET 0x0200 /* IRQ 0-31 set pending register */ +#define NVIC_IRQ32_63_PEND_OFFSET 0x0204 /* IRQ 32-63 set pending register */ +#define NVIC_IRQ64_95_PEND_OFFSET 0x0208 /* IRQ 64-95 set pending register */ +#define NVIC_IRQ96_127_PEND_OFFSET 0x020c /* IRQ 96-127 set pending register */ +#define NVIC_IRQ128_159_PEND_OFFSET 0x0210 /* IRQ 128-159 set pending register */ +#define NVIC_IRQ160_191_PEND_OFFSET 0x0214 /* IRQ 160-191 set pending register */ +#define NVIC_IRQ192_223_PEND_OFFSET 0x0218 /* IRQ 192-2231 set pending register */ +#define NVIC_IRQ224_239_PEND_OFFSET 0x021c /* IRQ 224-2391 set pending register */ + +#define NVIC_IRQ_CLRPEND_OFFSET(n) (0x0280 + 4*((n) >> 5)) +#define NVIC_IRQ0_31_CLRPEND_OFFSET 0x0280 /* IRQ 0-31 clear pending register */ +#define NVIC_IRQ32_63_CLRPEND_OFFSET 0x0284 /* IRQ 32-63 clear pending register */ +#define NVIC_IRQ64_95_CLRPEND_OFFSET 0x0288 /* IRQ 64-95 clear pending register */ +#define NVIC_IRQ96_127_CLRPEND_OFFSET 0x028c /* IRQ 96-127 clear pending register */ +#define NVIC_IRQ128_159_CLRPEND_OFFSET 0x0290 /* IRQ 128-159 clear pending register */ +#define NVIC_IRQ160_191_CLRPEND_OFFSET 0x0294 /* IRQ 160-191 clear pending register */ +#define NVIC_IRQ192_223_CLRPEND_OFFSET 0x0298 /* IRQ 192-223 clear pending register */ +#define NVIC_IRQ224_239_CLRPEND_OFFSET 0x029c /* IRQ 224-239 clear pending register */ + +#define NVIC_IRQ_ACTIVE_OFFSET(n) (0x0300 + 4*((n) >> 5)) +#define NVIC_IRQ0_31_ACTIVE_OFFSET 0x0300 /* IRQ 0-31 active bit register */ +#define NVIC_IRQ32_63_ACTIVE_OFFSET 0x0304 /* IRQ 32-63 active bit register */ +#define NVIC_IRQ64_95_ACTIVE_OFFSET 0x0308 /* IRQ 64-95 active bit register */ +#define NVIC_IRQ96_127_ACTIVE_OFFSET 0x030c /* IRQ 96-127 active bit register */ +#define NVIC_IRQ128_159_ACTIVE_OFFSET 0x0310 /* IRQ 128-159 active bit register */ +#define NVIC_IRQ160_191_ACTIVE_OFFSET 0x0314 /* IRQ 160-191 active bit register */ +#define NVIC_IRQ192_223_ACTIVE_OFFSET 0x0318 /* IRQ 192-223 active bit register */ +#define NVIC_IRQ224_239_ACTIVE_OFFSET 0x031c /* IRQ 224-239 active bit register */ + +#define NVIC_IRQ_PRIORITY_OFFSET(n) (0x0400 + 4*((n) >> 2)) +#define NVIC_IRQ0_3_PRIORITY_OFFSET 0x0400 /* IRQ 0-3 priority register */ +#define NVIC_IRQ4_7_PRIORITY_OFFSET 0x0404 /* IRQ 4-7 priority register */ +#define NVIC_IRQ8_11_PRIORITY_OFFSET 0x0408 /* IRQ 8-11 priority register */ +#define NVIC_IRQ12_15_PRIORITY_OFFSET 0x040c /* IRQ 12-15 priority register */ +#define NVIC_IRQ16_19_PRIORITY_OFFSET 0x0410 /* IRQ 16-19 priority register */ +#define NVIC_IRQ20_23_PRIORITY_OFFSET 0x0414 /* IRQ 20-23 priority register */ +#define NVIC_IRQ24_27_PRIORITY_OFFSET 0x0418 /* IRQ 24-29 priority register */ +#define NVIC_IRQ28_31_PRIORITY_OFFSET 0x041c /* IRQ 28-31 priority register */ +#define NVIC_IRQ32_35_PRIORITY_OFFSET 0x0420 /* IRQ 32-35 priority register */ +#define NVIC_IRQ36_39_PRIORITY_OFFSET 0x0424 /* IRQ 36-39 priority register */ +#define NVIC_IRQ40_43_PRIORITY_OFFSET 0x0428 /* IRQ 40-43 priority register */ +#define NVIC_IRQ44_47_PRIORITY_OFFSET 0x042c /* IRQ 44-47 priority register */ +#define NVIC_IRQ48_51_PRIORITY_OFFSET 0x0430 /* IRQ 48-51 priority register */ +#define NVIC_IRQ52_55_PRIORITY_OFFSET 0x0434 /* IRQ 52-55 priority register */ +#define NVIC_IRQ56_59_PRIORITY_OFFSET 0x0438 /* IRQ 56-59 priority register */ +#define NVIC_IRQ60_63_PRIORITY_OFFSET 0x043c /* IRQ 60-63 priority register */ +#define NVIC_IRQ64_67_PRIORITY_OFFSET 0x0440 /* IRQ 64-67 priority register */ +#define NVIC_IRQ68_71_PRIORITY_OFFSET 0x0444 /* IRQ 68-71 priority register */ +#define NVIC_IRQ72_75_PRIORITY_OFFSET 0x0448 /* IRQ 72-75 priority register */ +#define NVIC_IRQ76_79_PRIORITY_OFFSET 0x044c /* IRQ 76-79 priority register */ +#define NVIC_IRQ80_83_PRIORITY_OFFSET 0x0450 /* IRQ 80-83 priority register */ +#define NVIC_IRQ84_87_PRIORITY_OFFSET 0x0454 /* IRQ 84-87 priority register */ +#define NVIC_IRQ88_91_PRIORITY_OFFSET 0x0458 /* IRQ 88-91 priority register */ +#define NVIC_IRQ92_95_PRIORITY_OFFSET 0x045c /* IRQ 92-95 priority register */ +#define NVIC_IRQ96_99_PRIORITY_OFFSET 0x0460 /* IRQ 96-99 priority register */ +#define NVIC_IRQ100_103_PRIORITY_OFFSET 0x0464 /* IRQ 100-103 priority register */ +#define NVIC_IRQ104_107_PRIORITY_OFFSET 0x0468 /* IRQ 104-107 priority register */ +#define NVIC_IRQ108_111_PRIORITY_OFFSET 0x046c /* IRQ 108-111 priority register */ +#define NVIC_IRQ112_115_PRIORITY_OFFSET 0x0470 /* IRQ 112-115 priority register */ +#define NVIC_IRQ116_119_PRIORITY_OFFSET 0x0474 /* IRQ 116-119 priority register */ +#define NVIC_IRQ120_123_PRIORITY_OFFSET 0x0478 /* IRQ 120-123 priority register */ +#define NVIC_IRQ124_127_PRIORITY_OFFSET 0x047c /* IRQ 124-127 priority register */ +#define NVIC_IRQ128_131_PRIORITY_OFFSET 0x0480 /* IRQ 128-131 priority register */ +#define NVIC_IRQ132_135_PRIORITY_OFFSET 0x0484 /* IRQ 132-135 priority register */ +#define NVIC_IRQ136_139_PRIORITY_OFFSET 0x0488 /* IRQ 136-139 priority register */ +#define NVIC_IRQ140_143_PRIORITY_OFFSET 0x048c /* IRQ 140-143 priority register */ +#define NVIC_IRQ144_147_PRIORITY_OFFSET 0x0490 /* IRQ 144-147 priority register */ +#define NVIC_IRQ148_151_PRIORITY_OFFSET 0x0494 /* IRQ 148-151 priority register */ +#define NVIC_IRQ152_155_PRIORITY_OFFSET 0x0498 /* IRQ 152-155 priority register */ +#define NVIC_IRQ156_159_PRIORITY_OFFSET 0x049c /* IRQ 156-159 priority register */ +#define NVIC_IRQ160_163_PRIORITY_OFFSET 0x04a0 /* IRQ 160-163 priority register */ +#define NVIC_IRQ164_167_PRIORITY_OFFSET 0x04a4 /* IRQ 164-167 priority register */ +#define NVIC_IRQ168_171_PRIORITY_OFFSET 0x04a8 /* IRQ 168-171 priority register */ +#define NVIC_IRQ172_175_PRIORITY_OFFSET 0x04ac /* IRQ 172-175 priority register */ +#define NVIC_IRQ176_179_PRIORITY_OFFSET 0x04b0 /* IRQ 176-179 priority register */ +#define NVIC_IRQ180_183_PRIORITY_OFFSET 0x04b4 /* IRQ 180-183 priority register */ +#define NVIC_IRQ184_187_PRIORITY_OFFSET 0x04b8 /* IRQ 184-187 priority register */ +#define NVIC_IRQ188_191_PRIORITY_OFFSET 0x04bc /* IRQ 188-191 priority register */ +#define NVIC_IRQ192_195_PRIORITY_OFFSET 0x04c0 /* IRQ 192-195 priority register */ +#define NVIC_IRQ196_199_PRIORITY_OFFSET 0x04c4 /* IRQ 196-199 priority register */ +#define NVIC_IRQ200_203_PRIORITY_OFFSET 0x04c8 /* IRQ 200-203 priority register */ +#define NVIC_IRQ204_207_PRIORITY_OFFSET 0x04cc /* IRQ 204-207 priority register */ +#define NVIC_IRQ208_211_PRIORITY_OFFSET 0x04d0 /* IRQ 208-211 priority register */ +#define NVIC_IRQ212_215_PRIORITY_OFFSET 0x04d4 /* IRQ 212-215 priority register */ +#define NVIC_IRQ216_219_PRIORITY_OFFSET 0x04d8 /* IRQ 216-219 priority register */ +#define NVIC_IRQ220_223_PRIORITY_OFFSET 0x04dc /* IRQ 220-223 priority register */ +#define NVIC_IRQ224_227_PRIORITY_OFFSET 0x04e0 /* IRQ 224-227 priority register */ +#define NVIC_IRQ228_231_PRIORITY_OFFSET 0x04e4 /* IRQ 228-231 priority register */ +#define NVIC_IRQ232_235_PRIORITY_OFFSET 0x04e8 /* IRQ 232-235 priority register */ +#define NVIC_IRQ236_239_PRIORITY_OFFSET 0x04ec /* IRQ 236-239 priority register */ + +/* System Control Block (SCB) */ + +#define NVIC_CPUID_BASE_OFFSET 0x0d00 /* CPUID base register */ +#define NVIC_INTCTRL_OFFSET 0x0d04 /* Interrupt control state register */ +#define NVIC_VECTAB_OFFSET 0x0d08 /* Vector table offset register */ +#define NVIC_AIRC_OFFSET 0x0d0c /* Application interrupt/reset contol registr */ +#define NVIC_SYSCON_OFFSET 0x0d10 /* System control register */ +#define NVIC_CFGCON_OFFSET 0x0d14 /* Configuration control register */ +#define NVIC_SYSH_PRIORITY_OFFSET(n) (0x0d14 + 4*((n) >> 2)) +#define NVIC_SYSH4_7_PRIORITY_OFFSET 0x0d18 /* System handlers 4-7 priority register */ +#define NVIC_SYSH8_11_PRIORITY_OFFSET 0x0d1c /* System handler 8-11 priority register */ +#define NVIC_SYSH12_15_PRIORITY_OFFSET 0x0d20 /* System handler 12-15 priority register */ +#define NVIC_SYSHCON_OFFSET 0x0d24 /* System handler control and state register */ +#define NVIC_CFAULTS_OFFSET 0x0d28 /* Configurable fault status register */ +#define NVIC_HFAULTS_OFFSET 0x0d2c /* Hard fault status register */ +#define NVIC_DFAULTS_OFFSET 0x0d30 /* Debug fault status register */ +#define NVIC_MEMMANAGE_ADDR_OFFSET 0x0d34 /* Mem manage address register */ +#define NVIC_BFAULT_ADDR_OFFSET 0x0d38 /* Bus fault address register */ +#define NVIC_AFAULTS_OFFSET 0x0d3c /* Auxiliary fault status register */ +#define NVIC_PFR0_OFFSET 0x0d40 /* Processor feature register 0 */ +#define NVIC_PFR1_OFFSET 0x0d44 /* Processor feature register 1 */ +#define NVIC_DFR0_OFFSET 0x0d48 /* Debug feature register 0 */ +#define NVIC_AFR0_OFFSET 0x0d4c /* Auxiliary feature register 0 */ +#define NVIC_MMFR0_OFFSET 0x0d50 /* Memory model feature register 0 */ +#define NVIC_MMFR1_OFFSET 0x0d54 /* Memory model feature register 1 */ +#define NVIC_MMFR2_OFFSET 0x0d58 /* Memory model feature register 2 */ +#define NVIC_MMFR3_OFFSET 0x0d5c /* Memory model feature register 3 */ +#define NVIC_ISAR0_OFFSET 0x0d60 /* ISA feature register 0 */ +#define NVIC_ISAR1_OFFSET 0x0d64 /* ISA feature register 1 */ +#define NVIC_ISAR2_OFFSET 0x0d68 /* ISA feature register 2 */ +#define NVIC_ISAR3_OFFSET 0x0d6c /* ISA feature register 3 */ +#define NVIC_ISAR4_OFFSET 0x0d70 /* ISA feature register 4 */ +#define NVIC_CPACR_OFFSET 0x0d88 /* Coprocessor Access Control Register */ +#define NVIC_DHCSR_OFFSET 0x0df0 /* Debug Halting Control and Status Register */ +#define NVIC_DCRSR_OFFSET 0x0df4 /* Debug Core Register Selector Register */ +#define NVIC_DCRDR_OFFSET 0x0df8 /* Debug Core Register Data Register */ +#define NVIC_DEMCR_OFFSET 0x0dfc /* Debug Exception and Monitor Control Register */ +#define NVIC_STIR_OFFSET 0x0f00 /* Software trigger interrupt register */ +#define NVIC_FPCCR_OFFSET 0x0f34 /* Floating-point Context Control Register */ +#define NVIC_FPCAR_OFFSET 0x0f38 /* Floating-point Context Address Register */ +#define NVIC_FPDSCR_OFFSET 0x0f3c /* Floating-point Default Status Control Register */ +#define NVIC_MVFR0_OFFSET 0x0f40 /* Media and VFP Feature Register 0 */ +#define NVIC_MVFR1_OFFSET 0x0f44 /* Media and VFP Feature Register 1 */ +#define NVIC_PID4_OFFSET 0x0fd0 /* Peripheral identification register (PID4) */ +#define NVIC_PID5_OFFSET 0x0fd4 /* Peripheral identification register (PID5) */ +#define NVIC_PID6_OFFSET 0x0fd8 /* Peripheral identification register (PID6) */ +#define NVIC_PID7_OFFSET 0x0fdc /* Peripheral identification register (PID7) */ +#define NVIC_PID0_OFFSET 0x0fe0 /* Peripheral identification register bits 7:0 (PID0) */ +#define NVIC_PID1_OFFSET 0x0fe4 /* Peripheral identification register bits 15:8 (PID1) */ +#define NVIC_PID2_OFFSET 0x0fe8 /* Peripheral identification register bits 23:16 (PID2) */ +#define NVIC_PID3_OFFSET 0x0fec /* Peripheral identification register bits 23:16 (PID3) */ +#define NVIC_CID0_OFFSET 0x0ff0 /* Component identification register bits 7:0 (CID0) */ +#define NVIC_CID1_OFFSET 0x0ff4 /* Component identification register bits 15:8 (CID0) */ +#define NVIC_CID2_OFFSET 0x0ff8 /* Component identification register bits 23:16 (CID0) */ +#define NVIC_CID3_OFFSET 0x0ffc /* Component identification register bits 23:16 (CID0) */ + +/* NVIC register addresses ******************************************************************/ + +#define NVIC_ICTR (ARMV7M_NVIC_BASE + NVIC_ICTR_OFFSET) +#define NVIC_SYSTICK_CTRL (ARMV7M_NVIC_BASE + NVIC_SYSTICK_CTRL_OFFSET) +#define NVIC_SYSTICK_RELOAD (ARMV7M_NVIC_BASE + NVIC_SYSTICK_RELOAD_OFFSET) +#define NVIC_SYSTICK_CURRENT (ARMV7M_NVIC_BASE + NVIC_SYSTICK_CURRENT_OFFSET) +#define NVIC_SYSTICK_CALIB (ARMV7M_NVIC_BASE + NVIC_SYSTICK_CALIB_OFFSET) + +#define NVIC_IRQ_ENABLE(n) (ARMV7M_NVIC_BASE + NVIC_IRQ_ENABLE_OFFSET(n)) +#define NVIC_IRQ0_31_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ0_31_ENABLE_OFFSET) +#define NVIC_IRQ32_63_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ32_63_ENABLE_OFFSET) +#define NVIC_IRQ64_95_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ64_95_ENABLE_OFFSET) +#define NVIC_IRQ96_127_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ96_127_ENABLE_OFFSET) +#define NVIC_IRQ128_159_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ128_159_ENABLE_OFFSET) +#define NVIC_IRQ160_191_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ160_191_ENABLE_OFFSET) +#define NVIC_IRQ192_223_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ192_223_ENABLE_OFFSET) +#define NVIC_IRQ224_239_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ224_239_ENABLE_OFFSET) + +#define NVIC_IRQ_CLEAR(n) (ARMV7M_NVIC_BASE + NVIC_IRQ_CLEAR_OFFSET(n)) +#define NVIC_IRQ0_31_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ0_31_CLEAR_OFFSET) +#define NVIC_IRQ32_63_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ32_63_CLEAR_OFFSET) +#define NVIC_IRQ64_95_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ64_95_CLEAR_OFFSET) +#define NVIC_IRQ96_127_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ96_127_CLEAR_OFFSET) +#define NVIC_IRQ128_159_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ128_159_CLEAR_OFFSET) +#define NVIC_IRQ160_191_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ160_191_CLEAR_OFFSET) +#define NVIC_IRQ192_223_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ192_223_CLEAR_OFFSET) +#define NVIC_IRQ224_239_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ224_239_CLEAR_OFFSET) + +#define NVIC_IRQ_PEND(n) (ARMV7M_NVIC_BASE + NVIC_IRQ_PEND_OFFSET(n)) +#define NVIC_IRQ0_31_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ0_31_PEND_OFFSET) +#define NVIC_IRQ32_63_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ32_63_PEND_OFFSET) +#define NVIC_IRQ64_95_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ64_95_PEND_OFFSET) +#define NVIC_IRQ96_127_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ96_127_PEND_OFFSET) +#define NVIC_IRQ128_159_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ128_159_PEND_OFFSET) +#define NVIC_IRQ160_191_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ160_191_PEND_OFFSET) +#define NVIC_IRQ192_223_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ192_223_PEND_OFFSET) +#define NVIC_IRQ224_239_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ224_239_PEND_OFFSET) + +#define NVIC_IRQ_CLRPEND(n) (ARMV7M_NVIC_BASE + NVIC_IRQ_CLRPEND_OFFSET(n)) +#define NVIC_IRQ0_31_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ0_31_CLRPEND_OFFSET) +#define NVIC_IRQ32_63_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ32_63_CLRPEND_OFFSET) +#define NVIC_IRQ64_95_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ64_95_CLRPEND_OFFSET) +#define NVIC_IRQ96_127_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ96_127_CLRPEND_OFFSET) +#define NVIC_IRQ128_159_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ128_159_CLRPEND_OFFSET) +#define NVIC_IRQ160_191_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ160_191_CLRPEND_OFFSET) +#define NVIC_IRQ192_223_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ192_223_CLRPEND_OFFSET) +#define NVIC_IRQ224_239_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ224_239_CLRPEND_OFFSET) + +#define NVIC_IRQ_ACTIVE(n) (ARMV7M_NVIC_BASE + NVIC_IRQ_ACTIVE_OFFSET(n)) +#define NVIC_IRQ0_31_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ0_31_ACTIVE_OFFSET) +#define NVIC_IRQ32_63_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ32_63_ACTIVE_OFFSET) +#define NVIC_IRQ64_95_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ64_95_ACTIVE_OFFSET) +#define NVIC_IRQ96_127_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ96_127_ACTIVE_OFFSET) +#define NVIC_IRQ128_159_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ128_159_ACTIVE_OFFSET) +#define NVIC_IRQ160_191_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ160_191_ACTIVE_OFFSET) +#define NVIC_IRQ192_223_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ192_223_ACTIVE_OFFSET) +#define NVIC_IRQ224_239_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ224_239_ACTIVE_OFFSET) + +#define NVIC_IRQ_PRIORITY(n) (ARMV7M_NVIC_BASE + NVIC_IRQ_PRIORITY_OFFSET(n)) +#define NVIC_IRQ0_3_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ0_3_PRIORITY_OFFSET) +#define NVIC_IRQ4_7_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ4_7_PRIORITY_OFFSET) +#define NVIC_IRQ8_11_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ8_11_PRIORITY_OFFSET) +#define NVIC_IRQ12_15_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ12_15_PRIORITY_OFFSET) +#define NVIC_IRQ16_19_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ16_19_PRIORITY_OFFSET) +#define NVIC_IRQ20_23_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ20_23_PRIORITY_OFFSET) +#define NVIC_IRQ24_27_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ24_27_PRIORITY_OFFSET) +#define NVIC_IRQ28_31_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ28_31_PRIORITY_OFFSET) +#define NVIC_IRQ32_35_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ32_35_PRIORITY_OFFSET) +#define NVIC_IRQ36_39_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ36_39_PRIORITY_OFFSET) +#define NVIC_IRQ40_43_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ40_43_PRIORITY_OFFSET) +#define NVIC_IRQ44_47_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ44_47_PRIORITY_OFFSET) +#define NVIC_IRQ48_51_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ48_51_PRIORITY_OFFSET) +#define NVIC_IRQ52_55_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ52_55_PRIORITY_OFFSET) +#define NVIC_IRQ56_59_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ56_59_PRIORITY_OFFSET) +#define NVIC_IRQ60_63_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ60_63_PRIORITY_OFFSET) +#define NVIC_IRQ64_67_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ64_67_PRIORITY_OFFSET) +#define NVIC_IRQ68_71_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ68_71_PRIORITY_OFFSET) +#define NVIC_IRQ72_75_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ72_75_PRIORITY_OFFSET) +#define NVIC_IRQ76_79_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ76_79_PRIORITY_OFFSET) +#define NVIC_IRQ80_83_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ80_83_PRIORITY_OFFSET) +#define NVIC_IRQ84_87_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ84_87_PRIORITY_OFFSET) +#define NVIC_IRQ88_91_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ88_91_PRIORITY_OFFSET) +#define NVIC_IRQ92_95_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ92_95_PRIORITY_OFFSET) +#define NVIC_IRQ96_99_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ96_99_PRIORITY_OFFSET) +#define NVIC_IRQ100_103_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ100_103_PRIORITY_OFFSET) +#define NVIC_IRQ104_107_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ104_107_PRIORITY_OFFSET) +#define NVIC_IRQ108_111_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ108_111_PRIORITY_OFFSET) +#define NVIC_IRQ112_115_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ112_115_PRIORITY_OFFSET) +#define NVIC_IRQ116_119_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ116_119_PRIORITY_OFFSET) +#define NVIC_IRQ120_123_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ120_123_PRIORITY_OFFSET) +#define NVIC_IRQ124_127_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ124_127_PRIORITY_OFFSET) +#define NVIC_IRQ128_131_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ128_131_PRIORITY_OFFSET) +#define NVIC_IRQ132_135_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ132_135_PRIORITY_OFFSET) +#define NVIC_IRQ136_139_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ136_139_PRIORITY_OFFSET) +#define NVIC_IRQ140_143_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ140_143_PRIORITY_OFFSET) +#define NVIC_IRQ144_147_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ144_147_PRIORITY_OFFSET) +#define NVIC_IRQ148_151_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ148_151_PRIORITY_OFFSET) +#define NVIC_IRQ152_155_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ152_155_PRIORITY_OFFSET) +#define NVIC_IRQ156_159_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ156_159_PRIORITY_OFFSET) +#define NVIC_IRQ160_163_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ160_163_PRIORITY_OFFSET) +#define NVIC_IRQ164_167_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ164_167_PRIORITY_OFFSET) +#define NVIC_IRQ168_171_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ168_171_PRIORITY_OFFSET) +#define NVIC_IRQ172_175_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ172_175_PRIORITY_OFFSET) +#define NVIC_IRQ176_179_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ176_179_PRIORITY_OFFSET) +#define NVIC_IRQ180_183_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ180_183_PRIORITY_OFFSET) +#define NVIC_IRQ184_187_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ184_187_PRIORITY_OFFSET) +#define NVIC_IRQ188_191_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ188_191_PRIORITY_OFFSET) +#define NVIC_IRQ192_195_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ192_195_PRIORITY_OFFSET) +#define NVIC_IRQ196_199_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ196_199_PRIORITY_OFFSET) +#define NVIC_IRQ200_203_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ200_203_PRIORITY_OFFSET) +#define NVIC_IRQ204_207_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ204_207_PRIORITY_OFFSET) +#define NVIC_IRQ208_211_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ208_211_PRIORITY_OFFSET) +#define NVIC_IRQ212_215_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ212_215_PRIORITY_OFFSET) +#define NVIC_IRQ216_219_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ216_219_PRIORITY_OFFSET) +#define NVIC_IRQ220_223_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ220_223_PRIORITY_OFFSET) +#define NVIC_IRQ224_227_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ224_227_PRIORITY_OFFSET) +#define NVIC_IRQ228_231_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ228_231_PRIORITY_OFFSET) +#define NVIC_IRQ232_235_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ232_235_PRIORITY_OFFSET) + +#define NVIC_CPUID_BASE (ARMV7M_NVIC_BASE + NVIC_CPUID_BASE_OFFSET) +#define NVIC_INTCTRL (ARMV7M_NVIC_BASE + NVIC_INTCTRL_OFFSET) +#define NVIC_VECTAB (ARMV7M_NVIC_BASE + NVIC_VECTAB_OFFSET) +#define NVIC_AIRC (ARMV7M_NVIC_BASE + NVIC_AIRC_OFFSET) +#define NVIC_SYSCON (ARMV7M_NVIC_BASE + NVIC_SYSCON_OFFSET) +#define NVIC_CFGCON (ARMV7M_NVIC_BASE + NVIC_CFGCON_OFFSET) +#define NVIC_SYSH_PRIORITY(n) (ARMV7M_NVIC_BASE + NVIC_SYSH_PRIORITY_OFFSET(n)) +#define NVIC_SYSH4_7_PRIORITY (ARMV7M_NVIC_BASE + NVIC_SYSH4_7_PRIORITY_OFFSET) +#define NVIC_SYSH8_11_PRIORITY (ARMV7M_NVIC_BASE + NVIC_SYSH8_11_PRIORITY_OFFSET) +#define NVIC_SYSH12_15_PRIORITY (ARMV7M_NVIC_BASE + NVIC_SYSH12_15_PRIORITY_OFFSET) +#define NVIC_SYSHCON (ARMV7M_NVIC_BASE + NVIC_SYSHCON_OFFSET) +#define NVIC_CFAULTS (ARMV7M_NVIC_BASE + NVIC_CFAULTS_OFFSET) +#define NVIC_HFAULTS (ARMV7M_NVIC_BASE + NVIC_HFAULTS_OFFSET) +#define NVIC_DFAULTS (ARMV7M_NVIC_BASE + NVIC_DFAULTS_OFFSET) +#define NVIC_MEMMANAGE_ADDR (ARMV7M_NVIC_BASE + NVIC_MEMMANAGE_ADDR_OFFSET) +#define NVIC_BFAULT_ADDR (ARMV7M_NVIC_BASE + NVIC_BFAULT_ADDR_OFFSET) +#define NVIC_AFAULTS (ARMV7M_NVIC_BASE + NVIC_AFAULTS_OFFSET) +#define NVIC_PFR0 (ARMV7M_NVIC_BASE + NVIC_PFR0_OFFSET) +#define NVIC_PFR1 (ARMV7M_NVIC_BASE + NVIC_PFR1_OFFSET) +#define NVIC_DFR0 (ARMV7M_NVIC_BASE + NVIC_DFR0_OFFSET) +#define NVIC_AFR0 (ARMV7M_NVIC_BASE + NVIC_AFR0_OFFSET) +#define NVIC_MMFR0 (ARMV7M_NVIC_BASE + NVIC_MMFR0_OFFSET) +#define NVIC_MMFR1 (ARMV7M_NVIC_BASE + NVIC_MMFR1_OFFSET) +#define NVIC_MMFR2 (ARMV7M_NVIC_BASE + NVIC_MMFR2_OFFSET) +#define NVIC_MMFR3 (ARMV7M_NVIC_BASE + NVIC_MMFR3_OFFSET) +#define NVIC_ISAR0 (ARMV7M_NVIC_BASE + NVIC_ISAR0_OFFSET) +#define NVIC_ISAR1 (ARMV7M_NVIC_BASE + NVIC_ISAR1_OFFSET) +#define NVIC_ISAR2 (ARMV7M_NVIC_BASE + NVIC_ISAR2_OFFSET) +#define NVIC_ISAR3 (ARMV7M_NVIC_BASE + NVIC_ISAR3_OFFSET) +#define NVIC_ISAR4 (ARMV7M_NVIC_BASE + NVIC_ISAR4_OFFSET) +#define NVIC_CPACR (ARMV7M_NVIC_BASE + NVIC_CPACR_OFFSET) +#define NVIC_DHCSR (ARMV7M_NVIC_BASE + NVIC_DHCSR_OFFSET) +#define NVIC_DCRSR (ARMV7M_NVIC_BASE + NVIC_DCRSR_OFFSET) +#define NVIC_DCRDR (ARMV7M_NVIC_BASE + NVIC_DCRDR_OFFSET) +#define NVIC_DEMCR (ARMV7M_NVIC_BASE + NVIC_DEMCR_OFFSET) +#define NVIC_STIR (ARMV7M_NVIC_BASE + NVIC_STIR_OFFSET) +#define NVIC_FPCCR (ARMV7M_NVIC_BASE + NVIC_FPCCR_OFFSET) +#define NVIC_PID4 (ARMV7M_NVIC_BASE + NVIC_PID4_OFFSET) +#define NVIC_PID5 (ARMV7M_NVIC_BASE + NVIC_PID5_OFFSET) +#define NVIC_PID6 (ARMV7M_NVIC_BASE + NVIC_PID6_OFFSET) +#define NVIC_PID7 (ARMV7M_NVIC_BASE + NVIC_PID7_OFFSET) +#define NVIC_PID0 (ARMV7M_NVIC_BASE + NVIC_PID0_OFFSET) +#define NVIC_PID1 (ARMV7M_NVIC_BASE + NVIC_PID1_OFFSET) +#define NVIC_PID2 (ARMV7M_NVIC_BASE + NVIC_PID2_OFFSET) +#define NVIC_PID3 (ARMV7M_NVIC_BASE + NVIC_PID3_OFFSET) +#define NVIC_CID0 (ARMV7M_NVIC_BASE + NVIC_CID0_OFFSET) +#define NVIC_CID1 (ARMV7M_NVIC_BASE + NVIC_CID1_OFFSET) +#define NVIC_CID2 (ARMV7M_NVIC_BASE + NVIC_CID2_OFFSET) +#define NVIC_CID3 (ARMV7M_NVIC_BASE + NVIC_CID3_OFFSET) + +/* NVIC register bit definitions ************************************************************/ + +/* Interrrupt controller type (INCTCTL_TYPE) */ + +#define NVIC_ICTR_INTLINESNUM_SHIFT 0 /* Bits 4-0: Number of interrupt intputs / 32 */ +#define NVIC_ICTR_INTLINESNUM_MASK (0x1f << NVIC_ICTR_INTLINESNUM_SHIFT) + +/* SysTick control and status register (SYSTICK_CTRL) */ + +#define NVIC_SYSTICK_CTRL_ENABLE (1 << 0) /* Bit 0: Enable */ +#define NVIC_SYSTICK_CTRL_TICKINT (1 << 1) /* Bit 1: Tick interrupt */ +#define NVIC_SYSTICK_CTRL_CLKSOURCE (1 << 2) /* Bit 2: Clock source */ +#define NVIC_SYSTICK_CTRL_COUNTFLAG (1 << 16) /* Bit 16: Count Flag */ + +/* SysTick reload value register (SYSTICK_RELOAD) */ + +#define NVIC_SYSTICK_RELOAD_SHIFT 0 /* Bits 23-0: Timer reload value */ +#define NVIC_SYSTICK_RELOAD_MASK (0x00ffffff << NVIC_SYSTICK_RELOAD_SHIFT) + +/* SysTick current value register (SYSTICK_CURRENT) */ + +#define NVIC_SYSTICK_CURRENT_SHIFT 0 /* Bits 23-0: Timer current value */ +#define NVIC_SYSTICK_CURRENT_MASK (0x00ffffff << NVIC_SYSTICK_RELOAD_SHIFT) + +/* SysTick calibration value register (SYSTICK_CALIB) */ + +#define NVIC_SYSTICK_CALIB_TENMS_SHIFT 0 /* Bits 23-0: Calibration value */ +#define NVIC_SYSTICK_CALIB_TENMS_MASK (0x00ffffff << NVIC_SYSTICK_CALIB_TENMS_SHIFT) +#define NVIC_SYSTICK_CALIB_SKEW (1 << 30) /* Bit 30: Calibration value inexact */ +#define NVIC_SYSTICK_CALIB_NOREF (1 << 31) /* Bit 31: No external reference clock */ + +/* Interrupt control state register (INTCTRL) */ + +#define NVIC_INTCTRL_NMIPENDSET (1 << 31) /* Bit 31: Set pending NMI bit */ +#define NVIC_INTCTRL_PENDSVSET (1 << 28) /* Bit 28: Set pending PendSV bit */ +#define NVIC_INTCTRL_PENDSVCLR (1 << 27) /* Bit 27: Clear pending PendSV bit */ +#define NVIC_INTCTRL_PENDSTSET (1 << 26) /* Bit 26: Set pending SysTick bit */ +#define NVIC_INTCTRL_PENDSTCLR (1 << 25) /* Bit 25: Clear pending SysTick bit */ +#define NVIC_INTCTRL_ISPREEMPOT (1 << 23) /* Bit 23: Pending active next cycle */ +#define NVIC_INTCTRL_ISRPENDING (1 << 22) /* Bit 22: Interrupt pending flag */ +#define NVIC_INTCTRL_VECTPENDING_SHIFT 12 /* Bits 21-12: Pending ISR number field */ +#define NVIC_INTCTRL_VECTPENDING_MASK (0x3ff << NVIC_INTCTRL_VECTPENDING_SHIFT) +#define NVIC_INTCTRL_RETTOBASE (1 << 11) /* Bit 11: no other exceptions pending */ +#define NVIC_INTCTRL_VECTACTIVE_SHIFT 0 /* Bits 8-0: Active ISR number */ +#define NVIC_INTCTRL_VECTACTIVE_MASK (0x1ff << NVIC_INTCTRL_VECTACTIVE_SHIFT) + +/* System control register (SYSCON) */ + + /* Bit 0: Reserved */ +#define NVIC_SYSCON_SLEEPONEXIT (1 << 1) /* Bit 1: Sleep-on-exit (returning from Handler to Thread mode) */ +#define NVIC_SYSCON_SLEEPDEEP (1 << 2) /* Bit 2: Use deep sleep in low power mode */ + /* Bit 3: Reserved */ +#define NVIC_SYSCON_SEVONPEND (1 << 4) /* Bit 4: Send Event on Pending bit */ + /* Bits 5-31: Reserved */ + +/* System handler 4-7 priority register */ + +#define NVIC_SYSH_PRIORITY_PR4_SHIFT 0 +#define NVIC_SYSH_PRIORITY_PR4_MASK (0xff << NVIC_SYSH_PRIORITY_PR4_SHIFT) +#define NVIC_SYSH_PRIORITY_PR5_SHIFT 8 +#define NVIC_SYSH_PRIORITY_PR5_MASK (0xff << NVIC_SYSH_PRIORITY_PR5_SHIFT) +#define NVIC_SYSH_PRIORITY_PR6_SHIFT 16 +#define NVIC_SYSH_PRIORITY_PR6_MASK (0xff << NVIC_SYSH_PRIORITY_PR6_SHIFT) +#define NVIC_SYSH_PRIORITY_PR7_SHIFT 24 +#define NVIC_SYSH_PRIORITY_PR7_MASK (0xff << NVIC_SYSH_PRIORITY_PR7_SHIFT) + +/* System handler 8-11 priority register */ + +#define NVIC_SYSH_PRIORITY_PR8_SHIFT 0 +#define NVIC_SYSH_PRIORITY_PR8_MASK (0xff << NVIC_SYSH_PRIORITY_PR8_SHIFT) +#define NVIC_SYSH_PRIORITY_PR9_SHIFT 8 +#define NVIC_SYSH_PRIORITY_PR9_MASK (0xff << NVIC_SYSH_PRIORITY_PR9_SHIFT) +#define NVIC_SYSH_PRIORITY_PR10_SHIFT 16 +#define NVIC_SYSH_PRIORITY_PR10_MASK (0xff << NVIC_SYSH_PRIORITY_PR10_SHIFT) +#define NVIC_SYSH_PRIORITY_PR11_SHIFT 24 +#define NVIC_SYSH_PRIORITY_PR11_MASK (0xff << NVIC_SYSH_PRIORITY_PR11_SHIFT) + +/* System handler 12-15 priority register */ + +#define NVIC_SYSH_PRIORITY_PR12_SHIFT 0 +#define NVIC_SYSH_PRIORITY_PR12_MASK (0xff << NVIC_SYSH_PRIORITY_PR12_SHIFT) +#define NVIC_SYSH_PRIORITY_PR13_SHIFT 8 +#define NVIC_SYSH_PRIORITY_PR13_MASK (0xff << NVIC_SYSH_PRIORITY_PR13_SHIFT) +#define NVIC_SYSH_PRIORITY_PR14_SHIFT 16 +#define NVIC_SYSH_PRIORITY_PR14_MASK (0xff << NVIC_SYSH_PRIORITY_PR14_SHIFT) +#define NVIC_SYSH_PRIORITY_PR15_SHIFT 24 +#define NVIC_SYSH_PRIORITY_PR15_MASK (0xff << NVIC_SYSH_PRIORITY_PR15_SHIFT) + +/* System handler control and state register (SYSHCON) */ + +#define NVIC_SYSHCON_MEMFAULTACT (1 << 0) /* Bit 0: MemManage is active */ +#define NVIC_SYSHCON_BUSFAULTACT (1 << 1) /* Bit 1: BusFault is active */ +#define NVIC_SYSHCON_USGFAULTACT (1 << 3) /* Bit 3: UsageFault is active */ +#define NVIC_SYSHCON_SVCALLACT (1 << 7) /* Bit 7: SVCall is active */ +#define NVIC_SYSHCON_MONITORACT (1 << 8) /* Bit 8: Monitor is active */ +#define NVIC_SYSHCON_PENDSVACT (1 << 10) /* Bit 10: PendSV is active */ +#define NVIC_SYSHCON_SYSTICKACT (1 << 11) /* Bit 11: SysTick is active */ +#define NVIC_SYSHCON_USGFAULTPENDED (1 << 12) /* Bit 12: Usage fault is pended */ +#define NVIC_SYSHCON_MEMFAULTPENDED (1 << 13) /* Bit 13: MemManage is pended */ +#define NVIC_SYSHCON_BUSFAULTPENDED (1 << 14) /* Bit 14: BusFault is pended */ +#define NVIC_SYSHCON_SVCALLPENDED (1 << 15) /* Bit 15: SVCall is pended */ +#define NVIC_SYSHCON_MEMFAULTENA (1 << 16) /* Bit 16: MemFault enabled */ +#define NVIC_SYSHCON_BUSFAULTENA (1 << 17) /* Bit 17: BusFault enabled */ +#define NVIC_SYSHCON_USGFAULTENA (1 << 18) /* Bit 18: UsageFault enabled */ + +/* Debug Exception and Monitor Control Register (DEMCR) */ + +#define NVIC_DEMCR_VCCORERESET (1 << 0) /* Bit 0: Reset Vector Catch */ +#define NVIC_DEMCR_VCMMERR (1 << 4) /* Bit 4: Debug trap on Memory Management faults */ +#define NVIC_DEMCR_VCNOCPERR (1 << 5) /* Bit 5: Debug trap on Usage Fault access to non-present coprocessor */ +#define NVIC_DEMCR_VCCHKERR (1 << 6) /* Bit 6: Debug trap on Usage Fault enabled checking errors */ +#define NVIC_DEMCR_VCSTATERR (1 << 7) /* Bit 7: Debug trap on Usage Fault state error */ +#define NVIC_DEMCR_VCBUSERR (1 << 8) /* Bit 8: Debug Trap on normal Bus error */ +#define NVIC_DEMCR_VCINTERR (1 << 9) /* Bit 9: Debug Trap on interrupt/exception service errors */ +#define NVIC_DEMCR_VCHARDERR (1 << 10) /* Bit 10: Debug trap on Hard Fault */ +#define NVIC_DEMCR_MONEN (1 << 16) /* Bit 16: Enable the debug monitor */ +#define NVIC_DEMCR_MONPEND (1 << 17) /* Bit 17: Pend the monitor to activate when priority permits */ +#define NVIC_DEMCR_MONSTEP (1 << 18) /* Bit 18: Steps the core */ +#define NVIC_DEMCR_MONREQ (1 << 19) /* Bit 19: Monitor wake-up mode */ +#define NVIC_DEMCR_TRCENA (1 << 24) /* Bit 24: Enable trace and debug blocks */ + +/******************************************************************************************** + * Public Types + ********************************************************************************************/ + +/******************************************************************************************** + * Public Data + ********************************************************************************************/ + +/******************************************************************************************** + * Public Function Prototypes + ********************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_COMMON_ARMV7_M_NVIC_H */ diff --git a/nuttx/arch/arm/src/armv7-m/psr.h b/nuttx/arch/arm/src/armv7-m/psr.h new file mode 100644 index 0000000000..30913f7c9e --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/psr.h @@ -0,0 +1,87 @@ +/************************************************************************************ + * arch/arm/src/armv7-m/psr.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_COMMON_ARMV7_M_PSR_H +#define __ARCH_ARM_SRC_COMMON_ARMV7_M_PSR_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Application Program Status Register (APSR) */ + +#define ARMV7M_APSR_Q (1 << 27) /* Bit 27: Sticky saturation flag */ +#define ARMV7M_APSR_V (1 << 28) /* Bit 28: Overflow flag */ +#define ARMV7M_APSR_C (1 << 29) /* Bit 29: Carry/borrow flag */ +#define ARMV7M_APSR_Z (1 << 30) /* Bit 30: Zero flag */ +#define ARMV7M_APSR_N (1 << 31) /* Bit 31: Negative, less than flag */ + +/* Interrupt Program Status Register (IPSR) */ + +#define ARMV7M_IPSR_ISR_SHIFT 0 /* Bits 8-0: ISR number */ +#define ARMV7M_IPSR_ISR_MASK (0x1ff << ARMV7M_IPSR_ISR_SHIFT) + +/* Execution PSR Register (EPSR) */ + +#define ARMV7M_EPSR_ICIIT1_SHIFT 10 /* Bits 15-10: Interrupt-Continuable-Instruction/If-Then bits */ +#define ARMV7M_EPSR_ICIIT1_MASK (3 << ARMV7M_EPSR_ICIIT1_SHIFT) +#define ARMV7M_EPSR_T (1 << 24) /* Bit 24: T-bit */ +#define ARMV7M_EPSR_ICIIT2_SHIFT 25 /* Bits 26-25: Interrupt-Continuable-Instruction/If-Then bits */ +#define ARMV7M_EPSR_ICIIT2_MASK (3 << ARMV7M_EPSR_ICIIT2_SHIFT) + +/* Save xPSR bits */ + +#define ARMV7M_XPSR_ISR_SHIFT ARMV7M_IPSR_ISR_SHIFT +#define ARMV7M_XPSR_ISR_MASK ARMV7M_IPSR_ISR_MASK +#define ARMV7M_XPSR_ICIIT1_SHIFT ARMV7M_EPSR_ICIIT1_SHIFT/ +#define ARMV7M_XPSR_ICIIT1_MASK ARMV7M_EPSR_ICIIT1_MASK +#define ARMV7M_XPSR_T ARMV7M_EPSR_T +#define ARMV7M_XPSR_ICIIT2_SHIFT ARMV7M_EPSR_ICIIT2_SHIFT +#define ARMV7M_XPSR_ICIIT2_MASK ARMV7M_EPSR_ICIIT2_MASK +#define ARMV7M_XPSR_Q ARMV7M_APSR_Q +#define ARMV7M_XPSR_V ARMV7M_APSR_V +#define ARMV7M_XPSR_C ARMV7M_APSR_C +#define ARMV7M_XPSR_Z ARMV7M_APSR_Z +#define ARMV7M_XPSR_N ARMV7M_APSR_N + +/************************************************************************************ + * Inline Functions + ************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_COMMON_ARMV7_M_PSR_H */ diff --git a/nuttx/arch/arm/src/armv7-m/svcall.h b/nuttx/arch/arm/src/armv7-m/svcall.h new file mode 100644 index 0000000000..51b5b9111a --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/svcall.h @@ -0,0 +1,94 @@ +/************************************************************************************ + * arch/arm/src/armv7-m/svcall.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_COMMON_CORTEXM_SVCALL_H +#define __ARCH_ARM_SRC_COMMON_CORTEXM_SVCALL_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#ifdef CONFIG_NUTTX_KERNEL +# include +#endif + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Configuration ********************************************************************/ +/* This logic uses three system calls {0,1,2} for context switching. The first three + * syscall values must be reserved. + */ + +#ifdef CONFIG_NUTTX_KERNEL +# ifndef CONFIG_SYS_RESERVED +# error "CONFIG_SYS_RESERVED must be defined to the value 3" +# elif CONFIG_SYS_RESERVED != 3 +# error "CONFIG_SYS_RESERVED must have the value 3" +# endif +#endif + +/* Cortex M3 system calls ***********************************************************/ + +/* SYS call 0: + * + * int up_saveusercontext(uint32_t *saveregs); + */ + +#define SYS_save_context (0) + +/* SYS call 1: + * + * void up_fullcontextrestore(uint32_t *restoreregs) __attribute__ ((noreturn)); + */ + +#define SYS_restore_context (1) + +/* SYS call 2: + * + * void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs); + */ + +#define SYS_switch_context (2) + +/************************************************************************************ + * Inline Functions + ************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_COMMON_CORTEXM_SVCALL_H */ + diff --git a/nuttx/arch/arm/src/armv7-m/up_assert.c b/nuttx/arch/arm/src/armv7-m/up_assert.c new file mode 100644 index 0000000000..77fd0b596f --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_assert.c @@ -0,0 +1,334 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_assert.c + * + * Copyright (C) 2009-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Output debug info if stack dump is selected -- even if + * debug is not selected. + */ + +#ifdef CONFIG_ARCH_STACKDUMP +# undef lldbg +# define lldbg lib_lowprintf +#endif + +/* The following is just intended to keep some ugliness out of the mainline + * code. We are going to print the task name if: + * + * CONFIG_TASK_NAME_SIZE > 0 && <-- The task has a name + * (defined(CONFIG_DEBUG) || <-- And the debug is enabled (lldbg used) + * defined(CONFIG_ARCH_STACKDUMP) <-- Or lib_lowprintf() is used + */ + +#undef CONFIG_PRINT_TASKNAME +#if CONFIG_TASK_NAME_SIZE > 0 && (defined(CONFIG_DEBUG) || defined(CONFIG_ARCH_STACKDUMP)) +# define CONFIG_PRINT_TASKNAME 1 +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_getsp + ****************************************************************************/ + +/* I don't know if the builtin to get SP is enabled */ + +static inline uint32_t up_getsp(void) +{ + uint32_t sp; + __asm__ + ( + "\tmov %0, sp\n\t" + : "=r"(sp) + ); + return sp; +} + +/**************************************************************************** + * Name: up_stackdump + ****************************************************************************/ + +#ifdef CONFIG_ARCH_STACKDUMP +static void up_stackdump(uint32_t sp, uint32_t stack_base) +{ + uint32_t stack ; + + for (stack = sp & ~0x1f; stack < stack_base; stack += 32) + { + uint32_t *ptr = (uint32_t*)stack; + lldbg("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", + stack, ptr[0], ptr[1], ptr[2], ptr[3], + ptr[4], ptr[5], ptr[6], ptr[7]); + } +} +#else +# define up_stackdump() +#endif + +/**************************************************************************** + * Name: up_registerdump + ****************************************************************************/ + +#ifdef CONFIG_ARCH_STACKDUMP +static inline void up_registerdump(void) +{ + /* Are user registers available from interrupt processing? */ + + if (current_regs) + { + /* Yes.. dump the interrupt registers */ + + lldbg("R0: %08x %08x %08x %08x %08x %08x %08x %08x\n", + current_regs[REG_R0], current_regs[REG_R1], + current_regs[REG_R2], current_regs[REG_R3], + current_regs[REG_R4], current_regs[REG_R5], + current_regs[REG_R6], current_regs[REG_R7]); + lldbg("R8: %08x %08x %08x %08x %08x %08x %08x %08x\n", + current_regs[REG_R8], current_regs[REG_R9], + current_regs[REG_R10], current_regs[REG_R11], + current_regs[REG_R12], current_regs[REG_R13], + current_regs[REG_R14], current_regs[REG_R15]); + lldbg("xPSR: %08x PRIMASK: %08x\n", + current_regs[REG_XPSR], current_regs[REG_PRIMASK]); + } +} +#else +# define up_registerdump() +#endif + +/**************************************************************************** + * Name: up_dumpstate + ****************************************************************************/ + +#ifdef CONFIG_ARCH_STACKDUMP +static void up_dumpstate(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + uint32_t sp = up_getsp(); + uint32_t ustackbase; + uint32_t ustacksize; +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + uint32_t istackbase; + uint32_t istacksize; +#endif + + /* Get the limits on the user stack memory */ + + if (rtcb->pid == 0) + { + ustackbase = g_heapbase - 4; + ustacksize = CONFIG_IDLETHREAD_STACKSIZE; + } + else + { + ustackbase = (uint32_t)rtcb->adj_stack_ptr; + ustacksize = (uint32_t)rtcb->adj_stack_size; + } + + /* Get the limits on the interrupt stack memory */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + istackbase = (uint32_t)&g_intstackbase; + istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4; + + /* Show interrupt stack info */ + + lldbg("sp: %08x\n", sp); + lldbg("IRQ stack:\n"); + lldbg(" base: %08x\n", istackbase); + lldbg(" size: %08x\n", istacksize); + + /* Does the current stack pointer lie within the interrupt + * stack? + */ + + if (sp <= istackbase && sp > istackbase - istacksize) + { + /* Yes.. dump the interrupt stack */ + + up_stackdump(sp, istackbase); + } + + /* Extract the user stack pointer if we are in an interrupt handler. + * If we are not in an interrupt handler. Then sp is the user stack + * pointer (and the above range check should have failed). + */ + + if (current_regs) + { + sp = current_regs[REG_R13]; + lldbg("sp: %08x\n", sp); + } + + lldbg("User stack:\n"); + lldbg(" base: %08x\n", ustackbase); + lldbg(" size: %08x\n", ustacksize); + + /* Dump the user stack if the stack pointer lies within the allocated user + * stack memory. + */ + + if (sp <= ustackbase && sp > ustackbase - ustacksize) + { + up_stackdump(sp, ustackbase); + } +#else + lldbg("sp: %08x\n", sp); + lldbg("stack base: %08x\n", ustackbase); + lldbg("stack size: %08x\n", ustacksize); + + /* Dump the user stack if the stack pointer lies within the allocated user + * stack memory. + */ + + if (sp > ustackbase || sp <= ustackbase - ustacksize) + { + lldbg("ERROR: Stack pointer is not within allocated stack\n"); + } + else + { + up_stackdump(sp, ustackbase); + } +#endif + + /* Then dump the registers (if available) */ + + up_registerdump(); +} +#else +# define up_dumpstate() +#endif + +/**************************************************************************** + * Name: _up_assert + ****************************************************************************/ + +static void _up_assert(int errorcode) /* __attribute__ ((noreturn)) */ +{ + /* Are we in an interrupt handler or the idle task? */ + + if (current_regs || ((_TCB*)g_readytorun.head)->pid == 0) + { + (void)irqsave(); + for(;;) + { +#ifdef CONFIG_ARCH_LEDS + up_ledon(LED_PANIC); + up_mdelay(250); + up_ledoff(LED_PANIC); + up_mdelay(250); +#endif + } + } + else + { + exit(errorcode); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_assert + ****************************************************************************/ + +void up_assert(const uint8_t *filename, int lineno) +{ +#ifdef CONFIG_PRINT_TASKNAME + _TCB *rtcb = (_TCB*)g_readytorun.head; +#endif + + up_ledon(LED_ASSERTION); +#ifdef CONFIG_PRINT_TASKNAME + lldbg("Assertion failed at file:%s line: %d task: %s\n", + filename, lineno, rtcb->name); +#else + lldbg("Assertion failed at file:%s line: %d\n", + filename, lineno); +#endif + up_dumpstate(); + _up_assert(EXIT_FAILURE); +} + +/**************************************************************************** + * Name: up_assert_code + ****************************************************************************/ + +void up_assert_code(const uint8_t *filename, int lineno, int errorcode) +{ +#ifdef CONFIG_PRINT_TASKNAME + _TCB *rtcb = (_TCB*)g_readytorun.head; +#endif + + up_ledon(LED_ASSERTION); +#ifdef CONFIG_PRINT_TASKNAME + lldbg("Assertion failed at file:%s line: %d task: %s error code: %d\n", + filename, lineno, rtcb->name, errorcode); +#else + lldbg("Assertion failed at file:%s line: %d error code: %d\n", + filename, lineno, errorcode); +#endif + up_dumpstate(); + _up_assert(errorcode); +} diff --git a/nuttx/arch/arm/src/armv7-m/up_blocktask.c b/nuttx/arch/arm/src/armv7-m/up_blocktask.c new file mode 100755 index 0000000000..896476ed2e --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_blocktask.c @@ -0,0 +1,167 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_blocktask.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_block_task + * + * Description: + * The currently executing task at the head of + * the ready to run list must be stopped. Save its context + * and move it to the inactive list specified by task_state. + * + * Inputs: + * tcb: Refers to a task in the ready-to-run list (normally + * the task at the head of the list). It most be + * stopped, its context saved and moved into one of the + * waiting task lists. It it was the task at the head + * of the ready-to-run list, then a context to the new + * ready to run task must be performed. + * task_state: Specifies which waiting task list should be + * hold the blocked task TCB. + * + ****************************************************************************/ + +void up_block_task(_TCB *tcb, tstate_t task_state) +{ + /* Verify that the context switch can be performed */ + + if ((tcb->task_state < FIRST_READY_TO_RUN_STATE) || + (tcb->task_state > LAST_READY_TO_RUN_STATE)) + { + PANIC(OSERR_BADBLOCKSTATE); + } + else + { + _TCB *rtcb = (_TCB*)g_readytorun.head; + bool switch_needed; + + /* Remove the tcb task from the ready-to-run list. If we + * are blocking the task at the head of the task list (the + * most likely case), then a context switch to the next + * ready-to-run task is needed. In this case, it should + * also be true that rtcb == tcb. + */ + + switch_needed = sched_removereadytorun(tcb); + + /* Add the task to the specified blocked task list */ + + sched_addblocked(tcb, (tstate_t)task_state); + + /* If there are any pending tasks, then add them to the g_readytorun + * task list now + */ + + if (g_pendingtasks.head) + { + switch_needed |= sched_mergepending(); + } + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + /* Are we in an interrupt handler? */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* No, then we will need to perform the user context switch */ + + else + { + /* Switch context to the context of the task at the head of the + * ready to run list. + */ + + _TCB *nexttcb = (_TCB*)g_readytorun.head; + up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); + + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ + } + } + } +} diff --git a/nuttx/arch/arm/src/armv7-m/up_copystate.c b/nuttx/arch/arm/src/armv7-m/up_copystate.c new file mode 100644 index 0000000000..a5ad312f5e --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_copystate.c @@ -0,0 +1,86 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_copystate.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_copystate + ****************************************************************************/ + +/* A little faster than most memcpy's */ + +void up_copystate(uint32_t *dest, uint32_t *src) +{ + int i; + + /* In the Cortex-M3 model, the state is copied from the stack to the TCB, + * but only a reference is passed to get the state from the TCB. So the + * following check avoids copying the TCB save area onto itself: + */ + + if (src != dest) + { + for (i = 0; i < XCPTCONTEXT_REGS; i++) + { + *dest++ = *src++; + } + } +} + diff --git a/nuttx/arch/arm/src/armv7-m/up_doirq.c b/nuttx/arch/arm/src/armv7-m/up_doirq.c new file mode 100644 index 0000000000..7ac1ec34db --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_doirq.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_doirq.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +uint32_t *up_doirq(int irq, uint32_t *regs) +{ + up_ledon(LED_INIRQ); +#ifdef CONFIG_SUPPRESS_INTERRUPTS + PANIC(OSERR_ERREXCEPTION); +#else + uint32_t *savestate; + + /* Nested interrupts are not supported in this implementation. If you want + * implemented nested interrupts, you would have to (1) change the way that + * current regs is handled and (2) the design associated with + * CONFIG_ARCH_INTERRUPTSTACK. + */ + + /* Current regs non-zero indicates that we are processing an interrupt; + * current_regs is also used to manage interrupt level context switches. + */ + + savestate = (uint32_t*)current_regs; + current_regs = regs; + + /* Mask and acknowledge the interrupt */ + + up_maskack_irq(irq); + + /* Deliver the IRQ */ + + irq_dispatch(irq, regs); + + /* If a context switch occurred while processing the interrupt then + * current_regs may have change value. If we return any value different + * from the input regs, then the lower level will know that a context + * switch occurred during interrupt processing. + */ + + regs = (uint32_t*)current_regs; + + /* Restore the previous value of current_regs. NULL would indicate that + * we are no longer in an interrupt handler. It will be non-NULL if we + * are returning from a nested interrupt. + */ + + current_regs = savestate; + + /* Unmask the last interrupt (global interrupts are still disabled) */ + + up_enable_irq(irq); +#endif + up_ledoff(LED_INIRQ); + return regs; +} diff --git a/nuttx/arch/arm/src/armv7-m/up_exception.S b/nuttx/arch/arm/src/armv7-m/up_exception.S new file mode 100644 index 0000000000..31d8dbb0cc --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_exception.S @@ -0,0 +1,237 @@ +/************************************************************************************ + * arch/arm/src/stm32/up_exception.S + * arch/arm/src/chip/up_exception.S + * + * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012 Michael Smith. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include "exc_return.h" + +#include "chip.h" + +/************************************************************************************ + * Global Symbols + ************************************************************************************/ + + .globl exception_common + + .syntax unified + .thumb + .file "up_exception.S" + +/************************************************************************************ + * .text + ************************************************************************************/ + +/* Common exception handling logic. On entry here, the return stack is on either + * the PSP or the MSP and looks like the following: + * + * REG_XPSR + * REG_R15 + * REG_R14 + * REG_R12 + * REG_R3 + * REG_R2 + * REG_R1 + * MSP->REG_R0 + * + * And + * IPSR contains the IRQ number + * R14 Contains the EXC_RETURN value + * We are in handler mode and the current SP is the MSP + * + * If CONFIG_ARCH_FPU is defined, the volatile FP registers and FPSCR are on the + * return stack immediately above REG_XPSR. + */ + + .text + .type exception_common, function + .thumb_func +exception_common: + + mrs r0, ipsr /* R0=exception number */ + + /* Complete the context save */ + + /* The EXC_RETURN value tells us whether the context is on the MSP or PSP */ + + tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */ + ite eq /* next two instructions conditional */ + mrseq r1, msp /* R1=The main stack pointer */ + mrsne r1, psp /* R1=The process stack pointer */ + + mov r2, r1 /* R2=Copy of the main/process stack pointer */ + add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */ + /* (ignoring the xPSR[9] alignment bit) */ + mrs r3, primask /* R3=Current PRIMASK setting */ + +#ifdef CONFIG_ARCH_FPU + + /* Save the non-volatile FP registers here. + * + * This routine is the only point where we can save these registers; either before + * or after calling up_doirq. The compiler is free to use them at any time as long + * as they are restored before returning, so we can't assume that we can get at the + * true values of these registers in any routine called from here. + * + * XXX we could do all this saving lazily on the context switch side if we knew where to put + * the registers. + */ + + vstmdb r1!, {s16-s31} /* Save the non-volatile FP context */ + +#endif + + stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP/PRIMASK values */ + + /* Disable interrupts, select the stack to use for interrupt handling + * and call up_doirq to handle the interrupt + */ + + cpsid i /* Disable further interrupts */ + + /* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will use a special interrupt + * stack pointer. The way that this is done here prohibits nested interrupts! + * Otherwise, we will use the stack that was current when the interrupt was taken. + */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + ldr sp, =g_intstackbase + push r1 /* Save the MSP on the interrupt stack */ + bl up_doirq /* R0=IRQ, R1=register save area on stack */ + pop r1 /* Recover R1=main stack pointer */ +#else + msr msp, r1 /* We are using the main stack pointer */ + bl up_doirq /* R0=IRQ, R1=register save area on stack */ + mrs r1, msp /* Recover R1=main stack pointer */ +#endif + + /* On return from up_doirq, R0 will hold a pointer to register context + * array to use for the interrupt return. If that return value is the same + * as current stack pointer, then things are relatively easy. + */ + + cmp r0, r1 /* Context switch? */ + beq 1f /* Branch if no context switch */ + + /* We are returning with a pending context switch. This case is different + * because in this case, the register save structure does not lie on the + * stack but, rather within a TCB structure. We'll have to copy some + * values to the stack. + */ + + /* Copy the hardware-saved context to the stack, and restore the software + * saved context directly. + * + * XXX In the normal case, it appears that this entire operation is unnecessary; + * context switch time would be improved if we could work out when the stack + * is dirty and avoid the work... + */ + + add r1, r0, #SW_XCPT_SIZE /* R1=Address of HW save area in reg array */ + ldmia r1!, {r4-r11} /* Fetch eight registers in HW save area */ +#ifdef CONFIG_ARCH_FPU + vldmia r1!, {s0-s15} /* Fetch sixteen FP registers in HW save area */ + ldmia r1, {r2-r3} /* Fetch FPSCR and Reserved in HW save area */ +#endif + ldr r1, [r0, #(4*REG_SP)] /* R1=Value of SP before interrupt */ +#ifdef CONFIG_ARCH_FPU + stmdb r1!, {r2-r3} /* Store FPSCR and Reserved on the return stack */ + vstmdb r1!, {s0-s15} /* Store sixteen FP registers on the return stack */ +#endif + stmdb r1!, {r4-r11} /* Store eight registers on the return stack */ + ldmia r0!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */ +#ifdef CONFIG_ARCH_FPU + vldmia r0, {s16-s31} /* Recover S16-S31 */ +#endif + + b 2f /* Re-join common logic */ + +1: + /* We are returning with no context switch. We simply need to "unwind" + * the same stack frame that we created at entry. + */ + + ldmia r1!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */ +#ifdef CONFIG_ARCH_FPU + vldmia r1!, {s16-s31} /* Recover S16-S31 */ +#endif + +2: + /* The EXC_RETURN value tells us whether we are returning on the MSP or PSP + */ + + tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */ + ite eq /* next two instructions conditional */ + msreq msp, r1 /* R1=The main stack pointer */ + msrne psp, r1 /* R1=The process stack pointer */ + + /* Restore the interrupt state */ + + msr primask, r3 /* Restore interrupts */ + + /* Always return with R14 containing the special value that will: (1) + * return to thread mode, and (2) select the correct stack. + */ + + bx r14 /* And return */ + + .size exception_common, .-exception_common + +/************************************************************************************ + * Name: up_interruptstack/g_intstackbase + * + * Description: + * Shouldn't happen + * + ************************************************************************************/ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + .bss + .global g_intstackbase + .align 4 +up_interruptstack: + .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3) +g_intstackbase: + .size up_interruptstack, .-up_interruptstack +#endif + + .end + diff --git a/nuttx/arch/arm/src/armv7-m/up_fpu.S b/nuttx/arch/arm/src/armv7-m/up_fpu.S new file mode 100644 index 0000000000..707420f064 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_fpu.S @@ -0,0 +1,286 @@ +/************************************************************************************ + * arch/arm/src/armv7-m/stm32_fpu.S + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ +/* + * When this file is assembled, it will require the following GCC options: + * + * -mcpu=cortex-m3 -mfloat-abi=hard -mfpu=vfp -meabi=5 + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include + +#ifdef CONFIG_ARCH_FPU + +/************************************************************************************ + * Preprocessor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Global Symbols + ************************************************************************************/ + + .globl up_savefpu + .globl up_restorefpu + + .syntax unified + .thumb + .file "up_fpu.S" + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_savefpu + * + * Description: + * Given the pointer to a register save area (in R0), save the state of the + * floating point registers. + * + * C Function Prototype: + * void up_savefpu(uint32_t *regs); + * + * Input Parameters: + * regs - A pointer to the register save area in which to save the floating point + * registers + * + * Returned Value: + * None + * + ************************************************************************************/ + + .thumb_func + .type up_savefpu, function +up_savefpu: + + add r1, r0, #(4*REG_S0) /* R1=Address of FP register storage */ + + /* Some older GNU assemblers don't support all the newer UAL mnemonics. */ + +#if 1 /* Use UAL mnemonics */ + /* Store all floating point registers. Registers are stored in numeric order, + * s0, s1, ... in increasing address order. + */ + + vstmia r1!, {s0-s31} /* Save the full FP context */ + + /* Store the floating point control and status register. At the end of the + * vstmia, r1 will point to the FPCSR storage location. + */ + + vmrs r2, fpscr /* Fetch the FPCSR */ + str r2, [r1], #4 /* Save the floating point control and status register */ +#else + /* Store all floating point registers */ + +#if 1 /* Use store multiple */ + fstmias r1!, {s0-s31} /* Save the full FP context */ +#else + vmov r2, r3, d0 /* r2, r3 = d0 */ + str r2, [r1], #4 /* Save S0 and S1 values */ + str r3, [r1], #4 + vmov r2, r3, d1 /* r2, r3 = d1 */ + str r2, [r1], #4 /* Save S2 and S3 values */ + str r3, [r1], #4 + vmov r2, r3, d2 /* r2, r3 = d2 */ + str r2, [r1], #4 /* Save S4 and S5 values */ + str r3, [r1], #4 + vmov r2, r3, d3 /* r2, r3 = d3 */ + str r2, [r1], #4 /* Save S6 and S7 values */ + str r3, [r1], #4 + vmov r2, r3, d4 /* r2, r3 = d4 */ + str r2, [r1], #4 /* Save S8 and S9 values */ + str r3, [r1], #4 + vmov r2, r3, d5 /* r2, r3 = d5 */ + str r2, [r1], #4 /* Save S10 and S11 values */ + str r3, [r1], #4 + vmov r2, r3, d6 /* r2, r3 = d6 */ + str r2, [r1], #4 /* Save S12 and S13 values */ + str r3, [r1], #4 + vmov r2, r3, d7 /* r2, r3 = d7 */ + str r2, [r1], #4 /* Save S14 and S15 values */ + str r3, [r1], #4 + vmov r2, r3, d8 /* r2, r3 = d8 */ + str r2, [r1], #4 /* Save S16 and S17 values */ + str r3, [r1], #4 + vmov r2, r3, d9 /* r2, r3 = d9 */ + str r2, [r1], #4 /* Save S18 and S19 values */ + str r3, [r1], #4 + vmov r2, r3, d10 /* r2, r3 = d10 */ + str r2, [r1], #4 /* Save S20 and S21 values */ + str r3, [r1], #4 + vmov r2, r3, d11 /* r2, r3 = d11 */ + str r2, [r1], #4 /* Save S22 and S23 values */ + str r3, [r1], #4 + vmov r2, r3, d12 /* r2, r3 = d12 */ + str r2, [r1], #4 /* Save S24 and S25 values */ + str r3, [r1], #4 + vmov r2, r3, d13 /* r2, r3 = d13 */ + str r2, [r1], #4 /* Save S26 and S27 values */ + str r3, [r1], #4 + vmov r2, r3, d14 /* r2, r3 = d14 */ + str r2, [r1], #4 /* Save S28 and S29 values */ + str r3, [r1], #4 + vmov r2, r3, d15 /* r2, r3 = d15 */ + str r2, [r1], #4 /* Save S30 and S31 values */ + str r3, [r1], #4 +#endif + + /* Store the floating point control and status register */ + + fmrx r2, fpscr /* Fetch the FPCSR */ + str r2, [r1], #4 /* Save the floating point control and status register */ +#endif + bx lr + + .size up_savefpu, .-up_savefpu + +/************************************************************************************ + * Name: up_restorefpu + * + * Description: + * Given the pointer to a register save area (in R0), restore the state of the + * floating point registers. + * + * C Function Prototype: + * void up_restorefpu(const uint32_t *regs); + * + * Input Parameters: + * regs - A pointer to the register save area containing the floating point + * registers. + * + * Returned Value: + * This function does not return anything explicitly. However, it is called from + * interrupt level assembly logic that assumes that r0 is preserved. + * + ************************************************************************************/ + + .thumb_func + .type up_restorefpu, function +up_restorefpu: + + add r1, r0, #(4*REG_S0) /* R1=Address of FP register storage */ + + /* Some older GNU assemblers don't support all the newer UAL mnemonics. */ + +#if 1 /* Use UAL mnemonics */ + /* Load all floating point registers. Registers are loaded in numeric order, + * s0, s1, ... in increasing address order. + */ + + vldmia r1!, {s0-s31} /* Restore the full FP context */ + + /* Load the floating point control and status register. At the end of the + * vstmia, r1 will point to the FPCSR storage location. + */ + + ldr r2, [r1], #4 /* Fetch the floating point control and status register */ + vmsr fpscr, r2 /* Restore the FPCSR */ +#else + /* Load all floating point registers Registers are loaded in numeric order, + * s0, s1, ... in increasing address order. + */ + +#if 1 /* Use load multiple */ + fldmias r1!, {s0-s31} /* Restore the full FP context */ +#else + ldr r2, [r1], #4 /* Fetch S0 and S1 values */ + ldr r3, [r1], #4 + vmov d0, r2, r3 /* Save as d0 */ + ldr r2, [r1], #4 /* Fetch S2 and S3 values */ + ldr r3, [r1], #4 + vmov d1, r2, r3 /* Save as d1 */ + ldr r2, [r1], #4 /* Fetch S4 and S5 values */ + ldr r3, [r1], #4 + vmov d2, r2, r3 /* Save as d2 */ + ldr r2, [r1], #4 /* Fetch S6 and S7 values */ + ldr r3, [r1], #4 + vmov d3, r2, r3 /* Save as d3 */ + ldr r2, [r1], #4 /* Fetch S8 and S9 values */ + ldr r3, [r1], #4 + vmov d4, r2, r3 /* Save as d4 */ + ldr r2, [r1], #4 /* Fetch S10 and S11 values */ + ldr r3, [r1], #4 + vmov d5, r2, r3 /* Save as d5 */ + ldr r2, [r1], #4 /* Fetch S12 and S13 values */ + ldr r3, [r1], #4 + vmov d6, r2, r3 /* Save as d6 */ + ldr r2, [r1], #4 /* Fetch S14 and S15 values */ + ldr r3, [r1], #4 + vmov d7, r2, r3 /* Save as d7 */ + ldr r2, [r1], #4 /* Fetch S16 and S17 values */ + ldr r3, [r1], #4 + vmov d8, r2, r3 /* Save as d8 */ + ldr r2, [r1], #4 /* Fetch S18 and S19 values */ + ldr r3, [r1], #4 + vmov d9, r2, r3 /* Save as d9 */ + ldr r2, [r1], #4 /* Fetch S20 and S21 values */ + ldr r3, [r1], #4 + vmov d10, r2, r3 /* Save as d10 */ + ldr r2, [r1], #4 /* Fetch S22 and S23 values */ + ldr r3, [r1], #4 + vmov d11, r2, r3 /* Save as d11 */ + ldr r2, [r1], #4 /* Fetch S24 and S25 values */ + ldr r3, [r1], #4 + vmov d12, r2, r3 /* Save as d12 */ + ldr r2, [r1], #4 /* Fetch S26 and S27 values */ + ldr r3, [r1], #4 + vmov d13, r2, r3 /* Save as d13 */ + ldr r2, [r1], #4 /* Fetch S28 and S29 values */ + ldr r3, [r1], #4 + vmov d14, r2, r3 /* Save as d14 */ + ldr r2, [r1], #4 /* Fetch S30 and S31 values */ + ldr r3, [r1], #4 + vmov d15, r2, r3 /* Save as d15 */ +#endif + + /* Load the floating point control and status register. r1 points t + * the address of the FPCSR register. + */ + + ldr r2, [r1], #4 /* Fetch the floating point control and status register */ + fmxr fpscr, r2 /* Restore the FPCSR */ +#endif + bx lr + + .size up_restorefpu, .-up_restorefpu +#endif /* CONFIG_ARCH_FPU */ + .end + diff --git a/nuttx/arch/arm/src/armv7-m/up_fullcontextrestore.S b/nuttx/arch/arm/src/armv7-m/up_fullcontextrestore.S new file mode 100755 index 0000000000..3ce51c9cd6 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_fullcontextrestore.S @@ -0,0 +1,95 @@ +/************************************************************************************ + * arch/arm/src/armv7-m/up_fullcontextrestore.S + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +#include "nvic.h" +#include "svcall.h" + +/************************************************************************************ + * Preprocessor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Global Symbols + ************************************************************************************/ + + .syntax unified + .thumb + .file "up_fullcontextrestore.S" + +/************************************************************************************ + * Macros + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_fullcontextrestore + * + * Description: + * Restore the current thread context. Full prototype is: + * + * void up_fullcontextrestore(uint32_t *restoreregs) __attribute__ ((noreturn)); + * + * Return: + * None + * + ************************************************************************************/ + + .thumb_func + .globl up_fullcontextrestore + .type up_fullcontextrestore, function +up_fullcontextrestore: + + /* Perform the System call with R0=1 and R1=regs */ + + mov r1, r0 /* R1: regs */ + mov r0, #SYS_restore_context /* R0: restore context */ + svc 0 /* Force synchronous SVCall (or Hard Fault) */ + + /* This call should not return */ + + bx lr /* Unnecessary ... will not return */ + .size up_fullcontextrestore, .-up_fullcontextrestore + .end + diff --git a/nuttx/arch/arm/src/armv7-m/up_hardfault.c b/nuttx/arch/arm/src/armv7-m/up_hardfault.c new file mode 100644 index 0000000000..a9eea81036 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_hardfault.c @@ -0,0 +1,144 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_hardfault.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "up_arch.h" +#include "os_internal.h" +#include "nvic.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Debug output from this file may interfere with context switching! */ + +#undef DEBUG_HARDFAULTS /* Define to debug hard faults */ + +#ifdef DEBUG_HARDFAULTS +# define hfdbg(format, arg...) lldbg(format, ##arg) +#else +# define hfdbg(x...) +#endif + +#define INSN_SVC0 0xdf00 /* insn: svc 0 */ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_hardfault + * + * Description: + * This is Hard Fault exception handler. It also catches SVC call + * exceptions that are performed in bad contexts. + * + ****************************************************************************/ + +int up_hardfault(int irq, FAR void *context) +{ + uint32_t *regs = (uint32_t*)context; + uint16_t *pc; + uint16_t insn; + + /* Get the value of the program counter where the fault occurred */ + + pc = (uint16_t*)regs[REG_PC] - 1; + if ((void*)pc >= (void*)&_stext && (void*)pc < (void*)&_etext) + { + /* Fetch the instruction that caused the Hard fault */ + + insn = *pc; + hfdbg(" PC: %p INSN: %04x\n", pc, insn); + + /* If this was the instruction 'svc 0', then forward processing + * to the SVCall handler + */ + + if (insn == INSN_SVC0) + { + hfdbg("Forward SVCall\n"); + return up_svcall(irq, context); + } + } + + /* Dump some hard fault info */ + + hfdbg("\nHard Fault:\n"); + hfdbg(" IRQ: %d regs: %p\n", irq, regs); + hfdbg(" BASEPRI: %08x PRIMASK: %08x IPSR: %08x\n", + getbasepri(), getprimask(), getipsr()); + hfdbg(" CFAULTS: %08x HFAULTS: %08x DFAULTS: %08x BFAULTADDR: %08x AFAULTS: %08x\n", + getreg32(NVIC_CFAULTS), getreg32(NVIC_HFAULTS), + getreg32(NVIC_DFAULTS), getreg32(NVIC_BFAULT_ADDR), + getreg32(NVIC_AFAULTS)); + hfdbg(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n", + regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3], + regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]); + hfdbg(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n", + regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11], + regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]); + hfdbg(" PSR=%08x\n", regs[REG_XPSR]); + + (void)irqsave(); + lldbg("PANIC!!! Hard fault: %08x\n", getreg32(NVIC_HFAULTS)); + PANIC(OSERR_UNEXPECTEDISR); + return OK; +} diff --git a/nuttx/arch/arm/src/armv7-m/up_initialstate.c b/nuttx/arch/arm/src/armv7-m/up_initialstate.c new file mode 100644 index 0000000000..52a2682a07 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_initialstate.c @@ -0,0 +1,200 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_initialstate.c + * + * Copyright (C) 2009, 2011-2 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "up_internal.h" +#include "up_arch.h" + +#include "psr.h" +#include "exc_return.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_initial_state + * + * Description: + * A new thread is being started and a new TCB + * has been created. This function is called to initialize + * the processor specific portions of the new TCB. + * + * This function must setup the intial architecture registers + * and/or stack so that execution will begin at tcb->start + * on the next context switch. + * + ****************************************************************************/ + +void up_initial_state(_TCB *tcb) +{ + struct xcptcontext *xcp = &tcb->xcp; + + /* Initialize the initial exception register context structure */ + + memset(xcp, 0, sizeof(struct xcptcontext)); + + /* Save the initial stack pointer */ + + xcp->regs[REG_SP] = (uint32_t)tcb->adj_stack_ptr; + + /* Set the stack limit value */ + + xcp->regs[REG_R10] = (uint32_t)tcb->stack_alloc_ptr + 64; + + /* Fill the stack with a watermark value */ + + memset(tcb->stack_alloc_ptr, 0xff, tcb->adj_stack_size); + + /* Save the task entry point (stripping off the thumb bit) */ + + xcp->regs[REG_PC] = (uint32_t)tcb->start & ~1; + + /* Specify thumb mode */ + + xcp->regs[REG_XPSR] = ARMV7M_XPSR_T; + + /* If this task is running PIC, then set the PIC base register to the + * address of the allocated D-Space region. + */ + +#ifdef CONFIG_PIC + if (tcb->dspace != NULL) + { + /* Set the PIC base register (probably R10) to the address of the + * alloacated D-Space region. + */ + + xcp->regs[REG_PIC] = (uint32_t)tcb->dspace->region; + } + + /* Make certain that bit 0 is set in the main entry address. This + * is only an issue when NXFLAT is enabled. NXFLAT doesn't know + * anything about thumb; the addresses that NXFLAT sets are based + * on file header info and won't have bit 0 set. + */ + +#ifdef CONFIG_NXFLAT + tcb->entry.main = (main_t)((uint32_t)tcb->entry.main | 1); +#endif +#endif /* CONFIG_PIC */ + +#ifdef CONFIG_ARMV7M_CMNVECTOR + /* Set privileged- or unprivileged-mode, depending on how NuttX is + * configured and what kind of thread is being started. + * + * If the kernel build is not selected, then all threads run in + * privileged thread mode. + * + * If FPU support is not configured, set the bit that indicates that + * the context does not include the volatile FP registers. + */ + + xcp->regs[REG_EXC_RETURN] = EXC_RETURN_BASE | EXC_RETURN_THREAD_MODE; + +#ifndef CONFIG_ARCH_FPU + + xcp->regs[REG_EXC_RETURN] |= EXC_RETURN_STD_CONTEXT; + +#else + + xcp->regs[REG_FPSCR] = 0; // XXX initial FPSCR should be configurable + xcp->regs[REG_FPReserved] = 0; + +#endif + +#ifdef CONFIG_NUTTX_KERNEL + if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL) + { + /* It is a normal task or a pthread. Set user mode */ + + xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PROCESS_STACK; + } +#endif + +#else /* CONFIG_ARMV7M_CMNVECTOR */ + + /* Set privileged- or unprivileged-mode, depending on how NuttX is + * configured and what kind of thread is being started. + * + * If the kernel build is not selected, then all threads run in + * privileged thread mode. + */ + +#ifdef CONFIG_NUTTX_KERNEL + if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL) + { + /* It is a kernel thread.. set privileged thread mode */ + + xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; + } + else + { + /* It is a normal task or a pthread. Set user mode */ + + xcp->regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; + } +#endif +#endif /* CONFIG_ARMV7M_CMNVECTOR */ + + /* Enable or disable interrupts, based on user configuration */ + +#ifdef CONFIG_SUPPRESS_INTERRUPTS + xcp->regs[REG_PRIMASK] = 1; +#endif +} diff --git a/nuttx/arch/arm/src/armv7-m/up_memfault.c b/nuttx/arch/arm/src/armv7-m/up_memfault.c new file mode 100644 index 0000000000..bbe3f6573f --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_memfault.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_memfault.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "up_arch.h" +#include "os_internal.h" +#include "nvic.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#undef DEBUG_MEMFAULTS /* Define to debug memory management faults */ + +#ifdef DEBUG_MEMFAULTS +# define mfdbg(format, arg...) lldbg(format, ##arg) +#else +# define mfdbg(x...) +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_memfault + * + * Description: + * This is Memory Management Fault exception handler. Normally we get here + * when the Cortex M3 MPU is enabled and an MPU fault is detected. However, + * I understand that there are other error conditions that can also generate + * memory management faults. + * + ****************************************************************************/ + +int up_memfault(int irq, FAR void *context) +{ + /* Dump some memory management fault info */ + + (void)irqsave(); + lldbg("PANIC!!! Memory Management Fault:\n"); + mfdbg(" IRQ: %d context: %p\n", irq, regs); + lldbg(" CFAULTS: %08x MMFAR: %08x\n", + getreg32(NVIC_CFAULTS), getreg32(NVIC_MEMMANAGE_ADDR)); + mfdbg(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n", + regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3], + regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]); + mfdbg(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n", + regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11], + regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]); + mfdbg(" PSR=%08x\n", regs[REG_XPSR]); + + PANIC(OSERR_UNEXPECTEDISR); + return OK; +} diff --git a/nuttx/arch/arm/src/armv7-m/up_mpu.c b/nuttx/arch/arm/src/armv7-m/up_mpu.c new file mode 100644 index 0000000000..27936562c9 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_mpu.c @@ -0,0 +1,176 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_mpu.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "mpu.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This set represents the set of disabled memory sub-regions. A bit set + * corresponds to a disabled sub-region; the LS bit corresponds to the first + * region. The array is indexed by the number of subregions: 0 means no sub- + * regions (0xff), and 0 means all subregions but one (0x00). + */ + +static const void uint8_t g_regionmap[9] = +{ + 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00 +}; + +/* The next available region number */ + +static uint8_t g_region; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mpu_allocregion + * + * Description: + * Allocate the next region + * + * Assumptions: + * - Regions are never deallocated + * - Regions are only allocated early in initialization, so nothing + * special is require; + * + ****************************************************************************/ + +unsigned int mpu_allocregion(void) +{ + return (unsigned int)g_region++; +} + +/**************************************************************************** + * Name: mpu_log2regionsize + * + * Description: + * Determine the smallest value of l2size (log base 2 size) such that the + * following is true: + * + * size <= (1 << l2size) + * + ****************************************************************************/ + +uint8_t mpu_log2regionsize(size_t size) +{ + /* The minimum permitted region size is 16 bytes (log2(16) = 4. */ + + uint32_t l2size; + for (l2size = 4; l2size < 32 && size > (1 << l2size); size++); + return l2size; +} + +/**************************************************************************** + * Name: mpu_subregion + * + * Description: + * Given the size of the (1) memory to be mapped and (2) the log2 size + * of the mapping to use, determine the minimal sub-region set to span + * that memory region. + * + * Assumption: + * l2size has the same properties as the return value from + * mpu_log2regionsize() + * + ****************************************************************************/ + +uint32_t mpu_subregion(size_t size, uint8_t l2size) +{ + unsigned int nsrs + uint32_t asize; + uint32_t mask; + + /* Eight subregions are support. The representation is as an 8-bit + * value with the LS bit corresponding to subregion 0. A bit is set + * to disable the sub-region. + * + * l2size: Log2 of the actual region size is <= (1 << l2size); + */ + + DEBUGASSERT(lsize > 3 && size <= (1 << l2size)); + + /* Examples with l2size = 12: + * + * Shifted Adjusted Number Sub-Region + * Size Mask Size Shift Sub-Regions Bitset + * 0x1000 0x01ff 0x1000 9 8 0x00 + * 0x0c00 0x01ff 0x0c00 9 6 0x03 + * 0x0c40 0x01ff 0x0e00 9 7 0x01 + */ + + if (l2size < 32) + { + mask = ((1 << lsize)-1) >> 3; /* Shifted mask */ + } + + /* The 4Gb region size is a special case */ + + else + { + /* NOTE: There is no way to represent a 4Gb region size in the 32-bit + * input. + */ + + mask = 0x1fffffff; /* Shifted mask */ + } + + asize = (size + mask) & ~mask; /* Adjusted size */ + nsrs = asize >> (lsize-3); /* Number of subregions */ + return g_regionmap[nsrs]; +} + + + diff --git a/nuttx/arch/arm/src/armv7-m/up_releasepending.c b/nuttx/arch/arm/src/armv7-m/up_releasepending.c new file mode 100755 index 0000000000..2f0d4dc39b --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_releasepending.c @@ -0,0 +1,129 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_releasepending.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_release_pending + * + * Description: + * Release and ready-to-run tasks that have + * collected in the pending task list. This can call a + * context switch if a new task is placed at the head of + * the ready to run list. + * + ****************************************************************************/ + +void up_release_pending(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + + slldbg("From TCB=%p\n", rtcb); + + /* Merge the g_pendingtasks list into the g_readytorun task list */ + + /* sched_lock(); */ + if (sched_mergepending()) + { + /* The currently active task has changed! We will need to switch + * contexts. First check if we are operating in interrupt context. + */ + + if (current_regs) + { + /* Yes, then we have to do things differently. Just copy the + * current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + slldbg("New Active Task TCB=%p\n", rtcb); + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* No, then we will need to perform the user context switch */ + + else + { + /* Switch context to the context of the task at the head of the + * ready to run list. + */ + + _TCB *nexttcb = (_TCB*)g_readytorun.head; + up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); + + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ + } + } +} diff --git a/nuttx/arch/arm/src/armv7-m/up_reprioritizertr.c b/nuttx/arch/arm/src/armv7-m/up_reprioritizertr.c new file mode 100755 index 0000000000..f1c961b15e --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_reprioritizertr.c @@ -0,0 +1,182 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_reprioritizertr.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_reprioritize_rtr + * + * Description: + * Called when the priority of a running or + * ready-to-run task changes and the reprioritization will + * cause a context switch. Two cases: + * + * 1) The priority of the currently running task drops and the next + * task in the ready to run list has priority. + * 2) An idle, ready to run task's priority has been raised above the + * the priority of the current, running task and it now has the + * priority. + * + * Inputs: + * tcb: The TCB of the task that has been reprioritized + * priority: The new task priority + * + ****************************************************************************/ + +void up_reprioritize_rtr(_TCB *tcb, uint8_t priority) +{ + /* Verify that the caller is sane */ + + if (tcb->task_state < FIRST_READY_TO_RUN_STATE || + tcb->task_state > LAST_READY_TO_RUN_STATE || + priority < SCHED_PRIORITY_MIN || + priority > SCHED_PRIORITY_MAX) + { + PANIC(OSERR_BADREPRIORITIZESTATE); + } + else + { + _TCB *rtcb = (_TCB*)g_readytorun.head; + bool switch_needed; + + slldbg("TCB=%p PRI=%d\n", tcb, priority); + + /* Remove the tcb task from the ready-to-run list. + * sched_removereadytorun will return true if we just removed the head + * of the ready to run list. + */ + + switch_needed = sched_removereadytorun(tcb); + + /* Setup up the new task priority */ + + tcb->sched_priority = (uint8_t)priority; + + /* Return the task to the ready-to-run task list. sched_addreadytorun + * will return true if the task was added to the head of ready-to-run + * list. We will need to perform a context switch only if the + * EXCLUSIVE or of the two calls is non-zero (i.e., one and only one + * the calls changes the head of the ready-to-run list). + */ + + switch_needed ^= sched_addreadytorun(tcb); + + /* Now, perform the context switch if one is needed (i.e. if the head + * of the ready-to-run list is no longer the same). + */ + + if (switch_needed) + { + /* If we are going to do a context switch, then now is the right + * time to add any pending tasks back into the ready-to-run list. + * task list now + */ + + if (g_pendingtasks.head) + { + sched_mergepending(); + } + + /* Are we in an interrupt handler? */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + slldbg("New Active Task TCB=%p\n", rtcb); + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* No, then we will need to perform the user context switch */ + + else + { + /* Switch context to the context of the task at the head of the + * ready to run list. + */ + + _TCB *nexttcb = (_TCB*)g_readytorun.head; + up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); + + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ + } + } + } +} diff --git a/nuttx/arch/arm/src/armv7-m/up_saveusercontext.S b/nuttx/arch/arm/src/armv7-m/up_saveusercontext.S new file mode 100755 index 0000000000..c8da074303 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_saveusercontext.S @@ -0,0 +1,104 @@ +/************************************************************************************ + * arch/arm/src/armv7-m/up_saveusercontext.S + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +#include "nvic.h" +#include "svcall.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Global Symbols + ************************************************************************************/ + + .syntax unified + .thumb + .file "up_saveusercontext.S" + +/************************************************************************************ + * Macros + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_saveusercontext + * + * Description: + * Save the current thread context. Full prototype is: + * + * int up_saveusercontext(uint32_t *saveregs); + * + * Return: + * 0: Normal return + * 1: Context switch return + * + ************************************************************************************/ + + .text + .thumb_func + .globl up_saveusercontext + .type up_saveusercontext, function +up_saveusercontext: + + /* Perform the System call with R0=0 and R1=regs */ + + mov r1, r0 /* R1: regs */ + mov r0, #SYS_save_context /* R0: save context (also return value) */ + svc 0 /* Force synchronous SVCall (or Hard Fault) */ + + /* There are two return conditions. On the first return, R0 (the + * return value will be zero. On the second return we need to + * force R0 to be 1. + */ + + add r2, r1, #(4*REG_R0) + mov r3, #1 + str r3, [r2, #0] + bx lr /* "normal" return with r0=0 or + * context switch with r0=1 */ + .size up_saveusercontext, .-up_saveusercontext + .end + diff --git a/nuttx/arch/arm/src/armv7-m/up_schedulesigaction.c b/nuttx/arch/arm/src/armv7-m/up_schedulesigaction.c new file mode 100644 index 0000000000..9e6dbd14b4 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_schedulesigaction.c @@ -0,0 +1,208 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_schedulesigaction.c + * + * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "psr.h" +#include "os_internal.h" +#include "up_internal.h" +#include "up_arch.h" + +#ifndef CONFIG_DISABLE_SIGNALS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_schedule_sigaction + * + * Description: + * This function is called by the OS when one or more + * signal handling actions have been queued for execution. + * The architecture specific code must configure things so + * that the 'igdeliver' callback is executed on the thread + * specified by 'tcb' as soon as possible. + * + * This function may be called from interrupt handling logic. + * + * This operation should not cause the task to be unblocked + * nor should it cause any immediate execution of sigdeliver. + * Typically, a few cases need to be considered: + * + * (1) This function may be called from an interrupt handler + * During interrupt processing, all xcptcontext structures + * should be valid for all tasks. That structure should + * be modified to invoke sigdeliver() either on return + * from (this) interrupt or on some subsequent context + * switch to the recipient task. + * (2) If not in an interrupt handler and the tcb is NOT + * the currently executing task, then again just modify + * the saved xcptcontext structure for the recipient + * task so it will invoke sigdeliver when that task is + * later resumed. + * (3) If not in an interrupt handler and the tcb IS the + * currently executing task -- just call the signal + * handler now. + * + ****************************************************************************/ + +void up_schedule_sigaction(_TCB *tcb, sig_deliver_t sigdeliver) +{ + /* Refuse to handle nested signal actions */ + + sdbg("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver); + + if (!tcb->xcp.sigdeliver) + { + irqstate_t flags; + + /* Make sure that interrupts are disabled */ + + flags = irqsave(); + + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ + + sdbg("rtcb=0x%p current_regs=0x%p\n", g_readytorun.head, current_regs); + + if (tcb == (_TCB*)g_readytorun.head) + { + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. + */ + + if (!current_regs) + { + /* In this case just deliver the signal now. */ + + sigdeliver(tcb); + } + + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following + * logic would fail in the strange case where we are in an + * interrupt handler, the thread is signalling itself, but + * a context switch to another task has occurred so that + * current_regs does not refer to the thread at g_readytorun.head! + */ + + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pc = current_regs[REG_PC]; + tcb->xcp.saved_primask = current_regs[REG_PRIMASK]; + tcb->xcp.saved_xpsr = current_regs[REG_XPSR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + current_regs[REG_PC] = (uint32_t)up_sigdeliver; + current_regs[REG_PRIMASK] = 1; + current_regs[REG_XPSR] = ARMV7M_XPSR_T; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + up_savestate(tcb->xcp.regs); + } + } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; + tcb->xcp.saved_primask = tcb->xcp.regs[REG_PRIMASK]; + tcb->xcp.saved_xpsr = tcb->xcp.regs[REG_XPSR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver; + tcb->xcp.regs[REG_PRIMASK] = 1; + tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T; + } + + irqrestore(flags); + } +} + +#endif /* !CONFIG_DISABLE_SIGNALS */ diff --git a/nuttx/arch/arm/src/armv7-m/up_sigdeliver.c b/nuttx/arch/arm/src/armv7-m/up_sigdeliver.c new file mode 100644 index 0000000000..3c340b8d3c --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_sigdeliver.c @@ -0,0 +1,142 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_sigdeliver.c + * + * Copyright (C) 2009-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "os_internal.h" +#include "up_internal.h" +#include "up_arch.h" + +#ifndef CONFIG_DISABLE_SIGNALS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_sigdeliver + * + * Description: + * This is the a signal handling trampoline. When a signal action was + * posted. The task context was mucked with and forced to branch to this + * location with interrupts disabled. + * + ****************************************************************************/ + +void up_sigdeliver(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + uint32_t regs[XCPTCONTEXT_REGS]; + sig_deliver_t sigdeliver; + + /* Save the errno. This must be preserved throughout the signal handling + * so that the user code final gets the correct errno value (probably + * EINTR). + */ + + int saved_errno = rtcb->pterrno; + + up_ledon(LED_SIGNAL); + + sdbg("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", + rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); + ASSERT(rtcb->xcp.sigdeliver != NULL); + + /* Save the real return state on the stack. */ + + up_copystate(regs, rtcb->xcp.regs); + regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_PRIMASK] = rtcb->xcp.saved_primask; + regs[REG_XPSR] = rtcb->xcp.saved_xpsr; + + /* Get a local copy of the sigdeliver function pointer. We do this so that + * we can nullify the sigdeliver function pointer in the TCB and accept + * more signal deliveries while processing the current pending signals. + */ + + sigdeliver = rtcb->xcp.sigdeliver; + rtcb->xcp.sigdeliver = NULL; + + /* Then restore the task interrupt state */ + + irqrestore((uint16_t)regs[REG_PRIMASK]); + + /* Deliver the signals */ + + sigdeliver(rtcb); + + /* Output any debug messages BEFORE restoring errno (because they may + * alter errno), then disable interrupts again and restore the original + * errno that is needed by the user logic (it is probably EINTR). + */ + + sdbg("Resuming\n"); + (void)irqsave(); + rtcb->pterrno = saved_errno; + + /* Then restore the correct state for this thread of + * execution. + */ + + up_ledoff(LED_SIGNAL); + up_fullcontextrestore(regs); +} + +#endif /* !CONFIG_DISABLE_SIGNALS */ + diff --git a/nuttx/arch/arm/src/armv7-m/up_stackcheck.c b/nuttx/arch/arm/src/armv7-m/up_stackcheck.c new file mode 100644 index 0000000000..e8f02a863b --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_stackcheck.c @@ -0,0 +1,40 @@ + + +void __cyg_profile_func_enter(void *func, void *caller) __attribute__((naked, no_instrument_function)); +void __cyg_profile_func_exit(void *func, void *caller) __attribute__((naked, no_instrument_function)); +void __stack_overflow_trap(void) __attribute__((naked, no_instrument_function)); + +void +__stack_overflow_trap(void) +{ + /* if we get here, the stack has overflowed */ + asm ( "b ."); +} + +void +__cyg_profile_func_enter(void *func, void *caller) +{ + asm volatile ( + " mrs r2, ipsr \n" /* Check whether we are in interrupt mode */ + " cmp r2, #0 \n" /* since we don't switch r10 on interrupt entry, we */ + " bne 2f \n" /* can't detect overflow of the interrupt stack. */ + " \n" + " sub r2, sp, #68 \n" /* compute stack pointer as though we just stacked a full frame */ + " mrs r1, control \n" /* Test CONTROL.FPCA to see whether we also need room for the FP */ + " tst r1, #4 \n" /* context. */ + " beq 1f \n" + " sub r2, r2, #136 \n" /* subtract FP context frame size */ + "1: \n" + " cmp r2, r10 \n" /* compare stack with limit */ + " bgt 2f \n" /* stack is above limit and thus OK */ + " b __stack_overflow_trap\n" + "2: \n" + " bx lr \n" + ); +} + +void +__cyg_profile_func_exit(void *func, void *caller) +{ + asm volatile("bx lr"); +} diff --git a/nuttx/arch/arm/src/armv7-m/up_svcall.c b/nuttx/arch/arm/src/armv7-m/up_svcall.c new file mode 100644 index 0000000000..5a4d64fe20 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_svcall.c @@ -0,0 +1,363 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_svcall.c + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_NUTTX_KERNEL +# include +#endif + +#include "svcall.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +#undef SYSCALL_INTERRUPTIBLE +#if defined(CONFIG_NUTTX_KERNEL) +# if CONFIG_ARCH_INTERRUPTSTACK > 3 +# warning "CONFIG_ARCH_INTERRUPTSTACK and CONFIG_NUTTX_KERNEL are incompatible" +# warning "options as currently implemented. Interrupts will have to be disabled" +# warning "during SYScall processing to avoid un-handled nested interrupts" +# else +# define SYSCALL_INTERRUPTIBLE 1 +# endif +#endif + +/* Debug ********************************************************************/ +/* Debug output from this file may interfere with context switching! To get + * debug output you must enabled the following in your NuttX configuration: + * + * CONFIG_DEBUG and CONFIG_DEBUG_SCHED + * + * And you must explicitly define DEBUG_SVCALL below: + */ + +#undef DEBUG_SVCALL /* Define to debug SVCall */ +#ifdef DEBUG_SVCALL +# define svcdbg(format, arg...) slldbg(format, ##arg) +#else +# define svcdbg(x...) +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dispatch_syscall + * + * Description: + * Dispatch a system call to the appropriate handling logic. + * + ****************************************************************************/ + +#ifdef CONFIG_NUTTX_KERNEL +static inline void dispatch_syscall(uint32_t *regs) +{ + uint32_t cmd = regs[REG_R0]; + FAR _TCB *rtcb = sched_self(); + uintptr_t ret = (uintptr_t)ERROR; + + /* Verify the the SYS call number is within range */ + + if (cmd < SYS_maxsyscall) + { + /* Report error and return ERROR */ + + slldbg("ERROR: Bad SYS call: %d\n", cmd); + } + else + { + /* The index into the syscall table is offset by the number of architecture- + * specific reserved entries at the beginning of the SYS call number space. + */ + + int index = cmd - CONFIG_SYS_RESERVED; + + /* Enable interrupts while the SYSCALL executes */ + +#ifdef SYSCALL_INTERRUPTIBLE + irqenable(); +#endif + + /* Call the correct stub for each SYS call, based on the number of parameters */ + + svcdbg("Calling stub%d at %p\n", index, g_stubloopkup[index].stub0); + + switch (g_stubnparms[index]) + { + /* No parameters */ + + case 0: + ret = g_stublookup[index].stub0(); + break; + + /* Number of parameters: 1 */ + + case 1: + ret = g_stublookup[index].stub1(regs[REG_R1]); + break; + + /* Number of parameters: 2 */ + + case 2: + ret = g_stublookup[index].stub2(regs[REG_R1], regs[REG_R2]); + break; + + /* Number of parameters: 3 */ + + case 3: + ret = g_stublookup[index].stub3(regs[REG_R1], regs[REG_R2], + regs[REG_R3]); + break; + + /* Number of parameters: 4 */ + + case 4: + ret = g_stublookup[index].stub4(regs[REG_R1], regs[REG_R2], + regs[REG_R3], regs[REG_R4]); + break; + + /* Number of parameters: 5 */ + + case 5: + ret = g_stublookup[index].stub5(regs[REG_R1], regs[REG_R2], + regs[REG_R3], regs[REG_R4], + regs[REG_R5]); + break; + + /* Number of parameters: 6 */ + + case 6: + ret = g_stublookup[index].stub6(regs[REG_R1], regs[REG_R2], + regs[REG_R3], regs[REG_R4], + regs[REG_R5], regs[REG_R6]); + break; + + /* Unsupported number of paramters. Report error and return ERROR */ + + default: + slldbg("ERROR: Bad SYS call %d number parameters %d\n", + cmd, g_stubnparms[index]); + break; + } + +#ifdef SYSCALL_INTERRUPTIBLE + irqdisable(); +#endif + } + + /* Set up the return value. First, check if a context switch occurred. + * In this case, regs will no longer be the same as current_regs. In + * the case of a context switch, we will have to save the return value + * in the TCB where it can be returned later when the task is restarted. + */ + + if (regs != current_regs) + { + regs = rtcb->xcp.regs; + } + + /* Then return the result in R0 */ + + svcdbg("Return value regs: %p value: %d\n", regs, ret); + regs[REG_R0] = (uint32_t)ret; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_svcall + * + * Description: + * This is SVCall exception handler that performs context switching + * + ****************************************************************************/ + +int up_svcall(int irq, FAR void *context) +{ + uint32_t *regs = (uint32_t*)context; + + DEBUGASSERT(regs && regs == current_regs); + + /* The SVCall software interrupt is called with R0 = system call command + * and R1..R7 = variable number of arguments depending on the system call. + */ + + svcdbg("SVCALL Entry: regs: %p cmd: %d\n", regs, regs[REG_R0]); + svcdbg(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n", + regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3], + regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]); + svcdbg(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n", + regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11], + regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]); + svcdbg(" PSR=%08x\n", regs[REG_XPSR]); + + /* Handle the SVCall according to the command in R0 */ + + switch (regs[REG_R0]) + { + /* R0=SYS_save_context: This is a save context command: + * + * int up_saveusercontext(uint32_t *saveregs); + * + * At this point, the following values are saved in context: + * + * R0 = SYS_save_context + * R1 = saveregs + * + * In this case, we simply need to copy the current regsters to the + * save register space references in the saved R1 and return. + */ + + case SYS_save_context: + { + DEBUGASSERT(regs[REG_R1] != 0); + memcpy((uint32_t*)regs[REG_R1], regs, XCPTCONTEXT_SIZE); +#if defined(CONFIG_ARCH_FPU) && !defined(CONFIG_ARMV7M_CMNVECTOR) + up_savefpu((uint32_t*)regs[REG_R1]); +#endif + } + break; + + /* R0=SYS_restore_context: This a restore context command: + * + * void up_fullcontextrestore(uint32_t *restoreregs) __attribute__ ((noreturn)); + * + * At this point, the following values are saved in context: + * + * R0 = SYS_restore_context + * R1 = restoreregs + * + * In this case, we simply need to set current_regs to restore register + * area referenced in the saved R1. context == current_regs is the normal + * exception return. By setting current_regs = context[R1], we force + * the return to the saved context referenced in R1. + */ + + case SYS_restore_context: + { + DEBUGASSERT(regs[REG_R1] != 0); + current_regs = (uint32_t*)regs[REG_R1]; + } + break; + + /* R0=SYS_switch_context: This a switch context command: + * + * void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs); + * + * At this point, the following values are saved in context: + * + * R0 = 1 + * R1 = saveregs + * R2 = restoreregs + * + * In this case, we do both: We save the context registers to the save + * register area reference by the saved contents of R1 and then set + * current_regs to to the save register area referenced by the saved + * contents of R2. + */ + + case SYS_switch_context: + { + DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0); + memcpy((uint32_t*)regs[REG_R1], regs, XCPTCONTEXT_SIZE); +#if defined(CONFIG_ARCH_FPU) && !defined(CONFIG_ARMV7M_CMNVECTOR) + up_savefpu((uint32_t*)regs[REG_R1]); +#endif + current_regs = (uint32_t*)regs[REG_R2]; + } + break; + + /* This is not an architecture-specific system call. If NuttX is built + * as a standalone kernel with a system call interface, then all of the + * additional system calls must be handled as in the default case. + */ + + default: +#ifdef CONFIG_NUTTX_KERNEL + dispatch_syscall(regs); +#else + slldbg("ERROR: Bad SYS call: %d\n", regs[REG_R0]); +#endif + break; + } + + /* Report what happened. That might difficult in the case of a context switch */ + + if (regs != current_regs) + { + svcdbg("SVCall Return: Context switch!\n"); + svcdbg(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n", + current_regs[REG_R0], current_regs[REG_R1], current_regs[REG_R2], current_regs[REG_R3], + current_regs[REG_R4], current_regs[REG_R5], current_regs[REG_R6], current_regs[REG_R7]); + svcdbg(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n", + current_regs[REG_R8], current_regs[REG_R9], current_regs[REG_R10], current_regs[REG_R11], + current_regs[REG_R12], current_regs[REG_R13], current_regs[REG_R14], current_regs[REG_R15]); + svcdbg(" PSR=%08x\n", current_regs[REG_XPSR]); + } + else + { + svcdbg("SVCall Return: %d\n", regs[REG_R0]); + } + + return OK; +} diff --git a/nuttx/arch/arm/src/armv7-m/up_switchcontext.S b/nuttx/arch/arm/src/armv7-m/up_switchcontext.S new file mode 100755 index 0000000000..854f6fa162 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_switchcontext.S @@ -0,0 +1,97 @@ +/************************************************************************************ + * arch/arm/src/armv7-m/up_switchcontext.S + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +#include "nvic.h" +#include "svcall.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Global Symbols + ************************************************************************************/ + + .syntax unified + .thumb + .file "up_switchcontext.S" + +/************************************************************************************ + * Macros + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_switchcontext + * + * Description: + * Save the current thread context and restore the specified context. + * Full prototype is: + * + * void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs); + * + * Return: + * None + * + ************************************************************************************/ + + .thumb_func + .globl up_switchcontext + .type up_switchcontext, function +up_switchcontext: + + /* Perform the System call with R0=1, R1=saveregs, R2=restoreregs */ + + mov r2, r1 /* R2: restoreregs */ + mov r1, r0 /* R1: saveregs */ + mov r0, #SYS_switch_context /* R0: context switch */ + svc 0 /* Force synchronous SVCall (or Hard Fault) */ + + /* This call should not return */ + + bx lr /* Unnecessary ... will not return */ + .size up_switchcontext, .-up_switchcontext + .end + diff --git a/nuttx/arch/arm/src/armv7-m/up_unblocktask.c b/nuttx/arch/arm/src/armv7-m/up_unblocktask.c new file mode 100755 index 0000000000..da10f03763 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_unblocktask.c @@ -0,0 +1,157 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_unblocktask.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#include "clock_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_unblock_task + * + * Description: + * A task is currently in an inactive task list + * but has been prepped to execute. Move the TCB to the + * ready-to-run list, restore its context, and start execution. + * + * Inputs: + * tcb: Refers to the tcb to be unblocked. This tcb is + * in one of the waiting tasks lists. It must be moved to + * the ready-to-run list and, if it is the highest priority + * ready to run taks, executed. + * + ****************************************************************************/ + +void up_unblock_task(_TCB *tcb) +{ + /* Verify that the context switch can be performed */ + + if ((tcb->task_state < FIRST_BLOCKED_STATE) || + (tcb->task_state > LAST_BLOCKED_STATE)) + { + PANIC(OSERR_BADUNBLOCKSTATE); + } + else + { + _TCB *rtcb = (_TCB*)g_readytorun.head; + + /* Remove the task from the blocked task list */ + + sched_removeblocked(tcb); + + /* Reset its timeslice. This is only meaningful for round + * robin tasks but it doesn't here to do it for everything + */ + +#if CONFIG_RR_INTERVAL > 0 + tcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; +#endif + + /* Add the task in the correct location in the prioritized + * g_readytorun task list + */ + + if (sched_addreadytorun(tcb)) + { + /* The currently active task has changed! We need to do + * a context switch to the new task. + * + * Are we in an interrupt handler? + */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* No, then we will need to perform the user context switch */ + + else + { + /* Switch context to the context of the task at the head of the + * ready to run list. + */ + + _TCB *nexttcb = (_TCB*)g_readytorun.head; + up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); + + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ + } + } + } +} diff --git a/nuttx/arch/arm/src/armv7-m/up_vectors.c b/nuttx/arch/arm/src/armv7-m/up_vectors.c new file mode 100644 index 0000000000..b85ac92462 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_vectors.c @@ -0,0 +1,95 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_vectors.c + * + * Copyright (C) 2012 Michael Smith. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +/************************************************************************************ + * Preprocessor Definitions + ************************************************************************************/ + +#define IDLE_STACK ((unsigned)&_ebss+CONFIG_IDLETHREAD_STACKSIZE-4) + +#ifndef ARMV7M_PERIPHERAL_INTERRUPTS +# error ARMV7M_PERIPHERAL_INTERRUPTS must be defined to the number of I/O interrupts to be supported +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Chip-specific entrypoint */ + +extern void __start(void); + +/* Common exception entrypoint */ + +extern void exception_common(void); + +/************************************************************************************ + * Public data + ************************************************************************************/ + +/* Provided by the linker script to indicate the end of the BSS */ + +extern char _ebss; + +/* The v7m vector table consists of an array of function pointers, with the first + * slot (vector zero) used to hold the initial stack pointer. + * + * As all exceptions (interrupts) are routed via exception_common, we just need to + * fill this array with pointers to it. + * + * Note that the [ ... ] desginated initialiser is a GCC extension. + */ + +unsigned _vectors[] __attribute__((section(".vectors"))) = + { + /* Initial stack */ + + IDLE_STACK, + + /* Reset exception handler */ + + (unsigned)&__start, + + /* Vectors 2 - n point directly at the generic handler */ + + [2 ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)] = (unsigned)&exception_common + }; diff --git a/nuttx/arch/arm/src/common/up_allocateheap.c b/nuttx/arch/arm/src/common/up_allocateheap.c new file mode 100644 index 0000000000..fbd1421a74 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_allocateheap.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * arch/arm/src/common/up_allocateheap.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "up_arch.h" +#include "up_internal.h" + +/**************************************************************************** + * Private Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocate_heap + * + * Description: + * The heap may be statically allocated by + * defining CONFIG_HEAP_BASE and CONFIG_HEAP_SIZE. If these + * are not defined, then this function will be called to + * dynamically set aside the heap region. + * + ****************************************************************************/ + +void up_allocate_heap(FAR void **heap_start, size_t *heap_size) +{ + up_ledon(LED_HEAPALLOCATE); + *heap_start = (FAR void*)g_heapbase; + *heap_size = CONFIG_DRAM_END - g_heapbase; +} diff --git a/nuttx/arch/arm/src/common/up_arch.h b/nuttx/arch/arm/src/common/up_arch.h new file mode 100644 index 0000000000..b612f6af25 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_arch.h @@ -0,0 +1,105 @@ +/**************************************************************************** + * arch/arm/src/common/up_arch.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef ___ARCH_ARM_SRC_COMMON_UP_ARCH_H +#define ___ARCH_ARM_SRC_COMMON_UP_ARCH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +# define getreg8(a) (*(volatile uint8_t *)(a)) +# define putreg8(v,a) (*(volatile uint8_t *)(a) = (v)) +# define getreg32(a) (*(volatile uint32_t *)(a)) +# define putreg32(v,a) (*(volatile uint32_t *)(a) = (v)) + +/* Some compiler options will convert short loads and stores into byte loads + * and stores. We don't want this to happen for IO reads and writes! + */ + +/* # define getreg16(a) (*(volatile uint16_t *)(a)) */ +static inline uint16_t getreg16(unsigned int addr) +{ + uint16_t retval; + __asm__ __volatile__("\tldrh %0, [%1]\n\t" : "=r"(retval) : "r"(addr)); + return retval; +} + +/* define putreg16(v,a) (*(volatile uint16_t *)(a) = (v)) */ +static inline void putreg16(uint16_t val, unsigned int addr) +{ + __asm__ __volatile__("\tstrh %0, [%1]\n\t": : "r"(val), "r"(addr)); +} + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Atomic modification of registers */ + +EXTERN void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits); +EXTERN void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits); +EXTERN void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* ___ARCH_ARM_SRC_COMMON_UP_ARCH_H */ diff --git a/nuttx/arch/arm/src/common/up_checkstack.c b/nuttx/arch/arm/src/common/up_checkstack.c new file mode 100644 index 0000000000..6c13f63d13 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_checkstack.c @@ -0,0 +1,147 @@ +/**************************************************************************** + * arch/arm/src/common/up_checkstack.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "os_internal.h" + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_check_stack + * + * Description: + * Determine (approximately) how much stack has been used be searching the + * stack memory for a high water mark. That is, the deepest level of the + * stack that clobbered some recognizable marker in the stack memory. + * + * Input Parameters: + * None + * + * Returned value: + * The estimated amount of stack space used. + * + ****************************************************************************/ + +size_t up_check_tcbstack(FAR _TCB *tcb) +{ + FAR uint32_t *ptr; + size_t mark; + + /* The ARM uses a push-down stack: the stack grows toward lower addresses + * in memory. We need to start at the lowest address in the stack memory + * allocation and search to higher addresses. The first word we encounter + * that does not have the magic value is the high water mark. + */ + + for (ptr = (FAR uint32_t *)tcb->stack_alloc_ptr, mark = tcb->adj_stack_size/4; + *ptr == 0xDEADBEEF && mark > 0; + ptr++, mark--); + + /* If the stack is completely used, then this might mean that the stack + * overflowed from above (meaning that the stack is too small), or may + * have been overwritten from below meaning that some other stack or data + * structure overflowed. + * + * If you see returned values saying that the entire stack is being used + * then enable the following logic to see it there are unused areas in the + * middle of the stack. + */ + +#if 0 + if (mark + 16 > tcb->adj_stack_size/4) + { + int i, j; + + ptr = (FAR uint32_t *)tcb->stack_alloc_ptr; + for (i = 0; i < tcb->adj_stack_size; i += 4*64) + { + for (j = 0; j < 64; j++) + { + int ch; + if (*ptr++ == 0xDEADBEEF) + { + ch = '.'; + } + else + { + ch = 'X'; + } + up_putc(ch); + } + up_putc('\n'); + } + } +#endif + + /* Return our guess about how much stack space was used */ + + return mark*4; +} + +size_t up_check_stack(void) +{ + return up_check_tcbstack((FAR _TCB*)g_readytorun.head); +} + +size_t up_check_stack_remain(void) +{ + return ((FAR _TCB*)g_readytorun.head)->adj_stack_size - up_check_tcbstack((FAR _TCB*)g_readytorun.head); +} + +#endif /* CONFIG_DEBUG && CONFIG_DEBUG_STACK */ diff --git a/nuttx/arch/arm/src/common/up_createstack.c b/nuttx/arch/arm/src/common/up_createstack.c new file mode 100644 index 0000000000..3d6dfef454 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_createstack.c @@ -0,0 +1,197 @@ +/**************************************************************************** + * arch/arm/src/common/up_createstack.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* ARM requires at least a 4-byte stack alignment. For use with EABI and + * floating point, the stack must be aligned to 8-byte addresses. + */ + +#ifndef CONFIG_STACK_ALIGNMENT + +/* The symbol __ARM_EABI__ is defined by GCC if EABI is being used. If you + * are not using GCC, make sure that CONFIG_STACK_ALIGNMENT is set correctly! + */ + +# ifdef __ARM_EABI__ +# define CONFIG_STACK_ALIGNMENT 8 +# else +# define CONFIG_STACK_ALIGNMENT 4 +# endif +#endif + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (CONFIG_STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Name: memset32 + * + * On most larger then 8 bit archs this will need to be word aligned so + * so maybe some checks should be put in place? + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK) +static void *memset32(void *s, uint32_t c, size_t n) +{ + uint32_t *p = (uint32_t *)s; + while (n-- > 0) *p++ = c; + return s; +} +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_create_stack + * + * Description: + * Allocate a stack for a new thread and setup + * up stack-related information in the TCB. + * + * The following TCB fields must be initialized: + * adj_stack_size: Stack size after adjustment for hardware, + * processor, etc. This value is retained only for debug + * purposes. + * stack_alloc_ptr: Pointer to allocated stack + * adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The + * initial value of the stack pointer. + * + * Inputs: + * tcb: The TCB of new task + * stack_size: The requested stack size. At least this much + * must be allocated. + ****************************************************************************/ + +int up_create_stack(_TCB *tcb, size_t stack_size) +{ + if (tcb->stack_alloc_ptr && + tcb->adj_stack_size != stack_size) + { + sched_free(tcb->stack_alloc_ptr); + tcb->stack_alloc_ptr = NULL; + } + + if (!tcb->stack_alloc_ptr) + { +#ifdef CONFIG_DEBUG + tcb->stack_alloc_ptr = (uint32_t*)kzalloc(stack_size); +#else + tcb->stack_alloc_ptr = (uint32_t*)kmalloc(stack_size); +#endif + } + + if (tcb->stack_alloc_ptr) + { + size_t top_of_stack; + size_t size_of_stack; + + /* The ARM uses a push-down stack: the stack grows toward lower + * addresses in memory. The stack pointer register, points to + * the lowest, valid work address (the "top" of the stack). Items + * on the stack are referenced as positive word offsets from sp. + */ + + top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4; + + /* The ARM stack must be aligned; 4 byte alignment for OABI and + * 8-byte alignment for EABI. If necessary top_of_stack must be + * rounded down to the next boundary + */ + + top_of_stack = STACK_ALIGN_DOWN(top_of_stack); + + /* The size of the stack in bytes is then the difference between + * the top and the bottom of the stack (+4 because if the top + * is the same as the bottom, then the size is one 32-bit element). + * The size need not be aligned. + */ + + size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4; + + /* Save the adjusted stack values in the _TCB */ + + tcb->adj_stack_ptr = (uint32_t*)top_of_stack; + tcb->adj_stack_size = size_of_stack; + + /* If stack debug is enabled, then fill the stack with a + * recognizable value that we can use later to test for high + * water marks. + */ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK) + memset32(tcb->stack_alloc_ptr, 0xDEADBEEF, tcb->adj_stack_size/4); +#endif + + up_ledon(LED_STACKCREATED); + return OK; + } + + return ERROR; +} + diff --git a/nuttx/arch/arm/src/common/up_etherstub.c b/nuttx/arch/arm/src/common/up_etherstub.c new file mode 100755 index 0000000000..1c4a71ce68 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_etherstub.c @@ -0,0 +1,86 @@ +/**************************************************************************** + * arch/arm/src/common/up_etherstub.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "up_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_netinitialize (stub) + * + * Description: + * This is a stub version os up_netinitialize. Normally, up_netinitialize + * is defined in board/up_network.c for board-specific ethernet + * implementations, or chip/xyx_ethernet.c for chip-specific ethernet + * implementations. The stub version here is used in the cornercase where + * the network is enable yet there is no ethernet driver to be initialized. + * In this case, up_initialize will still try to call up_netinitialize() + * when one does not exist. This cornercase would occur if, for example, + * only a USB network interface is being used or perhaps if a SLIP is + * being used). + * + * In the long run, it might be better to have some kind of CONFIG_NO_ETHERNET + * to suppress the call to up_netinitialize() in up_initialize(). Then + * this stub would not be needed. + * + ****************************************************************************/ + +void up_netinitialize(void) +{ +} diff --git a/nuttx/arch/arm/src/common/up_exit.c b/nuttx/arch/arm/src/common/up_exit.c new file mode 100644 index 0000000000..6f6d54f767 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_exit.c @@ -0,0 +1,174 @@ +/**************************************************************************** + * common/up_exit.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#include "up_internal.h" + +#ifdef CONFIG_DUMP_ON_EXIT +#include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _up_dumponexit + * + * Description: + * Dump the state of all tasks whenever on task exits. This is debug + * instrumentation that was added to check file-related reference counting + * but could be useful again sometime in the future. + * + ****************************************************************************/ + +#if defined(CONFIG_DUMP_ON_EXIT) && defined(CONFIG_DEBUG) +static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg) +{ +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NFILE_STREAMS > 0 + int i; +#endif + + sdbg(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); + sdbg(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); + +#if CONFIG_NFILE_DESCRIPTORS > 0 + if (tcb->filelist) + { + sdbg(" filelist refcount=%d\n", + tcb->filelist->fl_crefs); + + for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + { + struct inode *inode = tcb->filelist->fl_files[i].f_inode; + if (inode) + { + sdbg(" fd=%d refcount=%d\n", + i, inode->i_crefs); + } + } + } +#endif + +#if CONFIG_NFILE_STREAMS > 0 + if (tcb->streams) + { + sdbg(" streamlist refcount=%d\n", + tcb->streams->sl_crefs); + + for (i = 0; i < CONFIG_NFILE_STREAMS; i++) + { + struct file_struct *filep = &tcb->streams->sl_streams[i]; + if (filep->fs_filedes >= 0) + { +#if CONFIG_STDIO_BUFFER_SIZE > 0 + sdbg(" fd=%d nbytes=%d\n", + filep->fs_filedes, + filep->fs_bufpos - filep->fs_bufstart); +#else + sdbg(" fd=%d\n", filep->fs_filedes); +#endif + } + } + } +#endif +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _exit + * + * Description: + * This function causes the currently executing task to cease + * to exist. This is a special case of task_delete() where the task to + * be deleted is the currently executing task. It is more complex because + * a context switch must be perform to the next ready to run task. + * + ****************************************************************************/ + +void _exit(int status) +{ + _TCB* tcb; + + /* Disable interrupts. They will be restored when the next + * task is started. + */ + + (void)irqsave(); + + slldbg("TCB=%p exitting\n", g_readytorun.head); + +#if defined(CONFIG_DUMP_ON_EXIT) && defined(CONFIG_DEBUG) + slldbg("Other tasks:\n"); + sched_foreach(_up_dumponexit, NULL); +#endif + + /* Destroy the task at the head of the ready to run list. */ + + (void)task_deletecurrent(); + + /* Now, perform the context switch to the new ready-to-run task at the + * head of the list. + */ + + tcb = (_TCB*)g_readytorun.head; + + /* Then switch contexts */ + + up_fullcontextrestore(tcb->xcp.regs); +} + diff --git a/nuttx/arch/arm/src/common/up_idle.c b/nuttx/arch/arm/src/common/up_idle.c new file mode 100644 index 0000000000..62557c3a8d --- /dev/null +++ b/nuttx/arch/arm/src/common/up_idle.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * arch/arm/src/common/up_idle.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idle + * + * Description: + * up_idle() is the logic that will be executed when their is no other + * ready-to-run task. This is processor idle time and will continue until + * some interrupt occurs to cause a context switch from the idle task. + * + * Processing in this state may be processor-specific. e.g., this is where + * power management operations might be performed. + * + ****************************************************************************/ + +void up_idle(void) +{ +#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS) + /* If the system is idle and there are no timer interrupts, then process + * "fake" timer interrupts. Hopefully, something will wake up. + */ + + sched_process_timer(); +#else + + /* Sleep until an interrupt occurs to save power */ + +#if 0 + asm("WFI"); /* For example */ +#endif +#endif +} + diff --git a/nuttx/arch/arm/src/common/up_initialize.c b/nuttx/arch/arm/src/common/up_initialize.c new file mode 100644 index 0000000000..094835c293 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_initialize.c @@ -0,0 +1,191 @@ +/**************************************************************************** + * arch/arm/src/common/up_initialize.c + * + * Copyright (C) 2007-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include + +#include + +#include "up_arch.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_calibratedelay + * + * Description: + * Delay loops are provided for short timing loops. This function, if + * enabled, will just wait for 100 seconds. Using a stopwatch, you can + * can then determine if the timing loops are properly calibrated. + * + ****************************************************************************/ + +#if defined(CONFIG_ARCH_CALIBRATION) && defined(CONFIG_DEBUG) +static void up_calibratedelay(void) +{ + int i; + lldbg("Beginning 100s delay\n"); + for (i = 0; i < 100; i++) + { + up_mdelay(1000); + } + lldbg("End 100s delay\n"); +} +#else +# define up_calibratedelay() +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_initialize + * + * Description: + * up_initialize will be called once during OS initialization after the + * basic OS services have been initialized. The architecture specific + * details of initializing the OS will be handled here. Such things as + * setting up interrupt service routines, starting the clock, and + * registering device drivers are some of the things that are different + * for each processor and hardware platform. + * + * up_initialize is called after the OS initialized but before the user + * initialization logic has been started and before the libraries have + * been initialized. OS services and driver services are available. + * + ****************************************************************************/ + +void up_initialize(void) +{ + /* Initialize global variables */ + + current_regs = NULL; + + /* Calibrate the timing loop */ + + up_calibratedelay(); + + /* Add any extra memory fragments to the memory manager */ + + up_addregion(); + + /* Initialize the interrupt subsystem */ + + up_irqinitialize(); + + /* Initialize the power management subsystem. This MCU-specific function + * must be called *very* early in the intialization sequence *before* any + * other device drivers are initialized (since they may attempt to register + * with the power management subsystem). + */ + +#ifdef CONFIG_PM + up_pminitialize(); +#endif + + /* Initialize the DMA subsystem if the weak function stm32_dmainitialize has been + * brought into the build + */ + +#ifdef CONFIG_ARCH_DMA +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (up_dmainitialize) +#endif + { + up_dmainitialize(); + } +#endif + + /* Initialize the system timer interrupt */ + +#if !defined(CONFIG_SUPPRESS_INTERRUPTS) && !defined(CONFIG_SUPPRESS_TIMER_INTS) + up_timerinit(); +#endif + + /* Register devices */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + devnull_register(); /* Standard /dev/null */ +#endif + + /* Initialize the console device driver */ + +#if defined(USE_SERIALDRIVER) + up_serialinit(); +#elif defined(CONFIG_DEV_LOWCONSOLE) + lowconsole_init(); +#elif defined(CONFIG_RAMLOG_CONSOLE) + ramlog_consoleinit(); +#endif + + /* Initialize the system logging device */ + +#ifdef CONFIG_SYSLOG_CHAR + syslog_initialize(); +#endif +#ifdef CONFIG_RAMLOG_SYSLOG + ramlog_sysloginit(); +#endif + + /* Initialize the network */ + + up_netinitialize(); + + /* Initialize USB -- device and/or host */ + + up_usbinitialize(); + up_ledon(LED_IRQSENABLED); +} diff --git a/nuttx/arch/arm/src/common/up_internal.h b/nuttx/arch/arm/src/common/up_internal.h new file mode 100644 index 0000000000..45cb1dcc09 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_internal.h @@ -0,0 +1,393 @@ +/**************************************************************************** + * common/up_internal.h + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_COMMON_UP_INTERNAL_H +#define __ARCH_ARM_SRC_COMMON_UP_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +# include +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Bring-up debug configurations. These are here (vs defconfig) + * because these should only be controlled during low level + * board bring-up and not part of normal platform configuration. + */ + +#undef CONFIG_SUPPRESS_INTERRUPTS /* DEFINED: Do not enable interrupts */ +#undef CONFIG_SUPPRESS_TIMER_INTS /* DEFINED: No timer */ +#undef CONFIG_SUPPRESS_SERIAL_INTS /* DEFINED: Console will poll */ +#undef CONFIG_SUPPRESS_UART_CONFIG /* DEFINED: Do not reconfig UART */ +#undef CONFIG_DUMP_ON_EXIT /* DEFINED: Dump task state on exit */ + +/* Determine which (if any) console driver to use */ + +#if !defined(CONFIG_DEV_CONSOLE) || CONFIG_NFILE_DESCRIPTORS == 0 +# undef USE_SERIALDRIVER +# undef USE_EARLYSERIALINIT +# undef CONFIG_DEV_LOWCONSOLE +# undef CONFIG_RAMLOG_CONSOLE +#else +# if defined(CONFIG_RAMLOG_CONSOLE) +# undef USE_SERIALDRIVER +# undef USE_EARLYSERIALINIT +# undef CONFIG_DEV_LOWCONSOLE +# elif defined(CONFIG_DEV_LOWCONSOLE) +# undef USE_SERIALDRIVER +# undef USE_EARLYSERIALINIT +# else +# define USE_SERIALDRIVER 1 +# define USE_EARLYSERIALINIT 1 +# endif +#endif + +/* Determine which device to use as the system logging device */ + +#ifndef CONFIG_SYSLOG +# undef CONFIG_SYSLOG_CHAR +# undef CONFIG_RAMLOG_SYSLOG +#endif + +/* Check if an interrupt stack size is configured */ + +#ifndef CONFIG_ARCH_INTERRUPTSTACK +# define CONFIG_ARCH_INTERRUPTSTACK 0 +#endif + +/* Macros to handle saving and restoring interrupt state. In the current ARM + * model, the state is always copied to and from the stack and TCB. In the + * Cortex-M3 model, the state is copied from the stack to the TCB, but only + * a referenced is passed to get the state from the TCB. + */ + +#if defined(CONFIG_ARCH_CORTEXM3) || defined(CONFIG_ARCH_CORTEXM4) +# if defined(CONFIG_ARCH_FPU) && !defined(CONFIG_ARMV7M_CMNVECTOR) +# define up_savestate(regs) \ + do { \ + up_copystate(regs, (uint32_t*)current_regs); \ + up_savefpu(regs); \ + } \ + while (0) +# else +# define up_savestate(regs) up_copystate(regs, (uint32_t*)current_regs) +# endif +# define up_restorestate(regs) (current_regs = regs) +#else +# define up_savestate(regs) up_copystate(regs, (uint32_t*)current_regs) +# define up_restorestate(regs) up_copystate((uint32_t*)current_regs, regs) +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +typedef void (*up_vector_t)(void); +#endif + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +/* This holds a references to the current interrupt level + * register storage structure. If is non-NULL only during + * interrupt processing. + */ + +extern volatile uint32_t *current_regs; + +/* This is the beginning of heap as provided from up_head.S. + * This is the first address in DRAM after the loaded + * program+bss+idle stack. The end of the heap is + * CONFIG_DRAM_END + */ + +extern const uint32_t g_heapbase; + +/* Address of the saved user stack pointer */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 +#if defined(CONFIG_ARCH_CORTEXM3) || defined(CONFIG_ARCH_CORTEXM4) +extern uint32_t g_intstackbase; +# else +extern uint32_t g_userstack; +# endif +#endif + +/* These 'addresses' of these values are setup by the linker script. They are + * not actual uint32_t storage locations! They are only used meaningfully in the + * following way: + * + * - The linker script defines, for example, the symbol_sdata. + * - The declareion extern uint32_t _sdata; makes C happy. C will believe + * that the value _sdata is the address of a uint32_t variable _data (it is + * not!). + * - We can recoved the linker value then by simply taking the address of + * of _data. like: uint32_t *pdata = &_sdata; + */ + +extern uint32_t _stext; /* Start of .text */ +extern uint32_t _etext; /* End_1 of .text + .rodata */ +extern const uint32_t _eronly; /* End+1 of read only section (.text + .rodata) */ +extern uint32_t _sdata; /* Start of .data */ +extern uint32_t _edata; /* End+1 of .data */ +extern uint32_t _sbss; /* Start of .bss */ +extern uint32_t _ebss; /* End+1 of .bss */ + +/* Sometimes, functions must be executed from RAM. In this case, the following + * macro may be used (with GCC!) to specify a function that will execute from + * RAM. For example, + * + * int __ramfunc__ foo (void); + * int __ramfunc__ foo (void) { return bar; } + * + * will create a function named foo that will execute from RAM. + */ + +#ifdef CONFIG_BOOT_RAMFUNCS + +# define __ramfunc__ __attribute__ ((section(".ramfunc"))) + +/* Functions decleared in the .ramfunc section will be packaged together + * by the linker script and stored in FLASH. During boot-up, the start + * logic must include logic to copy the RAM functions from their storage + * location in FLASH to their correct destination in SRAM. The following + * following linker-defined values provide the information to copy the + * functions from flash to RAM. + */ + +extern const uint32_t _framfuncs; /* Copy source address in FLASH */ +extern uint32_t _sramfuncs; /* Copy destination start address in RAM */ +extern uint32_t _eramfuncs; /* Copy destination start address in RAM */ + +#endif /* CONFIG_BOOT_RAMFUNCS */ +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Low level initialization provided by board-level logic ******************/ + +extern void up_boot(void); + +/* Context switching */ + +extern void up_copystate(uint32_t *dest, uint32_t *src); +extern void up_decodeirq(uint32_t *regs); +extern int up_saveusercontext(uint32_t *saveregs); +extern void up_fullcontextrestore(uint32_t *restoreregs) __attribute__ ((noreturn)); +extern void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs); + +/* Signal handling **********************************************************/ + +extern void up_sigdeliver(void); + +/* Power management *********************************************************/ + +#ifdef CONFIG_PM +extern void up_pminitialize(void); +#else +# define up_pminitialize() +#endif + +/* Interrupt handling *******************************************************/ + +extern void up_irqinitialize(void); +extern void up_maskack_irq(int irq); + +#if defined(CONFIG_ARCH_CORTEXM3) || defined(CONFIG_ARCH_CORTEXM4) + +extern uint32_t *up_doirq(int irq, uint32_t *regs); +extern int up_svcall(int irq, FAR void *context); +extern int up_hardfault(int irq, FAR void *context); +extern int up_memfault(int irq, FAR void *context); + +#else /* CONFIG_ARCH_CORTEXM3 || CONFIG_ARCH_CORTEXM4 */ + +extern void up_doirq(int irq, uint32_t *regs); +#ifdef CONFIG_PAGING +extern void up_pginitialize(void); +extern uint32_t *up_va2pte(uintptr_t vaddr); +extern void up_dataabort(uint32_t *regs, uint32_t far, uint32_t fsr); +#else /* CONFIG_PAGING */ +# define up_pginitialize() +extern void up_dataabort(uint32_t *regs); +#endif /* CONFIG_PAGING */ +extern void up_prefetchabort(uint32_t *regs); +extern void up_syscall(uint32_t *regs); +extern void up_undefinedinsn(uint32_t *regs); + +#endif /* CONFIG_ARCH_CORTEXM3 || CONFIG_ARCH_CORTEXM4 */ + +extern void up_vectorundefinsn(void); +extern void up_vectorswi(void); +extern void up_vectorprefetch(void); +extern void up_vectordata(void); +extern void up_vectoraddrexcptn(void); +extern void up_vectorirq(void); +extern void up_vectorfiq(void); + +/* Floating point unit ******************************************************/ + +#ifdef CONFIG_ARCH_FPU +extern void up_savefpu(uint32_t *regs); +extern void up_restorefpu(const uint32_t *regs); +#else +# define up_savefpu(regs) +# define up_restorefpu(regs) +#endif + +/* System timer *************************************************************/ + +extern void up_timerinit(void); +extern int up_timerisr(int irq, uint32_t *regs); + +/* Low level serial output **************************************************/ + +extern void up_lowputc(char ch); +extern void up_puts(const char *str); +extern void up_lowputs(const char *str); + +#if CONFIG_NFILE_DESCRIPTORS > 0 +extern void up_earlyserialinit(void); +extern void up_serialinit(void); +#else +# define up_earlyserialinit() +# define up_serialinit() +#endif + +/* Defined in drivers/lowconsole.c */ + +#ifdef CONFIG_DEV_LOWCONSOLE +extern void lowconsole_init(void); +#else +# define lowconsole_init() +#endif + +/* DMA **********************************************************************/ + +#ifdef CONFIG_ARCH_DMA +extern void weak_function up_dmainitialize(void); +#endif + +/* Memory management ********************************************************/ + +#if CONFIG_MM_REGIONS > 1 +void up_addregion(void); +#else +# define up_addregion() +#endif + +/* Watchdog timer ***********************************************************/ + +extern void up_wdtinit(void); + +/* LED interfaces provided by board-level logic *****************************/ + +#ifdef CONFIG_ARCH_LEDS +extern void up_ledinit(void); +extern void up_ledon(int led); +extern void up_ledoff(int led); +#else +# define up_ledinit() +# define up_ledon(led) +# define up_ledoff(led) +#endif + +/* Networking ***************************************************************/ + +/* Defined in board/up_network.c for board-specific ethernet implementations, + * or chip/xyx_ethernet.c for chip-specific ethernet implementations, or + * common/up_etherstub.c for a cornercase where the network is enabled yet + * there is no ethernet driver to be initialized. + */ + +#ifdef CONFIG_NET +extern void up_netinitialize(void); +#else +# define up_netinitialize() +#endif + +/* USB **********************************************************************/ + +#ifdef CONFIG_USBDEV +extern void up_usbinitialize(void); +extern void up_usbuninitialize(void); +#else +# define up_usbinitialize() +# define up_usbuninitialize() +#endif + +/**************************************************************************** + * Name: up_check_stack + * + * Description: + * Determine (approximately) how much stack has been used be searching the + * stack memory for a high water mark. That is, the deepest level of the + * stack that clobbered some recognizable marker in the stack memory. + * + * Input Parameters: + * None + * + * Returned value: + * The estimated amount of stack space used. + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK) +extern size_t up_check_stack(void); +extern size_t up_check_tcbstack(FAR _TCB); +extern size_t up_check_tcbstack_remain(FAR _TCB); +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_ARM_SRC_COMMON_UP_INTERNAL_H */ diff --git a/nuttx/arch/arm/src/common/up_interruptcontext.c b/nuttx/arch/arm/src/common/up_interruptcontext.c new file mode 100644 index 0000000000..b67ad523a2 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_interruptcontext.c @@ -0,0 +1,70 @@ +/**************************************************************************** + * arch/arm/src/common/up_interruptcontext.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "up_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_interrupt_context + * + * Description: Return true is we are currently executing in + * the interrupt handler context. + ****************************************************************************/ + +bool up_interrupt_context(void) +{ + return current_regs != NULL; +} diff --git a/nuttx/arch/arm/src/common/up_lowputs.c b/nuttx/arch/arm/src/common/up_lowputs.c new file mode 100644 index 0000000000..8b2919a05e --- /dev/null +++ b/nuttx/arch/arm/src/common/up_lowputs.c @@ -0,0 +1,74 @@ +/**************************************************************************** + * arch/arm/src/common/up_lowputs.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_lowputs + * + * Description: + * This is a low-level helper function used to support debug. + * + ****************************************************************************/ + +void up_lowputs(const char *str) +{ + while(*str) + { + up_lowputc(*str++); + } +} diff --git a/nuttx/arch/arm/src/common/up_mdelay.c b/nuttx/arch/arm/src/common/up_mdelay.c new file mode 100644 index 0000000000..b9b9ffc0e4 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_mdelay.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * arch/arm/src/common/up_mdelay.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_mdelay + * + * Description: + * Delay inline for the requested number of milliseconds. + * *** NOT multi-tasking friendly *** + * + * ASSUMPTIONS: + * The setting CONFIG_BOARD_LOOPSPERMSEC has been calibrated + * + ****************************************************************************/ + +void up_mdelay(unsigned int milliseconds) +{ + volatile int i; + volatile int j; + + for (i = 0; i < milliseconds; i++) + { + for (j = 0; j < CONFIG_BOARD_LOOPSPERMSEC; j++) + { + } + } +} diff --git a/nuttx/arch/arm/src/common/up_modifyreg16.c b/nuttx/arch/arm/src/common/up_modifyreg16.c new file mode 100644 index 0000000000..e488a6eee3 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_modifyreg16.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * arch/arm/src/common/up_modifyreg16.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "up_arch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: modifyreg16 + * + * Description: + * Atomically modify the specified bits in a memory mapped register + * + ****************************************************************************/ + +void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits) +{ + irqstate_t flags; + uint16_t regval; + + flags = irqsave(); + regval = getreg16(addr); + regval &= ~clearbits; + regval |= setbits; + putreg16(regval, addr); + irqrestore(flags); +} diff --git a/nuttx/arch/arm/src/common/up_modifyreg32.c b/nuttx/arch/arm/src/common/up_modifyreg32.c new file mode 100644 index 0000000000..8b93f6b84f --- /dev/null +++ b/nuttx/arch/arm/src/common/up_modifyreg32.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * arch/arm/src/common/up_modifyreg32.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "up_arch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: modifyreg32 + * + * Description: + * Atomically modify the specified bits in a memory mapped register + * + ****************************************************************************/ + +void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits) +{ + irqstate_t flags; + uint32_t regval; + + flags = irqsave(); + regval = getreg32(addr); + regval &= ~clearbits; + regval |= setbits; + putreg32(regval, addr); + irqrestore(flags); +} diff --git a/nuttx/arch/arm/src/common/up_modifyreg8.c b/nuttx/arch/arm/src/common/up_modifyreg8.c new file mode 100644 index 0000000000..2c9dbac250 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_modifyreg8.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * arch/arm/src/common/up_modifyreg8.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "up_arch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: modifyreg8 + * + * Description: + * Atomically modify the specified bits in a memory mapped register + * + ****************************************************************************/ + +void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits) +{ + irqstate_t flags; + uint8_t regval; + + flags = irqsave(); + regval = getreg8(addr); + regval &= ~clearbits; + regval |= setbits; + putreg8(regval, addr); + irqrestore(flags); +} diff --git a/nuttx/arch/arm/src/common/up_puts.c b/nuttx/arch/arm/src/common/up_puts.c new file mode 100644 index 0000000000..4e74f0cdc3 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_puts.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * arch/arm/src/common/up_puts.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_puts + * + * Description: + * This is a low-level helper function used to support debug. + * + ****************************************************************************/ + +void up_puts(const char *str) +{ + while(*str) + { + up_putc(*str++); + } +} diff --git a/nuttx/arch/arm/src/common/up_releasestack.c b/nuttx/arch/arm/src/common/up_releasestack.c new file mode 100644 index 0000000000..407bd1b544 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_releasestack.c @@ -0,0 +1,79 @@ +/**************************************************************************** + * arch/arm/src/common/up_releasestack.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_release_stack + * + * Description: + * A task has been stopped. Free all stack + * related resources retained int the defunct TCB. + * + ****************************************************************************/ + +void up_release_stack(_TCB *dtcb) +{ + if (dtcb->stack_alloc_ptr) + { + sched_free(dtcb->stack_alloc_ptr); + dtcb->stack_alloc_ptr = NULL; + } + + dtcb->adj_stack_size = 0; +} diff --git a/nuttx/arch/arm/src/common/up_udelay.c b/nuttx/arch/arm/src/common/up_udelay.c new file mode 100644 index 0000000000..d2d5b74d93 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_udelay.c @@ -0,0 +1,129 @@ +/**************************************************************************** + * arch/arm/src/common/up_udelay.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define CONFIG_BOARD_LOOPSPER100USEC ((CONFIG_BOARD_LOOPSPERMSEC+5)/10) +#define CONFIG_BOARD_LOOPSPER10USEC ((CONFIG_BOARD_LOOPSPERMSEC+50)/100) +#define CONFIG_BOARD_LOOPSPERUSEC ((CONFIG_BOARD_LOOPSPERMSEC+500)/1000) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_udelay + * + * Description: + * Delay inline for the requested number of microseconds. NOTE: Because + * of all of the setup, several microseconds will be lost before the actual + * timing looop begins. Thus, the delay will always be a few microseconds + * longer than requested. + * + * *** NOT multi-tasking friendly *** + * + * ASSUMPTIONS: + * The setting CONFIG_BOARD_LOOPSPERMSEC has been calibrated + * + ****************************************************************************/ + +void up_udelay(useconds_t microseconds) +{ + volatile int i; + + /* We'll do this a little at a time because we expect that the + * CONFIG_BOARD_LOOPSPERUSEC is very inaccurate during to truncation in + * the divisions of its calculation. We'll use the largest values that + * we can in order to prevent significant error buildup in the loops. + */ + + while (microseconds > 1000) + { + for (i = 0; i < CONFIG_BOARD_LOOPSPERMSEC; i++) + { + } + microseconds -= 1000; + } + + while (microseconds > 100) + { + for (i = 0; i < CONFIG_BOARD_LOOPSPER100USEC; i++) + { + } + microseconds -= 100; + } + + while (microseconds > 10) + { + for (i = 0; i < CONFIG_BOARD_LOOPSPER10USEC; i++) + { + } + microseconds -= 10; + } + + while (microseconds > 0) + { + for (i = 0; i < CONFIG_BOARD_LOOPSPERUSEC; i++) + { + } + microseconds--; + } +} diff --git a/nuttx/arch/arm/src/common/up_usestack.c b/nuttx/arch/arm/src/common/up_usestack.c new file mode 100644 index 0000000000..f46be0cc90 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_usestack.c @@ -0,0 +1,155 @@ +/**************************************************************************** + * arch/arm/src/common/up_usestack.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* ARM requires at least a 4-byte stack alignment. For use with EABI and + * floating point, the stack must be aligned to 8-byte addresses. + */ + +#ifndef CONFIG_STACK_ALIGNMENT + +/* The symbol __ARM_EABI__ is defined by GCC if EABI is being used. If you + * are not using GCC, make sure that CONFIG_STACK_ALIGNMENT is set correctly! + */ + +# ifdef __ARM_EABI__ +# define CONFIG_STACK_ALIGNMENT 8 +# else +# define CONFIG_STACK_ALIGNMENT 4 +# endif +#endif + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (CONFIG_STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_use_stack + * + * Description: + * Setup up stack-related information in the TCB + * using pre-allocated stack memory + * + * The following TCB fields must be initialized: + * adj_stack_size: Stack size after adjustment for hardware, + * processor, etc. This value is retained only for debug + * purposes. + * stack_alloc_ptr: Pointer to allocated stack + * adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The + * initial value of the stack pointer. + * + * Inputs: + * tcb: The TCB of new task + * stack_size: The allocated stack size. + * + ****************************************************************************/ + +int up_use_stack(_TCB *tcb, void *stack, size_t stack_size) +{ + size_t top_of_stack; + size_t size_of_stack; + + if (tcb->stack_alloc_ptr) + { + sched_free(tcb->stack_alloc_ptr); + } + + /* Save the stack allocation */ + + tcb->stack_alloc_ptr = stack; + + /* The ARM uses a push-down stack: the stack grows toward lower addresses + * in memory. The stack pointer register, points to the lowest, valid + * work address (the "top" of the stack). Items on the stack are + * referenced as positive word offsets from sp. + */ + + top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4; + + /* The ARM stack must be aligned; 4 byte alignment for OABI and 8-byte + * alignment for EABI. If necessary top_of_stack must be rounded down + * to the next boundary + */ + + top_of_stack = STACK_ALIGN_DOWN(top_of_stack); + + /* The size of the stack in bytes is then the difference between + * the top and the bottom of the stack (+4 because if the top + * is the same as the bottom, then the size is one 32-bit element). + * The size need not be aligned. + */ + + size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4; + + /* Save the adjusted stack values in the _TCB */ + + tcb->adj_stack_ptr = (uint32_t*)top_of_stack; + tcb->adj_stack_size = size_of_stack; + + return OK; +} diff --git a/nuttx/arch/arm/src/stm32/Kconfig b/nuttx/arch/arm/src/stm32/Kconfig new file mode 100644 index 0000000000..5d0d48f880 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/Kconfig @@ -0,0 +1,1912 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +choice + prompt "STM32 Chip Selection" + default ARCH_CHIP_STM32F103ZET6 + depends on ARCH_CHIP_STM32 + +config ARCH_CHIP_STM32F103ZET6 + bool "STM32F103ZET6" + +config ARCH_CHIP_STM32F103RET6 + bool "STM32F103RET6" + +config ARCH_CHIP_STM32F103VCT6 + bool "STM32F103VCT6" + +config ARCH_CHIP_STM32F105VBT7 + bool "STM32F105VBT7" + +config ARCH_CHIP_STM32F107VC + bool "STM32F107VC" + +config ARCH_CHIP_STM32F207IG + bool "STM32F207IG" + +config ARCH_CHIP_STM32F405RG + bool "STM32F405RG" + +config ARCH_CHIP_STM32F405VG + bool "STM32F405VG" + +config ARCH_CHIP_STM32F405ZG + bool "STM32F405ZG" + +config ARCH_CHIP_STM32F407VE + bool "STM32F407VE" + +config ARCH_CHIP_STM32F407VG + bool "STM32F407VG" + +config ARCH_CHIP_STM32F407ZE + bool "STM32F407ZE" + +config ARCH_CHIP_STM32F407ZG + bool "STM32F407ZG" + +config ARCH_CHIP_STM32F407IE + bool "STM32F407IE" + +config ARCH_CHIP_STM32F407IG + bool "STM32F407IG" + +endchoice + +config STM32_STM32F10XX + bool + default y if ARCH_CHIP_STM32F103ZET6 || ARCH_CHIP_STM32F103RET6 || ARCH_CHIP_STM32F103VCT6 || ARCH_CHIP_STM32F105VBT7 || ARCH_CHIP_STM32F107VC + +config STM32_CONNECTIVITYLINE + bool + default y if ARCH_CHIP_STM32F105VBT7 || ARCH_CHIP_STM32F107VC + +config STM32_STM32F20XX + bool + default y if ARCH_CHIP_STM32F207IG + +config STM32_STM32F40XX + bool + default y if ARCH_CHIP_STM32F405RG || ARCH_CHIP_STM32F405VG || ARCH_CHIP_STM32F405ZG || ARCH_CHIP_STM32F407VE || ARCH_CHIP_STM32F407VG || ARCH_CHIP_STM32F407ZE || ARCH_CHIP_STM32F407ZG || ARCH_CHIP_STM32F407IE || ARCH_CHIP_STM32F407IE + +config ARCH_CORTEXM3 + bool + default y if !STM32_STM32F40XX + +config ARCH_CORTEXM4 + bool + default y if STM32_STM32F40XX + +menu "STM32 Peripheral Support" + +config STM32_ADC1 + bool "ADC1" + default n + +config STM32_ADC2 + bool "ADC2" + default n + +config STM32_ADC3 + bool "ADC3" + default n + +config STM32_CRC + bool "CRC" + default n + +config STM32_DMA1 + bool "DMA1" + default n + +config STM32_DMA2 + bool "DMA2" + default n + +config STM32_BKP + bool "BKP" + default n + depends on STM32_STM32F10XX + +config STM32_BKPSRAM + bool "BKP RAM" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_CAN1 + bool "CAN1" + default n + +config STM32_CAN2 + bool "CAN2" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_CCMDATARAM + bool "CMD/DATA RAM" + default n + depends on STM32_STM32F40XX + +config STM32_CRYP + bool "CRYP" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_DAC1 + bool "DAC1" + default n + +config STM32_DAC2 + bool "DAC2" + default n + +config STM32_DCMI + bool "DCMI" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_ETHMAC + bool "Ethernet MAC" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_FSMC + bool "FSMC" + default n + +config STM32_HASH + bool "HASH" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_I2C1 + bool "I2C1" + default n + +config STM32_I2C2 + bool "I2C2" + default n + +config STM32_I2C3 + bool "I2C3" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_IWDG + bool "IWDG" + default n + +config STM32_OTGFS + bool "OTG FS" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_OTGHS + bool "OTG HS" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_PWR + bool "PWR" + default n + +config STM32_RNG + bool "RNG" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_SDIO + bool "SDIO" + default n + +config STM32_SPI1 + bool "SPI1" + default n + +config STM32_SPI2 + bool "SPI2" + default n + +config STM32_SPI3 + bool "SPI3" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_SPI4 + bool "SPI4" + default n + depends on STM32_STM32F10XX + +config STM32_SYSCFG + bool "SYSCFG" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_TIM1 + bool "TIM1" + default n + +config STM32_TIM2 + bool "TIM2" + default n + +config STM32_TIM3 + bool "TIM3" + default n + +config STM32_TIM4 + bool "TIM4" + default n + +config STM32_TIM5 + bool "TIM5" + default n + +config STM32_TIM6 + bool "TIM6" + default n + +config STM32_TIM7 + bool "TIM7" + default n + +config STM32_TIM8 + bool "TIM8" + default n + +config STM32_TIM9 + bool "TIM9" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_TIM10 + bool "TIM10" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_TIM11 + bool "TIM11" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_TIM12 + bool "TIM12" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_TIM13 + bool "TIM13" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_TIM14 + bool "TIM14" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_USART1 + bool "USART1" + default n + +config STM32_USART2 + bool "USART2" + default n + +config STM32_USART3 + bool "USART3" + default n + +config STM32_UART4 + bool "UART4" + default n + +config STM32_UART5 + bool "UART5" + default n + +config STM32_USART6 + bool "USART6" + default n + depends on STM32_STM32F20XX || STM32_STM32F40XX + +config STM32_USB + bool "USB Device" + default n + depends on STM32_STM32F10XX + +config STM32_WWDG + bool "WWDG" + default n + +endmenu + +config STM32_ADC + bool + default y if STM32_ADC1 || STM32_ADC2 || STM32_ADC3 + +config STM32_DAC + bool + default y if STM32_DAC1 || STM32_ADC2 + +config STM32_SPI + bool + default y if STM32_SPI1 || STM32_SPI2 || STM32_SPI3 || STM32_SPI4 + +config STM32_DMA + bool + default y if STM32_DMA1 || STM32_DMA2 + +config STM32_CAN + bool + default y if STM32_CAN1 || STM32_CAN2 + +choice + prompt "TIM1 Alternate Pin Mappings" + depends on STM32_STM32F10XX && STM32_TIM1 + default STM32_TIM1_NO_REMAP + +config STM32_TIM1_NO_REMAP + bool "No pin remapping" + +config STM32_TIM1_FULL_REMAP + bool "Full pin remapping" + +config STM32_TIM1_PARTIAL_REMAP + bool "Partial pin remapping" + +endchoice + +choice + prompt "TIM2 Alternate Pin Mappings" + depends on STM32_STM32F10XX && STM32_TIM2 + default STM32_TIM2_NO_REMAP + +config STM32_TIM2_NO_REMAP + bool "No pin remapping" + +config STM32_TIM2_FULL_REMAP + bool "Full pin remapping" + +config STM32_TIM2_PARTIAL_REMAP_1 + bool "Partial pin remapping #1" + +config STM32_TIM2_PARTIAL_REMAP_2 + bool "Partial pin remapping #2" + +endchoice + +choice + prompt "TIM3 Alternate Pin Mappings" + depends on STM32_STM32F10XX && STM32_TIM3 + default STM32_TIM3_NO_REMAP + +config STM32_TIM3_NO_REMAP + bool "No pin remapping" + +config STM32_TIM3_FULL_REMAP + bool "Full pin remapping" + +config STM32_TIM3_PARTIAL_REMAP + bool "Partial pin remapping" + +endchoice + +config STM32_TIM4_REMAP + bool "TIM4 Alternate Pin Mapping" + default n + depends on STM32_STM32F10XX && STM32_TIM4 + +config STM32_USART1_REMAP + bool "USART1 Alternate Pin Mapping" + default n + depends on STM32_STM32F10XX && STM32_USART1 + +config STM32_USART2_REMAP + bool "USART2 Alternate Pin Mapping" + default n + depends on STM32_STM32F10XX && STM32_USART2 + +choice + prompt "USART3 Alternate Pin Mappings" + depends on STM32_STM32F10XX && STM32_USART3 + default STM32_USART3_NO_REMAP + +config STM32_USART3_NO_REMAP + bool "No pin remapping" + +config STM32_USART3_FULL_REMAP + bool "Full pin remapping" + +config STM32_USART3_PARTIAL_REMAP + bool "Partial pin remapping" + +endchoice + +config STM32_SPI1_REMAP + bool "SPI1 Alternate Pin Mapping" + default n + depends on STM32_STM32F10XX && STM32_SPI1 + +config STM32_SPI3_REMAP + bool "SPI3 Alternate Pin Mapping" + default n + depends on STM32_STM32F10XX && STM32_SPI3 + +config STM32_I2C1_REMAP + bool "I2C1 Alternate Pin Mapping" + default n + depends on STM32_STM32F10XX && STM32_I2C1 + +choice + prompt "CAN1 Alternate Pin Mappings" + depends on STM32_STM32F10XX && STM32_CAN1 + default STM32_CAN1_NO_REMAP + +config STM32_CAN1_NO_REMAP + bool "No pin remapping" + +config STM32_CAN1_FULL_REMAP + bool "Full pin remapping" + +config STM32_CAN1_PARTIAL_REMAP + bool "Partial pin remapping" + +endchoice + +config STM32_CAN2_REMAP + bool "CAN2 Alternate Pin Mapping" + default n + depends on STM32_STM32F10XX && STM32_CAN2 + +choice + prompt "JTAG Configuration" + default STM32_JTAG_DISABLE + ---help--- + JTAG Enable settings (by default JTAG-DP and SW-DP are disabled) + +config STM32_JTAG_DISABLE + bool "Disable all JTAG clocking" + +config STM32_JTAG_FULL_ENABLE + bool "Enable full SWJ (JTAG-DP + SW-DP)" + +config STM32_JTAG_NOJNTRST_ENABLE + bool "Enable full SWJ (JTAG-DP + SW-DP) but without JNTRST" + +config STM32_JTAG_SW_ENABLE + bool "Set JTAG-DP disabled and SW-DP enabled" + +endchoice + +config STM32_FORCEPOWER + bool "Force power" + default n + ---help--- + Timer and I2C devices may need to the following to force power to be applied + unconditionally at power up. (Otherwise, the device is powered when it is + initialized). + +config ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG + bool "Custom clock configuration" + default n + ---help--- + Enables special, board-specific STM32 clock configuration. + +config STM32_CCMEXCLUDE + bool "Exclude CCM SRAM from the heap" + depends on STM32_STM32F20XX || STM32_STM32F40XX + default y if STM32_DMA1 || STM32_DMA2 + ---help--- + Exclude CCM SRAM from the HEAP because it cannot be used for DMA. + +config STM32_FSMC_SRAM + bool "External SRAM on FSMC" + default n + depends on FSMC + ---help--- + In addition to internal SRAM, SRAM may also be available through the FSMC. + +config HEAP2_BASE + hex "FSMC SRAM base address" + default 0x00000000 + depends on STM32_FSMC_SRAM + ---help--- + The base address of the SRAM in the FSMC address space. + +config HEAP2_END + hex "FSMC SRAM end+1 address" + default 0x00000000 + depends on STM32_FSMC_SRAM + ---help--- + The end (+1) of the SRAM in the FSMC address space + +config ARCH_FPU + bool "FPU support" + default y + depends on ARCH_CORTEXM4 + ---help--- + Build in support for the ARM Cortex-M4 FPU. Only the STM3240xxx supports + a floating point unit (FPU) + +config STM32_TIM1_PWM + bool "TIM1 PWM" + default n + depends on STM32_TIM1 + ---help--- + Reserve timer 1 for use by PWM + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If STM32_TIM1 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +config STM32_TIM1_CHANNEL + int "TIM1 PWM Output Channel" + default 1 + depends on STM32_TIM1_PWM + ---help--- + If TIM1 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +config STM32_TIM2_PWM + bool "TIM2 PWM" + default n + depends on STM32_TIM2 + ---help--- + Reserve timer 1 for use by PWM + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If STM32_TIM2 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +config STM32_TIM2_CHANNEL + int "TIM2 PWM Output Channel" + default 1 + depends on STM32_TIM2_PWM + ---help--- + If TIM2 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +config STM32_TIM3_PWM + bool "TIM3 PWM" + default n + depends on STM32_TIM3 + ---help--- + Reserve timer 1 for use by PWM + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If STM32_TIM3 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +config STM32_TIM3_CHANNEL + int "TIM3 PWM Output Channel" + default 1 + depends on STM32_TIM3_PWM + ---help--- + If TIM3 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +config STM32_TIM4_PWM + bool "TIM4 PWM" + default n + depends on STM32_TIM4 + ---help--- + Reserve timer 1 for use by PWM + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If STM32_TIM4 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +config STM32_TIM4_CHANNEL + int "TIM4 PWM Output Channel" + default 1 + depends on STM32_TIM4_PWM + ---help--- + If TIM4 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +config STM32_TIM5_PWM + bool "TIM5 PWM" + default n + depends on STM32_TIM5 + ---help--- + Reserve timer 1 for use by PWM + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If STM32_TIM5 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +config STM32_TIM5_CHANNEL + int "TIM5 PWM Output Channel" + default 1 + depends on STM32_TIM5_PWM + ---help--- + If TIM5 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +config STM32_TIM8_PWM + bool "TIM8 PWM" + default n + depends on STM32_TIM8 + ---help--- + Reserve timer 1 for use by PWM + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If STM32_TIM8 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +config STM32_TIM8_CHANNEL + int "TIM8 PWM Output Channel" + default 1 + depends on STM32_TIM8_PWM + ---help--- + If TIM8 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +config STM32_TIM9_PWM + bool "TIM9 PWM" + default n + depends on STM32_TIM9 + ---help--- + Reserve timer 1 for use by PWM + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If STM32_TIM9 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +config STM32_TIM9_CHANNEL + int "TIM9 PWM Output Channel" + default 1 + depends on STM32_TIM9_PWM + ---help--- + If TIM9 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +config STM32_TIM10_PWM + bool "TIM10 PWM" + default n + depends on STM32_TIM10 + ---help--- + Reserve timer 1 for use by PWM + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If STM32_TIM10 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +config STM32_TIM10_CHANNEL + int "TIM10 PWM Output Channel" + default 1 + depends on STM32_TIM10_PWM + ---help--- + If TIM10 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +config STM32_TIM11_PWM + bool "TIM11 PWM" + default n + depends on STM32_TIM11 + ---help--- + Reserve timer 1 for use by PWM + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If STM32_TIM11 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +config STM32_TIM11_CHANNEL + int "TIM11 PWM Output Channel" + default 1 + depends on STM32_TIM11_PWM + ---help--- + If TIM11 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +config STM32_TIM12_PWM + bool "TIM12 PWM" + default n + depends on STM32_TIM12 + ---help--- + Reserve timer 1 for use by PWM + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If STM32_TIM12 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +config STM32_TIM12_CHANNEL + int "TIM12 PWM Output Channel" + default 1 + depends on STM32_TIM12_PWM + ---help--- + If TIM12 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +config STM32_TIM13_PWM + bool "TIM13 PWM" + default n + depends on STM32_TIM13 + ---help--- + Reserve timer 1 for use by PWM + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If STM32_TIM13 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +config STM32_TIM13_CHANNEL + int "TIM13 PWM Output Channel" + default 1 + depends on STM32_TIM13_PWM + ---help--- + If TIM13 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +config STM32_TIM14_PWM + bool "TIM14 PWM" + default n + depends on STM32_TIM14 + ---help--- + Reserve timer 1 for use by PWM + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If STM32_TIM14 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +config STM32_TIM14_CHANNEL + int "TIM14 PWM Output Channel" + default 1 + depends on STM32_TIM14_PWM + ---help--- + If TIM14 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +config STM32_TIM1_ADC + bool "TIM1 ADC" + default n + depends on STM32_TIM1 && STM32_ADC + ---help--- + Reserve timer 1 for use by ADC + + Timer devices may be used for different purposes. If STM32_TIM1 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select TIM1 ADC channel" + default STM32_TIM1_ADC1 + depends on STM32_TIM1_ADC + +config STM32_TIM1_ADC1 + bool "TIM1 ADC channel 1" + ---help--- + Reserve TIM1 to trigger ADC1 + +config STM32_TIM1_ADC2 + bool "TIM1 ADC channel 2" + ---help--- + Reserve TIM1 to trigger ADC2 + +config STM32_TIM1_ADC3 + bool "TIM1 ADC channel 3" + ---help--- + Reserve TIM1 to trigger ADC3 + +endchoice + +config STM32_TIM2_ADC + bool "TIM2 ADC" + default n + depends on STM32_TIM2 && STM32_ADC + ---help--- + Reserve timer 1 for use by ADC + + Timer devices may be used for different purposes. If STM32_TIM2 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select TIM2 ADC channel" + default STM32_TIM2_ADC1 + depends on STM32_TIM2_ADC + +config STM32_TIM2_ADC1 + bool "TIM2 ADC channel 1" + ---help--- + Reserve TIM2 to trigger ADC1 + +config STM32_TIM2_ADC2 + bool "TIM2 ADC channel 2" + ---help--- + Reserve TIM2 to trigger ADC2 + +config STM32_TIM2_ADC3 + bool "TIM2 ADC channel 3" + ---help--- + Reserve TIM2 to trigger ADC3 + +endchoice + +config STM32_TIM3_ADC + bool "TIM3 ADC" + default n + depends on STM32_TIM3 && STM32_ADC + ---help--- + Reserve timer 1 for use by ADC + + Timer devices may be used for different purposes. If STM32_TIM3 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select TIM3 ADC channel" + default STM32_TIM3_ADC1 + depends on STM32_TIM3_ADC + +config STM32_TIM3_ADC1 + bool "TIM3 ADC channel 1" + ---help--- + Reserve TIM3 to trigger ADC1 + +config STM32_TIM3_ADC2 + bool "TIM3 ADC channel 2" + ---help--- + Reserve TIM3 to trigger ADC2 + +config STM32_TIM3_ADC3 + bool "TIM3 ADC channel 3" + ---help--- + Reserve TIM3 to trigger ADC3 + +endchoice + +config STM32_TIM4_ADC + bool "TIM4 ADC" + default n + depends on STM32_TIM4 && STM32_ADC + ---help--- + Reserve timer 1 for use by ADC + + Timer devices may be used for different purposes. If STM32_TIM4 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select TIM4 ADC channel" + default STM32_TIM4_ADC1 + depends on STM32_TIM4_ADC + +config STM32_TIM4_ADC1 + bool "TIM4 ADC channel 1" + ---help--- + Reserve TIM4 to trigger ADC1 + +config STM32_TIM4_ADC2 + bool "TIM4 ADC channel 2" + ---help--- + Reserve TIM4 to trigger ADC2 + +config STM32_TIM4_ADC3 + bool "TIM4 ADC channel 3" + ---help--- + Reserve TIM4 to trigger ADC3 + +endchoice + +config STM32_TIM5_ADC + bool "TIM5 ADC" + default n + depends on STM32_TIM5 && STM32_ADC + ---help--- + Reserve timer 1 for use by ADC + + Timer devices may be used for different purposes. If STM32_TIM5 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select TIM5 ADC channel" + default STM32_TIM5_ADC1 + depends on STM32_TIM5_ADC + +config STM32_TIM5_ADC1 + bool "TIM5 ADC channel 1" + ---help--- + Reserve TIM5 to trigger ADC1 + +config STM32_TIM5_ADC2 + bool "TIM5 ADC channel 2" + ---help--- + Reserve TIM5 to trigger ADC2 + +config STM32_TIM5_ADC3 + bool "TIM5 ADC channel 3" + ---help--- + Reserve TIM5 to trigger ADC3 + +endchoice + +config STM32_TIM8_ADC + bool "TIM8 ADC" + default n + depends on STM32_TIM8 && STM32_ADC + ---help--- + Reserve timer 1 for use by ADC + + Timer devices may be used for different purposes. If STM32_TIM8 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select TIM8 ADC channel" + default STM32_TIM8_ADC1 + depends on STM32_TIM8_ADC + +config STM32_TIM8_ADC1 + bool "TIM8 ADC channel 1" + ---help--- + Reserve TIM8 to trigger ADC1 + +config STM32_TIM8_ADC2 + bool "TIM8 ADC channel 2" + ---help--- + Reserve TIM8 to trigger ADC2 + +config STM32_TIM8_ADC3 + bool "TIM8 ADC channel 3" + ---help--- + Reserve TIM8 to trigger ADC3 + +endchoice + +config STM32_TIM1_DAC + bool "TIM1 DAC" + default n + depends on STM32_TIM1 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM1 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM1 DAC channel" + default STM32_TIM1_DAC1 + depends on STM32_TIM1_DAC + +config STM32_TIM1_DAC1 + bool "TIM1 DAC channel 1" + ---help--- + Reserve TIM1 to trigger DAC1 + +config STM32_TIM1_DAC2 + bool "TIM1 DAC channel 2" + ---help--- + Reserve TIM1 to trigger DAC2 + +endchoice + +config STM32_TIM2_DAC + bool "TIM2 DAC" + default n + depends on STM32_TIM2 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM2 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM2 DAC channel" + default STM32_TIM2_DAC1 + depends on STM32_TIM2_DAC + +config STM32_TIM2_DAC1 + bool "TIM2 DAC channel 1" + ---help--- + Reserve TIM2 to trigger DAC1 + +config STM32_TIM2_DAC2 + bool "TIM2 DAC channel 2" + ---help--- + Reserve TIM2 to trigger DAC2 + +endchoice + +config STM32_TIM3_DAC + bool "TIM3 DAC" + default n + depends on STM32_TIM3 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM3 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM3 DAC channel" + default STM32_TIM3_DAC1 + depends on STM32_TIM3_DAC + +config STM32_TIM3_DAC1 + bool "TIM3 DAC channel 1" + ---help--- + Reserve TIM3 to trigger DAC1 + +config STM32_TIM3_DAC2 + bool "TIM3 DAC channel 2" + ---help--- + Reserve TIM3 to trigger DAC2 + +endchoice + +config STM32_TIM4_DAC + bool "TIM4 DAC" + default n + depends on STM32_TIM4 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM4 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM4 DAC channel" + default STM32_TIM4_DAC1 + depends on STM32_TIM4_DAC + +config STM32_TIM4_DAC1 + bool "TIM4 DAC channel 1" + ---help--- + Reserve TIM4 to trigger DAC1 + +config STM32_TIM4_DAC2 + bool "TIM4 DAC channel 2" + ---help--- + Reserve TIM4 to trigger DAC2 + +endchoice + +config STM32_TIM5_DAC + bool "TIM5 DAC" + default n + depends on STM32_TIM5 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM5 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM5 DAC channel" + default STM32_TIM5_DAC1 + depends on STM32_TIM5_DAC + +config STM32_TIM5_DAC1 + bool "TIM5 DAC channel 1" + ---help--- + Reserve TIM5 to trigger DAC1 + +config STM32_TIM5_DAC2 + bool "TIM5 DAC channel 2" + ---help--- + Reserve TIM5 to trigger DAC2 + +endchoice + +config STM32_TIM6_DAC + bool "TIM6 DAC" + default n + depends on STM32_TIM6 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM6 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM6 DAC channel" + default STM32_TIM6_DAC1 + depends on STM32_TIM6_DAC + +config STM32_TIM6_DAC1 + bool "TIM6 DAC channel 1" + ---help--- + Reserve TIM6 to trigger DAC1 + +config STM32_TIM6_DAC2 + bool "TIM6 DAC channel 2" + ---help--- + Reserve TIM6 to trigger DAC2 + +endchoice + +config STM32_TIM7_DAC + bool "TIM7 DAC" + default n + depends on STM32_TIM7 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM7 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM7 DAC channel" + default STM32_TIM7_DAC1 + depends on STM32_TIM7_DAC + +config STM32_TIM7_DAC1 + bool "TIM7 DAC channel 1" + ---help--- + Reserve TIM7 to trigger DAC1 + +config STM32_TIM7_DAC2 + bool "TIM7 DAC channel 2" + ---help--- + Reserve TIM7 to trigger DAC2 + +endchoice + +config STM32_TIM8_DAC + bool "TIM8 DAC" + default n + depends on STM32_TIM8 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM8 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM8 DAC channel" + default STM32_TIM8_DAC1 + depends on STM32_TIM8_DAC + +config STM32_TIM8_DAC1 + bool "TIM8 DAC channel 1" + ---help--- + Reserve TIM8 to trigger DAC1 + +config STM32_TIM8_DAC2 + bool "TIM8 DAC channel 2" + ---help--- + Reserve TIM8 to trigger DAC2 + +endchoice + +config STM32_TIM9_DAC + bool "TIM9 DAC" + default n + depends on STM32_TIM9 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM9 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM9 DAC channel" + default STM32_TIM9_DAC1 + depends on STM32_TIM9_DAC + +config STM32_TIM9_DAC1 + bool "TIM9 DAC channel 1" + ---help--- + Reserve TIM9 to trigger DAC1 + +config STM32_TIM9_DAC2 + bool "TIM9 DAC channel 2" + ---help--- + Reserve TIM9 to trigger DAC2 + +endchoice + +config STM32_TIM10_DAC + bool "TIM10 DAC" + default n + depends on STM32_TIM10 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM10 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM10 DAC channel" + default STM32_TIM10_DAC1 + depends on STM32_TIM10_DAC + +config STM32_TIM10_DAC1 + bool "TIM10 DAC channel 1" + ---help--- + Reserve TIM10 to trigger DAC1 + +config STM32_TIM10_DAC2 + bool "TIM10 DAC channel 2" + ---help--- + Reserve TIM10 to trigger DAC2 + +endchoice + +config STM32_TIM11_DAC + bool "TIM11 DAC" + default n + depends on STM32_TIM11 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM11 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM11 DAC channel" + default STM32_TIM11_DAC1 + depends on STM32_TIM11_DAC + +config STM32_TIM11_DAC1 + bool "TIM11 DAC channel 1" + ---help--- + Reserve TIM11 to trigger DAC1 + +config STM32_TIM11_DAC2 + bool "TIM11 DAC channel 2" + ---help--- + Reserve TIM11 to trigger DAC2 + +endchoice + +config STM32_TIM12_DAC + bool "TIM12 DAC" + default n + depends on STM32_TIM12 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM12 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM12 DAC channel" + default STM32_TIM12_DAC1 + depends on STM32_TIM12_DAC + +config STM32_TIM12_DAC1 + bool "TIM12 DAC channel 1" + ---help--- + Reserve TIM12 to trigger DAC1 + +config STM32_TIM12_DAC2 + bool "TIM12 DAC channel 2" + ---help--- + Reserve TIM12 to trigger DAC2 + +endchoice + +config STM32_TIM13_DAC + bool "TIM13 DAC" + default n + depends on STM32_TIM13 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM13 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM13 DAC channel" + default STM32_TIM13_DAC1 + depends on STM32_TIM13_DAC + +config STM32_TIM13_DAC1 + bool "TIM13 DAC channel 1" + ---help--- + Reserve TIM13 to trigger DAC1 + +config STM32_TIM13_DAC2 + bool "TIM13 DAC channel 2" + ---help--- + Reserve TIM13 to trigger DAC2 + +endchoice + +config STM32_TIM14_DAC + bool "TIM14 DAC" + default n + depends on STM32_TIM14 && STM32_DAC + ---help--- + Reserve timer 1 for use by DAC + + Timer devices may be used for different purposes. If STM32_TIM14 is + defined then the following may also be defined to indicate that the + timer is intended to be used for DAC conversion. Note that DAC usage + requires two definition: Not only do you have to assign the timer + for used by the DAC, but then you also have to configure which DAC + channel it is assigned to. + +choice + prompt "Select TIM14 DAC channel" + default STM32_TIM14_DAC1 + depends on STM32_TIM14_DAC + +config STM32_TIM14_DAC1 + bool "TIM14 DAC channel 1" + ---help--- + Reserve TIM14 to trigger DAC1 + +config STM32_TIM14_DAC2 + bool "TIM14 DAC channel 2" + ---help--- + Reserve TIM14 to trigger DAC2 + +endchoice + +menu "USART1 Configuration" + depends on STM32_USART1 + +config USART1_SERIAL_CONSOLE + bool "USART1 serial console" + default y + ---help--- + Selects the USART1 for the console and ttys0 (default is the USART1). + +config USART1_RXBUFSIZE + int "USART1 Rx buffer size" + default 256 + ---help--- + Characters are buffered as received. This specific the size of the receive + buffer. + +config USART1_TXBUFSIZE + int "USART1 Tx buffer size" + default 256 + ---help--- + Characters are buffered before being sent. This specific the size of the + transmit buffer + +config USART1_BAUD + int "USART1 BAUD" + default 11520 + ---help--- + The configured BAUD of the UART + +config USART1_BITS + int "USART1 number of bits" + default 8 + ---help--- + The number of bits. Must be either 7 or 8. + +config USART1_PARITY + int "USART1 parity" + default 0 + ---help--- + 0=no parity, 1=odd parity, 2=even parity + +config USART1_2STOP + bool "USART1 two stop bits" + default n + ---help--- + Two stop bits + +config USART1_RXDMA + bool "USART1 Rx DMA" + default n + depends on STM32_STM32F40XX && ARCH_DMA && STM32_DMA2 + ---help--- + In high data rate usage, Rx DMA may eliminate Rx overrun errors + +endmenu + +menu "USART2 Configuration" + depends on STM32_USART2 + +config USART2_SERIAL_CONSOLE + bool "USART2 serial console" + default y if !STM32_USART1 + ---help--- + Selects the USART2 for the console and ttys0 (default is the USART2). + +config USART2_RXBUFSIZE + int "USART2 Rx buffer size" + default 256 + ---help--- + Characters are buffered as received. This specific the size of the receive + buffer. + +config USART2_TXBUFSIZE + int "USART2 Tx buffer size" + default 256 + ---help--- + Characters are buffered before being sent. This specific the size of the + transmit buffer + +config USART2_BAUD + int "USART2 BAUD" + default 11520 + ---help--- + The configured BAUD of the UART + +config USART2_BITS + int "USART2 number of bits" + default 8 + ---help--- + The number of bits. Must be either 7 or 8. + +config USART2_PARITY + int "USART2 parity" + default 0 + ---help--- + 0=no parity, 1=odd parity, 2=even parity + +config USART2_2STOP + bool "USART2 two stop bits" + default n + ---help--- + Two stop bits + +config USART2_RXDMA + bool "USART2 Rx DMA" + default n + depends on STM32_STM32F40XX && ARCH_DMA && STM32_DMA1 + ---help--- + In high data rate usage, Rx DMA may eliminate Rx overrun errors + +endmenu + +menu "USART3 Configuration" + depends on STM32_USART3 + +config USART3_SERIAL_CONSOLE + bool "USART3 serial console" + default y if !STM32_USART1 && !STM32_USART2 + ---help--- + Selects the USART3 for the console and ttys0 (default is the USART3). + +config USART3_RXBUFSIZE + int "USART3 Rx buffer size" + default 256 + ---help--- + Characters are buffered as received. This specific the size of the receive + buffer. + +config USART3_TXBUFSIZE + int "USART3 Tx buffer size" + default 256 + ---help--- + Characters are buffered before being sent. This specific the size of the + transmit buffer + +config USART3_BAUD + int "USART3 BAUD" + default 11520 + ---help--- + The configured BAUD of the UART + +config USART3_BITS + int "USART3 number of bits" + default 8 + ---help--- + The number of bits. Must be either 7 or 8. + +config USART3_PARITY + int "USART3 parity" + default 0 + ---help--- + 0=no parity, 1=odd parity, 2=even parity + +config USART3_2STOP + bool "USART3 two stop bits" + default n + ---help--- + Two stop bits + +config USART3_RXDMA + bool "USART3 Rx DMA" + default n + depends on STM32_STM32F40XX && ARCH_DMA && STM32_DMA1 + ---help--- + In high data rate usage, Rx DMA may eliminate Rx overrun errors + +endmenu + +menu "UART4 Configuration" + depends on STM32_UART4 + +config USART4_SERIAL_CONSOLE + bool "UART4 serial console" + default y if !STM32_USART1 && !STM32_USART2 && !STM32_USART3 + ---help--- + Selects the UART4 for the console and ttys0 (default is the USART1). + +config USART4_RXBUFSIZE + int "UART4 Rx buffer size" + default 256 + ---help--- + Characters are buffered as received. This specific the size of the receive + buffer. + +config USART4_TXBUFSIZE + int "UART4 Tx buffer size" + default 256 + ---help--- + Characters are buffered before being sent. This specific the size of the + transmit buffer + +config USART4_BAUD + int "UART4 BAUD" + default 11520 + ---help--- + The configured BAUD of the UART + +config USART4_BITS + int "UART4 number of bits" + default 8 + ---help--- + The number of bits. Must be either 7 or 8. + +config USART4_PARITY + int "UART4 parity" + default 0 + ---help--- + 0=no parity, 1=odd parity, 2=even parity + +config USART4_2STOP + bool "UART4 two stop bits" + default n + ---help--- + Two stop bits + +config USART4_RXDMA + bool "USART4 Rx DMA" + default n + depends on STM32_STM32F40XX && ARCH_DMA && STM32_DMA1 + ---help--- + In high data rate usage, Rx DMA may eliminate Rx overrun errors + +endmenu + +menu "UART5 Configuration" + depends on STM32_UART5 + +config USART5_SERIAL_CONSOLE + bool "UART5 serial console" + default y if !STM32_USART1 && !STM32_USART2 && !STM32_USART3 && !STM32_UART4 + ---help--- + Selects the UART5 for the console and ttys0 (default is the USART1). + +config USART5_RXBUFSIZE + int "USART5 Rx buffer size" + default 256 + ---help--- + Characters are buffered as received. This specific the size of the receive + buffer. + +config USART5_TXBUFSIZE + int "UART5 Tx buffer size" + default 256 + ---help--- + Characters are buffered before being sent. This specific the size of the + transmit buffer + +config USART5_BAUD + int "UART5 BAUD" + default 11520 + ---help--- + The configured BAUD of the UART + +config USART5_BITS + int "UART5 number of bits" + default 8 + ---help--- + The number of bits. Must be either 7 or 8. + +config USART5_PARITY + int "UART5 parity" + default 0 + ---help--- + 0=no parity, 1=odd parity, 2=even parity + +config USART5_2STOP + bool "UART5 two stop bits" + default n + ---help--- + Two stop bits + +config USART5_RXDMA + bool "USART5 Rx DMA" + default n + depends on STM32_STM32F40XX && ARCH_DMA && STM32_DMA1 + ---help--- + In high data rate usage, Rx DMA may eliminate Rx overrun errors + +endmenu + +menu "USART6 Configuration" + depends on STM32_USART6 + +config USART6_SERIAL_CONSOLE + bool "USART6 serial console" + default y if !STM32_USART1 && !STM32_USART2 && !STM32_USART3 && !STM32_UART4 && !STM32_UART5 + ---help--- + Selects the USART6 for the console and ttys0 (default is the USART6). + +config USART6_RXBUFSIZE + int "USART6 Rx buffer size" + default 256 + ---help--- + Characters are buffered as received. This specific the size of the receive + buffer. + +config USART6_TXBUFSIZE + int "USART6 Tx buffer size" + default 256 + ---help--- + Characters are buffered before being sent. This specific the size of the + transmit buffer + +config USART6_BAUD + int "USART6 BAUD" + default 11520 + ---help--- + The configured BAUD of the UART + +config USART6_BITS + int "USART6 number of bits" + default 8 + ---help--- + The number of bits. Must be either 7 or 8. + +config USART6_PARITY + int "USART6 parity" + default 0 + ---help--- + 0=no parity, 1=odd parity, 2=even parity + +config USART6_2STOP + bool "USART6 two stop bits" + default n + ---help--- + Two stop bits + +config USART6_RXDMA + bool "USART6 Rx DMA" + default n + depends on STM32_STM32F40XX && ARCH_DMA && STM32_DMA2 + ---help--- + In high data rate usage, Rx DMA may eliminate Rx overrun errors + +endmenu + +config SERIAL_TERMIOS + bool "Serial driver TERMIOS supported" + depends on STM32_USART1 || STM32_USART2 || STM32_USART3 || STM32_UART4 || STM32_UART5 || STM32_USART6 + default n + ---help--- + Serial driver supports termios.h interfaces (tcsetattr, tcflush, etc.). + If this is not defined, then the terminal settings (baud, parity, etc). + are not configurable at runtime; serial streams cannot be flushed, etc.. + +menu "SPI Configuration" + depends on STM32_SPI + +config STM32_SPI_INTERRUPTS + bool "Interrupt driver SPI" + default n + ---help--- + Select to enable interrupt driven SPI support. Non-interrupt-driven, + poll-waiting is recommended if the interrupt rate would be to high in + the interrupt driven case. + +config STM32_SPI_DMA + bool "SPI DMA" + default n + ---help--- + Use DMA to improve SPI transfer performance. Cannot be used with STM32_SPI_INTERRUPT. + +endmenu + +menu "SDIO Configuration" + depends on STM32_SDIO + +config SDIO_DMA + bool "Support DMA data transfers" + default y if STM32_DMA2 + depends on STM32_DMA2 + ---help--- + Support DMA data transfers. Requires STM32_SDIO and config STM32_DMA2. + +config SDIO_PRI + hex "SDIO interrupt priority" + default 128 + ---help--- + Select SDIO interrupt prority. Default: 128. + +config SDIO_DMAPRIO + hex "SDIO DMA priority" + default 0x00001000 + ---help--- + Select SDIO DMA prority. Options: 0x00000000 low, 0x00001000 medium, + 0x00002000 high, 0x00003000 very high. Default: medium. + +config SDIO_WIDTH_D1_ONLY + bool "Use D1 only" + default n + ---help--- + Select 1-bit transfer mode. Default: 4-bit transfer mode. + +endmenu + +menu "Ethernet MAC configuration" + +config STM32_PHYADDR + int "PHY address" + ---help--- + The 5-bit address of the PHY on the board + +config STM32_MII + bool "Use MII interface" + default n + ---help--- + Support Ethernet MII interface. + +config STM32_MII_MCO2 + bool "Use MC02 as MII clock" + default n + depends on STM32_MII + ---help--- + Use MCO2 to clock the MII interface. Default: Use MC01 + +config STM32_AUTONEG + bool "Use autonegtiation" + default y + ---help--- + Use PHY autonegotion to determine speed and mode + +config STM32_ETHFD + bool "Full duplex" + default n + depends on !STM32_AUTONEG + ---help--- + If STM32_AUTONEG is not defined, then this may be defined to select full duplex + mode. Default: half-duplex + +config STM32_ETH100MBPS + bool "100 Mbps" + default n + depends on !STM32_AUTONEG + ---help--- + If STM32_AUTONEG is not defined, then this may be defined to select 100 MBps + speed. Default: 10 Mbps + +config STM32_PHYSR + hex "PHY status register address" + depends on STM32_AUTONEG + ---help--- + This must be provided if STM32_AUTONEG is defined. The PHY status register + address may diff from PHY to PHY. This configuration sets the address of + the PHY status register. + +config STM32_PHYSR_SPEED + hex "PHY speed mask" + depends on STM32_AUTONEG + ---help--- + This must be provided if STM32_AUTONEG is defined. This provides bit mask + indicating 10 or 100MBps speed. + +config STM32_PHYSR_100MBPS + hex "PHY 100Mbps speed value" + depends on STM32_AUTONEG + ---help--- + This must be provided if STM32_AUTONEG is defined. This provides the value + of the speed bit(s) indicating 100MBps speed. + +config STM32_PHYSR_MODE + hex "PHY mode mask" + depends on STM32_AUTONEG + ---help--- + This must be provided if STM32_AUTONEG is defined. This provide bit mask + indicating full or half duplex modes. + +config STM32_PHYSR_FULLDUPLEX + hex "PHY full duplex mode value" + depends on STM32_AUTONEG + ---help--- + This must be provided if STM32_AUTONEG is defined. This provides the + value of the mode bits indicating full duplex mode. + +config STM32_ETH_PTP + bool "Precision Time Protocol (PTP)" + default n + ---help--- + Precision Time Protocol (PTP). Not supported but some hooks are indicated + with this condition. + +endmenu + +config STM32_RMII + bool + default y if !STM32_MII + +config STM32_MII_MCO1 + bool + default y if !STM32_MII_MCO2 + depends on STM32_MII diff --git a/nuttx/arch/arm/src/stm32/Make.defs b/nuttx/arch/arm/src/stm32/Make.defs new file mode 100644 index 0000000000..1deb23189e --- /dev/null +++ b/nuttx/arch/arm/src/stm32/Make.defs @@ -0,0 +1,143 @@ +############################################################################ +# arch/arm/src/stm32/Make.defs +# +# Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y) +HEAD_ASRC = +else +HEAD_ASRC = stm32_vectors.S +endif + +CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_switchcontext.S +CMN_CSRCS = up_assert.c up_blocktask.c up_copystate.c \ + up_createstack.c up_mdelay.c up_udelay.c up_exit.c \ + up_initialize.c up_initialstate.c up_interruptcontext.c \ + up_memfault.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c \ + up_releasepending.c up_releasestack.c up_reprioritizertr.c \ + up_schedulesigaction.c up_sigdeliver.c up_unblocktask.c \ + up_usestack.c up_doirq.c up_hardfault.c up_svcall.c \ + up_stackcheck.c + +ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y) +CMN_ASRCS += up_exception.S +CMN_CSRCS += up_vectors.c +endif + +ifeq ($(CONFIG_DEBUG_STACK),y) +CMN_CSRCS += up_checkstack.c +endif + +ifeq ($(CONFIG_ARCH_FPU),y) +CMN_ASRCS += up_fpu.S +endif + +ifeq ($(CONFIG_ARCH_MEMCPY),y) +CMN_ASRCS += memcpy.S +endif + +CHIP_ASRCS = +CHIP_CSRCS = stm32_allocateheap.c stm32_start.c stm32_rcc.c stm32_lse.c \ + stm32_lsi.c stm32_gpio.c stm32_exti_gpio.c stm32_flash.c stm32_irq.c \ + stm32_timerisr.c stm32_dma.c stm32_lowputc.c stm32_serial.c \ + stm32_spi.c stm32_sdio.c stm32_tim.c stm32_i2c.c stm32_waste.c + +ifeq ($(CONFIG_USBDEV),y) +ifeq ($(CONFIG_STM32_USB),y) +CMN_CSRCS += stm32_usbdev.c +endif +ifeq ($(CONFIG_STM32_OTGFS),y) +CMN_CSRCS += stm32_otgfsdev.c +endif +endif + +ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y) +CHIP_ASRCS += stm32_vectors.S +endif + +ifneq ($(CONFIG_IDLE_CUSTOM),y) +CHIP_CSRCS += stm32_idle.c +endif + +CHIP_CSRCS += stm32_pmstop.c stm32_pmstandby.c stm32_pmsleep.c + +ifneq ($(CONFIG_PM_CUSTOMINIT),y) +CHIP_CSRCS += stm32_pminitialize.c +endif + +ifeq ($(CONFIG_STM32_ETHMAC),y) +CHIP_CSRCS += stm32_eth.c +endif + +ifeq ($(CONFIG_STM32_PWR),y) +CHIP_CSRCS += stm32_pwr.c +endif + +ifeq ($(CONFIG_RTC),y) +CHIP_CSRCS += stm32_rtc.c +ifeq ($(CONFIG_RTC_ALARM),y) +CHIP_CSRCS += stm32_exti_alarm.c +endif +endif + +ifeq ($(CONFIG_ADC),y) +CHIP_CSRCS += stm32_adc.c +endif + +ifeq ($(CONFIG_DAC),y) +CHIP_CSRCS += stm32_dac.c +endif + +ifeq ($(CONFIG_PWM),y) +CHIP_CSRCS += stm32_pwm.c +endif + +ifeq ($(CONFIG_QENCODER),y) +CHIP_CSRCS += stm32_qencoder.c +endif + +ifeq ($(CONFIG_CAN),y) +CHIP_CSRCS += stm32_can.c +endif + +ifeq ($(CONFIG_STM32_IWDG),y) +CHIP_CSRCS += stm32_iwdg.c +endif + +ifeq ($(CONFIG_STM32_WWDG),y) +CHIP_CSRCS += stm32_wwdg.c +endif + +ifeq ($(CONFIG_DEBUG),y) +CHIP_CSRCS += stm32_dumpgpio.c +endif diff --git a/nuttx/arch/arm/src/stm32/chip.h b/nuttx/arch/arm/src/stm32/chip.h new file mode 100644 index 0000000000..cc3ee1f96b --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip.h @@ -0,0 +1,100 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_H +#define __ARCH_ARM_SRC_STM32_CHIP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/* Include the chip capabilities file */ + +#include + +/* Include the chip pin configuration file */ + +#if defined(CONFIG_STM32_STM32F10XX) +# if defined(CONFIG_STM32_VALUELINE) +# include "chip/stm32f100_pinmap.h" +# elif defined(CONFIG_ARCH_CHIP_STM32F103ZET6) +# include "chip/stm32f103ze_pinmap.h" +# elif defined(CONFIG_ARCH_CHIP_STM32F103RET6) +# include "chip/stm32f103re_pinmap.h" +# elif defined(CONFIG_ARCH_CHIP_STM32F103VCT6) +# include "chip/stm32f103vc_pinmap.h" +# elif defined(CONFIG_ARCH_CHIP_STM32F105VBT7) +# include "chip/stm32f105vb_pinmap.h" +# elif defined(CONFIG_ARCH_CHIP_STM32F107VC) +# include "chip/stm32f107vc_pinmap.h" +# else +# error "Unsupported STM32F10XXX chip" +# endif +#elif defined(CONFIG_STM32_STM32F20XX) +# include "chip/stm32f20xxx_pinmap.h" +#elif defined(CONFIG_STM32_STM32F40XX) +# include "chip/stm32f40xxx_pinmap.h" +#else +# error "No pinmap file for this STM32 chip" +#endif + +/* If the common ARMv7-M vector handling logic is used, then include the + * required vector definitions as well. + */ + +#ifdef CONFIG_ARMV7M_CMNVECTOR +# if defined(CONFIG_STM32_STM32F10XX) +# include "chip/stm32f10xxx_vectors.h" +# elif defined(CONFIG_STM32_STM32F20XX) +# include "chip/stm32f20xxx_vectors.h" +# elif defined(CONFIG_STM32_STM32F40XX) +# include "chip/stm32f40xxx_vectors.h" +# else +# error "No vector file for this STM32 family" +# endif +#endif + +/* Include the chip memory map. */ + +#include "chip/stm32_memorymap.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_adc.h b/nuttx/arch/arm/src/stm32/chip/stm32_adc.h new file mode 100644 index 0000000000..218b11aa5b --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_adc.h @@ -0,0 +1,564 @@ +/**************************************************************************************************** + * arch/arm/src/stm32/chip/stm32_adc.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_ADC_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_ADC_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include + +#include "chip.h" + +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ + +/* Register Offsets *********************************************************************************/ + +#define STM32_ADC_SR_OFFSET 0x0000 /* ADC status register (32-bit) */ +#define STM32_ADC_CR1_OFFSET 0x0004 /* ADC control register 1 (32-bit) */ +#define STM32_ADC_CR2_OFFSET 0x0008 /* ADC control register 2 (32-bit) */ +#define STM32_ADC_SMPR1_OFFSET 0x000c /* ADC sample time register 1 (32-bit) */ +#define STM32_ADC_SMPR2_OFFSET 0x0010 /* ADC sample time register 2 (32-bit) */ +#define STM32_ADC_JOFR1_OFFSET 0x0014 /* ADC injected channel data offset register 1 (32-bit) */ +#define STM32_ADC_JOFR2_OFFSET 0x0018 /* ADC injected channel data offset register 2 (32-bit) */ +#define STM32_ADC_JOFR3_OFFSET 0x001c /* ADC injected channel data offset register 3 (32-bit) */ +#define STM32_ADC_JOFR4_OFFSET 0x0020 /* ADC injected channel data offset register 4 (32-bit) */ +#define STM32_ADC_HTR_OFFSET 0x0024 /* ADC watchdog high threshold register (32-bit) */ +#define STM32_ADC_LTR_OFFSET 0x0028 /* ADC watchdog low threshold register (32-bit) */ +#define STM32_ADC_SQR1_OFFSET 0x002c /* ADC regular sequence register 1 (32-bit) */ +#define STM32_ADC_SQR2_OFFSET 0x0030 /* ADC regular sequence register 2 (32-bit) */ +#define STM32_ADC_SQR3_OFFSET 0x0034 /* ADC regular sequence register 3 (32-bit) */ +#define STM32_ADC_JSQR_OFFSET 0x0038 /* ADC injected sequence register (32-bit) */ +#define STM32_ADC_JDR1_OFFSET 0x003c /* ADC injected data register 1 (32-bit) */ +#define STM32_ADC_JDR2_OFFSET 0x0040 /* ADC injected data register 1 (32-bit) */ +#define STM32_ADC_JDR3_OFFSET 0x0044 /* ADC injected data register 1 (32-bit) */ +#define STM32_ADC_JDR4_OFFSET 0x0048 /* ADC injected data register 1 (32-bit) */ +#define STM32_ADC_DR_OFFSET 0x004c /* ADC regular data register (32-bit) */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_ADC_CSR_OFFSET 0x0000 /* Common status register */ +# define STM32_ADC_CCR_OFFSET 0x0004 /* Common control register */ +# define STM32_ADC_CDR_OFFSET 0x0008 /* Data register for dual and triple modes */ +#endif + +/* Register Addresses *******************************************************************************/ + +#if STM32_NADC > 0 +# define STM32_ADC1_SR (STM32_ADC1_BASE+STM32_ADC_SR_OFFSET) +# define STM32_ADC1_CR1 (STM32_ADC1_BASE+STM32_ADC_CR1_OFFSET) +# define STM32_ADC1_CR2 (STM32_ADC1_BASE+STM32_ADC_CR2_OFFSET) +# define STM32_ADC1_SMPR1 (STM32_ADC1_BASE+STM32_ADC_SMPR1_OFFSET) +# define STM32_ADC1_SMPR2 (STM32_ADC1_BASE+STM32_ADC_SMPR2_OFFSET) +# define STM32_ADC1_JOFR1 (STM32_ADC1_BASE+STM32_ADC_JOFR1_OFFSET) +# define STM32_ADC1_JOFR2 (STM32_ADC1_BASE+STM32_ADC_JOFR2_OFFSET) +# define STM32_ADC1_JOFR3 (STM32_ADC1_BASE+STM32_ADC_JOFR3_OFFSET) +# define STM32_ADC1_JOFR4 (STM32_ADC1_BASE+STM32_ADC_JOFR4_OFFSET) +# define STM32_ADC1_HTR (STM32_ADC1_BASE+STM32_ADC_HTR_OFFSET) +# define STM32_ADC1_LTR (STM32_ADC1_BASE+STM32_ADC_LTR_OFFSET) +# define STM32_ADC1_SQR1 (STM32_ADC1_BASE+STM32_ADC_SQR1_OFFSET) +# define STM32_ADC1_SQR2 (STM32_ADC1_BASE+STM32_ADC_SQR2_OFFSET) +# define STM32_ADC1_SQR3 (STM32_ADC1_BASE+STM32_ADC_SQR3_OFFSET) +# define STM32_ADC1_JSQR (STM32_ADC1_BASE+STM32_ADC_JSQR_OFFSET) +# define STM32_ADC1_JDR1 (STM32_ADC1_BASE+STM32_ADC_JDR1_OFFSET) +# define STM32_ADC1_JDR2 (STM32_ADC1_BASE+STM32_ADC_JDR2_OFFSET) +# define STM32_ADC1_JDR3 (STM32_ADC1_BASE+STM32_ADC_JDR3_OFFSET) +# define STM32_ADC1_JDR4 (STM32_ADC1_BASE+STM32_ADC_JDR4_OFFSET) +# define STM32_ADC1_DR (STM32_ADC1_BASE+STM32_ADC_DR_OFFSET) +#endif + +#if STM32_NADC > 1 +# define STM32_ADC2_SR (STM32_ADC2_BASE+STM32_ADC_SR_OFFSET) +# define STM32_ADC2_CR1 (STM32_ADC2_BASE+STM32_ADC_CR1_OFFSET) +# define STM32_ADC2_CR2 (STM32_ADC2_BASE+STM32_ADC_CR2_OFFSET) +# define STM32_ADC2_SMPR1 (STM32_ADC2_BASE+STM32_ADC_SMPR1_OFFSET) +# define STM32_ADC2_SMPR2 (STM32_ADC2_BASE+STM32_ADC_SMPR2_OFFSET) +# define STM32_ADC2_JOFR1 (STM32_ADC2_BASE+STM32_ADC_JOFR1_OFFSET) +# define STM32_ADC2_JOFR2 (STM32_ADC2_BASE+STM32_ADC_JOFR2_OFFSET) +# define STM32_ADC2_JOFR3 (STM32_ADC2_BASE+STM32_ADC_JOFR3_OFFSET) +# define STM32_ADC2_JOFR4 (STM32_ADC2_BASE+STM32_ADC_JOFR4_OFFSET) +# define STM32_ADC2_HTR (STM32_ADC2_BASE+STM32_ADC_HTR_OFFSET) +# define STM32_ADC2_LTR (STM32_ADC2_BASE+STM32_ADC_LTR_OFFSET) +# define STM32_ADC2_SQR1 (STM32_ADC2_BASE+STM32_ADC_SQR1_OFFSET) +# define STM32_ADC2_SQR2 (STM32_ADC2_BASE+STM32_ADC_SQR2_OFFSET) +# define STM32_ADC2_SQR3 (STM32_ADC2_BASE+STM32_ADC_SQR3_OFFSET) +# define STM32_ADC2_JSQR (STM32_ADC2_BASE+STM32_ADC_JSQR_OFFSET) +# define STM32_ADC2_JDR1 (STM32_ADC2_BASE+STM32_ADC_JDR1_OFFSET) +# define STM32_ADC2_JDR2 (STM32_ADC2_BASE+STM32_ADC_JDR2_OFFSET) +# define STM32_ADC2_JDR3 (STM32_ADC2_BASE+STM32_ADC_JDR3_OFFSET) +# define STM32_ADC2_JDR4 (STM32_ADC2_BASE+STM32_ADC_JDR4_OFFSET) +# define STM32_ADC2_DR (STM32_ADC2_BASE+STM32_ADC_DR_OFFSET) +#endif + +#if STM32_NADC > 2 +# define STM32_ADC3_SR (STM32_ADC3_BASE+STM32_ADC_SR_OFFSET) +# define STM32_ADC3_CR1 (STM32_ADC3_BASE+STM32_ADC_CR1_OFFSET) +# define STM32_ADC3_CR2 (STM32_ADC3_BASE+STM32_ADC_CR2_OFFSET) +# define STM32_ADC3_SMPR1 (STM32_ADC3_BASE+STM32_ADC_SMPR1_OFFSET) +# define STM32_ADC3_SMPR2 (STM32_ADC3_BASE+STM32_ADC_SMPR2_OFFSET) +# define STM32_ADC3_JOFR1 (STM32_ADC3_BASE+STM32_ADC_JOFR1_OFFSET) +# define STM32_ADC3_JOFR2 (STM32_ADC3_BASE+STM32_ADC_JOFR2_OFFSET) +# define STM32_ADC3_JOFR3 (STM32_ADC3_BASE+STM32_ADC_JOFR3_OFFSET) +# define STM32_ADC3_JOFR4 (STM32_ADC3_BASE+STM32_ADC_JOFR4_OFFSET) +# define STM32_ADC3_HTR (STM32_ADC3_BASE+STM32_ADC_HTR_OFFSET) +# define STM32_ADC3_LTR (STM32_ADC3_BASE+STM32_ADC_LTR_OFFSET) +# define STM32_ADC3_SQR1 (STM32_ADC3_BASE+STM32_ADC_SQR1_OFFSET) +# define STM32_ADC3_SQR2 (STM32_ADC3_BASE+STM32_ADC_SQR2_OFFSET) +# define STM32_ADC3_SQR3 (STM32_ADC3_BASE+STM32_ADC_SQR3_OFFSET) +# define STM32_ADC3_JSQR (STM32_ADC3_BASE+STM32_ADC_JSQR_OFFSET) +# define STM32_ADC3_JDR1 (STM32_ADC3_BASE+STM32_ADC_JDR1_OFFSET) +# define STM32_ADC3_JDR2 (STM32_ADC3_BASE+STM32_ADC_JDR2_OFFSET) +# define STM32_ADC3_JDR3 (STM32_ADC3_BASE+STM32_ADC_JDR3_OFFSET) +# define STM32_ADC3_JDR4 (STM32_ADC3_BASE+STM32_ADC_JDR4_OFFSET) +# define STM32_ADC3_DR (STM32_ADC3_BASE+STM32_ADC_DR_OFFSET) +#endif + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_ADC_CSR (STM32_ADCCMN_BASE+STM32_ADC_CSR_OFFSET) +# define STM32_ADC_CCR (STM32_ADCCMN_BASE+STM32_ADC_CCR_OFFSET) +# define STM32_ADC_CDR (STM32_ADCCMN_BASE+STM32_ADC_CDR_OFFSET) +#endif + +/* Register Bitfield Definitions ********************************************************************/ + +/* ADC status register */ + +#define ADC_SR_AWD (1 << 0) /* Bit 0 : Analog watchdog flag */ +#define ADC_SR_EOC (1 << 1) /* Bit 1 : End of conversion */ +#define ADC_SR_JEOC (1 << 2) /* Bit 2 : Injected channel end of conversion */ +#define ADC_SR_JSTRT (1 << 3) /* Bit 3 : Injected channel Start flag */ +#define ADC_SR_STRT (1 << 4) /* Bit 4 : Regular channel Start flag */ +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define ADC_SR_OVR (1 << 5) /* Bit 5 : Overrun */ +#endif + +/* ADC control register 1 */ + +#define ADC_CR1_AWDCH_SHIFT (0) /* Bits 4-0: Analog watchdog channel select bits */ +#define ADC_CR1_AWDCH_MASK (0x1f << ADC_CR1_AWDCH_SHIFT) + +#define ADC_CR1_EOCIE (1 << 5) /* Bit 5: Interrupt enable for EOC */ +#define ADC_CR1_AWDIE (1 << 6) /* Bit 6: Analog Watchdog interrupt enable */ +#define ADC_CR1_JEOCIE (1 << 7) /* Bit 7: Interrupt enable for injected channels */ +#define ADC_CR1_SCAN (1 << 8) /* Bit 8: Scan mode */ +#define ADC_CR1_AWDSGL (1 << 9) /* Bit 9: Enable the watchdog on a single channel in scan mode */ +#define ADC_CR1_JAUTO (1 << 10) /* Bit 10: Automatic Injected Group conversion */ +#define ADC_CR1_DISCEN (1 << 11) /* Bit 11: Discontinuous mode on regular channels */ +#define ADC_CR1_JDISCEN (1 << 12) /* Bit 12: Discontinuous mode on injected channels */ + +#define ADC_CR1_DISCNUM_SHIFT (13) /* Bits 15-13: Discontinuous mode channel count */ +#define ADC_CR1_DISCNUM_MASK (0x07 << ADC_CR1_DISCNUM_SHIFT) + +#ifdef CONFIG_STM32_STM32F10XX +# define ADC_CR1_DUALMOD_SHIFT (16) /* Bits 19-16: Dual mode selection */ +# define ADC_CR1_DUALMOD_MASK (0x0f << ADC_CR1_DUALMOD_SHIFT) +# define ADC_CR1_IND (0 << ADC_CR1_DUALMOD_SHIFT) /* 0000: Independent mode */ +# define ADC_CR1_RSIS (1 << ADC_CR1_DUALMOD_SHIFT) /* 0001: Combined regular simultaneous + injected simultaneous mode */ +# define ADC_CR1_RSAT (2 << ADC_CR1_DUALMOD_SHIFT) /* 0010: Combined regular simultaneous + alternate trigger mode */ +# define ADC_CR1_ISFI (3 << ADC_CR1_DUALMOD_SHIFT) /* 0011: Combined injected simultaneous + fast interleaved mode */ +# define ADC_CR1_ISFL (4 << ADC_CR1_DUALMOD_SHIFT) /* 0100: Combined injected simultaneous + slow Interleaved mode */ +# define ADC_CR1_IS (5 << ADC_CR1_DUALMOD_SHIFT) /* 0101: Injected simultaneous mode only */ +# define ADC_CR1_RS (6 << ADC_CR1_DUALMOD_SHIFT) /* 0110: Regular simultaneous mode only */ +# define ADC_CR1_FI (7 << ADC_CR1_DUALMOD_SHIFT) /* 0111: Fast interleaved mode only */ +# define ADC_CR1_SI (8 << ADC_CR1_DUALMOD_SHIFT) /* 1000: Slow interleaved mode only */ +# define ADC_CR1_AT (9 << ADC_CR1_DUALMOD_SHIFT) /* 1001: Alternate trigger mode only */ +#endif + +#define ADC_CR1_JAWDEN (1 << 22) /* Bit 22: Analog watchdog enable on injected channels */ +#define ADC_CR1_AWDEN (1 << 23) /* Bit 23: Analog watchdog enable on regular channels */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define ACD_CR1_RES_SHIFT (24) /* Bits 24-25: Resolution */ +# define ACD_CR1_RES_MASK (3 << ACD_CR1_RES_SHIFT) +# define ACD_CR1_RES_12BIT (0 << ACD_CR1_RES_SHIFT) /* 15 ADCCLK clyes */ +# define ACD_CR1_RES_10BIT (1 << ACD_CR1_RES_SHIFT) /* 13 ADCCLK clyes */ +# define ACD_CR1_RES_8BIT (2 << ACD_CR1_RES_SHIFT) /* 11 ADCCLK clyes */ +# define ACD_CR1_RES_6BIT (3 << ACD_CR1_RES_SHIFT) /* 9 ADCCLK clyes */ +# define ADC_CR1_OVRIE (1 << 26) /* Bit 26: Overrun interrupt enable */ +#endif + +/* ADC control register 2 */ + +#define ADC_CR2_ADON (1 << 0) /* Bit 0: A/D Converter ON / OFF */ +#define ADC_CR2_CONT (1 << 1) /* Bit 1: Continuous Conversion */ + +#ifdef CONFIG_STM32_STM32F10XX +# define ADC_CR2_CAL (1 << 2) /* Bit 2: A/D Calibration */ +#endif + +#define ADC_CR2_RSTCAL (1 << 3) /* Bit 3: Reset Calibration */ +#define ADC_CR2_DMA (1 << 8) /* Bit 8: Direct Memory access mode */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define ADC_CR2_DDS (1 << 9) /* Bit 9: DMA disable selection (for single ADC mode) */ +# define ADC_CR2_EOCS (1 << 10) /* Bit 10: End of conversion selection */ +#endif + +#define ADC_CR2_ALIGN (1 << 11) /* Bit 11: Data Alignment */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + /* Bits 12-15: Reserved */ +# define ADC_CR2_JEXTSEL_SHIFT (16) /* Bits 16-19: External event select for injected group */ +# define ADC_CR2_JEXTSEL_MASK (15 << ADC_CR2_JEXTSEL_SHIFT) +# define ADC_CR2_JEXTSEL_T1CC4 (0 << ADC_CR2_JEXTSEL_SHIFT) /* 0000: Timer 1 CC4 event */ +# define ADC_CR2_JEXTSEL_T1TRGO (1 << ADC_CR2_JEXTSEL_SHIFT) /* 0001: Timer 1 TRGO event */ +# define ADC_CR2_JEXTSEL_T2CC1 (2 << ADC_CR2_JEXTSEL_SHIFT) /* 0010: Timer 2 CC1 event */ +# define ADC_CR2_JEXTSEL_T2TRGO (3 << ADC_CR2_JEXTSEL_SHIFT) /* 0011: Timer 2 TRGO event */ +# define ADC_CR2_JEXTSEL_T3CC2 (4 << ADC_CR2_JEXTSEL_SHIFT) /* 0100: Timer 3 CC2 event */ +# define ADC_CR2_JEXTSEL_T3CC4 (5 << ADC_CR2_JEXTSEL_SHIFT) /* 0101: Timer 3 CC4 event */ +# define ADC_CR2_JEXTSEL_T4CC1 (6 << ADC_CR2_JEXTSEL_SHIFT) /* 0110: Timer 4 CC1 event */ +# define ADC_CR2_JEXTSEL_T4CC2 (7 << ADC_CR2_JEXTSEL_SHIFT) /* 0111: Timer 4 CC2 event */ +# define ADC_CR2_JEXTSEL_T4CC3 (8 << ADC_CR2_JEXTSEL_SHIFT) /* 1000: Timer 4 CC3 event */ +# define ADC_CR2_JEXTSEL_T4TRGO (9 << ADC_CR2_JEXTSEL_SHIFT) /* 1001: Timer 4 TRGO event */ +# define ADC_CR2_JEXTSEL_T5CC4 (10 << ADC_CR2_JEXTSEL_SHIFT) /* 1010: Timer 5 CC4 event */ +# define ADC_CR2_JEXTSEL_T5TRGO (11 << ADC_CR2_JEXTSEL_SHIFT) /* 1011: Timer 5 TRGO event */ +# define ADC_CR2_JEXTSEL_T8CC2 (12 << ADC_CR2_JEXTSEL_SHIFT) /* 1100: Timer 8 CC2 event */ +# define ADC_CR2_JEXTSEL_T8CC3 (13 << ADC_CR2_JEXTSEL_SHIFT) /* 1101: Timer 8 CC3 event */ +# define ADC_CR2_JEXTSEL_T8CC4 (14 << ADC_CR2_JEXTSEL_SHIFT) /* 1110: Timer 8 CC4 event */ +# define ADC_CR2_JEXTSEL_EXTI (15 << ADC_CR2_JEXTSEL_SHIFT) /* 1111: EXTI line15 */ + +# define ACD_CR2_JEXTEN_SHIFT (20) /* Bits 20-21: External trigger enable for injected channels */ +# define ACD_CR2_JEXTEN_MASK (3 << ACD_CR2_JEXTEN_SHIFT) +# define ACD_CR2_JEXTEN_NONE (0 << ACD_CR2_JEXTEN_SHIFT) /* 00: Trigger detection disabled */ +# define ACD_CR2_JEXTEN_RISING (1 << ACD_CR2_JEXTEN_SHIFT) /* 01: Trigger detection on the rising edge */ +# define ACD_CR2_JEXTEN_FALLING (2 << ACD_CR2_JEXTEN_SHIFT) /* 10: Trigger detection on the falling edge */ +# define ACD_CR2_JEXTEN_BOTH (3 << ACD_CR2_JEXTEN_SHIFT) /* 11: Trigger detection on both the rising and falling edges */ + +# define ADC_CR2_JSWSTART (1 << 22) /* Bit 22: Start Conversion of injected channels */ + /* Bit 23: Reserved, must be kept at reset value. */ +# define ADC_CR2_EXTSEL_SHIFT (24) /* Bits 24-27: External Event Select for regular group */ +# define ADC_CR2_EXTSEL_MASK (15 << ADC_CR2_EXTSEL_SHIFT) +# define ADC_CR2_EXTSEL_T1CC1 (0 << ADC_CR2_EXTSEL_SHIFT) /* 0000: Timer 1 CC1 event */ +# define ADC_CR2_EXTSEL_T1CC2 (1 << ADC_CR2_EXTSEL_SHIFT) /* 0001: Timer 1 CC2 event */ +# define ADC_CR2_EXTSEL_T1CC3 (2 << ADC_CR2_EXTSEL_SHIFT) /* 0010: Timer 1 CC3 event */ +# define ADC_CR2_EXTSEL_T2CC2 (3 << ADC_CR2_EXTSEL_SHIFT) /* 0011: Timer 2 CC2 event */ +# define ADC_CR2_EXTSEL_T2CC3 (4 << ADC_CR2_EXTSEL_SHIFT) /* 0100: Timer 2 CC3 event */ +# define ADC_CR2_EXTSEL_T2CC4 (5 << ADC_CR2_EXTSEL_SHIFT) /* 0101: Timer 2 CC4 event */ +# define ADC_CR2_EXTSEL_T2TRGO (6 << ADC_CR2_EXTSEL_SHIFT) /* 0110: Timer 2 TRGO event */ +# define ADC_CR2_EXTSEL_T3CC1 (7 << ADC_CR2_EXTSEL_SHIFT) /* 0111: Timer 3 CC1 event */ +# define ADC_CR2_EXTSEL_T3TRGO (8 << ADC_CR2_EXTSEL_SHIFT) /* 1000: Timer 3 TRGO event */ +# define ADC_CR2_EXTSEL_T4CC4 (9 << ADC_CR2_EXTSEL_SHIFT) /* 1001: Timer 4 CC4 event */ +# define ADC_CR2_EXTSEL_T5CC1 (10 << ADC_CR2_EXTSEL_SHIFT) /* 1010: Timer 5 CC1 event */ +# define ADC_CR2_EXTSEL_T5CC2 (11 << ADC_CR2_EXTSEL_SHIFT) /* 1011: Timer 5 CC2 event */ +# define ADC_CR2_EXTSEL_T5CC3 (12 << ADC_CR2_EXTSEL_SHIFT) /* 1100: Timer 5 CC3 event */ +# define ADC_CR2_EXTSEL_T8CC1 (13 << ADC_CR2_EXTSEL_SHIFT) /* 1101: Timer 8 CC1 event */ +# define ADC_CR2_EXTSEL_T8TRGO (14 << ADC_CR2_EXTSEL_SHIFT) /* 1110: Timer 8 TRGO event */ +# define ADC_CR2_EXTSEL_EXTI (15 << ADC_CR2_EXTSEL_SHIFT) /* 1111: EXTI line11 */ + +# define ACD_CR2_EXTEN_SHIFT (28) /* Bits 28-29: External trigger enable for regular channels */ +# define ACD_CR2_EXTEN_MASK (3 << ACD_CR2_EXTEN_SHIFT) +# define ACD_CR2_EXTEN_NONE (0 << ACD_CR2_EXTEN_SHIFT) /* 00: Trigger detection disabled */ +# define ACD_CR2_EXTEN_RISING (1 << ACD_CR2_EXTEN_SHIFT) /* 01: Trigger detection on the rising edge */ +# define ACD_CR2_EXTEN_FALLING (2 << ACD_CR2_EXTEN_SHIFT) /* 10: Trigger detection on the falling edge */ +# define ACD_CR2_EXTEN_BOTH (3 << ACD_CR2_EXTEN_SHIFT) /* 11: Trigger detection on both the rising and falling edges */ + +# define ADC_CR2_SWSTART (1 << 30) /* Bit 30: Start Conversion of regular channels */ + +#else +# define ADC_CR2_JEXTSEL_SHIFT (12) /* Bits 12-14: External event select for injected group */ +# define ADC_CR2_JEXTSEL_MASK (7 << ADC_CR2_JEXTSEL_SHIFT) +# define ADC_CR2_JEXTSEL_T1TRGO (0 << ADC_CR2_JEXTSEL_SHIFT) /* 000: Timer 1 TRGO event */ +# define ADC_CR2_JEXTSEL_T1CC4 (1 << ADC_CR2_JEXTSEL_SHIFT) /* 001: Timer 1 CC4 event */ +# define ADC_CR2_JEXTSEL_T2TRGO (2 << ADC_CR2_JEXTSEL_SHIFT) /* 010: Timer 2 TRGO event */ +# define ADC_CR2_JEXTSEL_T2CC1 (3 << ADC_CR2_JEXTSEL_SHIFT) /* 011: Timer 2 CC1 event */ +# define ADC_CR2_JEXTSEL_T3CC4 (4 << ADC_CR2_JEXTSEL_SHIFT) /* 100: Timer 3 CC4 event */ +# define ADC_CR2_JEXTSEL_T4TRGO (5 << ADC_CR2_JEXTSEL_SHIFT) /* 101: Timer 4 TRGO event */ +# define ADC_CR2_JEXTSEL_EXTI15 (6 << ADC_CR2_JEXTSEL_SHIFT) /* 110: EXTI line15 */ +# define ADC_CR2_JEXTSEL_SWSTART (7 << ADC_CR2_JEXTSEL_SHIFT) /* 111: JSWSTART */ + +# define ADC_CR2_JEXTTRIG (1 << 15) /* Bit 15: External Trigger Conversion mode for injected channels */ +# define ADC_CR2_EXTSEL_SHIFT (17) /* Bits 19-17: External Event Select for regular group */ +# define ADC_CR2_EXTSEL_MASK (7 << ADC_CR2_EXTSEL_SHIFT) +# define ADC_CR2_EXTSEL_T1CC1 (0 << ADC_CR2_EXTSEL_SHIFT) /* 000: Timer 1 CC1 event */ +# define ADC_CR2_EXTSEL_T1CC2 (1 << ADC_CR2_EXTSEL_SHIFT) /* 001: Timer 1 CC2 event */ +# define ADC_CR2_EXTSEL_T1CC3 (2 << ADC_CR2_EXTSEL_SHIFT) /* 010: Timer 1 CC3 event */ +# define ADC_CR2_EXTSEL_T2CC2 (3 << ADC_CR2_EXTSEL_SHIFT) /* 011: Timer 2 CC2 event */ +# define ADC_CR2_EXTSEL_T3TRGO (4 << ADC_CR2_EXTSEL_SHIFT) /* 100: Timer 3 TRGO event */ +# define ADC_CR2_EXTSEL_T4CC4 (5 << ADC_CR2_EXTSEL_SHIFT) /* 101: Timer 4 CC4 event */ +# define ADC_CR2_EXTSEL_EXTI11 (6 << ADC_CR2_EXTSEL_SHIFT) /* 110: EXTI line11 */ +# define ADC_CR2_EXTSEL_SWSTART (7 << ADC_CR2_EXTSEL_SHIFT) /* 111: SWSTART */ + +# define ADC_CR2_EXTTRIG (1 << 20) /* Bit 20: External Trigger Conversion mode for regular channels */ +# define ADC_CR2_JSWSTART (1 << 21) /* Bit 21: Start Conversion of injected channels */ +# define ADC_CR2_SWSTART (1 << 22) /* Bit 22: Start Conversion of regular channels */ +# define ADC_CR2_TSVREFE (1 << 23) /* Bit 23: Temperature Sensor and VREFINT Enable */ +#endif + +/* ADC sample time register 1 */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + +# define ADC_SMPR_3 0 /* 000: 3 cycles */ +# define ADC_SMPR_15 1 /* 001: 15 cycles */ +# define ADC_SMPR_28 2 /* 010: 28 cycles */ +# define ADC_SMPR_56 3 /* 011: 56 cycles */ +# define ADC_SMPR_84 4 /* 100: 84 cycles */ +# define ADC_SMPR_112 5 /* 101: 112 cycles */ +# define ADC_SMPR_144 6 /* 110: 144 cycles */ +# define ADC_SMPR_480 7 /* 111: 480 cycles */ + +#else + +# define ADC_SMPR_1p5 0 /* 000: 1.5 cycles */ +# define ADC_SMPR_7p5 1 /* 001: 7.5 cycles */ +# define ADC_SMPR_13p5 2 /* 010: 13.5 cycles */ +# define ADC_SMPR_28p5 3 /* 011: 28.5 cycles */ +# define ADC_SMPR_41p5 4 /* 100: 41.5 cycles */ +# define ADC_SMPR_55p5 5 /* 101: 55.5 cycles */ +# define ADC_SMPR_71p5 6 /* 110: 71.5 cycles */ +# define ADC_SMPR_239p5 7 /* 111: 239.5 cycles */ + +#endif + +#define ADC_SMPR1_SMP10_SHIFT (0) /* Bits 0-2: Channel 10 Sample time selection */ +#define ADC_SMPR1_SMP10_MASK (7 << ADC_SMPR1_SMP10_SHIFT) +#define ADC_SMPR1_SMP11_SHIFT (3) /* Bits 3-5: Channel 11 Sample time selection */ +#define ADC_SMPR1_SMP11_MASK (7 << ADC_SMPR1_SMP11_SHIFT) +#define ADC_SMPR1_SMP12_SHIFT (6) /* Bits 6-8: Channel 12 Sample time selection */ +#define ADC_SMPR1_SMP12_MASK (7 << ADC_SMPR1_SMP12_SHIFT) +#define ADC_SMPR1_SMP13_SHIFT (9) /* Bits 9-11: Channel 13 Sample time selection */ +#define ADC_SMPR1_SMP13_MASK (7 << ADC_SMPR1_SMP13_SHIFT) +#define ADC_SMPR1_SMP14_SHIFT (12) /* Bits 12-14: Channel 14 Sample time selection */ +#define ADC_SMPR1_SMP14_MASK (7 << ADC_SMPR1_SMP14_SHIFT) +#define ADC_SMPR1_SMP15_SHIFT (15) /* Bits 15-17: Channel 15 Sample time selection */ +#define ADC_SMPR1_SMP15_MASK (7 << ADC_SMPR1_SMP15_SHIFT) +#define ADC_SMPR1_SMP16_SHIFT (18) /* Bits 18-20: Channel 16 Sample time selection */ +#define ADC_SMPR1_SMP16_MASK (7 << ADC_SMPR1_SMP16_SHIFT) +#define ADC_SMPR1_SMP17_SHIFT (21) /* Bits 21-23: Channel 17 Sample time selection */ +#define ADC_SMPR1_SMP17_MASK (7 << ADC_SMPR1_SMP17_SHIFT) +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define ADC_SMPR1_SMP18_SHIFT (21) /* Bits 24-26: Channel 18 Sample time selection */ +# define ADC_SMPR1_SMP18_MASK (7 << ADC_SMPR1_SMP17_SHIFT) +#endif + +/* ADC sample time register 2 */ + +#define ADC_SMPR2_SMP0_SHIFT (0) /* Bits 2-0: Channel 0 Sample time selection */ +#define ADC_SMPR2_SMP0_MASK (7 << ADC_SMPR1_SMP0_SHIFT) +#define ADC_SMPR2_SMP1_SHIFT (3) /* Bits 5-3: Channel 1 Sample time selection */ +#define ADC_SMPR2_SMP1_MASK (7 << ADC_SMPR1_SMP1_SHIFT) +#define ADC_SMPR2_SMP2_SHIFT (6) /* Bits 8-6: Channel 2 Sample time selection */ +#define ADC_SMPR2_SMP2_MASK (7 << ADC_SMPR1_SMP2_SHIFT) +#define ADC_SMPR2_SMP3_SHIFT (9) /* Bits 11-9: Channel 3 Sample time selection */ +#define ADC_SMPR2_SMP3_MASK (7 << ADC_SMPR1_SMP3_SHIFT) +#define ADC_SMPR2_SMP4_SHIFT (12) /* Bits 14-12: Channel 4 Sample time selection */ +#define ADC_SMPR2_SMP4_MASK (7 << ADC_SMPR1_SMP4_SHIFT) +#define ADC_SMPR2_SMP5_SHIFT (15) /* Bits 17-15: Channel 5 Sample time selection */ +#define ADC_SMPR2_SMP5_MASK (7 << ADC_SMPR1_SMP5_SHIFT) +#define ADC_SMPR2_SMP6_SHIFT (18) /* Bits 20-18: Channel 6 Sample time selection */ +#define ADC_SMPR2_SMP6_MASK (7 << ADC_SMPR1_SMP6_SHIFT) +#define ADC_SMPR2_SMP7_SHIFT (21) /* Bits 23-21: Channel 7 Sample time selection */ +#define ADC_SMPR2_SMP7_MASK (7 << ADC_SMPR1_SMP7_SHIFT) +#define ADC_SMPR2_SMP8_SHIFT (24) /* Bits 26-24: Channel 8 Sample time selection */ +#define ADC_SMPR2_SMP8_MASK (7 << ADC_SMPR1_SMP8_SHIFT) +#define ADC_SMPR2_SMP9_SHIFT (27) /* Bits 29-27: Channel 9 Sample time selection */ +#define ADC_SMPR2_SMP9_MASK (7 << ADC_SMPR1_SMP9_SHIFT) + +/* ADC injected channel data offset register 1-4 */ + +#define ADC_JOFR_SHIFT (0) /* Bits 11-0: Data offset for injected channel x */ +#define ADC_JOFR_MASK (0x0fff << ADC_JOFR_SHIFT) + +/* ADC watchdog high threshold register */ + +#define ADC_HTR_SHIFT (0) /* Bits 11-0: Analog watchdog high threshold */ +#define ADC_HTR_MASK (0x0fff << ADC_HTR_SHIFT) + +/* ADC watchdog low threshold register */ + +#define ADC_LTR_SHIFT (0) /* Bits 11-0: Analog watchdog low threshold */ +#define ADC_LTR_MASK (0x0fff << ADC_LTR_SHIFT) + +/* ADC regular sequence register 1 */ + +#define ADC_SQR1_SQ13_SHIFT (0) /* Bits 4-0: 13th conversion in regular sequence */ +#define ADC_SQR1_SQ13_MASK (0x1f << ADC_SQR1_SQ13_SHIFT) +#define ADC_SQR1_SQ14_SHIFT (5) /* Bits 9-5: 14th conversion in regular sequence */ +#define ADC_SQR1_SQ14_MASK (0x1f << ADC_SQR1_SQ14_SHIFT) +#define ADC_SQR1_SQ15_SHIFT (10) /* Bits 14-10: 15th conversion in regular sequence */ +#define ADC_SQR1_SQ15_MASK (0x1f << ADC_SQR1_SQ15_SHIFT) +#define ADC_SQR1_SQ16_SHIFT (15) /* Bits 19-15: 16th conversion in regular sequence */ +#define ADC_SQR1_SQ16_MASK (0x1f << ADC_SQR1_SQ16_SHIFT) +#define ADC_SQR1_L_SHIFT (20) /* Bits 23-20: Regular channel sequence length */ +#define ADC_SQR1_L_MASK (0x0f << ADC_SQR1_L_SHIFT) +#define ADC_SQR1_RESERVED (0xff000000) + +/* ADC regular sequence register 2 */ + +#define ADC_SQR2_SQ7_SHIFT (0) /* Bits 4-0: 7th conversion in regular sequence */ +#define ADC_SQR2_SQ7_MASK (0x1f << ADC_SQR2_SQ7_SHIFT) +#define ADC_SQR2_SQ8_SHIFT (5) /* Bits 9-5: 8th conversion in regular sequence */ +#define ADC_SQR2_SQ8_MASK (0x1f << ADC_SQR2_SQ8_SHIFT) +#define ADC_SQR2_SQ9_SHIFT (10) /* Bits 14-10: 9th conversion in regular sequence */ +#define ADC_SQR2_SQ9_MASK (0x1f << ADC_SQR2_SQ9_SHIFT) +#define ADC_SQR2_SQ10_SHIFT (15) /* Bits 19-15: 10th conversion in regular sequence */ +#define ADC_SQR2_SQ10_MASK (0x1f << ADC_SQR2_SQ10_SHIFT) +#define ADC_SQR2_SQ11_SHIFT (20) /* Bits 24-20: 11th conversion in regular sequence */ +#define ADC_SQR2_SQ11_MASK (0x1f << ADC_SQR2_SQ11_SHIFT ) +#define ADC_SQR2_SQ12_SHIFT (25) /* Bits 29-25: 12th conversion in regular sequence */ +#define ADC_SQR2_SQ12_MASK (0x1f << ADC_SQR2_SQ12_SHIFT) +#define ADC_SQR2_RESERVED (0xc0000000) + +/* ADC regular sequence register 3 */ + +#define ADC_SQR3_SQ1_SHIFT (0) /* Bits 4-0: 1st conversion in regular sequence */ +#define ADC_SQR3_SQ1_MASK (0x1f << ADC_SQR3_SQ1_SHIFT) +#define ADC_SQR3_SQ2_SHIFT (5) /* Bits 9-5: 2nd conversion in regular sequence */ +#define ADC_SQR3_SQ2_MASK (0x1f << ADC_SQR3_SQ2_SHIFT) +#define ADC_SQR3_SQ3_SHIFT (10) /* Bits 14-10: 3rd conversion in regular sequence */ +#define ADC_SQR3_SQ3_MASK (0x1f << ADC_SQR3_SQ3_SHIFT) +#define ADC_SQR3_SQ4_SHIFT (15) /* Bits 19-15: 4th conversion in regular sequence */ +#define ADC_SQR3_SQ4_MASK (0x1f << ADC_SQR3_SQ4_SHIFT) +#define ADC_SQR3_SQ5_SHIFT (20) /* Bits 24-20: 5th conversion in regular sequence */ +#define ADC_SQR3_SQ5_MASK (0x1f << ADC_SQR3_SQ5_SHIFT ) +#define ADC_SQR3_SQ6_SHIFT (25) /* Bits 29-25: 6th conversion in regular sequence */ +#define ADC_SQR3_SQ6_MASK (0x1f << ADC_SQR3_SQ6_SHIFT) +#define ADC_SQR3_RESERVED (0xc0000000) + +/* ADC injected sequence register */ + +#define ADC_JSQR_JSQ1_SHIFT (0) /* Bits 4-0: 1st conversion in injected sequence */ +#define ADC_JSQR_JSQ1_MASK (0x1f << ADC_JSQR_JSQ1_SHIFT) +#define ADC_JSQR_JSQ2_SHIFT (5) /* Bits 9-5: 2nd conversion in injected sequence */ +#define ADC_JSQR_JSQ2_MASK (0x1f << ADC_JSQR_JSQ2_MASK) +#define ADC_JSQR_JSQ3_SHIFT (10) /* Bits 14-10: 3rd conversion in injected sequence */ +#define ADC_JSQR_JSQ3_MASK (0x1f << ADC_JSQR_JSQ3_SHIFT) +#define ADC_JSQR_JSQ4_SHIFT (15) /* Bits 19-15: 4th conversion in injected sequence */ +#define ADC_JSQR_JSQ4_MASK (0x1f << ADC_JSQR_JSQ4_SHIFT) +#define ADC_JSQR_JL_SHIFT (20) /* Bits 21-20: Injected Sequence length */ +#define ADC_JSQR_JL_MASK (3 << ADC_JSQR_JL_SHIFT) + +/* ADC injected data register 1-4 */ + +#define ADC_JDR_SHIFT (0) /* Bits 15-0: Injected data */ +#define ADC_JDR_MASK (0xffff << ADC_JDR_SHIFT) + +/* ADC regular data register */ + +#define ADC_DR_DATA_SHIFT (0) /* Bits 15-0 Regular data */ +#define ADC_DR_DATA_MASK (0xffff << ADC_DR_DATA_SHIFT) +#define ADC_DR_ADC2DATA_SHIFT (16) /* Bits 31-16: ADC2 data */ +#define ADC_DR_ADC2DATA_MASK (0xffff << ADC_DR_ADC2DATA_SHIFT) + +/* Common status register */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define ADC_CSR_AWD1 (1 << 0) /* Bit 0: Analog watchdog flag of ADC1 (copy of AWD in ADC1_SR) */ +# define ADC_CSR_EOC1 (1 << 1) /* Bit 1: End of conversion of ADC1 (copy of EOC in ADC1_SR) */ +# define ADC_CSR_JEOC1 (1 << 2) /* Bit 2: Injected channel end of conversion of ADC1 (copy of JEOC in ADC1_SR) */ +# define ADC_CSR_JSTRT1 (1 << 3) /* Bit 3: Injected channel Start flag of ADC1 (copy of JSTRT in ADC1_SR) */ +# define ADC_CSR_STRT1 (1 << 4) /* Bit 4: Regular channel Start flag of ADC1 (copy of STRT in ADC1_SR) */ +# define ADC_CSR_OVR1 (1 << 5) /* Bit 5: Overrun flag of ADC1 (copy of OVR in ADC1_SR) */ + /* Bits 6-7: Reserved, must be kept at reset value. */ +# define ADC_CSR_AWD2 (1 << 8) /* Bit 8: Analog watchdog flag of ADC2 (copy of AWD in ADC2_SR) */ +# define ADC_CSR_EOC2 (1 << 9) /* Bit 9: End of conversion of ADC2 (copy of EOC in ADC2_SR) */ +# define ADC_CSR_JEOC2 (1 << 10) /* Bit 10: Injected channel end of conversion of ADC2 (copy of JEOC in ADC2_SR) */ +# define ADC_CSR_JSTRT2 (1 << 11) /* Bit 11: Injected channel Start flag of ADC2 (copy of JSTRT in ADC2_SR) */ +# define ADC_CSR_STRT2 (1 << 12) /* Bit 12: Regular channel Start flag of ADC2 (copy of STRT in ADC2_SR) */ +# define ADC_CSR_OVR2 (1 << 13) /* Bit 13: Overrun flag of ADC2 (copy of OVR in ADC2_SR) */ + /* Bits 14-15: Reserved, must be kept at reset value. */ +# define ADC_CSR_AWD3 (1 << 16) /* Bit 16: ADC3 Analog watchdog flag (copy of AWD in ADC3_SR) */ +# define ADC_CSR_EOC3 (1 << 17) /* Bit 17: ADC3 End of conversion (copy of EOC in ADC3_SR) */ +# define ADC_CSR_JEOC3 (1 << 18) /* Bit 18: ADC3 Injected channel end of conversion (copy of JEOC in ADC3_SR) */ +# define ADC_CSR_JSTRT3 (1 << 19) /* Bit 19: ADC3 Injected channel Start flag (copy of JSTRT in ADC3_SR) */ +# define ADC_CSR_STRT3 (1 << 20) /* Bit 20: ADC3 Regular channel Start flag (copy of STRT in ADC3_SR). */ +# define ADC_CSR_OVR3 (1 << 21) /* Bit 21: ADC3 overrun flag (copy of OVR in ADC3_SR). */ + /* Bits 22-31: Reserved, must be kept at reset value. */ +#endif + +/* Common control register */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define ADC_CCR_MULTI_SHIFT (0) /* Bits 0-4: Multi ADC mode selection */ +# define ADC_CCR_MULTI_MASK (31 << ADC_CCR_MULTI_SHIFT) +# define ADC_CCR_MULTI_NONE (0 << ADC_CCR_MULTI_SHIFT) /* 00000: Independent mode */ + /* 00001 to 01001: Dual mode (ADC1 and ADC2), ADC3 independent */ +# define ADC_CCR_MULTI_RSISM2 (1 << ADC_CCR_MULTI_SHIFT) /* 00001: Combined regular simultaneous + injected simultaneous mode */ +# define ADC_CCR_MULTI_RSATM2 (2 << ADC_CCR_MULTI_SHIFT) /* 00010: Combined regular simultaneous + alternate trigger mode */ +# define ADC_CCR_MULTI_ISM2 (5 << ADC_CCR_MULTI_SHIFT) /* 00101: Injected simultaneous mode only */ +# define ADC_CCR_MULTI_RSM2 (6 << ADC_CCR_MULTI_SHIFT) /* 00110: Regular simultaneous mode only */ +# define ADC_CCR_MULTI_IM2 (7 << ADC_CCR_MULTI_SHIFT) /* 00111: interleaved mode only */ +# define ADC_CCR_MULTI_ATM2 (9 << ADC_CCR_MULTI_SHIFT) /* 01001: Alternate trigger mode only */ + /* 10001 to 11001: Triple mode (ADC1, 2 and 3) */ +# define ADC_CCR_MULTI_RSISM3 (17 << ADC_CCR_MULTI_SHIFT) /* 10001: Combined regular simultaneous + injected simultaneous mode */ +# define ADC_CCR_MULTI_RSATM3 (18 << ADC_CCR_MULTI_SHIFT) /* 10010: Combined regular simultaneous + alternate trigger mode */ +# define ADC_CCR_MULTI_ISM3 (21 << ADC_CCR_MULTI_SHIFT) /* 10101: Injected simultaneous mode only */ +# define ADC_CCR_MULTI_RSM3 (22 << ADC_CCR_MULTI_SHIFT) /* 10110: Regular simultaneous mode only */ +# define ADC_CCR_MULTI_IM3 (23 << ADC_CCR_MULTI_SHIFT) /* 10111: interleaved mode only */ +# define ADC_CCR_MULTI_ATM3 (25 << ADC_CCR_MULTI_SHIFT) /* 11001: Alternate trigger mode only */ + /* Bits 5-7: Reserved, must be kept at reset value. */ +# define ADC_CCR_DELAY_SHIFT (8) /* Bits 8-11: Delay between 2 sampling phases */ +# define ADC_CCR_DELAY_MASK (15 << ADC_CCR_DELAY_SHIFT) +# define ADC_CCR_DELAY(n) (((5)-5) << ADC_CCR_DELAY_SHIFT) /* n * TADCCLK, n=5-20 */ + /* Bit 12 Reserved, must be kept at reset value. */ +# define ADC_CCR_DDS (1 << 13) /* Bit 13: DMA disable selection (for multi-ADC mode) */ + +# define ADC_CCR_DMA_SHIFT (14) /* Bits 14-15: Direct memory access mode for multi ADC mode */ +# define ADC_CCR_DMA_MASK (3 << ADC_CCR_DMA_SHIFT) +# define ADC_CCR_DMA_DISABLED (0 << ADC_CCR_DMA_SHIFT) /* 00: DMA mode disabled */ +# define ADC_CCR_DMA_MODE1 (1 << ADC_CCR_DMA_SHIFT) /* 01: DMA mode 1 enabled */ +# define ADC_CCR_DMA_MODE2 (2 << ADC_CCR_DMA_SHIFT) /* 10: DMA mode 2 enabled */ +# define ADC_CCR_DMA_MODE3 (3 << ADC_CCR_DMA_SHIFT) /* 11: DMA mode 3 enabled */ + +# define ADC_CCR_ADCPRE_SHIFT (16) /* Bits 16-17: ADC prescaler */ +# define ADC_CCR_ADCPRE_MASK (3 << ADC_CCR_ADCPRE_SHIFT) +# define ADC_CCR_ADCPRE_DIV2 (0 << ADC_CCR_ADCPRE_SHIFT) /* 00: PCLK2 divided by 2 */ +# define ADC_CCR_ADCPRE_DIV4 (1 << ADC_CCR_ADCPRE_SHIFT) /* 01: PCLK2 divided by 4 */ +# define ADC_CCR_ADCPRE_DIV6 (2 << ADC_CCR_ADCPRE_SHIFT) /* 10: PCLK2 divided by 6 */ +# define ADC_CCR_ADCPRE_DIV8 (3 << ADC_CCR_ADCPRE_SHIFT) /* 11: PCLK2 divided by 8 */ + /* Bits 18-21: Reserved, must be kept at reset value. */ +# define ADC_CCR_VBATE (1 << 22) /* Bit 22: VBAT enable */ +# define ADC_CCR_TSVREFE (1 << 23) /* Bit 23: Temperature sensor and VREFINT enable */ + /* Bits 24-31 Reserved, must be kept at reset value. */ +#endif + +/* Data register for dual and triple modes (32-bit data with no named fields) */ + +/**************************************************************************************************** + * Public Types + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public Data + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public Function Prototypes + ****************************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_ADC_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_bkp.h b/nuttx/arch/arm/src/stm32/chip/stm32_bkp.h new file mode 100644 index 0000000000..1788bdee08 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_bkp.h @@ -0,0 +1,190 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_bkp.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_BKP_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_BKP_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#if defined(CONFIG_STM32_HIGHDENSITY) || defined(CONFIG_STM32_CONNECTIVITYLINE) +# define CONFIG_STM32_NBKP_BYTES 84 +# define CONFIG_STM32_NBKP_REGS 42 +#else +# define CONFIG_STM32_NBKP_BYTES 20 +# define CONFIG_STM32_NBKP_REGS 10 +#endif + +/* Register Offsets *****************************************************************/ + +#if defined(CONFIG_STM32_HIGHDENSITY) || defined(CONFIG_STM32_CONNECTIVITYLINE) +# define STM32_BKP_DR_OFFSET(n) ((n) > 10 ? 0x0040+4*((n)-10) : 0x0004+4*(n)) +#else +# define STM32_BKP_DR_OFFSET(n) (0x0004+4*(n)) +#endif + +#define STM32_BKP_DR1_OFFSET 0x0004 /* Backup data register 1 */ +#define STM32_BKP_DR2_OFFSET 0x0008 /* Backup data register 2 */ +#define STM32_BKP_DR3_OFFSET 0x000c /* Backup data register 3 */ +#define STM32_BKP_DR4_OFFSET 0x0010 /* Backup data register 4 */ +#define STM32_BKP_DR5_OFFSET 0x0014 /* Backup data register 5 */ +#define STM32_BKP_DR6_OFFSET 0x0018 /* Backup data register 6 */ +#define STM32_BKP_DR7_OFFSET 0x001c /* Backup data register 7 */ +#define STM32_BKP_DR8_OFFSET 0x0020 /* Backup data register 8 */ +#define STM32_BKP_DR9_OFFSET 0x0024 /* Backup data register 9 */ +#define STM32_BKP_DR10_OFFSET 0x0028 /* Backup data register 10 */ + +#define STM32_BKP_RTCCR_OFFSET 0x002c /* RTC clock calibration register */ +#define STM32_BKP_CR_OFFSET 0x0030 /* Backup control register */ +#define STM32_BKP_CSR_OFFSET 0x0034 /* Backup control/status register */ + +#if defined(CONFIG_STM32_HIGHDENSITY) || defined(CONFIG_STM32_CONNECTIVITYLINE) +# define STM32_BKP_DR11_OFFSET 0x0040 /* Backup data register 11 */ +# define STM32_BKP_DR12_OFFSET 0x0044 /* Backup data register 12 */ +# define STM32_BKP_DR13_OFFSET 0x0048 /* Backup data register 13 */ +# define STM32_BKP_DR14_OFFSET 0x004c /* Backup data register 14 */ +# define STM32_BKP_DR15_OFFSET 0x0050 /* Backup data register 15 */ +# define STM32_BKP_DR16_OFFSET 0x0054 /* Backup data register 16 */ +# define STM32_BKP_DR17_OFFSET 0x0058 /* Backup data register 17 */ +# define STM32_BKP_DR18_OFFSET 0x005c /* Backup data register 18 */ +# define STM32_BKP_DR19_OFFSET 0x0060 /* Backup data register 19 */ +# define STM32_BKP_DR20_OFFSET 0x0064 /* Backup data register 20 */ +# define STM32_BKP_DR21_OFFSET 0x0068 /* Backup data register 21 */ +# define STM32_BKP_DR22_OFFSET 0x006c /* Backup data register 22 */ +# define STM32_BKP_DR23_OFFSET 0x0070 /* Backup data register 23 */ +# define STM32_BKP_DR24_OFFSET 0x0074 /* Backup data register 24 */ +# define STM32_BKP_DR25_OFFSET 0x0078 /* Backup data register 25 */ +# define STM32_BKP_DR26_OFFSET 0x007c /* Backup data register 26 */ +# define STM32_BKP_DR27_OFFSET 0x0080 /* Backup data register 27 */ +# define STM32_BKP_DR28_OFFSET 0x0084 /* Backup data register 28 */ +# define STM32_BKP_DR29_OFFSET 0x0088 /* Backup data register 29 */ +# define STM32_BKP_DR30_OFFSET 0x008c /* Backup data register 30 */ +# define STM32_BKP_DR31_OFFSET 0x0090 /* Backup data register 31 */ +# define STM32_BKP_DR32_OFFSET 0x0094 /* Backup data register 32 */ +# define STM32_BKP_DR33_OFFSET 0x0098 /* Backup data register 33 */ +# define STM32_BKP_DR34_OFFSET 0x009c /* Backup data register 34 */ +# define STM32_BKP_DR35_OFFSET 0x00a0 /* Backup data register 35 */ +# define STM32_BKP_DR36_OFFSET 0x00a4 /* Backup data register 36 */ +# define STM32_BKP_DR37_OFFSET 0x00a8 /* Backup data register 37 */ +# define STM32_BKP_DR38_OFFSET 0x00ac /* Backup data register 38 */ +# define STM32_BKP_DR39_OFFSET 0x00b0 /* Backup data register 39 */ +# define STM32_BKP_DR40_OFFSET 0x00b4 /* Backup data register 40 */ +# define STM32_BKP_DR41_OFFSET 0x00b8 /* Backup data register 41 */ +# define STM32_BKP_DR42_OFFSET 0x00bc /* Backup data register 42 */ +#endif + +/* Register Addresses ***************************************************************/ + +#define STM32_BKP_RTCCR (STM32_BKP_BASE+STM32_BKP_RTCCR_OFFSET) +#define STM32_BKP_CR (STM32_BKP_BASE+STM32_BKP_CR_OFFSET) +#define STM32_BKP_CSR (STM32_BKP_BASE+STM32_BKP_CSR_OFFSET) + +#define STM32_BKP_DR(n) (STM32_BKP_BASE+STM32_BKP_DR_OFFSET(n)) +#define STM32_BKP_DR1 (STM32_BKP_BASE+STM32_BKP_DR1_OFFSET) +#define STM32_BKP_DR2 (STM32_BKP_BASE+STM32_BKP_DR2_OFFSET) +#define STM32_BKP_DR3 (STM32_BKP_BASE+STM32_BKP_DR3_OFFSET) +#define STM32_BKP_DR4 (STM32_BKP_BASE+STM32_BKP_DR4_OFFSET) +#define STM32_BKP_DR5 (STM32_BKP_BASE+STM32_BKP_DR5_OFFSET) +#define STM32_BKP_DR6 (STM32_BKP_BASE+STM32_BKP_DR6_OFFSET) +#define STM32_BKP_DR7 (STM32_BKP_BASE+STM32_BKP_DR7_OFFSET) +#define STM32_BKP_DR8 (STM32_BKP_BASE+STM32_BKP_DR8_OFFSET) +#define STM32_BKP_DR9 (STM32_BKP_BASE+STM32_BKP_DR9_OFFSET) +#define STM32_BKP_DR10 (STM32_BKP_BASE+STM32_BKP_DR10_OFFSET) + +#if defined(CONFIG_STM32_HIGHDENSITY) || defined(CONFIG_STM32_CONNECTIVITYLINE) +# define STM32_BKP_DR11 (STM32_BKP_BASE+STM32_BKP_DR11_OFFSET) +# define STM32_BKP_DR12 (STM32_BKP_BASE+STM32_BKP_DR12_OFFSET) +# define STM32_BKP_DR13 (STM32_BKP_BASE+STM32_BKP_DR13_OFFSET) +# define STM32_BKP_DR14 (STM32_BKP_BASE+STM32_BKP_DR14_OFFSET) +# define STM32_BKP_DR15 (STM32_BKP_BASE+STM32_BKP_DR15_OFFSET) +# define STM32_BKP_DR16 (STM32_BKP_BASE+STM32_BKP_DR16_OFFSET) +# define STM32_BKP_DR17 (STM32_BKP_BASE+STM32_BKP_DR17_OFFSET) +# define STM32_BKP_DR18 (STM32_BKP_BASE+STM32_BKP_DR18_OFFSET) +# define STM32_BKP_DR19 (STM32_BKP_BASE+STM32_BKP_DR19_OFFSET) +# define STM32_BKP_DR20 (STM32_BKP_BASE+STM32_BKP_DR20_OFFSET) +# define STM32_BKP_DR21 (STM32_BKP_BASE+STM32_BKP_DR21_OFFSET) +# define STM32_BKP_DR22 (STM32_BKP_BASE+STM32_BKP_DR22_OFFSET) +# define STM32_BKP_DR23 (STM32_BKP_BASE+STM32_BKP_DR23_OFFSET) +# define STM32_BKP_DR24 (STM32_BKP_BASE+STM32_BKP_DR24_OFFSET) +# define STM32_BKP_DR25 (STM32_BKP_BASE+STM32_BKP_DR25_OFFSET) +# define STM32_BKP_DR26 (STM32_BKP_BASE+STM32_BKP_DR26_OFFSET) +# define STM32_BKP_DR27 (STM32_BKP_BASE+STM32_BKP_DR27_OFFSET) +# define STM32_BKP_DR28 (STM32_BKP_BASE+STM32_BKP_DR28_OFFSET) +# define STM32_BKP_DR29 (STM32_BKP_BASE+STM32_BKP_DR29_OFFSET) +# define STM32_BKP_DR30 (STM32_BKP_BASE+STM32_BKP_DR30_OFFSET) +# define STM32_BKP_DR31 (STM32_BKP_BASE+STM32_BKP_DR31_OFFSET) +# define STM32_BKP_DR32 (STM32_BKP_BASE+STM32_BKP_DR32_OFFSET) +# define STM32_BKP_DR33 (STM32_BKP_BASE+STM32_BKP_DR33_OFFSET) +# define STM32_BKP_DR34 (STM32_BKP_BASE+STM32_BKP_DR34_OFFSET) +# define STM32_BKP_DR35 (STM32_BKP_BASE+STM32_BKP_DR35_OFFSET) +# define STM32_BKP_DR36 (STM32_BKP_BASE+STM32_BKP_DR36_OFFSET) +# define STM32_BKP_DR37 (STM32_BKP_BASE+STM32_BKP_DR37_OFFSET) +# define STM32_BKP_DR38 (STM32_BKP_BASE+STM32_BKP_DR38_OFFSET) +# define STM32_BKP_DR39 (STM32_BKP_BASE+STM32_BKP_DR39_OFFSET) +# define STM32_BKP_DR40 (STM32_BKP_BASE+STM32_BKP_DR40_OFFSET) +# define STM32_BKP_DR41 (STM32_BKP_BASE+STM32_BKP_DR41_OFFSET) +# define STM32_BKP_DR42 (STM32_BKP_BASE+STM32_BKP_DR42_OFFSET) +#endif + +/* Register Bitfield Definitions ****************************************************/ + +/* RTC clock calibration register */ + +#define BKP_RTCCR_CAL_SHIFT (0) /* Bits 6-0: Calibration value */ +#define BKP_RTCCR_CAL_MASK (0x7f << BKP_RTCCR_CAL_SHIFT) +#define BKP_RTCCR_CCO (1 << 7) /* Bit 7: Calibration Clock Output */ +#define BKP_RTCCR_ASOE (1 << 8) /* Bit 8: Alarm or Second Output Enable */ +#define BKP_RTCCR_ASOS (1 << 9) /* Bit 9: Alarm or Second Output Selection */ + +/* Backup control register */ + +#define BKP_CR_TPE (1 << 0) /* Bit 0: TAMPER pin enable */ +#define BKP_CR_TPAL (1 << 1) /* Bit 1: TAMPER pin active level */ + +/* Backup control/status register */ + +#define BKP_CSR_CTE (1 << 0) /* Bit 0: Clear Tamper event */ +#define BKP_CSR_CTI (1 << 1) /* Bit 1: Clear Tamper Interrupt */ +#define BKP_CSR_TPIE (1 << 2) /* Bit 2: TAMPER Pin interrupt enable */ +#define BKP_CSR_TEF (1 << 8) /* Bit 8: Tamper Event Flag */ +#define BKP_CSR_TIF (1 << 9) /* Bit 9: Tamper Interrupt Flag */ + +/* Backup data register */ + +#define BKP_DR_SHIFT (0) /* Bits 1510: Backup data */ +#define BKP_DR_MASK (0xffff << BKP_DR_SHIFT) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_BKP_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_can.h b/nuttx/arch/arm/src/stm32/chip/stm32_can.h new file mode 100644 index 0000000000..253bf68fc6 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_can.h @@ -0,0 +1,505 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_can.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_CAN_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_CAN_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* 3 TX mailboxes */ + +#define CAN_TXMBOX1 0 +#define CAN_TXMBOX2 1 +#define CAN_TXMBOX3 2 + +/* 2 RX mailboxes */ + +#define CAN_RXMBOX1 0 +#define CAN_RXMBOX2 1 + +/* Number of filters depends on silicon */ + +#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define CAN_NFILTERS 28 +#else +# define CAN_NFILTERS 14 +#endif + +/* Register Offsets *****************************************************************/ + +/* CAN control and status registers */ + +#define STM32_CAN_MCR_OFFSET 0x0000 /* CAN master control register */ +#define STM32_CAN_MSR_OFFSET 0x0004 /* CAN master status register */ +#define STM32_CAN_TSR_OFFSET 0x0008 /* CAN transmit status register */ +#define STM32_CAN_RF0R_OFFSET 0x000c /* CAN receive FIFO 0 register */ +#define STM32_CAN_RF1R_OFFSET 0x0010 /* CAN receive FIFO 1 register */ +#define STM32_CAN_IER_OFFSET 0x0014 /* CAN interrupt enable register */ +#define STM32_CAN_ESR_OFFSET 0x0018 /* CAN error status register */ +#define STM32_CAN_BTR_OFFSET 0x001c /* CAN bit timing register */ + +/* CAN mailbox registers (3 TX and 2 RX) */ + +#define STM32_CAN_TIR_OFFSET(m) (0x0180+((m)<<4)) +#define STM32_CAN_TI0R_OFFSET 0x0180 /* TX mailbox identifier register 0 */ +#define STM32_CAN_TI1R_OFFSET 0x0190 /* TX mailbox identifier register 1 */ +#define STM32_CAN_TI2R_OFFSET 0x01a0 /* TX mailbox identifier register 2 */ + +#define STM32_CAN_TDTR_OFFSET(m) (0x0184+((m)<<4)) +#define STM32_CAN_TDT0R_OFFSET 0x0184 /* Mailbox data length control and time stamp register 0 */ +#define STM32_CAN_TDT1R_OFFSET 0x0194 /* Mailbox data length control and time stamp register 1 */ +#define STM32_CAN_TDT2R_OFFSET 0x01a4 /* Mailbox data length control and time stamp register 2 */ + +#define STM32_CAN_TDLR_OFFSET(m) (0x0188+((m)<<4)) +#define STM32_CAN_TDL0R_OFFSET 0x0188 /* Mailbox data low register 0 */ +#define STM32_CAN_TDL1R_OFFSET 0x0198 /* Mailbox data low register 1 */ +#define STM32_CAN_TDL2R_OFFSET 0x01a8 /* Mailbox data low register 2 */ + +#define STM32_CAN_TDHR_OFFSET(m) (0x018c+((m)<<4)) +#define STM32_CAN_TDH0R_OFFSET 0x018c /* Mailbox data high register 0 */ +#define STM32_CAN_TDH1R_OFFSET 0x019c /* Mailbox data high register 1 */ +#define STM32_CAN_TDH2R_OFFSET 0x01ac /* Mailbox data high register 2 */ + +#define STM32_CAN_RIR_OFFSET(m) (0x01b0+((m)<<4)) +#define STM32_CAN_RI0R_OFFSET 0x01b0 /* Rx FIFO mailbox identifier register 0 */ +#define STM32_CAN_RI1R_OFFSET 0x01c0 /* Rx FIFO mailbox identifier register 1 */ + +#define STM32_CAN_RDTR_OFFSET(m) (0x01b4+((m)<<4)) +#define STM32_CAN_RDT0R_OFFSET 0x01b4 /* Rx FIFO mailbox data length control and time stamp register 0 */ +#define STM32_CAN_RDT1R_OFFSET 0x01c4 /* Rx FIFO mailbox data length control and time stamp register 1 */ + +#define STM32_CAN_RDLR_OFFSET(m) (0x01b8+((m)<<4)) +#define STM32_CAN_RDL0R_OFFSET 0x01b8 /* Receive FIFO mailbox data low register 0 */ +#define STM32_CAN_RDL1R_OFFSET 0x01c8 /* Receive FIFO mailbox data low register 1 */ + +#define STM32_CAN_RDHR_OFFSET(m) (0x01bc+((m)<<4)) +#define STM32_CAN_RDH0R_OFFSET 0x01bc /* Receive FIFO mailbox data high register 0 */ +#define STM32_CAN_RDH1R_OFFSET 0x01cc /* Receive FIFO mailbox data high register 1 */ + +/* CAN filter registers */ + +#define STM32_CAN_FMR_OFFSET 0x0200 /* CAN filter master register */ +#define STM32_CAN_FM1R_OFFSET 0x0204 /* CAN filter mode register */ +#define STM32_CAN_FS1R_OFFSET 0x020c /* CAN filter scale register */ +#define STM32_CAN_FFA1R_OFFSET 0x0214 /* CAN filter FIFO assignment register */ +#define STM32_CAN_FA1R_OFFSET 0x021c /* CAN filter activation register */ + +/* There are 14 or 28 filter banks (depending) on the device. Each filter bank is + * composed of two 32-bit registers, CAN_FiR: + * F0R1 Offset 0x240 + * F0R2 Offset 0x244 + * F1R1 Offset 0x248 + * F1R2 Offset 0x24c + * ... + */ + +#define STM32_CAN_FR_OFFSET(f,i) (0x240+((f)<<3)+(((i)-1)<<2)) + +/* Register Addresses ***************************************************************/ + +#if STM32_NCAN > 0 +# define STM32_CAN1_MCR (STM32_CAN1_BASE+STM32_CAN_MCR_OFFSET) +# define STM32_CAN1_MSR (STM32_CAN1_BASE+STM32_CAN_MSR_OFFSET) +# define STM32_CAN1_TSR (STM32_CAN1_BASE+STM32_CAN_TSR_OFFSET) +# define STM32_CAN1_RF0R (STM32_CAN1_BASE+STM32_CAN_RF0R_OFFSET) +# define STM32_CAN1_RF1R (STM32_CAN1_BASE+STM32_CAN_RF1R_OFFSET) +# define STM32_CAN1_IER (STM32_CAN1_BASE+STM32_CAN_IER_OFFSET) +# define STM32_CAN1_ESR (STM32_CAN1_BASE+STM32_CAN_ESR_OFFSET) +# define STM32_CAN1_BTR (STM32_CAN1_BASE+STM32_CAN_BTR_OFFSET) + +# define STM32_CAN1_TIR(m) (STM32_CAN1_BASE+STM32_CAN_TIR_OFFSET(m)) +# define STM32_CAN1_TI0R (STM32_CAN1_BASE+STM32_CAN_TI0R_OFFSET) +# define STM32_CAN1_TI1R (STM32_CAN1_BASE+STM32_CAN_TI1R_OFFSET) +# define STM32_CAN1_TI2R (STM32_CAN1_BASE+STM32_CAN_TI2R_OFFSET) + +# define STM32_CAN1_TDTR(m) (STM32_CAN1_BASE+STM32_CAN_TDTR_OFFSET(m)) +# define STM32_CAN1_TDT0R (STM32_CAN1_BASE+STM32_CAN_TDT0R_OFFSET) +# define STM32_CAN1_TDT1R (STM32_CAN1_BASE+STM32_CAN_TDT1R_OFFSET) +# define STM32_CAN1_TDT2R (STM32_CAN1_BASE+STM32_CAN_TDT2R_OFFSET) + +# define STM32_CAN1_TDLR(m) (STM32_CAN1_BASE+STM32_CAN_TDLR_OFFSET(m)) +# define STM32_CAN1_TDL0R (STM32_CAN1_BASE+STM32_CAN_TDL0R_OFFSET) +# define STM32_CAN1_TDL1R (STM32_CAN1_BASE+STM32_CAN_TDL1R_OFFSET) +# define STM32_CAN1_TDL2R (STM32_CAN1_BASE+STM32_CAN_TDL2R_OFFSET) + +# define STM32_CAN1_TDHR(m) (STM32_CAN1_BASE+STM32_CAN_TDHR_OFFSET(m)) +# define STM32_CAN1_TDH0R (STM32_CAN1_BASE+STM32_CAN_TDH0R_OFFSET) +# define STM32_CAN1_TDH1R (STM32_CAN1_BASE+STM32_CAN_TDH1R_OFFSET) +# define STM32_CAN1_TDH2R (STM32_CAN1_BASE+STM32_CAN_TDH2R_OFFSET) + +# define STM32_CAN1_RIR(m) (STM32_CAN1_BASE+STM32_CAN_RIR_OFFSET(m)) +# define STM32_CAN1_RI0R (STM32_CAN1_BASE+STM32_CAN_RI0R_OFFSET) +# define STM32_CAN1_RI1R (STM32_CAN1_BASE+STM32_CAN_RI1R_OFFSET) + +# define STM32_CAN1_RDTR(m) (STM32_CAN1_BASE+STM32_CAN_RDTR_OFFSET(m)) +# define STM32_CAN1_RDT0R (STM32_CAN1_BASE+STM32_CAN_RDT0R_OFFSET) +# define STM32_CAN1_RDT1R (STM32_CAN1_BASE+STM32_CAN_RDT1R_OFFSET) + +# define STM32_CAN1_RDLR(m) (STM32_CAN1_BASE+STM32_CAN_RDLR_OFFSET(m)) +# define STM32_CAN1_RDL0R (STM32_CAN1_BASE+STM32_CAN_RDL0R_OFFSET) +# define STM32_CAN1_RDL1R (STM32_CAN1_BASE+STM32_CAN_RDL1R_OFFSET) + +# define STM32_CAN1_RDHR(m) (STM32_CAN1_BASE+STM32_CAN_RDHR_OFFSET(m)) +# define STM32_CAN1_RDH0R (STM32_CAN1_BASE+STM32_CAN_RDH0R_OFFSET) +# define STM32_CAN1_RDH1R (STM32_CAN1_BASE+STM32_CAN_RDH1R_OFFSET) + +# define STM32_CAN1_FMR (STM32_CAN1_BASE+STM32_CAN_FMR_OFFSET) +# define STM32_CAN1_FM1R (STM32_CAN1_BASE+STM32_CAN_FM1R_OFFSET) +# define STM32_CAN1_FS1R (STM32_CAN1_BASE+STM32_CAN_FS1R_OFFSET) +# define STM32_CAN1_FFA1R (STM32_CAN1_BASE+STM32_CAN_FFA1R_OFFSET) +# define STM32_CAN1_FA1R (STM32_CAN1_BASE+STM32_CAN_FA1R_OFFSET) +# define STM32_CAN1_FIR(b,i) (STM32_CAN1_BASE+STM32_CAN_FIR_OFFSET(b,i)) +#endif + +#if STM32_NCAN > 1 +# define STM32_CAN2_MCR (STM32_CAN2_BASE+STM32_CAN_MCR_OFFSET) +# define STM32_CAN2_MSR (STM32_CAN2_BASE+STM32_CAN_MSR_OFFSET) +# define STM32_CAN2_TSR (STM32_CAN2_BASE+STM32_CAN_TSR_OFFSET) +# define STM32_CAN2_RF0R (STM32_CAN2_BASE+STM32_CAN_RF0R_OFFSET) +# define STM32_CAN2_RF1R (STM32_CAN2_BASE+STM32_CAN_RF1R_OFFSET) +# define STM32_CAN2_IER (STM32_CAN2_BASE+STM32_CAN_IER_OFFSET) +# define STM32_CAN2_ESR (STM32_CAN2_BASE+STM32_CAN_ESR_OFFSET) +# define STM32_CAN2_BTR (STM32_CAN2_BASE+STM32_CAN_BTR_OFFSET) + +# define STM32_CAN2_TIR(m) (STM32_CAN2_BASE+STM32_CAN_TIR_OFFSET(m)) +# define STM32_CAN2_TI0R (STM32_CAN2_BASE+STM32_CAN_TI0R_OFFSET) +# define STM32_CAN2_TI1R (STM32_CAN2_BASE+STM32_CAN_TI1R_OFFSET) +# define STM32_CAN2_TI2R (STM32_CAN2_BASE+STM32_CAN_TI2R_OFFSET) + +# define STM32_CAN2_TDTR(m) (STM32_CAN2_BASE+STM32_CAN_TDTR_OFFSET(m)) +# define STM32_CAN2_TDT0R (STM32_CAN2_BASE+STM32_CAN_TDT0R_OFFSET) +# define STM32_CAN2_TDT1R (STM32_CAN2_BASE+STM32_CAN_TDT1R_OFFSET) +# define STM32_CAN2_TDT2R (STM32_CAN2_BASE+STM32_CAN_TDT2R_OFFSET) + +# define STM32_CAN2_TDLR(m) (STM32_CAN2_BASE+STM32_CAN_TDLR_OFFSET(m)) +# define STM32_CAN2_TDL0R (STM32_CAN2_BASE+STM32_CAN_TDL0R_OFFSET) +# define STM32_CAN2_TDL1R (STM32_CAN2_BASE+STM32_CAN_TDL1R_OFFSET) +# define STM32_CAN2_TDL2R (STM32_CAN2_BASE+STM32_CAN_TDL2R_OFFSET) + +# define STM32_CAN2_TDHR(m) (STM32_CAN2_BASE+STM32_CAN_TDHR_OFFSET(m)) +# define STM32_CAN2_TDH0R (STM32_CAN2_BASE+STM32_CAN_TDH0R_OFFSET) +# define STM32_CAN2_TDH1R (STM32_CAN2_BASE+STM32_CAN_TDH1R_OFFSET) +# define STM32_CAN2_TDH2R (STM32_CAN2_BASE+STM32_CAN_TDH2R_OFFSET) + +# define STM32_CAN2_RIR(m) (STM32_CAN2_BASE+STM32_CAN_RIR_OFFSET(m)) +# define STM32_CAN2_RI0R (STM32_CAN2_BASE+STM32_CAN_RI0R_OFFSET) +# define STM32_CAN2_RI1R (STM32_CAN2_BASE+STM32_CAN_RI1R_OFFSET) + +# define STM32_CAN2_RDTR(m) (STM32_CAN2_BASE+STM32_CAN_RDTR_OFFSET(m)) +# define STM32_CAN2_RDT0R (STM32_CAN2_BASE+STM32_CAN_RDT0R_OFFSET) +# define STM32_CAN2_RDT1R (STM32_CAN2_BASE+STM32_CAN_RDT1R_OFFSET) + +# define STM32_CAN2_RDLR(m) (STM32_CAN2_BASE+STM32_CAN_RDLR_OFFSET(m)) +# define STM32_CAN2_RDL0R (STM32_CAN2_BASE+STM32_CAN_RDL0R_OFFSET) +# define STM32_CAN2_RDL1R (STM32_CAN2_BASE+STM32_CAN_RDL1R_OFFSET) + +# define STM32_CAN2_RDHR(m) (STM32_CAN2_BASE+STM32_CAN_RDHR_OFFSET(m)) +# define STM32_CAN2_RDH0R (STM32_CAN2_BASE+STM32_CAN_RDH0R_OFFSET) +# define STM32_CAN2_RDH1R (STM32_CAN2_BASE+STM32_CAN_RDH1R_OFFSET) + +# define STM32_CAN2_FMR (STM32_CAN2_BASE+STM32_CAN_FMR_OFFSET) +# define STM32_CAN2_FM1R (STM32_CAN2_BASE+STM32_CAN_FM1R_OFFSET) +# define STM32_CAN2_FS1R (STM32_CAN2_BASE+STM32_CAN_FS1R_OFFSET) +# define STM32_CAN2_FFA1R (STM32_CAN2_BASE+STM32_CAN_FFA1R_OFFSET) +# define STM32_CAN2_FA1R (STM32_CAN2_BASE+STM32_CAN_FA1R_OFFSET) +# define STM32_CAN2_FIR(b,i) (STM32_CAN2_BASE+STM32_CAN_FIR_OFFSET(b,i)) +#endif + +/* Register Bitfield Definitions ****************************************************/ + +/* CAN master control register */ + +#define CAN_MCR_INRQ (1 << 0) /* Bit 0: Initialization Request */ +#define CAN_MCR_SLEEP (1 << 1) /* Bit 1: Sleep Mode Request */ +#define CAN_MCR_TXFP (1 << 2) /* Bit 2: Transmit FIFO Priority */ +#define CAN_MCR_RFLM (1 << 3) /* Bit 3: Receive FIFO Locked Mode */ +#define CAN_MCR_NART (1 << 4) /* Bit 4: No Automatic Retransmission */ +#define CAN_MCR_AWUM (1 << 5) /* Bit 5: Automatic Wakeup Mode */ +#define CAN_MCR_ABOM (1 << 6) /* Bit 6: Automatic Bus-Off Management */ +#define CAN_MCR_TTCM (1 << 7) /* Bit 7: Time Triggered Communication Mode Enable */ +#define CAN_MCR_RESET (1 << 15) /* Bit 15: bxCAN software master reset */ +#define CAN_MCR_DBF (1 << 16) /* Bit 16: Debug freeze */ + +/* CAN master status register */ + +#define CAN_MSR_INAK (1 << 0) /* Bit 0: Initialization Acknowledge */ +#define CAN_MSR_SLAK (1 << 1) /* Bit 1: Sleep Acknowledge */ +#define CAN_MSR_ERRI (1 << 2) /* Bit 2: Error Interrupt */ +#define CAN_MSR_WKUI (1 << 3) /* Bit 3: Wakeup Interrupt */ +#define CAN_MSR_SLAKI (1 << 4) /* Bit 4: Sleep acknowledge interrupt */ +#define CAN_MSR_TXM (1 << 8) /* Bit 8: Transmit Mode */ +#define CAN_MSR_RXM (1 << 9) /* Bit 9: Receive Mode */ +#define CAN_MSR_SAMP (1 << 20) /* Bit 10: Last Sample Point */ +#define CAN_MSR_RX (1 << 11) /* Bit 11: CAN Rx Signal */ + +/* CAN transmit status register */ + +#define CAN_TSR_RQCP0 (1 << 0) /* Bit 0: Request Completed Mailbox 0 */ +#define CAN_TSR_TXOK0 (1 << 1) /* Bit 1 : Transmission OK of Mailbox 0 */ +#define CAN_TSR_ALST0 (1 << 2) /* Bit 2 : Arbitration Lost for Mailbox 0 */ +#define CAN_TSR_TERR0 (1 << 3) /* Bit 3 : Transmission Error of Mailbox 0 */ +#define CAN_TSR_ABRQ0 (1 << 7) /* Bit 7 : Abort Request for Mailbox 0 */ +#define CAN_TSR_RQCP1 (1 << 8) /* Bit 8 : Request Completed Mailbox 1 */ +#define CAN_TSR_TXOK1 (1 << 9) /* Bit 9 : Transmission OK of Mailbox 1 */ +#define CAN_TSR_ALST1 (1 << 10) /* Bit 10 : Arbitration Lost for Mailbox 1 */ +#define CAN_TSR_TERR1 (1 << 11) /* Bit 11 : Transmission Error of Mailbox 1 */ +#define CAN_TSR_ABRQ1 (1 << 15) /* Bit 15 : Abort Request for Mailbox 1 */ +#define CAN_TSR_RQCP2 (1 << 16) /* Bit 16 : Request Completed Mailbox 2 */ +#define CAN_TSR_TXOK2 (1 << 17) /* Bit 17 : Transmission OK of Mailbox 2 */ +#define CAN_TSR_ALST2 (1 << 18) /* Bit 18: Arbitration Lost for Mailbox 2 */ +#define CAN_TSR_TERR2 (1 << 19) /* Bit 19: Transmission Error of Mailbox 2 */ +#define CAN_TSR_ABRQ2 (1 << 23) /* Bit 23: Abort Request for Mailbox 2 */ +#define CAN_TSR_CODE_SHIFT (24) /* Bits 25-24: Mailbox Code */ +#define CAN_TSR_CODE_MASK (3 << CAN_TSR_CODE_SHIFT) +#define CAN_TSR_TME0 (1 << 26) /* Bit 26: Transmit Mailbox 0 Empty */ +#define CAN_TSR_TME1 (1 << 27) /* Bit 27: Transmit Mailbox 1 Empty */ +#define CAN_TSR_TME2 (1 << 28) /* Bit 28: Transmit Mailbox 2 Empty */ +#define CAN_TSR_LOW0 (1 << 29) /* Bit 29: Lowest Priority Flag for Mailbox 0 */ +#define CAN_TSR_LOW1 (1 << 30) /* Bit 30: Lowest Priority Flag for Mailbox 1 */ +#define CAN_TSR_LOW2 (1 << 31) /* Bit 31: Lowest Priority Flag for Mailbox 2 */ + +/* CAN receive FIFO 0/1 registers */ + +#define CAN_RFR_FMP_SHIFT (0) /* Bits 1-0: FIFO Message Pending */ +#define CAN_RFR_FMP_MASK (3 << CAN_RFR_FMP_SHIFT) +#define CAN_RFR_FULL (1 << 3) /* Bit 3: FIFO 0 Full */ +#define CAN_RFR_FOVR (1 << 4) /* Bit 4: FIFO 0 Overrun */ +#define CAN_RFR_RFOM (1 << 5) /* Bit 5: Release FIFO 0 Output Mailbox */ + +/* CAN interrupt enable register */ + +#define CAN_IER_TMEIE (1 << 0) /* Bit 0: Transmit Mailbox Empty Interrupt Enable */ +#define CAN_IER_FMPIE0 (1 << 1) /* Bit 1: FIFO Message Pending Interrupt Enable */ +#define CAN_IER_FFIE0 (1 << 2) /* Bit 2: FIFO Full Interrupt Enable */ +#define CAN_IER_FOVIE0 (1 << 3) /* Bit 3: FIFO Overrun Interrupt Enable */ +#define CAN_IER_FMPIE1 (1 << 4) /* Bit 4: FIFO Message Pending Interrupt Enable */ +#define CAN_IER_FFIE1 (1 << 5) /* Bit 5: FIFO Full Interrupt Enable */ +#define CAN_IER_FOVIE1 (1 << 6) /* Bit 6: FIFO Overrun Interrupt Enable */ +#define CAN_IER_EWGIE (1 << 8) /* Bit 8: Error Warning Interrupt Enable */ +#define CAN_IER_EPVIE (1 << 9) /* Bit 9: Error Passive Interrupt Enable */ +#define CAN_IER_BOFIE (1 << 10) /* Bit 10: Bus-Off Interrupt Enable */ +#define CAN_IER_LECIE (1 << 11) /* Bit 11: Last Error Code Interrupt Enable */ +#define CAN_IER_ERRIE (1 << 15) /* Bit 15: Error Interrupt Enable */ +#define CAN_IER_WKUIE (1 << 16) /* Bit 16: Wakeup Interrupt Enable */ +#define CAN_IER_SLKIE (1 << 17) /* Bit 17: Sleep Interrupt Enable */ + +/* CAN error status register */ + +#define CAN_ESR_EWGF (1 << 0) /* Bit 0: Error Warning Flag */ +#define CAN_ESR_EPVF (1 << 1) /* Bit 1: Error Passive Flag */ +#define CAN_ESR_BOFF (1 << 2) /* Bit 2: Bus-Off Flag */ +#define CAN_ESR_LEC_SHIFT (4) /* Bits 6-4: Last Error Code */ +#define CAN_ESR_LEC_MASK (7 << CAN_ESR_LEC_SHIFT) +# define CAN_ESR_NOERROR (0 << CAN_ESR_LEC_SHIFT) /* 000: No Error */ +# define CAN_ESR_STUFFERROR (1 << CAN_ESR_LEC_SHIFT) /* 001: Stuff Error */ +# define CAN_ESR_FORMERROR (2 << CAN_ESR_LEC_SHIFT) /* 010: Form Error */ +# define CAN_ESR_ACKERROR (3 << CAN_ESR_LEC_SHIFT) /* 011: Acknowledgment Error */ +# define CAN_ESR_BRECERROR (4 << CAN_ESR_LEC_SHIFT) /* 100: Bit recessive Error */ +# define CAN_ESR_BDOMERROR (5 << CAN_ESR_LEC_SHIFT) /* 101: Bit dominant Error */ +# define CAN_ESR_CRCERRPR (6 << CAN_ESR_LEC_SHIFT) /* 110: CRC Error */ +# define CAN_ESR_SWERROR (7 << CAN_ESR_LEC_SHIFT) /* 111: Set by software */ +#define CAN_ESR_TEC_SHIFT (16) /* Bits 23-16: LS byte of the 9-bit Transmit Error Counter */ +#define CAN_ESR_TEC_MASK (0xff << CAN_ESR_TEC_SHIF) +#define CAN_ESR_REC_SHIFT (24) /* Bits 31-24: Receive Error Counter */ +#define CAN_ESR_REC_MASK (0xff << CAN_ESR_REC_SHIFT) + +/* CAN bit timing register */ + +#define CAN_BTR_BRP_SHIFT (0) /* Bits 9-0: Baud Rate Prescaler */ +#define CAN_BTR_BRP_MASK (0x03ff << CAN_BTR_BRP_SHIFT) +#define CAN_BTR_TS1_SHIFT (16) /* Bits 19-16: Time Segment 1 */ +#define CAN_BTR_TS1_MASK (0x0f << CAN_BTR_TS1_SHIFT) +#define CAN_BTR_TS2_SHIFT (20) /* Bits 22-20: Time Segment 2 */ +#define CAN_BTR_TS2_MASK (7 << CAN_BTR_TS2_SHIFT) +#define CAN_BTR_SJW_SHIFT (24) /* Bits 25-24: Resynchronization Jump Width */ +#define CAN_BTR_SJW_MASK (3 << CAN_BTR_SJW_SHIFT) +#define CAN_BTR_LBKM (1 << 30) /* Bit 30: Loop Back Mode (Debug) */ +#define CAN_BTR_SILM (1 << 31) /* Bit 31: Silent Mode (Debug) */ + +#define CAN_BTR_BRP_MAX (1024) /* Maximum BTR value (without decrement) */ +#define CAN_BTR_TSEG1_MAX (16) /* Maximum TSEG1 value (without decrement) */ +#define CAN_BTR_TSEG2_MAX (8) /* Maximum TSEG2 value (without decrement) */ + +/* TX mailbox identifier register */ + +#define CAN_TIR_TXRQ (1 << 0) /* Bit 0: Transmit Mailbox Request */ +#define CAN_TIR_RTR (1 << 1) /* Bit 1: Remote Transmission Request */ +#define CAN_TIR_IDE (1 << 2) /* Bit 2: Identifier Extension */ +#define CAN_TIR_EXID_SHIFT (3) /* Bit 3-31: Extended Identifier */ +#define CAN_TIR_EXID_MASK (0x1fffffff << CAN_TIR_EXID_SHIFT) +#define CAN_TIR_STID_SHIFT (21) /* Bits 21-31: Standard Identifier */ +#define CAN_TIR_STID_MASK (0x07ff << CAN_TIR_STID_SHIFT) + +/* Mailbox data length control and time stamp register */ + +#define CAN_TDTR_DLC_SHIFT (0) /* Bits 3:0: Data Length Code */ +#define CAN_TDTR_DLC_MASK (0x0f << CAN_TDTR_DLC_SHIFT) +#define CAN_TDTR_TGT (1 << 8) /* Bit 8: Transmit Global Time */ +#define CAN_TDTR_TIME_SHIFT (16) /* Bits 31:16: Message Time Stamp */ +#define CAN_TDTR_TIME_MASK (0xffff << CAN_TDTR_TIME_SHIFT) + +/* Mailbox data low register */ + +#define CAN_TDLR_DATA0_SHIFT (0) /* Bits 7-0: Data Byte 0 */ +#define CAN_TDLR_DATA0_MASK (0xff << CAN_TDLR_DATA0_SHIFT) +#define CAN_TDLR_DATA1_SHIFT (8) /* Bits 15-8: Data Byte 1 */ +#define CAN_TDLR_DATA1_MASK (0xff << CAN_TDLR_DATA1_SHIFT) +#define CAN_TDLR_DATA2_SHIFT (16) /* Bits 23-16: Data Byte 2 */ +#define CAN_TDLR_DATA2_MASK (0xff << CAN_TDLR_DATA2_SHIFT) +#define CAN_TDLR_DATA3_SHIFT (24) /* Bits 31-24: Data Byte 3 */ +#define CAN_TDLR_DATA3_MASK (0xff << CAN_TDLR_DATA3_SHIFT) + +/* Mailbox data high register */ + +#define CAN_TDHR_DATA4_SHIFT (0) /* Bits 7-0: Data Byte 4 */ +#define CAN_TDHR_DATA4_MASK (0xff << CAN_TDHR_DATA4_SHIFT) +#define CAN_TDHR_DATA5_SHIFT (8) /* Bits 15-8: Data Byte 5 */ +#define CAN_TDHR_DATA5_MASK (0xff << CAN_TDHR_DATA5_SHIFT) +#define CAN_TDHR_DATA6_SHIFT (16) /* Bits 23-16: Data Byte 6 */ +#define CAN_TDHR_DATA6_MASK (0xff << CAN_TDHR_DATA6_SHIFT) +#define CAN_TDHR_DATA7_SHIFT (24) /* Bits 31-24: Data Byte 7 */ +#define CAN_TDHR_DATA7_MASK (0xff << CAN_TDHR_DATA7_SHIFT) + +/* Rx FIFO mailbox identifier register */ + +#define CAN_RIR_RTR (1 << 1) /* Bit 1: Remote Transmission Request */ +#define CAN_RIR_IDE (1 << 2) /* Bit 2: Identifier Extension */ +#define CAN_RIR_EXID_SHIFT (3) /* Bit 3-31: Extended Identifier */ +#define CAN_RIR_EXID_MASK (0x1fffffff << CAN_RIR_EXID_SHIFT) +#define CAN_RIR_STID_SHIFT (21) /* Bits 21-31: Standard Identifier */ +#define CAN_RIR_STID_MASK (0x07ff << CAN_RIR_STID_SHIFT) + +/* Receive FIFO mailbox data length control and time stamp register */ + +#define CAN_RDTR_DLC_SHIFT (0) /* Bits 3:0: Data Length Code */ +#define CAN_RDTR_DLC_MASK (0x0f << CAN_RDTR_DLC_SHIFT) +#define CAN_RDTR_FM_SHIFT (8) /* Bits 15-8: Filter Match Index */ +#define CAN_RDTR_FM_MASK (0xff << CAN_RDTR_FM_SHIFT) +#define CAN_RDTR_TIME_SHIFT (16) /* Bits 31:16: Message Time Stamp */ +#define CAN_RDTR_TIME_MASK (0xffff << CAN_RDTR_TIME_SHIFT) + +/* Receive FIFO mailbox data low register */ + +#define CAN_RDLR_DATA0_SHIFT (0) /* Bits 7-0: Data Byte 0 */ +#define CAN_RDLR_DATA0_MASK (0xff << CAN_RDLR_DATA0_SHIFT) +#define CAN_RDLR_DATA1_SHIFT (8) /* Bits 15-8: Data Byte 1 */ +#define CAN_RDLR_DATA1_MASK (0xff << CAN_RDLR_DATA1_SHIFT) +#define CAN_RDLR_DATA2_SHIFT (16) /* Bits 23-16: Data Byte 2 */ +#define CAN_RDLR_DATA2_MASK (0xff << CAN_RDLR_DATA2_SHIFT) +#define CAN_RDLR_DATA3_SHIFT (24) /* Bits 31-24: Data Byte 3 */ +#define CAN_RDLR_DATA3_MASK (0xff << CAN_RDLR_DATA3_SHIFT) + +/* Receive FIFO mailbox data high register */ + +#define CAN_RDHR_DATA4_SHIFT (0) /* Bits 7-0: Data Byte 4 */ +#define CAN_RDHR_DATA4_MASK (0xff << CAN_RDHR_DATA4_SHIFT) +#define CAN_RDHR_DATA5_SHIFT (8) /* Bits 15-8: Data Byte 5 */ +#define CAN_RDHR_DATA5_MASK (0xff << CAN_RDHR_DATA5_SHIFT) +#define CAN_RDHR_DATA6_SHIFT (16) /* Bits 23-16: Data Byte 6 */ +#define CAN_RDHR_DATA6_MASK (0xff << CAN_RDHR_DATA6_SHIFT) +#define CAN_RDHR_DATA7_SHIFT (24) /* Bits 31-24: Data Byte 7 */ +#define CAN_RDHR_DATA7_MASK (0xff << CAN_RDHR_DATA7_SHIFT) + +/* CAN filter master register */ + +#define CAN_FMR_FINIT (1 << 0) /* Bit 0: Filter Init Mode */ +#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define CAN_FMR_CAN2SB_SHIFT (8) /* Bits 13-8: CAN2 start bank */ +# define CAN_FMR_CAN2SB_MASK (0x3f << CAN_FMR_CAN2SB_SHIFT) +#endif + +/* CAN filter mode register */ + +#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define CAN_FM1R_FBM_SHIFT (0) /* Bits 13:0: Filter Mode */ +# define CAN_FM1R_FBM_MASK (0x3fff << CAN_FM1R_FBM_SHIFT) +#else +# define CAN_FM1R_FBM_SHIFT (0) /* Bits 27:0: Filter Mode */ +# define CAN_FM1R_FBM_MASK (0x0fffffff << CAN_FM1R_FBM_SHIFT) +#endif + +/* CAN filter scale register */ + +#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define CAN_FS1R_FSC_SHIFT (0) /* Bits 13:0: Filter Scale Configuration */ +# define CAN_FS1R_FSC_MASK (0x3fff << CAN_FS1R_FSC_SHIFT) +#else +# define CAN_FS1R_FSC_SHIFT (0) /* Bits 27:0: Filter Scale Configuration */ +# define CAN_FS1R_FSC_MASK (0x0fffffff << CAN_FS1R_FSC_SHIFT) +#endif + +/* CAN filter FIFO assignment register */ + +#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define CAN_FFA1R_FFA_SHIFT (0) /* Bits 13:0: Filter FIFO Assignment */ +# define CAN_FFA1R_FFA_MASK (0x3fff << CAN_FFA1R_FFA_SHIFT) +#else +# define CAN_FFA1R_FFA_SHIFT (0) /* Bits 27:0: Filter FIFO Assignment */ +# define CAN_FFA1R_FFA_MASK (0x0fffffff << CAN_FFA1R_FFA_SHIFT) +#endif + +/* CAN filter activation register */ + +#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define CAN_FA1R_FACT_SHIFT (0) /* Bits 13:0: Filter Active */ +# define CAN_FA1R_FACT_MASK (0x3fff << CAN_FA1R_FACT_SHIFT) +#else +# define CAN_FA1R_FACT_SHIFT (0) /* Bits 27:0: Filter Active */ +# define CAN_FA1R_FACT_MASK (0x0fffffff << CAN_FA1R_FACT_SHIFT) +#endif + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_CAN_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_dac.h b/nuttx/arch/arm/src/stm32/chip/stm32_dac.h new file mode 100644 index 0000000000..1498c8c93c --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_dac.h @@ -0,0 +1,256 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_dac.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_DAC_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_DAC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include "chip.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +#define STM32_DAC_CR_OFFSET 0x0000 /* DAC control register */ +#define STM32_DAC_SWTRIGR_OFFSET 0x0004 /* DAC software trigger register */ +#define STM32_DAC_DHR12R1_OFFSET 0x0008 /* DAC channel1 12-bit right-aligned data holding register */ +#define STM32_DAC_DHR12L1_OFFSET 0x000c /* DAC channel1 12-bit left aligned data holding register */ +#define STM32_DAC_DHR8R1_OFFSET 0x0010 /* DAC channel1 8-bit right aligned data holding register */ +#define STM32_DAC_DHR12R2_OFFSET 0x0014 /* DAC channel2 12-bit right aligned data holding register */ +#define STM32_DAC_DHR12L_OFFSET 0x0018 /* DAC channel2 12-bit left aligned data holding register */ +#define STM32_DAC_DHR8R2_OFFSET 0x001c /* DAC channel2 8-bit right-aligned data holding register */ +#define STM32_DAC_DHR12RD_OFFSET 0x0020 /* Dual DAC 12-bit right-aligned data holding register */ +#define STM32_DAC_DHR12LD_OFFSET 0x0024 /* DUAL DAC 12-bit left aligned data holding register */ +#define STM32_DAC_DHR8RD_OFFSET 0x0028 /* DUAL DAC 8-bit right aligned data holding register */ +#define STM32_DAC_DOR1_OFFSET 0x002c /* DAC channel1 data output register */ +#define STM32_DAC_DOR2_OFFSET 0x0030 /* DAC channel2 data output register */ +#define STM32_DAC_SR_OFFSET 0x0034 /* DAC status register */ + +/* Register Addresses ***************************************************************/ + +#define STM32_DAC_CR (STM32_DAC_BASE+STM32_DAC_CR_OFFSET) +#define STM32_DAC_SWTRIGR (STM32_DAC_BASE+STM32_DAC_SWTRIGR_OFFSET) +#define STM32_DAC_DHR12R1 (STM32_DAC_BASE+STM32_DAC_DHR12R1_OFFSET) +#define STM32_DAC_DHR12L1 (STM32_DAC_BASE+STM32_DAC_DHR12L1_OFFSET) +#define STM32_DAC_DHR8R1 (STM32_DAC_BASE+STM32_DAC_DHR8R1_OFFSET) +#define STM32_DAC_DHR12R2 (STM32_DAC_BASE+STM32_DAC_DHR12R2_OFFSET) +#define STM32_DAC_DHR12L (STM32_DAC_BASE+STM32_DAC_DHR12L_OFFSET) +#define STM32_DAC_DHR8R2 (STM32_DAC_BASE+STM32_DAC_DHR8R2_OFFSET) +#define STM32_DAC_DHR12RD (STM32_DAC_BASE+STM32_DAC_DHR12RD_OFFSET) +#define STM32_DAC_DHR12LD (STM32_DAC_BASE+STM32_DAC_DHR12LD_OFFSET) +#define STM32_DAC_DHR8RD (STM32_DAC_BASE+STM32_DAC_DHR8RD_OFFSET) +#define STM32_DAC_DOR1 (STM32_DAC_BASE+STM32_DAC_DOR1_OFFSET) +#define STM32_DAC_DOR2 (STM32_DAC_BASE+STM32_DAC_DOR2_OFFSET) +#define STM32_DAC_SR (STM32_DAC_BASE+STM32_DAC_SR_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +/* DAC control register */ +/* These definitions may be used for 16-bit values of either channel */ + +#define DAC_CR_EN (1 << 0) /* Bit 0: DAC channel1 enable */ +#define DAC_CR_BOFF (1 << 1) /* Bit 1: DAC channel1 output buffer disable */ +#define DAC_CR_TSEL_SHIFT (3) /* Bits 3-5: DAC channel1 trigger selection */ +#define DAC_CR_TSEL_MASK (7 << DAC_CR_TSEL_SHIFT) +# define DAC_CR_TSEL_TIM6 (0 << DAC_CR_TSEL_SHIFT) /* Timer 6 TRGO event */ +#ifdef CONFIG_STM32_CONNECTIVITYLINE +# define DAC_CR_TSEL_TIM3 (1 << DAC_CR_TSEL_SHIFT) /* Timer 3 TRGO event */ +#else +# define DAC_CR_TSEL_TIM8 (1 << DAC_CR_TSEL_SHIFT) /* Timer 8 TRGO event */ +#endif +# define DAC_CR_TSEL_TIM7 (2 << DAC_CR_TSEL_SHIFT) /* Timer 7 TRGO event */ +# define DAC_CR_TSEL_TIM5 (3 << DAC_CR_TSEL_SHIFT) /* Timer 5 TRGO event */ +# define DAC_CR_TSEL_TIM2 (4 << DAC_CR_TSEL_SHIFT) /* Timer 2 TRGO event */ +# define DAC_CR_TSEL_TIM4 (5 << DAC_CR_TSEL_SHIFT) /* Timer 4 TRGO event */ +# define DAC_CR_TSEL_EXT9 (6 << DAC_CR_TSEL_SHIFT) /* External line9 */ +# define DAC_CR_TSEL_SW (7 << DAC_CR_TSEL_SHIFT) /* Software trigger */ +#define DAC_CR_WAVE_SHIFT (6) /* Bits 6-7: DAC channel1 noise/triangle wave generation */enable +#define DAC_CR_WAVE_MASK (3 << DAC_CR_WAVE_SHIFT) +# define DAC_CR_WAVE_DISABLED (0 << DAC_CR_WAVE_SHIFT) /* Wave generation disabled */ +# define DAC_CR_WAVE_NOISE (1 << DAC_CR_WAVE_SHIFT) /* Noise wave generation enabled */ +# define DAC_CR_WAVE_TRIANGLE (2 << DAC_CR_WAVE_SHIFT) /* Triangle wave generation enabled */ +#define DAC_CR_MAMP_SHIFT (8) /* Bits 8-11: DAC channel1 mask/amplitude selector */ +#define DAC_CR_MAMP_MASK (15 << DAC_CR_MAMP_SHIFT) +# define DAC_CR_MAMP_AMP1 (0 << DAC_CR_MAMP1_SHIFT) /* Unmask bit0 of LFSR/triangle amplitude=1 */ +# define DAC_CR_MAMP_AMP3 (1 << DAC_CR_MAMP_SHIFT) /* Unmask bits[1:0] of LFSR/triangle amplitude=3 */ +# define DAC_CR_MAMP_AMP7 (2 << DAC_CR_MAMP_SHIFT) /* Unmask bits[2:0] of LFSR/triangle amplitude=7 */ +# define DAC_CR_MAMP_AMP15 (3 << DAC_CR_MAMP_SHIFT) /* Unmask bits[3:0] of LFSR/triangle amplitude=15 */ +# define DAC_CR_MAMP_AMP31 (4 << DAC_CR_MAMP_SHIFT) /* Unmask bits[4:0] of LFSR/triangle amplitude=31 */ +# define DAC_CR_MAMP_AMP63 (5 << DAC_CR_MAMP_SHIFT) /* Unmask bits[5:0] of LFSR/triangle amplitude=63 */ +# define DAC_CR_MAMP_AMP127 (6 << DAC_CR_MAMP_SHIFT) /* Unmask bits[6:0] of LFSR/triangle amplitude=127 */ +# define DAC_CR_MAMP_AMP255 (7 << DAC_CR_MAMP_SHIFT) /* Unmask bits[7:0] of LFSR/triangle amplitude=255 */ +# define DAC_CR_MAMP_AMP511 (8 << DAC_CR_MAMP_SHIFT) /* Unmask bits[8:0] of LFSR/triangle amplitude=511 */ +# define DAC_CR_MAMP_AMP1023 (9 << DAC_CR_MAMP_SHIFT) /* Unmask bits[9:0] of LFSR/triangle amplitude=1023 */ +# define DAC_CR_MAMP_AMP2047 (10 << DAC_CR_MAMP_SHIFT) /* Unmask bits[10:0] of LFSR/triangle amplitude=2047 */ +# define DAC_CR_MAMP_AMP4095 (11 << DAC_CR_MAMP_SHIFT) /* Unmask bits[11:0] of LFSR/triangle amplitude=4095 */ +#define DAC_CR_DMAEN (1 << 12) /* Bit 12: DAC channel1 DMA enable */ +#define DAC_CR_DMAUDRIE (1 << 13) /* Bit 13: DAC channel1 DMA Underrun Interrupt enable */ + +/* These definitions may be used with the full, 32-bit register */ + +#define DAC_CR_EN1 (1 << 0) /* Bit 0: DAC channel1 enable */ +#define DAC_CR_BOFF1 (1 << 1) /* Bit 1: DAC channel1 output buffer disable */ +#define DAC_CR_TSEL1_SHIFT (3) /* Bits 3-5: DAC channel1 trigger selection */ +#define DAC_CR_TSEL1_MASK (7 << DAC_CR_TSEL1_SHIFT) +# define DAC_CR_TSEL1_TIM6 (0 << DAC_CR_TSEL1_SHIFT) /* Timer 6 TRGO event */ +# define DAC_CR_TSEL1_TIM8 (1 << DAC_CR_TSEL1_SHIFT) /* Timer 8 TRGO event */ +# define DAC_CR_TSEL1_TIM7 (2 << DAC_CR_TSEL1_SHIFT) /* Timer 7 TRGO event */ +# define DAC_CR_TSEL1_TIM5 (3 << DAC_CR_TSEL1_SHIFT) /* Timer 5 TRGO event */ +# define DAC_CR_TSEL1_TIM2 (4 << DAC_CR_TSEL1_SHIFT) /* Timer 2 TRGO event */ +# define DAC_CR_TSEL1_TIM4 (5 << DAC_CR_TSEL1_SHIFT) /* Timer 4 TRGO event */ +# define DAC_CR_TSEL1_EXT9 (6 << DAC_CR_TSEL1_SHIFT) /* External line9 */ +# define DAC_CR_TSEL1_SW (7 << DAC_CR_TSEL1_SHIFT) /* Software trigger */ +#define DAC_CR_WAVE1_SHIFT (6) /* Bits 6-7: DAC channel1 noise/triangle wave generation */enable +#define DAC_CR_WAVE1_MASK (3 << DAC_CR_WAVE1_SHIFT) +# define DAC_CR_WAVE1_DISABLED (0 << DAC_CR_WAVE1_SHIFT) /* Wave generation disabled */ +# define DAC_CR_WAVE1_NOISE (1 << DAC_CR_WAVE1_SHIFT) /* Noise wave generation enabled */ +# define DAC_CR_WAVE1_TRIANGLE (2 << DAC_CR_WAVE1_SHIFT) /* Triangle wave generation enabled */ +#define DAC_CR_MAMP1_SHIFT (8) /* Bits 8-11: DAC channel1 mask/amplitude selector */ +#define DAC_CR_MAMP1_MASK (15 << DAC_CR_MAMP1_SHIFT) +# define DAC_CR_MAMP1_AMP1 (0 << DAC_CR_MAMP1_SHIFT) /* Unmask bit0 of LFSR/triangle amplitude=1 */ +# define DAC_CR_MAMP1_AMP3 (1 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[1:0] of LFSR/triangle amplitude=3 */ +# define DAC_CR_MAMP1_AMP7 (2 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[2:0] of LFSR/triangle amplitude=7 */ +# define DAC_CR_MAMP1_AMP15 (3 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[3:0] of LFSR/triangle amplitude=15 */ +# define DAC_CR_MAMP1_AMP31 (4 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[4:0] of LFSR/triangle amplitude=31 */ +# define DAC_CR_MAMP1_AMP63 (5 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[5:0] of LFSR/triangle amplitude=63 */ +# define DAC_CR_MAMP1_AMP127 (6 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[6:0] of LFSR/triangle amplitude=127 */ +# define DAC_CR_MAMP1_AMP255 (7 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[7:0] of LFSR/triangle amplitude=255 */ +# define DAC_CR_MAMP1_AMP511 (8 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[8:0] of LFSR/triangle amplitude=511 */ +# define DAC_CR_MAMP1_AMP1023 (9 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[9:0] of LFSR/triangle amplitude=1023 */ +# define DAC_CR_MAMP1_AMP2047 (10 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[10:0] of LFSR/triangle amplitude=2047 */ +# define DAC_CR_MAMP1_AMP4095 (11 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[11:0] of LFSR/triangle amplitude=4095 */ +#define DAC_CR_DMAEN1 (1 << 12) /* Bit 12: DAC channel1 DMA enable */ +#define DAC_CR_DMAUDRIE1 (1 << 13) /* Bit 13: DAC channel1 DMA Underrun Interrupt enable */ + +#define DAC_CR_EN2 (1 << 16) /* Bit 16: DAC channel2 enable */ +#define DAC_CR_BOFF2 (1 << 17) /* Bit 17: DAC channel2 output buffer disable */ +#define DAC_CR_TEN2 (1 << 18) /* Bit 18: DAC channel2 trigger enable */ +#define DAC_CR_TSEL2_SHIFT (19) /* Bits 19-21: DAC channel2 trigger selection */ +#define DAC_CR_TSEL2_MASK (7 << DAC_CR_TSEL2_SHIFT) +# define DAC_CR_TSEL2_TIM6 (0 << DAC_CR_TSEL2_SHIFT) /* Timer 6 TRGO event */ +# define DAC_CR_TSEL2_TIM8 (1 << DAC_CR_TSEL2_SHIFT) /* Timer 8 TRGO event */ +# define DAC_CR_TSEL2_TIM7 (2 << DAC_CR_TSEL2_SHIFT) /* Timer 7 TRGO event */ +# define DAC_CR_TSEL2_TIM5 (3 << DAC_CR_TSEL2_SHIFT) /* Timer 5 TRGO event */ +# define DAC_CR_TSEL2_TIM2 (4 << DAC_CR_TSEL2_SHIFT) /* Timer 2 TRGO event */ +# define DAC_CR_TSEL2_TIM4 (5 << DAC_CR_TSEL2_SHIFT) /* Timer 4 TRGO event */ +# define DAC_CR_TSEL2_EXT9 (6 << DAC_CR_TSEL2_SHIFT) /* External line9 */ +# define DAC_CR_TSEL2_SW (7 << DAC_CR_TSEL2_SHIFT) /* Software trigger */ +#define DAC_CR_WAVE2_SHIFT (22) /* Bit 22-23: DAC channel2 noise/triangle wave generation enable */ +#define DAC_CR_WAVE2_MASK (3 << DAC_CR_WAVE2_SHIFT) +# define DAC_CR_WAVE2_DISABLED (0 << DAC_CR_WAVE2_SHIFT) /* Wave generation disabled */ +# define DAC_CR_WAVE2_NOISE (1 << DAC_CR_WAVE2_SHIFT) /* Noise wave generation enabled */ +# define DAC_CR_WAVE2_TRIANGLE (2 << DAC_CR_WAVE2_SHIFT) /* Triangle wave generation enabled */ +#define DAC_CR_MAMP2_SHIFT (24) /* Bit 24-27: DAC channel2 mask/amplitude selector */ +#define DAC_CR_MAMP2_MASK (15 << DAC_CR_MAMP2_SHIFT) +# define DAC_CR_MAMP2_AMP1 (0 << DAC_CR_MAMP2_SHIFT) /* Unmask bit0 of LFSR/triangle amplitude=1 */ +# define DAC_CR_MAMP2_AMP3 (1 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[1:0] of LFSR/triangle amplitude=3 */ +# define DAC_CR_MAMP2_AMP7 (2 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[2:0] of LFSR/triangle amplitude=7 */ +# define DAC_CR_MAMP2_AMP15 (3 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[3:0] of LFSR/triangle amplitude=15 */ +# define DAC_CR_MAMP2_AMP31 (4 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[4:0] of LFSR/triangle amplitude=31 */ +# define DAC_CR_MAMP2_AMP63 (5 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[5:0] of LFSR/triangle amplitude=63 */ +# define DAC_CR_MAMP2_AMP127 (6 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[6:0] of LFSR/triangle amplitude=127 */ +# define DAC_CR_MAMP2_AMP255 (7 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[7:0] of LFSR/triangle amplitude=255 */ +# define DAC_CR_MAMP2_AMP511 (8 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[8:0] of LFSR/triangle amplitude=511 */ +# define DAC_CR_MAMP2_AMP1023 (9 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[9:0] of LFSR/triangle amplitude=1023 */ +# define DAC_CR_MAMP2_AMP2047 (10 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[10:0] of LFSR/triangle amplitude=2047 */ +# define DAC_CR_MAMP2_AMP4095 (11 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[11:0] of LFSR/triangle amplitude=4095 */ +#define DAC_CR_DMAEN2 (1 << 28) /* Bit 28: DAC channel2 DMA enable */ +#define DAC_CR_DMAUDRIE2 (1 << 29) /* Bits 29: DAC channel2 DMA underrun interrupt enable */ + +/* DAC software trigger register */ + +#define DAC_SWTRIGR_SWTRIG(n) (1 << ((n)-1)) +#define DAC_SWTRIGR_SWTRIG1 (1 << 0) /* Bit 0: DAC channel1 software trigger */ +#define DAC_SWTRIGR_SWTRIG2 (1 << 1) /* Bit 1: DAC channel2 software trigger */ + +/* DAC channel1/2 12-bit right-aligned data holding register */ + +#define DAC_DHR12R_MASK (0x0fff) + +/* DAC channel1/2 12-bit left aligned data holding register */ + +#define DAC_DHR12L_MASK (0xfff0) + +/* DAC channel1/2 8-bit right aligned data holding register */ + +#define DAC_DHR8R_MASK (0x00ff) + +/* Dual DAC 12-bit right-aligned data holding register */ + +#define DAC_DHR12RD_DACC_SHIFT(n) (1 << (((n)-1) << 4)) +#define DAC_DHR12RD_DACC_MASK(n) (0xfff << DAC_DHR12RD_DACC_SHIFT(n)) + +#define DAC_DHR12RD_DACC1_SHIFT (0) /* Bits 0-11: DAC channel1 12-bit right-aligned data */ +#define DAC_DHR12RD_DACC1_MASK (0xfff << DAC_DHR12RD_DACC2_SHIFT) +#define DAC_DHR12RD_DACC2_SHIFT (16) /* Bits 16-27: DAC channel2 12-bit right-aligned data */ +#define DAC_DHR12RD_DACC2_MASK (0xfff << DAC_DHR12RD_DACC2_SHIFT) + +/* Dual DAC 12-bit left-aligned data holding register */ + +#define DAC_DHR12LD_DACC_SHIFT(n) ((1 << (((n)-1) << 4)) + 4) +#define DAC_DHR12LD_DACC_MASK(n) (0xfff << DAC_DHR12LD_DACC_SHIFT(n)) + +#define DAC_DHR12LD_DACC1_SHIFT (4) /* Bits 4-15: DAC channel1 12-bit left-aligned data */ +#define DAC_DHR12LD_DACC1_MASK (0xfff << DAC_DHR12LD_DACC1_SHIFT) +#define DAC_DHR12LD_DACC2_SHIFT (20) /* Bits 20-31: DAC channel2 12-bit left-aligned data */ +#define DAC_DHR12LD_DACC2_MASK (0xfff << DAC_DHR12LD_DACC2_SHIFT) + +/* DUAL DAC 8-bit right aligned data holding register */ + +#define DAC_DHR8RD_DACC_SHIFT(n) (1 << (((n)-1) << 3)) +#define DAC_DHR8RD_DACC_MASK(n) (0xff << DAC_DHR8RD_DACC_SHIFT(n)) + +#define DAC_DHR8RD_DACC1_SHIFT (0) /* Bits 0-7: DAC channel1 8-bit right-aligned data */ +#define DAC_DHR8RD_DACC1_MASK (0xff << DAC_DHR8RD_DACC1_SHIFT) +#define DAC_DHR8RD_DACC2_SHIFT (8) /* Bits 8-15: DAC channel2 8-bit right-aligned data */ +#define DAC_DHR8RD_DACC2_MASK (0xff << DAC_DHR8RD_DACC2_SHIFT) + +/* DAC channel1/2 data output register */ + +#define DAC_DOR_MASK (0x0fff) + +/* DAC status register */ + +#define DAC_SR_DMAUDR(n) ((1 << (((n)-1) << 4)) + 13) +#define DAC_SR_DMAUDR1 (1 << 13) /* Bit 13: DAC channel1 DMA underrun flag */ +#define DAC_SR_DMAUDR2 (1 << 29) /* Bit 29: DAC channel2 DMA underrun flag */ + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_DAC_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_dbgmcu.h b/nuttx/arch/arm/src/stm32/chip/stm32_dbgmcu.h new file mode 100644 index 0000000000..ff16613132 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_dbgmcu.h @@ -0,0 +1,144 @@ +/**************************************************************************************************** + * arch/arm/src/stm32/chip/stm32_dbgmcu.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_DBGMCU_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_DBGMCU_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include + +#include "chip.h" + +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ + +/* Register Addresses *******************************************************************************/ + +#define STM32_DBGMCU_IDCODE 0xe0042000 /* MCU identifier */ +#define STM32_DBGMCU_CR 0xe0042004 /* MCU debug */ +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_DBGMCU_APB1_FZ 0xe0042008 /* Debug MCU APB1 freeze register */ +# define STM32_DBGMCU_APB2_FZ 0xe004200c /* Debug MCU APB2 freeze register */ +#endif + +/* Register Bitfield Definitions ********************************************************************/ + +/* MCU identifier */ + +#define DBGMCU_IDCODE_DEVID_SHIFT (0) /* Bits 11-0: Device Identifier */ +#define DBGMCU_IDCODE_DEVID_MASK (0x0fff << DBGMCU_IDCODE_DEVID_SHIFT) +#define DBGMCU_IDCODE_REVID_SHIFT (16) /* Bits 31-16: Revision Identifier */ +#define DBGMCU_IDCODE_REVID_MASK (0xffff << DBGMCU_IDCODE_REVID_SHIFT) + +/* MCU debug */ + +#define DBGMCU_CR_SLEEP (1 << 0) /* Bit 0: Debug Sleep Mode */ +#define DBGMCU_CR_STOP (1 << 1) /* Bit 1: Debug Stop Mode */ +#define DBGMCU_CR_STANDBY (1 << 2) /* Bit 2: Debug Standby mode */ +#define DBGMCU_CR_TRACEIOEN (1 << 5) /* Bit 5: Trace enabled */ + +#define DBGMCU_CR_TRACEMODE_SHIFT (6) /* Bits 7-6: Trace mode pin assignement */ +#define DBGMCU_CR_TRACEMODE_MASK (3 << DBGMCU_CR_TRACEMODE_SHIFT) +# define DBGMCU_CR_ASYNCH (0 << DBGMCU_CR_TRACEMODE_SHIFT) /* Asynchronous Mode */ +# define DBGMCU_CR_SYNCH1 (1 << DBGMCU_CR_TRACEMODE_SHIFT) /* Synchronous Mode, TRACEDATA size=1 */ +# define DBGMCU_CR_SYNCH2 (2 << DBGMCU_CR_TRACEMODE_SHIFT) /* Synchronous Mode, TRACEDATA size=2 */ +# define DBGMCU_CR_SYNCH4 (3 << DBGMCU_CR_TRACEMODE_SHIFT) /* Synchronous Mode, TRACEDATA size=4 */ + +#ifdef CONFIG_STM32_STM32F10XX +# define DBGMCU_CR_IWDGSTOP (1 << 8) /* Bit 8: Independent Watchdog stopped when core is halted */ +# define DBGMCU_CR_WWDGSTOP (1 << 9) /* Bit 9: Window Watchdog stopped when core is halted */ +# define DBGMCU_CR_TIM1STOP (1 << 10) /* Bit 10: TIM1 stopped when core is halted */ +# define DBGMCU_CR_TIM2STOP (1 << 11) /* Bit 11: TIM2 stopped when core is halted */ +# define DBGMCU_CR_TIM3STOP (1 << 12) /* Bit 12: TIM3 stopped when core is halted */ +# define DBGMCU_CR_TIM4STOP (1 << 13) /* Bit 13: TIM4 stopped when core is halted */ +# define DBGMCU_CR_CAN1STOP (1 << 14) /* Bit 14: CAN1 stopped when core is halted */ +# define DBGMCU_CR_SMBUS1STOP (1 << 15) /* Bit 15: I2C1 SMBUS timeout mode stopped when core is halted */ +# define DBGMCU_CR_SMBUS2STOP (1 << 16) /* Bit 16: I2C2 SMBUS timeout mode stopped when core is halted */ +# define DBGMCU_CR_TIM8STOP (1 << 17) /* Bit 17: TIM8 stopped when core is halted */ +# define DBGMCU_CR_TIM5STOP (1 << 18) /* Bit 18: TIM5 stopped when core is halted */ +# define DBGMCU_CR_TIM6STOP (1 << 19) /* Bit 19: TIM6 stopped when core is halted */ +# define DBGMCU_CR_TIM7STOP (1 << 20) /* Bit 20: TIM7 stopped when core is halted */ +# define DBGMCU_CR_CAN2STOP (1 << 21) /* Bit 21: CAN2 stopped when core is halted */ +#endif + +/* Debug MCU APB1 freeze register */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define DBGMCU_APB1_TIM2STOP (1 << 0) /* Bit 0: TIM2 stopped when core is halted */ +# define DBGMCU_APB1_TIM3STOP (1 << 1) /* Bit 1: TIM3 stopped when core is halted */ +# define DBGMCU_APB1_TIM4STOP (1 << 2) /* Bit 2: TIM4 stopped when core is halted */ +# define DBGMCU_APB1_TIM5STOP (1 << 3) /* Bit 3: TIM5 stopped when core is halted */ +# define DBGMCU_APB1_TIM6STOP (1 << 4) /* Bit 4: TIM6 stopped when core is halted */ +# define DBGMCU_APB1_TIM7STOP (1 << 5) /* Bit 5: TIM7 stopped when core is halted */ +# define DBGMCU_APB1_TIM12STOP (1 << 6) /* Bit 6: TIM12 stopped when core is halted */ +# define DBGMCU_APB1_TIM13STOP (1 << 7) /* Bit 7: TIM13 stopped when core is halted */ +# define DBGMCU_APB1_TIM14STOP (1 << 8) /* Bit 7: TIM14 stopped when core is halted */ +# define DBGMCU_CR_RTCSTOP (1 << 10) /* Bit 11: RTC stopped when Core is halted */ +# define DBGMCU_CR_WWDGSTOP (1 << 11) /* Bit 11: Window Watchdog stopped when core is halted */ +# define DBGMCU_CR_IWDGSTOP (1 << 12) /* Bit 12: Independent Watchdog stopped when core is halted */ +# define DBGMCU_APB1_I2C1STOP (1 << 21) /* Bit 21: SMBUS timeout mode stopped when Core is halted */ +# define DBGMCU_APB1_I2C2STOP (1 << 22) /* Bit 22: SMBUS timeout mode stopped when Core is halted */ +# define DBGMCU_APB1_I2C3STOP (1 << 23) /* Bit 23: SMBUS timeout mode stopped when Core is halted */ +# define DBGMCU_APB1_CAN1STOP (1 << 25) /* Bit 25: CAN1 stopped when core is halted */ +# define DBGMCU_APB1_CAN2STOP (1 << 26) /* Bit 26: CAN2 stopped when core is halted */ +#endif + +/* Debug MCU APB2 freeze register */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define DBGMCU_APB2_TIM1STOP (1 << 0) /* Bit 0: TIM1 stopped when core is halted */ +# define DBGMCU_APB2_TIM8STOP (1 << 1) /* Bit 1: TIM8 stopped when core is halted */ +# define DBGMCU_APB2_TIM9STOP (1 << 16) /* Bit 16: TIM9 stopped when core is halted */ +# define DBGMCU_APB2_TIM10STOP (1 << 17) /* Bit 17: TIM10 stopped when core is halted */ +# define DBGMCU_APB2_TIM11STOP (1 << 18) /* Bit 18: TIM11 stopped when core is halted */ +#endif + +/**************************************************************************************************** + * Public Types + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public Data + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public Functions + ****************************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_DBGMCU_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_eth.h b/nuttx/arch/arm/src/stm32/chip/stm32_eth.h new file mode 100644 index 0000000000..431144009e --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_eth.h @@ -0,0 +1,829 @@ +/**************************************************************************************************** + * arch/arm/src/stm32/chip/stm32_eth.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_ETH_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_ETH_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include + +#include "chip.h" + +#if STM32_NETHERNET > 0 + +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ +/* Register Offsets *********************************************************************************/ +/* MAC Registers */ + +#define STM32_ETH_MACCR_OFFSET 0x0000 /* Ethernet MAC configuration register */ +#define STM32_ETH_MACFFR_OFFSET 0x0004 /* Ethernet MAC frame filter register */ +#define STM32_ETH_MACHTHR_OFFSET 0x0008 /* Ethernet MAC hash table high register */ +#define STM32_ETH_MACHTLR_OFFSET 0x000c /* Ethernet MAC hash table low register */ +#define STM32_ETH_MACMIIAR_OFFSET 0x0010 /* Ethernet MAC MII address register */ +#define STM32_ETH_MACMIIDR_OFFSET 0x0014 /* Ethernet MAC MII data register */ +#define STM32_ETH_MACFCR_OFFSET 0x0018 /* Ethernet MAC flow control register */ +#define STM32_ETH_MACVLANTR_OFFSET 0x001c /* Ethernet MAC VLAN tag register */ +#define STM32_ETH_MACRWUFFR_OFFSET 0x0028 /* Ethernet MAC remote wakeup frame filter reg */ +#define STM32_ETH_MACPMTCSR_OFFSET 0x002c /* Ethernet MAC PMT control and status register */ +#define STM32_ETH_MACDBGR_OFFSET 0x0034 /* Ethernet MAC debug register */ +#define STM32_ETH_MACSR_OFFSET 0x0038 /* Ethernet MAC interrupt status register */ +#define STM32_ETH_MACIMR_OFFSET 0x003c /* Ethernet MAC interrupt mask register */ +#define STM32_ETH_MACA0HR_OFFSET 0x0040 /* Ethernet MAC address 0 high register */ +#define STM32_ETH_MACA0LR_OFFSET 0x0044 /* Ethernet MAC address 0 low register */ +#define STM32_ETH_MACA1HR_OFFSET 0x0048 /* Ethernet MAC address 1 high register */ +#define STM32_ETH_MACA1LR_OFFSET 0x004c /* Ethernet MAC address1 low register */ +#define STM32_ETH_MACA2HR_OFFSET 0x0050 /* Ethernet MAC address 2 high register */ +#define STM32_ETH_MACA2LR_OFFSET 0x0054 /* Ethernet MAC address 2 low register */ +#define STM32_ETH_MACA3HR_OFFSET 0x0058 /* Ethernet MAC address 3 high register */ +#define STM32_ETH_MACA3LR_OFFSET 0x005c /* Ethernet MAC address 3 low register */ + +/* MMC Registers */ + +#define STM32_ETH_MMCCR_OFFSET 0x0100 /* Ethernet MMC control register */ +#define STM32_ETH_MMCRIR_OFFSET 0x0104 /* Ethernet MMC receive interrupt register */ +#define STM32_ETH_MMCTIR_OFFSET 0x0108 /* Ethernet MMC transmit interrupt register */ +#define STM32_ETH_MMCRIMR_OFFSET 0x010c /* Ethernet MMC receive interrupt mask register */ +#define STM32_ETH_MMCTIMR_OFFSET 0x0110 /* Ethernet MMC transmit interrupt mask register */ +#define STM32_ETH_MMCTGFSCCR_OFFSET 0x014c /* Ethernet MMC transmitted good frames counter register (single collision) */ +#define STM32_ETH_MMCTGFMSCCR_OFFSET 0x0150 /* Ethernet MMC transmitted good frames counter register (multiple-collision) */ +#define STM32_ETH_MMCTGFCR_OFFSET 0x0168 /* Ethernet MMC transmitted good frames counter register */ +#define STM32_ETH_MMCRFCECR_OFFSET 0x0194 /* Ethernet MMC received frames with CRC error counter register */ +#define STM32_ETH_MMCRFAECR_OFFSET 0x0198 /* Ethernet MMC received frames with alignment error counter */ +#define STM32_ETH_MMCRGUFCR_OFFSET 0x01c4 /* MMC received good unicast frames counter register */ + +/* IEEE 1588 time stamp registers */ + +#define STM32_ETH_PTPTSCR_OFFSET 0x0700 /* Ethernet PTP time stamp control register */ +#define STM32_ETH_PTPSSIR_OFFSET 0x0704 /* Ethernet PTP subsecond increment register */ +#define STM32_ETH_PTPTSHR_OFFSET 0x0708 /* Ethernet PTP time stamp high register */ +#define STM32_ETH_PTPTSLR_OFFSET 0x070c /* Ethernet PTP time stamp low register */ +#define STM32_ETH_PTPTSHUR_OFFSET 0x0710 /* Ethernet PTP time stamp high update register */ +#define STM32_ETH_PTPTSLUR_OFFSET 0x0714 /* Ethernet PTP time stamp low update register */ +#define STM32_ETH_PTPTSAR_OFFSET 0x0718 /* Ethernet PTP time stamp addend register */ +#define STM32_ETH_PTPTTHR_OFFSET 0x071c /* Ethernet PTP target time high register */ +#define STM32_ETH_PTPTTLR_OFFSET 0x0720 /* Ethernet PTP target time low register */ +#define STM32_ETH_PTPTSSR_OFFSET 0x0728 /* Ethernet PTP time stamp status register */ +#define STM32_ETH_PTPPPSCR_OFFSET 0x072c /* Ethernet PTP PPS control register */ + +/* DMA Registers */ + +#define STM32_ETH_DMABMR_OFFSET 0x1000 /* Ethernet DMA bus mode register */ +#define STM32_ETH_DMATPDR_OFFSET 0x1004 /* Ethernet DMA transmit poll demand register */ +#define STM32_ETH_DMARPDR_OFFSET 0x1008 /* Ethernet DMA receive poll demand register */ +#define STM32_ETH_DMARDLAR_OFFSET 0x100c /* Ethernet DMA receive descriptor list address register */ +#define STM32_ETH_DMATDLAR_OFFSET 0x1010 /* Ethernet DMA transmit descriptor list address register */ +#define STM32_ETH_DMASR_OFFSET 0x1014 /* Ethernet DMA status register */ +#define STM32_ETH_DMAOMR_OFFSET 0x1018 /* Ethernet DMA operation mode register */ +#define STM32_ETH_DMAIER_OFFSET 0x101c /* Ethernet DMA interrupt enable register */ +#define STM32_ETH_DMAMFBOC_OFFSET 0x1020 /* Ethernet DMA missed frame and buffer overflow counter register */ +#define STM32_ETH_DMARSWTR_OFFSET 0x1024 /* Ethernet DMA receive status watchdog timer register */ +#define STM32_ETH_DMACHTDR_OFFSET 0x1048 /* Ethernet DMA current host transmit descriptor register */ +#define STM32_ETH_DMACHRDR_OFFSET 0x104c /* Ethernet DMA current host receive descriptor register */ +#define STM32_ETH_DMACHTBAR_OFFSET 0x1050 /* Ethernet DMA current host transmit buffer address register */ +#define STM32_ETH_DMACHRBAR_OFFSET 0x1054 /* Ethernet DMA current host receive buffer address register */ + +/* Register Base Addresses **************************************************************************/ +/* MAC Registers */ + +#define STM32_ETH_MACCR (STM32_ETHERNET_BASE+STM32_ETH_MACCR_OFFSET) +#define STM32_ETH_MACFFR (STM32_ETHERNET_BASE+STM32_ETH_MACFFR_OFFSET) +#define STM32_ETH_MACHTHR (STM32_ETHERNET_BASE+STM32_ETH_MACHTHR_OFFSET) +#define STM32_ETH_MACHTLR (STM32_ETHERNET_BASE+STM32_ETH_MACHTLR_OFFSET) +#define STM32_ETH_MACMIIAR (STM32_ETHERNET_BASE+STM32_ETH_MACMIIAR_OFFSET) +#define STM32_ETH_MACMIIDR (STM32_ETHERNET_BASE+STM32_ETH_MACMIIDR_OFFSET) +#define STM32_ETH_MACFCR (STM32_ETHERNET_BASE+STM32_ETH_MACFCR_OFFSET) +#define STM32_ETH_MACVLANTR (STM32_ETHERNET_BASE+STM32_ETH_MACVLANTR_OFFSET) +#define STM32_ETH_MACRWUFFR (STM32_ETHERNET_BASE+STM32_ETH_MACRWUFFR_OFFSET) +#define STM32_ETH_MACPMTCSR (STM32_ETHERNET_BASE+STM32_ETH_MACPMTCSR_OFFSET) +#define STM32_ETH_MACDBGR (STM32_ETHERNET_BASE+STM32_ETH_MACDBGR_OFFSET) +#define STM32_ETH_MACSR (STM32_ETHERNET_BASE+STM32_ETH_MACSR_OFFSET) +#define STM32_ETH_MACIMR (STM32_ETHERNET_BASE+STM32_ETH_MACIMR_OFFSET) +#define STM32_ETH_MACA0HR (STM32_ETHERNET_BASE+STM32_ETH_MACA0HR_OFFSET) +#define STM32_ETH_MACA0LR (STM32_ETHERNET_BASE+STM32_ETH_MACA0LR_OFFSET) +#define STM32_ETH_MACA1HR (STM32_ETHERNET_BASE+STM32_ETH_MACA1HR_OFFSET) +#define STM32_ETH_MACA1LR (STM32_ETHERNET_BASE+STM32_ETH_MACA1LR_OFFSET) +#define STM32_ETH_MACA2HR (STM32_ETHERNET_BASE+STM32_ETH_MACA2HR_OFFSET) +#define STM32_ETH_MACA2LR (STM32_ETHERNET_BASE+STM32_ETH_MACA2LR_OFFSET) +#define STM32_ETH_MACA3HR (STM32_ETHERNET_BASE+STM32_ETH_MACA3HR_OFFSET) +#define STM32_ETH_MACA3LR (STM32_ETHERNET_BASE+STM32_ETH_MACA3LR_OFFSET) + +/* MMC Registers */ + +#define STM32_ETH_MMCC (STM32_ETHERNET_BASE+STM32_ETH_MMCCR_OFFSET) +#define STM32_ETH_MMCRIR (STM32_ETHERNET_BASE+STM32_ETH_MMCRIR_OFFSET) +#define STM32_ETH_MMCTIR (STM32_ETHERNET_BASE+STM32_ETH_MMCTIR_OFFSET) +#define STM32_ETH_MMCRIMR (STM32_ETHERNET_BASE+STM32_ETH_MMCRIMR_OFFSET) +#define STM32_ETH_MMCTIMR (STM32_ETHERNET_BASE+STM32_ETH_MMCTIMR_OFFSET) +#define STM32_ETH_MMCTGFSCCR (STM32_ETHERNET_BASE+STM32_ETH_MMCTGFSCCR_OFFSET) +#define STM32_ETH_MMCTGFMSCCR (STM32_ETHERNET_BASE+STM32_ETH_MMCTGFMSCCR_OFFSET) +#define STM32_ETH_MMCTGFCR (STM32_ETHERNET_BASE+STM32_ETH_MMCTGFCR_OFFSET) +#define STM32_ETH_MMCRFCECR (STM32_ETHERNET_BASE+STM32_ETH_MMCRFCECR_OFFSET) +#define STM32_ETH_MMCRFAECR (STM32_ETHERNET_BASE+STM32_ETH_MMCRFAECR_OFFSET) +#define STM32_ETH_MMCRGUFCR (STM32_ETHERNET_BASE+STM32_ETH_MMCRGUFCR_OFFSET) + +/* IEEE 1588 time stamp registers */ + +#define STM32_ETH_PTPTSCR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSCR_OFFSET) +#define STM32_ETH_PTPSSIR (STM32_ETHERNET_BASE+STM32_ETH_PTPSSIR_OFFSET) +#define STM32_ETH_PTPTSHR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSHR_OFFSET) +#define STM32_ETH_PTPTSLR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSLR_OFFSET) +#define STM32_ETH_PTPTSHUR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSHUR_OFFSET) +#define STM32_ETH_PTPTSLUR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSLUR_OFFSET) +#define STM32_ETH_PTPTSAR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSAR_OFFSET) +#define STM32_ETH_PTPTTHR (STM32_ETHERNET_BASE+STM32_ETH_PTPTTHR_OFFSET) +#define STM32_ETH_PTPTTLR (STM32_ETHERNET_BASE+STM32_ETH_PTPTTLR_OFFSET) +#define STM32_ETH_PTPTSSR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSSR_OFFSET) +#define STM32_ETH_PTPPPSCR (STM32_ETHERNET_BASE+STM32_ETH_PTPPPSCR_OFFSET) + +/* DMA Registers */ + +#define STM32_ETH_DMABMR (STM32_ETHERNET_BASE+STM32_ETH_DMABMR_OFFSET) +#define STM32_ETH_DMATPDR (STM32_ETHERNET_BASE+STM32_ETH_DMATPDR_OFFSET) +#define STM32_ETH_DMARPDR (STM32_ETHERNET_BASE+STM32_ETH_DMARPDR_OFFSET) +#define STM32_ETH_DMARDLAR (STM32_ETHERNET_BASE+STM32_ETH_DMARDLAR_OFFSET) +#define STM32_ETH_DMATDLAR (STM32_ETHERNET_BASE+STM32_ETH_DMATDLAR_OFFSET) +#define STM32_ETH_DMASR (STM32_ETHERNET_BASE+STM32_ETH_DMASR_OFFSET) +#define STM32_ETH_DMAOMR (STM32_ETHERNET_BASE+STM32_ETH_DMAOMR_OFFSET) +#define STM32_ETH_DMAIER (STM32_ETHERNET_BASE+STM32_ETH_DMAIER_OFFSET) +#define STM32_ETH_DMAMFBOC (STM32_ETHERNET_BASE+STM32_ETH_DMAMFBOC_OFFSET) +#define STM32_ETH_DMARSWTR (STM32_ETHERNET_BASE+STM32_ETH_DMARSWTR_OFFSET) +#define STM32_ETH_DMACHTDR (STM32_ETHERNET_BASE+STM32_ETH_DMACHTDR_OFFSET) +#define STM32_ETH_DMACHRDR (STM32_ETHERNET_BASE+STM32_ETH_DMACHRDR_OFFSET) +#define STM32_ETH_DMACHTBAR (STM32_ETHERNET_BASE+STM32_ETH_DMACHTBAR_OFFSET) +#define STM32_ETH_DMACHRBAR (STM32_ETHERNET_BASE+STM32_ETH_DMACHRBAR_OFFSET) + +/* Register Bit-Field Definitions *******************************************************************/ +/* MAC Registers */ + +/* Ethernet MAC configuration register */ + +#define ETH_MACCR_RE (1 << 2) /* Bit 2: Receiver enable */ +#define ETH_MACCR_TE (1 << 3) /* Bit 3: Transmitter enable */ +#define ETH_MACCR_DC (1 << 4) /* Bit 4: Deferral check */ +#define ETH_MACCR_BL_SHIFT (5) /* Bits 5-6: Back-off limit */ +#define ETH_MACCR_BL_MASK (3 << ETH_MACCR_BL_SHIFT) +# define ETH_MACCR_BL_10 (0 << ETH_MACCR_BL_SHIFT) /* 00: k = min (n, 10) */ +# define ETH_MACCR_BL_8 (1 << ETH_MACCR_BL_SHIFT) /* 01: k = min (n, 8) */ +# define ETH_MACCR_BL_4 (2 << ETH_MACCR_BL_SHIFT) /* 10: k = min (n, 4) */ +# define ETH_MACCR_BL_1 (3 << ETH_MACCR_BL_SHIFT) /* 11: k = min (n, 1) */ +#define ETH_MACCR_APCS (1 << 7) /* Bit 7: Automatic pad/CRC stripping */ +#define ETH_MACCR_RD (1 << 9) /* Bit 9: Retry disable */ +#define ETH_MACCR_IPCO (1 << 10) /* Bit 10: IPv4 checksum offload */ +#define ETH_MACCR_DM (1 << 11) /* Bit 11: Duplex mode */ +#define ETH_MACCR_LM (1 << 12) /* Bit 12: Loopback mode */ +#define ETH_MACCR_ROD (1 << 13) /* Bit 13: Receive own disable */ +#define ETH_MACCR_FES (1 << 14) /* Bit 14: Fast Ethernet speed */ +#define ETH_MACCR_CSD (1 << 16) /* Bit 16: Carrier sense disable */ +#define ETH_MACCR_IFG_SHIFT (17) /* Bits 17-19: Interframe gap */ +#define ETH_MACCR_IFG_MASK (7 << ETH_MACCR_IFG_SHIFT) +# define ETH_MACCR_IFG(n) ((12-((n) >> 3)) << ETH_MACCR_IFG_SHIFT) /* n bit times, n=40,48,..96 */ +#define ETH_MACCR_JD (1 << 22) /* Bit 22: Jabber disable */ +#define ETH_MACCR_WD (1 << 23) /* Bit 23: Watchdog disable */ +#define ETH_MACCR_CSTF (1 << 25) /* Bits 25: CRC stripping for Type frames */ + +/* Ethernet MAC frame filter register */ + +#define ETH_MACFFR_PM (1 << 0) /* Bit 0: Promiscuous mode */ +#define ETH_MACFFR_HU (1 << 1) /* Bit 1: Hash unicast */ +#define ETH_MACFFR_HM (1 << 2) /* Bit 2: Hash multicast */ +#define ETH_MACFFR_DAIF (1 << 3) /* Bit 3: Destination address inverse filtering */ +#define ETH_MACFFR_PAM (1 << 4) /* Bit 4: Pass all multicast */ +#define ETH_MACFFR_BFD (1 << 5) /* Bit 5: Broadcast frames disable */ +#define ETH_MACFFR_PCF_SHIFT (6) /* Bits 6-7: Pass control frames */ +#define ETH_MACFFR_PCF_MASK (3 << ETH_MACFFR_PCF_SHIFT) +# define ETH_MACFFR_PCF_NONE (0 << ETH_MACFFR_PCF_SHIFT) /* Prevents all control frames */ +# define ETH_MACFFR_PCF_PAUSE (1 << ETH_MACFFR_PCF_SHIFT) /* Prevents all except Pause control frames */ +# define ETH_MACFFR_PCF_ALL (2 << ETH_MACFFR_PCF_SHIFT) /* Forwards all control frames */ +# define ETH_MACFFR_PCF_FILTER (3 << ETH_MACFFR_PCF_SHIFT) /* Forwards all that pass address filter */ +#define ETH_MACFFR_SAIF (1 << 8) /* Bit 8: Source address inverse filtering */ +#define ETH_MACFFR_SAF (1 << 9) /* Bit 9: Source address filter */ +#define ETH_MACFFR_HPF (1 << 10) /* Bit 10: Hash or perfect filter */ +#define ETH_MACFFR_RA (1 << 31) /* Bit 31: Receive all */ + +/* Ethernet MAC hash table high/low registers (32-bit values) */ + +/* Ethernet MAC MII address register */ + +#define ETH_MACMIIAR_MB (1 << 0) /* Bit 0: MII busy */ +#define ETH_MACMIIAR_MW (1 << 1) /* Bit 1: MII write */ +#define ETH_MACMIIAR_CR_SHIFT (2) /* Bits 2-4: Clock range */ +#define ETH_MACMIIAR_CR_MASK (7 << ETH_MACMIIAR_CR_SHIFT) +#if 0 /* Per the reference manual */ +# define ETH_MACMIIAR_CR_60_100 (0 << ETH_MACMIIAR_CR_SHIFT) /* 000 60-100 MHzHCLK/42 */ +# define ETH_MACMIIAR_CR_100_168 (1 << ETH_MACMIIAR_CR_SHIFT) /* 001 100-168 MHz HCLK/62 */ +# define ETH_MACMIIAR_CR_20_35 (2 << ETH_MACMIIAR_CR_SHIFT) /* 010 20-35 MHz HCLK/16 */ +# define ETH_MACMIIAR_CR_35_60 (3 << ETH_MACMIIAR_CR_SHIFT) /* 011 35-60 MHz HCLK/26 */ +#else /* Per the driver example */ +# define ETH_MACMIIAR_CR_60_100 (0 << ETH_MACMIIAR_CR_SHIFT) /* 000 60-100 MHz HCLK/42 */ +# define ETH_MACMIIAR_CR_100_150 (1 << ETH_MACMIIAR_CR_SHIFT) /* 001 100-150 MHz HCLK/62 */ +# define ETH_MACMIIAR_CR_20_35 (2 << ETH_MACMIIAR_CR_SHIFT) /* 010 20-35 MHz HCLK/16 */ +# define ETH_MACMIIAR_CR_35_60 (3 << ETH_MACMIIAR_CR_SHIFT) /* 011 35-60 MHz HCLK/26 */ +# define ETH_MACMIIAR_CR_150_168 (4 << ETH_MACMIIAR_CR_SHIFT) /* 100 150-168 MHz HCLK/102 */ +#endif +#define ETH_MACMIIAR_MR_SHIFT (6) /* Bits 6-10: MII register */ +#define ETH_MACMIIAR_MR_MASK (31 << ETH_MACMIIAR_MR_SHIFT) +#define ETH_MACMIIAR_PA_SHIFT (11) /* Bits 11-15: PHY address */ +#define ETH_MACMIIAR_PA_MASK (31 << ETH_MACMIIAR_PA_SHIFT) + +/* Ethernet MAC MII data register */ + +#define ETH_MACMIIDR_MASK (0xffff) + +/* Ethernet MAC flow control register */ + +#define ETH_MACFCR_FCB_BPA (1 << 0) /* Bit 0: Flow control busy/back pressure activate */ +#define ETH_MACFCR_TFCE (1 << 1) /* Bit 1: Transmit flow control enable */ +#define ETH_MACFCR_RFCE (1 << 2) /* Bit 2: Receive flow control enable */ +#define ETH_MACFCR_UPFD (1 << 3) /* Bit 3: Unicast pause frame detect */ +#define ETH_MACFCR_PLT_SHIFT (4) /* Bits 4-5: Pause low threshold */ +#define ETH_MACFCR_PLT_MASK (3 << ETH_MACFCR_PLT_SHIFT) +# define ETH_MACFCR_PLT_M4 (0 << ETH_MACFCR_PLT_SHIFT) /* 00 Pause - 4 slot times */ +# define ETH_MACFCR_PLT_M28 (1 << ETH_MACFCR_PLT_SHIFT) /* 01 Pause - 28 slot times */ +# define ETH_MACFCR_PLT_M144 (2 << ETH_MACFCR_PLT_SHIFT) /* 10 Pause - 144 slot times */ +# define ETH_MACFCR_PLT_M256 (3 << ETH_MACFCR_PLT_SHIFT) /* 11 Pause -s 256 slot times */ +#define ETH_MACFCR_ZQPD (1 << 7) /* Bit 7: Zero-quanta pause disable */ +#define ETH_MACFCR_PT_SHIFT (16) /* Bits 16-31: Pause time */ +#define ETH_MACFCR_PT_MASK (0xffff << ETH_MACFCR_PT_SHIFT) + +/* Ethernet MAC VLAN tag register */ + +#define ETH_MACVLANTR_VLANTI_SHIFT (0) /* Bits 0-15: VLAN tag identifier (for receive frames) */ +#define ETH_MACVLANTR_VLANTI_MASK (0xffff << ETH_MACVLANTR_VLANTI_SHIFT) +#define ETH_MACVLANTR_VLANTC (1 << 16) /* Bit 16: 12-bit VLAN tag comparison */ + +/* Ethernet MAC remote wakeup frame filter reg. Provides 32-bit access to remote + * remote wake-up filters. + */ + +/* Ethernet MAC PMT control and status register */ + +#define ETH_MACPMTCSR_PD (1 << 0) /* Bit 0: Power down */ +#define ETH_MACPMTCSR_MPE (1 << 1) /* Bit 1: Magic Packet enable */ +#define ETH_MACPMTCSR_WFE (1 << 2) /* Bit 2: Wakeup frame enable */ +#define ETH_MACPMTCSR_MPR (1 << 5) /* Bit 5: Magic packet received */ +#define ETH_MACPMTCSR_WFR (1 << 6) /* Bit 6: Wakeup frame received */ +#define ETH_MACPMTCSR_GU (1 << 9) /* Bit 9: Global unicast */ + +/* Ethernet MAC debug register */ + +#define ETH_MACDBGR_MMRPEA (1 << 0) /* Bit 0: MAC MII receive protocol engine active */ +#define ETH_MACDBGR_MSFRWCS_SHIFT (1) /* Bits 1-2: MAC small FIFO read / write controllers status */ +#define ETH_MACDBGR_MSFRWCS_MASK (3 << ETH_MACDBGR_MSFRWCS_SHIFT) +#define ETH_MACDBGR_RFWRA (1 << 4) /* Bit 4: Rx FIFO write controller active */ +#define ETH_MACDBGR_RFRCS_SHIFT (5) /* Bits 5-6: Rx FIFO read controller status */ +#define ETH_MACDBGR_RFRCS_MASK (3 << ETH_MACDBGR_RFRCS_SHIFT) +# define ETH_MACDBGR_RFRCS_IDLE (0 << ETH_MACDBGR_RFRCS_SHIFT) /* 00: IDLE state */ +# define ETH_MACDBGR_RFRCS_RFRAME (1 << ETH_MACDBGR_RFRCS_SHIFT) /* 01: Reading frame data */ +# define ETH_MACDBGR_RFRCS_RSTATUS (2 << ETH_MACDBGR_RFRCS_SHIFT) /* 10: Reading frame status (or time-stamp) */ +# define ETH_MACDBGR_RFRCS_FLUSHING (3 << ETH_MACDBGR_RFRCS_SHIFT) /* 11: Flushing the frame data and status */ +#define ETH_MACDBGR_RFFL_SHIFT (8) /* Bits 8-9: Rx FIFO fill level */ +#define ETH_MACDBGR_RFFL_MASK (3 << ETH_MACDBGR_RFFL_SHIFT) +# define ETH_MACDBGR_RFFL_EMPTY (0 << ETH_MACDBGR_RFFL_SHIFT) /* 00: RxFIFO empty */ +# define ETH_MACDBGR_RFFL_DEACT (1 << ETH_MACDBGR_RFFL_SHIFT) /* 01: RxFIFO fill-level below flow-control de-activate threshold */ +# define ETH_MACDBGR_RFFL_ACTIV (2 << ETH_MACDBGR_RFFL_SHIFT) /* 10: RxFIFO fill-level above flow-control activate threshold */ +# define ETH_MACDBGR_RFFL_FULL (3 << ETH_MACDBGR_RFFL_SHIFT) /* 11: RxFIFO full */ +#define ETH_MACDBGR_MMTEA (1 << 16) /* Bit 16: MAC MII transmit engine active */ +#define ETH_MACDBGR_MTFCS_SHIFT (17) /* Bits 17-18: MAC transmit frame controller status */ +#define ETH_MACDBGR_MTFCS_MASK (3 << ETH_MACDBGR_MTFCS_SHIFT) +# define ETH_MACDBGR_MTFCS_IDLE (0 << ETH_MACDBGR_MTFCS_SHIFT) /* 00: Idle */ +# define ETH_MACDBGR_MTFCS_WAITING (1 << ETH_MACDBGR_MTFCS_SHIFT) /* 01: Waiting for Status of previous frame or IFG/backoff period to be over */ +# define ETH_MACDBGR_MTFCS_PAUSE (2 << ETH_MACDBGR_MTFCS_SHIFT) /* 10: Generating and transmitting a Pause control frame */ +# define ETH_MACDBGR_MTFCS_FRAME (3 << ETH_MACDBGR_MTFCS_SHIFT) /* 11: Transferring input frame for transmission */ +#define ETH_MACDBGR_MTP (1 << 19) /* Bit 19: MAC transmitter in pause */ +#define ETH_MACDBGR_TFRS_SHIFT (20) /* Bits 20-21: Tx FIFO read status */ +#define ETH_MACDBGR_TFRS_MASK (3 << ETH_MACDBGR_TFRS_SHIFT) +# define ETH_MACDBGR_TFRS_IDLE (0 << ETH_MACDBGR_TFRS_SHIFT) /* 00: Idle state */ +# define ETH_MACDBGR_TFRS_READ (1 << ETH_MACDBGR_TFRS_SHIFT) /* 01: Read state */ +# define ETH_MACDBGR_TFRS_WAITING (2 << ETH_MACDBGR_TFRS_SHIFT) /* 10: Waiting for TxStatus from MAC transmitter */ +# define ETH_MACDBGR_TFRS_WRITING (3 << ETH_MACDBGR_TFRS_SHIFT) /* 11: Writing the received TxStatus or flushing the TxFIFO */ +#define ETH_MACDBGR_TFWA (1 << 22) /* Bit 22: Tx FIFO write active */ +#define ETH_MACDBGR_TFNE (1 << 24) /* Bit 24: Tx FIFO not empty */ +#define ETH_MACDBGR_TFF (1 << 25) /* Bit 25: Tx FIFO full */ + +/* Ethernet MAC interrupt status register */ + +#define ETH_MACSR_PMTS (1 << 3) /* Bit 3: PMT status */ +#define ETH_MACSR_MMCS (1 << 4) /* Bit 4: MMC status */ +#define ETH_MACSR_MMCRS (1 << 5) /* Bit 5: MMC receive status */ +#define ETH_MACSR_MMCTS (1 << 6) /* Bit 6: MMC transmit status */ +#define ETH_MACSR_TSTS (1 << 9) /* Bit 9: Time stamp trigger status */ + +/* Ethernet MAC interrupt mask register */ + +#define ETH_MACIMR_PMTIM (1 << 3) /* Bit 3: PMT interrupt mask */ +#define ETH_MACIMR_TSTIM (1 << 9) /* Bit 9: Time stamp trigger interrupt mask */ +#define ETH_MACIMR_ALLINTS (ETH_MACIMR_PMTIM|ETH_MACIMR_TSTIM) + +/* Ethernet MAC address 0 high register */ + +#define ETH_MACA0HR_MACA0H_SHIFT (0) /* Bits 0-15: MAC address0 high [47:32] */ +#define ETH_MACA0HR_MACA0H_MASK (0xffff << ETH_MACA0HR_MACA0H_SHIFT) +#define ETH_MACA0HR_MO (1 << 31) /* Bit 31:Always */ + +/* Ethernet MAC address 0 low register (MAC address0 low [31:0]) */ + +/* Ethernet MAC address 1 high register */ + +#define ETH_MACA1HR_MACA1H_SHIFT (0) /* Bits 0-15: MAC address1 high [47:32] */ +#define ETH_MACA1HR_MACA1H_MASK (0xffff << ETH_MACA1HR_MACA1H_SHIFT) +#define ETH_MACA1HR_MBC_SHIFT (24) /* Bits 24-29: Mask byte control */ +#define ETH_MACA1HR_MBC_MASK (0x3f << ETH_MACA1HR_MBC_SHIFT) +# define ETH_MACA1HR_MBC_40_47 (0x20 << ETH_MACA1HR_MBC_SHIFT) /* Bit 29: ETH_MACA1HR [8-15] */ +# define ETH_MACA1HR_MBC_32_39 (0x10 << ETH_MACA1HR_MBC_SHIFT) /* Bit 28: ETH_MACA1HR [0-7] */ +# define ETH_MACA1HR_MBC_24_31 (0x08 << ETH_MACA1HR_MBC_SHIFT) /* Bit 27: ETH_MACA1LR [24-31] */ +# define ETH_MACA1HR_MBC_16_23 (0x04 << ETH_MACA1HR_MBC_SHIFT) /* Bit 26: ETH_MACA1LR [16-23] */ +# define ETH_MACA1HR_MBC_8_15 (0x02 << ETH_MACA1HR_MBC_SHIFT) /* Bit 25: ETH_MACA1LR [8-15] */ +# define ETH_MACA1HR_MBC_0_7 (0x01 << ETH_MACA1HR_MBC_SHIFT) /* Bit 24: ETH_MACA1LR [0-7] */ +#define ETH_MACA1HR_SA (1 << 30) /* Bit 30: Source address */ +#define ETH_MACA1HR_AE (1 << 31) /* Bit 31: Address enable */ + +/* Ethernet MAC address1 low register (MAC address1 low [31:0]) */ + +/* Ethernet MAC address 2 high register */ + +#define ETH_MACA2HR_MACA2H_SHIFT (0) /* Bits 0-15: MAC address2 high [47:32] */ +#define ETH_MACA2HR_MACA2H_MASK (0xffff << ETH_MACA2HR_MACA2H_SHIFT) +#define ETH_MACA2HR_MBC_SHIFT (24) /* Bits 24-29: Mask byte control */ +#define ETH_MACA2HR_MBC_MASK (0x3f << ETH_MACA2HR_MBC_SHIFT) +# define ETH_MACA2HR_MBC_40_47 (0x20 << ETH_MACA2HR_MBC_SHIFT) /* Bit 29: ETH_MACA2HR [8-15] */ +# define ETH_MACA2HR_MBC_32_39 (0x10 << ETH_MACA2HR_MBC_SHIFT) /* Bit 28: ETH_MACA2HR [0-7] */ +# define ETH_MACA2HR_MBC_24_31 (0x08 << ETH_MACA2HR_MBC_SHIFT) /* Bit 27: ETH_MACA2LR [24-31] */ +# define ETH_MACA2HR_MBC_16_23 (0x04 << ETH_MACA2HR_MBC_SHIFT) /* Bit 26: ETH_MACA2LR [16-23] */ +# define ETH_MACA2HR_MBC_8_15 (0x02 << ETH_MACA2HR_MBC_SHIFT) /* Bit 25: ETH_MACA2LR [8-15] */ +# define ETH_MACA2HR_MBC_0_7 (0x01 << ETH_MACA2HR_MBC_SHIFT) /* Bit 24: ETH_MACA2LR [0-7] */ +#define ETH_MACA2HR_SA (1 << 30) /* Bit 30: Source address */ +#define ETH_MACA2HR_AE (1 << 31) /* Bit 31: Address enable */ + +/* Ethernet MAC address 2 low register (MAC address2 low [31:0]) */ + +/* Ethernet MAC address 3 high register */ + +#define ETH_MACA3HR_MACA3H_SHIFT (0) /* Bits 0-15: MAC address3 high [47:32] */ +#define ETH_MACA3HR_MACA3H_MASK (0xffff << ETH_MACA3HR_MACA3H_SHIFT) +#define ETH_MACA3HR_MBC_SHIFT (24) /* Bits 24-29: Mask byte control */ +#define ETH_MACA3HR_MBC_MASK (0x3f << ETH_MACA3HR_MBC_SHIFT) +# define ETH_MACA3HR_MBC_40_47 (0x20 << ETH_MACA3HR_MBC_SHIFT) /* Bit 29: ETH_MACA3HR [8-15] */ +# define ETH_MACA3HR_MBC_32_39 (0x10 << ETH_MACA3HR_MBC_SHIFT) /* Bit 28: ETH_MACA3HR [0-7] */ +# define ETH_MACA3HR_MBC_24_31 (0x08 << ETH_MACA3HR_MBC_SHIFT) /* Bit 27: ETH_MACA3LR [24-31] */ +# define ETH_MACA3HR_MBC_16_23 (0x04 << ETH_MACA3HR_MBC_SHIFT) /* Bit 26: ETH_MACA3LR [16-23] */ +# define ETH_MACA3HR_MBC_8_15 (0x02 << ETH_MACA3HR_MBC_SHIFT) /* Bit 25: ETH_MACA3LR [8-15] */ +# define ETH_MACA3HR_MBC_0_7 (0x01 << ETH_MACA3HR_MBC_SHIFT) /* Bit 24: ETH_MACA3LR [0-7] */ +#define ETH_MACA3HR_SA (1 << 30) /* Bit 30: Source address */ +#define ETH_MACA3HR_AE (1 << 31) /* Bit 31: Address enable */ + +/* Ethernet MAC address 3 low register (MAC address3 low [31:0]) */ + +/* MMC Registers */ + +/* Ethernet MMC control register */ + +#define ETH_MMCCR_CR (1 << 0) /* Bit 0: Counter reset */ +#define ETH_MMCCR_CSR (1 << 1) /* Bit 1: Counter stop rollover */ +#define ETH_MMCCR_ROR (1 << 2) /* Bit 2: Reset on read */ +#define ETH_MMCCR_MCF (1 << 3) /* Bit 3: MMC counter freeze */ +#define ETH_MMCCR_MCP (1 << 4) /* Bit 4: MMC counter preset */ +#define ETH_MMCCR_MCFHP (1 << 5) /* Bit 5: MMC counter Full-Half preset */ + +/* Ethernet MMC receive interrupt and interrupt mask registers */ + +#define ETH_MMCRI_RFCE (1 << 5) /* Bit 5: Received frame CRC error */ +#define ETH_MMCRI_RFAE (1 << 6) /* Bit 6: Received frames alignment error */ +#define ETH_MMCRI_RGUF (1 << 17) /* Bit 17: Received good unicast frames */ + +/* Ethernet MMC transmit interrupt and interrupt mask register */ + +#define ETH_MMCTI_TGFSC (1 << 14) /* Bit 14: Transmitted good frames single collision */ +#define ETH_MMCTI_TGFMSC (1 << 15) /* Bit 15: Transmitted good frames more single collision */ +#define ETH_MMCTI_TGF (1 << 21) /* Bit 21: Transmitted good frames */ + +/* 32-bit counters: + * + * Ethernet MMC transmitted good frames counter register (single collision) + * Ethernet MMC transmitted good frames counter register (multiple-collision) + * Ethernet MMC transmitted good frames counter register + * Ethernet MMC received frames with CRC error counter register + * Ethernet MMC received frames with alignment error counter + * MMC received good unicast frames counter register + */ + +/* IEEE 1588 time stamp registers */ + +/* Ethernet PTP time stamp control register */ + +#define ETH_PTPTSCR_TSE (1 << 0) /* Bit 0: Time stamp enable */ +#define ETH_PTPTSCR_TSFCU (1 << 1) /* Bit 1: Time stamp fine or coarse update */ +#define ETH_PTPTSCR_TSSTI (1 << 2) /* Bit 2: Time stamp system time initialize */ +#define ETH_PTPTSCR_TSSTU (1 << 3) /* Bit 3: Time stamp system time update */ +#define ETH_PTPTSCR_TSITE (1 << 4) /* Bit 4: Time stamp interrupt trigger enable */ +#define ETH_PTPTSCR_TSARU (1 << 5) /* Bit 5: Time stamp addend register update */ +#define ETH_PTPTSCR_TSSARFE (1 << 8) /* Bit 8: Time stamp snapshot for all received frames enable */ +#define ETH_PTPTSCR_TSSSR (1 << 9) /* Bit 9: Time stamp subsecond rollover: digital or binary rollover control */ +#define ETH_PTPTSCR_TSPTPPSV2E (1 << 10) /* Bit 10: Time stamp PTP packet snooping for version2 format enable */ +#define ETH_PTPTSCR_TSSPTPOEFE (1 << 11) /* Bit 11: Time stamp snapshot for PTP over ethernet frames enable */ +#define ETH_PTPTSCR_TSSIPV6FE (1 << 12) /* Bit 12: Time stamp snapshot for IPv6 frames enable */ +#define ETH_PTPTSCR_TSSIPV4FE (1 << 13) /* Bit 13: Time stamp snapshot for IPv4 frames enable */ +#define ETH_PTPTSCR_TSSEME (1 << 14) /* Bit 14: Time stamp snapshot for event message enable */ +#define ETH_PTPTSCR_TSSMRME (1 << 15) /* Bit 15: Time stamp snapshot for message relevant to master enable */ +#define ETH_PTPTSCR_TSCNT_SHIFT (16) /* Bits 16-17: Time stamp clock node type */ +#define ETH_PTPTSCR_TSCNT_MASK (3 << ETH_PTPTSCR_TSCNT_SHIFT) +# define ETH_PTPTSCR_TSCNT_ORDINARY (0 << ETH_PTPTSCR_TSCNT_SHIFT) /* 00: Ordinary clock */ +# define ETH_PTPTSCR_TSCNT_BOUNDARY (1 << ETH_PTPTSCR_TSCNT_SHIFT) /* 01: Boundary clock */ +# define ETH_PTPTSCR_TSCNT_E2E (2 << ETH_PTPTSCR_TSCNT_SHIFT) /* 10: End-to-end transparent clock */ +# define ETH_PTPTSCR_TSCNT_P2P (3 << ETH_PTPTSCR_TSCNT_SHIFT) /* 11: Peer-to-peer transparent clock */ +#define ETH_PTPTSCR_TSPFFMAE (1 << 18) /* Bit 18: Time stamp PTP frame filtering MAC address enable */ + +/* Ethernet PTP subsecond increment register */ + +#define ETH_PTPSSIR_MASK (0xff) + +/* Ethernet PTP time stamp high register (32-bit) */ + +/* Ethernet PTP time stamp low register */ + +#define ETH_PTPTSLR_STPNS (1 << 31) /* Bit 31: System time positive or negative sign */ +#define ETH_PTPTSLR_MASK (0x7fffffff) /* Bits 0-30: System time subseconds */ + +/* Ethernet PTP time stamp high update register (32-bit) */ + +/* Ethernet PTP time stamp low update register */ + +#define ETH_PTPTSLU_TSUPNS (1 << 31) /* Bit 31: System time positive or negative sign */ +#define ETH_PTPTSLU_MASK (0x7fffffff) /* Bits 0-30: Time stamp update subsecond */ + +/* Ethernet PTP time stamp addend register (32-bit) */ +/* Ethernet PTP target time high register (32-bit) */ +/* Ethernet PTP target time low register (32-bit) */ + +/* Ethernet PTP time stamp status register */ + +#define ETH_PTPTSSR_TSSO (1 << 0) /* Bit 0: Time stamp second overflow */ +#define ETH_PTPTSSR_TSTTR (1 << 1) /* Bit 1: Time stamp target time reached */ + +/* Ethernet PTP PPS control register */ + +#define ETH_PTPPPSCR_PPSFREQ_SHIFT (0) /* Bits 0-3: PPS frequency selection */ +#define ETH_PTPPPSCR_PPSFREQ_MASK (15 << ETH_PTPPPSCR_PPSFREQ_SHIFT) +# define ETH_PTPPPSCR_PPSFREQ_1HZ (0 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 1 Hz with pulse width of 125/100 ms for binary/digital rollover */ +# define ETH_PTPPPSCR_PPSFREQ_2HZ (1 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 2 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_4HZ (2 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 4 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_8HZ (3 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 8 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_16HZ (4 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 16 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_32HZ (5 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 32 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_64HZ (6 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 64 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_128HZ (7 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 128 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_256HZ (8 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 256 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_512HZ (9 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 512 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_1KHZ (10 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 1024 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_2KHZ (11 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 2048 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_4KHZ (12 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 4096 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_8KHZ (13 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 8192 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_16KHZ (14 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 16384 Hz with 50% duty cycle */ +# define ETH_PTPPPSCR_PPSFREQ_32KHZ (15 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 32768 Hz with 50% duty cycle */ + +/* DMA Registers */ + +/* Ethernet DMA bus mode register */ + +#define ETH_DMABMR_SR (1 << 0) /* Bit 0: Software reset */ +#define ETH_DMABMR_DA (1 << 1) /* Bit 1: DMA Arbitration */ +#define ETH_DMABMR_DSL_SHIFT (2) /* Bits 2-6: Descriptor skip length */ +#define ETH_DMABMR_DSL_MASK (31 << ETH_DMABMR_DSL_SHIFT) +# define ETH_DMABMR_DSL(n) ((n) << ETH_DMABMR_DSL_SHIFT) +#define ETH_DMABMR_EDFE (1 << 7) /* Bit 7: Enhanced descriptor format enable */ +#define ETH_DMABMR_PBL_SHIFT (8) /* Bits 8-13: Programmable burst length */ +# define ETH_DMABMR_PBL(n) ((n) << ETH_DMABMR_PBL_SHIFT) /* n=1, 2, 4, 8, 16, 32 */ +#define ETH_DMABMR_PBL_MASK (0x3f << ETH_DMABMR_PBL_SHIFT) +#define ETH_DMABMR_RTPR_SHIFT (14) /* Bits 14-15: Rx Tx priority ratio */ +#define ETH_DMABMR_RTPR_MASK (3 << ETH_DMABMR_RTPR_SHIFT) +# define ETH_DMABMR_RTPR_1TO1 (0 << ETH_DMABMR_RTPR_SHIFT) /* 00: 1:1 */ +# define ETH_DMABMR_RTPR_2TO1 (1 << ETH_DMABMR_RTPR_SHIFT) /* 01: 2:1 */ +# define ETH_DMABMR_RTPR_3TO1 (2 << ETH_DMABMR_RTPR_SHIFT) /* 10: 3:1 */ +# define ETH_DMABMR_RTPR_4TO1 (3 << ETH_DMABMR_RTPR_SHIFT) /* 11: 4:1 */ +#define ETH_DMABMR_FB (1 << 16) /* Bit 16: Fixed burst */ +#define ETH_DMABMR_RDP_SHIFT (17) /* Bits 17-22: Rx DMA PBL */ +#define ETH_DMABMR_RDP_MASK (0x3f << ETH_DMABMR_RDP_SHIFT) +# define ETH_DMABMR_RDP(n) ((n) << ETH_DMABMR_RDP_SHIFT) /* n=1, 2, 4, 8, 16, 32 */ +#define ETH_DMABMR_USP (1 << 23) /* Bit 23: Use separate PBL */ +#define ETH_DMABMR_FPM (1 << 24) /* Bit 24: 4xPBL mode */ +#define ETH_DMABMR_AAB (1 << 25) /* Bit 25: Address-aligned beats */ +#define ETH_DMABMR_MB (1 << 26) /* Bit 26: Mixed burst */ + +/* Ethernet DMA transmit poll demand register (32-bit) */ +/* Ethernet DMA receive poll demand register (32-bit) */ +/* Ethernet DMA receive descriptor list address register (32-bit address) */ +/* Ethernet DMA transmit descriptor list address register (32-bit address) */ + +/* Interrupt bit definitions common between the DMA status register (DMASR) and + * the DMA interrupt enable register (DMAIER). + */ + +#define ETH_DMAINT_TI (1 << 0) /* Bit 0: Transmit interrupt */ +#define ETH_DMAINT_TPSI (1 << 1) /* Bit 1: Transmit process stopped interrupt */ +#define ETH_DMAINT_TBUI (1 << 2) /* Bit 2: Transmit buffer unavailable interrupt */ +#define ETH_DMAINT_TJTI (1 << 3) /* Bit 3: Transmit jabber timeout interrupt */ +#define ETH_DMAINT_ROI (1 << 4) /* Bit 4: Overflow interrupt */ +#define ETH_DMAINT_TUI (1 << 5) /* Bit 5: Underflow interrupt */ +#define ETH_DMAINT_RI (1 << 6) /* Bit 6: Receive interrupt */ +#define ETH_DMAINT_RBUI (1 << 7) /* Bit 7: Receive buffer unavailable interrupt */ +#define ETH_DMAINT_RPSI (1 << 8) /* Bit 8: Receive process stopped interrupt */ +#define ETH_DMAINT_RWTI (1 << 9) /* Bit 9: Receive watchdog timeout interrupt */ +#define ETH_DMAINT_ETI (1 << 10) /* Bit 10: Early transmit interrupt */ +#define ETH_DMAINT_FBEI (1 << 13) /* Bit 13: Fatal bus error interrupt */ +#define ETH_DMAINT_ERI (1 << 14) /* Bit 14: Early receive interrupt */ +#define ETH_DMAINT_AIS (1 << 15) /* Bit 15: Abnormal interrupt summary */ +#define ETH_DMAINT_NIS (1 << 16) /* Bit 16: Normal interrupt summary */ + +/* Ethernet DMA status register (in addition to the interrupt bits above */ + +#define ETH_DMASR_RPS_SHIFT (17) /* Bits 17-19: Receive process state */ +#define ETH_DMASR_RPS_MASK (7 << ETH_DMASR_RPS_SHIFT) +# define ETH_DMASR_RPS_STOPPED (0 << ETH_DMASR_RPS_SHIFT) /* 000: Stopped: Reset or Stop Receive Command issued */ +# define ETH_DMASR_RPS_RXDESC (1 << ETH_DMASR_RPS_SHIFT) /* 001: Running: Fetching receive transfer descriptor */ +# define ETH_DMASR_RPS_WAITING (3 << ETH_DMASR_RPS_SHIFT) /* 011: Running: Waiting for receive packet */ +# define ETH_DMASR_RPS_SUSPENDED (4 << ETH_DMASR_RPS_SHIFT) /* 100: Suspended: Receive descriptor unavailable */ +# define ETH_DMASR_RPS_CLOSING (5 << ETH_DMASR_RPS_SHIFT) /* 101: Running: Closing receive descriptor */ +# define ETH_DMASR_RPS_TRANSFER (6 << ETH_DMASR_RPS_SHIFT) /* 111: Running: Transferring the receive data to memory */ +#define ETH_DMASR_TPS_SHIFT (20) /* Bits 20-22: Transmit process state */ +#define ETH_DMASR_TPS_MASK (7 << ETH_DMASR_TPS_SHIFT) +# define ETH_DMASR_TPS_STOPPED (0 << ETH_DMASR_TPS_SHIFT) /* 000: Stopped; Reset or Stop Transmit Command issued */ +# define ETH_DMASR_TPS_TXDESC (1 << ETH_DMASR_TPS_SHIFT) /* 001: Running; Fetching transmit transfer descriptor */ +# define ETH_DMASR_TPS_WAITING (2 << ETH_DMASR_TPS_SHIFT) /* 010: Running; Waiting for status */ +# define ETH_DMASR_TPS_TRANSFER (3 << ETH_DMASR_TPS_SHIFT) /* 011: Running; Reading data and queuing to transmit (TxFIFO) */ +# define ETH_DMASR_TPS_SUSPENDED (6 << ETH_DMASR_TPS_SHIFT) /* 110: Suspended; Transmit descriptor unavailable or buffer underflow */ +# define ETH_DMASR_TPS_CLOSING (7 << ETH_DMASR_TPS_SHIFT) /* 111: Running; Closing transmit descriptor */ +#define ETH_DMASR_EBS_SHIFT (23) /* Bits 23-25: Error bits status */ +#define ETH_DMASR_EBS_MASK (7 << ETH_DMASR_EBS_SHIFT) +#define ETH_DMASR_EBS_TXDMS (1 << ETH_DMASR_EBS_SHIFT) /* Bit 23 1 Error during data transfer by TxDMA */ +#define ETH_DMASR_EBS_READ (2 << ETH_DMASR_EBS_SHIFT) /* Bit 24 1 Error during read transfer */ +#define ETH_DMASR_EBS_DESC (4 << ETH_DMASR_EBS_SHIFT) /* Bit 25 1 Error during descriptor access */ +#define ETH_DMASR_MMCS (1 << 27) /* Bit 27: MMC status */ +#define ETH_DMASR_PMTS (1 << 28) /* Bit 28: PMT status */ +#define ETH_DMASR_TSTS (1 << 29) /* Bit 29: Time stamp trigger status */ + +/* Ethernet DMA operation mode register */ + +#define ETH_DMAOMR_SR (1 << 1) /* Bit 1: Start/stop receive */ +#define ETH_DMAOMR_OSF (1 << 2) /* Bit 2: Operate on second frame */ +#define ETH_DMAOMR_RTC_SHIFT (3) /* Bits 3-4: Receive threshold control */ +#define ETH_DMAOMR_RTC_MASK (3 << ETH_DMAOMR_RTC_SHIFT) +# define ETH_DMAOMR_RTC_64 (0 << ETH_DMAOMR_RTC_SHIFT) +# define ETH_DMAOMR_RTC_32 (1 << ETH_DMAOMR_RTC_SHIFT) +# define ETH_DMAOMR_RTC_96 (2 << ETH_DMAOMR_RTC_SHIFT) +# define ETH_DMAOMR_RTC_128 (3 << ETH_DMAOMR_RTC_SHIFT) +#define ETH_DMAOMR_FUGF (1 << 6) /* Bit 6: Forward undersized good frames */ +#define ETH_DMAOMR_FEF (1 << 7) /* Bit 7: Forward error frames */ +#define ETH_DMAOMR_ST (1 << 13) /* Bit 13: Start/stop transmission */ +#define ETH_DMAOMR_TTC_SHIFT (14) /* Bits 14-16: Transmit threshold control */ +#define ETH_DMAOMR_TTC_MASK (7 << ETH_DMAOMR_TTC_SHIFT) +# define ETH_DMAOMR_TTC_64 (0 << ETH_DMAOMR_TTC_SHIFT) +# define ETH_DMAOMR_TTC_128 (1 << ETH_DMAOMR_TTC_SHIFT) +# define ETH_DMAOMR_TTC_192 (2 << ETH_DMAOMR_TTC_SHIFT) +# define ETH_DMAOMR_TTC_256 (3 << ETH_DMAOMR_TTC_SHIFT) +# define ETH_DMAOMR_TTC_40 (4 << ETH_DMAOMR_TTC_SHIFT) +# define ETH_DMAOMR_TTC_32 (5 << ETH_DMAOMR_TTC_SHIFT) +# define ETH_DMAOMR_TTC_24 (6 << ETH_DMAOMR_TTC_SHIFT) +# define ETH_DMAOMR_TTC_16 (7 << ETH_DMAOMR_TTC_SHIFT) +#define ETH_DMAOMR_FTF (1 << 20) /* Bit 20: Flush transmit FIFO */ +#define ETH_DMAOMR_TSF (1 << 21) /* Bit 21: Transmit store and forward */ +#define ETH_DMAOMR_DFRF (1 << 24) /* Bit 24: Disable flushing of received frames */ +#define ETH_DMAOMR_RSF (1 << 25) /* Bit 25: Receive store and forward */ +#define ETH_DMAOMR_DTCEFD (1 << 26) /* Bit 26: Dropping of TCP/IP checksum error frames disable */ + +/* Ethernet DMA missed frame and buffer overflow counter register */ + +#define ETH_DMAMFBOC_MFC_SHIFT (0) /* Bits 0-15: Missed frames by the controller */ +#define ETH_DMAMFBOC_MFC_MASK (0xffff << ETH_DMAMFBOC_MFC_SHIFT) +#define ETH_DMAMFBOC_OMFC (1 << 16) /* Bit 16: Overflow bit for missed frame counter */ +#define ETH_DMAMFBOC_MFA_SHIFT (17) /* Bits 17-27: Missed frames by the application */ +#define ETH_DMAMFBOC_MFA_MASK (0x7ff << ETH_DMAMFBOC_MFA_SHIFT) +#define ETH_DMAMFBOC_OFOC (1 << 28) /* Bit 28: Overflow bit for FIFO overflow counter */ + +/* Ethernet DMA receive status watchdog timer register */ + +#define ETH_DMARSWTR_MASK (0xff) + +/* Ethernet DMA current host transmit descriptor register (32-bit address) */ +/* Ethernet DMA current host receive descriptor register (32-bit address) */ +/* Ethernet DMA current host transmit buffer address register (32-bit address) */ +/* Ethernet DMA current host receive buffer address register (32-bit address) */ + +/* DMA Descriptors **********************************************************************************/ +/* TDES0: Transmit descriptor Word0 */ + +#define ETH_TDES0_DB (1 << 0) /* Bit 0: Deferred bit */ +#define ETH_TDES0_UF (1 << 1) /* Bit 1: Underflow error */ +#define ETH_TDES0_ED (1 << 2) /* Bit 2: Excessive deferral */ +#define ETH_TDES0_CC_SHIFT (3) /* Bits 3-6: Collision count */ +#define ETH_TDES0_CC_MASK (15 << ETH_TDES0_CC_SHIFT) +#define ETH_TDES0_VF (1 << 7) /* Bit 7: VLAN frame */ +#define ETH_TDES0_EC (1 << 8) /* Bit 8: Excessive collision */ +#define ETH_TDES0_LCO (1 << 9) /* Bit 9: Late collision */ +#define ETH_TDES0_NC (1 << 10) /* Bit 10: No carrier */ +#define ETH_TDES0_LCA (1 << 11) /* Bit 11: Loss of carrier */ +#define ETH_TDES0_IPE (1 << 12) /* Bit 12: IP payload error */ +#define ETH_TDES0_FF (1 << 13) /* Bit 13: Frame flushed */ +#define ETH_TDES0_JT (1 << 14) /* Bit 14: Jabber timeout */ +#define ETH_TDES0_ES (1 << 15) /* Bit 15: Error summary */ +#define ETH_TDES0_IHE (1 << 16) /* Bit 16: IP header error */ +#define ETH_TDES0_TTSS (1 << 17) /* Bit 17: Transmit time stamp status */ +#define ETH_TDES0_TCH (1 << 20) /* Bit 20: Second address chained */ +#define ETH_TDES0_TER (1 << 21) /* Bit 21: Transmit end of ring */ +#define ETH_TDES0_CIC_SHIFT (22) /* Bits 22-23: Checksum insertion control */ +#define ETH_TDES0_CIC_MASK (3 << ETH_TDES0_CIC_SHIFT) +# define ETH_TDES0_CIC_DISABLED (0 << ETH_TDES0_CIC_SHIFT) /* Checksum disabled */ +# define ETH_TDES0_CIC_IH (1 << ETH_TDES0_CIC_SHIFT) /* IP header checksum enabled */ +# define ETH_TDES0_CIC_IHPL (2 << ETH_TDES0_CIC_SHIFT) /* IP header and payload checksum enabled */ +# define ETH_TDES0_CIC_ALL (3 << ETH_TDES0_CIC_SHIFT) /* IP Header, payload, and pseudo-header checksum enabled */ +#define ETH_TDES0_TTSE (1 << 25) /* Bit 25: Transmit time stamp enable */ +#define ETH_TDES0_DP (1 << 26) /* Bit 26: Disable pad */ +#define ETH_TDES0_DC (1 << 27) /* Bit 27: Disable CRC */ +#define ETH_TDES0_FS (1 << 28) /* Bit 28: First segment */ +#define ETH_TDES0_LS (1 << 29) /* Bit 29: Last segment */ +#define ETH_TDES0_IC (1 << 30) /* Bit 30: Interrupt on completion */ +#define ETH_TDES0_OWN (1 << 31) /* Bit 31: Own bit */ + +/* TDES1: Transmit descriptor Word1 */ + +#define ETH_TDES1_TBS1_SHIFT (0) /* Bits 0-12: Transmit buffer 1 size */ +#define ETH_TDES1_TBS1_MASK (0x1fff << ETH_TDES1_TBS1_SHIFT) +#define ETH_TDES1_TBS2_SHIFT (16) /* Bits 16-28: Transmit buffer 2 size */ +#define ETH_TDES1_TBS2_MASK (0x1fff << ETH_TDES1_TBS2_SHIFT) + +/* TDES2: Transmit descriptor Word2 (32-bit address) */ +/* TDES3: Transmit descriptor Word3 (32-bit address) */ +/* TDES6: Transmit descriptor Word6 (32-bit time stamp) */ +/* TDES7: Transmit descriptor Word7 (32-bit time stamp) */ + +/* RDES0: Receive descriptor Word0 */ + +#define ETH_RDES0_PCE (1 << 0) /* Bit 0: Payload checksum error */ +#define ETH_RDES0_ESA (1 << 0) /* Bit 0: Extended status available */ +#define ETH_RDES0_CE (1 << 1) /* Bit 1: CRC error */ +#define ETH_RDES0_DBE (1 << 2) /* Bit 2: Dribble bit error */ +#define ETH_RDES0_RE (1 << 3) /* Bit 3: Receive error */ +#define ETH_RDES0_RWT (1 << 4) /* Bit 4: Receive watchdog timeout */ +#define ETH_RDES0_FT (1 << 5) /* Bit 5: Frame type */ +#define ETH_RDES0_LCO (1 << 6) /* Bit 6: Late collision */ +#define ETH_RDES0_TSV (1 << 7) /* Bit 7: Time stamp valid */ +#define ETH_RDES0_IPHCE (1 << 7) /* Bit 7: IPv header checksum error */ +#define ETH_RDES0_LS (1 << 8) /* Bit 8: Last descriptor */ +#define ETH_RDES0_FS (1 << 9) /* Bit 9: First descriptor */ +#define ETH_RDES0_VLAN (1 << 10) /* Bit 10: VLAN tag */ +#define ETH_RDES0_OE (1 << 11) /* Bit 11: Overflow error */ +#define ETH_RDES0_LE (1 << 12) /* Bit 12: Length error */ +#define ETH_RDES0_SAF (1 << 13) /* Bit 13: Source address filter fail */ +#define ETH_RDES0_DE (1 << 14) /* Bit 14: Descriptor error */ +#define ETH_RDES0_ES (1 << 15) /* Bit 15: Error summary */ +#define ETH_RDES0_FL_SHIFT (16) /* Bits 16-29: Frame length */ +#define ETH_RDES0_FL_MASK (0x3fff << ETH_RDES0_FL_SHIFT) +#define ETH_RDES0_AFM (1 << 30) /* Bit 30: Destination address filter fail */ +#define ETH_RDES0_OWN (1 << 31) /* Bit 31: Own bit */ + +/* RDES1: Receive descriptor Word1 */ + +#define ETH_RDES1_RBS1_SHIFT (0) /* Bits 0-12: Receive buffer 1 size */ +#define ETH_RDES1_RBS1_MASK (0x1fff << ETH_RDES1_RBS1_SHIFT) +#define ETH_RDES1_RCH (1 << 14) /* Bit 14: Second address chained */ +#define ETH_RDES1_RER (1 << 15) /* Bit 15: Receive end of ring */ +#define ETH_RDES1_RBS2_SHIFT (16) /* Bits 16-28: Receive buffer 2 size */ +#define ETH_RDES1_RBS2_MASK (0x1fff << ETH_RDES1_RBS2_SHIFT) +#define ETH_RDES1_DIC (1 << 31) /* Bit 31: Disable interrupt on completion */ + +/* RDES2: Receive descriptor Word2 (32-bit address) */ +/* RDES3: Receive descriptor Word3 (32-bit address) */ + +/* RDES4: Receive descriptor Word4 */ + +#define ETH_RDES4_IPPT_SHIFT (0) /* Bits 0-2: IP payload type */ +#define ETH_RDES4_IPPT_MASK (7 << ETH_RDES4_IPPT_SHIFT) +# define ETH_RDES4_IPPT_UDP (1 << ETH_RDES4_IPPT_SHIFT) /* UDP payload in IP datagram */ +# define ETH_RDES4_IPPT_TCP (2 << ETH_RDES4_IPPT_SHIFT) /* TCP payload in IP datagram */ +# define ETH_RDES4_IPPT_ICMP (3 << ETH_RDES4_IPPT_SHIFT) /* ICMP payload in IP datagram */ +#define ETH_RDES4_IPHE (1 << 3) /* Bit 3: IP header error */ +#define ETH_RDES4_IPPE (1 << 4) /* Bit 4: IP payload error */ +#define ETH_RDES4_IPCB (1 << 5) /* Bit 5: IP checksum bypassed */ +#define ETH_RDES4_IPV4PR (1 << 6) /* Bit 6: IPv4 packet received */ +#define ETH_RDES4_IPV6PR (1 << 7) /* Bit 7: IPv6 packet received */ +#define ETH_RDES4_PMT_SHIFT (8) /* Bits 8-11: PTP message type */ +#define ETH_RDES4_PMT_MASK (15 << ETH_RDES4_PMT_SHIFT) +# define ETH_RDES4_PMT_NONE (0 << ETH_RDES4_PMT_SHIFT) /* No PTP message received */ +# define ETH_RDES4_PMT_SYNC (1 << ETH_RDES4_PMT_SHIFT) /* SYNC (all clock types) */ +# define ETH_RDES4_PMT_FOLLOWUP (2 << ETH_RDES4_PMT_SHIFT) /* Follow_Up (all clock types) */ +# define ETH_RDES4_PMT_DELAYREQ (3 << ETH_RDES4_PMT_SHIFT) /* Delay_Req (all clock types) */ +# define ETH_RDES4_PMT_DELAYRESP (4 << ETH_RDES4_PMT_SHIFT) /* Delay_Resp (all clock types) */ +# define ETH_RDES4_PMT_PDELREQAM (5 << ETH_RDES4_PMT_SHIFT) /* Pdelay_Req (in peer-to-peer + * transparent clock) or Announce (in + * ordinary or boundary clock) */ +# define ETH_RDES4_PMT_PDELREQMM (6 << ETH_RDES4_PMT_SHIFT) /* Pdelay_Resp (in peer-to-peer + * transparent clock) or Management (in + * ordinary or boundary clock) */ +# define ETH_RDES4_PMT_PDELREQFUS (7 << ETH_RDES4_PMT_SHIFT) /* Pdelay_Resp_Follow_Up (in + * peer-to-peer transparent clock) or + * Signaling (for ordinary or boundary + * clock) */ +#define ETH_RDES4_PFT (1 << 12) /* Bit 12: PTP frame type */ +#define ETH_RDES4_PV (1 << 13) /* Bit 13: PTP version */ + +/* RDES5: Receive descriptor Word5 - Reserved */ +/* RDES6: Receive descriptor Word6 (32-bit time stamp) */ +/* RDES7: Receive descriptor Word7 (32-bit time stamp) */ + +/**************************************************************************************************** + * Public Types + ****************************************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Ethernet TX DMA Descriptor */ + +struct eth_txdesc_s +{ + /* Normal DMA descriptor words */ + + volatile uint32_t tdes0; /* Status */ + volatile uint32_t tdes1; /* Control and buffer1/2 lengths */ + volatile uint32_t tdes2; /* Buffer1 address pointer */ + volatile uint32_t tdes3; /* Buffer2 or next descriptor address pointer */ + + /* Enhanced DMA descriptor words with time stamp */ + +#ifdef CONFIG_STM32_ETH_ENHANCEDDESC + volatile uint32_t tdes4; /* Reserved */ + volatile uint32_t tdes5; /* Reserved */ + volatile uint32_t tdes6; /* Time Stamp Low value for transmit and receive */ + volatile uint32_t tdes7; /* Time Stamp High value for transmit and receive */ +#endif +}; + +/* Ethernet RX DMA Descriptor */ + +struct eth_rxdesc_s +{ + volatile uint32_t rdes0; /* Status */ + volatile uint32_t rdes1; /* Control and buffer1/2 lengths */ + volatile uint32_t rdes2; /* Buffer1 address pointer */ + volatile uint32_t rdes3; /* Buffer2 or next descriptor address pointer */ + + /* Enhanced DMA descriptor words with time stamp and PTP support */ + +#ifdef CONFIG_STM32_ETH_ENHANCEDDESC + volatile uint32_t rdes4; /* Extended status for PTP receive descriptor */ + volatile uint32_t rdes5; /* Reserved */ + volatile uint32_t rdes6; /* Time Stamp Low value for transmit and receive */ + volatile uint32_t rdes7; /* Time Stamp High value for transmit and receive */ +#endif +}; + +/**************************************************************************************************** + * Public Functions + ****************************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* STM32_NETHERNET > 0 */ +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_ETH_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_exti.h b/nuttx/arch/arm/src/stm32/chip/stm32_exti.h new file mode 100644 index 0000000000..82477db549 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_exti.h @@ -0,0 +1,141 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_exti.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_EXTI_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_EXTI_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include "chip.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#if defined(CONFIG_STM32_STM32F10XX) +# ifdef CONFIG_STM32_CONNECTIVITYLINE +# define STM32_NEXTI 20 +# define STM32_EXTI_MASK 0x000fffff +# else +# define STM32_NEXTI 19 +# define STM32_EXTI_MASK 0x0007ffff +# endif +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_NEXTI 23 +# define STM32_EXTI_MASK 0x007fffff +#endif + +#define STM32_EXTI_BIT(n) (1 << (n)) + +/* Register Offsets *****************************************************************/ + +#define STM32_EXTI_IMR_OFFSET 0x0000 /* Interrupt mask register */ +#define STM32_EXTI_EMR_OFFSET 0x0004 /* Event mask register */ +#define STM32_EXTI_RTSR_OFFSET 0x0008 /* Rising Trigger selection register */ +#define STM32_EXTI_FTSR_OFFSET 0x000c /* Falling Trigger selection register */ +#define STM32_EXTI_SWIER_OFFSET 0x0010 /* Software interrupt event register */ +#define STM32_EXTI_PR_OFFSET 0x0014 /* Pending register */ + +/* Register Addresses ***************************************************************/ + +#define STM32_EXTI_IMR (STM32_EXTI_BASE+STM32_EXTI_IMR_OFFSET) +#define STM32_EXTI_EMR (STM32_EXTI_BASE+STM32_EXTI_EMR_OFFSET) +#define STM32_EXTI_RTSR (STM32_EXTI_BASE+STM32_EXTI_RTSR_OFFSET) +#define STM32_EXTI_FTSR (STM32_EXTI_BASE+STM32_EXTI_FTSR_OFFSET) +#define STM32_EXTI_SWIER (STM32_EXTI_BASE+STM32_EXTI_SWIER_OFFSET) +#define STM32_EXTI_PR (STM32_EXTI_BASE+STM32_EXTI_PR_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +/* EXTI lines > 15 are associated with internal devices: */ + +#if defined(CONFIG_STM32_STM32F10XX) +# define EXTI_PVD_LINE (1 << 16) /* EXTI line 16 is connected to the PVD output */ +# define EXTI_RTC_ALARM (1 << 17) /* EXTI line 17 is connected to the RTC Alarm event */ +# define EXTI_USB_WAKEUP (1 << 18) /* EXTI line 18 is connected to the USB Wakeup event */ +# ifdef CONFIG_STM32_CONNECTIVITYLINE +# define EXTI_ETH_WAKEUP (1 << 19) /* EXTI line 19 is connected to the Ethernet Wakeup event */ +# endif +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define EXTI_PVD_LINE (1 << 16) /* EXTI line 16 is connected to the PVD output */ +# define EXTI_RTC_ALARM (1 << 17) /* EXTI line 17 is connected to the RTC Alarm event */ +# define EXTI_OTGFS_WAKEUP (1 << 18) /* EXTI line 18 is connected to the USB OTG FS Wakeup event */ +# define EXTI_ETH_WAKEUP (1 << 19) /* EXTI line 19 is connected to the Ethernet Wakeup event */ +# define EXTI_OTGHS_WAKEUP (1 << 20) /* EXTI line 20 is connected to the USB OTG HS Wakeup event */ +# define EXTI_RTC_TAMPER (1 << 21) /* EXTI line 21 is connected to the RTC Tamper and TimeStamp events */ +# define EXTI_RTC_TIMESTAMP (1 << 22) /* EXTI line 21 is connected to the RTC Tamper and TimeStamp events */ +# define EXTI_RTC_WAKEUP (1 << 23) /* EXTI line 22 is connected to the RTC Wakeup event */ +#endif + +/* Interrupt mask register */ + +#define EXTI_IMR_BIT(n) STM32_EXTI_BIT(n) /* 1=Interrupt request from line x is not masked */ +#define EXTI_IMR_SHIFT (0) /* Bits 0-X: Interrupt Mask for all lines */ +#define EXTI_IMR_MASK STM32_EXTI_MASK + +/* Event mask register */ + +#define EXTI_EMR_BIT(n) STM32_EXTI_BIT(n) /* 1=Event request from line x is not mask */ +#define EXTI_EMR_SHIFT (0) /* Bits Bits 0-X: Event Mask for all lines */ +#define EXTI_EMR_MASK STM32_EXTI_MASK + +/* Rising Trigger selection register */ + +#define EXTI_RTSR_BIT(n) STM32_EXTI_BIT(n) /* 1=Rising trigger enabled (for Event and Interrupt) for input line */ +#define EXTI_RTSR_SHIFT (0) /* Bits 0-X: Rising trigger event configuration bit for all lines */ +#define EXTI_RTSR_MASK STM32_EXTI_MASK + +/* Falling Trigger selection register */ + +#define EXTI_FTSR_BIT(n) STM32_EXTI_BIT(n) /* 1=Falling trigger enabled (for Event and Interrupt) for input line */ +#define EXTI_FTSR_SHIFT (0) /* Bits 0-X: Falling trigger event configuration bitfor all lines */ +#define EXTI_FTSR_MASK STM32_EXTI_MASK + +/* Software interrupt event register */ + +#define EXTI_SWIER_BIT(n) STM32_EXTI_BIT(n) /* 1=Sets the corresponding pending bit in EXTI_PR */ +#define EXTI_SWIER_SHIFT (0) /* Bits 0-X: Software Interrupt for all lines */ +#define EXTI_SWIER_MASK STM32_EXTI_MASK + +/* Pending register */ + +#define EXTI_IMR_BIT(n) STM32_EXTI_BIT(n) /* 1=Selected trigger request occurred */ +#define EXTI_IMR_SHIFT (0) /* Bits 0-X: Pending bit for all lines */ +#define EXTI_IMR_MASK STM32_EXTI_MASK + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_EXTI_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_flash.h b/nuttx/arch/arm/src/stm32/chip/stm32_flash.h new file mode 100644 index 0000000000..c2e4409239 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_flash.h @@ -0,0 +1,190 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_flash.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_FLASH_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_FLASH_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#if defined(CONFIG_STM32_LOWDENSITY) +# define STM32_FLASH_NPAGES 32 +# define STM32_FLASH_PAGESIZE 1024 +#elif defined(CONFIG_STM32_MEDIUMDENSITY) +# define STM32_FLASH_NPAGES 128 +# define STM32_FLASH_PAGESIZE 1024 +#elif defined(CONFIG_STM32_CONNECTIVITYLINE) +# define STM32_FLASH_NPAGES 128 +# define STM32_FLASH_PAGESIZE 2048 +#elif defined(CONFIG_STM32_HIGHDENSITY) +# define STM32_FLASH_NPAGES 256 +# define STM32_FLASH_PAGESIZE 2048 +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_FLASH_NPAGES 8 +# define STM32_FLASH_PAGESIZE (128*1024) +#endif + +#define STM32_FLASH_SIZE (STM32_FLASH_NPAGES * STM32_FLASH_PAGESIZE) + +/* Register Offsets *****************************************************************/ + +#define STM32_FLASH_ACR_OFFSET 0x0000 +#define STM32_FLASH_KEYR_OFFSET 0x0004 +#define STM32_FLASH_OPTKEYR_OFFSET 0x0008 +#define STM32_FLASH_SR_OFFSET 0x000c +#define STM32_FLASH_CR_OFFSET 0x0010 + +#if defined(CONFIG_STM32_STM32F10XX) +# define STM32_FLASH_AR_OFFSET 0x0014 +# define STM32_FLASH_OBR_OFFSET 0x001c +# define STM32_FLASH_WRPR_OFFSET 0x0020 +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_FLASH_OPTCR_OFFSET 0x0014 +#endif + +/* Register Addresses ***************************************************************/ + +#define STM32_FLASH_ACR (STM32_FLASHIF_BASE+STM32_FLASH_ACR_OFFSET) +#define STM32_FLASH_KEYR (STM32_FLASHIF_BASE+STM32_FLASH_KEYR_OFFSET) +#define STM32_FLASH_OPTKEYR (STM32_FLASHIF_BASE+STM32_FLASH_OPTKEYR_OFFSET) +#define STM32_FLASH_SR (STM32_FLASHIF_BASE+STM32_FLASH_SR_OFFSET) +#define STM32_FLASH_CR (STM32_FLASHIF_BASE+STM32_FLASH_CR_OFFSET) + +#if defined(CONFIG_STM32_STM32F10XX) +# define STM32_FLASH_AR (STM32_FLASHIF_BASE+STM32_FLASH_AR_OFFSET) +# define STM32_FLASH_OBR (STM32_FLASHIF_BASE+STM32_FLASH_OBR_OFFSET) +# define STM32_FLASH_WRPR (STM32_FLASHIF_BASE+STM32_FLASH_WRPR_OFFSET) +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_FLASH_OPTCR (STM32_FLASHIF_BASE+STM32_FLASH_OPTCR_OFFSET) +#endif + +/* Register Bitfield Definitions ****************************************************/ +/* Flash Access Control Register (ACR) */ + +#define FLASH_ACR_LATENCY_SHIFT (0) +#define FLASH_ACR_LATENCY_MASK (7 << FLASH_ACR_LATENCY_SHIFT) +# define FLASH_ACR_LATENCY(n) ((n) << FLASH_ACR_LATENCY_SHIFT) /* n wait states */ +# define FLASH_ACR_LATENCY_0 (0 << FLASH_ACR_LATENCY_SHIFT) /* 000: Zero wait states */ +# define FLASH_ACR_LATENCY_1 (1 << FLASH_ACR_LATENCY_SHIFT) /* 001: One wait state */ +# define FLASH_ACR_LATENCY_2 (2 << FLASH_ACR_LATENCY_SHIFT) /* 010: Two wait states */ +# define FLASH_ACR_LATENCY_3 (3 << FLASH_ACR_LATENCY_SHIFT) /* 011: Three wait states */ +# define FLASH_ACR_LATENCY_4 (4 << FLASH_ACR_LATENCY_SHIFT) /* 100: Four wait states */ +# define FLASH_ACR_LATENCY_5 (5 << FLASH_ACR_LATENCY_SHIFT) /* 101: Five wait states */ +# define FLASH_ACR_LATENCY_6 (6 << FLASH_ACR_LATENCY_SHIFT) /* 110: Six wait states */ +# define FLASH_ACR_LATENCY_7 (7 << FLASH_ACR_LATENCY_SHIFT) /* 111: Seven wait states */ + +#if defined(CONFIG_STM32_STM32F10XX) +# define FLASH_ACR_HLFCYA (1 << 3) /* FLASH half cycle access */ +# define FLASH_ACR_PRTFBE (1 << 4) /* FLASH prefetch enable */ +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define FLASH_ACR_ICEN (1 << 9) /* Bit 9: Instruction cache enable */ +# define FLASH_ACR_DCEN (1 << 10) /* Bit 10: Data cache enable */ +# define FLASH_ACR_ICRST (1 << 11) /* Bit 11: Instruction cache reset */ +# define FLASH_ACR_DCRST (1 << 12) /* Bit 12: Data cache reset */ +#endif + +/* Flash Status Register (SR) */ + +#if defined(CONFIG_STM32_STM32F10XX) +# define FLASH_SR_BSY (1 << 0) /* Busy */ +# define FLASH_SR_PGERR (1 << 2) /* Programming Error */ +# define FLASH_SR_WRPRT_ERR (1 << 4) /* Write Protection Error */ +# define FLASH_SR_EOP (1 << 5) /* End of Operation */ +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define FLASH_SR_EOP (1 << 0) /* Bit 0: End of operation */ +# define FLASH_SR_OPERR (1 << 1) /* Bit 1: Operation error */ +# define FLASH_SR_WRPERR (1 << 4) /* Bit 4: Write protection error */ +# define FLASH_SR_PGAERR (1 << 5) /* Bit 5: Programming alignment error */ +# define FLASH_SR_PGPERR (1 << 6) /* Bit 6: Programming parallelism error */ +# define FLASH_SR_PGSERR (1 << 7) /* Bit 7: Programming sequence error */ +# define FLASH_SR_BSY (1 << 16) /* Bit 16: Busy */ +#endif + +/* Flash Control Register (CR) */ + +#if defined(CONFIG_STM32_STM32F10XX) +# define FLASH_CR_PG (1 << 0) /* Program Page */ +# define FLASH_CR_PER (1 << 1) /* Page Erase */ +# define FLASH_CR_MER (1 << 2) /* Mass Erase */ +# define FLASH_CR_OPTPG (1 << 4) /* Option Byte Programming */ +# define FLASH_CR_OPTER (1 << 5) /* Option Byte Erase */ +# define FLASH_CR_STRT (1 << 6) /* Start Erase */ +# define FLASH_CR_LOCK (1 << 7) /* Page Locked or Lock Page */ +# define FLASH_CR_OPTWRE (1 << 9) /* Option Bytes Write Enable */ +# define FLASH_CR_ERRIE (1 << 10) /* Error Interrupt Enable */ +# define FLASH_CR_EOPIE (1 << 12) /* End of Program Interrupt Enable */ +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define FLASH_CR_PG (1 << 0) /* Bit 0: Programming */ +# define FLASH_CR_SER (1 << 1) /* Bit 1: Sector Erase */ +# define FLASH_CR_MER (1 << 2) /* Bit 2: Mass Erase */ +# define FLASH_CR_SNB_SHIFT (3) /* Bits 3-6: Sector number */ +# define FLASH_CR_SNB_MASK (15 << FLASH_CR_SNB_SHIFT) +# define FLASH_CR_SNB(n) ((n) << FLASH_CR_SNB_SHIFT) /* Sector n, n=0..11 */ +# define FLASH_CR_PSIZE_SHIFT (8) /* Bits 8-9: Program size */ +# define FLASH_CR_PSIZE_MASK (3 << FLASH_CR_PSIZE_SHIFT) +# define FLASH_CR_PSIZE_X8 (0 << FLASH_CR_PSIZE_SHIFT) /* 00 program x8 */ +# define FLASH_CR_PSIZE_X16 (1 << FLASH_CR_PSIZE_SHIFT) /* 01 program x16 */ +# define FLASH_CR_PSIZE_X32 (2 << FLASH_CR_PSIZE_SHIFT) /* 10 program x32 */ +# define FLASH_CR_PSIZE_X64 (3 << FLASH_CR_PSIZE_SHIFT) /* 11 program x64 */ +# define FLASH_CR_EOPIE (1 << 24) /* Bit 24: End of operation interrupt enable */ +# define FLASH_CR_ERRIE (1 << 25) /* Bit 25: Error interrupt enable */ +# define FLASH_CR_LOCK (1 << 31) /* Bit 31: Lock */ +#endif + +/* Flash Option Control Register (OPTCR) */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define FLASH_OPTCR_OPTLOCK (1 << 0) /* Bit 0: Option lock */ +# define FLASH_OPTCR_OPTSTRT (1 << 1) /* Bit 1: Option start */ +# define FLASH_OPTCR_BORLEV_SHIFT (2) /* Bits 2-3: BOR reset Level */ +# define FLASH_OPTCR_BORLEV_MASK (3 << FLASH_OPTCR_BORLEV_SHIFT) +# define FLASH_OPTCR_VBOR3 (0 << FLASH_OPTCR_BORLEV_SHIFT) /* 00: BOR Level 3 */ +# define FLASH_OPTCR_VBOR2 (1 << FLASH_OPTCR_BORLEV_SHIFT) /* 01: BOR Level 2 */ +# define FLASH_OPTCR_VBOR1 (2 << FLASH_OPTCR_BORLEV_SHIFT) /* 10: BOR Level 1 */ +# define FLASH_OPTCR_VBOR0 (3 << FLASH_OPTCR_BORLEV_SHIFT) /* 11: BOR off */ +# define FLASH_OPTCR_USER_SHIFT (5) /* Bits 5-7: User option bytes */ +# define FLASH_OPTCR_USER_MASK (7 << FLASH_OPTCR_USER_SHIFT) +# define FLASH_OPTCR_NRST_STDBY (1 << 7) /* Bit 7: nRST_STDBY */ +# define FLASH_OPTCR_NRST_STOP (1 << 6) /* Bit 6: nRST_STOP */ +# define FLASH_OPTCR_WDG_SW (1 << 5) /* Bit 5: WDG_SW */ +# define FLASH_OPTCR_RDP_SHIFT (8) /* Bits 8-15: Read protect */ +# define FLASH_OPTCR_RDP_MASK (0xff << FLASH_OPTCR_RDP_SHIFT) +# define FLASH_OPTCR_NWRP_SHIFT (16) /* Bits 16-27: Not write protect */ +# define FLASH_OPTCR_NWRP_MASK (0xfff << FLASH_OPTCR_NWRP_SHIFT) +#endif + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_FLASH_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_i2c.h b/nuttx/arch/arm/src/stm32/chip/stm32_i2c.h new file mode 100644 index 0000000000..f481245e0b --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_i2c.h @@ -0,0 +1,192 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_i2c.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_I2C_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_I2C_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +#define STM32_I2C_CR1_OFFSET 0x0000 /* Control register 1 (16-bit) */ +#define STM32_I2C_CR2_OFFSET 0x0004 /* Control register 2 (16-bit) */ +#define STM32_I2C_OAR1_OFFSET 0x0008 /* Own address register 1 (16-bit) */ +#define STM32_I2C_OAR2_OFFSET 0x000c /* Own address register 2 (16-bit) */ +#define STM32_I2C_DR_OFFSET 0x0010 /* Data register (16-bit) */ +#define STM32_I2C_SR1_OFFSET 0x0014 /* Status register 1 (16-bit) */ +#define STM32_I2C_SR2_OFFSET 0x0018 /* Status register 2 (16-bit) */ +#define STM32_I2C_CCR_OFFSET 0x001c /* Clock control register (16-bit) */ +#define STM32_I2C_TRISE_OFFSET 0x0020 /* TRISE Register (16-bit) */ + +/* Register Addresses ***************************************************************/ + +#if STM32_NI2C > 0 +# define STM32_I2C1_CR1 (STM32_I2C1_BASE+STM32_I2C_CR1_OFFSET) +# define STM32_I2C1_CR2 (STM32_I2C1_BASE+STM32_I2C_CR2_OFFSET) +# define STM32_I2C1_OAR1 (STM32_I2C1_BASE+STM32_I2C_OAR1_OFFSET) +# define STM32_I2C1_OAR2 (STM32_I2C1_BASE+STM32_I2C_OAR2_OFFSET) +# define STM32_I2C1_DR (STM32_I2C1_BASE+STM32_I2C_DR_OFFSET) +# define STM32_I2C1_SR1 (STM32_I2C1_BASE+STM32_I2C_SR1_OFFSET) +# define STM32_I2C1_SR2 (STM32_I2C1_BASE+STM32_I2C_SR2_OFFSET) +# define STM32_I2C1_CCR (STM32_I2C1_BASE+STM32_I2C_CCR_OFFSET) +# define STM32_I2C1_TRISE (STM32_I2C1_BASE+STM32_I2C_TRISE_OFFSET) +#endif + +#if STM32_NI2C > 1 +# define STM32_I2C2_CR1 (STM32_I2C2_BASE+STM32_I2C_CR1_OFFSET) +# define STM32_I2C2_CR2 (STM32_I2C2_BASE+STM32_I2C_CR2_OFFSET) +# define STM32_I2C2_OAR1 (STM32_I2C2_BASE+STM32_I2C_OAR1_OFFSET) +# define STM32_I2C2_OAR2 (STM32_I2C2_BASE+STM32_I2C_OAR2_OFFSET) +# define STM32_I2C2_DR (STM32_I2C2_BASE+STM32_I2C_DR_OFFSET) +# define STM32_I2C2_SR1 (STM32_I2C2_BASE+STM32_I2C_SR1_OFFSET) +# define STM32_I2C2_SR2 (STM32_I2C2_BASE+STM32_I2C_SR2_OFFSET) +# define STM32_I2C2_CCR (STM32_I2C2_BASE+STM32_I2C_CCR_OFFSET) +# define STM32_I2C2_TRISE (STM32_I2C2_BASE+STM32_I2C_TRISE_OFFSET) +#endif + +#if STM32_NI2C > 2 +# define STM32_I2C3_CR1 (STM32_I2C3_BASE+STM32_I2C_CR1_OFFSET) +# define STM32_I2C3_CR2 (STM32_I2C3_BASE+STM32_I2C_CR2_OFFSET) +# define STM32_I2C3_OAR1 (STM32_I2C3_BASE+STM32_I2C_OAR1_OFFSET) +# define STM32_I2C3_OAR2 (STM32_I2C3_BASE+STM32_I2C_OAR2_OFFSET) +# define STM32_I2C3_DR (STM32_I2C3_BASE+STM32_I2C_DR_OFFSET) +# define STM32_I2C3_SR1 (STM32_I2C3_BASE+STM32_I2C_SR1_OFFSET) +# define STM32_I2C3_SR2 (STM32_I2C3_BASE+STM32_I2C_SR2_OFFSET) +# define STM32_I2C3_CCR (STM32_I2C3_BASE+STM32_I2C_CCR_OFFSET) +# define STM32_I2C3_TRISE (STM32_I2C3_BASE+STM32_I2C_TRISE_OFFSET) +#endif + +/* Register Bitfield Definitions ****************************************************/ + +/* Control register 1 */ + +#define I2C_CR1_PE (1 << 0) /* Bit 0: Peripheral Enable */ +#define I2C_CR1_SMBUS (1 << 1) /* Bit 1: SMBus Mode */ +#define I2C_CR1_SMBTYPE (1 << 3) /* Bit 3: SMBus Type */ +#define I2C_CR1_ENARP (1 << 4) /* Bit 4: ARP Enable */ +#define I2C_CR1_ENPEC (1 << 5) /* Bit 5: PEC Enable */ +#define I2C_CR1_ENGC (1 << 6) /* Bit 6: General Call Enable */ +#define I2C_CR1_NOSTRETCH (1 << 7) /* Bit 7: Clock Stretching Disable (Slave mode) */ +#define I2C_CR1_START (1 << 8) /* Bit 8: Start Generation */ +#define I2C_CR1_STOP (1 << 9) /* Bit 9: Stop Generation */ +#define I2C_CR1_ACK (1 << 10) /* Bit 10: Acknowledge Enable */ +#define I2C_CR1_POS (1 << 11) /* Bit 11: Acknowledge/PEC Position (for data reception) */ +#define I2C_CR1_PEC (1 << 12) /* Bit 12: Packet Error Checking */ +#define I2C_CR1_ALERT (1 << 13) /* Bit 13: SMBus Alert */ +#define I2C_CR1_SWRST (1 << 15) /* Bit 15: Software Reset */ + +/* Control register 2 */ + +#define I2C_CR2_FREQ_SHIFT (0) /* Bits 5-0: Peripheral Clock Frequency */ +#define I2C_CR2_FREQ_MASK (0x3f << I2C_CR2_FREQ_SHIFT) +#define I2C_CR2_ITERREN (1 << 8) /* Bit 8: Error Interrupt Enable */ +#define I2C_CR2_ITEVFEN (1 << 9) /* Bit 9: Event Interrupt Enable */ +#define I2C_CR2_ITBUFEN (1 << 10) /* Bit 10: Buffer Interrupt Enable */ +#define I2C_CR2_DMAEN (1 << 11) /* Bit 11: DMA Requests Enable */ +#define I2C_CR2_LAST (1 << 12) /* Bit 12: DMA Last Transfer */ + +#define I2C_CR2_ALLINTS (I2C_CR2_ITERREN|I2C_CR2_ITEVFEN|I2C_CR2_ITBUFEN) + +/* Own address register 1 */ + +#define I2C_OAR1_ADD0 (1 << 0) /* Bit 0: Interface Address */ +#define I2C_OAR1_ADD8_SHIFT (1) /* Bits 7-1: Interface Address */ +#define I2C_OAR1_ADD8_MASK (0x007f << I2C_OAR1_ADD8_SHIFT) +#define I2C_OAR1_ADD10_SHIFT (1) /* Bits 9-1: Interface Address (10-bit addressing mode)*/ +#define I2C_OAR1_ADD10_MASK (0x01ff << I2C_OAR1_ADD10_SHIFT) +#define I2C_OAR1_ONE (1 << 14) /* Bit 14: Must be configured and kept at 1 */ +#define I2C_OAR1_ADDMODE (1 << 15) /* Bit 15: Addressing Mode (Slave mode) */ + +/* Own address register 2 */ + +#define I2C_OAR2_ENDUAL (1 << 0) /* Bit 0: Dual addressing mode enable */ +#define I2C_OAR2_ADD2_SHIFT (1) /* Bits 7-1: Interface address */ +#define I2C_OAR2_ADD2_MASK (0x7f << I2C_OAR2_ADD2_SHIFT) + +/* Data register */ + +#define I2C_DR_SHIFT (0) /* Bits 7-0: 8-bit Data Register */ +#define I2C_DR_MASK (0x00ff << I2C_DR_SHIFT) + +/* Status register 1 */ + +#define I2C_SR1_SB (1 << 0) /* Bit 0: Start Bit (Master mode) */ +#define I2C_SR1_ADDR (1 << 1) /* Bit 1: Address sent (master mode)/matched (slave mode) */ +#define I2C_SR1_BTF (1 << 2) /* Bit 2: Byte Transfer Finished */ +#define I2C_SR1_ADD10 (1 << 3) /* Bit 3: 10-bit header sent (Master mode) */ +#define I2C_SR1_STOPF (1 << 4) /* Bit 4: Stop detection (Slave mode) */ + /* Bit 5: Reserved */ +#define I2C_SR1_RXNE (1 << 6) /* Bit 6: Data Register not Empty (receivers) */ +#define I2C_SR1_TXE (1 << 7) /* Bit 7: Data Register Empty (transmitters) */ +#define I2C_SR1_BERR (1 << 8) /* Bit 8: Bus Error */ +#define I2C_SR1_ARLO (1 << 9) /* Bit 9: Arbitration Lost (master mode) */ +#define I2C_SR1_AF (1 << 10) /* Bit 10: Acknowledge Failure */ +#define I2C_SR1_OVR (1 << 11) /* Bit 11: Overrun/Underrun */ +#define I2C_SR1_PECERR (1 << 12) /* Bit 12: PEC Error in reception */ + /* Bit 13: Reserved */ +#define I2C_SR1_TIMEOUT (1 << 14) /* Bit 14: Timeout or Tlow Error */ +#define I2C_SR1_SMBALERT (1 << 15) /* Bit 15: SMBus Alert */ + +#define I2C_SR1_ERRORMASK (I2C_SR1_BERR|I2C_SR1_ARLO|I2C_SR1_AF|I2C_SR1_OVR|\ + I2C_SR1_PECERR|I2C_SR1_TIMEOUT|I2C_SR1_SMBALERT) + +/* Status register 2 */ + +#define I2C_SR2_MSL (1 << 0) /* Bit 0: Master/Slave */ +#define I2C_SR2_BUSY (1 << 1) /* Bit 1: Bus Busy */ +#define I2C_SR2_TRA (1 << 2) /* Bit 2: Transmitter/Receiver */ +#define I2C_SR2_GENCALL (1 << 4) /* Bit 4: General Call Address (Slave mode) */ +#define I2C_SR2_SMBDEFAULT (1 << 5) /* Bit 5: SMBus Device Default Address (Slave mode) */ +#define I2C_SR2_SMBHOST (1 << 6) /* Bit 6: SMBus Host Header (Slave mode) */ +#define I2C_SR2_DUALF (1 << 7) /* Bit 7: Dual Flag (Slave mode) */ +#define I2C_SR2_PEC_SHIFT (1) /* Bits 15-8: Packet Error Checking Register */ +#define I2C_SR2_PEC_MASK (0xff << I2C_SR2_PEC_SHIFT) + +/* Clock control register */ + +#define I2C_CCR_CCR_SHIFT (0) /* Bits 11-0: Clock Control Register in Fast/Standard mode (Master mode) */ +#define I2C_CCR_CCR_MASK (0x0fff << I2C_CCR_CCR_SHIFT) +#define I2C_CCR_DUTY (1 << 14) /* Bit 14: Fast Mode Duty Cycle */ +#define I2C_CCR_FS (1 << 15) /* Bit 15: Fast Mode Selection */ + +/* TRISE Register */ + +#define I2C_TRISE_SHIFT (0) /* Bits 5-0: Maximum Rise Time in Fast/Standard mode (Master mode) */ +#define I2C_TRISE_MASK (0x3f << I2C_TRISE_SHIFT) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_I2C_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_memorymap.h b/nuttx/arch/arm/src/stm32/chip/stm32_memorymap.h new file mode 100644 index 0000000000..a53c7441cf --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_memorymap.h @@ -0,0 +1,57 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_memorymap.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_MEMORYMAP_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_MEMORYMAP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include "chip.h" + +#if defined(CONFIG_STM32_STM32F10XX) +# include "chip/stm32f10xxx_memorymap.h" +#elif defined(CONFIG_STM32_STM32F20XX) +# include "chip/stm32f20xxx_memorymap.h" +#elif defined(CONFIG_STM32_STM32F40XX) +# include "chip/stm32f40xxx_memorymap.h" +#else +# error "Unsupported STM32 memory map" +#endif + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_MEMORYMAP_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_otgfs.h b/nuttx/arch/arm/src/stm32/chip/stm32_otgfs.h new file mode 100644 index 0000000000..d3bf7eb547 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_otgfs.h @@ -0,0 +1,1002 @@ +/**************************************************************************************************** + * arch/arm/src/stm32/chip/stm32_otgfs.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_OTGFS_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_OTGFS_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include +#include "chip.h" + +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ + +/* Register Offsets *********************************************************************************/ +/* Core global control and status registers */ + +#define STM32_OTGFS_GOTGCTL_OFFSET 0x0000 /* Control and status register */ +#define STM32_OTGFS_GOTGINT_OFFSET 0x0004 /* Interrupt register */ +#define STM32_OTGFS_GAHBCFG_OFFSET 0x0008 /* AHB configuration register */ +#define STM32_OTGFS_GUSBCFG_OFFSET 0x000c /* USB configuration register */ +#define STM32_OTGFS_GRSTCTL_OFFSET 0x0010 /* Reset register */ +#define STM32_OTGFS_GINTSTS_OFFSET 0x0014 /* Core interrupt register */ +#define STM32_OTGFS_GINTMSK_OFFSET 0x0018 /* Interrupt mask register */ +#define STM32_OTGFS_GRXSTSR_OFFSET 0x001c /* Receive status debug read/OTG status read register */ +#define STM32_OTGFS_GRXSTSP_OFFSET 0x0020 /* Receive status debug read/OTG status pop register */ +#define STM32_OTGFS_GRXFSIZ_OFFSET 0x0024 /* Receive FIFO size register */ +#define STM32_OTGFS_HNPTXFSIZ_OFFSET 0x0028 /* Host non-periodic transmit FIFO size register */ +#define STM32_OTGFS_DIEPTXF0_OFFSET 0x0028 /* Endpoint 0 Transmit FIFO size */ +#define STM32_OTGFS_HNPTXSTS_OFFSET 0x002c /* Non-periodic transmit FIFO/queue status register */ +#define STM32_OTGFS_GCCFG_OFFSET 0x0038 /* general core configuration register */ +#define STM32_OTGFS_CID_OFFSET 0x003c /* Core ID register */ +#define STM32_OTGFS_HPTXFSIZ_OFFSET 0x0100 /* Host periodic transmit FIFO size register */ + +#define STM32_OTGFS_DIEPTXF_OFFSET(n) (104+(((n)-1) << 2)) +#define STM32_OTGFS_DIEPTXF1_OFFSET 0x0104 /* Device IN endpoint transmit FIFO1 size register */ +#define STM32_OTGFS_DIEPTXF2_OFFSET 0x0108 /* Device IN endpoint transmit FIFO2 size register */ +#define STM32_OTGFS_DIEPTXF3_OFFSET 0x010c /* Device IN endpoint transmit FIFO3 size register */ + +/* Host-mode control and status registers */ + +#define STM32_OTGFS_HCFG_OFFSET 0x0400 /* Host configuration register */ +#define STM32_OTGFS_HFIR_OFFSET 0x0404 /* Host frame interval register */ +#define STM32_OTGFS_HFNUM_OFFSET 0x0408 /* Host frame number/frame time remaining register */ +#define STM32_OTGFS_HPTXSTS_OFFSET 0x0410 /* Host periodic transmit FIFO/queue status register */ +#define STM32_OTGFS_HAINT_OFFSET 0x0414 /* Host all channels interrupt register */ +#define STM32_OTGFS_HAINTMSK_OFFSET 0x0418 /* Host all channels interrupt mask register */ +#define STM32_OTGFS_HPRT_OFFSET 0x0440 /* Host port control and status register */ + +#define STM32_OTGFS_CHAN_OFFSET(n) (0x500 + ((n) << 5) +#define STM32_OTGFS_HCCHAR_CHOFFSET 0x0000 /* Host channel characteristics register */ +#define STM32_OTGFS_HCINT_CHOFFSET 0x0008 /* Host channel interrupt register */ +#define STM32_OTGFS_HCINTMSK_CHOFFSET 0x000c /* Host channel interrupt mask register */ +#define STM32_OTGFS_HCTSIZ_CHOFFSET 0x0010 /* Host channel interrupt register */ + +#define STM32_OTGFS_HCCHAR_OFFSET(n) (0x500 + ((n) << 5)) +#define STM32_OTGFS_HCCHAR0_OFFSET 0x0500 /* Host channel-0 characteristics register */ +#define STM32_OTGFS_HCCHAR1_OFFSET 0x0520 /* Host channel-1 characteristics register */ +#define STM32_OTGFS_HCCHAR2_OFFSET 0x0540 /* Host channel-2 characteristics register */ +#define STM32_OTGFS_HCCHAR3_OFFSET 0x0560 /* Host channel-3 characteristics register */ +#define STM32_OTGFS_HCCHAR4_OFFSET 0x0580 /* Host channel-4 characteristics register */ +#define STM32_OTGFS_HCCHAR5_OFFSET 0x05a0 /* Host channel-5 characteristics register */ +#define STM32_OTGFS_HCCHAR6_OFFSET 0x05c0 /* Host channel-6 characteristics register */ +#define STM32_OTGFS_HCCHAR7_OFFSET 0x05e0 /* Host channel-7 characteristics register */ + +#define STM32_OTGFS_HCINT_OFFSET(n) (0x508 + ((n) << 5)) +#define STM32_OTGFS_HCINT0_OFFSET 0x0508 /* Host channel-0 interrupt register */ +#define STM32_OTGFS_HCINT1_OFFSET 0x0528 /* Host channel-1 interrupt register */ +#define STM32_OTGFS_HCINT2_OFFSET 0x0548 /* Host channel-2 interrupt register */ +#define STM32_OTGFS_HCINT3_OFFSET 0x0568 /* Host channel-3 interrupt register */ +#define STM32_OTGFS_HCINT4_OFFSET 0x0588 /* Host channel-4 interrupt register */ +#define STM32_OTGFS_HCINT5_OFFSET 0x05a8 /* Host channel-5 interrupt register */ +#define STM32_OTGFS_HCINT6_OFFSET 0x05c8 /* Host channel-6 interrupt register */ +#define STM32_OTGFS_HCINT7_OFFSET 0x05e8 /* Host channel-7 interrupt register */ + +#define STM32_OTGFS_HCINTMSK_OFFSET(n) (0x50c + ((n) << 5)) +#define STM32_OTGFS_HCINTMSK0_OFFSET 0x050c /* Host channel-0 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK1_OFFSET 0x052c /* Host channel-1 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK2_OFFSET 0x054c /* Host channel-2 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK3_OFFSET 0x056c /* Host channel-3 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK4_OFFSET 0x058c /* Host channel-4 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK5_OFFSET 0x05ac /* Host channel-5 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK6_OFFSET 0x05cc /* Host channel-6 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK7_OFFSET 0x05ec /* Host channel-7 interrupt mask register */ + +#define STM32_OTGFS_HCTSIZ_OFFSET(n) (0x510 + ((n) << 5)) +#define STM32_OTGFS_HCTSIZ0_OFFSET 0x0510 /* Host channel-0 interrupt register */ +#define STM32_OTGFS_HCTSIZ1_OFFSET 0x0530 /* Host channel-1 interrupt register */ +#define STM32_OTGFS_HCTSIZ2_OFFSET 0x0550 /* Host channel-2 interrupt register */ +#define STM32_OTGFS_HCTSIZ3_OFFSET 0x0570 /* Host channel-3 interrupt register */ +#define STM32_OTGFS_HCTSIZ4_OFFSET 0x0590 /* Host channel-4 interrupt register */ +#define STM32_OTGFS_HCTSIZ5_OFFSET 0x05b0 /* Host channel-5 interrupt register */ +#define STM32_OTGFS_HCTSIZ6_OFFSET 0x05d9 /* Host channel-6 interrupt register */ +#define STM32_OTGFS_HCTSIZ7_OFFSET 0x05f9 /* Host channel-7 interrupt register */ + +/* Device-mode control and status registers */ + +#define STM32_OTGFS_DCFG_OFFSET 0x0800 /* Device configuration register */ +#define STM32_OTGFS_DCTL_OFFSET 0x0804 /* Device control register */ +#define STM32_OTGFS_DSTS_OFFSET 0x0808 /* Device status register */ +#define STM32_OTGFS_DIEPMSK_OFFSET 0x0810 /* Device IN endpoint common interrupt mask register */ +#define STM32_OTGFS_DOEPMSK_OFFSET 0x0814 /* Device OUT endpoint common interrupt mask register */ +#define STM32_OTGFS_DAINT_OFFSET 0x0818 /* Device all endpoints interrupt register */ +#define STM32_OTGFS_DAINTMSK_OFFSET 0x081c /* All endpoints interrupt mask register */ +#define STM32_OTGFS_DVBUSDIS_OFFSET 0x0828 /* Device VBUS discharge time register */ +#define STM32_OTGFS_DVBUSPULSE_OFFSET 0x082c /* Device VBUS pulsing time register */ +#define STM32_OTGFS_DIEPEMPMSK_OFFSET 0x0834 /* Device IN endpoint FIFO empty interrupt mask register */ + +#define STM32_OTGFS_DIEP_OFFSET(n) (0x0900 + ((n) << 5)) +#define STM32_OTGFS_DIEPCTL_EPOFFSET 0x0000 /* Device endpoint control register */ +#define STM32_OTGFS_DIEPINT_EPOFFSET 0x0008 /* Device endpoint interrupt register */ +#define STM32_OTGFS_DIEPTSIZ_EPOFFSET 0x0010 /* Device IN endpoint transfer size register */ +#define STM32_OTGFS_DTXFSTS_EPOFFSET 0x0018 /* Device IN endpoint transmit FIFO status register */ + +#define STM32_OTGFS_DIEPCTL_OFFSET(n) (0x0900 + ((n) << 5)) +#define STM32_OTGFS_DIEPCTL0_OFFSET 0x0900 /* Device control IN endpoint 0 control register */ +#define STM32_OTGFS_DIEPCTL1_OFFSET 0x0920 /* Device control IN endpoint 2 control register */ +#define STM32_OTGFS_DIEPCTL2_OFFSET 0x0940 /* Device control IN endpoint 3 control register */ +#define STM32_OTGFS_DIEPCTL3_OFFSET 0x0960 /* Device control IN endpoint 4 control register */ + +#define STM32_OTGFS_DIEPINT_OFFSET(n) (0x0908 + ((n) << 5)) +#define STM32_OTGFS_DIEPINT0_OFFSET 0x0908 /* Device endpoint-0 interrupt register */ +#define STM32_OTGFS_DIEPINT1_OFFSET 0x0928 /* Device endpoint-1 interrupt register */ +#define STM32_OTGFS_DIEPINT2_OFFSET 0x0948 /* Device endpoint-2 interrupt register */ +#define STM32_OTGFS_DIEPINT3_OFFSET 0x0968 /* Device endpoint-3 interrupt register */ + +#define STM32_OTGFS_DIEPTSIZ_OFFSET(n) (0x910 + ((n) << 5)) +#define STM32_OTGFS_DIEPTSIZ0_OFFSET 0x0910 /* Device IN endpoint 0 transfer size register */ +#define STM32_OTGFS_DIEPTSIZ1_OFFSET 0x0930 /* Device IN endpoint 1 transfer size register */ +#define STM32_OTGFS_DIEPTSIZ2_OFFSET 0x0950 /* Device IN endpoint 2 transfer size register */ +#define STM32_OTGFS_DIEPTSIZ3_OFFSET 0x0970 /* Device IN endpoint 3 transfer size register */ + +#define STM32_OTGFS_DTXFSTS_OFFSET(n) (0x0918 + ((n) << 5)) +#define STM32_OTGFS_DTXFSTS0_OFFSET 0x0918 /* Device OUT endpoint-0 TxFIFO status register */ +#define STM32_OTGFS_DTXFSTS1_OFFSET 0x0938 /* Device OUT endpoint-1 TxFIFO status register */ +#define STM32_OTGFS_DTXFSTS2_OFFSET 0x0958 /* Device OUT endpoint-2 TxFIFO status register */ +#define STM32_OTGFS_DTXFSTS3_OFFSET 0x0978 /* Device OUT endpoint-3 TxFIFO status register */ + +#define STM32_OTGFS_DOEP_OFFSET(n) (0x0b00 + ((n) << 5)) +#define STM32_OTGFS_DOEPCTL_EPOFFSET 0x0000 /* Device control OUT endpoint 0 control register */ +#define STM32_OTGFS_DOEPINT_EPOFFSET 0x0008 /* Device endpoint-x interrupt register */ + +#define STM32_OTGFS_DOEPCTL_OFFSET(n) (0x0b00 + ((n) << 5)) +#define STM32_OTGFS_DOEPCTL0_OFFSET 0x00b00 /* Device OUT endpoint 0 control register */ +#define STM32_OTGFS_DOEPCTL1_OFFSET 0x00b20 /* Device OUT endpoint 1 control register */ +#define STM32_OTGFS_DOEPCTL2_OFFSET 0x00b40 /* Device OUT endpoint 2 control register */ +#define STM32_OTGFS_DOEPCTL3_OFFSET 0x00b60 /* Device OUT endpoint 3 control register */ + +#define STM32_OTGFS_DOEPINT_OFFSET(n) (0x0b08 + ((n) << 5)) +#define STM32_OTGFS_DOEPINT0_OFFSET 0x00b08 /* Device endpoint-0 interrupt register */ +#define STM32_OTGFS_DOEPINT1_OFFSET 0x00b28 /* Device endpoint-1 interrupt register */ +#define STM32_OTGFS_DOEPINT2_OFFSET 0x00b48 /* Device endpoint-2 interrupt register */ +#define STM32_OTGFS_DOEPINT3_OFFSET 0x00b68 /* Device endpoint-3 interrupt register */ + +#define STM32_OTGFS_DOEPTSIZ_OFFSET(n) (0x0b10 + ((n) << 5)) +#define STM32_OTGFS_DOEPTSIZ0_OFFSET 0x00b10 /* Device OUT endpoint-0 transfer size register */ +#define STM32_OTGFS_DOEPTSIZ1_OFFSET 0x00b30 /* Device OUT endpoint-1 transfer size register */ +#define STM32_OTGFS_DOEPTSIZ2_OFFSET 0x00b50 /* Device OUT endpoint-2 transfer size register */ +#define STM32_OTGFS_DOEPTSIZ3_OFFSET 0x00b70 /* Device OUT endpoint-3 transfer size register */ + +/* Data FIFO (DFIFO) access registers */ + +#define STM32_OTGFS_DFIFO_DEP_OFFSET(n) (0x1000 + ((n) << 12)) +#define STM32_OTGFS_DFIFO_HCH_OFFSET(n) (0x1000 + ((n) << 12)) + +#define STM32_OTGFS_DFIFO_DEP0_OFFSET 0x1000 /* 0x1000-0x1ffc Device IN/OUT Endpoint 0 DFIFO Write/Read Access */ +#define STM32_OTGFS_DFIFO_HCH0_OFFSET 0x1000 /* 0x1000-0x1ffc Host OUT/IN Channel 0 DFIFO Read/Write Access */ + +#define STM32_OTGFS_DFIFO_DEP1_OFFSET 0x2000 /* 0x2000-0x2ffc Device IN/OUT Endpoint 1 DFIFO Write/Read Access */ +#define STM32_OTGFS_DFIFO_HCH1_OFFSET 0x2000 /* 0x2000-0x2ffc Host OUT/IN Channel 1 DFIFO Read/Write Access */ + +#define STM32_OTGFS_DFIFO_DEP2_OFFSET 0x3000 /* 0x3000-0x3ffc Device IN/OUT Endpoint 1 DFIFO Write/Read Access */ +#define STM32_OTGFS_DFIFO_HCH2_OFFSET 0x3000 /* 0x3000-0x3ffc Host OUT/IN Channel 1 DFIFO Read/Write Access */ + +#define STM32_OTGFS_DFIFO_DEP3_OFFSET 0x4000 /* 0x4000-0x4ffc Device IN/OUT Endpoint 1 DFIFO Write/Read Access */ +#define STM32_OTGFS_DFIFO_HCH3_OFFSET 0x4000 /* 0x4000-0x4ffc Host OUT/IN Channel 1 DFIFO Read/Write Access */ + +/* Power and clock gating registers */ + +#define STM32_OTGFS_PCGCCTL_OFFSET 0x0e00 /* Power and clock gating control register */ + +/* Register Addresses *******************************************************************************/ + +#define STM32_OTGFS_GOTGCTL (STM32_OTGFS_BASE+STM32_OTGFS_GOTGCTL_OFFSET) +#define STM32_OTGFS_GOTGINT (STM32_OTGFS_BASE+STM32_OTGFS_GOTGINT_OFFSET) +#define STM32_OTGFS_GAHBCFG (STM32_OTGFS_BASE+STM32_OTGFS_GAHBCFG_OFFSET) +#define STM32_OTGFS_GUSBCFG (STM32_OTGFS_BASE+STM32_OTGFS_GUSBCFG_OFFSET) +#define STM32_OTGFS_GRSTCTL (STM32_OTGFS_BASE+STM32_OTGFS_GRSTCTL_OFFSET) +#define STM32_OTGFS_GINTSTS (STM32_OTGFS_BASE+STM32_OTGFS_GINTSTS_OFFSET) +#define STM32_OTGFS_GINTMSK (STM32_OTGFS_BASE+STM32_OTGFS_GINTMSK_OFFSET) +#define STM32_OTGFS_GRXSTSR (STM32_OTGFS_BASE+STM32_OTGFS_GRXSTSR_OFFSET) +#define STM32_OTGFS_GRXSTSP (STM32_OTGFS_BASE+STM32_OTGFS_GRXSTSP_OFFSET) +#define STM32_OTGFS_GRXFSIZ (STM32_OTGFS_BASE+STM32_OTGFS_GRXFSIZ_OFFSET) +#define STM32_OTGFS_HNPTXFSIZ (STM32_OTGFS_BASE+STM32_OTGFS_HNPTXFSIZ_OFFSET) +#define STM32_OTGFS_DIEPTXF0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF0_OFFSET) +#define STM32_OTGFS_HNPTXSTS (STM32_OTGFS_BASE+STM32_OTGFS_HNPTXSTS_OFFSET) +#define STM32_OTGFS_GCCFG (STM32_OTGFS_BASE+STM32_OTGFS_GCCFG_OFFSET) +#define STM32_OTGFS_CID (STM32_OTGFS_BASE+STM32_OTGFS_CID_OFFSET) +#define STM32_OTGFS_HPTXFSIZ (STM32_OTGFS_BASE+STM32_OTGFS_HPTXFSIZ_OFFSET) + +#define STM32_OTGFS_DIEPTXF(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF_OFFSET(n)) +#define STM32_OTGFS_DIEPTXF1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF1_OFFSET) +#define STM32_OTGFS_DIEPTXF2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF2_OFFSET) +#define STM32_OTGFS_DIEPTXF3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF3_OFFSET) + +/* Host-mode control and status registers */ + +#define STM32_OTGFS_HCFG (STM32_OTGFS_BASE+STM32_OTGFS_HCFG_OFFSET) +#define STM32_OTGFS_HFIR (STM32_OTGFS_BASE+STM32_OTGFS_HFIR_OFFSET) +#define STM32_OTGFS_HFNUM (STM32_OTGFS_BASE+STM32_OTGFS_HFNUM_OFFSET) +#define STM32_OTGFS_HPTXSTS (STM32_OTGFS_BASE+STM32_OTGFS_HPTXSTS_OFFSET) +#define STM32_OTGFS_HAINT (STM32_OTGFS_BASE+STM32_OTGFS_HAINT_OFFSET) +#define STM32_OTGFS_HAINTMSK (STM32_OTGFS_BASE+STM32_OTGFS_HAINTMSK_OFFSET) +#define STM32_OTGFS_HPRT (STM32_OTGFS_BASE+STM32_OTGFS_HPRT_OFFSET) + +#define STM32_OTGFS_CHAN(n) (STM32_OTGFS_BASE+STM32_OTGFS_CHAN_OFFSET(n)) + +#define STM32_OTGFS_HCCHAR(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR_OFFSET(n)) +#define STM32_OTGFS_HCCHAR0 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR0_OFFSET) +#define STM32_OTGFS_HCCHAR1 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR1_OFFSET) +#define STM32_OTGFS_HCCHAR2 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR2_OFFSET) +#define STM32_OTGFS_HCCHAR3 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR3_OFFSET) +#define STM32_OTGFS_HCCHAR4 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR4_OFFSET) +#define STM32_OTGFS_HCCHAR5 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR5_OFFSET) +#define STM32_OTGFS_HCCHAR6 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR6_OFFSET) +#define STM32_OTGFS_HCCHAR7 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR7_OFFSET) + +#define STM32_OTGFS_HCINT(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCINT_OFFSET(n)) +#define STM32_OTGFS_HCINT0 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT0_OFFSET) +#define STM32_OTGFS_HCINT1 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT1_OFFSET) +#define STM32_OTGFS_HCINT2 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT2_OFFSET) +#define STM32_OTGFS_HCINT3 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT3_OFFSET) +#define STM32_OTGFS_HCINT4 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT4_OFFSET) +#define STM32_OTGFS_HCINT5 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT5_OFFSET) +#define STM32_OTGFS_HCINT6 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT6_OFFSET) +#define STM32_OTGFS_HCINT7 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT7_OFFSET) + +#define STM32_OTGFS_HCINTMSK(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK_OFFSET(n)) +#define STM32_OTGFS_HCINTMSK0 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK0_OFFSET) +#define STM32_OTGFS_HCINTMSK1 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK1_OFFSET) +#define STM32_OTGFS_HCINTMSK2 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK2_OFFSET) +#define STM32_OTGFS_HCINTMSK3 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK3_OFFSET) +#define STM32_OTGFS_HCINTMSK4 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK4_OFFSET) +#define STM32_OTGFS_HCINTMSK5 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK5_OFFSET) +#define STM32_OTGFS_HCINTMSK6 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK6_OFFSET) +#define STM32_OTGFS_HCINTMSK7 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK7_OFFSET)_ + +#define STM32_OTGFS_HCTSIZ(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ_OFFSET(n)) +#define STM32_OTGFS_HCTSIZ0 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ0_OFFSET) +#define STM32_OTGFS_HCTSIZ1 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ1_OFFSET) +#define STM32_OTGFS_HCTSIZ2 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ2_OFFSET) +#define STM32_OTGFS_HCTSIZ3 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ3_OFFSET) +#define STM32_OTGFS_HCTSIZ4 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ4_OFFSET) +#define STM32_OTGFS_HCTSIZ5 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ5_OFFSET) +#define STM32_OTGFS_HCTSIZ6 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ6_OFFSET) +#define STM32_OTGFS_HCTSIZ7 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ7_OFFSET) + +/* Device-mode control and status registers */ + +#define STM32_OTGFS_DCFG (STM32_OTGFS_BASE+STM32_OTGFS_DCFG_OFFSET) +#define STM32_OTGFS_DCTL (STM32_OTGFS_BASE+STM32_OTGFS_DCTL_OFFSET) +#define STM32_OTGFS_DSTS (STM32_OTGFS_BASE+STM32_OTGFS_DSTS_OFFSET) +#define STM32_OTGFS_DIEPMSK (STM32_OTGFS_BASE+STM32_OTGFS_DIEPMSK_OFFSET) +#define STM32_OTGFS_DOEPMSK (STM32_OTGFS_BASE+STM32_OTGFS_DOEPMSK_OFFSET) +#define STM32_OTGFS_DAINT (STM32_OTGFS_BASE+STM32_OTGFS_DAINT_OFFSET) +#define STM32_OTGFS_DAINTMSK (STM32_OTGFS_BASE+STM32_OTGFS_DAINTMSK_OFFSET) +#define STM32_OTGFS_DVBUSDIS (STM32_OTGFS_BASE+STM32_OTGFS_DVBUSDIS_OFFSET) +#define STM32_OTGFS_DVBUSPULSE (STM32_OTGFS_BASE+STM32_OTGFS_DVBUSPULSE_OFFSET) +#define STM32_OTGFS_DIEPEMPMSK (STM32_OTGFS_BASE+STM32_OTGFS_DIEPEMPMSK_OFFSET) + +#define STM32_OTGFS_DIEP(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEP_OFFSET(n)) + +#define STM32_OTGFS_DIEPCTL(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL_OFFSET(n)) +#define STM32_OTGFS_DIEPCTL0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL0_OFFSET) +#define STM32_OTGFS_DIEPCTL1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL1_OFFSET) +#define STM32_OTGFS_DIEPCTL2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL2_OFFSET) +#define STM32_OTGFS_DIEPCTL3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL3_OFFSET) + +#define STM32_OTGFS_DIEPINT(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT_OFFSET(n)) +#define STM32_OTGFS_DIEPINT0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT0_OFFSET) +#define STM32_OTGFS_DIEPINT1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT1_OFFSET) +#define STM32_OTGFS_DIEPINT2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT2_OFFSET) +#define STM32_OTGFS_DIEPINT3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT3_OFFSET) + +#define STM32_OTGFS_DIEPTSIZ(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ_OFFSET(n)) +#define STM32_OTGFS_DIEPTSIZ0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ0_OFFSET) +#define STM32_OTGFS_DIEPTSIZ1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ1_OFFSET) +#define STM32_OTGFS_DIEPTSIZ2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ2_OFFSET) +#define STM32_OTGFS_DIEPTSIZ3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ3_OFFSET) + +#define STM32_OTGFS_DTXFSTS(n) (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS_OFFSET(n)) +#define STM32_OTGFS_DTXFSTS0 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS0_OFFSET) +#define STM32_OTGFS_DTXFSTS1 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS1_OFFSET) +#define STM32_OTGFS_DTXFSTS2 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS2_OFFSET) +#define STM32_OTGFS_DTXFSTS3 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS3_OFFSET) + +#define STM32_OTGFS_DOEP(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEP_OFFSET(n)) + +#define STM32_OTGFS_DOEPCTL(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL_OFFSET(n)) +#define STM32_OTGFS_DOEPCTL0 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL0_OFFSET) +#define STM32_OTGFS_DOEPCTL1 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL1_OFFSET) +#define STM32_OTGFS_DOEPCTL2 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL2_OFFSET) +#define STM32_OTGFS_DOEPCTL3 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL3_OFFSET) + +#define STM32_OTGFS_DOEPINT(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT_OFFSET(n)) +#define STM32_OTGFS_DOEPINT0 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT0_OFFSET) +#define STM32_OTGFS_DOEPINT1 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT1_OFFSET) +#define STM32_OTGFS_DOEPINT2 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT2_OFFSET) +#define STM32_OTGFS_DOEPINT3 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT3_OFFSET) + +#define STM32_OTGFS_DOEPTSIZ(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ_OFFSET(n)) +#define STM32_OTGFS_DOEPTSIZ0 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ0_OFFSET) +#define STM32_OTGFS_DOEPTSIZ1 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ1_OFFSET) +#define STM32_OTGFS_DOEPTSIZ2 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ2_OFFSET) +#define STM32_OTGFS_DOEPTSIZ3 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ3_OFFSET) + +/* Data FIFO (DFIFO) access registers */ + +#define STM32_OTGFS_DFIFO_DEP(n) (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP_OFFSET(n)) +#define STM32_OTGFS_DFIFO_HCH(n) (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH_OFFSET(n)) + +#define STM32_OTGFS_DFIFO_DEP0 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP0_OFFSET) +#define STM32_OTGFS_DFIFO_HCH0 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH0_OFFSET) + +#define STM32_OTGFS_DFIFO_DEP1 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP1_OFFSET) +#define STM32_OTGFS_DFIFO_HCH1 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH1_OFFSET) + +#define STM32_OTGFS_DFIFO_DEP2 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP2_OFFSET) +#define STM32_OTGFS_DFIFO_HCH2 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH2_OFFSET) + +#define STM32_OTGFS_DFIFO_DEP3 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP3_OFFSET) +#define STM32_OTGFS_DFIFO_HCH3 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH3_OFFSET) + +/* Power and clock gating registers */ + +#define STM32_OTGFS_PCGCCTL (STM32_OTGFS_BASE+STM32_OTGFS_PCGCCTL_OFFSET) + +/* Register Bitfield Definitions ********************************************************************/ +/* Core global control and status registers */ + +/* Control and status register */ + +#define OTGFS_GOTGCTL_SRQSCS (1 << 0) /* Bit 0: Session request success */ +#define OTGFS_GOTGCTL_SRQ (1 << 1) /* Bit 1: Session request */ + /* Bits 2-72 Reserved, must be kept at reset value */ +#define OTGFS_GOTGCTL_HNGSCS (1 << 8) /* Bit 8: Host negotiation success */ +#define OTGFS_GOTGCTL_HNPRQ (1 << 9) /* Bit 9: HNP request */ +#define OTGFS_GOTGCTL_HSHNPEN (1 << 10) /* Bit 10: host set HNP enable */ +#define OTGFS_GOTGCTL_DHNPEN (1 << 11) /* Bit 11: Device HNP enabled */ + /* Bits 12-15: Reserved, must be kept at reset value */ +#define OTGFS_GOTGCTL_CIDSTS (1 << 16) /* Bit 16: Connector ID status */ +#define OTGFS_GOTGCTL_DBCT (1 << 17) /* Bit 17: Long/short debounce time */ +#define OTGFS_GOTGCTL_ASVLD (1 << 18) /* Bit 18: A-session valid */ +#define OTGFS_GOTGCTL_BSVLD (1 << 19) /* Bit 19: B-session valid */ + /* Bits 20-31: Reserved, must be kept at reset value */ +/* Interrupt register */ + /* Bits 1:0 Reserved, must be kept at reset value */ +#define OTGFS_GOTGINT_SEDET (1 << 2) /* Bit 2: Session end detected */ + /* Bits 3-7: Reserved, must be kept at reset value */ +#define OTGFS_GOTGINT_SRSSCHG (1 << 8) /* Bit 8: Session request success status change */ +#define OTGFS_GOTGINT_HNSSCHG (1 << 9) /* Bit 9: Host negotiation success status change */ + /* Bits 16:10 Reserved, must be kept at reset value */ +#define OTGFS_GOTGINT_HNGDET (1 << 17) /* Bit 17: Host negotiation detected */ +#define OTGFS_GOTGINT_ADTOCHG (1 << 18) /* Bit 18: A-device timeout change */ +#define OTGFS_GOTGINT_DBCDNE (1 << 19) /* Bit 19: Debounce done */ + /* Bits 2-31: Reserved, must be kept at reset value */ + +/* AHB configuration register */ + +#define OTGFS_GAHBCFG_GINTMSK (1 << 0) /* Bit 0: Global interrupt mask */ + /* Bits 1-6: Reserved, must be kept at reset value */ +#define OTGFS_GAHBCFG_TXFELVL (1 << 7) /* Bit 7: TxFIFO empty level */ +#define OTGFS_GAHBCFG_PTXFELVL (1 << 8) /* Bit 8: Periodic TxFIFO empty level */ + /* Bits 20-31: Reserved, must be kept at reset value */ +/* USB configuration register */ + +#define OTGFS_GUSBCFG_TOCAL_SHIFT (0) /* Bits 0-2: FS timeout calibration */ +#define OTGFS_GUSBCFG_TOCAL_MASK (7 << OTGFS_GUSBCFG_TOCAL_SHIFT) + /* Bits 3-6: Reserved, must be kept at reset value */ +#define OTGFS_GUSBCFG_SRPCAP (1 << 8) /* Bit 8: SRP-capable */ +#define OTGFS_GUSBCFG_HNPCAP (1 << 9) /* Bit 9: HNP-capable */ +#define OTGFS_GUSBCFG_TRDT_SHIFT (10) /* Bits 10-13: USB turnaround time */ +#define OTGFS_GUSBCFG_TRDT_MASK (15 << OTGFS_GUSBCFG_TRDT_SHIFT) +# define OTGFS_GUSBCFG_TRDT(n) ((n) << OTGFS_GUSBCFG_TRDT_SHIFT) + /* Bits 14-28: Reserved, must be kept at reset value */ +#define OTGFS_GUSBCFG_FHMOD (1 << 29) /* Bit 29: Force host mode */ +#define OTGFS_GUSBCFG_FDMOD (1 << 30) /* Bit 30: Force device mode */ +#define OTGFS_GUSBCFG_CTXPKT (1 << 31) /* Bit 31: Corrupt Tx packet */ + /* Bits 20-31: Reserved, must be kept at reset value */ +/* Reset register */ + +#define OTGFS_GRSTCTL_CSRST (1 << 0) /* Bit 0: Core soft reset */ +#define OTGFS_GRSTCTL_HSRST (1 << 1) /* Bit 1: HCLK soft reset */ +#define OTGFS_GRSTCTL_FCRST (1 << 2) /* Bit 2: Host frame counter reset */ + /* Bit 3 Reserved, must be kept at reset value */ +#define OTGFS_GRSTCTL_RXFFLSH (1 << 4) /* Bit 4: RxFIFO flush */ +#define OTGFS_GRSTCTL_TXFFLSH (1 << 5) /* Bit 5: TxFIFO flush */ +#define OTGFS_GRSTCTL_TXFNUM_SHIFT (10) /* Bits 6-10: TxFIFO number */ +#define OTGFS_GRSTCTL_TXFNUM_MASK (31 << OTGFS_GRSTCTL_TXFNUM_SHIFT) +# define OTGFS_GRSTCTL_TXFNUM_HNONPER (0 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Non-periodic TxFIFO flush in host mode */ +# define OTGFS_GRSTCTL_TXFNUM_HPER (1 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Periodic TxFIFO flush in host mode */ +# define OTGFS_GRSTCTL_TXFNUM_HALL (16 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Flush all the transmit FIFOs in host mode.*/ +# define OTGFS_GRSTCTL_TXFNUM_D(n) ((n) << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* TXFIFO n flush in device mode, n=0-15 */ +# define OTGFS_GRSTCTL_TXFNUM_DALL (16 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Flush all the transmit FIFOs in device mode.*/ + /* Bits 11-31: Reserved, must be kept at reset value */ +#define OTGFS_GRSTCTL_AHBIDL (1 << 31) /* Bit 31: AHB master idle */ + +/* Core interrupt and Interrupt mask registers */ + +#define OTGFS_GINTSTS_CMOD (1 << 0) /* Bit 0: Current mode of operation */ +# define OTGFS_GINTSTS_DEVMODE (0) +# define OTGFS_GINTSTS_HOSTMODE (OTGFS_GINTSTS_CMOD) +#define OTGFS_GINT_MMIS (1 << 1) /* Bit 1: Mode mismatch interrupt */ +#define OTGFS_GINT_OTG (1 << 2) /* Bit 2: OTG interrupt */ +#define OTGFS_GINT_SOF (1 << 3) /* Bit 3: Start of frame */ +#define OTGFS_GINT_RXFLVL (1 << 4) /* Bit 4: RxFIFO non-empty */ +#define OTGFS_GINT_NPTXFE (1 << 5) /* Bit 5: Non-periodic TxFIFO empty */ +#define OTGFS_GINT_GINAKEFF (1 << 6) /* Bit 6: Global IN non-periodic NAK effective */ +#define OTGFS_GINT_GONAKEFF (1 << 7) /* Bit 7: Global OUT NAK effective */ + /* Bits 8-9: Reserved, must be kept at reset value */ +#define OTGFS_GINT_ESUSP (1 << 10) /* Bit 10: Early suspend */ +#define OTGFS_GINT_USBSUSP (1 << 11) /* Bit 11: USB suspend */ +#define OTGFS_GINT_USBRST (1 << 12) /* Bit 12: USB reset */ +#define OTGFS_GINT_ENUMDNE (1 << 13) /* Bit 13: Enumeration done */ +#define OTGFS_GINT_ISOODRP (1 << 14) /* Bit 14: Isochronous OUT packet dropped interrupt */ +#define OTGFS_GINT_EOPF (1 << 15) /* Bit 15: End of periodic frame interrupt */ + /* Bits 16 Reserved, must be kept at reset value */ +#define OTGFS_GINTMSK_EPMISM (1 << 17) /* Bit 17: Endpoint mismatch interrupt mask */ +#define OTGFS_GINT_IEP (1 << 18) /* Bit 18: IN endpoint interrupt */ +#define OTGFS_GINT_OEP (1 << 19) /* Bit 19: OUT endpoint interrupt */ +#define OTGFS_GINT_IISOIXFR (1 << 20) /* Bit 20: Incomplete isochronous IN transfer */ +#define OTGFS_GINT_IISOOXFR (1 << 21) /* Bit 21: Incomplete isochronous OUT transfer */ + /* Bits 22-23: Reserved, must be kept at reset value */ +#define OTGFS_GINT_HPRT (1 << 24) /* Bit 24: Host port interrupt */ +#define OTGFS_GINT_HC (1 << 25) /* Bit 25: Host channels interrupt */ +#define OTGFS_GINT_PTXFE (1 << 26) /* Bit 26: Periodic TxFIFO empty */ + /* Bit 27 Reserved, must be kept at reset value */ +#define OTGFS_GINT_CIDSCHG (1 << 28) /* Bit 28: Connector ID status change */ +#define OTGFS_GINT_DISC (1 << 29) /* Bit 29: Disconnect detected interrupt */ +#define OTGFS_GINT_SRQ (1 << 30) /* Bit 30: Session request/new session detected interrupt */ +#define OTGFS_GINT_WKUP (1 << 31) /* Bit 31: Resume/remote wakeup detected interrupt */ + +/* Receive status debug read/OTG status read and pop registers (host mode) */ + +#define OTGFS_GRXSTSH_CHNUM_SHIFT (0) /* Bits 0-3: Channel number */ +#define OTGFS_GRXSTSH_CHNUM_MASK (15 << OTGFS_GRXSTSH_CHNUM_SHIFT) +#define OTGFS_GRXSTSH_BCNT_SHIFT (4) /* Bits 4-14: Byte count */ +#define OTGFS_GRXSTSH_BCNT_MASK (0x7ff << OTGFS_GRXSTSH_BCNT_SHIFT) +#define OTGFS_GRXSTSH_DPID_SHIFT (15) /* Bits 15-16: Data PID */ +#define OTGFS_GRXSTSH_DPID_MASK (3 << OTGFS_GRXSTSH_DPID_SHIFT) +# define OTGFS_GRXSTSH_DPID_DATA0 (0 << OTGFS_GRXSTSH_DPID_SHIFT) +# define OTGFS_GRXSTSH_DPID_DATA2 (1 << OTGFS_GRXSTSH_DPID_SHIFT) +# define OTGFS_GRXSTSH_DPID_DATA1 (2 << OTGFS_GRXSTSH_DPID_SHIFT) +# define OTGFS_GRXSTSH_DPID_MDATA (3 << OTGFS_GRXSTSH_DPID_SHIFT) +#define OTGFS_GRXSTSH_PKTSTS_SHIFT (17) /* Bits 17-20: Packet status */ +#define OTGFS_GRXSTSH_PKTSTS_MASK (15 << OTGFS_GRXSTSH_PKTSTS_SHIFT) +# define OTGFS_GRXSTSH_PKTSTS_INRECVD (2 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* IN data packet received */ +# define OTGFS_GRXSTSH_PKTSTS_INDONE (3 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* IN transfer completed */ +# define OTGFS_GRXSTSH_PKTSTS_DTOGERR (2 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* Data toggle error */ +# define OTGFS_GRXSTSH_PKTSTS_HALTED (7 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* Channel halted */ + /* Bits 21-31: Reserved, must be kept at reset value */ +/* Receive status debug read/OTG status read and pop registers (device mode) */ + +#define OTGFS_GRXSTSD_EPNUM_SHIFT (0) /* Bits 0-3: Endpoint number */ +#define OTGFS_GRXSTSD_EPNUM_MASK (15 << OTGFS_GRXSTSD_EPNUM_SHIFT) +#define OTGFS_GRXSTSD_BCNT_SHIFT (4) /* Bits 4-14: Byte count */ +#define OTGFS_GRXSTSD_BCNT_MASK (0x7ff << OTGFS_GRXSTSD_BCNT_SHIFT) +#define OTGFS_GRXSTSD_DPID_SHIFT (15) /* Bits 15-16: Data PID */ +#define OTGFS_GRXSTSD_DPID_MASK (3 << OTGFS_GRXSTSD_DPID_SHIFT) +# define OTGFS_GRXSTSD_DPID_DATA0 (0 << OTGFS_GRXSTSD_DPID_SHIFT) +# define OTGFS_GRXSTSD_DPID_DATA2 (1 << OTGFS_GRXSTSD_DPID_SHIFT) +# define OTGFS_GRXSTSD_DPID_DATA1 (2 << OTGFS_GRXSTSD_DPID_SHIFT) +# define OTGFS_GRXSTSD_DPID_MDATA (3 << OTGFS_GRXSTSD_DPID_SHIFT) +#define OTGFS_GRXSTSD_PKTSTS_SHIFT (17) /* Bits 17-20: Packet status */ +#define OTGFS_GRXSTSD_PKTSTS_MASK (15 << OTGFS_GRXSTSD_PKTSTS_SHIFT) +# define OTGFS_GRXSTSD_PKTSTS_OUTNAK (1 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* Global OUT NAK */ +# define OTGFS_GRXSTSD_PKTSTS_OUTRECVD (2 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* OUT data packet received */ +# define OTGFS_GRXSTSD_PKTSTS_OUTDONE (3 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* OUT transfer completed */ +# define OTGFS_GRXSTSD_PKTSTS_SETUPDONE (4 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* SETUP transaction completed */ +# define OTGFS_GRXSTSD_PKTSTS_SETUPRECVD (6 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* SETUP data packet received */ +#define OTGFS_GRXSTSD_FRMNUM_SHIFT (21) /* Bits 21-24: Frame number */ +#define OTGFS_GRXSTSD_FRMNUM_MASK (15 << OTGFS_GRXSTSD_FRMNUM_SHIFT) + /* Bits 25-31: Reserved, must be kept at reset value */ +/* Receive FIFO size register */ + +#define OTGFS_GRXFSIZ_MASK (0xffff) + +/* Host non-periodic transmit FIFO size register */ + +#define OTGFS_HNPTXFSIZ_NPTXFSA_SHIFT (0) /* Bits 0-15: Non-periodic transmit RAM start address */ +#define OTGFS_HNPTXFSIZ_NPTXFSA_MASK (0xffff << OTGFS_HNPTXFSIZ_NPTXFSA_SHIFT) +#define OTGFS_HNPTXFSIZ_NPTXFD_SHIFT (16) /* Bits 16-31: Non-periodic TxFIFO depth */ +#define OTGFS_HNPTXFSIZ_NPTXFD_MASK (0xffff << OTGFS_HNPTXFSIZ_NPTXFD_SHIFT) +# define OTGFS_HNPTXFSIZ_NPTXFD_MIN (16 << OTGFS_HNPTXFSIZ_NPTXFD_SHIFT) +# define OTGFS_HNPTXFSIZ_NPTXFD_MAX (256 << OTGFS_HNPTXFSIZ_NPTXFD_SHIFT) + +/* Endpoint 0 Transmit FIFO size */ + +#define OTGFS_DIEPTXF0_TX0FD_SHIFT (0) /* Bits 0-15: Endpoint 0 transmit RAM start address */ +#define OTGFS_DIEPTXF0_TX0FD_MASK (0xffff << OTGFS_DIEPTXF0_TX0FD_SHIFT) +#define OTGFS_DIEPTXF0_TX0FSA_SHIFT (16) /* Bits 16-31: Endpoint 0 TxFIFO depth */ +#define OTGFS_DIEPTXF0_TX0FSA_MASK (0xffff << OTGFS_DIEPTXF0_TX0FSA_SHIFT) +# define OTGFS_DIEPTXF0_TX0FSA_MIN (16 << OTGFS_DIEPTXF0_TX0FSA_SHIFT) +# define OTGFS_DIEPTXF0_TX0FSA_MAX (256 << OTGFS_DIEPTXF0_TX0FSA_SHIFT) + +/* Non-periodic transmit FIFO/queue status register */ + +#define OTGFS_HNPTXSTS_NPTXFSAV_SHIFT (0) /* Bits 0-15: Non-periodic TxFIFO space available */ +#define OTGFS_HNPTXSTS_NPTXFSAV_MASK (0xffff << OTGFS_HNPTXSTS_NPTXFSAV_SHIFT) +# define OTGFS_HNPTXSTS_NPTXFSAV_FULL (0 << OTGFS_HNPTXSTS_NPTXFSAV_SHIFT) +#define OTGFS_HNPTXSTS_NPTQXSAV_SHIFT (16) /* Bits 16-23: Non-periodic transmit request queue space available */ +#define OTGFS_HNPTXSTS_NPTQXSAV_MASK (0xff << OTGFS_HNPTXSTS_NPTQXSAV_SHIFT) +# define OTGFS_HNPTXSTS_NPTQXSAV_FULL (0 << OTGFS_HNPTXSTS_NPTQXSAV_SHIFT) +#define OTGFS_HNPTXSTS_NPTXQTOP_SHIFT (24) /* Bits 24-30: Top of the non-periodic transmit request queue */ +#define OTGFS_HNPTXSTS_NPTXQTOP_MASK (0x7f << OTGFS_HNPTXSTS_NPTXQTOP_SHIFT) +# define OTGFS_HNPTXSTS_TERMINATE (1 << 24) /* Bit 24: Terminate (last entry for selected channel/endpoint) */ +# define OTGFS_HNPTXSTS_TYPE_SHIFT (25) /* Bits 25-26: Status */ +# define OTGFS_HNPTXSTS_TYPE_MASK (3 << OTGFS_HNPTXSTS_TYPE_SHIFT) +# define OTGFS_HNPTXSTS_TYPE_INOUT (0 << OTGFS_HNPTXSTS_TYPE_SHIFT) /* IN/OUT token */ +# define OTGFS_HNPTXSTS_TYPE_ZLP (1 << OTGFS_HNPTXSTS_TYPE_SHIFT) /* Zero-length transmit packet (device IN/host OUT) */ +# define OTGFS_HNPTXSTS_TYPE_HALT (3 << OTGFS_HNPTXSTS_TYPE_SHIFT) /* Channel halt command */ +# define OTGFS_HNPTXSTS_CHNUM_SHIFT (27) /* Bits 27-30: Channel number */ +# define OTGFS_HNPTXSTS_CHNUM_MASK (15 << OTGFS_HNPTXSTS_CHNUM_SHIFT) +# define OTGFS_HNPTXSTS_EPNUM_SHIFT (27) /* Bits 27-30: Endpoint number */ +# define OTGFS_HNPTXSTS_EPNUM_MASK (15 << OTGFS_HNPTXSTS_EPNUM_SHIFT) + /* Bit 31 Reserved, must be kept at reset value */ +/* general core configuration register */ + /* Bits 15:0 Reserved, must be kept at reset value */ +#define OTGFS_GCCFG_PWRDWN (1 << 16) /* Bit 16: Power down */ + /* Bit 17 Reserved, must be kept at reset value */ +#define OTGFS_GCCFG_VBUSASEN (1 << 18) /* Bit 18: Enable the VBUS sensing “A” device */ +#define OTGFS_GCCFG_VBUSBSEN (1 << 19) /* Bit 19: Enable the VBUS sensing “B” device */ +#define OTGFS_GCCFG_SOFOUTEN (1 << 20) /* Bit 20: SOF output enable */ +#define OTGFS_GCCFG_NOVBUSSENS (1 << 21) /* Bit 21: VBUS sensing disable option */ + /* Bits 31:22 Reserved, must be kept at reset value */ +/* Core ID register (32-bit product ID) */ + +/* Host periodic transmit FIFO size register */ + +#define OTGFS_HPTXFSIZ_PTXSA_SHIFT (0) /* Bits 0-15: Host periodic TxFIFO start address */ +#define OTGFS_HPTXFSIZ_PTXSA_MASK (0xffff << OTGFS_HPTXFSIZ_PTXSA_SHIFT) +#define OTGFS_HPTXFSIZ_PTXFD_SHIFT (16) /* Bits 16-31: Host periodic TxFIFO depth */ +#define OTGFS_HPTXFSIZ_PTXFD_MASK (0xffff << OTGFS_HPTXFSIZ_PTXFD_SHIFT) + +/* Device IN endpoint transmit FIFOn size register */ + +#define OTGFS_DIEPTXF_INEPTXSA_SHIFT (0) /* Bits 0-15: IN endpoint FIFOx transmit RAM start address */ +#define OTGFS_DIEPTXF_INEPTXSA_MASK (0xffff << OTGFS_DIEPTXF_INEPTXSA_SHIFT) +#define OTGFS_DIEPTXF_INEPTXFD_SHIFT (16) /* Bits 16-31: IN endpoint TxFIFO depth */ +#define OTGFS_DIEPTXF_INEPTXFD_MASK (0xffff << OTGFS_DIEPTXF_INEPTXFD_SHIFT) +# define OTGFS_DIEPTXF_INEPTXFD_MIN (16 << OTGFS_DIEPTXF_INEPTXFD_MASK) + +/* Host-mode control and status registers */ + +/* Host configuration register */ + +#define OTGFS_HCFG_FSLSPCS_SHIFT (0) /* Bits 0-1: FS/LS PHY clock select */ +#define OTGFS_HCFG_FSLSPCS_MASK (3 << OTGFS_HCFG_FSLSPCS_SHIFT) +# define OTGFS_HCFG_FSLSPCS_FS48MHz (1 << OTGFS_HCFG_FSLSPCS_SHIFT) /* FS host mode, PHY clock is running at 48 MHz */ +# define OTGFS_HCFG_FSLSPCS_LS48MHz (1 << OTGFS_HCFG_FSLSPCS_SHIFT) /* LS host mode, Select 48 MHz PHY clock frequency */ +# define OTGFS_HCFG_FSLSPCS_LS6MHz (2 << OTGFS_HCFG_FSLSPCS_SHIFT) /* LS host mode, Select 6 MHz PHY clock frequency */ +#define OTGFS_HCFG_FSLSS (1 << 2) /* Bit 2: FS- and LS-only support */ + /* Bits 31:3 Reserved, must be kept at reset value */ +/* Host frame interval register */ + +#define OTGFS_HFIR_MASK (0xffff) + +/* Host frame number/frame time remaining register */ + +#define OTGFS_HFNUM_FRNUM_SHIFT (0) /* Bits 0-15: Frame number */ +#define OTGFS_HFNUM_FRNUM_MASK (0xffff << OTGFS_HFNUM_FRNUM_SHIFT) +#define OTGFS_HFNUM_FTREM_SHIFT (16) /* Bits 16-31: Frame time remaining */ +#define OTGFS_HFNUM_FTREM_MASK (0xffff << OTGFS_HFNUM_FTREM_SHIFT) + +/* Host periodic transmit FIFO/queue status register */ + +#define OTGFS_HPTXSTS_PTXFSAVL_SHIFT (0) /* Bits 0-15: Periodic transmit data FIFO space available */ +#define OTGFS_HPTXSTS_PTXFSAVL_MASK (0xffff << OTGFS_HPTXSTS_PTXFSAVL_SHIFT) +# define OTGFS_HPTXSTS_PTXFSAVL_FULL (0 << OTGFS_HPTXSTS_PTXFSAVL_SHIFT) +#define OTGFS_HPTXSTS_PTXQSAV_SHIFT (16) /* Bits 16-23: Periodic transmit request queue space available */ +#define OTGFS_HPTXSTS_PTXQSAV_MASK (0xff << OTGFS_HPTXSTS_PTXQSAV_SHIFT) +# define OTGFS_HPTXSTS_PTXQSAV_FULL (0 << OTGFS_HPTXSTS_PTXQSAV_SHIFT) +#define OTGFS_HPTXSTS_PTXQTOP_SHIFT (24) /* Bits 24-31: Top of the periodic transmit request queue */ +#define OTGFS_HPTXSTS_PTXQTOP_MASK (0x7f << OTGFS_HPTXSTS_PTXQTOP_SHIFT) +# define OTGFS_HPTXSTS_TERMINATE (1 << 24) /* Bit 24: Terminate (last entry for selected channel/endpoint) */ +# define OTGFS_HPTXSTS_TYPE_SHIFT (25) /* Bits 25-26: Type */ +# define OTGFS_HPTXSTS_TYPE_MASK (3 << OTGFS_HPTXSTS_TYPE_SHIFT) +# define OTGFS_HPTXSTS_TYPE_INOUT (0 << OTGFS_HPTXSTS_TYPE_SHIFT) /* IN/OUT token */ +# define OTGFS_HPTXSTS_TYPE_ZLP (1 << OTGFS_HPTXSTS_TYPE_SHIFT) /* Zero-length transmit packet */ +# define OTGFS_HPTXSTS_TYPE_HALT (3 << OTGFS_HPTXSTS_TYPE_SHIFT) /* Disable channel command */ +# define OTGFS_HPTXSTS_EPNUM_SHIFT (27) /* Bits 27-30: Endpoint number */ +# define OTGFS_HPTXSTS_EPNUM_MASK (15 << OTGFS_HPTXSTS_EPNUM_SHIFT) +# define OTGFS_HPTXSTS_ODD (1 << 24) /* Bit 31: Send in odd (vs even) frame */ + +/* Host all channels interrupt and all channels interrupt mask registers */ + +#define OTGFS_HAINT(n) (1 << (n)) /* Bits 15:0 HAINTM: Channel interrupt */ + +/* Host port control and status register */ + +#define OTGFS_HPRT_PCSTS (1 << 0) /* Bit 0: Port connect status */ +#define OTGFS_HPRT_PCDET (1 << 1) /* Bit 1: Port connect detected */ +#define OTGFS_HPRT_PENA (1 << 2) /* Bit 2: Port enable */ +#define OTGFS_HPRT_PENCHNG (1 << 3) /* Bit 3: Port enable/disable change */ +#define OTGFS_HPRT_POCA (1 << 4) /* Bit 4: Port overcurrent active */ +#define OTGFS_HPRT_POCCHNG (1 << 5) /* Bit 5: Port overcurrent change */ +#define OTGFS_HPRT_PRES (1 << 6) /* Bit 6: Port resume */ +#define OTGFS_HPRT_PSUSP (1 << 7) /* Bit 7: Port suspend */ +#define OTGFS_HPRT_PRST (1 << 8) /* Bit 8: Port reset */ + /* Bit 9: Reserved, must be kept at reset value */ +#define OTGFS_HPRT_PLSTS_SHIFT (10) /* Bits 10-11: Port line status */ +#define OTGFS_HPRT_PLSTS_MASK (3 << OTGFS_HPRT_PLSTS_SHIFT) +# define OTGFS_HPRT_PLSTS_DP (1 << 10) /* Bit 10: Logic level of OTG_FS_FS_DP */ +# define OTGFS_HPRT_PLSTS_DM (1 << 11) /* Bit 11: Logic level of OTG_FS_FS_DM */ +#define OTGFS_HPRT_PPWR (1 << 12) /* Bit 12: Port power */ +#define OTGFS_HPRT_PTCTL_SHIFT (13) /* Bits 13-16: Port test control */ +#define OTGFS_HPRT_PTCTL_MASK (15 << OTGFS_HPRT_PTCTL_SHIFT) +# define OTGFS_HPRT_PTCTL_DISABLED (0 << OTGFS_HPRT_PTCTL_SHIFT) /* Test mode disabled */ +# define OTGFS_HPRT_PTCTL_J (1 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_J mode */ +# define OTGFS_HPRT_PTCTL_L (2 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_K mode */ +# define OTGFS_HPRT_PTCTL_SE0_NAK (3 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_SE0_NAK mode */ +# define OTGFS_HPRT_PTCTL_PACKET (4 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_Packet mode */ +# define OTGFS_HPRT_PTCTL_FORCE (5 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_Force_Enable */ +#define OTGFS_HPRT_PSPD_SHIFT (17) /* Bits 17-18: Port speed */ +#define OTGFS_HPRT_PSPD_MASK (3 << OTGFS_HPRT_PSPD_SHIFT) +# define OTGFS_HPRT_PSPD_FS (1 << OTGFS_HPRT_PSPD_SHIFT) /* Full speed */ +# define OTGFS_HPRT_PSPD_LS (2 << OTGFS_HPRT_PSPD_SHIFT) /* Low speed */ + /* Bits 19-31: Reserved, must be kept at reset value */ + +/* Host channel-n characteristics register */ + +#define OTGFS_HCCHAR0_MPSIZ_SHIFT (0) /* Bits 0-10: Maximum packet size */ +#define OTGFS_HCCHAR_MPSIZ_MASK (0x7ff << OTGFS_HCCHAR_MPSIZ_SHIFT) +#define OTGFS_HCCHAR_EPNUM_SHIFT (11) /* Bits 11-14: Endpoint number */ +#define OTGFS_HCCHAR_EPNUM_MASK (15 << OTGFS_HCCHAR_EPNUM_SHIFT) +#define OTGFS_HCCHAR_EPDIR (1 << 15) /* Bit 15: Endpoint direction */ +# define OTGFS_HCCHAR_EPDIR_OUT (0) +# define OTGFS_HCCHAR_EPDIR_IN OTGFS_HCCHAR_EPDIR + /* Bit 16 Reserved, must be kept at reset value */ +#define OTGFS_HCCHAR_LSDEV (1 << 17) /* Bit 17: Low-speed device */ +#define OTGFS_HCCHAR_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_HCCHAR_EPTYP_MASK (3 << OTGFS_HCCHAR_EPTYP_SHIFT) +# define OTGFS_HCCHAR_EPTYP_CTRL (0 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Control */ +# define OTGFS_HCCHAR_EPTYP_ISOC (1 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Isochronous */ +# define OTGFS_HCCHAR_EPTYP_BULK (2 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Bulk */ +# define OTGFS_HCCHAR_EPTYP_INTR (3 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Interrupt */ +#define OTGFS_HCCHAR_MCNT_SHIFT (20) /* Bits 20-21: Multicount */ +#define OTGFS_HCCHAR_MCNT_MASK (3 << OTGFS_HCCHAR_MCNT_SHIFT) +#define OTGFS_HCCHAR_DAD_SHIFT (22) /* Bits 22-28: Device address */ +#define OTGFS_HCCHAR_DAD_MASK (0x7f << OTGFS_HCCHAR_DAD_SHIFT) +#define OTGFS_HCCHAR_ODDFRM (1 << 29) /* Bit 29: Odd frame */ +#define OTGFS_HCCHAR_CHDIS (1 << 30) /* Bit 30: Channel disable */ +#define OTGFS_HCCHAR_CHENA (1 << 31) /* Bit 31: Channel enable */ + +/* Host channel-n interrupt and Host channel-0 interrupt mask registers */ + +#define OTGFS_HCINT_XFRC (1 << 0) /* Bit 0: Transfer completed */ +#define OTGFS_HCINT_CHH (1 << 1) /* Bit 1: Channel halted */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_HCINT_STALL (1 << 3) /* Bit 3: STALL response received interrupt */ +#define OTGFS_HCINT_NAK (1 << 4) /* Bit 4: NAK response received interrupt */ +#define OTGFS_HCINT_ACK (1 << 5) /* Bit 5: ACK response received/transmitted interrupt */ +#define OTGFS_HCINTMSK_NYET (1 << 6) /* Bit 6: response received interrupt mask */ +#define OTGFS_HCINT_TXERR (1 << 7) /* Bit 7: Transaction error */ +#define OTGFS_HCINT_BBERR (1 << 8) /* Bit 8: Babble error */ +#define OTGFS_HCINT_FRMOR (1 << 9) /* Bit 9: Frame overrun */ +#define OTGFS_HCINT_DTERR (1 << 10) /* Bit 10: Data toggle error */ + /* Bits 11-31 Reserved, must be kept at reset value */ +/* Host channel-n interrupt register */ + +#define OTGFS_HCTSIZ_XFRSIZ_SHIFT (0) /* Bits 0-18: Transfer size */ +#define OTGFS_HCTSIZ_XFRSIZ_MASK (0x7ffff << OTGFS_HCTSIZ_XFRSIZ_SHIFT) +#define OTGFS_HCTSIZ_PKTCNT_SHIFT (19) /* Bits 19-28: Packet count */ +#define OTGFS_HCTSIZ_PKTCNT_MASK (0x3ff << OTGFS_HCTSIZ_PKTCNT_SHIFT) +#define OTGFS_HCTSIZ_DPID_SHIFT (29) /* Bits 29-30: Data PID */ +#define OTGFS_HCTSIZ_DPID_MASK (3 << OTGFS_HCTSIZ_DPID_SHIFT) +# define OTGFS_HCTSIZ_DPID_DATA0 (0 << OTGFS_HCTSIZ_DPID_SHIFT) +# define OTGFS_HCTSIZ_DPID_DATA2 (1 << OTGFS_HCTSIZ_DPID_SHIFT) +# define OTGFS_HCTSIZ_DPID_DATA1 (2 << OTGFS_HCTSIZ_DPID_SHIFT) +# define OTGFS_HCTSIZ_DPID_MDATA (3 << OTGFS_HCTSIZ_DPID_SHIFT) + /* Bit 31 Reserved, must be kept at reset value */ +/* Device-mode control and status registers */ + +/* Device configuration register */ + +#define OTGFS_DCFG_DSPD_SHIFT (0) /* Bits 0-1: Device speed */ +#define OTGFS_DCFG_DSPD_MASK (3 << OTGFS_DCFG_DSPD_SHIFT) +# define OTGFS_DCFG_DSPD_FS (3 << OTGFS_DCFG_DSPD_SHIFT) /* Full speed */ +#define OTGFS_DCFG_NZLSOHSK (1 << 2) /* Bit 2: Non-zero-length status OUT handshake */ + /* Bit 3: Reserved, must be kept at reset value */ +#define OTGFS_DCFG_DAD_SHIFT (4) /* Bits 4-10: Device address */ +#define OTGFS_DCFG_DAD_MASK (0x7f << OTGFS_DCFG_DAD_SHIFT) +#define OTGFS_DCFG_PFIVL_SHIFT (11) /* Bits 11-12: Periodic frame interval */ +#define OTGFS_DCFG_PFIVL_MASK (3 << OTGFS_DCFG_PFIVL_SHIFT) +# define OTGFS_DCFG_PFIVL_80PCT (0 << OTGFS_DCFG_PFIVL_SHIFT) /* 80% of the frame interval */ +# define OTGFS_DCFG_PFIVL_85PCT (1 << OTGFS_DCFG_PFIVL_SHIFT) /* 85% of the frame interval */ +# define OTGFS_DCFG_PFIVL_90PCT (2 << OTGFS_DCFG_PFIVL_SHIFT) /* 90% of the frame interval */ +# define OTGFS_DCFG_PFIVL_95PCT (3 << OTGFS_DCFG_PFIVL_SHIFT) /* 95% of the frame interval */ + /* Bits 13-31 Reserved, must be kept at reset value */ +/* Device control register */ + +#define OTGFS_TESTMODE_DISABLED (0) /* Test mode disabled */ +#define OTGFS_TESTMODE_J (1) /* Test_J mode */ +#define OTGFS_TESTMODE_K (2) /* Test_K mode */ +#define OTGFS_TESTMODE_SE0_NAK (3) /* Test_SE0_NAK mode */ +#define OTGFS_TESTMODE_PACKET (4) /* Test_Packet mode */ +#define OTGFS_TESTMODE_FORCE (5) /* Test_Force_Enable */ + +#define OTGFS_DCTL_RWUSIG (1 << 0) /* Bit 0: Remote wakeup signaling */ +#define OTGFS_DCTL_SDIS (1 << 1) /* Bit 1: Soft disconnect */ +#define OTGFS_DCTL_GINSTS (1 << 2) /* Bit 2: Global IN NAK status */ +#define OTGFS_DCTL_GONSTS (1 << 3) /* Bit 3: Global OUT NAK status */ +#define OTGFS_DCTL_TCTL_SHIFT (4) /* Bits 4-6: Test control */ +#define OTGFS_DCTL_TCTL_MASK (7 << OTGFS_DCTL_TCTL_SHIFT) +# define OTGFS_DCTL_TCTL_DISABLED (0 << OTGFS_DCTL_TCTL_SHIFT) /* Test mode disabled */ +# define OTGFS_DCTL_TCTL_J (1 << OTGFS_DCTL_TCTL_SHIFT) /* Test_J mode */ +# define OTGFS_DCTL_TCTL_K (2 << OTGFS_DCTL_TCTL_SHIFT) /* Test_K mode */ +# define OTGFS_DCTL_TCTL_SE0_NAK (3 << OTGFS_DCTL_TCTL_SHIFT) /* Test_SE0_NAK mode */ +# define OTGFS_DCTL_TCTL_PACKET (4 << OTGFS_DCTL_TCTL_SHIFT) /* Test_Packet mode */ +# define OTGFS_DCTL_TCTL_FORCE (5 << OTGFS_DCTL_TCTL_SHIFT) /* Test_Force_Enable */ +#define OTGFS_DCTL_SGINAK (1 << 7) /* Bit 7: Set global IN NAK */ +#define OTGFS_DCTL_CGINAK (1 << 8) /* Bit 8: Clear global IN NAK */ +#define OTGFS_DCTL_SGONAK (1 << 9) /* Bit 9: Set global OUT NAK */ +#define OTGFS_DCTL_CGONAK (1 << 10) /* Bit 10: Clear global OUT NAK */ +#define OTGFS_DCTL_POPRGDNE (1 << 11) /* Bit 11: Power-on programming done */ + /* Bits 12-31: Reserved, must be kept at reset value */ +/* Device status register */ + +#define OTGFS_DSTS_SUSPSTS (1 << 0) /* Bit 0: Suspend status */ +#define OTGFS_DSTS_ENUMSPD_SHIFT (1) /* Bits 1-2: Enumerated speed */ +#define OTGFS_DSTS_ENUMSPD_MASK (3 << OTGFS_DSTS_ENUMSPD_SHIFT) +# define OTGFS_DSTS_ENUMSPD_FS (3 << OTGFS_DSTS_ENUMSPD_MASK) /* Full speed */ + /* Bits 4-7: Reserved, must be kept at reset value */ +#define OTGFS_DSTS_EERR (1 << 3) /* Bit 3: Erratic error */ +#define OTGFS_DSTS_SOFFN_SHIFT (8) /* Bits 8-21: Frame number of the received SOF */ +#define OTGFS_DSTS_SOFFN_MASK (0x3fff << OTGFS_DSTS_SOFFN_SHIFT) +#define OTGFS_DSTS_SOFFN0 (1 << 8) /* Bits 8: Frame number even/odd bit */ +#define OTGFS_DSTS_SOFFN_EVEN 0 +#define OTGFS_DSTS_SOFFN_ODD OTGFS_DSTS_SOFFN0 + /* Bits 22-31: Reserved, must be kept at reset value */ +/* Device IN endpoint common interrupt mask register */ + +#define OTGFS_DIEPMSK_XFRCM (1 << 0) /* Bit 0: Transfer completed interrupt mask */ +#define OTGFS_DIEPMSK_EPDM (1 << 1) /* Bit 1: Endpoint disabled interrupt mask */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_DIEPMSK_TOM (1 << 3) /* Bit 3: Timeout condition mask (Non-isochronous endpoints) */ +#define OTGFS_DIEPMSK_ITTXFEMSK (1 << 4) /* Bit 4: IN token received when TxFIFO empty mask */ +#define OTGFS_DIEPMSK_INEPNMM (1 << 5) /* Bit 5: IN token received with EP mismatch mask */ +#define OTGFS_DIEPMSK_INEPNEM (1 << 6) /* Bit 6: IN endpoint NAK effective mask */ + /* Bits 7-31: Reserved, must be kept at reset value */ +/* Device OUT endpoint common interrupt mask register */ + +#define OTGFS_DOEPMSK_XFRCM (1 << 0) /* Bit 0: Transfer completed interrupt mask */ +#define OTGFS_DOEPMSK_EPDM (1 << 1) /* Bit 1: Endpoint disabled interrupt mask */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_DOEPMSK_STUPM (1 << 3) /* Bit 3: SETUP phase done mask */ +#define OTGFS_DOEPMSK_OTEPDM (1 << 4) /* Bit 4: OUT token received when endpoint disabled mask */ + /* Bits 5-31: Reserved, must be kept at reset value */ +/* Device all endpoints interrupt and All endpoints interrupt mask registers */ + +#define OTGFS_DAINT_IEP_SHIFT (0) /* Bits 0-15: IN endpoint interrupt bits */ +#define OTGFS_DAINT_IEP_MASK (0xffff << OTGFS_DAINT_IEP_SHIFT) +# define OTGFS_DAINT_IEP(n) (1 << (n)) +#define OTGFS_DAINT_OEP_SHIFT (16) /* Bits 16-31: OUT endpoint interrupt bits */ +#define OTGFS_DAINT_OEP_MASK (0xffff << OTGFS_DAINT_OEP_SHIFT) +# define OTGFS_DAINT_OEP(n) (1 << ((n)+16)) + +/* Device VBUS discharge time register */ + +#define OTGFS_DVBUSDIS_MASK (0xffff) + +/* Device VBUS pulsing time register */ + +#define OTGFS_DVBUSPULSE_MASK (0xfff) + +/* Device IN endpoint FIFO empty interrupt mask register */ + +#define OTGFS_DIEPEMPMSK(n) (1 << (n)) + +/* Device control IN endpoint 0 control register */ + +#define OTGFS_DIEPCTL0_MPSIZ_SHIFT (0) /* Bits 0-1: Maximum packet size */ +#define OTGFS_DIEPCTL0_MPSIZ_MASK (3 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) +# define OTGFS_DIEPCTL0_MPSIZ_64 (0 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 64 bytes */ +# define OTGFS_DIEPCTL0_MPSIZ_32 (1 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 32 bytes */ +# define OTGFS_DIEPCTL0_MPSIZ_16 (2 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 16 bytes */ +# define OTGFS_DIEPCTL0_MPSIZ_8 (3 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 8 bytes */ + /* Bits 2-14: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL0_USBAEP (1 << 15) /* Bit 15: USB active endpoint */ + /* Bit 16: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL0_NAKSTS (1 << 17) /* Bit 17: NAK status */ +#define OTGFS_DIEPCTL0_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_DIEPCTL0_EPTYP_MASK (3 << OTGFS_DIEPCTL0_EPTYP_SHIFT) +# define OTGFS_DIEPCTL0_EPTYP_CTRL (0 << OTGFS_DIEPCTL0_EPTYP_SHIFT) /* Control (hard-coded) */ + /* Bit 20: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL0_STALL (1 << 21) /* Bit 21: STALL handshake */ +#define OTGFS_DIEPCTL0_TXFNUM_SHIFT (22) /* Bits 22-25: TxFIFO number */ +#define OTGFS_DIEPCTL0_TXFNUM_MASK (15 << OTGFS_DIEPCTL0_TXFNUM_SHIFT) +#define OTGFS_DIEPCTL0_CNAK (1 << 26) /* Bit 26: Clear NAK */ +#define OTGFS_DIEPCTL0_SNAK (1 << 27) /* Bit 27: Set NAK */ + /* Bits 28-29: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL0_EPDIS (1 << 30) /* Bit 30: Endpoint disable */ +#define OTGFS_DIEPCTL0_EPENA (1 << 31) /* Bit 31: Endpoint enable */ + +/* Device control IN endpoint n control register */ + +#define OTGFS_DIEPCTL_MPSIZ_SHIFT (0) /* Bits 0-10: Maximum packet size */ +#define OTGFS_DIEPCTL_MPSIZ_MASK (0x7ff << OTGFS_DIEPCTL_MPSIZ_SHIFT) + /* Bits 11-14: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL_USBAEP (1 << 15) /* Bit 15: USB active endpoint */ +#define OTGFS_DIEPCTL_EONUM (1 << 16) /* Bit 16: Even/odd frame */ +# define OTGFS_DIEPCTL_EVEN (0) +# define OTGFS_DIEPCTL_ODD OTGFS_DIEPCTL_EONUM +# define OTGFS_DIEPCTL_DATA0 (0) +# define OTGFS_DIEPCTL_DATA1 OTGFS_DIEPCTL_EONUM +#define OTGFS_DIEPCTL_NAKSTS (1 << 17) /* Bit 17: NAK status */ +#define OTGFS_DIEPCTL_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_DIEPCTL_EPTYP_MASK (3 << OTGFS_DIEPCTL_EPTYP_SHIFT) +# define OTGFS_DIEPCTL_EPTYP_CTRL (0 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Control */ +# define OTGFS_DIEPCTL_EPTYP_ISOC (1 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Isochronous */ +# define OTGFS_DIEPCTL_EPTYP_BULK (2 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Bulk */ +# define OTGFS_DIEPCTL_EPTYP_INTR (3 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Interrupt */ + /* Bit 20: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL_STALL (1 << 21) /* Bit 21: STALL handshake */ +#define OTGFS_DIEPCTL_TXFNUM_SHIFT (22) /* Bits 22-25: TxFIFO number */ +#define OTGFS_DIEPCTL_TXFNUM_MASK (15 << OTGFS_DIEPCTL_TXFNUM_SHIFT) +#define OTGFS_DIEPCTL_CNAK (1 << 26) /* Bit 26: Clear NAK */ +#define OTGFS_DIEPCTL_SNAK (1 << 27) /* Bit 27: Set NAK */ +#define OTGFS_DIEPCTL_SD0PID (1 << 28) /* Bit 28: Set DATA0 PID (interrupt/bulk) */ +#define OTGFS_DIEPCTL_SEVNFRM (1 << 28) /* Bit 28: Set even frame (isochronous)) */ +#define OTGFS_DIEPCTL_SODDFRM (1 << 29) /* Bit 29: Set odd frame (isochronous) */ +#define OTGFS_DIEPCTL_EPDIS (1 << 30) /* Bit 30: Endpoint disable */ +#define OTGFS_DIEPCTL_EPENA (1 << 31) /* Bit 31: Endpoint enable */ + +/* Device endpoint-n interrupt register */ + +#define OTGFS_DIEPINT_XFRC (1 << 0) /* Bit 0: Transfer completed interrupt */ +#define OTGFS_DIEPINT_EPDISD (1 << 1) /* Bit 1: Endpoint disabled interrupt */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_DIEPINT_TOC (1 << 3) /* Bit 3: Timeout condition */ +#define OTGFS_DIEPINT_ITTXFE (1 << 4) /* Bit 4: IN token received when TxFIFO is empty */ + /* Bit 5: Reserved, must be kept at reset value */ +#define OTGFS_DIEPINT_INEPNE (1 << 6) /* Bit 6: IN endpoint NAK effective */ +#define OTGFS_DIEPINT_TXFE (1 << 7) /* Bit 7: Transmit FIFO empty */ + /* Bits 8-31: Reserved, must be kept at reset value */ +/* Device IN endpoint 0 transfer size register */ + +#define OTGFS_DIEPTSIZ0_XFRSIZ_SHIFT (0) /* Bits 0-6: Transfer size */ +#define OTGFS_DIEPTSIZ0_XFRSIZ_MASK (0x7f << OTGFS_DIEPTSIZ0_XFRSIZ_SHIFT) + /* Bits 7-18: Reserved, must be kept at reset value */ +#define OTGFS_DIEPTSIZ0_PKTCNT_SHIFT (19) /* Bits 19-20: Packet count */ +#define OTGFS_DIEPTSIZ0_PKTCNT_MASK (3 << OTGFS_DIEPTSIZ0_PKTCNT_SHIFT) + /* Bits 21-31: Reserved, must be kept at reset value */ +/* Device IN endpoint n transfer size register */ + +#define OTGFS_DIEPTSIZ_XFRSIZ_SHIFT (0) /* Bits 0-18: Transfer size */ +#define OTGFS_DIEPTSIZ_XFRSIZ_MASK (0x7ffff << OTGFS_DIEPTSIZ_XFRSIZ_SHIFT) +#define OTGFS_DIEPTSIZ_PKTCNT_SHIFT (19) /* Bit 19-28: Packet count */ +#define OTGFS_DIEPTSIZ_PKTCNT_MASK (0x3ff << OTGFS_DIEPTSIZ_PKTCNT_SHIFT) +#define OTGFS_DIEPTSIZ_MCNT_SHIFT (29) /* Bits 29-30: Multi count */ +#define OTGFS_DIEPTSIZ_MCNT_MASK (3 << OTGFS_DIEPTSIZ_MCNT_SHIFT) + /* Bit 31: Reserved, must be kept at reset value */ +/* Device OUT endpoint TxFIFO status register */ + +#define OTGFS_DTXFSTS_MASK (0xffff) + +/* Device OUT endpoint 0 control register */ + +#define OTGFS_DOEPCTL0_MPSIZ_SHIFT (0) /* Bits 0-1: Maximum packet size */ +#define OTGFS_DOEPCTL0_MPSIZ_MASK (3 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) +# define OTGFS_DOEPCTL0_MPSIZ_64 (0 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 64 bytes */ +# define OTGFS_DOEPCTL0_MPSIZ_32 (1 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 32 bytes */ +# define OTGFS_DOEPCTL0_MPSIZ_16 (2 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 16 bytes */ +# define OTGFS_DOEPCTL0_MPSIZ_8 (3 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 8 bytes */ + /* Bits 2-14: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL0_USBAEP (1 << 15) /* Bit 15: USB active endpoint */ + /* Bit 16: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL0_NAKSTS (1 << 17) /* Bit 17: NAK status */ +#define OTGFS_DOEPCTL0_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_DOEPCTL0_EPTYP_MASK (3 << OTGFS_DOEPCTL0_EPTYP_SHIFT) +# define OTGFS_DOEPCTL0_EPTYP_CTRL (0 << OTGFS_DOEPCTL0_EPTYP_SHIFT) /* Control (hard-coded) */ +#define OTGFS_DOEPCTL0_SNPM (1 << 20) /* Bit 20: Snoop mode */ +#define OTGFS_DOEPCTL0_STALL (1 << 21) /* Bit 21: STALL handshake */ + /* Bits 22-25: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL0_CNAK (1 << 26) /* Bit 26: Clear NAK */ +#define OTGFS_DOEPCTL0_SNAK (1 << 27) /* Bit 27: Set NAK */ + /* Bits 28-29: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL0_EPDIS (1 << 30) /* Bit 30: Endpoint disable */ +#define OTGFS_DOEPCTL0_EPENA (1 << 31) /* Bit 31: Endpoint enable */ + +/* Device OUT endpoint n control register */ + +#define OTGFS_DOEPCTL_MPSIZ_SHIFT (0) /* Bits 0-10: Maximum packet size */ +#define OTGFS_DOEPCTL_MPSIZ_MASK (0x7ff << OTGFS_DOEPCTL_MPSIZ_SHIFT) + /* Bits 11-14: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL_USBAEP (1 << 15) /* Bit 15: USB active endpoint */ +#define OTGFS_DOEPCTL_DPID (1 << 16) /* Bit 16: Endpoint data PID (interrupt/buld) */ +# define OTGFS_DOEPCTL_DATA0 (0) +# define OTGFS_DOEPCTL_DATA1 OTGFS_DOEPCTL_DPID +#define OTGFS_DOEPCTL_EONUM (1 << 16) /* Bit 16: Even/odd frame (isochronous) */ +# define OTGFS_DOEPCTL_EVEN (0) +# define OTGFS_DOEPCTL_ODD OTGFS_DOEPCTL_EONUM +#define OTGFS_DOEPCTL_NAKSTS (1 << 17) /* Bit 17: NAK status */ +#define OTGFS_DOEPCTL_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_DOEPCTL_EPTYP_MASK (3 << OTGFS_DOEPCTL_EPTYP_SHIFT) +# define OTGFS_DOEPCTL_EPTYP_CTRL (0 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Control */ +# define OTGFS_DOEPCTL_EPTYP_ISOC (1 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Isochronous */ +# define OTGFS_DOEPCTL_EPTYP_BULK (2 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Bulk */ +# define OTGFS_DOEPCTL_EPTYP_INTR (3 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Interrupt */ +#define OTGFS_DOEPCTL_SNPM (1 << 20) /* Bit 20: Snoop mode */ +#define OTGFS_DOEPCTL_STALL (1 << 21) /* Bit 21: STALL handshake */ + /* Bits 22-25: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL_CNAK (1 << 26) /* Bit 26: Clear NAK */ +#define OTGFS_DOEPCTL_SNAK (1 << 27) /* Bit 27: Set NAK */ +#define OTGFS_DOEPCTL_SD0PID (1 << 28) /* Bit 28: Set DATA0 PID (interrupt/bulk) */ +#define OTGFS_DOEPCTL_SEVNFRM (1 << 28) /* Bit 28: Set even frame (isochronous) */ +#define OTGFS_DOEPCTL_SD1PID (1 << 29) /* Bit 29: Set DATA1 PID (interrupt/bulk) */ +#define OTGFS_DOEPCTL_SODDFRM (1 << 29) /* Bit 29: Set odd frame (isochronous */ +#define OTGFS_DOEPCTL_EPDIS (1 << 30) /* Bit 30: Endpoint disable */ +#define OTGFS_DOEPCTL_EPENA (1 << 31) /* Bit 31: Endpoint enable */ + +/* Device endpoint-n interrupt register */ + +#define OTGFS_DOEPINT_XFRC (1 << 0) /* Bit 0: Transfer completed interrupt */ +#define OTGFS_DOEPINT_EPDISD (1 << 1) /* Bit 1: Endpoint disabled interrupt */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_DOEPINT_SETUP (1 << 3) /* Bit 3: SETUP phase done */ +#define OTGFS_DOEPINT_OTEPDIS (1 << 4) /* Bit 4: OUT token received when endpoint disabled */ + /* Bit 5: Reserved, must be kept at reset value */ +#define OTGFS_DOEPINT_B2BSTUP (1 << 6) /* Bit 6: Back-to-back SETUP packets received */ + /* Bits 7-31: Reserved, must be kept at reset value */ +/* Device OUT endpoint-0 transfer size register */ + +#define OTGFS_DOEPTSIZ0_XFRSIZ_SHIFT (0) /* Bits 0-6: Transfer size */ +#define OTGFS_DOEPTSIZ0_XFRSIZ_MASK (0x7f << OTGFS_DOEPTSIZ0_XFRSIZ_SHIFT) + /* Bits 7-18: Reserved, must be kept at reset value */ +#define OTGFS_DOEPTSIZ0_PKTCNT (1 << 19) /* Bit 19 PKTCNT: Packet count */ + /* Bits 20-28: Reserved, must be kept at reset value */ +#define OTGFS_DOEPTSIZ0_STUPCNT_SHIFT (29) /* Bits 29-30: SETUP packet count */ +#define OTGFS_DOEPTSIZ0_STUPCNT_MASK (3 << OTGFS_DOEPTSIZ0_STUPCNT_SHIFT) + /* Bit 31: Reserved, must be kept at reset value */ +/* Device OUT endpoint-n transfer size register */ + +#define OTGFS_DOEPTSIZ_XFRSIZ_SHIFT (0) /* Bits 0-18: Transfer size */ +#define OTGFS_DOEPTSIZ_XFRSIZ_MASK (0x7ffff << OTGFS_DOEPTSIZ_XFRSIZ_SHIFT) +#define OTGFS_DOEPTSIZ_PKTCNT_SHIFT (19) /* Bit 19-28: Packet count */ +#define OTGFS_DOEPTSIZ_PKTCNT_MASK (0x3ff << OTGFS_DOEPTSIZ_PKTCNT_SHIFT) +#define OTGFS_DOEPTSIZ_STUPCNT_SHIFT (29) /* Bits 29-30: SETUP packet count */ +#define OTGFS_DOEPTSIZ_STUPCNT_MASK (3 << OTGFS_DOEPTSIZ_STUPCNT_SHIFT) +#define OTGFS_DOEPTSIZ_RXDPID_SHIFT (29) /* Bits 29-30: Received data PID */ +#define OTGFS_DOEPTSIZ_RXDPID_MASK (3 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) +# define OTGFS_DOEPTSIZ_RXDPID_DATA0 (0 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) +# define OTGFS_DOEPTSIZ_RXDPID_DATA2 (1 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) +# define OTGFS_DOEPTSIZ_RXDPID_DATA1 (2 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) +# define OTGFS_DOEPTSIZ_RXDPID_MDATA (3 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) + /* Bit 31: Reserved, must be kept at reset value */ +/* Power and clock gating registers */ + +/* Power and clock gating control register */ + +#define OTGFS_PCGCCTL_STPPCLK (1 << 0) /* Bit 0: Stop PHY clock */ +#define OTGFS_PCGCCTL_GATEHCLK (1 << 1) /* Bit 1: Gate HCLK */ + /* Bits 2-3: Reserved, must be kept at reset value */ +#define OTGFS_PCGCCTL_PHYSUSP (1 << 4) /* Bit 4: PHY Suspended */ + /* Bits 5-31: Reserved, must be kept at reset value */ + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_OTGFS_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_pwr.h b/nuttx/arch/arm/src/stm32/chip/stm32_pwr.h new file mode 100644 index 0000000000..2ece6a3572 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_pwr.h @@ -0,0 +1,103 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_pwr.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_PWR_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_PWR_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include "chip.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +#define STM32_PWR_CR_OFFSET 0x0000 /* Power control register */ +#define STM32_PWR_CSR_OFFSET 0x0004 /* Power control/status register */ + +/* Register Addresses ***************************************************************/ + +#define STM32_PWR_CR (STM32_PWR_BASE+STM32_PWR_CR_OFFSET) +#define STM32_PWR_CSR (STM32_PWR_BASE+STM32_PWR_CSR_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +/* Power control register */ + +#define PWR_CR_LPDS (1 << 0) /* Bit 0: Low-Power Deepsleep */ +#define PWR_CR_PDDS (1 << 1) /* Bit 1: Power Down Deepsleep */ +#define PWR_CR_CWUF (1 << 2) /* Bit 2: Clear Wakeup Flag */ +#define PWR_CR_CSBF (1 << 3) /* Bit 3: Clear Standby Flag */ +#define PWR_CR_PVDE (1 << 4) /* Bit 4: Power Voltage Detector Enable */ +#define PWR_CR_PLS_SHIFT (5) /* Bits 7-5: PVD Level Selection */ +#define PWR_CR_PLS_MASK (7 << PWR_CR_PLS_SHIFT) +# define PWR_CR_2p2V (0 << PWR_CR_PLS_SHIFT) /* 000: 2.2V */ +# define PWR_CR_2p3V (1 << PWR_CR_PLS_SHIFT) /* 001: 2.3V */ +# define PWR_CR_2p4V (2 << PWR_CR_PLS_SHIFT) /* 010: 2.4V */ +# define PWR_CR_2p5V (3 << PWR_CR_PLS_SHIFT) /* 011: 2.5V */ +# define PWR_CR_2p6V (4 << PWR_CR_PLS_SHIFT) /* 100: 2.6V */ +# define PWR_CR_2p7V (5 << PWR_CR_PLS_SHIFT) /* 101: 2.7V */ +# define PWR_CR_2p8V (6 << PWR_CR_PLS_SHIFT) /* 110: 2.8V */ +# define PWR_CR_2p9V (7 << PWR_CR_PLS_SHIFT) /* 111: 2.9V */ +#define PWR_CR_DBP (1 << 8) /* Bit 8: Disable Backup Domain write protection */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define PWR_CR_FPDS (1 << 9) /* Bit 9: Flash power down in Stop mode */ +# define PWR_CR_VOS (1 << 14) /* Bit 14: Regulator voltage scaling output selection */ +#endif + +/* Power control/status register */ + +#define PWR_CSR_WUF (1 << 0) /* Bit 0: Wakeup Flag */ +#define PWR_CSR_SBF (1 << 1) /* Bit 1: Standby Flag */ +#define PWR_CSR_PVDO (1 << 2) /* Bit 2: PVD Output */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define PWR_CSR_BRR (1 << 3) /* Bit 3: Backup regulator ready */ +#endif + +#define PWR_CSR_EWUP (1 << 8) /* Bit 8: Enable WKUP pin */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define PWR_CSR_BRE (1 << 9) /* Bit 9: Backup regulator enable */ +# define PWR_CSR_VOSRDY (1 << 14) /* Bit 14: Regulator voltage scaling output selection ready bite */ +#endif + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_PWR_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_sdio.h b/nuttx/arch/arm/src/stm32/chip/stm32_sdio.h new file mode 100644 index 0000000000..d2af8a32cc --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_sdio.h @@ -0,0 +1,291 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_sdio.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_SDIO_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_SDIO_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +#define STM32_SDIO_POWER_OFFSET 0x0000 /* SDIO power control register */ +#define STM32_SDIO_CLKCR_OFFSET 0x0004 /* SDI clock control register */ +#define STM32_SDIO_ARG_OFFSET 0x0008 /* SDIO argument register */ +#define STM32_SDIO_CMD_OFFSET 0x000c /* SDIO command register */ +#define STM32_SDIO_RESPCMD_OFFSET 0x0010 /* SDIO command response register */ +#define STM32_SDIO_RESP_OFFSET(n) (0x0010+4*(n)) +#define STM32_SDIO_RESP1_OFFSET 0x0014 /* SDIO response 1 register */ +#define STM32_SDIO_RESP2_OFFSET 0x0018 /* SDIO response 2 register */ +#define STM32_SDIO_RESP3_OFFSET 0x001c /* SDIO response 3 register */ +#define STM32_SDIO_RESP4_OFFSET 0x0020 /* SDIO response 4 register */ +#define STM32_SDIO_DTIMER_OFFSET 0x0024 /* SDIO data timer register */ +#define STM32_SDIO_DLEN_OFFSET 0x0028 /* SDIO data length register */ +#define STM32_SDIO_DCTRL_OFFSET 0x002c /* SDIO data control register */ +#define STM32_SDIO_DCOUNT_OFFSET 0x0030 /* SDIO data counter register */ +#define STM32_SDIO_STA_OFFSET 0x0034 /* SDIO status register */ +#define STM32_SDIO_ICR_OFFSET 0x0038 /* SDIO interrupt clear register */ +#define STM32_SDIO_MASK_OFFSET 0x003c /* SDIO mask register */ +#define STM32_SDIO_FIFOCNT_OFFSET 0x0048 /* SDIO FIFO counter register */ +#define STM32_SDIO_FIFO_OFFSET 0x0080 /* SDIO data FIFO register */ + +/* Register Addresses ***************************************************************/ + +#define STM32_SDIO_POWER (STM32_SDIO_BASE+STM32_SDIO_POWER_OFFSET) +#define STM32_SDIO_CLKCR (STM32_SDIO_BASE+STM32_SDIO_CLKCR_OFFSET) +#define STM32_SDIO_ARG (STM32_SDIO_BASE+STM32_SDIO_ARG_OFFSET) +#define STM32_SDIO_CMD (STM32_SDIO_BASE+STM32_SDIO_CMD_OFFSET) +#define STM32_SDIO_RESPCMD (STM32_SDIO_BASE+STM32_SDIO_RESPCMD_OFFSET) +#define STM32_SDIO_RESP(n) (STM32_SDIO_BASE+STM32_SDIO_RESP_OFFSET(n)) +#define STM32_SDIO_RESP1 (STM32_SDIO_BASE+STM32_SDIO_RESP1_OFFSET) +#define STM32_SDIO_RESP2 (STM32_SDIO_BASE+STM32_SDIO_RESP2_OFFSET) +#define STM32_SDIO_RESP3 (STM32_SDIO_BASE+STM32_SDIO_RESP3_OFFSET) +#define STM32_SDIO_RESP4 (STM32_SDIO_BASE+STM32_SDIO_RESP4_OFFSET) +#define STM32_SDIO_DTIMER (STM32_SDIO_BASE+STM32_SDIO_DTIMER_OFFSET) +#define STM32_SDIO_DLEN (STM32_SDIO_BASE+STM32_SDIO_DLEN_OFFSET) +#define STM32_SDIO_DCTRL (STM32_SDIO_BASE+STM32_SDIO_DCTRL_OFFSET) +#define STM32_SDIO_DCOUNT (STM32_SDIO_BASE+STM32_SDIO_DCOUNT_OFFSET) +#define STM32_SDIO_STA (STM32_SDIO_BASE+STM32_SDIO_STA_OFFSET) +#define STM32_SDIO_ICR (STM32_SDIO_BASE+STM32_SDIO_ICR_OFFSET) +#define STM32_SDIO_MASK (STM32_SDIO_BASE+STM32_SDIO_MASK_OFFSET) +#define STM32_SDIO_FIFOCNT (STM32_SDIO_BASE+STM32_SDIO_FIFOCNT_OFFSET) +#define STM32_SDIO_FIFO (STM32_SDIO_BASE+STM32_SDIO_FIFO_OFFSET) + +/* Bit-band (BB) base addresses ****************************************************/ + +#define STM32_SDIO_OFFSET (STM32_SDIO_BASE-STM32_PERIPH_BASE) + +#define STM32_SDIO_POWER_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_POWER_OFFSET)<<5)) +#define STM32_SDIO_CLKCR_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_CLKCR_OFFSET)<<5)) +#define STM32_SDIO_ARG_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_ARG_OFFSET)<<5)) +#define STM32_SDIO_CMD_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_CMD_OFFSET)<<5)) +#define STM32_SDIO_RESPCMD_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_RESPCMD_OFFSET)<<5)) +#define STM32_SDIO_RESP_BB(n) (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_RESP_OFFSET(n))<<5)) +#define STM32_SDIO_RESP1_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_RESP1_OFFSET)<<5)) +#define STM32_SDIO_RESP2_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_RESP2_OFFSET)<<5)) +#define STM32_SDIO_RESP3_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_RESP3_OFFSET)<<5)) +#define STM32_SDIO_RESP4_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_RESP4_OFFSET)<<5)) +#define STM32_SDIO_DTIMER_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_DTIMER_OFFSET)<<5)) +#define STM32_SDIO_DLEN_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_DLEN_OFFSET)<<5)) +#define STM32_SDIO_DCTRL_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_DCTRL_OFFSET)<<5)) +#define STM32_SDIO_DCOUNT_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_DCOUNT_OFFSET)<<5)) +#define STM32_SDIO_STA_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_STA_OFFSET)<<5)) +#define STM32_SDIO_ICR_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_ICR_OFFSET)<<5)) +#define STM32_SDIO_MASK_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_MASK_OFFSET)<<5)) +#define STM32_SDIO_FIFOCNT_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_FIFOCNT_OFFSET)<<5)) +#define STM32_SDIO_FIFO_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_FIFO_OFFSET)<<5)) + +/* Register Bitfield Definitions ****************************************************/ + +#define SDIO_POWER_PWRCTRL_SHIFT (0) /* Bits 0-1: Power supply control bits */ +#define SDIO_POWER_PWRCTRL_MASK (3 << SDIO_POWER_PWRCTRL_SHIFT) +# define SDIO_POWER_PWRCTRL_OFF (0 << SDIO_POWER_PWRCTRL_SHIFT) /* 00: Power-off: card clock stopped */ +# define SDIO_POWER_PWRCTRL_PWRUP (2 << SDIO_POWER_PWRCTRL_SHIFT) /* 10: Reserved power-up */ +# define SDIO_POWER_PWRCTRL_ON (3 << SDIO_POWER_PWRCTRL_SHIFT) /* 11: Power-on: card is clocked */ + +#define SDIO_POWER_RESET (0) /* Reset value */ + +#define SDIO_CLKCR_CLKDIV_SHIFT (0) /* Bits 7-0: Clock divide factor */ +#define SDIO_CLKCR_CLKDIV_MASK (0xff << SDIO_CLKCR_CLKDIV_SHIFT) +#define SDIO_CLKCR_CLKEN (1 << 8) /* Bit 8: Clock enable bit */ +#define SDIO_CLKCR_PWRSAV (1 << 9) /* Bit 9: Power saving configuration bit */ +#define SDIO_CLKCR_BYPASS (1 << 10) /* Bit 10: Clock divider bypass enable bit */ +#define SDIO_CLKCR_WIDBUS_SHIFT (11) /* Bits 12-11: Wide bus mode enable bits */ +#define SDIO_CLKCR_WIDBUS_MASK (3 << SDIO_CLKCR_WIDBUS_SHIFT) +# define SDIO_CLKCR_WIDBUS_D1 (0 << SDIO_CLKCR_WIDBUS_SHIFT) /* 00: Default (SDIO_D0) */ +# define SDIO_CLKCR_WIDBUS_D4 (1 << SDIO_CLKCR_WIDBUS_SHIFT) /* 01: 4-wide (SDIO_D[3:0]) */ +# define SDIO_CLKCR_WIDBUS_D8 (2 << SDIO_CLKCR_WIDBUS_SHIFT) /* 10: 8-wide (SDIO_D[7:0]) */ +#define SDIO_CLKCR_NEGEDGE (1 << 13) /* Bit 13: SDIO_CK dephasing selection bit */ +#define SDIO_CLKCR_HWFC_EN (1 << 14) /* Bit 14: HW Flow Control enable */ + +#define SDIO_CLKCR_RESET (0) /* Reset value */ +#define SDIO_ARG_RESET (0) /* Reset value */ + +#define SDIO_CLKCR_CLKEN_BB (STM32_SDIO_CLKCR_BB + (8 * 4)) +#define SDIO_CLKCR_PWRSAV_BB (STM32_SDIO_CLKCR_BB + (9 * 4)) +#define SDIO_CLKCR_BYPASS_BB (STM32_SDIO_CLKCR_BB + (10 * 4)) +#define SDIO_CLKCR_NEGEDGE_BB (STM32_SDIO_CLKCR_BB + (13 * 4)) +#define SDIO_CLKCR_HWFC_EN_BB (STM32_SDIO_CLKCR_BB + (14 * 4)) + +#define SDIO_CMD_CMDINDEX_SHIFT (0) +#define SDIO_CMD_CMDINDEX_MASK (0x3f << SDIO_CMD_CMDINDEX_SHIFT) +#define SDIO_CMD_WAITRESP_SHIFT (6) /* Bits 7-6: Wait for response bits */ +#define SDIO_CMD_WAITRESP_MASK (3 << SDIO_CMD_WAITRESP_SHIFT) +# define SDIO_CMD_NORESPONSE (0 << SDIO_CMD_WAITRESP_SHIFT) /* 00/10: No response */ +# define SDIO_CMD_SHORTRESPONSE (1 << SDIO_CMD_WAITRESP_SHIFT) /* 01: Short response */ +# define SDIO_CMD_LONGRESPONSE (3 << SDIO_CMD_WAITRESP_SHIFT) /* 11: Long response */ +#define SDIO_CMD_WAITINT (1 << 8) /* Bit 8: CPSM waits for interrupt request */ +#define SDIO_CMD_WAITPEND (1 << 9) /* Bit 9: CPSM Waits for ends of data transfer */ +#define SDIO_CMD_CPSMEN (1 << 10) /* Bit 10: Command path state machine enable */ +#define SDIO_CMD_SUSPEND (1 << 11) /* Bit 11: SD I/O suspend command */ +#define SDIO_CMD_ENDCMD (1 << 12) /* Bit 12: Enable CMD completion */ +#define SDIO_CMD_NIEN (1 << 13) /* Bit 13: not Interrupt Enable */ +#define SDIO_CMD_ATACMD (1 << 14) /* Bit 14: CE-ATA command */ + +#define SDIO_CMD_RESET (0) /* Reset value */ + +#define SDIO_CMD_WAITINT_BB (STM32_SDIO_CMD_BB + (8 * 4)) +#define SDIO_CMD_WAITPEND_BB (STM32_SDIO_CMD_BB + (9 * 4)) +#define SDIO_CMD_CPSMEN_BB (STM32_SDIO_CMD_BB + (10 * 4)) +#define SDIO_CMD_SUSPEND_BB (STM32_SDIO_CMD_BB + (11 * 4)) +#define SDIO_CMD_ENCMD_BB (STM32_SDIO_CMD_BB + (12 * 4)) +#define SDIO_CMD_NIEN_BB (STM32_SDIO_CMD_BB + (13 * 4)) +#define SDIO_CMD_ATACMD_BB (STM32_SDIO_CMD_BB + (14 * 4)) + +#define SDIO_RESPCMD_SHIFT (0) +#define SDIO_RESPCMD_MASK (0x3f << SDIO_RESPCMD_SHIFT) + +#define SDIO_DTIMER_RESET (0) /* Reset value */ + +#define SDIO_DLEN_SHIFT (0) +#define SDIO_DLEN_MASK (0x01ffffff << SDIO_DLEN_SHIFT) + +#define SDIO_DLEN_RESET (0) /* Reset value */ + +#define SDIO_DCTRL_DTEN (1 << 0) /* Bit 0: Data transfer enabled bit */ +#define SDIO_DCTRL_DTDIR (1 << 1) /* Bit 1: Data transfer direction */ +#define SDIO_DCTRL_DTMODE (1 << 2) /* Bit 2: Data transfer mode */ +#define SDIO_DCTRL_DMAEN (1 << 3) /* Bit 3: DMA enable bit */ +#define SDIO_DCTRL_DBLOCKSIZE_SHIFT (4) /* Bits 7-4: Data block size */ +#define SDIO_DCTRL_DBLOCKSIZE_MASK (15 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_1BYTE (0 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_2BYTES (1 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_4BYTES (2 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_8BYTES (3 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_16BYTES (4 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_32BYTES (5 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_64BYTES (6 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_128BYTES (7 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_256BYTES (8 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_512BYTES (9 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_1KBYTE (10 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_2KBYTES (11 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_4KBYTES (12 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_8KBYTES (13 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +# define SDIO_DCTRL_16KBYTES (14 << SDIO_DCTRL_DBLOCKSIZE_SHIFT) +#define SDIO_DCTRL_RWSTART (1 << 8) /* Bit 8: Read wait start */ +#define SDIO_DCTRL_RWSTOP (1 << 9) /* Bit 9: Read wait stop */ +#define SDIO_DCTRL_RWMOD (1 << 10) /* Bit 10: Read wait mode */ +#define SDIO_DCTRL_SDIOEN (1 << 11) /* Bit 11: SD I/O enable functions */ + +#define SDIO_DCTRL_RESET (0) /* Reset value */ + +#define SDIO_DCTRL_DTEN_BB (STM32_SDIO_DCTRL_BB + (0 * 4)) +#define SDIO_DCTRL_DTDIR_BB (STM32_SDIO_DCTRL_BB + (1 * 4)) +#define SDIO_DCTRL_DTMODE_BB (STM32_SDIO_DCTRL_BB + (2 * 4)) +#define SDIO_DCTRL_DMAEN_BB (STM32_SDIO_DCTRL_BB + (3 * 4)) +#define SDIO_DCTRL_RWSTART_BB (STM32_SDIO_DCTRL_BB + (8 * 4)) +#define SDIO_DCTRL_RWSTOP_BB (STM32_SDIO_DCTRL_BB + (9 * 4)) +#define SDIO_DCTRL_RWMOD_BB (STM32_SDIO_DCTRL_BB + (10 * 4)) +#define SDIO_DCTRL_SDIOEN_BB (STM32_SDIO_DCTRL_BB + (11 * 4)) + +#define SDIO_DATACOUNT_SHIFT (0) +#define SDIO_DATACOUNT_MASK (0x01ffffff << SDIO_DATACOUNT_SHIFT) + +#define SDIO_STA_CCRCFAIL (1 << 0) /* Bit 0: Command response CRC fail */ +#define SDIO_STA_DCRCFAIL (1 << 1) /* Bit 1: Data block CRC fail */ +#define SDIO_STA_CTIMEOUT (1 << 2) /* Bit 2: Command response timeout */ +#define SDIO_STA_DTIMEOUT (1 << 3) /* Bit 3: Data timeout */ +#define SDIO_STA_TXUNDERR (1 << 4) /* Bit 4: Transmit FIFO underrun error */ +#define SDIO_STA_RXOVERR (1 << 5) /* Bit 5: Received FIFO overrun error */ +#define SDIO_STA_CMDREND (1 << 6) /* Bit 6: Command response received */ +#define SDIO_STA_CMDSENT (1 << 7) /* Bit 7: Command sent */ +#define SDIO_STA_DATAEND (1 << 8) /* Bit 8: Data end */ +#define SDIO_STA_STBITERR (1 << 9) /* Bit 9: Start bit not detected */ +#define SDIO_STA_DBCKEND (1 << 10) /* Bit 10: Data block sent/received */ +#define SDIO_STA_CMDACT (1 << 11) /* Bit 11: Command transfer in progress */ +#define SDIO_STA_TXACT (1 << 12) /* Bit 12: Data transmit in progress */ +#define SDIO_STA_RXACT (1 << 13) /* Bit 13: Data receive in progress */ +#define SDIO_STA_TXFIFOHE (1 << 14) /* Bit 14: Transmit FIFO half empty */ +#define SDIO_STA_RXFIFOHF (1 << 15) /* Bit 15: Receive FIFO half full */ +#define SDIO_STA_TXFIFOF (1 << 16) /* Bit 16: Transmit FIFO full */ +#define SDIO_STA_RXFIFOF (1 << 17) /* Bit 17: Receive FIFO full */ +#define SDIO_STA_TXFIFOE (1 << 18) /* Bit 18: Transmit FIFO empty */ +#define SDIO_STA_RXFIFOE (1 << 19) /* Bit 19: Receive FIFO empty */ +#define SDIO_STA_TXDAVL (1 << 20) /* Bit 20: Data available in transmit FIFO */ +#define SDIO_STA_RXDAVL (1 << 21) /* Bit 21: Data available in receive FIFO */ +#define SDIO_STA_SDIOIT (1 << 22) /* Bit 22: SDIO interrupt received */ +#define SDIO_STA_CEATAEND (1 << 23) /* Bit 23: CMD6 CE-ATA command completion */ + +#define SDIO_ICR_CCRCFAILC (1 << 0) /* Bit 0: CCRCFAIL flag clear bit */ +#define SDIO_ICR_DCRCFAILC (1 << 1) /* Bit 1: DCRCFAIL flag clear bit */ +#define SDIO_ICR_CTIMEOUTC (1 << 2) /* Bit 2: CTIMEOUT flag clear bit */ +#define SDIO_ICR_DTIMEOUTC (1 << 3) /* Bit 3: DTIMEOUT flag clear bit */ +#define SDIO_ICR_TXUNDERRC (1 << 4) /* Bit 4: TXUNDERR flag clear bit */ +#define SDIO_ICR_RXOVERRC (1 << 5) /* Bit 5: RXOVERR flag clear bit */ +#define SDIO_ICR_CMDRENDC (1 << 6) /* Bit 6: CMDREND flag clear bit */ +#define SDIO_ICR_CMDSENTC (1 << 7) /* Bit 7: CMDSENT flag clear bit */ +#define SDIO_ICR_DATAENDC (1 << 8) /* Bit 8: DATAEND flag clear bit */ +#define SDIO_ICR_STBITERRC (1 << 9) /* Bit 9: STBITERR flag clear bit */ +#define SDIO_ICR_DBCKENDC (1 << 10) /* Bit 10: DBCKEND flag clear bit */ +#define SDIO_ICR_SDIOITC (1 << 22) /* Bit 22: SDIOIT flag clear bit */ +#define SDIO_ICR_CEATAENDC (1 << 23) /* Bit 23: CEATAEND flag clear bit */ + +#define SDIO_ICR_RESET 0x00c007ff +#define SDIO_ICR_STATICFLAGS 0x000005ff + +#define SDIO_MASK_CCRCFAILIE (1 << 0) /* Bit 0: Command CRC fail interrupt enable */ +#define SDIO_MASK_DCRCFAILIE (1 << 1) /* Bit 1: Data CRC fail interrupt enable */ +#define SDIO_MASK_CTIMEOUTIE (1 << 2) /* Bit 2: Command timeout interrupt enable */ +#define SDIO_MASK_DTIMEOUTIE (1 << 3) /* Bit 3: Data timeout interrupt enable */ +#define SDIO_MASK_TXUNDERRIE (1 << 4) /* Bit 4: Tx FIFO underrun error interrupt enable */ +#define SDIO_MASK_RXOVERRIE (1 << 5) /* Bit 5: Rx FIFO overrun error interrupt enable */ +#define SDIO_MASK_CMDRENDIE (1 << 6) /* Bit 6: Command response received interrupt enable */ +#define SDIO_MASK_CMDSENTIE (1 << 7) /* Bit 7: Command sent interrupt enable */ +#define SDIO_MASK_DATAENDIE (1 << 8) /* Bit 8: Data end interrupt enable */ +#define SDIO_MASK_STBITERRIE (1 << 9) /* Bit 9: Start bit error interrupt enable */ +#define SDIO_MASK_DBCKENDIE (1 << 10) /* Bit 10: Data block end interrupt enable */ +#define SDIO_MASK_CMDACTIE (1 << 11) /* Bit 11: Command acting interrupt enable */ +#define SDIO_MASK_TXACTIE (1 << 12) /* Bit 12: Data transmit acting interrupt enable */ +#define SDIO_MASK_RXACTIE (1 << 13) /* Bit 13: Data receive acting interrupt enable */ +#define SDIO_MASK_TXFIFOHEIE (1 << 14) /* Bit 14: Tx FIFO half empty interrupt enable */ +#define SDIO_MASK_RXFIFOHFIE (1 << 15) /* Bit 15: Rx FIFO half full interrupt enable */ +#define SDIO_MASK_TXFIFOFIE (1 << 16) /* Bit 16: Tx FIFO full interrupt enable */ +#define SDIO_MASK_RXFIFOFIE (1 << 17) /* Bit 17: Rx FIFO full interrupt enable */ +#define SDIO_MASK_TXFIFOEIE (1 << 18) /* Bit 18: Tx FIFO empty interrupt enable */ +#define SDIO_MASK_RXFIFOEIE (1 << 19) /* Bit 19: Rx FIFO empty interrupt enable */ +#define SDIO_MASK_TXDAVLIE (1 << 20) /* Bit 20: Data available in Tx FIFO interrupt enable */ +#define SDIO_MASK_RXDAVLIE (1 << 21) /* Bit 21: Data available in Rx FIFO interrupt enable */ +#define SDIO_MASK_SDIOITIE (1 << 22) /* Bit 22: SDIO mode interrupt received interrupt enable */ +#define SDIO_MASK_CEATAENDIE (1 << 23) /* Bit 23: CE-ATA command completion interrupt enable */ + +#define SDIO_MASK_RESET (0) + +#define SDIO_FIFOCNT_SHIFT (0) +#define SDIO_FIFOCNT_MASK (0x01ffffff << SDIO_FIFOCNT_SHIFT) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_SDIO_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_spi.h b/nuttx/arch/arm/src/stm32/chip/stm32_spi.h new file mode 100644 index 0000000000..d80c447bbd --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_spi.h @@ -0,0 +1,205 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_spi.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_STC_STM32_CHIP_STM32_SPI_H +#define __ARCH_ARM_STC_STM32_CHIP_STM32_SPI_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include "chip.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#define STM32_SPI_CLK_MAX 18000000UL /* Maximum allowed speed as per specifications for all SPIs */ + +/* Register Offsets *****************************************************************/ + +#define STM32_SPI_CR1_OFFSET 0x0000 /* SPI Control Register 1 (16-bit) */ +#define STM32_SPI_CR2_OFFSET 0x0004 /* SPI control register 2 (16-bit) */ +#define STM32_SPI_SR_OFFSET 0x0008 /* SPI status register (16-bit) */ +#define STM32_SPI_DR_OFFSET 0x000c /* SPI data register (16-bit) */ +#define STM32_SPI_CRCPR_OFFSET 0x0010 /* SPI CRC polynomial register (16-bit) */ +#define STM32_SPI_RXCRCR_OFFSET 0x0014 /* SPI Rx CRC register (16-bit) */ +#define STM32_SPI_TXCRCR_OFFSET 0x0018 /* SPI Tx CRC register (16-bit) */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_SPI_I2SCFGR_OFFSET 0x001c /* I2S configuration register */ +# define STM32_SPI_I2SPR_OFFSET 0x0020 /* I2S prescaler register */ +#endif + +/* Register Addresses ***************************************************************/ + +#if STM32_NSPI > 0 +# define STM32_SPI1_CR1 (STM32_SPI1_BASE+STM32_SPI_CR1_OFFSET) +# define STM32_SPI1_CR2 (STM32_SPI1_BASE+STM32_SPI_CR2_OFFSET) +# define STM32_SPI1_SR (STM32_SPI1_BASE+STM32_SPI_SR_OFFSET) +# define STM32_SPI1_DR (STM32_SPI1_BASE+STM32_SPI_DR_OFFSET) +# define STM32_SPI1_CRCPR (STM32_SPI1_BASE+STM32_SPI_CRCPR_OFFSET) +# define STM32_SPI1_RXCRCR (STM32_SPI1_BASE+STM32_SPI_RXCRCR_OFFSET) +# define STM32_SPI1_TXCRCR (STM32_SPI1_BASE+STM32_SPI_TXCRCR_OFFSET) +#endif + +#if STM32_NSPI > 1 +# define STM32_SPI2_CR1 (STM32_SPI2_BASE+STM32_SPI_CR1_OFFSET) +# define STM32_SPI2_CR2 (STM32_SPI2_BASE+STM32_SPI_CR2_OFFSET) +# define STM32_SPI2_SR (STM32_SPI2_BASE+STM32_SPI_SR_OFFSET) +# define STM32_SPI2_DR (STM32_SPI2_BASE+STM32_SPI_DR_OFFSET) +# define STM32_SPI2_CRCPR (STM32_SPI2_BASE+STM32_SPI_CRCPR_OFFSET) +# define STM32_SPI2_RXCRCR (STM32_SPI2_BASE+STM32_SPI_RXCRCR_OFFSET) +# define STM32_SPI2_TXCRCR (STM32_SPI2_BASE+STM32_SPI_TXCRCR_OFFSET) +# if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_SPI2_I2SCFGR (STM32_SPI2_BASE+STM32_SPI_I2SCFGR_OFFSET) +# define STM32_SPI2_I2SPR (STM32_SPI2_BASE+STM32_SPI_I2SPR_OFFSET) +# endif +#endif + +#if STM32_NSPI > 2 +# define STM32_SPI3_CR1 (STM32_SPI3_BASE+STM32_SPI_CR1_OFFSET) +# define STM32_SPI3_CR2 (STM32_SPI3_BASE+STM32_SPI_CR2_OFFSET) +# define STM32_SPI3_SR (STM32_SPI3_BASE+STM32_SPI_SR_OFFSET) +# define STM32_SPI3_DR (STM32_SPI3_BASE+STM32_SPI_DR_OFFSET) +# define STM32_SPI3_CRCPR (STM32_SPI3_BASE+STM32_SPI_CRCPR_OFFSET) +# define STM32_SPI3_RXCRCR (STM32_SPI3_BASE+STM32_SPI_RXCRCR_OFFSET) +# define STM32_SPI3_TXCRCR (STM32_SPI3_BASE+STM32_SPI_TXCRCR_OFFSET) +# if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_SPI3_I2SCFGR (STM32_SPI3_BASE+STM32_SPI_I2SCFGR_OFFSET) +# define STM32_SPI3_I2SPR (STM32_SPI3_BASE+STM32_SPI_I2SPR_OFFSET) +# endif +#endif + +/* Register Bitfield Definitions ****************************************************/ + +/* SPI Control Register 1 */ + +#define SPI_CR1_CPHA (1 << 0) /* Bit 0: Clock Phase */ +#define SPI_CR1_CPOL (1 << 1) /* Bit 1: Clock Polarity */ +#define SPI_CR1_MSTR (1 << 2) /* Bit 2: Master Selection */ +#define SPI_CR1_BR_SHIFT (3) /* Bits 5:3 Baud Rate Control */ +#define SPI_CR1_BR_MASK (7 << SPI_CR1_BR_SHIFT) +# define SPI_CR1_FPCLCKd2 (0 << SPI_CR1_BR_SHIFT) /* 000: fPCLK/2 */ +# define SPI_CR1_FPCLCKd4 (1 << SPI_CR1_BR_SHIFT) /* 001: fPCLK/4 */ +# define SPI_CR1_FPCLCKd8 (2 << SPI_CR1_BR_SHIFT) /* 010: fPCLK/8 */ +# define SPI_CR1_FPCLCKd16 (3 << SPI_CR1_BR_SHIFT) /* 011: fPCLK/16 */ +# define SPI_CR1_FPCLCKd32 (4 << SPI_CR1_BR_SHIFT) /* 100: fPCLK/32 */ +# define SPI_CR1_FPCLCKd64 (5 << SPI_CR1_BR_SHIFT) /* 101: fPCLK/64 */ +# define SPI_CR1_FPCLCKd128 (6 << SPI_CR1_BR_SHIFT) /* 110: fPCLK/128 */ +# define SPI_CR1_FPCLCKd256 (7 << SPI_CR1_BR_SHIFT) /* 111: fPCLK/256 */ +#define SPI_CR1_SPE (1 << 6) /* Bit 6: SPI Enable */ +#define SPI_CR1_LSBFIRST (1 << 7) /* Bit 7: Frame Format */ +#define SPI_CR1_SSI (1 << 8) /* Bit 8: Internal slave select */ +#define SPI_CR1_SSM (1 << 9) /* Bit 9: Software slave management */ +#define SPI_CR1_RXONLY (1 << 10) /* Bit 10: Receive only */ +#define SPI_CR1_DFF (1 << 11) /* Bit 11: Data Frame Format */ +#define SPI_CR1_CRCNEXT (1 << 12) /* Bit 12: Transmit CRC next */ +#define SPI_CR1_CRCEN (1 << 13) /* Bit 13: Hardware CRC calculation enable */ +#define SPI_CR1_BIDIOE (1 << 14) /* Bit 14: Output enable in bidirectional mode */ +#define SPI_CR1_BIDIMODE (1 << 15) /* Bit 15: Bidirectional data mode enable */ + +/* SPI Control Register 2 */ + +#define SPI_CR2_RXDMAEN (1 << 0) /* Bit 0: Rx Buffer DMA Enable */ +#define SPI_CR2_TXDMAEN (1 << 1) /* Bit 1: Tx Buffer DMA Enable */ +#define SPI_CR2_SSOE (1 << 2) /* Bit 2: SS Output Enable */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_SPI3_FRF (1 << 4) /* Bit 4: Frame format */ +#endif + +#define SPI_CR2_ERRIE (1 << 5) /* Bit 5: Error interrupt enable */ +#define SPI_CR2_RXNEIE (1 << 6) /* Bit 6: RX buffer not empty interrupt enable */ +#define SPI_CR2_TXEIE (1 << 7) /* Bit 7: Tx buffer empty interrupt enable */ + +/* SPI status register */ + +#define SPI_SR_RXNE (1 << 0) /* Bit 0: Receive buffer not empty */ +#define SPI_SR_TXE (1 << 1) /* Bit 1: Transmit buffer empty */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define SPI_SR_CHSIDE (1 << 2) /* Bit 2: Channel side */ +# define SPI_SR_UDR (1 << 3) /* Bit 3: Underrun flag */ +#endif + +#define SPI_SR_CRCERR (1 << 4) /* Bit 4: CRC error flag */ +#define SPI_SR_MODF (1 << 5) /* Bit 5: Mode fault */ +#define SPI_SR_OVR (1 << 6) /* Bit 6: Overrun flag */ +#define SPI_SR_BSY (1 << 7) /* Bit 7: Busy flag */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define SPI_SR_TIFRFE (1 << 8) /* Bit 8: TI frame format error */ +#endif + +/* I2S configuration register */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define SPI_I2SCFGR_CHLEN (1 << 0) /* Bit 0: Channel length (number of bits per audio channel) */ +# define SPI_I2SCFGR_DATLEN_SHIFT (1) /* Bit 1-2: Data length to be transferred */ +# define SPI_I2SCFGR_DATLEN_MASK (3 << SPI_I2SCFGR_DATLEN_SHIFT) +# define SPI_I2SCFGR_DATLEN_16BIT (0 << SPI_I2SCFGR_DATLEN_SHIFT) /* 00: 16-bit data length */ +# define SPI_I2SCFGR_DATLEN_8BIT (1 << SPI_I2SCFGR_DATLEN_SHIFT) /* 01: 24-bit data length */ +# define SPI_I2SCFGR_DATLEN_32BIT (2 << SPI_I2SCFGR_DATLEN_SHIFT) /* 10: 32-bit data length */ +# define SPI_I2SCFGR_CKPOL (1 << 3) /* Bit 3: Steady state clock polarity */ +# define SPI_I2SCFGR_I2SSTD_SHIFT (4) /* Bit 4-5: I2S standard selection */ +# define SPI_I2SCFGR_I2SSTD_MASK (3 << SPI_I2SCFGR_I2SSTD_SHIFT) +# define SPI_I2SCFGR_I2SSTD_PHILLIPS (xx << SPI_I2SCFGR_I2SSTD_SHIFT) /* 00: I2S Phillips standard. */ +# define SPI_I2SCFGR_I2SSTD_MSB (0 << SPI_I2SCFGR_I2SSTD_SHIFT) /* 01: MSB justified standard (left justified) */ +# define SPI_I2SCFGR_I2SSTD_LSB (2 << SPI_I2SCFGR_I2SSTD_SHIFT) /* 10: LSB justified standard (right justified) */ +# define SPI_I2SCFGR_I2SSTD_PCM (3 << SPI_I2SCFGR_I2SSTD_SHIFT) /* 11: PCM standard */ +# define SPI_I2SCFGR_PCMSYNC (1 << 7) /* Bit 7: PCM frame synchronization */ +# define SPI_I2SCFGR_I2SCFG_SHIFT (8) /* Bit 8-9: I2S configuration mode */ +# define SPI_I2SCFGR_I2SCFG_MASK (3 << SPI_I2SCFGR_I2SCFG_SHIFT) +# define SPI_I2SCFGR_I2SCFG_STX (0 << SPI_I2SCFGR_I2SCFG_SHIFT) /* 00: Slave - transmit */ +# define SPI_I2SCFGR_I2SCFG_SRX (1 << SPI_I2SCFGR_I2SCFG_SHIFT) /* 01: Slave - receive */ +# define SPI_I2SCFGR_I2SCFG_MTX (2 << SPI_I2SCFGR_I2SCFG_SHIFT) /* 10: Master - transmit */ +# define SPI_I2SCFGR_I2SCFG_MRX (3 << SPI_I2SCFGR_I2SCFG_SHIFT) /* 11: Master - receive */ +# define SPI_I2SCFGR_I2SE (1 << 10) /* Bit 10: I2S Enable */ +# define SPI_I2SCFGR_I2SMOD (1 << 11) /* Bit 11: I2S mode selection */ +#endif + +/* I2S prescaler register */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define SPI_I2SPR_I2SDIV_SHIFT (0) /* Bit 0-7: I2S Linear prescaler */ +# define SPI_I2SPR_I2SDIV_MASK (0xff << SPI_I2SPR_I2SDIV_SHIFT) +# define SPI_I2SPR_ODD (1 << 8) /* Bit 8: Odd factor for the prescaler */ +# define SPI_I2SPR_MCKOE (1 << 9) /* Bit 9: Master clock output enable */ +#endif + +#endif /* __ARCH_ARM_STC_STM32_CHIP_STM32_SPI_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_syscfg.h b/nuttx/arch/arm/src/stm32/chip/stm32_syscfg.h new file mode 100644 index 0000000000..6642b13059 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_syscfg.h @@ -0,0 +1,151 @@ +/**************************************************************************************************** + * arch/arm/src/stm32/chip/stm32_syscfg.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_SYSCFG_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_SYSCFG_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include +#include "chip.h" + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ + +/* Register Offsets *********************************************************************************/ + +#define STM32_SYSCFG_MEMRMP_OFFSET 0x0000 /* SYSCFG memory remap register */ +#define STM32_SYSCFG_PMC_OFFSET 0x0004 /* SYSCFG peripheral mode configuration register */ + +#define STM32_SYSCFG_EXTICR_OFFSET(p) (0x0008 + ((p) & 0x000c)) /* Registers are displaced by 4! */ +#define STM32_SYSCFG_EXTICR1_OFFSET 0x0008 /* SYSCFG external interrupt configuration register 1 */ +#define STM32_SYSCFG_EXTICR2_OFFSET 0x000c /* SYSCFG external interrupt configuration register 2 */ +#define STM32_SYSCFG_EXTICR3_OFFSET 0x0010 /* SYSCFG external interrupt configuration register 3 */ +#define STM32_SYSCFG_EXTICR4_OFFSET 0x0014 /* SYSCFG external interrupt configuration register 4 */ + +#define STM32_SYSCFG_CMPCR_OFFSET 0x0020 /* Compensation cell control register */ + +/* Register Addresses *******************************************************************************/ + +#define STM32_SYSCFG_MEMRMP (STM32_SYSCFG_BASE+STM32_SYSCFG_MEMRMP_OFFSET) +#define STM32_SYSCFG_PMC (STM32_SYSCFG_BASE+STM32_SYSCFG_PMC_OFFSET) + +#define STM32_SYSCFG_EXTICR(p) (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR_OFFSET(p)) +#define STM32_SYSCFG_EXTICR1 (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR1_OFFSET) +#define STM32_SYSCFG_EXTICR2 (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR2_OFFSET) +#define STM32_SYSCFG_EXTICR3 (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR3_OFFSET) +#define STM32_SYSCFG_EXTICR4 (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR4_OFFSET) + +#define STM32_SYSCFG_CMPCR (STM32_SYSCFG_BASE+STM32_SYSCFG_CMPCR_OFFSET) + +/* Register Bitfield Definitions ********************************************************************/ + +/* SYSCFG memory remap register */ + +#define SYSCFG_MEMRMP_SHIFT (0) /* Bits 1:0 MEM_MODE: Memory mapping selection */ +#define SYSCFG_MEMRMP_MASK (3 << SYSCFG_MEMRMP_SHIFT) +# define SYSCFG_MEMRMP_FLASH (0 << SYSCFG_MEMRMP_SHIFT) /* 00: Main Flash memory mapped at 0x0000 0000 */ +# define SYSCFG_MEMRMP_SYSTEM (1 << SYSCFG_MEMRMP_SHIFT) /* 01: System Flash memory mapped at 0x0000 0000 */ +# define SYSCFG_MEMRMP_FSMC (2 << SYSCFG_MEMRMP_SHIFT) /* 10: FSMC Bank1 (NOR/PSRAM 1 and 2) mapped at 0x0000 0000 */ +# define SYSCFG_MEMRMP_SRAM (3 << SYSCFG_MEMRMP_SHIFT) /* 11: Embedded SRAM (112kB) mapped at 0x0000 0000 */ + +/* SYSCFG peripheral mode configuration register */ + +#define SYSCFG_PMC_MII_RMII_SEL (1 << 23) /* Bit 23: Ethernet PHY interface selection */ + +/* SYSCFG external interrupt configuration register 1-4 */ + +#define SYSCFG_EXTICR_PORTA (0) /* 0000: PA[x] pin */ +#define SYSCFG_EXTICR_PORTB (1) /* 0001: PB[x] pin */ +#define SYSCFG_EXTICR_PORTC (2) /* 0010: PC[x] pin */ +#define SYSCFG_EXTICR_PORTD (3) /* 0011: PD[x] pin */ +#define SYSCFG_EXTICR_PORTE (4) /* 0100: PE[x] pin */ +#define SYSCFG_EXTICR_PORTF (5) /* 0101: PF[C] pin */ +#define SYSCFG_EXTICR_PORTG (6) /* 0110: PG[x] pin */ +#define SYSCFG_EXTICR_PORTH (7) /* 0111: PH[x] pin */ +#define SYSCFG_EXTICR_PORTI (8) /* 1000: PI[x] pin */ + +#define SYSCFG_EXTICR_PORT_MASK (15) +#define SYSCFG_EXTICR_EXTI_SHIFT(g) (((g) & 3) << 2) +#define SYSCFG_EXTICR_EXTI_MASK(g) (SYSCFG_EXTICR_PORT_MASK << (SYSCFG_EXTICR_EXTI_SHIFT(g))) + +#define SYSCFG_EXTICR1_EXTI0_SHIFT (0) /* Bits 0-3: EXTI 0 coinfiguration */ +#define SYSCFG_EXTICR1_EXTI0_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI0_SHIFT) +#define SYSCFG_EXTICR1_EXTI1_SHIFT (4) /* Bits 4-7: EXTI 1 coinfiguration */ +#define SYSCFG_EXTICR1_EXTI1_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI1_SHIFT) +#define SYSCFG_EXTICR1_EXTI2_SHIFT (8) /* Bits 8-11: EXTI 2 coinfiguration */ +#define SYSCFG_EXTICR1_EXTI2_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI2_SHIFT) +#define SYSCFG_EXTICR1_EXTI3_SHIFT (12) /* Bits 12-15: EXTI 3 coinfiguration */ +#define SYSCFG_EXTICR1_EXTI3_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI3_SHIFT) + +#define SYSCFG_EXTICR2_EXTI4_SHIFT (0) /* Bits 0-3: EXTI 4 coinfiguration */ +#define SYSCFG_EXTICR2_EXTI4_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI4_SHIFT) +#define SYSCFG_EXTICR2_EXTI5_SHIFT (4) /* Bits 4-7: EXTI 5 coinfiguration */ +#define SYSCFG_EXTICR2_EXTI5_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI5_SHIFT) +#define SYSCFG_EXTICR2_EXTI6_SHIFT (8) /* Bits 8-11: EXTI 6 coinfiguration */ +#define SYSCFG_EXTICR2_EXTI6_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI6_SHIFT) +#define SYSCFG_EXTICR2_EXTI7_SHIFT (12) /* Bits 12-15: EXTI 7 coinfiguration */ +#define SYSCFG_EXTICR2_EXTI7_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI7_SHIFT) + +#define SYSCFG_EXTICR3_EXTI8_SHIFT (0) /* Bits 0-3: EXTI 8 coinfiguration */ +#define SYSCFG_EXTICR3_EXTI8_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI8_SHIFT) +#define SYSCFG_EXTICR3_EXTI9_SHIFT (4) /* Bits 4-7: EXTI 9 coinfiguration */ +#define SYSCFG_EXTICR3_EXTI9_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI9_SHIFT) +#define SYSCFG_EXTICR3_EXTI10_SHIFT (8) /* Bits 8-11: EXTI 10 coinfiguration */ +#define SYSCFG_EXTICR3_EXTI10_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI10_SHIFT) +#define SYSCFG_EXTICR3_EXTI11_SHIFT (12) /* Bits 12-15: EXTI 11 coinfiguration */ +#define SYSCFG_EXTICR3_EXTI11_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI11_SHIFT) + +#define SYSCFG_EXTICR4_EXTI12_SHIFT (0) /* Bits 0-3: EXTI 12 coinfiguration */ +#define SYSCFG_EXTICR4_EXTI12_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI12_SHIFT) +#define SYSCFG_EXTICR4_EXTI13_SHIFT (4) /* Bits 4-7: EXTI 13 coinfiguration */ +#define SYSCFG_EXTICR4_EXTI13_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI13_SHIFT) +#define SYSCFG_EXTICR4_EXTI14_SHIFT (8) /* Bits 8-11: EXTI 14 coinfiguration */ +#define SYSCFG_EXTICR4_EXTI14_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI14_SHIFT) +#define SYSCFG_EXTICR4_EXTI15_SHIFT (12) /* Bits 12-15: EXTI 15 coinfiguration */ +#define SYSCFG_EXTICR4_EXTI15_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI15_SHIFT) + +/* Compensation cell control register */ + +#define SYSCFG_CMPCR_CMPPD (1 << 0) /* Bit 0: Compensation cell power-down */ +#define SYSCFG_CMPCR_READY (1 << 8) /* Bit 8: Compensation cell ready flag */ + +#endif /* CONFIG_STM32_STM32F20XX || CONFIG_STM32_STM32F40XX */ +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_SYSCFG_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_tim.h b/nuttx/arch/arm/src/stm32/chip/stm32_tim.h new file mode 100644 index 0000000000..3713f8b796 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_tim.h @@ -0,0 +1,1029 @@ +/**************************************************************************************************** + * arch/arm/src/stm32/chip/stm32_tim.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_TIM_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_TIM_H + +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ + +/* Register Offsets *********************************************************************************/ + +/* Basic Timers - TIM6 and TIM7 */ + +#define STM32_BTIM_CR1_OFFSET 0x0000 /* Control register 1 (16-bit) */ +#define STM32_BTIM_CR2_OFFSET 0x0004 /* Control register 2 (16-bit) */ +#define STM32_BTIM_DIER_OFFSET 0x000c /* DMA/Interrupt enable register (16-bit) */ +#define STM32_BTIM_SR_OFFSET 0x0010 /* Status register (16-bit) */ +#define STM32_BTIM_EGR_OFFSET 0x0014 /* Event generation register (16-bit) */ +#define STM32_BTIM_CNT_OFFSET 0x0024 /* Counter (16-bit) */ +#define STM32_BTIM_PSC_OFFSET 0x0028 /* Prescaler (16-bit) */ +#define STM32_BTIM_ARR_OFFSET 0x002c /* Auto-reload register (16-bit) */ + +/* 16-/32-bit General Timers with DMA: TIM2, TM3, TIM4, and TIM5 + * 16-bit General Timers without DMA: TIM9, TIM10, TIM11, TIM12, TIM13, and TIM14 + * For the STM32F10xx all timers are 16-bit. + * For the STM32F20xx and STM32F40xx, TIM2 and 5 are 32-bit + */ + +#define STM32_GTIM_CR1_OFFSET 0x0000 /* Control register 1 (16-bit) */ +#define STM32_GTIM_CR2_OFFSET 0x0004 /* Control register 2 (16-bit, TIM2-5 only) */ +#define STM32_GTIM_SMCR_OFFSET 0x0008 /* Slave mode control register (16-bit, TIM2-5 only) */ +#define STM32_GTIM_DIER_OFFSET 0x000c /* DMA/Interrupt enable register (16-bit) */ +#define STM32_GTIM_SR_OFFSET 0x0010 /* Status register (16-bit) */ +#define STM32_GTIM_EGR_OFFSET 0x0014 /* Event generation register (16-bit) */ +#define STM32_GTIM_CCMR1_OFFSET 0x0018 /* Capture/compare mode register 1 (16-bit) */ +#define STM32_GTIM_CCMR2_OFFSET 0x001c /* Capture/compare mode register 2 (16-bit, TIM2-5 only) */ +#define STM32_GTIM_CCER_OFFSET 0x0020 /* Capture/compare enable register (16-bit) */ +#define STM32_GTIM_CNT_OFFSET 0x0024 /* Counter (16-bit or 32-bit STM3240 TIM2 and 5 only) */ +#define STM32_GTIM_PSC_OFFSET 0x0028 /* Prescaler (16-bit) */ +#define STM32_GTIM_ARR_OFFSET 0x002c /* Auto-reload register (16-bit) */ +#define STM32_GTIM_CCR1_OFFSET 0x0034 /* Capture/compare register 1 (16-bit or 32-bit STM3240 TIM2/5 only) */ +#define STM32_GTIM_CCR2_OFFSET 0x0038 /* Capture/compare register 2 (16-bit TIM2-5 only or 32-bit STM3240 TIM2/5 only) */ +#define STM32_GTIM_CCR3_OFFSET 0x003c /* Capture/compare register 3 (16-bit TIM2-5 only or 32-bit STM3240 TIM2/5 only) */ +#define STM32_GTIM_CCR4_OFFSET 0x0040 /* Capture/compare register 4 (16-bit TIM2-5 only or 32-bit STM3240 TIM2/5 only) */ +#define STM32_GTIM_DCR_OFFSET 0x0048 /* DMA control register (16-bit, TIM2-5 only) */ +#define STM32_GTIM_DMAR_OFFSET 0x004c /* DMA address for burst mode (16-bit, TIM2-5 only) */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_GTIM_OR_OFFSET 0x0050 /* Timer 2/5/11 option register */ +#endif + +/* Advanced Timers - TIM1 and TIM8 */ + +#define STM32_ATIM_CR1_OFFSET 0x0000 /* Control register 1 (16-bit) */ +#define STM32_ATIM_CR2_OFFSET 0x0004 /* Control register 2 *(16-bit) */ +#define STM32_ATIM_SMCR_OFFSET 0x0008 /* Slave mode control register (16-bit) */ +#define STM32_ATIM_DIER_OFFSET 0x000c /* DMA/Interrupt enable register (16-bit) */ +#define STM32_ATIM_SR_OFFSET 0x0010 /* Status register (16-bit) */ +#define STM32_ATIM_EGR_OFFSET 0x0014 /* Event generation register (16-bit) */ +#define STM32_ATIM_CCMR1_OFFSET 0x0018 /* Capture/compare mode register 1 (16-bit) */ +#define STM32_ATIM_CCMR2_OFFSET 0x001c /* Capture/compare mode register 2 (16-bit) */ +#define STM32_ATIM_CCER_OFFSET 0x0020 /* Capture/compare enable register (16-bit) */ +#define STM32_ATIM_CNT_OFFSET 0x0024 /* Counter (16-bit) */ +#define STM32_ATIM_PSC_OFFSET 0x0028 /* Prescaler (16-bit) */ +#define STM32_ATIM_ARR_OFFSET 0x002c /* Auto-reload register (16-bit) */ +#define STM32_ATIM_RCR_OFFSET 0x0030 /* Repetition counter register (16-bit) */ +#define STM32_ATIM_CCR1_OFFSET 0x0034 /* Capture/compare register 1 (16-bit) */ +#define STM32_ATIM_CCR2_OFFSET 0x0038 /* Capture/compare register 2 (16-bit) */ +#define STM32_ATIM_CCR3_OFFSET 0x003c /* Capture/compare register 3 (16-bit) */ +#define STM32_ATIM_CCR4_OFFSET 0x0040 /* Capture/compare register 4 (16-bit) */ +#define STM32_ATIM_BDTR_OFFSET 0x0044 /* Break and dead-time register (16-bit) */ +#define STM32_ATIM_DCR_OFFSET 0x0048 /* DMA control register (16-bit) */ +#define STM32_ATIM_DMAR_OFFSET 0x004c /* DMA address for burst mode (16-bit) */ + +/* Register Addresses *******************************************************************************/ + +/* Advanced Timers - TIM1 and TIM8 */ + +#if STM32_NATIM > 0 +# define STM32_TIM1_CR1 (STM32_TIM1_BASE+STM32_ATIM_CR1_OFFSET) +# define STM32_TIM1_CR2 (STM32_TIM1_BASE+STM32_ATIM_CR2_OFFSET) +# define STM32_TIM1_SMCR (STM32_TIM1_BASE+STM32_ATIM_SMCR_OFFSET) +# define STM32_TIM1_DIER (STM32_TIM1_BASE+STM32_ATIM_DIER_OFFSET) +# define STM32_TIM1_SR (STM32_TIM1_BASE+STM32_ATIM_SR_OFFSET) +# define STM32_TIM1_EGR (STM32_TIM1_BASE+STM32_ATIM_EGR_OFFSET) +# define STM32_TIM1_CCMR1 (STM32_TIM1_BASE+STM32_ATIM_CCMR1_OFFSET) +# define STM32_TIM1_CCMR2 (STM32_TIM1_BASE+STM32_ATIM_CCMR2_OFFSET) +# define STM32_TIM1_CCER (STM32_TIM1_BASE+STM32_ATIM_CCER_OFFSET) +# define STM32_TIM1_CNT (STM32_TIM1_BASE+STM32_ATIM_CNT_OFFSET) +# define STM32_TIM1_PSC (STM32_TIM1_BASE+STM32_ATIM_PSC_OFFSET) +# define STM32_TIM1_ARR (STM32_TIM1_BASE+STM32_ATIM_ARR_OFFSET) +# define STM32_TIM1_RCR (STM32_TIM1_BASE+STM32_ATIM_RCR_OFFSET) +# define STM32_TIM1_CCR1 (STM32_TIM1_BASE+STM32_ATIM_CCR1_OFFSET) +# define STM32_TIM1_CCR2 (STM32_TIM1_BASE+STM32_ATIM_CCR2_OFFSET) +# define STM32_TIM1_CCR3 (STM32_TIM1_BASE+STM32_ATIM_CCR3_OFFSET) +# define STM32_TIM1_CCR4 (STM32_TIM1_BASE+STM32_ATIM_CCR4_OFFSET) +# define STM32_TIM1_BDTR (STM32_TIM1_BASE+STM32_ATIM_BDTR_OFFSET) +# define STM32_TIM1_DCR (STM32_TIM1_BASE+STM32_ATIM_DCR_OFFSET) +# define STM32_TIM1_DMAR (STM32_TIM1_BASE+STM32_ATIM_DMAR_OFFSET) +#endif + +#if STM32_NATIM > 1 +# define STM32_TIM8_CR1 (STM32_TIM8_BASE+STM32_ATIM_CR1_OFFSET) +# define STM32_TIM8_CR2 (STM32_TIM8_BASE+STM32_ATIM_CR2_OFFSET) +# define STM32_TIM8_SMCR (STM32_TIM8_BASE+STM32_ATIM_SMCR_OFFSET) +# define STM32_TIM8_DIER (STM32_TIM8_BASE+STM32_ATIM_DIER_OFFSET) +# define STM32_TIM8_SR (STM32_TIM8_BASE+STM32_ATIM_SR_OFFSET) +# define STM32_TIM8_EGR (STM32_TIM8_BASE+STM32_ATIM_EGR_OFFSET) +# define STM32_TIM8_CCMR1 (STM32_TIM8_BASE+STM32_ATIM_CCMR1_OFFSET) +# define STM32_TIM8_CCMR2 (STM32_TIM8_BASE+STM32_ATIM_CCMR2_OFFSET) +# define STM32_TIM8_CCER (STM32_TIM8_BASE+STM32_ATIM_CCER_OFFSET) +# define STM32_TIM8_CNT (STM32_TIM8_BASE+STM32_ATIM_CNT_OFFSET) +# define STM32_TIM8_PSC (STM32_TIM8_BASE+STM32_ATIM_PSC_OFFSET) +# define STM32_TIM8_ARR (STM32_TIM8_BASE+STM32_ATIM_ARR_OFFSET) +# define STM32_TIM8_RCR (STM32_TIM8_BASE+STM32_ATIM_RCR_OFFSET) +# define STM32_TIM8_CCR1 (STM32_TIM8_BASE+STM32_ATIM_CCR1_OFFSET) +# define STM32_TIM8_CCR2 (STM32_TIM8_BASE+STM32_ATIM_CCR2_OFFSET) +# define STM32_TIM8_CCR3 (STM32_TIM8_BASE+STM32_ATIM_CCR3_OFFSET) +# define STM32_TIM8_CCR4 (STM32_TIM8_BASE+STM32_ATIM_CCR4_OFFSET) +# define STM32_TIM8_BDTR (STM32_TIM8_BASE+STM32_ATIM_BDTR_OFFSET) +# define STM32_TIM8_DCR (STM32_TIM8_BASE+STM32_ATIM_DCR_OFFSET) +# define STM32_TIM8_DMAR (STM32_TIM8_BASE+STM32_ATIM_DMAR_OFFSET) +#endif + +/* 16-/32-bit General Timers - TIM2, TIM3, TIM4, and TIM5 with DMA. + * For the STM32F10xx all timers are 16-bit. + * For the STM32F2xx and STM32F40xx, TIM2 and 5 are 32-bit + */ + +#if STM32_NGTIM > 0 +# define STM32_TIM2_CR1 (STM32_TIM2_BASE+STM32_GTIM_CR1_OFFSET) +# define STM32_TIM2_CR2 (STM32_TIM2_BASE+STM32_GTIM_CR2_OFFSET) +# define STM32_TIM2_SMCR (STM32_TIM2_BASE+STM32_GTIM_SMCR_OFFSET) +# define STM32_TIM2_DIER (STM32_TIM2_BASE+STM32_GTIM_DIER_OFFSET) +# define STM32_TIM2_SR (STM32_TIM2_BASE+STM32_GTIM_SR_OFFSET) +# define STM32_TIM2_EGR (STM32_TIM2_BASE+STM32_GTIM_EGR_OFFSET) +# define STM32_TIM2_CCMR1 (STM32_TIM2_BASE+STM32_GTIM_CCMR1_OFFSET) +# define STM32_TIM2_CCMR2 (STM32_TIM2_BASE+STM32_GTIM_CCMR2_OFFSET) +# define STM32_TIM2_CCER (STM32_TIM2_BASE+STM32_GTIM_CCER_OFFSET) +# define STM32_TIM2_CNT (STM32_TIM2_BASE+STM32_GTIM_CNT_OFFSET) +# define STM32_TIM2_PSC (STM32_TIM2_BASE+STM32_GTIM_PSC_OFFSET) +# define STM32_TIM2_ARR (STM32_TIM2_BASE+STM32_GTIM_ARR_OFFSET) +# define STM32_TIM2_CCR1 (STM32_TIM2_BASE+STM32_GTIM_CCR1_OFFSET) +# define STM32_TIM2_CCR2 (STM32_TIM2_BASE+STM32_GTIM_CCR2_OFFSET) +# define STM32_TIM2_CCR3 (STM32_TIM2_BASE+STM32_GTIM_CCR3_OFFSET) +# define STM32_TIM2_CCR4 (STM32_TIM2_BASE+STM32_GTIM_CCR4_OFFSET) +# define STM32_TIM2_DCR (STM32_TIM2_BASE+STM32_GTIM_DCR_OFFSET) +# define STM32_TIM2_DMAR (STM32_TIM2_BASE+STM32_GTIM_DMAR_OFFSET) +# if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_TIM2_OR (STM32_TIM2_BASE+STM32_GTIM_OR_OFFSET) +# endif +#endif + +#if STM32_NGTIM > 1 +# define STM32_TIM3_CR1 (STM32_TIM3_BASE+STM32_GTIM_CR1_OFFSET) +# define STM32_TIM3_CR2 (STM32_TIM3_BASE+STM32_GTIM_CR2_OFFSET) +# define STM32_TIM3_SMCR (STM32_TIM3_BASE+STM32_GTIM_SMCR_OFFSET) +# define STM32_TIM3_DIER (STM32_TIM3_BASE+STM32_GTIM_DIER_OFFSET) +# define STM32_TIM3_SR (STM32_TIM3_BASE+STM32_GTIM_SR_OFFSET) +# define STM32_TIM3_EGR (STM32_TIM3_BASE+STM32_GTIM_EGR_OFFSET) +# define STM32_TIM3_CCMR1 (STM32_TIM3_BASE+STM32_GTIM_CCMR1_OFFSET) +# define STM32_TIM3_CCMR2 (STM32_TIM3_BASE+STM32_GTIM_CCMR2_OFFSET) +# define STM32_TIM3_CCER (STM32_TIM3_BASE+STM32_GTIM_CCER_OFFSET) +# define STM32_TIM3_CNT (STM32_TIM3_BASE+STM32_GTIM_CNT_OFFSET) +# define STM32_TIM3_PSC (STM32_TIM3_BASE+STM32_GTIM_PSC_OFFSET) +# define STM32_TIM3_ARR (STM32_TIM3_BASE+STM32_GTIM_ARR_OFFSET) +# define STM32_TIM3_CCR1 (STM32_TIM3_BASE+STM32_GTIM_CCR1_OFFSET) +# define STM32_TIM3_CCR2 (STM32_TIM3_BASE+STM32_GTIM_CCR2_OFFSET) +# define STM32_TIM3_CCR3 (STM32_TIM3_BASE+STM32_GTIM_CCR3_OFFSET) +# define STM32_TIM3_CCR4 (STM32_TIM3_BASE+STM32_GTIM_CCR4_OFFSET) +# define STM32_TIM3_DCR (STM32_TIM3_BASE+STM32_GTIM_DCR_OFFSET) +# define STM32_TIM3_DMAR (STM32_TIM3_BASE+STM32_GTIM_DMAR_OFFSET) +#endif + +#if STM32_NGTIM > 2 +# define STM32_TIM4_CR1 (STM32_TIM4_BASE+STM32_GTIM_CR1_OFFSET) +# define STM32_TIM4_CR2 (STM32_TIM4_BASE+STM32_GTIM_CR2_OFFSET) +# define STM32_TIM4_SMCR (STM32_TIM4_BASE+STM32_GTIM_SMCR_OFFSET) +# define STM32_TIM4_DIER (STM32_TIM4_BASE+STM32_GTIM_DIER_OFFSET) +# define STM32_TIM4_SR (STM32_TIM4_BASE+STM32_GTIM_SR_OFFSET) +# define STM32_TIM4_EGR (STM32_TIM4_BASE+STM32_GTIM_EGR_OFFSET) +# define STM32_TIM4_CCMR1 (STM32_TIM4_BASE+STM32_GTIM_CCMR1_OFFSET) +# define STM32_TIM4_CCMR2 (STM32_TIM4_BASE+STM32_GTIM_CCMR2_OFFSET) +# define STM32_TIM4_CCER (STM32_TIM4_BASE+STM32_GTIM_CCER_OFFSET) +# define STM32_TIM4_CNT (STM32_TIM4_BASE+STM32_GTIM_CNT_OFFSET) +# define STM32_TIM4_PSC (STM32_TIM4_BASE+STM32_GTIM_PSC_OFFSET) +# define STM32_TIM4_ARR (STM32_TIM4_BASE+STM32_GTIM_ARR_OFFSET) +# define STM32_TIM4_CCR1 (STM32_TIM4_BASE+STM32_GTIM_CCR1_OFFSET) +# define STM32_TIM4_CCR2 (STM32_TIM4_BASE+STM32_GTIM_CCR2_OFFSET) +# define STM32_TIM4_CCR3 (STM32_TIM4_BASE+STM32_GTIM_CCR3_OFFSET) +# define STM32_TIM4_CCR4 (STM32_TIM4_BASE+STM32_GTIM_CCR4_OFFSET) +# define STM32_TIM4_DCR (STM32_TIM4_BASE+STM32_GTIM_DCR_OFFSET) +# define STM32_TIM4_DMAR (STM32_TIM4_BASE+STM32_GTIM_DMAR_OFFSET) +#endif + +#if STM32_NGTIM > 3 +# define STM32_TIM5_CR1 (STM32_TIM5_BASE+STM32_GTIM_CR1_OFFSET) +# define STM32_TIM5_CR2 (STM32_TIM5_BASE+STM32_GTIM_CR2_OFFSET) +# define STM32_TIM5_SMCR (STM32_TIM5_BASE+STM32_GTIM_SMCR_OFFSET) +# define STM32_TIM5_DIER (STM32_TIM5_BASE+STM32_GTIM_DIER_OFFSET) +# define STM32_TIM5_SR (STM32_TIM5_BASE+STM32_GTIM_SR_OFFSET) +# define STM32_TIM5_EGR (STM32_TIM5_BASE+STM32_GTIM_EGR_OFFSET) +# define STM32_TIM5_CCMR1 (STM32_TIM5_BASE+STM32_GTIM_CCMR1_OFFSET) +# define STM32_TIM5_CCMR2 (STM32_TIM5_BASE+STM32_GTIM_CCMR2_OFFSET) +# define STM32_TIM5_CCER (STM32_TIM5_BASE+STM32_GTIM_CCER_OFFSET) +# define STM32_TIM5_CNT (STM32_TIM5_BASE+STM32_GTIM_CNT_OFFSET) +# define STM32_TIM5_PSC (STM32_TIM5_BASE+STM32_GTIM_PSC_OFFSET) +# define STM32_TIM5_ARR (STM32_TIM5_BASE+STM32_GTIM_ARR_OFFSET) +# define STM32_TIM5_CCR1 (STM32_TIM5_BASE+STM32_GTIM_CCR1_OFFSET) +# define STM32_TIM5_CCR2 (STM32_TIM5_BASE+STM32_GTIM_CCR2_OFFSET) +# define STM32_TIM5_CCR3 (STM32_TIM5_BASE+STM32_GTIM_CCR3_OFFSET) +# define STM32_TIM5_CCR4 (STM32_TIM5_BASE+STM32_GTIM_CCR4_OFFSET) +# define STM32_TIM5_DCR (STM32_TIM5_BASE+STM32_GTIM_DCR_OFFSET) +# define STM32_TIM5_DMAR (STM32_TIM5_BASE+STM32_GTIM_DMAR_OFFSET) +# if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_TIM5_OR (STM32_TIM5_BASE+STM32_GTIM_OR_OFFSET) +# endif +#endif + +/* 16-bit General Timers - TIM9-14 without DMA. Note that (1) these timers + * support only a subset of the general timer registers are supported, and + * (2) TIM9 and TIM12 differ from the others. + */ + +#if STM32_NGTIMNDMA > 0 +# define STM32_TIM9_CR1 (STM32_TIM9_BASE+STM32_GTIM_CR1_OFFSET) +# define STM32_TIM9_CR2 (STM32_TIM9_BASE+STM32_GTIM_CR2_OFFSET) +# define STM32_TIM9_DIER (STM32_TIM9_BASE+STM32_GTIM_DIER_OFFSET) +# define STM32_TIM9_SR (STM32_TIM9_BASE+STM32_GTIM_SR_OFFSET) +# define STM32_TIM9_EGR (STM32_TIM9_BASE+STM32_GTIM_EGR_OFFSET) +# define STM32_TIM9_CCMR1 (STM32_TIM9_BASE+STM32_GTIM_CCMR1_OFFSET) +# define STM32_TIM9_CCER (STM32_TIM9_BASE+STM32_GTIM_CCER_OFFSET) +# define STM32_TIM9_CNT (STM32_TIM9_BASE+STM32_GTIM_CNT_OFFSET) +# define STM32_TIM9_PSC (STM32_TIM9_BASE+STM32_GTIM_PSC_OFFSET) +# define STM32_TIM9_ARR (STM32_TIM9_BASE+STM32_GTIM_ARR_OFFSET) +# define STM32_TIM9_CCR1 (STM32_TIM9_BASE+STM32_GTIM_CCR1_OFFSET) +# define STM32_TIM9_CCR2 (STM32_TIM9_BASE+STM32_GTIM_CCR2_OFFSET) +#endif + +#if STM32_NGTIMNDMA > 1 +# define STM32_TIM10_CR1 (STM32_TIM10_BASE+STM32_GTIM_CR1_OFFSET) +# define STM32_TIM10_DIER (STM32_TIM10_BASE+STM32_GTIM_DIER_OFFSET) +# define STM32_TIM10_SR (STM32_TIM10_BASE+STM32_GTIM_SR_OFFSET) +# define STM32_TIM10_EGR (STM32_TIM10_BASE+STM32_GTIM_EGR_OFFSET) +# define STM32_TIM10_CCMR1 (STM32_TIM10_BASE+STM32_GTIM_CCMR1_OFFSET) +# define STM32_TIM10_CCER (STM32_TIM10_BASE+STM32_GTIM_CCER_OFFSET) +# define STM32_TIM10_CNT (STM32_TIM10_BASE+STM32_GTIM_CNT_OFFSET) +# define STM32_TIM10_PSC (STM32_TIM10_BASE+STM32_GTIM_PSC_OFFSET) +# define STM32_TIM10_ARR (STM32_TIM10_BASE+STM32_GTIM_ARR_OFFSET) +# define STM32_TIM10_CCR1 (STM32_TIM10_BASE+STM32_GTIM_CCR1_OFFSET) +#endif + +#if STM32_NGTIMNDMA > 2 +# define STM32_TIM11_CR1 (STM32_TIM11_BASE+STM32_GTIM_CR1_OFFSET) +# define STM32_TIM11_DIER (STM32_TIM11_BASE+STM32_GTIM_DIER_OFFSET) +# define STM32_TIM11_SR (STM32_TIM11_BASE+STM32_GTIM_SR_OFFSET) +# define STM32_TIM11_EGR (STM32_TIM11_BASE+STM32_GTIM_EGR_OFFSET) +# define STM32_TIM11_CCMR1 (STM32_TIM11_BASE+STM32_GTIM_CCMR1_OFFSET) +# define STM32_TIM11_CCER (STM32_TIM11_BASE+STM32_GTIM_CCER_OFFSET) +# define STM32_TIM11_CNT (STM32_TIM11_BASE+STM32_GTIM_CNT_OFFSET) +# define STM32_TIM11_PSC (STM32_TIM11_BASE+STM32_GTIM_PSC_OFFSET) +# define STM32_TIM11_ARR (STM32_TIM11_BASE+STM32_GTIM_ARR_OFFSET) +# define STM32_TIM11_CCR1 (STM32_TIM11_BASE+STM32_GTIM_CCR1_OFFSET) +# define STM32_TIM11_OR (STM32_TIM11_BASE+STM32_GTIM_OR_OFFSET) +#endif + +#if STM32_NGTIMNDMA > 3 +# define STM32_TIM12_CR1 (STM32_TIM12_BASE+STM32_GTIM_CR1_OFFSET) +# define STM32_TIM12_CR2 (STM32_TIM9_BASE+STM32_GTIM_CR2_OFFSET) +# define STM32_TIM12_DIER (STM32_TIM12_BASE+STM32_GTIM_DIER_OFFSET) +# define STM32_TIM12_SR (STM32_TIM12_BASE+STM32_GTIM_SR_OFFSET) +# define STM32_TIM12_EGR (STM32_TIM12_BASE+STM32_GTIM_EGR_OFFSET) +# define STM32_TIM12_CCMR1 (STM32_TIM12_BASE+STM32_GTIM_CCMR1_OFFSET) +# define STM32_TIM12_CCER (STM32_TIM12_BASE+STM32_GTIM_CCER_OFFSET) +# define STM32_TIM12_CNT (STM32_TIM12_BASE+STM32_GTIM_CNT_OFFSET) +# define STM32_TIM12_PSC (STM32_TIM12_BASE+STM32_GTIM_PSC_OFFSET) +# define STM32_TIM12_ARR (STM32_TIM12_BASE+STM32_GTIM_ARR_OFFSET) +# define STM32_TIM12_CCR1 (STM32_TIM12_BASE+STM32_GTIM_CCR1_OFFSET) +# define STM32_TIM12_CCR2 (STM32_TIM12_BASE+STM32_GTIM_CCR2_OFFSET) +#endif + +#if STM32_NGTIMNDMA > 4 +# define STM32_TIM13_CR1 (STM32_TIM13_BASE+STM32_GTIM_CR1_OFFSET) +# define STM32_TIM13_DIER (STM32_TIM13_BASE+STM32_GTIM_DIER_OFFSET) +# define STM32_TIM13_SR (STM32_TIM13_BASE+STM32_GTIM_SR_OFFSET) +# define STM32_TIM13_EGR (STM32_TIM13_BASE+STM32_GTIM_EGR_OFFSET) +# define STM32_TIM13_CCMR1 (STM32_TIM13_BASE+STM32_GTIM_CCMR1_OFFSET) +# define STM32_TIM13_CCER (STM32_TIM13_BASE+STM32_GTIM_CCER_OFFSET) +# define STM32_TIM13_CNT (STM32_TIM13_BASE+STM32_GTIM_CNT_OFFSET) +# define STM32_TIM13_PSC (STM32_TIM13_BASE+STM32_GTIM_PSC_OFFSET) +# define STM32_TIM13_ARR (STM32_TIM13_BASE+STM32_GTIM_ARR_OFFSET) +# define STM32_TIM13_CCR1 (STM32_TIM13_BASE+STM32_GTIM_CCR1_OFFSET) +#endif + +#if STM32_NGTIMNDMA > 5 +# define STM32_TIM14_CR1 (STM32_TIM14_BASE+STM32_GTIM_CR1_OFFSET) +# define STM32_TIM14_DIER (STM32_TIM14_BASE+STM32_GTIM_DIER_OFFSET) +# define STM32_TIM14_SR (STM32_TIM14_BASE+STM32_GTIM_SR_OFFSET) +# define STM32_TIM14_EGR (STM32_TIM14_BASE+STM32_GTIM_EGR_OFFSET) +# define STM32_TIM14_CCMR1 (STM32_TIM14_BASE+STM32_GTIM_CCMR1_OFFSET) +# define STM32_TIM14_CCER (STM32_TIM14_BASE+STM32_GTIM_CCER_OFFSET) +# define STM32_TIM14_CNT (STM32_TIM14_BASE+STM32_GTIM_CNT_OFFSET) +# define STM32_TIM14_PSC (STM32_TIM14_BASE+STM32_GTIM_PSC_OFFSET) +# define STM32_TIM14_ARR (STM32_TIM14_BASE+STM32_GTIM_ARR_OFFSET) +# define STM32_TIM14_CCR1 (STM32_TIM14_BASE+STM32_GTIM_CCR1_OFFSET) +#endif + +/* Basic Timers - TIM6 and TIM7 */ + +#if STM32_NBTIM > 0 +# define STM32_TIM6_CR1 (STM32_TIM6_BASE+STM32_BTIM_CR1_OFFSET) +# define STM32_TIM6_CR2 (STM32_TIM6_BASE+STM32_BTIM_CR2_OFFSET) +# define STM32_TIM6_DIER (STM32_TIM6_BASE+STM32_BTIM_DIER_OFFSET) +# define STM32_TIM6_SR (STM32_TIM6_BASE+STM32_BTIM_SR_OFFSET) +# define STM32_TIM6_EGR (STM32_TIM6_BASE+STM32_BTIM_EGR_OFFSET) +# define STM32_TIM6_CNT (STM32_TIM6_BASE+STM32_BTIM_CNT_OFFSET) +# define STM32_TIM6_PSC (STM32_TIM6_BASE+STM32_BTIM_PSC_OFFSET) +# define STM32_TIM6_ARR (STM32_TIM6_BASE+STM32_BTIM_ARR_OFFSET) +#endif + +#if STM32_NBTIM > 1 +# define STM32_TIM7_CR1 (STM32_TIM7_BASE+STM32_BTIM_CR1_OFFSET) +# define STM32_TIM7_CR2 (STM32_TIM7_BASE+STM32_BTIM_CR2_OFFSET) +# define STM32_TIM7_DIER (STM32_TIM7_BASE+STM32_BTIM_DIER_OFFSET) +# define STM32_TIM7_SR (STM32_TIM7_BASE+STM32_BTIM_SR_OFFSET) +# define STM32_TIM7_EGR (STM32_TIM7_BASE+STM32_BTIM_EGR_OFFSET) +# define STM32_TIM7_CNT (STM32_TIM7_BASE+STM32_BTIM_CNT_OFFSET) +# define STM32_TIM7_PSC (STM32_TIM7_BASE+STM32_BTIM_PSC_OFFSET) +# define STM32_TIM7_ARR (STM32_TIM7_BASE+STM32_BTIM_ARR_OFFSET) +#endif + +/* Register Bitfield Definitions ********************************************************************/ + +/* Control register 1 */ + +#define ATIM_CR1_CEN (1 << 0) /* Bit 0: Counter enable */ +#define ATIM_CR1_UDIS (1 << 1) /* Bit 1: Update disable */ +#define ATIM_CR1_URS (1 << 2) /* Bit 2: Update request source */ +#define ATIM_CR1_OPM (1 << 3) /* Bit 3: One pulse mode */ +#define ATIM_CR1_DIR (1 << 4) /* Bit 4: Direction */ +#define ATIM_CR1_CMS_SHIFT (5) /* Bits 6-5: Center-aligned mode selection */ +#define ATIM_CR1_CMS_MASK (3 << ATIM_CR1_CMS_SHIFT) +# define ATIM_CR1_EDGE (0 << ATIM_CR1_CMS_SHIFT) /* 00: Edge-aligned mode */ +# define ATIM_CR1_CENTER1 (1 << ATIM_CR1_CMS_SHIFT) /* 01: Center-aligned mode 1 */ +# define ATIM_CR1_CENTER2 (2 << ATIM_CR1_CMS_SHIFT) /* 10: Center-aligned mode 2 */ +# define ATIM_CR1_CENTER3 (3 << ATIM_CR1_CMS_SHIFT) /* 11: Center-aligned mode 3 */ +#define ATIM_CR1_ARPE (1 << 7) /* Bit 7: Auto-reload preload enable */ +#define ATIM_CR1_CKD_SHIFT (8) /* Bits 9-8: Clock division */ +#define ATIM_CR1_CKD_MASK (3 << ATIM_CR1_CKD_SHIFT) +# define ATIM_CR1_TCKINT (0 << ATIM_CR1_CKD_SHIFT) /* 00: tDTS=tCK_INT */ +# define ATIM_CR1_2TCKINT (1 << ATIM_CR1_CKD_SHIFT) /* 01: tDTS=2*tCK_INT */ +# define ATIM_CR1_4TCKINT (2 << ATIM_CR1_CKD_SHIFT) /* 10: tDTS=4*tCK_INT */ + +/* Control register 2 */ + +#define ATIM_CR2_CCPC (1 << 0) /* Bit 0: Capture/Compare Preloaded Control */ +#define ATIM_CR2_CCUS (1 << 2) /* Bit 2: Capture/Compare Control Update Selection */ +#define ATIM_CR2_CCDS (1 << 3) /* Bit 3: Capture/Compare DMA Selection */ +#define ATIM_CR2_MMS_SHIFT (4) /* Bits 6-4: Master Mode Selection */ +#define ATIM_CR2_MMS_MASK (7 << ATIM_CR2_MMS_SHIFT) +#define ATIM_CR2_OC1REF (4 << ATIM_CR2_MMS_SHIFT) /* 100: Compare OC1REF is TRGO */ +#define ATIM_CR2_OC2REF (5 << ATIM_CR2_MMS_SHIFT) /* 101: Compare OC2REF is TRGO */ +#define ATIM_CR2_OC3REF (6 << ATIM_CR2_MMS_SHIFT) /* 110: Compare OC3REF is TRGO */ +#define ATIM_CR2_OC4REF (7 << ATIM_CR2_MMS_SHIFT) /* 111: Compare OC4REF is TRGO */ +#define ATIM_CR2_TI1S (1 << 7) /* Bit 7: TI1 Selection */ +#define ATIM_CR2_OIS1 (1 << 8) /* Bit 8: Output Idle state 1 (OC1 output) */ +#define ATIM_CR2_OIS1N (1 << 9) /* Bit 9: Output Idle state 1 (OC1N output) */ +#define ATIM_CR2_OIS2 (1 << 10) /* Bit 10: Output Idle state 2 (OC2 output) */ +#define ATIM_CR2_OIS2N (1 << 11) /* Bit 11: Output Idle state 2 (OC2N output) */ +#define ATIM_CR2_OIS3 (1 << 12) /* Bit 12: Output Idle state 3 (OC3 output) */ +#define ATIM_CR2_OIS3N (1 << 13) /* Bit 13: Output Idle state 3 (OC3N output) */ +#define ATIM_CR2_OIS4 (1 << 14) /* Bit 14: Output Idle state 4 (OC4 output) */ + +/* Slave mode control register */ + +#define ATIM_SMCR_SMS_SHIFT (0) /* Bits 0-2: Slave mode selection */ +#define ATIM_SMCR_SMS_MASK (7 << ATIM_SMCR_SMS_SHIFT) +# define ATIM_SMCR_DISAB (0 << ATIM_SMCR_SMS_SHIFT) /* 000: Slave mode disabled */ +# define ATIM_SMCR_ENCMD1 (1 << ATIM_SMCR_SMS_SHIFT) /* 001: Encoder mode 1 */ +# define ATIM_SMCR_ENCMD2 (2 << ATIM_SMCR_SMS_SHIFT) /* 010: Encoder mode 2 */ +# define ATIM_SMCR_ENCMD3 (3 << ATIM_SMCR_SMS_SHIFT) /* 011: Encoder mode 3 */ +# define ATIM_SMCR_RESET (4 << ATIM_SMCR_SMS_SHIFT) /* 100: Reset Mode */ +# define ATIM_SMCR_GATED (5 << ATIM_SMCR_SMS_SHIFT) /* 101: Gated Mode */ +# define ATIM_SMCR_TRIGGER (6 << ATIM_SMCR_SMS_SHIFT) /* 110: Trigger Mode */ +# define ATIM_SMCR_EXTCLK1 (7 << ATIM_SMCR_SMS_SHIFT) /* 111: External Clock Mode 1 */ +#define ATIM_SMCR_TS_SHIFT (4) /* Bits 4-6: Trigger selection */ +#define ATIM_SMCR_TS_MASK (7 << ATIM_SMCR_TS_SHIFT) +# define ATIM_SMCR_ITR0 (0 << ATIM_SMCR_TS_SHIFT) /* 000: Internal trigger 0 (ITR0) */ +# define ATIM_SMCR_ITR1 (1 << ATIM_SMCR_TS_SHIFT) /* 001: Internal trigger 1 (ITR1) */ +# define ATIM_SMCR_ITR2 (2 << ATIM_SMCR_TS_SHIFT) /* 010: Internal trigger 2 (ITR2) */ +# define ATIM_SMCR_ITR3 (3 << ATIM_SMCR_TS_SHIFT) /* 011: Internal trigger 3 (ITR3) */ +# define ATIM_SMCR_T1FED (4 << ATIM_SMCR_TS_SHIFT) /* 100: TI1 Edge Detector (TI1F_ED) */ +# define ATIM_SMCR_TI1FP1 (5 << ATIM_SMCR_TS_SHIFT) /* 101: Filtered Timer Input 1 (TI1FP1) */ +# define ATIM_SMCR_T12FP2 (6 << ATIM_SMCR_TS_SHIFT) /* 110: Filtered Timer Input 2 (TI2FP2) */ +# define ATIM_SMCR_ETRF (7 << ATIM_SMCR_TS_SHIFT) /* 111: External Trigger input (ETRF) */ +#define ATIM_SMCR_MSM (1 << 7) /* Bit 7: Master/slave mode */ +#define ATIM_SMCR_ETF_SHIFT (8) /* Bits 8-11: External trigger filter */ +#define ATIM_SMCR_ETF_MASK (0x0f << ATIM_SMCR_ETF_SHIFT) +# define ATIM_SMCR_NOFILT (0 << ATIM_SMCR_ETF_SHIFT) /* 0000: No filter, sampling is done at fDTS */ +# define ATIM_SMCR_FCKINT2 (1 << ATIM_SMCR_ETF_SHIFT) /* 0001: fSAMPLING=fCK_INT, N=2 */ +# define ATIM_SMCR_FCKINT4 (2 << ATIM_SMCR_ETF_SHIFT) /* 0010: fSAMPLING=fCK_INT, N=4 */ +# define ATIM_SMCR_FCKINT8 (3 << ATIM_SMCR_ETF_SHIFT) /* 0011: fSAMPLING=fCK_INT, N=8 */ +# define ATIM_SMCR_FDTSd26 (4 << ATIM_SMCR_ETF_SHIFT) /* 0100: fSAMPLING=fDTS/2, N=6 */ +# define ATIM_SMCR_FDTSd28 (5 << ATIM_SMCR_ETF_SHIFT) /* 0101: fSAMPLING=fDTS/2, N=8 */ +# define ATIM_SMCR_FDTSd46 (6 << ATIM_SMCR_ETF_SHIFT) /* 0110: fSAMPLING=fDTS/4, N=6 */ +# define ATIM_SMCR_FDTSd48 (7 << ATIM_SMCR_ETF_SHIFT) /* 0111: fSAMPLING=fDTS/4, N=8 */ +# define ATIM_SMCR_FDTSd86 (8 << ATIM_SMCR_ETF_SHIFT) /* 1000: fSAMPLING=fDTS/8, N=6 */ +# define ATIM_SMCR_FDTSd88 (9 << ATIM_SMCR_ETF_SHIFT) /* 1001: fSAMPLING=fDTS/8, N=8 */ +# define ATIM_SMCR_FDTSd165 (10 << ATIM_SMCR_ETF_SHIFT) /* 1010: fSAMPLING=fDTS/16, N=5 */ +# define ATIM_SMCR_FDTSd166 (11 << ATIM_SMCR_ETF_SHIFT) /* 1011: fSAMPLING=fDTS/16, N=6 */ +# define ATIM_SMCR_FDTSd168 (12 << ATIM_SMCR_ETF_SHIFT) /* 1100: fSAMPLING=fDTS/16, N=8 */ +# define ATIM_SMCR_FDTSd325 (13 << ATIM_SMCR_ETF_SHIFT) /* 1101: fSAMPLING=fDTS/32, N=5 */ +# define ATIM_SMCR_FDTSd326 (14 << ATIM_SMCR_ETF_SHIFT) /* 1110: fSAMPLING=fDTS/32, N=6 */ +# define ATIM_SMCR_FDTSd328 (15 << ATIM_SMCR_ETF_SHIFT) /* 1111: fSAMPLING=fDTS/32, N=8 */ +#define ATIM_SMCR_ETPS_SHIFT (12) /* Bits 12-13: External trigger prescaler */ +#define ATIM_SMCR_ETPS_MASK (3 << ATIM_SMCR_ETPS_SHIFT) +# define ATIM_SMCR_PSCOFF (0 << ATIM_SMCR_ETPS_SHIFT) /* 00: Prescaler OFF */ +# define ATIM_SMCR_ETRPd2 (1 << ATIM_SMCR_ETPS_SHIFT) /* 01: ETRP frequency divided by 2 */ +# define ATIM_SMCR_ETRPd4 (2 << ATIM_SMCR_ETPS_SHIFT) /* 10: ETRP frequency divided by 4 */ +# define ATIM_SMCR_ETRPd8 (3 << ATIM_SMCR_ETPS_SHIFT) /* 11: ETRP frequency divided by 8 */ +#define ATIM_SMCR_ECE (1 << 14) /* Bit 14: External clock enable */ +#define ATIM_SMCR_ETP (1 << 15) /* Bit 15: External trigger polarity */ + +/* DMA/Interrupt enable register */ + +#define ATIM_DIER_UIE (1 << 0) /* Bit 0: Update interrupt enable */ +#define ATIM_DIER_CC1IE (1 << 1) /* Bit 1: Capture/Compare 1 interrupt enable */ +#define ATIM_DIER_CC2IE (1 << 2) /* Bit 2: Capture/Compare 2 interrupt enable */ +#define ATIM_DIER_CC3IE (1 << 3) /* Bit 3: Capture/Compare 3 interrupt enable */ +#define ATIM_DIER_CC4IE (1 << 4) /* Bit 4: Capture/Compare 4 interrupt enable */ + +#ifdef CONFIG_STM32_STM32F10XX +# define ATIM_DIER_COMIE (1 << 5) /* Bit 5: COM interrupt enable */ +#endif + +#define ATIM_DIER_TIE (1 << 6) /* Bit 6: Trigger interrupt enable */ + +#ifdef CONFIG_STM32_STM32F10XX +# define ATIM_DIER_BIE (1 << 7) /* Bit 7: Break interrupt enable */ +#endif + +#define ATIM_DIER_UDE (1 << 8) /* Bit 8: Update DMA request enable */ +#define ATIM_DIER_CC1DE (1 << 9) /* Bit 9: Capture/Compare 1 DMA request enable */ +#define ATIM_DIER_CC2DE (1 << 10) /* Bit 10: Capture/Compare 2 DMA request enable */ +#define ATIM_DIER_CC3DE (1 << 11) /* Bit 11: Capture/Compare 3 DMA request enable */ +#define ATIM_DIER_CC4DE (1 << 12) /* Bit 12: Capture/Compare 4 DMA request enable */ + +#ifdef CONFIG_STM32_STM32F10XX +# define ATIM_DIER_COMDE (1 << 13) /* Bit 13: COM DMA request enable */ +#endif + +#define ATIM_DIER_TDE (1 << 14) /* Bit 14: Trigger DMA request enable */ + +/* Status register */ + +#define ATIM_SR_UIF (1 << 0) /* Bit 0: Update interrupt Flag */ +#define ATIM_SR_CC1IF (1 << 1) /* Bit 1: Capture/Compare 1 interrupt Flag */ +#define ATIM_SR_CC2IF (1 << 2) /* Bit 2: Capture/Compare 2 interrupt Flag */ +#define ATIM_SR_CC3IF (1 << 3) /* Bit 3: Capture/Compare 3 interrupt Flag */ +#define ATIM_SR_CC4IF (1 << 4) /* Bit 4: Capture/Compare 4 interrupt Flag */ +#define ATIM_SR_COMIF (1 << 5) /* Bit 5: COM interrupt Flag */ +#define ATIM_SR_TIF (1 << 6) /* Bit 6: Trigger interrupt Flag */ + +#ifdef CONFIG_STM32_STM32F10XX +# define ATIM_SR_BIF (1 << 7) /* Bit 7: Break interrupt Flag */ +#endif + +#define ATIM_SR_CC1OF (1 << 9) /* Bit 9: Capture/Compare 1 Overcapture Flag */ +#define ATIM_SR_CC2OF (1 << 10) /* Bit 10: Capture/Compare 2 Overcapture Flag */ +#define ATIM_SR_CC3OF (1 << 11) /* Bit 11: Capture/Compare 3 Overcapture Flag */ +#define ATIM_SR_CC4OF (1 << 12) /* Bit 12: Capture/Compare 4 Overcapture Flag */ + +/* Event generation register */ + +#define ATIM_EGR_UG (1 << 0) /* Bit 0: Update Generation */ +#define ATIM_EGR_CC1G (1 << 1) /* Bit 1: Capture/Compare 1 Generation */ +#define ATIM_EGR_CC2G (1 << 2) /* Bit 2: Capture/Compare 2 Generation */ +#define ATIM_EGR_CC3G (1 << 3) /* Bit 3: Capture/Compare 3 Generation */ +#define ATIM_EGR_CC4G (1 << 4) /* Bit 4: Capture/Compare 4 Generation */ + +#ifdef CONFIG_STM32_STM32F10XX +# define ATIM_EGR_COMG (1 << 5) /* Bit 5: Capture/Compare Control Update Generation */ +#endif + +#define ATIM_EGR_TG (1 << 6) /* Bit 6: Trigger Generation */ + +#ifdef CONFIG_STM32_STM32F10XX +# define ATIM_EGR_BG (1 << 7) /* Bit 7: Break Generation */ +#endif + +/* Capture/compare mode register 1 -- Output compare mode */ + +#define ATIM_CCMR1_CC1S_SHIFT (0) /* Bits 1-0: Capture/Compare 1 Selection */ +#define ATIM_CCMR1_CC1S_MASK (3 << ATIM_CCMR1_CC1S_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR1_OC1FE (1 << 2) /* Bit 2: Output Compare 1 Fast enable */ +#define ATIM_CCMR1_OC1PE (1 << 3) /* Bit 3: Output Compare 1 Preload enable */ +#define ATIM_CCMR1_OC1M_SHIFT (4) /* Bits 6-4: Output Compare 1 Mode */ +#define ATIM_CCMR1_OC1M_MASK (7 << ATIM_CCMR1_OC1M_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR1_OC1CE (1 << 7) /* Bit 7: Output Compare 1Clear Enable */ +#define ATIM_CCMR1_CC2S_SHIFT (8) /* Bits 8-9: Capture/Compare 2 Selection */ +#define ATIM_CCMR1_CC2S_MASK (3 << ATIM_CCMR1_CC2S_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR1_OC2FE (1 << 10) /* Bit 10: Output Compare 2 Fast enable */ +#define ATIM_CCMR1_OC2PE (1 << 11) /* Bit 11: Output Compare 2 Preload enable */ +#define ATIM_CCMR1_OC2M_SHIFT (12) /* Bits 14-12: Output Compare 2 Mode */ +#define ATIM_CCMR1_OC2M_MASK (7 << ATIM_CCMR1_OC2M_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR1_OC2CE (1 << 15) /* Bit 15: Output Compare 2 Clear Enable */ + +/* Common CCMR (unshifted) Capture/Compare Selection bit-field definitions */ + +#define ATIM_CCMR_CCS_CCOUT (0) /* 00: CCx channel output */ +#define ATIM_CCMR_CCS_CCIN1 (1) /* 01: CCx channel input, ICx is TIx */ +#define ATIM_CCMR_CCS_CCIN2 (2) /* 10: CCx channel input, ICx is TIy */ +#define ATIM_CCMR_CCS_CCINTRC (3) /* 11: CCx channel input, ICx is TRC */ + +/* Common CCMR (unshifted) Compare Mode bit field definitions */ + +#define ATIM_CCMR_MODE_FRZN (0) /* 000: Frozen */ +#define ATIM_CCMR_MODE_CHACT (1) /* 001: Channel x active on match */ +#define ATIM_CCMR_MODE_CHINACT (2) /* 010: Channel x inactive on match */ +#define ATIM_CCMR_MODE_OCREFTOG (3) /* 011: OCxREF toggle ATIM_CNT=ATIM_CCRx */ +#define ATIM_CCMR_MODE_OCREFLO (4) /* 100: OCxREF forced low */ +#define ATIM_CCMR_MODE_OCREFHI (5) /* 101: OCxREF forced high */ +#define ATIM_CCMR_MODE_PWM1 (6) /* 110: PWM mode 1 */ +#define ATIM_CCMR_MODE_PWM2 (7) /* 111: PWM mode 2 */ + +/* Capture/compare mode register 1 -- Input capture mode */ + + /* Bits 1-0:(same as output compare mode) */ +#define ATIM_CCMR1_IC1PSC_SHIFT (2) /* Bits 3-2: Input Capture 1 Prescaler */ +#define ATIM_CCMR1_IC1PSC_MASK (3 << ATIM_CCMR1_IC1PSC_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR1_IC1F_SHIFT (4) /* Bits 7-4: Input Capture 1 Filter */ +#define ATIM_CCMR1_IC1F_MASK (0x0f << ATIM_CCMR1_IC1F_SHIFT) + /* (See common (unshifted) bit field definitions below) */ + /* Bits 9:8 (same as output compare mode) */ +#define ATIM_CCMR1_IC2PSC_SHIFT (10) /* Bits 11:10: Input Capture 2 Prescaler */ +#define ATIM_CCMR1_IC2PSC_MASK (3 << ATIM_CCMR1_IC2PSC_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR1_IC2F_SHIFT (12) /* Bits 15-12: Input Capture 2 Filter */ +#define ATIM_CCMR1_IC2F_MASK (0x0f << ATIM_CCMR1_IC2F_SHIFT) + /* (See common (unshifted) bit field definitions below) */ + +/* Common CCMR (unshifted) Input Capture Prescaler bit-field definitions */ + +#define ATIM_CCMR_ICPSC_NOPSC (0) /* 00: no prescaler, capture each edge */ +#define ATIM_CCMR_ICPSC_EVENTS2 (1) /* 01: capture once every 2 events */ +#define ATIM_CCMR_ICPSC_EVENTS4 (2) /* 10: capture once every 4 events */ +#define ATIM_CCMR_ICPSC_EVENTS8 (3) /* 11: capture once every 8 events */ + +/* Common CCMR (unshifted) Input Capture Filter bit-field definitions */ + +#define ATIM_CCMR_ICF_NOFILT (0) /* 0000: No filter, sampling at fDTS */ +#define ATIM_CCMR_ICF_FCKINT2 (1) /* 0001: fSAMPLING=fCK_INT, N=2 */ +#define ATIM_CCMR_ICF_FCKINT4 (2) /* 0010: fSAMPLING=fCK_INT, N=4 */ +#define ATIM_CCMR_ICF_FCKINT8 (3) /* 0011: fSAMPLING=fCK_INT, N=8 */ +#define ATIM_CCMR_ICF_FDTSd26 (4) /* 0100: fSAMPLING=fDTS/2, N=6 */ +#define ATIM_CCMR_ICF_FDTSd28 (5) /* 0101: fSAMPLING=fDTS/2, N=8 */ +#define ATIM_CCMR_ICF_FDTSd46 (6) /* 0110: fSAMPLING=fDTS/4, N=6 */ +#define ATIM_CCMR_ICF_FDTSd48 (7) /* 0111: fSAMPLING=fDTS/4, N=8 */ +#define ATIM_CCMR_ICF_FDTSd86 (8) /* 1000: fSAMPLING=fDTS/8, N=6 */ +#define ATIM_CCMR_ICF_FDTSd88 (9) /* 1001: fSAMPLING=fDTS/8, N=8 */ +#define ATIM_CCMR_ICF_FDTSd165 (10) /* 1010: fSAMPLING=fDTS/16, N=5 */ +#define ATIM_CCMR_ICF_FDTSd166 (11) /* 1011: fSAMPLING=fDTS/16, N=6 */ +#define ATIM_CCMR_ICF_FDTSd168 (12) /* 1100: fSAMPLING=fDTS/16, N=8 */ +#define ATIM_CCMR_ICF_FDTSd325 (13) /* 1101: fSAMPLING=fDTS/32, N=5 */ +#define ATIM_CCMR_ICF_FDTSd326 (14) /* 1110: fSAMPLING=fDTS/32, N=6 */ +#define ATIM_CCMR_ICF_FDTSd328 (15) /* 1111: fSAMPLING=fDTS/32, N=8 */ + +/* Capture/compare mode register 2 - Output Compare mode */ + +#define ATIM_CCMR2_CC3S_SHIFT (0) /* Bits 1-0: Capture/Compare 3 Selection */ +#define ATIM_CCMR2_CC3S_MASK (3 << ATIM_CCMR2_CC3S_SHIFT) + /* (See common (unshifted) bit field definitions above) */ +#define ATIM_CCMR2_OC3FE (1 << 2) /* Bit 2: Output Compare 3 Fast enable */ +#define ATIM_CCMR2_OC3PE (1 << 3) /* Bit 3: Output Compare 3 Preload enable */ +#define ATIM_CCMR2_OC3M_SHIFT (4) /* Bits 6-4: Output Compare 3 Mode */ +#define ATIM_CCMR2_OC3M_MASK (7 << ATIM_CCMR2_OC3M_SHIFT) + /* (See common (unshifted) bit field definitions above) */ +#define ATIM_CCMR2_OC3CE (1 << 7) /* Bit 7: Output Compare 3 Clear Enable */ +#define ATIM_CCMR2_CC4S_SHIFT (8) /* Bits 9-8: Capture/Compare 4 Selection */ +#define ATIM_CCMR2_CC4S_MASK (3 << ATIM_CCMR2_CC4S_SHIFT) + /* (See common (unshifted) bit field definitions above) */ +#define ATIM_CCMR2_OC4FE (1 << 10) /* Bit 10: Output Compare 4 Fast enable */ +#define ATIM_CCMR2_OC4PE (1 << 11) /* Bit 11: Output Compare 4 Preload enable */ +#define ATIM_CCMR2_OC4M_SHIFT (12) /* Bits 14-12: Output Compare 4 Mode */ +#define ATIM_CCMR2_OC4M_MASK (7 << ATIM_CCMR2_OC4M_SHIFT) + /* (See common (unshifted) bit field definitions above) */ +#define ATIM_CCMR2_OC4CE (1 << 15) /* Bit 15: Output Compare 4 Clear Enable */ + +/* Capture/compare mode register 2 - Input Capture Mode */ + + /* Bits 1-0:(same as output compare mode) */ +#define ATIM_CCMR2_IC3PSC_SHIFT (2) /* Bits 3-2: Input Capture 3 Prescaler */ +#define ATIM_CCMR1_IC3PSC_MASK (3 << ATIM_CCMR2_IC3PSC_SHIFT) + /* (See common (unshifted) bit field definitions above) */ +#define ATIM_CCMR2_IC3F_SHIFT (4) /* Bits 7-4: Input Capture 3 Filter */ +#define ATIM_CCMR2_IC3F_MASK (0x0f << ATIM_CCMR2_IC3F_SHIFT) + /* (See common (unshifted) bit field definitions above) */ + /* Bits 9:8 (same as output compare mode) */ +#define ATIM_CCMR2_IC4PSC_SHIFT (10) /* Bits 11:10: Input Capture 4 Prescaler */ +#define ATIM_CCMR2_IC4PSC_MASK (3 << ATIM_CCMR2_IC4PSC_SHIFT) + /* (See common (unshifted) bit field definitions above) */ +#define ATIM_CCMR2_IC4F_SHIFT (12) /* Bits 15-12: Input Capture 4 Filter */ +#define ATIM_CCMR2_IC4F_MASK (0x0f << ATIM_CCMR2_IC4F_SHIFT) + /* (See common (unshifted) bit field definitions above) */ + +/* Capture/compare enable register */ + +#define ATIM_CCER_CC1E (1 << 0) /* Bit 0: Capture/Compare 1 output enable */ +#define ATIM_CCER_CC1P (1 << 1) /* Bit 1: Capture/Compare 1 output Polarity */ +#define ATIM_CCER_CC1NE (1 << 2) /* Bit 2: Capture/Compare 1 Complementary output enable */ +#define ATIM_CCER_CC1NP (1 << 3) /* Bit 3: Capture/Compare 1 Complementary output Polarity */ +#define ATIM_CCER_CC2E (1 << 4) /* Bit 4: Capture/Compare 2 output enable */ +#define ATIM_CCER_CC2P (1 << 5) /* Bit 5: Capture/Compare 2 output Polarity */ +#define ATIM_CCER_CC2NE (1 << 6) /* Bit 6: Capture/Compare 2 Complementary output enable */ +#define ATIM_CCER_CC2NP (1 << 7) /* Bit 7: Capture/Compare 2 Complementary output Polarity */ +#define ATIM_CCER_CC3E (1 << 8) /* Bit 8: Capture/Compare 3 output enable */ +#define ATIM_CCER_CC3P (1 << 9) /* Bit 9: Capture/Compare 3 output Polarity */ +#define ATIM_CCER_CC3NE (1 << 10) /* Bit 10: Capture/Compare 3 Complementary output enable */ +#define ATIM_CCER_CC3NP (1 << 11) /* Bit 11: Capture/Compare 3 Complementary output Polarity */ +#define ATIM_CCER_CC4E (1 << 12) /* Bit 12: Capture/Compare 4 output enable */ +#define ATIM_CCER_CC4P (1 << 13) /* Bit 13: Capture/Compare 4 output Polarity */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define ATIM_CCER_CC4NP (1 << 15) /* Bit 15: Capture/Compare 4 output Polarity */ +#endif + +/* Repetition counter register */ + +#define ATIM_RCR_REP_SHIFT (0) /* Bits 7-0: Repetition Counter Value */ +#define ATIM_RCR_REP_MASK (0xff << ATIM_RCR_REP_SHIFT) + +#define ATIM_RCR_REP_MAX 128 + +/* Break and dead-time register */ + +#define ATIM_BDTR_DTG_SHIFT (0) /* Bits 7:0 [7:0]: Dead-Time Generator set-up */ +#define ATIM_BDTR_DTG_MASK (0xff << ATIM_BDTR_DTG_SHIFT) +#define ATIM_BDTR_LOCK_SHIFT (8) /* Bits 9:8 [1:0]: Lock Configuration */ +#define ATIM_BDTR_LOCK_MASK (3 << ATIM_BDTR_LOCK_SHIFT) +# define ATIM_BDTR_LOCKOFF (0 << ATIM_BDTR_LOCK_SHIFT) /* 00: LOCK OFF - No bit is write protected */ +# define ATIM_BDTR_LOCK1 (1 << ATIM_BDTR_LOCK_SHIFT) /* 01: LOCK Level 1 protection */ +# define ATIM_BDTR_LOCK2 (2 << ATIM_BDTR_LOCK_SHIFT) /* 10: LOCK Level 2 protection */ +# define ATIM_BDTR_LOCK3 (3 << ATIM_BDTR_LOCK_SHIFT) /* 11: LOCK Level 3 protection */ */ +#define ATIM_BDTR_OSSI (1 << 10) /* Bit 10: Off-State Selection for Idle mode */ +#define ATIM_BDTR_OSSR (1 << 11) /* Bit 11: Off-State Selection for Run mode */ +#define ATIM_BDTR_BKE (1 << 12) /* Bit 12: Break enable */ +#define ATIM_BDTR_BKP (1 << 13) /* Bit 13: Break Polarity */ +#define ATIM_BDTR_AOE (1 << 14) /* Bit 14: Automatic Output enable */ +#define ATIM_BDTR_MOE (1 << 15) /* Bit 15: Main Output enable */ + +/* DMA control register */ + +#define ATIM_DCR_DBL_SHIFT (8) /* Bits 12-8: DMA Burst Length */ +#define ATIM_DCR_DBL_MASK (0x1f << ATIM_DCR_DBL_SHIFT) +# define ATIM_DCR_DBL(n) (((n)-1) << ATIM_DCR_DBL_SHIFT) /* n transfers, n = 1..18 */ +#define ATIM_DCR_DBA_SHIFT (0) /* Bits 4-0: DMA Base Address */ +#define ATIM_DCR_DBA_MASK (0x1f << ATIM_DCR_DBA_SHIFT) + +/* Control register 1 (TIM2-5 and TIM9-14) */ + +#define GTIM_CR1_CEN (1 << 0) /* Bit 0: Counter enable */ +#define GTIM_CR1_UDIS (1 << 1) /* Bit 1: Update Disable */ +#define GTIM_CR1_URS (1 << 2) /* Bit 2: Update Request Source */ +#define GTIM_CR1_OPM (1 << 3) /* Bit 3: One Pulse Mode (TIM2-5, 9, and 12 only) */ +#define GTIM_CR1_DIR (1 << 4) /* Bit 4: Direction (TIM2-5 only) */ +#define GTIM_CR1_CMS_SHIFT (5) /* Bits 6-5: Center-aligned Mode Selection (TIM2-5 only) */ +#define GTIM_CR1_CMS_MASK (3 << GTIM_CR1_CMS_SHIFT) +# define GTIM_CR1_EDGE (0 << GTIM_CR1_CMS_SHIFT) /* 00: Edge-aligned mode. */ +# define GTIM_CR1_CENTER1 (1 << GTIM_CR1_CMS_SHIFT) /* 01: Center-aligned mode 1 */ +# define GTIM_CR1_CENTER2 (2 << GTIM_CR1_CMS_SHIFT) /* 10: Center-aligned mode 2 */ +# define GTIM_CR1_CENTER3 (3 << GTIM_CR1_CMS_SHIFT) /* 11: Center-aligned mode 3 */ +#define GTIM_CR1_ARPE (1 << 7) /* Bit 7: Auto-Reload Preload enable */ +#define GTIM_CR1_CKD_SHIFT (8) /* Bits 9-8: Clock Division */ +#define GTIM_CR1_CKD_MASK (3 << GTIM_CR1_CKD_SHIFT) +# define GTIM_CR1_TCKINT (0 << GTIM_CR1_CKD_SHIFT) /* 00: tDTS = tCK_INT */ +# define GTIM_CR1_2TCKINT (1 << GTIM_CR1_CKD_SHIFT) /* 01: tDTS = 2 x tCK_INT */ +# define GTIM_CR1_4TCKINT (2 << GTIM_CR1_CKD_SHIFT) /* 10: tDTS = 4 x tCK_INT */ + +/* Control register 2 (TIM2-5 and TIM9/12 only) */ + +#define GTIM_CR2_CCDS (1 << 3) /* Bit 3: Capture/Compare DMA Selection (TIM2-5 only) */ +#define GTIM_CR2_MMS_SHIFT (4) /* Bits 6-4: Master Mode Selection */ +#define GTIM_CR2_MMS_MASK (7 << GTIM_CR2_MMS_SHIFT) +# define GTIM_CR2_RESET (0 << GTIM_CR2_MMS_SHIFT) /* 000: Reset */ +# define GTIM_CR2_ENAB (1 << GTIM_CR2_MMS_SHIFT) /* 001: Enable */ +# define GTIM_CR2_UPDT (2 << GTIM_CR2_MMS_SHIFT) /* 010: Update */ +# define GTIM_CR2_CMPP (3 << GTIM_CR2_MMS_SHIFT) /* 011: Compare Pulse */ +# define GTIM_CR2_CMP1 (4 << GTIM_CR2_MMS_SHIFT) /* 100: Compare - OC1REF signal is used as trigger output (TRGO) */ +# define GTIM_CR2_CMP2 (5 << GTIM_CR2_MMS_SHIFT) /* 101: Compare - OC2REF signal is used as trigger output (TRGO) */ +# define GTIM_CR2_CMP3 (6 << GTIM_CR2_MMS_SHIFT) /* 110: Compare - OC3REF signal is used as trigger output (TRGO, TIM2-5 only) */ +# define GTIM_CR2_CMP4 (7 << GTIM_CR2_MMS_SHIFT) /* 111: Compare - OC4REF signal is used as trigger output (TRGO, TIM2-5 only) */ +#define GTIM_CR2_TI1S (1 << 7) /* Bit 7: TI1 Selection */ + +/* Slave mode control register (TIM2-5 only) */ + +#define GTIM_SMCR_SMS_SHIFT (0) /* Bits 2-0: Slave Mode Selection */ +#define GTIM_SMCR_SMS_MASK (7 << GTIM_SMCR_SMS_SHIFT) +# define GTIM_SMCR_DISAB (0 << GTIM_SMCR_SMS_SHIFT) /* 000: Slave mode disabled */ +# define GTIM_SMCR_ENCMD1 (1 << GTIM_SMCR_SMS_SHIFT) /* 001: Encoder mode 1 */ +# define GTIM_SMCR_ENCMD2 (2 << GTIM_SMCR_SMS_SHIFT) /* 010: Encoder mode 2 */ +# define GTIM_SMCR_ENCMD3 (3 << GTIM_SMCR_SMS_SHIFT) /* 011: Encoder mode 3 */ +# define GTIM_SMCR_RESET (4 << GTIM_SMCR_SMS_SHIFT) /* 100: Reset Mode */ +# define GTIM_SMCR_GATED (5 << GTIM_SMCR_SMS_SHIFT) /* 101: Gated Mode */ +# define GTIM_SMCR_TRIGGER (6 << GTIM_SMCR_SMS_SHIFT) /* 110: Trigger Mode */ +# define GTIM_SMCR_EXTCLK1 (7 << GTIM_SMCR_SMS_SHIFT) /* 111: External Clock Mode 1 */ +#define GTIM_SMCR_TS_SHIFT (4) /* Bits 6-4: Trigger Selection */ +#define GTIM_SMCR_TS_MASK (7 << GTIM_SMCR_TS_SHIFT) +# define GTIM_SMCR_ITR0 (0 << GTIM_SMCR_TS_SHIFT) /* 000: Internal Trigger 0 (ITR0). TIM1 */ +# define GTIM_SMCR_ITR1 (1 << GTIM_SMCR_TS_SHIFT) /* 001: Internal Trigger 1 (ITR1). TIM2 */ +# define GTIM_SMCR_ITR2 (2 << GTIM_SMCR_TS_SHIFT) /* 010: Internal Trigger 2 (ITR2). TIM3 */ +# define GTIM_SMCR_ITR3 (3 << GTIM_SMCR_TS_SHIFT) /* 011: Internal Trigger 3 (ITR3). TIM4 */ +# define GTIM_SMCR_TI1FED (4 << GTIM_SMCR_TS_SHIFT) /* 100: TI1 Edge Detector (TI1F_ED) */ +# define GTIM_SMCR_TI1FP1 (5 << GTIM_SMCR_TS_SHIFT) /* 101: Filtered Timer Input 1 (TI1FP1) */ +# define GTIM_SMCR_TI2FP2 (6 << GTIM_SMCR_TS_SHIFT) /* 110: Filtered Timer Input 2 (TI2FP2) */ +# define GTIM_SMCR_ETRF (7 << GTIM_SMCR_TS_SHIFT) /* 111: External Trigger input (ETRF) */ +#define GTIM_SMCR_MSM (1 << 7) /* Bit 7: Master/Slave mode */ +#define GTIM_SMCR_ETF_SHIFT (8) /* Bits 11-8: External Trigger Filter */ +#define GTIM_SMCR_ETF_MASK (0x0f << GTIM_SMCR_ETF_SHIFT) +# define GTIM_SMCR_NOFILT (0 << GTIM_SMCR_ETF_SHIFT) /* 0000: No filter, sampling is done at fDTS */ +# define GTIM_SMCR_FCKINT2 (1 << GTIM_SMCR_ETF_SHIFT) /* 0001: fSAMPLING=fCK_INT, N=2 */ +# define GTIM_SMCR_FCKINT4 (2 << GTIM_SMCR_ETF_SHIFT) /* 0010: fSAMPLING=fCK_INT, N=4 */ +# define GTIM_SMCR_FCKINT8 (3 << GTIM_SMCR_ETF_SHIFT) /* 0011: fSAMPLING=fCK_INT, N=8 */ +# define GTIM_SMCR_FDTSd26 (4 << GTIM_SMCR_ETF_SHIFT) /* 0100: fSAMPLING=fDTS/2, N=6 */ +# define GTIM_SMCR_FDTSd28 (5 << GTIM_SMCR_ETF_SHIFT) /* 0101: fSAMPLING=fDTS/2, N=8 */ +# define GTIM_SMCR_FDTSd36 (6 << GTIM_SMCR_ETF_SHIFT) /* 0110: fSAMPLING=fDTS/4, N=6 */ +# define GTIM_SMCR_FDTSd38 (7 << GTIM_SMCR_ETF_SHIFT) /* 0111: fSAMPLING=fDTS/4, N=8 */ +# define GTIM_SMCR_FDTSd86 (8 << GTIM_SMCR_ETF_SHIFT) /* 1000: fSAMPLING=fDTS/8, N=6 */ +# define GTIM_SMCR_FDTSd88 (9 << GTIM_SMCR_ETF_SHIFT) /* 1001: fSAMPLING=fDTS/8, N=8 */ +# define GTIM_SMCR_FDTSd165 (10 << GTIM_SMCR_ETF_SHIFT) /* 1010: fSAMPLING=fDTS/16, N=5 */ +# define GTIM_SMCR_FDTSd166 (11 << GTIM_SMCR_ETF_SHIFT) /* 1011: fSAMPLING=fDTS/16, N=6 */ +# define GTIM_SMCR_FDTSd168 (12 << GTIM_SMCR_ETF_SHIFT) /* 1100: fSAMPLING=fDTS/16, N=8 */ +# define GTIM_SMCR_FDTSd325 (13 << GTIM_SMCR_ETF_SHIFT) /* 1101: fSAMPLING=fDTS/32, N=5 */ +# define GTIM_SMCR_FDTSd326 (14 << GTIM_SMCR_ETF_SHIFT) /* 1110: fSAMPLING=fDTS/32, N=6 */ +# define GTIM_SMCR_FDTSd328 (15 << GTIM_SMCR_ETF_SHIFT) /* 1111: fSAMPLING=fDTS/32, N=8 */ +#define GTIM_SMCR_ETPS_SHIFT (12) /* Bits 13-12: External Trigger Prescaler */ +#define GTIM_SMCR_ETPS_MASK (3 << GTIM_SMCR_ETPS_SHIFT) +# define GTIM_SMCR_PSCOFF (0 << GTIM_SMCR_ETPS_SHIFT) /* 00: Prescaler OFF */ +# define GTIM_SMCR_ETRPd2 (1 << GTIM_SMCR_ETPS_SHIFT) /* 01: ETRP frequency divided by 2 */ +# define GTIM_SMCR_ETRPd4 (2 << GTIM_SMCR_ETPS_SHIFT) /* 10: ETRP frequency divided by 4 */ +# define GTIM_SMCR_ETRPd8 (3 << GTIM_SMCR_ETPS_SHIFT) /* 11: ETRP frequency divided by 8 */ +#define GTIM_SMCR_ECE (1 << 14) /* Bit 14: External Clock enable */ +#define GTIM_SMCR_ETP (1 << 15) /* Bit 15: External Trigger Polarity */ + +/* DMA/Interrupt enable register (TIM2-5 and TIM9-14) */ + +#define GTIM_DIER_UIE (1 << 0) /* Bit 0: Update interrupt enable */ +#define GTIM_DIER_CC1IE (1 << 1) /* Bit 1: Capture/Compare 1 interrupt enable */ +#define GTIM_DIER_CC2IE (1 << 2) /* Bit 2: Capture/Compare 2 interrupt enable (TIM2-5,9,&12 only) */ +#define GTIM_DIER_CC3IE (1 << 3) /* Bit 3: Capture/Compare 3 interrupt enable (TIM2-5 only) */ +#define GTIM_DIER_CC4IE (1 << 4) /* Bit 4: Capture/Compare 4 interrupt enable (TIM2-5 only) */ +#define GTIM_DIER_TIE (1 << 6) /* Bit 6: Trigger interrupt enable (TIM2-5,9,&12 only) */ +#define GTIM_DIER_UDE (1 << 8) /* Bit 8: Update DMA request enable (TIM2-5 only) */ +#define GTIM_DIER_CC1DE (1 << 9) /* Bit 9: Capture/Compare 1 DMA request enable (TIM2-5 only) */ +#define GTIM_DIER_CC2DE (1 << 10) /* Bit 10: Capture/Compare 2 DMA request enable (TIM2-5 only) */ +#define GTIM_DIER_CC3DE (1 << 11) /* Bit 11: Capture/Compare 3 DMA request enable (TIM2-5 only) */ +#define GTIM_DIER_CC4DE (1 << 12) /* Bit 12: Capture/Compare 4 DMA request enable (TIM2-5 only) */ +#define GTIM_DIER_TDE (1 << 14) /* Bit 14: Trigger DMA request enable (TIM2-5 only) */ + +/* Status register */ + +#define GTIM_SR_UIF (1 << 0) /* Bit 0: Update interrupt flag */ +#define GTIM_SR_CC1IF (1 << 1) /* Bit 1: Capture/compare 1 interrupt Flag */ +#define GTIM_SR_CC2IF (1 << 2) /* Bit 2: Capture/Compare 2 interrupt Flag (TIM2-5,9,&12 only) */ +#define GTIM_SR_CC3IF (1 << 3) /* Bit 3: Capture/Compare 3 interrupt Flag (TIM2-5 only) */ +#define GTIM_SR_CC4IF (1 << 4) /* Bit 4: Capture/Compare 4 interrupt Flag (TIM2-5 only) */ +#define GTIM_SR_TIF (1 << 6) /* Bit 6: Trigger interrupt Flag (TIM2-5,9,&12 only) */ +#define GTIM_SR_CC1OF (1 << 9) /* Bit 9: Capture/Compare 1 Overcapture Flag */ +#define GTIM_SR_CC2OF (1 << 10) /* Bit 10: Capture/Compare 2 Overcapture Flag (TIM2-5,9,&12 only) */ +#define GTIM_SR_CC3OF (1 << 11) /* Bit 11: Capture/Compare 3 Overcapture Flag (TIM2-5 only) */ +#define GTIM_SR_CC4OF (1 << 12) /* Bit 12: Capture/Compare 4 Overcapture Flag (TIM2-5 only) */ + +/* Event generation register (TIM2-5 and TIM9-14) */ + +#define GTIM_EGR_UG (1 << 0) /* Bit 0: Update generation */ +#define GTIM_EGR_CC1G (1 << 1) /* Bit 1: Capture/compare 1 generation */ +#define GTIM_EGR_CC2G (1 << 2) /* Bit 2: Capture/compare 2 generation (TIM2-5,9,&12 only) */ +#define GTIM_EGR_CC3G (1 << 3) /* Bit 3: Capture/compare 3 generation (TIM2-5 only) */ +#define GTIM_EGR_CC4G (1 << 4) /* Bit 4: Capture/compare 4 generation (TIM2-5 only) */ +#define GTIM_EGR_TG (1 << 6) /* Bit 6: Trigger generation (TIM2-5,9,&12 only) */ + +/* Capture/compare mode register 1 - Output compare mode (TIM2-5 and TIM9-14) */ + +#define GTIM_CCMR1_CC1S_SHIFT (0) /* Bits 1-0: Capture/Compare 1 Selection */ +#define GTIM_CCMR1_CC1S_MASK (3 << GTIM_CCMR1_CC1S_SHIFT) + /* (See common CCMR Capture/Compare Selection definitions below) */ +#define GTIM_CCMR1_OC1FE (1 << 2) /* Bit 2: Output Compare 1 Fast enable */ +#define GTIM_CCMR1_OC1PE (1 << 3) /* Bit 3: Output Compare 1 Preload enable */ +#define GTIM_CCMR1_OC1M_SHIFT (4) /* Bits 6-4: Output Compare 1 Mode */ +#define GTIM_CCMR1_OC1M_MASK (7 << GTIM_CCMR1_OC1M_SHIFT) + /* (See common CCMR Output Compare Mode definitions below) */ +#define GTIM_CCMR1_OC1CE (1 << 7) /* Bit 7: Output Compare 1Clear Enable */ +#define GTIM_CCMR1_CC2S_SHIFT (8) /* Bits 9-8: Capture/Compare 2 Selection */ +#define GTIM_CCMR1_CC2S_MASK (3 << GTIM_CCMR1_CC2S_SHIFT) + /* (See common CCMR Capture/Compare Selection definitions below) */ +#define GTIM_CCMR1_OC2FE (1 << 10) /* Bit 10: Output Compare 2 Fast enable */ +#define GTIM_CCMR1_OC2PE (1 << 11) /* Bit 11: Output Compare 2 Preload enable */ +#define GTIM_CCMR1_OC2M_SHIFT (12) /* Bits 14-12: Output Compare 2 Mode */ +#define GTIM_CCMR1_OC2M_MASK (7 << GTIM_CCMR1_OC2M_SHIFT) + /* (See common CCMR Output Compare Mode definitions below) */ +#define GTIM_CCMR1_OC2CE (1 << 15) /* Bit 15: Output Compare 2 Clear Enable */ + +/* Common CCMR (unshifted) Capture/Compare Selection bit-field definitions */ + +#define GTIM_CCMR_CCS_CCOUT (0) /* 00: CCx channel output */ +#define GTIM_CCMR_CCS_CCIN1 (1) /* 01: CCx channel input, ICx is TIx */ +#define GTIM_CCMR_CCS_CCIN2 (2) /* 10: CCx channel input, ICx is TIy */ +#define GTIM_CCMR_CCS_CCINTRC (3) /* 11: CCx channel input, ICx is TRC */ + +/* Common CCMR (unshifted) Compare Mode bit field definitions */ + +#define GTIM_CCMR_MODE_FRZN (0) /* 000: Frozen */ +#define GTIM_CCMR_MODE_CHACT (1) /* 001: Channel x active on match */ +#define GTIM_CCMR_MODE_CHINACT (2) /* 010: Channel x inactive on match */ +#define GTIM_CCMR_MODE_OCREFTOG (3) /* 011: OCxREF toggle ATIM_CNT=ATIM_CCRx */ +#define GTIM_CCMR_MODE_OCREFLO (4) /* 100: OCxREF forced low */ +#define GTIM_CCMR_MODE_OCREFHI (5) /* 101: OCxREF forced high */ +#define GTIM_CCMR_MODE_PWM1 (6) /* 110: PWM mode 1 */ +#define GTIM_CCMR_MODE_PWM2 (7) /* 111: PWM mode 2 */ + +/* Capture/compare mode register 1 - Input capture mode (TIM2-5 and TIM9-14) */ + + /* Bits 1-0 (Same as Output Compare Mode) */ +#define GTIM_CCMR1_IC1PSC_SHIFT (2) /* Bits 3-2: Input Capture 1 Prescaler */ +#define GTIM_CCMR1_IC1PSC_MASK (3 << GTIM_CCMR1_IC1PSC_SHIFT) + /* (See common CCMR Input Capture Prescaler definitions below) */ +#define GTIM_CCMR1_IC1F_SHIFT (4) /* Bits 7-4: Input Capture 1 Filter */ +#define GTIM_CCMR1_IC1F_MASK (0x0f << GTIM_CCMR1_IC1F_SHIFT) + /* (See common CCMR Input Capture Filter definitions below) */ + /* Bits 9-8: (Same as Output Compare Mode) */ +#define GTIM_CCMR1_IC2PSC_SHIFT (10) /* Bits 11-10: Input Capture 2 Prescaler */ +#define GTIM_CCMR1_IC2PSC_MASK (3 << GTIM_CCMR1_IC2PSC_SHIFT) + /* (See common CCMR Input Capture Prescaler definitions below) */ +#define GTIM_CCMR1_IC2F_SHIFT (12) /* Bits 15-12: Input Capture 2 Filter */ +#define GTIM_CCMR1_IC2F_MASK (0x0f << GTIM_CCMR1_IC2F_SHIFT) + /* (See common CCMR Input Capture Filter definitions below) */ + +/* Common CCMR (unshifted) Input Capture Prescaler bit-field definitions */ + +#define GTIM_CCMR_ICPSC_NOPSC (0) /* 00: no prescaler, capture each edge */ +#define GTIM_CCMR_ICPSC_EVENTS2 (1) /* 01: capture once every 2 events */ +#define GTIM_CCMR_ICPSC_EVENTS4 (2) /* 10: capture once every 4 events */ +#define GTIM_CCMR_ICPSC_EVENTS8 (3) /* 11: capture once every 8 events */ + +/* Common CCMR (unshifted) Input Capture Filter bit-field definitions */ + +#define GTIM_CCMR_ICF_NOFILT (0) /* 0000: No filter, sampling at fDTS */ +#define GTIM_CCMR_ICF_FCKINT2 (1) /* 0001: fSAMPLING=fCK_INT, N=2 */ +#define GTIM_CCMR_ICF_FCKINT4 (2) /* 0010: fSAMPLING=fCK_INT, N=4 */ +#define GTIM_CCMR_ICF_FCKINT8 (3) /* 0011: fSAMPLING=fCK_INT, N=8 */ +#define GTIM_CCMR_ICF_FDTSd26 (4) /* 0100: fSAMPLING=fDTS/2, N=6 */ +#define GTIM_CCMR_ICF_FDTSd28 (5) /* 0101: fSAMPLING=fDTS/2, N=8 */ +#define GTIM_CCMR_ICF_FDTSd46 (6) /* 0110: fSAMPLING=fDTS/4, N=6 */ +#define GTIM_CCMR_ICF_FDTSd48 (7) /* 0111: fSAMPLING=fDTS/4, N=8 */ +#define GTIM_CCMR_ICF_FDTSd86 (8) /* 1000: fSAMPLING=fDTS/8, N=6 */ +#define GTIM_CCMR_ICF_FDTSd88 (9) /* 1001: fSAMPLING=fDTS/8, N=8 */ +#define GTIM_CCMR_ICF_FDTSd165 (10) /* 1010: fSAMPLING=fDTS/16, N=5 */ +#define GTIM_CCMR_ICF_FDTSd166 (11) /* 1011: fSAMPLING=fDTS/16, N=6 */ +#define GTIM_CCMR_ICF_FDTSd168 (12) /* 1100: fSAMPLING=fDTS/16, N=8 */ +#define GTIM_CCMR_ICF_FDTSd325 (13) /* 1101: fSAMPLING=fDTS/32, N=5 */ +#define GTIM_CCMR_ICF_FDTSd326 (14) /* 1110: fSAMPLING=fDTS/32, N=6 */ +#define GTIM_CCMR_ICF_FDTSd328 (15) /* 1111: fSAMPLING=fDTS/32, N=8 */ + +/* Capture/compare mode register 2 - Output Compare mode (TIM2-5 only) */ + +#define GTIM_CCMR2_CC3S_SHIFT (0) /* Bits 1-0: Capture/Compare 3 Selection */ +#define GTIM_CCMR2_CC3S_MASK (3 << GTIM_CCMR2_CC3S_SHIFT) + /* (See common CCMR Capture/Compare Selection definitions above) */ +#define GTIM_CCMR2_OC3FE (1 << 2) /* Bit 2: Output Compare 3 Fast enable */ +#define GTIM_CCMR2_OC3PE (1 << 3) /* Bit 3: Output Compare 3 Preload enable */ +#define GTIM_CCMR2_OC3M_SHIFT (4) /* Bits 6-4: Output Compare 3 Mode */ +#define GTIM_CCMR2_OC3M_MASK (7 << GTIM_CCMR2_OC3M_SHIFT) + /* (See common CCMR Output Compare Mode definitions above) */ +#define GTIM_CCMR2_OC3CE (1 << 7) /* Bit 7: Output Compare 3 Clear Enable */ +#define GTIM_CCMR2_CC4S_SHIFT (8) /* Bits 9-8: Capture/Compare 4 Selection */ +#define GTIM_CCMR2_CC4S_MASK (3 << GTIM_CCMR2_CC4S_SHIFT) + /* (See common CCMR Capture/Compare Selection definitions above) */ +#define GTIM_CCMR2_OC4FE (1 << 10) /* Bit 10: Output Compare 4 Fast enable */ +#define GTIM_CCMR2_OC4PE (1 << 11) /* Bit 11: Output Compare 4 Preload enable */ +#define GTIM_CCMR2_OC4M_SHIFT (12) /* Bits 14-12: Output Compare 4 Mode */ +#define GTIM_CCMR2_OC4M_MASK (7 << GTIM_CCMR2_OC4M_SHIFT) + /* (See common CCMR Output Compare Mode definitions above) */ +#define GTIM_CCMR2_OC4CE (1 << 15) /* Bit 15: Output Compare 4 Clear Enable */ + +/* Capture/compare mode register 2 - Input capture mode (TIM2-5 only) */ + + /* Bits 1-0 (Same as Output Compare Mode) */ +#define GTIM_CCMR2_IC3PSC_SHIFT (2) /* Bits 3-2: Input Capture 3 Prescaler */ +#define GTIM_CCMR2_IC3PSC_MASK (3 << GTIM_CCMR2_IC3PSC_SHIFT) + /* (See common CCMR Input Capture Prescaler definitions below) */ +#define GTIM_CCMR2_IC3F_SHIFT (4) /* Bits 7-4: Input Capture 3 Filter */ +#define GTIM_CCMR2_IC3F_MASK (0x0f << GTIM_CCMR2_IC3F_SHIFT) + /* (See common CCMR Input Capture Filter definitions below) */ + /* Bits 9-8: (Same as Output Compare Mode) */ +#define GTIM_CCMR2_IC4PSC_SHIFT (10) /* Bits 11-10: Input Capture 4 Prescaler */ +#define GTIM_CCMR2_IC4PSC_MASK (3 << GTIM_CCMR2_IC4PSC_SHIFT) + /* (See common CCMR Input Capture Prescaler definitions below) */ +#define GTIM_CCMR2_IC4F_SHIFT (12) /* Bits 15-12: Input Capture 4 Filter */ +#define GTIM_CCMR2_IC4F_MASK (0x0f << GTIM_CCMR2_IC4F_SHIFT) + /* (See common CCMR Input Capture Filter definitions below) */ + +/* Capture/compare enable register (TIM2-5 and TIM9-14) */ + +#define GTIM_CCER_CC1E (1 << 0) /* Bit 0: Capture/Compare 1 output enable */ +#define GTIM_CCER_CC1P (1 << 1) /* Bit 1: Capture/Compare 1 output Polarity */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define GTIM_CCER_CC1NP (1 << 3) /* Bit 3: Capture/Compare 1 output Polarity */ +#endif + +#define GTIM_CCER_CC2E (1 << 4) /* Bit 4: Capture/Compare 2 output enable (TIM2-5,9&12 only) */ +#define GTIM_CCER_CC2P (1 << 5) /* Bit 5: Capture/Compare 2 output Polarity (TIM2-5,9&12 only) */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define GTIM_CCER_CC2NP (1 << 7) /* Bit 7: Capture/Compare 2 output Polarity (TIM2-5,9&12 only) */ +#endif + +#define GTIM_CCER_CC3E (1 << 8) /* Bit 8: Capture/Compare 3 output enable (TIM2-5 only) */ +#define GTIM_CCER_CC3P (1 << 9) /* Bit 9: Capture/Compare 3 output Polarity (TIM2-5 only) */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define GTIM_CCER_CC3NP (1 << 11) /* Bit 11: Capture/Compare 3 output Polarity (TIM2-5 only) */ +#endif + +#define GTIM_CCER_CC4E (1 << 12) /* Bit 12: Capture/Compare 4 output enable (TIM2-5 only) */ +#define GTIM_CCER_CC4P (1 << 13) /* Bit 13: Capture/Compare 4 output Polarity (TIM2-5 only) */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define GTIM_CCER_CC4NP (1 << 15) /* Bit 15: Capture/Compare 4 output Polarity (TIM2-5 only) */ +#endif + +/* DMA control register */ + +#define GTIM_DCR_DBL_SHIFT (8) /* Bits 12-8: DMA Burst Length */ +#define GTIM_DCR_DBL_MASK (0x1f << GTIM_DCR_DBL_SHIFT) +#define GTIM_DCR_DBA_SHIFT (0) /* Bits 4-0: DMA Base Address */ +#define GTIM_DCR_DBA_MASK (0x1f << GTIM_DCR_DBA_SHIFT) + +/* Timer 2/5 option register */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define TIM2_OR_ITR1_RMP_SHIFT (10) /* Bits 10-11: Internal trigger 1 remap */ +# define TIM2_OR_ITR1_RMP_MASK (3 << TIM2_OR_ITR1_RMP_SHIFT) +# define TIM2_OR_ITR1_TIM8_TRGOUT (0 << TIM2_OR_ITR1_RMP_SHIFT) /* 00: TIM2_ITR1 input connected to TIM8_TRGOUT */ +# define TIM2_OR_ITR1_PTP (1 << TIM2_OR_ITR1_RMP_SHIFT) /* 01: TIM2_ITR1 input connected to PTP trigger output */ +# define TIM2_OR_ITR1_OTGFSSOF (2 << TIM2_OR_ITR1_RMP_SHIFT) /* 10: TIM2_ITR1 input connected to OTG FS SOF */ +# define TIM2_OR_ITR1_OTGHSSOF (3 << TIM2_OR_ITR1_RMP_SHIFT) /* 11: TIM2_ITR1 input connected to OTG HS SOF */ + +# define TIM5_OR_TI4_RMP_SHIFT (6) /* Bits 6-7: Internal trigger 4 remap */ +# define TIM5_OR_TI4_RMP_MASK (3 << TIM5_OR_TI4_RMP_SHIFT) +# define TIM5_OR_TI4_GPIO (0 << TIM5_OR_TI4_RMP_SHIFT) /* 00: TIM5_CH4 input connected to GPIO */ +# define TIM5_OR_TI4_LSI (1 << TIM5_OR_TI4_RMP_SHIFT) /* 01: TIM5_CH4 input connected to LSI internal clock */ +# define TIM5_OR_TI4_LSE (2 << TIM5_OR_TI4_RMP_SHIFT) /* 10: TIM5_CH4 input connected to LSE internal clock */ +# define TIM5_OR_TI4_RTC (3 << TIM5_OR_TI4_RMP_SHIFT) /* 11: TIM5_CH4 input connected to RTC output event */ + +# define TIM11_OR_TI1_RMP_SHIFT (6) /* Bits 6-7: Internal trigger 4 remap */ +# define TIM11_OR_TI1_RMP_MASK (3 << TIM11_OR_TI1_RMP_SHIFT) +# define TIM11_OR_TI1_GPIO (0 << TIM11_OR_TI1_RMP_SHIFT) /* 00-11: TIM11_CH1 input connected to GPIO */ +# define TIM11_OR_TI1_HSERTC (3 << TIM11_OR_TI1_RMP_SHIFT) /* 11: TIM11_CH1 input connected to HSE_RTC clock */ +#endif + +/* Control register 1 */ + +#define BTIM_CR1_CEN (1 << 0) /* Bit 0: Counter enable */ +#define BTIM_CR1_UDIS (1 << 1) /* Bit 1: Update Disable */ +#define BTIM_CR1_URS (1 << 2) /* Bit 2: Update Request Source */ +#define BTIM_CR1_OPM (1 << 3) /* Bit 3: One Pulse Mode */ +#define BTIM_CR1_ARPE (1 << 7) /* Bit 7: Auto-Reload Preload enable */ + +/* Control register 2 */ + +#define BTIM_CR2_MMS_SHIFT (4) /* Bits 6-4: Master Mode Selection */ +#define BTIM_CR2_MMS_MASK (7 << BTIM_CR2_MMS_SHIFT) +# define BTIM_CR2_RESET (0 << BTIM_CR2_MMS_SHIFT) /* 000: Reset */ +# define BTIM_CR2_ENAB (1 << BTIM_CR2_MMS_SHIFT) /* 001: Enable */ +# define BTIM_CR2_UPDT (2 << BTIM_CR2_MMS_SHIFT) /* 010: Update */ + +/* DMA/Interrupt enable register */ + +#define BTIM_DIER_UIE (1 << 0) /* Bit 0: Update interrupt enable */ +#define BTIM_DIER_UDE (1 << 8) /* Bit 8: Update DMA request enable */ + +/* Status register */ + +#define BTIM_SR_UIF (1 << 0) /* Bit 0: Update interrupt flag */ + +/* Event generation register */ + +#define BTIM_EGR_UG (1 << 0) /* Bit 0: Update generation */ + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_TIM_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_uart.h b/nuttx/arch/arm/src/stm32/chip/stm32_uart.h new file mode 100644 index 0000000000..d3c1e137e6 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_uart.h @@ -0,0 +1,229 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_uart.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_STC_STM32_CHIP_STM32_UART_H +#define __ARCH_ARM_STC_STM32_CHIP_STM32_UART_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +#define STM32_USART_SR_OFFSET 0x0000 /* Status register (32-bits) */ +#define STM32_USART_DR_OFFSET 0x0004 /* Data register (32-bits) */ +#define STM32_USART_BRR_OFFSET 0x0008 /* Baud Rate Register (32-bits) */ +#define STM32_USART_CR1_OFFSET 0x000c /* Control register 1 (32-bits) */ +#define STM32_USART_CR2_OFFSET 0x0010 /* Control register 2 (32-bits) */ +#define STM32_USART_CR3_OFFSET 0x0014 /* Control register 3 (32-bits) */ +#define STM32_USART_GTPR_OFFSET 0x0018 /* Guard time and prescaler register (32-bits) */ + +/* Register Addresses ***************************************************************/ + +#if STM32_NUSART > 0 +# define STM32_USART1_SR (STM32_USART1_BASE+STM32_USART_SR_OFFSET) +# define STM32_USART1_DR (STM32_USART1_BASE+STM32_USART_DR_OFFSET) +# define STM32_USART1_BRR (STM32_USART1_BASE+STM32_USART_BRR_OFFSET) +# define STM32_USART1_CR1 (STM32_USART1_BASE+STM32_USART_CR1_OFFSET) +# define STM32_USART1_CR2 (STM32_USART1_BASE+STM32_USART_CR2_OFFSET) +# define STM32_USART1_CR3 (STM32_USART1_BASE+STM32_USART_CR3_OFFSET) +# define STM32_USART1_GTPR (STM32_USART1_BASE+STM32_USART_GTPR_OFFSET) +#endif + +#if STM32_NUSART > 1 +# define STM32_USART2_SR (STM32_USART2_BASE+STM32_USART_SR_OFFSET) +# define STM32_USART2_DR (STM32_USART2_BASE+STM32_USART_DR_OFFSET) +# define STM32_USART2_BRR (STM32_USART2_BASE+STM32_USART_BRR_OFFSET) +# define STM32_USART2_CR1 (STM32_USART2_BASE+STM32_USART_CR1_OFFSET) +# define STM32_USART2_CR2 (STM32_USART2_BASE+STM32_USART_CR2_OFFSET) +# define STM32_USART2_CR3 (STM32_USART2_BASE+STM32_USART_CR3_OFFSET) +# define STM32_USART2_GTPR (STM32_USART2_BASE+STM32_USART_GTPR_OFFSET) +#endif + +#if STM32_NUSART > 2 +# define STM32_USART3_SR (STM32_USART3_BASE+STM32_USART_SR_OFFSET) +# define STM32_USART3_DR (STM32_USART3_BASE+STM32_USART_DR_OFFSET) +# define STM32_USART3_BRR (STM32_USART3_BASE+STM32_USART_BRR_OFFSET) +# define STM32_USART3_CR1 (STM32_USART3_BASE+STM32_USART_CR1_OFFSET) +# define STM32_USART3_CR2 (STM32_USART3_BASE+STM32_USART_CR2_OFFSET) +# define STM32_USART3_CR3 (STM32_USART3_BASE+STM32_USART_CR3_OFFSET) +# define STM32_USART3_GTPR (STM32_USART3_BASE+STM32_USART_GTPR_OFFSET) +#endif + +#if STM32_NUSART > 3 +# define STM32_UART4_SR (STM32_UART4_BASE+STM32_USART_SR_OFFSET) +# define STM32_UART4_DR (STM32_UART4_BASE+STM32_USART_DR_OFFSET) +# define STM32_UART4_BRR (STM32_UART4_BASE+STM32_USART_BRR_OFFSET) +# define STM32_UART4_CR1 (STM32_UART4_BASE+STM32_USART_CR1_OFFSET) +# define STM32_UART4_CR2 (STM32_UART4_BASE+STM32_USART_CR2_OFFSET) +# define STM32_UART4_CR3 (STM32_UART4_BASE+STM32_USART_CR3_OFFSET) +#endif + +#if STM32_NUSART > 4 +# define STM32_UART5_SR (STM32_UART5_BASE+STM32_USART_SR_OFFSET) +# define STM32_UART5_DR (STM32_UART5_BASE+STM32_USART_DR_OFFSET) +# define STM32_UART5_BRR (STM32_UART5_BASE+STM32_USART_BRR_OFFSET) +# define STM32_UART5_CR1 (STM32_UART5_BASE+STM32_USART_CR1_OFFSET) +# define STM32_UART5_CR2 (STM32_UART5_BASE+STM32_USART_CR2_OFFSET) +# define STM32_UART5_CR3 (STM32_UART5_BASE+STM32_USART_CR3_OFFSET) +#endif + +#if STM32_NUSART > 5 +# define STM32_USART6_SR (STM32_USART6_BASE+STM32_USART_SR_OFFSET) +# define STM32_USART6_DR (STM32_USART6_BASE+STM32_USART_DR_OFFSET) +# define STM32_USART6_BRR (STM32_USART6_BASE+STM32_USART_BRR_OFFSET) +# define STM32_USART6_CR1 (STM32_USART6_BASE+STM32_USART_CR1_OFFSET) +# define STM32_USART6_CR2 (STM32_USART6_BASE+STM32_USART_CR2_OFFSET) +# define STM32_USART6_CR3 (STM32_USART6_BASE+STM32_USART_CR3_OFFSET) +# define STM32_USART6_GTPR (STM32_USART6_BASE+STM32_USART_GTPR_OFFSET) +#endif + +/* Register Bitfield Definitions ****************************************************/ + +/* Status register */ + +#define USART_SR_PE (1 << 0) /* Bit 0: Parity Error */ +#define USART_SR_FE (1 << 1) /* Bit 1: Framing Error */ +#define USART_SR_NE (1 << 2) /* Bit 2: Noise Error Flag */ +#define USART_SR_ORE (1 << 3) /* Bit 3: OverRun Error */ +#define USART_SR_IDLE (1 << 4) /* Bit 4: IDLE line detected */ +#define USART_SR_RXNE (1 << 5) /* Bit 5: Read Data Register Not Empty */ +#define USART_SR_TC (1 << 6) /* Bit 6: Transmission Complete */ +#define USART_SR_TXE (1 << 7) /* Bit 7: Transmit Data Register Empty */ +#define USART_SR_LBD (1 << 8) /* Bit 8: LIN Break Detection Flag */ +#define USART_SR_CTS (1 << 9) /* Bit 9: CTS Flag */ + +#define USART_SR_ALLBITS (0x03ff) +#define USART_SR_CLRBITS (USART_SR_CTS|USART_SR_LBD) /* Cleared by SW write to SR */ + +/* Data register */ + +#define USART_DR_SHIFT (0) /* Bits 8:0: Data value */ +#define USART_DR_MASK (0xff << USART_DR_SHIFT) + +/* Baud Rate Register */ + +#define USART_BRR_FRAC_SHIFT (0) /* Bits 3-0: fraction of USARTDIV */ +#define USART_BRR_FRAC_MASK (0x0f << USART_BRR_FRAC_SHIFT) +#define USART_BRR_MANT_SHIFT (4) /* Bits 15-4: mantissa of USARTDIV */ +#define USART_BRR_MANT_MASK (0x0fff << USART_BRR_MANT_SHIFT) + +/* Control register 1 */ + +#define USART_CR1_SBK (1 << 0) /* Bit 0: Send Break */ +#define USART_CR1_RWU (1 << 1) /* Bit 1: Receiver wakeup */ +#define USART_CR1_RE (1 << 2) /* Bit 2: Receiver Enable */ +#define USART_CR1_TE (1 << 3) /* Bit 3: Transmitter Enable */ +#define USART_CR1_IDLEIE (1 << 4) /* Bit 4: IDLE Interrupt Enable */ +#define USART_CR1_RXNEIE (1 << 5) /* Bit 5: RXNE Interrupt Enable */ +#define USART_CR1_TCIE (1 << 6) /* Bit 6: Transmission Complete Interrupt Enable */ +#define USART_CR1_TXEIE (1 << 7) /* Bit 7: TXE Interrupt Enable */ +#define USART_CR1_PEIE (1 << 8) /* Bit 8: PE Interrupt Enable */ +#define USART_CR1_PS (1 << 9) /* Bit 9: Parity Selection */ +#define USART_CR1_PCE (1 << 10) /* Bit 10: Parity Control Enable */ +#define USART_CR1_WAKE (1 << 11) /* Bit 11: Wakeup method */ +#define USART_CR1_M (1 << 12) /* Bit 12: word length */ +#define USART_CR1_UE (1 << 13) /* Bit 13: USART Enable */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define USART_CR1_OVER8 (1 << 15) /* Bit 15: Oversampling mode */ +#endif + +#define USART_CR1_ALLINTS (USART_CR1_IDLEIE|USART_CR1_RXNEIE|USART_CR1_TCIE|USART_CR1_PEIE) + +/* Control register 2 */ + +#define USART_CR2_ADD_SHIFT (0) /* Bits 3-0: Address of the USART node */ +#define USART_CR2_ADD_MASK (0x0f << USART_CR2_ADD_SHIFT) +#define USART_CR2_LBDL (1 << 5) /* Bit 5: LIN Break Detection Length */ +#define USART_CR2_LBDIE (1 << 6) /* Bit 6: LIN Break Detection Interrupt Enable */ +#define USART_CR2_LBCL (1 << 8) /* Bit 8: Last Bit Clock pulse */ +#define USART_CR2_CPHA (1 << 9) /* Bit 9: Clock Phase */ +#define USART_CR2_CPOL (1 << 10) /* Bit 10: Clock Polarity */ +#define USART_CR2_CLKEN (1 << 11) /* Bit 11: Clock Enable */ +#define USART_CR2_STOP_SHIFT (12) /* Bits 13-12: STOP bits */ +#define USART_CR2_STOP_MASK (3 << USART_CR2_STOP_SHIFT) +# define USART_CR2_STOP1 (0 << USART_CR2_STOP_SHIFT) /* 00: 1 Stop bit */ +# define USART_CR2_STOP0p5 (1 << USART_CR2_STOP_SHIFT) /* 01: 0.5 Stop bit */ +# define USART_CR2_STOP2 (2 << USART_CR2_STOP_SHIFT) /* 10: 2 Stop bits */ +# define USART_CR2_STOP1p5 (3 << USART_CR2_STOP_SHIFT) /* 11: 1.5 Stop bit */ +#define USART_CR2_LINEN (1 << 14) /* Bit 14: LIN mode enable */ + +/* Control register 3 */ + +#define USART_CR3_EIE (1 << 0) /* Bit 0: Error Interrupt Enable */ +#define USART_CR3_IREN (1 << 1) /* Bit 1: IrDA mode Enable */ +#define USART_CR3_IRLP (1 << 2) /* Bit 2: IrDA Low-Power */ +#define USART_CR3_HDSEL (1 << 3) /* Bit 3: Half-Duplex Selection */ +#define USART_CR3_NACK (1 << 4) /* Bit 4: Smartcard NACK enable */ +#define USART_CR3_SCEN (1 << 5) /* Bit 5: Smartcard mode enable */ +#define USART_CR3_DMAR (1 << 6) /* Bit 6: DMA Enable Receiver */ +#define USART_CR3_DMAT (1 << 7) /* Bit 7: DMA Enable Transmitter */ +#define USART_CR3_RTSE (1 << 8) /* Bit 8: RTS Enable */ +#define USART_CR3_CTSE (1 << 9) /* Bit 9: CTS Enable */ +#define USART_CR3_CTSIE (1 << 10) /* Bit 10: CTS Interrupt Enable */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define USART_CR1_ONEBIT (1 << 11) /* Bit 11: One sample bit method enable */ +#endif + +/* Guard time and prescaler register */ + +#define USART_GTPR_PSC_SHIFT (0) /* Bits 0-7: Prescaler value */ +#define USART_GTPR_PSC_MASK (0xff << USART_GTPR_PSC_SHIFT) +#define USART_GTPR_GT_SHIFT (8) /* Bits 8-15: Guard time value */ +#define USART_GTPR_GT_MASK (0xff << USART_GTPR_GT_SHIFT) + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#endif /* __ARCH_ARM_STC_STM32_CHIP_STM32_UART_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_usbdev.h b/nuttx/arch/arm/src/stm32/chip/stm32_usbdev.h new file mode 100644 index 0000000000..daa9a926e0 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_usbdev.h @@ -0,0 +1,236 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_usbdev.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_USBDEV_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_USBDEV_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +#ifdef CONFIG_STM32_STM32F10XX + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +/* Endpoint Registers */ + +#define STM32_USB_EPR_OFFSET(n) ((n) << 2) /* USB endpoint n register (16-bits) */ +#define STM32_USB_EP0R_OFFSET 0x0000 /* USB endpoint 0 register (16-bits) */ +#define STM32_USB_EP1R_OFFSET 0x0004 /* USB endpoint 1 register (16-bits) */ +#define STM32_USB_EP2R_OFFSET 0x0008 /* USB endpoint 2 register (16-bits) */ +#define STM32_USB_EP3R_OFFSET 0x000c /* USB endpoint 3 register (16-bits) */ +#define STM32_USB_EP4R_OFFSET 0x0010 /* USB endpoint 4 register (16-bits) */ +#define STM32_USB_EP5R_OFFSET 0x0014 /* USB endpoint 5 register (16-bits) */ +#define STM32_USB_EP6R_OFFSET 0x0018 /* USB endpoint 6 register (16-bits) */ +#define STM32_USB_EP7R_OFFSET 0x001c /* USB endpoint 7 register (16-bits) */ + +/* Common Registers */ + +#define STM32_USB_CNTR_OFFSET 0x0040 /* USB control register (16-bits) */ +#define STM32_USB_ISTR_OFFSET 0x0044 /* USB interrupt status register (16-bits) */ +#define STM32_USB_FNR_OFFSET 0x0048 /* USB frame number register (16-bits) */ +#define STM32_USB_DADDR_OFFSET 0x004c /* USB device address (16-bits) */ +#define STM32_USB_BTABLE_OFFSET 0x0050 /* Buffer table address (16-bits) */ + +/* Buffer Descriptor Table (Relatative to BTABLE address) */ + +#define STM32_USB_ADDR_TX_WOFFSET (0) /* Transmission buffer address n (16-bits) */ +#define STM32_USB_COUNT_TX_WOFFSET (2) /* Transmission byte count n (16-bits) */ +#define STM32_USB_ADDR_RX_WOFFSET (4) /* Reception buffer address n (16-bits) */ +#define STM32_USB_COUNT_RX_WOFFSET (6) /* Reception byte count n (16-bits) */ + +#define STM32_USB_BTABLE_RADDR(ep,o) ((((uint32_t)getreg16(STM32_USB_BTABLE) + ((ep) << 3)) + (o)) << 1) +#define STM32_USB_ADDR_TX_OFFSET(ep) STM32_USB_BTABLE_RADDR(ep,STM32_USB_ADDR_TX_WOFFSET) +#define STM32_USB_COUNT_TX_OFFSET(ep) STM32_USB_BTABLE_RADDR(ep,STM32_USB_COUNT_TX_WOFFSET) +#define STM32_USB_ADDR_RX_OFFSET(ep) STM32_USB_BTABLE_RADDR(ep,STM32_USB_ADDR_RX_WOFFSET) +#define STM32_USB_COUNT_RX_OFFSET(ep) STM32_USB_BTABLE_RADDR(ep,STM32_USB_COUNT_RX_WOFFSET) + +/* Register Addresses ***************************************************************/ + +/* Endpoint Registers */ + +#define STM32_USB_EPR(n) (STM32_USB_BASE+STM32_USB_EPR_OFFSET(n)) +#define STM32_USB_EP0R (STM32_USB_BASE+STM32_USB_EP0R_OFFSET) +#define STM32_USB_EP1R (STM32_USB_BASE+STM32_USB_EP1R_OFFSET) +#define STM32_USB_EP2R (STM32_USB_BASE+STM32_USB_EP2R_OFFSET) +#define STM32_USB_EP3R (STM32_USB_BASE+STM32_USB_EP3R_OFFSET) +#define STM32_USB_EP4R (STM32_USB_BASE+STM32_USB_EP4R_OFFSET) +#define STM32_USB_EP5R (STM32_USB_BASE+STM32_USB_EP5R_OFFSET) +#define STM32_USB_EP6R (STM32_USB_BASE+STM32_USB_EP6R_OFFSET) +#define STM32_USB_EP7R (STM32_USB_BASE+STM32_USB_EP7R_OFFSET) + +/* Common Registers */ + +#define STM32_USB_CNTR (STM32_USB_BASE+STM32_USB_CNTR_OFFSET) +#define STM32_USB_ISTR (STM32_USB_BASE+STM32_USB_ISTR_OFFSET) +#define STM32_USB_FNR (STM32_USB_BASE+STM32_USB_FNR_OFFSET) +#define STM32_USB_DADDR (STM32_USB_BASE+STM32_USB_DADDR_OFFSET) +#define STM32_USB_BTABLE (STM32_USB_BASE+STM32_USB_BTABLE_OFFSET) + +/* Buffer Descriptor Table (Relatative to BTABLE address) */ + +#define STM32_USB_BTABLE_ADDR(ep,o) (STM32_USBCANRAM_BASE+STM32_USB_BTABLE_RADDR(ep,o)) +#define STM32_USB_ADDR_TX(ep) STM32_USB_BTABLE_ADDR(ep,STM32_USB_ADDR_TX_WOFFSET) +#define STM32_USB_COUNT_TX(ep) STM32_USB_BTABLE_ADDR(ep,STM32_USB_COUNT_TX_WOFFSET) +#define STM32_USB_ADDR_RX(ep) STM32_USB_BTABLE_ADDR(ep,STM32_USB_ADDR_RX_WOFFSET) +#define STM32_USB_COUNT_RX(ep) STM32_USB_BTABLE_ADDR(ep,STM32_USB_COUNT_RX_WOFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +/* USB endpoint register */ + +#define USB_EPR_EA_SHIFT (0) /* Bits 3:0 [3:0]: Endpoint Address */ +#define USB_EPR_EA_MASK (0X0f << USB_EPR_EA_SHIFT) +#define USB_EPR_STATTX_SHIFT (4) /* Bits 5-4: Status bits, for transmission transfers */ +#define USB_EPR_STATTX_MASK (3 << USB_EPR_STATTX_SHIFT) +# define USB_EPR_STATTX_DIS (0 << USB_EPR_STATTX_SHIFT) /* EndPoint TX DISabled */ +# define USB_EPR_STATTX_STALL (1 << USB_EPR_STATTX_SHIFT) /* EndPoint TX STALLed */ +# define USB_EPR_STATTX_NAK (2 << USB_EPR_STATTX_SHIFT) /* EndPoint TX NAKed */ +# define USB_EPR_STATTX_VALID (3 << USB_EPR_STATTX_SHIFT) /* EndPoint TX VALID */ +# define USB_EPR_STATTX_DTOG1 (1 << USB_EPR_STATTX_SHIFT) /* EndPoint TX Data Toggle bit1 */ +# define USB_EPR_STATTX_DTOG2 (2 << USB_EPR_STATTX_SHIFT) /* EndPoint TX Data Toggle bit2 */ +#define USB_EPR_DTOG_TX (1 << 6) /* Bit 6: Data Toggle, for transmission transfers */ +#define USB_EPR_CTR_TX (1 << 7) /* Bit 7: Correct Transfer for transmission */ +#define USB_EPR_EP_KIND (1 << 8) /* Bit 8: Endpoint Kind */ +#define USB_EPR_EPTYPE_SHIFT (9) /* Bits 10-9: Endpoint type */ +#define USB_EPR_EPTYPE_MASK (3 << USB_EPR_EPTYPE_SHIFT) +# define USB_EPR_EPTYPE_BULK (0 << USB_EPR_EPTYPE_SHIFT) /* EndPoint BULK */ +# define USB_EPR_EPTYPE_CONTROL (1 << USB_EPR_EPTYPE_SHIFT) /* EndPoint CONTROL */ +# define USB_EPR_EPTYPE_ISOC (2 << USB_EPR_EPTYPE_SHIFT) /* EndPoint ISOCHRONOUS */ +# define USB_EPR_EPTYPE_INTERRUPT (3 << USB_EPR_EPTYPE_SHIFT) /* EndPoint INTERRUPT */ +#define USB_EPR_SETUP (1 << 11) /* Bit 11: Setup transaction completed */ +#define USB_EPR_STATRX_SHIFT (12) /* Bits 13-12: Status bits, for reception transfers */ +#define USB_EPR_STATRX_MASK (3 << USB_EPR_STATRX_SHIFT) +# define USB_EPR_STATRX_DIS (0 << USB_EPR_STATRX_SHIFT) /* EndPoint RX DISabled */ +# define USB_EPR_STATRX_STALL (1 << USB_EPR_STATRX_SHIFT) /* EndPoint RX STALLed */ +# define USB_EPR_STATRX_NAK (2 << USB_EPR_STATRX_SHIFT) /* EndPoint RX NAKed */ +# define USB_EPR_STATRX_VALID (3 << USB_EPR_STATRX_SHIFT) /* EndPoint RX VALID */ +# define USB_EPR_STATRX_DTOG1 (1 << USB_EPR_STATRX_SHIFT) /* EndPoint RX Data TOGgle bit1 */ +# define USB_EPR_STATRX_DTOG2 (2 << USB_EPR_STATRX_SHIFT) /* EndPoint RX Data TOGgle bit1 */ +#define USB_EPR_DTOG_RX (1 << 14) /* Bit 14: Data Toggle, for reception transfers */ +#define USB_EPR_CTR_RX (1 << 15) /* Bit 15: Correct Transfer for reception */ + +/* USB control register */ + +#define USB_CNTR_FRES (1 << 0) /* Bit 0: Force USB Reset */ +#define USB_CNTR_PDWN (1 << 1) /* Bit 1: Power down */ +#define USB_CNTR_LPMODE (1 << 2) /* Bit 2: Low-power mode */ +#define USB_CNTR_FSUSP (1 << 3) /* Bit 3: Force suspend */ +#define USB_CNTR_RESUME (1 << 4) /* Bit 4: Resume request */ +#define USB_CNTR_ESOFM (1 << 8) /* Bit 8: Expected Start Of Frame Interrupt Mask */ +#define USB_CNTR_SOFM (1 << 9) /* Bit 9: Start Of Frame Interrupt Mask */ +#define USB_CNTR_RESETM (1 << 10) /* Bit 10: USB Reset Interrupt Mask */ +#define USB_CNTR_SUSPM (1 << 11) /* Bit 11: Suspend mode Interrupt Mask */ +#define USB_CNTR_WKUPM (1 << 12) /* Bit 12: Wakeup Interrupt Mask */ +#define USB_CNTR_ERRM (1 << 13) /* Bit 13: Error Interrupt Mask */ +#define USB_CNTR_DMAOVRNM (1 << 14) /* Bit 14: Packet Memory Area Over / Underrun Interrupt Mask */ +#define USB_CNTR_CTRM (1 << 15) /* Bit 15: Correct Transfer Interrupt Mask */ + +#define USB_CNTR_ALLINTS (USB_CNTR_ESOFM|USB_CNTR_SOFM|USB_CNTR_RESETM|USB_CNTR_SUSPM|\ + USB_CNTR_WKUPM|USB_CNTR_ERRM|USB_CNTR_DMAOVRNM|USB_CNTR_CTRM) + +/* USB interrupt status register */ + +#define USB_ISTR_EPID_SHIFT (0) /* Bits 3-0: Endpoint Identifier */ +#define USB_ISTR_EPID_MASK (0x0f << USB_ISTR_EPID_SHIFT) +#define USB_ISTR_DIR (1 << 4) /* Bit 4: Direction of transaction */ +#define USB_ISTR_ESOF (1 << 8) /* Bit 8: Expected Start Of Frame */ +#define USB_ISTR_SOF (1 << 9) /* Bit 9: Start Of Frame */ +#define USB_ISTR_RESET (1 << 10) /* Bit 10: USB RESET request */ +#define USB_ISTR_SUSP (1 << 11) /* Bit 11: Suspend mode request */ +#define USB_ISTR_WKUP (1 << 12) /* Bit 12: Wake up */ +#define USB_ISTR_ERR (1 << 13) /* Bit 13: Error */ +#define USB_ISTR_DMAOVRN (1 << 14) /* Bit 14: Packet Memory Area Over / Underrun */ +#define USB_ISTR_CTR (1 << 15) /* Bit 15: Correct Transfer */ + +#define USB_ISTR_ALLINTS (USB_ISTR_ESOF|USB_ISTR_SOF|USB_ISTR_RESET|USB_ISTR_SUSP|\ + USB_ISTR_WKUP|USB_ISTR_ERR|USB_ISTR_DMAOVRN|USB_ISTR_CTR) + +/* USB frame number register */ + +#define USB_FNR_FN_SHIFT (0) /* Bits 10-0: Frame Number */ +#define USB_FNR_FN_MASK (0x07ff << USB_FNR_FN_SHIFT) +#define USB_FNR_LSOF_SHIFT (11) /* Bits 12-11: Lost SOF */ +#define USB_FNR_LSOF_MASK (3 << USB_FNR_LSOF_SHIFT) +#define USB_FNR_LCK (1 << 13) /* Bit 13: Locked */ +#define USB_FNR_RXDM (1 << 14) /* Bit 14: Receive Data - Line Status */ +#define USB_FNR_RXDP (1 << 15) /* Bit 15: Receive Data + Line Status */ + +/* USB device address */ + +#define USB_DADDR_ADD_SHIFT (0) /* Bits 6-0: Device Address */ +#define USB_DADDR_ADD_MASK (0x7f << USB_DADDR_ADD_SHIFT) +#define USB_DADDR_EF (1 << 7) /* Bit 7: Enable Function */ + +/* Buffer table address */ + +#define USB_BTABLE_SHIFT (3) /* Bits 15:3: Buffer Table */ +#define USB_BTABLE_MASK (0x1fff << USB_BTABLE_SHIFT) + +/* Transmission buffer address */ + +#define USB_ADDR_TX_ZERO (1 << 0) /* Bit 0 Must always be written as ‘0’ */ +#define USB_ADDR_TX_SHIFT (1) /* Bits 15-1: Transmission Buffer Address */ +#define USB_ADDR_TX_MASK (0x7fff << USB_ADDR_ADDR_TX_SHIFT) + +/* Transmission byte count */ + +#define USB_COUNT_TX_SHIFT (0) /* Bits 9-0: Transmission Byte Count */ +#define USB_COUNT_TX_MASK (0x03ff << USB_COUNT_COUNT_TX_SHIFT) + +/* Reception buffer address */ + +#define USB_ADDR_RX_ZERO (1 << 0) /* Bit 0 This bit must always be written as ‘0’ */ +#define USB_ADDR_RX_SHIFT (1) /* Bits 15:1 ADDRn_RX[15:1]: Reception Buffer Address */ +#define USB_ADDR_RX_MASK (0x7fff << USB_ADDR_RX_SHIFT) + +/* Reception byte count */ + +#define USB_COUNT_RX_BL_SIZE (1 << 15) /* Bit 15: BLock SIZE. */ +#define USB_COUNT_RX_NUM_BLOCK_SHIFT (10) /* Bits 14-10: Number of blocks */ +#define USB_COUNT_RX_NUM_BLOCK_MASK (0x1f << USB_COUNT_RX_NUM_BLOCK_SHIFT) +#define USB_COUNT_RX_SHIFT (0) /* Bits 9-0: Reception Byte Count */ +#define USB_COUNT_RX_MASK (0x03ff << USB_COUNT_RX_SHIFT) + +#endif /* CONFIG_STM32_STM32F10XX */ +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_USBDEV_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_wdg.h b/nuttx/arch/arm/src/stm32/chip/stm32_wdg.h new file mode 100644 index 0000000000..5abb5bc6db --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32_wdg.h @@ -0,0 +1,145 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_wdg.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_WDG_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_WDG_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +#define STM32_IWDG_KR_OFFSET 0x0000 /* Key register (32-bit) */ +#define STM32_IWDG_PR_OFFSET 0x0004 /* Prescaler register (32-bit) */ +#define STM32_IWDG_RLR_OFFSET 0x0008 /* Reload register (32-bit) */ +#define STM32_IWDG_SR_OFFSET 0x000c /* Status register (32-bit) */ + +#define STM32_WWDG_CR_OFFSET 0x0000 /* Control Register (32-bit) */ +#define STM32_WWDG_CFR_OFFSET 0x0004 /* Configuration register (32-bit) */ +#define STM32_WWDG_SR_OFFSET 0x0008 /* Status register (32-bit) */ + +/* Register Addresses ***************************************************************/ + +#define STM32_IWDG_KR (STM32_IWDG_BASE+STM32_IWDG_KR_OFFSET) +#define STM32_IWDG_PR (STM32_IWDG_BASE+STM32_IWDG_PR_OFFSET) +#define STM32_IWDG_RLR (STM32_IWDG_BASE+STM32_IWDG_RLR_OFFSET) +#define STM32_IWDG_SR (STM32_IWDG_BASE+STM32_IWDG_SR_OFFSET) + +#define STM32_WWDG_CR (STM32_WWDG_BASE+STM32_WWDG_CR_OFFSET) +#define STM32_WWDG_CFR (STM32_WWDG_BASE+STM32_WWDG_CFR_OFFSET) +#define STM32_WWDG_SR (STM32_WWDG_BASE+STM32_WWDG_SR_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +/* Key register (32-bit) */ + +#define IWDG_KR_KEY_SHIFT (0) /* Bits 15-0: Key value (write only, read 0000h) */ +#define IWDG_KR_KEY_MASK (0xffff << IWDG_KR_KEY_SHIFT) + +#define IWDG_KR_KEY_ENABLE (0x5555) /* Enable register access */ +#define IWDG_KR_KEY_DISABLE (0x0000) /* Disable register access */ +#define IWDG_KR_KEY_RELOAD (0xaaaa) /* Reload the counter */ +#define IWDG_KR_KEY_START (0xcccc) /* Start the watchdog */ + +/* Prescaler register (32-bit) */ + +#define IWDG_PR_SHIFT (0) /* Bits 2-0: Prescaler divider */ +#define IWDG_PR_MASK (7 << IWDG_PR_SHIFT) +# define IWDG_PR_DIV4 (0 << IWDG_PR_SHIFT) /* 000: divider /4 */ +# define IWDG_PR_DIV8 (1 << IWDG_PR_SHIFT) /* 001: divider /8 */ +# define IWDG_PR_DIV16 (2 << IWDG_PR_SHIFT) /* 010: divider /16 */ +# define IWDG_PR_DIV32 (3 << IWDG_PR_SHIFT) /* 011: divider /32 */ +# define IWDG_PR_DIV64 (4 << IWDG_PR_SHIFT) /* 100: divider /64 */ +# define IWDG_PR_DIV128 (5 << IWDG_PR_SHIFT) /* 101: divider /128 */ +# define IWDG_PR_DIV256 (6 << IWDG_PR_SHIFT) /* 11x: divider /256 */ + +/* Reload register (32-bit) */ + +#define IWDG_RLR_RL_SHIFT (0) /* Bits11:0 RL[11:0]: Watchdog counter reload value */ +#define IWDG_RLR_RL_MASK (0x0fff << IWDG_RLR_RL_SHIFT) + +#define IWDG_RLR_MAX (0xfff) + +/* Status register (32-bit) */ + +#define IWDG_SR_PVU (1 << 0) /* Bit 0: Watchdog prescaler value update */ +#define IWDG_SR_RVU (1 << 1) /* Bit 1: Watchdog counter reload value update */ + +/* Control Register (32-bit) */ + +#define WWDG_CR_T_SHIFT (0) /* Bits 6:0 T[6:0]: 7-bit counter (MSB to LSB) */ +#define WWDG_CR_T_MASK (0x7f << WWDG_CR_T_SHIFT) +# define WWDG_CR_T_MAX (0x3f << WWDG_CR_T_SHIFT) +# define WWDG_CR_T_RESET (0x40 << WWDG_CR_T_SHIFT) +#define WWDG_CR_WDGA (1 << 7) /* Bit 7: Activation bit */ + +/* Configuration register (32-bit) */ + +#define WWDG_CFR_W_SHIFT (0) /* Bits 6:0 W[6:0] 7-bit window value */ +#define WWDG_CFR_W_MASK (0x7f << WWDG_CFR_W_SHIFT) +#define WWDG_CFR_WDGTB_SHIFT (7) /* Bits 8:7 [1:0]: Timer Base */ +#define WWDG_CFR_WDGTB_MASK (3 << WWDG_CFR_WDGTB_SHIFT) +# define WWDG_CFR_PCLK1 (0 << WWDG_CFR_WDGTB_SHIFT) /* 00: CK Counter Clock (PCLK1 div 4096) div 1 */ +# define WWDG_CFR_PCLK1d2 (1 << WWDG_CFR_WDGTB_SHIFT) /* 01: CK Counter Clock (PCLK1 div 4096) div 2 */ +# define WWDG_CFR_PCLK1d4 (2 << WWDG_CFR_WDGTB_SHIFT) /* 10: CK Counter Clock (PCLK1 div 4096) div 4 */ +# define WWDG_CFR_PCLK1d8 (3 << WWDG_CFR_WDGTB_SHIFT) /* 11: CK Counter Clock (PCLK1 div 4096) div 8 */ +#define WWDG_CFR_EWI (1 << 9) /* Bit 9: Early Wakeup Interrupt */ + +/* Status register (32-bit) */ + +#define WWDG_SR_EWIF (1 << 0) /* Bit 0: Early Wakeup Interrupt Flag */ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_WDG_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f100_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f100_pinmap.h new file mode 100644 index 0000000000..18e8435f77 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f100_pinmap.h @@ -0,0 +1,267 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f100_pinmap.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Copyright (C) 2012 Michael Smith. All Rights reserved. + * Author: Gregory Nutt + * Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F100_PINMAP_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F100_PINMAP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* TIMERS */ + +#if defined(CONFIG_STM32_TIM1_FULL_REMAP) +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN7) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN9) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN11) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN13) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN14) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN15) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12) +#elif defined(CONFIG_STM32_TIM1_PARTIAL_REMAP) +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#else +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15) +#endif + +#if defined(CONFIG_STM32_TIM2_FULL_REMAP) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_1) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_2) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#else +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#endif + +#if defined(CONFIG_STM32_TIM3_FULL_REMAP) +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9) +#elif defined(CONFIG_STM32_TIM3_PARTIAL_REMAP) +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN5) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#else +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#endif + +#if defined(CONFIG_STM32_TIM4_REMAP) +# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN12) +# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN13) +# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13) +# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN14) +# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14) +# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN15) +# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15) +#else +# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6) +# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6) +# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7) +# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7) +# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8) +# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9) +# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +#endif + +/* USART */ + +#if defined(CONFIG_STM32_USART1_REMAP) +# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6) +# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7) +#else +# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +#endif + +#if defined(CONFIG_STM32_USART2_REMAP) +# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN3) +# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4) +# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5) +# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6) +# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7) +#else +# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4) +#endif + +#if defined(CONFIG_STM32_USART3_FULL_REMAP) +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN9) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN11) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +#elif defined(CONFIG_STM32_USART3_PARTIAL_REMAP) +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#else +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#endif + +/* SPI */ + +#if defined(CONFIG_STM32_SPI1_REMAP) +# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#else +# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4) +# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN5) +# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6) +# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +#endif + +#define GPIO_SPI2_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +#define GPIO_SPI2_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +#define GPIO_SPI2_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#define GPIO_SPI2_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15) + +/* I2C */ + +#if defined(CONFIG_STM32_I2C1_REMAP) +# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +#else +# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6) +# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7) +#endif +#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_CNF_INFLOAT|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) + +#define GPIO_I2C2_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +#define GPIO_I2C2_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#define GPIO_I2C2_SMBA (GPIO_ALT|GPIO_CNF_INFLOAT|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F100_PINMAP_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f103re_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f103re_pinmap.h new file mode 100644 index 0000000000..7c33da449a --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f103re_pinmap.h @@ -0,0 +1,332 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f103re_pinmap.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Gregory Nutt + * Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F103RE_PINMAP_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F103RE_PINMAP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* TIMERS */ + +#if defined(CONFIG_STM32_TIM1_FULL_REMAP) +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN7) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN9) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN11) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN13) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN14) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN15) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12) +#elif defined(CONFIG_STM32_TIM1_PARTIAL_REMAP) +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#else +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15) +#endif + +#if defined(CONFIG_STM32_TIM2_FULL_REMAP) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_1) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_2) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#else +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#endif + +#if defined(CONFIG_STM32_TIM3_FULL_REMAP) +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9) +#elif defined(CONFIG_STM32_TIM3_PARTIAL_REMAP) +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN5) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#else +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#endif + +#if defined(CONFIG_STM32_TIM4_REMAP) +# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN12) +# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN13) +# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13) +# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN14) +# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14) +# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN15) +# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15) +#else +# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6) +# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6) +# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7) +# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7) +# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8) +# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9) +# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +#endif + +#define GPIO_TIM5_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM5_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) + +#define GPIO_TIM8_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM8_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM8_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM8_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM8_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM8_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM8_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM8_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM8_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM8_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM8_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM8_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +#define GPIO_TIM8_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) + +/* USART */ + +#if defined(CONFIG_STM32_USART1_REMAP) +# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +#else +# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +#endif + +#if defined(CONFIG_STM32_USART2_REMAP) +# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN3) +# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4) +# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5) +# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6) +# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7) +#else +# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4) +#endif + +#if defined(CONFIG_STM32_USART3_FULL_REMAP) +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN9) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN11) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +#elif defined(CONFIG_STM32_USART3_PARTIAL_REMAP) +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#else +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#endif + +/* SPI */ + +#if defined(CONFIG_STM32_SPI1_REMAP) +# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#else +# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4) +# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN5) +# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6) +# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +#endif + +#define GPIO_SPI2_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +#define GPIO_SPI2_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +#define GPIO_SPI2_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#define GPIO_SPI2_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15) + +#if defined(CONFIG_STM32_SPI3_REMAP) +# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4) +# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +#else +# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#endif + +/* I2C */ + +#if defined(CONFIG_STM32_I2C1_REMAP) +# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +#else +# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6) +# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7) +#endif +#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_CNF_INFLOAT|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) + +#define GPIO_I2C2_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +#define GPIO_I2C2_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#define GPIO_I2C2_SMBA (GPIO_ALT|GPIO_CNF_INFLOAT|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) + +/* CAN */ + +#if defined(CONFIG_STM32_CAN1_REMAP1) +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9) +#elif defined(CONFIG_STM32_CAN1_REMAP2) +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN1) +#else +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +#endif + + +/* SDIO */ + +#define GPIO_SDIO_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8) + +#ifndef CONFIG_SDIO_WIDTH_D1_ONLY +# define GPIO_SDIO_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9) +# define GPIO_SDIO_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_SDIO_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN11) +# define GPIO_SDIO_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_SDIO_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +# define GPIO_SDIO_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +# define GPIO_SDIO_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +#endif + +#define GPIO_SDIO_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +#define GPIO_SDIO_CMD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN2) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F103RE_PINMAP_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f103vc_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f103vc_pinmap.h new file mode 100644 index 0000000000..c8f33321a0 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f103vc_pinmap.h @@ -0,0 +1,423 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f103vc_pinmap.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Laurent Latil + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F103VC_PINMAP_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F103VC_PINMAP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Alternate Pin Functions: */ + +#define GPIO_ADC12_IN0 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC12_IN1 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC12_IN10 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC12_IN11 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC12_IN12 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC12_IN13 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC12_IN14 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC12_IN15 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN5) +#define GPIO_ADC12_IN2 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC12_IN3 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC12_IN4 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC12_IN5 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC12_IN6 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC12_IN7 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC12_IN8 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC12_IN9 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) + +#if defined(CONFIG_STM32_CAN1_FULL_REMAP) +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN1) +#elif defined(CONFIG_STM32_CAN1_PARTIAL_REMAP) +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9) +#else +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +#endif + +/* SDIO */ + +#define GPIO_SDIO_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8) + +#ifndef CONFIG_SDIO_WIDTH_D1_ONLY +# define GPIO_SDIO_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9) +# define GPIO_SDIO_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_SDIO_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN11) +# define GPIO_SDIO_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_SDIO_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +# define GPIO_SDIO_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +# define GPIO_SDIO_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +#endif + +#define GPIO_SDIO_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +#define GPIO_SDIO_CMD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN2) + +/* FSMC: NOR/PSRAM/SRAM (NPS) */ +#define GPIO_NPS_A16 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN11) +#define GPIO_NPS_A17 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +#define GPIO_NPS_A18 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13) +#define GPIO_NPS_A19 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN3) +#define GPIO_NPS_A20 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN4) +#define GPIO_NPS_A21 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN5) +#define GPIO_NPS_A22 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN6) +#define GPIO_NPS_A23 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN2) + +#define GPIO_NPS_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14) +#define GPIO_NPS_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15) +#define GPIO_NPS_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0) +#define GPIO_NPS_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1) +#define GPIO_NPS_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN7) +#define GPIO_NPS_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8) +#define GPIO_NPS_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9) +#define GPIO_NPS_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10) +#define GPIO_NPS_D8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11) +#define GPIO_NPS_D9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12) +#define GPIO_NPS_D10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13) +#define GPIO_NPS_D11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14) +#define GPIO_NPS_D12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN15) +#define GPIO_NPS_D13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +#define GPIO_NPS_D14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9) +#define GPIO_NPS_D15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) + +#define GPIO_NPS_CLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN3) +#define GPIO_NPS_NOE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4) +#define GPIO_NPS_NWE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5) +#define GPIO_NPS_NWAIT (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6) +#define GPIO_NPS_NE1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7) + + +#if 0 /* Needs further investigation */ +#define GPIO_DAC_OUT1 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUTz|GPIO_PORTA|GPIO_PIN4) +#define GPIO_DAC_OUT2 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5) +#endif + +#if defined(CONFIG_STM32_I2C1_REMAP) +# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +#else +# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6) +# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7) +#endif +#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) + +#define GPIO_I2C2_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +#define GPIO_I2C2_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#define GPIO_I2C2_SMBA (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) + +#define GPIO_I2S2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +#define GPIO_I2S2_MCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +#define GPIO_I2S2_WS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) + +#define GPIO_I2S3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +#define GPIO_I2S3_MCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +#define GPIO_I2S3_SD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#define GPIO_I2S3_WS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) + +#if 0 /* Needs further investigation */ +#define GPIO_MCO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +#endif + +#if 0 /* Needs further investigation */ +#define GPIO_OTG_FSDM (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +#define GPIO_OTG_FSDP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12) +#define GPIO_OTG_FSID (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +#define GPIO_OTG_FSSOF (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +#define GPIO_OTG_FSVBUS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +#endif + +#if defined(CONFIG_STM32_SPI1_REMAP) +# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#else +# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4) +# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN5) +# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6) +# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +#endif + +#define GPIO_SPI2_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12) +#define GPIO_SPI2_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +#define GPIO_SPI2_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN14) +#define GPIO_SPI2_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15) + +#if defined(CONFIG_STM32_SPI3_REMAP) +# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4) +# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +#else +# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#endif + +#if 0 /* Needs further investigation */ +#define GPIO_TAMPER_RTC (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN13) +#endif + +#if defined(CONFIG_STM32_TIM1_FULL_REMAP) +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN7) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN9) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN11) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN13) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN14) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN15) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12) +#elif defined(CONFIG_STM32_TIM1_PARTIAL_REMAP) +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#else +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15) +#endif + +#if defined(CONFIG_STM32_TIM2_FULL_REMAP) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_1) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_2) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#else +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#endif + +#if defined(CONFIG_STM32_TIM3_FULL_REMAP) +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9) +#elif defined(CONFIG_STM32_TIM3_PARTIAL_REMAP) +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN5) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#else +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#endif +#define GPIO_TIM3_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN2) + +#if defined(CONFIG_STM32_TIM4_REMAP) +# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN12) +# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN13) +# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13) +# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN14) +# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14) +# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN15) +# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15) +#else +# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6) +# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6) +# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7) +# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7) +# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8) +# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9) +# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +#endif +#define GPIO_TIM4_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN0) + +#define GPIO_TIM5_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH4IN (GGPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM5_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) + +#if 0 /* Needs further investigation */ +#define GPIO_TRACECK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN2) +#define GPIO_TRACED0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN3) +#define GPIO_TRACED1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN4) +#define GPIO_TRACED2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN5) +#define GPIO_TRACED3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN6) +#if defined(CONFIG_STM32_TRACESWO_REMAP) +# define GPIO_TRACESWO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +#endif +#endif + +#define GPIO_USART1_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +#define GPIO_USART1_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12) +#define GPIO_USART1_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +#if defined(CONFIG_STM32_USART1_REMAP) +# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6) +# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +#else +# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +#endif + +#if defined(CONFIG_STM32_USART2_REMAP) +# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN3) +# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4) +# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5) +# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6) +# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7) +#else +# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4) +#endif + +#if defined(CONFIG_STM32_USART3_FULL_REMAP) +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN9) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN11) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +#elif defined(CONFIG_STM32_USART3_PARTIAL_REMAP) +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#else +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#endif + +#define GPIO_UART4_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +#define GPIO_UART4_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) + +#define GPIO_UART5_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN2) +#define GPIO_UART5_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) + +#define GPIO_WKUP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) + +/* Some GPIOs are accessible only as remapped, alternate functions */ + +#if 0 /* Needs further investigation */ +#define GPIO_PA13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN13) +#define GPIO_PA14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN14) +#define GPIO_PA15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +#define GPIO_PB3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +#define GPIO_PB4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4) +#endif + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F103VC_PINMAP_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f103ze_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f103ze_pinmap.h new file mode 100644 index 0000000000..4a320e1fda --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f103ze_pinmap.h @@ -0,0 +1,583 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f103ze_pinmap.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F103ZE_PINMAP_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F103ZE_PINMAP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Alternate Pin Functions: */ + +/* ADC */ + +#define GPIO_ADC1_IN0 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC1_IN1 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC1_IN2 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC1_IN3 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC1_IN4 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC1_IN5 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC1_IN6 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC1_IN7 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC1_IN8 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC1_IN9 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +#define GPIO_ADC1_IN10 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC1_IN11 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC1_IN12 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC1_IN13 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC1_IN14 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC1_IN15 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN5) + +#define GPIO_ADC2_IN0 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC2_IN1 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC2_IN2 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC2_IN3 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC2_IN4 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC2_IN5 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC2_IN6 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC2_IN7 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC2_IN8 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC2_IN9 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +#define GPIO_ADC2_IN10 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC2_IN11 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC2_IN12 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC2_IN13 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC2_IN14 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC2_IN15 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN5) + +#define GPIO_ADC3_IN0 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC3_IN1 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC3_IN2 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC3_IN3 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC3_IN4 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN6) +#define GPIO_ADC3_IN5 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN7) +#define GPIO_ADC3_IN6 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN8) +#define GPIO_ADC3_IN7 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN9) +#define GPIO_ADC3_IN8 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN10) +#define GPIO_ADC3_IN10 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC3_IN11 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC3_IN12 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC3_IN13 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3) + +/* DAC - "Once the DAC channelx is enabled, the corresponding GPIO pin + * (PA4 or PA5) is automatically connected to the analog converter output + * (DAC_OUTx). In order to avoid parasitic consumption, the PA4 or PA5 pin + * should first be configured to analog (AIN)." + */ + +#define GPIO_DAC_OUT1 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN10) +#define GPIO_DAC_OUT2 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PIN10) + +/* TIMERS */ + +#if defined(CONFIG_STM32_TIM1_FULL_REMAP) +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN7) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN9) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN11) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN13) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN14) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN15) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12) +#elif defined(CONFIG_STM32_TIM1_PARTIAL_REMAP) +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#else +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15) +#endif + +#if defined(CONFIG_STM32_TIM2_FULL_REMAP) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_1) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_2) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#else +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#endif + +#if defined(CONFIG_STM32_TIM3_FULL_REMAP) +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9) +#elif defined(CONFIG_STM32_TIM3_PARTIAL_REMAP) +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN5) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#else +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#endif + +#if defined(CONFIG_STM32_TIM4_REMAP) +# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN12) +# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN13) +# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13) +# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN14) +# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14) +# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN15) +# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15) +#else +# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6) +# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6) +# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7) +# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7) +# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8) +# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9) +# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +#endif + +#define GPIO_TIM5_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM5_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) + +#define GPIO_TIM8_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM8_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM8_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM8_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM8_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM8_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM8_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM8_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM8_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM8_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM8_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM8_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +#define GPIO_TIM8_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) + +/* USART */ + +#if defined(CONFIG_STM32_USART1_REMAP) +# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +#else +# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +#endif + +#if defined(CONFIG_STM32_USART2_REMAP) +# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN3) +# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4) +# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5) +# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6) +# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7) +#else +# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4) +#endif + +#if defined(CONFIG_STM32_USART3_FULL_REMAP) +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN9) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN11) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +#elif defined(CONFIG_STM32_USART3_PARTIAL_REMAP) +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#else +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#endif + +/* SPI */ + +#if defined(CONFIG_STM32_SPI1_REMAP) +# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#else +# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4) +# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN5) +# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6) +# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +#endif + +#if defined(CONFIG_STM32_SPI3_REMAP) +# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4) +# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +#else +# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#endif + +/* I2C */ + +#if defined(CONFIG_STM32_I2C1_REMAP) +# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +#else +# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6) +# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7) +#endif + +#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_CNF_INFLOAT|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) + +#define GPIO_I2C2_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +#define GPIO_I2C2_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#define GPIO_I2C2_SMBA (GPIO_ALT|GPIO_CNF_INFLOAT|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) + +/* CAN */ + +#if defined(CONFIG_STM32_CAN1_REMAP1) +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8) +#elif defined(CONFIG_STM32_CAN1_REMAP2) +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN0) +#else +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +#endif + +/* FSMC: CF */ + +#define GPIO_CF_A0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN0) +#define GPIO_CF_A1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN1) +#define GPIO_CF_A2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN2) +#define GPIO_CF_A3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN3) +#define GPIO_CF_A4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN4) +#define GPIO_CF_A5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN5) +#define GPIO_CF_A6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN12) +#define GPIO_CF_A7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN13) +#define GPIO_CF_A8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN14) +#define GPIO_CF_A9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN15) +#define GPIO_CF_A10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN0) +#define GPIO_CF_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14) +#define GPIO_CF_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15) +#define GPIO_CF_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0) +#define GPIO_CF_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1) +#define GPIO_CF_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN7) +#define GPIO_CF_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8) +#define GPIO_CF_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9) +#define GPIO_CF_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10) +#define GPIO_CF_D8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11) +#define GPIO_CF_D9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12) +#define GPIO_CF_D10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13) +#define GPIO_CF_D11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14) +#define GPIO_CF_D12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN15) +#define GPIO_CF_D13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +#define GPIO_CF_D14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9) +#define GPIO_CF_D15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) +#define GPIO_CF_NIORD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN6) +#define GPIO_CF_NREG (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN7) +#define GPIO_CF_NIOWR (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN8) +#define GPIO_CF_CD (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN9) +#define GPIO_CF_INTR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN10) +#define GPIO_CF_NIOS16 (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN11) +#define GPIO_CF_NOE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4) +#define GPIO_CF_NWE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5) +#define GPIO_CF_NWAIT (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6) +#define GPIO_CF_NCE41 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN10) +#define GPIO_CF_NCE42 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN11) + +/* FSMC: CF/IDE */ + +#define GPIO_CFIDE_A0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN0) +#define GPIO_CFIDE_A1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN1) +#define GPIO_CFIDE_A2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN2) +#define GPIO_CFIDE_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14) +#define GPIO_CFIDE_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15) +#define GPIO_CFIDE_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0) +#define GPIO_CFIDE_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1) +#define GPIO_CFIDE_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN7) +#define GPIO_CFIDE_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8) +#define GPIO_CFIDE_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9) +#define GPIO_CFIDE_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10) +#define GPIO_CFIDE_D8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11) +#define GPIO_CFIDE_D9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12) +#define GPIO_CFIDE_D10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13) +#define GPIO_CFIDE_D11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14) +#define GPIO_CFIDE_D12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN15) +#define GPIO_CFIDE_D13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +#define GPIO_CFIDE_D14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9) +#define GPIO_CFIDE_D15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) +#define GPIO_CFIDE_NIORD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN6) +#define GPIO_CFIDE_NREG (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN7) +#define GPIO_CFIDE_NIOWR (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN8) +#define GPIO_CFIDE_CD (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN9) +#define GPIO_CFIDE_INTR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN10) +#define GPIO_CFIDE_NIOS16 (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN11) +#define GPIO_CFIDE_NOE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4) +#define GPIO_CFIDE_NWE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5) +#define GPIO_CFIDE_NWAIT (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6) +#define GPIO_CFIDE_NCE41 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN10) +#define GPIO_CFIDE_NCE42 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN11) + +/* SDIO */ + +#define GPIO_SDIO_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8) + +#ifndef CONFIG_SDIO_WIDTH_D1_ONLY +# define GPIO_SDIO_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9) +# define GPIO_SDIO_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_SDIO_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN11) +# define GPIO_SDIO_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_SDIO_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +# define GPIO_SDIO_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +# define GPIO_SDIO_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +#endif + +#define GPIO_SDIO_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +#define GPIO_SDIO_CMD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN2) + +/* FSMC: NOR/PSRAM/SRAM (NPS) */ + +#define GPIO_NPS_A0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN0) +#define GPIO_NPS_A1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN1) +#define GPIO_NPS_A2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN2) +#define GPIO_NPS_A3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN3) +#define GPIO_NPS_A4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN4) +#define GPIO_NPS_A5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN5) +#define GPIO_NPS_A6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN12) +#define GPIO_NPS_A7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN13) +#define GPIO_NPS_A8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN14) +#define GPIO_NPS_A9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN15) +#define GPIO_NPS_A10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN0) +#define GPIO_NPS_A11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN1) +#define GPIO_NPS_A12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN2) +#define GPIO_NPS_A13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN3) +#define GPIO_NPS_A14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN4) +#define GPIO_NPS_A15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN5) +#define GPIO_NPS_A16 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN11) +#define GPIO_NPS_A17 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +#define GPIO_NPS_A18 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13) +#define GPIO_NPS_A19 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN3) +#define GPIO_NPS_A20 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN4) +#define GPIO_NPS_A21 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN5) +#define GPIO_NPS_A22 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN6) +#define GPIO_NPS_A23 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN2) +#define GPIO_NPS_A24 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN13) +#define GPIO_NPS_A25 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN14) +#define GPIO_NPS_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14) +#define GPIO_NPS_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15) +#define GPIO_NPS_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0) +#define GPIO_NPS_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1) +#define GPIO_NPS_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN7) +#define GPIO_NPS_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8) +#define GPIO_NPS_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9) +#define GPIO_NPS_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10) +#define GPIO_NPS_D8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11) +#define GPIO_NPS_D9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12) +#define GPIO_NPS_D10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13) +#define GPIO_NPS_D11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14) +#define GPIO_NPS_D12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN15) +#define GPIO_NPS_D13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +#define GPIO_NPS_D14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9) +#define GPIO_NPS_D15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) +#define GPIO_NPS_CLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN3) +#define GPIO_NPS_NOE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4) +#define GPIO_NPS_NWE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5) +#define GPIO_NPS_NWAIT (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6) +#define GPIO_NPS_NE1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7) +#define GPIO_NPS_NE2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN9) +#define GPIO_NPS_NE3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN10) +#define GPIO_NPS_NE4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN12) +#define GPIO_NPS_NBL0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN0) +#define GPIO_NPS_NBL1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN1) + +/* FSMC: NOR/PSRAM Multiplex (NPM) */ + +#define GPIO_NPM_A16 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN11) +#define GPIO_NPM_A17 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +#define GPIO_NPM_A18 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13) +#define GPIO_NPM_A19 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN3) +#define GPIO_NPM_A20 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN4) +#define GPIO_NPM_A21 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN5) +#define GPIO_NPM_A22 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN6) +#define GPIO_NPM_A23 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN2) +#define GPIO_NPM_DA0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14) +#define GPIO_NPM_DA1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15) +#define GPIO_NPM_DA2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0) +#define GPIO_NPM_DA3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1) +#define GPIO_NPM_DA4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN7) +#define GPIO_NPM_DA5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8) +#define GPIO_NPM_DA6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9) +#define GPIO_NPM_DA7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10) +#define GPIO_NPM_DA8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11) +#define GPIO_NPM_DA9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12) +#define GPIO_NPM_DA10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13) +#define GPIO_NPM_DA11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14) +#define GPIO_NPM_DA12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN15) +#define GPIO_NPM_DA13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +#define GPIO_NPM_DA14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9) +#define GPIO_NPM_DA15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) +#define GPIO_NPM_CLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN3) +#define GPIO_NPM_NOE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4) +#define GPIO_NPM_NWE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5) +#define GPIO_NPM_NWAIT (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6) +#define GPIO_NPM_NE1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7) +#define GPIO_NPM_NE2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN9) +#define GPIO_NPM_NE3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN10) +#define GPIO_NPM_NE4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN12) +#define GPIO_NPM_A24 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN13) +#define GPIO_NPM_A25 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN14) +#define GPIO_NPM_NBL0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN0) +#define GPIO_NPM_NBL1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN1) + +/* FSMC: NAND */ + +#define GPIO_NAND_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN7) +#define GPIO_NAND_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8) +#define GPIO_NAND_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9) +#define GPIO_NAND_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10) +#define GPIO_NAND_D8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11) +#define GPIO_NAND_D9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12) +#define GPIO_NAND_D10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13) +#define GPIO_NAND_D11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14) +#define GPIO_NAND_D12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN15) +#define GPIO_NAND_D13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +#define GPIO_NAND_D14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9) +#define GPIO_NAND_D15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) +#define GPIO_NAND_CLE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN11) +#define GPIO_NAND_ALE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +#define GPIO_NAND_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14) +#define GPIO_NAND_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15) +#define GPIO_NAND_INT2 (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTG|GPIO_PIN6) +#define GPIO_NAND_INT3 (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTG|GPIO_PIN7) +#define GPIO_NAND_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0) +#define GPIO_NAND_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1) +#define GPIO_NAND_NOE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4) +#define GPIO_NAND_NWE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5) +#define GPIO_NAND_NWAIT (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6) +#define GPIO_NAND_NCE2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7) +#define GPIO_NAND_NCE3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN9) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F103ZE_PINMAP_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f105vb_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f105vb_pinmap.h new file mode 100644 index 0000000000..81f621dd9f --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f105vb_pinmap.h @@ -0,0 +1,416 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f105vb_pinmap.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F105VB_PINMAP_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F105VB_PINMAP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Alternate Pin Functions: */ + +#define GPIO_ADC12_IN0 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC12_IN1 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC12_IN10 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC12_IN11 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC12_IN12 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC12_IN13 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC12_IN14 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC12_IN15 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN5) +#define GPIO_ADC12_IN2 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC12_IN3 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC12_IN4 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC12_IN5 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC12_IN6 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC12_IN7 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC12_IN8 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC12_IN9 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) + +#if defined(CONFIG_STM32_CAN1_FULL_REMAP) +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN1) +#elif defined(CONFIG_STM32_CAN1_PARTIAL_REMAP) +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9) +#else +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +#endif + +#if defined(CONFIG_STM32_CAN2_REMAP) +# define GPIO_CAN2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +# define GPIO_CAN2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6) +#else +# define GPIO_CAN2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +# define GPIO_CAN2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +#endif + +#if 0 /* Needs further investigation */ +#define GPIO_DAC_OUT1 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUTz|GPIO_PORTA|GPIO_PIN4) +#define GPIO_DAC_OUT2 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5) +#endif + +#if 0 /* Needs further investigation */ +#define GPIO_ETH_MDC (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ETH_MDIO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ETH_MIICOL (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ETH_MIICRSWKUP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ETH_MIIRXCLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) + +#if defined(CONFIG_STM32_ETH_REMAP) +# define GPIO_ETH_MIIRXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9) +# define GPIO_ETH_MIIRXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) +# define GPIO_ETH_MIIRXD2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN11) +# define GPIO_ETH_MIIRXD3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +# define GPIO_ETH_MIIRXDV (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +#else +# define GPIO_ETH_MIIRXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN4) +# define GPIO_ETH_MIIRXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN5) +# define GPIO_ETH_MIIRXD2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_ETH_MIIRXD3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +# define GPIO_ETH_MIIRXDV (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +#endif + +#define GPIO_ETH_MIIRXER (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +#define GPIO_ETH_MIITXCLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ETH_MIITXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +#define GPIO_ETH_MIITXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +#define GPIO_ETH_MIITXD2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ETH_MIITXD3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +#define GPIO_ETH_MIITXEN (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#define GPIO_ETH_PPSOUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#define GPIO_ETH_RMIICRSDV (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ETH_RMIIREFCLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ETH_RMIIRXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ETH_RMIIRXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN5) +#define GPIO_ETH_RMIITXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +#define GPIO_ETH_RMIITXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +#define GPIO_ETH_RMIITXEN (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#endif + +#if defined(CONFIG_STM32_I2C1_REMAP) +# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +#else +# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6) +# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7) +#endif +#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) + +#define GPIO_I2C2_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +#define GPIO_I2C2_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#define GPIO_I2C2_SMBA (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +#define GPIO_I2S2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +#define GPIO_I2S2_MCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +#define GPIO_I2S2_WS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) + +#define GPIO_I2S3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +#define GPIO_I2S3_MCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +#define GPIO_I2S3_SD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#define GPIO_I2S3_WS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) + +#if 0 /* Needs further investigation */ +#define GPIO_MCO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +#endif + +#if 0 /* Needs further investigation */ +#define GPIO_OTG_FSDM (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +#define GPIO_OTG_FSDP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12) +#define GPIO_OTG_FSID (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +#define GPIO_OTG_FSSOF (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +#define GPIO_OTG_FSVBUS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +#endif + +#if defined(CONFIG_STM32_SPI1_REMAP) +# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#else +# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4) +# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN5) +# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6) +# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +#endif + +#define GPIO_SPI2_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12) +#define GPIO_SPI2_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +#define GPIO_SPI2_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN14) +#define GPIO_SPI2_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15) + +#if defined(CONFIG_STM32_SPI3_REMAP) +# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4) +# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +#else +# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#endif + +#if 0 /* Needs further investigation */ +#define GPIO_TAMPER_RTC (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN13) +#endif + +#if defined(CONFIG_STM32_TIM1_FULL_REMAP) +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN7) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN9) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN11) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN13) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN14) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN15) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12) +#elif defined(CONFIG_STM32_TIM1_PARTIAL_REMAP) +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#else +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15) +#endif + +#if defined(CONFIG_STM32_TIM2_FULL_REMAP) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_1) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_2) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#else +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#endif + +#if defined(CONFIG_STM32_TIM3_FULL_REMAP) +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9) +#elif defined(CONFIG_STM32_TIM3_PARTIAL_REMAP) +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN5) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#else +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#endif +#define GPIO_TIM3_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN2) + +#if defined(CONFIG_STM32_TIM4_REMAP) +# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN12) +# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN13) +# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13) +# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN14) +# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14) +# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN15) +# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15) +#else +# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6) +# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6) +# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7) +# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7) +# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8) +# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9) +# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +#endif +#define GPIO_TIM4_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN0) + +#define GPIO_TIM5_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH4IN (GGPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM5_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) + +#if 0 /* Needs further investigation */ +#define GPIO_TRACECK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN2) +#define GPIO_TRACED0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN3) +#define GPIO_TRACED1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN4) +#define GPIO_TRACED2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN5) +#define GPIO_TRACED3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN6) +#if defined(CONFIG_STM32_TRACESWO_REMAP) +# define GPIO_TRACESWO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +#endif +#endif + +#define GPIO_USART1_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +#define GPIO_USART1_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12) +#define GPIO_USART1_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +#if defined(CONFIG_STM32_USART1_REMAP) +# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +#else +# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +#endif + +#if defined(CONFIG_STM32_USART2_REMAP) +# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN3) +# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4) +# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5) +# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6) +# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7) +#else +# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4) +#endif + +#if defined(CONFIG_STM32_USART3_FULL_REMAP) +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN9) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN11) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +#elif defined(CONFIG_STM32_USART3_PARTIAL_REMAP) +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#else +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#endif + +#define GPIO_UART4_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +#define GPIO_UART4_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) + +#define GPIO_UART5_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN2) +#define GPIO_UART5_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) + +#define GPIO_WKUP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) + +/* Some GPIOs are accessible only as remapped, alternate functions */ + +#if 0 /* Needs further investigation */ +#define GPIO_PA13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN13) +#define GPIO_PA14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN14) +#define GPIO_PA15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +#define GPIO_PB3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +#define GPIO_PB4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4) +#endif + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F105VB_PINMAP_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f107vc_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f107vc_pinmap.h new file mode 100644 index 0000000000..0b46d79fa9 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f107vc_pinmap.h @@ -0,0 +1,416 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f107vc_pinmap.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F107VC_PINMAP_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F107VC_PINMAP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Alternate Pin Functions: */ + +#define GPIO_ADC12_IN0 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC12_IN1 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC12_IN10 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC12_IN11 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC12_IN12 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC12_IN13 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC12_IN14 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC12_IN15 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN5) +#define GPIO_ADC12_IN2 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC12_IN3 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC12_IN4 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC12_IN5 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC12_IN6 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC12_IN7 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC12_IN8 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC12_IN9 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) + +#if defined(CONFIG_STM32_CAN1_FULL_REMAP) +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN1) +#elif defined(CONFIG_STM32_CAN1_PARTIAL_REMAP) +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9) +#else +# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +#endif + +#if defined(CONFIG_STM32_CAN2_REMAP) +# define GPIO_CAN2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +# define GPIO_CAN2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6) +#else +# define GPIO_CAN2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +# define GPIO_CAN2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +#endif + +#if 0 /* Needs further investigation */ +#define GPIO_DAC_OUT1 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUTz|GPIO_PORTA|GPIO_PIN4) +#define GPIO_DAC_OUT2 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5) +#endif + +#if 0 /* Needs further investigation */ +#define GPIO_ETH_MDC (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ETH_MDIO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ETH_MIICOL (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ETH_MIICRSWKUP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ETH_MIIRXCLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) + +#if defined(CONFIG_STM32_ETH_REMAP) +# define GPIO_ETH_MIIRXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9) +# define GPIO_ETH_MIIRXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) +# define GPIO_ETH_MIIRXD2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN11) +# define GPIO_ETH_MIIRXD3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +# define GPIO_ETH_MIIRXDV (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +#else +# define GPIO_ETH_MIIRXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN4) +# define GPIO_ETH_MIIRXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN5) +# define GPIO_ETH_MIIRXD2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_ETH_MIIRXD3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +# define GPIO_ETH_MIIRXDV (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +#endif + +#define GPIO_ETH_MIIRXER (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +#define GPIO_ETH_MIITXCLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ETH_MIITXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +#define GPIO_ETH_MIITXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +#define GPIO_ETH_MIITXD2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ETH_MIITXD3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +#define GPIO_ETH_MIITXEN (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#define GPIO_ETH_PPSOUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#define GPIO_ETH_RMIICRSDV (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ETH_RMIIREFCLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ETH_RMIIRXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ETH_RMIIRXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN5) +#define GPIO_ETH_RMIITXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +#define GPIO_ETH_RMIITXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +#define GPIO_ETH_RMIITXEN (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#endif + +#if defined(CONFIG_STM32_I2C1_REMAP) +# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +#else +# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6) +# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7) +#endif +#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) + +#define GPIO_I2C2_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +#define GPIO_I2C2_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#define GPIO_I2C2_SMBA (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +#define GPIO_I2S2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +#define GPIO_I2S2_MCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +#define GPIO_I2S2_WS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) + +#define GPIO_I2S3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +#define GPIO_I2S3_MCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +#define GPIO_I2S3_SD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#define GPIO_I2S3_WS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) + +#if 0 /* Needs further investigation */ +#define GPIO_MCO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +#endif + +#if 0 /* Needs further investigation */ +#define GPIO_OTG_FSDM (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +#define GPIO_OTG_FSDP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12) +#define GPIO_OTG_FSID (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +#define GPIO_OTG_FSSOF (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +#define GPIO_OTG_FSVBUS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +#endif + +#if defined(CONFIG_STM32_SPI1_REMAP) +# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#else +# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4) +# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN5) +# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6) +# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +#endif + +#define GPIO_SPI2_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12) +#define GPIO_SPI2_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +#define GPIO_SPI2_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN14) +#define GPIO_SPI2_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15) + +#if defined(CONFIG_STM32_SPI3_REMAP) +# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4) +# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +#else +# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +#endif + +#if 0 /* Needs further investigation */ +#define GPIO_TAMPER_RTC (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN13) +#endif + +#if defined(CONFIG_STM32_TIM1_FULL_REMAP) +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN7) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN9) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN11) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN13) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN14) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN15) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12) +#elif defined(CONFIG_STM32_TIM1_PARTIAL_REMAP) +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#else +# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12) +# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10) +# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11) +# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12) +# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13) +# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15) +#endif + +#if defined(CONFIG_STM32_TIM2_FULL_REMAP) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_1) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_2) +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11) +#else +# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) +#endif + +#if defined(CONFIG_STM32_TIM3_FULL_REMAP) +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9) +#elif defined(CONFIG_STM32_TIM3_PARTIAL_REMAP) +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN5) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#else +# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6) +# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7) +# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0) +# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1) +#endif +#define GPIO_TIM3_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN2) + +#if defined(CONFIG_STM32_TIM4_REMAP) +# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN12) +# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN13) +# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13) +# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN14) +# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14) +# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN15) +# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15) +#else +# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6) +# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6) +# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7) +# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7) +# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8) +# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8) +# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9) +# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9) +#endif +#define GPIO_TIM4_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN0) + +#define GPIO_TIM5_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH4IN (GGPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM5_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3) + +#if 0 /* Needs further investigation */ +#define GPIO_TRACECK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN2) +#define GPIO_TRACED0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN3) +#define GPIO_TRACED1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN4) +#define GPIO_TRACED2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN5) +#define GPIO_TRACED3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN6) +#if defined(CONFIG_STM32_TRACESWO_REMAP) +# define GPIO_TRACESWO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +#endif +#endif + +#define GPIO_USART1_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11) +#define GPIO_USART1_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12) +#define GPIO_USART1_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8) +#if defined(CONFIG_STM32_USART1_REMAP) +# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +#else +# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9) +# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10) +#endif + +#if defined(CONFIG_STM32_USART2_REMAP) +# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN3) +# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4) +# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5) +# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6) +# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7) +#else +# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1) +# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2) +# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4) +#endif + +#if defined(CONFIG_STM32_USART3_FULL_REMAP) +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN9) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN11) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12) +#elif defined(CONFIG_STM32_USART3_PARTIAL_REMAP) +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#else +# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10) +# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11) +# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12) +# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) +# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14) +#endif + +#define GPIO_UART4_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11) +#define GPIO_UART4_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10) + +#define GPIO_UART5_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN2) +#define GPIO_UART5_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12) + +#define GPIO_WKUP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0) + +/* Some GPIOs are accessible only as remapped, alternate functions */ + +#if 0 /* Needs further investigation */ +#define GPIO_PA13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN13) +#define GPIO_PA14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN14) +#define GPIO_PA15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15) +#define GPIO_PB3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3) +#define GPIO_PB4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4) +#endif + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F107VC_PINMAP_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_dma.h b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_dma.h new file mode 100644 index 0000000000..a8241bc724 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_dma.h @@ -0,0 +1,350 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f10xxx_dma.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_DMA_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_DMA_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* 7 DMA Channels */ + +#define DMA1 0 +#define DMA2 1 +#define DMA3 2 +#define DMA4 3 +#define DMA5 4 +#define DMA6 5 +#define DMA7 6 + +/* Register Offsets *****************************************************************/ + +#define STM32_DMA_ISR_OFFSET 0x0000 /* DMA interrupt status register */ +#define STM32_DMA_IFCR_OFFSET 0x0004 /* DMA interrupt flag clear register */ + +#define STM32_DMACHAN_OFFSET(n) (0x0014*(n)) +#define STM32_DMACHAN_CCR_OFFSET 0x0008 +#define STM32_DMACHAN_CNDTR_OFFSET 0x000c +#define STM32_DMACHAN_CPAR_OFFSET 0x0010 +#define STM32_DMACHAN_CMAR_OFFSET 0x0014 + +#define STM32_DMA_CCR_OFFSET(n) (STM32_DMACHAN_CCR_OFFSET+STM32_DMACHAN_OFFSET(n)) +#define STM32_DMA_CNDTR_OFFSET(n) (STM32_DMACHAN_CNDTR_OFFSET+STM32_DMACHAN_OFFSET(n)) +#define STM32_DMA_CPAR_OFFSET(n) (STM32_DMACHAN_CPAR_OFFSET+STM32_DMACHAN_OFFSET(n)) +#define STM32_DMA_CMAR_OFFSET(n) (STM32_DMACHAN_CMAR_OFFSET+STM32_DMACHAN_OFFSET(n)) + +#define STM32_DMA_CCR1_OFFSET 0x0008 /* DMA channel 1 configuration register */ +#define STM32_DMA_CCR2_OFFSET 0x001c /* DMA channel 2 configuration register */ +#define STM32_DMA_CCR3_OFFSET 0x0030 /* DMA channel 3 configuration register */ +#define STM32_DMA_CCR4_OFFSET 0x0044 /* DMA channel 4 configuration register */ +#define STM32_DMA_CCR5_OFFSET 0x0058 /* DMA channel 5 configuration register */ +#define STM32_DMA_CCR6_OFFSET 0x006c /* DMA channel 6 configuration register */ +#define STM32_DMA_CCR7_OFFSET 0x0080 /* DMA channel 7 configuration register */ + +#define STM32_DMA_CNDTR1_OFFSET 0x000c /* DMA channel 1 number of data register */ +#define STM32_DMA_CNDTR2_OFFSET 0x0020 /* DMA channel 2 number of data register */ +#define STM32_DMA_CNDTR3_OFFSET 0x0034 /* DMA channel 3 number of data register */ +#define STM32_DMA_CNDTR4_OFFSET 0x0048 /* DMA channel 4 number of data register */ +#define STM32_DMA_CNDTR5_OFFSET 0x005c /* DMA channel 5 number of data register */ +#define STM32_DMA_CNDTR6_OFFSET 0x0070 /* DMA channel 6 number of data register */ +#define STM32_DMA_CNDTR7_OFFSET 0x0084 /* DMA channel 7 number of data register */ + +#define STM32_DMA_CPAR1_OFFSET 0x0010 /* DMA channel 1 peripheral address register */ +#define STM32_DMA_CPAR2_OFFSET 0x0024 /* DMA channel 2 peripheral address register */ +#define STM32_DMA_CPAR3_OFFSET 0x0038 /* DMA channel 3 peripheral address register */ +#define STM32_DMA_CPAR4_OFFSET 0x004c /* DMA channel 4 peripheral address register */ +#define STM32_DMA_CPAR5_OFFSET 0x0060 /* DMA channel 5 peripheral address register */ +#define STM32_DMA_CPAR6_OFFSET 0x0074 /* DMA channel 6 peripheral address register */ +#define STM32_DMA_CPAR7_OFFSET 0x0088 /* DMA channel 7 peripheral address register */ + +#define STM32_DMA_CMAR1_OFFSET 0x0014 /* DMA channel 1 memory address register */ +#define STM32_DMA_CMAR2_OFFSET 0x0028 /* DMA channel 2 memory address register */ +#define STM32_DMA_CMAR3_OFFSET 0x003c /* DMA channel 3 memory address register */ +#define STM32_DMA_CMAR4_OFFSET 0x0050 /* DMA channel 4 memory address register */ +#define STM32_DMA_CMAR5_OFFSET 0x0064 /* DMA channel 5 memory address register */ +#define STM32_DMA_CMAR6_OFFSET 0x0078 /* DMA channel 6 memory address register */ +#define STM32_DMA_CMAR7_OFFSET 0x008c /* DMA channel 7 memory address register */ + +/* Register Addresses ***************************************************************/ + +#define STM32_DMA1_ISRC (STM32_DMA1_BASE+STM32_DMA_ISR_OFFSET) +#define STM32_DMA1_IFCR (STM32_DMA1_BASE+STM32_DMA_IFCR_OFFSET) + +#define STM32_DMA1_CCR(n) (STM32_DMA1_BASE+STM32_DMA_CCR_OFFSET(n)) +#define STM32_DMA1_CCR1 (STM32_DMA1_BASE+STM32_DMA_CCR1_OFFSET) +#define STM32_DMA1_CCR2 (STM32_DMA1_BASE+STM32_DMA_CCR2_OFFSET) +#define STM32_DMA1_CCR3 (STM32_DMA1_BASE+STM32_DMA_CCR3_OFFSET) +#define STM32_DMA1_CCR4 (STM32_DMA1_BASE+STM32_DMA_CCR4_OFFSET) +#define STM32_DMA1_CCR5 (STM32_DMA1_BASE+STM32_DMA_CCR5_OFFSET) +#define STM32_DMA1_CCR6 (STM32_DMA1_BASE+STM32_DMA_CCR6_OFFSET) +#define STM32_DMA1_CCR7 (STM32_DMA1_BASE+STM32_DMA_CCR7_OFFSET) + +#define STM32_DMA1_CNDTR(n) (STM32_DMA1_BASE+STM32_DMA_CNDTR_OFFSET(n)) +#define STM32_DMA1_CNDTR1 (STM32_DMA1_BASE+STM32_DMA_CNDTR1_OFFSET) +#define STM32_DMA1_CNDTR2 (STM32_DMA1_BASE+STM32_DMA_CNDTR2_OFFSET) +#define STM32_DMA1_CNDTR3 (STM32_DMA1_BASE+STM32_DMA_CNDTR3_OFFSET) +#define STM32_DMA1_CNDTR4 (STM32_DMA1_BASE+STM32_DMA_CNDTR4_OFFSET) +#define STM32_DMA1_CNDTR5 (STM32_DMA1_BASE+STM32_DMA_CNDTR5_OFFSET) +#define STM32_DMA1_CNDTR6 (STM32_DMA1_BASE+STM32_DMA_CNDTR6_OFFSET) +#define STM32_DMA1_CNDTR7 (STM32_DMA1_BASE+STM32_DMA_CNDTR7_OFFSET) + +#define STM32_DMA1_CPAR(n) (STM32_DMA1_BASE+STM32_DMA_CPAR_OFFSET(n)) +#define STM32_DMA1_CPAR1 (STM32_DMA1_BASE+STM32_DMA_CPAR1_OFFSET) +#define STM32_DMA1_CPAR2 (STM32_DMA1_BASE+STM32_DMA_CPAR2_OFFSET) +#define STM32_DMA1_CPAR3 (STM32_DMA1_BASE+STM32_DMA_CPAR3_OFFSET) +#define STM32_DMA1_CPAR4 (STM32_DMA1_BASE+STM32_DMA_CPAR4_OFFSET) +#define STM32_DMA1_CPAR5 (STM32_DMA1_BASE+STM32_DMA_CPAR5_OFFSET) +#define STM32_DMA1_CPAR6 (STM32_DMA1_BASE+STM32_DMA_CPAR6_OFFSET) +#define STM32_DMA1_CPAR7 (STM32_DMA1_BASE+STM32_DMA_CPAR7_OFFSET) + +#define STM32_DMA1_CMAR(n) (STM32_DMA1_BASE+STM32_DMA_CMAR_OFFSET(n)) +#define STM32_DMA1_CMAR1 (STM32_DMA1_BASE+STM32_DMA_CMAR1_OFFSET) +#define STM32_DMA1_CMAR2 (STM32_DMA1_BASE+STM32_DMA_CMAR2_OFFSET) +#define STM32_DMA1_CMAR3 (STM32_DMA1_BASE+STM32_DMA_CMAR3_OFFSET) +#define STM32_DMA1_CMAR4 (STM32_DMA1_BASE+STM32_DMA_CMAR4_OFFSET) +#define STM32_DMA1_CMAR5 (STM32_DMA1_BASE+STM32_DMA_CMAR5_OFFSET) +#define STM32_DMA1_CMAR6 (STM32_DMA1_BASE+STM32_DMA_CMAR6_OFFSET) +#define STM32_DMA1_CMAR7 (STM32_DMA1_BASE+STM32_DMA_CMAR7_OFFSET) + +#define STM32_DMA2_ISRC (STM32_DMA2_BASE+STM32_DMA_ISR_OFFSET) +#define STM32_DMA2_IFCR (STM32_DMA2_BASE+STM32_DMA_IFCR_OFFSET) + +#define STM32_DMA2_CCR(n) (STM32_DMA2_BASE+STM32_DMA_CCR_OFFSET(n)) +#define STM32_DMA2_CCR1 (STM32_DMA2_BASE+STM32_DMA_CCR1_OFFSET) +#define STM32_DMA2_CCR2 (STM32_DMA2_BASE+STM32_DMA_CCR2_OFFSET) +#define STM32_DMA2_CCR3 (STM32_DMA2_BASE+STM32_DMA_CCR3_OFFSET) +#define STM32_DMA2_CCR4 (STM32_DMA2_BASE+STM32_DMA_CCR4_OFFSET) +#define STM32_DMA2_CCR5 (STM32_DMA2_BASE+STM32_DMA_CCR5_OFFSET) + +#define STM32_DMA2_CNDTR(n) (STM32_DMA2_BASE+STM32_DMA_CNDTR_OFFSET(n)) +#define STM32_DMA2_CNDTR1 (STM32_DMA2_BASE+STM32_DMA_CNDTR1_OFFSET) +#define STM32_DMA2_CNDTR2 (STM32_DMA2_BASE+STM32_DMA_CNDTR2_OFFSET) +#define STM32_DMA2_CNDTR3 (STM32_DMA2_BASE+STM32_DMA_CNDTR3_OFFSET) +#define STM32_DMA2_CNDTR4 (STM32_DMA2_BASE+STM32_DMA_CNDTR4_OFFSET) +#define STM32_DMA2_CNDTR5 (STM32_DMA2_BASE+STM32_DMA_CNDTR5_OFFSET) + +#define STM32_DMA2_CPAR(n) (STM32_DMA2_BASE+STM32_DMA_CPAR_OFFSET(n)) +#define STM32_DMA2_CPAR1 (STM32_DMA2_BASE+STM32_DMA_CPAR1_OFFSET) +#define STM32_DMA2_CPAR2 (STM32_DMA2_BASE+STM32_DMA_CPAR2_OFFSET) +#define STM32_DMA2_CPAR3 (STM32_DMA2_BASE+STM32_DMA_CPAR3_OFFSET) +#define STM32_DMA2_CPAR4 (STM32_DMA2_BASE+STM32_DMA_CPAR4_OFFSET) +#define STM32_DMA2_CPAR5 (STM32_DMA2_BASE+STM32_DMA_CPAR5_OFFSET) + +#define STM32_DMA2_CMAR(n) (STM32_DMA2_BASE+STM32_DMA_CMAR_OFFSET(n)) +#define STM32_DMA2_CMAR1 (STM32_DMA2_BASE+STM32_DMA_CMAR1_OFFSET) +#define STM32_DMA2_CMAR2 (STM32_DMA2_BASE+STM32_DMA_CMAR2_OFFSET) +#define STM32_DMA2_CMAR3 (STM32_DMA2_BASE+STM32_DMA_CMAR3_OFFSET) +#define STM32_DMA2_CMAR4 (STM32_DMA2_BASE+STM32_DMA_CMAR4_OFFSET) +#define STM32_DMA2_CMAR5 (STM32_DMA2_BASE+STM32_DMA_CMAR5_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +#define DMA_CHAN_SHIFT(n) ((n) << 2) +#define DMA_CHAN_MASK 0x0f +#define DMA_CHAN_GIF_BIT (1 << 0) /* Bit 0: Channel Global interrupt flag */ +#define DMA_CHAN_TCIF_BIT (1 << 1) /* Bit 1: Channel Transfer Complete flag */ +#define DMA_CHAN_HTIF_BIT (1 << 2) /* Bit 2: Channel Half Transfer flag */ +#define DMA_CHAN_TEIF_BIT (1 << 3) /* Bit 3: Channel Transfer Error flag */ + +/* DMA interrupt status register */ + +#define DMA_ISR_CHAN_SHIFT(n) DMA_CHAN_SHIFT(n) +#define DMA_ISR_CHAN_MASK(n) (DMA_CHAN_MASK << DMA_ISR_CHAN_SHIFT(n)) +#define DMA_ISR_CHAN1_SHIFT (0) /* Bits 3-0: DMA Channel 1 interrupt status */ +#define DMA_ISR_CHAN1_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN1_SHIFT) +#define DMA_ISR_CHAN2_SHIFT (4) /* Bits 7-4: DMA Channel 2 interrupt status */ +#define DMA_ISR_CHAN2_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN2_SHIFT) +#define DMA_ISR_CHAN3_SHIFT (8) /* Bits 11-8: DMA Channel 3 interrupt status */ +#define DMA_ISR_CHAN3_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN3_SHIFT) +#define DMA_ISR_CHAN4_SHIFT (12) /* Bits 15-12: DMA Channel 4 interrupt status */ +#define DMA_ISR_CHAN4_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN4_SHIFT) +#define DMA_ISR_CHAN5_SHIFT (16) /* Bits 19-16: DMA Channel 5 interrupt status */ +#define DMA_ISR_CHAN5_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN5_SHIFT) +#define DMA_ISR_CHAN6_SHIFT (20) /* Bits 23-20: DMA Channel 6 interrupt status */ +#define DMA_ISR_CHAN6_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN6_SHIFT) +#define DMA_ISR_CHAN7_SHIFT (24) /* Bits 27-24: DMA Channel 7 interrupt status */ +#define DMA_ISR_CHAN7_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN7_SHIFT) + +#define DMA_ISR_GIF(n) (DMA_CHAN_GIF_BIT << DMA_ISR_CHAN_SHIFT(n)) +#define DMA_ISR_TCIF(n) (DMA_CHAN_TCIF_BIT << DMA_ISR_CHAN_SHIFT(n)) +#define DMA_ISR_HTIF(n) (DMA_CHAN_HTIF_BIT << DMA_ISR_CHAN_SHIFT(n)) +#define DMA_ISR_TEIF(n) (DMA_CHAN_TEIF_BIT << DMA_ISR_CHAN_SHIFT(n)) + +/* DMA interrupt flag clear register */ + +#define DMA_IFCR_CHAN_SHIFT(n) DMA_CHAN_SHIFT(n) +#define DMA_IFCR_CHAN_MASK(n) (DMA_CHAN_MASK << DMA_IFCR_CHAN_SHIFT(n)) +#define DMA_IFCR_CHAN1_SHIFT (0) /* Bits 3-0: DMA Channel 1 interrupt flag clear */ +#define DMA_IFCR_CHAN1_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN1_SHIFT) +#define DMA_IFCR_CHAN2_SHIFT (4) /* Bits 7-4: DMA Channel 2 interrupt flag clear */ +#define DMA_IFCR_CHAN2_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN2_SHIFT) +#define DMA_IFCR_CHAN3_SHIFT (8) /* Bits 11-8: DMA Channel 3 interrupt flag clear */ +#define DMA_IFCR_CHAN3_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN3_SHIFT) +#define DMA_IFCR_CHAN4_SHIFT (12) /* Bits 15-12: DMA Channel 4 interrupt flag clear */ +#define DMA_IFCR_CHAN4_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN4_SHIFT) +#define DMA_IFCR_CHAN5_SHIFT (16) /* Bits 19-16: DMA Channel 5 interrupt flag clear */ +#define DMA_IFCR_CHAN5_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN5_SHIFT) +#define DMA_IFCR_CHAN6_SHIFT (20) /* Bits 23-20: DMA Channel 6 interrupt flag clear */ +#define DMA_IFCR_CHAN6_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN6_SHIFT) +#define DMA_IFCR_CHAN7_SHIFT (24) /* Bits 27-24: DMA Channel 7 interrupt flag clear */ +#define DMA_IFCR_CHAN7_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN7_SHIFT) +#define DMA_IFCR_ALLCHANNELS (0x0fffffff) + +#define DMA_IFCR_CGIF(n) (DMA_CHAN_GIF_BIT << DMA_IFCR_CHAN_SHIFT(n)) +#define DMA_IFCR_CTCIF(n) (DMA_CHAN_TCIF_BIT << DMA_IFCR_CHAN_SHIFT(n)) +#define DMA_IFCR_CHTIF(n) (DMA_CHAN_HTIF_BIT << DMA_IFCR_CHAN_SHIFT(n)) +#define DMA_IFCR_CTEIF(n) (DMA_CHAN_TEIF_BIT << DMA_IFCR_CHAN_SHIFT(n)) + +/* DMA channel configuration register */ + +#define DMA_CCR_EN (1 << 0) /* Bit 0: Channel enable */ +#define DMA_CCR_TCIE (1 << 1) /* Bit 1: Transfer complete interrupt enable */ +#define DMA_CCR_HTIE (1 << 2) /* Bit 2: Half Transfer interrupt enable */ +#define DMA_CCR_TEIE (1 << 3) /* Bit 3: Transfer error interrupt enable */ +#define DMA_CCR_DIR (1 << 4) /* Bit 4: Data transfer direction */ +#define DMA_CCR_CIRC (1 << 5) /* Bit 5: Circular mode */ +#define DMA_CCR_PINC (1 << 6) /* Bit 6: Peripheral increment mode */ +#define DMA_CCR_MINC (1 << 7) /* Bit 7: Memory increment mode */ +#define DMA_CCR_PSIZE_SHIFT (8) /* Bits 8-9: Peripheral size */ +#define DMA_CCR_PSIZE_MASK (3 << DMA_CCR_PSIZE_SHIFT) +# define DMA_CCR_PSIZE_8BITS (0 << DMA_CCR_PSIZE_SHIFT) /* 00: 8-bits */ +# define DMA_CCR_PSIZE_16BITS (1 << DMA_CCR_PSIZE_SHIFT) /* 01: 16-bits */ +# define DMA_CCR_PSIZE_32BITS (2 << DMA_CCR_PSIZE_SHIFT) /* 10: 32-bits */ +#define DMA_CCR_MSIZE_SHIFT (10) /* Bits 10-11: Memory size */ +#define DMA_CCR_MSIZE_MASK (3 << DMA_CCR_MSIZE_SHIFT) +# define DMA_CCR_MSIZE_8BITS (0 << DMA_CCR_MSIZE_SHIFT) /* 00: 8-bits */ +# define DMA_CCR_MSIZE_16BITS (1 << DMA_CCR_MSIZE_SHIFT) /* 01: 16-bits */ +# define DMA_CCR_MSIZE_32BITS (2 << DMA_CCR_MSIZE_SHIFT) /* 10: 32-bits */ +#define DMA_CCR_PL_SHIFT (12) /* Bits 12-13: Channel Priority level */ +#define DMA_CCR_PL_MASK (3 << DMA_CCR_PL_SHIFT) +# define DMA_CCR_PRILO (0 << DMA_CCR_PL_SHIFT) /* 00: Low */ +# define DMA_CCR_PRIMED (1 << DMA_CCR_PL_SHIFT) /* 01: Medium */ +# define DMA_CCR_PRIHI (2 << DMA_CCR_PL_SHIFT) /* 10: High */ +# define DMA_CCR_PRIVERYHI (3 << DMA_CCR_PL_SHIFT) /* 11: Very high */ +#define DMA_CCR_MEM2MEM (1 << 14) /* Bit 14: Memory to memory mode */ + +#define DMA_CCR_ALLINTS (DMA_CCR_TEIE|DMA_CCR_HTIE|DMA_CCR_TCIE) + +/* DMA channel number of data register */ + +#define DMA_CNDTR_NDT_SHIFT (0) /* Bits 15-0: Number of data to Transfer */ +#define DMA_CNDTR_NDT_MASK (0xffff << DMA_CNDTR_NDT_SHIFT) + +/* DMA Channel mapping. Each DMA channel has a mapping to several possible + * sources/sinks of data. The requests from peripherals assigned to a channel + * are simply OR'ed together before entering the DMA block. This means that only + * one request on a given channel can be enabled at once. + */ + +#define STM32_DMA1_CHAN1 (0) +#define STM32_DMA1_CHAN2 (1) +#define STM32_DMA1_CHAN3 (2) +#define STM32_DMA1_CHAN4 (3) +#define STM32_DMA1_CHAN5 (4) +#define STM32_DMA1_CHAN6 (5) +#define STM32_DMA1_CHAN7 (6) + +#define STM32_DMA2_CHAN1 (7) +#define STM32_DMA2_CHAN2 (8) +#define STM32_DMA2_CHAN3 (1) +#define STM32_DMA2_CHAN4 (10) +#define STM32_DMA2_CHAN5 (11) + +#define DMACHAN_ADC1 STM32_DMA1_CHAN1 +#define DMACHAN_TIM2_CH3 STM32_DMA1_CHAN1 +#define DMACHAN_TIM4_CH1 STM32_DMA1_CHAN1 +#define DMACHAN_SPI1_RX STM32_DMA1_CHAN2 +#define DMACHAN_USART3_TX STM32_DMA1_CHAN2 +#define DMACHAN_TIM1_CH1 STM32_DMA1_CHAN2 +#define DMACHAN_TIM2_UP STM32_DMA1_CHAN2 +#define DMACHAN_TIM3_CH3 STM32_DMA1_CHAN2 +#define DMACHAN_SPI1_TX STM32_DMA1_CHAN3 +#define DMACHAN_USART3_RX STM32_DMA1_CHAN3 +#define DMACHAN_TIM1_CH2 STM32_DMA1_CHAN3 +#define DMACHAN_TIM3_CH4 STM32_DMA1_CHAN3 +#define DMACHAN_TIM3_UP STM32_DMA1_CHAN3 +#define DMACHAN_SPI2_RX STM32_DMA1_CHAN4 +#define DMACHAN_I2S2_RX STM32_DMA1_CHAN4 +#define DMACHAN_USART1_TX STM32_DMA1_CHAN4 +#define DMACHAN_I2C2_TX STM32_DMA1_CHAN4 +#define DMACHAN_TIM1_CH4 STM32_DMA1_CHAN4 +#define DMACHAN_TIM1_TRIG STM32_DMA1_CHAN4 +#define DMACHAN_TIM1_COM STM32_DMA1_CHAN4 +#define DMACHAN_TIM4_CH2 STM32_DMA1_CHAN4 +#define DMACHAN_SPI2_TX STM32_DMA1_CHAN5 +#define DMACHAN_I2S2_TX STM32_DMA1_CHAN5 +#define DMACHAN_USART1_RX STM32_DMA1_CHAN5 +#define DMACHAN_I2C2_RX STM32_DMA1_CHAN5 +#define DMACHAN_TIM1_UP STM32_DMA1_CHAN5 +#define DMACHAN_TIM2_CH1 STM32_DMA1_CHAN5 +#define DMACHAN_TIM4_CH3 STM32_DMA1_CHAN5 +#define DMACHAN_USART2_RX STM32_DMA1_CHAN6 +#define DMACHAN_I2C1_TX STM32_DMA1_CHAN6 +#define DMACHAN_TIM1_CH3 STM32_DMA1_CHAN6 +#define DMACHAN_TIM3_CH1 STM32_DMA1_CHAN6 +#define DMACHAN_TIM3_TRIG STM32_DMA1_CHAN6 +#define DMACHAN_USART2_TX STM32_DMA1_CHAN7 +#define DMACHAN_I2C1_RX STM32_DMA1_CHAN7 +#define DMACHAN_TIM2_CH2 STM32_DMA1_CHAN7 +#define DMACHAN_TIM2_CH4 STM32_DMA1_CHAN7 +#define DMACHAN_TIM4_UP STM32_DMA1_CHAN7 +#define DMACHAN_SPI3_RX STM32_DMA2_CHAN1 +#define DMACHAN_I2S3_RX STM32_DMA2_CHAN1 +#define DMACHAN_TIM5_CH4 STM32_DMA2_CHAN1 +#define DMACHAN_TIM5_TRIG STM32_DMA2_CHAN1 +#define DMACHAN_TIM8_CH3 STM32_DMA2_CHAN1 +#define DMACHAN_TIM8_UP STM32_DMA2_CHAN1 +#define DMACHAN_SPI3_TX STM32_DMA2_CHAN2 +#define DMACHAN_I2S3_TX STM32_DMA2_CHAN2 +#define DMACHAN_TIM5_CH3 STM32_DMA2_CHAN2 +#define DMACHAN_TIM5_UP STM32_DMA2_CHAN2 +#define DMACHAN_TIM5_UP STM32_DMA2_CHAN2 +#define DMACHAN_TIM8_TRIG STM32_DMA2_CHAN2 +#define DMACHAN_TIM8_COM STM32_DMA2_CHAN2 +#define DMACHAN_UART4_RX STM32_DMA2_CHAN3 +#define DMACHAN_TIM6_UP STM32_DMA2_CHAN3 +#define DMACHAN_DAC_CHAN1 STM32_DMA2_CHAN3 +#define DMACHAN_TIM8_CH1 STM32_DMA2_CHAN3 +#define DMACHAN_SDIO STM32_DMA2_CHAN4 +#define DMACHAN_TIM5_CH2 STM32_DMA2_CHAN4 +#define DMACHAN_TIM7_UP STM32_DMA2_CHAN4 +#define DMACHAN_DAC_CHAN2 STM32_DMA2_CHAN4 +#define DMACHAN_ADC3 STM32_DMA2_CHAN5 +#define DMACHAN_UART4_TX STM32_DMA2_CHAN5 +#define DMACHAN_TIM5_CH1 STM32_DMA2_CHAN5 +#define DMACHAN_TIM8_CH2 STM32_DMA2_CHAN5 + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_DMA_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_gpio.h b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_gpio.h new file mode 100644 index 0000000000..e3b0241290 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_gpio.h @@ -0,0 +1,364 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f10xxx_gpio.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_GPIO_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_GPIO_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#define STM32_NGPIO_PORTS ((STM32_NGPIO + 15) >> 4) + +/* Register Offsets *****************************************************************/ + +#define STM32_GPIO_CRL_OFFSET 0x0000 /* Port configuration register low */ +#define STM32_GPIO_CRH_OFFSET 0x0004 /* Port configuration register high */ +#define STM32_GPIO_IDR_OFFSET 0x0008 /* Port input data register */ +#define STM32_GPIO_ODR_OFFSET 0x000c /* Port output data register */ +#define STM32_GPIO_BSRR_OFFSET 0x0010 /* Port bit set/reset register */ +#define STM32_GPIO_BRR_OFFSET 0x0014 /* Port bit reset register */ +#define STM32_GPIO_LCKR_OFFSET 0x0018 /* Port configuration lock register */ + +#define STM32_AFIO_EVCR_OFFSET 0x0000 /* Event control register */ +#define STM32_AFIO_MAPR_OFFSET 0x0004 /* AF remap and debug I/O configuration register */ +#define STM32_AFIO_EXTICR_OFFSET(p) (0x0008 + ((p) & 0x000c)) /* Registers are displaced by 4! */ +#define STM32_AFIO_EXTICR1_OFFSET 0x0008 /* External interrupt configuration register 1 */ +#define STM32_AFIO_EXTICR2_OFFSET 0x000c /* External interrupt configuration register 2 */ +#define STM32_AFIO_EXTICR3_OFFSET 0x0010 /* External interrupt configuration register 3 */ +#define STM32_AFIO_EXTICR4_OFFSET 0x0014 /* External interrupt configuration register 4 */ + +/* Register Addresses ***************************************************************/ + +#if STM32_NGPIO_PORTS > 0 +# define STM32_GPIOA_CRL (STM32_GPIOA_BASE+STM32_GPIO_CRL_OFFSET) +# define STM32_GPIOA_CRH (STM32_GPIOA_BASE+STM32_GPIO_CRH_OFFSET) +# define STM32_GPIOA_IDR (STM32_GPIOA_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOA_ODR (STM32_GPIOA_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOA_BSRR (STM32_GPIOA_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOA_BRR (STM32_GPIOA_BASE+STM32_GPIO_BRR_OFFSET) +# define STM32_GPIOA_LCKR (STM32_GPIOA_BASE+STM32_GPIO_LCKR_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 1 +# define STM32_GPIOB_CRL (STM32_GPIOB_BASE+STM32_GPIO_CRL_OFFSET) +# define STM32_GPIOB_CRH (STM32_GPIOB_BASE+STM32_GPIO_CRH_OFFSET) +# define STM32_GPIOB_IDR (STM32_GPIOB_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOB_ODR (STM32_GPIOB_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOB_BSRR (STM32_GPIOB_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOB_BRR (STM32_GPIOB_BASE+STM32_GPIO_BRR_OFFSET) +# define STM32_GPIOB_LCKR (STM32_GPIOB_BASE+STM32_GPIO_LCKR_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 2 +# define STM32_GPIOC_CRL (STM32_GPIOC_BASE+STM32_GPIO_CRL_OFFSET) +# define STM32_GPIOC_CRH (STM32_GPIOC_BASE+STM32_GPIO_CRH_OFFSET) +# define STM32_GPIOC_IDR (STM32_GPIOC_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOC_ODR (STM32_GPIOC_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOC_BSRR (STM32_GPIOC_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOC_BRR (STM32_GPIOC_BASE+STM32_GPIO_BRR_OFFSET) +# define STM32_GPIOC_LCKR (STM32_GPIOC_BASE+STM32_GPIO_LCKR_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 3 +# define STM32_GPIOD_CRL (STM32_GPIOD_BASE+STM32_GPIO_CRL_OFFSET) +# define STM32_GPIOD_CRH (STM32_GPIOD_BASE+STM32_GPIO_CRH_OFFSET) +# define STM32_GPIOD_IDR (STM32_GPIOD_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOD_ODR (STM32_GPIOD_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOD_BSRR (STM32_GPIOD_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOD_BRR (STM32_GPIOD_BASE+STM32_GPIO_BRR_OFFSET) +# define STM32_GPIOD_LCKR (STM32_GPIOD_BASE+STM32_GPIO_LCKR_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 4 +# define STM32_GPIOE_CRL (STM32_GPIOE_BASE+STM32_GPIO_CRL_OFFSET) +# define STM32_GPIOE_CRH (STM32_GPIOE_BASE+STM32_GPIO_CRH_OFFSET) +# define STM32_GPIOE_IDR (STM32_GPIOE_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOE_ODR (STM32_GPIOE_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOE_BSRR (STM32_GPIOE_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOE_BRR (STM32_GPIOE_BASE+STM32_GPIO_BRR_OFFSET) +# define STM32_GPIOE_LCKR (STM32_GPIOE_BASE+STM32_GPIO_LCKR_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 5 +# define STM32_GPIOF_CRL (STM32_GPIOF_BASE+STM32_GPIO_CRL_OFFSET) +# define STM32_GPIOF_CRH (STM32_GPIOF_BASE+STM32_GPIO_CRH_OFFSET) +# define STM32_GPIOF_IDR (STM32_GPIOF_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOF_ODR (STM32_GPIOF_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOF_BSRR (STM32_GPIOF_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOF_BRR (STM32_GPIOF_BASE+STM32_GPIO_BRR_OFFSET) +# define STM32_GPIOF_LCKR (STM32_GPIOF_BASE+STM32_GPIO_LCKR_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 6 +# define STM32_GPIOG_CRL (STM32_GPIOG_BASE+STM32_GPIO_CRL_OFFSET) +# define STM32_GPIOG_CRH (STM32_GPIOG_BASE+STM32_GPIO_CRH_OFFSET) +# define STM32_GPIOG_IDR (STM32_GPIOG_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOG_ODR (STM32_GPIOG_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOG_BSRR (STM32_GPIOG_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOG_BRR (STM32_GPIOG_BASE+STM32_GPIO_BRR_OFFSET) +# define STM32_GPIOG_LCKR (STM32_GPIOG_BASE+STM32_GPIO_LCKR_OFFSET) +#endif + +#define STM32_AFIO_EVCR (STM32_AFIO_BASE+STM32_AFIO_EVCR_OFFSET) +#define STM32_AFIO_MAPR (STM32_AFIO_BASE+STM32_AFIO_MAPR_OFFSET) +#define STM32_AFIO_EXTICR(p) (STM32_AFIO_BASE+STM32_AFIO_EXTICR_OFFSET(p)) +#define STM32_AFIO_EXTICR1 (STM32_AFIO_BASE+STM32_AFIO_EXTICR1_OFFSET) +#define STM32_AFIO_EXTICR2 (STM32_AFIO_BASE+STM32_AFIO_EXTICR2_OFFSET) +#define STM32_AFIO_EXTICR3 (STM32_AFIO_BASE+STM32_AFIO_EXTICR3_OFFSET) +#define STM32_AFIO_EXTICR4 (STM32_AFIO_BASE+STM32_AFIO_EXTICR4_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +/* Port configuration register low */ + +#define GPIO_CR_MODE_SHIFT(n) ((n) << 2) +#define GPIO_CR_MODE_MASK(n) (3 << GPIO_CR_MODE_SHIFT(n)) +#define GPIO_CR_CNF_SHIFT(n) (2 + ((n) << 2)) +#define GPIO_CR_CNF_MASK(n) (3 << GPIO_CR_CNF_SHIFT(n)) + +#define GPIO_CR_MODECNF_SHIFT(n) ((n) << 2) +#define GPIO_CR_MODECNF_MASK(n) (0x0f << GPIO_CR_MODECNF_SHIFT(n)) + +#define GPIO_CRL_MODE0_SHIFT (0) /* Bits 1:0: Port mode bits */ +#define GPIO_CRL_MODE0_MASK (3 << GPIO_CRL_MODE0_SHIFT) +#define GPIO_CRL_CNF0_SHIFT (2) /* Bits 3:2: Port configuration bits */ +#define GPIO_CRL_CNF0_MASK (3 << GPIO_CRL_CNF0_SHIFT) +#define GPIO_CRL_MODE1_SHIFT (4) /* Bits 5:4: Port mode bits */ +#define GPIO_CRL_MODE1_MASK (3 << GPIO_CRL_MODE1_SHIFT) +#define GPIO_CRL_CNF1_SHIFT (6) /* Bits 7:6: Port configuration bits */ +#define GPIO_CRL_CNF1_MASK (3 << GPIO_CRL_CNF1_SHIFT) +#define GPIO_CRL_MODE2_SHIFT (8) /* Bits 9:8: Port mode bits */ +#define GPIO_CRL_MODE2_MASK (3 << GPIO_CRL_MODE2_SHIFT) +#define GPIO_CRL_CNF2_SHIFT (10) /* Bits 11:10: Port configuration bits */ +#define GPIO_CRL_CNF2_MASK (3 << GPIO_CRL_CNF2_SHIFT) +#define GPIO_CRL_MODE3_SHIFT (12) /* Bits 13:12: Port mode bits */ +#define GPIO_CRL_MODE3_MASK (3 << GPIO_CRL_MODE3_SHIFT) +#define GPIO_CRL_CNF3_SHIFT (14) /* Bits 15:14: Port configuration bits */ +#define GPIO_CRL_CNF3_MASK (3 << GPIO_CRL_CNF3_SHIFT) +#define GPIO_CRL_MODE4_SHIFT (16) /* Bits 17:16: Port mode bits */ +#define GPIO_CRL_MODE4_MASK (3 << GPIO_CRL_MODE4_SHIFT) +#define GPIO_CRL_CNF4_SHIFT (18) /* Bits 19:18: Port configuration bits */ +#define GPIO_CRL_CNF4_MASK (3 << GPIO_CRL_CNF4_SHIFT) +#define GPIO_CRL_MODE5_SHIFT (20) /* Bits 21:20: Port mode bits */ +#define GPIO_CRL_MODE5_MASK (3 << GPIO_CRL_MODE5_SHIFT) +#define GPIO_CRL_CNF5_SHIFT (22) /* Bits 23:22: Port configuration bits */ +#define GPIO_CRL_CNF5_MASK (3 << GPIO_CRL_CNF5_SHIFT) +#define GPIO_CRL_MODE6_SHIFT (24) /* Bits 25:24: Port mode bits */ +#define GPIO_CRL_MODE6_MASK (3 << GPIO_CRL_MODE6_SHIFT) +#define GPIO_CRL_CNF6_SHIFT (26) /* Bits 27:26: Port configuration bits */ +#define GPIO_CRL_CNF6_MASK (3 << GPIO_CRL_CNF6_SHIFT) +#define GPIO_CRL_MODE7_SHIFT (28) /* Bits 29:28: Port mode bits */ +#define GPIO_CRL_MODE7_MASK (3 << GPIO_CRL_MODE7_SHIFT) +#define GPIO_CRL_CNF7_SHIFT (30) /* Bits 31:30: Port configuration bits */ +#define GPIO_CRL_CNF7_MASK (3 << GPIO_CRL_CNF7_SHIFT) + +#define GPIO_CR_CNF_INANALOG (0) /* 00: Analog input mode */ +#define GPIO_CR_CNF_INFLOAT (1) /* 01: Floating input (reset state) */ +#define GPIO_CR_CNF_INPULLUD (2) /* 10: Input with pull-up / pull-down */ + +#define GPIO_CR_CNF_OUTPP (0) /* 00: General purpose output push-pull */ +#define GPIO_CR_CNF_OUTOD (1) /* 01: General purpose output Open-drain */ +#define GPIO_CR_CNF_ALTPP (2) /* 10: Alternate function output Push-pull */ +#define GPIO_CR_CNF_ALTOD (3) /* 11: Alternate function output Open-drain */ + +#define GPIO_CR_MODE_INRST (0) /* 00: Input mode (reset state) */ +#define GPIO_CR_MODE_OUT10MHz (1) /* 01: Output mode, max speed 10 MHz */ +#define GPIO_CR_MODE_OUT2MHz (2) /* 10: Output mode, max speed 2 MHz */ +#define GPIO_CR_MODE_OUT50MHz (3) /* 11: Output mode, max speed 50 MHz */ + +/* Port configuration register high */ + +#define GPIO_CRH_MODE8_SHIFT (0) /* Bits 1:0: Port mode bits */ +#define GPIO_CRH_MODE8_MASK (3 << GPIO_CRH_MODE8_SHIFT) +#define GPIO_CRH_CNF8_SHIFT (2) /* Bits 3:2: Port configuration bits */ +#define GPIO_CRH_CNF8_MASK (3 << GPIO_CRH_CNF8_SHIFT) +#define GPIO_CRH_MODE9_SHIFT (4) /* Bits 5:4: Port mode bits */ +#define GPIO_CRH_MODE9_MASK (3 << GPIO_CRH_MODE9_SHIFT) +#define GPIO_CRH_CNF9_SHIFT (6) /* Bits 7:6: Port configuration bits */ +#define GPIO_CRH_CNF9_MASK (3 << GPIO_CRH_CNF9_SHIFT) +#define GPIO_CRH_MODE10_SHIFT (8) /* Bits 9:8: Port mode bits */ +#define GPIO_CRH_MODE10_MASK (3 << GPIO_CRH_MODE10_SHIFT) +#define GPIO_CRH_CNF10_SHIFT (10) /* Bits 11:10: Port configuration bits */ +#define GPIO_CRH_CNF10_MASK (3 << GPIO_CRH_CNF10_SHIFT) +#define GPIO_CRH_MODE11_SHIFT (12) /* Bits 13:12: Port mode bits */ +#define GPIO_CRH_MODE11_MASK (3 << GPIO_CRH_MODE11_SHIFT) +#define GPIO_CRH_CNF11_SHIFT (14) /* Bits 15:14: Port configuration bits */ +#define GPIO_CRH_CNF11_MASK (3 << GPIO_CRH_CNF11_SHIFT) +#define GPIO_CRH_MODE12_SHIFT (16) /* Bits 17:16: Port mode bits */ +#define GPIO_CRH_MODE12_MASK (3 << GPIO_CRH_MODE12_SHIFT) +#define GPIO_CRH_CNF12_SHIFT (18) /* Bits 19:18: Port configuration bits */ +#define GPIO_CRH_CNF12_MASK (3 << GPIO_CRH_CNF12_SHIFT) +#define GPIO_CRH_MODE13_SHIFT (20) /* Bits 21:20: Port mode bits */ +#define GPIO_CRH_MODE13_MASK (3 << GPIO_CRH_MODE13_SHIFT) +#define GPIO_CRH_CNF13_SHIFT (22) /* Bits 23:22: Port configuration bits */ +#define GPIO_CRH_CNF13_MASK (3 << GPIO_CRH_CNF13_SHIFT) +#define GPIO_CRH_MODE14_SHIFT (24) /* Bits 25:24: Port mode bits */ +#define GPIO_CRH_MODE14_MASK (3 << GPIO_CRH_MODE14_SHIFT) +#define GPIO_CRH_CNF14_SHIFT (26) /* Bits 27:26: Port configuration bits */ +#define GPIO_CRH_CNF14_MASK (3 << GPIO_CRH_CNF14_SHIFT) +#define GPIO_CRH_MODE15_SHIFT (28) /* Bits 29:28: Port mode bits */ +#define GPIO_CRH_MODE15_MASK (3 << GPIO_CRH_MODE15_SHIFT) +#define GPIO_CRH_CNF15_SHIFT (30) /* Bits 31:30: Port configuration bits */ +#define GPIO_CRL_CNF15_MASK (3 << GPIO_CRL_CNF15_SHIFT) + +/* Port input/ouput data register */ + +#define GPIO_IDR(n) (1 << (n)) +#define GPIO_ODR(n) (1 << (n)) + +/* Port bit set/reset register */ + +#define GPIO_BSRR_RESET(n) (1 << ((n)+16)) +#define GPIO_BSRR_SET(n) (1 << (n)) +#define GPIO_BRR(n) (1 << (n)) + +/* Port configuration lock register */ + +#define GPIO_LCKR_LCKK (1 << 16) /* Bit 16: Lock key */ +#define GPIO_LCKR_LCK(n) (1 << (n)) + +/* Event control register */ + +#define AFIO_EVCR_PIN_SHIFT (0) /* Bits 3-0: Pin selection */ +#define AFIO_EVCR_PIN_MASK (0x0f << AFIO_EVCR_PIN_SHIFT) +#define AFIO_EVCR_PORT_SHIFT (4) /* Bits 6-4: Port selection */ +#define AFIO_EVCR_PORT_MASK (7 << AFIO_EVCR_PORT_SHIFT) +# define AFIO_EVCR_PORTA (0 << AFIO_EVCR_PORT_SHIFT) /* 000: PA selected */ +# define AFIO_EVCR_PORTB (1 << AFIO_EVCR_PORT_SHIFT) /* 001: PB selected */ +# define AFIO_EVCR_PORTC (2 << AFIO_EVCR_PORT_SHIFT) /* 010: PC selected */ +# define AFIO_EVCR_PORTD (3 << AFIO_EVCR_PORT_SHIFT) /* 011: PD selected */ +# define AFIO_EVCR_PORTE (4 << AFIO_EVCR_PORT_SHIFT) /* 100: PE selected */ +#define AFIO_EVCR_EVOE (1 << 7) /* Bit 7: Event Output Enable */ + +/* AF remap and debug I/O configuration register */ + +#define AFIO_MAPR_SWJ_CFG_SHIFT (24) /* Bits 26-24: Serial Wire JTAG configuration*/ +#define AFIO_MAPR_SWJ_CFG_MASK (7 << AFIO_MAPR_SWJ_CFG_SHIFT) +# define AFIO_MAPR_SWJRST (0 << AFIO_MAPR_SWJ_CFG_SHIFT) /* 000: Full SWJ (JTAG-DP + SW-DP): Reset State */ +# define AFIO_MAPR_SWJ (1 << AFIO_MAPR_SWJ_CFG_SHIFT) /* 001: Full SWJ (JTAG-DP + SW-DP) but without JNTRST */ +# define AFIO_MAPR_SWDP (2 << AFIO_MAPR_SWJ_CFG_SHIFT) /* 010: JTAG-DP Disabled and SW-DP Enabled */ +# define AFIO_MAPR_DISAB (4 << AFIO_MAPR_SWJ_CFG_SHIFT) /* 100: JTAG-DP Disabled and SW-DP Disabled */ +#define AFIO_MAPR_PD01_REMAP (1 << 15) /* Bit 15 : Port D0/Port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_MAPR_CAN_REMAP_SHIFT (13) /* Bits 14-13: CAN Alternate function remapping */ +#define AFIO_MAPR_CAN_REMAP_MASK (3 << AFIO_MAPR_CAN_REMAP_SHIFT) +# define AFIO_MAPR_PA1112 (0 << AFIO_MAPR_CAN_REMAP_SHIFT) /* 00: CANRX mapped to PA11, CANTX mapped to PA12 */ +# define AFIO_MAPR_PB89 (2 << AFIO_MAPR_CAN_REMAP_SHIFT) /* 10: CANRX mapped to PB8, CANTX mapped to PB9 */ +# define AFIO_MAPR_PD01 (3 << AFIO_MAPR_CAN_REMAP_SHIFT) /* 11: CANRX mapped to PD0, CANTX mapped to PD1 */ +#define AFIO_MAPR_TIM4_REMAP (1 << 12) /* Bit 12: TIM4 remapping */ +#define AFIO_MAPR_TIM3_REMAP_SHIFT (10) /* Bits 11-10: TIM3 remapping */ +#define AFIO_MAPR_TIM3_REMAP_MASK (3 << AFIO_MAPR_TIM3_REMAP_SHIFT) +# define AFIO_MAPR_TIM3_NOREMAP (0 << AFIO_MAPR_TIM3_REMAP_SHIFT) /* 00: No remap (CH1/PA6, CH2/PA7, CH3/PB0, CH4/PB1) */ +# define AFIO_MAPR_TIM3_PARTREMAP (2 << AFIO_MAPR_TIM3_REMAP_SHIFT) /* 10: Partial remap (CH1/PB4, CH2/PB5, CH3/PB0, CH4/PB1) */ +# define AFIO_MAPR_TIM3_FULLREMAP (3 << AFIO_MAPR_TIM3_REMAP_SHIFT) /* 11: Full remap (CH1/PC6, CH2/PC7, CH3/PC8, CH4/PC9) */ +#define AFIO_MAPR_TIM2_REMAP_SHIFT (8) /* Bits 9-8: TIM2 remapping */ +#define AFIO_MAPR_TIM2_REMAP_MASK (3 << AFIO_MAPR_TIM2_REMAP_SHIFT) +# define AFIO_MAPR_TIM2_NOREMAP (0 << AFIO_MAPR_TIM2_REMAP_SHIFT) /* 00: No remap (CH1/ETR/PA0, CH2/PA1, CH3/PA2, CH4/PA3) */ +# define AFIO_MAPR_TIM2_PARTREMAP1 (1 << AFIO_MAPR_TIM2_REMAP_SHIFT) /* 01: Partial remap (CH1/ETR/PA15, CH2/PB3, CH3/PA2, CH4/PA3) */ +# define AFIO_MAPR_TIM2_PARTREMAP2 (2 << AFIO_MAPR_TIM2_REMAP_SHIFT) /* 10: Partial remap (CH1/ETR/PA0, CH2/PA1, CH3/PB10, CH4/PB11) */ +# define AFIO_MAPR_TIM2_FULLREMAP (3 << AFIO_MAPR_TIM2_REMAP_SHIFT) /* 11: Full remap (CH1/ETR/PA15, CH2/PB3, CH3/PB10, CH4/PB11) */ +#define AFIO_MAPR_TIM1_REMAP_SHIFT (6) /* Bits 7-6: TIM1 remapping */ +#define AFIO_MAPR_TIM1_REMAP_MASK (3 << AFIO_MAPR_TIM1_REMAP_SHIFT) +# define AFIO_MAPR_TIM1_NOREMAP (0 << AFIO_MAPR_TIM1_REMAP_SHIFT) /* 00: No remap (ETR/PA12, CH1/PA8, CH2/PA9, CH3/PA10, CH4/PA11, BKIN/PB12, CH1N/PB13, CH2N/PB14, CH3N/PB15) */ +# define AFIO_MAPR_TIM1_PARTREMAP (1 << AFIO_MAPR_TIM1_REMAP_SHIFT) /* 01: Partial remap (ETR/PA12, CH1/PA8, CH2/PA9, CH3/PA10, CH4/PA11, BKIN/PA6, CH1N/PA7, CH2N/PB0, CH3N/PB1) */ +# define AFIO_MAPR_TIM1_FULLREMAP (3 << AFIO_MAPR_TIM1_REMAP_SHIFT) /* 11: Full remap (ETR/PE7, CH1/PE9, CH2/PE11, CH3/PE13, CH4/PE14, BKIN/PE15, CH1N/PE8, CH2N/PE10, CH3N/PE12) */ +#define AFIO_MAPR_USART3_REMAP_SHIFT (6) /* Bits 5-4: USART3 remapping */ +#define AFIO_MAPR_USART3_REMAP_MASK (3 << AFIO_MAPR_USART3_REMAP_SHIFT) +# define AFIO_MAPR_USART3_NOREMAP (0 << AFIO_MAPR_USART3_REMAP_SHIFT) /* 00: No remap (TX/PB10, RX/PB11, CK/PB12, CTS/PB13, RTS/PB14) */ +# define AFIO_MAPR_USART3_PARTREMAP (1 << AFIO_MAPR_USART3_REMAP_SHIFT) /* 01: Partial remap (TX/PC10, RX/PC11, CK/PC12, CTS/PB13, RTS/PB14) */ +# define AFIO_MAPR_USART3_FULLREMAP (3 << AFIO_MAPR_USART3_REMAP_SHIFT) /* 11: Full remap (TX/PD8, RX/PD9, CK/PD10, CTS/PD11, RTS/PD12) */ +#define AFIO_MAPR_USART2_REMAP (1 << 3) /* Bit 3: USART2 remapping */ +#define AFIO_MAPR_USART1_REMAP (1 << 2) /* Bit 2: USART1 remapping */ +#define AFIO_MAPR_I2C1_REMAP (1 << 1) /* Bit 1: I2C1 remapping */ +#define AFIO_MAPR_SPI1_REMAP (1 << 0) /* Bit 0: SPI1 remapping */ + +/* External interrupt configuration register 1 */ + +#define AFIO_EXTICR_PORT_MASK (0x0f) +#define AFIO_EXTICR_EXTI_SHIFT(g) (((g) & 3) << 2) +#define AFIO_EXTICR_EXTI_MASK(g) (AFIO_EXTICR_PORT_MASK << (AFIO_EXTICR_EXTI_SHIFT(g))) + +#define AFIO_EXTICR1_EXTI0_SHIFT (0) /* Bits 3-0: EXTI 0 configuration */ +#define AFIO_EXTICR1_EXTI0_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR1_EXTI0_SHIFT) +#define AFIO_EXTICR1_EXTI1_SHIFT (4) /* Bits 7-4: EXTI 1 configuration */ +#define AFIO_EXTICR1_EXTI1_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR1_EXTI1_SHIFT) +#define AFIO_EXTICR1_EXTI2_SHIFT (8) /* Bits 11-8: EXTI 2 configuration */ +#define AFIO_EXTICR1_EXTI2_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR1_EXTI2_SHIFT) +#define AFIO_EXTICR1_EXTI3_SHIFT (12) /* Bits 15-12: EXTI 3 configuration */ +#define AFIO_EXTICR1_EXTI3_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR1_EXTI3_SHIFT) + +#define AFIO_EXTICR_PORTA (0) /* 0000: PA[x] pin */ +#define AFIO_EXTICR_PORTB (1) /* 0001: PB[x] pin */ +#define AFIO_EXTICR_PORTC (2) /* 0010: PC[x] pin */ +#define AFIO_EXTICR_PORTD (3) /* 0011: PD[x] pin */ +#define AFIO_EXTICR_PORTE (4) /* 0100: PE[x] pin */ +#define AFIO_EXTICR_PORTF (5) /* 0101: PF[x] pin */ +#define AFIO_EXTICR_PORTG (6) /* 0110: PG[x] pin */ + +/* External interrupt configuration register 2 */ + +#define AFIO_EXTICR2_EXTI4_SHIFT (0) /* Bits 3-0: EXTI 4 configuration */ +#define AFIO_EXTICR2_EXTI4_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR2_EXTI4_SHIFT) +#define AFIO_EXTICR2_EXTI5_SHIFT (4) /* Bits 7-4: EXTI 5 configuration */ +#define AFIO_EXTICR2_EXTI5_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR2_EXTI5_SHIFT) +#define AFIO_EXTICR2_EXTI6_SHIFT (8) /* Bits 11-8: EXTI 6 configuration */ +#define AFIO_EXTICR2_EXTI6_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR2_EXTI6_SHIFT) +#define AFIO_EXTICR2_EXTI7_SHIFT (12) /* Bits 15-12: EXTI 7 configuration */ +#define AFIO_EXTICR2_EXTI7_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR2_EXTI7_SHIFT) + +/* External interrupt configuration register 3 */ + +#define AFIO_EXTICR3_EXTI8_SHIFT (0) /* Bits 3-0: EXTI 8 configuration */ +#define AFIO_EXTICR3_EXTI8_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR3_EXTI8_SHIFT) +#define AFIO_EXTICR3_EXTI9_SHIFT (4) /* Bits 7-4: EXTI 9 configuration */ +#define AFIO_EXTICR3_EXTI9_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR3_EXTI9_SHIFT) +#define AFIO_EXTICR3_EXTI10_SHIFT (8) /* Bits 11-8: EXTI 10 configuration */ +#define AFIO_EXTICR3_EXTI10_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR3_EXTI10_SHIFT) +#define AFIO_EXTICR3_EXTI11_SHIFT (12) /* Bits 15-12: EXTI 11 configuration */ +#define AFIO_EXTICR3_EXTI11_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR3_EXTI11_SHIFT) + +/* External interrupt configuration register 4 */ + +#define AFIO_EXTICR4_EXTI12_SHIFT (0) /* Bits 3-0: EXTI 12 configuration */ +#define AFIO_EXTICR4_EXTI12_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR4_EXTI12_SHIFT) +#define AFIO_EXTICR4_EXTI13_SHIFT (4) /* Bits 7-4: EXTI 13 configuration */ +#define AFIO_EXTICR4_EXTI13_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR4_EXTI13_SHIFT) +#define AFIO_EXTICR4_EXTI14_SHIFT (8) /* Bits 11-8: EXTI 14 configuration */ +#define AFIO_EXTICR4_EXTI14_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR4_EXTI14_SHIFT) +#define AFIO_EXTICR4_EXTI15_SHIFT (12) /* Bits 15-12: EXTI 15 configuration */ +#define AFIO_EXTICR4_EXTI15_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR4_EXTI15_SHIFT) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_GPIO_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_memorymap.h b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_memorymap.h new file mode 100644 index 0000000000..80b38a89fe --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_memorymap.h @@ -0,0 +1,136 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f10xxx_memorymap.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_MEMORYMAP_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_MEMORYMAP_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* FLASH and SRAM *******************************************************************/ + +#define STM32_FLASH_BASE 0x08000000 /* 0x08000000 - Up to 512Kb */ +#define STM32_SRAM_BASE 0x20000000 /* 0x20000000 - 64Kb SRAM */ +#define STM32_SRAMBB_BASE 0x22000000 +#define STM32_PERIPH_BASE 0x40000000 + +/* Register Base Address ************************************************************/ + +/* APB1 bus */ + +#define STM32_TIM2_BASE 0x40000000 /* 0x40000000 - 0x400003ff: TIM2 timer */ +#define STM32_TIM3_BASE 0x40000400 /* 0x40000400 - 0x400007ff: TIM3 timer */ +#define STM32_TIM4_BASE 0x40000800 /* 0x40000800 - 0x40000bff: TIM4 timer */ +#define STM32_TIM5_BASE 0x40000c00 /* 0x40000c00 - 0x40000fff: TIM5 timer */ +#define STM32_TIM6_BASE 0x40001000 /* 0x40001000 - 0x400013ff: TIM6 timer */ +#define STM32_TIM7_BASE 0x40001400 /* 0x40001400 - 0x400007ff: TIM7 timer */ + /* 0x40001800 - 0x40000fff: Reserved */ +#define STM32_RTC_BASE 0x40002800 /* 0x40002800 - 0x40002bff: RTC */ +#define STM32_WWDG_BASE 0x40002c00 /* 0x40002C00 - 0x40002fff: Window watchdog (WWDG) */ +#define STM32_IWDG_BASE 0x40003000 /* 0x40003000 - 0x400033ff: Independent watchdog (IWDG) */ + /* 0x40003400 - 0x400037ff: Reserved */ +#define STM32_SPI2_BASE 0x40003800 /* 0x40003800 - 0x40003bff: SPI2/I2S2 */ +#define STM32_I2S2_BASE 0x40003800 +#define STM32_SPI3_BASE 0x40003c00 /* 0x40003c00 - 0x40003fff: SPI3/I2S3 */ +#define STM32_I2S3_BASE 0x40003c00 + /* 0x40004000 - 0x400043ff: Reserved */ +#define STM32_USART2_BASE 0x40004400 /* 0x40004400 - 0x400047ff: USART2 */ +#define STM32_USART3_BASE 0x40004800 /* 0x40004800 - 0x40004bff: USART3 */ +#define STM32_UART4_BASE 0x40004c00 /* 0x40004c00 - 0x40004fff: UART4 */ +#define STM32_UART5_BASE 0x40005000 /* 0x40005000 - 0x400053ff: UART5 */ +#define STM32_I2C1_BASE 0x40005400 /* 0x40005400 - 0x400057ff: I2C1 */ +#define STM32_I2C2_BASE 0x40005800 /* 0x40005800 - 0x40005Bff: I2C2 */ +#define STM32_USB_BASE 0x40005c00 /* 0x40005c00 - 0x40005fff: USB device FS registers */ +#define STM32_USBCANRAM_BASE 0x40006000 /* 0x40006000 - 0x400063ff: Shared USB/CAN SRAM 512 bytes */ +#define STM32_CAN1_BASE 0x40006400 /* 0x40006400 - 0x400067ff: bxCAN1 */ +#define STM32_CAN2_BASE 0x40006800 /* 0x40006800 - 0x40006bff: bxCAN2 */ +#define STM32_BKP_BASE 0x40006c00 /* 0x40006c00 - 0x40006fff: Backup registers (BKP) */ +#define STM32_PWR_BASE 0x40007000 /* 0x40007000 - 0x400073ff: Power control PWR */ +#define STM32_DAC_BASE 0x40007400 /* 0x40007400 - 0x400077ff: DAC */ + /* 0x40007800 - 0x4000ffff: Reserved */ + +/* APB2 bus */ + +#define STM32_AFIO_BASE 0x40010000 /* 0x40010000 - 0x400103ff: AFIO */ +#define STM32_EXTI_BASE 0x40010400 /* 0x40010400 - 0x400107ff: EXTI */ +#define STM32_GPIOA_BASE 0x40010800 /* 0x40010800 - 0x40010bff: GPIO Port A */ +#define STM32_GPIOB_BASE 0X40010c00 /* 0X40010c00 - 0x40010fff: GPIO Port B */ +#define STM32_GPIOC_BASE 0x40011000 /* 0x40011000 - 0x400113ff: GPIO Port C */ +#define STM32_GPIOD_BASE 0x40011400 /* 0x40011400 - 0x400117ff: GPIO Port D */ +#define STM32_GPIOE_BASE 0x40011800 /* 0x40011800 - 0x40011bff: GPIO Port E */ +#define STM32_GPIOF_BASE 0x40011c00 /* 0x4001c000 - 0x400111ff: GPIO Port F */ +#define STM32_GPIOG_BASE 0x40012000 /* 0x40012000 - 0x400123ff: GPIO Port G */ +#define STM32_ADC1_BASE 0x40012400 /* 0x40012400 - 0x400127ff: ADC1 */ +#define STM32_ADC2_BASE 0x40012800 /* 0x40012800 - 0x40012bff: ADC2 */ +#define STM32_TIM1_BASE 0x40012c00 /* 0x40012c00 - 0x40012fff: TIM1 timer */ +#define STM32_SPI1_BASE 0x40013000 /* 0x40013000 - 0x400133ff: SPI1 */ +#define STM32_TIM8_BASE 0x40013400 /* 0x40013400 - 0x400137ff: TIM8 timer */ +#define STM32_USART1_BASE 0x40013800 /* 0x40013800 - 0x40013bff: USART1 */ +#define STM32_ADC3_BASE 0x40012800 /* 0x40012800 - 0x40013fff: ADC3 */ + /* 0x40014000 - 0x40017fff: Reserved */ +/* AHB bus */ + +#define STM32_SDIO_BASE 0x40018000 /* 0x40018000 - 0x400183ff: SDIO */ + /* 0x40018400 - 0x40017fff: Reserved */ +#define STM32_DMA1_BASE 0x40020000 /* 0x40020000 - 0x400203ff: DMA1 */ +#define STM32_DMA2_BASE 0x40020400 /* 0x40020000 - 0x400207ff: DMA2 */ + /* 0x40020800 - 0x40020fff: Reserved */ +#define STM32_RCC_BASE 0x40021000 /* 0x40021000 - 0x400213ff: Reset and Clock control RCC */ + /* 0x40021400 - 0x40021fff: Reserved */ +#define STM32_OTGFS_BASE 0x50000000 /* 0x50000000 - 0x500003ff: USB OTG FS */ +#define STM32_FLASHIF_BASE 0x40022000 /* 0x40022000 - 0x400223ff: Flash memory interface */ +#define STM32_CRC_BASE 0x40028000 /* 0x40023000 - 0x400233ff: CRC */ + /* 0x40023400 - 0x40027fff: Reserved */ +#define STM32_ETHERNET_BASE 0x40028000 /* 0x40028000 - 0x40029fff: Ethernet */ + /* 0x40030000 - 0x4fffffff: Reserved */ + +/* Peripheral BB base */ + +#define STM32_PERIPHBB_BASE 0x42000000 + +/* Flexible SRAM controller (FSMC) */ + +#define STM32_FSMC_BASE 0xa0000000 + +/* Other registers -- see armv7-m/nvic.h for standard Cortex-M3 registers in this + * address range + */ + +#define STM32_SCS_BASE 0xe000e000 +#define STM32_DEBUGMCU_BASE 0xe0042000 + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_MEMORYMAP_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rcc.h b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rcc.h new file mode 100644 index 0000000000..31544c99f3 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rcc.h @@ -0,0 +1,328 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f10xx_rcc.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_RCC_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_RCC_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +#define STM32_RCC_CR_OFFSET 0x0000 /* Clock control register */ +#define STM32_RCC_CFGR_OFFSET 0x0004 /* Clock configuration register */ +#define STM32_RCC_CIR_OFFSET 0x0008 /* Clock interrupt register */ +#define STM32_RCC_APB2RSTR_OFFSET 0x000c /* APB2 Peripheral reset register */ +#define STM32_RCC_APB1RSTR_OFFSET 0x0010 /* APB1 Peripheral reset register */ +#define STM32_RCC_AHBENR_OFFSET 0x0014 /* AHB Peripheral Clock enable register */ +#define STM32_RCC_APB2ENR_OFFSET 0x0018 /* APB2 Peripheral Clock enable register */ +#define STM32_RCC_APB1ENR_OFFSET 0x001c /* APB1 Peripheral Clock enable register */ +#define STM32_RCC_BDCR_OFFSET 0x0020 /* Backup domain control register */ +#define STM32_RCC_CSR_OFFSET 0x0024 /* Control/status register */ +#ifdef CONFIG_STM32_VALUELINE +# define STM32_RCC_CFGR2_OFFSET 0x002c /* Clock configuration register 2 */ +#endif + +/* Register Addresses ***************************************************************/ + +#define STM32_RCC_CR (STM32_RCC_BASE+STM32_RCC_CR_OFFSET) +#define STM32_RCC_CFGR (STM32_RCC_BASE+STM32_RCC_CFGR_OFFSET) +#define STM32_RCC_CIR (STM32_RCC_BASE+STM32_RCC_CIR_OFFSET) +#define STM32_RCC_APB2RSTR (STM32_RCC_BASE+STM32_RCC_APB2RSTR_OFFSET) +#define STM32_RCC_APB1RSTR (STM32_RCC_BASE+STM32_RCC_APB1RSTR_OFFSET) +#define STM32_RCC_AHBENR (STM32_RCC_BASE+STM32_RCC_AHBENR_OFFSET) +#define STM32_RCC_APB2ENR (STM32_RCC_BASE+STM32_RCC_APB2ENR_OFFSET) +#define STM32_RCC_APB1ENR (STM32_RCC_BASE+STM32_RCC_APB1ENR_OFFSET) +#define STM32_RCC_BDCR (STM32_RCC_BASE+STM32_RCC_BDCR_OFFSET) +#define STM32_RCC_CSR (STM32_RCC_BASE+STM32_RCC_CSR_OFFSET) +#ifdef CONFIG_STM32_VALUELINE +# define STM32_RCC_CFGR2 (STM32_RCC_BASE+STM32_RCC_CFGR2_OFFSET) +#endif + +/* Register Bitfield Definitions ****************************************************/ + +/* Clock control register */ + +#define RCC_CR_HSION (1 << 0) /* Bit 0: Internal High Speed clock enable */ +#define RCC_CR_HSIRDY (1 << 1) /* Bit 1: Internal High Speed clock ready flag */ +#define RCC_CR_HSITRIM_SHIFT (3) /* Bits 7-3: Internal High Speed clock trimming */ +#define RCC_CR_HSITRIM_MASK (0x1f << RCC_CR_HSITRIM_SHIFT) +#define RCC_CR_HSICAL_SHIFT (8) /* Bits 15-8: Internal High Speed clock Calibration */ +#define RCC_CR_HSICAL_MASK (0xff << RCC_CR_HSICAL_SHIFT) +#define RCC_CR_HSEON (1 << 16) /* Bit 16: External High Speed clock enable */ +#define RCC_CR_HSERDY (1 << 17) /* Bit 17: External High Speed clock ready flag */ +#define RCC_CR_HSEBYP (1 << 18) /* Bit 18: External High Speed clock Bypass */ +#define RCC_CR_CSSON (1 << 19) /* Bit 19: Clock Security System enable */ +#define RCC_CR_PLLON (1 << 24) /* Bit 24: PLL enable */ +#define RCC_CR_PLLRDY (1 << 25) /* Bit 25: PLL clock ready flag */ + +/* Clock configuration register */ + +#define RCC_CFGR_SW_SHIFT (0) /* Bits 1-0: System clock Switch */ +#define RCC_CFGR_SW_MASK (3 << RCC_CFGR_SW_SHIFT) +# define RCC_CFGR_SW_HSI (0 << RCC_CFGR_SW_SHIFT) /* 00: HSI selected as system clock */ +# define RCC_CFGR_SW_HSE (1 << RCC_CFGR_SW_SHIFT) /* 01: HSE selected as system clock */ +# define RCC_CFGR_SW_PLL (2 << RCC_CFGR_SW_SHIFT) /* 10: PLL selected as system clock */ +#define RCC_CFGR_SWS_SHIFT (2) /* Bits 3-2: System Clock Switch Status */ +#define RCC_CFGR_SWS_MASK (3 << RCC_CFGR_SWS_SHIFT) +# define RCC_CFGR_SWS_HSI (0 << RCC_CFGR_SWS_SHIFT) /* 00: HSI oscillator used as system clock */ +# define RCC_CFGR_SWS_HSE (1 << RCC_CFGR_SWS_SHIFT) /* 01: HSE oscillator used as system clock */ +# define RCC_CFGR_SWS_PLL (2 << RCC_CFGR_SWS_SHIFT) /* 10: PLL used as system clock */ +#define RCC_CFGR_HPRE_SHIFT (4) /* Bits 7-4: AHB prescaler */ +#define RCC_CFGR_HPRE_MASK (0x0f << RCC_CFGR_HPRE_SHIFT) +# define RCC_CFGR_HPRE_SYSCLK (0 << RCC_CFGR_HPRE_SHIFT) /* 0xxx: SYSCLK not divided */ +# define RCC_CFGR_HPRE_SYSCLKd2 (8 << RCC_CFGR_HPRE_SHIFT) /* 1000: SYSCLK divided by 2 */ +# define RCC_CFGR_HPRE_SYSCLKd4 (9 << RCC_CFGR_HPRE_SHIFT) /* 1001: SYSCLK divided by 4 */ +# define RCC_CFGR_HPRE_SYSCLKd8 (10 << RCC_CFGR_HPRE_SHIFT) /* 1010: SYSCLK divided by 8 */ +# define RCC_CFGR_HPRE_SYSCLKd16 (11 << RCC_CFGR_HPRE_SHIFT) /* 1011: SYSCLK divided by 16 */ +# define RCC_CFGR_HPRE_SYSCLKd64 (12 << RCC_CFGR_HPRE_SHIFT) /* 1100: SYSCLK divided by 64 */ +# define RCC_CFGR_HPRE_SYSCLKd128 (13 << RCC_CFGR_HPRE_SHIFT) /* 1101: SYSCLK divided by 128 */ +# define RCC_CFGR_HPRE_SYSCLKd256 (14 << RCC_CFGR_HPRE_SHIFT) /* 1110: SYSCLK divided by 256 */ +# define RCC_CFGR_HPRE_SYSCLKd512 (15 << RCC_CFGR_HPRE_SHIFT) /* 1111: SYSCLK divided by 512 */ +#define RCC_CFGR_PPRE1_SHIFT (8) /* Bits 10-8: APB Low speed prescaler (APB1) */ +#define RCC_CFGR_PPRE1_MASK (7 << RCC_CFGR_PPRE1_SHIFT) +# define RCC_CFGR_PPRE1_HCLK (0 << RCC_CFGR_PPRE1_SHIFT) /* 0xx: HCLK not divided */ +# define RCC_CFGR_PPRE1_HCLKd2 (4 << RCC_CFGR_PPRE1_SHIFT) /* 100: HCLK divided by 2 */ +# define RCC_CFGR_PPRE1_HCLKd4 (5 << RCC_CFGR_PPRE1_SHIFT) /* 101: HCLK divided by 4 */ +# define RCC_CFGR_PPRE1_HCLKd8 (6 << RCC_CFGR_PPRE1_SHIFT) /* 110: HCLK divided by 8 */ +# define RCC_CFGR_PPRE1_HCLKd16 (7 << RCC_CFGR_PPRE1_SHIFT) /* 111: HCLK divided by 16 */ +#define RCC_CFGR_PPRE2_SHIFT (11) /* Bits 13-11: APB High speed prescaler (APB2) */ +#define RCC_CFGR_PPRE2_MASK (7 << RCC_CFGR_PPRE2_SHIFT) +# define RCC_CFGR_PPRE2_HCLK (0 << RCC_CFGR_PPRE2_SHIFT) /* 0xx: HCLK not divided */ +# define RCC_CFGR_PPRE2_HCLKd2 (4 << RCC_CFGR_PPRE2_SHIFT) /* 100: HCLK divided by 2 */ +# define RCC_CFGR_PPRE2_HCLKd4 (5 << RCC_CFGR_PPRE2_SHIFT) /* 101: HCLK divided by 4 */ +# define RCC_CFGR_PPRE2_HCLKd8 (6 << RCC_CFGR_PPRE2_SHIFT) /* 110: HCLK divided by 8 */ +# define RCC_CFGR_PPRE2_HCLKd16 (7 << RCC_CFGR_PPRE2_SHIFT) /* 111: HCLK divided by 16 */ +#define RCC_CFGR_ADCPRE_SHIFT (14) /* Bits 15-14: ADC prescaler */ +#define RCC_CFGR_ADCPRE_MASK (3 << RCC_CFGR_ADCPRE_SHIFT) +# define RCC_CFGR_PLCK2d2 (0 << RCC_CFGR_ADCPRE_SHIFT) /* 00: PLCK2 divided by 2 */ +# define RCC_CFGR_PLCK2d4 (1 << RCC_CFGR_ADCPRE_SHIFT) /* 01: PLCK2 divided by 4 */ +# define RCC_CFGR_PLCK2d6 (2 << RCC_CFGR_ADCPRE_SHIFT) /* 10: PLCK2 divided by 6 */ +# define RCC_CFGR_PLCK2d8 (3 << RCC_CFGR_ADCPRE_SHIFT) /* 11: PLCK2 divided by 8 */ +#define RCC_CFGR_PLLSRC (1 << 16) /* Bit 16: PLL entry clock source */ +#define RCC_CFGR_PLLXTPRE (1 << 17) /* Bit 17: HSE divider for PLL entry */ +#define RCC_CFGR_PLLMUL_SHIFT (18) /* Bits 21-18: PLL Multiplication Factor */ +#define RCC_CFGR_PLLMUL_MASK (0x0f << RCC_CFGR_PLLMUL_SHIFT) +# define RCC_CFGR_PLLMUL_CLKx2 (0 << RCC_CFGR_PLLMUL_SHIFT) /* 0000: PLL input clock x 2 */ +# define RCC_CFGR_PLLMUL_CLKx3 (1 << RCC_CFGR_PLLMUL_SHIFT) /* 0001: PLL input clock x 3 */ +# define RCC_CFGR_PLLMUL_CLKx4 (2 << RCC_CFGR_PLLMUL_SHIFT) /* 0010: PLL input clock x 4 */ +# define RCC_CFGR_PLLMUL_CLKx5 (3 << RCC_CFGR_PLLMUL_SHIFT) /* 0011: PLL input clock x 5 */ +# define RCC_CFGR_PLLMUL_CLKx6 (4 << RCC_CFGR_PLLMUL_SHIFT) /* 0100: PLL input clock x 6 */ +# define RCC_CFGR_PLLMUL_CLKx7 (5 << RCC_CFGR_PLLMUL_SHIFT) /* 0101: PLL input clock x 7 */ +# define RCC_CFGR_PLLMUL_CLKx8 (6 << RCC_CFGR_PLLMUL_SHIFT) /* 0110: PLL input clock x 8 */ +# define RCC_CFGR_PLLMUL_CLKx9 (7 << RCC_CFGR_PLLMUL_SHIFT) /* 0111: PLL input clock x 9 */ +# define RCC_CFGR_PLLMUL_CLKx10 (8 << RCC_CFGR_PLLMUL_SHIFT) /* 1000: PLL input clock x 10 */ +# define RCC_CFGR_PLLMUL_CLKx11 (9 << RCC_CFGR_PLLMUL_SHIFT) /* 1001: PLL input clock x 11 */ +# define RCC_CFGR_PLLMUL_CLKx12 (10 << RCC_CFGR_PLLMUL_SHIFT) /* 1010: PLL input clock x 12 */ +# define RCC_CFGR_PLLMUL_CLKx13 (11 << RCC_CFGR_PLLMUL_SHIFT) /* 1011: PLL input clock x 13 */ +# define RCC_CFGR_PLLMUL_CLKx14 (12 << RCC_CFGR_PLLMUL_SHIFT) /* 1100: PLL input clock x 14 */ +# define RCC_CFGR_PLLMUL_CLKx15 (13 << RCC_CFGR_PLLMUL_SHIFT) /* 1101: PLL input clock x 15 */ +# define RCC_CFGR_PLLMUL_CLKx16 (14 << RCC_CFGR_PLLMUL_SHIFT) /* 111x: PLL input clock x 16 */ +#define RCC_CFGR_USBPRE (1 << 22) /* Bit 22: USB prescaler */ +#define RCC_CFGR_MCO_SHIFT (24) /* Bits 26-24: Microcontroller Clock Output */ +#define RCC_CFGR_MCO_MASK (7 << RCC_CFGR_MCO_SHIFT) +# define RCC_CFGR_NOCLK (0 << RCC_CFGR_MCO_SHIFT) /* 0xx: No clock */ +# define RCC_CFGR_SYSCLK (4 << RCC_CFGR_MCO_SHIFT) /* 100: System clock selected */ +# define RCC_CFGR_INTCLK (5 << RCC_CFGR_MCO_SHIFT) /* 101: Internal 8 MHz RC oscillator clock selected */ +# define RCC_CFGR_EXTCLK (6 << RCC_CFGR_MCO_SHIFT) /* 110: External 1-25 MHz oscillator clock selected */ +# define RCC_CFGR_PLLCLKd2 (7 << RCC_CFGR_MCO_SHIFT) /* 111: PLL clock divided by 2 selected */ + +/* Clock interrupt register */ + +#define RCC_CIR_LSIRDYF (1 << 0) /* Bit 0: LSI Ready Interrupt flag */ +#define RCC_CIR_LSERDYF (1 << 1) /* Bit 1: LSE Ready Interrupt flag */ +#define RCC_CIR_HSIRDYF (1 << 2) /* Bit 2: HSI Ready Interrupt flag */ +#define RCC_CIR_HSERDYF (1 << 3) /* Bit 3: HSE Ready Interrupt flag */ +#define RCC_CIR_PLLRDYF (1 << 4) /* Bit 4: PLL Ready Interrupt flag */ +#define RCC_CIR_CSSF (1 << 7) /* Bit 7: Clock Security System Interrupt flag */ +#define RCC_CIR_LSIRDYIE (1 << 8) /* Bit 8: LSI Ready Interrupt Enable */ +#define RCC_CIR_LSERDYIE (1 << 9) /* Bit 9: LSE Ready Interrupt Enable */ +#define RCC_CIR_HSIRDYIE (1 << 10) /* Bit 10: HSI Ready Interrupt Enable */ +#define RCC_CIR_HSERDYIE (1 << 11) /* Bit 11: HSE Ready Interrupt Enable */ +#define RCC_CIR_PLLRDYIE (1 << 12) /* Bit 12: PLL Ready Interrupt Enable */ +#define RCC_CIR_LSIRDYC (1 << 16) /* Bit 16: LSI Ready Interrupt Clear */ +#define RCC_CIR_LSERDYC (1 << 17) /* Bit 17: LSE Ready Interrupt Clear */ +#define RCC_CIR_HSIRDYC (1 << 18) /* Bit 18: HSI Ready Interrupt Clear */ +#define RCC_CIR_HSERDYC (1 << 19) /* Bit 19: HSE Ready Interrupt Clear */ +#define RCC_CIR_PLLRDYC (1 << 20) /* Bit 20: PLL Ready Interrupt Clear */ +#define RCC_CIR_CSSC (1 << 23) /* Bit 23: Clock Security System Interrupt Clear */ + +/* APB2 Peripheral reset register */ + +#define RCC_APB2RSTR_AFIORST (1 << 0) /* Bit 0: Alternate Function I/O reset */ +#define RCC_APB2RSTR_IOPARST (1 << 2) /* Bit 2: I/O port A reset */ +#define RCC_APB2RSTR_IOPBRST (1 << 3) /* Bit 3: IO port B reset */ +#define RCC_APB2RSTR_IOPCRST (1 << 4) /* Bit 4: IO port C reset */ +#define RCC_APB2RSTR_IOPDRST (1 << 5) /* Bit 5: IO port D reset */ +#define RCC_APB2RSTR_IOPERST (1 << 6) /* Bit 6: IO port E reset */ +#define TCC_APB2RSTR_IOPFRST (1 << 7) /* Bit 7: IO port F reset */ +#define TCC_APB2RSTR_IOPGRST (1 << 8) /* Bit 8: IO port G reset */ +#define RCC_APB2RSTR_ADC1RST (1 << 9) /* Bit 9: ADC 1 interface reset */ +#define RCC_APB2RSTR_ADC2RST (1 << 10) /* Bit 10: ADC 2 interface reset */ +#define RCC_APB2RSTR_TIM1RST (1 << 11) /* Bit 11: TIM1 Timer reset */ +#define RCC_APB2RSTR_SPI1RST (1 << 12) /* Bit 12: SPI 1 reset */ +#define RCC_APB2RSTR_TIM8RST (1 << 13) /* Bit 13: TIM8 Timer reset */ +#define RCC_APB2RSTR_USART1RST (1 << 14) /* Bit 14: USART1 reset */ +#define RCC_APB2RSTR_ADC3RST (1 << 15) /* Bit 15: ADC3 interface reset */ + +/* APB1 Peripheral reset register */ + +#define RCC_APB1RSTR_TIM2RST (1 << 0) /* Bit 0: Timer 2 reset */ +#define RCC_APB1RSTR_TIM3RST (1 << 1) /* Bit 1: Timer 3 reset */ +#define RCC_APB1RSTR_TIM4RST (1 << 2) /* Bit 2: Timer 4 reset */ +#define RCC_APB1RSTR_TIM5RST (1 << 3) /* Bit 3: Timer 5 reset */ +#define RCC_APB1RSTR_TIM6RST (1 << 4) /* Bit 4: Timer 6 reset */ +#define RCC_APB1RSTR_TIM7RST (1 << 5) /* Bit 5: Timer 7 reset */ +#define RCC_APB1RSTR_WWDGRST (1 << 11) /* Bit 11: Window Watchdog reset */ +#define RCC_APB1RSTR_SPI2RST (1 << 14) /* Bit 14: SPI 2 reset */ +#define RCC_APB1RSTR_SPI3RST (1 << 15) /* Bit 15: SPI 3 reset */ +#define RCC_APB1RSTR_USART2RST (1 << 17) /* Bit 17: USART 2 reset */ +#define RCC_APB1RSTR_USART3RST (1 << 18) /* Bit 18: USART 3 reset */ +#define RCC_APB1RSTR_UART4RST (1 << 19) /* Bit 19: UART 4 reset */ +#define RCC_APB1RSTR_UART5RST (1 << 20) /* Bit 18: UART 5 reset */ +#define RCC_APB1RSTR_I2C1RST (1 << 21) /* Bit 21: I2C 1 reset */ +#define RCC_APB1RSTR_I2C2RST (1 << 22) /* Bit 22: I2C 2 reset */ +#define RCC_APB1RSTR_USBRST (1 << 23) /* Bit 23: USB reset */ +#define RCC_APB1RSTR_CAN1RST (1 << 25) /* Bit 25: CAN1 reset */ +#define RCC_APB1RSTR_CAN2RST (1 << 26) /* Bit 26: CAN2 reset */ +#define RCC_APB1RSTR_BKPRST (1 << 27) /* Bit 27: Backup interface reset */ +#define RCC_APB1RSTR_PWRRST (1 << 28) /* Bit 28: Power interface reset */ +#define RCC_APB1RSTR_DACRST (1 << 29) /* Bit 29: DAC interface reset */ + +/* AHB Peripheral Clock enable register */ + +#define RCC_AHBENR_DMA1EN (1 << 0) /* Bit 0: DMA1 clock enable */ +#define RCC_AHBENR_DMA2EN (1 << 1) /* Bit 1: DMA2 clock enable */ +#define RCC_AHBENR_SRAMEN (1 << 2) /* Bit 2: SRAM interface clock enable */ +#define RCC_AHBENR_FLITFEN (1 << 4) /* Bit 4: FLITF clock enable */ +#define RCC_AHBENR_CRCEN (1 << 6) /* Bit 6: CRC clock enable */ +#define RCC_AHBENR_FSMCEN (1 << 8) /* Bit 8: FSMC clock enable */ +#define RCC_AHBENR_SDIOEN (1 << 10) /* Bit 10: SDIO clock enable */ + +/* APB2 Peripheral Clock enable register */ + +#define RCC_APB2ENR_AFIOEN (1 << 0) /* Bit 0: Alternate Function I/O clock enable */ +#define RCC_APB2ENR_IOPEN(n) (1 << ((n)+2)) +#define RCC_APB2ENR_IOPAEN (1 << 2) /* Bit 2: I/O port A clock enable */ +#define RCC_APB2ENR_IOPBEN (1 << 3) /* Bit 3: I/O port B clock enable */ +#define RCC_APB2ENR_IOPCEN (1 << 4) /* Bit 4: I/O port C clock enable */ +#define RCC_APB2ENR_IOPDEN (1 << 5) /* Bit 5: I/O port D clock enable */ +#define RCC_APB2ENR_IOPEEN (1 << 6) /* Bit 6: I/O port E clock enable */ +#define RCC_APB2ENR_IOPFEN (1 << 7) /* Bit 7: I/O port F clock enable */ +#define RCC_APB2ENR_IOPGEN (1 << 8) /* Bit 8: I/O port G clock enable */ +#define RCC_APB2ENR_ADC1EN (1 << 9) /* Bit 9: ADC 1 interface clock enable */ +#define RCC_APB2ENR_ADC2EN (1 << 10) /* Bit 10: ADC 2 interface clock enable */ +#define RCC_APB2ENR_TIM1EN (1 << 11) /* Bit 11: TIM1 Timer clock enable */ +#define RCC_APB2ENR_SPI1EN (1 << 12) /* Bit 12: SPI 1 clock enable */ +#define RCC_APB2ENR_TIM8EN (1 << 13) /* Bit 13: TIM8 Timer clock enable */ +#define RCC_APB2ENR_USART1EN (1 << 14) /* Bit 14: USART1 clock enable */ +#define RCC_APB2ENR_ADC3EN (1 << 15) /* Bit 14: ADC3 interface clock enable */ + +/* APB1 Peripheral Clock enable register */ + +#define RCC_APB1ENR_TIM2EN (1 << 0) /* Bit 0: Timer 2 clock enable */ +#define RCC_APB1ENR_TIM3EN (1 << 1) /* Bit 1: Timer 3 clock enable */ +#define RCC_APB1ENR_TIM4EN (1 << 2) /* Bit 2: Timer 4 clock enable */ +#define RCC_APB1ENR_TIM5EN (1 << 3) /* Bit 3: Timer 5 clock enable */ +#define RCC_APB1ENR_TIM6EN (1 << 4) /* Bit 4: Timer 6 clock enable */ +#define RCC_APB1ENR_TIM7EN (1 << 5) /* Bit 5: Timer 7 clock enable */ +#define RCC_APB1ENR_WWDGEN (1 << 11) /* Bit 11: Window Watchdog clock enable */ +#define RCC_APB1ENR_SPI2EN (1 << 14) /* Bit 14: SPI 2 clock enable */ +#define RCC_APB1ENR_SPI3EN (1 << 15) /* Bit 15: SPI 3 clock enable */ +#define RCC_APB1ENR_USART2EN (1 << 17) /* Bit 17: USART 2 clock enable */ +#define RCC_APB1ENR_USART3EN (1 << 18) /* Bit 18: USART 3 clock enable */ +#define RCC_APB1ENR_UART4EN (1 << 19) /* Bit 19: UART 4 clock enable */ +#define RCC_APB1ENR_UART5EN (1 << 20) /* Bit 20: UART 5 clock enable */ +#define RCC_APB1ENR_I2C1EN (1 << 21) /* Bit 21: I2C 1 clock enable */ +#define RCC_APB1ENR_I2C2EN (1 << 22) /* Bit 22: I2C 2 clock enable */ +#define RCC_APB1ENR_USBEN (1 << 23) /* Bit 23: USB clock enable */ +#define RCC_APB1ENR_CAN1EN (1 << 25) /* Bit 25: CAN1 clock enable */ +#define RCC_APB1ENR_CAN2EN (1 << 26) /* Bit 25: CAN2 clock enable */ +#define RCC_APB1ENR_BKPEN (1 << 27) /* Bit 27: Backup interface clock enable */ +#define RCC_APB1ENR_PWREN (1 << 28) /* Bit 28: Power interface clock enable */ +#define RCC_APB1ENR_DACEN (1 << 29) /* Bit 29: DAC interface clock enable */ + +/* Backup domain control register */ + +#define RCC_BDCR_BDRST (1 << 16) /* Bit 16: Backup domain software reset */ +#define RCC_BDCR_RTCEN (1 << 15) /* Bit 15: RTC clock enable */ +#define RCC_BDCR_RTCSEL_SHIFT (8) /* Bits 9:8: RTC clock source selection */ +#define RCC_BDCR_RTCSEL_MASK (3 << RCC_BDCR_RTCSEL_SHIFT) +# define RCC_BDCR_RTCSEL_NOCLK (0 << RCC_BDCR_RTCSEL_SHIFT) /* 00: No clock */ +# define RCC_BDCR_RTCSEL_LSE (1 << RCC_BDCR_RTCSEL_SHIFT) /* 01: LSE oscillator clock used as RTC clock */ +# define RCC_BDCR_RTCSEL_LSI (2 << RCC_BDCR_RTCSEL_SHIFT) /* 10: LSI oscillator clock used as RTC clock */ +# define RCC_BDCR_RTCSEL_HSE (3 << RCC_BDCR_RTCSEL_SHIFT) /* 11: HSE oscillator clock divided by 128 used as RTC clock */ +#define RCC_BDCR_LSEBYP (1 << 2) /* Bit 2: External Low Speed oscillator Bypass */ +#define RCC_BDCR_LSERDY (1 << 1) /* Bit 1: External Low Speed oscillator Ready */ +#define RCC_BDCR_LSEON (1 << 0) /* Bit 0: External Low Speed oscillator enable */ + +/* Control/status register */ + +#define RCC_CSR_LSION (1 << 0) /* Bit 0: Internal Low Speed oscillator enable */ +#define RCC_CSR_LSIRDY (1 << 1) /* Bit 1: Internal Low Speed oscillator Ready */ +#define RCC_CSR_RMVF (1 << 24) /* Bit 24: Remove reset flag */ +#define RCC_CSR_PINRSTF (1 << 26) /* Bit 26: PIN reset flag */ +#define RCC_CSR_PORRSTF (1 << 27) /* Bit 27: POR/PDR reset flag */ +#define RCC_CSR_SFTRSTF (1 << 28) /* Bit 28: Software Reset flag */ +#define RCC_CSR_IWDGRSTF (1 << 29) /* Bit 29: Independent Watchdog reset flag */ +#define RCC_CSR_WWDGRSTF (1 << 30) /* Bit 30: Window watchdog reset flag */ +#define RCC_CSR_LPWRRSTF (1 << 31) /* Bit 31: Low-Power reset flag */ + +#ifdef CONFIG_STM32_VALUELINE + +/* Clock configuration register 2 */ + +# define RCC_CFGR2_PREDIV1d1 0 /* HSE input not divided */ +# define RCC_CFGR2_PREDIV1d2 1 /* HSE input divided by 2 */ +# define RCC_CFGR2_PREDIV1d3 2 /* HSE input divided by 3 */ +# define RCC_CFGR2_PREDIV1d4 3 /* HSE input divided by 4 */ +# define RCC_CFGR2_PREDIV1d5 4 /* HSE input divided by 5 */ +# define RCC_CFGR2_PREDIV1d6 5 /* HSE input divided by 6 */ +# define RCC_CFGR2_PREDIV1d7 6 /* HSE input divided by 7 */ +# define RCC_CFGR2_PREDIV1d8 7 /* HSE input divided by 8 */ +# define RCC_CFGR2_PREDIV1d9 8 /* HSE input divided by 9 */ +# define RCC_CFGR2_PREDIV1d10 9 /* HSE input divided by 10 */ +# define RCC_CFGR2_PREDIV1d11 10 /* HSE input divided by 11 */ +# define RCC_CFGR2_PREDIV1d12 11 /* HSE input divided by 12 */ +# define RCC_CFGR2_PREDIV1d13 12 /* HSE input divided by 13 */ +# define RCC_CFGR2_PREDIV1d14 13 /* HSE input divided by 14 */ +# define RCC_CFGR2_PREDIV1d15 14 /* HSE input divided by 15 */ +# define RCC_CFGR2_PREDIV1d16 15 /* HSE input divided by 16 */ + +#endif + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_RCC_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rtc.h b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rtc.h new file mode 100644 index 0000000000..a0778f4e6a --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rtc.h @@ -0,0 +1,96 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f10xxx_rtc.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_RTC_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_RTC_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +#define STM32_RTC_CRH_OFFSET 0x0000 /* RTC control register High (16-bit) */ +#define STM32_RTC_CRL_OFFSET 0x0004 /* RTC control register low (16-bit) */ +#define STM32_RTC_PRLH_OFFSET 0x0008 /* RTC prescaler load register high (16-bit) */ +#define STM32_RTC_PRLL_OFFSET 0x000c /* RTC prescaler load register low (16-bit) */ +#define STM32_RTC_DIVH_OFFSET 0x0010 /* RTC prescaler divider register high (16-bit) */ +#define STM32_RTC_DIVL_OFFSET 0x0014 /* RTC prescaler divider register low (16-bit) */ +#define STM32_RTC_CNTH_OFFSET 0x0018 /* RTC counter register high (16-bit) */ +#define STM32_RTC_CNTL_OFFSET 0x001c /* RTC counter register low (16-bit) */ +#define STM32_RTC_ALRH_OFFSET 0x0020 /* RTC alarm register high (16-bit) */ +#define STM32_RTC_ALRL_OFFSET 0x0024 /* RTC alarm register low (16-bit) */ + +/* Register Addresses ***************************************************************/ + +#define STM32_RTC_CRH (STM32_RTC_BASE+STM32_RTC_CRH_OFFSET) +#define STM32_RTC_CRL (STM32_RTC_BASE+STM32_RTC_CRL_OFFSET) +#define STM32_RTC_PRLH (STM32_RTC_BASE+STM32_RTC_PRLH_OFFSET) +#define STM32_RTC_PRLL (STM32_RTC_BASE+STM32_RTC_PRLL_OFFSET) +#define STM32_RTC_DIVH (STM32_RTC_BASE+STM32_RTC_DIVH_OFFSET) +#define STM32_RTC_DIVL (STM32_RTC_BASE+STM32_RTC_DIVL_OFFSET) +#define STM32_RTC_CNTH (STM32_RTC_BASE+STM32_RTC_CNTH_OFFSET) +#define STM32_RTC_CNTL (STM32_RTC_BASE+STM32_RTC_CNTL_OFFSET) +#define STM32_RTC_ALRH (STM32_RTC_BASE+STM32_RTC_ALRH_OFFSET) +#define STM32_RTC_ALRL (STM32_RTC_BASE+STM32_RTC_ALRL_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +/* RTC control register High (16-bit) */ + +#define RTC_CRH_SECIE (1 << 0) /* Bit 0 : Second Interrupt Enable */ +#define RTC_CRH_ALRIE (1 << 1) /* Bit 1: Alarm Interrupt Enable */ +#define RTC_CRH_OWIE (1 << 2) /* Bit 2: OverfloW Interrupt Enable */ + +/* RTC control register low (16-bit) */ + +#define RTC_CRL_SECF (1 << 0) /* Bit 0: Second Flag */ +#define RTC_CRL_ALRF (1 << 1) /* Bit 1: Alarm Flag */ +#define RTC_CRL_OWF (1 << 2) /* Bit 2: Overflow Flag */ +#define RTC_CRL_RSF (1 << 3) /* Bit 3: Registers Synchronized Flag */ +#define RTC_CRL_CNF (1 << 4) /* Bit 4: Configuration Flag */ +#define RTC_CRL_RTOFF (1 << 5) /* Bit 5: RTC operation OFF */ + +/* RTC prescaler load register high (16-bit) */ + +#define RTC_PRLH_PRL_SHIFT (0) /* Bits 3-0: RTC Prescaler Reload Value High */ +#define RTC_PRLH_PRL_MASK (0x0f << RTC_PRLH_PRL_SHIFT) + +/* RTC prescaler divider register high (16-bit) */ + +#define RTC_DIVH_RTC_DIV_SHIFT (0) /* Bits 3-0: RTC Clock Divider High */ +#define RTC_DIVH_RTC_DIV_MASK (0x0f << RTC_DIVH_RTC_DIV_SHIFT) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_RTC_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_vectors.h b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_vectors.h new file mode 100644 index 0000000000..d18c7e7898 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_vectors.h @@ -0,0 +1,214 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f10xxx_vectors.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Pre-processor definitions + ************************************************************************************/ +/* This file is included by stm32_vectors.S. It provides the macro VECTOR that + * supplies ach STM32F10xxx vector in terms of a (lower-case) ISR label and an + * (upper-case) IRQ number as defined in arch/arm/include/stm32/stm32f10xxx_irq.h. + * stm32_vectors.S will defined the VECTOR in different ways in order to generate + * the interrupt vectors and handlers in their final form. + */ + +#if defined(CONFIG_STM32_VALUELINE) + +/* If the common ARMv7-M vector handling is used, then all it needs is the following + * definition that provides the number of supported vectors. + */ + +#ifdef CONFIG_ARMV7M_CMNVECTOR + +/* Reserve 60 interrupt table entries for I/O interrupts. */ + +# define ARMV7M_PERIPHERAL_INTERRUPTS 60 + +#else +# error This target requires CONFIG_ARMV7M_CMNVECTOR +#endif /* CONFIG_ARMV7M_CMNVECTOR */ + +#elif defined(CONFIG_STM32_CONNECTIVITYLINE) + +/* If the common ARMv7-M vector handling is used, then all it needs is the following + * definition that provides the number of supported vectors. + */ + +#ifdef CONFIG_ARMV7M_CMNVECTOR + +/* Reserve 68 interrupt table entries for I/O interrupts. */ + +# define ARMV7M_PERIPHERAL_INTERRUPTS 68 + +#else + +VECTOR(stm32_wwdg, STM32_IRQ_WWDG) /* Vector 16+0: Window Watchdog interrupt */ +VECTOR(stm32_pvd, STM32_IRQ_PVD) /* Vector 16+1: PVD through EXTI Line detection interrupt */ +VECTOR(stm32_tamper, STM32_IRQ_TAMPER) /* Vector 16+2: Tamper interrupt */ +VECTOR(stm32_rtc, STM32_IRQ_RTC) /* Vector 16+3: RTC global interrupt */ +VECTOR(stm32_flash, STM32_IRQ_FLASH) /* Vector 16+4: Flash global interrupt */ +VECTOR(stm32_rcc, STM32_IRQ_RCC) /* Vector 16+5: RCC global interrupt */ +VECTOR(stm32_exti0, STM32_IRQ_EXTI0) /* Vector 16+6: EXTI Line 0 interrupt */ +VECTOR(stm32_exti1, STM32_IRQ_EXTI1) /* Vector 16+7: EXTI Line 1 interrupt */ +VECTOR(stm32_exti2, STM32_IRQ_EXTI2) /* Vector 16+8: EXTI Line 2 interrupt */ +VECTOR(stm32_exti3, STM32_IRQ_EXTI3) /* Vector 16+9: EXTI Line 3 interrupt */ +VECTOR(stm32_exti4, STM32_IRQ_EXTI4) /* Vector 16+10: EXTI Line 4 interrupt */ +VECTOR(stm32_dma1ch1, STM32_IRQ_DMA1CH1) /* Vector 16+11: DMA1 Channel 1 global interrupt */ +VECTOR(stm32_dma1ch2, STM32_IRQ_DMA1CH2) /* Vector 16+12: DMA1 Channel 2 global interrupt */ +VECTOR(stm32_dma1ch3, STM32_IRQ_DMA1CH3) /* Vector 16+13: DMA1 Channel 3 global interrupt */ +VECTOR(stm32_dma1ch4, STM32_IRQ_DMA1CH4) /* Vector 16+14: DMA1 Channel 4 global interrupt */ +VECTOR(stm32_dma1ch5, STM32_IRQ_DMA1CH5) /* Vector 16+15: DMA1 Channel 5 global interrupt */ +VECTOR(stm32_dma1ch6, STM32_IRQ_DMA1CH6) /* Vector 16+16: DMA1 Channel 7 global interrupt */ +VECTOR(stm32_adc12, STM32_IRQ_ADC12) /* Vector 16+18: ADC1 and ADC2 global interrupt */ +VECTOR(stm32_can1tx, STM32_IRQ_CAN1TX) /* Vector 16+19: CAN1 TX interrupts */ +VECTOR(stm32_can1rx0, STM32_IRQ_CAN1RX0) /* Vector 16+20: CAN1 RX0 interrupts */ +VECTOR(stm32_can1rx, STM32_IRQ_CAN1RX1) /* Vector 16+21: CAN1 RX1 interrupt */ +VECTOR(stm32_can1sce, STM32_IRQ_CAN1SCE) /* Vector 16+22: CAN1 SCE interrupt */ +VECTOR(stm32_exti95, STM32_IRQ_EXTI95) /* Vector 16+23: EXTI Line[9:5] interrupts */ +VECTOR(stm32_tim1brk, STM32_IRQ_TIM1BRK) /* Vector 16+24: TIM1 Break interrupt */ +VECTOR(stm32_tim1up, STM32_IRQ_TIM1UP) /* Vector 16+25: TIM1 Update interrupt */ +VECTOR(stm32_tim1trgcom, STM32_IRQ_TIM1TRGCOM) /* Vector 16+26: TIM1 Trigger and Commutation interrupts */ +VECTOR(stm32_tim1cc, STM32_IRQ_TIM1CC) /* Vector 16+27: TIM1 Capture Compare interrupt */ +VECTOR(stm32_tim2, STM32_IRQ_TIM2) /* Vector 16+28: TIM2 global interrupt */ +VECTOR(stm32_tim3, STM32_IRQ_TIM3) /* Vector 16+29: TIM3 global interrupt */ +VECTOR(stm32_tim4, STM32_IRQ_TIM4) /* Vector 16+30: TIM4 global interrupt */ +VECTOR(stm32_i2c1ev, STM32_IRQ_I2C1EV) /* Vector 16+31: I2C1 event interrupt */ +VECTOR(stm32_i2c1er, STM32_IRQ_I2C1ER) /* Vector 16+32: I2C1 error interrupt */ +VECTOR(stm32_i2c2ev, STM32_IRQ_I2C2EV) /* Vector 16+33: I2C2 event interrupt */ +VECTOR(stm32_i2c2er, STM32_IRQ_I2C2ER) /* Vector 16+34: I2C2 error interrupt */ +VECTOR(stm32_spi1, STM32_IRQ_SPI1) /* Vector 16+35: SPI1 global interrupt */ +VECTOR(stm32_spi2, STM32_IRQ_SPI2) /* Vector 16+36: SPI2 global interrupt */ +VECTOR(stm32_usart1, STM32_IRQ_USART1) /* Vector 16+37: USART1 global interrupt */ +VECTOR(stm32_usart2, STM32_IRQ_USART2) /* Vector 16+38: USART2 global interrupt */ +VECTOR(stm32_usart3, STM32_IRQ_USART3) /* Vector 16+39: USART3 global interrupt */ +VECTOR(stm32_exti1510, STM32_IRQ_EXTI1510) /* Vector 16+40: EXTI Line[15:10] interrupts */ +VECTOR(stm32_rtcalr, STM32_IRQ_RTCALRM) /* Vector 16+41: RTC alarm through EXTI line interrupt */ +VECTOR(stm32_otgfswkup, STM32_IRQ_OTGFSWKUP) /* Vector 16+42: USB On-The-Go FS Wakeup through EXTI line interrupt */ +VECTOR(stm32_tim5, STM32_IRQ_TIM5) /* Vector 16+50: TIM5 global interrupt */ +VECTOR(stm32_spi3, STM32_IRQ_SPI3 ) /* Vector 16+51: SPI3 global interrupt */ +VECTOR(stm32_uart4 , STM32_IRQ_UART4) /* Vector 16+52: UART4 global interrupt */ +VECTOR(stm32_uart5, STM32_IRQ_UART5) /* Vector 16+53: UART5 global interrupt */ +VECTOR(stm32_tim6, STM32_IRQ_TIM6) /* Vector 16+54: TIM6 global interrupt */ +VECTOR(stm32_tim7, STM32_IRQ_TIM7) /* Vector 16+55: TIM7 global interrupt */ +VECTOR(stm32_dma2ch1, STM32_IRQ_DMA2CH1) /* Vector 16+56: DMA2 Channel 1 global interrupt */ +VECTOR(stm32_dma2ch2, STM32_IRQ_DMA2CH2) /* Vector 16+57: DMA2 Channel 2 global interrupt */ +VECTOR(stm32_dma2ch3, STM32_IRQ_DMA2CH3) /* Vector 16+58: DMA2 Channel 3 global interrupt */ +VECTOR(stm32_dma2ch4, STM32_IRQ_DMA2CH4) /* Vector 16+59: DMA2 Channel 4 global interrupt */ +VECTOR(stm32_dma2ch5, STM32_IRQ_DMA2CH5) /* Vector 16+60: DMA2 Channel 5 global interrupt */ +VECTOR(stm32_eth, STM32_IRQ_ETH) /* Vector 16+61: Ethernet global interrupt */ +VECTOR(stm32_ethwkup, STM32_IRQ_ETHWKUP) /* Vector 16+62: Ethernet Wakeup through EXTI line interrupt */ +VECTOR(stm32_can2tx, STM32_IRQ_CAN2TX) /* Vector 16+63: CAN2 TX interrupts */ +VECTOR(stm32_can2rx0, STM32_IRQ_CAN2RX0) /* Vector 16+64: CAN2 RX0 interrupts */ +VECTOR(stm32_can2rx1, STM32_IRQ_CAN2RX1) /* Vector 16+65: CAN2 RX1 interrupt */ +VECTOR(stm32_can2sce, STM32_IRQ_CAN2SCE) /* Vector 16+66: CAN2 SCE interrupt */ +VECTOR(stm32_otgfs, STM32_IRQ_OTGFS) /* Vector 16+67: USB On The Go FS global interrupt */ + +#endif /* CONFIG_ARMV7M_CMNVECTOR */ +#else /* CONFIG_STM32_CONNECTIVITYLINE */ + +/* If the common ARMv7-M vector handling is used, then all it needs is the following + * definition that provides the number of supported vectors. + */ + +#ifdef CONFIG_ARMV7M_CMNVECTOR + +/* Reserve 60 interrupt table entries for I/O interrupts. */ + +# define ARMV7M_PERIPHERAL_INTERRUPTS 60 + +#else + +VECTOR(stm32_wwdg, STM32_IRQ_WWDG) /* Vector 16+0: Window Watchdog interrupt */ +VECTOR(stm32_pvd, STM32_IRQ_PVD) /* Vector 16+1: PVD through EXTI Line detection interrupt */ +VECTOR(stm32_tamper, STM32_IRQ_TAMPER) /* Vector 16+2: Tamper interrupt */ +VECTOR(stm32_rtc, STM32_IRQ_RTC) /* Vector 16+3: RTC global interrupt */ +VECTOR(stm32_flash, STM32_IRQ_FLASH) /* Vector 16+4: Flash global interrupt */ +VECTOR(stm32_rcc, STM32_IRQ_RCC) /* Vector 16+5: RCC global interrupt */ +VECTOR(stm32_exti0, STM32_IRQ_EXTI0) /* Vector 16+6: EXTI Line 0 interrupt */ +VECTOR(stm32_exti1, STM32_IRQ_EXTI1) /* Vector 16+7: EXTI Line 1 interrupt */ +VECTOR(stm32_exti2, STM32_IRQ_EXTI2) /* Vector 16+8: EXTI Line 2 interrupt */ +VECTOR(stm32_exti3, STM32_IRQ_EXTI3) /* Vector 16+9: EXTI Line 3 interrupt */ +VECTOR(stm32_exti4, STM32_IRQ_EXTI4) /* Vector 16+10: EXTI Line 4 interrupt */ +VECTOR(stm32_dma1ch1, STM32_IRQ_DMA1CH1) /* Vector 16+11: DMA1 Channel 1 global interrupt */ +VECTOR(stm32_dma1ch2, STM32_IRQ_DMA1CH2) /* Vector 16+12: DMA1 Channel 2 global interrupt */ +VECTOR(stm32_dma1ch3, STM32_IRQ_DMA1CH3) /* Vector 16+13: DMA1 Channel 3 global interrupt */ +VECTOR(stm32_dma1ch4, STM32_IRQ_DMA1CH4) /* Vector 16+14: DMA1 Channel 4 global interrupt */ +VECTOR(stm32_dma1ch5, STM32_IRQ_DMA1CH5) /* Vector 16+15: DMA1 Channel 5 global interrupt */ +VECTOR(stm32_dma1ch6, STM32_IRQ_DMA1CH6) /* Vector 16+16: DMA1 Channel 6 global interrupt */ +VECTOR(stm32_dma1ch7, STM32_IRQ_DMA1CH7) /* Vector 16+17: DMA1 Channel 7 global interrupt */ +VECTOR(stm32_adc12, STM32_IRQ_ADC12) /* Vector 16+18: ADC1 and ADC2 global interrupt */ +VECTOR(stm32_usbhpcantx, STM32_IRQ_USBHPCANTX) /* Vector 16+19: USB High Priority or CAN TX interrupts*/ +VECTOR(stm32_usblpcanrx0, STM32_IRQ_USBLPCANRX0) /* Vector 16+20: USB Low Priority or CAN RX0 interrupts*/ +VECTOR(stm32_can1rx1, STM32_IRQ_CAN1RX1) /* Vector 16+21: CAN1 RX1 interrupt */ +VECTOR(stm32_can1sce, STM32_IRQ_CAN1SCE) /* Vector 16+22: CAN1 SCE interrupt */ +VECTOR(stm32_exti95, STM32_IRQ_EXTI95) /* Vector 16+23: EXTI Line[9:5] interrupts */ +VECTOR(stm32_tim1brk, STM32_IRQ_TIM1BRK) /* Vector 16+24: TIM1 Break interrupt */ +VECTOR(stm32_tim1up, STM32_IRQ_TIM1UP) /* Vector 16+25: TIM1 Update interrupt */ +VECTOR(stm32_tim1rtgcom, STM32_IRQ_TIM1TRGCOM) /* Vector 16+26: TIM1 Trigger and Commutation interrupts */ +VECTOR(stm32_tim1cc, STM32_IRQ_TIM1CC) /* Vector 16+27: TIM1 Capture Compare interrupt */ +VECTOR(stm32_tim2, STM32_IRQ_TIM2) /* Vector 16+28: TIM2 global interrupt */ +VECTOR(stm32_tim3, STM32_IRQ_TIM3) /* Vector 16+29: TIM3 global interrupt */ +VECTOR(stm32_tim4, STM32_IRQ_TIM4) /* Vector 16+30: TIM4 global interrupt */ +VECTOR(stm32_i2c1ev, STM32_IRQ_I2C1EV) /* Vector 16+31: I2C1 event interrupt */ +VECTOR(stm32_i2c1er, STM32_IRQ_I2C1ER) /* Vector 16+32: I2C1 error interrupt */ +VECTOR(stm32_i2c2ev, STM32_IRQ_I2C2EV) /* Vector 16+33: I2C2 event interrupt */ +VECTOR(stm32_i2c2er, STM32_IRQ_I2C2ER) /* Vector 16+34: I2C2 error interrupt */ +VECTOR(stm32_spi1, STM32_IRQ_SPI1) /* Vector 16+35: SPI1 global interrupt */ +VECTOR(stm32_spi2, STM32_IRQ_SPI2) /* Vector 16+36: SPI2 global interrupt */ +VECTOR(stm32_usart1, STM32_IRQ_USART1) /* Vector 16+37: USART1 global interrupt */ +VECTOR(stm32_usart2, STM32_IRQ_USART2) /* Vector 16+38: USART2 global interrupt */ +VECTOR(stm32_usart3, STM32_IRQ_USART3) /* Vector 16+39: USART3 global interrupt */ +VECTOR(stm32_exti1510, STM32_IRQ_EXTI1510) /* Vector 16+40: EXTI Line[15:10] interrupts */ +VECTOR(stm32_rtcalr, STM32_IRQ_RTCALRM) /* Vector 16+41: RTC alarm through EXTI line interrupt */ +VECTOR(stm32_usbwkup, STM32_IRQ_USBWKUP) /* Vector 16+42: USB wakeup from suspend through EXTI line interrupt*/ +VECTOR(stm32_tim8brk, STM32_IRQ_TIM8BRK) /* Vector 16+43: TIM8 Break interrupt */ +VECTOR(stm32_tim8up, STM32_IRQ_TIM8UP) /* Vector 16+44: TIM8 Update interrupt */ +VECTOR(stm32_tim8trgcom, STM32_IRQ_TIM8TRGCOM) /* Vector 16+45: TIM8 Trigger and Commutation interrupts */ +VECTOR(stm32_tim8cc, STM32_IRQ_TIM8CC) /* Vector 16+46: TIM8 Capture Compare interrupt */ +VECTOR(stm32_adc3, STM32_IRQ_ADC3) /* Vector 16+47: ADC3 global interrupt */ +VECTOR(stm32_fsmc, STM32_IRQ_FSMC) /* Vector 16+48: FSMC global interrupt */ +VECTOR(stm32_sdio, STM32_IRQ_SDIO) /* Vector 16+49: SDIO global interrupt */ +VECTOR(stm32_tim5, STM32_IRQ_TIM5) /* Vector 16+50: TIM5 global interrupt */ +VECTOR(stm32_spi3, STM32_IRQ_SPI3) /* Vector 16+51: SPI3 global interrupt */ +VECTOR(stm32_uart4, STM32_IRQ_UART4) /* Vector 16+52: UART4 global interrupt */ +VECTOR(stm32_uart5, STM32_IRQ_UART5) /* Vector 16+53: UART5 global interrupt */ +VECTOR(stm32_tim6, STM32_IRQ_TIM6) /* Vector 16+54: TIM6 global interrupt */ +VECTOR(stm32_tim7, STM32_IRQ_TIM7) /* Vector 16+55: TIM7 global interrupt */ +VECTOR(stm32_dma2ch1, STM32_IRQ_DMA2CH1) /* Vector 16+56: DMA2 Channel 1 global interrupt */ +VECTOR(stm32_dma2ch2, STM32_IRQ_DMA2CH2) /* Vector 16+57: DMA2 Channel 2 global interrupt */ +VECTOR(stm32_dma2ch3, STM32_IRQ_DMA2CH3) /* Vector 16+58: DMA2 Channel 3 global interrupt */ +VECTOR(stm32_dma2ch45, STM32_IRQ_DMA2CH45) /* Vector 16+59: DMA2 Channel 4&5 global interrupt */ + +#endif /* CONFIG_ARMV7M_CMNVECTOR */ +#endif /* CONFIG_STM32_CONNECTIVITYLINE */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_dma.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_dma.h new file mode 100644 index 0000000000..af4b361c29 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_dma.h @@ -0,0 +1,520 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f20xxx_dma.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_DMA_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_DMA_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* 2 DMA controllers */ + +#define DMA1 (0) +#define DMA2 (1) + +/* 8 DMA streams */ + +#define DMA_STREAM0 (0) +#define DMA_STREAM1 (1) +#define DMA_STREAM2 (2) +#define DMA_STREAM3 (3) +#define DMA_STREAM4 (4) +#define DMA_STREAM5 (5) +#define DMA_STREAM6 (6) +#define DMA_STREAM7 (7) + +/* 8 DMA channels */ + +#define DMA_CHAN0 (0) +#define DMA_CHAN1 (1) +#define DMA_CHAN2 (2) +#define DMA_CHAN3 (3) +#define DMA_CHAN4 (4) +#define DMA_CHAN5 (5) +#define DMA_CHAN6 (6) +#define DMA_CHAN7 (7) + +/* Register Offsets *****************************************************************/ + +#define STM32_DMA_LISR_OFFSET 0x0000 /* DMA low interrupt status register */ +#define STM32_DMA_HISR_OFFSET 0x0004 /* DMA high interrupt status register */ +#define STM32_DMA_LIFCR_OFFSET 0x0008 /* DMA low interrupt flag clear register */ +#define STM32_DMA_HIFCR_OFFSET 0x000c /* DMA high interrupt flag clear register */ + +#define STM32_DMA_OFFSET(n) (0x0010+0x0018*(n)) +#define STM32_DMA_SCR_OFFSET 0x0000 /* DMA stream n configuration register */ +#define STM32_DMA_SNDTR_OFFSET 0x0004 /* DMA stream n number of data register */ +#define STM32_DMA_SPAR_OFFSET 0x0008 /* DMA stream n peripheral address register */ +#define STM32_DMA_SM0AR_OFFSET 0x000c /* DMA stream n memory 0 address register */ +#define STM32_DMA_SM1AR_OFFSET 0x0010 /* DMA stream n memory 1 address register */ +#define STM32_DMA_SFCR_OFFSET 0x0014 /* DMA stream n FIFO control register */ + +#define STM32_DMA_S0CR_OFFSET 0x0010 /* DMA stream 0 configuration register */ +#define STM32_DMA_S1CR_OFFSET 0x0028 /* DMA stream 1 configuration register */ +#define STM32_DMA_S2CR_OFFSET 0x0040 /* DMA stream 2 configuration register */ +#define STM32_DMA_S3CR_OFFSET 0x0058 /* DMA stream 3 configuration register */ +#define STM32_DMA_S4CR_OFFSET 0x0070 /* DMA stream 4 configuration register */ +#define STM32_DMA_S5CR_OFFSET 0x0088 /* DMA stream 5 configuration register */ +#define STM32_DMA_S6CR_OFFSET 0x00a0 /* DMA stream 6 configuration register */ +#define STM32_DMA_S7CR_OFFSET 0x00b8 /* DMA stream 7 configuration register */ + +#define STM32_DMA_S0NDTR_OFFSET 0x0014 /* DMA stream 0 number of data register */ +#define STM32_DMA_S1NDTR_OFFSET 0x002c /* DMA stream 1 number of data register */ +#define STM32_DMA_S2NDTR_OFFSET 0x0044 /* DMA stream 2 number of data register */ +#define STM32_DMA_S3NDTR_OFFSET 0x005c /* DMA stream 3 number of data register */ +#define STM32_DMA_S4NDTR_OFFSET 0x0074 /* DMA stream 4 number of data register */ +#define STM32_DMA_S5NDTR_OFFSET 0x008c /* DMA stream 5 number of data register */ +#define STM32_DMA_S6NDTR_OFFSET 0x00a4 /* DMA stream 6 number of data register */ +#define STM32_DMA_S7NDTR_OFFSET 0x00bc /* DMA stream 7 number of data register */ + +#define STM32_DMA_S0PAR_OFFSET 0x0018 /* DMA stream 0 peripheral address register */ +#define STM32_DMA_S1PAR_OFFSET 0x0030 /* DMA stream 1 peripheral address register */ +#define STM32_DMA_S2PAR_OFFSET 0x0048 /* DMA stream 2 peripheral address register */ +#define STM32_DMA_S3PAR_OFFSET 0x0060 /* DMA stream 3 peripheral address register */ +#define STM32_DMA_S4PAR_OFFSET 0x0078 /* DMA stream 4 peripheral address register */ +#define STM32_DMA_S5PAR_OFFSET 0x0090 /* DMA stream 5 peripheral address register */ +#define STM32_DMA_S6PAR_OFFSET 0x00a8 /* DMA stream 6 peripheral address register */ +#define STM32_DMA_S7PAR_OFFSET 0x00c0 /* DMA stream 7 peripheral address register */ + +#define STM32_DMA_S0M0AR_OFFSET 0x001c /* DMA stream 0 memory 0 address register */ +#define STM32_DMA_S1M0AR_OFFSET 0x0034 /* DMA stream 1 memory 0 address register */ +#define STM32_DMA_S2M0AR_OFFSET 0x004c /* DMA stream 2 memory 0 address register */ +#define STM32_DMA_S3M0AR_OFFSET 0x0064 /* DMA stream 3 memory 0 address register */ +#define STM32_DMA_S4M0AR_OFFSET 0x007c /* DMA stream 4 memory 0 address register */ +#define STM32_DMA_S5M0AR_OFFSET 0x0094 /* DMA stream 5 memory 0 address register */ +#define STM32_DMA_S6M0AR_OFFSET 0x00ac /* DMA stream 6 memory 0 address register */ +#define STM32_DMA_S7M0AR_OFFSET 0x00c4 /* DMA stream 7 memory 0 address register */ + +#define STM32_DMA_S0M1AR_OFFSET 0x0020 /* DMA stream 0 memory 1 address register */ +#define STM32_DMA_S1M1AR_OFFSET 0x0038 /* DMA stream 1 memory 1 address register */ +#define STM32_DMA_S2M1AR_OFFSET 0x0050 /* DMA stream 2 memory 1 address register */ +#define STM32_DMA_S3M1AR_OFFSET 0x0068 /* DMA stream 3 memory 1 address register */ +#define STM32_DMA_S4M1AR_OFFSET 0x0080 /* DMA stream 4 memory 1 address register */ +#define STM32_DMA_S5M1AR_OFFSET 0x0098 /* DMA stream 5 memory 1 address register */ +#define STM32_DMA_S6M1AR_OFFSET 0x00b0 /* DMA stream 6 memory 1 address register */ +#define STM32_DMA_S7M1AR_OFFSET 0x00c8 /* DMA stream 7 memory 1 address register */ + +#define STM32_DMA_S0FCR_OFFSET 0x0024 /* DMA stream 0 FIFO control register */ +#define STM32_DMA_S1FCR_OFFSET 0x003c /* DMA stream 1 FIFO control register */ +#define STM32_DMA_S2FCR_OFFSET 0x0054 /* DMA stream 2 FIFO control register */ +#define STM32_DMA_S3FCR_OFFSET 0x006c /* DMA stream 3 FIFO control register */ +#define STM32_DMA_S4FCR_OFFSET 0x0084 /* DMA stream 4 FIFO control register */ +#define STM32_DMA_S5FCR_OFFSET 0x009c /* DMA stream 5 FIFO control register */ +#define STM32_DMA_S6FCR_OFFSET 0x00b4 /* DMA stream 6 FIFO control register */ +#define STM32_DMA_S7FCR_OFFSET 0x00cc /* DMA stream 7 FIFO control register */ + +/* Register Addresses ***************************************************************/ + +#define STM32_DMA1_LISRC (STM32_DMA1_BASE+STM32_DMA_LISR_OFFSET) +#define STM32_DMA1_HISRC (STM32_DMA1_BASE+STM32_DMA_HISR_OFFSET) +#define STM32_DMA1_LIFCR (STM32_DMA1_BASE+STM32_DMA_LIFCR_OFFSET) +#define STM32_DMA1_HIFCR (STM32_DMA1_BASE+STM32_DMA_HIFCR_OFFSET) + +#define STM32_DMA1_SCR(n) (STM32_DMA1_BASE+STM32_DMA_SCR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA1_S0CR (STM32_DMA1_BASE+STM32_DMA_S0CR_OFFSET) +#define STM32_DMA1_S1CR (STM32_DMA1_BASE+STM32_DMA_S1CR_OFFSET) +#define STM32_DMA1_S2CR (STM32_DMA1_BASE+STM32_DMA_S2CR_OFFSET) +#define STM32_DMA1_S3CR (STM32_DMA1_BASE+STM32_DMA_S3CR_OFFSET) +#define STM32_DMA1_S4CR (STM32_DMA1_BASE+STM32_DMA_S4CR_OFFSET) +#define STM32_DMA1_S5CR (STM32_DMA1_BASE+STM32_DMA_S5CR_OFFSET) +#define STM32_DMA1_S6CR (STM32_DMA1_BASE+STM32_DMA_S6CR_OFFSET) +#define STM32_DMA1_S7CR (STM32_DMA1_BASE+STM32_DMA_S7CR_OFFSET) + +#define STM32_DMA1_SNDTR(n) (STM32_DMA1_BASE+STM32_DMA_SNDTR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA1_S0NDTR (STM32_DMA1_BASE+STM32_DMA_S0NDTR_OFFSET) +#define STM32_DMA1_S1NDTR (STM32_DMA1_BASE+STM32_DMA_S1NDTR_OFFSET) +#define STM32_DMA1_S2NDTR (STM32_DMA1_BASE+STM32_DMA_S2NDTR_OFFSET) +#define STM32_DMA1_S3NDTR (STM32_DMA1_BASE+STM32_DMA_S3NDTR_OFFSET) +#define STM32_DMA1_S4NDTR (STM32_DMA1_BASE+STM32_DMA_S4NDTR_OFFSET) +#define STM32_DMA1_S5NDTR (STM32_DMA1_BASE+STM32_DMA_S5NDTR_OFFSET) +#define STM32_DMA1_S6NDTR (STM32_DMA1_BASE+STM32_DMA_S6NDTR_OFFSET) +#define STM32_DMA1_S7NDTR (STM32_DMA1_BASE+STM32_DMA_S7NDTR_OFFSET) + +#define STM32_DMA1_SPAR(n) (STM32_DMA1_BASE+STM32_DMA_SPAR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA1_S0PAR (STM32_DMA1_BASE+STM32_DMA_S0PAR_OFFSET) +#define STM32_DMA1_S1PAR (STM32_DMA1_BASE+STM32_DMA_S1PAR_OFFSET) +#define STM32_DMA1_S2PAR (STM32_DMA1_BASE+STM32_DMA_S2PAR_OFFSET) +#define STM32_DMA1_S3PAR (STM32_DMA1_BASE+STM32_DMA_S3PAR_OFFSET) +#define STM32_DMA1_S4PAR (STM32_DMA1_BASE+STM32_DMA_S4PAR_OFFSET) +#define STM32_DMA1_S5PAR (STM32_DMA1_BASE+STM32_DMA_S5PAR_OFFSET) +#define STM32_DMA1_S6PAR (STM32_DMA1_BASE+STM32_DMA_S6PAR_OFFSET) +#define STM32_DMA1_S7PAR (STM32_DMA1_BASE+STM32_DMA_S7PAR_OFFSET) + +#define STM32_DMA1_SM0AR(n) (STM32_DMA1_BASE+STM32_DMA_SM0AR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA1_S0M0AR (STM32_DMA1_BASE+STM32_DMA_S0M0AR_OFFSET) +#define STM32_DMA1_S1M0AR (STM32_DMA1_BASE+STM32_DMA_S1M0AR_OFFSET) +#define STM32_DMA1_S2M0AR (STM32_DMA1_BASE+STM32_DMA_S2M0AR_OFFSET) +#define STM32_DMA1_S3M0AR (STM32_DMA1_BASE+STM32_DMA_S3M0AR_OFFSET) +#define STM32_DMA1_S4M0AR (STM32_DMA1_BASE+STM32_DMA_S4M0AR_OFFSET) +#define STM32_DMA1_S5M0AR (STM32_DMA1_BASE+STM32_DMA_S5M0AR_OFFSET) +#define STM32_DMA1_S6M0AR (STM32_DMA1_BASE+STM32_DMA_S6M0AR_OFFSET) +#define STM32_DMA1_S7M0AR (STM32_DMA1_BASE+STM32_DMA_S7M0AR_OFFSET) + +#define STM32_DMA1_SM1AR(n) (STM32_DMA1_BASE+STM32_DMA_SM1AR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA1_S0M1AR (STM32_DMA1_BASE+STM32_DMA_S0M1AR_OFFSET) +#define STM32_DMA1_S1M1AR (STM32_DMA1_BASE+STM32_DMA_S1M1AR_OFFSET) +#define STM32_DMA1_S2M1AR (STM32_DMA1_BASE+STM32_DMA_S2M1AR_OFFSET) +#define STM32_DMA1_S3M1AR (STM32_DMA1_BASE+STM32_DMA_S3M1AR_OFFSET) +#define STM32_DMA1_S4M1AR (STM32_DMA1_BASE+STM32_DMA_S4M1AR_OFFSET) +#define STM32_DMA1_S5M1AR (STM32_DMA1_BASE+STM32_DMA_S5M1AR_OFFSET) +#define STM32_DMA1_S6M1AR (STM32_DMA1_BASE+STM32_DMA_S6M1AR_OFFSET) +#define STM32_DMA1_S7M1AR (STM32_DMA1_BASE+STM32_DMA_S7M1AR_OFFSET) + +#define STM32_DMA1_SFCR(n) (STM32_DMA1_BASE+STM32_DMA_SFCR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA1_S0FCR (STM32_DMA1_BASE+STM32_DMA_S0FCR_OFFSET) +#define STM32_DMA1_S1FCR (STM32_DMA1_BASE+STM32_DMA_S1FCR_OFFSET) +#define STM32_DMA1_S2FCR (STM32_DMA1_BASE+STM32_DMA_S2FCR_OFFSET) +#define STM32_DMA1_S3FCR (STM32_DMA1_BASE+STM32_DMA_S3FCR_OFFSET) +#define STM32_DMA1_S4FCR (STM32_DMA1_BASE+STM32_DMA_S4FCR_OFFSET) +#define STM32_DMA1_S5FCR (STM32_DMA1_BASE+STM32_DMA_S5FCR_OFFSET) +#define STM32_DMA1_S6FCR (STM32_DMA1_BASE+STM32_DMA_S6FCR_OFFSET) +#define STM32_DMA1_S7FCR (STM32_DMA1_BASE+STM32_DMA_S7FCR_OFFSET) + +#define STM32_DMA2_LISRC (STM32_DMA2_BASE+STM32_DMA_LISR_OFFSET) +#define STM32_DMA2_HISRC (STM32_DMA2_BASE+STM32_DMA_HISR_OFFSET) +#define STM32_DMA2_LIFCR (STM32_DMA2_BASE+STM32_DMA_LIFCR_OFFSET) +#define STM32_DMA2_HIFCR (STM32_DMA2_BASE+STM32_DMA_HIFCR_OFFSET) + +#define STM32_DMA2_SCR(n) (STM32_DMA2_BASE+STM32_DMA_SCR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA2_S0CR (STM32_DMA2_BASE+STM32_DMA_S0CR_OFFSET) +#define STM32_DMA2_S1CR (STM32_DMA2_BASE+STM32_DMA_S1CR_OFFSET) +#define STM32_DMA2_S2CR (STM32_DMA2_BASE+STM32_DMA_S2CR_OFFSET) +#define STM32_DMA2_S3CR (STM32_DMA2_BASE+STM32_DMA_S3CR_OFFSET) +#define STM32_DMA2_S4CR (STM32_DMA2_BASE+STM32_DMA_S4CR_OFFSET) +#define STM32_DMA2_S5CR (STM32_DMA2_BASE+STM32_DMA_S5CR_OFFSET) +#define STM32_DMA2_S6CR (STM32_DMA2_BASE+STM32_DMA_S6CR_OFFSET) +#define STM32_DMA2_S7CR (STM32_DMA2_BASE+STM32_DMA_S7CR_OFFSET) + +#define STM32_DMA2_SNDTR(n) (STM32_DMA2_BASE+STM32_DMA_SNDTR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA2_S0NDTR (STM32_DMA2_BASE+STM32_DMA_S0NDTR_OFFSET) +#define STM32_DMA2_S1NDTR (STM32_DMA2_BASE+STM32_DMA_S1NDTR_OFFSET) +#define STM32_DMA2_S2NDTR (STM32_DMA2_BASE+STM32_DMA_S2NDTR_OFFSET) +#define STM32_DMA2_S3NDTR (STM32_DMA2_BASE+STM32_DMA_S3NDTR_OFFSET) +#define STM32_DMA2_S4NDTR (STM32_DMA2_BASE+STM32_DMA_S4NDTR_OFFSET) +#define STM32_DMA2_S5NDTR (STM32_DMA2_BASE+STM32_DMA_S5NDTR_OFFSET) +#define STM32_DMA2_S6NDTR (STM32_DMA2_BASE+STM32_DMA_S6NDTR_OFFSET) +#define STM32_DMA2_S7NDTR (STM32_DMA2_BASE+STM32_DMA_S7NDTR_OFFSET) + +#define STM32_DMA2_SPAR(n) (STM32_DMA2_BASE+STM32_DMA_SPAR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA2_S0PAR (STM32_DMA2_BASE+STM32_DMA_S0PAR_OFFSET) +#define STM32_DMA2_S1PAR (STM32_DMA2_BASE+STM32_DMA_S1PAR_OFFSET) +#define STM32_DMA2_S2PAR (STM32_DMA2_BASE+STM32_DMA_S2PAR_OFFSET) +#define STM32_DMA2_S3PAR (STM32_DMA2_BASE+STM32_DMA_S3PAR_OFFSET) +#define STM32_DMA2_S4PAR (STM32_DMA2_BASE+STM32_DMA_S4PAR_OFFSET) +#define STM32_DMA2_S5PAR (STM32_DMA2_BASE+STM32_DMA_S5PAR_OFFSET) +#define STM32_DMA2_S6PAR (STM32_DMA2_BASE+STM32_DMA_S6PAR_OFFSET) +#define STM32_DMA2_S7PAR (STM32_DMA2_BASE+STM32_DMA_S7PAR_OFFSET) + +#define STM32_DMA2_SM0AR(n) (STM32_DMA2_BASE+STM32_DMA_SM0AR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA2_S0M0AR (STM32_DMA2_BASE+STM32_DMA_S0M0AR_OFFSET) +#define STM32_DMA2_S1M0AR (STM32_DMA2_BASE+STM32_DMA_S1M0AR_OFFSET) +#define STM32_DMA2_S2M0AR (STM32_DMA2_BASE+STM32_DMA_S2M0AR_OFFSET) +#define STM32_DMA2_S3M0AR (STM32_DMA2_BASE+STM32_DMA_S3M0AR_OFFSET) +#define STM32_DMA2_S4M0AR (STM32_DMA2_BASE+STM32_DMA_S4M0AR_OFFSET) +#define STM32_DMA2_S5M0AR (STM32_DMA2_BASE+STM32_DMA_S5M0AR_OFFSET) +#define STM32_DMA2_S6M0AR (STM32_DMA2_BASE+STM32_DMA_S6M0AR_OFFSET) +#define STM32_DMA2_S7M0AR (STM32_DMA2_BASE+STM32_DMA_S7M0AR_OFFSET) + +#define STM32_DMA2_SM1AR(n) (STM32_DMA2_BASE+STM32_DMA_SM1AR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA2_S0M1AR (STM32_DMA2_BASE+STM32_DMA_S0M1AR_OFFSET) +#define STM32_DMA2_S1M1AR (STM32_DMA2_BASE+STM32_DMA_S1M1AR_OFFSET) +#define STM32_DMA2_S2M1AR (STM32_DMA2_BASE+STM32_DMA_S2M1AR_OFFSET) +#define STM32_DMA2_S3M1AR (STM32_DMA2_BASE+STM32_DMA_S3M1AR_OFFSET) +#define STM32_DMA2_S4M1AR (STM32_DMA2_BASE+STM32_DMA_S4M1AR_OFFSET) +#define STM32_DMA2_S5M1AR (STM32_DMA2_BASE+STM32_DMA_S5M1AR_OFFSET) +#define STM32_DMA2_S6M1AR (STM32_DMA2_BASE+STM32_DMA_S6M1AR_OFFSET) +#define STM32_DMA2_S7M1AR (STM32_DMA2_BASE+STM32_DMA_S7M1AR_OFFSET) + +#define STM32_DMA2_SFCR(n) (STM32_DMA2_BASE+STM32_DMA_SFCR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA2_S0FCR (STM32_DMA2_BASE+STM32_DMA_S0FCR_OFFSET) +#define STM32_DMA2_S1FCR (STM32_DMA2_BASE+STM32_DMA_S1FCR_OFFSET) +#define STM32_DMA2_S2FCR (STM32_DMA2_BASE+STM32_DMA_S2FCR_OFFSET) +#define STM32_DMA2_S3FCR (STM32_DMA2_BASE+STM32_DMA_S3FCR_OFFSET) +#define STM32_DMA2_S4FCR (STM32_DMA2_BASE+STM32_DMA_S4FCR_OFFSET) +#define STM32_DMA2_S5FCR (STM32_DMA2_BASE+STM32_DMA_S5FCR_OFFSET) +#define STM32_DMA2_S6FCR (STM32_DMA2_BASE+STM32_DMA_S6FCR_OFFSET) +#define STM32_DMA2_S7FCR (STM32_DMA2_BASE+STM32_DMA_S7FCR_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +#define DMA_STREAM_MASK 0x3f +#define DMA_STREAM_FEIF_BIT (1 << 0) /* Bit 0: Stream FIFO error interrupt flag */ +#define DMA_STREAM_DMEIF_BIT (1 << 2) /* Bit 2: Stream direct mode error interrupt flag */ +#define DMA_STREAM_TEIF_BIT (1 << 3) /* Bit 3: Stream Transfer Error flag */ +#define DMA_STREAM_HTIF_BIT (1 << 4) /* Bit 4: Stream Half Transfer flag */ +#define DMA_STREAM_TCIF_BIT (1 << 5) /* Bit 5: Stream Transfer Complete flag */ + +/* DMA interrupt status register and interrupt flag clear register field defintions */ + +#define DMA_INT_STREAM0_SHIFT (0) /* Bits 0-5: DMA Stream 0 interrupt */ +#define DMA_INT_STREAM0_MASK (DMA_STREAM_MASK << DMA_INT_STREAM0_SHIFT) +#define DMA_INT_STREAM1_SHIFT (6) /* Bits 6-11: DMA Stream 1 interrupt */ +#define DMA_INT_STREAM1_MASK (DMA_STREAM_MASK << DMA_INT_STREAM1_SHIFT) +#define DMA_INT_STREAM2_SHIFT (16) /* Bits 16-21: DMA Stream 2 interrupt */ +#define DMA_INT_STREAM2_MASK (DMA_STREAM_MASK << DMA_INT_STREAM2_SHIFT) +#define DMA_INT_STREAM3_SHIFT (22) /* Bits 22-27: DMA Stream 3 interrupt */ +#define DMA_INT_STREAM3_MASK (DMA_STREAM_MASK << DMA_INT_STREAM3_SHIFT) + +#define DMA_INT_STREAM4_SHIFT (0) /* Bits 0-5: DMA Stream 4 interrupt */ +#define DMA_INT_STREAM4_MASK (DMA_STREAM_MASK << DMA_INT_STREAM4_SHIFT) +#define DMA_INT_STREAM5_SHIFT (6) /* Bits 6-11: DMA Stream 5 interrupt */ +#define DMA_INT_STREAM5_MASK (DMA_STREAM_MASK << DMA_INT_STREAM5_SHIFT) +#define DMA_INT_STREAM6_SHIFT (16) /* Bits 16-21: DMA Stream 6 interrupt */ +#define DMA_INT_STREAM6_MASK (DMA_STREAM_MASK << DMA_INT_STREAM6_SHIFT) +#define DMA_INT_STREAM7_SHIFT (22) /* Bits 22-27: DMA Stream 7 interrupt */ +#define DMA_INT_STREAM7_MASK (DMA_STREAM_MASK << DMA_INT_STREAM7_SHIFT) + +/* DMA stream configuration register */ + +#define DMA_SCR_EN (1 << 0) /* Bit 0: Stream enable */ +#define DMA_SCR_DMEIE (1 << 1) /* Bit 1: Direct mode error interrupt enable */ +#define DMA_SCR_TEIE (1 << 2) /* Bit 2: Transfer error interrupt enable */ +#define DMA_SCR_HTIE (1 << 3) /* Bit 3: Half Transfer interrupt enable */ +#define DMA_SCR_TCIE (1 << 4) /* Bit 4: Transfer complete interrupt enable */ +#define DMA_SCR_PFCTRL (1 << 5) /* Bit 5: Peripheral flow controller */ +#define DMA_SCR_DIR_SHIFT (6) /* Bits 6-7: Data transfer direction */ +#define DMA_SCR_DIR_MASK (3 << DMA_SCR_DIR_SHIFT) +# define DMA_SCR_DIR_P2M (0 << DMA_SCR_DIR_SHIFT) /* 00: Peripheral-to-memory */ +# define DMA_SCR_DIR_M2P (1 << DMA_SCR_DIR_SHIFT) /* 01: Memory-to-peripheral */ +# define DMA_SCR_DIR_M2M (2 << DMA_SCR_DIR_SHIFT) /* 10: Memory-to-memory */ +#define DMA_SCR_CIRC (1 << 8) /* Bit 8: Circular mode */ +#define DMA_SCR_PINC (1 << 9) /* Bit 9: Peripheral increment mode */ +#define DMA_SCR_MINC (1 << 10) /* Bit 10: Memory increment mode */ +#define DMA_SCR_PSIZE_SHIFT (11) /* Bits 11-12: Peripheral size */ +#define DMA_SCR_PSIZE_MASK (3 << DMA_SCR_PSIZE_SHIFT) +# define DMA_SCR_PSIZE_8BITS (0 << DMA_SCR_PSIZE_SHIFT) /* 00: 8-bits */ +# define DMA_SCR_PSIZE_16BITS (1 << DMA_SCR_PSIZE_SHIFT) /* 01: 16-bits */ +# define DMA_SCR_PSIZE_32BITS (2 << DMA_SCR_PSIZE_SHIFT) /* 10: 32-bits */ +#define DMA_SCR_MSIZE_SHIFT (13) /* Bits 13-14: Memory size */ +#define DMA_SCR_MSIZE_MASK (3 << DMA_SCR_MSIZE_SHIFT) +# define DMA_SCR_MSIZE_8BITS (0 << DMA_SCR_MSIZE_SHIFT) /* 00: 8-bits */ +# define DMA_SCR_MSIZE_16BITS (1 << DMA_SCR_MSIZE_SHIFT) /* 01: 16-bits */ +# define DMA_SCR_MSIZE_32BITS (2 << DMA_SCR_MSIZE_SHIFT) /* 10: 32-bits */ +#define DMA_SCR_PINCOS (1 << 15) /* Bit 15: Peripheral increment offset size */ +#define DMA_SCR_PL_SHIFT (16) /* Bits 16-17: Stream Priority level */ +#define DMA_SCR_PL_MASK (3 << DMA_SCR_PL_SHIFT) +# define DMA_SCR_PRILO (0 << DMA_SCR_PL_SHIFT) /* 00: Low */ +# define DMA_SCR_PRIMED (1 << DMA_SCR_PL_SHIFT) /* 01: Medium */ +# define DMA_SCR_PRIHI (2 << DMA_SCR_PL_SHIFT) /* 10: High */ +# define DMA_SCR_PRIVERYHI (3 << DMA_SCR_PL_SHIFT) /* 11: Very high */ +#define DMA_SCR_DBM (1 << 18) /* Bit 15: Double buffer mode */ +#define DMA_SCR_CT (1 << 19) /* Bit 19: Current target */ +#define DMA_SCR_PBURST_SHIFT (21) /* Bits 21-22: Peripheral burst transfer configuration */ +#define DMA_SCR_PBURST_MASK (3 << DMA_SCR_PBURST_SHIFT) +# define DMA_SCR_PBURST_SINGLE (0 << DMA_SCR_PBURST_SHIFT) /* 00: Single transfer */ +# define DMA_SCR_PBURST_INCR4 (1 << DMA_SCR_PBURST_SHIFT) /* 01: Incremental burst of 4 beats */ +# define DMA_SCR_PBURST_INCR8 (2 << DMA_SCR_PBURST_SHIFT) /* 10: Incremental burst of 8 beats */ +# define DMA_SCR_PBURST_INCR16 (3 << DMA_SCR_PBURST_SHIFT) /* 11: Incremental burst of 16 beats */ +#define DMA_SCR_MBURST_SHIFT (23) /* Bits 23-24: Memory burst transfer configuration */ +#define DMA_SCR_MBURST_MASK (3 << DMA_SCR_MBURST_SHIFT) +# define DMA_SCR_MBURST_SINGLE (0 << DMA_SCR_MBURST_SHIFT) /* 00: Single transfer */ +# define DMA_SCR_MBURST_INCR4 (1 << DMA_SCR_MBURST_SHIFT) /* 01: Incremental burst of 4 beats */ +# define DMA_SCR_MBURST_INCR8 (2 << DMA_SCR_MBURST_SHIFT) /* 10: Incremental burst of 8 beats */ +# define DMA_SCR_MBURST_INCR16 (3 << DMA_SCR_MBURST_SHIFT) /* 11: Incremental burst of 16 beats */ +#define DMA_SCR_CHSEL_SHIFT (25) /* Bits 25-27: Channel selection */ +#define DMA_SCR_CHSEL_MASK (7 << DMA_SCR_CHSEL_SHIFT) +# define DMA_SCR_CHSEL(n) ((n) << DMA_SCR_CHSEL_SHIFT) + +#define DMA_SCR_ALLINTS (DMA_SCR_DMEIE|DMA_SCR_TEIE|DMA_SCR_HTIE|DMA_SCR_TCIE) + +/* DMA stream number of data register */ + +#define DMA_SNDTR_NDT_SHIFT (0) /* Bits 15-0: Number of data to Transfer */ +#define DMA_SNDTR_NDT_MASK (0xffff << DMA_SNDTR_NDT_SHIFT) + +/* DMA stream n FIFO control register */ + +#define DMA_SFCR_FTH_SHIFT (0) /* Bits 0-1: FIFO threshold selection */ +#define DMA_SFCR_FTH_MASK (3 << DMA_SFCR_FTH_SHIFT) +# define DMA_SFCR_FTH_QUARTER (0 << DMA_SFCR_FTH_SHIFT) /* 1/4 full FIFO */ +# define DMA_SFCR_FTH_HALF (1 << DMA_SFCR_FTH_SHIFT) /* 1/2 full FIFO */ +# define DMA_SFCR_FTH_3QUARTER (2 << DMA_SFCR_FTH_SHIFT) /* 3/4 full FIFO */ +# define DMA_SFCR_FTH_FULL (3 << DMA_SFCR_FTH_SHIFT) /* full FIFO */ +#define DMA_SFCR_DMDIS (1 << 2) /* Bit 2: Direct mode disable */ +#define DMA_SFCR_FS_SHIFT (3) /* Bits 3-5: FIFO status */ +#define DMA_SFCR_FS_MASK (7 << DMA_SFCR_FS_SHIFT) +# define DMA_SFCR_FS_QUARTER (0 << DMA_SFCR_FS_SHIFT) /* 0 < fifo_level < 1/4 */ +# define DMA_SFCR_FS_HALF (1 << DMA_SFCR_FS_SHIFT) /* 1/4 = fifo_level < 1/2 */ +# define DMA_SFCR_FS_3QUARTER (2 << DMA_SFCR_FS_SHIFT) /* 1/2 = fifo_level < 3/4 */ +# define DMA_SFCR_FS_ALMOSTFULL (3 << DMA_SFCR_FS_SHIFT) /* 3/4 = fifo_level < full */ +# define DMA_SFCR_FS_EMPTY (4 << DMA_SFCR_FS_SHIFT) /* FIFO is empty */ +# define DMA_SFCR_FS_FULL (5 << DMA_SFCR_FS_SHIFT) /* FIFO is full */ + /* Bit 6: Reserved */ +#define DMA_SFCR_FEIE (1 << 7) /* Bit 7: FIFO error interrupt enable */ + /* Bits 8-31: Reserved */ + +/* DMA Stream mapping. Each DMA stream has a mapping to several possible + * sources/sinks of data. The requests from peripherals assigned to a stream + * are simply OR'ed together before entering the DMA block. This means that only + * one request on a given stream can be enabled at once. + * + * Alternative stream selections are provided with a numeric suffix like _1, _2, etc. + * The DMA driver, however, will use the pin selection without the numeric suffix. + * Additional definitions are required in the board.h file. For example, if + * SPI3_RX connects via DMA STREAM0, then following should be application-specific + * mapping should be used: + * + * #define DMAMAP_SPI3_RX DMAMAP_SPI3_RX_1 + */ + +#define STM32_DMA_MAP(d,s,c) ((d) << 6 | (s) << 3 | (c)) +#define STM32_DMA_CONTROLLER(m) (((m) >> 6) & 1) +#define STM32_DMA_STREAM(m) (((m) >> 3) & 7) +#define STM32_DMA_CHANNEL(m) ((m) & 7) + +#define DMAMAP_SPI3_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN0) +#define DMAMAP_SPI3_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN0) +#define DMAMAP_SPI2_RX STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN0) +#define DMAMAP_SPI2_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN0) +#define DMAMAP_SPI3_TX_1 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN0) +#define DMAMAP_SPI3_TX_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN0) + +#define DMAMAP_I2C1_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN1) +#define DMAMAP_TIM7_UP_1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN1) +#define DMAMAP_TIM7_UP_2 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN1) +#define DMAMAP_I2C1_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN1) +#define DMAMAP_I2C1_TX_1 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN1) +#define DMAMAP_I2C1_TX_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN1) + +#define DMAMAP_TIM4_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN2) +#define DMAMAP_I2S2_EXT_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN2) +#define DMAMAP_TIM4_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN2) +#define DMAMAP_I2S2_EXT_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN2) +#define DMAMAP_I2S3_EXT_TX STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN2) +#define DMAMAP_TIM4_UP STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN2) +#define DMAMAP_TIM4_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN2) + +#define DMAMAP_I2S3_EXT_RX STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN3) +#define DMAMAP_TIM2_UP_1 STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN3) +#define DMAMAP_TIM2_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN3) +#define DMAMAP_I2C3_RX STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN3) +#define DMAMAP_I2S2_EXT_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN3) +#define DMAMAP_I2C3_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN3) +#define DMAMAP_TIM2_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN3) +#define DMAMAP_TIM2_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN3) +#define DMAMAP_TIM2_CH4_1 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN3) +#define DMAMAP_TIM2_UP_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN3) +#define DMAMAP_TIM2_CH4_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN3) + +#define DMAMAP_UART5_RX STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN4) +#define DMAMAP_USART3_RX STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN4) +#define DMAMAP_UART4_RX STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN4) +#define DMAMAP_USART3_TX_1 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN4) +#define DMAMAP_UART4_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN4) +#define DMAMAP_USART2_RX STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN4) +#define DMAMAP_USART2_TX STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN4) +#define DMAMAP_UART5_TX STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN4) + +#define DMAMAP_TIM3_CH4 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN5) +#define DMAMAP_TIM3_UP STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN5) +#define DMAMAP_TIM3_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN5) +#define DMAMAP_TIM3_TRIG STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN5) +#define DMAMAP_TIM3_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN5) +#define DMAMAP_TIM3_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN5) + +#define DMAMAP_TIM5_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN6) +#define DMAMAP_TIM5_UP_1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN6) +#define DMAMAP_TIM5_CH4_1 STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN6) +#define DMAMAP_TIM5_TRIG_1 STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN6) +#define DMAMAP_TIM5_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN6) +#define DMAMAP_TIM5_CH4_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN6) +#define DMAMAP_TIM5_TRIG_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN6) +#define DMAMAP_TIM5_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN6) +#define DMAMAP_TIM5_UP_2 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN6) + +#define DMAMAP_TIM6_UP STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN7) +#define DMAMAP_I2C2_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN7) +#define DMAMAP_I2C2_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN7) +#define DMAMAP_USART3_TX_2 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN7) +#define DMAMAP_DAC1 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN7) +#define DMAMAP_DAC2 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN7) +#define DMAMAP_I2C2_TX STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN7) + +#define DMAMAP_ADC1_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN0) +#define DMAMAP_TIM8_CH1_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN0) +#define DMAMAP_TIM8_CH2_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN0) +#define DMAMAP_TIM8_CH3_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN0) +#define DMAMAP_ADC1_2 STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN0) +#define DMAMAP_TIM1_CH1_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN0) +#define DMAMAP_TIM1_CH2_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN0) +#define DMAMAP_TIM1_CH3_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN0) + +#define DMAMAP_DCMI_1 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN1) +#define DMAMAP_ADC2_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN1) +#define DMAMAP_ADC2_2 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN1) +#define DMAMAP_DCMI_2 STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN1) + +#define DMAMAP_ADC3_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN2) +#define DMAMAP_ADC3_2 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN2) +#define DMAMAP_CRYP_OUT STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN2) +#define DMAMAP_CRYP_IN STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN2) +#define DMAMAP_HASH_IN STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN2) + +#define DMAMAP_SPI1_RX_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN3) +#define DMAMAP_SPI1_RX_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN3) +#define DMAMAP_SPI1_TX_1 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN3) +#define DMAMAP_SPI1_TX_2 STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN3) + +#define DMAMAP_USART1_RX_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN4) +#define DMAMAP_SDIO_1 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN4) +#define DMAMAP_USART1_RX_2 STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN4) +#define DMAMAP_SDIO_2 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN4) +#define DMAMAP_USART1_TX STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN4) + +#define DMAMAP_USART6_RX_1 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN5) +#define DMAMAP_USART6_RX_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN5) +#define DMAMAP_USART6_TX_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN5) +#define DMAMAP_USART6_TX_2 STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN5) + +#define DMAMAP_TIM1_TRIG_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN6) +#define DMAMAP_TIM1_CH1_2 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN6) +#define DMAMAP_TIM1_CH2_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN6) +#define DMAMAP_TIM1_CH1 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN6) +#define DMAMAP_TIM1_CH4 STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN6) +#define DMAMAP_TIM1_TRIG_2 STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN6) +#define DMAMAP_TIM1_COM STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN6) +#define DMAMAP_TIM1_UP STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN6) +#define DMAMAP_TIM1_CH3_2 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN6) + +#define DMAMAP_TIM8_UP STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN7) +#define DMAMAP_TIM8_CH1_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN7) +#define DMAMAP_TIM8_CH2_2 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN7) +#define DMAMAP_TIM8_CH3_2 STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN7) +#define DMAMAP_TIM8_CH4 STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN7) +#define DMAMAP_TIM8_TRIG STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN7) +#define DMAMAP_TIM8_COM STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN7) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_DMA_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_gpio.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_gpio.h new file mode 100644 index 0000000000..73a0282442 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_gpio.h @@ -0,0 +1,370 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f20xxx_gpio.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_GPIO_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_GPIO_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#define STM32_NGPIO_PORTS ((STM32_NGPIO + 15) >> 4) + +/* Register Offsets *****************************************************************/ + +#define STM32_GPIO_MODER_OFFSET 0x0000 /* GPIO port mode register */ +#define STM32_GPIO_OTYPER_OFFSET 0x0004 /* GPIO port output type register */ +#define STM32_GPIO_OSPEED_OFFSET 0x0008 /* GPIO port output speed register */ +#define STM32_GPIO_PUPDR_OFFSET 0x000c /* GPIO port pull-up/pull-down register */ +#define STM32_GPIO_IDR_OFFSET 0x0010 /* GPIO port input data register */ +#define STM32_GPIO_ODR_OFFSET 0x0014 /* GPIO port output data register */ +#define STM32_GPIO_BSRR_OFFSET 0x0018 /* GPIO port bit set/reset register */ +#define STM32_GPIO_LCKR_OFFSET 0x001c /* GPIO port configuration lock register */ +#define STM32_GPIO_AFRL_OFFSET 0x0020 /* GPIO alternate function low register */ +#define STM32_GPIO_ARFH_OFFSET 0x0024 /* GPIO alternate function high register */ + +/* Register Addresses ***************************************************************/ + +#if STM32_NGPIO_PORTS > 0 +# define STM32_GPIOA_MODER (STM32_GPIOA_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOA_OTYPER (STM32_GPIOA_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOA_OSPEED (STM32_GPIOA_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOA_PUPDR (STM32_GPIOA_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOA_IDR (STM32_GPIOA_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOA_ODR (STM32_GPIOA_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOA_BSRR (STM32_GPIOA_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOA_LCKR (STM32_GPIOA_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOA_AFRL (STM32_GPIOA_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOA_ARFH (STM32_GPIOA_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 1 +# define STM32_GPIOB_MODER (STM32_GPIOB_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOB_OTYPER (STM32_GPIOB_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOB_OSPEED (STM32_GPIOB_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOB_PUPDR (STM32_GPIOB_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOB_IDR (STM32_GPIOB_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOB_ODR (STM32_GPIOB_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOB_BSRR (STM32_GPIOB_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOB_LCKR (STM32_GPIOB_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOB_AFRL (STM32_GPIOB_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOB_ARFH (STM32_GPIOB_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 2 +# define STM32_GPIOC_MODER (STM32_GPIOC_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOC_OTYPER (STM32_GPIOC_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOC_OSPEED (STM32_GPIOC_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOC_PUPDR (STM32_GPIOC_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOC_IDR (STM32_GPIOC_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOC_ODR (STM32_GPIOC_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOC_BSRR (STM32_GPIOC_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOC_LCKR (STM32_GPIOC_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOC_AFRL (STM32_GPIOC_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOC_ARFH (STM32_GPIOC_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 3 +# define STM32_GPIOD_MODER (STM32_GPIOD_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOD_OTYPER (STM32_GPIOD_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOD_OSPEED (STM32_GPIOD_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOD_PUPDR (STM32_GPIOD_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOD_IDR (STM32_GPIOD_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOD_ODR (STM32_GPIOD_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOD_BSRR (STM32_GPIOD_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOD_LCKR (STM32_GPIOD_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOD_AFRL (STM32_GPIOD_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOD_ARFH (STM32_GPIOD_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 4 +# define STM32_GPIOE_MODER (STM32_GPIOE_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOE_OTYPER (STM32_GPIOE_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOE_OSPEED (STM32_GPIOE_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOE_PUPDR (STM32_GPIOE_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOE_IDR (STM32_GPIOE_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOE_ODR (STM32_GPIOE_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOE_BSRR (STM32_GPIOE_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOE_LCKR (STM32_GPIOE_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOE_AFRL (STM32_GPIOE_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOE_ARFH (STM32_GPIOE_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 5 +# define STM32_GPIOF_MODER (STM32_GPIOF_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOF_OTYPER (STM32_GPIOF_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOF_OSPEED (STM32_GPIOF_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOF_PUPDR (STM32_GPIOF_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOF_IDR (STM32_GPIOF_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOF_ODR (STM32_GPIOF_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOF_BSRR (STM32_GPIOF_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOF_LCKR (STM32_GPIOF_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOF_AFRL (STM32_GPIOF_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOF_ARFH (STM32_GPIOF_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 6 +# define STM32_GPIOG_MODER (STM32_GPIOG_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOG_OTYPER (STM32_GPIOG_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOG_OSPEED (STM32_GPIOG_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOG_PUPDR (STM32_GPIOG_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOG_IDR (STM32_GPIOG_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOG_ODR (STM32_GPIOG_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOG_BSRR (STM32_GPIOG_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOG_LCKR (STM32_GPIOG_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOG_AFRL (STM32_GPIOG_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOG_ARFH (STM32_GPIOG_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 7 +# define STM32_GPIOH_MODER (STM32_GPIOH_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOH_OTYPER (STM32_GPIOH_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOH_OSPEED (STM32_GPIOH_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOH_PUPDR (STM32_GPIOH_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOH_IDR (STM32_GPIOH_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOH_ODR (STM32_GPIOH_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOH_BSRR (STM32_GPIOH_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOH_LCKR (STM32_GPIOH_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOH_AFRL (STM32_GPIOH_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOH_ARFH (STM32_GPIOH_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 8 +# define STM32_GPIOI_MODER (STM32_GPIOI_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOI_OTYPER (STM32_GPIOI_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOI_OSPEED (STM32_GPIOI_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOI_PUPDR (STM32_GPIOI_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOI_IDR (STM32_GPIOI_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOI_ODR (STM32_GPIOI_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOI_BSRR (STM32_GPIOI_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOI_LCKR (STM32_GPIOI_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOI_AFRL (STM32_GPIOI_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOI_ARFH (STM32_GPIOI_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +/* Register Bitfield Definitions ****************************************************/ + +/* GPIO port mode register */ + +#define GPIO_MODER_INPUT (0) /* Input */ +#define GPIO_MODER_OUTPUT (1) /* General purpose output mode */ +#define GPIO_MODER_ALT (2) /* Alternate mode */ +#define GPIO_MODER_ANALOG (3) /* Analog mode */ + +#define GPIO_MODER_SHIFT(n) ((n) << 1) +#define GPIO_MODER_MASK(n) (3 << GPIO_MODER_SHIFT(n)) + +#define GPIO_MODER0_SHIFT (0) +#define GPIO_MODER0_MASK (3 << GPIO_MODER0_SHIFT) +#define GPIO_MODER1_SHIFT (2) +#define GPIO_MODER1_MASK (3 << GPIO_MODER1_SHIFT) +#define GPIO_MODER2_SHIFT (4) +#define GPIO_MODER2_MASK (3 << GPIO_MODER2_SHIFT) +#define GPIO_MODER3_SHIFT (6) +#define GPIO_MODER3_MASK (3 << GPIO_MODER3_SHIFT) +#define GPIO_MODER4_SHIFT (8) +#define GPIO_MODER4_MASK (3 << GPIO_MODER4_SHIFT) +#define GPIO_MODER5_SHIFT (10) +#define GPIO_MODER5_MASK (3 << GPIO_MODER5_SHIFT) +#define GPIO_MODER6_SHIFT (12) +#define GPIO_MODER6_MASK (3 << GPIO_MODER6_SHIFT) +#define GPIO_MODER7_SHIFT (14) +#define GPIO_MODER7_MASK (3 << GPIO_MODER7_SHIFT) +#define GPIO_MODER8_SHIFT (16) +#define GPIO_MODER8_MASK (3 << GPIO_MODER8_SHIFT) +#define GPIO_MODER9_SHIFT (18) +#define GPIO_MODER9_MASK (3 << GPIO_MODER9_SHIFT) +#define GPIO_MODER10_SHIFT (20) +#define GPIO_MODER10_MASK (3 << GPIO_MODER10_SHIFT) +#define GPIO_MODER11_SHIFT (22) +#define GPIO_MODER11_MASK (3 << GPIO_MODER11_SHIFT) +#define GPIO_MODER12_SHIFT (24) +#define GPIO_MODER12_MASK (3 << GPIO_MODER12_SHIFT) +#define GPIO_MODER13_SHIFT (26) +#define GPIO_MODER13_MASK (3 << GPIO_MODER13_SHIFT) +#define GPIO_MODER14_SHIFT (28) +#define GPIO_MODER14_MASK (3 << GPIO_MODER14_SHIFT) +#define GPIO_MODER15_SHIFT (30) +#define GPIO_MODER15_MASK (3 << GPIO_MODER15_SHIFT) + +/* GPIO port output type register */ + +#define GPIO_OTYPER_OD(n) (1 << (n)) /* 1=Output open-drain */ +#define GPIO_OTYPER_PP(n) (0) /* 0=Ouput push-pull */ + +/* GPIO port output speed register */ + +#define GPIO_OSPEED_2MHz (0) /* 2 MHz Low speed */ +#define GPIO_OSPEED_25MHz (1) /* 25 MHz Medium speed */ +#define GPIO_OSPEED_50MHz (2) /* 50 MHz Fast speed */ +#define GPIO_OSPEED_100MHz (3) /* 100 MHz High speed on 30 pF (80 MHz Output max speed on 15 pF) */ + +#define GPIO_OSPEED_SHIFT(n) ((n) << 1) +#define GPIO_OSPEED_MASK(n) (3 << GPIO_OSPEED_SHIFT(n)) + +#define GPIO_OSPEED0_SHIFT (0) +#define GPIO_OSPEED0_MASK (3 << GPIO_OSPEED0_SHIFT) +#define GPIO_OSPEED1_SHIFT (2) +#define GPIO_OSPEED1_MASK (3 << GPIO_OSPEED1_SHIFT) +#define GPIO_OSPEED2_SHIFT (4) +#define GPIO_OSPEED2_MASK (3 << GPIO_OSPEED2_SHIFT) +#define GPIO_OSPEED3_SHIFT (6) +#define GPIO_OSPEED3_MASK (3 << GPIO_OSPEED3_SHIFT) +#define GPIO_OSPEED4_SHIFT (8) +#define GPIO_OSPEED4_MASK (3 << GPIO_OSPEED4_SHIFT) +#define GPIO_OSPEED5_SHIFT (10) +#define GPIO_OSPEED5_MASK (3 << GPIO_OSPEED5_SHIFT) +#define GPIO_OSPEED6_SHIFT (12) +#define GPIO_OSPEED6_MASK (3 << GPIO_OSPEED6_SHIFT) +#define GPIO_OSPEED7_SHIFT (14) +#define GPIO_OSPEED7_MASK (3 << GPIO_OSPEED7_SHIFT) +#define GPIO_OSPEED8_SHIFT (16) +#define GPIO_OSPEED8_MASK (3 << GPIO_OSPEED8_SHIFT) +#define GPIO_OSPEED9_SHIFT (18) +#define GPIO_OSPEED9_MASK (3 << GPIO_OSPEED9_SHIFT) +#define GPIO_OSPEED10_SHIFT (20) +#define GPIO_OSPEED10_MASK (3 << GPIO_OSPEED10_SHIFT) +#define GPIO_OSPEED11_SHIFT (22) +#define GPIO_OSPEED11_MASK (3 << GPIO_OSPEED11_SHIFT) +#define GPIO_OSPEED12_SHIFT (24) +#define GPIO_OSPEED12_MASK (3 << GPIO_OSPEED12_SHIFT) +#define GPIO_OSPEED13_SHIFT (26) +#define GPIO_OSPEED13_MASK (3 << GPIO_OSPEED13_SHIFT) +#define GPIO_OSPEED14_SHIFT (28) +#define GPIO_OSPEED14_MASK (3 << GPIO_OSPEED14_SHIFT) +#define GPIO_OSPEED15_SHIFT (30) +#define GPIO_OSPEED15_MASK (3 << GPIO_OSPEED15_SHIFT) + +/* GPIO port pull-up/pull-down register */ + +#define GPIO_PUPDR_NONE (0) /* No pull-up, pull-down */ +#define GPIO_PUPDR_PULLUP (1) /* Pull-up */ +#define GPIO_PUPDR_PULLDOWN (2) /* Pull-down */ + +#define GPIO_PUPDR_SHIFT(n) ((n) << 1) +#define GPIO_PUPDR_MASK(n) (3 << GPIO_PUPDR_SHIFT(n)) + +#define GPIO_PUPDR0_SHIFT (0) +#define GPIO_PUPDR0_MASK (3 << GPIO_PUPDR0_SHIFT) +#define GPIO_PUPDR1_SHIFT (2) +#define GPIO_PUPDR1_MASK (3 << GPIO_PUPDR1_SHIFT) +#define GPIO_PUPDR2_SHIFT (4) +#define GPIO_PUPDR2_MASK (3 << GPIO_PUPDR2_SHIFT) +#define GPIO_PUPDR3_SHIFT (6) +#define GPIO_PUPDR3_MASK (3 << GPIO_PUPDR3_SHIFT) +#define GPIO_PUPDR4_SHIFT (8) +#define GPIO_PUPDR4_MASK (3 << GPIO_PUPDR4_SHIFT) +#define GPIO_PUPDR5_SHIFT (10) +#define GPIO_PUPDR5_MASK (3 << GPIO_PUPDR5_SHIFT) +#define GPIO_PUPDR6_SHIFT (12) +#define GPIO_PUPDR6_MASK (3 << GPIO_PUPDR6_SHIFT) +#define GPIO_PUPDR7_SHIFT (14) +#define GPIO_PUPDR7_MASK (3 << GPIO_PUPDR7_SHIFT) +#define GPIO_PUPDR8_SHIFT (16) +#define GPIO_PUPDR8_MASK (3 << GPIO_PUPDR8_SHIFT) +#define GPIO_PUPDR9_SHIFT (18) +#define GPIO_PUPDR9_MASK (3 << GPIO_PUPDR9_SHIFT) +#define GPIO_PUPDR10_SHIFT (20) +#define GPIO_PUPDR10_MASK (3 << GPIO_PUPDR10_SHIFT) +#define GPIO_PUPDR11_SHIFT (22) +#define GPIO_PUPDR11_MASK (3 << GPIO_PUPDR11_SHIFT) +#define GPIO_PUPDR12_SHIFT (24) +#define GPIO_PUPDR12_MASK (3 << GPIO_PUPDR12_SHIFT) +#define GPIO_PUPDR13_SHIFT (26) +#define GPIO_PUPDR13_MASK (3 << GPIO_PUPDR13_SHIFT) +#define GPIO_PUPDR14_SHIFT (28) +#define GPIO_PUPDR14_MASK (3 << GPIO_PUPDR14_SHIFT) +#define GPIO_PUPDR15_SHIFT (30) +#define GPIO_PUPDR15_MASK (3 << GPIO_PUPDR15_SHIFT) + +/* GPIO port input data register */ + +#define GPIO_IDR(n) (1 << (n)) + +/* GPIO port output data register */ + +#define GPIO_ODR(n) (1 << (n)) + +/* GPIO port bit set/reset register */ + +#define GPIO_BSRR_SET(n) (1 << (n)) +#define GPIO_BSRR_RESET(n) (1 << ((n)+16)) + +/* GPIO port configuration lock register */ + +#define GPIO_LCKR(n) (1 << (n)) +#define GPIO_LCKK (1 << 16) /* Lock key */ + +/* GPIO alternate function low/high register */ + +#define GPIO_AFR_SHIFT(n) ((n) << 2) +#define GPIO_AFR_MASK(n) (15 << GPIO_AFR_SHIFT(n)) + +#define GPIO_AFRL0_SHIFT (0) +#define GPIO_AFRL0_MASK (15 << GPIO_AFRL0_SHIFT) +#define GPIO_AFRL1_SHIFT (4) +#define GPIO_AFRL1_MASK (15 << GPIO_AFRL1_SHIFT) +#define GPIO_AFRL2_SHIFT (8) +#define GPIO_AFRL2_MASK (15 << GPIO_AFRL2_SHIFT) +#define GPIO_AFRL3_SHIFT (12) +#define GPIO_AFRL3_MASK (15 << GPIO_AFRL3_SHIFT) +#define GPIO_AFRL4_SHIFT (16) +#define GPIO_AFRL4_MASK (15 << GPIO_AFRL4_SHIFT) +#define GPIO_AFRL5_SHIFT (20) +#define GPIO_AFRL5_MASK (15 << GPIO_AFRL5_SHIFT) +#define GPIO_AFRL6_SHIFT (24) +#define GPIO_AFRL6_MASK (15 << GPIO_AFRL6_SHIFT) +#define GPIO_AFRL7_SHIFT (28) +#define GPIO_AFRL7_MASK (15 << GPIO_AFRL7_SHIFT) + +#define GPIO_AFRH8_SHIFT (0) +#define GPIO_AFRH8_MASK (15 << GPIO_AFRH8_SHIFT) +#define GPIO_AFRH9_SHIFT (4) +#define GPIO_AFRH9_MASK (15 << GPIO_AFRH9_SHIFT) +#define GPIO_AFRH10_SHIFT (8) +#define GPIO_AFRH10_MASK (15 << GPIO_AFRH10_SHIFT) +#define GPIO_AFRH11_SHIFT (12) +#define GPIO_AFRH11_MASK (15 << GPIO_AFRH11_SHIFT) +#define GPIO_AFRH12_SHIFT (16) +#define GPIO_AFRH12_MASK (15 << GPIO_AFRH12_SHIFT) +#define GPIO_AFRH13_SHIFT (20) +#define GPIO_AFRH13_MASK (15 << GPIO_AFRH13_SHIFT) +#define GPIO_AFRH14_SHIFT (24) +#define GPIO_AFRH14_MASK (15 << GPIO_AFRH14_SHIFT) +#define GPIO_AFRH15_SHIFT (28) +#define GPIO_AFRH15_MASK (15 << GPIO_AFRH15_SHIFT) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_GPIO_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_memorymap.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_memorymap.h new file mode 100644 index 0000000000..2fa7056076 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_memorymap.h @@ -0,0 +1,197 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f20xxx_memorymap.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_MEMORYMAP_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_MEMORYMAP_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* STM32F20XXX Address Blocks *******************************************************/ + +#define STM32_CODE_BASE 0x00000000 /* 0x00000000-0x1fffffff: 512Mb code block */ +#define STM32_SRAM_BASE 0x20000000 /* 0x20000000-0x3fffffff: 512Mb sram block */ +#define STM32_PERIPH_BASE 0x40000000 /* 0x40000000-0x5fffffff: 512Mb peripheral block */ +#define STM32_FSMC_BASE12 0x60000000 /* 0x60000000-0x7fffffff: 512Mb FSMC bank1&2 block */ +#define STM32_FSMC_BASE34 0x80000000 /* 0x80000000-0x8fffffff: 512Mb FSMC bank3&4 block */ +#define STM32_FSMC_BASE 0xa0000000 /* 0xa0000000-0xbfffffff: 512Mb FSMC register block */ + /* 0xc0000000-0xdfffffff: 512Mb (not used) */ +#define STM32_CORTEX_BASE 0xe0000000 /* 0xe0000000-0xffffffff: 512Mb Cortex-M4 block */ + +/* Code Base Addresses **************************************************************/ + +#define STM32_BOOT_BASE 0x00000000 /* 0x00000000-0x000fffff: Aliased boot memory */ + /* 0x00100000-0x07ffffff: Reserved */ +#define STM32_FLASH_BASE 0x08000000 /* 0x08000000-0x080fffff: FLASH memory */ + /* 0x08100000-0x0fffffff: Reserved */ +#define STM32_CCMRAM_BASE 0x10000000 /* 0x10000000-0x1000ffff: 64Kb CCM data RAM */ + /* 0x10010000-0x1ffeffff: Reserved */ +#define STM32_SYSMEM_BASE 0x1fff0000 /* 0x1fff0000-0x1fff7a0f: System memory */ + /* 0x1fff7a10-0x1fff7fff: Reserved */ +#define STM32_OPTION_BASE 0x1fffc000 /* 0x1fffc000-0x1fffc007: Option bytes */ + /* 0x1fffc008-0x1fffffff: Reserved */ + +/* SRAM Base Addresses **************************************************************/ + + /* 0x20000000-0x2001bfff: 112Kb aliased by bit-banding */ + /* 0x2001c000-0x2001ffff: 16Kb aliased by bit-banding */ +#define STM32_SRAMBB_BASE 0x22000000 /* 0x22000000- : SRAM bit-band region */ + +/* Peripheral Base Addresses ********************************************************/ + +#define STM32_APB1_BASE 0x40000000 /* 0x40000000-0x400023ff: APB1 */ + /* 0x40002400-0x400027ff: Reserved */ + /* 0x40002800-0x400077ff: APB1 */ + /* 0x40007800-0x4000ffff: Reserved */ +#define STM32_APB2_BASE 0x40010000 /* 0x40010000-0x400023ff: APB2 */ + /* 0x40013400-0x400137ff: Reserved */ + /* 0x40013800-0x40013bff: SYSCFG */ +#define STM32_EXTI_BASE 0x40013c00 /* 0x40013c00-0x40013fff: EXTI */ + /* 0x40014000-0x40014bff: APB2 */ + /* 0x40014c00-0x4001ffff: Reserved */ +#define STM32_AHB1_BASE 0x40020000 /* 0x40020000-0x400223ff: APB1 */ + /* 0x40022400-0x40022fff: Reserved */ + /* 0x40023000-0x400233ff: CRC */ + /* 0x40023400-0x400237ff: Reserved */ + /* 0x40023800-0x40023bff: Reset and Clock control RCC */ + /* 0x40023c00-0x400293ff: AHB1 (?) */ + /* 0x40029400-0x4fffffff: Reserved (?) */ +#define STM32_AHB2_BASE 0x50000000 /* 0x50000000-0x5003ffff: AHB2 */ + /* 0x50040000-0x5004ffff: Reserved */ + /* 0x50050000-0x500503ff: AHB2 */ + /* 0x50050400-0x500607ff: Reserved */ + /* 0x50060800-0x50060bff: AHB2 */ + /* 0x50060c00-0x5fffffff: Reserved */ + +/* FSMC Base Addresses **************************************************************/ + +#define STM32_AHB3_BASE 0x60000000 /* 0x60000000-0xa0000fff: AHB3 */ + +/* APB1 Base Addresses **************************************************************/ + +#define STM32_TIM2_BASE 0x40000000 /* 0x40000000-0x400003ff: TIM2 timer */ +#define STM32_TIM3_BASE 0x40000400 /* 0x40000400-0x400007ff: TIM3 timer */ +#define STM32_TIM4_BASE 0x40000800 /* 0x40000800-0x40000bff: TIM4 timer */ +#define STM32_TIM5_BASE 0x40000c00 /* 0x40000c00-0x40000fff: TIM5 timer */ +#define STM32_TIM6_BASE 0x40001000 /* 0x40001000-0x400013ff: TIM6 timer */ +#define STM32_TIM7_BASE 0x40001400 /* 0x40001400-0x400017ff: TIM7 timer */ +#define STM32_TIM12_BASE 0x40001800 /* 0x40001800-0x40001bff: TIM12 timer */ +#define STM32_TIM13_BASE 0x40001c00 /* 0x40001c00-0x40001fff: TIM13 timer */ +#define STM32_TIM14_BASE 0x40002000 /* 0x40002000-0x400023ff: TIM14 timer */ +#define STM32_RTC_BASE 0x40002800 /* 0x40002800-0x40002bff: RTC & BKP registers */ +#define STM32_BKP_BASE 0x40002850 +#define STM32_WWDG_BASE 0x40002c00 /* 0x40002c00-0x40002fff: Window watchdog (WWDG) */ +#define STM32_IWDG_BASE 0x40003000 /* 0x40003000-0x400033ff: Independent watchdog (IWDG) */ +#define STM32_I2S2EXT_BASE 0x40003400 /* 0x40003400-0x400037ff: I2S2ext */ +#define STM32_SPI2_BASE 0x40003800 /* 0x40003800-0x40003bff: SPI2/I2S2 */ +#define STM32_I2S2_BASE 0x40003800 +#define STM32_SPI3_BASE 0x40003c00 /* 0x40003c00-0x40003fff: SPI3/I2S3 */ +#define STM32_I2S3_BASE 0x40003c00 +#define STM32_I2S3EXT_BASE 0x40004000 /* 0x40003400-0x400043ff: I2S3ext */ +#define STM32_USART2_BASE 0x40004400 /* 0x40004400-0x400047ff: USART2 */ +#define STM32_USART3_BASE 0x40004800 /* 0x40004800-0x40004bff: USART3 */ +#define STM32_UART4_BASE 0x40004c00 /* 0x40004c00-0x40004fff: UART4 */ +#define STM32_UART5_BASE 0x40005000 /* 0x40005000-0x400053ff: UART5 */ +#define STM32_I2C1_BASE 0x40005400 /* 0x40005400-0x400057ff: I2C1 */ +#define STM32_I2C2_BASE 0x40005800 /* 0x40005800-0x40005Bff: I2C2 */ +#define STM32_I2C3_BASE 0x40005c00 /* 0x40005c00-0x40005fff: I2C3 */ +#define STM32_CAN1_BASE 0x40006400 /* 0x40006400-0x400067ff: bxCAN1 */ +#define STM32_CAN2_BASE 0x40006800 /* 0x40006800-0x40006bff: bxCAN2 */ +#define STM32_PWR_BASE 0x40007000 /* 0x40007000-0x400073ff: Power control PWR */ +#define STM32_DAC_BASE 0x40007400 /* 0x40007400-0x400077ff: DAC */ + +/* APB2 Base Addresses **************************************************************/ + +#define STM32_TIM1_BASE 0x40010000 /* 0x40010000-0x400103ff: TIM1 timer */ +#define STM32_TIM8_BASE 0x40010400 /* 0x40010400-0x400107ff: TIM8 timer */ +#define STM32_USART1_BASE 0x40011000 /* 0x40011000-0x400113ff: USART1 */ +#define STM32_USART6_BASE 0x40011400 /* 0x40011400-0x400117ff: USART6 */ +#define STM32_ADC_BASE 0x40012000 /* 0x40012000-0x400123ff: ADC1-3 */ +# define STM32_ADC1_BASE 0x40012000 /* ADC1 */ +# define STM32_ADC2_BASE 0x40012100 /* ADC2 */ +# define STM32_ADC3_BASE 0x40012200 /* ADC3 */ +# define STM32_ADCCMN_BASE 0x40012300 /* Common */ +#define STM32_SDIO_BASE 0x40012c00 /* 0x40012c00-0x40012fff: SDIO */ +#define STM32_SPI1_BASE 0x40013000 /* 0x40013000-0x400133ff: SPI1 */ +#define STM32_SYSCFG_BASE 0x40013800 /* 0x40013800-0x40013bff: SYSCFG */ +#define STM32_EXTI_BASE 0x40013c00 /* 0x40013c00-0x40013fff: EXTI */ +#define STM32_TIM9_BASE 0x40014000 /* 0x40014000-0x400143ff: TIM9 timer */ +#define STM32_TIM10_BASE 0x40014400 /* 0x40014400-0x400147ff: TIM10 timer */ +#define STM32_TIM11_BASE 0x40014800 /* 0x40014800-0x40014bff: TIM11 timer */ + +/* AHB1 Base Addresses **************************************************************/ + +#define STM32_GPIOA_BASE 0x40020000 /* 0x40020000-0x400203ff: GPIO Port A */ +#define STM32_GPIOB_BASE 0x40020400 /* 0x40020400-0x400207ff: GPIO Port B */ +#define STM32_GPIOC_BASE 0x40020800 /* 0x40020800-0x40020bff: GPIO Port C */ +#define STM32_GPIOD_BASE 0X40020C00 /* 0x40020c00-0x40020fff: GPIO Port D */ +#define STM32_GPIOE_BASE 0x40021000 /* 0x40021000-0x400213ff: GPIO Port E */ +#define STM32_GPIOF_BASE 0x40021400 /* 0x40021400-0x400217ff: GPIO Port F */ +#define STM32_GPIOG_BASE 0x40021800 /* 0x40021800-0x40021bff: GPIO Port G */ +#define STM32_GPIOH_BASE 0x40021C00 /* 0x40021C00-0x40021fff: GPIO Port H */ +#define STM32_GPIOI_BASE 0x40022000 /* 0x40022000-0x400223ff: GPIO Port I */ +#define STM32_CRC_BASE 0x40023000 /* 0x40023000-0x400233ff: CRC */ +#define STM32_RCC_BASE 0x40023800 /* 0x40023800-0x40023bff: Reset and Clock control RCC */ +#define STM32_FLASHIF_BASE 0x40023c00 /* 0x40023c00-0x40023fff: Flash memory interface */ +#define STM32_BKPSRAM_BASE 0x40024000 /* 0x40024000-0x40024fff: Backup SRAM (BKPSRAM) */ +#define STM32_DMA1_BASE 0x40026000 /* 0x40026000-0x400263ff: DMA1 */ +#define STM32_DMA2_BASE 0x40026400 /* 0x40026400-0x400267ff: DMA2 */ +#define STM32_ETHERNET_BASE 0x40028000 /* 0x40028000-0x400283ff: Ethernet MAC */ + /* 0x40028400-0x400287ff: Ethernet MAC */ + /* 0x40028800-0x40028bff: Ethernet MAC */ + /* 0x40028c00-0x40028fff: Ethernet MAC */ + /* 0x40029000-0x400293ff: Ethernet MAC */ +#define STM32_OTGHS_BASE 0x40040000 /* 0x40040000-0x4007ffff: USB OTG HS */ +#define STM32_PERIPHBB_BASE 0x42000000 /* Peripheral bit-band region */ + +/* AHB2 Base Addresses **************************************************************/ + +#define STM32_OTGFS_BASE 0x50000000 /* 0x50000000-0x5003ffff: USB OTG FS */ +#define STM32_DCMI_BASE 0x50050000 /* 0x50050000-0x500503ff: DCMI */ +#define STM32_CRYP_BASE 0x50060000 /* 0x50060000-0x500603ff: CRYP */ +#define STM32_HASH_BASE 0x50060400 /* 0x50060400-0x500607ff: HASH */ +#define STM32_RNG_BASE 0x50060800 /* 0x50060800-0x50060bff: RNG */ + +/* Cortex-M4 Base Addresses *********************************************************/ +/* Other registers -- see armv7-m/nvic.h for standard Cortex-M3 registers in this + * address range + */ + +#define STM32_SCS_BASE 0xe000e000 +#define STM32_DEBUGMCU_BASE 0xe0042000 + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_MEMORYMAP_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_pinmap.h new file mode 100644 index 0000000000..2c8587855e --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_pinmap.h @@ -0,0 +1,695 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f20xxx_pinmap.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_PINMAP_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_PINMAP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "stm32_gpio.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Alternate Pin Functions. All members of the STM32F20xxx family share the same + * pin multiplexing (although they may differ in the pins physically available). + * + * Alternative pin selections are provided with a numeric suffix like _1, _2, etc. + * Drivers, however, will use the pin selection without the numeric suffix. + * Additional definitions are required in the board.h file. For example, if + * CAN1_RX connects vis PA11 on some board, then the following definitions should + * appear inthe board.h header file for that board: + * + * #define GPIO_CAN1_RX GPIO_CAN1_RX_1 + * + * The driver will then automatically configre PA11 as the CAN1 RX pin. + */ + +/* WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! + * Additional effort is required to select specific GPIO options such as frequency, + * open-drain/push-pull, and pull-up/down! Just the basics are defined for most + * pins in this file. + */ + +/* ADC */ + +#define GPIO_ADC1_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC1_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC1_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC1_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC1_IN4 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC1_IN5 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC1_IN6 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC1_IN7 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC1_IN8 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC1_IN9 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN1) +#define GPIO_ADC1_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC1_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC1_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC1_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC1_IN14 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC1_IN15 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN5) + +#define GPIO_ADC2_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC2_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC2_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC2_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC2_IN4 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC2_IN5 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC2_IN6 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC2_IN7 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC2_IN8 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC2_IN9 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN1) +#define GPIO_ADC2_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC2_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC2_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC2_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC2_IN14 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC2_IN15 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN5) + +#define GPIO_ADC3_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC3_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC3_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC3_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC3_IN4 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN6) +#define GPIO_ADC3_IN5 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN7) +#define GPIO_ADC3_IN6 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN8) +#define GPIO_ADC3_IN7 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN9) +#define GPIO_ADC3_IN9 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN3) +#define GPIO_ADC3_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC3_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC3_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC3_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC3_IN14 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN4) +#define GPIO_ADC3_IN15 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN5) + +/* CAN */ + +#define GPIO_CAN1_RX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11) +#define GPIO_CAN1_RX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) +#define GPIO_CAN1_RX_3 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN0) +#define GPIO_CAN1_RX_4 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN9) +#define GPIO_CAN1_TX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN12) +#define GPIO_CAN1_TX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) +#define GPIO_CAN1_TX_3 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN1) +#define GPIO_CAN1_TX_4 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN13) + +#define GPIO_CAN2_RX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12) +#define GPIO_CAN2_RX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5) +#define GPIO_CAN2_TX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN13) +#define GPIO_CAN2_TX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6) + +/* DAC -" Once the DAC channelx is enabled, the corresponding GPIO pin + * (PA4 or PA5) is automatically connected to the analog converter output + * (DAC_OUTx). In order to avoid parasitic consumption, the PA4 or PA5 pin + * should first be configured to analog (AIN)". + */ + +#define GPIO_DAC1_OUT (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4) +#define GPIO_DAC2_OUT (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5) + +/* Digital Camera Interface (DCMI) */ + +#define GPIO_DCMI_D0_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN9) +#define GPIO_DCMI_D0_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN6) +#define GPIO_DCMI_D0_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN9) +#define GPIO_DCMI_D1_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN10) +#define GPIO_DCMI_D1_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN7) +#define GPIO_DCMI_D1_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN10) +#define GPIO_DCMI_D2_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN8) +#define GPIO_DCMI_D2_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN0) +#define GPIO_DCMI_D2_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN11) +#define GPIO_DCMI_D3_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN9) +#define GPIO_DCMI_D3_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN1) +#define GPIO_DCMI_D3_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN12) +#define GPIO_DCMI_D4_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN11) +#define GPIO_DCMI_D4_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN4) +#define GPIO_DCMI_D4_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN14) +#define GPIO_DCMI_D5_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN6) +#define GPIO_DCMI_D5_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN4) +#define GPIO_DCMI_D6_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN8) +#define GPIO_DCMI_D6_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN5) +#define GPIO_DCMI_D6_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN6) +#define GPIO_DCMI_D7_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN9) +#define GPIO_DCMI_D7_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN6) +#define GPIO_DCMI_D7_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN7) +#define GPIO_DCMI_D8_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN10) +#define GPIO_DCMI_D8_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN1) +#define GPIO_DCMI_D9_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN12) +#define GPIO_DCMI_D9_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN2) +#define GPIO_DCMI_D10_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN5) +#define GPIO_DCMI_D10_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN3) +#define GPIO_DCMI_D11_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTD|GPIO_PIN2) +#define GPIO_DCMI_D11_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN15) +#define GPIO_DCMI_D12 (GPIO_ALT|GPIO_AF13|GPIO_PORTF|GPIO_PIN11) +#define GPIO_DCMI_D13_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTG|GPIO_PIN15) +#define GPIO_DCMI_D13_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN0) +#define GPIO_DCMI_HSYNC_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN4) +#define GPIO_DCMI_HSYNC_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN8) +#define GPIO_DCMI_PIXCK (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN6) +#define GPIO_DCMI_VSYNC_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN7) +#define GPIO_DCMI_VSYNC_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN5) + +/* Clocks outputs */ + +#define GPIO_MCO1 (GPIO_ALT|GPIO_AF0|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) +#define GPIO_MCO2 (GPIO_ALT|GPIO_AF0|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) + +/* Ethernet MAC */ + +#define GPIO_ETH_MDC (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ETH_MDIO (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ETH_MII_COL_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ETH_MII_COL_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN3) +#define GPIO_ETH_MII_CRS_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ETH_MII_CRS_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN2) +#define GPIO_ETH_MII_RXD0 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ETH_MII_RXD1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN5) +#define GPIO_ETH_MII_RXD2_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ETH_MII_RXD2_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6) +#define GPIO_ETH_MII_RXD3_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1) +#define GPIO_ETH_MII_RXD3_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN7) +#define GPIO_ETH_MII_RX_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ETH_MII_RX_DV (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ETH_MII_RX_ER_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10) +#define GPIO_ETH_MII_RX_ER_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN10) +#define GPIO_ETH_MII_TXD0_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12) +#define GPIO_ETH_MII_TXD0_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN13) +#define GPIO_ETH_MII_TXD1_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN13) +#define GPIO_ETH_MII_TXD1_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14) +#define GPIO_ETH_MII_TXD2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ETH_MII_TXD3_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) +#define GPIO_ETH_MII_TXD3_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN2) +#define GPIO_ETH_MII_TX_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ETH_MII_TX_EN_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11) +#define GPIO_ETH_MII_TX_EN_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN11) +#define GPIO_ETH_PPS_OUT_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5) +#define GPIO_ETH_PPS_OUT_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN8) +#define GPIO_ETH_RMII_CRS_DV (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULLGPIO_PORTA|GPIO_PIN7) +#define GPIO_ETH_RMII_REF_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ETH_RMII_RXD0 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ETH_RMII_RXD1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN5) +#define GPIO_ETH_RMII_TXD0_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12) +#define GPIO_ETH_RMII_TXD0_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN13) +#define GPIO_ETH_RMII_TXD1_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN13) +#define GPIO_ETH_RMII_TXD1_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14) +#define GPIO_ETH_RMII_TX_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ETH_RMII_TX_EN_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11) +#define GPIO_ETH_RMII_TX_EN_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN11) + +/* Flexible Static Memory Controller (FSMC) */ + +#define GPIO_FSMC_A0 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN0) +#define GPIO_FSMC_A1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN1) +#define GPIO_FSMC_A2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN2) +#define GPIO_FSMC_A3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN3) +#define GPIO_FSMC_A4 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN4) +#define GPIO_FSMC_A5 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN5) +#define GPIO_FSMC_A6 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN12) +#define GPIO_FSMC_A7 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN13) +#define GPIO_FSMC_A8 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN14) +#define GPIO_FSMC_A9 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN15) +#define GPIO_FSMC_A10 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN0) +#define GPIO_FSMC_A11 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN1) +#define GPIO_FSMC_A12 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN2) +#define GPIO_FSMC_A13 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN3) +#define GPIO_FSMC_A14 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN4) +#define GPIO_FSMC_A15 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN5) +#define GPIO_FSMC_A16 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN11) +#define GPIO_FSMC_A17 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN12) +#define GPIO_FSMC_A18 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN13) +#define GPIO_FSMC_A19 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN3) +#define GPIO_FSMC_A20 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN4) +#define GPIO_FSMC_A21 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN5) +#define GPIO_FSMC_A22 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN6) +#define GPIO_FSMC_A23 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN2) +#define GPIO_FSMC_A24 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN13) +#define GPIO_FSMC_A25 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN14) +#define GPIO_FSMC_NBL1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN1) +#define GPIO_FSMC_CD (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN9) +#define GPIO_FSMC_CLK (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN3) +#define GPIO_FSMC_D0 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN14) +#define GPIO_FSMC_D1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN15) +#define GPIO_FSMC_D2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN0) +#define GPIO_FSMC_D3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN1) +#define GPIO_FSMC_D4 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN7) +#define GPIO_FSMC_D5 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN8) +#define GPIO_FSMC_D6 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN9) +#define GPIO_FSMC_D7 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN10) +#define GPIO_FSMC_D8 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN11) +#define GPIO_FSMC_D9 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN12) +#define GPIO_FSMC_D10 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN13) +#define GPIO_FSMC_D11 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN14) +#define GPIO_FSMC_D12 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN15) +#define GPIO_FSMC_D13 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN8) +#define GPIO_FSMC_D14 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN9) +#define GPIO_FSMC_D15 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN10) +#define GPIO_FSMC_INT2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN6) +#define GPIO_FSMC_INT3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN7) +#define GPIO_FSMC_INTR (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN10) +#define GPIO_FSMC_NBL0 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN0) +#define GPIO_FSMC_NCE2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN7) +#define GPIO_FSMC_NCE3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN9) +#define GPIO_FSMC_NCE4_1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN10) +#define GPIO_FSMC_NCE4_2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN11) +#define GPIO_FSMC_NE1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN7) +#define GPIO_FSMC_NE2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN9) +#define GPIO_FSMC_NE3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN10) +#define GPIO_FSMC_NE4 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN12) +#define GPIO_FSMC_NIORD (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN6) +#define GPIO_FSMC_NIOWR (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN8) +#define GPIO_FSMC_NL (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTB|GPIO_PIN7) +#define GPIO_FSMC_NOE (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN4) +#define GPIO_FSMC_NREG (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN7) +#define GPIO_FSMC_NWAIT (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN6) +#define GPIO_FSMC_NWE (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN5) + +/* I2C */ + +#define GPIO_I2C1_SCL_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN6) +#define GPIO_I2C1_SCL_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN8) +#define GPIO_I2C1_SDA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN7) +#define GPIO_I2C1_SDA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN9) +#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5) + +#define GPIO_I2C2_SCL_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN10) +#define GPIO_I2C2_SCL_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTF|GPIO_PIN1) +#define GPIO_I2C2_SCL_3 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN4) +#define GPIO_I2C2_SDA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN11) +#define GPIO_I2C2_SDA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTF|GPIO_PIN0) +#define GPIO_I2C2_SDA_3 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN5) +#define GPIO_I2C2_SMBA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12) +#define GPIO_I2C2_SMBA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN2) +#define GPIO_I2C2_SMBA_3 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6) + +#define GPIO_I2C3_SCL_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTA|GPIO_PIN8) +#define GPIO_I2C3_SCL_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN7) +#define GPIO_I2C3_SDA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTC|GPIO_PIN9) +#define GPIO_I2C3_SDA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN8) +#define GPIO_I2C3_SMBA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9) +#define GPIO_I2C3_SMBA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN9) + +/* I2S */ + +#define GPIO_I2S2_CK_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN10) +#define GPIO_I2S2_CK_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN13) +#define GPIO_I2S2_CK_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN1) +#define GPIO_I2S2_MCK (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN6) +#define GPIO_I2S2_SD_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN15) +#define GPIO_I2S2_SD_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN3) +#define GPIO_I2S2_SD_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN3) +#define GPIO_I2S2_WS_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN12) +#define GPIO_I2S2_WS_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN6) +#define GPIO_I2S2_WS_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN9) +#define GPIO_I2S2_WS_4 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN0) + +#define GPIO_I2S2EXT_SD_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN14) +#define GPIO_I2S2EXT_SD_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN2) +#define GPIO_I2S2EXT_SD_3 (GPIO_ALT|GPIO_AF6|GPIO_PORTI|GPIO_PIN2) + +#define GPIO_I2S3_CK_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN3) +#define GPIO_I2S3_CK_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN10) +#define GPIO_I2S3_MCK (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN7) +#define GPIO_I2S3_SD_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN5) +#define GPIO_I2S3_SD_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN12) +#define GPIO_I2S3_WS_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN4) +#define GPIO_I2S3_WS_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN15) + +#define GPIO_I2S3EXT_SD_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN11) +#define GPIO_I2S3EXT_SD_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN4) + +#define GPIO_I2S_CKIN (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN9) + +/* JTAG */ + +#define GPIO_JTCK_SWCLK (GPIO_ALT|GPIO_AF0|GPIO_PORTA|GPIO_PIN14) +#define GPIO_JTDI (GPIO_ALT|GPIO_AF0|GPIO_PORTA|GPIO_PIN15) +#define GPIO_JTDO (GPIO_ALT|GPIO_AF0|GPIO_PORTB|GPIO_PIN3) +#define GPIO_JTMS_SWDIO (GPIO_ALT|GPIO_AF0|GPIO_PORTA|GPIO_PIN13) +#define GPIO_JTRST (GPIO_ALT|GPIO_AF0|GPIO_PORTB|GPIO_PIN4) + +/* OTG FS/HS */ + +#define GPIO_OTGFS_DM (GPIO_ALT|GPIO_FLOAT|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11) +#define GPIO_OTGFS_DP (GPIO_ALT|GPIO_FLOAT|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN12) +#define GPIO_OTGFS_ID (GPIO_ALT|GPIO_PULLUP|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_OPENDRAIN|GPIO_PORTA|GPIO_PIN10) +#define GPIO_OTGFS_SCL (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN8) +#define GPIO_OTGFS_SDA (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN9) +#define GPIO_OTGFS_SOF (GPIO_ALT|GPIO_FLOAT|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) + +#define GPIO_OTGHS_DM (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN14) +#define GPIO_OTGHS_DP (GPIO_ALT|GPIO_AF12|GPIO_PORTC|GPIO_PIN15) +#define GPIO_OTGHS_ID (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN12) +#define GPIO_OTGHS_INTN_1 (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN1) +#define GPIO_OTGFS_INTN_2 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN6) +#define GPIO_OTGHS_SCL (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN10) +#define GPIO_OTGHS_SDA (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN11) +#define GPIO_OTGHS_SOF (GPIO_ALT|GPIO_AF12|GPIO_PORTA|GPIO_PIN4) +#define GPIO_OTGHS_ULPI_CK (GPIO_ALT|GPIO_AF10|GPIO_PORTA|GPIO_PIN5) +#define GPIO_OTGHS_ULPI_D0 (GPIO_ALT|GPIO_AF10|GPIO_PORTA|GPIO_PIN3) +#define GPIO_OTGHS_ULPI_D1 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN0) +#define GPIO_OTGHS_ULPI_D2 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN1) +#define GPIO_OTGHS_ULPI_D3 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN10) +#define GPIO_OTGHS_ULPI_D4 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN11) +#define GPIO_OTGHS_ULPI_D5 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN12) +#define GPIO_OTGHS_ULPI_D6 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN13) +#define GPIO_OTGHS_ULPI_D7 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN5) +#define GPIO_OTGHS_ULPI_DIR_1 (GPIO_ALT|GPIO_AF10|GPIO_PORTC|GPIO_PIN2) +#define GPIO_OTGHS_ULPI_DIR_2 (GPIO_ALT|GPIO_AF10|GPIO_PORTI|GPIO_PIN11) +#define GPIO_OTGHS_ULPI_NXT_1 (GPIO_ALT|GPIO_AF10|GPIO_PORTC|GPIO_PIN3) +#define GPIO_OTGHS_ULPI_NXT_2 (GPIO_ALT|GPIO_AF10|GPIO_PORTH|GPIO_PIN4) +#define GPIO_OTGHS_ULPI_STP (GPIO_ALT|GPIO_AF10|GPIO_PORTC|GPIO_PIN0) + +/* RTC */ + +#define GPIO_RTC_50HZ (GPIO_ALT|GPIO_AF0|GPIO_PORTC|GPIO_PIN15) + +/* SDIO */ + +#define GPIO_SDIO_CK (GPIO_ALT|GPIO_AF12|GPIO_PORTC|GPIO_PIN12) +#define GPIO_SDIO_CMD (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN2) +#define GPIO_SDIO_D0 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8) +#define GPIO_SDIO_D1 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) +#define GPIO_SDIO_D2 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10) +#define GPIO_SDIO_D3 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN11) +#define GPIO_SDIO_D4 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) +#define GPIO_SDIO_D5 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) +#define GPIO_SDIO_D6 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) +#define GPIO_SDIO_D7 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) + +/* SPI */ + +#define GPIO_SPI1_MISO_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN6) +#define GPIO_SPI1_MISO_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN4) +#define GPIO_SPI1_MOSI_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN7) +#define GPIO_SPI1_MOSI_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN5) +#define GPIO_SPI1_NSS_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN15) +#define GPIO_SPI1_NSS_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN4) +#define GPIO_SPI1_SCK_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN5) +#define GPIO_SPI1_SCK_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN3) + +#define GPIO_SPI2_MISO_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN14) +#define GPIO_SPI2_MISO_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN2) +#define GPIO_SPI2_MISO_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN2) +#define GPIO_SPI2_MOSI_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN15) +#define GPIO_SPI2_MOSI_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN3) +#define GPIO_SPI2_MOSI_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN3) +#define GPIO_SPI2_NSS_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN12) +#define GPIO_SPI2_NSS_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN9) +#define GPIO_SPI2_NSS_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN0) +#define GPIO_SPI2_SCK_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN10) +#define GPIO_SPI2_SCK_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN13) +#define GPIO_SPI2_SCK_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN1) + +#define GPIO_SPI3_MISO_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN4) +#define GPIO_SPI3_MISO_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN11) +#define GPIO_SPI3_MOSI_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN5) +#define GPIO_SPI3_MOSI_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN12) +#define GPIO_SPI3_NSS_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN15) +#define GPIO_SPI3_NSS_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN4) +#define GPIO_SPI3_SCK_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN3) +#define GPIO_SPI3_SCK_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN10) + +/* Timers */ + +#define GPIO_TIM1_BKIN_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM1_BKIN_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN12) +#define GPIO_TIM1_BKIN_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN15) +#define GPIO_TIM1_CH1N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM1_CH1N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN13) +#define GPIO_TIM1_CH1N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN8) +#define GPIO_TIM1_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN8) +#define GPIO_TIM1_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN9) +#define GPIO_TIM1_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) +#define GPIO_TIM1_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN9) +#define GPIO_TIM1_CH2N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN0) +#define GPIO_TIM1_CH2N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN14) +#define GPIO_TIM1_CH2N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN10) +#define GPIO_TIM1_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN9) +#define GPIO_TIM1_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN11) +#define GPIO_TIM1_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9) +#define GPIO_TIM1_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN11) +#define GPIO_TIM1_CH3N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN1) +#define GPIO_TIM1_CH3N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTC|GPIO_PIN15) +#define GPIO_TIM1_CH3N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN12) +#define GPIO_TIM1_CH3IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN10) +#define GPIO_TIM1_CH3IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN13) +#define GPIO_TIM1_CH3OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10) +#define GPIO_TIM1_CH3OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN13) +#define GPIO_TIM1_CH4IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN11) +#define GPIO_TIM1_CH4IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN14) +#define GPIO_TIM1_CH4OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11) +#define GPIO_TIM1_CH4OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN14) +#define GPIO_TIM1_ETR_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN12) +#define GPIO_TIM1_ETR_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN7) + +#define GPIO_TIM2_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM2_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN15) +#define GPIO_TIM2_CH1IN_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN5) +#define GPIO_TIM2_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM2_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN15) +#define GPIO_TIM2_CH1OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN5) +#define GPIO_TIM2_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM2_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN3) +#define GPIO_TIM2_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM2_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN3) +#define GPIO_TIM2_CH3IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM2_CH3IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN10) +#define GPIO_TIM2_CH3OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM2_CH3OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10) +#define GPIO_TIM2_CH4IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM2_CH4IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN11) +#define GPIO_TIM2_CH4OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM2_CH4OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11) +#define GPIO_TIM2_ETR_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM2_ETR_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN15) +#define GPIO_TIM2_ETR_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN5) + +#define GPIO_TIM3_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM3_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN4) +#define GPIO_TIM3_CH1IN_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM3_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM3_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN4) +#define GPIO_TIM3_CH1OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM3_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM3_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN5) +#define GPIO_TIM3_CH2IN_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM3_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM3_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5) +#define GPIO_TIM3_CH2OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM3_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN0) +#define GPIO_TIM3_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM3_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0) +#define GPIO_TIM3_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM3_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN1) +#define GPIO_TIM3_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM3_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1) +#define GPIO_TIM3_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM3_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN2) + +#define GPIO_TIM4_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN6) +#define GPIO_TIM4_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN12) +#define GPIO_TIM4_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6) +#define GPIO_TIM4_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN12) +#define GPIO_TIM4_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN7) +#define GPIO_TIM4_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN13) +#define GPIO_TIM4_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN7) +#define GPIO_TIM4_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN13) +#define GPIO_TIM4_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM4_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN14) +#define GPIO_TIM4_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM4_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN14) +#define GPIO_TIM4_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM4_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN15) +#define GPIO_TIM4_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM4_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN15) +#define GPIO_TIM4_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN0) + +#define GPIO_TIM5_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN10) +#define GPIO_TIM5_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN10) +#define GPIO_TIM5_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN11) +#define GPIO_TIM5_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN11) +#define GPIO_TIM5_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN12) +#define GPIO_TIM5_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN12) +#define GPIO_TIM5_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM5_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN0) +#define GPIO_TIM5_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM5_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN0) +#define GPIO_TIM5_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN10) + +#define GPIO_TIM8_BKIN_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM8_BKIN_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTI|GPIO_PIN4) +#define GPIO_TIM8_CH1N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN5) +#define GPIO_TIM8_CH1N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM8_CH1N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN13) +#define GPIO_TIM8_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM8_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN5) +#define GPIO_TIM8_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM8_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN5) +#define GPIO_TIM8_CH2IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM8_CH2IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN6) +#define GPIO_TIM8_CH2OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM8_CH2OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN6) +#define GPIO_TIM8_CH2N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN0) +#define GPIO_TIM8_CH2N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN14) +#define GPIO_TIM8_CH2N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN14) +#define GPIO_TIM8_CH3N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN1) +#define GPIO_TIM8_CH3N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTC|GPIO_PIN15) +#define GPIO_TIM8_CH3N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN15) +#define GPIO_TIM8_CH3IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM8_CH3IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN7) +#define GPIO_TIM8_CH3OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM8_CH3OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN7) +#define GPIO_TIM8_CH4IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM8_CH4IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN2) +#define GPIO_TIM8_CH4OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM8_CH4OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN2) +#define GPIO_TIM8_ETR_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM8_ETR_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN3) + +#define GPIO_TIM9_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM9_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN5) +#define GPIO_TIM9_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM9_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN5) +#define GPIO_TIM9_CH2IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM9_CH2IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN6) +#define GPIO_TIM9_CH2OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM9_CH2OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN6) + +#define GPIO_TIM10_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM10_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN6) +#define GPIO_TIM10_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM10_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN6) + +#define GPIO_TIM11_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM11_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN7) +#define GPIO_TIM11_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM11_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN7) + +#define GPIO_TIM12_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN6) +#define GPIO_TIM12_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN14) +#define GPIO_TIM12_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6) +#define GPIO_TIM12_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN14) +#define GPIO_TIM12_CH2IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN15) +#define GPIO_TIM12_CH2IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN9) +#define GPIO_TIM12_CH2OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN15) +#define GPIO_TIM12_CH2OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN9) + +#define GPIO_TIM13_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM13_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN8) +#define GPIO_TIM13_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM13_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN8) + +#define GPIO_TIM14_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM14_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN9) +#define GPIO_TIM14_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM14_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN9) + +/* Trace */ + +#define GPIO_TRACECLK (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN2) +#define GPIO_TRACED0 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN3) +#define GPIO_TRACED1 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN4) +#define GPIO_TRACED2 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN5) +#define GPIO_TRACED3 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN6) +#define GPIO_TRACESWO (GPIO_ALT|GPIO_AF0|GPIO_PORTB|GPIO_PIN3) + +/* UARTs/USARTs */ + +#define GPIO_USART1_CK (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN8) +#define GPIO_USART1_CTS (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN11) +#define GPIO_USART1_RTS (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN12) +#define GPIO_USART1_RX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10) +#define GPIO_USART1_RX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN7) +#define GPIO_USART1_TX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9) +#define GPIO_USART1_TX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6) + +#define GPIO_USART2_CK_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN4) +#define GPIO_USART2_CK_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN7) +#define GPIO_USART2_CTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN0) +#define GPIO_USART2_CTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN3) +#define GPIO_USART2_RTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN1) +#define GPIO_USART2_RTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN4) +#define GPIO_USART2_RX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_USART2_RX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN6) +#define GPIO_USART2_TX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_USART2_TX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN5) + +#define GPIO_USART3_CK_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN12) +#define GPIO_USART3_CK_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTC|GPIO_PIN12) +#define GPIO_USART3_CK_3 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN10) +#define GPIO_USART3_CTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN13) +#define GPIO_USART3_CTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN11) +#define GPIO_USART3_RTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN14) +#define GPIO_USART3_RTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN12) +#define GPIO_USART3_RX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11) +#define GPIO_USART3_RX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN11) +#define GPIO_USART3_RX_3 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN9) +#define GPIO_USART3_TX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10) +#define GPIO_USART3_TX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10) +#define GPIO_USART3_TX_3 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN8) + +#define GPIO_UART4_RX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_UART4_RX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN11) +#define GPIO_UART4_TX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) +#define GPIO_UART4_TX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10) + +#define GPIO_UART5_RX (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN2) +#define GPIO_UART5_TX (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN12) + +#define GPIO_USART6_CK_1 (GPIO_ALT|GPIO_AF8|GPIO_PORTC|GPIO_PIN8) +#define GPIO_USART6_CK_2 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN7) +#define GPIO_USART6_CTS_1 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN13) +#define GPIO_USART6_CTS_2 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN15) +#define GPIO_USART6_RTS_1 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN12) +#define GPIO_USART6_RTS_2 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN8) +#define GPIO_USART6_RX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) +#define GPIO_USART6_RX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN9) +#define GPIO_USART6_TX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) +#define GPIO_USART6_TX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_PINMAP_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rcc.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rcc.h new file mode 100644 index 0000000000..8a926250bc --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rcc.h @@ -0,0 +1,504 @@ +/**************************************************************************************************** + * arch/arm/src/stm32/chip/stm32f20xxx_rcc.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_RCC_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_RCC_H + +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ + +/* Register Offsets *********************************************************************************/ + +#define STM32_RCC_CR_OFFSET 0x0000 /* Clock control register */ +#define STM32_RCC_PLLCFG_OFFSET 0x0004 /* PLL configuration register */ +#define STM32_RCC_CFGR_OFFSET 0x0008 /* Clock configuration register */ +#define STM32_RCC_CIR_OFFSET 0x000c /* Clock interrupt register */ +#define STM32_RCC_AHB1RSTR_OFFSET 0x0010 /* AHB1 peripheral reset register */ +#define STM32_RCC_AHB2RSTR_OFFSET 0x0014 /* AHB2 peripheral reset register */ +#define STM32_RCC_AHB3RSTR_OFFSET 0x0018 /* AHB3 peripheral reset register */ +#define STM32_RCC_APB1RSTR_OFFSET 0x0020 /* APB1 Peripheral reset register */ +#define STM32_RCC_APB2RSTR_OFFSET 0x0024 /* APB2 Peripheral reset register */ +#define STM32_RCC_AHB1ENR_OFFSET 0x0030 /* AHB1 Peripheral Clock enable register */ +#define STM32_RCC_AHB2ENR_OFFSET 0x0034 /* AHB2 Peripheral Clock enable register */ +#define STM32_RCC_AHB3ENR_OFFSET 0x0038 /* AHB3 Peripheral Clock enable register */ +#define STM32_RCC_APB1ENR_OFFSET 0x0040 /* APB1 Peripheral Clock enable register */ +#define STM32_RCC_APB2ENR_OFFSET 0x0044 /* APB2 Peripheral Clock enable register */ +#define STM32_RCC_AHB1LPENR_OFFSET 0x0050 /* RCC AHB1 low power modeperipheral clock enable register */ +#define STM32_RCC_AH2BLPENR_OFFSET 0x0054 /* RCC AHB2 low power modeperipheral clock enable register */ +#define STM32_RCC_AH3BLPENR_OFFSET 0x0058 /* RCC AHB3 low power modeperipheral clock enable register */ +#define STM32_RCC_APB1LPENR_OFFSET 0x0060 /* RCC APB1 low power modeperipheral clock enable register */ +#define STM32_RCC_APB2LPENR_OFFSET 0x0060 /* RCC APB2 low power modeperipheral clock enable register */ +#define STM32_RCC_BDCR_OFFSET 0x0070 /* Backup domain control register */ +#define STM32_RCC_CSR_OFFSET 0x0074 /* Control/status register */ +#define STM32_RCC_SSCGR_OFFSET 0x0080 /* Spread spectrum clock generation register */ +#define STM32_RCC_PLLI2SCFGR_OFFSET 0x0084 /* PLLI2S configuration register */ + +/* Register Addresses *******************************************************************************/ + +#define STM32_RCC_CR (STM32_RCC_BASE+STM32_RCC_CR_OFFSET) +#define STM32_RCC_PLLCFG (STM32_RCC_BASE+STM32_RCC_PLLCFG_OFFSET) +#define STM32_RCC_CFGR (STM32_RCC_BASE+STM32_RCC_CFGR_OFFSET) +#define STM32_RCC_CIR (STM32_RCC_BASE+STM32_RCC_CIR_OFFSET) +#define STM32_RCC_AHB1RSTR (STM32_RCC_BASE+STM32_RCC_AHB1RSTR_OFFSET) +#define STM32_RCC_AHB2RSTR (STM32_RCC_BASE+STM32_RCC_AHB2RSTR_OFFSET) +#define STM32_RCC_AHB3RSTR (STM32_RCC_BASE+STM32_RCC_AHB3RSTR_OFFSET) +#define STM32_RCC_APB1RSTR (STM32_RCC_BASE+STM32_RCC_APB1RSTR_OFFSET) +#define STM32_RCC_APB2RSTR (STM32_RCC_BASE+STM32_RCC_APB2RSTR_OFFSET) +#define STM32_RCC_AHB1ENR (STM32_RCC_BASE+STM32_RCC_AHB1ENR_OFFSET) +#define STM32_RCC_AHB2ENR (STM32_RCC_BASE+STM32_RCC_AHB2ENR_OFFSET) +#define STM32_RCC_AHB3ENR (STM32_RCC_BASE+STM32_RCC_AHB3ENR_OFFSET) +#define STM32_RCC_APB1ENR (STM32_RCC_BASE+STM32_RCC_APB1ENR_OFFSET) +#define STM32_RCC_APB2ENR (STM32_RCC_BASE+STM32_RCC_APB2ENR_OFFSET) +#define STM32_RCC_AHB1LPENR (STM32_RCC_BASE+STM32_RCC_AHB1LPENR_OFFSET) +#define STM32_RCC_AH2BLPENR (STM32_RCC_BASE+STM32_RCC_AH2BLPENR) +#define STM32_RCC_AH3BLPENR (STM32_RCC_BASE+STM32_RCC_AH3BLPENR_OFFSET) +#define STM32_RCC_APB1LPENR (STM32_RCC_BASE+STM32_RCC_APB1LPENR_OFFSET) +#define STM32_RCC_APB2LPENR (STM32_RCC_BASE+STM32_RCC_APB2LPENR_OFFSET) +#define STM32_RCC_BDCR (STM32_RCC_BASE+STM32_RCC_BDCR_OFFSET) +#define STM32_RCC_CSR (STM32_RCC_BASE+STM32_RCC_CSR_OFFSET) +#define STM32_RCC_SSCGR (STM32_RCC_BASE+STM32_RCC_SSCGR_OFFSET) +#define STM32_RCC_PLLI2SCFGR (STM32_RCC_BASE+STM32_RCC_PLLI2SCFGR_OFFSET) + +/* Register Bitfield Definitions ********************************************************************/ + +/* Clock control register */ + +#define RCC_CR_HSION (1 << 0) /* Bit 0: Internal High Speed clock enable */ +#define RCC_CR_HSIRDY (1 << 1) /* Bit 1: Internal High Speed clock ready flag */ +#define RCC_CR_HSITRIM_SHIFT (3) /* Bits 7-3: Internal High Speed clock trimming */ +#define RCC_CR_HSITRIM_MASK (0x1f << RCC_CR_HSITRIM_SHIFT) +#define RCC_CR_HSICAL_SHIFT (8) /* Bits 15-8: Internal High Speed clock Calibration */ +#define RCC_CR_HSICAL_MASK (0xff << RCC_CR_HSICAL_SHIFT) +#define RCC_CR_HSEON (1 << 16) /* Bit 16: External High Speed clock enable */ +#define RCC_CR_HSERDY (1 << 17) /* Bit 17: External High Speed clock ready flag */ +#define RCC_CR_HSEBYP (1 << 18) /* Bit 18: External High Speed clock Bypass */ +#define RCC_CR_CSSON (1 << 19) /* Bit 19: Clock Security System enable */ +#define RCC_CR_PLLON (1 << 24) /* Bit 24: PLL enable */ +#define RCC_CR_PLLRDY (1 << 25) /* Bit 25: PLL clock ready flag */ +#define RCC_CR_PLLI2SON (1 << 26) /* Bit 26: PLLI2S enable */ +#define RCC_CR_PLLI2SRDY (1 << 27) /* Bit 27: PLLI2S clock ready flag */ + +/* PLL configuration register */ + +#define RCC_PLLCFG_PLLM_SHIFT (0) /* Bits 0-5: Main PLL (PLL) and audio PLL (PLLI2S) + * input clock divider */ +#define RCC_PLLCFG_PLLM_MASK (0x3f << RCC_PLLCFG_PLLM_SHIFT) +# define RCC_PLLCFG_PLLM(n) ((n) << RCC_PLLCFG_PLLM_SHIFT) /* n = 2..63 */ +#define RCC_PLLCFG_PLLN_SHIFT (6) /* Bits 6-14: Main PLL (PLL) VCO multiplier */ +#define RCC_PLLCFG_PLLN_MASK (0x1ff << RCC_PLLCFG_PLLN_SHIFT) +# define RCC_PLLCFG_PLLN(n) ((n) << RCC_PLLCFG_PLLN_SHIFT) /* n = 2..432 */ +#define RCC_PLLCFG_PLLP_SHIFT (16) /* Bits 16-17: Main PLL (PLL) main system clock divider */ +#define RCC_PLLCFG_PLLP_MASK (3 << RCC_PLLCFG_PLLP_SHIFT) +# define RCC_PLLCFG_PLLP(n) ((((n)>>1)-1)<< RCC_PLLCFG_PLLP_SHIFT) /* n=2,4,6,8 */ +# define RCC_PLLCFG_PLLP_2 (0 << RCC_PLLCFG_PLLP_SHIFT) /* 00: PLLP = 2 */ +# define RCC_PLLCFG_PLLP_4 (1 << RCC_PLLCFG_PLLP_SHIFT) /* 01: PLLP = 4 */ +# define RCC_PLLCFG_PLLP_6 (2 << RCC_PLLCFG_PLLP_SHIFT) /* 10: PLLP = 6 */ +# define RCC_PLLCFG_PLLP_8 (3 << RCC_PLLCFG_PLLP_SHIFT) /* 11: PLLP = 8 */ +#define RCC_PLLCFG_PLLSRC (1 << 22) /* Bit 22: Main PLL(PLL) and audio PLL (PLLI2S) + * entry clock source */ +# define RCC_PLLCFG_PLLSRC_HSI (0) +# define RCC_PLLCFG_PLLSRC_HSE RCC_PLLCFG_PLLSRC +#define RCC_PLLCFG_PLLQ_SHIFT (24) /* Bits 24-27: Main PLL (PLL) divider + * (USB OTG FS, SDIO and RNG clocks) */ +#define RCC_PLLCFG_PLLQ_MASK (15 << RCC_PLLCFG_PLLQ_SHIFT) +# define RCC_PLLCFG_PLLQ(n) ((n) << RCC_PLLCFG_PLLQ_SHIFT) /* n=2..15 */ + +#define RCC_PLLCFG_RESET (0x24003010) /* PLLCFG reset value */ + +/* Clock configuration register */ + +#define RCC_CFGR_SW_SHIFT (0) /* Bits 0-1: System clock Switch */ +#define RCC_CFGR_SW_MASK (3 << RCC_CFGR_SW_SHIFT) +# define RCC_CFGR_SW_HSI (0 << RCC_CFGR_SW_SHIFT) /* 00: HSI selected as system clock */ +# define RCC_CFGR_SW_HSE (1 << RCC_CFGR_SW_SHIFT) /* 01: HSE selected as system clock */ +# define RCC_CFGR_SW_PLL (2 << RCC_CFGR_SW_SHIFT) /* 10: PLL selected as system clock */ +#define RCC_CFGR_SWS_SHIFT (2) /* Bits 2-3: System Clock Switch Status */ +#define RCC_CFGR_SWS_MASK (3 << RCC_CFGR_SWS_SHIFT) +# define RCC_CFGR_SWS_HSI (0 << RCC_CFGR_SWS_SHIFT) /* 00: HSI oscillator used as system clock */ +# define RCC_CFGR_SWS_HSE (1 << RCC_CFGR_SWS_SHIFT) /* 01: HSE oscillator used as system clock */ +# define RCC_CFGR_SWS_PLL (2 << RCC_CFGR_SWS_SHIFT) /* 10: PLL used as system clock */ +#define RCC_CFGR_HPRE_SHIFT (4) /* Bits 4-7: AHB prescaler */ +#define RCC_CFGR_HPRE_MASK (0x0f << RCC_CFGR_HPRE_SHIFT) +# define RCC_CFGR_HPRE_SYSCLK (0 << RCC_CFGR_HPRE_SHIFT) /* 0xxx: SYSCLK not divided */ +# define RCC_CFGR_HPRE_SYSCLKd2 (8 << RCC_CFGR_HPRE_SHIFT) /* 1000: SYSCLK divided by 2 */ +# define RCC_CFGR_HPRE_SYSCLKd4 (9 << RCC_CFGR_HPRE_SHIFT) /* 1001: SYSCLK divided by 4 */ +# define RCC_CFGR_HPRE_SYSCLKd8 (10 << RCC_CFGR_HPRE_SHIFT) /* 1010: SYSCLK divided by 8 */ +# define RCC_CFGR_HPRE_SYSCLKd16 (11 << RCC_CFGR_HPRE_SHIFT) /* 1011: SYSCLK divided by 16 */ +# define RCC_CFGR_HPRE_SYSCLKd64 (12 << RCC_CFGR_HPRE_SHIFT) /* 1100: SYSCLK divided by 64 */ +# define RCC_CFGR_HPRE_SYSCLKd128 (13 << RCC_CFGR_HPRE_SHIFT) /* 1101: SYSCLK divided by 128 */ +# define RCC_CFGR_HPRE_SYSCLKd256 (14 << RCC_CFGR_HPRE_SHIFT) /* 1110: SYSCLK divided by 256 */ +# define RCC_CFGR_HPRE_SYSCLKd512 (15 << RCC_CFGR_HPRE_SHIFT) /* 1111: SYSCLK divided by 512 */ +#define RCC_CFGR_PPRE1_SHIFT (10) /* Bits 10-12: APB Low speed prescaler (APB1) */ +#define RCC_CFGR_PPRE1_MASK (7 << RCC_CFGR_PPRE1_SHIFT) +# define RCC_CFGR_PPRE1_HCLK (0 << RCC_CFGR_PPRE1_SHIFT) /* 0xx: HCLK not divided */ +# define RCC_CFGR_PPRE1_HCLKd2 (4 << RCC_CFGR_PPRE1_SHIFT) /* 100: HCLK divided by 2 */ +# define RCC_CFGR_PPRE1_HCLKd4 (5 << RCC_CFGR_PPRE1_SHIFT) /* 101: HCLK divided by 4 */ +# define RCC_CFGR_PPRE1_HCLKd8 (6 << RCC_CFGR_PPRE1_SHIFT) /* 110: HCLK divided by 8 */ +# define RCC_CFGR_PPRE1_HCLKd16 (7 << RCC_CFGR_PPRE1_SHIFT) /* 111: HCLK divided by 16 */ +#define RCC_CFGR_PPRE2_SHIFT (13) /* Bits 13-15: APB High speed prescaler (APB2) */ +#define RCC_CFGR_PPRE2_MASK (7 << RCC_CFGR_PPRE2_SHIFT) +# define RCC_CFGR_PPRE2_HCLK (0 << RCC_CFGR_PPRE2_SHIFT) /* 0xx: HCLK not divided */ +# define RCC_CFGR_PPRE2_HCLKd2 (4 << RCC_CFGR_PPRE2_SHIFT) /* 100: HCLK divided by 2 */ +# define RCC_CFGR_PPRE2_HCLKd4 (5 << RCC_CFGR_PPRE2_SHIFT) /* 101: HCLK divided by 4 */ +# define RCC_CFGR_PPRE2_HCLKd8 (6 << RCC_CFGR_PPRE2_SHIFT) /* 110: HCLK divided by 8 */ +# define RCC_CFGR_PPRE2_HCLKd16 (7 << RCC_CFGR_PPRE2_SHIFT) /* 111: HCLK divided by 16 */ +#define RCC_CFGR_RTCPRE_SHIFT (16) /* Bits 16-20: APB High speed prescaler (APB2) */ +#define RCC_CFGR_RTCPRE_MASK (31 << RCC_CFGR_RTCPRE) +# define RCC_CFGR_RTCPRE(n) ((n) << RCC_CFGR_RTCPRE) /* HSE/n, n=1..31 */ +#define RCC_CFGR_MCO1_SHIFT (21) /* Bits 21-22: Microcontroller Clock Output */ +#define RCC_CFGR_MCO1_MASK (3 << RCC_CFGR_MCO1_SHIFT) +# define RCC_CFGR_MCO1_HSI (0 << RCC_CFGR_MCO1_SHIFT) /* 00: HSI clock selected */ +# define RCC_CFGR_MCO1_LSE (1 << RCC_CFGR_MCO1_SHIFT) /* 01: LSE oscillator selected */ +# define RCC_CFGR_MCO1_HSE (2 << RCC_CFGR_MCO1_SHIFT) /* 10: HSE oscillator clock selected */ +# define RCC_CFGR_MCO1_PLL (3 << RCC_CFGR_MCO1_SHIFT) /* 11: PLL clock selected */ +#define TCC_CFGR_I2SSRC (1 << 23) /* Bit 23: I2S clock selection */ +#define RCC_CFGR_MCO1PRE_SHIFT (24) /* Bits 24-26: MCO1 prescaler */ +#define RCC_CFGR_MCO1PRE_MASK (7 << RCC_CFGR_MCO1PRE_SHIFT) +# define RCC_CFGR_MCO1PRE_NONE (0 << RCC_CFGR_MCO1PRE_SHIFT) /* 0xx: no division */ +# define RCC_CFGR_MCO1PRE_DIV2 (4 << RCC_CFGR_MCO1PRE_SHIFT) /* 100: division by 2 */ +# define RCC_CFGR_MCO1PRE_DIV3 (5 << RCC_CFGR_MCO1PRE_SHIFT) /* 101: division by 3 */ +# define RCC_CFGR_MCO1PRE_DIV4 (6 << RCC_CFGR_MCO1PRE_SHIFT) /* 110: division by 4 */ +# define RCC_CFGR_MCO1PRE_DIV5 (7 << RCC_CFGR_MCO1PRE_SHIFT) /* 111: division by 5 */ +#define RCC_CFGR_MCO2PRE_SHIFT (27) /* Bits 27-29: MCO2 prescaler */ +#define RCC_CFGR_MCO2PRE_MASK (7 << RCC_CFGR_MCO2PRE_SHIFT) +# define RCC_CFGR_MCO2PRE_NONE (0 << RCC_CFGR_MCO2PRE_SHIFT) /* 0xx: no division */ +# define RCC_CFGR_MCO2PRE_DIV2 (4 << RCC_CFGR_MCO2PRE_SHIFT) /* 100: division by 2 */ +# define RCC_CFGR_MCO2PRE_DIV3 (5 << RCC_CFGR_MCO2PRE_SHIFT) /* 101: division by 3 */ +# define RCC_CFGR_MCO2PRE_DIV4 (6 << RCC_CFGR_MCO2PRE_SHIFT) /* 110: division by 4 */ +# define RCC_CFGR_MCO2PRE_DIV5 (7 << RCC_CFGR_MCO2PRE_SHIFT) /* 111: division by 5 */ +#define RCC_CFGR_MCO2_SHIFT (30) /* Bits 30-31: Microcontroller clock output 2 */ +#define RCC_CFGR_MCO2_MASK (3 << RCC_CFGR_MCO2_SHIFT) +# define RCC_CFGR_MCO2_SYSCLK (0 << RCC_CFGR_MCO2_SHIFT) /* 00: System clock (SYSCLK) selected */ +# define RCC_CFGR_MCO2_PLLI2S (1 << RCC_CFGR_MCO2_SHIFT) /* 01: PLLI2S clock selected */ +# define RCC_CFGR_MCO2_HSE (2 << RCC_CFGR_MCO2_SHIFT) /* 10: HSE oscillator clock selected */ +# define RCC_CFGR_MCO2_PLL (3 << RCC_CFGR_MCO2_SHIFT) /* 11: PLL clock selected */ + +/* Clock interrupt register */ + +#define RCC_CIR_LSIRDYF (1 << 0) /* Bit 0: LSI Ready Interrupt flag */ +#define RCC_CIR_LSERDYF (1 << 1) /* Bit 1: LSE Ready Interrupt flag */ +#define RCC_CIR_HSIRDYF (1 << 2) /* Bit 2: HSI Ready Interrupt flag */ +#define RCC_CIR_HSERDYF (1 << 3) /* Bit 3: HSE Ready Interrupt flag */ +#define RCC_CIR_PLLRDYF (1 << 4) /* Bit 4: PLL Ready Interrupt flag */ +#define RCC_CIR_PLLI2SRDYF (1 << 5) /* Bit 5: PLLI2S Ready Interrupt flag */ +#define RCC_CIR_CSSF (1 << 7) /* Bit 7: Clock Security System Interrupt flag */ +#define RCC_CIR_LSIRDYIE (1 << 8) /* Bit 8: LSI Ready Interrupt Enable */ +#define RCC_CIR_LSERDYIE (1 << 9) /* Bit 9: LSE Ready Interrupt Enable */ +#define RCC_CIR_HSIRDYIE (1 << 10) /* Bit 10: HSI Ready Interrupt Enable */ +#define RCC_CIR_HSERDYIE (1 << 11) /* Bit 11: HSE Ready Interrupt Enable */ +#define RCC_CIR_PLLRDYIE (1 << 12) /* Bit 12: PLL Ready Interrupt Enable */ +#define RCC_CIR_PLLI2SRDYIE (1 << 13) /* Bit 13: PLLI2S Ready Interrupt enable */ +#define RCC_CIR_LSIRDYC (1 << 16) /* Bit 16: LSI Ready Interrupt Clear */ +#define RCC_CIR_LSERDYC (1 << 17) /* Bit 17: LSE Ready Interrupt Clear */ +#define RCC_CIR_HSIRDYC (1 << 18) /* Bit 18: HSI Ready Interrupt Clear */ +#define RCC_CIR_HSERDYC (1 << 19) /* Bit 19: HSE Ready Interrupt Clear */ +#define RCC_CIR_PLLRDYC (1 << 20) /* Bit 20: PLL Ready Interrupt Clear */ +#define RCC_CIR_PLLI2SRDYC (1 << 21) /* Bit 21: PLLI2S Ready Interrupt clear */ +#define RCC_CIR_CSSC (1 << 23) /* Bit 23: Clock Security System Interrupt Clear */ + +/* AHB1 peripheral reset register */ + +#define RCC_AHB1RSTR_GPIOARST (1 << 0) /* Bit 0: IO port A reset */ +#define RCC_AHB1RSTR_GPIOBRST (1 << 1) /* Bit 1: IO port B reset */ +#define RCC_AHB1RSTR_GPIOCRST (1 << 2) /* Bit 2: IO port C reset */ +#define RCC_AHB1RSTR_GPIODRST (1 << 3) /* Bit 3: IO port D reset */ +#define RCC_AHB1RSTR_GPIOERST (1 << 4) /* Bit 4: IO port E reset */ +#define RCC_AHB1RSTR_GPIOFRST (1 << 5) /* Bit 5: IO port F reset */ +#define RCC_AHB1RSTR_GPIOGRST (1 << 6) /* Bit 6: IO port G reset */ +#define RCC_AHB1RSTR_GPIOHRST (1 << 7) /* Bit 7: IO port H reset */ +#define RCC_AHB1RSTR_CRCRST (1 << 12) /* Bit 12 IO port I reset */ +#define RCC_AHB1RSTR_DMA1RST (1 << 21) /* Bit 21: DMA1 reset */ +#define RCC_AHB1RSTR_DMA2RST (1 << 22) /* Bit 22: DMA2 reset */ +#define RCC_AHB1RSTR_ETHMACRST (1 << 25) /* Bit 25: Ethernet MAC reset */ +#define RCC_AHB1RSTR_OTGHSRST (1 << 29) /* Bit 29: USB OTG HS module reset */ + +/* AHB2 peripheral reset register */ + +#define RCC_AHB2RSTR_DCMIRST (1 << 0) /* Bit 0: Camera interface reset */ +#define RCC_AHB2RSTR_CRYPRST (1 << 4) /* Bit 4: Cryptographic module reset */ +#define RCC_AHB2RSTR_HASHRST (1 << 5) /* Bit 5: Hash module reset */ +#define RCC_AHB2RSTR_RNGRST (1 << 6) /* Bit 6: Random number generator module reset */ +#define RCC_AHB2RSTR_OTGFSRST (1 << 7) /* Bit 7: USB OTG FS module reset */ + +/* AHB3 peripheral reset register */ + +#define RCC_AHB3RSTR_FSMCRST (1 << 0) /* Bit 0: Flexible static memory controller module reset */ + +/* APB1 Peripheral reset register */ + +#define RCC_APB1RSTR_TIM2RST (1 << 0) /* Bit 0: TIM2 reset */ +#define RCC_APB1RSTR_TIM3RST (1 << 1) /* Bit 1: TIM3 reset */ +#define RCC_APB1RSTR_TIM4RST (1 << 2) /* Bit 2: TIM4 reset */ +#define RCC_APB1RSTR_TIM5RST (1 << 3) /* Bit 3: TIM5 reset */ +#define RCC_APB1RSTR_TIM6RST (1 << 4) /* Bit 4: TIM6 reset */ +#define RCC_APB1RSTR_TIM7RST (1 << 5) /* Bit 5: TIM7 reset */ +#define RCC_APB1RSTR_TIM12RST (1 << 6) /* Bit 6: TIM12 reset */ +#define RCC_APB1RSTR_TIM13RST (1 << 7) /* Bit 7: TIM13 reset */ +#define RCC_APB1RSTR_TIM14RST (1 << 8) /* Bit 8: TIM14 reset */ +#define RCC_APB1RSTR_WWDGRST (1 << 11) /* Bit 11: Window watchdog reset */ +#define RCC_APB1RSTR_SPI2RST (1 << 14) /* Bit 14: SPI 2 reset */ +#define RCC_APB1RSTR_SPI3RST (1 << 15) /* Bit 15: SPI 3 reset */ +#define RCC_APB1RSTR_USART2RST (1 << 17) /* Bit 17: USART 2 reset */ +#define RCC_APB1RSTR_USART3RST (1 << 18) /* Bit 18: USART 3 reset */ +#define RCC_APB1RSTR_UART4RST (1 << 19) /* Bit 19: USART 4 reset */ +#define RCC_APB1RSTR_UART5RST (1 << 20) /* Bit 20: USART 5 reset */ +#define RCC_APB1RSTR_I2C1RST (1 << 21) /* Bit 21: I2C 1 reset */ +#define RCC_APB1RSTR_I2C2RST (1 << 22) /* Bit 22: I2C 2 reset */ +#define RCC_APB1RSTR_I2C3RST (1 << 23) /* Bit 23: I2C3 reset */ +#define RCC_APB1RSTR_CAN1RST (1 << 25) /* Bit 25: CAN1 reset */ +#define RCC_APB1RSTR_CAN2RST (1 << 26) /* Bit 26: CAN2 reset */ +#define RCC_APB1RSTR_PWRRST (1 << 28) /* Bit 28: Power interface reset */ +#define RCC_APB1RSTR_DACRST (1 << 29) /* Bit 29: DAC reset */ + +/* APB2 Peripheral reset register */ + +#define RCC_APB2RSTR_TIM1RST (1 << 0) /* Bit 0: TIM1 reset */ +#define RCC_APB2RSTR_TIM8RST (1 << 1) /* Bit 1: TIM8 reset */ +#define RCC_APB2RSTR_USART1RST (1 << 4) /* Bit 4: USART1 reset */ +#define RCC_APB2RSTR_USART6RST (1 << 5) /* Bit 5: USART6 reset */ +#define RCC_APB2RSTR_ADCRST (1 << 8) /* Bit 8: ADC interface reset (common to all ADCs) */ +#define RCC_APB2RSTR_SDIORST (1 << 11) /* Bit 11: SDIO reset */ +#define RCC_APB2RSTR_SPI1RST (1 << 12) /* Bit 12: SPI 1 reset */ +#define RCC_APB2RSTR_SYSCFGRST (1 << 14) /* Bit 14: System configuration controller reset */ +#define RCC_APB2RSTR_TIM9RST (1 << 16) /* Bit 16: TIM9 reset */ +#define RCC_APB2RSTR_TIM10RST (1 << 17) /* Bit 17: TIM10 reset */ +#define RCC_APB2RSTR_TIM11RST (1 << 18) /* Bit 18: TIM11 reset */ + +/* AHB1 Peripheral Clock enable register */ + +#define RCC_AHB1ENR_GPIOEN(n) (1 << (n)) +#define RCC_AHB1ENR_GPIOAEN (1 << 0) /* Bit 0: IO port A clock enable */ +#define RCC_AHB1ENR_GPIOBEN (1 << 1) /* Bit 1: IO port B clock enable */ +#define RCC_AHB1ENR_GPIOCEN (1 << 2) /* Bit 2: IO port C clock enable */ +#define RCC_AHB1ENR_GPIODEN (1 << 3) /* Bit 3: IO port D clock enable */ +#define RCC_AHB1ENR_GPIOEEN (1 << 4) /* Bit 4: IO port E clock enable */ +#define RCC_AHB1ENR_GPIOFEN (1 << 5) /* Bit 5: IO port F clock enable */ +#define RCC_AHB1ENR_GPIOGEN (1 << 6) /* Bit 6: IO port G clock enable */ +#define RCC_AHB1ENR_GPIOHEN (1 << 7) /* Bit 7: IO port H clock enable */ +#define RCC_AHB1ENR_GPIOIEN (1 << 8) /* Bit 8: IO port I clock enable */ +#define RCC_AHB1ENR_CRCEN (1 << 12) /* Bit 12: CRC clock enable */ +#define RCC_AHB1ENR_BKPSRAMEN (1 << 18) /* Bit 18: Backup SRAM interface clock enable */ +#define RCC_AHB1ENR_DMA1EN (1 << 21) /* Bit 21: DMA1 clock enable */ +#define RCC_AHB1ENR_DMA2EN (1 << 22) /* Bit 22: DMA2 clock enable */ +#define RCC_AHB1ENR_ETHMACEN (1 << 25) /* Bit 25: Ethernet MAC clock enable */ +#define RCC_AHB1ENR_ETHMACTXEN (1 << 26) /* Bit 26: Ethernet Transmission clock enable */ +#define RCC_AHB1ENR_ETHMACRXEN (1 << 27) /* Bit 27: Ethernet Reception clock enable */ +#define RCC_AHB1ENR_ETHMACPTPEN (1 << 28) /* Bit 28: Ethernet PTP clock enable */ +#define RCC_AHB1ENR_OTGHSEN (1 << 29) /* Bit 29: USB OTG HS clock enable */ +#define RCC_AHB1ENR_OTGHSULPIEN (1 << 30) /* Bit 30: USB OTG HSULPI clock enable */ + +/* AHB2 Peripheral Clock enable register */ + +#define RCC_AHB2ENR_DCMIEN (1 << 0) /* Bit 0: Camera interface enable */ +#define RCC_AHB2ENR_CRYPEN (1 << 4) /* Bit 4: Cryptographic modules clock enable */ +#define RCC_AHB2ENR_HASHEN (1 << 5) /* Bit 5: Hash modules clock enable */ +#define RCC_AHB2ENR_RNGEN (1 << 6) /* Bit 6: Random number generator clock enable */ +#define RCC_AHB2ENR_OTGFSEN (1 << 7) /* Bit 7: USB OTG FS clock enable */ + +/* AHB3 Peripheral Clock enable register */ + +#define RCC_AHB3ENR_FSMCEN (1 << 0) /* Bit 0: Flexible static memory controller module clock enable */ + +/* APB1 Peripheral Clock enable register */ + +#define RCC_APB1ENR_TIM2EN (1 << 0) /* Bit 0: TIM2 clock enable */ +#define RCC_APB1ENR_TIM3EN (1 << 1) /* Bit 1: TIM3 clock enable */ +#define RCC_APB1ENR_TIM4EN (1 << 2) /* Bit 2: TIM4 clock enable */ +#define RCC_APB1ENR_TIM5EN (1 << 3) /* Bit 3: TIM5 clock enable */ +#define RCC_APB1ENR_TIM6EN (1 << 4) /* Bit 4: TIM6 clock enable */ +#define RCC_APB1ENR_TIM7EN (1 << 5) /* Bit 5: TIM7 clock enable */ +#define RCC_APB1ENR_TIM12EN (1 << 6) /* Bit 6: TIM12 clock enable */ +#define RCC_APB1ENR_TIM13EN (1 << 7) /* Bit 7: TIM13 clock enable */ +#define RCC_APB1ENR_TIM14EN (1 << 8) /* Bit 8: TIM14 clock enable */ +#define RCC_APB1ENR_WWDGEN (1 << 11) /* Bit 11: Window watchdog clock enable */ +#define RCC_APB1ENR_SPI2EN (1 << 14) /* Bit 14: SPI2 clock enable */ +#define RCC_APB1ENR_SPI3EN (1 << 15) /* Bit 15: SPI3 clock enable */ +#define RCC_APB1ENR_USART2EN (1 << 17) /* Bit 17: USART 2 clock enable */ +#define RCC_APB1ENR_USART3EN (1 << 18) /* Bit 18: USART3 clock enable */ +#define RCC_APB1ENR_UART4EN (1 << 19) /* Bit 19: UART4 clock enable */ +#define RCC_APB1ENR_UART5EN (1 << 20) /* Bit 20: UART5 clock enable */ +#define RCC_APB1ENR_I2C1EN (1 << 21) /* Bit 21: I2C1 clock enable */ +#define RCC_APB1ENR_I2C2EN (1 << 22) /* Bit 22: I2C2 clock enable */ +#define RCC_APB1ENR_I2C3EN (1 << 23) /* Bit 23: I2C3 clock enable */ +#define RCC_APB1ENR_CAN1EN (1 << 25) /* Bit 25: CAN 1 clock enable */ +#define RCC_APB1ENR_CAN2EN (1 << 26) /* Bit 26: CAN 2 clock enable */ +#define RCC_APB1ENR_PWREN (1 << 28) /* Bit 28: Power interface clock enable */ +#define RCC_APB1ENR_DACEN (1 << 29) /* Bit 29: DAC interface clock enable */ + +/* APB2 Peripheral Clock enable register */ + +#define RCC_APB2ENR_TIM1EN (1 << 0) /* Bit 0: TIM1 clock enable */ +#define RCC_APB2ENR_TIM8EN (1 << 1) /* Bit 1: TIM8 clock enable */ +#define RCC_APB2ENR_USART1EN (1 << 4) /* Bit 4: USART1 clock enable */ +#define RCC_APB2ENR_USART6EN (1 << 5) /* Bit 5: USART6 clock enable */ +#define RCC_APB2ENR_ADC1EN (1 << 8) /* Bit 8: ADC1 clock enable */ +#define RCC_APB2ENR_ADC2EN (1 << 9) /* Bit 9: ADC2 clock enable */ +#define RCC_APB2ENR_ADC3EN (1 << 10) /* Bit 10: ADC3 clock enable */ +#define RCC_APB2ENR_SDIOEN (1 << 11) /* Bit 11: SDIO clock enable */ +#define RCC_APB2ENR_SPI1EN (1 << 12) /* Bit 12: SPI1 clock enable */ +#define RCC_APB2ENR_SYSCFGEN (1 << 14) /* Bit 14: System configuration controller clock enable */ +#define RCC_APB2ENR_TIM9EN (1 << 16) /* Bit 16: TIM9 clock enable */ +#define RCC_APB2ENR_TIM10EN (1 << 17) /* Bit 17: TIM10 clock enable */ +#define RCC_APB2ENR_TIM11EN (1 << 18) /* Bit 18: TIM11 clock enable */ + +/* RCC AHB1 low power modeperipheral clock enable register */ + +#define RCC_AHB1LPENR_GPIOLPEN(n) (1 << (n)) +#define RCC_AHB1LPENR_GPIOALPEN (1 << 0) /* Bit 0: IO port A clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOBLPEN (1 << 1) /* Bit 1: IO port B clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOCLPEN (1 << 2) /* Bit 2: IO port C clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIODLPEN (1 << 3) /* Bit 3: IO port D clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOELPEN (1 << 4) /* Bit 4: IO port E clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOFLPEN (1 << 5) /* Bit 5: IO port F clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOGLPEN (1 << 6) /* Bit 6: IO port G clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOHLPEN (1 << 7) /* Bit 7: IO port H clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOILPEN (1 << 8) /* Bit 8: IO port I clock enable during Sleep mode */ +#define RCC_AHB1LPENR_CRCLPEN (1 << 12) /* Bit 12: CRC clock enable during Sleep mode */ +#define RCC_AHB1LPENR_FLITFLPEN (1 << 15) /* Bit 15: Flash interface clock enable during Sleep mode */ +#define RCC_AHB1LPENR_SRAM1LPEN (1 << 16) /* Bit 16: SRAM 1 interface clock enable during Sleep mode */ +#define RCC_AHB1LPENR_SRAM2LPEN (1 << 17) /* Bit 17: SRAM 2 interface clock enable during Sleep mode */ +#define RCC_AHB1LPENR_BKPSRAMLPEN (1 << 18) /* Bit 18: Backup SRAM interface clock enable during Sleep mode */ +#define RCC_AHB1LPENR_DMA1LPEN (1 << 21) /* Bit 21: DMA1 clock enable during Sleep mode */ +#define RCC_AHB1LPENR_DMA2LPEN (1 << 22) /* Bit 22: DMA2 clock enable during Sleep mode */ +#define RCC_AHB1LPENR_ETHMACLPEN (1 << 25) /* Bit 25: Ethernet MAC clock enable during Sleep mode */ +#define RCC_AHB1LPENR_ETHMACTXLPEN (1 << 26) /* Bit 26: Ethernet Transmission clock enable during Sleep mode */ +#define RCC_AHB1LPENR_ETHMACRXLPEN (1 << 27) /* Bit 27: Ethernet Reception clock enable during Sleep mode */ +#define RCC_AHB1LPENR_ETHMACPTPLPEN (1 << 28) /* Bit 28: Ethernet PTP clock enable during Sleep mode */ +#define RCC_AHB1LPENR_OTGHSLPEN (1 << 29) /* Bit 29: USB OTG HS clock enable during Sleep mode */ +#define RCC_AHB1LPENR_OTGHSULPILPEN (1 << 30) /* Bit 30: USB OTG HSULPI clock enable during Sleep mode */ + +/* RCC AHB2 low power modeperipheral clock enable register */ + +#define RCC_AHB2LPENR_DCMILPEN (1 << 0) /* Bit 0: Camera interface enable during Sleep mode */ +#define RCC_AHB2LPENR_CRYPLPEN (1 << 4) /* Bit 4: Cryptographic modules clock enable during Sleep mode */ +#define RCC_AHB2LPENR_HASHLPEN (1 << 5) /* Bit 5: Hash modules clock enable during Sleep mode */ +#define RCC_AHB2LPENR_RNGLPEN (1 << 6) /* Bit 6: Random number generator clock enable during Sleep mode */ +#define RCC_AHB2LPENR_OTGFLPSEN (1 << 7) /* Bit 7: USB OTG FS clock enable during Sleep mode */ + +/* RCC AHB3 low power modeperipheral clock enable register */ + +#define RCC_AHB3LPENR_FSMLPEN (1 << 0) /* Bit 0: Flexible static memory controller module clock + * enable during Sleep mode */ + +/* RCC APB1 low power modeperipheral clock enable register */ + +#define RCC_APB1LPENR_TIM2LPEN (1 << 0) /* Bit 0: TIM2 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM3LPEN (1 << 1) /* Bit 1: TIM3 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM4LPEN (1 << 2) /* Bit 2: TIM4 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM5LPEN (1 << 3) /* Bit 3: TIM5 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM6LPEN (1 << 4) /* Bit 4: TIM6 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM7LPEN (1 << 5) /* Bit 5: TIM7 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM12LPEN (1 << 6) /* Bit 6: TIM12 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM13LPEN (1 << 7) /* Bit 7: TIM13 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM14LPEN (1 << 8) /* Bit 8: TIM14 clock enable during Sleep mode */ +#define RCC_APB1LPENR_WWDGLPEN (1 << 11) /* Bit 11: Window watchdog clock enable during Sleep mode */ +#define RCC_APB1LPENR_SPI2LPEN (1 << 14) /* Bit 14: SPI2 clock enable during Sleep mode */ +#define RCC_APB1LPENR_SPI3LPEN (1 << 15) /* Bit 15: SPI3 clock enable during Sleep mode */ +#define RCC_APB1LPENR_USART2LPEN (1 << 17) /* Bit 17: USART 2 clock enable during Sleep mode */ +#define RCC_APB1LPENR_USART3LPEN (1 << 18) /* Bit 18: USART3 clock enable during Sleep mode */ +#define RCC_APB1LPENR_UART4LPEN (1 << 19) /* Bit 19: UART4 clock enable during Sleep mode */ +#define RCC_APB1LPENR_UART5LPEN (1 << 20) /* Bit 20: UART5 clock enable during Sleep mode */ +#define RCC_APB1LPENR_I2C1LPEN (1 << 21) /* Bit 21: I2C1 clock enable during Sleep mode */ +#define RCC_APB1LPENR_I2C2LPEN (1 << 22) /* Bit 22: I2C2 clock enable during Sleep mode */ +#define RCC_APB1LPENR_I2C3LPEN (1 << 23) /* Bit 23: I2C3 clock enable during Sleep mode */ +#define RCC_APB1LPENR_CAN1LPEN (1 << 25) /* Bit 25: CAN 1 clock enable during Sleep mode */ +#define RCC_APB1LPENR_CAN2LPEN (1 << 26) /* Bit 26: CAN 2 clock enable during Sleep mode */ +#define RCC_APB1LPENR_PWRLPEN (1 << 28) /* Bit 28: Power interface clock enable during Sleep mode */ +#define RCC_APB1LPENR_DACLPEN (1 << 29) /* Bit 29: DAC interface clock enable during Sleep mode */ + +/* RCC APB2 low power modeperipheral clock enable register */ + +#define RCC_APB2LPENR_TIM1LPEN (1 << 0) /* Bit 0: TIM1 clock enable during Sleep mode */ +#define RCC_APB2LPENR_TIM8LPEN (1 << 1) /* Bit 1: TIM8 clock enable during Sleep mode */ +#define RCC_APB2LPENR_USART1LPEN (1 << 4) /* Bit 4: USART1 clock enable during Sleep mode */ +#define RCC_APB2LPENR_USART6LPEN (1 << 5) /* Bit 5: USART6 clock enable during Sleep mode */ +#define RCC_APB2LPENR_ADC1LPEN (1 << 8) /* Bit 8: ADC1 clock enable during Sleep mode */ +#define RCC_APB2LPENR_ADC2LPEN (1 << 9) /* Bit 9: ADC2 clock enable during Sleep mode */ +#define RCC_APB2LPENR_ADC3LPEN (1 << 10) /* Bit 10: ADC3 clock enable during Sleep mode */ +#define RCC_APB2LPENR_SDIOLPEN (1 << 11) /* Bit 11: SDIO clock enable during Sleep mode */ +#define RCC_APB2LPENR_SPI1LPEN (1 << 12) /* Bit 12: SPI1 clock enable during Sleep mode */ +#define RCC_APB2LPENR_SYSCFGLPEN (1 << 14) /* Bit 14: System configuration controller clock enable during Sleep mode */ +#define RCC_APB2LPENR_TIM9LPEN (1 << 16) /* Bit 16: TIM9 clock enable during Sleep mode */ +#define RCC_APB2LPENR_TIM10LPEN (1 << 17) /* Bit 17: TIM10 clock enable during Sleep mode */ +#define RCC_APB2LPENR_TIM11LPEN (1 << 18) /* Bit 18: TIM11 clock enable during Sleep mode */ + +/* Backup domain control register */ + +#define RCC_BDCR_LSEON (1 << 0) /* Bit 0: External Low Speed oscillator enable */ +#define RCC_BDCR_LSERDY (1 << 1) /* Bit 1: External Low Speed oscillator Ready */ +#define RCC_BDCR_LSEBYP (1 << 2) /* Bit 2: External Low Speed oscillator Bypass */ +#define RCC_BDCR_RTCSEL_SHIFT (8) /* Bits 9:8: RTC clock source selection */ +#define RCC_BDCR_RTCSEL_MASK (3 << RCC_BDCR_RTCSEL_SHIFT) +# define RCC_BDCR_RTCSEL_NOCLK (0 << RCC_BDCR_RTCSEL_SHIFT) /* 00: No clock */ +# define RCC_BDCR_RTCSEL_LSE (1 << RCC_BDCR_RTCSEL_SHIFT) /* 01: LSE oscillator clock used as RTC clock */ +# define RCC_BDCR_RTCSEL_LSI (2 << RCC_BDCR_RTCSEL_SHIFT) /* 10: LSI oscillator clock used as RTC clock */ +# define RCC_BDCR_RTCSEL_HSE (3 << RCC_BDCR_RTCSEL_SHIFT) /* 11: HSE oscillator clock divided by 128 used as RTC clock */ +#define RCC_BDCR_RTCEN (1 << 15) /* Bit 15: RTC clock enable */ +#define RCC_BDCR_BDRST (1 << 16) /* Bit 16: Backup domain software reset */ + +/* Control/status register */ + +#define RCC_CSR_LSION (1 << 0) /* Bit 0: Internal Low Speed oscillator enable */ +#define RCC_CSR_LSIRDY (1 << 1) /* Bit 1: Internal Low Speed oscillator Ready */ +#define RCC_CSR_RMVF (1 << 24) /* Bit 24: Remove reset flag */ +#define RCC_CSR_BORRSTF (1 << 25) /* Bit 25: BOR reset flag */ +#define RCC_CSR_PINRSTF (1 << 26) /* Bit 26: PIN reset flag */ +#define RCC_CSR_PORRSTF (1 << 27) /* Bit 27: POR/PDR reset flag */ +#define RCC_CSR_SFTRSTF (1 << 28) /* Bit 28: Software Reset flag */ +#define RCC_CSR_IWDGRSTF (1 << 29) /* Bit 29: Independent Watchdog reset flag */ +#define RCC_CSR_WWDGRSTF (1 << 30) /* Bit 30: Window watchdog reset flag */ +#define RCC_CSR_LPWRRSTF (1 << 31) /* Bit 31: Low-Power reset flag */ + +/* Spread spectrum clock generation register */ + +#define RCC_SSCGR_MODPER_SHIFT (0) /* Bit 0-12: Modulation period */ +#define RCC_SSCGR_MODPER_MASK (0x1fff << RCC_SSCGR_MODPER_SHIFT) +# define RCC_SSCGR_MODPER(n) ((n) << RCC_SSCGR_MODPER_SHIFT) +#define RCC_SSCGR_INCSTEP_SHIFT (13) /* Bit 13-27: Incrementation step */ +#define RCC_SSCGR_INCSTEP_MASK (0x7fff << RCC_SSCGR_INCSTEP_SHIFT) +# define RCC_SSCGR_INCSTEP(n) ((n) << RCC_SSCGR_INCSTEP_SHIFT) +#define RCC_SSCGR_SPREADSEL (1 << 30) /* Bit 30: Spread Select */ +#define RCC_SSCGR_SSCGEN (1 << 31) /* Bit 31: Spread spectrum modulation enable */ + +/* PLLI2S configuration register */ + +#define RCC_PLLI2SCFGR_PLLI2SN_SHIFT (6) /* Bits 6-14: PLLI2S multiplication factor for VCO */ +#define RCC_PLLI2SCFGR_PLLI2SN_MASK (0x1ff << RCC_PLLI2SCFGR_PLLI2SN_SHIFT) +#define RCC_PLLI2SCFGR_PLLI2SR_SHIFT (28) /* Bits 28-30: PLLI2S division factor for I2S clocks */ +#define RCC_PLLI2SCFGR_PLLI2SR_MASK (7 << RCC_PLLI2SCFGR_PLLI2SR_SHIFT) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_RCC_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rtc.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rtc.h new file mode 100644 index 0000000000..b0d7ec9135 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rtc.h @@ -0,0 +1,338 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f20xxx_rtc.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_RTC_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_RTC_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +#define STM32_RTC_TR_OFFSET 0x0000 /* RTC time register */ +#define STM32_RTC_DR_OFFSET 0x0004 /* RTC date register */ +#define STM32_RTC_CR_OFFSET 0x0008 /* RTC control register */ +#define STM32_RTC_ISR_OFFSET 0x000c /* RTC initialization and status register */ +#define STM32_RTC_PRER_OFFSET 0x0010 /* RTC prescaler register */ +#define STM32_RTC_WUTR_OFFSET 0x0014 /* RTC wakeup timer register */ +#define STM32_RTC_CALIBR_OFFSET 0x0018 /* RTC calibration register */ +#define STM32_RTC_ALRMAR_OFFSET 0x001c /* RTC alarm A register */ +#define STM32_RTC_ALRMBR_OFFSET 0x0020 /* RTC alarm B register */ +#define STM32_RTC_WPR_OFFSET 0x0024 /* RTC write protection register */ +#define STM32_RTC_SSR_OFFSET 0x0028 /* RTC sub second register */ +#define STM32_RTC_SHIFTR_OFFSET 0x002c /* RTC shift control register */ +#define STM32_RTC_TSTR_OFFSET 0x0030 /* RTC time stamp time register */ +#define STM32_RTC_TSDR_OFFSET 0x0030 /* RTC time stamp date register */ +#define STM32_RTC_TSSSR_OFFSET 0x0038 /* RTC timestamp sub second register */ +#define STM32_RTC_CALR_OFFSET 0x003c /* RTC calibration register */ +#define STM32_RTC_TAFCR_OFFSET 0x0040 /* RTC tamper and alternate function configuration register */ +#define STM32_RTC_ALRMASSR_OFFSET 0x0044 /* RTC alarm A sub second register */ +#define STM32_RTC_ALRMBSSR_OFFSET 0x0048 /* RTC alarm B sub second register */ + +#define STM32_RTC_BKR_OFFSET(n) (0x0050+((n)<<2)) +#define STM32_RTC_BK0R_OFFSET 0x0050 /* RTC backup register 0 */ +#define STM32_RTC_BK1R_OFFSET 0x0054 /* RTC backup register 1 */ +#define STM32_RTC_BK2R_OFFSET 0x0058 /* RTC backup register 2 */ +#define STM32_RTC_BK3R_OFFSET 0x005c /* RTC backup register 3 */ +#define STM32_RTC_BK4R_OFFSET 0x0060 /* RTC backup register 4 */ +#define STM32_RTC_BK5R_OFFSET 0x0064 /* RTC backup register 5 */ +#define STM32_RTC_BK6R_OFFSET 0x0068 /* RTC backup register 6 */ +#define STM32_RTC_BK7R_OFFSET 0x006c /* RTC backup register 7 */ +#define STM32_RTC_BK8R_OFFSET 0x0070 /* RTC backup register 8 */ +#define STM32_RTC_BK9R_OFFSET 0x0074 /* RTC backup register 9 */ +#define STM32_RTC_BK10R_OFFSET 0x0078 /* RTC backup register 10 */ +#define STM32_RTC_BK11R_OFFSET 0x007c /* RTC backup register 11 */ +#define STM32_RTC_BK12R_OFFSET 0x0080 /* RTC backup register 12 */ +#define STM32_RTC_BK13R_OFFSET 0x0084 /* RTC backup register 13 */ +#define STM32_RTC_BK14R_OFFSET 0x0088 /* RTC backup register 14 */ +#define STM32_RTC_BK15R_OFFSET 0x008c /* RTC backup register 15 */ +#define STM32_RTC_BK16R_OFFSET 0x0090 /* RTC backup register 16 */ +#define STM32_RTC_BK17R_OFFSET 0x0094 /* RTC backup register 17 */ +#define STM32_RTC_BK18R_OFFSET 0x0098 /* RTC backup register 18 */ +#define STM32_RTC_BK19R_OFFSET 0x009c /* RTC backup register 19 */ + +/* Register Addresses ***************************************************************/ + +#define STM32_RTC_TR (STM32_RTC_BASE+STM32_RTC_TR_OFFSET) +#define STM32_RTC_DR (STM32_RTC_BASE+STM32_RTC_DR_OFFSET) +#define STM32_RTC_CR (STM32_RTC_BASE+STM32_RTC_CR_OFFSET) +#define STM32_RTC_ISR (STM32_RTC_BASE+STM32_RTC_ISR_OFFSET) +#define STM32_RTC_PRER (STM32_RTC_BASE+STM32_RTC_PRER_OFFSET) +#define STM32_RTC_WUTR (STM32_RTC_BASE+STM32_RTC_WUTR_OFFSET) +#define STM32_RTC_CALIBR (STM32_RTC_BASE+STM32_RTC_CALIBR_OFFSET) +#define STM32_RTC_ALRMAR (STM32_RTC_BASE+STM32_RTC_ALRMAR_OFFSET) +#define STM32_RTC_ALRMBR (STM32_RTC_BASE+STM32_RTC_ALRMBR_OFFSET) +#define STM32_RTC_WPR (STM32_RTC_BASE+STM32_RTC_WPR_OFFSET) +#define STM32_RTC_SSR (STM32_RTC_BASE+STM32_RTC_SSR_OFFSET) +#define STM32_RTC_SHIFTR (STM32_RTC_BASE+STM32_RTC_SHIFTR_OFFSET) +#define STM32_RTC_TSTR (STM32_RTC_BASE+STM32_RTC_TSTR_OFFSET) +#define STM32_RTC_TSDR (STM32_RTC_BASE+STM32_RTC_TSDR_OFFSET) +#define STM32_RTC_TSSSR (STM32_RTC_BASE+STM32_RTC_TSSSR_OFFSET) +#define STM32_RTC_CALR (STM32_RTC_BASE+STM32_RTC_CALR_OFFSET) +#define STM32_RTC_TAFCR (STM32_RTC_BASE+STM32_RTC_TAFCR_OFFSET) +#define STM32_RTC_ALRMASSR (STM32_RTC_BASE+STM32_RTC_ALRMASSR_OFFSET) +#define STM32_RTC_ALRMBSSR (STM32_RTC_BASE+STM32_RTC_ALRMBSSR_OFFSET) + +#define STM32_RTC_BKR(n) (STM32_RTC_BASE+STM32_RTC_BKR_OFFSET(n)) +#define STM32_RTC_BK0R (STM32_RTC_BASE+STM32_RTC_BK0R_OFFSET) +#define STM32_RTC_BK1R (STM32_RTC_BASE+STM32_RTC_BK1R_OFFSET) +#define STM32_RTC_BK2R (STM32_RTC_BASE+STM32_RTC_BK2R_OFFSET) +#define STM32_RTC_BK3R (STM32_RTC_BASE+STM32_RTC_BK3R_OFFSET) +#define STM32_RTC_BK4R (STM32_RTC_BASE+STM32_RTC_BK4R_OFFSET) +#define STM32_RTC_BK5R (STM32_RTC_BASE+STM32_RTC_BK5R_OFFSET) +#define STM32_RTC_BK6R (STM32_RTC_BASE+STM32_RTC_BK6R_OFFSET) +#define STM32_RTC_BK7R (STM32_RTC_BASE+STM32_RTC_BK7R_OFFSET) +#define STM32_RTC_BK8R (STM32_RTC_BASE+STM32_RTC_BK8R_OFFSET) +#define STM32_RTC_BK9R (STM32_RTC_BASE+STM32_RTC_BK9R_OFFSET) +#define STM32_RTC_BK10R (STM32_RTC_BASE+STM32_RTC_BK10R_OFFSET) +#define STM32_RTC_BK11R (STM32_RTC_BASE+STM32_RTC_BK11R_OFFSET) +#define STM32_RTC_BK12R (STM32_RTC_BASE+STM32_RTC_BK12R_OFFSET) +#define STM32_RTC_BK13R (STM32_RTC_BASE+STM32_RTC_BK13R_OFFSET) +#define STM32_RTC_BK14R (STM32_RTC_BASE+STM32_RTC_BK14R_OFFSET) +#define STM32_RTC_BK15R (STM32_RTC_BASE+STM32_RTC_BK15R_OFFSET) +#define STM32_RTC_BK16R (STM32_RTC_BASE+STM32_RTC_BK16R_OFFSET) +#define STM32_RTC_BK17R (STM32_RTC_BASE+STM32_RTC_BK17R_OFFSET) +#define STM32_RTC_BK18R (STM32_RTC_BASE+STM32_RTC_BK18R_OFFSET) +#define STM32_RTC_BK19R (STM32_RTC_BASE+STM32_RTC_BK19R_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +/* RTC time register */ + +#define RTC_TR_SU_SHIFT (0) /* Bits 0-3: Second units in BCD format */ +#define RTC_TR_SU_MASK (15 << RTC_TR_SU_SHIFT) +#define RTC_TR_ST_SHIFT (4) /* Bits 4-6: Second tens in BCD format */ +#define RTC_TR_ST_MASK (7 << RTC_TR_ST_SHIFT) +#define RTC_TR_MNU_SHIFT (8) /* Bit 8-11: Minute units in BCD format */ +#define RTC_TR_MNU_MASK (15 << RTC_TR_MNU_SHIFT) +#define RTC_TR_MNT_SHIFT (12) /* Bits 12-14: Minute tens in BCD format */ +#define RTC_TR_MNT_MASK (7 << RTC_TR_MNT_SHIFT) +#define RTC_TR_HU_SHIFT (16) /* Bit 16-19: Hour units in BCD format */ +#define RTC_TR_HU_MASK (15 << RTC_TR_HU_SHIFT) +#define RTC_TR_HT_SHIFT (20) /* Bits 20-21: Hour tens in BCD format */ +#define RTC_TR_HT_MASK (3 << RTC_TR_HT_SHIFT) +#define RTC_TR_PM (1 << 22) /* Bit 22: AM/PM notation */ +#define RTC_TR_RESERVED_BITS (0xff808080) + +/* RTC date register */ + +#define RTC_DR_DU_SHIFT (0) /* Bits 0-3: Date units in BCD format */ +#define RTC_DR_DU_MASK (15 << RTC_DR_DU_SHIFT) +#define RTC_DR_DT_SHIFT (4) /* Bits 4-5: Date tens in BCD format */ +#define RTC_DR_DT_MASK (3 << RTC_DR_DT_SHIFT) +#define RTC_DR_MU_SHIFT (8) /* Bits 8-11: Month units in BCD format */ +#define RTC_DR_MU_MASK (15 << RTC_DR_MU_SHIFT) +#define RTC_DR_MT (1 << 12) /* Bit 12: Month tens in BCD format */ +#define RTC_DR_WDU_SHIFT (13) /* Bits 13-15: Week day units */ +#define RTC_DR_WDU_MASK (7 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_MONDAY (1 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_TUESDAY (2 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_WEDNESDAY (3 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_THURSDAY (4 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_FRIDAY (5 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_SATURDAY (6 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_SUNDAY (7 << RTC_DR_WDU_SHIFT) +#define RTC_DR_YU_SHIFT (16) /* Bits 16-19: Year units in BCD format */ +#define RTC_DR_YU_MASK (15 << RTC_DR_YU_SHIFT) +#define RTC_DR_YT_SHIFT (20) /* Bits 20-23: Year tens in BCD format */ +#define RTC_DR_YT_MASK (15 << RTC_DR_YT_SHIFT) +#define RTC_DR_RESERVED_BITS (0xff0000c0) + +/* RTC control register */ + +#define RTC_CR_WUCKSEL_SHIFT (0) /* Bits 0-2: Wakeup clock selection */ +#define RTC_CR_WUCKSEL_MASK (7 << RTC_CR_WUCKSEL_SHIFT) +# define RTC_CR_WUCKSEL_RTCDIV16 (0 << RTC_CR_WUCKSEL_SHIFT) /* 000: RTC/16 clock is selected */ +# define RTC_CR_WUCKSEL_RTCDIV8 (1 << RTC_CR_WUCKSEL_SHIFT) /* 001: RTC/8 clock is selected */ +# define RTC_CR_WUCKSEL_RTCDIV4 (2 << RTC_CR_WUCKSEL_SHIFT) /* 010: RTC/4 clock is selected */ +# define RTC_CR_WUCKSEL_RTCDIV2 (3 << RTC_CR_WUCKSEL_SHIFT) /* 011: RTC/2 clock is selected */ +# define RTC_CR_WUCKSEL_CKSPRE (4 << RTC_CR_WUCKSEL_SHIFT) /* 10x: ck_spre clock is selected */ +# define RTC_CR_WUCKSEL_CKSPREADD (6 << RTC_CR_WUCKSEL_SHIFT) /* 11x: ck_spr clock and 216 added WUT counter */ +#define RTC_CR_TSEDGE (1 << 3) /* Bit 3: Timestamp event active edge */ +#define RTC_CR_REFCKON (1 << 4) /* Bit 4: Reference clock detection enable (50 or 60 Hz) */ +#define RTC_CR_BYPSHAD (1 << 5) /* Bit 5: Bypass the shadow registers */ +#define RTC_CR_FMT (1 << 6) /* Bit 6: Hour format */ +#define RTC_CR_DCE (1 << 7) /* Bit 7: Coarse digital calibration enable */ +#define RTC_CR_ALRAE (1 << 8) /* Bit 8: Alarm A enable */ +#define RTC_CR_ALRBE (1 << 9) /* Bit 9: Alarm B enable */ +#define RTC_CR_WUTE (1 << 10) /* Bit 10: Wakeup timer enable */ +#define RTC_CR_TSE (1 << 11) /* Bit 11: Time stamp enable */ +#define RTC_CR_ALRAIE (1 << 12) /* Bit 12: Alarm A interrupt enable */ +#define RTC_CR_ALRBIE (1 << 13) /* Bit 13: Alarm B interrupt enable */ +#define RTC_CR_WUTIE (1 << 14) /* Bit 14: Wakeup timer interrupt enable */ +#define RTC_CR_TSIE (1 << 15) /* Bit 15: Timestamp interrupt enable */ +#define RTC_CR_ADD1H (1 << 16) /* Bit 16: Add 1 hour (summer time change) */ +#define RTC_CR_SUB1H (1 << 17) /* Bit 17: Subtract 1 hour (winter time change) */ +#define RTC_CR_BKP (1 << 18) /* Bit 18: Backup */ +#define RTC_CR_COSEL (1 << 19) /* Bit 19 : Calibration output selection */ +#define RTC_CR_POL (1 << 20) /* Bit 20: Output polarity */ +#define RTC_CR_OSEL_SHIFT (21) /* Bits 21-22: Output selection */ +#define RTC_CR_OSEL_MASK (3 << RTC_CR_OSEL_SHIFT) +# define RTC_CR_OSEL_DISABLED (0 << RTC_CR_OSEL_SHIFT) /* 00: Output disabled */ +# define RTC_CR_OSEL_ALRMA (1 << RTC_CR_OSEL_SHIFT) /* 01: Alarm A output enabled */ +# define RTC_CR_OSEL_ALRMB (2 << RTC_CR_OSEL_SHIFT) /* 10: Alarm B output enabled */ +# define RTC_CR_OSEL_WUT (3 << RTC_CR_OSEL_SHIFT) /* 11: Wakeup output enabled */ +#define RTC_CR_COE (1 << 23) /* Bit 23: Calibration output enable */ + +/* RTC initialization and status register */ + +#define RTC_ISR_ALRAWF (1 << 0) /* Bit 0: Alarm A write flag */ +#define RTC_ISR_ALRBWF (1 << 1) /* Bit 1: Alarm B write flag */ +#define RTC_ISR_WUTWF (1 << 2) /* Bit 2: Wakeup timer write flag */ +#define RTC_ISR_SHPF (1 << 3) /* Bit 3: Shift operation pending */ +#define RTC_ISR_INITS (1 << 4) /* Bit 4: Initialization status flag */ +#define RTC_ISR_RSF (1 << 5) /* Bit 5: Registers synchronization flag */ +#define RTC_ISR_INITF (1 << 6) /* Bit 6: Initialization flag */ +#define RTC_ISR_INIT (1 << 7) /* Bit 7: Initialization mode */ +#define RTC_ISR_ALRAF (1 << 8) /* Bit 8: Alarm A flag */ +#define RTC_ISR_ALRBF (1 << 9) /* Bit 9: Alarm B flag */ +#define RTC_ISR_WUTF (1 << 10) /* Bit 10: Wakeup timer flag */ +#define RTC_ISR_TSF (1 << 11) /* Bit 11: Timestamp flag */ +#define RTC_ISR_TSOVF (1 << 12) /* Bit 12: Timestamp overflow flag */ +#define RTC_ISR_TAMP1F (1 << 13) /* Bit 13: Tamper detection flag */ +#define RTC_ISR_TAMP2F (1 << 14) /* Bit 14: TAMPER2 detection flag */ +#define RTC_ISR_RECALPF (1 << 16) /* Bit 16: Recalibration pending Flag */ +#define RTC_ISR_ALLFLAGS (0x00017fff) + +/* RTC prescaler register */ + +#define RTC_PRER_PREDIV_S_SHIFT (0) /* Bits 0-14: Synchronous prescaler factor */ +#define RTC_PRER_PREDIV_S_MASK (0x7fff << RTC_PRER_PREDIV_S_SHIFT) +#define RTC_PRER_PREDIV_A_SHIFT (16) /* Bits 16-22: Asynchronous prescaler factor */ +#define RTC_PRER_PREDIV_A_MASK (0x7f << RTC_PRER_PREDIV_A_SHIFT) + +/* RTC wakeup timer register */ + +#define RTC_WUTR_MASK (0xffff) /* Bits 15:0 Wakeup auto-reload value bits */ + +/* RTC calibration register */ + +#define RTC_CALIBR_DCS (1 << 7) /* Bit 7 Digital calibration sign */ +#define RTC_CALIBR_DC_SHIFT (0) /* Bits 4:0 0-4: Digital calibration */ +#define RTC_CALIBR_DC_MASK (31 << RTC_CALIBR_DC_SHIFT) +# define RTC_CALIBR_DC(n) (((n) >> 2) << RTC_CALIBR_DC_SHIFT) /* n= 0, 4, 8, ... 126 */ + +/* RTC alarm A/B registers */ + +#define RTC_ALRMR_SU_SHIFT (0) /* Bits 0-3: Second units in BCD format. */ +#define RTC_ALRMR_SU_MASK (15 << RTC_ALRMR_SU_SHIFT) +#define RTC_ALRMR_ST_SHIFT (4) /* Bits 4-6: Second tens in BCD format. */ +#define RTC_ALRMR_ST_MASK (7 << RTC_ALRMR_ST_SHIFT) +#define RTC_ALRMR_MSK1 (1 << 7) /* Bit 7 : Alarm A seconds mask */ +#define RTC_ALRMR_MNU_SHIFT (8) /* Bits 8-11: Minute units in BCD format. */ +#define RTC_ALRMR_MNU_MASK (15 << RTC_ALRMR_MNU_SHIFT) +#define RTC_ALRMR_MNT_SHIFT (12) /* Bits 12-14: Minute tens in BCD format. */ +#define RTC_ALRMR_MNT_MASK (7 << RTC_ALRMR_MNT_SHIFT) +#define RTC_ALRMR_MSK2 (1 << 15) /* Bit 15 : Alarm A minutes mask */ +#define RTC_ALRMR_HU_SHIFT (16) /* Bits 16-19: Hour units in BCD format. */ +#define RTC_ALRMR_HU_MASK (15 << RTC_ALRMR_HU_SHIFT) +#define RTC_ALRMR_HT_SHIFT (20) /* Bits 20-21: Hour tens in BCD format. */ +#define RTC_ALRMR_HT_MASK (3 << RTC_ALRMR_HT_SHIFT) +#define RTC_ALRMR_PM (1 << 22) /* Bit 22 : AM/PM notation */ +#define RTC_ALRMR_MSK3 (1 << 23) /* Bit 23 : Alarm A hours mask */ +#define RTC_ALRMR_DU_SHIFT (24) /* Bits 24-27: Date units or day in BCD format. */ +#define RTC_ALRMR_DU_MASK (15 << RTC_ALRMR_DU_SHIFT) +#define RTC_ALRMR_DT_SHIFT (28) /* Bits 28-29: Date tens in BCD format. */ +#define RTC_ALRMR_DT_MASK (3 << RTC_ALRMR_DT_SHIFT) +#define RTC_ALRMR_WDSEL (1 << 30) /* Bit 30: Week day selection */ +#define RTC_ALRMR_MSK4 (1 << 31) /* Bit 31: Alarm A date mask */ + +/* RTC write protection register */ + +#define RTC_WPR_MASK (0xff) /* Bits 0-7: Write protection key */ + +/* RTC sub second register */ + +#define RTC_SSR_MASK (0xffff) /* Bits 0-15: Sub second value */ + +/* RTC shift control register */ + +#define RTC_SHIFTR_SUBFS_SHIFT (0) /* Bits 0-14: Subtract a fraction of a second */ +#define RTC_SHIFTR_SUBFS_MASK (0x7ffff << RTC_SHIFTR_SUBFS_SHIFT) +#define RTC_SHIFTR_ADD1S (1 << 31) /* Bit 31: Add one second */ + +/* RTC time stamp time register */ + +#define RTC_TSTR_SU_SHIFT (0) /* Bits 0-3: Second units in BCD format. */ +#define RTC_TSTR_SU_MASK (15 << RTC_TSTR_SU_SHIFT) +#define RTC_TSTR_ST_SHIFT (4) /* Bits 4-6: Second tens in BCD format. */ +#define RTC_TSTR_ST_MASK (7 << RTC_TSTR_ST_SHIFT) +#define RTC_TSTR_MNU_SHIFT (8) /* Bits 8-11: Minute units in BCD format. */ +#define RTC_TSTR_MNU_MASK (15 << RTC_TSTR_MNU_SHIFT) +#define RTC_TSTR_MNT_SHIFT (12) /* Bits 12-14: Minute tens in BCD format. */ +#define RTC_TSTR_MNT_MASK (7 << RTC_TSTR_MNT_SHIFT) +#define RTC_TSTR_HU_SHIFT (16) /* Bits 16-19: Hour units in BCD format. */ +#define RTC_TSTR_HU_MASK (15 << RTC_TSTR_HU_SHIFT) +#define RTC_TSTR_HT_SHIFT (20) /* Bits 20-21: Hour tens in BCD format. */ +#define RTC_TSTR_HT_MASK (3 << RTC_TSTR_HT_SHIFT) +#define RTC_TSTR_PM (1 << 22) /* Bit 22: AM/PM notation */ + +/* RTC time stamp date register */ + +#define RTC_TSDR_DU_SHIFT (0) /* Bit 0-3: Date units in BCD format */ +#define RTC_TSDR_DU_MASK (15 << RTC_TSDR_DU_SHIFT) */ +#define RTC_TSDR_DT_SHIFT (4) /* Bits 4-5: Date tens in BCD format */ +#define RTC_TSDR_DT_MASK (3 << RTC_TSDR_DT_SHIFT) +#define RTC_TSDR_MU_SHIFT (8) /* Bits 8-11: Month units in BCD format */ +#define RTC_TSDR_MU_MASK (xx << RTC_TSDR_MU_SHIFT) +#define RTC_TSDR_MT (1 << 12) /* Bit 12: Month tens in BCD format */ +#define RTC_TSDR_WDU_SHIFT (13) /* Bits 13-15: Week day units */ +#define RTC_TSDR_WDU_MASK (7 << RTC_TSDR_WDU_SHIFT) + +/* RTC timestamp sub second register */ + +#define RTC_TSSSR_MASK (0xffff) /* Bits 0-15: Sub second value */ + +/* RTC calibration register */ + +#define RTC_CALR_ + +/* RTC tamper and alternate function configuration register */ + +#define RTC_TAFCR_CALM_SHIFT (0) /* Bits 0-8: Calibration minus */ +#define RTC_TAFCR_CALM_MASK (0x1ff << RTC_TAFCR_CALM_SHIFT) +#define RTC_TAFCR_CALW16 (1 << 13) /* Bit 13: Use a 16-second calibration cycle period */ +#define RTC_TAFCR_CALW8 (1 << 14) /* Bit 14: Use an 8-second calibration cycle period */ +#define RTC_TAFCR_CALP (1 << 15) /* Bit 15: Increase frequency of RTC by 488.5 ppm */ + +/* RTC alarm A/B sub second register */ + +#define RTC_ALRMSSR_SS_SHIFT (0) /* Bits 0-15: Sub second value */ +#define RTC_ALRMSSR_SS_MASK (0xffff << RTC_ALRMSSR_SS_SHIFT) +#define RTC_ALRMSSR_MASKSS_SHIFT (0) /* Bits 24-27: Mask the most-significant bits starting at this bit */ +#define RTC_ALRMSSR_MASKSS_MASK (0xffff << RTC_ALRMSSR_SS_SHIFT) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_RTC_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_vectors.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_vectors.h new file mode 100644 index 0000000000..12fb5565c1 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_vectors.h @@ -0,0 +1,141 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f20xxx_vectors.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Pre-processor definitions + ************************************************************************************/ + +/* This file is included by stm32_vectors.S. It provides the macro VECTOR that + * supplies ach STM32F20xxx vector in terms of a (lower-case) ISR label and an + * (upper-case) IRQ number as defined in arch/arm/include/stm32/stm32f20xxx_irq.h. + * stm32_vectors.S will defined the VECTOR in different ways in order to generate + * the interrupt vectors and handlers in their final form. + */ + +/* If the common ARMv7-M vector handling is used, then all it needs is the following + * definition that provides the number of supported vectors. + */ + +#ifdef CONFIG_ARMV7M_CMNVECTOR + +/* Reserve 82 interrupt table entries for I/O interrupts. */ + +# define ARMV7M_PERIPHERAL_INTERRUPTS 82 + +#else + +VECTOR(stm32_wwdg, STM32_IRQ_WWDG) /* Vector 16+0: Window Watchdog interrupt */ +VECTOR(stm32_pvd, STM32_IRQ_PVD) /* Vector 16+1: PVD through EXTI Line detection interrupt */ +VECTOR(stm32_tamper, STM32_IRQ_TAMPER) /* Vector 16+2: Tamper and time stamp interrupts */ +VECTOR(stm32_rtc_wkup, STM32_IRQ_RTC_WKUP) /* Vector 16+3: RTC global interrupt */ +VECTOR(stm32_flash, STM32_IRQ_FLASH) /* Vector 16+4: Flash global interrupt */ +VECTOR(stm32_rcc, STM32_IRQ_RCC) /* Vector 16+5: RCC global interrupt */ +VECTOR(stm32_exti0, STM32_IRQ_EXTI0) /* Vector 16+6: EXTI Line 0 interrupt */ +VECTOR(stm32_exti1, STM32_IRQ_EXTI1) /* Vector 16+7: EXTI Line 1 interrupt */ +VECTOR(stm32_exti2, STM32_IRQ_EXTI2) /* Vector 16+8: EXTI Line 2 interrupt */ +VECTOR(stm32_exti3, STM32_IRQ_EXTI3) /* Vector 16+9: EXTI Line 3 interrupt */ +VECTOR(stm32_exti4, STM32_IRQ_EXTI4) /* Vector 16+10: EXTI Line 4 interrupt */ +VECTOR(stm32_dma1s0, STM32_IRQ_DMA1S0) /* Vector 16+11: DMA1 Stream 0 global interrupt */ +VECTOR(stm32_dma1s1, STM32_IRQ_DMA1S1) /* Vector 16+12: DMA1 Stream 1 global interrupt */ +VECTOR(stm32_dma1s2, STM32_IRQ_DMA1S2) /* Vector 16+13: DMA1 Stream 2 global interrupt */ +VECTOR(stm32_dma1s3, STM32_IRQ_DMA1S3) /* Vector 16+14: DMA1 Stream 3 global interrupt */ +VECTOR(stm32_dma1s4, STM32_IRQ_DMA1S4) /* Vector 16+15: DMA1 Stream 4 global interrupt */ +VECTOR(stm32_dma1s5, STM32_IRQ_DMA1S5) /* Vector 16+16: DMA1 Stream 5 global interrupt */ +VECTOR(stm32_dma1s6, STM32_IRQ_DMA1S6) /* Vector 16+17: DMA1 Stream 6 global interrupt */ +VECTOR(stm32_adc, STM32_IRQ_ADC) /* Vector 16+18: ADC1, ADC2, and ADC3 global interrupt */ +VECTOR(stm32_can1tx, STM32_IRQ_CAN1TX) /* Vector 16+19: CAN1 TX interrupts */ +VECTOR(stm32_can1rx0, STM32_IRQ_CAN1RX0) /* Vector 16+20: CAN1 RX0 interrupts */ +VECTOR(stm32_can1rx1, STM32_IRQ_CAN1RX1) /* Vector 16+21: CAN1 RX1 interrupt */ +VECTOR(stm32_can1sce, STM32_IRQ_CAN1SCE) /* Vector 16+22: CAN1 SCE interrupt */ +VECTOR(stm32_exti95, STM32_IRQ_EXTI95) /* Vector 16+23: EXTI Line[9:5] interrupts */ +VECTOR(stm32_tim1brk, STM32_IRQ_TIM1BRK) /* Vector 16+24: TIM1 Break interrupt/TIM9 global interrupt */ +VECTOR(stm32_tim1up, STM32_IRQ_TIM1UP) /* Vector 16+25: TIM1 Update interrupt/TIM10 global interrupt */ +VECTOR(stm32_tim1trgcom, STM32_IRQ_TIM1TRGCOM) /* Vector 16+26: TIM1 Trigger and Commutation interrupts/TIM11 global interrupt */ +VECTOR(stm32_tim1cc, STM32_IRQ_TIM1CC) /* Vector 16+27: TIM1 Capture Compare interrupt */ +VECTOR(stm32_tim2, STM32_IRQ_TIM2) /* Vector 16+28: TIM2 global interrupt */ +VECTOR(stm32_tim3, STM32_IRQ_TIM3) /* Vector 16+29: TIM3 global interrupt */ +VECTOR(stm32_tim4, STM32_IRQ_TIM4) /* Vector 16+30: TIM4 global interrupt */ +VECTOR(stm32_i2c1ev, STM32_IRQ_I2C1EV) /* Vector 16+31: I2C1 event interrupt */ +VECTOR(stm32_i2c1er, STM32_IRQ_I2C1ER) /* Vector 16+32: I2C1 error interrupt */ +VECTOR(stm32_i2c2ev, STM32_IRQ_I2C2EV) /* Vector 16+33: I2C2 event interrupt */ +VECTOR(stm32_i2c2er, STM32_IRQ_I2C2ER) /* Vector 16+34: I2C2 error interrupt */ +VECTOR(stm32_spi1, STM32_IRQ_SPI1) /* Vector 16+35: SPI1 global interrupt */ +VECTOR(stm32_spi2, STM32_IRQ_SPI2) /* Vector 16+36: SPI2 global interrupt */ +VECTOR(stm32_usart1, STM32_IRQ_USART1) /* Vector 16+37: USART1 global interrupt */ +VECTOR(stm32_usart2, STM32_IRQ_USART2) /* Vector 16+38: USART2 global interrupt */ +VECTOR(stm32_usart3, STM32_IRQ_USART3) /* Vector 16+39: USART3 global interrupt */ +VECTOR(stm32_exti1510, STM32_IRQ_EXTI1510) /* Vector 16+40: EXTI Line[15:10] interrupts */ +VECTOR(stm32_rtcalrm, STM32_IRQ_RTCALRM) /* Vector 16+41: RTC alarm through EXTI line interrupt */ +VECTOR(stm32_otgfswkup, STM32_IRQ_OTGFSWKUP) /* Vector 16+42: USB On-The-Go FS Wakeup through EXTI line interrupt */ +VECTOR(stm32_tim8brk, STM32_IRQ_TIM8BRK) /* Vector 16+43: TIM8 Break interrupt/TIM12 global interrupt */ +VECTOR(stm32_tim8up, STM32_IRQ_TIM8UP) /* Vector 16+44: TIM8 Update interrup/TIM13 global interrupt */ +VECTOR(stm32_tim8trgcom, STM32_IRQ_TIM8TRGCOM) /* Vector 16+45: TIM8 Trigger and Commutation interrupts/TIM14 global interrupt */ +VECTOR(stm32_tim8cc, STM32_IRQ_TIM8CC) /* Vector 16+46: TIM8 Capture Compare interrupt */ +VECTOR(stm32_dma1s7, STM32_IRQ_DMA1S7) /* Vector 16+47: DMA1 Stream 7 global interrupt */ +VECTOR(stm32_fsmc, STM32_IRQ_FSMC) /* Vector 16+48: FSMC global interrupt */ +VECTOR(stm32_sdio, STM32_IRQ_SDIO) /* Vector 16+49: SDIO global interrupt */ +VECTOR(stm32_tim5, STM32_IRQ_TIM5) /* Vector 16+50: TIM5 global interrupt */ +VECTOR(stm32_spi3, STM32_IRQ_SPI3) /* Vector 16+51: SPI3 global interrupt */ +VECTOR(stm32_uart4, STM32_IRQ_UART4) /* Vector 16+52: UART4 global interrupt */ +VECTOR(stm32_uart5, STM32_IRQ_UART5) /* Vector 16+53: UART5 global interrupt */ +VECTOR(stm32_tim6, STM32_IRQ_TIM6) /* Vector 16+54: TIM6 global interrupt/DAC1 and DAC2 underrun error interrupts */ +VECTOR(stm32_tim7, STM32_IRQ_TIM7) /* Vector 16+55: TIM7 global interrupt */ +VECTOR(stm32_dma2s0, STM32_IRQ_DMA2S0) /* Vector 16+56: DMA2 Stream 0 global interrupt */ +VECTOR(stm32_dma2s1, STM32_IRQ_DMA2S1) /* Vector 16+57: DMA2 Stream 1 global interrupt */ +VECTOR(stm32_dma2s2, STM32_IRQ_DMA2S2) /* Vector 16+58: DMA2 Stream 2 global interrupt */ +VECTOR(stm32_dma2s3, STM32_IRQ_DMA2S3) /* Vector 16+59: DMA2 Stream 3 global interrupt */ +VECTOR(stm32_dma2s4, STM32_IRQ_DMA2S4) /* Vector 16+60: DMA2 Stream 4 global interrupt */ +VECTOR(stm32_eth, STM32_IRQ_ETH) /* Vector 16+61: Ethernet global interrupt */ +VECTOR(stm32_ethwkup, STM32_IRQ_ETHWKUP) /* Vector 16+62: Ethernet Wakeup through EXTI line interrupt */ +VECTOR(stm32_can2tx, STM32_IRQ_CAN2TX) /* Vector 16+63: CAN2 TX interrupts */ +VECTOR(stm32_can2rx0, STM32_IRQ_CAN2RX0) /* Vector 16+64: CAN2 RX0 interrupts */ +VECTOR(stm32_can2rx1, STM32_IRQ_CAN2RX1) /* Vector 16+65: CAN2 RX1 interrupt */ +VECTOR(stm32_can2sce, STM32_IRQ_CAN2SCE) /* Vector 16+66: CAN2 SCE interrupt */ +VECTOR(stm32_otgfs, STM32_IRQ_OTGFS) /* Vector 16+67: USB On The Go FS global interrupt */ +VECTOR(stm32_dma2s5, STM32_IRQ_DMA2S5) /* Vector 16+68: DMA2 Stream 5 global interrupt */ +VECTOR(stm32_dma2s6, STM32_IRQ_DMA2S6) /* Vector 16+69: DMA2 Stream 6 global interrupt */ +VECTOR(stm32_dma2s7, STM32_IRQ_DMA2S7) /* Vector 16+70: DMA2 Stream 7 global interrupt */ +VECTOR(stm32_usart6, STM32_IRQ_USART6) /* Vector 16+71: USART6 global interrupt */ +VECTOR(stm32_i2c3ev, STM32_IRQ_I2C3EV) /* Vector 16+72: I2C3 event interrupt */ +VECTOR(stm32_i2c3er, STM32_IRQ_I2C3ER) /* Vector 16+73: I2C3 error interrupt */ +VECTOR(stm32_otghsep1out, STM32_IRQ_OTGHSEP1OUT) /* Vector 16+74: USB On The Go HS End Point 1 Out global interrupt */ +VECTOR(stm32_otghsep1in, STM32_IRQ_OTGHSEP1IN) /* Vector 16+75: USB On The Go HS End Point 1 In global interrupt */ +VECTOR(stm32_otghswkup, STM32_IRQ_OTGHSWKUP) /* Vector 16+76: USB On The Go HS Wakeup through EXTI interrupt */ +VECTOR(stm32_otghs, STM32_IRQ_OTGHS ) /* Vector 16+77: USB On The Go HS global interrupt */ +VECTOR(stm32_dcmi, STM32_IRQ_DCMI) /* Vector 16+78: DCMI global interrupt */ +VECTOR(stm32_cryp, STM32_IRQ_CRYP) /* Vector 16+79: CRYP crypto global interrupt */ +VECTOR(stm32_hash, STM32_IRQ_HASH) /* Vector 16+80: Hash and Rng global interrupt */ + +#endif /* CONFIG_ARMV7M_CMNVECTOR */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_dma.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_dma.h new file mode 100644 index 0000000000..ab0cfceaca --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_dma.h @@ -0,0 +1,520 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f40xxx_dma.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_DMA_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_DMA_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* 2 DMA controllers */ + +#define DMA1 (0) +#define DMA2 (1) + +/* 8 DMA streams */ + +#define DMA_STREAM0 (0) +#define DMA_STREAM1 (1) +#define DMA_STREAM2 (2) +#define DMA_STREAM3 (3) +#define DMA_STREAM4 (4) +#define DMA_STREAM5 (5) +#define DMA_STREAM6 (6) +#define DMA_STREAM7 (7) + +/* 8 DMA channels */ + +#define DMA_CHAN0 (0) +#define DMA_CHAN1 (1) +#define DMA_CHAN2 (2) +#define DMA_CHAN3 (3) +#define DMA_CHAN4 (4) +#define DMA_CHAN5 (5) +#define DMA_CHAN6 (6) +#define DMA_CHAN7 (7) + +/* Register Offsets *****************************************************************/ + +#define STM32_DMA_LISR_OFFSET 0x0000 /* DMA low interrupt status register */ +#define STM32_DMA_HISR_OFFSET 0x0004 /* DMA high interrupt status register */ +#define STM32_DMA_LIFCR_OFFSET 0x0008 /* DMA low interrupt flag clear register */ +#define STM32_DMA_HIFCR_OFFSET 0x000c /* DMA high interrupt flag clear register */ + +#define STM32_DMA_OFFSET(n) (0x0010+0x0018*(n)) +#define STM32_DMA_SCR_OFFSET 0x0000 /* DMA stream n configuration register */ +#define STM32_DMA_SNDTR_OFFSET 0x0004 /* DMA stream n number of data register */ +#define STM32_DMA_SPAR_OFFSET 0x0008 /* DMA stream n peripheral address register */ +#define STM32_DMA_SM0AR_OFFSET 0x000c /* DMA stream n memory 0 address register */ +#define STM32_DMA_SM1AR_OFFSET 0x0010 /* DMA stream n memory 1 address register */ +#define STM32_DMA_SFCR_OFFSET 0x0014 /* DMA stream n FIFO control register */ + +#define STM32_DMA_S0CR_OFFSET 0x0010 /* DMA stream 0 configuration register */ +#define STM32_DMA_S1CR_OFFSET 0x0028 /* DMA stream 1 configuration register */ +#define STM32_DMA_S2CR_OFFSET 0x0040 /* DMA stream 2 configuration register */ +#define STM32_DMA_S3CR_OFFSET 0x0058 /* DMA stream 3 configuration register */ +#define STM32_DMA_S4CR_OFFSET 0x0070 /* DMA stream 4 configuration register */ +#define STM32_DMA_S5CR_OFFSET 0x0088 /* DMA stream 5 configuration register */ +#define STM32_DMA_S6CR_OFFSET 0x00a0 /* DMA stream 6 configuration register */ +#define STM32_DMA_S7CR_OFFSET 0x00b8 /* DMA stream 7 configuration register */ + +#define STM32_DMA_S0NDTR_OFFSET 0x0014 /* DMA stream 0 number of data register */ +#define STM32_DMA_S1NDTR_OFFSET 0x002c /* DMA stream 1 number of data register */ +#define STM32_DMA_S2NDTR_OFFSET 0x0044 /* DMA stream 2 number of data register */ +#define STM32_DMA_S3NDTR_OFFSET 0x005c /* DMA stream 3 number of data register */ +#define STM32_DMA_S4NDTR_OFFSET 0x0074 /* DMA stream 4 number of data register */ +#define STM32_DMA_S5NDTR_OFFSET 0x008c /* DMA stream 5 number of data register */ +#define STM32_DMA_S6NDTR_OFFSET 0x00a4 /* DMA stream 6 number of data register */ +#define STM32_DMA_S7NDTR_OFFSET 0x00bc /* DMA stream 7 number of data register */ + +#define STM32_DMA_S0PAR_OFFSET 0x0018 /* DMA stream 0 peripheral address register */ +#define STM32_DMA_S1PAR_OFFSET 0x0030 /* DMA stream 1 peripheral address register */ +#define STM32_DMA_S2PAR_OFFSET 0x0048 /* DMA stream 2 peripheral address register */ +#define STM32_DMA_S3PAR_OFFSET 0x0060 /* DMA stream 3 peripheral address register */ +#define STM32_DMA_S4PAR_OFFSET 0x0078 /* DMA stream 4 peripheral address register */ +#define STM32_DMA_S5PAR_OFFSET 0x0090 /* DMA stream 5 peripheral address register */ +#define STM32_DMA_S6PAR_OFFSET 0x00a8 /* DMA stream 6 peripheral address register */ +#define STM32_DMA_S7PAR_OFFSET 0x00c0 /* DMA stream 7 peripheral address register */ + +#define STM32_DMA_S0M0AR_OFFSET 0x001c /* DMA stream 0 memory 0 address register */ +#define STM32_DMA_S1M0AR_OFFSET 0x0034 /* DMA stream 1 memory 0 address register */ +#define STM32_DMA_S2M0AR_OFFSET 0x004c /* DMA stream 2 memory 0 address register */ +#define STM32_DMA_S3M0AR_OFFSET 0x0064 /* DMA stream 3 memory 0 address register */ +#define STM32_DMA_S4M0AR_OFFSET 0x007c /* DMA stream 4 memory 0 address register */ +#define STM32_DMA_S5M0AR_OFFSET 0x0094 /* DMA stream 5 memory 0 address register */ +#define STM32_DMA_S6M0AR_OFFSET 0x00ac /* DMA stream 6 memory 0 address register */ +#define STM32_DMA_S7M0AR_OFFSET 0x00c4 /* DMA stream 7 memory 0 address register */ + +#define STM32_DMA_S0M1AR_OFFSET 0x0020 /* DMA stream 0 memory 1 address register */ +#define STM32_DMA_S1M1AR_OFFSET 0x0038 /* DMA stream 1 memory 1 address register */ +#define STM32_DMA_S2M1AR_OFFSET 0x0050 /* DMA stream 2 memory 1 address register */ +#define STM32_DMA_S3M1AR_OFFSET 0x0068 /* DMA stream 3 memory 1 address register */ +#define STM32_DMA_S4M1AR_OFFSET 0x0080 /* DMA stream 4 memory 1 address register */ +#define STM32_DMA_S5M1AR_OFFSET 0x0098 /* DMA stream 5 memory 1 address register */ +#define STM32_DMA_S6M1AR_OFFSET 0x00b0 /* DMA stream 6 memory 1 address register */ +#define STM32_DMA_S7M1AR_OFFSET 0x00c8 /* DMA stream 7 memory 1 address register */ + +#define STM32_DMA_S0FCR_OFFSET 0x0024 /* DMA stream 0 FIFO control register */ +#define STM32_DMA_S1FCR_OFFSET 0x003c /* DMA stream 1 FIFO control register */ +#define STM32_DMA_S2FCR_OFFSET 0x0054 /* DMA stream 2 FIFO control register */ +#define STM32_DMA_S3FCR_OFFSET 0x006c /* DMA stream 3 FIFO control register */ +#define STM32_DMA_S4FCR_OFFSET 0x0084 /* DMA stream 4 FIFO control register */ +#define STM32_DMA_S5FCR_OFFSET 0x009c /* DMA stream 5 FIFO control register */ +#define STM32_DMA_S6FCR_OFFSET 0x00b4 /* DMA stream 6 FIFO control register */ +#define STM32_DMA_S7FCR_OFFSET 0x00cc /* DMA stream 7 FIFO control register */ + +/* Register Addresses ***************************************************************/ + +#define STM32_DMA1_LISRC (STM32_DMA1_BASE+STM32_DMA_LISR_OFFSET) +#define STM32_DMA1_HISRC (STM32_DMA1_BASE+STM32_DMA_HISR_OFFSET) +#define STM32_DMA1_LIFCR (STM32_DMA1_BASE+STM32_DMA_LIFCR_OFFSET) +#define STM32_DMA1_HIFCR (STM32_DMA1_BASE+STM32_DMA_HIFCR_OFFSET) + +#define STM32_DMA1_SCR(n) (STM32_DMA1_BASE+STM32_DMA_SCR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA1_S0CR (STM32_DMA1_BASE+STM32_DMA_S0CR_OFFSET) +#define STM32_DMA1_S1CR (STM32_DMA1_BASE+STM32_DMA_S1CR_OFFSET) +#define STM32_DMA1_S2CR (STM32_DMA1_BASE+STM32_DMA_S2CR_OFFSET) +#define STM32_DMA1_S3CR (STM32_DMA1_BASE+STM32_DMA_S3CR_OFFSET) +#define STM32_DMA1_S4CR (STM32_DMA1_BASE+STM32_DMA_S4CR_OFFSET) +#define STM32_DMA1_S5CR (STM32_DMA1_BASE+STM32_DMA_S5CR_OFFSET) +#define STM32_DMA1_S6CR (STM32_DMA1_BASE+STM32_DMA_S6CR_OFFSET) +#define STM32_DMA1_S7CR (STM32_DMA1_BASE+STM32_DMA_S7CR_OFFSET) + +#define STM32_DMA1_SNDTR(n) (STM32_DMA1_BASE+STM32_DMA_SNDTR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA1_S0NDTR (STM32_DMA1_BASE+STM32_DMA_S0NDTR_OFFSET) +#define STM32_DMA1_S1NDTR (STM32_DMA1_BASE+STM32_DMA_S1NDTR_OFFSET) +#define STM32_DMA1_S2NDTR (STM32_DMA1_BASE+STM32_DMA_S2NDTR_OFFSET) +#define STM32_DMA1_S3NDTR (STM32_DMA1_BASE+STM32_DMA_S3NDTR_OFFSET) +#define STM32_DMA1_S4NDTR (STM32_DMA1_BASE+STM32_DMA_S4NDTR_OFFSET) +#define STM32_DMA1_S5NDTR (STM32_DMA1_BASE+STM32_DMA_S5NDTR_OFFSET) +#define STM32_DMA1_S6NDTR (STM32_DMA1_BASE+STM32_DMA_S6NDTR_OFFSET) +#define STM32_DMA1_S7NDTR (STM32_DMA1_BASE+STM32_DMA_S7NDTR_OFFSET) + +#define STM32_DMA1_SPAR(n) (STM32_DMA1_BASE+STM32_DMA_SPAR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA1_S0PAR (STM32_DMA1_BASE+STM32_DMA_S0PAR_OFFSET) +#define STM32_DMA1_S1PAR (STM32_DMA1_BASE+STM32_DMA_S1PAR_OFFSET) +#define STM32_DMA1_S2PAR (STM32_DMA1_BASE+STM32_DMA_S2PAR_OFFSET) +#define STM32_DMA1_S3PAR (STM32_DMA1_BASE+STM32_DMA_S3PAR_OFFSET) +#define STM32_DMA1_S4PAR (STM32_DMA1_BASE+STM32_DMA_S4PAR_OFFSET) +#define STM32_DMA1_S5PAR (STM32_DMA1_BASE+STM32_DMA_S5PAR_OFFSET) +#define STM32_DMA1_S6PAR (STM32_DMA1_BASE+STM32_DMA_S6PAR_OFFSET) +#define STM32_DMA1_S7PAR (STM32_DMA1_BASE+STM32_DMA_S7PAR_OFFSET) + +#define STM32_DMA1_SM0AR(n) (STM32_DMA1_BASE+STM32_DMA_SM0AR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA1_S0M0AR (STM32_DMA1_BASE+STM32_DMA_S0M0AR_OFFSET) +#define STM32_DMA1_S1M0AR (STM32_DMA1_BASE+STM32_DMA_S1M0AR_OFFSET) +#define STM32_DMA1_S2M0AR (STM32_DMA1_BASE+STM32_DMA_S2M0AR_OFFSET) +#define STM32_DMA1_S3M0AR (STM32_DMA1_BASE+STM32_DMA_S3M0AR_OFFSET) +#define STM32_DMA1_S4M0AR (STM32_DMA1_BASE+STM32_DMA_S4M0AR_OFFSET) +#define STM32_DMA1_S5M0AR (STM32_DMA1_BASE+STM32_DMA_S5M0AR_OFFSET) +#define STM32_DMA1_S6M0AR (STM32_DMA1_BASE+STM32_DMA_S6M0AR_OFFSET) +#define STM32_DMA1_S7M0AR (STM32_DMA1_BASE+STM32_DMA_S7M0AR_OFFSET) + +#define STM32_DMA1_SM1AR(n) (STM32_DMA1_BASE+STM32_DMA_SM1AR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA1_S0M1AR (STM32_DMA1_BASE+STM32_DMA_S0M1AR_OFFSET) +#define STM32_DMA1_S1M1AR (STM32_DMA1_BASE+STM32_DMA_S1M1AR_OFFSET) +#define STM32_DMA1_S2M1AR (STM32_DMA1_BASE+STM32_DMA_S2M1AR_OFFSET) +#define STM32_DMA1_S3M1AR (STM32_DMA1_BASE+STM32_DMA_S3M1AR_OFFSET) +#define STM32_DMA1_S4M1AR (STM32_DMA1_BASE+STM32_DMA_S4M1AR_OFFSET) +#define STM32_DMA1_S5M1AR (STM32_DMA1_BASE+STM32_DMA_S5M1AR_OFFSET) +#define STM32_DMA1_S6M1AR (STM32_DMA1_BASE+STM32_DMA_S6M1AR_OFFSET) +#define STM32_DMA1_S7M1AR (STM32_DMA1_BASE+STM32_DMA_S7M1AR_OFFSET) + +#define STM32_DMA1_SFCR(n) (STM32_DMA1_BASE+STM32_DMA_SFCR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA1_S0FCR (STM32_DMA1_BASE+STM32_DMA_S0FCR_OFFSET) +#define STM32_DMA1_S1FCR (STM32_DMA1_BASE+STM32_DMA_S1FCR_OFFSET) +#define STM32_DMA1_S2FCR (STM32_DMA1_BASE+STM32_DMA_S2FCR_OFFSET) +#define STM32_DMA1_S3FCR (STM32_DMA1_BASE+STM32_DMA_S3FCR_OFFSET) +#define STM32_DMA1_S4FCR (STM32_DMA1_BASE+STM32_DMA_S4FCR_OFFSET) +#define STM32_DMA1_S5FCR (STM32_DMA1_BASE+STM32_DMA_S5FCR_OFFSET) +#define STM32_DMA1_S6FCR (STM32_DMA1_BASE+STM32_DMA_S6FCR_OFFSET) +#define STM32_DMA1_S7FCR (STM32_DMA1_BASE+STM32_DMA_S7FCR_OFFSET) + +#define STM32_DMA2_LISRC (STM32_DMA2_BASE+STM32_DMA_LISR_OFFSET) +#define STM32_DMA2_HISRC (STM32_DMA2_BASE+STM32_DMA_HISR_OFFSET) +#define STM32_DMA2_LIFCR (STM32_DMA2_BASE+STM32_DMA_LIFCR_OFFSET) +#define STM32_DMA2_HIFCR (STM32_DMA2_BASE+STM32_DMA_HIFCR_OFFSET) + +#define STM32_DMA2_SCR(n) (STM32_DMA2_BASE+STM32_DMA_SCR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA2_S0CR (STM32_DMA2_BASE+STM32_DMA_S0CR_OFFSET) +#define STM32_DMA2_S1CR (STM32_DMA2_BASE+STM32_DMA_S1CR_OFFSET) +#define STM32_DMA2_S2CR (STM32_DMA2_BASE+STM32_DMA_S2CR_OFFSET) +#define STM32_DMA2_S3CR (STM32_DMA2_BASE+STM32_DMA_S3CR_OFFSET) +#define STM32_DMA2_S4CR (STM32_DMA2_BASE+STM32_DMA_S4CR_OFFSET) +#define STM32_DMA2_S5CR (STM32_DMA2_BASE+STM32_DMA_S5CR_OFFSET) +#define STM32_DMA2_S6CR (STM32_DMA2_BASE+STM32_DMA_S6CR_OFFSET) +#define STM32_DMA2_S7CR (STM32_DMA2_BASE+STM32_DMA_S7CR_OFFSET) + +#define STM32_DMA2_SNDTR(n) (STM32_DMA2_BASE+STM32_DMA_SNDTR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA2_S0NDTR (STM32_DMA2_BASE+STM32_DMA_S0NDTR_OFFSET) +#define STM32_DMA2_S1NDTR (STM32_DMA2_BASE+STM32_DMA_S1NDTR_OFFSET) +#define STM32_DMA2_S2NDTR (STM32_DMA2_BASE+STM32_DMA_S2NDTR_OFFSET) +#define STM32_DMA2_S3NDTR (STM32_DMA2_BASE+STM32_DMA_S3NDTR_OFFSET) +#define STM32_DMA2_S4NDTR (STM32_DMA2_BASE+STM32_DMA_S4NDTR_OFFSET) +#define STM32_DMA2_S5NDTR (STM32_DMA2_BASE+STM32_DMA_S5NDTR_OFFSET) +#define STM32_DMA2_S6NDTR (STM32_DMA2_BASE+STM32_DMA_S6NDTR_OFFSET) +#define STM32_DMA2_S7NDTR (STM32_DMA2_BASE+STM32_DMA_S7NDTR_OFFSET) + +#define STM32_DMA2_SPAR(n) (STM32_DMA2_BASE+STM32_DMA_SPAR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA2_S0PAR (STM32_DMA2_BASE+STM32_DMA_S0PAR_OFFSET) +#define STM32_DMA2_S1PAR (STM32_DMA2_BASE+STM32_DMA_S1PAR_OFFSET) +#define STM32_DMA2_S2PAR (STM32_DMA2_BASE+STM32_DMA_S2PAR_OFFSET) +#define STM32_DMA2_S3PAR (STM32_DMA2_BASE+STM32_DMA_S3PAR_OFFSET) +#define STM32_DMA2_S4PAR (STM32_DMA2_BASE+STM32_DMA_S4PAR_OFFSET) +#define STM32_DMA2_S5PAR (STM32_DMA2_BASE+STM32_DMA_S5PAR_OFFSET) +#define STM32_DMA2_S6PAR (STM32_DMA2_BASE+STM32_DMA_S6PAR_OFFSET) +#define STM32_DMA2_S7PAR (STM32_DMA2_BASE+STM32_DMA_S7PAR_OFFSET) + +#define STM32_DMA2_SM0AR(n) (STM32_DMA2_BASE+STM32_DMA_SM0AR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA2_S0M0AR (STM32_DMA2_BASE+STM32_DMA_S0M0AR_OFFSET) +#define STM32_DMA2_S1M0AR (STM32_DMA2_BASE+STM32_DMA_S1M0AR_OFFSET) +#define STM32_DMA2_S2M0AR (STM32_DMA2_BASE+STM32_DMA_S2M0AR_OFFSET) +#define STM32_DMA2_S3M0AR (STM32_DMA2_BASE+STM32_DMA_S3M0AR_OFFSET) +#define STM32_DMA2_S4M0AR (STM32_DMA2_BASE+STM32_DMA_S4M0AR_OFFSET) +#define STM32_DMA2_S5M0AR (STM32_DMA2_BASE+STM32_DMA_S5M0AR_OFFSET) +#define STM32_DMA2_S6M0AR (STM32_DMA2_BASE+STM32_DMA_S6M0AR_OFFSET) +#define STM32_DMA2_S7M0AR (STM32_DMA2_BASE+STM32_DMA_S7M0AR_OFFSET) + +#define STM32_DMA2_SM1AR(n) (STM32_DMA2_BASE+STM32_DMA_SM1AR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA2_S0M1AR (STM32_DMA2_BASE+STM32_DMA_S0M1AR_OFFSET) +#define STM32_DMA2_S1M1AR (STM32_DMA2_BASE+STM32_DMA_S1M1AR_OFFSET) +#define STM32_DMA2_S2M1AR (STM32_DMA2_BASE+STM32_DMA_S2M1AR_OFFSET) +#define STM32_DMA2_S3M1AR (STM32_DMA2_BASE+STM32_DMA_S3M1AR_OFFSET) +#define STM32_DMA2_S4M1AR (STM32_DMA2_BASE+STM32_DMA_S4M1AR_OFFSET) +#define STM32_DMA2_S5M1AR (STM32_DMA2_BASE+STM32_DMA_S5M1AR_OFFSET) +#define STM32_DMA2_S6M1AR (STM32_DMA2_BASE+STM32_DMA_S6M1AR_OFFSET) +#define STM32_DMA2_S7M1AR (STM32_DMA2_BASE+STM32_DMA_S7M1AR_OFFSET) + +#define STM32_DMA2_SFCR(n) (STM32_DMA2_BASE+STM32_DMA_SFCR_OFFSET+STM32_DMA_OFFSET(n)) +#define STM32_DMA2_S0FCR (STM32_DMA2_BASE+STM32_DMA_S0FCR_OFFSET) +#define STM32_DMA2_S1FCR (STM32_DMA2_BASE+STM32_DMA_S1FCR_OFFSET) +#define STM32_DMA2_S2FCR (STM32_DMA2_BASE+STM32_DMA_S2FCR_OFFSET) +#define STM32_DMA2_S3FCR (STM32_DMA2_BASE+STM32_DMA_S3FCR_OFFSET) +#define STM32_DMA2_S4FCR (STM32_DMA2_BASE+STM32_DMA_S4FCR_OFFSET) +#define STM32_DMA2_S5FCR (STM32_DMA2_BASE+STM32_DMA_S5FCR_OFFSET) +#define STM32_DMA2_S6FCR (STM32_DMA2_BASE+STM32_DMA_S6FCR_OFFSET) +#define STM32_DMA2_S7FCR (STM32_DMA2_BASE+STM32_DMA_S7FCR_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +#define DMA_STREAM_MASK 0x3f +#define DMA_STREAM_FEIF_BIT (1 << 0) /* Bit 0: Stream FIFO error interrupt flag */ +#define DMA_STREAM_DMEIF_BIT (1 << 2) /* Bit 2: Stream direct mode error interrupt flag */ +#define DMA_STREAM_TEIF_BIT (1 << 3) /* Bit 3: Stream Transfer Error flag */ +#define DMA_STREAM_HTIF_BIT (1 << 4) /* Bit 4: Stream Half Transfer flag */ +#define DMA_STREAM_TCIF_BIT (1 << 5) /* Bit 5: Stream Transfer Complete flag */ + +/* DMA interrupt status register and interrupt flag clear register field defintions */ + +#define DMA_INT_STREAM0_SHIFT (0) /* Bits 0-5: DMA Stream 0 interrupt */ +#define DMA_INT_STREAM0_MASK (DMA_STREAM_MASK << DMA_INT_STREAM0_SHIFT) +#define DMA_INT_STREAM1_SHIFT (6) /* Bits 6-11: DMA Stream 1 interrupt */ +#define DMA_INT_STREAM1_MASK (DMA_STREAM_MASK << DMA_INT_STREAM1_SHIFT) +#define DMA_INT_STREAM2_SHIFT (16) /* Bits 16-21: DMA Stream 2 interrupt */ +#define DMA_INT_STREAM2_MASK (DMA_STREAM_MASK << DMA_INT_STREAM2_SHIFT) +#define DMA_INT_STREAM3_SHIFT (22) /* Bits 22-27: DMA Stream 3 interrupt */ +#define DMA_INT_STREAM3_MASK (DMA_STREAM_MASK << DMA_INT_STREAM3_SHIFT) + +#define DMA_INT_STREAM4_SHIFT (0) /* Bits 0-5: DMA Stream 4 interrupt */ +#define DMA_INT_STREAM4_MASK (DMA_STREAM_MASK << DMA_INT_STREAM4_SHIFT) +#define DMA_INT_STREAM5_SHIFT (6) /* Bits 6-11: DMA Stream 5 interrupt */ +#define DMA_INT_STREAM5_MASK (DMA_STREAM_MASK << DMA_INT_STREAM5_SHIFT) +#define DMA_INT_STREAM6_SHIFT (16) /* Bits 16-21: DMA Stream 6 interrupt */ +#define DMA_INT_STREAM6_MASK (DMA_STREAM_MASK << DMA_INT_STREAM6_SHIFT) +#define DMA_INT_STREAM7_SHIFT (22) /* Bits 22-27: DMA Stream 7 interrupt */ +#define DMA_INT_STREAM7_MASK (DMA_STREAM_MASK << DMA_INT_STREAM7_SHIFT) + +/* DMA stream configuration register */ + +#define DMA_SCR_EN (1 << 0) /* Bit 0: Stream enable */ +#define DMA_SCR_DMEIE (1 << 1) /* Bit 1: Direct mode error interrupt enable */ +#define DMA_SCR_TEIE (1 << 2) /* Bit 2: Transfer error interrupt enable */ +#define DMA_SCR_HTIE (1 << 3) /* Bit 3: Half Transfer interrupt enable */ +#define DMA_SCR_TCIE (1 << 4) /* Bit 4: Transfer complete interrupt enable */ +#define DMA_SCR_PFCTRL (1 << 5) /* Bit 5: Peripheral flow controller */ +#define DMA_SCR_DIR_SHIFT (6) /* Bits 6-7: Data transfer direction */ +#define DMA_SCR_DIR_MASK (3 << DMA_SCR_DIR_SHIFT) +# define DMA_SCR_DIR_P2M (0 << DMA_SCR_DIR_SHIFT) /* 00: Peripheral-to-memory */ +# define DMA_SCR_DIR_M2P (1 << DMA_SCR_DIR_SHIFT) /* 01: Memory-to-peripheral */ +# define DMA_SCR_DIR_M2M (2 << DMA_SCR_DIR_SHIFT) /* 10: Memory-to-memory */ +#define DMA_SCR_CIRC (1 << 8) /* Bit 8: Circular mode */ +#define DMA_SCR_PINC (1 << 9) /* Bit 9: Peripheral increment mode */ +#define DMA_SCR_MINC (1 << 10) /* Bit 10: Memory increment mode */ +#define DMA_SCR_PSIZE_SHIFT (11) /* Bits 11-12: Peripheral size */ +#define DMA_SCR_PSIZE_MASK (3 << DMA_SCR_PSIZE_SHIFT) +# define DMA_SCR_PSIZE_8BITS (0 << DMA_SCR_PSIZE_SHIFT) /* 00: 8-bits */ +# define DMA_SCR_PSIZE_16BITS (1 << DMA_SCR_PSIZE_SHIFT) /* 01: 16-bits */ +# define DMA_SCR_PSIZE_32BITS (2 << DMA_SCR_PSIZE_SHIFT) /* 10: 32-bits */ +#define DMA_SCR_MSIZE_SHIFT (13) /* Bits 13-14: Memory size */ +#define DMA_SCR_MSIZE_MASK (3 << DMA_SCR_MSIZE_SHIFT) +# define DMA_SCR_MSIZE_8BITS (0 << DMA_SCR_MSIZE_SHIFT) /* 00: 8-bits */ +# define DMA_SCR_MSIZE_16BITS (1 << DMA_SCR_MSIZE_SHIFT) /* 01: 16-bits */ +# define DMA_SCR_MSIZE_32BITS (2 << DMA_SCR_MSIZE_SHIFT) /* 10: 32-bits */ +#define DMA_SCR_PINCOS (1 << 15) /* Bit 15: Peripheral increment offset size */ +#define DMA_SCR_PL_SHIFT (16) /* Bits 16-17: Stream Priority level */ +#define DMA_SCR_PL_MASK (3 << DMA_SCR_PL_SHIFT) +# define DMA_SCR_PRILO (0 << DMA_SCR_PL_SHIFT) /* 00: Low */ +# define DMA_SCR_PRIMED (1 << DMA_SCR_PL_SHIFT) /* 01: Medium */ +# define DMA_SCR_PRIHI (2 << DMA_SCR_PL_SHIFT) /* 10: High */ +# define DMA_SCR_PRIVERYHI (3 << DMA_SCR_PL_SHIFT) /* 11: Very high */ +#define DMA_SCR_DBM (1 << 18) /* Bit 15: Double buffer mode */ +#define DMA_SCR_CT (1 << 19) /* Bit 19: Current target */ +#define DMA_SCR_PBURST_SHIFT (21) /* Bits 21-22: Peripheral burst transfer configuration */ +#define DMA_SCR_PBURST_MASK (3 << DMA_SCR_PBURST_SHIFT) +# define DMA_SCR_PBURST_SINGLE (0 << DMA_SCR_PBURST_SHIFT) /* 00: Single transfer */ +# define DMA_SCR_PBURST_INCR4 (1 << DMA_SCR_PBURST_SHIFT) /* 01: Incremental burst of 4 beats */ +# define DMA_SCR_PBURST_INCR8 (2 << DMA_SCR_PBURST_SHIFT) /* 10: Incremental burst of 8 beats */ +# define DMA_SCR_PBURST_INCR16 (3 << DMA_SCR_PBURST_SHIFT) /* 11: Incremental burst of 16 beats */ +#define DMA_SCR_MBURST_SHIFT (23) /* Bits 23-24: Memory burst transfer configuration */ +#define DMA_SCR_MBURST_MASK (3 << DMA_SCR_MBURST_SHIFT) +# define DMA_SCR_MBURST_SINGLE (0 << DMA_SCR_MBURST_SHIFT) /* 00: Single transfer */ +# define DMA_SCR_MBURST_INCR4 (1 << DMA_SCR_MBURST_SHIFT) /* 01: Incremental burst of 4 beats */ +# define DMA_SCR_MBURST_INCR8 (2 << DMA_SCR_MBURST_SHIFT) /* 10: Incremental burst of 8 beats */ +# define DMA_SCR_MBURST_INCR16 (3 << DMA_SCR_MBURST_SHIFT) /* 11: Incremental burst of 16 beats */ +#define DMA_SCR_CHSEL_SHIFT (25) /* Bits 25-27: Channel selection */ +#define DMA_SCR_CHSEL_MASK (7 << DMA_SCR_CHSEL_SHIFT) +# define DMA_SCR_CHSEL(n) ((n) << DMA_SCR_CHSEL_SHIFT) + +#define DMA_SCR_ALLINTS (DMA_SCR_DMEIE|DMA_SCR_TEIE|DMA_SCR_HTIE|DMA_SCR_TCIE) + +/* DMA stream number of data register */ + +#define DMA_SNDTR_NDT_SHIFT (0) /* Bits 15-0: Number of data to Transfer */ +#define DMA_SNDTR_NDT_MASK (0xffff << DMA_SNDTR_NDT_SHIFT) + +/* DMA stream n FIFO control register */ + +#define DMA_SFCR_FTH_SHIFT (0) /* Bits 0-1: FIFO threshold selection */ +#define DMA_SFCR_FTH_MASK (3 << DMA_SFCR_FTH_SHIFT) +# define DMA_SFCR_FTH_QUARTER (0 << DMA_SFCR_FTH_SHIFT) /* 1/4 full FIFO */ +# define DMA_SFCR_FTH_HALF (1 << DMA_SFCR_FTH_SHIFT) /* 1/2 full FIFO */ +# define DMA_SFCR_FTH_3QUARTER (2 << DMA_SFCR_FTH_SHIFT) /* 3/4 full FIFO */ +# define DMA_SFCR_FTH_FULL (3 << DMA_SFCR_FTH_SHIFT) /* full FIFO */ +#define DMA_SFCR_DMDIS (1 << 2) /* Bit 2: Direct mode disable */ +#define DMA_SFCR_FS_SHIFT (3) /* Bits 3-5: FIFO status */ +#define DMA_SFCR_FS_MASK (7 << DMA_SFCR_FS_SHIFT) +# define DMA_SFCR_FS_QUARTER (0 << DMA_SFCR_FS_SHIFT) /* 0 < fifo_level < 1/4 */ +# define DMA_SFCR_FS_HALF (1 << DMA_SFCR_FS_SHIFT) /* 1/4 = fifo_level < 1/2 */ +# define DMA_SFCR_FS_3QUARTER (2 << DMA_SFCR_FS_SHIFT) /* 1/2 = fifo_level < 3/4 */ +# define DMA_SFCR_FS_ALMOSTFULL (3 << DMA_SFCR_FS_SHIFT) /* 3/4 = fifo_level < full */ +# define DMA_SFCR_FS_EMPTY (4 << DMA_SFCR_FS_SHIFT) /* FIFO is empty */ +# define DMA_SFCR_FS_FULL (5 << DMA_SFCR_FS_SHIFT) /* FIFO is full */ + /* Bit 6: Reserved */ +#define DMA_SFCR_FEIE (1 << 7) /* Bit 7: FIFO error interrupt enable */ + /* Bits 8-31: Reserved */ + +/* DMA Stream mapping. Each DMA stream has a mapping to several possible + * sources/sinks of data. The requests from peripherals assigned to a stream + * are simply OR'ed together before entering the DMA block. This means that only + * one request on a given stream can be enabled at once. + * + * Alternative stream selections are provided with a numeric suffix like _1, _2, etc. + * The DMA driver, however, will use the pin selection without the numeric suffix. + * Additional definitions are required in the board.h file. For example, if + * SPI3_RX connects via DMA STREAM0, then following should be application-specific + * mapping should be used: + * + * #define DMAMAP_SPI3_RX DMAMAP_SPI3_RX_1 + */ + +#define STM32_DMA_MAP(d,s,c) ((d) << 6 | (s) << 3 | (c)) +#define STM32_DMA_CONTROLLER(m) (((m) >> 6) & 1) +#define STM32_DMA_STREAM(m) (((m) >> 3) & 7) +#define STM32_DMA_CHANNEL(m) ((m) & 7) + +#define DMAMAP_SPI3_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN0) +#define DMAMAP_SPI3_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN0) +#define DMAMAP_SPI2_RX STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN0) +#define DMAMAP_SPI2_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN0) +#define DMAMAP_SPI3_TX_1 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN0) +#define DMAMAP_SPI3_TX_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN0) + +#define DMAMAP_I2C1_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN1) +#define DMAMAP_TIM7_UP_1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN1) +#define DMAMAP_TIM7_UP_2 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN1) +#define DMAMAP_I2C1_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN1) +#define DMAMAP_I2C1_TX_1 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN1) +#define DMAMAP_I2C1_TX_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN1) + +#define DMAMAP_TIM4_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN2) +#define DMAMAP_I2S2_EXT_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN2) +#define DMAMAP_TIM4_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN2) +#define DMAMAP_I2S2_EXT_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN2) +#define DMAMAP_I2S3_EXT_TX STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN2) +#define DMAMAP_TIM4_UP STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN2) +#define DMAMAP_TIM4_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN2) + +#define DMAMAP_I2S3_EXT_RX STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN3) +#define DMAMAP_TIM2_UP_1 STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN3) +#define DMAMAP_TIM2_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN3) +#define DMAMAP_I2C3_RX STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN3) +#define DMAMAP_I2S2_EXT_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN3) +#define DMAMAP_I2C3_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN3) +#define DMAMAP_TIM2_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN3) +#define DMAMAP_TIM2_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN3) +#define DMAMAP_TIM2_CH4_1 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN3) +#define DMAMAP_TIM2_UP_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN3) +#define DMAMAP_TIM2_CH4_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN3) + +#define DMAMAP_UART5_RX STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN4) +#define DMAMAP_USART3_RX STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN4) +#define DMAMAP_UART4_RX STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN4) +#define DMAMAP_USART3_TX_1 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN4) +#define DMAMAP_UART4_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN4) +#define DMAMAP_USART2_RX STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN4) +#define DMAMAP_USART2_TX STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN4) +#define DMAMAP_UART5_TX STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN4) + +#define DMAMAP_TIM3_CH4 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN5) +#define DMAMAP_TIM3_UP STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN5) +#define DMAMAP_TIM3_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN5) +#define DMAMAP_TIM3_TRIG STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN5) +#define DMAMAP_TIM3_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN5) +#define DMAMAP_TIM3_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN5) + +#define DMAMAP_TIM5_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN6) +#define DMAMAP_TIM5_UP_1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN6) +#define DMAMAP_TIM5_CH4_1 STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN6) +#define DMAMAP_TIM5_TRIG_1 STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN6) +#define DMAMAP_TIM5_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN6) +#define DMAMAP_TIM5_CH4_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN6) +#define DMAMAP_TIM5_TRIG_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN6) +#define DMAMAP_TIM5_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN6) +#define DMAMAP_TIM5_UP_2 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN6) + +#define DMAMAP_TIM6_UP STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN7) +#define DMAMAP_I2C2_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN7) +#define DMAMAP_I2C2_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN7) +#define DMAMAP_USART3_TX_2 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN7) +#define DMAMAP_DAC1 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN7) +#define DMAMAP_DAC2 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN7) +#define DMAMAP_I2C2_TX STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN7) + +#define DMAMAP_ADC1_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN0) +#define DMAMAP_TIM8_CH1_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN0) +#define DMAMAP_TIM8_CH2_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN0) +#define DMAMAP_TIM8_CH3_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN0) +#define DMAMAP_ADC1_2 STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN0) +#define DMAMAP_TIM1_CH1_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN0) +#define DMAMAP_TIM1_CH2_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN0) +#define DMAMAP_TIM1_CH3_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN0) + +#define DMAMAP_DCMI_1 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN1) +#define DMAMAP_ADC2_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN1) +#define DMAMAP_ADC2_2 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN1) +#define DMAMAP_DCMI_2 STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN1) + +#define DMAMAP_ADC3_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN2) +#define DMAMAP_ADC3_2 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN2) +#define DMAMAP_CRYP_OUT STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN2) +#define DMAMAP_CRYP_IN STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN2) +#define DMAMAP_HASH_IN STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN2) + +#define DMAMAP_SPI1_RX_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN3) +#define DMAMAP_SPI1_RX_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN3) +#define DMAMAP_SPI1_TX_1 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN3) +#define DMAMAP_SPI1_TX_2 STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN3) + +#define DMAMAP_USART1_RX_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN4) +#define DMAMAP_SDIO_1 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN4) +#define DMAMAP_USART1_RX_2 STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN4) +#define DMAMAP_SDIO_2 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN4) +#define DMAMAP_USART1_TX STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN4) + +#define DMAMAP_USART6_RX_1 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN5) +#define DMAMAP_USART6_RX_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN5) +#define DMAMAP_USART6_TX_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN5) +#define DMAMAP_USART6_TX_2 STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN5) + +#define DMAMAP_TIM1_TRIG_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN6) +#define DMAMAP_TIM1_CH1_2 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN6) +#define DMAMAP_TIM1_CH2_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN6) +#define DMAMAP_TIM1_CH1 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN6) +#define DMAMAP_TIM1_CH4 STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN6) +#define DMAMAP_TIM1_TRIG_2 STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN6) +#define DMAMAP_TIM1_COM STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN6) +#define DMAMAP_TIM1_UP STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN6) +#define DMAMAP_TIM1_CH3_2 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN6) + +#define DMAMAP_TIM8_UP STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN7) +#define DMAMAP_TIM8_CH1_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN7) +#define DMAMAP_TIM8_CH2_2 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN7) +#define DMAMAP_TIM8_CH3_2 STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN7) +#define DMAMAP_TIM8_CH4 STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN7) +#define DMAMAP_TIM8_TRIG STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN7) +#define DMAMAP_TIM8_COM STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN7) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_DMA_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_gpio.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_gpio.h new file mode 100644 index 0000000000..aa7353ed9d --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_gpio.h @@ -0,0 +1,370 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f40xxx_gpio.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_GPIO_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_GPIO_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#define STM32_NGPIO_PORTS ((STM32_NGPIO + 15) >> 4) + +/* Register Offsets *****************************************************************/ + +#define STM32_GPIO_MODER_OFFSET 0x0000 /* GPIO port mode register */ +#define STM32_GPIO_OTYPER_OFFSET 0x0004 /* GPIO port output type register */ +#define STM32_GPIO_OSPEED_OFFSET 0x0008 /* GPIO port output speed register */ +#define STM32_GPIO_PUPDR_OFFSET 0x000c /* GPIO port pull-up/pull-down register */ +#define STM32_GPIO_IDR_OFFSET 0x0010 /* GPIO port input data register */ +#define STM32_GPIO_ODR_OFFSET 0x0014 /* GPIO port output data register */ +#define STM32_GPIO_BSRR_OFFSET 0x0018 /* GPIO port bit set/reset register */ +#define STM32_GPIO_LCKR_OFFSET 0x001c /* GPIO port configuration lock register */ +#define STM32_GPIO_AFRL_OFFSET 0x0020 /* GPIO alternate function low register */ +#define STM32_GPIO_ARFH_OFFSET 0x0024 /* GPIO alternate function high register */ + +/* Register Addresses ***************************************************************/ + +#if STM32_NGPIO_PORTS > 0 +# define STM32_GPIOA_MODER (STM32_GPIOA_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOA_OTYPER (STM32_GPIOA_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOA_OSPEED (STM32_GPIOA_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOA_PUPDR (STM32_GPIOA_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOA_IDR (STM32_GPIOA_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOA_ODR (STM32_GPIOA_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOA_BSRR (STM32_GPIOA_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOA_LCKR (STM32_GPIOA_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOA_AFRL (STM32_GPIOA_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOA_ARFH (STM32_GPIOA_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 1 +# define STM32_GPIOB_MODER (STM32_GPIOB_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOB_OTYPER (STM32_GPIOB_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOB_OSPEED (STM32_GPIOB_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOB_PUPDR (STM32_GPIOB_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOB_IDR (STM32_GPIOB_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOB_ODR (STM32_GPIOB_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOB_BSRR (STM32_GPIOB_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOB_LCKR (STM32_GPIOB_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOB_AFRL (STM32_GPIOB_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOB_ARFH (STM32_GPIOB_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 2 +# define STM32_GPIOC_MODER (STM32_GPIOC_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOC_OTYPER (STM32_GPIOC_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOC_OSPEED (STM32_GPIOC_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOC_PUPDR (STM32_GPIOC_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOC_IDR (STM32_GPIOC_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOC_ODR (STM32_GPIOC_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOC_BSRR (STM32_GPIOC_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOC_LCKR (STM32_GPIOC_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOC_AFRL (STM32_GPIOC_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOC_ARFH (STM32_GPIOC_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 3 +# define STM32_GPIOD_MODER (STM32_GPIOD_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOD_OTYPER (STM32_GPIOD_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOD_OSPEED (STM32_GPIOD_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOD_PUPDR (STM32_GPIOD_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOD_IDR (STM32_GPIOD_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOD_ODR (STM32_GPIOD_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOD_BSRR (STM32_GPIOD_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOD_LCKR (STM32_GPIOD_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOD_AFRL (STM32_GPIOD_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOD_ARFH (STM32_GPIOD_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 4 +# define STM32_GPIOE_MODER (STM32_GPIOE_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOE_OTYPER (STM32_GPIOE_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOE_OSPEED (STM32_GPIOE_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOE_PUPDR (STM32_GPIOE_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOE_IDR (STM32_GPIOE_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOE_ODR (STM32_GPIOE_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOE_BSRR (STM32_GPIOE_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOE_LCKR (STM32_GPIOE_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOE_AFRL (STM32_GPIOE_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOE_ARFH (STM32_GPIOE_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 5 +# define STM32_GPIOF_MODER (STM32_GPIOF_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOF_OTYPER (STM32_GPIOF_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOF_OSPEED (STM32_GPIOF_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOF_PUPDR (STM32_GPIOF_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOF_IDR (STM32_GPIOF_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOF_ODR (STM32_GPIOF_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOF_BSRR (STM32_GPIOF_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOF_LCKR (STM32_GPIOF_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOF_AFRL (STM32_GPIOF_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOF_ARFH (STM32_GPIOF_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 6 +# define STM32_GPIOG_MODER (STM32_GPIOG_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOG_OTYPER (STM32_GPIOG_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOG_OSPEED (STM32_GPIOG_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOG_PUPDR (STM32_GPIOG_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOG_IDR (STM32_GPIOG_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOG_ODR (STM32_GPIOG_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOG_BSRR (STM32_GPIOG_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOG_LCKR (STM32_GPIOG_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOG_AFRL (STM32_GPIOG_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOG_ARFH (STM32_GPIOG_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 7 +# define STM32_GPIOH_MODER (STM32_GPIOH_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOH_OTYPER (STM32_GPIOH_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOH_OSPEED (STM32_GPIOH_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOH_PUPDR (STM32_GPIOH_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOH_IDR (STM32_GPIOH_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOH_ODR (STM32_GPIOH_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOH_BSRR (STM32_GPIOH_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOH_LCKR (STM32_GPIOH_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOH_AFRL (STM32_GPIOH_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOH_ARFH (STM32_GPIOH_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +#if STM32_NGPIO_PORTS > 8 +# define STM32_GPIOI_MODER (STM32_GPIOI_BASE+STM32_GPIO_MODER_OFFSET) +# define STM32_GPIOI_OTYPER (STM32_GPIOI_BASE+STM32_GPIO_OTYPER_OFFSET) +# define STM32_GPIOI_OSPEED (STM32_GPIOI_BASE+STM32_GPIO_OSPEED_OFFSET) +# define STM32_GPIOI_PUPDR (STM32_GPIOI_BASE+STM32_GPIO_PUPDR_OFFSET) +# define STM32_GPIOI_IDR (STM32_GPIOI_BASE+STM32_GPIO_IDR_OFFSET) +# define STM32_GPIOI_ODR (STM32_GPIOI_BASE+STM32_GPIO_ODR_OFFSET) +# define STM32_GPIOI_BSRR (STM32_GPIOI_BASE+STM32_GPIO_BSRR_OFFSET) +# define STM32_GPIOI_LCKR (STM32_GPIOI_BASE+STM32_GPIO_LCKR_OFFSET) +# define STM32_GPIOI_AFRL (STM32_GPIOI_BASE+STM32_GPIO_AFRL_OFFSET) +# define STM32_GPIOI_ARFH (STM32_GPIOI_BASE+STM32_GPIO_ARFH_OFFSET) +#endif + +/* Register Bitfield Definitions ****************************************************/ + +/* GPIO port mode register */ + +#define GPIO_MODER_INPUT (0) /* Input */ +#define GPIO_MODER_OUTPUT (1) /* General purpose output mode */ +#define GPIO_MODER_ALT (2) /* Alternate mode */ +#define GPIO_MODER_ANALOG (3) /* Analog mode */ + +#define GPIO_MODER_SHIFT(n) ((n) << 1) +#define GPIO_MODER_MASK(n) (3 << GPIO_MODER_SHIFT(n)) + +#define GPIO_MODER0_SHIFT (0) +#define GPIO_MODER0_MASK (3 << GPIO_MODER0_SHIFT) +#define GPIO_MODER1_SHIFT (2) +#define GPIO_MODER1_MASK (3 << GPIO_MODER1_SHIFT) +#define GPIO_MODER2_SHIFT (4) +#define GPIO_MODER2_MASK (3 << GPIO_MODER2_SHIFT) +#define GPIO_MODER3_SHIFT (6) +#define GPIO_MODER3_MASK (3 << GPIO_MODER3_SHIFT) +#define GPIO_MODER4_SHIFT (8) +#define GPIO_MODER4_MASK (3 << GPIO_MODER4_SHIFT) +#define GPIO_MODER5_SHIFT (10) +#define GPIO_MODER5_MASK (3 << GPIO_MODER5_SHIFT) +#define GPIO_MODER6_SHIFT (12) +#define GPIO_MODER6_MASK (3 << GPIO_MODER6_SHIFT) +#define GPIO_MODER7_SHIFT (14) +#define GPIO_MODER7_MASK (3 << GPIO_MODER7_SHIFT) +#define GPIO_MODER8_SHIFT (16) +#define GPIO_MODER8_MASK (3 << GPIO_MODER8_SHIFT) +#define GPIO_MODER9_SHIFT (18) +#define GPIO_MODER9_MASK (3 << GPIO_MODER9_SHIFT) +#define GPIO_MODER10_SHIFT (20) +#define GPIO_MODER10_MASK (3 << GPIO_MODER10_SHIFT) +#define GPIO_MODER11_SHIFT (22) +#define GPIO_MODER11_MASK (3 << GPIO_MODER11_SHIFT) +#define GPIO_MODER12_SHIFT (24) +#define GPIO_MODER12_MASK (3 << GPIO_MODER12_SHIFT) +#define GPIO_MODER13_SHIFT (26) +#define GPIO_MODER13_MASK (3 << GPIO_MODER13_SHIFT) +#define GPIO_MODER14_SHIFT (28) +#define GPIO_MODER14_MASK (3 << GPIO_MODER14_SHIFT) +#define GPIO_MODER15_SHIFT (30) +#define GPIO_MODER15_MASK (3 << GPIO_MODER15_SHIFT) + +/* GPIO port output type register */ + +#define GPIO_OTYPER_OD(n) (1 << (n)) /* 1=Output open-drain */ +#define GPIO_OTYPER_PP(n) (0) /* 0=Ouput push-pull */ + +/* GPIO port output speed register */ + +#define GPIO_OSPEED_2MHz (0) /* 2 MHz Low speed */ +#define GPIO_OSPEED_25MHz (1) /* 25 MHz Medium speed */ +#define GPIO_OSPEED_50MHz (2) /* 50 MHz Fast speed */ +#define GPIO_OSPEED_100MHz (3) /* 100 MHz High speed on 30 pF (80 MHz Output max speed on 15 pF) */ + +#define GPIO_OSPEED_SHIFT(n) ((n) << 1) +#define GPIO_OSPEED_MASK(n) (3 << GPIO_OSPEED_SHIFT(n)) + +#define GPIO_OSPEED0_SHIFT (0) +#define GPIO_OSPEED0_MASK (3 << GPIO_OSPEED0_SHIFT) +#define GPIO_OSPEED1_SHIFT (2) +#define GPIO_OSPEED1_MASK (3 << GPIO_OSPEED1_SHIFT) +#define GPIO_OSPEED2_SHIFT (4) +#define GPIO_OSPEED2_MASK (3 << GPIO_OSPEED2_SHIFT) +#define GPIO_OSPEED3_SHIFT (6) +#define GPIO_OSPEED3_MASK (3 << GPIO_OSPEED3_SHIFT) +#define GPIO_OSPEED4_SHIFT (8) +#define GPIO_OSPEED4_MASK (3 << GPIO_OSPEED4_SHIFT) +#define GPIO_OSPEED5_SHIFT (10) +#define GPIO_OSPEED5_MASK (3 << GPIO_OSPEED5_SHIFT) +#define GPIO_OSPEED6_SHIFT (12) +#define GPIO_OSPEED6_MASK (3 << GPIO_OSPEED6_SHIFT) +#define GPIO_OSPEED7_SHIFT (14) +#define GPIO_OSPEED7_MASK (3 << GPIO_OSPEED7_SHIFT) +#define GPIO_OSPEED8_SHIFT (16) +#define GPIO_OSPEED8_MASK (3 << GPIO_OSPEED8_SHIFT) +#define GPIO_OSPEED9_SHIFT (18) +#define GPIO_OSPEED9_MASK (3 << GPIO_OSPEED9_SHIFT) +#define GPIO_OSPEED10_SHIFT (20) +#define GPIO_OSPEED10_MASK (3 << GPIO_OSPEED10_SHIFT) +#define GPIO_OSPEED11_SHIFT (22) +#define GPIO_OSPEED11_MASK (3 << GPIO_OSPEED11_SHIFT) +#define GPIO_OSPEED12_SHIFT (24) +#define GPIO_OSPEED12_MASK (3 << GPIO_OSPEED12_SHIFT) +#define GPIO_OSPEED13_SHIFT (26) +#define GPIO_OSPEED13_MASK (3 << GPIO_OSPEED13_SHIFT) +#define GPIO_OSPEED14_SHIFT (28) +#define GPIO_OSPEED14_MASK (3 << GPIO_OSPEED14_SHIFT) +#define GPIO_OSPEED15_SHIFT (30) +#define GPIO_OSPEED15_MASK (3 << GPIO_OSPEED15_SHIFT) + +/* GPIO port pull-up/pull-down register */ + +#define GPIO_PUPDR_NONE (0) /* No pull-up, pull-down */ +#define GPIO_PUPDR_PULLUP (1) /* Pull-up */ +#define GPIO_PUPDR_PULLDOWN (2) /* Pull-down */ + +#define GPIO_PUPDR_SHIFT(n) ((n) << 1) +#define GPIO_PUPDR_MASK(n) (3 << GPIO_PUPDR_SHIFT(n)) + +#define GPIO_PUPDR0_SHIFT (0) +#define GPIO_PUPDR0_MASK (3 << GPIO_PUPDR0_SHIFT) +#define GPIO_PUPDR1_SHIFT (2) +#define GPIO_PUPDR1_MASK (3 << GPIO_PUPDR1_SHIFT) +#define GPIO_PUPDR2_SHIFT (4) +#define GPIO_PUPDR2_MASK (3 << GPIO_PUPDR2_SHIFT) +#define GPIO_PUPDR3_SHIFT (6) +#define GPIO_PUPDR3_MASK (3 << GPIO_PUPDR3_SHIFT) +#define GPIO_PUPDR4_SHIFT (8) +#define GPIO_PUPDR4_MASK (3 << GPIO_PUPDR4_SHIFT) +#define GPIO_PUPDR5_SHIFT (10) +#define GPIO_PUPDR5_MASK (3 << GPIO_PUPDR5_SHIFT) +#define GPIO_PUPDR6_SHIFT (12) +#define GPIO_PUPDR6_MASK (3 << GPIO_PUPDR6_SHIFT) +#define GPIO_PUPDR7_SHIFT (14) +#define GPIO_PUPDR7_MASK (3 << GPIO_PUPDR7_SHIFT) +#define GPIO_PUPDR8_SHIFT (16) +#define GPIO_PUPDR8_MASK (3 << GPIO_PUPDR8_SHIFT) +#define GPIO_PUPDR9_SHIFT (18) +#define GPIO_PUPDR9_MASK (3 << GPIO_PUPDR9_SHIFT) +#define GPIO_PUPDR10_SHIFT (20) +#define GPIO_PUPDR10_MASK (3 << GPIO_PUPDR10_SHIFT) +#define GPIO_PUPDR11_SHIFT (22) +#define GPIO_PUPDR11_MASK (3 << GPIO_PUPDR11_SHIFT) +#define GPIO_PUPDR12_SHIFT (24) +#define GPIO_PUPDR12_MASK (3 << GPIO_PUPDR12_SHIFT) +#define GPIO_PUPDR13_SHIFT (26) +#define GPIO_PUPDR13_MASK (3 << GPIO_PUPDR13_SHIFT) +#define GPIO_PUPDR14_SHIFT (28) +#define GPIO_PUPDR14_MASK (3 << GPIO_PUPDR14_SHIFT) +#define GPIO_PUPDR15_SHIFT (30) +#define GPIO_PUPDR15_MASK (3 << GPIO_PUPDR15_SHIFT) + +/* GPIO port input data register */ + +#define GPIO_IDR(n) (1 << (n)) + +/* GPIO port output data register */ + +#define GPIO_ODR(n) (1 << (n)) + +/* GPIO port bit set/reset register */ + +#define GPIO_BSRR_SET(n) (1 << (n)) +#define GPIO_BSRR_RESET(n) (1 << ((n)+16)) + +/* GPIO port configuration lock register */ + +#define GPIO_LCKR(n) (1 << (n)) +#define GPIO_LCKK (1 << 16) /* Lock key */ + +/* GPIO alternate function low/high register */ + +#define GPIO_AFR_SHIFT(n) ((n) << 2) +#define GPIO_AFR_MASK(n) (15 << GPIO_AFR_SHIFT(n)) + +#define GPIO_AFRL0_SHIFT (0) +#define GPIO_AFRL0_MASK (15 << GPIO_AFRL0_SHIFT) +#define GPIO_AFRL1_SHIFT (4) +#define GPIO_AFRL1_MASK (15 << GPIO_AFRL1_SHIFT) +#define GPIO_AFRL2_SHIFT (8) +#define GPIO_AFRL2_MASK (15 << GPIO_AFRL2_SHIFT) +#define GPIO_AFRL3_SHIFT (12) +#define GPIO_AFRL3_MASK (15 << GPIO_AFRL3_SHIFT) +#define GPIO_AFRL4_SHIFT (16) +#define GPIO_AFRL4_MASK (15 << GPIO_AFRL4_SHIFT) +#define GPIO_AFRL5_SHIFT (20) +#define GPIO_AFRL5_MASK (15 << GPIO_AFRL5_SHIFT) +#define GPIO_AFRL6_SHIFT (24) +#define GPIO_AFRL6_MASK (15 << GPIO_AFRL6_SHIFT) +#define GPIO_AFRL7_SHIFT (28) +#define GPIO_AFRL7_MASK (15 << GPIO_AFRL7_SHIFT) + +#define GPIO_AFRH8_SHIFT (0) +#define GPIO_AFRH8_MASK (15 << GPIO_AFRH8_SHIFT) +#define GPIO_AFRH9_SHIFT (4) +#define GPIO_AFRH9_MASK (15 << GPIO_AFRH9_SHIFT) +#define GPIO_AFRH10_SHIFT (8) +#define GPIO_AFRH10_MASK (15 << GPIO_AFRH10_SHIFT) +#define GPIO_AFRH11_SHIFT (12) +#define GPIO_AFRH11_MASK (15 << GPIO_AFRH11_SHIFT) +#define GPIO_AFRH12_SHIFT (16) +#define GPIO_AFRH12_MASK (15 << GPIO_AFRH12_SHIFT) +#define GPIO_AFRH13_SHIFT (20) +#define GPIO_AFRH13_MASK (15 << GPIO_AFRH13_SHIFT) +#define GPIO_AFRH14_SHIFT (24) +#define GPIO_AFRH14_MASK (15 << GPIO_AFRH14_SHIFT) +#define GPIO_AFRH15_SHIFT (28) +#define GPIO_AFRH15_MASK (15 << GPIO_AFRH15_SHIFT) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_GPIO_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_memorymap.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_memorymap.h new file mode 100644 index 0000000000..c7f7ff2ec3 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_memorymap.h @@ -0,0 +1,197 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f40xxx_memorymap.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_MEMORYMAP_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_MEMORYMAP_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* STM32F40XXX Address Blocks *******************************************************/ + +#define STM32_CODE_BASE 0x00000000 /* 0x00000000-0x1fffffff: 512Mb code block */ +#define STM32_SRAM_BASE 0x20000000 /* 0x20000000-0x3fffffff: 512Mb sram block */ +#define STM32_PERIPH_BASE 0x40000000 /* 0x40000000-0x5fffffff: 512Mb peripheral block */ +#define STM32_FSMC_BASE12 0x60000000 /* 0x60000000-0x7fffffff: 512Mb FSMC bank1&2 block */ +#define STM32_FSMC_BASE34 0x80000000 /* 0x80000000-0x8fffffff: 512Mb FSMC bank3&4 block */ +#define STM32_FSMC_BASE 0xa0000000 /* 0xa0000000-0xbfffffff: 512Mb FSMC register block */ + /* 0xc0000000-0xdfffffff: 512Mb (not used) */ +#define STM32_CORTEX_BASE 0xe0000000 /* 0xe0000000-0xffffffff: 512Mb Cortex-M4 block */ + +/* Code Base Addresses **************************************************************/ + +#define STM32_BOOT_BASE 0x00000000 /* 0x00000000-0x000fffff: Aliased boot memory */ + /* 0x00100000-0x07ffffff: Reserved */ +#define STM32_FLASH_BASE 0x08000000 /* 0x08000000-0x080fffff: FLASH memory */ + /* 0x08100000-0x0fffffff: Reserved */ +#define STM32_CCMRAM_BASE 0x10000000 /* 0x10000000-0x1000ffff: 64Kb CCM data RAM */ + /* 0x10010000-0x1ffeffff: Reserved */ +#define STM32_SYSMEM_BASE 0x1fff0000 /* 0x1fff0000-0x1fff7a0f: System memory */ + /* 0x1fff7a10-0x1fff7fff: Reserved */ +#define STM32_OPTION_BASE 0x1fffc000 /* 0x1fffc000-0x1fffc007: Option bytes */ + /* 0x1fffc008-0x1fffffff: Reserved */ + +/* SRAM Base Addresses **************************************************************/ + + /* 0x20000000-0x2001bfff: 112Kb aliased by bit-banding */ + /* 0x2001c000-0x2001ffff: 16Kb aliased by bit-banding */ +#define STM32_SRAMBB_BASE 0x22000000 /* 0x22000000- : SRAM bit-band region */ + +/* Peripheral Base Addresses ********************************************************/ + +#define STM32_APB1_BASE 0x40000000 /* 0x40000000-0x400023ff: APB1 */ + /* 0x40002400-0x400027ff: Reserved */ + /* 0x40002800-0x400077ff: APB1 */ + /* 0x40007800-0x4000ffff: Reserved */ +#define STM32_APB2_BASE 0x40010000 /* 0x40010000-0x400023ff: APB2 */ + /* 0x40013400-0x400137ff: Reserved */ + /* 0x40013800-0x40013bff: SYSCFG */ +#define STM32_EXTI_BASE 0x40013c00 /* 0x40013c00-0x40013fff: EXTI */ + /* 0x40014000-0x40014bff: APB2 */ + /* 0x40014c00-0x4001ffff: Reserved */ +#define STM32_AHB1_BASE 0x40020000 /* 0x40020000-0x400223ff: APB1 */ + /* 0x40022400-0x40022fff: Reserved */ + /* 0x40023000-0x400233ff: CRC */ + /* 0x40023400-0x400237ff: Reserved */ + /* 0x40023800-0x40023bff: Reset and Clock control RCC */ + /* 0x40023c00-0x400293ff: AHB1 (?) */ + /* 0x40029400-0x4fffffff: Reserved (?) */ +#define STM32_AHB2_BASE 0x50000000 /* 0x50000000-0x5003ffff: AHB2 */ + /* 0x50040000-0x5004ffff: Reserved */ + /* 0x50050000-0x500503ff: AHB2 */ + /* 0x50050400-0x500607ff: Reserved */ + /* 0x50060800-0x50060bff: AHB2 */ + /* 0x50060c00-0x5fffffff: Reserved */ + +/* FSMC Base Addresses **************************************************************/ + +#define STM32_AHB3_BASE 0x60000000 /* 0x60000000-0xa0000fff: AHB3 */ + +/* APB1 Base Addresses **************************************************************/ + +#define STM32_TIM2_BASE 0x40000000 /* 0x40000000-0x400003ff: TIM2 timer */ +#define STM32_TIM3_BASE 0x40000400 /* 0x40000400-0x400007ff: TIM3 timer */ +#define STM32_TIM4_BASE 0x40000800 /* 0x40000800-0x40000bff: TIM4 timer */ +#define STM32_TIM5_BASE 0x40000c00 /* 0x40000c00-0x40000fff: TIM5 timer */ +#define STM32_TIM6_BASE 0x40001000 /* 0x40001000-0x400013ff: TIM6 timer */ +#define STM32_TIM7_BASE 0x40001400 /* 0x40001400-0x400017ff: TIM7 timer */ +#define STM32_TIM12_BASE 0x40001800 /* 0x40001800-0x40001bff: TIM12 timer */ +#define STM32_TIM13_BASE 0x40001c00 /* 0x40001c00-0x40001fff: TIM13 timer */ +#define STM32_TIM14_BASE 0x40002000 /* 0x40002000-0x400023ff: TIM14 timer */ +#define STM32_RTC_BASE 0x40002800 /* 0x40002800-0x40002bff: RTC & BKP registers */ +#define STM32_BKP_BASE 0x40002850 +#define STM32_WWDG_BASE 0x40002c00 /* 0x40002c00-0x40002fff: Window watchdog (WWDG) */ +#define STM32_IWDG_BASE 0x40003000 /* 0x40003000-0x400033ff: Independent watchdog (IWDG) */ +#define STM32_I2S2EXT_BASE 0x40003400 /* 0x40003400-0x400037ff: I2S2ext */ +#define STM32_SPI2_BASE 0x40003800 /* 0x40003800-0x40003bff: SPI2/I2S2 */ +#define STM32_I2S2_BASE 0x40003800 +#define STM32_SPI3_BASE 0x40003c00 /* 0x40003c00-0x40003fff: SPI3/I2S3 */ +#define STM32_I2S3_BASE 0x40003c00 +#define STM32_I2S3EXT_BASE 0x40004000 /* 0x40003400-0x400043ff: I2S3ext */ +#define STM32_USART2_BASE 0x40004400 /* 0x40004400-0x400047ff: USART2 */ +#define STM32_USART3_BASE 0x40004800 /* 0x40004800-0x40004bff: USART3 */ +#define STM32_UART4_BASE 0x40004c00 /* 0x40004c00-0x40004fff: UART4 */ +#define STM32_UART5_BASE 0x40005000 /* 0x40005000-0x400053ff: UART5 */ +#define STM32_I2C1_BASE 0x40005400 /* 0x40005400-0x400057ff: I2C1 */ +#define STM32_I2C2_BASE 0x40005800 /* 0x40005800-0x40005Bff: I2C2 */ +#define STM32_I2C3_BASE 0x40005c00 /* 0x40005c00-0x40005fff: I2C3 */ +#define STM32_CAN1_BASE 0x40006400 /* 0x40006400-0x400067ff: bxCAN1 */ +#define STM32_CAN2_BASE 0x40006800 /* 0x40006800-0x40006bff: bxCAN2 */ +#define STM32_PWR_BASE 0x40007000 /* 0x40007000-0x400073ff: Power control PWR */ +#define STM32_DAC_BASE 0x40007400 /* 0x40007400-0x400077ff: DAC */ + +/* APB2 Base Addresses **************************************************************/ + +#define STM32_TIM1_BASE 0x40010000 /* 0x40010000-0x400103ff: TIM1 timer */ +#define STM32_TIM8_BASE 0x40010400 /* 0x40010400-0x400107ff: TIM8 timer */ +#define STM32_USART1_BASE 0x40011000 /* 0x40011000-0x400113ff: USART1 */ +#define STM32_USART6_BASE 0x40011400 /* 0x40011400-0x400117ff: USART6 */ +#define STM32_ADC_BASE 0x40012000 /* 0x40012000-0x400123ff: ADC1-3 */ +# define STM32_ADC1_BASE 0x40012000 /* ADC1 */ +# define STM32_ADC2_BASE 0x40012100 /* ADC2 */ +# define STM32_ADC3_BASE 0x40012200 /* ADC3 */ +# define STM32_ADCCMN_BASE 0x40012300 /* Common */ +#define STM32_SDIO_BASE 0x40012c00 /* 0x40012c00-0x40012fff: SDIO */ +#define STM32_SPI1_BASE 0x40013000 /* 0x40013000-0x400133ff: SPI1 */ +#define STM32_SYSCFG_BASE 0x40013800 /* 0x40013800-0x40013bff: SYSCFG */ +#define STM32_EXTI_BASE 0x40013c00 /* 0x40013c00-0x40013fff: EXTI */ +#define STM32_TIM9_BASE 0x40014000 /* 0x40014000-0x400143ff: TIM9 timer */ +#define STM32_TIM10_BASE 0x40014400 /* 0x40014400-0x400147ff: TIM10 timer */ +#define STM32_TIM11_BASE 0x40014800 /* 0x40014800-0x40014bff: TIM11 timer */ + +/* AHB1 Base Addresses **************************************************************/ + +#define STM32_GPIOA_BASE 0x40020000 /* 0x40020000-0x400203ff: GPIO Port A */ +#define STM32_GPIOB_BASE 0x40020400 /* 0x40020400-0x400207ff: GPIO Port B */ +#define STM32_GPIOC_BASE 0x40020800 /* 0x40020800-0x40020bff: GPIO Port C */ +#define STM32_GPIOD_BASE 0X40020C00 /* 0x40020c00-0x40020fff: GPIO Port D */ +#define STM32_GPIOE_BASE 0x40021000 /* 0x40021000-0x400213ff: GPIO Port E */ +#define STM32_GPIOF_BASE 0x40021400 /* 0x40021400-0x400217ff: GPIO Port F */ +#define STM32_GPIOG_BASE 0x40021800 /* 0x40021800-0x40021bff: GPIO Port G */ +#define STM32_GPIOH_BASE 0x40021C00 /* 0x40021C00-0x40021fff: GPIO Port H */ +#define STM32_GPIOI_BASE 0x40022000 /* 0x40022000-0x400223ff: GPIO Port I */ +#define STM32_CRC_BASE 0x40023000 /* 0x40023000-0x400233ff: CRC */ +#define STM32_RCC_BASE 0x40023800 /* 0x40023800-0x40023bff: Reset and Clock control RCC */ +#define STM32_FLASHIF_BASE 0x40023c00 /* 0x40023c00-0x40023fff: Flash memory interface */ +#define STM32_BKPSRAM_BASE 0x40024000 /* 0x40024000-0x40024fff: Backup SRAM (BKPSRAM) */ +#define STM32_DMA1_BASE 0x40026000 /* 0x40026000-0x400263ff: DMA1 */ +#define STM32_DMA2_BASE 0x40026400 /* 0x40026400-0x400267ff: DMA2 */ +#define STM32_ETHERNET_BASE 0x40028000 /* 0x40028000-0x400283ff: Ethernet MAC */ + /* 0x40028400-0x400287ff: Ethernet MAC */ + /* 0x40028800-0x40028bff: Ethernet MAC */ + /* 0x40028c00-0x40028fff: Ethernet MAC */ + /* 0x40029000-0x400293ff: Ethernet MAC */ +#define STM32_OTGHS_BASE 0x40040000 /* 0x40040000-0x4007ffff: USB OTG HS */ +#define STM32_PERIPHBB_BASE 0x42000000 /* Peripheral bit-band region */ + +/* AHB2 Base Addresses **************************************************************/ + +#define STM32_OTGFS_BASE 0x50000000 /* 0x50000000-0x5003ffff: USB OTG FS */ +#define STM32_DCMI_BASE 0x50050000 /* 0x50050000-0x500503ff: DCMI */ +#define STM32_CRYP_BASE 0x50060000 /* 0x50060000-0x500603ff: CRYP */ +#define STM32_HASH_BASE 0x50060400 /* 0x50060400-0x500607ff: HASH */ +#define STM32_RNG_BASE 0x50060800 /* 0x50060800-0x50060bff: RNG */ + +/* Cortex-M4 Base Addresses *********************************************************/ +/* Other registers -- see armv7-m/nvic.h for standard Cortex-M3 registers in this + * address range + */ + +#define STM32_SCS_BASE 0xe000e000 +#define STM32_DEBUGMCU_BASE 0xe0042000 + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_MEMORYMAP_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h new file mode 100644 index 0000000000..a588b56a27 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h @@ -0,0 +1,695 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_PINMAP_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_PINMAP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "stm32_gpio.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Alternate Pin Functions. All members of the STM32F40xxx family share the same + * pin multiplexing (although they may differ in the pins physically available). + * + * Alternative pin selections are provided with a numeric suffix like _1, _2, etc. + * Drivers, however, will use the pin selection without the numeric suffix. + * Additional definitions are required in the board.h file. For example, if + * CAN1_RX connects vis PA11 on some board, then the following definitions should + * appear inthe board.h header file for that board: + * + * #define GPIO_CAN1_RX GPIO_CAN1_RX_1 + * + * The driver will then automatically configre PA11 as the CAN1 RX pin. + */ + +/* WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! + * Additional effort is required to select specific GPIO options such as frequency, + * open-drain/push-pull, and pull-up/down! Just the basics are defined for most + * pins in this file. + */ + +/* ADC */ + +#define GPIO_ADC1_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC1_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC1_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC1_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC1_IN4 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC1_IN5 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC1_IN6 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC1_IN7 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC1_IN8 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC1_IN9 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN1) +#define GPIO_ADC1_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC1_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC1_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC1_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC1_IN14 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC1_IN15 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN5) + +#define GPIO_ADC2_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC2_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC2_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC2_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC2_IN4 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC2_IN5 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC2_IN6 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC2_IN7 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC2_IN8 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC2_IN9 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN1) +#define GPIO_ADC2_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC2_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC2_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC2_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC2_IN14 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC2_IN15 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN5) + +#define GPIO_ADC3_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC3_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC3_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC3_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC3_IN4 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN6) +#define GPIO_ADC3_IN5 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN7) +#define GPIO_ADC3_IN6 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN8) +#define GPIO_ADC3_IN7 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN9) +#define GPIO_ADC3_IN9 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN3) +#define GPIO_ADC3_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC3_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC3_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC3_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC3_IN14 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN4) +#define GPIO_ADC3_IN15 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN5) + +/* CAN */ + +#define GPIO_CAN1_RX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11) +#define GPIO_CAN1_RX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) +#define GPIO_CAN1_RX_3 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN0) +#define GPIO_CAN1_RX_4 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN9) +#define GPIO_CAN1_TX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN12) +#define GPIO_CAN1_TX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) +#define GPIO_CAN1_TX_3 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN1) +#define GPIO_CAN1_TX_4 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN13) + +#define GPIO_CAN2_RX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12) +#define GPIO_CAN2_RX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5) +#define GPIO_CAN2_TX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN13) +#define GPIO_CAN2_TX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6) + +/* DAC -" Once the DAC channelx is enabled, the corresponding GPIO pin + * (PA4 or PA5) is automatically connected to the analog converter output + * (DAC_OUTx). In order to avoid parasitic consumption, the PA4 or PA5 pin + * should first be configured to analog (AIN)". + */ + +#define GPIO_DAC1_OUT (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4) +#define GPIO_DAC2_OUT (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5) + +/* Digital Camera Interface (DCMI) */ + +#define GPIO_DCMI_D0_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN9) +#define GPIO_DCMI_D0_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN6) +#define GPIO_DCMI_D0_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN9) +#define GPIO_DCMI_D1_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN10) +#define GPIO_DCMI_D1_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN7) +#define GPIO_DCMI_D1_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN10) +#define GPIO_DCMI_D2_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN8) +#define GPIO_DCMI_D2_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN0) +#define GPIO_DCMI_D2_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN11) +#define GPIO_DCMI_D3_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN9) +#define GPIO_DCMI_D3_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN1) +#define GPIO_DCMI_D3_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN12) +#define GPIO_DCMI_D4_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN11) +#define GPIO_DCMI_D4_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN4) +#define GPIO_DCMI_D4_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN14) +#define GPIO_DCMI_D5_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN6) +#define GPIO_DCMI_D5_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN4) +#define GPIO_DCMI_D6_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN8) +#define GPIO_DCMI_D6_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN5) +#define GPIO_DCMI_D6_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN6) +#define GPIO_DCMI_D7_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN9) +#define GPIO_DCMI_D7_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN6) +#define GPIO_DCMI_D7_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN7) +#define GPIO_DCMI_D8_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN10) +#define GPIO_DCMI_D8_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN1) +#define GPIO_DCMI_D9_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN12) +#define GPIO_DCMI_D9_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN2) +#define GPIO_DCMI_D10_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN5) +#define GPIO_DCMI_D10_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN3) +#define GPIO_DCMI_D11_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTD|GPIO_PIN2) +#define GPIO_DCMI_D11_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN15) +#define GPIO_DCMI_D12 (GPIO_ALT|GPIO_AF13|GPIO_PORTF|GPIO_PIN11) +#define GPIO_DCMI_D13_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTG|GPIO_PIN15) +#define GPIO_DCMI_D13_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN0) +#define GPIO_DCMI_HSYNC_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN4) +#define GPIO_DCMI_HSYNC_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN8) +#define GPIO_DCMI_PIXCK (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN6) +#define GPIO_DCMI_VSYNC_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN7) +#define GPIO_DCMI_VSYNC_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN5) + +/* Clocks outputs */ + +#define GPIO_MCO1 (GPIO_ALT|GPIO_AF0|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) +#define GPIO_MCO2 (GPIO_ALT|GPIO_AF0|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) + +/* Ethernet MAC */ + +#define GPIO_ETH_MDC (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ETH_MDIO (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ETH_MII_COL_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ETH_MII_COL_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN3) +#define GPIO_ETH_MII_CRS_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ETH_MII_CRS_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN2) +#define GPIO_ETH_MII_RXD0 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ETH_MII_RXD1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN5) +#define GPIO_ETH_MII_RXD2_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ETH_MII_RXD2_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6) +#define GPIO_ETH_MII_RXD3_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1) +#define GPIO_ETH_MII_RXD3_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN7) +#define GPIO_ETH_MII_RX_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ETH_MII_RX_DV (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ETH_MII_RX_ER_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10) +#define GPIO_ETH_MII_RX_ER_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN10) +#define GPIO_ETH_MII_TXD0_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12) +#define GPIO_ETH_MII_TXD0_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN13) +#define GPIO_ETH_MII_TXD1_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN13) +#define GPIO_ETH_MII_TXD1_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14) +#define GPIO_ETH_MII_TXD2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ETH_MII_TXD3_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) +#define GPIO_ETH_MII_TXD3_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN2) +#define GPIO_ETH_MII_TX_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ETH_MII_TX_EN_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11) +#define GPIO_ETH_MII_TX_EN_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN11) +#define GPIO_ETH_PPS_OUT_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5) +#define GPIO_ETH_PPS_OUT_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN8) +#define GPIO_ETH_RMII_CRS_DV (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULLGPIO_PORTA|GPIO_PIN7) +#define GPIO_ETH_RMII_REF_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ETH_RMII_RXD0 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ETH_RMII_RXD1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN5) +#define GPIO_ETH_RMII_TXD0_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12) +#define GPIO_ETH_RMII_TXD0_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN13) +#define GPIO_ETH_RMII_TXD1_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN13) +#define GPIO_ETH_RMII_TXD1_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14) +#define GPIO_ETH_RMII_TX_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ETH_RMII_TX_EN_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11) +#define GPIO_ETH_RMII_TX_EN_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN11) + +/* Flexible Static Memory Controller (FSMC) */ + +#define GPIO_FSMC_A0 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN0) +#define GPIO_FSMC_A1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN1) +#define GPIO_FSMC_A2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN2) +#define GPIO_FSMC_A3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN3) +#define GPIO_FSMC_A4 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN4) +#define GPIO_FSMC_A5 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN5) +#define GPIO_FSMC_A6 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN12) +#define GPIO_FSMC_A7 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN13) +#define GPIO_FSMC_A8 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN14) +#define GPIO_FSMC_A9 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN15) +#define GPIO_FSMC_A10 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN0) +#define GPIO_FSMC_A11 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN1) +#define GPIO_FSMC_A12 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN2) +#define GPIO_FSMC_A13 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN3) +#define GPIO_FSMC_A14 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN4) +#define GPIO_FSMC_A15 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN5) +#define GPIO_FSMC_A16 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN11) +#define GPIO_FSMC_A17 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN12) +#define GPIO_FSMC_A18 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN13) +#define GPIO_FSMC_A19 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN3) +#define GPIO_FSMC_A20 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN4) +#define GPIO_FSMC_A21 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN5) +#define GPIO_FSMC_A22 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN6) +#define GPIO_FSMC_A23 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN2) +#define GPIO_FSMC_A24 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN13) +#define GPIO_FSMC_A25 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN14) +#define GPIO_FSMC_NBL1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN1) +#define GPIO_FSMC_CD (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN9) +#define GPIO_FSMC_CLK (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN3) +#define GPIO_FSMC_D0 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN14) +#define GPIO_FSMC_D1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN15) +#define GPIO_FSMC_D2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN0) +#define GPIO_FSMC_D3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN1) +#define GPIO_FSMC_D4 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN7) +#define GPIO_FSMC_D5 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN8) +#define GPIO_FSMC_D6 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN9) +#define GPIO_FSMC_D7 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN10) +#define GPIO_FSMC_D8 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN11) +#define GPIO_FSMC_D9 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN12) +#define GPIO_FSMC_D10 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN13) +#define GPIO_FSMC_D11 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN14) +#define GPIO_FSMC_D12 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN15) +#define GPIO_FSMC_D13 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN8) +#define GPIO_FSMC_D14 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN9) +#define GPIO_FSMC_D15 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN10) +#define GPIO_FSMC_INT2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN6) +#define GPIO_FSMC_INT3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN7) +#define GPIO_FSMC_INTR (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN10) +#define GPIO_FSMC_NBL0 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN0) +#define GPIO_FSMC_NCE2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN7) +#define GPIO_FSMC_NCE3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN9) +#define GPIO_FSMC_NCE4_1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN10) +#define GPIO_FSMC_NCE4_2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN11) +#define GPIO_FSMC_NE1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN7) +#define GPIO_FSMC_NE2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN9) +#define GPIO_FSMC_NE3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN10) +#define GPIO_FSMC_NE4 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN12) +#define GPIO_FSMC_NIORD (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN6) +#define GPIO_FSMC_NIOWR (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN8) +#define GPIO_FSMC_NL (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTB|GPIO_PIN7) +#define GPIO_FSMC_NOE (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN4) +#define GPIO_FSMC_NREG (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN7) +#define GPIO_FSMC_NWAIT (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN6) +#define GPIO_FSMC_NWE (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN5) + +/* I2C */ + +#define GPIO_I2C1_SCL_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN6) +#define GPIO_I2C1_SCL_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN8) +#define GPIO_I2C1_SDA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN7) +#define GPIO_I2C1_SDA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN9) +#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5) + +#define GPIO_I2C2_SCL_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN10) +#define GPIO_I2C2_SCL_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTF|GPIO_PIN1) +#define GPIO_I2C2_SCL_3 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN4) +#define GPIO_I2C2_SDA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN11) +#define GPIO_I2C2_SDA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTF|GPIO_PIN0) +#define GPIO_I2C2_SDA_3 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN5) +#define GPIO_I2C2_SMBA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12) +#define GPIO_I2C2_SMBA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN2) +#define GPIO_I2C2_SMBA_3 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6) + +#define GPIO_I2C3_SCL_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTA|GPIO_PIN8) +#define GPIO_I2C3_SCL_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN7) +#define GPIO_I2C3_SDA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTC|GPIO_PIN9) +#define GPIO_I2C3_SDA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN8) +#define GPIO_I2C3_SMBA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9) +#define GPIO_I2C3_SMBA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN9) + +/* I2S */ + +#define GPIO_I2S2_CK_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN10) +#define GPIO_I2S2_CK_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN13) +#define GPIO_I2S2_CK_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN1) +#define GPIO_I2S2_MCK (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN6) +#define GPIO_I2S2_SD_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN15) +#define GPIO_I2S2_SD_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN3) +#define GPIO_I2S2_SD_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN3) +#define GPIO_I2S2_WS_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN12) +#define GPIO_I2S2_WS_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN6) +#define GPIO_I2S2_WS_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN9) +#define GPIO_I2S2_WS_4 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN0) + +#define GPIO_I2S2EXT_SD_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN14) +#define GPIO_I2S2EXT_SD_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN2) +#define GPIO_I2S2EXT_SD_3 (GPIO_ALT|GPIO_AF6|GPIO_PORTI|GPIO_PIN2) + +#define GPIO_I2S3_CK_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN3) +#define GPIO_I2S3_CK_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN10) +#define GPIO_I2S3_MCK (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN7) +#define GPIO_I2S3_SD_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN5) +#define GPIO_I2S3_SD_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN12) +#define GPIO_I2S3_WS_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN4) +#define GPIO_I2S3_WS_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN15) + +#define GPIO_I2S3EXT_SD_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN11) +#define GPIO_I2S3EXT_SD_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN4) + +#define GPIO_I2S_CKIN (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN9) + +/* JTAG */ + +#define GPIO_JTCK_SWCLK (GPIO_ALT|GPIO_AF0|GPIO_PORTA|GPIO_PIN14) +#define GPIO_JTDI (GPIO_ALT|GPIO_AF0|GPIO_PORTA|GPIO_PIN15) +#define GPIO_JTDO (GPIO_ALT|GPIO_AF0|GPIO_PORTB|GPIO_PIN3) +#define GPIO_JTMS_SWDIO (GPIO_ALT|GPIO_AF0|GPIO_PORTA|GPIO_PIN13) +#define GPIO_JTRST (GPIO_ALT|GPIO_AF0|GPIO_PORTB|GPIO_PIN4) + +/* OTG FS/HS */ + +#define GPIO_OTGFS_DM (GPIO_ALT|GPIO_FLOAT|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11) +#define GPIO_OTGFS_DP (GPIO_ALT|GPIO_FLOAT|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN12) +#define GPIO_OTGFS_ID (GPIO_ALT|GPIO_PULLUP|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_OPENDRAIN|GPIO_PORTA|GPIO_PIN10) +#define GPIO_OTGFS_SCL (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN8) +#define GPIO_OTGFS_SDA (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN9) +#define GPIO_OTGFS_SOF (GPIO_ALT|GPIO_FLOAT|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) + +#define GPIO_OTGHS_DM (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN14) +#define GPIO_OTGHS_DP (GPIO_ALT|GPIO_AF12|GPIO_PORTC|GPIO_PIN15) +#define GPIO_OTGHS_ID (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN12) +#define GPIO_OTGHS_INTN_1 (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN1) +#define GPIO_OTGFS_INTN_2 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN6) +#define GPIO_OTGHS_SCL (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN10) +#define GPIO_OTGHS_SDA (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN11) +#define GPIO_OTGHS_SOF (GPIO_ALT|GPIO_AF12|GPIO_PORTA|GPIO_PIN4) +#define GPIO_OTGHS_ULPI_CK (GPIO_ALT|GPIO_AF10|GPIO_PORTA|GPIO_PIN5) +#define GPIO_OTGHS_ULPI_D0 (GPIO_ALT|GPIO_AF10|GPIO_PORTA|GPIO_PIN3) +#define GPIO_OTGHS_ULPI_D1 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN0) +#define GPIO_OTGHS_ULPI_D2 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN1) +#define GPIO_OTGHS_ULPI_D3 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN10) +#define GPIO_OTGHS_ULPI_D4 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN11) +#define GPIO_OTGHS_ULPI_D5 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN12) +#define GPIO_OTGHS_ULPI_D6 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN13) +#define GPIO_OTGHS_ULPI_D7 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN5) +#define GPIO_OTGHS_ULPI_DIR_1 (GPIO_ALT|GPIO_AF10|GPIO_PORTC|GPIO_PIN2) +#define GPIO_OTGHS_ULPI_DIR_2 (GPIO_ALT|GPIO_AF10|GPIO_PORTI|GPIO_PIN11) +#define GPIO_OTGHS_ULPI_NXT_1 (GPIO_ALT|GPIO_AF10|GPIO_PORTC|GPIO_PIN3) +#define GPIO_OTGHS_ULPI_NXT_2 (GPIO_ALT|GPIO_AF10|GPIO_PORTH|GPIO_PIN4) +#define GPIO_OTGHS_ULPI_STP (GPIO_ALT|GPIO_AF10|GPIO_PORTC|GPIO_PIN0) + +/* RTC */ + +#define GPIO_RTC_50HZ (GPIO_ALT|GPIO_AF0|GPIO_PORTC|GPIO_PIN15) + +/* SDIO */ + +#define GPIO_SDIO_CK (GPIO_ALT|GPIO_AF12|GPIO_PORTC|GPIO_PIN12) +#define GPIO_SDIO_CMD (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN2) +#define GPIO_SDIO_D0 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8) +#define GPIO_SDIO_D1 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) +#define GPIO_SDIO_D2 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10) +#define GPIO_SDIO_D3 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN11) +#define GPIO_SDIO_D4 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) +#define GPIO_SDIO_D5 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) +#define GPIO_SDIO_D6 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) +#define GPIO_SDIO_D7 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) + +/* SPI */ + +#define GPIO_SPI1_MISO_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN6) +#define GPIO_SPI1_MISO_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN4) +#define GPIO_SPI1_MOSI_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN7) +#define GPIO_SPI1_MOSI_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN5) +#define GPIO_SPI1_NSS_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN15) +#define GPIO_SPI1_NSS_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN4) +#define GPIO_SPI1_SCK_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN5) +#define GPIO_SPI1_SCK_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN3) + +#define GPIO_SPI2_MISO_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN14) +#define GPIO_SPI2_MISO_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN2) +#define GPIO_SPI2_MISO_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN2) +#define GPIO_SPI2_MOSI_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN15) +#define GPIO_SPI2_MOSI_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN3) +#define GPIO_SPI2_MOSI_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN3) +#define GPIO_SPI2_NSS_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN12) +#define GPIO_SPI2_NSS_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN9) +#define GPIO_SPI2_NSS_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN0) +#define GPIO_SPI2_SCK_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN10) +#define GPIO_SPI2_SCK_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN13) +#define GPIO_SPI2_SCK_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN1) + +#define GPIO_SPI3_MISO_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN4) +#define GPIO_SPI3_MISO_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN11) +#define GPIO_SPI3_MOSI_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN5) +#define GPIO_SPI3_MOSI_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN12) +#define GPIO_SPI3_NSS_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN15) +#define GPIO_SPI3_NSS_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN4) +#define GPIO_SPI3_SCK_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN3) +#define GPIO_SPI3_SCK_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN10) + +/* Timers */ + +#define GPIO_TIM1_BKIN_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM1_BKIN_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN12) +#define GPIO_TIM1_BKIN_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN15) +#define GPIO_TIM1_CH1N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM1_CH1N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN13) +#define GPIO_TIM1_CH1N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN8) +#define GPIO_TIM1_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN8) +#define GPIO_TIM1_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN9) +#define GPIO_TIM1_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) +#define GPIO_TIM1_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN9) +#define GPIO_TIM1_CH2N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN0) +#define GPIO_TIM1_CH2N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN14) +#define GPIO_TIM1_CH2N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN10) +#define GPIO_TIM1_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN9) +#define GPIO_TIM1_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN11) +#define GPIO_TIM1_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9) +#define GPIO_TIM1_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN11) +#define GPIO_TIM1_CH3N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN1) +#define GPIO_TIM1_CH3N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTC|GPIO_PIN15) +#define GPIO_TIM1_CH3N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN12) +#define GPIO_TIM1_CH3IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN10) +#define GPIO_TIM1_CH3IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN13) +#define GPIO_TIM1_CH3OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10) +#define GPIO_TIM1_CH3OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN13) +#define GPIO_TIM1_CH4IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN11) +#define GPIO_TIM1_CH4IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN14) +#define GPIO_TIM1_CH4OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11) +#define GPIO_TIM1_CH4OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN14) +#define GPIO_TIM1_ETR_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN12) +#define GPIO_TIM1_ETR_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN7) + +#define GPIO_TIM2_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM2_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN15) +#define GPIO_TIM2_CH1IN_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN5) +#define GPIO_TIM2_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM2_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN15) +#define GPIO_TIM2_CH1OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN5) +#define GPIO_TIM2_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM2_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN3) +#define GPIO_TIM2_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM2_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN3) +#define GPIO_TIM2_CH3IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM2_CH3IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN10) +#define GPIO_TIM2_CH3OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM2_CH3OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10) +#define GPIO_TIM2_CH4IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM2_CH4IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN11) +#define GPIO_TIM2_CH4OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM2_CH4OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11) +#define GPIO_TIM2_ETR_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM2_ETR_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN15) +#define GPIO_TIM2_ETR_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN5) + +#define GPIO_TIM3_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM3_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN4) +#define GPIO_TIM3_CH1IN_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM3_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM3_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN4) +#define GPIO_TIM3_CH1OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM3_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM3_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN5) +#define GPIO_TIM3_CH2IN_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM3_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM3_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5) +#define GPIO_TIM3_CH2OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM3_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN0) +#define GPIO_TIM3_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM3_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0) +#define GPIO_TIM3_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM3_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN1) +#define GPIO_TIM3_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM3_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1) +#define GPIO_TIM3_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM3_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN2) + +#define GPIO_TIM4_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN6) +#define GPIO_TIM4_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN12) +#define GPIO_TIM4_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6) +#define GPIO_TIM4_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN12) +#define GPIO_TIM4_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN7) +#define GPIO_TIM4_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN13) +#define GPIO_TIM4_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN7) +#define GPIO_TIM4_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN13) +#define GPIO_TIM4_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM4_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN14) +#define GPIO_TIM4_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM4_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN14) +#define GPIO_TIM4_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM4_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN15) +#define GPIO_TIM4_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM4_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN15) +#define GPIO_TIM4_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN0) + +#define GPIO_TIM5_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN10) +#define GPIO_TIM5_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN10) +#define GPIO_TIM5_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN11) +#define GPIO_TIM5_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN11) +#define GPIO_TIM5_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN12) +#define GPIO_TIM5_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN12) +#define GPIO_TIM5_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM5_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN0) +#define GPIO_TIM5_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM5_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN0) +#define GPIO_TIM5_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN10) + +#define GPIO_TIM8_BKIN_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM8_BKIN_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTI|GPIO_PIN4) +#define GPIO_TIM8_CH1N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN5) +#define GPIO_TIM8_CH1N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM8_CH1N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN13) +#define GPIO_TIM8_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM8_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN5) +#define GPIO_TIM8_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM8_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN5) +#define GPIO_TIM8_CH2IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM8_CH2IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN6) +#define GPIO_TIM8_CH2OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM8_CH2OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN6) +#define GPIO_TIM8_CH2N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN0) +#define GPIO_TIM8_CH2N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN14) +#define GPIO_TIM8_CH2N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN14) +#define GPIO_TIM8_CH3N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN1) +#define GPIO_TIM8_CH3N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTC|GPIO_PIN15) +#define GPIO_TIM8_CH3N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN15) +#define GPIO_TIM8_CH3IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM8_CH3IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN7) +#define GPIO_TIM8_CH3OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM8_CH3OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN7) +#define GPIO_TIM8_CH4IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM8_CH4IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN2) +#define GPIO_TIM8_CH4OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM8_CH4OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN2) +#define GPIO_TIM8_ETR_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM8_ETR_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN3) + +#define GPIO_TIM9_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM9_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN5) +#define GPIO_TIM9_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM9_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN5) +#define GPIO_TIM9_CH2IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM9_CH2IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN6) +#define GPIO_TIM9_CH2OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM9_CH2OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN6) + +#define GPIO_TIM10_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM10_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN6) +#define GPIO_TIM10_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM10_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN6) + +#define GPIO_TIM11_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM11_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN7) +#define GPIO_TIM11_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM11_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN7) + +#define GPIO_TIM12_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN6) +#define GPIO_TIM12_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN14) +#define GPIO_TIM12_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6) +#define GPIO_TIM12_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN14) +#define GPIO_TIM12_CH2IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN15) +#define GPIO_TIM12_CH2IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN9) +#define GPIO_TIM12_CH2OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN15) +#define GPIO_TIM12_CH2OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN9) + +#define GPIO_TIM13_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM13_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN8) +#define GPIO_TIM13_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM13_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN8) + +#define GPIO_TIM14_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM14_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN9) +#define GPIO_TIM14_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM14_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN9) + +/* Trace */ + +#define GPIO_TRACECLK (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN2) +#define GPIO_TRACED0 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN3) +#define GPIO_TRACED1 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN4) +#define GPIO_TRACED2 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN5) +#define GPIO_TRACED3 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN6) +#define GPIO_TRACESWO (GPIO_ALT|GPIO_AF0|GPIO_PORTB|GPIO_PIN3) + +/* UARTs/USARTs */ + +#define GPIO_USART1_CK (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN8) +#define GPIO_USART1_CTS (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN11) +#define GPIO_USART1_RTS (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN12) +#define GPIO_USART1_RX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10) +#define GPIO_USART1_RX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN7) +#define GPIO_USART1_TX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9) +#define GPIO_USART1_TX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6) + +#define GPIO_USART2_CK_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN4) +#define GPIO_USART2_CK_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN7) +#define GPIO_USART2_CTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN0) +#define GPIO_USART2_CTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN3) +#define GPIO_USART2_RTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN1) +#define GPIO_USART2_RTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN4) +#define GPIO_USART2_RX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_USART2_RX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN6) +#define GPIO_USART2_TX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_USART2_TX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN5) + +#define GPIO_USART3_CK_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN12) +#define GPIO_USART3_CK_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTC|GPIO_PIN12) +#define GPIO_USART3_CK_3 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN10) +#define GPIO_USART3_CTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN13) +#define GPIO_USART3_CTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN11) +#define GPIO_USART3_RTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN14) +#define GPIO_USART3_RTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN12) +#define GPIO_USART3_RX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11) +#define GPIO_USART3_RX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN11) +#define GPIO_USART3_RX_3 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN9) +#define GPIO_USART3_TX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10) +#define GPIO_USART3_TX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10) +#define GPIO_USART3_TX_3 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN8) + +#define GPIO_UART4_RX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_UART4_RX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN11) +#define GPIO_UART4_TX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) +#define GPIO_UART4_TX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10) + +#define GPIO_UART5_RX (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN2) +#define GPIO_UART5_TX (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN12) + +#define GPIO_USART6_CK_1 (GPIO_ALT|GPIO_AF8|GPIO_PORTC|GPIO_PIN8) +#define GPIO_USART6_CK_2 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN7) +#define GPIO_USART6_CTS_1 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN13) +#define GPIO_USART6_CTS_2 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN15) +#define GPIO_USART6_RTS_1 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN12) +#define GPIO_USART6_RTS_2 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN8) +#define GPIO_USART6_RX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) +#define GPIO_USART6_RX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN9) +#define GPIO_USART6_TX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) +#define GPIO_USART6_TX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_PINMAP_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rcc.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rcc.h new file mode 100644 index 0000000000..04cb057417 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rcc.h @@ -0,0 +1,506 @@ +/**************************************************************************************************** + * arch/arm/src/stm32/chip/stm32f40xxx_rcc.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_RCC_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_RCC_H + +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ + +/* Register Offsets *********************************************************************************/ + +#define STM32_RCC_CR_OFFSET 0x0000 /* Clock control register */ +#define STM32_RCC_PLLCFG_OFFSET 0x0004 /* PLL configuration register */ +#define STM32_RCC_CFGR_OFFSET 0x0008 /* Clock configuration register */ +#define STM32_RCC_CIR_OFFSET 0x000c /* Clock interrupt register */ +#define STM32_RCC_AHB1RSTR_OFFSET 0x0010 /* AHB1 peripheral reset register */ +#define STM32_RCC_AHB2RSTR_OFFSET 0x0014 /* AHB2 peripheral reset register */ +#define STM32_RCC_AHB3RSTR_OFFSET 0x0018 /* AHB3 peripheral reset register */ +#define STM32_RCC_APB1RSTR_OFFSET 0x0020 /* APB1 Peripheral reset register */ +#define STM32_RCC_APB2RSTR_OFFSET 0x0024 /* APB2 Peripheral reset register */ +#define STM32_RCC_AHB1ENR_OFFSET 0x0030 /* AHB1 Peripheral Clock enable register */ +#define STM32_RCC_AHB2ENR_OFFSET 0x0034 /* AHB2 Peripheral Clock enable register */ +#define STM32_RCC_AHB3ENR_OFFSET 0x0038 /* AHB3 Peripheral Clock enable register */ +#define STM32_RCC_APB1ENR_OFFSET 0x0040 /* APB1 Peripheral Clock enable register */ +#define STM32_RCC_APB2ENR_OFFSET 0x0044 /* APB2 Peripheral Clock enable register */ +#define STM32_RCC_AHB1LPENR_OFFSET 0x0050 /* RCC AHB1 low power modeperipheral clock enable register */ +#define STM32_RCC_AH2BLPENR_OFFSET 0x0054 /* RCC AHB2 low power modeperipheral clock enable register */ +#define STM32_RCC_AH3BLPENR_OFFSET 0x0058 /* RCC AHB3 low power modeperipheral clock enable register */ +#define STM32_RCC_APB1LPENR_OFFSET 0x0060 /* RCC APB1 low power modeperipheral clock enable register */ +#define STM32_RCC_APB2LPENR_OFFSET 0x0060 /* RCC APB2 low power modeperipheral clock enable register */ +#define STM32_RCC_BDCR_OFFSET 0x0070 /* Backup domain control register */ +#define STM32_RCC_CSR_OFFSET 0x0074 /* Control/status register */ +#define STM32_RCC_SSCGR_OFFSET 0x0080 /* Spread spectrum clock generation register */ +#define STM32_RCC_PLLI2SCFGR_OFFSET 0x0084 /* PLLI2S configuration register */ + +/* Register Addresses *******************************************************************************/ + +#define STM32_RCC_CR (STM32_RCC_BASE+STM32_RCC_CR_OFFSET) +#define STM32_RCC_PLLCFG (STM32_RCC_BASE+STM32_RCC_PLLCFG_OFFSET) +#define STM32_RCC_CFGR (STM32_RCC_BASE+STM32_RCC_CFGR_OFFSET) +#define STM32_RCC_CIR (STM32_RCC_BASE+STM32_RCC_CIR_OFFSET) +#define STM32_RCC_AHB1RSTR (STM32_RCC_BASE+STM32_RCC_AHB1RSTR_OFFSET) +#define STM32_RCC_AHB2RSTR (STM32_RCC_BASE+STM32_RCC_AHB2RSTR_OFFSET) +#define STM32_RCC_AHB3RSTR (STM32_RCC_BASE+STM32_RCC_AHB3RSTR_OFFSET) +#define STM32_RCC_APB1RSTR (STM32_RCC_BASE+STM32_RCC_APB1RSTR_OFFSET) +#define STM32_RCC_APB2RSTR (STM32_RCC_BASE+STM32_RCC_APB2RSTR_OFFSET) +#define STM32_RCC_AHB1ENR (STM32_RCC_BASE+STM32_RCC_AHB1ENR_OFFSET) +#define STM32_RCC_AHB2ENR (STM32_RCC_BASE+STM32_RCC_AHB2ENR_OFFSET) +#define STM32_RCC_AHB3ENR (STM32_RCC_BASE+STM32_RCC_AHB3ENR_OFFSET) +#define STM32_RCC_APB1ENR (STM32_RCC_BASE+STM32_RCC_APB1ENR_OFFSET) +#define STM32_RCC_APB2ENR (STM32_RCC_BASE+STM32_RCC_APB2ENR_OFFSET) +#define STM32_RCC_AHB1LPENR (STM32_RCC_BASE+STM32_RCC_AHB1LPENR_OFFSET) +#define STM32_RCC_AH2BLPENR (STM32_RCC_BASE+STM32_RCC_AH2BLPENR) +#define STM32_RCC_AH3BLPENR (STM32_RCC_BASE+STM32_RCC_AH3BLPENR_OFFSET) +#define STM32_RCC_APB1LPENR (STM32_RCC_BASE+STM32_RCC_APB1LPENR_OFFSET) +#define STM32_RCC_APB2LPENR (STM32_RCC_BASE+STM32_RCC_APB2LPENR_OFFSET) +#define STM32_RCC_BDCR (STM32_RCC_BASE+STM32_RCC_BDCR_OFFSET) +#define STM32_RCC_CSR (STM32_RCC_BASE+STM32_RCC_CSR_OFFSET) +#define STM32_RCC_SSCGR (STM32_RCC_BASE+STM32_RCC_SSCGR_OFFSET) +#define STM32_RCC_PLLI2SCFGR (STM32_RCC_BASE+STM32_RCC_PLLI2SCFGR_OFFSET) + +/* Register Bitfield Definitions ********************************************************************/ + +/* Clock control register */ + +#define RCC_CR_HSION (1 << 0) /* Bit 0: Internal High Speed clock enable */ +#define RCC_CR_HSIRDY (1 << 1) /* Bit 1: Internal High Speed clock ready flag */ +#define RCC_CR_HSITRIM_SHIFT (3) /* Bits 7-3: Internal High Speed clock trimming */ +#define RCC_CR_HSITRIM_MASK (0x1f << RCC_CR_HSITRIM_SHIFT) +#define RCC_CR_HSICAL_SHIFT (8) /* Bits 15-8: Internal High Speed clock Calibration */ +#define RCC_CR_HSICAL_MASK (0xff << RCC_CR_HSICAL_SHIFT) +#define RCC_CR_HSEON (1 << 16) /* Bit 16: External High Speed clock enable */ +#define RCC_CR_HSERDY (1 << 17) /* Bit 17: External High Speed clock ready flag */ +#define RCC_CR_HSEBYP (1 << 18) /* Bit 18: External High Speed clock Bypass */ +#define RCC_CR_CSSON (1 << 19) /* Bit 19: Clock Security System enable */ +#define RCC_CR_PLLON (1 << 24) /* Bit 24: PLL enable */ +#define RCC_CR_PLLRDY (1 << 25) /* Bit 25: PLL clock ready flag */ +#define RCC_CR_PLLI2SON (1 << 26) /* Bit 26: PLLI2S enable */ +#define RCC_CR_PLLI2SRDY (1 << 27) /* Bit 27: PLLI2S clock ready flag */ + +/* PLL configuration register */ + +#define RCC_PLLCFG_PLLM_SHIFT (0) /* Bits 0-5: Main PLL (PLL) and audio PLL (PLLI2S) + * input clock divider */ +#define RCC_PLLCFG_PLLM_MASK (0x3f << RCC_PLLCFG_PLLM_SHIFT) +# define RCC_PLLCFG_PLLM(n) ((n) << RCC_PLLCFG_PLLM_SHIFT) /* n = 2..63 */ +#define RCC_PLLCFG_PLLN_SHIFT (6) /* Bits 6-14: Main PLL (PLL) VCO multiplier */ +#define RCC_PLLCFG_PLLN_MASK (0x1ff << RCC_PLLCFG_PLLN_SHIFT) +# define RCC_PLLCFG_PLLN(n) ((n) << RCC_PLLCFG_PLLN_SHIFT) /* n = 2..432 */ +#define RCC_PLLCFG_PLLP_SHIFT (16) /* Bits 16-17: Main PLL (PLL) main system clock divider */ +#define RCC_PLLCFG_PLLP_MASK (3 << RCC_PLLCFG_PLLP_SHIFT) +# define RCC_PLLCFG_PLLP(n) ((((n)>>1)-1)<< RCC_PLLCFG_PLLP_SHIFT) /* n=2,4,6,8 */ +# define RCC_PLLCFG_PLLP_2 (0 << RCC_PLLCFG_PLLP_SHIFT) /* 00: PLLP = 2 */ +# define RCC_PLLCFG_PLLP_4 (1 << RCC_PLLCFG_PLLP_SHIFT) /* 01: PLLP = 4 */ +# define RCC_PLLCFG_PLLP_6 (2 << RCC_PLLCFG_PLLP_SHIFT) /* 10: PLLP = 6 */ +# define RCC_PLLCFG_PLLP_8 (3 << RCC_PLLCFG_PLLP_SHIFT) /* 11: PLLP = 8 */ +#define RCC_PLLCFG_PLLSRC (1 << 22) /* Bit 22: Main PLL(PLL) and audio PLL (PLLI2S) + * entry clock source */ +# define RCC_PLLCFG_PLLSRC_HSI (0) +# define RCC_PLLCFG_PLLSRC_HSE RCC_PLLCFG_PLLSRC +#define RCC_PLLCFG_PLLQ_SHIFT (24) /* Bits 24-27: Main PLL (PLL) divider + * (USB OTG FS, SDIO and RNG clocks) */ +#define RCC_PLLCFG_PLLQ_MASK (15 << RCC_PLLCFG_PLLQ_SHIFT) +# define RCC_PLLCFG_PLLQ(n) ((n) << RCC_PLLCFG_PLLQ_SHIFT) /* n=2..15 */ + +#define RCC_PLLCFG_RESET (0x24003010) /* PLLCFG reset value */ + +/* Clock configuration register */ + +#define RCC_CFGR_SW_SHIFT (0) /* Bits 0-1: System clock Switch */ +#define RCC_CFGR_SW_MASK (3 << RCC_CFGR_SW_SHIFT) +# define RCC_CFGR_SW_HSI (0 << RCC_CFGR_SW_SHIFT) /* 00: HSI selected as system clock */ +# define RCC_CFGR_SW_HSE (1 << RCC_CFGR_SW_SHIFT) /* 01: HSE selected as system clock */ +# define RCC_CFGR_SW_PLL (2 << RCC_CFGR_SW_SHIFT) /* 10: PLL selected as system clock */ +#define RCC_CFGR_SWS_SHIFT (2) /* Bits 2-3: System Clock Switch Status */ +#define RCC_CFGR_SWS_MASK (3 << RCC_CFGR_SWS_SHIFT) +# define RCC_CFGR_SWS_HSI (0 << RCC_CFGR_SWS_SHIFT) /* 00: HSI oscillator used as system clock */ +# define RCC_CFGR_SWS_HSE (1 << RCC_CFGR_SWS_SHIFT) /* 01: HSE oscillator used as system clock */ +# define RCC_CFGR_SWS_PLL (2 << RCC_CFGR_SWS_SHIFT) /* 10: PLL used as system clock */ +#define RCC_CFGR_HPRE_SHIFT (4) /* Bits 4-7: AHB prescaler */ +#define RCC_CFGR_HPRE_MASK (0x0f << RCC_CFGR_HPRE_SHIFT) +# define RCC_CFGR_HPRE_SYSCLK (0 << RCC_CFGR_HPRE_SHIFT) /* 0xxx: SYSCLK not divided */ +# define RCC_CFGR_HPRE_SYSCLKd2 (8 << RCC_CFGR_HPRE_SHIFT) /* 1000: SYSCLK divided by 2 */ +# define RCC_CFGR_HPRE_SYSCLKd4 (9 << RCC_CFGR_HPRE_SHIFT) /* 1001: SYSCLK divided by 4 */ +# define RCC_CFGR_HPRE_SYSCLKd8 (10 << RCC_CFGR_HPRE_SHIFT) /* 1010: SYSCLK divided by 8 */ +# define RCC_CFGR_HPRE_SYSCLKd16 (11 << RCC_CFGR_HPRE_SHIFT) /* 1011: SYSCLK divided by 16 */ +# define RCC_CFGR_HPRE_SYSCLKd64 (12 << RCC_CFGR_HPRE_SHIFT) /* 1100: SYSCLK divided by 64 */ +# define RCC_CFGR_HPRE_SYSCLKd128 (13 << RCC_CFGR_HPRE_SHIFT) /* 1101: SYSCLK divided by 128 */ +# define RCC_CFGR_HPRE_SYSCLKd256 (14 << RCC_CFGR_HPRE_SHIFT) /* 1110: SYSCLK divided by 256 */ +# define RCC_CFGR_HPRE_SYSCLKd512 (15 << RCC_CFGR_HPRE_SHIFT) /* 1111: SYSCLK divided by 512 */ +#define RCC_CFGR_PPRE1_SHIFT (10) /* Bits 10-12: APB Low speed prescaler (APB1) */ +#define RCC_CFGR_PPRE1_MASK (7 << RCC_CFGR_PPRE1_SHIFT) +# define RCC_CFGR_PPRE1_HCLK (0 << RCC_CFGR_PPRE1_SHIFT) /* 0xx: HCLK not divided */ +# define RCC_CFGR_PPRE1_HCLKd2 (4 << RCC_CFGR_PPRE1_SHIFT) /* 100: HCLK divided by 2 */ +# define RCC_CFGR_PPRE1_HCLKd4 (5 << RCC_CFGR_PPRE1_SHIFT) /* 101: HCLK divided by 4 */ +# define RCC_CFGR_PPRE1_HCLKd8 (6 << RCC_CFGR_PPRE1_SHIFT) /* 110: HCLK divided by 8 */ +# define RCC_CFGR_PPRE1_HCLKd16 (7 << RCC_CFGR_PPRE1_SHIFT) /* 111: HCLK divided by 16 */ +#define RCC_CFGR_PPRE2_SHIFT (13) /* Bits 13-15: APB High speed prescaler (APB2) */ +#define RCC_CFGR_PPRE2_MASK (7 << RCC_CFGR_PPRE2_SHIFT) +# define RCC_CFGR_PPRE2_HCLK (0 << RCC_CFGR_PPRE2_SHIFT) /* 0xx: HCLK not divided */ +# define RCC_CFGR_PPRE2_HCLKd2 (4 << RCC_CFGR_PPRE2_SHIFT) /* 100: HCLK divided by 2 */ +# define RCC_CFGR_PPRE2_HCLKd4 (5 << RCC_CFGR_PPRE2_SHIFT) /* 101: HCLK divided by 4 */ +# define RCC_CFGR_PPRE2_HCLKd8 (6 << RCC_CFGR_PPRE2_SHIFT) /* 110: HCLK divided by 8 */ +# define RCC_CFGR_PPRE2_HCLKd16 (7 << RCC_CFGR_PPRE2_SHIFT) /* 111: HCLK divided by 16 */ +#define RCC_CFGR_RTCPRE_SHIFT (16) /* Bits 16-20: APB High speed prescaler (APB2) */ +#define RCC_CFGR_RTCPRE_MASK (31 << RCC_CFGR_RTCPRE) +# define RCC_CFGR_RTCPRE(n) ((n) << RCC_CFGR_RTCPRE) /* HSE/n, n=1..31 */ +#define RCC_CFGR_MCO1_SHIFT (21) /* Bits 21-22: Microcontroller Clock Output */ +#define RCC_CFGR_MCO1_MASK (3 << RCC_CFGR_MCO1_SHIFT) +# define RCC_CFGR_MCO1_HSI (0 << RCC_CFGR_MCO1_SHIFT) /* 00: HSI clock selected */ +# define RCC_CFGR_MCO1_LSE (1 << RCC_CFGR_MCO1_SHIFT) /* 01: LSE oscillator selected */ +# define RCC_CFGR_MCO1_HSE (2 << RCC_CFGR_MCO1_SHIFT) /* 10: HSE oscillator clock selected */ +# define RCC_CFGR_MCO1_PLL (3 << RCC_CFGR_MCO1_SHIFT) /* 11: PLL clock selected */ +#define TCC_CFGR_I2SSRC (1 << 23) /* Bit 23: I2S clock selection */ +#define RCC_CFGR_MCO1PRE_SHIFT (24) /* Bits 24-26: MCO1 prescaler */ +#define RCC_CFGR_MCO1PRE_MASK (7 << RCC_CFGR_MCO1PRE_SHIFT) +# define RCC_CFGR_MCO1PRE_NONE (0 << RCC_CFGR_MCO1PRE_SHIFT) /* 0xx: no division */ +# define RCC_CFGR_MCO1PRE_DIV2 (4 << RCC_CFGR_MCO1PRE_SHIFT) /* 100: division by 2 */ +# define RCC_CFGR_MCO1PRE_DIV3 (5 << RCC_CFGR_MCO1PRE_SHIFT) /* 101: division by 3 */ +# define RCC_CFGR_MCO1PRE_DIV4 (6 << RCC_CFGR_MCO1PRE_SHIFT) /* 110: division by 4 */ +# define RCC_CFGR_MCO1PRE_DIV5 (7 << RCC_CFGR_MCO1PRE_SHIFT) /* 111: division by 5 */ +#define RCC_CFGR_MCO2PRE_SHIFT (27) /* Bits 27-29: MCO2 prescaler */ +#define RCC_CFGR_MCO2PRE_MASK (7 << RCC_CFGR_MCO2PRE_SHIFT) +# define RCC_CFGR_MCO2PRE_NONE (0 << RCC_CFGR_MCO2PRE_SHIFT) /* 0xx: no division */ +# define RCC_CFGR_MCO2PRE_DIV2 (4 << RCC_CFGR_MCO2PRE_SHIFT) /* 100: division by 2 */ +# define RCC_CFGR_MCO2PRE_DIV3 (5 << RCC_CFGR_MCO2PRE_SHIFT) /* 101: division by 3 */ +# define RCC_CFGR_MCO2PRE_DIV4 (6 << RCC_CFGR_MCO2PRE_SHIFT) /* 110: division by 4 */ +# define RCC_CFGR_MCO2PRE_DIV5 (7 << RCC_CFGR_MCO2PRE_SHIFT) /* 111: division by 5 */ +#define RCC_CFGR_MCO2_SHIFT (30) /* Bits 30-31: Microcontroller clock output 2 */ +#define RCC_CFGR_MCO2_MASK (3 << RCC_CFGR_MCO2_SHIFT) +# define RCC_CFGR_MCO2_SYSCLK (0 << RCC_CFGR_MCO2_SHIFT) /* 00: System clock (SYSCLK) selected */ +# define RCC_CFGR_MCO2_PLLI2S (1 << RCC_CFGR_MCO2_SHIFT) /* 01: PLLI2S clock selected */ +# define RCC_CFGR_MCO2_HSE (2 << RCC_CFGR_MCO2_SHIFT) /* 10: HSE oscillator clock selected */ +# define RCC_CFGR_MCO2_PLL (3 << RCC_CFGR_MCO2_SHIFT) /* 11: PLL clock selected */ + +/* Clock interrupt register */ + +#define RCC_CIR_LSIRDYF (1 << 0) /* Bit 0: LSI Ready Interrupt flag */ +#define RCC_CIR_LSERDYF (1 << 1) /* Bit 1: LSE Ready Interrupt flag */ +#define RCC_CIR_HSIRDYF (1 << 2) /* Bit 2: HSI Ready Interrupt flag */ +#define RCC_CIR_HSERDYF (1 << 3) /* Bit 3: HSE Ready Interrupt flag */ +#define RCC_CIR_PLLRDYF (1 << 4) /* Bit 4: PLL Ready Interrupt flag */ +#define RCC_CIR_PLLI2SRDYF (1 << 5) /* Bit 5: PLLI2S Ready Interrupt flag */ +#define RCC_CIR_CSSF (1 << 7) /* Bit 7: Clock Security System Interrupt flag */ +#define RCC_CIR_LSIRDYIE (1 << 8) /* Bit 8: LSI Ready Interrupt Enable */ +#define RCC_CIR_LSERDYIE (1 << 9) /* Bit 9: LSE Ready Interrupt Enable */ +#define RCC_CIR_HSIRDYIE (1 << 10) /* Bit 10: HSI Ready Interrupt Enable */ +#define RCC_CIR_HSERDYIE (1 << 11) /* Bit 11: HSE Ready Interrupt Enable */ +#define RCC_CIR_PLLRDYIE (1 << 12) /* Bit 12: PLL Ready Interrupt Enable */ +#define RCC_CIR_PLLI2SRDYIE (1 << 13) /* Bit 13: PLLI2S Ready Interrupt enable */ +#define RCC_CIR_LSIRDYC (1 << 16) /* Bit 16: LSI Ready Interrupt Clear */ +#define RCC_CIR_LSERDYC (1 << 17) /* Bit 17: LSE Ready Interrupt Clear */ +#define RCC_CIR_HSIRDYC (1 << 18) /* Bit 18: HSI Ready Interrupt Clear */ +#define RCC_CIR_HSERDYC (1 << 19) /* Bit 19: HSE Ready Interrupt Clear */ +#define RCC_CIR_PLLRDYC (1 << 20) /* Bit 20: PLL Ready Interrupt Clear */ +#define RCC_CIR_PLLI2SRDYC (1 << 21) /* Bit 21: PLLI2S Ready Interrupt clear */ +#define RCC_CIR_CSSC (1 << 23) /* Bit 23: Clock Security System Interrupt Clear */ + +/* AHB1 peripheral reset register */ + +#define RCC_AHB1RSTR_GPIOARST (1 << 0) /* Bit 0: IO port A reset */ +#define RCC_AHB1RSTR_GPIOBRST (1 << 1) /* Bit 1: IO port B reset */ +#define RCC_AHB1RSTR_GPIOCRST (1 << 2) /* Bit 2: IO port C reset */ +#define RCC_AHB1RSTR_GPIODRST (1 << 3) /* Bit 3: IO port D reset */ +#define RCC_AHB1RSTR_GPIOERST (1 << 4) /* Bit 4: IO port E reset */ +#define RCC_AHB1RSTR_GPIOFRST (1 << 5) /* Bit 5: IO port F reset */ +#define RCC_AHB1RSTR_GPIOGRST (1 << 6) /* Bit 6: IO port G reset */ +#define RCC_AHB1RSTR_GPIOHRST (1 << 7) /* Bit 7: IO port H reset */ +#define RCC_AHB1RSTR_CRCRST (1 << 12) /* Bit 12 IO port I reset */ +#define RCC_AHB1RSTR_DMA1RST (1 << 21) /* Bit 21: DMA1 reset */ +#define RCC_AHB1RSTR_DMA2RST (1 << 22) /* Bit 22: DMA2 reset */ +#define RCC_AHB1RSTR_ETHMACRST (1 << 25) /* Bit 25: Ethernet MAC reset */ +#define RCC_AHB1RSTR_OTGHSRST (1 << 29) /* Bit 29: USB OTG HS module reset */ + +/* AHB2 peripheral reset register */ + +#define RCC_AHB2RSTR_DCMIRST (1 << 0) /* Bit 0: Camera interface reset */ +#define RCC_AHB2RSTR_CRYPRST (1 << 4) /* Bit 4: Cryptographic module reset */ +#define RCC_AHB2RSTR_HASHRST (1 << 5) /* Bit 5: Hash module reset */ +#define RCC_AHB2RSTR_RNGRST (1 << 6) /* Bit 6: Random number generator module reset */ +#define RCC_AHB2RSTR_OTGFSRST (1 << 7) /* Bit 7: USB OTG FS module reset */ + +/* AHB3 peripheral reset register */ + +#define RCC_AHB3RSTR_FSMCRST (1 << 0) /* Bit 0: Flexible static memory controller module reset */ + +/* APB1 Peripheral reset register */ + +#define RCC_APB1RSTR_TIM2RST (1 << 0) /* Bit 0: TIM2 reset */ +#define RCC_APB1RSTR_TIM3RST (1 << 1) /* Bit 1: TIM3 reset */ +#define RCC_APB1RSTR_TIM4RST (1 << 2) /* Bit 2: TIM4 reset */ +#define RCC_APB1RSTR_TIM5RST (1 << 3) /* Bit 3: TIM5 reset */ +#define RCC_APB1RSTR_TIM6RST (1 << 4) /* Bit 4: TIM6 reset */ +#define RCC_APB1RSTR_TIM7RST (1 << 5) /* Bit 5: TIM7 reset */ +#define RCC_APB1RSTR_TIM12RST (1 << 6) /* Bit 6: TIM12 reset */ +#define RCC_APB1RSTR_TIM13RST (1 << 7) /* Bit 7: TIM13 reset */ +#define RCC_APB1RSTR_TIM14RST (1 << 8) /* Bit 8: TIM14 reset */ +#define RCC_APB1RSTR_WWDGRST (1 << 11) /* Bit 11: Window watchdog reset */ +#define RCC_APB1RSTR_SPI2RST (1 << 14) /* Bit 14: SPI 2 reset */ +#define RCC_APB1RSTR_SPI3RST (1 << 15) /* Bit 15: SPI 3 reset */ +#define RCC_APB1RSTR_USART2RST (1 << 17) /* Bit 17: USART 2 reset */ +#define RCC_APB1RSTR_USART3RST (1 << 18) /* Bit 18: USART 3 reset */ +#define RCC_APB1RSTR_UART4RST (1 << 19) /* Bit 19: USART 4 reset */ +#define RCC_APB1RSTR_UART5RST (1 << 20) /* Bit 20: USART 5 reset */ +#define RCC_APB1RSTR_I2C1RST (1 << 21) /* Bit 21: I2C 1 reset */ +#define RCC_APB1RSTR_I2C2RST (1 << 22) /* Bit 22: I2C 2 reset */ +#define RCC_APB1RSTR_I2C3RST (1 << 23) /* Bit 23: I2C3 reset */ +#define RCC_APB1RSTR_CAN1RST (1 << 25) /* Bit 25: CAN1 reset */ +#define RCC_APB1RSTR_CAN2RST (1 << 26) /* Bit 26: CAN2 reset */ +#define RCC_APB1RSTR_PWRRST (1 << 28) /* Bit 28: Power interface reset */ +#define RCC_APB1RSTR_DACRST (1 << 29) /* Bit 29: DAC reset */ + +/* APB2 Peripheral reset register */ + +#define RCC_APB2RSTR_TIM1RST (1 << 0) /* Bit 0: TIM1 reset */ +#define RCC_APB2RSTR_TIM8RST (1 << 1) /* Bit 1: TIM8 reset */ +#define RCC_APB2RSTR_USART1RST (1 << 4) /* Bit 4: USART1 reset */ +#define RCC_APB2RSTR_USART6RST (1 << 5) /* Bit 5: USART6 reset */ +#define RCC_APB2RSTR_ADCRST (1 << 8) /* Bit 8: ADC interface reset (common to all ADCs) */ +#define RCC_APB2RSTR_SDIORST (1 << 11) /* Bit 11: SDIO reset */ +#define RCC_APB2RSTR_SPI1RST (1 << 12) /* Bit 12: SPI 1 reset */ +#define RCC_APB2RSTR_SYSCFGRST (1 << 14) /* Bit 14: System configuration controller reset */ +#define RCC_APB2RSTR_TIM9RST (1 << 16) /* Bit 16: TIM9 reset */ +#define RCC_APB2RSTR_TIM10RST (1 << 17) /* Bit 17: TIM10 reset */ +#define RCC_APB2RSTR_TIM11RST (1 << 18) /* Bit 18: TIM11 reset */ + +/* AHB1 Peripheral Clock enable register */ + +#define RCC_AHB1ENR_GPIOEN(n) (1 << (n)) +#define RCC_AHB1ENR_GPIOAEN (1 << 0) /* Bit 0: IO port A clock enable */ +#define RCC_AHB1ENR_GPIOBEN (1 << 1) /* Bit 1: IO port B clock enable */ +#define RCC_AHB1ENR_GPIOCEN (1 << 2) /* Bit 2: IO port C clock enable */ +#define RCC_AHB1ENR_GPIODEN (1 << 3) /* Bit 3: IO port D clock enable */ +#define RCC_AHB1ENR_GPIOEEN (1 << 4) /* Bit 4: IO port E clock enable */ +#define RCC_AHB1ENR_GPIOFEN (1 << 5) /* Bit 5: IO port F clock enable */ +#define RCC_AHB1ENR_GPIOGEN (1 << 6) /* Bit 6: IO port G clock enable */ +#define RCC_AHB1ENR_GPIOHEN (1 << 7) /* Bit 7: IO port H clock enable */ +#define RCC_AHB1ENR_GPIOIEN (1 << 8) /* Bit 8: IO port I clock enable */ +#define RCC_AHB1ENR_CRCEN (1 << 12) /* Bit 12: CRC clock enable */ +#define RCC_AHB1ENR_BKPSRAMEN (1 << 18) /* Bit 18: Backup SRAM interface clock enable */ +#define RCC_AHB1ENR_CCMDATARAMEN (1 << 20) /* Bit 20: CCM data RAM clock enable */ +#define RCC_AHB1ENR_DMA1EN (1 << 21) /* Bit 21: DMA1 clock enable */ +#define RCC_AHB1ENR_DMA2EN (1 << 22) /* Bit 22: DMA2 clock enable */ +#define RCC_AHB1ENR_ETHMACEN (1 << 25) /* Bit 25: Ethernet MAC clock enable */ +#define RCC_AHB1ENR_ETHMACTXEN (1 << 26) /* Bit 26: Ethernet Transmission clock enable */ +#define RCC_AHB1ENR_ETHMACRXEN (1 << 27) /* Bit 27: Ethernet Reception clock enable */ +#define RCC_AHB1ENR_ETHMACPTPEN (1 << 28) /* Bit 28: Ethernet PTP clock enable */ +#define RCC_AHB1ENR_OTGHSEN (1 << 29) /* Bit 29: USB OTG HS clock enable */ +#define RCC_AHB1ENR_OTGHSULPIEN (1 << 30) /* Bit 30: USB OTG HSULPI clock enable */ + +/* AHB2 Peripheral Clock enable register */ + +#define RCC_AHB2ENR_DCMIEN (1 << 0) /* Bit 0: Camera interface enable */ +#define RCC_AHB2ENR_CRYPEN (1 << 4) /* Bit 4: Cryptographic modules clock enable */ +#define RCC_AHB2ENR_HASHEN (1 << 5) /* Bit 5: Hash modules clock enable */ +#define RCC_AHB2ENR_RNGEN (1 << 6) /* Bit 6: Random number generator clock enable */ +#define RCC_AHB2ENR_OTGFSEN (1 << 7) /* Bit 7: USB OTG FS clock enable */ + +/* AHB3 Peripheral Clock enable register */ + +#define RCC_AHB3ENR_FSMCEN (1 << 0) /* Bit 0: Flexible static memory controller module clock enable */ + +/* APB1 Peripheral Clock enable register */ + +#define RCC_APB1ENR_TIM2EN (1 << 0) /* Bit 0: TIM2 clock enable */ +#define RCC_APB1ENR_TIM3EN (1 << 1) /* Bit 1: TIM3 clock enable */ +#define RCC_APB1ENR_TIM4EN (1 << 2) /* Bit 2: TIM4 clock enable */ +#define RCC_APB1ENR_TIM5EN (1 << 3) /* Bit 3: TIM5 clock enable */ +#define RCC_APB1ENR_TIM6EN (1 << 4) /* Bit 4: TIM6 clock enable */ +#define RCC_APB1ENR_TIM7EN (1 << 5) /* Bit 5: TIM7 clock enable */ +#define RCC_APB1ENR_TIM12EN (1 << 6) /* Bit 6: TIM12 clock enable */ +#define RCC_APB1ENR_TIM13EN (1 << 7) /* Bit 7: TIM13 clock enable */ +#define RCC_APB1ENR_TIM14EN (1 << 8) /* Bit 8: TIM14 clock enable */ +#define RCC_APB1ENR_WWDGEN (1 << 11) /* Bit 11: Window watchdog clock enable */ +#define RCC_APB1ENR_SPI2EN (1 << 14) /* Bit 14: SPI2 clock enable */ +#define RCC_APB1ENR_SPI3EN (1 << 15) /* Bit 15: SPI3 clock enable */ +#define RCC_APB1ENR_USART2EN (1 << 17) /* Bit 17: USART 2 clock enable */ +#define RCC_APB1ENR_USART3EN (1 << 18) /* Bit 18: USART3 clock enable */ +#define RCC_APB1ENR_UART4EN (1 << 19) /* Bit 19: UART4 clock enable */ +#define RCC_APB1ENR_UART5EN (1 << 20) /* Bit 20: UART5 clock enable */ +#define RCC_APB1ENR_I2C1EN (1 << 21) /* Bit 21: I2C1 clock enable */ +#define RCC_APB1ENR_I2C2EN (1 << 22) /* Bit 22: I2C2 clock enable */ +#define RCC_APB1ENR_I2C3EN (1 << 23) /* Bit 23: I2C3 clock enable */ +#define RCC_APB1ENR_CAN1EN (1 << 25) /* Bit 25: CAN 1 clock enable */ +#define RCC_APB1ENR_CAN2EN (1 << 26) /* Bit 26: CAN 2 clock enable */ +#define RCC_APB1ENR_PWREN (1 << 28) /* Bit 28: Power interface clock enable */ +#define RCC_APB1ENR_DACEN (1 << 29) /* Bit 29: DAC interface clock enable */ + +/* APB2 Peripheral Clock enable register */ + +#define RCC_APB2ENR_TIM1EN (1 << 0) /* Bit 0: TIM1 clock enable */ +#define RCC_APB2ENR_TIM8EN (1 << 1) /* Bit 1: TIM8 clock enable */ +#define RCC_APB2ENR_USART1EN (1 << 4) /* Bit 4: USART1 clock enable */ +#define RCC_APB2ENR_USART6EN (1 << 5) /* Bit 5: USART6 clock enable */ +#define RCC_APB2ENR_ADC1EN (1 << 8) /* Bit 8: ADC1 clock enable */ +#define RCC_APB2ENR_ADC2EN (1 << 9) /* Bit 9: ADC2 clock enable */ +#define RCC_APB2ENR_ADC3EN (1 << 10) /* Bit 10: ADC3 clock enable */ +#define RCC_APB2ENR_SDIOEN (1 << 11) /* Bit 11: SDIO clock enable */ +#define RCC_APB2ENR_SPI1EN (1 << 12) /* Bit 12: SPI1 clock enable */ +#define RCC_APB2ENR_SYSCFGEN (1 << 14) /* Bit 14: System configuration controller clock enable */ +#define RCC_APB2ENR_TIM9EN (1 << 16) /* Bit 16: TIM9 clock enable */ +#define RCC_APB2ENR_TIM10EN (1 << 17) /* Bit 17: TIM10 clock enable */ +#define RCC_APB2ENR_TIM11EN (1 << 18) /* Bit 18: TIM11 clock enable */ + +/* RCC AHB1 low power modeperipheral clock enable register */ + +#define RCC_AHB1LPENR_GPIOLPEN(n) (1 << (n)) +#define RCC_AHB1LPENR_GPIOALPEN (1 << 0) /* Bit 0: IO port A clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOBLPEN (1 << 1) /* Bit 1: IO port B clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOCLPEN (1 << 2) /* Bit 2: IO port C clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIODLPEN (1 << 3) /* Bit 3: IO port D clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOELPEN (1 << 4) /* Bit 4: IO port E clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOFLPEN (1 << 5) /* Bit 5: IO port F clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOGLPEN (1 << 6) /* Bit 6: IO port G clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOHLPEN (1 << 7) /* Bit 7: IO port H clock enable during Sleep mode */ +#define RCC_AHB1LPENR_GPIOILPEN (1 << 8) /* Bit 8: IO port I clock enable during Sleep mode */ +#define RCC_AHB1LPENR_CRCLPEN (1 << 12) /* Bit 12: CRC clock enable during Sleep mode */ +#define RCC_AHB1LPENR_FLITFLPEN (1 << 15) /* Bit 15: Flash interface clock enable during Sleep mode */ +#define RCC_AHB1LPENR_SRAM1LPEN (1 << 16) /* Bit 16: SRAM 1 interface clock enable during Sleep mode */ +#define RCC_AHB1LPENR_SRAM2LPEN (1 << 17) /* Bit 17: SRAM 2 interface clock enable during Sleep mode */ +#define RCC_AHB1LPENR_BKPSRAMLPEN (1 << 18) /* Bit 18: Backup SRAM interface clock enable during Sleep mode */ +#define RCC_AHB1LPENR_CCMDATARAMLPEN (1 << 20) /* Bit 20: CCM data RAM clock enable during Sleep mode */ +#define RCC_AHB1LPENR_DMA1LPEN (1 << 21) /* Bit 21: DMA1 clock enable during Sleep mode */ +#define RCC_AHB1LPENR_DMA2LPEN (1 << 22) /* Bit 22: DMA2 clock enable during Sleep mode */ +#define RCC_AHB1LPENR_ETHMACLPEN (1 << 25) /* Bit 25: Ethernet MAC clock enable during Sleep mode */ +#define RCC_AHB1LPENR_ETHMACTXLPEN (1 << 26) /* Bit 26: Ethernet Transmission clock enable during Sleep mode */ +#define RCC_AHB1LPENR_ETHMACRXLPEN (1 << 27) /* Bit 27: Ethernet Reception clock enable during Sleep mode */ +#define RCC_AHB1LPENR_ETHMACPTPLPEN (1 << 28) /* Bit 28: Ethernet PTP clock enable during Sleep mode */ +#define RCC_AHB1LPENR_OTGHSLPEN (1 << 29) /* Bit 29: USB OTG HS clock enable during Sleep mode */ +#define RCC_AHB1LPENR_OTGHSULPILPEN (1 << 30) /* Bit 30: USB OTG HSULPI clock enable during Sleep mode */ + +/* RCC AHB2 low power modeperipheral clock enable register */ + +#define RCC_AHB2LPENR_DCMILPEN (1 << 0) /* Bit 0: Camera interface enable during Sleep mode */ +#define RCC_AHB2LPENR_CRYPLPEN (1 << 4) /* Bit 4: Cryptographic modules clock enable during Sleep mode */ +#define RCC_AHB2LPENR_HASHLPEN (1 << 5) /* Bit 5: Hash modules clock enable during Sleep mode */ +#define RCC_AHB2LPENR_RNGLPEN (1 << 6) /* Bit 6: Random number generator clock enable during Sleep mode */ +#define RCC_AHB2LPENR_OTGFLPSEN (1 << 7) /* Bit 7: USB OTG FS clock enable during Sleep mode */ + +/* RCC AHB3 low power modeperipheral clock enable register */ + +#define RCC_AHB3LPENR_FSMLPEN (1 << 0) /* Bit 0: Flexible static memory controller module clock + * enable during Sleep mode */ + +/* RCC APB1 low power modeperipheral clock enable register */ + +#define RCC_APB1LPENR_TIM2LPEN (1 << 0) /* Bit 0: TIM2 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM3LPEN (1 << 1) /* Bit 1: TIM3 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM4LPEN (1 << 2) /* Bit 2: TIM4 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM5LPEN (1 << 3) /* Bit 3: TIM5 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM6LPEN (1 << 4) /* Bit 4: TIM6 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM7LPEN (1 << 5) /* Bit 5: TIM7 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM12LPEN (1 << 6) /* Bit 6: TIM12 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM13LPEN (1 << 7) /* Bit 7: TIM13 clock enable during Sleep mode */ +#define RCC_APB1LPENR_TIM14LPEN (1 << 8) /* Bit 8: TIM14 clock enable during Sleep mode */ +#define RCC_APB1LPENR_WWDGLPEN (1 << 11) /* Bit 11: Window watchdog clock enable during Sleep mode */ +#define RCC_APB1LPENR_SPI2LPEN (1 << 14) /* Bit 14: SPI2 clock enable during Sleep mode */ +#define RCC_APB1LPENR_SPI3LPEN (1 << 15) /* Bit 15: SPI3 clock enable during Sleep mode */ +#define RCC_APB1LPENR_USART2LPEN (1 << 17) /* Bit 17: USART 2 clock enable during Sleep mode */ +#define RCC_APB1LPENR_USART3LPEN (1 << 18) /* Bit 18: USART3 clock enable during Sleep mode */ +#define RCC_APB1LPENR_UART4LPEN (1 << 19) /* Bit 19: UART4 clock enable during Sleep mode */ +#define RCC_APB1LPENR_UART5LPEN (1 << 20) /* Bit 20: UART5 clock enable during Sleep mode */ +#define RCC_APB1LPENR_I2C1LPEN (1 << 21) /* Bit 21: I2C1 clock enable during Sleep mode */ +#define RCC_APB1LPENR_I2C2LPEN (1 << 22) /* Bit 22: I2C2 clock enable during Sleep mode */ +#define RCC_APB1LPENR_I2C3LPEN (1 << 23) /* Bit 23: I2C3 clock enable during Sleep mode */ +#define RCC_APB1LPENR_CAN1LPEN (1 << 25) /* Bit 25: CAN 1 clock enable during Sleep mode */ +#define RCC_APB1LPENR_CAN2LPEN (1 << 26) /* Bit 26: CAN 2 clock enable during Sleep mode */ +#define RCC_APB1LPENR_PWRLPEN (1 << 28) /* Bit 28: Power interface clock enable during Sleep mode */ +#define RCC_APB1LPENR_DACLPEN (1 << 29) /* Bit 29: DAC interface clock enable during Sleep mode */ + +/* RCC APB2 low power modeperipheral clock enable register */ + +#define RCC_APB2LPENR_TIM1LPEN (1 << 0) /* Bit 0: TIM1 clock enable during Sleep mode */ +#define RCC_APB2LPENR_TIM8LPEN (1 << 1) /* Bit 1: TIM8 clock enable during Sleep mode */ +#define RCC_APB2LPENR_USART1LPEN (1 << 4) /* Bit 4: USART1 clock enable during Sleep mode */ +#define RCC_APB2LPENR_USART6LPEN (1 << 5) /* Bit 5: USART6 clock enable during Sleep mode */ +#define RCC_APB2LPENR_ADC1LPEN (1 << 8) /* Bit 8: ADC1 clock enable during Sleep mode */ +#define RCC_APB2LPENR_ADC2LPEN (1 << 9) /* Bit 9: ADC2 clock enable during Sleep mode */ +#define RCC_APB2LPENR_ADC3LPEN (1 << 10) /* Bit 10: ADC3 clock enable during Sleep mode */ +#define RCC_APB2LPENR_SDIOLPEN (1 << 11) /* Bit 11: SDIO clock enable during Sleep mode */ +#define RCC_APB2LPENR_SPI1LPEN (1 << 12) /* Bit 12: SPI1 clock enable during Sleep mode */ +#define RCC_APB2LPENR_SYSCFGLPEN (1 << 14) /* Bit 14: System configuration controller clock enable during Sleep mode */ +#define RCC_APB2LPENR_TIM9LPEN (1 << 16) /* Bit 16: TIM9 clock enable during Sleep mode */ +#define RCC_APB2LPENR_TIM10LPEN (1 << 17) /* Bit 17: TIM10 clock enable during Sleep mode */ +#define RCC_APB2LPENR_TIM11LPEN (1 << 18) /* Bit 18: TIM11 clock enable during Sleep mode */ + +/* Backup domain control register */ + +#define RCC_BDCR_LSEON (1 << 0) /* Bit 0: External Low Speed oscillator enable */ +#define RCC_BDCR_LSERDY (1 << 1) /* Bit 1: External Low Speed oscillator Ready */ +#define RCC_BDCR_LSEBYP (1 << 2) /* Bit 2: External Low Speed oscillator Bypass */ +#define RCC_BDCR_RTCSEL_SHIFT (8) /* Bits 9:8: RTC clock source selection */ +#define RCC_BDCR_RTCSEL_MASK (3 << RCC_BDCR_RTCSEL_SHIFT) +# define RCC_BDCR_RTCSEL_NOCLK (0 << RCC_BDCR_RTCSEL_SHIFT) /* 00: No clock */ +# define RCC_BDCR_RTCSEL_LSE (1 << RCC_BDCR_RTCSEL_SHIFT) /* 01: LSE oscillator clock used as RTC clock */ +# define RCC_BDCR_RTCSEL_LSI (2 << RCC_BDCR_RTCSEL_SHIFT) /* 10: LSI oscillator clock used as RTC clock */ +# define RCC_BDCR_RTCSEL_HSE (3 << RCC_BDCR_RTCSEL_SHIFT) /* 11: HSE oscillator clock divided by 128 used as RTC clock */ +#define RCC_BDCR_RTCEN (1 << 15) /* Bit 15: RTC clock enable */ +#define RCC_BDCR_BDRST (1 << 16) /* Bit 16: Backup domain software reset */ + +/* Control/status register */ + +#define RCC_CSR_LSION (1 << 0) /* Bit 0: Internal Low Speed oscillator enable */ +#define RCC_CSR_LSIRDY (1 << 1) /* Bit 1: Internal Low Speed oscillator Ready */ +#define RCC_CSR_RMVF (1 << 24) /* Bit 24: Remove reset flag */ +#define RCC_CSR_BORRSTF (1 << 25) /* Bit 25: BOR reset flag */ +#define RCC_CSR_PINRSTF (1 << 26) /* Bit 26: PIN reset flag */ +#define RCC_CSR_PORRSTF (1 << 27) /* Bit 27: POR/PDR reset flag */ +#define RCC_CSR_SFTRSTF (1 << 28) /* Bit 28: Software Reset flag */ +#define RCC_CSR_IWDGRSTF (1 << 29) /* Bit 29: Independent Watchdog reset flag */ +#define RCC_CSR_WWDGRSTF (1 << 30) /* Bit 30: Window watchdog reset flag */ +#define RCC_CSR_LPWRRSTF (1 << 31) /* Bit 31: Low-Power reset flag */ + +/* Spread spectrum clock generation register */ + +#define RCC_SSCGR_MODPER_SHIFT (0) /* Bit 0-12: Modulation period */ +#define RCC_SSCGR_MODPER_MASK (0x1fff << RCC_SSCGR_MODPER_SHIFT) +# define RCC_SSCGR_MODPER(n) ((n) << RCC_SSCGR_MODPER_SHIFT) +#define RCC_SSCGR_INCSTEP_SHIFT (13) /* Bit 13-27: Incrementation step */ +#define RCC_SSCGR_INCSTEP_MASK (0x7fff << RCC_SSCGR_INCSTEP_SHIFT) +# define RCC_SSCGR_INCSTEP(n) ((n) << RCC_SSCGR_INCSTEP_SHIFT) +#define RCC_SSCGR_SPREADSEL (1 << 30) /* Bit 30: Spread Select */ +#define RCC_SSCGR_SSCGEN (1 << 31) /* Bit 31: Spread spectrum modulation enable */ + +/* PLLI2S configuration register */ + +#define RCC_PLLI2SCFGR_PLLI2SN_SHIFT (6) /* Bits 6-14: PLLI2S multiplication factor for VCO */ +#define RCC_PLLI2SCFGR_PLLI2SN_MASK (0x1ff << RCC_PLLI2SCFGR_PLLI2SN_SHIFT) +#define RCC_PLLI2SCFGR_PLLI2SR_SHIFT (28) /* Bits 28-30: PLLI2S division factor for I2S clocks */ +#define RCC_PLLI2SCFGR_PLLI2SR_MASK (7 << RCC_PLLI2SCFGR_PLLI2SR_SHIFT) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_RCC_H */ + diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rtc.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rtc.h new file mode 100644 index 0000000000..fdfa9b3230 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rtc.h @@ -0,0 +1,338 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f40xxx_rtc.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_RTC_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_RTC_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +#define STM32_RTC_TR_OFFSET 0x0000 /* RTC time register */ +#define STM32_RTC_DR_OFFSET 0x0004 /* RTC date register */ +#define STM32_RTC_CR_OFFSET 0x0008 /* RTC control register */ +#define STM32_RTC_ISR_OFFSET 0x000c /* RTC initialization and status register */ +#define STM32_RTC_PRER_OFFSET 0x0010 /* RTC prescaler register */ +#define STM32_RTC_WUTR_OFFSET 0x0014 /* RTC wakeup timer register */ +#define STM32_RTC_CALIBR_OFFSET 0x0018 /* RTC calibration register */ +#define STM32_RTC_ALRMAR_OFFSET 0x001c /* RTC alarm A register */ +#define STM32_RTC_ALRMBR_OFFSET 0x0020 /* RTC alarm B register */ +#define STM32_RTC_WPR_OFFSET 0x0024 /* RTC write protection register */ +#define STM32_RTC_SSR_OFFSET 0x0028 /* RTC sub second register */ +#define STM32_RTC_SHIFTR_OFFSET 0x002c /* RTC shift control register */ +#define STM32_RTC_TSTR_OFFSET 0x0030 /* RTC time stamp time register */ +#define STM32_RTC_TSDR_OFFSET 0x0030 /* RTC time stamp date register */ +#define STM32_RTC_TSSSR_OFFSET 0x0038 /* RTC timestamp sub second register */ +#define STM32_RTC_CALR_OFFSET 0x003c /* RTC calibration register */ +#define STM32_RTC_TAFCR_OFFSET 0x0040 /* RTC tamper and alternate function configuration register */ +#define STM32_RTC_ALRMASSR_OFFSET 0x0044 /* RTC alarm A sub second register */ +#define STM32_RTC_ALRMBSSR_OFFSET 0x0048 /* RTC alarm B sub second register */ + +#define STM32_RTC_BKR_OFFSET(n) (0x0050+((n)<<2)) +#define STM32_RTC_BK0R_OFFSET 0x0050 /* RTC backup register 0 */ +#define STM32_RTC_BK1R_OFFSET 0x0054 /* RTC backup register 1 */ +#define STM32_RTC_BK2R_OFFSET 0x0058 /* RTC backup register 2 */ +#define STM32_RTC_BK3R_OFFSET 0x005c /* RTC backup register 3 */ +#define STM32_RTC_BK4R_OFFSET 0x0060 /* RTC backup register 4 */ +#define STM32_RTC_BK5R_OFFSET 0x0064 /* RTC backup register 5 */ +#define STM32_RTC_BK6R_OFFSET 0x0068 /* RTC backup register 6 */ +#define STM32_RTC_BK7R_OFFSET 0x006c /* RTC backup register 7 */ +#define STM32_RTC_BK8R_OFFSET 0x0070 /* RTC backup register 8 */ +#define STM32_RTC_BK9R_OFFSET 0x0074 /* RTC backup register 9 */ +#define STM32_RTC_BK10R_OFFSET 0x0078 /* RTC backup register 10 */ +#define STM32_RTC_BK11R_OFFSET 0x007c /* RTC backup register 11 */ +#define STM32_RTC_BK12R_OFFSET 0x0080 /* RTC backup register 12 */ +#define STM32_RTC_BK13R_OFFSET 0x0084 /* RTC backup register 13 */ +#define STM32_RTC_BK14R_OFFSET 0x0088 /* RTC backup register 14 */ +#define STM32_RTC_BK15R_OFFSET 0x008c /* RTC backup register 15 */ +#define STM32_RTC_BK16R_OFFSET 0x0090 /* RTC backup register 16 */ +#define STM32_RTC_BK17R_OFFSET 0x0094 /* RTC backup register 17 */ +#define STM32_RTC_BK18R_OFFSET 0x0098 /* RTC backup register 18 */ +#define STM32_RTC_BK19R_OFFSET 0x009c /* RTC backup register 19 */ + +/* Register Addresses ***************************************************************/ + +#define STM32_RTC_TR (STM32_RTC_BASE+STM32_RTC_TR_OFFSET) +#define STM32_RTC_DR (STM32_RTC_BASE+STM32_RTC_DR_OFFSET) +#define STM32_RTC_CR (STM32_RTC_BASE+STM32_RTC_CR_OFFSET) +#define STM32_RTC_ISR (STM32_RTC_BASE+STM32_RTC_ISR_OFFSET) +#define STM32_RTC_PRER (STM32_RTC_BASE+STM32_RTC_PRER_OFFSET) +#define STM32_RTC_WUTR (STM32_RTC_BASE+STM32_RTC_WUTR_OFFSET) +#define STM32_RTC_CALIBR (STM32_RTC_BASE+STM32_RTC_CALIBR_OFFSET) +#define STM32_RTC_ALRMAR (STM32_RTC_BASE+STM32_RTC_ALRMAR_OFFSET) +#define STM32_RTC_ALRMBR (STM32_RTC_BASE+STM32_RTC_ALRMBR_OFFSET) +#define STM32_RTC_WPR (STM32_RTC_BASE+STM32_RTC_WPR_OFFSET) +#define STM32_RTC_SSR (STM32_RTC_BASE+STM32_RTC_SSR_OFFSET) +#define STM32_RTC_SHIFTR (STM32_RTC_BASE+STM32_RTC_SHIFTR_OFFSET) +#define STM32_RTC_TSTR (STM32_RTC_BASE+STM32_RTC_TSTR_OFFSET) +#define STM32_RTC_TSDR (STM32_RTC_BASE+STM32_RTC_TSDR_OFFSET) +#define STM32_RTC_TSSSR (STM32_RTC_BASE+STM32_RTC_TSSSR_OFFSET) +#define STM32_RTC_CALR (STM32_RTC_BASE+STM32_RTC_CALR_OFFSET) +#define STM32_RTC_TAFCR (STM32_RTC_BASE+STM32_RTC_TAFCR_OFFSET) +#define STM32_RTC_ALRMASSR (STM32_RTC_BASE+STM32_RTC_ALRMASSR_OFFSET) +#define STM32_RTC_ALRMBSSR (STM32_RTC_BASE+STM32_RTC_ALRMBSSR_OFFSET) + +#define STM32_RTC_BKR(n) (STM32_RTC_BASE+STM32_RTC_BKR_OFFSET(n)) +#define STM32_RTC_BK0R (STM32_RTC_BASE+STM32_RTC_BK0R_OFFSET) +#define STM32_RTC_BK1R (STM32_RTC_BASE+STM32_RTC_BK1R_OFFSET) +#define STM32_RTC_BK2R (STM32_RTC_BASE+STM32_RTC_BK2R_OFFSET) +#define STM32_RTC_BK3R (STM32_RTC_BASE+STM32_RTC_BK3R_OFFSET) +#define STM32_RTC_BK4R (STM32_RTC_BASE+STM32_RTC_BK4R_OFFSET) +#define STM32_RTC_BK5R (STM32_RTC_BASE+STM32_RTC_BK5R_OFFSET) +#define STM32_RTC_BK6R (STM32_RTC_BASE+STM32_RTC_BK6R_OFFSET) +#define STM32_RTC_BK7R (STM32_RTC_BASE+STM32_RTC_BK7R_OFFSET) +#define STM32_RTC_BK8R (STM32_RTC_BASE+STM32_RTC_BK8R_OFFSET) +#define STM32_RTC_BK9R (STM32_RTC_BASE+STM32_RTC_BK9R_OFFSET) +#define STM32_RTC_BK10R (STM32_RTC_BASE+STM32_RTC_BK10R_OFFSET) +#define STM32_RTC_BK11R (STM32_RTC_BASE+STM32_RTC_BK11R_OFFSET) +#define STM32_RTC_BK12R (STM32_RTC_BASE+STM32_RTC_BK12R_OFFSET) +#define STM32_RTC_BK13R (STM32_RTC_BASE+STM32_RTC_BK13R_OFFSET) +#define STM32_RTC_BK14R (STM32_RTC_BASE+STM32_RTC_BK14R_OFFSET) +#define STM32_RTC_BK15R (STM32_RTC_BASE+STM32_RTC_BK15R_OFFSET) +#define STM32_RTC_BK16R (STM32_RTC_BASE+STM32_RTC_BK16R_OFFSET) +#define STM32_RTC_BK17R (STM32_RTC_BASE+STM32_RTC_BK17R_OFFSET) +#define STM32_RTC_BK18R (STM32_RTC_BASE+STM32_RTC_BK18R_OFFSET) +#define STM32_RTC_BK19R (STM32_RTC_BASE+STM32_RTC_BK19R_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +/* RTC time register */ + +#define RTC_TR_SU_SHIFT (0) /* Bits 0-3: Second units in BCD format */ +#define RTC_TR_SU_MASK (15 << RTC_TR_SU_SHIFT) +#define RTC_TR_ST_SHIFT (4) /* Bits 4-6: Second tens in BCD format */ +#define RTC_TR_ST_MASK (7 << RTC_TR_ST_SHIFT) +#define RTC_TR_MNU_SHIFT (8) /* Bit 8-11: Minute units in BCD format */ +#define RTC_TR_MNU_MASK (15 << RTC_TR_MNU_SHIFT) +#define RTC_TR_MNT_SHIFT (12) /* Bits 12-14: Minute tens in BCD format */ +#define RTC_TR_MNT_MASK (7 << RTC_TR_MNT_SHIFT) +#define RTC_TR_HU_SHIFT (16) /* Bit 16-19: Hour units in BCD format */ +#define RTC_TR_HU_MASK (15 << RTC_TR_HU_SHIFT) +#define RTC_TR_HT_SHIFT (20) /* Bits 20-21: Hour tens in BCD format */ +#define RTC_TR_HT_MASK (3 << RTC_TR_HT_SHIFT) +#define RTC_TR_PM (1 << 22) /* Bit 22: AM/PM notation */ +#define RTC_TR_RESERVED_BITS (0xff808080) + +/* RTC date register */ + +#define RTC_DR_DU_SHIFT (0) /* Bits 0-3: Date units in BCD format */ +#define RTC_DR_DU_MASK (15 << RTC_DR_DU_SHIFT) +#define RTC_DR_DT_SHIFT (4) /* Bits 4-5: Date tens in BCD format */ +#define RTC_DR_DT_MASK (3 << RTC_DR_DT_SHIFT) +#define RTC_DR_MU_SHIFT (8) /* Bits 8-11: Month units in BCD format */ +#define RTC_DR_MU_MASK (15 << RTC_DR_MU_SHIFT) +#define RTC_DR_MT (1 << 12) /* Bit 12: Month tens in BCD format */ +#define RTC_DR_WDU_SHIFT (13) /* Bits 13-15: Week day units */ +#define RTC_DR_WDU_MASK (7 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_MONDAY (1 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_TUESDAY (2 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_WEDNESDAY (3 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_THURSDAY (4 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_FRIDAY (5 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_SATURDAY (6 << RTC_DR_WDU_SHIFT) +# define RTC_DR_WDU_SUNDAY (7 << RTC_DR_WDU_SHIFT) +#define RTC_DR_YU_SHIFT (16) /* Bits 16-19: Year units in BCD format */ +#define RTC_DR_YU_MASK (15 << RTC_DR_YU_SHIFT) +#define RTC_DR_YT_SHIFT (20) /* Bits 20-23: Year tens in BCD format */ +#define RTC_DR_YT_MASK (15 << RTC_DR_YT_SHIFT) +#define RTC_DR_RESERVED_BITS (0xff0000c0) + +/* RTC control register */ + +#define RTC_CR_WUCKSEL_SHIFT (0) /* Bits 0-2: Wakeup clock selection */ +#define RTC_CR_WUCKSEL_MASK (7 << RTC_CR_WUCKSEL_SHIFT) +# define RTC_CR_WUCKSEL_RTCDIV16 (0 << RTC_CR_WUCKSEL_SHIFT) /* 000: RTC/16 clock is selected */ +# define RTC_CR_WUCKSEL_RTCDIV8 (1 << RTC_CR_WUCKSEL_SHIFT) /* 001: RTC/8 clock is selected */ +# define RTC_CR_WUCKSEL_RTCDIV4 (2 << RTC_CR_WUCKSEL_SHIFT) /* 010: RTC/4 clock is selected */ +# define RTC_CR_WUCKSEL_RTCDIV2 (3 << RTC_CR_WUCKSEL_SHIFT) /* 011: RTC/2 clock is selected */ +# define RTC_CR_WUCKSEL_CKSPRE (4 << RTC_CR_WUCKSEL_SHIFT) /* 10x: ck_spre clock is selected */ +# define RTC_CR_WUCKSEL_CKSPREADD (6 << RTC_CR_WUCKSEL_SHIFT) /* 11x: ck_spr clock and 216 added WUT counter */ +#define RTC_CR_TSEDGE (1 << 3) /* Bit 3: Timestamp event active edge */ +#define RTC_CR_REFCKON (1 << 4) /* Bit 4: Reference clock detection enable (50 or 60 Hz) */ +#define RTC_CR_BYPSHAD (1 << 5) /* Bit 5: Bypass the shadow registers */ +#define RTC_CR_FMT (1 << 6) /* Bit 6: Hour format */ +#define RTC_CR_DCE (1 << 7) /* Bit 7: Coarse digital calibration enable */ +#define RTC_CR_ALRAE (1 << 8) /* Bit 8: Alarm A enable */ +#define RTC_CR_ALRBE (1 << 9) /* Bit 9: Alarm B enable */ +#define RTC_CR_WUTE (1 << 10) /* Bit 10: Wakeup timer enable */ +#define RTC_CR_TSE (1 << 11) /* Bit 11: Time stamp enable */ +#define RTC_CR_ALRAIE (1 << 12) /* Bit 12: Alarm A interrupt enable */ +#define RTC_CR_ALRBIE (1 << 13) /* Bit 13: Alarm B interrupt enable */ +#define RTC_CR_WUTIE (1 << 14) /* Bit 14: Wakeup timer interrupt enable */ +#define RTC_CR_TSIE (1 << 15) /* Bit 15: Timestamp interrupt enable */ +#define RTC_CR_ADD1H (1 << 16) /* Bit 16: Add 1 hour (summer time change) */ +#define RTC_CR_SUB1H (1 << 17) /* Bit 17: Subtract 1 hour (winter time change) */ +#define RTC_CR_BKP (1 << 18) /* Bit 18: Backup */ +#define RTC_CR_COSEL (1 << 19) /* Bit 19 : Calibration output selection */ +#define RTC_CR_POL (1 << 20) /* Bit 20: Output polarity */ +#define RTC_CR_OSEL_SHIFT (21) /* Bits 21-22: Output selection */ +#define RTC_CR_OSEL_MASK (3 << RTC_CR_OSEL_SHIFT) +# define RTC_CR_OSEL_DISABLED (0 << RTC_CR_OSEL_SHIFT) /* 00: Output disabled */ +# define RTC_CR_OSEL_ALRMA (1 << RTC_CR_OSEL_SHIFT) /* 01: Alarm A output enabled */ +# define RTC_CR_OSEL_ALRMB (2 << RTC_CR_OSEL_SHIFT) /* 10: Alarm B output enabled */ +# define RTC_CR_OSEL_WUT (3 << RTC_CR_OSEL_SHIFT) /* 11: Wakeup output enabled */ +#define RTC_CR_COE (1 << 23) /* Bit 23: Calibration output enable */ + +/* RTC initialization and status register */ + +#define RTC_ISR_ALRAWF (1 << 0) /* Bit 0: Alarm A write flag */ +#define RTC_ISR_ALRBWF (1 << 1) /* Bit 1: Alarm B write flag */ +#define RTC_ISR_WUTWF (1 << 2) /* Bit 2: Wakeup timer write flag */ +#define RTC_ISR_SHPF (1 << 3) /* Bit 3: Shift operation pending */ +#define RTC_ISR_INITS (1 << 4) /* Bit 4: Initialization status flag */ +#define RTC_ISR_RSF (1 << 5) /* Bit 5: Registers synchronization flag */ +#define RTC_ISR_INITF (1 << 6) /* Bit 6: Initialization flag */ +#define RTC_ISR_INIT (1 << 7) /* Bit 7: Initialization mode */ +#define RTC_ISR_ALRAF (1 << 8) /* Bit 8: Alarm A flag */ +#define RTC_ISR_ALRBF (1 << 9) /* Bit 9: Alarm B flag */ +#define RTC_ISR_WUTF (1 << 10) /* Bit 10: Wakeup timer flag */ +#define RTC_ISR_TSF (1 << 11) /* Bit 11: Timestamp flag */ +#define RTC_ISR_TSOVF (1 << 12) /* Bit 12: Timestamp overflow flag */ +#define RTC_ISR_TAMP1F (1 << 13) /* Bit 13: Tamper detection flag */ +#define RTC_ISR_TAMP2F (1 << 14) /* Bit 14: TAMPER2 detection flag */ +#define RTC_ISR_RECALPF (1 << 16) /* Bit 16: Recalibration pending Flag */ +#define RTC_ISR_ALLFLAGS (0x00017fff) + +/* RTC prescaler register */ + +#define RTC_PRER_PREDIV_S_SHIFT (0) /* Bits 0-14: Synchronous prescaler factor */ +#define RTC_PRER_PREDIV_S_MASK (0x7fff << RTC_PRER_PREDIV_S_SHIFT) +#define RTC_PRER_PREDIV_A_SHIFT (16) /* Bits 16-22: Asynchronous prescaler factor */ +#define RTC_PRER_PREDIV_A_MASK (0x7f << RTC_PRER_PREDIV_A_SHIFT) + +/* RTC wakeup timer register */ + +#define RTC_WUTR_MASK (0xffff) /* Bits 15:0 Wakeup auto-reload value bits */ + +/* RTC calibration register */ + +#define RTC_CALIBR_DCS (1 << 7) /* Bit 7 Digital calibration sign */ +#define RTC_CALIBR_DC_SHIFT (0) /* Bits 4:0 0-4: Digital calibration */ +#define RTC_CALIBR_DC_MASK (31 << RTC_CALIBR_DC_SHIFT) +# define RTC_CALIBR_DC(n) (((n) >> 2) << RTC_CALIBR_DC_SHIFT) /* n= 0, 4, 8, ... 126 */ + +/* RTC alarm A/B registers */ + +#define RTC_ALRMR_SU_SHIFT (0) /* Bits 0-3: Second units in BCD format. */ +#define RTC_ALRMR_SU_MASK (15 << RTC_ALRMR_SU_SHIFT) +#define RTC_ALRMR_ST_SHIFT (4) /* Bits 4-6: Second tens in BCD format. */ +#define RTC_ALRMR_ST_MASK (7 << RTC_ALRMR_ST_SHIFT) +#define RTC_ALRMR_MSK1 (1 << 7) /* Bit 7 : Alarm A seconds mask */ +#define RTC_ALRMR_MNU_SHIFT (8) /* Bits 8-11: Minute units in BCD format. */ +#define RTC_ALRMR_MNU_MASK (15 << RTC_ALRMR_MNU_SHIFT) +#define RTC_ALRMR_MNT_SHIFT (12) /* Bits 12-14: Minute tens in BCD format. */ +#define RTC_ALRMR_MNT_MASK (7 << RTC_ALRMR_MNT_SHIFT) +#define RTC_ALRMR_MSK2 (1 << 15) /* Bit 15 : Alarm A minutes mask */ +#define RTC_ALRMR_HU_SHIFT (16) /* Bits 16-19: Hour units in BCD format. */ +#define RTC_ALRMR_HU_MASK (15 << RTC_ALRMR_HU_SHIFT) +#define RTC_ALRMR_HT_SHIFT (20) /* Bits 20-21: Hour tens in BCD format. */ +#define RTC_ALRMR_HT_MASK (3 << RTC_ALRMR_HT_SHIFT) +#define RTC_ALRMR_PM (1 << 22) /* Bit 22 : AM/PM notation */ +#define RTC_ALRMR_MSK3 (1 << 23) /* Bit 23 : Alarm A hours mask */ +#define RTC_ALRMR_DU_SHIFT (24) /* Bits 24-27: Date units or day in BCD format. */ +#define RTC_ALRMR_DU_MASK (15 << RTC_ALRMR_DU_SHIFT) +#define RTC_ALRMR_DT_SHIFT (28) /* Bits 28-29: Date tens in BCD format. */ +#define RTC_ALRMR_DT_MASK (3 << RTC_ALRMR_DT_SHIFT) +#define RTC_ALRMR_WDSEL (1 << 30) /* Bit 30: Week day selection */ +#define RTC_ALRMR_MSK4 (1 << 31) /* Bit 31: Alarm A date mask */ + +/* RTC write protection register */ + +#define RTC_WPR_MASK (0xff) /* Bits 0-7: Write protection key */ + +/* RTC sub second register */ + +#define RTC_SSR_MASK (0xffff) /* Bits 0-15: Sub second value */ + +/* RTC shift control register */ + +#define RTC_SHIFTR_SUBFS_SHIFT (0) /* Bits 0-14: Subtract a fraction of a second */ +#define RTC_SHIFTR_SUBFS_MASK (0x7ffff << RTC_SHIFTR_SUBFS_SHIFT) +#define RTC_SHIFTR_ADD1S (1 << 31) /* Bit 31: Add one second */ + +/* RTC time stamp time register */ + +#define RTC_TSTR_SU_SHIFT (0) /* Bits 0-3: Second units in BCD format. */ +#define RTC_TSTR_SU_MASK (15 << RTC_TSTR_SU_SHIFT) +#define RTC_TSTR_ST_SHIFT (4) /* Bits 4-6: Second tens in BCD format. */ +#define RTC_TSTR_ST_MASK (7 << RTC_TSTR_ST_SHIFT) +#define RTC_TSTR_MNU_SHIFT (8) /* Bits 8-11: Minute units in BCD format. */ +#define RTC_TSTR_MNU_MASK (15 << RTC_TSTR_MNU_SHIFT) +#define RTC_TSTR_MNT_SHIFT (12) /* Bits 12-14: Minute tens in BCD format. */ +#define RTC_TSTR_MNT_MASK (7 << RTC_TSTR_MNT_SHIFT) +#define RTC_TSTR_HU_SHIFT (16) /* Bits 16-19: Hour units in BCD format. */ +#define RTC_TSTR_HU_MASK (15 << RTC_TSTR_HU_SHIFT) +#define RTC_TSTR_HT_SHIFT (20) /* Bits 20-21: Hour tens in BCD format. */ +#define RTC_TSTR_HT_MASK (3 << RTC_TSTR_HT_SHIFT) +#define RTC_TSTR_PM (1 << 22) /* Bit 22: AM/PM notation */ + +/* RTC time stamp date register */ + +#define RTC_TSDR_DU_SHIFT (0) /* Bit 0-3: Date units in BCD format */ +#define RTC_TSDR_DU_MASK (15 << RTC_TSDR_DU_SHIFT) */ +#define RTC_TSDR_DT_SHIFT (4) /* Bits 4-5: Date tens in BCD format */ +#define RTC_TSDR_DT_MASK (3 << RTC_TSDR_DT_SHIFT) +#define RTC_TSDR_MU_SHIFT (8) /* Bits 8-11: Month units in BCD format */ +#define RTC_TSDR_MU_MASK (xx << RTC_TSDR_MU_SHIFT) +#define RTC_TSDR_MT (1 << 12) /* Bit 12: Month tens in BCD format */ +#define RTC_TSDR_WDU_SHIFT (13) /* Bits 13-15: Week day units */ +#define RTC_TSDR_WDU_MASK (7 << RTC_TSDR_WDU_SHIFT) + +/* RTC timestamp sub second register */ + +#define RTC_TSSSR_MASK (0xffff) /* Bits 0-15: Sub second value */ + +/* RTC calibration register */ + +#define RTC_CALR_ + +/* RTC tamper and alternate function configuration register */ + +#define RTC_TAFCR_CALM_SHIFT (0) /* Bits 0-8: Calibration minus */ +#define RTC_TAFCR_CALM_MASK (0x1ff << RTC_TAFCR_CALM_SHIFT) +#define RTC_TAFCR_CALW16 (1 << 13) /* Bit 13: Use a 16-second calibration cycle period */ +#define RTC_TAFCR_CALW8 (1 << 14) /* Bit 14: Use an 8-second calibration cycle period */ +#define RTC_TAFCR_CALP (1 << 15) /* Bit 15: Increase frequency of RTC by 488.5 ppm */ + +/* RTC alarm A/B sub second register */ + +#define RTC_ALRMSSR_SS_SHIFT (0) /* Bits 0-15: Sub second value */ +#define RTC_ALRMSSR_SS_MASK (0xffff << RTC_ALRMSSR_SS_SHIFT) +#define RTC_ALRMSSR_MASKSS_SHIFT (0) /* Bits 24-27: Mask the most-significant bits starting at this bit */ +#define RTC_ALRMSSR_MASKSS_MASK (0xffff << RTC_ALRMSSR_SS_SHIFT) + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_RTC_H */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_vectors.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_vectors.h new file mode 100644 index 0000000000..8db1bd19eb --- /dev/null +++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_vectors.h @@ -0,0 +1,142 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32f40xxx_vectors.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Pre-processor definitions + ************************************************************************************/ + +/* This file is included by stm32_vectors.S. It provides the macro VECTOR that + * supplies ach STM32F40xxx vector in terms of a (lower-case) ISR label and an + * (upper-case) IRQ number as defined in arch/arm/include/stm32/stm32f40xxx_irq.h. + * stm32_vectors.S will defined the VECTOR in different ways in order to generate + * the interrupt vectors and handlers in their final form. + */ + +/* If the common ARMv7-M vector handling is used, then all it needs is the following + * definition that provides the number of supported vectors. + */ + +#ifdef CONFIG_ARMV7M_CMNVECTOR + +/* Reserve 82 interrupt table entries for I/O interrupts. */ + +# define ARMV7M_PERIPHERAL_INTERRUPTS 82 + +#else + +VECTOR(stm32_wwdg, STM32_IRQ_WWDG) /* Vector 16+0: Window Watchdog interrupt */ +VECTOR(stm32_pvd, STM32_IRQ_PVD) /* Vector 16+1: PVD through EXTI Line detection interrupt */ +VECTOR(stm32_tamper, STM32_IRQ_TAMPER) /* Vector 16+2: Tamper and time stamp interrupts */ +VECTOR(stm32_rtc_wkup, STM32_IRQ_RTC_WKUP) /* Vector 16+3: RTC global interrupt */ +VECTOR(stm32_flash, STM32_IRQ_FLASH) /* Vector 16+4: Flash global interrupt */ +VECTOR(stm32_rcc, STM32_IRQ_RCC) /* Vector 16+5: RCC global interrupt */ +VECTOR(stm32_exti0, STM32_IRQ_EXTI0) /* Vector 16+6: EXTI Line 0 interrupt */ +VECTOR(stm32_exti1, STM32_IRQ_EXTI1) /* Vector 16+7: EXTI Line 1 interrupt */ +VECTOR(stm32_exti2, STM32_IRQ_EXTI2) /* Vector 16+8: EXTI Line 2 interrupt */ +VECTOR(stm32_exti3, STM32_IRQ_EXTI3) /* Vector 16+9: EXTI Line 3 interrupt */ +VECTOR(stm32_exti4, STM32_IRQ_EXTI4) /* Vector 16+10: EXTI Line 4 interrupt */ +VECTOR(stm32_dma1s0, STM32_IRQ_DMA1S0) /* Vector 16+11: DMA1 Stream 0 global interrupt */ +VECTOR(stm32_dma1s1, STM32_IRQ_DMA1S1) /* Vector 16+12: DMA1 Stream 1 global interrupt */ +VECTOR(stm32_dma1s2, STM32_IRQ_DMA1S2) /* Vector 16+13: DMA1 Stream 2 global interrupt */ +VECTOR(stm32_dma1s3, STM32_IRQ_DMA1S3) /* Vector 16+14: DMA1 Stream 3 global interrupt */ +VECTOR(stm32_dma1s4, STM32_IRQ_DMA1S4) /* Vector 16+15: DMA1 Stream 4 global interrupt */ +VECTOR(stm32_dma1s5, STM32_IRQ_DMA1S5) /* Vector 16+16: DMA1 Stream 5 global interrupt */ +VECTOR(stm32_dma1s6, STM32_IRQ_DMA1S6) /* Vector 16+17: DMA1 Stream 6 global interrupt */ +VECTOR(stm32_adc, STM32_IRQ_ADC) /* Vector 16+18: ADC1, ADC2, and ADC3 global interrupt */ +VECTOR(stm32_can1tx, STM32_IRQ_CAN1TX) /* Vector 16+19: CAN1 TX interrupts */ +VECTOR(stm32_can1rx0, STM32_IRQ_CAN1RX0) /* Vector 16+20: CAN1 RX0 interrupts */ +VECTOR(stm32_can1rx1, STM32_IRQ_CAN1RX1) /* Vector 16+21: CAN1 RX1 interrupt */ +VECTOR(stm32_can1sce, STM32_IRQ_CAN1SCE) /* Vector 16+22: CAN1 SCE interrupt */ +VECTOR(stm32_exti95, STM32_IRQ_EXTI95) /* Vector 16+23: EXTI Line[9:5] interrupts */ +VECTOR(stm32_tim1brk, STM32_IRQ_TIM1BRK) /* Vector 16+24: TIM1 Break interrupt/TIM9 global interrupt */ +VECTOR(stm32_tim1up, STM32_IRQ_TIM1UP) /* Vector 16+25: TIM1 Update interrupt/TIM10 global interrupt */ +VECTOR(stm32_tim1trgcom, STM32_IRQ_TIM1TRGCOM) /* Vector 16+26: TIM1 Trigger and Commutation interrupts/TIM11 global interrupt */ +VECTOR(stm32_tim1cc, STM32_IRQ_TIM1CC) /* Vector 16+27: TIM1 Capture Compare interrupt */ +VECTOR(stm32_tim2, STM32_IRQ_TIM2) /* Vector 16+28: TIM2 global interrupt */ +VECTOR(stm32_tim3, STM32_IRQ_TIM3) /* Vector 16+29: TIM3 global interrupt */ +VECTOR(stm32_tim4, STM32_IRQ_TIM4) /* Vector 16+30: TIM4 global interrupt */ +VECTOR(stm32_i2c1ev, STM32_IRQ_I2C1EV) /* Vector 16+31: I2C1 event interrupt */ +VECTOR(stm32_i2c1er, STM32_IRQ_I2C1ER) /* Vector 16+32: I2C1 error interrupt */ +VECTOR(stm32_i2c2ev, STM32_IRQ_I2C2EV) /* Vector 16+33: I2C2 event interrupt */ +VECTOR(stm32_i2c2er, STM32_IRQ_I2C2ER) /* Vector 16+34: I2C2 error interrupt */ +VECTOR(stm32_spi1, STM32_IRQ_SPI1) /* Vector 16+35: SPI1 global interrupt */ +VECTOR(stm32_spi2, STM32_IRQ_SPI2) /* Vector 16+36: SPI2 global interrupt */ +VECTOR(stm32_usart1, STM32_IRQ_USART1) /* Vector 16+37: USART1 global interrupt */ +VECTOR(stm32_usart2, STM32_IRQ_USART2) /* Vector 16+38: USART2 global interrupt */ +VECTOR(stm32_usart3, STM32_IRQ_USART3) /* Vector 16+39: USART3 global interrupt */ +VECTOR(stm32_exti1510, STM32_IRQ_EXTI1510) /* Vector 16+40: EXTI Line[15:10] interrupts */ +VECTOR(stm32_rtcalrm, STM32_IRQ_RTCALRM) /* Vector 16+41: RTC alarm through EXTI line interrupt */ +VECTOR(stm32_otgfswkup, STM32_IRQ_OTGFSWKUP) /* Vector 16+42: USB On-The-Go FS Wakeup through EXTI line interrupt */ +VECTOR(stm32_tim8brk, STM32_IRQ_TIM8BRK) /* Vector 16+43: TIM8 Break interrupt/TIM12 global interrupt */ +VECTOR(stm32_tim8up, STM32_IRQ_TIM8UP) /* Vector 16+44: TIM8 Update interrup/TIM13 global interrupt */ +VECTOR(stm32_tim8trgcom, STM32_IRQ_TIM8TRGCOM) /* Vector 16+45: TIM8 Trigger and Commutation interrupts/TIM14 global interrupt */ +VECTOR(stm32_tim8cc, STM32_IRQ_TIM8CC) /* Vector 16+46: TIM8 Capture Compare interrupt */ +VECTOR(stm32_dma1s7, STM32_IRQ_DMA1S7) /* Vector 16+47: DMA1 Stream 7 global interrupt */ +VECTOR(stm32_fsmc, STM32_IRQ_FSMC) /* Vector 16+48: FSMC global interrupt */ +VECTOR(stm32_sdio, STM32_IRQ_SDIO) /* Vector 16+49: SDIO global interrupt */ +VECTOR(stm32_tim5, STM32_IRQ_TIM5) /* Vector 16+50: TIM5 global interrupt */ +VECTOR(stm32_spi3, STM32_IRQ_SPI3) /* Vector 16+51: SPI3 global interrupt */ +VECTOR(stm32_uart4, STM32_IRQ_UART4) /* Vector 16+52: UART4 global interrupt */ +VECTOR(stm32_uart5, STM32_IRQ_UART5) /* Vector 16+53: UART5 global interrupt */ +VECTOR(stm32_tim6, STM32_IRQ_TIM6) /* Vector 16+54: TIM6 global interrupt/DAC1 and DAC2 underrun error interrupts */ +VECTOR(stm32_tim7, STM32_IRQ_TIM7) /* Vector 16+55: TIM7 global interrupt */ +VECTOR(stm32_dma2s0, STM32_IRQ_DMA2S0) /* Vector 16+56: DMA2 Stream 0 global interrupt */ +VECTOR(stm32_dma2s1, STM32_IRQ_DMA2S1) /* Vector 16+57: DMA2 Stream 1 global interrupt */ +VECTOR(stm32_dma2s2, STM32_IRQ_DMA2S2) /* Vector 16+58: DMA2 Stream 2 global interrupt */ +VECTOR(stm32_dma2s3, STM32_IRQ_DMA2S3) /* Vector 16+59: DMA2 Stream 3 global interrupt */ +VECTOR(stm32_dma2s4, STM32_IRQ_DMA2S4) /* Vector 16+60: DMA2 Stream 4 global interrupt */ +VECTOR(stm32_eth, STM32_IRQ_ETH) /* Vector 16+61: Ethernet global interrupt */ +VECTOR(stm32_ethwkup, STM32_IRQ_ETHWKUP) /* Vector 16+62: Ethernet Wakeup through EXTI line interrupt */ +VECTOR(stm32_can2tx, STM32_IRQ_CAN2TX) /* Vector 16+63: CAN2 TX interrupts */ +VECTOR(stm32_can2rx0, STM32_IRQ_CAN2RX0) /* Vector 16+64: CAN2 RX0 interrupts */ +VECTOR(stm32_can2rx1, STM32_IRQ_CAN2RX1) /* Vector 16+65: CAN2 RX1 interrupt */ +VECTOR(stm32_can2sce, STM32_IRQ_CAN2SCE) /* Vector 16+66: CAN2 SCE interrupt */ +VECTOR(stm32_otgfs, STM32_IRQ_OTGFS) /* Vector 16+67: USB On The Go FS global interrupt */ +VECTOR(stm32_dma2s5, STM32_IRQ_DMA2S5) /* Vector 16+68: DMA2 Stream 5 global interrupt */ +VECTOR(stm32_dma2s6, STM32_IRQ_DMA2S6) /* Vector 16+69: DMA2 Stream 6 global interrupt */ +VECTOR(stm32_dma2s7, STM32_IRQ_DMA2S7) /* Vector 16+70: DMA2 Stream 7 global interrupt */ +VECTOR(stm32_usart6, STM32_IRQ_USART6) /* Vector 16+71: USART6 global interrupt */ +VECTOR(stm32_i2c3ev, STM32_IRQ_I2C3EV) /* Vector 16+72: I2C3 event interrupt */ +VECTOR(stm32_i2c3er, STM32_IRQ_I2C3ER) /* Vector 16+73: I2C3 error interrupt */ +VECTOR(stm32_otghsep1out, STM32_IRQ_OTGHSEP1OUT) /* Vector 16+74: USB On The Go HS End Point 1 Out global interrupt */ +VECTOR(stm32_otghsep1in, STM32_IRQ_OTGHSEP1IN) /* Vector 16+75: USB On The Go HS End Point 1 In global interrupt */ +VECTOR(stm32_otghswkup, STM32_IRQ_OTGHSWKUP) /* Vector 16+76: USB On The Go HS Wakeup through EXTI interrupt */ +VECTOR(stm32_otghs, STM32_IRQ_OTGHS ) /* Vector 16+77: USB On The Go HS global interrupt */ +VECTOR(stm32_dcmi, STM32_IRQ_DCMI) /* Vector 16+78: DCMI global interrupt */ +VECTOR(stm32_cryp, STM32_IRQ_CRYP) /* Vector 16+79: CRYP crypto global interrupt */ +VECTOR(stm32_hash, STM32_IRQ_HASH) /* Vector 16+80: Hash and Rng global interrupt */ +VECTOR(stm32_fpu, STM32_IRQ_FPU) /* Vector 16+81: FPU global interrupt */ + +#endif /* CONFIG_ARMV7M_CMNVECTOR */ diff --git a/nuttx/arch/arm/src/stm32/stm32.h b/nuttx/arch/arm/src/stm32/stm32.h new file mode 100644 index 0000000000..44a23aece4 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32.h @@ -0,0 +1,103 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32.h + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Authors: Uros Platise + * Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_H +#define __ARCH_ARM_SRC_STM32_STM32_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include +#include + +#include "up_internal.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Additional Configuration *********************************************************/ +/* Custom debug settings used in the STM32 port. These are managed by STM32-specific + * logic and not the common logic in include/debug.h. NOTE: Some of these also + * depend on CONFIG_DEBUG_VERBOSE + */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_DMA +# undef CONFIG_DEBUG_RTC +# undef CONFIG_DEBUG_I2C +# undef CONFIG_DEBUG_CAN +# undef CONFIG_DEBUG_PWM +# undef CONFIG_DEBUG_QENCODER +#endif + +/* NVIC priority levels *************************************************************/ + +#define NVIC_SYSH_PRIORITY_MIN 0xff /* All bits set in minimum priority */ +#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 /* Midpoint is the default */ +#define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ + +/* Peripherals **********************************************************************/ + +#include "chip.h" +#include "stm32_adc.h" +//#include "stm32_bkp.h" +#include "stm32_can.h" +#include "stm32_dbgmcu.h" +#include "stm32_dma.h" +#include "stm32_exti.h" +#include "stm32_flash.h" +#include "stm32_fsmc.h" +#include "stm32_gpio.h" +#include "stm32_i2c.h" +#include "stm32_pwr.h" +#include "stm32_rcc.h" +#include "stm32_rtc.h" +#include "stm32_sdio.h" +#include "stm32_spi.h" +#include "stm32_tim.h" +#include "stm32_uart.h" +#include "stm32_usbdev.h" +#include "stm32_wdg.h" +#include "stm32_lowputc.h" +#include "stm32_eth.h" + +#endif /* __ARCH_ARM_SRC_STM32_STM32_H */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_adc.c b/nuttx/arch/arm/src/stm32/stm32_adc.c new file mode 100644 index 0000000000..a45b732aea --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_adc.c @@ -0,0 +1,1780 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_adc.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Diego Sanchez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "up_internal.h" +#include "up_arch.h" + +#include "chip.h" +#include "stm32_internal.h" +#include "stm32_adc.h" + +#ifdef CONFIG_ADC +#if defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2) || defined(CONFIG_STM32_ADC3) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* ADC interrupts ***********************************************************/ + +#ifdef CONFIG_STM32_STM32F10XX +# define ADC_SR_ALLINTS (ADC_SR_AWD | ADC_SR_EOC | ADC_SR_JEOC) +#else +# define ADC_SR_ALLINTS (ADC_SR_AWD | ADC_SR_EOC | ADC_SR_JEOC | ADC_SR_OVR) +#endif + +#ifdef CONFIG_STM32_STM32F10XX +# define ADC_CR1_ALLINTS (ADC_CR1_AWDIE | ADC_CR1_EOCIE | ADC_CR1_JEOCIE) +#else +# define ADC_CR1_ALLINTS (ADC_CR1_AWDIE | ADC_CR1_EOCIE | ADC_CR1_JEOCIE | ADC_CR1_OVRIE) +#endif + +/* The maximum number of channels that can be sampled. If dma support is + * not enabled, then only a single channel can be sampled. Otherwise, + * data overruns would occur. + */ + +#ifdef CONFIG_ADC_DMA +# define ADC_MAX_SAMPLES 16 +#else +# define ADC_MAX_SAMPLES 1 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure describes the state of one ADC block */ + +struct stm32_dev_s +{ + uint8_t irq; /* Interrupt generated by this ADC block */ + uint8_t nchannels; /* Number of channels */ + uint8_t intf; /* ADC interface number */ + uint8_t current; /* Current ADC channel being converted */ +#ifdef ADC_HAVE_TIMER + uint8_t trigger; /* Timer trigger channel: 0=CC1, 1=CC2, 2=CC3, 3=CC4, 4=TRGO */ +#endif + xcpt_t isr; /* Interrupt handler for this ADC block */ + uint32_t base; /* Base address of registers unique to this ADC block */ +#ifdef ADC_HAVE_TIMER + uint32_t tbase; /* Base address of timer used by this ADC block */ + uint32_t extsel; /* EXTSEL value used by this ADC block */ + uint32_t pclck; /* The PCLK frequency that drives this timer */ + uint32_t freq; /* The desired frequency of conversions */ +#endif + uint8_t chanlist[ADC_MAX_SAMPLES]; +#ifdef CONFIG_ADC_DMA + const unsigned int rxdma_channel; /* DMA channel assigned */ + DMA_HANDLE rxdma; /* currently-open receive DMA stream */ + bool rxenable; /* DMA-based reception en/disable */ + uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */ + int32_t *const rxfifo; /* Receive DMA buffer */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +# ifdef CONFIG_ADC_DMA +static int16_t g_adc3dmarxfifo[ADC_MAX_SAMPLES]; +# endif + + + +/* ADC Register access */ + +static uint32_t adc_getreg(struct stm32_dev_s *priv, int offset); +static void adc_putreg(struct stm32_dev_s *priv, int offset, uint32_t value); +#ifdef ADC_HAVE_TIMER +static uint16_t tim_getreg(struct stm32_dev_s *priv, int offset); +static void tim_putreg(struct stm32_dev_s *priv, int offset, uint16_t value); +static void adc_tim_dumpregs(struct stm32_dev_s *priv, FAR const char *msg); +#endif +static void adc_rccreset(struct stm32_dev_s *priv, bool reset); + +/* ADC Interrupt Handler */ + +static int adc_interrupt(FAR struct adc_dev_s *dev); +#if defined(CONFIG_STM32_STM32F10XX) && (defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2)) +static int adc12_interrupt(int irq, void *context); +#endif +#if defined(CONFIG_STM32_STM32F10XX) && defined (CONFIG_STM32_ADC3) +static int adc3_interrupt(int irq, void *context); +#endif +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +static int adc123_interrupt(int irq, void *context); +#endif + +/* ADC Driver Methods */ + +static void adc_reset(FAR struct adc_dev_s *dev); +static int adc_setup(FAR struct adc_dev_s *dev); +static void adc_shutdown(FAR struct adc_dev_s *dev); +static void adc_rxint(FAR struct adc_dev_s *dev, bool enable); +static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg); +static void adc_enable(FAR struct stm32_dev_s *priv, bool enable); + +#ifdef ADC_HAVE_TIMER +static void adc_timstart(FAR struct stm32_dev_s *priv, bool enable); +static int adc_timinit(FAR struct stm32_dev_s *priv); +#endif + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable); +#endif + +#ifdef CONFIG_ADC_DMA +static int up_dma_setup(struct adc_dev_s *dev); +static void up_dma_shutdown(struct adc_dev_s *dev); +//static int up_dma_receive(struct uart_dev_s *dev, uint32_t *status); +//static void up_dma_rxint(struct uart_dev_s *dev, bool enable); +//static bool up_dma_rxavailable(struct uart_dev_s *dev); +static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, FAR struct adc_dev_s *dev); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* ADC interface operations */ + +static const struct adc_ops_s g_adcops = +{ + .ao_reset = adc_reset, + .ao_setup = adc_setup, + .ao_shutdown = adc_shutdown, + .ao_rxint = adc_rxint, + .ao_ioctl = adc_ioctl, +}; + +/* ADC1 state */ + +#ifdef CONFIG_STM32_ADC1 +static struct stm32_dev_s g_adcpriv1 = +{ +#ifdef CONFIG_STM32_STM32F10XX + .irq = STM32_IRQ_ADC12, + .isr = adc12_interrupt, +#else + .irq = STM32_IRQ_ADC, + .isr = adc123_interrupt, +#endif + .intf = 1, + .base = STM32_ADC1_BASE, +#ifdef ADC1_HAVE_TIMER + .trigger = CONFIG_STM32_ADC1_TIMTRIG, + .tbase = ADC1_TIMER_BASE, + .extsel = ADC1_EXTSEL_VALUE, + .pclck = ADC1_TIMER_PCLK_FREQUENCY, + .freq = CONFIG_STM32_ADC1_SAMPLE_FREQUENCY, +#endif +}; + +static struct adc_dev_s g_adcdev1 = +{ + .ad_ops = &g_adcops, + .ad_priv= &g_adcpriv1, +}; +#endif + +/* ADC2 state */ + +#ifdef CONFIG_STM32_ADC2 +static struct stm32_dev_s g_adcpriv2 = +{ +#ifdef CONFIG_STM32_STM32F10XX + .irq = STM32_IRQ_ADC12, + .isr = adc12_interrupt, +#else + .irq = STM32_IRQ_ADC, + .isr = adc123_interrupt, +#endif + .intf = 2, + .base = STM32_ADC2_BASE, +#ifdef ADC2_HAVE_TIMER + .trigger = CONFIG_STM32_ADC2_TIMTRIG, + .tbase = ADC2_TIMER_BASE, + .extsel = ADC2_EXTSEL_VALUE, + .pclck = ADC2_TIMER_PCLK_FREQUENCY, + .freq = CONFIG_STM32_ADC2_SAMPLE_FREQUENCY, +#endif +}; + +static struct adc_dev_s g_adcdev2 = +{ + .ad_ops = &g_adcops, + .ad_priv= &g_adcpriv2, +}; +#endif + +/* ADC3 state */ + +#ifdef CONFIG_STM32_ADC3 +static struct stm32_dev_s g_adcpriv3 = +{ +#ifdef CONFIG_STM32_STM32F10XX + .irq = STM32_IRQ_ADC3, + .isr = adc3_interrupt, +#else + .irq = STM32_IRQ_ADC, + .isr = adc123_interrupt, +#endif + .intf = 3, + .base = STM32_ADC3_BASE, +#ifdef ADC3_HAVE_TIMER + .trigger = CONFIG_STM32_ADC3_TIMTRIG, + .tbase = ADC3_TIMER_BASE, + .extsel = ADC3_EXTSEL_VALUE, + .pclck = ADC3_TIMER_PCLK_FREQUENCY, + .freq = CONFIG_STM32_ADC3_SAMPLE_FREQUENCY, +#endif +#ifdef CONFIG_ADC_DMA + .rxdma_channel = DMAMAP_ADC3_2, + .rxfifo = g_adc3dmarxfifo, +#endif +}; + +static struct adc_dev_s g_adcdev3 = +{ + .ad_ops = &g_adcops, + .ad_priv= &g_adcpriv3, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: adc_getreg + * + * Description: + * Read the value of an ADC register. + * + * Input Parameters: + * priv - A reference to the ADC block status + * offset - The offset to the register to read + * + * Returned Value: + * + ****************************************************************************/ + +static uint32_t adc_getreg(struct stm32_dev_s *priv, int offset) +{ + return getreg32(priv->base + offset); +} + +/**************************************************************************** + * Name: adc_getreg + * + * Description: + * Read the value of an ADC register. + * + * Input Parameters: + * priv - A reference to the ADC block status + * offset - The offset to the register to read + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_putreg(struct stm32_dev_s *priv, int offset, uint32_t value) +{ + putreg32(value, priv->base + offset); +} + +/**************************************************************************** + * Name: tim_getreg + * + * Description: + * Read the value of an ADC timer register. + * + * Input Parameters: + * priv - A reference to the ADC block status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ****************************************************************************/ + +#ifdef ADC_HAVE_TIMER +static uint16_t tim_getreg(struct stm32_dev_s *priv, int offset) +{ + return getreg16(priv->tbase + offset); +} +#endif + +/**************************************************************************** + * Name: tim_putreg + * + * Description: + * Read the value of an ADC timer register. + * + * Input Parameters: + * priv - A reference to the ADC block status + * offset - The offset to the register to read + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef ADC_HAVE_TIMER +static void tim_putreg(struct stm32_dev_s *priv, int offset, uint16_t value) +{ + putreg16(value, priv->tbase + offset); +} +#endif + +/**************************************************************************** + * Name: adc_tim_dumpregs + * + * Description: + * Dump all timer registers. + * + * Input parameters: + * priv - A reference to the ADC block status + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef ADC_HAVE_TIMER +static void adc_tim_dumpregs(struct stm32_dev_s *priv, FAR const char *msg) +{ +#if defined(CONFIG_DEBUG_ANALOG) && defined(CONFIG_DEBUG_VERBOSE) + avdbg("%s:\n", msg); + avdbg(" CR1: %04x CR2: %04x SMCR: %04x DIER: %04x\n", + tim_getreg(priv, STM32_GTIM_CR1_OFFSET), + tim_getreg(priv, STM32_GTIM_CR2_OFFSET), + tim_getreg(priv, STM32_GTIM_SMCR_OFFSET), + tim_getreg(priv, STM32_GTIM_DIER_OFFSET)); + avdbg(" SR: %04x EGR: 0000 CCMR1: %04x CCMR2: %04x\n", + tim_getreg(priv, STM32_GTIM_SR_OFFSET), + tim_getreg(priv, STM32_GTIM_CCMR1_OFFSET), + tim_getreg(priv, STM32_GTIM_CCMR2_OFFSET)); + avdbg(" CCER: %04x CNT: %04x PSC: %04x ARR: %04x\n", + tim_getreg(priv, STM32_GTIM_CCER_OFFSET), + tim_getreg(priv, STM32_GTIM_CNT_OFFSET), + tim_getreg(priv, STM32_GTIM_PSC_OFFSET), + tim_getreg(priv, STM32_GTIM_ARR_OFFSET)); + avdbg(" CCR1: %04x CCR2: %04x CCR3: %04x CCR4: %04x\n", + tim_getreg(priv, STM32_GTIM_CCR1_OFFSET), + tim_getreg(priv, STM32_GTIM_CCR2_OFFSET), + tim_getreg(priv, STM32_GTIM_CCR3_OFFSET), + tim_getreg(priv, STM32_GTIM_CCR4_OFFSET)); + + if (priv->tbase == STM32_TIM1_BASE || priv->tbase == STM32_TIM8_BASE) + { + avdbg(" RCR: %04x BDTR: %04x DCR: %04x DMAR: %04x\n", + tim_getreg(priv, STM32_ATIM_RCR_OFFSET), + tim_getreg(priv, STM32_ATIM_BDTR_OFFSET), + tim_getreg(priv, STM32_ATIM_DCR_OFFSET), + tim_getreg(priv, STM32_ATIM_DMAR_OFFSET)); + } + else + { + avdbg(" DCR: %04x DMAR: %04x\n", + tim_getreg(priv, STM32_GTIM_DCR_OFFSET), + tim_getreg(priv, STM32_GTIM_DMAR_OFFSET)); + } +#endif +} +#endif + +/**************************************************************************** + * Name: adc_timstart + * + * Description: + * Start (or stop) the timer counter + * + * Input Parameters: + * priv - A reference to the ADC block status + * enable - True: Start conversion + * + * Returned Value: + * + ****************************************************************************/ + + #ifdef ADC_HAVE_TIMER +static void adc_timstart(struct stm32_dev_s *priv, bool enable) +{ + uint16_t regval; + + avdbg("enable: %d\n", enable); + regval = tim_getreg(priv, STM32_GTIM_CR1_OFFSET); + + if (enable) + { + /* Start the counter */ + + regval |= ATIM_CR1_CEN; + } + + else + { + /* Disable the counter */ + + regval &= ~ATIM_CR1_CEN; + } + tim_putreg(priv, STM32_GTIM_CR1_OFFSET, regval); +} +#endif + +/**************************************************************************** + * Name: adc_timinit + * + * Description: + * Initialize the timer that drivers the ADC sampling for this channel using + * the pre-calculated timer divider definitions. + * + * Input Parameters: + * priv - A reference to the ADC block status + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef ADC_HAVE_TIMER +static int adc_timinit(FAR struct stm32_dev_s *priv) +{ + uint32_t prescaler; + uint32_t reload; + uint32_t regval; + uint32_t timclk; + + uint16_t cr1; + uint16_t cr2; + uint16_t ccmr1; + uint16_t ccmr2; + uint16_t ocmode1; + uint16_t ocmode2; + uint16_t ccenable; + uint16_t ccer; + uint16_t egr; + + avdbg("Initializing timers extsel = %d\n", priv->extsel); + + /* If the timer base address is zero, then this ADC was not configured to + * use a timer. + */ + + regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); + +#ifdef CONFIG_STM32_STM32F10XX + if (!priv->tbase) + { + /* Configure the ADC to use the selected timer and timer channel as the trigger + * EXTTRIG: External Trigger Conversion mode for regular channels DISABLE + */ + + regval &= ~ADC_CR2_EXTTRIG; + adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval); + return OK; + } + else + { + regval |= ADC_CR2_EXTTRIG; + } +#endif + + /* EXTSEL selection: These bits select the external event used to trigger + * the start of conversion of a regular group. NOTE: + * + * - The position with with of the EXTSEL field varies from one STM32 MCU + * to another. + * - The width of the EXTSEL field varies from one STM3 MCU to another. + * - The value in priv->extsel is already shifted into the correct bit position. + */ + + regval &= ~ADC_CR2_EXTSEL_MASK; + regval |= priv->extsel; + adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval); + + /* Configure the timer channel to drive the ADC */ + + /* Caculate optimal values for the timer prescaler and for the timer reload + * register. If freq is the desired frequency, then + * + * reload = timclk / freq + * reload = (pclck / prescaler) / freq + * + * There are many solutions to do this, but the best solution will be the + * one that has the largest reload value and the smallest prescaler value. + * That is the solution that should give us the most accuracy in the timer + * control. Subject to: + * + * 0 <= prescaler <= 65536 + * 1 <= reload <= 65535 + * + * So ( prescaler = pclck / 65535 / freq ) would be optimal. + */ + + prescaler = 128;//(priv->pclck / priv->freq + 65534) / 65535; + + /* We need to decrement the prescaler value by one, but only, the value does + * not underflow. + */ + + if (prescaler < 1) + { + adbg("WARNING: Prescaler underflowed.\n"); + prescaler = 1; + } + + /* Check for overflow */ + + else if (prescaler > 65536) + { + adbg("WARNING: Prescaler overflowed.\n"); + prescaler = 65536; + } + + timclk = priv->pclck / prescaler; + + reload = priv->freq;//timclk / priv->freq; + if (reload < 1) + { + adbg("WARNING: Reload value underflowed.\n"); + reload = 1; + } + else if (reload > 65535) + { + adbg("WARNING: Reload value overflowed.\n"); + reload = 65535; + } + + /* Set up the timer CR1 register */ + + cr1 = tim_getreg(priv, STM32_GTIM_CR1_OFFSET); + + /* Disable the timer until we get it configured */ + + adc_timstart(priv, false); + + /* Select the Counter Mode == count up: + * + * ATIM_CR1_EDGE: The counter counts up or down depending on the + * direction bit(DIR). + * ATIM_CR1_DIR: 0: count up, 1: count down + */ + + cr1 &= ~(ATIM_CR1_DIR | ATIM_CR1_CMS_MASK); + cr1 |= ATIM_CR1_EDGE; + + /* Set the clock division to zero for all */ + + cr1 &= ~GTIM_CR1_CKD_MASK; + tim_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1); + + /* Set the reload and prescaler values */ + + tim_putreg(priv, STM32_GTIM_PSC_OFFSET, prescaler-1); + tim_putreg(priv, STM32_GTIM_ARR_OFFSET, reload); + + /* Clear the advanced timers repitition counter in TIM1 */ + + if (priv->tbase == STM32_TIM1_BASE || priv->tbase == STM32_TIM8_BASE) + { + tim_putreg(priv, STM32_ATIM_RCR_OFFSET, 0); + tim_putreg(priv, STM32_ATIM_BDTR_OFFSET, ATIM_BDTR_MOE); /* Check me */ + } + + /* TIMx event generation: Bit 0 UG: Update generation */ + + tim_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG); + + /* Handle channel specific setup */ + + ocmode1 = 0; + ocmode2 = 0; + + switch (priv->trigger) + { + case 0: /* TimerX CC1 event */ + { + ccenable = ATIM_CCER_CC1E; + ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) | + ATIM_CCMR1_OC1PE; + + /* Set the event CC1 */ + + egr = ATIM_EGR_CC1G; + + /* Set the duty cycle by writing to the CCR register for this channel */ + + tim_putreg(priv, STM32_GTIM_CCR1_OFFSET, (uint16_t)(reload >> 1)); + } + break; + + case 1: /* TimerX CC2 event */ + { + ccenable = ATIM_CCER_CC2E; + ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC2M_SHIFT) | + ATIM_CCMR1_OC2PE; + + /* Set the event CC2 */ + + egr = ATIM_EGR_CC2G; + + /* Set the duty cycle by writing to the CCR register for this channel */ + + tim_putreg(priv, STM32_GTIM_CCR2_OFFSET, (uint16_t)(reload >> 1)); + } + break; + + case 2: /* TimerX CC3 event */ + { + ccenable = ATIM_CCER_CC3E; + ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC3S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC3M_SHIFT) | + ATIM_CCMR2_OC3PE; + + /* Set the event CC3 */ + + egr = ATIM_EGR_CC3G; + + /* Set the duty cycle by writing to the CCR register for this channel */ + + tim_putreg(priv, STM32_GTIM_CCR3_OFFSET, (uint16_t)(reload >> 1)); + } + break; + + case 3: /* TimerX CC4 event */ + { + ccenable = ATIM_CCER_CC4E; + ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC4S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC4M_SHIFT) | + ATIM_CCMR2_OC4PE; + + /* Set the event CC4 */ + + egr = ATIM_EGR_CC4G; + + /* Set the duty cycle by writing to the CCR register for this channel */ + + tim_putreg(priv, STM32_GTIM_CCR4_OFFSET, (uint16_t)(reload >> 1)); + } + break; + + case 4: /* TimerX TRGO event */ + { +#warning "TRGO support not yet implemented" + + /* Set the event TRGO */ + + egr = GTIM_EGR_TG; + + /* Set the duty cycle by writing to the CCR register for this channel */ + + tim_putreg(priv, STM32_GTIM_CCR4_OFFSET, (uint16_t)(reload >> 1)); + } + break; + + default: + adbg("No such trigger: %d\n", priv->trigger); + return -EINVAL; + } + + /* Disable the Channel by resetting the CCxE Bit in the CCER register */ + + ccer = tim_getreg(priv, STM32_GTIM_CCER_OFFSET); + ccer &= ~ccenable; + tim_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer); + + /* Fetch the CR2, CCMR1, and CCMR2 register (already have cr1 and ccer) */ + + cr2 = tim_getreg(priv, STM32_GTIM_CR2_OFFSET); + ccmr1 = tim_getreg(priv, STM32_GTIM_CCMR1_OFFSET); + ccmr2 = tim_getreg(priv, STM32_GTIM_CCMR2_OFFSET); + + /* Reset the Output Compare Mode Bits and set the select output compare mode */ + + ccmr1 &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK | ATIM_CCMR1_OC1PE | + ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK | ATIM_CCMR1_OC2PE); + ccmr2 &= ~(ATIM_CCMR2_CC3S_MASK | ATIM_CCMR2_OC3M_MASK | ATIM_CCMR2_OC3PE | + ATIM_CCMR2_CC4S_MASK | ATIM_CCMR2_OC4M_MASK | ATIM_CCMR2_OC4PE); + ccmr1 |= ocmode1; + ccmr2 |= ocmode2; + + /* Reset the output polarity level of all channels (selects high polarity)*/ + + ccer &= ~(ATIM_CCER_CC1P | ATIM_CCER_CC2P | ATIM_CCER_CC3P | ATIM_CCER_CC4P); + + /* Enable the output state of the selected channel (only) */ + + ccer &= ~(ATIM_CCER_CC1E | ATIM_CCER_CC2E | ATIM_CCER_CC3E | ATIM_CCER_CC4E); + ccer |= ccenable; + + if (priv->tbase == STM32_TIM1_BASE || priv->tbase == STM32_TIM8_BASE) + { + /* Reset output N polarity level, output N state, output compre state, + * output compare N idle state. + */ +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE | ATIM_CCER_CC2NP | + ATIM_CCER_CC3NE | ATIM_CCER_CC3NP | ATIM_CCER_CC4NP); +#else + ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE | ATIM_CCER_CC2NP | + ATIM_CCER_CC3NE | ATIM_CCER_CC3NP); +#endif + + /* Reset the output compare and output compare N IDLE State */ + + cr2 &= ~(ATIM_CR2_OIS1 | ATIM_CR2_OIS1N | ATIM_CR2_OIS2 | ATIM_CR2_OIS2N | + ATIM_CR2_OIS3 | ATIM_CR2_OIS3N | ATIM_CR2_OIS4); + } +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + else + { + ccer &= ~(GTIM_CCER_CC1NP | GTIM_CCER_CC2NP | GTIM_CCER_CC3NP | GTIM_CCER_CC4NP); + } +#endif + + /* Save the modified register values */ + + tim_putreg(priv, STM32_GTIM_CR2_OFFSET, cr2); + tim_putreg(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1); + tim_putreg(priv, STM32_GTIM_CCMR2_OFFSET, ccmr2); + tim_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer); + tim_putreg(priv, STM32_GTIM_EGR_OFFSET, egr); + + /* Set the ARR Preload Bit */ + + cr1 = tim_getreg(priv, STM32_GTIM_CR1_OFFSET); + cr1 |= GTIM_CR1_ARPE; + tim_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1); + + /* Enable the timer counter + * All but the CEN bit with the default config in CR1 + */ + + adc_timstart(priv, true); + + adc_tim_dumpregs(priv, "After starting Timers"); + + return OK; +} +#endif + +/**************************************************************************** + * Name: adc_startconv + * + * Description: + * Start (or stop) the ADC conversion process in DMA mode + * + * Input Parameters: + * priv - A reference to the ADC block status + * enable - True: Start conversion + * + * Returned Value: + * + ****************************************************************************/ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +static void adc_startconv(struct stm32_dev_s *priv, bool enable) +{ + uint32_t regval; + + avdbg("enable: %d\n", enable); + + regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); + if (enable) + { + /* Start conversion of regular channles */ + + regval |= ADC_CR2_SWSTART; + } + else + { + /* Disable the conversion of regular channels */ + + regval &= ~ADC_CR2_SWSTART; + } + adc_putreg(priv, STM32_ADC_CR2_OFFSET,regval); +} +#endif + +/**************************************************************************** + * Name: adc_rccreset + * + * Description: + * Deinitializes the ADCx peripheral registers to their default + * reset values. It could set all the ADCs configured. + * + * Input Parameters: + * regaddr - The register to read + * reset - Condition, set or reset + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_rccreset(struct stm32_dev_s *priv, bool reset) +{ + irqstate_t flags; + uint32_t regval; + uint32_t adcbit; + + /* Pick the appropriate bit in the APB2 reset register */ + +#ifdef CONFIG_STM32_STM32F10XX + /* For the STM32 F1, there is an individual bit to reset each ADC. */ + + switch (priv->intf) + { +#ifdef CONFIG_STM32_ADC1 + case 1: + adcbit = RCC_APB2RSTR_ADC1RST; + break; +#endif +#ifdef CONFIG_STM32_ADC2 + case 2: + adcbit = RCC_APB2RSTR_ADC2RST; + break; +#endif +#ifdef CONFIG_STM32_ADC3 + case 3: + adcbit = RCC_APB2RSTR_ADC3RST; + break; +#endif + default: + return; + } + +#else + /* For the STM32 F4, there is one common reset for all ADC block. + * THIS will probably cause some problems! + */ + + adcbit = RCC_APB2RSTR_ADCRST; +#endif + + /* Disable interrupts. This is necessary because the APB2RTSR register + * is used by several different drivers. + */ + + flags = irqsave(); + + /* Set or clear the selected bit in the APB2 reset register */ + + regval = getreg32(STM32_RCC_APB2RSTR); + if (reset) + { + /* Enable ADC reset state */ + + regval |= adcbit; + } + else + { + /* Release ADC from reset state */ + + regval &= ~adcbit; + } + putreg32(regval, STM32_RCC_APB2RSTR); + irqrestore(flags); +} + +/**************************************************************************** + * Name: up_dma_setup + * + * Description: + * + ****************************************************************************/ + +#ifdef CONFIG_ADC_DMA +static int up_dma_setup(FAR struct adc_dev_s *dev) +{ + + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + int result; + uint32_t regval; + +// +// result = up_setup(dev); +// if (result != OK) +// { +// return result; +// } + + /* Acquire the DMA channel. This should always succeed. */ + + priv->rxdma = stm32_dmachannel(priv->rxdma_channel); + + /* Configure for circular DMA reception into the RX fifo */ + + stm32_dmasetup(priv->rxdma, + priv->base + STM32_ADC_DR_OFFSET, + (uint32_t)priv->rxfifo, + 4,//buffersize + DMA_SCR_DIR_P2M | + DMA_SCR_CIRC | + DMA_SCR_MINC | + DMA_SCR_PSIZE_16BITS | + DMA_SCR_MSIZE_16BITS | + DMA_SCR_PBURST_SINGLE | + DMA_SCR_MBURST_SINGLE); + + /* Reset our DMA shadow pointer to match the address just + * programmed above. + */ + + //priv->rxdmanext = 0; + + /* Enable DMA for the ADC */ + + /* Start the DMA channel, and arrange for callbacks at the half and + * full points in the FIFO. This ensures that we have half a FIFO + * worth of time to claim bytes before they are overwritten. + */ + + stm32_dmastart(priv->rxdma, up_dma_rxcallback, (void *)dev, false); + + return OK; +} +#endif +/**************************************************************************** + * Name: up_dma_rxcallback + * + * Description: + + * + ****************************************************************************/ + +#ifdef CONFIG_ADC_DMA +static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, FAR struct adc_dev_s *dev) +{ + //struct up_dev_s *priv = (struct up_dev_s*)arg; + //uint32_t regval; + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + //struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + + //if (priv->rxenable && up_dma_rxavailable(&priv->dev)) + { + /* Give the ADC data to the ADC driver. adc_receive accepts 3 parameters: + * + * 1) The first is the ADC device instance for this ADC block. + * 2) The second is the channel number for the data, and + * 3) The third is the converted data for the channel. + */ + + + adc_receive(dev, 10, (int32_t)g_adc3dmarxfifo[1]); + adc_receive(dev, 11, (int32_t)g_adc3dmarxfifo[2]); + adc_receive(dev, 12, (int32_t)g_adc3dmarxfifo[3]); + adc_receive(dev, 13, (int32_t)g_adc3dmarxfifo[0]); + + + /* Set the channel number of the next channel that will complete conversion */ + + priv->current++; + + if (priv->current >= priv->nchannels) + { + /* Restart the conversion sequence from the beginning */ + + priv->current = 0; + } + + + } +} +#endif + +/**************************************************************************** + * Name: up_dma_shutdown + * + * Description: + * Disable the DMA + * + ****************************************************************************/ + +#ifdef CONFIG_ADC_DMA +static void up_dma_shutdown(struct adc_dev_s *dev) +{ + + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + + + /* Stop the DMA channel */ + + stm32_dmastop(priv->rxdma); + + /* Release the DMA channel */ + + stm32_dmafree(priv->rxdma); + priv->rxdma = NULL; +} +#endif + + +/******************************************************************************* + * Name: adc_enable + * + * Description : Enables or disables the specified ADC peripheral. + * Also, starts a conversion when the ADC is not + * triggered by timers + * + * Input Parameters: + * + * enable - true: enable ADC conversion + * false: disable ADC conversion + * + * Returned Value: + * + *******************************************************************************/ + +static void adc_enable(FAR struct stm32_dev_s *priv, bool enable) +{ + uint32_t regval; + + // avdbg("enable: %d\n", enable); + + regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); + if (enable) + { + regval |= ADC_CR2_ADON; + } + else + { + regval &= ~ADC_CR2_ADON; + } + adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval); +} + +/**************************************************************************** + * Name: adc_reset + * + * Description: + * Reset the ADC device. Called early to initialize the hardware. This + * is called, before adc_setup() and on error conditions. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_reset(FAR struct adc_dev_s *dev) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + irqstate_t flags; + uint32_t regval; + int offset; + int i; + int ret; + + avdbg("intf: ADC%d\n", priv->intf); + flags = irqsave(); + + /* Enable ADC reset state */ + + adc_rccreset(priv, true); + + /* Release ADC from reset state */ + + adc_rccreset(priv, false); + + /* Initialize the ADC data structures */ + + /* Initialize the watchdog high threshold register */ + + adc_putreg(priv, STM32_ADC_HTR_OFFSET, 0x00000fff); + + /* Initialize the watchdog low threshold register */ + + adc_putreg(priv, STM32_ADC_LTR_OFFSET, 0x00000000); + + + /* Initialize the same sample time for each ADC 55.5 cycles + * + * During sample cycles channel selection bits must remain unchanged. + * + * 000: 1.5 cycles + * 001: 7.5 cycles + * 010: 13.5 cycles + * 011: 28.5 cycles + * 100: 41.5 cycles + * 101: 55.5 cycles + * 110: 71.5 cycles + * 111: 239.5 cycles + */ + + adc_putreg(priv, STM32_ADC_SMPR1_OFFSET, 0x00b6db6d); + adc_putreg(priv, STM32_ADC_SMPR2_OFFSET, 0x00b6db6d); + + /* ADC CR1 Configuration */ + + regval = adc_getreg(priv, STM32_ADC_CR1_OFFSET); + + /* Set mode configuration (Independent mode) */ + +#ifdef CONFIG_STM32_STM32F10XX + regval |= ADC_CR1_IND; +#endif + + /* Initialize the Analog watchdog enable */ + + regval |= ADC_CR1_AWDEN; + regval |= (priv->chanlist[0] << ADC_CR1_AWDCH_SHIFT); + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + + /* Set the resolution of the conversion */ + + regval |= ACD_CR1_RES_12BIT; +#endif + + adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval); + + /* ADC CR2 Configuration */ + + regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); + + /* Clear CONT, continuous mode disable */ + + regval &= ~ADC_CR2_CONT; + + /* Set ALIGN (Right = 0) */ + + regval &= ~ADC_CR2_ALIGN; + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + /* External trigger enable for regular channels */ + + regval |= ACD_CR2_EXTEN_RISING; +#endif + + adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval); + + /* Configuration of the channel conversions */ + + regval = adc_getreg(priv, STM32_ADC_SQR3_OFFSET) & ADC_SQR3_RESERVED; + for (i = 0, offset = 0; i < priv->nchannels && i < 6; i++, offset += 5) + { + regval |= (uint32_t)priv->chanlist[i] << offset; + } + adc_putreg(priv, STM32_ADC_SQR3_OFFSET, regval); + + regval = adc_getreg(priv, STM32_ADC_SQR2_OFFSET) & ADC_SQR2_RESERVED; + for (i = 6, offset = 0; i < priv->nchannels && i < 12; i++, offset += 5) + { + regval |= (uint32_t)priv->chanlist[i] << offset; + } + adc_putreg(priv, STM32_ADC_SQR2_OFFSET, regval); + + regval = adc_getreg(priv, STM32_ADC_SQR1_OFFSET) & ADC_SQR1_RESERVED; + for (i = 12, offset = 0; i < priv->nchannels && i < 16; i++, offset += 5) + { + regval |= (uint32_t)priv->chanlist[i] << offset; + } + /* Set the number of conversions */ + + DEBUGASSERT(priv->nchannels <= ADC_MAX_SAMPLES); + + regval |= (((uint32_t)priv->nchannels-1) << ADC_SQR1_L_SHIFT); + adc_putreg(priv, STM32_ADC_SQR1_OFFSET, regval); + + /* ADC CCR configuration */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + regval = getreg32(STM32_ADC_CCR); + regval &= ~(ADC_CCR_MULTI_MASK | ADC_CCR_DELAY_MASK | ADC_CCR_DDS | ADC_CCR_DMA_MASK | + ADC_CCR_ADCPRE_MASK | ADC_CCR_VBATE | ADC_CCR_TSVREFE); + regval |= (ADC_CCR_MULTI_NONE | ADC_CCR_DMA_DISABLED | ADC_CCR_ADCPRE_DIV2); + putreg32(regval, STM32_ADC_CCR); +#endif + + + + /* Set the channel index of the first conversion */ + + priv->current = 0; + + /* Set ADON to wake up the ADC from Power Down state. */ + + adc_enable(priv, true); + +#ifdef ADC_HAVE_TIMER + ret = adc_timinit(priv); + if (ret!=OK) + { + adbg("Error initializing the timers\n"); + } +#else +#ifdef CONFIG_STM32_STM32F10XX + /* Set ADON (Again) to start the conversion. Only if Timers are not + * configured as triggers + */ + + adc_enable(priv, true); +#else +#ifdef CONFIG_ADC_DMA + //nothing +#else + adc_startconv(priv, true); +#endif +#endif /* CONFIG_STM32_STM32F10XX */ +#endif /* ADC_HAVE_TIMER */ + + + irqrestore(flags); + +// avdbg("SR: 0x%08x CR1: 0x%08x CR2: 0x%08x\n", +// adc_getreg(priv, STM32_ADC_SR_OFFSET), +// adc_getreg(priv, STM32_ADC_CR1_OFFSET), +// adc_getreg(priv, STM32_ADC_CR2_OFFSET)); +// avdbg("SQR1: 0x%08x SQR2: 0x%08x SQR3: 0x%08x\n", +// adc_getreg(priv, STM32_ADC_SQR1_OFFSET), +// adc_getreg(priv, STM32_ADC_SQR2_OFFSET), +// adc_getreg(priv, STM32_ADC_SQR3_OFFSET)); +//#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +// avdbg("CCR: 0x%08x\n", +// getreg32(STM32_ADC_CCR)); +//#endif +} + +/**************************************************************************** + * Name: adc_setup + * + * Description: + * Configure the ADC. This method is called the first time that the ADC + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching ADC interrupts. Interrupts + * are all disabled upon return. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static int adc_setup(FAR struct adc_dev_s *dev) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + int ret; + uint32_t regval; + + + /* the adc seems to need a full reset to be enabled correctly */ + adc_reset(dev); + +#ifndef CONFIG_ADC_DMA + /* Attach the ADC interrupt */ + + ret = irq_attach(priv->irq, priv->isr); + if (ret == OK) + { + /* Enable the ADC interrupt */ + + avdbg("Enable the ADC interrupt: irq=%d\n", priv->irq); + up_enable_irq(priv->irq); + } +#endif + +#ifdef CONFIG_ADC_DMA + up_dma_setup(dev); + + +//#ifndef ADC_HAVE_TIMER +// /*disable external trigger*/ +// regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); +// regval |= ACD_CR2_EXTEN_NONE; +// //regval |= ADC_CR1_DISCEN; +// adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval); +//#else +// /*enable external trigger*/ +// regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); +// regval |=ADC_CR2_EXTSEL_T4CC4; +// regval |=ACD_CR2_EXTEN_BOTH; +// //regval |= ADC_CR2_CONT; +// adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval); +//#endif + + + /*enable scan mode*/ + regval = adc_getreg(priv, STM32_ADC_CR1_OFFSET); + regval |= ADC_CR1_SCAN; + //regval |= ADC_CR1_DISCEN; + adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval); + + /* Enable DMA request after last transfer (Single-ADC mode) */ + //ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE); + regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); + regval |= ADC_CR2_DDS; + adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval); + + /* Enable ADC3 DMA */ + // ADC_DMACmd(ADC3, ENABLE); + regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); + regval |= ADC_CR2_DMA; + adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval); +#endif + + +#ifndef ADC_HAVE_TIMER + /*set continuous conversion */ + regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); + regval |= ADC_CR2_CONT; + adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval); +#endif + + /* Enable ADC3 */ + //ADC_Cmd(ADC3, ENABLE); + regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); + regval |= ADC_CR2_ADON; + adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval); + +//// /*start conversion*/ +// regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); +// regval |= ADC_CR2_SWSTART; +// adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval); + + + + + + return ret; +} + +/**************************************************************************** + * Name: adc_shutdown + * + * Description: + * Disable the ADC. This method is called when the ADC device is closed. + * This method reverses the operation the setup method. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_shutdown(FAR struct adc_dev_s *dev) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + +#ifdef CONFIG_ADC_DMA + up_dma_shutdown(dev); +#endif + +#ifdef ADC_HAVE_TIMER + /* stop adc timer */ + adc_timstart(priv, false); +#endif + + /* power down ADC */ + adc_enable(priv, false); + + adc_rxint(priv, false); + + /* Disable ADC interrupts and detach the ADC interrupt handler */ + up_disable_irq(priv->irq); +// irq_detach(priv->irq); + + + + +} + +/**************************************************************************** + * Name: adc_rxint + * + * Description: + * Call to enable or disable RX interrupts. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_rxint(FAR struct adc_dev_s *dev, bool enable) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + uint32_t regval; + + avdbg("intf: %d enable: %d\n", priv->intf, enable); + + regval = adc_getreg(priv, STM32_ADC_CR1_OFFSET); + if (enable) + { + /* Enable the end-of-conversion ADC and analog watchdog interrupts */ + + regval |= ADC_CR1_ALLINTS; + } + else + { + /* Disable all ADC interrupts */ + + regval &= ~ADC_CR1_ALLINTS; + } + adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval); +} + +/**************************************************************************** + * Name: adc_ioctl + * + * Description: + * All ioctl calls will be routed through this method. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg) +{ + return -ENOTTY; +} + +/**************************************************************************** + * Name: adc_interrupt + * + * Description: + * Common ADC interrupt handler. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static int adc_interrupt(FAR struct adc_dev_s *dev) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + uint32_t adcsr; + int32_t value; + + /* Identifies the interruption AWD, OVR or EOC */ + + adcsr = adc_getreg(priv, STM32_ADC_SR_OFFSET); + if ((adcsr & ADC_SR_AWD) != 0) + { + alldbg("WARNING: Analog Watchdog, Value converted out of range!\n"); + } + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + if ((adcsr & ADC_SR_OVR) != 0) + { + alldbg("WARNING: Overrun has ocurred!\n"); + } +#endif + + /* EOC: End of conversion */ + + if ((adcsr & ADC_SR_EOC) != 0) + { + /* Read the converted value and clear EOC bit + * (It is cleared by reading the ADC_DR) + */ + + value = adc_getreg(priv, STM32_ADC_DR_OFFSET); + value &= ADC_DR_DATA_MASK; + + /* Give the ADC data to the ADC driver. adc_receive accepts 3 parameters: + * + * 1) The first is the ADC device instance for this ADC block. + * 2) The second is the channel number for the data, and + * 3) The third is the converted data for the channel. + */ + + adc_receive(dev, priv->chanlist[priv->current], value); + + /* Set the channel number of the next channel that will complete conversion */ + + priv->current++; + + if (priv->current >= priv->nchannels) + { + /* Restart the conversion sequence from the beginning */ + + priv->current = 0; + } + } + + return OK; +} + +/**************************************************************************** + * Name: adc12_interrupt + * + * Description: + * ADC12 interrupt handler for the STM32 F1 family. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +#if defined(CONFIG_STM32_STM32F10XX) && (defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2)) +static int adc12_interrupt(int irq, void *context) +{ + uint32_t regval; + uint32_t pending; + + /* Check for pending ADC1 interrupts */ + +#ifdef CONFIG_STM32_ADC1 + regval = getreg32(STM32_ADC1_SR); + pending = regval & ADC_SR_ALLINTS; + if (pending != 0) + { + adc_interrupt(&g_adcdev1); + regval &= ~pending; + putreg32(regval, STM32_ADC1_SR); + } +#endif + + /* Check for pending ADC2 interrupts */ + +#ifdef CONFIG_STM32_ADC2 + regval = getreg32(STM32_ADC2_SR); + pending = regval & ADC_SR_ALLINTS; + if (pending != 0) + { + adc_interrupt(&g_adcdev2); + regval &= ~pending; + putreg32(regval, STM32_ADC2_SR); + } +#endif + return OK; +} +#endif + +/**************************************************************************** + * Name: adc3_interrupt + * + * Description: + * ADC1/2 interrupt handler for the STM32 F1 family. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +#if defined (CONFIG_STM32_STM32F10XX) && defined (CONFIG_STM32_ADC3) +static int adc3_interrupt(int irq, void *context) +{ + uint32_t regval; + uint32_t pending; + + /* Check for pending ADC3 interrupts */ + + regval = getreg32(STM32_ADC3_SR); + pending = regval & ADC_SR_ALLINTS; + if (pending != 0) + { + adc_interrupt(&g_adcdev3); + regval &= ~pending; + putreg32(regval, STM32_ADC3_SR); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: adc123_interrupt + * + * Description: + * ADC1/2/3 interrupt handler for the STM32 F4 family. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +static int adc123_interrupt(int irq, void *context) +{ + uint32_t regval; + uint32_t pending; + + /* Check for pending ADC1 interrupts */ + +#ifdef CONFIG_STM32_ADC1 + regval = getreg32(STM32_ADC1_SR); + pending = regval & ADC_SR_ALLINTS; + if (pending != 0) + { + adc_interrupt(&g_adcdev1); + regval &= ~pending; + putreg32(regval, STM32_ADC1_SR); + } +#endif + + /* Check for pending ADC2 interrupts */ + +#ifdef CONFIG_STM32_ADC2 + regval = getreg32(STM32_ADC2_SR); + pending = regval & ADC_SR_ALLINTS; + if (pending != 0) + { + adc_interrupt(&g_adcdev2); + regval &= ~pending; + putreg32(regval, STM32_ADC2_SR); + } +#endif + + /* Check for pending ADC3 interrupts */ + +#ifdef CONFIG_STM32_ADC3 + regval = getreg32(STM32_ADC3_SR); + pending = regval & ADC_SR_ALLINTS; + if (pending != 0) + { + adc_interrupt(&g_adcdev3); + regval &= ~pending; + putreg32(regval, STM32_ADC3_SR); + } +#endif + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_adcinitialize + * + * Description: + * Initialize the ADC. + * + * The logic is, save nchannels : # of channels (conversions) in ADC_SQR1_L + * Then, take the chanlist array and store it in the SQR Regs, + * chanlist[0] -> ADC_SQR3_SQ1 + * chanlist[1] -> ADC_SQR3_SQ2 + * ... + * chanlist[15]-> ADC_SQR1_SQ16 + * + * up to + * chanlist[nchannels] + * + * Input Parameters: + * intf - Could be {1,2,3} for ADC1, ADC2, or ADC3 + * chanlist - The list of channels + * nchannels - Number of channels + * + * Returned Value: + * Valid ADC device structure reference on succcess; a NULL on failure + * + ****************************************************************************/ + +struct adc_dev_s *stm32_adcinitialize(int intf, const uint8_t *chanlist, int nchannels) +{ + FAR struct adc_dev_s *dev; + FAR struct stm32_dev_s *priv; + + avdbg("intf: %d nchannels: %d\n", intf, nchannels); + +#ifdef CONFIG_STM32_ADC1 + if (intf == 1) + { + avdbg("ADC1 Selected\n"); + dev = &g_adcdev1; + } + else +#endif +#ifdef CONFIG_STM32_ADC2 + if (intf == 2) + { + avdbg("ADC2 Selected\n"); + dev = &g_adcdev2; + } + else +#endif +#ifdef CONFIG_STM32_ADC3 + if (intf == 3) + { + avdbg("ADC3 Selected\n"); + dev = &g_adcdev3; + } + else +#endif + { + adbg("No ADC interface defined\n"); + return NULL; + } + + /* Configure the selected ADC */ + + priv = dev->ad_priv; + + DEBUGASSERT(nchannels <= ADC_MAX_SAMPLES); + priv->nchannels = nchannels; + + memcpy(priv->chanlist, chanlist, nchannels); + return dev; +} + +#endif /* CONFIG_STM32_ADC || CONFIG_STM32_ADC2 || CONFIG_STM32_ADC3 */ +#endif /* CONFIG_ADC */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_adc.h b/nuttx/arch/arm/src/stm32/stm32_adc.h new file mode 100644 index 0000000000..c25da38305 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_adc.h @@ -0,0 +1,596 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_adc.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_ADC_H +#define __ARCH_ARM_SRC_STM32_STM32_ADC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" +#include "chip/stm32_adc.h" + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* Timer devices may be used for different purposes. One special purpose is to + * control periodic ADC sampling. If CONFIG_STM32_TIMn is defined then + * CONFIG_STM32_TIMn_ADC must also be defined to indicate that timer "n" is intended + * to be used for that purpose. + */ + +/* For the STM32 F1 line, timers 1-4 may be used. For STM32 F4 line, timers 1-5 and + * 8 may be used. + */ + +#ifndef CONFIG_STM32_TIM1 +# undef CONFIG_STM32_TIM1_ADC +# undef CONFIG_STM32_TIM1_ADC1 +# undef CONFIG_STM32_TIM1_ADC2 +# undef CONFIG_STM32_TIM1_ADC3 +#endif +#ifndef CONFIG_STM32_TIM2 +# undef CONFIG_STM32_TIM2_ADC +# undef CONFIG_STM32_TIM2_ADC1 +# undef CONFIG_STM32_TIM2_ADC2 +# undef CONFIG_STM32_TIM2_ADC3 +#endif +#ifndef CONFIG_STM32_TIM3 +# undef CONFIG_STM32_TIM3_ADC +# undef CONFIG_STM32_TIM3_ADC1 +# undef CONFIG_STM32_TIM3_ADC2 +# undef CONFIG_STM32_TIM3_ADC3 +#endif +#ifndef CONFIG_STM32_TIM4 +# undef CONFIG_STM32_TIM4_ADC +# undef CONFIG_STM32_TIM4_ADC1 +# undef CONFIG_STM32_TIM4_ADC2 +# undef CONFIG_STM32_TIM4_ADC3 +#endif + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# ifndef CONFIG_STM32_TIM5 +# undef CONFIG_STM32_TIM5_ADC +# undef CONFIG_STM32_TIM5_ADC1 +# undef CONFIG_STM32_TIM5_ADC2 +# undef CONFIG_STM32_TIM5_ADC3 +# endif +# ifndef CONFIG_STM32_TIM8 +# undef CONFIG_STM32_TIM8_ADC +# undef CONFIG_STM32_TIM8_ADC1 +# undef CONFIG_STM32_TIM8_ADC2 +# undef CONFIG_STM32_TIM8_ADC3 +# endif +#else +# undef CONFIG_STM32_TIM5_ADC +# undef CONFIG_STM32_TIM5_ADC1 +# undef CONFIG_STM32_TIM5_ADC2 +# undef CONFIG_STM32_TIM5_ADC3 +# undef CONFIG_STM32_TIM8_ADC +# undef CONFIG_STM32_TIM8_ADC1 +# undef CONFIG_STM32_TIM8_ADC2 +# undef CONFIG_STM32_TIM8_ADC3 +#endif + +/* Timers 6, 7, and 10-14 are not used with the ADC by any supported family */ + +#undef CONFIG_STM32_TIM6_ADC +#undef CONFIG_STM32_TIM6_ADC1 +#undef CONFIG_STM32_TIM6_ADC2 +#undef CONFIG_STM32_TIM6_ADC3 +#undef CONFIG_STM32_TIM7_ADC +#undef CONFIG_STM32_TIM7_ADC1 +#undef CONFIG_STM32_TIM7_ADC2 +#undef CONFIG_STM32_TIM7_ADC3 +#undef CONFIG_STM32_TIM9_ADC +#undef CONFIG_STM32_TIM9_ADC1 +#undef CONFIG_STM32_TIM9_ADC2 +#undef CONFIG_STM32_TIM9_ADC3 +#undef CONFIG_STM32_TIM10_ADC +#undef CONFIG_STM32_TIM10_ADC1 +#undef CONFIG_STM32_TIM10_ADC2 +#undef CONFIG_STM32_TIM10_ADC3 +#undef CONFIG_STM32_TIM11_ADC +#undef CONFIG_STM32_TIM11_ADC1 +#undef CONFIG_STM32_TIM11_ADC2 +#undef CONFIG_STM32_TIM11_ADC3 +#undef CONFIG_STM32_TIM12_ADC +#undef CONFIG_STM32_TIM12_ADC1 +#undef CONFIG_STM32_TIM12_ADC2 +#undef CONFIG_STM32_TIM12_ADC3 +#undef CONFIG_STM32_TIM13_ADC +#undef CONFIG_STM32_TIM13_ADC1 +#undef CONFIG_STM32_TIM13_ADC2 +#undef CONFIG_STM32_TIM13_ADC3 +#undef CONFIG_STM32_TIM14_ADC +#undef CONFIG_STM32_TIM14_ADC1 +#undef CONFIG_STM32_TIM14_ADC2 +#undef CONFIG_STM32_TIM14_ADC3 + +/* Up to 3 ADC interfaces are supported */ + +#if STM32_NADC < 3 +# undef CONFIG_STM32_ADC3 +#endif + +#if STM32_NADC < 2 +# undef CONFIG_STM32_ADC2 +#endif + +#if STM32_NADC < 1 +# undef CONFIG_STM32_ADC1 +#endif + +#if defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2) || defined(CONFIG_STM32_ADC3) + +/* Timer configuration: If a timer trigger is specified, then get information + * about the timer. + */ + +#if defined(CONFIG_STM32_TIM1_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM1_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN +#elif defined(CONFIG_STM32_TIM2_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM2_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN +#elif defined(CONFIG_STM32_TIM3_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM3_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN +#elif defined(CONFIG_STM32_TIM4_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM4_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN +#elif defined(CONFIG_STM32_TIM5_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM5_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM5_CLKIN +#elif defined(CONFIG_STM32_TIM8_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM8_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN +#else +# undef ADC1_HAVE_TIMER +#endif + +#ifdef ADC1_HAVE_TIMER +# ifndef CONFIG_STM32_ADC1_SAMPLE_FREQUENCY +# error "CONFIG_STM32_ADC1_SAMPLE_FREQUENCY not defined" +# endif +# ifndef CONFIG_STM32_ADC1_TIMTRIG +# error "CONFIG_STM32_ADC1_TIMTRIG not defined" +# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO" +# endif +#endif + +#if defined(CONFIG_STM32_TIM1_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM1_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN +#elif defined(CONFIG_STM32_TIM2_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM2_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN +#elif defined(CONFIG_STM32_TIM3_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM3_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN +#elif defined(CONFIG_STM32_TIM4_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM4_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN +#elif defined(CONFIG_STM32_TIM5_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM5_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM5_CLKIN +#elif defined(CONFIG_STM32_TIM8_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM8_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN +#else +# undef ADC2_HAVE_TIMER +#endif + +#ifdef ADC2_HAVE_TIMER +# ifndef CONFIG_STM32_ADC2_SAMPLE_FREQUENCY +# error "CONFIG_STM32_ADC2_SAMPLE_FREQUENCY not defined" +# endif +# ifndef CONFIG_STM32_ADC2_TIMTRIG +# error "CONFIG_STM32_ADC2_TIMTRIG not defined" +# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO" +# endif +#endif + +#if defined(CONFIG_STM32_TIM1_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM1_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN +#elif defined(CONFIG_STM32_TIM2_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM2_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN +#elif defined(CONFIG_STM32_TIM3_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM3_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN +#elif defined(CONFIG_STM32_TIM4_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM4_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN +#elif defined(CONFIG_STM32_TIM5_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM5_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM5_CLKIN +#elif defined(CONFIG_STM32_TIM8_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM8_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN +#else +# undef ADC3_HAVE_TIMER +#endif + +#ifdef ADC3_HAVE_TIMER +# ifndef CONFIG_STM32_ADC3_SAMPLE_FREQUENCY +# error "CONFIG_STM32_ADC3_SAMPLE_FREQUENCY not defined" +# endif +# ifndef CONFIG_STM32_ADC3_TIMTRIG +# error "CONFIG_STM32_ADC3_TIMTRIG not defined" +# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO" +# endif +#endif + +#if defined(ADC1_HAVE_TIMER) || defined(ADC2_HAVE_TIMER) || defined(ADC3_HAVE_TIMER) +# define ADC_HAVE_TIMER 1 +# if defined(CONFIG_STM32_STM32F10XX) && defined(CONFIG_STM32_FORCEPOWER) +# warning "CONFIG_STM32_FORCEPOWER must be defined to enable the timer(s)" +# endif +#else +# undef ADC_HAVE_TIMER +#endif + +/* NOTE: The following assumes that all possible combinations of timers and + * values are support EXTSEL. That is not so and it varies from one STM32 to another. + * But this (wrong) assumptions keeps the logic as simple as possible. If un + * unsupported combination is used, an error will show up later during compilation + * although it may be difficult to track it back to this simplification. + */ + +#if defined(CONFIG_STM32_TIM1_ADC1) +# if CONFIG_STM32_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC1 +# elif CONFIG_STM32_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC2 +# elif CONFIG_STM32_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC3 +# elif CONFIG_STM32_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC4 +# elif CONFIG_STM32_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T1TRGO +# else +# error "CONFIG_STM32_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM2_ADC1) +# if CONFIG_STM32_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC1 +# elif CONFIG_STM32_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC2 +# elif CONFIG_STM32_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC3 +# elif CONFIG_STM32_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC4 +# elif CONFIG_STM32_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T2TRGO +# else +# error "CONFIG_STM32_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM3_ADC1) +# if CONFIG_STM32_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC1 +# elif CONFIG_STM32_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC2 +# elif CONFIG_STM32_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC3 +# elif CONFIG_STM32_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC4 +# elif CONFIG_STM32_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T3TRGO +# else +# error "CONFIG_STM32_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM4_ADC1) +# if CONFIG_STM32_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC1 +# elif CONFIG_STM32_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC2 +# elif CONFIG_STM32_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC3 +# elif CONFIG_STM32_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC4 +# elif CONFIG_STM32_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T4TRGO +# else +# error "CONFIG_STM32_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM5_ADC1) +# if CONFIG_STM32_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC1 +# elif CONFIG_STM32_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC2 +# elif CONFIG_STM32_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC3 +# elif CONFIG_STM32_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC4 +# elif CONFIG_STM32_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T5TRGO +# else +# error "CONFIG_STM32_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM8_ADC1) +# if CONFIG_STM32_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC1 +# elif CONFIG_STM32_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC2 +# elif CONFIG_STM32_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC3 +# elif CONFIG_STM32_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC4 +# elif CONFIG_STM32_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T8TRGO +# else +# error "CONFIG_STM32_ADC1_TIMTRIG is out of range" +# endif +#endif + +#if defined(CONFIG_STM32_TIM1_ADC2) +# if CONFIG_STM32_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC1 +# elif CONFIG_STM32_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC2 +# elif CONFIG_STM32_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC3 +# elif CONFIG_STM32_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC4 +# elif CONFIG_STM32_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T1TRGO +# else +# error "CONFIG_STM32_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM2_ADC2) +# if CONFIG_STM32_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC1 +# elif CONFIG_STM32_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC2 +# elif CONFIG_STM32_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC3 +# elif CONFIG_STM32_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC4 +# elif CONFIG_STM32_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T2TRGO +# else +# error "CONFIG_STM32_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM3_ADC2) +# if CONFIG_STM32_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC1 +# elif CONFIG_STM32_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC2 +# elif CONFIG_STM32_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC3 +# elif CONFIG_STM32_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC4 +# elif CONFIG_STM32_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T3TRGO +# else +# error "CONFIG_STM32_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM4_ADC2) +# if CONFIG_STM32_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC1 +# elif CONFIG_STM32_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC2 +# elif CONFIG_STM32_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC3 +# elif CONFIG_STM32_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC4 +# elif CONFIG_STM32_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T4TRGO +# else +# error "CONFIG_STM32_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM5_ADC2) +# if CONFIG_STM32_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC1 +# elif CONFIG_STM32_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC2 +# elif CONFIG_STM32_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC3 +# elif CONFIG_STM32_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC4 +# elif CONFIG_STM32_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T5TRGO +# else +# error "CONFIG_STM32_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM8_ADC2) +# if CONFIG_STM32_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC1 +# elif CONFIG_STM32_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC2 +# elif CONFIG_STM32_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC3 +# elif CONFIG_STM32_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC4 +# elif CONFIG_STM32_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T8TRGO +# else +# error "CONFIG_STM32_ADC2_TIMTRIG is out of range" +# endif +#endif + +#if defined(CONFIG_STM32_TIM1_ADC3) +# if CONFIG_STM32_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC1 +# elif CONFIG_STM32_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC2 +# elif CONFIG_STM32_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC3 +# elif CONFIG_STM32_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC4 +# elif CONFIG_STM32_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T1TRGO +# else +# error "CONFIG_STM32_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM2_ADC3) +# if CONFIG_STM32_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC1 +# elif CONFIG_STM32_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC2 +# elif CONFIG_STM32_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC3 +# elif CONFIG_STM32_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC4 +# elif CONFIG_STM32_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T2TRGO +# else +# error "CONFIG_STM32_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM3_ADC3) +# if CONFIG_STM32_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC1 +# elif CONFIG_STM32_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC2 +# elif CONFIG_STM32_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC3 +# elif CONFIG_STM32_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC4 +# elif CONFIG_STM32_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T3TRGO +# else +# error "CONFIG_STM32_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM4_ADC3) +# if CONFIG_STM32_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC1 +# elif CONFIG_STM32_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC2 +# elif CONFIG_STM32_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC3 +# elif CONFIG_STM32_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC4 +# elif CONFIG_STM32_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T4TRGO +# else +# error "CONFIG_STM32_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM5_ADC3) +# if CONFIG_STM32_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC1 +# elif CONFIG_STM32_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC2 +# elif CONFIG_STM32_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC3 +# elif CONFIG_STM32_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC4 +# elif CONFIG_STM32_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T5TRGO +# else +# error "CONFIG_STM32_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32_TIM8_ADC3) +# if CONFIG_STM32_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC1 +# elif CONFIG_STM32_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC2 +# elif CONFIG_STM32_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC3 +# elif CONFIG_STM32_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC4 +# elif CONFIG_STM32_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T8TRGO +# else +# error "CONFIG_STM32_ADC3_TIMTRIG is out of range" +# endif +#endif + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: stm32_adcinitialize + * + * Description: + * Initialize the ADC. + * + * Input Parameters: + * intf - Could be {1,2,3} for ADC1, ADC2, or ADC3 + * chanlist - The list of channels + * nchannels - Number of channels + * + * Returned Value: + * Valid can device structure reference on succcess; a NULL on failure + * + ****************************************************************************/ + +struct adc_dev_s; +EXTERN struct adc_dev_s *stm32_adcinitialize(int intf, const uint8_t *chanlist, + int nchannels); + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* CONFIG_STM32_ADC || CONFIG_STM32_ADC2 || CONFIG_STM32_ADC3 */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_ADC_H */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_allocateheap.c b/nuttx/arch/arm/src/stm32/stm32_allocateheap.c new file mode 100644 index 0000000000..4c186a852b --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_allocateheap.c @@ -0,0 +1,323 @@ +/**************************************************************************** + * arch/arm/src/stm32/up_allocateheap.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include + +#include "chip.h" +#include "up_arch.h" +#include "up_internal.h" + +/**************************************************************************** + * Private Definitions + ****************************************************************************/ +/* Internal SRAM is available in all members of the STM32 family. The + * following definitions must be provided to specify the size and + * location of internal(system) SRAM: + * + * CONFIG_DRAM_END : End address (+1) of SRAM (F1 family only, the + * : F4 family uses the a priori end of SRAM) + * + * The F4 family also contains internal CCM SRAM. This SRAM is different + * because it cannot be used for DMA. So if DMA needed, then the following + * should be defined to exclude CCM SRAM from the heap: + * + * CONFIG_STM32_CCMEXCLUDE : Exclude CCM SRAM from the HEAP + * + * In addition to internal SRAM, SRAM may also be available through the FSMC. + * In order to use FSMC SRAM, the following additional things need to be + * present in the NuttX configuration file: + * + * CONFIG_STM32_FSMC=y : Enables the FSMC + * CONFIG_STM32_FSMC_SRAM=y : Indicates that SRAM is available via the + * FSMC (as opposed to an LCD or FLASH). + * CONFIG_HEAP2_BASE : The base address of the SRAM in the FSMC + * address space + * CONFIG_HEAP2_END : The end (+1) of the SRAM in the FSMC + * address space + * CONFIG_MM_REGIONS : Must be set to a large enough value to + * include the FSMC SRAM (as determined by the rules provided below) + */ + +#ifndef CONFIG_STM32_FSMC +# undef CONFIG_STM32_FSMC_SRAM +#endif + +/* For the STM312F10xxx family, all internal SRAM is in one contiguous block + * starting at g_heapbase and extending through CONFIG_DRAM_END (my apologies for + * the bad naming). In addition, external FSMC SRAM may be available. + */ + +#if defined(CONFIG_STM32_STM32F10XX) + + /* Set the end of system SRAM */ + +# define SRAM1_END CONFIG_DRAM_END + + /* Check if external FSMC SRAM is provided */ + +# if CONFIG_STM32_FSMC_SRAM +# if CONFIG_MM_REGIONS < 2 +# warning "FSMC SRAM not included in the heap" +# undef CONFIG_STM32_FSMC_SRAM +# elif CONFIG_MM_REGIONS > 2 +# error "CONFIG_MM_REGIONS > 2 but I don't know what some of the region(s) are" +# undef CONFIG_MM_REGIONS +# define CONFIG_MM_REGIONS 2 +# endif +# elif CONFIG_MM_REGIONS > 1 +# error "CONFIG_MM_REGIONS > 1 but I don't know what the other region(s) are" +# endif + + /* The STM32 F1 has no CCM SRAM */ + +# undef CONFIG_STM32_CCMEXCLUDE +# define CONFIG_STM32_CCMEXCLUDE 1 + +/* All members of the STM32F20xxx and STM32F40xxx families have 192Kb in three banks: + * + * 1) 112Kb of System SRAM beginning at address 0x2000:0000 + * 2) 16Kb of System SRAM beginning at address 0x2001:c000 + * 3) 64Kb of CCM SRAM beginning at address 0x1000:0000 + * + * As determined by ld.script, g_heapbase lies in the 112Kb memory + * region and that extends to 0x2001:0000. But the first and second memory + * regions are contiguous and treated as one in this logic that extends to + * 0x2002:0000. + * + * As a complication, it appears that CCM SRAM cannot be used for DMA. So, if + * STM32 DMA is enabled, CCM SRAM should probably be excluded from the heap. + * + * In addition, external FSMC SRAM may be available. + */ + +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + + + /* The STM32 F2 has no CCM SRAM */ + +# ifdef CONFIG_STM32_STM32F20XX +# undef CONFIG_STM32_CCMEXCLUDE +# define CONFIG_STM32_CCMEXCLUDE 1 +# endif + + /* Set the end of system SRAM */ + +# define SRAM1_END 0x20020000 + + /* Set the range of CCM SRAM as well (although we may not use it) */ + +# define SRAM2_START 0x10000000 +# define SRAM2_END 0x10010000 + + /* There are 4 possible SRAM configurations: + * + * Configuration 1. System SRAM (only) + * CONFIG_MM_REGIONS == 1 + * CONFIG_STM32_FSMC_SRAM NOT defined + * CONFIG_STM32_CCMEXCLUDE defined + * Configuration 2. System SRAM and CCM SRAM + * CONFIG_MM_REGIONS == 2 + * CONFIG_STM32_FSMC_SRAM NOT defined + * CONFIG_STM32_CCMEXCLUDE NOT defined + * Configuration 3. System SRAM and FSMC SRAM + * CONFIG_MM_REGIONS == 2 + * CONFIG_STM32_FSMC_SRAM defined + * CONFIG_STM32_CCMEXCLUDE defined + * Configuration 4. System SRAM, CCM SRAM, and FSMC SRAM + * CONFIG_MM_REGIONS == 3 + * CONFIG_STM32_FSMC_SRAM defined + * CONFIG_STM32_CCMEXCLUDE NOT defined + * + * Let's make sure that all definitions are consitent before doing + * anything else + */ + +# if defined(CONFIG_STM32_FSMC_SRAM) + + /* Configuration 3 or 4. External SRAM is available. CONFIG_MM_REGIONS + * should be at least 2. + */ + +# if CONFIG_MM_REGIONS < 2 + /* Only one memory region. Force Configuration 1 */ + +# warning "FSMC SRAM (and CCM SRAM) excluded from the heap" +# undef CONFIG_STM32_FSMC_SRAM +# undef CONFIG_STM32_CCMEXCLUDE +# define CONFIG_STM32_CCMEXCLUDE 1 + + /* CONFIG_MM_REGIONS may be 3 if CCM SRAM is included in the head */ + +# elif CONFIG_MM_REGIONS > 2 + + /* More than two memory regions. This is okay if CCM SRAM is not + * disabled. + */ + +# if defined(CONFIG_STM32_CCMEXCLUDE) + + /* Configuration 3: CONFIG_MM_REGIONS should have been 2 */ + +# error "CONFIG_MM_REGIONS > 2 but I don't know what some of the region(s) are" +# undef CONFIG_MM_REGIONS +# define CONFIG_MM_REGIONS 2 +# else + + /* Configuration 4: DMA should be disabled and CONFIG_MM_REGIONS + * should be 3. + */ + +# ifdef CONFIG_STM32_DMA +# warning "CCM SRAM is included in the heap AND DMA is enabled" +# endif +# if CONFIG_MM_REGIONS != 3 +# error "CONFIG_MM_REGIONS > 3 but I don't know what some of the region(s) are" +# undef CONFIG_MM_REGIONS +# define CONFIG_MM_REGIONS 3 +# endif +# endif + + /* CONFIG_MM_REGIONS is exactly 2. We cannot support both CCM SRAM and + * FSMC SRAM. + */ + +# elif !defined(CONFIG_STM32_CCMEXCLUDE) +# error "CONFIG_MM_REGIONS == 2, cannot support both CCM SRAM and FSMC SRAM" +# undef CONFIG_STM32_CCMEXCLUDE +# define CONFIG_STM32_CCMEXCLUDE 1 +# endif + +# elif !defined(CONFIG_STM32_CCMEXCLUDE) + + /* Configuration 2: FSMC SRAM is not used, but CCM SRAM is requested. DMA + * should be disabled and CONFIG_MM_REGIONS should be 2. + */ + +# ifdef CONFIG_STM32_DMA +# warning "CCM SRAM is included in the heap AND DMA is enabled" +# endif +# if CONFIG_MM_REGIONS < 2 +# error "CCM SRAM excluded from the heap because CONFIG_MM_REGIONS < 2" +# undef CONFIG_STM32_CCMEXCLUDE +# define CONFIG_STM32_CCMEXCLUDE 1 +# elif CONFIG_MM_REGIONS > 2 +# error "CONFIG_MM_REGIONS > 2 but I don't know what some of the region(s) are" +# undef CONFIG_MM_REGIONS +# define CONFIG_MM_REGIONS 2 +# endif +# endif +#else +# error "Unsupported STM32 chip" +#endif + +/* If FSMC SRAM is going to be used as heap, then verify that the starting + * address and size of the external SRAM region has been provided in the + * configuration (as CONFIG_HEAP2_BASE and CONFIG_HEAP2_END). + */ + +#ifdef CONFIG_STM32_FSMC_SRAM +# if !defined(CONFIG_HEAP2_BASE) || !defined(CONFIG_HEAP2_END) +# error "CONFIG_HEAP2_BASE and CONFIG_HEAP2_END must be provided" +# undef CONFIG_STM32_FSMC_SRAM +# endif +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocate_heap + * + * Description: + * The heap may be statically allocated by + * defining CONFIG_HEAP_BASE and CONFIG_HEAP_SIZE. If these + * are not defined, then this function will be called to + * dynamically set aside the heap region. + * + ****************************************************************************/ + +void up_allocate_heap(FAR void **heap_start, size_t *heap_size) +{ + up_ledon(LED_HEAPALLOCATE); + *heap_start = (FAR void*)g_heapbase; + *heap_size = SRAM1_END - g_heapbase; +} + +/**************************************************************************** + * Name: up_addregion + * + * Description: + * Memory may be added in non-contiguous chunks. Additional chunks are + * added by calling this function. + * + ****************************************************************************/ + +#if CONFIG_MM_REGIONS > 1 +void up_addregion(void) +{ + /* Add the STM32F20xxx/STM32F40xxx CCM SRAM heap region. */ + +#ifndef CONFIG_STM32_CCMEXCLUDE + mm_addregion((FAR void*)SRAM2_START, SRAM2_END-SRAM2_START); +#endif + + /* Add the external FSMC SRAM heap region. */ + +#ifdef CONFIG_STM32_FSMC_SRAM + mm_addregion((FAR void*)CONFIG_HEAP2_BASE, CONFIG_HEAP2_END - CONFIG_HEAP2_BASE); +#endif +} +#endif diff --git a/nuttx/arch/arm/src/stm32/stm32_bkp.h b/nuttx/arch/arm/src/stm32/stm32_bkp.h new file mode 100644 index 0000000000..21399c38bd --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_bkp.h @@ -0,0 +1,52 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_bkp.h + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_BKP_H +#define __ARCH_ARM_SRC_STM32_STM32_BKP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" +#include "chip/stm32_bkp.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32_STM32_BKP_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_can.c b/nuttx/arch/arm/src/stm32/stm32_can.c new file mode 100644 index 0000000000..bed2a80f6e --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_can.c @@ -0,0 +1,1636 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_can.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "up_internal.h" +#include "up_arch.h" + +#include "os_internal.h" + +#include "chip.h" +#include "stm32_internal.h" +#include "stm32_can.h" + +#if defined(CONFIG_CAN) && (defined(CONFIG_STM32_CAN1) || defined(CONFIG_STM32_CAN2)) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Delays *******************************************************************/ +/* Time out for INAK bit */ + +#define INAK_TIMEOUT 65535 + +/* Mailboxes ****************************************************************/ + +#define CAN_ALL_MAILBOXES (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2) + +/* Bit timing ***************************************************************/ + +#define CAN_BIT_QUANTA (CONFIG_CAN_TSEG1 + CONFIG_CAN_TSEG2 + 1) + +/* Debug ********************************************************************/ +/* Non-standard debug that may be enabled just for testing CAN */ + +#ifdef CONFIG_DEBUG_CAN +# define candbg dbg +# define canvdbg vdbg +# define canlldbg lldbg +# define canllvdbg llvdbg +#else +# define candbg(x...) +# define canvdbg(x...) +# define canlldbg(x...) +# define canllvdbg(x...) +#endif + +#if !defined(CONFIG_DEBUG) || !defined(CONFIG_DEBUG_CAN) +# undef CONFIG_CAN_REGDEBUG +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct stm32_can_s +{ + uint8_t port; /* CAN port number (1 or 2) */ + uint8_t canrx0; /* CAN RX FIFO 0 IRQ number */ + uint8_t cantx; /* CAN TX IRQ number */ + uint8_t filter; /* Filter number */ + uint32_t base; /* Base address of the CAN registers */ + uint32_t baud; /* Configured baud */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* CAN Register access */ + +static uint32_t can_getreg(struct stm32_can_s *priv, int offset); +static void can_putreg(struct stm32_can_s *priv, int offset, uint32_t value); +#ifdef CONFIG_CAN_REGDEBUG +static void can_dumpctrlregs(struct stm32_can_s *priv, FAR const char *msg); +static void can_dumpmbregs(struct stm32_can_s *priv, FAR const char *msg); +static void can_dumpfiltregs(struct stm32_can_s *priv, FAR const char *msg); +#else +# define can_dumpctrlregs(priv,msg) +# define can_dumpmbregs(priv,msg) +# define can_dumpfiltregs(priv,msg) +#endif + +/* CAN driver methods */ + +static void can_reset(FAR struct can_dev_s *dev); +static int can_setup(FAR struct can_dev_s *dev); +static void can_shutdown(FAR struct can_dev_s *dev); +static void can_rxint(FAR struct can_dev_s *dev, bool enable); +static void can_txint(FAR struct can_dev_s *dev, bool enable); +static int can_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg); +static int can_remoterequest(FAR struct can_dev_s *dev, uint16_t id); +static int can_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg); +static bool can_txready(FAR struct can_dev_s *dev); +static bool can_txempty(FAR struct can_dev_s *dev); + +/* CAN interrupt handling */ + +static int can_rx0interrupt(int irq, void *context); +static int can_txinterrupt(int irq, void *context); + +/* Initialization */ + +static int can_bittiming(struct stm32_can_s *priv); +static int can_cellinit(struct stm32_can_s *priv); +static int can_filterinit(struct stm32_can_s *priv); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct can_ops_s g_canops = +{ + .co_reset = can_reset, + .co_setup = can_setup, + .co_shutdown = can_shutdown, + .co_rxint = can_rxint, + .co_txint = can_txint, + .co_ioctl = can_ioctl, + .co_remoterequest = can_remoterequest, + .co_send = can_send, + .co_txready = can_txready, + .co_txempty = can_txempty, +}; + +#ifdef CONFIG_STM32_CAN1 +static struct stm32_can_s g_can1priv = +{ + .port = 1, +#if defined(CONFIG_STM32_STM32F10XX) && !defined(CONFIG_STM32_CONNECTIVITYLINE) + .canrx0 = STM32_IRQ_USBLPCANRX0, + .cantx = STM32_IRQ_USBHPCANTX, +#else + .canrx0 = STM32_IRQ_CAN1RX0, + .cantx = STM32_IRQ_CAN1TX, +#endif + .filter = 0, + .base = STM32_CAN1_BASE, + .baud = CONFIG_CAN1_BAUD, +}; + +static struct can_dev_s g_can1dev = +{ + .cd_ops = &g_canops, + .cd_priv = &g_can1priv, +}; +#endif + +#ifdef CONFIG_STM32_CAN2 +static struct stm32_can_s g_can2priv = +{ + .port = 2, + .canrx0 = STM32_IRQ_CAN2RX0, + .cantx = STM32_IRQ_CAN2TX, + .filter = CAN_NFILTERS / 2, + .base = STM32_CAN2_BASE, + .baud = CONFIG_CAN2_BAUD, +}; + +static struct can_dev_s g_can2dev = +{ + .cd_ops = &g_canops, + .cd_priv = &g_can2priv, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: can_getreg + * + * Description: + * Read the value of an CAN register. + * + * Input Parameters: + * priv - A reference to the CAN block status + * offset - The offset to the register to read + * + * Returned Value: + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_REGDEBUG +static uint32_t can_getreg(struct stm32_can_s *priv, int offset) +{ + static uint32_t prevaddr = 0; + static uint32_t preval = 0; + static uint32_t count = 0; + uint32_t addr = priv->base + offset; + + /* Read the value from the register */ + + uint32_t val = getreg32(addr); + + /* Is this the same value that we read from the same register last time? + * Are we polling the register? If so, suppress some of the output. + */ + + if (addr == prevaddr && val == preval) + { + if (count == 0xffffffff || ++count > 3) + { + if (count == 4) + { + lldbg("...\n"); + } + return val; + } + } + + /* No this is a new address or value */ + + else + { + /* Did we print "..." for the previous value? */ + + if (count > 3) + { + /* Yes.. then show how many times the value repeated */ + + lldbg("[repeats %d more times]\n", count-3); + } + + /* Save the new address, value, and count */ + + prevaddr = addr; + preval = val; + count = 1; + } + + /* Show the register value read */ + + lldbg("%08x->%08x\n", addr, val); + return val; +} +#else +static uint32_t can_getreg(struct stm32_can_s *priv, int offset) +{ + return getreg32(priv->base + offset); +} +#endif + +/**************************************************************************** + * Name: can_putreg + * + * Description: + * Set the value of an CAN register. + * + * Input Parameters: + * priv - A reference to the CAN block status + * offset - The offset to the register to write + * value - The value to write to the register + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_REGDEBUG +static void can_putreg(struct stm32_can_s *priv, int offset, uint32_t value) +{ + uint32_t addr = priv->base + offset; + + /* Show the register value being written */ + + lldbg("%08x<-%08x\n", addr, value); + + /* Write the value */ + + putreg32(value, addr); +} +#else +static void can_putreg(struct stm32_can_s *priv, int offset, uint32_t value) +{ + putreg32(value, priv->base + offset); +} +#endif + +/**************************************************************************** + * Name: can_dumpctrlregs + * + * Description: + * Dump the contents of all CAN control registers + * + * Input Parameters: + * priv - A reference to the CAN block status + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_REGDEBUG +static void can_dumpctrlregs(struct stm32_can_s *priv, FAR const char *msg) +{ + if (msg) + { + canlldbg("Control Registers: %s\n", msg); + } + else + { + canlldbg("Control Registers:\n"); + } + + /* CAN control and status registers */ + + lldbg(" MCR: %08x MSR: %08x TSR: %08x\n", + getreg32(priv->base + STM32_CAN_MCR_OFFSET), + getreg32(priv->base + STM32_CAN_MSR_OFFSET), + getreg32(priv->base + STM32_CAN_TSR_OFFSET)); + + lldbg(" RF0R: %08x RF1R: %08x\n", + getreg32(priv->base + STM32_CAN_RF0R_OFFSET), + getreg32(priv->base + STM32_CAN_RF1R_OFFSET)); + + lldbg(" IER: %08x ESR: %08x BTR: %08x\n", + getreg32(priv->base + STM32_CAN_IER_OFFSET), + getreg32(priv->base + STM32_CAN_ESR_OFFSET), + getreg32(priv->base + STM32_CAN_BTR_OFFSET)); +} +#endif + +/**************************************************************************** + * Name: can_dumpmbregs + * + * Description: + * Dump the contents of all CAN mailbox registers + * + * Input Parameters: + * priv - A reference to the CAN block status + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_REGDEBUG +static void can_dumpmbregs(struct stm32_can_s *priv, FAR const char *msg) +{ + if (msg) + { + canlldbg("Mailbox Registers: %s\n", msg); + } + else + { + canlldbg("Mailbox Registers:\n"); + } + + /* CAN mailbox registers (3 TX and 2 RX) */ + + lldbg(" TI0R: %08x TDT0R: %08x TDL0R: %08x TDH0R: %08x\n", + getreg32(priv->base + STM32_CAN_TI0R_OFFSET), + getreg32(priv->base + STM32_CAN_TDT0R_OFFSET), + getreg32(priv->base + STM32_CAN_TDL0R_OFFSET), + getreg32(priv->base + STM32_CAN_TDH0R_OFFSET)); + + lldbg(" TI1R: %08x TDT1R: %08x TDL1R: %08x TDH1R: %08x\n", + getreg32(priv->base + STM32_CAN_TI1R_OFFSET), + getreg32(priv->base + STM32_CAN_TDT1R_OFFSET), + getreg32(priv->base + STM32_CAN_TDL1R_OFFSET), + getreg32(priv->base + STM32_CAN_TDH1R_OFFSET)); + + lldbg(" TI2R: %08x TDT2R: %08x TDL2R: %08x TDH2R: %08x\n", + getreg32(priv->base + STM32_CAN_TI2R_OFFSET), + getreg32(priv->base + STM32_CAN_TDT2R_OFFSET), + getreg32(priv->base + STM32_CAN_TDL2R_OFFSET), + getreg32(priv->base + STM32_CAN_TDH2R_OFFSET)); + + lldbg(" RI0R: %08x RDT0R: %08x RDL0R: %08x RDH0R: %08x\n", + getreg32(priv->base + STM32_CAN_RI0R_OFFSET), + getreg32(priv->base + STM32_CAN_RDT0R_OFFSET), + getreg32(priv->base + STM32_CAN_RDL0R_OFFSET), + getreg32(priv->base + STM32_CAN_RDH0R_OFFSET)); + + lldbg(" RI1R: %08x RDT1R: %08x RDL1R: %08x RDH1R: %08x\n", + getreg32(priv->base + STM32_CAN_RI1R_OFFSET), + getreg32(priv->base + STM32_CAN_RDT1R_OFFSET), + getreg32(priv->base + STM32_CAN_RDL1R_OFFSET), + getreg32(priv->base + STM32_CAN_RDH1R_OFFSET)); +} +#endif + +/**************************************************************************** + * Name: can_dumpfiltregs + * + * Description: + * Dump the contents of all CAN filter registers + * + * Input Parameters: + * priv - A reference to the CAN block status + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_REGDEBUG +static void can_dumpfiltregs(struct stm32_can_s *priv, FAR const char *msg) +{ + int i; + + if (msg) + { + canlldbg("Filter Registers: %s\n", msg); + } + else + { + canlldbg("Filter Registers:\n"); + } + + lldbg(" FMR: %08x FM1R: %08x FS1R: %08x FFA1R: %08x FA1R: %08x\n", + getreg32(priv->base + STM32_CAN_FMR_OFFSET), + getreg32(priv->base + STM32_CAN_FM1R_OFFSET), + getreg32(priv->base + STM32_CAN_FS1R_OFFSET), + getreg32(priv->base + STM32_CAN_FFA1R_OFFSET), + getreg32(priv->base + STM32_CAN_FA1R_OFFSET)); + + for (i = 0; i < CAN_NFILTERS; i++) + { + lldbg(" F%dR1: %08x F%dR2: %08x\n", + i, getreg32(priv->base + STM32_CAN_FR_OFFSET(i,1)), + i, getreg32(priv->base + STM32_CAN_FR_OFFSET(i,2))); + } +} +#endif + +/**************************************************************************** + * Name: can_reset + * + * Description: + * Reset the CAN device. Called early to initialize the hardware. This + * function is called, before can_setup() and on error conditions. + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void can_reset(FAR struct can_dev_s *dev) +{ + FAR struct stm32_can_s *priv = dev->cd_priv; + uint32_t regval; + uint32_t regbit = 0; + irqstate_t flags; + + canllvdbg("CAN%d\n", priv->port); + + /* Get the bits in the AHB1RSTR register needed to reset this CAN device */ + +#ifdef CONFIG_STM32_CAN1 + if (priv->port == 1) + { + regbit = RCC_APB1RSTR_CAN1RST; + } + else +#endif +#ifdef CONFIG_STM32_CAN2 + if (priv->port == 2) + { + regbit = RCC_APB1RSTR_CAN2RST; + } + else +#endif + { + canlldbg("Unsupported port %d\n", priv->port); + return; + } + + /* Disable interrupts momentary to stop any ongoing CAN event processing and + * to prevent any concurrent access to the AHB1RSTR register. + */ + + flags = irqsave(); + + /* Reset the CAN */ + + regval = getreg32(STM32_RCC_APB1RSTR); + regval |= regbit; + putreg32(regval, STM32_RCC_APB1RSTR); + + regval &= ~regbit; + putreg32(regval, STM32_RCC_APB1RSTR); + irqrestore(flags); +} + +/**************************************************************************** + * Name: can_setup + * + * Description: + * Configure the CAN. This method is called the first time that the CAN + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching CAN interrupts. + * All CAN interrupts are disabled upon return. + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int can_setup(FAR struct can_dev_s *dev) +{ + FAR struct stm32_can_s *priv = dev->cd_priv; + int ret; + + canllvdbg("CAN%d RX0 irq: %d TX irq: %d\n", priv->port, priv->canrx0, priv->cantx); + + /* CAN cell initialization */ + + ret = can_cellinit(priv); + if (ret < 0) + { + canlldbg("CAN%d cell initialization failed: %d\n", priv->port, ret); + return ret; + } + + can_dumpctrlregs(priv, "After cell initialization"); + can_dumpmbregs(priv, NULL); + + /* CAN filter initialization */ + + ret = can_filterinit(priv); + if (ret < 0) + { + canlldbg("CAN%d filter initialization failed: %d\n", priv->port, ret); + return ret; + } + can_dumpfiltregs(priv, "After filter initialization"); + + /* Attach the CAN RX FIFO 0 interrupt and TX interrupts. The others are not used */ + + ret = irq_attach(priv->canrx0, can_rx0interrupt); + if (ret < 0) + { + canlldbg("Failed to attach CAN%d RX0 IRQ (%d)", priv->port, priv->canrx0); + return ret; + } + + ret = irq_attach(priv->cantx, can_txinterrupt); + if (ret < 0) + { + canlldbg("Failed to attach CAN%d TX IRQ (%d)", priv->port, priv->cantx); + return ret; + } + + /* Enable the interrupts at the NVIC. Interrupts arestill disabled in + * the CAN module. Since we coming out of reset here, there should be + * no pending interrupts. + */ + + up_enable_irq(priv->canrx0); + up_enable_irq(priv->cantx); + return OK; +} + +/**************************************************************************** + * Name: can_shutdown + * + * Description: + * Disable the CAN. This method is called when the CAN device is closed. + * This method reverses the operation the setup method. + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void can_shutdown(FAR struct can_dev_s *dev) +{ + FAR struct stm32_can_s *priv = dev->cd_priv; + + canllvdbg("CAN%d\n", priv->port); + + /* Disable the RX FIFO 0 and TX interrupts */ + + up_disable_irq(priv->canrx0); + up_disable_irq(priv->cantx); + + /* Detach the RX FIFO 0 and TX interrupts */ + + irq_detach(priv->canrx0); + irq_detach(priv->cantx); + + /* And reset the hardware */ + + can_reset(dev); +} + +/**************************************************************************** + * Name: can_rxint + * + * Description: + * Call to enable or disable RX interrupts. + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void can_rxint(FAR struct can_dev_s *dev, bool enable) +{ + FAR struct stm32_can_s *priv = dev->cd_priv; + uint32_t regval; + + canllvdbg("CAN%d enable: %d\n", priv->port, enable); + + /* Enable/disable the FIFO 0 message pending interrupt */ + + regval = can_getreg(priv, STM32_CAN_IER_OFFSET); + if (enable) + { + regval |= CAN_IER_FMPIE0; + } + else + { + regval &= ~CAN_IER_FMPIE0; + } + can_putreg(priv, STM32_CAN_IER_OFFSET, regval); +} + +/**************************************************************************** + * Name: can_txint + * + * Description: + * Call to enable or disable TX interrupts. + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void can_txint(FAR struct can_dev_s *dev, bool enable) +{ + FAR struct stm32_can_s *priv = dev->cd_priv; + uint32_t regval; + + canllvdbg("CAN%d enable: %d\n", priv->port, enable); + + /* Support only disabling the transmit mailbox interrupt */ + + if (!enable) + { + regval = can_getreg(priv, STM32_CAN_IER_OFFSET); + regval &= ~CAN_IER_TMEIE; + can_putreg(priv, STM32_CAN_IER_OFFSET, regval); + } +} + +/**************************************************************************** + * Name: can_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int can_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg) +{ + /* No CAN ioctls are supported */ + + return -ENOTTY; +} + +/**************************************************************************** + * Name: can_remoterequest + * + * Description: + * Send a remote request + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int can_remoterequest(FAR struct can_dev_s *dev, uint16_t id) +{ +#warning "Remote request not implemented" + return -ENOSYS; +} + +/**************************************************************************** + * Name: can_send + * + * Description: + * Send one can message. + * + * One CAN-message consists of a maximum of 10 bytes. A message is + * composed of at least the first 2 bytes (when there are no data bytes). + * + * Byte 0: Bits 0-7: Bits 3-10 of the 11-bit CAN identifier + * Byte 1: Bits 5-7: Bits 0-2 of the 11-bit CAN identifier + * Bit 4: Remote Tranmission Request (RTR) + * Bits 0-3: Data Length Code (DLC) + * Bytes 2-10: CAN data + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int can_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg) +{ + FAR struct stm32_can_s *priv = dev->cd_priv; + FAR uint8_t *ptr; + uint32_t regval; + uint32_t tmp; + int dlc; + int txmb; + + canllvdbg("CAN%d ID: %d DLC: %d\n", priv->port, msg->cm_hdr.ch_id, msg->cm_hdr.ch_dlc); + + /* Select one empty transmit mailbox */ + + regval = can_getreg(priv, STM32_CAN_TSR_OFFSET); + if ((regval & CAN_TSR_TME0) != 0) + { + txmb = 0; + } + else if ((regval & CAN_TSR_TME1) != 0) + { + txmb = 1; + } + else if ((regval & CAN_TSR_TME2) != 0) + { + txmb = 2; + } + else + { + canlldbg("ERROR: No available mailbox\n"); + return -EBUSY; + } + + /* Clear TXRQ, RTR, IDE, EXID, and STID fields */ + + regval = can_getreg(priv, STM32_CAN_TIR_OFFSET(txmb)); + regval &= ~(CAN_TIR_TXRQ | CAN_TIR_RTR | CAN_TIR_IDE | CAN_TIR_EXID_MASK | CAN_TIR_STID_MASK); + can_putreg(priv, STM32_CAN_TIR_OFFSET(txmb), regval); + + /* Set up the ID, standard 11-bit or extended 29-bit. */ + +#ifdef CONFIG_CAN_EXTID + regval &= ~CAN_TIR_EXID_MASK; + if (msg->cm_hdr.ch_extid) + { + DEBUGASSERT(msg->cm_hdr.ch_id < (1 << 29)); + regval |= (msg->cm_hdr.ch_id << CAN_TIR_EXID_SHIFT) | CAN_TIR_IDE; + } + else + { + DEBUGASSERT(msg->cm_hdr.ch_id < (1 << 11)); + regval |= msg->cm_hdr.ch_id << CAN_TIR_STID_SHIFT; + } +#else + regval &= ~CAN_TIR_STID_MASK; + regval |= (uint32_t)msg->cm_hdr.ch_id << CAN_TIR_STID_SHIFT; +#endif + can_putreg(priv, STM32_CAN_TIR_OFFSET(txmb), regval); + + /* Set up the DLC */ + + dlc = msg->cm_hdr.ch_dlc; + regval = can_getreg(priv, STM32_CAN_TDTR_OFFSET(txmb)); + regval &= ~(CAN_TDTR_DLC_MASK | CAN_TDTR_TGT); + regval |= (uint32_t)dlc << CAN_TDTR_DLC_SHIFT; + can_putreg(priv, STM32_CAN_TDTR_OFFSET(txmb), regval); + + /* Set up the data fields */ + + ptr = msg->cm_data; + regval = 0; + + if (dlc > 0) + { + tmp = (uint32_t)*ptr++; + regval = tmp << CAN_TDLR_DATA0_SHIFT; + + if (dlc > 1) + { + tmp = (uint32_t)*ptr++; + regval |= tmp << CAN_TDLR_DATA1_SHIFT; + + if (dlc > 2) + { + tmp = (uint32_t)*ptr++; + regval |= tmp << CAN_TDLR_DATA2_SHIFT; + + if (dlc > 3) + { + tmp = (uint32_t)*ptr++; + regval |= tmp << CAN_TDLR_DATA3_SHIFT; + } + } + } + } + can_putreg(priv, STM32_CAN_TDLR_OFFSET(txmb), regval); + + regval = 0; + if (dlc > 4) + { + tmp = (uint32_t)*ptr++; + regval = tmp << CAN_TDHR_DATA4_SHIFT; + + if (dlc > 5) + { + tmp = (uint32_t)*ptr++; + regval |= tmp << CAN_TDHR_DATA5_SHIFT; + + if (dlc > 6) + { + tmp = (uint32_t)*ptr++; + regval |= tmp << CAN_TDHR_DATA6_SHIFT; + + if (dlc > 7) + { + tmp = (uint32_t)*ptr++; + regval |= tmp << CAN_TDHR_DATA7_SHIFT; + } + } + } + } + can_putreg(priv, STM32_CAN_TDHR_OFFSET(txmb), regval); + + /* Enable the transmit mailbox empty interrupt (may already be enabled) */ + + regval = can_getreg(priv, STM32_CAN_IER_OFFSET); + regval |= CAN_IER_TMEIE; + can_putreg(priv, STM32_CAN_IER_OFFSET, regval); + + /* Request transmission */ + + regval = can_getreg(priv, STM32_CAN_TIR_OFFSET(txmb)); + regval |= CAN_TIR_TXRQ; /* Transmit Mailbox Request */ + can_putreg(priv, STM32_CAN_TIR_OFFSET(txmb), regval); + + can_dumpmbregs(priv, "After send"); + return OK; +} + +/**************************************************************************** + * Name: can_txready + * + * Description: + * Return true if the CAN hardware can accept another TX message. + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * True if the CAN hardware is ready to accept another TX message. + * + ****************************************************************************/ + +static bool can_txready(FAR struct can_dev_s *dev) +{ + FAR struct stm32_can_s *priv = dev->cd_priv; + uint32_t regval; + + /* Return true if any mailbox is available */ + + regval = can_getreg(priv, STM32_CAN_TSR_OFFSET); + canllvdbg("CAN%d TSR: %08x\n", priv->port, regval); + + if ((regval & CAN_ALL_MAILBOXES) != 0) + { + return true; + } + return false; +} + +/**************************************************************************** + * Name: can_txempty + * + * Description: + * Return true if all message have been sent. If for example, the CAN + * hardware implements FIFOs, then this would mean the transmit FIFO is + * empty. This method is called when the driver needs to make sure that + * all characters are "drained" from the TX hardware before calling + * co_shutdown(). + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * True if there are no pending TX transfers in the CAN hardware. + * + ****************************************************************************/ + +static bool can_txempty(FAR struct can_dev_s *dev) +{ + FAR struct stm32_can_s *priv = dev->cd_priv; + uint32_t regval; + + /* Return true if all mailboxes are available */ + + regval = can_getreg(priv, STM32_CAN_TSR_OFFSET); + canllvdbg("CAN%d TSR: %08x\n", priv->port, regval); + + if ((regval & CAN_ALL_MAILBOXES) == CAN_ALL_MAILBOXES) + { + return true; + } + return false; +} + +/**************************************************************************** + * Name: can_rx0interrupt + * + * Description: + * CAN RX FIFO 0 interrupt handler + * + * Input Parameters: + * irq - The IRQ number of the interrupt. + * context - The register state save array at the time of the interrupt. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int can_rx0interrupt(int irq, void *context) +{ + FAR struct can_dev_s *dev = NULL; + FAR struct stm32_can_s *priv; + struct can_hdr_s hdr; + uint8_t data[CAN_MAXDATALEN]; + uint32_t regval; + int npending; + int ret; + +#if defined(CONFIG_STM32_CAN1) && defined(CONFIG_STM32_CAN2) + if (g_can1priv.canrx0 == irq) + { + dev = &g_can1dev; + } + else if (g_can2priv.canrx0 == irq) + { + dev = &g_can2dev; + } + else + { + PANIC(OSERR_UNEXPECTEDISR); + } +#elif defined(CONFIG_STM32_CAN1) + dev = &g_can1dev; +#else /* defined(CONFIG_STM32_CAN2) */ + dev = &g_can2dev; +#endif + priv = dev->cd_priv; + + /* Verify that a message is pending in FIFO 0 */ + + regval = can_getreg(priv, STM32_CAN_RF0R_OFFSET); + npending = (regval & CAN_RFR_FMP_MASK) >> CAN_RFR_FMP_SHIFT; + if (npending < 1) + { + canlldbg("WARNING: No messages pending\n"); + return OK; + } + + can_dumpmbregs(priv, "RX0 interrupt"); + + /* Get the CAN identifier. */ + + regval = can_getreg(priv, STM32_CAN_RI0R_OFFSET); +#ifdef CONFIG_CAN_EXTID + if ((regval & CAN_RIR_IDE) != 0) + { + hdr.ch_id = (regval & CAN_RIR_EXID_MASK) >> CAN_RIR_EXID_SHIFT; + hdr.ch_extid = true; + } + else + { + hdr.ch_id = (regval & CAN_RIR_STID_MASK) >> CAN_RIR_STID_SHIFT; + hdr.ch_extid = false; + } +#else + if ((regval & CAN_RIR_IDE) != 0) + { + canlldbg("ERROR: Received message with extended identifier. Dropped\n"); + ret = -ENOSYS; + goto errout; + } + + hdr.ch_id = (regval & CAN_RIR_STID_MASK) >> CAN_RIR_STID_SHIFT; +#endif + + /* Extract the RTR bit */ + + hdr.ch_rtr = (regval & CAN_RIR_RTR) != 0 ? true : false; + + /* Get the DLC */ + + regval = can_getreg(priv, STM32_CAN_RDT0R_OFFSET); + hdr.ch_dlc = (regval & CAN_RDTR_DLC_MASK) >> CAN_RDTR_DLC_SHIFT; + + /* Save the message data */ + + regval = can_getreg(priv, STM32_CAN_RDL0R_OFFSET); + data[0] = (regval & CAN_RDLR_DATA0_MASK) >> CAN_RDLR_DATA0_SHIFT; + data[1] = (regval & CAN_RDLR_DATA1_MASK) >> CAN_RDLR_DATA1_SHIFT; + data[2] = (regval & CAN_RDLR_DATA2_MASK) >> CAN_RDLR_DATA2_SHIFT; + data[3] = (regval & CAN_RDLR_DATA3_MASK) >> CAN_RDLR_DATA3_SHIFT; + + regval = can_getreg(priv, STM32_CAN_RDH0R_OFFSET); + data[4] = (regval & CAN_RDHR_DATA4_MASK) >> CAN_RDHR_DATA4_SHIFT; + data[5] = (regval & CAN_RDHR_DATA5_MASK) >> CAN_RDHR_DATA5_SHIFT; + data[6] = (regval & CAN_RDHR_DATA6_MASK) >> CAN_RDHR_DATA6_SHIFT; + data[7] = (regval & CAN_RDHR_DATA7_MASK) >> CAN_RDHR_DATA7_SHIFT; + + /* Provide the data to the upper half driver */ + + ret = can_receive(dev, &hdr, data); + + /* Release the FIFO0 */ + +#ifndef CONFIG_CAN_EXTID +errout: +#endif + regval = can_getreg(priv, STM32_CAN_RF0R_OFFSET); + regval |= CAN_RFR_RFOM; + can_putreg(priv, STM32_CAN_RF0R_OFFSET, regval); + return OK; +} + +/**************************************************************************** + * Name: can_txinterrupt + * + * Description: + * CAN TX mailbox complete interrupt handler + * + * Input Parameters: + * irq - The IRQ number of the interrupt. + * context - The register state save array at the time of the interrupt. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int can_txinterrupt(int irq, void *context) +{ + FAR struct can_dev_s *dev = NULL; + FAR struct stm32_can_s *priv; + uint32_t regval; + +#if defined(CONFIG_STM32_CAN1) && defined(CONFIG_STM32_CAN2) + if (g_can1priv.cantx == irq) + { + dev = &g_can1dev; + } + else if (g_can2priv.cantx == irq) + { + dev = &g_can2dev; + } + else + { + PANIC(OSERR_UNEXPECTEDISR); + } +#elif defined(CONFIG_STM32_CAN1) + dev = &g_can1dev; +#else /* defined(CONFIG_STM32_CAN2) */ + dev = &g_can2dev; +#endif + priv = dev->cd_priv; + + /* Get the transmit status */ + + regval = can_getreg(priv, STM32_CAN_TSR_OFFSET); + + /* Check for RQCP0: Request completed mailbox 0 */ + + if ((regval & CAN_TSR_RQCP0) != 0) + { + /* Writing '1' to RCP0 clears RCP0 and all the status bits (TXOK0, + * ALST0 and TERR0) for Mailbox 0. + */ + + can_putreg(priv, STM32_CAN_TSR_OFFSET, CAN_TSR_RQCP0); + + /* Check for errors */ + + if ((regval & CAN_TSR_TXOK0) != 0) + { + /* Tell the upper half that the tansfer is finished. */ + + (void)can_txdone(dev); + } + } + + /* Check for RQCP1: Request completed mailbox 1 */ + + if ((regval & CAN_TSR_RQCP1) != 0) + { + /* Writing '1' to RCP1 clears RCP1 and all the status bits (TXOK1, + * ALST1 and TERR1) for Mailbox 1. + */ + + can_putreg(priv, STM32_CAN_TSR_OFFSET, CAN_TSR_RQCP1); + + /* Check for errors */ + + if ((regval & CAN_TSR_TXOK1) != 0) + { + /* Tell the upper half that the tansfer is finished. */ + + (void)can_txdone(dev); + } + } + + /* Check for RQCP2: Request completed mailbox 2 */ + + if ((regval & CAN_TSR_RQCP2) != 0) + { + /* Writing '1' to RCP2 clears RCP2 and all the status bits (TXOK2, + * ALST2 and TERR2) for Mailbox 2. + */ + + can_putreg(priv, STM32_CAN_TSR_OFFSET, CAN_TSR_RQCP2); + + /* Check for errors */ + + if ((regval & CAN_TSR_TXOK2) != 0) + { + /* Tell the upper half that the tansfer is finished. */ + + (void)can_txdone(dev); + } + } + + /* Were all transmissions complete in all mailboxes when we entered this + * handler? + */ + + if ((regval & CAN_ALL_MAILBOXES) == CAN_ALL_MAILBOXES) + { + /* Yes.. disable further TX interrupts */ + + regval = can_getreg(priv, STM32_CAN_IER_OFFSET); + regval &= ~CAN_IER_TMEIE; + can_putreg(priv, STM32_CAN_IER_OFFSET, regval); + } + + return OK; +} + +/**************************************************************************** + * Name: can_bittiming + * + * Description: + * Set the CAN bit timing register (BTR) based on the configured BAUD. + * + * "The bit timing logic monitors the serial bus-line and performs sampling + * and adjustment of the sample point by synchronizing on the start-bit edge + * and resynchronizing on the following edges. + * + * "Its operation may be explained simply by splitting nominal bit time into + * three segments as follows: + * + * 1. "Synchronization segment (SYNC_SEG): a bit change is expected to occur + * within this time segment. It has a fixed length of one time quantum + * (1 x tCAN). + * 2. "Bit segment 1 (BS1): defines the location of the sample point. It + * includes the PROP_SEG and PHASE_SEG1 of the CAN standard. Its duration + * is programmable between 1 and 16 time quanta but may be automatically + * lengthened to compensate for positive phase drifts due to differences + * in the frequency of the various nodes of the network. + * 3. "Bit segment 2 (BS2): defines the location of the transmit point. It + * represents the PHASE_SEG2 of the CAN standard. Its duration is + * programmable between 1 and 8 time quanta but may also be automatically + * shortened to compensate for negative phase drifts." + * + * Pictorially: + * + * |<----------------- NOMINAL BIT TIME ----------------->| + * |<- SYNC_SEG ->|<------ BS1 ------>|<------ BS2 ------>| + * |<---- Tq ---->|<----- Tbs1 ------>|<----- Tbs2 ------>| + * + * Where + * Tbs1 is the duration of the BS1 segment + * Tbs2 is the duration of the BS2 segment + * Tq is the "Time Quantum" + * + * Relationships: + * + * baud = 1 / bit_time + * bit_time = Tq + Tbs1 + Tbs2 + * Tbs1 = Tq * ts1 + * Tbs2 = Tq * ts2 + * Tq = brp * Tpclk1 + * + * Where: + * Tpclk1 is the period of the APB1 clock (PCLK1). + * + * Input Parameter: + * priv - A reference to the CAN block status + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int can_bittiming(struct stm32_can_s *priv) +{ + uint32_t tmp; + uint32_t brp; + uint32_t ts1; + uint32_t ts2; + + canllvdbg("CAN%d PCLK1: %d baud: %d\n", + priv->port, STM32_PCLK1_FREQUENCY, priv->baud); + + /* Try to get CAN_BIT_QUANTA quanta in one bit_time. + * + * bit_time = Tq*(ts1 + ts2 + 1) + * nquanta = bit_time / Tq + * nquanta = (ts1 + ts2 + 1) + * + * bit_time = brp * Tpclk1 * (ts1 + ts2 + 1) + * nquanta = bit_time / brp / Tpclk1 + * = PCLK1 / baud / brp + * brp = PCLK1 / baud / nquanta; + * + * Example: + * PCLK1 = 42,000,000 baud = 1,000,000 nquanta = 14 : brp = 3 + * PCLK1 = 42,000,000 baud = 700,000 nquanta = 14 : brp = 4 + */ + + tmp = STM32_PCLK1_FREQUENCY / priv->baud; + if (tmp < CAN_BIT_QUANTA) + { + /* At the smallest brp value (1), there are already too few bit times + * (PCLCK1 / baud) to meet our goal. brp must be one and we need + * make some reasonable guesses about ts1 and ts2. + */ + + brp = 1; + + /* In this case, we have to guess a good value for ts1 and ts2 */ + + ts1 = (tmp - 1) >> 1; + ts2 = tmp - ts1 - 1; + if (ts1 == ts2 && ts1 > 1 && ts2 < CAN_BTR_TSEG2_MAX) + { + ts1--; + ts2++; + } + } + + /* Otherwise, nquanta is CAN_BIT_QUANTA, ts1 is CONFIG_CAN_TSEG1, ts2 is + * CONFIG_CAN_TSEG2 and we calculate brp to achieve CAN_BIT_QUANTA quanta + * in the bit time + */ + + else + { + ts1 = CONFIG_CAN_TSEG1; + ts2 = CONFIG_CAN_TSEG2; + brp = (tmp + (CAN_BIT_QUANTA/2)) / CAN_BIT_QUANTA; + DEBUGASSERT(brp >=1 && brp <= CAN_BTR_BRP_MAX); + } + + canllvdbg("TS1: %d TS2: %d BRP: %d\n", ts1, ts2, brp); + + /* Configure bit timing. This also does the the following, less obvious + * things. Unless loopback mode is enabled, it: + * + * - Disables silent mode. + * - Disables loopback mode. + * + * NOTE that for the time being, SJW is set to 1 just because I don't + * know any better. + */ + + tmp = ((brp - 1) << CAN_BTR_BRP_SHIFT) | ((ts1 - 1) << CAN_BTR_TS1_SHIFT) | + ((ts2 - 1) << CAN_BTR_TS2_SHIFT) | ((1 - 1) << CAN_BTR_SJW_SHIFT); +#ifdef CONFIG_CAN_LOOPBACK +//tmp |= (CAN_BTR_LBKM | CAN_BTR_SILM); + tmp |= CAN_BTR_LBKM; +#endif + + can_putreg(priv, STM32_CAN_BTR_OFFSET, tmp); + return OK; +} + +/**************************************************************************** + * Name: can_cellinit + * + * Description: + * CAN cell initialization + * + * Input Parameter: + * priv - A pointer to the private data structure for this CAN block + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int can_cellinit(struct stm32_can_s *priv) +{ + volatile uint32_t timeout; + uint32_t regval; + int ret; + + canllvdbg("CAN%d\n", priv->port); + + /* Exit from sleep mode */ + + regval = can_getreg(priv, STM32_CAN_MCR_OFFSET); + regval &= ~CAN_MCR_SLEEP; + can_putreg(priv, STM32_CAN_MCR_OFFSET, regval); + + /* Configure CAN behavior. Priority driven request order, not message ID. */ + + regval |= CAN_MCR_TXFP; + can_putreg(priv, STM32_CAN_MCR_OFFSET, regval); + + /* Enter initialization mode */ + + regval |= CAN_MCR_INRQ; + can_putreg(priv, STM32_CAN_MCR_OFFSET, regval); + + /* Wait until initialization mode is acknowledged */ + + for (timeout = INAK_TIMEOUT; timeout > 0; timeout--) + { + regval = can_getreg(priv, STM32_CAN_MSR_OFFSET); + if ((regval & CAN_MSR_INAK) != 0) + { + /* We are in initialization mode */ + + break; + } + } + + /* Check for a timeout */ + + if (timeout < 1) + { + canlldbg("ERROR: Timed out waiting to enter initialization mode\n"); + return -ETIMEDOUT; + } + + /* Disable the following modes: + * + * - Time triggered communication mode + * - Automatic bus-off management + * - Automatic wake-up mode + * - No automatic retransmission + * - Receive FIFO locked mode + * - Transmit FIFO priority + */ + + regval = can_getreg(priv, STM32_CAN_MCR_OFFSET); + regval &= ~(CAN_MCR_TXFP | CAN_MCR_RFLM | CAN_MCR_NART | CAN_MCR_AWUM | CAN_MCR_ABOM | CAN_MCR_TTCM); + can_putreg(priv, STM32_CAN_MCR_OFFSET, regval); + + /* Configure bit timing. */ + + ret = can_bittiming(priv); + if (ret < 0) + { + canlldbg("ERROR: Failed to set bit timing: %d\n", ret); + return ret; + } + + /* Exit initialization mode */ + + regval = can_getreg(priv, STM32_CAN_MCR_OFFSET); + regval &= ~CAN_MCR_INRQ; + can_putreg(priv, STM32_CAN_MCR_OFFSET, regval); + + /* Wait until the initialization mode exit is acknowledged */ + + for (timeout = INAK_TIMEOUT; timeout > 0; timeout--) + { + regval = can_getreg(priv, STM32_CAN_MSR_OFFSET); + if ((regval & CAN_MSR_INAK) == 0) + { + /* We are out of initialization mode */ + + break; + } + } + + /* Check for a timeout */ + + if (timeout < 1) + { + canlldbg("ERROR: Timed out waiting to exit initialization mode: %08x\n", regval); + return -ETIMEDOUT; + } + return OK; +} + +/**************************************************************************** + * Name: can_filterinit + * + * Description: + * CAN filter initialization. CAN filters are not currently used by this + * driver. The CAN filters can be configured in a different way: + * + * 1. As a match of specific IDs in a list (IdList mode), or as + * 2. And ID and a mask (IdMask mode). + * + * Filters can also be configured as: + * + * 3. 16- or 32-bit. The advantage of 16-bit filters is that you get + * more filters; The advantage of 32-bit filters is that you get + * finer control of the filtering. + * + * One filter is set up for each CAN. The filter resources are shared + * between the two CAN modules: CAN1 uses only filter 0 (but reserves + * 0 through CAN_NFILTERS/2-1); CAN2 uses only filter CAN_NFILTERS/2 + * (but reserves CAN_NFILTERS/2 through CAN_NFILTERS-1). + * + * 32-bit IdMask mode is configured. However, both the ID and the MASK + * are set to zero thus supressing all filtering because anything masked + * with zero matches zero. + * + * Input Parameter: + * priv - A pointer to the private data structure for this CAN block + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int can_filterinit(struct stm32_can_s *priv) +{ + uint32_t regval; + uint32_t bitmask; + + canllvdbg("CAN%d filter: %d\n", priv->port, priv->filter); + + /* Get the bitmask associated with the filter used by this CAN block */ + + bitmask = ((uint32_t)1) << priv->filter; + + /* Enter filter initialization mode */ + + regval = can_getreg(priv, STM32_CAN_FMR_OFFSET); + regval |= CAN_FMR_FINIT; + can_putreg(priv, STM32_CAN_FMR_OFFSET, regval); + + /* Disable the filter */ + + regval = can_getreg(priv, STM32_CAN_FA1R_OFFSET); + regval &= ~bitmask; + can_putreg(priv, STM32_CAN_FA1R_OFFSET, regval); + + /* Select the 32-bit scale for the filter */ + + regval = can_getreg(priv, STM32_CAN_FS1R_OFFSET); + regval |= bitmask; + can_putreg(priv, STM32_CAN_FS1R_OFFSET, regval); + + /* There are 14 or 28 filter banks (depending) on the device. Each filter bank is + * composed of two 32-bit registers, CAN_FiR: + */ + + can_putreg(priv, STM32_CAN_FR_OFFSET(priv->filter, 1), 0); + can_putreg(priv, STM32_CAN_FR_OFFSET(priv->filter, 2), 0); + + /* Set Id/Mask mode for the filter */ + + regval = can_getreg(priv, STM32_CAN_FM1R_OFFSET); + regval &= ~bitmask; + can_putreg(priv, STM32_CAN_FM1R_OFFSET, regval); + + /* Assign FIFO 0 for the filter */ + + regval = can_getreg(priv, STM32_CAN_FFA1R_OFFSET); + regval &= ~bitmask; + can_putreg(priv, STM32_CAN_FFA1R_OFFSET, regval); + + /* Enable the filter */ + + regval = can_getreg(priv, STM32_CAN_FA1R_OFFSET); + regval |= bitmask; + can_putreg(priv, STM32_CAN_FA1R_OFFSET, regval); + + /* Exit filter initialization mode */ + + regval = can_getreg(priv, STM32_CAN_FMR_OFFSET); + regval &= ~CAN_FMR_FINIT; + can_putreg(priv, STM32_CAN_FMR_OFFSET, regval); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_caninitialize + * + * Description: + * Initialize the selected CAN port + * + * Input Parameter: + * Port number (for hardware that has mutiple CAN interfaces) + * + * Returned Value: + * Valid CAN device structure reference on succcess; a NULL on failure + * + ****************************************************************************/ + +FAR struct can_dev_s *stm32_caninitialize(int port) +{ + struct can_dev_s *dev = NULL; + + canvdbg("CAN%d\n", port); + + /* NOTE: Peripherical clocking for CAN1 and/or CAN2 was already provided + * by stm32_clockconfig() early in the reset sequence. + */ + +#ifdef CONFIG_STM32_CAN1 + if( port == 1 ) + { + /* Select the CAN1 device structure */ + + dev = &g_can1dev; + + /* Configure CAN1 pins. The ambiguous settings in the stm32*_pinmap.h + * file must have been disambiguated in the board.h file. + */ + + stm32_configgpio(GPIO_CAN1_RX); + stm32_configgpio(GPIO_CAN1_TX); + } + else +#endif +#ifdef CONFIG_STM32_CAN2 + if ( port ==2 ) + { + /* Select the CAN2 device structure */ + + dev = &g_can2dev; + + /* Configure CAN2 pins. The ambiguous settings in the stm32*_pinmap.h + * file must have been disambiguated in the board.h file. + */ + + stm32_configgpio(GPIO_CAN2_RX); + stm32_configgpio(GPIO_CAN2_TX); + } + else +#endif + { + candbg("ERROR: Unsupported port %d\n", port); + return NULL; + } + + return dev; +} + +#endif /* CONFIG_CAN && (CONFIG_STM32_CAN1 || CONFIG_STM32_CAN2) */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_can.h b/nuttx/arch/arm/src/stm32/stm32_can.h new file mode 100644 index 0000000000..15203b5c91 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_can.h @@ -0,0 +1,145 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_can.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_CAN_H +#define __ARCH_ARM_SRC_STM32_STM32_CAN_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" +#include "chip/stm32_can.h" + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* Up to 2 CAN interfaces are supported */ + +#if STM32_NCAN < 2 +# undef CONFIG_STM32_CAN2 +#endif + +#if STM32_NCAN < 1 +# undef CONFIG_STM32_CAN1 +#endif + +#if defined(CONFIG_CAN) && (defined(CONFIG_STM32_CAN1) || defined(CONFIG_STM32_CAN2)) + +/* CAN BAUD */ + +#if defined(CONFIG_STM32_CAN1) && !defined(CONFIG_CAN1_BAUD) +# error "CONFIG_CAN1_BAUD is not defined" +#endif + +#if defined(CONFIG_STM32_CAN2) && !defined(CONFIG_CAN2_BAUD) +# error "CONFIG_CAN2_BAUD is not defined" +#endif + +/* User-defined TSEG1 and TSEG2 settings may be used. + * + * CONFIG_CAN_TSEG1 = the number of CAN time quanta in segment 1 + * CONFIG_CAN_TSEG2 = the number of CAN time quanta in segment 2 + * CAN_BIT_QUANTA = The number of CAN time quanta in on bit time + */ + +#ifndef CONFIG_CAN_TSEG1 +# define CONFIG_CAN_TSEG1 6 +#endif + +#if CONFIG_CAN_TSEG1 < 1 || CONFIG_CAN_TSEG1 > CAN_BTR_TSEG1_MAX +# errror "CONFIG_CAN_TSEG1 is out of range" +#endif + +#ifndef CONFIG_CAN_TSEG2 +# define CONFIG_CAN_TSEG2 7 +#endif + +#if CONFIG_CAN_TSEG2 < 1 || CONFIG_CAN_TSEG2 > CAN_BTR_TSEG2_MAX +# errror "CONFIG_CAN_TSEG2 is out of range" +#endif + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/**************************************************************************** + * Name: stm32_caninitialize + * + * Description: + * Initialize the selected CAN port + * + * Input Parameter: + * Port number (for hardware that has mutiple CAN interfaces) + * + * Returned Value: + * Valid CAN device structure reference on succcess; a NULL on failure + * + ****************************************************************************/ + +struct can_dev_s; +EXTERN FAR struct can_dev_s *stm32_caninitialize(int port); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_CAN && (CONFIG_STM32_CAN1 || CONFIG_STM32_CAN2) */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_CAN_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_dac.c b/nuttx/arch/arm/src/stm32/stm32_dac.c new file mode 100644 index 0000000000..b92da7b717 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_dac.c @@ -0,0 +1,860 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_dac.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "up_internal.h" +#include "up_arch.h" + +#include "chip.h" +#include "stm32_internal.h" +#include "stm32_dac.h" + +#ifdef CONFIG_DAC + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* Up to 2 DAC interfaces are supported */ + +#if STM32_NDAC < 2 +# undef CONFIG_STM32_DAC2 +# undef CONFIG_STM32_DAC2_DMA +# undef CONFIG_STM32_DAC2_TIMER +# undef CONFIG_STM32_DAC2_TIMER_FREQUENCY +#endif + +#if STM32_NDAC < 1 +# undef CONFIG_STM32_DAC1 +# undef CONFIG_STM32_DAC1_DMA +# undef CONFIG_STM32_DAC1_TIMER +# undef CONFIG_STM32_DAC1_TIMER_FREQUENCY +#endif + +#if defined(CONFIG_STM32_DAC1) || defined(CONFIG_STM32_DAC2) + +/* DMA configuration. */ + +#if defined(CONFIG_STM32_DAC1_DMA) || defined(CONFIG_STM32_DAC2_DMA) +# if defined(CONFIG_STM32_STM32F10XX) +# ifndef CONFIG_STM32_DMA2 +# warning "STM32 F1 DAC DMA support requires CONFIG_STM32_DMA2" +# undef CONFIG_STM32_DAC1_DMA +# undef CONFIG_STM32_DAC2_DMA +# endif +# elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# ifndef CONFIG_STM32_DMA1 +# warning "STM32 F4 DAC DMA support requires CONFIG_STM32_DMA1" +# undef CONFIG_STM32_DAC1_DMA +# undef CONFIG_STM32_DAC2_DMA +# endif +# else +# warning "No DAC DMA information for this STM32 family" +# undef CONFIG_STM32_DAC1_DMA +# undef CONFIG_STM32_DAC2_DMA +# endif +#endif + +/* If DMA is selected, then a timer and output frequency must also be + * provided to support the DMA transfer. The DMA transfer could be + * supported by and EXTI trigger, but this feature is not currently + * supported by the driver. + */ + +#ifdef CONFIG_STM32_DAC1_DMA +# if !defined(CONFIG_STM32_DAC1_TIMER) +# warning "A timer number must be specificed in CONFIG_STM32_DAC1_TIMER" +# undef CONFIG_STM32_DAC1_DMA +# undef CONFIG_STM32_DAC1_TIMER_FREQUENCY +# elif !defined(CONFIG_STM32_DAC1_TIMER_FREQUENCY) +# warning "A timer frequency must be specificed in CONFIG_STM32_DAC1_TIMER_FREQUENCY" +# undef CONFIG_STM32_DAC1_DMA +# undef CONFIG_STM32_DAC1_TIMER +# endif +#endif + +#ifdef CONFIG_STM32_DAC2_DMA +# if !defined(CONFIG_STM32_DAC2_TIMER) +# warning "A timer number must be specificed in CONFIG_STM32_DAC2_TIMER" +# undef CONFIG_STM32_DAC2_DMA +# undef CONFIG_STM32_DAC2_TIMER_FREQUENCY +# elif !defined(CONFIG_STM32_DAC2_TIMER_FREQUENCY) +# warning "A timer frequency must be specificed in CONFIG_STM32_DAC2_TIMER_FREQUENCY" +# undef CONFIG_STM32_DAC2_DMA +# undef CONFIG_STM32_DAC2_TIMER +# endif +#endif + +/* DMA *********************************************************************/ +/* DMA channels and interface values differ for the F1 and F4 families */ + +#undef HAVE_DMA +#if defined(CONFIG_STM32_DAC1_DMA) || defined(CONFIG_STM32_DAC2_DMA) +# if defined(CONFIG_STM32_STM32F10XX) +# define HAVE_DMA 1 +# define DAC_DMA 2 +# define DAC1_DMA_CHAN DMACHAN_DAC_CHAN1 +# define DAC2_DMA_CHAN DMACHAN_DAC_CHAN2 +# elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define HAVE_DMA 1 +# define DAC_DMA 1 +# define DAC1_DMA_CHAN DMAMAP_DAC1 +# define DAC2_DMA_CHAN DMAMAP_DAC2 +# endif +#endif + +/* Timer configuration. The STM32 supports 8 different trigger for DAC + * output: + * + * TSEL SOURCE DEVICES + * ---- ----------------------- ------------------------------------- + * 000 Timer 6 TRGO event ALL + * 001 Timer 3 TRGO event STM32 F1 Connectivity Line + * Timer 8 TRGO event Other STM32 F1 and all STM32 F4 + * 010 Timer 7 TRGO event ALL + * 011 Timer 5 TRGO event ALL + * 100 Timer 2 TRGO event ALL + * 101 Timer 4 TRGO event ALL + * 110 EXTI line9 ALL + * 111 SWTRIG Software control ALL + * + * This driver does not support the EXTI trigger. + */ + +#ifdef CONFIG_STM32_DAC1_DMA +# if CONFIG_STM32_DAC1_TIMER == 6 +# ifndef CONFIG_STM32_TIM6_DAC +# error "CONFIG_STM32_TIM6_DAC required for DAC1" +# endif +# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM6 +# define DAC1_TIMER_BASE STM32_TIM6_BASE +# define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +# elif CONFIG_STM32_DAC1_TIMER == 3 && defined(CONFIG_STM32_CONNECTIVITYLINE) +# ifndef CONFIG_STM32_TIM3_DAC +# error "CONFIG_STM32_TIM3_DAC required for DAC1" +# endif +# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM3 +# define DAC1_TIMER_BASE STM32_TIM3_BASE +# define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +# elif CONFIG_STM32_DAC1_TIMER == 8 && !defined(CONFIG_STM32_CONNECTIVITYLINE) +# ifndef CONFIG_STM32_TIM8_DAC +# error "CONFIG_STM32_TIM8_DAC required for DAC1" +# endif +# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM8 +# define DAC1_TIMER_BASE STM32_TIM8_BASE +# define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY +# elif CONFIG_STM32_DAC1_TIMER == 7 +# ifndef CONFIG_STM32_TIM7_DAC +# error "CONFIG_STM32_TIM7_DAC required for DAC1" +# endif +# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM7 +# define DAC1_TIMER_BASE STM32_TIM7_BASE +# elif CONFIG_STM32_DAC1_TIMER == 5 +# ifndef CONFIG_STM32_TIM5_DAC +# error "CONFIG_STM32_TIM5_DAC required for DAC1" +# endif +# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM5 +# define DAC1_TIMER_BASE STM32_TIM5_BASE +# define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +# elif CONFIG_STM32_DAC1_TIMER == 2 +# ifndef CONFIG_STM32_TIM2_DAC +# error "CONFIG_STM32_TIM2_DAC required for DAC1" +# endif +# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM2 +# define DAC1_TIMER_BASE STM32_TIM2_BASE +# define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +# elif CONFIG_STM32_DAC1_TIMER == 4 +# ifndef CONFIG_STM32_TIM4_DAC +# error "CONFIG_STM32_TIM4_DAC required for DAC1" +# endif +# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM4 +# define DAC1_TIMER_BASE STM32_TIM4_BASE +# define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +# else +# error "Unsupported CONFIG_STM32_DAC1_TIMER" +# endif +#else +# define DAC1_TSEL_VALUE DAC_CR_TSEL_SW +#endif + +#ifdef CONFIG_STM32_DAC2_DMA +# if CONFIG_STM32_DAC2_TIMER == 6 +# ifndef CONFIG_STM32_TIM6_DAC +# error "CONFIG_STM32_TIM6_DAC required for DAC2" +# endif +# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM6 +# define DAC2_TIMER_BASE STM32_TIM6_BASE +# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +# elif CONFIG_STM32_DAC2_TIMER == 3 && defined(CONFIG_STM32_CONNECTIVITYLINE) +# ifndef CONFIG_STM32_TIM3_DAC +# error "CONFIG_STM32_TIM3_DAC required for DAC2" +# endif +# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM3 +# define DAC2_TIMER_BASE STM32_TIM3_BASE +# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +# elif CONFIG_STM32_DAC2_TIMER == 8 && !defined(CONFIG_STM32_CONNECTIVITYLINE) +# ifndef CONFIG_STM32_TIM8_DAC +# error "CONFIG_STM32_TIM8_DAC required for DAC2" +# endif +# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM8 +# define DAC2_TIMER_BASE STM32_TIM8_BASE +# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY +# elif CONFIG_STM32_DAC2_TIMER == 7 +# ifndef CONFIG_STM32_TIM7_DAC +# error "CONFIG_STM32_TIM7_DAC required for DAC2" +# endif +# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM7 +# define DAC2_TIMER_BASE STM32_TIM7_BASE +# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +# elif CONFIG_STM32_DAC2_TIMER == 5 +# ifndef CONFIG_STM32_TIM5_DAC +# error "CONFIG_STM32_TIM5_DAC required for DAC2" +# endif +# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM5 +# define DAC2_TIMER_BASE STM32_TIM5_BASE +# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +# elif CONFIG_STM32_DAC2_TIMER == 2 +# ifndef CONFIG_STM32_TIM2_DAC +# error "CONFIG_STM32_TIM2_DAC required for DAC2" +# endif +# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM2 +# define DAC2_TIMER_BASE STM32_TIM2_BASE +# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +# elif CONFIG_STM32_DAC2_TIMER == 4 +# ifndef CONFIG_STM32_TIM4_DAC +# error "CONFIG_STM32_TIM4_DAC required for DAC2" +# endif +# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM4 +# define DAC2_TIMER_BASE STM32_TIM4_BASE +# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +# else +# error "Unsupported CONFIG_STM32_DAC2_TIMER" +# endif +#else +# define DAC2_TSEL_VALUE DAC_CR_TSEL_SW +#endif + +/* Calculate timer divider values based upon DACn_TIMER_PCLK_FREQUENCY and + * CONFIG_STM32_DACn_TIMER_FREQUENCY. + */ +#warning "Missing Logic" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure represents the internal state of the single STM32 DAC block */ + +struct stm32_dac_s +{ + uint8_t init : 1; /* True, the DAC block has been initialized */ +}; + +/* This structure represents the internal state of one STM32 DAC channel */ + +struct stm32_chan_s +{ + uint8_t inuse : 1; /* True, the driver is in use and not available */ +#ifdef HAVE_DMA + uint8_t hasdma : 1; /* True, this channel supports DMA */ +#endif + uint8_t intf; /* DAC zero-based interface number (0 or 1) */ +#ifdef HAVE_DMA + uint16_t dmachan; /* DMA channel needed by this DAC */ + DMA_HANDLE dma; /* Allocated DMA channel */ + uint32_t tsel; /* CR trigger select value */ + uint32_t tbase; /* Timer base address */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* DAC Register access */ + +#ifdef HAVE_DMA +static uint32_t tim_getreg(struct stm32_chan_s *chan, int offset); +static void tim_putreg(struct stm32_chan_s *chan, int offset, uint32_t value); +#endif + +/* Interrupt handler */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +static int dac_interrupt(int irq, void *context); +#endif + +/* DAC methods */ + +static void dac_reset(FAR struct dac_dev_s *dev); +static int dac_setup(FAR struct dac_dev_s *dev); +static void dac_shutdown(FAR struct dac_dev_s *dev); +static void dac_txint(FAR struct dac_dev_s *dev, bool enable); +static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg); +static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg); +static int dac_interrupt(int irq, void *context); + +/* Initialization */ + +#ifdef HAVE_DMA +static int dac_timinit(struct stm32_chan_s *chan); +#endif +static int dac_chaninit(struct stm32_chan_s *chan); +static int dac_blockinit(void); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct dac_ops_s g_dacops = +{ + .ao_reset = dac_reset, + .ao_setup = dac_setup, + .ao_shutdown = dac_shutdown, + .ao_txint = dac_txint, + .ao_send = dac_send, + .ao_ioctl = dac_ioctl, +}; + +#ifdef CONFIG_STM32_DAC1 +static struct stm32_chan_s g_dac1priv = +{ + .intf = 0; +#ifdef CONFIG_STM32_DAC1_DMA + .hasdma = 1; + .dmachan = DAC1_DMA_CHAN, + .tsel = DAC1_TSEL_VALUE, + .tbase = DAC1_TIMER_BASE +#endif +} + +static struct dac_dev_s g_dac1dev = +{ + .ad_ops = &g_dacops, + .ad_priv = &g_dac1priv, +}; +#endif + +#ifdef CONFIG_STM32_DAC2 +static struct stm32_chan_s g_dac2priv = +{ + .intf = 1; +#ifdef CONFIG_STM32_DAC2_DMA + .hasdma = 1; + .dmachan = DAC2_DMA_CHAN, + .tsel = DAC2_TSEL_VALUE. + .tbase = DAC2_TIMER_BASE +#endif +} + +static struct dac_dev_s g_dac2dev = +{ + .ad_ops = &g_dacops, + .ad_priv = &g_dac2priv, +}; +#endif + +static struct stm32_dac_s g_dacblock; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tim_getreg + * + * Description: + * Read the value of an DMA timer register. + * + * Input Parameters: + * chan - A reference to the DAC block status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ****************************************************************************/ + +#ifdef HAVE_DMA +static uint32_t tim_getreg(struct stm32_chan_s *chan, int offset) +{ + return getreg32(chan->tbase + offset); +} +#endif + +/**************************************************************************** + * Name: tim_putreg + * + * Description: + * Read the value of an DMA timer register. + * + * Input Parameters: + * chan - A reference to the DAC block status + * offset - The offset to the register to read + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void tim_putreg(struct stm32_chan_s *chan, int offset, uint32_t value) +{ + putreg32(value, chan->tbase + offset); +} +#endif + +/**************************************************************************** + * Name: dac_interrupt + * + * Description: + * DAC interrupt handler. The STM32 F4 family supports a only a DAC + * underrun interrupt. + * + * Input Parameters: + * + * Returned Value: + * OK + * + ****************************************************************************/ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +static int dac_interrupt(int irq, void *context) +{ +#warning "Missing logic" + return OK; +} +#endif + +/**************************************************************************** + * Name: dac_reset + * + * Description: + * Reset the DAC channel. Called early to initialize the hardware. This + * is called, before dac_setup() and on error conditions. + * + * NOTE: DAC reset will reset both DAC channels! + * + * Input Parameters: + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void dac_reset(FAR struct dac_dev_s *dev) +{ + irqstate_t flags; + uint32_t regval; + + /* Reset only the selected DAC channel; the other DAC channel must remain + * functional. + */ + + flags = irqsave(); + +#warning "Missing logic" + + irqrestore(flags); +} + +/**************************************************************************** + * Name: dac_setup + * + * Description: + * Configure the DAC. This method is called the first time that the DAC + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching DAC interrupts. Interrupts + * are all disabled upon return. + * + * Input Parameters: + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int dac_setup(FAR struct dac_dev_s *dev) +{ +# warning "Missing logic" + return -ENOSYS; +} + +/**************************************************************************** + * Name: dac_shutdown + * + * Description: + * Disable the DAC. This method is called when the DAC device is closed. + * This method reverses the operation the setup method. + * + * Input Parameters: + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void dac_shutdown(FAR struct dac_dev_s *dev) +{ +# warning "Missing logic" +} + +/**************************************************************************** + * Name: dac_txint + * + * Description: + * Call to enable or disable TX interrupts. + * + * Input Parameters: + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void dac_txint(FAR struct dac_dev_s *dev, bool enable) +{ +# warning "Missing logic" +} + +/**************************************************************************** + * Name: dac_send + * + * Description: + * Set the DAC output. + * + * Input Parameters: + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg) +{ +#ifdef HAVE_DMA + if (priv->hasdma) + { + /* Configure the DMA stream/channel. + * + * - Channel number + * - Peripheral address + * - Direction: Memory to peripheral + * - Disable peripheral address increment + * - Enable memory address increment + * - Peripheral data size: half word + * - Mode: circular??? + * - Priority: ? + * - FIFO mode: disable + * - FIFO threshold: half full + * - Memory Burst: single + * - Peripheral Burst: single + */ +#warning "Missing logic" + + /* Enable DMA */ +#warning "Missing logic" + + /* Enable DAC Channel */ +#warning "Missing logic" + + /* Enable DMA for DAC Channel */ +#warning "Missing logic" + } + else + { + /* Non-DMA transfer */ +#warning "Missing logic" + } + return -ENOSYS; +} + +/**************************************************************************** + * Name: dac_ioctl + * + * Description: + * All ioctl calls will be routed through this method. + * + * Input Parameters: + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg) +{ + return -ENOTTY; +} + +/**************************************************************************** + * Name: dac_timinit + * + * Description: + * Initialize the timer that drivers the DAC DMA for this channel using + * the pre-calculated timer divider definitions. + * + * Input Parameters: + * chan - A reference to the DAC channel state data + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef HAVE_DMA +static int dac_timinit(struct stm32_chan_s *chan) +{ + /* Configure the time base: Timer period, prescaler, clock division, + * counter mode (up). + */ +#warning "Missing Logic" + + /* Selection TRGO selection: update */ +#warning "Missing Logic" + + /* Enable the counter */ +#warning "Missing Logic" +} +#endif + +/**************************************************************************** + * Name: dac_chaninit + * + * Description: + * Initialize the DAC channel. + * + * Input Parameters: + * chan - A reference to the DAC channel state data + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int dac_chaninit(struct stm32_chan_s *chan) +{ + /* Is the selected channel already in-use? */ + + if (chan->inuse) + { + /* Yes.. then return EBUSY */ + + return -EBUSY; + } + + /* Configure the DAC output pin: + * + * DAC -" Once the DAC channelx is enabled, the corresponding GPIO pin + * (PA4 or PA5) is automatically connected to the analog converter output + * (DAC_OUTx). In order to avoid parasitic consumption, the PA4 or PA5 pin + * should first be configured to analog (AIN)". + */ + + stm32_configgpio(chan->intf ? GPIO_DAC2_OUT : GPIO_DAC1_OUT); + + /* DAC channel configuration: + * + * - Set the trigger selection based upon the configuration. + * - Set wave generation == None. + * - Enable the output buffer. + */ +#warning "Missing logic" + + /* Determine if DMA is supported by this channel */ + +#ifdef HAVE_DMA + if (priv->hasdma) + { + /* Yes.. allocate a DMA channel */ + + priv->dma = stm32_dmachannel(priv->dmachan); + if (!priv->dma) + { + adbg("Failed to allocate a DMA channel\n"); + return -EBUSY; + } + + /* Configure the timer that supports the DMA operation */ + + ret = dac_timinit(chan); + if (ret < 0) + { + adbg("Failed to initialize the DMA timer: %d\n", ret); + return ret; + } + } +#endif + + /* Mark the DAC channel "in-use" */ + + chan->inuse = 1; + return OK; +} + +/**************************************************************************** + * Name: dac_blockinit + * + * Description: + * All ioctl calls will be routed through this method. + * + * Input Parameters: + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int dac_blockinit(void) +{ + irqstate_t flags; + uint32_t regval; + + /* Has the DMA block already been initialized? */ + + if (g_dacblock.init) + { + /* Yes.. then return success We only have to do this once */ + + return OK; + } + + /* Put the entire DAC block in reset state */ + + flags = irqsave(); + regval = getreg32(STM32_RCC_APB1RSTR); + regval |= RCC_APB1RSTR_DACRST + putreg32(regval, STM32_RCC_APB1RSTR); + + /* Take the DAC out of reset state */ + + regval &= ~RCC_APB1RSTR_DACRST + putreg32(regval, STM32_RCC_APB1RSTR); + irqrestore(flags); + + /* Mark the DAC block as initialized */ + + g_dacblock.init = 1; + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_dacinitialize + * + * Description: + * Initialize the DAC. + * + * Input Parameters: + * intf - The DAC interface number. + * + * Returned Value: + * Valid dac device structure reference on succcess; a NULL on failure. + * + * Assumptions: + * 1. Clock to the DAC block has enabled, + * 2. Board-specific logic has already configured + * + ****************************************************************************/ + +FAR struct dac_dev_s *stm32_dacinitialize(int intf) +{ + FAR struct dac_dev_s *dev; + FAR struct stm32_chan_s *chan; + int ret; + +#ifdef CONFIG_STM32_DAC1 + if (intf == 1) + { + avdbg("DAC1 Selected\n"); + dev = &g_dacdev1; + } + else +#endif +#ifdef CONFIG_STM32_DAC2 + if (intf == 2) + { + avdbg("DAC2 Selected\n"); + dev = &g_dac2dev; + } + else +#endif + { + adbg("No such DAC interface: %d\n", intf); + return NULL; + } + + /* Make sure that the DAC block has been initialized */ + + ret = dac_blockinit(); + if (ret < 0) + { + adbg("Failed to initialize the DAC block: %d\n", ret); + return ret; + } + + /* Configure the selected DAC channel */ + + chan = dev->ad_priv; + ret = dac_chaninit(chan); + if (ret < 0) + { + adbg("Failed to initialize DAC channel %d: %d\n", intf, ret); + return ret; + } + + return dev; +} + +#endif /* CONFIG_STM32_DAC1 || CONFIG_STM32_DAC2 */ +#endif /* CONFIG_DAC */ diff --git a/nuttx/arch/arm/src/stm32/stm32_dac.h b/nuttx/arch/arm/src/stm32/stm32_dac.h new file mode 100644 index 0000000000..44404e6fb3 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_dac.h @@ -0,0 +1,139 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_dac.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_DAC_H +#define __ARCH_ARM_SRC_STM32_STM32_DAC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" +#include "chip/stm32_dac.h" + +#include + +/************************************************************************************ + * Pre-processor definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* Timer devices may be used for different purposes. One special purpose is to + * control periodic DAC outputs. If CONFIG_STM32_TIMn is defined then + * CONFIG_STM32_TIMn_DAC must also be defined to indicate that timer "n" is intended + * to be used for that purpose. + */ + +#ifndef CONFIG_STM32_TIM1 +# undef CONFIG_STM32_TIM1_DAC +#endif +#ifndef CONFIG_STM32_TIM2 +# undef CONFIG_STM32_TIM2_DAC +#endif +#ifndef CONFIG_STM32_TIM3 +# undef CONFIG_STM32_TIM3_DAC +#endif +#ifndef CONFIG_STM32_TIM4 +# undef CONFIG_STM32_TIM4_DAC +#endif +#ifndef CONFIG_STM32_TIM5 +# undef CONFIG_STM32_TIM5_DAC +#endif +#ifndef CONFIG_STM32_TIM6 +# undef CONFIG_STM32_TIM6_DAC +#endif +#ifndef CONFIG_STM32_TIM7 +# undef CONFIG_STM32_TIM7_DAC +#endif +#ifndef CONFIG_STM32_TIM8 +# undef CONFIG_STM32_TIM8_DAC +#endif +#ifndef CONFIG_STM32_TIM9 +# undef CONFIG_STM32_TIM9_DAC +#endif +#ifndef CONFIG_STM32_TIM10 +# undef CONFIG_STM32_TIM10_DAC +#endif +#ifndef CONFIG_STM32_TIM11 +# undef CONFIG_STM32_TIM11_DAC +#endif +#ifndef CONFIG_STM32_TIM12 +# undef CONFIG_STM32_TIM12_DAC +#endif +#ifndef CONFIG_STM32_TIM13 +# undef CONFIG_STM32_TIM13_DAC +#endif +#ifndef CONFIG_STM32_TIM14 +# undef CONFIG_STM32_TIM14_DAC +#endif + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: stm32_dacinitialize + * + * Description: + * Initialize the DAC + * + * Input Parameters: + * intf - The DAC interface number. + * + * Returned Value: + * Valid dac device structure reference on succcess; a NULL on failure + * + ****************************************************************************/ + +struct dac_dev_s; +EXTERN FAR struct dac_dev_s *stm32_dacinitialize(int intf); + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_ARM_SRC_STM32_STM32_DAC_H */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_dbgmcu.h b/nuttx/arch/arm/src/stm32/stm32_dbgmcu.h new file mode 100644 index 0000000000..080f4bec5d --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_dbgmcu.h @@ -0,0 +1,64 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_dbgmcu.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_DBGMCU_H +#define __ARCH_ARM_SRC_STM32_STM32_DBGMCU_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" +#include "chip/stm32_dbgmcu.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32_STM32_DBGMCU_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_dma.c b/nuttx/arch/arm/src/stm32/stm32_dma.c new file mode 100644 index 0000000000..0dd8eb94e8 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_dma.c @@ -0,0 +1,80 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_dma.c + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* This file is only a thin shell that includes the correct DMA implementation + * for the selected STM32 family. The correct file cannot be selected by + * the make system because it needs the intelligence that only exists in + * chip.h that can associate an STM32 part number with an STM32 family. + * + * The STM32 F4 DMA differs from the F1 DMA primarily in that it adds the + * concept of "streams" that are used to associate DMA sources with DMA + * channels. + */ + +#if defined(CONFIG_STM32_STM32F10XX) +# include "stm32f10xxx_dma.c" +#elif defined(CONFIG_STM32_STM32F20XX) +# include "stm32f20xxx_dma.c" +#elif defined(CONFIG_STM32_STM32F40XX) +# include "stm32f40xxx_dma.c" +#endif diff --git a/nuttx/arch/arm/src/stm32/stm32_dma.h b/nuttx/arch/arm/src/stm32/stm32_dma.h new file mode 100644 index 0000000000..cccbc41f01 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_dma.h @@ -0,0 +1,309 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_dma.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_DMA_H +#define __ARCH_ARM_SRC_STM32_STM32_DMA_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +#include "chip.h" + +/* Include the correct DMA register definitions for this STM32 family */ + +#if defined(CONFIG_STM32_STM32F10XX) +# include "chip/stm32f10xxx_dma.h" +#elif defined(CONFIG_STM32_STM32F20XX) +# include "chip/stm32f20xxx_dma.h" +#elif defined(CONFIG_STM32_STM32F40XX) +# include "chip/stm32f40xxx_dma.h" +#else +# error "Unknown STM32 DMA" +#endif + +/* These definitions provide the bit encoding of the 'status' parameter passed to the + * DMA callback function (see dma_callback_t). + */ + +#if defined(CONFIG_STM32_STM32F10XX) +# define DMA_STATUS_FEIF 0 /* (Not available in F1) */ +# define DMA_STATUS_DMEIF 0 /* (Not available in F1) */ +# define DMA_STATUS_TEIF DMA_CHAN_TEIF_BIT /* Channel Transfer Error */ +# define DMA_STATUS_HTIF DMA_CHAN_HTIF_BIT /* Channel Half Transfer */ +# define DMA_STATUS_TCIF DMA_CHAN_TCIF_BIT /* Channel Transfer Complete */ +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define DMA_STATUS_FEIF 0 /* Stream FIFO error (ignored) */ +# define DMA_STATUS_DMEIF DMA_STREAM_DMEIF_BIT /* Stream direct mode error */ +# define DMA_STATUS_TEIF DMA_STREAM_TEIF_BIT /* Stream Transfer Error */ +# define DMA_STATUS_HTIF DMA_STREAM_HTIF_BIT /* Stream Half Transfer */ +# define DMA_STATUS_TCIF DMA_STREAM_TCIF_BIT /* Stream Transfer Complete */ +#endif + +#define DMA_STATUS_ERROR (DMA_STATUS_FEIF|DMA_STATUS_DMEIF|DMA_STATUS_TEIF) +#define DMA_STATUS_SUCCESS (DMA_STATUS_TCIF|DMA_STATUS_HTIF) + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/* DMA_HANDLE provides an opaque are reference that can be used to represent a DMA + * channel (F1) or a DMA stream (F4). + */ + +typedef FAR void *DMA_HANDLE; + +/* Description: + * This is the type of the callback that is used to inform the user of the the + * completion of the DMA. + * + * Input Parameters: + * handle - Refers tot he DMA channel or stream + * status - A bit encoded value that provides the completion status. See the + * DMASTATUS_* definitions above. + * arg - A user-provided value that was provided when stm32_dmastart() was + * called. + */ + +typedef void (*dma_callback_t)(DMA_HANDLE handle, uint8_t status, void *arg); + +#ifdef CONFIG_DEBUG_DMA +#if defined(CONFIG_STM32_STM32F10XX) +struct stm32_dmaregs_s +{ + uint32_t isr; + uint32_t ccr; + uint32_t cndtr; + uint32_t cpar; + uint32_t cmar; +}; +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +struct stm32_dmaregs_s +{ + uint32_t lisr; + uint32_t hisr; + uint32_t scr; + uint32_t sndtr; + uint32_t spar; + uint32_t sm0ar; + uint32_t sm1ar; + uint32_t sfcr; +}; +#else +# error "Unknown STM32 DMA" +#endif +#endif + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/**************************************************************************** + * Name: stm32_dmachannel + * + * Description: + * Allocate a DMA channel. This function gives the caller mutually + * exclusive access to the DMA channel specified by the 'chan' argument. + * DMA channels are shared on the STM32: Devices sharing the same DMA + * channel cannot do DMA concurrently! See the DMACHAN_* definitions in + * stm32_dma.h. + * + * If the DMA channel is not available, then stm32_dmachannel() will wait + * until the holder of the channel relinquishes the channel by calling + * stm32_dmafree(). WARNING: If you have two devices sharing a DMA + * channel and the code never releases the channel, the stm32_dmachannel + * call for the other will hang forever in this function! Don't let your + * design do that! + * + * Hmm.. I suppose this interface could be extended to make a non-blocking + * version. Feel free to do that if that is what you need. + * + * Input parameter: + * chan - Identifies the stream/channel resource + * For the STM32 F1, this is simply the channel number as provided by + * the DMACHAN_* definitions in chip/stm32f10xxx_dma.h. + * For the STM32 F4, this is a bit encoded value as provided by the + * the DMAMAP_* definitions in chip/stm32f40xxx_dma.h + * + * Returned Value: + * Provided that 'chan' is valid, this function ALWAYS returns a non-NULL, + * void* DMA channel handle. (If 'chan' is invalid, the function will + * assert if debug is enabled or do something ignorant otherwise). + * + * Assumptions: + * - The caller does not hold he DMA channel. + * - The caller can wait for the DMA channel to be freed if it is no + * available. + * + ****************************************************************************/ + +EXTERN DMA_HANDLE stm32_dmachannel(unsigned int chan); + +/**************************************************************************** + * Name: stm32_dmafree + * + * Description: + * Release a DMA channel. If another thread is waiting for this DMA channel + * in a call to stm32_dmachannel, then this function will re-assign the + * DMA channel to that thread and wake it up. NOTE: The 'handle' used + * in this argument must NEVER be used again until stm32_dmachannel() is + * called again to re-gain access to the channel. + * + * Returned Value: + * None + * + * Assumptions: + * - The caller holds the DMA channel. + * - There is no DMA in progress + * + ****************************************************************************/ + +EXTERN void stm32_dmafree(DMA_HANDLE handle); + +/**************************************************************************** + * Name: stm32_dmasetup + * + * Description: + * Configure DMA before using + * + ****************************************************************************/ + +EXTERN void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, + size_t ntransfers, uint32_t ccr); + +/**************************************************************************** + * Name: stm32_dmastart + * + * Description: + * Start the DMA transfer + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * - No DMA in progress + * + ****************************************************************************/ + +EXTERN void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, + void *arg, bool half); + +/**************************************************************************** + * Name: stm32_dmastop + * + * Description: + * Cancel the DMA. After stm32_dmastop() is called, the DMA channel is + * reset and stm32_dmasetup() must be called before stm32_dmastart() can be + * called again + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +EXTERN void stm32_dmastop(DMA_HANDLE handle); + +/**************************************************************************** + * Name: stm32_dmaresidual + * + * Description: + * Returns the number of bytes remaining to be transferred + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +EXTERN size_t stm32_dmaresidual(DMA_HANDLE handle); + +/**************************************************************************** + * Name: stm32_dmasample + * + * Description: + * Sample DMA register contents + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA +EXTERN void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs); +#else +# define stm32_dmasample(handle,regs) +#endif + +/**************************************************************************** + * Name: stm32_dmadump + * + * Description: + * Dump previously sampled DMA register contents + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA +EXTERN void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs, + const char *msg); +#else +# define stm32_dmadump(handle,regs,msg) +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_DMA_H */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_dumpgpio.c b/nuttx/arch/arm/src/stm32/stm32_dumpgpio.c new file mode 100644 index 0000000000..cd19338315 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_dumpgpio.c @@ -0,0 +1,179 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_gpio.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "up_arch.h" + +#include "chip.h" +#include "stm32_gpio.h" +#include "stm32_rcc.h" + +#ifdef CONFIG_DEBUG + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* Port letters for prettier debug output */ + +#ifdef CONFIG_DEBUG +static const char g_portchar[STM32_NGPIO_PORTS] = +{ +#if STM32_NGPIO_PORTS > 9 +# error "Additional support required for this number of GPIOs" +#elif STM32_NGPIO_PORTS > 8 + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I' +#elif STM32_NGPIO_PORTS > 7 + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' +#elif STM32_NGPIO_PORTS > 6 + 'A', 'B', 'C', 'D', 'E', 'F', 'G' +#elif STM32_NGPIO_PORTS > 5 + 'A', 'B', 'C', 'D', 'E', 'F' +#elif STM32_NGPIO_PORTS > 4 + 'A', 'B', 'C', 'D', 'E' +#elif STM32_NGPIO_PORTS > 3 + 'A', 'B', 'C', 'D' +#elif STM32_NGPIO_PORTS > 2 + 'A', 'B', 'C' +#elif STM32_NGPIO_PORTS > 1 + 'A', 'B' +#elif STM32_NGPIO_PORTS > 0 + 'A' +#else +# error "Bad number of GPIOs" +#endif +}; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: stm32_dumpgpio + * + * Description: + * Dump all GPIO registers associated with the provided base address + * + ****************************************************************************/ + +int stm32_dumpgpio(uint32_t pinset, const char *msg) +{ + irqstate_t flags; + uint32_t base; + unsigned int port; + unsigned int pin; + + /* Get the base address associated with the GPIO port */ + + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + base = g_gpiobase[port]; + + /* The following requires exclusive access to the GPIO registers */ + + flags = irqsave(); +#if defined(CONFIG_STM32_STM32F10XX) + lldbg("GPIO%c pinset: %08x base: %08x -- %s\n", + g_portchar[port], pinset, base, msg); + if ((getreg32(STM32_RCC_APB2ENR) & RCC_APB2ENR_IOPEN(port)) != 0) + { + lldbg(" CR: %08x %08x IDR: %04x ODR: %04x LCKR: %04x\n", + getreg32(base + STM32_GPIO_CRH_OFFSET), + getreg32(base + STM32_GPIO_CRL_OFFSET), + getreg32(base + STM32_GPIO_IDR_OFFSET), + getreg32(base + STM32_GPIO_ODR_OFFSET), + getreg32(base + STM32_GPIO_LCKR_OFFSET)); + lldbg(" EVCR: %02x MAPR: %08x CR: %04x %04x %04x %04x\n", + getreg32(STM32_AFIO_EVCR), getreg32(STM32_AFIO_MAPR), + getreg32(STM32_AFIO_EXTICR1), + getreg32(STM32_AFIO_EXTICR2), + getreg32(STM32_AFIO_EXTICR3), + getreg32(STM32_AFIO_EXTICR4)); + } + else + { + lldbg(" GPIO%c not enabled: APB2ENR: %08x\n", + g_portchar[port], getreg32(STM32_RCC_APB2ENR)); + } +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + DEBUGASSERT(port < STM32_NGPIO_PORTS); + + lldbg("GPIO%c pinset: %08x base: %08x -- %s\n", + g_portchar[port], pinset, base, msg); + if ((getreg32(STM32_RCC_AHB1ENR) & RCC_AHB1ENR_GPIOEN(port)) != 0) + { + lldbg(" MODE: %08x OTYPE: %04x OSPEED: %08x PUPDR: %08x\n", + getreg32(base + STM32_GPIO_MODER_OFFSET), + getreg32(base + STM32_GPIO_OTYPER_OFFSET), + getreg32(base + STM32_GPIO_OSPEED_OFFSET), + getreg32(base + STM32_GPIO_PUPDR_OFFSET)); + lldbg(" IDR: %04x ODR: %04x BSRR: %08x LCKR: %04x\n", + getreg32(base + STM32_GPIO_IDR_OFFSET), + getreg32(base + STM32_GPIO_ODR_OFFSET), + getreg32(base + STM32_GPIO_BSRR_OFFSET), + getreg32(base + STM32_GPIO_LCKR_OFFSET)); + lldbg(" AFRH: %08x AFRL: %08x\n", + getreg32(base + STM32_GPIO_ARFH_OFFSET), + getreg32(base + STM32_GPIO_AFRL_OFFSET)); + } + else + { + lldbg(" GPIO%c not enabled: AHB1ENR: %08x\n", + g_portchar[port], getreg32(STM32_RCC_AHB1ENR)); + } +#else +# error "Unsupported STM32 chip" +#endif + irqrestore(flags); + return OK; +} + +#endif /* CONFIG_DEBUG */ diff --git a/nuttx/arch/arm/src/stm32/stm32_eth.c b/nuttx/arch/arm/src/stm32/stm32_eth.c new file mode 100644 index 0000000000..68ee78fd5f --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_eth.c @@ -0,0 +1,3109 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_eth.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_STM32_ETHMAC) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "up_internal.h" + +#include "chip.h" +#include "stm32_gpio.h" +#include "stm32_rcc.h" +#include "stm32_syscfg.h" +#include "stm32_eth.h" + +#include + +/* STM32_NETHERNET determines the number of physical interfaces + * that will be supported. + */ + +#if STM32_NETHERNET > 0 + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* See configs/stm3240g-eval/README.txt for an explanation of the configuration + * settings. + */ + +#if STM32_NETHERNET > 1 +# error "Logic to support multiple Ethernet interfaces is incomplete" +#endif + +#ifndef CONFIG_STM32_SYSCFG +# error "CONFIG_STM32_SYSCFG must be defined in the NuttX configuration" +#endif + +#ifndef CONFIG_STM32_PHYADDR +# error "CONFIG_STM32_PHYADDR must be defined in the NuttX configuration" +#endif + +#if !defined(CONFIG_STM32_MII) && !defined(CONFIG_STM32_RMII) +# warning "Neither CONFIG_STM32_MII nor CONFIG_STM32_RMII defined" +#endif + +#if defined(CONFIG_STM32_MII) && defined(CONFIG_STM32_RMII) +# error "Both CONFIG_STM32_MII and CONFIG_STM32_RMII defined" +#endif + +#ifdef CONFIG_STM32_MII +# if !defined(CONFIG_STM32_MII_MCO1) && !defined(CONFIG_STM32_MII_MCO2) +# warning "Neither CONFIG_STM32_MII_MCO1 nor CONFIG_STM32_MII_MCO2 defined" +# endif +# if defined(CONFIG_STM32_MII_MCO1) && defined(CONFIG_STM32_MII_MCO2) +# error "Both CONFIG_STM32_MII_MCO1 and CONFIG_STM32_MII_MCO2 defined" +# endif +#endif + +#ifdef CONFIG_STM32_AUTONEG +# ifndef CONFIG_STM32_PHYSR +# error "CONFIG_STM32_PHYSR must be defined in the NuttX configuration" +# endif +# ifndef CONFIG_STM32_PHYSR_SPEED +# error "CONFIG_STM32_PHYSR_SPEED must be defined in the NuttX configuration" +# endif +# ifndef CONFIG_STM32_PHYSR_100MBPS +# error "CONFIG_STM32_PHYSR_100MBPS must be defined in the NuttX configuration" +# endif +# ifndef CONFIG_STM32_PHYSR_MODE +# error "CONFIG_STM32_PHYSR_MODE must be defined in the NuttX configuration" +# endif +# ifndef CONFIG_STM32_PHYSR_FULLDUPLEX +# error "CONFIG_STM32_PHYSR_FULLDUPLEX must be defined in the NuttX configuration" +# endif +#endif + +#ifdef CONFIG_STM32_ETH_PTP +# warning "CONFIG_STM32_ETH_PTP is not yet supported" +#endif + +/* This driver does not use enhanced descriptors. Enhanced descriptors must + * be used, however, if time stamping or and/or IPv4 checksum offload is + * supported. + */ + +#undef CONFIG_STM32_ETH_ENHANCEDDESC +#undef CONFIG_STM32_ETH_HWCHECKSUM + +/* Ethernet buffer sizes, number of buffers, and number of descriptors */ + +#ifndef CONFIG_NET_MULTIBUFFER +# error "CONFIG_NET_MULTIBUFFER is required" +#endif + +/* Add 4 to the configured buffer size to account for the 2 byte checksum + * memory needed at the end of the maximum size packet. + */ + +#define OPTIMAL_ETH_BUFSIZE (CONFIG_NET_BUFSIZE+4) + +#ifndef CONFIG_STM32_ETH_BUFSIZE +# define CONFIG_STM32_ETH_BUFSIZE OPTIMAL_ETH_BUFSIZE +#endif + +#if CONFIG_STM32_ETH_BUFSIZE > ETH_TDES1_TBS1_MASK +# error "CONFIG_STM32_ETH_BUFSIZE is too large" +#endif + +#if CONFIG_STM32_ETH_BUFSIZE != OPTIMAL_ETH_BUFSIZE +# warning "You using an incomplete/untested configuration" +#endif + +#ifndef CONFIG_STM32_ETH_NRXDESC +# define CONFIG_STM32_ETH_NRXDESC 8 +#endif +#ifndef CONFIG_STM32_ETH_NTXDESC +# define CONFIG_STM32_ETH_NTXDESC 4 +#endif + +/* We need at least one more free buffer than transmit buffers */ + +#define STM32_ETH_NFREEBUFFERS (CONFIG_STM32_ETH_NTXDESC+1) + +/* Extremely detailed register debug that you would normally never want + * enabled. + */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_STM32_ETHMAC_REGDEBUG +#endif + +/* Clocking *****************************************************************/ +/* Set MACMIIAR CR bits depending on HCLK setting */ + +#if STM32_HCLK_FREQUENCY >= 20000000 && STM32_HCLK_FREQUENCY < 35000000 +# define ETH_MACMIIAR_CR ETH_MACMIIAR_CR_20_35 +#elif STM32_HCLK_FREQUENCY >= 35000000 && STM32_HCLK_FREQUENCY < 60000000 +# define ETH_MACMIIAR_CR ETH_MACMIIAR_CR_35_60 +#elif STM32_HCLK_FREQUENCY >= 60000000 && STM32_HCLK_FREQUENCY < 100000000 +# define ETH_MACMIIAR_CR ETH_MACMIIAR_CR_60_100 +#elif STM32_HCLK_FREQUENCY >= 100000000 && STM32_HCLK_FREQUENCY < 150000000 +# define ETH_MACMIIAR_CR ETH_MACMIIAR_CR_100_150 +#elif STM32_HCLK_FREQUENCY >= 150000000 && STM32_HCLK_FREQUENCY <= 168000000 +# define ETH_MACMIIAR_CR ETH_MACMIIAR_CR_150_168 +#else +# error "STM32_HCLK_FREQUENCY not supportable" +#endif + +/* Timing *******************************************************************/ +/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per + * second + */ + +#define STM32_WDDELAY (1*CLK_TCK) +#define STM32_POLLHSEC (1*2) + +/* TX timeout = 1 minute */ + +#define STM32_TXTIMEOUT (60*CLK_TCK) + +/* PHY reset/configuration delays in milliseconds */ + +#define PHY_RESET_DELAY (65) +#define PHY_CONFIG_DELAY (1000) + +/* PHY read/write delays in loop counts */ + +#define PHY_READ_TIMEOUT (0x0004ffff) +#define PHY_WRITE_TIMEOUT (0x0004ffff) +#define PHY_RETRY_TIMEOUT (0x0004ffff) + +/* Register values **********************************************************/ + +/* Clear the MACCR bits that will be setup during MAC initialization (or that + * are cleared unconditionally). Per the reference manual, all reserved bits + * must be retained at their reset value. + * + * ETH_MACCR_RE Bit 2: Receiver enable + * ETH_MACCR_TE Bit 3: Transmitter enable + * ETH_MACCR_DC Bit 4: Deferral check + * ETH_MACCR_BL Bits 5-6: Back-off limit + * ETH_MACCR_APCS Bit 7: Automatic pad/CRC stripping + * ETH_MACCR_RD Bit 9: Retry disable + * ETH_MACCR_IPCO Bit 10: IPv4 checksum offload + * ETH_MACCR_DM Bit 11: Duplex mode + * ETH_MACCR_LM Bit 12: Loopback mode + * ETH_MACCR_ROD Bit 13: Receive own disable + * ETH_MACCR_FES Bit 14: Fast Ethernet speed + * ETH_MACCR_CSD Bit 16: Carrier sense disable + * ETH_MACCR_IFG Bits 17-19: Interframe gap + * ETH_MACCR_JD Bit 22: Jabber disable + * ETH_MACCR_WD Bit 23: Watchdog disable + * ETH_MACCR_CSTF Bits 25: CRC stripping for Type frames + */ + +#define MACCR_CLEAR_BITS \ + ( ETH_MACCR_RE | ETH_MACCR_TE | ETH_MACCR_DC | ETH_MACCR_BL_MASK | \ + ETH_MACCR_APCS | ETH_MACCR_RD | ETH_MACCR_IPCO | ETH_MACCR_DM | \ + ETH_MACCR_LM | ETH_MACCR_ROD | ETH_MACCR_FES | ETH_MACCR_CSD | \ + ETH_MACCR_IFG_MASK | ETH_MACCR_JD | ETH_MACCR_WD | ETH_MACCR_CSTF ) + +/* The following bits are set or left zero unconditionally in all modes. + * + * ETH_MACCR_RE Receiver enable 0 (disabled) + * ETH_MACCR_TE Transmitter enable 0 (disabled) + * ETH_MACCR_DC Deferral check 0 (disabled) + * ETH_MACCR_BL Back-off limit 0 (10) + * ETH_MACCR_APCS Automatic pad/CRC stripping 0 (disabled) + * ETH_MACCR_RD Retry disable 1 (disabled) + * ETH_MACCR_IPCO IPv4 checksum offload Depends on CONFIG_STM32_ETH_HWCHECKSUM + * ETH_MACCR_LM Loopback mode 0 (disabled) + * ETH_MACCR_ROD Receive own disable 0 (enabled) + * ETH_MACCR_CSD Carrier sense disable 0 (enabled) + * ETH_MACCR_IFG Interframe gap 0 (96 bits) + * ETH_MACCR_JD Jabber disable 0 (enabled) + * ETH_MACCR_WD Watchdog disable 0 (enabled) + * ETH_MACCR_CSTF CRC stripping for Type frames 0 (disabled) + * + * The following are set conditioinally based on mode and speed. + * + * ETH_MACCR_DM Duplex mode Depends on priv->fduplex + * ETH_MACCR_FES Fast Ethernet speed Depends on priv->mbps100 + */ + +#ifdef CONFIG_STM32_ETH_HWCHECKSUM +# define MACCR_SET_BITS \ + (ETH_MACCR_BL_10 | ETH_MACCR_RD | ETH_MACCR_IPCO | ETH_MACCR_IFG(96)) +#else +# define MACCR_SET_BITS \ + (ETH_MACCR_BL_10 | ETH_MACCR_RD | ETH_MACCR_IFG(96)) +#endif + +/* Clear the MACCR bits that will be setup during MAC initialization (or that + * are cleared unconditionally). Per the reference manual, all reserved bits + * must be retained at their reset value. + * + * ETH_MACFFR_PM Bit 0: Promiscuous mode + * ETH_MACFFR_HU Bit 1: Hash unicast + * ETH_MACFFR_HM Bit 2: Hash multicast + * ETH_MACFFR_DAIF Bit 3: Destination address inverse filtering + * ETH_MACFFR_PAM Bit 4: Pass all multicast + * ETH_MACFFR_BFD Bit 5: Broadcast frames disable + * ETH_MACFFR_PCF Bits 6-7: Pass control frames + * ETH_MACFFR_SAIF Bit 8: Source address inverse filtering + * ETH_MACFFR_SAF Bit 9: Source address filter + * ETH_MACFFR_HPF Bit 10: Hash or perfect filter + * ETH_MACFFR_RA Bit 31: Receive all + */ + +#define MACFFR_CLEAR_BITS \ + (ETH_MACFFR_PM | ETH_MACFFR_HU | ETH_MACFFR_HM | ETH_MACFFR_DAIF | \ + ETH_MACFFR_PAM | ETH_MACFFR_BFD | ETH_MACFFR_PCF_MASK | ETH_MACFFR_SAIF | \ + ETH_MACFFR_SAF | ETH_MACFFR_HPF | ETH_MACFFR_RA) + +/* The following bits are set or left zero unconditionally in all modes. + * + * ETH_MACFFR_PM Promiscuous mode 0 (disabled) + * ETH_MACFFR_HU Hash unicast 0 (perfect dest filtering) + * ETH_MACFFR_HM Hash multicast 0 (perfect dest filtering) + * ETH_MACFFR_DAIF Destination address inverse filtering 0 (normal) + * ETH_MACFFR_PAM Pass all multicast 0 (Depends on HM bit) + * ETH_MACFFR_BFD Broadcast frames disable 0 (enabled) + * ETH_MACFFR_PCF Pass control frames 1 (block all but PAUSE) + * ETH_MACFFR_SAIF Source address inverse filtering 0 (not used) + * ETH_MACFFR_SAF Source address filter 0 (disabled) + * ETH_MACFFR_HPF Hash or perfect filter 0 (Only matching frames passed) + * ETH_MACFFR_RA Receive all 0 (disabled) + */ + +#define MACFFR_SET_BITS (ETH_MACFFR_PCF_PAUSE) + +/* Clear the MACFCR bits that will be setup during MAC initialization (or that + * are cleared unconditionally). Per the reference manual, all reserved bits + * must be retained at their reset value. + * + * ETH_MACFCR_FCB_BPA Bit 0: Flow control busy/back pressure activate + * ETH_MACFCR_TFCE Bit 1: Transmit flow control enable + * ETH_MACFCR_RFCE Bit 2: Receive flow control enable + * ETH_MACFCR_UPFD Bit 3: Unicast pause frame detect + * ETH_MACFCR_PLT Bits 4-5: Pause low threshold + * ETH_MACFCR_ZQPD Bit 7: Zero-quanta pause disable + * ETH_MACFCR_PT Bits 16-31: Pause time + */ + +#define MACFCR_CLEAR_MASK \ + (ETH_MACFCR_FCB_BPA | ETH_MACFCR_TFCE | ETH_MACFCR_RFCE | ETH_MACFCR_UPFD | \ + ETH_MACFCR_PLT_MASK | ETH_MACFCR_ZQPD | ETH_MACFCR_PT_MASK) + +/* The following bits are set or left zero unconditionally in all modes. + * + * ETH_MACFCR_FCB_BPA Flow control busy/back pressure activate 0 (no pause control frame) + * ETH_MACFCR_TFCE Transmit flow control enable 0 (disabled) + * ETH_MACFCR_RFCE Receive flow control enable 0 (disabled) + * ETH_MACFCR_UPFD Unicast pause frame detect 0 (disabled) + * ETH_MACFCR_PLT Pause low threshold 0 (pause time - 4) + * ETH_MACFCR_ZQPD Zero-quanta pause disable 1 (disabled) + * ETH_MACFCR_PT Pause time 0 + */ + +#define MACFCR_SET_MASK (ETH_MACFCR_PLT_M4 | ETH_MACFCR_ZQPD) + +/* Clear the DMAOMR bits that will be setup during MAC initialization (or that + * are cleared unconditionally). Per the reference manual, all reserved bits + * must be retained at their reset value. + * + * ETH_DMAOMR_SR Bit 1: Start/stop receive + * TH_DMAOMR_OSF Bit 2: Operate on second frame + * ETH_DMAOMR_RTC Bits 3-4: Receive threshold control + * ETH_DMAOMR_FUGF Bit 6: Forward undersized good frames + * ETH_DMAOMR_FEF Bit 7: Forward error frames + * ETH_DMAOMR_ST Bit 13: Start/stop transmission + * ETH_DMAOMR_TTC Bits 14-16: Transmit threshold control + * ETH_DMAOMR_FTF Bit 20: Flush transmit FIFO + * ETH_DMAOMR_TSF Bit 21: Transmit store and forward + * ETH_DMAOMR_DFRF Bit 24: Disable flushing of received frames + * ETH_DMAOMR_RSF Bit 25: Receive store and forward + * TH_DMAOMR_DTCEFD Bit 26: Dropping of TCP/IP checksum error frames disable + */ + +#define DMAOMR_CLEAR_MASK \ + (ETH_DMAOMR_SR | ETH_DMAOMR_OSF | ETH_DMAOMR_RTC_MASK | ETH_DMAOMR_FUGF | \ + ETH_DMAOMR_FEF | ETH_DMAOMR_ST | ETH_DMAOMR_TTC_MASK | ETH_DMAOMR_FTF | \ + ETH_DMAOMR_TSF | ETH_DMAOMR_DFRF | ETH_DMAOMR_RSF | ETH_DMAOMR_DTCEFD) + +/* The following bits are set or left zero unconditionally in all modes. + * + * ETH_DMAOMR_SR Start/stop receive 0 (not running) + * TH_DMAOMR_OSF Operate on second frame 1 (enabled) + * ETH_DMAOMR_RTC Receive threshold control 0 (64 bytes) + * ETH_DMAOMR_FUGF Forward undersized good frames 0 (disabled) + * ETH_DMAOMR_FEF Forward error frames 0 (disabled) + * ETH_DMAOMR_ST Start/stop transmission 0 (not running) + * ETH_DMAOMR_TTC Transmit threshold control 0 (64 bytes) + * ETH_DMAOMR_FTF Flush transmit FIFO 0 (no flush) + * ETH_DMAOMR_TSF Transmit store and forward Depends on CONFIG_STM32_ETH_HWCHECKSUM + * ETH_DMAOMR_DFRF Disable flushing of received frames 0 (enabled) + * ETH_DMAOMR_RSF Receive store and forward Depends on CONFIG_STM32_ETH_HWCHECKSUM + * TH_DMAOMR_DTCEFD Dropping of TCP/IP checksum error Depends on CONFIG_STM32_ETH_HWCHECKSUM + * frames disable + * + * When the checksum offload feature is enabled, we need to enable the Store + * and Forward mode: the store and forward guarantee that a whole frame is + * stored in the FIFO, so the MAC can insert/verify the checksum, if the + * checksum is OK the DMA can handle the frame otherwise the frame is dropped + */ + +#if CONFIG_STM32_ETH_HWCHECKSUM +# define DMAOMR_SET_MASK \ + (ETH_DMAOMR_OSF | ETH_DMAOMR_RTC_64 | ETH_DMAOMR_TTC_64 | \ + ETH_DMAOMR_TSF | ETH_DMAOMR_RSF) +#else +# define DMAOMR_SET_MASK \ + (ETH_DMAOMR_OSF | ETH_DMAOMR_RTC_64 | ETH_DMAOMR_TTC_64 | \ + ETH_DMAOMR_DTCEFD) +#endif + +/* Clear the DMABMR bits that will be setup during MAC initialization (or that + * are cleared unconditionally). Per the reference manual, all reserved bits + * must be retained at their reset value. + * + * ETH_DMABMR_SR Bit 0: Software reset + * ETH_DMABMR_DA Bit 1: DMA Arbitration + * ETH_DMABMR_DSL Bits 2-6: Descriptor skip length + * ETH_DMABMR_EDFE Bit 7: Enhanced descriptor format enable + * ETH_DMABMR_PBL Bits 8-13: Programmable burst length + * ETH_DMABMR_RTPR Bits 14-15: RX TX priority ratio + * ETH_DMABMR_FB Bit 16: Fixed burst + * ETH_DMABMR_RDP Bits 17-22: RX DMA PBL + * ETH_DMABMR_USP Bit 23: Use separate PBL + * ETH_DMABMR_FPM Bit 24: 4xPBL mode + * ETH_DMABMR_AAB Bit 25: Address-aligned beats + * ETH_DMABMR_MB Bit 26: Mixed burst + */ + +#define DMABMR_CLEAR_MASK \ + (ETH_DMABMR_SR | ETH_DMABMR_DA | ETH_DMABMR_DSL_MASK | ETH_DMABMR_EDFE | \ + ETH_DMABMR_PBL_MASK | ETH_DMABMR_RTPR_MASK | ETH_DMABMR_FB | ETH_DMABMR_RDP_MASK | \ + ETH_DMABMR_USP | ETH_DMABMR_FPM | ETH_DMABMR_AAB | ETH_DMABMR_MB) + +/* The following bits are set or left zero unconditionally in all modes. + * + * + * ETH_DMABMR_SR Software reset 0 (no reset) + * ETH_DMABMR_DA DMA Arbitration 0 (round robin) + * ETH_DMABMR_DSL Descriptor skip length 0 + * ETH_DMABMR_EDFE Enhanced descriptor format enable Depends on CONFIG_STM32_ETH_ENHANCEDDESC + * ETH_DMABMR_PBL Programmable burst length 32 beats + * ETH_DMABMR_RTPR RX TX priority ratio 2:1 + * ETH_DMABMR_FB Fixed burst 1 (enabled) + * ETH_DMABMR_RDP RX DMA PBL 32 beats + * ETH_DMABMR_USP Use separate PBL 1 (enabled) + * ETH_DMABMR_FPM 4xPBL mode 0 (disabled) + * ETH_DMABMR_AAB Address-aligned beats 1 (enabled) + * ETH_DMABMR_MB Mixed burst 0 (disabled) + */ + +#ifdef CONFIG_STM32_ETH_ENHANCEDDESC +# define DMABMR_SET_MASK \ + (ETH_DMABMR_DSL(0) | ETH_DMABMR_PBL(32) | ETH_DMABMR_EDFE | ETH_DMABMR_RTPR_2TO1 | \ + ETH_DMABMR_FB | ETH_DMABMR_RDP(32) | ETH_DMABMR_USP | ETH_DMABMR_AAB) +#else +# define DMABMR_SET_MASK \ + (ETH_DMABMR_DSL(0) | ETH_DMABMR_PBL(32) | ETH_DMABMR_RTPR_2TO1 | ETH_DMABMR_FB | \ + ETH_DMABMR_RDP(32) | ETH_DMABMR_USP | ETH_DMABMR_AAB) +#endif + +/* Interrupt bit sets *******************************************************/ +/* All interrupts in the normal and abnormal interrupt summary. Early transmit + * interrupt (ETI) is excluded from the abnormal set because it causes too + * many interrupts and is not interesting. + */ + +#define ETH_DMAINT_NORMAL \ + (ETH_DMAINT_TI | ETH_DMAINT_TBUI |ETH_DMAINT_RI | ETH_DMAINT_ERI) + +#define ETH_DMAINT_ABNORMAL \ + (ETH_DMAINT_TPSI | ETH_DMAINT_TJTI | ETH_DMAINT_ROI | ETH_DMAINT_TUI | \ + ETH_DMAINT_RBUI | ETH_DMAINT_RPSI | ETH_DMAINT_RWTI | /* ETH_DMAINT_ETI | */ \ + ETH_DMAINT_FBEI) + +/* Normal receive, transmit, error interrupt enable bit sets */ + +#define ETH_DMAINT_RECV_ENABLE (ETH_DMAINT_NIS | ETH_DMAINT_RI) +#define ETH_DMAINT_XMIT_ENABLE (ETH_DMAINT_NIS | ETH_DMAINT_TI) +#define ETH_DMAINT_XMIT_DISABLE (ETH_DMAINT_TI) + +#ifdef CONFIG_DEBUG_NET +# define ETH_DMAINT_ERROR_ENABLE (ETH_DMAINT_AIS | ETH_DMAINT_ABNORMAL) +#else +# define ETH_DMAINT_ERROR_ENABLE (0) +#endif + +/* Helpers ******************************************************************/ +/* This is a helper pointer for accessing the contents of the Ethernet + * header + */ + +#define BUF ((struct uip_eth_hdr *)priv->dev.d_buf) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The stm32_ethmac_s encapsulates all state information for a single hardware + * interface + */ + +struct stm32_ethmac_s +{ + uint8_t ifup : 1; /* true:ifup false:ifdown */ + uint8_t mbps100 : 1; /* 100MBps operation (vs 10 MBps) */ + uint8_t fduplex : 1; /* Full (vs. half) duplex */ + WDOG_ID txpoll; /* TX poll timer */ + WDOG_ID txtimeout; /* TX timeout timer */ + + /* This holds the information visible to uIP/NuttX */ + + struct uip_driver_s dev; /* Interface understood by uIP */ + + /* Used to track transmit and receive descriptors */ + + struct eth_txdesc_s *txhead; /* Next available TX descriptor */ + struct eth_rxdesc_s *rxhead; /* Next available RX descriptor */ + + struct eth_txdesc_s *txtail; /* First "in_flight" TX descriptor */ + struct eth_rxdesc_s *rxcurr; /* First RX descriptor of the segment */ + uint16_t segments; /* RX segment count */ + uint16_t inflight; /* Number of TX transfers "in_flight" */ + sq_queue_t freeb; /* The free buffer list */ + + /* Descriptor allocations */ + + struct eth_rxdesc_s rxtable[CONFIG_STM32_ETH_NRXDESC]; + struct eth_txdesc_s txtable[CONFIG_STM32_ETH_NTXDESC]; + + /* Buffer allocations */ + + uint8_t rxbuffer[CONFIG_STM32_ETH_NRXDESC*CONFIG_STM32_ETH_BUFSIZE]; + uint8_t alloc[STM32_ETH_NFREEBUFFERS*CONFIG_STM32_ETH_BUFSIZE]; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct stm32_ethmac_s g_stm32ethmac[STM32_NETHERNET]; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* Register operations ******************************************************/ + +#if defined(CONFIG_STM32_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG) +static uint32_t stm32_getreg(uint32_t addr); +static void stm32_putreg(uint32_t val, uint32_t addr); +static void stm32_checksetup(void); +#else +# define stm32_getreg(addr) getreg32(addr) +# define stm32_putreg(val,addr) putreg32(val,addr) +# define stm32_checksetup() +#endif + +/* Free buffer management */ + +static void stm32_initbuffer(FAR struct stm32_ethmac_s *priv); +static inline uint8_t *stm32_allocbuffer(FAR struct stm32_ethmac_s *priv); +static inline void stm32_freebuffer(FAR struct stm32_ethmac_s *priv, uint8_t *buffer); +static inline bool stm32_isfreebuffer(FAR struct stm32_ethmac_s *priv); + +/* Common TX logic */ + +static int stm32_transmit(FAR struct stm32_ethmac_s *priv); +static int stm32_uiptxpoll(struct uip_driver_s *dev); +static void stm32_dopoll(FAR struct stm32_ethmac_s *priv); + +/* Interrupt handling */ + +static void stm32_enableint(FAR struct stm32_ethmac_s *priv, uint32_t ierbit); +static void stm32_disableint(FAR struct stm32_ethmac_s *priv, uint32_t ierbit); + +static void stm32_freesegment(FAR struct stm32_ethmac_s *priv, + FAR struct eth_rxdesc_s *rxfirst, int segments); +static int stm32_recvframe(FAR struct stm32_ethmac_s *priv); +static void stm32_receive(FAR struct stm32_ethmac_s *priv); +static void stm32_freeframe(FAR struct stm32_ethmac_s *priv); +static void stm32_txdone(FAR struct stm32_ethmac_s *priv); +static int stm32_interrupt(int irq, FAR void *context); + +/* Watchdog timer expirations */ + +static void stm32_polltimer(int argc, uint32_t arg, ...); +static void stm32_txtimeout(int argc, uint32_t arg, ...); + +/* NuttX callback functions */ + +static int stm32_ifup(struct uip_driver_s *dev); +static int stm32_ifdown(struct uip_driver_s *dev); +static int stm32_txavail(struct uip_driver_s *dev); +#ifdef CONFIG_NET_IGMP +static int stm32_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +static int stm32_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +#endif + +/* Descriptor Initialization */ + +static void stm32_txdescinit(FAR struct stm32_ethmac_s *priv); +static void stm32_rxdescinit(FAR struct stm32_ethmac_s *priv); + +/* PHY Initialization */ + +static int stm32_phyread(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t *value); +static int stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t value); +static int stm32_phyinit(FAR struct stm32_ethmac_s *priv); + +/* MAC/DMA Initialization */ + +static inline void stm32_ethgpioconfig(FAR struct stm32_ethmac_s *priv); +static void stm32_ethreset(FAR struct stm32_ethmac_s *priv); +static int stm32_macconfig(FAR struct stm32_ethmac_s *priv); +static void stm32_macaddress(FAR struct stm32_ethmac_s *priv); +static int stm32_macenable(FAR struct stm32_ethmac_s *priv); +static int stm32_ethconfig(FAR struct stm32_ethmac_s *priv); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: stm32_getreg + * + * Description: + * This function may to used to intercept an monitor all register accesses. + * Clearly this is nothing you would want to do unless you are debugging + * this driver. + * + * Input Parameters: + * addr - The register address to read + * + * Returned Value: + * The value read from the register + * + ****************************************************************************/ + +#if defined(CONFIG_STM32_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG) +static uint32_t stm32_getreg(uint32_t addr) +{ + static uint32_t prevaddr = 0; + static uint32_t preval = 0; + static uint32_t count = 0; + + /* Read the value from the register */ + + uint32_t val = getreg32(addr); + + /* Is this the same value that we read from the same register last time? + * Are we polling the register? If so, suppress some of the output. + */ + + if (addr == prevaddr && val == preval) + { + if (count == 0xffffffff || ++count > 3) + { + if (count == 4) + { + lldbg("...\n"); + } + return val; + } + } + + /* No this is a new address or value */ + + else + { + /* Did we print "..." for the previous value? */ + + if (count > 3) + { + /* Yes.. then show how many times the value repeated */ + + lldbg("[repeats %d more times]\n", count-3); + } + + /* Save the new address, value, and count */ + + prevaddr = addr; + preval = val; + count = 1; + } + + /* Show the register value read */ + + lldbg("%08x->%08x\n", addr, val); + return val; +} +#endif + +/**************************************************************************** + * Name: stm32_putreg + * + * Description: + * This function may to used to intercept an monitor all register accesses. + * Clearly this is nothing you would want to do unless you are debugging + * this driver. + * + * Input Parameters: + * val - The value to write to the register + * addr - The register address to read + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_STM32_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG) +static void stm32_putreg(uint32_t val, uint32_t addr) +{ + /* Show the register value being written */ + + lldbg("%08x<-%08x\n", addr, val); + + /* Write the value */ + + putreg32(val, addr); +} +#endif + +/**************************************************************************** + * Name: stm32_checksetup + * + * Description: + * Show the state of critical configuration registers. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_STM32_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG) +static void stm32_checksetup(void) +{ +} +#endif + +/**************************************************************************** + * Function: stm32_initbuffer + * + * Description: + * Initialize the free buffer list. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called during early driver initialization before Ethernet interrupts + * are enabled. + * + ****************************************************************************/ + +static void stm32_initbuffer(FAR struct stm32_ethmac_s *priv) +{ + uint8_t *buffer; + int i; + + /* Initialize the head of the free buffer list */ + + sq_init(&priv->freeb); + + /* Add all of the pre-allocated buffers to the free buffer list */ + + for (i = 0, buffer = priv->alloc; + i < STM32_ETH_NFREEBUFFERS; + i++, buffer += CONFIG_STM32_ETH_BUFSIZE) + { + sq_addlast((FAR sq_entry_t *)buffer, &priv->freeb); + } +} + +/**************************************************************************** + * Function: stm32_allocbuffer + * + * Description: + * Allocate one buffer from the free buffer list. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * Pointer to the allocated buffer on success; NULL on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static inline uint8_t *stm32_allocbuffer(FAR struct stm32_ethmac_s *priv) +{ + /* Allocate a buffer by returning the head of the free buffer list */ + + return (uint8_t *)sq_remfirst(&priv->freeb); +} + +/**************************************************************************** + * Function: stm32_freebuffer + * + * Description: + * Return a buffer to the free buffer list. + * + * Parameters: + * priv - Reference to the driver state structure + * buffer - A pointer to the buffer to be freed + * + * Returned Value: + * None + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static inline void stm32_freebuffer(FAR struct stm32_ethmac_s *priv, uint8_t *buffer) +{ + /* Free the buffer by adding it to to the end of the free buffer list */ + + sq_addlast((FAR sq_entry_t *)buffer, &priv->freeb); +} + +/**************************************************************************** + * Function: stm32_isfreebuffer + * + * Description: + * Return TRUE if the free buffer list is not empty. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * True if there are one or more buffers in the free buffer list; + * false if the free buffer list is empty + * + * Assumptions: + * None. + * + ****************************************************************************/ + +static inline bool stm32_isfreebuffer(FAR struct stm32_ethmac_s *priv) +{ + /* Return TRUE if the free buffer list is not empty */ + + return !sq_empty(&priv->freeb); +} + +/**************************************************************************** + * Function: stm32_transmit + * + * Description: + * Start hardware transmission. Called either from the txdone interrupt + * handling or from watchdog based polling. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int stm32_transmit(FAR struct stm32_ethmac_s *priv) +{ + struct eth_txdesc_s *txdesc; + struct eth_txdesc_s *txfirst; + + /* The internal (optimal) uIP buffer size may be configured to be larger + * than the Ethernet buffer size. + */ + +#if OPTIMAL_ETH_BUFSIZE > CONFIG_STM32_ETH_BUFSIZE + uint8_t *buffer; + int bufcount; + int lastsize; + int i; +#endif + + /* Verify that the hardware is ready to send another packet. If we get + * here, then we are committed to sending a packet; Higher level logic + * must have assured that there is no transmission in progress. + */ + + txdesc = priv->txhead; + txfirst = txdesc; + + nllvdbg("d_len: %d d_buf: %p txhead: %p tdes0: %08x\n", + priv->dev.d_len, priv->dev.d_buf, txdesc, txdesc->tdes0); + + DEBUGASSERT(txdesc && (txdesc->tdes0 & ETH_TDES0_OWN) == 0); + + /* Is the size to be sent greater than the size of the Ethernet buffer? */ + + DEBUGASSERT(priv->dev.d_len > 0 && priv->dev.d_buf != NULL); + +#if OPTIMAL_ETH_BUFSIZE > CONFIG_STM32_ETH_BUFSIZE + if (priv->dev.d_len > CONFIG_STM32_ETH_BUFSIZE) + { + /* Yes... how many buffers will be need to send the packet? */ + + bufcount = (priv->dev.d_len + (CONFIG_STM32_ETH_BUFSIZE-1)) / CONFIG_STM32_ETH_BUFSIZE; + lastsize = priv->dev.d_len - (bufcount - 1) * CONFIG_STM32_ETH_BUFSIZE; + + nllvdbg("bufcount: %d lastsize: %d\n", bufcount, lastsize); + + /* Set the first segment bit in the first TX descriptor */ + + txdesc->tdes0 |= ETH_TDES0_FS; + + /* Set up all but the last TX descriptor */ + + buffer = priv->dev.d_buf; + + for (i = 0; i < bufcount; i++) + { + /* This could be a normal event but the design does not handle it */ + + DEBUGASSERT((txdesc->tdes0 & ETH_TDES0_OWN) == 0); + + /* Set the Buffer1 address pointer */ + + txdesc->tdes2 = (uint32_t)buffer; + + /* Set the buffer size in all TX descriptors */ + + if (i == (bufcount-1)) + { + /* This is the last segment. Set the last segment bit in the + * last TX descriptor and ask for an interrupt when this + * segment transfer completes. + */ + + txdesc->tdes0 |= (ETH_TDES0_LS | ETH_TDES0_IC); + + /* This segement is, most likely, of fractional buffersize */ + + txdesc->tdes1 = lastsize; + buffer += lastsize; + } + else + { + /* This is not the last segment. We don't want an interrupt + * when this segment transfer completes. + */ + + txdesc->tdes0 &= ~ETH_TDES0_IC; + + /* The size of the transfer is the whole buffer */ + + txdesc->tdes1 = CONFIG_STM32_ETH_BUFSIZE; + buffer += CONFIG_STM32_ETH_BUFSIZE; + } + + /* Give the descriptor to DMA */ + + txdesc->tdes0 |= ETH_TDES0_OWN; + txdesc = (struct eth_txdesc_s *)txdesc->tdes3; + } + } + else +#endif + { + /* The single descriptor is both the first and last segment. And we do + * want an interrupt when the transfer completes. + */ + + txdesc->tdes0 |= (ETH_TDES0_FS | ETH_TDES0_LS | ETH_TDES0_IC); + + /* Set frame size */ + + DEBUGASSERT(priv->dev.d_len <= CONFIG_NET_BUFSIZE); + txdesc->tdes1 = priv->dev.d_len; + + /* Set the Buffer1 address pointer */ + + txdesc->tdes2 = (uint32_t)priv->dev.d_buf; + + /* Set OWN bit of the TX descriptor tdes0. This gives the buffer to + * Ethernet DMA + */ + + txdesc->tdes0 |= ETH_TDES0_OWN; + + /* Point to the next available TX descriptor */ + + txdesc = (struct eth_txdesc_s *)txdesc->tdes3; + } + + /* Remember where we left off in the TX descriptor chain */ + + priv->txhead = txdesc; + + /* Detach the buffer from priv->dev structure. That buffer is now + * "in-flight". + */ + + priv->dev.d_buf = NULL; + priv->dev.d_len = 0; + + /* If there is no other TX buffer, in flight, then remember the location + * of the TX descriptor. This is the location to check for TX done events. + */ + + if (!priv->txtail) + { + DEBUGASSERT(priv->inflight == 0); + priv->txtail = txfirst; + } + + /* Increment the number of TX transfer in-flight */ + + priv->inflight++; + + nllvdbg("txhead: %p txtail: %p inflight: %d\n", + priv->txhead, priv->txtail, priv->inflight); + + /* If all TX descriptors are in-flight, then we have to disable receive interrupts + * too. This is because receive events can trigger more un-stoppable transmit + * events. + */ + + if (priv->inflight >= CONFIG_STM32_ETH_NTXDESC) + { + stm32_disableint(priv, ETH_DMAINT_RI); + } + + /* Check if the TX Buffer unavailable flag is set */ + + if ((stm32_getreg(STM32_ETH_DMASR) & ETH_DMAINT_TBUI) != 0) + { + /* Clear TX Buffer unavailable flag */ + + stm32_putreg(ETH_DMAINT_TBUI, STM32_ETH_DMASR); + + /* Resume DMA transmission */ + + stm32_putreg(0, STM32_ETH_DMATPDR); + } + + /* Enable TX interrupts */ + + stm32_enableint(priv, ETH_DMAINT_TI); + + /* Setup the TX timeout watchdog (perhaps restarting the timer) */ + + (void)wd_start(priv->txtimeout, STM32_TXTIMEOUT, stm32_txtimeout, 1, (uint32_t)priv); + return OK; +} + +/**************************************************************************** + * Function: stm32_uiptxpoll + * + * Description: + * The transmitter is available, check if uIP has any outgoing packets ready + * to send. This is a callback from uip_poll(). uip_poll() may be called: + * + * 1. When the preceding TX packet send is complete, + * 2. When the preceding TX packet send timesout and the interface is reset + * 3. During normal TX polling + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int stm32_uiptxpoll(struct uip_driver_s *dev) +{ + FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private; + + DEBUGASSERT(priv->dev.d_buf != NULL); + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + /* Send the packet */ + + uip_arp_out(&priv->dev); + stm32_transmit(priv); + DEBUGASSERT(dev->d_len == 0 && dev->d_buf == NULL); + + /* Check if the next TX descriptor is owned by the Ethernet DMA or CPU. We + * cannot perform the TX poll if we are unable to accept another packet for + * transmission. + * + * In a race condition, ETH_TDES0_OWN may be cleared BUT still not available + * because stm32_freeframe() has not yet run. If stm32_freeframe() has run, + * the buffer1 pointer (tdes2) will be nullified (and inflight should be < + * CONFIG_STM32_ETH_NTXDESC). + */ + + if ((priv->txhead->tdes0 & ETH_TDES0_OWN) != 0 || + priv->txhead->tdes2 != 0) + { + /* We have to terminate the poll if we have no more descriptors + * available for another transfer. + */ + + return -EBUSY; + } + + /* We have the descriptor, we can continue the poll. Allocate a new + * buffer for the poll. + */ + + dev->d_buf = stm32_allocbuffer(priv); + + /* We can't continue the poll if we have no buffers */ + + if (dev->d_buf == NULL) + { + /* Terminate the poll. */ + + return -ENOMEM; + } + } + + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + + return 0; +} + +/**************************************************************************** + * Function: stm32_dopoll + * + * Description: + * The function is called when a frame is received using the DMA receive + * interrupt. It scans the RX descriptors to the the received frame. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void stm32_dopoll(FAR struct stm32_ethmac_s *priv) +{ + FAR struct uip_driver_s *dev = &priv->dev; + + /* Check if the next TX descriptor is owned by the Ethernet DMA or + * CPU. We cannot perform the TX poll if we are unable to accept + * another packet for transmission. + * + * In a race condition, ETH_TDES0_OWN may be cleared BUT still not available + * because stm32_freeframe() has not yet run. If stm32_freeframe() has run, + * the buffer1 pointer (tdes2) will be nullified (and inflight should be < + * CONFIG_STM32_ETH_NTXDESC). + */ + + if ((priv->txhead->tdes0 & ETH_TDES0_OWN) == 0 && + priv->txhead->tdes2 == 0) + { + /* If we have the descriptor, then poll uIP for new XMIT data. + * Allocate a buffer for the poll. + */ + + DEBUGASSERT(dev->d_len == 0 && dev->d_buf == NULL); + dev->d_buf = stm32_allocbuffer(priv); + + /* We can't poll if we have no buffers */ + + if (dev->d_buf) + { + (void)uip_poll(dev, stm32_uiptxpoll); + + /* We will, most likely end up with a buffer to be freed. But it + * might not be the same one that we allocated above. + */ + + if (dev->d_buf) + { + DEBUGASSERT(dev->d_len == 0); + stm32_freebuffer(priv, dev->d_buf); + dev->d_buf = NULL; + } + } + } +} + +/**************************************************************************** + * Function: stm32_enableint + * + * Description: + * Enable a "normal" interrupt + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void stm32_enableint(FAR struct stm32_ethmac_s *priv, uint32_t ierbit) +{ + uint32_t regval; + + /* Enable the specified "normal" interrupt */ + + regval = stm32_getreg(STM32_ETH_DMAIER); + regval |= (ETH_DMAINT_NIS | ierbit); + stm32_putreg(regval, STM32_ETH_DMAIER); +} + +/**************************************************************************** + * Function: stm32_disableint + * + * Description: + * Disable a normal interrupt. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void stm32_disableint(FAR struct stm32_ethmac_s *priv, uint32_t ierbit) +{ + uint32_t regval; + + /* Disable the "normal" interrupt */ + + regval = stm32_getreg(STM32_ETH_DMAIER); + regval &= ~ierbit; + + /* Are all "normal" interrupts now disabled? */ + + if ((regval & ETH_DMAINT_NORMAL) == 0) + { + /* Yes.. disable normal interrupts */ + + regval &= ~ETH_DMAINT_NIS; + } + + stm32_putreg(regval, STM32_ETH_DMAIER); +} + +/**************************************************************************** + * Function: stm32_freesegment + * + * Description: + * The function is called when a frame is received using the DMA receive + * interrupt. It scans the RX descriptors to the the received frame. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void stm32_freesegment(FAR struct stm32_ethmac_s *priv, + FAR struct eth_rxdesc_s *rxfirst, int segments) +{ + struct eth_rxdesc_s *rxdesc; + int i; + + nllvdbg("rxfirst: %p segments: %d\n", rxfirst, segments); + + /* Set OWN bit in RX descriptors. This gives the buffers back to DMA */ + + rxdesc = rxfirst; + for (i = 0; i < segments; i++) + { + rxdesc->rdes0 = ETH_RDES0_OWN; + rxdesc = (struct eth_rxdesc_s *)rxdesc->rdes3; + } + + /* Reset the segment managment logic */ + + priv->rxcurr = NULL; + priv->segments = 0; + + /* Check if the RX Buffer unavailable flag is set */ + + if ((stm32_getreg(STM32_ETH_DMASR) & ETH_DMAINT_RBUI) != 0) + { + /* Clear RBUS Ethernet DMA flag */ + + stm32_putreg(ETH_DMAINT_RBUI, STM32_ETH_DMASR); + + /* Resume DMA reception */ + + stm32_putreg(0, STM32_ETH_DMARPDR); + } +} + +/**************************************************************************** + * Function: stm32_recvframe + * + * Description: + * The function is called when a frame is received using the DMA receive + * interrupt. It scans the RX descriptors of the received frame. + * + * NOTE: This function will silently discard any packets containing errors. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * OK if a packet was successfully returned; -EAGAIN if there are no + * further packets available + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static int stm32_recvframe(FAR struct stm32_ethmac_s *priv) +{ + struct eth_rxdesc_s *rxdesc; + struct eth_rxdesc_s *rxcurr; + uint8_t *buffer; + int i; + + nllvdbg("rxhead: %p rxcurr: %p segments: %d\n", + priv->rxhead, priv->rxcurr, priv->segments); + + /* Check if there are free buffers. We cannot receive new frames in this + * design unless there is at least one free buffer. + */ + + if (!stm32_isfreebuffer(priv)) + { + nlldbg("No free buffers\n"); + return -ENOMEM; + } + + /* Scan descriptors owned by the CPU. Scan until: + * + * 1) We find a descriptor still owned by the DMA, + * 2) We have examined all of the RX descriptors, or + * 3) All of the TX descriptors are in flight. + * + * This last case is obscure. It is due to that fact that each packet + * that we receive can generate an unstoppable transmisson. So we have + * to stop receiving when we can not longer transmit. In this case, the + * transmit logic should also have disabled further RX interrupts. + */ + + rxdesc = priv->rxhead; + for (i = 0; + (rxdesc->rdes0 & ETH_RDES0_OWN) == 0 && + i < CONFIG_STM32_ETH_NRXDESC && + priv->inflight < CONFIG_STM32_ETH_NTXDESC; + i++) + { + /* Check if this is the first segment in the frame */ + + if ((rxdesc->rdes0 & ETH_RDES0_FS) != 0 && + (rxdesc->rdes0 & ETH_RDES0_LS) == 0) + { + priv->rxcurr = rxdesc; + priv->segments = 1; + } + + /* Check if this is an intermediate segment in the frame */ + + else if (((rxdesc->rdes0 & ETH_RDES0_LS) == 0)&& + ((rxdesc->rdes0 & ETH_RDES0_FS) == 0)) + { + priv->segments++; + } + + /* Otherwise, it is the last segment in the frame */ + + else + { + priv->segments++; + + nllvdbg("rxhead: %p rxcurr: %p segments: %d\n", + priv->rxhead, priv->rxcurr, priv->segments); + + /* Check if the there is only one segment in the frame */ + + if (priv->segments == 1) + { + rxcurr = rxdesc; + } + else + { + rxcurr = priv->rxcurr; + } + + /* Check if any errors are reported in the frame */ + + if ((rxdesc->rdes0 & ETH_RDES0_ES) == 0) + { + struct uip_driver_s *dev = &priv->dev; + + /* Get the Frame Length of the received packet: substruct 4 + * bytes of the CRC + */ + + dev->d_len = ((rxdesc->rdes0 & ETH_RDES0_FL_MASK) >> ETH_RDES0_FL_SHIFT) - 4; + + /* Get a buffer from the free list. We don't even check if + * this is successful because we already assure the the free + * list is not empty above. + */ + + buffer = stm32_allocbuffer(priv); + + /* Take the buffer from the RX descriptor of the first free + * segment, put it into the uIP device structure, then replace + * the buffer in the RX descriptor with the newly allocated + * buffer. + */ + + DEBUGASSERT(dev->d_buf == NULL); + dev->d_buf = (uint8_t*)rxcurr->rdes2; + rxcurr->rdes2 = (uint32_t)buffer; + + /* Return success, remebering where we should re-start scanning + * and resetting the segment scanning logic + */ + + priv->rxhead = (struct eth_rxdesc_s*)rxdesc->rdes3; + stm32_freesegment(priv, rxcurr, priv->segments); + + nllvdbg("rxhead: %p d_buf: %p d_len: %d\n", + priv->rxhead, dev->d_buf, dev->d_len); + + return OK; + } + else + { + /* Drop the frame that contains the errors, reset the segment + * scanning logic, and continue scanning with the next frame. + */ + + nlldbg("DROPPED: RX descriptor errors: %08x\n", rxdesc->rdes0); + stm32_freesegment(priv, rxcurr, priv->segments); + } + } + + /* Try the next descriptor */ + + rxdesc = (struct eth_rxdesc_s*)rxdesc->rdes3; + } + + /* We get here after all of the descriptors have been scanned or when rxdesc points + * to the first descriptor owned by the DMA. Remember where we left off. + */ + + priv->rxhead = rxdesc; + + nllvdbg("rxhead: %p rxcurr: %p segments: %d\n", + priv->rxhead, priv->rxcurr, priv->segments); + + return -EAGAIN; +} + +/**************************************************************************** + * Function: stm32_receive + * + * Description: + * An interrupt was received indicating the availability of a new RX packet + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void stm32_receive(FAR struct stm32_ethmac_s *priv) +{ + struct uip_driver_s *dev = &priv->dev; + + /* Loop while while stm32_recvframe() successfully retrieves valid + * Ethernet frames. + */ + + while (stm32_recvframe(priv) == OK) + { + /* Check if the packet is a valid size for the uIP buffer configuration + * (this should not happen) + */ + + if (dev->d_len > CONFIG_NET_BUFSIZE) + { + nlldbg("DROPPED: Too big: %d\n", dev->d_len); + } + + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv6 + else if (BUF->type == HTONS(UIP_ETHTYPE_IP6)) +#else + else if (BUF->type == HTONS(UIP_ETHTYPE_IP)) +#endif + { + nllvdbg("IP frame\n"); + + /* Handle ARP on input then give the IP packet to uIP */ + + uip_arp_ipin(&priv->dev); + uip_input(&priv->dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + uip_arp_out(&priv->dev); + stm32_transmit(priv); + } + } + else if (BUF->type == htons(UIP_ETHTYPE_ARP)) + { + nllvdbg("ARP frame\n"); + + /* Handle ARP packet */ + + uip_arp_arpin(&priv->dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + stm32_transmit(priv); + } + } + else + { + nlldbg("DROPPED: Unknown type: %04x\n", BUF->type); + } + + /* We are finished with the RX buffer. NOTE: If the buffer is + * re-used for transmission, the dev->d_buf field will have been + * nullified. + */ + + if (dev->d_buf) + { + /* Free the receive packet buffer */ + + stm32_freebuffer(priv, dev->d_buf); + dev->d_buf = NULL; + } + } +} + +/**************************************************************************** + * Function: stm32_freeframe + * + * Description: + * Scans the TX descriptors and frees the buffers of completed TX transfers. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None. + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void stm32_freeframe(FAR struct stm32_ethmac_s *priv) +{ + struct eth_txdesc_s *txdesc; + int i; + + nllvdbg("txhead: %p txtail: %p inflight: %d\n", + priv->txhead, priv->txtail, priv->inflight); + + /* Scan for "in-flight" descriptors owned by the CPU */ + + txdesc = priv->txtail; + if (txdesc) + { + DEBUGASSERT(priv->inflight > 0); + + for (i = 0; (txdesc->tdes0 & ETH_TDES0_OWN) == 0; i++) + { + /* There should be a buffer assigned to all in-flight + * TX descriptors. + */ + + nllvdbg("txtail: %p tdes0: %08x tdes2: %08x tdes3: %08x\n", + txdesc, txdesc->tdes0, txdesc->tdes2, txdesc->tdes3); + + DEBUGASSERT(txdesc->tdes2 != 0); + + /* Check if this is the first segment of a TX frame. */ + + if ((txdesc->tdes0 & ETH_TDES0_FS) != 0) + { + /* Yes.. Free the buffer */ + + stm32_freebuffer(priv, (uint8_t*)txdesc->tdes2); + } + + /* In any event, make sure that TDES2 is nullified. */ + + txdesc->tdes2 = 0; + + /* Check if this is the last segement of a TX frame */ + + if ((txdesc->tdes0 & ETH_TDES0_FS) != 0) + { + /* Yes.. Decrement the number of frames "in-flight". */ + + priv->inflight--; + + /* If all of the TX descriptors were in-flight, then RX interrupts + * may have been disabled... we can re-enable them now. + */ + + stm32_enableint(priv, ETH_DMAINT_RI); + + /* If there are no more frames in-flight, then bail. */ + + if (priv->inflight <= 0) + { + priv->txtail = NULL; + priv->inflight = 0; + return; + } + } + + /* Try the next descriptor in the TX chain */ + + txdesc = (struct eth_txdesc_s*)txdesc->tdes3; + } + + /* We get here if (1) there are still frames "in-flight". Remember + * where we left off. + */ + + priv->txtail = txdesc; + + nllvdbg("txhead: %p txtail: %p inflight: %d\n", + priv->txhead, priv->txtail, priv->inflight); + } +} + +/**************************************************************************** + * Function: stm32_txdone + * + * Description: + * An interrupt was received indicating that the last TX packet(s) is done + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void stm32_txdone(FAR struct stm32_ethmac_s *priv) +{ + DEBUGASSERT(priv->txtail != NULL); + + /* Scan the TX desciptor change, returning buffers to free list */ + + stm32_freeframe(priv); + + /* If no further xmits are pending, then cancel the TX timeout */ + + if (priv->inflight <= 0) + { + wd_cancel(priv->txtimeout); + + /* And disable further TX interrupts. */ + + stm32_disableint(priv, ETH_DMAINT_TI); + } + + /* Then poll uIP for new XMIT data */ + + stm32_dopoll(priv); +} + +/**************************************************************************** + * Function: stm32_interrupt + * + * Description: + * Hardware interrupt handler + * + * Parameters: + * irq - Number of the IRQ that generated the interrupt + * context - Interrupt register state save info (architecture-specific) + * + * Returned Value: + * OK on success + * + * Assumptions: + * + ****************************************************************************/ + +static int stm32_interrupt(int irq, FAR void *context) +{ + register FAR struct stm32_ethmac_s *priv = &g_stm32ethmac[0]; + uint32_t dmasr; + + /* Get the DMA interrupt status bits (no MAC interrupts are expected) */ + + dmasr = stm32_getreg(STM32_ETH_DMASR); + + /* Mask only enabled interrupts. This depends on the fact that the interrupt + * related bits (0-16) correspond in these two registers. + */ + + dmasr &= stm32_getreg(STM32_ETH_DMAIER); + + /* Check if there are pending "normal" interrupts */ + + if ((dmasr & ETH_DMAINT_NIS) != 0) + { + /* Yes.. Check if we received an incoming packet, if so, call + * stm32_receive() + */ + + if ((dmasr & ETH_DMAINT_RI) != 0) + { + /* Clear the pending receive interrupt */ + + stm32_putreg(ETH_DMAINT_RI, STM32_ETH_DMASR); + + /* Handle the received package */ + + stm32_receive(priv); + } + + /* Check if a packet transmission just completed. If so, call + * stm32_txdone(). This may disable further TX interrupts if there + * are no pending tansmissions. + */ + + if ((dmasr & ETH_DMAINT_TI) != 0) + { + /* Clear the pending receive interrupt */ + + stm32_putreg(ETH_DMAINT_TI, STM32_ETH_DMASR); + + /* Check if there are pending transmissions */ + + stm32_txdone(priv); + } + + /* Clear the pending normal summary interrupt */ + + stm32_putreg(ETH_DMAINT_NIS, STM32_ETH_DMASR); + } + + /* Handle error interrupt only if CONFIG_DEBUG_NET is eanbled */ + +#ifdef CONFIG_DEBUG_NET + + /* Check if there are pending "anormal" interrupts */ + + if ((dmasr & ETH_DMAINT_AIS) != 0) + { + /* Just let the user know what happened */ + + nlldbg("Abormal event(s): %08x\n", dmasr); + + /* Clear all pending abnormal events */ + + stm32_putreg(ETH_DMAINT_ABNORMAL, STM32_ETH_DMASR); + + /* Clear the pending abnormal summary interrupt */ + + stm32_putreg(ETH_DMAINT_AIS, STM32_ETH_DMASR); + } +#endif + return OK; +} + +/**************************************************************************** + * Function: stm32_txtimeout + * + * Description: + * Our TX watchdog timed out. Called from the timer interrupt handler. + * The last TX never completed. Reset the hardware and start again. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void stm32_txtimeout(int argc, uint32_t arg, ...) +{ + FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg; + + nlldbg("Timeout!\n"); + + /* Then reset the hardware. Just take the interface down, then back + * up again. + */ + + stm32_ifdown(&priv->dev); + stm32_ifup(&priv->dev); + + /* Then poll uIP for new XMIT data */ + + stm32_dopoll(priv); +} + +/**************************************************************************** + * Function: stm32_polltimer + * + * Description: + * Periodic timer handler. Called from the timer interrupt handler. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void stm32_polltimer(int argc, uint32_t arg, ...) +{ + FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg; + FAR struct uip_driver_s *dev = &priv->dev; + + /* Check if the next TX descriptor is owned by the Ethernet DMA or CPU. We + * cannot perform the timer poll if we are unable to accept another packet + * for transmission. Hmmm.. might be bug here. Does this mean if there is + * a transmit in progress, we will missing TCP time state updates? + * + * In a race condition, ETH_TDES0_OWN may be cleared BUT still not available + * because stm32_freeframe() has not yet run. If stm32_freeframe() has run, + * the buffer1 pointer (tdes2) will be nullified (and inflight should be < + * CONFIG_STM32_ETH_NTXDESC). + */ + + if ((priv->txhead->tdes0 & ETH_TDES0_OWN) == 0 && + priv->txhead->tdes2 == 0) + { + /* If we have the descriptor, then perform the timer poll. Allocate a + * buffer for the poll. + */ + + DEBUGASSERT(dev->d_len == 0 && dev->d_buf == NULL); + dev->d_buf = stm32_allocbuffer(priv); + + /* We can't poll if we have no buffers */ + + if (dev->d_buf) + { + /* Update TCP timing states and poll uIP for new XMIT data. + */ + + (void)uip_timer(dev, stm32_uiptxpoll, STM32_POLLHSEC); + + /* We will, most likely end up with a buffer to be freed. But it + * might not be the same one that we allocated above. + */ + + if (dev->d_buf) + { + DEBUGASSERT(dev->d_len == 0); + stm32_freebuffer(priv, dev->d_buf); + dev->d_buf = NULL; + } + } + } + + /* Setup the watchdog poll timer again */ + + (void)wd_start(priv->txpoll, STM32_WDDELAY, stm32_polltimer, 1, arg); +} + +/**************************************************************************** + * Function: stm32_ifup + * + * Description: + * NuttX Callback: Bring up the Ethernet interface when an IP address is + * provided + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int stm32_ifup(struct uip_driver_s *dev) +{ + FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private; + int ret; + + ndbg("Bringing up: %d.%d.%d.%d\n", + dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, + (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 ); + + /* Configure the Ethernet interface for DMA operation. */ + + ret = stm32_ethconfig(priv); + if (ret < 0) + { + return ret; + } + + /* Set and activate a timer process */ + + (void)wd_start(priv->txpoll, STM32_WDDELAY, stm32_polltimer, 1, (uint32_t)priv); + + /* Enable the Ethernet interrupt */ + + priv->ifup = true; + up_enable_irq(STM32_IRQ_ETH); + + stm32_checksetup(); + return OK; +} + +/**************************************************************************** + * Function: stm32_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int stm32_ifdown(struct uip_driver_s *dev) +{ + FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private; + irqstate_t flags; + + ndbg("Taking the network down\n"); + + /* Disable the Ethernet interrupt */ + + flags = irqsave(); + up_disable_irq(STM32_IRQ_ETH); + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(priv->txpoll); + wd_cancel(priv->txtimeout); + + /* Put the EMAC in its reset, non-operational state. This should be + * a known configuration that will guarantee the stm32_ifup() always + * successfully brings the interface back up. + */ + + stm32_ethreset(priv); + + /* Mark the device "down" */ + + priv->ifup = false; + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Function: stm32_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int stm32_txavail(struct uip_driver_s *dev) +{ + FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private; + irqstate_t flags; + + nllvdbg("ifup: %d\n", priv->ifup); + + /* Disable interrupts because this function may be called from interrupt + * level processing. + */ + + flags = irqsave(); + + /* Ignore the notification if the interface is not yet up */ + + if (priv->ifup) + { + /* Poll uIP for new XMIT data */ + + stm32_dopoll(priv); + } + + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Function: stm32_addmac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int stm32_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private; + + nllvdbg("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + /* Add the MAC address to the hardware multicast routing table */ + /* Add the MAC address to the hardware multicast routing table */ +#error "Missing logic" + + return OK; +} +#endif + +/**************************************************************************** + * Function: stm32_rmmac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int stm32_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private; + + nllvdbg("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + /* Add the MAC address to the hardware multicast routing table */ +#error "Missing logic" + + return OK; +} +#endif + +/**************************************************************************** + * Function: stm32_txdescinit + * + * Description: + * Initializes the DMA TX descriptors in chain mode. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void stm32_txdescinit(FAR struct stm32_ethmac_s *priv) +{ + struct eth_txdesc_s *txdesc; + int i; + + /* priv->txhead will point to the first, available TX descriptor in the chain. + * Set the priv->txhead pointer to the first descriptor in the table. + */ + + priv->txhead = priv->txtable; + + /* priv->txtail will point to the first segment of the oldest pending + * "in-flight" TX transfer. NULL means that there are no active TX + * transfers. + */ + + priv->txtail = NULL; + priv->inflight = 0; + + /* Initialize each TX descriptor */ + + for (i = 0; i < CONFIG_STM32_ETH_NTXDESC; i++) + { + txdesc = &priv->txtable[i]; + + /* Set Second Address Chained bit */ + + txdesc->tdes0 = ETH_TDES0_TCH; + +#ifdef CHECKSUM_BY_HARDWARE + /* Enable the checksum insertion for the TX frames */ + + txdesc->tdes0 |= ETH_TDES0_CIC_ALL; +#endif + + /* Clear Buffer1 address pointer (buffers will be assigned as they + * are used) + */ + + txdesc->tdes2 = 0; + + /* Initialize the next descriptor with the Next Descriptor Polling Enable */ + + if( i < (CONFIG_STM32_ETH_NTXDESC-1)) + { + /* Set next descriptor address register with next descriptor base + * address + */ + + txdesc->tdes3 = (uint32_t)&priv->txtable[i+1]; + } + else + { + /* For last descriptor, set next descriptor address register equal + * to the first descriptor base address + */ + + txdesc->tdes3 = (uint32_t)priv->txtable; + } + } + + /* Set Transmit Desciptor List Address Register */ + + stm32_putreg((uint32_t)priv->txtable, STM32_ETH_DMATDLAR); +} + +/**************************************************************************** + * Function: stm32_rxdescinit + * + * Description: + * Initializes the DMA RX descriptors in chain mode. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void stm32_rxdescinit(FAR struct stm32_ethmac_s *priv) +{ + struct eth_rxdesc_s *rxdesc; + int i; + + /* priv->rxhead will point to the first, RX descriptor in the chain. + * This will be where we receive the first incomplete frame. + */ + + priv->rxhead = priv->rxtable; + + /* If we accumulate the frame in segments, priv->rxcurr points to the + * RX descriptor of the first segment in the current TX frame. + */ + + priv->rxcurr = NULL; + priv->segments = 0; + + /* Initialize each TX descriptor */ + + for (i = 0; i < CONFIG_STM32_ETH_NRXDESC; i++) + { + rxdesc = &priv->rxtable[i]; + + /* Set Own bit of the RX descriptor rdes0 */ + + rxdesc->rdes0 = ETH_RDES0_OWN; + + /* Set Buffer1 size and Second Address Chained bit and enabled DMA + * RX desc receive interrupt + */ + + rxdesc->rdes1 = ETH_RDES1_RCH | (uint32_t)CONFIG_STM32_ETH_BUFSIZE; + + /* Set Buffer1 address pointer */ + + rxdesc->rdes2 = (uint32_t)&priv->rxbuffer[i*CONFIG_STM32_ETH_BUFSIZE]; + + /* Initialize the next descriptor with the Next Descriptor Polling Enable */ + + if( i < (CONFIG_STM32_ETH_NRXDESC-1)) + { + /* Set next descriptor address register with next descriptor base + * address + */ + + rxdesc->rdes3 = (uint32_t)&priv->rxtable[i+1]; + } + else + { + /* For last descriptor, set next descriptor address register equal + * to the first descriptor base address + */ + + rxdesc->rdes3 = (uint32_t)priv->rxtable; + } + } + + /* Set Receive Descriptor List Address Register */ + + stm32_putreg((uint32_t)priv->rxtable, STM32_ETH_DMARDLAR); +} + +/**************************************************************************** + * Function: stm32_phyread + * + * Description: + * Read a PHY register. + * + * Parameters: + * phydevaddr - The PHY device address + * phyregaddr - The PHY register address + * value - The location to return the 16-bit PHY register value. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int stm32_phyread(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t *value) +{ + volatile uint32_t timeout; + uint32_t regval; + + /* Configure the MACMIIAR register, preserving CSR Clock Range CR[2:0] bits */ + + regval = stm32_getreg(STM32_ETH_MACMIIAR); + regval &= ETH_MACMIIAR_CR_MASK; + + /* Set the PHY device address, PHY register address, and set the buy bit. + * the ETH_MACMIIAR_MW is clear, indicating a read operation. + */ + + regval |= (((uint32_t)phydevaddr << ETH_MACMIIAR_PA_SHIFT) & ETH_MACMIIAR_PA_MASK); + regval |= (((uint32_t)phyregaddr << ETH_MACMIIAR_MR_SHIFT) & ETH_MACMIIAR_MR_MASK); + regval |= ETH_MACMIIAR_MB; + + stm32_putreg(regval, STM32_ETH_MACMIIAR); + + /* Wait for the transfer to complete */ + + for (timeout = 0; timeout < PHY_READ_TIMEOUT; timeout++) + { + if ((stm32_getreg(STM32_ETH_MACMIIAR) & ETH_MACMIIAR_MB) == 0) + { + *value = (uint16_t)stm32_getreg(STM32_ETH_MACMIIDR); + return OK; + } + } + + ndbg("MII transfer timed out: phydevaddr: %04x phyregaddr: %04x\n", + phydevaddr, phyregaddr); + + return -ETIMEDOUT; +} + +/**************************************************************************** + * Function: stm32_phywrite + * + * Description: + * Write to a PHY register. + * + * Parameters: + * phydevaddr - The PHY device address + * phyregaddr - The PHY register address + * value - The 16-bit value to write to the PHY register value. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t value) +{ + volatile uint32_t timeout; + uint32_t regval; + + /* Configure the MACMIIAR register, preserving CSR Clock Range CR[2:0] bits */ + + regval = stm32_getreg(STM32_ETH_MACMIIAR); + regval &= ETH_MACMIIAR_CR_MASK; + + /* Set the PHY device address, PHY register address, and set the busy bit. + * the ETH_MACMIIAR_MW is set, indicating a write operation. + */ + + regval |= (((uint32_t)phydevaddr << ETH_MACMIIAR_PA_SHIFT) & ETH_MACMIIAR_PA_MASK); + regval |= (((uint32_t)phyregaddr << ETH_MACMIIAR_MR_SHIFT) & ETH_MACMIIAR_MR_MASK); + regval |= (ETH_MACMIIAR_MB | ETH_MACMIIAR_MW); + + /* Write the value into the MACIIDR register before setting the new MACMIIAR + * register value. + */ + + stm32_putreg(value, STM32_ETH_MACMIIDR); + stm32_putreg(regval, STM32_ETH_MACMIIAR); + + /* Wait for the transfer to complete */ + + for (timeout = 0; timeout < PHY_WRITE_TIMEOUT; timeout++) + { + if ((stm32_getreg(STM32_ETH_MACMIIAR) & ETH_MACMIIAR_MB) == 0) + { + return OK; + } + } + + ndbg("MII transfer timed out: phydevaddr: %04x phyregaddr: %04x value: %04x\n", + phydevaddr, phyregaddr, value); + + return -ETIMEDOUT; +} + +/**************************************************************************** + * Function: stm32_phyinit + * + * Description: + * Configure the PHY and determine the link speed/duplex. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int stm32_phyinit(FAR struct stm32_ethmac_s *priv) +{ + volatile uint32_t timeout; + uint32_t regval; + uint16_t phyval; + int ret; + + /* Assume 10MBps and half duplex */ + + priv->mbps100 = 0; + priv->fduplex = 0; + + /* Setup up PHY clocking by setting the SR field in the MACMIIAR register */ + + regval = stm32_getreg(STM32_ETH_MACMIIAR); + regval &= ~ETH_MACMIIAR_CR_MASK; + regval |= ETH_MACMIIAR_CR; + stm32_putreg(regval, STM32_ETH_MACMIIAR); + + /* Put the PHY in reset mode */ + + ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_MCR, MII_MCR_RESET); + if (ret < 0) + { + ndbg("Failed to reset the PHY: %d\n", ret); + return ret; + } + up_mdelay(PHY_RESET_DELAY); + + /* Perform auto-negotion if so configured */ + +#ifdef CONFIG_STM32_AUTONEG + /* Wait for link status */ + + for (timeout = 0; timeout < PHY_RETRY_TIMEOUT; timeout++) + { + ret = stm32_phyread(CONFIG_STM32_PHYADDR, MII_MSR, &phyval); + if (ret < 0) + { + ndbg("Failed to read the PHY MSR: %d\n", ret); + return ret; + } + else if ((phyval & MII_MSR_LINKSTATUS) != 0) + { + break; + } + } + + if (timeout >= PHY_RETRY_TIMEOUT) + { + ndbg("Timed out waiting for link status\n"); + return -ETIMEDOUT; + } + + /* Enable auto-gegotiation */ + + ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_MCR, MII_MCR_ANENABLE); + if (ret < 0) + { + ndbg("Failed to enable auto-negotiation: %d\n", ret); + return ret; + } + + /* Wait until auto-negotiation completes */ + + for (timeout = 0; timeout < PHY_RETRY_TIMEOUT; timeout++) + { + ret = stm32_phyread(CONFIG_STM32_PHYADDR, MII_MSR, &phyval); + if (ret < 0) + { + ndbg("Failed to read the PHY MSR: %d\n", ret); + return ret; + } + else if ((phyval & MII_MSR_ANEGCOMPLETE) != 0) + { + break; + } + } + + if (timeout >= PHY_RETRY_TIMEOUT) + { + ndbg("Timed out waiting for auto-negotiation\n"); + return -ETIMEDOUT; + } + + /* Read the result of the auto-negotiation from the PHY-specific register */ + + ret = stm32_phyread(CONFIG_STM32_PHYADDR, CONFIG_STM32_PHYSR, &phyval); + if (ret < 0) + { + ndbg("Failed to read PHY status register\n"); + return ret; + } + + /* Remember the selected speed and duplex modes */ + + if ((phyval & CONFIG_STM32_PHYSR_MODE) == CONFIG_STM32_PHYSR_FULLDUPLEX) + { + priv->fduplex = 1; + } + + if ((phyval & CONFIG_STM32_PHYSR_SPEED) == CONFIG_STM32_PHYSR_100MBPS) + { + priv->mbps100 = 1; + } + +#else /* Auto-negotion not selected */ + + phyval = 0; +#ifdef CONFIG_STM32_ETHFD + phyval |= MII_MCR_FULLDPLX; +#endif +#ifdef CONFIG_STM32_ETH100MBPS + phyval |= MII_MCR_SPEED100; +#endif + + ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_MCR, phyval); + if (ret < 0) + { + ndbg("Failed to write the PHY MCR: %d\n", ret); + return ret; + } + up_mdelay(PHY_CONFIG_DELAY); + + /* Remember the selected speed and duplex modes */ + +#ifdef CONFIG_STM32_ETHFD + priv->fduplex = 1; +#endif +#ifdef CONFIG_STM32_ETH100MBPS + priv->mbps100 = 1; +#endif +#endif + + ndbg("Duplex: %s Speed: %d MBps\n", + priv->fduplex ? "FULL" : "HALF", + priv->mbps100 ? 100 : 10); + + return OK; +} + +/**************************************************************************** + * Function: stm32_ethgpioconfig + * + * Description: + * Configure GPIOs for the Ethernet interface. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None. + * + * Assumptions: + * + ****************************************************************************/ + +static inline void stm32_ethgpioconfig(FAR struct stm32_ethmac_s *priv) +{ + /* Configure GPIO pins to support Ethernet */ + +#if defined(CONFIG_STM32_MII) || defined(CONFIG_STM32_RMII) + + /* MDC and MDIO are common to both modes */ + + stm32_configgpio(GPIO_ETH_MDC); + stm32_configgpio(GPIO_ETH_MDIO); + + /* Set up the MII interface */ + +#if defined(CONFIG_STM32_MII) + + /* Select the MII interface */ + + stm32_selectmii(); + + /* Provide clocking via MCO1 or MCO2: + * + * "MCO1 (microcontroller clock output), used to output HSI, LSE, HSE or PLL + * clock (through a configurable prescaler) on PA8 pin." + * + * "MCO2 (microcontroller clock output), used to output HSE, PLL, SYSCLK or + * PLLI2S clock (through a configurable prescaler) on PC9 pin." + */ + +# if defined(CONFIG_STM32_MII_MCO1) + /* Configure MC01 to drive the PHY. Board logic must provide MC01 clocking + * info. + */ + + stm32_configgpio(GPIO_MCO1); + stm32_mco1config(BOARD_CFGR_MC01_SOURCE, BOARD_CFGR_MC01_DIVIDER); + +# elif defined(CONFIG_STM32_MII_MCO2) + /* Configure MC02 to drive the PHY. Board logic must provide MC02 clocking + * info. + */ + + stm32_configgpio(GPIO_MCO2); + stm32_mco2config(BOARD_CFGR_MC02_SOURCE, BOARD_CFGR_MC02_DIVIDER); +# endif + + /* MII interface pins (17): + * + * MII_TX_CLK, MII_TXD[3:0], MII_TX_EN, MII_RX_CLK, MII_RXD[3:0], MII_RX_ER, + * MII_RX_DV, MII_CRS, MII_COL, MDC, MDIO + */ + + stm32_configgpio(GPIO_ETH_MII_COL); + stm32_configgpio(GPIO_ETH_MII_CRS); + stm32_configgpio(GPIO_ETH_MII_RXD0); + stm32_configgpio(GPIO_ETH_MII_RXD1); + stm32_configgpio(GPIO_ETH_MII_RXD2); + stm32_configgpio(GPIO_ETH_MII_RXD3); + stm32_configgpio(GPIO_ETH_MII_RX_CLK); + stm32_configgpio(GPIO_ETH_MII_RX_DV); + stm32_configgpio(GPIO_ETH_MII_RX_ER); + stm32_configgpio(GPIO_ETH_MII_TXD0); + stm32_configgpio(GPIO_ETH_MII_TXD1); + stm32_configgpio(GPIO_ETH_MII_TXD2); + stm32_configgpio(GPIO_ETH_MII_TXD3); + stm32_configgpio(GPIO_ETH_MII_TX_CLK); + stm32_configgpio(GPIO_ETH_MII_TX_EN); + + /* Set up the RMII interface. */ + +#elif defined(CONFIG_STM32_RMII) + + /* Select the RMII interface */ + + stm32_selectrmii(); + + /* RMII interface pins (7): + * + * RMII_TXD[1:0], RMII_TX_EN, RMII_RXD[1:0], RMII_CRS_DV, MDC, MDIO, + * RMII_REF_CLK + */ + + stm32_configgpio(GPIO_ETH_RMII_CRS_DV); + stm32_configgpio(GPIO_ETH_RMII_REF_CLK); + stm32_configgpio(GPIO_ETH_RMII_RXD0); + stm32_configgpio(GPIO_ETH_RMII_RXD1); + stm32_configgpio(GPIO_ETH_RMII_TXD0); + stm32_configgpio(GPIO_ETH_RMII_TXD1); + stm32_configgpio(GPIO_ETH_RMII_TX_CLK); + stm32_configgpio(GPIO_ETH_RMII_TX_EN); + +#endif +#endif + + /* Enable pulse-per-second (PPS) output signal */ + + stm32_configgpio(GPIO_ETH_PPS_OUT); +} + +/**************************************************************************** + * Function: stm32_ethreset + * + * Description: + * Reset the Ethernet block. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None. + * + * Assumptions: + * + ****************************************************************************/ + +static void stm32_ethreset(FAR struct stm32_ethmac_s *priv) +{ + uint32_t regval; + + /* Reset the Ethernet on the AHB1 bus */ + + regval = stm32_getreg(STM32_RCC_AHB1RSTR); + regval |= RCC_AHB1RSTR_ETHMACRST; + stm32_putreg(regval, STM32_RCC_AHB1RSTR); + + regval &= ~RCC_AHB1RSTR_ETHMACRST; + stm32_putreg(regval, STM32_RCC_AHB1RSTR); + + /* Perform a software reset by setting the SR bit in the DMABMR register. + * This Resets all MAC subsystem internal registers and logic. After this + * reset all the registers holds their reset values. + */ + + regval = stm32_getreg(STM32_ETH_DMABMR); + regval |= ETH_DMABMR_SR; + stm32_putreg(regval, STM32_ETH_DMABMR); + + /* Wait for software reset to complete. The SR bit is cleared automatically + * after the reset operation has completed in all of the core clock domains. + */ + + while ((stm32_getreg(STM32_ETH_DMABMR) & ETH_DMABMR_SR) != 0); +} + +/**************************************************************************** + * Function: stm32_macconfig + * + * Description: + * Configure the Ethernet MAC for DMA operation. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int stm32_macconfig(FAR struct stm32_ethmac_s *priv) +{ + uint32_t regval; + + /* Set up the MACCR register */ + + regval = stm32_getreg(STM32_ETH_MACCR); + regval &= ~MACCR_CLEAR_BITS; + regval |= MACCR_SET_BITS; + + if (priv->fduplex) + { + /* Set the DM bit for full duplex support */ + + regval |= ETH_MACCR_DM; + } + + if (priv->mbps100) + { + /* Set the FES bit for 100Mbps fast ethernet support */ + + regval |= ETH_MACCR_FES; + } + + stm32_putreg(regval, STM32_ETH_MACCR); + + /* Set up the MACFFR register */ + + regval = stm32_getreg(STM32_ETH_MACFFR); + regval &= ~MACFFR_CLEAR_BITS; + regval |= MACFFR_SET_BITS; + stm32_putreg(regval, STM32_ETH_MACFFR); + + /* Set up the MACHTHR and MACHTLR registers */ + + stm32_putreg(0, STM32_ETH_MACHTHR); + stm32_putreg(0, STM32_ETH_MACHTLR); + + /* Setup up the MACFCR register */ + + regval = stm32_getreg(STM32_ETH_MACFCR); + regval &= ~MACFCR_CLEAR_MASK; + regval |= MACFCR_SET_MASK; + stm32_putreg(regval, STM32_ETH_MACFCR); + + /* Setup up the MACVLANTR register */ + + stm32_putreg(0, STM32_ETH_MACVLANTR); + + /* DMA Configuration */ + /* Set up the DMAOMR register */ + + regval = stm32_getreg(STM32_ETH_DMAOMR); + regval &= ~DMAOMR_CLEAR_MASK; + regval |= DMAOMR_SET_MASK; + stm32_putreg(regval, STM32_ETH_DMAOMR); + + /* Set up the DMABMR register */ + + regval = stm32_getreg(STM32_ETH_DMABMR); + regval &= ~DMABMR_CLEAR_MASK; + regval |= DMABMR_SET_MASK; + stm32_putreg(regval, STM32_ETH_DMABMR); + + return OK; +} + +/**************************************************************************** + * Function: stm32_macaddress + * + * Description: + * Configure the selected MAC address. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static void stm32_macaddress(FAR struct stm32_ethmac_s *priv) +{ + FAR struct uip_driver_s *dev = &priv->dev; + uint32_t regval; + + nllvdbg("%s MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->d_ifname, + dev->d_mac.ether_addr_octet[0], dev->d_mac.ether_addr_octet[1], + dev->d_mac.ether_addr_octet[2], dev->d_mac.ether_addr_octet[3], + dev->d_mac.ether_addr_octet[4], dev->d_mac.ether_addr_octet[5]); + + /* Set the MAC address high register */ + + regval = ((uint32_t)dev->d_mac.ether_addr_octet[5] << 8) | + (uint32_t)dev->d_mac.ether_addr_octet[4]; + stm32_putreg(regval, STM32_ETH_MACA0HR); + + /* Set the MAC address low register */ + + regval = ((uint32_t)dev->d_mac.ether_addr_octet[3] << 24) | + ((uint32_t)dev->d_mac.ether_addr_octet[2] << 16) | + ((uint32_t)dev->d_mac.ether_addr_octet[1] << 8) | + (uint32_t)dev->d_mac.ether_addr_octet[0]; + stm32_putreg(regval, STM32_ETH_MACA0LR); +} + +/**************************************************************************** + * Function: stm32_macenable + * + * Description: + * Enable normal MAC operation. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int stm32_macenable(FAR struct stm32_ethmac_s *priv) +{ + uint32_t regval; + + /* Set the MAC address */ + + stm32_macaddress(priv); + + /* Enable transmit state machine of the MAC for transmission on the MII */ + + regval = stm32_getreg(STM32_ETH_MACCR); + regval |= ETH_MACCR_TE; + stm32_putreg(regval, STM32_ETH_MACCR); + + /* Flush Transmit FIFO */ + + regval = stm32_getreg(STM32_ETH_DMAOMR); + regval |= ETH_DMAOMR_FTF; + stm32_putreg(regval, STM32_ETH_DMAOMR); + + /* Enable receive state machine of the MAC for reception from the MII */ + + /* Enables or disables the MAC reception. */ + + regval = stm32_getreg(STM32_ETH_MACCR); + regval |= ETH_MACCR_RE; + stm32_putreg(regval, STM32_ETH_MACCR); + + /* Start DMA transmission */ + + regval = stm32_getreg(STM32_ETH_DMAOMR); + regval |= ETH_DMAOMR_ST; + stm32_putreg(regval, STM32_ETH_DMAOMR); + + /* Start DMA reception */ + + regval = stm32_getreg(STM32_ETH_DMAOMR); + regval |= ETH_DMAOMR_SR; + stm32_putreg(regval, STM32_ETH_DMAOMR); + + /* Enable Ethernet DMA interrupts. + * + * The STM32 hardware supports two interrupts: (1) one dedicated to normal + * Ethernet operations and the other, used only for the Ethernet wakeup + * event. The wake-up interrupt is not used by this driver. + * + * The first Ethernet vector is reserved for interrupts generated by the + * MAC and the DMA. The MAC provides PMT and time stamp trigger interrupts, + * neither of which are used by this driver. + */ + + stm32_putreg(ETH_MACIMR_ALLINTS, STM32_ETH_MACIMR); + + /* Ethernet DMA supports two classes of interrupts: Normal interrupt + * summary (NIS) and Abnormal interrupt summary (AIS) with a variety + * individual normal and abnormal interrupting events. Here only + * the normal receive event is enabled (unless DEBUG is enabled). Transmit + * events will only be enabled when a transmit interrupt is expected. + */ + + stm32_putreg((ETH_DMAINT_RECV_ENABLE | ETH_DMAINT_ERROR_ENABLE), STM32_ETH_DMAIER); + return OK; +} + +/**************************************************************************** + * Function: stm32_ethconfig + * + * Description: + * Configure the Ethernet interface for DMA operation. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int stm32_ethconfig(FAR struct stm32_ethmac_s *priv) +{ + int ret; + + /* NOTE: The Ethernet clocks were initialized early in the boot-up + * sequence in stm32_rcc.c. + */ + + /* Reset the Ethernet block */ + + nllvdbg("Reset the Ethernet block\n"); + stm32_ethreset(priv); + + /* Initialize the PHY */ + + nllvdbg("Initialize the PHY\n"); + ret = stm32_phyinit(priv); + if (ret < 0) + { + return ret; + } + + /* Initialize the MAC and DMA */ + + nllvdbg("Initialize the MAC and DMA\n"); + ret = stm32_macconfig(priv); + if (ret < 0) + { + return ret; + } + + /* Initialize the free buffer list */ + + stm32_initbuffer(priv); + + /* Initialize TX Descriptors list: Chain Mode */ + + stm32_txdescinit(priv); + + /* Initialize RX Descriptors list: Chain Mode */ + + stm32_rxdescinit(priv); + + /* Enable normal MAC operation */ + + nllvdbg("Enable normal operation\n"); + return stm32_macenable(priv); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: stm32_ethinitialize + * + * Description: + * Initialize the Ethernet driver for one interface. If the STM32 chip + * supports multiple Ethernet controllers, then board specific logic + * must implement up_netinitialize() and call this function to initialize + * the desired interfaces. + * + * Parameters: + * intf - In the case where there are multiple EMACs, this value + * identifies which EMAC is to be initialized. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +#if STM32_NETHERNET == 1 +static inline +#endif + +int stm32_ethinitialize(int intf) +{ + struct stm32_ethmac_s *priv; + + nvdbg("intf: %d\n", intf); + + /* Get the interface structure associated with this interface number. */ + + DEBUGASSERT(intf < STM32_NETHERNET); + priv = &g_stm32ethmac[intf]; + + /* Initialize the driver structure */ + + memset(priv, 0, sizeof(struct stm32_ethmac_s)); + priv->dev.d_ifup = stm32_ifup; /* I/F up (new IP address) callback */ + priv->dev.d_ifdown = stm32_ifdown; /* I/F down callback */ + priv->dev.d_txavail = stm32_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_IGMP + priv->dev.d_addmac = stm32_addmac; /* Add multicast MAC address */ + priv->dev.d_rmmac = stm32_rmmac; /* Remove multicast MAC address */ +#endif + priv->dev.d_private = (void*)g_stm32ethmac; /* Used to recover private state from dev */ + + /* Create a watchdog for timing polling for and timing of transmisstions */ + + priv->txpoll = wd_create(); /* Create periodic poll timer */ + priv->txtimeout = wd_create(); /* Create TX timeout timer */ + + /* Configure GPIO pins to support Ethernet */ + + stm32_ethgpioconfig(priv); + + /* Attach the IRQ to the driver */ + + if (irq_attach(STM32_IRQ_ETH, stm32_interrupt)) + { + /* We could not attach the ISR to the interrupt */ + + return -EAGAIN; + } + + /* Put the interface in the down state. */ + + stm32_ifdown(&priv->dev); + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + (void)netdev_register(&priv->dev); + return OK; +} + +/**************************************************************************** + * Function: up_netinitialize + * + * Description: + * This is the "standard" network initialization logic called from the + * low-level initialization logic in up_initialize.c. If STM32_NETHERNET + * greater than one, then board specific logic will have to supply a + * version of up_netinitialize() that calls stm32_ethinitialize() with + * the appropriate interface number. + * + * Parameters: + * None. + * + * Returned Value: + * None. + * + * Assumptions: + * + ****************************************************************************/ + +#if STM32_NETHERNET == 1 +void up_netinitialize(void) +{ + (void)stm32_ethinitialize(0); +} +#endif + +#endif /* STM32_NETHERNET > 0 */ +#endif /* CONFIG_NET && CONFIG_STM32_ETHMAC */ diff --git a/nuttx/arch/arm/src/stm32/stm32_eth.h b/nuttx/arch/arm/src/stm32/stm32_eth.h new file mode 100644 index 0000000000..188dc10d36 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_eth.h @@ -0,0 +1,97 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_eth.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_ETH_H +#define __ARCH_ARM_SRC_STM32_STM32_ETH_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" + +#if STM32_NETHERNET > 0 + +#include "chip/stm32_eth.h" + +#ifndef __ASSEMBLY__ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Function: stm32_ethinitialize + * + * Description: + * Initialize the Ethernet driver for one interface. If the STM32 chip + * supports multiple Ethernet controllers, then board specific logic + * must implement up_netinitialize() and call this function to initialize + * the desired interfaces. + * + * Parameters: + * intf - In the case where there are multiple EMACs, this value + * identifies which EMAC is to be initialized. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ************************************************************************************/ + +#if STM32_NETHERNET > 1 +EXTERN int stm32_ethinitialize(int intf); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* STM32_NETHERNET > 0 */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_ETH_H */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_exti.h b/nuttx/arch/arm/src/stm32/stm32_exti.h new file mode 100644 index 0000000000..6dddf38360 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_exti.h @@ -0,0 +1,119 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_exti.h + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_EXTI_H +#define __ARCH_ARM_SRC_STM32_STM32_EXTI_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include + +#include "chip.h" +#include "chip/stm32_exti.h" + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_gpiosetevent + * + * Description: + * Sets/clears GPIO based event and interrupt triggers. + * + * Parameters: + * - pinset: gpio pin configuration + * - rising/falling edge: enables + * - event: generate event when set + * - func: when non-NULL, generate interrupt + * + * Returns: + * The previous value of the interrupt handler function pointer. This value may, + * for example, be used to restore the previous handler when multiple handlers are + * used. + * + ************************************************************************************/ + +EXTERN xcpt_t stm32_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge, + bool event, xcpt_t func); + +/**************************************************************************** + * Name: stm32_exti_alarm + * + * Description: + * Sets/clears EXTI alarm interrupt. + * + * Parameters: + * - rising/falling edge: enables interrupt on rising/falling edget + * - event: generate event when set + * - func: when non-NULL, generate interrupt + * + * Returns: + * The previous value of the interrupt handler function pointer. This + * value may, for example, be used to restore the previous handler when + * multiple handlers are used. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +EXTERN xcpt_t stm32_exti_alarm(bool risingedge, bool fallingedge, bool event, + xcpt_t func); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_EXTI_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_exti_alarm.c b/nuttx/arch/arm/src/stm32/stm32_exti_alarm.c new file mode 100644 index 0000000000..07db26fd40 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_exti_alarm.c @@ -0,0 +1,167 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_exti_alarm.c + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Diego Sanchez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include + +#include + +#include "up_arch.h" +#include "chip.h" +#include "stm32_gpio.h" +#include "stm32_exti.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Interrupt handlers attached to the ALARM EXTI */ + +static xcpt_t stm32_exti_callback; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + + /**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_exti_alarm_isr + * + * Description: + * EXTI ALARM interrupt service routine/dispatcher + * + ****************************************************************************/ + +static int stm32_exti_alarm_isr(int irq, void *context) +{ + int ret = OK; + + /* Clear the pending EXTI interrupt */ + + putreg32(EXTI_RTC_ALARM, STM32_EXTI_PR); + + /* And dispatch the interrupt to the handler */ + + if (stm32_exti_callback) + { + ret = stm32_exti_callback(irq, context); + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_exti_alarm + * + * Description: + * Sets/clears EXTI alarm interrupt. + * + * Parameters: + * - rising/falling edge: enables interrupt on rising/falling edget + * - event: generate event when set + * - func: when non-NULL, generate interrupt + * + * Returns: + * The previous value of the interrupt handler function pointer. This + * value may, for example, be used to restore the previous handler when + * multiple handlers are used. + * + ****************************************************************************/ + +xcpt_t stm32_exti_alarm(bool risingedge, bool fallingedge, bool event, + xcpt_t func) +{ + xcpt_t oldhandler; + + /* Get the previous GPIO IRQ handler; Save the new IRQ handler. */ + + oldhandler = stm32_exti_callback; + stm32_exti_callback = func; + + /* Install external interrupt handlers (if not already attached) */ + + if (func) + { + irq_attach(STM32_IRQ_RTCALRM, stm32_exti_alarm_isr); + up_enable_irq(STM32_IRQ_RTCALRM); + } + else + { + up_disable_irq(STM32_IRQ_RTCALRM); + } + + /* Configure rising/falling edges */ + + modifyreg32(STM32_EXTI_RTSR, + risingedge ? 0 : EXTI_RTC_ALARM, + risingedge ? EXTI_RTC_ALARM : 0); + modifyreg32(STM32_EXTI_FTSR, + fallingedge ? 0 : EXTI_RTC_ALARM, + fallingedge ? EXTI_RTC_ALARM : 0); + + /* Enable Events and Interrupts */ + + modifyreg32(STM32_EXTI_EMR, + event ? 0 : EXTI_RTC_ALARM, + event ? EXTI_RTC_ALARM : 0); + modifyreg32(STM32_EXTI_IMR, + func ? 0 : EXTI_RTC_ALARM, + func ? EXTI_RTC_ALARM : 0); + + /* Return the old IRQ handler */ + + return oldhandler; +} diff --git a/nuttx/arch/arm/src/stm32/stm32_exti_gpio.c b/nuttx/arch/arm/src/stm32/stm32_exti_gpio.c new file mode 100644 index 0000000000..f897691ef0 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_exti_gpio.c @@ -0,0 +1,337 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_exti_gpio.c + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Gregory Nutt + * Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "up_arch.h" +#include "chip.h" +#include "stm32_gpio.h" +#include "stm32_exti.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Interrupt handlers attached to each EXTI */ + +static xcpt_t stm32_exti_callbacks[16]; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + + /**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Interrupt Service Routines - Dispatchers + ****************************************************************************/ + +static int stm32_exti0_isr(int irq, void *context) +{ + int ret = OK; + + /* Clear the pending interrupt */ + + putreg32(0x0001, STM32_EXTI_PR); + + /* And dispatch the interrupt to the handler */ + + if (stm32_exti_callbacks[0]) + { + ret = stm32_exti_callbacks[0](irq, context); + } + + return ret; +} + +static int stm32_exti1_isr(int irq, void *context) +{ + int ret = OK; + + /* Clear the pending interrupt */ + + putreg32(0x0002, STM32_EXTI_PR); + + /* And dispatch the interrupt to the handler */ + + if (stm32_exti_callbacks[1]) + { + ret = stm32_exti_callbacks[1](irq, context); + } + + return ret; +} + +static int stm32_exti2_isr(int irq, void *context) +{ + int ret = OK; + + /* Clear the pending interrupt */ + + putreg32(0x0004, STM32_EXTI_PR); + + /* And dispatch the interrupt to the handler */ + + if (stm32_exti_callbacks[2]) + { + ret = stm32_exti_callbacks[2](irq, context); + } + + return ret; +} + +static int stm32_exti3_isr(int irq, void *context) +{ + int ret = OK; + + /* Clear the pending interrupt */ + + putreg32(0x0008, STM32_EXTI_PR); + + /* And dispatch the interrupt to the handler */ + + if (stm32_exti_callbacks[3]) + { + ret = stm32_exti_callbacks[3](irq, context); + } + + return ret; +} + +static int stm32_exti4_isr(int irq, void *context) +{ + int ret = OK; + + /* Clear the pending interrupt */ + + putreg32(0x0010, STM32_EXTI_PR); + + /* And dispatch the interrupt to the handler */ + + if (stm32_exti_callbacks[4]) + { + ret = stm32_exti_callbacks[4](irq, context); + } + + return ret; +} + +static int stm32_exti_multiisr(int irq, void *context, int first, int last) +{ + uint32_t pr; + int pin; + int ret = OK; + + /* Examine the state of each pin in the group */ + + pr = getreg32(STM32_EXTI_PR); + + /* And dispatch the interrupt to the handler */ + + for (pin = first; pin <= last; pin++) + { + /* Is an interrupt pending on this pin? */ + + uint32_t mask = (1 << pin); + if ((pr & mask) != 0) + { + /* Clear the pending interrupt */ + + putreg32(mask, STM32_EXTI_PR); + + /* And dispatch the interrupt to the handler */ + + if (stm32_exti_callbacks[pin]) + { + int tmp = stm32_exti_callbacks[pin](irq, context); + if (tmp != OK) + { + ret = tmp; + } + } + } + } + + return ret; +} + +static int stm32_exti95_isr(int irq, void *context) +{ + return stm32_exti_multiisr(irq, context, 5, 9); +} + +static int stm32_exti1510_isr(int irq, void *context) +{ + return stm32_exti_multiisr(irq, context, 10, 15); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_gpiosetevent + * + * Description: + * Sets/clears GPIO based event and interrupt triggers. + * + * Parameters: + * - pinset: gpio pin configuration + * - rising/falling edge: enables + * - event: generate event when set + * - func: when non-NULL, generate interrupt + * + * Returns: + * The previous value of the interrupt handler function pointer. This value may, + * for example, be used to restore the previous handler when multiple handlers are + * used. + * + ****************************************************************************/ + +xcpt_t stm32_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge, + bool event, xcpt_t func) +{ + uint32_t pin = pinset & GPIO_PIN_MASK; + uint32_t exti = STM32_EXTI_BIT(pin); + int irq; + xcpt_t handler; + xcpt_t oldhandler = NULL; + + /* Select the interrupt handler for this EXTI pin */ + + if (pin < 5) + { + irq = pin + STM32_IRQ_EXTI0; + switch (pin) + { + case 0: + handler = stm32_exti0_isr; + break; + + case 1: + handler = stm32_exti1_isr; + break; + + case 2: + handler = stm32_exti2_isr; + break; + + case 3: + handler = stm32_exti3_isr; + break; + + default: + handler = stm32_exti4_isr; + break; + } + } + else if (pin < 10) + { + irq = STM32_IRQ_EXTI95; + handler = stm32_exti95_isr; + } + else + { + irq = STM32_IRQ_EXTI1510; + handler = stm32_exti1510_isr; + } + + /* Get the previous GPIO IRQ handler; Save the new IRQ handler. */ + + oldhandler = stm32_exti_callbacks[pin]; + stm32_exti_callbacks[pin] = func; + + /* Install external interrupt handlers */ + + if (func) + { + irq_attach(irq, handler); + up_enable_irq(irq); + } + else + { + up_disable_irq(irq); + } + + /* Configure GPIO, enable EXTI line enabled if event or interrupt is + * enabled. + */ + + if (event || func) + { + pinset |= GPIO_EXTI; + } + + stm32_configgpio(pinset); + + /* Configure rising/falling edges */ + + modifyreg32(STM32_EXTI_RTSR, + risingedge ? 0 : exti, + risingedge ? exti : 0); + modifyreg32(STM32_EXTI_FTSR, + fallingedge ? 0 : exti, + fallingedge ? exti : 0); + + /* Enable Events and Interrupts */ + + modifyreg32(STM32_EXTI_EMR, + event ? 0 : exti, + event ? exti : 0); + modifyreg32(STM32_EXTI_IMR, + func ? 0 : exti, + func ? exti : 0); + + /* Return the old IRQ handler */ + + return oldhandler; +} diff --git a/nuttx/arch/arm/src/stm32/stm32_flash.c b/nuttx/arch/arm/src/stm32/stm32_flash.c new file mode 100644 index 0000000000..83fcc6172e --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_flash.c @@ -0,0 +1,247 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_flash.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/* Provides standard flash access functions, to be used by the flash mtd driver. + * The interface is defined in the include/nuttx/progmem.h + * + * Requirements during write/erase operations on FLASH: + * - HSI must be ON. + * - Low Power Modes are not permitted during write/erase + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include + +#include "stm32_flash.h" +#include "stm32_rcc.h" +#include "stm32_waste.h" + +#include "up_arch.h" + +/* Only for the STM32F10xx family for now */ + +#ifdef CONFIG_STM32_STM32F10XX + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#define FLASH_KEY1 0x45670123 +#define FLASH_KEY2 0xCDEF89AB + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +void stm32_flash_unlock(void) +{ + while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) + { + up_waste(); + } + + if (getreg32(STM32_FLASH_CR) & FLASH_CR_LOCK) + { + /* Unlock sequence */ + + putreg32(FLASH_KEY1, STM32_FLASH_KEYR); + putreg32(FLASH_KEY2, STM32_FLASH_KEYR); + } +} + +void stm32_flash_lock(void) +{ + modifyreg16(STM32_FLASH_CR, 0, FLASH_CR_LOCK); +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +uint16_t up_progmem_npages(void) +{ + return STM32_FLASH_NPAGES; +} + +bool up_progmem_isuniform(void) +{ + return true; +} + +uint16_t up_progmem_pagesize(uint16_t page) +{ + return STM32_FLASH_PAGESIZE; +} + +int up_progmem_getpage(uint32_t addr) +{ + if (addr >= STM32_FLASH_SIZE) + { + return -EFAULT; + } + + return addr / STM32_FLASH_PAGESIZE; +} + +int up_progmem_erasepage(uint16_t page) +{ + uint32_t addr; + uint16_t count; + + if (page >= STM32_FLASH_NPAGES) + { + return -EFAULT; + } + + /* Get flash ready and begin erasing single page */ + + if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION)) + { + return -EPERM; + } + + stm32_flash_unlock(); + + modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PER); + putreg32(page * STM32_FLASH_PAGESIZE, STM32_FLASH_AR); + modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_STRT); + + while(getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste(); + + modifyreg32(STM32_FLASH_CR, FLASH_CR_PER, 0); + + /* Verify */ + + for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE; + count; count-=4, addr += 4) + { + if (getreg32(addr) != 0xffffffff) + { + return -EIO; + } + } + + return STM32_FLASH_PAGESIZE; +} + +int up_progmem_ispageerased(uint16_t page) +{ + uint32_t addr; + uint16_t count; + uint16_t bwritten = 0; + + if (page >= STM32_FLASH_NPAGES) + { + return -EFAULT; + } + + /* Verify */ + + for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE; + count; count--, addr++) + { + if (getreg8(addr) != 0xff) + { + bwritten++; + } + } + + return bwritten; +} + +int up_progmem_write(uint32_t addr, const void *buf, size_t count) +{ + uint16_t *hword = (uint16_t *)buf; + size_t written = count; + + /* STM32 requires half-word access */ + + if (count & 1) + { + return -EINVAL; + } + + /* Check for valid address range */ + + if ((addr+count) >= STM32_FLASH_SIZE) + { + return -EFAULT; + } + + /* Get flash ready and begin flashing */ + + if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION)) + { + return -EPERM; + } + + stm32_flash_unlock(); + + modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PG); + + for (addr += STM32_FLASH_BASE; count; count--, hword++, addr+=2) + { + /* Write half-word and wait to complete */ + + putreg16(*hword, addr); + + while(getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste(); + + /* Verify */ + + if (getreg32(STM32_FLASH_SR) & FLASH_SR_WRPRT_ERR) + { + modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0); + return -EROFS; + } + + if (getreg16(addr) != *hword) + { + modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0); + return -EIO; + } + + } + + modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0); + return written; +} + +#endif /* CONFIG_STM32_STM32F10XX */ diff --git a/nuttx/arch/arm/src/stm32/stm32_flash.h b/nuttx/arch/arm/src/stm32/stm32_flash.h new file mode 100644 index 0000000000..10c5cc189e --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_flash.h @@ -0,0 +1,49 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_flash.h + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_FLASH_H +#define __ARCH_ARM_SRC_STM32_STM32_FLASH_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +#include "chip.h" +#include "chip/stm32_flash.h" + +#endif /* __ARCH_ARM_SRC_STM32_STM32_FLASH_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_fsmc.h b/nuttx/arch/arm/src/stm32/stm32_fsmc.h new file mode 100644 index 0000000000..9fd4f3fa25 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_fsmc.h @@ -0,0 +1,304 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_fsmc.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_FSMC_H +#define __ARCH_ARM_SRC_STM32_STM32_FSMC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +#define STM32_FSMC_BCR_OFFSET(n) (8*((n)-1)) +#define STM32_FSMC_BCR1_OFFSET 0x0000 /* SRAM/NOR-Flash chip-select control registers 1 */ +#define STM32_FSMC_BCR2_OFFSET 0x0008 /* SRAM/NOR-Flash chip-select control registers 2 */ +#define STM32_FSMC_BCR3_OFFSET 0x0010 /* SRAM/NOR-Flash chip-select control registers 3 */ +#define STM32_FSMC_BCR4_OFFSET 0x0018 /* SRAM/NOR-Flash chip-select control registers 4 */ + +#define STM32_FSMC_BTR_OFFSET(n) (8*((n)-1)+0x0004) +#define STM32_FSMC_BTR1_OFFSET 0x0004 /* SRAM/NOR-Flash chip-select timing registers 1 */ +#define STM32_FSMC_BTR2_OFFSET 0x000c /* SRAM/NOR-Flash chip-select timing registers 2 */ +#define STM32_FSMC_BTR3_OFFSET 0x0014 /* SRAM/NOR-Flash chip-select timing registers 3 */ +#define STM32_FSMC_BTR4_OFFSET 0x001c /* SRAM/NOR-Flash chip-select timing registers 4 */ + +#define STM32_FSMC_BWTR_OFFSET(n) (8*((n)-1)+0x0104) +#define STM32_FSMC_BWTR1_OFFSET 0x0104 /* SRAM/NOR-Flash write timing registers 1 */ +#define STM32_FSMC_BWTR2_OFFSET 0x010c /* SRAM/NOR-Flash write timing registers 2 */ +#define STM32_FSMC_BWTR3_OFFSET 0x0114 /* SRAM/NOR-Flash write timing registers 3 */ +#define STM32_FSMC_BWTR4_OFFSET 0x011c /* SRAM/NOR-Flash write timing registers 4 */ + +#define STM32_FSMC_PCR_OFFSET(n) (0x0020*((n)-1)+0x0040) +#define STM32_FSMC_PCR2_OFFSET 0x0060 /* NAND Flash/PC Card controller register 2 */ +#define STM32_FSMC_PCR3_OFFSET 0x0080 /* NAND Flash/PC Card controller register 3 */ +#define STM32_FSMC_PCR4_OFFSET 0x00a0 /* NAND Flash/PC Card controller register 4 */ + +#define STM32_FSMC_SR_OFFSET(n) (0x0020*((n)-1)+0x0044) +#define STM32_FSMC_SR2_OFFSET 0x0064 /* NAND Flash/PC Card controller register 2 */ +#define STM32_FSMC_SR3_OFFSET 0x0084 /* NAND Flash/PC Card controller register 3 */ +#define STM32_FSMC_SR4_OFFSET 0x00a4 /* NAND Flash/PC Card controller register 4 */ + +#define STM32_FSMC_PMEM_OFFSET(n) (0x0020*((n)-1)+0x0048) +#define STM32_FSMC_PMEM2_OFFSET 0x0068 /* Common memory space timing register 2 */ +#define STM32_FSMC_PMEM3_OFFSET 0x0088 /* Common memory space timing register 3 */ +#define STM32_FSMC_PMEM4_OFFSET 0x00a8 /* Common memory space timing register 4 */ + +#define STM32_FSMC_PATT_OFFSET(n) (0x0020*((n)-1)+0x004c) +#define STM32_FSMC_PATT2_OFFSET 0x006c /* Attribute memory space timing register 2 */ +#define STM32_FSMC_PATT3_OFFSET 0x008c /* Attribute memory space timing register 3 */ +#define STM32_FSMC_PATT4_OFFSET 0x00ac /* Attribute memory space timing register 4 */ + +#define STM32_PIO4_OFFSET 0x00b0 /* I/O space timing register 4 */ + +#define STM32_FSMC_ECCR_OFFSET(n) (0x0020*((n)-1)+0x003c) +#define STM32_FSMC_ECCR2_OFFSET 0x0054 /* ECC result register 2 */ +#define STM32_FSMC_ECCR3_OFFSET 0x0074 /* ECC result register 3 */ + +/* Register Addresses ***************************************************************/ + +#define STM32_FSMC_BCR(n) (STM32_FSMC_BASE+STM32_FSMC_BCR_OFFSET(n)) +#define STM32_FSMC_BCR1 (STM32_FSMC_BASE+STM32_FSMC_BCR1_OFFSET ) +#define STM32_FSMC_BCR2 (STM32_FSMC_BASE+STM32_FSMC_BCR2_OFFSET ) +#define STM32_FSMC_BCR3 (STM32_FSMC_BASE+STM32_FSMC_BCR3_OFFSET ) +#define STM32_FSMC_BCR4 (STM32_FSMC_BASE+STM32_FSMC_BCR4_OFFSET ) + +#define STM32_FSMC_BTR(n) (STM32_FSMC_BASE+STM32_FSMC_BTR_OFFSET(n)) +#define STM32_FSMC_BTR1 (STM32_FSMC_BASE+STM32_FSMC_BTR1_OFFSET ) +#define STM32_FSMC_BTR2 (STM32_FSMC_BASE+STM32_FSMC_BTR2_OFFSET ) +#define STM32_FSMC_BTR3 (STM32_FSMC_BASE+STM32_FSMC_BTR3_OFFSET ) +#define STM32_FSMC_BTR4 (STM32_FSMC_BASE+STM32_FSMC_BTR4_OFFSET ) + +#define STM32_FSMC_BWTR(n) (STM32_FSMC_BASE+STM32_FSMC_BWTR_OFFSET(n)) +#define STM32_FSMC_BWTR1 (STM32_FSMC_BASE+STM32_FSMC_BWTR1_OFFSET ) +#define STM32_FSMC_BWTR2 (STM32_FSMC_BASE+STM32_FSMC_BWTR2_OFFSET ) +#define STM32_FSMC_BWTR3 (STM32_FSMC_BASE+STM32_FSMC_BWTR3_OFFSET ) +#define STM32_FSMC_BWTR4 (STM32_FSMC_BASE+STM32_FSMC_BWTR4_OFFSET ) + +#define STM32_FSMC_PCR(n) (STM32_FSMC_BASE+STM32_FSMC_PCR_OFFSET(n)) +#define STM32_FSMC_PCR2 (STM32_FSMC_BASE+STM32_FSMC_PCR2_OFFSET ) +#define STM32_FSMC_PCR3 (STM32_FSMC_BASE+STM32_FSMC_PCR3_OFFSET ) +#define STM32_FSMC_PCR4 (STM32_FSMC_BASE+STM32_FSMC_PCR4_OFFSET ) + +#define STM32_FSMC_SR(n) (STM32_FSMC_BASE+STM32_FSMC_SR_OFFSET(n)) +#define STM32_FSMC_SR2 (STM32_FSMC_BASE+STM32_FSMC_SR2_OFFSET ) +#define STM32_FSMC_SR3 (STM32_FSMC_BASE+STM32_FSMC_SR3_OFFSET ) +#define STM32_FSMC_SR4 (STM32_FSMC_BASE+STM32_FSMC_SR4_OFFSET ) + +#define STM32_FSMC_PMEM(n) (STM32_FSMC_BASE+STM32_FSMC_PMEM_OFFSET(n)) +#define STM32_FSMC_PMEM2 (STM32_FSMC_BASE+STM32_FSMC_PMEM2_OFFSET ) +#define STM32_FSMC_PMEM3 (STM32_FSMC_BASE+STM32_FSMC_PMEM3_OFFSET ) +#define STM32_FSMC_PMEM4 (STM32_FSMC_BASE+STM32_FSMC_PMEM4_OFFSET ) + +#define STM32_FSMC_PATT(n) (STM32_FSMC_BASE+STM32_FSMC_PATT_OFFSET(n)) +#define STM32_FSMC_PATT2 (STM32_FSMC_BASE+STM32_FSMC_PATT2_OFFSET ) +#define STM32_FSMC_PATT3 (STM32_FSMC_BASE+STM32_FSMC_PATT3_OFFSET ) +#define STM32_FSMC_PATT4 (STM32_FSMC_BASE+STM32_FSMC_PATT4_OFFSET ) + +#define STM32_PIO4 (STM32_FSMC_BASE+STM32_FSMC_PIO4_OFFSET ) + +#define STM32_FSMC_ECCR(n) (STM32_FSMC_BASE+STM32_FSMC_ECCR_OFFSET(n)) +#define STM32_FSMC_ECCR2 (STM32_FSMC_BASE+STM32_FSMC_ECCR2_OFFSET ) +#define STM32_FSMC_ECCR3 (STM32_FSMC_BASE+STM32_FSMC_ECCR3_OFFSET ) + +/* Register Bitfield Definitions ****************************************************/ + +#define FSMC_BCR_MBKEN (1 << 0) /* Memory bank enable bit */ +#define FSMC_BCR_MUXEN (1 << 1) /* Address/data multiplexing enable bit */ +#define FSMC_BCR_MTYP_SHIFT (2) /* Memory type */ +#define FSMC_BCR_MTYP_MASK (3 << FSMC_BCR_MTYP_SHIFT) +# define FSMC_BCR_SRAM (0 << FSMC_BCR_MTYP_SHIFT) +# define FSMC_BCR_ROM (0 << FSMC_BCR_MTYP_SHIFT) +# define FSMC_BCR_PSRAM (1 << FSMC_BCR_MTYP_SHIFT) +# define FSMC_BCR_CRAM (1 << FSMC_BCR_MTYP_SHIFT) +# define FSMC_BCR_NOR (2 << FSMC_BCR_MTYP_SHIFT) +#define FSMC_BCR_MWID_SHIFT (4) /* Memory data bus width */ +#define FSMC_BCR_MWID_MASK (3 << FSMC_BCR_MWID_SHIFT) +# define FSMC_BCR_MWID8 (0 << FSMC_BCR_MWID_SHIFT) +# define FSMC_BCR_MWID16 (1 << FSMC_BCR_MWID_SHIFT) +#define FSMC_BCR_FACCEN (1 << 6) /* Flash access enable */ +#define FSMC_BCR_BURSTEN (1 << 8) /* Burst enable bit */ +#define FSMC_BCR_WAITPOL (1 << 9) /* Wait signal polarity bit */ +#define FSMC_BCR_WRAPMOD (1 << 10) /* Wrapped burst mode support */ +#define FSMC_BCR_WAITCFG (1 << 11) /* Wait timing configuration */ +#define FSMC_BCR_WREN (1 << 12) /* Write enable bit */ +#define FSMC_BCR_WAITEN (1 << 13) /* Wait enable bit */ +#define FSMC_BCR_EXTMOD (1 << 14) /* Extended mode enable */ +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define FSMC_BCR_ASYNCWAIT (1 << 15) /* Wait signal during asynchronous transfers */ +#endif +#define FSMC_BCR_CBURSTRW (1 << 19) /* Write burst enable */ + +#define FSMC_BCR_RSTVALUE 0x000003d2 + +#define FSMC_BTR_ADDSET_SHIFT (0) /* Address setup phase duration */ +#define FSMC_BTR_ADDSET_MASK (15 << FSMC_BTR_ADDSET_SHIFT) +# define FSMC_BTR_ADDSET(n) ((n-1) << FSMC_BTR_ADDSET_SHIFT) /* (n)xHCLK n=1..16 */ +#define FSMC_BTR_ADDHLD_SHIFT (4) /* Address-hold phase duration */ +#define FSMC_BTR_ADDHLD_MASK (15 << FSMC_BTR_ADDHLD_SHIFT) +# define FSMC_BTR_ADDHLD(n) ((n-1) << FSMC_BTR_ADDHLD_SHIFT) /* (n)xHCLK n=2..16*/ +#define FSMC_BTR_DATAST_SHIFT (8) /* Data-phase duration */ +#define FSMC_BTR_DATAST_MASK (255 << FSMC_BTR_DATAST_SHIFT) +# define FSMC_BTR_DATAST(n) ((n-1) << FSMC_BTR_DATAST_SHIFT) /* (n)xHCLK n=2..256 */ +#define FSMC_BTR_BUSTURN_SHIFT (16) /* Bus turnaround phase duration */ +#define FSMC_BTR_BUSTURN_MASK (15 << FSMC_BTR1_BUSTURN_SHIFT) +# define FSMC_BTR_BUSTRUN(n) ((n-1) << FSMC_BTR_BUSTURN_SHIFT) /* (n)xHCLK n=1..16 */ +#define FSMC_BTR_CLKDIV_SHIFT (20) /* Clock divide ratio */ +#define FSMC_BTR_CLKDIV_MASK (15 << FSMC_BTR_CLKDIV_SHIFT) +# define FSMC_BTR_CLKDIV(n) ((n-1) << FSMC_BTR_CLKDIV_SHIFT) /* (n)xHCLK n=2..16 */ +#define FSMC_BTR_DATLAT_SHIFT (24) /* Data latency */ +#define FSMC_BTR_DATLAT_MASK (15 << FSMC_BTR_DATLAT_SHIFT) +# define FSMC_BTR_DATLAT(n) ((n-2) << FSMC_BTR_DATLAT_SHIFT) /* (n)xHCLK n=2..17 */ +#define FSMC_BTR_ACCMOD_SHIFT (28) /* Access mode */ +#define FSMC_BTR_ACCMOD_MASK (3 << FSMC_BTR_ACCMOD_SHIFT) +# define FSMC_BTR_ACCMODA (0 << FSMC_BTR_ACCMOD_SHIFT) +# define FSMC_BTR_ACCMODB (1 << FSMC_BTR_ACCMOD_SHIFT) +# define FSMC_BTR_ACCMODC (2 << FSMC_BTR_ACCMOD_SHIFT) +# define FSMC_BTR_ACCMODD (3 << FSMC_BTR_ACCMOD_SHIFT) + +#define FSMC_BTR_RSTVALUE 0xffffffff + +#define FSMC_BWTR_ADDSET_SHIFT (0) /* Address setup phase duration */ +#define FSMC_BWTR_ADDSET_MASK (15 << FSMC_BWTR_ADDSET_SHIFT) +# define FSMC_BWTR_ADDSET(n) ((n-1) << FSMC_BWTR_ADDSET_SHIFT) /* (n)xHCLK n=1..16 */ +#define FSMC_BWTR_ADDHLD_SHIFT (4) /* Address-hold phase duration */ +#define FSMC_BWTR_ADDHLD_MASK (15 << FSMC_BWTR_ADDHLD_SHIFT) +# define FSMC_BWTR_ADDHLD(n) ((n-1) << FSMC_BWTR_ADDHLD_SHIFT) /* (n)xHCLK n=2..16*/ +#define FSMC_BWTR_DATAST_SHIFT (8) /* Data-phase duration */ +#define FSMC_BWTR_DATAST_MASK (255 << FSMC_BWTR_DATAST_SHIFT) +# define FSMC_BWTR_DATAST(n) ((n-1) << FSMC_BWTR_DATAST_SHIFT) /* (n)xHCLK n=2..256 */ +#define FSMC_BWTR_CLKDIV_SHIFT (20) /* Clock divide ratio */ +#define FSMC_BWTR_CLKDIV_MASK (15 << FSMC_BWTR_CLKDIV_SHIFT) +# define FSMC_BWTR_CLKDIV(n) ((n-1) << FSMC_BWTR_CLKDIV_SHIFT) /* (n)xHCLK n=2..16 */ +#define FSMC_BWTR_DATLAT_SHIFT (24) /* Data latency */ +#define FSMC_BWTR_DATLAT_MASK (15 << FSMC_BWTR_DATLAT_SHIFT) +# define FSMC_BWTR_DATLAT(n) ((n-2) << FSMC_BWTR_DATLAT_SHIFT) /* (n)xHCLK n=2..17 */ +#define FSMC_BWTR_ACCMOD_SHIFT (28) /* Access mode */ +#define FSMC_BWTR_ACCMOD_MASK (3 << FSMC_BWTR_ACCMOD_SHIFT) +# define FSMC_BWTR_ACCMODA (0 << FSMC_BWTR_ACCMOD_SHIFT) +# define FSMC_BWTR_ACCMODB (1 << FSMC_BWTR_ACCMOD_SHIFT) +# define FSMC_BWTR_ACCMODC (2 << FSMC_BWTR_ACCMOD_SHIFT) +# define FSMC_BWTR_ACCMODD (3 << FSMC_BTR_ACCMOD_SHIFT) + +#define FSMC_PCR_PWAITEN (1 << 1) /* Wait feature enable bit */ +#define FSMC_PCR_PBKEN (1 << 2) /* PC Card/NAND Flash memory bank enable bit */ +#define FSMC_PCR_PTYP (1 << 3) /* Memory type */ +#define FSMC_PCR_PWID_SHIFT (4) /* NAND Flash databus width */ +#define FSMC_PCR_PWID_MASK (3 << FSMC_PCR_PWID_SHIFT) +# define FSMC_PCR_PWID8 (0 << FSMC_PCR_PWID_SHIFT) +# define FSMC_PCR_PWID16 (1 << FSMC_PCR_PWID_SHIFT) +#define FSMC_PCR_ECCEN (1 << 6) /* ECC computation logic enable bit */ +#define FSMC_PCR_TCLR_SHIFT (9) /* CLE to RE delay */ +#define FSMC_PCR_TCLR_MASK (15 << FSMC_PCR_TCLR_SHIFT) +# define FSMC_PCR_TCLR(n) ((n-1) << FSMC_PCR_TCLR_SHIFT) /* (n)xHCLK n=1..16 */ +#define FSMC_PCR_TAR_SHIFT (13) /* ALE to RE delay */ +#define FSMC_PCR_TAR_MASK (15 << FSMC_PCR_TAR_MASK) +# define FSMC_PCR_TAR(n) ((n-1) << FSMC_PCR_TAR_SHIFT) /* (n)xHCLK n=1..16 */ +#define FSMC_PCR_ECCPS_SHIFT (17) /* ECC page size */ +#define FSMC_PCR_ECCPS_MASK (7 << FSMC_PCR_ECCPS_SHIFT) +# define FSMC_PCR_ECCPS256 (0 << FSMC_PCR_ECCPS_SHIFT) /* 256 bytes */ +# define FSMC_PCR_ECCPS512 (1 << FSMC_PCR_ECCPS_SHIFT) /* 512 bytes */ +# define FSMC_PCR_ECCPS1024 (2 << FSMC_PCR_ECCPS_SHIFT) /* 1024 bytes */ +# define FSMC_PCR_ECCPS2048 (3 << FSMC_PCR_ECCPS_SHIFT) /* 2048 bytes */ +# define FSMC_PCR_ECCPS4096 (4 << FSMC_PCR_ECCPS_SHIFT) /* 8192 bytes */ +# define FSMC_PCR_ECCPS8192 (5 << FSMC_PCR_ECCPS_SHIFT) /* 1024 bytes */ + +#define FSMC_SR_IRS (1 << 0) /* Interrupt Rising Edge status */ +#define FSMC_SR_ILS (1 << 1) /* Interrupt Level status */ +#define FSMC_SR_IFS (1 << 2) /* Interrupt Falling Edge status */ +#define FSMC_SR_IREN (1 << 3) /* Interrupt Rising Edge detection Enable bit */ +#define FSMC_SR_ILEN (1 << 4) /* Interrupt Level detection Enable bit */ +#define FSMC_SR_IFEN (1 << 5) /* Interrupt Falling Edge detection Enable bit */ +#define FSMC_SR_FEMPT (1 << 6) /* FIFO empty */ + +#define FSMC_PMEM_MEMSET_SHIFT (0) /* Common memory setup time */ +#define FSMC_PMEM_MEMSET_MASK (255 << FSMC_PMEM_MEMSET_SHIFT) +# define FSMC_PMEM_MEMSET(n) ((n-1) << FSMC_PMEM_MEMSET_SHIFT) /* (n)xHCLK n=1..256 */ +#define FSMC_PMEM_MEMWAIT_SHIFT (8) /* Common memory wait time */ +#define FSMC_PMEM_MEMWAIT_MASK (255 << FSMC_PMEM_MEMWAIT_SHIFT) +# define FSMC_PMEM_MEMWAIT(n) ((n-1) << FSMC_PMEM_MEMWAIT_SHIFT) /* (n)xHCLK n=2..256 */ +#define FSMC_PMEM_MEMHOLD_SHIFT (16) /* Common memoryhold time */ +#define FSMC_PMEM_MEMHOLD_MASK (255 << FSMC_PMEM_MEMHOLD_SHIFT) +# define FSMC_PMEM_MEMHOLD(n) ((n) << FSMC_PMEM_MEMHOLD_SHIFT) /* (n)xHCLK n=1..255 */ +#define FSMC_PMEM_MEMHIZ_SHIFT (24) /* Common memory databus HiZ time */ +#define FSMC_PMEM_MEMHIZ_MASK (255 << FSMC_PMEM_MEMHIZ_SHIFT) +# define FSMC_PMEM_MEMHIZ(n) ((n) << FSMC_PMEM_MEMHIZ_SHIFT) /* (n)xHCLK n=0..255 */ + +#define FSMC_PATT_ATTSET_SHIFT (0) /* Attribute memory setup time */ +#define FSMC_PATT_ATTSET_MASK (255 << FSMC_PATT_ATTSET_SHIFT) +# define FSMC_PATT_ATTSET(n) ((n-1) << FSMC_PATT_ATTSET_SHIFT) /* (n)xHCLK n=1..256 */ +#define FSMC_PATT_ATTWAIT_SHIFT (8) /* Attribute memory wait time */ +#define FSMC_PATT_ATTWAIT_MASK (255 << FSMC_PATT_ATTWAIT_SHIFT) +# define FSMC_PATT_ATTWAIT(n) ((n-1) << FSMC_PATT_ATTWAIT_SHIFT) /* (n)xHCLK n=2..256 */ +#define FSMC_PATT_ATTHOLD_SHIFT (16) /* Attribute memory hold time */ +#define FSMC_PATT_ATTHOLD_MASK (255 << FSMC_PATT_ATTHOLD_SHIFT) +# define FSMC_PATT_ATTHOLD(n) ((n) << FSMC_PATT_ATTHOLD_SHIFT) /* (n)xHCLK n=1..255 */ +#define FSMC_PATT_ATTHIZ_SHIFT (24) /* Attribute memory databus HiZ time */ +#define FSMC_PATT_ATTHIZ_MASK (255 << FSMC_PATT_ATTHIZ_SHIFT) +# define FSMC_PATT_ATTHIZ(n) ((n) << FSMC_PATT_ATTHIZ_SHIFT) /* (n)xHCLK n=0..255 */ + +#define FSMC_PIO4_IOSET_SHIFT (0) /* IOribute memory setup time */ +#define FSMC_PIO4_IOSET_MASK (255 << FSMC_PIO4_IOSET_SHIFT) +# define FSMC_PIO4_IOSET(n) ((n-1) << FSMC_PIO4_IOSET_SHIFT) /* (n)xHCLK n=1..256 */ +#define FSMC_PIO4_IOWAIT_SHIFT (8) /* IOribute memory wait time */ +#define FSMC_PIO4_IOWAIT_MASK (255 << FSMC_PIO4_IOWAIT_SHIFT) +# define FSMC_PIO4_IOWAIT(n) ((n-1) << FSMC_PIO4_IOWAIT_SHIFT) /* (n)xHCLK n=2..256 */ +#define FSMC_PIO4_IOHOLD_SHIFT (16) /* IOribute memory hold time */ +#define FSMC_PIO4_IOHOLD_MASK (255 << FSMC_PIO4_IOHOLD_SHIFT) +# define FSMC_PIO4_IOHOLD(n) ((n) << FSMC_PIO4_IOHOLD_SHIFT) /* (n)xHCLK n=1..255 */ +#define FSMC_PIO4_IOHIZ_SHIFT (24) /* IOribute memory databus HiZ time */ +#define FSMC_PIO4_IOHIZ_MASK (255 << FSMC_PIO4_IOHIZ_SHIFT) +# define FSMC_PIO4_IOHIZ(n) ((n) << FSMC_PIO4_IOHIZ_SHIFT) /* (n)xHCLK n=0..255 */ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32_STM32_FSMC_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_gpio.c b/nuttx/arch/arm/src/stm32/stm32_gpio.c new file mode 100644 index 0000000000..143e48a2c8 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_gpio.c @@ -0,0 +1,736 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_gpio.c + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Gregory Nutt + * Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "up_arch.h" + +#include "chip.h" +#include "stm32_gpio.h" + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# include "chip/stm32_syscfg.h" +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ +/* Base addresses for each GPIO block */ + +const uint32_t g_gpiobase[STM32_NGPIO_PORTS] = +{ +#if STM32_NGPIO_PORTS > 0 + STM32_GPIOA_BASE, +#endif +#if STM32_NGPIO_PORTS > 1 + STM32_GPIOB_BASE, +#endif +#if STM32_NGPIO_PORTS > 2 + STM32_GPIOC_BASE, +#endif +#if STM32_NGPIO_PORTS > 3 + STM32_GPIOD_BASE, +#endif +#if STM32_NGPIO_PORTS > 4 + STM32_GPIOE_BASE, +#endif +#if STM32_NGPIO_PORTS > 5 + STM32_GPIOF_BASE, +#endif +#if STM32_NGPIO_PORTS > 6 + STM32_GPIOG_BASE, +#endif +#if STM32_NGPIO_PORTS > 7 + STM32_GPIOH_BASE, +#endif +#if STM32_NGPIO_PORTS > 8 + STM32_GPIOI_BASE, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: stm32_gpioremap + * + * Description: + * + * Based on configuration within the .config file, this function will + * remaps positions of alternative functions. + * + ****************************************************************************/ + +static inline void stm32_gpioremap(void) +{ +#if defined(CONFIG_STM32_STM32F10XX) + + /* Remap according to the configuration within .config file */ + + uint32_t val = 0; + +#ifdef CONFIG_STM32_JTAG_FULL_ENABLE + /* The reset default */ +#elif CONFIG_STM32_JTAG_NOJNTRST_ENABLE + val |= AFIO_MAPR_SWJ; /* enabled but without JNTRST */ +#elif CONFIG_STM32_JTAG_SW_ENABLE + val |= AFIO_MAPR_SWDP; /* set JTAG-DP disabled and SW-DP enabled */ +#else + val |= AFIO_MAPR_DISAB; /* set JTAG-DP and SW-DP Disabled */ +#endif + +#ifdef CONFIG_STM32_TIM1_FULL_REMAP + val |= AFIO_MAPR_TIM1_FULLREMAP; +#endif +#ifdef CONFIG_STM32_TIM1_PARTIAL_REMAP + val |= AFIO_MAPR_TIM1_PARTREMAP; +#endif +#ifdef CONFIG_STM32_TIM2_FULL_REMAP + val |= AFIO_MAPR_TIM2_FULLREMAP; +#endif +#ifdef CONFIG_STM32_TIM2_PARTIAL_REMAP_1 + val |= AFIO_MAPR_TIM2_PARTREMAP1; +#endif +#ifdef CONFIG_STM32_TIM2_PARTIAL_REMAP_2 + val |= AFIO_MAPR_TIM2_PARTREMAP2; +#endif +#ifdef CONFIG_STM32_TIM3_FULL_REMAP + val |= AFIO_MAPR_TIM3_FULLREMAP; +#endif +#ifdef CONFIG_STM32_TIM3_PARTIAL_REMAP + val |= AFIO_MAPR_TIM3_PARTREMAP; +#endif +#ifdef CONFIG_STM32_TIM4_REMAP + val |= AFIO_MAPR_TIM4_REMAP; +#endif + +#ifdef CONFIG_STM32_USART1_REMAP + val |= AFIO_MAPR_USART1_REMAP; +#endif +#ifdef CONFIG_STM32_USART2_REMAP + val |= AFIO_MAPR_USART2_REMAP; +#endif +#ifdef CONFIG_STM32_USART3_FULL_REMAP + val |= AFIO_MAPR_USART3_FULLREMAP; +#endif +#ifdef CONFIG_STM32_USART3_PARTIAL_REMAP + val |= AFIO_MAPR_USART3_PARTREMAP; +#endif + +#ifdef CONFIG_STM32_SPI1_REMAP + val |= AFIO_MAPR_SPI1_REMAP; +#endif +#ifdef CONFIG_STM32_SPI3_REMAP +#endif + +#ifdef CONFIG_STM32_I2C1_REMAP + val |= AFIO_MAPR_I2C1_REMAP; +#endif + +#ifdef CONFIG_STM32_CAN1_REMAP1 + val |= AFIO_MAPR_PB89; +#endif +#ifdef CONFIG_STM32_CAN1_REMAP2 + val |= AFIO_MAPR_PD01; +#endif + + putreg32(val, STM32_AFIO_MAPR); +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: stm32_gpioinit + * + * Description: + * Based on configuration within the .config file, it does: + * - Remaps positions of alternative functions. + * + * Typically called from stm32_start(). + * + * Assumptions: + * This function is called early in the initialization sequence so that + * no mutual exlusion is necessary. + * + ****************************************************************************/ + +void stm32_gpioinit(void) +{ + /* Remap according to the configuration within .config file */ + + stm32_gpioremap(); +} + +/**************************************************************************** + * Name: stm32_configgpio + * + * Description: + * Configure a GPIO pin based on bit-encoded description of the pin. + * Once it is configured as Alternative (GPIO_ALT|GPIO_CNF_AFPP|...) + * function, it must be unconfigured with stm32_unconfiggpio() with + * the same cfgset first before it can be set to non-alternative function. + * + * Returns: + * OK on success + * A negated errono valu on invalid port, or when pin is locked as ALT + * function. + * + * To-Do: Auto Power Enable + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_configgpio (for the STM32F10xxx family) + ****************************************************************************/ + +#if defined(CONFIG_STM32_STM32F10XX) +int stm32_configgpio(uint32_t cfgset) +{ + uint32_t base; + uint32_t cr; + uint32_t regval; + uint32_t regaddr; + unsigned int port; + unsigned int pin; + unsigned int pos; + unsigned int modecnf; + irqstate_t flags; + bool input; + + /* Verify that this hardware supports the select GPIO port */ + + port = (cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + if (port >= STM32_NGPIO_PORTS) + { + return -EINVAL; + } + + /* Get the port base address */ + + base = g_gpiobase[port]; + + /* Get the pin number and select the port configuration register for that + * pin + */ + + pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + if (pin < 8) + { + cr = base + STM32_GPIO_CRL_OFFSET; + pos = pin; + } + else + { + cr = base + STM32_GPIO_CRH_OFFSET; + pos = pin - 8; + } + + /* Input or output? */ + + input = ((cfgset & GPIO_INPUT) != 0); + + /* Interrupts must be disabled from here on out so that we have mutually + * exclusive access to all of the GPIO configuration registers. + */ + + flags = irqsave(); + + /* Decode the mode and configuration */ + + regval = getreg32(cr); + + if (input) + { + /* Input.. force mode = INPUT */ + + modecnf = 0; + } + else + { + /* Output or alternate function */ + + modecnf = (cfgset & GPIO_MODE_MASK) >> GPIO_MODE_SHIFT; + } + + modecnf |= ((cfgset & GPIO_CNF_MASK) >> GPIO_CNF_SHIFT) << 2; + + /* Set the port configuration register */ + + regval &= ~(GPIO_CR_MODECNF_MASK(pos)); + regval |= (modecnf << GPIO_CR_MODECNF_SHIFT(pos)); + putreg32(regval, cr); + + /* Set or reset the corresponding BRR/BSRR bit */ + + if (!input) + { + /* It is an output or an alternate function. We have to look at the CNF + * bits to know which. + */ + + unsigned int cnf = (cfgset & GPIO_CNF_MASK); + if (cnf != GPIO_CNF_OUTPP && cnf != GPIO_CNF_OUTOD) + { + /* Its an alternate function pin... we can return early */ + + irqrestore(flags); + return OK; + } + } + else + { + /* It is an input pin... Should it configured as an EXTI interrupt? */ + + if ((cfgset & GPIO_EXTI) != 0) + { + int shift; + + /* Yes.. Set the bits in the EXTI CR register */ + + regaddr = STM32_AFIO_EXTICR(pin); + regval = getreg32(regaddr); + shift = AFIO_EXTICR_EXTI_SHIFT(pin); + regval &= ~(AFIO_EXTICR_PORT_MASK << shift); + regval |= (((uint32_t)port) << shift); + + putreg32(regval, regaddr); + } + + if ((cfgset & GPIO_CNF_MASK) != GPIO_CNF_INPULLUD) + { + /* Neither... we can return early */ + + irqrestore(flags); + return OK; + } + } + + /* If it is an output... set the pin to the correct initial state. + * If it is pull-down or pull up, then we need to set the ODR + * appropriately for that function. + */ + + if ((cfgset & GPIO_OUTPUT_SET) != 0) + { + /* Use the BSRR register to set the output */ + + regaddr = base + STM32_GPIO_BSRR_OFFSET; + } + else + { + /* Use the BRR register to clear */ + + regaddr = base + STM32_GPIO_BRR_OFFSET; + } + + regval = getreg32(regaddr); + regval |= (1 << pin); + putreg32(regval, regaddr); + + irqrestore(flags); + return OK; +} +#endif + +/**************************************************************************** + * Name: stm32_configgpio (for the STM2F20xxx and STM32F40xxx family) + ****************************************************************************/ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +int stm32_configgpio(uint32_t cfgset) +{ + uintptr_t base; + uint32_t regval; + uint32_t setting; + unsigned int regoffset; + unsigned int port; + unsigned int pin; + unsigned int pos; + unsigned int pinmode; + irqstate_t flags; + + /* Verify that this hardware supports the select GPIO port */ + + port = (cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + if (port >= STM32_NGPIO_PORTS) + { + return -EINVAL; + } + + /* Get the port base address */ + + base = g_gpiobase[port]; + + /* Get the pin number and select the port configuration register for that + * pin + */ + + pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + + /* Set up the mode register (and remember whether the pin mode) */ + + switch (cfgset & GPIO_MODE_MASK) + { + default: + case GPIO_INPUT: /* Input mode */ + pinmode = GPIO_MODER_INPUT; + break; + + case GPIO_OUTPUT: /* General purpose output mode */ + pinmode = GPIO_MODER_OUTPUT; + break; + + case GPIO_ALT: /* Alternate function mode */ + pinmode = GPIO_MODER_ALT; + break; + + case GPIO_ANALOG: /* Analog mode */ + pinmode = GPIO_MODER_ANALOG; + break; + } + + /* Interrupts must be disabled from here on out so that we have mutually + * exclusive access to all of the GPIO configuration registers. + */ + + flags = irqsave(); + + /* Now apply the configuration to the mode register */ + + regval = getreg32(base + STM32_GPIO_MODER_OFFSET); + regval &= ~GPIO_MODER_MASK(pin); + regval |= ((uint32_t)pinmode << GPIO_MODER_SHIFT(pin)); + putreg32(regval, base + STM32_GPIO_MODER_OFFSET); + + /* Set up the pull-up/pull-down configuration (all but analog pins) */ + + setting = GPIO_PUPDR_NONE; + if (pinmode != GPIO_MODER_ANALOG) + { + switch (cfgset & GPIO_PUPD_MASK) + { + default: + case GPIO_FLOAT: /* No pull-up, pull-down */ + break; + + case GPIO_PULLUP: /* Pull-up */ + setting = GPIO_PUPDR_PULLUP; + break; + + case GPIO_PULLDOWN: /* Pull-down */ + setting = GPIO_PUPDR_PULLDOWN; + break; + } + } + + regval = getreg32(base + STM32_GPIO_PUPDR_OFFSET); + regval &= ~GPIO_PUPDR_MASK(pin); + regval |= (setting << GPIO_PUPDR_SHIFT(pin)); + putreg32(regval, base + STM32_GPIO_PUPDR_OFFSET); + + /* Set the alternate function (Only alternate function pins) */ + + if (pinmode == GPIO_MODER_ALT) + { + setting = (cfgset & GPIO_AF_MASK) >> GPIO_AF_SHIFT; + } + else + { + setting = 0; + } + + if (pin < 8) + { + regoffset = STM32_GPIO_AFRL_OFFSET; + pos = pin; + } + else + { + regoffset = STM32_GPIO_ARFH_OFFSET; + pos = pin - 8; + } + + regval = getreg32(base + regoffset); + regval &= ~GPIO_AFR_MASK(pos); + regval |= (setting << GPIO_AFR_SHIFT(pos)); + putreg32(regval, base + regoffset); + + /* Set speed (Only outputs and alternate function pins) */ + + if (pinmode == GPIO_MODER_OUTPUT || pinmode == GPIO_MODER_ALT) + { + switch (cfgset & GPIO_SPEED_MASK) + { + default: + case GPIO_SPEED_2MHz: /* 2 MHz Low speed output */ + setting = GPIO_OSPEED_2MHz; + break; + + case GPIO_SPEED_25MHz: /* 25 MHz Medium speed output */ + setting = GPIO_OSPEED_25MHz; + break; + + case GPIO_SPEED_50MHz: /* 50 MHz Fast speed output */ + setting = GPIO_OSPEED_50MHz; + break; + + case GPIO_SPEED_100MHz: /* 100 MHz High speed output */ + setting = GPIO_OSPEED_100MHz; + break; + } + } + else + { + setting = 0; + } + + regval = getreg32(base + STM32_GPIO_OSPEED_OFFSET); + regval &= ~GPIO_OSPEED_MASK(pin); + regval |= (setting << GPIO_OSPEED_SHIFT(pin)); + putreg32(regval, base + STM32_GPIO_OSPEED_OFFSET); + + /* Set push-pull/open-drain (Only outputs and alternate function pins) */ + + regval = getreg32(base + STM32_GPIO_OTYPER_OFFSET); + setting = GPIO_OTYPER_OD(pin); + + if ((pinmode == GPIO_MODER_OUTPUT || pinmode == GPIO_MODER_ALT) && + (cfgset & GPIO_OPENDRAIN) != 0) + { + regval |= setting; + } + else + { + regval &= ~setting; + } + + putreg32(regval, base + STM32_GPIO_OTYPER_OFFSET); + + /* If it is an output... set the pin to the correct initial state. */ + + if (pinmode == GPIO_MODER_OUTPUT) + { + bool value = ((cfgset & GPIO_OUTPUT_SET) != 0); + stm32_gpiowrite(cfgset, value); + } + + /* Otherwise, it is an input pin. Should it configured as an EXTI interrupt? */ + + else if ((cfgset & GPIO_EXTI) != 0) + { + /* "In STM32 F1 the selection of the EXTI line source is performed through + * the EXTIx bits in the AFIO_EXTICRx registers, while in F2 series this + * selection is done through the EXTIx bits in the SYSCFG_EXTICRx registers. + * + * "Only the mapping of the EXTICRx registers has been changed, without any + * changes to the meaning of the EXTIx bits. However, the range of EXTI + * bits values has been extended to 0b1000 to support the two ports added + * in F2, port H and I (in F1 series the maximum value is 0b0110)." + */ + + uint32_t regaddr; + int shift; + + /* Set the bits in the SYSCFG EXTICR register */ + + regaddr = STM32_SYSCFG_EXTICR(pin); + regval = getreg32(regaddr); + shift = SYSCFG_EXTICR_EXTI_SHIFT(pin); + regval &= ~(SYSCFG_EXTICR_PORT_MASK << shift); + regval |= (((uint32_t)port) << shift); + + putreg32(regval, regaddr); + } + + irqrestore(flags); + return OK; +} +#endif + +/**************************************************************************** + * Name: stm32_unconfiggpio + * + * Description: + * Unconfigure a GPIO pin based on bit-encoded description of the pin, set it + * into default HiZ state (and possibly mark it's unused) and unlock it whether + * it was previsouly selected as alternative function (GPIO_ALT|GPIO_CNF_AFPP|...). + * + * This is a safety function and prevents hardware from schocks, as unexpected + * write to the Timer Channel Output GPIO to fixed '1' or '0' while it should + * operate in PWM mode could produce excessive on-board currents and trigger + * over-current/alarm function. + * + * Returns: + * OK on success + * A negated errno value on invalid port + * + * To-Do: Auto Power Disable + ****************************************************************************/ + +int stm32_unconfiggpio(uint32_t cfgset) +{ + /* Reuse port and pin number and set it to default HiZ INPUT */ + + cfgset &= GPIO_PORT_MASK | GPIO_PIN_MASK; +#if defined(CONFIG_STM32_STM32F10XX) + cfgset |= GPIO_INPUT | GPIO_CNF_INFLOAT | GPIO_MODE_INPUT; +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + cfgset |= GPIO_INPUT | GPIO_FLOAT; +#else +# error "Unsupported STM32 chip" +#endif + + /* To-Do: Mark its unuse for automatic power saving options */ + + return stm32_configgpio(cfgset); +} + +/**************************************************************************** + * Name: stm32_gpiowrite + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void stm32_gpiowrite(uint32_t pinset, bool value) +{ + uint32_t base; +#if defined(CONFIG_STM32_STM32F10XX) + uint32_t offset; +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + uint32_t bit; +#endif + unsigned int port; + unsigned int pin; + + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + if (port < STM32_NGPIO_PORTS) + { + /* Get the port base address */ + + base = g_gpiobase[port]; + + /* Get the pin number */ + + pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + + /* Set or clear the output on the pin */ + +#if defined(CONFIG_STM32_STM32F10XX) + + if (value) + { + offset = STM32_GPIO_BSRR_OFFSET; + } + else + { + offset = STM32_GPIO_BRR_OFFSET; + } + + putreg32((1 << pin), base + offset); + +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + + if (value) + { + bit = GPIO_BSRR_SET(pin); + } + else + { + bit = GPIO_BSRR_RESET(pin); + } + + putreg32(bit, base + STM32_GPIO_BSRR_OFFSET); + +#else +# error "Unsupported STM32 chip" +#endif + } +} + +/**************************************************************************** + * Name: stm32_gpioread + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool stm32_gpioread(uint32_t pinset) +{ + uint32_t base; + unsigned int port; + unsigned int pin; + + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + if (port < STM32_NGPIO_PORTS) + { + /* Get the port base address */ + + base = g_gpiobase[port]; + + /* Get the pin number and return the input state of that pin */ + + pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + return ((getreg32(base + STM32_GPIO_IDR_OFFSET) & (1 << pin)) != 0); + } + return 0; +} diff --git a/nuttx/arch/arm/src/stm32/stm32_gpio.h b/nuttx/arch/arm/src/stm32/stm32_gpio.h new file mode 100644 index 0000000000..34623c5253 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_gpio.h @@ -0,0 +1,514 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_gpio.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Gregory Nutt + * Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_GPIO_H +#define __ARCH_ARM_SRC_STM32_STM32_GPIO_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +# include +#endif + +#include + +#include "chip.h" + +#if defined(CONFIG_STM32_STM32F10XX) +# include "chip/stm32f10xxx_gpio.h" +#elif defined(CONFIG_STM32_STM32F20XX) +# include "chip/stm32f20xxx_gpio.h" +#elif defined(CONFIG_STM32_STM32F40XX) +# include "chip/stm32f40xxx_gpio.h" +#else +# error "Unrecognized STM32 chip" +#endif + +/************************************************************************************ + * Pre-Processor Declarations + ************************************************************************************/ + +/* Bit-encoded input to stm32_configgpio() */ + +#if defined(CONFIG_STM32_STM32F10XX) + +/* 16-bit Encoding: + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * OFFS SX.. VPPP BBBB + */ + +/* Output mode: + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * O... .... .... .... + */ + +#define GPIO_INPUT (1 << 15) /* Bit 15: 1=Input mode */ +#define GPIO_OUTPUT (0) /* 0=Output or alternate function */ +#define GPIO_ALT (0) + +/* If the pin is a GPIO digital output, then this identifies the initial output value. + * If the pin is an input, this bit is overloaded to provide the qualifier to\ + * distinquish input pull-up and -down: + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * .... .... V... .... + */ + +#define GPIO_OUTPUT_SET (1 << 7) /* Bit 7: If output, inital value of output */ +#define GPIO_OUTPUT_CLEAR (0) + +/* These bits set the primary function of the pin: + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * .FF. .... .... .... + */ + +#define GPIO_CNF_SHIFT 13 /* Bits 13-14: GPIO function */ +#define GPIO_CNF_MASK (3 << GPIO_CNF_SHIFT) + +# define GPIO_CNF_ANALOGIN (0 << GPIO_CNF_SHIFT) /* Analog input */ +# define GPIO_CNF_INFLOAT (1 << GPIO_CNF_SHIFT) /* Input floating */ +# define GPIO_CNF_INPULLUD (2 << GPIO_CNF_SHIFT) /* Input pull-up/down general bit, since up is composed of two parts */ +# define GPIO_CNF_INPULLDWN (2 << GPIO_CNF_SHIFT) /* Input pull-down */ +# define GPIO_CNF_INPULLUP ((2 << GPIO_CNF_SHIFT) | GPIO_OUTPUT_SET) /* Input pull-up */ + +# define GPIO_CNF_OUTPP (0 << GPIO_CNF_SHIFT) /* Output push-pull */ +# define GPIO_CNF_OUTOD (1 << GPIO_CNF_SHIFT) /* Output open-drain */ +# define GPIO_CNF_AFPP (2 << GPIO_CNF_SHIFT) /* Alternate function push-pull */ +# define GPIO_CNF_AFOD (3 << GPIO_CNF_SHIFT) /* Alternate function open-drain */ + +/* Maximum frequency selection: + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * ...S S... .... .... + */ + +#define GPIO_MODE_SHIFT 11 /* Bits 11-12: GPIO frequency selection */ +#define GPIO_MODE_MASK (3 << GPIO_MODE_SHIFT) +# define GPIO_MODE_INPUT (0 << GPIO_MODE_SHIFT) /* Input mode (reset state) */ +# define GPIO_MODE_10MHz (1 << GPIO_MODE_SHIFT) /* Output mode, max speed 10 MHz */ +# define GPIO_MODE_2MHz (2 << GPIO_MODE_SHIFT) /* Output mode, max speed 2 MHz */ +# define GPIO_MODE_50MHz (3 << GPIO_MODE_SHIFT) /* Output mode, max speed 50 MHz */ + +/* External interrupt selection (GPIO inputs only): + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * .... .X.. .... .... + */ + +#define GPIO_EXTI (1 << 10) /* Bit 10: Configure as EXTI interrupt */ + +/* This identifies the GPIO port: + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * .... .... .PPP .... + */ + +#define GPIO_PORT_SHIFT 4 /* Bit 4-6: Port number */ +#define GPIO_PORT_MASK (7 << GPIO_PORT_SHIFT) +# define GPIO_PORTA (0 << GPIO_PORT_SHIFT) /* GPIOA */ +# define GPIO_PORTB (1 << GPIO_PORT_SHIFT) /* GPIOB */ +# define GPIO_PORTC (2 << GPIO_PORT_SHIFT) /* GPIOC */ +# define GPIO_PORTD (3 << GPIO_PORT_SHIFT) /* GPIOD */ +# define GPIO_PORTE (4 << GPIO_PORT_SHIFT) /* GPIOE */ +# define GPIO_PORTF (5 << GPIO_PORT_SHIFT) /* GPIOF */ +# define GPIO_PORTG (6 << GPIO_PORT_SHIFT) /* GPIOG */ + +/* This identifies the bit in the port: + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * .... .... .... BBBB + */ + +#define GPIO_PIN_SHIFT 0 /* Bits 0-3: GPIO number: 0-15 */ +#define GPIO_PIN_MASK (15 << GPIO_PIN_SHIFT) +#define GPIO_PIN0 (0 << GPIO_PIN_SHIFT) +#define GPIO_PIN1 (1 << GPIO_PIN_SHIFT) +#define GPIO_PIN2 (2 << GPIO_PIN_SHIFT) +#define GPIO_PIN3 (3 << GPIO_PIN_SHIFT) +#define GPIO_PIN4 (4 << GPIO_PIN_SHIFT) +#define GPIO_PIN5 (5 << GPIO_PIN_SHIFT) +#define GPIO_PIN6 (6 << GPIO_PIN_SHIFT) +#define GPIO_PIN7 (7 << GPIO_PIN_SHIFT) +#define GPIO_PIN8 (8 << GPIO_PIN_SHIFT) +#define GPIO_PIN9 (9 << GPIO_PIN_SHIFT) +#define GPIO_PIN10 (10 << GPIO_PIN_SHIFT) +#define GPIO_PIN11 (11 << GPIO_PIN_SHIFT) +#define GPIO_PIN12 (12 << GPIO_PIN_SHIFT) +#define GPIO_PIN13 (13 << GPIO_PIN_SHIFT) +#define GPIO_PIN14 (14 << GPIO_PIN_SHIFT) +#define GPIO_PIN15 (15 << GPIO_PIN_SHIFT) + +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + +/* Each port bit of the general-purpose I/O (GPIO) ports can be individually configured + * by software in several modes: + * + * - Input floating + * - Input pull-up + * - Input-pull-down + * - Output open-drain with pull-up or pull-down capability + * - Output push-pull with pull-up or pull-down capability + * - Alternate function push-pull with pull-up or pull-down capability + * - Alternate function open-drain with pull-up or pull-down capability + * - Analog + * + * 20-bit Encoding: 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * Inputs: MMUU .... ...X PPPP BBBB + * Outputs: MMUU .... FFOV PPPP BBBB + * Alternate Functions: MMUU AAAA FFO. PPPP BBBB + * Analog: MM.. .... .... PPPP BBBB + */ + +/* Mode: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * MM.. .... .... .... .... + */ + +#define GPIO_MODE_SHIFT (18) /* Bits 18-19: GPIO port mode */ +#define GPIO_MODE_MASK (3 << GPIO_MODE_SHIFT) +# define GPIO_INPUT (0 << GPIO_MODE_SHIFT) /* Input mode */ +# define GPIO_OUTPUT (1 << GPIO_MODE_SHIFT) /* General purpose output mode */ +# define GPIO_ALT (2 << GPIO_MODE_SHIFT) /* Alternate function mode */ +# define GPIO_ANALOG (3 << GPIO_MODE_SHIFT) /* Analog mode */ + +/* Input/output pull-ups/downs (not used with analog): + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * ..UU .... .... .... .... + */ + +#define GPIO_PUPD_SHIFT (16) /* Bits 16-17: Pull-up/pull down */ +#define GPIO_PUPD_MASK (3 << GPIO_PUPD_SHIFT) +# define GPIO_FLOAT (0 << GPIO_PUPD_SHIFT) /* No pull-up, pull-down */ +# define GPIO_PULLUP (1 << GPIO_PUPD_SHIFT) /* Pull-up */ +# define GPIO_PULLDOWN (2 << GPIO_PUPD_SHIFT) /* Pull-down */ + +/* Alternate Functions: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... AAAA .... .... .... + */ + +#define GPIO_AF_SHIFT (12) /* Bits 12-15: Alternate function */ +#define GPIO_AF_MASK (15 << GPIO_AF_SHIFT) +# define GPIO_AF(n) ((n) << GPIO_AF_SHIFT) +# define GPIO_AF0 (0 << GPIO_AF_SHIFT) +# define GPIO_AF1 (1 << GPIO_AF_SHIFT) +# define GPIO_AF2 (2 << GPIO_AF_SHIFT) +# define GPIO_AF3 (3 << GPIO_AF_SHIFT) +# define GPIO_AF4 (4 << GPIO_AF_SHIFT) +# define GPIO_AF5 (5 << GPIO_AF_SHIFT) +# define GPIO_AF6 (6 << GPIO_AF_SHIFT) +# define GPIO_AF7 (7 << GPIO_AF_SHIFT) +# define GPIO_AF8 (8 << GPIO_AF_SHIFT) +# define GPIO_AF9 (9 << GPIO_AF_SHIFT) +# define GPIO_AF10 (10 << GPIO_AF_SHIFT) +# define GPIO_AF11 (11 << GPIO_AF_SHIFT) +# define GPIO_AF12 (12 << GPIO_AF_SHIFT) +# define GPIO_AF13 (13 << GPIO_AF_SHIFT) +# define GPIO_AF14 (14 << GPIO_AF_SHIFT) +# define GPIO_AF15 (15 << GPIO_AF_SHIFT) + +/* Output/Alt function frequency selection: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... FF.. .... .... + */ + +#define GPIO_SPEED_SHIFT (10) /* Bits 10-11: GPIO frequency selection */ +#define GPIO_SPEED_MASK (3 << GPIO_SPEED_SHIFT) +# define GPIO_SPEED_2MHz (0 << GPIO_SPEED_SHIFT) /* 2 MHz Low speed output */ +# define GPIO_SPEED_25MHz (1 << GPIO_SPEED_SHIFT) /* 25 MHz Medium speed output */ +# define GPIO_SPEED_50MHz (2 << GPIO_SPEED_SHIFT) /* 50 MHz Fast speed output */ +# define GPIO_SPEED_100MHz (3 << GPIO_SPEED_SHIFT) /* 100 MHz High speed output */ + +/* Output/Alt function type selection: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... ..O. .... .... + */ + +#define GPIO_OPENDRAIN (1 << 9) /* Bit9: 1=Open-drain output */ +#define GPIO_PUSHPULL (0) /* Bit9: 0=Push-pull output */ + +/* If the pin is a GPIO digital output, then this identifies the initial output value. + * If the pin is an input, this bit is overloaded to provide the qualifier to + * distinquish input pull-up and -down: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... ...V .... .... + */ + +#define GPIO_OUTPUT_SET (1 << 8) /* Bit 8: If output, inital value of output */ +#define GPIO_OUTPUT_CLEAR (0) + +/* External interrupt selection (GPIO inputs only): + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... ...X .... .... + */ + +#define GPIO_EXTI (1 << 8) /* Bit 8: Configure as EXTI interrupt */ + +/* This identifies the GPIO port: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... .... PPPP .... + */ + +#define GPIO_PORT_SHIFT (4) /* Bit 4-7: Port number */ +#define GPIO_PORT_MASK (15 << GPIO_PORT_SHIFT) +# define GPIO_PORTA (0 << GPIO_PORT_SHIFT) /* GPIOA */ +# define GPIO_PORTB (1 << GPIO_PORT_SHIFT) /* GPIOB */ +# define GPIO_PORTC (2 << GPIO_PORT_SHIFT) /* GPIOC */ +# define GPIO_PORTD (3 << GPIO_PORT_SHIFT) /* GPIOD */ +# define GPIO_PORTE (4 << GPIO_PORT_SHIFT) /* GPIOE */ +# define GPIO_PORTF (5 << GPIO_PORT_SHIFT) /* GPIOF */ +# define GPIO_PORTG (6 << GPIO_PORT_SHIFT) /* GPIOG */ +# define GPIO_PORTH (7 << GPIO_PORT_SHIFT) /* GPIOH */ +# define GPIO_PORTI (8 << GPIO_PORT_SHIFT) /* GPIOI */ + +/* This identifies the bit in the port: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... .... .... BBBB + */ + +#define GPIO_PIN_SHIFT (0) /* Bits 0-3: GPIO number: 0-15 */ +#define GPIO_PIN_MASK (15 << GPIO_PIN_SHIFT) +# define GPIO_PIN0 (0 << GPIO_PIN_SHIFT) +# define GPIO_PIN1 (1 << GPIO_PIN_SHIFT) +# define GPIO_PIN2 (2 << GPIO_PIN_SHIFT) +# define GPIO_PIN3 (3 << GPIO_PIN_SHIFT) +# define GPIO_PIN4 (4 << GPIO_PIN_SHIFT) +# define GPIO_PIN5 (5 << GPIO_PIN_SHIFT) +# define GPIO_PIN6 (6 << GPIO_PIN_SHIFT) +# define GPIO_PIN7 (7 << GPIO_PIN_SHIFT) +# define GPIO_PIN8 (8 << GPIO_PIN_SHIFT) +# define GPIO_PIN9 (9 << GPIO_PIN_SHIFT) +# define GPIO_PIN10 (10 << GPIO_PIN_SHIFT) +# define GPIO_PIN11 (11 << GPIO_PIN_SHIFT) +# define GPIO_PIN12 (12 << GPIO_PIN_SHIFT) +# define GPIO_PIN13 (13 << GPIO_PIN_SHIFT) +# define GPIO_PIN14 (14 << GPIO_PIN_SHIFT) +# define GPIO_PIN15 (15 << GPIO_PIN_SHIFT) + +#else +# error "Unrecognized STM32 chip" +#endif + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Base addresses for each GPIO block */ + +EXTERN const uint32_t g_gpiobase[STM32_NGPIO_PORTS]; + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_configgpio + * + * Description: + * Configure a GPIO pin based on bit-encoded description of the pin. + * Once it is configured as Alternative (GPIO_ALT|GPIO_CNF_AFPP|...) + * function, it must be unconfigured with stm32_unconfiggpio() with + * the same cfgset first before it can be set to non-alternative function. + * + * Returns: + * OK on success + * ERROR on invalid port, or when pin is locked as ALT function. + * + ************************************************************************************/ + +EXTERN int stm32_configgpio(uint32_t cfgset); + +/************************************************************************************ + * Name: stm32_unconfiggpio + * + * Description: + * Unconfigure a GPIO pin based on bit-encoded description of the pin, set it + * into default HiZ state (and possibly mark it's unused) and unlock it whether + * it was previsouly selected as alternative function (GPIO_ALT|GPIO_CNF_AFPP|...). + * + * This is a safety function and prevents hardware from schocks, as unexpected + * write to the Timer Channel Output GPIO to fixed '1' or '0' while it should + * operate in PWM mode could produce excessive on-board currents and trigger + * over-current/alarm function. + * + * Returns: + * OK on success + * ERROR on invalid port + * + ************************************************************************************/ + +EXTERN int stm32_unconfiggpio(uint32_t cfgset); + +/************************************************************************************ + * Name: stm32_gpiowrite + * + * Description: + * Write one or zero to the selected GPIO pin + * + ************************************************************************************/ + +EXTERN void stm32_gpiowrite(uint32_t pinset, bool value); + +/************************************************************************************ + * Name: stm32_gpioread + * + * Description: + * Read one or zero from the selected GPIO pin + * + ************************************************************************************/ + +EXTERN bool stm32_gpioread(uint32_t pinset); + +/************************************************************************************ + * Name: stm32_gpiosetevent + * + * Description: + * Sets/clears GPIO based event and interrupt triggers. + * + * Parameters: + * - pinset: gpio pin configuration + * - rising/falling edge: enables + * - event: generate event when set + * - func: when non-NULL, generate interrupt + * + * Returns: + * The previous value of the interrupt handler function pointer. This value may, + * for example, be used to restore the previous handler when multiple handlers are + * used. + * + ************************************************************************************/ + +EXTERN xcpt_t stm32_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge, + bool event, xcpt_t func); + +/************************************************************************************ + * Function: stm32_dumpgpio + * + * Description: + * Dump all GPIO registers associated with the provided base address + * + ************************************************************************************/ + +#ifdef CONFIG_DEBUG +EXTERN int stm32_dumpgpio(uint32_t pinset, const char *msg); +#else +# define stm32_dumpgpio(p,m) +#endif + +/************************************************************************************ + * Function: stm32_gpioinit + * + * Description: + * Based on configuration within the .config file, it does: + * - Remaps positions of alternative functions. + * + * Typically called from stm32_start(). + * + ************************************************************************************/ + +EXTERN void stm32_gpioinit(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_GPIO_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_i2c.c b/nuttx/arch/arm/src/stm32/stm32_i2c.c new file mode 100644 index 0000000000..d02115a157 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_i2c.c @@ -0,0 +1,2137 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_i2c.c + * STM32 I2C Hardware Layer - Device Driver + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * With extensions, modifications by: + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregroy Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/* Supports: + * - Master operation, 100 kHz (standard) and 400 kHz (full speed) + * - Multiple instances (shared bus) + * - Interrupt based operation + * + * Structure naming: + * - Device: structure as defined by the nuttx/i2c/i2c.h + * - Instance: represents each individual access to the I2C driver, obtained by + * the i2c_init(); it extends the Device structure from the nuttx/i2c/i2c.h; + * Instance points to OPS, to common I2C Hardware private data and contains + * its own private data, as frequency, address, mode of operation (in the future) + * - Private: Private data of an I2C Hardware + * + * TODO + * - Check for all possible deadlocks (as BUSY='1' I2C needs to be reset in HW using the I2C_CR1_SWRST) + * - SMBus support (hardware layer timings are already supported) and add SMBA gpio pin + * - Slave support with multiple addresses (on multiple instances): + * - 2 x 7-bit address or + * - 1 x 10 bit adresses + 1 x 7 bit address (?) + * - plus the broadcast address (general call) + * - Multi-master support + * - DMA (to get rid of too many CPU wake-ups and interventions) + * - Be ready for IPMI + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "up_arch.h" + +#include "stm32_rcc.h" +#include "stm32_i2c.h" +#include "stm32_waste.h" + +#if defined(CONFIG_STM32_I2C1) || defined(CONFIG_STM32_I2C2) || defined(CONFIG_STM32_I2C3) + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* CONFIG_I2C_POLLED may be set so that I2C interrrupts will not be used. Instead, + * CPU-intensive polling will be used. + */ + +/* Interrupt wait timeout in seconds and milliseconds */ + +#if !defined(CONFIG_STM32_I2CTIMEOSEC) && !defined(CONFIG_STM32_I2CTIMEOMS) +# define CONFIG_STM32_I2CTIMEOSEC 0 +# define CONFIG_STM32_I2CTIMEOMS 500 /* Default is 500 milliseconds */ +#elif !defined(CONFIG_STM32_I2CTIMEOSEC) +# define CONFIG_STM32_I2CTIMEOSEC 0 /* User provided milliseconds */ +#elif !defined(CONFIG_STM32_I2CTIMEOMS) +# define CONFIG_STM32_I2CTIMEOMS 0 /* User provided seconds */ +#endif + +/* Interrupt wait time timeout in system timer ticks */ + +#define CONFIG_STM32_I2CTIMEOTICKS \ + (SEC2TICK(CONFIG_STM32_I2CTIMEOSEC) + MSEC2TICK(CONFIG_STM32_I2CTIMEOMS)) + +/* On the STM32F103ZE, there is an internal conflict between I2C1 and FSMC. In that + * case, it is necessary to disable FSMC before each I2C1 access and re-enable FSMC + * when the I2C access completes. + */ + +#undef I2C1_FSMC_CONFLICT +#if defined(CONFIG_STM32_STM32F10XX) && defined(CONFIG_STM32_FSMC) && defined(CONFIG_STM32_I2C1) +# define I2C1_FSMC_CONFLICT +#endif + +/* Debug ****************************************************************************/ +/* CONFIG_DEBUG_I2C + CONFIG_DEBUG enables general I2C debug output. */ + +#ifdef CONFIG_DEBUG_I2C +# define i2cdbg dbg +# define i2cvdbg vdbg +#else +# define i2cdbg(x...) +# define i2cvdbg(x...) +#endif + +/* I2C event trace logic. NOTE: trace uses the internal, non-standard, low-level + * debug interface lib_rawprintf() but does not require that any other debug + * is enabled. + */ + +#ifndef CONFIG_I2C_TRACE +# define stm32_i2c_tracereset(p) +# define stm32_i2c_tracenew(p,s) +# define stm32_i2c_traceevent(p,e,a) +# define stm32_i2c_tracedump(p) +#endif + +#ifndef CONFIG_I2C_NTRACE +# define CONFIG_I2C_NTRACE 32 +#endif + +/************************************************************************************ + * Private Types + ************************************************************************************/ +/* Interrupt state */ + +enum stm32_intstate_e +{ + INTSTATE_IDLE = 0, /* No I2C activity */ + INTSTATE_WAITING, /* Waiting for completion of interrupt activity */ + INTSTATE_DONE, /* Interrupt activity complete */ +}; + +/* Trace events */ + +enum stm32_trace_e +{ + I2CEVENT_NONE = 0, /* No events have occurred with this status */ + I2CEVENT_SENDADDR, /* Start/Master bit set and address sent, param = msgc */ + I2CEVENT_SENDBYTE, /* Send byte, param = dcnt */ + I2CEVENT_ITBUFEN, /* Enable buffer interrupts, param = 0 */ + I2CEVENT_RCVBYTE, /* Read more dta, param = dcnt */ + I2CEVENT_REITBUFEN, /* Re-enable buffer interrupts, param = 0 */ + I2CEVENT_DISITBUFEN, /* Disable buffer interrupts, param = 0 */ + I2CEVENT_BTFNOSTART, /* BTF on last byte with no restart, param = msgc */ + I2CEVENT_BTFRESTART, /* Last byte sent, re-starting, param = msgc */ + I2CEVENT_BTFSTOP, /* Last byte sten, send stop, param = 0 */ + I2CEVENT_ERROR /* Error occurred, param = 0 */ +}; + +/* Trace data */ + +struct stm32_trace_s +{ + uint32_t status; /* I2C 32-bit SR2|SR1 status */ + uint32_t count; /* Interrupt count when status change */ + enum stm32_intstate_e event; /* Last event that occurred with this status */ + uint32_t parm; /* Parameter associated with the event */ + uint32_t time; /* First of event or first status */ +}; + +/* I2C Device Private Data */ + +struct stm32_i2c_priv_s +{ + uint32_t base; /* I2C base address */ + int refs; /* Referernce count */ + sem_t sem_excl; /* Mutual exclusion semaphore */ +#ifndef CONFIG_I2C_POLLED + sem_t sem_isr; /* Interrupt wait semaphore */ +#endif + volatile uint8_t intstate; /* Interrupt handshake (see enum stm32_intstate_e) */ + + uint8_t msgc; /* Message count */ + struct i2c_msg_s *msgv; /* Message list */ + uint8_t *ptr; /* Current message buffer */ + int dcnt; /* Current message length */ + uint16_t flags; /* Current message flags */ + + /* I2C trace support */ + +#ifdef CONFIG_I2C_TRACE + int tndx; /* Trace array index */ + uint32_t start_time; /* Time when the trace was started */ + + /* The actual trace data */ + + struct stm32_trace_s trace[CONFIG_I2C_NTRACE]; +#endif + + uint32_t status; /* End of transfer SR2|SR1 status */ +}; + +/* I2C Device, Instance */ + +struct stm32_i2c_inst_s +{ + struct i2c_ops_s *ops; /* Standard I2C operations */ + struct stm32_i2c_priv_s *priv; /* Common driver private data structure */ + + uint32_t frequency; /* Frequency used in this instantiation */ + int address; /* Address used in this instantiation */ + uint16_t flags; /* Flags used in this instantiation */ +}; + +/************************************************************************************ + * Private Function Prototypes + ************************************************************************************/ + +static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv, + uint8_t offset); +static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset, + uint16_t value); +static inline void stm32_i2c_modifyreg(FAR struct stm32_i2c_priv_s *priv, + uint8_t offset, uint16_t clearbits, + uint16_t setbits); +static inline void stm32_i2c_sem_wait(FAR struct i2c_dev_s *dev); +static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv, int timeout_us); +static inline void stm32_i2c_sem_waitstop(FAR struct stm32_i2c_priv_s *priv, int timeout_us); +static inline void stm32_i2c_sem_post(FAR struct i2c_dev_s *dev); +static inline void stm32_i2c_sem_init(FAR struct i2c_dev_s *dev); +static inline void stm32_i2c_sem_destroy(FAR struct i2c_dev_s *dev); +#ifdef CONFIG_I2C_TRACE +static void stm32_i2c_tracereset(FAR struct stm32_i2c_priv_s *priv); +static void stm32_i2c_tracenew(FAR struct stm32_i2c_priv_s *priv, uint32_t status); +static void stm32_i2c_traceevent(FAR struct stm32_i2c_priv_s *priv, + enum stm32_trace_e event, uint32_t parm); +static void stm32_i2c_tracedump(FAR struct stm32_i2c_priv_s *priv); +#endif +static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, + uint32_t frequency); +static inline void stm32_i2c_sendstart(FAR struct stm32_i2c_priv_s *priv); +static inline void stm32_i2c_clrstart(FAR struct stm32_i2c_priv_s *priv); +static inline void stm32_i2c_sendstop(FAR struct stm32_i2c_priv_s *priv); +static inline uint32_t stm32_i2c_getstatus(FAR struct stm32_i2c_priv_s *priv); +#ifdef I2C1_FSMC_CONFLICT +static inline uint32_t stm32_i2c_disablefsmc(FAR struct stm32_i2c_priv_s *priv); +static inline void stm32_i2c_enablefsmc(uint32_t ahbenr); +#endif +static int stm32_i2c_isr(struct stm32_i2c_priv_s * priv); +#ifndef CONFIG_I2C_POLLED +#ifdef CONFIG_STM32_I2C1 +static int stm32_i2c1_isr(int irq, void *context); +#endif +#ifdef CONFIG_STM32_I2C2 +static int stm32_i2c2_isr(int irq, void *context); +#endif +#ifdef CONFIG_STM32_I2C3 +static int stm32_i2c3_isr(int irq, void *context); +#endif +#endif +static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv); +static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv); +static uint32_t stm32_i2c_setfrequency(FAR struct i2c_dev_s *dev, + uint32_t frequency); +static int stm32_i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits); +static int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, + int count); +static int stm32_i2c_write(FAR struct i2c_dev_s *dev, const uint8_t *buffer, + int buflen); +static int stm32_i2c_read(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen); +#ifdef CONFIG_I2C_WRITEREAD +static int stm32_i2c_writeread(FAR struct i2c_dev_s *dev, + const uint8_t *wbuffer, int wbuflen, + uint8_t *buffer, int buflen); +#endif +#ifdef CONFIG_I2C_TRANSFER +static int stm32_i2c_transfer(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, + int count); +#endif + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +#ifdef CONFIG_STM32_I2C1 +struct stm32_i2c_priv_s stm32_i2c1_priv = +{ + .base = STM32_I2C1_BASE, + .refs = 0, + .intstate = INTSTATE_IDLE, + .msgc = 0, + .msgv = NULL, + .ptr = NULL, + .dcnt = 0, + .flags = 0, + .status = 0 +}; +#endif + +#ifdef CONFIG_STM32_I2C2 +struct stm32_i2c_priv_s stm32_i2c2_priv = +{ + .base = STM32_I2C2_BASE, + .refs = 0, + .intstate = INTSTATE_IDLE, + .msgc = 0, + .msgv = NULL, + .ptr = NULL, + .dcnt = 0, + .flags = 0, + .status = 0 +}; +#endif + +#ifdef CONFIG_STM32_I2C3 +struct stm32_i2c_priv_s stm32_i2c3_priv = +{ + .base = STM32_I2C3_BASE, + .refs = 0, + .intstate = INTSTATE_IDLE, + .msgc = 0, + .msgv = NULL, + .ptr = NULL, + .dcnt = 0, + .flags = 0, + .status = 0 +}; +#endif + + +/* Device Structures, Instantiation */ + +struct i2c_ops_s stm32_i2c_ops = +{ + .setfrequency = stm32_i2c_setfrequency, + .setaddress = stm32_i2c_setaddress, + .write = stm32_i2c_write, + .read = stm32_i2c_read +#ifdef CONFIG_I2C_WRITEREAD + , .writeread = stm32_i2c_writeread +#endif +#ifdef CONFIG_I2C_TRANSFER + , .transfer = stm32_i2c_transfer +#endif +#ifdef CONFIG_I2C_SLAVE + , .setownaddress = stm32_i2c_setownaddress, + .registercallback = stm32_i2c_registercallback +#endif +}; + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_i2c_getreg + * + * Description: + * Get register value by offset + * + ************************************************************************************/ + +static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv, + uint8_t offset) +{ + return getreg16(priv->base + offset); +} + +/************************************************************************************ + * Name: stm32_i2c_putreg + * + * Description: + * Put register value by offset + * + ************************************************************************************/ + +static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset, + uint16_t value) +{ + putreg16(value, priv->base + offset); +} + +/************************************************************************************ + * Name: stm32_i2c_modifyreg + * + * Description: + * Modify register value by offset + * + ************************************************************************************/ + +static inline void stm32_i2c_modifyreg(FAR struct stm32_i2c_priv_s *priv, + uint8_t offset, uint16_t clearbits, + uint16_t setbits) +{ + modifyreg16(priv->base + offset, clearbits, setbits); +} + +/************************************************************************************ + * Name: + * + * Description: + * + * + ************************************************************************************/ + +static inline void stm32_i2c_sem_wait(FAR struct i2c_dev_s *dev) +{ + while (sem_wait(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl) != 0) + { + ASSERT(errno == EINTR); + } +} + +/************************************************************************************ + * Name: stm32_i2c_sem_waitdone + * + * Description: + * Wait for a transfer to complete + * + ************************************************************************************/ + +#ifndef CONFIG_I2C_POLLED +static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv, int timeout_us) +{ + struct timespec abstime; + irqstate_t flags; + uint32_t regval; + int ret; + + flags = irqsave(); + + /* Enable I2C interrupts */ + + regval = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET); + regval |= (I2C_CR2_ITERREN | I2C_CR2_ITEVFEN); + stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval); + + /* Signal the interrupt handler that we are waiting. NOTE: Interrupts + * are currently disabled but will be temporarily re-enabled below when + * sem_timedwait() sleeps. + */ + + priv->intstate = INTSTATE_WAITING; + do + { + /* Get the current time */ + + (void)clock_gettime(CLOCK_REALTIME, &abstime); + + /* Calculate a time in the future */ + +#if CONFIG_STM32_I2CTIMEOSEC > 0 + abstime.tv_sec += CONFIG_STM32_I2CTIMEOSEC; +#endif +#if CONFIG_STM32_I2CTIMEOUS_PER_BYTE > 0 + + /* Count the number of bytes left to process */ + int i; + int bytecount = 0; + for (i = 0; i < priv->msgc; i++) + { + bytecount += priv->msgv[i].length; + } + + abstime.tv_nsec += (CONFIG_STM32_I2CTIMEOUS_PER_BYTE * bytecount) * 1000; + if (abstime.tv_nsec > 1000 * 1000 * 1000) + { + abstime.tv_sec++; + abstime.tv_nsec -= 1000 * 1000 * 1000; + } +#else + #if CONFIG_STM32_I2CTIMEOMS > 0 + abstime.tv_nsec += CONFIG_STM32_I2CTIMEOMS * 1000 * 1000; + if (abstime.tv_nsec > 1000 * 1000 * 1000) + { + abstime.tv_sec++; + abstime.tv_nsec -= 1000 * 1000 * 1000; + } + #endif +#endif + /* Wait until either the transfer is complete or the timeout expires */ + + ret = sem_timedwait(&priv->sem_isr, &abstime); + if (ret != OK && errno != EINTR) + { + /* Break out of the loop on irrecoverable errors. This would + * include timeouts and mystery errors reported by sem_timedwait. + * NOTE that we try again if we are awakened by a signal (EINTR). + */ + + break; + } + } + + /* Loop until the interrupt level transfer is complete. */ + + while (priv->intstate != INTSTATE_DONE); + + /* Set the interrupt state back to IDLE */ + + priv->intstate = INTSTATE_IDLE; + + /* Disable I2C interrupts */ + + regval = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET); + regval &= ~I2C_CR2_ALLINTS; + stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval); + + irqrestore(flags); + return ret; +} +#else +static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv, int timeout_us) +{ + uint32_t start; + uint32_t elapsed; + int ret; + + /* Signal the interrupt handler that we are waiting. NOTE: Interrupts + * are currently disabled but will be temporarily re-enabled below when + * sem_timedwait() sleeps. + */ + + priv->intstate = INTSTATE_WAITING; + start = clock_systimer(); + + do + { + /* Poll by simply calling the timer interrupt handler until it + * reports that it is done. + */ + + stm32_i2c_isr(priv); + + /* Calculate the elapsed time */ + + elapsed = clock_systimer() - start; + } + + /* Loop until the transfer is complete. */ + while (priv->intstate != INTSTATE_DONE && elapsed < USEC2TICK(timeout_us)); + + i2cvdbg("intstate: %d elapsed: %d threshold: %d status: %08x\n", + priv->intstate, elapsed, USEC2TICK(timeout_us), priv->status); + + /* Set the interrupt state back to IDLE */ + + ret = priv->intstate == INTSTATE_DONE ? OK : -ETIMEDOUT; + priv->intstate = INTSTATE_IDLE; + return ret; +} +#endif + +/************************************************************************************ + * Name: stm32_i2c_sem_waitstop + * + * Description: + * Wait for a STOP to complete + * + ************************************************************************************/ + +static inline void stm32_i2c_sem_waitstop(FAR struct stm32_i2c_priv_s *priv, int timeout_us) +{ + uint32_t start; + uint32_t elapsed; + uint32_t cr1; + uint32_t sr1; + + /* Wait as stop might still be in progress; but stop might also + * be set because of a timeout error: "The [STOP] bit is set and + * cleared by software, cleared by hardware when a Stop condition is + * detected, set by hardware when a timeout error is detected." + */ + + start = clock_systimer(); + do + { + /* Check for STOP condition */ + + cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET); + if ((cr1 & I2C_CR1_STOP) == 0) + { + return; + } + + /* Check for timeout error */ + + sr1 = stm32_i2c_getreg(priv, STM32_I2C_SR1_OFFSET); + if ((sr1 & I2C_SR1_TIMEOUT) != 0) + { + return; + } + + /* Calculate the elapsed time */ + + elapsed = clock_systimer() - start; + } + + /* Loop until the stop is complete or a timeout occurs. */ + + while (elapsed < USEC2TICK(timeout_us)); + + /* If we get here then a timeout occurred with the STOP condition + * still pending. + */ + + i2cvdbg("Timeout with CR1: %04x SR1: %04x\n", cr1, sr1); +} + +/************************************************************************************ + * Name: stm32_i2c_sem_post + * + * Description: + * Release the mutual exclusion semaphore + * + ************************************************************************************/ + +static inline void stm32_i2c_sem_post(FAR struct i2c_dev_s *dev) +{ + sem_post( &((struct stm32_i2c_inst_s *)dev)->priv->sem_excl ); +} + +/************************************************************************************ + * Name: stm32_i2c_sem_init + * + * Description: + * Initialize semaphores + * + ************************************************************************************/ + +static inline void stm32_i2c_sem_init(FAR struct i2c_dev_s *dev) +{ + sem_init(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl, 0, 1); +#ifndef CONFIG_I2C_POLLED + sem_init(&((struct stm32_i2c_inst_s *)dev)->priv->sem_isr, 0, 0); +#endif +} + +/************************************************************************************ + * Name: stm32_i2c_sem_destroy + * + * Description: + * Destroy semaphores. + * + ************************************************************************************/ + +static inline void stm32_i2c_sem_destroy(FAR struct i2c_dev_s *dev) +{ + sem_destroy(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl); +#ifndef CONFIG_I2C_POLLED + sem_destroy(&((struct stm32_i2c_inst_s *)dev)->priv->sem_isr); +#endif +} + +/************************************************************************************ + * Name: stm32_i2c_trace* + * + * Description: + * I2C trace instrumentation + * + ************************************************************************************/ + +#ifdef CONFIG_I2C_TRACE +static void stm32_i2c_traceclear(FAR struct stm32_i2c_priv_s *priv) +{ + struct stm32_trace_s *trace = &priv->trace[priv->tndx]; + + trace->status = 0; /* I2C 32-bit SR2|SR1 status */ + trace->count = 0; /* Interrupt count when status change */ + trace->event = I2CEVENT_NONE; /* Last event that occurred with this status */ + trace->parm = 0; /* Parameter associated with the event */ + trace->time = 0; /* Time of first status or event */ +} + +static void stm32_i2c_tracereset(FAR struct stm32_i2c_priv_s *priv) +{ + /* Reset the trace info for a new data collection */ + + priv->tndx = 0; + priv->start_time = clock_systimer(); + stm32_i2c_traceclear(priv); +} + +static void stm32_i2c_tracenew(FAR struct stm32_i2c_priv_s *priv, uint32_t status) +{ + struct stm32_trace_s *trace = &priv->trace[priv->tndx]; + + /* Is the current entry uninitialized? Has the status changed? */ + + if (trace->count == 0 || status != trace->status) + { + /* Yes.. Was it the status changed? */ + + if (trace->count != 0) + { + /* Yes.. bump up the trace index (unless we are out of trace entries) */ + + if (priv->tndx >= (CONFIG_I2C_NTRACE-1)) + { + i2cdbg("Trace table overflow\n"); + return; + } + + priv->tndx++; + trace = &priv->trace[priv->tndx]; + } + + /* Initialize the new trace entry */ + + stm32_i2c_traceclear(priv); + trace->status = status; + trace->count = 1; + trace->time = clock_systimer(); + } + else + { + /* Just increment the count of times that we have seen this status */ + + trace->count++; + } +} + +static void stm32_i2c_traceevent(FAR struct stm32_i2c_priv_s *priv, + enum stm32_trace_e event, uint32_t parm) +{ + struct stm32_trace_s *trace; + + if (event != I2CEVENT_NONE) + { + trace = &priv->trace[priv->tndx]; + + /* Initialize the new trace entry */ + + trace->event = event; + trace->parm = parm; + + /* Bump up the trace index (unless we are out of trace entries) */ + + if (priv->tndx >= (CONFIG_I2C_NTRACE-1)) + { + i2cdbg("Trace table overflow\n"); + return; + } + + priv->tndx++; + stm32_i2c_traceclear(priv); + } +} + +static void stm32_i2c_tracedump(FAR struct stm32_i2c_priv_s *priv) +{ + struct stm32_trace_s *trace; + int i; + + lib_rawprintf("Elapsed time: %d\n", clock_systimer() - priv->start_time); + for (i = 0; i <= priv->tndx; i++) + { + trace = &priv->trace[i]; + lib_rawprintf("%2d. STATUS: %08x COUNT: %3d EVENT: %2d PARM: %08x TIME: %d\n", + i+1, trace->status, trace->count, trace->event, trace->parm, + trace->time - priv->start_time); + } +} +#endif /* CONFIG_I2C_TRACE */ + +/************************************************************************************ + * Name: stm32_i2c_setclock + * + * Description: + * Set the I2C clock + * + ************************************************************************************/ + +static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequency) +{ + uint16_t cr1; + uint16_t ccr; + uint16_t trise; + uint16_t freqmhz; + uint16_t speed; + + /* Disable the selected I2C peripheral to configure TRISE */ + + cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET); + stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1 & ~I2C_CR1_PE); + + /* Update timing and control registers */ + + freqmhz = (uint16_t)(STM32_PCLK1_FREQUENCY / 1000000); + ccr = 0; + + /* Configure speed in standard mode */ + + if (frequency <= 100000) + { + /* Standard mode speed calculation */ + + speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency << 1)); + + /* The CCR fault must be >= 4 */ + + if (speed < 4) + { + /* Set the minimum allowed value */ + + speed = 4; + } + ccr |= speed; + + /* Set Maximum Rise Time for standard mode */ + + trise = freqmhz + 1; + } + + /* Configure speed in fast mode */ + + else /* (frequency <= 400000) */ + { + /* Fast mode speed calculation with Tlow/Thigh = 16/9 */ + +#ifdef CONFIG_I2C_DUTY16_9 + speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 25)); + + /* Set DUTY and fast speed bits */ + + ccr |= (I2C_CCR_DUTY|I2C_CCR_FS); +#else + /* Fast mode speed calculation with Tlow/Thigh = 2 */ + + speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 3)); + + /* Set fast speed bit */ + + ccr |= I2C_CCR_FS; +#endif + + /* Verify that the CCR speed value is nonzero */ + + if (speed < 1) + { + /* Set the minimum allowed value */ + + speed = 1; + } + ccr |= speed; + + /* Set Maximum Rise Time for fast mode */ + + trise = (uint16_t)(((freqmhz * 300) / 1000) + 1); + } + + /* Write the new values of the CCR and TRISE registers */ + + stm32_i2c_putreg(priv, STM32_I2C_CCR_OFFSET, ccr); + stm32_i2c_putreg(priv, STM32_I2C_TRISE_OFFSET, trise); + + /* Bit 14 of OAR1 must be configured and kept at 1 */ + + stm32_i2c_putreg(priv, STM32_I2C_OAR1_OFFSET, I2C_OAR1_ONE); + + /* Re-enable the peripheral (or not) */ + + stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1); +} + +/************************************************************************************ + * Name: stm32_i2c_sendstart + * + * Description: + * Send the START conditions/force Master mode + * + ************************************************************************************/ + +static inline void stm32_i2c_sendstart(FAR struct stm32_i2c_priv_s *priv) +{ + /* Disable ACK on receive by default and generate START */ + + stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, I2C_CR1_START); +} + +/************************************************************************************ + * Name: stm32_i2c_clrstart + * + * Description: + * Clear the STOP, START or PEC condition on certain error recovery steps. + * + ************************************************************************************/ + +static inline void stm32_i2c_clrstart(FAR struct stm32_i2c_priv_s *priv) +{ + /* "Note: When the STOP, START or PEC bit is set, the software must + * not perform any write access to I2C_CR1 before this bit is + * cleared by hardware. Otherwise there is a risk of setting a + * second STOP, START or PEC request." + * + * "The [STOP] bit is set and cleared by software, cleared by hardware + * when a Stop condition is detected, set by hardware when a timeout + * error is detected. + * + * "This [START] bit is set and cleared by software and cleared by hardware + * when start is sent or PE=0." The bit must be cleared by software if the + * START is never sent. + * + * "This [PEC] bit is set and cleared by software, and cleared by hardware + * when PEC is transferred or by a START or Stop condition or when PE=0." + */ + + stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, + I2C_CR1_START|I2C_CR1_STOP|I2C_CR1_PEC, 0); +} + +/************************************************************************************ + * Name: stm32_i2c_sendstop + * + * Description: + * Send the STOP conditions + * + ************************************************************************************/ + +static inline void stm32_i2c_sendstop(FAR struct stm32_i2c_priv_s *priv) +{ + stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, I2C_CR1_STOP); +} + +/************************************************************************************ + * Name: stm32_i2c_getstatus + * + * Description: + * Get 32-bit status (SR1 and SR2 combined) + * + ************************************************************************************/ + +static inline uint32_t stm32_i2c_getstatus(FAR struct stm32_i2c_priv_s *priv) +{ + uint32_t status = stm32_i2c_getreg(priv, STM32_I2C_SR1_OFFSET); + status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16); + return status; +} + +/************************************************************************************ + * Name: stm32_i2c_disablefsmc + * + * Description: + * FSMC must be disable while accessing I2C1 because it uses a common resource + * (LBAR) + * + * NOTE: This is an issue with the STM32F103ZE, but may not be an issue with other + * STM32s. You may need to experiment + * + ************************************************************************************/ + +#ifdef I2C1_FSMC_CONFLICT +static inline uint32_t stm32_i2c_disablefsmc(FAR struct stm32_i2c_priv_s *priv) +{ + uint32_t ret = 0; + uint32_t regval; + + /* Is this I2C1 */ + +#ifdef CONFIG_STM32_I2C2 + if (priv->base == STM32_I2C1_BASE) +#endif + { + /* Disable FSMC unconditionally */ + + ret = getreg32( STM32_RCC_AHBENR); + regval = ret & ~RCC_AHBENR_FSMCEN; + putreg32(regval, STM32_RCC_AHBENR); + } + return ret; +} + +/************************************************************************************ + * Name: stm32_i2c_enablefsmc + * + * Description: + * Re-enabled the FSMC + * + ************************************************************************************/ + +static inline void stm32_i2c_enablefsmc(uint32_t ahbenr) +{ + uint32_t regval; + + /* Enable AHB clocking to the FSMC only if it was previously enabled. */ + + if ((ahbenr & RCC_AHBENR_FSMCEN) != 0) + { + regval = getreg32( STM32_RCC_AHBENR); + regval |= RCC_AHBENR_FSMCEN; + putreg32(regval, STM32_RCC_AHBENR); + } +} +#else +# define stm32_i2c_disablefsmc(priv) (0) +# define stm32_i2c_enablefsmc(ahbenr) +#endif /* I2C1_FSMC_CONFLICT */ + +/************************************************************************************ + * Name: stm32_i2c_isr + * + * Description: + * Common Interrupt Service Routine + * + ************************************************************************************/ + +static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv) +{ + uint32_t status = stm32_i2c_getstatus(priv); + + /* Check for new trace setup */ + + stm32_i2c_tracenew(priv, status); + + /* Was start bit sent */ + + if ((status & I2C_SR1_SB) != 0) + { + stm32_i2c_traceevent(priv, I2CEVENT_SENDADDR, priv->msgc); + + /* Get run-time data */ + + priv->ptr = priv->msgv->buffer; + priv->dcnt = priv->msgv->length; + priv->flags = priv->msgv->flags; + + /* Send address byte and define addressing mode */ + + stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET, + (priv->flags & I2C_M_TEN) ? + 0 : ((priv->msgv->addr << 1) | (priv->flags & I2C_M_READ))); + + /* Set ACK for receive mode */ + + if (priv->dcnt > 1 && (priv->flags & I2C_M_READ) != 0) + { + stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, 0, I2C_CR1_ACK); + } + + /* Increment to next pointer and decrement message count */ + + priv->msgv++; + priv->msgc--; + } + + /* In 10-bit addressing mode, was first byte sent */ + + else if ((status & I2C_SR1_ADD10) != 0) + { + /* TODO: Finish 10-bit mode addressing */ + } + + /* Was address sent, continue with either sending or reading data */ + + else if ((priv->flags & I2C_M_READ) == 0 && (status & (I2C_SR1_ADDR | I2C_SR1_TXE)) != 0) + { + if (priv->dcnt > 0) + { + /* Send a byte */ + + stm32_i2c_traceevent(priv, I2CEVENT_SENDBYTE, priv->dcnt); + stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET, *priv->ptr++); + priv->dcnt--; + } + } + + else if ((priv->flags & I2C_M_READ) != 0 && (status & I2C_SR1_ADDR) != 0) + { + /* Enable RxNE and TxE buffers in order to receive one or multiple bytes */ + +#ifndef CONFIG_I2C_POLLED + stm32_i2c_traceevent(priv, I2CEVENT_ITBUFEN, 0); + stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, 0, I2C_CR2_ITBUFEN); +#endif + } + + /* More bytes to read */ + + else if ((status & I2C_SR1_RXNE) != 0) + { + /* Read a byte, if dcnt goes < 0, then read dummy bytes to ack ISRs */ + + if (priv->dcnt > 0) + { + stm32_i2c_traceevent(priv, I2CEVENT_RCVBYTE, priv->dcnt); + + /* Receive a byte */ + + *priv->ptr++ = stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET); + + /* Disable acknowledge when last byte is to be received */ + + if (priv->dcnt == 1) + { + stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, 0); + } + priv->dcnt--; + } + } + + /* Do we have more bytes to send, enable/disable buffer interrupts + * (these ISRs could be replaced by DMAs) + */ + +#ifndef CONFIG_I2C_POLLED + if (priv->dcnt > 0) + { + stm32_i2c_traceevent(priv, I2CEVENT_REITBUFEN, 0); + stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, 0, I2C_CR2_ITBUFEN); + } + else if (priv->dcnt == 0) + { + stm32_i2c_traceevent(priv, I2CEVENT_DISITBUFEN, 0); + stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_ITBUFEN, 0); + } +#endif + + /* Was last byte received or sent? Hmmm... the F2 and F4 seems to differ from + * the F1 in that BTF is not set after data is received (only RXNE). + */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + if (priv->dcnt <= 0 && (status & (I2C_SR1_BTF|I2C_SR1_RXNE)) != 0) +#else + if (priv->dcnt <= 0 && (status & I2C_SR1_BTF) != 0) +#endif + { + stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET); /* ACK ISR */ + + /* Do we need to terminate or restart after this byte? + * If there are more messages to send, then we may: + * + * - continue with repeated start + * - or just continue sending writeable part + * - or we close down by sending the stop bit + */ + + if (priv->msgc > 0) + { + if (priv->msgv->flags & I2C_M_NORESTART) + { + stm32_i2c_traceevent(priv, I2CEVENT_BTFNOSTART, priv->msgc); + priv->ptr = priv->msgv->buffer; + priv->dcnt = priv->msgv->length; + priv->flags = priv->msgv->flags; + priv->msgv++; + priv->msgc--; + + /* Restart this ISR! */ + +#ifndef CONFIG_I2C_POLLED + stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, 0, I2C_CR2_ITBUFEN); +#endif + } + else + { + stm32_i2c_traceevent(priv, I2CEVENT_BTFRESTART, priv->msgc); + stm32_i2c_sendstart(priv); + } + } + else if (priv->msgv) + { + stm32_i2c_traceevent(priv, I2CEVENT_BTFSTOP, 0); + stm32_i2c_sendstop(priv); + + /* Is there a thread waiting for this event (there should be) */ + +#ifndef CONFIG_I2C_POLLED + if (priv->intstate == INTSTATE_WAITING) + { + /* Yes.. inform the thread that the transfer is complete + * and wake it up. + */ + + sem_post( &priv->sem_isr ); + priv->intstate = INTSTATE_DONE; + } +#else + priv->intstate = INTSTATE_DONE; +#endif + + /* Mark that we have stopped with this transaction */ + + priv->msgv = NULL; + } + } + + /* Check for errors, in which case, stop the transfer and return + * Note that in master reception mode AF becomes set on last byte + * since ACK is not returned. We should ignore this error. + */ + + if ((status & I2C_SR1_ERRORMASK) != 0) + { + stm32_i2c_traceevent(priv, I2CEVENT_ERROR, 0); + + /* Clear interrupt flags */ + + stm32_i2c_putreg(priv, STM32_I2C_SR1_OFFSET, 0); + + /* Is there a thread waiting for this event (there should be) */ + +#ifndef CONFIG_I2C_POLLED + if (priv->intstate == INTSTATE_WAITING) + { + /* Yes.. inform the thread that the transfer is complete + * and wake it up. + */ + + sem_post( &priv->sem_isr ); + priv->intstate = INTSTATE_DONE; + } +#else + priv->intstate = INTSTATE_DONE; +#endif + } + + priv->status = status; + return OK; +} + +/************************************************************************************ + * Name: stm32_i2c1_isr + * + * Description: + * I2C1 interrupt service routine + * + ************************************************************************************/ + +#ifndef CONFIG_I2C_POLLED +#ifdef CONFIG_STM32_I2C1 +static int stm32_i2c1_isr(int irq, void *context) +{ + return stm32_i2c_isr(&stm32_i2c1_priv); +} +#endif + +/************************************************************************************ + * Name: stm32_i2c2_isr + * + * Description: + * I2C2 interrupt service routine + * + ************************************************************************************/ + +#ifdef CONFIG_STM32_I2C2 +static int stm32_i2c2_isr(int irq, void *context) +{ + return stm32_i2c_isr(&stm32_i2c2_priv); +} +#endif + +/************************************************************************************ + * Name: stm32_i2c3_isr + * + * Description: + * I2C2 interrupt service routine + * + ************************************************************************************/ + +#ifdef CONFIG_STM32_I2C3 +static int stm32_i2c3_isr(int irq, void *context) +{ + return stm32_i2c_isr(&stm32_i2c3_priv); +} +#endif +#endif + +/************************************************************************************ + * Private Initialization and Deinitialization + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_i2c_init + * + * Description: + * Setup the I2C hardware, ready for operation with defaults + * + ************************************************************************************/ + +static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv) +{ + /* Power-up and configure GPIOs */ + + switch (priv->base) + { +#ifdef CONFIG_STM32_I2C1 + case STM32_I2C1_BASE: + + /* Enable power and reset the peripheral */ + + modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_I2C1EN); + + modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C1RST); + modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST, 0); + + /* Configure pins */ + + if (stm32_configgpio(GPIO_I2C1_SCL) < 0) + { + return ERROR; + } + + if (stm32_configgpio(GPIO_I2C1_SDA) < 0) + { + stm32_unconfiggpio(GPIO_I2C1_SCL); + return ERROR; + } + + /* Attach ISRs */ + +#ifndef CONFIG_I2C_POLLED + irq_attach(STM32_IRQ_I2C1EV, stm32_i2c1_isr); + irq_attach(STM32_IRQ_I2C1ER, stm32_i2c1_isr); + up_enable_irq(STM32_IRQ_I2C1EV); + up_enable_irq(STM32_IRQ_I2C1ER); +#endif + break; +#endif + +#ifdef CONFIG_STM32_I2C2 + case STM32_I2C2_BASE: + + /* Enable power and reset the peripheral */ + + modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_I2C2EN); + + modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C2RST); + modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST, 0); + + /* Configure pins */ + + if (stm32_configgpio(GPIO_I2C2_SCL) < 0) + { + return ERROR; + } + + if (stm32_configgpio(GPIO_I2C2_SDA) < 0) + { + stm32_unconfiggpio(GPIO_I2C2_SCL); + return ERROR; + } + + /* Attach ISRs */ + +#ifndef CONFIG_I2C_POLLED + irq_attach(STM32_IRQ_I2C2EV, stm32_i2c2_isr); + irq_attach(STM32_IRQ_I2C2ER, stm32_i2c2_isr); + up_enable_irq(STM32_IRQ_I2C2EV); + up_enable_irq(STM32_IRQ_I2C2ER); +#endif + break; +#endif + +#ifdef CONFIG_STM32_I2C3 + case STM32_I2C3_BASE: + + /* Enable power and reset the peripheral */ + + modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_I2C3EN); + + modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C3RST); + modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C3RST, 0); + + /* Configure pins */ + + if (stm32_configgpio(GPIO_I2C3_SCL) < 0) + { + return ERROR; + } + + if (stm32_configgpio(GPIO_I2C3_SDA) < 0) + { + stm32_unconfiggpio(GPIO_I2C3_SCL); + return ERROR; + } + + /* Attach ISRs */ + +#ifndef CONFIG_I2C_POLLED + irq_attach(STM32_IRQ_I2C3EV, stm32_i2c3_isr); + irq_attach(STM32_IRQ_I2C3ER, stm32_i2c3_isr); + up_enable_irq(STM32_IRQ_I2C3EV); + up_enable_irq(STM32_IRQ_I2C3ER); +#endif + break; +#endif + + default: + return ERROR; + } + + /* Set peripheral frequency, where it must be at least 2 MHz for 100 kHz + * or 4 MHz for 400 kHz. This also disables all I2C interrupts. + */ + + stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, (STM32_PCLK1_FREQUENCY / 1000000)); + stm32_i2c_setclock(priv, 100000); + + /* Enable I2C */ + + stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_PE); + return OK; +} + +/************************************************************************************ + * Name: stm32_i2c_deinit + * + * Description: + * Shutdown the I2C hardware + * + ************************************************************************************/ + +static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv) +{ + /* Disable I2C */ + + stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, 0); + + switch (priv->base) + { +#ifdef CONFIG_STM32_I2C1 + case STM32_I2C1_BASE: + stm32_unconfiggpio(GPIO_I2C1_SCL); + stm32_unconfiggpio(GPIO_I2C1_SDA); + +#ifndef CONFIG_I2C_POLLED + up_disable_irq(STM32_IRQ_I2C1EV); + up_disable_irq(STM32_IRQ_I2C1ER); + irq_detach(STM32_IRQ_I2C1EV); + irq_detach(STM32_IRQ_I2C1ER); +#endif + modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_I2C1EN, 0); + break; +#endif + +#ifdef CONFIG_STM32_I2C2 + case STM32_I2C2_BASE: + stm32_unconfiggpio(GPIO_I2C2_SCL); + stm32_unconfiggpio(GPIO_I2C2_SDA); + +#ifndef CONFIG_I2C_POLLED + up_disable_irq(STM32_IRQ_I2C2EV); + up_disable_irq(STM32_IRQ_I2C2ER); + irq_detach(STM32_IRQ_I2C2EV); + irq_detach(STM32_IRQ_I2C2ER); +#endif + modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_I2C2EN, 0); + break; +#endif + +#ifdef CONFIG_STM32_I2C3 + case STM32_I2C3_BASE: + stm32_unconfiggpio(GPIO_I2C3_SCL); + stm32_unconfiggpio(GPIO_I2C3_SDA); + +#ifndef CONFIG_I2C_POLLED + up_disable_irq(STM32_IRQ_I2C3EV); + up_disable_irq(STM32_IRQ_I2C3ER); + irq_detach(STM32_IRQ_I2C3EV); + irq_detach(STM32_IRQ_I2C3ER); +#endif + modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_I2C3EN, 0); + break; +#endif + + default: + return ERROR; + } + + return OK; +} + +/************************************************************************************ + * Device Driver Operations + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_i2c_setfrequency + * + * Description: + * Set the I2C frequency + * + ************************************************************************************/ + +static uint32_t stm32_i2c_setfrequency(FAR struct i2c_dev_s *dev, uint32_t frequency) +{ + stm32_i2c_sem_wait(dev); + +#if STM32_PCLK1_FREQUENCY < 4000000 + ((struct stm32_i2c_inst_s *)dev)->frequency = 100000; +#else + ((struct stm32_i2c_inst_s *)dev)->frequency = frequency; +#endif + + stm32_i2c_sem_post(dev); + return ((struct stm32_i2c_inst_s *)dev)->frequency; +} + +/************************************************************************************ + * Name: stm32_i2c_setaddress + * + * Description: + * Set the I2C slave address + * + ************************************************************************************/ + +static int stm32_i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits) +{ + stm32_i2c_sem_wait(dev); + + ((struct stm32_i2c_inst_s *)dev)->address = addr; + ((struct stm32_i2c_inst_s *)dev)->flags = (nbits == 10) ? I2C_M_TEN : 0; + + stm32_i2c_sem_post(dev); + return OK; +} + +/************************************************************************************ + * Name: stm32_i2c_process + * + * Description: + * Common I2C transfer logic + * + ************************************************************************************/ + +static int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int count) +{ + struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev; + FAR struct stm32_i2c_priv_s *priv = inst->priv; + uint32_t status = 0; + //uint32_t ahbenr; + int errval = 0; + + ASSERT(count); + + /* Disable FSMC that shares a pin with I2C1 (LBAR) */ + + (void)stm32_i2c_disablefsmc(priv); + + /* Wait for any STOP in progress. NOTE: If we have to disable the FSMC + * then we cannot do this at the top of the loop, unfortunately. The STOP + * will not complete normally if the FSMC is enabled. + */ + +#ifndef I2C1_FSMC_CONFLICT + #if CONFIG_STM32_I2CTIMEOUS_START_STOP > 0 + stm32_i2c_sem_waitstop(priv, CONFIG_STM32_I2CTIMEOUS_START_STOP); + #else + stm32_i2c_sem_waitstop(priv, CONFIG_STM32_I2CTIMEOMS + CONFIG_STM32_I2CTIMEOSEC * 1000000); + #endif +#endif + + /* Clear any pending error interrupts */ + + stm32_i2c_putreg(priv, STM32_I2C_SR1_OFFSET, 0); + + /* "Note: When the STOP, START or PEC bit is set, the software must + * not perform any write access to I2C_CR1 before this bit is + * cleared by hardware. Otherwise there is a risk of setting a + * second STOP, START or PEC request." However, if the bits are + * not cleared by hardware, then we will have to do that from hardware. + */ + + stm32_i2c_clrstart(priv); + + /* Old transfers are done */ + + priv->msgv = msgs; + priv->msgc = count; + + /* Calculate timeout values */ + int timeout_us = 0; + #if CONFIG_STM32_I2CTIMEOUS_PER_BYTE > 0 + /* Count the number of bytes left to process */ + int i; + int bytecount = 10; + for (i = 0; i < count; i++) + { + bytecount += msgs[i].length; + } + timeout_us = CONFIG_STM32_I2CTIMEOUS_PER_BYTE * bytecount; + //i2cvdbg("i2c wait: %d\n", timeout_us); + #else + timeout_us = CONFIG_STM32_I2CTIMEOMS + CONFIG_STM32_I2CTIMEOSEC * 1000000; + #endif + + /* Reset I2C trace logic */ + + stm32_i2c_tracereset(priv); + + /* Set I2C clock frequency (on change it toggles I2C_CR1_PE !) */ + + stm32_i2c_setclock(priv, inst->frequency); + + /* Trigger start condition, then the process moves into the ISR. I2C + * interrupts will be enabled within stm32_i2c_waitdone(). + */ + + priv->status = 0; + stm32_i2c_sendstart(priv); + + /* Wait for an ISR, if there was a timeout, fetch latest status to get + * the BUSY flag. + */ + + if (stm32_i2c_sem_waitdone(priv, timeout_us) < 0) + { + status = stm32_i2c_getstatus(priv); + errval = ETIMEDOUT; + + i2cdbg("Timed out: CR1: %04x status: %08x\n", + stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET), status); + + /* "Note: When the STOP, START or PEC bit is set, the software must + * not perform any write access to I2C_CR1 before this bit is + * cleared by hardware. Otherwise there is a risk of setting a + * second STOP, START or PEC request." + */ + + stm32_i2c_clrstart(priv); + // XXX also clear busy flag in case of timeout + status = priv->status & 0xffff; + } + else + { + /* clear SR2 (BUSY flag) as we've done successfully */ + + status = priv->status & 0xffff; + } + + /* Check for error status conditions */ + + if ((status & I2C_SR1_ERRORMASK) != 0) + { + /* I2C_SR1_ERRORMASK is the 'OR' of the following individual bits: */ + + if (status & I2C_SR1_BERR) + { + /* Bus Error */ + + errval = EIO; + } + else if (status & I2C_SR1_ARLO) + { + /* Arbitration Lost (master mode) */ + + errval = EAGAIN; + } + else if (status & I2C_SR1_AF) + { + /* Acknowledge Failure */ + + errval = ENXIO; + } + else if (status & I2C_SR1_OVR) + { + /* Overrun/Underrun */ + + errval = EIO; + } + else if (status & I2C_SR1_PECERR) + { + /* PEC Error in reception */ + + errval = EPROTO; + } + else if (status & I2C_SR1_TIMEOUT) + { + /* Timeout or Tlow Error */ + + errval = ETIME; + } + + /* This is not an error and should never happen since SMBus is not enabled */ + + else /* if (status & I2C_SR1_SMBALERT) */ + { + /* SMBus alert is an optional signal with an interrupt line for devices + * that want to trade their ability to master for a pin. + */ + + errval = EINTR; + } + } + + /* This is not an error, but should not happen. The BUSY signal can hang, + * however, if there are unhealthy devices on the bus that need to be reset. + * NOTE: We will only see this buy indication if stm32_i2c_sem_waitdone() + * fails above; Otherwise it is cleared. + */ + + else if ((status & (I2C_SR2_BUSY << 16)) != 0) + { + /* I2C Bus is for some reason busy */ + + errval = EBUSY; + } + + /* Dump the trace result */ + + stm32_i2c_tracedump(priv); + + /* Wait for any STOP in progress. NOTE: If we have to disable the FSMC + * then we cannot do this at the top of the loop, unfortunately. The STOP + * will not complete normally if the FSMC is enabled. + */ + +#ifdef I2C1_FSMC_CONFLICT + stm32_i2c_sem_waitstop(priv); +#endif + + /* Re-enable the FSMC */ + + stm32_i2c_enablefsmc(ahbenr); + stm32_i2c_sem_post(dev); + + return -errval; +} + +/************************************************************************************ + * Name: stm32_i2c_write + * + * Description: + * Write I2C data + * + ************************************************************************************/ + +static int stm32_i2c_write(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int buflen) +{ + stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */ + + struct i2c_msg_s msgv = + { + .addr = ((struct stm32_i2c_inst_s *)dev)->address, + .flags = ((struct stm32_i2c_inst_s *)dev)->flags, + .buffer = (uint8_t *)buffer, + .length = buflen + }; + + return stm32_i2c_process(dev, &msgv, 1); +} + +/************************************************************************************ + * Name: stm32_i2c_read + * + * Description: + * Read I2C data + * + ************************************************************************************/ + +int stm32_i2c_read(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen) +{ + stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */ + + struct i2c_msg_s msgv = + { + .addr = ((struct stm32_i2c_inst_s *)dev)->address, + .flags = ((struct stm32_i2c_inst_s *)dev)->flags | I2C_M_READ, + .buffer = buffer, + .length = buflen + }; + + return stm32_i2c_process(dev, &msgv, 1); +} + +/************************************************************************************ + * Name: stm32_i2c_writeread + * + * Description: + * Read then write I2C data + * + ************************************************************************************/ + +#ifdef CONFIG_I2C_WRITEREAD +static int stm32_i2c_writeread(FAR struct i2c_dev_s *dev, + const uint8_t *wbuffer, int wbuflen, + uint8_t *buffer, int buflen) +{ + stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */ + + struct i2c_msg_s msgv[2] = + { + { + .addr = ((struct stm32_i2c_inst_s *)dev)->address, + .flags = ((struct stm32_i2c_inst_s *)dev)->flags, + .buffer = (uint8_t *)wbuffer, /* this is really ugly, sorry const ... */ + .length = wbuflen + }, + { + .addr = ((struct stm32_i2c_inst_s *)dev)->address, + .flags = ((struct stm32_i2c_inst_s *)dev)->flags | ((buflen>0) ? I2C_M_READ : I2C_M_NORESTART), + .buffer = buffer, + .length = (buflen>0) ? buflen : -buflen + } + }; + + return stm32_i2c_process(dev, msgv, 2); +} +#endif + +/************************************************************************************ + * Name: stm32_i2c_transfer + * + * Description: + * Generic I2C transfer function + * + ************************************************************************************/ + +#ifdef CONFIG_I2C_TRANSFER +static int stm32_i2c_transfer(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, + int count) +{ + stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */ + return stm32_i2c_process(dev, msgs, count); +} +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_i2cinitialize + * + * Description: + * Initialize one I2C bus + * + ************************************************************************************/ + +FAR struct i2c_dev_s *up_i2cinitialize(int port) +{ + struct stm32_i2c_priv_s * priv = NULL; /* private data of device with multiple instances */ + struct stm32_i2c_inst_s * inst = NULL; /* device, single instance */ + int irqs; + +#if STM32_PCLK1_FREQUENCY < 4000000 +# warning STM32_I2C_INIT: Peripheral clock must be at least 4 MHz to support 400 kHz operation. +#endif + +#if STM32_PCLK1_FREQUENCY < 2000000 +# warning STM32_I2C_INIT: Peripheral clock must be at least 2 MHz to support 100 kHz operation. + return NULL; +#endif + + /* Get I2C private structure */ + + switch (port) + { +#ifdef CONFIG_STM32_I2C1 + case 1: + priv = (struct stm32_i2c_priv_s *)&stm32_i2c1_priv; + break; +#endif +#ifdef CONFIG_STM32_I2C2 + case 2: + priv = (struct stm32_i2c_priv_s *)&stm32_i2c2_priv; + break; +#endif +#ifdef CONFIG_STM32_I2C3 + case 3: + priv = (struct stm32_i2c_priv_s *)&stm32_i2c3_priv; + break; +#endif + default: + return NULL; + } + + /* Allocate instance */ + + if (!(inst = kmalloc( sizeof(struct stm32_i2c_inst_s)))) + { + return NULL; + } + + /* Initialize instance */ + + inst->ops = &stm32_i2c_ops; + inst->priv = priv; + inst->frequency = 100000; + inst->address = 0; + inst->flags = 0; + + /* Init private data for the first time, increment refs count, + * power-up hardware and configure GPIOs. + */ + + irqs = irqsave(); + + if ((volatile int)priv->refs++ == 0) + { + stm32_i2c_sem_init( (struct i2c_dev_s *)inst ); + stm32_i2c_init( priv ); + } + + irqrestore(irqs); + return (struct i2c_dev_s *)inst; +} + +/************************************************************************************ + * Name: up_i2cuninitialize + * + * Description: + * Uninitialize an I2C bus + * + ************************************************************************************/ + +int up_i2cuninitialize(FAR struct i2c_dev_s * dev) +{ + int irqs; + + ASSERT(dev); + + /* Decrement refs and check for underflow */ + + if (((struct stm32_i2c_inst_s *)dev)->priv->refs == 0) + { + return ERROR; + } + + irqs = irqsave(); + + if (--((struct stm32_i2c_inst_s *)dev)->priv->refs) + { + irqrestore(irqs); + kfree(dev); + return OK; + } + + irqrestore(irqs); + + /* Disable power and other HW resource (GPIO's) */ + + stm32_i2c_deinit( ((struct stm32_i2c_inst_s *)dev)->priv ); + + /* Release unused resources */ + + stm32_i2c_sem_destroy( (struct i2c_dev_s *)dev ); + + kfree(dev); + return OK; +} + +/************************************************************************************ + * Name: up_i2creset + * + * Description: + * Reset an I2C bus + * + ************************************************************************************/ + +int up_i2creset(FAR struct i2c_dev_s * dev) +{ + // ASSERT(dev); + + // stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */ + + // struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev; + // FAR struct stm32_i2c_priv_s *priv = inst->priv; + + // /* Clear any pending error interrupts */ + + // stm32_i2c_putreg(priv, STM32_I2C_SR1_OFFSET, 0); + + // /* "Note: When the STOP, START or PEC bit is set, the software must + // * not perform any write access to I2C_CR1 before this bit is + // * cleared by hardware. Otherwise there is a risk of setting a + // * second STOP, START or PEC request." However, if the bits are + // * not cleared by hardware, then we will have to do that from hardware. + // */ + + // stm32_i2c_clrstart(priv); + + // /* Reset peripheral */ + // uint16_t cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET); + // /* Set reset flag */ + // cr1 &= I2C_CR1_SWRST; + // stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1); + // /* Clear CR1 */ + // stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, 0); + + // switch (priv->base) + // { + // case STM32_I2C1_BASE: + // modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C1RST); + // modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST, 0); + // break; + // case STM32_I2C2_BASE: + // modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C2RST); + // modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST, 0); + // break; + // case STM32_I2C3_BASE: + // modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C3RST); + // modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C3RST, 0); + // break; + // } + + + + // stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, (STM32_PCLK1_FREQUENCY / 1000000)); + // stm32_i2c_setclock(priv, inst->frequency); + // inst->flags = 0; + + // /* Enable I2C */ + + // stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_PE); + + + + + + + + + + + + + + + + int irqs; + + ASSERT(dev); + + /* Decrement refs and check for underflow */ + + if (((struct stm32_i2c_inst_s *)dev)->priv->refs == 0) + { + return ERROR; + } + + irqs = irqsave(); + + irqrestore(irqs); + + /* Disable power and other HW resource (GPIO's) */ + + //stm32_i2c_deinit( ((struct stm32_i2c_inst_s *)dev)->priv ); + + /* Release unused resources */ + + //stm32_i2c_sem_destroy( (struct i2c_dev_s *)dev ); + + struct stm32_i2c_priv_s * priv = NULL; /* private data of device with multiple instances */ + struct stm32_i2c_inst_s * inst = NULL; /* device, single instance */ + +#if STM32_PCLK1_FREQUENCY < 4000000 +# warning STM32_I2C_INIT: Peripheral clock must be at least 4 MHz to support 400 kHz operation. +#endif + +#if STM32_PCLK1_FREQUENCY < 2000000 +# warning STM32_I2C_INIT: Peripheral clock must be at least 2 MHz to support 100 kHz operation. + return NULL; +#endif + + /* Get I2C private structure */ + + priv = ((struct stm32_i2c_inst_s *)dev)->priv; + +// switch (port) +// { +// #ifdef CONFIG_STM32_I2C1 +// case 1: +// priv = (struct stm32_i2c_priv_s *)&stm32_i2c1_priv; +// break; +// #endif +// #ifdef CONFIG_STM32_I2C2 +// case 2: +// priv = (struct stm32_i2c_priv_s *)&stm32_i2c2_priv; +// break; +// #endif +// #ifdef CONFIG_STM32_I2C3 +// case 3: +// priv = (struct stm32_i2c_priv_s *)&stm32_i2c3_priv; +// break; +// #endif +// default: +// return NULL; +// } + + /* Allocate instance */ + inst = (struct stm32_i2c_inst_s *)dev; + + /* Initialize instance */ + + inst->ops = &stm32_i2c_ops; + inst->priv = priv; + inst->frequency = 100000; + inst->address = 0; + inst->flags = 0; + + /* Init private data for the first time, increment refs count, + * power-up hardware and configure GPIOs. + */ + + irqs = irqsave(); + + if ((volatile int)priv->refs++ == 0) + { + stm32_i2c_sem_init( (struct i2c_dev_s *)inst ); + stm32_i2c_init( priv ); + } + + irqrestore(irqs); + return OK; +} + +#endif /* defined(CONFIG_STM32_I2C1) && defined(CONFIG_STM32_I2C2) */ diff --git a/nuttx/arch/arm/src/stm32/stm32_i2c.h b/nuttx/arch/arm/src/stm32/stm32_i2c.h new file mode 100644 index 0000000000..23a06bc051 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_i2c.h @@ -0,0 +1,50 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_i2c.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_I2C_H +#define __ARCH_ARM_SRC_STM32_STM32_I2C_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +#include "chip.h" +#include "chip/stm32_i2c.h" + +#endif /* __ARCH_ARM_SRC_STM32_STM32_I2C_H */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_idle.c b/nuttx/arch/arm/src/stm32/stm32_idle.c new file mode 100644 index 0000000000..791a79429c --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_idle.c @@ -0,0 +1,188 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_idle.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +#include + +#include "stm32_pm.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Does the board support an IDLE LED to indicate that the board is in the + * IDLE state? + */ + +#if defined(CONFIG_ARCH_LEDS) && defined(LED_IDLE) +# define BEGIN_IDLE() up_ledon(LED_IDLE) +# define END_IDLE() up_ledoff(LED_IDLE) +#else +# define BEGIN_IDLE() +# define END_IDLE() +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idlepm + * + * Description: + * Perform IDLE state power management. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static void up_idlepm(void) +{ + static enum pm_state_e oldstate = PM_NORMAL; + enum pm_state_e newstate; + irqstate_t flags; + int ret; + + /* Decide, which power saving level can be obtained */ + + newstate = pm_checkstate(); + + /* Check for state changes */ + + if (newstate != oldstate) + { + flags = irqsave(); + + /* Perform board-specific, state-dependent logic here */ + + llvdbg("newstate= %d oldstate=%d\n", newstate, oldstate); + + /* Then force the global state change */ + + ret = pm_changestate(newstate); + if (ret < 0) + { + /* The new state change failed, revert to the preceding state */ + + (void)pm_changestate(oldstate); + } + else + { + /* Save the new state */ + + oldstate = newstate; + } + + /* MCU-specific power management logic */ + + switch (newstate) + { + case PM_NORMAL: + break; + + case PM_IDLE: + break; + + case PM_STANDBY: + stm32_pmstop(true); + break; + + case PM_SLEEP: + (void)stm32_pmstandby(); + break; + + default: + break; + } + + irqrestore(flags); + } +} +#else +# define up_idlepm() +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idle + * + * Description: + * up_idle() is the logic that will be executed when their is no other + * ready-to-run task. This is processor idle time and will continue until + * some interrupt occurs to cause a context switch from the idle task. + * + * Processing in this state may be processor-specific. e.g., this is where + * power management operations might be performed. + * + ****************************************************************************/ + +void up_idle(void) +{ +#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS) + /* If the system is idle and there are no timer interrupts, then process + * "fake" timer interrupts. Hopefully, something will wake up. + */ + + sched_process_timer(); +#else + + /* Perform IDLE mode power management */ + + up_idlepm(); + + /* Sleep until an interrupt occurs to save power */ + + BEGIN_IDLE(); + asm("WFI"); + END_IDLE(); +#endif +} + diff --git a/nuttx/arch/arm/src/stm32/stm32_internal.h b/nuttx/arch/arm/src/stm32/stm32_internal.h new file mode 100644 index 0000000000..8db936786e --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_internal.h @@ -0,0 +1,45 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_internal.h + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_INTERNAL_H +#define __ARCH_ARM_SRC_STM32_STM32_INTERNAL_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include "stm32.h" + +#endif /* __ARCH_ARM_SRC_STM32_STM32_INTERNAL_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_irq.c b/nuttx/arch/arm/src/stm32/stm32_irq.c new file mode 100644 index 0000000000..36a5cf5fa7 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_irq.c @@ -0,0 +1,476 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_irq.c + * arch/arm/src/chip/stm32_irq.c + * + * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "nvic.h" +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" +#include "stm32_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Enable NVIC debug features that are probably only desireable during + * bringup + */ + +#undef STM32_IRQ_DEBUG + +/* Get a 32-bit version of the default priority */ + +#define DEFPRIORITY32 \ + (NVIC_SYSH_PRIORITY_DEFAULT << 24 |\ + NVIC_SYSH_PRIORITY_DEFAULT << 16 |\ + NVIC_SYSH_PRIORITY_DEFAULT << 8 |\ + NVIC_SYSH_PRIORITY_DEFAULT) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +volatile uint32_t *current_regs; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_dumpnvic + * + * Description: + * Dump some interesting NVIC registers + * + ****************************************************************************/ + +#if defined(STM32_IRQ_DEBUG) && defined (CONFIG_DEBUG) +static void stm32_dumpnvic(const char *msg, int irq) +{ + irqstate_t flags; + + flags = irqsave(); + slldbg("NVIC (%s, irq=%d):\n", msg, irq); + slldbg(" INTCTRL: %08x VECTAB: %08x\n", + getreg32(NVIC_INTCTRL), getreg32(NVIC_VECTAB)); +#if 0 + slldbg(" SYSH ENABLE MEMFAULT: %08x BUSFAULT: %08x USGFAULT: %08x SYSTICK: %08x\n", + getreg32(NVIC_SYSHCON_MEMFAULTENA), getreg32(NVIC_SYSHCON_BUSFAULTENA), + getreg32(NVIC_SYSHCON_USGFAULTENA), getreg32(NVIC_SYSTICK_CTRL_ENABLE)); +#endif + slldbg(" IRQ ENABLE: %08x %08x %08x\n", + getreg32(NVIC_IRQ0_31_ENABLE), getreg32(NVIC_IRQ32_63_ENABLE), + getreg32(NVIC_IRQ64_95_ENABLE)); + slldbg(" SYSH_PRIO: %08x %08x %08x\n", + getreg32(NVIC_SYSH4_7_PRIORITY), getreg32(NVIC_SYSH8_11_PRIORITY), + getreg32(NVIC_SYSH12_15_PRIORITY)); + slldbg(" IRQ PRIO: %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ0_3_PRIORITY), getreg32(NVIC_IRQ4_7_PRIORITY), + getreg32(NVIC_IRQ8_11_PRIORITY), getreg32(NVIC_IRQ12_15_PRIORITY)); + slldbg(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ16_19_PRIORITY), getreg32(NVIC_IRQ20_23_PRIORITY), + getreg32(NVIC_IRQ24_27_PRIORITY), getreg32(NVIC_IRQ28_31_PRIORITY)); + slldbg(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ32_35_PRIORITY), getreg32(NVIC_IRQ36_39_PRIORITY), + getreg32(NVIC_IRQ40_43_PRIORITY), getreg32(NVIC_IRQ44_47_PRIORITY)); + slldbg(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ48_51_PRIORITY), getreg32(NVIC_IRQ52_55_PRIORITY), + getreg32(NVIC_IRQ56_59_PRIORITY), getreg32(NVIC_IRQ60_63_PRIORITY)); + slldbg(" %08x\n", + getreg32(NVIC_IRQ64_67_PRIORITY)); + irqrestore(flags); +} +#else +# define stm32_dumpnvic(msg, irq) +#endif + +/**************************************************************************** + * Name: stm32_nmi, stm32_busfault, stm32_usagefault, stm32_pendsv, + * stm32_dbgmonitor, stm32_pendsv, stm32_reserved + * + * Description: + * Handlers for various execptions. None are handled and all are fatal + * error conditions. The only advantage these provided over the default + * unexpected interrupt handler is that they provide a diagnostic output. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG +static int stm32_nmi(int irq, FAR void *context) +{ + (void)irqsave(); + dbg("PANIC!!! NMI received\n"); + PANIC(OSERR_UNEXPECTEDISR); + return 0; +} + +static int stm32_busfault(int irq, FAR void *context) +{ + (void)irqsave(); + dbg("PANIC!!! Bus fault recived\n"); + PANIC(OSERR_UNEXPECTEDISR); + return 0; +} + +static int stm32_usagefault(int irq, FAR void *context) +{ + (void)irqsave(); + dbg("PANIC!!! Usage fault received\n"); + PANIC(OSERR_UNEXPECTEDISR); + return 0; +} + +static int stm32_pendsv(int irq, FAR void *context) +{ + (void)irqsave(); + dbg("PANIC!!! PendSV received\n"); + PANIC(OSERR_UNEXPECTEDISR); + return 0; +} + +static int stm32_dbgmonitor(int irq, FAR void *context) +{ + (void)irqsave(); + dbg("PANIC!!! Debug Monitor receieved\n"); + PANIC(OSERR_UNEXPECTEDISR); + return 0; +} + +static int stm32_reserved(int irq, FAR void *context) +{ + (void)irqsave(); + dbg("PANIC!!! Reserved interrupt\n"); + PANIC(OSERR_UNEXPECTEDISR); + return 0; +} +#endif + +/**************************************************************************** + * Name: stm32_irqinfo + * + * Description: + * Given an IRQ number, provide the register and bit setting to enable or + * disable the irq. + * + ****************************************************************************/ + +static int stm32_irqinfo(int irq, uint32_t *regaddr, uint32_t *bit) +{ + DEBUGASSERT(irq >= STM32_IRQ_NMI && irq < NR_IRQS); + + /* Check for external interrupt */ + + if (irq >= STM32_IRQ_INTERRUPTS) + { + if (irq < STM32_IRQ_INTERRUPTS + 32) + { + *regaddr = NVIC_IRQ0_31_ENABLE; + *bit = 1 << (irq - STM32_IRQ_INTERRUPTS); + } + else if (irq < STM32_IRQ_INTERRUPTS + 64) + { + *regaddr = NVIC_IRQ32_63_ENABLE; + *bit = 1 << (irq - STM32_IRQ_INTERRUPTS - 32); + } + else if (irq < NR_IRQS) + { + *regaddr = NVIC_IRQ64_95_ENABLE; + *bit = 1 << (irq - STM32_IRQ_INTERRUPTS - 64); + } + else + { + return ERROR; /* Invalid interrupt */ + } + } + + /* Handle processor exceptions. Only a few can be disabled */ + + else + { + *regaddr = NVIC_SYSHCON; + if (irq == STM32_IRQ_MEMFAULT) + { + *bit = NVIC_SYSHCON_MEMFAULTENA; + } + else if (irq == STM32_IRQ_BUSFAULT) + { + *bit = NVIC_SYSHCON_BUSFAULTENA; + } + else if (irq == STM32_IRQ_USAGEFAULT) + { + *bit = NVIC_SYSHCON_USGFAULTENA; + } + else if (irq == STM32_IRQ_SYSTICK) + { + *regaddr = NVIC_SYSTICK_CTRL; + *bit = NVIC_SYSTICK_CTRL_ENABLE; + } + else + { + return ERROR; /* Invalid or unsupported exception */ + } + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irqinitialize + ****************************************************************************/ + +void up_irqinitialize(void) +{ + uint32_t regaddr; + int num_priority_registers; + + /* Disable all interrupts */ + + putreg32(0, NVIC_IRQ0_31_ENABLE); + putreg32(0, NVIC_IRQ32_63_ENABLE); + + /* The standard location for the vector table is at the beginning of FLASH + * at address 0x0800:0000. If we are using the STMicro DFU bootloader, then + * the vector table will be offset to a different location in FLASH and we + * will need to set the NVIC vector location to this alternative location. + */ + +#ifdef CONFIG_STM32_DFU + putreg32((uint32_t)stm32_vectors, NVIC_VECTAB); +#endif + + /* Set all interrupts (and exceptions) to the default priority */ + + putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY); + + /* The NVIC ICTR register (bits 0-4) holds the number of of interrupt + * lines that the NVIC supports: + * + * 0 -> 32 interrupt lines, 8 priority registers + * 1 -> 64 " " " ", 16 priority registers + * 2 -> 96 " " " ", 32 priority registers + * ... + */ + + num_priority_registers = (getreg32(NVIC_ICTR) + 1) * 8; + + /* Now set all of the interrupt lines to the default priority */ + + regaddr = NVIC_IRQ0_3_PRIORITY; + while (num_priority_registers--) + { + putreg32(DEFPRIORITY32, regaddr); + regaddr += 4; + } + + /* currents_regs is non-NULL only while processing an interrupt */ + + current_regs = NULL; + + /* Attach the SVCall and Hard Fault exception handlers. The SVCall + * exception is used for performing context switches; The Hard Fault + * must also be caught because a SVCall may show up as a Hard Fault + * under certain conditions. + */ + + irq_attach(STM32_IRQ_SVCALL, up_svcall); + irq_attach(STM32_IRQ_HARDFAULT, up_hardfault); + + /* Set the priority of the SVCall interrupt */ + +#ifdef CONFIG_ARCH_IRQPRIO +/* up_prioritize_irq(STM32_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); */ +#endif + + /* If the MPU is enabled, then attach and enable the Memory Management + * Fault handler. + */ + +#ifdef CONFIG_ARMV7M_MPU + irq_attach(STM32_IRQ_MEMFAULT, up_memfault); + up_enable_irq(STM32_IRQ_MEMFAULT); +#endif + + /* Attach all other processor exceptions (except reset and sys tick) */ + +#ifdef CONFIG_DEBUG + irq_attach(STM32_IRQ_NMI, stm32_nmi); +#ifndef CONFIG_ARMV7M_MPU + irq_attach(STM32_IRQ_MEMFAULT, up_memfault); +#endif + irq_attach(STM32_IRQ_BUSFAULT, stm32_busfault); + irq_attach(STM32_IRQ_USAGEFAULT, stm32_usagefault); + irq_attach(STM32_IRQ_PENDSV, stm32_pendsv); + irq_attach(STM32_IRQ_DBGMONITOR, stm32_dbgmonitor); + irq_attach(STM32_IRQ_RESERVED, stm32_reserved); +#endif + + stm32_dumpnvic("initial", NR_IRQS); + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + + /* And finally, enable interrupts */ + + setbasepri(NVIC_SYSH_PRIORITY_MAX); + irqrestore(0); +#endif +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + uint32_t regaddr; + uint32_t regval; + uint32_t bit; + + if (stm32_irqinfo(irq, ®addr, &bit) == 0) + { + /* Clear the appropriate bit in the register to enable the interrupt */ + + regval = getreg32(regaddr); + regval &= ~bit; + putreg32(regval, regaddr); + } + stm32_dumpnvic("disable", irq); +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + uint32_t regaddr; + uint32_t regval; + uint32_t bit; + + if (stm32_irqinfo(irq, ®addr, &bit) == 0) + { + /* Set the appropriate bit in the register to enable the interrupt */ + + regval = getreg32(regaddr); + regval |= bit; + putreg32(regval, regaddr); + } + stm32_dumpnvic("enable", irq); +} + +/**************************************************************************** + * Name: up_maskack_irq + * + * Description: + * Mask the IRQ and acknowledge it + * + ****************************************************************************/ + +void up_maskack_irq(int irq) +{ + up_disable_irq(irq); +} + +/**************************************************************************** + * Name: up_prioritize_irq + * + * Description: + * Set the priority of an IRQ. + * + * Since this API is not supported on all architectures, it should be + * avoided in common implementations where possible. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_IRQPRIO +int up_prioritize_irq(int irq, int priority) +{ + uint32_t regaddr; + uint32_t regval; + int shift; + + DEBUGASSERT(irq >= STM32_IRQ_MEMFAULT && irq < NR_IRQS && (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); + + if (irq < STM32_IRQ_INTERRUPTS) + { + irq -= 4; + regaddr = NVIC_SYSH_PRIORITY(irq); + } + else + { + irq -= STM32_IRQ_INTERRUPTS; + regaddr = NVIC_IRQ_PRIORITY(irq); + } + + regval = getreg32(regaddr); + shift = ((irq & 3) << 3); + regval &= ~(0xff << shift); + regval |= (priority << shift); + putreg32(regval, regaddr); + + stm32_dumpnvic("prioritize", irq); + return OK; +} +#endif diff --git a/nuttx/arch/arm/src/stm32/stm32_iwdg.c b/nuttx/arch/arm/src/stm32/stm32_iwdg.c new file mode 100644 index 0000000000..fd51ba0fe6 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_iwdg.c @@ -0,0 +1,711 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_iwdg.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" +#include "stm32_rcc.h" +#include "chip/stm32_dbgmcu.h" +#include "stm32_wdg.h" + +#if defined(CONFIG_WATCHDOG) && defined(CONFIG_STM32_IWDG) + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Clocking *****************************************************************/ +/* The minimum frequency of the IWDG clock is: + * + * Fmin = Flsi / 256 + * + * So the maximum delay (in milliseconds) is then: + * + * 1000 * IWDG_RLR_MAX / Fmin + * + * For example, if Flsi = 30Khz (the nominal, uncalibrathed value), then the + * maximum delay is: + * + * Fmin = 117.1875 + * 1000 * 4095 / Fmin = 34,944 MSec + */ + +#define IWDG_FMIN (STM32_LSI_FREQUENCY / 256) +#define IWDG_MAXTIMEOUT (1000 * IWDG_RLR_MAX / IWDG_FMIN) + +/* Configuration ************************************************************/ + +#ifndef CONFIG_STM32_IWDG_DEFTIMOUT +# define CONFIG_STM32_IWDG_DEFTIMOUT IWDG_MAXTIMEOUT +#endif + +/* REVISIT: It appears that you can only setup the prescaler and reload + * registers once. After that, the SR register's PVU and RVU bits never go + * to zero. So we defer setting up these registers until the watchdog + * is started, then refuse any further attempts to change timeout. + */ + +#define CONFIG_STM32_IWDG_ONETIMESETUP 1 + +/* REVISIT: Another possibility is that we CAN change the prescaler and + * reload values after starting the timer. This option is untested but the + * implementation place conditioned on the following: + */ + +#undef CONFIG_STM32_IWDG_DEFERREDSETUP + +/* But you can only try one at a time */ + +#if defined(CONFIG_STM32_IWDG_ONETIMESETUP) && defined(CONFIG_STM32_IWDG_DEFERREDSETUP) +# error "Both CONFIG_STM32_IWDG_ONETIMESETUP and CONFIG_STM32_IWDG_DEFERREDSETUP are defined" +#endif + +/* Debug ********************************************************************/ +/* Non-standard debug that may be enabled just for testing the watchdog + * driver. NOTE: that only lldbg types are used so that the output is + * immediately available. + */ + +#ifdef CONFIG_DEBUG_WATCHDOG +# define wddbg lldbg +# define wdvdbg llvdbg +#else +# define wddbg(x...) +# define wdvdbg(x...) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ +/* This structure provides the private representation of the "lower-half" + * driver state structure. This structure must be cast-compatible with the + * well-known watchdog_lowerhalf_s structure. + */ + +struct stm32_lowerhalf_s +{ + FAR const struct watchdog_ops_s *ops; /* Lower half operations */ + uint32_t lsifreq; /* The calibrated frequency of the LSI oscillator */ + uint32_t timeout; /* The (actual) selected timeout */ + uint32_t lastreset; /* The last reset time */ + bool started; /* true: The watchdog timer has been started */ + uint8_t prescaler; /* Clock prescaler value */ + uint16_t reload; /* Timer reload value */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* Register operations ******************************************************/ + +#if defined(CONFIG_STM32_IWDG_REGDEBUG) && defined(CONFIG_DEBUG) +static uint16_t stm32_getreg(uint32_t addr); +static void stm32_putreg(uint16_t val, uint32_t addr); +#else +# define stm32_getreg(addr) getreg16(addr) +# define stm32_putreg(val,addr) putreg16(val,addr) +#endif + +static inline void stm32_setprescaler(FAR struct stm32_lowerhalf_s *priv); + +/* "Lower half" driver methods **********************************************/ + +static int stm32_start(FAR struct watchdog_lowerhalf_s *lower); +static int stm32_stop(FAR struct watchdog_lowerhalf_s *lower); +static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower); +static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower, + FAR struct watchdog_status_s *status); +static int stm32_settimeout(FAR struct watchdog_lowerhalf_s *lower, + uint32_t timeout); + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* "Lower half" driver methods */ + +static const struct watchdog_ops_s g_wdgops = +{ + .start = stm32_start, + .stop = stm32_stop, + .keepalive = stm32_keepalive, + .getstatus = stm32_getstatus, + .settimeout = stm32_settimeout, + .capture = NULL, + .ioctl = NULL, +}; + +/* "Lower half" driver state */ + +static struct stm32_lowerhalf_s g_wdgdev; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_getreg + * + * Description: + * Get the contents of an STM32 IWDG register + * + ****************************************************************************/ + +#if defined(CONFIG_STM32_IWDG_REGDEBUG) && defined(CONFIG_DEBUG) +static uint16_t stm32_getreg(uint32_t addr) +{ + static uint32_t prevaddr = 0; + static uint32_t count = 0; + static uint16_t preval = 0; + + /* Read the value from the register */ + + uint16_t val = getreg16(addr); + + /* Is this the same value that we read from the same registe last time? Are + * we polling the register? If so, suppress some of the output. + */ + + if (addr == prevaddr && val == preval) + { + if (count == 0xffffffff || ++count > 3) + { + if (count == 4) + { + lldbg("...\n"); + } + return val; + } + } + + /* No this is a new address or value */ + + else + { + /* Did we print "..." for the previous value? */ + + if (count > 3) + { + /* Yes.. then show how many times the value repeated */ + + lldbg("[repeats %d more times]\n", count-3); + } + + /* Save the new address, value, and count */ + + prevaddr = addr; + preval = val; + count = 1; + } + + /* Show the register value read */ + + lldbg("%08x->%04x\n", addr, val); + return val; +} +#endif + +/**************************************************************************** + * Name: stm32_putreg + * + * Description: + * Set the contents of an STM32 register to a value + * + ****************************************************************************/ + +#if defined(CONFIG_STM32_IWDG_REGDEBUG) && defined(CONFIG_DEBUG) +static void stm32_putreg(uint16_t val, uint32_t addr) +{ + /* Show the register value being written */ + + lldbg("%08x<-%04x\n", addr, val); + + /* Write the value */ + + putreg16(val, addr); +} +#endif + +/**************************************************************************** + * Name: stm32_setprescaler + * + * Description: + * Set up the prescaler and reload values. This seems to be something + * that can only be done one time. + * + * Input Parameters: + * priv - A pointer the internal representation of the "lower-half" + * driver state structure. + * timeout - The new timeout value in millisecnds. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static inline void stm32_setprescaler(FAR struct stm32_lowerhalf_s *priv) +{ + /* Enable write access to IWDG_PR and IWDG_RLR registers */ + + stm32_putreg(IWDG_KR_KEY_ENABLE, STM32_IWDG_KR); + + /* Wait for the PVU and RVU bits to be reset be hardware. These bits + * were set the last time that the PR register was written and may not + * yet be cleared. + * + * If the setup is only permitted one time, then this wait should not + * be necessary. + */ + +#ifndef CONFIG_STM32_IWDG_ONETIMESETUP + while ((stm32_getreg(STM32_IWDG_SR) & (IWDG_SR_PVU|IWDG_SR_RVU)) != 0); +#endif + + /* Set the prescaler */ + + stm32_putreg((uint16_t)priv->prescaler << IWDG_PR_SHIFT, STM32_IWDG_PR); + + /* Set the reload value */ + + stm32_putreg((uint16_t)priv->reload, STM32_IWDG_RLR); + + /* Reload the counter (and disable write access) */ + + stm32_putreg(IWDG_KR_KEY_RELOAD, STM32_IWDG_KR); +} + +/**************************************************************************** + * Name: stm32_start + * + * Description: + * Start the watchdog timer, resetting the time to the current timeout, + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_start(FAR struct watchdog_lowerhalf_s *lower) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; + irqstate_t flags; + + wdvdbg("Entry: started=%d\n"); + DEBUGASSERT(priv); + + /* Have we already been started? */ + + if (!priv->started) + { + /* REVISIT: It appears that you can only setup the prescaler and reload + * registers once. After that, the SR register's PVU and RVU bits never go + * to zero. So we defer setting up these registers until the watchdog + * is started, then refuse any further attempts to change timeout. + */ + + /* Set up prescaler and reload value for the selected timeout before + * starting the watchdog timer. + */ + +#if defined(CONFIG_STM32_IWDG_ONETIMESETUP) || defined(CONFIG_STM32_IWDG_DEFERREDSETUP) + stm32_setprescaler(priv); +#endif + + /* Enable IWDG (the LSI oscillator will be enabled by hardware). NOTE: + * If the "Hardware watchdog" feature is enabled through the device option + * bits, the watchdog is automatically enabled at power-on. + */ + + flags = irqsave(); + stm32_putreg(IWDG_KR_KEY_START, STM32_IWDG_KR); + priv->lastreset = clock_systimer(); + priv->started = true; + irqrestore(flags); + } + return OK; +} + +/**************************************************************************** + * Name: stm32_stop + * + * Description: + * Stop the watchdog timer + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_stop(FAR struct watchdog_lowerhalf_s *lower) +{ + /* There is no way to disable the IDWG timer once it has been started */ + + wdvdbg("Entry\n"); + return -ENOSYS; +} + +/**************************************************************************** + * Name: stm32_keepalive + * + * Description: + * Reset the watchdog timer to the current timeout value, prevent any + * imminent watchdog timeouts. This is sometimes referred as "pinging" + * the atchdog timer or "petting the dog". + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; + irqstate_t flags; + + wdvdbg("Entry\n"); + + /* Reload the IWDG timer */ + + flags = irqsave(); + stm32_putreg(IWDG_KR_KEY_RELOAD, STM32_IWDG_KR); + priv->lastreset = clock_systimer(); + irqrestore(flags); + + return OK; +} + +/**************************************************************************** + * Name: stm32_getstatus + * + * Description: + * Get the current watchdog timer status + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * stawtus - The location to return the watchdog status information. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower, + FAR struct watchdog_status_s *status) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; + uint32_t ticks; + uint32_t elapsed; + + wdvdbg("Entry\n"); + DEBUGASSERT(priv); + + /* Return the status bit */ + + status->flags = WDFLAGS_RESET; + if (priv->started) + { + status->flags |= WDFLAGS_ACTIVE; + } + + /* Return the actual timeout in milliseconds */ + + status->timeout = priv->timeout; + + /* Get the elapsed time since the last ping */ + + ticks = clock_systimer() - priv->lastreset; + elapsed = (int32_t)TICK2MSEC(ticks); + + if (elapsed > priv->timeout) + { + elapsed = priv->timeout; + } + + /* Return the approximate time until the watchdog timer expiration */ + + status->timeleft = priv->timeout - elapsed; + + wdvdbg("Status :\n"); + wdvdbg(" flags : %08x\n", status->flags); + wdvdbg(" timeout : %d\n", status->timeout); + wdvdbg(" timeleft : %d\n", status->timeleft); + return OK; +} + +/**************************************************************************** + * Name: stm32_settimeout + * + * Description: + * Set a new timeout value (and reset the watchdog timer) + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * timeout - The new timeout value in millisecnds. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_settimeout(FAR struct watchdog_lowerhalf_s *lower, + uint32_t timeout) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; + uint32_t fiwdg; + uint64_t reload; + int prescaler; + int shift; + + wdvdbg("Entry: timeout=%d\n", timeout); + DEBUGASSERT(priv); + + /* Can this timeout be represented? */ + + if (timeout < 1 || timeout > IWDG_MAXTIMEOUT) + { + wddbg("Cannot represent timeout=%d > %d\n", + timeout, IWDG_MAXTIMEOUT); + return -ERANGE; + } + + /* REVISIT: It appears that you can only setup the prescaler and reload + * registers once. After that, the SR register's PVU and RVU bits never go + * to zero. + */ + +#ifdef CONFIG_STM32_IWDG_ONETIMESETUP + if (priv->started) + { + wddbg("Timer is already started\n"); + return -EBUSY; + } +#endif + + /* Select the smallest prescaler that will result in a reload value that is + * less than the maximum. + */ + + for (prescaler = 0; ; prescaler++) + { + /* PR = 0 -> Divider = 4 = 1 << 2 + * PR = 1 -> Divider = 8 = 1 << 3 + * PR = 2 -> Divider = 16 = 1 << 4 + * PR = 3 -> Divider = 32 = 1 << 5 + * PR = 4 -> Divider = 64 = 1 << 6 + * PR = 5 -> Divider = 128 = 1 << 7 + * PR = 6 -> Divider = 256 = 1 << 8 + * PR = n -> Divider = 1 << (n+2) + */ + + shift = prescaler + 2; + + /* Get the IWDG counter frequency in Hz. For a nominal 32Khz LSI clock, + * this is value in the range of 7500 and 125. + */ + + fiwdg = priv->lsifreq >> shift; + + /* We want: + * 1000 * reload / Fiwdg = timeout + * Or: + * reload = Fiwdg * timeout / 1000 + */ + + reload = (uint64_t)fiwdg * (uint64_t)timeout / 1000; + + /* If this reload valid is less than the maximum or we are not ready + * at the prescaler value, then break out of the loop to use these + * settings. + */ + + if (reload <= IWDG_RLR_MAX || prescaler == 6) + { + /* Note that we explicity break out of the loop rather than using + * the 'for' loop termination logic because we do not want the + * value of prescaler to be incremented. + */ + + break; + } + } + + /* Make sure that the final reload value is within range */ + + if (reload > IWDG_RLR_MAX) + { + reload = IWDG_RLR_MAX; + } + + /* Get the actual timeout value in milliseconds. + * + * We have: + * reload = Fiwdg * timeout / 1000 + * So we want: + * timeout = 1000 * reload / Fiwdg + */ + + priv->timeout = (1000 * (uint32_t)reload) / fiwdg; + + /* Save setup values for later use */ + + priv->prescaler = prescaler; + priv->reload = reload; + + /* Write the prescaler and reload values to the IWDG registers. + * + * REVISIT: It appears that you can only setup the prescaler and reload + * registers once. After that, the SR register's PVU and RVU bits never go + * to zero. + */ + +#ifndef CONFIG_STM32_IWDG_ONETIMESETUP + /* If CONFIG_STM32_IWDG_DEFERREDSETUP is selected, then perform the register + * configuration only if the timer has been started. + */ + +#ifdef CONFIG_STM32_IWDG_DEFERREDSETUP + if (priv->started) +#endif + { + stm32_setprescaler(priv); + } +#endif + + wdvdbg("prescaler=%d fiwdg=%d reload=%d\n", prescaler, fiwdg, reload); + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_iwdginitialize + * + * Description: + * Initialize the IWDG watchdog time. The watchdog timer is intialized and + * registers as 'devpath. The initial state of the watchdog time is + * disabled. + * + * Input Parameters: + * devpath - The full path to the watchdog. This should be of the form + * /dev/watchdog0 + * lsifreq - The calibrated LSI clock frequency + * + * Returned Values: + * None + * + ****************************************************************************/ + +void stm32_iwdginitialize(FAR const char *devpath, uint32_t lsifreq) +{ + FAR struct stm32_lowerhalf_s *priv = &g_wdgdev; + + wdvdbg("Entry: devpath=%s lsifreq=%d\n", devpath, lsifreq); + + /* NOTE we assume that clocking to the IWDG has already been provided by + * the RCC initialization logic. + */ + + /* Initialize the driver state structure. */ + + priv->ops = &g_wdgops; + priv->lsifreq = lsifreq; + priv->started = false; + + /* Make sure that the LSI ocsillator is enabled. NOTE: The LSI oscillator + * is enabled here but is not disabled by this file (because this file does + * not know the the global usage of the oscillator. Any clock management + * logic (say, as part of a power management scheme) needs handle other + * LSI controls outside of this file. + */ + + stm32_rcc_enablelsi(); + wdvdbg("RCC CSR: %08x\n", getreg32(STM32_RCC_CSR)); + + /* Select an arbitrary initial timeout value. But don't start the watchdog + * yet. NOTE: If the "Hardware watchdog" feature is enabled through the + * device option bits, the watchdog is automatically enabled at power-on. + */ + + stm32_settimeout((FAR struct watchdog_lowerhalf_s *)priv, CONFIG_STM32_IWDG_DEFTIMOUT); + + /* Register the watchdog driver as /dev/watchdog0 */ + + (void)watchdog_register(devpath, (FAR struct watchdog_lowerhalf_s *)priv); + + /* When the microcontroller enters debug mode (Cortex™-M4F core halted), + * the IWDG counter either continues to work normally or stops, depending + * on DBG_WIDG_STOP configuration bit in DBG module. + */ + +#if defined(CONFIG_STM32_JTAG_FULL_ENABLE) || \ + defined(CONFIG_STM32_JTAG_NOJNTRST_ENABLE) || \ + defined(CONFIG_STM32_JTAG_SW_ENABLE) + { + uint32_t cr = getreg32(STM32_DBGMCU_CR); + cr |= DBGMCU_CR_IWDGSTOP; + putreg32(cr, STM32_DBGMCU_CR); + } +#endif +} + +#endif /* CONFIG_WATCHDOG && CONFIG_STM32_IWDG */ diff --git a/nuttx/arch/arm/src/stm32/stm32_lowputc.c b/nuttx/arch/arm/src/stm32/stm32_lowputc.c new file mode 100644 index 0000000000..14f4efae46 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_lowputc.c @@ -0,0 +1,428 @@ +/************************************************************************** + * arch/arm/src/stm32/stm32_lowputc.c + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************/ + +/************************************************************************** + * Included Files + **************************************************************************/ + +#include + +#include + +#include + +#include "up_internal.h" +#include "up_arch.h" + +#include "chip.h" + +#include "stm32_rcc.h" +#include "stm32_gpio.h" +#include "stm32_uart.h" +#include "stm32_internal.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ +/* Select USART parameters for the selected console */ + +#if defined(CONFIG_USART1_SERIAL_CONSOLE) +# define STM32_CONSOLE_BASE STM32_USART1_BASE +# define STM32_APBCLOCK STM32_PCLK2_FREQUENCY +# define STM32_CONSOLE_BAUD CONFIG_USART1_BAUD +# define STM32_CONSOLE_BITS CONFIG_USART1_BITS +# define STM32_CONSOLE_PARITY CONFIG_USART1_PARITY +# define STM32_CONSOLE_2STOP CONFIG_USART1_2STOP +# define STM32_CONSOLE_TX GPIO_USART1_TX +# define STM32_CONSOLE_RX GPIO_USART1_RX +#elif defined(CONFIG_USART2_SERIAL_CONSOLE) +# define STM32_CONSOLE_BASE STM32_USART2_BASE +# define STM32_APBCLOCK STM32_PCLK1_FREQUENCY +# define STM32_CONSOLE_BAUD CONFIG_USART2_BAUD +# define STM32_CONSOLE_BITS CONFIG_USART2_BITS +# define STM32_CONSOLE_PARITY CONFIG_USART2_PARITY +# define STM32_CONSOLE_2STOP CONFIG_USART2_2STOP +# define STM32_CONSOLE_TX GPIO_USART2_TX +# define STM32_CONSOLE_RX GPIO_USART2_RX +#elif defined(CONFIG_USART3_SERIAL_CONSOLE) +# define STM32_CONSOLE_BASE STM32_USART3_BASE +# define STM32_APBCLOCK STM32_PCLK1_FREQUENCY +# define STM32_CONSOLE_BAUD CONFIG_USART3_BAUD +# define STM32_CONSOLE_BITS CONFIG_USART3_BITS +# define STM32_CONSOLE_PARITY CONFIG_USART3_PARITY +# define STM32_CONSOLE_2STOP CONFIG_USART3_2STOP +# define STM32_CONSOLE_TX GPIO_USART3_TX +# define STM32_CONSOLE_RX GPIO_USART3_RX +#elif defined(CONFIG_USART4_SERIAL_CONSOLE) +# define STM32_CONSOLE_BASE STM32_UART4_BASE +# define STM32_APBCLOCK STM32_PCLK1_FREQUENCY +# define STM32_CONSOLE_BAUD CONFIG_USART4_BAUD +# define STM32_CONSOLE_BITS CONFIG_USART4_BITS +# define STM32_CONSOLE_PARITY CONFIG_USART4_PARITY +# define STM32_CONSOLE_2STOP CONFIG_USART4_2STOP +# define STM32_CONSOLE_TX GPIO_UART4_TX +# define STM32_CONSOLE_RX GPIO_UART4_RX +#elif defined(CONFIG_USART5_SERIAL_CONSOLE) +# define STM32_CONSOLE_BASE STM32_UART5_BASE +# define STM32_APBCLOCK STM32_PCLK1_FREQUENCY +# define STM32_CONSOLE_BAUD CONFIG_USART5_BAUD +# define STM32_CONSOLE_BITS CONFIG_USART5_BITS +# define STM32_CONSOLE_PARITY CONFIG_USART5_PARITY +# define STM32_CONSOLE_2STOP CONFIG_USART5_2STOP +# define STM32_CONSOLE_TX GPIO_UART5_TX +# define STM32_CONSOLE_RX GPIO_UART5_RX +#elif defined(CONFIG_USART6_SERIAL_CONSOLE) +# define STM32_CONSOLE_BASE STM32_USART6_BASE +# define STM32_APBCLOCK STM32_PCLK2_FREQUENCY +# define STM32_CONSOLE_BAUD CONFIG_USART6_BAUD +# define STM32_CONSOLE_BITS CONFIG_USART6_BITS +# define STM32_CONSOLE_PARITY CONFIG_USART6_PARITY +# define STM32_CONSOLE_2STOP CONFIG_USART6_2STOP +# define STM32_CONSOLE_TX GPIO_USART6_TX +# define STM32_CONSOLE_RX GPIO_USART6_RX +#endif + +/* CR1 settings */ + +#if STM32_CONSOLE_BITS == 9 +# define USART_CR1_M_VALUE USART_CR1_M +#else +# define USART_CR1_M_VALUE 0 +#endif + +#if STM32_CONSOLE_PARITY == 1 +# define USART_CR1_PARITY_VALUE (USART_CR1_PCE|USART_CR1_PS) +#elif STM32_CONSOLE_PARITY == 2 +# define USART_CR1_PARITY_VALUE USART_CR1_PCE +#else +# define USART_CR1_PARITY_VALUE 0 +#endif + +#define USART_CR1_CLRBITS (USART_CR1_M|USART_CR1_PCE|USART_CR1_PS|USART_CR1_TE|USART_CR1_RE|USART_CR1_ALLINTS) +#define USART_CR1_SETBITS (USART_CR1_M_VALUE|USART_CR1_PARITY_VALUE) + +/* CR2 settings */ + +#if STM32_CONSOLE_2STOP != 0 +# define USART_CR2_STOP2_VALUE USART_CR2_STOP2 +#else +# define USART_CR2_STOP2_VALUE 0 +#endif + +#define USART_CR2_CLRBITS (USART_CR2_STOP_MASK|USART_CR2_CLKEN|USART_CR2_CPOL|USART_CR2_CPHA|USART_CR2_LBCL|USART_CR2_LBDIE) +#define USART_CR2_SETBITS USART_CR2_STOP2_VALUE + +/* CR3 settings */ + +#define USART_CR3_CLRBITS (USART_CR3_CTSIE|USART_CR3_CTSE|USART_CR3_RTSE|USART_CR3_EIE) +#define USART_CR3_SETBITS 0 + +/* Calculate USART BAUD rate divider + * + * The baud rate for the receiver and transmitter (Rx and Tx) are both set to + * the same value as programmed in the Mantissa and Fraction values of USARTDIV. + * + * baud = fCK / (16 * usartdiv) + * usartdiv = fCK / (16 * baud) + * + * Where fCK is the input clock to the peripheral (PCLK1 for USART2, 3, 4, 5 + * or PCLK2 for USART1). Example, fCK=72MHz baud=115200, usartdiv=39.0625=39 1/16th; + * + * First calculate: + * + * usartdiv32 = 32 * usartdiv = fCK / (baud/2) + * + * (NOTE: all standard baud values are even so dividing by two does not + * lose precision). Eg. (same fCK and buad), usartdiv32 = 1250 + */ + +#define STM32_USARTDIV32 (STM32_APBCLOCK / (STM32_CONSOLE_BAUD >> 1)) + +/* The mantissa is then usartdiv32 / 32: + * + * mantissa = usartdiv32 / 32/ + * + * Eg. usartdiv32=1250, mantissa = 39 + */ + +#define STM32_MANTISSA (STM32_USARTDIV32 >> 5) + +/* And the fraction: + * + * fraction = (usartdiv32 - mantissa*32 + 1) / 2 + * + * Eg., (1,250 - 39*32 + 1)/2 = 1 (or 0.0625) + */ + +#define STM32_FRACTION ((STM32_USARTDIV32 - (STM32_MANTISSA << 5) + 1) >> 1) + +/* And, finally, the BRR value is: */ + +#define STM32_BRR_VALUE ((STM32_MANTISSA << USART_BRR_MANT_SHIFT) | (STM32_FRACTION << USART_BRR_FRAC_SHIFT)) + +/************************************************************************** + * Private Types + **************************************************************************/ + +/************************************************************************** + * Private Function Prototypes + **************************************************************************/ + +/************************************************************************** + * Global Variables + **************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/************************************************************************** + * Public Functions + **************************************************************************/ + +/************************************************************************** + * Name: up_lowputc + * + * Description: + * Output one byte on the serial console + * + **************************************************************************/ + +void up_lowputc(char ch) +{ +#ifdef HAVE_CONSOLE + /* Wait until the TX data register is empty */ + + while ((getreg32(STM32_CONSOLE_BASE + STM32_USART_SR_OFFSET) & USART_SR_TXE) == 0); + + /* Then send the character */ + + putreg32((uint32_t)ch, STM32_CONSOLE_BASE + STM32_USART_DR_OFFSET); +#endif +} + +/************************************************************************** + * Name: stm32_lowsetup + * + * Description: + * This performs basic initialization of the USART used for the serial + * console. Its purpose is to get the console output availabe as soon + * as possible. + * + **************************************************************************/ + +#if defined(CONFIG_STM32_STM32F10XX) +void stm32_lowsetup(void) +{ +#if defined(HAVE_UART) + uint32_t mapr; +#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) + uint32_t cr; +#endif + + /* Set up the pin mapping registers for the selected U[S]ARTs. + * + * NOTE: Clocking for selected U[S]ARTs was already provided in stm32_rcc.c + */ + + mapr = getreg32(STM32_AFIO_MAPR); + +#ifdef CONFIG_STM32_USART1 + /* Assume default pin mapping: + * + * Alternate USART1_REMAP USART1_REMAP + * Function = 0 = 1 + * ---------- ------------ ------------ + * USART1_TX PA9 PB6 + * USART1_RX PA10 PB7 + */ + +#ifdef CONFIG_STM32_USART1_REMAP + mapr |= AFIO_MAPR_USART1_REMAP; +#else + mapr &= ~AFIO_MAPR_USART1_REMAP; +#endif +#endif /* CONFIG_STM32_USART1 */ + +#ifdef CONFIG_STM32_USART2 + /* Assume default pin mapping: + * + * Alternate USART2_REMAP USART2_REMAP + * Function = 0 = 1 + * ---------- ------------ ------------ + * USART2_CTS PA0 PD3 + * USART2_RTS PA1 PD4 + * USART2_TX PA2 PD5 + * USART2_RX PA3 PD6 + * USART3_CK PA4 PD7 + */ + +#ifdef CONFIG_STM32_USART2_REMAP + mapr |= AFIO_MAPR_USART2_REMAP; +#else + mapr &= ~AFIO_MAPR_USART2_REMAP; +#endif +#endif /* CONFIG_STM32_USART2 */ + + /* Assume default pin mapping: + * + * Alternate USART3_REMAP[1:0] USART3_REMAP[1:0] USART3_REMAP[1:0] + * Function = “00†(no remap) = “01†(partial remap) = “11†(full remap) + * ---------_ ------------------ ---------------------- -------------------- + * USART3_TX PB10 PC10 PD8 + * USART3_RX PB11 PC11 PD9 + * USART3_CK PB12 PC12 PD10 + * USART3_CTS PB13 PB13 PD11 + * USART3_RTS PB14 PB14 PD12 + */ + + mapr &= ~AFIO_MAPR_USART3_REMAP_MASK; + +#ifdef CONFIG_STM32_USART3 +#if defined(CONFIG_STM32_USART3_PARTIAL_REMAP) + mapr |= AFIO_MAPR_USART3_PARTREMAP; +#elif defined(CONFIG_STM32_USART3_FULL_REMAP) + mapr |= AFIO_MAPR_USART3_FULLREMAP; +#endif +#endif /* CONFIG_STM32_USART3 */ + + putreg32(mapr, STM32_AFIO_MAPR); + + /* Configure GPIO pins needed for rx/tx. */ + +#ifdef STM32_CONSOLE_TX + stm32_configgpio(STM32_CONSOLE_TX); + stm32_configgpio(STM32_CONSOLE_TX); +#endif + + /* Enable and configure the selected console device */ + +#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) + /* Configure CR2 */ + + cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR2_OFFSET); + cr &= ~USART_CR2_CLRBITS; + cr |= USART_CR2_SETBITS; + putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR2_OFFSET); + + /* Configure CR1 */ + + cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET); + cr &= ~USART_CR1_CLRBITS; + cr |= USART_CR1_SETBITS; + putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET); + + /* Configure CR3 */ + + cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR3_OFFSET); + cr &= ~USART_CR3_CLRBITS; + cr |= USART_CR3_SETBITS; + putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR3_OFFSET); + + /* Configure the USART Baud Rate */ + + putreg32(STM32_BRR_VALUE, STM32_CONSOLE_BASE + STM32_USART_BRR_OFFSET); + + /* Enable Rx, Tx, and the USART */ + + cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET); + cr |= (USART_CR1_UE|USART_CR1_TE|USART_CR1_RE); + putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET); +#endif +#endif /* HAVE_UART */ +} +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +void stm32_lowsetup(void) +{ +#if defined(HAVE_UART) +#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) + uint32_t cr; +#endif + + /* Enable the console USART and configure GPIO pins needed for rx/tx. + * + * NOTE: Clocking for selected U[S]ARTs was already provided in stm32_rcc.c + */ + +#ifdef STM32_CONSOLE_TX + stm32_configgpio(STM32_CONSOLE_TX); + stm32_configgpio(STM32_CONSOLE_TX); +#endif + + /* Enable and configure the selected console device */ + +#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) + /* Configure CR2 */ + + cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR2_OFFSET); + cr &= ~USART_CR2_CLRBITS; + cr |= USART_CR2_SETBITS; + putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR2_OFFSET); + + /* Configure CR1 */ + + cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET); + cr &= ~USART_CR1_CLRBITS; + cr |= USART_CR1_SETBITS; + putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET); + + /* Configure CR3 */ + + cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR3_OFFSET); + cr &= ~USART_CR3_CLRBITS; + cr |= USART_CR3_SETBITS; + putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR3_OFFSET); + + /* Configure the USART Baud Rate */ + + putreg32(STM32_BRR_VALUE, STM32_CONSOLE_BASE + STM32_USART_BRR_OFFSET); + + /* Enable Rx, Tx, and the USART */ + + cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET); + cr |= (USART_CR1_UE|USART_CR1_TE|USART_CR1_RE); + putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET); +#endif +#endif /* HAVE_UART */ +} +#else +# error "Unsupported STM32 chip" +#endif + + diff --git a/nuttx/arch/arm/src/stm32/stm32_lowputc.h b/nuttx/arch/arm/src/stm32/stm32_lowputc.h new file mode 100644 index 0000000000..edcc78d8f1 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_lowputc.h @@ -0,0 +1,79 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_lowputc.h + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_LOWPUTC_H +#define __ARCH_ARM_SRC_STM32_STM32_LOWPUTC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Name: stm32_lowsetup + * + * Description: + * Called at the very beginning of _start. Performs low level initialization + * of serial console. + * + ************************************************************************************/ + +EXTERN void stm32_lowsetup(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_LOWPUTC_H */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_lse.c b/nuttx/arch/arm/src/stm32/stm32_lse.c new file mode 100644 index 0000000000..931199efdc --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_lse.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_lse.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "up_arch.h" + +#include "stm32_rcc.h" +#include "stm32_waste.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_rcc_enablelse + * + * Description: + * Enable the External Low-Speed (LSE) Oscillator and, if the RTC is + * configured, setup the LSE as the RTC clock source, and enable the RTC. + * + * Todo: + * Check for LSE good timeout and return with -1, + * + ****************************************************************************/ + +void stm32_rcc_enablelse(void) +{ + /* Enable the External Low-Speed (LSE) Oscillator by setting the LSEON bit + * the RCC BDCR register. + */ + + modifyreg16(STM32_RCC_BDCR, 0, RCC_BDCR_LSEON); + + /* Wait for the LSE clock to be ready */ + + while ((getreg16(STM32_RCC_BDCR) & RCC_BDCR_LSERDY) == 0) + { + up_waste(); + } + + /* The primariy purpose of the LSE clock is to drive the RTC. The RTC could + * also be driven by the LSI (but that would be very inaccurate) or by the + * HSE (but that would prohibit low-power operation) + * + * Select LSE as RTC Clock Source by setting the RTCSEL field of the RCC BDCR + * register. + */ + +#ifdef CONFIG_RTC + modifyreg16(STM32_RCC_BDCR, RCC_BDCR_RTCSEL_MASK, RCC_BDCR_RTCSEL_LSE); + + /* Enable the RTC Clock by setting the RTCEN bit in the RCC BDCR register */ + + modifyreg16(STM32_RCC_BDCR, 0, RCC_BDCR_RTCEN); +#endif +} diff --git a/nuttx/arch/arm/src/stm32/stm32_lsi.c b/nuttx/arch/arm/src/stm32/stm32_lsi.c new file mode 100644 index 0000000000..e365fbf06f --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_lsi.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_lsi.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "up_arch.h" + +#include "stm32_rcc.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_rcc_enablelsi + * + * Description: + * Enable the Internal Low-Speed (LSI) RC Oscillator. + * + ****************************************************************************/ + +void stm32_rcc_enablelsi(void) +{ + /* Enable the Internal Low-Speed (LSI) RC Oscillator by setting the LSION bit + * the RCC CSR register. + */ + + modifyreg32(STM32_RCC_CSR, 0, RCC_CSR_LSION); + + /* Wait for the internal RC 40 kHz oscillator to be stable. */ + + while ((getreg32(STM32_RCC_CSR) & RCC_CSR_LSIRDY) == 0); +} + +/**************************************************************************** + * Name: stm32_rcc_disablelsi + * + * Description: + * Disable the Internal Low-Speed (LSI) RC Oscillator. + * + ****************************************************************************/ + +void stm32_rcc_disablelsi(void) +{ + /* Enable the Internal Low-Speed (LSI) RC Oscillator by setting the LSION bit + * the RCC CSR register. + */ + + modifyreg32(STM32_RCC_CSR, RCC_CSR_LSION, 0); + + /* LSIRDY should go low after 3 LSI clock cycles */ +} diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfs.h b/nuttx/arch/arm/src/stm32/stm32_otgfs.h new file mode 100644 index 0000000000..74f2bdd315 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_otgfs.h @@ -0,0 +1,93 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_otgfs.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_OTGFS_H +#define __ARCH_ARM_SRC_STM32_STM32_OTGFS_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include + +#include "stm32.h" +#include "chip/stm32_otgfs.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ + +#ifndef CONFIG_OTGFS_PRI +# define CONFIG_OTGFS_PRI NVIC_SYSH_PRIORITY_DEFAULT +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Name: stm32_usbsuspend + * + * Description: + * Board logic must provide the stm32_usbsuspend logic if the OTG FS device driver + * is used. This function is called whenever the USB enters or leaves suspend + * mode. This is an opportunity for the board logic to shutdown clocks, power, + * etc. while the USB is suspended. + * + ************************************************************************************/ + +EXTERN void stm32_usbsuspend(FAR struct usbdev_s *dev, bool resume); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_OTGFS_H */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c new file mode 100644 index 0000000000..39c40d80ab --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c @@ -0,0 +1,5413 @@ +/******************************************************************************* + * arch/arm/src/stm32/stm32_usbdev.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +/******************************************************************************* + * Included Files + *******************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "chip.h" +#include "up_arch.h" +#include "up_internal.h" + +#include "stm32_otgfs.h" + +#if defined(CONFIG_USBDEV) && defined(CONFIG_STM32_OTGFS) + +/******************************************************************************* + * Definitions + *******************************************************************************/ +/* Configuration ***************************************************************/ + +#ifndef CONFIG_USBDEV_EP0_MAXSIZE +# define CONFIG_USBDEV_EP0_MAXSIZE 64 +#endif + +#ifndef CONFIG_USBDEV_SETUP_MAXDATASIZE +# define CONFIG_USBDEV_SETUP_MAXDATASIZE CONFIG_USBDEV_EP0_MAXSIZE +#endif + +#ifndef CONFIG_USBDEV_MAXPOWER +# define CONFIG_USBDEV_MAXPOWER 100 /* mA */ +#endif + +/* There is 1.25Kb of FIFO memory. The default partitions this memory + * so that there is a TxFIFO allocated for each endpoint and with more + * memory provided for the common RxFIFO. A more knowledge-able + * configuration would not allocate any TxFIFO space to OUT endpoints. + */ + +#ifndef CONFIG_USBDEV_RXFIFO_SIZE +# define CONFIG_USBDEV_RXFIFO_SIZE 512 +#endif + +#ifndef CONFIG_USBDEV_EP0_TXFIFO_SIZE +# define CONFIG_USBDEV_EP0_TXFIFO_SIZE 192 +#endif + +#ifndef CONFIG_USBDEV_EP1_TXFIFO_SIZE +# define CONFIG_USBDEV_EP1_TXFIFO_SIZE 192 +#endif + +#ifndef CONFIG_USBDEV_EP2_TXFIFO_SIZE +# define CONFIG_USBDEV_EP2_TXFIFO_SIZE 192 +#endif + +#ifndef CONFIG_USBDEV_EP3_TXFIFO_SIZE +# define CONFIG_USBDEV_EP3_TXFIFO_SIZE 192 +#endif + +#if (CONFIG_USBDEV_RXFIFO_SIZE + CONFIG_USBDEV_EP0_TXFIFO_SIZE + \ + CONFIG_USBDEV_EP2_TXFIFO_SIZE + CONFIG_USBDEV_EP3_TXFIFO_SIZE) > 1280 +# error "FIFO allocations exceed FIFO memory size" +#endif + +/* The actual FIFO addresses that we use must be aligned to 4-byte boundaries; + * FIFO sizes must be provided in units of 32-bit words. + */ + +#define STM32_RXFIFO_BYTES ((CONFIG_USBDEV_RXFIFO_SIZE + 3) & ~3) +#define STM32_RXFIFO_WORDS ((CONFIG_USBDEV_RXFIFO_SIZE + 3) >> 2) + +#define STM32_EP0_TXFIFO_BYTES ((CONFIG_USBDEV_EP0_TXFIFO_SIZE + 3) & ~3) +#define STM32_EP0_TXFIFO_WORDS ((CONFIG_USBDEV_EP0_TXFIFO_SIZE + 3) >> 2) + +#if STM32_EP0_TXFIFO_WORDS < 16 || STM32_EP0_TXFIFO_WORDS > 256 +# error "CONFIG_USBDEV_EP0_TXFIFO_SIZE is out of range" +#endif + +#define STM32_EP1_TXFIFO_BYTES ((CONFIG_USBDEV_EP1_TXFIFO_SIZE + 3) & ~3) +#define STM32_EP1_TXFIFO_WORDS ((CONFIG_USBDEV_EP1_TXFIFO_SIZE + 3) >> 2) + +#if STM32_EP1_TXFIFO_WORDS < 16 +# error "CONFIG_USBDEV_EP1_TXFIFO_SIZE is out of range" +#endif + +#define STM32_EP2_TXFIFO_BYTES ((CONFIG_USBDEV_EP2_TXFIFO_SIZE + 3) & ~3) +#define STM32_EP2_TXFIFO_WORDS ((CONFIG_USBDEV_EP2_TXFIFO_SIZE + 3) >> 2) + +#if STM32_EP2_TXFIFO_WORDS < 16 +# error "CONFIG_USBDEV_EP2_TXFIFO_SIZE is out of range" +#endif + +#define STM32_EP3_TXFIFO_BYTES ((CONFIG_USBDEV_EP3_TXFIFO_SIZE + 3) & ~3) +#define STM32_EP3_TXFIFO_WORDS ((CONFIG_USBDEV_EP3_TXFIFO_SIZE + 3) >> 2) + +#if STM32_EP3_TXFIFO_WORDS < 16 +# error "CONFIG_USBDEV_EP3_TXFIFO_SIZE is out of range" +#endif + +/* REVISIT! This forces a hack that polls DTXFSTS for space in the Tx FIFO. + * Enabling this option is a BAD thing. It will cause inline waits inside + * of the USB interrupt handler. The correct way to handle this is to + * enable the correct TxFIFO interrupt and wait until the Tx FIFO is empty. + * Unfortunately, the interrupt driven logic is not working... Please fix! + */ + +#define ENABLE_DTXFSTS_POLLHACK 1 + +/* Debug ***********************************************************************/ +/* Trace error codes */ + +#define STM32_TRACEERR_ALLOCFAIL 0x01 +#define STM32_TRACEERR_BADCLEARFEATURE 0x02 +#define STM32_TRACEERR_BADDEVGETSTATUS 0x03 +#define STM32_TRACEERR_BADEPNO 0x04 +#define STM32_TRACEERR_BADEPGETSTATUS 0x05 +#define STM32_TRACEERR_BADGETCONFIG 0x06 +#define STM32_TRACEERR_BADGETSETDESC 0x07 +#define STM32_TRACEERR_BADGETSTATUS 0x08 +#define STM32_TRACEERR_BADSETADDRESS 0x09 +#define STM32_TRACEERR_BADSETCONFIG 0x0a +#define STM32_TRACEERR_BADSETFEATURE 0x0b +#define STM32_TRACEERR_BADTESTMODE 0x0c +#define STM32_TRACEERR_BINDFAILED 0x0d +#define STM32_TRACEERR_DISPATCHSTALL 0x0e +#define STM32_TRACEERR_DRIVER 0x0f +#define STM32_TRACEERR_DRIVERREGISTERED 0x10 +#define STM32_TRACEERR_EP0NOSETUP 0x11 +#define STM32_TRACEERR_EP0SETUPSTALLED 0x12 +#define STM32_TRACEERR_EPINNULLPACKET 0x13 +#define STM32_TRACEERR_EPOUTNULLPACKET 0x14 +#define STM32_TRACEERR_INVALIDCTRLREQ 0x15 +#define STM32_TRACEERR_INVALIDPARMS 0x16 +#define STM32_TRACEERR_IRQREGISTRATION 0x17 +#define STM32_TRACEERR_NOEP 0x18 +#define STM32_TRACEERR_NOTCONFIGURED 0x19 +#define STM32_TRACEERR_EPOUTQEMPTY 0x1a +#define STM32_TRACEERR_EPINQEMPTY 0x1b +#define STM32_TRACEERR_NOOUTSETUP 0x1c + +/* Trace interrupt codes */ + +#define STM32_TRACEINTID_USB 1 /* USB Interrupt entry/exit */ +#define STM32_TRACEINTID_INTPENDING 2 /* On each pass through the loop */ + +#define STM32_TRACEINTID_EPOUT (10 + 0) /* First level interrupt decode */ +#define STM32_TRACEINTID_EPIN (10 + 1) +#define STM32_TRACEINTID_MISMATCH (10 + 2) +#define STM32_TRACEINTID_WAKEUP (10 + 3) +#define STM32_TRACEINTID_SUSPEND (10 + 4) +#define STM32_TRACEINTID_SOF (10 + 5) +#define STM32_TRACEINTID_RXFIFO (10 + 6) +#define STM32_TRACEINTID_DEVRESET (10 + 7) +#define STM32_TRACEINTID_ENUMDNE (10 + 8) +#define STM32_TRACEINTID_IISOIXFR (10 + 9) +#define STM32_TRACEINTID_IISOOXFR (10 + 10) +#define STM32_TRACEINTID_SRQ (10 + 11) +#define STM32_TRACEINTID_OTG (10 + 12) + +#define STM32_TRACEINTID_EPOUT_XFRC (40 + 0) /* EPOUT second level decode */ +#define STM32_TRACEINTID_EPOUT_EPDISD (40 + 1) +#define STM32_TRACEINTID_EPOUT_SETUP (40 + 2) +#define STM32_TRACEINTID_DISPATCH (40 + 3) + +#define STM32_TRACEINTID_GETSTATUS (50 + 0) /* EPOUT third level decode */ +#define STM32_TRACEINTID_EPGETSTATUS (50 + 1) +#define STM32_TRACEINTID_DEVGETSTATUS (50 + 2) +#define STM32_TRACEINTID_IFGETSTATUS (50 + 3) +#define STM32_TRACEINTID_CLEARFEATURE (50 + 4) +#define STM32_TRACEINTID_SETFEATURE (50 + 5) +#define STM32_TRACEINTID_SETADDRESS (50 + 6) +#define STM32_TRACEINTID_GETSETDESC (50 + 7) +#define STM32_TRACEINTID_GETCONFIG (50 + 8) +#define STM32_TRACEINTID_SETCONFIG (50 + 9) +#define STM32_TRACEINTID_GETSETIF (50 + 10) +#define STM32_TRACEINTID_SYNCHFRAME (50 + 11) + +#define STM32_TRACEINTID_EPIN_XFRC (70 + 0) /* EPIN second level decode */ +#define STM32_TRACEINTID_EPIN_TOC (70 + 1) +#define STM32_TRACEINTID_EPIN_ITTXFE (70 + 2) +#define STM32_TRACEINTID_EPIN_EPDISD (70 + 3) +#define STM32_TRACEINTID_EPIN_TXFE (70 + 4) + +#define STM32_TRACEINTID_EPIN_EMPWAIT (80 + 0) /* EPIN second level decode */ + +#define STM32_TRACEINTID_OUTNAK (90 + 0) /* RXFLVL second level decode */ +#define STM32_TRACEINTID_OUTRECVD (90 + 1) +#define STM32_TRACEINTID_OUTDONE (90 + 2) +#define STM32_TRACEINTID_SETUPDONE (90 + 3) +#define STM32_TRACEINTID_SETUPRECVD (90 + 4) + +/* Endpoints ******************************************************************/ + +/* Number of endpoints */ + +#define STM32_NENDPOINTS (4) /* ep0-3 x 2 for IN and OUT */ + +/* Odd physical endpoint numbers are IN; even are OUT */ + +#define STM32_EPPHYIN2LOG(epphy) ((uint8_t)(epphy)|USB_DIR_IN) +#define STM32_EPPHYOUT2LOG(epphy) ((uint8_t)(epphy)|USB_DIR_OUT) + +/* Endpoint 0 */ + +#define EP0 (0) + +/* The set of all enpoints available to the class implementation (1-3) */ + +#define STM32_EP_AVAILABLE (0x0e) /* All available endpoints */ + +/* Maximum packet sizes for full speed endpoints */ + +#define STM32_MAXPACKET (64) /* Max packet size (1-64) */ + +/* Delays **********************************************************************/ + +#define STM32_READY_DELAY 200000 +#define STM32_FLUSH_DELAY 200000 + +/* Request queue operations ****************************************************/ + +#define stm32_rqempty(ep) ((ep)->head == NULL) +#define stm32_rqpeek(ep) ((ep)->head) + +/* Standard stuff **************************************************************/ + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/******************************************************************************* + * Private Types + *******************************************************************************/ + +/* Overall device state */ + +enum stm32_devstate_e +{ + DEVSTATE_DEFAULT = 0, /* Power-up, unconfigured state. This state simply + * means that the device is not yet been given an + * address. + * SET: At initialization, uninitialization, + * reset, and whenever the device address + * is set to zero + * TESTED: Never + */ + DEVSTATE_ADDRESSED, /* Device address has been assigned, not no + * configuration has yet been selected. + * SET: When either a non-zero device address + * is first assigned or when the device + * is unconfigured (with configuration == 0) + * TESTED: never + */ + DEVSTATE_CONFIGURED, /* Address assigned and configured: + * SET: When the device has been addressed and + * an non-zero configuration has been selected. + * TESTED: In many places to assure that the USB device + * has been properly configured by the host. + */ +}; + +/* Endpoint 0 states */ + +enum stm32_ep0state_e +{ + EP0STATE_IDLE = 0, /* Idle State, leave on receiving a SETUP packet or + * epsubmit: + * SET: In stm32_epin() and stm32_epout() when + * we revert from request processing to + * SETUP processing. + * TESTED: Never + */ + EP0STATE_SETUP_OUT, /* OUT SETUP packet received. Waiting for the DATA + * OUT phase of SETUP Packet to complete before + * processing a SETUP command (without a USB request): + * SET: Set in stm32_rxinterrupt() when SETUP OUT + * packet is received. + * TESTED: In stm32_ep0out_receive() + */ + EP0STATE_SETUP_READY, /* IN SETUP packet received -OR- OUT SETUP packet and + * accompanying data have been received. Processing + * of SETUP command will happen soon. + * SET: (1) stm32_ep0out_receive() when the OUT + * SETUP data phase completes, or (2) + * stm32_rxinterrupt() when an IN SETUP is + * packet received. + * TESTED: Tested in stm32_epout_interrupt() when + * SETUP phase is done to see if the SETUP + * command is ready to be processed. Also + * tested in stm32_ep0out_setup() just to + * double-check that we have a SETUP request + * and any accompanying data. + */ + EP0STATE_SETUP_PROCESS, /* SETUP Packet is being processed by stm32_ep0out_setup(): + * SET: When SETUP packet received in EP0 OUT + * TESTED: Never + */ + EP0STATE_SETUPRESPONSE, /* Short SETUP response write (without a USB request): + * SET: When SETUP response is sent by + * stm32_ep0in_setupresponse() + * TESTED: Never + */ + EP0STATE_DATA_IN, /* Waiting for data out stage (with a USB request): + * SET: In stm32_epin_request() when a write + * request is processed on EP0. + * TESTED: In stm32_epin() to see if we should + * revert to SETUP processing. + */ + EP0STATE_DATA_OUT /* Waiting for data in phase to complete ( with a + * USB request) + * SET: In stm32_epout_request() when a read + * request is processed on EP0. + * TESTED: In stm32_epout() to see if we should + * revert to SETUP processing + */ +}; + +/* Parsed control request */ + +struct stm32_ctrlreq_s +{ + uint8_t type; + uint8_t req; + uint16_t value; + uint16_t index; + uint16_t len; +}; + +/* A container for a request so that the request may be retained in a list */ + +struct stm32_req_s +{ + struct usbdev_req_s req; /* Standard USB request */ + struct stm32_req_s *flink; /* Supports a singly linked list */ +}; + +/* This is the internal representation of an endpoint */ + +struct stm32_ep_s +{ + /* Common endpoint fields. This must be the first thing defined in the + * structure so that it is possible to simply cast from struct usbdev_ep_s + * to struct stm32_ep_s. + */ + + struct usbdev_ep_s ep; /* Standard endpoint structure */ + + /* STM32-specific fields */ + + struct stm32_usbdev_s *dev; /* Reference to private driver data */ + struct stm32_req_s *head; /* Request list for this endpoint */ + struct stm32_req_s *tail; + uint8_t epphy; /* Physical EP address */ + uint8_t eptype:2; /* Endpoint type */ + uint8_t configured:1; /* 1: Endpoint has been configured */ + uint8_t active:1; /* 1: A request is being processed */ + uint8_t stalled:1; /* 1: Endpoint is stalled */ + uint8_t isin:1; /* 1: IN Endpoint */ + uint8_t odd:1; /* 1: Odd frame */ + uint8_t zlp:1; /* 1: Transmit a zero-length-packet (IN EPs only) */ +}; + +/* This structure retains the state of the USB device controller */ + +struct stm32_usbdev_s +{ + /* Common device fields. This must be the first thing defined in the + * structure so that it is possible to simply cast from struct usbdev_s + * to struct stm32_usbdev_s. + */ + + struct usbdev_s usbdev; + + /* The bound device class driver */ + + struct usbdevclass_driver_s *driver; + + /* STM32-specific fields */ + + uint8_t stalled:1; /* 1: Protocol stalled */ + uint8_t selfpowered:1; /* 1: Device is self powered */ + uint8_t connected:1; /* 1: Host connected */ + uint8_t addressed:1; /* 1: Peripheral address has been set */ + uint8_t configured:1; /* 1: Class driver has been configured */ + uint8_t wakeup:1; /* 1: Device remote wake-up */ + uint8_t dotest:1; /* 1: Test mode selected */ + + uint8_t devstate:4; /* See enum stm32_devstate_e */ + uint8_t ep0state:4; /* See enum stm32_ep0state_e */ + uint8_t testmode:4; /* Selected test mode */ + uint8_t epavail:4; /* Bitset of available endpoints */ + + /* E0 SETUP data buffering. + * + * ctrlreq: + * The 8-byte SETUP request is received on the EP0 OUT endpoint and is + * saved. + * + * ep0data + * For OUT SETUP requests, the SETUP data phase must also complete before + * the SETUP command can be processed. The pack receipt logic will save + * the accompanying EP0 IN data in ep0data[] before the SETUP command is + * processed. + * + * For IN SETUP requests, the DATA phase will occurr AFTER the SETUP + * control request is processed. In that case, ep0data[] may be used as + * the response buffer. + * + * ep0datlen + * Lenght of OUT DATA received in ep0data[] (Not used with OUT data) + */ + + struct usb_ctrlreq_s ctrlreq; + uint8_t ep0data[CONFIG_USBDEV_SETUP_MAXDATASIZE]; + uint16_t ep0datlen; + + /* The endpoint lists */ + + struct stm32_ep_s epin[STM32_NENDPOINTS]; + struct stm32_ep_s epout[STM32_NENDPOINTS]; +}; + +/******************************************************************************* + * Private Function Prototypes + *******************************************************************************/ + +/* Register operations ********************************************************/ + +#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG) +static uint32_t stm32_getreg(uint32_t addr); +static void stm32_putreg(uint32_t val, uint32_t addr); +#else +# define stm32_getreg(addr) getreg32(addr) +# define stm32_putreg(val,addr) putreg32(val,addr) +#endif + +/* Request queue operations ****************************************************/ + +static FAR struct stm32_req_s *stm32_req_remfirst(FAR struct stm32_ep_s *privep); +static bool stm32_req_addlast(FAR struct stm32_ep_s *privep, + FAR struct stm32_req_s *req); + +/* Low level data transfers and request operations *****************************/ +/* Special endpoint 0 data transfer logic */ + +static void stm32_ep0in_setupresponse(FAR struct stm32_usbdev_s *priv, + FAR uint8_t *data, uint32_t nbytes); +static inline void stm32_ep0in_transmitzlp(FAR struct stm32_usbdev_s *priv); +static void stm32_ep0in_activate(void); + +static void stm32_ep0out_ctrlsetup(FAR struct stm32_usbdev_s *priv); + +/* IN request and TxFIFO handling */ + +static void stm32_txfifo_write(FAR struct stm32_ep_s *privep, + FAR uint8_t *buf, int nbytes); +static void stm32_epin_transfer(FAR struct stm32_ep_s *privep, + FAR uint8_t *buf, int nbytes); +static void stm32_epin_request(FAR struct stm32_usbdev_s *priv, + FAR struct stm32_ep_s *privep); + +/* OUT request and RxFIFO handling */ + +static void stm32_rxfifo_read(FAR struct stm32_ep_s *privep, + FAR uint8_t *dest, uint16_t len); +static void stm32_rxfifo_discard(FAR struct stm32_ep_s *privep, int len); +static void stm32_epout_complete(FAR struct stm32_usbdev_s *priv, + FAR struct stm32_ep_s *privep); +static inline void stm32_ep0out_receive(FAR struct stm32_ep_s *privep, int bcnt); +static inline void stm32_epout_receive(FAR struct stm32_ep_s *privep, int bcnt); +static void stm32_epout_request(FAR struct stm32_usbdev_s *priv, + FAR struct stm32_ep_s *privep); + +/* General request handling */ + +static void stm32_ep_flush(FAR struct stm32_ep_s *privep); +static void stm32_req_complete(FAR struct stm32_ep_s *privep, + int16_t result); +static void stm32_req_cancel(FAR struct stm32_ep_s *privep, + int16_t status); + +/* Interrupt handling **********************************************************/ + +static struct stm32_ep_s *stm32_ep_findbyaddr(struct stm32_usbdev_s *priv, + uint16_t eplog); +static int stm32_req_dispatch(FAR struct stm32_usbdev_s *priv, + FAR const struct usb_ctrlreq_s *ctrl); +static void stm32_usbreset(FAR struct stm32_usbdev_s *priv); + +/* Second level OUT endpoint interrupt processing */ + +static inline void stm32_ep0out_testmode(FAR struct stm32_usbdev_s *priv, + uint16_t index); +static inline void stm32_ep0out_stdrequest(struct stm32_usbdev_s *priv, + FAR struct stm32_ctrlreq_s *ctrlreq); +static inline void stm32_ep0out_setup(struct stm32_usbdev_s *priv); +static inline void stm32_epout(FAR struct stm32_usbdev_s *priv, + uint8_t epno); +static inline void stm32_epout_interrupt(FAR struct stm32_usbdev_s *priv); + +/* Second level IN endpoint interrupt processing */ + +static inline void stm32_epin_runtestmode(FAR struct stm32_usbdev_s *priv); +static inline void stm32_epin(FAR struct stm32_usbdev_s *priv, uint8_t epno); +static inline void stm32_epin_txfifoempty(FAR struct stm32_usbdev_s *priv, int epno); +static inline void stm32_epin_interrupt(FAR struct stm32_usbdev_s *priv); + +/* Other second level interrupt processing */ + +static inline void stm32_resumeinterrupt(FAR struct stm32_usbdev_s *priv); +static inline void stm32_suspendinterrupt(FAR struct stm32_usbdev_s *priv); +static inline void stm32_rxinterrupt(FAR struct stm32_usbdev_s *priv); +static inline void stm32_enuminterrupt(FAR struct stm32_usbdev_s *priv); +#ifdef CONFIG_USBDEV_ISOCHRONOUS +static inline void stm32_isocininterrupt(FAR struct stm32_usbdev_s *priv); +static inline void stm32_isocoutinterrupt(FAR struct stm32_usbdev_s *priv); +#endif +#ifdef CONFIG_USBDEV_VBUSSENSING +static inline void stm32_sessioninterrupt(FAR struct stm32_usbdev_s *priv); +static inline void stm32_otginterrupt(FAR struct stm32_usbdev_s *priv); +#endif + +/* First level interrupt processing */ + +static int stm32_usbinterrupt(int irq, FAR void *context); + +/* Endpoint operations *********************************************************/ +/* Global OUT NAK controls */ + +static void stm32_enablegonak(FAR struct stm32_ep_s *privep); +static void stm32_disablegonak(FAR struct stm32_ep_s *privep); + +/* Endpoint configuration */ + +static int stm32_epout_configure(FAR struct stm32_ep_s *privep, + uint8_t eptype, uint16_t maxpacket); +static int stm32_epin_configure(FAR struct stm32_ep_s *privep, + uint8_t eptype, uint16_t maxpacket); +static int stm32_ep_configure(FAR struct usbdev_ep_s *ep, + FAR const struct usb_epdesc_s *desc, bool last); +static void stm32_ep0_configure(FAR struct stm32_usbdev_s *priv); + +/* Endpoint disable */ + +static void stm32_epout_disable(FAR struct stm32_ep_s *privep); +static void stm32_epin_disable(FAR struct stm32_ep_s *privep); +static int stm32_ep_disable(FAR struct usbdev_ep_s *ep); + +/* Endpoint request management */ + +static FAR struct usbdev_req_s *stm32_ep_allocreq(FAR struct usbdev_ep_s *ep); +static void stm32_ep_freereq(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *); + +/* Endpoint buffer management */ + +#ifdef CONFIG_ARCH_USBDEV_DMA +static void *stm32_ep_allocbuffer(FAR struct usbdev_ep_s *ep, unsigned bytes); +static void stm32_ep_freebuffer(FAR struct usbdev_ep_s *ep, FAR void *buf); +#endif + +/* Endpoint request submission */ + +static int stm32_ep_submit(FAR struct usbdev_ep_s *ep, + struct usbdev_req_s *req); + +/* Endpoint request cancellation */ + +static int stm32_ep_cancel(FAR struct usbdev_ep_s *ep, + struct usbdev_req_s *req); + +/* Stall handling */ + +static int stm32_epout_setstall(FAR struct stm32_ep_s *privep); +static int stm32_epin_setstall(FAR struct stm32_ep_s *privep); +static int stm32_ep_setstall(FAR struct stm32_ep_s *privep); +static int stm32_ep_clrstall(FAR struct stm32_ep_s *privep); +static int stm32_ep_stall(FAR struct usbdev_ep_s *ep, bool resume); +static void stm32_ep0_stall(FAR struct stm32_usbdev_s *priv); + +/* Endpoint allocation */ + +static FAR struct usbdev_ep_s *stm32_ep_alloc(FAR struct usbdev_s *dev, + uint8_t epno, bool in, uint8_t eptype); +static void stm32_ep_free(FAR struct usbdev_s *dev, + FAR struct usbdev_ep_s *ep); + +/* USB device controller operations ********************************************/ + +static int stm32_getframe(struct usbdev_s *dev); +static int stm32_wakeup(struct usbdev_s *dev); +static int stm32_selfpowered(struct usbdev_s *dev, bool selfpowered); +static int stm32_pullup(struct usbdev_s *dev, bool enable); +static void stm32_setaddress(struct stm32_usbdev_s *priv, + uint16_t address); +static int stm32_txfifo_flush(uint32_t txfnum); +static int stm32_rxfifo_flush(void); + +/* Initialization **************************************************************/ + +static void stm32_swinitialize(FAR struct stm32_usbdev_s *priv); +static void stm32_hwinitialize(FAR struct stm32_usbdev_s *priv); + +/******************************************************************************* + * Private Data + *******************************************************************************/ +/* Since there is only a single USB interface, all status information can be + * be simply retained in a single global instance. + */ + +static struct stm32_usbdev_s g_otgfsdev; + +static const struct usbdev_epops_s g_epops = +{ + .configure = stm32_ep_configure, + .disable = stm32_ep_disable, + .allocreq = stm32_ep_allocreq, + .freereq = stm32_ep_freereq, +#ifdef CONFIG_ARCH_USBDEV_DMA + .allocbuffer = stm32_ep_allocbuffer, + .freebuffer = stm32_ep_freebuffer, +#endif + .submit = stm32_ep_submit, + .cancel = stm32_ep_cancel, + .stall = stm32_ep_stall, +}; + +static const struct usbdev_ops_s g_devops = +{ + .allocep = stm32_ep_alloc, + .freeep = stm32_ep_free, + .getframe = stm32_getframe, + .wakeup = stm32_wakeup, + .selfpowered = stm32_selfpowered, + .pullup = stm32_pullup, +}; + +/******************************************************************************* + * Public Data + *******************************************************************************/ + +/******************************************************************************* + * Private Functions + *******************************************************************************/ + +/******************************************************************************* + * Name: stm32_getreg + * + * Description: + * Get the contents of an STM32 register + * + *******************************************************************************/ + +#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG) +static uint32_t stm32_getreg(uint32_t addr) +{ + static uint32_t prevaddr = 0; + static uint32_t preval = 0; + static uint32_t count = 0; + + /* Read the value from the register */ + + uint32_t val = getreg32(addr); + + /* Is this the same value that we read from the same registe last time? Are + * we polling the register? If so, suppress some of the output. + */ + + if (addr == prevaddr && val == preval) + { + if (count == 0xffffffff || ++count > 3) + { + if (count == 4) + { + lldbg("...\n"); + } + return val; + } + } + + /* No this is a new address or value */ + + else + { + /* Did we print "..." for the previous value? */ + + if (count > 3) + { + /* Yes.. then show how many times the value repeated */ + + lldbg("[repeats %d more times]\n", count-3); + } + + /* Save the new address, value, and count */ + + prevaddr = addr; + preval = val; + count = 1; + } + + /* Show the register value read */ + + lldbg("%08x->%08x\n", addr, val); + return val; +} +#endif + +/******************************************************************************* + * Name: stm32_putreg + * + * Description: + * Set the contents of an STM32 register to a value + * + *******************************************************************************/ + +#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG) +static void stm32_putreg(uint32_t val, uint32_t addr) +{ + /* Show the register value being written */ + + lldbg("%08x<-%08x\n", addr, val); + + /* Write the value */ + + putreg32(val, addr); +} +#endif + +/******************************************************************************* + * Name: stm32_req_remfirst + * + * Description: + * Remove a request from the head of an endpoint request queue + * + *******************************************************************************/ + +static FAR struct stm32_req_s *stm32_req_remfirst(FAR struct stm32_ep_s *privep) +{ + FAR struct stm32_req_s *ret = privep->head; + + if (ret) + { + privep->head = ret->flink; + if (!privep->head) + { + privep->tail = NULL; + } + + ret->flink = NULL; + } + + return ret; +} + +/******************************************************************************* + * Name: stm32_req_addlast + * + * Description: + * Add a request to the end of an endpoint request queue + * + *******************************************************************************/ + +static bool stm32_req_addlast(FAR struct stm32_ep_s *privep, + FAR struct stm32_req_s *req) +{ + bool is_empty = !privep->head; + + req->flink = NULL; + if (is_empty) + { + privep->head = req; + privep->tail = req; + } + else + { + privep->tail->flink = req; + privep->tail = req; + } + return is_empty; +} + +/******************************************************************************* + * Name: stm32_ep0in_setupresponse + * + * Description: + * Schedule a short transfer on Endpoint 0 (IN or OUT) + * + *******************************************************************************/ + +static void stm32_ep0in_setupresponse(FAR struct stm32_usbdev_s *priv, + FAR uint8_t *buf, uint32_t nbytes) +{ + stm32_epin_transfer(&priv->epin[EP0], buf, nbytes); + priv->ep0state = EP0STATE_SETUPRESPONSE; + stm32_ep0out_ctrlsetup(priv); +} + +/**************************************************************************** + * Name: stm32_ep0in_transmitzlp + * + * Description: + * Send a zero length packet (ZLP) on endpoint 0 IN + * + ****************************************************************************/ + +static inline void stm32_ep0in_transmitzlp(FAR struct stm32_usbdev_s *priv) +{ + stm32_ep0in_setupresponse(priv, NULL, 0); +} + +/******************************************************************************* + * Name: stm32_ep0in_activate + * + * Description: + * Activate the endpoint 0 IN endpoint. + * + *******************************************************************************/ + +static void stm32_ep0in_activate(void) +{ + uint32_t regval; + + /* Set the max packet size of the IN EP. */ + + regval = stm32_getreg(STM32_OTGFS_DIEPCTL0); + regval &= ~OTGFS_DIEPCTL0_MPSIZ_MASK; + +#if CONFIG_USBDEV_EP0_MAXSIZE == 8 + regval |= OTGFS_DIEPCTL0_MPSIZ_8; +#elif CONFIG_USBDEV_EP0_MAXSIZE == 16 + regval |= OTGFS_DIEPCTL0_MPSIZ_16; +#elif CONFIG_USBDEV_EP0_MAXSIZE == 32 + regval |= OTGFS_DIEPCTL0_MPSIZ_32; +#elif CONFIG_USBDEV_EP0_MAXSIZE == 64 + regval |= OTGFS_DIEPCTL0_MPSIZ_64; +#else +# error "Unsupported value of CONFIG_USBDEV_EP0_MAXSIZE" +#endif + + stm32_putreg(regval, STM32_OTGFS_DIEPCTL0); + + /* Clear global IN NAK */ + + regval = stm32_getreg(STM32_OTGFS_DCTL); + regval |= OTGFS_DCTL_CGINAK; + stm32_putreg(regval, STM32_OTGFS_DCTL); +} + +/******************************************************************************* + * Name: stm32_ep0out_ctrlsetup + * + * Description: + * Setup to receive a SETUP packet. + * + *******************************************************************************/ + +static void stm32_ep0out_ctrlsetup(FAR struct stm32_usbdev_s *priv) +{ + uint32_t regval; + + /* Setup the hardware to perform the SETUP transfer */ + + regval = (USB_SIZEOF_CTRLREQ * 3 << OTGFS_DOEPTSIZ0_XFRSIZ_SHIFT) | + (OTGFS_DOEPTSIZ0_PKTCNT) | + (3 << OTGFS_DOEPTSIZ0_STUPCNT_SHIFT); + stm32_putreg(regval, STM32_OTGFS_DOEPTSIZ0); + + /* Then clear NAKing and enable the transfer */ + + regval = stm32_getreg(STM32_OTGFS_DOEPCTL0); + regval |= (OTGFS_DOEPCTL0_CNAK | OTGFS_DOEPCTL0_EPENA); + stm32_putreg(regval, STM32_OTGFS_DOEPCTL0); +} + +/**************************************************************************** + * Name: stm32_txfifo_write + * + * Description: + * Send data to the endpoint's TxFIFO. + * + ****************************************************************************/ + +static void stm32_txfifo_write(FAR struct stm32_ep_s *privep, + FAR uint8_t *buf, int nbytes) +{ + uint32_t regaddr; + uint32_t regval; + int nwords; + int i; + + /* Convert the number of bytes to words */ + + nwords = (nbytes + 3) >> 2; + + /* Get the TxFIFO for this endpoint (same as the endpoint number) */ + + regaddr = STM32_OTGFS_DFIFO_DEP(privep->epphy); + + /* Then transfer each word to the TxFIFO */ + + for (i = 0; i < nwords; i++) + { + /* Read four bytes from the source buffer (to avoid unaligned accesses) + * and pack these into one 32-bit word (little endian). + */ + + regval = (uint32_t)*buf++; + regval |= ((uint32_t)*buf++) << 8; + regval |= ((uint32_t)*buf++) << 16; + regval |= ((uint32_t)*buf++) << 24; + + /* Then write the packed data to the TxFIFO */ + + stm32_putreg(regval, regaddr); + } +} + +/**************************************************************************** + * Name: stm32_epin_transfer + * + * Description: + * Start the Tx data transfer + * + ****************************************************************************/ + +static void stm32_epin_transfer(FAR struct stm32_ep_s *privep, + FAR uint8_t *buf, int nbytes) +{ + uint32_t pktcnt; + uint32_t regval; + + /* Read the DIEPSIZx register */ + + regval = stm32_getreg(STM32_OTGFS_DIEPTSIZ(privep->epphy)); + + /* Clear the XFRSIZ, PKTCNT, and MCNT field of the DIEPSIZx register */ + + regval &= ~(OTGFS_DIEPTSIZ_XFRSIZ_MASK | OTGFS_DIEPTSIZ_PKTCNT_MASK | + OTGFS_DIEPTSIZ_MCNT_MASK); + + /* Are we sending a zero length packet (ZLP) */ + + if (nbytes == 0) + { + /* Yes.. leave the transfer size at zero and set the packet count to 1 */ + + pktcnt = 1; + } + else + { + /* No.. Program the transfer size and packet count . First calculate: + * + * xfrsize = The total number of bytes to be sent. + * pktcnt = the number of packets (of maxpacket bytes) required to + * perform the transfer. + */ + + pktcnt = ((uint32_t)nbytes + (privep->ep.maxpacket - 1)) / privep->ep.maxpacket; + } + + /* Set the XFRSIZ and PKTCNT */ + + regval |= (pktcnt << OTGFS_DIEPTSIZ_PKTCNT_SHIFT); + regval |= ((uint32_t)nbytes << OTGFS_DIEPTSIZ_XFRSIZ_SHIFT); + + /* If this is an isconchronous endpoint, then set the multi-count field to + * the PKTCNT as well. + */ + + if (privep->eptype == USB_EP_ATTR_XFER_ISOC) + { + regval |= (pktcnt << OTGFS_DIEPTSIZ_MCNT_SHIFT); + } + + /* Save DIEPSIZx register value */ + + stm32_putreg(regval, STM32_OTGFS_DIEPTSIZ(privep->epphy)); + + /* Read the DIEPCTLx register */ + + regval = stm32_getreg(STM32_OTGFS_DIEPCTL(privep->epphy)); + + /* If this is an isochronous endpoint, then set the even/odd frame bit + * the DIEPCTLx register. + */ + + if (privep->eptype == USB_EP_ATTR_XFER_ISOC) + { + /* Check bit 0 of the frame number of the received SOF and set the + * even/odd frame to match. + */ + + uint32_t status = stm32_getreg(STM32_OTGFS_DSTS); + if ((status & OTGFS_DSTS_SOFFN0) == OTGFS_DSTS_SOFFN_EVEN) + { + regval |= OTGFS_DIEPCTL_SEVNFRM; + } + else + { + regval |= OTGFS_DIEPCTL_SODDFRM; + } + } + + /* EP enable, IN data in FIFO */ + + regval &= ~OTGFS_DIEPCTL_EPDIS; + regval |= (OTGFS_DIEPCTL_CNAK | OTGFS_DIEPCTL_EPENA); + stm32_putreg(regval, STM32_OTGFS_DIEPCTL(privep->epphy)); + + /* Transfer the data to the TxFIFO. At this point, the caller has already + * assured that there is sufficient space in the TxFIFO to hold the transfer + * we can just blindly continue. + */ + + stm32_txfifo_write(privep, buf, nbytes); +} + +/**************************************************************************** + * Name: stm32_epin_request + * + * Description: + * Begin or continue write request processing. + * + ****************************************************************************/ + +static void stm32_epin_request(FAR struct stm32_usbdev_s *priv, + FAR struct stm32_ep_s *privep) +{ + struct stm32_req_s *privreq; + uint32_t regaddr; + uint32_t regval; +#ifdef ENABLE_DTXFSTS_POLLHACK + int32_t timeout; +#endif + uint8_t *buf; + int nbytes; + int nwords; + int bytesleft; + + /* We get here in one of four possible ways. From three interrupting + * events: + * + * 1. From stm32_epin as part of the transfer complete interrupt processing + * This interrupt indicates that the last transfer has completed. + * 2. As part of the ITTXFE interrupt processing. That interrupt indicates + * that an IN token was received when the associated TxFIFO was empty. + * 3. From stm32_epin_txfifoempty as part of the TXFE interrupt processing. + * The TXFE interrupt is only enabled when the TxFIFO is full and the + * software must wait for space to become available in the TxFIFO. + * + * And this function may be called immediately when the write request is + * queue to start up the next transaction. + * + * 4. From stm32_ep_submit when a new write request is received WHILE the + * endpoint is not active (privep->active == false). + */ + + /* Check the request from the head of the endpoint request queue */ + + privreq = stm32_rqpeek(privep); + if (!privreq) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPINQEMPTY), privep->epphy); + + /* There is no TX transfer in progress and no new pending TX + * requests to send. To stop transmitting any data on a particular + * IN endpoint, the application must set the IN NAK bit. To set this + * bit, the following field must be programmed. + */ + + regaddr = STM32_OTGFS_DIEPCTL(privep->epphy); + regval = stm32_getreg(regaddr); + regval |= OTGFS_DIEPCTL_SNAK; + stm32_putreg(regval, regaddr); + + /* The endpoint is no longer active */ + + privep->active = false; + return; + } + + ullvdbg("EP%d req=%p: len=%d xfrd=%d zlp=%d\n", + privep->epphy, privreq, privreq->req.len, + privreq->req.xfrd, privep->zlp); + + /* Check for a special case: If we are just starting a request (xfrd==0) and + * the class driver is trying to send a zero-length packet (len==0). Then set + * the ZLP flag so that the packet will be sent. + */ + + if (privreq->req.len == 0) + { + /* The ZLP flag is set TRUE whenever we want to force the driver to + * send a zero-length-packet on the next pass through the loop (below). + * The flag is cleared whenever a packet is sent in the loop below. + */ + + privep->zlp = true; + } + + /* Loop while there are still bytes to be transferred (or a zero-length- + * packet, ZLP, to be sent). The loop will also be terminated if there + * is insufficient space remaining in the TxFIFO to send a complete + * packet. + */ + + while (privreq->req.xfrd < privreq->req.len || privep->zlp) + { + /* Get the number of bytes left to be sent in the request */ + + bytesleft = privreq->req.len - privreq->req.xfrd; + nbytes = bytesleft; + + /* Assume no zero-length-packet on the next pass through this loop */ + + privep->zlp = false; + + /* Limit the size of the transfer to one full packet and handle + * zero-length packets (ZLPs). + */ + + if (nbytes > 0) + { + /* Either send the maxpacketsize or all of the remaining data in + * the request. + */ + + if (nbytes >= privep->ep.maxpacket) + { + nbytes = privep->ep.maxpacket; + + /* Handle the case where this packet is exactly the + * maxpacketsize. Do we need to send a zero-length packet + * in this case? + */ + + if (bytesleft == privep->ep.maxpacket && + (privreq->req.flags & USBDEV_REQFLAGS_NULLPKT) != 0) + { + /* The ZLP flag is set TRUE whenever we want to force + * the driver to send a zero-length-packet on the next + * pass through this loop. The flag is cleared (above) + * whenever we are committed to sending any packet and + * set here when we want to force one more pass through + * the loop. + */ + + privep->zlp = true; + } + } + } + + /* Get the transfer size in 32-bit words */ + + nwords = (nbytes + 3) >> 2; + + /* Get the number of 32-bit words available in the TxFIFO. The + * DXTFSTS indicates the amount of free space available in the + * endpoint TxFIFO. Values are in terms of 32-bit words: + * + * 0: Endpoint TxFIFO is full + * 1: 1 word available + * 2: 2 words available + * n: n words available + */ + + regaddr = STM32_OTGFS_DTXFSTS(privep->epphy); + +#ifdef ENABLE_DTXFSTS_POLLHACK + /* If ENABLE_DTXFSTS_POLLHACK is enabled , then poll DTXFSTS until + * space in the TxFIFO is available. If it doesn't become available, + * in a reasonable amount of time, then just pretend that it is. + */ + + for (timeout = 250000; timeout > 0; timeout--) + { + regval = stm32_getreg(regaddr); + if ((regval & OTGFS_DTXFSTS_MASK) >= nwords) + { + break; + } + } +#else + /* If ENABLE_DTXFSTS_POLLHACK is not enabled, then check once for + * space in the TxFIFO. If space in the TxFIFO is not available, + * then set up an interrupt to resume the transfer when the TxFIFO + * is empty. + */ + + regval = stm32_getreg(regaddr); + if ((regval & OTGFS_DTXFSTS_MASK) < nwords) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_EMPWAIT), (uint16_t)regval); + + /* There is insufficent space in the TxFIFO. Wait for a TxFIFO + * empty interrupt and try again. + */ + + uint32_t empmsk = stm32_getreg(STM32_OTGFS_DIEPEMPMSK); + empmsk |= OTGFS_DIEPEMPMSK(privep->epphy); + stm32_putreg(empmsk, STM32_OTGFS_DIEPEMPMSK); + + /* Terminate the transfer loop */ + + break; + } +#endif + + /* Transfer data to the TxFIFO */ + + buf = privreq->req.buf + privreq->req.xfrd; + stm32_epin_transfer(privep, buf, nbytes); + + /* If it was not before, the OUT endpoint is now actively transferring + * data. + */ + + privep->active = true; + + /* EP0 is a special case */ + + if (privep->epphy == EP0) + { + priv->ep0state = EP0STATE_DATA_IN; + } + + /* Update for the next time through the loop */ + + privreq->req.xfrd += nbytes; + } + + /* Note that the ZLP, if any, must be sent as a separate transfer. The need + * for a ZLP is indicated by privep->zlp. If all of the bytes were sent + * (including any final null packet) then we are finished with the transfer + */ + + if (privreq->req.xfrd >= privreq->req.len && !privep->zlp) + { + usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd); + stm32_req_complete(privep, OK); + + /* The endpoint is no longer transferring data */ + + privep->active = false; + } +} + +/******************************************************************************* + * Name: stm32_rxfifo_read + * + * Description: + * Read packet from the RxFIFO into a read request. + * + *******************************************************************************/ + +static void stm32_rxfifo_read(FAR struct stm32_ep_s *privep, + FAR uint8_t *dest, uint16_t len) +{ + uint32_t regaddr; + int i; + + /* Get the address of the RxFIFO. Note: there is only one RxFIFO so + * we might as well use the addess associated with EP0. + */ + + regaddr = STM32_OTGFS_DFIFO_DEP(EP0); + + /* Read 32-bits and write 4 x 8-bits at time (to avoid unaligned accesses) */ + + for (i = 0; i < len; i += 4) + { + union + { + uint32_t w; + uint8_t b[4]; + } data; + + /* Read 1 x 32-bits of EP0 packet data */ + + data.w = stm32_getreg(regaddr); + + /* Write 4 x 8-bits of EP0 packet data */ + + *dest++ = data.b[0]; + *dest++ = data.b[1]; + *dest++ = data.b[2]; + *dest++ = data.b[3]; + } +} + +/******************************************************************************* + * Name: stm32_rxfifo_discard + * + * Description: + * Discard packet data from the RxFIFO. + * + *******************************************************************************/ + +static void stm32_rxfifo_discard(FAR struct stm32_ep_s *privep, int len) +{ + if (len > 0) + { + uint32_t regaddr; + int i; + + /* Get the address of the RxFIFO Note: there is only one RxFIFO so + * we might as well use the addess associated with EP0. + */ + + regaddr = STM32_OTGFS_DFIFO_DEP(EP0); + + /* Read 32-bits at time */ + + for (i = 0; i < len; i += 4) + { + volatile uint32_t data = stm32_getreg(regaddr); + (void)data; + } + } +} + +/******************************************************************************* + * Name: stm32_epout_complete + * + * Description: + * This function is called when an OUT transfer complete interrupt is + * received. It completes the read request at the head of the endpoint's + * request queue. + * + *******************************************************************************/ + +static void stm32_epout_complete(FAR struct stm32_usbdev_s *priv, + FAR struct stm32_ep_s *privep) +{ + struct stm32_req_s *privreq; + + /* Since a transfer just completed, there must be a read request at the head of + * the endpoint request queue. + */ + + privreq = stm32_rqpeek(privep); + DEBUGASSERT(privreq); + + if (!privreq) + { + /* An OUT transfer completed, but no packet to receive the data. This + * should not happen. + */ + + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPOUTQEMPTY), privep->epphy); + privep->active = false; + return; + } + + ullvdbg("EP%d: len=%d xfrd=%d\n", + privep->epphy, privreq->req.len, privreq->req.xfrd); + + /* Return the completed read request to the class driver and mark the state + * IDLE. + */ + + usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd); + stm32_req_complete(privep, OK); + privep->active = false; + + /* Now set up the next read request (if any) */ + + stm32_epout_request(priv, privep); +} + +/******************************************************************************* + * Name: stm32_ep0out_receive + * + * Description: + * This function is called from the RXFLVL interrupt handler when new incoming + * data is available in the endpoint's RxFIFO. This function will simply + * copy the incoming data into pending request's data buffer. + * + *******************************************************************************/ + +static inline void stm32_ep0out_receive(FAR struct stm32_ep_s *privep, int bcnt) +{ + FAR struct stm32_usbdev_s *priv; + + /* Sanity Checking */ + + DEBUGASSERT(privep && privep->ep.priv); + priv = (FAR struct stm32_usbdev_s *)privep->ep.priv; + DEBUGASSERT(priv->ep0state == EP0STATE_SETUP_OUT); + + ullvdbg("EP0: bcnt=%d\n", bcnt); + usbtrace(TRACE_READ(EP0), bcnt); + + /* Verify that an OUT SETUP request as received before this data was + * received in the RxFIFO. + */ + + if (priv->ep0state == EP0STATE_SETUP_OUT) + { + /* Read the data into our special buffer for SETUP data */ + + int readlen = MIN(CONFIG_USBDEV_SETUP_MAXDATASIZE, bcnt); + stm32_rxfifo_read(privep, priv->ep0data, readlen); + + /* Do we have to discard any excess bytes? */ + + stm32_rxfifo_discard(privep, bcnt - readlen); + + /* Now we can process the setup command */ + + privep->active = false; + priv->ep0state = EP0STATE_SETUP_READY; + priv->ep0datlen = readlen; + + stm32_ep0out_setup(priv); + } + else + { + /* This is an error. We don't have any idea what to do with the EP0 + * data in this case. Just read and discard it so that the RxFIFO + * does not become constipated. + */ + + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_NOOUTSETUP), priv->ep0state); + stm32_rxfifo_discard(privep, bcnt); + privep->active = false; + } +} + +/******************************************************************************* + * Name: stm32_epout_receive + * + * Description: + * This function is called from the RXFLVL interrupt handler when new incoming + * data is available in the endpoint's RxFIFO. This function will simply + * copy the incoming data into pending request's data buffer. + * + *******************************************************************************/ + +static inline void stm32_epout_receive(FAR struct stm32_ep_s *privep, int bcnt) +{ + struct stm32_req_s *privreq; + uint8_t *dest; + int buflen; + int readlen; + + /* Get a reference to the request at the head of the endpoint's request + * queue. + */ + + privreq = stm32_rqpeek(privep); + if (!privreq) + { + /* Incoming data is available in the RxFIFO, but there is no read setup + * to receive the receive the data. This should not happen for data + * endpoints; those endpoints should have been NAKing any OUT data tokens. + * + * We should get here normally on OUT data phase following an OUT + * SETUP command. EP0 data will still receive data in this case and it + * should not be NAKing. + */ + + if (privep->epphy == 0) + { + stm32_ep0out_receive(privep, bcnt); + } + else + { + /* Otherwise, the data is lost. This really should not happen if + * NAKing is working as expected. + */ + + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPOUTQEMPTY), privep->epphy); + + /* Discard the data in the RxFIFO */ + + stm32_rxfifo_discard(privep, bcnt); + } + + privep->active = false; + return; + } + + ullvdbg("EP%d: len=%d xfrd=%d\n", privep->epphy, privreq->req.len, privreq->req.xfrd); + usbtrace(TRACE_READ(privep->epphy), bcnt); + + /* Get the number of bytes to transfer from the RxFIFO */ + + buflen = privreq->req.len - privreq->req.xfrd; + DEBUGASSERT(buflen > 0 && buflen >= bcnt); + readlen = MIN(buflen, bcnt); + + /* Get the destination of the data transfer */ + + dest = privreq->req.buf + privreq->req.xfrd; + + /* Transfer the data from the RxFIFO to the request's data buffer */ + + stm32_rxfifo_read(privep, dest, readlen); + + /* If there were more bytes in the RxFIFO than could be held in the read + * request, then we will have to discard those. + */ + + stm32_rxfifo_discard(privep, bcnt - readlen); + + /* Update the number of bytes transferred */ + + privreq->req.xfrd += readlen; +} + +/******************************************************************************* + * Name: stm32_epout_request + * + * Description: + * This function is called when either (1) new read request is received, or + * (2) a pending receive request completes. If there is no read in pending, + * then this function will initiate the next OUT (read) operation. + * + *******************************************************************************/ + +static void stm32_epout_request(FAR struct stm32_usbdev_s *priv, + FAR struct stm32_ep_s *privep) +{ + struct stm32_req_s *privreq; + uint32_t regaddr; + uint32_t regval; + uint32_t xfrsize; + uint32_t pktcnt; + + /* Make sure that there is not already a pending request request. If there is, + * just return, leaving the newly received request in the request queue. + */ + + if (!privep->active) + { + /* Loop until a valid request is found (or the request queue is empty). + * The loop is only need to look at the request queue again is an invalid + * read request is encountered. + */ + + for (;;) + { + /* Get a reference to the request at the head of the endpoint's request queue */ + + privreq = stm32_rqpeek(privep); + if (!privreq) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPOUTQEMPTY), privep->epphy); + + /* There are no read requests to be setup. Configure the hardware to + * NAK any incoming packets. (This should already be the case. I + * think that the hardware will automatically NAK after a transfer is + * completed until SNAK is cleared). + */ + + regaddr = STM32_OTGFS_DOEPCTL(privep->epphy); + regval = stm32_getreg(regaddr); + regval |= OTGFS_DOEPCTL_SNAK; + stm32_putreg(regval, regaddr); + + /* This endpoint is no longer actively transferring */ + + privep->active = false; + return; + } + + ullvdbg("EP%d: len=%d\n", privep->epphy, privreq->req.len); + + /* Ignore any attempt to receive a zero length packet (this really + * should not happen. + */ + + if (privreq->req.len <= 0) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPOUTNULLPACKET), 0); + stm32_req_complete(privep, OK); + } + + /* Otherwise, we have a usable read request... break out of the loop */ + + else + { + break; + } + } + + /* Setup the pending read into the request buffer. First calculate: + * + * pktcnt = the number of packets (of maxpacket bytes) required to + * perform the transfer. + * xfrsize = The total number of bytes required (in units of + * maxpacket bytes). + */ + + pktcnt = (privreq->req.len + (privep->ep.maxpacket - 1)) / privep->ep.maxpacket; + xfrsize = pktcnt * privep->ep.maxpacket; + + /* Then setup the hardware to perform this transfer */ + + regaddr = STM32_OTGFS_DOEPTSIZ(privep->epphy); + regval = stm32_getreg(regaddr); + regval &= ~(OTGFS_DOEPTSIZ_XFRSIZ_MASK | OTGFS_DOEPTSIZ_PKTCNT_MASK); + regval |= (xfrsize << OTGFS_DOEPTSIZ_XFRSIZ_SHIFT); + regval |= (pktcnt << OTGFS_DOEPTSIZ_PKTCNT_SHIFT); + stm32_putreg(regval, regaddr); + + /* Then enable the transfer */ + + regaddr = STM32_OTGFS_DOEPCTL(privep->epphy); + regval = stm32_getreg(regaddr); + + /* When an isochronous transfer is enabled the Even/Odd frame bit must + * also be set appropriately. + */ + +#ifdef CONFIG_USBDEV_ISOCHRONOUS + if (privep->eptype == USB_EP_ATTR_XFER_ISOC) + { + if (privep->odd) + { + regval |= OTGFS_DOEPCTL_SODDFRM; + } + else + { + regval |= OTGFS_DOEPCTL_SEVNFRM; + } + } +#endif + + /* Clearing NAKing and enable the transfer. */ + + regval |= (OTGFS_DOEPCTL_CNAK | OTGFS_DOEPCTL_EPENA); + stm32_putreg(regval, regaddr); + + /* A transfer is now active on this endpoint */ + + privep->active = true; + + /* EP0 is a special case. We need to know when to switch back to + * normal SETUP processing. + */ + + if (privep->epphy == EP0) + { + priv->ep0state = EP0STATE_DATA_OUT; + } + } +} + +/******************************************************************************* + * Name: stm32_ep_flush + * + * Description: + * Flush any primed descriptors from this ep + * + *******************************************************************************/ + +static void stm32_ep_flush(struct stm32_ep_s *privep) +{ + if (privep->isin) + { + stm32_txfifo_flush(OTGFS_GRSTCTL_TXFNUM_D(privep->epphy)); + } + else + { + stm32_rxfifo_flush(); + } +} + +/******************************************************************************* + * Name: stm32_req_complete + * + * Description: + * Handle termination of the request at the head of the endpoint request queue. + * + *******************************************************************************/ + +static void stm32_req_complete(struct stm32_ep_s *privep, int16_t result) +{ + FAR struct stm32_req_s *privreq; + + /* Remove the request at the head of the request list */ + + privreq = stm32_req_remfirst(privep); + DEBUGASSERT(privreq != NULL); + + /* If endpoint 0, temporarily reflect the state of protocol stalled + * in the callback. + */ + + bool stalled = privep->stalled; + if (privep->epphy == EP0) + { + privep->stalled = privep->dev->stalled; + } + + /* Save the result in the request structure */ + + privreq->req.result = result; + + /* Callback to the request completion handler */ + + privreq->req.callback(&privep->ep, &privreq->req); + + /* Restore the stalled indication */ + + privep->stalled = stalled; +} + +/******************************************************************************* + * Name: stm32_req_cancel + * + * Description: + * Cancel all pending requests for an endpoint + * + *******************************************************************************/ + +static void stm32_req_cancel(struct stm32_ep_s *privep, int16_t status) +{ + if (!stm32_rqempty(privep)) + { + stm32_ep_flush(privep); + } + + while (!stm32_rqempty(privep)) + { + usbtrace(TRACE_COMPLETE(privep->epphy), + (stm32_rqpeek(privep))->req.xfrd); + stm32_req_complete(privep, status); + } +} + +/******************************************************************************* + * Name: stm32_ep_findbyaddr + * + * Description: + * Find the physical endpoint structure corresponding to a logic endpoint + * address + * + *******************************************************************************/ + +static struct stm32_ep_s *stm32_ep_findbyaddr(struct stm32_usbdev_s *priv, + uint16_t eplog) +{ + struct stm32_ep_s *privep; + uint8_t epphy = USB_EPNO(eplog); + + if (epphy >= STM32_NENDPOINTS) + { + return NULL; + } + + /* Is this an IN or an OUT endpoint? */ + + if (USB_ISEPIN(eplog)) + { + privep = &priv->epin[epphy]; + } + else + { + privep = &priv->epout[epphy]; + } + + /* Verify that the endpoint has been configured */ + + if (!privep->configured) + { + return NULL; + } + + /* Return endpoint reference */ + + DEBUGASSERT(privep->epphy == epphy); + return privep; +} + +/******************************************************************************* + * Name: stm32_req_dispatch + * + * Description: + * Provide unhandled setup actions to the class driver. This is logically part + * of the USB interrupt handler. + * + *******************************************************************************/ + +static int stm32_req_dispatch(struct stm32_usbdev_s *priv, + const struct usb_ctrlreq_s *ctrl) +{ + int ret = -EIO; + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_DISPATCH), 0); + if (priv->driver) + { + /* Forward to the control request to the class driver implementation */ + + ret = CLASS_SETUP(priv->driver, &priv->usbdev, ctrl, + priv->ep0data, priv->ep0datlen); + } + + if (ret < 0) + { + /* Stall on failure */ + + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DISPATCHSTALL), 0); + priv->stalled = true; + } + + return ret; +} + +/******************************************************************************* + * Name: stm32_usbreset + * + * Description: + * Reset Usb engine + * + *******************************************************************************/ + +static void stm32_usbreset(struct stm32_usbdev_s *priv) +{ + FAR struct stm32_ep_s *privep; + uint32_t regval; + int i; + + /* Clear the Remote Wake-up Signaling */ + + regval = stm32_getreg(STM32_OTGFS_DCTL); + regval &= ~OTGFS_DCTL_RWUSIG; + stm32_putreg(regval, STM32_OTGFS_DCTL); + + /* Flush the EP0 Tx FIFO */ + + stm32_txfifo_flush(OTGFS_GRSTCTL_TXFNUM_D(EP0)); + + /* Tell the class driver that we are disconnected. The class + * driver should then accept any new configurations. + */ + + if (priv->driver) + { + CLASS_DISCONNECT(priv->driver, &priv->usbdev); + } + priv->epavail = STM32_EP_AVAILABLE; + + /* Disable all end point interrupts */ + + for (i = 0; i < STM32_NENDPOINTS ; i++) + { + /* Disable endpoint interrupts */ + + stm32_putreg(0xff, STM32_OTGFS_DIEPINT(i)); + stm32_putreg(0xff, STM32_OTGFS_DOEPINT(i)); + + /* Return write requests to the class implementation */ + + privep = &priv->epin[i]; + stm32_req_cancel(privep, -ESHUTDOWN); + + /* Reset IN endpoint status */ + + privep->stalled = false; + + /* Return read requests to the class implementation */ + + privep = &priv->epout[i]; + stm32_req_cancel(privep, -ESHUTDOWN); + + /* Reset endpoint status */ + + privep->stalled = false; + } + + stm32_putreg(0xffffffff, STM32_OTGFS_DAINT); + + /* Mask all device endpoint interrupts except EP0 */ + + regval = (OTGFS_DAINT_IEP(EP0) | OTGFS_DAINT_OEP(EP0)); + stm32_putreg(regval, STM32_OTGFS_DAINTMSK); + + /* Unmask OUT interrupts */ + + regval = (OTGFS_DOEPMSK_XFRCM | OTGFS_DOEPMSK_STUPM | OTGFS_DOEPMSK_EPDM); + stm32_putreg(regval, STM32_OTGFS_DOEPMSK); + + /* Unmask IN interrupts */ + + regval = (OTGFS_DIEPMSK_XFRCM | OTGFS_DIEPMSK_EPDM | OTGFS_DIEPMSK_TOM); + stm32_putreg(regval, STM32_OTGFS_DIEPMSK); + + /* Reset device address to 0 */ + + stm32_setaddress(priv, 0); + priv->devstate = DEVSTATE_DEFAULT; + priv->usbdev.speed = USB_SPEED_FULL; + + /* Re-configure EP0 */ + + stm32_ep0_configure(priv); + + /* Setup EP0 to receive SETUP packets */ + + stm32_ep0out_ctrlsetup(priv); +} + +/******************************************************************************* + * Name: stm32_ep0out_testmode + * + * Description: + * Select test mode + * + *******************************************************************************/ + +static inline void stm32_ep0out_testmode(FAR struct stm32_usbdev_s *priv, + uint16_t index) +{ + uint32_t regval; + uint8_t testmode; + + regval = stm32_getreg(STM32_OTGFS_DCTL); + + testmode = index >> 8; + switch (testmode) + { + case 1: + priv->testmode = OTGFS_TESTMODE_J; + break; + + case 2: + priv->testmode = OTGFS_TESTMODE_K; + break; + + case 3: + priv->testmode = OTGFS_TESTMODE_SE0_NAK; + break; + + case 4: + priv->testmode = OTGFS_TESTMODE_PACKET; + break; + + case 5: + priv->testmode = OTGFS_TESTMODE_FORCE; + break; + + default: + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADTESTMODE), testmode); + priv->dotest = false; + priv->testmode = OTGFS_TESTMODE_DISABLED; + priv->stalled = true; + } + + priv->dotest = true; + stm32_ep0in_transmitzlp(priv); +} + +/******************************************************************************* + * Name: stm32_ep0out_stdrequest + * + * Description: + * Handle a stanard request on EP0. Pick off the things of interest to the + * USB device controller driver; pass what is left to the class driver. + * + *******************************************************************************/ + +static inline void stm32_ep0out_stdrequest(struct stm32_usbdev_s *priv, + FAR struct stm32_ctrlreq_s *ctrlreq) +{ + FAR struct stm32_ep_s *privep; + + /* Handle standard request */ + + switch (ctrlreq->req) + { + case USB_REQ_GETSTATUS: + { + /* type: device-to-host; recipient = device, interface, endpoint + * value: 0 + * index: zero interface endpoint + * len: 2; data = status + */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETSTATUS), 0); + if (!priv->addressed || + ctrlreq->len != 2 || + USB_REQ_ISOUT(ctrlreq->type) || + ctrlreq->value != 0) + { + priv->stalled = true; + } + else + { + switch (ctrlreq->type & USB_REQ_RECIPIENT_MASK) + { + case USB_REQ_RECIPIENT_ENDPOINT: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPGETSTATUS), 0); + privep = stm32_ep_findbyaddr(priv, ctrlreq->index); + if (!privep) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPGETSTATUS), 0); + priv->stalled = true; + } + else + { + if (privep->stalled) + { + priv->ep0data[0] = (1 << USB_FEATURE_ENDPOINTHALT); + } + else + { + priv->ep0data[0] = 0; /* Not stalled */ + } + + priv->ep0data[1] = 0; + stm32_ep0in_setupresponse(priv, priv->ep0data, 2); + } + } + break; + + case USB_REQ_RECIPIENT_DEVICE: + { + if (ctrlreq->index == 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_DEVGETSTATUS), 0); + + /* Features: Remote Wakeup and selfpowered */ + + priv->ep0data[0] = (priv->selfpowered << USB_FEATURE_SELFPOWERED); + priv->ep0data[0] |= (priv->wakeup << USB_FEATURE_REMOTEWAKEUP); + priv->ep0data[1] = 0; + + stm32_ep0in_setupresponse(priv, priv->ep0data, 2); + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADDEVGETSTATUS), 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_RECIPIENT_INTERFACE: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_IFGETSTATUS), 0); + priv->ep0data[0] = 0; + priv->ep0data[1] = 0; + + stm32_ep0in_setupresponse(priv, priv->ep0data, 2); + } + break; + + default: + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETSTATUS), 0); + priv->stalled = true; + } + break; + } + } + } + break; + + case USB_REQ_CLEARFEATURE: + { + /* type: host-to-device; recipient = device, interface or endpoint + * value: feature selector + * index: zero interface endpoint; + * len: zero, data = none + */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_CLEARFEATURE), 0); + if (priv->addressed != 0 && ctrlreq->len == 0) + { + uint8_t recipient = ctrlreq->type & USB_REQ_RECIPIENT_MASK; + if (recipient == USB_REQ_RECIPIENT_ENDPOINT && + ctrlreq->value == USB_FEATURE_ENDPOINTHALT && + (privep = stm32_ep_findbyaddr(priv, ctrlreq->index)) != NULL) + { + stm32_ep_clrstall(privep); + stm32_ep0in_transmitzlp(priv); + } + else if (recipient == USB_REQ_RECIPIENT_DEVICE && + ctrlreq->value == USB_FEATURE_REMOTEWAKEUP) + { + priv->wakeup = 0; + stm32_ep0in_transmitzlp(priv); + } + else + { + /* Actually, I think we could just stall here. */ + + (void)stm32_req_dispatch(priv, &priv->ctrlreq); + } + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADCLEARFEATURE), 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_SETFEATURE: + { + /* type: host-to-device; recipient = device, interface, endpoint + * value: feature selector + * index: zero interface endpoint; + * len: 0; data = none + */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETFEATURE), 0); + if (priv->addressed != 0 && ctrlreq->len == 0) + { + uint8_t recipient = ctrlreq->type & USB_REQ_RECIPIENT_MASK; + if (recipient == USB_REQ_RECIPIENT_ENDPOINT && + ctrlreq->value == USB_FEATURE_ENDPOINTHALT && + (privep = stm32_ep_findbyaddr(priv, ctrlreq->index)) != NULL) + { + stm32_ep_setstall(privep); + stm32_ep0in_transmitzlp(priv); + } + else if (recipient == USB_REQ_RECIPIENT_DEVICE && + ctrlreq->value == USB_FEATURE_REMOTEWAKEUP) + { + priv->wakeup = 1; + stm32_ep0in_transmitzlp(priv); + } + else if (recipient == USB_REQ_RECIPIENT_DEVICE && + ctrlreq->value == USB_FEATURE_TESTMODE && + ((ctrlreq->index & 0xff) == 0)) + { + stm32_ep0out_testmode(priv, ctrlreq->index); + } + else if (priv->configured) + { + /* Actually, I think we could just stall here. */ + + (void)stm32_req_dispatch(priv, &priv->ctrlreq); + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETFEATURE), 0); + priv->stalled = true; + } + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETFEATURE), 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_SETADDRESS: + { + /* type: host-to-device; recipient = device + * value: device address + * index: 0 + * len: 0; data = none + */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETADDRESS), ctrlreq->value); + if ((ctrlreq->type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE && + ctrlreq->index == 0 && + ctrlreq->len == 0 && + ctrlreq->value < 128 && + priv->devstate != DEVSTATE_CONFIGURED) + { + /* Save the address. We cannot actually change to the next address until + * the completion of the status phase. + */ + + stm32_setaddress(priv, (uint16_t)priv->ctrlreq.value[0]); + stm32_ep0in_transmitzlp(priv); + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETADDRESS), 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_GETDESCRIPTOR: + /* type: device-to-host; recipient = device + * value: descriptor type and index + * index: 0 or language ID; + * len: descriptor len; data = descriptor + */ + + case USB_REQ_SETDESCRIPTOR: + /* type: host-to-device; recipient = device + * value: descriptor type and index + * index: 0 or language ID; + * len: descriptor len; data = descriptor + */ + + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETSETDESC), 0); + if ((ctrlreq->type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE) + { + (void)stm32_req_dispatch(priv, &priv->ctrlreq); + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETSETDESC), 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_GETCONFIGURATION: + /* type: device-to-host; recipient = device + * value: 0; + * index: 0; + * len: 1; data = configuration value + */ + + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETCONFIG), 0); + if (priv->addressed && + (ctrlreq->type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE && + ctrlreq->value == 0 && + ctrlreq->index == 0 && + ctrlreq->len == 1) + { + (void)stm32_req_dispatch(priv, &priv->ctrlreq); + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETCONFIG), 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_SETCONFIGURATION: + /* type: host-to-device; recipient = device + * value: configuration value + * index: 0; + * len: 0; data = none + */ + + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETCONFIG), 0); + if (priv->addressed && + (ctrlreq->type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE && + ctrlreq->index == 0 && + ctrlreq->len == 0) + { + /* Give the configuration to the class driver */ + + int ret = stm32_req_dispatch(priv, &priv->ctrlreq); + + /* If the class driver accepted the configuration, then mark the + * device state as configured (or not, depending on the + * configuration). + */ + + if (ret == OK) + { + uint8_t cfg = (uint8_t)ctrlreq->value; + if (cfg != 0) + { + priv->devstate = DEVSTATE_CONFIGURED; + priv->configured = true; + } + else + { + priv->devstate = DEVSTATE_ADDRESSED; + priv->configured = false; + } + } + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETCONFIG), 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_GETINTERFACE: + /* type: device-to-host; recipient = interface + * value: 0 + * index: interface; + * len: 1; data = alt interface + */ + + case USB_REQ_SETINTERFACE: + /* type: host-to-device; recipient = interface + * value: alternate setting + * index: interface; + * len: 0; data = none + */ + + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETSETIF), 0); + (void)stm32_req_dispatch(priv, &priv->ctrlreq); + } + break; + + case USB_REQ_SYNCHFRAME: + /* type: device-to-host; recipient = endpoint + * value: 0 + * index: endpoint; + * len: 2; data = frame number + */ + + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SYNCHFRAME), 0); + } + break; + + default: + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDCTRLREQ), 0); + priv->stalled = true; + } + break; + } +} + +/******************************************************************************* + * Name: stm32_ep0out_setup + * + * Description: + * USB Ctrl EP Setup Event. This is logically part of the USB interrupt + * handler. This event occurs when a setup packet is receive on EP0 OUT. + * + *******************************************************************************/ + +static inline void stm32_ep0out_setup(struct stm32_usbdev_s *priv) +{ + struct stm32_ctrlreq_s ctrlreq; + + /* Verify that a SETUP was received */ + + if (priv->ep0state != EP0STATE_SETUP_READY) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0NOSETUP), priv->ep0state); + return; + } + + /* Terminate any pending requests */ + + stm32_req_cancel(&priv->epout[EP0], -EPROTO); + stm32_req_cancel(&priv->epin[EP0], -EPROTO); + + /* Assume NOT stalled */ + + priv->epout[EP0].stalled = false; + priv->epin[EP0].stalled = false; + priv->stalled = false; + + /* Starting to process a control request - update state */ + + priv->ep0state = EP0STATE_SETUP_PROCESS; + + /* And extract the little-endian 16-bit values to host order */ + + ctrlreq.type = priv->ctrlreq.type; + ctrlreq.req = priv->ctrlreq.req; + ctrlreq.value = GETUINT16(priv->ctrlreq.value); + ctrlreq.index = GETUINT16(priv->ctrlreq.index); + ctrlreq.len = GETUINT16(priv->ctrlreq.len); + + ullvdbg("type=%02x req=%02x value=%04x index=%04x len=%04x\n", + ctrlreq.type, ctrlreq.req, ctrlreq.value, ctrlreq.index, ctrlreq.len); + + /* Check for a standard request */ + + if ((ctrlreq.type & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) + { + /* Dispatch any non-standard requests */ + + (void)stm32_req_dispatch(priv, &priv->ctrlreq); + } + else + { + /* Handle standard requests. */ + + stm32_ep0out_stdrequest(priv, &ctrlreq); + } + + /* Check if the setup processing resulted in a STALL */ + + if (priv->stalled) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0SETUPSTALLED), priv->ep0state); + stm32_ep0_stall(priv); + } + + /* Reset state/data associated with thie SETUP request */ + + priv->ep0datlen = 0; +} + +/******************************************************************************* + * Name: stm32_epout + * + * Description: + * This is part of the OUT endpoint interrupt processing. This function + * handles the OUT event for a single endpoint. + * + *******************************************************************************/ + +static inline void stm32_epout(FAR struct stm32_usbdev_s *priv, uint8_t epno) +{ + FAR struct stm32_ep_s *privep; + + /* Endpoint 0 is a special case. */ + + if (epno == 0) + { + privep = &priv->epout[EP0]; + + /* In the EP0STATE_DATA_OUT state, we are receiving data into the + * request buffer. In that case, we must continue the request + * processing. + */ + + if (priv->ep0state == EP0STATE_DATA_OUT) + { + /* Continue processing data from the EP0 OUT request queue */ + + stm32_epout_complete(priv, privep); + } + + /* If we are not actively processing an OUT request, then we + * need to setup to receive the next control request. + */ + + if (!privep->active) + { + stm32_ep0out_ctrlsetup(priv); + priv->ep0state = EP0STATE_IDLE; + } + } + + /* For other endpoints, the only possibility is that we are continuing + * or finishing an OUT request. + */ + + else if (priv->devstate == DEVSTATE_CONFIGURED) + { + stm32_epout_complete(priv, &priv->epout[epno]); + } +} + +/******************************************************************************* + * Name: stm32_epout_interrupt + * + * Description: + * USB OUT endpoint interrupt handler. The core generates this interrupt when + * there is an interrupt is pending on one of the OUT endpoints of the core. + * The driver must read the OTGFS DAINT register to determine the exact number + * of the OUT endpoint on which the interrupt occurred, and then read the + * corresponding OTGFS DOEPINTx register to determine the exact cause of the + * interrupt. + * + *******************************************************************************/ + +static inline void stm32_epout_interrupt(FAR struct stm32_usbdev_s *priv) +{ + uint32_t daint; + uint32_t regval; + uint32_t doepint; + int epno; + + /* Get the pending, enabled interrupts for the OUT endpoint from the endpoint + * interrupt status register. + */ + + regval = stm32_getreg(STM32_OTGFS_DAINT); + regval &= stm32_getreg(STM32_OTGFS_DAINTMSK); + daint = (regval & OTGFS_DAINT_OEP_MASK) >> OTGFS_DAINT_OEP_SHIFT; + + /* Process each pending IN endpoint interrupt */ + + epno = 0; + while (daint) + { + /* Is an OUT interrupt pending for this endpoint? */ + + if ((daint & 1) != 0) + { + /* Yes.. get the OUT endpoint interrupt status */ + + doepint = stm32_getreg(STM32_OTGFS_DOEPINT(epno)); + doepint &= stm32_getreg(STM32_OTGFS_DOEPMSK); + + /* Transfer completed interrupt. This interrupt is trigged when + * stm32_rxinterrupt() removes the last packet data from the RxFIFO. + * In this case, core internally sets the NAK bit for this endpoint to + * prevent it from receiving any more packets. + */ + + if ((doepint & OTGFS_DOEPINT_XFRC) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUT_XFRC), (uint16_t)doepint); + + /* Clear the bit in DOEPINTn for this interrupt */ + + stm32_putreg(OTGFS_DOEPINT_XFRC, STM32_OTGFS_DOEPINT(epno)); + + /* Handle the RX transfer data ready event */ + + stm32_epout(priv, epno); + } + + /* Endpoint disabled interrupt (ignored because this interrrupt is + * used in polled mode by the endpoint disable logic). + */ +#if 1 + /* REVISIT: */ + if ((doepint & OTGFS_DOEPINT_EPDISD) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUT_EPDISD), (uint16_t)doepint); + + /* Clear the bit in DOEPINTn for this interrupt */ + + stm32_putreg(OTGFS_DOEPINT_EPDISD, STM32_OTGFS_DOEPINT(epno)); + } +#endif + /* Setup Phase Done (control EPs) */ + + if ((doepint & OTGFS_DOEPINT_SETUP) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUT_SETUP), priv->ep0state); + + /* Handle the receipt of the IN SETUP packets now (OUT setup + * packet processing may be delayed until the accompanying + * OUT DATA is received) + */ + + if (priv->ep0state == EP0STATE_SETUP_READY) + { + stm32_ep0out_setup(priv); + } + stm32_putreg(OTGFS_DOEPINT_SETUP, STM32_OTGFS_DOEPINT(epno)); + } + } + + epno++; + daint >>= 1; + } +} + +/******************************************************************************* + * Name: stm32_epin_runtestmode + * + * Description: + * Execute the test mode setup by the SET FEATURE request + * + *******************************************************************************/ + +static inline void stm32_epin_runtestmode(FAR struct stm32_usbdev_s *priv) +{ + uint32_t regval = stm32_getreg(STM32_OTGFS_DCTL); + regval &= OTGFS_DCTL_TCTL_MASK; + regval |= (uint32_t)priv->testmode << OTGFS_DCTL_TCTL_SHIFT; + stm32_putreg(regval , STM32_OTGFS_DCTL); + + priv->dotest = 0; + priv->testmode = OTGFS_TESTMODE_DISABLED; +} + +/******************************************************************************* + * Name: stm32_epin + * + * Description: + * This is part of the IN endpoint interrupt processing. This function + * handles the IN event for a single endpoint. + * + *******************************************************************************/ + +static inline void stm32_epin(FAR struct stm32_usbdev_s *priv, uint8_t epno) +{ + FAR struct stm32_ep_s *privep = &priv->epin[epno]; + + /* Endpoint 0 is a special case. */ + + if (epno == 0) + { + /* In the EP0STATE_DATA_IN state, we are sending data from request + * buffer. In that case, we must continue the request processing. + */ + + if (priv->ep0state == EP0STATE_DATA_IN) + { + /* Continue processing data from the EP0 OUT request queue */ + + stm32_epin_request(priv, privep); + } + + /* If we are not actively processing an OUT request, then we + * need to setup to receive the next control request. + */ + + if (!privep->active) + { + stm32_ep0out_ctrlsetup(priv); + priv->ep0state = EP0STATE_IDLE; + } + + /* Test mode is another special case */ + + if (priv->dotest) + { + stm32_epin_runtestmode(priv); + } + } + + /* For other endpoints, the only possibility is that we are continuing + * or finishing an IN request. + */ + + else if (priv->devstate == DEVSTATE_CONFIGURED) + { + /* Continue processing data from the endpoint write request queue */ + + stm32_epin_request(priv, privep); + } +} + +/**************************************************************************** + * Name: stm32_epin_txfifoempty + * + * Description: + * TxFIFO empty interrupt handling + * + ****************************************************************************/ + +static inline void stm32_epin_txfifoempty(FAR struct stm32_usbdev_s *priv, int epno) +{ + FAR struct stm32_ep_s *privep = &priv->epin[epno]; + + /* Continue processing the write request queue. This may mean sending + * more dat from the exisiting request or terminating the current requests + * and (perhaps) starting the IN transfer from the next write request. + */ + + stm32_epin_request(priv, privep); +} + +/******************************************************************************* + * Name: stm32_epin_interrupt + * + * Description: + * USB IN endpoint interrupt handler. The core generates this interrupt when + * an interrupt is pending on one of the IN endpoints of the core. The driver + * must read the OTGFS DAINT register to determine the exact number of the IN + * endpoint on which the interrupt occurred, and then read the corresponding + * OTGFS DIEPINTx register to determine the exact cause of the interrupt. + * + *******************************************************************************/ + +static inline void stm32_epin_interrupt(FAR struct stm32_usbdev_s *priv) +{ + uint32_t diepint; + uint32_t daint; + uint32_t mask; + uint32_t empty; + int epno; + + /* Get the pending, enabled interrupts for the IN endpoint from the endpoint + * interrupt status register. + */ + + daint = stm32_getreg(STM32_OTGFS_DAINT); + daint &= stm32_getreg(STM32_OTGFS_DAINTMSK); + daint &= OTGFS_DAINT_IEP_MASK; + + /* Process each pending IN endpoint interrupt */ + + epno = 0; + while (daint) + { + /* Is an IN interrupt pending for this endpoint? */ + + if ((daint & 1) != 0) + { + /* Get IN interrupt mask register. Bits 0-6 correspond to enabled + * interrupts as will be found in the DIEPINT interrupt status + * register. + */ + + mask = stm32_getreg(STM32_OTGFS_DIEPMSK); + + /* Check for FIFO not empty. Bits n corresponds to endpoint n. + * That condition corresponds to bit 7 of the DIEPINT interrupt + * status register. + */ + + empty = stm32_getreg(STM32_OTGFS_DIEPEMPMSK); + if ((empty & OTGFS_DIEPEMPMSK(epno)) != 0) + { + mask |= OTGFS_DIEPINT_TXFE; + } + + /* Now, read the interrupt status and mask out all disabled + * interrupts. + */ + + diepint = stm32_getreg(STM32_OTGFS_DIEPINT(epno)) & mask; + + /* Decode and process the enabled, pending interrupts */ + /* Transfer completed interrupt */ + + if ((diepint & OTGFS_DIEPINT_XFRC) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_XFRC), (uint16_t)diepint); + + /* It is possible that logic may be waiting for a the TxFIFO to become + * empty. We disable the TxFIFO empty interrupt here; it will be + * re-enabled if there is still insufficient space in the TxFIFO. + */ + + empty &= ~OTGFS_DIEPEMPMSK(epno); + stm32_putreg(empty, STM32_OTGFS_DIEPEMPMSK); + stm32_putreg(OTGFS_DIEPINT_XFRC, STM32_OTGFS_DIEPINT(epno)); + + /* IN transfer complete */ + + stm32_epin(priv, epno); + } + + /* Timeout condition */ + + if ((diepint & OTGFS_DIEPINT_TOC) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_TOC), (uint16_t)diepint); + stm32_putreg(OTGFS_DIEPINT_TOC, STM32_OTGFS_DIEPINT(epno)); + } + + /* IN token received when TxFIFO is empty. Applies to non-periodic IN + * endpoints only. This interrupt indicates that an IN token was received + * when the associated TxFIFO (periodic/non-periodic) was empty. This + * interrupt is asserted on the endpoint for which the IN token was + * received. + */ + + if ((diepint & OTGFS_DIEPINT_ITTXFE) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_ITTXFE), (uint16_t)diepint); + stm32_epin_request(priv, &priv->epin[epno]); + stm32_putreg(OTGFS_DIEPINT_ITTXFE, STM32_OTGFS_DIEPINT(epno)); + } + + /* IN endpoint NAK effective (ignored as this used only in polled + * mode) + */ +#if 0 + if ((diepint & OTGFS_DIEPINT_INEPNE) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_INEPNE), (uint16_t)diepint); + stm32_putreg(OTGFS_DIEPINT_INEPNE, STM32_OTGFS_DIEPINT(epno)); + } +#endif + /* Endpoint disabled interrupt (ignored as this used only in polled + * mode) + */ +#if 0 + if ((diepint & OTGFS_DIEPINT_EPDISD) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_EPDISD), (uint16_t)diepint); + stm32_putreg(OTGFS_DIEPINT_EPDISD, STM32_OTGFS_DIEPINT(epno)); + } +#endif + /* Transmit FIFO empty */ + + if ((diepint & OTGFS_DIEPINT_TXFE) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_TXFE), (uint16_t)diepint); + + /* If we were waiting for TxFIFO to become empty, the we might have both + * XFRC and TXFE interrups pending. Since we do the same thing for both + * cases, ignore the TXFE if we have already processed the XFRC. + */ + + if ((diepint & OTGFS_DIEPINT_XFRC) == 0) + { + /* Mask further FIFO empty interrupts. This will be re-enabled + * whenever we need to wait for a FIFO event. + */ + + empty &= ~OTGFS_DIEPEMPMSK(epno); + stm32_putreg(empty, STM32_OTGFS_DIEPEMPMSK); + + /* Handle TxFIFO empty */ + + stm32_epin_txfifoempty(priv, epno); + } + + /* Clear the pending TxFIFO empty interrupt */ + + stm32_putreg(OTGFS_DIEPINT_TXFE, STM32_OTGFS_DIEPINT(epno)); + } + } + + epno++; + daint >>= 1; + } +} + +/******************************************************************************* + * Name: stm32_resumeinterrupt + * + * Description: + * Resume/remote wakeup detected interrupt + * + *******************************************************************************/ + +static inline void stm32_resumeinterrupt(FAR struct stm32_usbdev_s *priv) +{ + uint32_t regval; + + /* Restart the PHY clock and un-gate USB core clock (HCLK) */ + +#ifdef CONFIG_USBDEV_LOWPOWER + regval = stm32_getreg(STM32_OTGFS_PCGCCTL); + regval &= ~(OTGFS_PCGCCTL_STPPCLK | OTGFS_PCGCCTL_GATEHCLK); + stm32_putreg(regval, STM32_OTGFS_PCGCCTL); +#endif + + /* Clear remote wake-up signaling */ + + regval = stm32_getreg(STM32_OTGFS_DCTL); + regval &= ~OTGFS_DCTL_RWUSIG; + stm32_putreg(regval, STM32_OTGFS_DCTL); + + /* Restore full power -- whatever that means for this particular board */ + + stm32_usbsuspend((struct usbdev_s *)priv, true); +} + +/******************************************************************************* + * Name: stm32_suspendinterrupt + * + * Description: + * USB suspend interrupt + * + *******************************************************************************/ + +static inline void stm32_suspendinterrupt(FAR struct stm32_usbdev_s *priv) +{ +#ifdef CONFIG_USBDEV_LOWPOWER + uint32_t regval; + + /* OTGFS_DSTS_SUSPSTS is set as long as the suspend condition is detected + * on USB. Check if we are still have the suspend condition, that we are + * connected to the host, and that we have been configured. + */ + + regval = stm32_getreg(STM32_OTGFS_DSTS); + + if ((regval & OTGFS_DSTS_SUSPSTS) != 0 && + priv->connected && + devstate == DEVSTATE_CONFIGURED) + { + /* Switch off OTG FS clocking. Setting OTGFS_PCGCCTL_STPPCLK stops the + * PHY clock. + */ + + regval = stm32_getreg(STM32_OTGFS_PCGCCTL); + regval |= OTGFS_PCGCCTL_STPPCLK; + stm32_putreg(regval, STM32_OTGFS_PCGCCTL); + + /* Setting OTGFS_PCGCCTL_GATEHCLK gate HCLK to modules other than + * the AHB Slave and Master and wakeup logic. + */ + + regval |= OTGFS_PCGCCTL_GATEHCLK; + stm32_putreg(regval, STM32_OTGFS_PCGCCTL); + } +#endif + + /* Let the board-specific logic know that we have entered the suspend + * state + */ + + stm32_usbsuspend((FAR struct usbdev_s *)priv, false); +} + +/******************************************************************************* + * Name: stm32_rxinterrupt + * + * Description: + * RxFIFO non-empty interrupt. This interrupt indicates that there is at + * least one packet pending to be read from the RxFIFO. + * + *******************************************************************************/ + +static inline void stm32_rxinterrupt(FAR struct stm32_usbdev_s *priv) +{ + FAR struct stm32_ep_s *privep; + uint32_t regval; + int bcnt; + int epphy; + + /* Disable the Rx status queue level interrupt */ + + regval = stm32_getreg(STM32_OTGFS_GINTMSK); + regval &= ~OTGFS_GINT_RXFLVL; + stm32_putreg(regval, STM32_OTGFS_GINTMSK); + + /* Get the status from the top of the FIFO */ + + regval = stm32_getreg(STM32_OTGFS_GRXSTSP); + + /* Decode status fields */ + + epphy = (regval & OTGFS_GRXSTSD_EPNUM_MASK) >> OTGFS_GRXSTSD_EPNUM_SHIFT; + privep = &priv->epout[epphy]; + + /* Handle the RX event according to the packet status field */ + + switch (regval & OTGFS_GRXSTSD_PKTSTS_MASK) + { + /* Global OUT NAK. This indicate that the global OUT NAK bit has taken + * effect. + * + * PKTSTS = Global OUT NAK, BCNT = 0, EPNUM = Don't Care, DPID = Don't + * Care. + */ + + case OTGFS_GRXSTSD_PKTSTS_OUTNAK: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTNAK), 0); + } + break; + + /* OUT data packet received. + * + * PKTSTS = DataOUT, BCNT = size of the received data OUT packet, + * EPNUM = EPNUM on which the packet was received, DPID = Actual Data PID. + */ + + case OTGFS_GRXSTSD_PKTSTS_OUTRECVD: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTRECVD), epphy); + bcnt = (regval & OTGFS_GRXSTSD_BCNT_MASK) >> OTGFS_GRXSTSD_BCNT_SHIFT; + if (bcnt > 0) + { + stm32_epout_receive(privep, bcnt); + } + } + break; + + /* OUT transfer completed. This indicates that an OUT data transfer for + * the specified OUT endpoint has completed. After this entry is popped + * from the receive FIFO, the core asserts a Transfer Completed interrupt + * on the specified OUT endpoint. + * + * PKTSTS = Data OUT Transfer Done, BCNT = 0, EPNUM = OUT EP Num on + * which the data transfer is complete, DPID = Don't Care. + */ + + case OTGFS_GRXSTSD_PKTSTS_OUTDONE: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTDONE), epphy); + } + break; + + /* SETUP transaction completed. This indicates that the Setup stage for + * the specified endpoint has completed and the Data stage has started. + * After this entry is popped from the receive FIFO, the core asserts a + * Setup interrupt on the specified control OUT endpoint (triggers an + * interrupt). + * + * PKTSTS = Setup Stage Done, BCNT = 0, EPNUM = Control EP Num, + * DPID = Don't Care. + */ + + case OTGFS_GRXSTSD_PKTSTS_SETUPDONE: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPDONE), epphy); + } + break; + + /* SETUP data packet received. This indicates that a SETUP packet for the + * specified endpoint is now available for reading from the receive FIFO. + * + * PKTSTS = SETUP, BCNT = 8, EPNUM = Control EP Num, DPID = D0. + */ + + case OTGFS_GRXSTSD_PKTSTS_SETUPRECVD: + { + uint16_t datlen; + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPRECVD), epphy); + + /* Read EP0 setup data. NOTE: If multiple SETUP packets are received, + * the last one overwrites the previous setup packets and only that + * last SETUP packet will be processed. + */ + + stm32_rxfifo_read(&priv->epout[EP0], (FAR uint8_t*)&priv->ctrlreq, + USB_SIZEOF_CTRLREQ); + + /* Was this an IN or an OUT SETUP packet. If it is an OUT SETUP, + * then we need to wait for the completion of the data phase to + * process the setup command. If it is an IN SETUP packet, then + * we must processing the command BEFORE we enter the DATA phase. + * + * If the data associated with the OUT SETUP packet is zero length, + * then, of course, we don't need to wait. + */ + + datlen = GETUINT16(priv->ctrlreq.len); + if (USB_REQ_ISOUT(priv->ctrlreq.type) && datlen > 0) + { + /* Wait for the data phase. */ + + priv->ep0state = EP0STATE_SETUP_OUT; + } + else + { + /* We can process the setup data as soon as SETUP done word is + * popped of the RxFIFO. + */ + + priv->ep0state = EP0STATE_SETUP_READY; + } + } + break; + + default: + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), + (regval & OTGFS_GRXSTSD_PKTSTS_MASK) >> OTGFS_GRXSTSD_PKTSTS_SHIFT); + } + break; + } + + /* Enable the Rx Status Queue Level interrupt */ + + regval = stm32_getreg(STM32_OTGFS_GINTMSK); + regval |= OTGFS_GINT_RXFLVL; + stm32_putreg(regval, STM32_OTGFS_GINTMSK); +} + +/******************************************************************************* + * Name: stm32_enuminterrupt + * + * Description: + * Enumeration done interrupt + * + *******************************************************************************/ + +static inline void stm32_enuminterrupt(FAR struct stm32_usbdev_s *priv) +{ + uint32_t regval; + + /* Activate EP0 */ + + stm32_ep0in_activate(); + + /* Set USB turn-around time for the full speed device with internal PHY interface. */ + + regval = stm32_getreg(STM32_OTGFS_GUSBCFG); + regval &= ~OTGFS_GUSBCFG_TRDT_MASK; + regval |= OTGFS_GUSBCFG_TRDT(5); + stm32_putreg(regval, STM32_OTGFS_GUSBCFG); +} + +/******************************************************************************* + * Name: stm32_isocininterrupt + * + * Description: + * Incomplete isochronous IN transfer interrupt. Assertion of the incomplete + * isochronous IN transfer interrupt indicates an incomplete isochronous IN + * transfer on at least one of the isochronous IN endpoints. + * + *******************************************************************************/ + +#ifdef CONFIG_USBDEV_ISOCHRONOUS +static inline void stm32_isocininterrupt(FAR struct stm32_usbdev_s *priv) +{ + int i; + + /* The application must read the endpoint control register for all isochronous + * IN endpoints to detect endpoints with incomplete IN data transfers. + */ + + for (i = 0; i < STM32_NENDPOINTS; i++) + { + /* Is this an isochronous IN endpoint? */ + + privep = &priv->epin[i]; + if (privep->eptype != USB_EP_ATTR_XFER_ISOC) + { + /* No... keep looking */ + + continue; + } + + /* Is there an active read request on the isochronous OUT endpoint? */ + + if (!privep->active) + { + /* No.. the endpoint is not actively transmitting data */ + + continue; + } + + /* Check if this is the endpoint that had the incomplete transfer */ + + regaddr = STM32_OTGFS_DIEPCTL(privep->epphy); + doepctl = stm32_getreg(regaddr); + dsts = stm32_getreg(STM32_OTGFS_DSTS); + + /* EONUM = 0:even frame, 1:odd frame + * SOFFN = Frame number of the received SOF + */ + + eonum = ((doepctl & OTGFS_DIEPCTL_EONUM) != 0); + soffn = ((dsts & OTGFS_DSTS_SOFFN0) != 0); + + if (eonum != soffn) + { + /* Not this endpoint */ + + continue; + } + + /* For isochronous IN endpoints with incomplete transfers, + * the application must discard the data in the memory and + * disable the endpoint. + */ + + stm32_req_complete(privep, -EIO); +#warning "Will clear OTGFS_DIEPCTL_USBAEP too" + stm32_epin_disable(privep); + break; + } +} +#endif + +/******************************************************************************* + * Name: stm32_isocoutinterrupt + * + * Description: + * Incomplete periodic transfer interrupt + * + *******************************************************************************/ + +#ifdef CONFIG_USBDEV_ISOCHRONOUS +static inline void stm32_isocoutinterrupt(FAR struct stm32_usbdev_s *priv) +{ + FAR struct stm32_ep_s *privep; + FAR struct stm32_req_s *privreq; + uint32_t regaddr; + uint32_t doepctl; + uint32_t dsts; + bool eonum; + bool soffn; + + /* When it receives an IISOOXFR interrupt, the application must read the + * control registers of all isochronous OUT endpoints to determine which + * endpoints had an incomplete transfer in the current microframe. An + * endpoint transfer is incomplete if both the following conditions are true: + * + * DOEPCTLx:EONUM = DSTS:SOFFN[0], and + * DOEPCTLx:EPENA = 1 + */ + + for (i = 0; i < STM32_NENDPOINTS; i++) + { + /* Is this an isochronous OUT endpoint? */ + + privep = &priv->epout[i]; + if (privep->eptype != USB_EP_ATTR_XFER_ISOC) + { + /* No... keep looking */ + + continue; + } + + /* Is there an active read request on the isochronous OUT endpoint? */ + + if (!privep->active) + { + /* No.. the endpoint is not actively transmitting data */ + + continue; + } + + /* Check if this is the endpoint that had the incomplete transfer */ + + regaddr = STM32_OTGFS_DOEPCTL(privep->epphy); + doepctl = stm32_getreg(regaddr); + dsts = stm32_getreg(STM32_OTGFS_DSTS); + + /* EONUM = 0:even frame, 1:odd frame + * SOFFN = Frame number of the received SOF + */ + + eonum = ((doepctl & OTGFS_DOEPCTL_EONUM) != 0); + soffn = ((dsts & OTGFS_DSTS_SOFFN0) != 0); + + if (eonum != soffn) + { + /* Not this endpoint */ + + continue; + } + + /* For isochronous OUT endpoints with incomplete transfers, + * the application must discard the data in the memory and + * disable the endpoint. + */ + + stm32_req_complete(privep, -EIO); +#warning "Will clear OTGFS_DOEPCTL_USBAEP too" + stm32_epout_disable(privep); + break; + } +} +#endif + +/******************************************************************************* + * Name: stm32_sessioninterrupt + * + * Description: + * Session request/new session detected interrupt + * + *******************************************************************************/ + +#ifdef CONFIG_USBDEV_VBUSSENSING +static inline void stm32_sessioninterrupt(FAR struct stm32_usbdev_s *priv) +{ +#warning "Missing logic" +} +#endif + +/******************************************************************************* + * Name: stm32_otginterrupt + * + * Description: + * OTG interrupt + * + *******************************************************************************/ + +#ifdef CONFIG_USBDEV_VBUSSENSING +static inline void stm32_otginterrupt(FAR struct stm32_usbdev_s *priv) +{ + uint32_t regval; + + /* Check for session end detected */ + + regval = stm32_getreg(STM32_OTGFS_GOTGINT); + if ((regval & OTGFS_GOTGINT_SEDET) != 0) + { +#warning "Missing logic" + } + + /* Clear OTG interrupt */ + + stm32_putreg(retval, STM32_OTGFS_GOTGINT); +} +#endif + +/******************************************************************************* + * Name: stm32_usbinterrupt + * + * Description: + * USB interrupt handler + * + *******************************************************************************/ + +static int stm32_usbinterrupt(int irq, FAR void *context) +{ + /* At present, there is only a single OTG FS device support. Hence it is + * pre-allocated as g_otgfsdev. However, in most code, the private data + * structure will be referenced using the 'priv' pointer (rather than the + * global data) in order to simplify any future support for multiple devices. + */ + + FAR struct stm32_usbdev_s *priv = &g_otgfsdev; + uint32_t regval; + + usbtrace(TRACE_INTENTRY(STM32_TRACEINTID_USB), 0); + + /* Assure that we are in device mode */ + + DEBUGASSERT((stm32_getreg(STM32_OTGFS_GINTSTS) & OTGFS_GINTSTS_CMOD) == OTGFS_GINTSTS_DEVMODE); + + /* Get the state of all enabled interrupts. We will do this repeatedly + * some interrupts (like RXFLVL) will generate additional interrupting + * events. + */ + + for (;;) + { + /* Get the set of pending, un-masked interrupts */ + + regval = stm32_getreg(STM32_OTGFS_GINTSTS); + regval &= stm32_getreg(STM32_OTGFS_GINTMSK); + + /* Break out of the loop when there are no further pending (and + * unmasked) interrupts to be processes. + */ + + if (regval == 0) + { + break; + } + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_INTPENDING), (uint16_t)regval); + + /* OUT endpoint interrupt. The core sets this bit to indicate that an + * interrupt is pending on one of the OUT endpoints of the core. + */ + + if ((regval & OTGFS_GINT_OEP) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUT), (uint16_t)regval); + stm32_epout_interrupt(priv); + stm32_putreg(OTGFS_GINT_OEP, STM32_OTGFS_GINTSTS); + } + + /* IN endpoint interrupt. The core sets this bit to indicate that + * an interrupt is pending on one of the IN endpoints of the core. + */ + + if ((regval & OTGFS_GINT_IEP) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN), (uint16_t)regval); + stm32_epin_interrupt(priv); + stm32_putreg(OTGFS_GINT_IEP, STM32_OTGFS_GINTSTS); + } + + /* Host/device mode mismatch error interrupt */ + +#ifdef CONFIG_DEBUG_USB + if ((regval & OTGFS_GINT_MMIS) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_MISMATCH), (uint16_t)regval); + stm32_putreg(OTGFS_GINT_MMIS, STM32_OTGFS_GINTSTS); + } +#endif + + /* Resume/remote wakeup detected interrupt */ + + if ((regval & OTGFS_GINT_WKUP) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_WAKEUP), (uint16_t)regval); + stm32_resumeinterrupt(priv); + stm32_putreg(OTGFS_GINT_WKUP, STM32_OTGFS_GINTSTS); + } + + /* USB suspend interrupt */ + + if ((regval & OTGFS_GINT_USBSUSP) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SUSPEND), (uint16_t)regval); + stm32_suspendinterrupt(priv); + stm32_putreg(OTGFS_GINT_USBSUSP, STM32_OTGFS_GINTSTS); + } + + /* Start of frame interrupt */ + +#ifdef CONFIG_USBDEV_SOFINTERRUPT + if ((regval & OTGFS_GINT_SOF) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SOF), (uint16_t)regval); + stm32_putreg(OTGFS_GINT_SOF, STM32_OTGFS_GINTSTS); + } +#endif + + /* RxFIFO non-empty interrupt. Indicates that there is at least one + * packet pending to be read from the RxFIFO. + */ + + if ((regval & OTGFS_GINT_RXFLVL) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_RXFIFO), (uint16_t)regval); + stm32_rxinterrupt(priv); + stm32_putreg(OTGFS_GINT_RXFLVL, STM32_OTGFS_GINTSTS); + } + + /* USB reset interrupt */ + + if ((regval & OTGFS_GINT_USBRST) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_DEVRESET), (uint16_t)regval); + + /* Perform the device reset */ + + stm32_usbreset(priv); + usbtrace(TRACE_INTEXIT(STM32_TRACEINTID_USB), 0); + stm32_putreg(OTGFS_GINT_USBRST, STM32_OTGFS_GINTSTS); + return OK; + } + + /* Enumeration done interrupt */ + + if ((regval & OTGFS_GINT_ENUMDNE) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_ENUMDNE), (uint16_t)regval); + stm32_enuminterrupt(priv); + stm32_putreg(OTGFS_GINT_ENUMDNE, STM32_OTGFS_GINTSTS); + } + + /* Incomplete isochronous IN transfer interrupt. When the core finds + * non-empty any of the isochronous IN endpoint FIFOs scheduled for + * the current frame non-empty, the core generates an IISOIXFR + * interrupt. + */ + +#ifdef CONFIG_USBDEV_ISOCHRONOUS + if ((regval & OTGFS_GINT_IISOIXFR) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_IISOIXFR), (uint16_t)regval); + stm32_isocininterrupt(priv); + stm32_putreg(OTGFS_GINT_IISOIXFR, STM32_OTGFS_GINTSTS); + } + + /* Incomplete isochronous OUT transfer. For isochronous OUT + * endpoints, the XFRC interrupt may not always be asserted. If the + * core drops isochronous OUT data packets, the application could fail + * to detect the XFRC interrupt. The incomplete Isochronous OUT data + * interrupt indicates that an XFRC interrupt was not asserted on at + * least one of the isochronous OUT endpoints. At this point, the + * endpoint with the incomplete transfer remains enabled, but no active + * transfers remain in progress on this endpoint on the USB. + */ + + if ((regval & OTGFS_GINT_IISOOXFR) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_IISOOXFR), (uint16_t)regval); + stm32_isocoutinterrupt(priv); + stm32_putreg(OTGFS_GINT_IISOOXFR, STM32_OTGFS_GINTSTS); + } +#endif + + /* Session request/new session detected interrupt */ + +#ifdef CONFIG_USBDEV_VBUSSENSING + if ((regval & OTGFS_GINT_SRQ) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SRQ), (uint16_t)regval); + stm32_sessioninterrupt(priv); + stm32_putreg(OTGFS_GINT_SRQ, STM32_OTGFS_GINTSTS); + } + + /* OTG interrupt */ + + if ((regval & OTGFS_GINT_OTG) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OTG), (uint16_t)regval); + stm32_otginterrupt(priv); + stm32_putreg(OTGFS_GINT_OTG, STM32_OTGFS_GINTSTS); + } +#endif + } + + usbtrace(TRACE_INTEXIT(STM32_TRACEINTID_USB), 0); + return OK; +} + +/******************************************************************************* + * Endpoint operations + *******************************************************************************/ + +/******************************************************************************* + * Name: stm32_enablegonak + * + * Description: + * Enable global OUT NAK mode + * + *******************************************************************************/ + +static void stm32_enablegonak(FAR struct stm32_ep_s *privep) +{ + uint32_t regval; + + /* First, make sure that there is no GNOAKEFF interrupt pending. */ + +#if 0 + stm32_putreg(OTGFS_GINT_GONAKEFF, STM32_OTGFS_GINTSTS); +#endif + + /* Enable Global OUT NAK mode in the core. */ + + regval = stm32_getreg(STM32_OTGFS_DCTL); + regval |= OTGFS_DCTL_SGONAK; + stm32_putreg(regval, STM32_OTGFS_DCTL); + +#if 0 + /* Wait for the GONAKEFF interrupt that indicates that the OUT NAK + * mode is in effect. When the interrupt handler pops the OUTNAK word + * from the RxFIFO, the core sets the GONAKEFF interrupt. + */ + + while ((stm32_getreg(STM32_OTGFS_GINTSTS) & OTGFS_GINT_GONAKEFF) == 0); + stm32_putreg(OTGFS_GINT_GONAKEFF, STM32_OTGFS_GINTSTS); + +#else + /* Since we are in the interrupt handler, we cannot wait inline for the + * GONAKEFF because it cannot occur until service th RXFLVL global interrupt + * and pop the OUTNAK word from the RxFIFO. + * + * Perhaps it is sufficient to wait for Global OUT NAK status to be reported + * in OTGFS DCTL register? + */ + + while ((stm32_getreg(STM32_OTGFS_DCTL) & OTGFS_DCTL_GONSTS) == 0); +#endif +} + +/******************************************************************************* + * Name: stm32_disablegonak + * + * Description: + * Disable global OUT NAK mode + * + *******************************************************************************/ + +static void stm32_disablegonak(FAR struct stm32_ep_s *privep) +{ + uint32_t regval; + + /* Set the "Clear the Global OUT NAK bit" to disable global OUT NAK mode */ + + regval = stm32_getreg(STM32_OTGFS_DCTL); + regval |= OTGFS_DCTL_CGONAK; + stm32_putreg(regval, STM32_OTGFS_DCTL); +} + +/******************************************************************************* + * Name: stm32_epout_configure + * + * Description: + * Configure an OUT endpoint, making it usable + * + * Input Parameters: + * privep - a pointer to an internal endpoint structure + * eptype - The type of the endpoint + * maxpacket - The max packet size of the endpoint + * + *******************************************************************************/ + +static int stm32_epout_configure(FAR struct stm32_ep_s *privep, uint8_t eptype, + uint16_t maxpacket) +{ + uint32_t mpsiz; + uint32_t regaddr; + uint32_t regval; + + usbtrace(TRACE_EPCONFIGURE, privep->epphy); + + /* For EP0, the packet size is encoded */ + + if (privep->epphy == EP0) + { + DEBUGASSERT(eptype == USB_EP_ATTR_XFER_CONTROL); + + /* Map the size in bytes to the encoded value in the register */ + + switch (maxpacket) + { + case 8: + mpsiz = OTGFS_DOEPCTL0_MPSIZ_8; + break; + + case 16: + mpsiz = OTGFS_DOEPCTL0_MPSIZ_16; + break; + + case 32: + mpsiz = OTGFS_DOEPCTL0_MPSIZ_32; + break; + + case 64: + mpsiz = OTGFS_DOEPCTL0_MPSIZ_64; + break; + + default: + udbg("Unsupported maxpacket: %d\n", maxpacket); + return -EINVAL; + } + } + + /* For other endpoints, the packet size is in bytes */ + + else + { + mpsiz = (maxpacket << OTGFS_DOEPCTL_MPSIZ_SHIFT); + } + + /* If the endpoint is already active don't change the endpoint control + * register. + */ + + regaddr = STM32_OTGFS_DOEPCTL(privep->epphy); + regval = stm32_getreg(regaddr); + if ((regval & OTGFS_DOEPCTL_USBAEP) == 0) + { + regval &= ~(OTGFS_DOEPCTL_MPSIZ_MASK | OTGFS_DIEPCTL_EPTYP_MASK | OTGFS_DIEPCTL_TXFNUM_MASK); + regval |= mpsiz; + regval |= (eptype << OTGFS_DOEPCTL_EPTYP_SHIFT); + regval |= (eptype << OTGFS_DIEPCTL_TXFNUM_SHIFT); + regval |= (OTGFS_DOEPCTL_SD0PID | OTGFS_DOEPCTL_USBAEP); + stm32_putreg(regval, regaddr); + + /* Save the endpoint configuration */ + + privep->ep.maxpacket = maxpacket; + privep->eptype = eptype; + privep->stalled = false; + } + + /* Enable the interrupt for this endpoint */ + + regval = stm32_getreg(STM32_OTGFS_DAINTMSK); + regval |= OTGFS_DAINT_OEP(privep->epphy); + stm32_putreg(regval, STM32_OTGFS_DAINTMSK); + return OK; +} + +/******************************************************************************* + * Name: stm32_epin_configure + * + * Description: + * Configure an IN endpoint, making it usable + * + * Input Parameters: + * privep - a pointer to an internal endpoint structure + * eptype - The type of the endpoint + * maxpacket - The max packet size of the endpoint + * + *******************************************************************************/ + +static int stm32_epin_configure(FAR struct stm32_ep_s *privep, uint8_t eptype, + uint16_t maxpacket) +{ + uint32_t mpsiz; + uint32_t regaddr; + uint32_t regval; + + usbtrace(TRACE_EPCONFIGURE, privep->epphy); + + /* For EP0, the packet size is encoded */ + + if (privep->epphy == EP0) + { + DEBUGASSERT(eptype == USB_EP_ATTR_XFER_CONTROL); + + /* Map the size in bytes to the encoded value in the register */ + + switch (maxpacket) + { + case 8: + mpsiz = OTGFS_DIEPCTL0_MPSIZ_8; + break; + + case 16: + mpsiz = OTGFS_DIEPCTL0_MPSIZ_16; + break; + + case 32: + mpsiz = OTGFS_DIEPCTL0_MPSIZ_32; + break; + + case 64: + mpsiz = OTGFS_DIEPCTL0_MPSIZ_64; + break; + + default: + udbg("Unsupported maxpacket: %d\n", maxpacket); + return -EINVAL; + } + } + + /* For other endpoints, the packet size is in bytes */ + + else + { + mpsiz = (maxpacket << OTGFS_DIEPCTL_MPSIZ_SHIFT); + } + + + /* If the endpoint is already active don't change the endpoint control + * register. + */ + + regaddr = STM32_OTGFS_DIEPCTL(privep->epphy); + regval = stm32_getreg(regaddr); + if ((regval & OTGFS_DIEPCTL_USBAEP) == 0) + { + regval &= ~(OTGFS_DIEPCTL_MPSIZ_MASK | OTGFS_DIEPCTL_EPTYP_MASK | OTGFS_DIEPCTL_TXFNUM_MASK); + regval |= mpsiz; + regval |= (eptype << OTGFS_DIEPCTL_EPTYP_SHIFT); + regval |= (eptype << OTGFS_DIEPCTL_TXFNUM_SHIFT); + regval |= (OTGFS_DIEPCTL_SD0PID | OTGFS_DIEPCTL_USBAEP); + stm32_putreg(regval, regaddr); + + /* Save the endpoint configuration */ + + privep->ep.maxpacket = maxpacket; + privep->eptype = eptype; + privep->stalled = false; + } + + /* Enable the interrupt for this endpoint */ + + regval = stm32_getreg(STM32_OTGFS_DAINTMSK); + regval |= OTGFS_DAINT_IEP(privep->epphy); + stm32_putreg(regval, STM32_OTGFS_DAINTMSK); + + return OK; +} + +/******************************************************************************* + * Name: stm32_ep_configure + * + * Description: + * Configure endpoint, making it usable + * + * Input Parameters: + * ep - the struct usbdev_ep_s instance obtained from allocep() + * desc - A struct usb_epdesc_s instance describing the endpoint + * last - true if this this last endpoint to be configured. Some hardware + * needs to take special action when all of the endpoints have been + * configured. + * + *******************************************************************************/ + +static int stm32_ep_configure(FAR struct usbdev_ep_s *ep, + FAR const struct usb_epdesc_s *desc, + bool last) +{ + FAR struct stm32_ep_s *privep = (FAR struct stm32_ep_s *)ep; + uint16_t maxpacket; + uint8_t eptype; + int ret; + + usbtrace(TRACE_EPCONFIGURE, privep->epphy); + DEBUGASSERT(desc->addr == ep->eplog); + + /* Initialize EP capabilities */ + + maxpacket = GETUINT16(desc->mxpacketsize); + eptype = desc->attr & USB_EP_ATTR_XFERTYPE_MASK; + + /* Setup Endpoint Control Register */ + + if (privep->isin) + { + ret = stm32_epin_configure(privep, eptype, maxpacket); + } + else + { + ret = stm32_epout_configure(privep, eptype, maxpacket); + } + + return ret; +} + +/******************************************************************************* + * Name: stm32_ep0_configure + * + * Description: + * Reset Usb engine + * + *******************************************************************************/ + +static void stm32_ep0_configure(FAR struct stm32_usbdev_s *priv) +{ + /* Enable EP0 IN and OUT */ + + (void)stm32_epin_configure(&priv->epin[EP0], USB_EP_ATTR_XFER_CONTROL, + CONFIG_USBDEV_EP0_MAXSIZE); + (void)stm32_epout_configure(&priv->epout[EP0], USB_EP_ATTR_XFER_CONTROL, + CONFIG_USBDEV_EP0_MAXSIZE); +} + +/******************************************************************************* + * Name: stm32_epout_disable + * + * Description: + * Diable an OUT endpoint will no longer be used + * + *******************************************************************************/ + +static void stm32_epout_disable(FAR struct stm32_ep_s *privep) +{ + uint32_t regaddr; + uint32_t regval; + irqstate_t flags; + + usbtrace(TRACE_EPDISABLE, privep->epphy); + + /* Is this an IN or an OUT endpoint */ + + /* Before disabling any OUT endpoint, the application must enable + * Global OUT NAK mode in the core. + */ + + flags = irqsave(); + stm32_enablegonak(privep); + + /* Disable the required OUT endpoint by setting the EPDIS and SNAK bits + * int DOECPTL register. + */ + + regaddr = STM32_OTGFS_DOEPCTL(privep->epphy); + regval = stm32_getreg(regaddr); + regval &= ~OTGFS_DOEPCTL_USBAEP; + regval |= (OTGFS_DOEPCTL_EPDIS | OTGFS_DOEPCTL_SNAK); + stm32_putreg(regval, regaddr); + + /* Wait for the EPDISD interrupt which indicates that the OUT + * endpoint is completely disabled. + */ + +#if 0 /* Doesn't happen */ + regaddr = STM32_OTGFS_DOEPINT(privep->epphy); + while ((stm32_getreg(regaddr) & OTGFS_DOEPINT_EPDISD) == 0); +#else + /* REVISIT: */ + up_mdelay(50); +#endif + + /* Then disble the Global OUT NAK mode to continue receiving data + * from other non-disabled OUT endpoints. + */ + + stm32_disablegonak(privep); + + /* Disable endpoint interrupts */ + + regval = stm32_getreg(STM32_OTGFS_DAINTMSK); + regval &= ~OTGFS_DAINT_OEP(privep->epphy); + stm32_putreg(regval, STM32_OTGFS_DAINTMSK); + + /* Cancel any queued read requests */ + + stm32_req_cancel(privep, -ESHUTDOWN); + + irqrestore(flags); +} + +/******************************************************************************* + * Name: stm32_epin_disable + * + * Description: + * Diable an IN endpoint will no longer be used + * + *******************************************************************************/ + +static void stm32_epin_disable(FAR struct stm32_ep_s *privep) +{ + uint32_t regaddr; + uint32_t regval; + irqstate_t flags; + + usbtrace(TRACE_EPDISABLE, privep->epphy); + + /* Make sure that there is no pending IPEPNE interrupt (because we are + * to poll this bit below). + */ + + stm32_putreg(OTGFS_DIEPINT_INEPNE, STM32_OTGFS_DIEPINT(privep->epphy)); + + /* Set the endpoint in NAK mode */ + + regaddr = STM32_OTGFS_DIEPCTL(privep->epphy); + regval = stm32_getreg(regaddr); + regval &= ~OTGFS_DIEPCTL_USBAEP; + regval |= (OTGFS_DIEPCTL_EPDIS | OTGFS_DIEPCTL_SNAK); + stm32_putreg(regval, regaddr); + + /* Wait for the INEPNE interrupt that indicates that we are now in NAK mode */ + + regaddr = STM32_OTGFS_DIEPINT(privep->epphy); + while ((stm32_getreg(regaddr) & OTGFS_DIEPINT_INEPNE) == 0); + stm32_putreg(OTGFS_DIEPINT_INEPNE, regaddr); + + /* Deactivate and disable the endpoint by setting the EPIS and SNAK bits + * the DIEPCTLx register. + */ + + flags = irqsave(); + regaddr = STM32_OTGFS_DIEPCTL(privep->epphy); + regval = stm32_getreg(regaddr); + regval &= ~OTGFS_DIEPCTL_USBAEP; + regval |= (OTGFS_DIEPCTL_EPDIS | OTGFS_DIEPCTL_SNAK); + stm32_putreg(regval, regaddr); + + /* Wait for the EPDISD interrupt which indicates that the IN + * endpoint is completely disabled. + */ + + regaddr = STM32_OTGFS_DIEPINT(privep->epphy); + while ((stm32_getreg(regaddr) & OTGFS_DIEPINT_EPDISD) == 0); + + /* Flush any data remaining in the TxFIFO */ + + stm32_txfifo_flush(OTGFS_GRSTCTL_TXFNUM_D(privep->epphy)); + + /* Disable endpoint interrupts */ + + regval = stm32_getreg(STM32_OTGFS_DAINTMSK); + regval &= ~OTGFS_DAINT_IEP(privep->epphy); + stm32_putreg(regval, STM32_OTGFS_DAINTMSK); + + /* Cancel any queued write requests */ + + stm32_req_cancel(privep, -ESHUTDOWN); + + irqrestore(flags); +} + +/******************************************************************************* + * Name: stm32_ep_disable + * + * Description: + * The endpoint will no longer be used + * + *******************************************************************************/ + +static int stm32_ep_disable(FAR struct usbdev_ep_s *ep) +{ + FAR struct stm32_ep_s *privep = (FAR struct stm32_ep_s *)ep; + +#ifdef CONFIG_DEBUG + if (!ep) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } +#endif + usbtrace(TRACE_EPDISABLE, privep->epphy); + + /* Is this an IN or an OUT endpoint */ + + if (privep->isin) + { + /* Disable the IN endpoint */ + + stm32_epin_disable(privep); + } + else + { + /* Disable the OUT endpoint */ + + stm32_epout_disable(privep); + } + + return OK; +} + +/******************************************************************************* + * Name: stm32_ep_allocreq + * + * Description: + * Allocate an I/O request + * + *******************************************************************************/ + +static FAR struct usbdev_req_s *stm32_ep_allocreq(FAR struct usbdev_ep_s *ep) +{ + FAR struct stm32_req_s *privreq; + +#ifdef CONFIG_DEBUG + if (!ep) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return NULL; + } +#endif + usbtrace(TRACE_EPALLOCREQ, ((FAR struct stm32_ep_s *)ep)->epphy); + + privreq = (FAR struct stm32_req_s *)malloc(sizeof(struct stm32_req_s)); + if (!privreq) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_ALLOCFAIL), 0); + return NULL; + } + + memset(privreq, 0, sizeof(struct stm32_req_s)); + return &privreq->req; +} + +/******************************************************************************* + * Name: stm32_ep_freereq + * + * Description: + * Free an I/O request + * + *******************************************************************************/ + +static void stm32_ep_freereq(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req) +{ + FAR struct stm32_req_s *privreq = (FAR struct stm32_req_s *)req; + +#ifdef CONFIG_DEBUG + if (!ep || !req) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return; + } +#endif + + usbtrace(TRACE_EPFREEREQ, ((FAR struct stm32_ep_s *)ep)->epphy); + free(privreq); +} + +/******************************************************************************* + * Name: stm32_ep_allocbuffer + * + * Description: + * Allocate an I/O buffer + * + *******************************************************************************/ + +#ifdef CONFIG_ARCH_USBDEV_DMA +static void *stm32_ep_allocbuffer(FAR struct usbdev_ep_s *ep, unsigned bytes) +{ + usbtrace(TRACE_EPALLOCBUFFER, privep->epphy); + return malloc(bytes) +} +#endif + +/******************************************************************************* + * Name: stm32_ep_freebuffer + * + * Description: + * Free an I/O buffer + * + *******************************************************************************/ + +#ifdef CONFIG_LPC313x_USBDEV_DMA +static void stm32_ep_freebuffer(FAR struct usbdev_ep_s *ep, FAR void *buf) +{ + usbtrace(TRACE_EPFREEBUFFER, privep->epphy); + free(buf); +} +#endif + +/******************************************************************************* + * Name: stm32_ep_submit + * + * Description: + * Submit an I/O request to the endpoint + * + *******************************************************************************/ + +static int stm32_ep_submit(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req) +{ + FAR struct stm32_req_s *privreq = (FAR struct stm32_req_s *)req; + FAR struct stm32_ep_s *privep = (FAR struct stm32_ep_s *)ep; + FAR struct stm32_usbdev_s *priv; + irqstate_t flags; + int ret = OK; + + /* Some sanity checking */ + +#ifdef CONFIG_DEBUG + if (!req || !req->callback || !req->buf || !ep) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + ullvdbg("req=%p callback=%p buf=%p ep=%p\n", req, req->callback, req->buf, ep); + return -EINVAL; + } +#endif + + usbtrace(TRACE_EPSUBMIT, privep->epphy); + priv = privep->dev; + +#ifdef CONFIG_DEBUG + if (!priv->driver) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_NOTCONFIGURED), priv->usbdev.speed); + return -ESHUTDOWN; + } +#endif + + /* Handle the request from the class driver */ + + req->result = -EINPROGRESS; + req->xfrd = 0; + + /* Disable Interrupts */ + + flags = irqsave(); + + /* If we are stalled, then drop all requests on the floor */ + + if (privep->stalled) + { + ret = -EBUSY; + } + else + { + /* Add the new request to the request queue for the endpoint. */ + + if (stm32_req_addlast(privep, privreq) && !privep->active) + { + /* If a request was added to an IN endpoint, then attempt to send + * the request data buffer now. + */ + + if (privep->isin) + { + usbtrace(TRACE_INREQQUEUED(privep->epphy), privreq->req.len); + + /* If the endpoint is not busy with another write request, + * then process the newly received write request now. + */ + + if (!privep->active) + { + stm32_epin_request(priv, privep); + } + } + + /* If the request was added to an OUT endoutput, then attempt to + * setup a read into the request data buffer now (this will, of + * course, fail if there is already a read in place). + */ + + else + { + usbtrace(TRACE_OUTREQQUEUED(privep->epphy), privreq->req.len); + stm32_epout_request(priv, privep); + } + } + } + + irqrestore(flags); + return ret; +} + +/******************************************************************************* + * Name: stm32_ep_cancel + * + * Description: + * Cancel an I/O request previously sent to an endpoint + * + *******************************************************************************/ + +static int stm32_ep_cancel(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req) +{ + FAR struct stm32_ep_s *privep = (FAR struct stm32_ep_s *)ep; + FAR struct stm32_usbdev_s *priv; + irqstate_t flags; + +#ifdef CONFIG_DEBUG + if (!ep || !req) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } +#endif + + usbtrace(TRACE_EPCANCEL, privep->epphy); + priv = privep->dev; + + flags = irqsave(); + + /* FIXME: if the request is the first, then we need to flush the EP + * otherwise just remove it from the list + * + * but ... all other implementations cancel all requests ... + */ + + stm32_req_cancel(privep, -ESHUTDOWN); + irqrestore(flags); + return OK; +} + +/******************************************************************************* + * Name: stm32_epout_setstall + * + * Description: + * Stall an OUT endpoint + * + *******************************************************************************/ + +static int stm32_epout_setstall(FAR struct stm32_ep_s *privep) +{ +#if 1 + /* This implementation follows the requirements from the STM32 F4 reference + * manual. + */ + + uint32_t regaddr; + uint32_t regval; + + /* Put the core in the Global OUT NAK mode */ + + stm32_enablegonak(privep); + + /* Disable and STALL the OUT endpoint by setting the EPDIS and STALL bits + * in the DOECPTL register. + */ + + regaddr = STM32_OTGFS_DOEPCTL(privep->epphy); + regval = stm32_getreg(regaddr); + regval |= (OTGFS_DOEPCTL_EPDIS | OTGFS_DOEPCTL_STALL); + stm32_putreg(regval, regaddr); + + /* Wait for the EPDISD interrupt which indicates that the OUT + * endpoint is completely disabled. + */ + +#if 0 /* Doesn't happen */ + regaddr = STM32_OTGFS_DOEPINT(privep->epphy); + while ((stm32_getreg(regaddr) & OTGFS_DOEPINT_EPDISD) == 0); +#else + /* REVISIT: */ + up_mdelay(50); +#endif + + /* Disable Global OUT NAK mode */ + + stm32_disablegonak(privep); + + /* The endpoint is now stalled */ + + privep->stalled = true; + return OK; +#else + /* This implementation follows the STMicro code example. */ + /* REVISIT: */ + + uint32_t regaddr; + uint32_t regval; + + /* Stall the OUT endpoint by setting the STALL bit in the DOECPTL register. */ + + regaddr = STM32_OTGFS_DOEPCTL(privep->epphy); + regval = stm32_getreg(regaddr); + regval |= OTGFS_DOEPCTL_STALL; + stm32_putreg(regval, regaddr); + + /* The endpoint is now stalled */ + + privep->stalled = true; + return OK; +#endif +} + +/******************************************************************************* + * Name: stm32_epin_setstall + * + * Description: + * Stall an IN endpoint + * + *******************************************************************************/ + +static int stm32_epin_setstall(FAR struct stm32_ep_s *privep) +{ + uint32_t regaddr; + uint32_t regval; + + /* Get the IN endpoint device control register */ + + regaddr = STM32_OTGFS_DIEPCTL(privep->epphy); + regval = stm32_getreg(regaddr); + + /* Is the endpoint enabled? */ + + if ((regval & OTGFS_DIEPCTL_EPENA) != 0) + { + /* Yes.. the endpoint is enabled, disable it */ + + regval = OTGFS_DIEPCTL_EPDIS; + } + else + { + regval = 0; + } + + /* Then stall the endpoint */ + + regval |= OTGFS_DIEPCTL_STALL; + stm32_putreg(regval, regaddr); + + /* The endpoint is now stalled */ + + privep->stalled = true; + return OK; +} + +/******************************************************************************* + * Name: stm32_ep_setstall + * + * Description: + * Stall an endpoint + * + *******************************************************************************/ + +static int stm32_ep_setstall(FAR struct stm32_ep_s *privep) +{ + usbtrace(TRACE_EPSTALL, privep->epphy); + + /* Is this an IN endpoint? */ + + if (privep->isin == 1) + { + return stm32_epin_setstall(privep); + } + else + { + return stm32_epout_setstall(privep); + } +} + +/******************************************************************************* + * Name: stm32_ep_clrstall + * + * Description: + * Resume a stalled endpoint + * + *******************************************************************************/ + +static int stm32_ep_clrstall(FAR struct stm32_ep_s *privep) +{ + uint32_t regaddr; + uint32_t regval; + uint32_t stallbit; + uint32_t data0bit; + + usbtrace(TRACE_EPRESUME, privep->epphy); + + /* Is this an IN endpoint? */ + + if (privep->isin == 1) + { + /* Clear the stall bit in the IN endpoint device control register */ + + regaddr = STM32_OTGFS_DIEPCTL(privep->epphy); + stallbit = OTGFS_DIEPCTL_STALL; + data0bit = OTGFS_DIEPCTL_SD0PID; + } + else + { + /* Clear the stall bit in the IN endpoint device control register */ + + regaddr = STM32_OTGFS_DOEPCTL(privep->epphy); + stallbit = OTGFS_DOEPCTL_STALL; + data0bit = OTGFS_DOEPCTL_SD0PID; + } + + /* Clear the stall bit */ + + regval = stm32_getreg(regaddr); + regval &= ~stallbit; + + /* Set the DATA0 pid for interrupt and bulk endpoints */ + + if (privep->eptype == USB_EP_ATTR_XFER_INT || + privep->eptype == USB_EP_ATTR_XFER_BULK) + { + /* Writing this bit sets the DATA0 PID */ + + regval |= data0bit; + } + + stm32_putreg(regval, regaddr); + + /* The endpoint is no longer stalled */ + + privep->stalled = false; + return OK; +} + +/******************************************************************************* + * Name: stm32_ep_stall + * + * Description: + * Stall or resume an endpoint + * + *******************************************************************************/ + +static int stm32_ep_stall(FAR struct usbdev_ep_s *ep, bool resume) +{ + FAR struct stm32_ep_s *privep = (FAR struct stm32_ep_s *)ep; + irqstate_t flags; + int ret; + + /* Set or clear the stall condition as requested */ + + flags = irqsave(); + if (resume) + { + ret = stm32_ep_clrstall(privep); + } + else + { + ret = stm32_ep_setstall(privep); + } + irqrestore(flags); + + return ret; +} + +/******************************************************************************* + * Name: stm32_ep0_stall + * + * Description: + * Stall endpoint 0 + * + *******************************************************************************/ + +static void stm32_ep0_stall(FAR struct stm32_usbdev_s *priv) +{ + stm32_epin_setstall(&priv->epin[EP0]); + stm32_epout_setstall(&priv->epout[EP0]); + priv->stalled = true; + stm32_ep0out_ctrlsetup(priv); +} + +/******************************************************************************* + * Device operations + *******************************************************************************/ + +/******************************************************************************* + * Name: stm32_ep_alloc + * + * Description: + * Allocate an endpoint matching the parameters. + * + * Input Parameters: + * eplog - 7-bit logical endpoint number (direction bit ignored). Zero means + * that any endpoint matching the other requirements will suffice. The + * assigned endpoint can be found in the eplog field. + * in - true: IN (device-to-host) endpoint requested + * eptype - Endpoint type. One of {USB_EP_ATTR_XFER_ISOC, USB_EP_ATTR_XFER_BULK, + * USB_EP_ATTR_XFER_INT} + * + *******************************************************************************/ + +static FAR struct usbdev_ep_s *stm32_ep_alloc(FAR struct usbdev_s *dev, + uint8_t eplog, bool in, + uint8_t eptype) +{ + FAR struct stm32_usbdev_s *priv = (FAR struct stm32_usbdev_s *)dev; + uint8_t epavail; + irqstate_t flags; + int epphy; + int epno = 0; + + usbtrace(TRACE_DEVALLOCEP, (uint16_t)eplog); + + /* Ignore any direction bits in the logical address */ + + epphy = USB_EPNO(eplog); + + /* Get the set of available endpoints */ + + flags = irqsave(); + epavail = priv->epavail; + + /* A physical address of 0 means that any endpoint will do */ + + if (epphy > 0) + { + /* Otherwise, we will return the endpoint structure only for the requested + * 'logical' endpoint. All of the other checks will still be performed. + * + * First, verify that the logical endpoint is in the range supported by + * by the hardware. + */ + + if (epphy >= STM32_NENDPOINTS) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPNO), (uint16_t)epphy); + return NULL; + } + + /* Remove all of the candidate endpoints from the bitset except for the + * this physical endpoint number. + */ + + epavail &= (1 << epphy); + } + + /* Is there an available endpoint? */ + + if (epavail) + { + /* Yes.. Select the lowest numbered endpoint in the set of available + * endpoints. + */ + + for (epno = 1; epno < STM32_NENDPOINTS; epno++) + { + uint8_t bit = 1 << epno; + if ((epavail & bit) != 0) + { + /* Mark the endpoint no longer available */ + + priv->epavail &= ~(1 << epno); + + /* And return the pointer to the standard endpoint structure */ + + irqrestore(flags); + return in ? &priv->epin[epno].ep : &priv->epout[epno].ep; + } + } + + /* We should not get here */ + } + + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_NOEP), (uint16_t)eplog); + irqrestore(flags); + return NULL; +} + +/******************************************************************************* + * Name: stm32_ep_free + * + * Description: + * Free the previously allocated endpoint + * + *******************************************************************************/ + +static void stm32_ep_free(FAR struct usbdev_s *dev, FAR struct usbdev_ep_s *ep) +{ + FAR struct stm32_usbdev_s *priv = (FAR struct stm32_usbdev_s *)dev; + FAR struct stm32_ep_s *privep = (FAR struct stm32_ep_s *)ep; + irqstate_t flags; + + usbtrace(TRACE_DEVFREEEP, (uint16_t)privep->epphy); + + if (priv && privep) + { + /* Mark the endpoint as available */ + + flags = irqsave(); + priv->epavail |= (1 << privep->epphy); + irqrestore(flags); + } +} + +/******************************************************************************* + * Name: stm32_getframe + * + * Description: + * Returns the current frame number + * + *******************************************************************************/ + +static int stm32_getframe(struct usbdev_s *dev) +{ + uint32_t regval; + + usbtrace(TRACE_DEVGETFRAME, 0); + + /* Return the last frame number of the last SOF detected by the hardware */ + + regval = stm32_getreg(STM32_OTGFS_DSTS); + return (int)((regval & OTGFS_DSTS_SOFFN_MASK) >> OTGFS_DSTS_SOFFN_SHIFT); +} + +/******************************************************************************* + * Name: stm32_wakeup + * + * Description: + * Exit suspend mode. + * + *******************************************************************************/ + +static int stm32_wakeup(struct usbdev_s *dev) +{ + FAR struct stm32_usbdev_s *priv = (FAR struct stm32_usbdev_s *)dev; + uint32_t regval; + irqstate_t flags; + + usbtrace(TRACE_DEVWAKEUP, 0); + + /* Is wakeup enabled? */ + + flags = irqsave(); + if (priv->wakeup) + { + /* Yes... is the core suspended? */ + + regval = stm32_getreg(STM32_OTGFS_DSTS); + if ((regval & OTGFS_DSTS_SUSPSTS) != 0) + { + /* Re-start the PHY clock and un-gate USB core clock (HCLK) */ + +#ifdef CONFIG_USBDEV_LOWPOWER + regval = stm32_getreg(STM32_OTGFS_PCGCCTL); + regval &= ~(OTGFS_PCGCCTL_STPPCLK | OTGFS_PCGCCTL_GATEHCLK); + stm32_putreg(regval, STM32_OTGFS_PCGCCTL); +#endif + + /* Activate Remote wakeup signaling */ + + regval = stm32_getreg(STM32_OTGFS_DCTL); + regval |= OTGFS_DCTL_RWUSIG; + stm32_putreg(regval, STM32_OTGFS_DCTL); + up_mdelay(5); + regval &= ~OTGFS_DCTL_RWUSIG; + stm32_putreg(regval, STM32_OTGFS_DCTL); + } + } + + irqrestore(flags); + return OK; +} + +/******************************************************************************* + * Name: stm32_selfpowered + * + * Description: + * Sets/clears the device selfpowered feature + * + *******************************************************************************/ + +static int stm32_selfpowered(struct usbdev_s *dev, bool selfpowered) +{ + FAR struct stm32_usbdev_s *priv = (FAR struct stm32_usbdev_s *)dev; + + usbtrace(TRACE_DEVSELFPOWERED, (uint16_t)selfpowered); + +#ifdef CONFIG_DEBUG + if (!dev) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return -ENODEV; + } +#endif + + priv->selfpowered = selfpowered; + return OK; +} + +/******************************************************************************* + * Name: stm32_pullup + * + * Description: + * Software-controlled connect to/disconnect from USB host + * + *******************************************************************************/ + +static int stm32_pullup(struct usbdev_s *dev, bool enable) +{ + uint32_t regval; + + usbtrace(TRACE_DEVPULLUP, (uint16_t)enable); + + irqstate_t flags = irqsave(); + regval = stm32_getreg(STM32_OTGFS_DCTL); + if (enable) + { + /* Connect the device by clearing the soft disconnect bit in the DCTL + * register + */ + + regval &= ~OTGFS_DCTL_SDIS; + } + else + { + /* Connect the device by setting the soft disconnect bit in the DCTL + * register + */ + + regval |= OTGFS_DCTL_SDIS; + } + + stm32_putreg(regval, STM32_OTGFS_DCTL); + up_mdelay(3); + + irqrestore(flags); + return OK; +} + +/******************************************************************************* + * Name: stm32_setaddress + * + * Description: + * Set the devices USB address + * + *******************************************************************************/ + +static void stm32_setaddress(struct stm32_usbdev_s *priv, uint16_t address) +{ + uint32_t regval; + + /* Set the device address in the DCFG register */ + + regval = stm32_getreg(STM32_OTGFS_DCFG); + regval &= ~OTGFS_DCFG_DAD_MASK; + regval |= ((uint32_t)address << OTGFS_DCFG_DAD_SHIFT); + stm32_putreg(regval, STM32_OTGFS_DCFG); + + /* Are we now addressed? (i.e., do we have a non-NULL device + * address?) + */ + + if (address != 0) + { + priv->devstate = DEVSTATE_ADDRESSED; + priv->addressed = true; + } + else + { + priv->devstate = DEVSTATE_DEFAULT; + priv->addressed = false; + } +} + +/******************************************************************************* + * Name: stm32_txfifo_flush + * + * Description: + * Flush the specific TX fifo. + * + *******************************************************************************/ + +static int stm32_txfifo_flush(uint32_t txfnum) +{ + uint32_t regval; + uint32_t timeout; + + /* Initiate the TX FIFO flush operation */ + + regval = OTGFS_GRSTCTL_TXFFLSH | txfnum; + stm32_putreg(regval, STM32_OTGFS_GRSTCTL); + + /* Wait for the FLUSH to complete */ + + for (timeout = 0; timeout < STM32_FLUSH_DELAY; timeout++) + { + regval = stm32_getreg(STM32_OTGFS_GRSTCTL); + if ((regval & OTGFS_GRSTCTL_TXFFLSH) == 0) + { + break; + } + } + + /* Wait for 3 PHY Clocks */ + + up_udelay(3); + return OK; +} + +/******************************************************************************* + * Name: stm32_rxfifo_flush + * + * Description: + * Flush the RX fifo. + * + *******************************************************************************/ + +static int stm32_rxfifo_flush(void) +{ + uint32_t regval; + uint32_t timeout; + + /* Initiate the RX FIFO flush operation */ + + stm32_putreg(OTGFS_GRSTCTL_RXFFLSH, STM32_OTGFS_GRSTCTL); + + /* Wait for the FLUSH to complete */ + + for (timeout = 0; timeout < STM32_FLUSH_DELAY; timeout++) + { + regval = stm32_getreg(STM32_OTGFS_GRSTCTL); + if ((regval & OTGFS_GRSTCTL_RXFFLSH) == 0) + { + break; + } + } + + /* Wait for 3 PHY Clocks */ + + up_udelay(3); + return OK; +} + +/******************************************************************************* + * Name: stm32_swinitialize + * + * Description: + * Initialize all driver data structures. + * + *******************************************************************************/ + +static void stm32_swinitialize(FAR struct stm32_usbdev_s *priv) +{ + FAR struct stm32_ep_s *privep; + int i; + + /* Initialize the device state structure */ + + memset(priv, 0, sizeof(struct stm32_usbdev_s)); + + priv->usbdev.ops = &g_devops; + priv->usbdev.ep0 = &priv->epin[EP0].ep; + priv->epavail = STM32_EP_AVAILABLE; + + priv->epin[EP0].ep.priv = priv; + priv->epout[EP0].ep.priv = priv; + + /* Initialize the endpoint lists */ + + for (i = 0; i < STM32_NENDPOINTS; i++) + { + /* Set endpoint operations, reference to driver structure (not + * really necessary because there is only one controller), and + * the physical endpoint number (which is just the index to the + * endpoint). + */ + + privep = &priv->epin[i]; + privep->ep.ops = &g_epops; + privep->dev = priv; + privep->isin = 1; + + /* The index, i, is the physical endpoint address; Map this + * to a logical endpoint address usable by the class driver. + */ + + privep->epphy = i; + privep->ep.eplog = STM32_EPPHYIN2LOG(i); + + /* Control until endpoint is activated */ + + privep->eptype = USB_EP_ATTR_XFER_CONTROL; + privep->ep.maxpacket = CONFIG_USBDEV_EP0_MAXSIZE; + } + + /* Initialize the endpoint lists */ + + for (i = 0; i < STM32_NENDPOINTS; i++) + { + /* Set endpoint operations, reference to driver structure (not + * really necessary because there is only one controller), and + * the physical endpoint number (which is just the index to the + * endpoint). + */ + + privep = &priv->epout[i]; + privep->ep.ops = &g_epops; + privep->dev = priv; + + /* The index, i, is the physical endpoint address; Map this + * to a logical endpoint address usable by the class driver. + */ + + privep->epphy = i; + privep->ep.eplog = STM32_EPPHYOUT2LOG(i); + + /* Control until endpoint is activated */ + + privep->eptype = USB_EP_ATTR_XFER_CONTROL; + privep->ep.maxpacket = CONFIG_USBDEV_EP0_MAXSIZE; + } +} + +/******************************************************************************* + * Name: stm32_hwinitialize + * + * Description: + * Configure the OTG FS core for operation. + * + *******************************************************************************/ + +static void stm32_hwinitialize(FAR struct stm32_usbdev_s *priv) +{ + uint32_t regval; + uint32_t timeout; + uint32_t address; + int i; + + /* At startup the core is in FS mode. */ + + /* Disable the USB global interrupt by clearing GINTMSK in the global OTG + * FS AHB configuration register. + */ + + stm32_putreg(OTGFS_GAHBCFG_TXFELVL, STM32_OTGFS_GAHBCFG); + + /* Common USB OTG core initialization */ + /* Reset after a PHY select and set Host mode. First, wait for AHB master + * IDLE state. + */ + + for (timeout = 0; timeout < STM32_READY_DELAY; timeout++) + { + up_udelay(3); + regval = stm32_getreg(STM32_OTGFS_GRSTCTL); + if ((regval & OTGFS_GRSTCTL_AHBIDL) != 0) + { + break; + } + } + + /* Then perform the core soft reset. */ + + stm32_putreg(OTGFS_GRSTCTL_CSRST, STM32_OTGFS_GRSTCTL); + for (timeout = 0; timeout < STM32_READY_DELAY; timeout++) + { + regval = stm32_getreg(STM32_OTGFS_GRSTCTL); + if ((regval & OTGFS_GRSTCTL_CSRST) == 0) + { + break; + } + } + + /* Wait for 3 PHY Clocks */ + + up_udelay(3); + + /* Deactivate the power down */ + + regval = (OTGFS_GCCFG_PWRDWN | OTGFS_GCCFG_VBUSASEN | OTGFS_GCCFG_VBUSBSEN); +#ifndef CONFIG_USBDEV_VBUSSENSING + regval |= OTGFS_GCCFG_NOVBUSSENS; +#endif +#ifdef CONFIG_USBDEV_SOFOUTPUT + regval |= OTGFS_GCCFG_SOFOUTEN; +#endif + stm32_putreg(regval, STM32_OTGFS_GCCFG); + up_mdelay(20); + + /* Force Device Mode */ + + regval = stm32_getreg(STM32_OTGFS_GUSBCFG); + regval &= ~OTGFS_GUSBCFG_FHMOD; + regval |= OTGFS_GUSBCFG_FDMOD; + stm32_putreg(regval, STM32_OTGFS_GUSBCFG); + up_mdelay(50); + + /* Initialize device mode */ + /* Restart the Phy Clock */ + + stm32_putreg(0, STM32_OTGFS_PCGCCTL); + + /* Device configuration register */ + + regval = stm32_getreg(STM32_OTGFS_DCFG); + regval &= ~OTGFS_DCFG_PFIVL_MASK; + regval |= OTGFS_DCFG_PFIVL_80PCT; + stm32_putreg(regval, STM32_OTGFS_DCFG); + + /* Set full speed phy */ + + regval = stm32_getreg(STM32_OTGFS_DCFG); + regval &= ~OTGFS_DCFG_DSPD_MASK; + regval |= OTGFS_DCFG_DSPD_FS; + stm32_putreg(regval, STM32_OTGFS_DCFG); + + /* Set Rx FIFO size */ + + stm32_putreg(STM32_RXFIFO_WORDS, STM32_OTGFS_GRXFSIZ); + + /* EP0 TX */ + + address = STM32_RXFIFO_WORDS; + regval = (address << OTGFS_DIEPTXF0_TX0FD_SHIFT) | + (STM32_EP0_TXFIFO_WORDS << OTGFS_DIEPTXF0_TX0FSA_SHIFT); + stm32_putreg(regval, STM32_OTGFS_DIEPTXF0); + + /* EP1 TX */ + + address += STM32_EP0_TXFIFO_WORDS; + regval = (address << OTGFS_DIEPTXF_INEPTXSA_SHIFT) | + (STM32_EP1_TXFIFO_WORDS << OTGFS_DIEPTXF_INEPTXFD_SHIFT); + stm32_putreg(regval, STM32_OTGFS_DIEPTXF1); + + /* EP2 TX */ + + address += STM32_EP1_TXFIFO_WORDS; + regval = (address << OTGFS_DIEPTXF_INEPTXSA_SHIFT) | + (STM32_EP2_TXFIFO_WORDS << OTGFS_DIEPTXF_INEPTXFD_SHIFT); + stm32_putreg(regval, STM32_OTGFS_DIEPTXF2); + + /* EP3 TX */ + + address += STM32_EP2_TXFIFO_WORDS; + regval = (address << OTGFS_DIEPTXF_INEPTXSA_SHIFT) | + (STM32_EP3_TXFIFO_WORDS << OTGFS_DIEPTXF_INEPTXFD_SHIFT); + stm32_putreg(regval, STM32_OTGFS_DIEPTXF3); + + /* Flush the FIFOs */ + + stm32_txfifo_flush(OTGFS_GRSTCTL_TXFNUM_DALL); + stm32_rxfifo_flush(); + + /* Clear all pending Device Interrupts */ + + stm32_putreg(0, STM32_OTGFS_DIEPMSK); + stm32_putreg(0, STM32_OTGFS_DOEPMSK); + stm32_putreg(0xffffffff, STM32_OTGFS_DAINT); + stm32_putreg(0, STM32_OTGFS_DAINTMSK); + + /* Configure all IN endpoints */ + + for (i = 0; i < STM32_NENDPOINTS; i++) + { + regval = stm32_getreg(STM32_OTGFS_DIEPCTL(i)); + if ((regval & OTGFS_DIEPCTL_EPENA) != 0) + { + /* The endpoint is already enabled */ + + regval = OTGFS_DIEPCTL_EPENA | OTGFS_DIEPCTL_SNAK; + } + else + { + regval = 0; + } + + stm32_putreg(regval, STM32_OTGFS_DIEPCTL(i)); + stm32_putreg(0, STM32_OTGFS_DIEPTSIZ(i)); + stm32_putreg(0xff, STM32_OTGFS_DIEPINT(i)); + } + + /* Configure all OUT endpoints */ + + for (i = 0; i < STM32_NENDPOINTS; i++) + { + regval = stm32_getreg(STM32_OTGFS_DOEPCTL(i)); + if ((regval & OTGFS_DOEPCTL_EPENA) != 0) + { + /* The endpoint is already enabled */ + + regval = OTGFS_DOEPCTL_EPENA | OTGFS_DOEPCTL_SNAK; + } + else + { + regval = 0; + } + + stm32_putreg(regval, STM32_OTGFS_DOEPCTL(i)); + stm32_putreg(0, STM32_OTGFS_DOEPTSIZ(i)); + stm32_putreg(0xff, STM32_OTGFS_DOEPINT(i)); + } + + /* Disable all interrupts. */ + + stm32_putreg(0, STM32_OTGFS_GINTMSK); + + /* Clear any pending USB_OTG Interrupts */ + + stm32_putreg(0xffffffff, STM32_OTGFS_GOTGINT); + + /* Clear any pending interrupts */ + + stm32_putreg(0xbfffffff, STM32_OTGFS_GINTSTS); + + /* Enable the interrupts in the INTMSK */ + + regval = (OTGFS_GINT_RXFLVL | OTGFS_GINT_USBSUSP | OTGFS_GINT_ENUMDNE | + OTGFS_GINT_IEP | OTGFS_GINT_OEP | OTGFS_GINT_USBRST); + +#ifdef CONFIG_USBDEV_ISOCHRONOUS + regval |= (OTGFS_GINT_IISOIXFR | OTGFS_GINT_IISOOXFR); +#endif + +#ifdef CONFIG_USBDEV_SOFINTERRUPT + regval |= OTGFS_GINT_SOF; +#endif + +#ifdef CONFIG_USBDEV_VBUSSENSING + regval |= (OTGFS_GINT_OTG | OTGFS_GINT_SRQ); +#endif + +#ifdef CONFIG_DEBUG_USB + regval |= OTGFS_GINT_MMIS; +#endif + + stm32_putreg(regval, STM32_OTGFS_GINTMSK); + + /* Enable the USB global interrupt by setting GINTMSK in the global OTG + * FS AHB configuration register. + */ + + stm32_putreg(OTGFS_GAHBCFG_GINTMSK | OTGFS_GAHBCFG_TXFELVL, STM32_OTGFS_GAHBCFG); +} + +/******************************************************************************* + * Public Functions + *******************************************************************************/ + +/******************************************************************************* + * Name: up_usbinitialize + * + * Description: + * Initialize USB hardware. + * + * Assumptions: + * - This function is called very early in the initialization sequence + * - PLL and GIO pin initialization is not performed here but should been in + * the low-level boot logic: PLL1 must be configured for operation at 48MHz + * and P0.23 and PO.31 in PINSEL1 must be configured for Vbus and USB connect + * LED. + * + *******************************************************************************/ + +void up_usbinitialize(void) +{ + /* At present, there is only a single OTG FS device support. Hence it is + * pre-allocated as g_otgfsdev. However, in most code, the private data + * structure will be referenced using the 'priv' pointer (rather than the + * global data) in order to simplify any future support for multiple devices. + */ + + FAR struct stm32_usbdev_s *priv = &g_otgfsdev; + int ret; + + usbtrace(TRACE_DEVINIT, 0); + + /* Here we assume that: + * + * 1. GPIOA and OTG FS peripheral clocking has already been enabled as part + * of the boot sequence. + * 2. Board-specific logic has already enabled other board specific GPIOs + * for things like soft pull-up, VBUS sensing, power controls, and over- + * current detection. + */ + + /* Configure OTG FS alternate function pins */ + + stm32_configgpio(GPIO_OTGFS_DM); + stm32_configgpio(GPIO_OTGFS_DP); + stm32_configgpio(GPIO_OTGFS_ID); + stm32_configgpio(GPIO_OTGFS_SOF); + + /* Uninitialize the hardware so that we know that we are starting from a + * known state. */ + + up_usbuninitialize(); + + /* Initialie the driver data structure */ + + stm32_swinitialize(priv); + + /* Attach the OTG FS interrupt handler */ + + ret = irq_attach(STM32_IRQ_OTGFS, stm32_usbinterrupt); + if (ret < 0) + { + udbg("irq_attach failed\n", ret); + goto errout; + } + + /* Initialize the USB OTG core */ + + stm32_hwinitialize(priv); + + /* Disconnect device */ + + stm32_pullup(&priv->usbdev, false); + + /* Reset/Re-initialize the USB hardware */ + + stm32_usbreset(priv); + + /* Enable USB controller interrupts at the NVIC */ + + up_enable_irq(STM32_IRQ_OTGFS); + + /* Set the interrrupt priority */ + + up_prioritize_irq(STM32_IRQ_OTGFS, CONFIG_OTGFS_PRI); + return; + +errout: + up_usbuninitialize(); +} + +/******************************************************************************* + * Name: up_usbuninitialize + *******************************************************************************/ + +void up_usbuninitialize(void) +{ + /* At present, there is only a single OTG FS device support. Hence it is + * pre-allocated as g_otgfsdev. However, in most code, the private data + * structure will be referenced using the 'priv' pointer (rather than the + * global data) in order to simplify any future support for multiple devices. + */ + + FAR struct stm32_usbdev_s *priv = &g_otgfsdev; + irqstate_t flags; + int i; + + usbtrace(TRACE_DEVUNINIT, 0); + + if (priv->driver) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DRIVERREGISTERED), 0); + usbdev_unregister(priv->driver); + } + + /* Disconnect device */ + + flags = irqsave(); + stm32_pullup(&priv->usbdev, false); + priv->usbdev.speed = USB_SPEED_UNKNOWN; + + /* Disable and detach IRQs */ + + up_disable_irq(STM32_IRQ_OTGFS); + irq_detach(STM32_IRQ_OTGFS); + + /* Disable all endpoint interrupts */ + + for (i = 0; i < STM32_NENDPOINTS; i++) + { + stm32_putreg(0xff, STM32_OTGFS_DIEPINT(i)); + stm32_putreg(0xff, STM32_OTGFS_DOEPINT(i)); + } + + stm32_putreg(0, STM32_OTGFS_DIEPMSK); + stm32_putreg(0, STM32_OTGFS_DOEPMSK); + stm32_putreg(0, STM32_OTGFS_DAINTMSK); + stm32_putreg(0xffffffff, STM32_OTGFS_DAINT); + + /* Flush the FIFOs */ + + stm32_txfifo_flush(OTGFS_GRSTCTL_TXFNUM_DALL); + stm32_rxfifo_flush(); + + /* TODO: Turn off USB power and clocking */ + + priv->devstate = DEVSTATE_DEFAULT; + irqrestore(flags); +} + +/******************************************************************************* + * Name: usbdev_register + * + * Description: + * Register a USB device class driver. The class driver's bind() method will be + * called to bind it to a USB device driver. + * + *******************************************************************************/ + +int usbdev_register(struct usbdevclass_driver_s *driver) +{ + /* At present, there is only a single OTG FS device support. Hence it is + * pre-allocated as g_otgfsdev. However, in most code, the private data + * structure will be referenced using the 'priv' pointer (rather than the + * global data) in order to simplify any future support for multiple devices. + */ + + FAR struct stm32_usbdev_s *priv = &g_otgfsdev; + int ret; + + usbtrace(TRACE_DEVREGISTER, 0); + +#ifdef CONFIG_DEBUG + if (!driver || !driver->ops->bind || !driver->ops->unbind || + !driver->ops->disconnect || !driver->ops->setup) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } + + if (priv->driver) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DRIVER), 0); + return -EBUSY; + } +#endif + + /* First hook up the driver */ + + priv->driver = driver; + + /* Then bind the class driver */ + + ret = CLASS_BIND(driver, &priv->usbdev); + if (ret) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BINDFAILED), (uint16_t)-ret); + priv->driver = NULL; + } + else + { + /* Enable USB controller interrupts */ + + up_enable_irq(STM32_IRQ_OTGFS); + + /* FIXME: nothing seems to call DEV_CONNECT(), but we need to set + * the RS bit to enable the controller. It kind of makes sense + * to do this after the class has bound to us... + * GEN: This bug is really in the class driver. It should make the + * soft connect when it is ready to be enumerated. I have added + * that logic to the class drivers but left this logic here. + */ + + stm32_pullup(&priv->usbdev, true); + priv->usbdev.speed = USB_SPEED_FULL; + } + + return ret; +} + +/******************************************************************************* + * Name: usbdev_unregister + * + * Description: + * Un-register usbdev class driver.If the USB device is connected to a USB host, + * it will first disconnect(). The driver is also requested to unbind() and clean + * up any device state, before this procedure finally returns. + * + *******************************************************************************/ + +int usbdev_unregister(struct usbdevclass_driver_s *driver) +{ + /* At present, there is only a single OTG FS device support. Hence it is + * pre-allocated as g_otgfsdev. However, in most code, the private data + * structure will be referenced using the 'priv' pointer (rather than the + * global data) in order to simplify any future support for multiple devices. + */ + + FAR struct stm32_usbdev_s *priv = &g_otgfsdev; + irqstate_t flags; + + usbtrace(TRACE_DEVUNREGISTER, 0); + +#ifdef CONFIG_DEBUG + if (driver != priv->driver) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } +#endif + + /* Reset the hardware and cancel all requests. All requests must be + * canceled while the class driver is still bound. + */ + + flags = irqsave(); + stm32_usbreset(priv); + + /* Unbind the class driver */ + + CLASS_UNBIND(driver, &priv->usbdev); + + /* Disable USB controller interrupts */ + + up_disable_irq(STM32_IRQ_OTGFS); + + /* Disconnect device */ + + stm32_pullup(&priv->usbdev, false); + + /* Unhook the driver */ + + priv->driver = NULL; + irqrestore(flags); + + return OK; +} + +#endif /* CONFIG_USBDEV && CONFIG_STM32_OTGFSDEV */ diff --git a/nuttx/arch/arm/src/stm32/stm32_pm.h b/nuttx/arch/arm/src/stm32/stm32_pm.h new file mode 100644 index 0000000000..be040d296c --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_pm.h @@ -0,0 +1,142 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_pm.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_PM_H +#define __ARCH_ARM_SRC_STM32_STM32_PM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "chip.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + + #ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_pmstop + * + * Description: + * Enter STOP mode. + * + * Input Parameters: + * lpds - true: To further reduce power consumption in Stop mode, put the + * internal voltage regulator in low-power mode using the LPDS bit + * of the Power control register (PWR_CR). + * + * Returned Value: + * Zero means that the STOP was successfully entered and the system has + * been re-awakened. The internal volatage regulator is back to its + * original state. Otherwise, STOP mode did not occur and a negated + * errno value is returned to indicate the cause of the failure. + * + ****************************************************************************/ + +EXTERN int stm32_pmstop(bool lpds); + +/**************************************************************************** + * Name: stm32_pmstandby + * + * Description: + * Enter STANDBY mode. + * + * Input Parameters: + * None + * + * Returned Value. + * On success, this function will not return (STANDBY mode can only be + * terminated with a reset event). Otherwise, STANDBY mode did not occur + * and a negated errno value is returned to indicate the cause of the + * failure. + * + ****************************************************************************/ + +EXTERN int stm32_pmstandby(void); + +/**************************************************************************** + * Name: stm32_pmsleep + * + * Description: + * Enter SLEEP mode. + * + * Input Parameters: + * sleeponexit - true: SLEEPONEXIT bit is set when the WFI instruction is + * executed, the MCU enters Sleep mode as soon as it + * exits the lowest priority ISR. + * - false: SLEEPONEXIT bit is cleared, the MCU enters Sleep mode + * as soon as WFI or WFE instruction is executed. + * Returned Value: + * Zero means that the STOP was successfully entered and the system has + * been re-awakened. The internal volatage regulator is back to its + * original state. Otherwise, STOP mode did not occur and a negated + * errno value is returned to indicate the cause of the failure. + * + ****************************************************************************/ + +EXTERN void stm32_pmsleep(bool sleeponexit); + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_ARM_SRC_STM32_STM32_PM_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_pminitialize.c b/nuttx/arch/arm/src/stm32/stm32_pminitialize.c new file mode 100644 index 0000000000..a1f44a7f41 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_pminitialize.c @@ -0,0 +1,94 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_pminitialize.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "up_internal.h" +#include "stm32_pm.h" + +#ifdef CONFIG_PM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_pminitialize + * + * Description: + * This function is called by MCU-specific logic at power-on reset in + * order to provide one-time initialization the power management subystem. + * This function must be called *very* early in the intialization sequence + * *before* any other device drivers are initialized (since they may + * attempt to register with the power management subsystem). + * + * Input parameters: + * None. + * + * Returned value: + * None. + * + ****************************************************************************/ + +void up_pminitialize(void) +{ + /* Then initialize the NuttX power management subsystem proper */ + + pm_initialize(); +} + +#endif /* CONFIG_PM */ diff --git a/nuttx/arch/arm/src/stm32/stm32_pmsleep.c b/nuttx/arch/arm/src/stm32/stm32_pmsleep.c new file mode 100644 index 0000000000..3027b99a78 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_pmsleep.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_pmsleep.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * Diego Sanchez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "up_arch.h" +#include "nvic.h" +#include "stm32_pwr.h" +#include "stm32_pm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_pmsleep + * + * Description: + * Enter SLEEP mode. + * + * Input Parameters: + * sleeponexit - true: SLEEPONEXIT bit is set when the WFI instruction is + * executed, the MCU enters Sleep mode as soon as it + * exits the lowest priority ISR. + * - false: SLEEPONEXIT bit is cleared, the MCU enters Sleep mode + * as soon as WFI or WFE instruction is executed. + * Returned Value: + * Zero means that the STOP was successfully entered and the system has + * been re-awakened. The internal volatage regulator is back to its + * original state. Otherwise, STOP mode did not occur and a negated + * errno value is returned to indicate the cause of the failure. + * + ****************************************************************************/ + +void stm32_pmsleep(bool sleeponexit) +{ + uint32_t regval; + + /* Clear SLEEPDEEP bit of Cortex System Control Register */ + + regval = getreg32(NVIC_SYSCON); + regval &= ~NVIC_SYSCON_SLEEPDEEP; + if (sleeponexit) + { + regval |= NVIC_SYSCON_SLEEPONEXIT; + } + else + { + regval &= ~NVIC_SYSCON_SLEEPONEXIT; + } + + putreg32(regval, NVIC_SYSCON); + + /* Sleep until the wakeup interrupt or event occurs */ + +#ifdef CONFIG_PM_WFE + /* Mode: SLEEP + Entry with WFE */ + + asm("wfe"); +#else + /* Mode: SLEEP + Entry with WFI */ + + asm("wfi"); +#endif +} diff --git a/nuttx/arch/arm/src/stm32/stm32_pmstandby.c b/nuttx/arch/arm/src/stm32/stm32_pmstandby.c new file mode 100644 index 0000000000..467edaec2a --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_pmstandby.c @@ -0,0 +1,109 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_pmstandby.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "up_arch.h" +#include "nvic.h" +#include "stm32_pwr.h" +#include "stm32_pm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_pmstandby + * + * Description: + * Enter STANDBY mode. + * + * Input Parameters: + * None + * + * Returned Value. + * On success, this function will not return (STANDBY mode can only be + * terminated with a reset event). Otherwise, STANDBY mode did not occur + * and a negated errno value is returned to indicate the cause of the + * failure. + * + ****************************************************************************/ + +int stm32_pmstandby(void) +{ + uint32_t regval; + + /* Clear the Wake-Up Flag by setting the CWUF bit in the power control + * register. + */ + + regval = getreg32(STM32_PWR_CR); + regval |= PWR_CR_CWUF; + putreg32(regval, STM32_PWR_CR); + + /* Set the Power Down Deep Sleep (PDDS) bit in the power control register. */ + + regval |= PWR_CR_PDDS; + putreg32(regval, STM32_PWR_CR); + + /* Set SLEEPDEEP bit of Cortex System Control Register */ + + regval = getreg32(NVIC_SYSCON); + regval |= NVIC_SYSCON_SLEEPDEEP; + putreg32(regval, NVIC_SYSCON); + + /* Sleep until the wakeup reset occurs */ + + asm("wfi"); + return OK; /* Won't get here */ +} diff --git a/nuttx/arch/arm/src/stm32/stm32_pmstop.c b/nuttx/arch/arm/src/stm32/stm32_pmstop.c new file mode 100644 index 0000000000..14ce63b555 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_pmstop.c @@ -0,0 +1,122 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_pmstop.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "up_arch.h" +#include "nvic.h" +#include "stm32_pwr.h" +#include "stm32_pm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_pmstop + * + * Description: + * Enter STOP mode. + * + * Input Parameters: + * lpds - true: To further reduce power consumption in Stop mode, put the + * internal voltage regulator in low-power mode using the LPDS bit + * of the Power control register (PWR_CR). + * + * Returned Value: + * Zero means that the STOP was successfully entered and the system has + * been re-awakened. The internal volatage regulator is back to its + * original state. Otherwise, STOP mode did not occur and a negated + * errno value is returned to indicate the cause of the failure. + * + ****************************************************************************/ + +int stm32_pmstop(bool lpds) +{ + uint32_t regval; + + /* Clear the Power Down Deep Sleep (PDDS) and the Low Power Deep Sleep + * (LPDS)) bits in the power control register. + */ + + regval = getreg32(STM32_PWR_CR); + regval &= ~(PWR_CR_LPDS | PWR_CR_PDDS); + + /* Set the Low Power Deep Sleep (LPDS) bit if so requested */ + + if (lpds) + { + regval |= PWR_CR_LPDS; + } + + putreg32(regval, STM32_PWR_CR); + + /* Set SLEEPDEEP bit of Cortex System Control Register */ + + regval = getreg32(NVIC_SYSCON); + regval |= NVIC_SYSCON_SLEEPDEEP; + putreg32(regval, NVIC_SYSCON); + + /* Sleep until the wakeup interrupt or event occurs */ + +#ifdef CONFIG_PM_WFE + /* Mode: SLEEP + Entry with WFE */ + + asm("wfe"); +#else + /* Mode: SLEEP + Entry with WFI */ + + asm("wfi"); +#endif + return OK; +} diff --git a/nuttx/arch/arm/src/stm32/stm32_pwm.c b/nuttx/arch/arm/src/stm32/stm32_pwm.c new file mode 100644 index 0000000000..a3ef23e57a --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_pwm.c @@ -0,0 +1,1525 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_pwm.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "up_internal.h" +#include "up_arch.h" + +#include "chip.h" +#include "stm32_pwm.h" +#include "stm32_internal.h" + +/* This module then only compiles if there is at least one enabled timer + * intended for use with the PWM upper half driver. + */ + +#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM2_PWM) || \ + defined(CONFIG_STM32_TIM3_PWM) || defined(CONFIG_STM32_TIM4_PWM) || \ + defined(CONFIG_STM32_TIM5_PWM) || defined(CONFIG_STM32_TIM8_PWM) || \ + defined(CONFIG_STM32_TIM9_PWM) || defined(CONFIG_STM32_TIM10_PWM) || \ + defined(CONFIG_STM32_TIM11_PWM) || defined(CONFIG_STM32_TIM12_PWM) || \ + defined(CONFIG_STM32_TIM13_PWM) || defined(CONFIG_STM32_TIM14_PWM) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* PWM/Timer Definitions ****************************************************/ +/* The following definitions are used to identify the various time types */ + +#define TIMTYPE_BASIC 0 /* Basic timers: TIM6-7 */ +#define TIMTYPE_GENERAL16 1 /* General 16-bit timers: TIM2-5 on F1 */ +#define TIMTYPE_COUNTUP16 2 /* General 16-bit count-up timers: TIM9-14 on F4 */ +#define TIMTYPE_GENERAL32 3 /* General 32-bit timers: TIM2-5 on F4 */ +#define TIMTYPE_ADVANCED 4 /* Advanced timers: TIM1-8 */ + +#define TIMTYPE_TIM1 TIMTYPE_ADVANCED +#ifdef CONFIG_STM32_STM32F10XX +# define TIMTYPE_TIM2 TIMTYPE_GENERAL16 +# define TIMTYPE_TIM3 TIMTYPE_GENERAL16 +# define TIMTYPE_TIM4 TIMTYPE_GENERAL16 +# define TIMTYPE_TIM5 TIMTYPE_GENERAL16 +#else +# define TIMTYPE_TIM2 TIMTYPE_GENERAL32 +# define TIMTYPE_TIM3 TIMTYPE_GENERAL32 +# define TIMTYPE_TIM4 TIMTYPE_GENERAL32 +# define TIMTYPE_TIM5 TIMTYPE_GENERAL32 +#endif +#define TIMTYPE_TIM6 TIMTYPE_BASIC +#define TIMTYPE_TIM7 TIMTYPE_BASIC +#define TIMTYPE_TIM8 TIMTYPE_ADVANCED +#define TIMTYPE_TIM9 TIMTYPE_COUNTUP16 +#define TIMTYPE_TIM10 TIMTYPE_COUNTUP16 +#define TIMTYPE_TIM11 TIMTYPE_COUNTUP16 +#define TIMTYPE_TIM12 TIMTYPE_COUNTUP16 +#define TIMTYPE_TIM13 TIMTYPE_COUNTUP16 +#define TIMTYPE_TIM14 TIMTYPE_COUNTUP16 + +/* Debug ********************************************************************/ +/* Non-standard debug that may be enabled just for testing PWM */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_PWM +#endif + +#ifdef CONFIG_DEBUG_PWM +# define pwmdbg dbg +# define pwmlldbg lldbg +# ifdef CONFIG_DEBUG_VERBOSE +# define pwmvdbg vdbg +# define pwmllvdbg llvdbg +# define pwm_dumpgpio(p,m) stm32_dumpgpio(p,m) +# else +# define pwmlldbg(x...) +# define pwmllvdbg(x...) +# define pwm_dumpgpio(p,m) +# endif +#else +# define pwmdbg(x...) +# define pwmlldbg(x...) +# define pwmvdbg(x...) +# define pwmllvdbg(x...) +# define pwm_dumpgpio(p,m) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ +/* This structure representst the state of one PWM timer */ + +struct stm32_pwmtimer_s +{ + FAR const struct pwm_ops_s *ops; /* PWM operations */ + uint8_t timid; /* Timer ID {1,...,14} */ + uint8_t channel; /* Timer output channel: {1,..4} */ + uint8_t timtype; /* See the TIMTYPE_* definitions */ +#ifdef CONFIG_PWM_PULSECOUNT + uint8_t irq; /* Timer update IRQ */ + uint8_t prev; /* The previous value of the RCR (pre-loaded) */ + uint8_t curr; /* The current value of the RCR (pre-loaded) */ + uint32_t count; /* Remaining pluse count */ +#endif + uint32_t base; /* The base address of the timer */ + uint32_t pincfg; /* Output pin configuration */ + uint32_t pclk; /* The frequency of the peripheral clock + * that drives the timer module. */ +#ifdef CONFIG_PWM_PULSECOUNT + FAR void * handle; /* Handle used for upper-half callback */ +#endif +}; + +/**************************************************************************** + * Static Function Prototypes + ****************************************************************************/ +/* Register access */ + +static uint16_t pwm_getreg(struct stm32_pwmtimer_s *priv, int offset); +static void pwm_putreg(struct stm32_pwmtimer_s *priv, int offset, uint16_t value); + +#if defined(CONFIG_DEBUG_PWM) && defined(CONFIG_DEBUG_VERBOSE) +static void pwm_dumpregs(struct stm32_pwmtimer_s *priv, FAR const char *msg); +#else +# define pwm_dumpregs(priv,msg) +#endif + +/* Timer management */ + +static int pwm_timer(FAR struct stm32_pwmtimer_s *priv, + FAR const struct pwm_info_s *info); + +#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM)) +static int pwm_interrupt(struct stm32_pwmtimer_s *priv); +#if defined(CONFIG_STM32_TIM1_PWM) +static int pwm_tim1interrupt(int irq, void *context); +#endif +#if defined(CONFIG_STM32_TIM8_PWM) +static int pwm_tim8interrupt(int irq, void *context); +#endif +static uint8_t pwm_pulsecount(uint32_t count); +#endif + +/* PWM driver methods */ + +static int pwm_setup(FAR struct pwm_lowerhalf_s *dev); +static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev); + +#ifdef CONFIG_PWM_PULSECOUNT +static int pwm_start(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info, + FAR void *handle); +#else +static int pwm_start(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info); +#endif + +static int pwm_stop(FAR struct pwm_lowerhalf_s *dev); +static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, + int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* This is the list of lower half PWM driver methods used by the upper half driver */ + +static const struct pwm_ops_s g_pwmops = +{ + .setup = pwm_setup, + .shutdown = pwm_shutdown, + .start = pwm_start, + .stop = pwm_stop, + .ioctl = pwm_ioctl, +}; + +#ifdef CONFIG_STM32_TIM1_PWM +static struct stm32_pwmtimer_s g_pwm1dev = +{ + .ops = &g_pwmops, + .timid = 1, + .channel = CONFIG_STM32_TIM1_CHANNEL, + .timtype = TIMTYPE_TIM1, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32_IRQ_TIM1UP, +#endif + .base = STM32_TIM1_BASE, + .pincfg = PWM_TIM1_PINCFG, + .pclk = STM32_APB2_TIM1_CLKIN, +}; +#endif + +#ifdef CONFIG_STM32_TIM2_PWM +static struct stm32_pwmtimer_s g_pwm2dev = +{ + .ops = &g_pwmops, + .timid = 2, + .channel = CONFIG_STM32_TIM2_CHANNEL, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32_IRQ_TIM2, +#endif + .timtype = TIMTYPE_TIM2, + .base = STM32_TIM2_BASE, + .pincfg = PWM_TIM2_PINCFG, + .pclk = STM32_APB1_TIM2_CLKIN, +}; +#endif + +#ifdef CONFIG_STM32_TIM3_PWM +static struct stm32_pwmtimer_s g_pwm3dev = +{ + .ops = &g_pwmops, + .timid = 3, + .channel = CONFIG_STM32_TIM3_CHANNEL, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32_IRQ_TIM3, +#endif + .timtype = TIMTYPE_TIM3, + .base = STM32_TIM3_BASE, + .pincfg = PWM_TIM3_PINCFG, + .pclk = STM32_APB1_TIM3_CLKIN, +}; +#endif + +#ifdef CONFIG_STM32_TIM4_PWM +static struct stm32_pwmtimer_s g_pwm4dev = +{ + .ops = &g_pwmops, + .timid = 4, + .channel = CONFIG_STM32_TIM4_CHANNEL, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32_IRQ_TIM4, +#endif + .timtype = TIMTYPE_TIM4, + .base = STM32_TIM4_BASE, + .pincfg = PWM_TIM4_PINCFG, + .pclk = STM32_APB1_TIM4_CLKIN, +}; +#endif + +#ifdef CONFIG_STM32_TIM5_PWM +static struct stm32_pwmtimer_s g_pwm5dev = +{ + .ops = &g_pwmops, + .timid = 5, + .channel = CONFIG_STM32_TIM5_CHANNEL, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32_IRQ_TIM5, +#endif + .timtype = TIMTYPE_TIM5, + .base = STM32_TIM5_BASE, + .pincfg = PWM_TIM5_PINCFG, + .pclk = STM32_APB1_TIM5_CLKIN, +}; +#endif + +#ifdef CONFIG_STM32_TIM8_PWM +static struct stm32_pwmtimer_s g_pwm8dev = +{ + .ops = &g_pwmops, + .timid = 8, + .channel = CONFIG_STM32_TIM8_CHANNEL, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32_IRQ_TIM8UP, +#endif + .timtype = TIMTYPE_TIM8, + .base = STM32_TIM8_BASE, + .pincfg = PWM_TIM8_PINCFG, + .pclk = STM32_APB2_TIM8_CLKIN, +}; +#endif + +#ifdef CONFIG_STM32_TIM9_PWM +static struct stm32_pwmtimer_s g_pwm9dev = +{ + .ops = &g_pwmops, + .timid = 9, + .channel = CONFIG_STM32_TIM9_CHANNEL, + .timtype = TIMTYPE_TIM9, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32_IRQ_TIM9, +#endif + .base = STM32_TIM9_BASE, + .pincfg = PWM_TIM9_PINCFG, + .pclk = STM32_APB2_TIM9_CLKIN, +}; +#endif + +#ifdef CONFIG_STM32_TIM10_PWM +static struct stm32_pwmtimer_s g_pwm10dev = +{ + .ops = &g_pwmops, + .timid = 10, + .channel = CONFIG_STM32_TIM10_CHANNEL, + .timtype = TIMTYPE_TIM10, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32_IRQ_TIM10, +#endif + .base = STM32_TIM10_BASE, + .pincfg = PWM_TIM10_PINCFG, + .pclk = STM32_APB2_TIM10_CLKIN, +}; +#endif + +#ifdef CONFIG_STM32_TIM11_PWM +static struct stm32_pwmtimer_s g_pwm11dev = +{ + .ops = &g_pwmops, + .timid = 11, + .channel = CONFIG_STM32_TIM11_CHANNEL, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32_IRQ_TIM11, +#endif + .timtype = TIMTYPE_TIM11, + .base = STM32_TIM11_BASE, + .pincfg = PWM_TIM11_PINCFG, + .pclk = STM32_APB2_TIM11_CLKIN, +}; +#endif + +#ifdef CONFIG_STM32_TIM12_PWM +static struct stm32_pwmtimer_s g_pwm12dev = +{ + .ops = &g_pwmops, + .timid = 12, + .channel = CONFIG_STM32_TIM12_CHANNEL, + .timtype = TIMTYPE_TIM12, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32_IRQ_TIM12, +#endif + .base = STM32_TIM12_BASE, + .pincfg = PWM_TIM12_PINCFG, + .pclk = STM32_APB1_TIM12_CLKIN, +}; +#endif + +#ifdef CONFIG_STM32_TIM13_PWM +static struct stm32_pwmtimer_s g_pwm13dev = +{ + .ops = &g_pwmops, + .timid = 13, + .channel = CONFIG_STM32_TIM13_CHANNEL, + .timtype = TIMTYPE_TIM13, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32_IRQ_TIM13, +#endif + .base = STM32_TIM13_BASE, + .pincfg = PWM_TIM13_PINCFG, + .pclk = STM32_APB1_TIM13_CLKIN, +}; +#endif + +#ifdef CONFIG_STM32_TIM14_PWM +static struct stm32_pwmtimer_s g_pwm14dev = +{ + .ops = &g_pwmops, + .timid = 14, + .channel = CONFIG_STM32_TIM14_CHANNEL, + .timtype = TIMTYPE_TIM14, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32_IRQ_TIM14, +#endif + .base = STM32_TIM14_BASE, + .pincfg = PWM_TIM14_PINCFG, + .pclk = STM32_APB1_TIM14_CLKIN, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pwm_getreg + * + * Description: + * Read the value of an PWM timer register. + * + * Input Parameters: + * priv - A reference to the PWM block status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ****************************************************************************/ + +static uint16_t pwm_getreg(struct stm32_pwmtimer_s *priv, int offset) +{ + return getreg16(priv->base + offset); +} + +/**************************************************************************** + * Name: pwm_putreg + * + * Description: + * Read the value of an PWM timer register. + * + * Input Parameters: + * priv - A reference to the PWM block status + * offset - The offset to the register to read + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void pwm_putreg(struct stm32_pwmtimer_s *priv, int offset, uint16_t value) +{ + putreg16(value, priv->base + offset); +} + +/**************************************************************************** + * Name: pwm_dumpregs + * + * Description: + * Dump all timer registers. + * + * Input parameters: + * priv - A reference to the PWM block status + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_PWM) && defined(CONFIG_DEBUG_VERBOSE) +static void pwm_dumpregs(struct stm32_pwmtimer_s *priv, FAR const char *msg) +{ + pwmvdbg("%s:\n", msg); + pwmvdbg(" CR1: %04x CR2: %04x SMCR: %04x DIER: %04x\n", + pwm_getreg(priv, STM32_GTIM_CR1_OFFSET), + pwm_getreg(priv, STM32_GTIM_CR2_OFFSET), + pwm_getreg(priv, STM32_GTIM_SMCR_OFFSET), + pwm_getreg(priv, STM32_GTIM_DIER_OFFSET)); + pwmvdbg(" SR: %04x EGR: %04x CCMR1: %04x CCMR2: %04x\n", + pwm_getreg(priv, STM32_GTIM_SR_OFFSET), + pwm_getreg(priv, STM32_GTIM_EGR_OFFSET), + pwm_getreg(priv, STM32_GTIM_CCMR1_OFFSET), + pwm_getreg(priv, STM32_GTIM_CCMR2_OFFSET)); + pwmvdbg(" CCER: %04x CNT: %04x PSC: %04x ARR: %04x\n", + pwm_getreg(priv, STM32_GTIM_CCER_OFFSET), + pwm_getreg(priv, STM32_GTIM_CNT_OFFSET), + pwm_getreg(priv, STM32_GTIM_PSC_OFFSET), + pwm_getreg(priv, STM32_GTIM_ARR_OFFSET)); + pwmvdbg(" CCR1: %04x CCR2: %04x CCR3: %04x CCR4: %04x\n", + pwm_getreg(priv, STM32_GTIM_CCR1_OFFSET), + pwm_getreg(priv, STM32_GTIM_CCR2_OFFSET), + pwm_getreg(priv, STM32_GTIM_CCR3_OFFSET), + pwm_getreg(priv, STM32_GTIM_CCR4_OFFSET)); +#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM) + if (priv->timtype == TIMTYPE_ADVANCED) + { + pwmvdbg(" RCR: %04x BDTR: %04x DCR: %04x DMAR: %04x\n", + pwm_getreg(priv, STM32_ATIM_RCR_OFFSET), + pwm_getreg(priv, STM32_ATIM_BDTR_OFFSET), + pwm_getreg(priv, STM32_ATIM_DCR_OFFSET), + pwm_getreg(priv, STM32_ATIM_DMAR_OFFSET)); + } + else +#endif + { + pwmvdbg(" DCR: %04x DMAR: %04x\n", + pwm_getreg(priv, STM32_GTIM_DCR_OFFSET), + pwm_getreg(priv, STM32_GTIM_DMAR_OFFSET)); + } +} +#endif + +/**************************************************************************** + * Name: pwm_timer + * + * Description: + * (Re-)initialize the timer resources and start the pulsed output + * + * Input parameters: + * priv - A reference to the lower half PWM driver state structure + * info - A reference to the characteristics of the pulsed output + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_timer(FAR struct stm32_pwmtimer_s *priv, + FAR const struct pwm_info_s *info) +{ + /* Calculated values */ + + uint32_t prescaler; + uint32_t timclk; + uint32_t reload; + uint32_t ccr; + + /* Register contents */ + + uint16_t cr1; + uint16_t ccer; + uint16_t cr2; + uint16_t ccmr1; + uint16_t ccmr2; + + /* New timer regiser bit settings */ + + uint16_t ccenable; + uint16_t ocmode1; + uint16_t ocmode2; + + DEBUGASSERT(priv != NULL && info != NULL); + +#ifdef CONFIG_PWM_PULSECOUNT + pwmvdbg("TIM%d channel: %d frequency: %d duty: %08x count: %d\n", + priv->timid, priv->channel, info->frequency, + info->duty, info->count); +#else + pwmvdbg("TIM%d channel: %d frequency: %d duty: %08x\n", + priv->timid, priv->channel, info->frequency, info->duty); +#endif + DEBUGASSERT(info->frequency > 0 && info->duty > 0 && + info->duty < uitoub16(100)); + + /* Disable all interrupts and DMA requests, clear all pending status */ + +#ifdef CONFIG_PWM_PULSECOUNT + pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, 0); + pwm_putreg(priv, STM32_GTIM_SR_OFFSET, 0); +#endif + + /* Calculate optimal values for the timer prescaler and for the timer reload + * register. If' frequency' is the desired frequency, then + * + * reload = timclk / frequency + * timclk = pclk / presc + * + * Or, + * + * reload = pclk / presc / frequency + * + * There are many solutions to this this, but the best solution will be the + * one that has the largest reload value and the smallest prescaler value. + * That is the solution that should give us the most accuracy in the timer + * control. Subject to: + * + * 0 <= presc <= 65536 + * 1 <= reload <= 65535 + * + * So presc = pclk / 65535 / frequency would be optimal. + * + * Example: + * + * pclk = 42 MHz + * frequency = 100 Hz + * + * prescaler = 42,000,000 / 65,535 / 100 + * = 6.4 (or 7 -- taking the ceiling always) + * timclk = 42,000,000 / 7 + * = 6,000,000 + * reload = 7,000,000 / 100 + * = 60,000 + */ + + prescaler = (priv->pclk / info->frequency + 65534) / 65535; + if (prescaler < 1) + { + prescaler = 1; + } + else if (prescaler > 65536) + { + prescaler = 65536; + } + + timclk = priv->pclk / prescaler; + + reload = timclk / info->frequency; + if (reload < 1) + { + reload = 1; + } + else if (reload > 65535) + { + reload = 65535; + } + + /* Duty cycle: + * + * duty cycle = ccr / reload (fractional value) + */ + + ccr = b16toi(info->duty * reload + b16HALF); + + pwmvdbg("TIM%d PCLK: %d frequency: %d TIMCLK: %d prescaler: %d reload: %d ccr: %d\n", + priv->timid, priv->pclk, info->frequency, timclk, prescaler, reload, ccr); + + /* Set up the timer CR1 register: + * + * 1-8 CKD[1:0] ARPE CMS[1:0] DIR OPM URS UDIS CEN + * 2-5 CKD[1:0] ARPE CMS DIR OPM URS UDIS CEN + * 6-7 ARPE OPM URS UDIS CEN + * 9-14 CKD[1:0] ARPE URS UDIS CEN + */ + + cr1 = pwm_getreg(priv, STM32_GTIM_CR1_OFFSET); + + /* Disable the timer until we get it configured */ + + cr1 &= ~GTIM_CR1_CEN; + + /* Set the counter mode for the advanced timers (1,8) and most general + * purpose timers (all 2-5, but not 9-14), i.e., all but TIMTYPE_COUNTUP16 + * and TIMTYPE_BASIC + */ + +#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM2_PWM) || \ + defined(CONFIG_STM32_TIM3_PWM) || defined(CONFIG_STM32_TIM4_PWM) || \ + defined(CONFIG_STM32_TIM5_PWM) || defined(CONFIG_STM32_TIM8_PWM) + + if (priv->timtype != TIMTYPE_BASIC && priv->timtype != TIMTYPE_COUNTUP16) + { + /* Select the Counter Mode == count up: + * + * GTIM_CR1_EDGE: The counter counts up or down depending on the + * direction bit(DIR). + * GTIM_CR1_DIR: 0: count up, 1: count down + */ + + cr1 &= ~(GTIM_CR1_DIR | GTIM_CR1_CMS_MASK); + cr1 |= GTIM_CR1_EDGE; + } +#endif + + /* Set the clock division to zero for all (but the basic timers, but there + * should be no basic timers in this context + */ + + cr1 &= ~GTIM_CR1_CKD_MASK; + pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1); + + /* Set the reload and prescaler values */ + + pwm_putreg(priv, STM32_GTIM_ARR_OFFSET, (uint16_t)reload); + pwm_putreg(priv, STM32_GTIM_PSC_OFFSET, (uint16_t)(prescaler - 1)); + + /* Set the advanced timer's repitition counter */ + +#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM) + if (priv->timtype == TIMTYPE_ADVANCED) + { + /* If a non-zero repetition count has been selected, then set the + * repitition counter to the count-1 (pwm_start() has already + * assured us that the count value is within range). + */ + +#ifdef CONFIG_PWM_PULSECOUNT + if (info->count > 0) + { + /* Save the remining count and the number of counts that will have + * elapsed on the first interrupt. + */ + + /* If the first interrupt occurs at the end end of the first + * repition count, then the count will be the same as the RCR + * value. + */ + + priv->prev = pwm_pulsecount(info->count); + pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->prev - 1); + + /* Generate an update event to reload the prescaler. This should + * preload the RCR into active repetition counter. + */ + + pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG); + + /* Now set the value of the RCR that will be loaded on the next + * update event. + */ + + priv->count = info->count; + priv->curr = pwm_pulsecount(info->count - priv->prev); + pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1); + } + + /* Otherwise, just clear the repitition counter */ + + else +#endif + { + /* Set the repeition counter to zero */ + + pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, 0); + + /* Generate an update event to reload the prescaler */ + + pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG); + } + } + else +#endif + { + /* Generate an update event to reload the prescaler (all timers) */ + + pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG); + } + + /* Handle channel specific setup */ + + ocmode1 = 0; + ocmode2 = 0; + switch (priv->channel) + { + case 1: /* PWM Mode configuration: Channel 1 */ + { + /* Select the CCER enable bit for this channel */ + + ccenable = ATIM_CCER_CC1E; + + /* Set the CCMR1 mode values (leave CCMR2 zero) */ + + ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) | + ATIM_CCMR1_OC1PE; + + /* Set the duty cycle by writing to the CCR register for this channel */ + + pwm_putreg(priv, STM32_GTIM_CCR1_OFFSET, (uint16_t)ccr); + } + break; + + case 2: /* PWM Mode configuration: Channel 2 */ + { + /* Select the CCER enable bit for this channel */ + + ccenable = ATIM_CCER_CC2E; + + /* Set the CCMR1 mode values (leave CCMR2 zero) */ + + ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC2M_SHIFT) | + ATIM_CCMR1_OC2PE; + + /* Set the duty cycle by writing to the CCR register for this channel */ + + pwm_putreg(priv, STM32_GTIM_CCR2_OFFSET, (uint16_t)ccr); + } + break; + + case 3: /* PWM Mode configuration: Channel3 */ + { + /* Select the CCER enable bit for this channel */ + + ccenable = ATIM_CCER_CC3E; + + /* Set the CCMR2 mode values (leave CCMR1 zero) */ + + ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC3S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC3M_SHIFT) | + ATIM_CCMR2_OC3PE; + + /* Set the duty cycle by writing to the CCR register for this channel */ + + pwm_putreg(priv, STM32_GTIM_CCR3_OFFSET, (uint16_t)ccr); + } + break; + + case 4: /* PWM1 Mode configuration: Channel4 */ + { + /* Select the CCER enable bit for this channel */ + + ccenable = ATIM_CCER_CC4E; + + /* Set the CCMR2 mode values (leave CCMR1 zero) */ + + ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC4S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC4M_SHIFT) | + ATIM_CCMR2_OC4PE; + + /* Set the duty cycle by writing to the CCR register for this channel */ + + pwm_putreg(priv, STM32_GTIM_CCR4_OFFSET, (uint16_t)ccr); + } + break; + + default: + pwmdbg("No such channel: %d\n", priv->channel); + return -EINVAL; + } + + /* Disable the Channel by resetting the CCxE Bit in the CCER register */ + + ccer = pwm_getreg(priv, STM32_GTIM_CCER_OFFSET); + ccer &= ~ccenable; + pwm_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer); + + /* Fetch the CR2, CCMR1, and CCMR2 register (already have cr1 and ccer) */ + + cr2 = pwm_getreg(priv, STM32_GTIM_CR2_OFFSET); + ccmr1 = pwm_getreg(priv, STM32_GTIM_CCMR1_OFFSET); + ccmr2 = pwm_getreg(priv, STM32_GTIM_CCMR2_OFFSET); + + /* Reset the Output Compare Mode Bits and set the select output compare mode */ + + ccmr1 &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK | ATIM_CCMR1_OC1PE | + ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK | ATIM_CCMR1_OC2PE); + ccmr2 &= ~(ATIM_CCMR2_CC3S_MASK | ATIM_CCMR2_OC3M_MASK | ATIM_CCMR2_OC3PE | + ATIM_CCMR2_CC4S_MASK | ATIM_CCMR2_OC4M_MASK | ATIM_CCMR2_OC4PE); + ccmr1 |= ocmode1; + ccmr2 |= ocmode2; + + /* Reset the output polarity level of all channels (selects high polarity)*/ + + ccer &= ~(ATIM_CCER_CC1P | ATIM_CCER_CC2P | ATIM_CCER_CC3P | ATIM_CCER_CC4P); + + /* Enable the output state of the selected channel (only) */ + + ccer &= ~(ATIM_CCER_CC1E | ATIM_CCER_CC2E | ATIM_CCER_CC3E | ATIM_CCER_CC4E); + ccer |= ccenable; + + /* Some special setup for advanced timers */ + +#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM) + if (priv->timtype == TIMTYPE_ADVANCED) + { + uint16_t bdtr; + + /* Reset output N polarity level, output N state, output compare state, + * output compare N idle state. + */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE | ATIM_CCER_CC2NP | + ATIM_CCER_CC3NE | ATIM_CCER_CC3NP | ATIM_CCER_CC4NP); +#else + ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE | ATIM_CCER_CC2NP | + ATIM_CCER_CC3NE | ATIM_CCER_CC3NP); +#endif + + /* Reset the output compare and output compare N IDLE State */ + + cr2 &= ~(ATIM_CR2_OIS1 | ATIM_CR2_OIS1N | ATIM_CR2_OIS2 | ATIM_CR2_OIS2N | + ATIM_CR2_OIS3 | ATIM_CR2_OIS3N | ATIM_CR2_OIS4); + + /* Set the main output enable (MOE) bit and clear the OSSI and OSSR + * bits in the BDTR register. + */ + + bdtr = pwm_getreg(priv, STM32_ATIM_BDTR_OFFSET); + bdtr &= ~(ATIM_BDTR_OSSI | ATIM_BDTR_OSSR); + bdtr |= ATIM_BDTR_MOE; + pwm_putreg(priv, STM32_ATIM_BDTR_OFFSET, bdtr); + } +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + else +#endif +#endif +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + { + ccer &= ~(GTIM_CCER_CC1NP | GTIM_CCER_CC2NP | GTIM_CCER_CC3NP | GTIM_CCER_CC4NP); + } +#endif + + /* Save the modified register values */ + + pwm_putreg(priv, STM32_GTIM_CR2_OFFSET, cr2); + pwm_putreg(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1); + pwm_putreg(priv, STM32_GTIM_CCMR2_OFFSET, ccmr2); + pwm_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer); + + /* Set the ARR Preload Bit */ + + cr1 = pwm_getreg(priv, STM32_GTIM_CR1_OFFSET); + cr1 |= GTIM_CR1_ARPE; + pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1); + + /* Setup update interrupt. If info->count is > 0, then we can be + * assured that pwm_start() has already verified: (1) that this is an + * advanced timer, and that (2) the repetitioncount is within range. + */ + +#ifdef CONFIG_PWM_PULSECOUNT + if (info->count > 0) + { + /* Clear all pending interrupts and enable the update interrupt. */ + + pwm_putreg(priv, STM32_GTIM_SR_OFFSET, 0); + pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, ATIM_DIER_UIE); + + /* Enable the timer */ + + cr1 |= GTIM_CR1_CEN; + pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1); + + /* And enable timer interrupts at the NVIC */ + + up_enable_irq(priv->irq); + } + else +#endif + { + /* Just enable the timer, leaving all interrupts disabled */ + + cr1 |= GTIM_CR1_CEN; + pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1); + } + + pwm_dumpregs(priv, "After starting"); + return OK; +} + +/**************************************************************************** + * Name: pwm_interrupt + * + * Description: + * Handle timer interrupts. + * + * Input parameters: + * priv - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM)) +static int pwm_interrupt(struct stm32_pwmtimer_s *priv) +{ + uint16_t regval; + + /* Verify that this is an update interrupt. Nothing else is expected. */ + + regval = pwm_getreg(priv, STM32_ATIM_SR_OFFSET); + DEBUGASSERT((regval & ATIM_SR_UIF) != 0); + + /* Clear the UIF interrupt bit */ + + pwm_putreg(priv, STM32_ATIM_SR_OFFSET, regval & ~ATIM_SR_UIF); + + /* Calculate the new count by subtracting the number of pulses + * since the last interrupt. + */ + + if (priv->count <= priv->prev) + { + /* We are finished. Turn off the mast output to stop the output as + * quickly as possible. + */ + + regval = pwm_getreg(priv, STM32_ATIM_BDTR_OFFSET); + regval &= ~ATIM_BDTR_MOE; + pwm_putreg(priv, STM32_ATIM_BDTR_OFFSET, regval); + + /* Disable first interrtups, stop and reset the timer */ + + (void)pwm_stop((FAR struct pwm_lowerhalf_s *)priv); + + /* Then perform the callback into the upper half driver */ + + pwm_expired(priv->handle); + + priv->handle = NULL; + priv->count = 0; + priv->prev = 0; + priv->curr = 0; + } + else + { + /* Decrement the count of pulses remaining using the number of + * pulses generated since the last interrupt. + */ + + priv->count -= priv->prev; + + /* Set up the next RCR. Set 'prev' to the value of the RCR that + * was loaded when the update occurred (just before this interrupt) + * and set 'curr' to the current value of the RCR register (which + * will bet loaded on the next update event). + */ + + priv->prev = priv->curr; + priv->curr = pwm_pulsecount(priv->count - priv->prev); + pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1); + } + + /* Now all of the time critical stuff is done so we can do some debug output */ + + pwmllvdbg("Update interrupt SR: %04x prev: %d curr: %d count: %d\n", + regval, priv->prev, priv->curr, priv->count); + + return OK; +} +#endif + +/**************************************************************************** + * Name: pwm_tim1/8interrupt + * + * Description: + * Handle timer 1 and 8 interrupts. + * + * Input parameters: + * Standard NuttX interrupt inputs + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_STM32_TIM1_PWM) +static int pwm_tim1interrupt(int irq, void *context) +{ + return pwm_interrupt(&g_pwm1dev); +} +#endif + +#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_STM32_TIM8_PWM) +static int pwm_tim8interrupt(int irq, void *context) +{ + return pwm_interrupt(&g_pwm8dev); +} +#endif + +/**************************************************************************** + * Name: pwm_pulsecount + * + * Description: + * Pick an optimal pulse count to program the RCR. + * + * Input parameters: + * count - The total count remaining + * + * Returned Value: + * The recommended pulse count + * + ****************************************************************************/ + +#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM)) +static uint8_t pwm_pulsecount(uint32_t count) +{ + /* The the remaining pulse count is less than or equal to the maximum, the + * just return the count. + */ + + if (count <= ATIM_RCR_REP_MAX) + { + return count; + } + + /* Otherwise, we have to be careful. We do not want a small number of + * counts at the end because we might have trouble responding fast enough. + * If the remaining count is less than 150% of the maximum, then return + * half of the maximum. In this case the final sequence will be between 64 + * and 128. + */ + + else if (count < (3 * ATIM_RCR_REP_MAX / 2)) + { + return (ATIM_RCR_REP_MAX + 1) >> 1; + } + + /* Otherwise, return the maximum. The final count will be 64 or more */ + + else + { + return ATIM_RCR_REP_MAX; + } +} +#endif + +/**************************************************************************** + * Name: pwm_setup + * + * Description: + * This method is called when the driver is opened. The lower half driver + * should configure and initialize the device so that it is ready for use. + * It should not, however, output pulses until the start method is called. + * + * Input parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + * Assumptions: + * AHB1 or 2 clocking for the GPIOs and timer has already been configured + * by the RCC logic at power up. + * + ****************************************************************************/ + +static int pwm_setup(FAR struct pwm_lowerhalf_s *dev) +{ + FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev; + + pwmvdbg("TIM%d pincfg: %08x\n", priv->timid, priv->pincfg); + pwm_dumpregs(priv, "Initially"); + + /* Configure the PWM output pin, but do not start the timer yet */ + + stm32_configgpio(priv->pincfg); + pwm_dumpgpio(priv->pincfg, "PWM setup"); + return OK; +} + +/**************************************************************************** + * Name: pwm_shutdown + * + * Description: + * This method is called when the driver is closed. The lower half driver + * stop pulsed output, free any resources, disable the timer hardware, and + * put the system into the lowest possible power usage state + * + * Input parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev) +{ + FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev; + uint32_t pincfg; + + pwmvdbg("TIM%d pincfg: %08x\n", priv->timid, priv->pincfg); + + /* Make sure that the output has been stopped */ + + pwm_stop(dev); + + /* Then put the GPIO pin back to the default state */ + + pincfg = priv->pincfg & (GPIO_PORT_MASK|GPIO_PIN_MASK); + +#if defined(CONFIG_STM32_STM32F10XX) + pincfg |= (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT); +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + pincfg |= (GPIO_INPUT|GPIO_FLOAT); +#else +# error "Unrecognized STM32 chip" +#endif + + stm32_configgpio(pincfg); + return OK; +} + +/**************************************************************************** + * Name: pwm_start + * + * Description: + * (Re-)initialize the timer resources and start the pulsed output + * + * Input parameters: + * dev - A reference to the lower half PWM driver state structure + * info - A reference to the characteristics of the pulsed output + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +#ifdef CONFIG_PWM_PULSECOUNT +static int pwm_start(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info, + FAR void *handle) +{ + FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev; + + /* Check if a pulsecount has been selected */ + + if (info->count > 0) + { + /* Only the advanced timers (TIM1,8 can support the pulse counting) */ + + if (priv->timtype != TIMTYPE_ADVANCED) + { + pwmdbg("ERROR: TIM%d cannot support pulse count: %d\n", + priv->timid, info->count); + return -EPERM; + } + } + + /* Save the handle */ + + priv->handle = handle; + + /* Start the time */ + + return pwm_timer(priv, info); +} +#else +static int pwm_start(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info) +{ + FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev; + return pwm_timer(priv, info); +} +#endif + +/**************************************************************************** + * Name: pwm_stop + * + * Description: + * Stop the pulsed output and reset the timer resources + * + * Input parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + * Assumptions: + * This function is called to stop the pulsed output at anytime. This + * method is also called from the timer interrupt handler when a repetition + * count expires... automatically stopping the timer. + * + ****************************************************************************/ + +static int pwm_stop(FAR struct pwm_lowerhalf_s *dev) +{ + FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev; + uint32_t resetbit; + uint32_t regaddr; + uint32_t regval; + irqstate_t flags; + + pwmvdbg("TIM%d\n", priv->timid); + + /* Disable interrupts momentary to stop any ongoing timer processing and + * to prevent any concurrent access to the reset register. + */ + + flags = irqsave(); + + /* Disable further interrupts and stop the timer */ + + pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, 0); + pwm_putreg(priv, STM32_GTIM_SR_OFFSET, 0); + + /* Determine which timer to reset */ + + switch (priv->timid) + { +#ifdef CONFIG_STM32_TIM1_PWM + case 1: + regaddr = STM32_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM1RST; + break; +#endif +#ifdef CONFIG_STM32_TIM2_PWM + case 2: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM2RST; + break; +#endif +#ifdef CONFIG_STM32_TIM3_PWM + case 3: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM3RST; + break; +#endif +#ifdef CONFIG_STM32_TIM4_PWM + case 4: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM4RST; + break; +#endif +#ifdef CONFIG_STM32_TIM5_PWM + case 5: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM5RST; + break; +#endif +#ifdef CONFIG_STM32_TIM8_PWM + case 8: + regaddr = STM32_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM8RST; + break; +#endif +#ifdef CONFIG_STM32_TIM9_PWM + case 9: + regaddr = STM32_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM9RST; + break; +#endif +#ifdef CONFIG_STM32_TIM10_PWM + case 10: + regaddr = STM32_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM10RST; + break; +#endif +#ifdef CONFIG_STM32_TIM11_PWM + case 11: + regaddr = STM32_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM11RST; + break; +#endif +#ifdef CONFIG_STM32_TIM12_PWM + case 12: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM12RST; + break; +#endif +#ifdef CONFIG_STM32_TIM13_PWM + case 13: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM13RST; + break; +#endif +#ifdef CONFIG_STM32_TIM14_PWM + case 14: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM14RST; + break; +#endif + } + + /* Reset the timer - stopping the output and putting the timer back + * into a state where pwm_start() can be called. + */ + + regval = getreg32(regaddr); + regval |= resetbit; + putreg32(regval, regaddr); + + regval &= ~resetbit; + putreg32(regval, regaddr); + irqrestore(flags); + + pwmvdbg("regaddr: %08x resetbit: %08x\n", regaddr, resetbit); + pwm_dumpregs(priv, "After stop"); + return OK; +} + +/**************************************************************************** + * Name: pwm_ioctl + * + * Description: + * Lower-half logic may support platform-specific ioctl commands + * + * Input parameters: + * dev - A reference to the lower half PWM driver state structure + * cmd - The ioctl command + * arg - The argument accompanying the ioctl command + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg) +{ +#ifdef CONFIG_DEBUG_PWM + FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev; + + /* There are no platform-specific ioctl commands */ + + pwmvdbg("TIM%d\n", priv->timid); +#endif + return -ENOTTY; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_pwminitialize + * + * Description: + * Initialize one timer for use with the upper_level PWM driver. + * + * Input Parameters: + * timer - A number identifying the timer use. The number of valid timer + * IDs varies with the STM32 MCU and MCU family but is somewhere in + * the range of {1,..,14}. + * + * Returned Value: + * On success, a pointer to the STM32 lower half PWM driver is returned. + * NULL is returned on any failure. + * + ****************************************************************************/ + +FAR struct pwm_lowerhalf_s *stm32_pwminitialize(int timer) +{ + FAR struct stm32_pwmtimer_s *lower; + + pwmvdbg("TIM%d\n", timer); + + switch (timer) + { +#ifdef CONFIG_STM32_TIM1_PWM + case 1: + lower = &g_pwm1dev; + + /* Attach but disable the TIM1 update interrupt */ + +#ifdef CONFIG_PWM_PULSECOUNT + irq_attach(lower->irq, pwm_tim1interrupt); + up_disable_irq(lower->irq); +#endif + break; +#endif + +#ifdef CONFIG_STM32_TIM2_PWM + case 2: + lower = &g_pwm2dev; + break; +#endif + +#ifdef CONFIG_STM32_TIM3_PWM + case 3: + lower = &g_pwm3dev; + break; +#endif + +#ifdef CONFIG_STM32_TIM4_PWM + case 4: + lower = &g_pwm4dev; + break; +#endif + +#ifdef CONFIG_STM32_TIM5_PWM + case 5: + lower = &g_pwm5dev; + break; +#endif + +#ifdef CONFIG_STM32_TIM8_PWM + case 8: + lower = &g_pwm8dev; + + /* Attach but disable the TIM8 update interrupt */ + +#ifdef CONFIG_PWM_PULSECOUNT + irq_attach(lower->irq, pwm_tim8interrupt); + up_disable_irq(lower->irq); +#endif + break; +#endif + +#ifdef CONFIG_STM32_TIM9_PWM + case 9: + lower = &g_pwm9dev; + break; +#endif + +#ifdef CONFIG_STM32_TIM10_PWM + case 10: + lower = &g_pwm10dev; + break; +#endif + +#ifdef CONFIG_STM32_TIM11_PWM + case 11: + lower = &g_pwm11dev; + break; +#endif + +#ifdef CONFIG_STM32_TIM12_PWM + case 12: + lower = &g_pwm12dev; + break; +#endif + +#ifdef CONFIG_STM32_TIM13_PWM + case 13: + lower = &g_pwm13dev; + break; +#endif + +#ifdef CONFIG_STM32_TIM14_PWM + case 14: + lower = &g_pwm14dev; + break; +#endif + + default: + pwmdbg("No such timer configured\n"); + return NULL; + } + + return (FAR struct pwm_lowerhalf_s *)lower; +} + +#endif /* CONFIG_STM32_TIMn_PWM, n = 1,...,14 */ diff --git a/nuttx/arch/arm/src/stm32/stm32_pwm.h b/nuttx/arch/arm/src/stm32/stm32_pwm.h new file mode 100644 index 0000000000..c51c569504 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_pwm.h @@ -0,0 +1,370 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_pwm.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_PWM_H +#define __ARCH_ARM_SRC_STM32_STM32_PWM_H + +/* The STM32 does not have dedicated PWM hardware. Rather, pulsed output control + * is a capabilitiy of the STM32 timers. The logic in this file implements the + * lower half of the standard, NuttX PWM interface using the STM32 timers. That + * interface is described in include/nuttx/pwm.h. + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* Timer devices may be used for different purposes. One special purpose is + * to generate modulated outputs for such things as motor control. If CONFIG_STM32_TIMn + * is defined then the CONFIG_STM32_TIMn_PWM must also be defined to indicate that + * timer "n" is intended to be used for pulsed output signal generation. + */ + +#ifndef CONFIG_STM32_TIM1 +# undef CONFIG_STM32_TIM1_PWM +#endif +#ifndef CONFIG_STM32_TIM2 +# undef CONFIG_STM32_TIM2_PWM +#endif +#ifndef CONFIG_STM32_TIM3 +# undef CONFIG_STM32_TIM3_PWM +#endif +#ifndef CONFIG_STM32_TIM4 +# undef CONFIG_STM32_TIM4_PWM +#endif +#ifndef CONFIG_STM32_TIM5 +# undef CONFIG_STM32_TIM5_PWM +#endif +#ifndef CONFIG_STM32_TIM8 +# undef CONFIG_STM32_TIM8_PWM +#endif +#ifndef CONFIG_STM32_TIM9 +# undef CONFIG_STM32_TIM9_PWM +#endif +#ifndef CONFIG_STM32_TIM10 +# undef CONFIG_STM32_TIM10_PWM +#endif +#ifndef CONFIG_STM32_TIM11 +# undef CONFIG_STM32_TIM11_PWM +#endif +#ifndef CONFIG_STM32_TIM12 +# undef CONFIG_STM32_TIM12_PWM +#endif +#ifndef CONFIG_STM32_TIM13 +# undef CONFIG_STM32_TIM13_PWM +#endif +#ifndef CONFIG_STM32_TIM14 +# undef CONFIG_STM32_TIM14_PWM +#endif + +/* The basic timers (timer 6 and 7) are not capable of generating output pulses */ + +#undef CONFIG_STM32_TIM6_PWM +#undef CONFIG_STM32_TIM7_PWM + +/* Check if PWM support for any channel is enabled. */ + +#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM2_PWM) || \ + defined(CONFIG_STM32_TIM3_PWM) || defined(CONFIG_STM32_TIM4_PWM) || \ + defined(CONFIG_STM32_TIM5_PWM) || defined(CONFIG_STM32_TIM8_PWM) || \ + defined(CONFIG_STM32_TIM9_PWM) || defined(CONFIG_STM32_TIM10_PWM) || \ + defined(CONFIG_STM32_TIM11_PWM) || defined(CONFIG_STM32_TIM12_PWM) || \ + defined(CONFIG_STM32_TIM13_PWM) || defined(CONFIG_STM32_TIM14_PWM) + +#include +#include "chip/stm32_tim.h" + +/* For each timer that is enabled for PWM usage, we need the following additional + * configuration settings: + * + * CONFIG_STM32_TIMx_CHANNEL - Specifies the timer output channel {1,..,4} + * PWM_TIMx_CHn - One of the values defined in chip/stm32*_pinmap.h. In the case + * where there are multiple pin selections, the correct setting must be provided + * in the arch/board/board.h file. + * + * NOTE: The STM32 timers are each capable of generating different signals on + * each of the four channels with different duty cycles. That capability is + * not supported by this driver: Only one output channel per timer. + */ + +#ifdef CONFIG_STM32_TIM1_PWM +# if !defined(CONFIG_STM32_TIM1_CHANNEL) +# error "CONFIG_STM32_TIM1_CHANNEL must be provided" +# elif CONFIG_STM32_TIM1_CHANNEL == 1 +# define PWM_TIM1_PINCFG GPIO_TIM1_CH1OUT +# elif CONFIG_STM32_TIM1_CHANNEL == 2 +# define PWM_TIM1_PINCFG GPIO_TIM1_CH2OUT +# elif CONFIG_STM32_TIM1_CHANNEL == 3 +# define PWM_TIM1_PINCFG GPIO_TIM1_CH3OUT +# elif CONFIG_STM32_TIM1_CHANNEL == 4 +# define PWM_TIM1_PINCFG GPIO_TIM1_CH4OUT +# else +# error "Unsupported value of CONFIG_STM32_TIM1_CHANNEL" +# endif +#endif + +#ifdef CONFIG_STM32_TIM2_PWM +# if !defined(CONFIG_STM32_TIM2_CHANNEL) +# error "CONFIG_STM32_TIM2_CHANNEL must be provided" +# elif CONFIG_STM32_TIM2_CHANNEL == 1 +# define PWM_TIM2_PINCFG GPIO_TIM2_CH1OUT +# elif CONFIG_STM32_TIM2_CHANNEL == 2 +# define PWM_TIM2_PINCFG GPIO_TIM2_CH2OUT +# elif CONFIG_STM32_TIM2_CHANNEL == 3 +# define PWM_TIM2_PINCFG GPIO_TIM2_CH3OUT +# elif CONFIG_STM32_TIM2_CHANNEL == 4 +# define PWM_TIM2_PINCFG GPIO_TIM2_CH4OUT +# else +# error "Unsupported value of CONFIG_STM32_TIM2_CHANNEL" +# endif +#endif + +#ifdef CONFIG_STM32_TIM3_PWM +# if !defined(CONFIG_STM32_TIM3_CHANNEL) +# error "CONFIG_STM32_TIM3_CHANNEL must be provided" +# elif CONFIG_STM32_TIM3_CHANNEL == 1 +# define PWM_TIM3_PINCFG GPIO_TIM3_CH1OUT +# elif CONFIG_STM32_TIM3_CHANNEL == 2 +# define PWM_TIM3_PINCFG GPIO_TIM3_CH2OUT +# elif CONFIG_STM32_TIM3_CHANNEL == 3 +# define PWM_TIM3_PINCFG GPIO_TIM3_CH3OUT +# elif CONFIG_STM32_TIM3_CHANNEL == 4 +# define PWM_TIM3_PINCFG GPIO_TIM3_CH4OUT +# else +# error "Unsupported value of CONFIG_STM32_TIM3_CHANNEL" +# endif +#endif + +#ifdef CONFIG_STM32_TIM4_PWM +# if !defined(CONFIG_STM32_TIM4_CHANNEL) +# error "CONFIG_STM32_TIM4_CHANNEL must be provided" +# elif CONFIG_STM32_TIM4_CHANNEL == 1 +# define PWM_TIM4_PINCFG GPIO_TIM4_CH1OUT +# elif CONFIG_STM32_TIM4_CHANNEL == 2 +# define PWM_TIM4_PINCFG GPIO_TIM4_CH2OUT +# elif CONFIG_STM32_TIM4_CHANNEL == 3 +# define PWM_TIM4_PINCFG GPIO_TIM4_CH3OUT +# elif CONFIG_STM32_TIM4_CHANNEL == 4 +# define PWM_TIM4_PINCFG GPIO_TIM4_CH4OUT +# else +# error "Unsupported value of CONFIG_STM32_TIM4_CHANNEL" +# endif +#endif + +#ifdef CONFIG_STM32_TIM5_PWM +# if !defined(CONFIG_STM32_TIM5_CHANNEL) +# error "CONFIG_STM32_TIM5_CHANNEL must be provided" +# elif CONFIG_STM32_TIM5_CHANNEL == 1 +# define PWM_TIM5_PINCFG GPIO_TIM5_CH1OUT +# elif CONFIG_STM32_TIM5_CHANNEL == 2 +# define PWM_TIM5_PINCFG GPIO_TIM5_CH2OUT +# elif CONFIG_STM32_TIM5_CHANNEL == 3 +# define PWM_TIM5_PINCFG GPIO_TIM5_CH3OUT +# elif CONFIG_STM32_TIM5_CHANNEL == 4 +# define PWM_TIM5_PINCFG GPIO_TIM5_CH4OUT +# else +# error "Unsupported value of CONFIG_STM32_TIM5_CHANNEL" +# endif +#endif + +#ifdef CONFIG_STM32_TIM8_PWM +# if !defined(CONFIG_STM32_TIM8_CHANNEL) +# error "CONFIG_STM32_TIM8_CHANNEL must be provided" +# elif CONFIG_STM32_TIM8_CHANNEL == 1 +# define PWM_TIM8_PINCFG GPIO_TIM8_CH1OUT +# elif CONFIG_STM32_TIM8_CHANNEL == 2 +# define PWM_TIM8_PINCFG GPIO_TIM8_CH2OUT +# elif CONFIG_STM32_TIM8_CHANNEL == 3 +# define PWM_TIM8_PINCFG GPIO_TIM8_CH3OUT +# elif CONFIG_STM32_TIM8_CHANNEL == 4 +# define PWM_TIM8_PINCFG GPIO_TIM8_CH4OUT +# else +# error "Unsupported value of CONFIG_STM32_TIM8_CHANNEL" +# endif +#endif + +#ifdef CONFIG_STM32_TIM9_PWM +# if !defined(CONFIG_STM32_TIM9_CHANNEL) +# error "CONFIG_STM32_TIM9_CHANNEL must be provided" +# elif CONFIG_STM32_TIM9_CHANNEL == 1 +# define PWM_TIM9_PINCFG GPIO_TIM9_CH1OUT +# elif CONFIG_STM32_TIM9_CHANNEL == 2 +# define PWM_TIM9_PINCFG GPIO_TIM9_CH2OUT +# elif CONFIG_STM32_TIM9_CHANNEL == 3 +# define PWM_TIM9_PINCFG GPIO_TIM9_CH3OUT +# elif CONFIG_STM32_TIM9_CHANNEL == 4 +# define PWM_TIM9_PINCFG GPIO_TIM9_CH4OUT +# else +# error "Unsupported value of CONFIG_STM32_TIM9_CHANNEL" +# endif +#endif + +#ifdef CONFIG_STM32_TIM10_PWM +# if !defined(CONFIG_STM32_TIM10_CHANNEL) +# error "CONFIG_STM32_TIM10_CHANNEL must be provided" +# elif CONFIG_STM32_TIM10_CHANNEL == 1 +# define PWM_TIM10_PINCFG GPIO_TIM10_CH1OUT +# elif CONFIG_STM32_TIM10_CHANNEL == 2 +# define PWM_TIM10_PINCFG GPIO_TIM10_CH2OUT +# elif CONFIG_STM32_TIM10_CHANNEL == 3 +# define PWM_TIM10_PINCFG GPIO_TIM10_CH3OUT +# elif CONFIG_STM32_TIM10_CHANNEL == 4 +# define PWM_TIM10_PINCFG GPIO_TIM10_CH4OUT +# else +# error "Unsupported value of CONFIG_STM32_TIM10_CHANNEL" +# endif +#endif + +#ifdef CONFIG_STM32_TIM11_PWM +# if !defined(CONFIG_STM32_TIM11_CHANNEL) +# error "CONFIG_STM32_TIM11_CHANNEL must be provided" +# elif CONFIG_STM32_TIM11_CHANNEL == 1 +# define PWM_TIM11_PINCFG GPIO_TIM11_CH1OUT +# elif CONFIG_STM32_TIM11_CHANNEL == 2 +# define PWM_TIM11_PINCFG GPIO_TIM11_CH2OUT +# elif CONFIG_STM32_TIM11_CHANNEL == 3 +# define PWM_TIM11_PINCFG GPIO_TIM11_CH3OUT +# elif CONFIG_STM32_TIM11_CHANNEL == 4 +# define PWM_TIM11_PINCFG GPIO_TIM11_CH4OUT +# else +# error "Unsupported value of CONFIG_STM32_TIM11_CHANNEL" +# endif +#endif + +#ifdef CONFIG_STM32_TIM12_PWM +# if !defined(CONFIG_STM32_TIM12_CHANNEL) +# error "CONFIG_STM32_TIM12_CHANNEL must be provided" +# elif CONFIG_STM32_TIM12_CHANNEL == 1 +# define PWM_TIM12_PINCFG GPIO_TIM12_CH1OUT +# elif CONFIG_STM32_TIM12_CHANNEL == 2 +# define PWM_TIM12_PINCFG GPIO_TIM12_CH2OUT +# elif CONFIG_STM32_TIM12_CHANNEL == 3 +# define PWM_TIM12_PINCFG GPIO_TIM12_CH3OUT +# elif CONFIG_STM32_TIM12_CHANNEL == 4 +# define PWM_TIM12_PINCFG GPIO_TIM12_CH4OUT +# else +# error "Unsupported value of CONFIG_STM32_TIM12_CHANNEL" +# endif +#endif + +#ifdef CONFIG_STM32_TIM13_PWM +# if !defined(CONFIG_STM32_TIM13_CHANNEL) +# error "CONFIG_STM32_TIM13_CHANNEL must be provided" +# elif CONFIG_STM32_TIM13_CHANNEL == 1 +# define PWM_TIM13_PINCFG GPIO_TIM13_CH1OUT +# elif CONFIG_STM32_TIM13_CHANNEL == 2 +# define PWM_TIM13_PINCFG GPIO_TIM13_CH2OUT +# elif CONFIG_STM32_TIM13_CHANNEL == 3 +# define PWM_TIM13_PINCFG GPIO_TIM13_CH3OUT +# elif CONFIG_STM32_TIM13_CHANNEL == 4 +# define PWM_TIM13_PINCFG GPIO_TIM13_CH4OUT +# else +# error "Unsupported value of CONFIG_STM32_TIM13_CHANNEL" +# endif +#endif + +#ifdef CONFIG_STM32_TIM14_PWM +# if !defined(CONFIG_STM32_TIM14_CHANNEL) +# error "CONFIG_STM32_TIM14_CHANNEL must be provided" +# elif CONFIG_STM32_TIM14_CHANNEL == 1 +# define PWM_TIM14_PINCFG GPIO_TIM14_CH1OUT +# elif CONFIG_STM32_TIM14_CHANNEL == 2 +# define PWM_TIM14_PINCFG GPIO_TIM14_CH2OUT +# elif CONFIG_STM32_TIM14_CHANNEL == 3 +# define PWM_TIM14_PINCFG GPIO_TIM14_CH3OUT +# elif CONFIG_STM32_TIM14_CHANNEL == 4 +# define PWM_TIM14_PINCFG GPIO_TIM14_CH4OUT +# else +# error "Unsupported value of CONFIG_STM32_TIM14_CHANNEL" +# endif +#endif + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_pwminitialize + * + * Description: + * Initialize one timer for use with the upper_level PWM driver. + * + * Input Parameters: + * timer - A number identifying the timer use. The number of valid timer + * IDs varies with the STM32 MCU and MCU family but is somewhere in + * the range of {1,..,14}. + * + * Returned Value: + * On success, a pointer to the STM32 lower half PWM driver is returned. + * NULL is returned on any failure. + * + ************************************************************************************/ + +EXTERN FAR struct pwm_lowerhalf_s *stm32_pwminitialize(int timer); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_STM32_TIMx_PWM */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_PWM_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_pwr.c b/nuttx/arch/arm/src/stm32/stm32_pwr.c new file mode 100644 index 0000000000..bada048e3e --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_pwr.c @@ -0,0 +1,98 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_pwr.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +#include +#include + +#include "up_arch.h" +#include "stm32_pwr.h" + +#if defined(CONFIG_STM32_PWR) + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +static inline uint16_t stm32_pwr_getreg(uint8_t offset) +{ + return getreg32(STM32_PWR_BASE + offset); +} + +static inline void stm32_pwr_putreg(uint8_t offset, uint16_t value) +{ + putreg32(value, STM32_PWR_BASE + offset); +} + +static inline void stm32_pwr_modifyreg(uint8_t offset, uint16_t clearbits, uint16_t setbits) +{ + modifyreg32(STM32_PWR_BASE + offset, clearbits, setbits); +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_pwr_enablebkp + * + * Description: + * Enables access to the backup domain (RTC registers, RTC backup data registers + * and backup SRAM). + * + * Input Parameters: + * None + * + * Returned Values: + * None + * + ************************************************************************************/ + +void stm32_pwr_enablebkp(void) +{ + stm32_pwr_modifyreg(STM32_PWR_CR_OFFSET, 0, PWR_CR_DBP); +} + +#endif // defined(CONFIG_STM32_PWR) diff --git a/nuttx/arch/arm/src/stm32/stm32_pwr.h b/nuttx/arch/arm/src/stm32/stm32_pwr.h new file mode 100644 index 0000000000..56aee49b67 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_pwr.h @@ -0,0 +1,89 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_pwr.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_PWR_H +#define __ARCH_ARM_SRC_STM32_STM32_PWR_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" +#include "chip/stm32_pwr.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_pwr_enablebkp + * + * Description: + * Enables access to the backup domain (RTC registers, RTC backup data registers + * and backup SRAM). + * + * Input Parameters: + * None + * + * Returned Values: + * None + * + ************************************************************************************/ + +EXTERN void stm32_pwr_enablebkp(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_PWR_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_qencoder.c b/nuttx/arch/arm/src/stm32/stm32_qencoder.c new file mode 100644 index 0000000000..8553296f93 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_qencoder.c @@ -0,0 +1,1228 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_qencoder.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * Diego Sanchez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "chip.h" +#include "up_internal.h" +#include "up_arch.h" + +#include "stm32_internal.h" +#include "stm32_gpio.h" +#include "stm32_tim.h" +#include "stm32_qencoder.h" + +#ifdef CONFIG_QENCODER + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Clocking *************************************************************************/ +/* The CLKOUT value should not exceed the CLKIN value */ + +#if defined(CONFIG_STM32_TIM1_QE) && CONFIG_STM32_TIM1_QECLKOUT > STM32_APB2_TIM1_CLKIN +# warning "CONFIG_STM32_TIM1_QECLKOUT exceeds STM32_APB2_TIM1_CLKIN" +#endif + +#if defined(CONFIG_STM32_TIM2_QE) && CONFIG_STM32_TIM2_QECLKOUT > STM32_APB1_TIM2_CLKIN +# warning "CONFIG_STM32_TIM2_QECLKOUT exceeds STM32_APB2_TIM2_CLKIN" +#endif + +#if defined(CONFIG_STM32_TIM3_QE) && CONFIG_STM32_TIM3_QECLKOUT > STM32_APB1_TIM3_CLKIN +# warning "CONFIG_STM32_TIM3_QECLKOUT exceeds STM32_APB2_TIM3_CLKIN" +#endif + +#if defined(CONFIG_STM32_TIM4_QE) && CONFIG_STM32_TIM4_QECLKOUT > STM32_APB1_TIM4_CLKIN +# warning "CONFIG_STM32_TIM4_QECLKOUT exceeds STM32_APB2_TIM4_CLKIN" +#endif + +#if defined(CONFIG_STM32_TIM5_QE) && CONFIG_STM32_TIM5_QECLKOUT > STM32_APB1_TIM5_CLKIN +# warning "CONFIG_STM32_TIM5_QECLKOUT exceeds STM32_APB2_TIM5_CLKIN" +#endif + +#if defined(CONFIG_STM32_TIM8_QE) && CONFIG_STM32_TIM8_QECLKOUT > STM32_APB2_TIM8_CLKIN +# warning "CONFIG_STM32_TIM8_QECLKOUT exceeds STM32_APB2_TIM8_CLKIN" +#endif + +/* Timers ***************************************************************************/ +/* On the F1 series, all timers are 16-bit. */ + +#undef HAVE_32BIT_TIMERS +#undef HAVE_16BIT_TIMERS + +#if defined(CONFIG_STM32_STM32F10XX) + +# define HAVE_16BIT_TIMERS 1 + + /* The width in bits of each timer */ + +# define TIM1_BITWIDTH 16 +# define TIM2_BITWIDTH 16 +# define TIM3_BITWIDTH 16 +# define TIM4_BITWIDTH 16 +# define TIM5_BITWIDTH 16 +# define TIM8_BITWIDTH 16 + +/* On the F4 series, TIM2 and TIM5 are 32-bit. All of the rest are 16-bit */ + +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + + /* If TIM2 or TIM5 are enabled, then we have 32-bit timers */ + +# if defined(CONFIG_STM32_TIM2_QE) || defined(CONFIG_STM32_TIM5_QE) +# define HAVE_32BIT_TIMERS 1 +# endif + + /* If TIM1,3,4, or 8 are enabled, then we have 16-bit timers */ + +# if defined(CONFIG_STM32_TIM1_QE) || defined(CONFIG_STM32_TIM3_QE) || \ + defined(CONFIG_STM32_TIM4_QE) || defined(CONFIG_STM32_TIM8_QE) +# define HAVE_16BIT_TIMERS 1 +# endif + + /* The width in bits of each timer */ + +# define TIM1_BITWIDTH 16 +# define TIM2_BITWIDTH 32 +# define TIM3_BITWIDTH 16 +# define TIM4_BITWIDTH 16 +# define TIM5_BITWIDTH 32 +# define TIM8_BITWIDTH 16 +#endif + +/* Do we need to support mixed 16- and 32-bit timers */ + +#undef HAVE_MIXEDWIDTH_TIMERS +#if defined(HAVE_16BIT_TIMERS) && defined(HAVE_32BIT_TIMERS) +# define HAVE_MIXEDWIDTH_TIMERS 1 +#endif + +/* Debug ****************************************************************************/ +/* Non-standard debug that may be enabled just for testing the quadrature encoder */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_QENCODER +#endif + +#ifdef CONFIG_DEBUG_QENCODER +# define qedbg dbg +# define qelldbg lldbg +# ifdef CONFIG_DEBUG_VERBOSE +# define qevdbg vdbg +# define qellvdbg llvdbg +# define qe_dumpgpio(p,m) stm32_dumpgpio(p,m) +# else +# define qevdbg(x...) +# define qellvdbg(x...) +# define qe_dumpgpio(p,m) +# endif +#else +# define qedbg(x...) +# define qelldbg(x...) +# define qevdbg(x...) +# define qellvdbg(x...) +# define qe_dumpgpio(p,m) +#endif + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/* Constant configuration structure that is retained in FLASH */ + +struct stm32_qeconfig_s +{ + uint8_t timid; /* Timer ID {1,2,3,4,5,8} */ + uint8_t irq; /* Timer update IRQ */ +#ifdef HAVE_MIXEDWIDTH_TIMERS + uint8_t width; /* Timer width (16- or 32-bits) */ +#endif +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + uint32_t ti1cfg; /* TI1 input pin configuration (20-bit encoding) */ + uint32_t ti2cfg; /* TI2 input pin configuration (20-bit encoding) */ +#else + uint16_t ti1cfg; /* TI1 input pin configuration (16-bit encoding) */ + uint16_t ti2cfg; /* TI2 input pin configuration (16-bit encoding) */ +#endif + uint32_t base; /* Register base address */ + uint32_t psc; /* Timer input clock prescaler */ + xcpt_t handler; /* Interrupt handler for this IRQ */ +}; + +/* Overall, RAM-based state structure */ + +struct stm32_lowerhalf_s +{ + /* The first field of this state structure must be a pointer to the lower- + * half callback structure: + */ + + FAR const struct qe_ops_s *ops; /* Lower half callback structure */ + + /* STM32 driver-specific fields: */ + + FAR const struct stm32_qeconfig_s *config; /* static onfiguration */ + + bool inuse; /* True: The lower-half driver is in-use */ + +#ifdef HAVE_16BIT_TIMERS + volatile int32_t position; /* The current position offset */ +#endif +}; + +/************************************************************************************ + * Private Function Prototypes + ************************************************************************************/ +/* Helper functions */ + +static uint16_t stm32_getreg16(struct stm32_lowerhalf_s *priv, int offset); +static void stm32_putreg16(struct stm32_lowerhalf_s *priv, int offset, uint16_t value); +static uint32_t stm32_getreg32(FAR struct stm32_lowerhalf_s *priv, int offset); +static void stm32_putreg32(FAR struct stm32_lowerhalf_s *priv, int offset, uint32_t value); + +#if defined(CONFIG_DEBUG_QENCODER) && defined(CONFIG_DEBUG_VERBOSE) +static void stm32_dumpregs(struct stm32_lowerhalf_s *priv, FAR const char *msg); +#else +# define stm32_dumpregs(priv,msg) +#endif + +static FAR struct stm32_lowerhalf_s *stm32_tim2lower(int tim); + +/* Interrupt handling */ + +#ifdef HAVE_16BIT_TIMERS +static int stm32_interrupt(FAR struct stm32_lowerhalf_s *priv); +#if defined(CONFIG_STM32_TIM1_QE) && TIM1_BITWIDTH == 16 +static int stm32_tim1interrupt(int irq, FAR void *context); +#endif +#if defined(CONFIG_STM32_TIM2_QE) && TIM2_BITWIDTH == 16 +static int stm32_tim2interrupt(int irq, FAR void *context); +#endif +#if defined(CONFIG_STM32_TIM3_QE) && TIM3_BITWIDTH == 16 +static int stm32_tim3interrupt(int irq, FAR void *context); +#endif +#if defined(CONFIG_STM32_TIM4_QE) && TIM4_BITWIDTH == 16 +static int stm32_tim4interrupt(int irq, FAR void *context); +#endif +#if defined(CONFIG_STM32_TIM5_QE) && TIM5_BITWIDTH == 16 +static int stm32_tim5interrupt(int irq, FAR void *context); +#endif +#if defined(CONFIG_STM32_TIM8_QE) && TIM8_BITWIDTH == 16 +static int stm32_tim8interrupt(int irq, FAR void *context); +#endif +#endif + +/* Lower-half Quadrature Encoder Driver Methods */ + +static int stm32_setup(FAR struct qe_lowerhalf_s *lower); +static int stm32_shutdown(FAR struct qe_lowerhalf_s *lower); +static int stm32_position(FAR struct qe_lowerhalf_s *lower, int32_t *pos); +static int stm32_reset(FAR struct qe_lowerhalf_s *lower); +static int stm32_ioctl(FAR struct qe_lowerhalf_s *lower, int cmd, unsigned long arg); + +/************************************************************************************ + * Private Data + ************************************************************************************/ +/* The lower half callback structure */ + +static const struct qe_ops_s g_qecallbacks = +{ + .setup = stm32_setup, + .shutdown = stm32_shutdown, + .position = stm32_position, + .reset = stm32_reset, + .ioctl = stm32_ioctl, +}; + +/* Per-timer state structures */ + +#ifdef CONFIG_STM32_TIM1_QE +static const struct stm32_qeconfig_s g_tim1config = +{ + .timid = 1, + .irq = STM32_IRQ_TIM1UP, +#ifdef HAVE_MIXEDWIDTH_TIMERS + .width = TIM1_BITWIDTH, +#endif + .base = STM32_TIM1_BASE, + .psc = (STM32_APB2_TIM1_CLKIN / CONFIG_STM32_TIM1_QECLKOUT) - 1, + .ti1cfg = GPIO_TIM1_CH1IN, + .ti2cfg = GPIO_TIM1_CH2IN, +#if TIM1_BITWIDTH == 16 + .handler = stm32_tim1interrupt, +#endif +}; + +static struct stm32_lowerhalf_s g_tim1lower = +{ + .ops = &g_qecallbacks, + .config = &g_tim1config, + .inuse = false, +}; + +#endif + +#ifdef CONFIG_STM32_TIM2_QE +static const struct stm32_qeconfig_s g_tim2config = +{ + .timid = 2, + .irq = STM32_IRQ_TIM2, +#ifdef HAVE_MIXEDWIDTH_TIMERS + .width = TIM2_BITWIDTH, +#endif + .base = STM32_TIM2_BASE, + .psc = (STM32_APB1_TIM2_CLKIN / CONFIG_STM32_TIM2_QECLKOUT) - 1, + .ti1cfg = GPIO_TIM2_CH1IN, + .ti2cfg = GPIO_TIM2_CH2IN, +#if TIM2_BITWIDTH == 16 + .handler = stm32_tim2interrupt, +#endif +}; + +static struct stm32_lowerhalf_s g_tim2lower = +{ + .ops = &g_qecallbacks, + .config = &g_tim2config, + .inuse = false, +}; + +#endif + +#ifdef CONFIG_STM32_TIM3_QE +static const struct stm32_qeconfig_s g_tim3config = +{ + .timid = 3, + .irq = STM32_IRQ_TIM3, +#ifdef HAVE_MIXEDWIDTH_TIMERS + .width = TIM3_BITWIDTH, +#endif + .base = STM32_TIM3_BASE, + .psc = (STM32_APB1_TIM3_CLKIN / CONFIG_STM32_TIM3_QECLKOUT) - 1, + .ti1cfg = GPIO_TIM3_CH1IN, + .ti2cfg = GPIO_TIM3_CH2IN, +#if TIM3_BITWIDTH == 16 + .handler = stm32_tim3interrupt, +#endif +}; + +static struct stm32_lowerhalf_s g_tim3lower = +{ + .ops = &g_qecallbacks, + .config = &g_tim3config, + .inuse = false, +}; + +#endif + +#ifdef CONFIG_STM32_TIM4_QE +static const struct stm32_qeconfig_s g_tim4config = +{ + .timid = 4, + .irq = STM32_IRQ_TIM4, +#ifdef HAVE_MIXEDWIDTH_TIMERS + .width = TIM4_BITWIDTH, +#endif + .base = STM32_TIM4_BASE, + .psc = (STM32_APB1_TIM4_CLKIN / CONFIG_STM32_TIM4_QECLKOUT) - 1, + .ti1cfg = GPIO_TIM4_CH1IN, + .ti2cfg = GPIO_TIM4_CH2IN, +#if TIM4_BITWIDTH == 16 + .handler = stm32_tim4interrupt, +#endif +}; + +static struct stm32_lowerhalf_s g_tim4lower = +{ + .ops = &g_qecallbacks, + .config = &g_tim4config, + .inuse = false, +}; + +#endif + +#ifdef CONFIG_STM32_TIM5_QE +static const struct stm32_qeconfig_s g_tim5config = +{ + .timid = 5, + .irq = STM32_IRQ_TIM5, +#ifdef HAVE_MIXEDWIDTH_TIMERS + .width = TIM5_BITWIDTH, +#endif + .base = STM32_TIM5_BASE, + .psc = (STM32_APB1_TIM5_CLKIN / CONFIG_STM32_TIM5_QECLKOUT) - 1, + .ti1cfg = GPIO_TIM5_CH1IN, + .ti2cfg = GPIO_TIM5_CH2IN, +#if TIM5_BITWIDTH == 16 + .handler = stm32_tim5interrupt, +#endif +}; + +static struct stm32_lowerhalf_s g_tim5lower = +{ + .ops = &g_qecallbacks, + .config = &g_tim5config, + .inuse = false, +}; + +#endif + +#ifdef CONFIG_STM32_TIM8_QE +static const struct stm32_qeconfig_s g_tim8config = +{ + .timid = 8, + .irq = STM32_IRQ_TIM8UP, +#ifdef HAVE_MIXEDWIDTH_TIMERS + .width = TIM8_BITWIDTH, +#endif + .base = STM32_TIM8_BASE, + .psc = (STM32_APB2_TIM8_CLKIN / CONFIG_STM32_TIM8_QECLKOUT) - 1, + .ti1cfg = GPIO_TIM8_CH1IN, + .ti2cfg = GPIO_TIM8_CH2IN, +#if TIM8_BITWIDTH == 16 + .handler = stm32_tim8interrupt, +#endif +}; + +static struct stm32_lowerhalf_s g_tim8lower = +{ + .ops = &g_qecallbacks, + .config = &g_tim8config, + .inuse = false, +}; + +#endif + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_getreg16 + * + * Description: + * Read the value of a 16-bit timer register. + * + * Input Parameters: + * priv - A reference to the lower half status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ************************************************************************************/ + +static uint16_t stm32_getreg16(struct stm32_lowerhalf_s *priv, int offset) +{ + return getreg16(priv->config->base + offset); +} + +/************************************************************************************ + * Name: stm32_putreg16 + * + * Description: + * Write a value to a 16-bit timer register. + * + * Input Parameters: + * priv - A reference to the lower half status + * offset - The offset to the register to read + * + * Returned Value: + * None + * + ************************************************************************************/ + +static void stm32_putreg16(struct stm32_lowerhalf_s *priv, int offset, uint16_t value) +{ + putreg16(value, priv->config->base + offset); +} + +/************************************************************************************ + * Name: stm32_getreg32 + * + * Description: + * Read the value of a 32-bit timer register. This applies only for the STM32 F4 + * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5 (but works OK + * with the 16-bit TIM1,8 and F1 registers as well). + * + * Input Parameters: + * priv - A reference to the lower half status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ************************************************************************************/ + +static uint32_t stm32_getreg32(FAR struct stm32_lowerhalf_s *priv, int offset) +{ + return getreg32(priv->config->base + offset); +} + +/************************************************************************************ + * Name: stm32_putreg16 + * + * Description: + * Write a value to a 32-bit timer register. This applies only for the STM32 F4 + * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5 (but works OK + * with the 16-bit TIM1,8 and F1 registers). + * + * Input Parameters: + * priv - A reference to the lower half status + * offset - The offset to the register to read + * + * Returned Value: + * None + * + ************************************************************************************/ + +static void stm32_putreg32(FAR struct stm32_lowerhalf_s *priv, int offset, uint32_t value) +{ + putreg32(value, priv->config->base + offset); +} + +/**************************************************************************** + * Name: stm32_dumpregs + * + * Description: + * Dump all timer registers. + * + * Input parameters: + * priv - A reference to the QENCODER block status + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_QENCODER) && defined(CONFIG_DEBUG_VERBOSE) +static void stm32_dumpregs(struct stm32_lowerhalf_s *priv, FAR const char *msg) +{ + qevdbg("%s:\n", msg); + qevdbg(" CR1: %04x CR2: %04x SMCR: %04x DIER: %04x\n", + stm32_getreg16(priv, STM32_GTIM_CR1_OFFSET), + stm32_getreg16(priv, STM32_GTIM_CR2_OFFSET), + stm32_getreg16(priv, STM32_GTIM_SMCR_OFFSET), + stm32_getreg16(priv, STM32_GTIM_DIER_OFFSET)); + qevdbg(" SR: %04x EGR: %04x CCMR1: %04x CCMR2: %04x\n", + stm32_getreg16(priv, STM32_GTIM_SR_OFFSET), + stm32_getreg16(priv, STM32_GTIM_EGR_OFFSET), + stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET), + stm32_getreg16(priv, STM32_GTIM_CCMR2_OFFSET)); + qevdbg(" CCER: %04x CNT: %04x PSC: %04x ARR: %04x\n", + stm32_getreg16(priv, STM32_GTIM_CCER_OFFSET), + stm32_getreg16(priv, STM32_GTIM_CNT_OFFSET), + stm32_getreg16(priv, STM32_GTIM_PSC_OFFSET), + stm32_getreg16(priv, STM32_GTIM_ARR_OFFSET)); + qevdbg(" CCR1: %04x CCR2: %04x CCR3: %04x CCR4: %04x\n", + stm32_getreg16(priv, STM32_GTIM_CCR1_OFFSET), + stm32_getreg16(priv, STM32_GTIM_CCR2_OFFSET), + stm32_getreg16(priv, STM32_GTIM_CCR3_OFFSET), + stm32_getreg16(priv, STM32_GTIM_CCR4_OFFSET)); +#if defined(CONFIG_STM32_TIM1_QENCODER) || defined(CONFIG_STM32_TIM8_QENCODER) + if (priv->timtype == TIMTYPE_ADVANCED) + { + qevdbg(" RCR: %04x BDTR: %04x DCR: %04x DMAR: %04x\n", + stm32_getreg16(priv, STM32_ATIM_RCR_OFFSET), + stm32_getreg16(priv, STM32_ATIM_BDTR_OFFSET), + stm32_getreg16(priv, STM32_ATIM_DCR_OFFSET), + stm32_getreg16(priv, STM32_ATIM_DMAR_OFFSET)); + } + else +#endif + { + qevdbg(" DCR: %04x DMAR: %04x\n", + stm32_getreg16(priv, STM32_GTIM_DCR_OFFSET), + stm32_getreg16(priv, STM32_GTIM_DMAR_OFFSET)); + } +} +#endif + +/************************************************************************************ + * Name: stm32_tim2lower + * + * Description: + * Map a timer number to a device structure + * + ************************************************************************************/ + +static FAR struct stm32_lowerhalf_s *stm32_tim2lower(int tim) +{ + switch (tim) + { +#ifdef CONFIG_STM32_TIM1_QE + case 1: + return &g_tim1lower; +#endif +#ifdef CONFIG_STM32_TIM2_QE + case 2: + return &g_tim2lower; +#endif +#ifdef CONFIG_STM32_TIM3_QE + case 3: +#endif +#ifdef CONFIG_STM32_TIM4_QE + case 4: + return &g_tim4lower; +#endif +#ifdef CONFIG_STM32_TIM5_QE + case 5: + return &g_tim5lower; +#endif +#ifdef CONFIG_STM32_TIM8_QE + case 8: + return &g_tim8lower; +#endif + default: + return NULL; + } +} + +/************************************************************************************ + * Name: stm32_interrupt + * + * Description: + * Common timer interrupt handling. NOTE: Only 16-bit timers require timer + * interrupts. + * + ************************************************************************************/ + +#ifdef HAVE_16BIT_TIMERS +static int stm32_interrupt(FAR struct stm32_lowerhalf_s *priv) +{ + uint16_t regval; + + /* Verify that this is an update interrupt. Nothing else is expected. */ + + regval = stm32_getreg16(priv, STM32_GTIM_SR_OFFSET); + DEBUGASSERT((regval & ATIM_SR_UIF) != 0); + + /* Clear the UIF interrupt bit */ + + stm32_putreg16(priv, STM32_GTIM_SR_OFFSET, regval & ~GTIM_SR_UIF); + + /* Check the direction bit in the CR1 register and add or subtract the + * maximum value, as appropriate. + */ + + regval = stm32_getreg16(priv, STM32_GTIM_CR1_OFFSET); + if ((regval & ATIM_CR1_DIR) != 0) + { + priv->position -= (int32_t)0x0000ffff; + } + else + { + priv->position += (int32_t)0x0000ffff; + } + + return OK; +} +#endif + +/************************************************************************************ + * Name: stm32_intNinterrupt + * + * Description: + * TIMN interrupt handler + * + ************************************************************************************/ + +#if defined(CONFIG_STM32_TIM1_QE) && TIM1_BITWIDTH == 16 +static int stm32_tim1interrupt(int irq, FAR void *context) +{ + return stm32_interrupt(&g_tim1lower); +} +#endif + +#if defined(CONFIG_STM32_TIM2_QE) && TIM2_BITWIDTH == 16 +static int stm32_tim2interrupt(int irq, FAR void *context) +{ + return stm32_interrupt(&g_tim2lower); +} +#endif + +#if defined(CONFIG_STM32_TIM3_QE) && TIM3_BITWIDTH == 16 +static int stm32_tim3interrupt(int irq, FAR void *context) +{ + return stm32_interrupt(&g_tim3lower); +} +#endif + +#if defined(CONFIG_STM32_TIM4_QE) && TIM4_BITWIDTH == 16 +static int stm32_tim4interrupt(int irq, FAR void *context) +{ + return stm32_interrupt(&g_tim4lower); +} +#endif + +#if defined(CONFIG_STM32_TIM5_QE) && TIM5_BITWIDTH == 16 +static int stm32_tim5interrupt(int irq, FAR void *context) +{ + return stm32_interrupt(&g_tim5lower); +} +#endif + +#if defined(CONFIG_STM32_TIM8_QE) && TIM8_BITWIDTH == 16 +static int stm32_tim8interrupt(int irq, FAR void *context) +{ + return stm32_interrupt(&g_tim8lower); +} +#endif + +/************************************************************************************ + * Name: stm32_setup + * + * Description: + * This method is called when the driver is opened. The lower half driver + * should configure and initialize the device so that it is ready for use. + * The initial position value should be zero. * + * + ************************************************************************************/ + +static int stm32_setup(FAR struct qe_lowerhalf_s *lower) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; + uint16_t dier; + uint16_t smcr; + uint16_t ccmr1; + uint16_t ccer; + uint16_t cr1; +#ifdef HAVE_16BIT_TIMERS + uint16_t regval; + int ret; +#endif + + /* NOTE: Clocking should have been enabled in the low-level RCC logic at boot-up */ + + /* Timer base configuration */ + + cr1 = stm32_getreg16(priv, STM32_GTIM_CR1_OFFSET); + + /* Clear the direction bit (0=count up) and select the Counter Mode (0=Edge aligned) + * (Timers 2-5 and 1-8 only) + */ + + cr1 &= ~(GTIM_CR1_DIR | GTIM_CR1_CMS_MASK); + stm32_putreg16(priv, STM32_GTIM_CR1_OFFSET, cr1); + + /* Set the Autoreload value */ + +#if defined(HAVE_MIXEDWIDTH_TIMERS) + if (priv->config->width == 32) + { + stm32_putreg32(priv, STM32_GTIM_ARR_OFFSET, 0xffffffff); + } + else + { + stm32_putreg32(priv, STM32_GTIM_ARR_OFFSET, 0xffff); + } +#elif defined(HAVE_32BIT_TIMERS) + stm32_putreg32(priv, STM32_GTIM_ARR_OFFSET, 0xffffffff); +#else + stm32_putreg32(priv, STM32_GTIM_ARR_OFFSET, 0xffff); +#endif + + /* Set the timerp rescaler value. The clock input value (CLKIN) is based on the + * peripheral clock (PCLK) and a multiplier. These CLKIN values are provided in + * the board.h file. The prescaler value is then that CLKIN value divided by the + * configured CLKOUT value (minus one) + */ + + stm32_putreg16(priv, STM32_GTIM_PSC_OFFSET, (uint16_t)priv->config->psc); + +#if defined(CONFIG_STM32_TIM1_QE) || defined(CONFIG_STM32_TIM8_QE) + if (priv->config->timid == 1 || priv->config->timid == 8) + { + /* Clear the Repetition Counter value */ + + stm32_putreg16(priv, STM32_ATIM_RCR_OFFSET, 0); + } +#endif + + /* Generate an update event to reload the Prescaler + * and the repetition counter(only for TIM1 and TIM8) value immediatly + */ + + stm32_putreg16(priv, STM32_GTIM_EGR_OFFSET, GTIM_EGR_UG); + + /* GPIO pin configuration */ + + stm32_configgpio(priv->config->ti1cfg); + stm32_configgpio(priv->config->ti2cfg); + + /* Set the encoder Mode 3 */ + + smcr = stm32_getreg16(priv, STM32_GTIM_SMCR_OFFSET); + smcr &= ~GTIM_SMCR_SMS_MASK; + smcr |= GTIM_SMCR_ENCMD3; + stm32_putreg16(priv, STM32_GTIM_SMCR_OFFSET, smcr); + + /* TI1 Channel Configuration */ + /* Disable the Channel 1: Reset the CC1E Bit */ + + ccer = stm32_getreg16(priv, STM32_GTIM_CCER_OFFSET); + ccer &= ~GTIM_CCER_CC1E; + stm32_putreg16(priv, STM32_GTIM_CCER_OFFSET, ccer); + + ccmr1 = stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET); + ccer = stm32_getreg16(priv, STM32_GTIM_CCER_OFFSET); + + /* Select the Input IC1=TI1 and set the filter fSAMPLING=fDTS/4, N=6 */ + + ccmr1 &= ~(GTIM_CCMR1_CC1S_MASK|GTIM_CCMR1_IC1F_MASK); + ccmr1 |= GTIM_CCMR_CCS_CCIN1 << GTIM_CCMR1_CC1S_SHIFT; + ccmr1 |= GTIM_CCMR_ICF_FDTSd46 << GTIM_CCMR1_IC1F_SHIFT; + + /* Select the Polarity=rising and set the CC1E Bit */ + + ccer &= ~(GTIM_CCER_CC1P | GTIM_CCER_CC1NP); + ccer |= GTIM_CCER_CC1E; + + /* Write to TIM CCMR1 and CCER registers */ + + stm32_putreg16(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1); + stm32_putreg16(priv, STM32_GTIM_CCER_OFFSET, ccer); + + /* Set the Input Capture Prescaler value: Capture performed each time an + * edge is detected on the capture input. + */ + + ccmr1 = stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET); + ccmr1 &= ~GTIM_CCMR1_IC1PSC_MASK; + ccmr1 |= (GTIM_CCMR_ICPSC_NOPSC << GTIM_CCMR1_IC1PSC_SHIFT); + stm32_putreg16(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1); + + /* TI2 Channel Configuration */ + /* Disable the Channel 2: Reset the CC2E Bit */ + + ccer = stm32_getreg16(priv, STM32_GTIM_CCER_OFFSET); + ccer &= ~GTIM_CCER_CC2E; + stm32_putreg16(priv, STM32_GTIM_CCER_OFFSET, ccer); + + ccmr1 = stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET); + ccer = stm32_getreg16(priv, STM32_GTIM_CCER_OFFSET); + + /* Select the Input IC2=TI2 and set the filter fSAMPLING=fDTS/4, N=6 */ + + ccmr1 &= ~(GTIM_CCMR1_CC2S_MASK|GTIM_CCMR1_IC2F_MASK); + ccmr1 |= GTIM_CCMR_CCS_CCIN1 << GTIM_CCMR1_CC2S_SHIFT; + ccmr1 |= GTIM_CCMR_ICF_FDTSd46 << GTIM_CCMR1_IC2F_SHIFT; + + /* Select the Polarity=rising and set the CC2E Bit */ + + ccer &= ~(GTIM_CCER_CC2P | GTIM_CCER_CC2NP); + ccer |= GTIM_CCER_CC2E; + + /* Write to TIM CCMR1 and CCER registers */ + + stm32_putreg16(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1); + stm32_putreg16(priv, STM32_GTIM_CCER_OFFSET, ccer); + + /* Set the Input Capture Prescaler value: Capture performed each time an + * edge is detected on the capture input. + */ + + ccmr1 = stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET); + ccmr1 &= ~GTIM_CCMR1_IC2PSC_MASK; + ccmr1 |= (GTIM_CCMR_ICPSC_NOPSC << GTIM_CCMR1_IC2PSC_SHIFT); + stm32_putreg16(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1); + + /* Disable the update interrupt */ + + dier = stm32_getreg16(priv, STM32_GTIM_DIER_OFFSET); + dier &= ~GTIM_DIER_UIE; + stm32_putreg16(priv, STM32_GTIM_DIER_OFFSET, dier); + + /* There is no need for interrupts with 32-bit timers */ + +#ifdef HAVE_16BIT_TIMERS +#ifdef HAVE_MIXEDWIDTH_TIMERS + if (priv->config->width != 32) +#endif + { + /* Attach the interrupt handler */ + + ret = irq_attach(priv->config->irq, priv->config->handler); + if (ret < 0) + { + stm32_shutdown(lower); + return ret; + } + + /* Enable the update/global interrupt at the NVIC */ + + up_enable_irq(priv->config->irq); + } +#endif + + /* Reset the Update Disable Bit */ + + cr1 = stm32_getreg16(priv, STM32_GTIM_CR1_OFFSET); + cr1 &= ~GTIM_CR1_UDIS; + stm32_putreg16(priv, STM32_GTIM_CR1_OFFSET, cr1); + + /* Reset the URS Bit */ + + cr1 &= ~GTIM_CR1_URS; + stm32_putreg16(priv, STM32_GTIM_CR1_OFFSET, cr1); + + /* There is no need for interrupts with 32-bit timers */ + +#ifdef HAVE_16BIT_TIMERS +#ifdef HAVE_MIXEDWIDTH_TIMERS + if (priv->config->width != 32) +#endif + { + /* Clear any pending update interrupts */ + + regval = stm32_getreg16(priv, STM32_GTIM_SR_OFFSET); + stm32_putreg16(priv, STM32_GTIM_SR_OFFSET, regval & ~GTIM_SR_UIF); + + /* Then enable the update interrupt */ + + dier = stm32_getreg16(priv, STM32_GTIM_DIER_OFFSET); + dier |= GTIM_DIER_UIE; + stm32_putreg16(priv, STM32_GTIM_DIER_OFFSET, dier); + } +#endif + + /* Enable the TIM Counter */ + + cr1 = stm32_getreg16(priv, STM32_GTIM_CR1_OFFSET); + cr1 |= GTIM_CR1_CEN; + stm32_putreg16(priv, STM32_GTIM_CR1_OFFSET, cr1); + + return OK; +} + +/************************************************************************************ + * Name: stm32_shutdown + * + * Description: + * This method is called when the driver is closed. The lower half driver + * should stop data collection, free any resources, disable timer hardware, and + * put the system into the lowest possible power usage state * + * + ************************************************************************************/ + +static int stm32_shutdown(FAR struct qe_lowerhalf_s *lower) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; + irqstate_t flags; + uint32_t regaddr; + uint32_t regval; + uint32_t resetbit; + uint32_t pincfg; + + /* Disable the update/global interrupt at the NVIC */ + + flags = irqsave(); + up_disable_irq(priv->config->irq); + + /* Detach the interrupt handler */ + + (void)irq_detach(priv->config->irq); + + /* Disable interrupts momentary to stop any ongoing timer processing and + * to prevent any concurrent access to the reset register. + */ + + /* Disable further interrupts and stop the timer */ + + stm32_putreg16(priv, STM32_GTIM_DIER_OFFSET, 0); + stm32_putreg16(priv, STM32_GTIM_SR_OFFSET, 0); + + /* Determine which timer to reset */ + + switch (priv->config->timid) + { +#ifdef CONFIG_STM32_TIM1_PWM + case 1: + regaddr = STM32_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM1RST; + break; +#endif +#ifdef CONFIG_STM32_TIM2_PWM + case 2: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM2RST; + break; +#endif +#ifdef CONFIG_STM32_TIM3_PWM + case 3: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM3RST; + break; +#endif +#ifdef CONFIG_STM32_TIM4_PWM + case 4: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM4RST; + break; +#endif +#ifdef CONFIG_STM32_TIM5_PWM + case 5: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM5RST; + break; +#endif +#ifdef CONFIG_STM32_TIM8_PWM + case 8: + regaddr = STM32_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM8RST; + break; +#endif + default: + return -EINVAL; + } + + /* Reset the timer - stopping the output and putting the timer back + * into a state where stm32_start() can be called. + */ + + regval = getreg32(regaddr); + regval |= resetbit; + putreg32(regval, regaddr); + + regval &= ~resetbit; + putreg32(regval, regaddr); + irqrestore(flags); + + qevdbg("regaddr: %08x resetbit: %08x\n", regaddr, resetbit); + stm32_dumpregs(priv, "After stop"); + + /* Put the TI1 GPIO pin back to its default state */ + + pincfg = priv->config->ti1cfg & (GPIO_PORT_MASK|GPIO_PIN_MASK); + +#if defined(CONFIG_STM32_STM32F10XX) + pincfg |= (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT); +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + pincfg |= (GPIO_INPUT|GPIO_FLOAT); +#else +# error "Unrecognized STM32 chip" +#endif + + stm32_configgpio(pincfg); + + /* Put the TI2 GPIO pin back to its default state */ + + pincfg = priv->config->ti2cfg & (GPIO_PORT_MASK|GPIO_PIN_MASK); + +#if defined(CONFIG_STM32_STM32F10XX) + pincfg |= (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT); +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) + pincfg |= (GPIO_INPUT|GPIO_FLOAT); +#else +# error "Unrecognized STM32 chip" +#endif + + stm32_configgpio(pincfg); + return -ENOSYS; +} + +/************************************************************************************ + * Name: stm32_position + * + * Description: + * Return the current position measurement. + * + ************************************************************************************/ + +static int stm32_position(FAR struct qe_lowerhalf_s *lower, int32_t *pos) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; +#ifdef HAVE_16BIT_TIMERS + int32_t position; + int32_t verify; + uint32_t count; + + DEBUGASSERT(lower && priv->inuse); + + /* Loop until we are certain that no interrupt occurred between samples */ + + do + { + /* Don't let another task pre-empt us until we get the measurement. The timer + * interrupt may still be processed + */ + + sched_lock(); + position = priv->position; + count = stm32_getreg32(priv, STM32_GTIM_CNT_OFFSET); + verify = priv->position; + sched_unlock(); + } + while (position != verify); + + /* Return the position measurement */ + + *pos = position + (int32_t)count; +#else + /* Return the counter value */ + + *pos = (int32_t)stm32_getreg32(priv, STM32_GTIM_CNT_OFFSET);; +#endif + return OK; +} + +/************************************************************************************ + * Name: stm32_reset + * + * Description: + * Reset the position measurement to zero. + * + ************************************************************************************/ + +static int stm32_reset(FAR struct qe_lowerhalf_s *lower) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; +#ifdef HAVE_16BIT_TIMERS + irqstate_t flags; + + qevdbg("Resetting position to zero\n"); + DEBUGASSERT(lower && priv->inuse); + + /* Reset the timer and the counter. Interrupts are disabled to make this atomic + * (if possible) + */ + + flags = irqsave(); + stm32_putreg32(priv, STM32_GTIM_CNT_OFFSET, 0); + priv->position = 0; + irqrestore(flags); +#else + qevdbg("Resetting position to zero\n"); + DEBUGASSERT(lower && priv->inuse); + + /* Reset the counter to zero */ + + stm32_putreg32(priv, STM32_GTIM_CNT_OFFSET, 0); +#endif + return OK; +} + +/************************************************************************************ + * Name: stm32_ioctl + * + * Description: + * Lower-half logic may support platform-specific ioctl commands + * + ************************************************************************************/ + +static int stm32_ioctl(FAR struct qe_lowerhalf_s *lower, int cmd, unsigned long arg) +{ + /* No ioctl commands supported */ + + return -ENOTTY; +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_qeinitialize + * + * Description: + * Initialize a quadrature encoder interface. This function must be called from + * board-specific logic. + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/qe0" + * tim - The timer number to used. 'tim' must be an element of {1,2,3,4,5,8} + * + * Returned Values: + * Zero on success; A negated errno value is returned on failure. + * + ************************************************************************************/ + +int stm32_qeinitialize(FAR const char *devpath, int tim) +{ + FAR struct stm32_lowerhalf_s *priv; + int ret; + + /* Find the pre-allocated timer state structure corresponding to this timer */ + + priv = stm32_tim2lower(tim); + if (!priv) + { + qedbg("TIM%d support not configured\n", tim); + return -ENXIO; + } + + /* Make sure that it is available */ + + if (priv->inuse) + { + qedbg("TIM%d is in-used\n", tim); + return -EBUSY; + } + + /* Register the priv-half driver */ + + ret = qe_register(devpath, (FAR struct qe_lowerhalf_s *)priv); + if (ret < 0) + { + qedbg("qe_register failed: %d\n", ret); + return ret; + } + + /* Make sure that the timer is in the shutdown state */ + + stm32_shutdown((FAR struct qe_lowerhalf_s *)priv); + + /* The driver is now in-use */ + + priv->inuse = true; + return OK; +} + +#endif /* CONFIG_QENCODER */ diff --git a/nuttx/arch/arm/src/stm32/stm32_qencoder.h b/nuttx/arch/arm/src/stm32/stm32_qencoder.h new file mode 100644 index 0000000000..5effa7163d --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_qencoder.h @@ -0,0 +1,142 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_qencoder.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_QENCODER_H +#define __ARCH_ARM_SRC_STM32_STM32_QENCODER_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" + +#ifdef CONFIG_QENCODER + +/************************************************************************************ + * Included Files + ************************************************************************************/ +/* Timer devices may be used for different purposes. One special purpose is as + * a quadrature encoder input device. If CONFIG_STM32_TIMn is defined then the + * CONFIG_STM32_TIMn_QE must also be defined to indicate that timer "n" is intended + * to be used for as a quadrature encoder. + */ + +#ifndef CONFIG_STM32_TIM1 +# undef CONFIG_STM32_TIM1_QE +#endif +#ifndef CONFIG_STM32_TIM2 +# undef CONFIG_STM32_TIM2_QE +#endif +#ifndef CONFIG_STM32_TIM3 +# undef CONFIG_STM32_TIM3_QE +#endif +#ifndef CONFIG_STM32_TIM4 +# undef CONFIG_STM32_TIM4_QE +#endif +#ifndef CONFIG_STM32_TIM5 +# undef CONFIG_STM32_TIM5_QE +#endif +#ifndef CONFIG_STM32_TIM8 +# undef CONFIG_STM32_TIM8_QE +#endif + +/* Only timers 2-5, and 1 & 8 can be used as a quadrature encoder (at least for the + * STM32 F4) + */ + +#undef CONFIG_STM32_TIM6_QE +#undef CONFIG_STM32_TIM7_QE +#undef CONFIG_STM32_TIM9_QE +#undef CONFIG_STM32_TIM10_QE +#undef CONFIG_STM32_TIM11_QE +#undef CONFIG_STM32_TIM12_QE +#undef CONFIG_STM32_TIM13_QE +#undef CONFIG_STM32_TIM14_QE + +/* Clock out frequency. This value is used to calculation the timer CLKIN in + * prescaler value. + */ + +#ifndef CONFIG_STM32_TIM1_QECLKOUT +# define CONFIG_STM32_TIM1_QECLKOUT 28000000 +#endif + +#ifndef CONFIG_STM32_TIM2_QECLKOUT +# define CONFIG_STM32_TIM2_QECLKOUT 28000000 +#endif + +#ifndef CONFIG_STM32_TIM3_QECLKOUT +# define CONFIG_STM32_TIM3_QECLKOUT 28000000 +#endif + +#ifndef CONFIG_STM32_TIM4_QECLKOUT +# define CONFIG_STM32_TIM4_QECLKOUT 28000000 +#endif + +#ifndef CONFIG_STM32_TIM5_QECLKOUT +# define CONFIG_STM32_TIM5_QECLKOUT 28000000 +#endif + +#ifndef CONFIG_STM32_TIM8_QECLKOUT +# define CONFIG_STM32_TIM8_QECLKOUT 28000000 +#endif + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_qeinitialize + * + * Description: + * Initialize a quadrature encoder interface. This function must be called from + * board-specific logic.. + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/qe0" + * tim - The timer number to used. 'tim' must be an element of {1,2,3,4,5,8} + * + * Returned Values: + * Zero on success; A negated errno value is returned on failure. + * + ************************************************************************************/ + +int stm32_qeinitialize(FAR const char *devpath, int tim); + +#endif /* CONFIG_QENCODER */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_QENCODER_H */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_rcc.c b/nuttx/arch/arm/src/stm32/stm32_rcc.c new file mode 100644 index 0000000000..6656186f28 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_rcc.c @@ -0,0 +1,183 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_rcc.c + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "up_internal.h" +#include "up_arch.h" + +#include "chip.h" +#include "stm32_rcc.h" +#include "stm32_flash.h" +#include "stm32_internal.h" +#include "stm32_waste.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Allow up to 100 milliseconds for the high speed clock to become ready. + * that is a very long delay, but if the clock does not become ready we are + * hosed anyway. + */ + +#define HSERDY_TIMEOUT (100 * CONFIG_BOARD_LOOPSPERMSEC) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Include chip-specific clocking initialization logic */ + +#if defined(CONFIG_STM32_STM32F10XX) +# include "chip/stm32f10xxx_rcc.c" +#elif defined(CONFIG_STM32_STM32F20XX) +# include "chip/stm32f20xxx_rcc.c" +#elif defined(CONFIG_STM32_STM32F40XX) +# include "chip/stm32f40xxx_rcc.c" +#else +# error "Unsupported STM32 chip" +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/************************************************************************************ + * Name: stm32_clockconfig + * + * Description: + * Called to establish the clock settings based on the values in board.h. This + * function (by default) will reset most everything, enable the PLL, and enable + * peripheral clocking for all periperipherals enabled in the NuttX configuration + * file. + * + * If CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG is defined, then clocking will + * be enabled by an externally provided, board-specific function called + * stm32_board_clockconfig(). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +void stm32_clockconfig(void) +{ + /* Make sure that we are starting in the reset state */ + + rcc_reset(); + +#if defined(CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG) + + /* Invoke Board Custom Clock Configuration */ + + stm32_board_clockconfig(); + +#else + + /* Invoke standard, fixed clock configuration based on definitions in board.h */ + + stm32_stdclockconfig(); + +#endif + + /* Enable peripheral clocking */ + + rcc_enableperipherals(); +} + +/************************************************************************************ + * Name: stm32_clockenable + * + * Description: + * Re-enable the clock and restore the clock settings based on settings in board.h. + * This function is only available to support low-power modes of operation: When + * re-awakening from deep-sleep modes, it is necessary to re-enable/re-start the + * PLL + * + * This functional performs a subset of the operations performed by + * stm32_clockconfig(): It does not reset any devices, and it does not reset the + * currenlty enabled peripheral clocks. + * + * If CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG is defined, then clocking will + * be enabled by an externally provided, board-specific function called + * stm32_board_clockconfig(). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifdef CONFIG_PM +void stm32_clockenable(void) +{ +#if defined(CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG) + + /* Invoke Board Custom Clock Configuration */ + + stm32_board_clockconfig(); + +#else + + /* Invoke standard, fixed clock configuration based on definitions in board.h */ + + stm32_stdclockconfig(); + +#endif +} +#endif + + diff --git a/nuttx/arch/arm/src/stm32/stm32_rcc.h b/nuttx/arch/arm/src/stm32/stm32_rcc.h new file mode 100644 index 0000000000..c4d43db3a7 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_rcc.h @@ -0,0 +1,239 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_rcc.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_RRC_H +#define __ARCH_ARM_SRC_STM32_STM32_RRC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "up_arch.h" +#include "chip.h" + +#if defined(CONFIG_STM32_STM32F10XX) +# include "chip/stm32f10xxx_rcc.h" +#elif defined(CONFIG_STM32_STM32F20XX) +# include "chip/stm32f20xxx_rcc.h" +#elif defined(CONFIG_STM32_STM32F40XX) +# include "chip/stm32f40xxx_rcc.h" +#endif + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/* This symbol references the Cortex-M3 vector table (as positioned by the the linker + * script, ld.script or ld.script.dfu. The standard location for the vector table is + * at the beginning of FLASH at address 0x0800:0000. If we are using the STMicro DFU + * bootloader, then the vector table will be offset to a different location in FLASH + * and we will need to set the NVIC vector location to this alternative location. + */ + +extern uint32_t stm32_vectors[]; /* See stm32_vectors.S */ + +/************************************************************************************ + * Inline Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_mco1config + * + * Description: + * Selects the clock source to output on MCO1 pin (PA8). PA8 should be configured in + * alternate function mode. + * + * Input Parameters: + * source - One of the definitions for the RCC_CFGR_MCO1 definitions from + * chip/stm32f40xxx_rcc.h {RCC_CFGR_MCO1_HSI, RCC_CFGR_MCO1_LSE, + * RCC_CFGR_MCO1_HSE, RCC_CFGR_MCO1_PLL} + * div - One of the definitions for the RCC_CFGR_MCO1PRE definitions from + * chip/stm32f40xxx_rcc.h {RCC_CFGR_MCO1PRE_NONE, RCC_CFGR_MCO1PRE_DIV2, + * RCC_CFGR_MCO1PRE_DIV3, RCC_CFGR_MCO1PRE_DIV4, RCC_CFGR_MCO1PRE_DIV5} + * + * Returned Value: + * None + * + ************************************************************************************/ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +static inline void stm32_mco1config(uint32_t source, uint32_t div) +{ + uint32_t regval; + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~(RCC_CFGR_MCO1_MASK|RCC_CFGR_MCO1PRE_MASK); + regval |= (source | div); + putreg32(regval, STM32_RCC_CFGR); +} +#endif + +/************************************************************************************ + * Name: stm32_mco2config + * + * Description: + * Selects the clock source to output on MCO2 pin (PC9). PC9 should be configured in + * alternate function mode. + * + * Input Parameters: + * source - One of the definitions for the RCC_CFGR_MCO2 definitions from + * chip/stm32f40xxx_rcc.h {RCC_CFGR_MCO2_SYSCLK, RCC_CFGR_MCO2_PLLI2S, + * RCC_CFGR_MCO2_HSE, RCC_CFGR_MCO2_PLL} + * div - One of the definitions for the RCC_CFGR_MCO2PRE definitions from + * chip/stm32f40xxx_rcc.h {RCC_CFGR_MCO2PRE_NONE, RCC_CFGR_MCO2PRE_DIV2, + * RCC_CFGR_MCO2PRE_DIV3, RCC_CFGR_MCO2PRE_DIV4, RCC_CFGR_MCO2PRE_DIV5} + * + * Returned Value: + * None + * + ************************************************************************************/ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +static inline void stm32_mco2config(uint32_t source, uint32_t div) +{ + uint32_t regval; + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~(RCC_CFGR_MCO2_MASK|RCC_CFGR_MCO2PRE_MASK); + regval |= (source | div); + putreg32(regval, STM32_RCC_CFGR); +} +#endif + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_clockconfig + * + * Description: + * Called to establish the clock settings based on the values in board.h. This + * function (by default) will reset most everything, enable the PLL, and enable + * peripheral clocking for all periperipherals enabled in the NuttX configuration + * file. + * + * If CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG is defined, then clocking will + * be enabled by an externally provided, board-specific function called + * stm32_board_clockconfig(). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +EXTERN void stm32_clockconfig(void); + +/************************************************************************************ + * Name: stm32_clockenable + * + * Description: + * Re-enable the clock and restore the clock settings based on settings in board.h. + * This function is only available to support low-power modes of operation: When + * re-awakening from deep-sleep modes, it is necessary to re-enable/re-start the + * PLL + * + * This functional performs a subset of the operations performed by + * stm32_clockconfig(): It does not reset any devices, and it does not reset the + * currenlty enabled peripheral clocks. + * + * If CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG is defined, then clocking will + * be enabled by an externally provided, board-specific function called + * stm32_board_clockconfig(). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifdef CONFIG_PM +EXTERN void stm32_clockenable(void); +#endif + +/************************************************************************************ + * Name: stm32_rcc_enablelse + * + * Description: + * Enable the External Low-Speed (LSE) Oscillator and, if the RTC is + * configured, setup the LSE as the RTC clock source, and enable the RTC. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +EXTERN void stm32_rcc_enablelse(void); + +/**************************************************************************** + * Name: stm32_rcc_enablelsi + * + * Description: + * Enable the Internal Low-Speed (LSI) RC Oscillator. + * + ****************************************************************************/ + +EXTERN void stm32_rcc_enablelsi(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_RRC_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_rtc.c b/nuttx/arch/arm/src/stm32/stm32_rtc.c new file mode 100644 index 0000000000..b79a74dcb5 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_rtc.c @@ -0,0 +1,80 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_rtc.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* This file is only a thin shell that includes the correct RTC implementation + * for the selected STM32 family. The correct file cannot be selected by + * the make system because it needs the intelligence that only exists in + * chip.h that can associate an STM32 part number with an STM32 family. + * + * The STM32 F4 RTC differs dramatically the F1 RTC. The F1 RTC is a simple + * battery-backed counter; the F4 RTC is provides broken-out data/time in BCD + * format. + */ + +#if defined(CONFIG_STM32_STM32F10XX) +# include "stm32f10xxx_rtc.c" +#elif defined(CONFIG_STM32_STM32F20XX) +# include "stm32f20xxx_rtc.c" +#elif defined(CONFIG_STM32_STM32F40XX) +# include "stm32f40xxx_rtc.c" +#endif diff --git a/nuttx/arch/arm/src/stm32/stm32_rtc.h b/nuttx/arch/arm/src/stm32/stm32_rtc.h new file mode 100644 index 0000000000..11822f76c8 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_rtc.h @@ -0,0 +1,85 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_rtc.h + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_RTC_H +#define __ARCH_ARM_SRC_STM32_STM32_RTC_H + +#include + +#include "chip.h" +#if defined(CONFIG_STM32_STM32F10XX) +# include "chip/stm32f10xxx_rtc.h" +# include "chip/stm32_bkp.h" +#elif defined(CONFIG_STM32_STM32F20XX) +# include "chip/stm32f20xxx_rtc.h" +#elif defined(CONFIG_STM32_STM32F40XX) +# include "chip/stm32f40xxx_rtc.h" +#endif + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#define STM32_RTC_PRESCALER_SECOND 32767 /* Default prescaler to get a second base */ +#define STM32_RTC_PRESCALER_MIN 1 /* Maximum speed of 16384 Hz */ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/* Set alarm output pin */ + +EXTERN void stm32_rtc_settalarmpin(bool activate); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_RTC_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_sdio.c b/nuttx/arch/arm/src/stm32/stm32_sdio.c new file mode 100644 index 0000000000..b109160a17 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_sdio.c @@ -0,0 +1,2842 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_sdio.c + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "chip.h" +#include "up_arch.h" + +#include "stm32_internal.h" +#include "stm32_dma.h" +#include "stm32_sdio.h" + +#if CONFIG_STM32_SDIO + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ +/* Required system configuration options: + * + * CONFIG_ARCH_DMA - Enable architecture-specific DMA subsystem + * initialization. Required if CONFIG_SDIO_DMA is enabled. + * CONFIG_STM32_DMA2 - Enable STM32 DMA2 support. Required if + * CONFIG_SDIO_DMA is enabled + * CONFIG_SCHED_WORKQUEUE -- Callback support requires work queue support. + * + * Driver-specific configuration options: + * + * CONFIG_SDIO_MUXBUS - Setting this configuration enables some locking + * APIs to manage concurrent accesses on the SDIO bus. This is not + * needed for the simple case of a single SD card, for example. + * CONFIG_SDIO_DMA - Enable SDIO. This is a marginally optional. For + * most usages, SDIO will cause data overruns if used without DMA. + * NOTE the above system DMA configuration options. + * CONFIG_SDIO_WIDTH_D1_ONLY - This may be selected to force the driver + * operate with only a single data line (the default is to use all + * 4 SD data lines). + * CONFIG_SDIO_PRI - SDIO interrupt priority. This setting is not very + * important since interrupt nesting is not currently supported. + * CONFIG_SDM_DMAPRIO - SDIO DMA priority. This can be selecte if + * CONFIG_SDIO_DMA is enabled. + * CONFIG_SDIO_XFRDEBUG - Enables some very low-level debug output + * This also requires CONFIG_DEBUG_FS and CONFIG_DEBUG_VERBOSE + */ + +#if defined(CONFIG_SDIO_DMA) && !defined(CONFIG_STM32_DMA2) +# warning "CONFIG_SDIO_DMA support requires CONFIG_STM32_DMA2" +#endif + +#ifndef CONFIG_SDIO_DMA +# warning "Large Non-DMA transfer may result in RX overrun failures" +#endif + +#ifndef CONFIG_SCHED_WORKQUEUE +# error "Callback support requires CONFIG_SCHED_WORKQUEUE" +#endif + +#ifndef CONFIG_SDIO_PRI +# define CONFIG_SDIO_PRI NVIC_SYSH_PRIORITY_DEFAULT +#endif + +#ifdef CONFIG_SDIO_DMA +# ifndef CONFIG_SDIO_DMAPRIO +# if defined(CONFIG_STM32_STM32F10XX) +# define CONFIG_SDIO_DMAPRIO DMA_CCR_PRIMED +# elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define CONFIG_SDIO_DMAPRIO DMA_SCR_PRIVERYHI +# else +# error "Unknown STM32 DMA" +# endif +# endif +# if defined(CONFIG_STM32_STM32F10XX) +# if (CONFIG_SDIO_DMAPRIO & ~DMA_CCR_PL_MASK) != 0 +# error "Illegal value for CONFIG_SDIO_DMAPRIO" +# endif +# elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# if (CONFIG_SDIO_DMAPRIO & ~DMA_SCR_PL_MASK) != 0 +# error "Illegal value for CONFIG_SDIO_DMAPRIO" +# endif +# else +# error "Unknown STM32 DMA" +# endif +#else +# undef CONFIG_SDIO_DMAPRIO +#endif + +#if !defined(CONFIG_DEBUG_FS) || !defined(CONFIG_DEBUG) +# undef CONFIG_SDIO_XFRDEBUG +#endif + +/* Friendly CLKCR bit re-definitions ****************************************/ + +#define SDIO_CLKCR_RISINGEDGE (0) +#define SDIO_CLKCR_FALLINGEDGE SDIO_CLKCR_NEGEDGE + +/* Mode dependent settings. These depend on clock devisor settings that must + * be defined in the board-specific board.h header file: SDIO_INIT_CLKDIV, + * SDIO_MMCXFR_CLKDIV, and SDIO_SDXFR_CLKDIV. + */ + +#define STM32_CLCKCR_INIT (SDIO_INIT_CLKDIV|SDIO_CLKCR_RISINGEDGE|\ + SDIO_CLKCR_WIDBUS_D1) +#define SDIO_CLKCR_MMCXFR (SDIO_MMCXFR_CLKDIV|SDIO_CLKCR_RISINGEDGE|\ + SDIO_CLKCR_WIDBUS_D1) +#define SDIO_CLCKR_SDXFR (SDIO_SDXFR_CLKDIV|SDIO_CLKCR_RISINGEDGE|\ + SDIO_CLKCR_WIDBUS_D1) +#define SDIO_CLCKR_SDWIDEXFR (SDIO_SDXFR_CLKDIV|SDIO_CLKCR_RISINGEDGE|\ + SDIO_CLKCR_WIDBUS_D4) + +/* Timing */ + +#define SDIO_CMDTIMEOUT (100000) +#define SDIO_LONGTIMEOUT (0x7fffffff) + +/* Big DTIMER setting */ + +#define SDIO_DTIMER_DATATIMEOUT (0x000fffff) + +/* DMA channel/stream configuration register settings. The following + * must be selected. The DMA driver will select the remaining fields. + * + * - 32-bit DMA + * - Memory increment + * - Direction (memory-to-peripheral, peripheral-to-memory) + * - Memory burst size (F4 only) + */ + +/* STM32 F1 channel configuration register (CCR) settings */ + +#if defined(CONFIG_STM32_STM32F10XX) +# define SDIO_RXDMA32_CONFIG (CONFIG_SDIO_DMAPRIO|DMA_CCR_MSIZE_32BITS|\ + DMA_CCR_PSIZE_32BITS|DMA_CCR_MINC) +# define SDIO_TXDMA32_CONFIG (CONFIG_SDIO_DMAPRIO|DMA_CCR_MSIZE_32BITS|\ + DMA_CCR_PSIZE_32BITS|DMA_CCR_MINC|DMA_CCR_DIR) + +/* STM32 F4 stream configuration register (SCR) settings. */ + +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define SDIO_RXDMA32_CONFIG (DMA_SCR_PFCTRL|DMA_SCR_DIR_P2M|DMA_SCR_MINC|\ + DMA_SCR_PSIZE_32BITS|DMA_SCR_MSIZE_32BITS|\ + CONFIG_SDIO_DMAPRIO|DMA_SCR_PBURST_INCR4|\ + DMA_SCR_MBURST_INCR4) +# define SDIO_TXDMA32_CONFIG (DMA_SCR_PFCTRL|DMA_SCR_DIR_M2P|DMA_SCR_MINC|\ + DMA_SCR_PSIZE_32BITS|DMA_SCR_MSIZE_32BITS|\ + CONFIG_SDIO_DMAPRIO|DMA_SCR_PBURST_INCR4|\ + DMA_SCR_MBURST_INCR4) +#else +# error "Unknown STM32 DMA" +#endif + +/* SDIO DMA Channel/Stream selection. For the the case of the STM32 F4, there + * are multiple DMA stream options that must be dis-ambiguated in the board.h + * file. + */ + +#if defined(CONFIG_STM32_STM32F10XX) +# define SDIO_DMACHAN DMACHAN_SDIO +#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define SDIO_DMACHAN DMAMAP_SDIO +#else +# error "Unknown STM32 DMA" +#endif + +/* FIFO sizes */ + +#define SDIO_HALFFIFO_WORDS (8) +#define SDIO_HALFFIFO_BYTES (8*4) + +/* Data transfer interrupt mask bits */ + +#define SDIO_RECV_MASK (SDIO_MASK_DCRCFAILIE|SDIO_MASK_DTIMEOUTIE|\ + SDIO_MASK_DATAENDIE|SDIO_MASK_RXOVERRIE|\ + SDIO_MASK_RXFIFOHFIE|SDIO_MASK_STBITERRIE) +#define SDIO_SEND_MASK (SDIO_MASK_DCRCFAILIE|SDIO_MASK_DTIMEOUTIE|\ + SDIO_MASK_DATAENDIE|SDIO_MASK_TXUNDERRIE|\ + SDIO_MASK_TXFIFOHEIE|SDIO_MASK_STBITERRIE) +#define SDIO_DMARECV_MASK (SDIO_MASK_DCRCFAILIE|SDIO_MASK_DTIMEOUTIE|\ + SDIO_MASK_DATAENDIE|SDIO_MASK_RXOVERRIE|\ + SDIO_MASK_STBITERRIE) +#define SDIO_DMASEND_MASK (SDIO_MASK_DCRCFAILIE|SDIO_MASK_DTIMEOUTIE|\ + SDIO_MASK_DATAENDIE|SDIO_MASK_TXUNDERRIE|\ + SDIO_MASK_STBITERRIE) + +/* Event waiting interrupt mask bits */ + +#define SDIO_CMDDONE_STA (SDIO_STA_CMDSENT) +#define SDIO_RESPDONE_STA (SDIO_STA_CTIMEOUT|SDIO_STA_CCRCFAIL|\ + SDIO_STA_CMDREND) +#define SDIO_XFRDONE_STA (0) + +#define SDIO_CMDDONE_MASK (SDIO_MASK_CMDSENTIE) +#define SDIO_RESPDONE_MASK (SDIO_MASK_CCRCFAILIE|SDIO_MASK_CTIMEOUTIE|\ + SDIO_MASK_CMDRENDIE) +#define SDIO_XFRDONE_MASK (0) + +#define SDIO_CMDDONE_ICR (SDIO_ICR_CMDSENTC) +#define SDIO_RESPDONE_ICR (SDIO_ICR_CTIMEOUTC|SDIO_ICR_CCRCFAILC|\ + SDIO_ICR_CMDRENDC) +#define SDIO_XFRDONE_ICR (SDIO_ICR_DATAENDC|SDIO_ICR_DCRCFAILC|\ + SDIO_ICR_DTIMEOUTC|SDIO_ICR_RXOVERRC|\ + SDIO_ICR_TXUNDERRC|SDIO_ICR_STBITERRC) + +#define SDIO_WAITALL_ICR (SDIO_CMDDONE_ICR|SDIO_RESPDONE_ICR|\ + SDIO_XFRDONE_ICR) + +/* Let's wait until we have both SDIO transfer complete and DMA complete. */ + +#define SDIO_XFRDONE_FLAG (1) +#define SDIO_DMADONE_FLAG (2) +#define SDIO_ALLDONE (3) + +/* Register logging support */ + +#ifdef CONFIG_SDIO_XFRDEBUG +# ifdef CONFIG_SDIO_DMA +# define SAMPLENDX_BEFORE_SETUP 0 +# define SAMPLENDX_BEFORE_ENABLE 1 +# define SAMPLENDX_AFTER_SETUP 2 +# define SAMPLENDX_END_TRANSFER 3 +# define SAMPLENDX_DMA_CALLBACK 4 +# define DEBUG_NSAMPLES 5 +# else +# define SAMPLENDX_BEFORE_SETUP 0 +# define SAMPLENDX_AFTER_SETUP 1 +# define SAMPLENDX_END_TRANSFER 2 +# define DEBUG_NSAMPLES 3 +# endif +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure defines the state of the STM32 SDIO interface */ + +struct stm32_dev_s +{ + struct sdio_dev_s dev; /* Standard, base SDIO interface */ + + /* STM32-specific extensions */ + /* Event support */ + + sem_t waitsem; /* Implements event waiting */ + sdio_eventset_t waitevents; /* Set of events to be waited for */ + uint32_t waitmask; /* Interrupt enables for event waiting */ + volatile sdio_eventset_t wkupevent; /* The event that caused the wakeup */ + WDOG_ID waitwdog; /* Watchdog that handles event timeouts */ + + /* Callback support */ + + uint8_t cdstatus; /* Card status */ + sdio_eventset_t cbevents; /* Set of events to be cause callbacks */ + worker_t callback; /* Registered callback function */ + void *cbarg; /* Registered callback argument */ + struct work_s cbwork; /* Callback work queue structure */ + + /* Interrupt mode data transfer support */ + + uint32_t *buffer; /* Address of current R/W buffer */ + size_t remaining; /* Number of bytes remaining in the transfer */ + uint32_t xfrmask; /* Interrupt enables for data transfer */ + + /* DMA data transfer support */ + + bool widebus; /* Required for DMA support */ +#ifdef CONFIG_SDIO_DMA + volatile uint8_t xfrflags; /* Used to synchronize SDIO and DMA completion events */ + bool dmamode; /* true: DMA mode transfer */ + DMA_HANDLE dma; /* Handle for DMA channel */ +#endif +}; + +/* Register logging support */ + +#ifdef CONFIG_SDIO_XFRDEBUG +struct stm32_sdioregs_s +{ + uint8_t power; + uint16_t clkcr; + uint16_t dctrl; + uint32_t dtimer; + uint32_t dlen; + uint32_t dcount; + uint32_t sta; + uint32_t mask; + uint32_t fifocnt; +}; + +struct stm32_sampleregs_s +{ + struct stm32_sdioregs_s sdio; +#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA) + struct stm32_dmaregs_s dma; +#endif +}; +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Low-level helpers ********************************************************/ + +static void stm32_takesem(struct stm32_dev_s *priv); +#define stm32_givesem(priv) (sem_post(&priv->waitsem)) +static inline void stm32_setclkcr(uint32_t clkcr); +static void stm32_configwaitints(struct stm32_dev_s *priv, uint32_t waitmask, + sdio_eventset_t waitevents, sdio_eventset_t wkupevents); +static void stm32_configxfrints(struct stm32_dev_s *priv, uint32_t xfrmask); +static void stm32_setpwrctrl(uint32_t pwrctrl); +static inline uint32_t stm32_getpwrctrl(void); + +/* DMA Helpers **************************************************************/ + +#ifdef CONFIG_SDIO_XFRDEBUG +static void stm32_sampleinit(void); +static void stm32_sdiosample(struct stm32_sdioregs_s *regs); +static void stm32_sample(struct stm32_dev_s *priv, int index); +static void stm32_sdiodump(struct stm32_sdioregs_s *regs, const char *msg); +static void stm32_dumpsample(struct stm32_dev_s *priv, + struct stm32_sampleregs_s *regs, const char *msg); +static void stm32_dumpsamples(struct stm32_dev_s *priv); +#else +# define stm32_sampleinit() +# define stm32_sample(priv,index) +# define stm32_dumpsamples(priv) +#endif + +#ifdef CONFIG_SDIO_DMA +static void stm32_dmacallback(DMA_HANDLE handle, uint8_t status, void *arg); +#endif + +/* Data Transfer Helpers ****************************************************/ + +static uint8_t stm32_log2(uint16_t value); +static void stm32_dataconfig(uint32_t timeout, uint32_t dlen, uint32_t dctrl); +static void stm32_datadisable(void); +static void stm32_sendfifo(struct stm32_dev_s *priv); +static void stm32_recvfifo(struct stm32_dev_s *priv); +static void stm32_eventtimeout(int argc, uint32_t arg); +static void stm32_endwait(struct stm32_dev_s *priv, sdio_eventset_t wkupevent); +static void stm32_endtransfer(struct stm32_dev_s *priv, sdio_eventset_t wkupevent); + +/* Interrupt Handling *******************************************************/ + +static int stm32_interrupt(int irq, void *context); + +/* SDIO interface methods ***************************************************/ + +/* Mutual exclusion */ + +#ifdef CONFIG_SDIO_MUXBUS +static int stm32_lock(FAR struct sdio_dev_s *dev, bool lock); +#endif + +/* Initialization/setup */ + +static void stm32_reset(FAR struct sdio_dev_s *dev); +static uint8_t stm32_status(FAR struct sdio_dev_s *dev); +static void stm32_widebus(FAR struct sdio_dev_s *dev, bool enable); +static void stm32_clock(FAR struct sdio_dev_s *dev, + enum sdio_clock_e rate); +static int stm32_attach(FAR struct sdio_dev_s *dev); + +/* Command/Status/Data Transfer */ + +static int stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, + uint32_t arg); +static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, + size_t nbytes); +static int stm32_sendsetup(FAR struct sdio_dev_s *dev, + FAR const uint8_t *buffer, uint32_t nbytes); +static int stm32_cancel(FAR struct sdio_dev_s *dev); + +static int stm32_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd); +static int stm32_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd, + uint32_t *rshort); +static int stm32_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd, + uint32_t rlong[4]); +static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, + uint32_t *rshort); +static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd, + uint32_t *rnotimpl); + +/* EVENT handler */ + +static void stm32_waitenable(FAR struct sdio_dev_s *dev, + sdio_eventset_t eventset); +static sdio_eventset_t + stm32_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout); +static void stm32_callbackenable(FAR struct sdio_dev_s *dev, + sdio_eventset_t eventset); +static int stm32_registercallback(FAR struct sdio_dev_s *dev, + worker_t callback, void *arg); + +/* DMA */ + +#ifdef CONFIG_SDIO_DMA +static bool stm32_dmasupported(FAR struct sdio_dev_s *dev); +static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev, + FAR uint8_t *buffer, size_t buflen); +static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev, + FAR const uint8_t *buffer, size_t buflen); +#endif + +/* Initialization/uninitialization/reset ************************************/ + +static void stm32_callback(void *arg); +static void stm32_default(void); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct stm32_dev_s g_sdiodev = +{ + .dev = + { +#ifdef CONFIG_SDIO_MUXBUS + .lock = stm32_lock, +#endif + .reset = stm32_reset, + .status = stm32_status, + .widebus = stm32_widebus, + .clock = stm32_clock, + .attach = stm32_attach, + .sendcmd = stm32_sendcmd, + .recvsetup = stm32_recvsetup, + .sendsetup = stm32_sendsetup, + .cancel = stm32_cancel, + .waitresponse = stm32_waitresponse, + .recvR1 = stm32_recvshortcrc, + .recvR2 = stm32_recvlong, + .recvR3 = stm32_recvshort, + .recvR4 = stm32_recvnotimpl, + .recvR5 = stm32_recvnotimpl, + .recvR6 = stm32_recvshortcrc, + .recvR7 = stm32_recvshort, + .waitenable = stm32_waitenable, + .eventwait = stm32_eventwait, + .callbackenable = stm32_callbackenable, + .registercallback = stm32_registercallback, +#ifdef CONFIG_SDIO_DMA + .dmasupported = stm32_dmasupported, + .dmarecvsetup = stm32_dmarecvsetup, + .dmasendsetup = stm32_dmasendsetup, +#endif + }, +}; + +/* Register logging support */ + +#ifdef CONFIG_SDIO_XFRDEBUG +static struct stm32_sampleregs_s g_sampleregs[DEBUG_NSAMPLES]; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Low-level Helpers + ****************************************************************************/ +/**************************************************************************** + * Name: stm32_takesem + * + * Description: + * Take the wait semaphore (handling false alarm wakeups due to the receipt + * of signals). + * + * Input Parameters: + * dev - Instance of the SDIO device driver state structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void stm32_takesem(struct stm32_dev_s *priv) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&priv->waitsem) != 0) + { + /* The only case that an error should occr here is if the wait was + * awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Name: stm32_setclkcr + * + * Description: + * Modify oft-changed bits in the CLKCR register. Only the following bit- + * fields are changed: + * + * CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, and HWFC_EN + * + * Input Parameters: + * clkcr - A new CLKCR setting for the above mentions bits (other bits + * are ignored. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void stm32_setclkcr(uint32_t clkcr) +{ + uint32_t regval = getreg32(STM32_SDIO_CLKCR); + + /* Clear CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, HWFC_EN bits */ + + regval &= ~(SDIO_CLKCR_CLKDIV_MASK|SDIO_CLKCR_PWRSAV|SDIO_CLKCR_BYPASS| + SDIO_CLKCR_WIDBUS_MASK|SDIO_CLKCR_NEGEDGE|SDIO_CLKCR_HWFC_EN| + SDIO_CLKCR_CLKEN); + + /* Replace with user provided settings */ + + clkcr &= (SDIO_CLKCR_CLKDIV_MASK|SDIO_CLKCR_PWRSAV|SDIO_CLKCR_BYPASS| + SDIO_CLKCR_WIDBUS_MASK|SDIO_CLKCR_NEGEDGE|SDIO_CLKCR_HWFC_EN| + SDIO_CLKCR_CLKEN); + + regval |= clkcr; + putreg32(regval, STM32_SDIO_CLKCR); + + fvdbg("CLKCR: %08x PWR: %08x\n", + getreg32(STM32_SDIO_CLKCR), getreg32(STM32_SDIO_POWER)); +} + +/**************************************************************************** + * Name: stm32_configwaitints + * + * Description: + * Enable/disable SDIO interrupts needed to suport the wait function + * + * Input Parameters: + * priv - A reference to the SDIO device state structure + * waitmask - The set of bits in the SDIO MASK register to set + * waitevents - Waited for events + * wkupevent - Wake-up events + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void stm32_configwaitints(struct stm32_dev_s *priv, uint32_t waitmask, + sdio_eventset_t waitevents, + sdio_eventset_t wkupevent) +{ + irqstate_t flags; + + /* Save all of the data and set the new interrupt mask in one, atomic + * operation. + */ + + flags = irqsave(); + priv->waitevents = waitevents; + priv->wkupevent = wkupevent; + priv->waitmask = waitmask; +#ifdef CONFIG_SDIO_DMA + priv->xfrflags = 0; +#endif + putreg32(priv->xfrmask | priv->waitmask, STM32_SDIO_MASK); + irqrestore(flags); +} + +/**************************************************************************** + * Name: stm32_configxfrints + * + * Description: + * Enable SDIO interrupts needed to support the data transfer event + * + * Input Parameters: + * priv - A reference to the SDIO device state structure + * xfrmask - The set of bits in the SDIO MASK register to set + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void stm32_configxfrints(struct stm32_dev_s *priv, uint32_t xfrmask) +{ + irqstate_t flags; + flags = irqsave(); + priv->xfrmask = xfrmask; + putreg32(priv->xfrmask | priv->waitmask, STM32_SDIO_MASK); + irqrestore(flags); +} + +/**************************************************************************** + * Name: stm32_setpwrctrl + * + * Description: + * Change the PWRCTRL field of the SDIO POWER register to turn the SDIO + * ON or OFF + * + * Input Parameters: + * clkcr - A new PWRCTRL setting + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void stm32_setpwrctrl(uint32_t pwrctrl) +{ + uint32_t regval; + + regval = getreg32(STM32_SDIO_POWER); + regval &= ~SDIO_POWER_PWRCTRL_MASK; + regval |= pwrctrl; + putreg32(regval, STM32_SDIO_POWER); +} + +/**************************************************************************** + * Name: stm32_getpwrctrl + * + * Description: + * Return the current value of the the PWRCTRL field of the SDIO POWER + * register. This function can be used to see the the SDIO is power ON + * or OFF + * + * Input Parameters: + * None + * + * Returned Value: + * The current value of the the PWRCTRL field of the SDIO POWER register. + * + ****************************************************************************/ + +static inline uint32_t stm32_getpwrctrl(void) +{ + return getreg32(STM32_SDIO_POWER) & SDIO_POWER_PWRCTRL_MASK; +} + +/**************************************************************************** + * DMA Helpers + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_sampleinit + * + * Description: + * Setup prior to collecting DMA samples + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_XFRDEBUG +static void stm32_sampleinit(void) +{ + memset(g_sampleregs, 0xff, DEBUG_NSAMPLES * sizeof(struct stm32_sampleregs_s)); +} +#endif + +/**************************************************************************** + * Name: stm32_sdiosample + * + * Description: + * Sample SDIO registers + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_XFRDEBUG +static void stm32_sdiosample(struct stm32_sdioregs_s *regs) +{ + regs->power = (uint8_t)getreg32(STM32_SDIO_POWER); + regs->clkcr = (uint16_t)getreg32(STM32_SDIO_CLKCR); + regs->dctrl = (uint16_t)getreg32(STM32_SDIO_DCTRL); + regs->dtimer = getreg32(STM32_SDIO_DTIMER); + regs->dlen = getreg32(STM32_SDIO_DLEN); + regs->dcount = getreg32(STM32_SDIO_DCOUNT); + regs->sta = getreg32(STM32_SDIO_STA); + regs->mask = getreg32(STM32_SDIO_MASK); + regs->fifocnt = getreg32(STM32_SDIO_FIFOCNT); +} +#endif + +/**************************************************************************** + * Name: stm32_sample + * + * Description: + * Sample SDIO/DMA registers + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_XFRDEBUG +static void stm32_sample(struct stm32_dev_s *priv, int index) +{ + struct stm32_sampleregs_s *regs = &g_sampleregs[index]; +#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA) + if (priv->dmamode) + { + stm32_dmasample(priv->dma, ®s->dma); + } +#endif + stm32_sdiosample(®s->sdio); +} +#endif + +/**************************************************************************** + * Name: stm32_sdiodump + * + * Description: + * Dump one register sample + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_XFRDEBUG +static void stm32_sdiodump(struct stm32_sdioregs_s *regs, const char *msg) +{ + fdbg("SDIO Registers: %s\n", msg); + fdbg(" POWER[%08x]: %08x\n", STM32_SDIO_POWER, regs->power); + fdbg(" CLKCR[%08x]: %08x\n", STM32_SDIO_CLKCR, regs->clkcr); + fdbg(" DCTRL[%08x]: %08x\n", STM32_SDIO_DCTRL, regs->dctrl); + fdbg(" DTIMER[%08x]: %08x\n", STM32_SDIO_DTIMER, regs->dtimer); + fdbg(" DLEN[%08x]: %08x\n", STM32_SDIO_DLEN, regs->dlen); + fdbg(" DCOUNT[%08x]: %08x\n", STM32_SDIO_DCOUNT, regs->dcount); + fdbg(" STA[%08x]: %08x\n", STM32_SDIO_STA, regs->sta); + fdbg(" MASK[%08x]: %08x\n", STM32_SDIO_MASK, regs->mask); + fdbg("FIFOCNT[%08x]: %08x\n", STM32_SDIO_FIFOCNT, regs->fifocnt); +} +#endif + +/**************************************************************************** + * Name: stm32_dumpsample + * + * Description: + * Dump one register sample + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_XFRDEBUG +static void stm32_dumpsample(struct stm32_dev_s *priv, + struct stm32_sampleregs_s *regs, const char *msg) +{ +#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA) + if (priv->dmamode) + { + stm32_dmadump(priv->dma, ®s->dma, msg); + } +#endif + stm32_sdiodump(®s->sdio, msg); +} +#endif + +/**************************************************************************** + * Name: stm32_dumpsamples + * + * Description: + * Dump all sampled register data + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_XFRDEBUG +static void stm32_dumpsamples(struct stm32_dev_s *priv) +{ + stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_SETUP], "Before setup"); +#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA) + if (priv->dmamode) + { + stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_ENABLE], "Before DMA enable"); + } +#endif + stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_AFTER_SETUP], "After setup"); + stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_END_TRANSFER], "End of transfer"); +#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA) + if (priv->dmamode) + { + stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_DMA_CALLBACK], "DMA Callback"); + } +#endif +} +#endif + +/**************************************************************************** + * Name: stm32_dmacallback + * + * Description: + * Called when SDIO DMA completes + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_DMA +static void stm32_dmacallback(DMA_HANDLE handle, uint8_t status, void *arg) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)arg; + DEBUGASSERT(priv->dmamode); + sdio_eventset_t result; + + /* In the normal case, SDIO appears to handle the End-Of-Transfer interrupt + * first with the End-Of-DMA event occurring significantly later. On + * transfer errors, however, the DMA error will occur before the End-of- + * Transfer. + */ + + stm32_sample((struct stm32_dev_s*)arg, SAMPLENDX_DMA_CALLBACK); + + /* Get the result of the DMA transfer */ + + if ((status & DMA_STATUS_ERROR) != 0) + { + flldbg("DMA error %02x, remaining: %d\n", status, priv->remaining); + result = SDIOWAIT_ERROR; + } + else + { + result = SDIOWAIT_TRANSFERDONE; + } + + /* Then terminate the transfer if this completes all of the steps in the + * transfer OR if a DMA error occurred. In the non-error case, we should + * already have the SDIO transfer done interrupt. If not, the transfer + * will appropriately time out. + */ + + priv->xfrflags |= SDIO_DMADONE_FLAG; + if (priv->xfrflags == SDIO_ALLDONE || result == SDIOWAIT_ERROR) + { + stm32_endtransfer(priv, result); + } +} +#endif + +/**************************************************************************** + * Data Transfer Helpers + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_log2 + * + * Description: + * Take (approximate) log base 2 of the provided number (Only works if the + * provided number is a power of 2). + * + ****************************************************************************/ + +static uint8_t stm32_log2(uint16_t value) +{ + uint8_t log2 = 0; + + /* 0000 0000 0000 0001 -> return 0, + * 0000 0000 0000 001x -> return 1, + * 0000 0000 0000 01xx -> return 2, + * 0000 0000 0000 1xxx -> return 3, + * ... + * 1xxx xxxx xxxx xxxx -> return 15, + */ + + DEBUGASSERT(value > 0); + while (value != 1) + { + value >>= 1; + log2++; + } + return log2; +} + +/**************************************************************************** + * Name: stm32_dataconfig + * + * Description: + * Configure the SDIO data path for the next data transfer + * + ****************************************************************************/ + +static void stm32_dataconfig(uint32_t timeout, uint32_t dlen, uint32_t dctrl) +{ + uint32_t regval = 0; + + /* Enable data path */ + + putreg32(timeout, STM32_SDIO_DTIMER); /* Set DTIMER */ + putreg32(dlen, STM32_SDIO_DLEN); /* Set DLEN */ + + /* Configure DCTRL DTDIR, DTMODE, and DBLOCKSIZE fields and set the DTEN + * field + */ + + regval = getreg32(STM32_SDIO_DCTRL); + regval &= ~(SDIO_DCTRL_DTDIR|SDIO_DCTRL_DTMODE|SDIO_DCTRL_DBLOCKSIZE_MASK); + dctrl &= (SDIO_DCTRL_DTDIR|SDIO_DCTRL_DTMODE|SDIO_DCTRL_DBLOCKSIZE_MASK); + regval |= (dctrl|SDIO_DCTRL_DTEN); + putreg32(regval, STM32_SDIO_DCTRL); +} + +/**************************************************************************** + * Name: stm32_datadisable + * + * Description: + * Disable the the SDIO data path setup by stm32_dataconfig() and + * disable DMA. + * + ****************************************************************************/ + +static void stm32_datadisable(void) +{ + uint32_t regval; + + /* Disable the data path */ + + putreg32(SDIO_DTIMER_DATATIMEOUT, STM32_SDIO_DTIMER); /* Reset DTIMER */ + putreg32(0, STM32_SDIO_DLEN); /* Reset DLEN */ + + /* Reset DCTRL DTEN, DTDIR, DTMODE, DMAEN, and DBLOCKSIZE fields */ + + regval = getreg32(STM32_SDIO_DCTRL); + regval &= ~(SDIO_DCTRL_DTEN|SDIO_DCTRL_DTDIR|SDIO_DCTRL_DTMODE| + SDIO_DCTRL_DMAEN|SDIO_DCTRL_DBLOCKSIZE_MASK); + putreg32(regval, STM32_SDIO_DCTRL); +} + +/**************************************************************************** + * Name: stm32_sendfifo + * + * Description: + * Send SDIO data in interrupt mode + * + * Input Parameters: + * priv - An instance of the SDIO device interface + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void stm32_sendfifo(struct stm32_dev_s *priv) +{ + union + { + uint32_t w; + uint8_t b[4]; + } data; + + /* Loop while there is more data to be sent and the RX FIFO is not full */ + + while (priv->remaining > 0 && + (getreg32(STM32_SDIO_STA) & SDIO_STA_TXFIFOF) == 0) + { + /* Is there a full word remaining in the user buffer? */ + + if (priv->remaining >= sizeof(uint32_t)) + { + /* Yes, transfer the word to the TX FIFO */ + + data.w = *priv->buffer++; + priv->remaining -= sizeof(uint32_t); + } + else + { + /* No.. transfer just the bytes remaining in the user buffer, + * padding with zero as necessary to extend to a full word. + */ + + uint8_t *ptr = (uint8_t *)priv->remaining; + int i; + + data.w = 0; + for (i = 0; i < priv->remaining; i++) + { + data.b[i] = *ptr++; + } + + /* Now the transfer is finished */ + + priv->remaining = 0; + } + + /* Put the word in the FIFO */ + + putreg32(data.w, STM32_SDIO_FIFO); + } +} + +/**************************************************************************** + * Name: stm32_recvfifo + * + * Description: + * Receive SDIO data in interrupt mode + * + * Input Parameters: + * priv - An instance of the SDIO device interface + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void stm32_recvfifo(struct stm32_dev_s *priv) +{ + union + { + uint32_t w; + uint8_t b[4]; + } data; + + /* Loop while there is space to store the data and there is more + * data available in the RX FIFO. + */ + + while (priv->remaining > 0 && + (getreg32(STM32_SDIO_STA) & SDIO_STA_RXDAVL) != 0) + { + /* Read the next word from the RX FIFO */ + + data.w = getreg32(STM32_SDIO_FIFO); + if (priv->remaining >= sizeof(uint32_t)) + { + /* Transfer the whole word to the user buffer */ + + *priv->buffer++ = data.w; + priv->remaining -= sizeof(uint32_t); + } + else + { + /* Transfer any trailing fractional word */ + + uint8_t *ptr = (uint8_t*)priv->buffer; + int i; + + for (i = 0; i < priv->remaining; i++) + { + *ptr++ = data.b[i]; + } + + /* Now the transfer is finished */ + + priv->remaining = 0; + } + } +} + +/**************************************************************************** + * Name: stm32_eventtimeout + * + * Description: + * The watchdog timeout setup when the event wait start has expired without + * any other waited-for event occurring. + * + * Input Parameters: + * argc - The number of arguments (should be 1) + * arg - The argument (state structure reference cast to uint32_t) + * + * Returned Value: + * None + * + * Assumptions: + * Always called from the interrupt level with interrupts disabled. + * + ****************************************************************************/ + +static void stm32_eventtimeout(int argc, uint32_t arg) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s *)arg; + + /* There is always race conditions with timer expirations. */ + + DEBUGASSERT((priv->waitevents & SDIOWAIT_TIMEOUT) != 0 || priv->wkupevent != 0); + + /* Is a data transfer complete event expected? */ + + if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0) + { + /* Yes.. wake up any waiting threads */ + + stm32_endwait(priv, SDIOWAIT_TIMEOUT); + flldbg("Timeout: remaining: %d\n", priv->remaining); + } +} + +/**************************************************************************** + * Name: stm32_endwait + * + * Description: + * Wake up a waiting thread if the waited-for event has occurred. + * + * Input Parameters: + * priv - An instance of the SDIO device interface + * wkupevent - The event that caused the wait to end + * + * Returned Value: + * None + * + * Assumptions: + * Always called from the interrupt level with interrupts disabled. + * + ****************************************************************************/ + +static void stm32_endwait(struct stm32_dev_s *priv, sdio_eventset_t wkupevent) +{ + /* Cancel the watchdog timeout */ + + (void)wd_cancel(priv->waitwdog); + + /* Disable event-related interrupts */ + + stm32_configwaitints(priv, 0, 0, wkupevent); + + /* Wake up the waiting thread */ + + stm32_givesem(priv); +} + +/**************************************************************************** + * Name: stm32_endtransfer + * + * Description: + * Terminate a transfer with the provided status. This function is called + * only from the SDIO interrupt handler when end-of-transfer conditions + * are detected. + * + * Input Parameters: + * priv - An instance of the SDIO device interface + * wkupevent - The event that caused the transfer to end + * + * Returned Value: + * None + * + * Assumptions: + * Always called from the interrupt level with interrupts disabled. + * + ****************************************************************************/ + +static void stm32_endtransfer(struct stm32_dev_s *priv, sdio_eventset_t wkupevent) +{ + /* Disable all transfer related interrupts */ + + stm32_configxfrints(priv, 0); + + /* Clearing pending interrupt status on all transfer related interrupts */ + + putreg32(SDIO_XFRDONE_ICR, STM32_SDIO_ICR); + + /* If this was a DMA transfer, make sure that DMA is stopped */ + +#ifdef CONFIG_SDIO_DMA + if (priv->dmamode) + { + /* DMA debug instrumentation */ + + stm32_sample(priv, SAMPLENDX_END_TRANSFER); + + /* Make sure that the DMA is stopped (it will be stopped automatically + * on normal transfers, but not necessarily when the transfer terminates + * on an error condition). + */ + + stm32_dmastop(priv->dma); + } +#endif + + /* Mark the transfer finished */ + + priv->remaining = 0; + + /* Is a thread wait for these data transfer complete events? */ + + if ((priv->waitevents & wkupevent) != 0) + { + /* Yes.. wake up any waiting threads */ + + stm32_endwait(priv, wkupevent); + } +} + +/**************************************************************************** + * Interrrupt Handling + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_interrupt + * + * Description: + * SDIO interrupt handler + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int stm32_interrupt(int irq, void *context) +{ + struct stm32_dev_s *priv = &g_sdiodev; + uint32_t enabled; + uint32_t pending; + + /* Loop while there are pending interrupts. Check the SDIO status + * register. Mask out all bits that don't correspond to enabled + * interrupts. (This depends on the fact that bits are ordered + * the same in both the STA and MASK register). If there are non-zero + * bits remaining, then we have work to do here. + */ + + while ((enabled = getreg32(STM32_SDIO_STA) & getreg32(STM32_SDIO_MASK)) != 0) + { + /* Handle in progress, interrupt driven data transfers ****************/ + + pending = enabled & priv->xfrmask; + if (pending != 0) + { +#ifdef CONFIG_SDIO_DMA + if (!priv->dmamode) +#endif + { + /* Is the RX FIFO half full or more? Is so then we must be + * processing a receive transaction. + */ + + if ((pending & SDIO_STA_RXFIFOHF) != 0) + { + /* Receive data from the RX FIFO */ + + stm32_recvfifo(priv); + } + + /* Otherwise, Is the transmit FIFO half empty or less? If so we must + * be processing a send transaction. NOTE: We can't be processing + * both! + */ + + else if ((pending & SDIO_STA_TXFIFOHE) != 0) + { + /* Send data via the TX FIFO */ + + stm32_sendfifo(priv); + } + } + + /* Handle data end events */ + + if ((pending & SDIO_STA_DATAEND) != 0) + { + /* Handle any data remaining the RX FIFO. If the RX FIFO is + * less than half full at the end of the transfer, then no + * half-full interrupt will be received. + */ + + /* Was this transfer performed in DMA mode? */ + +#ifdef CONFIG_SDIO_DMA + if (priv->dmamode) + { + /* Yes.. Terminate the transfers only if the DMA has also + * finished. + */ + + priv->xfrflags |= SDIO_XFRDONE_FLAG; + if (priv->xfrflags == SDIO_ALLDONE) + { + stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE); + } + + /* Otherwise, just disable futher transfer interrupts and + * wait for the DMA complete event. + */ + + else + { + stm32_configxfrints(priv, 0); + } + } + else +#endif + { + /* Receive data from the RX FIFO */ + + stm32_recvfifo(priv); + + /* Then terminate the transfer */ + + stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE); + } + } + + /* Handle data block send/receive CRC failure */ + + else if ((pending & SDIO_STA_DCRCFAIL) != 0) + { + /* Terminate the transfer with an error */ + + flldbg("ERROR: Data block CRC failure, remaining: %d\n", priv->remaining); + stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR); + } + + /* Handle data timeout error */ + + else if ((pending & SDIO_STA_DTIMEOUT) != 0) + { + /* Terminate the transfer with an error */ + + flldbg("ERROR: Data timeout, remaining: %d\n", priv->remaining); + stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT); + } + + /* Handle RX FIFO overrun error */ + + else if ((pending & SDIO_STA_RXOVERR) != 0) + { + /* Terminate the transfer with an error */ + + flldbg("ERROR: RX FIFO overrun, remaining: %d\n", priv->remaining); + stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR); + } + + /* Handle TX FIFO underrun error */ + + else if ((pending & SDIO_STA_TXUNDERR) != 0) + { + /* Terminate the transfer with an error */ + + flldbg("ERROR: TX FIFO underrun, remaining: %d\n", priv->remaining); + stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR); + } + + /* Handle start bit error */ + + else if ((pending & SDIO_STA_STBITERR) != 0) + { + /* Terminate the transfer with an error */ + + flldbg("ERROR: Start bit, remaining: %d\n", priv->remaining); + stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR); + } + } + + /* Handle wait events *************************************************/ + + pending = enabled & priv->waitmask; + if (pending != 0) + { + /* Is this a response completion event? */ + + if ((pending & SDIO_RESPDONE_STA) != 0) + { + /* Yes.. Is their a thread waiting for response done? */ + + if ((priv->waitevents & SDIOWAIT_RESPONSEDONE) != 0) + { + /* Yes.. wake the thread up */ + + putreg32(SDIO_RESPDONE_ICR|SDIO_CMDDONE_ICR, STM32_SDIO_ICR); + stm32_endwait(priv, SDIOWAIT_RESPONSEDONE); + } + } + + /* Is this a command completion event? */ + + if ((pending & SDIO_CMDDONE_STA) != 0) + { + /* Yes.. Is their a thread waiting for command done? */ + + if ((priv->waitevents & SDIOWAIT_RESPONSEDONE) != 0) + { + /* Yes.. wake the thread up */ + + putreg32(SDIO_CMDDONE_ICR, STM32_SDIO_ICR); + stm32_endwait(priv, SDIOWAIT_CMDDONE); + } + } + } + } + + return OK; +} + +/**************************************************************************** + * SDIO Interface Methods + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_lock + * + * Description: + * Locks the bus. Function calls low-level multiplexed bus routines to + * resolve bus requests and acknowledgment issues. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * lock - TRUE to lock, FALSE to unlock. + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_MUXBUS +static int stm32_lock(FAR struct sdio_dev_s *dev, bool lock) +{ + /* Single SDIO instance so there is only one possibility. The multiplex + * bus is part of board support package. + */ + + stm32_muxbus_sdio_lock(lock); + return OK; +} +#endif + +/**************************************************************************** + * Name: stm32_reset + * + * Description: + * Reset the SDIO controller. Undo all setup and initialization. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void stm32_reset(FAR struct sdio_dev_s *dev) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev; + irqstate_t flags; + + /* Disable clocking */ + + flags = irqsave(); + putreg32(0, SDIO_CLKCR_CLKEN_BB); + stm32_setpwrctrl(SDIO_POWER_PWRCTRL_OFF); + + /* Put SDIO registers in their default, reset state */ + + stm32_default(); + + /* Reset data */ + + priv->waitevents = 0; /* Set of events to be waited for */ + priv->waitmask = 0; /* Interrupt enables for event waiting */ + priv->wkupevent = 0; /* The event that caused the wakeup */ +#ifdef CONFIG_SDIO_DMA + priv->xfrflags = 0; /* Used to synchronize SDIO and DMA completion events */ +#endif + + wd_cancel(priv->waitwdog); /* Cancel any timeouts */ + + /* Interrupt mode data transfer support */ + + priv->buffer = 0; /* Address of current R/W buffer */ + priv->remaining = 0; /* Number of bytes remaining in the transfer */ + priv->xfrmask = 0; /* Interrupt enables for data transfer */ + + /* DMA data transfer support */ + + priv->widebus = false; /* Required for DMA support */ +#ifdef CONFIG_SDIO_DMA + priv->dmamode = false; /* true: DMA mode transfer */ +#endif + + /* Configure the SDIO peripheral */ + + stm32_setclkcr(STM32_CLCKCR_INIT | SDIO_CLKCR_CLKEN); + stm32_setpwrctrl(SDIO_POWER_PWRCTRL_ON); + irqrestore(flags); + + fvdbg("CLCKR: %08x POWER: %08x\n", + getreg32(STM32_SDIO_CLKCR), getreg32(STM32_SDIO_POWER)); +} + +/**************************************************************************** + * Name: stm32_status + * + * Description: + * Get SDIO status. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Returns a bitset of status values (see stm32_status_* defines) + * + ****************************************************************************/ + +static uint8_t stm32_status(FAR struct sdio_dev_s *dev) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s *)dev; + return priv->cdstatus; +} + +/**************************************************************************** + * Name: stm32_widebus + * + * Description: + * Called after change in Bus width has been selected (via ACMD6). Most + * controllers will need to perform some special operations to work + * correctly in the new bus mode. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * wide - true: wide bus (4-bit) bus mode enabled + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void stm32_widebus(FAR struct sdio_dev_s *dev, bool wide) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s *)dev; + priv->widebus = wide; +} + +/**************************************************************************** + * Name: stm32_clock + * + * Description: + * Enable/disable SDIO clocking + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * rate - Specifies the clocking to use (see enum sdio_clock_e) + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void stm32_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) +{ + uint32_t clckr; + + switch (rate) + { + /* Disable clocking (with default ID mode divisor) */ + + default: + case CLOCK_SDIO_DISABLED: + clckr = STM32_CLCKCR_INIT; + return; + + /* Enable in initial ID mode clocking (<400KHz) */ + + case CLOCK_IDMODE: + clckr = (STM32_CLCKCR_INIT | SDIO_CLKCR_CLKEN); + break; + + /* Enable in MMC normal operation clocking */ + + case CLOCK_MMC_TRANSFER: + clckr = (SDIO_CLKCR_MMCXFR | SDIO_CLKCR_CLKEN); + break; + + /* SD normal operation clocking (wide 4-bit mode) */ + + case CLOCK_SD_TRANSFER_4BIT: +#ifndef CONFIG_SDIO_WIDTH_D1_ONLY + clckr = (SDIO_CLCKR_SDWIDEXFR | SDIO_CLKCR_CLKEN); + break; +#endif + + /* SD normal operation clocking (narrow 1-bit mode) */ + + case CLOCK_SD_TRANSFER_1BIT: + clckr = (SDIO_CLCKR_SDXFR | SDIO_CLKCR_CLKEN) + break; + } + + /* Set the new clock frequency along with the clock enable/disable bit */ + + stm32_setclkcr(clckr); +} + +/**************************************************************************** + * Name: stm32_attach + * + * Description: + * Attach and prepare interrupts + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * + * Returned Value: + * OK on success; A negated errno on failure. + * + ****************************************************************************/ + +static int stm32_attach(FAR struct sdio_dev_s *dev) +{ + int ret; + + /* Attach the SDIO interrupt handler */ + + ret = irq_attach(STM32_IRQ_SDIO, stm32_interrupt); + if (ret == OK) + { + + /* Disable all interrupts at the SDIO controller and clear static + * interrupt flags + */ + + putreg32(SDIO_MASK_RESET, STM32_SDIO_MASK); + putreg32(SDIO_ICR_STATICFLAGS, STM32_SDIO_ICR); + + /* Enable SDIO interrupts at the NVIC. They can now be enabled at + * the SDIO controller as needed. + */ + + up_enable_irq(STM32_IRQ_SDIO); + + /* Set the interrrupt priority */ + + up_prioritize_irq(STM32_IRQ_SDIO, CONFIG_SDIO_PRI); + } + + return ret; +} + +/**************************************************************************** + * Name: stm32_sendcmd + * + * Description: + * Send the SDIO command + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * cmd - The command to send (32-bits, encoded) + * arg - 32-bit argument required with some commands + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg) +{ + uint32_t regval; + uint32_t cmdidx; + + /* Set the SDIO Argument value */ + + putreg32(arg, STM32_SDIO_ARG); + + /* Clear CMDINDEX, WAITRESP, WAITINT, WAITPEND, and CPSMEN bits */ + + regval = getreg32(STM32_SDIO_CMD); + regval &= ~(SDIO_CMD_CMDINDEX_MASK|SDIO_CMD_WAITRESP_MASK| + SDIO_CMD_WAITINT|SDIO_CMD_WAITPEND|SDIO_CMD_CPSMEN); + + /* Set WAITRESP bits */ + + switch (cmd & MMCSD_RESPONSE_MASK) + { + case MMCSD_NO_RESPONSE: + regval |= SDIO_CMD_NORESPONSE; + break; + + case MMCSD_R1_RESPONSE: + case MMCSD_R1B_RESPONSE: + case MMCSD_R3_RESPONSE: + case MMCSD_R4_RESPONSE: + case MMCSD_R5_RESPONSE: + case MMCSD_R6_RESPONSE: + case MMCSD_R7_RESPONSE: + regval |= SDIO_CMD_SHORTRESPONSE; + break; + + case MMCSD_R2_RESPONSE: + regval |= SDIO_CMD_LONGRESPONSE; + break; + } + + /* Set CPSMEN and the command index */ + + cmdidx = (cmd & MMCSD_CMDIDX_MASK) >> MMCSD_CMDIDX_SHIFT; + regval |= cmdidx | SDIO_CMD_CPSMEN; + + fvdbg("cmd: %08x arg: %08x regval: %08x\n", cmd, arg, regval); + + /* Write the SDIO CMD */ + + putreg32(SDIO_RESPDONE_ICR|SDIO_CMDDONE_ICR, STM32_SDIO_ICR); + putreg32(regval, STM32_SDIO_CMD); + return OK; +} + +/**************************************************************************** + * Name: stm32_recvsetup + * + * Description: + * Setup hardware in preparation for data transfer from the card in non-DMA + * (interrupt driven mode). This method will do whatever controller setup + * is necessary. This would be called for SD memory just BEFORE sending + * CMD13 (SEND_STATUS), CMD17 (READ_SINGLE_BLOCK), CMD18 + * (READ_MULTIPLE_BLOCKS), ACMD51 (SEND_SCR), etc. Normally, SDIO_WAITEVENT + * will be called to receive the indication that the transfer is complete. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * buffer - Address of the buffer in which to receive the data + * nbytes - The number of bytes in the transfer + * + * Returned Value: + * Number of bytes sent on success; a negated errno on failure + * + ****************************************************************************/ + +static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, + size_t nbytes) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s *)dev; + uint32_t dblocksize; + + DEBUGASSERT(priv != NULL && buffer != NULL && nbytes > 0); + DEBUGASSERT(((uint32_t)buffer & 3) == 0); + + /* Reset the DPSM configuration */ + + stm32_datadisable(); + stm32_sampleinit(); + stm32_sample(priv, SAMPLENDX_BEFORE_SETUP); + + /* Save the destination buffer information for use by the interrupt handler */ + + priv->buffer = (uint32_t*)buffer; + priv->remaining = nbytes; +#ifdef CONFIG_SDIO_DMA + priv->dmamode = false; +#endif + + /* Then set up the SDIO data path */ + + dblocksize = stm32_log2(nbytes) << SDIO_DCTRL_DBLOCKSIZE_SHIFT; + stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, nbytes, dblocksize|SDIO_DCTRL_DTDIR); + + /* And enable interrupts */ + + stm32_configxfrints(priv, SDIO_RECV_MASK); + stm32_sample(priv, SAMPLENDX_AFTER_SETUP); + return OK; +} + +/**************************************************************************** + * Name: stm32_sendsetup + * + * Description: + * Setup hardware in preparation for data transfer from the card. This method + * will do whatever controller setup is necessary. This would be called + * for SD memory just AFTER sending CMD24 (WRITE_BLOCK), CMD25 + * (WRITE_MULTIPLE_BLOCK), ... and before SDIO_SENDDATA is called. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * buffer - Address of the buffer containing the data to send + * nbytes - The number of bytes in the transfer + * + * Returned Value: + * Number of bytes sent on success; a negated errno on failure + * + ****************************************************************************/ + +static int stm32_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer, + size_t nbytes) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s *)dev; + uint32_t dblocksize; + + DEBUGASSERT(priv != NULL && buffer != NULL && nbytes > 0); + DEBUGASSERT(((uint32_t)buffer & 3) == 0); + + /* Reset the DPSM configuration */ + + stm32_datadisable(); + stm32_sampleinit(); + stm32_sample(priv, SAMPLENDX_BEFORE_SETUP); + + /* Save the source buffer information for use by the interrupt handler */ + + priv->buffer = (uint32_t*)buffer; + priv->remaining = nbytes; +#ifdef CONFIG_SDIO_DMA + priv->dmamode = false; +#endif + + /* Then set up the SDIO data path */ + + dblocksize = stm32_log2(nbytes) << SDIO_DCTRL_DBLOCKSIZE_SHIFT; + stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, nbytes, dblocksize); + + /* Enable TX interrrupts */ + + stm32_configxfrints(priv, SDIO_SEND_MASK); + stm32_sample(priv, SAMPLENDX_AFTER_SETUP); + return OK; +} + +/**************************************************************************** + * Name: stm32_cancel + * + * Description: + * Cancel the data transfer setup of SDIO_RECVSETUP, SDIO_SENDSETUP, + * SDIO_DMARECVSETUP or SDIO_DMASENDSETUP. This must be called to cancel + * the data transfer setup if, for some reason, you cannot perform the + * transfer. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * + * Returned Value: + * OK is success; a negated errno on failure + * + ****************************************************************************/ + +static int stm32_cancel(FAR struct sdio_dev_s *dev) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s*)dev; + + /* Disable all transfer- and event- related interrupts */ + + stm32_configxfrints(priv, 0); + stm32_configwaitints(priv, 0, 0, 0); + + /* Clearing pending interrupt status on all transfer- and event- related + * interrupts + */ + + putreg32(SDIO_WAITALL_ICR, STM32_SDIO_ICR); + + /* Cancel any watchdog timeout */ + + (void)wd_cancel(priv->waitwdog); + + /* If this was a DMA transfer, make sure that DMA is stopped */ + +#ifdef CONFIG_SDIO_DMA + if (priv->dmamode) + { + /* Make sure that the DMA is stopped (it will be stopped automatically + * on normal transfers, but not necessarily when the transfer terminates + * on an error condition. + */ + + stm32_dmastop(priv->dma); + } +#endif + + /* Mark no transfer in progress */ + + priv->remaining = 0; + return OK; +} + +/**************************************************************************** + * Name: stm32_waitresponse + * + * Description: + * Poll-wait for the response to the last command to be ready. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * cmd - The command that was sent. See 32-bit command definitions above. + * + * Returned Value: + * OK is success; a negated errno on failure + * + ****************************************************************************/ + +static int stm32_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd) +{ + int32_t timeout; + uint32_t events; + + switch (cmd & MMCSD_RESPONSE_MASK) + { + case MMCSD_NO_RESPONSE: + events = SDIO_CMDDONE_STA; + timeout = SDIO_CMDTIMEOUT; + break; + + case MMCSD_R1_RESPONSE: + case MMCSD_R1B_RESPONSE: + case MMCSD_R2_RESPONSE: + case MMCSD_R6_RESPONSE: + events = SDIO_RESPDONE_STA; + timeout = SDIO_LONGTIMEOUT; + break; + + case MMCSD_R4_RESPONSE: + case MMCSD_R5_RESPONSE: + return -ENOSYS; + + case MMCSD_R3_RESPONSE: + case MMCSD_R7_RESPONSE: + events = SDIO_RESPDONE_STA; + timeout = SDIO_CMDTIMEOUT; + break; + + default: + return -EINVAL; + } + + /* Then wait for the response (or timeout) */ + + while ((getreg32(STM32_SDIO_STA) & events) == 0) + { + if (--timeout <= 0) + { + fdbg("ERROR: Timeout cmd: %08x events: %08x STA: %08x\n", + cmd, events, getreg32(STM32_SDIO_STA)); + + return -ETIMEDOUT; + } + } + + putreg32(SDIO_CMDDONE_ICR, STM32_SDIO_ICR); + return OK; +} + +/**************************************************************************** + * Name: stm32_recvRx + * + * Description: + * Receive response to SDIO command. Only the critical payload is + * returned -- that is 32 bits for 48 bit status and 128 bits for 136 bit + * status. The driver implementation should verify the correctness of + * the remaining, non-returned bits (CRCs, CMD index, etc.). + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * Rx - Buffer in which to receive the response + * + * Returned Value: + * Number of bytes sent on success; a negated errno on failure. Here a + * failure means only a faiure to obtain the requested reponse (due to + * transport problem -- timeout, CRC, etc.). The implementation only + * assures that the response is returned intacta and does not check errors + * within the response itself. + * + ****************************************************************************/ + +static int stm32_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rshort) +{ +#ifdef CONFIG_DEBUG + uint32_t respcmd; +#endif + uint32_t regval; + int ret = OK; + + /* R1 Command response (48-bit) + * 47 0 Start bit + * 46 0 Transmission bit (0=from card) + * 45:40 bit5 - bit0 Command index (0-63) + * 39:8 bit31 - bit0 32-bit card status + * 7:1 bit6 - bit0 CRC7 + * 0 1 End bit + * + * R1b Identical to R1 with the additional busy signaling via the data + * line. + * + * R6 Published RCA Response (48-bit, SD card only) + * 47 0 Start bit + * 46 0 Transmission bit (0=from card) + * 45:40 bit5 - bit0 Command index (0-63) + * 39:8 bit31 - bit0 32-bit Argument Field, consisting of: + * [31:16] New published RCA of card + * [15:0] Card status bits {23,22,19,12:0} + * 7:1 bit6 - bit0 CRC7 + * 0 1 End bit + */ + + +#ifdef CONFIG_DEBUG + if (!rshort) + { + fdbg("ERROR: rshort=NULL\n"); + ret = -EINVAL; + } + + /* Check that this is the correct response to this command */ + + else if ((cmd & MMCSD_RESPONSE_MASK) != MMCSD_R1_RESPONSE && + (cmd & MMCSD_RESPONSE_MASK) != MMCSD_R1B_RESPONSE && + (cmd & MMCSD_RESPONSE_MASK) != MMCSD_R6_RESPONSE) + { + fdbg("ERROR: Wrong response CMD=%08x\n", cmd); + ret = -EINVAL; + } + else +#endif + { + /* Check if a timeout or CRC error occurred */ + + regval = getreg32(STM32_SDIO_STA); + if ((regval & SDIO_STA_CTIMEOUT) != 0) + { + fdbg("ERROR: Command timeout: %08x\n", regval); + ret = -ETIMEDOUT; + } + else if ((regval & SDIO_STA_CCRCFAIL) != 0) + { + fdbg("ERROR: CRC failure: %08x\n", regval); + ret = -EIO; + } +#ifdef CONFIG_DEBUG + else + { + /* Check response received is of desired command */ + + respcmd = getreg32(STM32_SDIO_RESPCMD); + if ((uint8_t)(respcmd & SDIO_RESPCMD_MASK) != (cmd & MMCSD_CMDIDX_MASK)) + { + fdbg("ERROR: RESCMD=%02x CMD=%08x\n", respcmd, cmd); + ret = -EINVAL; + } + } +#endif + } + + /* Clear all pending message completion events and return the R1/R6 response */ + + putreg32(SDIO_RESPDONE_ICR|SDIO_CMDDONE_ICR, STM32_SDIO_ICR); + *rshort = getreg32(STM32_SDIO_RESP1); + return ret; +} + +static int stm32_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t rlong[4]) +{ + uint32_t regval; + int ret = OK; + + /* R2 CID, CSD register (136-bit) + * 135 0 Start bit + * 134 0 Transmission bit (0=from card) + * 133:128 bit5 - bit0 Reserved + * 127:1 bit127 - bit1 127-bit CID or CSD register + * (including internal CRC) + * 0 1 End bit + */ + +#ifdef CONFIG_DEBUG + /* Check that R1 is the correct response to this command */ + + if ((cmd & MMCSD_RESPONSE_MASK) != MMCSD_R2_RESPONSE) + { + fdbg("ERROR: Wrong response CMD=%08x\n", cmd); + ret = -EINVAL; + } + else +#endif + { + /* Check if a timeout or CRC error occurred */ + + regval = getreg32(STM32_SDIO_STA); + if (regval & SDIO_STA_CTIMEOUT) + { + fdbg("ERROR: Timeout STA: %08x\n", regval); + ret = -ETIMEDOUT; + } + else if (regval & SDIO_STA_CCRCFAIL) + { + fdbg("ERROR: CRC fail STA: %08x\n", regval); + ret = -EIO; + } + } + + /* Return the long response */ + + putreg32(SDIO_RESPDONE_ICR|SDIO_CMDDONE_ICR, STM32_SDIO_ICR); + if (rlong) + { + rlong[0] = getreg32(STM32_SDIO_RESP1); + rlong[1] = getreg32(STM32_SDIO_RESP2); + rlong[2] = getreg32(STM32_SDIO_RESP3); + rlong[3] = getreg32(STM32_SDIO_RESP4); + } + return ret; +} + +static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rshort) +{ + uint32_t regval; + int ret = OK; + + /* R3 OCR (48-bit) + * 47 0 Start bit + * 46 0 Transmission bit (0=from card) + * 45:40 bit5 - bit0 Reserved + * 39:8 bit31 - bit0 32-bit OCR register + * 7:1 bit6 - bit0 Reserved + * 0 1 End bit + */ + + /* Check that this is the correct response to this command */ + +#ifdef CONFIG_DEBUG + if ((cmd & MMCSD_RESPONSE_MASK) != MMCSD_R3_RESPONSE && + (cmd & MMCSD_RESPONSE_MASK) != MMCSD_R7_RESPONSE) + { + fdbg("ERROR: Wrong response CMD=%08x\n", cmd); + ret = -EINVAL; + } + else +#endif + { + /* Check if a timeout occurred (Apparently a CRC error can terminate + * a good response) + */ + + regval = getreg32(STM32_SDIO_STA); + if (regval & SDIO_STA_CTIMEOUT) + { + fdbg("ERROR: Timeout STA: %08x\n", regval); + ret = -ETIMEDOUT; + } + } + + putreg32(SDIO_RESPDONE_ICR|SDIO_CMDDONE_ICR, STM32_SDIO_ICR); + if (rshort) + { + *rshort = getreg32(STM32_SDIO_RESP1); + } + return ret; +} + +/* MMC responses not supported */ + +static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rnotimpl) +{ + putreg32(SDIO_RESPDONE_ICR|SDIO_CMDDONE_ICR, STM32_SDIO_ICR); + return -ENOSYS; +} + +/**************************************************************************** + * Name: stm32_waitenable + * + * Description: + * Enable/disable of a set of SDIO wait events. This is part of the + * the SDIO_WAITEVENT sequence. The set of to-be-waited-for events is + * configured before calling stm32_eventwait. This is done in this way + * to help the driver to eliminate race conditions between the command + * setup and the subsequent events. + * + * The enabled events persist until either (1) SDIO_WAITENABLE is called + * again specifying a different set of wait events, or (2) SDIO_EVENTWAIT + * returns. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * eventset - A bitset of events to enable or disable (see SDIOWAIT_* + * definitions). 0=disable; 1=enable. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void stm32_waitenable(FAR struct sdio_dev_s *dev, + sdio_eventset_t eventset) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s*)dev; + uint32_t waitmask; + + DEBUGASSERT(priv != NULL); + + /* Disable event-related interrupts */ + + stm32_configwaitints(priv, 0, 0, 0); + + /* Select the interrupt mask that will give us the appropriate wakeup + * interrupts. + */ + + waitmask = 0; + if ((eventset & SDIOWAIT_CMDDONE) != 0) + { + waitmask |= SDIO_CMDDONE_MASK; + } + + if ((eventset & SDIOWAIT_RESPONSEDONE) != 0) + { + waitmask |= SDIO_RESPDONE_MASK; + } + + if ((eventset & SDIOWAIT_TRANSFERDONE) != 0) + { + waitmask |= SDIO_XFRDONE_MASK; + } + + /* Enable event-related interrupts */ + + putreg32(SDIO_WAITALL_ICR, STM32_SDIO_ICR); + stm32_configwaitints(priv, waitmask, eventset, 0); +} + +/**************************************************************************** + * Name: stm32_eventwait + * + * Description: + * Wait for one of the enabled events to occur (or a timeout). Note that + * all events enabled by SDIO_WAITEVENTS are disabled when stm32_eventwait + * returns. SDIO_WAITEVENTS must be called again before stm32_eventwait + * can be used again. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * timeout - Maximum time in milliseconds to wait. Zero means immediate + * timeout with no wait. The timeout value is ignored if + * SDIOWAIT_TIMEOUT is not included in the waited-for eventset. + * + * Returned Value: + * Event set containing the event(s) that ended the wait. Should always + * be non-zero. All events are disabled after the wait concludes. + * + ****************************************************************************/ + +static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, + uint32_t timeout) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s*)dev; + sdio_eventset_t wkupevent = 0; + irqstate_t flags; + int ret; + + /* There is a race condition here... the event may have completed before + * we get here. In this case waitevents will be zero, but wkupevents will + * be non-zero (and, hopefully, the semaphore count will also be non-zero. + */ + + flags = irqsave(); + DEBUGASSERT(priv->waitevents != 0 || priv->wkupevent != 0); + + /* Check if the timeout event is specified in the event set */ + + if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0) + { + int delay; + + /* Yes.. Handle a cornercase: The user request a timeout event but + * with timeout == 0? + */ + + if (!timeout) + { + /* Then just tell the caller that we already timed out */ + + wkupevent = SDIOWAIT_TIMEOUT; + goto errout; + } + + /* Start the watchdog timer */ + + delay = (timeout + (MSEC_PER_TICK-1)) / MSEC_PER_TICK; + ret = wd_start(priv->waitwdog, delay, (wdentry_t)stm32_eventtimeout, + 1, (uint32_t)priv); + if (ret != OK) + { + fdbg("ERROR: wd_start failed: %d\n", ret); + } + } + + /* Loop until the event (or the timeout occurs). Race conditions are avoided + * by calling stm32_waitenable prior to triggering the logic that will cause + * the wait to terminate. Under certain race conditions, the waited-for + * may have already occurred before this function was called! + */ + + for (;;) + { + /* Wait for an event in event set to occur. If this the event has already + * occurred, then the semaphore will already have been incremented and + * there will be no wait. + */ + + stm32_takesem(priv); + wkupevent = priv->wkupevent; + + /* Check if the event has occurred. When the event has occurred, then + * evenset will be set to 0 and wkupevent will be set to a nonzero value. + */ + + if (wkupevent != 0) + { + /* Yes... break out of the loop with wkupevent non-zero */ + + break; + } + } + + /* Disable event-related interrupts */ + + stm32_configwaitints(priv, 0, 0, 0); +#ifdef CONFIG_SDIO_DMA + priv->xfrflags = 0; +#endif + +errout: + irqrestore(flags); + stm32_dumpsamples(priv); + return wkupevent; +} + +/**************************************************************************** + * Name: stm32_callbackenable + * + * Description: + * Enable/disable of a set of SDIO callback events. This is part of the + * the SDIO callback sequence. The set of events is configured to enabled + * callbacks to the function provided in stm32_registercallback. + * + * Events are automatically disabled once the callback is performed and no + * further callback events will occur until they are again enabled by + * calling this methos. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * eventset - A bitset of events to enable or disable (see SDIOMEDIA_* + * definitions). 0=disable; 1=enable. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void stm32_callbackenable(FAR struct sdio_dev_s *dev, + sdio_eventset_t eventset) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s*)dev; + + fvdbg("eventset: %02x\n", eventset); + DEBUGASSERT(priv != NULL); + + priv->cbevents = eventset; + stm32_callback(priv); +} + +/**************************************************************************** + * Name: stm32_registercallback + * + * Description: + * Register a callback that that will be invoked on any media status + * change. Callbacks should not be made from interrupt handlers, rather + * interrupt level events should be handled by calling back on the work + * thread. + * + * When this method is called, all callbacks should be disabled until they + * are enabled via a call to SDIO_CALLBACKENABLE + * + * Input Parameters: + * dev - Device-specific state data + * callback - The funtion to call on the media change + * arg - A caller provided value to return with the callback + * + * Returned Value: + * 0 on success; negated errno on failure. + * + ****************************************************************************/ + +static int stm32_registercallback(FAR struct sdio_dev_s *dev, + worker_t callback, void *arg) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s*)dev; + + /* Disable callbacks and register this callback and is argument */ + + fvdbg("Register %p(%p)\n", callback, arg); + DEBUGASSERT(priv != NULL); + + priv->cbevents = 0; + priv->cbarg = arg; + priv->callback = callback; + return OK; +} + +/**************************************************************************** + * Name: stm32_dmasupported + * + * Description: + * Return true if the hardware can support DMA + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * + * Returned Value: + * true if DMA is supported. + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_DMA +static bool stm32_dmasupported(FAR struct sdio_dev_s *dev) +{ + return true; +} +#endif + +/**************************************************************************** + * Name: stm32_dmarecvsetup + * + * Description: + * Setup to perform a read DMA. If the processor supports a data cache, + * then this method will also make sure that the contents of the DMA memory + * and the data cache are coherent. For read transfers this may mean + * invalidating the data cache. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * buffer - The memory to DMA from + * buflen - The size of the DMA transfer in bytes + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_DMA +static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, + size_t buflen) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s *)dev; + uint32_t dblocksize; + int ret = -EINVAL; + + DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0); + DEBUGASSERT(((uint32_t)buffer & 3) == 0); + + /* Reset the DPSM configuration */ + + stm32_datadisable(); + + /* Wide bus operation is required for DMA */ + + if (priv->widebus) + { + stm32_sampleinit(); + stm32_sample(priv, SAMPLENDX_BEFORE_SETUP); + + /* Save the destination buffer information for use by the interrupt handler */ + + priv->buffer = (uint32_t*)buffer; + priv->remaining = buflen; + priv->dmamode = true; + + /* Then set up the SDIO data path */ + + dblocksize = stm32_log2(buflen) << SDIO_DCTRL_DBLOCKSIZE_SHIFT; + stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, buflen, dblocksize|SDIO_DCTRL_DTDIR); + + /* Configure the RX DMA */ + + stm32_configxfrints(priv, SDIO_DMARECV_MASK); + + putreg32(1, SDIO_DCTRL_DMAEN_BB); + stm32_dmasetup(priv->dma, STM32_SDIO_FIFO, (uint32_t)buffer, + (buflen + 3) >> 2, SDIO_RXDMA32_CONFIG); + + /* Start the DMA */ + + stm32_sample(priv, SAMPLENDX_BEFORE_ENABLE); + stm32_dmastart(priv->dma, stm32_dmacallback, priv, false); + stm32_sample(priv, SAMPLENDX_AFTER_SETUP); + ret = OK; + } + return ret; +} +#endif + +/**************************************************************************** + * Name: stm32_dmasendsetup + * + * Description: + * Setup to perform a write DMA. If the processor supports a data cache, + * then this method will also make sure that the contents of the DMA memory + * and the data cache are coherent. For write transfers, this may mean + * flushing the data cache. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * buffer - The memory to DMA into + * buflen - The size of the DMA transfer in bytes + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_DMA +static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev, + FAR const uint8_t *buffer, size_t buflen) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s *)dev; + uint32_t dblocksize; + int ret = -EINVAL; + + DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0); + DEBUGASSERT(((uint32_t)buffer & 3) == 0); + + /* Reset the DPSM configuration */ + + stm32_datadisable(); + + /* Wide bus operation is required for DMA */ + + if (priv->widebus) + { + stm32_sampleinit(); + stm32_sample(priv, SAMPLENDX_BEFORE_SETUP); + + /* Save the source buffer information for use by the interrupt handler */ + + priv->buffer = (uint32_t*)buffer; + priv->remaining = buflen; + priv->dmamode = true; + + /* Then set up the SDIO data path */ + + dblocksize = stm32_log2(buflen) << SDIO_DCTRL_DBLOCKSIZE_SHIFT; + stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, buflen, dblocksize); + + /* Configure the TX DMA */ + + stm32_dmasetup(priv->dma, STM32_SDIO_FIFO, (uint32_t)buffer, + (buflen + 3) >> 2, SDIO_TXDMA32_CONFIG); + + stm32_sample(priv, SAMPLENDX_BEFORE_ENABLE); + putreg32(1, SDIO_DCTRL_DMAEN_BB); + + /* Start the DMA */ + + stm32_dmastart(priv->dma, stm32_dmacallback, priv, false); + stm32_sample(priv, SAMPLENDX_AFTER_SETUP); + + /* Enable TX interrrupts */ + + stm32_configxfrints(priv, SDIO_DMASEND_MASK); + + ret = OK; + } + return ret; +} +#endif + +/**************************************************************************** + * Initialization/uninitialization/reset + ****************************************************************************/ +/**************************************************************************** + * Name: stm32_callback + * + * Description: + * Perform callback. + * + * Assumptions: + * This function does not execute in the context of an interrupt handler. + * It may be invoked on any user thread or scheduled on the work thread + * from an interrupt handler. + * + ****************************************************************************/ + +static void stm32_callback(void *arg) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s*)arg; + + /* Is a callback registered? */ + + DEBUGASSERT(priv != NULL); + fvdbg("Callback %p(%p) cbevents: %02x cdstatus: %02x\n", + priv->callback, priv->cbarg, priv->cbevents, priv->cdstatus); + + if (priv->callback) + { + /* Yes.. Check for enabled callback events */ + + if ((priv->cdstatus & SDIO_STATUS_PRESENT) != 0) + { + /* Media is present. Is the media inserted event enabled? */ + + if ((priv->cbevents & SDIOMEDIA_INSERTED) == 0) + { + /* No... return without performing the callback */ + + return; + } + } + else + { + /* Media is not present. Is the media eject event enabled? */ + + if ((priv->cbevents & SDIOMEDIA_EJECTED) == 0) + { + /* No... return without performing the callback */ + + return; + } + } + + /* Perform the callback, disabling further callbacks. Of course, the + * the callback can (and probably should) re-enable callbacks. + */ + + priv->cbevents = 0; + + /* Callbacks cannot be performed in the context of an interrupt handler. + * If we are in an interrupt handler, then queue the callback to be + * performed later on the work thread. + */ + + if (up_interrupt_context()) + { + /* Yes.. queue it */ + + fvdbg("Queuing callback to %p(%p)\n", priv->callback, priv->cbarg); + (void)work_queue(&priv->cbwork, (worker_t)priv->callback, priv->cbarg, 0); + } + else + { + /* No.. then just call the callback here */ + + fvdbg("Callback to %p(%p)\n", priv->callback, priv->cbarg); + priv->callback(priv->cbarg); + } + } +} + +/**************************************************************************** + * Name: stm32_default + * + * Description: + * Restore SDIO registers to their default, reset values + * + ****************************************************************************/ + +static void stm32_default(void) +{ + putreg32(SDIO_POWER_RESET, STM32_SDIO_POWER); + putreg32(SDIO_CLKCR_RESET, STM32_SDIO_CLKCR); + putreg32(SDIO_ARG_RESET, STM32_SDIO_ARG); + putreg32(SDIO_CMD_RESET, STM32_SDIO_CMD); + putreg32(SDIO_DTIMER_RESET, STM32_SDIO_DTIMER); + putreg32(SDIO_DLEN_RESET, STM32_SDIO_DLEN); + putreg32(SDIO_DCTRL_RESET, STM32_SDIO_DCTRL); + putreg32(SDIO_ICR_RESET, STM32_SDIO_ICR); + putreg32(SDIO_MASK_RESET, STM32_SDIO_MASK); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sdio_initialize + * + * Description: + * Initialize SDIO for operation. + * + * Input Parameters: + * slotno - Not used. + * + * Returned Values: + * A reference to an SDIO interface structure. NULL is returned on failures. + * + ****************************************************************************/ + +FAR struct sdio_dev_s *sdio_initialize(int slotno) +{ + /* There is only one slot */ + + struct stm32_dev_s *priv = &g_sdiodev; + + /* Initialize the SDIO slot structure */ + + sem_init(&priv->waitsem, 0, 0); + priv->waitwdog = wd_create(); + DEBUGASSERT(priv->waitwdog); + + /* Allocate a DMA channel */ + +#ifdef CONFIG_SDIO_DMA + priv->dma = stm32_dmachannel(SDIO_DMACHAN); + DEBUGASSERT(priv->dma); +#endif + + /* Configure GPIOs for 4-bit, wide-bus operation (the chip is capable of + * 8-bit wide bus operation but D4-D7 are not configured). + * + * If bus is multiplexed then there is a custom bus configuration utility + * in the scope of the board support package. + */ + +#ifndef CONFIG_SDIO_MUXBUS + stm32_configgpio(GPIO_SDIO_D0); +#ifndef CONFIG_SDIO_WIDTH_D1_ONLY + stm32_configgpio(GPIO_SDIO_D1); + stm32_configgpio(GPIO_SDIO_D2); + stm32_configgpio(GPIO_SDIO_D3); +#endif + stm32_configgpio(GPIO_SDIO_CK); + stm32_configgpio(GPIO_SDIO_CMD); +#endif + + /* Reset the card and assure that it is in the initial, unconfigured + * state. + */ + + stm32_reset(&priv->dev); + return &g_sdiodev.dev; +} + +/**************************************************************************** + * Name: sdio_mediachange + * + * Description: + * Called by board-specific logic -- posssible from an interrupt handler -- + * in order to signal to the driver that a card has been inserted or + * removed from the slot + * + * Input Parameters: + * dev - An instance of the SDIO driver device state structure. + * cardinslot - true is a card has been detected in the slot; false if a + * card has been removed from the slot. Only transitions + * (inserted->removed or removed->inserted should be reported) + * + * Returned Values: + * None + * + ****************************************************************************/ + +void sdio_mediachange(FAR struct sdio_dev_s *dev, bool cardinslot) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s *)dev; + uint8_t cdstatus; + irqstate_t flags; + + /* Update card status */ + + flags = irqsave(); + cdstatus = priv->cdstatus; + if (cardinslot) + { + priv->cdstatus |= SDIO_STATUS_PRESENT; + } + else + { + priv->cdstatus &= ~SDIO_STATUS_PRESENT; + } + fvdbg("cdstatus OLD: %02x NEW: %02x\n", cdstatus, priv->cdstatus); + + /* Perform any requested callback if the status has changed */ + + if (cdstatus != priv->cdstatus) + { + stm32_callback(priv); + } + irqrestore(flags); +} + +/**************************************************************************** + * Name: sdio_wrprotect + * + * Description: + * Called by board-specific logic to report if the card in the slot is + * mechanically write protected. + * + * Input Parameters: + * dev - An instance of the SDIO driver device state structure. + * wrprotect - true is a card is writeprotected. + * + * Returned Values: + * None + * + ****************************************************************************/ + +void sdio_wrprotect(FAR struct sdio_dev_s *dev, bool wrprotect) +{ + struct stm32_dev_s *priv = (struct stm32_dev_s *)dev; + irqstate_t flags; + + /* Update card status */ + + flags = irqsave(); + if (wrprotect) + { + priv->cdstatus |= SDIO_STATUS_WRPROTECTED; + } + else + { + priv->cdstatus &= ~SDIO_STATUS_WRPROTECTED; + } + fvdbg("cdstatus: %02x\n", priv->cdstatus); + irqrestore(flags); +} +#endif /* CONFIG_STM32_SDIO */ diff --git a/nuttx/arch/arm/src/stm32/stm32_sdio.h b/nuttx/arch/arm/src/stm32/stm32_sdio.h new file mode 100644 index 0000000000..ceeb56f0dd --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_sdio.h @@ -0,0 +1,127 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_sdio.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_SDIO_H +#define __ARCH_ARM_SRC_STM32_STM32_SDIO_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include + +#include "chip.h" +#include "chip/stm32_sdio.h" + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: sdio_initialize + * + * Description: + * Initialize SDIO for operation. + * + * Input Parameters: + * slotno - Not used. + * + * Returned Values: + * A reference to an SDIO interface structure. NULL is returned on failures. + * + ****************************************************************************/ + +struct sdio_dev_s; /* See include/nuttx/sdio.h */ +EXTERN FAR struct sdio_dev_s *sdio_initialize(int slotno); + +/**************************************************************************** + * Name: sdio_mediachange + * + * Description: + * Called by board-specific logic -- posssible from an interrupt handler -- + * in order to signal to the driver that a card has been inserted or + * removed from the slot + * + * Input Parameters: + * dev - An instance of the SDIO driver device state structure. + * cardinslot - true is a card has been detected in the slot; false if a + * card has been removed from the slot. Only transitions + * (inserted->removed or removed->inserted should be reported) + * + * Returned Values: + * None + * + ****************************************************************************/ + +EXTERN void sdio_mediachange(FAR struct sdio_dev_s *dev, bool cardinslot); + +/**************************************************************************** + * Name: sdio_wrprotect + * + * Description: + * Called by board-specific logic to report if the card in the slot is + * mechanically write protected. + * + * Input Parameters: + * dev - An instance of the SDIO driver device state structure. + * wrprotect - true is a card is writeprotected. + * + * Returned Values: + * None + * + ****************************************************************************/ + +EXTERN void sdio_wrprotect(FAR struct sdio_dev_s *dev, bool wrprotect); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_SDIO_H */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_serial.c b/nuttx/arch/arm/src/stm32/stm32_serial.c new file mode 100644 index 0000000000..01c519b399 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_serial.c @@ -0,0 +1,1959 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_serial.c + * + * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + +#include +#include + +#include "chip.h" +#include "stm32_uart.h" +#include "stm32_dma.h" +#include "up_arch.h" +#include "up_internal.h" +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Some sanity checks *******************************************************/ +/* DMA configuration */ + +/* If DMA is enabled on any USART, then very that other pre-requisites + * have also been selected. + */ + +#if SERIAL_HAVE_DMA + +/* Verify that DMA has been enabled an the DMA channel has been defined. + * NOTE: These assignments may only be true for the F4. + */ + +# if defined(CONFIG_USART1_RXDMA) || defined(CONFIG_USART6_RXDMA) +# ifndef CONFIG_STM32_DMA2 +# error STM32 USART1/6 receive DMA requires CONFIG_STM32_DMA2 +# endif +# endif + +# if defined(CONFIG_USART2_RXDMA) || defined(CONFIG_USART3_RXDMA) || \ + defined(CONFIG_USART4_RXDMA) || defined(CONFIG_USART5_RXDMA) +# ifndef CONFIG_STM32_DMA1 +# error STM32 USART2/3/4/5 receive DMA requires CONFIG_STM32_DMA1 +# endif +# endif + +/* For the F4, there are alternate DMA channels for USART1 and 6. + * Logic in the board.h file make the DMA channel selection by defining + * the following in the board.h file. + */ + +# if defined(CONFIG_USART1_RXDMA) && !defined(DMAMAP_USART1_RX) +# error "USART1 DMA channel not defined (DMAMAP_USART1_RX)" +# endif + +# if defined(CONFIG_USART2_RXDMA) && !defined(DMAMAP_USART2_RX) +# error "USART2 DMA channel not defined (DMAMAP_USART2_RX)" +# endif + +# if defined(CONFIG_USART3_RXDMA) && !defined(DMAMAP_USART3_RX) +# error "USART3 DMA channel not defined (DMAMAP_USART3_RX)" +# endif + +# if defined(CONFIG_USART4_RXDMA) && !defined(DMAMAP_UART4_RX) +# error "UART4 DMA channel not defined (DMAMAP_UART4_RX)" +# endif + +# if defined(CONFIG_USART5_RXDMA) && !defined(DMAMAP_UART5_RX) +# error "UART5 DMA channel not defined (DMAMAP_UART5_RX)" +# endif + +# if defined(CONFIG_USART6_RXDMA) && !defined(DMAMAP_USART6_RX) +# error "USART6 DMA channel not defined (DMAMAP_USART6_RX)" +# endif + +/* The DMA buffer size when using RX DMA to emulate a FIFO. + * + * When streaming data, the generic serial layer will be called + * everytime the FIFO receives half this number of bytes. + */ + +# define RXDMA_BUFFER_SIZE 32 +#endif + +/* Power management definitions */ + +#if defined(CONFIG_PM) && !defined(CONFIG_PM_SERIAL_ACTIVITY) +# define CONFIG_PM_SERIAL_ACTIVITY 10 +#endif + +#ifdef USE_SERIALDRIVER +#ifdef HAVE_UART + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct up_dev_s +{ + struct uart_dev_s dev; /* Generic UART device */ + uint16_t ie; /* Saved interrupt mask bits value */ + uint16_t sr; /* Saved status bits */ + + /* If termios are supported, then the following fields may vary at + * runtime. + */ + +#ifdef CONFIG_SERIAL_TERMIOS + uint8_t parity; /* 0=none, 1=odd, 2=even */ + uint8_t bits; /* Number of bits (7 or 8) */ + bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */ + uint32_t baud; /* Configured baud */ +#else + const uint8_t parity; /* 0=none, 1=odd, 2=even */ + const uint8_t bits; /* Number of bits (7 or 8) */ + const bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */ + const uint32_t baud; /* Configured baud */ +#endif + + const uint8_t irq; /* IRQ associated with this USART */ + const uint32_t apbclock; /* PCLK 1 or 2 frequency */ + const uint32_t usartbase; /* Base address of USART registers */ + const uint32_t tx_gpio; /* U[S]ART TX GPIO pin configuration */ + const uint32_t rx_gpio; /* U[S]ART RX GPIO pin configuration */ + const uint32_t rts_gpio; /* U[S]ART RTS GPIO pin configuration */ + const uint32_t cts_gpio; /* U[S]ART CTS GPIO pin configuration */ + +#ifdef SERIAL_HAVE_DMA + const unsigned int rxdma_channel; /* DMA channel assigned */ +#endif + + int (* const vector)(int irq, void *context); /* Interrupt handler */ + + /* RX DMA state */ + +#ifdef SERIAL_HAVE_DMA + DMA_HANDLE rxdma; /* currently-open receive DMA stream */ + bool rxenable; /* DMA-based reception en/disable */ + uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */ + char *const rxfifo; /* Receive DMA buffer */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void up_setspeed(struct uart_dev_s *dev); +static int up_setup(struct uart_dev_s *dev); +static void up_shutdown(struct uart_dev_s *dev); +static int up_attach(struct uart_dev_s *dev); +static void up_detach(struct uart_dev_s *dev); +static int up_interrupt_common(struct up_dev_s *dev); +static int up_ioctl(struct file *filep, int cmd, unsigned long arg); +#ifndef SERIAL_HAVE_ONLY_DMA +static int up_receive(struct uart_dev_s *dev, uint32_t *status); +static void up_rxint(struct uart_dev_s *dev, bool enable); +static bool up_rxavailable(struct uart_dev_s *dev); +#endif +static void up_send(struct uart_dev_s *dev, int ch); +static void up_txint(struct uart_dev_s *dev, bool enable); +static bool up_txready(struct uart_dev_s *dev); + +#ifdef SERIAL_HAVE_DMA +static int up_dma_setup(struct uart_dev_s *dev); +static void up_dma_shutdown(struct uart_dev_s *dev); +static int up_dma_receive(struct uart_dev_s *dev, uint32_t *status); +static void up_dma_rxint(struct uart_dev_s *dev, bool enable); +static bool up_dma_rxavailable(struct uart_dev_s *dev); + +static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, void *arg); +#endif + +#ifdef CONFIG_PM +static void up_pm_notify(struct pm_callback_s *cb, enum pm_state_e pmstate); +static int up_pm_prepare(struct pm_callback_s *cb, enum pm_state_e pmstate); +#endif + +#ifdef CONFIG_STM32_USART1 +static int up_interrupt_usart1(int irq, void *context); +#endif +#ifdef CONFIG_STM32_USART2 +static int up_interrupt_usart2(int irq, void *context); +#endif +#ifdef CONFIG_STM32_USART3 +static int up_interrupt_usart3(int irq, void *context); +#endif +#ifdef CONFIG_STM32_UART4 +static int up_interrupt_uart4(int irq, void *context); +#endif +#ifdef CONFIG_STM32_UART5 +static int up_interrupt_uart5(int irq, void *context); +#endif +#ifdef CONFIG_STM32_USART6 +static int up_interrupt_usart6(int irq, void *context); +#endif + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +#ifndef SERIAL_HAVE_ONLY_DMA +static const struct uart_ops_s g_uart_ops = +{ + .setup = up_setup, + .shutdown = up_shutdown, + .attach = up_attach, + .detach = up_detach, + .ioctl = up_ioctl, + .receive = up_receive, + .rxint = up_rxint, + .rxavailable = up_rxavailable, + .send = up_send, + .txint = up_txint, + .txready = up_txready, + .txempty = up_txready, +}; +#endif + +#ifdef SERIAL_HAVE_DMA +static const struct uart_ops_s g_uart_dma_ops = +{ + .setup = up_dma_setup, + .shutdown = up_dma_shutdown, + .attach = up_attach, + .detach = up_detach, + .ioctl = up_ioctl, + .receive = up_dma_receive, + .rxint = up_dma_rxint, + .rxavailable = up_dma_rxavailable, + .send = up_send, + .txint = up_txint, + .txready = up_txready, + .txempty = up_txready, +}; +#endif + +/* I/O buffers */ + +#ifdef CONFIG_STM32_USART1 +static char g_usart1rxbuffer[CONFIG_USART1_RXBUFSIZE]; +static char g_usart1txbuffer[CONFIG_USART1_TXBUFSIZE]; +# ifdef CONFIG_USART1_RXDMA +static char g_usart1rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_STM32_USART2 +static char g_usart2rxbuffer[CONFIG_USART2_RXBUFSIZE]; +static char g_usart2txbuffer[CONFIG_USART2_TXBUFSIZE]; +# ifdef CONFIG_USART2_RXDMA +static char g_usart2rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_STM32_USART3 +static char g_usart3rxbuffer[CONFIG_USART3_RXBUFSIZE]; +static char g_usart3txbuffer[CONFIG_USART3_TXBUFSIZE]; +# ifdef CONFIG_USART3_RXDMA +static char g_usart3rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_STM32_UART4 +static char g_uart4rxbuffer[CONFIG_USART4_RXBUFSIZE]; +static char g_uart4txbuffer[CONFIG_USART4_TXBUFSIZE]; +# ifdef CONFIG_USART4_RXDMA +static char g_uart4rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_STM32_UART5 +static char g_uart5rxbuffer[CONFIG_USART5_RXBUFSIZE]; +static char g_uart5txbuffer[CONFIG_USART5_TXBUFSIZE]; +# ifdef CONFIG_USART5_RXDMA +static char g_uart5rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_STM32_USART6 +static char g_usart6rxbuffer[CONFIG_USART6_RXBUFSIZE]; +static char g_usart6txbuffer[CONFIG_USART6_TXBUFSIZE]; +# ifdef CONFIG_USART6_RXDMA +static char g_usart6rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +/* This describes the state of the STM32 USART1 ports. */ + +#ifdef CONFIG_STM32_USART1 +static struct up_dev_s g_usart1priv = +{ + .dev = + { +#if CONSOLE_UART == 1 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_USART1_RXBUFSIZE, + .buffer = g_usart1rxbuffer, + }, + .xmit = + { + .size = CONFIG_USART1_TXBUFSIZE, + .buffer = g_usart1txbuffer, + }, +#ifdef CONFIG_USART1_RXDMA + .ops = &g_uart_dma_ops, +#else + .ops = &g_uart_ops, +#endif + .priv = &g_usart1priv, + }, + + .irq = STM32_IRQ_USART1, + .parity = CONFIG_USART1_PARITY, + .bits = CONFIG_USART1_BITS, + .stopbits2 = CONFIG_USART1_2STOP, + .baud = CONFIG_USART1_BAUD, + .apbclock = STM32_PCLK2_FREQUENCY, + .usartbase = STM32_USART1_BASE, + .tx_gpio = GPIO_USART1_TX, + .rx_gpio = GPIO_USART1_RX, +#ifdef GPIO_USART1_CTS + .cts_gpio = GPIO_USART1_CTS, +#endif +#ifdef GPIO_USART1_RTS + .rts_gpio = GPIO_USART1_RTS, +#endif +#ifdef CONFIG_USART1_RXDMA + .rxdma_channel = DMAMAP_USART1_RX, + .rxfifo = g_usart1rxfifo, +#endif + .vector = up_interrupt_usart1, +}; +#endif + +/* This describes the state of the STM32 USART2 port. */ + +#ifdef CONFIG_STM32_USART2 +static struct up_dev_s g_usart2priv = +{ + .dev = + { +#if CONSOLE_UART == 2 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_USART2_RXBUFSIZE, + .buffer = g_usart2rxbuffer, + }, + .xmit = + { + .size = CONFIG_USART2_TXBUFSIZE, + .buffer = g_usart2txbuffer, + }, +#ifdef CONFIG_USART2_RXDMA + .ops = &g_uart_dma_ops, +#else + .ops = &g_uart_ops, +#endif + .priv = &g_usart2priv, + }, + + .irq = STM32_IRQ_USART2, + .parity = CONFIG_USART2_PARITY, + .bits = CONFIG_USART2_BITS, + .stopbits2 = CONFIG_USART2_2STOP, + .baud = CONFIG_USART2_BAUD, + .apbclock = STM32_PCLK1_FREQUENCY, + .usartbase = STM32_USART2_BASE, + .tx_gpio = GPIO_USART2_TX, + .rx_gpio = GPIO_USART2_RX, +#ifdef GPIO_USART2_CTS + .cts_gpio = GPIO_USART2_CTS, +#endif +#ifdef GPIO_USART2_RTS + .rts_gpio = GPIO_USART2_RTS, +#endif +#ifdef CONFIG_USART2_RXDMA + .rxdma_channel = DMAMAP_USART2_RX, + .rxfifo = g_usart2rxfifo, +#endif + .vector = up_interrupt_usart2, +}; +#endif + +/* This describes the state of the STM32 USART3 port. */ + +#ifdef CONFIG_STM32_USART3 +static struct up_dev_s g_usart3priv = +{ + .dev = + { +#if CONSOLE_UART == 3 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_USART3_RXBUFSIZE, + .buffer = g_usart3rxbuffer, + }, + .xmit = + { + .size = CONFIG_USART3_TXBUFSIZE, + .buffer = g_usart3txbuffer, + }, +#ifdef CONFIG_USART3_RXDMA + .ops = &g_uart_dma_ops, +#else + .ops = &g_uart_ops, +#endif + .priv = &g_usart3priv, + }, + + .irq = STM32_IRQ_USART3, + .parity = CONFIG_USART3_PARITY, + .bits = CONFIG_USART3_BITS, + .stopbits2 = CONFIG_USART3_2STOP, + .baud = CONFIG_USART3_BAUD, + .apbclock = STM32_PCLK1_FREQUENCY, + .usartbase = STM32_USART3_BASE, + .tx_gpio = GPIO_USART3_TX, + .rx_gpio = GPIO_USART3_RX, +#ifdef GPIO_USART3_CTS + .cts_gpio = GPIO_USART3_CTS, +#endif +#ifdef GPIO_USART3_RTS + .rts_gpio = GPIO_USART3_RTS, +#endif +#ifdef CONFIG_USART3_RXDMA + .rxdma_channel = DMAMAP_USART3_RX, + .rxfifo = g_usart3rxfifo, +#endif + .vector = up_interrupt_usart3, +}; +#endif + +/* This describes the state of the STM32 UART4 port. */ + +#ifdef CONFIG_STM32_UART4 +static struct up_dev_s g_uart4priv = +{ + .dev = + { +#if CONSOLE_UART == 4 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_USART4_RXBUFSIZE, + .buffer = g_uart4rxbuffer, + }, + .xmit = + { + .size = CONFIG_USART4_TXBUFSIZE, + .buffer = g_uart4txbuffer, + }, +#ifdef CONFIG_USART4_RXDMA + .ops = &g_uart_dma_ops, +#else + .ops = &g_uart_ops, +#endif + .priv = &g_uart4priv, + }, + + .irq = STM32_IRQ_UART4, + .parity = CONFIG_USART4_PARITY, + .bits = CONFIG_USART4_BITS, + .stopbits2 = CONFIG_USART4_2STOP, + .baud = CONFIG_USART4_BAUD, + .apbclock = STM32_PCLK1_FREQUENCY, + .usartbase = STM32_UART4_BASE, + .tx_gpio = GPIO_UART4_TX, + .rx_gpio = GPIO_UART4_RX, +#ifdef GPIO_USART4_CTS + .cts_gpio = GPIO_UART4_CTS, +#endif +#ifdef GPIO_USART4_RTS + .rts_gpio = GPIO_UART4_RTS, +#endif +#ifdef CONFIG_USART4_RXDMA + .rxdma_channel = DMAMAP_UART4_RX, + .rxfifo = g_uart4rxfifo, +#endif + .vector = up_interrupt_uart4, +}; +#endif + +/* This describes the state of the STM32 UART5 port. */ + +#ifdef CONFIG_STM32_UART5 +static struct up_dev_s g_uart5priv = +{ + .dev = + { +#if CONSOLE_UART == 5 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_USART5_RXBUFSIZE, + .buffer = g_uart5rxbuffer, + }, + .xmit = + { + .size = CONFIG_USART5_TXBUFSIZE, + .buffer = g_uart5txbuffer, + }, +#ifdef CONFIG_USART5_RXDMA + .ops = &g_uart_dma_ops, +#else + .ops = &g_uart_ops, +#endif + .priv = &g_uart5priv, + }, + + .irq = STM32_IRQ_UART5, + .parity = CONFIG_USART5_PARITY, + .bits = CONFIG_USART5_BITS, + .stopbits2 = CONFIG_USART5_2STOP, + .baud = CONFIG_USART5_BAUD, + .apbclock = STM32_PCLK1_FREQUENCY, + .usartbase = STM32_UART5_BASE, + .tx_gpio = GPIO_UART5_TX, + .rx_gpio = GPIO_UART5_RX, +#ifdef GPIO_USART5_CTS + .cts_gpio = GPIO_UART5_CTS, +#endif +#ifdef GPIO_USART5_RTS + .rts_gpio = GPIO_UART5_RTS, +#endif +#ifdef CONFIG_USART5_RXDMA + .rxdma_channel = DMAMAP_UART5_RX, + .rxfifo = g_uart5rxfifo, +#endif + .vector = up_interrupt_uart5, +}; +#endif + +/* This describes the state of the STM32 USART6 port. */ + +#ifdef CONFIG_STM32_USART6 +static struct up_dev_s g_usart6priv = +{ + .dev = + { +#if CONSOLE_UART == 6 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_USART6_RXBUFSIZE, + .buffer = g_usart6rxbuffer, + }, + .xmit = + { + .size = CONFIG_USART6_TXBUFSIZE, + .buffer = g_usart6txbuffer, + }, +#ifdef CONFIG_USART6_RXDMA + .ops = &g_uart_dma_ops, +#else + .ops = &g_uart_ops, +#endif + .priv = &g_usart6priv, + }, + + .irq = STM32_IRQ_USART6, + .parity = CONFIG_USART6_PARITY, + .bits = CONFIG_USART6_BITS, + .stopbits2 = CONFIG_USART6_2STOP, + .baud = CONFIG_USART6_BAUD, + .apbclock = STM32_PCLK2_FREQUENCY, + .usartbase = STM32_USART6_BASE, + .tx_gpio = GPIO_USART6_TX, + .rx_gpio = GPIO_USART6_RX, +#ifdef GPIO_USART6_CTS + .cts_gpio = GPIO_USART6_CTS, +#endif +#ifdef GPIO_USART6_RTS + .rts_gpio = GPIO_USART6_RTS, +#endif +#ifdef CONFIG_USART6_RXDMA + .rxdma_channel = DMAMAP_USART6_RX, + .rxfifo = g_usart6rxfifo, +#endif + .vector = up_interrupt_usart6, +}; +#endif + +/* This table lets us iterate over the configured USARTs */ + +static struct up_dev_s *uart_devs[STM32_NUSART] = +{ +#ifdef CONFIG_STM32_USART1 + [0] = &g_usart1priv, +#endif +#ifdef CONFIG_STM32_USART2 + [1] = &g_usart2priv, +#endif +#ifdef CONFIG_STM32_USART3 + [2] = &g_usart3priv, +#endif +#ifdef CONFIG_STM32_UART4 + [3] = &g_uart4priv, +#endif +#ifdef CONFIG_STM32_UART5 + [4] = &g_uart5priv, +#endif +#ifdef CONFIG_STM32_USART6 + [5] = &g_usart6priv, +#endif +}; + +#ifdef CONFIG_PM +static struct pm_callback_s g_serialcb = +{ + .notify = up_pm_notify, + .prepare = up_pm_prepare, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_serialin + ****************************************************************************/ + +static inline uint32_t up_serialin(struct up_dev_s *priv, int offset) +{ + return getreg32(priv->usartbase + offset); +} + +/**************************************************************************** + * Name: up_serialout + ****************************************************************************/ + +static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t value) +{ + putreg32(value, priv->usartbase + offset); +} + +/**************************************************************************** + * Name: up_restoreusartint + ****************************************************************************/ + +static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) +{ + uint32_t cr; + + /* Save the interrupt mask */ + + priv->ie = ie; + + /* And restore the interrupt state (see the interrupt enable/usage table above) */ + + cr = up_serialin(priv, STM32_USART_CR1_OFFSET); + cr &= ~(USART_CR1_RXNEIE|USART_CR1_TXEIE|USART_CR1_PEIE); + cr |= (ie & (USART_CR1_RXNEIE|USART_CR1_TXEIE|USART_CR1_PEIE)); + up_serialout(priv, STM32_USART_CR1_OFFSET, cr); + + cr = up_serialin(priv, STM32_USART_CR3_OFFSET); + cr &= ~USART_CR3_EIE; + cr |= (ie & USART_CR3_EIE); + up_serialout(priv, STM32_USART_CR3_OFFSET, cr); +} + +/**************************************************************************** + * Name: up_disableusartint + ****************************************************************************/ + +static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) +{ + if (ie) + { + uint32_t cr1; + uint32_t cr3; + + /* USART interrupts: + * + * Enable Bit Status Meaning Usage + * ------------------ --- --------------- ------------------------------ ---------- + * USART_CR1_IDLEIE 4 USART_SR_IDLE Idle Line Detected (not used) + * USART_CR1_RXNEIE 5 USART_SR_RXNE Received Data Ready to be Read + * " " USART_SR_ORE Overrun Error Detected + * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (not used) + * USART_CR1_TXEIE 7 USART_SR_TXE Transmit Data Register Empty + * USART_CR1_PEIE 8 USART_SR_PE Parity Error + * + * USART_CR2_LBDIE 6 USART_SR_LBD Break Flag (not used) + * USART_CR3_EIE 0 USART_SR_FE Framing Error + * " " USART_SR_NE Noise Error + * " " USART_SR_ORE Overrun Error Detected + * USART_CR3_CTSIE 10 USART_SR_CTS CTS flag (not used) + */ + + cr1 = up_serialin(priv, STM32_USART_CR1_OFFSET); + cr3 = up_serialin(priv, STM32_USART_CR3_OFFSET); + + /* Return the current interrupt mask value for the used interrupts. Notice + * that this depends on the fact that none of the used interrupt enable bits + * overlap. This logic would fail if we needed the break interrupt! + */ + + *ie = (cr1 & (USART_CR1_RXNEIE|USART_CR1_TXEIE|USART_CR1_PEIE)) | (cr3 & USART_CR3_EIE); + } + + /* Disable all interrupts */ + + up_restoreusartint(priv, 0); +} + +/**************************************************************************** + * Name: up_dma_nextrx + * + * Description: + * Returns the index into the RX FIFO where the DMA will place the next + * byte that it receives. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static int up_dma_nextrx(struct up_dev_s *priv) +{ + size_t dmaresidual; + + dmaresidual = stm32_dmaresidual(priv->rxdma); + + return (RXDMA_BUFFER_SIZE - (int)dmaresidual); +} +#endif + +/**************************************************************************** + * Name: up_setspeed + * + * Description: + * Set the serial line speed. + * + ****************************************************************************/ + +#ifndef CONFIG_SUPPRESS_UART_CONFIG +static void up_setspeed(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + uint32_t usartdiv32; + uint32_t mantissa; + uint32_t fraction; + uint32_t brr; + + /* Configure the USART Baud Rate. The baud rate for the receiver and + * transmitter (Rx and Tx) are both set to the same value as programmed + * in the Mantissa and Fraction values of USARTDIV. + * + * baud = fCK / (16 * usartdiv) + * usartdiv = fCK / (16 * baud) + * + * Where fCK is the input clock to the peripheral (PCLK1 for USART2, 3, 4, 5 + * or PCLK2 for USART1) + * + * First calculate (NOTE: all stand baud values are even so dividing by two + * does not lose precision): + * + * usartdiv32 = 32 * usartdiv = fCK / (baud/2) + */ + + usartdiv32 = priv->apbclock / (priv->baud >> 1); + + /* The mantissa part is then */ + + mantissa = usartdiv32 >> 5; + brr = mantissa << USART_BRR_MANT_SHIFT; + + /* The fractional remainder (with rounding) */ + + fraction = (usartdiv32 - (mantissa << 5) + 1) >> 1; + brr |= fraction << USART_BRR_FRAC_SHIFT; + up_serialout(priv, STM32_USART_BRR_OFFSET, brr); +} +#endif + +/**************************************************************************** + * Name: up_setup + * + * Description: + * Configure the USART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +static int up_setup(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; +#ifndef CONFIG_SUPPRESS_UART_CONFIG + uint32_t regval; + + /* Note: The logic here depends on the fact that that the USART module + * was enabled in stm32_lowsetup(). + */ + + /* Configure pins for USART use */ + + stm32_configgpio(priv->tx_gpio); + stm32_configgpio(priv->rx_gpio); + + if (priv->cts_gpio != 0) + { + stm32_configgpio(priv->cts_gpio); + } + + if (priv->rts_gpio != 0) + { + stm32_configgpio(priv->rts_gpio); + } + + /* Configure CR2 */ + /* Clear STOP, CLKEN, CPOL, CPHA, LBCL, and interrupt enable bits */ + + regval = up_serialin(priv, STM32_USART_CR2_OFFSET); + regval &= ~(USART_CR2_STOP_MASK|USART_CR2_CLKEN|USART_CR2_CPOL| + USART_CR2_CPHA|USART_CR2_LBCL|USART_CR2_LBDIE); + + /* Configure STOP bits */ + + if (priv->stopbits2) + { + regval |= USART_CR2_STOP2; + } + up_serialout(priv, STM32_USART_CR2_OFFSET, regval); + + /* Configure CR1 */ + /* Clear M, PCE, PS, TE, REm and all interrupt enable bits */ + + regval = up_serialin(priv, STM32_USART_CR1_OFFSET); + regval &= ~(USART_CR1_M|USART_CR1_PCE|USART_CR1_PS|USART_CR1_TE| + USART_CR1_RE|USART_CR1_ALLINTS); + + /* Configure word length and parity mode */ + + if (priv->bits == 9) /* Default: 1 start, 8 data, n stop */ + { + regval |= USART_CR1_M; /* 1 start, 9 data, n stop */ + } + + if (priv->parity == 1) /* Odd parity */ + { + regval |= (USART_CR1_PCE|USART_CR1_PS); + } + else if (priv->parity == 2) /* Even parity */ + { + regval |= USART_CR1_PCE; + } + + up_serialout(priv, STM32_USART_CR1_OFFSET, regval); + + /* Configure CR3 */ + /* Clear CTSE, RTSE, and all interrupt enable bits */ + + regval = up_serialin(priv, STM32_USART_CR3_OFFSET); + regval &= ~(USART_CR3_CTSIE|USART_CR3_CTSE|USART_CR3_RTSE|USART_CR3_EIE); + + /* Configure hardware flow control -- Not yet supported */ + + up_serialout(priv, STM32_USART_CR3_OFFSET, regval); + + /* Configure the USART Baud Rate. */ + + up_setspeed(dev); + + /* Enable Rx, Tx, and the USART */ + + regval = up_serialin(priv, STM32_USART_CR1_OFFSET); + regval |= (USART_CR1_UE|USART_CR1_TE|USART_CR1_RE); + up_serialout(priv, STM32_USART_CR1_OFFSET, regval); +#endif + + /* Set up the cached interrupt enables value */ + + priv->ie = 0; + return OK; +} + +/**************************************************************************** + * Name: up_dma_setup + * + * Description: + * Configure the USART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static int up_dma_setup(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + int result; + uint32_t regval; + + /* Do the basic UART setup first */ + + result = up_setup(dev); + if (result != OK) + { + return result; + } + + /* Acquire the DMA channel. This should always succeed. */ + + priv->rxdma = stm32_dmachannel(priv->rxdma_channel); + + /* Configure for circular DMA reception into the RX fifo */ + + stm32_dmasetup(priv->rxdma, + priv->usartbase + STM32_USART_DR_OFFSET, + (uint32_t)priv->rxfifo, + RXDMA_BUFFER_SIZE, + DMA_SCR_DIR_P2M | + DMA_SCR_CIRC | + DMA_SCR_MINC | + DMA_SCR_PSIZE_8BITS | + DMA_SCR_MSIZE_8BITS | + DMA_SCR_PBURST_SINGLE | + DMA_SCR_MBURST_SINGLE); + + /* Reset our DMA shadow pointer to match the address just + * programmed above. + */ + + priv->rxdmanext = 0; + + /* Enable receive DMA for the UART */ + + regval = up_serialin(priv, STM32_USART_CR3_OFFSET); + regval |= USART_CR3_DMAR; + up_serialout(priv, STM32_USART_CR3_OFFSET, regval); + + /* Start the DMA channel, and arrange for callbacks at the half and + * full points in the FIFO. This ensures that we have half a FIFO + * worth of time to claim bytes before they are overwritten. + */ + + stm32_dmastart(priv->rxdma, up_dma_rxcallback, (void *)priv, true); + + return OK; +} +#endif + +/**************************************************************************** + * Name: up_shutdown + * + * Description: + * Disable the USART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +static void up_shutdown(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + uint32_t regval; + + /* Disable all interrupts */ + + up_disableusartint(priv, NULL); + + /* Disable Rx, Tx, and the UART */ + + regval = up_serialin(priv, STM32_USART_CR1_OFFSET); + regval &= ~(USART_CR1_UE|USART_CR1_TE|USART_CR1_RE); + up_serialout(priv, STM32_USART_CR1_OFFSET, regval); +} + +/**************************************************************************** + * Name: up_dma_shutdown + * + * Description: + * Disable the USART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static void up_dma_shutdown(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + + /* Perform the normal UART shutdown */ + + up_shutdown(dev); + + /* Stop the DMA channel */ + + stm32_dmastop(priv->rxdma); + + /* Release the DMA channel */ + + stm32_dmafree(priv->rxdma); + priv->rxdma = NULL; +} +#endif + +/**************************************************************************** + * Name: up_attach + * + * Description: + * Configure the USART to operation in interrupt driven mode. This method is + * called when the serial port is opened. Normally, this is just after the + * the setup() method is called, however, the serial console may operate in + * a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled when by the attach method (unless the + * hardware supports multiple levels of interrupt enabling). The RX and TX + * interrupts are not enabled until the txint() and rxint() methods are called. + * + ****************************************************************************/ + +static int up_attach(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + int ret; + + /* Attach and enable the IRQ */ + + ret = irq_attach(priv->irq, priv->vector); + if (ret == OK) + { + /* Enable the interrupt (RX and TX interrupts are still disabled + * in the USART + */ + + up_enable_irq(priv->irq); + } + return ret; +} + +/**************************************************************************** + * Name: up_detach + * + * Description: + * Detach USART interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called. The exception + * is the serial console which is never shutdown. + * + ****************************************************************************/ + +static void up_detach(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + up_disable_irq(priv->irq); + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: up_interrupt_common + * + * Description: + * This is the USART interrupt handler. It will be invoked when an + * interrupt received on the 'irq' It should call uart_transmitchars or + * uart_receivechar to perform the appropriate data transfers. The + * interrupt handling logic must be able to map the 'irq' number into the + * approprite uart_dev_s structure in order to call these functions. + * + ****************************************************************************/ + +static int up_interrupt_common(struct up_dev_s *priv) +{ + int passes; + bool handled; + + /* Report serial activity to the power management logic */ + +#if defined(CONFIG_PM) && CONFIG_PM_SERIAL_ACTIVITY > 0 + pm_activity(CONFIG_PM_SERIAL_ACTIVITY); +#endif + + /* Loop until there are no characters to be transferred or, + * until we have been looping for a long time. + */ + + handled = true; + for (passes = 0; passes < 256 && handled; passes++) + { + handled = false; + + /* Get the masked USART status word. */ + + priv->sr = up_serialin(priv, STM32_USART_SR_OFFSET); + + /* USART interrupts: + * + * Enable Bit Status Meaning Usage + * ------------------ --- --------------- ------------------------------- ---------- + * USART_CR1_IDLEIE 4 USART_SR_IDLE Idle Line Detected (not used) + * USART_CR1_RXNEIE 5 USART_SR_RXNE Received Data Ready to be Read + * " " USART_SR_ORE Overrun Error Detected + * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (not used) + * USART_CR1_TXEIE 7 USART_SR_TXE Transmit Data Register Empty + * USART_CR1_PEIE 8 USART_SR_PE Parity Error + * + * USART_CR2_LBDIE 6 USART_SR_LBD Break Flag (not used) + * USART_CR3_EIE 0 USART_SR_FE Framing Error + * " " USART_SR_NE Noise Error + * " " USART_SR_ORE Overrun Error Detected + * USART_CR3_CTSIE 10 USART_SR_CTS CTS flag (not used) + * + * NOTE: Some of these status bits must be cleared by explicity writing zero + * to the SR register: USART_SR_CTS, USART_SR_LBD. Note of those are currently + * being used. + */ + + /* Handle incoming, receive bytes. */ + + if ((priv->sr & USART_SR_RXNE) != 0 && (priv->ie & USART_CR1_RXNEIE) != 0) + { + /* Received data ready... process incoming bytes. NOTE the check for + * RXNEIE: We cannot call uart_recvchards of RX interrupts are disabled. + */ + + uart_recvchars(&priv->dev); + handled = true; + } + + /* We may still have to read from the DR register to clear any pending + * error conditions. + */ + + else if ((priv->sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE)) != 0) + { + /* If an error occurs, read from DR to clear the error (data has + * been lost). If ORE is set along with RXNE then it tells you + * that the byte *after* the one in the data register has been + * lost, but the data register value is correct. That case will + * be handled above if interrupts are enabled. Otherwise, that + * good byte will be lost. + */ + + (void)up_serialin(priv, STM32_USART_DR_OFFSET); + } + + /* Handle outgoing, transmit bytes */ + + if ((priv->sr & USART_SR_TXE) != 0 && (priv->ie & USART_CR1_TXEIE) != 0) + { + /* Transmit data regiser empty ... process outgoing bytes */ + + uart_xmitchars(&priv->dev); + handled = true; + } + } + return OK; +} + +/**************************************************************************** + * Name: up_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int up_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + struct inode *inode = filep->f_inode; + struct uart_dev_s *dev = inode->i_private; +#ifdef CONFIG_SERIAL_TERMIOS + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; +#endif + int ret = OK; + + switch (cmd) + { + case TIOCSERGSTRUCT: + { + struct up_dev_s *user = (struct up_dev_s*)arg; + if (!user) + { + ret = -EINVAL; + } + else + { + memcpy(user, dev, sizeof(struct up_dev_s)); + } + } + break; + +#ifdef CONFIG_SERIAL_TERMIOS + case TCGETS: + { + struct termios *termiosp = (struct termios*)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* TODO: Other termios fields are not yet returned. + * Note that only cfsetospeed is not necessary because we have + * knowledge that only one speed is supported. + */ + + cfsetispeed(termiosp, priv->baud); + } + break; + + case TCSETS: + { + struct termios *termiosp = (struct termios*)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* TODO: Handle other termios settings. + * Note that only cfgetispeed is used besued we have knowledge + * that only one speed is supported. + */ + + priv->baud = cfgetispeed(termiosp); + up_setspeed(dev); + } + break; +#endif + +#ifdef CONFIG_USART_BREAKS + case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ + { + irqstate_t flags = irqsave(); + uint32_t cr2 = up_serialin(priv, STM32_USART_CR2_OFFSET); + up_serialout(priv, STM32_USART_CR2_OFFSET, cr2 | USART_CR2_LINEN); + irqrestore(flags); + } + break; + + case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ + { + irqstate_t flags; + flags = irqsave(); + uint32_t cr1 = up_serialin(priv, STM32_USART_CR2_OFFSET); + up_serialout(priv, STM32_USART_CR2_OFFSET, cr2 & ~USART_CR2_LINEN); + irqrestore(flags); + } + break; +#endif + + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Name: up_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the USART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +#ifndef SERIAL_HAVE_ONLY_DMA +static int up_receive(struct uart_dev_s *dev, uint32_t *status) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + uint32_t dr; + + /* Get the Rx byte */ + + dr = up_serialin(priv, STM32_USART_DR_OFFSET); + + /* Get the Rx byte plux error information. Return those in status */ + + *status = priv->sr << 16 | dr; + priv->sr = 0; + + /* Then return the actual received byte */ + + return dr & 0xff; +} +#endif + +/**************************************************************************** + * Name: up_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +#ifndef SERIAL_HAVE_ONLY_DMA +static void up_rxint(struct uart_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + irqstate_t flags; + uint16_t ie; + + /* USART receive interrupts: + * + * Enable Bit Status Meaning Usage + * ------------------ --- --------------- ------------------------------- ---------- + * USART_CR1_IDLEIE 4 USART_SR_IDLE Idle Line Detected (not used) + * USART_CR1_RXNEIE 5 USART_SR_RXNE Received Data Ready to be Read + * " " USART_SR_ORE Overrun Error Detected + * USART_CR1_PEIE 8 USART_SR_PE Parity Error + * + * USART_CR2_LBDIE 6 USART_SR_LBD Break Flag (not used) + * USART_CR3_EIE 0 USART_SR_FE Framing Error + * " " USART_SR_NE Noise Error + * " " USART_SR_ORE Overrun Error Detected + */ + + flags = irqsave(); + ie = priv->ie; + if (enable) + { + /* Receive an interrupt when their is anything in the Rx data register (or an Rx + * timeout occurs). + */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS +#ifdef CONFIG_USART_ERRINTS + ie |= (USART_CR1_RXNEIE|USART_CR1_PEIE|USART_CR3_EIE); +#else + ie |= USART_CR1_RXNEIE; +#endif +#endif + } + else + { + ie &= ~(USART_CR1_RXNEIE|USART_CR1_PEIE|USART_CR3_EIE); + } + + /* Then set the new interrupt state */ + + up_restoreusartint(priv, ie); + irqrestore(flags); +} +#endif + +/**************************************************************************** + * Name: up_rxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +#ifndef SERIAL_HAVE_ONLY_DMA +static bool up_rxavailable(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + return ((up_serialin(priv, STM32_USART_SR_OFFSET) & USART_SR_RXNE) != 0); +} +#endif + +/**************************************************************************** + * Name: up_dma_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the USART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static int up_dma_receive(struct uart_dev_s *dev, uint32_t *status) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + int c = 0; + + if (up_dma_nextrx(priv) != priv->rxdmanext) + { + c = priv->rxfifo[priv->rxdmanext]; + + priv->rxdmanext++; + if (priv->rxdmanext == RXDMA_BUFFER_SIZE) + { + priv->rxdmanext = 0; + } + } + + return c; +} +#endif + +/**************************************************************************** + * Name: up_dma_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static void up_dma_rxint(struct uart_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + + /* En/disable DMA reception. + * + * Note that it is not safe to check for available bytes and immediately + * pass them to uart_recvchars as that could potentially recurse back + * to us again. Instead, bytes must wait until the next up_dma_poll or + * DMA event. + */ + + priv->rxenable = enable; +} +#endif + +/**************************************************************************** + * Name: up_dma_rxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static bool up_dma_rxavailable(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + + /* Compare our receive pointer to the current DMA pointer, if they + * do not match, then there are bytes to be received. + */ + + return (up_dma_nextrx(priv) != priv->rxdmanext); +} +#endif + +/**************************************************************************** + * Name: up_send + * + * Description: + * This method will send one byte on the USART + * + ****************************************************************************/ + +static void up_send(struct uart_dev_s *dev, int ch) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + up_serialout(priv, STM32_USART_DR_OFFSET, (uint32_t)ch); +} + +/**************************************************************************** + * Name: up_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void up_txint(struct uart_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + irqstate_t flags; + + /* USART transmit interrupts: + * + * Enable Bit Status Meaning Usage + * ------------------ --- --------------- ---------------------------- ---------- + * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (not used) + * USART_CR1_TXEIE 7 USART_SR_TXE Transmit Data Register Empty + * USART_CR3_CTSIE 10 USART_SR_CTS CTS flag (not used) + */ + + flags = irqsave(); + if (enable) + { + /* Set to receive an interrupt when the TX data register is empty */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + up_restoreusartint(priv, priv->ie | USART_CR1_TXEIE); + + /* Fake a TX interrupt here by just calling uart_xmitchars() with + * interrupts disabled (note this may recurse). + */ + + uart_xmitchars(dev); +#endif + } + else + { + /* Disable the TX interrupt */ + + up_restoreusartint(priv, priv->ie & ~USART_CR1_TXEIE); + } + irqrestore(flags); +} + +/**************************************************************************** + * Name: up_txready + * + * Description: + * Return true if the tranmsit data register is empty + * + ****************************************************************************/ + +static bool up_txready(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + return ((up_serialin(priv, STM32_USART_SR_OFFSET) & USART_SR_TXE) != 0); +} + +/**************************************************************************** + * Name: up_interrupt_u[s]art[n] + * + * Description: + * Interrupt handlers for U[S]ART[n] where n=1,..,6. + * + ****************************************************************************/ + +#ifdef CONFIG_STM32_USART1 +static int up_interrupt_usart1(int irq, void *context) +{ + return up_interrupt_common(&g_usart1priv); +} +#endif + +#ifdef CONFIG_STM32_USART2 +static int up_interrupt_usart2(int irq, void *context) +{ + return up_interrupt_common(&g_usart2priv); +} +#endif + +#ifdef CONFIG_STM32_USART3 +static int up_interrupt_usart3(int irq, void *context) +{ + return up_interrupt_common(&g_usart3priv); +} +#endif + +#ifdef CONFIG_STM32_UART4 +static int up_interrupt_uart4(int irq, void *context) +{ + return up_interrupt_common(&g_uart4priv); +} +#endif + +#ifdef CONFIG_STM32_UART5 +static int up_interrupt_uart5(int irq, void *context) +{ + return up_interrupt_common(&g_uart5priv); +} +#endif + +#ifdef CONFIG_STM32_USART6 +static int up_interrupt_usart6(int irq, void *context) +{ + return up_interrupt_common(&g_usart6priv); +} +#endif + +/**************************************************************************** + * Name: up_dma_rxcallback + * + * Description: + * This function checks the current DMA state and calls the generic + * serial stack when bytes appear to be available. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, void *arg) +{ + struct up_dev_s *priv = (struct up_dev_s*)arg; + + if (priv->rxenable && up_dma_rxavailable(&priv->dev)) + { + uart_recvchars(&priv->dev); + } +} +#endif + +#endif /* HAVE UART */ + +/**************************************************************************** + * Name: up_pm_notify + * + * Description: + * Notify the driver of new power state. This callback is called after + * all drivers have had the opportunity to prepare for the new power state. + * + * Input Parameters: + * + * cb - Returned to the driver. The driver version of the callback + * strucure may include additional, driver-specific state data at + * the end of the structure. + * + * pmstate - Identifies the new PM state + * + * Returned Value: + * None - The driver already agreed to transition to the low power + * consumption state when when it returned OK to the prepare() call. + * + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static void up_pm_notify(struct pm_callback_s *cb, enum pm_state_e pmstate) +{ + switch (pmstate) + { + case(PM_NORMAL): + { + /* Logic for PM_NORMAL goes here */ + + } + break; + + case(PM_IDLE): + { + /* Logic for PM_IDLE goes here */ + + } + break; + + case(PM_STANDBY): + { + /* Logic for PM_STANDBY goes here */ + + } + break; + + case(PM_SLEEP): + { + /* Logic for PM_SLEEP goes here */ + + } + break; + + default: + /* Should not get here */ + break; + } +} +#endif + +/**************************************************************************** + * Name: up_pm_prepare + * + * Description: + * Request the driver to prepare for a new power state. This is a warning + * that the system is about to enter into a new power state. The driver + * should begin whatever operations that may be required to enter power + * state. The driver may abort the state change mode by returning a + * non-zero value from the callback function. + * + * Input Parameters: + * + * cb - Returned to the driver. The driver version of the callback + * strucure may include additional, driver-specific state data at + * the end of the structure. + * + * pmstate - Identifies the new PM state + * + * Returned Value: + * Zero - (OK) means the event was successfully processed and that the + * driver is prepared for the PM state change. + * + * Non-zero - means that the driver is not prepared to perform the tasks + * needed achieve this power setting and will cause the state + * change to be aborted. NOTE: The prepare() method will also + * be called when reverting from lower back to higher power + * consumption modes (say because another driver refused a + * lower power state change). Drivers are not permitted to + * return non-zero values when reverting back to higher power + * consumption modes! + * + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static int up_pm_prepare(struct pm_callback_s *cb, enum pm_state_e pmstate) +{ + /* Logic to prepare for a reduced power state goes here. */ + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_earlyserialinit + * + * Description: + * Performs the low level USART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before up_serialinit. + * + ****************************************************************************/ + +void up_earlyserialinit(void) +{ +#ifdef HAVE_UART + unsigned i; + + /* Disable all USART interrupts */ + + for (i = 0; i < STM32_NUSART; i++) + { + if (uart_devs[i]) + { + up_disableusartint(uart_devs[i], NULL); + } + } + + /* Configure whichever one is the console */ + +#if CONSOLE_UART > 0 + up_setup(&uart_devs[CONSOLE_UART - 1]->dev); +#endif +#endif /* HAVE UART */ +} + +/**************************************************************************** + * Name: up_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that up_earlyserialinit was called previously. + * + ****************************************************************************/ + +void up_serialinit(void) +{ +#ifdef HAVE_UART + char devname[16]; + unsigned i, j; +#ifdef CONFIG_PM + int ret; +#endif + + /* Register to receive power management callbacks */ + +#ifdef CONFIG_PM + ret = pm_register(&g_serialcb); + DEBUGASSERT(ret == OK); +#endif + + /* Register the console */ + +#if CONSOLE_UART > 0 + (void)uart_register("/dev/console", &uart_devs[CONSOLE_UART - 1]->dev); + (void)uart_register("/dev/ttyS0", &uart_devs[CONSOLE_UART - 1]->dev); +#endif + + /* Register all remaining USARTs */ + + strcpy(devname, "/dev/ttySx"); + + for (i = 0, j = 1; i < STM32_NUSART; i++) + { + + /* don't create a device for the console - we did that above */ + + if ((uart_devs[i] == 0) || (uart_devs[i]->dev.isconsole)) + { + continue; + } + + /* register USARTs as devices in increasing order */ + + devname[9] = '0' + j++; + (void)uart_register(devname, &uart_devs[i]->dev); + } +#endif /* HAVE UART */ +} + +/**************************************************************************** + * Name: stm32_serial_dma_poll + * + * Description: + * Checks receive DMA buffers for received bytes that have not accumulated + * to the point where the DMA half/full interrupt has triggered. + * + * This function should be called from a timer or other periodic context. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +void stm32_serial_dma_poll(void) +{ + irqstate_t flags; + + flags = irqsave(); + +#ifdef CONFIG_USART1_RXDMA + if (g_usart1priv.rxdma != NULL) + { + up_dma_rxcallback(g_usart1priv.rxdma, 0, &g_usart1priv); + } +#endif + +#ifdef CONFIG_USART2_RXDMA + if (g_usart2priv.rxdma != NULL) + { + up_dma_rxcallback(g_usart2priv.rxdma, 0, &g_usart2priv); + } +#endif + +#ifdef CONFIG_USART3_RXDMA + if (g_usart3priv.rxdma != NULL) + { + up_dma_rxcallback(g_usart3priv.rxdma, 0, &g_usart3priv); + } +#endif + +#ifdef CONFIG_USART4_RXDMA + if (g_uart4priv.rxdma != NULL) + { + up_dma_rxcallback(g_uart4priv.rxdma, 0, &g_uart4priv); + } +#endif + +#ifdef CONFIG_USART5_RXDMA + if (g_uart5priv.rxdma != NULL) + { + up_dma_rxcallback(g_uart5priv.rxdma, 0, &g_uart5priv); + } +#endif + +#ifdef CONFIG_USART6_RXDMA + if (g_usart6priv.rxdma != NULL) + { + up_dma_rxcallback(g_usart6priv.rxdma, 0, &g_usart6priv); + } +#endif + + irqrestore(flags); +} +#endif + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#if CONSOLE_UART > 0 + struct up_dev_s *priv = uart_devs[CONSOLE_UART - 1]; + uint16_t ie; + + up_disableusartint(priv, &ie); + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc(ch); + up_restoreusartint(priv, ie); +#endif + return ch; +} + +#else /* USE_SERIALDRIVER */ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#if CONSOLE_UART > 0 + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc(ch); +#endif + return ch; +} + +#endif /* USE_SERIALDRIVER */ diff --git a/nuttx/arch/arm/src/stm32/stm32_spi.c b/nuttx/arch/arm/src/stm32/stm32_spi.c new file mode 100644 index 0000000000..7fdd988cbb --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_spi.c @@ -0,0 +1,1396 @@ +/************************************************************************************ + * arm/arm/src/stm32/stm32_spi.c + * + * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * The external functions, stm32_spi1/2/3select and stm32_spi1/2/3status must be + * provided by board-specific logic. They are implementations of the select + * and status methods of the SPI interface defined by struct spi_ops_s (see + * include/nuttx/spi.h). All other methods (including up_spiinitialize()) + * are provided by common STM32 logic. To use this common SPI logic on your + * board: + * + * 1. Provide logic in stm32_boardinitialize() to configure SPI chip select + * pins. + * 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your + * board-specific logic. These functions will perform chip selection and + * status operations using GPIOs in the way your board is configured. + * 3. Add a calls to up_spiinitialize() in your low level application + * initialization logic + * 4. The handle returned by up_spiinitialize() may then be used to bind the + * SPI driver to higher level logic (e.g., calling + * mmcsd_spislotinitialize(), for example, will bind the SPI driver to + * the SPI MMC/SD driver). + * + ****************************************************c********************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "up_internal.h" +#include "up_arch.h" + +#include "chip.h" +#include "stm32_internal.h" +#include "stm32_gpio.h" +#include "stm32_dma.h" +#include "stm32_spi.h" + +#if defined(CONFIG_STM32_SPI1) || defined(CONFIG_STM32_SPI2) || defined(CONFIG_STM32_SPI3) + +/************************************************************************************ + * Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ + +#ifdef CONFIG_STM32_SPI_INTERRUPTS +# error "Interrupt driven SPI not yet supported" +#endif + +#if defined(CONFIG_STM32_SPI_INTERRUPTS) && defined(CONFIG_STM32_SPI_DMA) +# error "Cannot enable both interrupt mode and DMA mode for SPI" +#endif + +/* DMA channel configuration */ + +#define SPI_DMA_PRIO DMA_CCR_PRIMED /* Check this to alter priority */ + +#define SPI_RXDMA16_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_16BITS|DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC ) +#define SPI_RXDMA8_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS |DMA_CCR_MINC ) +#define SPI_RXDMA16NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_16BITS ) +#define SPI_RXDMA8NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS ) +#define SPI_TXDMA16_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_16BITS|DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC|DMA_CCR_DIR) +#define SPI_TXDMA8_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS |DMA_CCR_MINC|DMA_CCR_DIR) +#define SPI_TXDMA16NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_16BITS |DMA_CCR_DIR) +#define SPI_TXDMA8NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS |DMA_CCR_DIR) + +/* Debug ****************************************************************************/ +/* Check if (non-standard) SPI debug is enabled */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_SPI +#endif + +#ifdef CONFIG_DEBUG_SPI +# define spidbg lldbg +# ifdef CONFIG_DEBUG_VERBOSE +# define spivdbg lldbg +# else +# define spivdbg(x...) +# endif +#else +# define spidbg(x...) +# define spivdbg(x...) +#endif + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +struct stm32_spidev_s +{ + struct spi_dev_s spidev; /* Externally visible part of the SPI interface */ + uint32_t spibase; /* SPIn base address */ + uint32_t spiclock; /* Clocking for the SPI module */ +#ifdef CONFIG_STM32_SPI_INTERRUPTS + uint8_t spiirq; /* SPI IRQ number */ +#endif +#ifdef CONFIG_STM32_SPI_DMA + volatile uint8_t rxresult; /* Result of the RX DMA */ + volatile uint8_t txresult; /* Result of the RX DMA */ + uint8_t rxch; /* The RX DMA channel number */ + uint8_t txch; /* The TX DMA channel number */ + DMA_HANDLE rxdma; /* DMA channel handle for RX transfers */ + DMA_HANDLE txdma; /* DMA channel handle for TX transfers */ + sem_t rxsem; /* Wait for RX DMA to complete */ + sem_t txsem; /* Wait for TX DMA to complete */ +#endif +#ifndef CONFIG_SPI_OWNBUS + sem_t exclsem; /* Held while chip is selected for mutual exclusion */ + uint32_t frequency; /* Requested clock frequency */ + uint32_t actual; /* Actual clock frequency */ + uint8_t nbits; /* Width of word in bits (8 or 16) */ + uint8_t mode; /* Mode 0,1,2,3 */ +#endif +}; + +/************************************************************************************ + * Private Function Prototypes + ************************************************************************************/ + +/* Helpers */ + +static inline uint16_t spi_getreg(FAR struct stm32_spidev_s *priv, uint8_t offset); +static inline void spi_putreg(FAR struct stm32_spidev_s *priv, uint8_t offset, + uint16_t value); +static inline uint16_t spi_readword(FAR struct stm32_spidev_s *priv); +static inline void spi_writeword(FAR struct stm32_spidev_s *priv, uint16_t byte); +static inline bool spi_16bitmode(FAR struct stm32_spidev_s *priv); + +/* DMA support */ + +#ifdef CONFIG_STM32_SPI_DMA +static void spi_dmarxwait(FAR struct stm32_spidev_s *priv); +static void spi_dmatxwait(FAR struct stm32_spidev_s *priv); +static inline void spi_dmarxwakeup(FAR struct stm32_spidev_s *priv); +static inline void spi_dmatxwakeup(FAR struct stm32_spidev_s *priv); +static void spi_dmarxcallback(DMA_HANDLE handle, uint8_t isr, void *arg); +static void spi_dmatxcallback(DMA_HANDLE handle, uint8_t isr, void *arg); +static void spi_dmarxsetup(FAR struct stm32_spidev_s *priv, + FAR void *rxbuffer, FAR void *rxdummy, size_t nwords); +static void spi_dmatxsetup(FAR struct stm32_spidev_s *priv, + FAR const void *txbuffer, FAR const void *txdummy, size_t nwords); +static inline void spi_dmarxstart(FAR struct stm32_spidev_s *priv); +static inline void spi_dmatxstart(FAR struct stm32_spidev_s *priv); +#endif + +/* SPI methods */ + +#ifndef CONFIG_SPI_OWNBUS +static int spi_lock(FAR struct spi_dev_s *dev, bool lock); +#endif +static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); +static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); +static void spi_setbits(FAR struct spi_dev_s *dev, int nbits); +static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd); +static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, + FAR void *rxbuffer, size_t nwords); +#ifndef CONFIG_SPI_EXCHANGE +static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *txbuffer, + size_t nwords); +static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer, + size_t nwords); +#endif + +/* Initialization */ + +static void spi_portinitialize(FAR struct stm32_spidev_s *priv); + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +#ifdef CONFIG_STM32_SPI1 +static const struct spi_ops_s g_sp1iops = +{ +#ifndef CONFIG_SPI_OWNBUS + .lock = spi_lock, +#endif + .select = stm32_spi1select, + .setfrequency = spi_setfrequency, + .setmode = spi_setmode, + .setbits = spi_setbits, + .status = stm32_spi1status, +#ifdef CONFIG_SPI_CMDDATA + .cmddata = stm32_spi1cmddata, +#endif + .send = spi_send, +#ifdef CONFIG_SPI_EXCHANGE + .exchange = spi_exchange, +#else + .sndblock = spi_sndblock, + .recvblock = spi_recvblock, +#endif + .registercallback = 0, +}; + +static struct stm32_spidev_s g_spi1dev = +{ + .spidev = { &g_sp1iops }, + .spibase = STM32_SPI1_BASE, + .spiclock = STM32_PCLK2_FREQUENCY, +#ifdef CONFIG_STM32_SPI_INTERRUPTS + .spiirq = STM32_IRQ_SPI1, +#endif +#ifdef CONFIG_STM32_SPI_DMA + .rxch = DMACHAN_SPI1_RX, + .txch = DMACHAN_SPI1_TX, +#endif +}; +#endif + +#ifdef CONFIG_STM32_SPI2 +static const struct spi_ops_s g_sp2iops = +{ +#ifndef CONFIG_SPI_OWNBUS + .lock = spi_lock, +#endif + .select = stm32_spi2select, + .setfrequency = spi_setfrequency, + .setmode = spi_setmode, + .setbits = spi_setbits, + .status = stm32_spi2status, +#ifdef CONFIG_SPI_CMDDATA + .cmddata = stm32_spi2cmddata, +#endif + .send = spi_send, +#ifdef CONFIG_SPI_EXCHANGE + .exchange = spi_exchange, +#else + .sndblock = spi_sndblock, + .recvblock = spi_recvblock, +#endif + .registercallback = 0, +}; + +static struct stm32_spidev_s g_spi2dev = +{ + .spidev = { &g_sp2iops }, + .spibase = STM32_SPI2_BASE, + .spiclock = STM32_PCLK1_FREQUENCY, +#ifdef CONFIG_STM32_SPI_INTERRUPTS + .spiirq = STM32_IRQ_SPI2, +#endif +#ifdef CONFIG_STM32_SPI_DMA + .rxch = DMACHAN_SPI2_RX, + .txch = DMACHAN_SPI2_TX, +#endif +}; +#endif + +#ifdef CONFIG_STM32_SPI3 +static const struct spi_ops_s g_sp3iops = +{ +#ifndef CONFIG_SPI_OWNBUS + .lock = spi_lock, +#endif + .select = stm32_spi3select, + .setfrequency = spi_setfrequency, + .setmode = spi_setmode, + .setbits = spi_setbits, + .status = stm32_spi3status, +#ifdef CONFIG_SPI_CMDDATA + .cmddata = stm32_spi3cmddata, +#endif + .send = spi_send, +#ifdef CONFIG_SPI_EXCHANGE + .exchange = spi_exchange, +#else + .sndblock = spi_sndblock, + .recvblock = spi_recvblock, +#endif + .registercallback = 0, +}; + +static struct stm32_spidev_s g_spi3dev = +{ + .spidev = { &g_sp3iops }, + .spibase = STM32_SPI3_BASE, + .spiclock = STM32_PCLK1_FREQUENCY, +#ifdef CONFIG_STM32_SPI_INTERRUPTS + .spiirq = STM32_IRQ_SPI3, +#endif +#ifdef CONFIG_STM32_SPI_DMA + .rxch = DMACHAN_SPI3_RX, + .txch = DMACHAN_SPI3_TX, +#endif +}; +#endif + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: spi_getreg + * + * Description: + * Get the contents of the SPI register at offset + * + * Input Parameters: + * priv - private SPI device structure + * offset - offset to the register of interest + * + * Returned Value: + * The contents of the 16-bit register + * + ************************************************************************************/ + +static inline uint16_t spi_getreg(FAR struct stm32_spidev_s *priv, uint8_t offset) +{ + return getreg16(priv->spibase + offset); +} + +/************************************************************************************ + * Name: spi_putreg + * + * Description: + * Write a 16-bit value to the SPI register at offset + * + * Input Parameters: + * priv - private SPI device structure + * offset - offset to the register of interest + * value - the 16-bit value to be written + * + * Returned Value: + * The contents of the 16-bit register + * + ************************************************************************************/ + +static inline void spi_putreg(FAR struct stm32_spidev_s *priv, uint8_t offset, uint16_t value) +{ + putreg16(value, priv->spibase + offset); +} + +/************************************************************************************ + * Name: spi_readword + * + * Description: + * Read one byte from SPI + * + * Input Parameters: + * priv - Device-specific state data + * + * Returned Value: + * Byte as read + * + ************************************************************************************/ + +static inline uint16_t spi_readword(FAR struct stm32_spidev_s *priv) +{ + /* Wait until the receive buffer is not empty */ + + while ((spi_getreg(priv, STM32_SPI_SR_OFFSET) & SPI_SR_RXNE) == 0); + + /* Then return the received byte */ + + return spi_getreg(priv, STM32_SPI_DR_OFFSET); +} + +/************************************************************************************ + * Name: spi_writeword + * + * Description: + * Write one byte to SPI + * + * Input Parameters: + * priv - Device-specific state data + * byte - Byte to send + * + * Returned Value: + * None + * + ************************************************************************************/ + +static inline void spi_writeword(FAR struct stm32_spidev_s *priv, uint16_t word) +{ + /* Wait until the transmit buffer is empty */ + + while ((spi_getreg(priv, STM32_SPI_SR_OFFSET) & SPI_SR_TXE) == 0); + + /* Then send the byte */ + + spi_putreg(priv, STM32_SPI_DR_OFFSET, word); +} + +/************************************************************************************ + * Name: spi_16bitmode + * + * Description: + * Check if the SPI is operating in 16-bit mode + * + * Input Parameters: + * priv - Device-specific state data + * + * Returned Value: + * true: 16-bit mode, false: 8-bit mode + * + ************************************************************************************/ + +static inline bool spi_16bitmode(FAR struct stm32_spidev_s *priv) +{ + return ((spi_getreg(priv, STM32_SPI_CR1_OFFSET) & SPI_CR1_DFF) != 0); +} + +/************************************************************************************ + * Name: spi_dmarxwait + * + * Description: + * Wait for DMA to complete. + * + ************************************************************************************/ + +#ifdef CONFIG_STM32_SPI_DMA +static void spi_dmarxwait(FAR struct stm32_spidev_s *priv) +{ + /* Take the semaphore (perhaps waiting). If the result is zero, then the DMA + * must not really have completed??? + */ + + while (sem_wait(&priv->rxsem) != 0 && priv->rxresult == 0) + { + /* The only case that an error should occur here is if the wait was awakened + * by a signal. + */ + + ASSERT(errno == EINTR); + } +} +#endif + +/************************************************************************************ + * Name: spi_dmatxwait + * + * Description: + * Wait for DMA to complete. + * + ************************************************************************************/ + +#ifdef CONFIG_STM32_SPI_DMA +static void spi_dmatxwait(FAR struct stm32_spidev_s *priv) +{ + /* Take the semaphore (perhaps waiting). If the result is zero, then the DMA + * must not really have completed??? + */ + + while (sem_wait(&priv->txsem) != 0 && priv->txresult == 0) + { + /* The only case that an error should occur here is if the wait was awakened + * by a signal. + */ + + ASSERT(errno == EINTR); + } +} +#endif + +/************************************************************************************ + * Name: spi_dmarxwakeup + * + * Description: + * Signal that DMA is complete + * + ************************************************************************************/ + +#ifdef CONFIG_STM32_SPI_DMA +static inline void spi_dmarxwakeup(FAR struct stm32_spidev_s *priv) +{ + (void)sem_post(&priv->rxsem); +} +#endif + +/************************************************************************************ + * Name: spi_dmarxcallback + * + * Description: + * Called when the RX DMA completes + * + ************************************************************************************/ + +#ifdef CONFIG_STM32_SPI_DMA +static void spi_dmarxcallback(DMA_HANDLE handle, uint8_t isr, void *arg) +{ + FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)arg; + + /* Wake-up the SPI driver */ + + priv->rxresult = isr | 0x080; /* OR'ed with 0x80 to assure non-zero */ + spi_dmarxwakeup(priv); +} +#endif + +/************************************************************************************ + * Name: spi_dmatxcallback + * + * Description: + * Called when the RX DMA completes + * + ************************************************************************************/ + +#ifdef CONFIG_STM32_SPI_DMA +static void spi_dmatxcallback(DMA_HANDLE handle, uint8_t isr, void *arg) +{ + FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)arg; + + /* Wake-up the SPI driver */ + + priv->txresult = isr | 0x080; /* OR'ed with 0x80 to assure non-zero */ + spi_dmatxwakeup(priv); +} +#endif + +/************************************************************************************ + * Name: spi_dmarxsetup + * + * Description: + * Setup to perform RX DMA + * + ************************************************************************************/ + +#ifdef CONFIG_STM32_SPI_DMA +static void spi_dmarxsetup(FAR struct stm32_spidev_s *priv, FAR void *rxbuffer, + FAR void *rxdummy, size_t nwords) +{ + uint32_t ccr; + + /* 8- or 16-bit mode? */ + + if (spi_16bitmode(priv)) + { + /* 16-bit mode -- is there a buffer to receive data in? */ + + if (rxbuffer) + { + ccr = SPI_RXDMA16_CONFIG; + } + else + { + rxbuffer = rxdummy; + ccr = SPI_RXDMA16NULL_CONFIG; + } + } + else + { + /* 8-bit mode -- is there a buffer to receive data in? */ + + if (rxbuffer) + { + ccr = SPI_RXDMA8_CONFIG; + } + else + { + rxbuffer = rxdummy; + ccr = SPI_RXDMA8NULL_CONFIG; + } + } + + /* Configure the RX DMA */ + + stm32_dmasetup(priv->rxdma, priv->spibase + STM32_SPI_DR_OFFSET, (uint32_t)rxbuffer, nwords, ccr); +} +#endif + +/************************************************************************************ + * Name: spi_dmatxsetup + * + * Description: + * Setup to perform TX DMA + * + ************************************************************************************/ + +#ifdef CONFIG_STM32_SPI_DMA +static void spi_dmatxsetup(FAR struct stm32_spidev_s *priv, FAR const void *txbuffer, + FAR const void *txdummy, size_t nwords) +{ + uint32_t ccr; + + /* 8- or 16-bit mode? */ + + if (spi_16bitmode(priv)) + { + /* 16-bit mode -- is there a buffer to transfer data from? */ + + if (txbuffer) + { + ccr = SPI_TXDMA16_CONFIG; + } + else + { + txbuffer = txdummy; + ccr = SPI_TXDMA16NULL_CONFIG; + } + } + else + { + /* 8-bit mode -- is there a buffer to transfer data from? */ + + if (txbuffer) + { + ccr = SPI_TXDMA8_CONFIG; + } + else + { + txbuffer = txdummy; + ccr = SPI_TXDMA8NULL_CONFIG; + } + } + + /* Setup the TX DMA */ + + stm32_dmasetup(priv->txdma, priv->spibase + STM32_SPI_DR_OFFSET,(uint32_t)txbuffer, nwords, ccr); +} +#endif + +/************************************************************************************ + * Name: spi_dmarxstart + * + * Description: + * Start RX DMA + * + ************************************************************************************/ + +#ifdef CONFIG_STM32_SPI_DMA +static inline void spi_dmarxstart(FAR struct stm32_spidev_s *priv) +{ + stm32_dmastart(priv->rxdma, spi_dmarxcallback, priv, false); +} +#endif + +/************************************************************************************ + * Name: spi_dmatxstart + * + * Description: + * Start TX DMA + * + ************************************************************************************/ + +#ifdef CONFIG_STM32_SPI_DMA +static inline void spi_dmatxstart(FAR struct stm32_spidev_s *priv) +{ + stm32_dmastart(priv->txdma, spi_dmatxcallback, priv, false); +} +#endif + +/************************************************************************************ + * Name: spi_modifycr1 + * + * Description: + * Clear and set bits in the CR1 register + * + * Input Parameters: + * priv - Device-specific state data + * clrbits - The bits to clear + * setbits - The bits to set + * + * Returned Value: + * None + * + ************************************************************************************/ + +static void spi_modifycr1(FAR struct stm32_spidev_s *priv, uint16_t setbits, uint16_t clrbits) +{ + uint16_t cr1; + cr1 = spi_getreg(priv, STM32_SPI_CR1_OFFSET); + cr1 &= ~clrbits; + cr1 |= setbits; + spi_putreg(priv, STM32_SPI_CR1_OFFSET, cr1); +} + +/**************************************************************************** + * Name: spi_lock + * + * Description: + * On SPI busses where there are multiple devices, it will be necessary to + * lock SPI to have exclusive access to the busses for a sequence of + * transfers. The bus should be locked before the chip is selected. After + * locking the SPI bus, the caller should then also call the setfrequency, + * setbits, and setmode methods to make sure that the SPI is properly + * configured for the device. If the SPI buss is being shared, then it + * may have been left in an incompatible state. + * + * Input Parameters: + * dev - Device-specific state data + * lock - true: Lock spi bus, false: unlock SPI bus + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifndef CONFIG_SPI_OWNBUS +static int spi_lock(FAR struct spi_dev_s *dev, bool lock) +{ + FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; + + if (lock) + { + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&priv->exclsem) != 0) + { + /* The only case that an error should occur here is if the wait was awakened + * by a signal. + */ + + ASSERT(errno == EINTR); + } + } + else + { + (void)sem_post(&priv->exclsem); + } + return OK; +} +#endif + +/************************************************************************************ + * Name: spi_setfrequency + * + * Description: + * Set the SPI frequency. + * + * Input Parameters: + * dev - Device-specific state data + * frequency - The SPI frequency requested + * + * Returned Value: + * Returns the actual frequency selected + * + ************************************************************************************/ + +static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) +{ + FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; + uint16_t setbits; + uint32_t actual; + + /* Limit to max possible (if STM32_SPI_CLK_MAX is defined in board.h) */ + + if (frequency > STM32_SPI_CLK_MAX) + { + frequency = STM32_SPI_CLK_MAX; + } + + /* Has the frequency changed? */ + +#ifndef CONFIG_SPI_OWNBUS + if (frequency != priv->frequency) + { +#endif + /* Choices are limited by PCLK frequency with a set of divisors */ + + if (frequency >= priv->spiclock >> 1) + { + /* More than fPCLK/2. This is as fast as we can go */ + + setbits = SPI_CR1_FPCLCKd2; /* 000: fPCLK/2 */ + actual = priv->spiclock >> 1; + } + else if (frequency >= priv->spiclock >> 2) + { + /* Between fPCLCK/2 and fPCLCK/4, pick the slower */ + + setbits = SPI_CR1_FPCLCKd4; /* 001: fPCLK/4 */ + actual = priv->spiclock >> 2; + } + else if (frequency >= priv->spiclock >> 3) + { + /* Between fPCLCK/4 and fPCLCK/8, pick the slower */ + + setbits = SPI_CR1_FPCLCKd8; /* 010: fPCLK/8 */ + actual = priv->spiclock >> 3; + } + else if (frequency >= priv->spiclock >> 4) + { + /* Between fPCLCK/8 and fPCLCK/16, pick the slower */ + + setbits = SPI_CR1_FPCLCKd16; /* 011: fPCLK/16 */ + actual = priv->spiclock >> 4; + } + else if (frequency >= priv->spiclock >> 5) + { + /* Between fPCLCK/16 and fPCLCK/32, pick the slower */ + + setbits = SPI_CR1_FPCLCKd32; /* 100: fPCLK/32 */ + actual = priv->spiclock >> 5; + } + else if (frequency >= priv->spiclock >> 6) + { + /* Between fPCLCK/32 and fPCLCK/64, pick the slower */ + + setbits = SPI_CR1_FPCLCKd64; /* 101: fPCLK/64 */ + actual = priv->spiclock >> 6; + } + else if (frequency >= priv->spiclock >> 7) + { + /* Between fPCLCK/64 and fPCLCK/128, pick the slower */ + + setbits = SPI_CR1_FPCLCKd128; /* 110: fPCLK/128 */ + actual = priv->spiclock >> 7; + } + else + { + /* Less than fPCLK/128. This is as slow as we can go */ + + setbits = SPI_CR1_FPCLCKd256; /* 111: fPCLK/256 */ + actual = priv->spiclock >> 8; + } + + spi_modifycr1(priv, setbits, SPI_CR1_BR_MASK); + + /* Save the frequency selection so that subsequent reconfigurations will be + * faster. + */ + + spivdbg("Frequency %d->%d\n", frequency, actual); + +#ifndef CONFIG_SPI_OWNBUS + priv->frequency = frequency; + priv->actual = actual; + } + return priv->actual; +#else + return actual; +#endif +} + +/************************************************************************************ + * Name: spi_setmode + * + * Description: + * Set the SPI mode. see enum spi_mode_e for mode definitions + * + * Input Parameters: + * dev - Device-specific state data + * mode - The SPI mode requested + * + * Returned Value: + * Returns the actual frequency selected + * + ************************************************************************************/ + +static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) +{ + FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; + uint16_t setbits; + uint16_t clrbits; + + spivdbg("mode=%d\n", mode); + + /* Has the mode changed? */ + +#ifndef CONFIG_SPI_OWNBUS + if (mode != priv->mode) + { +#endif + /* Yes... Set CR1 appropriately */ + + switch (mode) + { + case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */ + setbits = 0; + clrbits = SPI_CR1_CPOL|SPI_CR1_CPHA; + break; + + case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */ + setbits = SPI_CR1_CPHA; + clrbits = SPI_CR1_CPOL; + break; + + case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */ + setbits = SPI_CR1_CPOL; + clrbits = SPI_CR1_CPHA; + break; + + case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */ + setbits = SPI_CR1_CPOL|SPI_CR1_CPHA; + clrbits = 0; + break; + + default: + return; + } + + spi_modifycr1(priv, setbits, clrbits); + + /* Save the mode so that subsequent re-configurations will be faster */ + +#ifndef CONFIG_SPI_OWNBUS + priv->mode = mode; + } +#endif +} + +/************************************************************************************ + * Name: spi_setbits + * + * Description: + * Set the number of bits per word. + * + * Input Parameters: + * dev - Device-specific state data + * nbits - The number of bits requested + * + * Returned Value: + * None + * + ************************************************************************************/ + +static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) +{ + FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; + uint16_t setbits; + uint16_t clrbits; + + spivdbg("nbits=%d\n", nbits); + + /* Has the number of bits changed? */ + +#ifndef CONFIG_SPI_OWNBUS + if (nbits != priv->nbits) + { +#endif + /* Yes... Set CR1 appropriately */ + + switch (nbits) + { + case 8: + setbits = 0; + clrbits = SPI_CR1_DFF; + break; + + case 16: + setbits = SPI_CR1_DFF; + clrbits = 0; + break; + + default: + return; + } + + spi_modifycr1(priv, setbits, clrbits); + + /* Save the selection so the subsequence re-configurations will be faster */ + +#ifndef CONFIG_SPI_OWNBUS + priv->nbits = nbits; + } +#endif +} + +/************************************************************************************ + * Name: spi_send + * + * Description: + * Exchange one word on SPI + * + * Input Parameters: + * dev - Device-specific state data + * wd - The word to send. the size of the data is determined by the + * number of bits selected for the SPI interface. + * + * Returned Value: + * response + * + ************************************************************************************/ + +static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) +{ + FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; + uint16_t ret; + + DEBUGASSERT(priv && priv->spibase); + + spi_writeword(priv, wd); + ret = spi_readword(priv); + + spivdbg("Sent: %04x Return: %04x\n", wd, ret); + return ret; +} + +/************************************************************************* + * Name: spi_exchange (no DMA) + * + * Description: + * Exchange a block of data on SPI without using DMA + * + * Input Parameters: + * dev - Device-specific state data + * txbuffer - A pointer to the buffer of data to be sent + * rxbuffer - A pointer to a buffer in which to receive data + * nwords - the length of data to be exchaned in units of words. + * The wordsize is determined by the number of bits-per-word + * selected for the SPI interface. If nbits <= 8, the data is + * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifndef CONFIG_STM32_SPI_DMA +static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, + FAR void *rxbuffer, size_t nwords) +{ + FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; + DEBUGASSERT(priv && priv->spibase); + + spivdbg("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords); + + /* 8- or 16-bit mode? */ + + if (spi_16bitmode(priv)) + { + /* 16-bit mode */ + + const uint16_t *src = (const uint16_t*)txbuffer;; + uint16_t *dest = (uint16_t*)rxbuffer; + uint16_t word; + + while (nwords-- > 0) + { + /* Get the next word to write. Is there a source buffer? */ + + if (src) + { + word = *src++; + } + else + { + word = 0xffff; + } + + /* Exchange one word */ + + word = spi_send(dev, word); + + /* Is there a buffer to receive the return value? */ + + if (dest) + { + *dest++ = word; + } + } + } + else + { + /* 8-bit mode */ + + const uint8_t *src = (const uint8_t*)txbuffer;; + uint8_t *dest = (uint8_t*)rxbuffer; + uint8_t word; + + while (nwords-- > 0) + { + /* Get the next word to write. Is there a source buffer? */ + + if (src) + { + word = *src++; + } + else + { + word = 0xff; + } + + /* Exchange one word */ + + word = (uint8_t)spi_send(dev, (uint16_t)word); + + /* Is there a buffer to receive the return value? */ + + if (dest) + { + *dest++ = word; + } + } + } +} +#endif + +/************************************************************************* + * Name: spi_exchange (with DMA capability) + * + * Description: + * Exchange a block of data on SPI using DMA + * + * Input Parameters: + * dev - Device-specific state data + * txbuffer - A pointer to the buffer of data to be sent + * rxbuffer - A pointer to a buffer in which to receive data + * nwords - the length of data to be exchanged in units of words. + * The wordsize is determined by the number of bits-per-word + * selected for the SPI interface. If nbits <= 8, the data is + * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifdef CONFIG_STM32_SPI_DMA +static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, + FAR void *rxbuffer, size_t nwords) +{ + FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; + uint16_t rxdummy = 0xffff; + uint16_t txdummy; + + spivdbg("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords); + DEBUGASSERT(priv && priv->spibase); + + /* Setup DMAs */ + + spi_dmarxsetup(priv, rxbuffer, &rxdummy, nwords); + spi_dmatxsetup(priv, txbuffer, &txdummy, nwords); + + /* Start the DMAs */ + + spi_dmarxstart(priv); + spi_dmatxstart(priv); + + /* Then wait for each to complete */ + + spi_dmarxwait(priv); + spi_dmatxwait(priv); +} +#endif + +/************************************************************************* + * Name: spi_sndblock + * + * Description: + * Send a block of data on SPI + * + * Input Parameters: + * dev - Device-specific state data + * txbuffer - A pointer to the buffer of data to be sent + * nwords - the length of data to send from the buffer in number of words. + * The wordsize is determined by the number of bits-per-word + * selected for the SPI interface. If nbits <= 8, the data is + * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifndef CONFIG_SPI_EXCHANGE +static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *txbuffer, size_t nwords) +{ + spivdbg("txbuffer=%p nwords=%d\n", txbuffer, nwords); + return spi_exchange(dev, txbuffer, NULL, nwords); +} +#endif + +/************************************************************************************ + * Name: spi_recvblock + * + * Description: + * Receive a block of data from SPI + * + * Input Parameters: + * dev - Device-specific state data + * rxbuffer - A pointer to the buffer in which to recieve data + * nwords - the length of data that can be received in the buffer in number + * of words. The wordsize is determined by the number of bits-per-word + * selected for the SPI interface. If nbits <= 8, the data is + * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifndef CONFIG_SPI_EXCHANGE +static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer, size_t nwords) +{ + spivdbg("rxbuffer=%p nwords=%d\n", rxbuffer, nwords); + return spi_exchange(dev, NULL, rxbuffer, nwords); +} +#endif + +/************************************************************************************ + * Name: spi_portinitialize + * + * Description: + * Initialize the selected SPI port in its default state (Master, 8-bit, mode 0, etc.) + * + * Input Parameter: + * priv - private SPI device structure + * + * Returned Value: + * None + * + ************************************************************************************/ + +static void spi_portinitialize(FAR struct stm32_spidev_s *priv) +{ + uint16_t setbits; + uint16_t clrbits; + + /* Configure CR1. Default configuration: + * Mode 0: CPHA=0 and CPOL=0 + * Master: MSTR=1 + * 8-bit: DFF=0 + * MSB tranmitted first: LSBFIRST=0 + * Replace NSS with SSI & SSI=1: SSI=1 SSM=1 (prevents MODF error) + * Two lines full duplex: BIDIMODE=0 BIDIOIE=(Don't care) and RXONLY=0 + */ + + clrbits = SPI_CR1_CPHA|SPI_CR1_CPOL|SPI_CR1_BR_MASK|SPI_CR1_LSBFIRST| + SPI_CR1_RXONLY|SPI_CR1_DFF|SPI_CR1_BIDIOE|SPI_CR1_BIDIMODE; + setbits = SPI_CR1_MSTR|SPI_CR1_SSI|SPI_CR1_SSM; + spi_modifycr1(priv, setbits, clrbits); + +#ifndef CONFIG_SPI_OWNBUS + priv->frequency = 0; + priv->nbits = 8; + priv->mode = SPIDEV_MODE0; +#endif + + /* Select a default frequency of approx. 400KHz */ + + spi_setfrequency((FAR struct spi_dev_s *)priv, 400000); + + /* CRCPOLY configuration */ + + spi_putreg(priv, STM32_SPI_CRCPR_OFFSET, 7); + + /* Initialize the SPI semaphore that enforces mutually exclusive access */ + +#ifndef CONFIG_SPI_OWNBUS + sem_init(&priv->exclsem, 0, 1); +#endif + + /* Initialize the SPI semaphores that is used to wait for DMA completion */ + +#ifdef CONFIG_STM32_SPI_DMA + sem_init(&priv->rxsem, 0, 0); + sem_init(&priv->txsem, 0, 0); + + /* Get DMA channels. NOTE: stm32_dmachannel() will always assign the DMA channel. + * if the channel is not available, then stm32_dmachannel() will block and wait + * until the channel becomes available. WARNING: If you have another device sharing + * a DMA channel with SPI and the code never releases that channel, then the call + * to stm32_dmachannel() will hang forever in this function! Don't let your + * design do that! + */ + + priv->rxdma = stm32_dmachannel(priv->rxch); + priv->txdma = stm32_dmachannel(priv->txch); + DEBUGASSERT(priv->rxdma && priv->txdma); +#endif + + /* Enable spi */ + + spi_modifycr1(priv, SPI_CR1_SPE, 0); +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_spiinitialize + * + * Description: + * Initialize the selected SPI port + * + * Input Parameter: + * Port number (for hardware that has mutiple SPI interfaces) + * + * Returned Value: + * Valid SPI device structure reference on succcess; a NULL on failure + * + ************************************************************************************/ + +FAR struct spi_dev_s *up_spiinitialize(int port) +{ + FAR struct stm32_spidev_s *priv = NULL; + + irqstate_t flags = irqsave(); + +#ifdef CONFIG_STM32_SPI1 + if (port == 1) + { + /* Select SPI1 */ + + priv = &g_spi1dev; + + /* Configure SPI1 pins: SCK, MISO, and MOSI */ + + stm32_configgpio(GPIO_SPI1_SCK); + stm32_configgpio(GPIO_SPI1_MISO); + stm32_configgpio(GPIO_SPI1_MOSI); + + /* Set up default configuration: Master, 8-bit, etc. */ + + spi_portinitialize(priv); + } + else +#endif +#ifdef CONFIG_STM32_SPI2 + if (port == 2) + { + /* Select SPI2 */ + + priv = &g_spi2dev; + + /* Configure SPI2 pins: SCK, MISO, and MOSI */ + + stm32_configgpio(GPIO_SPI2_SCK); + stm32_configgpio(GPIO_SPI2_MISO); + stm32_configgpio(GPIO_SPI2_MOSI); + + /* Set up default configuration: Master, 8-bit, etc. */ + + spi_portinitialize(priv); + } + else +#endif +#ifdef CONFIG_STM32_SPI3 + if (port == 3) + { + /* Select SPI3 */ + + priv = &g_spi3dev; + + /* Configure SPI3 pins: SCK, MISO, and MOSI */ + + stm32_configgpio(GPIO_SPI3_SCK); + stm32_configgpio(GPIO_SPI3_MISO); + stm32_configgpio(GPIO_SPI3_MOSI); + + /* Set up default configuration: Master, 8-bit, etc. */ + + spi_portinitialize(priv); + } +#endif + + irqrestore(flags); + return (FAR struct spi_dev_s *)priv; +} + +#endif /* CONFIG_STM32_SPI1 || CONFIG_STM32_SPI2 || CONFIG_STM32_SPI3 */ diff --git a/nuttx/arch/arm/src/stm32/stm32_spi.h b/nuttx/arch/arm/src/stm32/stm32_spi.h new file mode 100644 index 0000000000..268589bf35 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_spi.h @@ -0,0 +1,121 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_spi.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_STC_STM32_STM32_SPI_H +#define __ARCH_ARM_STC_STM32_STM32_SPI_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" +#include "chip/stm32_spi.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +struct spi_dev_s; +enum spi_dev_e; + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_spi1/2/3select and stm32_spi1/2/3status + * + * Description: + * The external functions, stm32_spi1/2/3select, stm32_spi1/2/3status, and + * stm32_spi1/2/3cmddata must be provided by board-specific logic. These are + * implementations of the select, status, and cmddata methods of the SPI interface + * defined by struct spi_ops_s (see include/nuttx/spi.h). All other methods + * (including up_spiinitialize()) are provided by common STM32 logic. To use this + * common SPI logic on your board: + * + * 1. Provide logic in stm32_boardinitialize() to configure SPI chip select + * pins. + * 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your + * board-specific logic. These functions will perform chip selection and + * status operations using GPIOs in the way your board is configured. + * 3. If CONFIG_SPI_CMDDATA is defined in your NuttX configuration file, then + * provide stm32_spi1/2/3cmddata() functions in your board-specific logic. + * These functions will perform cmd/data selection operations using GPIOs in the + * way your board is configured. + * 4. Add a calls to up_spiinitialize() in your low level application + * initialization logic + * 5. The handle returned by up_spiinitialize() may then be used to bind the + * SPI driver to higher level logic (e.g., calling + * mmcsd_spislotinitialize(), for example, will bind the SPI driver to + * the SPI MMC/SD driver). + * + ************************************************************************************/ + +EXTERN void stm32_spi1select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected); +EXTERN uint8_t stm32_spi1status(FAR struct spi_dev_s *dev, enum spi_dev_e devid); +EXTERN int stm32_spi1cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd); + +EXTERN void stm32_spi2select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected); +EXTERN uint8_t stm32_spi2status(FAR struct spi_dev_s *dev, enum spi_dev_e devid); +EXTERN int stm32_spi2cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd); + +EXTERN void stm32_spi3select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected); +EXTERN uint8_t stm32_spi3status(FAR struct spi_dev_s *dev, enum spi_dev_e devid); +EXTERN int stm32_spi3cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_STC_STM32_STM32_SPI_H */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_start.c b/nuttx/arch/arm/src/stm32/stm32_start.c new file mode 100644 index 0000000000..d341121f1e --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_start.c @@ -0,0 +1,240 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_start.c + * arch/arm/src/chip/stm32_start.c + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "up_internal.h" + +#include "stm32_internal.h" +#include "stm32_gpio.h" + +#ifdef CONFIG_ARCH_FPU +# include "nvic.h" +#endif + +/**************************************************************************** + * Name: showprogress + * + * Description: + * Print a character on the UART to show boot status. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG +# define showprogress(c) up_lowputc(c) +#else +# define showprogress(c) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* we need to get r10 set before we can allow instrumentation calls */ + +void __start(void) __attribute__ ((no_instrument_function)); + +/**************************************************************************** + * Name: stm32_fpuconfig + * + * Description: + * Configure the FPU. Relative bit settings: + * + * CPACR: Enables access to CP10 and CP11 + * CONTROL.FPCA: Determines whether the FP extension is active in the + * current context: + * FPCCR.ASPEN: Enables automatic FP state preservation, then the + * processor sets this bit to 1 on successful completion of any FP + * instruction. + * FPCCR.LSPEN: Enables lazy context save of FP state. When this is + * done, the processor reserves space on the stack for the FP state, + * but does not save that state information to the stack. + * + * Software must not change the value of the ASPEN bit or LSPEN bit while either: + * - the CPACR permits access to CP10 and CP11, that give access to the FP + * extension, or + * - the CONTROL.FPCA bit is set to 1 + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_FPU +#ifdef CONFIG_ARMV7M_CMNVECTOR + +static inline void stm32_fpuconfig(void) +{ + uint32_t regval; + + /* Set CONTROL.FPCA so that we always get the extended context frame + * with the volatile FP registers stacked above the basic context. + */ + + regval = getcontrol(); + regval |= (1 << 2); + setcontrol(regval); + + /* Ensure that FPCCR.LSPEN is disabled, so that we don't have to contend + * with the lazy FP context save behaviour. Clear FPCCR.ASPEN since we + * are going to turn on CONTROL.FPCA for all contexts. + */ + + regval = getreg32(NVIC_FPCCR); + regval &= ~((1 << 31) | (1 << 30)); + putreg32(regval, NVIC_FPCCR); + + /* Enable full access to CP10 and CP11 */ + + regval = getreg32(NVIC_CPACR); + regval |= ((3 << (2*10)) | (3 << (2*11))); + putreg32(regval, NVIC_CPACR); +} + +#else + +static inline void stm32_fpuconfig(void) +{ + uint32_t regval; + + /* Clear CONTROL.FPCA so that we do not get the extended context frame + * with the volatile FP registers stacked in the saved context. + */ + + regval = getcontrol(); + regval &= ~(1 << 2); + setcontrol(regval); + + /* Ensure that FPCCR.LSPEN is disabled, so that we don't have to contend + * with the lazy FP context save behaviour. Clear FPCCR.ASPEN since we + * are going to keep CONTROL.FPCA off for all contexts. + */ + + regval = getreg32(NVIC_FPCCR); + regval &= ~((1 << 31) | (1 << 30)); + putreg32(regval, NVIC_FPCCR); + + /* Enable full access to CP10 and CP11 */ + + regval = getreg32(NVIC_CPACR); + regval |= ((3 << (2*10)) | (3 << (2*11))); + putreg32(regval, NVIC_CPACR); +} + +#endif + +#else +# define stm32_fpuconfig() +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _start + * + * Description: + * This is the reset entry point. + * + ****************************************************************************/ + +void __start(void) +{ + const uint32_t *src; + uint32_t *dest; + + /* Set the stack limit before we attempt to call any functions */ + + __asm__ volatile ("sub r10, sp, %0" : : "r" (CONFIG_IDLETHREAD_STACKSIZE - 64) : ); + + /* Configure the uart so that we can get debug output as soon as possible */ + + stm32_clockconfig(); + stm32_fpuconfig(); + stm32_lowsetup(); + stm32_gpioinit(); + showprogress('A'); + + /* Clear .bss. We'll do this inline (vs. calling memset) just to be + * certain that there are no issues with the state of global variables. + */ + + for (dest = &_sbss; dest < &_ebss; ) + { + *dest++ = 0; + } + showprogress('B'); + + /* Move the intialized data section from his temporary holding spot in + * FLASH into the correct place in SRAM. The correct place in SRAM is + * give by _sdata and _edata. The temporary location is in FLASH at the + * end of all of the other read-only data (.text, .rodata) at _eronly. + */ + + for (src = &_eronly, dest = &_sdata; dest < &_edata; ) + { + *dest++ = *src++; + } + showprogress('C'); + + /* Perform early serial initialization */ + +#ifdef USE_EARLYSERIALINIT + up_earlyserialinit(); +#endif + showprogress('D'); + + /* Initialize onboard resources */ + + stm32_boardinitialize(); + showprogress('E'); + + /* Then start NuttX */ + + showprogress('\r'); + showprogress('\n'); + os_start(); + + /* Shoulnd't get here */ + + for(;;); +} diff --git a/nuttx/arch/arm/src/stm32/stm32_syscfg.h b/nuttx/arch/arm/src/stm32/stm32_syscfg.h new file mode 100644 index 0000000000..8a57a2c58f --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_syscfg.h @@ -0,0 +1,104 @@ +/**************************************************************************************************** + * arch/arm/src/stm32/stm32_syscfg.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_SYSCFG_H +#define __ARCH_ARM_SRC_STM32_STM32_SYSCFG_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include +#include "chip.h" + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# include "chip/stm32_syscfg.h" + +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ + +/**************************************************************************************************** + * Inline Functions + ****************************************************************************************************/ + +/************************************************************************************ + * Name: stm32_selectmii + * + * Description: + * Selects the MII inteface. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +static inline void stm32_selectmii(void) +{ + uint32_t regval; + + regval = getreg32(STM32_SYSCFG_PMC); + regval &= ~SYSCFG_PMC_MII_RMII_SEL; + putreg32(regval, STM32_SYSCFG_PMC); +} + +/************************************************************************************ + * Name: stm32_selectrmii + * + * Description: + * Selects the RMII inteface. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +static inline void stm32_selectrmii(void) +{ + uint32_t regval; + + regval = getreg32(STM32_SYSCFG_PMC); + regval |= SYSCFG_PMC_MII_RMII_SEL; + putreg32(regval, STM32_SYSCFG_PMC); +} + +#endif /* CONFIG_STM32_STM32F20XX || CONFIG_STM32_STM32F40XX */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_SYSCFG_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_tim.c b/nuttx/arch/arm/src/stm32/stm32_tim.c new file mode 100644 index 0000000000..d19c69c032 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_tim.c @@ -0,0 +1,1020 @@ +/************************************************************************************ + * arm/arm/src/stm32/stm32_tim.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * With modifications and updates by: + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "chip.h" +#include "up_internal.h" +#include "up_arch.h" + +#include "stm32_internal.h" +#include "stm32_gpio.h" +#include "stm32_tim.h" + +/************************************************************************************ + * Private Types + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* Timer devices may be used for different purposes. Such special purposes include: + * + * - To generate modulated outputs for such things as motor control. If CONFIG_STM32_TIMn + * is defined then the CONFIG_STM32_TIMn_PWM may also be defined to indicate that + * the timer is intended to be used for pulsed output modulation. + * + * - To control periodic ADC input sampling. If CONFIG_STM32_TIMn is defined then + * CONFIG_STM32_TIMn_ADC may also be defined to indicate that timer "n" is intended + * to be used for that purpose. + * + * - To control periodic DAC outputs. If CONFIG_STM32_TIMn is defined then + * CONFIG_STM32_TIMn_DAC may also be defined to indicate that timer "n" is intended + * to be used for that purpose. + * + * - To use a Quadrature Encoder. If CONFIG_STM32_TIMn is defined then + * CONFIG_STM32_TIMn_QE may also be defined to indicate that timer "n" is intended + * to be used for that purpose. + * + * In any of these cases, the timer will not be used by this timer module. + */ + +#if defined(CONFIG_STM32_TIM1_PWM) || defined (CONFIG_STM32_TIM1_ADC) || \ + defined(CONFIG_STM32_TIM1_DAC) || defined(CONFIG_STM32_TIM1_QE) +# undef CONFIG_STM32_TIM1 +#endif +#if defined(CONFIG_STM32_TIM2_PWM) || defined (CONFIG_STM32_TIM2_ADC) || \ + defined(CONFIG_STM32_TIM2_DAC) || defined(CONFIG_STM32_TIM2_QE) +# undef CONFIG_STM32_TIM2 +#endif +#if defined(CONFIG_STM32_TIM3_PWM) || defined (CONFIG_STM32_TIM3_ADC) || \ + defined(CONFIG_STM32_TIM3_DAC) || defined(CONFIG_STM32_TIM3_QE) +# undef CONFIG_STM32_TIM3 +#endif +#if defined(CONFIG_STM32_TIM4_PWM) || defined (CONFIG_STM32_TIM4_ADC) || \ + defined(CONFIG_STM32_TIM4_DAC) || defined(CONFIG_STM32_TIM4_QE) +# undef CONFIG_STM32_TIM4 +#endif +#if defined(CONFIG_STM32_TIM5_PWM) || defined (CONFIG_STM32_TIM5_ADC) || \ + defined(CONFIG_STM32_TIM5_DAC) || defined(CONFIG_STM32_TIM5_QE) +# undef CONFIG_STM32_TIM5 +#endif +#if defined(CONFIG_STM32_TIM6_PWM) || defined (CONFIG_STM32_TIM6_ADC) || \ + defined(CONFIG_STM32_TIM6_DAC) || defined(CONFIG_STM32_TIM6_QE) +# undef CONFIG_STM32_TIM6 +#endif +#if defined(CONFIG_STM32_TIM7_PWM) || defined (CONFIG_STM32_TIM7_ADC) || \ + defined(CONFIG_STM32_TIM7_DAC) || defined(CONFIG_STM32_TIM7_QE) +# undef CONFIG_STM32_TIM7 +#endif +#if defined(CONFIG_STM32_TIM8_PWM) || defined (CONFIG_STM32_TIM8_ADC) || \ + defined(CONFIG_STM32_TIM8_DAC) || defined(CONFIG_STM32_TIM8_QE) +# undef CONFIG_STM32_TIM8 +#endif +#if defined(CONFIG_STM32_TIM9_PWM) || defined (CONFIG_STM32_TIM9_ADC) || \ + defined(CONFIG_STM32_TIM9_DAC) || defined(CONFIG_STM32_TIM9_QE) +# undef CONFIG_STM32_TIM9 +#endif +#if defined(CONFIG_STM32_TIM10_PWM) || defined (CONFIG_STM32_TIM10_ADC) || \ + defined(CONFIG_STM32_TIM10_DAC) || defined(CONFIG_STM32_TIM10_QE) +# undef CONFIG_STM32_TIM10 +#endif +#if defined(CONFIG_STM32_TIM11_PWM) || defined (CONFIG_STM32_TIM11_ADC) || \ + defined(CONFIG_STM32_TIM11_DAC) || defined(CONFIG_STM32_TIM11_QE) +# undef CONFIG_STM32_TIM11 +#endif +#if defined(CONFIG_STM32_TIM12_PWM) || defined (CONFIG_STM32_TIM12_ADC) || \ + defined(CONFIG_STM32_TIM12_DAC) || defined(CONFIG_STM32_TIM12_QE) +# undef CONFIG_STM32_TIM12 +#endif +#if defined(CONFIG_STM32_TIM13_PWM) || defined (CONFIG_STM32_TIM13_ADC) || \ + defined(CONFIG_STM32_TIM13_DAC) || defined(CONFIG_STM32_TIM13_QE) +# undef CONFIG_STM32_TIM13 +#endif +#if defined(CONFIG_STM32_TIM14_PWM) || defined (CONFIG_STM32_TIM14_ADC) || \ + defined(CONFIG_STM32_TIM14_DAC) || defined(CONFIG_STM32_TIM14_QE) +# undef CONFIG_STM32_TIM14 +#endif + +/* This module then only compiles if there are enabled timers that are not intended for + * some other purpose. + */ + +#if defined(CONFIG_STM32_TIM1) || defined(CONFIG_STM32_TIM2) || defined(CONFIG_STM32_TIM3) || \ + defined(CONFIG_STM32_TIM4) || defined(CONFIG_STM32_TIM5) || defined(CONFIG_STM32_TIM6) || \ + defined(CONFIG_STM32_TIM7) || defined(CONFIG_STM32_TIM8) + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/* TIM Device Structure */ + +struct stm32_tim_priv_s +{ + struct stm32_tim_ops_s *ops; + stm32_tim_mode_t mode; + uint32_t base; /* TIMn base address */ +}; + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/* Get a 16-bit register value by offset */ + +static inline uint16_t stm32_getreg16(FAR struct stm32_tim_dev_s *dev, uint8_t offset) +{ + return getreg16(((struct stm32_tim_priv_s *)dev)->base + offset); +} + +/* Put a 16-bit register value by offset */ + +static inline void stm32_putreg16(FAR struct stm32_tim_dev_s *dev, uint8_t offset, uint16_t value) +{ + putreg16(value, ((struct stm32_tim_priv_s *)dev)->base + offset); +} + +/* Modify a 16-bit register value by offset */ + +static inline void stm32_modifyreg16(FAR struct stm32_tim_dev_s *dev, uint8_t offset, uint16_t clearbits, uint16_t setbits) +{ + modifyreg16(((struct stm32_tim_priv_s *)dev)->base + offset, clearbits, setbits); +} + +/* Get a 32-bit register value by offset. This applies only for the STM32 F4 + * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5. + */ + +static inline uint32_t stm32_getreg32(FAR struct stm32_tim_dev_s *dev, uint8_t offset) +{ + return getreg32(((struct stm32_tim_priv_s *)dev)->base + offset); +} + +/* Put a 32-bit register value by offset. This applies only for the STM32 F4 + * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5. + */ + +static inline void stm32_putreg32(FAR struct stm32_tim_dev_s *dev, uint8_t offset, uint32_t value) +{ + putreg32(value, ((struct stm32_tim_priv_s *)dev)->base + offset); +} + +static void stm32_tim_reload_counter(FAR struct stm32_tim_dev_s *dev) +{ + uint16_t val = stm32_getreg16(dev, STM32_BTIM_EGR_OFFSET); + val |= ATIM_EGR_UG; + stm32_putreg16(dev, STM32_BTIM_EGR_OFFSET, val); +} + +static void stm32_tim_enable(FAR struct stm32_tim_dev_s *dev) +{ + uint16_t val = stm32_getreg16(dev, STM32_BTIM_CR1_OFFSET); + val |= ATIM_CR1_CEN; + stm32_tim_reload_counter(dev); + stm32_putreg16(dev, STM32_BTIM_CR1_OFFSET, val); +} + +static void stm32_tim_disable(FAR struct stm32_tim_dev_s *dev) +{ + uint16_t val = stm32_getreg16(dev, STM32_BTIM_CR1_OFFSET); + val &= ~ATIM_CR1_CEN; + stm32_putreg16(dev, STM32_BTIM_CR1_OFFSET, val); +} + +/* Reset timer into system default state, but do not affect output/input pins */ +static void stm32_tim_reset(FAR struct stm32_tim_dev_s *dev) +{ + ((struct stm32_tim_priv_s *)dev)->mode = STM32_TIM_MODE_DISABLED; + stm32_tim_disable(dev); +} + +static void stm32_tim_gpioconfig(uint32_t cfg, stm32_tim_channel_t mode) +{ + /* TODO: Add support for input capture and bipolar dual outputs for TIM8 */ + + if (mode & STM32_TIM_CH_MODE_MASK) + { + stm32_configgpio(cfg); + } + else + { + stm32_unconfiggpio(cfg); + } +} + +/************************************************************************************ + * Basic Functions + ************************************************************************************/ + +static int stm32_tim_setclock(FAR struct stm32_tim_dev_s *dev, uint32_t freq) +{ + int prescaler; + + ASSERT(dev); + + /* Disable Timer? */ + + if (freq == 0) + { + stm32_tim_disable(dev); + return 0; + } + +#if STM32_NATIM > 0 + if (((struct stm32_tim_priv_s *)dev)->base == STM32_TIM1_BASE || + ((struct stm32_tim_priv_s *)dev)->base == STM32_TIM8_BASE) + { + prescaler = STM32_TIM18_FREQUENCY / freq; + } + else +#endif + { + prescaler = STM32_TIM27_FREQUENCY / freq; + } + + /* We need to decrement value for '1', but only, if we are allowed to + * not to cause underflow. Check for overflow. + */ + + if (prescaler > 0) + { + prescaler--; + } + + if (prescaler > 0xffff) + { + prescaler = 0xffff; + } + + stm32_putreg16(dev, STM32_BTIM_PSC_OFFSET, prescaler); + stm32_tim_enable(dev); + + return prescaler; +} + +static void stm32_tim_setperiod(FAR struct stm32_tim_dev_s *dev, uint32_t period) +{ + ASSERT(dev); + stm32_putreg32(dev, STM32_BTIM_ARR_OFFSET, period); +} + +static int stm32_tim_setisr(FAR struct stm32_tim_dev_s *dev, int (*handler)(int irq, void *context), int source) +{ + int vectorno; + + ASSERT(dev); + ASSERT(source==0); + + switch (((struct stm32_tim_priv_s *)dev)->base) + { +#if CONFIG_STM32_TIM2 + case STM32_TIM2_BASE: + vectorno = STM32_IRQ_TIM2; + break; +#endif +#if CONFIG_STM32_TIM3 + case STM32_TIM3_BASE: + vectorno = STM32_IRQ_TIM3; + break; +#endif +#if CONFIG_STM32_TIM4 + case STM32_TIM4_BASE: + vectorno = STM32_IRQ_TIM4; + break; +#endif +#if CONFIG_STM32_TIM5 + case STM32_TIM5_BASE: + vectorno = STM32_IRQ_TIM5; + break; +#endif +#if STM32_NBTIM > 0 +#if CONFIG_STM32_TIM6 + case STM32_TIM6_BASE: + vectorno = STM32_IRQ_TIM6; + break; +#endif +#endif +#if STM32_NBTIM > 1 +#if CONFIG_STM32_TIM7 + case STM32_TIM7_BASE: + vectorno = STM32_IRQ_TIM7; + break; +#endif +#endif +#if STM32_NATIM > 0 + /* TODO: add support for multiple sources and callbacks */ +#if CONFIG_STM32_TIM1 + case STM32_TIM1_BASE: + vectorno = STM32_IRQ_TIM1UP; + break; +#endif +#if CONFIG_STM32_TIM8 + case STM32_TIM8_BASE: + vectorno = STM32_IRQ_TIM8UP; + break; +#endif +#endif + default: + return ERROR; + } + + /* Disable interrupt when callback is removed */ + + if (!handler) + { + up_disable_irq(vectorno); + irq_detach(vectorno); + return OK; + } + + /* Otherwise set callback and enable interrupt */ + + irq_attach(vectorno, handler); + up_enable_irq(vectorno); +//up_prioritize_irq(vectorno, NVIC_SYSH_PRIORITY_DEFAULT); + return OK; +} + +static void stm32_tim_enableint(FAR struct stm32_tim_dev_s *dev, int source) +{ + ASSERT(dev); + stm32_modifyreg16(dev, STM32_BTIM_DIER_OFFSET, 0, ATIM_DIER_UIE); +} + +static void stm32_tim_disableint(FAR struct stm32_tim_dev_s *dev, int source) +{ + ASSERT(dev); + stm32_modifyreg16(dev, STM32_BTIM_DIER_OFFSET, ATIM_DIER_UIE, 0); +} + +static void stm32_tim_ackint(FAR struct stm32_tim_dev_s *dev, int source) +{ + stm32_putreg16(dev, STM32_BTIM_SR_OFFSET, ~ATIM_SR_UIF); +} + +/************************************************************************************ + * General Functions + ************************************************************************************/ + +static int stm32_tim_setmode(FAR struct stm32_tim_dev_s *dev, stm32_tim_mode_t mode) +{ + uint16_t val = ATIM_CR1_CEN | ATIM_CR1_ARPE; + + ASSERT(dev); + + /* This function is not supported on basic timers. To enable or + * disable it, simply set its clock to valid frequency or zero. + */ + +#if STM32_NBTIM > 0 + if (((struct stm32_tim_priv_s *)dev)->base == STM32_TIM6_BASE +#endif +#if STM32_NBTIM > 1 + || ((struct stm32_tim_priv_s *)dev)->base == STM32_TIM7_BASE +#endif +#if STM32_NBTIM > 0 + ) + { + return ERROR; + } +#endif + + /* Decode operational modes */ + + switch (mode & STM32_TIM_MODE_MASK) + { + case STM32_TIM_MODE_DISABLED: + val = 0; + break; + + case STM32_TIM_MODE_DOWN: + val |= ATIM_CR1_DIR; + + case STM32_TIM_MODE_UP: + break; + + case STM32_TIM_MODE_UPDOWN: + val |= ATIM_CR1_CENTER1; + // Our default: Interrupts are generated on compare, when counting down + break; + + case STM32_TIM_MODE_PULSE: + val |= ATIM_CR1_OPM; + break; + + default: return ERROR; + } + + stm32_tim_reload_counter(dev); + stm32_putreg16(dev, STM32_BTIM_CR1_OFFSET, val); + +#if STM32_NATIM > 0 + /* Advanced registers require Main Output Enable */ + + if (((struct stm32_tim_priv_s *)dev)->base == STM32_TIM1_BASE || + ((struct stm32_tim_priv_s *)dev)->base == STM32_TIM8_BASE) + { + stm32_modifyreg16(dev, STM32_ATIM_BDTR_OFFSET, 0, ATIM_BDTR_MOE); + } +#endif + + return OK; +} + +static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev, uint8_t channel, stm32_tim_channel_t mode) +{ + uint16_t ccmr_val = 0; + uint16_t ccer_val = stm32_getreg16(dev, STM32_GTIM_CCER_OFFSET); + uint8_t ccmr_offset = STM32_GTIM_CCMR1_OFFSET; + + ASSERT(dev); + + /* Further we use range as 0..3; if channel=0 it will also overflow here */ + + if (--channel > 4) return ERROR; + + /* Assume that channel is disabled and polarity is active high */ + + ccer_val &= ~(3 << (channel << 2)); + + /* This function is not supported on basic timers. To enable or + * disable it, simply set its clock to valid frequency or zero. + */ + +#if STM32_NBTIM > 0 + if (((struct stm32_tim_priv_s *)dev)->base == STM32_TIM6_BASE +#endif +#if STM32_NBTIM > 1 + || ((struct stm32_tim_priv_s *)dev)->base == STM32_TIM7_BASE +#endif +#if STM32_NBTIM > 0 + ) + { + return ERROR; + } +#endif + + /* Decode configuration */ + + switch (mode & STM32_TIM_CH_MODE_MASK) + { + case STM32_TIM_CH_DISABLED: + break; + + case STM32_TIM_CH_OUTPWM: + ccmr_val = (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) + ATIM_CCMR1_OC1PE; + ccer_val |= ATIM_CCER_CC1E << (channel << 2); + break; + + default: + return ERROR; + } + + /* Set polarity */ + + if (mode & STM32_TIM_CH_POLARITY_NEG) + { + ccer_val |= ATIM_CCER_CC1P << (channel << 2); + } + + /* Define its position (shift) and get register offset */ + + if (channel & 1) + { + ccmr_val <<= 8; + } + + if (channel > 1) + { + ccmr_offset = STM32_GTIM_CCMR2_OFFSET; + } + + stm32_putreg16(dev, ccmr_offset, ccmr_val); + stm32_putreg16(dev, STM32_GTIM_CCER_OFFSET, ccer_val); + + /* set GPIO */ + + switch (((struct stm32_tim_priv_s *)dev)->base) + { +#if CONFIG_STM32_TIM2 + case STM32_TIM2_BASE: + switch (channel) + { +#if defined(GPIO_TIM2_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM2_CH1OUT, mode); + break; +#endif +#if defined(GPIO_TIM2_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM2_CH2OUT, mode); + break; +#endif +#if defined(GPIO_TIM2_CH3OUT) + case 2: + stm32_tim_gpioconfig(GPIO_TIM2_CH3OUT, mode); + break; +#endif +#if defined(GPIO_TIM2_CH4OUT) + case 3: + stm32_tim_gpioconfig(GPIO_TIM2_CH4OUT, mode); + break; +#endif + default: + return ERROR; + } + break; +#endif +#if CONFIG_STM32_TIM3 + case STM32_TIM3_BASE: + switch (channel) + { +#if defined(GPIO_TIM3_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM3_CH1OUT, mode); + break; +#endif +#if defined(GPIO_TIM3_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM3_CH2OUT, mode); + break; +#endif +#if defined(GPIO_TIM3_CH3OUT) + case 2: + stm32_tim_gpioconfig(GPIO_TIM3_CH3OUT, mode); + break; +#endif +#if defined(GPIO_TIM3_CH4OUT) + case 3: + stm32_tim_gpioconfig(GPIO_TIM3_CH4OUT, mode); + break; +#endif + default: + return ERROR; + } + break; +#endif +#if CONFIG_STM32_TIM4 + case STM32_TIM4_BASE: + switch (channel) + { +#if defined(GPIO_TIM4_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM4_CH1OUT, mode); + break; +#endif +#if defined(GPIO_TIM4_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM4_CH2OUT, mode); + break; +#endif +#if defined(GPIO_TIM4_CH3OUT) + case 2: + stm32_tim_gpioconfig(GPIO_TIM4_CH3OUT, mode); + break; +#endif +#if defined(GPIO_TIM4_CH4OUT) + case 3: + stm32_tim_gpioconfig(GPIO_TIM4_CH4OUT, mode); + break; +#endif + default: return ERROR; + } + break; +#endif +#if CONFIG_STM32_TIM5 + case STM32_TIM5_BASE: + switch (channel) + { +#if defined(GPIO_TIM5_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM5_CH1OUT, mode); + break; +#endif +#if defined(GPIO_TIM5_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM5_CH2OUT, mode); + break; +#endif +#if defined(GPIO_TIM5_CH3OUT) + case 2: + stm32_tim_gpioconfig(GPIO_TIM5_CH3OUT, mode); + break; +#endif +#if defined(GPIO_TIM5_CH4OUT) + case 3: + stm32_tim_gpioconfig(GPIO_TIM5_CH4OUT, mode); + break; +#endif + default: return ERROR; + } + break; +#endif + +#if STM32_NATIM > 0 +#if CONFIG_STM32_TIM1 + case STM32_TIM1_BASE: + switch (channel) + { +#if defined(GPIO_TIM1_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM1_CH1OUT, mode); break; +#endif +#if defined(GPIO_TIM1_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM1_CH2OUT, mode); break; +#endif +#if defined(GPIO_TIM1_CH3OUT) + case 2: + stm32_tim_gpioconfig(GPIO_TIM1_CH3OUT, mode); break; +#endif +#if defined(GPIO_TIM1_CH4OUT) + case 3: + stm32_tim_gpioconfig(GPIO_TIM1_CH4OUT, mode); break; +#endif + default: return ERROR; + } + break; +#endif +#if CONFIG_STM32_TIM8 + case STM32_TIM8_BASE: + switch (channel) + { +#if defined(GPIO_TIM8_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM8_CH1OUT, mode); break; +#endif +#if defined(GPIO_TIM8_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM8_CH2OUT, mode); break; +#endif +#if defined(GPIO_TIM8_CH3OUT) + case 2: + stm32_tim_gpioconfig(GPIO_TIM8_CH3OUT, mode); break; +#endif +#if defined(GPIO_TIM8_CH4OUT) + case 3: + stm32_tim_gpioconfig(GPIO_TIM8_CH4OUT, mode); break; +#endif + default: + return ERROR; + } + break; +#endif +#endif + default: + return ERROR; + } + + return OK; +} + +static int stm32_tim_setcompare(FAR struct stm32_tim_dev_s *dev, uint8_t channel, uint32_t compare) +{ + ASSERT(dev); + + switch (channel) + { + case 1: + stm32_putreg32(dev, STM32_GTIM_CCR1_OFFSET, compare); + break; + case 2: + stm32_putreg32(dev, STM32_GTIM_CCR2_OFFSET, compare); + break; + case 3: + stm32_putreg32(dev, STM32_GTIM_CCR3_OFFSET, compare); + break; + case 4: + stm32_putreg32(dev, STM32_GTIM_CCR4_OFFSET, compare); + break; + default: + return ERROR; + } + return OK; +} + +static int stm32_tim_getcapture(FAR struct stm32_tim_dev_s *dev, uint8_t channel) +{ + ASSERT(dev); + + switch (channel) + { + case 1: + return stm32_getreg32(dev, STM32_GTIM_CCR1_OFFSET); + case 2: + return stm32_getreg32(dev, STM32_GTIM_CCR2_OFFSET); + case 3: + return stm32_getreg32(dev, STM32_GTIM_CCR3_OFFSET); + case 4: + return stm32_getreg32(dev, STM32_GTIM_CCR4_OFFSET); + } + return ERROR; +} + +/************************************************************************************ + * Advanced Functions + ************************************************************************************/ + +/* TODO: Advanced functions for the STM32_ATIM */ + +/************************************************************************************ + * Device Structures, Instantiation + ************************************************************************************/ + +struct stm32_tim_ops_s stm32_tim_ops = +{ + .setmode = &stm32_tim_setmode, + .setclock = &stm32_tim_setclock, + .setperiod = &stm32_tim_setperiod, + .setchannel = &stm32_tim_setchannel, + .setcompare = &stm32_tim_setcompare, + .getcapture = &stm32_tim_getcapture, + .setisr = &stm32_tim_setisr, + .enableint = &stm32_tim_enableint, + .disableint = &stm32_tim_disableint, + .ackint = &stm32_tim_ackint +}; + +#if CONFIG_STM32_TIM2 +struct stm32_tim_priv_s stm32_tim2_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM2_BASE, +}; +#endif + +#if CONFIG_STM32_TIM3 +struct stm32_tim_priv_s stm32_tim3_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM3_BASE, +}; +#endif + +#if CONFIG_STM32_TIM4 +struct stm32_tim_priv_s stm32_tim4_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM4_BASE, +}; +#endif + +#if CONFIG_STM32_TIM5 +struct stm32_tim_priv_s stm32_tim5_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM5_BASE, +}; +#endif + +#if STM32_NBTIM > 0 +#if CONFIG_STM32_TIM6 +struct stm32_tim_priv_s stm32_tim6_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM6_BASE, +}; +#endif +#endif + +#if STM32_NBTIM > 1 +#if CONFIG_STM32_TIM7 +struct stm32_tim_priv_s stm32_tim7_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM7_BASE, +}; +#endif +#endif + +#if STM32_NATIM > 0 + +#if CONFIG_STM32_TIM1 +struct stm32_tim_priv_s stm32_tim1_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM1_BASE, +}; +#endif + +#if CONFIG_STM32_TIM8 +struct stm32_tim_priv_s stm32_tim8_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM8_BASE, +}; +#endif + +#endif + +/************************************************************************************ + * Public Function - Initialization + ************************************************************************************/ + +FAR struct stm32_tim_dev_s *stm32_tim_init(int timer) +{ + struct stm32_tim_dev_s *dev = NULL; + + /* Get structure and enable power */ + + switch (timer) + { +#if CONFIG_STM32_TIM2 + case 2: + dev = (struct stm32_tim_dev_s *)&stm32_tim2_priv; + modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM2EN); + break; +#endif +#if CONFIG_STM32_TIM3 + case 3: + dev = (struct stm32_tim_dev_s *)&stm32_tim3_priv; + modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM3EN); + break; +#endif +#if CONFIG_STM32_TIM4 + case 4: + dev = (struct stm32_tim_dev_s *)&stm32_tim4_priv; + modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM4EN); + break; +#endif +#if CONFIG_STM32_TIM5 + case 5: + dev = (struct stm32_tim_dev_s *)&stm32_tim5_priv; + modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM5EN); + break; +#endif + +#if STM32_NBTIM > 0 +#if CONFIG_STM32_TIM6 + case 6: + dev = (struct stm32_tim_dev_s *)&stm32_tim6_priv; + modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM6EN); + break; +#endif +#endif +#if STM32_NBTIM > 1 +#if CONFIG_STM32_TIM7 + case 7: + dev = (struct stm32_tim_dev_s *)&stm32_tim7_priv; + modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM7EN); + break; +#endif +#endif + +#if STM32_NATIM > 0 +#if CONFIG_STM32_TIM1 + case 1: + dev = (struct stm32_tim_dev_s *)&stm32_tim1_priv; + modifyreg32(STM32_RCC_APB2ENR, 0, RCC_APB2ENR_TIM1EN); + break; +#endif +#if CONFIG_STM32_TIM8 + case 8: + dev = (struct stm32_tim_dev_s *)&stm32_tim8_priv; + modifyreg32(STM32_RCC_APB2ENR, 0, RCC_APB2ENR_TIM8EN); + break; +#endif +#endif + default: + return NULL; + } + + /* Is device already allocated */ + + if (((struct stm32_tim_priv_s *)dev)->mode != STM32_TIM_MODE_UNUSED) + { + return NULL; + } + + stm32_tim_reset(dev); + + return dev; +} + +/* TODO: Detach interrupts, and close down all TIM Channels */ + +int stm32_tim_deinit(FAR struct stm32_tim_dev_s * dev) +{ + ASSERT(dev); + + /* Disable power */ + + switch (((struct stm32_tim_priv_s *)dev)->base) + { +#if CONFIG_STM32_TIM2 + case STM32_TIM2_BASE: + modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM2EN, 0); + break; +#endif +#if CONFIG_STM32_TIM3 + case STM32_TIM3_BASE: + modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM3EN, 0); + break; +#endif +#if CONFIG_STM32_TIM4 + case STM32_TIM4_BASE: + modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM4EN, 0); + break; +#endif +#if CONFIG_STM32_TIM5 + case STM32_TIM5_BASE: + modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM5EN, 0); + break; +#endif +#if STM32_NBTIM > 0 +#if CONFIG_STM32_TIM6 + case STM32_TIM6_BASE: + modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM6EN, 0); + break; +#endif +#endif +#if STM32_NBTIM > 1 +#if CONFIG_STM32_TIM7 + case STM32_TIM7_BASE: + modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM7EN, 0); + break; +#endif +#endif + +#if STM32_NATIM > 0 +#if CONFIG_STM32_TIM1 + case STM32_TIM1_BASE: + modifyreg32(STM32_RCC_APB2ENR, RCC_APB2ENR_TIM1EN, 0); + break; +#endif +#if CONFIG_STM32_TIM8 + case STM32_TIM8_BASE: + modifyreg32(STM32_RCC_APB2ENR, RCC_APB2ENR_TIM8EN, 0); + break; +#endif +#endif + default: + return ERROR; + } + + /* Mark it as free */ + + ((struct stm32_tim_priv_s *)dev)->mode = STM32_TIM_MODE_UNUSED; + + return OK; +} + +#endif /* defined(CONFIG_STM32_TIM1 || ... || TIM8) */ diff --git a/nuttx/arch/arm/src/stm32/stm32_tim.h b/nuttx/arch/arm/src/stm32/stm32_tim.h new file mode 100644 index 0000000000..081a3489f1 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_tim.h @@ -0,0 +1,191 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_tim.h + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * With modifications and updates by: + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_TIM_H +#define __ARCH_ARM_SRC_STM32_STM32_TIM_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" +#include "chip/stm32_tim.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Helpers **************************************************************************/ + +#define STM32_TIM_SETMODE(d,mode) ((d)->ops->setmode(d,mode)) +#define STM32_TIM_SETCLOCK(d,freq) ((d)->ops->setclock(d,freq)) +#define STM32_TIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period)) +#define STM32_TIM_SETCHANNEL(d,ch,mode) ((d)->ops->setchannel(d,ch,mode)) +#define STM32_TIM_SETCOMPARE(d,ch,comp) ((d)->ops->setcompare(d,ch,comp)) +#define STM32_TIM_GETCAPTURE(d,ch) ((d)->ops->getcapture(d,ch)) +#define STM32_TIM_SETISR(d,hnd,s) ((d)->ops->setisr(d,hnd,s)) +#define STM32_TIM_ENABLEINT(d,s) ((d)->ops->enableint(d,s)) +#define STM32_TIM_DISABLEINT(d,s) ((d)->ops->disableint(d,s)) +#define STM32_TIM_ACKINT(d,s) ((d)->ops->ackint(d,s)) + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* TIM Device Structure */ + +struct stm32_tim_dev_s +{ + struct stm32_tim_ops_s *ops; +}; + +/* TIM Modes of Operation */ + +typedef enum +{ + STM32_TIM_MODE_UNUSED = -1, + + /* One of the following */ + + STM32_TIM_MODE_MASK = 0x0310, + STM32_TIM_MODE_DISABLED = 0x0000, + STM32_TIM_MODE_UP = 0x0100, + STM32_TIM_MODE_DOWN = 0x0110, + STM32_TIM_MODE_UPDOWN = 0x0200, + STM32_TIM_MODE_PULSE = 0x0300, + + /* One of the following */ + + STM32_TIM_MODE_CK_INT = 0x0000, +//STM32_TIM_MODE_CK_INT_TRIG = 0x0400, +//STM32_TIM_MODE_CK_EXT = 0x0800, +//STM32_TIM_MODE_CK_EXT_TRIG = 0x0C00, + + /* Clock sources, OR'ed with CK_EXT */ + +//STM32_TIM_MODE_CK_CHINVALID = 0x0000, +//STM32_TIM_MODE_CK_CH1 = 0x0001, +//STM32_TIM_MODE_CK_CH2 = 0x0002, +//STM32_TIM_MODE_CK_CH3 = 0x0003, +//STM32_TIM_MODE_CK_CH4 = 0x0004 + + /* Todo: external trigger block */ + +} stm32_tim_mode_t; + +/* TIM Channel Modes */ + +typedef enum +{ + STM32_TIM_CH_DISABLED = 0x00, + + /* Common configuration */ + + STM32_TIM_CH_POLARITY_POS = 0x00, + STM32_TIM_CH_POLARITY_NEG = 0x01, + + /* MODES: */ + + STM32_TIM_CH_MODE_MASK = 0x06, + + /* Output Compare Modes */ + + STM32_TIM_CH_OUTPWM = 0x04, /** Enable standard PWM mode, active high when counter < compare */ +//STM32_TIM_CH_OUTCOMPARE = 0x06, + + // TODO other modes ... as PWM capture, ENCODER and Hall Sensor +//STM32_TIM_CH_INCAPTURE = 0x10, +//STM32_TIM_CH_INPWM = 0x20 +//STM32_TIM_CH_DRIVE_OC -- open collector mode + +} stm32_tim_channel_t; + +/* TIM Operations */ + +struct stm32_tim_ops_s +{ + /* Basic Timers */ + + int (*setmode)(FAR struct stm32_tim_dev_s *dev, stm32_tim_mode_t mode); + int (*setclock)(FAR struct stm32_tim_dev_s *dev, uint32_t freq); + void (*setperiod)(FAR struct stm32_tim_dev_s *dev, uint32_t period); + + /* General and Advanced Timers Adds */ + + int (*setchannel)(FAR struct stm32_tim_dev_s *dev, uint8_t channel, stm32_tim_channel_t mode); + int (*setcompare)(FAR struct stm32_tim_dev_s *dev, uint8_t channel, uint32_t compare); + int (*getcapture)(FAR struct stm32_tim_dev_s *dev, uint8_t channel); + + int (*setisr)(FAR struct stm32_tim_dev_s *dev, int (*handler)(int irq, void *context), int source); + void (*enableint)(FAR struct stm32_tim_dev_s *dev, int source); + void (*disableint)(FAR struct stm32_tim_dev_s *dev, int source); + void (*ackint)(FAR struct stm32_tim_dev_s *dev, int source); +}; + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/* Power-up timer and get its structure */ + +EXTERN FAR struct stm32_tim_dev_s * stm32_tim_init(int timer); + +/* Power-down timer, mark it as unused */ + +EXTERN int stm32_tim_deinit(FAR struct stm32_tim_dev_s * dev); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_TIM_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_timerisr.c b/nuttx/arch/arm/src/stm32/stm32_timerisr.c new file mode 100644 index 0000000000..93cca02aca --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_timerisr.c @@ -0,0 +1,164 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_timerisr.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "nvic.h" +#include "clock_internal.h" +#include "up_internal.h" +#include "up_arch.h" + +#include "chip.h" +#include "stm32_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* The desired timer interrupt frequency is provided by the definition + * CLK_TCK (see include/time.h). CLK_TCK defines the desired number of + * system clock ticks per second. That value is a user configurable setting + * that defaults to 100 (100 ticks per second = 10 MS interval). + * + * The RCC feeds the Cortex System Timer (SysTick) with the AHB clock (HCLK) + * divided by 8. The SysTick can work either with this clock or with the + * Cortex clock (HCLK), configurable in the SysTick Control and Status + * register. + */ + +#undef CONFIG_STM32_SYSTICK_HCLKd8 /* Power up default is HCLK, not HCLK/8 */ + /* And I don't know now to re-configure it yet */ + +#if CONFIG_STM32_SYSTICK_HCLKd8 +# define SYSTICK_RELOAD ((STM32_HCLK_FREQUENCY / 8 / CLK_TCK) - 1) +#else +# define SYSTICK_RELOAD ((STM32_HCLK_FREQUENCY / CLK_TCK) - 1) +#endif + +/* The size of the reload field is 24 bits. Verify taht the reload value + * will fit in the reload register. + */ + +#if SYSTICK_RELOAD > 0x00ffffff +# error SYSTICK_RELOAD exceeds the range of the RELOAD register +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: up_timerisr + * + * Description: + * The timer ISR will perform a variety of services for various portions + * of the systems. + * + ****************************************************************************/ + +int up_timerisr(int irq, uint32_t *regs) +{ + /* Process timer interrupt */ + + sched_process_timer(); + return 0; +} + +/**************************************************************************** + * Function: up_timerinit + * + * Description: + * This function is called during start-up to initialize + * the timer interrupt. + * + ****************************************************************************/ + +void up_timerinit(void) +{ + uint32_t regval; + + /* Set the SysTick interrupt to the default priority */ + + regval = getreg32(NVIC_SYSH12_15_PRIORITY); + regval &= ~NVIC_SYSH_PRIORITY_PR15_MASK; + regval |= (NVIC_SYSH_PRIORITY_DEFAULT << NVIC_SYSH_PRIORITY_PR15_SHIFT); + putreg32(regval, NVIC_SYSH12_15_PRIORITY); + + /* Make sure that the SYSTICK clock source is set correctly */ + +#if 0 /* Does not work. Comes up with HCLK source and I can't change it */ + regval = getreg32(NVIC_SYSTICK_CTRL); +#if CONFIG_STM32_SYSTICK_HCLKd8 + regval &= ~NVIC_SYSTICK_CTRL_CLKSOURCE; +#else + regval |= NVIC_SYSTICK_CTRL_CLKSOURCE; +#endif + putreg32(regval, NVIC_SYSTICK_CTRL); +#endif + + /* Configure SysTick to interrupt at the requested rate */ + + putreg32(SYSTICK_RELOAD, NVIC_SYSTICK_RELOAD); + + /* Attach the timer interrupt vector */ + + (void)irq_attach(STM32_IRQ_SYSTICK, (xcpt_t)up_timerisr); + + /* Enable SysTick interrupts */ + + putreg32((NVIC_SYSTICK_CTRL_CLKSOURCE|NVIC_SYSTICK_CTRL_TICKINT|NVIC_SYSTICK_CTRL_ENABLE), NVIC_SYSTICK_CTRL); + + /* And enable the timer interrupt */ + + up_enable_irq(STM32_IRQ_SYSTICK); +} diff --git a/nuttx/arch/arm/src/stm32/stm32_uart.h b/nuttx/arch/arm/src/stm32/stm32_uart.h new file mode 100644 index 0000000000..42fe9e346b --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_uart.h @@ -0,0 +1,254 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_uart.h + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_STC_STM32_STM32_UART_H +#define __ARCH_ARM_STC_STM32_STM32_UART_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" +#include "chip/stm32_uart.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Make sure that we have not enabled more U[S]ARTs than are support by + * the device. + */ + +#if STM32_NUSART < 6 +# undef CONFIG_STM32_USART6 +#endif +#if STM32_NUSART < 5 +# undef CONFIG_STM32_UART5 +#endif +#if STM32_NUSART < 4 +# undef CONFIG_STM32_UART4 +#endif +#if STM32_NUSART < 3 +# undef CONFIG_STM32_USART3 +#endif +#if STM32_NUSART < 2 +# undef CONFIG_STM32_USART2 +#endif +#if STM32_NUSART < 1 +# undef CONFIG_STM32_USART1 +#endif + +/* Is there a USART enabled? */ + +#if defined(CONFIG_STM32_USART1) || defined(CONFIG_STM32_USART2) || \ + defined(CONFIG_STM32_USART3) || defined(CONFIG_STM32_UART4) || \ + defined(CONFIG_STM32_UART5) || defined(CONFIG_STM32_USART6) +# define HAVE_UART 1 +#endif + +/* Is there a serial console? */ + +#if defined(CONFIG_USART1_SERIAL_CONSOLE) && defined(CONFIG_STM32_USART1) +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_USART3_SERIAL_CONSOLE +# undef CONFIG_USART4_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# undef CONFIG_USART6_SERIAL_CONSOLE +# define CONSOLE_UART 1 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_USART2_SERIAL_CONSOLE) && defined(CONFIG_STM32_USART2) +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART3_SERIAL_CONSOLE +# undef CONFIG_USART4_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# undef CONFIG_USART6_SERIAL_CONSOLE +# define CONSOLE_UART 2 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_USART3_SERIAL_CONSOLE) && defined(CONFIG_STM32_USART3) +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_USART4_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# undef CONFIG_USART6_SERIAL_CONSOLE +# define CONSOLE_UART 3 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_USART4_SERIAL_CONSOLE) && defined(CONFIG_STM32_UART4) +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_USART3_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# undef CONFIG_USART6_SERIAL_CONSOLE +# define CONSOLE_UART 4 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_USART5_SERIAL_CONSOLE) && defined(CONFIG_STM32_UART5) +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_USART3_SERIAL_CONSOLE +# undef CONFIG_USART4_SERIAL_CONSOLE +# undef CONFIG_USART6_SERIAL_CONSOLE +# define CONSOLE_UART 5 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_USART6_SERIAL_CONSOLE) && defined(CONFIG_STM32_USART6) +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_USART3_SERIAL_CONSOLE +# undef CONFIG_USART4_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# define CONSOLE_UART 6 +# define HAVE_CONSOLE 1 +#else +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_USART3_SERIAL_CONSOLE +# undef CONFIG_USART4_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# undef CONFIG_USART6_SERIAL_CONSOLE +# define CONSOLE_UART 0 +# undef HAVE_CONSOLE +#endif + +/* DMA support is only provided if CONFIG_ARCH_DMA is in the NuttX configuration. + * Furthermore, DMA support is currently only implemented for the F4 (but could be + * extended to the F1 and F2 with a little effort in the DMA code. + */ + +#if !defined(HAVE_UART) || !defined(CONFIG_ARCH_DMA) || !defined(CONFIG_STM32_STM32F40XX) +# undef CONFIG_USART1_RXDMA +# undef CONFIG_USART2_RXDMA +# undef CONFIG_USART3_RXDMA +# undef CONFIG_USART4_RXDMA +# undef CONFIG_USART5_RXDMA +# undef CONFIG_USART6_RXDMA +#endif + +/* Disable the DMA configuration on all unused USARTs */ + +#ifndef CONFIG_STM32_USART1 +# undef CONFIG_USART1_RXDMA +#endif + +#ifndef CONFIG_STM32_USART2 +# undef CONFIG_USART2_RXDMA +#endif + +#ifndef CONFIG_STM32_USART3 +# undef CONFIG_USART3_RXDMA +#endif + +#ifndef CONFIG_STM32_UART4 +# undef CONFIG_USART4_RXDMA +#endif + +#ifndef CONFIG_STM32_UART5 +# undef CONFIG_USART5_RXDMA +#endif + +#ifndef CONFIG_STM32_USART6 +# undef CONFIG_USART6_RXDMA +#endif + +/* Is DMA available on any (enabled) USART? */ + +#undef SERIAL_HAVE_DMA +#if defined(CONFIG_USART1_RXDMA) || defined(CONFIG_USART2_RXDMA) || \ + defined(CONFIG_USART3_RXDMA) || defined(CONFIG_USART4_RXDMA) || \ + defined(CONFIG_USART5_RXDMA) || defined(CONFIG_USART6_RXDMA) +# define SERIAL_HAVE_DMA 1 +#endif + +/* Is DMA used on all (enabled) USARTs */ + +#define SERIAL_HAVE_ONLY_DMA 1 +#if defined(CONFIG_STM32_USART1) && !defined(CONFIG_USART1_RXDMA) +# undef SERIAL_HAVE_ONLY_DMA +#elif defined(CONFIG_STM32_USART2) && !defined(CONFIG_USART2_RXDMA) +# undef SERIAL_HAVE_ONLY_DMA +#elif defined(CONFIG_STM32_USART3) && !defined(CONFIG_USART3_RXDMA) +# undef SERIAL_HAVE_ONLY_DMA +#elif defined(CONFIG_STM32_UART4) && !defined(CONFIG_USART4_RXDMA) +# undef SERIAL_HAVE_ONLY_DMA +#elif defined(CONFIG_STM32_UART5) && !defined(CONFIG_USART5_RXDMA) +# undef SERIAL_HAVE_ONLY_DMA +#elif defined(CONFIG_STM32_USART6) && !defined(CONFIG_USART6_RXDMA) +# undef SERIAL_HAVE_ONLY_DMA +#endif + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/**************************************************************************** + * Name: stm32_serial_dma_poll + * + * Description: + * Must be called periodically if any STM32 UART is configured for DMA. + * The DMA callback is triggered for each fifo size/2 bytes, but this can + * result in some bytes being transferred but not collected if the incoming + * data is not a whole multiple of half the FIFO size. + * + * May be safely called from either interrupt or thread context. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +EXTERN void stm32_serial_dma_poll(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_STC_STM32_STM32_UART_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_usbdev.c b/nuttx/arch/arm/src/stm32/stm32_usbdev.c new file mode 100644 index 0000000000..602de38240 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_usbdev.c @@ -0,0 +1,3664 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_usbdev.c + * + * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * - RM0008 Reference manual, STMicro document ID 13902 + * - STM32F10xxx USB development kit, UM0424, STMicro + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "up_arch.h" +#include "stm32_internal.h" +#include "stm32_usbdev.h" + +#if defined(CONFIG_USBDEV) && defined(CONFIG_STM32_USB) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_USBDEV_EP0_MAXSIZE +# define CONFIG_USBDEV_EP0_MAXSIZE 64 +#endif + +#ifndef CONFIG_USB_PRI +# define CONFIG_USB_PRI NVIC_SYSH_PRIORITY_DEFAULT +#endif + +/* Extremely detailed register debug that you would normally never want + * enabled. + */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_STM32_USBDEV_REGDEBUG +#endif + +/* Initial interrupt mask: Reset + Suspend + Correct Transfer */ + +#define STM32_CNTR_SETUP (USB_CNTR_RESETM|USB_CNTR_SUSPM|USB_CNTR_CTRM) + +/* Endpoint identifiers. The STM32 supports up to 16 mono-directional or 8 + * bidirectional endpoints. However, when you take into account PMA buffer + * usage (see below) and the fact that EP0 is bidirectional, then there is + * a functional limitation of EP0 + 5 mono-directional endpoints = 6. We'll + * define STM32_NENDPOINTS to be 8, however, because that is how many + * endpoint register sets there are. + */ + +#define STM32_NENDPOINTS (8) +#define EP0 (0) +#define EP1 (1) +#define EP2 (2) +#define EP3 (3) +#define EP4 (4) +#define EP5 (5) +#define EP6 (6) +#define EP7 (7) + +#define STM32_ENDP_BIT(ep) (1 << (ep)) +#define STM32_ENDP_ALLSET 0xff + +/* Packet sizes. We us a fixed 64 max packet size for all endpoint types */ + +#define STM32_MAXPACKET_SHIFT (6) +#define STM32_MAXPACKET_SIZE (1 << (STM32_MAXPACKET_SHIFT)) +#define STM32_MAXPACKET_MASK (STM32_MAXPACKET_SIZE-1) + +#define STM32_EP0MAXPACKET STM32_MAXPACKET_SIZE + +/* Buffer descriptor table. We assume that USB has exclusive use of CAN/USB + * memory. The buffer table is positioned at the beginning of the 512-byte + * CAN/USB memory. We will use the first STM32_NENDPOINTS*4 words for the buffer + * table. That is exactly 64 bytes, leaving 7*64 bytes for endpoint buffers. + */ + +#define STM32_BTABLE_ADDRESS (0x00) /* Start at the beginning of USB/CAN RAM */ +#define STM32_DESC_SIZE (8) /* Each descriptor is 4*2=8 bytes in size */ +#define STM32_BTABLE_SIZE (STM32_NENDPOINTS*STM32_DESC_SIZE) + +/* Buffer layout. Assume that all buffers are 64-bytes (maxpacketsize), then + * we have space for only 7 buffers; endpoint 0 will require two buffers, leaving + * 5 for other endpoints. + */ + +#define STM32_BUFFER_START STM32_BTABLE_SIZE +#define STM32_EP0_RXADDR STM32_BUFFER_START +#define STM32_EP0_TXADDR (STM32_EP0_RXADDR+STM32_EP0MAXPACKET) + +#define STM32_BUFFER_EP0 0x03 +#define STM32_NBUFFERS 7 +#define STM32_BUFFER_BIT(bn) (1 << (bn)) +#define STM32_BUFFER_ALLSET 0x7f +#define STM32_BUFNO2BUF(bn) (STM32_BUFFER_START+((bn)<head == NULL) +#define stm32_rqpeek(ep) ((ep)->head) + +/* USB trace ****************************************************************/ +/* Trace error codes */ + +#define STM32_TRACEERR_ALLOCFAIL 0x0001 +#define STM32_TRACEERR_BADCLEARFEATURE 0x0002 +#define STM32_TRACEERR_BADDEVGETSTATUS 0x0003 +#define STM32_TRACEERR_BADEPGETSTATUS 0x0004 +#define STM32_TRACEERR_BADEPNO 0x0005 +#define STM32_TRACEERR_BADEPTYPE 0x0006 +#define STM32_TRACEERR_BADGETCONFIG 0x0007 +#define STM32_TRACEERR_BADGETSETDESC 0x0008 +#define STM32_TRACEERR_BADGETSTATUS 0x0009 +#define STM32_TRACEERR_BADSETADDRESS 0x000a +#define STM32_TRACEERR_BADSETCONFIG 0x000b +#define STM32_TRACEERR_BADSETFEATURE 0x000c +#define STM32_TRACEERR_BINDFAILED 0x000d +#define STM32_TRACEERR_DISPATCHSTALL 0x000e +#define STM32_TRACEERR_DRIVER 0x000f +#define STM32_TRACEERR_DRIVERREGISTERED 0x0010 +#define STM32_TRACEERR_EP0BADCTR 0x0011 +#define STM32_TRACEERR_EP0SETUPSTALLED 0x0012 +#define STM32_TRACEERR_EPBUFFER 0x0013 +#define STM32_TRACEERR_EPDISABLED 0x0014 +#define STM32_TRACEERR_EPOUTNULLPACKET 0x0015 +#define STM32_TRACEERR_EPRESERVE 0x0016 +#define STM32_TRACEERR_INVALIDCTRLREQ 0x0017 +#define STM32_TRACEERR_INVALIDPARMS 0x0018 +#define STM32_TRACEERR_IRQREGISTRATION 0x0019 +#define STM32_TRACEERR_NOTCONFIGURED 0x001a +#define STM32_TRACEERR_REQABORTED 0x001b + +/* Trace interrupt codes */ + +#define STM32_TRACEINTID_CLEARFEATURE 0x0001 +#define STM32_TRACEINTID_DEVGETSTATUS 0x0002 +#define STM32_TRACEINTID_DISPATCH 0x0003 +#define STM32_TRACEINTID_EP0IN 0x0004 +#define STM32_TRACEINTID_EP0INDONE 0x0005 +#define STM32_TRACEINTID_EP0OUTDONE 0x0006 +#define STM32_TRACEINTID_EP0SETUPDONE 0x0007 +#define STM32_TRACEINTID_EP0SETUPSETADDRESS 0x0008 +#define STM32_TRACEINTID_EPGETSTATUS 0x0009 +#define STM32_TRACEINTID_EPINDONE 0x000a +#define STM32_TRACEINTID_EPINQEMPTY 0x000b +#define STM32_TRACEINTID_EPOUTDONE 0x000c +#define STM32_TRACEINTID_EPOUTPENDING 0x000d +#define STM32_TRACEINTID_EPOUTQEMPTY 0x000e +#define STM32_TRACEINTID_ESOF 0x000f +#define STM32_TRACEINTID_GETCONFIG 0x0010 +#define STM32_TRACEINTID_GETSETDESC 0x0011 +#define STM32_TRACEINTID_GETSETIF 0x0012 +#define STM32_TRACEINTID_GETSTATUS 0x0013 +#define STM32_TRACEINTID_HPINTERRUPT 0x0014 +#define STM32_TRACEINTID_IFGETSTATUS 0x0015 +#define STM32_TRACEINTID_LPCTR 0x0016 +#define STM32_TRACEINTID_LPINTERRUPT 0x0017 +#define STM32_TRACEINTID_NOSTDREQ 0x0018 +#define STM32_TRACEINTID_RESET 0x0019 +#define STM32_TRACEINTID_SETCONFIG 0x001a +#define STM32_TRACEINTID_SETFEATURE 0x001b +#define STM32_TRACEINTID_SUSP 0x001c +#define STM32_TRACEINTID_SYNCHFRAME 0x001d +#define STM32_TRACEINTID_WKUP 0x001e + +/* Ever-present MIN and MAX macros */ + +#ifndef MIN +# define MIN(a,b) (a < b ? a : b) +#endif + +#ifndef MAX +# define MAX(a,b) (a > b ? a : b) +#endif + +/* Byte ordering in host-based values */ + +#ifdef CONFIG_ENDIAN_BIG +# define LSB 1 +# define MSB 0 +#else +# define LSB 0 +# define MSB 1 +#endif + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +/* The various states of a control pipe */ + +enum stm32_devstate_e +{ + DEVSTATE_IDLE = 0, /* No request in progress */ + DEVSTATE_RDREQUEST, /* Read request in progress */ + DEVSTATE_WRREQUEST, /* Write request in progress */ + DEVSTATE_STALLED /* We are stalled */ +}; + +/* Resume states */ + +enum stm32_rsmstate_e +{ + RSMSTATE_IDLE = 0, /* Device is either fully suspended or running */ + RSMSTATE_STARTED, /* Resume sequence has been started */ + RSMSTATE_WAITING /* Waiting (on ESOFs) for end of sequence */ +}; + +union wb_u +{ + uint16_t w; + uint8_t b[2]; +}; + +/* A container for a request so that the request make be retained in a list */ + +struct stm32_req_s +{ + struct usbdev_req_s req; /* Standard USB request */ + struct stm32_req_s *flink; /* Supports a singly linked list */ +}; + +/* This is the internal representation of an endpoint */ + +struct stm32_ep_s +{ + /* Common endpoint fields. This must be the first thing defined in the + * structure so that it is possible to simply cast from struct usbdev_ep_s + * to struct stm32_ep_s. + */ + + struct usbdev_ep_s ep; /* Standard endpoint structure */ + + /* STR71X-specific fields */ + + struct stm32_usbdev_s *dev; /* Reference to private driver data */ + struct stm32_req_s *head; /* Request list for this endpoint */ + struct stm32_req_s *tail; + uint8_t bufno; /* Allocated buffer number */ + uint8_t stalled:1; /* true: Endpoint is stalled */ + uint8_t halted:1; /* true: Endpoint feature halted */ + uint8_t txbusy:1; /* true: TX endpoint FIFO full */ + uint8_t txnullpkt:1; /* Null packet needed at end of transfer */ +}; + +struct stm32_usbdev_s +{ + /* Common device fields. This must be the first thing defined in the + * structure so that it is possible to simply cast from struct usbdev_s + * to structstm32_usbdev_s. + */ + + struct usbdev_s usbdev; + + /* The bound device class driver */ + + struct usbdevclass_driver_s *driver; + + /* STM32-specific fields */ + + struct usb_ctrlreq_s ctrl; /* Last EP0 request */ + uint8_t devstate; /* Driver state (see enum stm32_devstate_e) */ + uint8_t rsmstate; /* Resume state (see enum stm32_rsmstate_e) */ + uint8_t nesofs; /* ESOF counter (for resume support) */ + uint8_t rxpending:1; /* 1: OUT data in PMA, but no read requests */ + uint8_t selfpowered:1; /* 1: Device is self powered */ + uint8_t epavail; /* Bitset of available endpoints */ + uint8_t bufavail; /* Bitset of available buffers */ + uint16_t rxstatus; /* Saved during interrupt processing */ + uint16_t txstatus; /* " " " " " " " " */ + uint16_t imask; /* Current interrupt mask */ + + /* The endpoint list */ + + struct stm32_ep_s eplist[STM32_NENDPOINTS]; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Register operations ******************************************************/ + +#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG) +static uint16_t stm32_getreg(uint32_t addr); +static void stm32_putreg(uint16_t val, uint32_t addr); +static void stm32_checksetup(void); +static void stm32_dumpep(int epno); +#else +# define stm32_getreg(addr) getreg16(addr) +# define stm32_putreg(val,addr) putreg16(val,addr) +# define stm32_checksetup() +# define stm32_dumpep(epno) +#endif + +/* Low-Level Helpers ********************************************************/ + +static inline void + stm32_seteptxcount(uint8_t epno, uint16_t count); +static inline void + stm32_seteptxaddr(uint8_t epno, uint16_t addr); +static inline uint16_t + stm32_geteptxaddr(uint8_t epno); +static void stm32_seteprxcount(uint8_t epno, uint16_t count); +static inline uint16_t + stm32_geteprxcount(uint8_t epno); +static inline void + stm32_seteprxaddr(uint8_t epno, uint16_t addr); +static inline uint16_t + stm32_geteprxaddr(uint8_t epno); +static inline void + stm32_setepaddress(uint8_t epno, uint16_t addr); +static inline void + stm32_seteptype(uint8_t epno, uint16_t type); +static inline void + stm32_seteptxaddr(uint8_t epno, uint16_t addr); +static inline void + stm32_setstatusout(uint8_t epno); +static inline void + stm32_clrstatusout(uint8_t epno); +static void stm32_clrrxdtog(uint8_t epno); +static void stm32_clrtxdtog(uint8_t epno); +static void stm32_clrepctrrx(uint8_t epno); +static void stm32_clrepctrtx(uint8_t epno); +static void stm32_seteptxstatus(uint8_t epno, uint16_t state); +static void stm32_seteprxstatus(uint8_t epno, uint16_t state); +static inline uint16_t + stm32_geteptxstatus(uint8_t epno); +static inline uint16_t + stm32_geteprxstatus(uint8_t epno); +static bool stm32_eptxstalled(uint8_t epno); +static bool stm32_eprxstalled(uint8_t epno); +static void stm32_setimask(struct stm32_usbdev_s *priv, uint16_t setbits, + uint16_t clrbits); + +/* Suspend/Resume Helpers ***************************************************/ + +static void stm32_suspend(struct stm32_usbdev_s *priv); +static void stm32_initresume(struct stm32_usbdev_s *priv); +static void stm32_esofpoll(struct stm32_usbdev_s *priv) ; + +/* Request Helpers **********************************************************/ + +static void stm32_copytopma(const uint8_t *buffer, uint16_t pma, + uint16_t nbytes); +static inline void + stm32_copyfrompma(uint8_t *buffer, uint16_t pma, uint16_t nbytes); +static struct stm32_req_s * + stm32_rqdequeue(struct stm32_ep_s *privep); +static void stm32_rqenqueue(struct stm32_ep_s *privep, + struct stm32_req_s *req); +static inline void + stm32_abortrequest(struct stm32_ep_s *privep, + struct stm32_req_s *privreq, int16_t result); +static void stm32_reqcomplete(struct stm32_ep_s *privep, int16_t result); +static void stm32_epwrite(struct stm32_usbdev_s *buf, + struct stm32_ep_s *privep, const uint8_t *data, uint32_t nbytes); +static int stm32_wrrequest(struct stm32_usbdev_s *priv, + struct stm32_ep_s *privep); +static int stm32_rdrequest(struct stm32_usbdev_s *priv, + struct stm32_ep_s *privep); +static void stm32_cancelrequests(struct stm32_ep_s *privep); + +/* Interrupt level processing ***********************************************/ + +static void stm32_dispatchrequest(struct stm32_usbdev_s *priv); +static void stm32_epdone(struct stm32_usbdev_s *priv, uint8_t epno); +static void stm32_setdevaddr(struct stm32_usbdev_s *priv, uint8_t value); +static void stm32_ep0setup(struct stm32_usbdev_s *priv); +static void stm32_ep0out(struct stm32_usbdev_s *priv); +static void stm32_ep0in(struct stm32_usbdev_s *priv); +static inline void + stm32_ep0done(struct stm32_usbdev_s *priv, uint16_t istr); +static void stm32_lptransfer(struct stm32_usbdev_s *priv); +static int stm32_hpinterrupt(int irq, void *context); +static int stm32_lpinterrupt(int irq, void *context); + +/* Endpoint helpers *********************************************************/ + +static inline struct stm32_ep_s * + stm32_epreserve(struct stm32_usbdev_s *priv, uint8_t epset); +static inline void + stm32_epunreserve(struct stm32_usbdev_s *priv, + struct stm32_ep_s *privep); +static inline bool + stm32_epreserved(struct stm32_usbdev_s *priv, int epno); +static int stm32_epallocpma(struct stm32_usbdev_s *priv); +static inline void + stm32_epfreepma(struct stm32_usbdev_s *priv, + struct stm32_ep_s *privep); + +/* Endpoint operations ******************************************************/ + +static int stm32_epconfigure(struct usbdev_ep_s *ep, + const struct usb_epdesc_s *desc, bool last); +static int stm32_epdisable(struct usbdev_ep_s *ep); +static struct usbdev_req_s * + stm32_epallocreq(struct usbdev_ep_s *ep); +static void stm32_epfreereq(struct usbdev_ep_s *ep, + struct usbdev_req_s *); +static int stm32_epsubmit(struct usbdev_ep_s *ep, + struct usbdev_req_s *req); +static int stm32_epcancel(struct usbdev_ep_s *ep, + struct usbdev_req_s *req); +static int stm32_epstall(struct usbdev_ep_s *ep, bool resume); + +/* USB device controller operations *****************************************/ + +static struct usbdev_ep_s * + stm32_allocep(struct usbdev_s *dev, uint8_t epno, bool in, + uint8_t eptype); +static void stm32_freeep(struct usbdev_s *dev, struct usbdev_ep_s *ep); +static int stm32_getframe(struct usbdev_s *dev); +static int stm32_wakeup(struct usbdev_s *dev); +static int stm32_selfpowered(struct usbdev_s *dev, bool selfpowered); + +/* Initialization/Reset *****************************************************/ + +static void stm32_reset(struct stm32_usbdev_s *priv); +static void stm32_hwreset(struct stm32_usbdev_s *priv); +static void stm32_hwsetup(struct stm32_usbdev_s *priv); +static void stm32_hwshutdown(struct stm32_usbdev_s *priv); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Since there is only a single USB interface, all status information can be + * be simply retained in a single global instance. + */ + +static struct stm32_usbdev_s g_usbdev; + +static const struct usbdev_epops_s g_epops = +{ + .configure = stm32_epconfigure, + .disable = stm32_epdisable, + .allocreq = stm32_epallocreq, + .freereq = stm32_epfreereq, + .submit = stm32_epsubmit, + .cancel = stm32_epcancel, + .stall = stm32_epstall, +}; + +static const struct usbdev_ops_s g_devops = +{ + .allocep = stm32_allocep, + .freeep = stm32_freeep, + .getframe = stm32_getframe, + .wakeup = stm32_wakeup, + .selfpowered = stm32_selfpowered, + .pullup = stm32_usbpullup, +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Register Operations + ****************************************************************************/ +/**************************************************************************** + * Name: stm32_getreg + ****************************************************************************/ + +#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG) +static uint16_t stm32_getreg(uint32_t addr) +{ + static uint32_t prevaddr = 0; + static uint16_t preval = 0; + static uint32_t count = 0; + + /* Read the value from the register */ + + uint16_t val = getreg16(addr); + + /* Is this the same value that we read from the same register last time? + * Are we polling the register? If so, suppress some of the output. + */ + + if (addr == prevaddr && val == preval) + { + if (count == 0xffffffff || ++count > 3) + { + if (count == 4) + { + lldbg("...\n"); + } + return val; + } + } + + /* No this is a new address or value */ + + else + { + /* Did we print "..." for the previous value? */ + + if (count > 3) + { + /* Yes.. then show how many times the value repeated */ + + lldbg("[repeats %d more times]\n", count-3); + } + + /* Save the new address, value, and count */ + + prevaddr = addr; + preval = val; + count = 1; + } + + /* Show the register value read */ + + lldbg("%08x->%04x\n", addr, val); + return val; +} +#endif + +/**************************************************************************** + * Name: stm32_putreg + ****************************************************************************/ + +#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG) +static void stm32_putreg(uint16_t val, uint32_t addr) +{ + /* Show the register value being written */ + + lldbg("%08x<-%04x\n", addr, val); + + /* Write the value */ + + putreg16(val, addr); +} +#endif + +/**************************************************************************** + * Name: stm32_dumpep + ****************************************************************************/ + +#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG) +static void stm32_dumpep(int epno) +{ + uint32_t addr; + + /* Common registers */ + + lldbg("CNTR: %04x\n", getreg16(STM32_USB_CNTR)); + lldbg("ISTR: %04x\n", getreg16(STM32_USB_ISTR)); + lldbg("FNR: %04x\n", getreg16(STM32_USB_FNR)); + lldbg("DADDR: %04x\n", getreg16(STM32_USB_DADDR)); + lldbg("BTABLE: %04x\n", getreg16(STM32_USB_BTABLE)); + + /* Endpoint register */ + + addr = STM32_USB_EPR(epno); + lldbg("EPR%d: [%08x] %04x\n", epno, addr, getreg16(addr)); + + /* Endpoint descriptor */ + + addr = STM32_USB_BTABLE_ADDR(epno, 0); + lldbg("DESC: %08x\n", addr); + + /* Endpoint buffer descriptor */ + + addr = STM32_USB_ADDR_TX(epno); + lldbg(" TX ADDR: [%08x] %04x\n", addr, getreg16(addr)); + + addr = STM32_USB_COUNT_TX(epno); + lldbg(" COUNT: [%08x] %04x\n", addr, getreg16(addr)); + + addr = STM32_USB_ADDR_RX(epno); + lldbg(" RX ADDR: [%08x] %04x\n", addr, getreg16(addr)); + + addr = STM32_USB_COUNT_RX(epno); + lldbg(" COUNT: [%08x] %04x\n", addr, getreg16(addr)); +} +#endif + +/**************************************************************************** + * Name: stm32_checksetup + ****************************************************************************/ + +#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG) +static void stm32_checksetup(void) +{ + uint32_t cfgr = getreg32(STM32_RCC_CFGR); + uint32_t apb1rstr = getreg32(STM32_RCC_APB1RSTR); + uint32_t apb1enr = getreg32(STM32_RCC_APB1ENR); + + lldbg("CFGR: %08x APB1RSTR: %08x APB1ENR: %08x\n", cfgr, apb1rstr, apb1enr); + + if ((apb1rstr & RCC_APB1RSTR_USBRST) != 0 || + (apb1enr & RCC_APB1ENR_USBEN) == 0) + { + lldbg("ERROR: USB is NOT setup correctly\n"); + } +} +#endif + +/**************************************************************************** + * Low-Level Helpers + ****************************************************************************/ +/**************************************************************************** + * Name: stm32_seteptxcount + ****************************************************************************/ + +static inline void stm32_seteptxcount(uint8_t epno, uint16_t count) +{ + volatile uint32_t *epaddr = (uint32_t*)STM32_USB_COUNT_TX(epno); + *epaddr = count; +} + +/**************************************************************************** + * Name: stm32_seteptxaddr + ****************************************************************************/ + +static inline void stm32_seteptxaddr(uint8_t epno, uint16_t addr) +{ + volatile uint32_t *txaddr = (uint32_t*)STM32_USB_ADDR_TX(epno); + *txaddr = addr; +} + +/**************************************************************************** + * Name: stm32_geteptxaddr + ****************************************************************************/ + +static inline uint16_t stm32_geteptxaddr(uint8_t epno) +{ + volatile uint32_t *txaddr = (uint32_t*)STM32_USB_ADDR_TX(epno); + return (uint16_t)*txaddr; +} + +/**************************************************************************** + * Name: stm32_seteprxcount + ****************************************************************************/ + +static void stm32_seteprxcount(uint8_t epno, uint16_t count) +{ + volatile uint32_t *epaddr = (uint32_t*)STM32_USB_COUNT_RX(epno); + uint32_t rxcount = 0; + uint16_t nblocks; + + /* The upper bits of the RX COUNT value contain the size of allocated + * RX buffer. This is based on a block size of 2 or 32: + * + * USB_COUNT_RX_BL_SIZE not set: + * nblocks is in units of 2 bytes. + * 00000 - not allowed + * 00001 - 2 bytes + * .... + * 11111 - 62 bytes + * + * USB_COUNT_RX_BL_SIZE set: + * 00000 - 32 bytes + * 00001 - 64 bytes + * ... + * 01111 - 512 bytes + * 1xxxx - Not allowed + */ + + if (count > 62) + { + /* Blocks of 32 (with 0 meaning one block of 32) */ + + nblocks = (count >> 5) - 1 ; + DEBUGASSERT(nblocks <= 0x0f); + rxcount = (uint32_t)((nblocks << USB_COUNT_RX_NUM_BLOCK_SHIFT) | USB_COUNT_RX_BL_SIZE); + } + else if (count > 0) + { + /* Blocks of 2 (with 1 meaning one block of 2) */ + + nblocks = (count + 1) >> 1; + DEBUGASSERT(nblocks > 0 && nblocks < 0x1f); + rxcount = (uint32_t)(nblocks << USB_COUNT_RX_NUM_BLOCK_SHIFT); + } + *epaddr = rxcount; +} + +/**************************************************************************** + * Name: stm32_geteprxcount + ****************************************************************************/ + +static inline uint16_t stm32_geteprxcount(uint8_t epno) +{ + volatile uint32_t *epaddr = (uint32_t*)STM32_USB_COUNT_RX(epno); + return (*epaddr) & USB_COUNT_RX_MASK; +} + +/**************************************************************************** + * Name: stm32_seteprxaddr + ****************************************************************************/ + +static inline void stm32_seteprxaddr(uint8_t epno, uint16_t addr) +{ + volatile uint32_t *rxaddr = (uint32_t*)STM32_USB_ADDR_RX(epno); + *rxaddr = addr; +} + +/**************************************************************************** + * Name: stm32_seteprxaddr + ****************************************************************************/ + +static inline uint16_t stm32_geteprxaddr(uint8_t epno) +{ + volatile uint32_t *rxaddr = (uint32_t*)STM32_USB_ADDR_RX(epno); + return (uint16_t)*rxaddr; +} + +/**************************************************************************** + * Name: stm32_setepaddress + ****************************************************************************/ + +static inline void stm32_setepaddress(uint8_t epno, uint16_t addr) +{ + uint32_t epaddr = STM32_USB_EPR(epno); + uint16_t regval; + + regval = stm32_getreg(epaddr); + regval &= EPR_NOTOG_MASK; + regval &= ~USB_EPR_EA_MASK; + regval |= (addr << USB_EPR_EA_SHIFT); + stm32_putreg(regval, epaddr); +} + +/**************************************************************************** + * Name: stm32_seteptype + ****************************************************************************/ + +static inline void stm32_seteptype(uint8_t epno, uint16_t type) +{ + uint32_t epaddr = STM32_USB_EPR(epno); + uint16_t regval; + + regval = stm32_getreg(epaddr); + regval &= EPR_NOTOG_MASK; + regval &= ~USB_EPR_EPTYPE_MASK; + regval |= type; + stm32_putreg(regval, epaddr); +} + +/**************************************************************************** + * Name: stm32_setstatusout + ****************************************************************************/ + +static inline void stm32_setstatusout(uint8_t epno) +{ + uint32_t epaddr = STM32_USB_EPR(epno); + uint16_t regval; + + /* For a BULK endpoint the EP_KIND bit is used to enabled double buffering; + * for a CONTROL endpoint, it is set to indicate that a status OUT + * transaction is expected. The bit is not used with out endpoint types. + */ + + regval = stm32_getreg(epaddr); + regval &= EPR_NOTOG_MASK; + regval |= USB_EPR_EP_KIND; + stm32_putreg(regval, epaddr); +} + +/**************************************************************************** + * Name: stm32_clrstatusout + ****************************************************************************/ + +static inline void stm32_clrstatusout(uint8_t epno) +{ + uint32_t epaddr = STM32_USB_EPR(epno); + uint16_t regval; + + /* For a BULK endpoint the EP_KIND bit is used to enabled double buffering; + * for a CONTROL endpoint, it is set to indicate that a status OUT + * transaction is expected. The bit is not used with out endpoint types. + */ + + regval = stm32_getreg(epaddr); + regval &= EPR_NOTOG_MASK; + regval &= ~USB_EPR_EP_KIND; + stm32_putreg(regval, epaddr); +} + +/**************************************************************************** + * Name: stm32_clrrxdtog + ****************************************************************************/ + +static void stm32_clrrxdtog(uint8_t epno) +{ + uint32_t epaddr = STM32_USB_EPR(epno); + uint16_t regval; + + regval = stm32_getreg(epaddr); + if ((regval & USB_EPR_DTOG_RX) != 0) + { + regval &= EPR_NOTOG_MASK; + regval |= USB_EPR_DTOG_RX; + stm32_putreg(regval, epaddr); + } +} + +/**************************************************************************** + * Name: stm32_clrtxdtog + ****************************************************************************/ + +static void stm32_clrtxdtog(uint8_t epno) +{ + uint32_t epaddr = STM32_USB_EPR(epno); + uint16_t regval; + + regval = stm32_getreg(epaddr); + if ((regval & USB_EPR_DTOG_TX) != 0) + { + regval &= EPR_NOTOG_MASK; + regval |= USB_EPR_DTOG_TX; + stm32_putreg(regval, epaddr); + } +} + +/**************************************************************************** + * Name: stm32_clrepctrrx + ****************************************************************************/ + +static void stm32_clrepctrrx(uint8_t epno) +{ + uint32_t epaddr = STM32_USB_EPR(epno); + uint16_t regval; + + regval = stm32_getreg(epaddr); + regval &= EPR_NOTOG_MASK; + regval &= ~USB_EPR_CTR_RX; + stm32_putreg(regval, epaddr); +} + +/**************************************************************************** + * Name: stm32_clrepctrtx + ****************************************************************************/ + +static void stm32_clrepctrtx(uint8_t epno) +{ + uint32_t epaddr = STM32_USB_EPR(epno); + uint16_t regval; + + regval = stm32_getreg(epaddr); + regval &= EPR_NOTOG_MASK; + regval &= ~USB_EPR_CTR_TX; + stm32_putreg(regval, epaddr); +} + +/**************************************************************************** + * Name: stm32_geteptxstatus + ****************************************************************************/ + +static inline uint16_t stm32_geteptxstatus(uint8_t epno) +{ + return (uint16_t)(stm32_getreg(STM32_USB_EPR(epno)) & USB_EPR_STATTX_MASK); +} + +/**************************************************************************** + * Name: stm32_geteprxstatus + ****************************************************************************/ + +static inline uint16_t stm32_geteprxstatus(uint8_t epno) +{ + return (stm32_getreg(STM32_USB_EPR(epno)) & USB_EPR_STATRX_MASK); +} + +/**************************************************************************** + * Name: stm32_seteptxstatus + ****************************************************************************/ + +static void stm32_seteptxstatus(uint8_t epno, uint16_t state) +{ + uint32_t epaddr = STM32_USB_EPR(epno); + uint16_t regval; + + /* The bits in the STAT_TX field can be toggled by software to set their + * value. When set to 0, the value remains unchanged; when set to one, + * value toggles. + */ + + regval = stm32_getreg(epaddr); + + /* The exclusive OR will set STAT_TX bits to 1 if there value is different + * from the bits requested in 'state' + */ + + regval ^= state; + regval &= EPR_TXDTOG_MASK; + stm32_putreg(regval, epaddr); +} + +/**************************************************************************** + * Name: stm32_seteprxstatus + ****************************************************************************/ + +static void stm32_seteprxstatus(uint8_t epno, uint16_t state) +{ + uint32_t epaddr = STM32_USB_EPR(epno); + uint16_t regval; + + /* The bits in the STAT_RX field can be toggled by software to set their + * value. When set to 0, the value remains unchanged; when set to one, + * value toggles. + */ + + regval = stm32_getreg(epaddr); + + /* The exclusive OR will set STAT_RX bits to 1 if there value is different + * from the bits requested in 'state' + */ + + regval ^= state; + regval &= EPR_RXDTOG_MASK; + stm32_putreg(regval, epaddr); +} + +/**************************************************************************** + * Name: stm32_eptxstalled + ****************************************************************************/ + +static inline bool stm32_eptxstalled(uint8_t epno) +{ + return (stm32_geteptxstatus(epno) == USB_EPR_STATTX_STALL); +} + +/**************************************************************************** + * Name: stm32_eprxstalled + ****************************************************************************/ + +static inline bool stm32_eprxstalled(uint8_t epno) +{ + return (stm32_geteprxstatus(epno) == USB_EPR_STATRX_STALL); +} + +/**************************************************************************** + * Request Helpers + ****************************************************************************/ +/**************************************************************************** + * Name: stm32_copytopma + ****************************************************************************/ + +static void stm32_copytopma(const uint8_t *buffer, uint16_t pma, uint16_t nbytes) +{ + uint16_t *dest; + uint16_t ms; + uint16_t ls; + int nwords = (nbytes + 1) >> 1; + int i; + + /* Copy loop. Source=user buffer, Dest=packet memory */ + + dest = (uint16_t*)(STM32_USBCANRAM_BASE + ((uint32_t)pma << 1)); + for (i = nwords; i != 0; i--) + { + /* Read two bytes and pack into on 16-bit word */ + + ls = (uint16_t)(*buffer++); + ms = (uint16_t)(*buffer++); + *dest = ms << 8 | ls; + + /* Source address increments by 2*sizeof(uint8_t) = 2; Dest address + * increments by 2*sizeof(uint16_t) = 4. + */ + + dest += 2; + } +} + +/**************************************************************************** + * Name: stm32_copyfrompma + ****************************************************************************/ + +static inline void +stm32_copyfrompma(uint8_t *buffer, uint16_t pma, uint16_t nbytes) +{ + uint32_t *src; + int nwords = (nbytes + 1) >> 1; + int i; + + /* Copy loop. Source=packet memory, Dest=user buffer */ + + src = (uint32_t*)(STM32_USBCANRAM_BASE + ((uint32_t)pma << 1)); + for (i = nwords; i != 0; i--) + { + /* Copy 16-bits from packet memory to user buffer. */ + + *(uint16_t*)buffer = *src++; + + /* Source address increments by 1*sizeof(uint32_t) = 4; Dest address + * increments by 2*sizeof(uint8_t) = 2. + */ + + buffer += 2; + } +} + +/**************************************************************************** + * Name: stm32_rqdequeue + ****************************************************************************/ + +static struct stm32_req_s *stm32_rqdequeue(struct stm32_ep_s *privep) +{ + struct stm32_req_s *ret = privep->head; + + if (ret) + { + privep->head = ret->flink; + if (!privep->head) + { + privep->tail = NULL; + } + + ret->flink = NULL; + } + + return ret; +} + +/**************************************************************************** + * Name: stm32_rqenqueue + ****************************************************************************/ + +static void stm32_rqenqueue(struct stm32_ep_s *privep, struct stm32_req_s *req) +{ + req->flink = NULL; + if (!privep->head) + { + privep->head = req; + privep->tail = req; + } + else + { + privep->tail->flink = req; + privep->tail = req; + } +} + +/**************************************************************************** + * Name: stm32_abortrequest + ****************************************************************************/ + +static inline void +stm32_abortrequest(struct stm32_ep_s *privep, struct stm32_req_s *privreq, int16_t result) +{ + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_REQABORTED), (uint16_t)USB_EPNO(privep->ep.eplog)); + + /* Save the result in the request structure */ + + privreq->req.result = result; + + /* Callback to the request completion handler */ + + privreq->req.callback(&privep->ep, &privreq->req); +} + +/**************************************************************************** + * Name: stm32_reqcomplete + ****************************************************************************/ + +static void stm32_reqcomplete(struct stm32_ep_s *privep, int16_t result) +{ + struct stm32_req_s *privreq; + irqstate_t flags; + + /* Remove the completed request at the head of the endpoint request list */ + + flags = irqsave(); + privreq = stm32_rqdequeue(privep); + irqrestore(flags); + + if (privreq) + { + /* If endpoint 0, temporarily reflect the state of protocol stalled + * in the callback. + */ + + bool stalled = privep->stalled; + if (USB_EPNO(privep->ep.eplog) == EP0) + { + privep->stalled = (privep->dev->devstate == DEVSTATE_STALLED); + } + + /* Save the result in the request structure */ + + privreq->req.result = result; + + /* Callback to the request completion handler */ + + privreq->flink = NULL; + privreq->req.callback(&privep->ep, &privreq->req); + + /* Restore the stalled indication */ + + privep->stalled = stalled; + } +} + +/**************************************************************************** + * Name: tm32_epwrite + ****************************************************************************/ + +static void stm32_epwrite(struct stm32_usbdev_s *priv, + struct stm32_ep_s *privep, + const uint8_t *buf, uint32_t nbytes) +{ + uint8_t epno = USB_EPNO(privep->ep.eplog); + usbtrace(TRACE_WRITE(epno), nbytes); + + /* Check for a zero-length packet */ + + if (nbytes > 0) + { + /* Copy the data from the user buffer into packet memory for this + * endpoint + */ + + stm32_copytopma(buf, stm32_geteptxaddr(epno), nbytes); + } + + /* Send the packet (might be a null packet nbytes == 0) */ + + stm32_seteptxcount(epno, nbytes); + priv->txstatus = USB_EPR_STATTX_VALID; + + /* Indicate that there is data in the TX packet memory. This will be cleared + * when the next data out interrupt is received. + */ + + privep->txbusy = true; +} + +/**************************************************************************** + * Name: stm32_wrrequest + ****************************************************************************/ + +static int stm32_wrrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep) +{ + struct stm32_req_s *privreq; + uint8_t *buf; + uint8_t epno; + int nbytes; + int bytesleft; + + /* We get here when an IN endpoint interrupt occurs. So now we know that + * there is no TX transfer in progress. + */ + + privep->txbusy = false; + + /* Check the request from the head of the endpoint request queue */ + + privreq = stm32_rqpeek(privep); + if (!privreq) + { + /* There is no TX transfer in progress and no new pending TX + * requests to send. + */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPINQEMPTY), 0); + priv->devstate = DEVSTATE_IDLE; + return OK; + } + + epno = USB_EPNO(privep->ep.eplog); + ullvdbg("epno=%d req=%p: len=%d xfrd=%d nullpkt=%d\n", + epno, privreq, privreq->req.len, privreq->req.xfrd, privep->txnullpkt); + + /* Get the number of bytes left to be sent in the packet */ + + bytesleft = privreq->req.len - privreq->req.xfrd; + nbytes = bytesleft; + +#warning "REVISIT: If the EP supports double buffering, then we can do better" + + /* Send the next packet */ + + if (nbytes > 0) + { + /* Either send the maxpacketsize or all of the remaining data in + * the request. + */ + + privep->txnullpkt = 0; + if (nbytes >= privep->ep.maxpacket) + { + nbytes = privep->ep.maxpacket; + + /* Handle the case where this packet is exactly the + * maxpacketsize. Do we need to send a zero-length packet + * in this case? + */ + + if (bytesleft == privep->ep.maxpacket && + (privreq->req.flags & USBDEV_REQFLAGS_NULLPKT) != 0) + { + privep->txnullpkt = 1; + } + } + } + + /* Send the packet (might be a null packet nbytes == 0) */ + + buf = privreq->req.buf + privreq->req.xfrd; + stm32_epwrite(priv, privep, buf, nbytes); + priv->devstate = DEVSTATE_WRREQUEST; + + /* Update for the next data IN interrupt */ + + privreq->req.xfrd += nbytes; + bytesleft = privreq->req.len - privreq->req.xfrd; + + /* If all of the bytes were sent (including any final null packet) + * then we are finished with the transfer + */ + + if (bytesleft == 0 && !privep->txnullpkt) + { + usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)), privreq->req.xfrd); + privep->txnullpkt = 0; + stm32_reqcomplete(privep, OK); + priv->devstate = DEVSTATE_IDLE; + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_rdrequest + ****************************************************************************/ + +static int stm32_rdrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep) +{ + struct stm32_req_s *privreq; + uint32_t src; + uint8_t *dest; + uint8_t epno; + int pmalen; + int readlen; + + /* Check the request from the head of the endpoint request queue */ + + epno = USB_EPNO(privep->ep.eplog); + privreq = stm32_rqpeek(privep); + if (!privreq) + { + /* Incoming data available in PMA, but no packet to receive the data. + * Mark that the RX data is pending and hope that a packet is returned + * soon. + */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUTQEMPTY), epno); + return OK; + } + + ullvdbg("EP%d: len=%d xfrd=%d\n", epno, privreq->req.len, privreq->req.xfrd); + + /* Ignore any attempt to receive a zero length packet */ + + if (privreq->req.len == 0) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPOUTNULLPACKET), 0); + stm32_reqcomplete(privep, OK); + return OK; + } + + usbtrace(TRACE_READ(USB_EPNO(privep->ep.eplog)), privreq->req.xfrd); + + /* Get the source and destination transfer addresses */ + + dest = privreq->req.buf + privreq->req.xfrd; + src = stm32_geteprxaddr(epno); + + /* Get the number of bytes to read from packet memory */ + + pmalen = stm32_geteprxcount(epno); + readlen = MIN(privreq->req.len, pmalen); + + /* Receive the next packet */ + + stm32_copyfrompma(dest, src, readlen); + priv->devstate = DEVSTATE_RDREQUEST; + + /* If the receive buffer is full or this is a partial packet, + * then we are finished with the transfer + */ + + privreq->req.xfrd += readlen; + if (pmalen < privep->ep.maxpacket || privreq->req.xfrd >= privreq->req.len) + { + /* Complete the transfer and mark the state IDLE. The endpoint + * RX will be marked valid when the data phase completes. + */ + + usbtrace(TRACE_COMPLETE(epno), privreq->req.xfrd); + stm32_reqcomplete(privep, OK); + priv->devstate = DEVSTATE_IDLE; + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_cancelrequests + ****************************************************************************/ + +static void stm32_cancelrequests(struct stm32_ep_s *privep) +{ + while (!stm32_rqempty(privep)) + { + usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)), + (stm32_rqpeek(privep))->req.xfrd); + stm32_reqcomplete(privep, -ESHUTDOWN); + } +} + +/**************************************************************************** + * Interrupt Level Processing + ****************************************************************************/ +/**************************************************************************** + * Name: stm32_dispatchrequest + ****************************************************************************/ + +static void stm32_dispatchrequest(struct stm32_usbdev_s *priv) +{ + int ret; + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_DISPATCH), 0); + if (priv && priv->driver) + { + /* Forward to the control request to the class driver implementation */ + + ret = CLASS_SETUP(priv->driver, &priv->usbdev, &priv->ctrl, NULL, 0); + if (ret < 0) + { + /* Stall on failure */ + + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DISPATCHSTALL), 0); + priv->devstate = DEVSTATE_STALLED; + } + } +} + +/**************************************************************************** + * Name: stm32_epdone + ****************************************************************************/ + +static void stm32_epdone(struct stm32_usbdev_s *priv, uint8_t epno) +{ + struct stm32_ep_s *privep; + uint16_t epr; + + /* Decode and service non control endpoints interrupt */ + + epr = stm32_getreg(STM32_USB_EPR(epno)); + privep = &priv->eplist[epno]; + + /* OUT: host-to-device + * CTR_RX is set by the hardware when an OUT/SETUP transaction + * successfully completed on this endpoint. + */ + + if ((epr & USB_EPR_CTR_RX) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUTDONE), epr); + + /* Handle read requests. First check if a read request is available to + * accept the host data. + */ + + if (!stm32_rqempty(privep)) + { + /* Read host data into the current read request */ + + stm32_rdrequest(priv, privep); + + /* "After the received data is processed, the application software + * should set the STAT_RX bits to '11' (Valid) in the USB_EPnR, + * enabling further transactions. " + */ + + priv->rxstatus = USB_EPR_STATRX_VALID; + } + + /* NAK further OUT packets if there there no more read requests */ + + if (stm32_rqempty(privep)) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUTPENDING), (uint16_t)epno); + + /* Mark the RX processing as pending and NAK any OUT actions + * on this endpoint. "While the STAT_RX bits are equal to '10' + * (NAK), any OUT request addressed to that endpoint is NAKed, + * indicating a flow control condition: the USB host will retry + * the transaction until it succeeds." + */ + + priv->rxstatus = USB_EPR_STATRX_NAK; + priv->rxpending = true; + } + + /* Clear the interrupt status and set the new RX status */ + + stm32_clrepctrrx(epno); + stm32_seteprxstatus(epno, priv->rxstatus); + } + + /* IN: device-to-host + * CTR_TX is set when an IN transaction successfully completes on + * an endpoint + */ + + else if ((epr & USB_EPR_CTR_TX) != 0) + { + /* Clear interrupt status */ + + stm32_clrepctrtx(epno); + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPINDONE), epr); + + /* Handle write requests */ + + priv->txstatus = USB_EPR_STATTX_NAK; + stm32_wrrequest(priv, privep); + + /* Set the new TX status */ + + stm32_seteptxstatus(epno, priv->txstatus); + } +} + +/**************************************************************************** + * Name: stm32_setdevaddr + ****************************************************************************/ + +static void stm32_setdevaddr(struct stm32_usbdev_s *priv, uint8_t value) +{ + int epno; + + /* Set address in every allocated endpoint */ + + for (epno = 0; epno < STM32_NENDPOINTS; epno++) + { + if (stm32_epreserved(priv, epno)) + { + stm32_setepaddress((uint8_t)epno, (uint8_t)epno); + } + } + + /* Set the device address and enable function */ + + stm32_putreg(value|USB_DADDR_EF, STM32_USB_DADDR); +} + +/**************************************************************************** + * Name: stm32_ep0setup + ****************************************************************************/ + +static void stm32_ep0setup(struct stm32_usbdev_s *priv) +{ + struct stm32_ep_s *ep0 = &priv->eplist[EP0]; + struct stm32_req_s *privreq = stm32_rqpeek(ep0); + struct stm32_ep_s *privep; + union wb_u value; + union wb_u index; + union wb_u len; + union wb_u response; + bool handled = false; + uint8_t epno; + int nbytes = 0; /* Assume zero-length packet */ + int ret; + + /* Terminate any pending requests (doesn't work if the pending request + * was a zero-length transfer!) + */ + + while (!stm32_rqempty(ep0)) + { + int16_t result = OK; + if (privreq->req.xfrd != privreq->req.len) + { + result = -EPROTO; + } + + usbtrace(TRACE_COMPLETE(ep0->ep.eplog), privreq->req.xfrd); + stm32_reqcomplete(ep0, result); + } + + /* Assume NOT stalled; no TX in progress */ + + ep0->stalled = 0; + ep0->txbusy = 0; + + /* Get a 32-bit PMA address and use that to get the 8-byte setup request */ + + stm32_copyfrompma((uint8_t*)&priv->ctrl, stm32_geteprxaddr(EP0), USB_SIZEOF_CTRLREQ); + + /* And extract the little-endian 16-bit values to host order */ + + value.w = GETUINT16(priv->ctrl.value); + index.w = GETUINT16(priv->ctrl.index); + len.w = GETUINT16(priv->ctrl.len); + + ullvdbg("SETUP: type=%02x req=%02x value=%04x index=%04x len=%04x\n", + priv->ctrl.type, priv->ctrl.req, value.w, index.w, len.w); + + priv->devstate = DEVSTATE_IDLE; + + /* Dispatch any non-standard requests */ + + if ((priv->ctrl.type & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_NOSTDREQ), priv->ctrl.type); + + /* Let the class implementation handle all non-standar requests */ + + stm32_dispatchrequest(priv); + return; + } + + /* Handle standard request. Pick off the things of interest to the + * USB device controller driver; pass what is left to the class driver + */ + + switch (priv->ctrl.req) + { + case USB_REQ_GETSTATUS: + { + /* type: device-to-host; recipient = device, interface, endpoint + * value: 0 + * index: zero interface endpoint + * len: 2; data = status + */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETSTATUS), priv->ctrl.type); + if (len.w != 2 || (priv->ctrl.type & USB_REQ_DIR_IN) == 0 || + index.b[MSB] != 0 || value.w != 0) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPGETSTATUS), 0); + priv->devstate = DEVSTATE_STALLED; + } + else + { + switch (priv->ctrl.type & USB_REQ_RECIPIENT_MASK) + { + case USB_REQ_RECIPIENT_ENDPOINT: + { + epno = USB_EPNO(index.b[LSB]); + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPGETSTATUS), epno); + if (epno >= STM32_NENDPOINTS) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPGETSTATUS), epno); + priv->devstate = DEVSTATE_STALLED; + } + else + { + privep = &priv->eplist[epno]; + response.w = 0; /* Not stalled */ + nbytes = 2; /* Response size: 2 bytes */ + + if (USB_ISEPIN(index.b[LSB])) + { + /* IN endpoint */ + + if (stm32_eptxstalled(epno)) + { + /* IN Endpoint stalled */ + + response.b[LSB] = 1; /* Stalled */ + } + } + else + { + /* OUT endpoint */ + + if (stm32_eprxstalled(epno)) + { + /* OUT Endpoint stalled */ + + response.b[LSB] = 1; /* Stalled */ + } + } + } + } + break; + + case USB_REQ_RECIPIENT_DEVICE: + { + if (index.w == 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_DEVGETSTATUS), 0); + + /* Features: Remote Wakeup=YES; selfpowered=? */ + + response.w = 0; + response.b[LSB] = (priv->selfpowered << USB_FEATURE_SELFPOWERED) | + (1 << USB_FEATURE_REMOTEWAKEUP); + nbytes = 2; /* Response size: 2 bytes */ + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADDEVGETSTATUS), 0); + priv->devstate = DEVSTATE_STALLED; + } + } + break; + + case USB_REQ_RECIPIENT_INTERFACE: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_IFGETSTATUS), 0); + response.w = 0; + nbytes = 2; /* Response size: 2 bytes */ + } + break; + + default: + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETSTATUS), 0); + priv->devstate = DEVSTATE_STALLED; + } + break; + } + } + } + break; + + case USB_REQ_CLEARFEATURE: + { + /* type: host-to-device; recipient = device, interface or endpoint + * value: feature selector + * index: zero interface endpoint; + * len: zero, data = none + */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_CLEARFEATURE), priv->ctrl.type); + if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) != USB_REQ_RECIPIENT_ENDPOINT) + { + /* Let the class implementation handle all recipients (except for the + * endpoint recipient) + */ + + stm32_dispatchrequest(priv); + handled = true; + } + else + { + /* Endpoint recipient */ + + epno = USB_EPNO(index.b[LSB]); + if (epno < STM32_NENDPOINTS && index.b[MSB] == 0 && + value.w == USB_FEATURE_ENDPOINTHALT && len.w == 0) + { + privep = &priv->eplist[epno]; + privep->halted = 0; + ret = stm32_epstall(&privep->ep, true); + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADCLEARFEATURE), 0); + priv->devstate = DEVSTATE_STALLED; + } + } + } + break; + + case USB_REQ_SETFEATURE: + { + /* type: host-to-device; recipient = device, interface, endpoint + * value: feature selector + * index: zero interface endpoint; + * len: 0; data = none + */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETFEATURE), priv->ctrl.type); + if (((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE) && + value.w == USB_FEATURE_TESTMODE) + { + /* Special case recipient=device test mode */ + + ullvdbg("test mode: %d\n", index.w); + } + else if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) != USB_REQ_RECIPIENT_ENDPOINT) + { + /* The class driver handles all recipients except recipient=endpoint */ + + stm32_dispatchrequest(priv); + handled = true; + } + else + { + /* Handler recipient=endpoint */ + + epno = USB_EPNO(index.b[LSB]); + if (epno < STM32_NENDPOINTS && index.b[MSB] == 0 && + value.w == USB_FEATURE_ENDPOINTHALT && len.w == 0) + { + privep = &priv->eplist[epno]; + privep->halted = 1; + ret = stm32_epstall(&privep->ep, false); + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETFEATURE), 0); + priv->devstate = DEVSTATE_STALLED; + } + } + } + break; + + case USB_REQ_SETADDRESS: + { + /* type: host-to-device; recipient = device + * value: device address + * index: 0 + * len: 0; data = none + */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EP0SETUPSETADDRESS), value.w); + if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) != USB_REQ_RECIPIENT_DEVICE || + index.w != 0 || len.w != 0 || value.w > 127) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETADDRESS), 0); + priv->devstate = DEVSTATE_STALLED; + } + + /* Note that setting of the device address will be deferred. A zero-length + * packet will be sent and the device address will be set when the zero- + * length packet transfer completes. + */ + } + break; + + case USB_REQ_GETDESCRIPTOR: + /* type: device-to-host; recipient = device + * value: descriptor type and index + * index: 0 or language ID; + * len: descriptor len; data = descriptor + */ + case USB_REQ_SETDESCRIPTOR: + /* type: host-to-device; recipient = device + * value: descriptor type and index + * index: 0 or language ID; + * len: descriptor len; data = descriptor + */ + + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETSETDESC), priv->ctrl.type); + if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE) + { + /* The request seems valid... let the class implementation handle it */ + + stm32_dispatchrequest(priv); + handled = true; + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETSETDESC), 0); + priv->devstate = DEVSTATE_STALLED; + } + } + break; + + case USB_REQ_GETCONFIGURATION: + /* type: device-to-host; recipient = device + * value: 0; + * index: 0; + * len: 1; data = configuration value + */ + + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETCONFIG), priv->ctrl.type); + if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE && + value.w == 0 && index.w == 0 && len.w == 1) + { + /* The request seems valid... let the class implementation handle it */ + + stm32_dispatchrequest(priv); + handled = true; + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETCONFIG), 0); + priv->devstate = DEVSTATE_STALLED; + } + } + break; + + case USB_REQ_SETCONFIGURATION: + /* type: host-to-device; recipient = device + * value: configuration value + * index: 0; + * len: 0; data = none + */ + + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETCONFIG), priv->ctrl.type); + if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE && + index.w == 0 && len.w == 0) + { + /* The request seems valid... let the class implementation handle it */ + + stm32_dispatchrequest(priv); + handled = true; + } + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETCONFIG), 0); + priv->devstate = DEVSTATE_STALLED; + } + } + break; + + case USB_REQ_GETINTERFACE: + /* type: device-to-host; recipient = interface + * value: 0 + * index: interface; + * len: 1; data = alt interface + */ + case USB_REQ_SETINTERFACE: + /* type: host-to-device; recipient = interface + * value: alternate setting + * index: interface; + * len: 0; data = none + */ + + { + /* Let the class implementation handle the request */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETSETIF), priv->ctrl.type); + stm32_dispatchrequest(priv); + handled = true; + } + break; + + case USB_REQ_SYNCHFRAME: + /* type: device-to-host; recipient = endpoint + * value: 0 + * index: endpoint; + * len: 2; data = frame number + */ + + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SYNCHFRAME), 0); + } + break; + + default: + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDCTRLREQ), priv->ctrl.req); + priv->devstate = DEVSTATE_STALLED; + } + break; + } + + /* At this point, the request has been handled and there are three possible + * outcomes: + * + * 1. The setup request was successfully handled above and a response packet + * must be sent (may be a zero length packet). + * 2. The request was successfully handled by the class implementation. In + * case, the EP0 IN response has already been queued and the local variable + * 'handled' will be set to true and devstate != DEVSTATE_STALLED; + * 3. An error was detected in either the above logic or by the class implementation + * logic. In either case, priv->state will be set DEVSTATE_STALLED + * to indicate this case. + * + * NOTE: Non-standard requests are a special case. They are handled by the + * class implementation and this function returned early above, skipping this + * logic altogether. + */ + + if (priv->devstate != DEVSTATE_STALLED && !handled) + { + /* We will response. First, restrict the data length to the length + * requested in the setup packet + */ + + if (nbytes > len.w) + { + nbytes = len.w; + } + + /* Send the response (might be a zero-length packet) */ + + stm32_epwrite(priv, ep0, response.b, nbytes); + priv->devstate = DEVSTATE_IDLE; + } +} + +/**************************************************************************** + * Name: stm32_ep0in + ****************************************************************************/ + +static void stm32_ep0in(struct stm32_usbdev_s *priv) +{ + /* There is no longer anything in the EP0 TX packet memory */ + + priv->eplist[EP0].txbusy = false; + + /* Are we processing the completion of one packet of an outgoing request + * from the class driver? + */ + + if (priv->devstate == DEVSTATE_WRREQUEST) + { + stm32_wrrequest(priv, &priv->eplist[EP0]); + } + + /* No.. Are we processing the completion of a status response? */ + + else if (priv->devstate == DEVSTATE_IDLE) + { + /* Look at the saved SETUP command. Was it a SET ADDRESS request? + * If so, then now is the time to set the address. + */ + + if (priv->ctrl.req == USB_REQ_SETADDRESS && + (priv->ctrl.type & REQRECIPIENT_MASK) == (USB_REQ_TYPE_STANDARD | USB_REQ_RECIPIENT_DEVICE)) + { + union wb_u value; + value.w = GETUINT16(priv->ctrl.value); + stm32_setdevaddr(priv, value.b[LSB]); + } + } + else + { + priv->devstate = DEVSTATE_STALLED; + } +} + +/**************************************************************************** + * Name: stm32_ep0out + ****************************************************************************/ + +static void stm32_ep0out(struct stm32_usbdev_s *priv) +{ + struct stm32_ep_s *privep = &priv->eplist[EP0]; + switch (priv->devstate) + { + case DEVSTATE_RDREQUEST: /* Write request in progress */ + case DEVSTATE_IDLE: /* No transfer in progress */ + stm32_rdrequest(priv, privep); + break; + + default: + /* Unexpected state OR host aborted the OUT transfer before it + * completed, STALL the endpoint in either case + */ + + priv->devstate = DEVSTATE_STALLED; + break; + } +} + +/**************************************************************************** + * Name: stm32_ep0done + ****************************************************************************/ + +static inline void stm32_ep0done(struct stm32_usbdev_s *priv, uint16_t istr) +{ + uint16_t epr; + + /* Initialize RX and TX status. We shouldn't have to actually look at the + * status because the hardware is supposed to set the both RX and TX status + * to NAK when an EP0 SETUP occurs (of course, this might not be a setup) + */ + + priv->rxstatus = USB_EPR_STATRX_NAK; + priv->txstatus = USB_EPR_STATTX_NAK; + + /* Set both RX and TX status to NAK */ + + stm32_seteprxstatus(EP0, USB_EPR_STATRX_NAK); + stm32_seteptxstatus(EP0, USB_EPR_STATTX_NAK); + + /* Check the direction bit to determine if this the completion of an EP0 + * packet sent to or received from the host PC. + */ + + if ((istr & USB_ISTR_DIR) == 0) + { + /* EP0 IN: device-to-host (DIR=0) */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EP0IN), istr); + stm32_clrepctrtx(EP0); + stm32_ep0in(priv); + } + else + { + /* EP0 OUT: host-to-device (DIR=1) */ + + epr = stm32_getreg(STM32_USB_EPR(EP0)); + + /* CTR_TX is set when an IN transaction successfully + * completes on an endpoint + */ + + if ((epr & USB_EPR_CTR_TX) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EP0INDONE), epr); + stm32_clrepctrtx(EP0); + stm32_ep0in(priv); + } + + /* SETUP is set by the hardware when the last completed + * transaction was a control endpoint SETUP + */ + + else if ((epr & USB_EPR_SETUP) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EP0SETUPDONE), epr); + stm32_clrepctrrx(EP0); + stm32_ep0setup(priv); + } + + /* Set by the hardware when an OUT/SETUP transaction successfully + * completed on this endpoint. + */ + + else if ((epr & USB_EPR_CTR_RX) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EP0OUTDONE), epr); + stm32_clrepctrrx(EP0); + stm32_ep0out(priv); + } + + /* None of the above */ + + else + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0BADCTR), epr); + return; /* Does this ever happen? */ + } + } + + /* Make sure that the EP0 packet size is still OK (superstitious?) */ + + stm32_seteprxcount(EP0, STM32_EP0MAXPACKET); + + /* Now figure out the new RX/TX status. Here are all possible + * consequences of the above EP0 operations: + * + * rxstatus txstatus devstate MEANING + * -------- -------- --------- --------------------------------- + * NAK NAK IDLE Nothing happened + * NAK VALID IDLE EP0 response sent from USBDEV driver + * NAK VALID WRREQUEST EP0 response sent from class driver + * NAK --- STALL Some protocol error occurred + * + * First handle the STALL condition: + */ + + if (priv->devstate == DEVSTATE_STALLED) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0SETUPSTALLED), priv->devstate); + priv->rxstatus = USB_EPR_STATRX_STALL; + priv->txstatus = USB_EPR_STATTX_STALL; + } + + /* Was a transmission started? If so, txstatus will be VALID. The + * only special case to handle is when both are set to NAK. In that + * case, we need to set RX status to VALID in order to accept the next + * SETUP request. + */ + + else if (priv->rxstatus == USB_EPR_STATRX_NAK && + priv->txstatus == USB_EPR_STATTX_NAK) + { + priv->rxstatus = USB_EPR_STATRX_VALID; + } + + /* Now set the new TX and RX status */ + + stm32_seteprxstatus(EP0, priv->rxstatus); + stm32_seteptxstatus(EP0, priv->txstatus); +} + +/**************************************************************************** + * Name: stm32_lptransfer + ****************************************************************************/ + +static void stm32_lptransfer(struct stm32_usbdev_s *priv) +{ + uint8_t epno; + uint16_t istr; + + /* Stay in loop while LP interrupts are pending */ + + while (((istr = stm32_getreg(STM32_USB_ISTR)) & USB_ISTR_CTR) != 0) + { + stm32_putreg((uint16_t)~USB_ISTR_CTR, STM32_USB_ISTR); + + /* Extract highest priority endpoint number */ + + epno = (uint8_t)(istr & USB_ISTR_EPID_MASK); + + /* Handle EP0 completion events */ + + if (epno == 0) + { + stm32_ep0done(priv, istr); + } + + /* Handle other endpoint completion events */ + + else + { + stm32_epdone(priv, epno); + } + } +} + +/**************************************************************************** + * Name: stm32_hpinterrupt + ****************************************************************************/ + +static int stm32_hpinterrupt(int irq, void *context) +{ + /* For now there is only one USB controller, but we will always refer to + * it using a pointer to make any future ports to multiple USB controllers + * easier. + */ + + struct stm32_usbdev_s *priv = &g_usbdev; + uint16_t istr; + uint8_t epno; + + /* High priority interrupts are only triggered by a correct transfer event + * for isochronous and double-buffer bulk transfers. + */ + + istr = stm32_getreg(STM32_USB_ISTR); + usbtrace(TRACE_INTENTRY(STM32_TRACEINTID_HPINTERRUPT), istr); + while ((istr & USB_ISTR_CTR) != 0) + { + stm32_putreg((uint16_t)~USB_ISTR_CTR, STM32_USB_ISTR); + + /* Extract highest priority endpoint number */ + + epno = (uint8_t)(istr & USB_ISTR_EPID_MASK); + + /* And handle the completion event */ + + stm32_epdone(priv, epno); + + /* Fetch the status again for the next time through the loop */ + + istr = stm32_getreg(STM32_USB_ISTR); + } + + usbtrace(TRACE_INTEXIT(STM32_TRACEINTID_HPINTERRUPT), 0); + return OK; +} + +/**************************************************************************** + * Name: stm32_lpinterrupt + ****************************************************************************/ + +static int stm32_lpinterrupt(int irq, void *context) +{ + /* For now there is only one USB controller, but we will always refer to + * it using a pointer to make any future ports to multiple USB controllers + * easier. + */ + + struct stm32_usbdev_s *priv = &g_usbdev; + uint16_t istr = stm32_getreg(STM32_USB_ISTR); + + usbtrace(TRACE_INTENTRY(STM32_TRACEINTID_LPINTERRUPT), istr); + + /* Handle Reset interrupts. When this event occurs, the peripheral is left + * in the same conditions it is left by the system reset (but with the + * USB controller enabled). + */ + + if ((istr & USB_ISTR_RESET) != 0) + { + /* Reset interrupt received. Clear the RESET interrupt status. */ + + stm32_putreg(~USB_ISTR_RESET, STM32_USB_ISTR); + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_RESET), istr); + + /* Restore our power-up state and exit now because istr is no longer + * valid. + */ + + stm32_reset(priv); + goto exit_lpinterrupt; + } + + /* Handle Wakeup interrupts. This interrupt is only enable while the USB is + * suspended. + */ + + if ((istr & USB_ISTR_WKUP & priv->imask) != 0) + { + /* Wakeup interrupt received. Clear the WKUP interrupt status. The + * cause of the resume is indicated in the FNR register + */ + + stm32_putreg(~USB_ISTR_WKUP, STM32_USB_ISTR); + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_WKUP), stm32_getreg(STM32_USB_FNR)); + + /* Perform the wakeup action */ + + stm32_initresume(priv); + priv->rsmstate = RSMSTATE_IDLE; + + /* Disable ESOF polling, disable the wakeup interrupt, and + * re-enable the suspend interrupt. Clear any pending SUSP + * interrupts. + */ + + stm32_setimask(priv, USB_CNTR_SUSPM, USB_CNTR_ESOFM|USB_CNTR_WKUPM); + stm32_putreg(~USB_CNTR_SUSPM, STM32_USB_ISTR); + } + + if ((istr & USB_ISTR_SUSP & priv->imask) != 0) + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SUSP), 0); + stm32_suspend(priv); + + /* Clear of the ISTR bit must be done after setting of USB_CNTR_FSUSP */ + + stm32_putreg(~USB_ISTR_SUSP, STM32_USB_ISTR); + } + + if ((istr & USB_ISTR_ESOF & priv->imask) != 0) + { + stm32_putreg(~USB_ISTR_ESOF, STM32_USB_ISTR); + + /* Resume handling timing is made with ESOFs */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_ESOF), 0); + stm32_esofpoll(priv); + } + + if ((istr & USB_ISTR_CTR & priv->imask) != 0) + { + /* Low priority endpoint correct transfer interrupt */ + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_LPCTR), istr); + stm32_lptransfer(priv); + } + +exit_lpinterrupt: + usbtrace(TRACE_INTEXIT(STM32_TRACEINTID_LPINTERRUPT), stm32_getreg(STM32_USB_EP0R)); + return OK; +} + +/**************************************************************************** + * Name: stm32_setimask + ****************************************************************************/ + +static void +stm32_setimask(struct stm32_usbdev_s *priv, uint16_t setbits, uint16_t clrbits) +{ + uint16_t regval; + + /* Adjust the interrupt mask bits in the shadow copy first */ + + priv->imask &= ~clrbits; + priv->imask |= setbits; + + /* Then make the interrupt mask bits in the CNTR register match the shadow + * register (Hmmm... who is shadowing whom?) + */ + + regval = stm32_getreg(STM32_USB_CNTR); + regval &= ~USB_CNTR_ALLINTS; + regval |= priv->imask; + stm32_putreg(regval, STM32_USB_CNTR); +} + +/**************************************************************************** + * Suspend/Resume Helpers + ****************************************************************************/ +/**************************************************************************** + * Name: stm32_suspend + ****************************************************************************/ + +static void stm32_suspend(struct stm32_usbdev_s *priv) +{ + uint16_t regval; + + /* Disable ESOF polling, disable the SUSP interrupt, and enable the WKUP + * interrupt. Clear any pending WKUP interrupt. + */ + + stm32_setimask(priv, USB_CNTR_WKUPM, USB_CNTR_ESOFM|USB_CNTR_SUSPM); + stm32_putreg(~USB_ISTR_WKUP, STM32_USB_ISTR); + + /* Set the FSUSP bit in the CNTR register. This activates suspend mode + * within the USB peripheral and disables further SUSP interrupts. + */ + + regval = stm32_getreg(STM32_USB_CNTR); + regval |= USB_CNTR_FSUSP; + stm32_putreg(regval, STM32_USB_CNTR); + + /* If we are not a self-powered device, the got to low-power mode */ + + if (!priv->selfpowered) + { + /* Setting LPMODE in the CNTR register removes static power + * consumption in the USB analog transceivers but keeps them + * able to detect resume activity + */ + + regval = stm32_getreg(STM32_USB_CNTR); + regval |= USB_CNTR_LPMODE; + stm32_putreg(regval, STM32_USB_CNTR); + } + + /* Let the board-specific logic know that we have entered the suspend + * state + */ + + stm32_usbsuspend((struct usbdev_s *)priv, false); +} + +/**************************************************************************** + * Name: stm32_initresume + ****************************************************************************/ + +static void stm32_initresume(struct stm32_usbdev_s *priv) +{ + uint16_t regval; + + /* This function is called when either (1) a WKUP interrupt is received from + * the host PC, or (2) the class device implementation calls the wakeup() + * method. + */ + + /* Clear the USB low power mode (lower power mode was not set if this is + * a self-powered device. Also, low power mode is automatically cleared by + * hardware when a WKUP interrupt event occurs). + */ + + regval = stm32_getreg(STM32_USB_CNTR); + regval &= (~USB_CNTR_LPMODE); + stm32_putreg(regval, STM32_USB_CNTR); + + /* Restore full power -- whatever that means for this particular board */ + + stm32_usbsuspend((struct usbdev_s *)priv, true); + + /* Reset FSUSP bit and enable normal interrupt handling */ + + stm32_putreg(STM32_CNTR_SETUP, STM32_USB_CNTR); +} + +/**************************************************************************** + * Name: stm32_esofpoll + ****************************************************************************/ + +static void stm32_esofpoll(struct stm32_usbdev_s *priv) +{ + uint16_t regval; + + /* Called periodically from ESOF interrupt after RSMSTATE_STARTED */ + + switch (priv->rsmstate) + { + /* One ESOF after internal resume requested */ + + case RSMSTATE_STARTED: + regval = stm32_getreg(STM32_USB_CNTR); + regval |= USB_CNTR_RESUME; + stm32_putreg(regval, STM32_USB_CNTR); + priv->rsmstate = RSMSTATE_WAITING; + priv->nesofs = 10; + break; + + /* Countdown before completing the operation */ + + case RSMSTATE_WAITING: + priv->nesofs--; + if (priv->nesofs == 0) + { + /* Okay.. we are ready to resume normal operation */ + + regval = stm32_getreg(STM32_USB_CNTR); + regval &= (~USB_CNTR_RESUME); + stm32_putreg(regval, STM32_USB_CNTR); + priv->rsmstate = RSMSTATE_IDLE; + + /* Disable ESOF polling, disable the SUSP interrupt, and enable + * the WKUP interrupt. Clear any pending WKUP interrupt. + */ + + stm32_setimask(priv, USB_CNTR_WKUPM, USB_CNTR_ESOFM|USB_CNTR_SUSPM); + stm32_putreg(~USB_ISTR_WKUP, STM32_USB_ISTR); + } + break; + + case RSMSTATE_IDLE: + default: + priv->rsmstate = RSMSTATE_IDLE; + break; + } +} + +/**************************************************************************** + * Endpoint Helpers + ****************************************************************************/ +/**************************************************************************** + * Name: stm32_epreserve + ****************************************************************************/ + +static inline struct stm32_ep_s * +stm32_epreserve(struct stm32_usbdev_s *priv, uint8_t epset) +{ + struct stm32_ep_s *privep = NULL; + irqstate_t flags; + int epndx = 0; + + flags = irqsave(); + epset &= priv->epavail; + if (epset) + { + /* Select the lowest bit in the set of matching, available endpoints + * (skipping EP0) + */ + + for (epndx = 1; epndx < STM32_NENDPOINTS; epndx++) + { + uint8_t bit = STM32_ENDP_BIT(epndx); + if ((epset & bit) != 0) + { + /* Mark the endpoint no longer available */ + + priv->epavail &= ~bit; + + /* And return the pointer to the standard endpoint structure */ + + privep = &priv->eplist[epndx]; + break; + } + } + } + + irqrestore(flags); + return privep; +} + +/**************************************************************************** + * Name: stm32_epunreserve + ****************************************************************************/ + +static inline void +stm32_epunreserve(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep) +{ + irqstate_t flags = irqsave(); + priv->epavail |= STM32_ENDP_BIT(USB_EPNO(privep->ep.eplog)); + irqrestore(flags); +} + +/**************************************************************************** + * Name: stm32_epreserved + ****************************************************************************/ + +static inline bool +stm32_epreserved(struct stm32_usbdev_s *priv, int epno) +{ + return ((priv->epavail & STM32_ENDP_BIT(epno)) == 0); +} + +/**************************************************************************** + * Name: stm32_epallocpma + ****************************************************************************/ + +static int stm32_epallocpma(struct stm32_usbdev_s *priv) +{ + irqstate_t flags; + int bufno = ERROR; + int bufndx; + + flags = irqsave(); + for (bufndx = 2; bufndx < STM32_NBUFFERS; bufndx++) + { + /* Check if this buffer is available */ + + uint8_t bit = STM32_BUFFER_BIT(bufndx); + if ((priv->bufavail & bit) != 0) + { + /* Yes.. Mark the endpoint no longer available */ + + priv->bufavail &= ~bit; + + /* And return the index of the allocated buffer */ + + bufno = bufndx; + break; + } + } + + irqrestore(flags); + return bufno; +} + +/**************************************************************************** + * Name: stm32_epfreepma + ****************************************************************************/ + +static inline void +stm32_epfreepma(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep) +{ + irqstate_t flags = irqsave(); + priv->epavail |= STM32_ENDP_BIT(privep->bufno); + irqrestore(flags); +} + +/**************************************************************************** + * Endpoint operations + ****************************************************************************/ +/**************************************************************************** + * Name: stm32_epconfigure + ****************************************************************************/ + +static int stm32_epconfigure(struct usbdev_ep_s *ep, + const struct usb_epdesc_s *desc, + bool last) +{ + struct stm32_ep_s *privep = (struct stm32_ep_s *)ep; + uint16_t pma; + uint16_t setting; + uint16_t maxpacket; + uint8_t epno; + +#ifdef CONFIG_DEBUG + if (!ep || !desc) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + ulldbg("ERROR: ep=%p desc=%p\n"); + return -EINVAL; + } +#endif + + /* Get the unadorned endpoint address */ + + epno = USB_EPNO(desc->addr); + usbtrace(TRACE_EPCONFIGURE, (uint16_t)epno); + DEBUGASSERT(epno == USB_EPNO(ep->eplog)); + + /* Set the requested type */ + + switch (desc->attr & USB_EP_ATTR_XFERTYPE_MASK) + { + case USB_EP_ATTR_XFER_INT: /* Interrupt endpoint */ + setting = USB_EPR_EPTYPE_INTERRUPT; + break; + + case USB_EP_ATTR_XFER_BULK: /* Bulk endpoint */ + setting = USB_EPR_EPTYPE_BULK; + break; + + case USB_EP_ATTR_XFER_ISOC: /* Isochronous endpoint */ +#warning "REVISIT: Need to review isochronous EP setup" + setting = USB_EPR_EPTYPE_ISOC; + break; + + case USB_EP_ATTR_XFER_CONTROL: /* Control endpoint */ + setting = USB_EPR_EPTYPE_CONTROL; + break; + + default: + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPTYPE), (uint16_t)desc->type); + return -EINVAL; + } + + stm32_seteptype(epno, setting); + + /* Get the address of the PMA buffer allocated for this endpoint */ + +#warning "REVISIT: Should configure BULK EPs using double buffer feature" + pma = STM32_BUFNO2BUF(privep->bufno); + + /* Get the maxpacket size of the endpoint. */ + + maxpacket = GETUINT16(desc->mxpacketsize); + DEBUGASSERT(maxpacket <= STM32_MAXPACKET_SIZE); + ep->maxpacket = maxpacket; + + /* Get the subset matching the requested direction */ + + if (USB_ISEPIN(desc->addr)) + { + /* The full, logical EP number includes direction */ + + ep->eplog = USB_EPIN(epno); + + /* Set up TX; disable RX */ + + stm32_seteptxaddr(epno, pma); + stm32_seteptxstatus(epno, USB_EPR_STATTX_NAK); + stm32_seteprxstatus(epno, USB_EPR_STATRX_DIS); + } + else + { + /* The full, logical EP number includes direction */ + + ep->eplog = USB_EPOUT(epno); + + /* Set up RX; disable TX */ + + stm32_seteprxaddr(epno, pma); + stm32_seteprxcount(epno, maxpacket); + stm32_seteprxstatus(epno, USB_EPR_STATRX_VALID); + stm32_seteptxstatus(epno, USB_EPR_STATTX_DIS); + } + + stm32_dumpep(epno); + return OK; +} + +/**************************************************************************** + * Name: stm32_epdisable + ****************************************************************************/ + +static int stm32_epdisable(struct usbdev_ep_s *ep) +{ + struct stm32_ep_s *privep = (struct stm32_ep_s *)ep; + irqstate_t flags; + uint8_t epno; + +#ifdef CONFIG_DEBUG + if (!ep) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + ulldbg("ERROR: ep=%p\n", ep); + return -EINVAL; + } +#endif + + epno = USB_EPNO(ep->eplog); + usbtrace(TRACE_EPDISABLE, epno); + + /* Cancel any ongoing activity */ + + flags = irqsave(); + stm32_cancelrequests(privep); + + /* Disable TX; disable RX */ + + stm32_seteprxcount(epno, 0); + stm32_seteprxstatus(epno, USB_EPR_STATRX_DIS); + stm32_seteptxstatus(epno, USB_EPR_STATTX_DIS); + + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Name: stm32_epallocreq + ****************************************************************************/ + +static struct usbdev_req_s *stm32_epallocreq(struct usbdev_ep_s *ep) +{ + struct stm32_req_s *privreq; + +#ifdef CONFIG_DEBUG + if (!ep) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return NULL; + } +#endif + usbtrace(TRACE_EPALLOCREQ, USB_EPNO(ep->eplog)); + + privreq = (struct stm32_req_s *)malloc(sizeof(struct stm32_req_s)); + if (!privreq) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_ALLOCFAIL), 0); + return NULL; + } + + memset(privreq, 0, sizeof(struct stm32_req_s)); + return &privreq->req; +} + +/**************************************************************************** + * Name: stm32_epfreereq + ****************************************************************************/ + +static void stm32_epfreereq(struct usbdev_ep_s *ep, struct usbdev_req_s *req) +{ + struct stm32_req_s *privreq = (struct stm32_req_s*)req; + +#ifdef CONFIG_DEBUG + if (!ep || !req) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return; + } +#endif + usbtrace(TRACE_EPFREEREQ, USB_EPNO(ep->eplog)); + + free(privreq); +} + +/**************************************************************************** + * Name: stm32_epsubmit + ****************************************************************************/ + +static int stm32_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req) +{ + struct stm32_req_s *privreq = (struct stm32_req_s *)req; + struct stm32_ep_s *privep = (struct stm32_ep_s *)ep; + struct stm32_usbdev_s *priv; + irqstate_t flags; + uint8_t epno; + int ret = OK; + +#ifdef CONFIG_DEBUG + if (!req || !req->callback || !req->buf || !ep) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + ulldbg("ERROR: req=%p callback=%p buf=%p ep=%p\n", req, req->callback, req->buf, ep); + return -EINVAL; + } +#endif + + usbtrace(TRACE_EPSUBMIT, USB_EPNO(ep->eplog)); + priv = privep->dev; + +#ifdef CONFIG_DEBUG + if (!priv->driver) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_NOTCONFIGURED), priv->usbdev.speed); + ulldbg("ERROR: driver=%p\n", priv->driver); + return -ESHUTDOWN; + } +#endif + + /* Handle the request from the class driver */ + + epno = USB_EPNO(ep->eplog); + req->result = -EINPROGRESS; + req->xfrd = 0; + flags = irqsave(); + + /* If we are stalled, then drop all requests on the floor */ + + if (privep->stalled) + { + stm32_abortrequest(privep, privreq, -EBUSY); + ulldbg("ERROR: stalled\n"); + ret = -EBUSY; + } + + /* Handle IN (device-to-host) requests. NOTE: If the class device is + * using the bi-directional EP0, then we assume that they intend the EP0 + * IN functionality. + */ + + else if (USB_ISEPIN(ep->eplog) || epno == EP0) + { + /* Add the new request to the request queue for the IN endpoint */ + + stm32_rqenqueue(privep, privreq); + usbtrace(TRACE_INREQQUEUED(epno), req->len); + + /* If the IN endpoint FIFO is available, then transfer the data now */ + + if (!privep->txbusy) + { + priv->txstatus = USB_EPR_STATTX_NAK; + ret = stm32_wrrequest(priv, privep); + + /* Set the new TX status */ + + stm32_seteptxstatus(epno, priv->txstatus); + } + } + + /* Handle OUT (host-to-device) requests */ + + else + { + /* Add the new request to the request queue for the OUT endpoint */ + + privep->txnullpkt = 0; + stm32_rqenqueue(privep, privreq); + usbtrace(TRACE_OUTREQQUEUED(epno), req->len); + + /* This there a incoming data pending the availability of a request? */ + + if (priv->rxpending) + { + /* Set STAT_RX bits to '11' in the USB_EPnR, enabling further + * transactions. "While the STAT_RX bits are equal to '10' + * (NAK), any OUT request addressed to that endpoint is NAKed, + * indicating a flow control condition: the USB host will retry + * the transaction until it succeeds." + */ + + priv->rxstatus = USB_EPR_STATRX_VALID; + stm32_seteprxstatus(epno, priv->rxstatus); + + /* Data is no longer pending */ + + priv->rxpending = false; + } + } + + irqrestore(flags); + return ret; +} + +/**************************************************************************** + * Name: stm32_epcancel + ****************************************************************************/ + +static int stm32_epcancel(struct usbdev_ep_s *ep, struct usbdev_req_s *req) +{ + struct stm32_ep_s *privep = (struct stm32_ep_s *)ep; + struct stm32_usbdev_s *priv; + irqstate_t flags; + +#ifdef CONFIG_DEBUG + if (!ep || !req) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } +#endif + usbtrace(TRACE_EPCANCEL, USB_EPNO(ep->eplog)); + priv = privep->dev; + + flags = irqsave(); + stm32_cancelrequests(privep); + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Name: stm32_epstall + ****************************************************************************/ + +static int stm32_epstall(struct usbdev_ep_s *ep, bool resume) +{ + struct stm32_ep_s *privep; + struct stm32_usbdev_s *priv; + uint8_t epno = USB_EPNO(ep->eplog); + uint16_t status; + irqstate_t flags; + +#ifdef CONFIG_DEBUG + if (!ep) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } +#endif + privep = (struct stm32_ep_s *)ep; + priv = (struct stm32_usbdev_s *)privep->dev; + epno = USB_EPNO(ep->eplog); + + /* STALL or RESUME the endpoint */ + + flags = irqsave(); + usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, USB_EPNO(ep->eplog)); + + /* Get status of the endpoint; stall the request if the endpoint is + * disabled + */ + + if (USB_ISEPIN(ep->eplog)) + { + status = stm32_geteptxstatus(epno); + } + else + { + status = stm32_geteprxstatus(epno); + } + + if (status == 0) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPDISABLED), 0); + priv->devstate = DEVSTATE_STALLED; + return -ENODEV; + } + + /* Handle the resume condition */ + + if (resume) + { + /* Resuming a stalled endpoint */ + + usbtrace(TRACE_EPRESUME, epno); + privep->stalled = false; + + if (USB_ISEPIN(ep->eplog)) + { + /* IN endpoint */ + + if (stm32_eptxstalled(epno)) + { + stm32_clrtxdtog(epno); + + /* Restart any queued write requests */ + + priv->txstatus = USB_EPR_STATTX_NAK; + (void)stm32_wrrequest(priv, privep); + + /* Set the new TX status */ + + stm32_seteptxstatus(epno, priv->txstatus); + } + } + else + { + /* OUT endpoint */ + + if (stm32_eprxstalled(epno)) + { + if (epno == EP0) + { + /* After clear the STALL, enable the default endpoint receiver */ + + stm32_seteprxcount(epno, ep->maxpacket); + } + else + { + stm32_clrrxdtog(epno); + } + + priv->rxstatus = USB_EPR_STATRX_VALID; + stm32_seteprxstatus(epno, USB_EPR_STATRX_VALID); + } + } + } + + /* Handle the stall condition */ + + else + { + usbtrace(TRACE_EPSTALL, epno); + privep->stalled = true; + + if (USB_ISEPIN(ep->eplog)) + { + /* IN endpoint */ + + priv->txstatus = USB_EPR_STATTX_STALL; + stm32_seteptxstatus(epno, USB_EPR_STATTX_STALL); + } + else + { + /* OUT endpoint */ + + priv->rxstatus = USB_EPR_STATRX_STALL; + stm32_seteprxstatus(epno, USB_EPR_STATRX_STALL); + } + } + + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Device Controller Operations + ****************************************************************************/ +/**************************************************************************** + * Name: stm32_allocep + ****************************************************************************/ + +static struct usbdev_ep_s *stm32_allocep(struct usbdev_s *dev, uint8_t epno, + bool in, uint8_t eptype) +{ + struct stm32_usbdev_s *priv = (struct stm32_usbdev_s *)dev; + struct stm32_ep_s *privep = NULL; + uint8_t epset = STM32_ENDP_ALLSET; + int bufno; + + usbtrace(TRACE_DEVALLOCEP, (uint16_t)epno); +#ifdef CONFIG_DEBUG + if (!dev) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return NULL; + } +#endif + + /* Ignore any direction bits in the logical address */ + + epno = USB_EPNO(epno); + + /* A logical address of 0 means that any endpoint will do */ + + if (epno > 0) + { + /* Otherwise, we will return the endpoint structure only for the requested + * 'logical' endpoint. All of the other checks will still be performed. + * + * First, verify that the logical endpoint is in the range supported by + * by the hardware. + */ + + if (epno >= STM32_NENDPOINTS) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPNO), (uint16_t)epno); + return NULL; + } + + /* Convert the logical address to a physical OUT endpoint address and + * remove all of the candidate endpoints from the bitset except for the + * the IN/OUT pair for this logical address. + */ + + epset = STM32_ENDP_BIT(epno); + } + + /* Check if the selected endpoint number is available */ + + privep = stm32_epreserve(priv, epset); + if (!privep) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPRESERVE), (uint16_t)epset); + goto errout; + } + epno = USB_EPNO(privep->ep.eplog); + + /* Allocate a PMA buffer for this endpoint */ + +#warning "REVISIT: Should configure BULK EPs using double buffer feature" + bufno = stm32_epallocpma(priv); + if (bufno < 0) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPBUFFER), 0); + goto errout_with_ep; + } + privep->bufno = (uint8_t)bufno; + return &privep->ep; + +errout_with_ep: + stm32_epunreserve(priv, privep); +errout: + return NULL; +} + +/**************************************************************************** + * Name: stm32_freeep + ****************************************************************************/ + +static void stm32_freeep(struct usbdev_s *dev, struct usbdev_ep_s *ep) +{ + struct stm32_usbdev_s *priv; + struct stm32_ep_s *privep; + +#ifdef CONFIG_DEBUG + if (!dev || !ep) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return; + } +#endif + priv = (struct stm32_usbdev_s *)dev; + privep = (struct stm32_ep_s *)ep; + usbtrace(TRACE_DEVFREEEP, (uint16_t)USB_EPNO(ep->eplog)); + + if (priv && privep) + { + /* Free the PMA buffer assigned to this endpoint */ + + stm32_epfreepma(priv, privep); + + /* Mark the endpoint as available */ + + stm32_epunreserve(priv, privep); + } +} + +/**************************************************************************** + * Name: stm32_getframe + ****************************************************************************/ + +static int stm32_getframe(struct usbdev_s *dev) +{ + uint16_t fnr; + +#ifdef CONFIG_DEBUG + if (!dev) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } +#endif + + /* Return the last frame number detected by the hardware */ + + fnr = stm32_getreg(STM32_USB_FNR); + usbtrace(TRACE_DEVGETFRAME, fnr); + return (fnr & USB_FNR_FN_MASK); +} + +/**************************************************************************** + * Name: stm32_wakeup + ****************************************************************************/ + +static int stm32_wakeup(struct usbdev_s *dev) +{ + struct stm32_usbdev_s *priv = (struct stm32_usbdev_s *)dev; + irqstate_t flags; + + usbtrace(TRACE_DEVWAKEUP, 0); +#ifdef CONFIG_DEBUG + if (!dev) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } +#endif + + /* Start the resume sequence. The actual resume steps will be driven + * by the ESOF interrupt. + */ + + flags = irqsave(); + stm32_initresume(priv); + priv->rsmstate = RSMSTATE_STARTED; + + /* Disable the SUSP interrupt (until we are fully resumed), disable + * the WKUP interrupt (we are already waking up), and enable the + * ESOF interrupt that will drive the resume operations. Clear any + * pending ESOF interrupt. + */ + + stm32_setimask(priv, USB_CNTR_ESOFM, USB_CNTR_WKUPM|USB_CNTR_SUSPM); + stm32_putreg(~USB_ISTR_ESOF, STM32_USB_ISTR); + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Name: stm32_selfpowered + ****************************************************************************/ + +static int stm32_selfpowered(struct usbdev_s *dev, bool selfpowered) +{ + struct stm32_usbdev_s *priv = (struct stm32_usbdev_s *)dev; + + usbtrace(TRACE_DEVSELFPOWERED, (uint16_t)selfpowered); + +#ifdef CONFIG_DEBUG + if (!dev) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return -ENODEV; + } +#endif + + priv->selfpowered = selfpowered; + return OK; +} + +/**************************************************************************** + * Initialization/Reset + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_reset + ****************************************************************************/ + +static void stm32_reset(struct stm32_usbdev_s *priv) +{ + int epno; + + /* Put the USB controller in reset, disable all interrupts */ + + stm32_putreg(USB_CNTR_FRES, STM32_USB_CNTR); + + /* Tell the class driver that we are disconnected. The class driver + * should then accept any new configurations. + */ + + CLASS_DISCONNECT(priv->driver, &priv->usbdev); + + /* Reset the device state structure */ + + priv->devstate = DEVSTATE_IDLE; + priv->rsmstate = RSMSTATE_IDLE; + priv->rxpending = false; + + /* Reset endpoints */ + + for (epno = 0; epno < STM32_NENDPOINTS; epno++) + { + struct stm32_ep_s *privep = &priv->eplist[epno]; + + /* Cancel any queued requests. Since they are canceled + * with status -ESHUTDOWN, then will not be requeued + * until the configuration is reset. NOTE: This should + * not be necessary... the CLASS_DISCONNECT above should + * result in the class implementation calling stm32_epdisable + * for each of its configured endpoints. + */ + + stm32_cancelrequests(privep); + + /* Reset endpoint status */ + + privep->stalled = false; + privep->halted = false; + privep->txbusy = false; + privep->txnullpkt = false; + } + + /* Re-configure the USB controller in its initial, unconnected state */ + + stm32_hwreset(priv); + priv->usbdev.speed = USB_SPEED_FULL; +} + +/**************************************************************************** + * Name: stm32_hwreset + ****************************************************************************/ + +static void stm32_hwreset(struct stm32_usbdev_s *priv) +{ + /* Put the USB controller into reset, clear all interrupt enables */ + + stm32_putreg(USB_CNTR_FRES, STM32_USB_CNTR); + + /* Disable interrupts (and perhaps take the USB controller out of reset) */ + + priv->imask = 0; + stm32_putreg(priv->imask, STM32_USB_CNTR); + + /* Set the STM32 BTABLE address */ + + stm32_putreg(STM32_BTABLE_ADDRESS & 0xfff8, STM32_USB_BTABLE); + + /* Initialize EP0 */ + + stm32_seteptype(EP0, USB_EPR_EPTYPE_CONTROL); + stm32_seteptxstatus(EP0, USB_EPR_STATTX_NAK); + stm32_seteprxaddr(EP0, STM32_EP0_RXADDR); + stm32_seteprxcount(EP0, STM32_EP0MAXPACKET); + stm32_seteptxaddr(EP0, STM32_EP0_TXADDR); + stm32_clrstatusout(EP0); + stm32_seteprxstatus(EP0, USB_EPR_STATRX_VALID); + + /* Set the device to respond on default address */ + + stm32_setdevaddr(priv, 0); + + /* Clear any pending interrupts */ + + stm32_putreg(0, STM32_USB_ISTR); + + /* Enable interrupts at the USB controller */ + + stm32_setimask(priv, STM32_CNTR_SETUP, (USB_CNTR_ALLINTS & ~STM32_CNTR_SETUP)); + stm32_dumpep(EP0); +} + +/**************************************************************************** + * Name: stm32_hwsetup + ****************************************************************************/ + +static void stm32_hwsetup(struct stm32_usbdev_s *priv) +{ + int epno; + + /* Power the USB controller, put the USB controller into reset, disable + * all USB interrupts + */ + + stm32_putreg(USB_CNTR_FRES|USB_CNTR_PDWN, STM32_USB_CNTR); + + /* Disconnect the device / disable the pull-up. We don't want the + * host to enumerate us until the class driver is registered. + */ + + stm32_usbpullup(&priv->usbdev, false); + + /* Initialize the device state structure. NOTE: many fields + * have the initial value of zero and, hence, are not explicitly + * initialized here. + */ + + memset(priv, 0, sizeof(struct stm32_usbdev_s)); + priv->usbdev.ops = &g_devops; + priv->usbdev.ep0 = &priv->eplist[EP0].ep; + priv->epavail = STM32_ENDP_ALLSET & ~STM32_ENDP_BIT(EP0); + priv->bufavail = STM32_BUFFER_ALLSET & ~STM32_BUFFER_EP0; + + /* Initialize the endpoint list */ + + for (epno = 0; epno < STM32_NENDPOINTS; epno++) + { + /* Set endpoint operations, reference to driver structure (not + * really necessary because there is only one controller), and + * the (physical) endpoint number which is just the index to the + * endpoint. + */ + + priv->eplist[epno].ep.ops = &g_epops; + priv->eplist[epno].dev = priv; + priv->eplist[epno].ep.eplog = epno; + + /* We will use a fixed maxpacket size for all endpoints (perhaps + * ISOC endpoints could have larger maxpacket???). A smaller + * packet size can be selected when the endpoint is configured. + */ + + priv->eplist[epno].ep.maxpacket = STM32_MAXPACKET_SIZE; + } + + /* Select a smaller endpoint size for EP0 */ + +#if STM32_EP0MAXPACKET < STM32_MAXPACKET_SIZE + priv->eplist[EP0].ep.maxpacket = STM32_EP0MAXPACKET; +#endif + + /* Configure the USB controller. USB uses the following GPIO pins: + * + * PA9 - VBUS + * PA10 - ID + * PA11 - DM + * PA12 - DP + * + * "As soon as the USB is enabled, these pins [DM and DP] are connected to + * the USB internal transceiver automatically." + */ + + /* Power up the USB controller, holding it in reset. There is a delay of + * about 1uS after applying power before the USB will behave predictably. + * A 5MS delay is more than enough. NOTE that we leave the USB controller + * in the reset state; the hardware will not be initialized until the + * class driver has been bound. + */ + + stm32_putreg(USB_CNTR_FRES, STM32_USB_CNTR); + up_mdelay(5); +} + +/**************************************************************************** + * Name: stm32_hwshutdown + ****************************************************************************/ + +static void stm32_hwshutdown(struct stm32_usbdev_s *priv) +{ + priv->usbdev.speed = USB_SPEED_UNKNOWN; + + /* Disable all interrupts and force the USB controller into reset */ + + stm32_putreg(USB_CNTR_FRES, STM32_USB_CNTR); + + /* Clear any pending interrupts */ + + stm32_putreg(0, STM32_USB_ISTR); + + /* Disconnect the device / disable the pull-up */ + + stm32_usbpullup(&priv->usbdev, false); + + /* Power down the USB controller */ + + stm32_putreg(USB_CNTR_FRES|USB_CNTR_PDWN, STM32_USB_CNTR); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: up_usbinitialize + * Description: + * Initialize the USB driver + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void up_usbinitialize(void) +{ + /* For now there is only one USB controller, but we will always refer to + * it using a pointer to make any future ports to multiple USB controllers + * easier. + */ + + struct stm32_usbdev_s *priv = &g_usbdev; + + usbtrace(TRACE_DEVINIT, 0); + stm32_checksetup(); + + /* Power up the USB controller, but leave it in the reset state */ + + stm32_hwsetup(priv); + + /* Attach USB controller interrupt handlers. The hardware will not be + * initialized and interrupts will not be enabled until the class device + * driver is bound. Getting the IRQs here only makes sure that we have + * them when we need them later. + */ + + if (irq_attach(STM32_IRQ_USBHPCANTX, stm32_hpinterrupt) != 0) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_IRQREGISTRATION), + (uint16_t)STM32_IRQ_USBHPCANTX); + goto errout; + } + + if (irq_attach(STM32_IRQ_USBLPCANRX0, stm32_lpinterrupt) != 0) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_IRQREGISTRATION), + (uint16_t)STM32_IRQ_USBLPCANRX0); + goto errout; + } + return; + +errout: + up_usbuninitialize(); +} + +/**************************************************************************** + * Name: up_usbuninitialize + * Description: + * Initialize the USB driver + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void up_usbuninitialize(void) +{ + /* For now there is only one USB controller, but we will always refer to + * it using a pointer to make any future ports to multiple USB controllers + * easier. + */ + + struct stm32_usbdev_s *priv = &g_usbdev; + irqstate_t flags; + + flags = irqsave(); + usbtrace(TRACE_DEVUNINIT, 0); + + /* Disable and detach the USB IRQs */ + + up_disable_irq(STM32_IRQ_USBHPCANTX); + up_disable_irq(STM32_IRQ_USBLPCANRX0); + irq_detach(STM32_IRQ_USBHPCANTX); + irq_detach(STM32_IRQ_USBLPCANRX0); + + if (priv->driver) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DRIVERREGISTERED), 0); + usbdev_unregister(priv->driver); + } + + /* Put the hardware in an inactive state */ + + stm32_hwshutdown(priv); + irqrestore(flags); +} + +/**************************************************************************** + * Name: usbdev_register + * + * Description: + * Register a USB device class driver. The class driver's bind() method will be + * called to bind it to a USB device driver. + * + ****************************************************************************/ + +int usbdev_register(struct usbdevclass_driver_s *driver) +{ + /* For now there is only one USB controller, but we will always refer to + * it using a pointer to make any future ports to multiple USB controllers + * easier. + */ + + struct stm32_usbdev_s *priv = &g_usbdev; + int ret; + + usbtrace(TRACE_DEVREGISTER, 0); + +#ifdef CONFIG_DEBUG + if (!driver || !driver->ops->bind || !driver->ops->unbind || + !driver->ops->disconnect || !driver->ops->setup) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } + + if (priv->driver) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DRIVER), 0); + return -EBUSY; + } +#endif + + /* First hook up the driver */ + + priv->driver = driver; + + /* Then bind the class driver */ + + ret = CLASS_BIND(driver, &priv->usbdev); + if (ret) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BINDFAILED), (uint16_t)-ret); + priv->driver = NULL; + } + else + { + /* Setup the USB controller -- enabling interrupts at the USB controller */ + + stm32_hwreset(priv); + + /* Enable USB controller interrupts at the NVIC */ + + up_enable_irq(STM32_IRQ_USBHPCANTX); + up_enable_irq(STM32_IRQ_USBLPCANRX0); + + /* Set the interrrupt priority */ + + up_prioritize_irq(STM32_IRQ_USBHPCANTX, CONFIG_USB_PRI); + up_prioritize_irq(STM32_IRQ_USBLPCANRX0, CONFIG_USB_PRI); + + /* Enable pull-up to connect the device. The host should enumerate us + * some time after this + */ + + stm32_usbpullup(&priv->usbdev, true); + priv->usbdev.speed = USB_SPEED_FULL; + } + return ret; +} + +/**************************************************************************** + * Name: usbdev_unregister + * + * Description: + * Un-register usbdev class driver. If the USB device is connected to a + * USB host, it will first disconnect(). The driver is also requested to + * unbind() and clean up any device state, before this procedure finally + * returns. + * + ****************************************************************************/ + +int usbdev_unregister(struct usbdevclass_driver_s *driver) +{ + /* For now there is only one USB controller, but we will always refer to + * it using a pointer to make any future ports to multiple USB controllers + * easier. + */ + + struct stm32_usbdev_s *priv = &g_usbdev; + irqstate_t flags; + + usbtrace(TRACE_DEVUNREGISTER, 0); + +#ifdef CONFIG_DEBUG + if (driver != priv->driver) + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } +#endif + + /* Reset the hardware and cancel all requests. All requests must be + * canceled while the class driver is still bound. + */ + + flags = irqsave(); + stm32_reset(priv); + + /* Unbind the class driver */ + + CLASS_UNBIND(driver, &priv->usbdev); + + /* Disable USB controller interrupts (but keep them attached) */ + + up_disable_irq(STM32_IRQ_USBHPCANTX); + up_disable_irq(STM32_IRQ_USBLPCANRX0); + + /* Put the hardware in an inactive state. Then bring the hardware back up + * in the reset state (this is probably not necessary, the stm32_reset() + * call above was probably sufficient). + */ + + stm32_hwshutdown(priv); + stm32_hwsetup(priv); + + /* Unhook the driver */ + + priv->driver = NULL; + irqrestore(flags); + return OK; +} + +#endif /* CONFIG_USBDEV && CONFIG_STM32_USB */ diff --git a/nuttx/arch/arm/src/stm32/stm32_usbdev.h b/nuttx/arch/arm/src/stm32/stm32_usbdev.h new file mode 100644 index 0000000000..a1af471b25 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_usbdev.h @@ -0,0 +1,98 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_usbdev.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_USBDEV_H +#define __ARCH_ARM_SRC_STM32_STM32_USBDEV_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include + +#include "chip.h" +#include "chip/stm32_usbdev.h" + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Name: stm32_usbpullup + * + * Description: + * If USB is supported and the board supports a pullup via GPIO (for USB software + * connect and disconnect), then the board software must provide stm32_pullup. + * See include/nuttx/usb/usbdev.h for additional description of this method. + * Alternatively, if no pull-up GPIO the following EXTERN can be redefined to be + * NULL. + * + ************************************************************************************/ + +EXTERN int stm32_usbpullup(FAR struct usbdev_s *dev, bool enable); + +/************************************************************************************ + * Name: stm32_usbsuspend + * + * Description: + * Board logic must provide the stm32_usbsuspend logic if the USBDEV driver is + * used. This function is called whenever the USB enters or leaves suspend mode. + * This is an opportunity for the board logic to shutdown clocks, power, etc. + * while the USB is suspended. + * + ************************************************************************************/ + +EXTERN void stm32_usbsuspend(FAR struct usbdev_s *dev, bool resume); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_USBDEV_H */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_usbhost.c b/nuttx/arch/arm/src/stm32/stm32_usbhost.c new file mode 100644 index 0000000000..4bf6d646da --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_usbhost.c @@ -0,0 +1,2695 @@ +/******************************************************************************* + * arch/arm/src/stm32/stm32_usbhost.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +/******************************************************************************* + * Included Files + *******************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "chip.h" /* Includes default GPIO settings */ +#include /* May redefine GPIO settings */ + +#include "up_arch.h" +#include "up_internal.h" + +#include "stm32_usbhost.h" + +/******************************************************************************* + * Definitions + *******************************************************************************/ + +/* Configuration ***************************************************************/ + +/* All I/O buffers must lie in AHB SRAM because of the OHCI DMA. It might be + * okay if no I/O buffers are used *IF* the application can guarantee that all + * end-user I/O buffers reside in AHB SRAM. + */ + +#if STM32_IOBUFFERS < 1 +# warning "No IO buffers allocated" +#endif + +/* OHCI Setup ******************************************************************/ +/* Frame Interval / Periodic Start */ + +#define BITS_PER_FRAME 12000 +#define FI (BITS_PER_FRAME-1) +#define FSMPS ((6 * (FI - 210)) / 7) +#define DEFAULT_FMINTERVAL ((FSMPS << OHCI_FMINT_FSMPS_SHIFT) | FI) +#define DEFAULT_PERSTART (((9 * BITS_PER_FRAME) / 10) - 1) + +/* CLKCTRL enable bits */ + +#define STM32_CLKCTRL_ENABLES (USBOTG_CLK_HOSTCLK|USBOTG_CLK_PORTSELCLK|USBOTG_CLK_AHBCLK) + +/* Interrupt enable bits */ + +#ifdef CONFIG_DEBUG_USB +# define STM32_DEBUG_INTS (OHCI_INT_SO|OHCI_INT_RD|OHCI_INT_UE|OHCI_INT_OC) +#else +# define STM32_DEBUG_INTS 0 +#endif + +#define STM32_NORMAL_INTS (OHCI_INT_WDH|OHCI_INT_RHSC) +#define STM32_ALL_INTS (STM32_NORMAL_INTS|STM32_DEBUG_INTS) + +/* Dump GPIO registers */ + +#if defined(CONFIG_STM32_USBHOST_REGDEBUG) && defined(CONFIG_DEBUG_GPIO) +# define usbhost_dumpgpio() \ + do { \ + stm32_dumpgpio(GPIO_USB_DP, "D+ P0.29; D- P0.30"); \ + stm32_dumpgpio(GPIO_USB_UPLED, "LED P1:18; PPWR P1:19 PWRD P1:22 PVRCR P1:27"); \ + } while (0); +#else +# define usbhost_dumpgpio() +#endif + +/* USB Host Memory *************************************************************/ + +/* Helper definitions */ + +#define HCCA ((struct ohci_hcca_s *)STM32_HCCA_BASE) +#define TDTAIL ((struct stm32_gtd_s *)STM32_TDTAIL_ADDR) +#define EDCTRL ((struct stm32_ed_s *)STM32_EDCTRL_ADDR) + +/* Periodic intervals 2, 4, 8, 16,and 32 supported */ + +#define MIN_PERINTERVAL 2 +#define MAX_PERINTERVAL 32 + +/* Descriptors *****************************************************************/ + +/* TD delay interrupt value */ + +#define TD_DELAY(n) (uint32_t)((n) << GTD_STATUS_DI_SHIFT) + +/******************************************************************************* + * Private Types + *******************************************************************************/ + +/* This structure retains the state of the USB host controller */ + +struct stm32_usbhost_s +{ + /* Common device fields. This must be the first thing defined in the + * structure so that it is possible to simply cast from struct usbhost_s + * to structstm32_usbhost_s. + */ + + struct usbhost_driver_s drvr; + + /* The bound device class driver */ + + struct usbhost_class_s *class; + + /* Driver status */ + + volatile bool connected; /* Connected to device */ + volatile bool lowspeed; /* Low speed device attached. */ + volatile bool rhswait; /* TRUE: Thread is waiting for Root Hub Status change */ +#ifndef CONFIG_USBHOST_INT_DISABLE + uint8_t ininterval; /* Minimum periodic IN EP polling interval: 2, 4, 6, 16, or 32 */ + uint8_t outinterval; /* Minimum periodic IN EP polling interval: 2, 4, 6, 16, or 32 */ +#endif + sem_t exclsem; /* Support mutually exclusive access */ + sem_t rhssem; /* Semaphore to wait Writeback Done Head event */ +}; + +/* The OCHI expects the size of an endpoint descriptor to be 16 bytes. + * However, the size allocated for an endpoint descriptor is 32 bytes in + * stm32_ohciram.h. This extra 16-bytes is used by the OHCI host driver in + * order to maintain additional endpoint-specific data. + */ + +struct stm32_ed_s +{ + /* Hardware specific fields */ + + struct ohci_ed_s hw; + + /* Software specific fields */ + + uint8_t xfrtype; /* Transfer type. See SB_EP_ATTR_XFER_* in usb.h */ + uint8_t interval; /* Periodic EP polling interval: 2, 4, 6, 16, or 32 */ + volatile uint8_t tdstatus; /* TD control status bits from last Writeback Done Head event */ + volatile bool wdhwait; /* TRUE: Thread is waiting for WDH interrupt */ + sem_t wdhsem; /* Semaphore used to wait for Writeback Done Head event */ + /* Unused bytes follow, depending on the size of sem_t */ +}; + +/* The OCHI expects the size of an transfer descriptor to be 16 bytes. + * However, the size allocated for an endpoint descriptor is 32 bytes in + * stm32_ohciram.h. This extra 16-bytes is used by the OHCI host driver in + * order to maintain additional endpoint-specific data. + */ + +struct stm32_gtd_s +{ + /* Hardware specific fields */ + + struct ohci_gtd_s hw; + + /* Software specific fields */ + + struct stm32_ed_s *ed; /* Pointer to parent ED */ + uint8_t pad[12]; +}; + +/* The following is used to manage lists of free EDs, TDs, and TD buffers */ + +struct stm32_list_s +{ + struct stm32_list_s *flink; /* Link to next buffer in the list */ + /* Variable length buffer data follows */ +}; + +/******************************************************************************* + * Private Function Prototypes + *******************************************************************************/ + +/* Register operations ********************************************************/ + +#ifdef CONFIG_STM32_USBHOST_REGDEBUG +static void stm32_printreg(uint32_t addr, uint32_t val, bool iswrite); +static void stm32_checkreg(uint32_t addr, uint32_t val, bool iswrite); +static uint32_t stm32_getreg(uint32_t addr); +static void stm32_putreg(uint32_t val, uint32_t addr); +#else +# define stm32_getreg(addr) getreg32(addr) +# define stm32_putreg(val,addr) putreg32(val,addr) +#endif + +/* Semaphores ******************************************************************/ + +static void stm32_takesem(sem_t *sem); +#define stm32_givesem(s) sem_post(s); + +/* Byte stream access helper functions *****************************************/ + +static inline uint16_t stm32_getle16(const uint8_t *val); +static void stm32_putle16(uint8_t *dest, uint16_t val); + +/* OHCI memory pool helper functions *******************************************/ + +static inline void stm32_edfree(struct stm32_ed_s *ed); +static struct stm32_gtd_s *stm32_tdalloc(void); +static void stm32_tdfree(struct stm32_gtd_s *buffer); +static uint8_t *stm32_tballoc(void); +static void stm32_tbfree(uint8_t *buffer); +#if STM32_IOBUFFERS > 0 +static uint8_t *stm32_allocio(void); +static void stm32_freeio(uint8_t *buffer); +#endif + +/* ED list helper functions ****************************************************/ + +static inline int stm32_addbulked(struct stm32_usbhost_s *priv, + struct stm32_ed_s *ed); +static inline int stm32_rembulked(struct stm32_usbhost_s *priv, + struct stm32_ed_s *ed); + +#if !defined(CONFIG_USBHOST_INT_DISABLE) || !defined(CONFIG_USBHOST_ISOC_DISABLE) +static unsigned int stm32_getinterval(uint8_t interval); +static void stm32_setinttab(uint32_t value, unsigned int interval, unsigned int offset); +#endif + +static inline int stm32_addinted(struct stm32_usbhost_s *priv, + const FAR struct usbhost_epdesc_s *epdesc, + struct stm32_ed_s *ed); +static inline int stm32_reminted(struct stm32_usbhost_s *priv, + struct stm32_ed_s *ed); + +static inline int stm32_addisoced(struct stm32_usbhost_s *priv, + const FAR struct usbhost_epdesc_s *epdesc, + struct stm32_ed_s *ed); +static inline int stm32_remisoced(struct stm32_usbhost_s *priv, + struct stm32_ed_s *ed); + +/* Descriptor helper functions *************************************************/ + +static int stm32_enqueuetd(struct stm32_usbhost_s *priv, + struct stm32_ed_s *ed, uint32_t dirpid, + uint32_t toggle, volatile uint8_t *buffer, + size_t buflen); +static int stm32_ctrltd(struct stm32_usbhost_s *priv, uint32_t dirpid, + uint8_t *buffer, size_t buflen); + +/* Interrupt handling **********************************************************/ + +static int stm32_usbinterrupt(int irq, FAR void *context); + +/* USB host controller operations **********************************************/ + +static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected); +static int stm32_enumerate(FAR struct usbhost_driver_s *drvr); +static int stm32_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, + uint16_t maxpacketsize); +static int stm32_epalloc(FAR struct usbhost_driver_s *drvr, + const FAR struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep); +static int stm32_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep); +static int stm32_alloc(FAR struct usbhost_driver_s *drvr, + FAR uint8_t **buffer, FAR size_t *maxlen); +static int stm32_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer); +static int stm32_ioalloc(FAR struct usbhost_driver_s *drvr, + FAR uint8_t **buffer, size_t buflen); +static int stm32_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer); +static int stm32_ctrlin(FAR struct usbhost_driver_s *drvr, + FAR const struct usb_ctrlreq_s *req, + FAR uint8_t *buffer); +static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr, + FAR const struct usb_ctrlreq_s *req, + FAR const uint8_t *buffer); +static int stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, + FAR uint8_t *buffer, size_t buflen); +static void stm32_disconnect(FAR struct usbhost_driver_s *drvr); + +/* Initialization **************************************************************/ + +static inline void stm32_ep0init(struct stm32_usbhost_s *priv); + +/******************************************************************************* + * Private Data + *******************************************************************************/ + +/* In this driver implementation, support is provided for only a single a single + * USB device. All status information can be simply retained in a single global + * instance. + */ + +static struct stm32_usbhost_s g_usbhost = +{ + .drvr = + { + .wait = stm32_wait, + .enumerate = stm32_enumerate, + .ep0configure = stm32_ep0configure, + .epalloc = stm32_epalloc, + .epfree = stm32_epfree, + .alloc = stm32_alloc, + .free = stm32_free, + .ioalloc = stm32_ioalloc, + .iofree = stm32_iofree, + .ctrlin = stm32_ctrlin, + .ctrlout = stm32_ctrlout, + .transfer = stm32_transfer, + .disconnect = stm32_disconnect, + }, + .class = NULL, +}; + +/* This is a free list of EDs and TD buffers */ + +static struct stm32_list_s *g_edfree; /* List of unused EDs */ +static struct stm32_list_s *g_tdfree; /* List of unused TDs */ +static struct stm32_list_s *g_tbfree; /* List of unused transfer buffers */ +#if STM32_IOBUFFERS > 0 +static struct stm32_list_s *g_iofree; /* List of unused I/O buffers */ +#endif + +/******************************************************************************* + * Public Data + *******************************************************************************/ + +/******************************************************************************* + * Private Functions + *******************************************************************************/ + +/******************************************************************************* + * Name: stm32_printreg + * + * Description: + * Print the contents of an STM32xx register operation + * + *******************************************************************************/ + +#ifdef CONFIG_STM32_USBHOST_REGDEBUG +static void stm32_printreg(uint32_t addr, uint32_t val, bool iswrite) +{ + lldbg("%08x%s%08x\n", addr, iswrite ? "<-" : "->", val); +} +#endif + +/******************************************************************************* + * Name: stm32_checkreg + * + * Description: + * Get the contents of an STM32 register + * + *******************************************************************************/ + +#ifdef CONFIG_STM32_USBHOST_REGDEBUG +static void stm32_checkreg(uint32_t addr, uint32_t val, bool iswrite) +{ + static uint32_t prevaddr = 0; + static uint32_t preval = 0; + static uint32_t count = 0; + static bool prevwrite = false; + + /* Is this the same value that we read from/wrote to the same register last time? + * Are we polling the register? If so, suppress the output. + */ + + if (addr == prevaddr && val == preval && prevwrite == iswrite) + { + /* Yes.. Just increment the count */ + + count++; + } + else + { + /* No this is a new address or value or operation. Were there any + * duplicate accesses before this one? + */ + + if (count > 0) + { + /* Yes.. Just one? */ + + if (count == 1) + { + /* Yes.. Just one */ + + stm32_printreg(prevaddr, preval, prevwrite); + } + else + { + /* No.. More than one. */ + + lldbg("[repeats %d more times]\n", count); + } + } + + /* Save the new address, value, count, and operation for next time */ + + prevaddr = addr; + preval = val; + count = 0; + prevwrite = iswrite; + + /* Show the new regisgter access */ + + stm32_printreg(addr, val, iswrite); + } +} +#endif + +/******************************************************************************* + * Name: stm32_getreg + * + * Description: + * Get the contents of an STM32 register + * + *******************************************************************************/ + +#ifdef CONFIG_STM32_USBHOST_REGDEBUG +static uint32_t stm32_getreg(uint32_t addr) +{ + /* Read the value from the register */ + + uint32_t val = getreg32(addr); + + /* Check if we need to print this value */ + + stm32_checkreg(addr, val, false); + return val; +} +#endif + +/******************************************************************************* + * Name: stm32_putreg + * + * Description: + * Set the contents of an STM32 register to a value + * + *******************************************************************************/ + +#ifdef CONFIG_STM32_USBHOST_REGDEBUG +static void stm32_putreg(uint32_t val, uint32_t addr) +{ + /* Check if we need to print this value */ + + stm32_checkreg(addr, val, true); + + /* Write the value */ + + putreg32(val, addr); +} +#endif + +/**************************************************************************** + * Name: stm32_takesem + * + * Description: + * This is just a wrapper to handle the annoying behavior of semaphore + * waits that return due to the receipt of a signal. + * + *******************************************************************************/ + +static void stm32_takesem(sem_t *sem) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(sem) != 0) + { + /* The only case that an error should occr here is if the wait was + * awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Name: stm32_getle16 + * + * Description: + * Get a (possibly unaligned) 16-bit little endian value. + * + *******************************************************************************/ + +static inline uint16_t stm32_getle16(const uint8_t *val) +{ + return (uint16_t)val[1] << 8 | (uint16_t)val[0]; +} + +/**************************************************************************** + * Name: stm32_putle16 + * + * Description: + * Put a (possibly unaligned) 16-bit little endian value. + * + *******************************************************************************/ + +static void stm32_putle16(uint8_t *dest, uint16_t val) +{ + dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */ + dest[1] = val >> 8; +} + +/******************************************************************************* + * Name: stm32_edfree + * + * Description: + * Return an endpoint descriptor to the free list + * + *******************************************************************************/ + +static inline void stm32_edfree(struct stm32_ed_s *ed) +{ + struct stm32_list_s *entry = (struct stm32_list_s *)ed; + + /* Put the ED back into the free list */ + + entry->flink = g_edfree; + g_edfree = entry; +} + +/******************************************************************************* + * Name: stm32_tdalloc + * + * Description: + * Allocate an transfer descriptor from the free list + * + * Assumptions: + * - Never called from an interrupt handler. + * - Protected from conconcurrent access to the TD pool by the interrupt + * handler + * - Protection from re-entrance must be assured by the caller + * + *******************************************************************************/ + +static struct stm32_gtd_s *stm32_tdalloc(void) +{ + struct stm32_gtd_s *ret; + irqstate_t flags; + + /* Disable interrupts momentarily so that stm32_tdfree is not called from the + * interrupt handler. + */ + + flags = irqsave(); + ret = (struct stm32_gtd_s *)g_tdfree; + if (ret) + { + g_tdfree = ((struct stm32_list_s*)ret)->flink; + } + + irqrestore(flags); + return ret; +} + +/******************************************************************************* + * Name: stm32_tdfree + * + * Description: + * Return an transfer descriptor to the free list + * + * Assumptions: + * - Only called from the WDH interrupt handler (and during initialization). + * - Interrupts are disabled in any case. + * + *******************************************************************************/ + +static void stm32_tdfree(struct stm32_gtd_s *td) +{ + struct stm32_list_s *tdfree = (struct stm32_list_s *)td; + + /* This should not happen but just to be safe, don't free the common, pre- + * allocated tail TD. + */ + + if (tdfree != NULL && td != TDTAIL) + { + tdfree->flink = g_tdfree; + g_tdfree = tdfree; + } +} + +/******************************************************************************* + * Name: stm32_tballoc + * + * Description: + * Allocate an request/descriptor transfer buffer from the free list + * + * Assumptions: + * - Never called from an interrupt handler. + * - Protection from re-entrance must be assured by the caller + * + *******************************************************************************/ + +static uint8_t *stm32_tballoc(void) +{ + uint8_t *ret = (uint8_t *)g_tbfree; + if (ret) + { + g_tbfree = ((struct stm32_list_s*)ret)->flink; + } + return ret; +} + +/******************************************************************************* + * Name: stm32_tbfree + * + * Description: + * Return an request/descriptor transfer buffer to the free list + * + *******************************************************************************/ + +static void stm32_tbfree(uint8_t *buffer) +{ + struct stm32_list_s *tbfree = (struct stm32_list_s *)buffer; + + if (tbfree) + { + tbfree->flink = g_tbfree; + g_tbfree = tbfree; + } +} + +/******************************************************************************* + * Name: stm32_allocio + * + * Description: + * Allocate an IO buffer from the free list + * + * Assumptions: + * - Never called from an interrupt handler. + * - Protection from re-entrance must be assured by the caller + * + *******************************************************************************/ + +#if STM32_IOBUFFERS > 0 +static uint8_t *stm32_allocio(void) +{ + uint8_t *ret = (uint8_t *)g_iofree; + if (ret) + { + g_iofree = ((struct stm32_list_s*)ret)->flink; + } + return ret; +} +#endif + +/******************************************************************************* + * Name: stm32_freeio + * + * Description: + * Return an TD buffer to the free list + * + *******************************************************************************/ + +#if STM32_IOBUFFERS > 0 +static void stm32_freeio(uint8_t *buffer) +{ + struct stm32_list_s *iofree = (struct stm32_list_s *)buffer; + iofree->flink = g_iofree; + g_iofree = iofree; +} +#endif + +/******************************************************************************* + * Name: stm32_addbulked + * + * Description: + * Helper function to add an ED to the bulk list. + * + *******************************************************************************/ + +static inline int stm32_addbulked(struct stm32_usbhost_s *priv, + struct stm32_ed_s *ed) +{ +#ifndef CONFIG_USBHOST_BULK_DISABLE + uint32_t regval; + + /* Add the new bulk ED to the head of the bulk list */ + + ed->hw.nexted = stm32_getreg(STM32_USBHOST_BULKHEADED); + stm32_putreg((uint32_t)ed, STM32_USBHOST_BULKHEADED); + + /* BulkListEnable. This bit is set to enable the processing of the + * Bulk list. Note: once enabled, it remains. We really should + * never modify the bulk list while BLE is set. + */ + + regval = stm32_getreg(STM32_USBHOST_CTRL); + regval |= OHCI_CTRL_BLE; + stm32_putreg(regval, STM32_USBHOST_CTRL); + return OK; +#else + return -ENOSYS; +#endif +} + +/******************************************************************************* + * Name: stm32_rembulked + * + * Description: + * Helper function remove an ED from the bulk list. + * + *******************************************************************************/ + +static inline int stm32_rembulked(struct stm32_usbhost_s *priv, + struct stm32_ed_s *ed) +{ +#ifndef CONFIG_USBHOST_BULK_DISABLE + struct stm32_ed_s *curr; + struct stm32_ed_s *prev; + uint32_t regval; + + /* Find the ED in the bulk list. NOTE: We really should never be mucking + * with the bulk list while BLE is set. + */ + + for (curr = (struct stm32_ed_s *)stm32_getreg(STM32_USBHOST_BULKHEADED), + prev = NULL; + curr && curr != ed; + prev = curr, curr = (struct stm32_ed_s *)curr->hw.nexted); + + /* Hmmm.. It would be a bug if we do not find the ED in the bulk list. */ + + DEBUGASSERT(curr != NULL); + + /* Remove the ED from the bulk list */ + + if (curr != NULL) + { + /* Is this ED the first on in the bulk list? */ + + if (prev == NULL) + { + /* Yes... set the head of the bulk list to skip over this ED */ + + stm32_putreg(ed->hw.nexted, STM32_USBHOST_BULKHEADED); + + /* If the bulk list is now empty, then disable it */ + + regval = stm32_getreg(STM32_USBHOST_CTRL); + regval &= ~OHCI_CTRL_BLE; + stm32_putreg(regval, STM32_USBHOST_CTRL); + } + else + { + /* No.. set the forward link of the previous ED in the list + * skip over this ED. + */ + + prev->hw.nexted = ed->hw.nexted; + } + } + + return OK; +#else + return -ENOSYS; +#endif +} + +/******************************************************************************* + * Name: stm32_getinterval + * + * Description: + * Convert the endpoint polling interval into a HCCA table increment + * + *******************************************************************************/ + +#if !defined(CONFIG_USBHOST_INT_DISABLE) || !defined(CONFIG_USBHOST_ISOC_DISABLE) +static unsigned int stm32_getinterval(uint8_t interval) +{ + /* The bInterval field of the endpoint descriptor contains the polling interval + * for interrupt and isochronous endpoints. For other types of endpoint, this + * value should be ignored. bInterval is provided in units of 1MS frames. + */ + + if (interval < 3) + { + return 2; + } + else if (interval < 7) + { + return 4; + } + else if (interval < 15) + { + return 8; + } + else if (interval < 31) + { + return 16; + } + else + { + return 32; + } +} +#endif + +/******************************************************************************* + * Name: stm32_setinttab + * + * Description: + * Set the interrupt table to the selected value using the provided interval + * and offset. + * + *******************************************************************************/ + +#if !defined(CONFIG_USBHOST_INT_DISABLE) || !defined(CONFIG_USBHOST_ISOC_DISABLE) +static void stm32_setinttab(uint32_t value, unsigned int interval, unsigned int offset) +{ + unsigned int i; + for (i = offset; i < HCCA_INTTBL_WSIZE; i += interval) + { + HCCA->inttbl[i] = value; + } +} +#endif + +/******************************************************************************* + * Name: stm32_addinted + * + * Description: + * Helper function to add an ED to the HCCA interrupt table. + * + * To avoid reshuffling the table so much and to keep life simple in general, + * the following rules are applied: + * + * 1. IN EDs get the even entries, OUT EDs get the odd entries. + * 2. Add IN/OUT EDs are scheduled together at the minimum interval of all + * IN/OUT EDs. + * + * This has the following consequences: + * + * 1. The minimum support polling rate is 2MS, and + * 2. Some devices may get polled at a much higher rate than they request. + * + *******************************************************************************/ + +static inline int stm32_addinted(struct stm32_usbhost_s *priv, + const FAR struct usbhost_epdesc_s *epdesc, + struct stm32_ed_s *ed) +{ +#ifndef CONFIG_USBHOST_INT_DISABLE + unsigned int interval; + unsigned int offset; + uint32_t head; + uint32_t regval; + + /* Disable periodic list processing. Does this take effect immediately? Or + * at the next SOF... need to check. + */ + + regval = stm32_getreg(STM32_USBHOST_CTRL); + regval &= ~OHCI_CTRL_PLE; + stm32_putreg(regval, STM32_USBHOST_CTRL); + + /* Get the quanitized interval value associated with this ED and save it + * in the ED. + */ + + interval = stm32_getinterval(epdesc->interval); + ed->interval = interval; + uvdbg("interval: %d->%d\n", epdesc->interval, interval); + + /* Get the offset associated with the ED direction. IN EDs get the even + * entries, OUT EDs get the odd entries. + * + * Get the new, minimum interval. Add IN/OUT EDs are scheduled together + * at the minimum interval of all IN/OUT EDs. + */ + + if (epdesc->in) + { + offset = 0; + if (priv->ininterval > interval) + { + priv->ininterval = interval; + } + else + { + interval = priv->ininterval; + } + } + else + { + offset = 1; + if (priv->outinterval > interval) + { + priv->outinterval = interval; + } + else + { + interval = priv->outinterval; + } + } + uvdbg("min interval: %d offset: %d\n", interval, offset); + + /* Get the head of the first of the duplicated entries. The first offset + * entry is always guaranteed to contain the common ED list head. + */ + + head = HCCA->inttbl[offset]; + + /* Clear all current entries in the interrupt table for this direction */ + + stm32_setinttab(0, 2, offset); + + /* Add the new ED before the old head of the periodic ED list and set the + * new ED as the head ED in all of the appropriate entries of the HCCA + * interrupt table. + */ + + ed->hw.nexted = head; + stm32_setinttab((uint32_t)ed, interval, offset); + uvdbg("head: %08x next: %08x\n", ed, head); + + /* Re-enabled periodic list processing */ + + regval = stm32_getreg(STM32_USBHOST_CTRL); + regval |= OHCI_CTRL_PLE; + stm32_putreg(regval, STM32_USBHOST_CTRL); + return OK; +#else + return -ENOSYS; +#endif +} + +/******************************************************************************* + * Name: stm32_reminted + * + * Description: + * Helper function to remove an ED from the HCCA interrupt table. + * + * To avoid reshuffling the table so much and to keep life simple in general, + * the following rules are applied: + * + * 1. IN EDs get the even entries, OUT EDs get the odd entries. + * 2. Add IN/OUT EDs are scheduled together at the minimum interval of all + * IN/OUT EDs. + * + * This has the following consequences: + * + * 1. The minimum support polling rate is 2MS, and + * 2. Some devices may get polled at a much higher rate than they request. + * + *******************************************************************************/ + +static inline int stm32_reminted(struct stm32_usbhost_s *priv, + struct stm32_ed_s *ed) +{ +#ifndef CONFIG_USBHOST_INT_DISABLE + struct stm32_ed_s *head; + struct stm32_ed_s *curr; + struct stm32_ed_s *prev; + unsigned int interval; + unsigned int offset; + uint32_t regval; + + /* Disable periodic list processing. Does this take effect immediately? Or + * at the next SOF... need to check. + */ + + regval = stm32_getreg(STM32_USBHOST_CTRL); + regval &= ~OHCI_CTRL_PLE; + stm32_putreg(regval, STM32_USBHOST_CTRL); + + /* Get the offset associated with the ED direction. IN EDs get the even + * entries, OUT EDs get the odd entries. + */ + + if ((ed->hw.ctrl & ED_CONTROL_D_MASK) == ED_CONTROL_D_IN) + { + offset = 0; + } + else + { + offset = 1; + } + + /* Get the head of the first of the duplicated entries. The first offset + * entry is always guaranteed to contain the common ED list head. + */ + + head = (struct stm32_ed_s *)HCCA->inttbl[offset]; + uvdbg("ed: %08x head: %08x next: %08x offset: %d\n", + ed, head, head ? head->hw.nexted : 0, offset); + + /* Find the ED to be removed in the ED list */ + + for (curr = head, prev = NULL; + curr && curr != ed; + prev = curr, curr = (struct stm32_ed_s *)curr->hw.nexted); + + /* Hmmm.. It would be a bug if we do not find the ED in the bulk list. */ + + DEBUGASSERT(curr != NULL); + if (curr != NULL) + { + /* Clear all current entries in the interrupt table for this direction */ + + stm32_setinttab(0, 2, offset); + + /* Remove the ED from the list.. Is this ED the first on in the list? */ + + if (prev == NULL) + { + /* Yes... set the head of the bulk list to skip over this ED */ + + head = (struct stm32_ed_s *)ed->hw.nexted; + } + else + { + /* No.. set the forward link of the previous ED in the list + * skip over this ED. + */ + + prev->hw.nexted = ed->hw.nexted; + } + uvdbg("ed: %08x head: %08x next: %08x\n", + ed, head, head ? head->hw.nexted : 0); + + /* Calculate the new minimum interval for this list */ + + interval = MAX_PERINTERVAL; + for (curr = head; curr; curr = (struct stm32_ed_s *)curr->hw.nexted) + { + if (curr->interval < interval) + { + interval = curr->interval; + } + } + uvdbg("min interval: %d offset: %d\n", interval, offset); + + /* Save the new minimum interval */ + + if ((ed->hw.ctrl && ED_CONTROL_D_MASK) == ED_CONTROL_D_IN) + { + priv->ininterval = interval; + } + else + { + priv->outinterval = interval; + } + + /* Set the head ED in all of the appropriate entries of the HCCA interrupt + * table (head might be NULL). + */ + + stm32_setinttab((uint32_t)head, interval, offset); + } + + /* Re-enabled periodic list processing */ + + if (head != NULL) + { + regval = stm32_getreg(STM32_USBHOST_CTRL); + regval |= OHCI_CTRL_PLE; + stm32_putreg(regval, STM32_USBHOST_CTRL); + } + + return OK; +#else + return -ENOSYS; +#endif +} + +/******************************************************************************* + * Name: stm32_addisoced + * + * Description: + * Helper functions to add an ED to the periodic table. + * + *******************************************************************************/ + +static inline int stm32_addisoced(struct stm32_usbhost_s *priv, + const FAR struct usbhost_epdesc_s *epdesc, + struct stm32_ed_s *ed) +{ +#ifndef CONFIG_USBHOST_ISOC_DISABLE +# warning "Isochronous endpoints not yet supported" +#endif + return -ENOSYS; + +} + +/******************************************************************************* + * Name: stm32_remisoced + * + * Description: + * Helper functions to remove an ED from the periodic table. + * + *******************************************************************************/ + +static inline int stm32_remisoced(struct stm32_usbhost_s *priv, + struct stm32_ed_s *ed) +{ +#ifndef CONFIG_USBHOST_ISOC_DISABLE +# warning "Isochronous endpoints not yet supported" +#endif + return -ENOSYS; +} + +/******************************************************************************* + * Name: stm32_enqueuetd + * + * Description: + * Enqueue a transfer descriptor. Notice that this function only supports + * queue on TD per ED. + * + *******************************************************************************/ + +static int stm32_enqueuetd(struct stm32_usbhost_s *priv, + struct stm32_ed_s *ed, uint32_t dirpid, + uint32_t toggle, volatile uint8_t *buffer, size_t buflen) +{ + struct stm32_gtd_s *td; + int ret = -ENOMEM; + + /* Allocate a TD from the free list */ + + td = stm32_tdalloc(); + if (td != NULL) + { + /* Initialize the allocated TD and link it before the common tail TD. */ + + td->hw.ctrl = (GTD_STATUS_R | dirpid | TD_DELAY(0) | toggle | GTD_STATUS_CC_MASK); + TDTAIL->hw.ctrl = 0; + td->hw.cbp = (uint32_t)buffer; + TDTAIL->hw.cbp = 0; + td->hw.nexttd = (uint32_t)TDTAIL; + TDTAIL->hw.nexttd = 0; + td->hw.be = (uint32_t)(buffer + (buflen - 1)); + TDTAIL->hw.be = 0; + + /* Configure driver-only fields in the extended TD structure */ + + td->ed = ed; + + /* Link the td to the head of the ED's TD list */ + + ed->hw.headp = (uint32_t)td | ((ed->hw.headp) & ED_HEADP_C); + ed->hw.tailp = (uint32_t)TDTAIL; + + ret = OK; + } + + return ret; +} + +/******************************************************************************* + * Name: stm32_wdhwait + * + * Description: + * Set the request for the Writeback Done Head event well BEFORE enabling the + * transfer (as soon as we are absolutely committed to the to avoid transfer). + * We do this to minimize race conditions. This logic would have to be expanded + * if we want to have more than one packet in flight at a time! + * + *******************************************************************************/ + +static int stm32_wdhwait(struct stm32_usbhost_s *priv, struct stm32_ed_s *ed) +{ + irqstate_t flags = irqsave(); + int ret = -ENODEV; + + /* Is the device still connected? */ + + if (priv->connected) + { + /* Yes.. then set wdhwait to indicate that we expect to be informed when + * either (1) the device is disconnected, or (2) the transfer completed. + */ + + ed->wdhwait = true; + ret = OK; + } + + irqrestore(flags); + return ret; +} + +/******************************************************************************* + * Name: stm32_ctrltd + * + * Description: + * Process a IN or OUT request on the control endpoint. This function + * will enqueue the request and wait for it to complete. Only one transfer + * may be queued; Neither these methods nor the transfer() method can be + * called again until the control transfer functions returns. + * + * These are blocking methods; these functions will not return until the + * control transfer has completed. + * + *******************************************************************************/ + +static int stm32_ctrltd(struct stm32_usbhost_s *priv, uint32_t dirpid, + uint8_t *buffer, size_t buflen) +{ + uint32_t toggle; + uint32_t regval; + int ret; + + /* Set the request for the Writeback Done Head event well BEFORE enabling the + * transfer. + */ + + ret = stm32_wdhwait(priv, EDCTRL); + if (ret != OK) + { + udbg("ERROR: Device disconnected\n"); + return ret; + } + + /* Configure the toggle field in the TD */ + + if (dirpid == GTD_STATUS_DP_SETUP) + { + toggle = GTD_STATUS_T_DATA0; + } + else + { + toggle = GTD_STATUS_T_DATA1; + } + + /* Then enqueue the transfer */ + + EDCTRL->tdstatus = TD_CC_NOERROR; + ret = stm32_enqueuetd(priv, EDCTRL, dirpid, toggle, buffer, buflen); + if (ret == OK) + { + /* Set ControlListFilled. This bit is used to indicate whether there are + * TDs on the Control list. + */ + + regval = stm32_getreg(STM32_USBHOST_CMDST); + regval |= OHCI_CMDST_CLF; + stm32_putreg(regval, STM32_USBHOST_CMDST); + + /* Wait for the Writeback Done Head interrupt */ + + stm32_takesem(&EDCTRL->wdhsem); + + /* Check the TD completion status bits */ + + if (EDCTRL->tdstatus == TD_CC_NOERROR) + { + ret = OK; + } + else + { + uvdbg("Bad TD completion status: %d\n", EDCTRL->tdstatus); + ret = -EIO; + } + } + + /* Make sure that there is no outstanding request on this endpoint */ + + EDCTRL->wdhwait = false; + return ret; +} + +/******************************************************************************* + * Name: stm32_usbinterrupt + * + * Description: + * USB interrupt handler + * + *******************************************************************************/ + +static int stm32_usbinterrupt(int irq, FAR void *context) +{ + struct stm32_usbhost_s *priv = &g_usbhost; + uint32_t intst; + uint32_t pending; + uint32_t regval; + + /* Read Interrupt Status and mask out interrupts that are not enabled. */ + + intst = stm32_getreg(STM32_USBHOST_INTST); + regval = stm32_getreg(STM32_USBHOST_INTEN); + ullvdbg("INST: %08x INTEN: %08x\n", intst, regval); + + pending = intst & regval; + if (pending != 0) + { + /* Root hub status change interrupt */ + + if ((pending & OHCI_INT_RHSC) != 0) + { + uint32_t rhportst1 = stm32_getreg(STM32_USBHOST_RHPORTST1); + ullvdbg("Root Hub Status Change, RHPORTST1: %08x\n", rhportst1); + + if ((rhportst1 & OHCI_RHPORTST_CSC) != 0) + { + uint32_t rhstatus = stm32_getreg(STM32_USBHOST_RHSTATUS); + ullvdbg("Connect Status Change, RHSTATUS: %08x\n", rhstatus); + + /* If DRWE is set, Connect Status Change indicates a remote wake-up event */ + + if (rhstatus & OHCI_RHSTATUS_DRWE) + { + ullvdbg("DRWE: Remote wake-up\n"); + } + + /* Otherwise... Not a remote wake-up event */ + + else + { + /* Check current connect status */ + + if ((rhportst1 & OHCI_RHPORTST_CCS) != 0) + { + /* Connected ... Did we just become connected? */ + + if (!priv->connected) + { + /* Yes.. connected. */ + + ullvdbg("Connected\n"); + priv->connected = true; + + /* Notify any waiters */ + + if (priv->rhswait) + { + stm32_givesem(&priv->rhssem); + priv->rhswait = false; + } + } + else + { + ulldbg("Spurious status change (connected)\n"); + } + + /* The LSDA (Low speed device attached) bit is valid + * when CCS == 1. + */ + + priv->lowspeed = (rhportst1 & OHCI_RHPORTST_LSDA) != 0; + ullvdbg("Speed:%s\n", priv->lowspeed ? "LOW" : "FULL"); + } + + /* Check if we are now disconnected */ + + else if (priv->connected) + { + /* Yes.. disconnect the device */ + + ullvdbg("Disconnected\n"); + priv->connected = false; + priv->lowspeed = false; + + /* Are we bound to a class instance? */ + + if (priv->class) + { + /* Yes.. Disconnect the class */ + + CLASS_DISCONNECTED(priv->class); + priv->class = NULL; + } + + /* Notify any waiters for the Root Hub Status change event */ + + if (priv->rhswait) + { + stm32_givesem(&priv->rhssem); + priv->rhswait = false; + } + } + else + { + ulldbg("Spurious status change (disconnected)\n"); + } + } + + /* Clear the status change interrupt */ + + stm32_putreg(OHCI_RHPORTST_CSC, STM32_USBHOST_RHPORTST1); + } + + /* Check for port reset status change */ + + if ((rhportst1 & OHCI_RHPORTST_PRSC) != 0) + { + /* Release the RH port from reset */ + + stm32_putreg(OHCI_RHPORTST_PRSC, STM32_USBHOST_RHPORTST1); + } + } + + /* Writeback Done Head interrupt */ + + if ((pending & OHCI_INT_WDH) != 0) + { + struct stm32_gtd_s *td; + struct stm32_gtd_s *next; + + /* The host controller just wrote the list of finished TDs into the HCCA + * done head. This may include multiple packets that were transferred + * in the preceding frame. + * + * Remove the TD(s) from the Writeback Done Head in the HCCA and return + * them to the free list. Note that this is safe because the hardware + * will not modify the writeback done head again until the WDH bit is + * cleared in the interrupt status register. + */ + + td = (struct stm32_gtd_s *)HCCA->donehead; + HCCA->donehead = 0; + + /* Process each TD in the write done list */ + + for (; td; td = next) + { + /* Get the ED in which this TD was enqueued */ + + struct stm32_ed_s *ed = td->ed; + DEBUGASSERT(ed != NULL); + + /* Save the condition code from the (single) TD status/control + * word. + */ + + ed->tdstatus = (td->hw.ctrl & GTD_STATUS_CC_MASK) >> GTD_STATUS_CC_SHIFT; + +#ifdef CONFIG_DEBUG_USB + if (ed->tdstatus != TD_CC_NOERROR) + { + /* The transfer failed for some reason... dump some diagnostic info. */ + + ulldbg("ERROR: ED xfrtype:%d TD CTRL:%08x/CC:%d RHPORTST1:%08x\n", + ed->xfrtype, td->hw.ctrl, ed->tdstatus, + stm32_getreg(STM32_USBHOST_RHPORTST1)); + } +#endif + + /* Return the TD to the free list */ + + next = (struct stm32_gtd_s *)td->hw.nexttd; + stm32_tdfree(td); + + /* And wake up the thread waiting for the WDH event */ + + if (ed->wdhwait) + { + stm32_givesem(&ed->wdhsem); + ed->wdhwait = false; + } + } + } + +#ifdef CONFIG_DEBUG_USB + if ((pending & STM32_DEBUG_INTS) != 0) + { + ulldbg("ERROR: Unhandled interrupts INTST:%08x\n", intst); + } +#endif + + /* Clear interrupt status register */ + + stm32_putreg(intst, STM32_USBHOST_INTST); + } + + return OK; +} + +/******************************************************************************* + * USB Host Controller Operations + *******************************************************************************/ + +/******************************************************************************* + * Name: stm32_wait + * + * Description: + * Wait for a device to be connected or disconneced. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * connected - TRUE: Wait for device to be connected; FALSE: wait for device + * to be disconnected + * + * Returned Values: + * Zero (OK) is returned when a device in connected. This function will not + * return until either (1) a device is connected or (2) some failure occurs. + * On a failure, a negated errno value is returned indicating the nature of + * the failure + * + * Assumptions: + * - Called from a single thread so no mutual exclusion is required. + * - Never called from an interrupt handler. + * + *******************************************************************************/ + +static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected) +{ + struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr; + irqstate_t flags; + + /* Are we already connected? */ + + flags = irqsave(); + while (priv->connected == connected) + { + /* No... wait for the connection/disconnection */ + + priv->rhswait = true; + stm32_takesem(&priv->rhssem); + } + irqrestore(flags); + + udbg("Connected:%s\n", priv->connected ? "YES" : "NO"); + return OK; +} + +/******************************************************************************* + * Name: stm32_enumerate + * + * Description: + * Enumerate the connected device. As part of this enumeration process, + * the driver will (1) get the device's configuration descriptor, (2) + * extract the class ID info from the configuration descriptor, (3) call + * usbhost_findclass() to find the class that supports this device, (4) + * call the create() method on the struct usbhost_registry_s interface + * to get a class instance, and finally (5) call the configdesc() method + * of the struct usbhost_class_s interface. After that, the class is in + * charge of the sequence of operations. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * - Only a single class bound to a single device is supported. + * - Called from a single thread so no mutual exclusion is required. + * - Never called from an interrupt handler. + * + *******************************************************************************/ + +static int stm32_enumerate(FAR struct usbhost_driver_s *drvr) +{ + struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr; + + /* Are we connected to a device? The caller should have called the wait() + * method first to be assured that a device is connected. + */ + + while (!priv->connected) + { + /* No, return an error */ + + udbg("Not connected\n"); + return -ENODEV; + } + + /* USB 2.0 spec says at least 50ms delay before port reset */ + + up_mdelay(100); + + /* Put RH port 1 in reset (the STM32 supports only a single downstream port) */ + + stm32_putreg(OHCI_RHPORTST_PRS, STM32_USBHOST_RHPORTST1); + + /* Wait for the port reset to complete */ + + while ((stm32_getreg(STM32_USBHOST_RHPORTST1) & OHCI_RHPORTST_PRS) != 0); + + /* Release RH port 1 from reset and wait a bit */ + + stm32_putreg(OHCI_RHPORTST_PRSC, STM32_USBHOST_RHPORTST1); + up_mdelay(200); + + /* Let the common usbhost_enumerate do all of the real work. Note that the + * FunctionAddress (USB address) is hardcoded to one. + */ + + uvdbg("Enumerate the device\n"); + return usbhost_enumerate(drvr, 1, &priv->class); +} + +/************************************************************************************ + * Name: stm32_ep0configure + * + * Description: + * Configure endpoint 0. This method is normally used internally by the + * enumerate() method but is made available at the interface to support + * an external implementation of the enumeration logic. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * funcaddr - The USB address of the function containing the endpoint that EP0 + * controls + * maxpacketsize - The maximum number of bytes that can be sent to or + * received from the endpoint in a single data packet + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +static int stm32_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, + uint16_t maxpacketsize) +{ + struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr; + + DEBUGASSERT(drvr && funcaddr < 128 && maxpacketsize < 2048); + + /* We must have exclusive access to EP0 and the control list */ + + stm32_takesem(&priv->exclsem); + + /* Set the EP0 ED control word */ + + EDCTRL->hw.ctrl = (uint32_t)funcaddr << ED_CONTROL_FA_SHIFT | + (uint32_t)maxpacketsize << ED_CONTROL_MPS_SHIFT; + + if (priv->lowspeed) + { + EDCTRL->hw.ctrl |= ED_CONTROL_S; + } + + /* Set the transfer type to control */ + + EDCTRL->xfrtype = USB_EP_ATTR_XFER_CONTROL; + stm32_givesem(&priv->exclsem); + + uvdbg("EP0 CTRL:%08x\n", EDCTRL->hw.ctrl); + return OK; +} + +/************************************************************************************ + * Name: stm32_epalloc + * + * Description: + * Allocate and configure one endpoint. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * epdesc - Describes the endpoint to be allocated. + * ep - A memory location provided by the caller in which to receive the + * allocated endpoint desciptor. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +static int stm32_epalloc(FAR struct usbhost_driver_s *drvr, + const FAR struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep) +{ + struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr; + struct stm32_ed_s *ed; + int ret = -ENOMEM; + + /* Sanity check. NOTE that this method should only be called if a device is + * connected (because we need a valid low speed indication). + */ + + DEBUGASSERT(priv && epdesc && ep && priv->connected); + + /* We must have exclusive access to the ED pool, the bulk list, the periodic list + * and the interrupt table. + */ + + stm32_takesem(&priv->exclsem); + + /* Take the next ED from the beginning of the free list */ + + ed = (struct stm32_ed_s *)g_edfree; + if (ed) + { + /* Remove the ED from the freelist */ + + g_edfree = ((struct stm32_list_s*)ed)->flink; + + /* Configure the endpoint descriptor. */ + + memset((void*)ed, 0, sizeof(struct stm32_ed_s)); + ed->hw.ctrl = (uint32_t)(epdesc->funcaddr) << ED_CONTROL_FA_SHIFT | + (uint32_t)(epdesc->addr) << ED_CONTROL_EN_SHIFT | + (uint32_t)(epdesc->mxpacketsize) << ED_CONTROL_MPS_SHIFT; + + /* Get the direction of the endpoint */ + + if (epdesc->in) + { + ed->hw.ctrl |= ED_CONTROL_D_IN; + } + else + { + ed->hw.ctrl |= ED_CONTROL_D_OUT; + } + + /* Check for a low-speed device */ + + if (priv->lowspeed) + { + ed->hw.ctrl |= ED_CONTROL_S; + } + + /* Set the transfer type */ + + ed->xfrtype = epdesc->xfrtype; + + /* Special Case isochronous transfer types */ + +#if 0 /* Isochronous transfers not yet supported */ + if (ed->xfrtype == USB_EP_ATTR_XFER_ISOC) + { + ed->hw.ctrl |= ED_CONTROL_F; + } +#endif + uvdbg("EP%d CTRL:%08x\n", epdesc->addr, ed->hw.ctrl); + + /* Initialize the semaphore that is used to wait for the endpoint + * WDH event. + */ + + sem_init(&ed->wdhsem, 0, 0); + + /* Link the common tail TD to the ED's TD list */ + + ed->hw.headp = (uint32_t)TDTAIL; + ed->hw.tailp = (uint32_t)TDTAIL; + + /* Now add the endpoint descriptor to the appropriate list */ + + switch (ed->xfrtype) + { + case USB_EP_ATTR_XFER_BULK: + ret = stm32_addbulked(priv, ed); + break; + + case USB_EP_ATTR_XFER_INT: + ret = stm32_addinted(priv, epdesc, ed); + break; + + case USB_EP_ATTR_XFER_ISOC: + ret = stm32_addisoced(priv, epdesc, ed); + break; + + case USB_EP_ATTR_XFER_CONTROL: + default: + ret = -EINVAL; + break; + } + + /* Was the ED successfully added? */ + + if (ret != OK) + { + /* No.. destroy it and report the error */ + + udbg("ERROR: Failed to queue ED for transfer type: %d\n", ed->xfrtype); + sem_destroy(&ed->wdhsem); + stm32_edfree(ed); + } + else + { + /* Yes.. return an opaque reference to the ED */ + + *ep = (usbhost_ep_t)ed; + } + } + + stm32_givesem(&priv->exclsem); + return ret; +} + +/************************************************************************************ + * Name: stm32_epfree + * + * Description: + * Free and endpoint previously allocated by DRVR_EPALLOC. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * ep - The endpint to be freed. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +static int stm32_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep) +{ + struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr; + struct stm32_ed_s *ed = (struct stm32_ed_s *)ep; + int ret; + + /* There should not be any pending, real TDs linked to this ED */ + + DEBUGASSERT(ed && (ed->hw.headp & ED_HEADP_ADDR_MASK) == STM32_TDTAIL_ADDR); + + /* We must have exclusive access to the ED pool, the bulk list, the periodic list + * and the interrupt table. + */ + + stm32_takesem(&priv->exclsem); + + /* Remove the ED to the correct list depending on the trasfer type */ + + switch (ed->xfrtype) + { + case USB_EP_ATTR_XFER_BULK: + ret = stm32_rembulked(priv, ed); + break; + + case USB_EP_ATTR_XFER_INT: + ret = stm32_reminted(priv, ed); + break; + + case USB_EP_ATTR_XFER_ISOC: + ret = stm32_remisoced(priv, ed); + break; + + case USB_EP_ATTR_XFER_CONTROL: + default: + ret = -EINVAL; + break; + } + + /* Destroy the semaphore */ + + sem_destroy(&ed->wdhsem); + + /* Put the ED back into the free list */ + + stm32_edfree(ed); + stm32_givesem(&priv->exclsem); + return ret; +} + +/******************************************************************************* + * Name: stm32_alloc + * + * Description: + * Some hardware supports special memory in which request and descriptor data can + * be accessed more efficiently. This method provides a mechanism to allocate + * the request/descriptor memory. If the underlying hardware does not support + * such "special" memory, this functions may simply map to malloc. + * + * This interface was optimized under a particular assumption. It was assumed + * that the driver maintains a pool of small, pre-allocated buffers for descriptor + * traffic. NOTE that size is not an input, but an output: The size of the + * pre-allocated buffer is returned. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * buffer - The address of a memory location provided by the caller in which to + * return the allocated buffer memory address. + * maxlen - The address of a memory location provided by the caller in which to + * return the maximum size of the allocated buffer memory. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * - Called from a single thread so no mutual exclusion is required. + * - Never called from an interrupt handler. + * + *******************************************************************************/ + +static int stm32_alloc(FAR struct usbhost_driver_s *drvr, + FAR uint8_t **buffer, FAR size_t *maxlen) +{ + struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr; + DEBUGASSERT(priv && buffer && maxlen); + int ret = -ENOMEM; + + /* We must have exclusive access to the transfer buffer pool */ + + stm32_takesem(&priv->exclsem); + + *buffer = stm32_tballoc(); + if (*buffer) + { + *maxlen = CONFIG_USBHOST_TDBUFSIZE; + ret = OK; + } + + stm32_givesem(&priv->exclsem); + return ret; +} + +/******************************************************************************* + * Name: stm32_free + * + * Description: + * Some hardware supports special memory in which request and descriptor data can + * be accessed more efficiently. This method provides a mechanism to free that + * request/descriptor memory. If the underlying hardware does not support + * such "special" memory, this functions may simply map to free(). + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * buffer - The address of the allocated buffer memory to be freed. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * - Never called from an interrupt handler. + * + *******************************************************************************/ + +static int stm32_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer) +{ + struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr; + DEBUGASSERT(buffer); + + /* We must have exclusive access to the transfer buffer pool */ + + stm32_takesem(&priv->exclsem); + stm32_tbfree(buffer); + stm32_givesem(&priv->exclsem); + return OK; +} + +/************************************************************************************ + * Name: stm32_ioalloc + * + * Description: + * Some hardware supports special memory in which larger IO buffers can + * be accessed more efficiently. This method provides a mechanism to allocate + * the request/descriptor memory. If the underlying hardware does not support + * such "special" memory, this functions may simply map to malloc. + * + * This interface differs from DRVR_ALLOC in that the buffers are variable-sized. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * buffer - The address of a memory location provided by the caller in which to + * return the allocated buffer memory address. + * buflen - The size of the buffer required. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +static int stm32_ioalloc(FAR struct usbhost_driver_s *drvr, + FAR uint8_t **buffer, size_t buflen) +{ + DEBUGASSERT(drvr && buffer); + +#if STM32_IOBUFFERS > 0 + if (buflen <= CONFIG_USBHOST_IOBUFSIZE) + { + FAR uint8_t *alloc = stm32_allocio(); + if (alloc) + { + *buffer = alloc; + return OK; + } + } + return -ENOMEM; +#else + return -ENOSYS; +#endif +} + +/************************************************************************************ + * Name: stm32_iofree + * + * Description: + * Some hardware supports special memory in which IO data can be accessed more + * efficiently. This method provides a mechanism to free that IO buffer + * memory. If the underlying hardware does not support such "special" memory, + * this functions may simply map to free(). + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * buffer - The address of the allocated buffer memory to be freed. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +static int stm32_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer) +{ + DEBUGASSERT(drvr && buffer); + +#if STM32_IOBUFFERS > 0 + stm32_freeio(buffer); + return OK; +#else + return -ENOSYS; +#endif +} + +/******************************************************************************* + * Name: stm32_ctrlin and stm32_ctrlout + * + * Description: + * Process a IN or OUT request on the control endpoint. These methods + * will enqueue the request and wait for it to complete. Only one transfer may be + * queued; Neither these methods nor the transfer() method can be called again + * until the control transfer functions returns. + * + * These are blocking methods; these functions will not return until the + * control transfer has completed. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * req - Describes the request to be sent. This request must lie in memory + * created by DRVR_ALLOC. + * buffer - A buffer used for sending the request and for returning any + * responses. This buffer must be large enough to hold the length value + * in the request description. buffer must have been allocated using DRVR_ALLOC + * + * NOTE: On an IN transaction, req and buffer may refer to the same allocated + * memory. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * - Only a single class bound to a single device is supported. + * - Called from a single thread so no mutual exclusion is required. + * - Never called from an interrupt handler. + * + *******************************************************************************/ + +static int stm32_ctrlin(FAR struct usbhost_driver_s *drvr, + FAR const struct usb_ctrlreq_s *req, + FAR uint8_t *buffer) +{ + struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr; + uint16_t len; + int ret; + + DEBUGASSERT(drvr && req); + uvdbg("type:%02x req:%02x value:%02x%02x index:%02x%02x len:%02x%02x\n", + req->type, req->req, req->value[1], req->value[0], + req->index[1], req->index[0], req->len[1], req->len[0]); + + /* We must have exclusive access to EP0 and the control list */ + + stm32_takesem(&priv->exclsem); + + len = stm32_getle16(req->len); + ret = stm32_ctrltd(priv, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ); + if (ret == OK) + { + if (len) + { + ret = stm32_ctrltd(priv, GTD_STATUS_DP_IN, buffer, len); + } + + if (ret == OK) + { + ret = stm32_ctrltd(priv, GTD_STATUS_DP_OUT, NULL, 0); + } + } + + stm32_givesem(&priv->exclsem); + return ret; +} + +static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr, + FAR const struct usb_ctrlreq_s *req, + FAR const uint8_t *buffer) +{ + struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr; + uint16_t len; + int ret; + + DEBUGASSERT(drvr && req); + uvdbg("type:%02x req:%02x value:%02x%02x index:%02x%02x len:%02x%02x\n", + req->type, req->req, req->value[1], req->value[0], + req->index[1], req->index[0], req->len[1], req->len[0]); + + /* We must have exclusive access to EP0 and the control list */ + + stm32_takesem(&priv->exclsem); + + len = stm32_getle16(req->len); + ret = stm32_ctrltd(priv, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ); + if (ret == OK) + { + if (len) + { + ret = stm32_ctrltd(priv, GTD_STATUS_DP_OUT, (uint8_t*)buffer, len); + } + + if (ret == OK) + { + ret = stm32_ctrltd(priv, GTD_STATUS_DP_IN, NULL, 0); + } + } + + stm32_givesem(&priv->exclsem); + return ret; +} + +/******************************************************************************* + * Name: stm32_transfer + * + * Description: + * Process a request to handle a transfer descriptor. This method will + * enqueue the transfer request and return immediately. Only one transfer may be + * queued; Neither this method nor the ctrlin or ctrlout methods can be called + * again until this function returns. + * + * This is a blocking method; this functions will not return until the + * transfer has completed. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * ep - The IN or OUT endpoint descriptor for the device endpoint on which to + * perform the transfer. + * buffer - A buffer containing the data to be sent (OUT endpoint) or received + * (IN endpoint). buffer must have been allocated using DRVR_ALLOC + * buflen - The length of the data to be sent or received. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * - Only a single class bound to a single device is supported. + * - Called from a single thread so no mutual exclusion is required. + * - Never called from an interrupt handler. + * + *******************************************************************************/ + +static int stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, + FAR uint8_t *buffer, size_t buflen) +{ + struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr; + struct stm32_ed_s *ed = (struct stm32_ed_s *)ep; + uint32_t dirpid; + uint32_t regval; +#if STM32_IOBUFFERS > 0 + uint8_t *origbuf = NULL; +#endif + bool in; + int ret; + + DEBUGASSERT(priv && ed && buffer && buflen > 0); + + in = (ed->hw.ctrl & ED_CONTROL_D_MASK) == ED_CONTROL_D_IN; + uvdbg("EP%d %s toggle:%d maxpacket:%d buflen:%d\n", + (ed->hw.ctrl & ED_CONTROL_EN_MASK) >> ED_CONTROL_EN_SHIFT, + in ? "IN" : "OUT", + (ed->hw.headp & ED_HEADP_C) != 0 ? 1 : 0, + (ed->hw.ctrl & ED_CONTROL_MPS_MASK) >> ED_CONTROL_MPS_SHIFT, + buflen); + + /* We must have exclusive access to the endpoint, the TD pool, the I/O buffer + * pool, the bulk and interrupt lists, and the HCCA interrupt table. + */ + + stm32_takesem(&priv->exclsem); + + /* Allocate an IO buffer if the user buffer does not lie in AHB SRAM */ + +#if STM32_IOBUFFERS > 0 + if ((uintptr_t)buffer < STM32_SRAM_BANK0 || + (uintptr_t)buffer >= (STM32_SRAM_BANK0 + STM32_BANK0_SIZE + STM32_BANK1_SIZE)) + { + /* Will the transfer fit in an IO buffer? */ + + if (buflen > CONFIG_USBHOST_IOBUFSIZE) + { + uvdbg("buflen (%d) > IO buffer size (%d)\n", + buflen, CONFIG_USBHOST_IOBUFSIZE); + ret = -ENOMEM; + goto errout; + } + + /* Allocate an IO buffer in AHB SRAM */ + + origbuf = buffer; + buffer = stm32_allocio(); + if (!buffer) + { + uvdbg("IO buffer allocation failed\n"); + ret = -ENOMEM; + goto errout; + } + + /* If this is an OUT transaction, copy the user data into the AHB + * SRAM IO buffer. Sad... so inefficient. But without exposing + * the AHB SRAM to the final, end-user client I don't know of any + * way around this copy. + */ + + if (!in) + { + memcpy(buffer, origbuf, buflen); + } + } +#endif + + /* Set the request for the Writeback Done Head event well BEFORE enabling the + * transfer. + */ + + ret = stm32_wdhwait(priv, ed); + if (ret != OK) + { + udbg("ERROR: Device disconnected\n"); + goto errout; + } + + /* Get the direction of the endpoint */ + + if (in) + { + dirpid = GTD_STATUS_DP_IN; + } + else + { + dirpid = GTD_STATUS_DP_OUT; + } + + /* Then enqueue the transfer */ + + ed->tdstatus = TD_CC_NOERROR; + ret = stm32_enqueuetd(priv, ed, dirpid, GTD_STATUS_T_TOGGLE, buffer, buflen); + if (ret == OK) + { + /* BulkListFilled. This bit is used to indicate whether there are any + * TDs on the Bulk list. + */ + + regval = stm32_getreg(STM32_USBHOST_CMDST); + regval |= OHCI_CMDST_BLF; + stm32_putreg(regval, STM32_USBHOST_CMDST); + + /* Wait for the Writeback Done Head interrupt */ + + stm32_takesem(&ed->wdhsem); + + /* Check the TD completion status bits */ + + if (ed->tdstatus == TD_CC_NOERROR) + { + ret = OK; + } + else + { + uvdbg("Bad TD completion status: %d\n", ed->tdstatus); + ret = -EIO; + } + } + +errout: + /* Make sure that there is no outstanding request on this endpoint */ + + ed->wdhwait = false; + + /* Free any temporary IO buffers */ + +#if STM32_IOBUFFERS > 0 + if (buffer && origbuf) + { + /* If this is an IN transaction, get the user data from the AHB + * SRAM IO buffer. Sad... so inefficient. But without exposing + * the AHB SRAM to the final, end-user client I don't know of any + * way around this copy. + */ + + if (in && ret == OK) + { + memcpy(origbuf, buffer, buflen); + } + + /* Then free the temporary I/O buffer */ + + stm32_freeio(buffer); + } +#endif + + stm32_givesem(&priv->exclsem); + return ret; +} + +/******************************************************************************* + * Name: stm32_disconnect + * + * Description: + * Called by the class when an error occurs and driver has been disconnected. + * The USB host driver should discard the handle to the class instance (it is + * stale) and not attempt any further interaction with the class driver instance + * (until a new instance is received from the create() method). The driver + * should not called the class' disconnected() method. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * + * Returned Values: + * None + * + * Assumptions: + * - Only a single class bound to a single device is supported. + * - Never called from an interrupt handler. + * + *******************************************************************************/ + +static void stm32_disconnect(FAR struct usbhost_driver_s *drvr) +{ + struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr; + priv->class = NULL; +} + +/******************************************************************************* + * Initialization + *******************************************************************************/ +/******************************************************************************* + * Name: stm32_ep0init + * + * Description: + * Initialize ED for EP0, add it to the control ED list, and enable control + * transfers. + * + * Input Parameters: + * priv - private driver state instance. + * + * Returned Values: + * None + * + *******************************************************************************/ + +static inline void stm32_ep0init(struct stm32_usbhost_s *priv) +{ + uint32_t regval; + + /* Set up some default values */ + + (void)stm32_ep0configure(&priv->drvr, 1, 8); + + /* Initialize the common tail TD. */ + + memset(TDTAIL, 0, sizeof(struct stm32_gtd_s)); + TDTAIL->ed = EDCTRL; + + /* Link the common tail TD to the ED's TD list */ + + memset(EDCTRL, 0, sizeof(struct stm32_ed_s)); + EDCTRL->hw.headp = (uint32_t)TDTAIL; + EDCTRL->hw.tailp = (uint32_t)TDTAIL; + + /* Set the head of the control list to the EP0 EDCTRL (this would have to + * change if we want more than on control EP queued at a time). + */ + + stm32_putreg(STM32_EDCTRL_ADDR, STM32_USBHOST_CTRLHEADED); + + /* ControlListEnable. This bit is set to enable the processing of the + * Control list. Note: once enabled, it remains enabled and we may even + * complete list processing before we get the bit set. We really + * should never modify the control list while CLE is set. + */ + + regval = stm32_getreg(STM32_USBHOST_CTRL); + regval |= OHCI_CTRL_CLE; + stm32_putreg(regval, STM32_USBHOST_CTRL); +} + +/******************************************************************************* + * Public Functions + *******************************************************************************/ + +/******************************************************************************* + * Name: usbhost_initialize + * + * Description: + * Initialize USB host device controller hardware. + * + * Input Parameters: + * controller -- If the device supports more than USB host controller, then + * this identifies which controller is being intialized. Normally, this + * is just zero. + * + * Returned Value: + * And instance of the USB host interface. The controlling task should + * use this interface to (1) call the wait() method to wait for a device + * to be connected, and (2) call the enumerate() method to bind the device + * to a class driver. + * + * Assumptions: + * - This function should called in the initialization sequence in order + * to initialize the USB device functionality. + * - Class drivers should be initialized prior to calling this function. + * Otherwise, there is a race condition if the device is already connected. + * + *******************************************************************************/ + +FAR struct usbhost_driver_s *usbhost_initialize(int controller) +{ + struct stm32_usbhost_s *priv = &g_usbhost; + uint32_t regval; + uint8_t *buffer; + irqstate_t flags; + int i; + + /* Sanity checks. NOTE: If certain OS features are enabled, it may be + * necessary to increase the size of STM32_ED/TD_SIZE in stm32_ohciram.h + */ + + DEBUGASSERT(controller == 0); + DEBUGASSERT(sizeof(struct stm32_ed_s) <= STM32_ED_SIZE); + DEBUGASSERT(sizeof(struct stm32_gtd_s) <= STM32_TD_SIZE); + + /* Initialize the state data structure */ + + sem_init(&priv->rhssem, 0, 0); + sem_init(&priv->exclsem, 0, 1); + +#ifndef CONFIG_USBHOST_INT_DISABLE + priv->ininterval = MAX_PERINTERVAL; + priv->outinterval = MAX_PERINTERVAL; +#endif + + /* Enable power by setting PCUSB in the PCONP register. Disable interrupts + * because this register may be shared with other drivers. + */ + + flags = irqsave(); + regval = stm32_getreg(STM32_SYSCON_PCONP); + regval |= SYSCON_PCONP_PCUSB; + stm32_putreg(regval, STM32_SYSCON_PCONP); + irqrestore(flags); + + /* Enable clocking on USB (USB PLL clocking was initialized in very low- + * evel clock setup logic (see stm32_clockconfig.c)). We do still need + * to set up USBOTG CLKCTRL to enable clocking. + * + * NOTE: The PORTSEL clock needs to be enabled only when accessing OTGSTCTRL + */ + + stm32_putreg(STM32_CLKCTRL_ENABLES, STM32_USBOTG_CLKCTRL); + + /* Then wait for the clocks to be reported as "ON" */ + + do + { + regval = stm32_getreg(STM32_USBOTG_CLKST); + } + while ((regval & STM32_CLKCTRL_ENABLES) != STM32_CLKCTRL_ENABLES); + + /* Set the OTG status and control register. Bits 0:1 apparently mean: + * + * 00: U1=device, U2=host + * 01: U1=host, U2=host + * 10: reserved + * 11: U1=host, U2=device + * + * We need only select U1=host (Bit 0=1, Bit 1 is not used on STM32); + * NOTE: The PORTSEL clock needs to be enabled when accessing OTGSTCTRL + */ + + stm32_putreg(1, STM32_USBOTG_STCTRL); + + /* Now we can turn off the PORTSEL clock */ + + stm32_putreg((STM32_CLKCTRL_ENABLES & ~USBOTG_CLK_PORTSELCLK), STM32_USBOTG_CLKCTRL); + + /* Configure I/O pins */ + + usbhost_dumpgpio(); + stm32_configgpio(GPIO_USB_DP); /* Positive differential data */ + stm32_configgpio(GPIO_USB_DM); /* Negative differential data */ + stm32_configgpio(GPIO_USB_UPLED); /* GoodLink LED control signal */ + stm32_configgpio(GPIO_USB_PPWR); /* Port Power enable signal for USB port */ + stm32_configgpio(GPIO_USB_PWRD); /* Power Status for USB port (host power switch) */ + stm32_configgpio(GPIO_USB_OVRCR); /* USB port Over-Current status */ + usbhost_dumpgpio(); + + udbg("Initializing Host Stack\n"); + + /* Show AHB SRAM memory map */ + +#if 0 /* Useful if you have doubts about the layout */ + uvdbg("AHB SRAM:\n"); + uvdbg(" HCCA: %08x %d\n", STM32_HCCA_BASE, STM32_HCCA_SIZE); + uvdbg(" TDTAIL: %08x %d\n", STM32_TDTAIL_ADDR, STM32_TD_SIZE); + uvdbg(" EDCTRL: %08x %d\n", STM32_EDCTRL_ADDR, STM32_ED_SIZE); + uvdbg(" EDFREE: %08x %d\n", STM32_EDFREE_BASE, STM32_ED_SIZE); + uvdbg(" TDFREE: %08x %d\n", STM32_TDFREE_BASE, STM32_EDFREE_SIZE); + uvdbg(" TBFREE: %08x %d\n", STM32_TBFREE_BASE, STM32_TBFREE_SIZE); + uvdbg(" IOFREE: %08x %d\n", STM32_IOFREE_BASE, STM32_IOBUFFERS * CONFIG_USBHOST_IOBUFSIZE); +#endif + + /* Initialize all the TDs, EDs and HCCA to 0 */ + + memset((void*)HCCA, 0, sizeof(struct ohci_hcca_s)); + memset((void*)TDTAIL, 0, sizeof(struct ohci_gtd_s)); + memset((void*)EDCTRL, 0, sizeof(struct stm32_ed_s)); + sem_init(&EDCTRL->wdhsem, 0, 0); + + /* Initialize user-configurable EDs */ + + buffer = (uint8_t *)STM32_EDFREE_BASE; + for (i = 0; i < CONFIG_USBHOST_NEDS; i++) + { + /* Put the ED in a free list */ + + stm32_edfree((struct stm32_ed_s *)buffer); + buffer += STM32_ED_SIZE; + } + + /* Initialize user-configurable TDs */ + + buffer = (uint8_t *)STM32_TDFREE_BASE; + for (i = 0; i < CONFIG_USBHOST_NTDS; i++) + { + /* Put the ED in a free list */ + + stm32_tdfree((struct stm32_gtd_s *)buffer); + buffer += STM32_TD_SIZE; + } + + /* Initialize user-configurable request/descriptor transfer buffers */ + + buffer = (uint8_t *)STM32_TBFREE_BASE; + for (i = 0; i < CONFIG_USBHOST_TDBUFFERS; i++) + { + /* Put the TD buffer in a free list */ + + stm32_tbfree(buffer); + buffer += CONFIG_USBHOST_TDBUFSIZE; + } + +#if STM32_IOBUFFERS > 0 + /* Initialize user-configurable IO buffers */ + + buffer = (uint8_t *)STM32_IOFREE_BASE; + for (i = 0; i < STM32_IOBUFFERS; i++) + { + /* Put the IO buffer in a free list */ + + stm32_freeio(buffer); + buffer += CONFIG_USBHOST_IOBUFSIZE; + } +#endif + + /* Wait 50MS then perform hardware reset */ + + up_mdelay(50); + + stm32_putreg(0, STM32_USBHOST_CTRL); /* Hardware reset */ + stm32_putreg(0, STM32_USBHOST_CTRLHEADED); /* Initialize control list head to Zero */ + stm32_putreg(0, STM32_USBHOST_BULKHEADED); /* Initialize bulk list head to Zero */ + + /* Software reset */ + + stm32_putreg(OHCI_CMDST_HCR, STM32_USBHOST_CMDST); + + /* Write Fm interval (FI), largest data packet counter (FSMPS), and + * periodic start. + */ + + stm32_putreg(DEFAULT_FMINTERVAL, STM32_USBHOST_FMINT); + stm32_putreg(DEFAULT_PERSTART, STM32_USBHOST_PERSTART); + + /* Put HC in operational state */ + + regval = stm32_getreg(STM32_USBHOST_CTRL); + regval &= ~OHCI_CTRL_HCFS_MASK; + regval |= OHCI_CTRL_HCFS_OPER; + stm32_putreg(regval, STM32_USBHOST_CTRL); + + /* Set global power in HcRhStatus */ + + stm32_putreg(OHCI_RHSTATUS_SGP, STM32_USBHOST_RHSTATUS); + + /* Set HCCA base address */ + + stm32_putreg((uint32_t)HCCA, STM32_USBHOST_HCCA); + + /* Set up EP0 */ + + stm32_ep0init(priv); + + /* Clear pending interrupts */ + + regval = stm32_getreg(STM32_USBHOST_INTST); + stm32_putreg(regval, STM32_USBHOST_INTST); + + /* Enable OHCI interrupts */ + + stm32_putreg((STM32_ALL_INTS|OHCI_INT_MIE), STM32_USBHOST_INTEN); + + /* Attach USB host controller interrupt handler */ + + if (irq_attach(STM32_IRQ_USB, stm32_usbinterrupt) != 0) + { + udbg("Failed to attach IRQ\n"); + return NULL; + } + + /* Enable USB interrupts at the SYCON controller. Disable interrupts + * because this register may be shared with other drivers. + */ + + flags = irqsave(); + regval = stm32_getreg(STM32_SYSCON_USBINTST); + regval |= SYSCON_USBINTST_ENINTS; + stm32_putreg(regval, STM32_SYSCON_USBINTST); + irqrestore(flags); + + /* If there is a USB device in the slot at power up, then we will not + * get the status change interrupt to signal us that the device is + * connected. We need to set the initial connected state accordingly. + */ + + regval = stm32_getreg(STM32_USBHOST_RHPORTST1); + priv->connected = ((regval & OHCI_RHPORTST_CCS) != 0); + + /* Enable interrupts at the interrupt controller */ + + up_enable_irq(STM32_IRQ_USB); /* enable USB interrupt */ + udbg("USB host Initialized, Device connected:%s\n", + priv->connected ? "YES" : "NO"); + + return &priv->drvr; +} diff --git a/nuttx/arch/arm/src/stm32/stm32_usbhost.h b/nuttx/arch/arm/src/stm32/stm32_usbhost.h new file mode 100644 index 0000000000..854c327235 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_usbhost.h @@ -0,0 +1,71 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_usbhost.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_USBHOST_H +#define __ARCH_ARM_SRC_STM32_STM32_USBHOST_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include + +#include "chip.h" +#include "chip/stm32_otgfs.h" + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_USBHOST_H */ + diff --git a/nuttx/arch/arm/src/stm32/stm32_vectors.S b/nuttx/arch/arm/src/stm32/stm32_vectors.S new file mode 100644 index 0000000000..b75237e40f --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_vectors.S @@ -0,0 +1,421 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_vectors.S + * arch/arm/src/chip/stm32_vectors.S + * + * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + + +#include + +#include "chip.h" + +/************************************************************************************ + * Configuration + ************************************************************************************/ +/* Check if common ARMv7 interrupt vectoring is used (see + * arch/arm/src/armv7-m/up_vectors.S) + */ + +#ifndef CONFIG_ARMV7M_CMNVECTOR + +/************************************************************************************ + * Preprocessor Definitions + ************************************************************************************/ +/* Memory Map: + * + * 0x0800:0000 - Beginning of FLASH. Address of vectors (if not using bootloader) + * Mapped to address 0x0000:0000 at boot time. + * 0x0800:3000 - Address of vectors if using bootloader + * 0x0803:ffff - End of flash + * 0x2000:0000 - Start of SRAM and start of .data (_sdata) + * - End of .data (_edata) abd start of .bss (_sbss) + * - End of .bss (_ebss) and bottom of idle stack + * - _ebss + CONFIG_IDLETHREAD_STACKSIZE = end of idle stack, start of heap + * 0x2000:ffff - End of SRAM and end of heap + */ + +#define IDLE_STACK (_ebss+CONFIG_IDLETHREAD_STACKSIZE-4) +#define HEAP_BASE (_ebss+CONFIG_IDLETHREAD_STACKSIZE-4) + +/* The Cortex-M3 return from interrupt is unusual. We provide the following special + * address to the BX instruction. The particular value also forces a return to + * thread mode and covers state from the main stack point, the MSP (vs. the MSP). + */ + +#define EXC_RETURN 0xfffffff9 + +/************************************************************************************ + * Global Symbols + ************************************************************************************/ + + .globl __start + + .syntax unified + .thumb + .file "stm32_vectors.S" + +/************************************************************************************ + * Macros + ************************************************************************************/ + +/* On entry into an IRQ, the hardware automatically saves the xPSR, PC, LR, R12, R0-R3 + * registers on the stack, then branches to an instantantiation of the following + * macro. This macro simply loads the IRQ number into R0, then jumps to the common + * IRQ handling logic. + */ + + .macro HANDLER, label, irqno + .thumb_func +\label: + mov r0, #\irqno + b stm32_common + .endm + +/************************************************************************************ + * Vectors + ************************************************************************************/ + + .section .vectors, "ax" + .code 16 + .align 2 + .globl stm32_vectors + .type stm32_vectors, function + +stm32_vectors: + +/* Processor Exceptions */ + + .word IDLE_STACK /* Vector 0: Reset stack pointer */ + .word __start /* Vector 1: Reset vector */ + .word stm32_nmi /* Vector 2: Non-Maskable Interrupt (NMI) */ + .word stm32_hardfault /* Vector 3: Hard fault */ + .word stm32_mpu /* Vector 4: Memory management (MPU) */ + .word stm32_busfault /* Vector 5: Bus fault */ + .word stm32_usagefault /* Vector 6: Usage fault */ + .word stm32_reserved /* Vector 7: Reserved */ + .word stm32_reserved /* Vector 8: Reserved */ + .word stm32_reserved /* Vector 9: Reserved */ + .word stm32_reserved /* Vector 10: Reserved */ + .word stm32_svcall /* Vector 11: SVC call */ + .word stm32_dbgmonitor /* Vector 12: Debug monitor */ + .word stm32_reserved /* Vector 13: Reserved */ + .word stm32_pendsv /* Vector 14: Pendable system service request */ + .word stm32_systick /* Vector 15: System tick */ + +/* External Interrupts */ + +#undef VECTOR +#define VECTOR(l,i) .word l + +#if defined(CONFIG_STM32_STM32F10XX) +# include "chip/chip/stm32f10xxx_vectors.h" +#elif defined(CONFIG_STM32_STM32F20XX) +# include "chip/chip/stm32f20xxx_vectors.h" +#elif defined(CONFIG_STM32_STM32F40XX) +# include "chip/chip/stm32f40xxx_vectors.h" +#else +# error "No vectors for STM32 chip" +#endif + .size stm32_vectors, .-stm32_vectors + +/************************************************************************************ + * .text + ************************************************************************************/ + + .text + .type handlers, function + .thumb_func +handlers: + HANDLER stm32_reserved, STM32_IRQ_RESERVED /* Unexpected/reserved vector */ + HANDLER stm32_nmi, STM32_IRQ_NMI /* Vector 2: Non-Maskable Interrupt (NMI) */ + HANDLER stm32_hardfault, STM32_IRQ_HARDFAULT /* Vector 3: Hard fault */ + HANDLER stm32_mpu, STM32_IRQ_MEMFAULT /* Vector 4: Memory management (MPU) */ + HANDLER stm32_busfault, STM32_IRQ_BUSFAULT /* Vector 5: Bus fault */ + HANDLER stm32_usagefault, STM32_IRQ_USAGEFAULT /* Vector 6: Usage fault */ + HANDLER stm32_svcall, STM32_IRQ_SVCALL /* Vector 11: SVC call */ + HANDLER stm32_dbgmonitor, STM32_IRQ_DBGMONITOR /* Vector 12: Debug Monitor */ + HANDLER stm32_pendsv, STM32_IRQ_PENDSV /* Vector 14: Penable system service request */ + HANDLER stm32_systick, STM32_IRQ_SYSTICK /* Vector 15: System tick */ + +#undef VECTOR +#define VECTOR(l,i) HANDLER l, i + +#if defined(CONFIG_STM32_STM32F10XX) +# include "chip/chip/stm32f10xxx_vectors.h" +#elif defined(CONFIG_STM32_STM32F20XX) +# include "chip/chip/stm32f20xxx_vectors.h" +#elif defined(CONFIG_STM32_STM32F40XX) +# include "chip/chip/stm32f40xxx_vectors.h" +#else +# error "No handlers for STM32 chip" +#endif + +/* Common IRQ handling logic. On entry here, the return stack is on either + * the PSP or the MSP and looks like the following: + * + * REG_XPSR + * REG_R15 + * REG_R14 + * REG_R12 + * REG_R3 + * REG_R2 + * REG_R1 + * MSP->REG_R0 + * + * And + * R0 contains the IRQ number + * R14 Contains the EXC_RETURN value + * We are in handler mode and the current SP is the MSP + */ + +stm32_common: + + /* Complete the context save */ + +#ifdef CONFIG_NUTTX_KERNEL + /* The EXC_RETURN value will be 0xfffffff9 (privileged thread) or 0xfffffff1 + * (handler mode) if the state is on the MSP. It can only be on the PSP if + * EXC_RETURN is 0xfffffffd (unprivileged thread) + */ + + adds r2, r14, #3 /* If R14=0xfffffffd, then r2 == 0 */ + ite ne /* Next two instructions are conditional */ + mrsne r1, msp /* R1=The main stack pointer */ + mrseq r1, psp /* R1=The process stack pointer */ +#else + mrs r1, msp /* R1=The main stack pointer */ +#endif + + /* r1 holds the value of the stack pointer AFTER the excption handling logic + * pushed the various registers onto the stack. Get r2 = the value of the + * stack pointer BEFORE the interrupt modified it. + */ + + mov r2, r1 /* R2=Copy of the main/process stack pointer */ + add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */ + mrs r3, primask /* R3=Current PRIMASK setting */ + +#ifdef CONFIG_ARCH_FPU + /* Skip over the block of memory reserved for floating pointer register save. + * Lazy FPU register saving is used. FPU registers will be saved in this + * block only if a context switch occurs (this means, of course, that the FPU + * cannot be used in interrupt processing). + */ + + sub r1, #(4*SW_FPU_REGS) +#endif + + /* Save the the remaining registers on the stack after the registers pushed + * by the exception handling logic. r2=SP and r3=primask, r4-r11,r14=register + * values. + */ + +#ifdef CONFIG_NUTTX_KERNEL + stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP value */ +#else + stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */ +#endif + + /* Disable interrupts, select the stack to use for interrupt handling + * and call up_doirq to handle the interrupt + */ + + cpsid i /* Disable further interrupts */ + + /* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will use a special interrupt + * stack pointer. The way that this is done here prohibits nested interrupts! + * Otherwise, we will re-use the main stack for interrupt level processing. + */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + ldr sp, =g_intstackbase + str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */ + bl up_doirq /* R0=IRQ, R1=register save (msp) */ + ldr r1, [sp, #+4]! /* Recover R1=main stack pointer */ +#else + mov sp, r1 /* We are using the main stack pointer */ + bl up_doirq /* R0=IRQ, R1=register save (msp) */ + mov r1, sp /* Recover R1=main stack pointer */ +#endif + + /* On return from up_doirq, R0 will hold a pointer to register context + * array to use for the interrupt return. If that return value is the same + * as current stack pointer, then things are relatively easy. + */ + + cmp r0, r1 /* Context switch? */ + beq 1f /* Branch if no context switch */ + + /* We are returning with a pending context switch. + * + * If the FPU is enabled, then we will need to restore FPU registers. + * This is not done in normal interrupt save/restore because the cost + * is prohibitive. This is only done when switching contexts. A + * consequence of this is that floating point operations may not be + * performed in interrupt handling logic. + * + * Here: + * r0 = Address of the register save area + + * NOTE: It is a requirement that up_restorefpu() preserve the value of + * r0! + */ + +#ifdef CONFIG_ARCH_FPU + bl up_restorefpu /* Restore the FPU registers */ +#endif + + /* Returning with a pending context switch is different from the normal + * return because in this case, the register save structure does not lie + * on the stack but, rather, are within a TCB structure. We'll have to + * copy somevalues to the new stack. + */ + + add r1, r0, #SW_XCPT_SIZE /* R1=Address of HW save area in reg array */ + ldmia r1, {r4-r11} /* Fetch eight registers in HW save area */ + ldr r1, [r0, #(4*REG_SP)] /* R1=Value of SP before interrupt */ + stmdb r1!, {r4-r11} /* Store eight registers in HW save area */ +#ifdef CONFIG_NUTTX_KERNEL + ldmia r0, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */ +#else + ldmia r0, {r2-r11} /* Recover R4-R11 + 2 temp values */ +#endif + b 2f /* Re-join common logic */ + + /* We are returning with no context switch. We simply need to "unwind" + * the same stack frame that we created + * + * Here: + * r1 = Address of the return stack (same as r0) + */ +1: +#ifdef CONFIG_NUTTX_KERNEL + ldmia r1!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */ +#else + ldmia r1!, {r2-r11} /* Recover R4-R11 + 2 temp values */ +#endif +#ifdef CONFIG_ARCH_FPU + /* Skip over the block of memory reserved for floating pointer register + * save. Then R1 is the address of the HW save area + */ + + add r1, #(4*SW_FPU_REGS) +#endif + + /* Set up to return from the exception + * + * Here: + * r1 = Address on the target thread's stack position at the start of + * the registers saved by hardware + * r3 = primask + * r4-r11 = restored register values + */ +2: +#ifdef CONFIG_NUTTX_KERNEL + /* The EXC_RETURN value will be 0xfffffff9 (privileged thread) or 0xfffffff1 + * (handler mode) if the state is on the MSP. It can only be on the PSP if + * EXC_RETURN is 0xfffffffd (unprivileged thread) + */ + + adds r0, r14, #3 /* If R14=0xfffffffd, then r0 == 0 */ + ite ne /* Next two instructions are condition */ + msrne msp, r1 /* R1=The main stack pointer */ + msreq psp, r1 /* R1=The process stack pointer */ +#else + msr msp, r1 /* Recover the return MSP value */ + + /* Preload r14 with the special return value first (so that the return + * actually occurs with interrupts still disabled). + */ + + ldr r14, =EXC_RETURN /* Load the special value */ +#endif + + /* Restore the interrupt state */ + + msr primask, r3 /* Restore interrupts */ + + /* Always return with R14 containing the special value that will: (1) + * return to thread mode, and (2) continue to use the MSP + */ + + bx r14 /* And return */ + .size handlers, .-handlers + +/************************************************************************************ + * Name: up_interruptstack/g_intstackbase + * + * Description: + * Shouldn't happen + * + ************************************************************************************/ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + .bss + .global g_intstackbase + .align 4 +up_interruptstack: + .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3) +g_intstackbase: + .size up_interruptstack, .-up_interruptstack +#endif +#endif /* CONFIG_ARMV7M_CMNVECTOR */ + +/************************************************************************************ + * .rodata + ************************************************************************************/ + + .section .rodata, "a" + +/* Variables: _sbss is the start of the BSS region (see ld.script) _ebss is the end + * of the BSS regsion (see ld.script). The idle task stack starts at the end of BSS + * and is of size CONFIG_IDLETHREAD_STACKSIZE. The IDLE thread is the thread that + * the system boots on and, eventually, becomes the idle, do nothing task that runs + * only when there is nothing else to run. The heap continues from there until the + * end of memory. See g_heapbase below. + */ + + .globl g_heapbase + .type g_heapbase, object +g_heapbase: + .long _ebss+CONFIG_IDLETHREAD_STACKSIZE + .size g_heapbase, .-g_heapbase + + .end + diff --git a/nuttx/arch/arm/src/stm32/stm32_waste.c b/nuttx/arch/arm/src/stm32/stm32_waste.c new file mode 100644 index 0000000000..a680b8b0f3 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_waste.c @@ -0,0 +1,57 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_waste.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "stm32_waste.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +uint32_t idle_wastecounter = 0; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void up_waste(void) +{ + idle_wastecounter++; +} diff --git a/nuttx/arch/arm/src/stm32/stm32_waste.h b/nuttx/arch/arm/src/stm32/stm32_waste.h new file mode 100644 index 0000000000..fa734f432b --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_waste.h @@ -0,0 +1,78 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_waste.h + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_WASTE_H +#define __ARCH_ARM_SRC_STM32_STM32_WASTE_H + +/* Waste CPU Time */ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/** Waste CPU Time + * + * up_waste() is the logic that will be executed when portions of kernel + * or user-app is polling some register or similar, waiting for desired + * status. This time is wasted away. This function offers a measure of + * badly written piece of software or some undesired behavior. + * + * At the same time this function adds to some IDLE time which portion + * cannot be used for other purposes (yet). + **/ + +EXTERN void up_waste(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_RRC_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_wdg.h b/nuttx/arch/arm/src/stm32/stm32_wdg.h new file mode 100644 index 0000000000..38af388f92 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_wdg.h @@ -0,0 +1,118 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_wdg.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_WDG_H +#define __ARCH_ARM_SRC_STM32_STM32_WDG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" +#include "chip/stm32_wdg.h" + +#ifdef CONFIG_WATCHDOG + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_iwdginitialize + * + * Description: + * Initialize the IWDG watchdog time. The watchdog timer is intialized and + * registers as 'devpath. The initial state of the watchdog time is + * disabled. + * + * Input Parameters: + * devpath - The full path to the watchdog. This should be of the form + * /dev/watchdog0 + * lsifreq - The calibrated LSI clock frequency + * + * Returned Values: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_STM32_IWDG +EXTERN void stm32_iwdginitialize(FAR const char *devpath, uint32_t lsifreq); +#endif + +/**************************************************************************** + * Name: stm32_wwdginitialize + * + * Description: + * Initialize the WWDG watchdog time. The watchdog timer is intialized and + * registers as 'devpath. The initial state of the watchdog time is + * disabled. + * + * Input Parameters: + * devpath - The full path to the watchdog. This should be of the form + * /dev/watchdog0 + * + * Returned Values: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_STM32_WWDG +EXTERN void stm32_wwdginitialize(FAR const char *devpath); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_WATCHDOG */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_WDG_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_wwdg.c b/nuttx/arch/arm/src/stm32/stm32_wwdg.c new file mode 100644 index 0000000000..4506fa4e08 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32_wwdg.c @@ -0,0 +1,807 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_wwdg.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "chip/stm32_dbgmcu.h" +#include "stm32_wdg.h" + +#if defined(CONFIG_WATCHDOG) && defined(CONFIG_STM32_WWDG) + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Clocking *****************************************************************/ +/* The minimum frequency of the WWDG clock is: + * + * Fmin = PCLK1 / 4096 / 8 + * + * So the maximum delay (in milliseconds) is then: + * + * 1000 * (WWDG_CR_T_MAX+1) / Fmin + * + * For example, if PCLK1 = 42MHz, then the maximum delay is: + * + * Fmin = 1281.74 + * 1000 * 64 / Fmin = 49.93 msec + */ + +#define WWDG_FMIN (STM32_PCLK1_FREQUENCY / 4096 / 8) +#define WWDG_MAXTIMEOUT (1000 * (WWDG_CR_T_MAX+1) / WWDG_FMIN) + +/* Configuration ************************************************************/ + +#ifndef CONFIG_STM32_WWDG_DEFTIMOUT +# define CONFIG_STM32_WWDG_DEFTIMOUT WWDG_MAXTIMEOUT +#endif + +/* Debug ********************************************************************/ +/* Non-standard debug that may be enabled just for testing the watchdog + * driver. NOTE: that only lldbg types are used so that the output is + * immediately available. + */ + +#ifdef CONFIG_DEBUG_WATCHDOG +# define wddbg lldbg +# define wdvdbg llvdbg +#else +# define wddbg(x...) +# define wdvdbg(x...) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ +/* This structure provides the private representation of the "lower-half" + * driver state structure. This structure must be cast-compatible with the + * well-known watchdog_lowerhalf_s structure. + */ + +struct stm32_lowerhalf_s +{ + FAR const struct watchdog_ops_s *ops; /* Lower half operations */ + xcpt_t handler; /* Current EWI interrupt handler */ + uint32_t timeout; /* The actual timeout value */ + uint32_t fwwdg; /* WWDG clock frequency */ + bool started; /* The timer has been started */ + uint8_t reload; /* The 7-bit reload field reset value */ + uint8_t window; /* The 7-bit window (W) field value */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* Register operations ******************************************************/ + +#if defined(CONFIG_STM32_WWDG_REGDEBUG) && defined(CONFIG_DEBUG) +static uint16_t stm32_getreg(uint32_t addr); +static void stm32_putreg(uint16_t val, uint32_t addr); +#else +# define stm32_getreg(addr) getreg32(addr) +# define stm32_putreg(val,addr) putreg32(val,addr) +#endif +static void stm32_setwindow(FAR struct stm32_lowerhalf_s *priv, + uint8_t window); + +/* Interrupt hanlding *******************************************************/ + +static int stm32_interrupt(int irq, FAR void *context); + +/* "Lower half" driver methods **********************************************/ + +static int stm32_start(FAR struct watchdog_lowerhalf_s *lower); +static int stm32_stop(FAR struct watchdog_lowerhalf_s *lower); +static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower); +static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower, + FAR struct watchdog_status_s *status); +static int stm32_settimeout(FAR struct watchdog_lowerhalf_s *lower, + uint32_t timeout); +static xcpt_t stm32_capture(FAR struct watchdog_lowerhalf_s *lower, + xcpt_t handler); +static int stm32_ioctl(FAR struct watchdog_lowerhalf_s *lower, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* "Lower half" driver methods */ + +static const struct watchdog_ops_s g_wdgops = +{ + .start = stm32_start, + .stop = stm32_stop, + .keepalive = stm32_keepalive, + .getstatus = stm32_getstatus, + .settimeout = stm32_settimeout, + .capture = stm32_capture, + .ioctl = stm32_ioctl, +}; + +/* "Lower half" driver state */ + +static struct stm32_lowerhalf_s g_wdgdev; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_getreg + * + * Description: + * Get the contents of an STM32 register + * + ****************************************************************************/ + +#if defined(CONFIG_STM32_WWDG_REGDEBUG) && defined(CONFIG_DEBUG) +static uint16_t stm32_getreg(uint32_t addr) +{ + static uint32_t prevaddr = 0; + static uint32_t count = 0; + static uint16_t preval = 0; + + /* Read the value from the register */ + + uint16_t val = getreg16(addr); + + /* Is this the same value that we read from the same registe last time? Are + * we polling the register? If so, suppress some of the output. + */ + + if (addr == prevaddr && val == preval) + { + if (count == 0xffffffff || ++count > 3) + { + if (count == 4) + { + lldbg("...\n"); + } + return val; + } + } + + /* No this is a new address or value */ + + else + { + /* Did we print "..." for the previous value? */ + + if (count > 3) + { + /* Yes.. then show how many times the value repeated */ + + lldbg("[repeats %d more times]\n", count-3); + } + + /* Save the new address, value, and count */ + + prevaddr = addr; + preval = val; + count = 1; + } + + /* Show the register value read */ + + lldbg("%08x->%04x\n", addr, val); + return val; +} +#endif + +/**************************************************************************** + * Name: stm32_putreg + * + * Description: + * Set the contents of an STM32 register to a value + * + ****************************************************************************/ + +#if defined(CONFIG_STM32_WWDG_REGDEBUG) && defined(CONFIG_DEBUG) +static void stm32_putreg(uint16_t val, uint32_t addr) +{ + /* Show the register value being written */ + + lldbg("%08x<-%04x\n", addr, val); + + /* Write the value */ + + putreg16(val, addr); +} +#endif + +/**************************************************************************** + * Name: stm32_setwindow + * + * Description: + * Set the CFR window value. The window value is compared to the down- + * counter when the counter is updated. The WWDG counter should be updated + * only when the counter is below this window value (and greater than 64) + * otherwise a reset will be generated + * + ****************************************************************************/ + +static void stm32_setwindow(FAR struct stm32_lowerhalf_s *priv, uint8_t window) +{ + uint16_t regval; + + /* Set W[6:0] bits according to selected window value */ + + regval = stm32_getreg(STM32_WWDG_CFR); + regval &= ~WWDG_CFR_W_MASK; + regval |= window << WWDG_CFR_W_SHIFT; + stm32_putreg(regval, STM32_WWDG_CFR); + + /* Remember the window setting */ + + priv->window = window; +} + +/**************************************************************************** + * Name: stm32_interrupt + * + * Description: + * WWDG early warning interrupt + * + * Input Parameters: + * Usual interrupt handler arguments. + * + * Returned Values: + * Always returns OK. + * + ****************************************************************************/ + +static int stm32_interrupt(int irq, FAR void *context) +{ + FAR struct stm32_lowerhalf_s *priv = &g_wdgdev; + uint16_t regval; + + /* Check if the EWI interrupt is really pending */ + + regval = stm32_getreg(STM32_WWDG_SR); + if ((regval & WWDG_SR_EWIF) != 0) + { + /* Is there a registered handler? */ + + if (priv->handler) + { + /* Yes... NOTE: This interrupt service routine (ISR) must reload + * the WWDG counter to prevent the reset. Otherwise, we will reset + * upon return. + */ + + priv->handler(irq, context); + } + + /* The EWI interrupt is cleared by writing '0' to the EWIF bit in the + * WWDG_SR register. + */ + + regval &= ~WWDG_SR_EWIF; + stm32_putreg(regval, STM32_WWDG_SR); + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_start + * + * Description: + * Start the watchdog timer, resetting the time to the current timeout, + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_start(FAR struct watchdog_lowerhalf_s *lower) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; + + wdvdbg("Entry\n"); + DEBUGASSERT(priv); + + /* The watchdog is always disabled after a reset. It is enabled by setting + * the WDGA bit in the WWDG_CR register, then it cannot be disabled again + * except by a reset. + */ + + stm32_putreg(WWDG_CR_WDGA | WWDG_CR_T_RESET | priv->reload, STM32_WWDG_CR); + priv->started = true; + return OK; +} + +/**************************************************************************** + * Name: stm32_stop + * + * Description: + * Stop the watchdog timer + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_stop(FAR struct watchdog_lowerhalf_s *lower) +{ + /* The watchdog is always disabled after a reset. It is enabled by setting + * the WDGA bit in the WWDG_CR register, then it cannot be disabled again + * except by a reset. + */ + + wdvdbg("Entry\n"); + return -ENOSYS; +} + +/**************************************************************************** + * Name: stm32_keepalive + * + * Description: + * Reset the watchdog timer to the current timeout value, prevent any + * imminent watchdog timeouts. This is sometimes referred as "pinging" + * the atchdog timer or "petting the dog". + * + * The application program must write in the WWDG_CR register at regular + * intervals during normal operation to prevent an MCU reset. This operation + * must occur only when the counter value is lower than the window register + * value. The value to be stored in the WWDG_CR register must be between + * 0xff and 0xC0: + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; + + wdvdbg("Entry\n"); + DEBUGASSERT(priv); + + /* Write to T[6:0] bits to configure the counter value, no need to do + * a read-modify-write; writing a 0 to WDGA bit does nothing. + */ + + stm32_putreg((WWDG_CR_T_RESET | priv->reload), STM32_WWDG_CR); + return OK; +} + +/**************************************************************************** + * Name: stm32_getstatus + * + * Description: + * Get the current watchdog timer status + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * stawtus - The location to return the watchdog status information. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower, + FAR struct watchdog_status_s *status) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; + uint32_t elapsed; + uint16_t reload; + + wdvdbg("Entry\n"); + DEBUGASSERT(priv); + + /* Return the status bit */ + + status->flags = WDFLAGS_RESET; + if (priv->started) + { + status->flags |= WDFLAGS_ACTIVE; + } + + if (priv->handler) + { + status->flags |= WDFLAGS_CAPTURE; + } + + /* Return the actual timeout is milliseconds */ + + status->timeout = priv->timeout; + + /* Get the time remaining until the watchdog expires (in milliseconds) */ + + reload = (stm32_getreg(STM32_WWDG_CR) >> WWDG_CR_T_SHIFT) & 0x7f; + elapsed = priv->reload - reload; + status->timeleft = (priv->timeout * elapsed) / (priv->reload + 1); + + wdvdbg("Status :\n"); + wdvdbg(" flags : %08x\n", status->flags); + wdvdbg(" timeout : %d\n", status->timeout); + wdvdbg(" timeleft : %d\n", status->flags); + return OK; +} + +/**************************************************************************** + * Name: stm32_settimeout + * + * Description: + * Set a new timeout value (and reset the watchdog timer) + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * timeout - The new timeout value in millisecnds. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_settimeout(FAR struct watchdog_lowerhalf_s *lower, + uint32_t timeout) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; + uint32_t fwwdg; + uint32_t reload; + uint16_t regval; + int wdgtb; + + DEBUGASSERT(priv); + wdvdbg("Entry: timeout=%d\n", timeout); + + /* Can this timeout be represented? */ + + if (timeout < 1 || timeout > WWDG_MAXTIMEOUT) + { + wddbg("Cannot represent timeout=%d > %d\n", + timeout, WWDG_MAXTIMEOUT); + return -ERANGE; + } + + /* Determine prescaler value. + * + * Fwwdg = PCLK1/4096/prescaler. + * + * Where + * Fwwwdg is the frequency of the WWDG clock + * wdgtb is one of {1, 2, 4, or 8} + */ + + /* Select the smallest prescaler that will result in a reload field value that is + * less than the maximum. + */ + + for (wdgtb = 0; ; wdgtb++) + { + /* WDGTB = 0 -> Divider = 1 = 1 << 0 + * WDGTB = 1 -> Divider = 2 = 1 << 1 + * WDGTB = 2 -> Divider = 4 = 1 << 2 + * WDGTB = 3 -> Divider = 8 = 1 << 3 + */ + + /* Get the WWDG counter frequency in Hz. */ + + fwwdg = (STM32_PCLK1_FREQUENCY/4096) >> wdgtb; + + /* The formula to calculate the timeout value is given by: + * + * timeout = 1000 * (reload + 1) / Fwwdg, OR + * reload = timeout * Fwwdg / 1000 - 1 + * + * Where + * timeout is the desired timout in milliseconds + * reload is the contents of T{5:0] + * Fwwdg is the frequency of the WWDG clock + */ + + reload = timeout * fwwdg / 1000 - 1; + + /* If this reload valid is less than the maximum or we are not ready + * at the prescaler value, then break out of the loop to use these + * settings. + */ + +#if 0 + wdvdbg("wdgtb=%d fwwdg=%d reload=%d timout=%d\n", + wdgtb, fwwdg, reload, 1000 * (reload + 1) / fwwdg); +#endif + if (reload <= WWDG_CR_T_MAX || wdgtb == 3) + { + /* Note that we explicity break out of the loop rather than using + * the 'for' loop termination logic because we do not want the + * value of wdgtb to be incremented. + */ + + break; + } + } + + /* Make sure that the final reload value is within range */ + + if (reload > WWDG_CR_T_MAX) + { + reload = WWDG_CR_T_MAX; + } + + /* Calculate and save the actual timeout value in milliseconds: + * + * timeout = 1000 * (reload + 1) / Fwwdg + */ + + priv->timeout = 1000 * (reload + 1) / fwwdg; + + /* Remember the selected values */ + + priv->fwwdg = fwwdg; + priv->reload = reload; + + wdvdbg("wdgtb=%d fwwdg=%d reload=%d timout=%d\n", + wdgtb, fwwdg, reload, priv->timeout); + + /* Set WDGTB[1:0] bits according to calculated value */ + + regval = stm32_getreg(STM32_WWDG_CFR); + regval &= ~WWDG_CFR_WDGTB_MASK; + regval |= (uint16_t)wdgtb << WWDG_CFR_WDGTB_SHIFT; + stm32_putreg(regval, STM32_WWDG_CFR); + + /* Reset the 7-bit window value to the maximum value.. essentially disabling + * the lower limit of the watchdog reset time. + */ + + stm32_setwindow(priv, 0x7f); + return OK; +} + +/**************************************************************************** + * Name: stm32_capture + * + * Description: + * Don't reset on watchdog timer timeout; instead, call this user provider + * timeout handler. NOTE: Providing handler==NULL will restore the reset + * behavior. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * newhandler - The new watchdog expiration function pointer. If this + * function pointer is NULL, then the the reset-on-expiration + * behavior is restored, + * + * Returned Values: + * The previous watchdog expiration function pointer or NULL is there was + * no previous function pointer, i.e., if the previous behavior was + * reset-on-expiration (NULL is also returned if an error occurs). + * + ****************************************************************************/ + +static xcpt_t stm32_capture(FAR struct watchdog_lowerhalf_s *lower, + xcpt_t handler) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; + irqstate_t flags; + xcpt_t oldhandler; + uint16_t regval; + + DEBUGASSERT(priv); + wdvdbg("Entry: handler=%p\n", handler); + + /* Get the old handler return value */ + + flags = irqsave(); + oldhandler = priv->handler; + + /* Save the new handler */ + + priv->handler = handler; + + /* Are we attaching or detaching the handler? */ + + regval = stm32_getreg(STM32_WWDG_CFR); + if (handler) + { + /* Attaching... Enable the EWI interrupt */ + + regval |= WWDG_CFR_EWI; + stm32_putreg(regval, STM32_WWDG_CFR); + + up_enable_irq(STM32_IRQ_WWDG); + } + else + { + /* Detaching... Disable the EWI interrupt */ + + regval &= ~WWDG_CFR_EWI; + stm32_putreg(regval, STM32_WWDG_CFR); + + up_disable_irq(STM32_IRQ_WWDG); + } + + irqrestore(flags); + return oldhandler; +} + +/**************************************************************************** + * Name: stm32_ioctl + * + * Description: + * Any ioctl commands that are not recognized by the "upper-half" driver + * are forwarded to the lower half driver through this method. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * cmd - The ioctol command value + * arg - The optional argument that accompanies the 'cmd'. The + * interpretation of this argument depends on the particular + * command. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_ioctl(FAR struct watchdog_lowerhalf_s *lower, int cmd, + unsigned long arg) +{ + FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower; + int ret = -ENOTTY; + + DEBUGASSERT(priv); + wdvdbg("Entry: cmd=%d arg=%ld\n", cmd, arg); + + /* WDIOC_MINTIME: Set the minimum ping time. If two keepalive ioctls + * are received within this time, a reset event will be generated. + * Argument: A 32-bit time value in milliseconds. + */ + + if (cmd == WDIOC_MINTIME) + { + uint32_t mintime = (uint32_t)arg; + + /* The minimum time should be strictly less than the total delay + * which, in turn, will be less than or equal to WWDG_CR_T_MAX + */ + + ret = -EINVAL; + if (mintime < priv->timeout) + { + uint32_t window = (priv->timeout - mintime) * priv->fwwdg / 1000 - 1; + DEBUGASSERT(window < priv->reload); + stm32_setwindow(priv, window | WWDG_CR_T_RESET); + ret = OK; + } + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_wwdginitialize + * + * Description: + * Initialize the WWDG watchdog time. The watchdog timer is intialized and + * registers as 'devpath. The initial state of the watchdog time is + * disabled. + * + * Input Parameters: + * devpath - The full path to the watchdog. This should be of the form + * /dev/watchdog0 + * + * Returned Values: + * None + * + ****************************************************************************/ + +void stm32_wwdginitialize(FAR const char *devpath) +{ + FAR struct stm32_lowerhalf_s *priv = &g_wdgdev; + + wdvdbg("Entry: devpath=%s\n", devpath); + + /* NOTE we assume that clocking to the IWDG has already been provided by + * the RCC initialization logic. + */ + + /* Initialize the driver state structure. Here we assume: (1) the state + * structure lies in .bss and was zeroed at reset time. (2) This function + * is only called once so it is never necessary to re-zero the structure. + */ + + priv->ops = &g_wdgops; + + /* Attach our EWI interrupt handler (But don't enable it yet) */ + + (void)irq_attach(STM32_IRQ_WWDG, stm32_interrupt); + + /* Select an arbitrary initial timeout value. But don't start the watchdog + * yet. NOTE: If the "Hardware watchdog" feature is enabled through the + * device option bits, the watchdog is automatically enabled at power-on. + */ + + stm32_settimeout((FAR struct watchdog_lowerhalf_s *)priv, + CONFIG_STM32_WWDG_DEFTIMOUT); + + /* Register the watchdog driver as /dev/watchdog0 */ + + (void)watchdog_register(devpath, (FAR struct watchdog_lowerhalf_s *)priv); + + /* When the microcontroller enters debug mode (Cortex™-M4F core halted), + * the WWDG counter either continues to work normally or stops, depending + * on DBG_WWDG_STOP configuration bit in DBG module. + */ + +#if defined(CONFIG_STM32_JTAG_FULL_ENABLE) || \ + defined(CONFIG_STM32_JTAG_NOJNTRST_ENABLE) || \ + defined(CONFIG_STM32_JTAG_SW_ENABLE) + { + uint32_t cr = getreg32(STM32_DBGMCU_CR); + cr |= DBGMCU_CR_WWDGSTOP; + putreg32(cr, STM32_DBGMCU_CR); + } +#endif +} + +#endif /* CONFIG_WATCHDOG && CONFIG_STM32_WWDG */ diff --git a/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c b/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c new file mode 100644 index 0000000000..89b279beaa --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c @@ -0,0 +1,615 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32f10xxx_dma.c + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" +#include "up_internal.h" +#include "os_internal.h" +#include "chip.h" +#include "stm32_dma.h" +#include "stm32_internal.h" + +/* Only for the STM32F10xx family for now */ + +#ifdef CONFIG_STM32_STM32F10XX + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define DMA1_NCHANNELS 7 +#if STM32_NDMA > 1 +# define DMA2_NCHANNELS 5 +# define DMA_NCHANNELS (DMA1_NCHANNELS+DMA2_NCHANNELS) +#else +# define DMA_NCHANNELS DMA1_NCHANNELS +#endif + +#ifndef CONFIG_DMA_PRI +# define CONFIG_DMA_PRI NVIC_SYSH_PRIORITY_DEFAULT +#endif + +/* Convert the DMA channel base address to the DMA register block address */ + +#define DMA_BASE(ch) (ch & 0xfffffc00) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure descibes one DMA channel */ + +struct stm32_dma_s +{ + uint8_t chan; /* DMA channel number (0-6) */ + uint8_t irq; /* DMA channel IRQ number */ + sem_t sem; /* Used to wait for DMA channel to become available */ + uint32_t base; /* DMA register channel base address */ + dma_callback_t callback; /* Callback invoked when the DMA completes */ + void *arg; /* Argument passed to callback function */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This array describes the state of each DMA */ + +static struct stm32_dma_s g_dma[DMA_NCHANNELS] = +{ + { + .chan = 0, + .irq = STM32_IRQ_DMA1CH1, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(0), + }, + { + .chan = 1, + .irq = STM32_IRQ_DMA1CH2, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(1), + }, + { + .chan = 2, + .irq = STM32_IRQ_DMA1CH3, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(2), + }, + { + .chan = 3, + .irq = STM32_IRQ_DMA1CH4, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(3), + }, + { + .chan = 4, + .irq = STM32_IRQ_DMA1CH5, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(4), + }, + { + .chan = 5, + .irq = STM32_IRQ_DMA1CH6, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(5), + }, + { + .chan = 6, + .irq = STM32_IRQ_DMA1CH7, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(6), + }, +#if STM32_NDMA > 1 + { + .chan = 0, + .irq = STM32_IRQ_DMA2CH1, + .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(0), + }, + { + .chan = 1, + .irq = STM32_IRQ_DMA2CH2, + .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(1), + }, + { + .chan = 2, + .irq = STM32_IRQ_DMA2CH3, + .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(2), + }, + { + .chan = 3, +#ifdef CONFIG_STM32_CONNECTIVITYLINE + .irq = STM32_IRQ_DMA2CH4, +#else + .irq = STM32_IRQ_DMA2CH45, +#endif + .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(3), + }, + { + .chan = 4, +#ifdef CONFIG_STM32_CONNECTIVITYLINE + .irq = STM32_IRQ_DMA2CH5, +#else + .irq = STM32_IRQ_DMA2CH45, +#endif + .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(4), + }, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * DMA register access functions + ****************************************************************************/ + +/* Get non-channel register from DMA1 or DMA2 */ + +static inline uint32_t dmabase_getreg(struct stm32_dma_s *dmach, uint32_t offset) +{ + return getreg32(DMA_BASE(dmach->base) + offset); +} + +/* Write to non-channel register in DMA1 or DMA2 */ + +static inline void dmabase_putreg(struct stm32_dma_s *dmach, uint32_t offset, uint32_t value) +{ + putreg32(value, DMA_BASE(dmach->base) + offset); +} + +/* Get channel register from DMA1 or DMA2 */ + +static inline uint32_t dmachan_getreg(struct stm32_dma_s *dmach, uint32_t offset) +{ + return getreg32(dmach->base + offset); +} + +/* Write to channel register in DMA1 or DMA2 */ + +static inline void dmachan_putreg(struct stm32_dma_s *dmach, uint32_t offset, uint32_t value) +{ + putreg32(value, dmach->base + offset); +} + +/************************************************************************************ + * Name: stm32_dmatake() and stm32_dmagive() + * + * Description: + * Used to get exclusive access to a DMA channel. + * + ************************************************************************************/ + +static void stm32_dmatake(FAR struct stm32_dma_s *dmach) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&dmach->sem) != 0) + { + /* The only case that an error should occur here is if the wait was awakened + * by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +static inline void stm32_dmagive(FAR struct stm32_dma_s *dmach) +{ + (void)sem_post(&dmach->sem); +} + +/************************************************************************************ + * Name: stm32_dmachandisable + * + * Description: + * Disable the DMA channel + * + ************************************************************************************/ + +static void stm32_dmachandisable(struct stm32_dma_s *dmach) +{ + uint32_t regval; + + /* Disable all interrupts at the DMA controller */ + + regval = dmachan_getreg(dmach, STM32_DMACHAN_CCR_OFFSET); + regval &= ~DMA_CCR_ALLINTS; + + /* Disable the DMA channel */ + + regval &= ~DMA_CCR_EN; + dmachan_putreg(dmach, STM32_DMACHAN_CCR_OFFSET, regval); + + /* Clear pending channel interrupts */ + + dmabase_putreg(dmach, STM32_DMA_IFCR_OFFSET, DMA_ISR_CHAN_MASK(dmach->chan)); +} + +/************************************************************************************ + * Name: stm32_dmainterrupt + * + * Description: + * DMA interrupt handler + * + ************************************************************************************/ + +static int stm32_dmainterrupt(int irq, void *context) +{ + struct stm32_dma_s *dmach; + uint32_t isr; + int chndx = 0; + + /* Get the channel structure from the interrupt number */ + + if (irq >= STM32_IRQ_DMA1CH1 && irq <= STM32_IRQ_DMA1CH7) + { + chndx = irq - STM32_IRQ_DMA1CH1; + } + else +#if STM32_NDMA > 1 +#ifdef CONFIG_STM32_CONNECTIVITYLINE + if (irq >= STM32_IRQ_DMA2CH1 && irq <= STM32_IRQ_DMA2CH5) +#else + if (irq >= STM32_IRQ_DMA2CH1 && irq <= STM32_IRQ_DMA2CH45) +#endif + { + chndx = irq - STM32_IRQ_DMA2CH1 + DMA1_NCHANNELS; + } + else +#endif + { + PANIC(OSERR_INTERNAL); + } + dmach = &g_dma[chndx]; + + /* Get the interrupt status (for this channel only) -- not currently used */ + + isr = dmabase_getreg(dmach, STM32_DMA_ISR_OFFSET) & DMA_ISR_CHAN_MASK(dmach->chan); + + /* Disable the DMA channel */ + + stm32_dmachandisable(dmach); + + /* Invoke the callback */ + + if (dmach->callback) + { + dmach->callback(dmach, isr >> DMA_ISR_CHAN_SHIFT(dmach->chan), dmach->arg); + } + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_dmainitialize + * + * Description: + * Initialize the DMA subsystem + * + * Returned Value: + * None + * + ****************************************************************************/ + +void weak_function up_dmainitialize(void) +{ + struct stm32_dma_s *dmach; + int chndx; + + /* Initialize each DMA channel */ + + for (chndx = 0; chndx < DMA_NCHANNELS; chndx++) + { + dmach = &g_dma[chndx]; + sem_init(&dmach->sem, 0, 1); + + /* Attach DMA interrupt vectors */ + + (void)irq_attach(dmach->irq, stm32_dmainterrupt); + + /* Disable the DMA channel */ + + stm32_dmachandisable(dmach); + + /* Enable the IRQ at the NVIC (still disabled at the DMA controller) */ + + up_enable_irq(dmach->irq); + + /* Set the interrrupt priority */ + + up_prioritize_irq(dmach->irq, CONFIG_DMA_PRI); + } +} + +/**************************************************************************** + * Name: stm32_dmachannel + * + * Description: + * Allocate a DMA channel. This function gives the caller mutually + * exclusive access to the DMA channel specified by the 'chndx' argument. + * DMA channels are shared on the STM32: Devices sharing the same DMA + * channel cannot do DMA concurrently! See the DMACHAN_* definitions in + * stm32_dma.h. + * + * If the DMA channel is not available, then stm32_dmachannel() will wait + * until the holder of the channel relinquishes the channel by calling + * stm32_dmafree(). WARNING: If you have two devices sharing a DMA + * channel and the code never releases the channel, the stm32_dmachannel + * call for the other will hang forever in this function! Don't let your + * design do that! + * + * Hmm.. I suppose this interface could be extended to make a non-blocking + * version. Feel free to do that if that is what you need. + * + * Input parameter: + * chndx - Identifies the stream/channel resource. For the STM32 F1, this + * is simply the channel number as provided by the DMACHAN_* definitions + * in chip/stm32f10xxx_dma.h. + * + * Returned Value: + * Provided that 'chndx' is valid, this function ALWAYS returns a non-NULL, + * void* DMA channel handle. (If 'chndx' is invalid, the function will + * assert if debug is enabled or do something ignorant otherwise). + * + * Assumptions: + * - The caller does not hold he DMA channel. + * - The caller can wait for the DMA channel to be freed if it is no + * available. + * + ****************************************************************************/ + +DMA_HANDLE stm32_dmachannel(unsigned int chndx) +{ + struct stm32_dma_s *dmach = &g_dma[chndx]; + + DEBUGASSERT(chndx < DMA_NCHANNELS); + + /* Get exclusive access to the DMA channel -- OR wait until the channel + * is available if it is currently being used by another driver + */ + + stm32_dmatake(dmach); + + /* The caller now has exclusive use of the DMA channel */ + + return (DMA_HANDLE)dmach; +} + +/**************************************************************************** + * Name: stm32_dmafree + * + * Description: + * Release a DMA channel. If another thread is waiting for this DMA channel + * in a call to stm32_dmachannel, then this function will re-assign the + * DMA channel to that thread and wake it up. NOTE: The 'handle' used + * in this argument must NEVER be used again until stm32_dmachannel() is + * called again to re-gain access to the channel. + * + * Returned Value: + * None + * + * Assumptions: + * - The caller holds the DMA channel. + * - There is no DMA in progress + * + ****************************************************************************/ + +void stm32_dmafree(DMA_HANDLE handle) +{ + struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle; + + DEBUGASSERT(handle != NULL); + + /* Release the channel */ + + stm32_dmagive(dmach); +} + +/**************************************************************************** + * Name: stm32_dmasetup + * + * Description: + * Configure DMA before using + * + ****************************************************************************/ + +void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t ntransfers, uint32_t ccr) +{ + struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle; + uint32_t regval; + + /* Set the peripheral register address in the DMA_CPARx register. The data + * will be moved from/to this address to/from the memory after the + * peripheral event. + */ + + dmachan_putreg(dmach, STM32_DMACHAN_CPAR_OFFSET, paddr); + + /* Set the memory address in the DMA_CMARx register. The data will be + * written to or read from this memory after the peripheral event. + */ + + dmachan_putreg(dmach, STM32_DMACHAN_CMAR_OFFSET, maddr); + + /* Configure the total number of data to be transferred in the DMA_CNDTRx + * register. After each peripheral event, this value will be decremented. + */ + + dmachan_putreg(dmach, STM32_DMACHAN_CNDTR_OFFSET, ntransfers); + + /* Configure the channel priority using the PL[1:0] bits in the DMA_CCRx + * register. Configure data transfer direction, circular mode, peripheral & memory + * incremented mode, peripheral & memory data size, and interrupt after + * half and/or full transfer in the DMA_CCRx register. + */ + + regval = dmachan_getreg(dmach, STM32_DMACHAN_CCR_OFFSET); + regval &= ~(DMA_CCR_MEM2MEM|DMA_CCR_PL_MASK|DMA_CCR_MSIZE_MASK|DMA_CCR_PSIZE_MASK| + DMA_CCR_MINC|DMA_CCR_PINC|DMA_CCR_CIRC|DMA_CCR_DIR); + ccr &= (DMA_CCR_MEM2MEM|DMA_CCR_PL_MASK|DMA_CCR_MSIZE_MASK|DMA_CCR_PSIZE_MASK| + DMA_CCR_MINC|DMA_CCR_PINC|DMA_CCR_CIRC|DMA_CCR_DIR); + regval |= ccr; + dmachan_putreg(dmach, STM32_DMACHAN_CCR_OFFSET, regval); +} + +/**************************************************************************** + * Name: stm32_dmastart + * + * Description: + * Start the DMA transfer + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * - No DMA in progress + * + ****************************************************************************/ + +void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool half) +{ + struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle; + uint32_t ccr; + + DEBUGASSERT(handle != NULL); + + /* Save the callback info. This will be invoked whent the DMA commpletes */ + + dmach->callback = callback; + dmach->arg = arg; + + /* Activate the channel by setting the ENABLE bit in the DMA_CCRx register. + * As soon as the channel is enabled, it can serve any DMA request from the + * peripheral connected on the channel. + */ + + ccr = dmachan_getreg(dmach, STM32_DMACHAN_CCR_OFFSET); + ccr |= DMA_CCR_EN; + + /* Once half of the bytes are transferred, the half-transfer flag (HTIF) is + * set and an interrupt is generated if the Half-Transfer Interrupt Enable + * bit (HTIE) is set. At the end of the transfer, the Transfer Complete Flag + * (TCIF) is set and an interrupt is generated if the Transfer Complete + * Interrupt Enable bit (TCIE) is set. + */ + + ccr |= (half ? (DMA_CCR_HTIE|DMA_CCR_TEIE) : (DMA_CCR_TCIE|DMA_CCR_TEIE)); + dmachan_putreg(dmach, STM32_DMACHAN_CCR_OFFSET, ccr); +} + +/**************************************************************************** + * Name: stm32_dmastop + * + * Description: + * Cancel the DMA. After stm32_dmastop() is called, the DMA channel is + * reset and stm32_dmasetup() must be called before stm32_dmastart() can be + * called again + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +void stm32_dmastop(DMA_HANDLE handle) +{ + struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle; + stm32_dmachandisable(dmach); +} + +/**************************************************************************** + * Name: stm32_dmasample + * + * Description: + * Sample DMA register contents + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA +void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs) +{ + struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle; + irqstate_t flags; + + flags = irqsave(); + regs->isr = dmabase_getreg(dmach, STM32_DMA_ISR_OFFSET); + regs->ccr = dmachan_getreg(dmach, STM32_DMACHAN_CCR_OFFSET); + regs->cndtr = dmachan_getreg(dmach, STM32_DMACHAN_CNDTR_OFFSET); + regs->cpar = dmachan_getreg(dmach, STM32_DMACHAN_CPAR_OFFSET); + regs->cmar = dmachan_getreg(dmach, STM32_DMACHAN_CMAR_OFFSET); + irqrestore(flags); +} +#endif + +/**************************************************************************** + * Name: stm32_dmadump + * + * Description: + * Dump previously sampled DMA register contents + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA +void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs, + const char *msg) +{ + struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle; + uint32_t dmabase = DMA_BASE(dmach->base); + + dmadbg("DMA Registers: %s\n", msg); + dmadbg(" ISRC[%08x]: %08x\n", dmabase + STM32_DMA_ISR_OFFSET, regs->isr); + dmadbg(" CCR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CCR_OFFSET, regs->ccr); + dmadbg(" CNDTR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CNDTR_OFFSET, regs->cndtr); + dmadbg(" CPAR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CPAR_OFFSET, regs->cpar); + dmadbg(" CMAR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CMAR_OFFSET, regs->cmar); +} +#endif + +#endif /* CONFIG_STM32_STM32F10XX */ diff --git a/nuttx/arch/arm/src/stm32/stm32f10xxx_rcc.c b/nuttx/arch/arm/src/stm32/stm32f10xxx_rcc.c new file mode 100644 index 0000000000..516b026fb0 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32f10xxx_rcc.c @@ -0,0 +1,556 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32f10xxx_rcc.c + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Allow up to 100 milliseconds for the high speed clock to become ready. + * that is a very long delay, but if the clock does not become ready we are + * hosed anyway. Normally this is very fast, but I have seen at least one + * board that required this long, long timeout for the HSE to be ready. + */ + +#define HSERDY_TIMEOUT (100 * CONFIG_BOARD_LOOPSPERMSEC) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rcc_reset + * + * Description: + * Put all RCC registers in reset state + * + ****************************************************************************/ + +static inline void rcc_reset(void) +{ + uint32_t regval; + + putreg32(0, STM32_RCC_APB2RSTR); /* Disable APB2 Peripheral Reset */ + putreg32(0, STM32_RCC_APB1RSTR); /* Disable APB1 Peripheral Reset */ + putreg32(RCC_AHBENR_FLITFEN|RCC_AHBENR_SRAMEN, STM32_RCC_AHBENR); /* FLITF and SRAM Clock ON */ + putreg32(0, STM32_RCC_APB2ENR); /* Disable APB2 Peripheral Clock */ + putreg32(0, STM32_RCC_APB1ENR); /* Disable APB1 Peripheral Clock */ + + regval = getreg32(STM32_RCC_CR); /* Set the HSION bit */ + regval |= RCC_CR_HSION; + putreg32(regval, STM32_RCC_CR); + + regval = getreg32(STM32_RCC_CFGR); /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ + regval &= ~(RCC_CFGR_SW_MASK|RCC_CFGR_HPRE_MASK|RCC_CFGR_PPRE1_MASK|RCC_CFGR_PPRE2_MASK|RCC_CFGR_ADCPRE_MASK|RCC_CFGR_MCO_MASK); + putreg32(regval, STM32_RCC_CFGR); + + regval = getreg32(STM32_RCC_CR); /* Reset HSEON, CSSON and PLLON bits */ + regval &= ~(RCC_CR_HSEON|RCC_CR_CSSON|RCC_CR_PLLON); + putreg32(regval, STM32_RCC_CR); + + regval = getreg32(STM32_RCC_CR); /* Reset HSEBYP bit */ + regval &= ~RCC_CR_HSEBYP; + putreg32(regval, STM32_RCC_CR); + + regval = getreg32(STM32_RCC_CFGR); /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE bits */ + regval &= ~(RCC_CFGR_PLLSRC|RCC_CFGR_PLLXTPRE|RCC_CFGR_PLLMUL_MASK|RCC_CFGR_USBPRE); + putreg32(regval, STM32_RCC_CFGR); + + putreg32(0, STM32_RCC_CIR); /* Disable all interrupts */ +} + +/**************************************************************************** + * Name: rcc_enableahb + * + * Description: + * Enable selected AHB peripherals + * + ****************************************************************************/ + +static inline void rcc_enableahb(void) +{ + uint32_t regval; + + /* Always enable FLITF clock and SRAM clock */ + + regval = RCC_AHBENR_FLITFEN|RCC_AHBENR_SRAMEN; + +#ifdef CONFIG_STM32_DMA1 + /* DMA 1 clock enable */ + + regval |= RCC_AHBENR_DMA1EN; +#endif + +#ifdef CONFIG_STM32_DMA2 + /* DMA 2 clock enable */ + + regval |= RCC_AHBENR_DMA2EN; +#endif + +#ifdef CONFIG_STM32_CRC + /* CRC clock enable */ + + regval |= RCC_AHBENR_CRCEN; +#endif + +#ifdef CONFIG_STM32_FSMC + /* FSMC clock enable */ + + regval |= RCC_AHBENR_FSMCEN; +#endif + +#ifdef CONFIG_STM32_SDIO + /* SDIO clock enable */ + + regval |= RCC_AHBENR_SDIOEN; +#endif + + putreg32(regval, STM32_RCC_AHBENR); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: rcc_enableapb1 + * + * Description: + * Enable selected APB1 peripherals + * + ****************************************************************************/ + +static inline void rcc_enableapb1(void) +{ + uint32_t regval; + +#ifdef CONFIG_STM32_USB + /* USB clock divider. This bit must be valid before enabling the USB + * clock in the RCC_APB1ENR register. This bit can’t be reset if the USB + * clock is enabled. + */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~RCC_CFGR_USBPRE; + regval |= STM32_CFGR_USBPRE; + putreg32(regval, STM32_RCC_CFGR); +#endif + + /* Set the appropriate bits in the APB1ENR register to enabled the + * selected APB1 peripherals. + */ + + regval = getreg32(STM32_RCC_APB1ENR); +#ifdef CONFIG_STM32_TIM2 + /* Timer 2 clock enable */ +#ifdef CONFIG_STM32_FORCEPOWER + regval |= RCC_APB1ENR_TIM2EN; +#endif +#endif + +#ifdef CONFIG_STM32_TIM3 + /* Timer 3 clock enable */ +#ifdef CONFIG_STM32_FORCEPOWER + regval |= RCC_APB1ENR_TIM3EN; +#endif +#endif + +#ifdef CONFIG_STM32_TIM4 + /* Timer 4 clock enable */ +#ifdef CONFIG_STM32_FORCEPOWER + regval |= RCC_APB1ENR_TIM4EN; +#endif +#endif + +#ifdef CONFIG_STM32_TIM5 + /* Timer 5 clock enable */ +#ifdef CONFIG_STM32_FORCEPOWER + regval |= RCC_APB1ENR_TIM5EN; +#endif +#endif + +#ifdef CONFIG_STM32_TIM6 + /* Timer 6 clock enable */ +#ifdef CONFIG_STM32_FORCEPOWER + regval |= RCC_APB1ENR_TIM6EN; +#endif +#endif + +#ifdef CONFIG_STM32_TIM7 + /* Timer 7 clock enable */ +#ifdef CONFIG_STM32_FORCEPOWER + regval |= RCC_APB1ENR_TIM7EN; +#endif +#endif + +#ifdef CONFIG_STM32_WWDG + /* Window Watchdog clock enable */ + + regval |= RCC_APB1ENR_WWDGEN; +#endif + +#ifdef CONFIG_STM32_SPI2 + /* SPI 2 clock enable */ + + regval |= RCC_APB1ENR_SPI2EN; +#endif + +#ifdef CONFIG_STM32_SPI3 + /* SPI 3 clock enable */ + + regval |= RCC_APB1ENR_SPI3EN; +#endif + +#ifdef CONFIG_STM32_USART2 + /* USART 2 clock enable */ + + regval |= RCC_APB1ENR_USART2EN; +#endif + +#ifdef CONFIG_STM32_USART3 + /* USART 3 clock enable */ + + regval |= RCC_APB1ENR_USART3EN; +#endif + +#ifdef CONFIG_STM32_UART4 + /* UART 4 clock enable */ + + regval |= RCC_APB1ENR_UART4EN; +#endif + +#ifdef CONFIG_STM32_UART5 + /* UART 5 clock enable */ + + regval |= RCC_APB1ENR_UART5EN; +#endif + +#ifdef CONFIG_STM32_I2C1 + /* I2C 1 clock enable */ +#ifdef CONFIG_STM32_FORCEPOWER + regval |= RCC_APB1ENR_I2C1EN; +#endif +#endif + +#ifdef CONFIG_STM32_I2C2 + /* I2C 2 clock enable */ +#ifdef CONFIG_STM32_FORCEPOWER + regval |= RCC_APB1ENR_I2C2EN; +#endif +#endif + +#ifdef CONFIG_STM32_USB + /* USB clock enable */ + + regval |= RCC_APB1ENR_USBEN; +#endif + +#ifdef CONFIG_STM32_CAN1 + /* CAN1 clock enable */ + + regval |= RCC_APB1ENR_CAN1EN; +#endif + +#ifdef CONFIG_STM32_CAN2 + /* CAN2 clock enable. NOTE: CAN2 needs CAN1 clock as well. */ + + regval |= (RCC_APB1ENR_CAN1EN | RCC_APB1ENR_CAN2EN); +#endif + +#ifdef CONFIG_STM32_BKP + /* Backup interface clock enable */ + + regval |= RCC_APB1ENR_BKPEN; +#endif + +#ifdef CONFIG_STM32_PWR + /* Power interface clock enable */ + + regval |= RCC_APB1ENR_PWREN; +#endif + +#if defined(CONFIG_STM32_DAC1) || defined(CONFIG_STM32_DAC2) + /* DAC interface clock enable */ + + regval |= RCC_APB1ENR_DACEN; +#endif + putreg32(regval, STM32_RCC_APB1ENR); +} + +/**************************************************************************** + * Name: rcc_enableapb2 + * + * Description: + * Enable selected APB2 peripherals + * + ****************************************************************************/ + +static inline void rcc_enableapb2(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the APB2ENR register to enabled the + * selected APB2 peripherals. + */ + + /* Enable GPIOA, GPIOB, ... and AFIO clocks */ + + regval = getreg32(STM32_RCC_APB2ENR); + regval |= (RCC_APB2ENR_AFIOEN +#if STM32_NGPIO > 0 + |RCC_APB2ENR_IOPAEN +#endif +#if STM32_NGPIO > 16 + |RCC_APB2ENR_IOPBEN +#endif +#if STM32_NGPIO > 32 + |RCC_APB2ENR_IOPCEN +#endif +#if STM32_NGPIO > 48 + |RCC_APB2ENR_IOPDEN +#endif +#if STM32_NGPIO > 64 + |RCC_APB2ENR_IOPEEN +#endif +#if STM32_NGPIO > 80 + |RCC_APB2ENR_IOPFEN +#endif +#if STM32_NGPIO > 96 + |RCC_APB2ENR_IOPGEN +#endif + ); + +#ifdef CONFIG_STM32_ADC1 + /* ADC 1 interface clock enable */ + + regval |= RCC_APB2ENR_ADC1EN; +#endif + +#ifdef CONFIG_STM32_ADC2 + /* ADC 2 interface clock enable */ + + regval |= RCC_APB2ENR_ADC2EN; +#endif + +#ifdef CONFIG_STM32_TIM1 + /* TIM1 Timer clock enable */ +#ifdef CONFIG_STM32_FORCEPOWER + regval |= RCC_APB2ENR_TIM1EN; +#endif +#endif + +#ifdef CONFIG_STM32_SPI1 + /* SPI 1 clock enable */ + + regval |= RCC_APB2ENR_SPI1EN; +#endif + +#ifdef CONFIG_STM32_TIM8 + /* TIM8 Timer clock enable */ +#ifdef CONFIG_STM32_FORCEPOWER + regval |= RCC_APB2ENR_TIM8EN; +#endif +#endif + +#ifdef CONFIG_STM32_USART1 + /* USART1 clock enable */ + + regval |= RCC_APB2ENR_USART1EN; +#endif + +#ifdef CONFIG_STM32_ADC3 + /*ADC3 interface clock enable */ + + regval |= RCC_APB2ENR_ADC3EN; +#endif + putreg32(regval, STM32_RCC_APB2ENR); +} + +/**************************************************************************** + * Name: stm32_stdclockconfig + * + * Description: + * Called to change to new clock based on settings in board.h + * + * NOTE: This logic would need to be extended if you need to select low- + * power clocking modes! + ****************************************************************************/ + +#ifndef CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG +static void stm32_stdclockconfig(void) +{ + uint32_t regval; + + /* If the PLL is using the HSE, or the HSE is the system clock */ + +#if (STM32_CFGR_PLLSRC == RCC_CFGR_PLLSRC) || (STM32_SYSCLK_SW == RCC_CFGR_SW_HSE) + + { + volatile int32_t timeout; + + /* Enable External High-Speed Clock (HSE) */ + + regval = getreg32(STM32_RCC_CR); + regval &= ~RCC_CR_HSEBYP; /* Disable HSE clock bypass */ + regval |= RCC_CR_HSEON; /* Enable HSE */ + putreg32(regval, STM32_RCC_CR); + + /* Wait until the HSE is ready (or until a timeout elapsed) */ + + for (timeout = HSERDY_TIMEOUT; timeout > 0; timeout--) + { + /* Check if the HSERDY flag is the set in the CR */ + + if ((getreg32(STM32_RCC_CR) & RCC_CR_HSERDY) != 0) + { + /* If so, then break-out with timeout > 0 */ + + break; + } + } + + if (timeout == 0) + { + /* In the case of a timeout starting the HSE, we really don't have a + * strategy. This is almost always a hardware failure or misconfiguration. + */ + + return; + } + } + + /* If this is a value-line part and we are using the HSE as the PLL */ + +# if defined(CONFIG_STM32_VALUELINE) && (STM32_CFGR_PLLSRC == RCC_CFGR_PLLSRC) + +# if (STM32_CFGR_PLLXTPRE >> 17) != (STM32_CFGR2_PREDIV1 & 1) +# error STM32_CFGR_PLLXTPRE must match the LSB of STM32_CFGR2_PREDIV1 +# endif + + /* Set the HSE prescaler */ + + regval = STM32_CFGR2_PREDIV1; + putreg32(regval, STM32_RCC_CFGR2); + +# endif +#endif + + /* Value-line devices don't implement flash prefetch/waitstates */ + +#ifndef CONFIG_STM32_VALUELINE + + /* Enable FLASH prefetch buffer and 2 wait states */ + + regval = getreg32(STM32_FLASH_ACR); + regval &= ~FLASH_ACR_LATENCY_MASK; + regval |= (FLASH_ACR_LATENCY_2|FLASH_ACR_PRTFBE); + putreg32(regval, STM32_FLASH_ACR); + +#endif + + /* Set the HCLK source/divider */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~RCC_CFGR_HPRE_MASK; + regval |= STM32_RCC_CFGR_HPRE; + putreg32(regval, STM32_RCC_CFGR); + + /* Set the PCLK2 divider */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~RCC_CFGR_PPRE2_MASK; + regval |= STM32_RCC_CFGR_PPRE2; + putreg32(regval, STM32_RCC_CFGR); + + /* Set the PCLK1 divider */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~RCC_CFGR_PPRE1_MASK; + regval |= STM32_RCC_CFGR_PPRE1; + putreg32(regval, STM32_RCC_CFGR); + + /* If we are using the PLL, configure and start it */ + +#if STM32_SYSCLK_SW == RCC_CFGR_SW_PLL + + /* Set the PLL divider and multipler */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~(RCC_CFGR_PLLSRC|RCC_CFGR_PLLXTPRE|RCC_CFGR_PLLMUL_MASK); + regval |= (STM32_CFGR_PLLSRC|STM32_CFGR_PLLXTPRE|STM32_CFGR_PLLMUL); + putreg32(regval, STM32_RCC_CFGR); + + /* Enable the PLL */ + + regval = getreg32(STM32_RCC_CR); + regval |= RCC_CR_PLLON; + putreg32(regval, STM32_RCC_CR); + + /* Wait until the PLL is ready */ + + while ((getreg32(STM32_RCC_CR) & RCC_CR_PLLRDY) == 0); + +#endif + + /* Select the system clock source (probably the PLL) */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~RCC_CFGR_SW_MASK; + regval |= STM32_SYSCLK_SW; + putreg32(regval, STM32_RCC_CFGR); + + /* Wait until the selected source is used as the system clock source */ + + while ((getreg32(STM32_RCC_CFGR) & RCC_CFGR_SWS_MASK) != STM32_SYSCLK_SWS); +} +#endif + +/**************************************************************************** + * Name: rcc_enableperiphals + ****************************************************************************/ + +static inline void rcc_enableperipherals(void) +{ + rcc_enableahb(); + rcc_enableapb2(); + rcc_enableapb1(); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c b/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c new file mode 100644 index 0000000000..df8ad9dd5a --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c @@ -0,0 +1,685 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32f10xxx_rtc.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * With extensions, modifications by: + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregroy Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/* The STM32 RTC Driver offers standard precision of 1 Hz or High Resolution + * operating at rate up to 16384 Hz. It provides UTC time and alarm interface + * with external output pin (for wake-up). + * + * RTC is based on hardware RTC module which is located in a separate power + * domain. The 32-bit counter is extended by 16-bit registers in BKP domain + * STM32_BKP_DR1 to provide system equiv. function to the: time_t time(time_t *). + * + * Notation: + * - clock refers to 32-bit hardware counter + * - time is a combination of clock and upper bits stored in backuped domain + * with unit of 1 [s] + * + * TODO: Error Handling in case LSE fails during start-up or during operation. + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "up_arch.h" + +#include "stm32_pwr.h" +#include "stm32_rcc.h" +#include "stm32_rtc.h" +#include "stm32_waste.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* In hi-res mode, the RTC operates at 16384Hz. Overflow interrupts are handled + * when the 32-bit RTC counter overflows every 3 days and 43 minutes. A BKP register + * is incremented on each overflow interrupt creating, effectively, a 48-bit RTC + * counter. + * + * In the lo-res mode, the RTC operates at 1Hz. Overflow interrupts are not handled + * (because the next overflow is not expected until the year 2106. + * + * WARNING: Overflow interrupts are lost whenever the STM32 is powered down. The + * overflow interrupt may be lost even if the STM32 is powered down only momentarily. + * Therefor hi-res solution is only useful in systems where the power is always on. + */ + +#ifdef CONFIG_RTC_HIRES +# ifndef CONFIG_RTC_FREQUENCY +# error "CONFIG_RTC_FREQUENCY is required for CONFIG_RTC_HIRES" +# elif CONFIG_RTC_FREQUENCY != 16384 +# error "Only hi-res CONFIG_RTC_FREQUENCY of 16384Hz is supported" +# endif +#else +# ifndef CONFIG_RTC_FREQUENCY +# define CONFIG_RTC_FREQUENCY 1 +# endif +# if CONFIG_RTC_FREQUENCY != 1 +# error "Only lo-res CONFIG_RTC_FREQUENCY of 1Hz is supported" +# endif +#endif + +#ifndef CONFIG_STM32_BKP +# error "CONFIG_STM32_BKP is required for CONFIG_RTC" +#endif + +/* RTC/BKP Definitions *************************************************************/ +/* STM32_RTC_PRESCALAR_VALUE + * RTC pre-scalar value. The RTC is driven by a 32,768Hz input clock. This input + * value is divided by this value (plus one) to generate the RTC frequency. + * RTC_TIMEMSB_REG + * The BKP module register used to hold the RTC overflow value. Overflows are + * only handled in hi-res mode. + * RTC_CLOCKS_SHIFT + * The shift used to convert the hi-res timer LSB to one second. Not used with + * the lo-res timer. + */ + +#ifdef CONFIG_RTC_HIRES +# define STM32_RTC_PRESCALAR_VALUE STM32_RTC_PRESCALER_MIN +# define RTC_TIMEMSB_REG STM32_BKP_DR1 +# define RTC_CLOCKS_SHIFT 14 +#else +# define STM32_RTC_PRESCALAR_VALUE STM32_RTC_PRESCALER_SECOND +#endif + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +struct rtc_regvals_s +{ + uint16_t cntl; + uint16_t cnth; +#ifdef CONFIG_RTC_HIRES + uint16_t ovf; +#endif +}; + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +/* Callback to use when the alarm expires */ + +#ifdef CONFIG_RTC_ALARM +static alarmcb_t g_alarmcb; +#endif + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/* Variable determines the state of the LSE oscilator. + * Possible errors: + * - on start-up + * - during operation, reported by LSE interrupt + */ + +volatile bool g_rtc_enabled = false; + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_rtc_beginwr + * + * Description: + * Enter configuration mode + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +static inline void stm32_rtc_beginwr(void) +{ + /* Previous write is done? */ + + while ((getreg16(STM32_RTC_CRL) & RTC_CRL_RTOFF) == 0) + { + up_waste(); + } + + /* Enter Config mode, Set Value and Exit */ + + modifyreg16(STM32_RTC_CRL, 0, RTC_CRL_CNF); +} + +/************************************************************************************ + * Name: stm32_rtc_endwr + * + * Description: + * Exit configuration mode + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +static inline void stm32_rtc_endwr(void) +{ + modifyreg16(STM32_RTC_CRL, RTC_CRL_CNF, 0); +} + +/************************************************************************************ + * Name: stm32_rtc_wait4rsf + * + * Description: + * Wait for registers to synchronise with RTC module, call after power-up only + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +static inline void stm32_rtc_wait4rsf(void) +{ + modifyreg16(STM32_RTC_CRL, RTC_CRL_RSF, 0); + while ((getreg16(STM32_RTC_CRL) & RTC_CRL_RSF) == 0) + { + up_waste(); + } +} + +/************************************************************************************ + * Name: up_rtc_breakout + * + * Description: + * Set the RTC to the provided time. + * + * Input Parameters: + * tp - the time to use + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifdef CONFIG_RTC_HIRES +static void up_rtc_breakout(FAR const struct timespec *tp, + FAR struct rtc_regvals_s *regvals) +{ + uint64_t frac; + uint32_t cnt; + uint16_t ovf; + + /* Break up the time in seconds + milleconds into the correct values for our use */ + + frac = ((uint64_t)tp->tv_nsec * CONFIG_RTC_FREQUENCY) / 1000000000; + cnt = (tp->tv_sec << RTC_CLOCKS_SHIFT) | ((uint32_t)frac & (CONFIG_RTC_FREQUENCY-1)); + ovf = (tp->tv_sec >> (32 - RTC_CLOCKS_SHIFT)); + + /* Then return the broken out time */ + + regvals->cnth = cnt >> 16; + regvals->cntl = cnt & 0xffff; + regvals->ovf = ovf; +} +#else +static inline void up_rtc_breakout(FAR const struct timespec *tp, + FAR struct rtc_regvals_s *regvals) +{ + /* The low-res timer is easy... tv_sec holds exactly the value needed by the + * CNTH/CNTL registers. + */ + + regvals->cnth = (uint16_t)((uint32_t)tp->tv_sec >> 16); + regvals->cntl = (uint16_t)((uint32_t)tp->tv_sec & 0xffff); +} +#endif + +/************************************************************************************ + * Name: stm32_rtc_interrupt + * + * Description: + * RTC interrupt service routine + * + * Input Parameters: + * irq - The IRQ number that generated the interrupt + * context - Architecture specific register save information. + * + * Returned Value: + * Zero (OK) on success; A negated errno value on failure. + * + ************************************************************************************/ + +#if defined(CONFIG_RTC_HIRES) || defined(CONFIG_RTC_ALARM) +static int stm32_rtc_interrupt(int irq, void *context) +{ + uint16_t source = getreg16(STM32_RTC_CRL); + +#ifdef CONFIG_RTC_HIRES + if ((source & RTC_CRL_OWF) != 0) + { + putreg16(getreg16(RTC_TIMEMSB_REG) + 1, RTC_TIMEMSB_REG); + } +#endif + +#ifdef CONFIG_RTC_ALARM + if ((source & RTC_CRL_ALRF) != 0 && g_alarmcb != NULL) + { + /* Alarm callback */ + + g_alarmcb(); + g_alarmcb = NULL; + } +#endif + + /* Clear pending flags, leave RSF high */ + + putreg16(RTC_CRL_RSF, STM32_RTC_CRL); + return 0; +} +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_rtcinitialize + * + * Description: + * Initialize the hardware RTC per the selected configuration. This function is + * called once during the OS initialization sequence + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +int up_rtcinitialize(void) +{ + /* Set access to the peripheral, enable the backup domain (BKP) and the lower power + * extern 32,768Hz (Low-Speed External, LSE) oscillator. Configure the LSE to + * drive the RTC. + */ + + stm32_pwr_enablebkp(); + stm32_rcc_enablelse(); + + /* TODO: Get state from this function, if everything is + * okay and whether it is already enabled (if it was disabled + * reset upper time register) + */ + + g_rtc_enabled = true; + + /* TODO: Possible stall? should we set the timeout period? and return with -1 */ + + stm32_rtc_wait4rsf(); + + /* Configure prescaler, note that these are write-only registers */ + + stm32_rtc_beginwr(); + putreg16(STM32_RTC_PRESCALAR_VALUE >> 16, STM32_RTC_PRLH); + putreg16(STM32_RTC_PRESCALAR_VALUE & 0xffff, STM32_RTC_PRLL); + stm32_rtc_endwr(); + + /* Configure RTC interrupt to catch overflow and alarm interrupts. */ + +#if defined(CONFIG_RTC_HIRES) || defined(CONFIG_RTC_ALARM) + irq_attach(STM32_IRQ_RTC, stm32_rtc_interrupt); + up_enable_irq(STM32_IRQ_RTC); +#endif + + /* Previous write is done? This is required prior writing into CRH */ + + while ((getreg16(STM32_RTC_CRL) & RTC_CRL_RTOFF) == 0) + { + up_waste(); + } + modifyreg16(STM32_RTC_CRH, 0, RTC_CRH_OWIE); + + /* Alarm Int via EXTI Line */ + + /* STM32_IRQ_RTCALRM 41: RTC alarm through EXTI line interrupt */ + + return OK; +} + +/************************************************************************************ + * Name: up_rtc_time + * + * Description: + * Get the current time in seconds. This is similar to the standard time() + * function. This interface is only required if the low-resolution RTC/counter + * hardware implementation selected. It is only used by the RTOS during + * intialization to set up the system time when CONFIG_RTC is set but neither + * CONFIG_RTC_HIRES nor CONFIG_RTC_DATETIME are set. + * + * Input Parameters: + * None + * + * Returned Value: + * The current time in seconds + * + ************************************************************************************/ + +#ifndef CONFIG_RTC_HIRES +time_t up_rtc_time(void) +{ + irqstate_t flags; + uint16_t cnth; + uint16_t cntl; + uint16_t tmp; + + /* The RTC counter is read from two 16-bit registers to form one 32-bit + * value. Because these are non-atomic operations, many things can happen + * between the two reads: This thread could get suspended or interrrupted + * or the lower 16-bit counter could rollover between reads. Disabling + * interrupts will prevent suspensions and interruptions: + */ + + flags = irqsave(); + + /* And the following loop will handle any clock rollover events that may + * happen between samples. Most of the time (like 99.9%), the following + * loop will execute only once. In the rare rollover case, it should + * execute no more than 2 times. + */ + + do + { + tmp = getreg16(STM32_RTC_CNTL); + cnth = getreg16(STM32_RTC_CNTH); + cntl = getreg16(STM32_RTC_CNTL); + } + + /* The second sample of CNTL could be less than the first sample of CNTL + * only if rollover occurred. In that case, CNTH may or may not be out + * of sync. The best thing to do is try again until we know that no + * rollover occurred. + */ + + while (cntl < tmp); + irqrestore(flags); + + /* Okay.. the samples should be as close together in time as possible and + * we can be assured that no clock rollover occurred between the samples. + * + * Return the time in seconds. + */ + + return (time_t)cnth << 16 | (time_t)cntl; +} +#endif + +/************************************************************************************ + * Name: up_rtc_gettime + * + * Description: + * Get the current time from the high resolution RTC clock/counter. This interface + * is only supported by the high-resolution RTC/counter hardware implementation. + * It is used to replace the system timer. + * + * Input Parameters: + * tp - The location to return the high resolution time value. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +#ifdef CONFIG_RTC_HIRES +int up_rtc_gettime(FAR struct timespec *tp) +{ + irqstate_t flags; + uint32_t ls; + uint32_t ms; + uint16_t ovf; + uint16_t cnth; + uint16_t cntl; + uint16_t tmp; + + /* The RTC counter is read from two 16-bit registers to form one 32-bit + * value. Because these are non-atomic operations, many things can happen + * between the two reads: This thread could get suspended or interrrupted + * or the lower 16-bit counter could rollover between reads. Disabling + * interrupts will prevent suspensions and interruptions: + */ + + flags = irqsave(); + + /* And the following loop will handle any clock rollover events that may + * happen between samples. Most of the time (like 99.9%), the following + * loop will execute only once. In the rare rollover case, it should + * execute no more than 2 times. + */ + + do + { + tmp = getreg16(STM32_RTC_CNTL); + cnth = getreg16(STM32_RTC_CNTH); + ovf = getreg16(RTC_TIMEMSB_REG); + cntl = getreg16(STM32_RTC_CNTL); + } + + /* The second sample of CNTL could be less than the first sample of CNTL + * only if rollover occurred. In that case, CNTH may or may not be out + * of sync. The best thing to do is try again until we know that no + * rollover occurred. + */ + + while (cntl < tmp); + irqrestore(flags); + + /* Okay.. the samples should be as close together in time as possible and + * we can be assured that no clock rollover occurred between the samples. + * + * Create a 32-bit value from the LS and MS 16-bit RTC counter values and + * from the MS and overflow 16-bit counter values. + */ + + ls = (uint32_t)cnth << 16 | (uint32_t)cntl; + ms = (uint32_t)ovf << 16 | (uint32_t)cnth; + + /* Then we can save the time in seconds and fractional seconds. */ + + tp->tv_sec = (ms << (32-RTC_CLOCKS_SHIFT-16)) | (ls >> (RTC_CLOCKS_SHIFT+16)); + tp->tv_nsec = (ls & (CONFIG_RTC_FREQUENCY-1)) * (1000000000/CONFIG_RTC_FREQUENCY); + return OK; +} +#endif + +/************************************************************************************ + * Name: up_rtc_settime + * + * Description: + * Set the RTC to the provided time. All RTC implementations must be able to + * set their time based on a standard timespec. + * + * Input Parameters: + * tp - the time to use + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +int up_rtc_settime(FAR const struct timespec *tp) +{ + struct rtc_regvals_s regvals; + irqstate_t flags; + + /* Break out the time values */ + + up_rtc_breakout(tp, ®vals); + + /* Then write the broken out values to the RTC counter and BKP overflow register + * (hi-res mode only) + */ + + flags = irqsave(); + stm32_rtc_beginwr(); + putreg16(regvals.cnth, STM32_RTC_CNTH); + putreg16(regvals.cntl, STM32_RTC_CNTL); + stm32_rtc_endwr(); + +#ifdef CONFIG_RTC_HIRES + putreg16(regvals.ovf, RTC_TIMEMSB_REG); +#endif + irqrestore(flags); + return OK; +} + +/************************************************************************************ + * Name: up_rtc_setalarm + * + * Description: + * Set up an alarm. + * + * Input Parameters: + * tp - the time to set the alarm + * callback - the function to call when the alarm expires. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int up_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback) +{ + struct rtc_regvals_s regvals; + irqstate_t flags; + uint16_t cr; + int ret = -EBUSY; + + /* Is there already something waiting on the ALARM? */ + + if (g_alarmcb == NULL) + { + /* No.. Save the callback function pointer */ + + g_alarmcb = callback; + + /* Break out the time values */ + + up_rtc_breakout(tp, ®vals); + + /* Enable RTC alarm */ + + cr = getreg16(STM32_RTC_CRH); + cr |= RTC_CRH_ALRIE; + putreg16(cr, STM32_RTC_CRH); + + /* The set the alarm */ + + flags = irqsave(); + stm32_rtc_beginwr(); + putreg16(regvals.cnth, STM32_RTC_ALRH); + putreg16(regvals.cntl, STM32_RTC_ALRL); + stm32_rtc_endwr(); + irqrestore(flags); + + ret = OK; + } + return ret; +} +#endif + +/************************************************************************************ + * Name: up_rtc_cancelalarm + * + * Description: + * Cancel a pending alarm alarm + * + * Input Parameters: + * none + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int up_rtc_cancelalarm(void) +{ + irqstate_t flags; + int ret = -ENODATA; + + if (g_alarmcb != NULL) + { + /* Cancel the global callback function */ + + g_alarmcb = NULL; + + /* Unset the alarm */ + + flags = irqsave(); + stm32_rtc_beginwr(); + putreg16(0xffff, STM32_RTC_ALRH); + putreg16(0xffff, STM32_RTC_ALRL); + stm32_rtc_endwr(); + irqrestore(flags); + + ret = OK; + } + return ret; +} +#endif diff --git a/nuttx/arch/arm/src/stm32/stm32f20xxx_dma.c b/nuttx/arch/arm/src/stm32/stm32f20xxx_dma.c new file mode 100644 index 0000000000..7e3ece2fa7 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32f20xxx_dma.c @@ -0,0 +1,903 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32f20xxx_dma.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" +#include "up_internal.h" +#include "os_internal.h" +#include "chip.h" +#include "stm32_dma.h" +#include "stm32_internal.h" + +/* This file supports only the STM32 F2 family (although it is identical to + * the corresponding F4 file). + */ + +#if defined(CONFIG_STM32_STM32F20XX) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define DMA1_NSTREAMS 8 +#if STM32_NDMA > 1 +# define DMA2_NSTREAMS 8 +# define DMA_NSTREAMS (DMA1_NSTREAMS+DMA2_NSTREAMS) +#else +# define DMA_NSTREAMS DMA1_NSTREAMS +#endif + +#ifndef CONFIG_DMA_PRI +# define CONFIG_DMA_PRI NVIC_SYSH_PRIORITY_DEFAULT +#endif + +/* Convert the DMA stream base address to the DMA register block address */ + +#define DMA_BASE(ch) (ch & 0xfffffc00) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure descibes one DMA channel */ + +struct stm32_dma_s +{ + uint8_t stream; /* DMA stream number (0-7) */ + uint8_t irq; /* DMA stream IRQ number */ + uint8_t shift; /* ISR/IFCR bit shift value */ + uint8_t channel; /* DMA channel number (0-7) */ + bool nonstop; /* Stream is configured in a non-stopping mode. */ + sem_t sem; /* Used to wait for DMA channel to become available */ + uint32_t base; /* DMA register channel base address */ + dma_callback_t callback; /* Callback invoked when the DMA completes */ + void *arg; /* Argument passed to callback function */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This array describes the state of each DMA */ + +static struct stm32_dma_s g_dma[DMA_NSTREAMS] = +{ + { + .stream = 0, + .irq = STM32_IRQ_DMA1S0, + .shift = DMA_INT_STREAM0_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(0), + }, + { + .stream = 1, + .irq = STM32_IRQ_DMA1S1, + .shift = DMA_INT_STREAM1_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(1), + }, + { + .stream = 2, + .irq = STM32_IRQ_DMA1S2, + .shift = DMA_INT_STREAM2_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(2), + }, + { + .stream = 3, + .irq = STM32_IRQ_DMA1S3, + .shift = DMA_INT_STREAM3_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(4), + }, + { + .stream = 4, + .irq = STM32_IRQ_DMA1S4, + .shift = DMA_INT_STREAM4_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(4), + }, + { + .stream = 5, + .irq = STM32_IRQ_DMA1S5, + .shift = DMA_INT_STREAM5_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(5), + }, + { + .stream = 6, + .irq = STM32_IRQ_DMA1S6, + .shift = DMA_INT_STREAM6_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(6), + }, + { + .stream = 7, + .irq = STM32_IRQ_DMA1S7, + .shift = DMA_INT_STREAM7_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(7), + }, +#if STM32_NDMA > 1 + { + .stream = 0, + .irq = STM32_IRQ_DMA2S0, + .shift = DMA_INT_STREAM0_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(0), + }, + { + .stream = 1, + .irq = STM32_IRQ_DMA2S1, + .shift = DMA_INT_STREAM1_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(1), + }, + { + .stream = 2, + .irq = STM32_IRQ_DMA2S2, + .shift = DMA_INT_STREAM2_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(2), + }, + { + .stream = 3, + .irq = STM32_IRQ_DMA2S3, + .shift = DMA_INT_STREAM3_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(3), + }, + { + .stream = 4, + .irq = STM32_IRQ_DMA2S4, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(4), + }, + { + .stream = 5, + .irq = STM32_IRQ_DMA2S5, + .shift = DMA_INT_STREAM5_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(5), + }, + { + .stream = 6, + .irq = STM32_IRQ_DMA2S6, + .shift = DMA_INT_STREAM6_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(6), + }, + { + .stream = 7, + .irq = STM32_IRQ_DMA2S7, + .shift = DMA_INT_STREAM7_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(7), + }, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * DMA register access functions + ****************************************************************************/ + +/* Get non-channel register from DMA1 or DMA2 */ + +static inline uint32_t dmabase_getreg(struct stm32_dma_s *dmast, uint32_t offset) +{ + return getreg32(DMA_BASE(dmast->base) + offset); +} + +/* Write to non-channel register in DMA1 or DMA2 */ + +static inline void dmabase_putreg(struct stm32_dma_s *dmast, uint32_t offset, uint32_t value) +{ + putreg32(value, DMA_BASE(dmast->base) + offset); +} + +/* Get channel register from DMA1 or DMA2 */ + +static inline uint32_t dmast_getreg(struct stm32_dma_s *dmast, uint32_t offset) +{ + return getreg32(dmast->base + offset); +} + +/* Write to channel register in DMA1 or DMA2 */ + +static inline void dmast_putreg(struct stm32_dma_s *dmast, uint32_t offset, uint32_t value) +{ + putreg32(value, dmast->base + offset); +} + +/************************************************************************************ + * Name: stm32_dmatake() and stm32_dmagive() + * + * Description: + * Used to get exclusive access to a DMA channel. + * + ************************************************************************************/ + +static void stm32_dmatake(FAR struct stm32_dma_s *dmast) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&dmast->sem) != 0) + { + /* The only case that an error should occur here is if the wait was awakened + * by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +static inline void stm32_dmagive(FAR struct stm32_dma_s *dmast) +{ + (void)sem_post(&dmast->sem); +} + +/************************************************************************************ + * Name: stm32_dmastream + * + * Description: + * Get the g_dma table entry associated with a DMA controller and a stream number + * + ************************************************************************************/ + +static inline FAR struct stm32_dma_s *stm32_dmastream(unsigned int stream, + unsigned int controller) +{ + int index; + + DEBUGASSERT(stream < DMA_NSTREAMS && controller < STM32_NDMA); + + /* Convert the controller + stream based on the fact that there are 8 streams + * per controller. + */ + +#if STM32_NDMA > 1 + index = controller << 3 | stream; +#else + index = stream; +#endif + + /* Then return the stream structure associated with the stream index */ + + return &g_dma[index]; +} + +/************************************************************************************ + * Name: stm32_dmamap + * + * Description: + * Get the g_dma table entry associated with a bit-encoded DMA selection + * + ************************************************************************************/ + +static inline FAR struct stm32_dma_s *stm32_dmamap(unsigned long dmamap) +{ + /* Extract the DMA controller number from the bit encoded value */ + + unsigned int controller = STM32_DMA_CONTROLLER(dmamap); + + /* Extact the stream number from the bit encoded value */ + + unsigned int stream = STM32_DMA_STREAM(dmamap); + + /* Return the table entry associated with the controller + stream */ + + return stm32_dmastream(stream, controller); +} + +/************************************************************************************ + * Name: stm32_dmastreamdisable + * + * Description: + * Disable the DMA stream + * + ************************************************************************************/ + +static void stm32_dmastreamdisable(struct stm32_dma_s *dmast) +{ + uint32_t regoffset; + uint32_t regval; + + /* Disable all interrupts at the DMA controller */ + + regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET); + regval &= ~DMA_SCR_ALLINTS; + + /* Disable the DMA stream */ + + regval &= ~DMA_SCR_EN; + dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval); + + /* Clear pending stream interrupts by setting bits in the upper or lower IFCR + * register + */ + + if (dmast->stream < 4) + { + regoffset = STM32_DMA_LIFCR_OFFSET; + } + else + { + regoffset = STM32_DMA_HIFCR_OFFSET; + } + + dmabase_putreg(dmast, regoffset, (DMA_STREAM_MASK << dmast->shift)); +} + +/************************************************************************************ + * Name: stm32_dmainterrupt + * + * Description: + * DMA interrupt handler + * + ************************************************************************************/ + +static int stm32_dmainterrupt(int irq, void *context) +{ + struct stm32_dma_s *dmast; + uint32_t status; + uint32_t regoffset = 0; + unsigned int stream = 0; + unsigned int controller = 0; + + /* Get the stream and the controller that generated the interrupt */ + + if (irq >= STM32_IRQ_DMA1S0 && irq <= STM32_IRQ_DMA1S6) + { + stream = irq - STM32_IRQ_DMA1S0; + controller = DMA1; + } + else if (irq == STM32_IRQ_DMA1S7) + { + stream = 7; + controller = DMA1; + } + else +#if STM32_NDMA > 1 + if (irq >= STM32_IRQ_DMA2S0 && irq <= STM32_IRQ_DMA2S4) + { + stream = irq - STM32_IRQ_DMA2S0; + controller = DMA2; + } + else if (irq >= STM32_IRQ_DMA2S5 && irq <= STM32_IRQ_DMA2S7) + { + stream = irq - STM32_IRQ_DMA2S5 + 5; + controller = DMA2; + } + else +#endif + { + PANIC(OSERR_INTERNAL); + } + + /* Get the stream structure from the stream and controller numbers */ + + dmast = stm32_dmastream(stream, controller); + + /* Select the interrupt status register (either the LISR or HISR) + * based on the stream number that caused the interrupt. + */ + + if (stream < 4) + { + regoffset = STM32_DMA_LISR_OFFSET; + } + else + { + regoffset = STM32_DMA_HISR_OFFSET; + } + + /* Get the interrupt status for this stream */ + + status = (dmabase_getreg(dmast, regoffset) >> dmast->shift) & DMA_STREAM_MASK; + + /* Clear fetched stream interrupts by setting bits in the upper or lower IFCR + * register + */ + + if (stream < 4) + { + regoffset = STM32_DMA_LIFCR_OFFSET; + } + else + { + regoffset = STM32_DMA_HIFCR_OFFSET; + } + + dmabase_putreg(dmast, regoffset, (status << dmast->shift)); + + /* Invoke the callback */ + + if (dmast->callback) + { + dmast->callback(dmast, status, dmast->arg); + } + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_dmainitialize + * + * Description: + * Initialize the DMA subsystem + * + * Returned Value: + * None + * + ****************************************************************************/ + +void weak_function up_dmainitialize(void) +{ + struct stm32_dma_s *dmast; + int stream; + + /* Initialize each DMA stream */ + + for (stream = 0; stream < DMA_NSTREAMS; stream++) + { + dmast = &g_dma[stream]; + sem_init(&dmast->sem, 0, 1); + + /* Attach DMA interrupt vectors */ + + (void)irq_attach(dmast->irq, stm32_dmainterrupt); + + /* Disable the DMA stream */ + + stm32_dmastreamdisable(dmast); + + /* Enable the IRQ at the NVIC (still disabled at the DMA controller) */ + + up_enable_irq(dmast->irq); + + /* Set the interrrupt priority */ + + up_prioritize_irq(dmast->irq, CONFIG_DMA_PRI); + } +} + +/**************************************************************************** + * Name: stm32_dmachannel + * + * Description: + * Allocate a DMA channel. This function gives the caller mutually + * exclusive access to the DMA channel specified by the 'dmamap' argument. + * DMA channels are shared on the STM32: Devices sharing the same DMA + * channel cannot do DMA concurrently! See the DMACHAN_* definitions in + * stm32_dma.h. + * + * If the DMA channel is not available, then stm32_dmachannel() will wait + * until the holder of the channel relinquishes the channel by calling + * stm32_dmafree(). WARNING: If you have two devices sharing a DMA + * channel and the code never releases the channel, the stm32_dmachannel + * call for the other will hang forever in this function! Don't let your + * design do that! + * + * Hmm.. I suppose this interface could be extended to make a non-blocking + * version. Feel free to do that if that is what you need. + * + * Input parameter: + * dmamap - Identifies the stream/channel resource. For the STM32 F2, this + * is a bit-encoded value as provided by the the DMAMAP_* definitions + * in chip/stm32f20xxx_dma.h + * + * Returned Value: + * Provided that 'dmamap' is valid, this function ALWAYS returns a non-NULL, + * void* DMA channel handle. (If 'dmamap' is invalid, the function will + * assert if debug is enabled or do something ignorant otherwise). + * + * Assumptions: + * - The caller does not hold he DMA channel. + * - The caller can wait for the DMA channel to be freed if it is no + * available. + * + ****************************************************************************/ + +DMA_HANDLE stm32_dmachannel(unsigned int dmamap) +{ + FAR struct stm32_dma_s *dmast; + + /* Get the stream index from the bit-encoded channel value */ + + dmast = stm32_dmamap(dmamap); + DEBUGASSERT(dmast != NULL); + + /* Get exclusive access to the DMA channel -- OR wait until the channel + * is available if it is currently being used by another driver + */ + + stm32_dmatake(dmast); + + /* The caller now has exclusive use of the DMA channel. Assign the + * channel to the stream and return an opaque reference to the stream + * structure. + */ + + dmast->channel = STM32_DMA_CHANNEL(dmamap); + return (DMA_HANDLE)dmast; +} + +/**************************************************************************** + * Name: stm32_dmafree + * + * Description: + * Release a DMA channel. If another thread is waiting for this DMA channel + * in a call to stm32_dmachannel, then this function will re-assign the + * DMA channel to that thread and wake it up. NOTE: The 'handle' used + * in this argument must NEVER be used again until stm32_dmachannel() is + * called again to re-gain access to the channel. + * + * Returned Value: + * None + * + * Assumptions: + * - The caller holds the DMA channel. + * - There is no DMA in progress + * + ****************************************************************************/ + +void stm32_dmafree(DMA_HANDLE handle) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + + DEBUGASSERT(handle != NULL); + + /* Release the channel */ + + stm32_dmagive(dmast); +} + +/**************************************************************************** + * Name: stm32_dmasetup + * + * Description: + * Configure DMA before using + * + ****************************************************************************/ + +void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, + size_t ntransfers, uint32_t scr) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + uint32_t regoffset; + uint32_t regval; + + dmadbg("paddr: %08x maddr: %08x ntransfers: %d scr: %08x\n", + paddr, maddr, ntransfers, scr); + + /* "If the stream is enabled, disable it by resetting the EN bit in the + * DMA_SxCR register, then read this bit in order to confirm that there is no + * ongoing stream operation. Writing this bit to 0 is not immediately + * effective since it is actually written to 0 once all the current transfers + * have finished. When the EN bit is read as 0, this means that the stream is + * ready to be configured. It is therefore necessary to wait for the EN bit + * to be cleared before starting any stream configuration. ..." + */ + + while ((dmast_getreg(dmast, STM32_DMA_SCR_OFFSET) & DMA_SCR_EN) != 0); + + /* "... All the stream dedicated bits set in the status register (DMA_LISR + * and DMA_HISR) from the previous data block DMA transfer should be cleared + * before the stream can be re-enabled." + * + * Clear pending stream interrupts by setting bits in the upper or lower IFCR + * register + */ + + if (dmast->stream < 4) + { + regoffset = STM32_DMA_LIFCR_OFFSET; + } + else + { + regoffset = STM32_DMA_HIFCR_OFFSET; + } + + dmabase_putreg(dmast, regoffset, (DMA_STREAM_MASK << dmast->shift)); + + /* "Set the peripheral register address in the DMA_SPARx register. The data + * will be moved from/to this address to/from the memory after the + * peripheral event. + */ + + dmast_putreg(dmast, STM32_DMA_SPAR_OFFSET, paddr); + + /* "Set the memory address in the DMA_SM0ARx ... register. The data will be + * written to or read from this memory after the peripheral event." + * + * Note that in double-buffered mode it is explicitly assumed that the second + * buffer immediately follows the first. + */ + + dmast_putreg(dmast, STM32_DMA_SM0AR_OFFSET, maddr); + if (scr & DMA_SCR_DBM) + { + dmast_putreg(dmast, STM32_DMA_SM1AR_OFFSET, maddr + ntransfers); + } + + /* "Configure the total number of data items to be transferred in the + * DMA_SNDTRx register. After each peripheral event, this value will be + * decremented." + * + * "When the peripheral flow controller is used for a given stream, the value + * written into the DMA_SxNDTR has no effect on the DMA transfer. Actually, + * whatever the value written, it will be forced by hardware to 0xFFFF as soon + * as the stream is enabled..." + */ + + dmast_putreg(dmast, STM32_DMA_SNDTR_OFFSET, ntransfers); + + /* "Select the DMA channel (request) using CHSEL[2:0] in the DMA_SxCR register." + * + * "Configure the stream priority using the PL[1:0] bits in the DMA_SCRx" + * register." + */ + + regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET); + regval &= ~(DMA_SCR_PL_MASK|DMA_SCR_CHSEL_MASK); + regval |= scr & DMA_SCR_PL_MASK; + regval |= (uint32_t)dmast->channel << DMA_SCR_CHSEL_SHIFT; + dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval); + + /* "Configure the FIFO usage (enable or disable, threshold in transmission and + * reception)" + * + * "Caution is required when choosing the FIFO threshold (bits FTH[1:0] of the + * DMA_SxFCR register) and the size of the memory burst (MBURST[1:0] of the + * DMA_SxCR register): The content pointed by the FIFO threshold must exactly + * match to an integer number of memory burst transfers. If this is not in the + * case, a FIFO error (flag FEIFx of the DMA_HISR or DMA_LISR register) will be + * generated when the stream is enabled, then the stream will be automatically + * disabled." + * + * The FIFO is disabled in circular mode when transferring data from a + * peripheral to memory, as in this case it is usually desirable to know that + * every byte from the peripheral is transferred immediately to memory. It is + * not practical to flush the DMA FIFO, as this requires disabling the channel + * which triggers the transfer-complete interrupt. + * + * NOTE: The FEIFx error interrupt is not enabled because the FEIFx seems to + * be reported spuriously causing good transfers to be marked as failures. + */ + + regval = dmast_getreg(dmast, STM32_DMA_SFCR_OFFSET); + regval &= ~(DMA_SFCR_FTH_MASK | DMA_SFCR_FS_MASK | DMA_SFCR_FEIE); + if (!((scr & (DMA_SCR_CIRC | DMA_SCR_DIR_MASK)) == (DMA_SCR_CIRC | DMA_SCR_DIR_P2M))) + { + regval |= (DMA_SFCR_FTH_FULL | DMA_SFCR_DMDIS); + } + dmast_putreg(dmast, STM32_DMA_SFCR_OFFSET, regval); + + /* "Configure data transfer direction, circular mode, peripheral & memory + * incremented mode, peripheral & memory data size, and interrupt after + * half and/or full transfer in the DMA_CCRx register." + * + * Note: The CT bit is always reset. + */ + + regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET); + regval &= ~(DMA_SCR_PFCTRL|DMA_SCR_DIR_MASK|DMA_SCR_PINC|DMA_SCR_MINC| + DMA_SCR_PSIZE_MASK|DMA_SCR_MSIZE_MASK|DMA_SCR_PINCOS| + DMA_SCR_CIRC|DMA_SCR_DBM|DMA_SCR_CT| + DMA_SCR_PBURST_MASK|DMA_SCR_MBURST_MASK); + scr &= (DMA_SCR_PFCTRL|DMA_SCR_DIR_MASK|DMA_SCR_PINC|DMA_SCR_MINC| + DMA_SCR_PSIZE_MASK|DMA_SCR_MSIZE_MASK|DMA_SCR_PINCOS| + DMA_SCR_DBM|DMA_SCR_CIRC| + DMA_SCR_PBURST_MASK|DMA_SCR_MBURST_MASK); + regval |= scr; + dmast->nonstop = (scr & (DMA_SCR_DBM|DMA_SCR_CIRC)) != 0; + dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval); +} + +/**************************************************************************** + * Name: stm32_dmastart + * + * Description: + * Start the DMA transfer + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * - No DMA in progress + * + ****************************************************************************/ + +void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool half) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + uint32_t scr; + + DEBUGASSERT(handle != NULL); + + /* Save the callback info. This will be invoked whent the DMA commpletes */ + + dmast->callback = callback; + dmast->arg = arg; + + /* Activate the stream by setting the ENABLE bit in the DMA_SCRx register. + * As soon as the stream is enabled, it can serve any DMA request from the + * peripheral connected on the stream. + */ + + scr = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET); + scr |= DMA_SCR_EN; + + if (!dmast->nonstop) + { + /* Once half of the bytes are transferred, the half-transfer flag (HTIF) is + * set and an interrupt is generated if the Half-Transfer Interrupt Enable + * bit (HTIE) is set. At the end of the transfer, the Transfer Complete Flag + * (TCIF) is set and an interrupt is generated if the Transfer Complete + * Interrupt Enable bit (TCIE) is set. + */ + + scr |= (half ? (DMA_SCR_HTIE|DMA_SCR_TEIE) : (DMA_SCR_TCIE|DMA_SCR_TEIE)); + } + else + { + /* In nonstop mode, when the transfer completes it immediately resets + * and starts again. The transfer-complete interrupt is thus always + * enabled, and the half-complete interrupt can be used in circular + * mode to determine when the buffer is half-full, or in double-buffered + * mode to determine when one of the two buffers is full. + */ + scr |= (half ? DMA_SCR_HTIE : 0) | DMA_SCR_TCIE | DMA_SCR_TEIE; + } + + dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, scr); +} + +/**************************************************************************** + * Name: stm32_dmastop + * + * Description: + * Cancel the DMA. After stm32_dmastop() is called, the DMA channel is + * reset and stm32_dmasetup() must be called before stm32_dmastart() can be + * called again + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +void stm32_dmastop(DMA_HANDLE handle) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + stm32_dmastreamdisable(dmast); +} + +/**************************************************************************** + * Name: stm32_dmaresidual + * + * Description: + * Read the DMA bytes-remaining register. + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +size_t stm32_dmaresidual(DMA_HANDLE handle) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + uint32_t residual; + + /* Fetch the count of bytes remaining to be transferred. + * + * If the FIFO is enabled, this count may be inaccurate. ST don't + * appear to document whether this counts the peripheral or the memory + * side of the channel, and they don't make the memory pointer + * available either. + * + * For reception in circular mode the FIFO is disabled in order that + * this value can be useful. + */ + + residual = dmast_getreg(dmast, STM32_DMA_SNDTR_OFFSET); + + return (size_t)residual; +} + +/**************************************************************************** + * Name: stm32_dmasample + * + * Description: + * Sample DMA register contents + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA +void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + irqstate_t flags; + + flags = irqsave(); + regs->lisr = dmabase_getreg(dmast, STM32_DMA_LISR_OFFSET); + regs->hisr = dmabase_getreg(dmast, STM32_DMA_HISR_OFFSET); + regs->scr = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET); + regs->sndtr = dmast_getreg(dmast, STM32_DMA_SNDTR_OFFSET); + regs->spar = dmast_getreg(dmast, STM32_DMA_SPAR_OFFSET); + regs->sm0ar = dmast_getreg(dmast, STM32_DMA_SM0AR_OFFSET); + regs->sm1ar = dmast_getreg(dmast, STM32_DMA_SM1AR_OFFSET); + regs->sfcr = dmast_getreg(dmast, STM32_DMA_SFCR_OFFSET); + irqrestore(flags); +} +#endif + +/**************************************************************************** + * Name: stm32_dmadump + * + * Description: + * Dump previously sampled DMA register contents + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA +void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs, + const char *msg) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + uint32_t dmabase = DMA_BASE(dmast->base); + + dmadbg("DMA Registers: %s\n", msg); + dmadbg(" LISR[%08x]: %08x\n", dmabase + STM32_DMA_LISR_OFFSET, regs->lisr); + dmadbg(" HISR[%08x]: %08x\n", dmabase + STM32_DMA_HISR_OFFSET, regs->hisr); + dmadbg(" SCR[%08x]: %08x\n", dmast->base + STM32_DMA_SCR_OFFSET, regs->scr); + dmadbg(" SNDTR[%08x]: %08x\n", dmast->base + STM32_DMA_SNDTR_OFFSET, regs->sndtr); + dmadbg(" SPAR[%08x]: %08x\n", dmast->base + STM32_DMA_SPAR_OFFSET, regs->spar); + dmadbg(" SM0AR[%08x]: %08x\n", dmast->base + STM32_DMA_SM0AR_OFFSET, regs->sm0ar); + dmadbg(" SM1AR[%08x]: %08x\n", dmast->base + STM32_DMA_SM1AR_OFFSET, regs->sm1ar); + dmadbg(" SFCR[%08x]: %08x\n", dmast->base + STM32_DMA_SFCR_OFFSET, regs->sfcr); +} +#endif + +#endif /* CONFIG_STM32_STM32F20XX */ diff --git a/nuttx/arch/arm/src/stm32/stm32f20xxx_rcc.c b/nuttx/arch/arm/src/stm32/stm32f20xxx_rcc.c new file mode 100644 index 0000000000..8cfd405ded --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32f20xxx_rcc.c @@ -0,0 +1,666 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32f20xxx_rcc.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "stm32_pwr.h" + +/* This file supports only the STM32 F2 family (although it is identical to + * the corresponding F4 file). + */ + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Allow up to 100 milliseconds for the high speed clock to become ready. + * that is a very long delay, but if the clock does not become ready we are + * hosed anyway. Normally this is very fast, but I have seen at least one + * board that required this long, long timeout for the HSE to be ready. + */ + +#define HSERDY_TIMEOUT (100 * CONFIG_BOARD_LOOPSPERMSEC) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rcc_reset + * + * Description: + * Reset the RCC clock configuration to the default reset state + * + ****************************************************************************/ + +static inline void rcc_reset(void) +{ + uint32_t regval; + + /* Enable the Internal High Speed clock (HSI) */ + + regval = getreg32(STM32_RCC_CR); + regval |= RCC_CR_HSION; + putreg32(regval, STM32_RCC_CR); + + /* Reset CFGR register */ + + putreg32(0x00000000, STM32_RCC_CFGR); + + /* Reset HSEON, CSSON and PLLON bits */ + + regval = getreg32(STM32_RCC_CR); + regval &= ~(RCC_CR_HSEON|RCC_CR_CSSON|RCC_CR_PLLON); + putreg32(regval, STM32_RCC_CR); + + /* Reset PLLCFGR register to reset default */ + + putreg32(RCC_PLLCFG_RESET, STM32_RCC_PLLCFG); + + /* Reset HSEBYP bit */ + + regval = getreg32(STM32_RCC_CR); + regval &= ~RCC_CR_HSEBYP; + putreg32(regval, STM32_RCC_CR); + + /* Disable all interrupts */ + + putreg32(0x00000000, STM32_RCC_CIR); +} + +/**************************************************************************** + * Name: rcc_enableahb1 + * + * Description: + * Enable selected AHB1 peripherals + * + ****************************************************************************/ + +static inline void rcc_enableahb1(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the AHB1ENR register to enabled the + * selected AHB1 peripherals. + */ + + regval = getreg32(STM32_RCC_AHB1ENR); + + /* Enable GPIOA, GPIOB, .... GPIOI*/ + +#if STM32_NGPIO > 0 + regval |= (RCC_AHB1ENR_GPIOAEN +#if STM32_NGPIO > 16 + |RCC_AHB1ENR_GPIOBEN +#endif +#if STM32_NGPIO > 32 + |RCC_AHB1ENR_GPIOCEN +#endif +#if STM32_NGPIO > 48 + |RCC_AHB1ENR_GPIODEN +#endif +#if STM32_NGPIO > 64 + |RCC_AHB1ENR_GPIOEEN +#endif +#if STM32_NGPIO > 80 + |RCC_AHB1ENR_GPIOFEN +#endif +#if STM32_NGPIO > 96 + |RCC_AHB1ENR_GPIOGEN +#endif +#if STM32_NGPIO > 112 + |RCC_AHB1ENR_GPIOHEN +#endif +#if STM32_NGPIO > 128 + |RCC_AHB1ENR_GPIOIEN +#endif + ); +#endif + +#ifdef CONFIG_STM32_CRC + /* CRC clock enable */ + + regval |= RCC_AHB1ENR_CRCEN; +#endif + +#ifdef CONFIG_STM32_BKPSRAM + /* Backup SRAM clock enable */ + + regval |= RCC_AHB1ENR_BKPSRAMEN; +#endif + +#ifdef CONFIG_STM32_DMA1 + /* DMA 1 clock enable */ + + regval |= RCC_AHB1ENR_DMA1EN; +#endif + +#ifdef CONFIG_STM32_DMA2 + /* DMA 2 clock enable */ + + regval |= RCC_AHB1ENR_DMA2EN; +#endif + +#ifdef CONFIG_STM32_ETHMAC + /* Ethernet MAC clocking */ + + regval |= (RCC_AHB1ENR_ETHMACEN|RCC_AHB1ENR_ETHMACTXEN|RCC_AHB1ENR_ETHMACRXEN); + +#ifdef CONFIG_STM32_ETH_PTP + /* Precision Time Protocol (PTP) */ + + regval |= RCC_AHB1ENR_ETHMACPTPEN; + +#endif +#endif + +#ifdef CONFIG_STM32_OTGHS + /* USB OTG HS */ + + regval |= (RCC_AHB1ENR_OTGHSEN|RCC_AHB1ENR_OTGHSULPIEN); +#endif + + putreg32(regval, STM32_RCC_AHB1ENR); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: rcc_enableahb2 + * + * Description: + * Enable selected AHB2 peripherals + * + ****************************************************************************/ + +static inline void rcc_enableahb2(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the AHB2ENR register to enabled the + * selected AHB2 peripherals. + */ + + regval = getreg32(STM32_RCC_AHB2ENR); + +#ifdef CONFIG_STM32_DCMI + /* Camera interface enable */ + + regval |= RCC_AHB2ENR_DCMIEN; +#endif + +#ifdef CONFIG_STM32_CRYP + /* Cryptographic modules clock enable */ + + regval |= RCC_AHB2ENR_CRYPEN; +#endif + +#ifdef CONFIG_STM32_HASH + /* Hash modules clock enable */ + + regval |= RCC_AHB2ENR_HASHEN; +#endif + +#ifdef CONFIG_STM32_RNG + /* Random number generator clock enable */ + + regval |= RCC_AHB2ENR_RNGEN; +#endif + +#ifdef CONFIG_STM32_OTGFS + /* USB OTG FS clock enable */ + + regval |= RCC_AHB2ENR_OTGFSEN; +#endif + + putreg32(regval, STM32_RCC_AHB2ENR); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: rcc_enableahb3 + * + * Description: + * Enable selected AHB3 peripherals + * + ****************************************************************************/ + +static inline void rcc_enableahb3(void) +{ +#ifdef CONFIG_STM32_FSMC + uint32_t regval; + + /* Set the appropriate bits in the AHB3ENR register to enabled the + * selected AHB3 peripherals. + */ + + regval = getreg32(STM32_RCC_AHB3ENR); + + /* Flexible static memory controller module clock enable */ + + regval |= RCC_AHB3ENR_FSMCEN; + + putreg32(regval, STM32_RCC_AHB3ENR); /* Enable peripherals */ +#endif +} + +/**************************************************************************** + * Name: rcc_enableapb1 + * + * Description: + * Enable selected APB1 peripherals + * + ****************************************************************************/ + +static inline void rcc_enableapb1(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the APB1ENR register to enabled the + * selected APB1 peripherals. + */ + + regval = getreg32(STM32_RCC_APB1ENR); + +#ifdef CONFIG_STM32_TIM2 + /* TIM2 clock enable */ + + regval |= RCC_APB1ENR_TIM2EN; +#endif + +#ifdef CONFIG_STM32_TIM3 + /* TIM3 clock enable */ + + regval |= RCC_APB1ENR_TIM3EN; +#endif + +#ifdef CONFIG_STM32_TIM4 + /* TIM4 clock enable */ + + regval |= RCC_APB1ENR_TIM4EN; +#endif + +#ifdef CONFIG_STM32_TIM5 + /* TIM5 clock enable */ + + regval |= RCC_APB1ENR_TIM5EN; +#endif + +#ifdef CONFIG_STM32_TIM6 + /* TIM6 clock enable */ + + regval |= RCC_APB1ENR_TIM6EN; +#endif + +#ifdef CONFIG_STM32_TIM7 + /* TIM7 clock enable */ + + regval |= RCC_APB1ENR_TIM7EN; +#endif + +#ifdef CONFIG_STM32_TIM12 + /* TIM12 clock enable */ + + regval |= RCC_APB1ENR_TIM12EN; +#endif + +#ifdef CONFIG_STM32_TIM13 + /* TIM13 clock enable */ + + regval |= RCC_APB1ENR_TIM13EN; +#endif + +#ifdef CONFIG_STM32_TIM14 + /* TIM14 clock enable */ + + regval |= RCC_APB1ENR_TIM14EN; +#endif + +#ifdef CONFIG_STM32_WWDG + /* Window watchdog clock enable */ + + regval |= RCC_APB1ENR_WWDGEN; +#endif + +#ifdef CONFIG_STM32_SPI2 + /* SPI2 clock enable */ + + regval |= RCC_APB1ENR_SPI2EN; +#endif + +#ifdef CONFIG_STM32_SPI3 + /* SPI3 clock enable */ + + regval |= RCC_APB1ENR_SPI3EN; +#endif + +#ifdef CONFIG_STM32_USART2 + /* USART 2 clock enable */ + + regval |= RCC_APB1ENR_USART2EN; +#endif + +#ifdef CONFIG_STM32_USART3 + /* USART3 clock enable */ + + regval |= RCC_APB1ENR_USART3EN; +#endif + +#ifdef CONFIG_STM32_UART4 + /* UART4 clock enable */ + + regval |= RCC_APB1ENR_UART4EN; +#endif + +#ifdef CONFIG_STM32_UART5 + /* UART5 clock enable */ + + regval |= RCC_APB1ENR_UART5EN; +#endif + +#ifdef CONFIG_STM32_I2C1 + /* I2C1 clock enable */ + + regval |= RCC_APB1ENR_I2C1EN; +#endif + +#ifdef CONFIG_STM32_I2C2 + /* I2C2 clock enable */ + + regval |= RCC_APB1ENR_I2C2EN; +#endif + +#ifdef CONFIG_STM32_I2C3 + /* I2C3 clock enable */ + + regval |= RCC_APB1ENR_I2C3EN; +#endif + +#ifdef CONFIG_STM32_CAN1 + /* CAN 1 clock enable */ + + regval |= RCC_APB1ENR_CAN1EN; +#endif + +#ifdef CONFIG_STM32_CAN2 + /* CAN2 clock enable. NOTE: CAN2 needs CAN1 clock as well. */ + + regval |= (RCC_APB1ENR_CAN1EN | RCC_APB1ENR_CAN2EN); +#endif + + /* Power interface clock enable. The PWR block is always enabled so that + * we can set the internal voltage regulator for maximum performance. + */ + + regval |= RCC_APB1ENR_PWREN; + +#if defined (CONFIG_STM32_DAC1) || defined(CONFIG_STM32_DAC2) + /* DAC interface clock enable */ + + regval |= RCC_APB1ENR_DACEN; +#endif + + putreg32(regval, STM32_RCC_APB1ENR); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: rcc_enableapb2 + * + * Description: + * Enable selected APB2 peripherals + * + ****************************************************************************/ + +static inline void rcc_enableapb2(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the APB2ENR register to enabled the + * selected APB2 peripherals. + */ + + regval = getreg32(STM32_RCC_APB2ENR); + +#ifdef CONFIG_STM32_TIM1 + /* TIM1 clock enable */ + + regval |= RCC_APB2ENR_TIM1EN; +#endif + +#ifdef CONFIG_STM32_TIM8 + /* TIM8 clock enable */ + + regval |= RCC_APB2ENR_TIM8EN; +#endif + +#ifdef CONFIG_STM32_USART1 + /* USART1 clock enable */ + + regval |= RCC_APB2ENR_USART1EN; +#endif + +#ifdef CONFIG_STM32_USART6 + /* USART6 clock enable */ + + regval |= RCC_APB2ENR_USART6EN; +#endif + +#ifdef CONFIG_STM32_ADC1 + /* ADC1 clock enable */ + + regval |= RCC_APB2ENR_ADC1EN; +#endif + +#ifdef CONFIG_STM32_ADC2 + /* ADC2 clock enable */ + + regval |= RCC_APB2ENR_ADC2EN; +#endif + +#ifdef CONFIG_STM32_ADC3 + /* ADC3 clock enable */ + + regval |= RCC_APB2ENR_ADC3EN; +#endif + +#ifdef CONFIG_STM32_SDIO + /* SDIO clock enable */ + + regval |= RCC_APB2ENR_SDIOEN; +#endif + +#ifdef CONFIG_STM32_SPI1 + /* SPI1 clock enable */ + + regval |= RCC_APB2ENR_SPI1EN; +#endif + +#ifdef CONFIG_STM32_SYSCFG + /* System configuration controller clock enable */ + + regval |= RCC_APB2ENR_SYSCFGEN; +#endif + +#ifdef CONFIG_STM32_TIM9 + /* TIM9 clock enable */ + + regval |= RCC_APB2ENR_TIM9EN; +#endif + +#ifdef CONFIG_STM32_TIM10 + /* TIM10 clock enable */ + + regval |= RCC_APB2ENR_TIM10EN; +#endif + +#ifdef CONFIG_STM32_TIM11 + /* TIM11 clock enable */ + + regval |= RCC_APB2ENR_TIM11EN; +#endif + + putreg32(regval, STM32_RCC_APB2ENR); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: stm32_stdclockconfig + * + * Description: + * Called to change to new clock based on settings in board.h + * + * NOTE: This logic would need to be extended if you need to select low- + * power clocking modes! + ****************************************************************************/ + +#ifndef CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG +static void stm32_stdclockconfig(void) +{ + uint32_t regval; + volatile int32_t timeout; + + /* Enable External High-Speed Clock (HSE) */ + + regval = getreg32(STM32_RCC_CR); + regval |= RCC_CR_HSEON; /* Enable HSE */ + putreg32(regval, STM32_RCC_CR); + + /* Wait until the HSE is ready (or until a timeout elapsed) */ + + for (timeout = HSERDY_TIMEOUT; timeout > 0; timeout--) + { + /* Check if the HSERDY flag is the set in the CR */ + + if ((getreg32(STM32_RCC_CR) & RCC_CR_HSERDY) != 0) + { + /* If so, then break-out with timeout > 0 */ + + break; + } + } + + /* Check for a timeout. If this timeout occurs, then we are hosed. We + * have no real back-up plan, although the following logic makes it look + * as though we do. + */ + + if (timeout > 0) + { + /* Select regulator voltage output Scale 1 mode to support system + * frequencies up to 168 MHz. + */ + + regval = getreg32(STM32_RCC_APB1ENR); + regval |= RCC_APB1ENR_PWREN; + putreg32(regval, STM32_RCC_APB1ENR); + + regval = getreg32(STM32_PWR_CR); + regval |= PWR_CR_VOS; + putreg32(regval, STM32_PWR_CR); + + /* Set the HCLK source/divider */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~RCC_CFGR_HPRE_MASK; + regval |= STM32_RCC_CFGR_HPRE; + putreg32(regval, STM32_RCC_CFGR); + + /* Set the PCLK2 divider */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~RCC_CFGR_PPRE2_MASK; + regval |= STM32_RCC_CFGR_PPRE2; + putreg32(regval, STM32_RCC_CFGR); + + /* Set the PCLK1 divider */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~RCC_CFGR_PPRE1_MASK; + regval |= STM32_RCC_CFGR_PPRE1; + putreg32(regval, STM32_RCC_CFGR); + + /* Set the PLL dividers and multiplers to configure the main PLL */ + + regval = (STM32_PLLCFG_PLLM | STM32_PLLCFG_PLLN |STM32_PLLCFG_PLLP | + RCC_PLLCFG_PLLSRC_HSE | STM32_PLLCFG_PPQ); + putreg32(regval, STM32_RCC_PLLCFG); + + /* Enable the main PLL */ + + regval = getreg32(STM32_RCC_CR); + regval |= RCC_CR_PLLON; + putreg32(regval, STM32_RCC_CR); + + /* Wait until the PLL is ready */ + + while ((getreg32(STM32_RCC_CR) & RCC_CR_PLLRDY) == 0); + + /* Enable FLASH prefetch, instruction cache, data cache, and 5 wait states */ + + regval = (FLASH_ACR_LATENCY_5 | FLASH_ACR_ICEN | FLASH_ACR_DCEN); + putreg32(regval, STM32_FLASH_ACR); + + /* Select the main PLL as system clock source */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~RCC_CFGR_SW_MASK; + regval |= RCC_CFGR_SW_PLL; + putreg32(regval, STM32_RCC_CFGR); + + /* Wait until the PLL source is used as the system clock source */ + + while ((getreg32(STM32_RCC_CFGR) & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL); + } +} +#endif + +/**************************************************************************** + * Name: rcc_enableperiphals + ****************************************************************************/ + +static inline void rcc_enableperipherals(void) +{ + rcc_enableahb1(); + rcc_enableahb2(); + rcc_enableahb3(); + rcc_enableapb1(); + rcc_enableapb2(); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/nuttx/arch/arm/src/stm32/stm32f20xxx_rtc.c b/nuttx/arch/arm/src/stm32/stm32f20xxx_rtc.c new file mode 100644 index 0000000000..b98276498c --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32f20xxx_rtc.c @@ -0,0 +1,842 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32f20xxx_rtc.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include "up_arch.h" + +#include "stm32_rtc.h" + +#ifdef CONFIG_RTC + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* This RTC implementation supports only date/time RTC hardware */ + +#ifndef CONFIG_RTC_DATETIME +# error "CONFIG_RTC_DATETIME must be set to use this driver" +#endif + +#ifdef CONFIG_RTC_HIRES +# error "CONFIG_RTC_HIRES must NOT be set with this driver" +#endif + +#ifndef CONFIG_STM32_PWR +# error "CONFIG_STM32_PWR must selected to use this driver" +#endif + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_RTC +#endif + +/* Constants ************************************************************************/ + +#define SYNCHRO_TIMEOUT (0x00020000) +#define INITMODE_TIMEOUT (0x00010000) +#define RTC_MAGIC (0xfacefeed) +#define RTC_PREDIV_S (0xff) +#define RTC_PREDIV_A (0x7f) + +/* Debug ****************************************************************************/ + +#ifdef CONFIG_DEBUG_RTC +# define rtcdbg dbg +# define rtcvdbg vdbg +# define rtclldbg lldbg +# define rtcllvdbg llvdbg +#else +# define rtcdbg(x...) +# define rtcvdbg(x...) +# define rtclldbg(x...) +# define rtcllvdbg(x...) +#endif + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +/* Callback to use when the alarm expires */ + +#ifdef CONFIG_RTC_ALARM +static alarmcb_t g_alarmcb; +#endif + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/* g_rtc_enabled is set true after the RTC has successfully initialized */ + +volatile bool g_rtc_enabled = false; + +/************************************************************************************ + * Private Functions + ************************************************************************************/ +/************************************************************************************ + * Name: rtc_dumpregs + * + * Description: + * Disable RTC write protection + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifdef CONFIG_DEBUG_RTC +static void rtc_dumpregs(FAR const char *msg) +{ + rtclldbg("%s:\n", msg); + rtclldbg(" TR: %08x\n", getreg32(STM32_RTC_TR)); + rtclldbg(" DR: %08x\n", getreg32(STM32_RTC_DR)); + rtclldbg(" CR: %08x\n", getreg32(STM32_RTC_CR)); + rtclldbg(" ISR: %08x\n", getreg32(STM32_RTC_ISR)); + rtclldbg(" PRER: %08x\n", getreg32(STM32_RTC_PRER)); + rtclldbg(" WUTR: %08x\n", getreg32(STM32_RTC_WUTR)); + rtclldbg(" CALIBR: %08x\n", getreg32(STM32_RTC_CALIBR)); + rtclldbg(" ALRMAR: %08x\n", getreg32(STM32_RTC_ALRMAR)); + rtclldbg(" ALRMBR: %08x\n", getreg32(STM32_RTC_ALRMBR)); + rtclldbg(" SHIFTR: %08x\n", getreg32(STM32_RTC_SHIFTR)); + rtclldbg(" TSTR: %08x\n", getreg32(STM32_RTC_TSTR)); + rtclldbg(" TSDR: %08x\n", getreg32(STM32_RTC_TSDR)); + rtclldbg(" TSSSR: %08x\n", getreg32(STM32_RTC_TSSSR)); + rtclldbg(" CALR: %08x\n", getreg32(STM32_RTC_CALR)); + rtclldbg(" TAFCR: %08x\n", getreg32(STM32_RTC_TAFCR)); + rtclldbg("ALRMASSR: %08x\n", getreg32(STM32_RTC_ALRMASSR)); + rtclldbg("ALRMBSSR: %08x\n", getreg32(STM32_RTC_ALRMBSSR)); + rtclldbg(" BK0: %08x\n", getreg32(STM32_RTC_BK0R)); +} +#else +# define rtc_dumpregs(msg) +#endif + +/************************************************************************************ + * Name: rtc_dumptime + * + * Description: + * Disable RTC write protection + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifdef CONFIG_DEBUG_RTC +static void rtc_dumptime(FAR struct tm *tp, FAR const char *msg) +{ + rtclldbg("%s:\n", msg); + rtclldbg(" tm_sec: %08x\n", tp->tm_sec); + rtclldbg(" tm_min: %08x\n", tp->tm_min); + rtclldbg(" tm_hour: %08x\n", tp->tm_hour); + rtclldbg(" tm_mday: %08x\n", tp->tm_mday); + rtclldbg(" tm_mon: %08x\n", tp->tm_mon); + rtclldbg(" tm_year: %08x\n", tp->tm_year); +} +#else +# define rtc_dumptime(tp, msg) +#endif + +/************************************************************************************ + * Name: rtc_wprunlock + * + * Description: + * Disable RTC write protection + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +static void rtc_wprunlock(void) +{ + /* The following steps are required to unlock the write protection on all the + * RTC registers (except for RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR). + * + * 1. Write 0xCA into the RTC_WPR register. + * 2. Write 0x53 into the RTC_WPR register. + * + * Writing a wrong key reactivates the write protection. + */ + + putreg32(0xca, STM32_RTC_WPR); + putreg32(0x53, STM32_RTC_WPR); +} + +/************************************************************************************ + * Name: rtc_wprunlock + * + * Description: + * Enable RTC write protection + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +static inline void rtc_wprlock(void) +{ + /* Writing any wrong key reactivates the write protection. */ + + putreg32(0xff, STM32_RTC_WPR); +} + +/************************************************************************************ + * Name: rtc_synchwait + * + * Description: + * Waits until the RTC Time and Date registers (RTC_TR and RTC_DR) are + * synchronized with RTC APB clock. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static int rtc_synchwait(void) +{ + volatile uint32_t timeout; + uint32_t regval; + int ret; + + /* Disable the write protection for RTC registers */ + + rtc_wprunlock(); + + /* Clear Registers synchronization flag (RSF) */ + + regval = getreg32(STM32_RTC_ISR); + regval &= ~RTC_ISR_RSF; + putreg32(regval, STM32_RTC_ISR); + + /* Now wait the registers to become synchronised */ + + ret = -ETIMEDOUT; + for (timeout = 0; timeout < SYNCHRO_TIMEOUT; timeout++) + { + regval = getreg32(STM32_RTC_ISR); + if ((regval & RTC_ISR_RSF) != 0) + { + /* Synchronized */ + + ret = OK; + break; + } + } + + /* Re-enable the write protection for RTC registers */ + + rtc_wprlock(); + return ret; +} + +/************************************************************************************ + * Name: rtc_enterinit + * + * Description: + * Enter RTC initialization mode. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static int rtc_enterinit(void) +{ + volatile uint32_t timeout; + uint32_t regval; + int ret; + + /* Check if the Initialization mode is already set */ + + regval = getreg32(STM32_RTC_ISR); + + ret = OK; + if ((regval & RTC_ISR_INITF) == 0) + { + /* Set the Initialization mode */ + + putreg32(RTC_ISR_INIT, STM32_RTC_ISR); + + /* Wait until the RTC is in the INIT state (or a timeout occurs) */ + + ret = -ETIMEDOUT; + for (timeout = 0; timeout < INITMODE_TIMEOUT; timeout++) + { + regval = getreg32(STM32_RTC_ISR); + if ((regval & RTC_ISR_INITF) != 0) + { + ret = OK; + break; + } + } + } + + return ret; +} + +/************************************************************************************ + * Name: rtc_exitinit + * + * Description: + * Exit RTC initialization mode. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static void rtc_exitinit(void) +{ + uint32_t regval; + + regval = getreg32(STM32_RTC_ISR); + regval &= ~(RTC_ISR_INIT); + putreg32(regval, STM32_RTC_ISR); +} + +/************************************************************************************ + * Name: rtc_bin2bcd + * + * Description: + * Converts a 2 digit binary to BCD format + * + * Input Parameters: + * value - The byte to be converted. + * + * Returned Value: + * The value in BCD representation + * + ************************************************************************************/ + +static uint32_t rtc_bin2bcd(int value) +{ + uint32_t msbcd = 0; + + while (value >= 10) + { + msbcd++; + value -= 10; + } + + return (msbcd << 4) | value; +} + +/************************************************************************************ + * Name: rtc_bin2bcd + * + * Description: + * Convert from 2 digit BCD to binary. + * + * Input Parameters: + * value - The BCD value to be converted. + * + * Returned Value: + * The value in binary representation + * + ************************************************************************************/ + +static int rtc_bcd2bin(uint32_t value) +{ + uint32_t tens = (value >> 4) * 10; + return (int)(tens + (value & 0x0f)); +} + +/************************************************************************************ + * Name: rtc_setup + * + * Description: + * Performs first time configuration of the RTC. A special value written into + * back-up register 0 will prevent this function from being called on sub-sequent + * resets or power up. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static int rtc_setup(void) +{ + uint32_t regval; + int ret; + + /* Enable the External Low-Speed (LSE) Oscillator setup the LSE as the RTC clock\ + * source, and enable the RTC. + */ + + stm32_rcc_enablelse(); + + /* Wait for the RTC Time and Date registers to be synchronized with RTC APB + * clock. + */ + + ret = rtc_synchwait(); + if (ret == OK) + { + /* Disable the write protection for RTC registers */ + + rtc_wprunlock(); + + /* Set Initialization mode */ + + ret = rtc_enterinit(); + if (ret == OK) + { + /* Set the 24 hour format by clearing the FMT bit in the RTC + * control register + */ + + regval = getreg32(STM32_RTC_CR); + regval &= ~RTC_CR_FMT; + putreg32(regval, STM32_RTC_CR); + + /* Configure RTC pre-scaler to the required, default values for + * use with the 32.768 KHz LSE clock: + */ + + putreg32(((uint32_t)0xff << RTC_PRER_PREDIV_S_SHIFT) | + ((uint32_t)0x7f << RTC_PRER_PREDIV_A_SHIFT), + STM32_RTC_PRER); + + /* Exit RTC initialization mode */ + + rtc_exitinit(); + } + + /* Re-enable the write protection for RTC registers */ + + rtc_wprlock(); + } + return ret; +} + +/************************************************************************************ + * Name: rtc_resume + * + * Description: + * Called when the RTC was already initialized on a previous power cycle. This + * just brings the RTC back into full operation. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static int rtc_resume(void) +{ +#ifdef CONFIG_RTC_ALARM + uint32_t regval; +#endif + int ret; + + /* Wait for the RTC Time and Date registers to be syncrhonized with RTC APB + * clock. + */ + + ret = rtc_synchwait(); + + /* Clear the RTC alarm flags */ + +#ifdef CONFIG_RTC_ALARM + regval = getreg32(STM32_RTC_ISR); + regval &= ~(RTC_ISR_ALRAF|RTC_ISR_ALRBF); + putreg32(regval, STM32_RTC_ISR); + + /* Clear the EXTI Line 17 Pending bit (Connected internally to RTC Alarm) */ + + putreg32((1 << 17), STM32_EXTI_PR); +#endif + return ret; +} + +/************************************************************************************ + * Name: rtc_interrupt + * + * Description: + * RTC interrupt service routine + * + * Input Parameters: + * irq - The IRQ number that generated the interrupt + * context - Architecture specific register save information. + * + * Returned Value: + * Zero (OK) on success; A negated errno value on failure. + * + ************************************************************************************/ + +#if CONFIG_RTC_ALARM +static int rtc_interrupt(int irq, void *context) +{ +#warning "Missing logic" + return OK; +} +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_rtcinitialize + * + * Description: + * Initialize the hardware RTC per the selected configuration. This function is + * called once during the OS initialization sequence + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +int up_rtcinitialize(void) +{ + uint32_t regval; + int ret; + + rtc_dumpregs("On reset"); + + /* Clocking for the PWR block must be provided. However, this is done + * unconditionally in stm32f40xxx_rcc.c on power up. This done unconditionally + * because the PWR block is also needed to set the internal voltage regulator for + * maximum performance. + */ + + /* Enable access to the backup domain (RTC registers, RTC backup data registers + * and backup SRAM). + */ + + stm32_pwr_enablebkp(); + + /* Check if the one-time initialization of the RTC has already been performed. + * We can determine this by checking if the magic number has been writing to + * to back-up date register DR0. + */ + + regval = getreg32(STM32_RTC_BK0R); + if (regval != RTC_MAGIC) + { + /* Perform the one-time setup of the LSE clocking to the RTC */ + + ret = rtc_setup(); + + /* Remember that the RTC is initialized */ + + putreg32(RTC_MAGIC, STM32_RTC_BK0R); + } + else + { + /* RTC already set-up, just resume normal operation */ + + ret = rtc_resume(); + } + + /* Configure RTC interrupt to catch alarm interrupts. All RTC interrupts are + * connected to the EXTI controller. To enable the RTC Alarm interrupt, the + * following sequence is required: + * + * 1. Configure and enable the EXTI Line 17 in interrupt mode and select the + * rising edge sensitivity. + * 2. Configure and enable the RTC_Alarm IRQ channel in the NVIC. + * 3. Configure the RTC to generate RTC alarms (Alarm A or Alarm B). + */ + +#ifdef CONFIG_RTC_ALARM +# warning "Missing EXTI setup logic" + + /* Then attach the ALARM interrupt handler */ + + irq_attach(STM32_IRQ_RTC, rtc_interrupt); + up_enable_irq(STM32_IRQ_RTC); +#endif + + g_rtc_enabled = true; + rtc_dumpregs("After Initialzation"); + return OK; +} + +/************************************************************************************ + * Name: up_rtc_getdatetime + * + * Description: + * Get the current date and time from the date/time RTC. This interface + * is only supported by the date/time RTC hardware implementation. + * It is used to replace the system timer. It is only used by the RTOS during + * intialization to set up the system time when CONFIG_RTC and CONFIG_RTC_DATETIME + * are selected (and CONFIG_RTC_HIRES is not). + * + * NOTE: Some date/time RTC hardware is capability of sub-second accuracy. That + * sub-second accuracy is lost in this interface. However, since the system time + * is reinitialized on each power-up/reset, there will be no timing inaccuracy in + * the long run. + * + * Input Parameters: + * tp - The location to return the high resolution time value. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +int up_rtc_getdatetime(FAR struct tm *tp) +{ + uint32_t dr; + uint32_t tr; + uint32_t tmp; + + /* Sample the data time registers. There is a race condition here... If we sample + * the time just before midnight on December 31, the date could be wrong because + * the day rolled over while were sampling. + */ + + do + { + dr = getreg32(STM32_RTC_DR); + tr = getreg32(STM32_RTC_TR); + tmp = getreg32(STM32_RTC_DR); + } + while (tmp != dr); + + rtc_dumpregs("Reading Time"); + + /* Convert the RTC time to fields in struct tm format. All of the STM32 + * All of the ranges of values correspond between struct tm and the time + * register. + */ + + tmp = (tr & (RTC_TR_SU_MASK|RTC_TR_ST_MASK)) >> RTC_TR_SU_SHIFT; + tp->tm_sec = rtc_bcd2bin(tmp); + + tmp = (tr & (RTC_TR_MNU_MASK|RTC_TR_MNT_MASK)) >> RTC_TR_MNU_SHIFT; + tp->tm_min = rtc_bcd2bin(tmp); + + tmp = (tr & (RTC_TR_HU_MASK|RTC_TR_HT_MASK)) >> RTC_TR_HU_SHIFT; + tp->tm_hour = rtc_bcd2bin(tmp); + + /* Now convert the RTC date to fields in struct tm format: + * Days: 1-31 match in both cases. + * Month: STM32 is 1-12, struct tm is 0-11. + * Years: STM32 is 00-99, struct tm is years since 1900. + * + * Issue: I am not sure what the STM32 years mean. Are these the + * years 2000-2099? I'll assume so. + */ + + tmp = (dr & (RTC_DR_DU_MASK|RTC_DR_DT_MASK)) >> RTC_DR_DU_SHIFT; + tp->tm_mday = rtc_bcd2bin(tmp); + + tmp = (dr & (RTC_DR_MU_MASK|RTC_DR_MT)) >> RTC_DR_MU_SHIFT; + tp->tm_mon = rtc_bcd2bin(tmp) - 1; + + tmp = (dr & (RTC_DR_YU_MASK|RTC_DR_YT_MASK)) >> RTC_DR_YU_SHIFT; + tp->tm_year = rtc_bcd2bin(tmp) + 100; + + rtc_dumptime(tp, "Returning"); + return OK; +} + +/************************************************************************************ + * Name: up_rtc_settime + * + * Description: + * Set the RTC to the provided time. All RTC implementations must be able to + * set their time based on a standard timespec. + * + * Input Parameters: + * tp - the time to use + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +int up_rtc_settime(FAR const struct timespec *tp) +{ + FAR struct tm newtime; + uint32_t tr; + uint32_t dr; + int ret; + + /* Break out the time values (not that the time is set only to units of seconds) */ + + (void)gmtime_r(&tp->tv_sec, &newtime); + rtc_dumptime(&newtime, "Setting time"); + + /* Then write the broken out values to the RTC */ + + /* Convert the struct tm format to RTC time register fields. All of the STM32 + * All of the ranges of values correspond between struct tm and the time + * register. + */ + + tr = (rtc_bin2bcd(newtime.tm_sec) << RTC_TR_SU_SHIFT) | + (rtc_bin2bcd(newtime.tm_min) << RTC_TR_MNU_SHIFT) | + (rtc_bin2bcd(newtime.tm_hour) << RTC_TR_HU_SHIFT); + tr &= ~RTC_TR_RESERVED_BITS; + + /* Now convert the fields in struct tm format to the RTC date register fields: + * Days: 1-31 match in both cases. + * Month: STM32 is 1-12, struct tm is 0-11. + * Years: STM32 is 00-99, struct tm is years since 1900. + * + * Issue: I am not sure what the STM32 years mean. Are these the + * years 2000-2099? I'll assume so. + */ + + dr = (rtc_bin2bcd(newtime.tm_mday) << RTC_DR_DU_SHIFT) | + ((rtc_bin2bcd(newtime.tm_mon + 1)) << RTC_DR_MU_SHIFT) | + ((rtc_bin2bcd(newtime.tm_year - 100)) << RTC_DR_YU_SHIFT); + dr &= ~RTC_DR_RESERVED_BITS; + + /* Disable the write protection for RTC registers */ + + rtc_wprunlock(); + + /* Set Initialization mode */ + + ret = rtc_enterinit(); + if (ret == OK) + { + /* Set the RTC TR and DR registers */ + + putreg32(tr, STM32_RTC_TR); + putreg32(dr, STM32_RTC_DR); + + /* Exit Initialization mode and wait for the RTC Time and Date + * registers to be synchronized with RTC APB clock. + */ + + rtc_exitinit(); + ret = rtc_synchwait(); + } + + /* Re-enable the write protection for RTC registers */ + + rtc_wprlock(); + rtc_dumpregs("New time setting"); + return ret; +} + +/************************************************************************************ + * Name: up_rtc_setalarm + * + * Description: + * Set up an alarm. Up to two alarms can be supported (ALARM A and ALARM B). + * + * Input Parameters: + * tp - the time to set the alarm + * callback - the function to call when the alarm expires. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int up_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback); +{ + irqstate_t flags; + int ret = -EBUSY; + + /* Is there already something waiting on the ALARM? */ + + if (g_alarmcb == NULL) + { + /* No.. Save the callback function pointer */ + + g_alarmcb = callback; + + /* Break out the time values */ +#warning "Missing logic" + + /* The set the alarm */ +#warning "Missing logic" + + ret = OK; + } + return ret; +} +#endif + +#endif /* CONFIG_RTC */ + diff --git a/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c b/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c new file mode 100644 index 0000000000..c3555d7147 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c @@ -0,0 +1,903 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32f40xxx_dma.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" +#include "up_internal.h" +#include "os_internal.h" +#include "chip.h" +#include "stm32_dma.h" +#include "stm32_internal.h" + +/* This file supports only the STM32 F4 family (an probably the F2 family + * as well?) + */ + +#if defined(CONFIG_STM32_STM32F40XX) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define DMA1_NSTREAMS 8 +#if STM32_NDMA > 1 +# define DMA2_NSTREAMS 8 +# define DMA_NSTREAMS (DMA1_NSTREAMS+DMA2_NSTREAMS) +#else +# define DMA_NSTREAMS DMA1_NSTREAMS +#endif + +#ifndef CONFIG_DMA_PRI +# define CONFIG_DMA_PRI NVIC_SYSH_PRIORITY_DEFAULT +#endif + +/* Convert the DMA stream base address to the DMA register block address */ + +#define DMA_BASE(ch) (ch & 0xfffffc00) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure descibes one DMA channel */ + +struct stm32_dma_s +{ + uint8_t stream; /* DMA stream number (0-7) */ + uint8_t irq; /* DMA stream IRQ number */ + uint8_t shift; /* ISR/IFCR bit shift value */ + uint8_t channel; /* DMA channel number (0-7) */ + bool nonstop; /* Stream is configured in a non-stopping mode. */ + sem_t sem; /* Used to wait for DMA channel to become available */ + uint32_t base; /* DMA register channel base address */ + dma_callback_t callback; /* Callback invoked when the DMA completes */ + void *arg; /* Argument passed to callback function */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This array describes the state of each DMA */ + +static struct stm32_dma_s g_dma[DMA_NSTREAMS] = +{ + { + .stream = 0, + .irq = STM32_IRQ_DMA1S0, + .shift = DMA_INT_STREAM0_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(0), + }, + { + .stream = 1, + .irq = STM32_IRQ_DMA1S1, + .shift = DMA_INT_STREAM1_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(1), + }, + { + .stream = 2, + .irq = STM32_IRQ_DMA1S2, + .shift = DMA_INT_STREAM2_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(2), + }, + { + .stream = 3, + .irq = STM32_IRQ_DMA1S3, + .shift = DMA_INT_STREAM3_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(4), + }, + { + .stream = 4, + .irq = STM32_IRQ_DMA1S4, + .shift = DMA_INT_STREAM4_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(4), + }, + { + .stream = 5, + .irq = STM32_IRQ_DMA1S5, + .shift = DMA_INT_STREAM5_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(5), + }, + { + .stream = 6, + .irq = STM32_IRQ_DMA1S6, + .shift = DMA_INT_STREAM6_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(6), + }, + { + .stream = 7, + .irq = STM32_IRQ_DMA1S7, + .shift = DMA_INT_STREAM7_SHIFT, + .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(7), + }, +#if STM32_NDMA > 1 + { + .stream = 0, + .irq = STM32_IRQ_DMA2S0, + .shift = DMA_INT_STREAM0_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(0), + }, + { + .stream = 1, + .irq = STM32_IRQ_DMA2S1, + .shift = DMA_INT_STREAM1_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(1), + }, + { + .stream = 2, + .irq = STM32_IRQ_DMA2S2, + .shift = DMA_INT_STREAM2_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(2), + }, + { + .stream = 3, + .irq = STM32_IRQ_DMA2S3, + .shift = DMA_INT_STREAM3_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(3), + }, + { + .stream = 4, + .irq = STM32_IRQ_DMA2S4, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(4), + }, + { + .stream = 5, + .irq = STM32_IRQ_DMA2S5, + .shift = DMA_INT_STREAM5_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(5), + }, + { + .stream = 6, + .irq = STM32_IRQ_DMA2S6, + .shift = DMA_INT_STREAM6_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(6), + }, + { + .stream = 7, + .irq = STM32_IRQ_DMA2S7, + .shift = DMA_INT_STREAM7_SHIFT, + .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(7), + }, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * DMA register access functions + ****************************************************************************/ + +/* Get non-channel register from DMA1 or DMA2 */ + +static inline uint32_t dmabase_getreg(struct stm32_dma_s *dmast, uint32_t offset) +{ + return getreg32(DMA_BASE(dmast->base) + offset); +} + +/* Write to non-channel register in DMA1 or DMA2 */ + +static inline void dmabase_putreg(struct stm32_dma_s *dmast, uint32_t offset, uint32_t value) +{ + putreg32(value, DMA_BASE(dmast->base) + offset); +} + +/* Get channel register from DMA1 or DMA2 */ + +static inline uint32_t dmast_getreg(struct stm32_dma_s *dmast, uint32_t offset) +{ + return getreg32(dmast->base + offset); +} + +/* Write to channel register in DMA1 or DMA2 */ + +static inline void dmast_putreg(struct stm32_dma_s *dmast, uint32_t offset, uint32_t value) +{ + putreg32(value, dmast->base + offset); +} + +/************************************************************************************ + * Name: stm32_dmatake() and stm32_dmagive() + * + * Description: + * Used to get exclusive access to a DMA channel. + * + ************************************************************************************/ + +static void stm32_dmatake(FAR struct stm32_dma_s *dmast) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&dmast->sem) != 0) + { + /* The only case that an error should occur here is if the wait was awakened + * by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +static inline void stm32_dmagive(FAR struct stm32_dma_s *dmast) +{ + (void)sem_post(&dmast->sem); +} + +/************************************************************************************ + * Name: stm32_dmastream + * + * Description: + * Get the g_dma table entry associated with a DMA controller and a stream number + * + ************************************************************************************/ + +static inline FAR struct stm32_dma_s *stm32_dmastream(unsigned int stream, + unsigned int controller) +{ + int index; + + DEBUGASSERT(stream < DMA_NSTREAMS && controller < STM32_NDMA); + + /* Convert the controller + stream based on the fact that there are 8 streams + * per controller. + */ + +#if STM32_NDMA > 1 + index = controller << 3 | stream; +#else + index = stream; +#endif + + /* Then return the stream structure associated with the stream index */ + + return &g_dma[index]; +} + +/************************************************************************************ + * Name: stm32_dmamap + * + * Description: + * Get the g_dma table entry associated with a bit-encoded DMA selection + * + ************************************************************************************/ + +static inline FAR struct stm32_dma_s *stm32_dmamap(unsigned long dmamap) +{ + /* Extract the DMA controller number from the bit encoded value */ + + unsigned int controller = STM32_DMA_CONTROLLER(dmamap); + + /* Extact the stream number from the bit encoded value */ + + unsigned int stream = STM32_DMA_STREAM(dmamap); + + /* Return the table entry associated with the controller + stream */ + + return stm32_dmastream(stream, controller); +} + +/************************************************************************************ + * Name: stm32_dmastreamdisable + * + * Description: + * Disable the DMA stream + * + ************************************************************************************/ + +static void stm32_dmastreamdisable(struct stm32_dma_s *dmast) +{ + uint32_t regoffset; + uint32_t regval; + + /* Disable all interrupts at the DMA controller */ + + regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET); + regval &= ~DMA_SCR_ALLINTS; + + /* Disable the DMA stream */ + + regval &= ~DMA_SCR_EN; + dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval); + + /* Clear pending stream interrupts by setting bits in the upper or lower IFCR + * register + */ + + if (dmast->stream < 4) + { + regoffset = STM32_DMA_LIFCR_OFFSET; + } + else + { + regoffset = STM32_DMA_HIFCR_OFFSET; + } + + dmabase_putreg(dmast, regoffset, (DMA_STREAM_MASK << dmast->shift)); +} + +/************************************************************************************ + * Name: stm32_dmainterrupt + * + * Description: + * DMA interrupt handler + * + ************************************************************************************/ + +static int stm32_dmainterrupt(int irq, void *context) +{ + struct stm32_dma_s *dmast; + uint32_t status; + uint32_t regoffset = 0; + unsigned int stream = 0; + unsigned int controller = 0; + + /* Get the stream and the controller that generated the interrupt */ + + if (irq >= STM32_IRQ_DMA1S0 && irq <= STM32_IRQ_DMA1S6) + { + stream = irq - STM32_IRQ_DMA1S0; + controller = DMA1; + } + else if (irq == STM32_IRQ_DMA1S7) + { + stream = 7; + controller = DMA1; + } + else +#if STM32_NDMA > 1 + if (irq >= STM32_IRQ_DMA2S0 && irq <= STM32_IRQ_DMA2S4) + { + stream = irq - STM32_IRQ_DMA2S0; + controller = DMA2; + } + else if (irq >= STM32_IRQ_DMA2S5 && irq <= STM32_IRQ_DMA2S7) + { + stream = irq - STM32_IRQ_DMA2S5 + 5; + controller = DMA2; + } + else +#endif + { + PANIC(OSERR_INTERNAL); + } + + /* Get the stream structure from the stream and controller numbers */ + + dmast = stm32_dmastream(stream, controller); + + /* Select the interrupt status register (either the LISR or HISR) + * based on the stream number that caused the interrupt. + */ + + if (stream < 4) + { + regoffset = STM32_DMA_LISR_OFFSET; + } + else + { + regoffset = STM32_DMA_HISR_OFFSET; + } + + /* Get the interrupt status for this stream */ + + status = (dmabase_getreg(dmast, regoffset) >> dmast->shift) & DMA_STREAM_MASK; + + /* Clear fetched stream interrupts by setting bits in the upper or lower IFCR + * register + */ + + if (stream < 4) + { + regoffset = STM32_DMA_LIFCR_OFFSET; + } + else + { + regoffset = STM32_DMA_HIFCR_OFFSET; + } + + dmabase_putreg(dmast, regoffset, (status << dmast->shift)); + + /* Invoke the callback */ + + if (dmast->callback) + { + dmast->callback(dmast, status, dmast->arg); + } + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_dmainitialize + * + * Description: + * Initialize the DMA subsystem + * + * Returned Value: + * None + * + ****************************************************************************/ + +void weak_function up_dmainitialize(void) +{ + struct stm32_dma_s *dmast; + int stream; + + /* Initialize each DMA stream */ + + for (stream = 0; stream < DMA_NSTREAMS; stream++) + { + dmast = &g_dma[stream]; + sem_init(&dmast->sem, 0, 1); + + /* Attach DMA interrupt vectors */ + + (void)irq_attach(dmast->irq, stm32_dmainterrupt); + + /* Disable the DMA stream */ + + stm32_dmastreamdisable(dmast); + + /* Enable the IRQ at the NVIC (still disabled at the DMA controller) */ + + up_enable_irq(dmast->irq); + + /* Set the interrrupt priority */ + + up_prioritize_irq(dmast->irq, CONFIG_DMA_PRI); + } +} + +/**************************************************************************** + * Name: stm32_dmachannel + * + * Description: + * Allocate a DMA channel. This function gives the caller mutually + * exclusive access to the DMA channel specified by the 'dmamap' argument. + * DMA channels are shared on the STM32: Devices sharing the same DMA + * channel cannot do DMA concurrently! See the DMACHAN_* definitions in + * stm32_dma.h. + * + * If the DMA channel is not available, then stm32_dmachannel() will wait + * until the holder of the channel relinquishes the channel by calling + * stm32_dmafree(). WARNING: If you have two devices sharing a DMA + * channel and the code never releases the channel, the stm32_dmachannel + * call for the other will hang forever in this function! Don't let your + * design do that! + * + * Hmm.. I suppose this interface could be extended to make a non-blocking + * version. Feel free to do that if that is what you need. + * + * Input parameter: + * dmamap - Identifies the stream/channel resource. For the STM32 F4, this + * is a bit-encoded value as provided by the the DMAMAP_* definitions + * in chip/stm32f40xxx_dma.h + * + * Returned Value: + * Provided that 'dmamap' is valid, this function ALWAYS returns a non-NULL, + * void* DMA channel handle. (If 'dmamap' is invalid, the function will + * assert if debug is enabled or do something ignorant otherwise). + * + * Assumptions: + * - The caller does not hold he DMA channel. + * - The caller can wait for the DMA channel to be freed if it is no + * available. + * + ****************************************************************************/ + +DMA_HANDLE stm32_dmachannel(unsigned int dmamap) +{ + FAR struct stm32_dma_s *dmast; + + /* Get the stream index from the bit-encoded channel value */ + + dmast = stm32_dmamap(dmamap); + DEBUGASSERT(dmast != NULL); + + /* Get exclusive access to the DMA channel -- OR wait until the channel + * is available if it is currently being used by another driver + */ + + stm32_dmatake(dmast); + + /* The caller now has exclusive use of the DMA channel. Assign the + * channel to the stream and return an opaque reference to the stream + * structure. + */ + + dmast->channel = STM32_DMA_CHANNEL(dmamap); + return (DMA_HANDLE)dmast; +} + +/**************************************************************************** + * Name: stm32_dmafree + * + * Description: + * Release a DMA channel. If another thread is waiting for this DMA channel + * in a call to stm32_dmachannel, then this function will re-assign the + * DMA channel to that thread and wake it up. NOTE: The 'handle' used + * in this argument must NEVER be used again until stm32_dmachannel() is + * called again to re-gain access to the channel. + * + * Returned Value: + * None + * + * Assumptions: + * - The caller holds the DMA channel. + * - There is no DMA in progress + * + ****************************************************************************/ + +void stm32_dmafree(DMA_HANDLE handle) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + + DEBUGASSERT(handle != NULL); + + /* Release the channel */ + + stm32_dmagive(dmast); +} + +/**************************************************************************** + * Name: stm32_dmasetup + * + * Description: + * Configure DMA before using + * + ****************************************************************************/ + +void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, + size_t ntransfers, uint32_t scr) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + uint32_t regoffset; + uint32_t regval; + + dmadbg("paddr: %08x maddr: %08x ntransfers: %d scr: %08x\n", + paddr, maddr, ntransfers, scr); + + /* "If the stream is enabled, disable it by resetting the EN bit in the + * DMA_SxCR register, then read this bit in order to confirm that there is no + * ongoing stream operation. Writing this bit to 0 is not immediately + * effective since it is actually written to 0 once all the current transfers + * have finished. When the EN bit is read as 0, this means that the stream is + * ready to be configured. It is therefore necessary to wait for the EN bit + * to be cleared before starting any stream configuration. ..." + */ + + while ((dmast_getreg(dmast, STM32_DMA_SCR_OFFSET) & DMA_SCR_EN) != 0); + + /* "... All the stream dedicated bits set in the status register (DMA_LISR + * and DMA_HISR) from the previous data block DMA transfer should be cleared + * before the stream can be re-enabled." + * + * Clear pending stream interrupts by setting bits in the upper or lower IFCR + * register + */ + + if (dmast->stream < 4) + { + regoffset = STM32_DMA_LIFCR_OFFSET; + } + else + { + regoffset = STM32_DMA_HIFCR_OFFSET; + } + + dmabase_putreg(dmast, regoffset, (DMA_STREAM_MASK << dmast->shift)); + + /* "Set the peripheral register address in the DMA_SPARx register. The data + * will be moved from/to this address to/from the memory after the + * peripheral event. + */ + + dmast_putreg(dmast, STM32_DMA_SPAR_OFFSET, paddr); + + /* "Set the memory address in the DMA_SM0ARx ... register. The data will be + * written to or read from this memory after the peripheral event." + * + * Note that in double-buffered mode it is explicitly assumed that the second + * buffer immediately follows the first. + */ + + dmast_putreg(dmast, STM32_DMA_SM0AR_OFFSET, maddr); + if (scr & DMA_SCR_DBM) + { + dmast_putreg(dmast, STM32_DMA_SM1AR_OFFSET, maddr + ntransfers); + } + + /* "Configure the total number of data items to be transferred in the + * DMA_SNDTRx register. After each peripheral event, this value will be + * decremented." + * + * "When the peripheral flow controller is used for a given stream, the value + * written into the DMA_SxNDTR has no effect on the DMA transfer. Actually, + * whatever the value written, it will be forced by hardware to 0xFFFF as soon + * as the stream is enabled..." + */ + + dmast_putreg(dmast, STM32_DMA_SNDTR_OFFSET, ntransfers); + + /* "Select the DMA channel (request) using CHSEL[2:0] in the DMA_SxCR register." + * + * "Configure the stream priority using the PL[1:0] bits in the DMA_SCRx" + * register." + */ + + regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET); + regval &= ~(DMA_SCR_PL_MASK|DMA_SCR_CHSEL_MASK); + regval |= scr & DMA_SCR_PL_MASK; + regval |= (uint32_t)dmast->channel << DMA_SCR_CHSEL_SHIFT; + dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval); + + /* "Configure the FIFO usage (enable or disable, threshold in transmission and + * reception)" + * + * "Caution is required when choosing the FIFO threshold (bits FTH[1:0] of the + * DMA_SxFCR register) and the size of the memory burst (MBURST[1:0] of the + * DMA_SxCR register): The content pointed by the FIFO threshold must exactly + * match to an integer number of memory burst transfers. If this is not in the + * case, a FIFO error (flag FEIFx of the DMA_HISR or DMA_LISR register) will be + * generated when the stream is enabled, then the stream will be automatically + * disabled." + * + * The FIFO is disabled in circular mode when transferring data from a + * peripheral to memory, as in this case it is usually desirable to know that + * every byte from the peripheral is transferred immediately to memory. It is + * not practical to flush the DMA FIFO, as this requires disabling the channel + * which triggers the transfer-complete interrupt. + * + * NOTE: The FEIFx error interrupt is not enabled because the FEIFx seems to + * be reported spuriously causing good transfers to be marked as failures. + */ + + regval = dmast_getreg(dmast, STM32_DMA_SFCR_OFFSET); + regval &= ~(DMA_SFCR_FTH_MASK | DMA_SFCR_FS_MASK | DMA_SFCR_FEIE); + if (!((scr & (DMA_SCR_CIRC | DMA_SCR_DIR_MASK)) == (DMA_SCR_CIRC | DMA_SCR_DIR_P2M))) + { + regval |= (DMA_SFCR_FTH_FULL | DMA_SFCR_DMDIS); + } + dmast_putreg(dmast, STM32_DMA_SFCR_OFFSET, regval); + + /* "Configure data transfer direction, circular mode, peripheral & memory + * incremented mode, peripheral & memory data size, and interrupt after + * half and/or full transfer in the DMA_CCRx register." + * + * Note: The CT bit is always reset. + */ + + regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET); + regval &= ~(DMA_SCR_PFCTRL|DMA_SCR_DIR_MASK|DMA_SCR_PINC|DMA_SCR_MINC| + DMA_SCR_PSIZE_MASK|DMA_SCR_MSIZE_MASK|DMA_SCR_PINCOS| + DMA_SCR_CIRC|DMA_SCR_DBM|DMA_SCR_CT| + DMA_SCR_PBURST_MASK|DMA_SCR_MBURST_MASK); + scr &= (DMA_SCR_PFCTRL|DMA_SCR_DIR_MASK|DMA_SCR_PINC|DMA_SCR_MINC| + DMA_SCR_PSIZE_MASK|DMA_SCR_MSIZE_MASK|DMA_SCR_PINCOS| + DMA_SCR_DBM|DMA_SCR_CIRC| + DMA_SCR_PBURST_MASK|DMA_SCR_MBURST_MASK); + regval |= scr; + dmast->nonstop = (scr & (DMA_SCR_DBM|DMA_SCR_CIRC)) != 0; + dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval); +} + +/**************************************************************************** + * Name: stm32_dmastart + * + * Description: + * Start the DMA transfer + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * - No DMA in progress + * + ****************************************************************************/ + +void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool half) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + uint32_t scr; + + DEBUGASSERT(handle != NULL); + + /* Save the callback info. This will be invoked whent the DMA commpletes */ + + dmast->callback = callback; + dmast->arg = arg; + + /* Activate the stream by setting the ENABLE bit in the DMA_SCRx register. + * As soon as the stream is enabled, it can serve any DMA request from the + * peripheral connected on the stream. + */ + + scr = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET); + scr |= DMA_SCR_EN; + + if (!dmast->nonstop) + { + /* Once half of the bytes are transferred, the half-transfer flag (HTIF) is + * set and an interrupt is generated if the Half-Transfer Interrupt Enable + * bit (HTIE) is set. At the end of the transfer, the Transfer Complete Flag + * (TCIF) is set and an interrupt is generated if the Transfer Complete + * Interrupt Enable bit (TCIE) is set. + */ + + scr |= (half ? (DMA_SCR_HTIE|DMA_SCR_TEIE) : (DMA_SCR_TCIE|DMA_SCR_TEIE)); + } + else + { + /* In nonstop mode, when the transfer completes it immediately resets + * and starts again. The transfer-complete interrupt is thus always + * enabled, and the half-complete interrupt can be used in circular + * mode to determine when the buffer is half-full, or in double-buffered + * mode to determine when one of the two buffers is full. + */ + scr |= (half ? DMA_SCR_HTIE : 0) | DMA_SCR_TCIE | DMA_SCR_TEIE; + } + + dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, scr); +} + +/**************************************************************************** + * Name: stm32_dmastop + * + * Description: + * Cancel the DMA. After stm32_dmastop() is called, the DMA channel is + * reset and stm32_dmasetup() must be called before stm32_dmastart() can be + * called again + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +void stm32_dmastop(DMA_HANDLE handle) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + stm32_dmastreamdisable(dmast); +} + +/**************************************************************************** + * Name: stm32_dmaresidual + * + * Description: + * Read the DMA bytes-remaining register. + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +size_t stm32_dmaresidual(DMA_HANDLE handle) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + uint32_t residual; + + /* Fetch the count of bytes remaining to be transferred. + * + * If the FIFO is enabled, this count may be inaccurate. ST don't + * appear to document whether this counts the peripheral or the memory + * side of the channel, and they don't make the memory pointer + * available either. + * + * For reception in circular mode the FIFO is disabled in order that + * this value can be useful. + */ + + residual = dmast_getreg(dmast, STM32_DMA_SNDTR_OFFSET); + + return (size_t)residual; +} + +/**************************************************************************** + * Name: stm32_dmasample + * + * Description: + * Sample DMA register contents + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA +void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + irqstate_t flags; + + flags = irqsave(); + regs->lisr = dmabase_getreg(dmast, STM32_DMA_LISR_OFFSET); + regs->hisr = dmabase_getreg(dmast, STM32_DMA_HISR_OFFSET); + regs->scr = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET); + regs->sndtr = dmast_getreg(dmast, STM32_DMA_SNDTR_OFFSET); + regs->spar = dmast_getreg(dmast, STM32_DMA_SPAR_OFFSET); + regs->sm0ar = dmast_getreg(dmast, STM32_DMA_SM0AR_OFFSET); + regs->sm1ar = dmast_getreg(dmast, STM32_DMA_SM1AR_OFFSET); + regs->sfcr = dmast_getreg(dmast, STM32_DMA_SFCR_OFFSET); + irqrestore(flags); +} +#endif + +/**************************************************************************** + * Name: stm32_dmadump + * + * Description: + * Dump previously sampled DMA register contents + * + * Assumptions: + * - DMA handle allocated by stm32_dmachannel() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA +void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs, + const char *msg) +{ + struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle; + uint32_t dmabase = DMA_BASE(dmast->base); + + dmadbg("DMA Registers: %s\n", msg); + dmadbg(" LISR[%08x]: %08x\n", dmabase + STM32_DMA_LISR_OFFSET, regs->lisr); + dmadbg(" HISR[%08x]: %08x\n", dmabase + STM32_DMA_HISR_OFFSET, regs->hisr); + dmadbg(" SCR[%08x]: %08x\n", dmast->base + STM32_DMA_SCR_OFFSET, regs->scr); + dmadbg(" SNDTR[%08x]: %08x\n", dmast->base + STM32_DMA_SNDTR_OFFSET, regs->sndtr); + dmadbg(" SPAR[%08x]: %08x\n", dmast->base + STM32_DMA_SPAR_OFFSET, regs->spar); + dmadbg(" SM0AR[%08x]: %08x\n", dmast->base + STM32_DMA_SM0AR_OFFSET, regs->sm0ar); + dmadbg(" SM1AR[%08x]: %08x\n", dmast->base + STM32_DMA_SM1AR_OFFSET, regs->sm1ar); + dmadbg(" SFCR[%08x]: %08x\n", dmast->base + STM32_DMA_SFCR_OFFSET, regs->sfcr); +} +#endif + +#endif /* CONFIG_STM32_STM32F40XX */ diff --git a/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c b/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c new file mode 100644 index 0000000000..7ba341b2b8 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c @@ -0,0 +1,668 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32f40xxx_rcc.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "stm32_pwr.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Allow up to 100 milliseconds for the high speed clock to become ready. + * that is a very long delay, but if the clock does not become ready we are + * hosed anyway. Normally this is very fast, but I have seen at least one + * board that required this long, long timeout for the HSE to be ready. + */ + +#define HSERDY_TIMEOUT (100 * CONFIG_BOARD_LOOPSPERMSEC) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rcc_reset + * + * Description: + * Reset the RCC clock configuration to the default reset state + * + ****************************************************************************/ + +static inline void rcc_reset(void) +{ + uint32_t regval; + + /* Enable the Internal High Speed clock (HSI) */ + + regval = getreg32(STM32_RCC_CR); + regval |= RCC_CR_HSION; + putreg32(regval, STM32_RCC_CR); + + /* Reset CFGR register */ + + putreg32(0x00000000, STM32_RCC_CFGR); + + /* Reset HSEON, CSSON and PLLON bits */ + + regval = getreg32(STM32_RCC_CR); + regval &= ~(RCC_CR_HSEON|RCC_CR_CSSON|RCC_CR_PLLON); + putreg32(regval, STM32_RCC_CR); + + /* Reset PLLCFGR register to reset default */ + + putreg32(RCC_PLLCFG_RESET, STM32_RCC_PLLCFG); + + /* Reset HSEBYP bit */ + + regval = getreg32(STM32_RCC_CR); + regval &= ~RCC_CR_HSEBYP; + putreg32(regval, STM32_RCC_CR); + + /* Disable all interrupts */ + + putreg32(0x00000000, STM32_RCC_CIR); +} + +/**************************************************************************** + * Name: rcc_enableahb1 + * + * Description: + * Enable selected AHB1 peripherals + * + ****************************************************************************/ + +static inline void rcc_enableahb1(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the AHB1ENR register to enabled the + * selected AHB1 peripherals. + */ + + regval = getreg32(STM32_RCC_AHB1ENR); + + /* Enable GPIOA, GPIOB, .... GPIOI*/ + +#if STM32_NGPIO > 0 + regval |= (RCC_AHB1ENR_GPIOAEN +#if STM32_NGPIO > 16 + |RCC_AHB1ENR_GPIOBEN +#endif +#if STM32_NGPIO > 32 + |RCC_AHB1ENR_GPIOCEN +#endif +#if STM32_NGPIO > 48 + |RCC_AHB1ENR_GPIODEN +#endif +#if STM32_NGPIO > 64 + |RCC_AHB1ENR_GPIOEEN +#endif +#if STM32_NGPIO > 80 + |RCC_AHB1ENR_GPIOFEN +#endif +#if STM32_NGPIO > 96 + |RCC_AHB1ENR_GPIOGEN +#endif +#if STM32_NGPIO > 112 + |RCC_AHB1ENR_GPIOHEN +#endif +#if STM32_NGPIO > 128 + |RCC_AHB1ENR_GPIOIEN +#endif + ); +#endif + +#ifdef CONFIG_STM32_CRC + /* CRC clock enable */ + + regval |= RCC_AHB1ENR_CRCEN; +#endif + +#ifdef CONFIG_STM32_BKPSRAM + /* Backup SRAM clock enable */ + + regval |= RCC_AHB1ENR_BKPSRAMEN; +#endif + +#ifdef CONFIG_STM32_CCMDATARAM + /* CCM data RAM clock enable */ + + regval |= RCC_AHB1ENR_CCMDATARAMEN; +#endif + +#ifdef CONFIG_STM32_DMA1 + /* DMA 1 clock enable */ + + regval |= RCC_AHB1ENR_DMA1EN; +#endif + +#ifdef CONFIG_STM32_DMA2 + /* DMA 2 clock enable */ + + regval |= RCC_AHB1ENR_DMA2EN; +#endif + +#ifdef CONFIG_STM32_ETHMAC + /* Ethernet MAC clocking */ + + regval |= (RCC_AHB1ENR_ETHMACEN|RCC_AHB1ENR_ETHMACTXEN|RCC_AHB1ENR_ETHMACRXEN); + +#ifdef CONFIG_STM32_ETH_PTP + /* Precision Time Protocol (PTP) */ + + regval |= RCC_AHB1ENR_ETHMACPTPEN; + +#endif +#endif + +#ifdef CONFIG_STM32_OTGHS + /* USB OTG HS */ + + regval |= (RCC_AHB1ENR_OTGHSEN|RCC_AHB1ENR_OTGHSULPIEN); +#endif + + putreg32(regval, STM32_RCC_AHB1ENR); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: rcc_enableahb2 + * + * Description: + * Enable selected AHB2 peripherals + * + ****************************************************************************/ + +static inline void rcc_enableahb2(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the AHB2ENR register to enabled the + * selected AHB2 peripherals. + */ + + regval = getreg32(STM32_RCC_AHB2ENR); + +#ifdef CONFIG_STM32_DCMI + /* Camera interface enable */ + + regval |= RCC_AHB2ENR_DCMIEN; +#endif + +#ifdef CONFIG_STM32_CRYP + /* Cryptographic modules clock enable */ + + regval |= RCC_AHB2ENR_CRYPEN; +#endif + +#ifdef CONFIG_STM32_HASH + /* Hash modules clock enable */ + + regval |= RCC_AHB2ENR_HASHEN; +#endif + +#ifdef CONFIG_STM32_RNG + /* Random number generator clock enable */ + + regval |= RCC_AHB2ENR_RNGEN; +#endif + +#ifdef CONFIG_STM32_OTGFS + /* USB OTG FS clock enable */ + + regval |= RCC_AHB2ENR_OTGFSEN; +#endif + + putreg32(regval, STM32_RCC_AHB2ENR); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: rcc_enableahb3 + * + * Description: + * Enable selected AHB3 peripherals + * + ****************************************************************************/ + +static inline void rcc_enableahb3(void) +{ +#ifdef CONFIG_STM32_FSMC + uint32_t regval; + + /* Set the appropriate bits in the AHB3ENR register to enabled the + * selected AHB3 peripherals. + */ + + regval = getreg32(STM32_RCC_AHB3ENR); + + /* Flexible static memory controller module clock enable */ + + regval |= RCC_AHB3ENR_FSMCEN; + + putreg32(regval, STM32_RCC_AHB3ENR); /* Enable peripherals */ +#endif +} + +/**************************************************************************** + * Name: rcc_enableapb1 + * + * Description: + * Enable selected APB1 peripherals + * + ****************************************************************************/ + +static inline void rcc_enableapb1(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the APB1ENR register to enabled the + * selected APB1 peripherals. + */ + + regval = getreg32(STM32_RCC_APB1ENR); + +#ifdef CONFIG_STM32_TIM2 + /* TIM2 clock enable */ + + regval |= RCC_APB1ENR_TIM2EN; +#endif + +#ifdef CONFIG_STM32_TIM3 + /* TIM3 clock enable */ + + regval |= RCC_APB1ENR_TIM3EN; +#endif + +#ifdef CONFIG_STM32_TIM4 + /* TIM4 clock enable */ + + regval |= RCC_APB1ENR_TIM4EN; +#endif + +#ifdef CONFIG_STM32_TIM5 + /* TIM5 clock enable */ + + regval |= RCC_APB1ENR_TIM5EN; +#endif + +#ifdef CONFIG_STM32_TIM6 + /* TIM6 clock enable */ + + regval |= RCC_APB1ENR_TIM6EN; +#endif + +#ifdef CONFIG_STM32_TIM7 + /* TIM7 clock enable */ + + regval |= RCC_APB1ENR_TIM7EN; +#endif + +#ifdef CONFIG_STM32_TIM12 + /* TIM12 clock enable */ + + regval |= RCC_APB1ENR_TIM12EN; +#endif + +#ifdef CONFIG_STM32_TIM13 + /* TIM13 clock enable */ + + regval |= RCC_APB1ENR_TIM13EN; +#endif + +#ifdef CONFIG_STM32_TIM14 + /* TIM14 clock enable */ + + regval |= RCC_APB1ENR_TIM14EN; +#endif + +#ifdef CONFIG_STM32_WWDG + /* Window watchdog clock enable */ + + regval |= RCC_APB1ENR_WWDGEN; +#endif + +#ifdef CONFIG_STM32_SPI2 + /* SPI2 clock enable */ + + regval |= RCC_APB1ENR_SPI2EN; +#endif + +#ifdef CONFIG_STM32_SPI3 + /* SPI3 clock enable */ + + regval |= RCC_APB1ENR_SPI3EN; +#endif + +#ifdef CONFIG_STM32_USART2 + /* USART 2 clock enable */ + + regval |= RCC_APB1ENR_USART2EN; +#endif + +#ifdef CONFIG_STM32_USART3 + /* USART3 clock enable */ + + regval |= RCC_APB1ENR_USART3EN; +#endif + +#ifdef CONFIG_STM32_UART4 + /* UART4 clock enable */ + + regval |= RCC_APB1ENR_UART4EN; +#endif + +#ifdef CONFIG_STM32_UART5 + /* UART5 clock enable */ + + regval |= RCC_APB1ENR_UART5EN; +#endif + +#ifdef CONFIG_STM32_I2C1 + /* I2C1 clock enable */ + + regval |= RCC_APB1ENR_I2C1EN; +#endif + +#ifdef CONFIG_STM32_I2C2 + /* I2C2 clock enable */ + + regval |= RCC_APB1ENR_I2C2EN; +#endif + +#ifdef CONFIG_STM32_I2C3 + /* I2C3 clock enable */ + + regval |= RCC_APB1ENR_I2C3EN; +#endif + +#ifdef CONFIG_STM32_CAN1 + /* CAN 1 clock enable */ + + regval |= RCC_APB1ENR_CAN1EN; +#endif + +#ifdef CONFIG_STM32_CAN2 + /* CAN2 clock enable. NOTE: CAN2 needs CAN1 clock as well. */ + + regval |= (RCC_APB1ENR_CAN1EN | RCC_APB1ENR_CAN2EN); +#endif + + /* Power interface clock enable. The PWR block is always enabled so that + * we can set the internal voltage regulator for maximum performance. + */ + + regval |= RCC_APB1ENR_PWREN; + +#if defined (CONFIG_STM32_DAC1) || defined(CONFIG_STM32_DAC2) + /* DAC interface clock enable */ + + regval |= RCC_APB1ENR_DACEN; +#endif + + putreg32(regval, STM32_RCC_APB1ENR); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: rcc_enableapb2 + * + * Description: + * Enable selected APB2 peripherals + * + ****************************************************************************/ + +static inline void rcc_enableapb2(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the APB2ENR register to enabled the + * selected APB2 peripherals. + */ + + regval = getreg32(STM32_RCC_APB2ENR); + +#ifdef CONFIG_STM32_TIM1 + /* TIM1 clock enable */ + + regval |= RCC_APB2ENR_TIM1EN; +#endif + +#ifdef CONFIG_STM32_TIM8 + /* TIM8 clock enable */ + + regval |= RCC_APB2ENR_TIM8EN; +#endif + +#ifdef CONFIG_STM32_USART1 + /* USART1 clock enable */ + + regval |= RCC_APB2ENR_USART1EN; +#endif + +#ifdef CONFIG_STM32_USART6 + /* USART6 clock enable */ + + regval |= RCC_APB2ENR_USART6EN; +#endif + +#ifdef CONFIG_STM32_ADC1 + /* ADC1 clock enable */ + + regval |= RCC_APB2ENR_ADC1EN; +#endif + +#ifdef CONFIG_STM32_ADC2 + /* ADC2 clock enable */ + + regval |= RCC_APB2ENR_ADC2EN; +#endif + +#ifdef CONFIG_STM32_ADC3 + /* ADC3 clock enable */ + + regval |= RCC_APB2ENR_ADC3EN; +#endif + +#ifdef CONFIG_STM32_SDIO + /* SDIO clock enable */ + + regval |= RCC_APB2ENR_SDIOEN; +#endif + +#ifdef CONFIG_STM32_SPI1 + /* SPI1 clock enable */ + + regval |= RCC_APB2ENR_SPI1EN; +#endif + +#ifdef CONFIG_STM32_SYSCFG + /* System configuration controller clock enable */ + + regval |= RCC_APB2ENR_SYSCFGEN; +#endif + +#ifdef CONFIG_STM32_TIM9 + /* TIM9 clock enable */ + + regval |= RCC_APB2ENR_TIM9EN; +#endif + +#ifdef CONFIG_STM32_TIM10 + /* TIM10 clock enable */ + + regval |= RCC_APB2ENR_TIM10EN; +#endif + +#ifdef CONFIG_STM32_TIM11 + /* TIM11 clock enable */ + + regval |= RCC_APB2ENR_TIM11EN; +#endif + + putreg32(regval, STM32_RCC_APB2ENR); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: stm32_stdclockconfig + * + * Description: + * Called to change to new clock based on settings in board.h + * + * NOTE: This logic would need to be extended if you need to select low- + * power clocking modes! + ****************************************************************************/ + +#ifndef CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG +static void stm32_stdclockconfig(void) +{ + uint32_t regval; + volatile int32_t timeout; + + /* Enable External High-Speed Clock (HSE) */ + + regval = getreg32(STM32_RCC_CR); + regval |= RCC_CR_HSEON; /* Enable HSE */ + putreg32(regval, STM32_RCC_CR); + + /* Wait until the HSE is ready (or until a timeout elapsed) */ + + for (timeout = HSERDY_TIMEOUT; timeout > 0; timeout--) + { + /* Check if the HSERDY flag is the set in the CR */ + + if ((getreg32(STM32_RCC_CR) & RCC_CR_HSERDY) != 0) + { + /* If so, then break-out with timeout > 0 */ + + break; + } + } + + /* Check for a timeout. If this timeout occurs, then we are hosed. We + * have no real back-up plan, although the following logic makes it look + * as though we do. + */ + + if (timeout > 0) + { + /* Select regulator voltage output Scale 1 mode to support system + * frequencies up to 168 MHz. + */ + + regval = getreg32(STM32_RCC_APB1ENR); + regval |= RCC_APB1ENR_PWREN; + putreg32(regval, STM32_RCC_APB1ENR); + + regval = getreg32(STM32_PWR_CR); + regval |= PWR_CR_VOS; + putreg32(regval, STM32_PWR_CR); + + /* Set the HCLK source/divider */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~RCC_CFGR_HPRE_MASK; + regval |= STM32_RCC_CFGR_HPRE; + putreg32(regval, STM32_RCC_CFGR); + + /* Set the PCLK2 divider */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~RCC_CFGR_PPRE2_MASK; + regval |= STM32_RCC_CFGR_PPRE2; + putreg32(regval, STM32_RCC_CFGR); + + /* Set the PCLK1 divider */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~RCC_CFGR_PPRE1_MASK; + regval |= STM32_RCC_CFGR_PPRE1; + putreg32(regval, STM32_RCC_CFGR); + + /* Set the PLL dividers and multiplers to configure the main PLL */ + + regval = (STM32_PLLCFG_PLLM | STM32_PLLCFG_PLLN |STM32_PLLCFG_PLLP | + RCC_PLLCFG_PLLSRC_HSE | STM32_PLLCFG_PPQ); + putreg32(regval, STM32_RCC_PLLCFG); + + /* Enable the main PLL */ + + regval = getreg32(STM32_RCC_CR); + regval |= RCC_CR_PLLON; + putreg32(regval, STM32_RCC_CR); + + /* Wait until the PLL is ready */ + + while ((getreg32(STM32_RCC_CR) & RCC_CR_PLLRDY) == 0); + + /* Enable FLASH prefetch, instruction cache, data cache, and 5 wait states */ + + regval = (FLASH_ACR_LATENCY_5 | FLASH_ACR_ICEN | FLASH_ACR_DCEN); + putreg32(regval, STM32_FLASH_ACR); + + /* Select the main PLL as system clock source */ + + regval = getreg32(STM32_RCC_CFGR); + regval &= ~RCC_CFGR_SW_MASK; + regval |= RCC_CFGR_SW_PLL; + putreg32(regval, STM32_RCC_CFGR); + + /* Wait until the PLL source is used as the system clock source */ + + while ((getreg32(STM32_RCC_CFGR) & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL); + } +} +#endif + +/**************************************************************************** + * Name: rcc_enableperiphals + ****************************************************************************/ + +static inline void rcc_enableperipherals(void) +{ + rcc_enableahb1(); + rcc_enableahb2(); + rcc_enableahb3(); + rcc_enableapb1(); + rcc_enableapb2(); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/nuttx/arch/arm/src/stm32/stm32f40xxx_rtc.c b/nuttx/arch/arm/src/stm32/stm32f40xxx_rtc.c new file mode 100644 index 0000000000..c11748ae57 --- /dev/null +++ b/nuttx/arch/arm/src/stm32/stm32f40xxx_rtc.c @@ -0,0 +1,842 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32f40xxx_rtc.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include "up_arch.h" + +#include "stm32_rtc.h" + +#ifdef CONFIG_RTC + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* This RTC implementation supports only date/time RTC hardware */ + +#ifndef CONFIG_RTC_DATETIME +# error "CONFIG_RTC_DATETIME must be set to use this driver" +#endif + +#ifdef CONFIG_RTC_HIRES +# error "CONFIG_RTC_HIRES must NOT be set with this driver" +#endif + +#ifndef CONFIG_STM32_PWR +# error "CONFIG_STM32_PWR must selected to use this driver" +#endif + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_RTC +#endif + +/* Constants ************************************************************************/ + +#define SYNCHRO_TIMEOUT (0x00020000) +#define INITMODE_TIMEOUT (0x00010000) +#define RTC_MAGIC (0xfacefeed) +#define RTC_PREDIV_S (0xff) +#define RTC_PREDIV_A (0x7f) + +/* Debug ****************************************************************************/ + +#ifdef CONFIG_DEBUG_RTC +# define rtcdbg dbg +# define rtcvdbg vdbg +# define rtclldbg lldbg +# define rtcllvdbg llvdbg +#else +# define rtcdbg(x...) +# define rtcvdbg(x...) +# define rtclldbg(x...) +# define rtcllvdbg(x...) +#endif + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +/* Callback to use when the alarm expires */ + +#ifdef CONFIG_RTC_ALARM +static alarmcb_t g_alarmcb; +#endif + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/* g_rtc_enabled is set true after the RTC has successfully initialized */ + +volatile bool g_rtc_enabled = false; + +/************************************************************************************ + * Private Functions + ************************************************************************************/ +/************************************************************************************ + * Name: rtc_dumpregs + * + * Description: + * Disable RTC write protection + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifdef CONFIG_DEBUG_RTC +static void rtc_dumpregs(FAR const char *msg) +{ + rtclldbg("%s:\n", msg); + rtclldbg(" TR: %08x\n", getreg32(STM32_RTC_TR)); + rtclldbg(" DR: %08x\n", getreg32(STM32_RTC_DR)); + rtclldbg(" CR: %08x\n", getreg32(STM32_RTC_CR)); + rtclldbg(" ISR: %08x\n", getreg32(STM32_RTC_ISR)); + rtclldbg(" PRER: %08x\n", getreg32(STM32_RTC_PRER)); + rtclldbg(" WUTR: %08x\n", getreg32(STM32_RTC_WUTR)); + rtclldbg(" CALIBR: %08x\n", getreg32(STM32_RTC_CALIBR)); + rtclldbg(" ALRMAR: %08x\n", getreg32(STM32_RTC_ALRMAR)); + rtclldbg(" ALRMBR: %08x\n", getreg32(STM32_RTC_ALRMBR)); + rtclldbg(" SHIFTR: %08x\n", getreg32(STM32_RTC_SHIFTR)); + rtclldbg(" TSTR: %08x\n", getreg32(STM32_RTC_TSTR)); + rtclldbg(" TSDR: %08x\n", getreg32(STM32_RTC_TSDR)); + rtclldbg(" TSSSR: %08x\n", getreg32(STM32_RTC_TSSSR)); + rtclldbg(" CALR: %08x\n", getreg32(STM32_RTC_CALR)); + rtclldbg(" TAFCR: %08x\n", getreg32(STM32_RTC_TAFCR)); + rtclldbg("ALRMASSR: %08x\n", getreg32(STM32_RTC_ALRMASSR)); + rtclldbg("ALRMBSSR: %08x\n", getreg32(STM32_RTC_ALRMBSSR)); + rtclldbg(" BK0: %08x\n", getreg32(STM32_RTC_BK0R)); +} +#else +# define rtc_dumpregs(msg) +#endif + +/************************************************************************************ + * Name: rtc_dumptime + * + * Description: + * Disable RTC write protection + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifdef CONFIG_DEBUG_RTC +static void rtc_dumptime(FAR struct tm *tp, FAR const char *msg) +{ + rtclldbg("%s:\n", msg); + rtclldbg(" tm_sec: %08x\n", tp->tm_sec); + rtclldbg(" tm_min: %08x\n", tp->tm_min); + rtclldbg(" tm_hour: %08x\n", tp->tm_hour); + rtclldbg(" tm_mday: %08x\n", tp->tm_mday); + rtclldbg(" tm_mon: %08x\n", tp->tm_mon); + rtclldbg(" tm_year: %08x\n", tp->tm_year); +} +#else +# define rtc_dumptime(tp, msg) +#endif + +/************************************************************************************ + * Name: rtc_wprunlock + * + * Description: + * Disable RTC write protection + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +static void rtc_wprunlock(void) +{ + /* The following steps are required to unlock the write protection on all the + * RTC registers (except for RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR). + * + * 1. Write 0xCA into the RTC_WPR register. + * 2. Write 0x53 into the RTC_WPR register. + * + * Writing a wrong key reactivates the write protection. + */ + + putreg32(0xca, STM32_RTC_WPR); + putreg32(0x53, STM32_RTC_WPR); +} + +/************************************************************************************ + * Name: rtc_wprunlock + * + * Description: + * Enable RTC write protection + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +static inline void rtc_wprlock(void) +{ + /* Writing any wrong key reactivates the write protection. */ + + putreg32(0xff, STM32_RTC_WPR); +} + +/************************************************************************************ + * Name: rtc_synchwait + * + * Description: + * Waits until the RTC Time and Date registers (RTC_TR and RTC_DR) are + * synchronized with RTC APB clock. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static int rtc_synchwait(void) +{ + volatile uint32_t timeout; + uint32_t regval; + int ret; + + /* Disable the write protection for RTC registers */ + + rtc_wprunlock(); + + /* Clear Registers synchronization flag (RSF) */ + + regval = getreg32(STM32_RTC_ISR); + regval &= ~RTC_ISR_RSF; + putreg32(regval, STM32_RTC_ISR); + + /* Now wait the registers to become synchronised */ + + ret = -ETIMEDOUT; + for (timeout = 0; timeout < SYNCHRO_TIMEOUT; timeout++) + { + regval = getreg32(STM32_RTC_ISR); + if ((regval & RTC_ISR_RSF) != 0) + { + /* Synchronized */ + + ret = OK; + break; + } + } + + /* Re-enable the write protection for RTC registers */ + + rtc_wprlock(); + return ret; +} + +/************************************************************************************ + * Name: rtc_enterinit + * + * Description: + * Enter RTC initialization mode. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static int rtc_enterinit(void) +{ + volatile uint32_t timeout; + uint32_t regval; + int ret; + + /* Check if the Initialization mode is already set */ + + regval = getreg32(STM32_RTC_ISR); + + ret = OK; + if ((regval & RTC_ISR_INITF) == 0) + { + /* Set the Initialization mode */ + + putreg32(RTC_ISR_INIT, STM32_RTC_ISR); + + /* Wait until the RTC is in the INIT state (or a timeout occurs) */ + + ret = -ETIMEDOUT; + for (timeout = 0; timeout < INITMODE_TIMEOUT; timeout++) + { + regval = getreg32(STM32_RTC_ISR); + if ((regval & RTC_ISR_INITF) != 0) + { + ret = OK; + break; + } + } + } + + return ret; +} + +/************************************************************************************ + * Name: rtc_exitinit + * + * Description: + * Exit RTC initialization mode. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static void rtc_exitinit(void) +{ + uint32_t regval; + + regval = getreg32(STM32_RTC_ISR); + regval &= ~(RTC_ISR_INIT); + putreg32(regval, STM32_RTC_ISR); +} + +/************************************************************************************ + * Name: rtc_bin2bcd + * + * Description: + * Converts a 2 digit binary to BCD format + * + * Input Parameters: + * value - The byte to be converted. + * + * Returned Value: + * The value in BCD representation + * + ************************************************************************************/ + +static uint32_t rtc_bin2bcd(int value) +{ + uint32_t msbcd = 0; + + while (value >= 10) + { + msbcd++; + value -= 10; + } + + return (msbcd << 4) | value; +} + +/************************************************************************************ + * Name: rtc_bin2bcd + * + * Description: + * Convert from 2 digit BCD to binary. + * + * Input Parameters: + * value - The BCD value to be converted. + * + * Returned Value: + * The value in binary representation + * + ************************************************************************************/ + +static int rtc_bcd2bin(uint32_t value) +{ + uint32_t tens = (value >> 4) * 10; + return (int)(tens + (value & 0x0f)); +} + +/************************************************************************************ + * Name: rtc_setup + * + * Description: + * Performs first time configuration of the RTC. A special value written into + * back-up register 0 will prevent this function from being called on sub-sequent + * resets or power up. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static int rtc_setup(void) +{ + uint32_t regval; + int ret; + + /* Enable the External Low-Speed (LSE) Oscillator setup the LSE as the RTC clock\ + * source, and enable the RTC. + */ + + stm32_rcc_enablelse(); + + /* Wait for the RTC Time and Date registers to be synchronized with RTC APB + * clock. + */ + + ret = rtc_synchwait(); + if (ret == OK) + { + /* Disable the write protection for RTC registers */ + + rtc_wprunlock(); + + /* Set Initialization mode */ + + ret = rtc_enterinit(); + if (ret == OK) + { + /* Set the 24 hour format by clearing the FMT bit in the RTC + * control register + */ + + regval = getreg32(STM32_RTC_CR); + regval &= ~RTC_CR_FMT; + putreg32(regval, STM32_RTC_CR); + + /* Configure RTC pre-scaler to the required, default values for + * use with the 32.768 KHz LSE clock: + */ + + putreg32(((uint32_t)0xff << RTC_PRER_PREDIV_S_SHIFT) | + ((uint32_t)0x7f << RTC_PRER_PREDIV_A_SHIFT), + STM32_RTC_PRER); + + /* Exit RTC initialization mode */ + + rtc_exitinit(); + } + + /* Re-enable the write protection for RTC registers */ + + rtc_wprlock(); + } + return ret; +} + +/************************************************************************************ + * Name: rtc_resume + * + * Description: + * Called when the RTC was already initialized on a previous power cycle. This + * just brings the RTC back into full operation. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static int rtc_resume(void) +{ +#ifdef CONFIG_RTC_ALARM + uint32_t regval; +#endif + int ret; + + /* Wait for the RTC Time and Date registers to be syncrhonized with RTC APB + * clock. + */ + + ret = rtc_synchwait(); + + /* Clear the RTC alarm flags */ + +#ifdef CONFIG_RTC_ALARM + regval = getreg32(STM32_RTC_ISR); + regval &= ~(RTC_ISR_ALRAF|RTC_ISR_ALRBF); + putreg32(regval, STM32_RTC_ISR); + + /* Clear the EXTI Line 17 Pending bit (Connected internally to RTC Alarm) */ + + putreg32((1 << 17), STM32_EXTI_PR); +#endif + return ret; +} + +/************************************************************************************ + * Name: rtc_interrupt + * + * Description: + * RTC interrupt service routine + * + * Input Parameters: + * irq - The IRQ number that generated the interrupt + * context - Architecture specific register save information. + * + * Returned Value: + * Zero (OK) on success; A negated errno value on failure. + * + ************************************************************************************/ + +#if CONFIG_RTC_ALARM +static int rtc_interrupt(int irq, void *context) +{ +#warning "Missing logic" + return OK; +} +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_rtcinitialize + * + * Description: + * Initialize the hardware RTC per the selected configuration. This function is + * called once during the OS initialization sequence + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +int up_rtcinitialize(void) +{ + uint32_t regval; + int ret; + + rtc_dumpregs("On reset"); + + /* Clocking for the PWR block must be provided. However, this is done + * unconditionally in stm32f40xxx_rcc.c on power up. This done unconditionally + * because the PWR block is also needed to set the internal voltage regulator for + * maximum performance. + */ + + /* Enable access to the backup domain (RTC registers, RTC backup data registers + * and backup SRAM). + */ + + stm32_pwr_enablebkp(); + + /* Check if the one-time initialization of the RTC has already been performed. + * We can determine this by checking if the magic number has been writing to + * to back-up date register DR0. + */ + + regval = getreg32(STM32_RTC_BK0R); + if (regval != RTC_MAGIC) + { + /* Perform the one-time setup of the LSE clocking to the RTC */ + + ret = rtc_setup(); + + /* Remember that the RTC is initialized */ + + putreg32(RTC_MAGIC, STM32_RTC_BK0R); + } + else + { + /* RTC already set-up, just resume normal operation */ + + ret = rtc_resume(); + } + + /* Configure RTC interrupt to catch alarm interrupts. All RTC interrupts are + * connected to the EXTI controller. To enable the RTC Alarm interrupt, the + * following sequence is required: + * + * 1. Configure and enable the EXTI Line 17 in interrupt mode and select the + * rising edge sensitivity. + * 2. Configure and enable the RTC_Alarm IRQ channel in the NVIC. + * 3. Configure the RTC to generate RTC alarms (Alarm A or Alarm B). + */ + +#ifdef CONFIG_RTC_ALARM +# warning "Missing EXTI setup logic" + + /* Then attach the ALARM interrupt handler */ + + irq_attach(STM32_IRQ_RTC_WKUP, rtc_interrupt); + up_enable_irq(STM32_IRQ_RTC_WKUP); +#endif + + g_rtc_enabled = true; + rtc_dumpregs("After Initialization"); + return OK; +} + +/************************************************************************************ + * Name: up_rtc_getdatetime + * + * Description: + * Get the current date and time from the date/time RTC. This interface + * is only supported by the date/time RTC hardware implementation. + * It is used to replace the system timer. It is only used by the RTOS during + * intialization to set up the system time when CONFIG_RTC and CONFIG_RTC_DATETIME + * are selected (and CONFIG_RTC_HIRES is not). + * + * NOTE: Some date/time RTC hardware is capability of sub-second accuracy. That + * sub-second accuracy is lost in this interface. However, since the system time + * is reinitialized on each power-up/reset, there will be no timing inaccuracy in + * the long run. + * + * Input Parameters: + * tp - The location to return the high resolution time value. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +int up_rtc_getdatetime(FAR struct tm *tp) +{ + uint32_t dr; + uint32_t tr; + uint32_t tmp; + + /* Sample the data time registers. There is a race condition here... If we sample + * the time just before midnight on December 31, the date could be wrong because + * the day rolled over while were sampling. + */ + + do + { + dr = getreg32(STM32_RTC_DR); + tr = getreg32(STM32_RTC_TR); + tmp = getreg32(STM32_RTC_DR); + } + while (tmp != dr); + + rtc_dumpregs("Reading Time"); + + /* Convert the RTC time to fields in struct tm format. All of the STM32 + * All of the ranges of values correspond between struct tm and the time + * register. + */ + + tmp = (tr & (RTC_TR_SU_MASK|RTC_TR_ST_MASK)) >> RTC_TR_SU_SHIFT; + tp->tm_sec = rtc_bcd2bin(tmp); + + tmp = (tr & (RTC_TR_MNU_MASK|RTC_TR_MNT_MASK)) >> RTC_TR_MNU_SHIFT; + tp->tm_min = rtc_bcd2bin(tmp); + + tmp = (tr & (RTC_TR_HU_MASK|RTC_TR_HT_MASK)) >> RTC_TR_HU_SHIFT; + tp->tm_hour = rtc_bcd2bin(tmp); + + /* Now convert the RTC date to fields in struct tm format: + * Days: 1-31 match in both cases. + * Month: STM32 is 1-12, struct tm is 0-11. + * Years: STM32 is 00-99, struct tm is years since 1900. + * + * Issue: I am not sure what the STM32 years mean. Are these the + * years 2000-2099? I'll assume so. + */ + + tmp = (dr & (RTC_DR_DU_MASK|RTC_DR_DT_MASK)) >> RTC_DR_DU_SHIFT; + tp->tm_mday = rtc_bcd2bin(tmp); + + tmp = (dr & (RTC_DR_MU_MASK|RTC_DR_MT)) >> RTC_DR_MU_SHIFT; + tp->tm_mon = rtc_bcd2bin(tmp) - 1; + + tmp = (dr & (RTC_DR_YU_MASK|RTC_DR_YT_MASK)) >> RTC_DR_YU_SHIFT; + tp->tm_year = rtc_bcd2bin(tmp) + 100; + + rtc_dumptime(tp, "Returning"); + return OK; +} + +/************************************************************************************ + * Name: up_rtc_settime + * + * Description: + * Set the RTC to the provided time. All RTC implementations must be able to + * set their time based on a standard timespec. + * + * Input Parameters: + * tp - the time to use + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +int up_rtc_settime(FAR const struct timespec *tp) +{ + FAR struct tm newtime; + uint32_t tr; + uint32_t dr; + int ret; + + /* Break out the time values (not that the time is set only to units of seconds) */ + + (void)gmtime_r(&tp->tv_sec, &newtime); + rtc_dumptime(&newtime, "Setting time"); + + /* Then write the broken out values to the RTC */ + + /* Convert the struct tm format to RTC time register fields. All of the STM32 + * All of the ranges of values correspond between struct tm and the time + * register. + */ + + tr = (rtc_bin2bcd(newtime.tm_sec) << RTC_TR_SU_SHIFT) | + (rtc_bin2bcd(newtime.tm_min) << RTC_TR_MNU_SHIFT) | + (rtc_bin2bcd(newtime.tm_hour) << RTC_TR_HU_SHIFT); + tr &= ~RTC_TR_RESERVED_BITS; + + /* Now convert the fields in struct tm format to the RTC date register fields: + * Days: 1-31 match in both cases. + * Month: STM32 is 1-12, struct tm is 0-11. + * Years: STM32 is 00-99, struct tm is years since 1900. + * + * Issue: I am not sure what the STM32 years mean. Are these the + * years 2000-2099? I'll assume so. + */ + + dr = (rtc_bin2bcd(newtime.tm_mday) << RTC_DR_DU_SHIFT) | + ((rtc_bin2bcd(newtime.tm_mon + 1)) << RTC_DR_MU_SHIFT) | + ((rtc_bin2bcd(newtime.tm_year - 100)) << RTC_DR_YU_SHIFT); + dr &= ~RTC_DR_RESERVED_BITS; + + /* Disable the write protection for RTC registers */ + + rtc_wprunlock(); + + /* Set Initialization mode */ + + ret = rtc_enterinit(); + if (ret == OK) + { + /* Set the RTC TR and DR registers */ + + putreg32(tr, STM32_RTC_TR); + putreg32(dr, STM32_RTC_DR); + + /* Exit Initialization mode and wait for the RTC Time and Date + * registers to be synchronized with RTC APB clock. + */ + + rtc_exitinit(); + ret = rtc_synchwait(); + } + + /* Re-enable the write protection for RTC registers */ + + rtc_wprlock(); + rtc_dumpregs("New time setting"); + return ret; +} + +/************************************************************************************ + * Name: up_rtc_setalarm + * + * Description: + * Set up an alarm. Up to two alarms can be supported (ALARM A and ALARM B). + * + * Input Parameters: + * tp - the time to set the alarm + * callback - the function to call when the alarm expires. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int up_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback) +{ + irqstate_t flags; + int ret = -EBUSY; + + /* Is there already something waiting on the ALARM? */ + + if (g_alarmcb == NULL) + { + /* No.. Save the callback function pointer */ + + g_alarmcb = callback; + + /* Break out the time values */ +#warning "Missing logic" + + /* The set the alarm */ +#warning "Missing logic" + + ret = OK; + } + return ret; +} +#endif + +#endif /* CONFIG_RTC */ + diff --git a/nuttx/binfmt/Kconfig b/nuttx/binfmt/Kconfig new file mode 100644 index 0000000000..ae2bf31307 --- /dev/null +++ b/nuttx/binfmt/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# diff --git a/nuttx/binfmt/Makefile b/nuttx/binfmt/Makefile new file mode 100644 index 0000000000..dd9e459ced --- /dev/null +++ b/nuttx/binfmt/Makefile @@ -0,0 +1,102 @@ +############################################################################ +# nxflat/Makefile +# +# Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ifeq ($(WINTOOL),y) +INCDIROPT = -w +endif +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/sched} + +ifeq ($(CONFIG_NXFLAT),y) +include libnxflat/Make.defs +LIBNXFLAT_CSRCS += nxflat.c +endif + +BINFMT_ASRCS = +BINFMT_CSRCS = binfmt_globals.c binfmt_register.c binfmt_unregister.c \ + binfmt_loadmodule.c binfmt_unloadmodule.c binfmt_execmodule.c \ + binfmt_exec.c binfmt_dumpmodule.c + +SYMTAB_ASRCS = +SYMTAB_CSRCS = symtab_findbyname.c symtab_findbyvalue.c \ + symtab_findorderedbyname.c symtab_findorderedbyvalue.c + +SUBDIRS = libnxflat + +ASRCS = $(BINFMT_ASRCS) $(SYMTAB_ASRCS) $(LIBNXFLAT_ASRCS) +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +CSRCS = $(BINFMT_CSRCS) $(SYMTAB_CSRCS) $(LIBNXFLAT_CSRCS) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = libbinfmt$(LIBEXT) + +VPATH = libnxflat + +all: $(BIN) + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +.depend: Makefile $(SRCS) + @$(MKDEP) --dep-path . --dep-path libnxflat \ + $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f $(BIN) *~ .*.swp + $(call CLEAN) + @( for dir in $(SUBDIRS); do \ + rm -f $${dir}/*~ $${dir}/.*.swp; \ + done ; ) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/binfmt/binfmt_dumpmodule.c b/nuttx/binfmt/binfmt_dumpmodule.c new file mode 100644 index 0000000000..945dcb3ace --- /dev/null +++ b/nuttx/binfmt/binfmt_dumpmodule.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * binfmt/binfmt_dumpmodule.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "binfmt_internal.h" + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_BINFMT) && !defined(CONFIG_BINFMT_DISABLE) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/*********************************************************************** + * Public Functions + ***********************************************************************/ + +/*********************************************************************** + * Name: load_module + * + * Description: + * Load a module into memory and prep it for execution. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ***********************************************************************/ + +int dump_module(FAR const struct binary_s *bin) +{ + if (bin) + { + bdbg("Module:\n"); + bdbg(" filename: %s\n", bin->filename); + bdbg(" argv: %p\n", bin->argv); + bdbg(" entrypt: %p\n", bin->entrypt); + bdbg(" ispace: %p size=%d\n", bin->ispace, bin->isize); + bdbg(" dspace: %p\n", bin->dspace); + bdbg(" stacksize: %d\n", bin->stacksize); + } + return OK; +} +#endif + + diff --git a/nuttx/binfmt/binfmt_exec.c b/nuttx/binfmt/binfmt_exec.c new file mode 100644 index 0000000000..cefd3aa5c7 --- /dev/null +++ b/nuttx/binfmt/binfmt_exec.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * binfmt/binfmt_exec.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "binfmt_internal.h" + +#ifndef CONFIG_BINFMT_DISABLE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: exec + * + * Description: + * This is a convenience function that wraps load_ and exec_module into + * one call. + * + * Input Parameter: + * filename - Fulll path to the binary to be loaded + * argv - Argument list + * exports - Table of exported symbols + * nexports - The number of symbols in exports + * + * Returned Value: + * This is an end-user function, so it follows the normal convention: + * Returns the PID of the exec'ed module. On failure, it.returns + * -1 (ERROR) and sets errno appropriately. + * + ****************************************************************************/ + +int exec(FAR const char *filename, FAR const char **argv, + FAR const struct symtab_s *exports, int nexports) +{ + struct binary_s bin; + int ret; + + memset(&bin, 0, sizeof(struct binary_s)); + bin.filename = filename; + bin.exports = exports; + bin.nexports = nexports; + + ret = load_module(&bin); + if (ret < 0) + { + bdbg("ERROR: Failed to load program '%s'\n", filename); + return ERROR; + } + + ret = exec_module(&bin, 50); + if (ret < 0) + { + bdbg("ERROR: Failed to execute program '%s'\n", filename); + unload_module(&bin); + return ERROR; + } + + return ret; +} + +#endif /* CONFIG_BINFMT_DISABLE */ + diff --git a/nuttx/binfmt/binfmt_execmodule.c b/nuttx/binfmt/binfmt_execmodule.c new file mode 100644 index 0000000000..1965f6fa0b --- /dev/null +++ b/nuttx/binfmt/binfmt_execmodule.c @@ -0,0 +1,190 @@ +/**************************************************************************** + * binfmt/binfmt_execmodule.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" +#include "binfmt_internal.h" + +#ifndef CONFIG_BINFMT_DISABLE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: exec_module + * + * Description: + * Execute a module that has been loaded into memory by load_module(). + * + * Returned Value: + * This is an end-user function, so it follows the normal convention: + * Returns the PID of the exec'ed module. On failure, it.returns + * -1 (ERROR) and sets errno appropriately. + * + ****************************************************************************/ + +int exec_module(FAR const struct binary_s *bin, int priority) +{ + FAR _TCB *tcb; +#ifndef CONFIG_CUSTOM_STACK + FAR uint32_t *stack; +#endif + pid_t pid; + int err; + int ret; + + /* Sanity checking */ + +#ifdef CONFIG_DEBUG + if (!bin || !bin->ispace || !bin->entrypt || bin->stacksize <= 0) + { + err = EINVAL; + goto errout; + } +#endif + + bdbg("Executing %s\n", bin->filename); + + /* Allocate a TCB for the new task. */ + + tcb = (FAR _TCB*)zalloc(sizeof(_TCB)); + if (!tcb) + { + err = ENOMEM; + goto errout; + } + + /* Allocate the stack for the new task */ + +#ifndef CONFIG_CUSTOM_STACK + stack = (FAR uint32_t*)malloc(bin->stacksize); + if (!tcb) + { + err = ENOMEM; + goto errout_with_tcb; + } + + /* Initialize the task */ + + ret = task_init(tcb, bin->filename, priority, stack, bin->stacksize, bin->entrypt, bin->argv); +#else + /* Initialize the task */ + + ret = task_init(tcb, bin->filename, priority, stack, bin->entrypt, bin->argv); +#endif + if (ret < 0) + { + err = errno; + bdbg("task_init() failed: %d\n", err); + goto errout_with_stack; + } + + /* Add the DSpace address as the PIC base address */ + +#ifdef CONFIG_PIC + tcb->dspace = bin->dspace; + + /* Re-initialize the task's initial state to account for the new PIC base */ + + up_initial_state(tcb); +#endif + + /* Get the assigned pid before we start the task */ + + pid = tcb->pid; + + /* Then activate the task at the provided priority */ + + ret = task_activate(tcb); + if (ret < 0) + { + err = errno; + bdbg("task_activate() failed: %d\n", err); + goto errout_with_stack; + } + return (int)pid; + +errout_with_stack: +#ifndef CONFIG_CUSTOM_STACK + tcb->stack_alloc_ptr = NULL; + sched_releasetcb(tcb); + free(stack); +#else + sched_releasetcb(tcb); +#endif + goto errout; + +errout_with_tcb: + free(tcb); +errout: + errno = err; + bdbg("returning errno: %d\n", err); + return ERROR; +} + +#endif /* CONFIG_BINFMT_DISABLE */ + diff --git a/nuttx/binfmt/binfmt_globals.c b/nuttx/binfmt/binfmt_globals.c new file mode 100644 index 0000000000..0d0b2dbb42 --- /dev/null +++ b/nuttx/binfmt/binfmt_globals.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * binfmt/binfmt_globals.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#ifndef CONFIG_BINFMT_DISABLE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* This is a list of registered handlers for different binary formats. This + * list should only be accessed by normal user programs. It should be sufficient + * protection to simply disable pre-emption when accessing this list. + */ + +FAR struct binfmt_s *g_binfmts; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* CONFIG_BINFMT_DISABLE */ + + diff --git a/nuttx/binfmt/binfmt_internal.h b/nuttx/binfmt/binfmt_internal.h new file mode 100644 index 0000000000..22fadcd211 --- /dev/null +++ b/nuttx/binfmt/binfmt_internal.h @@ -0,0 +1,88 @@ +/**************************************************************************** + * binfmt/binfmt_internal.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __BINFMT_BINFMT_INTERNAL_H +#define __BINFMT_BINFMT_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* This is a list of registered handlers for different binary formats. This + * list should only be accessed by normal user programs. It should be sufficient + * protection to simply disable pre-emption when accessing this list. + */ + +EXTERN FAR struct binfmt_s *g_binfmts; + +/*********************************************************************** + * Public Function Prototypes + ***********************************************************************/ + +/* Dump the contents of strtuc binary_s */ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_BINFMT) +EXTERN int dump_module(FAR const struct binary_s *bin); +#else +# define dump_module(bin) +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __BINFMT_BINFMT_INTERNAL_H */ + diff --git a/nuttx/binfmt/binfmt_loadmodule.c b/nuttx/binfmt/binfmt_loadmodule.c new file mode 100644 index 0000000000..d4ef7cde27 --- /dev/null +++ b/nuttx/binfmt/binfmt_loadmodule.c @@ -0,0 +1,138 @@ +/**************************************************************************** + * binfmt/binfmt_loadmodule.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "binfmt_internal.h" + +#ifndef CONFIG_BINFMT_DISABLE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: load_module + * + * Description: + * Load a module into memory, bind it to an exported symbol take, and + * prep the module for execution. + * + * Returned Value: + * This is an end-user function, so it follows the normal convention: + * Returns 0 (OK) on success. On failure, it returns -1 (ERROR) with + * errno set appropriately. + * + ****************************************************************************/ + +int load_module(FAR struct binary_s *bin) +{ + FAR struct binfmt_s *binfmt; + int ret = -ENOENT; + +#ifdef CONFIG_DEBUG + if (bin && bin->filename) +#endif + { + bdbg("Loading %s\n", bin->filename); + + /* Disabling pre-emption should be sufficient protection while + * accessing the list of registered binary format handlers. + */ + + sched_lock(); + + /* Traverse the list of registered binary format handlers. Stop + * when either (1) a handler recognized and loads the format, or + * (2) no handler recognizes the format. + */ + + for (binfmt = g_binfmts; binfmt; binfmt = binfmt->next) + { + /* Use this handler to try to load the format */ + + ret = binfmt->load(bin); + if (ret == OK) + { + /* Successfully loaded -- break out with ret == 0 */ + + bvdbg("Successfully loaded module %s\n", bin->filename); + dump_module(bin); + break; + } + } + + sched_unlock(); + } + + /* This is an end-user function. Return failures via errno */ + + if (ret < 0) + { + bdbg("Returning errno %d\n", -ret); + errno = -ret; + return ERROR; + } + return OK; +} + +#endif /* CONFIG_BINFMT_DISABLE */ + diff --git a/nuttx/binfmt/binfmt_register.c b/nuttx/binfmt/binfmt_register.c new file mode 100644 index 0000000000..e41c7a0d98 --- /dev/null +++ b/nuttx/binfmt/binfmt_register.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * binfmt/binfmt_register.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "binfmt_internal.h" + +#ifndef CONFIG_BINFMT_DISABLE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: register_binfmt + * + * Description: + * Register a loader for a binary format + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int register_binfmt(FAR struct binfmt_s *binfmt) +{ + if (binfmt) + { + /* Add the new binary format handler to the head of the list of + * handlers + */ + + sched_lock(); + binfmt->next = g_binfmts; + g_binfmts = binfmt; + sched_unlock(); + return OK; + } + return -EINVAL; +} + +#endif /* CONFIG_BINFMT_DISABLE */ + diff --git a/nuttx/binfmt/binfmt_unloadmodule.c b/nuttx/binfmt/binfmt_unloadmodule.c new file mode 100644 index 0000000000..c6fa90c396 --- /dev/null +++ b/nuttx/binfmt/binfmt_unloadmodule.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * binfmt/binfmt_loadmodule.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "binfmt_internal.h" + +#ifndef CONFIG_BINFMT_DISABLE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: unload_module + * + * Description: + * Unload a (non-executing) module from memory. If the module has + * been started (via exec_module), calling this will be fatal. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int unload_module(FAR const struct binary_s *bin) +{ + if (bin) + { + if (bin->ispace) + { + bvdbg("Unmapping ISpace: %p\n", bin->ispace); + munmap(bin->ispace, bin->isize); + } + + if (bin->dspace) + { + bvdbg("Freeing DSpace: %p\n", bin->dspace); + free(bin->dspace); + } + } + return OK; +} + +#endif /* CONFIG_BINFMT_DISABLE */ + diff --git a/nuttx/binfmt/binfmt_unregister.c b/nuttx/binfmt/binfmt_unregister.c new file mode 100644 index 0000000000..1b50b2c582 --- /dev/null +++ b/nuttx/binfmt/binfmt_unregister.c @@ -0,0 +1,138 @@ +/**************************************************************************** + * binfmt/binfmt_unregister.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "binfmt_internal.h" + +#ifndef CONFIG_BINFMT_DISABLE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: unregister_binfmt + * + * Description: + * Register a loader for a binary format + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int unregister_binfmt(FAR struct binfmt_s *binfmt) +{ + FAR struct binfmt_s *curr; + FAR struct binfmt_s *prev; + int ret = -EINVAL; + + if (binfmt) + { + /* Disabling pre-emption should be sufficient protection while + * accessing the list of registered binary format handlers. + */ + + sched_lock(); + + /* Search the list of registered binary format handlers for the + * one to be unregistered. + */ + + for (prev = NULL, curr = g_binfmts; + curr && curr != binfmt; + prev = curr, curr = curr->next); + + /* Was it in the list? */ + + if (curr) + { + /* Yes.. was it at the head of the list? */ + + if (!prev) + { + /* Yes.. remove it from the head of the list */ + + g_binfmts = binfmt->next; + } + else + { + /* No.. remove it from the middle/end of the list */ + + prev->next = binfmt->next; + } + + binfmt->next = NULL; + ret = OK; + } + + sched_unlock(); + } + + return ret; +} + +#endif /* CONFIG_BINFMT_DISABLE */ + diff --git a/nuttx/binfmt/libnxflat/Kconfig b/nuttx/binfmt/libnxflat/Kconfig new file mode 100644 index 0000000000..ae2bf31307 --- /dev/null +++ b/nuttx/binfmt/libnxflat/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# diff --git a/nuttx/binfmt/libnxflat/Make.defs b/nuttx/binfmt/libnxflat/Make.defs new file mode 100644 index 0000000000..9e95936519 --- /dev/null +++ b/nuttx/binfmt/libnxflat/Make.defs @@ -0,0 +1,39 @@ +############################################################################ +# nxflat/lib/Make.defs +# +# Copyright (C) 2009 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +LIBNXFLAT_ASRCS = +LIBNXFLAT_CSRCS = libnxflat_init.c libnxflat_uninit.c libnxflat_load.c \ + libnxflat_unload.c libnxflat_verify.c libnxflat_read.c \ + libnxflat_bind.c diff --git a/nuttx/binfmt/libnxflat/gnu-nxflat.ld b/nuttx/binfmt/libnxflat/gnu-nxflat.ld new file mode 100644 index 0000000000..9a59c0ec09 --- /dev/null +++ b/nuttx/binfmt/libnxflat/gnu-nxflat.ld @@ -0,0 +1,172 @@ +/**************************************************************************** + * examples/nxflat/nxflat.ld + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +MEMORY +{ + ISPACE : ORIGIN = 0x0, LENGTH = 2097152 + DSPACE : ORIGIN = 0x0, LENGTH = 2097152 +} + +/**************************************************************************** + * The XFLAT program image is divided into two segments: + * + * (1) ISpace (Instruction Space). This is the segment that contains + * code (.text). Everything in the segment should be fetch-able + * machine PC instructions (jump, branch, call, etc.). + * (2) DSpace (Data Space). This is the segment that contains both + * read-write data (.data, .bss) as well as read-only data (.rodata). + * Everything in this segment should be access-able with machine + * with machine load and store instructions. + ****************************************************************************/ + +SECTIONS +{ + .text 0x00000000 : + { + /* ISpace is located at address 0. Every (unrelocated) ISpace + * address is an offset from the begining of this segment. + */ + + text_start = . ; + + *(.text) + *(.text.*) + *(.gnu.warning) + *(.stub) + *(.glue_7) + *(.glue_7t) + *(.jcr) + + /* C++ support: The .init and .fini sections contain XFLAT- + * specific logic to manage static constructors and destructors. + */ + + *(.gnu.linkonce.t.*) + *(.init) + *(.fini) + + /* This is special code area at the end of the normal + text section. It contains a small lookup table at + the start followed by the code pointed to by entries + in the lookup table. */ + + . = ALIGN (4) ; + PROVIDE(__ctbp = .); + *(.call_table_data) + *(.call_table_text) + + _etext = . ; + + } > ISPACE + + /* DSpace is also located at address 0. Every (unrelocated) DSpace + * address is an offset from the begining of this segment. + */ + + .data 0x00000000 : + { + __data_start = . ; + *(.rodata) + *(.rodata1) + *(.rodata.*) + *(.gnu.linkonce.r*) + *(.data) + *(.data1) + *(.data.*) + *(.gnu.linkonce.d*) + *(.data1) + *(.eh_frame) + *(.gcc_except_table) + + *(.gnu.linkonce.s.*) + *(__libc_atexit) + *(__libc_subinit) + *(__libc_subfreeres) + *(.note.ABI-tag) + + /* C++ support. For each global and static local C++ object, + * GCC creates a small subroutine to construct the object. Pointers + * to these routines (not the routines themselves) are stored as + * simple, linear arrays in the .ctors section of the object file. + * Similarly, pointers to global/static destructor routines are + * stored in .dtors. + */ + + *(.gnu.linkonce.d.*) + + _ctors_start = . ; + *(.ctors) + _ctors_end = . ; + _dtors_start = . ; + *(.dtors) + _dtors_end = . ; + + _edata = . ; + edata = ALIGN( 0x10 ) ; + } > DSPACE + + .bss : + { + __bss_start = _edata ; + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.scommon) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.bss*) + *(.gnu.linkonce.b*) + *(COMMON) + end = ALIGN( 0x10 ) ; + _end = ALIGN( 0x10 ) ; + } > DSPACE + + .got 0 : { *(.got.plt) *(.got) } + .junk 0 : { *(.rel*) *(.rela*) } + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/nuttx/binfmt/libnxflat/libnxflat_bind.c b/nuttx/binfmt/libnxflat/libnxflat_bind.c new file mode 100644 index 0000000000..eb65a7e63a --- /dev/null +++ b/nuttx/binfmt/libnxflat/libnxflat_bind.c @@ -0,0 +1,492 @@ +/**************************************************************************** + * binfmt/libnxflat/libnxflat_bind.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_BINFMT have to be + * defined or CONFIG_NXFLAT_DUMPBUFFER does nothing. + */ + +#if !defined(CONFIG_DEBUG_VERBOSE) || !defined (CONFIG_DEBUG_BINFMT) +# undef CONFIG_NXFLAT_DUMPBUFFER +#endif + +#ifdef CONFIG_NXFLAT_DUMPBUFFER +# define nxflat_dumpbuffer(m,b,n) bvdbgdumpbuffer(m,b,n) +#else +# define nxflat_dumpbuffer(m,b,n) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_bindrel32i + * + * Description: + * Perform the NXFLAT_RELOC_TYPE_REL32I binding: + * + * Meaning: Object file contains a 32-bit offset into I-Space at the offset. + * Fixup: Add mapped I-Space address to the offset. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +static inline int nxflat_bindrel32i(FAR struct nxflat_loadinfo_s *loadinfo, + uint32_t offset) +{ + uint32_t *addr; + + bvdbg("NXFLAT_RELOC_TYPE_REL32I Offset: %08x I-Space: %p\n", + offset, loadinfo->ispace + sizeof(struct nxflat_hdr_s)); + + if (offset < loadinfo->dsize) + { + addr = (uint32_t*)(offset + loadinfo->dspace->region); + bvdbg(" Before: %08x\n", *addr); + *addr += (uint32_t)(loadinfo->ispace + sizeof(struct nxflat_hdr_s)); + bvdbg(" After: %08x\n", *addr); + return OK; + } + else + { + bdbg("Offset: %08 does not lie in D-Space size: %08x\n", + offset, loadinfo->dsize); + return -EINVAL; + } +} + +/**************************************************************************** + * Name: nxflat_bindrel32d + * + * Description: + * Perform the NXFLAT_RELOC_TYPE_REL32D binding: + * + * Meaning: Object file contains a 32-bit offset into D-Space at the offset. + * Fixup: Add allocated D-Space address to the offset. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +static inline int nxflat_bindrel32d(FAR struct nxflat_loadinfo_s *loadinfo, + uint32_t offset) +{ + uint32_t *addr; + + bvdbg("NXFLAT_RELOC_TYPE_REL32D Offset: %08x D-Space: %p\n", + offset, loadinfo->dspace->region); + + if (offset < loadinfo->dsize) + { + addr = (uint32_t*)(offset + loadinfo->dspace->region); + bvdbg(" Before: %08x\n", *addr); + *addr += (uint32_t)(loadinfo->dspace->region); + bvdbg(" After: %08x\n", *addr); + return OK; + } + else + { + bdbg("Offset: %08 does not lie in D-Space size: %08x\n", + offset, loadinfo->dsize); + return -EINVAL; + } +} + +/**************************************************************************** + * Name: nxflat_bindrel32id + * + * Description: + * Perform the NXFLAT_RELOC_TYPE_REL32ID binding: + * + * Meaning: Object file contains a 32-bit offset into I-Space at the offset + * that will unfortunately be references relative to the GOT + * Fixup: Add allocated the mapped I-Space address MINUS the allocated + * D-Space address to the offset. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +#ifdef NXFLAT_RELOC_TYPE_REL32ID +static inline int nxflat_bindrel32id(FAR struct nxflat_loadinfo_s *loadinfo, + uint32_t offset) +{ + uint32_t *addr; + + bvdbg("NXFLAT_RELOC_TYPE_REL32D Offset: %08x D-Space: %p\n", + offset, loadinfo->dspace->region); + + if (offset < loadinfo->dsize) + { + addr = (uint32_t*)(offset + loadinfo->dspace->region); + bvdbg(" Before: %08x\n", *addr); + *addr += ((uint32_t)loadinfo->ispace - (uint32_t)(loadinfo->dspace->region)); + bvdbg(" After: %08x\n", *addr); + return OK; + } + else + { + bdbg("Offset: %08 does not lie in D-Space size: %08x\n", + offset, loadinfo->dsize); + return -EINVAL; + } +} +#endif + +/**************************************************************************** + * Name: nxflat_gotrelocs + * + * Description: + * Bind all of the GOT relocations in the loaded module described by + * 'loadinfo' + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +static inline int nxflat_gotrelocs(FAR struct nxflat_loadinfo_s *loadinfo) +{ + FAR struct nxflat_reloc_s *relocs; + FAR struct nxflat_reloc_s reloc; + FAR struct nxflat_hdr_s *hdr; + uint32_t offset; + uint16_t nrelocs; + int ret; + int result; + int i; + + /* The NXFLAT header is the first thing at the beginning of the ISpace. */ + + hdr = (FAR struct nxflat_hdr_s*)loadinfo->ispace; + + /* From this, we can get the list of relocation entries. */ + + /* From this, we can get the offset to the list of relocation entries */ + + offset = ntohl(hdr->h_relocstart); + nrelocs = ntohs(hdr->h_reloccount); + bvdbg("offset: %08lx nrelocs: %d\n", (long)offset, nrelocs); + + /* The value of the relocation list that we get from the header is a + * file offset. We will have to convert this to an offset into the + * DSpace segment to get the pointer to the beginning of the relocation + * list. + */ + + DEBUGASSERT(offset >= loadinfo->isize); + DEBUGASSERT(offset + nrelocs * sizeof(struct nxflat_reloc_s) + <= (loadinfo->isize + loadinfo->dsize)); + + relocs = (FAR struct nxflat_reloc_s*) + (offset - loadinfo->isize + loadinfo->dspace->region); + bvdbg("isize: %08lx dpsace: %p relocs: %p\n", + (long)loadinfo->isize, loadinfo->dspace->region, relocs); + + /* Now, traverse the relocation list of and bind each GOT relocation. */ + + ret = OK; /* Assume success */ + for (i = 0; i < nrelocs; i++) + { + /* Handle the relocation by the relocation type */ + + reloc = *relocs++; + result = OK; + switch (NXFLAT_RELOC_TYPE(reloc.r_info)) + { + + /* NXFLAT_RELOC_TYPE_REL32I Meaning: Object file contains a 32-bit offset + * into I-Space at the offset. + * Fixup: Add mapped I-Space address to the offset. + */ + + case NXFLAT_RELOC_TYPE_REL32I: + { + result = nxflat_bindrel32i(loadinfo, NXFLAT_RELOC_OFFSET(reloc.r_info)); + } + break; + + /* NXFLAT_RELOC_TYPE_REL32D Meaning: Object file contains a 32-bit offset + * into D-Space at the offset. + * Fixup: Add allocated D-Space address to the + * offset. + */ + + case NXFLAT_RELOC_TYPE_REL32D: + { + result = nxflat_bindrel32d(loadinfo, NXFLAT_RELOC_OFFSET(reloc.r_info)); + } + break; + + /* NXFLAT_RELOC_TYPE_REL32ID Meaning: Object file contains a 32-bit offset + * into I-Space at the offset that will + * unfortunately be references relative + * to the GOT + * Fixup: Add allocated the mapped I-Space + * address MINUS the allocated D-Space + * address to the offset. + */ + +#ifdef NXFLAT_RELOC_TYPE_REL32ID + case NXFLAT_RELOC_TYPE_REL32ID: + { + result = nxflat_bindrel32id(loadinfo, NXFLAT_RELOC_OFFSET(reloc.r_info)); + } + break; +#endif + + default: + { + bdbg("ERROR: Unrecognized relocation type: %d\n", NXFLAT_RELOC_TYPE(reloc.r_info)); + result = -EINVAL; + } + break; + } + + /* Check for failures */ + + if (result < 0 && ret == OK) + { + ret = result; + } + } + + /* Dump the relocation got */ + +#ifdef CONFIG_NXFLAT_DUMPBUFFER + if (ret == OK && nrelocs > 0) + { + relocs = (FAR struct nxflat_reloc_s*)(offset - loadinfo->isize + loadinfo->dspace->region); + nxflat_dumpbuffer("GOT", (FAR const uint8_t*)relocs, nrelocs * sizeof(struct nxflat_reloc_s)); + } +#endif + return ret; +} + +/**************************************************************************** + * Name: nxflat_bindimports + * + * Description: + * Bind the imported symbol names in the loaded module described by + * 'loadinfo' using the exported symbol values provided by 'symtab' + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +static inline int nxflat_bindimports(FAR struct nxflat_loadinfo_s *loadinfo, + FAR const struct symtab_s *exports, + int nexports) +{ + FAR struct nxflat_import_s *imports; + FAR struct nxflat_hdr_s *hdr; + FAR const struct symtab_s *symbol; + + char *symname; + uint32_t offset; + uint16_t nimports; + int i; + + /* The NXFLAT header is the first thing at the beginning of the ISpace. */ + + hdr = (FAR struct nxflat_hdr_s*)loadinfo->ispace; + + /* From this, we can get the offset to the list of symbols imported by + * this module and the number of symbols imported by this module. + */ + + offset = ntohl(hdr->h_importsymbols); + nimports = ntohs(hdr->h_importcount); + bvdbg("Imports offset: %08x nimports: %d\n", offset, nimports); + + /* Verify that this module requires imported symbols */ + + if (offset != 0 && nimports > 0) + { + /* It does.. make sure that exported symbols are provided */ + + DEBUGASSERT(exports && nexports > 0); + + /* If non-zero, the value of the imported symbol list that we get + * from the header is a file offset. We will have to convert this + * to an offset into the DSpace segment to get the pointer to the + * beginning of the imported symbol list. + */ + + DEBUGASSERT(offset >= loadinfo->isize && + offset < loadinfo->isize + loadinfo->dsize); + + imports = (struct nxflat_import_s*) + (offset - loadinfo->isize + loadinfo->dspace->region); + + /* Now, traverse the list of imported symbols and attempt to bind + * each symbol to the value exported by from the exported symbol + * table. + */ + + for (i = 0; i < nimports; i++) + { + bvdbg("Import[%d] (%08p) offset: %08x func: %08x\n", + i, &imports[i], imports[i].i_funcname, imports[i].i_funcaddress); + + /* Get a pointer to the imported symbol name. The name itself + * lies in the TEXT segment. But the reference to the name + * lies in DATA segment. Therefore, the name reference should + * have been relocated when the module was loaded. + */ + + offset = imports[i].i_funcname; + DEBUGASSERT(offset < loadinfo->isize); + + symname = (char*)(offset + loadinfo->ispace + sizeof(struct nxflat_hdr_s)); + + /* Find the exported symbol value for this this symbol name. */ + +#ifdef CONFIG_SYMTAB_ORDEREDBYNAME + symbol = symtab_findorderedbyname(exports, symname, nexports); +#else + symbol = symtab_findbyname(exports, symname, nexports); +#endif + if (!symbol) + { + bdbg("Exported symbol \"%s\" not found\n", symname); + return -ENOENT; + } + + /* And put this into the module's import structure. */ + + imports[i].i_funcaddress = (uint32_t)symbol->sym_value; + + bvdbg("Bound import[%d] (%08p) to export '%s' (%08x)\n", + i, &imports[i], symname, imports[i].i_funcaddress); + } + } + + /* Dump the relocation import table */ + +#ifdef CONFIG_NXFLAT_DUMPBUFFER + if (nimports > 0) + { + nxflat_dumpbuffer("Imports", (FAR const uint8_t*)imports, nimports * sizeof(struct nxflat_import_s)); + } +#endif + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_bind + * + * Description: + * Bind the imported symbol names in the loaded module described by + * 'loadinfo' using the exported symbol values provided by 'symtab'. + * After binding the module, clear the BSS region (which held the relocation + * data) in preparation for execution. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int nxflat_bind(FAR struct nxflat_loadinfo_s *loadinfo, + FAR const struct symtab_s *exports, int nexports) +{ + /* Bind the imported symbol, absolute relocations separately. This is done + * before the standard relocations because that logic may modify the + * import list (for the better hopefully, but we don't want to depend on it). + */ + + int ret = nxflat_bindimports(loadinfo, exports, nexports); + if (ret == OK) + { + /* Then bind all GOT relocations */ + + ret = nxflat_gotrelocs(loadinfo); + if (ret == OK) + { + /* Zero the BSS area, trashing the relocations that lived in that + * space in the loaded file. + */ + + memset((void*)(loadinfo->dspace->region + loadinfo->datasize), + 0, loadinfo->bsssize); + } + } + return ret; +} + diff --git a/nuttx/binfmt/libnxflat/libnxflat_init.c b/nuttx/binfmt/libnxflat/libnxflat_init.c new file mode 100644 index 0000000000..45f016e271 --- /dev/null +++ b/nuttx/binfmt/libnxflat/libnxflat_init.c @@ -0,0 +1,188 @@ +/**************************************************************************** + * binfmt/libnxflat/libnxflat_init.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_BINFMT have to be + * defined or CONFIG_NXFLAT_DUMPBUFFER does nothing. + */ + +#if !defined(CONFIG_DEBUG_VERBOSE) || !defined (CONFIG_DEBUG_BINFMT) +# undef CONFIG_NXFLAT_DUMPBUFFER +#endif + +#ifdef CONFIG_NXFLAT_DUMPBUFFER +# define nxflat_dumpbuffer(m,b,n) bvdbgdumpbuffer(m,b,n) +#else +# define nxflat_dumpbuffer(m,b,n) +#endif + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_init + * + * Description: + * This function is called to configure the library to process an NXFLAT + * program binary. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int nxflat_init(const char *filename, struct nxflat_loadinfo_s *loadinfo) +{ + uint32_t datastart; + uint32_t dataend; + uint32_t bssstart; + uint32_t bssend; + int ret; + + bvdbg("filename: %s loadinfo: %p\n", filename, loadinfo); + + /* Clear the load info structure */ + + memset(loadinfo, 0, sizeof(struct nxflat_loadinfo_s)); + + /* Open the binary file */ + + loadinfo->filfd = open(filename, O_RDONLY); + if (loadinfo->filfd < 0) + { + bdbg("Failed to open NXFLAT binary %s: %d\n", filename, ret); + return -errno; + } + + /* Read the NXFLAT header from offset 0 */ + + ret = nxflat_read(loadinfo, (char*)&loadinfo->header, + sizeof(struct nxflat_hdr_s), 0); + if (ret < 0) + { + bdbg("Failed to read NXFLAT header: %d\n", ret); + return ret; + } + nxflat_dumpbuffer("NXFLAT header", (FAR const uint8_t*)&loadinfo->header, + sizeof(struct nxflat_hdr_s)); + + /* Verify the NXFLAT header */ + + if (nxflat_verifyheader(&loadinfo->header) != 0) + { + /* This is not an error because we will be called to attempt loading + * EVERY binary. Returning -ENOEXEC simply informs the system that + * the file is not an NXFLAT file. Besides, if there is something worth + * complaining about, nnxflat_verifyheader() has already + * done so. + */ + + bdbg("Bad NXFLAT header\n"); + return -ENOEXEC; + } + + /* Save all of the input values in the loadinfo structure + * and extract some additional information from the xflat + * header. Note that the information in the xflat header is in + * network order. + */ + + datastart = ntohl(loadinfo->header.h_datastart); + dataend = ntohl(loadinfo->header.h_dataend); + bssstart = dataend; + bssend = ntohl(loadinfo->header.h_bssend); + + /* And put this information into the loadinfo structure as well. + * + * Note that: + * + * isize = the address range from 0 up to datastart. + * datasize = the address range from datastart up to dataend + * bsssize = the address range from dataend up to bssend. + */ + + loadinfo->entryoffs = ntohl(loadinfo->header.h_entry); + loadinfo->isize = datastart; + + loadinfo->datasize = dataend - datastart; + loadinfo->bsssize = bssend - dataend; + loadinfo->stacksize = ntohl(loadinfo->header.h_stacksize); + + /* This is the initial dspace size. We'll re-calculate this later + * after the memory has been allocated. + */ + + loadinfo->dsize = bssend - datastart; + + /* Get the offset to the start of the relocations (we'll relocate + * this later). + */ + + loadinfo->relocstart = ntohl(loadinfo->header.h_relocstart); + loadinfo->reloccount = ntohs(loadinfo->header.h_reloccount); + + return 0; +} + diff --git a/nuttx/binfmt/libnxflat/libnxflat_load.c b/nuttx/binfmt/libnxflat/libnxflat_load.c new file mode 100644 index 0000000000..25be056212 --- /dev/null +++ b/nuttx/binfmt/libnxflat/libnxflat_load.c @@ -0,0 +1,208 @@ +/**************************************************************************** + * binfmt/libnxflat/libnxflat_load.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#ifndef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_BINFMT) +static const char g_relocrel32i[] = "RELOC_REL32I"; +static const char g_relocrel32d[] = "RELOC_REL32D"; +static const char g_relocabs32[] = "RELOC_AB32"; +static const char g_undefined[] = "UNDEFINED"; + +static const char *g_reloctype[] = +{ + g_relocrel32i, + g_relocrel32d, + g_relocabs32, + g_undefined +}; +# define RELONAME(rl) g_reloctype[NXFLAT_RELOC_TYPE(rl)] +#else +# define RELONAME(rl) "(no name)" +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_load + * + * Description: + * Loads the binary specified by nxflat_init into memory, mapping + * the I-space executable regions, allocating the D-Space region, + * and inializing the data segment (relocation information is + * temporarily loaded into the BSS region. BSS will be cleared + * by nxflat_bind() after the relocation data has been processed). + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int nxflat_load(struct nxflat_loadinfo_s *loadinfo) +{ + off_t doffset; /* Offset to .data in the NXFLAT file */ + uint32_t dreadsize; /* Total number of bytes of .data to be read */ + uint32_t relocsize; /* Memory needed to hold relocations */ + uint32_t extrasize; /* MAX(BSS size, relocsize) */ + int ret = OK; + + /* Calculate the extra space we need to allocate. This extra space will be + * the size of the BSS section. This extra space will also be used + * temporarily to hold relocation information. So the allocated size of this + * region will either be the size of .data + size of.bss section OR, the + * size of .data + the relocation entries, whichever is larger + * + * This is the amount of memory that we have to have to hold the + * relocations. + */ + + relocsize = loadinfo->reloccount * sizeof(struct nxflat_reloc_s); + + /* In the file, the relocations should lie at the same offset as BSS. + * The additional amount that we allocate have to be either (1) the + * BSS size, or (2) the size of the relocation records, whicher is + * larger. + */ + + extrasize = MAX(loadinfo->bsssize, relocsize); + + /* Use this additional amount to adjust the total size of the dspace + * region. + */ + + loadinfo->dsize = loadinfo->datasize + extrasize; + + /* The number of bytes of data that we have to read from the file is + * the data size plus the size of the relocation table. + */ + + dreadsize = loadinfo->datasize + relocsize; + + /* We'll need this a few times. */ + + doffset = loadinfo->isize; + + /* We will make two mmap calls create an address space for the executable. + * We will attempt to map the file to get the ISpace address space and + * to allocate RAM to get the DSpace address space. If the filesystem does + * not support file mapping, the map() implementation should do the + * right thing. + */ + + /* The following call will give as a pointer to the mapped file ISpace. + * This may be in ROM, RAM, Flash, ... We don't really care where the memory + * resides as long as it is fully initialized and ready to execute. + */ + + loadinfo->ispace = (uint32_t)mmap(NULL, loadinfo->isize, PROT_READ, + MAP_SHARED|MAP_FILE, loadinfo->filfd, 0); + if (loadinfo->ispace == (uint32_t)MAP_FAILED) + { + bdbg("Failed to map NXFLAT ISpace: %d\n", errno); + return -errno; + } + + bvdbg("Mapped ISpace (%d bytes) at %08x\n", loadinfo->isize, loadinfo->ispace); + + /* The following call will give a pointer to the allocated but + * uninitialized ISpace memory. + */ + + loadinfo->dspace = (struct dspace_s *)malloc(SIZEOF_DSPACE_S(loadinfo->dsize)); + if (loadinfo->dspace == 0) + { + bdbg("Failed to allocate DSpace\n"); + ret = -ENOMEM; + goto errout; + } + loadinfo->dspace->crefs = 1; + + bvdbg("Allocated DSpace (%d bytes) at %p\n", loadinfo->dsize, loadinfo->dspace->region); + + /* Now, read the data into allocated DSpace at doffset into the + * allocated DSpace memory. + */ + + ret = nxflat_read(loadinfo, (char*)loadinfo->dspace->region, dreadsize, doffset); + if (ret < 0) + { + bdbg("Failed to read .data section: %d\n", ret); + goto errout; + } + + bvdbg("TEXT: %08x Entry point offset: %08x Data offset: %08x\n", + loadinfo->ispace, loadinfo->entryoffs, doffset); + + return OK; + +errout: + (void)nxflat_unload(loadinfo); + return ret; +} + diff --git a/nuttx/binfmt/libnxflat/libnxflat_read.c b/nuttx/binfmt/libnxflat/libnxflat_read.c new file mode 100644 index 0000000000..8f1650e873 --- /dev/null +++ b/nuttx/binfmt/libnxflat/libnxflat_read.c @@ -0,0 +1,165 @@ +/**************************************************************************** + * binfmt/libnxflat/libnxflat_read.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#undef NXFLAT_DUMP_READDATA /* Define to dump all file data read */ +#define DUMPER lib_rawprintf /* If NXFLAT_DUMP_READDATA is defined, this + * is the API used to dump data */ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_dumpreaddata + ****************************************************************************/ + +#if defined(NXFLAT_DUMP_READDATA) +static inline void nxflat_dumpreaddata(char *buffer, int buflen) +{ + uint32_t *buf32 = (uint32_t*)buffer; + int i; + int j; + + for (i = 0; i < buflen; i += 32) + { + DUMPER("%04x:", i); + for (j = 0; j < 32; j += sizeof(uint32_t)) + { + DUMPER(" %08x", *buf32++); + } + DUMPER("\n"); + } +} +#else +# define nxflat_dumpreaddata(b,n) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_read + * + * Description: + * Read 'readsize' bytes from the object file at 'offset' + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int nxflat_read(struct nxflat_loadinfo_s *loadinfo, char *buffer, int readsize, int offset) +{ + ssize_t nbytes; /* Number of bytes read */ + off_t rpos; /* Position returned by lseek */ + char *bufptr; /* Next buffer location to read into */ + int bytesleft; /* Number of bytes of .data left to read */ + int bytesread; /* Total number of bytes read */ + + bvdbg("Read %d bytes from offset %d\n", readsize, offset); + + /* Seek to the position in the object file where the initialized + * data is saved. + */ + + bytesread = 0; + bufptr = buffer; + bytesleft = readsize; + do + { + rpos = lseek(loadinfo->filfd, offset, SEEK_SET); + if (rpos != offset) + { + bdbg("Failed to seek to position %d: %d\n", offset, errno); + return -errno; + } + + /* Read the file data at offset into the user buffer */ + + nbytes = read(loadinfo->filfd, bufptr, bytesleft); + if (nbytes < 0) + { + if (errno != EINTR) + { + bdbg("Read of .data failed: %d\n", errno); + return -errno; + } + } + else if (nbytes == 0) + { + bdbg("Unexpected end of file\n"); + return -ENODATA; + } + else + { + bytesread += nbytes; + bytesleft -= nbytes; + bufptr += nbytes; + offset += nbytes; + } + } + while (bytesread < readsize); + + nxflat_dumpreaddata(buffer, readsize); + return OK; +} + diff --git a/nuttx/binfmt/libnxflat/libnxflat_uninit.c b/nuttx/binfmt/libnxflat/libnxflat_uninit.c new file mode 100644 index 0000000000..72be6c7aed --- /dev/null +++ b/nuttx/binfmt/libnxflat/libnxflat_uninit.c @@ -0,0 +1,88 @@ +/**************************************************************************** + * binfmt/libnxflat/libnxflat_uninit.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_swap32 + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_uninit + * + * Description: + * Releases any resources committed by nxflat_init(). This essentially + * undoes the actions of nxflat_init. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int nxflat_uninit(struct nxflat_loadinfo_s *loadinfo) +{ + if (loadinfo->filfd >= 0) + { + close(loadinfo->filfd); + } + return OK; +} + diff --git a/nuttx/binfmt/libnxflat/libnxflat_unload.c b/nuttx/binfmt/libnxflat/libnxflat_unload.c new file mode 100644 index 0000000000..7dc3e87a74 --- /dev/null +++ b/nuttx/binfmt/libnxflat/libnxflat_unload.c @@ -0,0 +1,97 @@ +/**************************************************************************** + * binfmt/libnxflat/libnxflat_unload.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_unload + * + * Description: + * This function unloads the object from memory. This essentially + * undoes the actions of nxflat_load. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int nxflat_unload(struct nxflat_loadinfo_s *loadinfo) +{ + /* Reset the contents of the info structure. */ + + /* Release the memory segments */ + + if (loadinfo->ispace) + { + munmap((void*)loadinfo->ispace, loadinfo->isize); + loadinfo->ispace = 0; + } + + if (loadinfo->dspace) + { + free((void*)loadinfo->dspace); + loadinfo->dspace = 0; + } + + return OK; +} + diff --git a/nuttx/binfmt/libnxflat/libnxflat_verify.c b/nuttx/binfmt/libnxflat/libnxflat_verify.c new file mode 100644 index 0000000000..de952774fc --- /dev/null +++ b/nuttx/binfmt/libnxflat/libnxflat_verify.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * binfmt/libnxflat/nxflat_verify.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_verifyheader + * + * Description: + * Given the header from a possible NXFLAT executable, verify that it + * is an NXFLAT executable. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int nxflat_verifyheader(const struct nxflat_hdr_s *header) +{ + if (!header) + { + bdbg("NULL NXFLAT header!"); + return -ENOEXEC; + } + + /* Check the FLT header -- magic number and revision. + * + * If the magic number does not match. Just return + * silently. This is not our binary. + */ + + if (strncmp(header->h_magic, NXFLAT_MAGIC, 4) != 0) + { + bdbg("Unrecognized magic=\"%c%c%c%c\"\n", + header->h_magic[0], header->h_magic[1], + header->h_magic[2], header->h_magic[3]); + return -ENOEXEC; + } + return OK; +} + diff --git a/nuttx/binfmt/nxflat.c b/nuttx/binfmt/nxflat.c new file mode 100644 index 0000000000..99b99249a1 --- /dev/null +++ b/nuttx/binfmt/nxflat.c @@ -0,0 +1,257 @@ +/**************************************************************************** + * binfmt/nxflat.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_NXFLAT + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_BINFMT have to be + * defined or CONFIG_NXFLAT_DUMPBUFFER does nothing. + */ + +#if !defined(CONFIG_DEBUG_VERBOSE) || !defined (CONFIG_DEBUG_BINFMT) +# undef CONFIG_NXFLAT_DUMPBUFFER +#endif + +#ifdef CONFIG_NXFLAT_DUMPBUFFER +# define nxflat_dumpbuffer(m,b,n) bvdbgdumpbuffer(m,b,n) +#else +# define nxflat_dumpbuffer(m,b,n) +#endif + +#ifndef MIN +# define MIN(a,b) (a < b ? a : b) +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int nxflat_loadbinary(struct binary_s *binp); +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_BINFMT) +static void nxflat_dumploadinfo(struct nxflat_loadinfo_s *loadinfo); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct binfmt_s g_nxflatbinfmt = +{ + NULL, /* next */ + nxflat_loadbinary, /* load */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_dumploadinfo + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_BINFMT) +static void nxflat_dumploadinfo(struct nxflat_loadinfo_s *loadinfo) +{ + unsigned long dsize = loadinfo->datasize + loadinfo->bsssize; + + bdbg("LOAD_INFO:\n"); + bdbg(" ISPACE:\n"); + bdbg(" ispace: %08lx\n", loadinfo->ispace); + bdbg(" entryoffs: %08lx\n", loadinfo->entryoffs); + bdbg(" isize: %08lx\n", loadinfo->isize); + + bdbg(" DSPACE:\n"); + bdbg(" dspace: %08lx\n", loadinfo->dspace); + if (loadinfo->dspace != NULL) + { + bdbg(" crefs: %d\n", loadinfo->dspace->crefs); + bdbg(" region: %08lx\n", loadinfo->dspace->region); + } + bdbg(" datasize: %08lx\n", loadinfo->datasize); + bdbg(" bsssize: %08lx\n", loadinfo->bsssize); + bdbg(" (pad): %08lx\n", loadinfo->dsize - dsize); + bdbg(" stacksize: %08lx\n", loadinfo->stacksize); + bdbg(" dsize: %08lx\n", loadinfo->dsize); + + bdbg(" RELOCS:\n"); + bdbg(" relocstart: %08lx\n", loadinfo->relocstart); + bdbg(" reloccount: %d\n", loadinfo->reloccount); + + bdbg(" HANDLES:\n"); + bdbg(" filfd: %d\n", loadinfo->filfd); +} +#else +# define nxflat_dumploadinfo(i) +#endif + +/**************************************************************************** + * Name: nxflat_loadbinary + * + * Description: + * Verify that the file is an NXFLAT binary and, if so, load the NXFLAT + * binary into memory + * + ****************************************************************************/ + +static int nxflat_loadbinary(struct binary_s *binp) +{ + struct nxflat_loadinfo_s loadinfo; /* Contains globals for libnxflat */ + int ret; + + bvdbg("Loading file: %s\n", binp->filename); + + /* Initialize the xflat library to load the program binary. */ + + ret = nxflat_init(binp->filename, &loadinfo); + nxflat_dumploadinfo(&loadinfo); + if (ret != 0) + { + bdbg("Failed to initialize for load of NXFLT program: %d\n", ret); + goto errout; + } + + /* Load the program binary */ + + ret = nxflat_load(&loadinfo); + nxflat_dumploadinfo(&loadinfo); + if (ret != 0) + { + bdbg("Failed to load NXFLT program binary: %d\n", ret); + goto errout_with_init; + } + + /* Bind the program to the exported symbol table */ + + ret = nxflat_bind(&loadinfo, binp->exports, binp->nexports); + if (ret != 0) + { + bdbg("Failed to bind symbols program binary: %d\n", ret); + goto errout_with_load; + } + + /* Return the load information */ + + binp->entrypt = (main_t)(loadinfo.ispace + loadinfo.entryoffs); + binp->ispace = (void*)loadinfo.ispace; + binp->dspace = (void*)loadinfo.dspace; + binp->isize = loadinfo.isize; + binp->stacksize = loadinfo.stacksize; + + nxflat_dumpbuffer("Entry code", (FAR const uint8_t*)binp->entrypt, + MIN(binp->isize - loadinfo.entryoffs,512)); + + nxflat_uninit(&loadinfo); + return OK; + +errout_with_load: + nxflat_unload(&loadinfo); +errout_with_init: + nxflat_uninit(&loadinfo); +errout: + return ret; +} + +/*********************************************************************** + * Public Functions + ***********************************************************************/ + +/*********************************************************************** + * Name: nxflat_initialize + * + * Description: + * NXFLAT support is built unconditionally. However, it order to + * use this binary format, this function must be called during system + * format in order to register the NXFLAT binary format. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ***********************************************************************/ + +int nxflat_initialize(void) +{ + int ret; + + /* Register ourselves as a binfmt loader */ + + bvdbg("Registering NXFLAT\n"); + ret = register_binfmt(&g_nxflatbinfmt); + if (ret != 0) + { + bdbg("Failed to register binfmt: %d\n", ret); + } + return ret; +} + +/**************************************************************************** + * Name: nxflat_uninitialize + * + * Description: + * Unregister the NXFLAT binary loader + * + * Returned Value: + * None + * + ****************************************************************************/ + +void nxflat_uninitialize(void) +{ + unregister_binfmt(&g_nxflatbinfmt); +} + +#endif /* CONFIG_NXFLAT */ + diff --git a/nuttx/binfmt/symtab_findbyname.c b/nuttx/binfmt/symtab_findbyname.c new file mode 100644 index 0000000000..02b2ac22b4 --- /dev/null +++ b/nuttx/binfmt/symtab_findbyname.c @@ -0,0 +1,97 @@ +/**************************************************************************** + * binfmt/symtab_findbyname.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/*********************************************************************** + * Public Functions + ***********************************************************************/ + +/**************************************************************************** + * Name: symtab_findbyname + * + * Description: + * Find the symbol in the symbol table with the matching name. + * This version assumes that table is not ordered with respect to symbol + * name and, hence, access time will be linear with respect to nsyms. + * + * Returned Value: + * A reference to the symbol table entry if an entry with the matching + * name is found; NULL is returned if the entry is not found. + * + ****************************************************************************/ + +FAR const struct symtab_s * +symtab_findbyname(FAR const struct symtab_s *symtab, + FAR const char *name, int nsyms) +{ + DEBUGASSERT(symtab != NULL && name != NULL); + for (; nsyms > 0; symtab++, nsyms--) + { + if (strcmp(name, symtab->sym_name) == 0) + { + return symtab; + } + } + return NULL; +} + diff --git a/nuttx/binfmt/symtab_findbyvalue.c b/nuttx/binfmt/symtab_findbyvalue.c new file mode 100644 index 0000000000..80df746684 --- /dev/null +++ b/nuttx/binfmt/symtab_findbyvalue.c @@ -0,0 +1,121 @@ +/**************************************************************************** + * binfmt/symtab_findbyvalue.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/*********************************************************************** + * Public Functions + ***********************************************************************/ + +/**************************************************************************** + * Name: symtab_findbyvalue + * + * Description: + * Find the symbol in the symbol table whose value closest (but not greater + * than), the provided value. This version assumes that table is not ordered + * with respect to symbol name and, hence, access time will be linear with + * respect to nsyms. + * + * Returned Value: + * A reference to the symbol table entry if an entry with the matching + * name is found; NULL is returned if the entry is not found. + * + ****************************************************************************/ + +FAR const struct symtab_s * +symtab_findbyvalue(FAR const struct symtab_s *symtab, + FAR void *value, int nsyms) +{ + FAR const struct symtab_s *retval = NULL; + + DEBUGASSERT(symtab != NULL); + for (; nsyms > 0; symtab++, nsyms--) + { + /* Look for symbols of lesser or equal value (probably address) to value */ + + if (symtab->sym_value <= value) + { + /* Found one. Is it the largest we have found so far? */ + + if (!retval || symtab->sym_value > retval->sym_value) + { + /* Yes, then it is the new candidate for the symbol whose value + * just below 'value' + */ + + retval = symtab; + + /* If it is exactly equal to the search 'value', then we might as + * well terminate early because we can't do any better than that. + */ + + if (retval->sym_value == value) + { + break; + } + } + } + } + + return retval; +} + diff --git a/nuttx/binfmt/symtab_findorderedbyname.c b/nuttx/binfmt/symtab_findorderedbyname.c new file mode 100644 index 0000000000..82d68bfea4 --- /dev/null +++ b/nuttx/binfmt/symtab_findorderedbyname.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * binfmt/symtab_findorderedbyname.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/*********************************************************************** + * Public Functions + ***********************************************************************/ + +/**************************************************************************** + * Name: symtab_findorderedbyname + * + * Description: + * Find the symbol in the symbol table with the matching name. + * This version assumes that table ordered with respect to symbol name. + * + * This function uses qsort() to implement the search and, hence, is a lot + * larger than symbtab_findbyname(). This function not be used, unless + * the symbol table is large and the performance benefit is worth the + * increased size. + * + * Returned Value: + * A reference to the symbol table entry if an entry with the matching + * name is found; NULL is returned if the entry is not found. + * + ****************************************************************************/ + +FAR const struct symtab_s * +symtab_findorderedbyname(FAR const struct symtab_s *symtab, + FAR const char *name, int nsyms) +{ + int low = 0; + int high = nsyms -1; + int mid; + int cmp; + + /* Loop until the range has been isolated to a single symbol table + * entry that may or may not match the search name. + */ + + DEBUGASSERT(symtab != NULL && name != NULL); + while (low < high) + { + /* Compare the name to the one in the middle. (or just below + * the middle in the case where one is even and one is odd). + */ + + mid = (low + high) >> 1; + cmp = strcmp(name, symtab[mid].sym_name); + if (cmp < 0) + { + /* name < symtab[mid].sym_name */ + + high = mid - 1; + } + else if (cmp > 0) + { + /* name > symtab[mid].sym_name */ + + low = mid + 1; + } + else + { + /* symtab[mid].sym_name == name */ + + return &symtab[mid]; + } + } + + /* low == high... One final check. We might not have actually tested + * the final symtab[] name. + * + * Example: Only the last pass through loop, suppose low = 1, high = 2, + * mid = 1, and symtab[high].sym_name == name. Then we would get here with + * low = 2, high = 2, but symtab[2].sym_name was never tested. + */ + + return strcmp(name, symtab[low].sym_name) == 0 ? &symtab[low] : NULL; +} + diff --git a/nuttx/binfmt/symtab_findorderedbyvalue.c b/nuttx/binfmt/symtab_findorderedbyvalue.c new file mode 100644 index 0000000000..a995595da9 --- /dev/null +++ b/nuttx/binfmt/symtab_findorderedbyvalue.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * binfmt/symtab_findorderedbyvalue.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/*********************************************************************** + * Public Functions + ***********************************************************************/ + +/**************************************************************************** + * Name: symtab_findorderedbyvalue + * + * Description: + * Find the symbol in the symbol table whose value closest (but not greater + * than), the provided value. This version assumes that table is ordered + * with respect to symbol name. + * + * Returned Value: + * A reference to the symbol table entry if an entry with the matching + * name is found; NULL is returned if the entry is not found. + * + ****************************************************************************/ + +FAR const struct symtab_s * +symtab_findorderedbyvalue(FAR const struct symtab_s *symtab, + FAR void *value, int nsyms) +{ + int low = 0; + int high = nsyms -1; + int mid; + + /* Loop until the range has been isolated to a single symbol table + * entry that may or may not match the search name. + */ + + DEBUGASSERT(symtab != NULL); + while (low < high) + { + /* Compare the name to the one in the middle. (or just below + * the middle in the case where one is even and one is odd). + */ + + mid = (low + high) >> 1; + if ( value < symtab[mid].sym_value) + { + high = mid - 1; + } + else if (value > symtab[mid].sym_value) + { + low = mid + 1; + } + else /* if (value == symtab[mid].sym_value) */ + { + return &symtab[mid]; + } + } + + /* low == high... One final check. We might not have actually tested + * the final symtab[] name. + * + * Example: Only the last pass through loop, suppose low = 1, high = 2, + * mid = 1, and symtab[high].sym_name == name. Then we would get here with + * low = 2, high = 2, but symtab[2].sym_name was never tested. + */ + + return value == symtab[low].sym_value ? &symtab[low] : NULL; +} + diff --git a/nuttx/configs/Kconfig b/nuttx/configs/Kconfig new file mode 100644 index 0000000000..2f6595dbdc --- /dev/null +++ b/nuttx/configs/Kconfig @@ -0,0 +1,714 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +choice + prompt "Select target board" + default ARCH_BOARD_CUSTOM + ---help--- + Select the board hosting the architure. You must first select the + exact MCU part number, then the boards supporting that part will + be available for selection. Use ARCH_BOARD_CUSTOM to create a new + board configuration. + +config ARCH_BOARD_AMBER + bool "Amber Web Server" + depends on ARCH_CHIP_ATMEGA128 + ---help--- + This is placeholder for the SoC Robotics Amber Web Server that is based + on the Atmel AVR ATMega128 MCU. There is not much there yet and what is + there is untested due to tool-related issues. + +config ARCH_BOARD_AVR32DEV1 + bool "Atmel AVR32DEV1 board" + depends on ARCH_CHIP_AT32UC3B0256 + ---help--- + This is a port of NuttX to the Atmel AVR32DEV1 board. That board is + based on the Atmel AT32UC3B0256 MCU and uses a specially patched + version of the GNU toolchain: The patches provide support for the + AVR32 family. That patched GNU toolchain is available only from the + Atmel website. STATUS: This port is functional but very basic. There + are configurations for NSH and the OS test. + +config ARCH_BOARD_C5471EVM + bool "Spectrum Digital C5471 evaluation board" + depends on ARCH_CHIP_C5471 + ---help--- + This is a port to the Spectrum Digital C5471 evaluation board. The + TMS320C5471 is a dual core processor from TI with an ARM7TDMI general + purpose processor and a c54 DSP. It is also known as TMS320DA180 or just DA180. + NuttX runs on the ARM core and is built with a GNU arm-elf toolchain*. + This port is complete and verified. + +config ARCH_BOARD_COMPALE88 + bool "Compal e88 phone" + depends on ARCH_CHIP_CALYPSO + ---help--- + These directories contain the board support for compal e88 and e99 phones. + These ports are based on patches contributed by Denis Carikli for both the + compal e99 and e88. The patches were made by Alan Carvalho de Assis and + Denis Carikli using the Stefan Richter's Osmocom-bb patches. + +config ARCH_BOARD_COMPALE99 + bool "Compal e99 phone" + depends on ARCH_CHIP_CALYPSO + ---help--- + These directories contain the board support for compal e88 and e99 phones. + These ports are based on patches contributed by Denis Carikli for both the + compal e99 and e88. The patches were made by Alan Carvalho de Assis and + Denis Carikli using the Stefan Richter's Osmocom-bb patches. + +config ARCH_BOARD_DEMOS92S12NEC64 + bool "Freescale DMO9S12NE64 board" + depends on ARCH_CHIP_MCS92S12NEC64 + ---help--- + Freescale DMO9S12NE64 board based on the MC9S12NE64 hcs12 cpu. This + port uses the m9s12x GCC toolchain. STATUS: (Still) under development; it + is code complete but has not yet been verified. + +config ARCH_BOARD_EA3131 + bool "Embedded Artists EA3131 Development board" + depends on ARCH_CHIP_LPC3131 + ---help--- + Embedded Artists EA3131 Development board. This board is based on the + an NXP LPC3131 MCU. This OS is built with the arm-elf toolchain*. + STATUS: This port is complete and mature. + +config ARCH_BOARD_EA3152 + bool "Embedded Artists EA3152 Development board" + depends on ARCH_CHIP_LPC3152 + ---help--- + Embedded Artists EA3152 Development board. This board is based on the + an NXP LPC3152 MCU. This OS is built with the arm-elf toolchain*. + STATUS: This port is has not be exercised well, but since it is + a simple derivative of the ea3131, it should be fully functional. + +config ARCH_BOARD_EAGLE100 + bool "Micromint Eagle-100 Development board" + depends on ARCH_CHIP_LM3S6918 + ---help--- + Micromint Eagle-100 Development board. This board is based on the + an ARM Cortex-M3 MCU, the Luminary LM3S6918. This OS is built with the + arm-elf toolchain*. STATUS: This port is complete and mature. + +config ARCH_BOARD_EKK_LM3S9B96 + bool "TI/Stellaris EKK-LM3S9B96" + depends on ARCH_CHIP_LM3S9B96 + ---help--- + TI/Stellaris EKK-LM3S9B96 board. This board is based on the + an EKK-LM3S9B96 which is a Cortex-M3. + +config ARCH_BOARD_EZ80F910200KITG + bool "ZiLOG ez80f0910200kitg development kit" + depends on ARCH_CHIP_EZ80F91 + ---help--- + ez80Acclaim! Microcontroller. This port use the ZiLOG ez80f0910200kitg + development kit, eZ80F091 part, and the Zilog ZDS-II Windows command line + tools. The development environment is Cygwin under WinXP. + +config ARCH_BOARD_EZ80F910200ZCO + bool "ZiLOG ez80f0910200zco development kit" + depends on ARCH_CHIP_EZ80F91 + ---help--- + ez80Acclaim! Microcontroller. This port use the Zilog ez80f0910200zco + development kit, eZ80F091 part, and the Zilog ZDS-II Windows command line + tools. The development environment is Cygwin under WinXP. + +config ARCH_BOARD_HYMINI_STM32V + bool "HY-Mini STM32v board" + depends on ARCH_CHIP_STM32F103VCT + ---help--- + A configuration for the HY-Mini STM32v board. This board is based on the + STM32F103VCT chip. + +config ARCH_BOARD_LINCOLN60 + bool "Micromint Lincoln 60 board" + depends on ARCH_CHIP_LPC1769 + ---help--- + Micromint Lincoln 60 board using the NXP LPC1769 MCU. + +config ARCH_BOARD_KWIKSTIK_K40 + bool "FreeScale KwikStik-K40 development board" + depends on ARCH_CHIP_MK40X256VLQ100 + ---help--- + Kinetis K40 Cortex-M4 MCU. This port uses the FreeScale KwikStik-K40 + development board. + +config ARCH_BOARD_LM3S6432S2E + bool "Stellaris RDK-S2E Reference Design Kit" + depends on ARCH_CHIP_LM3S6432 + ---help--- + Stellaris RDK-S2E Reference Design Kit and the MDL-S2E Ethernet to + Serial module. + +config ARCH_BOARD_LM3S6965EK + bool "Stellaris LM3S6965 Evaluation Kit" + depends on ARCH_CHIP_LM3S6965 + ---help--- + Stellaris LM3S6965 Evaluation Kit. This board is based on the + an ARM Cortex-M3 MCU, the Luminary/TI LM3S6965. This OS is built with the + arm-elf toolchain*. STATUS: This port is complete and mature. + +config ARCH_BOARD_LM3S8962EK + bool "Stellaris LMS38962 Evaluation Kit" + depends on ARCH_CHIP_LM3S8962 + ---help--- + Stellaris LMS38962 Evaluation Kit. + +config ARCH_BOARD_LPCXPRESSO + bool "NXP LPCExpresso LPC1768" + depends on ARCH_CHIP_LPC1768 + ---help--- + Embedded Artists base board with NXP LPCExpresso LPC1768. This board + is based on the NXP LPC1768. The Code Red toolchain is used by default. + +config ARCH_BOARD_LPC4330_XPLORER + bool "NXG LPC4330-Xplorer" + depends on ARCH_CHIP_LPC4330FET100 + ---help--- + NXG Technologoies LPC4330 Xplorer board. This board is based on the + LPC4330FET100. The Code Red toolchain is used by default. + +config ARCH_BOARD_M68332EVB + bool "Motoroloa M68332EVB" + depends on ARCH_M68332 + ---help--- + This is a work in progress for the venerable m68322evb board from + Motorola. This OS is also built with the arm-elf toolchain. STATUS: + This port was never completed. + +config ARCH_BOARD_MBED + bool "mbed LCP1768" + depends on ARCH_CHIP_LPC1768 + ---help--- + The configurations in this directory support the mbed board (http://mbed.org) + that features the NXP LPC1768 microcontroller. This OS is also built + with the arm-elf toolchain*. STATUS: Contributed. + +config ARCH_BOARD_MCU123 + bool "mcu123.com LPC2148 Development Board" + depends on ARCH_CHIP_LPC2148 + ---help--- + This port is for the NXP LPC2148 as provided on the mcu123.com + lpc214x development board. This OS is also built with the arm-elf + toolchain*. The port supports serial, timer0, spi, and usb. + +config ARCH_BOARD_MICROPENDOUS + bool "Opendous Micropendous 3 board" + depends on ARCH_CHIP_AT90USB646 || ARCH_CHIP_AT90USB647 || ARCH_CHIP_AT90USB1286 || ARCH_CHIP_AT90USB1287 + ---help--- + This is a port to the Opendous Micropendous 3 board. This board may + be populated with either an AVR AT90USB646, 647, 1286, or 1287 MCU. + Support is configured for the AT90USB647. + +config ARCH_BOARD_MX1ADS + bool "Motorola MX1ADS development board" + depends on ARCH_CHIP_IMX1 + ---help--- + This is a port to the Motorola MX1ADS development board. That board + is based on the Freescale i.MX1 processor. The i.MX1 is an ARM920T. + STATUS: This port is nearly code complete but was never fully + integrated due to tool-related issues. + +config ARCH_BOARD_NE64BADGE + bool "FEG NE64 /PoE Badge board" + depends on ARCH_CHIP_MCS92S12NEC64 + ---help--- + Future Electronics Group NE64 /PoE Badge board based on the + MC9S12NE64 hcs12 cpu. This port uses the m9s12x GCC toolchain. + STATUS: Under development. The port is code-complete but has + not yet been fully tested. + +config ARCH_BOARD_NTOSD_DM320 + bool "Neuros OSD v1.0 Dev Board" + depends on ARCH_CHIP_DM320 + ---help--- + This port uses the Neuros OSD v1.0 Dev Board with a GNU arm-elf + toolchain*: see + + http://wiki.neurostechnology.com/index.php/OSD_1.0_Developer_Home + + There are some differences between the Dev Board and the currently + available commercial v1.0 Boards. See + + http://wiki.neurostechnology.com/index.php/OSD_Developer_Board_v1 + + NuttX operates on the ARM9EJS of this dual core processor. + STATUS: This port is code complete, verified, and included in the + NuttX 0.2.1 release. + +config ARCH_BOARD_NUCLEUS2G + bool "Nucleus 2G board" + depends on ARCH_CHIP_LPC1768 + ---help--- + This port uses the Nucleus 2G board (with Babel CAN board). This board + features an NXP LPC1768 processor. See the 2G website (http://www.2g-eng.com/) + for more information about the Nucleus 2G. + +config ARCH_BOARD_LPC1766STK + bool "Olimex LPC1766-STK board" + depends on ARCH_CHIP_LPC1766 + ---help--- + This port uses the Olimex LPC1766-STK board and a GNU GCC toolchain* under + Linux or Cygwin. STATUS: Complete and mature. + +config ARCH_BOARD_MIRTOO + bool "Mirtoo PIC32 Module from Dimitech" + depends on ARCH_CHIP_PIC32MX250F128D + ---help--- + This is the port to the DTX1-4000L "Mirtoo" module. This module uses MicroChip + PIC32MX250F128D. See http://www.dimitech.com/ for further information. + +config ARCH_BOARD_OLIMEXLPC2378 + bool "Olimex-lpc2378 board" + depends on ARCH_CHIP_LPC2378 + ---help--- + This port uses the Olimex-lpc2378 board and a GNU arm-elf toolchain* under + Linux or Cygwin. STATUS: ostest and NSH configurations available. + This port for the NXP LPC2378 was contributed by Rommel Marcelo. + +config ARCH_BOARD_OLIMEX_STRP711 + bool "Olimex STR-P711 board" + depends on ARCH_CHIP_STR71X + ---help--- + This port uses the Olimex STR-P711 board and a GNU arm-elf toolchain* under + Linux or Cygwin. See the http://www.olimex.com/dev/str-p711.html" for + further information. STATUS: Configurations for the basic OS test and NSH + are complete and verified. + +config ARCH_BOARD_PCBLOGICPIC32MX + bool "PIC32MX board from PCB Logic Design Co" + depends on ARCH_CHIP_PIC32MX460F512L + ---help--- + This is the port of NuttX to the PIC32MX board from PCB Logic Design Co. + This board features the MicroChip PIC32MX460F512L. + The board is a very simple -- little more than a carrier for the PIC32 + MCU plus voltage regulation, debug interface, and an OTG connector. + STATUS: Code complete but testing has been stalled due to tool related problems + (PICkit 2 does not work with the PIC32). + +config ARCH_BOARD_PIC32_STARTERKIT + bool "Microchip PIC32 Ethernet Starter Kit (DM320004)" + depends on ARCH_CHIP_PIC32MX795F512L + ---help--- + This is the port of NuttX to the Microchip PIC32 Ethernet Starter Kit + (DM320004) with the Multimedia Expansion Board (MEB, DM320005). + See www.microchip.com for further information. + +config ARCH_BOARD_PIC32_PIC32MX7MMB + bool "Mikroelektronika PIC32MX7 MMB" + depends on ARCH_CHIP_PIC32MX795F512L + ---help--- + This is the port NuttX to the Mikroelektronika PIC32MX7 Multimedia Board + (MMB). See http://www.mikroe.com/ for further information. + +config ARCH_BOARD_PJRC_87C52 + bool "PJRC 87C52 development system" + depends on ARCH_CHIP_8052 + ---help--- + 8051 Microcontroller. This port uses the PJRC 87C52 development system + and the SDCC toolchain. This port is not quite ready for prime time. + +config ARCH_BOARD_QEMU_I486 + bool "Qemu i486 Mode" + depends on ARCH_QEMU + ---help--- + Port of NuttX to QEMU in i486 mode. This port will also run on real i486 + hardwared (Google the Bifferboard). + +config ARCH_BOARD_RGMP + bool "RGMP" + depends on ARCH_RGMP + ---help--- + RGMP stands for RTOS and GPOS on Multi-Processor. RGMP is a project for + running GPOS and RTOS simultaneously on multi-processor platforms. You can + port your favorite RTOS to RGMP together with an unmodified Linux to form a + hybrid operating system. This makes your application able to use both RTOS + and GPOS features. + + See http://rgmp.sourceforge.net/wiki/index.php/Main_Page for further information + about RGMP. + +config ARCH_BOARD_SAM3UEK + bool "Atmel SAM3U-EK development board" + depends on ARCH_CHIP_AT91SAM3U4E + ---help--- + The port of NuttX to the Atmel SAM3U-EK development board. + +config ARCH_BOARD_SKP16C26 + bool "Renesas SKP16C26 StarterKit" + depends on ARCH_CHIP_M30262F8 + ---help--- + Renesas M16C processor on the Renesas SKP16C26 StarterKit. This port + uses the GNU m32c toolchain. STATUS: The port is complete but untested + due to issues with compiler internal errors. + +config ARCH_BOARD_STM3210E_EVAL + bool "STMicro STM3210E-EVAL development board" + depends on ARCH_CHIP_STM32F103ZET6 + ---help--- + STMicro STM3210E-EVAL development board based on the STMicro STM32F103ZET6 + microcontroller (ARM Cortex-M3). This port uses the GNU Cortex-M3 + toolchain. + +config ARCH_BOARD_STM3220G_EVAL + bool "STMicro STM3220G-EVAL development board" + depends on ARCH_CHIP_STM32F207IG + ---help--- + STMicro STM3220G-EVAL development board based on the STMicro STM32F407IG + microcontroller (ARM Cortex-M3). + +config ARCH_BOARD_STM3240G_EVAL + bool "STMicro STM3240G-EVAL development board" + depends on ARCH_CHIP_STM32F407IG + ---help--- + STMicro STM3240G-EVAL development board based on the STMicro STM32F103ZET6 + microcontroller (ARM Cortex-M4 with FPU). This port uses a GNU Cortex-M4 + toolchain (such as CodeSourcery). + +config ARCH_BOARD_STM32F4_DISCOVERY + bool "STMicro STM32F4-Discovery board" + depends on ARCH_CHIP_STM32F407VG + ---help--- + STMicro STM32F4-Discovery board boased on the STMIcro STM32F407VGT6 MCU. + +config ARCH_BOARD_SUREPIC32MX + bool "Sure PIC32MX boards" + depends on ARCH_CHIP_PIC32MX440F512H + ---help--- + The "Advanced USB Storage Demo Board," Model DB-DP11215, from Sure + Electronics (http://www.sureelectronics.net/). This board features + the MicroChip PIC32MX440F512H. See also + http://www.sureelectronics.net/goods.php?id=1168 for further + information about the Sure DB-DP11215 board. + +config ARCH_BOARD_TEENSY + bool "PJRC Teensy++ 2.0 board" + depends on ARCH_CHIP_AT90USB1286 + ---help--- + This is the port of NuttX to the PJRC Teensy++ 2.0 board. This board is + developed by http://pjrc.com/teensy/. The Teensy++ 2.0 is based + on an Atmel AT90USB1286 MCU. + +config ARCH_BOARD_TWR_K60N512 + bool "FreeScale TWR-K60N512d evelopment board" + depends on ARCH_CHIP_MK60N512VMD100 + ---help--- + Kinetis K60 Cortex-M4 MCU. This port uses the FreeScale TWR-K60N512 + development board. + +config ARCH_BOARD_UBW32 + bool "UBW32 v2.4 board from Sparkfun" + depends on ARCH_CHIP_PIC32MX460F512L + ---help--- + This is the port to the Sparkfun UBW32 board. This port uses the original v2.4 + board which is based on the MicroChip PIC32MX460F512L. See + http://www.sparkfun.com/products/8971. This older version has been replaced + with this board http://www.sparkfun.com/products/9713. See also + http://www.schmalzhaus.com/UBW32/. + +config ARCH_BOARD_US7032EVB1 + bool "Hitachi SH-1/US7032EVB1 board" + depends on ARCH_CHIP_SH7032 + ---help--- + This is a port of the Hitachi SH-1 on the Hitachi SH-1/US7032EVB1 board. + STATUS: Work has just began on this port. + +config ARCH_BOARD_VSN + bool "SOTEL NetClamps VSN sensor network platform" + depends on ARCH_CHIP_STM32F103RET6 + ---help--- + ISOTEL NetClamps VSN V1.2 ready2go sensor network platform based on the + STMicro STM32F103RET6. Contributed by Uros Platise. See + http://isotel.eu/NetClamps/ + +config ARCH_BOARD_XTRS + bool "XTRS TRS80 Model 3 emulation" + depends on ARCH_CHIP_Z80 + ---help--- + TRS80 Model 3. This port uses a vintage computer based on the Z80. + An emulator for this computer is available to run TRS80 programs on a + linux platform (http://www.tim-mann.org/xtrs.html). + +config ARCH_BOARD_Z16F2800100ZCOG + bool "Zilog Z16F2800100ZCOG Development Kit" + depends on ARCH_CHIP_Z16F281 + ---help--- + z16f Microcontroller. This port use the ZiLIG z16f2800100zcog + development kit and the Zilog ZDS-II Windows command line tools. The + development environment is Cygwin under WinXP. + +config ARCH_BOARD_Z80SIM + bool "Z80 Instruction Set Simulator" + depends on ARCH_CHIP_Z80 + ---help--- + z80 Microcontroller. This port uses a Z80 instruction set simulator. + That simulator can be found in the NuttX SVN at + http://nuttx.svn.sourceforge.net/viewvc/nuttx/trunk/misc/sims/z80sim. + This port also uses the SDCC toolchain (http://sdcc.sourceforge.net/") + (verified with version 2.6.0). + +config ARCH_BOARD_Z8ENCORE000ZCO + bool "ZiLOG z8encore000zco Development Kit" + depends on ARCH_CHIP_Z8F6403 + ---help--- + z8Encore! Microcontroller. This port use the ZiLOG z8encore000zco + development kit, Z8F6403 part, and the Zilog ZDS-II Windows command line + tools. The development environment is Cygwin under WinXP. + +config ARCH_BOARD_Z8F64200100KI + bool "ZiLOG Z8F64200100KIT Development Kit" + depends on ARCH_CHIP_Z8F642X + ---help--- + z8Encore! Microcontroller. This port use the Zilog z8f64200100kit + development kit, Z8F6423 part, and the Zilog ZDS-II Windows command line + tools. The development environment is Cygwin under WinXP. + +config ARCH_BOARD_SIM + bool "User mode simulation" + depends on ARCH_SIM + ---help--- + A user-mode port of NuttX to the x86 Linux/Cygwin platform is available. + The purpose of this port is primarily to support OS feature development. + This port does not support interrupts or a real timer (and hence no + round robin scheduler) Otherwise, it is complete. + +config ARCH_BOARD_CUSTOM + bool "Custom development board" + ---help--- + Select this option if there is no directory for the board under configs/. + + Don't see the board you want? You must first select the exact MCU part + number, then the boards supporting that part will be available for selection. + +endchoice + +config ARCH_BOARD + string + default "amber" if ARCH_BOARD_AMBER + default "avr32dev1" if ARCH_BOARD_AVR32DEV1 + default "c5471evm" if ARCH_BOARD_C5471EVM + default "compal_e88" if ARCH_BOARD_COMPALE88 + default "compal_e99" if ARCH_BOARD_COMPALE99 + default "demo9s12ne64" if ARCH_BOARD_DEMOS92S12NEC64 + default "ea3131" if ARCH_BOARD_EA3131 + default "ea3152" if ARCH_BOARD_EA3152 + default "eagle100" if ARCH_BOARD_EAGLE100 + default "ekk-lm3s9b96" if ARCH_BOARD_EKK_LM3S9B96 + default "ez80f0910200kitg" if ARCH_BOARD_EZ80F910200KITG + default "ez80f0910200zco" if ARCH_BOARD_EZ80F910200ZCO + default "hymini-stm32v" if ARCH_BOARD_HYMINI_STM32V + default "kwikstik-k40" if ARCH_BOARD_KWIKSTIK_K40 + default "lincoln60" if ARCH_BOARD_LINCOLN60 + default "lm3s6432-s2e" if ARCH_BOARD_LM3S6432S2E + default "lm3s6965-ek" if ARCH_BOARD_LM3S6965EK + default "lm3s8962-ek" if ARCH_BOARD_LM3S8962EK + default "lpc4330-xplorer" if ARCH_BOARD_LPC4330_XPLORER + default "lpcxpresso-lpc1768" if ARCH_BOARD_LPCXPRESSO + default "m68322evb" if ARCH_BOARD_M68332EVB + default "mbed" if ARCH_BOARD_MBED + default "mcu123-lpc214x" if ARCH_BOARD_MCU123 + default "micropendous3" if ARCH_BOARD_MICROPENDOUS + default "mirtoo" if ARCH_BOARD_MIRTOO + default "mx1ads" if ARCH_BOARD_MX1ADS + default "ne64badge" if ARCH_BOARD_NE64BADGE + default "ntosd-dm320" if ARCH_BOARD_NTOSD_DM320 + default "nucleus2g" if ARCH_BOARD_NUCLEUS2G + default "olimex-lpc1766stk" if ARCH_BOARD_LPC1766STK + default "olimex-lpc2378" if ARCH_BOARD_OLIMEXLPC2378 + default "olimex-strp711" if ARCH_BOARD_OLIMEX_STRP711 + default "pcblogic-pic32mx" if ARCH_BOARD_PCBLOGICPIC32MX + default "pic32-starterkit" if ARCH_BOARD_PIC32_STARTERKIT + default "pic32mx7mmb" if ARCH_BOARD_PIC32_PIC32MX7MMB + default "pjrc-8051" if ARCH_BOARD_PJRC_87C52 + default "qemu-i486" if ARCH_BOARD_QEMU_I486 + default "rgmp" if ARCH_BOARD_RGMP + default "sam3u-ek" if ARCH_BOARD_SAM3UEK + default "skp16c26" if ARCH_BOARD_SKP16C26 + default "stm3210e-eval" if ARCH_BOARD_STM3210E_EVAL + default "stm3220g-eval" if ARCH_BOARD_STM3220G_EVAL + default "stm3240g-eval" if ARCH_BOARD_STM3240G_EVAL + default "stm32f4discovery" if ARCH_BOARD_STM32F4_DISCOVERY + default "sure-pic32mx" if ARCH_BOARD_SUREPIC32MX + default "teensy" if ARCH_BOARD_TEENSY + default "twr-k60n512" if ARCH_BOARD_TWR_K60N512 + default "ubw32" if ARCH_BOARD_UBW32 + default "us7032evb1" if ARCH_BOARD_US7032EVB1 + default "vsn" if ARCH_BOARD_VSN + default "xtrs" if ARCH_BOARD_XTRS + default "z16f2800100zcog" if ARCH_BOARD_Z16F2800100ZCOG + default "z80sim" if ARCH_BOARD_Z80SIM + default "z8encore000zco" if ARCH_BOARD_Z8ENCORE000ZCO + default "z8f64200100kit" if ARCH_BOARD_Z8F64200100KI + default "sim" if ARCH_BOARD_SIM + default "" if ARCH_BOARD_CUSTOM + +if ARCH_BOARD_AMBER +source "configs/amber/Kconfig" +endif +if ARCH_BOARD_AVR32DEV1 +source "configs/avr32dev1/Kconfig" +endif +if ARCH_BOARD_C5471EVM +source "configs/c5471evm/Kconfig" +endif +if ARCH_BOARD_COMPALE88 +source "configs/compal_e88/Kconfig" +endif +if ARCH_BOARD_COMPALE99 +source "configs/compal_e99/Kconfig" +endif +if ARCH_BOARD_DEMOS92S12NEC64 +source "configs/demo9s12ne64/Kconfig" +endif +if ARCH_BOARD_EA3131 +source "configs/ea3131/Kconfig" +endif +if ARCH_BOARD_EA3152 +source "configs/ea3152/Kconfig" +endif +if ARCH_BOARD_EAGLE100 +source "configs/eagle100/Kconfig" +endif +if ARCH_BOARD_EKK_LM3S9B96 +source "configs/ekk-lm3s9b96/Kconfig" +endif +if ARCH_BOARD_EZ80F910200KITG +source "configs/ez80f910200kitg/Kconfig" +endif +if ARCH_BOARD_EZ80F910200ZCO +source "configs/ez80f910200zco/Kconfig" +endif +if ARCH_BOARD_HYMINI_STM32V +source "configs/hymini-stm32v/Kconfig" +endif +if ARCH_BOARD_KWIKSTIK_K40 +source "configs/kwikstik-k40/Kconfig" +endif +if ARCH_BOARD_LINCOLN60 +source "configs/lincoln60/Kconfig" +endif +if ARCH_BOARD_LM3S6432S2E +source "configs/lm3s6432-s2e/Kconfig" +endif +if ARCH_BOARD_LM3S6965EK +source "configs/lm3s6965-ek/Kconfig" +endif +if ARCH_BOARD_LM3S8962EK +source "configs/lm3s8962-ek/Kconfig" +endif +if ARCH_BOARD_LPC4330_XPLORER +source "configs/lpc4330-xplorer/Kconfig" +endif +if ARCH_BOARD_LPCXPRESSO +source "configs/lpcxpresso-lpc1768/Kconfig" +endif +if ARCH_BOARD_M68332EVB +source "configs/m68332evb/Kconfig" +endif +if ARCH_BOARD_MBED +source "configs/mbed/Kconfig" +endif +if ARCH_BOARD_MCU123 +source "configs/mcu123-lpc214x/Kconfig" +endif +if ARCH_BOARD_MICROPENDOUS +source "configs/micropendous3/Kconfig" +endif +if ARCH_BOARD_MIRTOO +source "configs/mirtoo/Kconfig" +endif +if ARCH_BOARD_MX1ADS +source "configs/mx1ads/Kconfig" +endif +if ARCH_BOARD_NE64BADGE +source "configs/ne64badge/Kconfig" +endif +if ARCH_BOARD_NTOSD_DM320 +source "configs/ntosd-dm320/Kconfig" +endif +if ARCH_BOARD_NUCLEUS2G +source "configs/nucleus2g/Kconfig" +endif +if ARCH_BOARD_LPC1766STK +source "configs/olimex-lpc1766stk/Kconfig" +endif +if ARCH_BOARD_OLIMEXLPC2378 +source "configs/olimex-lpc2378/Kconfig" +endif +if ARCH_BOARD_OLIMEX_STRP711 +source "configs/olimex-strp711/Kconfig" +endif +if ARCH_BOARD_PCBLOGICPIC32MX +source "configs/pcblogic-pic32mx/Kconfig" +endif +if ARCH_BOARD_PIC32_STARTERKIT +source "configs/pic32-starterkit/Kconfig" +endif +if ARCH_BOARD_PIC32_PIC32MX7MMB +source "configs/pic32mx7mmb/Kconfig" +endif +if ARCH_BOARD_PJRC_87C52 +source "configs/pjrc-8051/Kconfig" +endif +if ARCH_BOARD_QEMU_I486 +source "configs/qemu-i486/Kconfig" +endif +if ARCH_BOARD_RGMP +source "configs/rgmp/Kconfig" +endif +if ARCH_BOARD_SAM3UEK +source "configs/sam3u-ek/Kconfig" +endif +if ARCH_BOARD_SKP16C26 +source "configs/skp16c26/Kconfig" +endif +if ARCH_BOARD_STM3210E_EVAL +source "configs/stm3210e-eval/Kconfig" +endif +if ARCH_BOARD_STM3220G_EVAL +source "configs/stm3220g-eval/Kconfig" +endif +if ARCH_BOARD_STM3240G_EVAL +source "configs/stm3240g-eval/Kconfig" +endif +if ARCH_BOARD_STM32F4_DISCOVERY +source "configs/stm32f4discovery/Kconfig" +endif +if ARCH_BOARD_SUREPIC32MX +source "configs/sure-pic32mx/Kconfig" +endif +if ARCH_BOARD_TEENSY +source "configs/teensy/Kconfig" +endif +if ARCH_BOARD_TWR_K60N512 +source "configs/twr-k60n512/Kconfig" +endif +if ARCH_BOARD_UBW32 +source "configs/ubw32/Kconfig" +endif +if ARCH_BOARD_US7032EVB1 +source "configs/us7032evb1/Kconfig" +endif +if ARCH_BOARD_VSN +source "configs/vsn/Kconfig" +endif +if ARCH_BOARD_XTRS +source "configs/xtrs/Kconfig" +endif +if ARCH_BOARD_Z16F2800100ZCOG +source "configs/z16f2800100zcog/Kconfig" +endif +if ARCH_BOARD_Z80SIM +source "configs/z80sim/Kconfig" +endif +if ARCH_BOARD_Z8ENCORE000ZCO +source "configs/z8encore000zco/Kconfig" +endif +if ARCH_BOARD_Z8F64200100KI +source "configs/z8f64200100kit/Kconfig" +endif +if ARCH_BOARD_SIM +source "configs/sim/Kconfig" +endif diff --git a/nuttx/configs/README.txt b/nuttx/configs/README.txt new file mode 100644 index 0000000000..db341dfe3b --- /dev/null +++ b/nuttx/configs/README.txt @@ -0,0 +1,1774 @@ +Board-Specific Configurations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Table of Contents +^^^^^^^^^^^^^^^^^ + + o Board-Specific Configurations + o Summary of Files + o Supported Architectures + o Configuring NuttX + +Board-Specific Configurations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The NuttX configuration consists of: + +o Processor architecture specific files. These are the files contained + in the arch// directory. + +o Chip/SoC specific files. Each processor processor architecture + is embedded in chip or System-on-a-Chip (SoC) architecture. The + full chip architecture includes the processor architecture plus + chip-specific interrupt logic, general purpose I/O (GIO) logic, and + specialized, internal peripherals (such as UARTs, USB, etc.). + + These chip-specific files are contained within chip-specific + sub-directories in the arch// directory and are selected + via the CONFIG_ARCH_name selection + +o Board specific files. In order to be usable, the chip must be + contained in a board environment. The board configuration defines + additional properties of the board including such things as + peripheral LEDs, external peripherals (such as network, USB, etc.). + + These board-specific configuration files can be found in the + configs// sub-directories and are discussed in this + README. Additional configuration information maybe available in + board-specific configs//README.txt files. + +The configs/ subdirectory contains configuration data for each board. These +board-specific configurations plus the architecture-specific configurations in +the arch/ subdirectory completely define a customized port of NuttX. + +Directory Structure +^^^^^^^^^^^^^^^^^^^ + +The configs directory contains board specific configurationlogic. Each +board must provide a subdirectory under configs/ with the +following characteristics: + + + + |-- README.txt + |-- include/ + | `-- (board-specific header files) + |-- src/ + | |-- Makefile + | `-- (board-specific source files) + |-- + | |-- Make.defs + | |-- defconfig + | |-- appconfig* + | `-- setenv.sh + |-- + | |-- Make.defs + | |-- defconfig + | |-- appconfig* + | `-- setenv.sh + ... + + *optional + +Summary of Files +^^^^^^^^^^^^^^^^ + +README.txt -- This text file provides additional information unique to + each board configuration sub-directory. + +include/ -- This directory contains board specific header files. This + directory will be linked as include/arch/board at configuration time and + can be included via '#include '. These header file + can only be included by files in arch/include/ and + arch//src + +src/ -- This directory contains board specific drivers. This + directory will be linked as arch//src/board at configuration + time and will be integrated into the build system. + +src/Makefile -- This makefile will be invoked to build the board specific + drivers. It must support the following targets: libext$(LIBEXT), clean, + and distclean. + +A board may have various different configurations using these common source +files. Each board configuration is described by three files: Make.defs, +defconfig, and setenv.sh. Typically, each set of configuration files is +retained in a separate configuration sub-directory (, +, .. in the above diagram). + +Make.defs -- This makefile fragment provides architecture and + tool-specific build options. It will be included by all other + makefiles in the build (once it is installed). This make fragment + should define: + + Tools: CC, LD, AR, NM, OBJCOPY, OBJDUMP + Tool options: CFLAGS, LDFLAGS + COMPILE, ASSEMBLE, ARCHIVE, CLEAN, and MKDEP macros + + When this makefile fragment runs, it will be passed TOPDIR which + is the path to the root directory of the build. This makefile + fragment may include ${TOPDIR}/.config to perform configuration + specific settings. For example, the CFLAGS will most likely be + different if CONFIG_DEBUG=y. + +defconfig -- This is a configuration file similar to the Linux + configuration file. In contains variable/value pairs like: + + CONFIG_VARIABLE=value + + This configuration file will be used at build time: + + (1) as a makefile fragment included in other makefiles, and + (2) to generate include/nuttx/config.h which is included by + most C files in the system. + + The following variables are recognized by the build (you may + also include architecture/board-specific settings). + + Architecture selection: + + CONFIG_ARCH - Identifies the arch/ subdirectory + CONFIG_ARCH_name - For use in C code + CONFIG_ARCH_CHIP - Identifies the arch/*/chip subdirectory + CONFIG_ARCH_CHIP_name - For use in C code + CONFIG_ARCH_BOARD - Identifies the configs subdirectory and + hence, the board that supports the particular chip or SoC. + CONFIG_ARCH_BOARD_name - For use in C code + CONFIG_ENDIAN_BIG - define if big endian (default is little + endian) + CONFIG_ARCH_NOINTC - define if the architecture does not + support an interrupt controller or otherwise cannot support + APIs like up_enable_irq() and up_disable_irq(). + CONFIG_ARCH_VECNOTIRQ - Usually the interrupt vector number provided + to interfaces like irq_attach() and irq_detach are the same as IRQ + numbers that are provied to IRQ management functions like + up_enable_irq() and up_disable_irq(). But that is not true for all + interrupt controller implementations. For example, the PIC32MX + interrupt controller manages interrupt sources that have a many-to-one + relationship to interrupt vectors. In such cases, CONFIG_ARCH_VECNOTIRQ + must defined so that the OS logic will know not to assume it can use + a vector number to enable or disable interrupts. + CONFIG_ARCH_IRQPRIO + Define if the architecture suports prioritizaton of interrupts + and the up_prioritize_irq() API. + + Some architectures require a description of the RAM configuration: + + CONFIG_DRAM_SIZE - Describes the installed DRAM. + CONFIG_DRAM_START - The start address of DRAM (physical) + CONFIG_DRAM_VSTART - The start address of DRAM (virtual) + + General build options: + + CONFIG_RRLOAD_BINARY - make the rrload binary format used with + BSPs from www.ridgerun.com using the tools/mkimage.sh script. + CONFIG_INTELHEX_BINARY - make the Intel HEX binary format + used with many different loaders using the GNU objcopy program + Should not be selected if you are not using the GNU toolchain. + CONFIG_MOTOROLA_SREC - make the Motorola S-Record binary format + used with many different loaders using the GNU objcopy program + Should not be selected if you are not using the GNU toolchain. + CONFIG_RAW_BINARY - make a raw binary format file used with many + different loaders using the GNU objcopy program. This option + should not be selected if you are not using the GNU toolchain. + CONFIG_HAVE_LIBM - toolchain supports libm.a + CONFIG_HAVE_CXX - toolchain supports C++ and CXX, CXXFLAGS, and + COMPILEXX have been defined in the configurations Make.defs + file. + CONFIG_HAVE_CXXINITIALIZE - The platform-specific logic includes support + for initialization of static C++ instances for this architecture + and for the selected toolchain (via up_cxxinitialize()). + + Building application code: + + CONFIG_APPS_DIR - Identifies the directory that builds the + application to link with NuttX. Default: ../apps This symbol must be assigned + to the path to the application build directory *relative* to + the NuttX top build direcory. If you had an application + directory and the NuttX directory each in separate directory + trees like this: + + build + |-nuttx + | | + | `- Makefile + `-application + | + `- Makefile + + Then you would set CONFIG_APPS_DIR=../application. + + The application direction must contain Makefile and this make + file must support the following targets: + + - libapps$(LIBEXT) (usually libapps.a). libapps.a is a static + library ( an archive) that contains all of application object + files. + - clean. Do whatever is appropriate to clean the application + directories for a fresh build. + - distclean. Clean everthing -- auto-generated files, symbolic + links etc. -- so that the directory contents are the same as + the contents in your configuration management system. + This is only done when you change the NuttX configuration. + - depend. Make or update the application build dependencies. + + When this application is invoked it will receive the setting TOPDIR like: + + $(MAKE) -C $(CONFIG_APPS_DIR) TOPDIR="$(TOPDIR)" + + TOPDIR is the full path to the NuttX directory. It can be used, for + example, to include makefile fragments (e.g., .config or Make.defs) + or to set up include file paths. + + Two-pass build options. If the 2 pass build option is selected, then these + options configure the make system build a extra link object. This link object + is assumed to be an incremental (relative) link object, but could be a static + library (archive) (some modification to this Makefile would be required if + CONFIG_PASS1_TARGET generates an archive). Pass 1 1ncremental (relative) link + objects should be put into the processor-specific source directory (where other + link objects will be created). If the pass1 obect is an archive, it could + go anywhere. + + CONFIG_BUILD_2PASS - Enables the two pass build options. + + When the two pass build option is enabled, the following also apply: + + CONFIG_PASS1_TARGET - The name of the first pass build target. This + can be specific build target, a special build target (all, default, etc.) + or may just be left undefined. + CONFIG_PASS1_BUILDIR - The path, relative to the top NuttX build + directory to directory that contains the Makefile to build the + first pass object. The Makefile must support the following targets: + - The special target CONFIG_PASS1_TARGET (if defined) + - and the usual depend, clean, and distclean targets. + CONFIG_PASS1_OBJECT - May be used to include an extra, pass1 object + into the final link. This would probably be the object generated + from the CONFIG_PASS1_TARGET. It may be available at link time + in the arch//src directory. + + General OS setup + + CONFIG_DEBUG - enables built-in debug options + CONFIG_DEBUG_VERBOSE - enables verbose debug output + CCONFIG_DEBUG_ENABLE - Support an interface to enable or disable debug output. + CONFIG_DEBUG_SYMBOLS - build without optimization and with + debug symbols (needed for use with a debugger). + CONFIG_DEBUG_SCHED - enable OS debug output (disabled by + default) + CONFIG_DEBUG_MM - enable memory management debug output + (disabled by default) + CONFIG_DEBUG_NET - enable network debug output (disabled + by default) + CONFIG_DEBUG_USB - enable usb debug output (disabled by + default) + CONFIG_DEBUG_FS - enable filesystem debug output (disabled + by default) + CONFIG_DEBUG_LIB - enable C library debug output (disabled + by default) + CONFIG_DEBUG_BINFMT - enable binary loader debug output (disabled + by default) + CONFIG_DEBUG_GRAPHICS - enable NX graphics debug output + (disabled by default) + CONFIG_ARCH_LOWPUTC - architecture supports low-level, boot + time console output + CONFIG_MM_REGIONS - If the architecture includes multiple + regions of memory to allocate from, this specifies the + number of memory regions that the memory manager must + handle and enables the API mm_addregion(start, end); + CONFIG_MM_SMALL - Each memory allocation has a small allocation + overhead. The size of that overhead is normally determined by + the "width" of the address support by the MCU. MCUs that support + 16-bit addressability have smaller overhead than devices that + support 32-bit addressability. However, there are many MCUs + that support 32-bit addressability *but* have internal SRAM + of size less than or equal to 64Kb. In this case, CONFIG_MM_SMALL + can be defined so that those MCUs will also benefit from the + smaller, 16-bit-based allocation overhead. + CONFIG_MSEC_PER_TICK - The default system timer is 100Hz + or MSEC_PER_TICK=10. This setting may be defined to + inform NuttX that the processor hardware is providing + system timer interrupts at some interrupt interval other + than 10 msec. + CONFIG_RR_INTERVAL - The round robin timeslice will be set + this number of milliseconds; Round robin scheduling can + be disabled by setting this value to zero. + CONFIG_SCHED_INSTRUMENTATION - enables instrumentation in + scheduler to monitor system performance + CONFIG_TASK_NAME_SIZE - Specifies that maximum size of a + task name to save in the TCB. Useful if scheduler + instrumentation is selected. Set to zero to disable. + CONFIG_START_YEAR, CONFIG_START_MONTH, CONFIG_START_DAY - + Used to initialize the internal time logic. + CONFIG_GREGORIAN_TIME - Enables Gregorian time conversions. + You would only need this if you are concerned about accurate + time conversions in the past or in the distant future. + CONFIG_JULIAN_TIME - Enables Julian time conversions. You + would only need this if you are concerned about accurate + time conversion in the distand past. You must also define + CONFIG_GREGORIAN_TIME in order to use Julian time. + CONFIG_DEV_CONSOLE - Set if architecture-specific logic + provides /dev/console. Enables stdout, stderr, stdin. + This implies the "normal" serial driver provides the + console unless another console device is specified + (See CONFIG_DEV_LOWCONSOLE). + CONFIG_MUTEX_TYPES - Set to enable support for recursive and + errorcheck mutexes. Enables pthread_mutexattr_settype(). + CONFIG_PRIORITY_INHERITANCE - Set to enable support for + priority inheritance on mutexes and semaphores. + Priority inheritance is a strategy for addressing priority + inversion. + CONFIG_SEM_PREALLOCHOLDERS: This setting is only used if priority + inheritance is enabled. It defines the maximum number of + different threads (minus one) that can take counts on a + semaphore with priority inheritance support. This may be + set to zero if priority inheritance is disabled OR if you + are only using semaphores as mutexes (only one holder) OR + if no more than two threads participate using a counting + semaphore. + CONFIG_SEM_NNESTPRIO. If priority inheritance is enabled, + then this setting is the maximum number of higher priority + threads (minus 1) than can be waiting for another thread + to release a count on a semaphore. This value may be set + to zero if no more than one thread is expected to wait for + a semaphore. + CONFIG_FDCLONE_DISABLE. Disable cloning of all file descriptors + by task_create() when a new task is started. If set, all + files/drivers will appear to be closed in the new task. + CONFIG_FDCLONE_STDIO. Disable cloning of all but the first + three file descriptors (stdin, stdout, stderr) by task_create() + when a new task is started. If set, all files/drivers will + appear to be closed in the new task except for stdin, stdout, + and stderr. + CONFIG_SDCLONE_DISABLE. Disable cloning of all socket + desciptors by task_create() when a new task is started. If + set, all sockets will appear to be closed in the new task. + CONFIG_NXFLAT. Enable support for the NXFLAT binary format. + This format will support execution of NuttX binaries located + in a ROMFS filesystem (see examples/nxflat). + CONFIG_SCHED_WORKQUEUE. Create a dedicated "worker" thread to + handle delayed processing from interrupt handlers. This feature + is required for some drivers but, if there are not complaints, + can be safely disabled. The worker thread also performs + garbage collection -- completing any delayed memory deallocations + from interrupt handlers. If the worker thread is disabled, + then that clean will be performed by the IDLE thread instead + (which runs at the lowest of priority and may not be appropriate + if memory reclamation is of high priority). If CONFIG_SCHED_WORKQUEUE + is enabled, then the following options can also be used: + CONFIG_SCHED_WORKPRIORITY - The execution priority of the worker + thread. Default: 50 + CONFIG_SCHED_WORKPERIOD - How often the worker thread checks for + work in units of microseconds. Default: 50*1000 (50 MS). + CONFIG_SCHED_WORKSTACKSIZE - The stack size allocated for the worker + thread. Default: CONFIG_IDLETHREAD_STACKSIZE. + CONFIG_SIG_SIGWORK - The signal number that will be used to wake-up + the worker thread. Default: 4 + CONFIG_SCHED_WAITPID - Enables the waitpid() API + CONFIG_SCHED_ATEXIT - Enables the atexit() API + CONFIG_SCHED_ATEXIT_MAX - By default if CONFIG_SCHED_ATEXIT is + selected, only a single atexit() function is supported. That number + can be increased by defined this setting to the number that you require. + CONFIG_SCHED_ONEXIT - Enables the on_exit() API + CONFIG_SCHED_ONEXIT_MAX - By default if CONFIG_SCHED_ONEXIT is selected, + only a single on_exit() function is supported. That number can be + increased by defined this setting to the number that you require. + + System Logging: + CONFIG_SYSLOG enables general system logging support. + CONFIG_SYSLOG_DEVPATH - The full path to the system logging device. Default + "/dev/ramlog" (RAMLOG) or "dev/ttyS1" (character device) + + At present, there are two system loggins devices available. If CONFIG_SYSLOG + is selected, then these options are also available. + + CONFIG_SYSLOG_CHAR - Enable the generic character device for the SYSLOG. + A disadvantage of using the generic character device for the SYSLOG is that + it cannot handle debug output generated from interrupt level handlers. + NOTE: No more than one SYSLOG device should be configured. + + CONFIG_RAMLOG - Enables the RAM logging feature. The RAM log is a circular + buffer in RAM. NOTE: No more than one SYSLOG device should be configured. + CONFIG_RAMLOG_CONSOLE - Use the RAM logging device as a system console. + If this feature is enabled (along with CONFIG_DEV_CONSOLE), then all + console output will be re-directed to a circular buffer in RAM. This + is useful, for example, if the only console is a Telnet console. Then + in that case, console output from non-Telnet threads will go to the + circular buffer and can be viewed using the NSH 'dmesg' command. + CONFIG_RAMLOG_SYSLOG - Use the RAM logging device for the syslogging + interface. If this feature is enabled (along with CONFIG_SYSLOG), + then all debug output (only) will be re-directed to the circular + buffer in RAM. This RAM log can be view from NSH using the 'dmesg' + command. NOTE: Unlike the limited, generic character driver SYSLOG + device, the RAMLOG *can* be used to generate debug output from interrupt + level handlers. + CONFIG_RAMLOG_NPOLLWAITERS - The number of threads than can be waiting + for this driver on poll(). Default: 4 + + If CONFIG_RAMLOG_CONSOLE or CONFIG_RAMLOG_SYSLOG is selected, then the + following may also be provided: + + CONFIG_RAMLOG_CONSOLE_BUFSIZE - Size of the console RAM log. Default: 1024 + + Kernel build options: + CONFIG_NUTTX_KERNEL - Builds NuttX as a separately compiled kernel. + CONFIG_SYS_RESERVED - Reserved system call values for use + by architecture-specific logic. + + OS setup related to on-demand paging: + + CONFIG_PAGING - If set =y in your configation file, this setting will + enable the on-demand paging feature as described in + http://www.nuttx.org/NuttXDemandPaging.html. + + If CONFIG_PAGING is selected, then you will probabaly need CONFIG_BUILD_2PASS to + correctly position the code and the following configuration options also apply: + + CONFIG_PAGING_PAGESIZE - The size of one managed page. This must + be a value supported by the processor's memory management unit. + CONFIG_PAGING_NLOCKED - This is the number of locked pages in the + memory map. The locked address region will then be from + CONFIG_DRAM_VSTART through (CONFIG_DRAM_VSTART + + CONFIG_PAGING_PAGESIZE*CONFIG_PAGING_NLOCKED) + CONFIG_PAGING_LOCKED_PBASE and CONFIG_PAGING_LOCKED_VBASE - These + may be defined to determine the base address of the locked page + regions. If neither are defined, the logic will be set the bases + to CONFIG_DRAM_START and CONFIG_DRAM_VSTART (i.e., it assumes + that the base address of the locked region is at the beginning + of RAM). + NOTE: In some architectures, it may be necessary to take some + memory from the beginning of this region for vectors or for a + page table. In such cases, CONFIG_PAGING_LOCKED_P/VBASE should + take that into consideration to prevent overlapping the locked + memory region and the system data at the beginning of SRAM. + CONFIG_PAGING_NPPAGED - This is the number of physical pages + available to support the paged text region. This paged region + begins at (CONFIG_PAGING_LOCKED_PBASE + CONFIG_PAGING_PAGESIZE*CONFIG_PAGING_NPPAGED) + and continues until (CONFIG_PAGING_LOCKED_PBASE + CONFIG_PAGING_PAGESIZE*(CONFIG_PAGING_NLOCKED + + CONFIG_PAGING_NPPAGED) + CONFIG_PAGING_NVPAGED - This actual size of the paged text region + (in pages). This is also the number of virtual pages required to + support the entire paged region. The on-demand paging feature is + intended to support only the case where the virtual paged text + area is much larger the available physical pages. Otherwise, why + would you enable on-demand paging? + CONFIG_PAGING_NDATA - This is the number of data pages in the memory + map. The data region will extend to the end of RAM unless overridden + by a setting in the configuration file. + NOTE: In some architectures, it may be necessary to take some memory + from the end of RAM for page tables or other system usage. The + configuration settings and linker directives must be cognizant of that: + CONFIG_PAGING_NDATA should be defined to prevent the data region from + extending all the way to the end of memory. + CONFIG_PAGING_DEFPRIO - The default, minimum priority of the page fill + worker thread. The priority of the page fill work thread will be boosted + boosted dynmically so that it matches the priority of the task on behalf + of which it peforms the fill. This defines the minimum priority that + will be used. Default: 50. + CONFIG_PAGING_STACKSIZE - Defines the size of the allocated stack + for the page fill worker thread. Default: 1024. + CONFIG_PAGING_BLOCKINGFILL - The architecture specific up_fillpage() + function may be blocking or non-blocking. If defined, this setting + indicates that the up_fillpage() implementation will block until the + transfer is completed. Default: Undefined (non-blocking). + CONFIG_PAGING_WORKPERIOD - The page fill worker thread will wake periodically + even if there is no mapping to do. This selection controls that wake-up + period (in microseconds). This wake-up a failsafe that will handle any + cases where a single is lost (that would really be a bug and shouldn't + happen!) and also supports timeouts for case of non-blocking, asynchronous + fills (see CONFIG_PAGING_TIMEOUT_TICKS). + CONFIG_PAGING_TIMEOUT_TICKS - If defined, the implementation will monitor + the (asynchronous) page fill logic. If the fill takes longer than this + number if microseconds, then a fatal error will be declared. + Default: No timeouts monitored. + + Some architecture-specific settings. Defaults are architecture specific. + If you don't know what you are doing, it is best to leave these undefined + and try the system defaults: + + CONFIG_PAGING_VECPPAGE - This the physical address of the page in + memory to be mapped to the vector address. + CONFIG_PAGING_VECL2PADDR - This is the physical address of the L2 + page table entry to use for the vector mapping. + CONFIG_PAGING_VECL2VADDR - This is the virtual address of the L2 + page table entry to use for the vector mapping. + CONFIG_PAGING_BINPATH - If CONFIG_PAGING_BINPATH is defined, then it + is the full path to a file on a mounted file system that contains + a binary image of the NuttX executable. Pages will be filled by + reading from offsets into this file that correspond to virtual + fault addresses. + CONFIG_PAGING_MOUNTPT - If CONFIG_PAGING_BINPATH is defined, additional + options may be provided to control the initialization of underlying + devices. CONFIG_PAGING_MOUNTPT identifies the mountpoint to be used + if a device is mounted. + CONFIG_PAGING_MINOR - Some mount operations require a "minor" number + to identify the specific device instance. Default: 0 + CONFIG_PAGING_SDSLOT - If CONFIG_PAGING_BINPATH is defined, additional + options may be provided to control the initialization of underlying + devices. CONFIG_PAGING_SDSLOT identifies the slot number of the SD + device to initialize. This must be undefined if SD is not being used. + This should be defined to be zero for the typical device that has + only a single slot (See CONFIG_MMCSD_NSLOTS). If defined, + CONFIG_PAGING_SDSLOT will instruct certain board-specific logic to + initialize the media in this SD slot. + CONFIG_PAGING_M25PX - Use the m25px.c FLASH driver. If this is selected, + then the MTD interface to the M25Px device will be used to support + paging. + CONFIG_PAGING_AT45DB - Use the at45db.c FLASH driver. If this is selected, + then the MTD interface to the Atmel AT45DB device will be used to support + paging. + CONFIG_PAGING_BINOFFSET - If CONFIG_PAGING_M25PX or is CONFIG_PAGING_AT45DB + defined then CONFIG_PAGING_BINOFFSET will be used to specify the offset + in bytes into the FLASH device where the NuttX binary image is located. + Default: 0 + CONFIG_PAGING_SPIPORT - If CONFIG_PAGING_M25PX CONFIG_PAGING_AT45DB is + defined and the device has multiple SPI busses (ports), then this + configuration should be set to indicate which SPI port the device is + connected. Default: 0 + + The following can be used to disable categories of APIs supported + by the OS. If the compiler supports weak functions, then it + should not be necessary to disable functions unless you want to + restrict usage of those APIs. + + There are certain dependency relationships in these features. + + o mq_notify logic depends on signals to awaken tasks + waiting for queues to become full or empty. + o pthread_condtimedwait() depends on signals to wake + up waiting tasks. + + CONFIG_DISABLE_CLOCK, CONFIG_DISABLE_POSIX_TIMERS, CONFIG_DISABLE_PTHREAD. + CONFIG_DISABLE_SIGNALS, CONFIG_DISABLE_MQUEUE, CONFIG_DISABLE_MOUNTPOUNT, + CONFIG_DISABLE_ENVIRON, CONFIG_DISABLE_POLL + + Misc libc settings + + CONFIG_NOPRINTF_FIELDWIDTH - sprintf-related logic is a + little smaller if we do not support fieldwidthes + CONFIG_LIBC_FLOATINGPOINT - By default, floating point + support in printf, sscanf, etc. is disabled. + + Allow for architecture optimized implementations + + The architecture can provide optimized versions of the + following to improve system performance + + CONFIG_ARCH_MEMCPY, CONFIG_ARCH_MEMCMP, CONFIG_ARCH_MEMMOVE + CONFIG_ARCH_MEMSET, CONFIG_ARCH_STRCMP, CONFIG_ARCH_STRCPY + CONFIG_ARCH_STRNCPY, CONFIG_ARCH_STRLEN, CONFIG_ARCH_STRNLEN + CONFIG_ARCH_BZERO + + The architecture may provide custom versions of certain standard header + files: + + CONFIG_ARCH_STDBOOL_H - The stdbool.h header file can be found at + nuttx/include/stdbool.h. However, that header includes logic to redirect + the inclusion of an architecture specific header file like: + + #ifdef CONFIG_ARCH_STDBOOL_H + # include + #else + ... + #endif + + Recall that that include path, include/arch, is a symbolic link and + will refer to a version of stdbool.h at nuttx/arch//include/stdbool.h. + + CONFIG_ARCH_STDINT_H - Similar logic exists for the stdint.h header + file can also be found at nuttx/include/stdint.h. + + #ifdef CONFIG_ARCH_STDBOOL_H + # include + #else + ... + #endif + + CONFIG_ARCH_MATH_H - There is also a re-directing version of math.h in + the source tree. However, it resides out-of-the-way at include/nuttx/math.h + because it conflicts too often with the system math.h. If CONFIG_ARCH_MATH_H=y + is defined, however, the top-level makefile will copy the redirecting + math.h header file from include/nuttx/math.h to include/math.h. math.h + will then include the architecture-specific version of math.h that you + must provide at nuttx/arch/>architecture + #endif + + So for the architectures that define CONFIG_ARCH_MATH_H=y, include/math.h + will be the redirecting math.h header file; for the architectures that + don't select CONFIG_ARCH_MATH_H, the redirecting math.h header file will + stay out-of-the-way in include/nuttx/. + + CONFIG_ARCH_STDARG_H - There is also a redirecting version of stdarg.h in + the source tree as well. It also resides out-of-the-way at include/nuttx/stdarg.h. + This is because you should normally use your toolchain's stdarg.h file. But + sometimes, your toolchain's stdarg.h file may have other header file + dependencies and so may not be usable in the NuttX build environment. In + those cases, you may have to create a architecture-specific stdarg.h header + file at nuttx/arch/>architecture 0) + CONFIG_STDIO_LINEBUFFER - If standard C buffered I/O is enabled + (CONFIG_STDIO_BUFFER_SIZE > 0), then this option may be added + to force automatic, line-oriented flushing the output buffer + for putc(), fputc(), putchar(), puts(), fputs(), printf(), + fprintf(), and vfprintf(). When a newline is encountered in + the output string, the output buffer will be flushed. This + (slightly) increases the NuttX footprint but supports the kind + of behavior that people expect for printf(). + CONFIG_NUNGET_CHARS - Number of characters that can be + buffered by ungetc() (Only if CONFIG_NFILE_STREAMS > 0) + CONFIG_PREALLOC_MQ_MSGS - The number of pre-allocated message + structures. The system manages a pool of preallocated + message structures to minimize dynamic allocations + CONFIG_PREALLOC_IGMPGROUPS - Pre-allocated IGMP groups are used + only if needed from interrupt level group created (by the IGMP server). + Default: 4. + CONFIG_MQ_MAXMSGSIZE - Message structures are allocated with + a fixed payload size given by this settin (does not include + other message structure overhead. + CONFIG_PREALLOC_WDOGS - The number of pre-allocated watchdog + structures. The system manages a pool of preallocated + watchdog structures to minimize dynamic allocations + CONFIG_DEV_PIPE_SIZE - Size, in bytes, of the buffer to allocated + for pipe and FIFO support + + Filesystem configuration + + CONFIG_FS_FAT - Enable FAT filesystem support + CONFIG_FAT_SECTORSIZE - Max supported sector size + CONFIG_FAT_LCNAMES - Enable use of the NT-style upper/lower case 8.3 + file name support. + CONFIG_FAT_LFN - Enable FAT long file names. NOTE: Microsoft claims + patents on FAT long file name technology. Please read the + disclaimer in the top-level COPYING file and only enable this + feature if you understand these issues. + CONFIG_FAT_MAXFNAME - If CONFIG_FAT_LFN is defined, then the + default, maximum long file name is 255 bytes. This can eat up + a lot of memory (especially stack space). If you are willing + to live with some non-standard, short long file names, then + define this value. A good choice would be the same value as + selected for CONFIG_NAME_MAX which will limit the visibility + of longer file names anyway. + CONFIG_FS_FATTIME: Support FAT date and time. NOTE: There is not + much sense in supporting FAT date and time unless you have a + hardware RTC or other way to get the time and date. + CONFIG_FS_NXFFS: Enable NuttX FLASH file system (NXFF) support. + CONFIG_NXFFS_ERASEDSTATE: The erased state of FLASH. + This must have one of the values of 0xff or 0x00. + Default: 0xff. + CONFIG_NXFFS_PACKTHRESHOLD: When packing flash file data, + don't both with file chunks smaller than this number of data bytes. + Default: 32. + CONFIG_NXFFS_MAXNAMLEN: The maximum size of an NXFFS file name. + Default: 255. + CONFIG_NXFFS_PACKTHRESHOLD: When packing flash file data, + don't both with file chunks smaller than this number of data bytes. + Default: 32. + CONFIG_NXFFS_TAILTHRESHOLD: clean-up can either mean + packing files together toward the end of the file or, if file are + deleted at the end of the file, clean up can simply mean erasing + the end of FLASH memory so that it can be re-used again. However, + doing this can also harm the life of the FLASH part because it can + mean that the tail end of the FLASH is re-used too often. This + threshold determines if/when it is worth erased the tail end of FLASH + and making it available for re-use (and possible over-wear). + Default: 8192. + CONFIG_FS_ROMFS - Enable ROMFS filesystem support + CONFIG_NFS - Enable Network File System (NFS) client file system support. + Provided support is version 3 using UDP. In addition to common + prerequisites for mount-able file systems in general, this option + requires UDP networking support; this would include CONFIG_NETand + CONFIG_NET_UDP at a minimum. + CONFIG_FS_RAMMAP - For file systems that do not support XIP, this + option will enable a limited form of memory mapping that is + implemented by copying whole files into memory. + + RTC + + CONFIG_RTC - Enables general support for a hardware RTC. Specific + architectures may require other specific settings. + CONFIG_RTC_DATETIME - There are two general types of RTC: (1) A simple + battery backed counter that keeps the time when power is down, and (2) + A full date / time RTC the provides the date and time information, often + in BCD format. If CONFIG_RTC_DATETIME is selected, it specifies this + second kind of RTC. In this case, the RTC is used to "seed" the normal + NuttX timer and the NuttX system timer provides for higher resoution + time. + CONFIG_RTC_HIRES - If CONFIG_RTC_DATETIME not selected, then the simple, + battery backed counter is used. There are two different implementations + of such simple counters based on the time resolution of the counter: + The typical RTC keeps time to resolution of 1 second, usually + supporting a 32-bit time_t value. In this case, the RTC is used to + "seed" the normal NuttX timer and the NuttX timer provides for higher + resoution time. If CONFIG_RTC_HIRES is enabled in the NuttX configuration, + then the RTC provides higher resolution time and completely replaces the + system timer for purpose of date and time. + CONFIG_RTC_FREQUENCY - If CONFIG_RTC_HIRES is defined, then the frequency + of the high resolution RTC must be provided. If CONFIG_RTC_HIRES is + not defined, CONFIG_RTC_FREQUENCY is assumed to be one. + CONFIG_RTC_ALARM - Enable if the RTC hardware supports setting of an + alarm. A callback function will be executed when the alarm goes off + + CAN driver + + CONFIG_CAN - Enables CAN support (one or both of CONFIG_STM32_CAN1 or + CONFIG_STM32_CAN2 must also be defined) + CONFIG_CAN_EXTID - Enables support for the 29-bit extended ID. Default + Standard 11-bit IDs. + CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages. + Default: 8 + CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests. + Default: 4 + CONFIG_CAN_LOOPBACK - A CAN driver may or may not support a loopback + mode for testing. If the driver does support loopback mode, the setting + will enable it. (If the driver does not, this setting will have no effect). + + SPI driver + + CONFIG_SPI_OWNBUS - Set if there is only one active device + on the SPI bus. No locking or SPI configuration will be performed. + It is not necessary for clients to lock, re-configure, etc.. + CONFIG_SPI_EXCHANGE - Driver supports a single exchange method + (vs a recvblock() and sndblock ()methods) + + SPI-based MMC/SD driver + + CONFIG_MMCSD_NSLOTS - Number of MMC/SD slots supported by the + driver. Default is one. + CONFIG_MMCSD_READONLY - Provide read-only access. Default is + Read/Write + CONFIG_MMCSD_SPICLOCK - Maximum SPI clock to drive MMC/SD card. + Default is 20MHz. + + SDIO/SDHC driver: + + CONFIG_SDIO_DMA - SDIO driver supports DMA + CONFIG_SDIO_MUXBUS - Set this SDIO interface if the SDIO interface + or hardware resources are shared with other drivers. + CONFIG_SDIO_WIDTH_D1_ONLY - Select 1-bit transfer mode. Default: + 4-bit transfer mode. + CONFIG_MMCSD_MULTIBLOCK_DISABLE - Use only the single block transfer method. + This setting is used to work around buggy SDIO drivers that cannot handle + multiple block transfers. + + SDIO-based MMC/SD driver + + CONFIG_FS_READAHEAD - Enable read-ahead buffering + CONFIG_FS_WRITEBUFFER - Enable write buffering + CONFIG_MMCSD_MMCSUPPORT - Enable support for MMC cards + CONFIG_MMCSD_HAVECARDDETECT - SDIO driver card detection is + 100% accurate + + RiT P14201 OLED driver + + CONFIG_LCD_P14201 - Enable P14201 support + CONFIG_P14201_SPIMODE - Controls the SPI mode + CONFIG_P14201_FREQUENCY - Define to use a different bus frequency + CONFIG_P14201_NINTERFACES - Specifies the number of physical P14201 + devices that will be supported. + CONFIG_P14201_FRAMEBUFFER - If defined, accesses will be performed + using an in-memory copy of the OLEDs GDDRAM. This cost of this + buffer is 128 * 96 / 2 = 6Kb. If this is defined, then the driver + will be fully functional. If not, then it will have the following + limitations: + - Reading graphics memory cannot be supported, and + - All pixel writes must be aligned to byte boundaries. + The latter limitation effectively reduces the 128x96 disply to 64x96. + + Nokia 6100 Configuration Settings: + + CONFIG_NOKIA6100_SPIMODE - Controls the SPI mode + CONFIG_NOKIA6100_FREQUENCY - Define to use a different bus frequency + CONFIG_NOKIA6100_NINTERFACES - Specifies the number of physical Nokia + 6100 devices that will be supported. + CONFIG_NOKIA6100_BPP - Device supports 8, 12, and 16 bits per pixel. + CONFIG_NOKIA6100_S1D15G10 - Selects the Epson S1D15G10 display controller + CONFIG_NOKIA6100_PCF8833 - Selects the Phillips PCF8833 display controller + CONFIG_NOKIA6100_BLINIT - Initial backlight setting + + The following may need to be tuned for your hardware: + CONFIG_NOKIA6100_INVERT - Display inversion, 0 or 1, Default: 1 + CONFIG_NOKIA6100_MY - Display row direction, 0 or 1, Default: 0 + CONFIG_NOKIA6100_MX - Display column direction, 0 or 1, Default: 1 + CONFIG_NOKIA6100_V - Display address direction, 0 or 1, Default: 0 + CONFIG_NOKIA6100_ML - Display scan direction, 0 or 1, Default: 0 + CONFIG_NOKIA6100_RGBORD - Display RGB order, 0 or 1, Default: 0 + + Required LCD driver settings: + CONFIG_LCD_NOKIA6100 - Enable Nokia 6100 support + CONFIG_LCD_MAXCONTRAST - must be 63 with the Epson controller and 127 with + the Phillips controller. + CONFIG_LCD_MAXPOWER - Maximum value of backlight setting. The backlight + control is managed outside of the 6100 driver so this value has no + meaning to the driver. Board-specific logic may place restrictions on + this value. + + Input Devices + + CONFIG_INPUT + Enables general support for input devices + + CONFIG_INPUT_TSC2007 + If CONFIG_INPUT is selected, then this setting will enable building + of the TI TSC2007 touchscreen driver. + CONFIG_TSC2007_MULTIPLE + Normally only a single TI TSC2007 touchscreen is used. But if + there are multiple TSC2007 touchscreens, this setting will enable + multiple touchscreens with the same driver. + + CONFIG_INPUT_STMPE811 + Enables support for the STMPE811 driver (Needs CONFIG_INPUT) + CONFIG_STMPE811_SPI + Enables support for the SPI interface (not currenly supported) + CONFIG_STMPE811_I2C + Enables support for the I2C interface + CONFIG_STMPE811_MULTIPLE + Can be defined to support multiple STMPE811 devices on board. + CONFIG_STMPE811_ACTIVELOW + Interrupt is generated by an active low signal (or falling edge). + CONFIG_STMPE811_EDGE + Interrupt is generated on an edge (vs. on the active level) + CONFIG_STMPE811_NPOLLWAITERS + Maximum number of threads that can be waiting on poll() (ignored if + CONFIG_DISABLE_POLL is set). + CONFIG_STMPE811_TSC_DISABLE + Disable driver touchscreen functionality. + CONFIG_STMPE811_ADC_DISABLE + Disable driver ADC functionality. + CONFIG_STMPE811_GPIO_DISABLE + Disable driver GPIO functionlaity. + CONFIG_STMPE811_GPIOINT_DISABLE + Disable driver GPIO interrupt functionality (ignored if GPIO + functionality is disabled). + CONFIG_STMPE811_SWAPXY + Reverse the meaning of X and Y to handle different LCD orientations. + CONFIG_STMPE811_TEMP_DISABLE + Disable driver temperature sensor functionality. + CONFIG_STMPE811_REGDEBUG + Enabled very low register-level debug output. Requires CONFIG_DEBUG. + CONFIG_STMPE811_THRESHX and CONFIG_STMPE811_THRESHY + STMPE811 touchscreen data comes in a a very high rate. New touch positions + will only be reported when the X or Y data changes by these thresholds. + This trades reduces data rate for some loss in dragging accuracy. The + STMPE811 is configure for 12-bit values so the raw ranges are 0-4095. So + for example, if your display is 320x240, then THRESHX=13 and THRESHY=17 + would correspond to one pixel. Default: 12 + + Analog Devices + + CONFIG_DAC + Enables general support for Digital-to-Analog conversion devices. + CONFIG_ADC + Enables general support for Analog-to-Digital conversion devices. + CONFIG_ADC_ADS125X + Adds support for the TI ADS 125x ADC. + + ENC28J60 Ethernet Driver Configuration Settings: + + CONFIG_NET_ENC28J60 - Enabled ENC28J60 support + CONFIG_ENC28J60_SPIMODE - Controls the SPI mode + CONFIG_ENC28J60_FREQUENCY - Define to use a different bus frequency + CONFIG_ENC28J60_NINTERFACES - Specifies the number of physical ENC28J60 + devices that will be supported. + CONFIG_ENC28J60_STATS - Collect network statistics + CONFIG_ENC28J60_HALFDUPPLEX - Default is full duplex + + Networking support via uIP + + CONFIG_NET - Enable or disable all network features + CONFIG_NET_NOINTS -- CONFIG_NET_NOINT indicates that uIP not called from + the interrupt level. If CONFIG_NET_NOINTS is defined, critical sections + will be managed with semaphores; Otherwise, it assumed that uIP will be + called from interrupt level handling and critical sections will be + managed by enabling and disabling interrupts. + CONFIG_NET_MULTIBUFFER - Traditionally, uIP has used a single buffer + for all incoming and outgoing traffic. If this configuration is + selected, then the driver can manage multiple I/O buffers and can, + for example, be filling one input buffer while sending another + output buffer. Or, as another example, the driver may support + queuing of concurrent input/ouput and output transfers for better + performance. + CONFIG_NET_IPv6 - Build in support for IPv6 + CONFIG_NSOCKET_DESCRIPTORS - Maximum number of socket descriptors + per task/thread. + CONFIG_NET_NACTIVESOCKETS - Maximum number of concurrent socket + operations (recv, send, etc.). Default: CONFIG_NET_TCP_CONNS+CONFIG_NET_UDP_CONNS + CONFIG_NET_SOCKOPTS - Enable or disable support for socket options + + CONFIG_NET_BUFSIZE - uIP buffer size + CONFIG_NET_TCPURGDATA - Determines if support for TCP urgent data + notification should be compiled in. Urgent data (out-of-band data) + is a rarely used TCP feature that is very seldom would be required. + CONFIG_NET_TCP - TCP support on or off + CONFIG_NET_TCP_CONNS - Maximum number of TCP connections (all tasks) + CONFIG_NET_MAX_LISTENPORTS - Maximum number of listening TCP ports (all tasks) + CONFIG_NET_TCP_READAHEAD_BUFSIZE - Size of TCP read-ahead buffers + CONFIG_NET_NTCP_READAHEAD_BUFFERS - Number of TCP read-ahead buffers + (may be zero) + CONFIG_NET_TCPBACKLOG - Incoming connections pend in a backlog until + accept() is called. The size of the backlog is selected when listen() + is called. + CONFIG_NET_UDP - UDP support on or off + CONFIG_NET_UDP_CHECKSUMS - UDP checksums on or off + CONFIG_NET_UDP_CONNS - The maximum amount of concurrent UDP + connections + CONFIG_NET_ICMP - Enable minimal ICMP support. Includes built-in support + for sending replies to received ECHO (ping) requests. + CONFIG_NET_ICMP_PING - Provide interfaces to support application level + support for sending ECHO (ping) requests and associating ECHO + replies. + CONFIG_NET_IGMP - Enable IGMPv2 client support. + CONFIG_PREALLOC_IGMPGROUPS - Pre-allocated IGMP groups are used + only if needed from interrupt level group created (by the IGMP server). + Default: 4. + CONFIG_NET_PINGADDRCONF - Use "ping" packet for setting IP address + CONFIG_NET_STATISTICS - uIP statistics on or off + CONFIG_NET_RECEIVE_WINDOW - The size of the advertised receiver's + window + CONFIG_NET_ARPTAB_SIZE - The size of the ARP table + CONFIG_NET_ARP_IPIN - Harvest IP/MAC address mappings from the ARP table + from incoming IP packets. + CONFIG_NET_BROADCAST - Incoming UDP broadcast support + CONFIG_NET_MULTICAST - Outgoing multi-cast address support + CONFIG_NET_FWCACHE_SIZE - number of packets to remember when + looking for duplicates + + SLIP Driver. SLIP supports point-to-point IP communications over a serial + port. The default data link layer for uIP is Ethernet. If CONFIG_NET_SLIP + is defined in the NuttX configuration file, then SLIP will be supported. + The basic differences between the SLIP and Ethernet configurations is that + when SLIP is selected: + + * The link level header (that comes before the IP header) is omitted. + * All MAC address processing is suppressed. + * ARP is disabled. + + If CONFIG_NET_SLIP is not selected, then Ethernet will be used (there is + no need to define anything special in the configuration file to use + Ethernet -- it is the default). + + CONFIG_NET_SLIP -- Enables building of the SLIP driver. SLIP requires + at least one IP protocols selected and the following additional + network settings: CONFIG_NET_NOINTS and CONFIG_NET_MULTIBUFFER. + CONFIG_NET_BUFSIZE *must* be set to 296. Other optional configuration + settings that affect the SLIP driver: CONFIG_NET_STATISTICS. + Default: Ethernet + + If SLIP is selected, then the following SLIP options are available: + + CONFIG_CLIP_NINTERFACES -- Selects the number of physical SLIP + interfaces to support. Default: 1 + CONFIG_SLIP_STACKSIZE -- Select the stack size of the SLIP RX and + TX tasks. Default: 2048 + CONFIG_SLIP_DEFPRIO - The priority of the SLIP RX and TX tasks. + Default: 128 + + UIP Network Utilities + + CONFIG_NET_DHCP_LIGHT - Reduces size of DHCP + CONFIG_NET_RESOLV_ENTRIES - Number of resolver entries + + THTTPD + + CONFIG_THTTPD_PORT - THTTPD Server port number + CONFIG_THTTPD_IPADDR - Server IP address (no host name) + CONFIG_THTTPD_SERVER_ADDRESS - SERVER_ADDRESS: response + CONFIG_THTTPD_SERVER_SOFTWARE - SERVER_SOFTWARE: response + CONFIG_THTTPD_PATH - Server working directory + CONFIG_THTTPD_CGI_PATH - Path to CGI executables + CONFIG_THTTPD_CGI_PATTERN - Only CGI programs matching this + pattern will be executed. In fact, if this value is not defined + then no CGI logic will be built. + CONFIG_THTTPD_CGI_PRIORITY - Provides the priority of CGI child tasks + CONFIG_THTTPD_CGI_STACKSIZE - Provides the initial stack size of + CGI child task (will be overridden by the stack size in the NXFLAT + header) + CONFIG_THTTPD_CGI_BYTECOUNT - Byte output limit for CGI tasks. + CONFIG_THTTPD_CGI_TIMELIMIT - How many seconds to allow CGI programs + to run before killing them. + CONFIG_THTTPD_CHARSET- The default character set name to use with + text MIME types. + CONFIG_THTTPD_IOBUFFERSIZE - + CONFIG_THTTPD_INDEX_NAMES - A list of index filenames to check. The + files are searched for in this order. + CONFIG_AUTH_FILE - The file to use for authentication. If this is + defined then thttpd checks for this file in the local directory + before every fetch. If the file exists then authentication is done, + otherwise the fetch proceeds as usual. If you leave this undefined + then thttpd will not implement authentication at all and will not + check for auth files, which saves a bit of CPU time. A typical + value is ".htpasswd" + CONFIG_THTTPD_LISTEN_BACKLOG - The listen() backlog queue length. + CONFIG_THTTPD_LINGER_MSEC - How many milliseconds to leave a connection + open while doing a lingering close. + CONFIG_THTTPD_OCCASIONAL_MSEC - How often to run the occasional + cleanup job. + CONFIG_THTTPD_IDLE_READ_LIMIT_SEC - How many seconds to allow for + reading the initial request on a new connection. + CONFIG_THTTPD_IDLE_SEND_LIMIT_SEC - How many seconds before an + idle connection gets closed. + CONFIG_THTTPD_TILDE_MAP1 and CONFIG_THTTPD_TILDE_MAP2 - Tilde mapping. + Many URLs use ~username to indicate a user's home directory. thttpd + provides two options for mapping this construct to an actual filename. + 1) Map ~username to /username. This is the recommended choice. + Each user gets a subdirectory in the main web tree, and the tilde + construct points there. The prefix could be something like "users", + or it could be empty. + 2) Map ~username to /. The postfix would be + the name of a subdirectory off of the user's actual home dir, + something like "public_html". + You can also leave both options undefined, and thttpd will not do + anything special about tildes. Enabling both options is an error. + Typical values, if they're defined, are "users" for + CONFIG_THTTPD_TILDE_MAP1 and "public_html"forCONFIG_THTTPD_TILDE_MAP2. + CONFIG_THTTPD_GENERATE_INDICES + CONFIG_THTTPD_URLPATTERN - If defined, then it will be used to match + and verify referrers. + + FTP Server + + CONFIG_FTPD_VENDORID - The vendor name to use in FTP communications. + Default: "NuttX" + CONFIG_FTPD_SERVERID - The server name to use in FTP communications. + Default: "NuttX FTP Server" + CONFIG_FTPD_CMDBUFFERSIZE - The maximum size of one command. Default: + 128 bytes. + CONFIG_FTPD_DATABUFFERSIZE - The size of the I/O buffer for data + transfers. Default: 512 bytes. + CONFIG_FTPD_WORKERSTACKSIZE - The stacksize to allocate for each + FTP daemon worker thread. Default: 2048 bytes. + + Other required configuration settings: Of course TCP networking support + is required. But here are a couple that are less obvious: + + CONFIG_DISABLE_PTHREAD - pthread support is required + CONFIG_DISABLE_POLL - poll() support is required + + USB device controller driver + + CONFIG_USBDEV - Enables USB device support + CONFIG_USBDEV_COMPOSITE + Enables USB composite device support + CONFIG_USBDEV_ISOCHRONOUS - Build in extra support for isochronous + endpoints + CONFIG_USBDEV_DUALSPEED -Hardware handles high and full speed + operation (USB 2.0) + CONFIG_USBDEV_SELFPOWERED - Will cause USB features to indicate + that the device is self-powered + CONFIG_USBDEV_MAXPOWER - Maximum power consumption in mA + CONFIG_USBDEV_TRACE - Enables USB tracing for debug + CONFIG_USBDEV_TRACE_NRECORDS - Number of trace entries to remember + + USB host controller driver + + CONFIG_USBHOST + Enables USB host support + CONFIG_USBHOST_NPREALLOC + Number of pre-allocated class instances + CONFIG_USBHOST_BULK_DISABLE + On some architectures, selecting this setting will reduce driver size + by disabling bulk endpoint support + CONFIG_USBHOST_INT_DISABLE + On some architectures, selecting this setting will reduce driver size + by disabling interrupt endpoint support + CONFIG_USBHOST_ISOC_DISABLE + On some architectures, selecting this setting will reduce driver size + by disabling isochronous endpoint support + + USB host HID class driver. Requires CONFIG_USBHOST=y, + CONFIG_USBHOST_INT_DISABLE=n, CONFIG_NFILE_DESCRIPTORS > 0, + CONFIG_SCHED_WORKQUEUE=y, and CONFIG_DISABLE_SIGNALS=n. + + CONFIG_HIDKBD_POLLUSEC + Device poll rate in microseconds. Default: 100 milliseconds. + CONFIG_HIDKBD_DEFPRIO + Priority of the polling thread. Default: 50. + CONFIG_HIDKBD_STACKSIZE + Stack size for polling thread. Default: 1024 + CONFIG_HIDKBD_BUFSIZE + Scancode buffer size. Default: 64. + CONFIG_HIDKBD_NPOLLWAITERS + If the poll() method is enabled, this defines the maximum number + of threads that can be waiting for keyboard events. Default: 2. + CONFIG_HIDKBD_RAWSCANCODES + If set to y no conversion will be made on the raw keyboard scan + codes. Default: ASCII conversion. + CONFIG_HIDKBD_ALLSCANCODES' + If set to y all 231 possible scancodes will be converted to + something. Default: 104 key US keyboard. + CONFIG_HIDKBD_NODEBOUNCE + If set to y normal debouncing is disabled. Default: + Debounce enabled (No repeat keys). + + USB host mass storage class driver. Requires CONFIG_USBHOST=y, + CONFIG_USBHOST_BULK_DISABLE=n, CONFIG_NFILE_DESCRIPTORS > 0, + and CONFIG_SCHED_WORKQUEUE=y + + USB serial device class driver (Prolific PL2303 Emulation) + + CONFIG_PL2303 + Enable compilation of the USB serial driver + CONFIG_PL2303_EPINTIN + The logical 7-bit address of a hardware endpoint that supports + interrupt IN operation + CONFIG_PL2303_EPBULKOUT + The logical 7-bit address of a hardware endpoint that supports + bulk OUT operation + CONFIG_PL2303_EPBULKIN + The logical 7-bit address of a hardware endpoint that supports + bulk IN operation + CONFIG_PL2303_NWRREQS and CONFIG_PL2303_NRDREQS + The number of write/read requests that can be in flight + CONFIG_PL2303_VENDORID and CONFIG_PL2303_VENDORSTR + The vendor ID code/string + CONFIG_PL2303_PRODUCTID and CONFIG_PL2303_PRODUCTSTR + The product ID code/string + CONFIG_PL2303_RXBUFSIZE and CONFIG_PL2303_TXBUFSIZE + Size of the serial receive/transmit buffers + + USB serial device class driver (Standard CDC ACM class) + + CONFIG_CDCACM + Enable compilation of the USB serial driver + CONFIG_CDCACM_COMPOSITE + Configure the CDC serial driver as part of a composite driver + (only if CONFIG_USBDEV_COMPOSITE is also defined) + CONFIG_CDCACM_IFNOBASE + If the CDC driver is part of a composite device, then this may need to + be defined to offset the CDC/ACM interface numbers so that they are + unique and contiguous. When used with the Mass Storage driver, the + correct value for this offset is zero. + CONFIG_CDCACM_STRBASE + If the CDC driver is part of a composite device, then this may need to + be defined to offset the CDC/ACM string numbers so that they are + unique and contiguous. When used with the Mass Storage driver, the + correct value for this offset is four (this value actuallly only needs + to be defined if names are provided for the Notification interface, + CONFIG_CDCACM_NOTIFSTR, or the data interface, CONFIG_CDCACM_DATAIFSTR). + CONFIG_CDCACM_EP0MAXPACKET + Endpoint 0 max packet size. Default 64. + CONFIG_CDCACM_EPINTIN + The logical 7-bit address of a hardware endpoint that supports + interrupt IN operation. Default 2. + CONFIG_CDCACM_EPINTIN_FSSIZE + Max package size for the interrupt IN endpoint if full speed mode. + Default 64. + CONFIG_CDCACM_EPINTIN_HSSIZE + Max package size for the interrupt IN endpoint if high speed mode. + Default 64. + CONFIG_CDCACM_EPBULKOUT + The logical 7-bit address of a hardware endpoint that supports + bulk OUT operation + CONFIG_CDCACM_EPBULKOUT_FSSIZE + Max package size for the bulk OUT endpoint if full speed mode. + Default 64. + CONFIG_CDCACM_EPBULKOUT_HSSIZE + Max package size for the bulk OUT endpoint if high speed mode. + Default 512. + CONFIG_CDCACM_EPBULKIN + The logical 7-bit address of a hardware endpoint that supports + bulk IN operation + CONFIG_CDCACM_EPBULKIN_FSSIZE + Max package size for the bulk IN endpoint if full speed mode. + Default 64. + CONFIG_CDCACM_EPBULKIN_HSSIZE + Max package size for the bulk IN endpoint if high speed mode. + Default 512. + CONFIG_CDCACM_NWRREQS and CONFIG_CDCACM_NRDREQS + The number of write/read requests that can be in flight. + CONFIG_CDCACM_NWRREQS includes write requests used for both the + interrupt and bulk IN endpoints. Default 4. + CONFIG_CDCACM_VENDORID and CONFIG_CDCACM_VENDORSTR + The vendor ID code/string. Default 0x0525 and "NuttX" + 0x0525 is the Netchip vendor and should not be used in any + products. This default VID was selected for compatibility with + the Linux CDC ACM default VID. + CONFIG_CDCACM_PRODUCTID and CONFIG_CDCACM_PRODUCTSTR + The product ID code/string. Default 0xa4a7 and "CDC/ACM Serial" + 0xa4a7 was selected for compatibility with the Linux CDC ACM + default PID. + CONFIG_CDCACM_RXBUFSIZE and CONFIG_CDCACM_TXBUFSIZE + Size of the serial receive/transmit buffers. Default 256. + + USB Storage Device Configuration + + CONFIG_USBMSC + Enable compilation of the USB storage driver + CONFIG_USBMSC_COMPOSITE + Configure the mass storage driver as part of a composite driver + (only if CONFIG_USBDEV_COMPOSITE is also defined) + CONFIG_USBMSC_IFNOBASE + If the CDC driver is part of a composite device, then this may need to + be defined to offset the mass storage interface number so that it is + unique and contiguous. When used with the CDC/ACM driver, the + correct value for this offset is two (because of the two CDC/ACM + interfaces that will precede it). + CONFIG_USBMSC_STRBASE + If the CDC driver is part of a composite device, then this may need to + be defined to offset the mass storage string numbers so that they are + unique and contiguous. When used with the CDC/ACM driver, the + correct value for this offset is four (or perhaps 5 or 6, depending + on if CONFIG_CDCACM_NOTIFSTR or CONFIG_CDCACM_DATAIFSTR are defined). + CONFIG_USBMSC_EP0MAXPACKET + Max packet size for endpoint 0 + CONFIG_USBMSCEPBULKOUT and CONFIG_USBMSC_EPBULKIN + The logical 7-bit address of a hardware endpoints that support + bulk OUT and IN operations + CONFIG_USBMSC_NWRREQS and CONFIG_USBMSC_NRDREQS + The number of write/read requests that can be in flight + CONFIG_USBMSC_BULKINREQLEN and CONFIG_USBMSC_BULKOUTREQLEN + The size of the buffer in each write/read request. This + value needs to be at least as large as the endpoint + maxpacket and ideally as large as a block device sector. + CONFIG_USBMSC_VENDORID and CONFIG_USBMSC_VENDORSTR + The vendor ID code/string + CONFIG_USBMSC_PRODUCTID and CONFIG_USBMSC_PRODUCTSTR + The product ID code/string + CONFIG_USBMSC_REMOVABLE + Select if the media is removable + + USB Composite Device Configuration + + CONFIG_USBDEV_COMPOSITE + Enables USB composite device support + CONFIG_CDCACM_COMPOSITE + Configure the CDC serial driver as part of a composite driver + (only if CONFIG_USBDEV_COMPOSITE is also defined) + CONFIG_USBMSC_COMPOSITE + Configure the mass storage driver as part of a composite driver + (only if CONFIG_USBDEV_COMPOSITE is also defined) + CONFIG_COMPOSITE_IAD + If one of the members of the composite has multiple interfaces + (such as CDC/ACM), then an Interface Association Descriptor (IAD) + will be necessary. Default: IAD will be used automatically if + needed. It should not be necessary to set this. + CONFIG_COMPOSITE_EP0MAXPACKET + Max packet size for endpoint 0 + CONFIG_COMPOSITE_VENDORID and CONFIG_COMPOSITE_VENDORSTR + The vendor ID code/string + CONFIG_COMPOSITE_PRODUCTID and CONFIG_COMPOSITE_PRODUCTSTR + The product ID code/string + CONFIG_COMPOSITE_SERIALSTR + Device serial number string + CONFIG_COMPOSITE_CONFIGSTR + Configuration string + CONFIG_COMPOSITE_VERSIONNO + Interface version number. + + Graphics related configuration settings + + CONFIG_NX + Enables overall support for graphics library and NX + CONFIG_NX_MULTIUSER + Configures NX in multi-user mode + CONFIG_NX_NPLANES + Some YUV color formats requires support for multiple planes, + one for each color component. Unless you have such special + hardware, this value should be undefined or set to 1. + CONFIG_NX_DISABLE_1BPP, CONFIG_NX_DISABLE_2BPP, + CONFIG_NX_DISABLE_4BPP, CONFIG_NX_DISABLE_8BPP, + CONFIG_NX_DISABLE_16BPP, CONFIG_NX_DISABLE_24BPP, and + CONFIG_NX_DISABLE_32BPP + NX supports a variety of pixel depths. You can save some + memory by disabling support for unused color depths. + CONFIG_NX_PACKEDMSFIRST + If a pixel depth of less than 8-bits is used, then NX needs + to know if the pixels pack from the MS to LS or from LS to MS + CONFIG_NX_LCDDRIVER + By default, NX builds to use a framebuffer driver (see + include/nuttx/fb.h). If this option is defined, NX will + build to use an LCD driver (see include/nuttx/lcd/lcd.h). + CONFIG_LCD_MAXPOWER - The full-on power setting for an LCD + device. + CONFIG_LCD_MAXCONTRAST - The maximum contrast value for an + LCD device. + CONFIG_LCD_LANDSCAPE, CONFIG_LCD_PORTRAIT, CONFIG_LCD_RLANDSCAPE, + and CONFIG_LCD_RPORTRAIT - Some LCD drivers may support + these options to present the display in landscape, portrait, + reverse landscape, or reverse portrait orientations. Check + the README.txt file in each board configuration directory to + see if any of these are supported by the board LCD logic. + CONFIG_NX_MOUSE + Build in support for mouse input. + CONFIG_NX_KBD + Build in support of keypad/keyboard input. + CONFIG_NXTK_BORDERWIDTH + Specifies with with of the border (in pixels) used with + framed windows. The default is 4. + CONFIG_NXTK_BORDERCOLOR1 and CONFIG_NXTK_BORDERCOLOR2 + Specify the colors of the border used with framed windows. + CONFIG_NXTK_BORDERCOLOR2 is the shadow side color and so + is normally darker. The default is medium and dark grey, + respectively + CONFIG_NXTK_AUTORAISE + If set, a window will be raised to the top if the mouse position + is over a visible portion of the window. Default: A mouse + button must be clicked over a visible portion of the window. + CONFIG_NXFONTS_CHARBITS + The number of bits in the character set. Current options are + only 7 and 8. The default is 7. + + CONFIG_NXFONT_SANS23X27 + This option enables support for a tiny, 23x27 san serif font + (font ID FONTID_SANS23X27 == 1). + CONFIG_NXFONT_SANS22X29 + This option enables support for a small, 22x29 san serif font + (font ID FONTID_SANS22X29 == 2). + CONFIG_NXFONT_SANS28X37 + This option enables support for a medium, 28x37 san serif font + (font ID FONTID_SANS28X37 == 3). + CONFIG_NXFONT_SANS39X48 + This option enables support for a large, 39x48 san serif font + (font ID FONTID_SANS39X48 == 4). + CONFIG_NXFONT_SANS22X29B + This option enables support for a small, 22x29 san serif bold font + (font ID FONTID_SANS22X29B == 5). + CONFIG_NXFONT_SANS28X37B + This option enables support for a medium, 28x37 san serif bold font + (font ID FONTID_SANS28X37B == 6). + CONFIG_NXFONT_SANS40X49B + This option enables support for a large, 40x49 san serif bold font + (font ID FONTID_SANS40X49B == 7). + CONFIG_NXFONT_SERIF22X29 + This option enables support for a small, 22x29 font (with serifs) + (font ID FONTID_SERIF22X29 == 8). + CONFIG_NXFONT_SERIF29X37 + This option enables support for a medium, 29x37 font (with serifs) + (font ID FONTID_SERIF29X37 == 9). + CONFIG_NXFONT_SERIF38X48 + This option enables support for a large, 38x48 font (with serifs) + (font ID FONTID_SERIF38X48 == 10). + CONFIG_NXFONT_SERIF22X28B + This option enables support for a small, 27x38 bold font (with serifs) + (font ID FONTID_SERIF22X28B == 11). + CONFIG_NXFONT_SERIF27X38B + This option enables support for a medium, 27x38 bold font (with serifs) + (font ID FONTID_SERIF27X38B == 12). + CONFIG_NXFONT_SERIF38X49B + This option enables support for a large, 38x49 bold font (with serifs) + (font ID FONTID_SERIF38X49B == 13). + + NX Multi-user only options: + + CONFIG_NX_BLOCKING + Open the client message queues in blocking mode. In this case, + nx_eventhandler() will never return. + CONFIG_NX_MXSERVERMSGS and CONFIG_NX_MXCLIENTMSGS + Specifies the maximum number of messages that can fit in + the message queues. No additional resources are allocated, but + this can be set to prevent flooding of the client or server with + too many messages (CONFIG_PREALLOC_MQ_MSGS controls how many + messages are pre-allocated). + + Stack and heap information + + CONFIG_BOOT_RUNFROMFLASH - Some configurations support XIP + operation from FLASH but must copy initialized .data sections to RAM. + CONFIG_BOOT_COPYTORAM - Some configurations boot in FLASH + but copy themselves entirely into RAM for better performance. + CONFIG_BOOT_RAMFUNCS - Other configurations may copy just some functions + into RAM, either for better performance or for errata workarounds. + CONFIG_STACK_POINTER - The initial stack pointer (may not be supported + in all architectures). + CONFIG_STACK_ALIGNMENT - Set if the your application has specific + stack alignment requirements (may not be supported + in all architectures). + CONFIG_IDLETHREAD_STACKSIZE - The size of the initial stack. + This is the thread that (1) performs the inital boot of the system up + to the point where user_start() is spawned, and (2) there after is the + IDLE thread that executes only when there is no other thread ready to + run. + CONFIG_USERMAIN_STACKSIZE - The size of the stack to allocate + for the main user thread that begins at the user_start() entry point. + CONFIG_PTHREAD_STACK_MIN - Minimum pthread stack size + CONFIG_PTHREAD_STACK_DEFAULT - Default pthread stack size + CONFIG_HEAP_BASE - The beginning of the heap + CONFIG_HEAP_SIZE - The size of the heap + +appconfig -- This is another configuration file that is specific to the + application. This file is copied into the application build directory + when NuttX is configured. See ../apps/README.txt for further details. + +setenv.sh -- This is a script that you can include that will be installed at + the toplevel of the directory structure and can be sourced to set any + necessary environment variables. You will most likely have to customize the + default setenv.sh script in order for it to work correctly in your + environment. + +Supported Boards +^^^^^^^^^^^^^^^^ + +configs/amber + This is placeholder for the SoC Robotics Amber Web Server that is based + on the Atmel AVR ATMega128 MCU. There is not much there yet and what is + there is untested due to tool-related issues. + +configs/avr32dev1 + This is a port of NuttX to the Atmel AVR32DEV1 board. That board is + based on the Atmel AT32UC3B0256 MCU and uses a specially patched + version of the GNU toolchain: The patches provide support for the + AVR32 family. That patched GNU toolchain is available only from the + Atmel website. STATUS: This port is functional but very basic. There + are configurations for NSH and the OS test. + +configs/c5471evm + This is a port to the Spectrum Digital C5471 evaluation board. The + TMS320C5471 is a dual core processor from TI with an ARM7TDMI general + purpose processor and a c54 DSP. It is also known as TMS320DA180 or just DA180. + NuttX runs on the ARM core and is built with a GNU arm-elf toolchain*. + This port is complete and verified. + +configs/compal_e88 and compal_e99 + These directories contain the board support for compal e88 and e99 phones. + These ports are based on patches contributed by Denis Carikli for both the + compal e99 and e88. The patches were made by Alan Carvalho de Assis and + Denis Carikli using the Stefan Richter's Osmocom-bb patches. + +configs/demo9s12ne64 + Freescale DMO9S12NE64 board based on the MC9S12NE64 hcs12 cpu. This + port uses the m9s12x GCC toolchain. STATUS: (Still) under development; it + is code complete but has not yet been verified. + +configs/ea3131 + Embedded Artists EA3131 Development board. This board is based on the + an NXP LPC3131 MCU. This OS is built with the arm-elf toolchain*. + STATUS: This port is complete and mature. + +configs/ea3152 + Embedded Artists EA3152 Development board. This board is based on the + an NXP LPC3152 MCU. This OS is built with the arm-elf toolchain*. + STATUS: This port is has not be exercised well, but since it is + a simple derivative of the ea3131, it should be fully functional. + +configs/eagle100 + Micromint Eagle-100 Development board. This board is based on the + an ARM Cortex-M3 MCU, the Luminary LM3S6918. This OS is built with the + arm-elf toolchain*. STATUS: This port is complete and mature. + +configs/ekk-lm3s9b96 + TI/Stellaris EKK-LM3S9B96 board. This board is based on the + an EKK-LM3S9B96 which is a Cortex-M3. + +configs/ez80f0910200kitg + ez80Acclaim! Microcontroller. This port use the Zilog ez80f0910200kitg + development kit, eZ80F091 part, and the Zilog ZDS-II Windows command line + tools. The development environment is Cygwin under WinXP. + +configs/ez80f0910200zco + ez80Acclaim! Microcontroller. This port use the Zilog ez80f0910200zco + development kit, eZ80F091 part, and the Zilog ZDS-II Windows command line + tools. The development environment is Cygwin under WinXP. + +configs/hymini-stm32v + A configuration for the HY-Mini STM32v board. This board is based on the + STM32F103VCT chip. + +configs/kwikstik-k40. + Kinetis K40 Cortex-M4 MCU. This port uses the FreeScale KwikStik-K40 + development board. + +configs/lincoln60 + NuttX port to the Micromint Lincoln 60 board. + +configs/lm3s6432-s2e + Stellaris RDK-S2E Reference Design Kit and the MDL-S2E Ethernet to + Serial module. + +configs/lm3s6965-ek + Stellaris LM3S6965 Evaluation Kit. This board is based on the + an ARM Cortex-M3 MCU, the Luminary/TI LM3S6965. This OS is built with the + arm-elf toolchain*. STATUS: This port is complete and mature. + +configs/lm3s8962-ek + Stellaris LMS38962 Evaluation Kit. + +configs/lpcxpresso-lpc1768 + Embedded Artists base board with NXP LPCExpresso LPC1768. This board + is based on the NXP LPC1768. The Code Red toolchain is used by default. + STATUS: Under development. + +configs/lpc4330-xplorer + NuttX port to the LPC4330-Xplorer board from NGX Technologies featuring + the NXP LPC4330FET100 MCU + +configs/m68322evb + This is a work in progress for the venerable m68322evb board from + Motorola. This OS is also built with the arm-elf toolchain*. STATUS: + This port was never completed. + +configs/mbed + The configurations in this directory support the mbed board (http://mbed.org) + that features the NXP LPC1768 microcontroller. This OS is also built + with the arm-elf toolchain*. STATUS: Contributed. + +configs/mcu123-lpc214x + This port is for the NXP LPC2148 as provided on the mcu123.com + lpc214x development board. This OS is also built with the arm-elf + toolchain*. The port supports serial, timer0, spi, and usb. + +configs/micropendous3 + This is a port to the Opendous Micropendous 3 board. This board may + be populated with either an AVR AT90USB646, 647, 1286, or 1287 MCU. + Support is configured for the AT90USB647. + +configs/mirtoo + This is the port to the DTX1-4000L "Mirtoo" module. This module uses MicroChip + PIC32MX250F128D. See http://www.dimitech.com/ for further information. + +configs/mx1ads + This is a port to the Motorola MX1ADS development board. That board + is based on the Freescale i.MX1 processor. The i.MX1 is an ARM920T. + STATUS: This port is nearly code complete but was never fully + integrated due to tool-related issues. + +configs/ne64badge + Future Electronics Group NE64 /PoE Badge board based on the + MC9S12NE64 hcs12 cpu. This port uses the m9s12x GCC toolchain. + STATUS: Under development. The port is code-complete but has + not yet been fully tested. + +configs/ntosd-dm320 + This port uses the Neuros OSD v1.0 Dev Board with a GNU arm-elf + toolchain*: see + + http://wiki.neurostechnology.com/index.php/OSD_1.0_Developer_Home + + There are some differences between the Dev Board and the currently + available commercial v1.0 Boards. See + + http://wiki.neurostechnology.com/index.php/OSD_Developer_Board_v1 + + NuttX operates on the ARM9EJS of this dual core processor. + STATUS: This port is code complete, verified, and included in the + NuttX 0.2.1 release. + +configs/nucleus2g + This port uses the Nucleus 2G board (with Babel CAN board). This board + features an NXP LPC1768 processor. See the 2G website (http://www.2g-eng.com/) + for more information about the Nucleus 2G. + +configs/olimex-lpc1766stk + This port uses the Olimex LPC1766-STK board and a GNU GCC toolchain* under + Linux or Cygwin. STATUS: Complete and mature. + +configs/olimex-lpc2378 + This port uses the Olimex-lpc2378 board and a GNU arm-elf toolchain* under + Linux or Cygwin. STATUS: ostest and NSH configurations available. + This port for the NXP LPC2378 was contributed by Rommel Marcelo. + +configs/olimex-strp711 + This port uses the Olimex STR-P711 board and a GNU arm-elf toolchain* under + Linux or Cygwin. See the http://www.olimex.com/dev/str-p711.html" for + further information. STATUS: Configurations for the basic OS test and NSH + are complete and verified. + +configs/pcblogic-pic32mx + This is the port of NuttX to the PIC32MX board from PCB Logic Design Co. + This board features the MicroChip PIC32MX460F512L. + The board is a very simple -- little more than a carrier for the PIC32 + MCU plus voltage regulation, debug interface, and an OTG connector. + STATUS: Code complete but testing has been stalled due to tool related problems + (PICkit 2 does not work with the PIC32). + +configs/pic32-starterkit + + This directory contains the port of NuttX to the Microchip PIC32 Ethernet + Starter Kit (DM320004) with the Multimedia Expansion Board (MEB, DM320005). + See www.microchip.com for further information. + +configs/pic32mx7mmb + + This directory will (eventually) contain the port of NuttX to the + Mikroelektronika PIC32MX7 Multimedia Board (MMB). See + http://www.mikroe.com/ for further information. + + STATUS: Basic OS test configuration is in place, but the board does not boot. + It looks like I will need an ICD3 in order to debug the code (PICkit3 + doesn't work for debug with this board). This effort is temporarily stalled. + +configs/pjrc-8051 + 8051 Microcontroller. This port uses the PJRC 87C52 development system + and the SDCC toolchain. This port is not quite ready for prime time. + +configs/qemu-i486 + + Port of NuttX to QEMU in i486 mode. This port will also run on real i486 + hardwared (Google the Bifferboard). + +configs/rgmp + RGMP stands for RTOS and GPOS on Multi-Processor. RGMP is a project for + running GPOS and RTOS simultaneously on multi-processor platforms. You can + port your favorite RTOS to RGMP together with an unmodified Linux to form a + hybrid operating system. This makes your application able to use both RTOS + and GPOS features. + + See http://rgmp.sourceforge.net/wiki/index.php/Main_Page for further information + about RGMP. + +configs/sam3u-ek + The port of NuttX to the Atmel SAM3U-EK development board. + +configs/sim + A user-mode port of NuttX to the x86 Linux platform is available. + The purpose of this port is primarily to support OS feature development. + This port does not support interrupts or a real timer (and hence no + round robin scheduler) Otherwise, it is complete. + +configs/skp16c26 + Renesas M16C processor on the Renesas SKP16C26 StarterKit. This port + uses the GNU m32c toolchain. STATUS: The port is complete but untested + due to issues with compiler internal errors. + +configs/stm3210e-eval + STMicro STM3210E-EVAL development board based on the STMicro STM32F103ZET6 + microcontroller (ARM Cortex-M3). This port uses the GNU Cortex-M3 + toolchain. + +configs/stm3220g-eval + STMicro STM3220G-EVAL development board based on the STMicro STM32F407IG + microcontroller (ARM Cortex-M3). + +configs/stm3240g-eval + STMicro STM3240G-EVAL development board based on the STMicro STM32F103ZET6 + microcontroller (ARM Cortex-M4 with FPU). This port uses a GNU Cortex-M4 + toolchain (such as CodeSourcery). + +configs/stm32f4discovery + STMicro STM32F4-Discovery board boased on the STMIcro STM32F407VGT6 MCU. + +configs/sure-pic32mx + The "Advanced USB Storage Demo Board," Model DB-DP11215, from Sure + Electronics (http://www.sureelectronics.net/). This board features + the MicroChip PIC32MX440F512H. See also + http://www.sureelectronics.net/goods.php?id=1168 for further + information about the Sure DB-DP11215 board. + +configs/teensy + This is the port of NuttX to the PJRC Teensy++ 2.0 board. This board is + developed by http://pjrc.com/teensy/. The Teensy++ 2.0 is based + on an Atmel AT90USB1286 MCU. + +configs/twr-k60n512 + Kinetis K60 Cortex-M4 MCU. This port uses the FreeScale TWR-K60N512 + development board. + +configs/ubw32 + + This is the port to the Sparkfun UBW32 board. This port uses the original v2.4 + board which is based on the MicroChip PIC32MX460F512L. See + http://www.sparkfun.com/products/8971. This older version has been replaced + with this board http://www.sparkfun.com/products/9713. See also + http://www.schmalzhaus.com/UBW32/. + +configs/us7032evb1 + This is a port of the Hitachi SH-1 on the Hitachi SH-1/US7032EVB1 board. + STATUS: Work has just began on this port. + +configs/vsn + ISOTEL NetClamps VSN V1.2 ready2go sensor network platform based on the + STMicro STM32F103RET6. Contributed by Uros Platise. See + http://isotel.eu/NetClamps/ + +configs/xtrs + TRS80 Model 3. This port uses a vintage computer based on the Z80. + An emulator for this computer is available to run TRS80 programs on a + linux platform (http://www.tim-mann.org/xtrs.html). + +configs/z16f2800100zcog + z16f Microcontroller. This port use the Zilog z16f2800100zcog + development kit and the Zilog ZDS-II Windows command line tools. The + development environment is Cygwin under WinXP. + +configs/z80sim + z80 Microcontroller. This port uses a Z80 instruction set simulator. + That simulator can be found in the NuttX SVN at + http://nuttx.svn.sourceforge.net/viewvc/nuttx/trunk/misc/sims/z80sim. + This port also uses the SDCC toolchain (http://sdcc.sourceforge.net/") + (verified with version 2.6.0). + +configs/z8encore000zco + z8Encore! Microcontroller. This port use the Zilog z8encore000zco + development kit, Z8F6403 part, and the Zilog ZDS-II Windows command line + tools. The development environment is Cygwin under WinXP. + +configs/z8f64200100kit + z8Encore! Microcontroller. This port use the Zilog z8f64200100kit + development kit, Z8F6423 part, and the Zilog ZDS-II Windows command line + tools. The development environment is Cygwin under WinXP. + +Configuring NuttX +^^^^^^^^^^^^^^^^^ + +Configuring NuttX requires only copying + + configs///Make.def to ${TOPDIR}/Make.defs + configs///setenv.sh to ${TOPDIR}/setenv.sh + configs///defconfig to ${TOPDIR}/.config + +And if configs///appconfig exists in the board +configuration directory: + + Copy configs///appconfig to /.config + echo "APPS_LOC=\"\"" >> "${TOPDIR}/.config" + +tools/configure.sh + There is a script that automates these steps. The following steps will + accomplish the same configuration: + + cd tools + ./configure.sh / + +And if configs///appconfig exists and your +application directory is not in the standard loction (../apps), then +you should also specify the location of the application directory on the +command line like: + + cd tools + ./configure.sh -a / diff --git a/nuttx/configs/px4fmu/README.txt b/nuttx/configs/px4fmu/README.txt new file mode 100755 index 0000000000..c92169206b --- /dev/null +++ b/nuttx/configs/px4fmu/README.txt @@ -0,0 +1,601 @@ +README +====== + +This README discusses issues unique to NuttX configurations for the +PX4FMU development board. + +Or, it will once those are established. For now, this is a copy of the file +as presented for the STMicro STM32F407 evaluation board. Read with caution. + +Contents +======== + + - Development Environment + - GNU Toolchain Options + - IDEs + - NuttX buildroot Toolchain + - STM3240G-EVAL-specific Configuration Options + - LEDs + - Ethernet + - PWM + - CAN + - Configurations + +Development Environment +======================= + + Either Linux or Cygwin on Windows can be used for the development environment. + The source has been built only using the GNU toolchain (see below). Other + toolchains will likely cause problems. Testing was performed using the Cygwin + environment because the Raisonance R-Link emulatator and some RIDE7 development tools + were used and those tools works only under Windows. + +GNU Toolchain Options +===================== + + The NuttX make system has been modified to support the following different + toolchain options. + + 1. The CodeSourcery GNU toolchain, + 2. The devkitARM GNU toolchain, + 3. Raisonance GNU toolchain, or + 4. The NuttX buildroot Toolchain (see below). + + All testing has been conducted using the CodeSourcery toolchain for Windows. To use + the devkitARM, Raisonance GNU, or NuttX buildroot toolchain, you simply need to + add one of the following configuration options to your .config (or defconfig) + file: + + CONFIG_STM32_CODESOURCERYW=y : CodeSourcery under Windows + CONFIG_STM32_CODESOURCERYL=y : CodeSourcery under Linux + CONFIG_STM32_DEVKITARM=y : devkitARM under Windows + CONFIG_STM32_RAISONANCE=y : Raisonance RIDE7 under Windows + CONFIG_STM32_BUILDROOT=y : NuttX buildroot under Linux or Cygwin (default) + + If you change the default toolchain, then you may also have to modify the PATH in + the setenv.h file if your make cannot find the tools. + + NOTE: the CodeSourcery (for Windows), devkitARM, and Raisonance toolchains are + Windows native toolchains. The CodeSourcey (for Linux) and NuttX buildroot + toolchains are Cygwin and/or Linux native toolchains. There are several limitations + to using a Windows based toolchain in a Cygwin environment. The three biggest are: + + 1. The Windows toolchain cannot follow Cygwin paths. Path conversions are + performed automatically in the Cygwin makefiles using the 'cygpath' utility + but you might easily find some new path problems. If so, check out 'cygpath -w' + + 2. Windows toolchains cannot follow Cygwin symbolic links. Many symbolic links + are used in Nuttx (e.g., include/arch). The make system works around these + problems for the Windows tools by copying directories instead of linking them. + But this can also cause some confusion for you: For example, you may edit + a file in a "linked" directory and find that your changes had no effect. + That is because you are building the copy of the file in the "fake" symbolic + directory. If you use a Windows toolchain, you should get in the habit of + making like this: + + make clean_context all + + An alias in your .bashrc file might make that less painful. + + 3. Dependencies are not made when using Windows versions of the GCC. This is + because the dependencies are generated using Windows pathes which do not + work with the Cygwin make. + + Support has been added for making dependencies with the windows-native toolchains. + That support can be enabled by modifying your Make.defs file as follows: + + - MKDEP = $(TOPDIR)/tools/mknulldeps.sh + + MKDEP = $(TOPDIR)/tools/mkdeps.sh --winpaths "$(TOPDIR)" + + If you have problems with the dependency build (for example, if you are not + building on C:), then you may need to modify tools/mkdeps.sh + + NOTE 1: The CodeSourcery toolchain (2009q1) does not work with default optimization + level of -Os (See Make.defs). It will work with -O0, -O1, or -O2, but not with + -Os. + + NOTE 2: The devkitARM toolchain includes a version of MSYS make. Make sure that + the paths to Cygwin's /bin and /usr/bin directories appear BEFORE the devkitARM + path or will get the wrong version of make. + +IDEs +==== + + NuttX is built using command-line make. It can be used with an IDE, but some + effort will be required to create the project. + + Makefile Build + -------------- + Under Eclipse, it is pretty easy to set up an "empty makefile project" and + simply use the NuttX makefile to build the system. That is almost for free + under Linux. Under Windows, you will need to set up the "Cygwin GCC" empty + makefile project in order to work with Windows (Google for "Eclipse Cygwin" - + there is a lot of help on the internet). + + Native Build + ------------ + Here are a few tips before you start that effort: + + 1) Select the toolchain that you will be using in your .config file + 2) Start the NuttX build at least one time from the Cygwin command line + before trying to create your project. This is necessary to create + certain auto-generated files and directories that will be needed. + 3) Set up include pathes: You will need include/, arch/arm/src/stm32, + arch/arm/src/common, arch/arm/src/armv7-m, and sched/. + 4) All assembly files need to have the definition option -D __ASSEMBLY__ + on the command line. + + Startup files will probably cause you some headaches. The NuttX startup file + is arch/arm/src/stm32/stm32_vectors.S. With RIDE, I have to build NuttX + one time from the Cygwin command line in order to obtain the pre-built + startup object needed by RIDE. + +NuttX buildroot Toolchain +========================= + + A GNU GCC-based toolchain is assumed. The files */setenv.sh should + be modified to point to the correct path to the Cortex-M3 GCC toolchain (if + different from the default in your PATH variable). + + If you have no Cortex-M3 toolchain, one can be downloaded from the NuttX + SourceForge download site (https://sourceforge.net/project/showfiles.php?group_id=189573). + This GNU toolchain builds and executes in the Linux or Cygwin environment. + + 1. You must have already configured Nuttx in /nuttx. + + cd tools + ./configure.sh stm3240g-eval/ + + 2. Download the latest buildroot package into + + 3. unpack the buildroot tarball. The resulting directory may + have versioning information on it like buildroot-x.y.z. If so, + rename /buildroot-x.y.z to /buildroot. + + 4. cd /buildroot + + 5. cp configs/cortexm3-defconfig-4.3.3 .config + + 6. make oldconfig + + 7. make + + 8. Edit setenv.h, if necessary, so that the PATH variable includes + the path to the newly built binaries. + + See the file configs/README.txt in the buildroot source tree. That has more + detailed PLUS some special instructions that you will need to follow if you are + building a Cortex-M3 toolchain for Cygwin under Windows. + +Ethernet +======== + +The Ethernet driver is configured to use the MII interface: + + Board Jumper Settings: + + Jumper Description + JP8 To enable MII, JP8 should not be fitted. + JP6 2-3: Enable MII interface mode + JP5 2-3: Provide 25 MHz clock for MII or 50 MHz clock for RMII by MCO at PA8 + SB1 Not used with MII + +LEDs +==== + +The STM3240G-EVAL board has four LEDs labeled LD1, LD2, LD3 and LD4 on the +board.. These LEDs are not used by the board port unless CONFIG_ARCH_LEDS is +defined. In that case, the usage by the board port is defined in +include/board.h and src/up_leds.c. The LEDs are used to encode OS-related\ +events as follows: + + SYMBOL Meaning LED1* LED2 LED3 LED4 + ------------------- ----------------------- ------- ------- ------- ------ + LED_STARTED NuttX has been started ON OFF OFF OFF + LED_HEAPALLOCATE Heap has been allocated OFF ON OFF OFF + LED_IRQSENABLED Interrupts enabled ON ON OFF OFF + LED_STACKCREATED Idle stack created OFF OFF ON OFF + LED_INIRQ In an interrupt** ON N/C N/C OFF + LED_SIGNAL In a signal handler*** N/C ON N/C OFF + LED_ASSERTION An assertion failed ON ON N/C OFF + LED_PANIC The system has crashed N/C N/C N/C ON + LED_IDLE STM32 is is sleep mode (Optional, not used) + + * If LED1, LED2, LED3 are statically on, then NuttX probably failed to boot + and these LEDs will give you some indication of where the failure was + ** The normal state is LED3 ON and LED1 faintly glowing. This faint glow + is because of timer interupts that result in the LED being illuminated + on a small proportion of the time. +*** LED2 may also flicker normally if signals are processed. + +PWM +=== + +The STM3240G-Eval has no real on-board PWM devices, but the board can be +configured to output a pulse train using TIM4 CH2. This pin is used by +FSMC is but is also connected to the Motor Control Connector (CN5) just +for this purpose: + + PD13 FSMC_A18 / MC_TIM4_CH2 pin 33 (EnB) + +FSMC must be disabled in this case! PD13 is available at: + + Daughterboard Extension Connector, CN3, pin 32 - available + TFT LCD Connector, CN19, pin 17 -- not available without removing the LCD. + Motor Control Connector CN15, pin 33 -- not available unless you bridge SB14. + +CAN +=== + +Connector 10 (CN10) is DB-9 male connector that can be used with CAN1 or CAN2. + + JP10 connects CAN1_RX or CAN2_RX to the CAN transceiver + JP3 connects CAN1_TX or CAN2_TX to the CAN transceiver + +CAN signals are then available on CN10 pins: + + CN10 Pin 7 = CANH + CN10 Pin 2 = CANL + +Mapping to STM32 GPIO pins: + + PD0 = FSMC_D2 & CAN1_RX + PD1 = FSMC_D3 & CAN1_TX + PB13 = ULPI_D6 & CAN2_TX + PB5 = ULPI_D7 & CAN2_RX + +Configuration Options: + + CONFIG_CAN - Enables CAN support (one or both of CONFIG_STM32_CAN1 or + CONFIG_STM32_CAN2 must also be defined) + CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages. + Default: 8 + CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests. + Default: 4 + + CONFIG_STM32_CAN1 - Enable support for CAN1 + CONFIG_CAN1_BAUD - CAN1 BAUD rate. Required if CONFIG_STM32_CAN1 is defined. + CONFIG_STM32_CAN2 - Enable support for CAN1 + CONFIG_CAN2_BAUD - CAN1 BAUD rate. Required if CONFIG_STM32_CAN2 is defined. + CONFIG_CAN_REGDEBUG - If CONFIG_DEBUG is set, this will generate an + dump of all CAN registers. + +STM3240G-EVAL-specific Configuration Options +============================================ + + CONFIG_ARCH - Identifies the arch/ subdirectory. This should + be set to: + + CONFIG_ARCH=arm + + CONFIG_ARCH_family - For use in C code: + + CONFIG_ARCH_ARM=y + + CONFIG_ARCH_architecture - For use in C code: + + CONFIG_ARCH_CORTEXM4=y + + CONFIG_ARCH_CHIP - Identifies the arch/*/chip subdirectory + + CONFIG_ARCH_CHIP=stm32 + + CONFIG_ARCH_CHIP_name - For use in C code to identify the exact + chip: + + CONFIG_ARCH_CHIP_STM32F407IG=y + + CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG - Enables special STM32 clock + configuration features. + + CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG=n + + CONFIG_ARCH_BOARD - Identifies the configs subdirectory and + hence, the board that supports the particular chip or SoC. + + CONFIG_ARCH_BOARD=stm3240g_eval (for the STM3240G-EVAL development board) + + CONFIG_ARCH_BOARD_name - For use in C code + + CONFIG_ARCH_BOARD_STM3240G_EVAL=y + + CONFIG_ARCH_LOOPSPERMSEC - Must be calibrated for correct operation + of delay loops + + CONFIG_ENDIAN_BIG - define if big endian (default is little + endian) + + CONFIG_DRAM_SIZE - Describes the installed DRAM (SRAM in this case): + + CONFIG_DRAM_SIZE=0x00010000 (64Kb) + + CONFIG_DRAM_START - The start address of installed DRAM + + CONFIG_DRAM_START=0x20000000 + + CONFIG_DRAM_END - Last address+1 of installed RAM + + CONFIG_DRAM_END=(CONFIG_DRAM_START+CONFIG_DRAM_SIZE) + + CONFIG_ARCH_IRQPRIO - The STM3240xxx supports interrupt prioritization + + CONFIG_ARCH_IRQPRIO=y + + CONFIG_ARCH_FPU - The STM3240xxx supports a floating point unit (FPU) + + CONFIG_ARCH_FPU=y + + CONFIG_ARCH_LEDS - Use LEDs to show state. Unique to boards that + have LEDs + + CONFIG_ARCH_INTERRUPTSTACK - This architecture supports an interrupt + stack. If defined, this symbol is the size of the interrupt + stack in bytes. If not defined, the user task stacks will be + used during interrupt handling. + + CONFIG_ARCH_STACKDUMP - Do stack dumps after assertions + + CONFIG_ARCH_LEDS - Use LEDs to show state. Unique to board architecture. + + CONFIG_ARCH_CALIBRATION - Enables some build in instrumentation that + cause a 100 second delay during boot-up. This 100 second delay + serves no purpose other than it allows you to calibratre + CONFIG_ARCH_LOOPSPERMSEC. You simply use a stop watch to measure + the 100 second delay then adjust CONFIG_ARCH_LOOPSPERMSEC until + the delay actually is 100 seconds. + + Individual subsystems can be enabled: + + AHB1 + ---- + CONFIG_STM32_CRC + CONFIG_STM32_BKPSRAM + CONFIG_STM32_CCMDATARAM + CONFIG_STM32_DMA1 + CONFIG_STM32_DMA2 + CONFIG_STM32_ETHMAC + CONFIG_STM32_OTGHS + + AHB2 + ---- + CONFIG_STM32_DCMI + CONFIG_STM32_CRYP + CONFIG_STM32_HASH + CONFIG_STM32_RNG + CONFIG_STM32_OTGFS + + AHB3 + ---- + CONFIG_STM32_FSMC + + APB1 + ---- + CONFIG_STM32_TIM2 + CONFIG_STM32_TIM3 + CONFIG_STM32_TIM4 + CONFIG_STM32_TIM5 + CONFIG_STM32_TIM6 + CONFIG_STM32_TIM7 + CONFIG_STM32_TIM12 + CONFIG_STM32_TIM13 + CONFIG_STM32_TIM14 + CONFIG_STM32_WWDG + CONFIG_STM32_SPI2 + CONFIG_STM32_SPI3 + CONFIG_STM32_USART2 + CONFIG_STM32_USART3 + CONFIG_STM32_UART4 + CONFIG_STM32_UART5 + CONFIG_STM32_I2C1 + CONFIG_STM32_I2C2 + CONFIG_STM32_I2C3 + CONFIG_STM32_CAN1 + CONFIG_STM32_CAN2 + CONFIG_STM32_DAC1 + CONFIG_STM32_DAC2 + CONFIG_STM32_PWR -- Required for RTC + + APB2 + ---- + CONFIG_STM32_TIM1 + CONFIG_STM32_TIM8 + CONFIG_STM32_USART1 + CONFIG_STM32_USART6 + CONFIG_STM32_ADC1 + CONFIG_STM32_ADC2 + CONFIG_STM32_ADC3 + CONFIG_STM32_SDIO + CONFIG_STM32_SPI1 + CONFIG_STM32_SYSCFG + CONFIG_STM32_TIM9 + CONFIG_STM32_TIM10 + CONFIG_STM32_TIM11 + + Timer and I2C devices may need to the following to force power to be applied + unconditionally at power up. (Otherwise, the device is powered when it is + initialized). + + CONFIG_STM32_FORCEPOWER + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If CONFIG_STM32_TIMn + is defined (as above) then the following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation, ADC conversion, + or DAC conversion. + + CONFIG_STM32_TIM1_PWM + CONFIG_STM32_TIM2_PWM + CONFIG_STM32_TIM3_PWM + CONFIG_STM32_TIM4_PWM + CONFIG_STM32_TIM5_PWM + CONFIG_STM32_TIM8_PWM + CONFIG_STM32_TIM9_PWM + CONFIG_STM32_TIM10_PWM + CONFIG_STM32_TIM11_PWM + CONFIG_STM32_TIM12_PWM + CONFIG_STM32_TIM13_PWM + CONFIG_STM32_TIM14_PWM + + CONFIG_STM32_TIM1_ADC + CONFIG_STM32_TIM2_ADC + CONFIG_STM32_TIM3_ADC + CONFIG_STM32_TIM4_ADC + CONFIG_STM32_TIM5_ADC + CONFIG_STM32_TIM6_ADC + CONFIG_STM32_TIM7_ADC + CONFIG_STM32_TIM8_ADC + + CONFIG_STM32_TIM1_DAC + CONFIG_STM32_TIM2_DAC + CONFIG_STM32_TIM3_DAC + CONFIG_STM32_TIM4_DAC + CONFIG_STM32_TIM5_DAC + CONFIG_STM32_TIM6_DAC + CONFIG_STM32_TIM7_DAC + CONFIG_STM32_TIM8_DAC + + For each timer that is enabled for PWM usage, we need the following additional + configuration settings: + + CONFIG_STM32_TIMx_CHANNEL - Specifies the timer output channel {1,..,4} + + NOTE: The STM32 timers are each capable of generating different signals on + each of the four channels with different duty cycles. That capability is + not supported by this driver: Only one output channel per timer. + + JTAG Enable settings (by default JTAG-DP and SW-DP are disabled): + + CONFIG_STM32_JTAG_FULL_ENABLE - Enables full SWJ (JTAG-DP + SW-DP) + CONFIG_STM32_JTAG_NOJNTRST_ENABLE - Enables full SWJ (JTAG-DP + SW-DP) + but without JNTRST. + CONFIG_STM32_JTAG_SW_ENABLE - Set JTAG-DP disabled and SW-DP enabled + + STM3240xxx specific device driver settings + + CONFIG_U[S]ARTn_SERIAL_CONSOLE - selects the USARTn (n=1,2,3) or UART + m (m=4,5) for the console and ttys0 (default is the USART1). + CONFIG_U[S]ARTn_RXBUFSIZE - Characters are buffered as received. + This specific the size of the receive buffer + CONFIG_U[S]ARTn_TXBUFSIZE - Characters are buffered before + being sent. This specific the size of the transmit buffer + CONFIG_U[S]ARTn_BAUD - The configure BAUD of the UART. Must be + CONFIG_U[S]ARTn_BITS - The number of bits. Must be either 7 or 8. + CONFIG_U[S]ARTn_PARTIY - 0=no parity, 1=odd parity, 2=even parity + CONFIG_U[S]ARTn_2STOP - Two stop bits + + CONFIG_STM32_SPI_INTERRUPTS - Select to enable interrupt driven SPI + support. Non-interrupt-driven, poll-waiting is recommended if the + interrupt rate would be to high in the interrupt driven case. + CONFIG_STM32_SPI_DMA - Use DMA to improve SPI transfer performance. + Cannot be used with CONFIG_STM32_SPI_INTERRUPT. + + CONFIG_SDIO_DMA - Support DMA data transfers. Requires CONFIG_STM32_SDIO + and CONFIG_STM32_DMA2. + CONFIG_SDIO_PRI - Select SDIO interrupt prority. Default: 128 + CONFIG_SDIO_DMAPRIO - Select SDIO DMA interrupt priority. + Default: Medium + CONFIG_SDIO_WIDTH_D1_ONLY - Select 1-bit transfer mode. Default: + 4-bit transfer mode. + + CONFIG_STM32_PHYADDR - The 5-bit address of the PHY on the board + CONFIG_STM32_MII - Support Ethernet MII interface + CONFIG_STM32_MII_MCO1 - Use MCO1 to clock the MII interface + CONFIG_STM32_MII_MCO2 - Use MCO2 to clock the MII interface + CONFIG_STM32_RMII - Support Ethernet RMII interface + CONFIG_STM32_AUTONEG - Use PHY autonegotion to determine speed and mode + CONFIG_STM32_ETHFD - If CONFIG_STM32_AUTONEG is not defined, then this + may be defined to select full duplex mode. Default: half-duplex + CONFIG_STM32_ETH100MBPS - If CONFIG_STM32_AUTONEG is not defined, then this + may be defined to select 100 MBps speed. Default: 10 Mbps + CONFIG_STM32_PHYSR - This must be provided if CONFIG_STM32_AUTONEG is + defined. The PHY status register address may diff from PHY to PHY. This + configuration sets the address of the PHY status register. + CONFIG_STM32_PHYSR_SPEED - This must be provided if CONFIG_STM32_AUTONEG is + defined. This provides bit mask indicating 10 or 100MBps speed. + CONFIG_STM32_PHYSR_100MBPS - This must be provided if CONFIG_STM32_AUTONEG is + defined. This provides the value of the speed bit(s) indicating 100MBps speed. + CONFIG_STM32_PHYSR_MODE - This must be provided if CONFIG_STM32_AUTONEG is + defined. This provide bit mask indicating full or half duplex modes. + CONFIG_STM32_PHYSR_FULLDUPLEX - This must be provided if CONFIG_STM32_AUTONEG is + defined. This provides the value of the mode bits indicating full duplex mode. + CONFIG_STM32_ETH_PTP - Precision Time Protocol (PTP). Not supported + but some hooks are indicated with this condition. + + STM3240G-EVAL CAN Configuration + + CONFIG_CAN - Enables CAN support (one or both of CONFIG_STM32_CAN1 or + CONFIG_STM32_CAN2 must also be defined) + CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages. + Default: 8 + CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests. + Default: 4 + CONFIG_CAN_LOOPBACK - A CAN driver may or may not support a loopback + mode for testing. The STM32 CAN driver does support loopback mode. + CONFIG_CAN1_BAUD - CAN1 BAUD rate. Required if CONFIG_STM32_CAN1 is defined. + CONFIG_CAN2_BAUD - CAN1 BAUD rate. Required if CONFIG_STM32_CAN2 is defined. + CONFIG_CAN_REGDEBUG - If CONFIG_DEBUG is set, this will generate an + dump of all CAN registers. + + STM3240G-EVAL LCD Hardware Configuration + +Configurations +============== + +Each STM3240G-EVAL configuration is maintained in a sudirectory and +can be selected as follow: + + cd tools + ./configure.sh stm3240g-eval/ + cd - + . ./setenv.sh + +Where is one of the following: + + dhcpd: + ----- + + This builds the DCHP server using the apps/examples/dhcpd application + (for execution from FLASH.) See apps/examples/README.txt for information + about the dhcpd example. The server address is 10.0.0.1 and it serves + IP addresses in the range 10.0.0.2 through 10.0.0.17 (all of which, of + course, are configurable). + + CONFIG_STM32_CODESOURCERYW=y : CodeSourcery under Windows + + nettest: + ------- + + This configuration directory may be used to verify networking performance + using the STM32's Ethernet controller. It uses apps/examples/nettest to excercise the + TCP/IP network. + + CONFIG_EXAMPLE_NETTEST_SERVER=n : Target is configured as the client + CONFIG_EXAMPLE_NETTEST_PERFORMANCE=y : Only network performance is verified. + CONFIG_EXAMPLE_NETTEST_IPADDR=(10<<24|0<<16|0<<8|2) : Target side is IP: 10.0.0.2 + CONFIG_EXAMPLE_NETTEST_DRIPADDR=(10<<24|0<<16|0<<8|1) : Host side is IP: 10.0.0.1 + CONFIG_EXAMPLE_NETTEST_CLIENTIP=(10<<24|0<<16|0<<8|1) : Server address used by which ever is client. + + ostest: + ------ + This configuration directory, performs a simple OS test using + examples/ostest. By default, this project assumes that you are + using the DFU bootloader. + + CONFIG_STM32_CODESOURCERYW=y : CodeSourcery under Windows + + nsh: + --- + Configures the NuttShell (nsh) located at apps/examples/nsh. The + Configuration enables both the serial and telnet NSH interfaces. + + CONFIG_STM32_CODESOURCERYW=y : CodeSourcery under Windows + CONFIG_NSH_DHCPC=n : DHCP is disabled + CONFIG_NSH_IPADDR=(10<<24|0<<16|0<<8|2) : Target IP address 10.0.0.2 + CONFIG_NSH_DRIPADDR=(10<<24|0<<16|0<<8|1) : Host IP address 10.0.0.1 + + NOTE: This example assumes that a network is connected. During its + initialization, it will try to negotiate the link speed. If you have + no network connected when you reset the board, there will be a long + delay (maybe 30 seconds?) before anything happens. That is the timeout + before the networking finally gives up and decides that no network is + available. diff --git a/nuttx/configs/px4fmu/common/Make.defs b/nuttx/configs/px4fmu/common/Make.defs new file mode 100644 index 0000000000..00a489eabf --- /dev/null +++ b/nuttx/configs/px4fmu/common/Make.defs @@ -0,0 +1,216 @@ +############################################################################ +# configs/px4fmu/common/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Generic Make.defs for the PX4FMU +# Do not specify/use this file directly - it is included by config-specific +# Make.defs in the per-config directories. +# + +# +# We only support building with the ARM bare-metal toolchain from +# https://launchpad.net/gcc-arm-embedded on Windows, Linux or Mac OS. +# + +CROSSDEV = arm-none-eabi- + +CC = $(CROSSDEV)gcc +CXX = $(CROSSDEV)g++ +CPP = $(CROSSDEV)gcc -E +LD = $(CROSSDEV)ld +AR = $(CROSSDEV)ar rcs +NM = $(CROSSDEV)nm +OBJCOPY = $(CROSSDEV)objcopy +OBJDUMP = $(CROSSDEV)objdump + +MAXOPTIMIZATION = -O3 +ARCHCPUFLAGS = -mcpu=cortex-m4 \ + -mthumb \ + -march=armv7e-m \ + -mfpu=fpv4-sp-d16 \ + -mfloat-abi=hard + + +# enable precise stack overflow tracking +INSTRUMENTATIONDEFINES = -finstrument-functions \ + -ffixed-r10 + +# pull in *just* libm from the toolchain ... this is grody +LIBM = "${shell $(CC) $(ARCHCPUFLAGS) -print-file-name=libm.a}" +EXTRA_LIBS += $(LIBM) + +# use our linker script +LDSCRIPT = ld.script + +ifeq ($(WINTOOL),y) + # Windows-native toolchains + DIRLINK = $(TOPDIR)/tools/winlink.sh + DIRUNLINK = $(TOPDIR)/tools/unlink.sh + MKDEP = $(TOPDIR)/tools/mknulldeps.sh + ARCHINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" + ARCHXXINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" -isystem "${shell cygpath -w $(TOPDIR)/include/cxx}" + ARCHSCRIPT = -T "${shell cygpath -w $(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/common/$(LDSCRIPT)}" +else + ifeq ($(PX4_WINTOOL),y) + # Windows-native toolchains (MSYS) + DIRLINK = $(TOPDIR)/tools/winlink.sh + DIRUNLINK = $(TOPDIR)/tools/unlink.sh + MKDEP = $(TOPDIR)/tools/mknulldeps.sh + ARCHINCLUDES = -I. -isystem $(TOPDIR)/include + ARCHXXINCLUDES = -I. -isystem $(TOPDIR)/include -isystem $(TOPDIR)/include/cxx + ARCHSCRIPT = -T$(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/common/$(LDSCRIPT) + else + # Linux/Cygwin-native toolchain + MKDEP = $(TOPDIR)/tools/mkdeps.sh + ARCHINCLUDES = -I. -isystem $(TOPDIR)/include + ARCHXXINCLUDES = -I. -isystem $(TOPDIR)/include -isystem $(TOPDIR)/include/cxx + ARCHSCRIPT = -T$(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/common/$(LDSCRIPT) + endif +endif + +# tool versions +ARCHCCVERSION = ${shell $(CC) -v 2>&1 | sed -n '/^gcc version/p' | sed -e 's/^gcc version \([0-9\.]\)/\1/g' -e 's/[-\ ].*//g' -e '1q'} +ARCHCCMAJOR = ${shell echo $(ARCHCCVERSION) | cut -d'.' -f1} + +# optimisation flags +ARCHOPTIMIZATION = $(MAXOPTIMIZATION) \ + -fno-strict-aliasing \ + -fno-strength-reduce \ + -fomit-frame-pointer \ + -funsafe-math-optimizations \ + -fno-builtin-printf \ + -ffunction-sections \ + -fdata-sections + +ifeq ("${CONFIG_DEBUG_SYMBOLS}","y") +ARCHOPTIMIZATION += -g +ARCHSCRIPT += -g +endif + +ARCHCFLAGS = -std=gnu99 +ARCHCXXFLAGS = -fno-exceptions -fno-rtti -std=gnu++0x +ARCHWARNINGS = -Wall \ + -Wextra \ + -Wdouble-promotion \ + -Wshadow \ + -Wfloat-equal \ + -Wframe-larger-than=1024 \ + -Wpointer-arith \ + -Wlogical-op \ + -Wmissing-declarations \ + -Wpacked \ + -Wno-unused-parameter +# -Wcast-qual - generates spurious noreturn attribute warnings, try again later +# -Wconversion - would be nice, but too many "risky-but-safe" conversions in the code +# -Wcast-align - would help catch bad casts in some cases, but generates too many false positives + +ARCHCWARNINGS = $(ARCHWARNINGS) \ + -Wbad-function-cast \ + -Wstrict-prototypes \ + -Wold-style-declaration \ + -Wmissing-parameter-type \ + -Wmissing-prototypes \ + -Wnested-externs \ + -Wunsuffixed-float-constants +ARCHWARNINGSXX = $(ARCHWARNINGS) +ARCHDEFINES = +ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10 + +# this seems to be the only way to add linker flags +ARCHSCRIPT += --warn-common \ + --gc-sections + +CFLAGS = $(ARCHCFLAGS) $(ARCHCWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(INSTRUMENTATIONDEFINES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe -fno-common +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(INSTRUMENTATIONDEFINES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS = $(ARCHINCLUDES) $(INSTRUMENTATIONDEFINES) $(ARCHDEFINES) $(EXTRADEFINES) +AFLAGS = $(CFLAGS) -D__ASSEMBLY__ + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 + +OBJEXT = .o +LIBEXT = .a +EXEEXT = + +# If VERBOSE is set, don't hide the compiler invocations. +ifeq ($(VERBOSE),YES) +_v = +else +_v = @ +endif + +define PREPROCESS + @echo "CPP: $1->$2" + @$(CPP) $(CPPFLAGS) $(abspath $1) -o $2 +endef + +define COMPILE + @echo "CC: $1" + $(_v)$(CC) -c $(CFLAGS) $(abspath $1) -o $2 +endef + +define COMPILEXX + @echo "CXX: $1" + $(_v)$(CXX) -c $(CXXFLAGS) $(abspath $1) -o $2 +endef + +define ASSEMBLE + @echo "AS: $1" + $(_v)$(CC) -c $(AFLAGS) $(abspath $1) -o $2 +endef + +# produce partially-linked $1 from files in $2 +define PRELINK + @echo "PRELINK: $1" + @$(LD) -Ur -o $1 $2 && $(OBJCOPY) --localize-hidden $1 +endef + +define ARCHIVE + echo "AR: $2"; \ + $(AR) $1 $2 || { echo "$(AR) $1 $2 FAILED!" ; exit 1 ; } +endef + +define CLEAN + @rm -f *.o *.a +endef + +HOSTCC = gcc +HOSTINCLUDES = -I. +HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -g -pipe +HOSTLDFLAGS = + diff --git a/nuttx/configs/px4fmu/common/ld.script b/nuttx/configs/px4fmu/common/ld.script new file mode 100644 index 0000000000..e3ca771b16 --- /dev/null +++ b/nuttx/configs/px4fmu/common/ld.script @@ -0,0 +1,133 @@ +/**************************************************************************** + * configs/px4fmu/common/ld.script + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* The STM32F405 has 1024Kb of FLASH beginning at address 0x0800:0000 and + * 192Kb of SRAM. SRAM is split up into three blocks: + * + * 1) 112Kb of SRAM beginning at address 0x2000:0000 + * 2) 16Kb of SRAM beginning at address 0x2001:c000 + * 3) 64Kb of TCM SRAM beginning at address 0x1000:0000 + * + * When booting from FLASH, FLASH memory is aliased to address 0x0000:0000 + * where the code expects to begin execution by jumping to the entry point in + * the 0x0800:0000 address range. + * + * The first 0x4000 of flash is reserved for the bootloader. + */ + +MEMORY +{ + flash (rx) : ORIGIN = 0x08004000, LENGTH = 1008K + sram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K + ccsram (rwx) : ORIGIN = 0x10000000, LENGTH = 64K +} + +OUTPUT_ARCH(arm) + +ENTRY(__start) /* treat __start as the anchor for dead code stripping */ +EXTERN(_vectors) /* force the vectors to be included in the output */ + +/* + * Ensure that abort() is present in the final object. The exception handling + * code pulled in by libgcc.a requires it (and that code cannot be easily avoided). + */ +EXTERN(abort) + +SECTIONS +{ + .text : { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + + /* + * This is a hack to make the newlib libm __errno() call + * use the NuttX get_errno_ptr() function. + */ + __errno = get_errno_ptr; + } > flash + + .ARM.extab : { + *(.ARM.extab*) + } > flash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : { + *(.ARM.exidx*) + } > flash + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + _edata = ABSOLUTE(.); + } > sram AT > flash + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/nuttx/configs/px4fmu/include/board.h b/nuttx/configs/px4fmu/include/board.h new file mode 100755 index 0000000000..0db8580ba9 --- /dev/null +++ b/nuttx/configs/px4fmu/include/board.h @@ -0,0 +1,392 @@ +/************************************************************************************ + * configs/px4fmu/include/board.h + * include/arch/board/board.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_BOARD_BOARD_H +#define __ARCH_BOARD_BOARD_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#ifndef __ASSEMBLY__ +# include +#endif +//#include "stm32_rcc.h" +//#include "stm32_sdio.h" +//#include "stm32_internal.h" + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/* Clocking *************************************************************************/ +/* The PX4FMU uses a 24MHz crystal connected to the HSE. + * + * This is the "standard" configuration as set up by arch/arm/src/stm32f40xx_rcc.c: + * System Clock source : PLL (HSE) + * SYSCLK(Hz) : 168000000 Determined by PLL configuration + * HCLK(Hz) : 168000000 (STM32_RCC_CFGR_HPRE) + * AHB Prescaler : 1 (STM32_RCC_CFGR_HPRE) + * APB1 Prescaler : 4 (STM32_RCC_CFGR_PPRE1) + * APB2 Prescaler : 2 (STM32_RCC_CFGR_PPRE2) + * HSE Frequency(Hz) : 24000000 (STM32_BOARD_XTAL) + * PLLM : 24 (STM32_PLLCFG_PLLM) + * PLLN : 336 (STM32_PLLCFG_PLLN) + * PLLP : 2 (STM32_PLLCFG_PLLP) + * PLLQ : 7 (STM32_PLLCFG_PPQ) + * Main regulator output voltage : Scale1 mode Needed for high speed SYSCLK + * Flash Latency(WS) : 5 + * Prefetch Buffer : OFF + * Instruction cache : ON + * Data cache : ON + * Require 48MHz for USB OTG FS, : Enabled + * SDIO and RNG clock + */ + +/* HSI - 16 MHz RC factory-trimmed + * LSI - 32 KHz RC + * HSE - On-board crystal frequency is 24MHz + * LSE - not installed + */ + +#define STM32_BOARD_XTAL 24000000ul + +#define STM32_HSI_FREQUENCY 16000000ul +#define STM32_LSI_FREQUENCY 32000 +#define STM32_HSE_FREQUENCY STM32_BOARD_XTAL +//#define STM32_LSE_FREQUENCY 32768 + +/* Main PLL Configuration. + * + * PLL source is HSE + * PLL_VCO = (STM32_HSE_FREQUENCY / PLLM) * PLLN + * = (25,000,000 / 25) * 336 + * = 336,000,000 + * SYSCLK = PLL_VCO / PLLP + * = 336,000,000 / 2 = 168,000,000 + * USB OTG FS, SDIO and RNG Clock + * = PLL_VCO / PLLQ + * = 48,000,000 + */ + +#define STM32_PLLCFG_PLLM RCC_PLLCFG_PLLM(24) +#define STM32_PLLCFG_PLLN RCC_PLLCFG_PLLN(336) +#define STM32_PLLCFG_PLLP RCC_PLLCFG_PLLP_2 +#define STM32_PLLCFG_PPQ RCC_PLLCFG_PLLQ(7) + +#define STM32_SYSCLK_FREQUENCY 168000000ul + +/* AHB clock (HCLK) is SYSCLK (168MHz) */ + +#define STM32_RCC_CFGR_HPRE RCC_CFGR_HPRE_SYSCLK /* HCLK = SYSCLK / 1 */ +#define STM32_HCLK_FREQUENCY STM32_SYSCLK_FREQUENCY +#define STM32_BOARD_HCLK STM32_HCLK_FREQUENCY /* same as above, to satisfy compiler */ + +/* APB1 clock (PCLK1) is HCLK/4 (42MHz) */ + +#define STM32_RCC_CFGR_PPRE1 RCC_CFGR_PPRE1_HCLKd4 /* PCLK1 = HCLK / 4 */ +#define STM32_PCLK1_FREQUENCY (STM32_HCLK_FREQUENCY/4) + +/* Timers driven from APB1 will be twice PCLK1 */ + +#define STM32_APB1_TIM2_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM3_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM4_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM5_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM6_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM7_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM12_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM13_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM14_CLKIN (2*STM32_PCLK1_FREQUENCY) + +/* APB2 clock (PCLK2) is HCLK/2 (84MHz) */ + +#define STM32_RCC_CFGR_PPRE2 RCC_CFGR_PPRE2_HCLKd2 /* PCLK2 = HCLK / 2 */ +#define STM32_PCLK2_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* Timers driven from APB2 will be twice PCLK2 */ + +#define STM32_APB2_TIM1_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM8_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM9_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB2_TIM10_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB2_TIM11_CLKIN (2*STM32_PCLK1_FREQUENCY) + +/* Timer Frequencies, if APBx is set to 1, frequency is same to APBx + * otherwise frequency is 2xAPBx. + * Note: TIM1,8 are on APB2, others on APB1 + */ + +#define STM32_TIM18_FREQUENCY (2*STM32_PCLK2_FREQUENCY) +#define STM32_TIM27_FREQUENCY (2*STM32_PCLK1_FREQUENCY) + +/* SDIO dividers. Note that slower clocking is required when DMA is disabled + * in order to avoid RX overrun/TX underrun errors due to delayed responses + * to service FIFOs in interrupt driven mode. These values have not been + * tuned!!! + * + * HCLK=72MHz, SDIOCLK=72MHz, SDIO_CK=HCLK/(178+2)=400 KHz + */ + +#define SDIO_INIT_CLKDIV (178 << SDIO_CLKCR_CLKDIV_SHIFT) + +/* DMA ON: HCLK=72 MHz, SDIOCLK=72MHz, SDIO_CK=HCLK/(2+2)=18 MHz + * DMA OFF: HCLK=72 MHz, SDIOCLK=72MHz, SDIO_CK=HCLK/(3+2)=14.4 MHz + */ + +#ifdef CONFIG_SDIO_DMA +# define SDIO_MMCXFR_CLKDIV (2 << SDIO_CLKCR_CLKDIV_SHIFT) +#else +# define SDIO_MMCXFR_CLKDIV (3 << SDIO_CLKCR_CLKDIV_SHIFT) +#endif + +/* DMA ON: HCLK=72 MHz, SDIOCLK=72MHz, SDIO_CK=HCLK/(1+2)=24 MHz + * DMA OFF: HCLK=72 MHz, SDIOCLK=72MHz, SDIO_CK=HCLK/(3+2)=14.4 MHz + */ + +#ifdef CONFIG_SDIO_DMA +# define SDIO_SDXFR_CLKDIV (1 << SDIO_CLKCR_CLKDIV_SHIFT) +#else +# define SDIO_SDXFR_CLKDIV (3 << SDIO_CLKCR_CLKDIV_SHIFT) +#endif + +/* High-resolution timer + */ +#ifdef CONFIG_HRT_TIMER +# define HRT_TIMER 1 /* use timer1 for the HRT */ +# define HRT_TIMER_CHANNEL 1 /* use capture/compare channel */ +#endif + +/* LED definitions ******************************************************************/ +/* PX4 has two LEDs that we will encode as: */ + +#define LED_STARTED 0 /* LED? */ +#define LED_HEAPALLOCATE 1 /* LED? */ +#define LED_IRQSENABLED 2 /* LED? + LED? */ +#define LED_STACKCREATED 3 /* LED? */ +#define LED_INIRQ 4 /* LED? + LED? */ +#define LED_SIGNAL 5 /* LED? + LED? */ +#define LED_ASSERTION 6 /* LED? + LED? + LED? */ +#define LED_PANIC 7 /* N/C + N/C + N/C + LED? */ + +/* Alternate function pin selections ************************************************/ + +/* + * UARTs. + * + * Note that UART5 has no optional pinout. + */ +#define GPIO_USART1_RX GPIO_USART1_RX_2 +#define GPIO_USART1_TX GPIO_USART1_TX_2 + +#define GPIO_USART2_RX GPIO_USART2_RX_1 +#define GPIO_USART2_TX GPIO_USART2_TX_1 +#define GPIO_USART2_RTS GPIO_USART2_RTS_1 +#define GPIO_USART2_CTS GPIO_USART2_CTS_1 + +#define GPIO_USART6_RX GPIO_USART6_RX_1 +#define GPIO_USART6_TX GPIO_USART6_TX_1 + +/* UART DMA configuration for USART1/6 */ +#define DMAMAP_USART1_RX DMAMAP_USART1_RX_2 +#define DMAMAP_USART6_RX DMAMAP_USART6_RX_2 + +/* + * PWM + * + * Four PWM outputs can be configured on pins otherwise shared with + * USART2; two can take the flow control pins if they are not being used. + * + * Pins: + * + * CTS - PA0 - TIM2CH1 + * RTS - PA1 - TIM2CH2 + * TX - PA2 - TIM2CH3 + * RX - PA3 - TIM2CH4 + * + */ +#define GPIO_TIM2_CH1OUT GPIO_TIM2_CH1OUT_1 +#define GPIO_TIM2_CH2OUT GPIO_TIM2_CH2OUT_1 +#define GPIO_TIM2_CH3OUT GPIO_TIM2_CH3OUT_1 +#define GPIO_TIM2_CH4OUT GPIO_TIM2_CH4OUT_1 + +/* + * PPM + * + * PPM input is handled by the HRT timer. + */ +#if defined(CONFIG_HRT_TIMER) && defined (CONFIG_HRT_PPM) +# define HRT_PPM_CHANNEL 3 /* use capture/compare channel 3 */ +# define GPIO_PPM_IN (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN10) +#endif + +/* + * CAN + * + * CAN2 is routed to the expansion connector. + */ + +#define GPIO_CAN2_RX GPIO_CAN2_RX_2 +#define GPIO_CAN2_TX GPIO_CAN2_TX_2 + +/* + * I2C + */ +#define GPIO_I2C1_SCL GPIO_I2C1_SCL_2 +#define GPIO_I2C1_SDA GPIO_I2C1_SDA_2 + +#define GPIO_I2C2_SCL GPIO_I2C2_SCL_1 +#define GPIO_I2C2_SDA GPIO_I2C2_SDA_1 + +#define GPIO_I2C3_SCL GPIO_I2C3_SCL_1 +#define GPIO_I2C3_SDA GPIO_I2C3_SDA_1 + +/* + * I2C busses + */ +#define PX4_I2C_BUS_ESC 1 +#define PX4_I2C_BUS_ONBOARD 2 +#define PX4_I2C_BUS_EXPANSION 3 + +/* + * Devices on the onboard bus. + * + * Note that these are unshifted addresses. + */ +#define PX4_I2C_OBDEV_HMC5883 0x1e +#define PX4_I2C_OBDEV_MS5611 NOTDEFINED +#define PX4_I2C_OBDEV_EEPROM 0x50 + +#define PX4_I2C_OBDEV_PX4IO_BL 0x18 +#define PX4_I2C_OBDEV_PX4IO 0x19 + +/* + * SPI + */ +#define GPIO_SPI1_MISO GPIO_SPI1_MISO_1 +#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1 +#define GPIO_SPI1_SCK GPIO_SPI1_SCK_1 + +#define GPIO_SPI3_MISO GPIO_SPI3_MISO_2 +#define GPIO_SPI3_MOSI GPIO_SPI3_MOSI_1 +#define GPIO_SPI3_SCK GPIO_SPI3_SCK_2 +#define GPIO_SPI3_NSS GPIO_SPI3_NSS_2 + +/* + * Use these in place of the spi_dev_e enumeration to + * select a specific SPI device on SPI1 + */ +#define PX4_SPIDEV_GYRO 1 +#define PX4_SPIDEV_ACCEL 2 +#define PX4_SPIDEV_MPU 3 + +/* + * Tone alarm output + */ +#ifdef CONFIG_TONE_ALARM +# define TONE_ALARM_TIMER 3 /* timer 3 */ +# define TONE_ALARM_CHANNEL 3 /* channel 3 */ +# define GPIO_TONE_ALARM (GPIO_ALT|GPIO_AF2|GPIO_SPEED_2MHz|GPIO_FLOAT|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8) +#endif + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ +/************************************************************************************ + * Name: stm32_boardinitialize + * + * Description: + * All STM32 architectures must provide the following entry point. This entry point + * is called early in the intitialization -- after all memory has been configured + * and mapped but before any devices have been initialized. + * + ************************************************************************************/ + +EXTERN void stm32_boardinitialize(void); + +/************************************************************************************ + * Button support. + * + * Description: + * up_buttoninit() must be called to initialize button resources. After + * that, up_buttons() may be called to collect the current state of all + * buttons or up_irqbutton() may be called to register button interrupt + * handlers. + * + * After up_buttoninit() has been called, up_buttons() may be called to + * collect the state of all buttons. up_buttons() returns an 8-bit bit set + * with each bit associated with a button. See the BUTTON_*_BIT + * definitions in board.h for the meaning of each bit. + * + * up_irqbutton() may be called to register an interrupt handler that will + * be called when a button is depressed or released. The ID value is a + * button enumeration value that uniquely identifies a button resource. See the + * BUTTON_* definitions in board.h for the meaning of enumeration + * value. The previous interrupt handler address is returned (so that it may + * restored, if so desired). + * + ************************************************************************************/ + +#ifdef CONFIG_ARCH_BUTTONS +EXTERN void up_buttoninit(void); +EXTERN uint8_t up_buttons(void); +#ifdef CONFIG_ARCH_IRQBUTTONS +EXTERN xcpt_t up_irqbutton(int id, xcpt_t irqhandler); +#endif +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_BOARD_BOARD_H */ diff --git a/nuttx/configs/px4fmu/include/drv_bma180.h b/nuttx/configs/px4fmu/include/drv_bma180.h new file mode 100644 index 0000000000..a403415e48 --- /dev/null +++ b/nuttx/configs/px4fmu/include/drv_bma180.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2012 Lorenz Meier. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of the author or 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. + */ + +/* + * Driver for the BOSCH BMA180 MEMS accelerometer + */ + +/* IMPORTANT NOTES: + * + * SPI max. clock frequency: 25 Mhz + * CS has to be high before transfer, + * go low right before transfer and + * go high again right after transfer + * + */ + +#include + +#define _BMA180BASE 0x6300 +#define BMA180C(_x) _IOC(_BMA180BASE, _x) + +/* + * Sets the sensor internal sampling rate, and if a buffer + * has been configured, the rate at which entries will be + * added to the buffer. + */ +#define BMA180_SETRATE BMA180C(1) + +#define BMA180_RATE_LP_10HZ (0<<4) +#define BMA180_RATE_LP_20HZ (1<<4) +#define BMA180_RATE_LP_40HZ (2<<4) +#define BMA180_RATE_LP_75HZ (3<<4) +#define BMA180_RATE_LP_150HZ (4<<4) +#define BMA180_RATE_LP_300HZ (5<<4) +#define BMA180_RATE_LP_600HZ (6<<4) +#define BMA180_RATE_LP_1200HZ (7<<4) + +/* + * Sets the sensor internal range. + */ +#define BMA180_SETRANGE BMA180C(2) + +#define BMA180_RANGE_1G (0<<1) +#define BMA180_RANGE_1_5G (1<<1) +#define BMA180_RANGE_2G (2<<1) +#define BMA180_RANGE_3G (3<<1) +#define BMA180_RANGE_4G (4<<1) +#define BMA180_RANGE_8G (5<<1) +#define BMA180_RANGE_16G (6<<1) + +/* + * Sets the address of a shared BMA180_buffer + * structure that is maintained by the driver. + * + * If zero is passed as the address, disables + * the buffer updating. + */ +#define BMA180_SETBUFFER BMA180C(3) + +struct bma180_buffer { + uint32_t size; /* number of entries in the samples[] array */ + uint32_t next; /* the next entry that will be populated */ + struct { + uint16_t x; + uint16_t y; + uint16_t z; + uint8_t temp; + } samples[]; +}; + +extern int bma180_attach(struct spi_dev_s *spi, int spi_id); diff --git a/nuttx/configs/px4fmu/include/drv_eeprom.h b/nuttx/configs/px4fmu/include/drv_eeprom.h new file mode 100644 index 0000000000..e6801f6c4a --- /dev/null +++ b/nuttx/configs/px4fmu/include/drv_eeprom.h @@ -0,0 +1,73 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * Driver for the ST MS5611 gyroscope + */ + +/* IMPORTANT NOTES: + * + * SPI max. clock frequency: 10 Mhz + * CS has to be high before transfer, + * go low right before transfer and + * go high again right after transfer + * + */ + +/* IMPORTANT: Adjust this number! */ +#define MAX_EEPROMS 2 + +/* FMU onboard */ +#define FMU_ONBOARD_EEPROM_ADDRESS 0x50 +#define FMU_ONBOARD_EEPROM_TOTAL_SIZE_BYTES 16000 +#define FMU_ONBOARD_EEPROM_PAGE_SIZE_BYTES 64 +#define FMU_ONBOARD_EEPROM_PAGE_WRITE_TIME_US 5500 +#define FMU_ONBOARD_EEPROM_BUS_CLOCK 1000000 ///< 1 Mhz max. clock + +#define FMU_BASEBOARD_EEPROM_ADDRESS 0x57 +#define FMU_BASEBOARD_EEPROM_TOTAL_SIZE_BYTES 128 +#define FMU_BASEBOARD_EEPROM_PAGE_SIZE_BYTES 8 +#define FMU_BASEBOARD_EEPROM_PAGE_WRITE_TIME_US 3300 +#define FMU_BASEBOARD_EEPROM_BUS_CLOCK 400000 ///< 400 KHz max. clock + +/** + * @brief i2c I2C bus struct + * @brief device_address The device address as stated in the datasheet, e.g. for a Microchip 24XX128 0x50 with all ID pins tied to GND + * @brief total_size_bytes The total size in bytes, e.g. 16K = 16000 bytes for the Microchip 24XX128 + * @brief page_size_bytes The size of one page, e.g. 64 bytes for the Microchip 24XX128 + * @brief device_name The device name to register this device to, e.g. /dev/eeprom + * @brief fail_if_missing Returns error if the EEPROM was not found. This is helpful if the EEPROM might be attached later when the board is running + */ +extern int +eeprom_attach(struct i2c_dev_s *i2c, uint8_t device_address, uint16_t total_size_bytes, uint16_t page_size_bytes, uint16_t page_write_time_us, const char* device_name, uint8_t fail_if_missing); + diff --git a/nuttx/configs/px4fmu/include/drv_gpio.h b/nuttx/configs/px4fmu/include/drv_gpio.h new file mode 100644 index 0000000000..22f80d0387 --- /dev/null +++ b/nuttx/configs/px4fmu/include/drv_gpio.h @@ -0,0 +1,107 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file GPIO driver interface. + * + * This header defines the basic interface to platform-specific GPIOs. + */ + +#ifndef _BOARD_DRV_GPIO_H +#define _BOARD_DRV_GPIO_H + +/* + * PX4FMU GPIO numbers. + * + * For shared pins, alternate function 1 selects the non-GPIO mode + * (USART2, CAN2, etc.) + */ +#define GPIO_EXT_1 (1<<0) /**< high-power GPIO 1 */ +#define GPIO_EXT_2 (1<<1) /**< high-power GPIO 1 */ +#define GPIO_MULTI_1 (1<<2) /**< USART2 CTS */ +#define GPIO_MULTI_2 (1<<3) /**< USART2 RTS */ +#define GPIO_MULTI_3 (1<<4) /**< USART2 TX */ +#define GPIO_MULTI_4 (1<<5) /**< USART2 RX */ +#define GPIO_CAN_TX (1<<6) /**< CAN2 TX */ +#define GPIO_CAN_RX (1<<7) /**< CAN2 RX */ + +/** + * Default GPIO device - other devices may also support this protocol if + * they also export GPIO-like things. This is always the GPIOs on the + * main board. + */ +#define GPIO_DEVICE_PATH "/dev/gpio" + +/* + * IOCTL definitions. + * + * For all ioctls, the (arg) argument is a bitmask of GPIOs to be affected + * by the operation, with the LSB being the lowest-numbered GPIO. + * + * Note that there may be board-specific relationships between GPIOs; + * applications using GPIOs should be aware of this. + */ +#define _GPIOCBASE 0x6700 +#define GPIOC(_x) _IOC(_GPIOCBASE, _x) + +/** reset all board GPIOs to their default state */ +#define GPIO_RESET GPIOC(0) + +/** configure the board GPIOs in (arg) as outputs */ +#define GPIO_SET_OUTPUT GPIOC(1) + +/** configure the board GPIOs in (arg) as inputs */ +#define GPIO_SET_INPUT GPIOC(2) + +/** configure the board GPIOs in (arg) for the first alternate function (if supported) */ +#define GPIO_SET_ALT_1 GPIOC(3) + +/** configure the board GPIO (arg) for the second alternate function (if supported) */ +#define GPIO_SET_ALT_2 GPIOC(4) + +/** configure the board GPIO (arg) for the third alternate function (if supported) */ +#define GPIO_SET_ALT_3 GPIOC(5) + +/** configure the board GPIO (arg) for the fourth alternate function (if supported) */ +#define GPIO_SET_ALT_4 GPIOC(6) + +/** set the GPIOs in (arg) */ +#define GPIO_SET GPIOC(10) + +/** clear the GPIOs in (arg) */ +#define GPIO_CLEAR GPIOC(11) + +/** read all the GPIOs and return their values in *(uint32_t *)arg */ +#define GPIO_GET GPIOC(12) + +#endif /* _DRV_GPIO_H */ diff --git a/nuttx/configs/px4fmu/include/drv_hmc5883l.h b/nuttx/configs/px4fmu/include/drv_hmc5883l.h new file mode 100644 index 0000000000..8dc9b8a93d --- /dev/null +++ b/nuttx/configs/px4fmu/include/drv_hmc5883l.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * Driver for the ST HMC5883L gyroscope + */ + +/* IMPORTANT NOTES: + * + * SPI max. clock frequency: 10 Mhz + * CS has to be high before transfer, + * go low right before transfer and + * go high again right after transfer + * + */ + +#include + +#define _HMC5883LBASE 0x6100 +#define HMC5883LC(_x) _IOC(_HMC5883LBASE, _x) + +/* + * Sets the sensor internal sampling rate, and if a buffer + * has been configured, the rate at which entries will be + * added to the buffer. + */ +#define HMC5883L_SETRATE HMC5883LC(1) + +/* set rate (configuration A register */ +#define HMC5883L_RATE_0_75HZ (0 << 2) /* 0.75 Hz */ +#define HMC5883L_RATE_1_50HZ (1 << 2) /* 1.5 Hz */ +#define HMC5883L_RATE_3_00HZ (2 << 2) /* 3 Hz */ +#define HMC5883L_RATE_7_50HZ (3 << 2) /* 7.5 Hz */ +#define HMC5883L_RATE_15HZ (4 << 2) /* 15 Hz (default) */ +#define HMC5883L_RATE_30HZ (5 << 2) /* 30 Hz */ +#define HMC5883L_RATE_75HZ (6 << 2) /* 75 Hz */ + +/* + * Sets the sensor internal range. + */ +#define HMC5883L_SETRANGE HMC5883LC(2) + +#define HMC5883L_RANGE_0_88GA (0 << 5) +#define HMC5883L_RANGE_1_33GA (1 << 5) +#define HMC5883L_RANGE_1_90GA (2 << 5) +#define HMC5883L_RANGE_2_50GA (3 << 5) +#define HMC5883L_RANGE_4_00GA (4 << 5) + +/* + * Sets the address of a shared HMC5883L_buffer + * structure that is maintained by the driver. + * + * If zero is passed as the address, disables + * the buffer updating. + */ +#define HMC5883L_SETBUFFER HMC5883LC(3) + +struct hmc5883l_buffer { + uint32_t size; /* number of entries in the samples[] array */ + uint32_t next; /* the next entry that will be populated */ + struct { + int16_t x; + int16_t y; + int16_t z; + } samples[]; +}; + +#define HMC5883L_RESET HMC5883LC(4) + +extern int hmc5883l_attach(struct i2c_dev_s *i2c); diff --git a/nuttx/configs/px4fmu/include/drv_l3gd20.h b/nuttx/configs/px4fmu/include/drv_l3gd20.h new file mode 100644 index 0000000000..3b284d60de --- /dev/null +++ b/nuttx/configs/px4fmu/include/drv_l3gd20.h @@ -0,0 +1,108 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ +/* + * Driver for the ST L3GD20 gyroscope + */ + +/* IMPORTANT NOTES: + * + * SPI max. clock frequency: 10 Mhz + * CS has to be high before transfer, + * go low right before transfer and + * go high again right after transfer + * + */ + +#include + +#define _L3GD20BASE 0x6200 +#define L3GD20C(_x) _IOC(_L3GD20BASE, _x) + +/* + * Sets the sensor internal sampling rate, and if a buffer + * has been configured, the rate at which entries will be + * added to the buffer. + */ +#define L3GD20_SETRATE L3GD20C(1) + +#define L3GD20_RATE_95HZ_LP_12_5HZ ((0<<7) | (0<<6) | (0<<5) | (0<<4)) +#define L3GD20_RATE_95HZ_LP_25HZ ((0<<7) | (0<<6) | (0<<5) | (1<<4)) +#define L3GD20_RATE_190HZ_LP_12_5HZ ((0<<7) | (1<<6) | (0<<5) | (0<<4)) +#define L3GD20_RATE_190HZ_LP_25HZ ((0<<7) | (1<<6) | (0<<5) | (1<<4)) +#define L3GD20_RATE_190HZ_LP_50HZ ((0<<7) | (1<<6) | (1<<5) | (0<<4)) +#define L3GD20_RATE_190HZ_LP_70HZ ((0<<7) | (1<<6) | (1<<5) | (1<<4)) +#define L3GD20_RATE_380HZ_LP_20HZ ((1<<7) | (0<<6) | (0<<5) | (0<<4)) +#define L3GD20_RATE_380HZ_LP_25HZ ((1<<7) | (0<<6) | (0<<5) | (1<<4)) +#define L3GD20_RATE_380HZ_LP_50HZ ((1<<7) | (0<<6) | (1<<5) | (0<<4)) +#define L3GD20_RATE_380HZ_LP_100HZ ((1<<7) | (0<<6) | (1<<5) | (1<<4)) +#define L3GD20_RATE_760HZ_LP_30HZ ((1<<7) | (1<<6) | (0<<5) | (0<<4)) +#define L3GD20_RATE_760HZ_LP_35HZ ((1<<7) | (1<<6) | (0<<5) | (1<<4)) +#define L3GD20_RATE_760HZ_LP_50HZ ((1<<7) | (1<<6) | (1<<5) | (0<<4)) +#define L3GD20_RATE_760HZ_LP_100HZ ((1<<7) | (1<<6) | (1<<5) | (1<<4)) + +/* + * Sets the sensor internal range. + */ +#define L3GD20_SETRANGE L3GD20C(2) + +#define L3GD20_RANGE_250DPS (0<<4) +#define L3GD20_RANGE_500DPS (1<<4) +#define L3GD20_RANGE_2000DPS (3<<4) + +#define L3GD20_RATE_95HZ ((0<<6) | (0<<4)) +#define L3GD20_RATE_190HZ ((1<<6) | (0<<4)) +#define L3GD20_RATE_380HZ ((2<<6) | (1<<4)) +#define L3GD20_RATE_760HZ ((3<<6) | (2<<4)) + + + +/* + * Sets the address of a shared l3gd20_buffer + * structure that is maintained by the driver. + * + * If zero is passed as the address, disables + * the buffer updating. + */ +#define L3GD20_SETBUFFER L3GD20C(3) + +struct l3gd20_buffer { + uint32_t size; /* number of entries in the samples[] array */ + uint32_t next; /* the next entry that will be populated */ + struct { + int16_t x; + int16_t y; + int16_t z; + } samples[]; +}; + +extern int l3gd20_attach(struct spi_dev_s *spi, int spi_id); diff --git a/nuttx/configs/px4fmu/include/drv_led.h b/nuttx/configs/px4fmu/include/drv_led.h new file mode 100644 index 0000000000..4b70933464 --- /dev/null +++ b/nuttx/configs/px4fmu/include/drv_led.h @@ -0,0 +1,51 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include + +#define _LEDCBASE 0x6800 +#define LEDC(_x) _IOC(_LEDCBASE, _x) + +/* set the LED identified by the argument */ +#define LED_ON LEDC(1) + +/* clear the LED identified by the argument */ +#define LED_OFF LEDC(2) + +///* toggle the LED identified by the argument */ +//#define LED_TOGGLE LEDC(3) + +#define LED_BLUE 0 /* Led on first port */ +#define LED_AMBER 1 /* Led on second port */ + +extern int px4fmu_led_init(void); diff --git a/nuttx/configs/px4fmu/include/drv_lis331.h b/nuttx/configs/px4fmu/include/drv_lis331.h new file mode 100644 index 0000000000..f4699cda06 --- /dev/null +++ b/nuttx/configs/px4fmu/include/drv_lis331.h @@ -0,0 +1,83 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * Driver for the ST LIS331 MEMS accelerometer + */ + +#include + +#define _LIS331BASE 0x6900 +#define LIS331C(_x) _IOC(_LIS331BASE, _x) + +/* + * Sets the sensor internal sampling rate, and if a buffer + * has been configured, the rate at which entries will be + * added to the buffer. + */ +#define LIS331_SETRATE LIS331C(1) + +#define LIS331_RATE_50Hz (0<<3) +#define LIS331_RATE_100Hz (1<<3) +#define LIS331_RATE_400Hz (2<<3) +#define LIS331_RATE_1000Hz (3<<3) + +/* + * Sets the sensor internal range. + */ +#define LIS331_SETRANGE LIS331C(2) + +#define LIS331_RANGE_2G (0<<4) +#define LIS331_RANGE_4G (1<<4) +#define LIS331_RANGE_8G (3<<4) + +/* + * Sets the address of a shared lis331_buffer + * structure that is maintained by the driver. + * + * If zero is passed as the address, disables + * the buffer updating. + */ +#define LIS331_SETBUFFER LIS331C(3) + +struct lis331_buffer { + uint32_t size; /* number of entries in the samples[] array */ + uint32_t next; /* the next entry that will be populated */ + struct { + uint16_t x; + uint16_t y; + uint16_t z; + } samples[]; +}; + +extern int lis331_attach(struct spi_dev_s *spi, int spi_id); diff --git a/nuttx/configs/px4fmu/include/drv_mpu6000.h b/nuttx/configs/px4fmu/include/drv_mpu6000.h new file mode 100644 index 0000000000..0a5a48b707 --- /dev/null +++ b/nuttx/configs/px4fmu/include/drv_mpu6000.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2012 Lorenz Meier. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of the author or 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. + */ + +/* + * Driver for the Invense MPU-6000 gyroscope + */ + +/* IMPORTANT NOTES: + * + * SPI max. clock frequency: 10 Mhz + * CS has to be high before transfer, + * go low right before transfer and + * go high again right after transfer + * + */ + +#include + +#define _MPU6000BASE 0x7600 +#define MPU6000C(_x) _IOC(_MPU6000BASE, _x) + +/* + * Sets the sensor internal sampling rate, and if a buffer + * has been configured, the rate at which entries will be + * added to the buffer. + */ +#define MPU6000_SETRATE MPU6000C(1) + +#define MPU6000_RATE_95HZ_LP_12_5HZ ((0<<7) | (0<<6) | (0<<5) | (0<<4)) + +/* + * Sets the sensor internal range. + */ +#define MPU6000_SETRANGE MPU6000C(2) + +#define MPU6000_RANGE_250DPS (0<<4) + +#define MPU6000_RATE_95HZ ((0<<6) | (0<<4)) + + + +/* + * Sets the address of a shared MPU6000_buffer + * structure that is maintained by the driver. + * + * If zero is passed as the address, disables + * the buffer updating. + */ +#define MPU6000_SETBUFFER MPU6000C(3) + +struct MPU6000_buffer { + uint32_t size; /* number of entries in the samples[] array */ + uint32_t next; /* the next entry that will be populated */ + struct { + uint16_t x; + uint16_t y; + uint16_t z; + uint16_t roll; + uint16_t pitch; + uint16_t yaw; + } samples[]; +}; + +extern int mpu6000_attach(struct spi_dev_s *spi, int spi_id); diff --git a/nuttx/configs/px4fmu/include/drv_ms5611.h b/nuttx/configs/px4fmu/include/drv_ms5611.h new file mode 100644 index 0000000000..922a112190 --- /dev/null +++ b/nuttx/configs/px4fmu/include/drv_ms5611.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2012 Lorenz Meier. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of the author or 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. + */ + +/* + * Driver for the Meas Spec MS5611 barometric pressure sensor + */ + +#include + +#define _MS5611BASE 0x6A00 +#define MS5611C(_x) _IOC(_MS5611BASE, _x) + +/* + * Sets the sensor internal sampling rate, and if a buffer + * has been configured, the rate at which entries will be + * added to the buffer. + */ +#define MS5611_SETRATE MS5611C(1) + +/* set rate (configuration A register */ +#define MS5611_RATE_0_75HZ (0 << 2) /* 0.75 Hz */ + +/* + * Sets the sensor internal range. + */ +#define MS5611_SETRANGE MS5611C(2) + +#define MS5611_RANGE_0_88GA (0 << 5) + +/* + * Sets the address of a shared MS5611_buffer + * structure that is maintained by the driver. + * + * If zero is passed as the address, disables + * the buffer updating. + */ +#define MS5611_SETBUFFER MS5611C(3) + +struct ms5611_buffer { + uint32_t size; /* number of entries in the samples[] array */ + uint32_t next; /* the next entry that will be populated */ + struct { + uint32_t pressure; + uint16_t temperature; + } samples[]; +}; + +extern int ms5611_attach(struct i2c_dev_s *i2c); diff --git a/nuttx/configs/px4fmu/include/drv_tone_alarm.h b/nuttx/configs/px4fmu/include/drv_tone_alarm.h new file mode 100644 index 0000000000..b24c85c8d0 --- /dev/null +++ b/nuttx/configs/px4fmu/include/drv_tone_alarm.h @@ -0,0 +1,130 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * Driver for the PX4 audio alarm port, /dev/tone_alarm. + * + * The tone_alarm driver supports a set of predefined "alarm" + * patterns and one user-supplied pattern. Patterns are ordered by + * priority, with a higher-priority pattern interrupting any + * lower-priority pattern that might be playing. + * + * The TONE_SET_ALARM ioctl can be used to select a predefined + * alarm pattern, from 1 - . Selecting pattern zero silences + * the alarm. + * + * To supply a custom pattern, write an array of 1 - tone_note + * structures to /dev/tone_alarm. The custom pattern has a priority + * of zero. + * + * Patterns will normally play once and then silence (if a pattern + * was overridden it will not resume). A pattern may be made to + * repeat by inserting a note with the duration set to + * DURATION_REPEAT. This pattern will loop until either a + * higher-priority pattern is started or pattern zero is requested + * via the ioctl. + */ + +#ifndef DRV_TONE_ALARM_H_ +#define DRV_TONE_ALARM_H_ + +#include + +#define _TONE_ALARM_BASE 0x7400 +#define TONE_SET_ALARM _IOC(_TONE_ALARM_BASE, 1) + +extern int tone_alarm_init(void); + +/* structure describing one note in a tone pattern */ +struct tone_note { + uint8_t pitch; + uint8_t duration; /* duration in multiples of 10ms */ +#define DURATION_END 0 /* ends the pattern */ +#define DURATION_REPEAT 255 /* resets the note counter to zero */ +}; + +enum tone_pitch { + TONE_NOTE_E4, /* E4 */ + TONE_NOTE_F4, /* F4 */ + TONE_NOTE_F4S, /* F#4/Gb4 */ + TONE_NOTE_G4, /* G4 */ + TONE_NOTE_G4S, /* G#4/Ab4 */ + TONE_NOTE_A4, /* A4 */ + TONE_NOTE_A4S, /* A#4/Bb4 */ + TONE_NOTE_B4, /* B4 */ + TONE_NOTE_C5, /* C5 */ + TONE_NOTE_C5S, /* C#5/Db5 */ + TONE_NOTE_D5, /* D5 */ + TONE_NOTE_D5S, /* D#5/Eb5 */ + TONE_NOTE_E5, /* E5 */ + TONE_NOTE_F5, /* F5 */ + TONE_NOTE_F5S, /* F#5/Gb5 */ + TONE_NOTE_G5, /* G5 */ + TONE_NOTE_G5S, /* G#5/Ab5 */ + TONE_NOTE_A5, /* A5 */ + TONE_NOTE_A5S, /* A#5/Bb5 */ + TONE_NOTE_B5, /* B5 */ + TONE_NOTE_C6, /* C6 */ + TONE_NOTE_C6S, /* C#6/Db6 */ + TONE_NOTE_D6, /* D6 */ + TONE_NOTE_D6S, /* D#6/Eb6 */ + TONE_NOTE_E6, /* E6 */ + TONE_NOTE_F6, /* F6 */ + TONE_NOTE_F6S, /* F#6/Gb6 */ + TONE_NOTE_G6, /* G6 */ + TONE_NOTE_G6S, /* G#6/Ab6 */ + TONE_NOTE_A6, /* A6 */ + TONE_NOTE_A6S, /* A#6/Bb6 */ + TONE_NOTE_B6, /* B6 */ + TONE_NOTE_C7, /* C7 */ + TONE_NOTE_C7S, /* C#7/Db7 */ + TONE_NOTE_D7, /* D7 */ + TONE_NOTE_D7S, /* D#7/Eb7 */ + TONE_NOTE_E7, /* E7 */ + TONE_NOTE_F7, /* F7 */ + TONE_NOTE_F7S, /* F#7/Gb7 */ + TONE_NOTE_G7, /* G7 */ + TONE_NOTE_G7S, /* G#7/Ab7 */ + TONE_NOTE_A7, /* A7 */ + TONE_NOTE_A7S, /* A#7/Bb7 */ + TONE_NOTE_B7, /* B7 */ + TONE_NOTE_C8, /* C8 */ + TONE_NOTE_C8S, /* C#8/Db8 */ + TONE_NOTE_D8, /* D8 */ + TONE_NOTE_D8S, /* D#8/Eb8 */ + + TONE_NOTE_SILENCE, + TONE_NOTE_MAX +}; + +#endif /* DRV_TONE_ALARM_H_ */ \ No newline at end of file diff --git a/nuttx/configs/px4fmu/include/nsh_romfsimg.h b/nuttx/configs/px4fmu/include/nsh_romfsimg.h new file mode 100644 index 0000000000..799670c4d7 --- /dev/null +++ b/nuttx/configs/px4fmu/include/nsh_romfsimg.h @@ -0,0 +1,601 @@ +unsigned char romfs_img[] = { + 0x2d, 0x72, 0x6f, 0x6d, 0x31, 0x66, 0x73, 0x2d, 0x00, 0x00, 0x18, 0x90, + 0xc0, 0x84, 0x3c, 0x72, 0x4e, 0x53, 0x48, 0x49, 0x6e, 0x69, 0x74, 0x56, + 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xff, 0x97, + 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xff, 0x80, 0x2e, 0x2e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x68, 0x2d, 0x96, 0x03, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xff, 0x00, + 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xff, 0x20, 0x2e, 0x2e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, + 0xaf, 0xce, 0x68, 0x4d, 0x72, 0x63, 0x2e, 0x6c, 0x6f, 0x67, 0x67, 0x69, + 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x21, 0x6e, 0x73, + 0x68, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, + 0x6c, 0x69, 0x73, 0x65, 0x20, 0x6c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, + 0x20, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x0a, 0x23, + 0x0a, 0x0a, 0x69, 0x66, 0x20, 0x5b, 0x20, 0x2d, 0x64, 0x20, 0x2f, 0x66, + 0x73, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x64, 0x20, 0x5d, 0x0a, + 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x23, 0x20, 0x58, 0x58, 0x58, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, + 0x62, 0x65, 0x20, 0x27, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x3e, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x27, 0x2e, 0x0a, 0x09, 0x23, + 0x20, 0x73, 0x64, 0x6c, 0x6f, 0x67, 0x20, 0x26, 0x0a, 0x66, 0x69, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xe9, 0x35, 0x68, 0x7f, 0x06, 0x72, 0x63, 0x2e, 0x50, + 0x58, 0x34, 0x49, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x21, 0x6e, 0x73, 0x68, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x46, 0x6c, + 0x69, 0x67, 0x68, 0x74, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, + 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x50, 0x58, 0x34, 0x46, 0x4d, 0x55, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x50, 0x58, 0x34, 0x49, 0x4f, 0x20, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, + 0x72, 0x20, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x0a, 0x23, 0x0a, 0x0a, + 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, 0x74, 0x5d, + 0x20, 0x64, 0x6f, 0x69, 0x6e, 0x67, 0x20, 0x50, 0x58, 0x34, 0x49, 0x4f, + 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x2e, 0x2e, 0x2e, 0x22, + 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x4f, 0x52, 0x42, 0x0a, 0x23, 0x0a, 0x75, 0x6f, + 0x72, 0x62, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0a, 0x0a, 0x23, 0x0a, + 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x2e, 0x0a, 0x23, 0x0a, 0x73, + 0x68, 0x20, 0x2f, 0x65, 0x74, 0x63, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x2e, + 0x64, 0x2f, 0x72, 0x63, 0x2e, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, + 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, + 0x4d, 0x41, 0x56, 0x4c, 0x69, 0x6e, 0x6b, 0x0a, 0x23, 0x0a, 0x6d, 0x61, + 0x76, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x2d, 0x64, 0x20, 0x2f, 0x64, 0x65, + 0x76, 0x2f, 0x74, 0x74, 0x79, 0x53, 0x30, 0x20, 0x2d, 0x62, 0x20, 0x35, + 0x37, 0x36, 0x30, 0x30, 0x20, 0x26, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x2e, 0x0a, 0x23, 0x0a, 0x23, + 0x20, 0x58, 0x58, 0x58, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x27, 0x3c, 0x63, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x3e, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x27, 0x2e, 0x0a, 0x23, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x65, 0x72, 0x20, 0x26, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x74, 0x74, 0x69, + 0x74, 0x75, 0x64, 0x65, 0x20, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, + 0x6f, 0x72, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x58, 0x58, 0x58, 0x20, 0x74, + 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, + 0x65, 0x20, 0x27, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x3e, + 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x27, 0x2e, 0x0a, 0x23, 0x0a, 0x61, + 0x74, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x5f, 0x65, 0x73, 0x74, 0x69, + 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x62, 0x6d, 0x20, 0x26, 0x0a, 0x23, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x73, 0x74, + 0x69, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x26, 0x0a, 0x0a, 0x23, 0x0a, + 0x23, 0x20, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x20, + 0x50, 0x58, 0x34, 0x46, 0x4d, 0x55, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x20, 0x50, 0x58, 0x34, 0x49, 0x4f, 0x0a, 0x23, 0x0a, 0x23, 0x20, + 0x58, 0x58, 0x58, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x3f, 0x0a, 0x23, 0x0a, 0x70, 0x78, 0x34, 0x66, 0x6d, 0x75, 0x20, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x78, + 0x65, 0x64, 0x2d, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x58, + 0x58, 0x58, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, + 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x27, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x3e, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x27, 0x2e, + 0x0a, 0x23, 0x0a, 0x66, 0x69, 0x78, 0x65, 0x64, 0x77, 0x69, 0x6e, 0x67, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x26, 0x0a, 0x0a, + 0x23, 0x0a, 0x23, 0x20, 0x46, 0x69, 0x72, 0x65, 0x20, 0x75, 0x70, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x50, 0x58, 0x34, 0x49, 0x4f, 0x20, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2e, 0x0a, 0x23, 0x0a, 0x70, + 0x78, 0x34, 0x69, 0x6f, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0a, 0x0a, + 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x6c, 0x6f, + 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, + 0x47, 0x50, 0x53, 0x2e, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x58, 0x58, 0x58, + 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x20, 0x74, 0x6f, + 0x20, 0x62, 0x65, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x65, 0x64, 0x0a, 0x23, 0x0a, 0x67, 0x70, 0x73, 0x20, 0x2d, + 0x64, 0x20, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x74, 0x74, 0x79, 0x53, 0x33, + 0x20, 0x2d, 0x6d, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x26, 0x0a, 0x0a, 0x23, + 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x6c, 0x6f, 0x67, + 0x67, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x69, 0x63, 0x72, + 0x6f, 0x53, 0x44, 0x20, 0x69, 0x66, 0x20, 0x77, 0x65, 0x20, 0x63, 0x61, + 0x6e, 0x0a, 0x23, 0x0a, 0x73, 0x68, 0x20, 0x2f, 0x65, 0x74, 0x63, 0x2f, + 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x64, 0x2f, 0x72, 0x63, 0x2e, 0x6c, 0x6f, + 0x67, 0x67, 0x69, 0x6e, 0x67, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x20, 0x69, 0x73, 0x20, 0x64, 0x6f, + 0x6e, 0x65, 0x3b, 0x20, 0x77, 0x65, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, + 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x68, + 0x65, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, + 0x77, 0x65, 0x0a, 0x23, 0x20, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x55, 0x41, 0x52, 0x54, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, + 0x20, 0x28, 0x64, 0x75, 0x6d, 0x62, 0x29, 0x2e, 0x0a, 0x23, 0x0a, 0x65, + 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, 0x74, 0x5d, 0x20, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x20, 0x64, 0x6f, 0x6e, 0x65, + 0x2c, 0x20, 0x65, 0x78, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x22, 0x0a, + 0x65, 0x78, 0x69, 0x74, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x09, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd6, + 0xf4, 0x16, 0x7b, 0x19, 0x72, 0x63, 0x2e, 0x50, 0x58, 0x34, 0x49, 0x4f, + 0x41, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x21, 0x6e, 0x73, + 0x68, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, + 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x20, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x50, 0x58, 0x34, 0x46, + 0x4d, 0x55, 0x20, 0x6f, 0x6e, 0x20, 0x50, 0x58, 0x34, 0x49, 0x4f, 0x41, + 0x52, 0x20, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x20, 0x62, 0x6f, + 0x61, 0x72, 0x64, 0x2e, 0x0a, 0x23, 0x0a, 0x0a, 0x65, 0x63, 0x68, 0x6f, + 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, 0x74, 0x5d, 0x20, 0x64, 0x6f, 0x69, + 0x6e, 0x67, 0x20, 0x50, 0x58, 0x34, 0x49, 0x4f, 0x41, 0x52, 0x20, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x2e, 0x2e, 0x2e, 0x22, 0x0a, 0x0a, + 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x4f, 0x52, 0x42, 0x0a, 0x23, 0x0a, 0x75, 0x6f, 0x72, 0x62, + 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, + 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x2e, 0x0a, 0x23, 0x0a, 0x73, 0x68, 0x20, + 0x2f, 0x65, 0x74, 0x63, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x64, 0x2f, + 0x72, 0x63, 0x2e, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x0a, 0x0a, + 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x4d, 0x41, + 0x56, 0x4c, 0x69, 0x6e, 0x6b, 0x0a, 0x23, 0x0a, 0x6d, 0x61, 0x76, 0x6c, + 0x69, 0x6e, 0x6b, 0x20, 0x2d, 0x64, 0x20, 0x2f, 0x64, 0x65, 0x76, 0x2f, + 0x74, 0x74, 0x79, 0x53, 0x30, 0x20, 0x2d, 0x62, 0x20, 0x35, 0x37, 0x36, + 0x30, 0x30, 0x20, 0x26, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x65, 0x72, 0x2e, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x58, + 0x58, 0x58, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, + 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x27, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x3e, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x27, 0x2e, + 0x0a, 0x23, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, + 0x20, 0x26, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x74, 0x74, 0x69, 0x74, 0x75, + 0x64, 0x65, 0x20, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x6f, 0x72, + 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x58, 0x58, 0x58, 0x20, 0x74, 0x68, 0x69, + 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, + 0x27, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x3e, 0x20, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x27, 0x2e, 0x0a, 0x23, 0x0a, 0x61, 0x74, 0x74, + 0x69, 0x74, 0x75, 0x64, 0x65, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, + 0x74, 0x6f, 0x72, 0x5f, 0x62, 0x6d, 0x20, 0x26, 0x0a, 0x23, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, + 0x61, 0x74, 0x6f, 0x72, 0x20, 0x26, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x20, 0x50, 0x58, + 0x34, 0x46, 0x4d, 0x55, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x50, 0x58, 0x34, 0x49, 0x4f, 0x41, 0x52, 0x0a, 0x23, 0x0a, 0x23, 0x20, + 0x58, 0x58, 0x58, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x3f, 0x0a, 0x23, 0x0a, 0x70, 0x78, 0x34, 0x66, 0x6d, 0x75, 0x20, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x46, + 0x69, 0x72, 0x65, 0x20, 0x75, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, + 0x52, 0x2e, 0x44, 0x72, 0x6f, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x0a, 0x23, 0x0a, 0x23, 0x20, + 0x58, 0x58, 0x58, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, + 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x27, 0x3c, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x3e, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x27, + 0x2e, 0x0a, 0x23, 0x0a, 0x61, 0x72, 0x64, 0x72, 0x6f, 0x6e, 0x65, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x2d, 0x64, 0x20, 0x2f, + 0x64, 0x65, 0x76, 0x2f, 0x74, 0x74, 0x79, 0x53, 0x31, 0x20, 0x2d, 0x6d, + 0x20, 0x61, 0x74, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x20, 0x26, 0x0a, + 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x6c, + 0x6f, 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, + 0x20, 0x47, 0x50, 0x53, 0x2e, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x58, 0x58, + 0x58, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, + 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x20, 0x74, + 0x6f, 0x20, 0x62, 0x65, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x65, 0x64, 0x0a, 0x23, 0x0a, 0x67, 0x70, 0x73, 0x20, + 0x2d, 0x64, 0x20, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x74, 0x74, 0x79, 0x53, + 0x33, 0x20, 0x2d, 0x6d, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x26, 0x0a, 0x0a, + 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x6c, 0x6f, + 0x67, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x69, 0x63, + 0x72, 0x6f, 0x53, 0x44, 0x20, 0x69, 0x66, 0x20, 0x77, 0x65, 0x20, 0x63, + 0x61, 0x6e, 0x0a, 0x23, 0x0a, 0x73, 0x68, 0x20, 0x2f, 0x65, 0x74, 0x63, + 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x64, 0x2f, 0x72, 0x63, 0x2e, 0x6c, + 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x20, 0x69, 0x73, 0x20, 0x64, + 0x6f, 0x6e, 0x65, 0x3b, 0x20, 0x77, 0x65, 0x20, 0x64, 0x6f, 0x6e, 0x27, + 0x74, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x68, 0x65, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, + 0x20, 0x77, 0x65, 0x0a, 0x23, 0x20, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x55, 0x41, 0x52, 0x54, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, + 0x79, 0x20, 0x28, 0x64, 0x75, 0x6d, 0x62, 0x29, 0x2e, 0x0a, 0x23, 0x0a, + 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, 0x74, 0x5d, + 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x20, 0x64, 0x6f, 0x6e, + 0x65, 0x2c, 0x20, 0x65, 0x78, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x22, + 0x0a, 0x65, 0x78, 0x69, 0x74, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x6e, 0xb5, 0xbb, 0x51, 0xae, 0x72, 0x63, 0x2e, 0x73, + 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x21, 0x6e, 0x73, 0x68, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, + 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x75, 0x70, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x50, 0x58, 0x34, 0x46, 0x4d, 0x55, 0x20, 0x6f, 0x6e, 0x62, + 0x6f, 0x61, 0x72, 0x64, 0x20, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x20, + 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x0a, 0x23, 0x0a, 0x0a, + 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x73, 0x65, + 0x6e, 0x73, 0x6f, 0x72, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, + 0x20, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x0a, 0x23, 0x0a, 0x0a, 0x23, 0x6d, + 0x73, 0x35, 0x36, 0x31, 0x31, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0a, + 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x20, 0x63, 0x6f, + 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x61, 0x73, + 0x6b, 0x2e, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x58, 0x58, 0x58, 0x20, 0x73, + 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x27, 0x73, 0x65, + 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x27, + 0x0a, 0x23, 0x0a, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x20, 0x26, + 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x73, + 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x0a, 0x23, 0x0a, 0x23, 0x20, + 0x58, 0x58, 0x58, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, + 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x27, 0x73, 0x65, 0x6e, 0x73, + 0x6f, 0x72, 0x73, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x27, 0x20, 0x3f, + 0x0a, 0x23, 0x0a, 0x23, 0x69, 0x66, 0x20, 0x73, 0x65, 0x6e, 0x73, 0x6f, + 0x72, 0x73, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x74, 0x65, 0x73, 0x74, + 0x0a, 0x23, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x23, 0x09, 0x65, 0x63, 0x68, + 0x6f, 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, 0x74, 0x5d, 0x20, 0x73, 0x65, + 0x6e, 0x73, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, + 0x69, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x46, 0x41, 0x49, 0x4c, + 0x45, 0x44, 0x2e, 0x22, 0x0a, 0x23, 0x09, 0x72, 0x65, 0x62, 0x6f, 0x6f, + 0x74, 0x0a, 0x23, 0x66, 0x69, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xf2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcd, 0x52, 0xce, 0xe0, 0xfc, + 0x72, 0x63, 0x2e, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, + 0x65, 0x00, 0x00, 0x00, 0x23, 0x21, 0x6e, 0x73, 0x68, 0x0a, 0x23, 0x0a, + 0x23, 0x20, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x75, 0x70, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x50, 0x58, 0x34, 0x46, 0x4d, 0x55, 0x20, 0x73, + 0x74, 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x0a, 0x23, 0x0a, 0x0a, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, + 0x6e, 0x69, 0x74, 0x5d, 0x20, 0x64, 0x6f, 0x69, 0x6e, 0x67, 0x20, 0x73, + 0x74, 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x20, 0x50, 0x58, + 0x34, 0x46, 0x4d, 0x55, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, + 0x2e, 0x2e, 0x2e, 0x22, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4f, 0x52, 0x42, 0x0a, + 0x23, 0x0a, 0x23, 0x75, 0x6f, 0x72, 0x62, 0x20, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, + 0x2e, 0x0a, 0x23, 0x0a, 0x23, 0x73, 0x68, 0x20, 0x2f, 0x65, 0x74, 0x63, + 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x64, 0x2f, 0x72, 0x63, 0x2e, 0x73, + 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x4d, 0x41, 0x56, 0x4c, 0x69, 0x6e, + 0x6b, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x6d, 0x61, 0x76, 0x6c, 0x69, 0x6e, + 0x6b, 0x20, 0x2d, 0x64, 0x20, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x74, 0x74, + 0x79, 0x53, 0x30, 0x20, 0x2d, 0x62, 0x20, 0x35, 0x37, 0x36, 0x30, 0x30, + 0x20, 0x26, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x65, 0x72, 0x2e, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x58, 0x58, 0x58, + 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, + 0x20, 0x62, 0x65, 0x20, 0x27, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x65, 0x72, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x27, 0x2e, 0x0a, 0x23, + 0x0a, 0x23, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x20, + 0x26, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x74, 0x74, 0x69, 0x74, 0x75, 0x64, + 0x65, 0x20, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x0a, + 0x23, 0x0a, 0x23, 0x20, 0x58, 0x58, 0x58, 0x20, 0x74, 0x68, 0x69, 0x73, + 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x27, + 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x3e, 0x20, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x27, 0x2e, 0x0a, 0x23, 0x0a, 0x23, 0x61, 0x74, 0x74, + 0x69, 0x74, 0x75, 0x64, 0x65, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, + 0x74, 0x6f, 0x72, 0x5f, 0x62, 0x6d, 0x20, 0x26, 0x0a, 0x23, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, + 0x61, 0x74, 0x6f, 0x72, 0x20, 0x26, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, + 0x78, 0x65, 0x64, 0x2d, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x0a, 0x23, 0x0a, 0x23, + 0x20, 0x58, 0x58, 0x58, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, + 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, + 0x20, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x0a, 0x23, 0x20, 0x77, 0x68, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, + 0x61, 0x72, 0x64, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x69, + 0x78, 0x65, 0x64, 0x2d, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, + 0x3f, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x58, 0x58, 0x58, 0x20, 0x74, 0x68, + 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, + 0x20, 0x27, 0x66, 0x69, 0x78, 0x65, 0x64, 0x77, 0x69, 0x6e, 0x67, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x27, 0x2e, 0x0a, 0x23, 0x0a, 0x23, 0x66, 0x69, 0x78, 0x65, 0x64, + 0x77, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x20, 0x26, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x65, 0x20, 0x46, 0x4d, 0x55, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, + 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x58, 0x58, + 0x58, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x3f, + 0x0a, 0x23, 0x0a, 0x23, 0x70, 0x78, 0x34, 0x66, 0x6d, 0x75, 0x20, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x47, 0x50, 0x53, 0x2e, 0x0a, 0x23, + 0x0a, 0x23, 0x20, 0x58, 0x58, 0x58, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, + 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6e, + 0x65, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x62, 0x61, + 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x65, 0x64, 0x0a, 0x23, + 0x0a, 0x23, 0x67, 0x70, 0x73, 0x20, 0x2d, 0x64, 0x20, 0x2f, 0x64, 0x65, + 0x76, 0x2f, 0x74, 0x74, 0x79, 0x53, 0x33, 0x20, 0x2d, 0x6d, 0x20, 0x61, + 0x6c, 0x6c, 0x20, 0x26, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x20, 0x6c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x20, + 0x74, 0x6f, 0x20, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x53, 0x44, 0x20, 0x69, + 0x66, 0x20, 0x77, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x0a, 0x23, 0x0a, 0x73, + 0x68, 0x20, 0x2f, 0x65, 0x74, 0x63, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x2e, + 0x64, 0x2f, 0x72, 0x63, 0x2e, 0x6c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, + 0x0a, 0x0a, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, + 0x74, 0x5d, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x20, 0x64, + 0x6f, 0x6e, 0x65, 0x22, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x76, 0x8d, 0x9c, 0xa3, 0x80, + 0x72, 0x63, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x23, 0x21, 0x6e, 0x73, 0x68, 0x0a, 0x23, 0x0a, + 0x23, 0x20, 0x50, 0x58, 0x34, 0x46, 0x4d, 0x55, 0x20, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x75, 0x70, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2e, + 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x3a, + 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x2d, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69, 0x63, 0x72, + 0x6f, 0x53, 0x44, 0x20, 0x63, 0x61, 0x72, 0x64, 0x20, 0x28, 0x69, 0x66, + 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x29, 0x0a, 0x23, 0x20, + 0x2d, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x75, 0x70, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x66, 0x72, + 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69, 0x63, 0x72, 0x6f, + 0x53, 0x44, 0x20, 0x63, 0x61, 0x72, 0x64, 0x20, 0x28, 0x69, 0x66, 0x20, + 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x29, 0x0a, 0x23, 0x20, 0x2d, + 0x20, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, + 0x69, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x73, 0x75, 0x69, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x23, 0x20, 0x20, 0x20, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x75, 0x70, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x4e, 0x6f, + 0x74, 0x65, 0x3a, 0x20, 0x44, 0x4f, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x61, + 0x64, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, + 0x63, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x3b, 0x0a, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, + 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x74, 0x6f, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x70, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, + 0x2e, 0x0a, 0x23, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x44, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2e, + 0x20, 0x20, 0x41, 0x6e, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x20, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x53, 0x44, 0x20, 0x63, 0x61, 0x72, 0x64, + 0x0a, 0x23, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x20, + 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x69, 0x67, 0x68, + 0x74, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2e, 0x0a, 0x23, 0x0a, + 0x73, 0x65, 0x74, 0x20, 0x4d, 0x4f, 0x44, 0x45, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x55, + 0x53, 0x42, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x45, 0x44, 0x20, 0x79, + 0x65, 0x73, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x55, 0x53, 0x42, 0x20, 0x6e, + 0x6f, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x54, 0x72, 0x79, 0x20, 0x74, + 0x6f, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x53, 0x44, 0x20, 0x63, 0x61, 0x72, 0x64, + 0x2e, 0x0a, 0x23, 0x0a, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, + 0x6e, 0x69, 0x74, 0x5d, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x69, 0x6e, 0x67, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x53, 0x44, + 0x2e, 0x2e, 0x2e, 0x22, 0x0a, 0x69, 0x66, 0x20, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x20, 0x2d, 0x74, 0x20, 0x76, 0x66, 0x61, 0x74, 0x20, 0x2f, 0x64, + 0x65, 0x76, 0x2f, 0x6d, 0x6d, 0x63, 0x73, 0x64, 0x30, 0x20, 0x2f, 0x66, + 0x73, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x64, 0x0a, 0x74, 0x68, + 0x65, 0x6e, 0x0a, 0x09, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, + 0x6e, 0x69, 0x74, 0x5d, 0x20, 0x63, 0x61, 0x72, 0x64, 0x20, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x61, 0x74, 0x20, 0x2f, 0x66, 0x73, + 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x64, 0x22, 0x0a, 0x65, 0x6c, + 0x73, 0x65, 0x0a, 0x09, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, + 0x6e, 0x69, 0x74, 0x5d, 0x20, 0x6e, 0x6f, 0x20, 0x6d, 0x69, 0x63, 0x72, + 0x6f, 0x53, 0x44, 0x20, 0x63, 0x61, 0x72, 0x64, 0x20, 0x66, 0x6f, 0x75, + 0x6e, 0x64, 0x22, 0x0a, 0x66, 0x69, 0x0a, 0x0a, 0x23, 0x0a, 0x23, 0x20, + 0x4c, 0x6f, 0x6f, 0x6b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, + 0x69, 0x6e, 0x69, 0x74, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, + 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69, 0x63, 0x72, 0x6f, + 0x53, 0x44, 0x20, 0x63, 0x61, 0x72, 0x64, 0x2e, 0x0a, 0x23, 0x0a, 0x23, + 0x20, 0x54, 0x6f, 0x20, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x20, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x75, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x69, + 0x67, 0x68, 0x74, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2c, 0x0a, 0x23, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, + 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20, 0x4d, 0x4f, + 0x44, 0x45, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6f, + 0x74, 0x68, 0x65, 0x72, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x0a, + 0x23, 0x0a, 0x69, 0x66, 0x20, 0x5b, 0x20, 0x2d, 0x66, 0x20, 0x2f, 0x66, + 0x73, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x64, 0x2f, 0x65, 0x74, + 0x63, 0x2f, 0x72, 0x63, 0x20, 0x5d, 0x0a, 0x74, 0x68, 0x65, 0x6e, 0x0a, + 0x09, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, 0x74, + 0x5d, 0x20, 0x72, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x2f, 0x66, + 0x73, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x64, 0x2f, 0x65, 0x74, + 0x63, 0x2f, 0x72, 0x63, 0x22, 0x0a, 0x09, 0x73, 0x68, 0x20, 0x2f, 0x66, + 0x73, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x64, 0x2f, 0x65, 0x74, + 0x63, 0x2f, 0x72, 0x63, 0x0a, 0x66, 0x69, 0x0a, 0x0a, 0x23, 0x0a, 0x23, + 0x20, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x55, + 0x53, 0x42, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x0a, 0x23, 0x0a, 0x69, 0x66, + 0x20, 0x5b, 0x20, 0x24, 0x55, 0x53, 0x42, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, + 0x57, 0x45, 0x44, 0x20, 0x3d, 0x3d, 0x20, 0x79, 0x65, 0x73, 0x20, 0x5d, + 0x0a, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x73, 0x65, + 0x72, 0x63, 0x6f, 0x6e, 0x0a, 0x09, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, + 0x09, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, 0x74, + 0x5d, 0x20, 0x55, 0x53, 0x42, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, + 0x61, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, + 0x64, 0x22, 0x0a, 0x09, 0x66, 0x69, 0x0a, 0x66, 0x69, 0x0a, 0x0a, 0x23, + 0x0a, 0x23, 0x20, 0x49, 0x66, 0x20, 0x77, 0x65, 0x20, 0x61, 0x72, 0x65, + 0x20, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x66, 0x6c, + 0x69, 0x67, 0x68, 0x74, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x77, + 0x6f, 0x72, 0x6b, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x77, 0x68, 0x61, 0x74, + 0x20, 0x61, 0x69, 0x72, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x0a, 0x23, + 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x77, 0x65, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x75, 0x70, 0x20, + 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x6c, 0x79, 0x2e, + 0x0a, 0x23, 0x0a, 0x69, 0x66, 0x20, 0x5b, 0x20, 0x24, 0x4d, 0x4f, 0x44, + 0x45, 0x20, 0x21, 0x3d, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x20, 0x5d, 0x0a, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x65, + 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, 0x74, 0x5d, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x20, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x75, 0x70, 0x20, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x6c, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x0a, 0x65, 0x6c, 0x73, 0x65, + 0x0a, 0x09, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, + 0x74, 0x5d, 0x20, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6e, 0x67, + 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x20, 0x68, 0x61, + 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x2e, 0x2e, 0x22, 0x0a, 0x0a, + 0x09, 0x23, 0x0a, 0x09, 0x23, 0x20, 0x41, 0x73, 0x73, 0x75, 0x6d, 0x65, + 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x20, 0x61, 0x72, 0x65, + 0x20, 0x50, 0x58, 0x34, 0x46, 0x4d, 0x55, 0x20, 0x69, 0x6e, 0x20, 0x73, + 0x74, 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x20, 0x6d, 0x6f, + 0x64, 0x65, 0x0a, 0x09, 0x23, 0x0a, 0x09, 0x73, 0x65, 0x74, 0x20, 0x42, + 0x4f, 0x41, 0x52, 0x44, 0x20, 0x50, 0x58, 0x34, 0x46, 0x4d, 0x55, 0x0a, + 0x0a, 0x09, 0x23, 0x0a, 0x09, 0x23, 0x20, 0x41, 0x72, 0x65, 0x20, 0x77, + 0x65, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x20, 0x74, + 0x6f, 0x20, 0x61, 0x20, 0x50, 0x58, 0x34, 0x49, 0x4f, 0x41, 0x52, 0x20, + 0x28, 0x41, 0x52, 0x2e, 0x44, 0x72, 0x6f, 0x6e, 0x65, 0x20, 0x63, 0x61, + 0x72, 0x72, 0x69, 0x65, 0x72, 0x20, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x29, + 0x3f, 0x0a, 0x09, 0x23, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x62, 0x6f, 0x61, + 0x72, 0x64, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x2d, 0x74, 0x20, 0x37, 0x0a, + 0x09, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x09, 0x73, 0x65, 0x74, 0x20, + 0x42, 0x4f, 0x41, 0x52, 0x44, 0x20, 0x50, 0x58, 0x34, 0x49, 0x4f, 0x41, + 0x52, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x5b, 0x20, 0x2d, 0x66, 0x20, + 0x2f, 0x65, 0x74, 0x63, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x64, 0x2f, + 0x72, 0x63, 0x2e, 0x50, 0x58, 0x34, 0x49, 0x4f, 0x41, 0x52, 0x20, 0x5d, + 0x0a, 0x09, 0x09, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x09, 0x09, 0x65, + 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, 0x74, 0x5d, 0x20, + 0x72, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x2f, 0x65, 0x74, 0x63, + 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x64, 0x2f, 0x72, 0x63, 0x2e, 0x50, + 0x58, 0x34, 0x49, 0x4f, 0x41, 0x52, 0x22, 0x0a, 0x09, 0x09, 0x09, 0x73, + 0x68, 0x20, 0x2f, 0x65, 0x74, 0x63, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x2e, + 0x64, 0x2f, 0x72, 0x63, 0x2e, 0x50, 0x58, 0x34, 0x49, 0x4f, 0x41, 0x52, + 0x0a, 0x09, 0x09, 0x66, 0x69, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0a, + 0x09, 0x09, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, + 0x74, 0x5d, 0x20, 0x50, 0x58, 0x34, 0x49, 0x4f, 0x41, 0x52, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x22, + 0x0a, 0x09, 0x66, 0x69, 0x0a, 0x0a, 0x09, 0x23, 0x0a, 0x09, 0x23, 0x20, + 0x41, 0x72, 0x65, 0x20, 0x77, 0x65, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, + 0x68, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x50, 0x58, 0x34, + 0x49, 0x4f, 0x3f, 0x0a, 0x09, 0x23, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x62, + 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x2d, 0x74, 0x20, + 0x36, 0x0a, 0x09, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x09, 0x73, 0x65, + 0x74, 0x20, 0x42, 0x4f, 0x41, 0x52, 0x44, 0x20, 0x50, 0x58, 0x34, 0x49, + 0x4f, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x5b, 0x20, 0x2d, 0x66, 0x20, + 0x2f, 0x65, 0x74, 0x63, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x64, 0x2f, + 0x72, 0x63, 0x2e, 0x50, 0x58, 0x34, 0x49, 0x4f, 0x20, 0x5d, 0x0a, 0x09, + 0x09, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x09, 0x09, 0x65, 0x63, 0x68, + 0x6f, 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, 0x74, 0x5d, 0x20, 0x72, 0x65, + 0x61, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x2f, 0x65, 0x74, 0x63, 0x2f, 0x69, + 0x6e, 0x69, 0x74, 0x2e, 0x64, 0x2f, 0x72, 0x63, 0x2e, 0x50, 0x58, 0x34, + 0x49, 0x4f, 0x22, 0x0a, 0x09, 0x09, 0x09, 0x73, 0x68, 0x20, 0x2f, 0x65, + 0x74, 0x63, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x64, 0x2f, 0x72, 0x63, + 0x2e, 0x50, 0x58, 0x34, 0x49, 0x4f, 0x0a, 0x09, 0x09, 0x66, 0x69, 0x0a, + 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x09, 0x09, 0x65, 0x63, 0x68, 0x6f, + 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, 0x74, 0x5d, 0x20, 0x50, 0x58, 0x34, + 0x49, 0x4f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x64, 0x65, 0x74, 0x65, 0x63, + 0x74, 0x65, 0x64, 0x22, 0x0a, 0x09, 0x66, 0x69, 0x0a, 0x0a, 0x09, 0x23, + 0x0a, 0x09, 0x23, 0x20, 0x4c, 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x6c, 0x69, + 0x6b, 0x65, 0x20, 0x77, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x74, + 0x61, 0x6e, 0x64, 0x2d, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x0a, 0x09, 0x23, + 0x0a, 0x09, 0x69, 0x66, 0x20, 0x5b, 0x20, 0x24, 0x42, 0x4f, 0x41, 0x52, + 0x44, 0x20, 0x3d, 0x3d, 0x20, 0x50, 0x58, 0x34, 0x46, 0x4d, 0x55, 0x20, + 0x5d, 0x0a, 0x09, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x09, 0x65, 0x63, + 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, 0x6e, 0x69, 0x74, 0x5d, 0x20, 0x6e, + 0x6f, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x20, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x22, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x5b, 0x20, 0x2d, + 0x66, 0x20, 0x2f, 0x65, 0x74, 0x63, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x2e, + 0x64, 0x2f, 0x72, 0x63, 0x2e, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x6c, + 0x6f, 0x6e, 0x65, 0x20, 0x5d, 0x0a, 0x09, 0x09, 0x74, 0x68, 0x65, 0x6e, + 0x0a, 0x09, 0x09, 0x09, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x5b, 0x69, + 0x6e, 0x69, 0x74, 0x5d, 0x20, 0x72, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, + 0x20, 0x2f, 0x65, 0x74, 0x63, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x64, + 0x2f, 0x72, 0x63, 0x2e, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6f, + 0x6e, 0x65, 0x22, 0x0a, 0x09, 0x09, 0x09, 0x73, 0x68, 0x20, 0x2f, 0x65, + 0x74, 0x63, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x64, 0x2f, 0x72, 0x63, + 0x2e, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x0a, + 0x09, 0x09, 0x66, 0x69, 0x0a, 0x09, 0x66, 0x69, 0x0a, 0x0a, 0x09, 0x23, + 0x0a, 0x09, 0x23, 0x20, 0x57, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x63, 0x68, 0x20, 0x68, 0x65, 0x72, + 0x65, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, + 0x66, 0x72, 0x61, 0x6d, 0x65, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, + 0x69, 0x63, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x65, 0x78, + 0x69, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x68, 0x65, 0x6c, + 0x6c, 0x2e, 0x0a, 0x09, 0x23, 0x0a, 0x09, 0x65, 0x63, 0x68, 0x6f, 0x20, + 0x22, 0x5b, 0x69, 0x6e, 0x69, 0x74, 0x5d, 0x20, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x75, 0x70, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x2e, 0x22, 0x0a, 0x66, + 0x69, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int romfs_img_len = 7168; diff --git a/nuttx/configs/px4fmu/include/rcS.template b/nuttx/configs/px4fmu/include/rcS.template new file mode 100644 index 0000000000..2f97a72239 --- /dev/null +++ b/nuttx/configs/px4fmu/include/rcS.template @@ -0,0 +1,39 @@ +#echo "---------------------------" +# Start apps +echo "init: Starting applications.." +echo "---------------------------" +# WARNING: +# ttyS0 is ALWAYS the NSH UART +# ttyS1..SN are enumerated according to HW +# uart indices (ttyS1 is the first UART NOT +# configured for NSH, e.g. UART2) +# ttyS0: UART1 +# ttyS1: UART2 +# ttyS2: UART5 +# ttyS3: UART6 +uorb start +mavlink -d /dev/ttyS0 -b 57600 & +echo "Trying to mount microSD card to /fs/microsd.." +if mount -t vfat /dev/mmcsd0 /fs/microsd +then +echo "Successfully mounted SD card." +else +echo "FAILED mounting SD card." +fi +commander & +sensors & +attitude_estimator_bm & +#position_estimator & +ardrone_control -d /dev/ttyS1 -m attitude & +gps -d /dev/ttyS3 -m all & +#sdlog & +#fixedwing_control & +echo "---------------------------" +echo "init: All applications started" +echo "INIT DONE, RUNNING SYSTEM.." + + +# WARNING! USE EXIT ONLY ON AR.DRONE +# NO NSH COMMANDS CAN BE USED AFTER + +exit diff --git a/nuttx/configs/px4fmu/include/up_adc.h b/nuttx/configs/px4fmu/include/up_adc.h new file mode 100644 index 0000000000..699c6a59af --- /dev/null +++ b/nuttx/configs/px4fmu/include/up_adc.h @@ -0,0 +1,60 @@ +/************************************************************************************ + * configs/stm3240g-eval/src/up_adc.c + * arch/arm/src/board/up_adc.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#ifdef CONFIG_ADC + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: adc_devinit + * + * Description: + * All STM32 architectures must provide the following interface to work with + * examples/adc. + * + ************************************************************************************/ + +int adc_devinit(void); + +#endif /* CONFIG_ADC */ diff --git a/nuttx/configs/px4fmu/include/up_cpuload.h b/nuttx/configs/px4fmu/include/up_cpuload.h new file mode 100644 index 0000000000..b61c5c550d --- /dev/null +++ b/nuttx/configs/px4fmu/include/up_cpuload.h @@ -0,0 +1,62 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef UP_CPULOAD_H_ +#define UP_CPULOAD_H_ + +#ifdef CONFIG_SCHED_INSTRUMENTATION + +#include + +struct system_load_taskinfo_s { + uint64_t total_runtime; ///< Runtime since start (start_time - total_runtime)/(start_time - current_time) = load + uint64_t curr_start_time; ///< Start time of the current scheduling slot + uint64_t start_time; ///< FIRST start time of task + FAR struct _TCB *tcb; ///< + bool valid; ///< Task is currently active / valid +}; + +struct system_load_s { + uint64_t start_time; ///< Global start time of measurements + struct system_load_taskinfo_s tasks[CONFIG_MAX_TASKS]; + uint8_t initialized; + int total_count; + int running_count; + int sleeping_count; +}; + +void cpuload_initialize_once(void); + +#endif + +#endif diff --git a/nuttx/configs/px4fmu/include/up_hrt.h b/nuttx/configs/px4fmu/include/up_hrt.h new file mode 100644 index 0000000000..6fd66ad746 --- /dev/null +++ b/nuttx/configs/px4fmu/include/up_hrt.h @@ -0,0 +1,130 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * High-resolution timer callouts and timekeeping. + */ + +#ifndef UP_HRT_H_ +#define UP_HRT_H_ + +#include +#include + +#include +#include + +/* + * Absolute time, in microsecond units. + * + * Absolute time is measured from some arbitrary epoch shortly after + * system startup. It should never wrap or go backwards. + */ +typedef uint64_t hrt_abstime; + +/* + * Callout function type. + * + * Note that callouts run in the timer interrupt context, so + * they are serialised with respect to each other, and must not + * block. + */ +typedef void (* hrt_callout)(void *arg); + +/* + * Callout record. + */ +typedef struct hrt_call { + struct sq_entry_s link; + + hrt_abstime deadline; + hrt_abstime period; + hrt_callout callout; + void *arg; +} *hrt_call_t; + +/* + * Get absolute time. + */ +extern hrt_abstime hrt_absolute_time(void); + +/* + * Convert a timespec to absolute time. + */ +extern hrt_abstime ts_to_abstime(struct timespec *ts); + +/* + * Convert absolute time to a timespec. + */ +extern void abstime_to_ts(struct timespec *ts, hrt_abstime abstime); + +/* + * Call callout(arg) after delay has elapsed. + * + * If callout is NULL, this can be used to implement a timeout by testing the call + * with hrt_called(). + */ +extern void hrt_call_after(struct hrt_call *entry, hrt_abstime delay, hrt_callout callout, void *arg); + +/* + * Call callout(arg) at absolute time calltime. + */ +extern void hrt_call_at(struct hrt_call *entry, hrt_abstime calltime, hrt_callout callout, void *arg); + +/* + * Call callout(arg) after delay, and then after every interval. + * + * Note thet the interval is timed between scheduled, not actual, call times, so the call rate may + * jitter but should not drift. + */ +extern void hrt_call_every(struct hrt_call *entry, hrt_abstime delay, hrt_abstime interval, hrt_callout callout, void *arg); + +/* + * If this returns true, the entry has been invoked and removed from the callout list, + * or it has never been entered. + * + * Always returns false for repeating callouts. + */ +extern bool hrt_called(struct hrt_call *entry); + +/* + * Remove the entry from the callout list. + */ +extern void hrt_cancel(struct hrt_call *entry); + +/* + * Initialise the HRT. + */ +extern void hrt_init(void); + +#endif /* UP_HRT_H_ */ diff --git a/nuttx/configs/px4fmu/include/up_pwm_servo.h b/nuttx/configs/px4fmu/include/up_pwm_servo.h new file mode 100644 index 0000000000..0b35035d54 --- /dev/null +++ b/nuttx/configs/px4fmu/include/up_pwm_servo.h @@ -0,0 +1,117 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * Low-level PWM servo control. + * + * The pwm_servo module supports servos connected to STM32 timer + * blocks. + * + * On PX4FMU, the outputs are: + * + * 0 : USART2/multi CTS + * 1 : USART2/multi RTS + * 2 : USART2/multi TX + * 3 : USART2/multi RX + * 4 : CAN2 TX + * 5 : CAN2 RX + */ + +#ifndef UP_PWM_SERVO_H +#define UP_PWM_SERVO_H + +typedef uint16_t servo_position_t; + + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * Intialise the PWM servo outputs using the specified configuration. + * + * @param channel_mask Bitmask of channels (LSB = channel 0) to enable. + * This allows some of the channels to remain configured + * as GPIOs or as another function. + * @return OK on success. + */ +extern int up_pwm_servo_init(uint32_t channel_mask); + +/** + * De-initialise the PWM servo outputs. + */ +extern void up_pwm_servo_deinit(void); + +/** + * Arm or disarm servo outputs. + * + * When disarmed, servos output no pulse. + * + * @bug This function should, but does not, guarantee that any pulse + * currently in progress is cleanly completed. + * + * @param armed If true, outputs are armed; if false they + * are disarmed. + */ +extern void up_pwm_servo_arm(bool armed); + +/** + * Set the servo update rate + * + * @param rate The update rate in Hz to set. + * @return OK on success, -ERANGE if an unsupported update rate is set. + */ +extern int up_pwm_servo_set_rate(unsigned rate); + +/** + * Set the current output value for a channel. + * + * @param channel The channel to set. + * @param value The output pulse width in microseconds. + */ +extern int up_pwm_servo_set(unsigned channel, servo_position_t value); + +/** + * Get the current output value for a channel. + * + * @param channel The channel to read. + * @return The output pulse width in microseconds, or zero if + * outputs are not armed or not configured. + */ +extern servo_position_t up_pwm_servo_get(unsigned channel); + +#if defined(__cplusplus) +} +#endif + +#endif /* UP_PWM_SERVO_H */ diff --git a/nuttx/configs/px4fmu/nsh/Make.defs b/nuttx/configs/px4fmu/nsh/Make.defs new file mode 100644 index 0000000000..87508e22ec --- /dev/null +++ b/nuttx/configs/px4fmu/nsh/Make.defs @@ -0,0 +1,3 @@ +include ${TOPDIR}/.config + +include $(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/common/Make.defs diff --git a/nuttx/configs/px4fmu/nsh/appconfig b/nuttx/configs/px4fmu/nsh/appconfig new file mode 100644 index 0000000000..85762f4c6b --- /dev/null +++ b/nuttx/configs/px4fmu/nsh/appconfig @@ -0,0 +1,92 @@ +############################################################################ +# configs/px4fmu/nsh/appconfig +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Path to example in apps/examples containing the user_start entry point + +CONFIGURED_APPS += examples/nsh + +# The NSH application library +CONFIGURED_APPS += nshlib +CONFIGURED_APPS += system/readline + +# System library - utility functions +CONFIGURED_APPS += systemlib + +CONFIGURED_APPS += systemcmds/reboot +CONFIGURED_APPS += systemcmds/perf +CONFIGURED_APPS += systemcmds/top +CONFIGURED_APPS += systemcmds/boardinfo +#CONFIGURED_APPS += systemcmds/calibration + +CONFIGURED_APPS += uORB + +ifeq ($(CONFIG_MAVLINK),y) +CONFIGURED_APPS += mavlink +endif + +CONFIGURED_APPS += gps +CONFIGURED_APPS += commander +#CONFIGURED_APPS += sdlog +CONFIGURED_APPS += sensors +CONFIGURED_APPS += ardrone_control +CONFIGURED_APPS += px4/attitude_estimator_bm +CONFIGURED_APPS += fixedwing_control +CONFIGURED_APPS += mix_and_link +CONFIGURED_APPS += position_estimator +CONFIGURED_APPS += attitude_estimator_ekf + +#CONFIGURED_APPS += system/i2c +#CONFIGURED_APPS += tools/i2c_dev + +# Communication and Drivers +CONFIGURED_APPS += drivers/device +#CONFIGURED_APPS += drivers/ms5611 +CONFIGURED_APPS += px4/px4io/driver +CONFIGURED_APPS += px4/fmu + +# Testing stuff +CONFIGURED_APPS += px4/sensors_bringup +CONFIGURED_APPS += px4/tests + +ifeq ($(CONFIG_CAN),y) +#CONFIGURED_APPS += examples/can +endif + +#ifeq ($(CONFIG_USBDEV),y) +#ifeq ($(CONFIG_CDCACM),y) +CONFIGURED_APPS += examples/cdcacm +#endif +#endif + diff --git a/nuttx/configs/px4fmu/nsh/defconfig b/nuttx/configs/px4fmu/nsh/defconfig new file mode 100755 index 0000000000..58c9ca45cd --- /dev/null +++ b/nuttx/configs/px4fmu/nsh/defconfig @@ -0,0 +1,1053 @@ +############################################################################ +# configs/px4fmu/nsh/defconfig +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ +# +# architecture selection +# +# CONFIG_ARCH - identifies the arch subdirectory and, hence, the +# processor architecture. +# CONFIG_ARCH_family - for use in C code. This identifies the +# particular chip family that the architecture is implemented +# in. +# CONFIG_ARCH_architecture - for use in C code. This identifies the +# specific architecture within the chip familyl. +# CONFIG_ARCH_CHIP - Identifies the arch/*/chip subdirectory +# CONFIG_ARCH_CHIP_name - For use in C code +# CONFIG_ARCH_BOARD - identifies the configs subdirectory and, hence, +# the board that supports the particular chip or SoC. +# CONFIG_ARCH_BOARD_name - for use in C code +# CONFIG_ENDIAN_BIG - define if big endian (default is little endian) +# CONFIG_BOARD_LOOPSPERMSEC - for delay loops +# CONFIG_DRAM_SIZE - Describes the installed DRAM. +# CONFIG_DRAM_START - The start address of DRAM (physical) +# CONFIG_DRAM_END - Last address+1 of installed RAM +# CONFIG_ARCH_IRQPRIO - The STM3240xxx supports interrupt prioritization +# CONFIG_ARCH_FPU - The STM3240xxx supports a floating point unit (FPU). +# CONFIG_ARCH_INTERRUPTSTACK - This architecture supports an interrupt +# stack. If defined, this symbol is the size of the interrupt +# stack in bytes. If not defined, the user task stacks will be +# used during interrupt handling. +# CONFIG_ARCH_STACKDUMP - Do stack dumps after assertions +# CONFIG_ARCH_BOOTLOADER - Set if you are using a bootloader. +# CONFIG_ARCH_LEDS - Use LEDs to show state. Unique to board architecture. +# CONFIG_ARCH_BUTTONS - Enable support for buttons. Unique to board architecture. +# CONFIG_ARCH_CALIBRATION - Enables some build in instrumentation that +# cause a 100 second delay during boot-up. This 100 second delay +# serves no purpose other than it allows you to calibrate +# CONFIG_BOARD_LOOPSPERMSEC. You simply use a stop watch to measure +# the 100 second delay then adjust CONFIG_BOARD_LOOPSPERMSEC until +# the delay actually is 100 seconds. +# CONFIG_ARCH_DMA - Support DMA initialization +# +CONFIG_ARCH=arm +CONFIG_ARCH_ARM=y +CONFIG_ARCH_CORTEXM4=y +CONFIG_ARCH_CHIP=stm32 +CONFIG_ARCH_CHIP_STM32F405RG=y +CONFIG_ARCH_BOARD=px4fmu +CONFIG_ARCH_BOARD_PX4FMU=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_DRAM_SIZE=0x00030000 +CONFIG_DRAM_START=0x20000000 +CONFIG_DRAM_END=(CONFIG_DRAM_START+CONFIG_DRAM_SIZE) +CONFIG_ARCH_IRQPRIO=y +CONFIG_ARCH_FPU=y +CONFIG_ARCH_INTERRUPTSTACK=n +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_BOOTLOADER=n +CONFIG_ARCH_LEDS=y +CONFIG_ARCH_BUTTONS=n +CONFIG_ARCH_CALIBRATION=n +CONFIG_ARCH_DMA=y +CONFIG_ARCH_MATH_H=y + +CONFIG_ARMV7M_CMNVECTOR=y + +# +# LIBC printf() options +# +# CONFIG_LIBC_FLOATINGPOINT - Enables printf("%f") +# CONFIG_LIBC_FIXEDPRECISION - Sets 7 digits after dot for printing: +# 5.1234567 +# CONFIG_HAVE_LONG_LONG - Enabled printf("%llu) +# +CONFIG_LIBC_FLOATINGPOINT=y +CONFIG_HAVE_LONG_LONG=y +#CONFIG_LIBC_FIXEDPRECISION=7 + +# +# CMSIS options +# +# CONFIG_DSPLIB_TARGET - Target for the CMSIS DSP library, one of +# CortexM0, CortexM3 or CortexM4 (with fpu) +# +CONFIG_CMSIS_DSPLIB_TARGET=CortexM4 + +# +# JTAG Enable settings (by default JTAG-DP and SW-DP are enabled): +# +# CONFIG_STM32_DFU - Use the DFU bootloader, not JTAG (ignored) +# +# JTAG Enable options: +# +# CONFIG_STM32_JTAG_FULL_ENABLE - Enables full SWJ (JTAG-DP + SW-DP) +# CONFIG_STM32_JTAG_NOJNTRST_ENABLE - Enables full SWJ (JTAG-DP + SW-DP) +# but without JNTRST. +# CONFIG_STM32_JTAG_SW_ENABLE - Set JTAG-DP disabled and SW-DP enabled +# +CONFIG_STM32_DFU=n +CONFIG_STM32_JTAG_FULL_ENABLE=y +CONFIG_STM32_JTAG_NOJNTRST_ENABLE=n +CONFIG_STM32_JTAG_SW_ENABLE=n + +# +# On-board FSMC SRAM configuration +# +# CONFIG_STM32_FSMC - Required. See below +# CONFIG_MM_REGIONS - Required. Must be 2 or 3 (see above) +# +# CONFIG_STM32_FSMC_SRAM=y - Indicates that SRAM is available via the +# FSMC (as opposed to an LCD or FLASH). +# CONFIG_HEAP2_BASE - The base address of the SRAM in the FSMC address space +# CONFIG_HEAP2_END - The end (+1) of the SRAM in the FSMC address space +# +#CONFIG_STM32_FSMC_SRAM=n +#CONFIG_HEAP2_BASE=0x64000000 +#CONFIG_HEAP2_END=(0x64000000+(2*1024*1024)) + +# +# Individual subsystems can be enabled: +# +# This set is exhaustive for PX4FMU and should be safe to cut and +# paste into any other config. +# +# AHB1: +CONFIG_STM32_CRC=n +CONFIG_STM32_BKPSRAM=y +CONFIG_STM32_CCMDATARAM=y +CONFIG_STM32_DMA1=y +CONFIG_STM32_DMA2=y +CONFIG_STM32_ETHMAC=n +CONFIG_STM32_OTGHS=n +# AHB2: +CONFIG_STM32_DCMI=n +CONFIG_STM32_CRYP=n +CONFIG_STM32_HASH=n +CONFIG_STM32_RNG=n +CONFIG_STM32_OTGFS=y +# AHB3: +CONFIG_STM32_FSMC=n +# APB1: +# TIM2 is owned by PWM output +CONFIG_STM32_TIM2=n +# TIM3 is owned by TONE_ALARM +CONFIG_STM32_TIM3=n +CONFIG_STM32_TIM4=y +CONFIG_STM32_TIM5=y +CONFIG_STM32_TIM6=y +CONFIG_STM32_TIM7=y +CONFIG_STM32_TIM12=y +CONFIG_STM32_TIM13=y +CONFIG_STM32_TIM14=y +CONFIG_STM32_WWDG=y +CONFIG_STM32_SPI2=n +CONFIG_STM32_SPI3=y +CONFIG_STM32_USART2=y +CONFIG_STM32_USART3=n +CONFIG_STM32_UART4=n +CONFIG_STM32_UART5=y +CONFIG_STM32_I2C1=y +CONFIG_STM32_I2C2=y +CONFIG_STM32_I2C3=y +CONFIG_STM32_CAN1=n +CONFIG_STM32_CAN2=y +CONFIG_STM32_DAC=n +CONFIG_STM32_PWR=y +# APB2: +# TIM1 is owned by the HRT +CONFIG_STM32_TIM1=n +# TIM8 is owned by PWM output +CONFIG_STM32_TIM8=n +CONFIG_STM32_USART1=y +CONFIG_STM32_USART6=y +CONFIG_STM32_ADC1=n +CONFIG_STM32_ADC2=n +CONFIG_STM32_ADC3=y +CONFIG_STM32_SDIO=n +CONFIG_STM32_SPI1=y +CONFIG_STM32_SYSCFG=y +CONFIG_STM32_TIM9=y +CONFIG_STM32_TIM10=y +CONFIG_STM32_TIM11=y + +# +# Configure the ADC +# +CONFIG_ADC=y +# select trigger timer +CONFIG_STM32_TIM4_ADC3=y +# select sample frequency 1^=1.5Msamples/second +# 65535^=10samples/second 16bit-timer runs at 84/128 MHz +CONFIG_STM32_ADC3_SAMPLE_FREQUENCY=6000 +# select timer channel 0=CC1,...,3=CC4 +CONFIG_STM32_ADC3_TIMTRIG=3 +CONFIG_ADC_DMA=y +# only 4 places usable! +CONFIG_ADC_FIFOSIZE=5 + +# +# Timer and I2C devices may need to the following to force power to be applied: +# +#CONFIG_STM32_FORCEPOWER=y + +# +# I2C configuration +# +CONFIG_I2C=y +CONFIG_I2C_POLLED=y +CONFIG_I2C_TRANSFER=y +CONFIG_I2C_WRITEREAD=y +CONFIG_I2C_TRACE=n +# Allow 180 us per byte, a wide margin for the 400 KHz clock we're using +# e.g. 9.6 ms for an EEPROM page write, 0.9 ms for a MAG update +CONFIG_STM32_I2CTIMEOUS_PER_BYTE=200 +# Constant overhead for generating I2C start / stop conditions +CONFIG_STM32_I2CTIMEOUS_START_STOP=700 +CONFIG_DEBUG_I2C=n + +# +# STM32F40xxx specific serial device driver settings +# +# CONFIG_SERIAL_TERMIOS - Serial driver supports termios.h interfaces (tcsetattr, +# tcflush, etc.). If this is not defined, then the terminal settings (baud, +# parity, etc.) are not configurable at runtime; serial streams cannot be +# flushed, etc. +# +# CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the +# console and ttys0 (default is the USART1). +# CONFIG_USARTn_RXBUFSIZE - Characters are buffered as received. +# This specific the size of the receive buffer +# CONFIG_USARTn_TXBUFSIZE - Characters are buffered before +# being sent. This specific the size of the transmit buffer +# CONFIG_USARTn_BAUD - The configure BAUD of the UART. Must be +# CONFIG_USARTn_BITS - The number of bits. Must be either 7 or 8. +# CONFIG_USARTn_PARTIY - 0=no parity, 1=odd parity, 2=even parity +# CONFIG_USARTn_2STOP - Two stop bits +# +CONFIG_SERIAL_TERMIOS=y + +CONFIG_USART1_SERIAL_CONSOLE=y +CONFIG_USART2_SERIAL_CONSOLE=n +CONFIG_USART3_SERIAL_CONSOLE=n +CONFIG_USART4_SERIAL_CONSOLE=n +CONFIG_USART5_SERIAL_CONSOLE=n +CONFIG_USART6_SERIAL_CONSOLE=n + +#Mavlink messages can be bigger than 128 +CONFIG_USART1_TXBUFSIZE=512 +CONFIG_USART2_TXBUFSIZE=128 +CONFIG_USART3_TXBUFSIZE=128 +CONFIG_USART4_TXBUFSIZE=128 +CONFIG_USART5_TXBUFSIZE=64 +CONFIG_USART6_TXBUFSIZE=128 + +CONFIG_USART1_RXBUFSIZE=512 +CONFIG_USART2_RXBUFSIZE=128 +CONFIG_USART3_RXBUFSIZE=128 +CONFIG_USART4_RXBUFSIZE=128 +CONFIG_USART5_RXBUFSIZE=128 +CONFIG_USART6_RXBUFSIZE=128 + +CONFIG_USART1_BAUD=57600 +CONFIG_USART2_BAUD=115200 +CONFIG_USART3_BAUD=115200 +CONFIG_USART4_BAUD=115200 +CONFIG_USART5_BAUD=115200 +CONFIG_USART6_BAUD=9600 + +CONFIG_USART1_BITS=8 +CONFIG_USART2_BITS=8 +CONFIG_USART3_BITS=8 +CONFIG_USART4_BITS=8 +CONFIG_USART5_BITS=8 +CONFIG_USART6_BITS=8 + +CONFIG_USART1_PARITY=0 +CONFIG_USART2_PARITY=0 +CONFIG_USART3_PARITY=0 +CONFIG_USART4_PARITY=0 +CONFIG_USART5_PARITY=0 +CONFIG_USART6_PARITY=0 + +CONFIG_USART1_2STOP=0 +CONFIG_USART2_2STOP=0 +CONFIG_USART3_2STOP=0 +CONFIG_USART4_2STOP=0 +CONFIG_USART5_2STOP=0 +CONFIG_USART6_2STOP=0 + +CONFIG_USART1_RXDMA=n +CONFIG_USART2_RXDMA=y +CONFIG_USART3_RXDMA=n +CONFIG_USART4_RXDMA=n +CONFIG_USART5_RXDMA=y +CONFIG_USART6_RXDMA=y + +# +# PX4FMU specific driver settings +# +# CONFIG_HRT_TIMER +# Enables the high-resolution timer. The board definition must +# set HRT_TIMER and HRT_TIMER_CHANNEL to the timer and capture/ +# compare channels to be used. +# CONFIG_HRT_PPM +# Enables R/C PPM input using the HRT. The board definition must +# set HRT_PPM_CHANNEL to the timer capture/compare channel to be +# used, and define GPIO_PPM_IN to configure the appropriate timer +# GPIO. +# CONFIG_TONE_ALARM +# Enables the tone alarm (buzzer) driver The board definition must +# set TONE_ALARM_TIMER and TONE_ALARM_CHANNEL to the timer and +# capture/compare channels to be used. +# CONFIG_PWM_SERVO +# Enables the PWM servo driver. The driver configuration must be +# supplied by the board support at initialisation time. +# Note that USART2 must be disabled on the PX4 board for this to +# be available. +# CONFIG_MULTIPORT +# Enabled support for run-time (or EEPROM based boot-time) configuration +# of ports for different functions (e.g. USART2 or ARDrone or PWM out) +# +# +CONFIG_HRT_TIMER=y +CONFIG_HRT_PPM=y +CONFIG_TONE_ALARM=y +CONFIG_PWM_SERVO=n +CONFIG_MULTIPORT=n + +# +# CONFIG_UART2_RTS_CTS_AS_GPIO +# If set, enables RTS and CTS pins as additional GPIOs 2 and 3 +# +CONFIG_PX4_UART2_RTS_CTS_AS_GPIO=y + + +# +# STM32F40xxx specific SPI device driver settings +# +CONFIG_SPI_EXCHANGE=y +# DMA needs more work, not implemented on STM32F4x yet +#CONFIG_STM32_SPI_DMA=y + +# +# STM32F40xxx specific CAN device driver settings +# +# CONFIG_CAN - Enables CAN support (one or both of CONFIG_STM32_CAN1 or +# CONFIG_STM32_CAN2 must also be defined) +# CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages. +# Default: 8 +# CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests. +# Default: 4 +# CONFIG_CAN_LOOPBACK - A CAN driver may or may not support a loopback +# mode for testing. The STM32 CAN driver does support loopback mode. +# CONFIG_CAN1_BAUD - CAN1 BAUD rate. Required if CONFIG_STM32_CAN1 is defined. +# CONFIG_CAN2_BAUD - CAN1 BAUD rate. Required if CONFIG_STM32_CAN2 is defined. +# +CONFIG_CAN=n +#CONFIG_CAN_FIFOSIZE +#CONFIG_CAN_NPENDINGRTR +CONFIG_CAN_LOOPBACK=n +CONFIG_CAN1_BAUD=700000 +CONFIG_CAN2_BAUD=700000 + +# +# General build options +# +# CONFIG_RRLOAD_BINARY - make the rrload binary format used with +# BSPs from www.ridgerun.com using the tools/mkimage.sh script +# CONFIG_INTELHEX_BINARY - make the Intel HEX binary format +# used with many different loaders using the GNU objcopy program +# Should not be selected if you are not using the GNU toolchain. +# CONFIG_MOTOROLA_SREC - make the Motorola S-Record binary format +# used with many different loaders using the GNU objcopy program +# Should not be selected if you are not using the GNU toolchain. +# CONFIG_RAW_BINARY - make a raw binary format file used with many +# different loaders using the GNU objcopy program. This option +# should not be selected if you are not using the GNU toolchain. +# CONFIG_HAVE_LIBM - toolchain supports libm.a +# +CONFIG_RRLOAD_BINARY=n +CONFIG_INTELHEX_BINARY=y +CONFIG_MOTOROLA_SREC=n +CONFIG_RAW_BINARY=y +CONFIG_HAVE_LIBM=y + +# +# General OS setup +# +# CONFIG_APPS_DIR - Identifies the relative path to the directory +# that builds the application to link with NuttX. Default: ../apps +# CONFIG_DEBUG - enables built-in debug options +# CONFIG_DEBUG_VERBOSE - enables verbose debug output +# CONFIG_DEBUG_SYMBOLS - build without optimization and with +# debug symbols (needed for use with a debugger). +# CONFIG_HAVE_CXX - Enable support for C++ +# CONFIG_MM_REGIONS - If the architecture includes multiple +# regions of memory to allocate from, this specifies the +# number of memory regions that the memory manager must +# handle and enables the API mm_addregion(start, end); +# CONFIG_ARCH_LOWPUTC - architecture supports low-level, boot +# time console output +# CONFIG_MSEC_PER_TICK - The default system timer is 100Hz +# or MSEC_PER_TICK=10. This setting may be defined to +# inform NuttX that the processor hardware is providing +# system timer interrupts at some interrupt interval other +# than 10 msec. +# CONFIG_RR_INTERVAL - The round robin timeslice will be set +# this number of milliseconds; Round robin scheduling can +# be disabled by setting this value to zero. +# CONFIG_SCHED_INSTRUMENTATION - enables instrumentation in +# scheduler to monitor system performance +# CONFIG_TASK_NAME_SIZE - Spcifies that maximum size of a +# task name to save in the TCB. Useful if scheduler +# instrumentation is selected. Set to zero to disable. +# CONFIG_START_YEAR, CONFIG_START_MONTH, CONFIG_START_DAY - +# Used to initialize the internal time logic. +# CONFIG_GREGORIAN_TIME - Enables Gregorian time conversions. +# You would only need this if you are concerned about accurate +# time conversions in the past or in the distant future. +# CONFIG_JULIAN_TIME - Enables Julian time conversions. You +# would only need this if you are concerned about accurate +# time conversion in the distand past. You must also define +# CONFIG_GREGORIAN_TIME in order to use Julian time. +# CONFIG_DEV_CONSOLE - Set if architecture-specific logic +# provides /dev/console. Enables stdout, stderr, stdin. +# CONFIG_DEV_LOWCONSOLE - Use the simple, low-level serial console +# driver (minimul support) +# CONFIG_MUTEX_TYPES: Set to enable support for recursive and +# errorcheck mutexes. Enables pthread_mutexattr_settype(). +# CONFIG_PRIORITY_INHERITANCE : Set to enable support for priority +# inheritance on mutexes and semaphores. +# CONFIG_SEM_PREALLOCHOLDERS: This setting is only used if priority +# inheritance is enabled. It defines the maximum number of +# different threads (minus one) that can take counts on a +# semaphore with priority inheritance support. This may be +# set to zero if priority inheritance is disabled OR if you +# are only using semaphores as mutexes (only one holder) OR +# if no more than two threads participate using a counting +# semaphore. +# CONFIG_SEM_NNESTPRIO. If priority inheritance is enabled, +# then this setting is the maximum number of higher priority +# threads (minus 1) than can be waiting for another thread +# to release a count on a semaphore. This value may be set +# to zero if no more than one thread is expected to wait for +# a semaphore. +# CONFIG_FDCLONE_DISABLE. Disable cloning of all file descriptors +# by task_create() when a new task is started. If set, all +# files/drivers will appear to be closed in the new task. +# CONFIG_FDCLONE_STDIO. Disable cloning of all but the first +# three file descriptors (stdin, stdout, stderr) by task_create() +# when a new task is started. If set, all files/drivers will +# appear to be closed in the new task except for stdin, stdout, +# and stderr. +# CONFIG_SDCLONE_DISABLE. Disable cloning of all socket +# desciptors by task_create() when a new task is started. If +# set, all sockets will appear to be closed in the new task. +# CONFIG_SCHED_WORKQUEUE. Create a dedicated "worker" thread to +# handle delayed processing from interrupt handlers. This feature +# is required for some drivers but, if there are not complaints, +# can be safely disabled. The worker thread also performs +# garbage collection -- completing any delayed memory deallocations +# from interrupt handlers. If the worker thread is disabled, +# then that clean will be performed by the IDLE thread instead +# (which runs at the lowest of priority and may not be appropriate +# if memory reclamation is of high priority). If CONFIG_SCHED_WORKQUEUE +# is enabled, then the following options can also be used: +# CONFIG_SCHED_WORKPRIORITY - The execution priority of the worker +# thread. Default: 50 +# CONFIG_SCHED_WORKPERIOD - How often the worker thread checks for +# work in units of microseconds. Default: 50*1000 (50 MS). +# CONFIG_SCHED_WORKSTACKSIZE - The stack size allocated for the worker +# thread. Default: CONFIG_IDLETHREAD_STACKSIZE. +# CONFIG_SIG_SIGWORK - The signal number that will be used to wake-up +# the worker thread. Default: 4 +# CONFIG_SCHED_WAITPID - Enable the waitpid() API +# CONFIG_SCHED_ATEXIT - Enabled the atexit() API +# +#CONFIG_APPS_DIR= +CONFIG_DEBUG=y +CONFIG_DEBUG_VERBOSE=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_ANALOG=n +CONFIG_DEBUG_FS=n +CONFIG_DEBUG_GRAPHICS=n +CONFIG_DEBUG_LCD=n +CONFIG_DEBUG_USB=n +CONFIG_DEBUG_NET=n +CONFIG_DEBUG_RTC=n +CONFIG_HAVE_CXX=y +CONFIG_MM_REGIONS=2 +CONFIG_ARCH_LOWPUTC=y +CONFIG_MSEC_PER_TICK=1 +CONFIG_RR_INTERVAL=1 +CONFIG_SCHED_INSTRUMENTATION=y +CONFIG_TASK_NAME_SIZE=24 +CONFIG_START_YEAR=1970 +CONFIG_START_MONTH=1 +CONFIG_START_DAY=1 +CONFIG_GREGORIAN_TIME=n +CONFIG_JULIAN_TIME=n +CONFIG_DEV_CONSOLE=y +CONFIG_DEV_LOWCONSOLE=n +CONFIG_MUTEX_TYPES=n +CONFIG_PRIORITY_INHERITANCE=y +CONFIG_SEM_PREALLOCHOLDERS=0 +CONFIG_SEM_NNESTPRIO=8 +CONFIG_FDCLONE_DISABLE=n +CONFIG_FDCLONE_STDIO=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_SCHED_WORKQUEUE=n +CONFIG_SCHED_WORKPRIORITY=50 +CONFIG_SCHED_WORKPERIOD=(50*1000) +CONFIG_SCHED_WORKSTACKSIZE=1024 +CONFIG_SIG_SIGWORK=4 +CONFIG_SCHED_WAITPID=y +CONFIG_SCHED_ATEXIT=n + +# +# The following can be used to disable categories of +# APIs supported by the OS. If the compiler supports +# weak functions, then it should not be necessary to +# disable functions unless you want to restrict usage +# of those APIs. +# +# There are certain dependency relationships in these +# features. +# +# o mq_notify logic depends on signals to awaken tasks +# waiting for queues to become full or empty. +# o pthread_condtimedwait() depends on signals to wake +# up waiting tasks. +# +CONFIG_DISABLE_CLOCK=n +CONFIG_DISABLE_POSIX_TIMERS=n +CONFIG_DISABLE_PTHREAD=n +CONFIG_DISABLE_SIGNALS=n +CONFIG_DISABLE_MQUEUE=n +CONFIG_DISABLE_MOUNTPOINT=n +CONFIG_DISABLE_ENVIRON=n +CONFIG_DISABLE_POLL=n + +# +# Misc libc settings +# +# CONFIG_NOPRINTF_FIELDWIDTH - sprintf-related logic is a +# little smaller if we do not support fieldwidthes +# +CONFIG_NOPRINTF_FIELDWIDTH=n + +# +# Allow for architecture optimized implementations +# +# The architecture can provide optimized versions of the +# following to improve system performance +# +CONFIG_ARCH_MEMCPY=y +CONFIG_ARCH_MEMCMP=n +CONFIG_ARCH_MEMMOVE=n +CONFIG_ARCH_MEMSET=n +CONFIG_ARCH_STRCMP=n +CONFIG_ARCH_STRCPY=n +CONFIG_ARCH_STRNCPY=n +CONFIG_ARCH_STRLEN=n +CONFIG_ARCH_STRNLEN=n +CONFIG_ARCH_BZERO=n + +# +# Sizes of configurable things (0 disables) +# +# CONFIG_MAX_TASKS - The maximum number of simultaneously +# active tasks. This value must be a power of two. +# CONFIG_MAX_TASK_ARGS - This controls the maximum number of +# of parameters that a task may receive (i.e., maxmum value +# of 'argc') +# CONFIG_NPTHREAD_KEYS - The number of items of thread- +# specific data that can be retained +# CONFIG_NFILE_DESCRIPTORS - The maximum number of file +# descriptors (one for each open) +# CONFIG_NFILE_STREAMS - The maximum number of streams that +# can be fopen'ed +# CONFIG_NAME_MAX - The maximum size of a file name. +# CONFIG_STDIO_BUFFER_SIZE - Size of the buffer to allocate +# on fopen. (Only if CONFIG_NFILE_STREAMS > 0) +# CONFIG_STDIO_LINEBUFFER - If standard C buffered I/O is enabled +# (CONFIG_STDIO_BUFFER_SIZE > 0), then this option may be added +# to force automatic, line-oriented flushing the output buffer +# for putc(), fputc(), putchar(), puts(), fputs(), printf(), +# fprintf(), and vfprintf(). When a newline is encountered in +# the output string, the output buffer will be flushed. This +# (slightly) increases the NuttX footprint but supports the kind +# of behavior that people expect for printf(). +# CONFIG_NUNGET_CHARS - Number of characters that can be +# buffered by ungetc() (Only if CONFIG_NFILE_STREAMS > 0) +# CONFIG_PREALLOC_MQ_MSGS - The number of pre-allocated message +# structures. The system manages a pool of preallocated +# message structures to minimize dynamic allocations +# CONFIG_MQ_MAXMSGSIZE - Message structures are allocated with +# a fixed payload size given by this settin (does not include +# other message structure overhead. +# CONFIG_MAX_WDOGPARMS - Maximum number of parameters that +# can be passed to a watchdog handler +# CONFIG_PREALLOC_WDOGS - The number of pre-allocated watchdog +# structures. The system manages a pool of preallocated +# watchdog structures to minimize dynamic allocations +# CONFIG_PREALLOC_TIMERS - The number of pre-allocated POSIX +# timer structures. The system manages a pool of preallocated +# timer structures to minimize dynamic allocations. Set to +# zero for all dynamic allocations. +# +CONFIG_MAX_TASKS=32 +CONFIG_MAX_TASK_ARGS=8 +CONFIG_NPTHREAD_KEYS=4 +CONFIG_NFILE_DESCRIPTORS=20 +CONFIG_NFILE_STREAMS=20 +CONFIG_NAME_MAX=32 +CONFIG_STDIO_BUFFER_SIZE=256 +CONFIG_STDIO_LINEBUFFER=y +CONFIG_NUNGET_CHARS=2 +CONFIG_PREALLOC_MQ_MSGS=4 +CONFIG_MQ_MAXMSGSIZE=32 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_PREALLOC_WDOGS=50 +CONFIG_PREALLOC_TIMERS=50 + +# +# Filesystem configuration +# +# CONFIG_FS_FAT - Enable FAT filesystem support +# CONFIG_FAT_SECTORSIZE - Max supported sector size +# CONFIG_FAT_LCNAMES - Enable use of the NT-style upper/lower case 8.3 +# file name support. +# CONFIG_FAT_LFN - Enable FAT long file names. NOTE: Microsoft claims +# patents on FAT long file name technology. Please read the +# disclaimer in the top-level COPYING file and only enable this +# feature if you understand these issues. +# CONFIG_FAT_MAXFNAME - If CONFIG_FAT_LFN is defined, then the +# default, maximum long file name is 255 bytes. This can eat up +# a lot of memory (especially stack space). If you are willing +# to live with some non-standard, short long file names, then +# define this value. A good choice would be the same value as +# selected for CONFIG_NAME_MAX which will limit the visibility +# of longer file names anyway. +# CONFIG_FS_NXFFS: Enable NuttX FLASH file system (NXFF) support. +# CONFIG_NXFFS_ERASEDSTATE: The erased state of FLASH. +# This must have one of the values of 0xff or 0x00. +# Default: 0xff. +# CONFIG_NXFFS_PACKTHRESHOLD: When packing flash file data, +# don't both with file chunks smaller than this number of data bytes. +# CONFIG_NXFFS_MAXNAMLEN: The maximum size of an NXFFS file name. +# Default: 255. +# CONFIG_NXFFS_PACKTHRESHOLD: When packing flash file data, +# don't both with file chunks smaller than this number of data bytes. +# Default: 32. +# CONFIG_NXFFS_TAILTHRESHOLD: clean-up can either mean +# packing files together toward the end of the file or, if file are +# deleted at the end of the file, clean up can simply mean erasing +# the end of FLASH memory so that it can be re-used again. However, +# doing this can also harm the life of the FLASH part because it can +# mean that the tail end of the FLASH is re-used too often. This +# threshold determines if/when it is worth erased the tail end of FLASH +# and making it available for re-use (and possible over-wear). +# Default: 8192. +# CONFIG_FS_ROMFS - Enable ROMFS filesystem support +# CONFIG_FS_RAMMAP - For file systems that do not support XIP, this +# option will enable a limited form of memory mapping that is +# implemented by copying whole files into memory. +# +CONFIG_FS_FAT=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FAT_MAXFNAME=32 +CONFIG_FS_NXFFS=n +CONFIG_FS_ROMFS=y + +# +# SPI-based MMC/SD driver +# +# CONFIG_MMCSD_NSLOTS +# Number of MMC/SD slots supported by the driver +# CONFIG_MMCSD_READONLY +# Provide read-only access (default is read/write) +# CONFIG_MMCSD_SPICLOCK - Maximum SPI clock to drive MMC/SD card. +# Default is 20MHz, current setting 24 MHz +# +CONFIG_MMCSD_NSLOTS=1 +CONFIG_MMCSD_READONLY=n +CONFIG_MMCSD_SPICLOCK=24000000 + +# +# Block driver buffering +# +# CONFIG_FS_READAHEAD +# Enable read-ahead buffering +# CONFIG_FS_WRITEBUFFER +# Enable write buffering +# +CONFIG_FS_READAHEAD=n +CONFIG_FS_WRITEBUFFER=n + +# +# RTC Configuration +# +# CONFIG_RTC - Enables general support for a hardware RTC. Specific +# architectures may require other specific settings. +# CONFIG_RTC_DATETIME - There are two general types of RTC: (1) A simple +# battery backed counter that keeps the time when power is down, and (2) +# A full date / time RTC the provides the date and time information, often +# in BCD format. If CONFIG_RTC_DATETIME is selected, it specifies this +# second kind of RTC. In this case, the RTC is used to "seed" the normal +# NuttX timer and the NuttX system timer provides for higher resoution +# time. +# CONFIG_RTC_HIRES - If CONFIG_RTC_DATETIME not selected, then the simple, +# battery backed counter is used. There are two different implementations +# of such simple counters based on the time resolution of the counter: +# The typical RTC keeps time to resolution of 1 second, usually +# supporting a 32-bit time_t value. In this case, the RTC is used to +# "seed" the normal NuttX timer and the NuttX timer provides for higher +# resoution time. If CONFIG_RTC_HIRES is enabled in the NuttX configuration, +# then the RTC provides higher resolution time and completely replaces the +# system timer for purpose of date and time. +# CONFIG_RTC_FREQUENCY - If CONFIG_RTC_HIRES is defined, then the frequency +# of the high resolution RTC must be provided. If CONFIG_RTC_HIRES is +# not defined, CONFIG_RTC_FREQUENCY is assumed to be one. +# CONFIG_RTC_ALARM - Enable if the RTC hardware supports setting of an +# alarm. A callback function will be executed when the alarm goes off +# +CONFIG_RTC=n +CONFIG_RTC_DATETIME=y +CONFIG_RTC_HIRES=n +CONFIG_RTC_FREQUENCY=n +CONFIG_RTC_ALARM=n + +# +# USB Device Configuration +# +# CONFIG_USBDEV +# Enables USB device support +# CONFIG_USBDEV_ISOCHRONOUS +# Build in extra support for isochronous endpoints +# CONFIG_USBDEV_DUALSPEED +# Hardware handles high and full speed operation (USB 2.0) +# CONFIG_USBDEV_SELFPOWERED +# Will cause USB features to indicate that the device is +# self-powered +# CONFIG_USBDEV_MAXPOWER +# Maximum power consumption in mA +# CONFIG_USBDEV_TRACE +# Enables USB tracing for debug +# CONFIG_USBDEV_TRACE_NRECORDS +# Number of trace entries to remember +# +CONFIG_USBDEV=y +CONFIG_USBDEV_ISOCHRONOUS=n +CONFIG_USBDEV_DUALSPEED=n +CONFIG_USBDEV_SELFPOWERED=y +CONFIG_USBDEV_REMOTEWAKEUP=n +CONFIG_USBDEV_MAXPOWER=500 +CONFIG_USBDEV_TRACE=n +CONFIG_USBDEV_TRACE_NRECORDS=512 + +# +# USB Serial Device Configuration (Prolifics PL2303 emulation) +# +# CONFIG_PL2303 +# Enable compilation of the USB serial driver +# CONFIG_PL2303_EPINTIN +# The logical 7-bit address of a hardware endpoint that supports +# interrupt IN operation +# CONFIG_PL2303_EPBULKOUT +# The logical 7-bit address of a hardware endpoint that supports +# bulk OUT operation +# CONFIG_PL2303_EPBULKIN +# The logical 7-bit address of a hardware endpoint that supports +# bulk IN operation +# # CONFIG_PL2303_NWRREQS and CONFIG_PL2303_NRDREQS +# The number of write/read requests that can be in flight +# CONFIG_PL2303_VENDORID and CONFIG_PL2303_VENDORSTR +# The vendor ID code/string +# CONFIG_PL2303_PRODUCTID and CONFIG_PL2303_PRODUCTSTR +# The product ID code/string +# CONFIG_PL2303_RXBUFSIZE and CONFIG_PL2303_TXBUFSIZE +# Size of the serial receive/transmit buffers +# +CONFIG_PL2303=n +CONFIG_PL2303_EPINTIN=1 +CONFIG_PL2303_EPBULKOUT=2 +CONFIG_PL2303_EPBULKIN=3 +CONFIG_PL2303_NWRREQS=4 +CONFIG_PL2303_NRDREQS=4 +CONFIG_PL2303_VENDORID=0x067b +CONFIG_PL2303_PRODUCTID=0x2303 +CONFIG_PL2303_VENDORSTR="Nuttx" +CONFIG_PL2303_PRODUCTSTR="USBdev Serial" +CONFIG_PL2303_RXBUFSIZE=512 +CONFIG_PL2303_TXBUFSIZE=512 + +# +# USB serial device class driver (Standard CDC ACM class) +# +# CONFIG_CDCACM +# Enable compilation of the USB serial driver +# CONFIG_CDCACM_CONSOLE +# Configures the CDC/ACM serial port as the console device. +# CONFIG_CDCACM_EP0MAXPACKET +# Endpoint 0 max packet size. Default 64 +# CONFIG_CDCACM_EPINTIN +# The logical 7-bit address of a hardware endpoint that supports +# interrupt IN operation. Default 2. +# CONFIG_CDCACM_EPINTIN_FSSIZE +# Max package size for the interrupt IN endpoint if full speed mode. +# Default 64. +# CONFIG_CDCACM_EPINTIN_HSSIZE +# Max package size for the interrupt IN endpoint if high speed mode. +# Default 64 +# CONFIG_CDCACM_EPBULKOUT +# The logical 7-bit address of a hardware endpoint that supports +# bulk OUT operation. Default 4. +# CONFIG_CDCACM_EPBULKOUT_FSSIZE +# Max package size for the bulk OUT endpoint if full speed mode. +# Default 64. +# CONFIG_CDCACM_EPBULKOUT_HSSIZE +# Max package size for the bulk OUT endpoint if high speed mode. +# Default 512. +# CONFIG_CDCACM_EPBULKIN +# The logical 7-bit address of a hardware endpoint that supports +# bulk IN operation. Default 3. +# CONFIG_CDCACM_EPBULKIN_FSSIZE +# Max package size for the bulk IN endpoint if full speed mode. +# Default 64. +# CONFIG_CDCACM_EPBULKIN_HSSIZE +# Max package size for the bulk IN endpoint if high speed mode. +# Default 512. +# CONFIG_CDCACM_NWRREQS and CONFIG_CDCACM_NRDREQS +# The number of write/read requests that can be in flight. +# Default 256. +# CONFIG_CDCACM_VENDORID and CONFIG_CDCACM_VENDORSTR +# The vendor ID code/string. Default 0x0525 and "NuttX" +# 0x0525 is the Netchip vendor and should not be used in any +# products. This default VID was selected for compatibility with +# the Linux CDC ACM default VID. +# CONFIG_CDCACM_PRODUCTID and CONFIG_CDCACM_PRODUCTSTR +# The product ID code/string. Default 0xa4a7 and "CDC/ACM Serial" +# 0xa4a7 was selected for compatibility with the Linux CDC ACM +# default PID. +# CONFIG_CDCACM_RXBUFSIZE and CONFIG_CDCACM_TXBUFSIZE +# Size of the serial receive/transmit buffers. Default 256. +# +CONFIG_CDCACM=y +CONFIG_CDCACM_CONSOLE=n +#CONFIG_CDCACM_EP0MAXPACKET +CONFIG_CDCACM_EPINTIN=1 +#CONFIG_CDCACM_EPINTIN_FSSIZE +#CONFIG_CDCACM_EPINTIN_HSSIZE +CONFIG_CDCACM_EPBULKOUT=3 +#CONFIG_CDCACM_EPBULKOUT_FSSIZE +#CONFIG_CDCACM_EPBULKOUT_HSSIZE +CONFIG_CDCACM_EPBULKIN=2 +#CONFIG_CDCACM_EPBULKIN_FSSIZE +#CONFIG_CDCACM_EPBULKIN_HSSIZE +#CONFIG_CDCACM_NWRREQS +#CONFIG_CDCACM_NRDREQS +CONFIG_CDCACM_VENDORID=0x26AC +CONFIG_CDCACM_VENDORSTR="3D Robotics" +CONFIG_CDCACM_PRODUCTID=0x0010 +CONFIG_CDCACM_PRODUCTSTR="PX4 FMU v1.6" +#CONFIG_CDCACM_RXBUFSIZE +#CONFIG_CDCACM_TXBUFSIZE + +# +# USB Storage Device Configuration +# +# CONFIG_USBMSC +# Enable compilation of the USB storage driver +# CONFIG_USBMSC_EP0MAXPACKET +# Max packet size for endpoint 0 +# CONFIG_USBMSC_EPBULKOUT and CONFIG_USBMSC_EPBULKIN +# The logical 7-bit address of a hardware endpoints that support +# bulk OUT and IN operations +# CONFIG_USBMSC_NWRREQS and CONFIG_USBMSC_NRDREQS +# The number of write/read requests that can be in flight +# CONFIG_USBMSC_BULKINREQLEN and CONFIG_USBMSC_BULKOUTREQLEN +# The size of the buffer in each write/read request. This +# value needs to be at least as large as the endpoint +# maxpacket and ideally as large as a block device sector. +# CONFIG_USBMSC_VENDORID and CONFIG_USBMSC_VENDORSTR +# The vendor ID code/string +# CONFIG_USBMSC_PRODUCTID and CONFIG_USBMSC_PRODUCTSTR +# The product ID code/string +# CONFIG_USBMSC_REMOVABLE +# Select if the media is removable +# +CONFIG_USBMSC=n +CONFIG_USBMSC_EP0MAXPACKET=64 +CONFIG_USBMSC_EPBULKOUT=2 +CONFIG_USBMSC_EPBULKIN=5 +CONFIG_USBMSC_NRDREQS=2 +CONFIG_USBMSC_NWRREQS=2 +CONFIG_USBMSC_BULKINREQLEN=256 +CONFIG_USBMSC_BULKOUTREQLEN=256 +CONFIG_USBMSC_VENDORID=0x584e +CONFIG_USBMSC_VENDORSTR="NuttX" +CONFIG_USBMSC_PRODUCTID=0x5342 +CONFIG_USBMSC_PRODUCTSTR="USBdev Storage" +CONFIG_USBMSC_VERSIONNO=0x0399 +CONFIG_USBMSC_REMOVABLE=y + + +# +# Settings for apps/nshlib +# +# CONFIG_NSH_BUILTIN_APPS - Support external registered, +# "named" applications that can be executed from the NSH +# command line (see apps/README.txt for more information). +# CONFIG_NSH_FILEIOSIZE - Size of a static I/O buffer +# CONFIG_NSH_STRERROR - Use strerror(errno) +# CONFIG_NSH_LINELEN - Maximum length of one command line +# CONFIG_NSH_STACKSIZE - Stack size to use for new threads. +# CONFIG_NSH_NESTDEPTH - Max number of nested if-then[-else]-fi +# CONFIG_NSH_DISABLESCRIPT - Disable scripting support +# CONFIG_NSH_DISABLEBG - Disable background commands +# CONFIG_NSH_ROMFSETC - Use startup script in /etc +# CONFIG_NSH_CONSOLE - Use serial console front end +# CONFIG_NSH_TELNET - Use telnetd console front end +# CONFIG_NSH_ARCHINIT - Platform provides architecture +# specific initialization (nsh_archinitialize()). +# +# If CONFIG_NSH_TELNET is selected: +# CONFIG_NSH_IOBUFFER_SIZE -- Telnetd I/O buffer size +# CONFIG_NSH_DHCPC - Obtain address using DHCP +# CONFIG_NSH_IPADDR - Provides static IP address +# CONFIG_NSH_DRIPADDR - Provides static router IP address +# CONFIG_NSH_NETMASK - Provides static network mask +# CONFIG_NSH_NOMAC - Use a bogus MAC address +# +# If CONFIG_NSH_ROMFSETC is selected: +# CONFIG_NSH_ROMFSMOUNTPT - ROMFS mountpoint +# CONFIG_NSH_INITSCRIPT - Relative path to init script +# CONFIG_NSH_ROMFSDEVNO - ROMFS RAM device minor +# CONFIG_NSH_ROMFSSECTSIZE - ROMF sector size +# CONFIG_NSH_FATDEVNO - FAT FS RAM device minor +# CONFIG_NSH_FATSECTSIZE - FAT FS sector size +# CONFIG_NSH_FATNSECTORS - FAT FS number of sectors +# CONFIG_NSH_FATMOUNTPT - FAT FS mountpoint +# +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_STRERROR=y +CONFIG_NSH_LINELEN=128 +CONFIG_NSH_NESTDEPTH=8 +CONFIG_NSH_DISABLESCRIPT=n +CONFIG_NSH_DISABLEBG=n +CONFIG_NSH_ROMFSETC=y +CONFIG_NSH_ARCHROMFS=y +CONFIG_NSH_CONSOLE=y +CONFIG_NSH_USBCONSOLE=n +CONFIG_NSH_USBCONDEV="/dev/ttyACM0" +CONFIG_NSH_TELNET=n +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_IOBUFFER_SIZE=512 +CONFIG_NSH_DHCPC=n +CONFIG_NSH_NOMAC=y +CONFIG_NSH_IPADDR=(10<<24|0<<16|0<<8|2) +CONFIG_NSH_DRIPADDR=(10<<24|0<<16|0<<8|1) +CONFIG_NSH_NETMASK=(255<<24|255<<16|255<<8|0) +CONFIG_NSH_ROMFSMOUNTPT="/etc" +CONFIG_NSH_INITSCRIPT="init.d/rcS" +CONFIG_NSH_ROMFSDEVNO=0 +CONFIG_NSH_ROMFSSECTSIZE=128 # Default 64, increased to allow for more than 64 folders on the sdcard +CONFIG_NSH_FATDEVNO=1 +CONFIG_NSH_FATSECTSIZE=512 +CONFIG_NSH_FATNSECTORS=1024 +CONFIG_NSH_FATMOUNTPT=/tmp + +# +# Architecture-specific NSH options +# +CONFIG_NSH_MMCSDSPIPORTNO=3 +CONFIG_NSH_MMCSDSLOTNO=0 +CONFIG_NSH_MMCSDMINOR=0 + +# +# Settings for mavlink +# +# CONFIG_MAVLINK - Enable MAVLINK app +# CONFIG_NSH_BUILTIN_APPS - Build the ADC test as an NSH built-in function. +# Default: Built as a standalone problem +CONFIG_MAVLINK=y + +# +# Stack and heap information +# +# CONFIG_BOOT_RUNFROMFLASH - Some configurations support XIP +# operation from FLASH but must copy initialized .data sections to RAM. +# (should also be =n for the STM3240G-EVAL which always runs from flash) +# CONFIG_BOOT_COPYTORAM - Some configurations boot in FLASH +# but copy themselves entirely into RAM for better performance. +# CONFIG_CUSTOM_STACK - The up_ implementation will handle +# all stack operations outside of the nuttx model. +# CONFIG_STACK_POINTER - The initial stack pointer (arm7tdmi only) +# CONFIG_IDLETHREAD_STACKSIZE - The size of the initial stack. +# This is the thread that (1) performs the inital boot of the system up +# to the point where user_start() is spawned, and (2) there after is the +# IDLE thread that executes only when there is no other thread ready to +# run. +# CONFIG_USERMAIN_STACKSIZE - The size of the stack to allocate +# for the main user thread that begins at the user_start() entry point. +# CONFIG_PTHREAD_STACK_MIN - Minimum pthread stack size +# CONFIG_PTHREAD_STACK_DEFAULT - Default pthread stack size +# CONFIG_HEAP_BASE - The beginning of the heap +# CONFIG_HEAP_SIZE - The size of the heap +# +CONFIG_BOOT_RUNFROMFLASH=n +CONFIG_BOOT_COPYTORAM=n +CONFIG_CUSTOM_STACK=n +CONFIG_STACK_POINTER= +# Idle thread needs 4096 bytes +# default 1 KB is not enough +CONFIG_IDLETHREAD_STACKSIZE=4096 +CONFIG_USERMAIN_STACKSIZE=3072 +CONFIG_PTHREAD_STACK_MIN=512 +CONFIG_PTHREAD_STACK_DEFAULT=2048 +CONFIG_HEAP_BASE= +CONFIG_HEAP_SIZE= diff --git a/nuttx/configs/px4fmu/nsh/setenv.sh b/nuttx/configs/px4fmu/nsh/setenv.sh new file mode 100755 index 0000000000..265520997d --- /dev/null +++ b/nuttx/configs/px4fmu/nsh/setenv.sh @@ -0,0 +1,67 @@ +#!/bin/bash +# configs/stm3240g-eval/nsh/setenv.sh +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +if [ "$_" = "$0" ] ; then + echo "You must source this script, not run it!" 1>&2 + exit 1 +fi + +WD=`pwd` +if [ ! -x "setenv.sh" ]; then + echo "This script must be executed from the top-level NuttX build directory" + exit 1 +fi + +if [ -z "${PATH_ORIG}" ]; then + export PATH_ORIG="${PATH}" +fi + +# This the Cygwin path to the location where I installed the RIDE +# toolchain under windows. You will also have to edit this if you install +# the RIDE toolchain in any other location +#export TOOLCHAIN_BIN="/cygdrive/c/Program Files (x86)/Raisonance/Ride/arm-gcc/bin" + +# This the Cygwin path to the location where I installed the CodeSourcery +# toolchain under windows. You will also have to edit this if you install +# the CodeSourcery toolchain in any other location +export TOOLCHAIN_BIN="/cygdrive/c/Program Files (x86)/CodeSourcery/Sourcery G++ Lite/bin" + +# This the Cygwin path to the location where I build the buildroot +# toolchain. +#export TOOLCHAIN_BIN="${WD}/../misc/buildroot/build_arm_nofpu/staging_dir/bin" + +# Add the path to the toolchain to the PATH varialble +export PATH="${TOOLCHAIN_BIN}:/sbin:/usr/sbin:${PATH_ORIG}" + +echo "PATH : ${PATH}" diff --git a/nuttx/configs/px4fmu/src/Makefile b/nuttx/configs/px4fmu/src/Makefile new file mode 100644 index 0000000000..2e3138aaa0 --- /dev/null +++ b/nuttx/configs/px4fmu/src/Makefile @@ -0,0 +1,102 @@ +############################################################################ +# configs/px4fmu/src/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +CFLAGS += -I$(TOPDIR)/sched + +ASRCS = +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +CSRCS = up_boot.c up_leds.c up_spi.c up_hrt.c \ + drv_gpio.c drv_bma180.c drv_l3gd20.c \ + drv_led.c drv_hmc5833l.c drv_ms5611.c drv_eeprom.c \ + drv_tone_alarm.c up_pwm_servo.c up_usbdev.c \ + up_cpuload.c drv_mpu6000.c + +ifeq ($(CONFIG_NSH_ARCHINIT),y) +CSRCS += up_nsh.c +endif + +ifeq ($(CONFIG_ADC),y) +CSRCS += up_adc.c +endif + +ifeq ($(CONFIG_CAN),y) +CSRCS += up_can.c +endif + +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ARCH_SRCDIR = $(TOPDIR)/arch/$(CONFIG_ARCH)/src +ifeq ($(WINTOOL),y) + CFLAGS += -I "${shell cygpath -w $(ARCH_SRCDIR)/chip}" \ + -I "${shell cygpath -w $(ARCH_SRCDIR)/common}" \ + -I "${shell cygpath -w $(ARCH_SRCDIR)/armv7-m}" +else + CFLAGS += -I$(ARCH_SRCDIR)/chip -I$(ARCH_SRCDIR)/common -I$(ARCH_SRCDIR)/armv7-m +endif + +all: libboard$(LIBEXT) + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS) $(LINKOBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +libboard$(LIBEXT): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +.depend: Makefile $(SRCS) + @$(MKDEP) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f libboard$(LIBEXT) *~ .*.swp + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep + diff --git a/nuttx/configs/px4fmu/src/drv_bma180.c b/nuttx/configs/px4fmu/src/drv_bma180.c new file mode 100644 index 0000000000..da80cc2e26 --- /dev/null +++ b/nuttx/configs/px4fmu/src/drv_bma180.c @@ -0,0 +1,341 @@ +/* + * Copyright (C) 2012 Lorenz Meier. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of the author or 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. + */ + +/* + * Driver for the Bosch BMA 180 MEMS accelerometer + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "chip.h" +#include "px4fmu-internal.h" + +#include + +/* + * BMA180 registers + */ + +/* Important Notes: + * + * - MAX SPI clock: 25 MHz + * - Readout time: 0.417 ms in high accuracy mode + * - Boot / ready time: 1.27 ms + * + */ + +#define DIR_READ (1<<7) +#define DIR_WRITE (0<<7) +#define ADDR_INCREMENT (1<<6) + +#define ADDR_CHIP_ID 0x00 +#define CHIP_ID 0x03 +#define ADDR_VERSION 0x01 + +#define ADDR_CTRL_REG0 0x0D +#define ADDR_CTRL_REG1 0x0E +#define ADDR_CTRL_REG2 0x0F +#define ADDR_BWTCS 0x20 +#define ADDR_CTRL_REG3 0x21 +#define ADDR_CTRL_REG4 0x22 +#define ADDR_OLSB1 0x35 + +#define ADDR_ACC_X_LSB 0x02 +#define ADDR_ACC_Z_MSB 0x07 +#define ADDR_TEMPERATURE 0x08 + +#define ADDR_STATUS_REG1 0x09 +#define ADDR_STATUS_REG2 0x0A +#define ADDR_STATUS_REG3 0x0B +#define ADDR_STATUS_REG4 0x0C + +#define ADDR_RESET 0x10 +#define SOFT_RESET 0xB6 + +#define ADDR_DIS_I2C 0x27 + +#define REG0_WRITE_ENABLE 0x10 + +#define RANGEMASK 0x0E +#define BWMASK 0xF0 + + +static ssize_t bma180_read(struct file *filp, FAR char *buffer, size_t buflen); +static int bma180_ioctl(struct file *filp, int cmd, unsigned long arg); + +static const struct file_operations bma180_fops = { + .read = bma180_read, + .ioctl = bma180_ioctl, +}; + +struct bma180_dev_s +{ + struct spi_dev_s *spi; + int spi_id; + uint8_t rate; + struct bma180_buffer *buffer; +}; + +static struct bma180_dev_s bma180_dev; + +static void bma180_write_reg(uint8_t address, uint8_t data); +static uint8_t bma180_read_reg(uint8_t address); +static bool read_fifo(uint16_t *data); +static int bma180_set_range(uint8_t range); +static int bma180_set_rate(uint8_t rate); + +static void +bma180_write_reg(uint8_t address, uint8_t data) +{ + uint8_t cmd[2] = { address | DIR_WRITE, data }; + + SPI_SELECT(bma180_dev.spi, bma180_dev.spi_id, true); + SPI_SNDBLOCK(bma180_dev.spi, &cmd, sizeof(cmd)); + SPI_SELECT(bma180_dev.spi, bma180_dev.spi_id, false); +} + +static uint8_t +bma180_read_reg(uint8_t address) +{ + uint8_t cmd[2] = {address | DIR_READ, 0}; + uint8_t data[2]; + + SPI_SELECT(bma180_dev.spi, bma180_dev.spi_id, true); + SPI_EXCHANGE(bma180_dev.spi, cmd, data, sizeof(cmd)); + SPI_SELECT(bma180_dev.spi, bma180_dev.spi_id, false); + + return data[1]; +} + +static bool +read_fifo(uint16_t *data) +{ + struct { /* status register and data as read back from the device */ + uint8_t cmd; + int16_t x; + int16_t y; + int16_t z; + uint8_t temp; + } __attribute__((packed)) report; + + report.cmd = ADDR_ACC_X_LSB | DIR_READ | ADDR_INCREMENT; + + SPI_LOCK(bma180_dev.spi, true); + report.x = bma180_read_reg(ADDR_ACC_X_LSB); + report.x |= (bma180_read_reg(ADDR_ACC_X_LSB+1) << 8); + report.y = bma180_read_reg(ADDR_ACC_X_LSB+2); + report.y |= (bma180_read_reg(ADDR_ACC_X_LSB+3) << 8); + report.z = bma180_read_reg(ADDR_ACC_X_LSB+4); + report.z |= (bma180_read_reg(ADDR_ACC_X_LSB+5) << 8); + report.temp = bma180_read_reg(ADDR_ACC_X_LSB+6); + SPI_LOCK(bma180_dev.spi, false); + + /* Collect status and remove two top bits */ + + uint8_t new_data = (report.x & 0x01) + (report.x & 0x01) + (report.x & 0x01); + report.x = (report.x >> 2); + report.y = (report.y >> 2); + report.z = (report.z >> 2); + + data[0] = report.x; + data[1] = report.y; + data[2] = report.z; + + /* return 1 for all three axes new */ + return (new_data > 0); // bit funky, depends on timing +} + +static int +bma180_set_range(uint8_t range) +{ + /* enable writing to chip config */ + uint8_t ctrl0 = bma180_read_reg(ADDR_CTRL_REG0); + ctrl0 |= REG0_WRITE_ENABLE; + bma180_write_reg(ADDR_CTRL_REG0, ctrl0); + + /* set range */ + uint8_t olsb1 = bma180_read_reg(ADDR_OLSB1); + olsb1 &= (~RANGEMASK); + olsb1 |= (range);// & RANGEMASK); + bma180_write_reg(ADDR_OLSB1, olsb1); + + // up_udelay(500); + + /* block writing to chip config */ + ctrl0 = bma180_read_reg(ADDR_CTRL_REG0); + ctrl0 &= (~REG0_WRITE_ENABLE); + bma180_write_reg(ADDR_CTRL_REG0, ctrl0); + + uint8_t new_olsb1 = bma180_read_reg(ADDR_OLSB1); + + /* return 0 on success, 1 on failure */ + return !(olsb1 == new_olsb1); +} + +static int +bma180_set_rate(uint8_t rate) +{ + /* enable writing to chip config */ + uint8_t ctrl0 = bma180_read_reg(ADDR_CTRL_REG0); + ctrl0 |= REG0_WRITE_ENABLE; + bma180_write_reg(ADDR_CTRL_REG0, ctrl0); + + /* set rate / bandwidth */ + uint8_t bwtcs = bma180_read_reg(ADDR_BWTCS); + bwtcs &= (~BWMASK); + bwtcs |= (rate);// & BWMASK); + bma180_write_reg(ADDR_BWTCS, bwtcs); + + // up_udelay(500); + + /* block writing to chip config */ + ctrl0 = bma180_read_reg(ADDR_CTRL_REG0); + ctrl0 &= (~REG0_WRITE_ENABLE); + bma180_write_reg(ADDR_CTRL_REG0, ctrl0); + + uint8_t new_bwtcs = bma180_read_reg(ADDR_BWTCS); + + /* return 0 on success, 1 on failure */ + return !(bwtcs == new_bwtcs); +} + +static ssize_t +bma180_read(struct file *filp, char *buffer, size_t buflen) +{ + /* if the buffer is large enough, and data are available, return success */ + if (buflen >= 6) { + if (read_fifo((uint16_t *)buffer)) + return 6; + + /* no data */ + return 0; + } + + /* buffer too small */ + errno = ENOSPC; + return ERROR; +} + +static int +bma180_ioctl(struct file *filp, int cmd, unsigned long arg) +{ + int result = ERROR; + + switch (cmd) { + case BMA180_SETRATE: + result = bma180_set_rate(arg); + break; + + case BMA180_SETRANGE: + result = bma180_set_range(arg); + break; + + case BMA180_SETBUFFER: + bma180_dev.buffer = (struct bma180_buffer *)arg; + result = 0; + break; + } + + if (result) + errno = EINVAL; + return result; +} + +int +bma180_attach(struct spi_dev_s *spi, int spi_id) +{ + int result = ERROR; + + bma180_dev.spi = spi; + bma180_dev.spi_id = spi_id; + + SPI_LOCK(bma180_dev.spi, true); + + /* verify that the device is attached and functioning */ + if (bma180_read_reg(ADDR_CHIP_ID) == CHIP_ID) { + + bma180_write_reg(ADDR_RESET, SOFT_RESET); // page 48 + + up_udelay(13000); // wait 12 ms, see page 49 + + /* Configuring the BMA180 */ + + /* enable writing to chip config */ + uint8_t ctrl0 = bma180_read_reg(ADDR_CTRL_REG0); + ctrl0 |= REG0_WRITE_ENABLE; + bma180_write_reg(ADDR_CTRL_REG0, ctrl0); + + /* disable I2C interface, datasheet page 31 */ + uint8_t disi2c = bma180_read_reg(ADDR_DIS_I2C); + disi2c |= 0x01; + bma180_write_reg(ADDR_DIS_I2C, disi2c); + + /* block writing to chip config */ + ctrl0 = bma180_read_reg(ADDR_CTRL_REG0); + ctrl0 &= (~REG0_WRITE_ENABLE); + bma180_write_reg(ADDR_CTRL_REG0, ctrl0); + + // up_udelay(500); + + /* set rate */ + result = bma180_set_rate(BMA180_RATE_LP_600HZ); + + // up_udelay(500); + + /* set range */ + result += bma180_set_range(BMA180_RANGE_4G); + + // up_udelay(500); + + if (result == 0) { + /* make ourselves available */ + register_driver("/dev/bma180", &bma180_fops, 0666, NULL); + } + } else { + errno = EIO; + } + + SPI_LOCK(bma180_dev.spi, false); + + return result; +} + diff --git a/nuttx/configs/px4fmu/src/drv_eeprom.c b/nuttx/configs/px4fmu/src/drv_eeprom.c new file mode 100644 index 0000000000..c22062ec50 --- /dev/null +++ b/nuttx/configs/px4fmu/src/drv_eeprom.c @@ -0,0 +1,522 @@ +/* + * Copyright (C) 2012 Lorenz Meier. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of the author or 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. + */ + +/* + * Generic driver for I2C EEPROMs with 8 bit or 16 bit addressing + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "chip.h" +#include "stm32_internal.h" +#include "px4fmu-internal.h" + +#include + +/* Split I2C transfers into smaller chunks to make sure to stay within tight timeout limits */ + +/* check defines */ +#ifndef MAX_EEPROMS + #error MAX_EEPROMS number must be defined (1-3) +#endif + +#if (MAX_EEPROMS > 3) + #error Currently only a maximum of three EEPROMS is supported, add missing code around here: __FILE__:__LINE__ +#endif +static int eeprom_open0(FAR struct file *filp); +static int eeprom_close0(FAR struct file *filp); +static ssize_t eeprom_read0(struct file *filp, FAR char *buffer, size_t buflen); +static ssize_t eeprom_write0(struct file *filp, FAR const char *buffer, size_t buflen); +static off_t eeprom_seek0(FAR struct file *filp, off_t offset, int whence); +#if (MAX_EEPROMS > 1) +static int eeprom_open1(FAR struct file *filp); +static int eeprom_close1(FAR struct file *filp); +static ssize_t eeprom_read1(struct file *filp, FAR char *buffer, size_t buflen); +static ssize_t eeprom_write1(struct file *filp, FAR const char *buffer, size_t buflen); +static off_t eeprom_seek1(FAR struct file *filp, off_t offset, int whence); +#endif +#if (MAX_EEPROMS > 2) +static int eeprom_open2(FAR struct file *filp); +static int eeprom_close2(FAR struct file *filp); +static ssize_t eeprom_read2(struct file *filp, FAR char *buffer, size_t buflen); +static ssize_t eeprom_write2(struct file *filp, FAR const char *buffer, size_t buflen); +static off_t eeprom_seek2(FAR struct file *filp, off_t offset, int whence); +#endif + +static const struct file_operations eeprom_fops[MAX_EEPROMS] = {{ + .open = eeprom_open0, + .close = eeprom_close0, + .read = eeprom_read0, + .write = eeprom_write0, + .seek = eeprom_seek0, + .ioctl = 0, +#ifndef CONFIG_DISABLE_POLL + .poll = 0 +#endif +} +#if (MAX_EEPROMS > 1) +,{ + .open = eeprom_open1, + .close = eeprom_close1, + .read = eeprom_read1, + .write = eeprom_write1, + .seek = eeprom_seek1, +} +#endif +#if (MAX_EEPROMS > 2) +,{ + .open = eeprom_open2, + .close = eeprom_close2, + .read = eeprom_read2, + .write = eeprom_write2, + .seek = eeprom_seek2, +} +#endif +}; + +static FAR struct eeprom_dev_s +{ + struct i2c_dev_s *i2c; + uint8_t eeprom_address; + uint16_t eeprom_size_bytes; + uint16_t eeprom_page_size_bytes; + uint16_t eeprom_page_write_time; + off_t offset; + bool is_open; +} eeprom_dev[MAX_EEPROMS]; + +static int +eeprom_open0(FAR struct file *filp) +{ + /* only allow one open at a time */ + if (eeprom_dev[0].is_open) { + errno = EBUSY; + return -EBUSY; + } + /* reset pointer */ + //eeprom_dev[0].is_open = true; + eeprom_dev[0].offset = 0; + return OK; +} +#if (MAX_EEPROMS > 1) +static int +eeprom_open1(FAR struct file *filp) +{ + /* only allow one open at a time */ + if (eeprom_dev[1].is_open) { + errno = EBUSY; + return -EBUSY; + } + /* reset pointer */ + //eeprom_dev[1].is_open = true; + eeprom_dev[1].offset = 0; + return OK; +} +#endif +#if (MAX_EEPROMS > 2) +static int +eeprom_open2(FAR struct file *filp) +{ + /* only allow one open at a time */ + if (eeprom_dev[2].is_open) { + errno = EBUSY; + return -EBUSY; + } + /* reset pointer */ + //eeprom_dev[2].is_open = true; + eeprom_dev[2].offset = 0; + return OK; +} +#endif + +static int +eeprom_close0(FAR struct file *filp) +{ + eeprom_dev[0].is_open = false; + return OK; +} +#if (MAX_EEPROMS > 1) +static int +eeprom_close1(FAR struct file *filp) +{ + eeprom_dev[1].is_open = false; + return OK; +} +#endif +#if (MAX_EEPROMS > 2) +static int +eeprom_close2(FAR struct file *filp) +{ + eeprom_dev[2].is_open = false; + return OK; +} +#endif + +static int +eeprom_read_internal(int dev, uint16_t len, uint8_t *data) +{ + /* abort if the number of requested bytes exceeds the EEPROM size */ + if (eeprom_dev[dev].offset + len > eeprom_dev[dev].eeprom_size_bytes) + { + errno = ENOSPC; + return -ENOSPC; + } + + /* set device address */ + I2C_SETADDRESS(eeprom_dev[dev].i2c, eeprom_dev[dev].eeprom_address, 7); + + uint8_t cmd[2] = {0, 0}; /* first (or only) part of address */ + /* second part of address, omitted if eeprom has 256 bytes or less */ + int ret = 0; + int remaining = len; + int readcounts = 0; + + while (remaining > 0) + { + /* read all requested bytes over potentially multiple pages */ + //int readlen = (remaining < eeprom_dev[dev].eeprom_page_size_bytes) ? remaining : eeprom_dev[dev].eeprom_page_size_bytes; + int read_offset = eeprom_dev[dev].offset + len - remaining;//+ write_counts*eeprom_dev[dev].eeprom_page_size_bytes; + /* set read length to page border */ + int readlen = eeprom_dev[dev].eeprom_page_size_bytes - (read_offset % eeprom_dev[dev].eeprom_page_size_bytes);//(remaining < eeprom_dev[dev].eeprom_page_size_bytes) ? remaining : eeprom_dev[dev].eeprom_page_size_bytes; + /* cap read length if not a full page read is needed */ + if (readlen > remaining) readlen = remaining; + + if (eeprom_dev[dev].eeprom_size_bytes <= 256) + { + cmd[0] = (read_offset); /* set at first byte */ + /* 8 bit addresses */ + ret = I2C_WRITEREAD(eeprom_dev[dev].i2c, cmd, 1, (data+(readcounts*eeprom_dev[dev].eeprom_page_size_bytes)), readlen); + } + else + { + /* 16 bit addresses */ + /* EEPROM: first address high, then address low */ + cmd[0] = (((uint16_t)read_offset) >> 8); + cmd[1] = (((uint8_t)read_offset)); + ret = I2C_WRITEREAD(eeprom_dev[dev].i2c, cmd, 2, (data+(readcounts*eeprom_dev[dev].eeprom_page_size_bytes)), readlen); + } + + /* abort on error */ + if (ret < 0) break; + + /* handled another chunk */ + remaining -= readlen; + readcounts++; + } + + /* use the negated value from I2C_TRANSFER to fill errno */ + errno = -ret; + + /* return len if data was read, < 0 else */ + if (ret == OK) + eeprom_dev[dev].offset += len; + return len; + + /* no data, return negated value from I2C_TRANSFER */ + return ret; +} + +static int +eeprom_write_internal(int dev, uint16_t len, const uint8_t *data) +{ + /* abort if the number of requested bytes exceeds the EEPROM size */ + if (eeprom_dev[dev].offset + len > eeprom_dev[dev].eeprom_size_bytes) + { + errno = ENOSPC; + return -ENOSPC; + } + + int ret = 0; + int remaining = len; + int write_counts = 0; + + uint8_t write_buf[2]; + + while (remaining > 0) + { + /* write all requested bytes over potentially multiple pages */ + int write_offset = eeprom_dev[dev].offset + len - remaining;//+ write_counts*eeprom_dev[dev].eeprom_page_size_bytes; + /* set write length to page border */ + int writelen = eeprom_dev[dev].eeprom_page_size_bytes - (write_offset % eeprom_dev[dev].eeprom_page_size_bytes);//(remaining < eeprom_dev[dev].eeprom_page_size_bytes) ? remaining : eeprom_dev[dev].eeprom_page_size_bytes; + /* cap write length if not a full page write is requested */ + if (writelen > remaining) writelen = remaining; + + if (eeprom_dev[dev].eeprom_size_bytes <= 256) + { + write_buf[0] = (write_offset); /* set at first byte */ + /* 8 bit addresses */ + + const uint8_t* data_ptr = (data+(write_offset)); + + struct i2c_msg_s msgv_eeprom_write[2] = { + { + .addr = eeprom_dev[dev].eeprom_address, + .flags = I2C_M_NORESTART, + .buffer = write_buf, + .length = 1 + }, + { + .addr = eeprom_dev[dev].eeprom_address, + .flags = I2C_M_NORESTART, + .buffer = (uint8_t*)data_ptr, + .length = writelen + } + }; + + + if ( (ret = I2C_TRANSFER(eeprom_dev[dev].i2c, msgv_eeprom_write, 2)) == OK ) + { + //printf("SUCCESS WRITING EEPROM 8BIT ADDR: %d, bytes: %d\n", ret, writelen); + } + } + else + { + /* 16 bit addresses */ + /* EEPROM: first address high, then address low */ + write_buf[0] = (((uint16_t)write_offset) >> 8); + write_buf[1] = (((uint8_t)write_offset)); + + const uint8_t* data_ptr = data+(write_counts*eeprom_dev[dev].eeprom_page_size_bytes); + + struct i2c_msg_s msgv_eeprom_write[2] = { + { + .addr = eeprom_dev[dev].eeprom_address, + .flags = I2C_M_NORESTART, + .buffer = write_buf, + .length = 2 + }, + { + .addr = eeprom_dev[dev].eeprom_address, + .flags = I2C_M_NORESTART, + .buffer = (uint8_t*)data_ptr, + .length = writelen + } + }; + + + if ( (ret = I2C_TRANSFER(eeprom_dev[dev].i2c, msgv_eeprom_write, 2)) == OK ) + { + //printf("SUCCESS WRITING EEPROM 16BIT ADDR: %d, bytes: %d\n", ret, writelen); + } + } + + /* abort on error */ + if (ret < 0) break; + + /* handled another chunk */ + remaining -= writelen; + write_counts++; + /* wait for the device to write the page */ + usleep(eeprom_dev[dev].eeprom_page_write_time); + } + + /* use the negated value from I2C_TRANSFER to fill errno */ + errno = -ret; + + /* return length if data was written, < 0 else */ + if (ret == OK) + eeprom_dev[dev].offset += len; + return len; + + /* no data, return negated value from I2C_TRANSFER */ + return ret; +} + +static ssize_t +eeprom_read0(struct file *filp, char *buffer, size_t buflen) +{ + return eeprom_read_internal(0, buflen, (uint8_t *)buffer); +} +#if (MAX_EEPROMS > 1) +static ssize_t +eeprom_read1(struct file *filp, char *buffer, size_t buflen) +{ + return eeprom_read_internal(1, buflen, (uint8_t *)buffer); +} +#endif +#if (MAX_EEPROMS > 2) +static ssize_t +eeprom_read2(struct file *filp, char *buffer, size_t buflen) +{ + return eeprom_read_internal(2, buflen, (uint8_t *)buffer); +} +#endif + +static ssize_t +eeprom_write0(struct file *filp, const char *buffer, size_t buflen) +{ + return eeprom_write_internal(0, buflen, (const uint8_t *)buffer); +} +#if (MAX_EEPROMS > 1) +static ssize_t +eeprom_write1(struct file *filp, const char *buffer, size_t buflen) +{ + return eeprom_write_internal(1, buflen, (const uint8_t *)buffer); +} +#endif +#if (MAX_EEPROMS > 2) +static ssize_t +eeprom_write2(struct file *filp, const char *buffer, size_t buflen) +{ + return eeprom_write_internal(2, buflen, (const uint8_t *)buffer); +} +#endif + +static off_t eeprom_seek0(FAR struct file *filp, off_t offset, int whence) +{ + switch (whence) + { + case SEEK_SET: + if (offset < eeprom_dev[0].eeprom_size_bytes - 1) { + eeprom_dev[0].offset = offset; + } else { + errno = ESPIPE; + return -ESPIPE; + } + break; + case SEEK_CUR: + if (eeprom_dev[0].offset + offset < eeprom_dev[0].eeprom_size_bytes - 1) { + eeprom_dev[0].offset = eeprom_dev[0].offset + offset; + } else { + errno = ESPIPE; + return -ESPIPE; + } + break; + case SEEK_END: + errno = ESPIPE; + return -ESPIPE; + break; + } + return eeprom_dev[0].offset; +} +#if (MAX_EEPROMS > 1) +static off_t eeprom_seek1(FAR struct file *filp, off_t offset, int whence) +{ + switch (whence) + { + case SEEK_SET: + if (offset < eeprom_dev[1].eeprom_size_bytes - 1) { + eeprom_dev[1].offset = offset; + } else { + errno = ESPIPE; + return -ESPIPE; + } + break; + case SEEK_CUR: + if (eeprom_dev[1].offset + offset < eeprom_dev[1].eeprom_size_bytes - 1) { + eeprom_dev[1].offset = eeprom_dev[1].offset + offset; + } else { + errno = ESPIPE; + return -ESPIPE; + } + break; + case SEEK_END: + errno = ESPIPE; + return -ESPIPE; + break; + } + return eeprom_dev[1].offset; +} +#endif +#if (MAX_EEPROMS > 2) +static off_t eeprom_seek2(FAR struct file *filp, off_t offset, int whence) +{ + switch (whence) + { + case SEEK_SET: + if (offset < eeprom_dev[2].eeprom_size_bytes - 1) { + eeprom_dev[2].offset = offset; + } else { + errno = ESPIPE; + return -ESPIPE; + } + break; + case SEEK_CUR: + if (eeprom_dev[2].offset + offset < eeprom_dev[2].eeprom_size_bytes - 1) { + eeprom_dev[2].offset = eeprom_dev[2].offset + offset; + } else { + errno = ESPIPE; + return -ESPIPE; + } + break; + case SEEK_END: + errno = ESPIPE; + return -ESPIPE; + break; + } + return eeprom_dev[2].offset; +} +#endif + +int +eeprom_attach(struct i2c_dev_s *i2c, uint8_t device_address, uint16_t total_size_bytes, uint16_t page_size_bytes, uint16_t page_write_time_us, const char* device_name, uint8_t fail_if_missing) +{ + static int eeprom_dev_counter = 0; + eeprom_dev[eeprom_dev_counter].i2c = i2c; + eeprom_dev[eeprom_dev_counter].eeprom_address = device_address; + eeprom_dev[eeprom_dev_counter].eeprom_size_bytes = total_size_bytes; + eeprom_dev[eeprom_dev_counter].eeprom_page_size_bytes = page_size_bytes; + eeprom_dev[eeprom_dev_counter].eeprom_page_write_time = page_write_time_us; + eeprom_dev[eeprom_dev_counter].offset = 0; + eeprom_dev[eeprom_dev_counter].is_open = false; + + int ret; + + if (fail_if_missing) { + /* read first value */ + uint8_t read_test; + ret = (eeprom_read_internal(eeprom_dev_counter, 1, &read_test) == 1) ? OK : ERROR; + } else { + ret = OK; + } + + /* make ourselves available */ + if (ret == OK) + { + register_driver(device_name, &(eeprom_fops[eeprom_dev_counter]), 0666, NULL); + eeprom_dev_counter++; + } + + /* Return 0 for device found, error number else */ + return ret; +} diff --git a/nuttx/configs/px4fmu/src/drv_gpio.c b/nuttx/configs/px4fmu/src/drv_gpio.c new file mode 100644 index 0000000000..be95420ddc --- /dev/null +++ b/nuttx/configs/px4fmu/src/drv_gpio.c @@ -0,0 +1,195 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * GPIO driver for PX4FMU. + * + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "chip.h" +#include "stm32_internal.h" +#include "px4fmu-internal.h" + +#include + +static int px4fmu_gpio_ioctl(struct file *filep, int cmd, unsigned long arg); + +static const struct file_operations px4fmu_gpio_fops = { + .ioctl = px4fmu_gpio_ioctl, +}; + +static struct { + uint32_t input; + uint32_t output; + uint32_t alt; +} gpio_tab[] = { + {GPIO_GPIO0_INPUT, GPIO_GPIO0_OUTPUT, 0}, + {GPIO_GPIO1_INPUT, GPIO_GPIO1_OUTPUT, 0}, + {GPIO_GPIO2_INPUT, GPIO_GPIO2_OUTPUT, GPIO_USART2_CTS_1}, + {GPIO_GPIO3_INPUT, GPIO_GPIO3_OUTPUT, GPIO_USART2_RTS_1}, + {GPIO_GPIO4_INPUT, GPIO_GPIO4_OUTPUT, GPIO_USART2_TX_1}, + {GPIO_GPIO5_INPUT, GPIO_GPIO5_OUTPUT, GPIO_USART2_RX_1}, + {GPIO_GPIO6_INPUT, GPIO_GPIO6_OUTPUT, GPIO_CAN2_TX_2}, + {GPIO_GPIO7_INPUT, GPIO_GPIO7_OUTPUT, GPIO_CAN2_RX_2}, +}; + +#define NGPIO (sizeof(gpio_tab) / sizeof(gpio_tab[0])) + + +static void +px4fmu_gpio_reset(void) +{ + /* + * Setup default GPIO config - all pins as GPIOs, GPIO driver chip + * to input mode. + */ + for (unsigned i = 0; i < NGPIO; i++) + stm32_configgpio(gpio_tab[i].input); + + stm32_gpiowrite(GPIO_GPIO_DIR, 0); + stm32_configgpio(GPIO_GPIO_DIR); +} + +static void +px4fmu_gpio_set_function(uint32_t gpios, int function) +{ + /* + * GPIOs 0 and 1 must have the same direction as they are buffered + * by a shared 2-port driver. Any attempt to set either sets both. + */ + if (gpios & 3) { + gpios |= 3; + + /* flip the buffer to output mode if required */ + if (GPIO_SET_OUTPUT == function) + stm32_gpiowrite(GPIO_GPIO_DIR, 1); + } + + /* configure selected GPIOs as required */ + for (unsigned i = 0; i < NGPIO; i++) { + if (gpios & (1< + +#include +#include +#include +#include +#include + +#include +#include + +#include "chip.h" +#include "px4fmu-internal.h" + +#include + +#define ADDR_CONF_A 0x00 +#define ADDR_CONF_B 0x01 +#define ADDR_MODE 0x02 +#define ADDR_DATA_OUT_X_MSB 0x03 +#define ADDR_DATA_OUT_X_LSB 0x04 +#define ADDR_DATA_OUT_Z_MSB 0x05 +#define ADDR_DATA_OUT_Z_LSB 0x06 +#define ADDR_DATA_OUT_Y_MSB 0x07 +#define ADDR_DATA_OUT_Y_LSB 0x08 +#define ADDR_STATUS 0x09 +#define ADDR_ID_A 0x10 +#define ADDR_ID_B 0x11 +#define ADDR_ID_C 0x12 + +#define HMC5883L_ADDRESS 0x1E + +/* modes not changeable outside of driver */ +#define HMC5883L_MODE_NORMAL (0 << 0) /* default */ +#define HMC5883L_MODE_POSITIVE_BIAS (1 << 0) /* positive bias */ +#define HMC5883L_MODE_NEGATIVE_BIAS (1 << 1) /* negative bias */ + +#define HMC5883L_AVERAGING_1 (0 << 5) /* conf a register */ +#define HMC5883L_AVERAGING_2 (1 << 5) +#define HMC5883L_AVERAGING_4 (2 << 5) +#define HMC5883L_AVERAGING_8 (3 << 5) + +#define MODE_REG_CONTINOUS_MODE (0 << 0) +#define MODE_REG_SINGLE_MODE (1 << 0) /* default */ + +#define STATUS_REG_DATA_OUT_LOCK (1 << 1) /* page 16: set if data is only partially read, read device to reset */ +#define STATUS_REG_DATA_READY (1 << 0) /* page 16: set if all axes have valid measurements */ + +#define ID_A_WHO_AM_I 'H' +#define ID_B_WHO_AM_I '4' +#define ID_C_WHO_AM_I '3' + +static FAR struct hmc5883l_dev_s hmc5883l_dev; + +static ssize_t hmc5883l_read(struct file *filp, FAR char *buffer, size_t buflen); +static int hmc5883l_ioctl(struct file *filp, int cmd, unsigned long arg); + +static const struct file_operations hmc5883l_fops = { + .open = 0, + .close = 0, + .read = hmc5883l_read, + .write = 0, + .seek = 0, + .ioctl = hmc5883l_ioctl, +#ifndef CONFIG_DISABLE_POLL + .poll = 0 +#endif +}; + +struct hmc5883l_dev_s +{ + struct i2c_dev_s *i2c; + uint8_t rate; + struct hmc5883l_buffer *buffer; +}; + +static int hmc5883l_write_reg(uint8_t address, uint8_t data); +static int hmc5883l_read_reg(uint8_t address); +static int hmc5883l_reset(void); + +static int +hmc5883l_write_reg(uint8_t address, uint8_t data) +{ + uint8_t cmd[] = {address, data}; + return I2C_WRITE(hmc5883l_dev.i2c, cmd, 2); +} + +static int +hmc5883l_read_reg(uint8_t address) +{ + uint8_t cmd = address; + uint8_t data; + + int ret = I2C_WRITEREAD(hmc5883l_dev.i2c, &cmd, 1, &data, 1); + /* return data on success, error code on failure */ + if (ret == OK) { + ret = data; + } + return ret; +} + +static int +hmc5883l_set_range(uint8_t range) +{ + I2C_SETADDRESS(hmc5883l_dev.i2c, HMC5883L_ADDRESS, 7); + + + /* mask out illegal bit positions */ + uint8_t write_range = range; //& REG4_RANGE_MASK; + /* immediately return if user supplied invalid value */ + if (write_range != range) return EINVAL; + /* set remaining bits to a sane value */ +// write_range |= REG4_BDU; + /* write to device */ + hmc5883l_write_reg(ADDR_CONF_B, write_range); + /* return 0 if register value is now written value, 1 if unchanged */ + return !(hmc5883l_read_reg(ADDR_CONF_B) == write_range); +} + +static int +hmc5883l_set_rate(uint8_t rate) +{ + I2C_SETADDRESS(hmc5883l_dev.i2c, HMC5883L_ADDRESS, 7); + /* mask out illegal bit positions */ + uint8_t write_rate = rate;// & REG1_RATE_LP_MASK; + /* immediately return if user supplied invalid value */ + if (write_rate != rate) return EINVAL; + /* set remaining bits to a sane value */ +// write_rate |= REG1_POWER_NORMAL | REG1_Z_ENABLE | REG1_Y_ENABLE | REG1_X_ENABLE; + write_rate |= HMC5883L_AVERAGING_8; + /* write to device */ + hmc5883l_write_reg(ADDR_CONF_A, write_rate); + /* return 0 if register value is now written value, 1 if unchanged */ + return !(hmc5883l_read_reg(ADDR_CONF_A) == write_rate); +} + +static bool +read_values(int16_t *data) +{ + struct { /* status register and data as read back from the device */ + int16_t x; + int16_t z; + int16_t y; + uint8_t status; + } __attribute__((packed)) hmc_report; + hmc_report.status = 0; + + static int read_err_count = 0; + + /* exchange the report structure with the device */ + + uint8_t cmd = ADDR_DATA_OUT_X_MSB; + + int ret = 0; + + I2C_SETADDRESS(hmc5883l_dev.i2c, HMC5883L_ADDRESS, 7); + + /* set device into single mode, trigger next measurement */ + ret = hmc5883l_write_reg(ADDR_MODE, MODE_REG_SINGLE_MODE); + + /* Only execute consecutive steps on success */ + if (ret == OK) + { + cmd = ADDR_DATA_OUT_X_MSB; + ret = I2C_WRITEREAD(hmc5883l_dev.i2c, &cmd, 1, (uint8_t*)&hmc_report, 6); + if (ret == OK) + { + /* Six bytes to read, stop if timed out */ + int hmc_status = hmc5883l_read_reg(ADDR_STATUS); + if (hmc_status < 0) + { + if (ret == ETIMEDOUT) hmc5883l_reset(); + ret = hmc_status; + } + else + { + hmc_report.status = hmc_status; + ret = OK; + } + } + else + { + if (ret == ETIMEDOUT) hmc5883l_reset(); + } + } + else + { + if (ret == ETIMEDOUT) hmc5883l_reset(); + } + + if (ret != OK) + { + read_err_count++; + /* If the last reads failed as well, reset the bus and chip */ + if (read_err_count > 3) hmc5883l_reset(); + + *get_errno_ptr() = -ret; + } else { + read_err_count = 0; + /* write values, and exchange the two 8bit blocks (big endian to little endian) */ + data[0] = ((hmc_report.x & 0x00FF) << 8) | ((hmc_report.x & 0xFF00) >> 8); + data[1] = ((hmc_report.y & 0x00FF) << 8) | ((hmc_report.y & 0xFF00) >> 8); + data[2] = ((hmc_report.z & 0x00FF) << 8) | ((hmc_report.z & 0xFF00) >> 8); + if ((hmc_report.status & STATUS_REG_DATA_READY) > 0) + { + ret = 6; + } else { + ret = -EAGAIN; + } + } + + /* return len if new data is available, error else. hmc_report.status is 0 on errors */ + return ret; +} + +static ssize_t +hmc5883l_read(struct file *filp, char *buffer, size_t buflen) +{ + /* if the buffer is large enough, and data are available, return success */ + if (buflen >= 6) { + return read_values((int16_t *)buffer); + } + + /* buffer too small */ + *get_errno_ptr() = ENOSPC; + return -ERROR; +} + +static int +hmc5883l_ioctl(struct file *filp, int cmd, unsigned long arg) +{ + int result = ERROR; + + switch (cmd) { + case HMC5883L_SETRATE: + result = hmc5883l_set_rate(arg); + break; + + case HMC5883L_SETRANGE: + result = hmc5883l_set_range(arg); + break; +// +// case HMC5883L_SETBUFFER: +// hmc5883l_dev.buffer = (struct hmc5883l_buffer *)arg; +// result = 0; +// break; + + case HMC5883L_RESET: + result = hmc5883l_reset(); + break; + } + + if (result) + errno = EINVAL; + return result; +} + +int hmc5883l_reset() +{ + int ret; + printf("[hmc5883l drv] Resettet I2C2 BUS\n"); + up_i2cuninitialize(hmc5883l_dev.i2c); + hmc5883l_dev.i2c = up_i2cinitialize(2); + I2C_SETFREQUENCY(hmc5883l_dev.i2c, 400000); + // up_i2creset(hmc5883l_dev.i2c); + //I2C_SETADDRESS(hmc5883l_dev.i2c, HMC5883L_ADDRESS, 7); + //hmc5883l_set_range(HMC5883L_RANGE_0_88GA); + //hmc5883l_set_rate(HMC5883L_RATE_75HZ); + /* set device into single mode, start measurement */ + //ret = hmc5883l_write_reg(ADDR_MODE, MODE_REG_SINGLE_MODE); + return ret; +} + +int +hmc5883l_attach(struct i2c_dev_s *i2c) +{ + int result = ERROR; + + hmc5883l_dev.i2c = i2c; + +// I2C_LOCK(hmc5883l_dev.i2c, true); + I2C_SETADDRESS(hmc5883l_dev.i2c, HMC5883L_ADDRESS, 7); + + uint8_t cmd = ADDR_STATUS; + uint8_t status_id[4] = {0, 0, 0, 0}; + + + int ret = I2C_WRITEREAD(i2c, &cmd, 1, status_id, 4); + + /* verify that the device is attached and functioning */ + if ((ret >= 0) && (status_id[1] == ID_A_WHO_AM_I) && (status_id[2] == ID_B_WHO_AM_I) && (status_id[3] == ID_C_WHO_AM_I)) { + + /* set update rate to 75 Hz */ + /* set 0.88 Ga range */ + if ((ret != 0) || (hmc5883l_set_range(HMC5883L_RANGE_0_88GA) != 0) || + (hmc5883l_set_rate(HMC5883L_RATE_75HZ) != 0)) + { + errno = EIO; + } else { + + /* set device into single mode, start measurement */ + ret = hmc5883l_write_reg(ADDR_MODE, MODE_REG_SINGLE_MODE); + + /* make ourselves available */ + register_driver("/dev/hmc5883l", &hmc5883l_fops, 0666, NULL); + + result = 0; + } + + } else { + errno = EIO; + } + + + + return result; +} diff --git a/nuttx/configs/px4fmu/src/drv_l3gd20.c b/nuttx/configs/px4fmu/src/drv_l3gd20.c new file mode 100644 index 0000000000..1c6c054495 --- /dev/null +++ b/nuttx/configs/px4fmu/src/drv_l3gd20.c @@ -0,0 +1,364 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * Driver for the ST L3GD20 MEMS gyroscope + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "chip.h" +#include "stm32_internal.h" +#include "px4fmu-internal.h" + +#define DIR_READ (1<<7) +#define DIR_WRITE (0<<7) +#define ADDR_INCREMENT (1<<6) + +#define ADDR_WHO_AM_I 0x0F +#define WHO_I_AM 0xD4 +#define ADDR_CTRL_REG1 0x20 +#define ADDR_CTRL_REG2 0x21 +#define ADDR_CTRL_REG3 0x22 +#define ADDR_CTRL_REG4 0x23 +#define ADDR_CTRL_REG5 0x24 +#define ADDR_REFERENCE 0x25 +#define ADDR_OUT_TEMP 0x26 +#define ADDR_STATUS_REG 0x27 +#define ADDR_OUT_X_L 0x28 +#define ADDR_OUT_X_H 0x29 +#define ADDR_OUT_Y_L 0x2A +#define ADDR_OUT_Y_H 0x2B +#define ADDR_OUT_Z_L 0x2C +#define ADDR_OUT_Z_H 0x2D +#define ADDR_FIFO_CTRL_REG 0x2E +#define ADDR_FIFO_SRC_REG 0x2F +#define ADDR_INT1_CFG 0x30 +#define ADDR_INT1_SRC 0x31 +#define ADDR_INT1_TSH_XH 0x32 +#define ADDR_INT1_TSH_XL 0x33 +#define ADDR_INT1_TSH_YH 0x34 +#define ADDR_INT1_TSH_YL 0x35 +#define ADDR_INT1_TSH_ZH 0x36 +#define ADDR_INT1_TSH_ZL 0x37 +#define ADDR_INT1_DURATION 0x38 + +#define REG1_RATE_LP_MASK 0xF0 /* Mask to guard partial register update */ +#define REG4_RANGE_MASK 0x30 /* Mask to guard partial register update */ + +/* Internal configuration values */ +#define REG1_POWER_NORMAL (1<<3) +#define REG1_Z_ENABLE (1<<2) +#define REG1_Y_ENABLE (1<<1) +#define REG1_X_ENABLE (1<<0) + +#define REG4_BDU (1<<7) +#define REG4_BLE (1<<6) +//#define REG4_SPI_3WIRE (1<<0) + +#define REG5_FIFO_ENABLE (1<<6) +#define REG5_REBOOT_MEMORY (1<<7) + +#define STATUS_ZYXOR (1<<7) +#define STATUS_ZOR (1<<6) +#define STATUS_YOR (1<<5) +#define STATUS_XOR (1<<4) +#define STATUS_ZYXDA (1<<3) +#define STATUS_ZDA (1<<2) +#define STATUS_YDA (1<<1) +#define STATUS_XDA (1<<0) + +#define FIFO_CTRL_BYPASS_MODE (0<<5) +#define FIFO_CTRL_FIFO_MODE (1<<5) +#define FIFO_CTRL_STREAM_MODE (1<<6) +#define FIFO_CTRL_STREAM_TO_FIFO_MODE (3<<5) +#define FIFO_CTRL_BYPASS_TO_STREAM_MODE (1<<7) + +static FAR struct l3gd20_dev_s l3gd20_dev; + +static ssize_t l3gd20_read(struct file *filp, FAR char *buffer, size_t buflen); +static int l3gd20_ioctl(struct file *filp, int cmd, unsigned long arg); + +static const struct file_operations l3gd20_fops = { + .open = 0, + .close = 0, + .read = l3gd20_read, + .write = 0, + .seek = 0, + .ioctl = l3gd20_ioctl, +#ifndef CONFIG_DISABLE_POLL + .poll = 0 +#endif +}; + +struct l3gd20_dev_s +{ + struct spi_dev_s *spi; + int spi_id; + uint8_t rate; + struct l3gd20_buffer *buffer; +}; + +static void l3gd20_write_reg(uint8_t address, uint8_t data); +static uint8_t l3gd20_read_reg(uint8_t address); + +static void +l3gd20_write_reg(uint8_t address, uint8_t data) +{ + uint8_t cmd[2] = { address | DIR_WRITE, data }; + + SPI_SELECT(l3gd20_dev.spi, l3gd20_dev.spi_id, true); + SPI_SNDBLOCK(l3gd20_dev.spi, &cmd, sizeof(cmd)); + SPI_SELECT(l3gd20_dev.spi, l3gd20_dev.spi_id, false); +} + +static uint8_t +l3gd20_read_reg(uint8_t address) +{ + uint8_t cmd[2] = {address | DIR_READ, 0}; + uint8_t data[2]; + + SPI_SELECT(l3gd20_dev.spi, l3gd20_dev.spi_id, true); + SPI_EXCHANGE(l3gd20_dev.spi, cmd, data, sizeof(cmd)); + SPI_SELECT(l3gd20_dev.spi, l3gd20_dev.spi_id, false); + + return data[1]; +} + +static int +set_range(uint8_t range) +{ + /* mask out illegal bit positions */ + uint8_t write_range = range & REG4_RANGE_MASK; + /* immediately return if user supplied invalid value */ + if (write_range != range) return EINVAL; + /* set remaining bits to a sane value */ + write_range |= REG4_BDU; + /* write to device */ + l3gd20_write_reg(ADDR_CTRL_REG4, write_range); + /* return 0 if register value is now written value, 1 if unchanged */ + return !(l3gd20_read_reg(ADDR_CTRL_REG4) == write_range); +} + +static int +set_rate(uint8_t rate) +{ + /* mask out illegal bit positions */ + uint8_t write_rate = rate & REG1_RATE_LP_MASK; + /* immediately return if user supplied invalid value */ + if (write_rate != rate) return EINVAL; + /* set remaining bits to a sane value */ + write_rate |= REG1_POWER_NORMAL | REG1_Z_ENABLE | REG1_Y_ENABLE | REG1_X_ENABLE; + /* write to device */ + l3gd20_write_reg(ADDR_CTRL_REG1, write_rate); + /* return 0 if register value is now written value, 1 if unchanged */ + return !(l3gd20_read_reg(ADDR_CTRL_REG1) == write_rate); +} + +static int +read_fifo(int16_t *data) +{ + + struct { /* status register and data as read back from the device */ + uint8_t cmd; + uint8_t temp; + uint8_t status; + int16_t x; + int16_t y; + int16_t z; + } __attribute__((packed)) report = {.status = 11}; + + report.cmd = 0x26 | DIR_READ | ADDR_INCREMENT; + + SPI_LOCK(l3gd20_dev.spi, true); + SPI_SELECT(l3gd20_dev.spi, PX4_SPIDEV_GYRO, true); + SPI_SETFREQUENCY(l3gd20_dev.spi, 25000000); + + SPI_EXCHANGE(l3gd20_dev.spi, &report, &report, sizeof(report)); + + /* XXX if the status value is unchanged, attempt a second exchange */ + if (report.status == 11) SPI_EXCHANGE(l3gd20_dev.spi, &report, &report, sizeof(report)); + /* XXX set magic error value if this still didn't succeed */ + if (report.status == 11) report.status = 12; + + SPI_SETFREQUENCY(l3gd20_dev.spi, 10000000); + SPI_SELECT(l3gd20_dev.spi, PX4_SPIDEV_GYRO, false); + SPI_LOCK(l3gd20_dev.spi, false); + + data[0] = report.x; + data[1] = report.y; + data[2] = report.z; + + /* if all axes are valid, return buflen (6), else return negative status */ + int ret = -((int)report.status); + if (STATUS_ZYXDA == (report.status & STATUS_ZYXDA) || STATUS_ZYXOR == (report.status & STATUS_ZYXOR)) + { + ret = 6; + } + + return ret; +} + +static ssize_t +l3gd20_read(struct file *filp, char *buffer, size_t buflen) +{ + /* if the buffer is large enough, and data are available, return success */ + if (buflen >= 6) { + /* return buflen or a negative value */ + int ret = read_fifo((int16_t *)buffer); + if (ret != 6) *get_errno_ptr() = EAGAIN; + return ret; + } + + /* buffer too small */ + *get_errno_ptr() = ENOSPC; + return ERROR; +} + +static int +l3gd20_ioctl(struct file *filp, int cmd, unsigned long arg) +{ + int result = ERROR; + + switch (cmd) { + case L3GD20_SETRATE: + if ((arg & REG1_RATE_LP_MASK) == arg) { + SPI_LOCK(l3gd20_dev.spi, true); + set_rate(arg); + SPI_LOCK(l3gd20_dev.spi, false); + result = 0; + l3gd20_dev.rate = arg; + } + break; + + case L3GD20_SETRANGE: + if ((arg & REG4_RANGE_MASK) == arg) { + SPI_LOCK(l3gd20_dev.spi, true); + set_range(arg); + SPI_LOCK(l3gd20_dev.spi, false); + result = 0; + } + break; + + case L3GD20_SETBUFFER: + l3gd20_dev.buffer = (struct l3gd20_buffer *)arg; + result = 0; + break; + } + + if (result) + errno = EINVAL; + return result; +} + +int +l3gd20_attach(struct spi_dev_s *spi, int spi_id) +{ + int result = ERROR; + + l3gd20_dev.spi = spi; + l3gd20_dev.spi_id = spi_id; + + SPI_LOCK(l3gd20_dev.spi, true); + /* read dummy value to void to clear SPI statemachine on sensor */ + (void)l3gd20_read_reg(ADDR_WHO_AM_I); + + /* verify that the device is attached and functioning */ + if (l3gd20_read_reg(ADDR_WHO_AM_I) == WHO_I_AM) { + + /* reset device memory */ + //l3gd20_write_reg(ADDR_CTRL_REG5, REG5_REBOOT_MEMORY); + //up_udelay(1000); + + /* set default configuration */ + l3gd20_write_reg(ADDR_CTRL_REG1, REG1_POWER_NORMAL | REG1_Z_ENABLE | REG1_Y_ENABLE | REG1_X_ENABLE); + l3gd20_write_reg(ADDR_CTRL_REG2, 0); /* disable high-pass filters */ + l3gd20_write_reg(ADDR_CTRL_REG3, 0); /* no interrupts - we don't use them */ + l3gd20_write_reg(ADDR_CTRL_REG4, 0x10); + l3gd20_write_reg(ADDR_CTRL_REG5, 0); + + l3gd20_write_reg(ADDR_CTRL_REG5, REG5_FIFO_ENABLE); /* disable wake-on-interrupt */ + l3gd20_write_reg(ADDR_FIFO_CTRL_REG, FIFO_CTRL_STREAM_MODE); /* Enable FIFO, old data is overwritten */ + + if ((set_range(L3GD20_RANGE_500DPS) != 0) || + (set_rate(L3GD20_RATE_760HZ_LP_100HZ) != 0)) /* takes device out of low-power mode */ + { + errno = EIO; + } else { + /* Read out the first few funky values */ + struct { /* status register and data as read back from the device */ + uint8_t cmd; + uint8_t temp; + uint8_t status; + int16_t x; + int16_t y; + int16_t z; + } __attribute__((packed)) report; + + report.cmd = 0x26 | DIR_READ | ADDR_INCREMENT; + + SPI_SELECT(spi, PX4_SPIDEV_GYRO, true); + SPI_EXCHANGE(spi, &report, &report, sizeof(report)); + SPI_SELECT(spi, PX4_SPIDEV_GYRO, false); + up_udelay(500); + /* And read another set */ + SPI_SELECT(spi, PX4_SPIDEV_GYRO, true); + SPI_EXCHANGE(spi, &report, &report, sizeof(report)); + SPI_SELECT(spi, PX4_SPIDEV_GYRO, false); + + + /* make ourselves available */ + register_driver("/dev/l3gd20", &l3gd20_fops, 0666, NULL); + + result = 0; + } + + } else { + + errno = EIO; + } + + SPI_LOCK(l3gd20_dev.spi, false); + + return result; +} diff --git a/nuttx/configs/px4fmu/src/drv_led.c b/nuttx/configs/px4fmu/src/drv_led.c new file mode 100644 index 0000000000..13d8eb22a4 --- /dev/null +++ b/nuttx/configs/px4fmu/src/drv_led.c @@ -0,0 +1,113 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * led driver for PX4FMU + * + * This is something of an experiment currently (ha, get it?) + */ + +#include + +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "chip.h" +#include "stm32_internal.h" +#include "px4fmu-internal.h" + +#include + +static int px4fmu_led_ioctl(struct file *filep, int cmd, unsigned long arg); +static ssize_t px4fmu_led_pseudoread(struct file *filp, FAR char *buffer, size_t buflen); + +static const struct file_operations px4fmu_led_fops = { + .read = px4fmu_led_pseudoread, + .ioctl = px4fmu_led_ioctl, +}; + +int +px4fmu_led_init(void) +{ + /* register the driver */ + return register_driver("/dev/led", &px4fmu_led_fops, 0666, NULL); +} + +static ssize_t +px4fmu_led_pseudoread(struct file *filp, FAR char *buffer, size_t buflen) +{ + return 0; +} + +static int +px4fmu_led_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + int result = 0; + + switch (cmd) { + + case LED_ON: + switch (arg) { + case 0: + case 1: + up_ledon(arg); + break; + default: + result = -1; + break; + } + break; + + case LED_OFF: + switch (arg) { + case 0: + case 1: + up_ledoff(arg); + break; + default: + result = -1; + break; + } + break; + default: + result = -1; + break; + } + return result; +} + diff --git a/nuttx/configs/px4fmu/src/drv_lis331.c b/nuttx/configs/px4fmu/src/drv_lis331.c new file mode 100644 index 0000000000..fd477b46fb --- /dev/null +++ b/nuttx/configs/px4fmu/src/drv_lis331.c @@ -0,0 +1,272 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * Driver for the ST LIS331 MEMS accelerometer + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "chip.h" +#include "stm32_internal.h" +#include "px4fmu-internal.h" + +#include + +/* + * LIS331 registers + */ + +#define DIR_READ (1<<7) +#define DIR_WRITE (0<<7) +#define ADDR_INCREMENT (1<<6) + +#define ADDR_WHO_AM_I 0x0f +#define WHO_I_AM 0x32 + +#define ADDR_CTRL_REG1 0x20 /* sample rate constants are in the public header */ +#define REG1_POWER_NORMAL (1<<5) +#define REG1_RATE_MASK (3<<3) +#define REG1_Z_ENABLE (1<<2) +#define REG1_Y_ENABLE (1<<1) +#define REG1_X_ENABLE (1<<0) + +#define ADDR_CTRL_REG2 0x21 + +#define ADDR_CTRL_REG3 0x22 + +#define ADDR_CTRL_REG4 0x23 +#define REG4_BDU (1<<7) +#define REG4_BIG_ENDIAN (1<<6) +#define REG4_RANGE_MASK (3<<4) +#define REG4_SPI_3WIRE (1<<0) + +#define ADDR_CTRL_REG5 0x24 + +#define ADDR_HP_FILTER_RESET 0x25 +#define ADDR_REFERENCE 0x26 +#define ADDR_STATUS_REG 0x27 +#define STATUS_ZYXOR (1<<7) +#define STATUS_ZOR (1<<6) +#define STATUS_YOR (1<<5) +#define STATUS_XOR (1<<4) +#define STATUS_ZYXDA (1<<3) +#define STATUS_ZDA (1<<2) +#define STATUS_YDA (1<<1) +#define STATUS_XDA (1<<0) + +#define ADDR_OUT_X 0x28 /* 16 bits */ +#define ADDR_OUT_Y 0x2A /* 16 bits */ +#define ADDR_OUT_Z 0x2C /* 16 bits */ + + +static ssize_t lis331_read(struct file *filp, FAR char *buffer, size_t buflen); +static int lis331_ioctl(struct file *filp, int cmd, unsigned long arg); + +static const struct file_operations lis331_fops = { + .read = lis331_read, + .ioctl = lis331_ioctl, +}; + +struct lis331_dev_s +{ + struct spi_dev_s *spi; + int spi_id; + + uint8_t rate; + struct lis331_buffer *buffer; +}; + +static struct lis331_dev_s lis331_dev; + +static void write_reg(uint8_t address, uint8_t data); +static uint8_t read_reg(uint8_t address); +static bool read_fifo(uint16_t *data); +static void set_range(uint8_t range); +static void set_rate(uint8_t rate); + +static void +write_reg(uint8_t address, uint8_t data) +{ + uint8_t cmd[2] = { address | DIR_WRITE, data }; + + SPI_SELECT(lis331_dev.spi, lis331_dev.spi_id, true); + SPI_SNDBLOCK(lis331_dev.spi, &cmd, sizeof(cmd)); + SPI_SELECT(lis331_dev.spi, lis331_dev.spi_id, false); +} + +static uint8_t +read_reg(uint8_t address) +{ + uint8_t cmd[2] = {address | DIR_READ, 0}; + uint8_t data[2]; + + SPI_SELECT(lis331_dev.spi, lis331_dev.spi_id, true); + SPI_EXCHANGE(lis331_dev.spi, cmd, data, sizeof(cmd)); + SPI_SELECT(lis331_dev.spi, lis331_dev.spi_id, false); + + return data[1]; +} + +static bool +read_fifo(uint16_t *data) +{ + struct { /* status register and data as read back from the device */ + uint8_t cmd; + uint8_t status; + int16_t x; + int16_t y; + int16_t z; + } __attribute__((packed)) report; + + report.cmd = ADDR_STATUS_REG | DIR_READ | ADDR_INCREMENT; + + /* exchange the report structure with the device */ + SPI_LOCK(lis331_dev.spi, true); + SPI_SELECT(lis331_dev.spi, lis331_dev.spi_id, true); + SPI_EXCHANGE(lis331_dev.spi, &report, &report, sizeof(report)); + SPI_SELECT(lis331_dev.spi, lis331_dev.spi_id, false); + SPI_LOCK(lis331_dev.spi, false); + + data[0] = report.x; + data[1] = report.y; + data[2] = report.z; + + return report.status & STATUS_ZYXDA; +} + +static void +set_range(uint8_t range) +{ + range &= REG4_RANGE_MASK; + write_reg(ADDR_CTRL_REG4, range | REG4_BDU); +} + +static void +set_rate(uint8_t rate) +{ + rate &= REG1_RATE_MASK; + write_reg(ADDR_CTRL_REG1, rate | REG1_POWER_NORMAL | REG1_Z_ENABLE | REG1_Y_ENABLE | REG1_X_ENABLE); +} + +static ssize_t +lis331_read(struct file *filp, char *buffer, size_t buflen) +{ + /* if the buffer is large enough, and data are available, return success */ + if (buflen >= 12) { + if (read_fifo((uint16_t *)buffer)) + return 12; + + /* no data */ + return 0; + } + + /* buffer too small */ + errno = ENOSPC; + return ERROR; +} + +static int +lis331_ioctl(struct file *filp, int cmd, unsigned long arg) +{ + int result = ERROR; + + switch (cmd) { + case LIS331_SETRATE: + if ((arg & REG1_RATE_MASK) == arg) { + set_rate(arg); + result = 0; + lis331_dev.rate = arg; + } + break; + + case LIS331_SETRANGE: + if ((arg & REG4_RANGE_MASK) == arg) { + set_range(arg); + result = 0; + } + break; + + case LIS331_SETBUFFER: + lis331_dev.buffer = (struct lis331_buffer *)arg; + result = 0; + break; + } + + if (result) + errno = EINVAL; + return result; +} + +int +lis331_attach(struct spi_dev_s *spi, int spi_id) +{ + int result = ERROR; + + lis331_dev.spi = spi; + + SPI_LOCK(lis331_dev.spi, true); + + /* verify that the device is attached and functioning */ + if (read_reg(ADDR_WHO_AM_I) == WHO_I_AM) { + + /* set default configuration */ + write_reg(ADDR_CTRL_REG2, 0); /* disable interrupt-generating high-pass filters */ + write_reg(ADDR_CTRL_REG3, 0); /* no interrupts - we don't use them */ + write_reg(ADDR_CTRL_REG5, 0); /* disable wake-on-interrupt */ + + set_range(LIS331_RANGE_4G); + set_rate(LIS331_RATE_400Hz); /* takes device out of low-power mode */ + + /* make ourselves available */ + register_driver("/dev/lis331", &lis331_fops, 0666, NULL); + + result = 0; + } else { + errno = EIO; + } + + SPI_LOCK(lis331_dev.spi, false); + + return result; +} + diff --git a/nuttx/configs/px4fmu/src/drv_mpu6000.c b/nuttx/configs/px4fmu/src/drv_mpu6000.c new file mode 100644 index 0000000000..47f6555631 --- /dev/null +++ b/nuttx/configs/px4fmu/src/drv_mpu6000.c @@ -0,0 +1,411 @@ +/* + * Copyright (C) 2012 Lorenz Meier. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of the author or 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. + */ + +/* + * Driver for the ST mpu6000 MEMS gyroscope + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "chip.h" +#include "stm32_internal.h" +#include "px4fmu-internal.h" + +#include + +#define DIR_READ (0x80) +#define DIR_WRITE (0<<7) +#define ADDR_INCREMENT (1<<6) + +#define WHO_I_AM 0xD4 + +// MPU 6000 registers +#define MPUREG_WHOAMI 0x75 // +#define MPUREG_SMPLRT_DIV 0x19 // +#define MPUREG_CONFIG 0x1A // +#define MPUREG_GYRO_CONFIG 0x1B +#define MPUREG_ACCEL_CONFIG 0x1C +#define MPUREG_FIFO_EN 0x23 +#define MPUREG_INT_PIN_CFG 0x37 +#define MPUREG_INT_ENABLE 0x38 +#define MPUREG_INT_STATUS 0x3A +#define MPUREG_ACCEL_XOUT_H 0x3B // +#define MPUREG_ACCEL_XOUT_L 0x3C // +#define MPUREG_ACCEL_YOUT_H 0x3D // +#define MPUREG_ACCEL_YOUT_L 0x3E // +#define MPUREG_ACCEL_ZOUT_H 0x3F // +#define MPUREG_ACCEL_ZOUT_L 0x40 // +#define MPUREG_TEMP_OUT_H 0x41// +#define MPUREG_TEMP_OUT_L 0x42// +#define MPUREG_GYRO_XOUT_H 0x43 // +#define MPUREG_GYRO_XOUT_L 0x44 // +#define MPUREG_GYRO_YOUT_H 0x45 // +#define MPUREG_GYRO_YOUT_L 0x46 // +#define MPUREG_GYRO_ZOUT_H 0x47 // +#define MPUREG_GYRO_ZOUT_L 0x48 // +#define MPUREG_USER_CTRL 0x6A // +#define MPUREG_PWR_MGMT_1 0x6B // +#define MPUREG_PWR_MGMT_2 0x6C // +#define MPUREG_FIFO_COUNTH 0x72 +#define MPUREG_FIFO_COUNTL 0x73 +#define MPUREG_FIFO_R_W 0x74 +#define MPUREG_PRODUCT_ID 0x0C // Product ID Register + + +// Configuration bits MPU 3000 and MPU 6000 (not revised)? +#define BIT_SLEEP 0x40 +#define BIT_H_RESET 0x80 +#define BITS_CLKSEL 0x07 +#define MPU_CLK_SEL_PLLGYROX 0x01 +#define MPU_CLK_SEL_PLLGYROZ 0x03 +#define MPU_EXT_SYNC_GYROX 0x02 +#define BITS_FS_250DPS 0x00 +#define BITS_FS_500DPS 0x08 +#define BITS_FS_1000DPS 0x10 +#define BITS_FS_2000DPS 0x18 +#define BITS_FS_MASK 0x18 +#define BITS_DLPF_CFG_256HZ_NOLPF2 0x00 +#define BITS_DLPF_CFG_188HZ 0x01 +#define BITS_DLPF_CFG_98HZ 0x02 +#define BITS_DLPF_CFG_42HZ 0x03 +#define BITS_DLPF_CFG_20HZ 0x04 +#define BITS_DLPF_CFG_10HZ 0x05 +#define BITS_DLPF_CFG_5HZ 0x06 +#define BITS_DLPF_CFG_2100HZ_NOLPF 0x07 +#define BITS_DLPF_CFG_MASK 0x07 +#define BIT_INT_ANYRD_2CLEAR 0x10 +#define BIT_RAW_RDY_EN 0x01 +#define BIT_I2C_IF_DIS 0x10 +#define BIT_INT_STATUS_DATA 0x01 + // Product ID Description for MPU6000 + // high 4 bits low 4 bits + // Product Name Product Revision +#define MPU6000ES_REV_C4 0x14 // 0001 0100 +#define MPU6000ES_REV_C5 0x15 // 0001 0101 +#define MPU6000ES_REV_D6 0x16 // 0001 0110 +#define MPU6000ES_REV_D7 0x17 // 0001 0111 +#define MPU6000ES_REV_D8 0x18 // 0001 1000 +#define MPU6000_REV_C4 0x54 // 0101 0100 +#define MPU6000_REV_C5 0x55 // 0101 0101 +#define MPU6000_REV_D6 0x56 // 0101 0110 +#define MPU6000_REV_D7 0x57 // 0101 0111 +#define MPU6000_REV_D8 0x58 // 0101 1000 +#define MPU6000_REV_D9 0x59 // 0101 1001 +#define MPU6000_REV_D10 0x5A // 0101 1010 + +static FAR struct mpu6000_dev_s mpu6000_dev; + +static ssize_t mpu6000_read(struct file *filp, FAR char *buffer, size_t buflen); +static int mpu6000_ioctl(struct file *filp, int cmd, unsigned long arg); + +static const struct file_operations mpu6000_fops = { + .open = 0, + .close = 0, + .read = mpu6000_read, + .write = 0, + .seek = 0, + .ioctl = mpu6000_ioctl, +#ifndef CONFIG_DISABLE_POLL + .poll = 0 +#endif +}; + +struct mpu6000_dev_s +{ + struct spi_dev_s *spi; + int spi_id; + uint8_t rate; + struct mpu6000_buffer *buffer; +}; + +static void mpu6000_write_reg(uint8_t address, uint8_t data); +static uint8_t mpu6000_read_reg(uint8_t address); + +static void +mpu6000_write_reg(uint8_t address, uint8_t data) +{ + uint8_t cmd[2] = { address | DIR_WRITE, data }; + + SPI_SELECT(mpu6000_dev.spi, mpu6000_dev.spi_id, true); + SPI_SNDBLOCK(mpu6000_dev.spi, &cmd, sizeof(cmd)); + SPI_SELECT(mpu6000_dev.spi, mpu6000_dev.spi_id, false); +} + +static uint8_t +mpu6000_read_reg(uint8_t address) +{ + uint8_t cmd[2] = {address | DIR_READ, 0}; + uint8_t data[2]; + + SPI_SELECT(mpu6000_dev.spi, mpu6000_dev.spi_id, true); + SPI_EXCHANGE(mpu6000_dev.spi, cmd, data, sizeof(cmd)); + SPI_SELECT(mpu6000_dev.spi, mpu6000_dev.spi_id, false); + + return data[1]; +} + +static int +mpu6000_set_range(uint8_t range) +{ +// /* mask out illegal bit positions */ +// uint8_t write_range = range & REG4_RANGE_MASK; +// /* immediately return if user supplied invalid value */ +// if (write_range != range) return EINVAL; +// /* set remaining bits to a sane value */ +// write_range |= REG4_BDU; +// /* write to device */ +// write_reg(ADDR_CTRL_REG4, write_range); +// /* return 0 if register value is now written value, 1 if unchanged */ +// return !(read_reg(ADDR_CTRL_REG4) == write_range); +} + +static int +mpu6000_set_rate(uint8_t rate) +{ +// /* mask out illegal bit positions */ +// uint8_t write_rate = rate & REG1_RATE_LP_MASK; +// /* immediately return if user supplied invalid value */ +// if (write_rate != rate) return EINVAL; +// /* set remaining bits to a sane value */ +// write_rate |= REG1_POWER_NORMAL | REG1_Z_ENABLE | REG1_Y_ENABLE | REG1_X_ENABLE; +// /* write to device */ +// write_reg(ADDR_CTRL_REG1, write_rate); +// /* return 0 if register value is now written value, 1 if unchanged */ +// return !(read_reg(ADDR_CTRL_REG1) == write_rate); +} + +static int +mpu6000_read_fifo(int16_t *data) +{ +// struct { /* status register and data as read back from the device */ +// uint8_t cmd; +// uint8_t temp; +// uint8_t status; +// int16_t x; +// int16_t y; +// int16_t z; +// } __attribute__((packed)) report; +// +// report.cmd = ADDR_OUT_TEMP | DIR_READ | ADDR_INCREMENT; +// +// /* exchange the report structure with the device */ +// SPI_LOCK(mpu6000_dev.spi, true); +// +// SPI_SELECT(mpu6000_dev.spi, mpu6000_dev.spi_id, true); +// +// read_reg(ADDR_WHO_AM_I); +// +// SPI_EXCHANGE(mpu6000_dev.spi, &report, &report, sizeof(report)); +// SPI_SELECT(mpu6000_dev.spi, mpu6000_dev.spi_id, false); +// +// SPI_LOCK(mpu6000_dev.spi, false); +// +// +// + // + + // Device has MSB first at lower address (big endian) + + + struct { /* status register and data as read back from the device */ + uint8_t cmd; + uint8_t int_status; + int16_t xacc; + int16_t yacc; + int16_t zacc; + int8_t temp; + int16_t rollspeed; + int16_t pitchspeed; + int16_t yawspeed; + } __attribute__((packed)) report; + + report.cmd = 0x26 | DIR_READ | ADDR_INCREMENT; + + SPI_LOCK(mpu6000_dev.spi, true); + SPI_SELECT(mpu6000_dev.spi, PX4_SPIDEV_MPU, true); + SPI_EXCHANGE(mpu6000_dev.spi, &report, &report, sizeof(report)); + SPI_SELECT(mpu6000_dev.spi, PX4_SPIDEV_MPU, false); + SPI_LOCK(mpu6000_dev.spi, false); + + data[0] = report.xacc; + data[1] = report.yacc; + data[2] = report.zacc; + + return (report.int_status & 0x01); +} + +static ssize_t +mpu6000_read(struct file *filp, char *buffer, size_t buflen) +{ + /* if the buffer is large enough, and data are available, return success */ + if (buflen >= 6) { + if (mpu6000_read_fifo((int16_t *)buffer)) + return 6; + + /* no data */ + return 0; + } + + /* buffer too small */ + errno = ENOSPC; + return ERROR; +} + +static int +mpu6000_ioctl(struct file *filp, int cmd, unsigned long arg) +{ + int result = ERROR; + + switch (cmd) { + case MPU6000_SETRATE: + if ((arg & 0x00/* XXX REG MASK MISSING */) == arg) { + SPI_LOCK(mpu6000_dev.spi, true); + mpu6000_set_rate(arg); + SPI_LOCK(mpu6000_dev.spi, false); + result = 0; + mpu6000_dev.rate = arg; + } + break; + + case MPU6000_SETRANGE: + if ((arg & 0x00/* XXX REG MASK MISSING */) == arg) { + SPI_LOCK(mpu6000_dev.spi, true); + mpu6000_set_range(arg); + SPI_LOCK(mpu6000_dev.spi, false); + result = 0; + } + break; + + case MPU6000_SETBUFFER: + mpu6000_dev.buffer = (struct mpu6000_buffer *)arg; + result = 0; + break; + } + + if (result) + errno = EINVAL; + return result; +} + +int +mpu6000_attach(struct spi_dev_s *spi, int spi_id) +{ + int result = ERROR; + + mpu6000_dev.spi = spi; + mpu6000_dev.spi_id = spi_id; + + SPI_LOCK(mpu6000_dev.spi, true); + + // Set sensor-specific SPI mode + SPI_SETFREQUENCY(mpu6000_dev.spi, 10000000); // 500 KHz + SPI_SETBITS(mpu6000_dev.spi, 8); + // Either mode 1 or mode 3 + SPI_SETMODE(mpu6000_dev.spi, SPIDEV_MODE3); + + // Chip reset + mpu6000_write_reg(MPUREG_PWR_MGMT_1, BIT_H_RESET); + up_udelay(10000); + // Wake up device and select GyroZ clock (better performance) + mpu6000_write_reg(MPUREG_PWR_MGMT_1, MPU_CLK_SEL_PLLGYROZ); + up_udelay(1000); + // Disable I2C bus (recommended on datasheet) + mpu6000_write_reg(MPUREG_USER_CTRL, BIT_I2C_IF_DIS); + up_udelay(1000); + // SAMPLE RATE + mpu6000_write_reg(MPUREG_SMPLRT_DIV,0x04); // Sample rate = 200Hz Fsample= 1Khz/(4+1) = 200Hz + usleep(1000); + // FS & DLPF FS=2000¼/s, DLPF = 98Hz (low pass filter) + mpu6000_write_reg(MPUREG_CONFIG, BITS_DLPF_CFG_98HZ); + usleep(1000); + mpu6000_write_reg(MPUREG_GYRO_CONFIG,BITS_FS_2000DPS); // Gyro scale 2000¼/s + usleep(1000); + + uint8_t _product_id = mpu6000_read_reg(MPUREG_PRODUCT_ID); + printf("MPU-6000 product id: %d\n", (int)_product_id); + + if ((_product_id == MPU6000ES_REV_C4) || (_product_id == MPU6000ES_REV_C5) || + (_product_id == MPU6000_REV_C4) || (_product_id == MPU6000_REV_C5)){ + // Accel scale 8g (4096 LSB/g) + // Rev C has different scaling than rev D + mpu6000_write_reg(MPUREG_ACCEL_CONFIG,1<<3); + } else { + // Accel scale 8g (4096 LSB/g) + mpu6000_write_reg(MPUREG_ACCEL_CONFIG,2<<3); + } + usleep(1000); + + // INT CFG => Interrupt on Data Ready + mpu6000_write_reg(MPUREG_INT_ENABLE,BIT_RAW_RDY_EN); // INT: Raw data ready + usleep(1000); + mpu6000_write_reg(MPUREG_INT_PIN_CFG,BIT_INT_ANYRD_2CLEAR); // INT: Clear on any read + usleep(1000); + // Oscillator set + // write_reg(MPUREG_PWR_MGMT_1,MPU_CLK_SEL_PLLGYROZ); + usleep(1000); + + /* revert back to normal bus mode */ + SPI_SETFREQUENCY(mpu6000_dev.spi, 10000000); + SPI_SETBITS(mpu6000_dev.spi, 8); + SPI_SETMODE(mpu6000_dev.spi, SPIDEV_MODE3); + + /* verify that the device is attached and functioning */ + if ((_product_id == MPU6000ES_REV_C4) || (_product_id == MPU6000ES_REV_C5) || + (_product_id == MPU6000_REV_C4) || (_product_id == MPU6000_REV_C5) || + (_product_id == MPU6000_REV_D7) || (_product_id == MPU6000_REV_D8) || + (_product_id == MPU6000_REV_D9) || (_product_id == MPU6000_REV_D10)){ + + /* make ourselves available */ + register_driver("/dev/mpu6000", &mpu6000_fops, 0666, NULL); + + result = OK; + } else { + + errno = EIO; + } + + SPI_LOCK(mpu6000_dev.spi, false); + + SPI_LOCK(mpu6000_dev.spi, false); + + return result; +} diff --git a/nuttx/configs/px4fmu/src/drv_ms5611.c b/nuttx/configs/px4fmu/src/drv_ms5611.c new file mode 100644 index 0000000000..7fea651595 --- /dev/null +++ b/nuttx/configs/px4fmu/src/drv_ms5611.c @@ -0,0 +1,493 @@ +/* + * Copyright (C) 2012 Lorenz Meier. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of the author or 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. + */ + +/* + * Driver for the Measurement Specialties MS5611 barometric pressure sensor + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" +#include "px4fmu-internal.h" + +#include +#include + +/* internal conversion time: 9.17 ms, so should not be read at rates higher than 100 Hz */ +#define MS5611_MIN_INTER_MEASUREMENT_INTERVAL 9200 + +#define MS5611_ADDRESS_1 0x76 /* address select pins pulled high (PX4FMU series v1.6+) */ +#define MS5611_ADDRESS_2 0x77 /* address select pins pulled low (PX4FMU prototypes) */ + +#define ADDR_RESET_CMD 0x1E /* read from this address to reset chip (0b0011110 on bus) */ +#define ADDR_CMD_CONVERT_D1 0x48 /* 4096 samples to this address to start conversion (0b01001000 on bus) */ +#define ADDR_CMD_CONVERT_D2 0x58 /* 4096 samples */ +#define ADDR_DATA 0x00 /* address of 3 bytes / 32bit pressure data */ +#define ADDR_PROM_SETUP 0xA0 /* address of 8x 2 bytes factory and calibration data */ +#define ADDR_PROM_C1 0xA2 /* address of 6x 2 bytes calibration data */ + +static FAR struct ms5611_dev_s ms5611_dev; + +static ssize_t ms5611_read(struct file *filp, FAR char *buffer, size_t buflen); +static int ms5611_ioctl(struct file *filp, int cmd, unsigned long arg); + +static const struct file_operations ms5611_fops = { + .read = ms5611_read, + .ioctl = ms5611_ioctl, +}; + +struct ms5611_prom_s +{ + uint16_t factory_setup; + uint16_t c1_pressure_sens; + uint16_t c2_pressure_offset; + uint16_t c3_temp_coeff_pres_sens; + uint16_t c4_temp_coeff_pres_offset; + uint16_t c5_reference_temp; + uint16_t c6_temp_coeff_temp; + uint16_t serial_and_crc; +} __attribute__((packed)); + +union ms5611_prom_u +{ + uint16_t c[8]; + struct ms5611_prom_s s; +} __attribute__((packed)); + +struct ms5611_dev_s +{ + union ms5611_prom_u prom; + struct i2c_dev_s *i2c; + struct ms5611_buffer *buffer; +} __attribute__((packed)); + +static FAR uint8_t MS5611_ADDRESS; + +static FAR struct { + /* status register and data as read back from the device */ + float pressure; + float altitude; + float temperature; + uint32_t d1_raw; + uint32_t d2_raw; + uint32_t measurements_count; + uint8_t last_state; + uint64_t last_read; + } ms5611_report = { + .pressure = 0.0f, + .altitude = 0.0f, + .temperature = 0.0f, + .last_state = 0, + /* make sure the first readout can be performed */ + .last_read = 0, +}; + +static int ms5611_read_prom(void); + +static bool +read_values(float *data) +{ + int ret; + uint8_t cmd_data[3]; + + /* check validity of pointer */ + if (data == NULL) + { + *get_errno_ptr() = EINVAL; + return -EINVAL; + } + + /* only start reading when data is available */ + if (ms5611_report.measurements_count > 0) + { + /* do not read more often than at minimum 9.17 ms intervals */ + if ((hrt_absolute_time() - ms5611_report.last_read) < MS5611_MIN_INTER_MEASUREMENT_INTERVAL) + { + /* set errno to 'come back later' */ + ret = -EAGAIN; + goto handle_return; + } + else + { + /* set new value */ + ms5611_report.last_read = hrt_absolute_time(); + } + + /* Read out last measurement */ + cmd_data[0] = 0x00; + + struct i2c_msg_s msgv[2] = { + { + .addr = MS5611_ADDRESS, + .flags = 0, + .buffer = cmd_data, + .length = 1 + }, + { + .addr = MS5611_ADDRESS, + .flags = I2C_M_READ, + .buffer = cmd_data, + .length = 3 + } + }; + ret = I2C_TRANSFER(ms5611_dev.i2c, msgv, 2); + if (ret != OK) goto handle_return; + + + /* at value 1 the last reading was temperature */ + if (ms5611_report.last_state == 1) + { + /* put temperature into the raw set */ + ms5611_report.d2_raw = (((uint32_t)cmd_data[0]) << 16) | (((uint32_t)cmd_data[1]) << 8) | ((uint32_t)cmd_data[2]); + } + else + { + /* put altitude into the raw set */ + ms5611_report.d1_raw = (((uint32_t)cmd_data[0]) << 16) | (((uint32_t)cmd_data[1]) << 8) | ((uint32_t)cmd_data[2]); + } + } + ms5611_report.measurements_count++; + + /* + * this block reads four pressure values and one temp value, + * resulting in 80 Hz pressure update and 20 Hz temperature updates + * at 100 Hz continuous operation. + */ + if (ms5611_report.last_state == 0) + { + /* request first a temperature reading */ + cmd_data[0] = ADDR_CMD_CONVERT_D2; + } + else + { + /* request pressure reading */ + cmd_data[0] = ADDR_CMD_CONVERT_D1; + } + + if (ms5611_report.last_state == 3) + { + ms5611_report.last_state = 0; + } + else + { + ms5611_report.last_state++; + } + + + /* write measurement command */ + struct i2c_msg_s conv_cmd[1] = { + { + .addr = MS5611_ADDRESS, + .flags = 0, + .buffer = cmd_data, + .length = 1 + }, + }; + + ret = I2C_TRANSFER(ms5611_dev.i2c, conv_cmd, 1); + if (ret != OK) goto handle_return; + + /* only write back values after first complete set */ + if (ms5611_report.measurements_count > 2) + { + /* Calculate results */ + + /* temperature calculation */ + int32_t dT = ms5611_report.d2_raw - (((int32_t)ms5611_dev.prom.s.c5_reference_temp)*256); + int64_t temp_int64 = 2000 + (((int64_t)dT)*ms5611_dev.prom.s.c6_temp_coeff_temp)/8388608; + + /* pressure calculation */ + int64_t offset = (int64_t)ms5611_dev.prom.s.c2_pressure_offset * 65536 + ((int64_t)dT*ms5611_dev.prom.s.c4_temp_coeff_pres_offset)/128; + int64_t sens = (int64_t)ms5611_dev.prom.s.c1_pressure_sens * 32768 + ((int64_t)dT*ms5611_dev.prom.s.c3_temp_coeff_pres_sens)/256; + + /* it's pretty cold, second order temperature compensation needed */ + if (temp_int64 < 2000) + { + /* second order temperature compensation */ + int64_t temp2 = (((int64_t)dT)*dT) >> 31; + int64_t tmp_64 = (temp_int64-2000)*(temp_int64-2000); + int64_t offset2 = (5*tmp_64)>>1; + int64_t sens2 = (5*tmp_64)>>2; + temp_int64 = temp_int64 - temp2; + offset = offset - offset2; + sens = sens - sens2; + } + + int64_t press_int64 = (((ms5611_report.d1_raw*sens)/2097152-offset)/32768); + + ms5611_report.temperature = temp_int64 / 100.0f; + ms5611_report.pressure = press_int64 / 100.0f; + /* convert as double for max. precision, store as float (more than enough precision) */ + ms5611_report.altitude = (44330.0 * (1.0 - pow((press_int64 / 101325.0), 0.190295))); + + /* Write back float values */ + data[0] = ms5611_report.pressure; + data[1] = ms5611_report.altitude; + data[2] = ms5611_report.temperature; + } + else + { + /* not ready, try again */ + ret = -EINPROGRESS; + } + + /* return 1 if new data is available, 0 else */ + handle_return: + if (ret == OK) + { + return (sizeof(ms5611_report.d1_raw) + sizeof(ms5611_report.altitude) + sizeof(ms5611_report.d2_raw)); + } + else + { + errno = -ret; + return ret; + } +} + +static ssize_t +ms5611_read(struct file *filp, char *buffer, size_t buflen) +{ + /* if the buffer is large enough, and data are available, return success */ + if (buflen >= 12) { + return read_values((float *)buffer); + } + + /* buffer too small */ + errno = ENOSPC; + return -ENOSPC; +} + +static int +ms5611_ioctl(struct file *filp, int cmd, unsigned long arg) +{ + return -ENOSYS; + +// switch (cmd) { +// case MS5611_SETRATE: +// if ((arg & REG1_RATE_LP_MASK) == arg) { +// set_rate(arg); +// result = 0; +// dev.rate = arg; +// } +// break; +// +// case MS5611_SETBUFFER: +// dev.buffer = (struct ms5611_buffer *)arg; +// result = 0; +// break; +// } +// +// if (result) +// errno = EINVAL; +// return result; +} + + + +int ms5611_crc4(uint16_t n_prom[]) +{ + /* routine ported from MS5611 application note */ + int16_t cnt; + uint16_t n_rem; + uint16_t crc_read; + uint8_t n_bit; + n_rem = 0x00; + /* save the read crc */ + crc_read = n_prom[7]; + /* remove CRC byte */ + n_prom[7] = (0xFF00 & (n_prom[7])); + for (cnt = 0; cnt < 16; cnt++) + { + /* uneven bytes */ + if (cnt & 1) + { + n_rem ^= (uint8_t) ((n_prom[cnt>>1]) & 0x00FF); + } + else + { + n_rem ^= (uint8_t) (n_prom[cnt>>1] >> 8); + } + for (n_bit = 8; n_bit > 0; n_bit--) + { + if (n_rem & 0x8000) + { + n_rem = (n_rem << 1) ^ 0x3000; + + } + else + { + n_rem = (n_rem << 1); + } + } + } + /* final 4 bit remainder is CRC value */ + n_rem = (0x000F & (n_rem >> 12)); + n_prom[7] = crc_read; + + /* return 0 == OK if CRCs match, 1 else */ + return !((0x000F & crc_read) == (n_rem ^ 0x00)); +} + + +int ms5611_read_prom() +{ + /* read PROM data */ + uint8_t prom_buf[2] = {255,255}; + + int retval = 0; + + for (int i = 0; i < 8; i++) + { + uint8_t cmd = {ADDR_PROM_SETUP + (i*2)}; + + I2C_SETADDRESS(ms5611_dev.i2c, MS5611_ADDRESS, 7); + retval = I2C_WRITEREAD(ms5611_dev.i2c, &cmd, 1, prom_buf, 2); + + /* assemble 16 bit value and convert from big endian (sensor) to little endian (MCU) */ + ms5611_dev.prom.c[i] = (((uint16_t)prom_buf[0])<<8) | ((uint16_t)prom_buf[1]); + + if (retval != OK) + { + break; + } + } + + /* calculate CRC and return error if mismatch */ + return ms5611_crc4(ms5611_dev.prom.c); +} + +int +ms5611_attach(struct i2c_dev_s *i2c) +{ + int result = ERROR; + + ms5611_dev.i2c = i2c; + + MS5611_ADDRESS = MS5611_ADDRESS_1; + + /* write reset command */ + uint8_t cmd_data = ADDR_RESET_CMD; + + struct i2c_msg_s reset_cmd[1] = { + { + .addr = MS5611_ADDRESS, + .flags = 0, + .buffer = &cmd_data, + .length = 1 + }, + }; + + int ret = I2C_TRANSFER(ms5611_dev.i2c, reset_cmd, 1); + + if (ret == OK) + { + /* wait for PROM contents to be in the device (2.8 ms) */ + up_udelay(3000); + + /* read PROM */ + ret = ms5611_read_prom(); + } + + /* check if the address was wrong */ + if (ret != OK) + { + /* try second address */ + MS5611_ADDRESS = MS5611_ADDRESS_2; + + /* write reset command */ + cmd_data = ADDR_RESET_CMD; + + struct i2c_msg_s reset_cmd_2[1] = { + { + .addr = MS5611_ADDRESS, + .flags = 0, + .buffer = &cmd_data, + .length = 1 + }, + }; + + ret = I2C_TRANSFER(ms5611_dev.i2c, reset_cmd_2, 1); + + /* wait for PROM contents to be in the device (2.8 ms) */ + up_udelay(3000); + + /* read PROM */ + ret = ms5611_read_prom(); + } + + if (ret < 0) return -EIO; + + + /* verify that the device is attached and functioning */ + if (ret == OK) { + + if (MS5611_ADDRESS == MS5611_ADDRESS_1) + { + printf("[ms5611 driver] Attached MS5611 at addr #1 (0x76)\n"); + } + else + { + printf("[ms5611 driver] Attached MS5611 at addr #2 (0x77)\n"); + } + + /* trigger temperature read */ + (void)read_values(NULL); + /* wait for conversion to complete */ + up_udelay(9200); + + /* trigger pressure read */ + (void)read_values(NULL); + /* wait for conversion to complete */ + up_udelay(9200); + /* now a read_values call would obtain valid results */ + + /* make ourselves available */ + register_driver("/dev/ms5611", &ms5611_fops, 0666, NULL); + + result = OK; + + } else { + errno = EIO; + } + + return result; +} diff --git a/nuttx/configs/px4fmu/src/drv_tone_alarm.c b/nuttx/configs/px4fmu/src/drv_tone_alarm.c new file mode 100644 index 0000000000..958a189047 --- /dev/null +++ b/nuttx/configs/px4fmu/src/drv_tone_alarm.c @@ -0,0 +1,511 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * Speaker driver supporting alarm sequences. + * + * Works with any of the 'generic' STM32 timers that has an output + * pin, does not require an interrupt. + * + * Depends on the HRT timer. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "chip.h" +#include "up_internal.h" +#include "up_arch.h" + +#include "stm32_internal.h" +#include "stm32_gpio.h" +#include "stm32_tim.h" + +#ifdef CONFIG_TONE_ALARM +# ifndef CONFIG_HRT_TIMER +# error CONFIG_TONE_ALARM requires CONFIG_HRT_TIMER +# endif + +/* Tone alarm configuration */ +#if TONE_ALARM_TIMER == 2 +# define TONE_ALARM_BASE STM32_TIM2_BASE +# define TONE_ALARM_CLOCK STM32_APB1_TIM2_CLKIN +# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM2EN +# ifdef CONFIG_STM32_TIM2 +# error Must not set CONFIG_STM32_TIM2 when TONE_ALARM_TIMER is 2 +# endif +#elif TONE_ALARM_TIMER == 3 +# define TONE_ALARM_BASE STM32_TIM3_BASE +# define TONE_ALARM_CLOCK STM32_APB1_TIM3_CLKIN +# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM3EN +# ifdef CONFIG_STM32_TIM3 +# error Must not set CONFIG_STM32_TIM3 when TONE_ALARM_TIMER is 3 +# endif +#elif TONE_ALARM_TIMER == 4 +# define TONE_ALARM_BASE STM32_TIM4_BASE +# define TONE_ALARM_CLOCK STM32_APB1_TIM4_CLKIN +# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM4EN +# ifdef CONFIG_STM32_TIM4 +# error Must not set CONFIG_STM32_TIM4 when TONE_ALARM_TIMER is 4 +# endif +#elif TONE_ALARM_TIMER == 5 +# define TONE_ALARM_BASE STM32_TIM5_BASE +# define TONE_ALARM_CLOCK STM32_APB1_TIM5_CLKIN +# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM5EN +# ifdef CONFIG_STM32_TIM5 +# error Must not set CONFIG_STM32_TIM5 when TONE_ALARM_TIMER is 5 +# endif +#elif TONE_ALARM_TIMER == 9 +# define TONE_ALARM_BASE STM32_TIM9_BASE +# define TONE_ALARM_CLOCK STM32_APB1_TIM9_CLKIN +# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM9EN +# ifdef CONFIG_STM32_TIM9 +# error Must not set CONFIG_STM32_TIM9 when TONE_ALARM_TIMER is 9 +# endif +#elif TONE_ALARM_TIMER == 10 +# define TONE_ALARM_BASE STM32_TIM10_BASE +# define TONE_ALARM_CLOCK STM32_APB1_TIM10_CLKIN +# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM10EN +# ifdef CONFIG_STM32_TIM10 +# error Must not set CONFIG_STM32_TIM10 when TONE_ALARM_TIMER is 10 +# endif +#elif TONE_ALARM_TIMER == 11 +# define TONE_ALARM_BASE STM32_TIM11_BASE +# define TONE_ALARM_CLOCK STM32_APB1_TIM11_CLKIN +# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM11EN +# ifdef CONFIG_STM32_TIM11 +# error Must not set CONFIG_STM32_TIM11 when TONE_ALARM_TIMER is 11 +# endif +#else +# error Must set TONE_ALARM_TIMER to a generic timer if CONFIG_TONE_ALARM is set +#endif + +#if TONE_ALARM_CHANNEL == 1 +# define TONE_CCMR1 (3 << 4) +# define TONE_CCMR2 0 +# define TONE_CCER (1 << 0) +# define TONE_rCCR rCCR1 +#elif TONE_ALARM_CHANNEL == 2 +# define TONE_CCMR1 (3 << 12) +# define TONE_CCMR2 0 +# define TONE_CCER (1 << 4) +# define TONE_rCCR rCCR2 +#elif TONE_ALARM_CHANNEL == 3 +# define TONE_CCMR1 0 +# define TONE_CCMR2 (3 << 4) +# define TONE_CCER (1 << 8) +# define TONE_rCCR rCCR3 +#elif TONE_ALARM_CHANNEL == 4 +# define TONE_CCMR1 0 +# define TONE_CCMR2 (3 << 12) +# define TONE_CCER (1 << 12) +# define TONE_rCCR rCCR4 +#else +# error Must set TONE_ALARM_CHANNEL to a value between 1 and 4 +#endif + +/* + * Timer register accessors + */ +#define REG(_reg) (*(volatile uint32_t *)(TONE_ALARM_BASE + _reg)) + +#define rCR1 REG(STM32_GTIM_CR1_OFFSET) +#define rCR2 REG(STM32_GTIM_CR2_OFFSET) +#define rSMCR REG(STM32_GTIM_SMCR_OFFSET) +#define rDIER REG(STM32_GTIM_DIER_OFFSET) +#define rSR REG(STM32_GTIM_SR_OFFSET) +#define rEGR REG(STM32_GTIM_EGR_OFFSET) +#define rCCMR1 REG(STM32_GTIM_CCMR1_OFFSET) +#define rCCMR2 REG(STM32_GTIM_CCMR2_OFFSET) +#define rCCER REG(STM32_GTIM_CCER_OFFSET) +#define rCNT REG(STM32_GTIM_CNT_OFFSET) +#define rPSC REG(STM32_GTIM_PSC_OFFSET) +#define rARR REG(STM32_GTIM_ARR_OFFSET) +#define rCCR1 REG(STM32_GTIM_CCR1_OFFSET) +#define rCCR2 REG(STM32_GTIM_CCR2_OFFSET) +#define rCCR3 REG(STM32_GTIM_CCR3_OFFSET) +#define rCCR4 REG(STM32_GTIM_CCR4_OFFSET) +#define rDCR REG(STM32_GTIM_DCR_OFFSET) +#define rDMAR REG(STM32_GTIM_DMAR_OFFSET) + +#define TONE_MAX_PATTERN 6 +#define TONE_MAX_PATTERN_LEN 40 + +/* predefined patterns for alarms 1-TONE_MAX_PATTERN */ +const struct tone_note patterns[TONE_MAX_PATTERN][TONE_MAX_PATTERN_LEN] = { + { + {TONE_NOTE_A7, 12}, + {TONE_NOTE_D8, 12}, + {TONE_NOTE_C8, 12}, + {TONE_NOTE_A7, 12}, + {TONE_NOTE_D8, 12}, + {TONE_NOTE_C8, 12}, + {TONE_NOTE_D8, 4}, + {TONE_NOTE_C8, 4}, + {TONE_NOTE_D8, 4}, + {TONE_NOTE_C8, 4}, + {TONE_NOTE_D8, 4}, + {TONE_NOTE_C8, 4}, + }, + {{TONE_NOTE_B6, 100}}, + {{TONE_NOTE_C7, 100}}, + {{TONE_NOTE_D7, 100}}, + {{TONE_NOTE_E7, 100}}, + { //This is tetris ;) + {TONE_NOTE_C6, 40}, + {TONE_NOTE_G5, 20}, + {TONE_NOTE_G5S, 20}, + {TONE_NOTE_A5S, 40}, + {TONE_NOTE_G5S, 20}, + {TONE_NOTE_G5, 20}, + {TONE_NOTE_F5, 40}, + {TONE_NOTE_F5, 20}, + {TONE_NOTE_G5S, 20}, + {TONE_NOTE_C6, 40}, + {TONE_NOTE_A5S, 20}, + {TONE_NOTE_G5S, 20}, + {TONE_NOTE_G5, 60}, + {TONE_NOTE_G5S, 20}, + {TONE_NOTE_A5S, 40}, + {TONE_NOTE_C6, 40}, + {TONE_NOTE_G5S, 40}, + {TONE_NOTE_F5, 40}, + {TONE_NOTE_F5, 60}, + + {TONE_NOTE_A5S, 40}, + {TONE_NOTE_C6S, 20}, + {TONE_NOTE_F6, 40}, + {TONE_NOTE_D6S, 20}, + {TONE_NOTE_C6S, 20}, + {TONE_NOTE_C6, 60}, + {TONE_NOTE_G5S, 20}, + {TONE_NOTE_C6, 40}, + {TONE_NOTE_A5S, 20}, + {TONE_NOTE_G5S, 20}, + {TONE_NOTE_G5, 40}, + {TONE_NOTE_G5, 20}, + {TONE_NOTE_G5S, 20}, + {TONE_NOTE_A5S, 40}, + {TONE_NOTE_C6, 40}, + {TONE_NOTE_G5S, 40}, + {TONE_NOTE_F5, 40}, + {TONE_NOTE_F5, 60}, + } +}; + +static uint16_t notes[TONE_NOTE_MAX] = { + 63707, /* E4 */ + 60132, /* F4 */ + 56758, /* F#4/Gb4 */ + 53571, /* G4 */ + 50565, /* G#4/Ab4 */ + 47727, /* A4 */ + 45048, /* A#4/Bb4 */ + 42520, /* B4 */ + 40133, /* C5 */ + 37880, /* C#5/Db5 */ + 35755, /* D5 */ + 33748, /* D#5/Eb5 */ + 31853, /* E5 */ + 30066, /* F5 */ + 28378, /* F#5/Gb5 */ + 26786, /* G5 */ + 25282, /* G#5/Ab5 */ + 23863, /* A5 */ + 22524, /* A#5/Bb5 */ + 21260, /* B5 */ + 20066, /* C6 */ + 18940, /* C#6/Db6 */ + 17877, /* D6 */ + 16874, /* D#6/Eb6 */ + 15927, /* E6 */ + 15033, /* F6 */ + 14189, /* F#6/Gb6 */ + 13393, /* G6 */ + 12641, /* G#6/Ab6 */ + 11931, /* A6 */ + 11262, /* A#6/Bb6 */ + 10630, /* B6 */ + 10033, /* C7 */ + 9470, /* C#7/Db7 */ + 8938, /* D7 */ + 8437, /* D#7/Eb7 */ + 7963, /* E7 */ + 7516, /* F7 */ + 7094, /* F#7/Gb7 */ + 6696, /* G7 */ + 6320, /* G#7/Ab7 */ + 5965, /* A7 */ + 5631, /* A#7/Bb7 */ + 5315, /* B7 */ + 5016, /* C8 */ + 4735, /* C#8/Db8 */ + 4469, /* D8 */ + 4218 /* D#8/Eb8 */ +}; + +/* current state of the tone driver */ +struct state { + int pattern; /* current pattern */ +#define PATTERN_NONE -1 +#define PATTERN_USER 0 + int note; /* next note to play */ + struct hrt_call note_end; + struct tone_note user_pattern[TONE_MAX_PATTERN_LEN]; /* user-supplied pattern (plays at pattern 0) */ +}; + +static struct state tone_state; + +static int tone_write(struct file *filp, const char *buffer, size_t len); +static int tone_ioctl(struct file *filep, int cmd, unsigned long arg); + +static const struct file_operations tone_fops = { + .write = tone_write, + .ioctl = tone_ioctl +}; + +static void tone_next(void); +static bool tone_ok(struct tone_note *pattern); +int +tone_alarm_init(void) +{ + /* configure the GPIO */ + stm32_configgpio(GPIO_TONE_ALARM); + + /* clock/power on our timer */ + modifyreg32(STM32_RCC_APB1ENR, 0, TONE_ALARM_CLOCK_ENABLE); + + /* default the state */ + tone_state.pattern = -1; + + /* initialise the timer */ + rCR1 = 0; + rCR2 = 0; + rSMCR = 0; + rDIER = 0; + rCCER = 0; /* unlock CCMR* registers */ + rCCMR1 = TONE_CCMR1; + rCCMR2 = TONE_CCMR2; + rCCER = TONE_CCER; + rDCR = 0; + + /* toggle the CC output each time the count passes 1 */ + TONE_rCCR = 1; + + /* + * Configure the timebase to free-run at half max frequency. + * XXX this should be more flexible in order to get a better + * frequency range, but for the F4 with the APB1 timers based + * at 42MHz, this gets us down to ~320Hz or so. + */ + rPSC = 1; + + tone_state.pattern = PATTERN_NONE; + tone_state.note = 0; + + /* play the startup tune */ + tone_ioctl(NULL, TONE_SET_ALARM, 1); + + /* register the device */ + return register_driver("/dev/tone_alarm", &tone_fops, 0666, NULL); +} + +static int +tone_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + int result = 0; + int new = (int)arg; + + irqstate_t flags = irqsave(); + + /* decide whether to increase the alarm level to cmd or leave it alone */ + switch (cmd) { + case TONE_SET_ALARM: + if (new == 0) { + /* cancel any current alarm */ + tone_state.pattern = PATTERN_NONE; + tone_next(); + + } else if (new > TONE_MAX_PATTERN) { + + /* not a legal alarm value */ + result = -ERANGE; + + } else if (new > tone_state.pattern) { + + /* higher priority than the current alarm */ + tone_state.pattern = new; + tone_state.note = 0; + + /* and start playing it */ + tone_next(); + } + break; + default: + result = -EINVAL; + break; + } + + irqrestore(flags); + return result; +} + +static int +tone_write(struct file *filp, const char *buffer, size_t len) +{ + irqstate_t flags; + + /* sanity-check the size of the write */ + if (len > (TONE_MAX_PATTERN_LEN * sizeof(struct tone_note))) + return -EFBIG; + if ((len % sizeof(struct tone_note)) || (len == 0)) + return -EIO; + if (!tone_ok((struct tone_note *)buffer)) + return -EIO; + + flags = irqsave(); + + /* if we aren't playing an alarm tone */ + if (tone_state.pattern <= PATTERN_USER) { + + /* reset the tone state to play the new user pattern */ + tone_state.pattern = PATTERN_USER; + tone_state.note = 0; + + /* copy in the new pattern */ + memset(tone_state.user_pattern, 0, sizeof(tone_state.user_pattern)); + memcpy(tone_state.user_pattern, buffer, len); + + /* and start it */ + tone_next(); + } + irqrestore(flags); + + return len; +} + +static void +tone_next(void) +{ + const struct tone_note *np; + + /* stop the current note */ + rCR1 = 0; + + /* if we are no longer playing a pattern, we have nothing else to do here */ + if (tone_state.pattern == PATTERN_NONE) { + return; + } + + /* if the current pattern has ended, clear the pattern and stop */ + if (tone_state.note == TONE_NOTE_MAX) { + tone_state.pattern = PATTERN_NONE; + return; + } + + /* find the note to play */ + if (tone_state.pattern == PATTERN_USER) { + np = &tone_state.user_pattern[tone_state.note]; + } else { + np = &patterns[tone_state.pattern - 1][tone_state.note]; + } + + /* work out which note is next */ + tone_state.note++; + if (tone_state.note >= TONE_NOTE_MAX) { + /* hit the end of the pattern, stop */ + tone_state.pattern = PATTERN_NONE; + } else if (np[1].duration == DURATION_END) { + /* hit the end of the pattern, stop */ + tone_state.pattern = PATTERN_NONE; + } else if (np[1].duration == DURATION_REPEAT) { + /* next note is a repeat, rewind in preparation */ + tone_state.note = 0; + } + + /* set the timer to play the note, if required */ + if (np->pitch <= TONE_NOTE_SILENCE) { + + /* set reload based on the pitch */ + rARR = notes[np->pitch]; + + /* force an update, reloads the counter and all registers */ + rEGR = GTIM_EGR_UG; + + /* start the timer */ + rCR1 = GTIM_CR1_CEN; + } + + /* arrange a callback when the note/rest is done */ + hrt_call_after(&tone_state.note_end, (hrt_abstime)10000 * np->duration, (hrt_callout)tone_next, NULL); + +} + +static bool +tone_ok(struct tone_note *pattern) +{ + int i; + + for (i = 0; i < TONE_NOTE_MAX; i++) { + + /* first note must not be repeat or end */ + if ((i == 0) && + ((pattern[i].duration == DURATION_END) || (pattern[i].duration == DURATION_REPEAT))) + return false; + if (pattern[i].duration == DURATION_END) + break; + + /* pitch must be legal */ + if (pattern[i].pitch >= TONE_NOTE_MAX) + return false; + } + return true; +} + +#endif /* CONFIG_TONE_ALARM */ \ No newline at end of file diff --git a/nuttx/configs/px4fmu/src/px4fmu-internal.h b/nuttx/configs/px4fmu/src/px4fmu-internal.h new file mode 100644 index 0000000000..f48b1bf5ed --- /dev/null +++ b/nuttx/configs/px4fmu/src/px4fmu-internal.h @@ -0,0 +1,166 @@ +/**************************************************************************************************** + * configs/px4fmu/src/px4fmu_internal.h + * arch/arm/src/board/px4fmu_internal.n + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +#ifndef __CONFIGS_PX4FMU_SRC_PX4FMU_INTERNAL_H +#define __CONFIGS_PX4FMU_SRC_PX4FMU_INTERNAL_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include +#include +#include + +/**************************************************************************************************** + * Definitions + ****************************************************************************************************/ +/* Configuration ************************************************************************************/ + +#ifdef CONFIG_STM32_SPI2 +# error "SPI2 is not supported on this board" +#endif + +#if defined(CONFIG_STM32_CAN1) +# warning "CAN1 is not supported on this board" +#endif + +/* PX4FMU GPIOs ***********************************************************************************/ +/* LEDs */ + +#define GPIO_LED1 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN15) +#define GPIO_LED2 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN14) + +/* External interrupts */ +#define GPIO_EXTI_COMPASS (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTB|GPIO_PIN1) +// XXX MPU6000 DRDY? + +/* SPI chip selects */ +#define GPIO_SPI_CS_GYRO (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN14) +#define GPIO_SPI_CS_ACCEL (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN15) +#define GPIO_SPI_CS_MPU (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTB|GPIO_PIN0) +#define GPIO_SPI_CS_SDCARD (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4) + +/* User GPIOs + * + * GPIO0-1 are the buffered high-power GPIOs. + * GPIO2-5 are the USART2 pins. + * GPIO6-7 are the CAN2 pins. + */ +#define GPIO_GPIO0_INPUT (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN4) +#define GPIO_GPIO1_INPUT (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN5) +#define GPIO_GPIO2_INPUT (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN0) +#define GPIO_GPIO3_INPUT (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN1) +#define GPIO_GPIO4_INPUT (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN2) +#define GPIO_GPIO5_INPUT (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN3) +#define GPIO_GPIO6_INPUT (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN13) +#define GPIO_GPIO7_INPUT (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN2) +#define GPIO_GPIO0_OUTPUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN4) +#define GPIO_GPIO1_OUTPUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN5) +#define GPIO_GPIO2_OUTPUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN0) +#define GPIO_GPIO3_OUTPUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN1) +#define GPIO_GPIO4_OUTPUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN2) +#define GPIO_GPIO5_OUTPUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN3) +#define GPIO_GPIO6_OUTPUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN13) +#define GPIO_GPIO7_OUTPUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN12) +#define GPIO_GPIO_DIR (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN13) + +/* USB OTG FS + * + * PA9 OTG_FS_VBUS VBUS sensing (also connected to the green LED) + */ +#define GPIO_OTGFS_VBUS (GPIO_INPUT|GPIO_FLOAT|GPIO_SPEED_100MHz|GPIO_OPENDRAIN|GPIO_PORTA|GPIO_PIN9) + +/* PWM + * + * The PX4FMU has five PWM outputs, of which only the output on + * pin PC8 is fixed assigned to this function. The other four possible + * pwm sources are the TX, RX, RTS and CTS pins of USART2 + * + * Alternate function mapping: + * PC8 - BUZZER - TIM8_CH3/SDIO_D0 /TIM3_CH3/ USART6_CK / DCMI_D2 + */ + +#ifdef CONFIG_PWM +# if defined(CONFIG_STM32_TIM3_PWM) +# define BUZZER_PWMCHANNEL 3 +# define BUZZER_PWMTIMER 3 +# elif defined(CONFIG_STM32_TIM8_PWM) +# define BUZZER_PWMCHANNEL 3 +# define BUZZER_PWMTIMER 8 +# endif +#endif + +/**************************************************************************************************** + * Public Types + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public data + ****************************************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************************************** + * Public Functions + ****************************************************************************************************/ + +/**************************************************************************************************** + * Name: stm32_spiinitialize + * + * Description: + * Called to configure SPI chip select GPIO pins for the PX4FMU board. + * + ****************************************************************************************************/ + +extern void stm32_spiinitialize(void); + +/**************************************************************************************************** + * Name: px4fmu_gpio_init + * + * Description: + * Called to configure the PX4FMU user GPIOs + * + ****************************************************************************************************/ + +extern void px4fmu_gpio_init(void); + + +// XXX additional SPI chipselect functions required? + +#endif /* __ASSEMBLY__ */ +#endif /* __CONFIGS_PX4FMU_SRC_PX4FMU_INTERNAL_H */ + diff --git a/nuttx/configs/px4fmu/src/up_adc.c b/nuttx/configs/px4fmu/src/up_adc.c new file mode 100644 index 0000000000..2d74e6f006 --- /dev/null +++ b/nuttx/configs/px4fmu/src/up_adc.c @@ -0,0 +1,173 @@ +/************************************************************************************ + * configs/stm3240g-eval/src/up_adc.c + * arch/arm/src/board/up_adc.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "chip.h" +#include "up_arch.h" + +//#include "stm32_pwm.h" +#include "stm32_adc.h" +#include "px4fmu-internal.h" + +#ifdef CONFIG_ADC + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/* Configuration ************************************************************/ +/* Up to 3 ADC interfaces are supported */ + +#if STM32_NADC < 3 +# undef CONFIG_STM32_ADC3 +#endif + +#if STM32_NADC < 2 +# undef CONFIG_STM32_ADC2 +#endif + +#if STM32_NADC < 1 +# undef CONFIG_STM32_ADC3 +#endif + +#if defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2) || defined(CONFIG_STM32_ADC3) +#ifndef CONFIG_STM32_ADC3 +# warning "Channel information only available for ADC3" +#endif + +#define ADC3_NCHANNELS 4 + +/************************************************************************************ + * Private Data + ************************************************************************************/ +/* The PX4FMU board has four ADC channels: ADC323 IN10-13 + */ + +/* Identifying number of each ADC channel: Variable Resistor. */ + +#ifdef CONFIG_STM32_ADC3 +static const uint8_t g_chanlist[ADC3_NCHANNELS] = {10, 11};// , 12, 13}; ADC12 and 13 are used by MPU on v1.5 boards + +/* Configurations of pins used byte each ADC channels */ +static const uint32_t g_pinlist[ADC3_NCHANNELS] = {GPIO_ADC3_IN10, GPIO_ADC3_IN11}; // ADC12 and 13 are used by MPU on v1.5 boards, GPIO_ADC3_IN12, GPIO_ADC3_IN13}; +#endif + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: adc_devinit + * + * Description: + * All STM32 architectures must provide the following interface to work with + * examples/adc. + * + ************************************************************************************/ + +int adc_devinit(void) +{ +#ifdef CONFIG_STM32_ADC3 + static bool initialized = false; + struct adc_dev_s *adc[ADC3_NCHANNELS]; + int ret; + int i; + + /* Check if we have already initialized */ + + if (!initialized) + { + char name[11]; + + for (i = 0; i < ADC3_NCHANNELS; i++) + { + stm32_configgpio(g_pinlist[i]); + } + + for (i = 0; i < 1; i++) + { + /* Configure the pins as analog inputs for the selected channels */ + //stm32_configgpio(g_pinlist[i]); + + /* Call stm32_adcinitialize() to get an instance of the ADC interface */ + //multiple channels only supported with dma! + adc[i] = stm32_adcinitialize(3, (g_chanlist), 4); + if (adc == NULL) + { + adbg("ERROR: Failed to get ADC interface\n"); + return -ENODEV; + } + + + /* Register the ADC driver at "/dev/adc0" */ + sprintf(name, "/dev/adc%d", i); + ret = adc_register(name, adc[i]); + if (ret < 0) + { + adbg("adc_register failed for adc %s: %d\n", name, ret); + return ret; + } + } + + /* Now we are initialized */ + + initialized = true; + } + + return OK; +#else + return -ENOSYS; +#endif +} + +#endif /* CONFIG_STM32_ADC || CONFIG_STM32_ADC2 || CONFIG_STM32_ADC3 */ +#endif /* CONFIG_ADC */ diff --git a/nuttx/configs/px4fmu/src/up_boot.c b/nuttx/configs/px4fmu/src/up_boot.c new file mode 100644 index 0000000000..da396cdd6f --- /dev/null +++ b/nuttx/configs/px4fmu/src/up_boot.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include + +#include + +#include "up_arch.h" +#include "px4fmu-internal.h" + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_boardinitialize + * + * Description: + * All STM32 architectures must provide the following entry point. This entry point + * is called early in the intitialization -- after all memory has been configured + * and mapped but before any devices have been initialized. + * + ************************************************************************************/ + +void stm32_boardinitialize(void) +{ + /* configure SPI interfaces */ + stm32_spiinitialize(); + + /* configure LEDs */ + up_ledinit(); +} diff --git a/nuttx/configs/px4fmu/src/up_can.c b/nuttx/configs/px4fmu/src/up_can.c new file mode 100644 index 0000000000..daf6484f22 --- /dev/null +++ b/nuttx/configs/px4fmu/src/up_can.c @@ -0,0 +1,142 @@ +/************************************************************************************ + * configs/px4fmu/src/up_can.c + * arch/arm/src/board/up_can.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "chip.h" +#include "up_arch.h" + +#include "stm32.h" +#include "stm32_can.h" +#include "px4fmu-internal.h" + +#if defined(CONFIG_CAN) && (defined(CONFIG_STM32_CAN1) || defined(CONFIG_STM32_CAN2)) + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ + +#if defined(CONFIG_STM32_CAN1) && defined(CONFIG_STM32_CAN2) +# warning "Both CAN1 and CAN2 are enabled. Assuming only CAN1." +# undef CONFIG_STM32_CAN2 +#endif + +#ifdef CONFIG_STM32_CAN1 +# define CAN_PORT 1 +#else +# define CAN_PORT 2 +#endif + +/* Debug ***************************************************************************/ +/* Non-standard debug that may be enabled just for testing CAN */ + +#ifdef CONFIG_DEBUG_CAN +# define candbg dbg +# define canvdbg vdbg +# define canlldbg lldbg +# define canllvdbg llvdbg +#else +# define candbg(x...) +# define canvdbg(x...) +# define canlldbg(x...) +# define canllvdbg(x...) +#endif + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: can_devinit + * + * Description: + * All STM32 architectures must provide the following interface to work with + * examples/can. + * + ************************************************************************************/ + +int can_devinit(void) +{ + static bool initialized = false; + struct can_dev_s *can; + int ret; + + /* Check if we have already initialized */ + + if (!initialized) + { + /* Call stm32_caninitialize() to get an instance of the CAN interface */ + + can = stm32_caninitialize(CAN_PORT); + if (can == NULL) + { + candbg("ERROR: Failed to get CAN interface\n"); + return -ENODEV; + } + + /* Register the CAN driver at "/dev/can0" */ + + ret = can_register("/dev/can0", can); + if (ret < 0) + { + candbg("ERROR: can_register failed: %d\n", ret); + return ret; + } + + /* Now we are initialized */ + + initialized = true; + } + + return OK; +} + +#endif /* CONFIG_STM32_CAN || CONFIG_STM32_CAN2 || CONFIG_STM32_CAN3 */ diff --git a/nuttx/configs/px4fmu/src/up_cpuload.c b/nuttx/configs/px4fmu/src/up_cpuload.c new file mode 100644 index 0000000000..750ec48522 --- /dev/null +++ b/nuttx/configs/px4fmu/src/up_cpuload.c @@ -0,0 +1,182 @@ +/**************************************************************************** + * configs/px4fmu/src/up_leds.c + * arch/arm/src/board/up_leds.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include "chip.h" +#include "up_arch.h" +#include "up_internal.h" +#include "stm32_internal.h" +#include "px4fmu-internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: + ****************************************************************************/ + +#ifdef CONFIG_SCHED_INSTRUMENTATION + +struct system_load_s system_load; + +extern FAR _TCB *sched_gettcb(pid_t pid); + +void cpuload_initialize_once(void); + +void cpuload_initialize_once() +{ +// if (!system_load.initialized) +// { + system_load.start_time = hrt_absolute_time(); + int i; + for (i = 0; i < CONFIG_MAX_TASKS; i++) + { + system_load.tasks[i].valid = false; + } + system_load.total_count = 0; + + uint64_t now = hrt_absolute_time(); + + /* initialize idle thread statically */ + system_load.tasks[0].start_time = now; + system_load.tasks[0].total_runtime = 0; + system_load.tasks[0].curr_start_time = 0; + system_load.tasks[0].tcb = sched_gettcb(0); + system_load.tasks[0].valid = true; + system_load.total_count++; + + /* initialize init thread statically */ + system_load.tasks[1].start_time = now; + system_load.tasks[1].total_runtime = 0; + system_load.tasks[1].curr_start_time = 0; + system_load.tasks[1].tcb = sched_gettcb(1); + system_load.tasks[1].valid = true; + /* count init thread */ + system_load.total_count++; + // } +} + +void sched_note_start(FAR _TCB *tcb ) +{ + /* search first free slot */ + int i; + for (i = 1; i < CONFIG_MAX_TASKS; i++) + { + if (!system_load.tasks[i].valid) + { + /* slot is available */ + system_load.tasks[i].start_time = hrt_absolute_time(); + system_load.tasks[i].total_runtime = 0; + system_load.tasks[i].curr_start_time = 0; + system_load.tasks[i].tcb = tcb; + system_load.tasks[i].valid = true; + system_load.total_count++; + break; + } + } +} + +void sched_note_stop(FAR _TCB *tcb ) +{ + int i; + for (i = 1; i < CONFIG_MAX_TASKS; i++) + { + if (system_load.tasks[i].tcb->pid == tcb->pid) + { + /* mark slot as fee */ + system_load.tasks[i].valid = false; + system_load.tasks[i].total_runtime = 0; + system_load.tasks[i].curr_start_time = 0; + system_load.tasks[i].tcb = NULL; + system_load.total_count--; + break; + } + } +} + +void sched_note_switch(FAR _TCB *pFromTcb, FAR _TCB *pToTcb) +{ + uint64_t new_time = hrt_absolute_time(); + + /* Kind of inefficient: find both tasks and update times */ + uint8_t both_found = 0; + for (int i = 0; i < CONFIG_MAX_TASKS; i++) + { + /* Task ending its current scheduling run */ + if (system_load.tasks[i].tcb->pid == pFromTcb->pid) + { + //if (system_load.tasks[i].curr_start_time != 0) + { + system_load.tasks[i].total_runtime += new_time - system_load.tasks[i].curr_start_time; + } + both_found++; + } + else if (system_load.tasks[i].tcb->pid == pToTcb->pid) + { + system_load.tasks[i].curr_start_time = new_time; + both_found++; + } + + /* Do only iterate as long as needed */ + if (both_found == 2) + { + break; + } + } +} + +#endif /* CONFIG_SCHED_INSTRUMENTATION */ diff --git a/nuttx/configs/px4fmu/src/up_hrt.c b/nuttx/configs/px4fmu/src/up_hrt.c new file mode 100644 index 0000000000..35aecfe080 --- /dev/null +++ b/nuttx/configs/px4fmu/src/up_hrt.c @@ -0,0 +1,801 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file High-resolution timer callouts and timekeeping. + * + * This can use any general or advanced STM32 timer. + * + * Note that really, this could use systick too, but that's + * monopolised by NuttX and stealing it would just be awkward. + * + * We don't use the NuttX STM32 driver per se; rather, we + * claim the timer and then drive it directly. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "chip.h" +#include "up_internal.h" +#include "up_arch.h" + +#include "stm32_internal.h" +#include "stm32_gpio.h" +#include "stm32_tim.h" + +#ifdef CONFIG_HRT_TIMER + +/* HRT configuration */ +#if HRT_TIMER == 1 +# define HRT_TIMER_BASE STM32_TIM1_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB2ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM1EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM1CC +# define HRT_TIMER_CLOCK STM32_APB2_TIM1_CLKIN +# if CONFIG_STM32_TIM1 +# error must not set CONFIG_STM32_TIM1=y and HRT_TIMER=1 +# endif +#elif HRT_TIMER == 2 +# define HRT_TIMER_BASE STM32_TIM2_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM2EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM2 +# define HRT_TIMER_CLOCK STM32_APB1_TIM2_CLKIN +# if CONFIG_STM32_TIM2 +# error must not set CONFIG_STM32_TIM2=y and HRT_TIMER=2 +# endif +#elif HRT_TIMER == 3 +# define HRT_TIMER_BASE STM32_TIM3_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM3EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM3 +# define HRT_TIMER_CLOCK STM32_APB1_TIM3_CLKIN +# if CONFIG_STM32_TIM3 +# error must not set CONFIG_STM32_TIM3=y and HRT_TIMER=3 +# endif +#elif HRT_TIMER == 4 +# define HRT_TIMER_BASE STM32_TIM4_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM4EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM4 +# define HRT_TIMER_CLOCK STM32_APB1_TIM4_CLKIN +# if CONFIG_STM32_TIM4 +# error must not set CONFIG_STM32_TIM4=y and HRT_TIMER=4 +# endif +#elif HRT_TIMER == 5 +# define HRT_TIMER_BASE STM32_TIM5_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM5EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM5 +# define HRT_TIMER_CLOCK STM32_APB1_TIM5_CLKIN +# if CONFIG_STM32_TIM5 +# error must not set CONFIG_STM32_TIM5=y and HRT_TIMER=5 +# endif +#elif HRT_TIMER == 8 +# define HRT_TIMER_BASE STM32_TIM8_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB2ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM8EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM8CC +# define HRT_TIMER_CLOCK STM32_APB2_TIM8_CLKIN +# if CONFIG_STM32_TIM8 +# error must not set CONFIG_STM32_TIM8=y and HRT_TIMER=6 +# endif +#elif HRT_TIMER == 9 +# define HRT_TIMER_BASE STM32_TIM9_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM9EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM1BRK +# define HRT_TIMER_CLOCK STM32_APB1_TIM9_CLKIN +# if CONFIG_STM32_TIM9 +# error must not set CONFIG_STM32_TIM9=y and HRT_TIMER=9 +# endif +#elif HRT_TIMER == 10 +# define HRT_TIMER_BASE STM32_TIM10_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM10EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM1UP +# define HRT_TIMER_CLOCK STM32_APB1_TIM10_CLKIN +# if CONFIG_STM32_TIM10 +# error must not set CONFIG_STM32_TIM11=y and HRT_TIMER=10 +# endif +#elif HRT_TIMER == 11 +# define HRT_TIMER_BASE STM32_TIM11_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM11EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM1TRGCOM +# define HRT_TIMER_CLOCK STM32_APB1_TIM11_CLKIN +# if CONFIG_STM32_TIM11 +# error must not set CONFIG_STM32_TIM11=y and HRT_TIMER=11 +# endif +#else +# error HRT_TIMER must be set in board.h if CONFIG_HRT_TIMER=y +#endif + +/* + * HRT clock must be a multiple of 1MHz greater than 1MHz + */ +#if (HRT_TIMER_CLOCK % 1000000) != 0 +# error HRT_TIMER_CLOCK must be a multiple of 1MHz +#endif +#if HRT_TIMER_CLOCK <= 1000000 +# error HRT_TIMER_CLOCK must be greater than 1MHz +#endif + +/* + * Minimum/maximum deadlines. + * + * These are suitable for use with a 16-bit timer/counter clocked + * at 1MHz. The high-resolution timer need only guarantee that it + * not wrap more than once in the 50ms period for absolute time to + * be consistently maintained. + * + * The minimum deadline must be such that the time taken between + * reading a time and writing a deadline to the timer cannot + * result in missing the deadline. + */ +#define HRT_INTERVAL_MIN 50 +#define HRT_INTERVAL_MAX 50000 + +/* + * Period of the free-running counter, in microseconds. + */ +#define HRT_COUNTER_PERIOD 65536 + +/* + * Scaling factor(s) for the free-running counter; convert an input + * in counts to a time in microseconds. + */ +#define HRT_COUNTER_SCALE(_c) (_c) + +/* + * Timer register accessors + */ +#define REG(_reg) (*(volatile uint32_t *)(HRT_TIMER_BASE + _reg)) + +#define rCR1 REG(STM32_GTIM_CR1_OFFSET) +#define rCR2 REG(STM32_GTIM_CR2_OFFSET) +#define rSMCR REG(STM32_GTIM_SMCR_OFFSET) +#define rDIER REG(STM32_GTIM_DIER_OFFSET) +#define rSR REG(STM32_GTIM_SR_OFFSET) +#define rEGR REG(STM32_GTIM_EGR_OFFSET) +#define rCCMR1 REG(STM32_GTIM_CCMR1_OFFSET) +#define rCCMR2 REG(STM32_GTIM_CCMR2_OFFSET) +#define rCCER REG(STM32_GTIM_CCER_OFFSET) +#define rCNT REG(STM32_GTIM_CNT_OFFSET) +#define rPSC REG(STM32_GTIM_PSC_OFFSET) +#define rARR REG(STM32_GTIM_ARR_OFFSET) +#define rCCR1 REG(STM32_GTIM_CCR1_OFFSET) +#define rCCR2 REG(STM32_GTIM_CCR2_OFFSET) +#define rCCR3 REG(STM32_GTIM_CCR3_OFFSET) +#define rCCR4 REG(STM32_GTIM_CCR4_OFFSET) +#define rDCR REG(STM32_GTIM_DCR_OFFSET) +#define rDMAR REG(STM32_GTIM_DMAR_OFFSET) + +/* + * Specific registers and bits used by HRT sub-functions + */ +#if HRT_TIMER_CHANNEL == 1 +# define rCCR_HRT rCCR1 /* compare register for HRT */ +# define DIER_HRT GTIM_DIER_CC1IE /* interrupt enable for HRT */ +# define SR_INT_HRT GTIM_SR_CC1IF /* interrupt status for HRT */ +#elif HRT_TIMER_CHANNEL == 2 +# define rCCR_HRT rCCR2 /* compare register for HRT */ +# define DIER_HRT GTIM_DIER_CC2IE /* interrupt enable for HRT */ +# define SR_INT_HRT GTIM_SR_CC2IF /* interrupt status for HRT */ +#elif HRT_TIMER_CHANNEL == 3 +# define rCCR_HRT rCCR3 /* compare register for HRT */ +# define DIER_HRT GTIM_DIER_CC3IE /* interrupt enable for HRT */ +# define SR_INT_HRT GTIM_SR_CC3IF /* interrupt status for HRT */ +#elif HRT_TIMER_CHANNEL == 4 +# define rCCR_HRT rCCR4 /* compare register for HRT */ +# define DIER_HRT GTIM_DIER_CC4IE /* interrupt enable for HRT */ +# define SR_INT_HRT GTIM_SR_CC4IF /* interrupt status for HRT */ +#else +# error HRT_TIMER_CHANNEL must be a value between 1 and 4 +#endif + +/* + * Queue of callout entries. + */ +static struct sq_queue_s callout_queue; + +/* timer-specific functions */ +static void hrt_tim_init(void); +static int hrt_tim_isr(int irq, void *context); + +/* callout list manipulation */ +static void hrt_call_internal(struct hrt_call *entry, + hrt_abstime deadline, + hrt_abstime interval, + hrt_callout callout, + void *arg); +static void hrt_call_enter(struct hrt_call *entry); +static void hrt_call_reschedule(void); +static void hrt_call_invoke(void); + +/* + * Specific registers and bits used by PPM sub-functions + */ +#ifdef CONFIG_HRT_PPM +# if HRT_PPM_CHANNEL == 1 +# define rCCR_PPM rCCR1 /* capture register for PPM */ +# define DIER_PPM GTIM_DIER_CC1IE /* capture interrupt (non-DMA mode) */ +# define SR_INT_PPM GTIM_SR_CC1IF /* capture interrupt (non-DMA mode) */ +# define SR_OVF_PPM GTIM_SR_CC1OF /* capture overflow (non-DMA mode) */ +# define CCMR1_PPM 1 /* not on TI1/TI2 */ +# define CCMR2_PPM 0 /* on TI3, not on TI4 */ +# define CCER_PPM (GTIM_CCER_CC1E | GTIM_CCER_CC1P | GTIM_CCER_CC1NP) /* CC1, both edges */ +# elif HRT_PPM_CHANNEL == 2 +# define rCCR_PPM rCCR2 /* capture register for PPM */ +# define DIER_PPM GTIM_DIER_CC2IE /* capture interrupt (non-DMA mode) */ +# define SR_INT_PPM GTIM_SR_CC2IF /* capture interrupt (non-DMA mode) */ +# define SR_OVF_PPM GTIM_SR_CC2OF /* capture overflow (non-DMA mode) */ +# define CCMR1_PPM 2 /* not on TI1/TI2 */ +# define CCMR2_PPM 0 /* on TI3, not on TI4 */ +# define CCER_PPM (GTIM_CCER_CC2E | GTIM_CCER_CC2P | GTIM_CCER_CC2NP) /* CC2, both edges */ +# elif HRT_PPM_CHANNEL == 3 +# define rCCR_PPM rCCR3 /* capture register for PPM */ +# define DIER_PPM GTIM_DIER_CC3IE /* capture interrupt (non-DMA mode) */ +# define SR_INT_PPM GTIM_SR_CC3IF /* capture interrupt (non-DMA mode) */ +# define SR_OVF_PPM GTIM_SR_CC3OF /* capture overflow (non-DMA mode) */ +# define CCMR1_PPM 0 /* not on TI1/TI2 */ +# define CCMR2_PPM 1 /* on TI3, not on TI4 */ +# define CCER_PPM (GTIM_CCER_CC3E | GTIM_CCER_CC3P | GTIM_CCER_CC3NP) /* CC3, both edges */ +# elif HRT_PPM_CHANNEL == 4 +# define rCCR_PPM rCCR4 /* capture register for PPM */ +# define DIER_PPM GTIM_DIER_CC4IE /* capture interrupt (non-DMA mode) */ +# define SR_INT_PPM GTIM_SR_CC4IF /* capture interrupt (non-DMA mode) */ +# define SR_OVF_PPM GTIM_SR_CC4OF /* capture overflow (non-DMA mode) */ +# define CCMR1_PPM 0 /* not on TI1/TI2 */ +# define CCMR2_PPM 2 /* on TI3, not on TI4 */ +# define CCER_PPM (GTIM_CCER_CC4E | GTIM_CCER_CC4P | GTIM_CCER_CC4NP) /* CC4, both edges */ +# else +# error HRT_PPM_CHANNEL must be a value between 1 and 4 if CONFIG_HRT_PPM is set +# endif + +/* + * PPM decoder tuning parameters + */ +# define PPM_MAX_PULSE_WIDTH 500 /* maximum width of a pulse */ +# define PPM_MIN_CHANNEL_VALUE 750 /* shortest valid channel signal */ +# define PPM_MAX_CHANNEL_VALUE 2400 /* longest valid channel signal */ +# define PPM_MIN_START 5000 /* shortest valid start gap */ + +/* decoded PPM buffer */ +#define PPM_MAX_CHANNELS 12 +uint16_t ppm_buffer[PPM_MAX_CHANNELS]; +unsigned ppm_decoded_channels; + +/* PPM edge history */ +uint16_t ppm_edge_history[32]; +unsigned ppm_edge_next; + +/* PPM pulse history */ +uint16_t ppm_pulse_history[32]; +unsigned ppm_pulse_next; + +static uint16_t ppm_temp_buffer[PPM_MAX_CHANNELS]; + +/* PPM decoder state machine */ +struct { + uint16_t last_edge; /* last capture time */ + uint16_t last_mark; /* last significant edge */ + unsigned next_channel; + enum { + UNSYNCH = 0, + ARM, + ACTIVE, + INACTIVE + } phase; +} ppm; + +static void hrt_ppm_decode(uint32_t status); + +#else +/* disable the PPM configuration */ +# define rCCR_PPM 0 +# define DIER_PPM 0 +# define SR_INT_PPM 0 +# define SR_OVF_PPM 0 +# define CCMR1_PPM 0 +# define CCMR2_PPM 0 +# define CCER_PPM 0 +#endif /* CONFIG_HRT_PPM */ + +/* + * Initialise the timer we are going to use. + * + * We expect that we'll own one of the reduced-function STM32 general + * timers, and that we can use channel 1 in compare mode. + */ +static void +hrt_tim_init(void) +{ + /* clock/power on our timer */ + modifyreg32(HRT_TIMER_POWER_REG, 0, HRT_TIMER_POWER_BIT); + + /* claim our interrupt vector */ + irq_attach(HRT_TIMER_VECTOR, hrt_tim_isr); + + /* disable and configure the timer */ + rCR1 = 0; + rCR2 = 0; + rSMCR = 0; + rDIER = DIER_HRT | DIER_PPM; + rCCER = 0; /* unlock CCMR* registers */ + rCCMR1 = CCMR1_PPM; + rCCMR2 = CCMR2_PPM; + rCCER = CCER_PPM; + rDCR = 0; + + /* configure the timer to free-run at 1MHz */ + rPSC = (HRT_TIMER_CLOCK / 1000000) - 1; /* this really only works for whole-MHz clocks */ + + /* run the full span of the counter */ + rARR = 0xffff; + + /* set an initial capture a little ways off */ + rCCR_HRT = 1000; + + /* generate an update event; reloads the counter, all registers */ + rEGR = GTIM_EGR_UG; + + /* enable the timer */ + rCR1 = GTIM_CR1_CEN; + + /* enable interrupts */ + up_enable_irq(HRT_TIMER_VECTOR); +} + +#ifdef CONFIG_HRT_PPM +/* + * Handle the PPM decoder state machine. + */ +static void +hrt_ppm_decode(uint32_t status) +{ + uint16_t count = rCCR_PPM; + uint16_t width; + uint16_t interval; + unsigned i; + + /* if we missed an edge, we have to give up */ + if (status & SR_OVF_PPM) + goto error; + + /* how long since the last edge? */ + width = count - ppm.last_edge; + ppm.last_edge = count; + + ppm_edge_history[ppm_edge_next++] = width; + if (ppm_edge_next >= 32) + ppm_edge_next = 0; + + /* + * if this looks like a start pulse, then push the last set of values + * and reset the state machine + */ + if (width >= PPM_MIN_START) { + + /* export the last set of samples if we got something sensible */ + if (ppm.next_channel > 4) { + for (i = 0; i < ppm.next_channel && i < PPM_MAX_CHANNELS; i++) + ppm_buffer[i] = ppm_temp_buffer[i]; + ppm_decoded_channels = i; + } + + /* reset for the next frame */ + ppm.next_channel = 0; + + /* next edge is the reference for the first channel */ + ppm.phase = ARM; + + return; + } + + switch (ppm.phase) { + case UNSYNCH: + /* we are waiting for a start pulse - nothing useful to do here */ + return; + + case ARM: + /* we expect a pulse giving us the first mark */ + if (width > PPM_MAX_PULSE_WIDTH) + goto error; /* pulse was too long */ + + /* record the mark timing, expect an inactive edge */ + ppm.last_mark = count; + ppm.phase = INACTIVE; + return; + + case INACTIVE: + /* this edge is not interesting, but now we are ready for the next mark */ + ppm.phase = ACTIVE; + return; + + case ACTIVE: + /* determine the interval from the last mark */ + interval = count - ppm.last_mark; + ppm.last_mark = count; + + ppm_pulse_history[ppm_pulse_next++] = interval; + if (ppm_pulse_next >= 32) + ppm_pulse_next = 0; + + /* if the mark-mark timing is out of bounds, abandon the frame */ + if ((interval < PPM_MIN_CHANNEL_VALUE) || (interval > PPM_MAX_CHANNEL_VALUE)) + goto error; + + /* if we have room to store the value, do so */ + if (ppm.next_channel < PPM_MAX_CHANNELS) + ppm_temp_buffer[ppm.next_channel++] = interval; + + ppm.phase = INACTIVE; + return; + + } + + /* the state machine is corrupted; reset it */ + +error: + /* we don't like the state of the decoder, reset it and try again */ + ppm.phase = UNSYNCH; +} +#endif /* CONFIG_HRT_PPM */ + +/* + * Handle the compare interupt by calling the callout dispatcher + * and then re-scheduling the next deadline. + */ +static int +hrt_tim_isr(int irq, void *context) +{ + uint32_t status; + + /* copy interrupt status */ + status = rSR; + + /* ack the interrupts we just read */ + rSR = ~status; + +#ifdef CONFIG_HRT_PPM + /* was this a PPM edge? */ + if (status & (SR_INT_PPM | SR_OVF_PPM)) + hrt_ppm_decode(status); +#endif + + /* was this a timer tick? */ + if (status & SR_INT_HRT) { + /* run any callouts that have met their deadline */ + hrt_call_invoke(); + + /* and schedule the next interrupt */ + hrt_call_reschedule(); + } + + return OK; +} + +/* + * Fetch a never-wrapping absolute time value in microseconds from + * some arbitrary epoch shortly after system start. + */ +hrt_abstime +hrt_absolute_time(void) +{ + hrt_abstime abstime; + uint32_t count; + uint32_t flags; + + /* + * Counter state. Marked volatile as they may change + * inside this routine but outside the irqsave/restore + * pair. Discourage the compiler from moving loads/stores + * to these outside of the protected range. + */ + static volatile hrt_abstime base_time; + static volatile uint32_t last_count; + + /* prevent re-entry */ + flags = irqsave(); + + /* get the current counter value */ + count = rCNT; + + /* + * Determine whether the counter has wrapped since the + * last time we're called. + * + * This simple test is sufficient due to the guarantee that + * we are always called at least once per counter period. + */ + if (count < last_count) + base_time += HRT_COUNTER_PERIOD; + + /* save the count for next time */ + last_count = count; + + /* compute the current time */ + abstime = HRT_COUNTER_SCALE(base_time + count); + + irqrestore(flags); + + return abstime; +} + +/* + * Convert a timespec to absolute time + */ +hrt_abstime +ts_to_abstime(struct timespec *ts) +{ + hrt_abstime result; + + result = (hrt_abstime)(ts->tv_sec) * 1000000; + result += ts->tv_nsec / 1000; + + return result; +} + +/* + * Convert absolute time to a timespec. + */ +void +abstime_to_ts(struct timespec *ts, hrt_abstime abstime) +{ + ts->tv_sec = abstime / 1000000; + abstime -= ts->tv_sec * 1000000; + ts->tv_nsec = abstime * 1000; +} + +/* + * Initalise the high-resolution timing module. + */ +void +hrt_init(void) +{ + sq_init(&callout_queue); + hrt_tim_init(); + +#ifdef CONFIG_HRT_PPM + /* configure the PPM input pin */ + stm32_configgpio(GPIO_PPM_IN); +#endif +} + +/* + * Call callout(arg) after interval has elapsed. + */ +void +hrt_call_after(struct hrt_call *entry, hrt_abstime delay, hrt_callout callout, void *arg) +{ + hrt_call_internal(entry, + hrt_absolute_time() + delay, + 0, + callout, + arg); +} + +/* + * Call callout(arg) at calltime. + */ +void +hrt_call_at(struct hrt_call *entry, hrt_abstime calltime, hrt_callout callout, void *arg) +{ + hrt_call_internal(entry, calltime, 0, callout, arg); +} + +/* + * Call callout(arg) every period. + */ +void +hrt_call_every(struct hrt_call *entry, hrt_abstime delay, hrt_abstime interval, hrt_callout callout, void *arg) +{ + hrt_call_internal(entry, + hrt_absolute_time() + delay, + interval, + callout, + arg); +} + +static void +hrt_call_internal(struct hrt_call *entry, hrt_abstime deadline, hrt_abstime interval, hrt_callout callout, void *arg) +{ + irqstate_t flags = irqsave(); + + /* if the entry is currently queued, remove it */ + if (entry->deadline != 0) + sq_rem(&entry->link, &callout_queue); + + entry->deadline = deadline; + entry->period = interval; + entry->callout = callout; + entry->arg = arg; + + hrt_call_enter(entry); + + irqrestore(flags); +} + +/* + * If this returns true, the call has been invoked and removed from the callout list. + * + * Always returns false for repeating callouts. + */ +bool +hrt_called(struct hrt_call *entry) +{ + return (entry->deadline == 0); +} + +/* + * Remove the entry from the callout list. + */ +void +hrt_cancel(struct hrt_call *entry) +{ + irqstate_t flags = irqsave(); + + sq_rem(&entry->link, &callout_queue); + entry->deadline = 0; + + /* if this is a periodic call being removed by the callout, prevent it from + * being re-entered when the callout returns. + */ + entry->period = 0; + + irqrestore(flags); +} + +static void +hrt_call_enter(struct hrt_call *entry) +{ + struct hrt_call *call, *next; + + call = (struct hrt_call *)sq_peek(&callout_queue); + + if ((call == NULL) || (entry->deadline < call->deadline)) { + sq_addfirst(&entry->link, &callout_queue); + //lldbg("call enter at head, reschedule\n"); + /* we changed the next deadline, reschedule the timer event */ + hrt_call_reschedule(); + } else { + do { + next = (struct hrt_call *)sq_next(&call->link); + if ((next == NULL) || (entry->deadline < next->deadline)) { + //lldbg("call enter after head\n"); + sq_addafter(&call->link, &entry->link, &callout_queue); + break; + } + } while ((call = next) != NULL); + } + + //lldbg("scheduled\n"); +} + +static void +hrt_call_invoke(void) +{ + struct hrt_call *call; + hrt_abstime deadline; + + while (true) { + /* get the current time */ + hrt_abstime now = hrt_absolute_time(); + + call = (struct hrt_call *)sq_peek(&callout_queue); + if (call == NULL) + break; + if (call->deadline > now) + break; + + sq_rem(&call->link, &callout_queue); + //lldbg("call pop\n"); + + /* save the intended deadline for periodic calls */ + deadline = call->deadline; + + /* zero the deadline, as the call has occurred */ + call->deadline = 0; + + /* invoke the callout (if there is one) */ + if (call->callout) { + //lldbg("call %p: %p(%p)\n", call, call->callout, call->arg); + call->callout(call->arg); + } + + /* if the callout has a non-zero period, it has to be re-entered */ + if (call->period != 0) { + call->deadline = deadline + call->period; + hrt_call_enter(call); + } + } +} + +/* + * Reschedule the next timer interrupt. + * + * This routine must be called with interrupts disabled. + */ +static void +hrt_call_reschedule() +{ + hrt_abstime now = hrt_absolute_time(); + struct hrt_call *next = (struct hrt_call *)sq_peek(&callout_queue); + hrt_abstime deadline = now + HRT_INTERVAL_MAX; + + /* + * Determine what the next deadline will be. + * + * Note that we ensure that this will be within the counter + * period, so that when we truncate all but the low 16 bits + * the next time the compare matches it will be the deadline + * we want. + * + * It is important for accurate timekeeping that the compare + * interrupt fires sufficiently often that the base_time update in + * hrt_absolute_time runs at least once per timer period. + */ + if (next != NULL) { + //lldbg("entry in queue\n"); + if (next->deadline <= (now + HRT_INTERVAL_MIN)) { + //lldbg("pre-expired\n"); + /* set a minimal deadline so that we call ASAP */ + deadline = now + HRT_INTERVAL_MIN; + } else if (next->deadline < deadline) { + //lldbg("due soon\n"); + deadline = next->deadline; + } + } + //lldbg("schedule for %u at %u\n", (unsigned)(deadline & 0xffffffff), (unsigned)(now & 0xffffffff)); + + /* set the new compare value */ + rCCR_HRT = deadline & 0xffff; +} + +#endif /* CONFIG_HRT_TIMER */ diff --git a/nuttx/configs/px4fmu/src/up_leds.c b/nuttx/configs/px4fmu/src/up_leds.c new file mode 100644 index 0000000000..f7b76aa58d --- /dev/null +++ b/nuttx/configs/px4fmu/src/up_leds.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * configs/px4fmu/src/up_leds.c + * arch/arm/src/board/up_leds.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "chip.h" +#include "up_arch.h" +#include "up_internal.h" +#include "stm32_internal.h" +#include "px4fmu-internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Enables debug output from this file (needs CONFIG_DEBUG with + * CONFIG_DEBUG_VERBOSE too) + */ + +#undef LED_DEBUG /* Define to enable debug */ + +#ifdef LED_DEBUG +# define leddbg lldbg +# define ledvdbg llvdbg +#else +# define leddbg(x...) +# define ledvdbg(x...) +#endif + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_ledinit + ****************************************************************************/ + +#ifdef CONFIG_ARCH_LEDS +void up_ledinit(void) +{ + /* Configure LED1-2 GPIOs for output */ + + stm32_configgpio(GPIO_LED1); + stm32_configgpio(GPIO_LED2); +} + +/**************************************************************************** + * Name: up_ledon + ****************************************************************************/ + +void up_ledon(int led) +{ + if (led == 0) + { + /* Pull down to switch on */ + stm32_gpiowrite(GPIO_LED1, false); + } + if (led == 1) + { + /* Pull down to switch on */ + stm32_gpiowrite(GPIO_LED2, false); + } +} + +/**************************************************************************** + * Name: up_ledoff + ****************************************************************************/ + +void up_ledoff(int led) +{ + if (led == 0) + { + /* Pull up to switch off */ + stm32_gpiowrite(GPIO_LED1, true); + } + if (led == 1) + { + /* Pull up to switch off */ + stm32_gpiowrite(GPIO_LED2, true); + } +} + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/nuttx/configs/px4fmu/src/up_nsh.c b/nuttx/configs/px4fmu/src/up_nsh.c new file mode 100644 index 0000000000..6e092e3b41 --- /dev/null +++ b/nuttx/configs/px4fmu/src/up_nsh.c @@ -0,0 +1,392 @@ +/**************************************************************************** + * config/stm3210e_eval/src/up_nsh.c + * arch/arm/src/board/up_nsh.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "stm32_internal.h" +#include "px4fmu-internal.h" +#include "stm32_uart.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Debug ********************************************************************/ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_DEBUG +# define message(...) lib_lowprintf(__VA_ARGS__) +# else +# define message(...) printf(__VA_ARGS__) +# endif +#else +# ifdef CONFIG_DEBUG +# define message lib_lowprintf +# else +# define message printf +# endif +#endif + +/**************************************************************************** + * Protected Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: multiport_setup + * + * Description: + * Perform setup of the PX4FMU's multi function ports + * + ****************************************************************************/ +int multiport_setup(void) +{ + int result = OK; + + return result; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_archinitialize + * + * Description: + * Perform architecture specific initialization + * + ****************************************************************************/ + +static struct spi_dev_s *spi1; +static struct spi_dev_s *spi3; +static struct i2c_dev_s *i2c1; +static struct i2c_dev_s *i2c2; +static struct i2c_dev_s *i2c3; + +#include + +#ifdef __cplusplus +int matherr(struct __exception *e) { + return 1; +} +#else +int matherr(struct exception *e) { + return 1; +} +#endif + +int nsh_archinitialize(void) +{ + int result; + + /* INIT 1 Lowest level NuttX initialization has been done at this point, LEDs and UARTs are configured */ + + /* INIT 2 Configuring PX4 low-level peripherals, these will be always needed */ + + /* configure the high-resolution time/callout interface */ +#ifdef CONFIG_HRT_TIMER + hrt_init(); +#endif + + /* configure CPU load estimation */ + #ifdef CONFIG_SCHED_INSTRUMENTATION + cpuload_initialize_once(); + #endif + + /* set up the serial DMA polling */ +#ifdef SERIAL_HAVE_DMA + { + static struct hrt_call serial_dma_call; + struct timespec ts; + + /* + * Poll at 1ms intervals for received bytes that have not triggered + * a DMA event. + */ + ts.tv_sec = 0; + ts.tv_nsec = 1000000; + + hrt_call_every(&serial_dma_call, + ts_to_abstime(&ts), + ts_to_abstime(&ts), + (hrt_callout)stm32_serial_dma_poll, + NULL); + } +#endif + + message("\r\n"); + + up_ledoff(LED_BLUE); + up_ledoff(LED_AMBER); + + up_ledon(LED_BLUE); + + /* Configure user-space led driver */ + px4fmu_led_init(); + + /* Configure SPI-based devices */ + + spi1 = up_spiinitialize(1); + if (!spi1) + { + message("[boot] FAILED to initialize SPI port 1\r\n"); + up_ledon(LED_AMBER); + return -ENODEV; + } + + // Setup 10 MHz clock (maximum rate the BMA180 can sustain) + SPI_SETFREQUENCY(spi1, 10000000); + SPI_SETBITS(spi1, 8); + SPI_SETMODE(spi1, SPIDEV_MODE3); + SPI_SELECT(spi1, PX4_SPIDEV_GYRO, false); + SPI_SELECT(spi1, PX4_SPIDEV_ACCEL, false); + SPI_SELECT(spi1, PX4_SPIDEV_MPU, false); + up_udelay(20); + + message("[boot] Successfully initialized SPI port 1\r\n"); + + /* initialize SPI peripherals redundantly */ + int gyro_attempts = 0; + int gyro_fail = 0; + + while (gyro_attempts < 5) + { + gyro_fail = l3gd20_attach(spi1, PX4_SPIDEV_GYRO); + gyro_attempts++; + if (gyro_fail == 0) break; + up_udelay(1000); + } + + if (gyro_fail) message("[boot] FAILED to attach L3GD20 gyro\r\n"); + + int acc_attempts = 0; + int acc_fail = 0; + + while (acc_attempts < 5) + { + acc_fail = bma180_attach(spi1, PX4_SPIDEV_ACCEL); + acc_attempts++; + if (acc_fail == 0) break; + up_udelay(1000); + } + + if (acc_fail) message("[boot] FAILED to attach BMA180 accelerometer\r\n"); + + int mpu_attempts = 0; + int mpu_fail = 0; + + while (mpu_attempts < 1) + { + mpu_fail = mpu6000_attach(spi1, PX4_SPIDEV_MPU); + mpu_attempts++; + if (mpu_fail == 0) break; + up_udelay(200); + } + + if (mpu_fail) message("[boot] FAILED to attach MPU 6000 gyro/acc\r\n"); + + /* initialize I2C2 bus */ + + i2c2 = up_i2cinitialize(2); + if (!i2c2) { + message("[boot] FAILED to initialize I2C bus 2\r\n"); + up_ledon(LED_AMBER); + return -ENODEV; + } + + /* set I2C2 speed */ + I2C_SETFREQUENCY(i2c2, 400000); + + + i2c3 = up_i2cinitialize(3); + if (!i2c3) { + message("[boot] FAILED to initialize I2C bus 3\r\n"); + up_ledon(LED_AMBER); + return -ENODEV; + } + + /* set I2C3 speed */ + I2C_SETFREQUENCY(i2c3, 400000); + + int mag_attempts = 0; + int mag_fail = 0; + + while (mag_attempts < 5) + { + mag_fail = hmc5883l_attach(i2c2); + mag_attempts++; + if (mag_fail == 0) break; + up_udelay(1000); + } + + if (mag_fail) message("[boot] FAILED to attach HMC5883L magnetometer\r\n"); + + int baro_attempts = 0; + int baro_fail = 0; + while (baro_attempts < 5) + { + baro_fail = ms5611_attach(i2c2); + baro_attempts++; + if (baro_fail == 0) break; + up_udelay(1000); + } + + if (baro_fail) message("[boot] FAILED to attach MS5611 baro at addr #1 or #2 (0x76 or 0x77)\r\n"); + + /* try to attach, don't fail if device is not responding */ + (void)eeprom_attach(i2c3, FMU_BASEBOARD_EEPROM_ADDRESS, + FMU_BASEBOARD_EEPROM_TOTAL_SIZE_BYTES, + FMU_BASEBOARD_EEPROM_PAGE_SIZE_BYTES, + FMU_BASEBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/baseboard_eeprom", 1); + + int eeprom_attempts = 0; + int eeprom_fail; + while (eeprom_attempts < 5) + { + /* try to attach, fail if device does not respond */ + eeprom_fail = eeprom_attach(i2c2, FMU_ONBOARD_EEPROM_ADDRESS, + FMU_ONBOARD_EEPROM_TOTAL_SIZE_BYTES, + FMU_ONBOARD_EEPROM_PAGE_SIZE_BYTES, + FMU_ONBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/eeprom", 1); + eeprom_attempts++; + if (eeprom_fail == OK) break; + up_udelay(1000); + } + + if (eeprom_fail) message("[boot] FAILED to attach FMU EEPROM\r\n"); + + /* Report back sensor status */ + if (acc_fail || gyro_fail || mag_fail || baro_fail || eeprom_fail) + { + up_ledon(LED_AMBER); + } + +#if defined(CONFIG_STM32_SPI3) + /* Get the SPI port */ + + message("[boot] Initializing SPI port 3\r\n"); + spi3 = up_spiinitialize(3); + if (!spi3) + { + message("[boot] FAILED to initialize SPI port 3\r\n"); + up_ledon(LED_AMBER); + return -ENODEV; + } + message("[boot] Successfully initialized SPI port 3\r\n"); + + /* Now bind the SPI interface to the MMCSD driver */ + result = mmcsd_spislotinitialize(CONFIG_NSH_MMCSDMINOR, CONFIG_NSH_MMCSDSLOTNO, spi3); + if (result != OK) + { + message("[boot] FAILED to bind SPI port 3 to the MMCSD driver\r\n"); + up_ledon(LED_AMBER); + return -ENODEV; + } + message("[boot] Successfully bound SPI port 3 to the MMCSD driver\r\n"); +#endif /* SPI3 */ + + /* initialize I2C1 bus */ + + i2c1 = up_i2cinitialize(1); + if (!i2c1) { + message("[boot] FAILED to initialize I2C bus 1\r\n"); + up_ledon(LED_AMBER); + return -ENODEV; + } + + /* set I2C1 speed */ + I2C_SETFREQUENCY(i2c1, 400000); + + /* INIT 3: MULTIPORT-DEPENDENT INITIALIZATION */ + + /* Get board information if available */ + + /* Initialize the user GPIOs */ + px4fmu_gpio_init(); + +#ifdef CONFIG_ADC + int adc_state = adc_devinit(); + if (adc_state != OK) + { + /* Try again */ + adc_state = adc_devinit(); + if (adc_state != OK) + { + /* Give up */ + message("[boot] FAILED adc_devinit: %d\r\n", adc_state); + return -ENODEV; + } + } +#endif + + /* configure the tone generator */ +#ifdef CONFIG_TONE_ALARM + tone_alarm_init(); +#endif + + return OK; +} diff --git a/nuttx/configs/px4fmu/src/up_pwm_servo.c b/nuttx/configs/px4fmu/src/up_pwm_servo.c new file mode 100644 index 0000000000..05daf1e97c --- /dev/null +++ b/nuttx/configs/px4fmu/src/up_pwm_servo.c @@ -0,0 +1,344 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * Servo driver supporting PWM servos connected to STM32 timer blocks. + * + * Works with any of the 'generic' or 'advanced' STM32 timers that + * have output pins, does not require an interrupt. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "chip.h" +#include "up_internal.h" +#include "up_arch.h" + +#include "stm32_internal.h" +#include "stm32_gpio.h" +#include "stm32_tim.h" + +/* configuration limits */ +#define PWM_SERVO_MAX_TIMERS 2 +#define PWM_SERVO_MAX_CHANNELS 8 + +/* default rate (in Hz) of PWM updates */ +static uint32_t pwm_update_rate = 50; + +/* + * Servo configuration for all of the pins that can be used as + * PWM outputs on FMU. + */ + +/* array of timers dedicated to PWM servo use */ +static const struct pwm_servo_timer { + uint32_t base; + uint32_t clock_register; + uint32_t clock_bit; + uint32_t clock_freq; +} pwm_timers[] = { + { + .base = STM32_TIM2_BASE, + .clock_register = STM32_RCC_APB1ENR, + .clock_bit = RCC_APB1ENR_TIM2EN, + .clock_freq = STM32_APB1_TIM2_CLKIN + } +}; + +/* array of channels in logical order */ +static const struct pwm_servo_channel { + uint32_t gpio; + uint8_t timer_index; + uint8_t timer_channel; + servo_position_t default_value; +} pwm_channels[] = { + { + .gpio = GPIO_TIM2_CH1OUT, + .timer_index = 0, + .timer_channel = 1, + .default_value = 1000, + }, + { + .gpio = GPIO_TIM2_CH2OUT, + .timer_index = 0, + .timer_channel = 2, + .default_value = 1000, + }, + { + .gpio = GPIO_TIM2_CH3OUT, + .timer_index = 0, + .timer_channel = 3, + .default_value = 1000, + }, + { + .gpio = GPIO_TIM2_CH4OUT, + .timer_index = 0, + .timer_channel = 4, + .default_value = 1000, + } +}; + + +#define REG(_tmr, _reg) (*(volatile uint32_t *)(pwm_timers[_tmr].base + _reg)) + +#define rCR1(_tmr) REG(_tmr, STM32_GTIM_CR1_OFFSET) +#define rCR2(_tmr) REG(_tmr, STM32_GTIM_CR2_OFFSET) +#define rSMCR(_tmr) REG(_tmr, STM32_GTIM_SMCR_OFFSET) +#define rDIER(_tmr) REG(_tmr, STM32_GTIM_DIER_OFFSET) +#define rSR(_tmr) REG(_tmr, STM32_GTIM_SR_OFFSET) +#define rEGR(_tmr) REG(_tmr, STM32_GTIM_EGR_OFFSET) +#define rCCMR1(_tmr) REG(_tmr, STM32_GTIM_CCMR1_OFFSET) +#define rCCMR2(_tmr) REG(_tmr, STM32_GTIM_CCMR2_OFFSET) +#define rCCER(_tmr) REG(_tmr, STM32_GTIM_CCER_OFFSET) +#define rCNT(_tmr) REG(_tmr, STM32_GTIM_CNT_OFFSET) +#define rPSC(_tmr) REG(_tmr, STM32_GTIM_PSC_OFFSET) +#define rARR(_tmr) REG(_tmr, STM32_GTIM_ARR_OFFSET) +#define rCCR1(_tmr) REG(_tmr, STM32_GTIM_CCR1_OFFSET) +#define rCCR2(_tmr) REG(_tmr, STM32_GTIM_CCR2_OFFSET) +#define rCCR3(_tmr) REG(_tmr, STM32_GTIM_CCR3_OFFSET) +#define rCCR4(_tmr) REG(_tmr, STM32_GTIM_CCR4_OFFSET) +#define rDCR(_tmr) REG(_tmr, STM32_GTIM_DCR_OFFSET) +#define rDMAR(_tmr) REG(_tmr, STM32_GTIM_DMAR_OFFSET) + +static void +pwm_timer_init(unsigned timer) +{ + /* enable the timer clock before we try to talk to it */ + modifyreg32(pwm_timers[timer].clock_register, 0, pwm_timers[timer].clock_bit); + + /* disable and configure the timer */ + rCR1(timer) = 0; + rCR2(timer) = 0; + rSMCR(timer) = 0; + rDIER(timer) = 0; + rCCER(timer) = 0; + rCCMR1(timer) = 0; + rCCMR2(timer) = 0; + rCCER(timer) = 0; + rDCR(timer) = 0; + + /* configure the timer to free-run at 1MHz */ + rPSC(timer) = pwm_timers[timer].clock_freq / 1000000; + + /* and update at the desired rate */ + rARR(timer) = 1000000 / pwm_update_rate; + + /* generate an update event; reloads the counter and all registers */ + rEGR(timer) = GTIM_EGR_UG; + + /* note that the timer is left disabled - arming is performed separately */ +} + +static void +pwm_timer_set_rate(unsigned timer, unsigned rate) +{ + /* configure the timer to update at the desired rate */ + rARR(timer) = 1000000 / pwm_update_rate; + + /* generate an update event; reloads the counter and all registers */ + rEGR(timer) = GTIM_EGR_UG; +} + +static void +pwm_channel_init(unsigned channel) +{ + unsigned timer = pwm_channels[channel].timer_index; + + /* configure the GPIO first */ + stm32_configgpio(pwm_channels[channel].gpio); + + /* configure the channel */ + switch (pwm_channels[channel].timer_channel) { + case 1: + rCCMR1(timer) |= (6 << 4); + rCCR1(timer) = pwm_channels[channel].default_value; + rCCER(timer) |= (1 << 0); + break; + case 2: + rCCMR1(timer) |= (6 << 12); + rCCR2(timer) = pwm_channels[channel].default_value; + rCCER(timer) |= (1 << 4); + break; + case 3: + rCCMR2(timer) |= (6 << 4); + rCCR3(timer) = pwm_channels[channel].default_value; + rCCER(timer) |= (1 << 8); + break; + case 4: + rCCMR2(timer) |= (6 << 12); + rCCR4(timer) = pwm_channels[channel].default_value; + rCCER(timer) |= (1 << 12); + break; + } +} + +int +up_pwm_servo_set(unsigned channel, servo_position_t value) +{ + if (channel >= PWM_SERVO_MAX_CHANNELS) { + lldbg("pwm_channel_set: bogus channel %u\n", channel); + return -1; + } + + unsigned timer = pwm_channels[channel].timer_index; + + /* test timer for validity */ + if ((pwm_timers[timer].base == 0) || + (pwm_channels[channel].gpio == 0)) + return -1; + + /* configure the channel */ + switch (pwm_channels[channel].timer_channel) { + case 1: + rCCR1(timer) = value; + break; + case 2: + rCCR2(timer) = value; + break; + case 3: + rCCR3(timer) = value; + break; + case 4: + rCCR4(timer) = value; + break; + default: + return -1; + } + return 0; +} + +servo_position_t +up_pwm_servo_get(unsigned channel) +{ + if (channel >= PWM_SERVO_MAX_CHANNELS) { + lldbg("pwm_channel_get: bogus channel %u\n", channel); + return 0; + } + + unsigned timer = pwm_channels[channel].timer_index; + servo_position_t value = 0; + + /* test timer for validity */ + if ((pwm_timers[timer].base == 0) || + (pwm_channels[channel].gpio == 0)) + return 0; + + /* configure the channel */ + switch (pwm_channels[channel].timer_channel) { + case 1: + value = rCCR1(timer); + break; + case 2: + value = rCCR2(timer); + break; + case 3: + value = rCCR3(timer); + break; + case 4: + value = rCCR4(timer); + break; + } + return value; +} + +int +up_pwm_servo_init(uint32_t channel_mask) +{ + /* do basic timer initialisation first */ + for (unsigned i = 0; i < PWM_SERVO_MAX_TIMERS; i++) { + if (pwm_timers[i].base != 0) + pwm_timer_init(i); + } + + /* now init channels */ + for (unsigned i = 0; i < PWM_SERVO_MAX_CHANNELS; i++) { + /* don't do init for disabled channels; this leaves the pin configs alone */ + if (((1< 400)) + return -ERANGE; + + for (unsigned i = 0; i < PWM_SERVO_MAX_TIMERS; i++) { + if (pwm_timers[i].base != 0) + pwm_timer_set_rate(i, rate); + } + return OK; +} + +void +up_pwm_servo_arm(bool armed) +{ + /* + * XXX this is inelgant and in particular will either jam outputs at whatever level + * they happen to be at at the time the timers stop or generate runts. + * The right thing is almost certainly to kill auto-reload on the timers so that + * they just stop at the end of their count for disable, and to reset/restart them + * for enable. + */ + + /* iterate timers and arm/disarm appropriately */ + for (unsigned i = 0; i < PWM_SERVO_MAX_TIMERS; i++) { + if (pwm_timers[i].base != 0) + rCR1(i) = armed ? GTIM_CR1_CEN : 0; + } +} diff --git a/nuttx/configs/px4fmu/src/up_spi.c b/nuttx/configs/px4fmu/src/up_spi.c new file mode 100644 index 0000000000..ea34c30ce1 --- /dev/null +++ b/nuttx/configs/px4fmu/src/up_spi.c @@ -0,0 +1,192 @@ +/************************************************************************************ + * configs/px4fmu/src/up_spi.c + * arch/arm/src/board/up_spi.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "chip.h" +#include "stm32_internal.h" +#include "px4fmu-internal.h" + +#if defined(CONFIG_STM32_SPI1) || defined(CONFIG_STM32_SPI2) || defined(CONFIG_STM32_SPI3) + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/* Enables debug output from this file (needs CONFIG_DEBUG too) */ + +#undef SPI_DEBUG /* Define to enable debug */ +#undef SPI_VERBOSE /* Define to enable verbose debug */ + +#ifdef SPI_DEBUG +# define spidbg lldbg +# ifdef SPI_VERBOSE +# define spivdbg lldbg +# else +# define spivdbg(x...) +# endif +#else +# undef SPI_VERBOSE +# define spidbg(x...) +# define spivdbg(x...) +#endif + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_spiinitialize + * + * Description: + * Called to configure SPI chip select GPIO pins for the PX4FMU board. + * + ************************************************************************************/ + +void weak_function stm32_spiinitialize(void) +{ + stm32_configgpio(GPIO_SPI_CS_GYRO); + stm32_configgpio(GPIO_SPI_CS_ACCEL); + stm32_configgpio(GPIO_SPI_CS_MPU); + stm32_configgpio(GPIO_SPI_CS_SDCARD); + + /* De-activate all peripherals, + * required for some peripheral + * state machines + */ + stm32_gpiowrite(GPIO_SPI_CS_GYRO, 1); + stm32_gpiowrite(GPIO_SPI_CS_ACCEL, 1); + stm32_gpiowrite(GPIO_SPI_CS_MPU, 1); + stm32_gpiowrite(GPIO_SPI_CS_SDCARD, 1); +} + +/**************************************************************************** + * Name: stm32_spi1/2/3select and stm32_spi1/2/3status + * + * Description: + * The external functions, stm32_spi1/2/3select and stm32_spi1/2/3status must be + * provided by board-specific logic. They are implementations of the select + * and status methods of the SPI interface defined by struct spi_ops_s (see + * include/nuttx/spi.h). All other methods (including up_spiinitialize()) + * are provided by common STM32 logic. To use this common SPI logic on your + * board: + * + * 1. Provide logic in stm32_boardinitialize() to configure SPI chip select + * pins. + * 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your + * board-specific logic. These functions will perform chip selection and + * status operations using GPIOs in the way your board is configured. + * 3. Add a calls to up_spiinitialize() in your low level application + * initialization logic + * 4. The handle returned by up_spiinitialize() may then be used to bind the + * SPI driver to higher level logic (e.g., calling + * mmcsd_spislotinitialize(), for example, will bind the SPI driver to + * the SPI MMC/SD driver). + * + ****************************************************************************/ + +#ifdef CONFIG_STM32_SPI1 +void stm32_spi1select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected) +{ + spidbg("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert"); + + /* SPI select is active low, so write !selected to select the device */ + + switch (devid) { + case PX4_SPIDEV_GYRO: + /* Making sure the other peripherals are not selected */ + stm32_gpiowrite(GPIO_SPI_CS_GYRO, !selected); + stm32_gpiowrite(GPIO_SPI_CS_MPU, selected); + stm32_gpiowrite(GPIO_SPI_CS_ACCEL, selected); + break; + case PX4_SPIDEV_ACCEL: + /* Making sure the other peripherals are not selected */ + stm32_gpiowrite(GPIO_SPI_CS_ACCEL, !selected); + stm32_gpiowrite(GPIO_SPI_CS_MPU, selected); + stm32_gpiowrite(GPIO_SPI_CS_GYRO, selected); + break; + case PX4_SPIDEV_MPU: + /* Making sure the other peripherals are not selected */ + stm32_gpiowrite(GPIO_SPI_CS_ACCEL, selected); + stm32_gpiowrite(GPIO_SPI_CS_GYRO, selected); + stm32_gpiowrite(GPIO_SPI_CS_MPU, !selected); + break; + default: + spidbg("devid: %d - unexpected\n", devid); + break; + + } +} + +uint8_t stm32_spi1status(FAR struct spi_dev_s *dev, enum spi_dev_e devid) +{ + return SPI_STATUS_PRESENT; +} +#endif + +#ifdef CONFIG_STM32_SPI3 +void stm32_spi3select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected) +{ + spidbg("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert"); + + /* there can only be one device on this bus, so always select it */ + stm32_gpiowrite(GPIO_SPI_CS_SDCARD, 0); +} + +uint8_t stm32_spi3status(FAR struct spi_dev_s *dev, enum spi_dev_e devid) +{ + /* this is actually bogus, but PX4 has no way to sense the presence of an SD card */ + return SPI_STATUS_PRESENT; +} +#endif + +#endif /* CONFIG_STM32_SPI1 || CONFIG_STM32_SPI2 */ diff --git a/nuttx/configs/px4fmu/src/up_usbdev.c b/nuttx/configs/px4fmu/src/up_usbdev.c new file mode 100644 index 0000000000..4ef105e91c --- /dev/null +++ b/nuttx/configs/px4fmu/src/up_usbdev.c @@ -0,0 +1,105 @@ +/************************************************************************************ + * configs/stm32f4discovery/src/up_usbdev.c + * arch/arm/src/board/up_boot.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "stm32_internal.h" +#include "px4fmu-internal.h" + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_usbinitialize + * + * Description: + * Called to setup USB-related GPIO pins for the STM3210E-EVAL board. + * + ************************************************************************************/ + +void stm32_usbinitialize(void) +{ + /* The OTG FS has an internal soft pull-up */ + + /* Configure the OTG FS VBUS sensing GPIO, Power On, and Overcurrent GPIOs */ + +#ifdef CONFIG_STM32_OTGFS + stm32_configgpio(GPIO_OTGFS_VBUS); + /* XXX We only support device mode + stm32_configgpio(GPIO_OTGFS_PWRON); + stm32_configgpio(GPIO_OTGFS_OVER); + */ +#endif +} + +/************************************************************************************ + * Name: stm32_usbsuspend + * + * Description: + * Board logic must provide the stm32_usbsuspend logic if the USBDEV driver is + * used. This function is called whenever the USB enters or leaves suspend mode. + * This is an opportunity for the board logic to shutdown clocks, power, etc. + * while the USB is suspended. + * + ************************************************************************************/ + +void stm32_usbsuspend(FAR struct usbdev_s *dev, bool resume) +{ + ulldbg("resume: %d\n", resume); +} + diff --git a/nuttx/configs/px4io/README.txt b/nuttx/configs/px4io/README.txt new file mode 100755 index 0000000000..9b1615f42d --- /dev/null +++ b/nuttx/configs/px4io/README.txt @@ -0,0 +1,806 @@ +README +====== + +This README discusses issues unique to NuttX configurations for the +STMicro STM3210E-EVAL development board. + +Contents +======== + + - Development Environment + - GNU Toolchain Options + - IDEs + - NuttX buildroot Toolchain + - DFU and JTAG + - OpenOCD + - LEDs + - Temperature Sensor + - RTC + - STM3210E-EVAL-specific Configuration Options + - Configurations + +Development Environment +======================= + + Either Linux or Cygwin on Windows can be used for the development environment. + The source has been built only using the GNU toolchain (see below). Other + toolchains will likely cause problems. Testing was performed using the Cygwin + environment because the Raisonance R-Link emulatator and some RIDE7 development tools + were used and those tools works only under Windows. + +GNU Toolchain Options +===================== + + The NuttX make system has been modified to support the following different + toolchain options. + + 1. The CodeSourcery GNU toolchain, + 2. The devkitARM GNU toolchain, + 3. Raisonance GNU toolchain, or + 4. The NuttX buildroot Toolchain (see below). + + All testing has been conducted using the NuttX buildroot toolchain. However, + the make system is setup to default to use the devkitARM toolchain. To use + the CodeSourcery, devkitARM or Raisonance GNU toolchain, you simply need to + add one of the following configuration options to your .config (or defconfig) + file: + + CONFIG_STM32_CODESOURCERYW=y : CodeSourcery under Windows + CONFIG_STM32_CODESOURCERYL=y : CodeSourcery under Linux + CONFIG_STM32_DEVKITARM=y : devkitARM under Windows + CONFIG_STM32_RAISONANCE=y : Raisonance RIDE7 under Windows + CONFIG_STM32_BUILDROOT=y : NuttX buildroot under Linux or Cygwin (default) + + If you are not using CONFIG_STM32_BUILDROOT, then you may also have to modify + the PATH in the setenv.h file if your make cannot find the tools. + + NOTE: the CodeSourcery (for Windows), devkitARM, and Raisonance toolchains are + Windows native toolchains. The CodeSourcey (for Linux) and NuttX buildroot + toolchains are Cygwin and/or Linux native toolchains. There are several limitations + to using a Windows based toolchain in a Cygwin environment. The three biggest are: + + 1. The Windows toolchain cannot follow Cygwin paths. Path conversions are + performed automatically in the Cygwin makefiles using the 'cygpath' utility + but you might easily find some new path problems. If so, check out 'cygpath -w' + + 2. Windows toolchains cannot follow Cygwin symbolic links. Many symbolic links + are used in Nuttx (e.g., include/arch). The make system works around these + problems for the Windows tools by copying directories instead of linking them. + But this can also cause some confusion for you: For example, you may edit + a file in a "linked" directory and find that your changes had no effect. + That is because you are building the copy of the file in the "fake" symbolic + directory. If you use a Windows toolchain, you should get in the habit of + making like this: + + make clean_context all + + An alias in your .bashrc file might make that less painful. + + 3. Dependencies are not made when using Windows versions of the GCC. This is + because the dependencies are generated using Windows pathes which do not + work with the Cygwin make. + + Support has been added for making dependencies with the windows-native toolchains. + That support can be enabled by modifying your Make.defs file as follows: + + - MKDEP = $(TOPDIR)/tools/mknulldeps.sh + + MKDEP = $(TOPDIR)/tools/mkdeps.sh --winpaths "$(TOPDIR)" + + If you have problems with the dependency build (for example, if you are not + building on C:), then you may need to modify tools/mkdeps.sh + + NOTE 1: The CodeSourcery toolchain (2009q1) does not work with default optimization + level of -Os (See Make.defs). It will work with -O0, -O1, or -O2, but not with + -Os. + + NOTE 2: The devkitARM toolchain includes a version of MSYS make. Make sure that + the paths to Cygwin's /bin and /usr/bin directories appear BEFORE the devkitARM + path or will get the wrong version of make. + +IDEs +==== + + NuttX is built using command-line make. It can be used with an IDE, but some + effort will be required to create the project (There is a simple RIDE project + in the RIDE subdirectory). + + Makefile Build + -------------- + Under Eclipse, it is pretty easy to set up an "empty makefile project" and + simply use the NuttX makefile to build the system. That is almost for free + under Linux. Under Windows, you will need to set up the "Cygwin GCC" empty + makefile project in order to work with Windows (Google for "Eclipse Cygwin" - + there is a lot of help on the internet). + + Native Build + ------------ + Here are a few tips before you start that effort: + + 1) Select the toolchain that you will be using in your .config file + 2) Start the NuttX build at least one time from the Cygwin command line + before trying to create your project. This is necessary to create + certain auto-generated files and directories that will be needed. + 3) Set up include pathes: You will need include/, arch/arm/src/stm32, + arch/arm/src/common, arch/arm/src/armv7-m, and sched/. + 4) All assembly files need to have the definition option -D __ASSEMBLY__ + on the command line. + + Startup files will probably cause you some headaches. The NuttX startup file + is arch/arm/src/stm32/stm32_vectors.S. With RIDE, I have to build NuttX + one time from the Cygwin command line in order to obtain the pre-built + startup object needed by RIDE. + +NuttX buildroot Toolchain +========================= + + A GNU GCC-based toolchain is assumed. The files */setenv.sh should + be modified to point to the correct path to the Cortex-M3 GCC toolchain (if + different from the default in your PATH variable). + + If you have no Cortex-M3 toolchain, one can be downloaded from the NuttX + SourceForge download site (https://sourceforge.net/project/showfiles.php?group_id=189573). + This GNU toolchain builds and executes in the Linux or Cygwin environment. + + 1. You must have already configured Nuttx in /nuttx. + + cd tools + ./configure.sh stm3210e-eval/ + + 2. Download the latest buildroot package into + + 3. unpack the buildroot tarball. The resulting directory may + have versioning information on it like buildroot-x.y.z. If so, + rename /buildroot-x.y.z to /buildroot. + + 4. cd /buildroot + + 5. cp configs/cortexm3-defconfig-4.3.3 .config + + 6. make oldconfig + + 7. make + + 8. Edit setenv.h, if necessary, so that the PATH variable includes + the path to the newly built binaries. + + See the file configs/README.txt in the buildroot source tree. That has more + detailed PLUS some special instructions that you will need to follow if you are + building a Cortex-M3 toolchain for Cygwin under Windows. + +DFU and JTAG +============ + + Enbling Support for the DFU Bootloader + -------------------------------------- + The linker files in these projects can be configured to indicate that you + will be loading code using STMicro built-in USB Device Firmware Upgrade (DFU) + loader or via some JTAG emulator. You can specify the DFU bootloader by + adding the following line: + + CONFIG_STM32_DFU=y + + to your .config file. Most of the configurations in this directory are set + up to use the DFU loader. + + If CONFIG_STM32_DFU is defined, the code will not be positioned at the beginning + of FLASH (0x08000000) but will be offset to 0x08003000. This offset is needed + to make space for the DFU loader and 0x08003000 is where the DFU loader expects + to find new applications at boot time. If you need to change that origin for some + other bootloader, you will need to edit the file(s) ld.script.dfu for each + configuration. + + The DFU SE PC-based software is available from the STMicro website, + http://www.st.com. General usage instructions: + + 1. Convert the NuttX Intel Hex file (nuttx.ihx) into a special DFU + file (nuttx.dfu)... see below for details. + 2. Connect the STM3210E-EVAL board to your computer using a USB + cable. + 3. Start the DFU loader on the STM3210E-EVAL board. You do this by + resetting the board while holding the "Key" button. Windows should + recognize that the DFU loader has been installed. + 3. Run the DFU SE program to load nuttx.dfu into FLASH. + + What if the DFU loader is not in FLASH? The loader code is available + inside of the Demo dirctory of the USBLib ZIP file that can be downloaded + from the STMicro Website. You can build it using RIDE (or other toolchains); + you will need a JTAG emulator to burn it into FLASH the first time. + + In order to use STMicro's built-in DFU loader, you will have to get + the NuttX binary into a special format with a .dfu extension. The + DFU SE PC_based software installation includes a file "DFU File Manager" + conversion program that a file in Intel Hex format to the special DFU + format. When you successfully build NuttX, you will find a file called + nutt.ihx in the top-level directory. That is the file that you should + provide to the DFU File Manager. You will need to rename it to nuttx.hex + in order to find it with the DFU File Manager. You will end up with + a file called nuttx.dfu that you can use with the STMicro DFU SE program. + + Enabling JTAG + ------------- + If you are not using the DFU, then you will probably also need to enable + JTAG support. By default, all JTAG support is disabled but there NuttX + configuration options to enable JTAG in various different ways. + + These configurations effect the setting of the SWJ_CFG[2:0] bits in the AFIO + MAPR register. These bits are used to configure the SWJ and trace alternate function I/Os. The SWJ (SerialWire JTAG) supports JTAG or SWD access to the + Cortex debug port. The default state in this port is for all JTAG support + to be disable. + + CONFIG_STM32_JTAG_FULL_ENABLE - sets SWJ_CFG[2:0] to 000 which enables full + SWJ (JTAG-DP + SW-DP) + + CONFIG_STM32_JTAG_NOJNTRST_ENABLE - sets SWJ_CFG[2:0] to 001 which enable + full SWJ (JTAG-DP + SW-DP) but without JNTRST. + + CONFIG_STM32_JTAG_SW_ENABLE - sets SWJ_CFG[2:0] to 010 which would set JTAG-DP + disabled and SW-DP enabled + + The default setting (none of the above defined) is SWJ_CFG[2:0] set to 100 + which disable JTAG-DP and SW-DP. + +OpenOCD +======= + +I have also used OpenOCD with the STM3210E-EVAL. In this case, I used +the Olimex USB ARM OCD. See the script in configs/stm3210e-eval/tools/oocd.sh +for more information. Using the script: + +1) Start the OpenOCD GDB server + + cd + configs/stm3210e-eval/tools/oocd.sh $PWD + +2) Load Nuttx + + cd + arm-none-eabi-gdb nuttx + gdb> target remote localhost:3333 + gdb> mon reset + gdb> mon halt + gdb> load nuttx + +3) Running NuttX + + gdb> mon reset + gdb> c + +LEDs +==== + +The STM3210E-EVAL board has four LEDs labeled LD1, LD2, LD3 and LD4 on the +board.. These LEDs are not used by the board port unless CONFIG_ARCH_LEDS is +defined. In that case, the usage by the board port is defined in +include/board.h and src/up_leds.c. The LEDs are used to encode OS-related +events as follows: + + SYMBOL Meaning LED1* LED2 LED3 LED4 + ---------------- ----------------------- ----- ----- ----- ----- + LED_STARTED NuttX has been started ON OFF OFF OFF + LED_HEAPALLOCATE Heap has been allocated OFF ON OFF OFF + LED_IRQSENABLED Interrupts enabled ON ON OFF OFF + LED_STACKCREATED Idle stack created OFF OFF ON OFF + LED_INIRQ In an interrupt** ON N/C N/C OFF + LED_SIGNAL In a signal handler*** N/C ON N/C OFF + LED_ASSERTION An assertion failed ON ON N/C OFF + LED_PANIC The system has crashed N/C N/C N/C ON + LED_IDLE STM32 is is sleep mode (Optional, not used) + + * If LED1, LED2, LED3 are statically on, then NuttX probably failed to boot + and these LEDs will give you some indication of where the failure was + ** The normal state is LED3 ON and LED1 faintly glowing. This faint glow + is because of timer interupts that result in the LED being illuminated + on a small proportion of the time. +*** LED2 may also flicker normally if signals are processed. + +Temperature Sensor +================== + +Support for the on-board LM-75 temperature sensor is available. This supported +has been verified, but has not been included in any of the available the +configurations. To set up the temperature sensor, add the following to the +NuttX configuration file + + CONFIG_I2C=y + CONFIG_I2C_LM75=y + +Then you can implement logic like the following to use the temperature sensor: + + #include + #include + + ret = stm32_lm75initialize("/dev/temp"); /* Register the temperature sensor */ + fd = open("/dev/temp", O_RDONLY); /* Open the temperature sensor device */ + ret = ioctl(fd, SNIOC_FAHRENHEIT, 0); /* Select Fahrenheit */ + bytesread = read(fd, buffer, 8*sizeof(b16_t)); /* Read temperature samples */ + +More complex temperature sensor operations are also available. See the IOCTAL +commands enumerated in include/nuttx/sensors/lm75.h. Also read the descriptions +of the stm32_lm75initialize() and stm32_lm75attach() interfaces in the +arch/board/board.h file (sames as configs/stm3210e-eval/include/board.h). + +RTC +=== + + The STM32 RTC may configured using the following settings. + + CONFIG_RTC - Enables general support for a hardware RTC. Specific + architectures may require other specific settings. + CONFIG_RTC_HIRES - The typical RTC keeps time to resolution of 1 + second, usually supporting a 32-bit time_t value. In this case, + the RTC is used to "seed" the normal NuttX timer and the + NuttX timer provides for higher resoution time. If CONFIG_RTC_HIRES + is enabled in the NuttX configuration, then the RTC provides higher + resolution time and completely replaces the system timer for purpose of + date and time. + CONFIG_RTC_FREQUENCY - If CONFIG_RTC_HIRES is defined, then the + frequency of the high resolution RTC must be provided. If CONFIG_RTC_HIRES + is not defined, CONFIG_RTC_FREQUENCY is assumed to be one. + CONFIG_RTC_ALARM - Enable if the RTC hardware supports setting of an alarm. + A callback function will be executed when the alarm goes off + + In hi-res mode, the STM32 RTC operates only at 16384Hz. Overflow interrupts + are handled when the 32-bit RTC counter overflows every 3 days and 43 minutes. + A BKP register is incremented on each overflow interrupt creating, effectively, + a 48-bit RTC counter. + + In the lo-res mode, the RTC operates at 1Hz. Overflow interrupts are not handled + (because the next overflow is not expected until the year 2106. + + WARNING: Overflow interrupts are lost whenever the STM32 is powered down. The + overflow interrupt may be lost even if the STM32 is powered down only momentarily. + Therefore hi-res solution is only useful in systems where the power is always on. + +STM3210E-EVAL-specific Configuration Options +============================================ + + CONFIG_ARCH - Identifies the arch/ subdirectory. This should + be set to: + + CONFIG_ARCH=arm + + CONFIG_ARCH_family - For use in C code: + + CONFIG_ARCH_ARM=y + + CONFIG_ARCH_architecture - For use in C code: + + CONFIG_ARCH_CORTEXM3=y + + CONFIG_ARCH_CHIP - Identifies the arch/*/chip subdirectory + + CONFIG_ARCH_CHIP=stm32 + + CONFIG_ARCH_CHIP_name - For use in C code to identify the exact + chip: + + CONFIG_ARCH_CHIP_STM32F103ZET6 + + CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG - Enables special STM32 clock + configuration features. + + CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG=n + + CONFIG_ARCH_BOARD - Identifies the configs subdirectory and + hence, the board that supports the particular chip or SoC. + + CONFIG_ARCH_BOARD=stm3210e_eval (for the STM3210E-EVAL development board) + + CONFIG_ARCH_BOARD_name - For use in C code + + CONFIG_ARCH_BOARD_STM3210E_EVAL=y + + CONFIG_ARCH_LOOPSPERMSEC - Must be calibrated for correct operation + of delay loops + + CONFIG_ENDIAN_BIG - define if big endian (default is little + endian) + + CONFIG_DRAM_SIZE - Describes the installed DRAM (SRAM in this case): + + CONFIG_DRAM_SIZE=0x00010000 (64Kb) + + CONFIG_DRAM_START - The start address of installed DRAM + + CONFIG_DRAM_START=0x20000000 + + CONFIG_DRAM_END - Last address+1 of installed RAM + + CONFIG_DRAM_END=(CONFIG_DRAM_START+CONFIG_DRAM_SIZE) + + CONFIG_ARCH_IRQPRIO - The STM32F103Z supports interrupt prioritization + + CONFIG_ARCH_IRQPRIO=y + + CONFIG_ARCH_LEDS - Use LEDs to show state. Unique to boards that + have LEDs + + CONFIG_ARCH_INTERRUPTSTACK - This architecture supports an interrupt + stack. If defined, this symbol is the size of the interrupt + stack in bytes. If not defined, the user task stacks will be + used during interrupt handling. + + CONFIG_ARCH_STACKDUMP - Do stack dumps after assertions + + CONFIG_ARCH_LEDS - Use LEDs to show state. Unique to board architecture. + + CONFIG_ARCH_CALIBRATION - Enables some build in instrumentation that + cause a 100 second delay during boot-up. This 100 second delay + serves no purpose other than it allows you to calibratre + CONFIG_ARCH_LOOPSPERMSEC. You simply use a stop watch to measure + the 100 second delay then adjust CONFIG_ARCH_LOOPSPERMSEC until + the delay actually is 100 seconds. + + Individual subsystems can be enabled: + AHB + --- + CONFIG_STM32_DMA1 + CONFIG_STM32_DMA2 + CONFIG_STM32_CRC + CONFIG_STM32_FSMC + CONFIG_STM32_SDIO + + APB1 + ---- + CONFIG_STM32_TIM2 + CONFIG_STM32_TIM3 + CONFIG_STM32_TIM4 + CONFIG_STM32_TIM5 + CONFIG_STM32_TIM6 + CONFIG_STM32_TIM7 + CONFIG_STM32_WWDG + CONFIG_STM32_SPI2 + CONFIG_STM32_SPI4 + CONFIG_STM32_USART2 + CONFIG_STM32_USART3 + CONFIG_STM32_UART4 + CONFIG_STM32_UART5 + CONFIG_STM32_I2C1 + CONFIG_STM32_I2C2 + CONFIG_STM32_USB + CONFIG_STM32_CAN + CONFIG_STM32_BKP + CONFIG_STM32_PWR + CONFIG_STM32_DAC1 + CONFIG_STM32_DAC2 + CONFIG_STM32_USB + + APB2 + ---- + CONFIG_STM32_ADC1 + CONFIG_STM32_ADC2 + CONFIG_STM32_TIM1 + CONFIG_STM32_SPI1 + CONFIG_STM32_TIM8 + CONFIG_STM32_USART1 + CONFIG_STM32_ADC3 + + Timer and I2C devices may need to the following to force power to be applied + unconditionally at power up. (Otherwise, the device is powered when it is + initialized). + + CONFIG_STM32_FORCEPOWER + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. If CONFIG_STM32_TIMn + is defined (as above) then the following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation, ADC conversion, + or DAC conversion. Note that ADC/DAC require two definition: Not only do you have + to assign the timer (n) for used by the ADC or DAC, but then you also have to + configure which ADC or DAC (m) it is assigned to. + + CONFIG_STM32_TIMn_PWM Reserve timer n for use by PWM, n=1,..,8 + CONFIG_STM32_TIMn_ADC Reserve timer n for use by ADC, n=1,..,8 + CONFIG_STM32_TIMn_ADCm Reserve timer n to trigger ADCm, n=1,..,8, m=1,..,3 + CONFIG_STM32_TIMn_DAC Reserve timer n for use by DAC, n=1,..,8 + CONFIG_STM32_TIMn_DACm Reserve timer n to trigger DACm, n=1,..,8, m=1,..,2 + + For each timer that is enabled for PWM usage, we need the following additional + configuration settings: + + CONFIG_STM32_TIMx_CHANNEL - Specifies the timer output channel {1,..,4} + + NOTE: The STM32 timers are each capable of generating different signals on + each of the four channels with different duty cycles. That capability is + not supported by this driver: Only one output channel per timer. + + Alternate pin mappings (should not be used with the STM3210E-EVAL board): + + CONFIG_STM32_TIM1_FULL_REMAP + CONFIG_STM32_TIM1_PARTIAL_REMAP + CONFIG_STM32_TIM2_FULL_REMAP + CONFIG_STM32_TIM2_PARTIAL_REMAP_1 + CONFIG_STM32_TIM2_PARTIAL_REMAP_2 + CONFIG_STM32_TIM3_FULL_REMAP + CONFIG_STM32_TIM3_PARTIAL_REMAP + CONFIG_STM32_TIM4_REMAP + CONFIG_STM32_USART1_REMAP + CONFIG_STM32_USART2_REMAP + CONFIG_STM32_USART3_FULL_REMAP + CONFIG_STM32_USART3_PARTIAL_REMAP + CONFIG_STM32_SPI1_REMAP + CONFIG_STM32_SPI3_REMAP + CONFIG_STM32_I2C1_REMAP + CONFIG_STM32_CAN1_FULL_REMAP + CONFIG_STM32_CAN1_PARTIAL_REMAP + CONFIG_STM32_CAN2_REMAP + + JTAG Enable settings (by default JTAG-DP and SW-DP are disabled): + CONFIG_STM32_JTAG_FULL_ENABLE - Enables full SWJ (JTAG-DP + SW-DP) + CONFIG_STM32_JTAG_NOJNTRST_ENABLE - Enables full SWJ (JTAG-DP + SW-DP) + but without JNTRST. + CONFIG_STM32_JTAG_SW_ENABLE - Set JTAG-DP disabled and SW-DP enabled + + STM32F103Z specific device driver settings + + CONFIG_U[S]ARTn_SERIAL_CONSOLE - selects the USARTn (n=1,2,3) or UART + m (m=4,5) for the console and ttys0 (default is the USART1). + CONFIG_U[S]ARTn_RXBUFSIZE - Characters are buffered as received. + This specific the size of the receive buffer + CONFIG_U[S]ARTn_TXBUFSIZE - Characters are buffered before + being sent. This specific the size of the transmit buffer + CONFIG_U[S]ARTn_BAUD - The configure BAUD of the UART. Must be + CONFIG_U[S]ARTn_BITS - The number of bits. Must be either 7 or 8. + CONFIG_U[S]ARTn_PARTIY - 0=no parity, 1=odd parity, 2=even parity + CONFIG_U[S]ARTn_2STOP - Two stop bits + + CONFIG_STM32_SPI_INTERRUPTS - Select to enable interrupt driven SPI + support. Non-interrupt-driven, poll-waiting is recommended if the + interrupt rate would be to high in the interrupt driven case. + CONFIG_STM32_SPI_DMA - Use DMA to improve SPI transfer performance. + Cannot be used with CONFIG_STM32_SPI_INTERRUPT. + + CONFIG_SDIO_DMA - Support DMA data transfers. Requires CONFIG_STM32_SDIO + and CONFIG_STM32_DMA2. + CONFIG_SDIO_PRI - Select SDIO interrupt prority. Default: 128 + CONFIG_SDIO_DMAPRIO - Select SDIO DMA interrupt priority. + Default: Medium + CONFIG_SDIO_WIDTH_D1_ONLY - Select 1-bit transfer mode. Default: + 4-bit transfer mode. + + STM3210E-EVAL CAN Configuration + + CONFIG_CAN - Enables CAN support (one or both of CONFIG_STM32_CAN1 or + CONFIG_STM32_CAN2 must also be defined) + CONFIG_CAN_EXTID - Enables support for the 29-bit extended ID. Default + Standard 11-bit IDs. + CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages. + Default: 8 + CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests. + Default: 4 + CONFIG_CAN_LOOPBACK - A CAN driver may or may not support a loopback + mode for testing. The STM32 CAN driver does support loopback mode. + CONFIG_CAN1_BAUD - CAN1 BAUD rate. Required if CONFIG_STM32_CAN1 is defined. + CONFIG_CAN2_BAUD - CAN1 BAUD rate. Required if CONFIG_STM32_CAN2 is defined. + CONFIG_CAN_TSEG1 - The number of CAN time quanta in segment 1. Default: 6 + CONFIG_CAN_TSEG2 - the number of CAN time quanta in segment 2. Default: 7 + CONFIG_CAN_REGDEBUG - If CONFIG_DEBUG is set, this will generate an + dump of all CAN registers. + + STM3210E-EVAL LCD Hardware Configuration + + CONFIG_LCD_LANDSCAPE - Define for 320x240 display "landscape" + support. Default is this 320x240 "landscape" orientation + (this setting is informative only... not used). + CONFIG_LCD_PORTRAIT - Define for 240x320 display "portrait" + orientation support. In this orientation, the STM3210E-EVAL's + LCD ribbon cable is at the bottom of the display. Default is + 320x240 "landscape" orientation. + CONFIG_LCD_RPORTRAIT - Define for 240x320 display "reverse + portrait" orientation support. In this orientation, the + STM3210E-EVAL's LCD ribbon cable is at the top of the display. + Default is 320x240 "landscape" orientation. + CONFIG_LCD_BACKLIGHT - Define to support a backlight. + CONFIG_LCD_PWM - If CONFIG_STM32_TIM1 is also defined, then an + adjustable backlight will be provided using timer 1 to generate + various pulse widthes. The granularity of the settings is + determined by CONFIG_LCD_MAXPOWER. If CONFIG_LCD_PWM (or + CONFIG_STM32_TIM1) is not defined, then a simple on/off backlight + is provided. + CONFIG_LCD_RDSHIFT - When reading 16-bit gram data, there appears + to be a shift in the returned data. This value fixes the offset. + Default 5. + + The LCD driver dynamically selects the LCD based on the reported LCD + ID value. However, code size can be reduced by suppressing support for + individual LCDs using: + + CONFIG_STM32_AM240320_DISABLE + CONFIG_STM32_SPFD5408B_DISABLE + CONFIG_STM32_R61580_DISABLE + +Configurations +============== + +Each STM3210E-EVAL configuration is maintained in a sudirectory and +can be selected as follow: + + cd tools + ./configure.sh stm3210e-eval/ + cd - + . ./setenv.sh + +Where is one of the following: + + buttons: + -------- + + Uses apps/examples/buttons to exercise STM3210E-EVAL buttons and + button interrupts. + + CONFIG_STM32_CODESOURCERYW=y : CodeSourcery under Windows + + composite + --------- + + This configuration exercises a composite USB interface consisting + of a CDC/ACM device and a USB mass storage device. This configuration + uses apps/examples/composite. + + nsh and nsh2: + ------------ + Configure the NuttShell (nsh) located at examples/nsh. + + Differences between the two NSH configurations: + + =========== ======================= ================================ + nsh nsh2 + =========== ======================= ================================ + Toolchain: NuttX buildroot for Codesourcery for Windows (1) + Linux or Cygwin (1,2) + ----------- ----------------------- -------------------------------- + Loader: DfuSe DfuSe + ----------- ----------------------- -------------------------------- + Serial Debug output: USART1 Debug output: USART1 + Console: NSH output: USART1 NSH output: USART1 (3) + ----------- ----------------------- -------------------------------- + microSD Yes Yes + Support + ----------- ----------------------- -------------------------------- + FAT FS CONFIG_FAT_LCNAME=y CONFIG_FAT_LCNAME=y + Config CONFIG_FAT_LFN=n CONFIG_FAT_LFN=y (4) + ----------- ----------------------- -------------------------------- + Support for No Yes + Built-in + Apps + ----------- ----------------------- -------------------------------- + Built-in None apps/examples/nx + Apps apps/examples/nxhello + apps/examples/usbstorage (5) + =========== ======================= ================================ + + (1) You will probably need to modify nsh/setenv.sh or nsh2/setenv.sh + to set up the correct PATH variable for whichever toolchain you + may use. + (2) Since DfuSe is assumed, this configuration may only work under + Cygwin without modification. + (3) When any other device other than /dev/console is used for a user + interface, (1) linefeeds (\n) will not be expanded to carriage return + / linefeeds \r\n). You will need to configure your terminal program + to account for this. And (2) input is not automatically echoed so + you will have to turn local echo on. + (4) Microsoft holds several patents related to the design of + long file names in the FAT file system. Please refer to the + details in the top-level COPYING file. Please do not use FAT + long file name unless you are familiar with these patent issues. + (5) When built as an NSH add-on command (CONFIG_EXAMPLES_USBMSC_BUILTIN=y), + Caution should be used to assure that the SD drive is not in use when + the USB storage device is configured. Specifically, the SD driver + should be unmounted like: + + nsh> mount -t vfat /dev/mmcsd0 /mnt/sdcard # Card is mounted in NSH + ... + nsh> umount /mnd/sdcard # Unmount before connecting USB!!! + nsh> msconn # Connect the USB storage device + ... + nsh> msdis # Disconnect USB storate device + nsh> mount -t vfat /dev/mmcsd0 /mnt/sdcard # Restore the mount + + Failure to do this could result in corruption of the SD card format. + + nx: + --- + An example using the NuttX graphics system (NX). This example + focuses on general window controls, movement, mouse and keyboard + input. + + CONFIG_STM32_CODESOURCERYW=y : CodeSourcery under Windows + CONFIG_LCD_RPORTRAIT=y : 240x320 reverse portrait + + nxlines: + ------ + Another example using the NuttX graphics system (NX). This + example focuses on placing lines on the background in various + orientations. + + CONFIG_STM32_CODESOURCERYW=y : CodeSourcery under Windows + CONFIG_LCD_RPORTRAIT=y : 240x320 reverse portrait + + nxtext: + ------ + Another example using the NuttX graphics system (NX). This + example focuses on placing text on the background while pop-up + windows occur. Text should continue to update normally with + or without the popup windows present. + + CONFIG_STM32_BUILDROOT=y : NuttX buildroot under Linux or Cygwin + CONFIG_LCD_RPORTRAIT=y : 240x320 reverse portrait + + NOTE: When I tried building this example with the CodeSourcery + tools, I got a hardfault inside of its libgcc. I haven't + retested since then, but beware if you choose to change the + toolchain. + + ostest: + ------ + This configuration directory, performs a simple OS test using + examples/ostest. By default, this project assumes that you are + using the DFU bootloader. + + CONFIG_STM32_BUILDROOT=y : NuttX buildroot under Linux or Cygwin + + RIDE + ---- + This configuration builds a trivial bring-up binary. It is + useful only because it words with the RIDE7 IDE and R-Link debugger. + + CONFIG_STM32_RAISONANCE=y : Raisonance RIDE7 under Windows + + usbserial: + --------- + This configuration directory exercises the USB serial class + driver at examples/usbserial. See examples/README.txt for + more information. + + CONFIG_STM32_BUILDROOT=y : NuttX buildroot under Linux or Cygwin + + USB debug output can be enabled as by changing the following + settings in the configuration file: + + -CONFIG_DEBUG=n + -CONFIG_DEBUG_VERBOSE=n + -CONFIG_DEBUG_USB=n + +CONFIG_DEBUG=y + +CONFIG_DEBUG_VERBOSE=y + +CONFIG_DEBUG_USB=y + + -CONFIG_EXAMPLES_USBSERIAL_TRACEINIT=n + -CONFIG_EXAMPLES_USBSERIAL_TRACECLASS=n + -CONFIG_EXAMPLES_USBSERIAL_TRACETRANSFERS=n + -CONFIG_EXAMPLES_USBSERIAL_TRACECONTROLLER=n + -CONFIG_EXAMPLES_USBSERIAL_TRACEINTERRUPTS=n + +CONFIG_EXAMPLES_USBSERIAL_TRACEINIT=y + +CONFIG_EXAMPLES_USBSERIAL_TRACECLASS=y + +CONFIG_EXAMPLES_USBSERIAL_TRACETRANSFERS=y + +CONFIG_EXAMPLES_USBSERIAL_TRACECONTROLLER=y + +CONFIG_EXAMPLES_USBSERIAL_TRACEINTERRUPTS=y + + By default, the usbserial example uses the Prolific PL2303 + serial/USB converter emulation. The example can be modified + to use the CDC/ACM serial class by making the following changes + to the configuration file: + + -CONFIG_PL2303=y + +CONFIG_PL2303=n + + -CONFIG_CDCACM=n + +CONFIG_CDCACM=y + + The example can also be converted to use the alternative + USB serial example at apps/examples/usbterm by changing the + following: + + -CONFIGURED_APPS += examples/usbserial + +CONFIGURED_APPS += examples/usbterm + + In either the original appconfig file (before configuring) + or in the final apps/.config file (after configuring). + + usbstorage: + ---------- + This configuration directory exercises the USB mass storage + class driver at examples/usbstorage. See examples/README.txt for + more information. + + CONFIG_STM32_BUILDROOT=y : NuttX buildroot under Linux or Cygwin + diff --git a/nuttx/configs/px4io/common/Make.defs b/nuttx/configs/px4io/common/Make.defs new file mode 100644 index 0000000000..a3996a9ed3 --- /dev/null +++ b/nuttx/configs/px4io/common/Make.defs @@ -0,0 +1,209 @@ +############################################################################ +# configs/px4fmu/common/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Generic Make.defs for the PX4FMU +# Do not specify/use this file directly - it is included by config-specific +# Make.defs in the per-config directories. +# + +# +# We only support building with the ARM bare-metal toolchain from +# https://launchpad.net/gcc-arm-embedded on Windows, Linux or Mac OS. +# + +CROSSDEV = arm-none-eabi- + +CC = $(CROSSDEV)gcc +CXX = $(CROSSDEV)g++ +CPP = $(CROSSDEV)gcc -E +LD = $(CROSSDEV)ld +AR = $(CROSSDEV)ar rcs +NM = $(CROSSDEV)nm +OBJCOPY = $(CROSSDEV)objcopy +OBJDUMP = $(CROSSDEV)objdump + +MAXOPTIMIZATION = -O3 +ARCHCPUFLAGS = -mcpu=cortex-m3 \ + -mthumb \ + -march=armv7-m + +# enable precise stack overflow tracking +#INSTRUMENTATIONDEFINES = -finstrument-functions \ +# -ffixed-r10 + +# use our linker script +LDSCRIPT = ld.script + +ifeq ($(WINTOOL),y) + # Windows-native toolchains + DIRLINK = $(TOPDIR)/tools/winlink.sh + DIRUNLINK = $(TOPDIR)/tools/unlink.sh + MKDEP = $(TOPDIR)/tools/mknulldeps.sh + ARCHINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" + ARCHXXINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" -isystem "${shell cygpath -w $(TOPDIR)/include/cxx}" + ARCHSCRIPT = -T "${shell cygpath -w $(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/common/$(LDSCRIPT)}" +else + ifeq ($(PX4_WINTOOL),y) + # Windows-native toolchains (MSYS) + DIRLINK = $(TOPDIR)/tools/winlink.sh + DIRUNLINK = $(TOPDIR)/tools/unlink.sh + MKDEP = $(TOPDIR)/tools/mknulldeps.sh + ARCHINCLUDES = -I. -isystem $(TOPDIR)/include + ARCHXXINCLUDES = -I. -isystem $(TOPDIR)/include -isystem $(TOPDIR)/include/cxx + ARCHSCRIPT = -T$(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/common/$(LDSCRIPT) + else + # Linux/Cygwin-native toolchain + MKDEP = $(TOPDIR)/tools/mkdeps.sh + ARCHINCLUDES = -I. -isystem $(TOPDIR)/include + ARCHXXINCLUDES = -I. -isystem $(TOPDIR)/include -isystem $(TOPDIR)/include/cxx + ARCHSCRIPT = -T$(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/common/$(LDSCRIPT) + endif +endif + +# tool versions +ARCHCCVERSION = ${shell $(CC) -v 2>&1 | sed -n '/^gcc version/p' | sed -e 's/^gcc version \([0-9\.]\)/\1/g' -e 's/[-\ ].*//g' -e '1q'} +ARCHCCMAJOR = ${shell echo $(ARCHCCVERSION) | cut -d'.' -f1} + +# optimisation flags +ARCHOPTIMIZATION = $(MAXOPTIMIZATION) \ + -fno-strict-aliasing \ + -fno-strength-reduce \ + -fomit-frame-pointer \ + -funsafe-math-optimizations \ + -fno-builtin-printf \ + -ffunction-sections \ + -fdata-sections + +ifeq ("${CONFIG_DEBUG_SYMBOLS}","y") +ARCHOPTIMIZATION += -g +ARCHSCRIPT += -g +endif + +ARCHCFLAGS = -std=gnu99 +ARCHCXXFLAGS = -fno-exceptions -fno-rtti -std=gnu++0x +ARCHWARNINGS = -Wall \ + -Wextra \ + -Wdouble-promotion \ + -Wshadow \ + -Wfloat-equal \ + -Wframe-larger-than=1024 \ + -Wpointer-arith \ + -Wlogical-op \ + -Wmissing-declarations \ + -Wpacked \ + -Wno-unused-parameter +# -Wcast-qual - generates spurious noreturn attribute warnings, try again later +# -Wconversion - would be nice, but too many "risky-but-safe" conversions in the code +# -Wcast-align - would help catch bad casts in some cases, but generates too many false positives + +ARCHCWARNINGS = $(ARCHWARNINGS) \ + -Wbad-function-cast \ + -Wstrict-prototypes \ + -Wold-style-declaration \ + -Wmissing-parameter-type \ + -Wmissing-prototypes \ + -Wnested-externs \ + -Wunsuffixed-float-constants +ARCHWARNINGSXX = $(ARCHWARNINGS) +ARCHDEFINES = +ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10 + +# this seems to be the only way to add linker flags +ARCHSCRIPT += --warn-common \ + --gc-sections + +CFLAGS = $(ARCHCFLAGS) $(ARCHCWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(INSTRUMENTATIONDEFINES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe -fno-common +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(INSTRUMENTATIONDEFINES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS = $(ARCHINCLUDES) $(INSTRUMENTATIONDEFINES) $(ARCHDEFINES) $(EXTRADEFINES) +AFLAGS = $(CFLAGS) -D__ASSEMBLY__ + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 + +OBJEXT = .o +LIBEXT = .a +EXEEXT = + +# If VERBOSE is set, don't hide the compiler invocations. +ifeq ($(VERBOSE),YES) +_v = +else +_v = @ +endif + +define PREPROCESS + @echo "CPP: $1->$2" + @$(CPP) $(CPPFLAGS) $(abspath $1) -o $2 +endef + +define COMPILE + @echo "CC: $1" + $(_v)$(CC) -c $(CFLAGS) $(abspath $1) -o $2 +endef + +define COMPILEXX + @echo "CXX: $1" + $(_v)$(CXX) -c $(CXXFLAGS) $(abspath $1) -o $2 +endef + +define ASSEMBLE + @echo "AS: $1" + $(_v)$(CC) -c $(AFLAGS) $(abspath $1) -o $2 +endef + +# produce partially-linked $1 from files in $2 +define PRELINK + @echo "PRELINK: $1" + @$(LD) -Ur -o $1 $2 && $(OBJCOPY) --localize-hidden $1 +endef + +define ARCHIVE + echo "AR: $2"; \ + $(AR) $1 $2 || { echo "$(AR) $1 $2 FAILED!" ; exit 1 ; } +endef + +define CLEAN + @rm -f *.o *.a +endef + +HOSTCC = gcc +HOSTINCLUDES = -I. +HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -g -pipe +HOSTLDFLAGS = + diff --git a/nuttx/configs/px4io/common/ld.script b/nuttx/configs/px4io/common/ld.script new file mode 100755 index 0000000000..17f816acfe --- /dev/null +++ b/nuttx/configs/px4io/common/ld.script @@ -0,0 +1,120 @@ +/**************************************************************************** + * configs/stm3210e-eval/nsh/ld.script + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* The STM32F100C8 has 64Kb of FLASH beginning at address 0x0800:0000 and + * 8Kb of SRAM beginning at address 0x2000:0000. When booting from FLASH, + * FLASH memory is aliased to address 0x0000:0000 where the code expects to + * begin execution by jumping to the entry point in the 0x0800:0000 address + * range. + */ + +MEMORY +{ + flash (rx) : ORIGIN = 0x08001000, LENGTH = 60K + sram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K +} + +OUTPUT_ARCH(arm) +ENTRY(__start) /* treat __start as the anchor for dead code stripping */ +EXTERN(_vectors) /* force the vectors to be included in the output */ + +/* + * Ensure that abort() is present in the final object. The exception handling + * code pulled in by libgcc.a requires it (and that code cannot be easily avoided). + */ +EXTERN(abort) + +SECTIONS +{ + .text : { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .ARM.extab : { + *(.ARM.extab*) + } > flash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : { + *(.ARM.exidx*) + } > flash + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + /* The STM32F100CB has 8Kb of SRAM beginning at the following address */ + + .data : { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + _edata = ABSOLUTE(.); + } > sram AT > flash + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/nuttx/configs/px4io/common/setenv.sh b/nuttx/configs/px4io/common/setenv.sh new file mode 100755 index 0000000000..d836851921 --- /dev/null +++ b/nuttx/configs/px4io/common/setenv.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# configs/stm3210e-eval/dfu/setenv.sh +# +# Copyright (C) 2009 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +if [ "$(basename $0)" = "setenv.sh" ] ; then + echo "You must source this script, not run it!" 1>&2 + exit 1 +fi + +if [ -z "${PATH_ORIG}" ]; then export PATH_ORIG="${PATH}"; fi + +WD=`pwd` +export RIDE_BIN="/cygdrive/c/Program Files/Raisonance/Ride/arm-gcc/bin" +export BUILDROOT_BIN="${WD}/../buildroot/build_arm_nofpu/staging_dir/bin" +export PATH="${BUILDROOT_BIN}:${RIDE_BIN}:/sbin:/usr/sbin:${PATH_ORIG}" + +echo "PATH : ${PATH}" diff --git a/nuttx/configs/px4io/include/README.txt b/nuttx/configs/px4io/include/README.txt new file mode 100755 index 0000000000..2264a80aa8 --- /dev/null +++ b/nuttx/configs/px4io/include/README.txt @@ -0,0 +1 @@ +This directory contains header files unique to the PX4IO board. diff --git a/nuttx/configs/px4io/include/board.h b/nuttx/configs/px4io/include/board.h new file mode 100755 index 0000000000..cd4d48649f --- /dev/null +++ b/nuttx/configs/px4io/include/board.h @@ -0,0 +1,167 @@ +/************************************************************************************ + * configs/px4io/include/board.h + * include/arch/board/board.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_BOARD_BOARD_H +#define __ARCH_BOARD_BOARD_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#ifndef __ASSEMBLY__ +# include +# include +#endif +#include "stm32_rcc.h" +#include "stm32_sdio.h" +#include "stm32_internal.h" + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/* Clocking *************************************************************************/ + +/* On-board crystal frequency is 24MHz (HSE) */ + +#define STM32_BOARD_XTAL 24000000ul + +/* Use the HSE output as the system clock */ + +#define STM32_SYSCLK_SW RCC_CFGR_SW_HSE +#define STM32_SYSCLK_SWS RCC_CFGR_SWS_HSE +#define STM32_SYSCLK_FREQUENCY STM32_BOARD_XTAL + +/* AHB clock (HCLK) is SYSCLK (24MHz) */ + +#define STM32_RCC_CFGR_HPRE RCC_CFGR_HPRE_SYSCLK +#define STM32_HCLK_FREQUENCY STM32_SYSCLK_FREQUENCY +#define STM32_BOARD_HCLK STM32_HCLK_FREQUENCY /* same as above, to satisfy compiler */ + +/* APB2 clock (PCLK2) is HCLK (24MHz) */ + +#define STM32_RCC_CFGR_PPRE2 RCC_CFGR_PPRE2_HCLK +#define STM32_PCLK2_FREQUENCY STM32_HCLK_FREQUENCY +#define STM32_APB2_CLKIN (STM32_PCLK2_FREQUENCY) /* Timers 2-4 */ + +/* APB2 timer 1 will receive PCLK2. */ + +#define STM32_APB2_TIM1_CLKIN (STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM8_CLKIN (STM32_PCLK2_FREQUENCY) + +/* APB1 clock (PCLK1) is HCLK (24MHz) */ + +#define STM32_RCC_CFGR_PPRE1 RCC_CFGR_PPRE1_HCLK +#define STM32_PCLK1_FREQUENCY (STM32_HCLK_FREQUENCY) + +/* All timers run off PCLK */ + +#define STM32_APB1_TIM1_CLKIN (STM32_PCLK2_FREQUENCY) +#define STM32_APB1_TIM2_CLKIN (STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM3_CLKIN (STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM4_CLKIN (STM32_PCLK1_FREQUENCY) + +/* + * High-resolution timer + */ +#ifdef CONFIG_HRT_TIMER +# define HRT_TIMER 1 /* use timer1 for the HRT */ +# define HRT_TIMER_CHANNEL 2 /* use capture/compare channel 2 */ +#endif + +/* + * PPM + * + * PPM input is handled by the HRT timer. + * + * Pin is PA8, timer 1, channel 1 + */ +#if defined(CONFIG_HRT_TIMER) && defined (CONFIG_HRT_PPM) +# define HRT_PPM_CHANNEL 1 /* use capture/compare channel 1 */ +# define GPIO_PPM_IN GPIO_TIM1_CH1IN +#endif + +/* + * PWM + * + * PWM configuration is provided via the configuration structure in up_boardinitialize.c + */ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ +/************************************************************************************ + * Name: stm32_boardinitialize + * + * Description: + * All STM32 architectures must provide the following entry point. This entry point + * is called early in the intitialization -- after all memory has been configured + * and mapped but before any devices have been initialized. + * + ************************************************************************************/ + +EXTERN void stm32_boardinitialize(void); + +/************************************************************************************ + * Power switch support. + */ +extern void up_power_init(void); +extern void up_power_set(int port, bool state); +extern bool up_power_error(int port); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_BOARD_BOARD_H */ diff --git a/nuttx/configs/px4io/include/drv_gpio.h b/nuttx/configs/px4io/include/drv_gpio.h new file mode 100644 index 0000000000..329d2bacfa --- /dev/null +++ b/nuttx/configs/px4io/include/drv_gpio.h @@ -0,0 +1,67 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file GPIO driver for PX4IO + */ + +#include + +#define _GPIO_IOCTL_BASE 0x7700 + +#define GPIO_SET(_x) _IOC(_GPIO_IOCTL_BASE, _x) +#define GPIO_GET(_x) _IOC(_GPIO_IOCTL_BASE + 1, _x) + +/* + * List of GPIOs; must be sorted with settable GPIOs first. + */ +#define GPIO_ACC1_POWER 0 /* settable */ +#define GPIO_ACC2_POWER 1 +#define GPIO_SERVO_POWER 2 +#define GPIO_RELAY1 3 +#define GPIO_RELAY2 4 +#define GPIO_LED_BLUE 5 +#define GPIO_LED_AMBER 6 +#define GPIO_LED_SAFETY 7 + +#define GPIO_ACC_OVERCURRENT 8 /* readonly */ +#define GPIO_SERVO_OVERCURRENT 9 +#define GPIO_SAFETY_BUTTON 10 + +#define GPIO_MAX_SETTABLE 7 +#define GPIO_MAX 10 + +/* + * GPIO driver init function. + */ +extern int gpio_drv_init(void); diff --git a/nuttx/configs/px4io/include/drv_i2c_device.h b/nuttx/configs/px4io/include/drv_i2c_device.h new file mode 100644 index 0000000000..02582bc092 --- /dev/null +++ b/nuttx/configs/px4io/include/drv_i2c_device.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + + /** + * @file A simple, polled I2C slave-mode driver. + * + * The master writes to and reads from a byte buffer, which the caller + * can update inbetween calls to the FSM. + */ + +extern void i2c_fsm_init(uint8_t *buffer, size_t buffer_size); +extern bool i2c_fsm(void); diff --git a/nuttx/configs/px4io/include/drv_ppm_input.h b/nuttx/configs/px4io/include/drv_ppm_input.h new file mode 100644 index 0000000000..78c4241542 --- /dev/null +++ b/nuttx/configs/px4io/include/drv_ppm_input.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file PPM input decoder. + * + * Works in conjunction with the HRT driver, exports a device node + * and a message queue (if message queues are enabled). + * + * Note that the device node supports both blocking and non-blocking + * opens, but actually never blocks. A nonblocking open will return + * EWOULDBLOCK if there has not been an update since the last read, + * while a blocking open will always return the most recent data. + */ + +#include + +#define _PPM_INPUT_BASE 0x7600 + +/* + * Fetch the state of the PPM input detector. + */ +#define PPM_INPUT_STATUS _IOC(_PPM_INPUT_BASE, 0) + +typedef enum { + PPM_STATUS_NO_SIGNAL = 0, + PPM_STATUS_SIGNAL_CURRENT = 1, +} ppm_input_status_t; + +/* + * Fetch the number of channels decoded (only valid when PPM_STATUS_SIGNAL_CURRENT). + */ +#define PPM_INPUT_CHANNELS _IOC(_PPM_INPUT_BASE, 1) + +typedef int ppm_input_channel_count_t; + +/* + * Device node + */ +#define PPM_DEVICE_NODE "/dev/ppm_input" + +/* + * Message queue; if message queues are supported, PPM input data is + * supplied to the queue when a frame is decoded. + */ +#ifndef CONFIG_DISABLE_MQUEUE +# define PPM_MESSAGE_QUEUE "ppm_input" +#endif + +/* + * Private hook from the HRT driver to the PPM decoder. + * + * This function is called for every edge of the incoming PPM + * signal. + * + * @param reset If true, the decoder should be reset (e.g.) + * capture failure was detected. + * @param count The counter value at which the edge + * was captured. + */ + +void ppm_input_decode(bool reset, uint16_t count); + +/* + * PPM input initialisation function. + * + * If message queues are enabled, and mq_name is not NULL, received input + * is posted to the message queue as an array of 16-bit unsigned channel values. + */ +int ppm_input_init(const char *mq_name); \ No newline at end of file diff --git a/nuttx/configs/px4io/include/drv_pwm_servo.h b/nuttx/configs/px4io/include/drv_pwm_servo.h new file mode 100644 index 0000000000..6634684046 --- /dev/null +++ b/nuttx/configs/px4io/include/drv_pwm_servo.h @@ -0,0 +1,94 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file PWM servo driver. + * + * The pwm_servo driver supports servos connected to STM32 timer + * blocks. + * + * Servo values can be set either with the PWM_SERVO_SET ioctl, or + * by writing an array of servo_position_t values to the device. + * Writing a value of 0 to a channel suppresses any output for that + * channel. + * + * Servo values can be read back either with the PWM_SERVO_GET + * ioctl, or by reading an array of servo_position_t values + * from the device. + * + * Attempts to set a channel that is not configured are ignored, + * and unconfigured channels always read zero. + * + * The PWM_SERVO_ARM / PWM_SERVO_DISARM calls globally arm + * (enable) and disarm (disable) all servo outputs. + */ + +#include + +#define _PWM_SERVO_BASE 0x7500 +#define PWM_SERVO_ARM _IOC(_PWM_SERVO_BASE, 0) +#define PWM_SERVO_DISARM _IOC(_PWM_SERVO_BASE, 1) + +#define PWM_SERVO_SET(_servo) _IOC(_PWM_SERVO_BASE, 0x20 + _servo) +#define PWM_SERVO_GET(_servo) _IOC(_PWM_SERVO_BASE, 0x40 + _servo) + +typedef uint16_t servo_position_t; + +/* configuration limits */ +#define PWM_SERVO_MAX_TIMERS 3 +#define PWM_SERVO_MAX_CHANNELS 8 + +struct pwm_servo_config { + /* rate (in Hz) of PWM updates */ + uint32_t update_rate; + + /* array of timers dedicated to PWM servo use */ + struct pwm_servo_timer { + uint32_t base; + uint32_t clock_register; + uint32_t clock_bit; + uint32_t clock_freq; + } timers[PWM_SERVO_MAX_TIMERS]; + + /* array of channels in logical order */ + struct pwm_servo_channel { + uint32_t gpio; + uint8_t timer_index; + uint8_t timer_channel; + servo_position_t default_value; + } channels[PWM_SERVO_MAX_CHANNELS]; +}; + +extern int pwm_servo_init(const struct pwm_servo_config *config); + + diff --git a/nuttx/configs/px4io/include/up_boardinitialize.h b/nuttx/configs/px4io/include/up_boardinitialize.h new file mode 100755 index 0000000000..01b9ca2143 --- /dev/null +++ b/nuttx/configs/px4io/include/up_boardinitialize.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Board initialisation prototype(s) + */ + +#ifndef __UP_BOARDINITIALIZE_H +#define __UP_BOARDINITIALIZE_H + +extern int up_boardinitialize(void); + +#endif diff --git a/nuttx/configs/px4io/include/up_hrt.h b/nuttx/configs/px4io/include/up_hrt.h new file mode 100644 index 0000000000..c83f14ac37 --- /dev/null +++ b/nuttx/configs/px4io/include/up_hrt.h @@ -0,0 +1,129 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file High-resolution timer callouts and timekeeping. + */ + +#ifndef UP_HRT_H_ +#define UP_HRT_H_ + +#include +#include + +#include +#include + +/* + * Absolute time, in microsecond units. + * + * Absolute time is measured from some arbitrary epoch shortly after + * system startup. It should never wrap or go backwards. + */ +typedef uint64_t hrt_abstime; + +/* + * Callout function type. + * + * Note that callouts run in the timer interrupt context, so + * they are serialised with respect to each other, and must not + * block. + */ +typedef void (* hrt_callout)(void *arg); + +/* + * Callout record. + */ +struct hrt_call { + struct sq_entry_s link; + + hrt_abstime deadline; + hrt_abstime period; + hrt_callout callout; + void *arg; +}; + +/* + * Get absolute time. + */ +extern hrt_abstime hrt_absolute_time(void); + +/* + * Convert a timespec to absolute time. + */ +extern hrt_abstime ts_to_abstime(struct timespec *ts); + +/* + * Convert absolute time to a timespec. + */ +extern void abstime_to_ts(struct timespec *ts, hrt_abstime abstime); + +/* + * Call callout(arg) after delay has elapsed. + * + * If callout is NULL, this can be used to implement a timeout by testing the call + * with hrt_called(). + */ +extern void hrt_call_after(struct hrt_call *entry, hrt_abstime delay, hrt_callout callout, void *arg); + +/* + * Call callout(arg) at absolute time calltime. + */ +extern void hrt_call_at(struct hrt_call *entry, hrt_abstime calltime, hrt_callout callout, void *arg); + +/* + * Call callout(arg) after delay, and then after every interval. + * + * Note thet the interval is timed between scheduled, not actual, call times, so the call rate may + * jitter but should not drift. + */ +extern void hrt_call_every(struct hrt_call *entry, hrt_abstime delay, hrt_abstime interval, hrt_callout callout, void *arg); + +/* + * If this returns true, the entry has been invoked and removed from the callout list. + * + * Always returns false for repeating callouts. + */ +extern bool hrt_called(struct hrt_call *entry); + +/* + * Remove the entry from the callout list. + */ +extern void hrt_cancel(struct hrt_call *entry); + +/* + * Initialise the HRT. + */ +extern void hrt_init(int timer); + +#endif /* UP_HRT_H_ */ diff --git a/nuttx/configs/px4io/io/Make.defs b/nuttx/configs/px4io/io/Make.defs new file mode 100644 index 0000000000..87508e22ec --- /dev/null +++ b/nuttx/configs/px4io/io/Make.defs @@ -0,0 +1,3 @@ +include ${TOPDIR}/.config + +include $(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/common/Make.defs diff --git a/nuttx/configs/px4io/io/appconfig b/nuttx/configs/px4io/io/appconfig new file mode 100644 index 0000000000..94176c6dcf --- /dev/null +++ b/nuttx/configs/px4io/io/appconfig @@ -0,0 +1,39 @@ +############################################################################ +# configs/stm3210e-eval/nsh/appconfig +# +# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Path to px4io app containing the user_start entry point + +CONFIGURED_APPS += px4io +CONFIGURED_APPS += systemlib diff --git a/nuttx/configs/px4io/io/defconfig b/nuttx/configs/px4io/io/defconfig new file mode 100755 index 0000000000..8ae6afe3cb --- /dev/null +++ b/nuttx/configs/px4io/io/defconfig @@ -0,0 +1,517 @@ +############################################################################ +# configs/px4io/nsh/defconfig +# +# Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ +# +# architecture selection +# +# CONFIG_ARCH - identifies the arch subdirectory and, hence, the +# processor architecture. +# CONFIG_ARCH_family - for use in C code. This identifies the +# particular chip family that the architecture is implemented +# in. +# CONFIG_ARCH_architecture - for use in C code. This identifies the +# specific architecture within the chip familyl. +# CONFIG_ARCH_CHIP - Identifies the arch/*/chip subdirectory +# CONFIG_ARCH_CHIP_name - For use in C code +# CONFIG_ARCH_BOARD - identifies the configs subdirectory and, hence, +# the board that supports the particular chip or SoC. +# CONFIG_ARCH_BOARD_name - for use in C code +# CONFIG_ENDIAN_BIG - define if big endian (default is little endian) +# CONFIG_BOARD_LOOPSPERMSEC - for delay loops +# CONFIG_DRAM_SIZE - Describes the installed DRAM. +# CONFIG_DRAM_START - The start address of DRAM (physical) +# CONFIG_DRAM_END - Last address+1 of installed RAM +# CONFIG_ARCH_IRQPRIO - The ST32F100CB supports interrupt prioritization +# CONFIG_ARCH_INTERRUPTSTACK - This architecture supports an interrupt +# stack. If defined, this symbol is the size of the interrupt +# stack in bytes. If not defined, the user task stacks will be +# used during interrupt handling. +# CONFIG_ARCH_STACKDUMP - Do stack dumps after assertions +# CONFIG_ARCH_BOOTLOADER - Set if you are using a bootloader. +# CONFIG_ARCH_LEDS - Use LEDs to show state. Unique to board architecture. +# CONFIG_ARCH_BUTTONS - Enable support for buttons. Unique to board architecture. +# CONFIG_ARCH_CALIBRATION - Enables some build in instrumentation that +# cause a 100 second delay during boot-up. This 100 second delay +# serves no purpose other than it allows you to calibrate +# CONFIG_BOARD_LOOPSPERMSEC. You simply use a stop watch to measure +# the 100 second delay then adjust CONFIG_BOARD_LOOPSPERMSEC until +# the delay actually is 100 seconds. +# CONFIG_ARCH_DMA - Support DMA initialization +# +CONFIG_ARCH=arm +CONFIG_ARCH_ARM=y +CONFIG_ARCH_CORTEXM3=y +CONFIG_ARCH_CHIP=stm32 +CONFIG_ARCH_CHIP_STM32F100C8=y +CONFIG_ARCH_BOARD=px4io +CONFIG_ARCH_BOARD_PX4IO=y +CONFIG_BOARD_LOOPSPERMSEC=2000 +CONFIG_DRAM_SIZE=0x00002000 +CONFIG_DRAM_START=0x20000000 +CONFIG_DRAM_END=(CONFIG_DRAM_START+CONFIG_DRAM_SIZE) +CONFIG_ARCH_IRQPRIO=y +CONFIG_ARCH_INTERRUPTSTACK=n +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_BOOTLOADER=n +CONFIG_ARCH_LEDS=n +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CALIBRATION=n +CONFIG_ARCH_DMA=n +CONFIG_ARMV7M_CMNVECTOR=y + +# +# JTAG Enable settings (by default JTAG-DP and SW-DP are disabled): +# +# CONFIG_STM32_DFU - Use the DFU bootloader, not JTAG +# +# JTAG Enable options: +# +# CONFIG_STM32_JTAG_FULL_ENABLE - Enables full SWJ (JTAG-DP + SW-DP) +# CONFIG_STM32_JTAG_NOJNTRST_ENABLE - Enables full SWJ (JTAG-DP + SW-DP) +# but without JNTRST. +# CONFIG_STM32_JTAG_SW_ENABLE - Set JTAG-DP disabled and SW-DP enabled +# +CONFIG_STM32_DFU=n +CONFIG_STM32_JTAG_FULL_ENABLE=y +CONFIG_STM32_JTAG_NOJNTRST_ENABLE=n +CONFIG_STM32_JTAG_SW_ENABLE=n + +# +# Individual subsystems can be enabled: +# AHB: +CONFIG_STM32_DMA1=n +CONFIG_STM32_DMA2=n +CONFIG_STM32_CRC=n +# APB1: +# Timers 2,3 and 4 are owned by the PWM driver +CONFIG_STM32_TIM2=n +CONFIG_STM32_TIM3=n +CONFIG_STM32_TIM4=n +CONFIG_STM32_TIM5=n +CONFIG_STM32_TIM6=n +CONFIG_STM32_TIM7=n +CONFIG_STM32_WWDG=n +CONFIG_STM32_SPI2=n +CONFIG_STM32_USART2=y +CONFIG_STM32_USART3=n +CONFIG_STM32_I2C1=y +CONFIG_STM32_I2C2=n +CONFIG_STM32_BKP=n +CONFIG_STM32_PWR=n +CONFIG_STM32_DAC=n +# APB2: +CONFIG_STM32_ADC1=y +CONFIG_STM32_ADC2=n +# TIM1 is owned by the HRT +CONFIG_STM32_TIM1=n +CONFIG_STM32_SPI1=n +CONFIG_STM32_TIM8=n +CONFIG_STM32_USART1=y +CONFIG_STM32_ADC3=n + +# +# Timer and I2C devices may need to the following to force power to be applied: +# +#CONFIG_STM32_FORCEPOWER=y + +# +# STM32F100 specific serial device driver settings +# +# CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the +# console and ttys0 (default is the USART1). +# CONFIG_USARTn_RXBUFSIZE - Characters are buffered as received. +# This specific the size of the receive buffer +# CONFIG_USARTn_TXBUFSIZE - Characters are buffered before +# being sent. This specific the size of the transmit buffer +# CONFIG_USARTn_BAUD - The configure BAUD of the UART. Must be +# CONFIG_USARTn_BITS - The number of bits. Must be either 7 or 8. +# CONFIG_USARTn_PARTIY - 0=no parity, 1=odd parity, 2=even parity +# CONFIG_USARTn_2STOP - Two stop bits +# +CONFIG_USART1_SERIAL_CONSOLE=y +CONFIG_USART2_SERIAL_CONSOLE=n +CONFIG_USART3_SERIAL_CONSOLE=n + +CONFIG_USART1_TXBUFSIZE=32 +CONFIG_USART2_TXBUFSIZE=32 +CONFIG_USART3_TXBUFSIZE=32 + +CONFIG_USART1_RXBUFSIZE=32 +CONFIG_USART2_RXBUFSIZE=32 +CONFIG_USART3_RXBUFSIZE=32 + +CONFIG_USART1_BAUD=57600 +CONFIG_USART2_BAUD=115200 +CONFIG_USART3_BAUD=115200 + +CONFIG_USART1_BITS=8 +CONFIG_USART2_BITS=8 +CONFIG_USART3_BITS=8 + +CONFIG_USART1_PARITY=0 +CONFIG_USART2_PARITY=0 +CONFIG_USART3_PARITY=0 + +CONFIG_USART1_2STOP=0 +CONFIG_USART2_2STOP=0 +CONFIG_USART3_2STOP=0 + +# +# PX4IO specific driver settings +# +# CONFIG_HRT_TIMER +# Enables the high-resolution timer. The board definition must +# set HRT_TIMER and HRT_TIMER_CHANNEL to the timer and capture/ +# compare channels to be used. +# CONFIG_HRT_PPM +# Enables R/C PPM input using the HRT. The board definition must +# set HRT_PPM_CHANNEL to the timer capture/compare channel to be +# used, and define GPIO_PPM_IN to configure the appropriate timer +# GPIO. +# CONFIG_PWM_SERVO +# Enables the PWM servo driver. The driver configuration must be +# supplied by the board support at initialisation time. +# Note that USART2 must be disabled on the PX4 board for this to +# be available. +# +# +CONFIG_HRT_TIMER=y +CONFIG_HRT_PPM=y +CONFIG_PWM_SERVO=y + +# +# General build options +# +# CONFIG_RRLOAD_BINARY - make the rrload binary format used with +# BSPs from www.ridgerun.com using the tools/mkimage.sh script +# CONFIG_INTELHEX_BINARY - make the Intel HEX binary format +# used with many different loaders using the GNU objcopy program +# Should not be selected if you are not using the GNU toolchain. +# CONFIG_MOTOROLA_SREC - make the Motorola S-Record binary format +# used with many different loaders using the GNU objcopy program +# Should not be selected if you are not using the GNU toolchain. +# CONFIG_RAW_BINARY - make a raw binary format file used with many +# different loaders using the GNU objcopy program. This option +# should not be selected if you are not using the GNU toolchain. +# CONFIG_HAVE_LIBM - toolchain supports libm.a +# +CONFIG_RRLOAD_BINARY=n +CONFIG_INTELHEX_BINARY=n +CONFIG_MOTOROLA_SREC=n +CONFIG_RAW_BINARY=y +CONFIG_HAVE_LIBM=n + +# +# General OS setup +# +# CONFIG_APPS_DIR - Identifies the relative path to the directory +# that builds the application to link with NuttX. Default: ../apps +# CONFIG_DEBUG - enables built-in debug options +# CONFIG_DEBUG_VERBOSE - enables verbose debug output +# CONFIG_DEBUG_SYMBOLS - build without optimization and with +# debug symbols (needed for use with a debugger). +# CONFIG_HAVE_CXX - Enable support for C++ +# CONFIG_HAVE_CXXINITIALIZE - The platform-specific logic includes support +# for initialization of static C++ instances for this architecture +# and for the selected toolchain (via up_cxxinitialize()). +# CONFIG_MM_REGIONS - If the architecture includes multiple +# regions of memory to allocate from, this specifies the +# number of memory regions that the memory manager must +# handle and enables the API mm_addregion(start, end); +# CONFIG_ARCH_LOWPUTC - architecture supports low-level, boot +# time console output +# CONFIG_MSEC_PER_TICK - The default system timer is 100Hz +# or MSEC_PER_TICK=10. This setting may be defined to +# inform NuttX that the processor hardware is providing +# system timer interrupts at some interrupt interval other +# than 10 msec. +# CONFIG_RR_INTERVAL - The round robin timeslice will be set +# this number of milliseconds; Round robin scheduling can +# be disabled by setting this value to zero. +# CONFIG_SCHED_INSTRUMENTATION - enables instrumentation in +# scheduler to monitor system performance +# CONFIG_TASK_NAME_SIZE - Spcifies that maximum size of a +# task name to save in the TCB. Useful if scheduler +# instrumentation is selected. Set to zero to disable. +# CONFIG_START_YEAR, CONFIG_START_MONTH, CONFIG_START_DAY - +# Used to initialize the internal time logic. +# CONFIG_GREGORIAN_TIME - Enables Gregorian time conversions. +# You would only need this if you are concerned about accurate +# time conversions in the past or in the distant future. +# CONFIG_JULIAN_TIME - Enables Julian time conversions. You +# would only need this if you are concerned about accurate +# time conversion in the distand past. You must also define +# CONFIG_GREGORIAN_TIME in order to use Julian time. +# CONFIG_DEV_CONSOLE - Set if architecture-specific logic +# provides /dev/console. Enables stdout, stderr, stdin. +# CONFIG_DEV_LOWCONSOLE - Use the simple, low-level serial console +# driver (minimul support) +# CONFIG_MUTEX_TYPES: Set to enable support for recursive and +# errorcheck mutexes. Enables pthread_mutexattr_settype(). +# CONFIG_PRIORITY_INHERITANCE : Set to enable support for priority +# inheritance on mutexes and semaphores. +# CONFIG_SEM_PREALLOCHOLDERS: This setting is only used if priority +# inheritance is enabled. It defines the maximum number of +# different threads (minus one) that can take counts on a +# semaphore with priority inheritance support. This may be +# set to zero if priority inheritance is disabled OR if you +# are only using semaphores as mutexes (only one holder) OR +# if no more than two threads participate using a counting +# semaphore. +# CONFIG_SEM_NNESTPRIO. If priority inheritance is enabled, +# then this setting is the maximum number of higher priority +# threads (minus 1) than can be waiting for another thread +# to release a count on a semaphore. This value may be set +# to zero if no more than one thread is expected to wait for +# a semaphore. +# CONFIG_FDCLONE_DISABLE. Disable cloning of all file descriptors +# by task_create() when a new task is started. If set, all +# files/drivers will appear to be closed in the new task. +# CONFIG_FDCLONE_STDIO. Disable cloning of all but the first +# three file descriptors (stdin, stdout, stderr) by task_create() +# when a new task is started. If set, all files/drivers will +# appear to be closed in the new task except for stdin, stdout, +# and stderr. +# CONFIG_SDCLONE_DISABLE. Disable cloning of all socket +# desciptors by task_create() when a new task is started. If +# set, all sockets will appear to be closed in the new task. +# CONFIG_NXFLAT. Enable support for the NXFLAT binary format. +# This format will support execution of NuttX binaries located +# in a ROMFS filesystem (see examples/nxflat). +# CONFIG_SCHED_WORKQUEUE. Create a dedicated "worker" thread to +# handle delayed processing from interrupt handlers. This feature +# is required for some drivers but, if there are not complaints, +# can be safely disabled. The worker thread also performs +# garbage collection -- completing any delayed memory deallocations +# from interrupt handlers. If the worker thread is disabled, +# then that clean will be performed by the IDLE thread instead +# (which runs at the lowest of priority and may not be appropriate +# if memory reclamation is of high priority). If CONFIG_SCHED_WORKQUEUE +# is enabled, then the following options can also be used: +# CONFIG_SCHED_WORKPRIORITY - The execution priority of the worker +# thread. Default: 50 +# CONFIG_SCHED_WORKPERIOD - How often the worker thread checks for +# work in units of microseconds. Default: 50*1000 (50 MS). +# CONFIG_SCHED_WORKSTACKSIZE - The stack size allocated for the worker +# thread. Default: CONFIG_IDLETHREAD_STACKSIZE. +# CONFIG_SIG_SIGWORK - The signal number that will be used to wake-up +# the worker thread. Default: 4 +# +#CONFIG_APPS_DIR= +CONFIG_DEBUG=n +CONFIG_DEBUG_VERBOSE=n +CONFIG_DEBUG_SYMBOLS=y +CONFIG_HAVE_CXX=n +CONFIG_HAVE_CXXINITIALIZE=n +CONFIG_MM_REGIONS=1 +CONFIG_MM_SMALL=y +CONFIG_ARCH_LOWPUTC=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_INSTRUMENTATION=n +CONFIG_TASK_NAME_SIZE=0 +CONFIG_START_YEAR=2009 +CONFIG_START_MONTH=9 +CONFIG_START_DAY=21 +CONFIG_GREGORIAN_TIME=n +CONFIG_JULIAN_TIME=n +CONFIG_DEV_CONSOLE=y +CONFIG_DEV_LOWCONSOLE=n +CONFIG_MUTEX_TYPES=n +CONFIG_PRIORITY_INHERITANCE=n +CONFIG_SEM_PREALLOCHOLDERS=0 +CONFIG_SEM_NNESTPRIO=0 +CONFIG_FDCLONE_DISABLE=n +CONFIG_FDCLONE_STDIO=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_NXFLAT=n +CONFIG_SCHED_WORKQUEUE=n +CONFIG_SCHED_WORKPRIORITY=50 +CONFIG_SCHED_WORKPERIOD=(50*1000) +CONFIG_SCHED_WORKSTACKSIZE=1024 +CONFIG_SIG_SIGWORK=4 + +# +# The following can be used to disable categories of +# APIs supported by the OS. If the compiler supports +# weak functions, then it should not be necessary to +# disable functions unless you want to restrict usage +# of those APIs. +# +# There are certain dependency relationships in these +# features. +# +# o mq_notify logic depends on signals to awaken tasks +# waiting for queues to become full or empty. +# o pthread_condtimedwait() depends on signals to wake +# up waiting tasks. +# +CONFIG_DISABLE_CLOCK=n +CONFIG_DISABLE_POSIX_TIMERS=y +CONFIG_DISABLE_PTHREAD=y +CONFIG_DISABLE_SIGNALS=y +CONFIG_DISABLE_MQUEUE=n +CONFIG_DISABLE_MOUNTPOINT=y +CONFIG_DISABLE_ENVIRON=y +CONFIG_DISABLE_POLL=y + +# +# Misc libc settings +# +# CONFIG_NOPRINTF_FIELDWIDTH - sprintf-related logic is a +# little smaller if we do not support fieldwidthes +# +CONFIG_NOPRINTF_FIELDWIDTH=n + +# +# Allow for architecture optimized implementations +# +# The architecture can provide optimized versions of the +# following to improve system performance +# +CONFIG_ARCH_MEMCPY=n +CONFIG_ARCH_MEMCMP=n +CONFIG_ARCH_MEMMOVE=n +CONFIG_ARCH_MEMSET=n +CONFIG_ARCH_STRCMP=n +CONFIG_ARCH_STRCPY=n +CONFIG_ARCH_STRNCPY=n +CONFIG_ARCH_STRLEN=n +CONFIG_ARCH_STRNLEN=n +CONFIG_ARCH_BZERO=n + +# +# Sizes of configurable things (0 disables) +# +# CONFIG_MAX_TASKS - The maximum number of simultaneously +# active tasks. This value must be a power of two. +# CONFIG_MAX_TASK_ARGS - This controls the maximum number of +# of parameters that a task may receive (i.e., maxmum value +# of 'argc') +# CONFIG_NPTHREAD_KEYS - The number of items of thread- +# specific data that can be retained +# CONFIG_NFILE_DESCRIPTORS - The maximum number of file +# descriptors (one for each open) +# CONFIG_NFILE_STREAMS - The maximum number of streams that +# can be fopen'ed +# CONFIG_NAME_MAX - The maximum size of a file name. +# CONFIG_STDIO_BUFFER_SIZE - Size of the buffer to allocate +# on fopen. (Only if CONFIG_NFILE_STREAMS > 0) +# CONFIG_NUNGET_CHARS - Number of characters that can be +# buffered by ungetc() (Only if CONFIG_NFILE_STREAMS > 0) +# CONFIG_PREALLOC_MQ_MSGS - The number of pre-allocated message +# structures. The system manages a pool of preallocated +# message structures to minimize dynamic allocations +# CONFIG_MQ_MAXMSGSIZE - Message structures are allocated with +# a fixed payload size given by this settin (does not include +# other message structure overhead. +# CONFIG_MAX_WDOGPARMS - Maximum number of parameters that +# can be passed to a watchdog handler +# CONFIG_PREALLOC_WDOGS - The number of pre-allocated watchdog +# structures. The system manages a pool of preallocated +# watchdog structures to minimize dynamic allocations +# CONFIG_PREALLOC_TIMERS - The number of pre-allocated POSIX +# timer structures. The system manages a pool of preallocated +# timer structures to minimize dynamic allocations. Set to +# zero for all dynamic allocations. +# +CONFIG_MAX_TASKS=8 +CONFIG_MAX_TASK_ARGS=4 +CONFIG_NPTHREAD_KEYS=4 +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NFILE_STREAMS=0 +CONFIG_NAME_MAX=32 +CONFIG_STDIO_BUFFER_SIZE=64 +CONFIG_NUNGET_CHARS=2 +CONFIG_PREALLOC_MQ_MSGS=4 +CONFIG_MQ_MAXMSGSIZE=32 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_PREALLOC_WDOGS=4 +CONFIG_PREALLOC_TIMERS=0 + + +# +# Settings for apps/nshlib +# +# CONFIG_NSH_BUILTIN_APPS - Support external registered, +# "named" applications that can be executed from the NSH +# command line (see apps/README.txt for more information). +# CONFIG_NSH_FILEIOSIZE - Size of a static I/O buffer +# CONFIG_NSH_STRERROR - Use strerror(errno) +# CONFIG_NSH_LINELEN - Maximum length of one command line +# CONFIG_NSH_NESTDEPTH - Max number of nested if-then[-else]-fi +# CONFIG_NSH_DISABLESCRIPT - Disable scripting support +# CONFIG_NSH_DISABLEBG - Disable background commands +# CONFIG_NSH_ROMFSETC - Use startup script in /etc +# CONFIG_NSH_CONSOLE - Use serial console front end +# CONFIG_NSH_TELNET - Use telnetd console front end +# CONFIG_NSH_ARCHINIT - Platform provides architecture +# specific initialization (nsh_archinitialize()). +# + +# Disable NSH completely +CONFIG_NSH_CONSOLE=n + +# +# Stack and heap information +# +# CONFIG_BOOT_RUNFROMFLASH - Some configurations support XIP +# operation from FLASH but must copy initialized .data sections to RAM. +# (should also be =n for the STM3210E-EVAL which always runs from flash) +# CONFIG_BOOT_COPYTORAM - Some configurations boot in FLASH +# but copy themselves entirely into RAM for better performance. +# CONFIG_CUSTOM_STACK - The up_ implementation will handle +# all stack operations outside of the nuttx model. +# CONFIG_STACK_POINTER - The initial stack pointer (arm7tdmi only) +# CONFIG_IDLETHREAD_STACKSIZE - The size of the initial stack. +# This is the thread that (1) performs the inital boot of the system up +# to the point where user_start() is spawned, and (2) there after is the +# IDLE thread that executes only when there is no other thread ready to +# run. +# CONFIG_USERMAIN_STACKSIZE - The size of the stack to allocate +# for the main user thread that begins at the user_start() entry point. +# CONFIG_PTHREAD_STACK_MIN - Minimum pthread stack size +# CONFIG_PTHREAD_STACK_DEFAULT - Default pthread stack size +# CONFIG_HEAP_BASE - The beginning of the heap +# CONFIG_HEAP_SIZE - The size of the heap +# +CONFIG_BOOT_RUNFROMFLASH=n +CONFIG_BOOT_COPYTORAM=n +CONFIG_CUSTOM_STACK=n +CONFIG_STACK_POINTER= +CONFIG_IDLETHREAD_STACKSIZE=1024 +CONFIG_USERMAIN_STACKSIZE=1024 +CONFIG_PTHREAD_STACK_MIN=512 +CONFIG_PTHREAD_STACK_DEFAULT=1024 +CONFIG_HEAP_BASE= +CONFIG_HEAP_SIZE= diff --git a/nuttx/configs/px4io/io/setenv.sh b/nuttx/configs/px4io/io/setenv.sh new file mode 100755 index 0000000000..d836851921 --- /dev/null +++ b/nuttx/configs/px4io/io/setenv.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# configs/stm3210e-eval/dfu/setenv.sh +# +# Copyright (C) 2009 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +if [ "$(basename $0)" = "setenv.sh" ] ; then + echo "You must source this script, not run it!" 1>&2 + exit 1 +fi + +if [ -z "${PATH_ORIG}" ]; then export PATH_ORIG="${PATH}"; fi + +WD=`pwd` +export RIDE_BIN="/cygdrive/c/Program Files/Raisonance/Ride/arm-gcc/bin" +export BUILDROOT_BIN="${WD}/../buildroot/build_arm_nofpu/staging_dir/bin" +export PATH="${BUILDROOT_BIN}:${RIDE_BIN}:/sbin:/usr/sbin:${PATH_ORIG}" + +echo "PATH : ${PATH}" diff --git a/nuttx/configs/px4io/nsh/Make.defs b/nuttx/configs/px4io/nsh/Make.defs new file mode 100644 index 0000000000..87508e22ec --- /dev/null +++ b/nuttx/configs/px4io/nsh/Make.defs @@ -0,0 +1,3 @@ +include ${TOPDIR}/.config + +include $(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/common/Make.defs diff --git a/nuttx/configs/px4io/nsh/appconfig b/nuttx/configs/px4io/nsh/appconfig new file mode 100644 index 0000000000..d5809a9391 --- /dev/null +++ b/nuttx/configs/px4io/nsh/appconfig @@ -0,0 +1,43 @@ +############################################################################ +# configs/stm3210e-eval/nsh/appconfig +# +# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Path to example in apps/examples containing the user_start entry point + +CONFIGURED_APPS += examples/nsh + +CONFIGURED_APPS += system/readline +CONFIGURED_APPS += nshlib +CONFIGURED_APPS += reboot + diff --git a/nuttx/configs/px4io/nsh/defconfig b/nuttx/configs/px4io/nsh/defconfig new file mode 100755 index 0000000000..6f4e208691 --- /dev/null +++ b/nuttx/configs/px4io/nsh/defconfig @@ -0,0 +1,565 @@ +############################################################################ +# configs/px4io/nsh/defconfig +# +# Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ +# +# architecture selection +# +# CONFIG_ARCH - identifies the arch subdirectory and, hence, the +# processor architecture. +# CONFIG_ARCH_family - for use in C code. This identifies the +# particular chip family that the architecture is implemented +# in. +# CONFIG_ARCH_architecture - for use in C code. This identifies the +# specific architecture within the chip familyl. +# CONFIG_ARCH_CHIP - Identifies the arch/*/chip subdirectory +# CONFIG_ARCH_CHIP_name - For use in C code +# CONFIG_ARCH_BOARD - identifies the configs subdirectory and, hence, +# the board that supports the particular chip or SoC. +# CONFIG_ARCH_BOARD_name - for use in C code +# CONFIG_ENDIAN_BIG - define if big endian (default is little endian) +# CONFIG_BOARD_LOOPSPERMSEC - for delay loops +# CONFIG_DRAM_SIZE - Describes the installed DRAM. +# CONFIG_DRAM_START - The start address of DRAM (physical) +# CONFIG_DRAM_END - Last address+1 of installed RAM +# CONFIG_ARCH_IRQPRIO - The ST32F100CB supports interrupt prioritization +# CONFIG_ARCH_INTERRUPTSTACK - This architecture supports an interrupt +# stack. If defined, this symbol is the size of the interrupt +# stack in bytes. If not defined, the user task stacks will be +# used during interrupt handling. +# CONFIG_ARCH_STACKDUMP - Do stack dumps after assertions +# CONFIG_ARCH_BOOTLOADER - Set if you are using a bootloader. +# CONFIG_ARCH_LEDS - Use LEDs to show state. Unique to board architecture. +# CONFIG_ARCH_BUTTONS - Enable support for buttons. Unique to board architecture. +# CONFIG_ARCH_CALIBRATION - Enables some build in instrumentation that +# cause a 100 second delay during boot-up. This 100 second delay +# serves no purpose other than it allows you to calibrate +# CONFIG_BOARD_LOOPSPERMSEC. You simply use a stop watch to measure +# the 100 second delay then adjust CONFIG_BOARD_LOOPSPERMSEC until +# the delay actually is 100 seconds. +# CONFIG_ARCH_DMA - Support DMA initialization +# +CONFIG_ARCH=arm +CONFIG_ARCH_ARM=y +CONFIG_ARCH_CORTEXM3=y +CONFIG_ARCH_CHIP=stm32 +CONFIG_ARCH_CHIP_STM32F100C8=y +CONFIG_ARCH_BOARD=px4io +CONFIG_ARCH_BOARD_PX4IO=y +CONFIG_BOARD_LOOPSPERMSEC=24000 +CONFIG_DRAM_SIZE=0x00002000 +CONFIG_DRAM_START=0x20000000 +CONFIG_DRAM_END=(CONFIG_DRAM_START+CONFIG_DRAM_SIZE) +CONFIG_ARCH_IRQPRIO=y +CONFIG_ARCH_INTERRUPTSTACK=n +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_BOOTLOADER=n +CONFIG_ARCH_LEDS=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CALIBRATION=n +CONFIG_ARCH_DMA=n +CONFIG_ARMV7M_CMNVECTOR=y + +# +# JTAG Enable settings (by default JTAG-DP and SW-DP are disabled): +# +# CONFIG_STM32_DFU - Use the DFU bootloader, not JTAG +# +# JTAG Enable options: +# +# CONFIG_STM32_JTAG_FULL_ENABLE - Enables full SWJ (JTAG-DP + SW-DP) +# CONFIG_STM32_JTAG_NOJNTRST_ENABLE - Enables full SWJ (JTAG-DP + SW-DP) +# but without JNTRST. +# CONFIG_STM32_JTAG_SW_ENABLE - Set JTAG-DP disabled and SW-DP enabled +# +CONFIG_STM32_DFU=n +CONFIG_STM32_JTAG_FULL_ENABLE=y +CONFIG_STM32_JTAG_NOJNTRST_ENABLE=n +CONFIG_STM32_JTAG_SW_ENABLE=n + +# +# Individual subsystems can be enabled: +# AHB: +CONFIG_STM32_DMA1=n +CONFIG_STM32_DMA2=n +CONFIG_STM32_CRC=n +# APB1: +# Timers 2,3 and 4 are owned by the PWM driver +CONFIG_STM32_TIM2=n +CONFIG_STM32_TIM3=n +CONFIG_STM32_TIM4=n +CONFIG_STM32_TIM5=n +CONFIG_STM32_TIM6=n +CONFIG_STM32_TIM7=n +CONFIG_STM32_WWDG=n +CONFIG_STM32_SPI2=n +CONFIG_STM32_USART2=y +CONFIG_STM32_USART3=y +CONFIG_STM32_I2C1=y +CONFIG_STM32_I2C2=n +CONFIG_STM32_BKP=n +CONFIG_STM32_PWR=n +CONFIG_STM32_DAC=n +# APB2: +CONFIG_STM32_ADC1=y +CONFIG_STM32_ADC2=n +# TIM1 is owned by the HRT +CONFIG_STM32_TIM1=n +CONFIG_STM32_SPI1=n +CONFIG_STM32_TIM8=n +CONFIG_STM32_USART1=y +CONFIG_STM32_ADC3=n + +# +# Timer and I2C devices may need to the following to force power to be applied: +# +#CONFIG_STM32_FORCEPOWER=y + +# +# STM32F100 specific serial device driver settings +# +# CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the +# console and ttys0 (default is the USART1). +# CONFIG_USARTn_RXBUFSIZE - Characters are buffered as received. +# This specific the size of the receive buffer +# CONFIG_USARTn_TXBUFSIZE - Characters are buffered before +# being sent. This specific the size of the transmit buffer +# CONFIG_USARTn_BAUD - The configure BAUD of the UART. Must be +# CONFIG_USARTn_BITS - The number of bits. Must be either 7 or 8. +# CONFIG_USARTn_PARTIY - 0=no parity, 1=odd parity, 2=even parity +# CONFIG_USARTn_2STOP - Two stop bits +# +CONFIG_USART1_SERIAL_CONSOLE=y +CONFIG_USART2_SERIAL_CONSOLE=n +CONFIG_USART3_SERIAL_CONSOLE=n + +CONFIG_USART1_TXBUFSIZE=64 +CONFIG_USART2_TXBUFSIZE=64 +CONFIG_USART3_TXBUFSIZE=64 + +CONFIG_USART1_RXBUFSIZE=64 +CONFIG_USART2_RXBUFSIZE=64 +CONFIG_USART3_RXBUFSIZE=64 + +CONFIG_USART1_BAUD=57600 +CONFIG_USART2_BAUD=115200 +CONFIG_USART3_BAUD=115200 + +CONFIG_USART1_BITS=8 +CONFIG_USART2_BITS=8 +CONFIG_USART3_BITS=8 + +CONFIG_USART1_PARITY=0 +CONFIG_USART2_PARITY=0 +CONFIG_USART3_PARITY=0 + +CONFIG_USART1_2STOP=0 +CONFIG_USART2_2STOP=0 +CONFIG_USART3_2STOP=0 + +# +# PX4IO specific driver settings +# +# CONFIG_HRT_TIMER +# Enables the high-resolution timer. The board definition must +# set HRT_TIMER and HRT_TIMER_CHANNEL to the timer and capture/ +# compare channels to be used. +# CONFIG_HRT_PPM +# Enables R/C PPM input using the HRT. The board definition must +# set HRT_PPM_CHANNEL to the timer capture/compare channel to be +# used, and define GPIO_PPM_IN to configure the appropriate timer +# GPIO. +# CONFIG_PWM_SERVO +# Enables the PWM servo driver. The driver configuration must be +# supplied by the board support at initialisation time. +# Note that USART2 must be disabled on the PX4 board for this to +# be available. +# +# +CONFIG_HRT_TIMER=y +CONFIG_HRT_PPM=y +CONFIG_PWM_SERVO=y + +# +# General build options +# +# CONFIG_RRLOAD_BINARY - make the rrload binary format used with +# BSPs from www.ridgerun.com using the tools/mkimage.sh script +# CONFIG_INTELHEX_BINARY - make the Intel HEX binary format +# used with many different loaders using the GNU objcopy program +# Should not be selected if you are not using the GNU toolchain. +# CONFIG_MOTOROLA_SREC - make the Motorola S-Record binary format +# used with many different loaders using the GNU objcopy program +# Should not be selected if you are not using the GNU toolchain. +# CONFIG_RAW_BINARY - make a raw binary format file used with many +# different loaders using the GNU objcopy program. This option +# should not be selected if you are not using the GNU toolchain. +# CONFIG_HAVE_LIBM - toolchain supports libm.a +# +CONFIG_RRLOAD_BINARY=n +CONFIG_INTELHEX_BINARY=n +CONFIG_MOTOROLA_SREC=n +CONFIG_RAW_BINARY=y +CONFIG_HAVE_LIBM=n + +# +# General OS setup +# +# CONFIG_APPS_DIR - Identifies the relative path to the directory +# that builds the application to link with NuttX. Default: ../apps +# CONFIG_DEBUG - enables built-in debug options +# CONFIG_DEBUG_VERBOSE - enables verbose debug output +# CONFIG_DEBUG_SYMBOLS - build without optimization and with +# debug symbols (needed for use with a debugger). +# CONFIG_HAVE_CXX - Enable support for C++ +# CONFIG_HAVE_CXXINITIALIZE - The platform-specific logic includes support +# for initialization of static C++ instances for this architecture +# and for the selected toolchain (via up_cxxinitialize()). +# CONFIG_MM_REGIONS - If the architecture includes multiple +# regions of memory to allocate from, this specifies the +# number of memory regions that the memory manager must +# handle and enables the API mm_addregion(start, end); +# CONFIG_ARCH_LOWPUTC - architecture supports low-level, boot +# time console output +# CONFIG_MSEC_PER_TICK - The default system timer is 100Hz +# or MSEC_PER_TICK=10. This setting may be defined to +# inform NuttX that the processor hardware is providing +# system timer interrupts at some interrupt interval other +# than 10 msec. +# CONFIG_RR_INTERVAL - The round robin timeslice will be set +# this number of milliseconds; Round robin scheduling can +# be disabled by setting this value to zero. +# CONFIG_SCHED_INSTRUMENTATION - enables instrumentation in +# scheduler to monitor system performance +# CONFIG_TASK_NAME_SIZE - Spcifies that maximum size of a +# task name to save in the TCB. Useful if scheduler +# instrumentation is selected. Set to zero to disable. +# CONFIG_START_YEAR, CONFIG_START_MONTH, CONFIG_START_DAY - +# Used to initialize the internal time logic. +# CONFIG_GREGORIAN_TIME - Enables Gregorian time conversions. +# You would only need this if you are concerned about accurate +# time conversions in the past or in the distant future. +# CONFIG_JULIAN_TIME - Enables Julian time conversions. You +# would only need this if you are concerned about accurate +# time conversion in the distand past. You must also define +# CONFIG_GREGORIAN_TIME in order to use Julian time. +# CONFIG_DEV_CONSOLE - Set if architecture-specific logic +# provides /dev/console. Enables stdout, stderr, stdin. +# CONFIG_DEV_LOWCONSOLE - Use the simple, low-level serial console +# driver (minimul support) +# CONFIG_MUTEX_TYPES: Set to enable support for recursive and +# errorcheck mutexes. Enables pthread_mutexattr_settype(). +# CONFIG_PRIORITY_INHERITANCE : Set to enable support for priority +# inheritance on mutexes and semaphores. +# CONFIG_SEM_PREALLOCHOLDERS: This setting is only used if priority +# inheritance is enabled. It defines the maximum number of +# different threads (minus one) that can take counts on a +# semaphore with priority inheritance support. This may be +# set to zero if priority inheritance is disabled OR if you +# are only using semaphores as mutexes (only one holder) OR +# if no more than two threads participate using a counting +# semaphore. +# CONFIG_SEM_NNESTPRIO. If priority inheritance is enabled, +# then this setting is the maximum number of higher priority +# threads (minus 1) than can be waiting for another thread +# to release a count on a semaphore. This value may be set +# to zero if no more than one thread is expected to wait for +# a semaphore. +# CONFIG_FDCLONE_DISABLE. Disable cloning of all file descriptors +# by task_create() when a new task is started. If set, all +# files/drivers will appear to be closed in the new task. +# CONFIG_FDCLONE_STDIO. Disable cloning of all but the first +# three file descriptors (stdin, stdout, stderr) by task_create() +# when a new task is started. If set, all files/drivers will +# appear to be closed in the new task except for stdin, stdout, +# and stderr. +# CONFIG_SDCLONE_DISABLE. Disable cloning of all socket +# desciptors by task_create() when a new task is started. If +# set, all sockets will appear to be closed in the new task. +# CONFIG_NXFLAT. Enable support for the NXFLAT binary format. +# This format will support execution of NuttX binaries located +# in a ROMFS filesystem (see examples/nxflat). +# CONFIG_SCHED_WORKQUEUE. Create a dedicated "worker" thread to +# handle delayed processing from interrupt handlers. This feature +# is required for some drivers but, if there are not complaints, +# can be safely disabled. The worker thread also performs +# garbage collection -- completing any delayed memory deallocations +# from interrupt handlers. If the worker thread is disabled, +# then that clean will be performed by the IDLE thread instead +# (which runs at the lowest of priority and may not be appropriate +# if memory reclamation is of high priority). If CONFIG_SCHED_WORKQUEUE +# is enabled, then the following options can also be used: +# CONFIG_SCHED_WORKPRIORITY - The execution priority of the worker +# thread. Default: 50 +# CONFIG_SCHED_WORKPERIOD - How often the worker thread checks for +# work in units of microseconds. Default: 50*1000 (50 MS). +# CONFIG_SCHED_WORKSTACKSIZE - The stack size allocated for the worker +# thread. Default: CONFIG_IDLETHREAD_STACKSIZE. +# CONFIG_SIG_SIGWORK - The signal number that will be used to wake-up +# the worker thread. Default: 4 +# +#CONFIG_APPS_DIR= +CONFIG_DEBUG=n +CONFIG_DEBUG_VERBOSE=n +CONFIG_DEBUG_SYMBOLS=y +CONFIG_HAVE_CXX=n +CONFIG_HAVE_CXXINITIALIZE=n +CONFIG_MM_REGIONS=1 +CONFIG_MM_SMALL=y +CONFIG_ARCH_LOWPUTC=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_INSTRUMENTATION=n +CONFIG_TASK_NAME_SIZE=0 +CONFIG_START_YEAR=2009 +CONFIG_START_MONTH=9 +CONFIG_START_DAY=21 +CONFIG_GREGORIAN_TIME=n +CONFIG_JULIAN_TIME=n +CONFIG_DEV_CONSOLE=y +CONFIG_DEV_LOWCONSOLE=n +CONFIG_MUTEX_TYPES=n +CONFIG_PRIORITY_INHERITANCE=n +CONFIG_SEM_PREALLOCHOLDERS=0 +CONFIG_SEM_NNESTPRIO=0 +CONFIG_FDCLONE_DISABLE=n +CONFIG_FDCLONE_STDIO=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_NXFLAT=n +CONFIG_SCHED_WORKQUEUE=n +CONFIG_SCHED_WORKPRIORITY=50 +CONFIG_SCHED_WORKPERIOD=(50*1000) +CONFIG_SCHED_WORKSTACKSIZE=512 +CONFIG_SIG_SIGWORK=4 + +# +# The following can be used to disable categories of +# APIs supported by the OS. If the compiler supports +# weak functions, then it should not be necessary to +# disable functions unless you want to restrict usage +# of those APIs. +# +# There are certain dependency relationships in these +# features. +# +# o mq_notify logic depends on signals to awaken tasks +# waiting for queues to become full or empty. +# o pthread_condtimedwait() depends on signals to wake +# up waiting tasks. +# +CONFIG_DISABLE_CLOCK=n +CONFIG_DISABLE_POSIX_TIMERS=y +CONFIG_DISABLE_PTHREAD=n +CONFIG_DISABLE_SIGNALS=n +CONFIG_DISABLE_MQUEUE=y +CONFIG_DISABLE_MOUNTPOINT=y +CONFIG_DISABLE_ENVIRON=y +CONFIG_DISABLE_POLL=y + +# +# Misc libc settings +# +# CONFIG_NOPRINTF_FIELDWIDTH - sprintf-related logic is a +# little smaller if we do not support fieldwidthes +# +CONFIG_NOPRINTF_FIELDWIDTH=n + +# +# Allow for architecture optimized implementations +# +# The architecture can provide optimized versions of the +# following to improve system performance +# +CONFIG_ARCH_MEMCPY=n +CONFIG_ARCH_MEMCMP=n +CONFIG_ARCH_MEMMOVE=n +CONFIG_ARCH_MEMSET=n +CONFIG_ARCH_STRCMP=n +CONFIG_ARCH_STRCPY=n +CONFIG_ARCH_STRNCPY=n +CONFIG_ARCH_STRLEN=n +CONFIG_ARCH_STRNLEN=n +CONFIG_ARCH_BZERO=n + +# +# Sizes of configurable things (0 disables) +# +# CONFIG_MAX_TASKS - The maximum number of simultaneously +# active tasks. This value must be a power of two. +# CONFIG_MAX_TASK_ARGS - This controls the maximum number of +# of parameters that a task may receive (i.e., maxmum value +# of 'argc') +# CONFIG_NPTHREAD_KEYS - The number of items of thread- +# specific data that can be retained +# CONFIG_NFILE_DESCRIPTORS - The maximum number of file +# descriptors (one for each open) +# CONFIG_NFILE_STREAMS - The maximum number of streams that +# can be fopen'ed +# CONFIG_NAME_MAX - The maximum size of a file name. +# CONFIG_STDIO_BUFFER_SIZE - Size of the buffer to allocate +# on fopen. (Only if CONFIG_NFILE_STREAMS > 0) +# CONFIG_NUNGET_CHARS - Number of characters that can be +# buffered by ungetc() (Only if CONFIG_NFILE_STREAMS > 0) +# CONFIG_PREALLOC_MQ_MSGS - The number of pre-allocated message +# structures. The system manages a pool of preallocated +# message structures to minimize dynamic allocations +# CONFIG_MQ_MAXMSGSIZE - Message structures are allocated with +# a fixed payload size given by this settin (does not include +# other message structure overhead. +# CONFIG_MAX_WDOGPARMS - Maximum number of parameters that +# can be passed to a watchdog handler +# CONFIG_PREALLOC_WDOGS - The number of pre-allocated watchdog +# structures. The system manages a pool of preallocated +# watchdog structures to minimize dynamic allocations +# CONFIG_PREALLOC_TIMERS - The number of pre-allocated POSIX +# timer structures. The system manages a pool of preallocated +# timer structures to minimize dynamic allocations. Set to +# zero for all dynamic allocations. +# +CONFIG_MAX_TASKS=4 +CONFIG_MAX_TASK_ARGS=4 +CONFIG_NPTHREAD_KEYS=2 +CONFIG_NFILE_DESCRIPTORS=6 +CONFIG_NFILE_STREAMS=4 +CONFIG_NAME_MAX=32 +CONFIG_STDIO_BUFFER_SIZE=64 +CONFIG_NUNGET_CHARS=2 +CONFIG_PREALLOC_MQ_MSGS=1 +CONFIG_MQ_MAXMSGSIZE=32 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_PREALLOC_WDOGS=3 +CONFIG_PREALLOC_TIMERS=1 + + +# +# Settings for apps/nshlib +# +# CONFIG_NSH_BUILTIN_APPS - Support external registered, +# "named" applications that can be executed from the NSH +# command line (see apps/README.txt for more information). +# CONFIG_NSH_FILEIOSIZE - Size of a static I/O buffer +# CONFIG_NSH_STRERROR - Use strerror(errno) +# CONFIG_NSH_LINELEN - Maximum length of one command line +# CONFIG_NSH_NESTDEPTH - Max number of nested if-then[-else]-fi +# CONFIG_NSH_DISABLESCRIPT - Disable scripting support +# CONFIG_NSH_DISABLEBG - Disable background commands +# CONFIG_NSH_ROMFSETC - Use startup script in /etc +# CONFIG_NSH_CONSOLE - Use serial console front end +# CONFIG_NSH_TELNET - Use telnetd console front end +# CONFIG_NSH_ARCHINIT - Platform provides architecture +# specific initialization (nsh_archinitialize()). +# +# If CONFIG_NSH_TELNET is selected: +# CONFIG_NSH_IOBUFFER_SIZE -- Telnetd I/O buffer size +# CONFIG_NSH_DHCPC - Obtain address using DHCP +# CONFIG_NSH_IPADDR - Provides static IP address +# CONFIG_NSH_DRIPADDR - Provides static router IP address +# CONFIG_NSH_NETMASK - Provides static network mask +# CONFIG_NSH_NOMAC - Use a bogus MAC address +# +# If CONFIG_NSH_ROMFSETC is selected: +# CONFIG_NSH_ROMFSMOUNTPT - ROMFS mountpoint +# CONFIG_NSH_INITSCRIPT - Relative path to init script +# CONFIG_NSH_ROMFSDEVNO - ROMFS RAM device minor +# CONFIG_NSH_ROMFSSECTSIZE - ROMF sector size +# CONFIG_NSH_FATDEVNO - FAT FS RAM device minor +# CONFIG_NSH_FATSECTSIZE - FAT FS sector size +# CONFIG_NSH_FATNSECTORS - FAT FS number of sectors +# CONFIG_NSH_FATMOUNTPT - FAT FS mountpoint +# +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=64 +CONFIG_NSH_STRERROR=n +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_NESTDEPTH=1 +CONFIG_NSH_DISABLESCRIPT=y +CONFIG_NSH_DISABLEBG=n +CONFIG_NSH_ROMFSETC=n +CONFIG_NSH_CONSOLE=y +CONFIG_NSH_TELNET=n +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_IOBUFFER_SIZE=256 +#CONFIG_NSH_STACKSIZE=1024 +CONFIG_NSH_DHCPC=n +CONFIG_NSH_NOMAC=n +CONFIG_NSH_IPADDR=(10<<24|0<<16|0<<8|2) +CONFIG_NSH_DRIPADDR=(10<<24|0<<16|0<<8|1) +CONFIG_NSH_NETMASK=(255<<24|255<<16|255<<8|0) +CONFIG_NSH_ROMFSMOUNTPT="/etc" +CONFIG_NSH_INITSCRIPT="init.d/rcS" +CONFIG_NSH_ROMFSDEVNO=0 +CONFIG_NSH_ROMFSSECTSIZE=64 +CONFIG_NSH_FATDEVNO=1 +CONFIG_NSH_FATSECTSIZE=512 +CONFIG_NSH_FATNSECTORS=1024 +CONFIG_NSH_FATMOUNTPT=/tmp + +# +# Architecture-specific NSH options +# +CONFIG_NSH_MMCSDSPIPORTNO=0 +CONFIG_NSH_MMCSDSLOTNO=0 +CONFIG_NSH_MMCSDMINOR=0 + +# +# Stack and heap information +# +# CONFIG_BOOT_RUNFROMFLASH - Some configurations support XIP +# operation from FLASH but must copy initialized .data sections to RAM. +# (should also be =n for the STM3210E-EVAL which always runs from flash) +# CONFIG_BOOT_COPYTORAM - Some configurations boot in FLASH +# but copy themselves entirely into RAM for better performance. +# CONFIG_CUSTOM_STACK - The up_ implementation will handle +# all stack operations outside of the nuttx model. +# CONFIG_STACK_POINTER - The initial stack pointer (arm7tdmi only) +# CONFIG_IDLETHREAD_STACKSIZE - The size of the initial stack. +# This is the thread that (1) performs the inital boot of the system up +# to the point where user_start() is spawned, and (2) there after is the +# IDLE thread that executes only when there is no other thread ready to +# run. +# CONFIG_USERMAIN_STACKSIZE - The size of the stack to allocate +# for the main user thread that begins at the user_start() entry point. +# CONFIG_PTHREAD_STACK_MIN - Minimum pthread stack size +# CONFIG_PTHREAD_STACK_DEFAULT - Default pthread stack size +# CONFIG_HEAP_BASE - The beginning of the heap +# CONFIG_HEAP_SIZE - The size of the heap +# +CONFIG_BOOT_RUNFROMFLASH=n +CONFIG_BOOT_COPYTORAM=n +CONFIG_CUSTOM_STACK=n +CONFIG_STACK_POINTER= +CONFIG_IDLETHREAD_STACKSIZE=800 +CONFIG_USERMAIN_STACKSIZE=1024 +CONFIG_PTHREAD_STACK_MIN=256 +CONFIG_PTHREAD_STACK_DEFAULT=512 +CONFIG_HEAP_BASE= +CONFIG_HEAP_SIZE= diff --git a/nuttx/configs/px4io/nsh/setenv.sh b/nuttx/configs/px4io/nsh/setenv.sh new file mode 100755 index 0000000000..d836851921 --- /dev/null +++ b/nuttx/configs/px4io/nsh/setenv.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# configs/stm3210e-eval/dfu/setenv.sh +# +# Copyright (C) 2009 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +if [ "$(basename $0)" = "setenv.sh" ] ; then + echo "You must source this script, not run it!" 1>&2 + exit 1 +fi + +if [ -z "${PATH_ORIG}" ]; then export PATH_ORIG="${PATH}"; fi + +WD=`pwd` +export RIDE_BIN="/cygdrive/c/Program Files/Raisonance/Ride/arm-gcc/bin" +export BUILDROOT_BIN="${WD}/../buildroot/build_arm_nofpu/staging_dir/bin" +export PATH="${BUILDROOT_BIN}:${RIDE_BIN}:/sbin:/usr/sbin:${PATH_ORIG}" + +echo "PATH : ${PATH}" diff --git a/nuttx/configs/px4io/src/Makefile b/nuttx/configs/px4io/src/Makefile new file mode 100644 index 0000000000..0ce004658c --- /dev/null +++ b/nuttx/configs/px4io/src/Makefile @@ -0,0 +1,95 @@ +############################################################################ +# configs/stm3210e-eval/src/Makefile +# +# Copyright (C) 2009-2010 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +CFLAGS += -I$(TOPDIR)/sched + +ASRCS = +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +CSRCS = up_boot.c up_hrt.c\ + drv_pwm_servo.c drv_ppm_input.c drv_gpio.c \ + up_boardinitialize.c + +ifeq ($(CONFIG_NSH_ARCHINIT),y) +CSRCS += up_nsh.c +endif + +ifeq ($(CONFIG_ADC),y) +CSRCS += up_adc.c +endif + +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ARCH_SRCDIR = $(TOPDIR)/arch/$(CONFIG_ARCH)/src +ifeq ($(WINTOOL),y) + CFLAGS += -I "${shell cygpath -w $(ARCH_SRCDIR)/chip}" \ + -I "${shell cygpath -w $(ARCH_SRCDIR)/common}" \ + -I "${shell cygpath -w $(ARCH_SRCDIR)/armv7-m}" +else + CFLAGS += -I$(ARCH_SRCDIR)/chip -I$(ARCH_SRCDIR)/common -I$(ARCH_SRCDIR)/armv7-m +endif + +all: libboard$(LIBEXT) + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS) $(LINKOBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +libboard$(LIBEXT): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +.depend: Makefile $(SRCS) + @$(MKDEP) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f libboard$(LIBEXT) *~ .*.swp + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/configs/px4io/src/README.txt b/nuttx/configs/px4io/src/README.txt new file mode 100644 index 0000000000..d4eda82fd7 --- /dev/null +++ b/nuttx/configs/px4io/src/README.txt @@ -0,0 +1 @@ +This directory contains drivers unique to the STMicro STM3210E-EVAL development board. diff --git a/nuttx/configs/px4io/src/drv_gpio.c b/nuttx/configs/px4io/src/drv_gpio.c new file mode 100644 index 0000000000..e53660a3ce --- /dev/null +++ b/nuttx/configs/px4io/src/drv_gpio.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file GPIO driver for PX4IO. + */ + +#include + +#include +#include + +#include + +#include +#include + +#include "px4io_internal.h" +#include "stm32_gpio.h" + +static int gpio_ioctl(struct file *filep, int cmd, unsigned long arg); + +static const struct file_operations gpio_fops = { + .ioctl = gpio_ioctl +}; + +/* + * Order of initialisers in this array must match the order of + * GPIO_ definitions in drv_gpio.h + */ +static const uint32_t gpios[] = { + /* settable */ + GPIO_ACC1_PWR_EN, + GPIO_ACC2_PWR_EN, + GPIO_SERVO_PWR_EN, + GPIO_RELAY1_EN, + GPIO_RELAY2_EN, + GPIO_LED1, + GPIO_LED2, + GPIO_LED3, + + /* readonly */ + GPIO_ACC_OC_DETECT, + GPIO_SERVO_OC_DETECT, + GPIO_BTN_SAFETY +}; + +int +gpio_drv_init(void) +{ + int i; + + /* initialise GPIOs */ + for (i = 0; i < GPIO_MAX; i++) + if (gpios[i]) + stm32_configgpio(gpios[i]); + + /* register the device */ + return register_driver("/dev/gpio", &gpio_fops, 0666, NULL); +} + +static int +gpio_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + /* attempt to set a GPIO? */ + if ((cmd >= GPIO_SET(0)) && (cmd <= GPIO_SET(GPIO_MAX_SETTABLE))) { + uint32_t gpio = gpios[cmd - GPIO_SET(0)]; + + if (gpio != 0) { + stm32_gpiowrite(gpio, arg ? true : false); + return 0; + } + } else if ((cmd >= GPIO_GET(0)) && (cmd <= GPIO_GET(GPIO_MAX))) { + uint32_t gpio = gpios[cmd - GPIO_GET(0)]; + + if (gpio != 0) + return stm32_gpioread(gpio) ? 1 : 0; + } + return -ENOTTY; +} \ No newline at end of file diff --git a/nuttx/configs/px4io/src/drv_i2c_device.c b/nuttx/configs/px4io/src/drv_i2c_device.c new file mode 100644 index 0000000000..1f5931ae5e --- /dev/null +++ b/nuttx/configs/px4io/src/drv_i2c_device.c @@ -0,0 +1,618 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + + /** + * @file A simple, polled I2C slave-mode driver. + * + * The master writes to and reads from a byte buffer, which the caller + * can update inbetween calls to the FSM. + */ + +#include + +#include "stm32_i2c.h" + +#include + +/* + * I2C register definitions. + */ +#define I2C_BASE STM32_I2C1_BASE + +#define REG(_reg) (*(volatile uint32_t *)(I2C_BASE + _reg)) + +#define rCR1 REG(STM32_I2C_CR1_OFFSET) +#define rCR2 REG(STM32_I2C_CR2_OFFSET) +#define rOAR1 REG(STM32_I2C_OAR1_OFFSET) +#define rOAR2 REG(STM32_I2C_OAR2_OFFSET) +#define rDR REG(STM32_I2C_DR_OFFSET) +#define rSR1 REG(STM32_I2C_SR1_OFFSET) +#define rSR2 REG(STM32_I2C_SR2_OFFSET) +#define rCCR REG(STM32_I2C_CCR_OFFSET) +#define rTRISE REG(STM32_I2C_TRISE_OFFSET) + +/* + * "event" values (cr2 << 16 | cr1) as described in the ST DriverLib + */ +#define I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED ((uint32_t)0x00020002) /* BUSY and ADDR flags */ +#define I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED ((uint32_t)0x00060082) /* TRA, BUSY, TXE and ADDR flags */ +#define I2C_EVENT_SLAVE_BYTE_RECEIVED ((uint32_t)0x00020040) /* BUSY and RXNE flags */ +#define I2C_EVENT_SLAVE_STOP_DETECTED ((uint32_t)0x00000010) /* STOPF flag */ +#define I2C_EVENT_SLAVE_BYTE_TRANSMITTED ((uint32_t)0x00060084) /* TRA, BUSY, TXE and BTF flags */ +#define I2C_EVENT_SLAVE_BYTE_TRANSMITTING ((uint32_t)0x00060080) /* TRA, BUSY and TXE flags */ +#define I2C_EVENT_SLAVE_ACK_FAILURE ((uint32_t)0x00000400) /* AF flag */ + +/** + * States implemented by the I2C FSM. + */ +enum fsm_state { + BAD_PHASE, // must be zero, default exit on a bad state transition + + WAIT_FOR_MASTER, + + /* write from master */ + WAIT_FOR_COMMAND, + RECEIVE_COMMAND, + RECEIVE_DATA, + HANDLE_COMMAND, + + /* read from master */ + WAIT_TO_SEND, + SEND_STATUS, + SEND_DATA, + + NUM_STATES +}; + +/** + * Events recognised by the I2C FSM. + */ +enum fsm_event { + /* automatic transition */ + AUTO, + + /* write from master */ + ADDRESSED_WRITE, + BYTE_RECEIVED, + STOP_RECEIVED, + + /* read from master */ + ADDRESSED_READ, + BYTE_SENDABLE, + ACK_FAILED, + + NUM_EVENTS +}; + +/** + * Context for the I2C FSM + */ +static struct fsm_context { + enum fsm_state state; + + /* XXX want to eliminate these */ + uint8_t command; + uint8_t status; + + uint8_t *data_ptr; + uint32_t data_count; + + size_t buffer_size; + uint8_t *buffer; +} context; + +/** + * Structure defining one FSM state and its outgoing transitions. + */ +struct fsm_transition { + void (*handler)(void); + enum fsm_state next_state[NUM_EVENTS]; +}; + +static bool i2c_command_received; + +static void fsm_event(enum fsm_event event); + +static void go_bad(void); +static void go_wait_master(void); + +static void go_wait_command(void); +static void go_receive_command(void); +static void go_receive_data(void); +static void go_handle_command(void); + +static void go_wait_send(void); +static void go_send_status(void); +static void go_send_buffer(void); + +/** + * The FSM state graph. + */ +static const struct fsm_transition fsm[NUM_STATES] = { + [BAD_PHASE] = { + .handler = go_bad, + .next_state = { + [AUTO] = WAIT_FOR_MASTER, + }, + }, + + [WAIT_FOR_MASTER] = { + .handler = go_wait_master, + .next_state = { + [ADDRESSED_WRITE] = WAIT_FOR_COMMAND, + [ADDRESSED_READ] = WAIT_TO_SEND, + }, + }, + + /* write from master*/ + [WAIT_FOR_COMMAND] = { + .handler = go_wait_command, + .next_state = { + [BYTE_RECEIVED] = RECEIVE_COMMAND, + [STOP_RECEIVED] = WAIT_FOR_MASTER, + }, + }, + [RECEIVE_COMMAND] = { + .handler = go_receive_command, + .next_state = { + [BYTE_RECEIVED] = RECEIVE_DATA, + [STOP_RECEIVED] = HANDLE_COMMAND, + }, + }, + [RECEIVE_DATA] = { + .handler = go_receive_data, + .next_state = { + [BYTE_RECEIVED] = RECEIVE_DATA, + [STOP_RECEIVED] = HANDLE_COMMAND, + }, + }, + [HANDLE_COMMAND] = { + .handler = go_handle_command, + .next_state = { + [AUTO] = WAIT_FOR_MASTER, + }, + }, + + /* buffer send */ + [WAIT_TO_SEND] = { + .handler = go_wait_send, + .next_state = { + [BYTE_SENDABLE] = SEND_STATUS, + }, + }, + [SEND_STATUS] = { + .handler = go_send_status, + .next_state = { + [BYTE_SENDABLE] = SEND_DATA, + [ACK_FAILED] = WAIT_FOR_MASTER, + }, + }, + [SEND_DATA] = { + .handler = go_send_buffer, + .next_state = { + [BYTE_SENDABLE] = SEND_DATA, + [ACK_FAILED] = WAIT_FOR_MASTER, + }, + }, +}; + + +/* debug support */ +#if 1 +struct fsm_logentry { + char kind; + uint32_t code; +}; + +#define LOG_ENTRIES 32 +static struct fsm_logentry fsm_log[LOG_ENTRIES]; +int fsm_logptr; +#define LOG_NEXT(_x) (((_x) + 1) % LOG_ENTRIES) +#define LOGx(_kind, _code) \ + do { \ + fsm_log[fsm_logptr].kind = _kind; \ + fsm_log[fsm_logptr].code = _code; \ + fsm_logptr = LOG_NEXT(fsm_logptr); \ + fsm_log[fsm_logptr].kind = 0; \ + } while(0) + +#define LOG(_kind, _code) \ + do {\ + if (fsm_logptr < LOG_ENTRIES) { \ + fsm_log[fsm_logptr].kind = _kind; \ + fsm_log[fsm_logptr].code = _code; \ + fsm_logptr++;\ + }\ + }while(0) + +#else +#define LOG(_kind, _code) +#endif + + +static void i2c_setclock(uint32_t frequency); + +/** + * Initialise I2C + * + */ +void +i2c_fsm_init(uint8_t *buffer, size_t buffer_size) +{ + /* save the buffer */ + context.buffer = buffer; + context.buffer_size = buffer_size; + + // initialise the FSM + context.status = 0; + context.command = 0; + context.state = BAD_PHASE; + fsm_event(AUTO); + +#if 0 + // enable the i2c block clock and reset it + modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_I2C1EN); + modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C1RST); + modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST, 0); + + // configure the i2c GPIOs + stm32_configgpio(GPIO_I2C1_SCL); + stm32_configgpio(GPIO_I2C1_SDA); + + // set the peripheral clock to match the APB clock + rCR2 = STM32_PCLK1_FREQUENCY / 1000000; + + // configure for 100kHz operation + i2c_setclock(100000); + + // enable i2c + rCR1 = I2C_CR1_PE; +#endif +} + +/** + * Run the I2C FSM for some period. + * + * @return True if the buffer has been updated by a command. + */ +bool +i2c_fsm(void) +{ + uint32_t event; + int idle_iterations = 0; + + for (;;) { + // handle bus error states by discarding the current operation + if (rSR1 & I2C_SR1_BERR) { + context.state = WAIT_FOR_MASTER; + rSR1 = ~I2C_SR1_BERR; + } + + // we do not anticipate over/underrun errors as clock-stretching is enabled + + // fetch the most recent event + event = ((rSR2 << 16) | rSR1) & 0x00ffffff; + + // generate FSM events based on I2C events + switch (event) { + case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: + LOG('w', 0); + fsm_event(ADDRESSED_WRITE); + break; + + case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: + LOG('r', 0); + fsm_event(ADDRESSED_READ); + break; + + case I2C_EVENT_SLAVE_BYTE_RECEIVED: + LOG('R', 0); + fsm_event(BYTE_RECEIVED); + break; + + case I2C_EVENT_SLAVE_STOP_DETECTED: + LOG('s', 0); + fsm_event(STOP_RECEIVED); + break; + + case I2C_EVENT_SLAVE_BYTE_TRANSMITTING: + //case I2C_EVENT_SLAVE_BYTE_TRANSMITTED: + LOG('T', 0); + fsm_event(BYTE_SENDABLE); + break; + + case I2C_EVENT_SLAVE_ACK_FAILURE: + LOG('a', 0); + fsm_event(ACK_FAILED); + break; + + default: + idle_iterations++; +// if ((event) && (event != 0x00020000)) +// LOG('e', event); + break; + } + + /* if we have just received something, drop out and let the caller handle it */ + if (i2c_command_received) { + i2c_command_received = false; + return true; + } + + /* if we have done nothing recently, drop out and let the caller have a slice */ + if (idle_iterations > 1000) + return false; + } +} + +/** + * Update the FSM with an event + * + * @param event New event. + */ +static void +fsm_event(enum fsm_event event) +{ + // move to the next state + context.state = fsm[context.state].next_state[event]; + + LOG('f', context.state); + + // call the state entry handler + if (fsm[context.state].handler) { + fsm[context.state].handler(); + } +} + +static void +go_bad() +{ + LOG('B', 0); + fsm_event(AUTO); +} + +/** + * Wait for the master to address us. + * + */ +static void +go_wait_master() +{ + // We currently don't have a command byte. + // + context.command = '\0'; + + // The data pointer starts pointing to the start of the data buffer. + // + context.data_ptr = context.buffer; + + // The data count is either: + // - the size of the data buffer + // - some value less than or equal the size of the data buffer during a write or a read + // + context.data_count = context.buffer_size; + + // (re)enable the peripheral, clear the stop event flag in + // case we just finished receiving data + rCR1 |= I2C_CR1_PE; + + // clear the ACK failed flag in case we just finished sending data + rSR1 = ~I2C_SR1_AF; +} + +/** + * Prepare to receive a command byte. + * + */ +static void +go_wait_command() +{ + // NOP +} + +/** + * Command byte has been received, save it and prepare to handle the data. + * + */ +static void +go_receive_command() +{ + + // fetch the command byte + context.command = (uint8_t)rDR; + LOG('c', context.command); + +} + +/** + * Receive a data byte. + * + */ +static void +go_receive_data() +{ + uint8_t d; + + // fetch the byte + d = (uint8_t)rDR; + LOG('d', d); + + // if we have somewhere to put it, do so + if (context.data_count) { + *context.data_ptr++ = d; + context.data_count--; + } +} + +/** + * Handle a command once the host is done sending it to us. + * + */ +static void +go_handle_command() +{ + // presume we are happy with the command + context.status = 0; + + // make a note that the buffer contains a fresh command + i2c_command_received = true; + + // kick along to the next state + fsm_event(AUTO); +} + +/** + * Wait to be able to send the status byte. + * + */ +static void +go_wait_send() +{ + // NOP +} + +/** + * Send the status byte. + * + */ +static void +go_send_status() +{ + rDR = context.status; + LOG('?', context.status); +} + +/** + * Send a data or pad byte. + * + */ +static void +go_send_buffer() +{ + if (context.data_count) { + LOG('D', *context.data_ptr); + rDR = *(context.data_ptr++); + context.data_count--; + } else { + LOG('-', 0); + rDR = 0xff; + } +} + +/* cribbed directly from the NuttX master driver */ +static void +i2c_setclock(uint32_t frequency) +{ + uint16_t cr1; + uint16_t ccr; + uint16_t trise; + uint16_t freqmhz; + uint16_t speed; + + /* Disable the selected I2C peripheral to configure TRISE */ + + cr1 = rCR1; + rCR1 &= ~I2C_CR1_PE; + + /* Update timing and control registers */ + + freqmhz = (uint16_t)(STM32_PCLK1_FREQUENCY / 1000000); + ccr = 0; + + /* Configure speed in standard mode */ + + if (frequency <= 100000) { + /* Standard mode speed calculation */ + + speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency << 1)); + + /* The CCR fault must be >= 4 */ + + if (speed < 4) { + /* Set the minimum allowed value */ + + speed = 4; + } + ccr |= speed; + + /* Set Maximum Rise Time for standard mode */ + + trise = freqmhz + 1; + + /* Configure speed in fast mode */ + } else { /* (frequency <= 400000) */ + /* Fast mode speed calculation with Tlow/Thigh = 16/9 */ + +#ifdef CONFIG_I2C_DUTY16_9 + speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 25)); + + /* Set DUTY and fast speed bits */ + + ccr |= (I2C_CCR_DUTY|I2C_CCR_FS); +#else + /* Fast mode speed calculation with Tlow/Thigh = 2 */ + + speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 3)); + + /* Set fast speed bit */ + + ccr |= I2C_CCR_FS; +#endif + + /* Verify that the CCR speed value is nonzero */ + + if (speed < 1) { + /* Set the minimum allowed value */ + + speed = 1; + } + ccr |= speed; + + /* Set Maximum Rise Time for fast mode */ + + trise = (uint16_t)(((freqmhz * 300) / 1000) + 1); + } + + /* Write the new values of the CCR and TRISE registers */ + + rCCR = ccr; + rTRISE = trise; + + /* Bit 14 of OAR1 must be configured and kept at 1 */ + + rOAR1 = I2C_OAR1_ONE); + + /* Re-enable the peripheral (or not) */ + + rCR1 = cr1; +} diff --git a/nuttx/configs/px4io/src/drv_ppm_input.c b/nuttx/configs/px4io/src/drv_ppm_input.c new file mode 100644 index 0000000000..f25ae41e27 --- /dev/null +++ b/nuttx/configs/px4io/src/drv_ppm_input.c @@ -0,0 +1,373 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file PPM input decoder. + * + * Works in conjunction with the HRT driver. + */ + + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "chip.h" +#include "up_internal.h" +#include "up_arch.h" + +#include "stm32_internal.h" +#include "stm32_gpio.h" +#include "stm32_tim.h" + +#ifdef CONFIG_HRT_PPM +# ifndef CONFIG_HRT_TIMER +# error CONFIG_HRT_PPM requires CONFIG_HRT_TIMER +# endif + +/* + * PPM decoder tuning parameters. + * + * The PPM decoder works as follows. + * + * Initially, the decoder waits in the UNSYNCH state for two edges + * separated by PPM_MIN_START. Once the second edge is detected, + * the decoder moves to the ARM state. + * + * The ARM state expects an edge within PPM_MAX_PULSE_WIDTH, being the + * timing mark for the first channel. If this is detected, it moves to + * the INACTIVE state. + * + * The INACTIVE phase waits for and discards the next edge, as it is not + * significant. Once the edge is detected, it moves to the ACTIVE stae. + * + * The ACTIVE state expects an edge within PPM_MAX_PULSE_WIDTH, and when + * received calculates the time from the previous mark and records + * this time as the value for the next channel. + * + * If at any time waiting for an edge, the delay from the previous edge + * exceeds PPM_MIN_START the frame is deemed to have ended and the recorded + * values are advertised to clients. + */ +#define PPM_MAX_PULSE_WIDTH 500 /* maximum width of a pulse */ +#define PPM_MIN_CHANNEL_VALUE 750 /* shortest valid channel signal */ +#define PPM_MAX_CHANNEL_VALUE 2400 /* longest valid channel signal */ +#define PPM_MIN_START 5000 /* shortest valid start gap */ + +/* Input timeout - after this interval we assume signal is lost */ +#define PPM_INPUT_TIMEOUT 100 * 1000 /* 100ms */ + +/* Number of same-sized frames required to 'lock' */ +#define PPM_CHANNEL_LOCK 3 /* should be less than the input timeout */ + +/* decoded PPM buffer */ +#define PPM_MIN_CHANNELS 4 +#define PPM_MAX_CHANNELS 12 +static uint16_t ppm_buffer[PPM_MAX_CHANNELS]; +static unsigned ppm_decoded_channels; + +static uint16_t ppm_temp_buffer[PPM_MAX_CHANNELS]; + +/* PPM decoder state machine */ +static struct { + uint16_t last_edge; /* last capture time */ + uint16_t last_mark; /* last significant edge */ + unsigned next_channel; + enum { + UNSYNCH = 0, + ARM, + ACTIVE, + INACTIVE + } phase; +} ppm; + +/* last time we got good data */ +static hrt_abstime ppm_timestamp; + +#ifndef CONFIG_DISABLE_MQUEUE +/* message queue we advertise PPM data on */ +static mqd_t ppm_message_queue; +#endif + +/* set if PPM data has not been read */ +static bool ppm_fresh_data; + +/* PPM device node file ops */ + +static int ppm_read(struct file *filp, char *buffer, size_t len); +static int ppm_ioctl(struct file *filp, int cmd, unsigned long arg); + +static const struct file_operations ppm_fops = { + .read = ppm_read, + .ioctl = ppm_ioctl +}; + +/* + * Initialise the PPM system for client use. + */ +int +ppm_input_init(const char *mq_name) +{ + int err; + + /* configure the PPM input pin */ + stm32_configgpio(GPIO_PPM_IN); + + /* and register the device node */ + if (OK != (err = register_driver(PPM_DEVICE_NODE, &ppm_fops, 0666, NULL))) + return err; + +#ifndef CONFIG_DISABLE_MQUEUE + if (mq_name != NULL) { + /* create the message queue */ + struct mq_attr attr = { + .mq_maxmsg = 1, + .mq_msgsize = sizeof(ppm_buffer) + }; + ppm_message_queue = mq_open(mq_name, O_WRONLY | O_CREAT | O_NONBLOCK, 0666, &attr); + if (ppm_message_queue < 0) + return -errno; + } +#endif + + return OK; +} + +/* + * Handle the PPM decoder state machine. + */ +void +ppm_input_decode(bool reset, uint16_t count) +{ + uint16_t width; + uint16_t interval; + unsigned i; + + /* if we missed an edge, we have to give up */ + if (reset) + goto error; + + /* how long since the last edge? */ + width = count - ppm.last_edge; + ppm.last_edge = count; + + /* + * If this looks like a start pulse, then push the last set of values + * and reset the state machine. + * + * Note that this is not a "high performance" design; it implies a whole + * frame of latency between the pulses being received and their being + * considered valid. + */ + if (width >= PPM_MIN_START) { + + /* + * If the number of channels changes unexpectedly, we don't want + * to just immediately jump on the new count as it may be a result + * of noise or dropped edges. Instead, take a few frames to settle. + */ + if (ppm.next_channel != ppm_decoded_channels) { + static int new_channel_count; + static int new_channel_holdoff; + + if (new_channel_count != ppm.next_channel) { + /* start the lock counter for the new channel count */ + new_channel_count = ppm.next_channel; + new_channel_holdoff = PPM_CHANNEL_LOCK; + + } else if (new_channel_holdoff > 0) { + /* this frame matched the last one, decrement the lock counter */ + new_channel_holdoff--; + + } else { + /* we have seen PPM_CHANNEL_LOCK frames with the new count, accept it */ + ppm_decoded_channels = new_channel_count; + new_channel_count = 0; + } + } else { + /* frame channel count matches expected, let's use it */ + if (ppm.next_channel > PPM_MIN_CHANNELS) { + for (i = 0; i < ppm.next_channel; i++) + ppm_buffer[i] = ppm_temp_buffer[i]; + ppm_timestamp = hrt_absolute_time(); + ppm_fresh_data = true; +#ifndef CONFIG_DISABLE_MQUEUE + /* advertise the new data to the message queue */ + mq_send(ppm_message_queue, ppm_buffer, ppm_decoded_channels * sizeof(ppm_buffer[0]), 0); +#endif + } + } + + /* reset for the next frame */ + ppm.next_channel = 0; + + /* next edge is the reference for the first channel */ + ppm.phase = ARM; + + return; + } + + switch (ppm.phase) { + case UNSYNCH: + /* we are waiting for a start pulse - nothing useful to do here */ + return; + + case ARM: + /* we expect a pulse giving us the first mark */ + if (width > PPM_MAX_PULSE_WIDTH) + goto error; /* pulse was too long */ + + /* record the mark timing, expect an inactive edge */ + ppm.last_mark = count; + ppm.phase = INACTIVE; + return; + + case INACTIVE: + /* this edge is not interesting, but now we are ready for the next mark */ + ppm.phase = ACTIVE; + + /* note that we don't bother looking at the timing of this edge */ + + return; + + case ACTIVE: + /* we expect a well-formed pulse */ + if (width > PPM_MAX_PULSE_WIDTH) + goto error; /* pulse was too long */ + + /* determine the interval from the last mark */ + interval = count - ppm.last_mark; + ppm.last_mark = count; + + /* if the mark-mark timing is out of bounds, abandon the frame */ + if ((interval < PPM_MIN_CHANNEL_VALUE) || (interval > PPM_MAX_CHANNEL_VALUE)) + goto error; + + /* if we have room to store the value, do so */ + if (ppm.next_channel < PPM_MAX_CHANNELS) + ppm_temp_buffer[ppm.next_channel++] = interval; + + ppm.phase = INACTIVE; + return; + + } + + /* the state machine is corrupted; reset it */ + +error: + /* we don't like the state of the decoder, reset it and try again */ + ppm.phase = UNSYNCH; + ppm_decoded_channels = 0; +} + +static int +ppm_read(struct file *filp, char *buffer, size_t len) +{ + size_t avail; + + /* the size of the returned data indicates the number of channels */ + avail = ppm_decoded_channels * sizeof(ppm_buffer[0]); + + /* if we have not decoded a frame, that's an I/O error */ + if (avail == 0) + return -EIO; + + /* if the caller's buffer is too small, that's also bad */ + if (len < avail) + return -EFBIG; + + /* if the caller doesn't want to block, and there is no fresh data, that's EWOULDBLOCK */ + if ((filp->f_oflags & O_NONBLOCK) && (!ppm_fresh_data)) + return -EWOULDBLOCK; + + /* + * Return the channel data. + * + * Note that we have to block the HRT while copying to avoid the + * possibility that we'll get interrupted in the middle of copying + * a single value. + */ + irqstate_t flags = irqsave(); + + memcpy(buffer, ppm_buffer, avail); + ppm_fresh_data = false; + + irqrestore(flags); + + return OK; +} + +static int +ppm_ioctl(struct file *filp, int cmd, unsigned long arg) +{ + switch (cmd) { + case PPM_INPUT_STATUS: + /* if we have received a frame within the timeout, the signal is "good" */ + if ((hrt_absolute_time() - ppm_timestamp) < PPM_INPUT_TIMEOUT) { + *(ppm_input_status_t *)arg = PPM_STATUS_SIGNAL_CURRENT; + } else { + /* reset the number of channels so that any attempt to read data will fail */ + ppm_decoded_channels = 0; + *(ppm_input_status_t *)arg = PPM_STATUS_NO_SIGNAL; + } + return OK; + + case PPM_INPUT_CHANNELS: + *(ppm_input_channel_count_t *)arg = ppm_decoded_channels; + return OK; + + default: + return -ENOTTY; + } + +} + +#endif /* CONFIG_HRT_PPM */ + + diff --git a/nuttx/configs/px4io/src/drv_pwm_servo.c b/nuttx/configs/px4io/src/drv_pwm_servo.c new file mode 100644 index 0000000000..7f3238da35 --- /dev/null +++ b/nuttx/configs/px4io/src/drv_pwm_servo.c @@ -0,0 +1,316 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Servo driver supporting PWM servos connected to STM32 timer blocks. + * + * Works with any of the 'generic' or 'advanced' STM32 timers that + * have output pins, does not require an interrupt. + */ + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include "stm32_gpio.h" +#include "stm32_tim.h" + +#ifdef CONFIG_PWM_SERVO + +static const struct pwm_servo_config *cfg; + +#define REG(_tmr, _reg) (*(volatile uint32_t *)(cfg->timers[_tmr].base + _reg)) + +#define rCR1(_tmr) REG(_tmr, STM32_GTIM_CR1_OFFSET) +#define rCR2(_tmr) REG(_tmr, STM32_GTIM_CR2_OFFSET) +#define rSMCR(_tmr) REG(_tmr, STM32_GTIM_SMCR_OFFSET) +#define rDIER(_tmr) REG(_tmr, STM32_GTIM_DIER_OFFSET) +#define rSR(_tmr) REG(_tmr, STM32_GTIM_SR_OFFSET) +#define rEGR(_tmr) REG(_tmr, STM32_GTIM_EGR_OFFSET) +#define rCCMR1(_tmr) REG(_tmr, STM32_GTIM_CCMR1_OFFSET) +#define rCCMR2(_tmr) REG(_tmr, STM32_GTIM_CCMR2_OFFSET) +#define rCCER(_tmr) REG(_tmr, STM32_GTIM_CCER_OFFSET) +#define rCNT(_tmr) REG(_tmr, STM32_GTIM_CNT_OFFSET) +#define rPSC(_tmr) REG(_tmr, STM32_GTIM_PSC_OFFSET) +#define rARR(_tmr) REG(_tmr, STM32_GTIM_ARR_OFFSET) +#define rCCR1(_tmr) REG(_tmr, STM32_GTIM_CCR1_OFFSET) +#define rCCR2(_tmr) REG(_tmr, STM32_GTIM_CCR2_OFFSET) +#define rCCR3(_tmr) REG(_tmr, STM32_GTIM_CCR3_OFFSET) +#define rCCR4(_tmr) REG(_tmr, STM32_GTIM_CCR4_OFFSET) +#define rDCR(_tmr) REG(_tmr, STM32_GTIM_DCR_OFFSET) +#define rDMAR(_tmr) REG(_tmr, STM32_GTIM_DMAR_OFFSET) + +static void +pwm_timer_init(unsigned timer) +{ + /* enable the timer clock before we try to talk to it */ + modifyreg32(cfg->timers[timer].clock_register, 0, cfg->timers[timer].clock_bit); + + /* disable and configure the timer */ + rCR1(timer) = 0; + rCR2(timer) = 0; + rSMCR(timer) = 0; + rDIER(timer) = 0; + rCCER(timer) = 0; + rCCMR1(timer) = 0; + rCCMR2(timer) = 0; + rCCER(timer) = 0; + rDCR(timer) = 0; + + /* configure the timer to free-run at 1MHz */ + rPSC(timer) = cfg->timers[timer].clock_freq / 1000000; + + /* and update at the desired rate */ + rARR(timer) = 1000000 / cfg->update_rate; + + /* generate an update event; reloads the counter and all registers */ + rEGR(timer) = GTIM_EGR_UG; + + /* note that the timer is left disabled - arming is performed separately */ +} + +static void +pwm_servos_arm(bool armed) +{ + /* iterate timers and arm/disarm appropriately */ + for (unsigned i = 0; i < PWM_SERVO_MAX_TIMERS; i++) { + if (cfg->timers[i].base != 0) + rCR1(i) = armed ? GTIM_CR1_CEN : 0; + } +} + +static void +pwm_channel_init(unsigned channel) +{ + unsigned timer = cfg->channels[channel].timer_index; + + /* configure the GPIO first */ + stm32_configgpio(cfg->channels[channel].gpio); + + /* configure the channel */ + switch (cfg->channels[channel].timer_channel) { + case 1: + rCCMR1(timer) |= (6 << 4); + rCCR1(timer) = cfg->channels[channel].default_value; + rCCER(timer) |= (1 << 0); + break; + case 2: + rCCMR1(timer) |= (6 << 12); + rCCR2(timer) = cfg->channels[channel].default_value; + rCCER(timer) |= (1 << 4); + break; + case 3: + rCCMR2(timer) |= (6 << 4); + rCCR3(timer) = cfg->channels[channel].default_value; + rCCER(timer) |= (1 << 8); + break; + case 4: + rCCMR2(timer) |= (6 << 12); + rCCR4(timer) = cfg->channels[channel].default_value; + rCCER(timer) |= (1 << 12); + break; + } +} + +static void +pwm_channel_set(unsigned channel, servo_position_t value) +{ + if (channel >= PWM_SERVO_MAX_CHANNELS) { + lldbg("pwm_channel_set: bogus channel %u\n", channel); + return; + } + + unsigned timer = cfg->channels[channel].timer_index; + + /* test timer for validity */ + if ((cfg->timers[timer].base == 0) || + (cfg->channels[channel].gpio == 0)) + return; + + /* configure the channel */ + switch (cfg->channels[channel].timer_channel) { + case 1: + rCCR1(timer) = value; + break; + case 2: + rCCR2(timer) = value; + break; + case 3: + rCCR3(timer) = value; + break; + case 4: + rCCR4(timer) = value; + break; + } +} + +static servo_position_t +pwm_channel_get(unsigned channel) +{ + if (channel >= PWM_SERVO_MAX_CHANNELS) { + lldbg("pwm_channel_get: bogus channel %u\n", channel); + return 0; + } + + unsigned timer = cfg->channels[channel].timer_index; + servo_position_t value = 0; + + /* test timer for validity */ + if ((cfg->timers[timer].base == 0) || + (cfg->channels[channel].gpio == 0)) + return 0; + + /* configure the channel */ + switch (cfg->channels[channel].timer_channel) { + case 1: + value = rCCR1(timer); + break; + case 2: + value = rCCR2(timer); + break; + case 3: + value = rCCR3(timer); + break; + case 4: + value = rCCR4(timer); + break; + } + return value; +} + +static int pwm_servo_write(struct file *filp, const char *buffer, size_t len); +static int pwm_servo_read(struct file *filp, char *buffer, size_t len); +static int pwm_servo_ioctl(struct file *filep, int cmd, unsigned long arg); + +static const struct file_operations pwm_servo_fops = { + .write = pwm_servo_write, + .read = pwm_servo_read, + .ioctl = pwm_servo_ioctl +}; + +static int +pwm_servo_write(struct file *filp, const char *buffer, size_t len) +{ + unsigned channels = len / sizeof(servo_position_t); + servo_position_t *pdata = (servo_position_t *)buffer; + unsigned i; + + if (channels > PWM_SERVO_MAX_CHANNELS) + return -EIO; + + for (i = 0; i < channels; i++) + pwm_channel_set(i, pdata[i]); + + return i * sizeof(servo_position_t); +} + +static int +pwm_servo_read(struct file *filp, char *buffer, size_t len) +{ + unsigned channels = len / sizeof(servo_position_t); + servo_position_t *pdata = (servo_position_t *)buffer; + unsigned i; + + if (channels > PWM_SERVO_MAX_CHANNELS) + return -EIO; + + for (i = 0; i < channels; i++) + pdata[i] = pwm_channel_get(i); + + return i * sizeof(servo_position_t); +} + +static int +pwm_servo_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + /* regular ioctl? */ + switch (cmd) { + case PWM_SERVO_ARM: + pwm_servos_arm(true); + return 0; + + case PWM_SERVO_DISARM: + pwm_servos_arm(false); + return 0; + } + + /* channel set? */ + if ((cmd >= PWM_SERVO_SET(0)) && (cmd < PWM_SERVO_SET(PWM_SERVO_MAX_CHANNELS))) { + /* XXX sanity-check value? */ + pwm_channel_set(cmd - PWM_SERVO_SET(0), (servo_position_t)arg); + return 0; + } + + /* channel get? */ + if ((cmd >= PWM_SERVO_GET(0)) && (cmd < PWM_SERVO_GET(PWM_SERVO_MAX_CHANNELS))) { + /* XXX sanity-check value? */ + *(servo_position_t *)arg = pwm_channel_get(cmd - PWM_SERVO_GET(0)); + return 0; + } + + /* not a recognised value */ + return -ENOTTY; +} + + +int +pwm_servo_init(const struct pwm_servo_config *config) +{ + /* save a pointer to the configuration */ + cfg = config; + + /* do basic timer initialisation first */ + for (unsigned i = 0; i < PWM_SERVO_MAX_TIMERS; i++) { + if (cfg->timers[i].base != 0) + pwm_timer_init(i); + } + + /* now init channels */ + for (unsigned i = 0; i < PWM_SERVO_MAX_CHANNELS; i++) { + if (cfg->channels[i].gpio != 0) + pwm_channel_init(i); + } + + /* register the device */ + return register_driver("/dev/pwm_servo", &pwm_servo_fops, 0666, NULL); +} + +#endif /* CONFIG_PWM_SERVO */ \ No newline at end of file diff --git a/nuttx/configs/px4io/src/px4io_internal.h b/nuttx/configs/px4io/src/px4io_internal.h new file mode 100644 index 0000000000..877a066537 --- /dev/null +++ b/nuttx/configs/px4io/src/px4io_internal.h @@ -0,0 +1,117 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file PX4IO hardware definitions. + */ + +#ifndef __CONFIGS_PX4IO_SRC_PX4IO_INTERNAL_H +#define __CONFIGS_PX4IO_SRC_PX4IO_INTERNAL_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/* PX4IO GPIOs **********************************************************************/ +/* LEDs */ + +#define GPIO_LED1 (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ + GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN14) +#define GPIO_LED2 (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ + GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN15) +#define GPIO_LED3 (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ + GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10) + +/* R/C in/out channels **************************************************************/ + +/* XXX just GPIOs for now - eventually timer pins */ + +#define GPIO_CH1_IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_CH2_IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_CH3_IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8) +#define GPIO_CH4_IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9) +#define GPIO_CH5_IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_CH6_IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_CH7_IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +#define GPIO_CH8_IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) + +#define GPIO_CH1_OUT (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN0) +#define GPIO_CH2_OUT (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN1) +#define GPIO_CH3_OUT (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN8) +#define GPIO_CH4_OUT (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN9) +#define GPIO_CH5_OUT (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN6) +#define GPIO_CH6_OUT (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN7) +#define GPIO_CH7_OUT (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN0) +#define GPIO_CH8_OUT (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN1) + +/* Safety switch button *************************************************************/ + +#define GPIO_BTN_SAFETY (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN5) + +/* Power switch controls ************************************************************/ + +#define GPIO_ACC1_PWR_EN (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN13) +#define GPIO_ACC2_PWR_EN (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN14) +#define GPIO_SERVO_PWR_EN (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN15) + +#define GPIO_ACC_OC_DETECT (GPIO_INPUT|GPIO_CNF_INPULLUP|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12) +#define GPIO_SERVO_OC_DETECT (GPIO_INPUT|GPIO_CNF_INPULLUP|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13) + +#define GPIO_RELAY1_EN (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN13) +#define GPIO_RELAY2_EN (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN12) + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public data + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#endif /* __ASSEMBLY__ */ +#endif /* __CONFIGS_PX4IO_SRC_PX4IO_INTERNAL_H */ + diff --git a/nuttx/configs/px4io/src/up_adc.c b/nuttx/configs/px4io/src/up_adc.c new file mode 100644 index 0000000000..c19f57f96b --- /dev/null +++ b/nuttx/configs/px4io/src/up_adc.c @@ -0,0 +1,164 @@ +/************************************************************************************ + * configs/stm3210e-eval/src/up_adc.c + * arch/arm/src/board/up_adc.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "chip.h" +#include "up_arch.h" + +#include "stm32_pwm.h" +#include "px4io-internal.h" + +#ifdef CONFIG_ADC + +/************************************************************************************ + * Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* Up to 3 ADC interfaces are supported */ + +#if STM32_NADC < 3 +# undef CONFIG_STM32_ADC3 +#endif + +#if STM32_NADC < 2 +# undef CONFIG_STM32_ADC2 +#endif + +#if STM32_NADC < 1 +# undef CONFIG_STM32_ADC1 +#endif + +#if defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2) || defined(CONFIG_STM32_ADC3) +#ifndef CONFIG_STM32_ADC1 +# warning "Channel information only available for ADC1" +#endif + +/* The number of ADC channels in the conversion list */ + +#define ADC1_NCHANNELS 2 + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +/* Identifying number of each ADC channel: Variable Resistor */ + +#ifdef CONFIG_STM32_ADC1 +static const uint8_t g_chanlist[ADC1_NCHANNELS] = {4, 5}; + +/* Configurations of pins used byte each ADC channels */ + +static const uint32_t g_pinlist[ADC1_NCHANNELS] = {GPIO_ADC1_IN4, GPIO_ADC1_IN5}; +#endif + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: adc_devinit + * + * Description: + * All STM32 architectures must provide the following interface to work with + * examples/adc. + * + ************************************************************************************/ + +int adc_devinit(void) +{ +#ifdef CONFIG_STM32_ADC1 + static bool initialized = false; + struct adc_dev_s *adc; + int ret; + int i; + + /* Check if we have already initialized */ + + if (!initialized) + { + /* Configure the pins as analog inputs for the selected channels */ + + for (i = 0; i < ADC1_NCHANNELS; i++) + { + stm32_configgpio(g_pinlist[i]); + } + + /* Call stm32_adcinitialize() to get an instance of the ADC interface */ + + adc = stm32_adcinitialize(1, g_chanlist, ADC1_NCHANNELS); + if (adc == NULL) + { + adbg("ERROR: Failed to get ADC interface\n"); + return -ENODEV; + } + + /* Register the ADC driver at "/dev/adc0" */ + + ret = adc_register("/dev/adc0", adc); + if (ret < 0) + { + adbg("adc_register failed: %d\n", ret); + return ret; + } + + /* Now we are initialized */ + + initialized = true; + } + + return OK; +#else + return -ENOSYS; +#endif +} + +#endif /* CONFIG_STM32_ADC1 || CONFIG_STM32_ADC2 || CONFIG_STM32_ADC3 */ +#endif /* CONFIG_ADC */ diff --git a/nuttx/configs/px4io/src/up_boardinitialize.c b/nuttx/configs/px4io/src/up_boardinitialize.c new file mode 100644 index 0000000000..f6900ebb54 --- /dev/null +++ b/nuttx/configs/px4io/src/up_boardinitialize.c @@ -0,0 +1,178 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file Board initialisation and configuration data. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "chip.h" +#include "up_internal.h" +#include "up_arch.h" + +#include "stm32_internal.h" +#include "stm32_gpio.h" +#include "stm32_tim.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Debug ********************************************************************/ + +/* Configuration ************************************************************/ + +#if CONFIG_PWM_SERVO + /* + * Servo configuration for the PX4IO board. + */ + static const struct pwm_servo_config servo_config = { + .update_rate = 50, + .timers = { + { + .base = STM32_TIM2_BASE, + .clock_register = STM32_RCC_APB1ENR, + .clock_bit = RCC_APB1ENR_TIM2EN, + .clock_freq = STM32_APB1_TIM2_CLKIN + }, + { + .base = STM32_TIM3_BASE, + .clock_register = STM32_RCC_APB1ENR, + .clock_bit = RCC_APB1ENR_TIM3EN, + .clock_freq = STM32_APB1_TIM3_CLKIN + }, + { + .base = STM32_TIM4_BASE, + .clock_register = STM32_RCC_APB1ENR, + .clock_bit = RCC_APB1ENR_TIM4EN, + .clock_freq = STM32_APB1_TIM4_CLKIN + }, + }, + .channels = { + { + .gpio = GPIO_TIM2_CH1OUT, + .timer_index = 0, + .timer_channel = 1, + .default_value = 1000, + }, + { + .gpio = GPIO_TIM2_CH2OUT, + .timer_index = 0, + .timer_channel = 2, + .default_value = 1000, + }, + { + .gpio = GPIO_TIM4_CH3OUT, + .timer_index = 2, + .timer_channel = 3, + .default_value = 1000, + }, + { + .gpio = GPIO_TIM4_CH4OUT, + .timer_index = 2, + .timer_channel = 4, + .default_value = 1000, + }, + { + .gpio = GPIO_TIM3_CH1OUT, + .timer_index = 1, + .timer_channel = 1, + .default_value = 1000, + }, + { + .gpio = GPIO_TIM3_CH2OUT, + .timer_index = 1, + .timer_channel = 2, + .default_value = 1000, + }, + { + .gpio = GPIO_TIM3_CH3OUT, + .timer_index = 1, + .timer_channel = 3, + .default_value = 1000, + }, + { + .gpio = GPIO_TIM3_CH4OUT, + .timer_index = 1, + .timer_channel = 4, + .default_value = 1000, + }, + } + }; +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_archinitialize + * + * Description: + * Perform architecture specific initialization + * + ****************************************************************************/ + +int up_boardinitialize() +{ + /* configure the high-resolution time/callout interface */ +#ifdef CONFIG_HRT_TIMER + hrt_init(CONFIG_HRT_TIMER); +#endif + + /* configure the PWM servo driver */ +#if CONFIG_PWM_SERVO + pwm_servo_init(&servo_config); +#endif + + /* configure the GPIO driver */ + gpio_drv_init(); + + return OK; +} diff --git a/nuttx/configs/px4io/src/up_boot.c b/nuttx/configs/px4io/src/up_boot.c new file mode 100644 index 0000000000..9d6a3b246e --- /dev/null +++ b/nuttx/configs/px4io/src/up_boot.c @@ -0,0 +1,82 @@ +/************************************************************************************ + * configs/stm3210e-eval/src/up_boot.c + * arch/arm/src/board/up_boot.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include + +#include + +#include "up_arch.h" +#include "px4io_internal.h" +#include +#include + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_boardinitialize + * + * Description: + * All STM32 architectures must provide the following entry point. This entry point + * is called early in the intitialization -- after all memory has been configured + * and mapped but before any devices have been initialized. + * + ************************************************************************************/ + +void stm32_boardinitialize(void) +{ + /* Configure on-board LEDs if LED support has been selected. */ + +#ifdef CONFIG_ARCH_LEDS + up_ledinit(); +#endif + +} diff --git a/nuttx/configs/px4io/src/up_hrt.c b/nuttx/configs/px4io/src/up_hrt.c new file mode 100644 index 0000000000..d0c46bd26f --- /dev/null +++ b/nuttx/configs/px4io/src/up_hrt.c @@ -0,0 +1,664 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file High-resolution timer callouts and timekeeping. + * + * This can use any general or advanced STM32 timer. + * + * Note that really, this could use systick too, but that's + * monopolised by NuttX and stealing it would just be awkward. + * + * We don't use the NuttX STM32 driver per se; rather, we + * claim the timer and then drive it directly. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "chip.h" +#include "up_internal.h" +#include "up_arch.h" + +#include "stm32_internal.h" +#include "stm32_gpio.h" +#include "stm32_tim.h" + +#ifdef CONFIG_HRT_TIMER + +/* HRT configuration */ +#if HRT_TIMER == 1 +# define HRT_TIMER_BASE STM32_TIM1_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB2ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM1EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM1CC +# define HRT_TIMER_CLOCK STM32_APB2_TIM1_CLKIN +# if CONFIG_STM32_TIM1 +# error must not set CONFIG_STM32_TIM1=y and HRT_TIMER=1 +# endif +#elif HRT_TIMER == 2 +# define HRT_TIMER_BASE STM32_TIM2_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM2EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM2 +# define HRT_TIMER_CLOCK STM32_APB1_TIM2_CLKIN +# if CONFIG_STM32_TIM2 +# error must not set CONFIG_STM32_TIM2=y and HRT_TIMER=2 +# endif +#elif HRT_TIMER == 3 +# define HRT_TIMER_BASE STM32_TIM3_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM3EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM3 +# define HRT_TIMER_CLOCK STM32_APB1_TIM3_CLKIN +# if CONFIG_STM32_TIM3 +# error must not set CONFIG_STM32_TIM3=y and HRT_TIMER=3 +# endif +#elif HRT_TIMER == 4 +# define HRT_TIMER_BASE STM32_TIM4_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM4EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM4 +# define HRT_TIMER_CLOCK STM32_APB1_TIM4_CLKIN +# if CONFIG_STM32_TIM4 +# error must not set CONFIG_STM32_TIM4=y and HRT_TIMER=4 +# endif +#elif HRT_TIMER == 5 +# define HRT_TIMER_BASE STM32_TIM5_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM5EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM5 +# define HRT_TIMER_CLOCK STM32_APB1_TIM5_CLKIN +# if CONFIG_STM32_TIM5 +# error must not set CONFIG_STM32_TIM5=y and HRT_TIMER=5 +# endif +#elif HRT_TIMER == 8 +# define HRT_TIMER_BASE STM32_TIM8_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB2ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM8EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM8CC +# define HRT_TIMER_CLOCK STM32_APB2_TIM8_CLKIN +# if CONFIG_STM32_TIM8 +# error must not set CONFIG_STM32_TIM8=y and HRT_TIMER=6 +# endif +#elif HRT_TIMER == 9 +# define HRT_TIMER_BASE STM32_TIM9_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM9EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM1BRK +# define HRT_TIMER_CLOCK STM32_APB1_TIM9_CLKIN +# if CONFIG_STM32_TIM9 +# error must not set CONFIG_STM32_TIM9=y and HRT_TIMER=9 +# endif +#elif HRT_TIMER == 10 +# define HRT_TIMER_BASE STM32_TIM10_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM10EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM1UP +# define HRT_TIMER_CLOCK STM32_APB1_TIM10_CLKIN +# if CONFIG_STM32_TIM10 +# error must not set CONFIG_STM32_TIM11=y and HRT_TIMER=10 +# endif +#elif HRT_TIMER == 11 +# define HRT_TIMER_BASE STM32_TIM11_BASE +# define HRT_TIMER_POWER_REG STM32_RCC_APB1ENR +# define HRT_TIMER_POWER_BIT RCC_APB2ENR_TIM11EN +# define HRT_TIMER_VECTOR STM32_IRQ_TIM1TRGCOM +# define HRT_TIMER_CLOCK STM32_APB1_TIM11_CLKIN +# if CONFIG_STM32_TIM11 +# error must not set CONFIG_STM32_TIM11=y and HRT_TIMER=11 +# endif +#else +# error HRT_TIMER must be set in board.h if CONFIG_HRT_TIMER=y +#endif + +/* + * HRT clock must be a multiple of 1MHz greater than 1MHz + */ +#if (HRT_TIMER_CLOCK % 1000000) != 0 +# error HRT_TIMER_CLOCK must be a multiple of 1MHz +#endif +#if HRT_TIMER_CLOCK <= 1000000 +# error HRT_TIMER_CLOCK must be greater than 1MHz +#endif + +/* + * Minimum/maximum deadlines. + * + * These are suitable for use with a 16-bit timer/counter clocked + * at 1MHz. The high-resolution timer need only guarantee that it + * not wrap more than once in the 50ms period for absolute time to + * be consistently maintained. + * + * The minimum deadline must be such that the time taken between + * reading a time and writing a deadline to the timer cannot + * result in missing the deadline. + */ +#define HRT_INTERVAL_MIN 50 +#define HRT_INTERVAL_MAX 50000 + +/* + * Period of the free-running counter, in microseconds. + */ +#define HRT_COUNTER_PERIOD 65536 + +/* + * Scaling factor(s) for the free-running counter; convert an input + * in counts to a time in microseconds. + */ +#define HRT_COUNTER_SCALE(_c) (_c) + +/* + * Timer register accessors + */ +#define REG(_reg) (*(volatile uint32_t *)(HRT_TIMER_BASE + _reg)) + +#define rCR1 REG(STM32_GTIM_CR1_OFFSET) +#define rCR2 REG(STM32_GTIM_CR2_OFFSET) +#define rSMCR REG(STM32_GTIM_SMCR_OFFSET) +#define rDIER REG(STM32_GTIM_DIER_OFFSET) +#define rSR REG(STM32_GTIM_SR_OFFSET) +#define rEGR REG(STM32_GTIM_EGR_OFFSET) +#define rCCMR1 REG(STM32_GTIM_CCMR1_OFFSET) +#define rCCMR2 REG(STM32_GTIM_CCMR2_OFFSET) +#define rCCER REG(STM32_GTIM_CCER_OFFSET) +#define rCNT REG(STM32_GTIM_CNT_OFFSET) +#define rPSC REG(STM32_GTIM_PSC_OFFSET) +#define rARR REG(STM32_GTIM_ARR_OFFSET) +#define rCCR1 REG(STM32_GTIM_CCR1_OFFSET) +#define rCCR2 REG(STM32_GTIM_CCR2_OFFSET) +#define rCCR3 REG(STM32_GTIM_CCR3_OFFSET) +#define rCCR4 REG(STM32_GTIM_CCR4_OFFSET) +#define rDCR REG(STM32_GTIM_DCR_OFFSET) +#define rDMAR REG(STM32_GTIM_DMAR_OFFSET) + +/* + * Specific registers and bits used by HRT sub-functions + */ +#if HRT_TIMER_CHANNEL == 1 +# define rCCR_HRT rCCR1 /* compare register for HRT */ +# define DIER_HRT GTIM_DIER_CC1IE /* interrupt enable for HRT */ +# define SR_INT_HRT GTIM_SR_CC1IF /* interrupt status for HRT */ +#elif HRT_TIMER_CHANNEL == 2 +# define rCCR_HRT rCCR2 /* compare register for HRT */ +# define DIER_HRT GTIM_DIER_CC2IE /* interrupt enable for HRT */ +# define SR_INT_HRT GTIM_SR_CC2IF /* interrupt status for HRT */ +#elif HRT_TIMER_CHANNEL == 3 +# define rCCR_HRT rCCR3 /* compare register for HRT */ +# define DIER_HRT GTIM_DIER_CC3IE /* interrupt enable for HRT */ +# define SR_INT_HRT GTIM_SR_CC3IF /* interrupt status for HRT */ +#elif HRT_TIMER_CHANNEL == 4 +# define rCCR_HRT rCCR4 /* compare register for HRT */ +# define DIER_HRT GTIM_DIER_CC4IE /* interrupt enable for HRT */ +# define SR_INT_HRT GTIM_SR_CC4IF /* interrupt status for HRT */ +#else +# error HRT_TIMER_CHANNEL must be a value between 1 and 4 +#endif + +/* + * Queue of callout entries. + */ +static struct sq_queue_s callout_queue; + +/* + * The time corresponding to a counter value of zero, as of the + * last time that hrt_absolute_time() was called. + */ +static hrt_abstime base_time; + +/* timer-specific functions */ +static void hrt_tim_init(int timer); +static int hrt_tim_isr(int irq, void *context); + +/* callout list manipulation */ +static void hrt_call_enter(struct hrt_call *entry); +static void hrt_call_reschedule(void); +static void hrt_call_invoke(void); + +/* + * Specific registers and bits used by PPM sub-functions + */ +#ifdef CONFIG_HRT_PPM +# include + +/* + * If the timer hardware doesn't support GTIM_CCER_CCxNP, then we will work around it. + */ +# ifndef GTIM_CCER_CC1NP +# define GTIM_CCER_CC1NP 0 +# define GTIM_CCER_CC2NP 0 +# define GTIM_CCER_CC3NP 0 +# define GTIM_CCER_CC4NP 0 +# define PPM_EDGE_FLIP +# endif + +# if HRT_PPM_CHANNEL == 1 +# define rCCR_PPM rCCR1 /* capture register for PPM */ +# define DIER_PPM GTIM_DIER_CC1IE /* capture interrupt (non-DMA mode) */ +# define SR_INT_PPM GTIM_SR_CC1IF /* capture interrupt (non-DMA mode) */ +# define SR_OVF_PPM GTIM_SR_CC1OF /* capture overflow (non-DMA mode) */ +# define CCMR1_PPM 1 /* on TI1 */ +# define CCMR2_PPM 0 +# define CCER_PPM (GTIM_CCER_CC1E | GTIM_CCER_CC1P | GTIM_CCER_CC1NP) /* CC1, both edges */ +# define CCER_PPM_FLIP GTIM_CCER_CC1P +# elif HRT_PPM_CHANNEL == 2 +# define rCCR_PPM rCCR2 /* capture register for PPM */ +# define DIER_PPM GTIM_DIER_CC2IE /* capture interrupt (non-DMA mode) */ +# define SR_INT_PPM GTIM_SR_CC2IF /* capture interrupt (non-DMA mode) */ +# define SR_OVF_PPM GTIM_SR_CC2OF /* capture overflow (non-DMA mode) */ +# define CCMR1_PPM 2 /* on TI2 */ +# define CCMR2_PPM 0 +# define CCER_PPM (GTIM_CCER_CC2E | GTIM_CCER_CC2P | GTIM_CCER_CC2NP) /* CC2, both edges */ +# define CCER_PPM_FLIP GTIM_CCER_CC2P +# elif HRT_PPM_CHANNEL == 3 +# define rCCR_PPM rCCR3 /* capture register for PPM */ +# define DIER_PPM GTIM_DIER_CC3IE /* capture interrupt (non-DMA mode) */ +# define SR_INT_PPM GTIM_SR_CC3IF /* capture interrupt (non-DMA mode) */ +# define SR_OVF_PPM GTIM_SR_CC3OF /* capture overflow (non-DMA mode) */ +# define CCMR1_PPM 0 +# define CCMR2_PPM 1 /* on TI3 */ +# define CCER_PPM (GTIM_CCER_CC3E | GTIM_CCER_CC3P | GTIM_CCER_CC3NP) /* CC3, both edges */ +# define CCER_PPM_FLIP GTIM_CCER_CC3P +# elif HRT_PPM_CHANNEL == 4 +# define rCCR_PPM rCCR4 /* capture register for PPM */ +# define DIER_PPM GTIM_DIER_CC4IE /* capture interrupt (non-DMA mode) */ +# define SR_INT_PPM GTIM_SR_CC4IF /* capture interrupt (non-DMA mode) */ +# define SR_OVF_PPM GTIM_SR_CC4OF /* capture overflow (non-DMA mode) */ +# define CCMR1_PPM 0 +# define CCMR2_PPM 2 /* on TI4 */ +# define CCER_PPM (GTIM_CCER_CC4E | GTIM_CCER_CC4P | GTIM_CCER_CC4NP) /* CC4, both edges */ +# define CCER_PPM_FLIP GTIM_CCER_CC4P +# else +# error HRT_PPM_CHANNEL must be a value between 1 and 4 if CONFIG_HRT_PPM is set +# endif +#else +/* disable the PPM configuration */ +# define rCCR_PPM 0 +# define DIER_PPM 0 +# define SR_INT_PPM 0 +# define SR_OVF_PPM 0 +# define CCMR1_PPM 0 +# define CCMR2_PPM 0 +# define CCER_PPM 0 +#endif /* CONFIG_HRT_PPM */ + +/* + * Initialise the timer we are going to use. + * + * We expect that we'll own one of the reduced-function STM32 general + * timers, and that we can use channel 1 in compare mode. + */ +static void +hrt_tim_init(int timer) +{ + /* clock/power on our timer */ + modifyreg32(HRT_TIMER_POWER_REG, 0, HRT_TIMER_POWER_BIT); + + /* claim our interrupt vector */ + irq_attach(HRT_TIMER_VECTOR, hrt_tim_isr); + + /* disable and configure the timer */ + rCR1 = 0; + rCR2 = 0; + rSMCR = 0; + rDIER = DIER_HRT | DIER_PPM; + rCCER = 0; /* unlock CCMR* registers */ + rCCMR1 = CCMR1_PPM; + rCCMR2 = CCMR2_PPM; + rCCER = CCER_PPM; + rDCR = 0; + + /* configure the timer to free-run at 1MHz */ + rPSC = (HRT_TIMER_CLOCK / 1000000) - 1; /* this really only works for whole-MHz clocks */ + + /* run the full span of the counter */ + rARR = 0xffff; + + /* set an initial capture a little ways off */ + rCCR_HRT = 1000; + + /* generate an update event; reloads the counter, all registers */ + rEGR = GTIM_EGR_UG; + + /* enable the timer */ + rCR1 = GTIM_CR1_CEN; + + /* enable interrupts */ + up_enable_irq(HRT_TIMER_VECTOR); +} + +/* + * Handle the compare interupt by calling the callout dispatcher + * and then re-scheduling the next deadline. + */ +static int +hrt_tim_isr(int irq, void *context) +{ + uint32_t status; + + /* copy interrupt status */ + status = rSR; + + /* ack the interrupts we just read */ + rSR = ~status; + +#ifdef CONFIG_HRT_PPM + /* was this a PPM edge? */ + if (status & (SR_INT_PPM | SR_OVF_PPM)) { + + /* if required, flip edge sensitivity */ +# ifdef PPM_EDGE_FLIP + rCCER ^= CCER_PPM_FLIP; +# endif + + /* feed the edge to the PPM decoder */ + ppm_input_decode(status & SR_OVF_PPM, rCCR_PPM); + } +#endif + + /* was this a timer tick? */ + if (status & SR_INT_HRT) { + /* run any callouts that have met their deadline */ + hrt_call_invoke(); + + /* and schedule the next interrupt */ + hrt_call_reschedule(); + } + + return OK; +} + +/* + * Fetch a never-wrapping absolute time value in microseconds from + * some arbitrary epoch shortly after system start. + */ +hrt_abstime +hrt_absolute_time(void) +{ + static uint32_t last_count; + uint32_t count; + uint32_t flags = irqsave(); + + count = rCNT; + + //lldbg("count %u last_count %u\n", count, last_count); + + /* This simple test is made possible by the guarantee that + * we are always called at least once per counter period. + */ + if (count < last_count) + base_time += HRT_COUNTER_PERIOD; + + last_count = count; + + irqrestore(flags); + + return HRT_COUNTER_SCALE(base_time + count); +} + +/* + * Convert a timespec to absolute time + */ +hrt_abstime +ts_to_abstime(struct timespec *ts) +{ + hrt_abstime result; + + result = (hrt_abstime)(ts->tv_sec) * 1000000; + result += ts->tv_nsec / 1000; + + return result; +} + +/* + * Convert absolute time to a timespec. + */ +void +abstime_to_ts(struct timespec *ts, hrt_abstime abstime) +{ + ts->tv_sec = abstime / 1000000; + abstime -= ts->tv_sec * 1000000; + ts->tv_nsec = abstime * 1000; +} + +/* + * Initalise the high-resolution timing module. + */ +void +hrt_init(int timer) +{ + sq_init(&callout_queue); + hrt_tim_init(timer); +} + +/* + * Call callout(arg) after interval has elapsed. + */ +void +hrt_call_after(struct hrt_call *entry, hrt_abstime delay, hrt_callout callout, void *arg) +{ + entry->deadline = hrt_absolute_time() + delay; + entry->period = 0; + entry->callout = callout; + entry->arg = arg; + + hrt_call_enter(entry); +} + +/* + * Call callout(arg) at calltime. + */ +void +hrt_call_at(struct hrt_call *entry, hrt_abstime calltime, hrt_callout callout, void *arg) +{ + entry->deadline = calltime; + entry->period = 0; + entry->callout = callout; + entry->arg = arg; + + hrt_call_enter(entry); +} + +/* + * Call callout(arg) every period. + */ +void +hrt_call_every(struct hrt_call *entry, hrt_abstime delay, hrt_abstime interval, hrt_callout callout, void *arg) +{ + entry->deadline = hrt_absolute_time() + delay; + entry->period = interval; + entry->callout = callout; + entry->arg = arg; + + hrt_call_enter(entry); +} + +/* + * If this returns true, the call has been invoked and removed from the callout list. + * + * Always returns false for repeating callouts. + */ +bool +hrt_called(struct hrt_call *entry) +{ + bool result; + + irqstate_t flags = irqsave(); + result = (entry->deadline == 0); + irqrestore(flags); + + return result; +} + +/* + * Remove the entry from the callout list. + */ +void +hrt_cancel(struct hrt_call *entry) +{ + irqstate_t flags = irqsave(); + + sq_rem(&entry->link, &callout_queue); + entry->deadline = 0; + + /* if this is a periodic call being removed by the callout, prevent it from + * being re-entered when the callout returns. + */ + entry->period = 0; + + irqrestore(flags); +} + +static void +hrt_call_enter(struct hrt_call *entry) +{ + irqstate_t flags = irqsave(); + struct hrt_call *call, *next; + + call = (struct hrt_call *)sq_peek(&callout_queue); + + if ((call == NULL) || (entry->deadline < call->deadline)) { + sq_addfirst(&entry->link, &callout_queue); + //lldbg("call enter at head, reschedule\n"); + /* we changed the next deadline, reschedule the timer event */ + hrt_call_reschedule(); + } else { + do { + next = (struct hrt_call *)sq_next(&call->link); + if ((next == NULL) || (entry->deadline < next->deadline)) { + //lldbg("call enter after head\n"); + sq_addafter(&call->link, &entry->link, &callout_queue); + break; + } + } while ((call = next) != NULL); + } + + //lldbg("scheduled\n"); + irqrestore(flags); +} + +static void +hrt_call_invoke(void) +{ + struct hrt_call *call; + hrt_abstime deadline; + + while (true) { + /* get the current time */ + hrt_abstime now = hrt_absolute_time(); + + call = (struct hrt_call *)sq_peek(&callout_queue); + if (call == NULL) + break; + if (call->deadline > now) + break; + + sq_rem(&call->link, &callout_queue); + //lldbg("call pop\n"); + + /* save the intended deadline for periodic calls */ + deadline = call->deadline; + + /* zero the deadline, as the call has occurred */ + call->deadline = 0; + + /* invoke the callout (if there is one) */ + if (call->callout) { + //lldbg("call %p: %p(%p)\n", call, call->callout, call->arg); + call->callout(call->arg); + } + + /* if the callout has a non-zero period, it has to be re-entered */ + if (call->period != 0) { + call->deadline = deadline + call->period; + hrt_call_enter(call); + } + } +} + +/* + * Reschedule the next timer interrupt. + * + * This routine must be called with interrupts disabled. + */ +static void +hrt_call_reschedule() +{ + hrt_abstime now = hrt_absolute_time(); + struct hrt_call *next = (struct hrt_call *)sq_peek(&callout_queue); + hrt_abstime deadline = now + HRT_INTERVAL_MAX; + + /* + * Determine what the next deadline will be. + * + * Note that we ensure that this will be within the counter + * period, so that when we truncate all but the low 16 bits + * the next time the compare matches it will be the deadline + * we want. + * + * It is important for accurate timekeeping that the compare + * interrupt fires sufficiently often that the base_time update in + * hrt_absolute_time runs at least once per timer period. + */ + if (next != NULL) { + //lldbg("entry in queue\n"); + if (next->deadline <= (now + HRT_INTERVAL_MIN)) { + //lldbg("pre-expired\n"); + /* set a minimal deadline so that we call ASAP */ + deadline = now + HRT_INTERVAL_MIN; + } else if (next->deadline < deadline) { + //lldbg("due soon\n"); + deadline = next->deadline; + } + } + //lldbg("schedule for %u at %u\n", (unsigned)(deadline & 0xffffffff), (unsigned)(now & 0xffffffff)); + + /* set the new compare value */ + rCCR_HRT = deadline & 0xffff; +} + +#endif /* CONFIG_HRT_TIMER */ diff --git a/nuttx/configs/px4io/src/up_nsh.c b/nuttx/configs/px4io/src/up_nsh.c new file mode 100644 index 0000000000..0358387806 --- /dev/null +++ b/nuttx/configs/px4io/src/up_nsh.c @@ -0,0 +1,63 @@ +/**************************************************************************** + * config/stm3210e_eval/src/up_nsh.c + * arch/arm/src/board/up_nsh.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "stm32_internal.h" + +#include + +/**************************************************************************** + * Name: nsh_archinitialize + * + * Description: + * Perform architecture specific initialization + * + ****************************************************************************/ + +int nsh_archinitialize(void) +{ + return up_boardinitialize(); +} diff --git a/nuttx/drivers/Kconfig b/nuttx/drivers/Kconfig new file mode 100644 index 0000000000..6d4c5fc6ae --- /dev/null +++ b/nuttx/drivers/Kconfig @@ -0,0 +1,329 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +comment "Device Driver Configuration" + +config DEV_NULL + bool "Enable /dev/null" + default y + +config DEV_ZERO + bool "Enable /dev/zero" + default y + +config LOOP + bool "Enable loop device" + default n + ---help--- + Supports the standard loop device that can be used to export a + file (or character device) as a block device. See losetup() and + loteardown() in include/nuttx/fs/fs.h. + +config RAMDISK + bool "RAM disk support" + default n + ---help--- + Can be used to set up a block of memory or (read-only) FLASH as + a block driver that can be mounted as a files system. See + include/nuttx/ramdisk.h. + +config CAN + bool "CAN support" + default n + ---help--- + This selection enables building of the "upper-half" CAN driver. + See include/nuttx/can.h for further CAN driver information. + +if CAN +config CAN_EXTID + bool "CAN extended IDs" + default n + ---help--- + Enables support for the 29-bit extended ID. Default Standard 11-bit IDs. + +config CAN_FIFOSIZE + int "CAN driver I/O buffer size" + default 8 + ---help--- + The size of the circular buffer of CAN messages. Default: 8 + +config CAN_NPENDINGRTR + int "Number of pending RTRs" + default 4 + ---help--- + The size of the list of pending RTR requests. Default: 4 + +config CAN_LOOPBACK + bool "CAN extended IDs" + default n + ---help--- + A CAN driver may or may not support a loopback mode for testing. If the + driver does support loopback mode, the setting will enable it. (If the + driver does not, this setting will have no effect). + +endif + +config PWM + bool "PWM support" + default n + ---help--- + This selection enables building of the "upper-half" PWM driver. + See include/nuttx/pwm.h for further PWM driver information. + +if PWM +config PWM_PULSECOUNT + bool "PWM pulse count support" + default n + ---help--- + Some hardware will support generation of a fixed number of pulses. This + might be used, for example to support a stepper motor. If the hardware + will support a fixed pulse count, then this configuration should be set to + enable the capability. + +endif + +config I2C + bool "I2C support" + default y + ---help--- + This selection enables building of the "upper-half" I2C driver. + See include/nuttx/i2c.h for further I2C driver information. + +if I2C +endif + +config SPI + bool "SPI support" + default y + ---help--- + This selection enables building of the "upper-half" SPI driver. + See include/nuttx/spi.h for further SPI driver information. + +if SPI +config SPI_OWNBUS + bool "SPI single device" + default y + ---help--- + Set if there is only one active device on the SPI bus. No locking or SPI + configuration will be performed. It is not necessary for clients to lock, + re-configure, etc.. + +config SPI_EXCHANGE + bool "SPI exchange" + default y + ---help--- + Driver supports a single exchange method (vs a recvblock() and sndblock ()methods). + +config SPI_CMDDATA + bool "SPI CMD/DATA" + default y + ---help--- + Devices on the SPI bus require out-of-band support to distinguish command + transfers from data transfers. Such devices will often support either 9-bit + SPI (yech) or 8-bit SPI and a GPIO output that selects between command and data. + +endif + +config WATCHDOG + bool "Watchdog timer support" + default y + ---help--- + This selection enables building of the "upper-half" watchdog timer driver. + See include/nuttx/watchdog.h for further watchdog timer driver information. + +if WATCHDOG +endif + +menuconfig ANALOG + bool "Analog Device(ADC/DAC) support" + default n + ---help--- + This directory holds implementations of analog device drivers. + This includes drivers for Analog to Digital Conversion (ADC) as + well as drivers for Digital to Analog Conversion (DAC). + See include/nuttx/analog/*.h for registration information. + +if ANALOG +source drivers/analog/Kconfig +endif + +config BCH + bool "BCH support" + default n + ---help--- + Contains logic that may be used to convert a block driver into + a character driver. This is the complementary conversion as that + performed by loop.c. See include/nuttx/fs/fs.h for registration + information. + +if BCH +source drivers/bch/Kconfig +endif + +menuconfig INPUT + bool "Input device support" + default y + ---help--- + This directory holds implementations of input device drivers. + This includes such things as touchscreen and keypad drivers. + See include/nuttx/input/*.h for registration information. + +if INPUT +source drivers/input/Kconfig +endif + +menuconfig LCD + bool "LCD support" + default n + select NX_LCDDRIVER + ---help--- + Drivers for parallel and serial LCD and OLED type devices. These + drivers support interfaces as defined in include/nuttx/lcd/lcd.h + +if LCD +source drivers/lcd/Kconfig +endif + +menuconfig MMCSD + bool "MMC/SD support" + default n + ---help--- + Support for MMC/SD block drivers. MMC/SD block drivers based on + SPI and SDIO/MCI interfaces are supported. See include/nuttx/mmcsd.h + and include/nuttx/sdio.h for further information. + +if MMCSD +source drivers/mmcsd/Kconfig +endif + +menuconfig MTD + bool "Memory Technology Device (MTD) support" + default n + ---help--- + Memory Technology Device (MTD) drivers. Some simple drivers for + memory technologies like FLASH, EEPROM, NVRAM, etc. See + include/nuttx/mtd.h + + (Note: This is a simple memory interface and should not be + confused with the "real" MTD developed at infradead.org. This + logic is unrelated; I just used the name MTD because I am not + aware of any other common way to refer to this class of devices). + +if MTD +source drivers/mtd/Kconfig +endif + +menuconfig NETDEVICES + bool "Network Device support" + default n + ---help--- + Network interface drivers. See also include/nuttx/net/net.h + +if NETDEVICES +source drivers/net/Kconfig +endif + +menuconfig PIPES + bool "FIFO and named pipe drivers" + default n + ---help--- + FIFO and named pipe drivers. Standard interfaces are declared + in include/unistd.h + +if PIPES +source drivers/pipes/Kconfig +endif + +config PM + bool "Power management (PM) driver interfaces" + default n + ---help--- + Power management (PM) driver interfaces. These interfaces are used + to manage power usage of a platform by monitoring driver activity + and by placing drivers into reduce power usage modes when the + drivers are not active. + +menuconfig POWER + bool "Power management device support" + default n + ---help--- + Enable building of power-related devices (battery monitors, chargers, etc). + +if POWER +source drivers/power/Kconfig +endif + +menuconfig SENSORS + bool "Sensors support" + default n + ---help--- + Drivers for various sensors + +if SENSORS +source drivers/sensors/Kconfig +endif + +menuconfig SERCOMM_CONSOLE + bool "Osmocom-bb serial console" + default n + ---help--- + Sercomm is the transport used by osmocom-bb that runs on top of serial. + See http://bb.osmocom.org/trac/wiki/nuttx-bb/run for detailed the usage + of nuttx with sercomm. + + drivers/sercomm is only built if SERCOMM_CONSOLE in the NuttX + configuration file. If you attempt to build this driver without + osmocom-bb, you will get compilation errors because of header files + that are needed from the osmocom-bb. + +if SERCOMM +source drivers/sercomm/Kconfig +endif + +menuconfig SERIAL + bool "Serial support" + default y + ---help--- + Front-end character drivers for chip-specific UARTs. This provide + some TTY-like functionality and are commonly used (but not required for) + the NuttX system console. See also include/nuttx/serial/serial.h + +if SERIAL +source drivers/serial/Kconfig +endif + +menuconfig USBDEV + bool "USB device support" + default n + ---help--- + USB device drivers. See also include/nuttx/usb/usbdev.h + +if USBDEV +source drivers/usbdev/Kconfig +endif + +menuconfig USBHOST + bool "USB Host support" + default n + ---help--- + USB host drivers. See also include/nuttx/usb/usbhost.h + +if USBHOST +source drivers/usbhost/Kconfig +endif + +menuconfig WIRELESS + bool "Wireless support" + default n + ---help--- + Drivers for various wireless devices. + +if WIRELESS +source drivers/wireless/Kconfig +endif + +source drivers/syslog/Kconfig + + diff --git a/nuttx/drivers/Makefile b/nuttx/drivers/Makefile new file mode 100644 index 0000000000..26a2ea9923 --- /dev/null +++ b/nuttx/drivers/Makefile @@ -0,0 +1,122 @@ +############################################################################ +# drivers/Makefile +# +# Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ifeq ($(WINTOOL),y) +INCDIROPT = -w +endif + +DEPPATH = --dep-path . +ASRCS = +CSRCS = +VPATH = . + +# Include support for various drivers. Each Make.defs file will add its +# files to the source file list, add its DEPPATH info, and will add +# the appropriate paths to the VPATH variable + +include analog/Make.defs +include bch/Make.defs +include input/Make.defs +include lcd/Make.defs +include mmcsd/Make.defs +include mtd/Make.defs +include net/Make.defs +include pipes/Make.defs +include power/Make.defs +include sensors/Make.defs +include sercomm/Make.defs +include serial/Make.defs +include syslog/Make.defs +include usbdev/Make.defs +include usbhost/Make.defs +include wireless/Make.defs + +ifneq ($(CONFIG_NFILE_DESCRIPTORS),0) + CSRCS += dev_null.c dev_zero.c loop.c + +ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y) + CSRCS += ramdisk.c rwbuffer.c +endif + +ifeq ($(CONFIG_CAN),y) + CSRCS += can.c +endif + +ifeq ($(CONFIG_PWM),y) + CSRCS += pwm.c +endif + +ifeq ($(CONFIG_WATCHDOG),y) + CSRCS += watchdog.c +endif +endif + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = libdrivers$(LIBEXT) + +all: $(BIN) + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +.depend: Makefile $(SRCS) + @$(MKDEP) $(DEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f $(BIN) *~ .*.swp + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/drivers/README.txt b/nuttx/drivers/README.txt new file mode 100644 index 0000000000..e27e8c5831 --- /dev/null +++ b/nuttx/drivers/README.txt @@ -0,0 +1,145 @@ +README +^^^^^^ + +This directory contains various device drivers -- both block and +character drivers as well as other more specialized drivers. + +Contents: + - Files in this directory + - Subdirectories of this directory + - Skeleton files + +Files in this directory +^^^^^^^^^^^^^^^^^^^^^^^ + +can.c + This is a CAN driver. See include/nuttx/can.h for usage information. + +dev_null.c and dev_zero.c + These files provide the standard /dev/null and /dev/zero devices. + See include/nuttx/fs/fs.h for functions that should be called if you + want to register these devices (devnull_register() and + devzero_register()). + +loop.c + Supports the standard loop device that can be used to export a + file (or character device) as a block device. See losetup() and + loteardown() in include/nuttx/fs/fs.h. + +pwm.c + Provides the "upper half" of a pulse width modulation (PWM) driver. + The "lower half" of the PWM driver is provided by device-specific + logic. See include/nuttx/pwm.h for usage information. + +ramdisk.c + Can be used to set up a block of memory or (read-only) FLASH as + a block driver that can be mounted as a files system. See + include/nuttx/ramdisk.h. + +ramlog.c + This is a driver that was intended to support debugging output, + aka syslogging, when the normal serial output is not available. + For example, if you are using a telnet or USB serial console, + the debug output will get lost. + + This driver is similar to a pipe in that it saves the debugging + output in a FIFO in RAM. It differs from a pipe in numerous + details as needed to support logging. + + This driver is built when CONFIG_RAMLOG is defined in the Nuttx + configuration. + +rwbuffer.c + A facility that can be use by any block driver in-order to add + writing buffering and read-ahead buffering. + +Subdirectories of this directory: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +analog/ + This directory holds implementations of analog device drivers. + This includes drivers for Analog to Digital Conversion (ADC) as + well as drivers for Digital to Analog Conversion (DAC). + See include/nuttx/analog/*.h for registration information. + +bch/ + Contains logic that may be used to convert a block driver into + a character driver. This is the complementary conversion as that + performed by loop.c. See include/nuttx/fs/fs.h for registration + information. + +input/ + This directory holds implementations of input device drivers. + This includes such things as touchscreen and keypad drivers. + See include/nuttx/input/*.h for registration information. + +lcd/ + Drivers for parallel and serial LCD and OLED type devices. These + drivers support interfaces as defined in include/nuttx/lcd/lcd.h + +mmcsd/ + Support for MMC/SD block drivers. MMC/SD block drivers based on + SPI and SDIO/MCI interfaces are supported. See include/nuttx/mmcsd.h + and include/nuttx/sdio.h for further information. + +mtd/ + Memory Technology Device (MTD) drivers. Some simple drivers for + memory technologies like FLASH, EEPROM, NVRAM, etc. See + include/nuttx/mtd.h + + (Note: This is a simple memory interface and should not be + confused with the "real" MTD developed at infradead.org. This + logic is unrelated; I just used the name MTD because I am not + aware of any other common way to refer to this class of devices). + +net/ + Network interface drivers. See also include/nuttx/net/net.h + +pipes/ + FIFO and named pipe drivers. Standard interfaces are declared + in include/unistd.h + +power/ + Power management (PM) driver interfaces. These interfaces are used + to manage power usage of a platform by monitoring driver activity + and by placing drivers into reduce power usage modes when the + drivers are not active. + +sensors/ + Drivers for various sensors + +sercomm/ + Sercomm is the transport used by osmocom-bb that runs on top of serial. + See http://bb.osmocom.org/trac/wiki/nuttx-bb/run for detailed the usage + of nuttx with sercomm. + + drivers/sercomm is only built if CONFIG_SERCOMM_CONSOLE in the NuttX + configuration file. If you attempt to build this driver without + osmocom-bb, you will get compilation errors because of header files + that are needed from the osmocom-bb. + +serial/ + Front-end character drivers for chip-specific UARTs. This provide + some TTY-like functionality and are commonly used (but not required for) + the NuttX system console. See also include/nuttx/serial/serial.h + +usbdev/ + USB device drivers. See also include/nuttx/usb/usbdev.h + +usbhost/ + USB host drivers. See also include/nuttx/usb/usbhost.h + +wireless/ + Drivers for various wireless devices. + +Skeleton Files +^^^^^^^^^^^^^^ + +Skeleton files a "empty" frameworks for NuttX drivers. They are provided to +give you a good starting point if you want to create a new NuttX driver. +The following skeleton files are available: + + drivers/lcd/skeleton.c -- Skeleton LCD driver + drivers/mtd/skeleton.c -- Skeleton memory technology device drivers + drivers/net/skeleton.c -- Skeleton network/Ethernet drivers + drivers/usbhost/usbhost_skeleton.c -- Skeleton USB host class driver diff --git a/nuttx/drivers/analog/Kconfig b/nuttx/drivers/analog/Kconfig new file mode 100644 index 0000000000..ebed79c788 --- /dev/null +++ b/nuttx/drivers/analog/Kconfig @@ -0,0 +1,77 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config ADC + bool "Analog-to-Digital Conversion" + default n + ---help--- + Select to enable support for analog input device support. This includes + not only Analog-to-Digital Converters (ADC) but also amplifiers and + analog multiplexers. + +config ADC_ADS125X + bool "TI ADS1255/ADS1256 support" + default n + depends on ADC + select SPI + +config ADS1255_FREQUENCY + int "ADS1255/ADS1256 SPI frequency" + default 1000000 + depends on ADC_ADS125X + +config ADC_PGA11X + bool "TI PGA112/3/6/7 support" + default n + depends on ADC + select SPI + ---help--- + Enables support for the PGA112, PGA113, PGA116, PGA117 Zerø-Drift + PROGRAMMABLE GAIN AMPLIFIER with MUX + +config PGA11X_SPIFREQUENCY + int "TI PGA112/3/6/7 SPI frequency" + default 1000000 + depends on ADC_PGA11X + ---help--- + PGA11x SPI frequency. + +config PGA11X_SPIMODE + int "TI PGA112/3/6/7 SPI mode" + default 0 + depends on ADC_PGA11X + ---help--- + PGA11x SPI mode. The specification says that the device operates in Mode 0 or + Mode 3. But sometimes you need to tinker with this to get things to work + correctly. Default: Mode 0 + +config PGA11X_DAISYCHAIN + bool "TI PGA112/3/6/7 daisy chain mode" + default n + depends on ADC_PGA11X + ---help--- + Enable support to use two PGA116/7's in Daisy Chain configuration. + +config PGA11X_MULTIPLE + bool "Multiple TI PGA112/3/6/7 support" + default n + depends on ADC_PGA11X && !PGA11X_DAISYCHAIN + ---help--- + Can be defined to support multiple PGA11X devices on board with separate + chip selects (not daisy chained). Each device will require a customized + SPI interface to distinguish them when SPI_SELECT is called with + devid=SPIDEV_MUX. + +config DAC + bool "Digital-to-Analog Conversion" + default n + ---help--- + Select to enable support for Digital-to-Analog Converters (DACs). + +config DAC_AD5410 + bool "AD5410 support" + default n + depends on DAC + select SPI diff --git a/nuttx/drivers/analog/Make.defs b/nuttx/drivers/analog/Make.defs new file mode 100644 index 0000000000..10b0db4785 --- /dev/null +++ b/nuttx/drivers/analog/Make.defs @@ -0,0 +1,87 @@ +############################################################################ +# drivers/analog/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Don't build anything if there is no support for analog devices + +# Check for DAC devices + +ifeq ($(CONFIG_DAC),y) + +# Include the common DAC character driver + +CSRCS += dac.c + +# Include DAC device drivers + +ifeq ($(CONFIG_DAC_AD5410),y) + CSRCS += ad5410.c +endif +endif + +# Check for ADC devices + +ifeq ($(CONFIG_ADC),y) + +# Include the common ADC character driver + +CSRCS += adc.c + +# Amplifiers/multiplexers + +ifeq ($(CONFIG_ADC_PGA11X),y) + CSRCS += pga11x.c +endif + +# Include ADC device drivers + +ifeq ($(CONFIG_ADC_ADS125X),y) + CSRCS += ads1255.c +endif +endif + +# Add analog driver build support (the nested if-then-else implements an OR) + +ifeq ($(CONFIG_DAC),y) + DEPPATH += --dep-path analog + VPATH += :analog + CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/analog} +else +ifeq ($(CONFIG_ADC),y) + DEPPATH += --dep-path analog + VPATH += :analog + CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/analog} +endif +endif + diff --git a/nuttx/drivers/analog/ad5410.c b/nuttx/drivers/analog/ad5410.c new file mode 100644 index 0000000000..3e925a3a9c --- /dev/null +++ b/nuttx/drivers/analog/ad5410.c @@ -0,0 +1,205 @@ +/************************************************************************************ + * arch/drivers/analog/ad5410.c + * + * Copyright (C) 2011 Li Zhuoyi. All rights reserved. + * Author: Li Zhuoyi + * History: 0.1 2011-08-05 initial version + * + * This file is a part of NuttX: + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(CONFIG_DAC_AD5410) + +#define AD5410_REG_NOP 0x00 +#define AD5410_REG_WR 0x01 +#define AD5410_REG_RD 0x02 +#define AD5410_REG_CMD 0x55 +#define AD5410_REG_RST 0x56 + +#define AD5410_CMD_REXT (1<<13) +#define AD5410_CMD_OUTEN (1<<12) +#define AD5410_CMD_SRCLK(x) (x<<8) +#define AD5410_CMD_SRSTEP(x) (x<<5) +#define AD5410_CMD_SREN (1<<4) +#define AD5410_CMD_DCEN (1<<3) +#define AD5410_CMD_420MA 0x05 +#define AD5410_CMD_020MA 0x06 +#define AD5410_CMD_024MA 0x07 + +/**************************************************************************** + * ad_private Types + ****************************************************************************/ +struct up_dev_s +{ + int devno; + FAR struct spi_dev_s *spi; /* Cached SPI device reference */ +}; + +/**************************************************************************** + * ad_private Function Prototypes + ****************************************************************************/ + +/* DAC methods */ + +static void dac_reset(FAR struct dac_dev_s *dev); +static int dac_setup(FAR struct dac_dev_s *dev); +static void dac_shutdown(FAR struct dac_dev_s *dev); +static void dac_txint(FAR struct dac_dev_s *dev, bool enable); +static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg); +static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg); +static int dac_interrupt(int irq, void *context); + +/**************************************************************************** + * ad_private Data + ****************************************************************************/ + +static const struct dac_ops_s g_dacops = +{ + .ao_reset =dac_reset, + .ao_setup = dac_setup, + .ao_shutdown = dac_shutdown, + .ao_txint = dac_txint, + .ao_send = dac_send, + .ao_ioctl = dac_ioctl, +}; + +static struct up_dev_s g_dacpriv; +static struct dac_dev_s g_dacdev = +{ + .ad_ops = &g_dacops, + .ad_priv= &g_dacpriv, +}; + +/**************************************************************************** + * ad_private Functions + ****************************************************************************/ + +/* Reset the DAC device. Called early to initialize the hardware. This +* is called, before ao_setup() and on error conditions. +*/ +static void dac_reset(FAR struct dac_dev_s *dev) +{ + +} + +/* Configure the DAC. This method is called the first time that the DAC +* device is opened. This will occur when the port is first opened. +* This setup includes configuring and attaching DAC interrupts. Interrupts +* are all disabled upon return. +*/ +static int dac_setup(FAR struct dac_dev_s *dev) +{ + FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv; + FAR struct spi_dev_s *spi = priv->spi; + SPI_SELECT(spi, priv->devno, true); + SPI_SEND(spi,AD5410_REG_CMD); + SPI_SEND(spi,(AD5410_CMD_OUTEN|AD5410_CMD_420MA)>>8); + SPI_SEND(spi,AD5410_CMD_OUTEN|AD5410_CMD_420MA); + SPI_SELECT(spi, priv->devno, false); + return OK; +} + +/* Disable the DAC. This method is called when the DAC device is closed. +* This method reverses the operation the setup method. +*/ +static void dac_shutdown(FAR struct dac_dev_s *dev) +{ +} + +/* Call to enable or disable TX interrupts */ +static void dac_txint(FAR struct dac_dev_s *dev, bool enable) +{ +} + +static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg) +{ + FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv; + FAR struct spi_dev_s *spi = priv->spi; + SPI_SELECT(spi, priv->devno, true); + SPI_SEND(spi,AD5410_REG_WR); + SPI_SEND(spi,(uint8_t)(msg->am_data>>24)); + SPI_SEND(spi,(uint8_t)(msg->am_data>>16)); + SPI_SELECT(spi, priv->devno, false); + dac_txdone(&g_dacdev); + return 0; +} + +/* All ioctl calls will be routed through this method */ +static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg) +{ + dbg("Fix me:Not Implemented\n"); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_ad5410cinitialize + * + * Description: + * Initialize the selected DAC port + * + * Input Parameter: + * Port number (for hardware that has mutiple DAC interfaces) + * + * Returned Value: + * Valid ad5410 device structure reference on succcess; a NULL on failure + * + ****************************************************************************/ + +FAR struct dac_dev_s *up_ad5410initialize(FAR struct spi_dev_s *spi, unsigned int devno) +{ + FAR struct up_dev_s *priv = (FAR struct up_dev_s *)g_dacdev.ad_priv; + priv->spi=spi; + priv->devno=devno; + return &g_dacdev; +} +#endif + diff --git a/nuttx/drivers/analog/adc.c b/nuttx/drivers/analog/adc.c new file mode 100644 index 0000000000..84070f162a --- /dev/null +++ b/nuttx/drivers/analog/adc.c @@ -0,0 +1,423 @@ +/**************************************************************************** + * drivers/analog/adc.c + * + * Copyright (C) 2011 Li Zhuoyi. All rights reserved. + * Author: Li Zhuoyi + * History: 0.1 2011-08-04 initial version + * + * Derived from drivers/can.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int adc_open(FAR struct file *filep); +static int adc_close(FAR struct file *filep); +static ssize_t adc_read(FAR struct file *, FAR char *, size_t); +static ssize_t adc_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); +static int adc_ioctl(FAR struct file *filep,int cmd,unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations adc_fops = +{ + adc_open, /* open */ + adc_close, /* close */ + adc_read, /* read */ + adc_write, /* write */ + 0, /* seek */ + adc_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , 0 /* poll */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/************************************************************************************ + * Name: adc_open + * + * Description: + * This function is called whenever the ADC device is opened. + * + ************************************************************************************/ + +static int adc_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct adc_dev_s *dev = inode->i_private; + uint8_t tmp; + int ret = OK; + + /* If the port is the middle of closing, wait until the close is finished */ + + if (sem_wait(&dev->ad_closesem) != OK) + { + ret = -errno; + } + else + { + /* Increment the count of references to the device. If this the first + * time that the driver has been opened for this device, then initialize + * the device. + */ + + tmp = dev->ad_ocount + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + } + else + { + /* Check if this is the first time that the driver has been opened. */ + + if (tmp == 1) + { + /* Yes.. perform one time hardware initialization. */ + + irqstate_t flags = irqsave(); + ret = dev->ad_ops->ao_setup(dev); + if (ret == OK) + { + /* Mark the FIFOs empty */ + + dev->ad_recv.af_head = 0; + dev->ad_recv.af_tail = 0; + + /* Finally, Enable the CAN RX interrupt */ + + dev->ad_ops->ao_rxint(dev, true); + + /* Save the new open count on success */ + + dev->ad_ocount = tmp; + } + irqrestore(flags); + } + } + sem_post(&dev->ad_closesem); + } + return ret; +} + +/************************************************************************************ + * Name: adc_close + * + * Description: + * This routine is called when the ADC device is closed. + * It waits for the last remaining data to be sent. + * + ************************************************************************************/ + +static int adc_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct adc_dev_s *dev = inode->i_private; + irqstate_t flags; + int ret = OK; + + if (sem_wait(&dev->ad_closesem) != OK) + { + ret = -errno; + } + else + { + /* Decrement the references to the driver. If the reference count will + * decrement to 0, then uninitialize the driver. + */ + + if (dev->ad_ocount > 1) + { + dev->ad_ocount--; + sem_post(&dev->ad_closesem); + } + else + { + /* There are no more references to the port */ + + dev->ad_ocount = 0; + + /* Free the IRQ and disable the ADC device */ + + flags = irqsave(); /* Disable interrupts */ + dev->ad_ops->ao_shutdown(dev); /* Disable the ADC */ + irqrestore(flags); + + sem_post(&dev->ad_closesem); + } + } + return ret; +} + +/**************************************************************************** + * Name: adc_read + ****************************************************************************/ + +static ssize_t adc_read(FAR struct file *filep, FAR char *buffer, size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct adc_dev_s *dev = inode->i_private; + size_t nread; + irqstate_t flags; + int ret = 0; + int msglen; + + avdbg("buflen: %d\n", (int)buflen); + + if (buflen % 5 == 0) + msglen = 5; + else if (buflen % 4 == 0) + msglen = 4; + else if (buflen % 3 == 0) + msglen = 3; + else if (buflen % 2 == 0) + msglen = 2; + else if (buflen == 1) + msglen = 1; + else + msglen = 5; + + if (buflen >= msglen) + { + /* Interrupts must be disabled while accessing the ad_recv FIFO */ + + flags = irqsave(); + while (dev->ad_recv.af_head == dev->ad_recv.af_tail) + { + /* The receive FIFO is empty -- was non-blocking mode selected? */ + + if (filep->f_oflags & O_NONBLOCK) + { + ret = -EAGAIN; + goto return_with_irqdisabled; + } + + /* Wait for a message to be received */ + + dev->ad_nrxwaiters++; + ret = sem_wait(&dev->ad_recv.af_sem); + dev->ad_nrxwaiters--; + if (ret < 0) + { + ret = -errno; + goto return_with_irqdisabled; + } + } + + /* The ad_recv FIFO is not empty. Copy all buffered data that will fit + * in the user buffer. + */ + + nread = 0; + do + { + FAR struct adc_msg_s *msg = &dev->ad_recv.af_buffer[dev->ad_recv.af_head]; + + /* Will the next message in the FIFO fit into the user buffer? */ + + if (nread + msglen > buflen) + { + /* No.. break out of the loop now with nread equal to the actual + * number of bytes transferred. + */ + + break; + } + + /* Copy the message to the user buffer */ + + if (msglen == 1) + { + /* Only one channel,read highest 8-bits */ + + buffer[nread] = msg->am_data >> 24; + } + else if (msglen == 2) + { + /* Only one channel, read highest 16-bits */ + + *(int16_t *)&buffer[nread] = msg->am_data >> 16; + } + else if (msglen == 3) + { + /* Read channel highest 16-bits */ + + buffer[nread] = msg->am_channel; + *(int16_t *)&buffer[nread + 1] = msg->am_data >> 16; + } + else if (msglen == 4) + { + /* read channel highest 24-bits */ + + *(int32_t *)&buffer[nread] = msg->am_data; + buffer[nread] = msg->am_channel; + } + else + { + /* Read all */ + + *(int32_t *)&buffer[nread + 1] = msg->am_data; + buffer[nread] = msg->am_channel; + } + nread += msglen; + + /* Increment the head of the circular message buffer */ + + if (++dev->ad_recv.af_head >= CONFIG_ADC_FIFOSIZE) + { + dev->ad_recv.af_head = 0; + } + } + while (dev->ad_recv.af_head != dev->ad_recv.af_tail); + + /* All on the messages have bee transferred. Return the number of bytes + * that were read. + */ + + ret = nread; + +return_with_irqdisabled: + irqrestore(flags); + } + + avdbg("Returning: %d\n", ret); + return ret; +} + +/************************************************************************************ + * Name: adc_write + ************************************************************************************/ + +static ssize_t adc_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) +{ + return 0; +} + +/************************************************************************************ + * Name: adc_ioctl + ************************************************************************************/ + +static int adc_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct adc_dev_s *dev = inode->i_private; + int ret = OK; + + ret = dev->ad_ops->ao_ioctl(dev, cmd, arg); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data) +{ + FAR struct adc_fifo_s *fifo = &dev->ad_recv; + int nexttail; + int err = -ENOMEM; + + /* Check if adding this new message would over-run the drivers ability to enqueue + * read data. + */ + + nexttail = fifo->af_tail + 1; + if (nexttail >= CONFIG_ADC_FIFOSIZE) + { + nexttail = 0; + } + + /* Refuse the new data if the FIFO is full */ + + if (nexttail != fifo->af_head) + { + /* Add the new, decoded CAN message at the tail of the FIFO */ + + fifo->af_buffer[fifo->af_tail].am_channel = ch; + fifo->af_buffer[fifo->af_tail].am_data = data; + + /* Increment the tail of the circular buffer */ + + fifo->af_tail = nexttail; + + if (dev->ad_nrxwaiters > 0) + { + sem_post(&fifo->af_sem); + } + err = OK; + } + return err; +} + +int adc_register(FAR const char *path, FAR struct adc_dev_s *dev) +{ + /* Initialize the ADC device structure */ + + dev->ad_ocount = 0; + + sem_init(&dev->ad_recv.af_sem, 0, 0); + sem_init(&dev->ad_closesem, 0, 1); + + dev->ad_ops->ao_reset(dev); + + return register_driver(path, &adc_fops, 0444, dev); +} diff --git a/nuttx/drivers/analog/ads1255.c b/nuttx/drivers/analog/ads1255.c new file mode 100644 index 0000000000..374decc54a --- /dev/null +++ b/nuttx/drivers/analog/ads1255.c @@ -0,0 +1,335 @@ +/************************************************************************************ + * arch/drivers/analog/ads1255.c + * + * Copyright (C) 2011 Li Zhuoyi. All rights reserved. + * Author: Li Zhuoyi + * History: 0.1 2011-08-05 initial version + * 0.2 2011-08-25 fix bug in g_adcdev (cd_ops -> ad_ops,cd_priv -> ad_priv) + * + * This file is a part of NuttX: + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(CONFIG_ADC_ADS1255) + +#define ADS125X_BUFON 0x02 +#define ADS125X_BUFOFF 0x00 + +#define ADS125X_PGA1 0x00 +#define ADS125X_PGA2 0x01 +#define ADS125X_PGA4 0x02 +#define ADS125X_PGA8 0x03 +#define ADS125X_PGA16 0x04 +#define ADS125X_PGA32 0x05 +#define ADS125X_PGA64 0x06 + +#define ADS125X_RDATA 0x01 //Read Data +#define ADS125X_RDATAC 0x03 //Read Data Continuously +#define ADS125X_SDATAC 0x0F //Stop Read Data Continuously +#define ADS125X_RREG 0x10 //Read from REG +#define ADS125X_WREG 0x50 //Write to REG +#define ADS125X_SELFCAL 0xF0 //Offset and Gain Self-Calibration +#define ADS125X_SELFOCAL 0xF1 //Offset Self-Calibration +#define ADS125X_SELFGCAL 0xF2 //Gain Self-Calibration +#define ADS125X_SYSOCAL 0xF3 //System Offset Calibration +#define ADS125X_SYSGCAL 0xF4 //System Gain Calibration +#define ADS125X_SYNC 0xFC //Synchronize the A/D Conversion +#define ADS125X_STANDBY 0xFD //Begin Standby Mode +#define ADS125X_RESET 0xFE //Reset to Power-Up Values +#define ADS125X_WAKEUP 0xFF //Completes SYNC and Exits Standby Mode + +#ifndef CONFIG_ADS1255_FREQUENCY +#define CONFIG_ADS1255_FREQUENCY 1000000 +#endif +#ifndef CONFIG_ADS1255_MUX +#define CONFIG_ADS1255_MUX 0x01 +#endif +#ifndef CONFIG_ADS1255_CHMODE +#define CONFIG_ADS1255_CHMODE 0x00 +#endif +#ifndef CONFIG_ADS1255_BUFON +#define CONFIG_ADS1255_BUFON 1 +#endif +#ifndef CONFIG_ADS1255_PGA +#define CONFIG_ADS1255_PGA ADS125X_PGA2 +#endif +#ifndef CONFIG_ADS1255_SPS +#define CONFIG_ADS1255_SPS 50 +#endif + +/**************************************************************************** + * ad_private Types + ****************************************************************************/ + +struct up_dev_s +{ + uint8_t channel; + uint32_t sps; + uint8_t pga; + uint8_t buf; + const uint8_t *mux; + int irq; + int devno; + FAR struct spi_dev_s *spi; /* Cached SPI device reference */ +}; + +/**************************************************************************** + * ad_private Function Prototypes + ****************************************************************************/ + +/* ADC methods */ + +static void adc_reset(FAR struct adc_dev_s *dev); +static int adc_setup(FAR struct adc_dev_s *dev); +static void adc_shutdown(FAR struct adc_dev_s *dev); +static void adc_rxint(FAR struct adc_dev_s *dev, bool enable); +static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg); +static int adc_interrupt(int irq, void *context); + +/**************************************************************************** + * ad_private Data + ****************************************************************************/ + +static const struct adc_ops_s g_adcops = +{ + .ao_reset = adc_reset, /* ao_reset */ + .ao_setup = adc_setup, /* ao_setup */ + .ao_shutdown = adc_shutdown, /* ao_shutdown */ + .ao_rxint = adc_rxint, /* ao_rxint */ + .ao_ioctl = adc_ioctl /* ao_read */ +}; + +static struct up_dev_s g_adcpriv = +{ + .mux = (const uint8_t []) + { + CONFIG_ADS1255_MUX,0 + }, + .sps = CONFIG_ADS1255_SPS, + .channel = 0, + .irq = CONFIG_ADS1255_IRQ, +}; + +static struct adc_dev_s g_adcdev = +{ + .ad_ops = &g_adcops, + .ad_priv= &g_adcpriv, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static uint8_t getspsreg(uint16_t sps) +{ + static const unsigned short sps_tab[]= + { + 3,7,12,20,27,40,55,80,300,750,1500,3000,5000,10000,20000,65535, + }; + static const unsigned char sps_reg[]= + { + 0x03,0x13,0x23,0x33,0x43,0x53,0x63,0x72,0x82,0x92,0xa1,0xb0,0xc0,0xd0,0xe0,0xf0, + }; + int i; + for (i=0; i<16; i++) + { + if (spsad_priv; + FAR struct spi_dev_s *spi = priv->spi; + + SPI_SETMODE(spi, SPIDEV_MODE1); + SPI_SETBITS(spi, 8); + SPI_SETFREQUENCY(spi, CONFIG_ADS1255_FREQUENCY); + usleep(1000); + SPI_SELECT(spi, priv->devno, true); + SPI_SEND(spi,ADS125X_WREG+0x03); //WRITE SPS REG + SPI_SEND(spi,0x00); //count=1 + SPI_SEND(spi,0x63); + SPI_SELECT(spi, priv->devno, false); +} + +/* Configure the ADC. This method is called the first time that the ADC +* device is opened. This will occur when the port is first opened. +* This setup includes configuring and attaching ADC interrupts. Interrupts +* are all disabled upon return. +*/ + +static int adc_setup(FAR struct adc_dev_s *dev) +{ + FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv; + FAR struct spi_dev_s *spi = priv->spi; + int ret = irq_attach(priv->irq, adc_interrupt); + if (ret == OK) + { + SPI_SELECT(spi, priv->devno, true); + SPI_SEND(spi,ADS125X_WREG); //WRITE REG from 0 + SPI_SEND(spi,0x03); //count=4+1 + if (priv->buf) + SPI_SEND(spi,ADS125X_BUFON); //REG0 STATUS BUFFER ON + else + SPI_SEND(spi,ADS125X_BUFOFF); + SPI_SEND(spi,priv->mux[0]); + SPI_SEND(spi,priv->pga); //REG2 ADCON PGA=2 + SPI_SEND(spi,getspsreg(priv->sps)); + usleep(1000); + SPI_SEND(spi,ADS125X_SELFCAL); + SPI_SELECT(spi, priv->devno, false); + up_enable_irq(priv->irq); + } + return ret; +} + +/* Disable the ADC. This method is called when the ADC device is closed. +* This method reverses the operation the setup method. +*/ + +static void adc_shutdown(FAR struct adc_dev_s *dev) +{ + FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv; + up_disable_irq(priv->irq); + irq_detach(priv->irq); +} + +/* Call to enable or disable RX interrupts */ + +static void adc_rxint(FAR struct adc_dev_s *dev, bool enable) +{ + FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv; + if (enable) + up_enable_irq(priv->irq); + else + up_disable_irq(priv->irq); +} + +/* All ioctl calls will be routed through this method */ + +static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg) +{ + dbg("Fix me:Not Implemented\n"); + return 0; +} + +static int adc_interrupt(int irq, void *context) +{ + uint32_t regval; + FAR struct up_dev_s *priv = (FAR struct up_dev_s *)g_adcdev.ad_priv; + FAR struct spi_dev_s *spi = priv->spi; + unsigned char buf[4]; + unsigned char ch; + + SPI_SELECT(spi, priv->devno, true); + SPI_SEND(spi,ADS125X_RDATA); + up_udelay(10); + buf[3]=SPI_SEND(spi,0xff); + buf[2]=SPI_SEND(spi,0xff); + buf[1]=SPI_SEND(spi,0xff); + buf[0]=0; + + priv->channel++; + ch = priv->mux[priv->channel]; + if ( ch == 0 ) + { + priv->channel=0; + ch = priv->mux[0]; + } + + SPI_SEND(spi,ADS125X_WREG+0x01); + SPI_SEND(spi,0x00); + SPI_SEND(spi,ch); + SPI_SEND(spi,ADS125X_SYNC); + up_udelay(2); + SPI_SEND(spi,ADS125X_WAKEUP); + SPI_SELECT(spi, priv->devno, false); + + adc_receive(&g_adcdev,priv->channel,*(int32_t *)buf); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_ads1255initialize + * + * Description: + * Initialize the selected adc port + * + * Input Parameter: + * Port number (for hardware that has mutiple adc interfaces) + * + * Returned Value: + * Valid can device structure reference on succcess; a NULL on failure + * + ****************************************************************************/ + +FAR struct adc_dev_s *up_ads1255initialize(FAR struct spi_dev_s *spi, unsigned int devno) +{ + FAR struct up_dev_s *priv = (FAR struct up_dev_s *)g_adcdev.ad_priv; + + /* Driver state data */ + + priv->spi = spi; + priv->devno = devno; + return &g_adcdev; +} +#endif + diff --git a/nuttx/drivers/analog/dac.c b/nuttx/drivers/analog/dac.c new file mode 100644 index 0000000000..9371e3414c --- /dev/null +++ b/nuttx/drivers/analog/dac.c @@ -0,0 +1,499 @@ +/**************************************************************************** + * drivers/analog/dac.c + * + * Copyright (C) 2011 Li Zhuoyi. All rights reserved. + * Author: Li Zhuoyi + * History: 0.1 2011-08-04 initial version + * + * Derived from drivers/can.c + * + * Copyright (C) 2008-2009Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define HALF_SECOND_MSEC 500 +#define HALF_SECOND_USEC 500000L + + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int dac_open(FAR struct file *filep); +static int dac_close(FAR struct file *filep); +static ssize_t dac_read(FAR struct file *, FAR char *, size_t); +static ssize_t dac_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); +static int dac_ioctl(FAR struct file *filep,int cmd,unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations dac_fops = +{ + dac_open, + dac_close, + dac_read, + dac_write, + 0, + dac_ioctl +#ifndef CONFIG_DISABLE_POLL + , 0 +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/************************************************************************************ + * Name: dac_open + * + * Description: + * This function is called whenever the DAC device is opened. + * + ************************************************************************************/ + +static int dac_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct dac_dev_s *dev = inode->i_private; + uint8_t tmp; + int ret = OK; + + /* If the port is the middle of closing, wait until the close is finished */ + + if (sem_wait(&dev->ad_closesem) != OK) + { + ret = -errno; + } + else + { + /* Increment the count of references to the device. If this the first + * time that the driver has been opened for this device, then initialize + * the device. + */ + + tmp = dev->ad_ocount + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + } + else + { + /* Check if this is the first time that the driver has been opened. */ + + if (tmp == 1) + { + /* Yes.. perform one time hardware initialization. */ + + irqstate_t flags = irqsave(); + ret = dev->ad_ops->ao_setup(dev); + if (ret == OK) + { + /* Mark the FIFOs empty */ + + dev->ad_xmit.af_head = 0; + dev->ad_xmit.af_tail = 0; + + /* Save the new open count on success */ + + dev->ad_ocount = tmp; + } + irqrestore(flags); + } + } + sem_post(&dev->ad_closesem); + } + return ret; +} + +/************************************************************************************ + * Name: dac_close + * + * Description: + * This routine is called when the DAC device is closed. + * It waits for the last remaining data to be sent. + * + ************************************************************************************/ + +static int dac_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct dac_dev_s *dev = inode->i_private; + irqstate_t flags; + int ret = OK; + + if (sem_wait(&dev->ad_closesem) != OK) + { + ret = -errno; + } + else + { + /* Decrement the references to the driver. If the reference count will + * decrement to 0, then uninitialize the driver. + */ + + if (dev->ad_ocount > 1) + { + dev->ad_ocount--; + sem_post(&dev->ad_closesem); + } + else + { + /* There are no more references to the port */ + + dev->ad_ocount = 0; + + /* Now we wait for the transmit FIFO to clear */ + + while (dev->ad_xmit.af_head != dev->ad_xmit.af_tail) + { +#ifndef CONFIG_DISABLE_SIGNALS + usleep(HALF_SECOND_USEC); +#else + up_mdelay(HALF_SECOND_MSEC); +#endif + } + + /* Free the IRQ and disable the DAC device */ + + flags = irqsave(); /* Disable interrupts */ + dev->ad_ops->ao_shutdown(dev); /* Disable the DAC */ + irqrestore(flags); + + sem_post(&dev->ad_closesem); + } + } + return ret; +} + +/**************************************************************************** + * Name: dac_read + ****************************************************************************/ + +static ssize_t dac_read(FAR struct file *filep, FAR char *buffer, size_t buflen) +{ + return 0; +} + +/************************************************************************************ + * Name: dac_xmit + * + * Description: + * Send the message at the head of the ad_xmit FIFO + * + * Assumptions: + * Called with interrupts disabled + * + ************************************************************************************/ + +static int dac_xmit(FAR struct dac_dev_s *dev) +{ + bool enable = false; + int ret = OK; + + /* Check if the xmit FIFO is empty */ + + if (dev->ad_xmit.af_head != dev->ad_xmit.af_tail) + { + /* Send the next message at the head of the FIFO */ + + ret = dev->ad_ops->ao_send(dev, &dev->ad_xmit.af_buffer[dev->ad_xmit.af_head]); + + /* Make sure the TX done interrupts are enabled */ + + enable = (ret == OK ? true : false); + } + dev->ad_ops->ao_txint(dev, enable); + return ret; +} + +/************************************************************************************ + * Name: dac_write + ************************************************************************************/ + +static ssize_t dac_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct dac_dev_s *dev = inode->i_private; + FAR struct dac_fifo_s *fifo = &dev->ad_xmit; + FAR struct dac_msg_s *msg; + bool empty = false; + ssize_t nsent = 0; + irqstate_t flags; + int nexttail; + int msglen; + int ret = 0; + + /* Interrupts must disabled throughout the following */ + + flags = irqsave(); + + /* Check if the TX FIFO was empty when we started. That is a clue that we have + * to kick off a new TX sequence. + */ + + empty = (fifo->af_head == fifo->af_tail); + + /* Add the messages to the FIFO. Ignore any trailing messages that are + * shorter than the minimum. + */ + + if (buflen % 5 ==0 ) + msglen=5; + else if (buflen % 4 ==0 ) + msglen=4; + else if (buflen % 3 ==0 ) + msglen=3; + else if (buflen % 2 ==0 ) + msglen=2; + else if (buflen == 1) + msglen=1; + else + msglen=5; + + while ((buflen - nsent) >= msglen ) + { + /* Check if adding this new message would over-run the drivers ability to enqueue + * xmit data. + */ + + nexttail = fifo->af_tail + 1; + if (nexttail >= CONFIG_DAC_FIFOSIZE) + { + nexttail = 0; + } + + /* If the XMIT fifo becomes full, then wait for space to become available */ + + while (nexttail == fifo->af_head) + { + /* The transmit FIFO is full -- was non-blocking mode selected? */ + + if (filep->f_oflags & O_NONBLOCK) + { + if (nsent == 0) + { + ret = -EAGAIN; + } + else + { + ret = nsent; + } + goto return_with_irqdisabled; + } + + /* If the FIFO was empty when we started, then we will have + * start the XMIT sequence to clear the FIFO. + */ + + if (empty) + { + dac_xmit(dev); + } + + /* Wait for a message to be sent */ + + do + { + ret = sem_wait(&fifo->af_sem); + if (ret < 0 && errno != EINTR) + { + ret = -errno; + goto return_with_irqdisabled; + } + } + while (ret < 0); + + /* Re-check the FIFO state */ + + empty = (fifo->af_head == fifo->af_tail); + } + + /* We get here if there is space at the end of the FIFO. Add the new + * CAN message at the tail of the FIFO. + */ + + if (msglen==5) + { + msg = (FAR struct dac_msg_s *)&buffer[nsent]; + memcpy(&fifo->af_buffer[fifo->af_tail], msg, msglen); + } + else if(msglen == 4) + { + fifo->af_buffer[fifo->af_tail].am_channel=buffer[nsent]; + fifo->af_buffer[fifo->af_tail].am_data=*(uint32_t *)&buffer[nsent]; + fifo->af_buffer[fifo->af_tail].am_data&=0xffffff00; + } + else if(msglen == 3) + { + fifo->af_buffer[fifo->af_tail].am_channel=buffer[nsent]; + fifo->af_buffer[fifo->af_tail].am_data=(*(uint16_t *)&buffer[nsent+1]); + fifo->af_buffer[fifo->af_tail].am_data<<=16; + } + else if(msglen == 2) + { + fifo->af_buffer[fifo->af_tail].am_channel=0; + fifo->af_buffer[fifo->af_tail].am_data=(*(uint16_t *)&buffer[nsent]); + fifo->af_buffer[fifo->af_tail].am_data<<=16; + } + else if(msglen == 1) + { + fifo->af_buffer[fifo->af_tail].am_channel=0; + fifo->af_buffer[fifo->af_tail].am_data=buffer[nsent]; + fifo->af_buffer[fifo->af_tail].am_data<<=24; + } + /* Increment the tail of the circular buffer */ + + fifo->af_tail = nexttail; + + /* Increment the number of bytes that were sent */ + + nsent += msglen; + } + + /* We get here after all messages have been added to the FIFO. Check if + * we need to kick of the XMIT sequence. + */ + + if (empty) + { + dac_xmit(dev); + } + + /* Return the number of bytes that were sent */ + + ret = nsent; + +return_with_irqdisabled: + irqrestore(flags); + return ret; +} + +/************************************************************************************ + * Name: dac_ioctl + ************************************************************************************/ + +static int dac_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct dac_dev_s *dev = inode->i_private; + int ret = OK; + + ret = dev->ad_ops->ao_ioctl(dev, cmd, arg); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/************************************************************************************ + * Name: dac_txdone + * + * Description: + * Called from the DAC interrupt handler at the completion of a send operation. + * + * Return: + * OK on success; a negated errno on failure. + * + ************************************************************************************/ + +int dac_txdone(FAR struct dac_dev_s *dev) +{ + int ret = -ENOENT; + + /* Verify that the xmit FIFO is not empty */ + + if (dev->ad_xmit.af_head != dev->ad_xmit.af_tail) + { + /* Remove the message at the head of the xmit FIFO */ + + if (++dev->ad_xmit.af_head >= CONFIG_DAC_FIFOSIZE) + { + dev->ad_xmit.af_head = 0; + } + + /* Send the next message in the FIFO */ + + ret = dac_xmit(dev); + if (ret == OK) + { + /* Inform any waiting threads that new xmit space is available */ + + ret = sem_post(&dev->ad_xmit.af_sem); + } + } + return ret; +} + +int dac_register(FAR const char *path, FAR struct dac_dev_s *dev) +{ + /* Initialize the DAC device structure */ + + dev->ad_ocount = 0; + + sem_init(&dev->ad_xmit.af_sem, 0, 0); + sem_init(&dev->ad_closesem, 0, 1); + + dev->ad_ops->ao_reset(dev); + + return register_driver(path, &dac_fops, 0555, dev); +} + diff --git a/nuttx/drivers/analog/pga11x.c b/nuttx/drivers/analog/pga11x.c new file mode 100644 index 0000000000..7bb4a11bb0 --- /dev/null +++ b/nuttx/drivers/analog/pga11x.c @@ -0,0 +1,793 @@ +/**************************************************************************** + * drivers/analog/pga11x.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "PGA112, PGA113, PGA116, PGA117: Zerø-Drift PROGRAMMABLE GAIN AMPLIFIER + * with MUX", SBOS424B, March 2008, Revised September 2008, Texas + * Instruments Incorporated" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#if defined(CONFIG_ADC) && defined(CONFIG_ADC_PGA11X) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* The PGA112/PGA113 have a three-wire SPI digital interface; the + * PGA116/PGA117 have a four-wire SPI digital interface. The PGA116/117 also + * have daisy-chain capability (The PGA112/PGA113 can be used as the last device + * in a daisy-chain as shown if write-only communication is acceptable). + */ + +/* PGA11x commands (PGA112/PGA113) */ + +#define PGA11X_CMD_READ 0x6a00 +#define PGA11X_CMD_WRITE 0x2a00 +#define PGA11X_CMD_NOOP 0x0000 +#define PGA11X_CMD_SDN_DIS 0xe100 +#define PGA11X_CMD_SDN_EN 0xe1f1 + +/* SPI Daisy-Chain Commands (PGA116/PGA117) */ + +#define PGA11X_DCCMD_SELECTOR 0x8000 +#define PGA11X_DCCMD_NOOP (PGA11X_DCCMD_SELECTOR | PGA11X_CMD_NOOP) +#define PGA11X_DCCMD_SDN_DIS (PGA11X_DCCMD_SELECTOR | PGA11X_CMD_SDN_DIS) +#define PGA11X_DCCMD_SDN_EN (PGA11X_DCCMD_SELECTOR | PGA11X_CMD_SDN_EN) +#define PGA11X_DCCMD_READ (PGA11X_DCCMD_SELECTOR | PGA11X_CMD_READ) +#define PGA11X_DCCMD_WRITE (PGA11X_DCCMD_SELECTOR | PGA11X_CMD_WRITE) + +/* Write command Gain Selection Bits (PGA112/PGA113) + * + * the PGA112 and PGA116 provide binary gain selections (1, 2, 4, 8, 16, 32, + * 64, 128); the PGA113 and PGA117 provide scope gain selections (1, 2, 5, 10, + * 20, 50, 100, 200). + */ + +#define PGA11X_GAIN_SHIFT (4) /* Bits 4-7: Gain Selection Bits */ +#define PGA11X_GAIN_MASK (15 << PGA11X_GAIN_SHIFT) + +/* Write command Mux Channel Selection Bits + * + * The PGA112/PGA113 have a two-channel input MUX; the PGA116/PGA117 have a + * 10-channel input MUX. + */ + +#define PGA11X_CHAN_SHIFT (0) /* Bits 0-3: Channel Selection Bits */ +#define PGA11X_CHAN_MASK (15 << PGA11X_CHAN_SHIFT) + +/* Other definitions ********************************************************/ + +#define SPI_DUMMY 0xff + +/* Debug ********************************************************************/ +/* Check if (non-standard) SPI debug is enabled */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_SPI +#endif + +#ifdef CONFIG_DEBUG_SPI +# define spidbg dbg +# ifdef CONFIG_DEBUG_VERBOSE +# define spivdbg dbg +# else +# define spivdbg(x...) +# endif +#else +# define spidbg(x...) +# define spivdbg(x...) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pga11x_configure + * + * Description: + * Configure the SPI bus as needed for the PGA11x device. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void pga11x_configure(FAR struct spi_dev_s *spi) +{ + spivdbg("MODE: %d BITS: 8 Frequency: %d\n", + CONFIG_PGA11X_SPIMODE, CONFIG_PGA11X_SPIFREQUENCY); + + /* Call the setfrequency, setbits, and setmode methods to make sure that + * the SPI is properly configured for the device. + */ + + SPI_SETMODE(spi, CONFIG_PGA11X_SPIMODE); + SPI_SETBITS(spi, 8); + (void)SPI_SETFREQUENCY(spi, CONFIG_PGA11X_SPIFREQUENCY); +} + +/**************************************************************************** + * Name: pga11x_lock + * + * Description: + * Lock the SPI bus and configure it as needed for the PGA11x device. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifndef CONFIG_SPI_OWNBUS +static void pga11x_lock(FAR struct spi_dev_s *spi) +{ + spivdbg("Locking\n"); + + /* On SPI busses where there are multiple devices, it will be necessary to + * lock SPI to have exclusive access to the busses for a sequence of + * transfers. The bus should be locked before the chip is selected. + * + * This is a blocking call and will not return until we have exclusiv access to + * the SPI buss. We will retain that exclusive access until the bus is unlocked. + */ + + SPI_LOCK(spi, true); + + /* After locking the SPI bus, the we also need call the setfrequency, setbits, and + * setmode methods to make sure that the SPI is properly configured for the device. + * If the SPI buss is being shared, then it may have been left in an incompatible + * state. + */ + + pga11x_configure(spi); +} +#else +# define pga11x_lock(spi) +#endif + +/**************************************************************************** + * Name: pga11x_unlock + * + * Description: + * Lock the SPI bus and configure it as needed for the PGA11x device. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifndef CONFIG_SPI_OWNBUS +static inline void pga11x_unlock(FAR struct spi_dev_s *spi) +{ + spivdbg("Unlocking\n"); + + SPI_LOCK(spi, false); +} +#else +# define pga11x_unlock(spi) +#endif + +/**************************************************************************** + * Name: pga11x_send16 + * + * Description: + * Send 16 bits of data, ignoring any returned data + * + * Input Parameters: + * spi - PGA11X driver instance + * word - The data to send + * + * Returned Value: + * None + * + * Assumptions: + * The bus is locked and the device is selected + * + ****************************************************************************/ + +static void pga11x_send16(FAR struct spi_dev_s *spi, uint16_t word) +{ + spivdbg("Send %04x\n", word); + + /* The logical interface is 16-bits wide. However, this driver uses a + * 8-bit configuration for greaer portability. + * + * Send the MS byte first. Then the LS byte. + */ + + SPI_SEND(spi, word >> 8); + SPI_SEND(spi, word & 0xff); +} + +/**************************************************************************** + * Name: pga11x_recv16 + * + * Description: + * Receive 16 bits of data. + * + * Input Parameters: + * spi - PGA11X driver instance + * + * Returned Value: + * The received 16-bit value + * + * Assumptions: + * The bus is locked and the device is selected + * + ****************************************************************************/ + +static uint16_t pga11x_recv16(FAR struct spi_dev_s *spi) +{ + uint8_t msb; + uint8_t lsb; + + /* The logical interface is 16-bits wide. However, this driver uses a + * 8-bit configuration for greaer portability. + * + * Send a dummy byte and receive MS byte first. Then the LS byte. + */ + + msb = SPI_SEND(spi, SPI_DUMMY); + lsb = SPI_SEND(spi, SPI_DUMMY); + spivdbg("Received %02x %02x\n", msb, lsb); + + return ((uint16_t)msb << 8) | (uint16_t)lsb; +} + +/**************************************************************************** + * Name: pga11x_write + * + * Description: + * Send a 16-bit command. + * + * Input Parameters: + * spi - PGA11X driver instance + * cmd - PGA11X command (non-daisy chained) + * u1cmd - PGA11X U1 command (daisy chained) + * u2cmd - PGA11X U2 command (daisy chained) + * + * Returned Value: + * The received 16-bit value + * + * Assumptions: + * The device is NOT selected and the NOT bus is locked. + * + ****************************************************************************/ + +#ifndef CONFIG_PGA11X_DAISYCHAIN +static void pga11x_write(FAR struct spi_dev_s *spi, uint16_t cmd) +{ + spivdbg("cmd %04x\n", cmd); + + /* Lock, select, send the 16-bit command, de-select, and un-lock. */ + + pga11x_lock(spi); + SPI_SELECT(spi, SPIDEV_MUX, true); + pga11x_send16(spi, cmd); + SPI_SELECT(spi, SPIDEV_MUX, false); + pga11x_unlock(spi); +} +#else +static void pga11x_write(FAR struct spi_dev_s *spi, uint16_t u1cmd, uint16_t u2cmd) +{ + spivdbg("U1 cmd: %04x U2 cmd: %04x\n", u1cmd, u2cmd); + + /* Lock, select, send the U2 16-bit command, the U1 16-bit command, de-select, + * and un-lock. + */ + + pga11x_lock(spi); + SPI_SELECT(spi, SPIDEV_MUX, true); + pga11x_send16(spi, u2cmd); + pga11x_send16(spi, u1cmd); + SPI_SELECT(spi, SPIDEV_MUX, false); + pga11x_unlock(spi); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pga11x_initialize + * + * Description: + * Initialize the PGA117 amplifier/multiplexer(s). + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * + * Returned Value: + * On success, a non-NULL opaque handle is returned; a NULL is returned + * on any failure. This handle may be used with the other PGA117 interface + * functions to control the multiplexer + * + ****************************************************************************/ + +PGA11X_HANDLE pga11x_initialize(FAR struct spi_dev_s *spi) +{ + spivdbg("Entry\n"); + + /* Configure the SPI us for the device. Do this now only if the PGA11X is + * the only device on the bus. + */ + +#ifdef CONFIG_SPI_OWNBUS + pga11x_configure(spi); +#endif + + /* No other special state is required, just return the SPI driver instance + * as the handle. This gives us a place to extend functionality in the + * future if neccessary. + */ + + return (PGA11X_HANDLE)spi; +} + +/**************************************************************************** + * Name: pga11x_select + * + * Description: + * Select an input channel and gain for all PGA11xs. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_select() configures + * both chips in the daisy-chain. pga11x_uselect() is provided to support + * configuring the parts in the daisychain independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * settings - New channel and gain settings + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +int pga11x_select(PGA11X_HANDLE handle, + FAR const struct pga11x_settings_s *settings) +{ +#ifndef CONFIG_PGA11X_DAISYCHAIN + FAR struct spi_dev_s *spi = (FAR struct spi_dev_s *)handle; + uint16_t cmd; + + DEBUGASSERT(handle && settings); + spivdbg("channel: %d gain: %d\n", settings->channel, settings->gain); + + /* Format the command */ + + cmd = PGA11X_CMD_WRITE | + ((uint16_t)settings->channel << PGA11X_CHAN_SHIFT) | + ((uint16_t)settings->gain << PGA11X_GAIN_SHIFT); + + /* Send the command */ + + pga11x_write(spi, cmd); + return OK; +#else + FAR struct spi_dev_s *spi = (FAR struct spi_dev_s *)handle; + uint16_t u1cmd; + uint16_t u2cmd; + + DEBUGASSERT(handle && settings); + spivdbg("U1 channel: %d gain: %d\n", settings->u1.channel, settings->u1.gain); + spivdbg("U1 channel: %d gain: %d\n", settings->u1.channel, settings->u1.gain); + + /* Format the commands */ + + u1cmd = PGA11X_CMD_WRITE | + ((uint16_t)settings->u1.channel << PGA11X_CHAN_SHIFT) | + ((uint16_t)settings->u1.gain << PGA11X_GAIN_SHIFT); + + u2cmd = PGA11X_DCCMD_WRITE | + ((uint16_t)settings->u2.channel << PGA11X_CHAN_SHIFT) | + ((uint16_t)settings->u2.gain << PGA11X_GAIN_SHIFT); + + /* Send the command */ + + pga11x_write(spi, u1cmd, u2cmd); + return OK; +#endif +} + +/**************************************************************************** + * Name: pga11x_uselect + * + * Description: + * Select an input channel and gain for one PGA11x. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_uselect() configures + * one chips in the daisy-chain. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * pos - Position of the chip in the daisy chain (0 or 1) + * settings - New channel and gain settings + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_PGA11X_DAISYCHAIN +int pga11x_uselect(PGA11X_HANDLE handle, int pos, + FAR const struct pga11x_usettings_s *settings) +{ + FAR struct spi_dev_s *spi = (FAR struct spi_dev_s *)handle; + uint16_t u1cmd; + uint16_t u2cmd; + + spivdbg("channel: %d gain: %d\n", settings->channel, settings->gain); + DEBUGASSERT(handle); + + /* Format the commands */ + + if (pos == 0) + { + u1cmd = PGA11X_CMD_WRITE | + ((uint16_t)settings->channel << PGA11X_CHAN_SHIFT) | + ((uint16_t)settings->gain << PGA11X_GAIN_SHIFT); + u2cmd = PGA11X_DCCMD_NOOP; + } + else /* if (pos == 1) */ + { + u1cmd = PGA11X_CMD_NOOP; + u2cmd = PGA11X_DCCMD_WRITE | + ((uint16_t)settings->channel << PGA11X_CHAN_SHIFT) | + ((uint16_t)settings->gain << PGA11X_GAIN_SHIFT); + } + + /* Send the command */ + + pga11x_write(spi, u1cmd, u2cmd); + return OK; +} +#endif + +/**************************************************************************** + * Name: pga11x_read + * + * Description: + * Read from all PGA117 amplifier/multiplexers. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_read() reads from + * both chips in the daisy-chain. pga11x_uread() is provided to support + * accessing the parts independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * settings - Returned channel and gain settings + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +int pga11x_read(PGA11X_HANDLE handle, FAR struct pga11x_settings_s *settings) +{ +#ifdef CONFIG_PGA11X_DAISYCHAIN + FAR struct spi_dev_s *spi = (FAR struct spi_dev_s *)handle; + uint16_t u1value; + uint16_t u2value; + + spivdbg("Entry\n"); + DEBUGASSERT(handle && settings); + + /* Lock the bus and read the configuration */ + + pga11x_lock(spi); + + /* Select, send the 16-bit command, the 16-bit daisy-chain command, and + * then de-select the part. I do not know if de-selection between word + * transfers is required. However, it is shown in the timing diagrams + * for the part. + */ + + SPI_SELECT(spi, SPIDEV_MUX, true); + pga11x_send16(spi, PGA11X_CMD_READ); + pga11x_send16(spi, PGA11X_DCCMD_READ); + SPI_SELECT(spi, SPIDEV_MUX, false); + + /* Re-select, get the returned values, de-select, and unlock */ + + SPI_SELECT(spi, SPIDEV_MUX, true); + u2value = pga11x_recv16(spi); + u1value = pga11x_recv16(spi); + SPI_SELECT(spi, SPIDEV_MUX, false); + pga11x_unlock(spi); + + /* Decode the returned value */ + + spivdbg("Returning %04x %04x\n", u2value, u1value); + settings->u1.channel = (uint8_t)((u1value & PGA11X_CHAN_MASK) >> PGA11X_CHAN_SHIFT); + settings->u1.gain = (uint8_t)((u1value & PGA11X_GAIN_MASK) >> PGA11X_GAIN_SHIFT); + settings->u2.channel = (uint8_t)((u2value & PGA11X_CHAN_MASK) >> PGA11X_CHAN_SHIFT); + settings->u2.gain = (uint8_t)((u2value & PGA11X_GAIN_MASK) >> PGA11X_GAIN_SHIFT); + return OK; +#else + FAR struct spi_dev_s *spi = (FAR struct spi_dev_s *)handle; + uint16_t value; + + spivdbg("Entry\n"); + DEBUGASSERT(handle); + + /* Lock the bus and read the configuration */ + + pga11x_lock(spi); + + /* Select, send the 16-bit PGA11X_CMD_READ command, and de-select. I do + * not know if de-selection between word transfers is required. However, + * it is shown in the timing diagrams for the part. + */ + + SPI_SELECT(spi, SPIDEV_MUX, true); + pga11x_send16(spi, PGA11X_CMD_READ); + SPI_SELECT(spi, SPIDEV_MUX, false); + + /* Re-select, get the returned value, de-select, and unlock */ + + SPI_SELECT(spi, SPIDEV_MUX, true); + value = pga11x_recv16(spi); + SPI_SELECT(spi, SPIDEV_MUX, false); + pga11x_unlock(spi); + + /* Decode the returned value */ + + spivdbg("Returning: %04x\n", value); + settings->channel = (uint8_t)((value & PGA11X_CHAN_MASK) >> PGA11X_CHAN_SHIFT); + settings->gain = (uint8_t)((value & PGA11X_GAIN_MASK) >> PGA11X_GAIN_SHIFT); + return OK; +#endif +} + +/**************************************************************************** + * Name: pga11x_uread + * + * Description: + * Read from one PGA117 amplifier/multiplexer. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_read() reads + * the parts independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * pos - Position of the chip in the daisy chain (0 or 1) + * settings - Returned channel and gain settings + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_PGA11X_DAISYCHAIN +int pga11x_uread(PGA11X_HANDLE handle, int pos, + FAR struct pga11x_usettings_s *settings) +{ + struct pga11x_settings_s both; + int ret = pga11x_read(handle, &both); + if (ret == OK) + { + if (pos == 0) + { + settings->channel = both.u1.channel; + settings->gain = both.u1.gain; + } + else /* if (pos == 1) */ + { + settings->channel = both.u2.channel; + settings->gain = both.u2.gain; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: pga11x_shutdown + * + * Description: + * Put all PGA11x's in shutdown down mode. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_shutdown() controls + * both chips in the daisy-chain. pga11x_ushutdown() is provided to + * control the parts independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +int pga11x_shutdown(PGA11X_HANDLE handle) +{ + FAR struct spi_dev_s *spi = (FAR struct spi_dev_s *)handle; + + spivdbg("Entry\n"); + DEBUGASSERT(handle); + + /* Enter shutdown mode by issuing an SDN_EN command */ + +#ifdef CONFIG_PGA11X_DAISYCHAIN + pga11x_write(spi, PGA11X_CMD_SDN_EN, PGA11X_DCCMD_SDN_EN); +#else + pga11x_write(spi, PGA11X_CMD_SDN_EN); +#endif + return OK; +} + +/**************************************************************************** + * Name: pga11x_ushutdown + * + * Description: + * Put one PGA11x in shutdown down mode. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_ushutdown() is + * provided to shutdown the parts independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * pos - Position of the chip in the daisy chain (0 or 1) + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_PGA11X_DAISYCHAIN +int pga11x_ushutdown(PGA11X_HANDLE handle, int pos) +{ + FAR struct spi_dev_s *spi = (FAR struct spi_dev_s *)handle; + + spivdbg("Entry\n"); + DEBUGASSERT(handle); + + /* Enter shutdown mode by issuing an SDN_EN command */ + + if (pos == 0) + { + pga11x_write(spi, PGA11X_CMD_SDN_EN, PGA11X_DCCMD_NOOP); + } + else + { + pga11x_write(spi, PGA11X_CMD_NOOP, PGA11X_DCCMD_SDN_EN); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: pga11x_enable + * + * Description: + * Take all PGA11x's out of shutdown down mode. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_enable() controls + * both chips in the daisy-chain. pga11x_uenable() is provided to + * control the parts independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +int pga11x_enable(PGA11X_HANDLE handle) +{ + FAR struct spi_dev_s *spi = (FAR struct spi_dev_s *)handle; + + spivdbg("Entry\n"); + DEBUGASSERT(handle); + + /* Lock the bus and send the shutdown disable command. Shutdown mode is + * cleared (returned to the last valid write configuration) by the SDN_DIS + * command or by any valid Write command + */ + +#ifdef CONFIG_PGA11X_DAISYCHAIN + pga11x_write(spi, PGA11X_CMD_SDN_DIS, PGA11X_DCCMD_SDN_DIS); +#else + pga11x_write(spi, PGA11X_CMD_SDN_DIS); +#endif + return OK; +} + +/**************************************************************************** + * Name: pga11x_uenable + * + * Description: + * Take one PGA11x out of shutdown down mode. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_uenable() is + * provided to enable the parts independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * pos - Position of the chip in the daisy chain (0 or 1) + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_PGA11X_DAISYCHAIN +int pga11x_uenable(PGA11X_HANDLE handle, int pos) +{ + FAR struct spi_dev_s *spi = (FAR struct spi_dev_s *)handle; + + spivdbg("Entry\n"); + DEBUGASSERT(handle); + + /* Enter shutdown mode by issuing an SDN_EN command */ + + if (pos == 0) + { + pga11x_write(spi, PGA11X_CMD_SDN_DIS, PGA11X_DCCMD_NOOP); + } + else + { + pga11x_write(spi, PGA11X_CMD_NOOP, PGA11X_DCCMD_SDN_DIS); + } + + return OK; +} +#endif + +#endif /* CONFIG_ADC && CONFIG_ADC_PGA11X */ + diff --git a/nuttx/drivers/bch/Kconfig b/nuttx/drivers/bch/Kconfig new file mode 100644 index 0000000000..ae2bf31307 --- /dev/null +++ b/nuttx/drivers/bch/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# diff --git a/nuttx/drivers/bch/Make.defs b/nuttx/drivers/bch/Make.defs new file mode 100644 index 0000000000..bc22df8e26 --- /dev/null +++ b/nuttx/drivers/bch/Make.defs @@ -0,0 +1,52 @@ +############################################################################ +# drivers/bch/Make.defs +# +# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifneq ($(CONFIG_NFILE_DESCRIPTORS),0) +ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y) + +# Include BCH driver + +CSRCS += bchlib_setup.c bchlib_teardown.c bchlib_read.c bchlib_write.c \ + bchlib_cache.c bchlib_sem.c bchdev_register.c bchdev_unregister.c \ + bchdev_driver.c + +# Include BCH driver build support + +DEPPATH += --dep-path bch +VPATH += :bch +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/bch} + +endif +endif diff --git a/nuttx/drivers/bch/bch_internal.h b/nuttx/drivers/bch/bch_internal.h new file mode 100644 index 0000000000..fb1c642367 --- /dev/null +++ b/nuttx/drivers/bch/bch_internal.h @@ -0,0 +1,102 @@ +/**************************************************************************** + * drivers/bch/bch_internal.h + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_BCH_INTERNAL_H +#define __FS_BCH_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define bchlib_semgive(d) sem_post(&(d)->sem) /* To match bchlib_semtake */ +#define MAX_OPENCNT (255) /* Limit of uint8_t */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct bchlib_s +{ + struct inode *inode; /* I-node of the block driver */ + sem_t sem; /* For atomic accesses to this structure */ + size_t nsectors; /* Number of sectors supported by the device */ + size_t sector; /* The current sector in the buffer */ + uint16_t sectsize; /* The size of one sector on the device */ + uint8_t refs; /* Number of references */ + bool dirty; /* Data has been written to the buffer */ + bool readonly; /* true: Only read operations are supported */ + FAR uint8_t *buffer; /* One sector buffer */ +}; + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN const struct file_operations bch_fops; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +EXTERN void bchlib_semtake(FAR struct bchlib_s *bch); +EXTERN int bchlib_flushsector(FAR struct bchlib_s *bch); +EXTERN int bchlib_readsector(FAR struct bchlib_s *bch, size_t sector); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __FS_BCH_INTERNAL_H */ diff --git a/nuttx/drivers/bch/bchdev_driver.c b/nuttx/drivers/bch/bchdev_driver.c new file mode 100644 index 0000000000..262a0af469 --- /dev/null +++ b/nuttx/drivers/bch/bchdev_driver.c @@ -0,0 +1,255 @@ +/**************************************************************************** + * drivers/bch/bchdev_driver.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bch_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int bch_open(FAR struct file *filp); +static int bch_close(FAR struct file *filp); +static ssize_t bch_read(FAR struct file *, FAR char *, size_t); +static ssize_t bch_write(FAR struct file *, FAR const char *, size_t); +static int bch_ioctl(FAR struct file *filp, int cmd, unsigned long arg); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct file_operations bch_fops = +{ + bch_open, /* open */ + bch_close, /* close */ + bch_read, /* read */ + bch_write, /* write */ + 0, /* seek */ + bch_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , 0 /* poll */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bch_open + * + * Description: Open the block device + * + ****************************************************************************/ + +static int bch_open(FAR struct file *filp) +{ + FAR struct inode *inode = filp->f_inode; + FAR struct bchlib_s *bch; + + DEBUGASSERT(inode && inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + /* Increment the reference count */ + + bchlib_semtake(bch); + if (bch->refs == MAX_OPENCNT) + { + return -EMFILE; + } + else + { + bch->refs++; + } + bchlib_semgive(bch); + + return OK; +} + +/**************************************************************************** + * Name: bch_close + * + * Description: close the block device + * + ****************************************************************************/ + +static int bch_close(FAR struct file *filp) +{ + FAR struct inode *inode = filp->f_inode; + FAR struct bchlib_s *bch; + int ret = OK; + + DEBUGASSERT(inode && inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + /* Flush any dirty pages remaining in the cache */ + + bchlib_semtake(bch); + (void)bchlib_flushsector(bch); + + /* Decrement the reference count (I don't use bchlib_decref() because I + * want the entire close operation to be atomic wrt other driver operations. + */ + + if (bch->refs == 0) + { + ret = -EIO; + } + else + { + bch->refs--; + } + bchlib_semgive(bch); + + return ret; +} + +/**************************************************************************** + * Name:bch_read + ****************************************************************************/ + +static ssize_t bch_read(FAR struct file *filp, FAR char *buffer, size_t len) +{ + FAR struct inode *inode = filp->f_inode; + FAR struct bchlib_s *bch; + int ret; + + DEBUGASSERT(inode && inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + bchlib_semtake(bch); + ret = bchlib_read(bch, buffer, filp->f_pos, len); + if (ret > 0) + { + filp->f_pos += len; + } + bchlib_semgive(bch); + return ret; +} + +/**************************************************************************** + * Name:bch_write + ****************************************************************************/ + +static ssize_t bch_write(FAR struct file *filp, FAR const char *buffer, size_t len) +{ + FAR struct inode *inode = filp->f_inode; + FAR struct bchlib_s *bch; + int ret = -EACCES; + + DEBUGASSERT(inode && inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + if (!bch->readonly) + { + bchlib_semtake(bch); + ret = bchlib_write(bch, buffer, filp->f_pos, len); + if (ret > 0) + { + filp->f_pos += len; + } + bchlib_semgive(bch); + } + + return ret; +} + +/**************************************************************************** + * Name: bch_ioctl + * + * Description: Return device geometry + * + ****************************************************************************/ + +static int bch_ioctl(FAR struct file *filp, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filp->f_inode; + FAR struct bchlib_s *bch; + int ret = -ENOTTY; + + DEBUGASSERT(inode && inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + if (cmd == DIOC_GETPRIV) + { + FAR struct bchlib_s **bchr = (FAR struct bchlib_s **)((uintptr_t)arg); + + bchlib_semtake(bch); + if (!bchr && bch->refs < 255) + { + ret = -EINVAL; + } + else + { + bch->refs++; + *bchr = bch; + } + bchlib_semgive(bch); + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/nuttx/drivers/bch/bchdev_register.c b/nuttx/drivers/bch/bchdev_register.c new file mode 100644 index 0000000000..924977371e --- /dev/null +++ b/nuttx/drivers/bch/bchdev_register.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * drivers/bch/bchdev_register.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "bch_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bchdev_register + * + * Description: + * Setup so that it exports the block driver referenced by 'blkdev' as a + * character device 'chardev' + * + ****************************************************************************/ + +int bchdev_register(FAR const char *blkdev, FAR const char *chardev, + bool readonly) +{ + FAR void *handle; + int ret; + + /* Setup the BCH lib functions */ + + ret = bchlib_setup(blkdev, readonly, &handle); + if (ret < 0) + { + fdbg("bchlib_setup failed: %d\n", -ret); + return ret; + } + + /* Then setup the character device */ + + ret = register_driver(chardev, &bch_fops, 0666, handle); + if (ret < 0) + { + fdbg("register_driver failed: %d\n", -ret); + bchlib_teardown(handle); + handle = NULL; + } + + return ret; +} diff --git a/nuttx/drivers/bch/bchdev_unregister.c b/nuttx/drivers/bch/bchdev_unregister.c new file mode 100644 index 0000000000..8c7360882b --- /dev/null +++ b/nuttx/drivers/bch/bchdev_unregister.c @@ -0,0 +1,160 @@ +/**************************************************************************** + * drivers/bch/bchdev_unregister.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bch_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bchdev_unregister + * + * Description: + * Unregister character driver access to a block device that was created + * by a previous call to bchdev_register(). + * + ****************************************************************************/ + +int bchdev_unregister(FAR const char *chardev) +{ + FAR struct bchlib_s *bch; + int fd; + int ret; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (!chardev) + { + return -EINVAL; + } +#endif + + /* Open the character driver associated with chardev */ + + fd = open(chardev, O_RDONLY); + if (fd < 0) + { + dbg("Failed to open %s: %d\n", chardev, errno); + return -errno; + } + + /* Get a reference to the internal data structure. On success, we + * will hold a reference count on the state structure. + */ + + ret = ioctl(fd, DIOC_GETPRIV, (unsigned long)((uintptr_t)&bch)); + (void)close(fd); + + if (ret < 0) + { + dbg("ioctl failed: %d\n", errno); + return -errno; + } + + /* Lock out context switches. If there are no other references + * and no context switches, then we can assume that we can safely + * teardown the driver. + */ + + sched_lock(); + + /* Check if the internal structure is non-busy (we hold one reference). */ + + if (bch->refs > 1) + { + ret = -EBUSY; + goto errout_with_lock; + } + + /* Unregister the driver (this cannot suspend or we lose our non-preemptive + * state!). Once the driver is successfully unregistered, we can assume + * we have exclusive access to the state instance. + */ + + ret = unregister_driver(chardev); + if (ret < 0) + { + goto errout_with_lock; + } + + sched_unlock(); + + /* Release the internal structure */ + + bch->refs = 0; + return bchlib_teardown(bch); + +errout_with_lock: + bch->refs--; + sched_unlock(); + return ret; +} diff --git a/nuttx/drivers/bch/bchlib_cache.c b/nuttx/drivers/bch/bchlib_cache.c new file mode 100644 index 0000000000..3b8212a13f --- /dev/null +++ b/nuttx/drivers/bch/bchlib_cache.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * drivers/bch/bchlib_cache.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "bch_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bchlib_flushsector + * + * Description: + * Flush the current contents of the sector buffer (if dirty) + * + * Assumptions: + * Caller must assume mutual exclusion + * + ****************************************************************************/ + +int bchlib_flushsector(FAR struct bchlib_s *bch) +{ + FAR struct inode *inode; + ssize_t ret = OK; + + if (bch->dirty) + { + inode = bch->inode; + ret = inode->u.i_bops->write(inode, bch->buffer, bch->sector, 1); + if (ret < 0) + { + fdbg("Write failed: %d\n"); + } + bch->dirty = false; + } + return (int)ret; +} + +/**************************************************************************** + * Name: bchlib_readsector + * + * Description: + * Flush the current contents of the sector buffer (if dirty) + * + * Assumptions: + * Caller must assume mutual exclusion + * + ****************************************************************************/ + +int bchlib_readsector(FAR struct bchlib_s *bch, size_t sector) +{ + FAR struct inode *inode; + ssize_t ret = OK; + + if (bch->sector != sector) + { + inode = bch->inode; + + (void)bchlib_flushsector(bch); + bch->sector = (size_t)-1; + + ret = inode->u.i_bops->read(inode, bch->buffer, sector, 1); + if (ret < 0) + { + fdbg("Read failed: %d\n"); + } + bch->sector = sector; + } + return (int)ret; +} + diff --git a/nuttx/drivers/bch/bchlib_read.c b/nuttx/drivers/bch/bchlib_read.c new file mode 100644 index 0000000000..f4fad10969 --- /dev/null +++ b/nuttx/drivers/bch/bchlib_read.c @@ -0,0 +1,203 @@ +/**************************************************************************** + * drivers/bch/bchlib_read.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "bch_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bchlib_read + * + * Description: + * Read from the block device set-up by bchlib_setup as if it were a character + * device. + * + ****************************************************************************/ + +ssize_t bchlib_read(FAR void *handle, FAR char *buffer, size_t offset, size_t len) +{ + FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle; + size_t nsectors; + size_t sector; + uint16_t sectoffset; + size_t nbytes; + size_t bytesread; + int ret; + + /* Get rid of this special case right away */ + + if (len < 1) + { + return 0; + } + + /* Convert the file position into a sector number an offset. */ + + sector = offset / bch->sectsize; + sectoffset = offset - sector * bch->sectsize; + + if (sector >= bch->nsectors) + { + /* Return end-of-file */ + + return 0; + } + + /* Read the initial partial sector */ + + bytesread = 0; + if (sectoffset > 0) + { + /* Read the sector into the sector buffer */ + + bchlib_readsector(bch, sector); + + /* Copy the tail end of the sector to the user buffer */ + + if (sectoffset + len > bch->sectsize) + { + nbytes = bch->sectsize - sectoffset; + } + else + { + nbytes = len; + } + + memcpy(buffer, &bch->buffer[sectoffset], nbytes); + + /* Adjust pointers and counts */ + + sectoffset = 0; + sector++; + + if (sector >= bch->nsectors) + { + return nbytes; + } + + bytesread = nbytes; + buffer += nbytes; + len -= nbytes; + } + + /* Then read all of the full sectors following the partial sector directly + * into the user buffer. + */ + + if (len >= bch->sectsize ) + { + nsectors = len / bch->sectsize; + if (sector + nsectors > bch->nsectors) + { + nsectors = bch->nsectors - sector; + } + + ret = bch->inode->u.i_bops->read(bch->inode, (FAR uint8_t *)buffer, + sector, nsectors); + if (ret < 0) + { + fdbg("Read failed: %d\n"); + return ret; + } + + /* Adjust pointers and counts */ + + sectoffset = 0; + sector += nsectors; + + nbytes = nsectors * bch->sectsize; + bytesread += nbytes; + + if (sector >= bch->nsectors) + { + return bytesread; + } + + buffer += nbytes; + len -= nbytes; + } + + /* Then read any partial final sector */ + + if (len > 0) + { + /* Read the sector into the sector buffer */ + + bchlib_readsector(bch, sector); + + /* Copy the head end of the sector to the user buffer */ + + memcpy(buffer, bch->buffer, len); + + /* Adjust counts */ + + bytesread += len; + } + + return bytesread; +} diff --git a/nuttx/drivers/bch/bchlib_sem.c b/nuttx/drivers/bch/bchlib_sem.c new file mode 100644 index 0000000000..1698ed0a54 --- /dev/null +++ b/nuttx/drivers/bch/bchlib_sem.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * drivers/bch/bchlib_sem.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "bch_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bch_semtake + ****************************************************************************/ + +void bchlib_semtake(FAR struct bchlib_s *bch) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&bch->sem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} diff --git a/nuttx/drivers/bch/bchlib_setup.c b/nuttx/drivers/bch/bchlib_setup.c new file mode 100644 index 0000000000..1026248b5a --- /dev/null +++ b/nuttx/drivers/bch/bchlib_setup.c @@ -0,0 +1,159 @@ +/**************************************************************************** + * drivers/bch/bchlib_setup.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bch_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bchlib_setup + * + * Description: + * Setup so that the block driver referenced by 'blkdev' can be accessed + * similar to a character device. + * + ****************************************************************************/ + +int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle) +{ + FAR struct bchlib_s *bch; + struct geometry geo; + int ret; + + DEBUGASSERT(blkdev); + + /* Allocate the BCH state structure */ + + bch = (FAR struct bchlib_s*)kzalloc(sizeof(struct bchlib_s)); + if (!bch) + { + fdbg("Failed to allocate BCH structure\n"); + return -ENOMEM; + } + + /* Open the block driver */ + + ret = open_blockdriver(blkdev, readonly ? MS_RDONLY : 0, &bch->inode); + if (ret < 0) + { + fdbg("Failed to open driver %s: %d\n", blkdev, -ret); + goto errout_with_bch; + } + + DEBUGASSERT(bch->inode && bch->inode->u.i_bops && bch->inode->u.i_bops->geometry); + + ret = bch->inode->u.i_bops->geometry(bch->inode, &geo); + if (ret < 0) + { + fdbg("geometry failed: %d\n", -ret); + goto errout_with_bch; + } + + if (!geo.geo_available) + { + fdbg("geometry failed: %d\n", -ret); + ret = -ENODEV; + goto errout_with_bch; + } + + if (!readonly && (!bch->inode->u.i_bops->write || !geo.geo_writeenabled)) + { + fdbg("write access not supported\n"); + ret = -EACCES; + goto errout_with_bch; + } + + /* Save the geometry info and complete initialization of the structure */ + + sem_init(&bch->sem, 0, 1); + bch->nsectors = geo.geo_nsectors; + bch->sectsize = geo.geo_sectorsize; + bch->sector = (size_t)-1; + bch->readonly = readonly; + + /* Allocate the sector I/O buffer */ + + bch->buffer = (FAR uint8_t *)kmalloc(bch->sectsize); + if (!bch->buffer) + { + fdbg("Failed to allocate sector buffer\n"); + ret = -ENOMEM; + goto errout_with_bch; + } + + *handle = bch; + return OK; + +errout_with_bch: + kfree(bch); + return ret; +} diff --git a/nuttx/drivers/bch/bchlib_teardown.c b/nuttx/drivers/bch/bchlib_teardown.c new file mode 100644 index 0000000000..8657c4a697 --- /dev/null +++ b/nuttx/drivers/bch/bchlib_teardown.c @@ -0,0 +1,113 @@ +/**************************************************************************** + * drivers/bch/bchlib_teardown.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "bch_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bchlib_teardown + * + * Description: + * Setup so that the block driver referenced by 'blkdev' can be accessed + * similar to a character device. + * + ****************************************************************************/ + +int bchlib_teardown(FAR void *handle) +{ + FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle; + + DEBUGASSERT(handle); + + /* Check that there are not outstanding reference counts on the object */ + + if (bch->refs > 0) + { + return -EBUSY; + } + + /* Flush any pending data to the block driver */ + + bchlib_flushsector(bch); + + /* Close the block driver */ + + (void)close_blockdriver(bch->inode); + + /* Free the BCH state structure */ + + if (bch->buffer) + { + kfree(bch->buffer); + } + + sem_destroy(&bch->sem); + kfree(bch); + return OK; +} + diff --git a/nuttx/drivers/bch/bchlib_write.c b/nuttx/drivers/bch/bchlib_write.c new file mode 100644 index 0000000000..8d7dcf26f9 --- /dev/null +++ b/nuttx/drivers/bch/bchlib_write.c @@ -0,0 +1,216 @@ +/**************************************************************************** + * drivers/bch/bchlib_write.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "bch_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bchlib_write + * + * Description: + * Write to the block device set-up by bchlib_setup as if it were a character + * device. + * + ****************************************************************************/ + +ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, size_t offset, size_t len) +{ + FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle; + size_t nsectors; + size_t sector; + uint16_t sectoffset; + size_t nbytes; + size_t byteswritten; + int ret; + + /* Get rid of this special case right away */ + + if (len < 1) + { + return 0; + } + + /* Convert the file position into a sector number an offset. */ + + sector = offset / bch->sectsize; + sectoffset = offset - sector * bch->sectsize; + + if (sector >= bch->nsectors) + { + return -EFBIG; + } + + /* Write the initial partial sector */ + + byteswritten = 0; + if (sectoffset > 0) + { + /* Read the full sector into the sector buffer */ + + bchlib_readsector(bch, sector); + + /* Copy the tail end of the sector from the user buffer */ + + if (sectoffset + len > bch->sectsize) + { + nbytes = bch->sectsize - sectoffset; + } + else + { + nbytes = len; + } + + memcpy(&bch->buffer[sectoffset], buffer, nbytes); + bch->dirty = true; + + /* Adjust pointers and counts */ + + sectoffset = 0; + sector++; + + if (sector >= bch->nsectors) + { + return nbytes; + } + + byteswritten = nbytes; + buffer += nbytes; + len -= nbytes; + } + + /* Then write all of the full sectors following the partial sector + * directly from the user buffer. + */ + + if (len >= bch->sectsize ) + { + nsectors = len / bch->sectsize; + if (sector + nsectors > bch->nsectors) + { + nsectors = bch->nsectors - sector; + } + + /* Write the contiguous sectors */ + + ret = bch->inode->u.i_bops->write(bch->inode, (FAR uint8_t *)buffer, + sector, nsectors); + if (ret < 0) + { + fdbg("Write failed: %d\n", ret); + return ret; + } + + /* Adjust pointers and counts */ + + sectoffset = 0; + sector += nsectors; + + nbytes = nsectors * bch->sectsize; + byteswritten += nbytes; + + if (sector >= bch->nsectors) + { + return byteswritten; + } + + buffer += nbytes; + len -= nbytes; + } + + /* Then write any partial final sector */ + + if (len > 0) + { + /* Read the sector into the sector buffer */ + + bchlib_readsector(bch, sector); + + /* Copy the head end of the sector from the user buffer */ + + memcpy(bch->buffer, buffer, len); + bch->dirty = true; + + /* Adjust counts */ + + byteswritten += len; + } + + /* Finally, flush any cached writes to the device as well */ + + ret = bchlib_flushsector(bch); + if (ret < 0) + { + fdbg("Flush failed: %d\n", ret); + return ret; + } + + return byteswritten; +} + diff --git a/nuttx/drivers/can.c b/nuttx/drivers/can.c new file mode 100644 index 0000000000..2c15677812 --- /dev/null +++ b/nuttx/drivers/can.c @@ -0,0 +1,845 @@ +/**************************************************************************** + * drivers/can.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#ifdef CONFIG_CAN + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Debug ********************************************************************/ +/* Non-standard debug that may be enabled just for testing CAN */ + +#ifdef CONFIG_DEBUG_CAN +# define candbg dbg +# define canvdbg vdbg +# define canlldbg lldbg +# define canllvdbg llvdbg +#else +# define candbg(x...) +# define canvdbg(x...) +# define canlldbg(x...) +# define canllvdbg(x...) +#endif + +/* Timing Definitions *******************************************************/ + +#define HALF_SECOND_MSEC 500 +#define HALF_SECOND_USEC 500000L + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int can_open(FAR struct file *filep); +static int can_close(FAR struct file *filep); +static ssize_t can_read(FAR struct file *filep, FAR char *buffer, size_t buflen); +static int can_xmit(FAR struct can_dev_s *dev); +static ssize_t can_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); +static inline ssize_t can_rtrread(FAR struct can_dev_s *dev, FAR struct canioctl_rtr_s *rtr); +static int can_ioctl(FAR struct file *filep, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_canops = +{ + can_open, /* open */ + can_close, /* close */ + can_read, /* read */ + can_write, /* write */ + 0, /* seek */ + can_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , 0 /* poll */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/************************************************************************************ + * Name: can_open + * + * Description: + * This function is called whenever the CAN device is opened. + * + ************************************************************************************/ + +static int can_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct can_dev_s *dev = inode->i_private; + uint8_t tmp; + int ret = OK; + + canvdbg("ocount: %d\n", dev->cd_ocount); + + /* If the port is the middle of closing, wait until the close is finished */ + + if (sem_wait(&dev->cd_closesem) != OK) + { + ret = -errno; + } + else + { + /* Increment the count of references to the device. If this the first + * time that the driver has been opened for this device, then initialize + * the device. + */ + + tmp = dev->cd_ocount + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + } + else + { + /* Check if this is the first time that the driver has been opened. */ + + if (tmp == 1) + { + /* Yes.. perform one time hardware initialization. */ + + irqstate_t flags = irqsave(); + ret = dev_setup(dev); + if (ret == OK) + { + /* Mark the FIFOs empty */ + + dev->cd_xmit.tx_head = 0; + dev->cd_xmit.tx_queue = 0; + dev->cd_xmit.tx_tail = 0; + dev->cd_recv.rx_head = 0; + dev->cd_recv.rx_tail = 0; + + /* Finally, Enable the CAN RX interrupt */ + + dev_rxint(dev, true); + + /* Save the new open count on success */ + + dev->cd_ocount = tmp; + } + irqrestore(flags); + } + } + sem_post(&dev->cd_closesem); + } + return ret; +} + +/************************************************************************************ + * Name: can_close + * + * Description: + * This routine is called when the CAN device is closed. + * It waits for the last remaining data to be sent. + * + ************************************************************************************/ + +static int can_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct can_dev_s *dev = inode->i_private; + irqstate_t flags; + int ret = OK; + + canvdbg("ocount: %d\n", dev->cd_ocount); + + if (sem_wait(&dev->cd_closesem) != OK) + { + ret = -errno; + } + else + { + /* Decrement the references to the driver. If the reference count will + * decrement to 0, then uninitialize the driver. + */ + + if (dev->cd_ocount > 1) + { + dev->cd_ocount--; + sem_post(&dev->cd_closesem); + } + else + { + /* There are no more references to the port */ + + dev->cd_ocount = 0; + + /* Stop accepting input */ + + dev_rxint(dev, false); + + /* Now we wait for the transmit FIFO to clear */ + + while (dev->cd_xmit.tx_head != dev->cd_xmit.tx_tail) + { +#ifndef CONFIG_DISABLE_SIGNALS + usleep(HALF_SECOND_USEC); +#else + up_mdelay(HALF_SECOND_MSEC); +#endif + } + + /* And wait for the TX hardware FIFO to drain */ + + while (!dev_txempty(dev)) + { +#ifndef CONFIG_DISABLE_SIGNALS + usleep(HALF_SECOND_USEC); +#else + up_mdelay(HALF_SECOND_MSEC); +#endif + } + + /* Free the IRQ and disable the CAN device */ + + flags = irqsave(); /* Disable interrupts */ + dev_shutdown(dev); /* Disable the CAN */ + irqrestore(flags); + + sem_post(&dev->cd_closesem); + } + } + return ret; +} + +/************************************************************************************ + * Name: can_read + * + * Description: + * Read standard CAN messages + * + ************************************************************************************/ + +static ssize_t can_read(FAR struct file *filep, FAR char *buffer, size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct can_dev_s *dev = inode->i_private; + size_t nread; + irqstate_t flags; + int ret = 0; + + canvdbg("buflen: %d\n", buflen); + + /* The caller must provide enough memory to catch the smallest possible message + * This is not a system error condition, but we won't permit it, Hence we return 0. + */ + + if (buflen >= CAN_MSGLEN(0)) + { + /* Interrupts must be disabled while accessing the cd_recv FIFO */ + + flags = irqsave(); + while (dev->cd_recv.rx_head == dev->cd_recv.rx_tail) + { + /* The receive FIFO is empty -- was non-blocking mode selected? */ + + if (filep->f_oflags & O_NONBLOCK) + { + ret = -EAGAIN; + goto return_with_irqdisabled; + } + + /* Wait for a message to be received */ + + ret = sem_wait(&dev->cd_recv.rx_sem); + if (ret < 0) + { + ret = -errno; + goto return_with_irqdisabled; + } + } + + /* The cd_recv FIFO is not empty. Copy all buffered data that will fit + * in the user buffer. + */ + + nread = 0; + do + { + /* Will the next message in the FIFO fit into the user buffer? */ + + FAR struct can_msg_s *msg = &dev->cd_recv.rx_buffer[dev->cd_recv.rx_head]; + int msglen = CAN_MSGLEN(msg->cm_hdr.ch_dlc); + + if (nread + msglen > buflen) + { + break; + } + + /* Copy the message to the user buffer */ + + memcpy(&buffer[nread], msg, msglen); + nread += msglen; + + /* Increment the head of the circular message buffer */ + + if (++dev->cd_recv.rx_head >= CONFIG_CAN_FIFOSIZE) + { + dev->cd_recv.rx_head = 0; + } + } + while (dev->cd_recv.rx_head != dev->cd_recv.rx_tail); + + /* All on the messages have bee transferred. Return the number of bytes + * that were read. + */ + + ret = nread; + +return_with_irqdisabled: + irqrestore(flags); + } + return ret; +} + +/************************************************************************************ + * Name: can_xmit + * + * Description: + * Send the message at the head of the cd_xmit FIFO + * + * Assumptions: + * Called with interrupts disabled + * + ************************************************************************************/ + +static int can_xmit(FAR struct can_dev_s *dev) +{ + int tmpndx; + int ret = -EBUSY; + + canllvdbg("xmit head: %d queue: %d tail: %d\n", + dev->cd_xmit.tx_head, dev->cd_xmit.tx_queue, dev->cd_xmit.tx_tail); + + /* If there is nothing to send, then just disable interrupts and return */ + + if (dev->cd_xmit.tx_head == dev->cd_xmit.tx_tail) + { + DEBUGASSERT(dev->cd_xmit.tx_queue == dev->cd_xmit.tx_head); + dev_txint(dev, false); + return -EIO; + } + + /* Check if we have already queued all of the data in the TX fifo. + * + * tx_tail: Incremented in can_write each time a message is queued in the FIFO + * tx_head: Incremented in can_txdone each time a message completes + * tx_queue: Incremented each time that a message is sent to the hardware. + * + * Logically (ignoring buffer wrap-around): tx_head <= tx_queue <= tx_tail + * tx_head == tx_queue == tx_tail means that the FIFO is empty + * tx_head < tx_queue == tx_tail means that all data has been queued, but + * we are still waiting for transmissions to complete. + */ + + while (dev->cd_xmit.tx_queue != dev->cd_xmit.tx_tail && dev_txready(dev)) + { + /* No.. The fifo should not be empty in this case */ + + DEBUGASSERT(dev->cd_xmit.tx_head != dev->cd_xmit.tx_tail); + + /* Increment the FIFO queue index before sending (because dev_send() + * might call can_txdone(). + */ + + tmpndx = dev->cd_xmit.tx_queue; + if (++dev->cd_xmit.tx_queue >= CONFIG_CAN_FIFOSIZE) + { + dev->cd_xmit.tx_queue = 0; + } + + /* Send the next message at the FIFO queue index */ + + ret = dev_send(dev, &dev->cd_xmit.tx_buffer[tmpndx]); + if (ret != OK) + { + candbg("dev_send failed: %d\n", ret); + break; + } + } + + /* Make sure that TX interrupts are enabled */ + + dev_txint(dev, true); + return ret; +} + +/************************************************************************************ + * Name: can_write + ************************************************************************************/ + +static ssize_t can_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct can_dev_s *dev = inode->i_private; + FAR struct can_txfifo_s *fifo = &dev->cd_xmit; + FAR struct can_msg_s *msg; + bool inactive; + ssize_t nsent = 0; + irqstate_t flags; + int nexttail; + int msglen; + int ret = 0; + + canvdbg("buflen: %d\n", buflen); + + /* Interrupts must disabled throughout the following */ + + flags = irqsave(); + + /* Check if the TX is inactive when we started. In certain race conditionas, there + * may be a pending interrupt to kick things back off, but we will here that there + * is not. That the hardware is IDLE and will need to be kick-started. + */ + + inactive = dev_txempty(dev); + + /* Add the messages to the FIFO. Ignore any trailing messages that are + * shorter than the minimum. + */ + + while ((buflen - nsent) >= CAN_MSGLEN(0)) + { + /* Check if adding this new message would over-run the drivers ability to enqueue + * xmit data. + */ + + nexttail = fifo->tx_tail + 1; + if (nexttail >= CONFIG_CAN_FIFOSIZE) + { + nexttail = 0; + } + + /* If the XMIT fifo becomes full, then wait for space to become available */ + + while (nexttail == fifo->tx_head) + { + /* The transmit FIFO is full -- was non-blocking mode selected? */ + + if (filep->f_oflags & O_NONBLOCK) + { + if (nsent == 0) + { + ret = -EAGAIN; + } + else + { + ret = nsent; + } + goto return_with_irqdisabled; + } + + /* If the TX hardware was inactive when we started, then we will have + * start the XMIT sequence generate the TX done interrrupts needed + * to clear the FIFO. + */ + + if (inactive) + { + can_xmit(dev); + } + + /* Wait for a message to be sent */ + + do + { + DEBUGASSERT(dev->cd_ntxwaiters < 255); + dev->cd_ntxwaiters++; + ret = sem_wait(&fifo->tx_sem); + dev->cd_ntxwaiters--; + + if (ret < 0 && errno != EINTR) + { + ret = -errno; + goto return_with_irqdisabled; + } + } + while (ret < 0); + + /* Re-check the FIFO state */ + + inactive = dev_txempty(dev); + } + + /* We get here if there is space at the end of the FIFO. Add the new + * CAN message at the tail of the FIFO. + */ + + msg = (FAR struct can_msg_s *)&buffer[nsent]; + msglen = CAN_MSGLEN(msg->cm_hdr.ch_dlc); + memcpy(&fifo->tx_buffer[fifo->tx_tail], msg, msglen); + + /* Increment the tail of the circular buffer */ + + fifo->tx_tail = nexttail; + + /* Increment the number of bytes that were sent */ + + nsent += msglen; + } + + /* We get here after all messages have been added to the FIFO. Check if + * we need to kick of the XMIT sequence. + */ + + if (inactive) + { + can_xmit(dev); + } + + /* Return the number of bytes that were sent */ + + ret = nsent; + +return_with_irqdisabled: + irqrestore(flags); + return ret; +} + +/************************************************************************************ + * Name: can_rtrread + * + * Description: + * Read RTR messages. The RTR message is a special message -- it is an outgoing + * message that says "Please re-transmit the message with the same identifier as + * this message. So the RTR read is really a send-wait-receive operation. + * + ************************************************************************************/ + +static inline ssize_t can_rtrread(FAR struct can_dev_s *dev, FAR struct canioctl_rtr_s *rtr) +{ + FAR struct can_rtrwait_s *wait = NULL; + irqstate_t flags; + int i; + int ret = -ENOMEM; + + /* Disable interrupts through this operation */ + + flags = irqsave(); + + /* Find an avaiable slot in the pending RTR list */ + + for (i = 0; i < CONFIG_CAN_NPENDINGRTR; i++) + { + FAR struct can_rtrwait_s *tmp = &dev->cd_rtr[i]; + if (!rtr->ci_msg) + { + tmp->cr_id = rtr->ci_id; + tmp->cr_msg = rtr->ci_msg; + dev->cd_npendrtr++; + wait = tmp; + break; + } + } + + if (wait) + { + /* Send the remote transmission request */ + + ret = dev_remoterequest(dev, wait->cr_id); + if (ret == OK) + { + /* Then wait for the response */ + + ret = sem_wait(&wait->cr_sem); + } + } + irqrestore(flags); + return ret; +} + +/************************************************************************************ + * Name: can_ioctl + ************************************************************************************/ + +static int can_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct can_dev_s *dev = inode->i_private; + int ret = OK; + + canvdbg("cmd: %d arg: %ld\n", cmd, arg); + + /* Handle built-in ioctl commands */ + + switch (cmd) + { + /* CANIOCTL_RTR: Send the remote transmission request and wait for the response. + * Argument is a reference to struct canioctl_rtr_s (casting to uintptr_t first + * eliminates complaints on some architectures where the sizeof long is different + * from the size of a pointer). + */ + + case CANIOCTL_RTR: + ret = can_rtrread(dev, (struct canioctl_rtr_s*)((uintptr_t)arg)); + break; + + /* Not a "built-in" ioctl command.. perhaps it is unique to this device driver */ + + default: + ret = dev_ioctl(dev, cmd, arg); + break; + } + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/************************************************************************************ + * Name: can_register + * + * Description: + * Register serial console and serial ports. + * + ************************************************************************************/ + +int can_register(FAR const char *path, FAR struct can_dev_s *dev) +{ + int i; + + /* Initialize the CAN device structure */ + + dev->cd_ocount = 0; + + sem_init(&dev->cd_xmit.tx_sem, 0, 0); + sem_init(&dev->cd_recv.rx_sem, 0, 0); + sem_init(&dev->cd_closesem, 0, 1); + + for (i = 0; i < CONFIG_CAN_NPENDINGRTR; i++) + { + sem_init(&dev->cd_rtr[i].cr_sem, 0, 0); + dev->cd_rtr[i].cr_msg = NULL; + dev->cd_npendrtr--; + } + + /* Initialize/reset the CAN hardware */ + + dev_reset(dev); + + /* Register the CAN device */ + + canvdbg("Registering %s\n", path); + return register_driver(path, &g_canops, 0666, dev); +} + +/************************************************************************************ + * Name: can_receive + * + * Description: + * Called from the CAN interrupt handler when new read data is available + * + * Parameters: + * dev - CAN driver state structure + * hdr - CAN message header + * data - CAN message data (if DLC > 0) + * + * Assumptions: + * CAN interrupts are disabled. + * + ************************************************************************************/ + +int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr, FAR uint8_t *data) +{ + FAR struct can_rxfifo_s *fifo = &dev->cd_recv; + FAR uint8_t *dest; + int nexttail; + int err = -ENOMEM; + int i; + + canllvdbg("ID: %d DLC: %d\n", hdr->ch_id, hdr->ch_dlc); + + /* Check if adding this new message would over-run the drivers ability to enqueue + * read data. + */ + + nexttail = fifo->rx_tail + 1; + if (nexttail >= CONFIG_CAN_FIFOSIZE) + { + nexttail = 0; + } + + /* First, check if this response matches any RTR response that we may be waiting for */ + + if (dev->cd_npendrtr > 0) + { + /* There are pending RTR requests -- search the lists of requests + * and see any any matches this new message. + */ + + for (i = 0; i < CONFIG_CAN_NPENDINGRTR; i++) + { + FAR struct can_rtrwait_s *rtr = &dev->cd_rtr[i]; + FAR struct can_msg_s *msg = rtr->cr_msg; + + /* Check if the entry is valid and if the ID matches. A valid entry has + * a non-NULL receiving address + */ + + if (msg && hdr->ch_id == rtr->cr_id) + { + /* We have the response... copy the data to the user's buffer */ + + memcpy(&msg->cm_hdr, hdr, sizeof(struct can_hdr_s)); + for (i = 0, dest = msg->cm_data; i < hdr->ch_dlc; i++) + { + *dest++ = *data++; + } + + /* Mark the entry unused */ + + rtr->cr_msg = NULL; + + /* And restart the waiting thread */ + + sem_post(&rtr->cr_sem); + } + } + } + + /* Refuse the new data if the FIFO is full */ + + if (nexttail != fifo->rx_head) + { + /* Add the new, decoded CAN message at the tail of the FIFO */ + + memcpy(&fifo->rx_buffer[fifo->rx_tail].cm_hdr, hdr, sizeof(struct can_hdr_s)); + for (i = 0, dest = fifo->rx_buffer[fifo->rx_tail].cm_data; i < hdr->ch_dlc; i++) + { + *dest++ = *data++; + } + + /* Increment the tail of the circular buffer */ + + fifo->rx_tail = nexttail; + + /* The increment the counting semaphore. The maximum value should be + * CONFIG_CAN_FIFOSIZE -- one possible count for each allocated message buffer. + */ + + sem_post(&fifo->rx_sem); + err = OK; + } + return err; +} + +/************************************************************************************ + * Name: can_txdone + * + * Description: + * Called from the CAN interrupt handler at the completion of a send operation. + * + * Parameters: + * dev - The specific CAN device + * hdr - The 16-bit CAN header + * data - An array contain the CAN data. + * + * Return: + * OK on success; a negated errno on failure. + * + ************************************************************************************/ + +int can_txdone(FAR struct can_dev_s *dev) +{ + int ret = -ENOENT; + + canllvdbg("xmit head: %d queue: %d tail: %d\n", + dev->cd_xmit.tx_head, dev->cd_xmit.tx_queue, dev->cd_xmit.tx_tail); + + /* Verify that the xmit FIFO is not empty */ + + if (dev->cd_xmit.tx_head != dev->cd_xmit.tx_tail) + { + DEBUGASSERT(dev->cd_xmit.tx_head != dev->cd_xmit.tx_queue); + + /* Remove the message at the head of the xmit FIFO */ + + if (++dev->cd_xmit.tx_head >= CONFIG_CAN_FIFOSIZE) + { + dev->cd_xmit.tx_head = 0; + } + + /* Send the next message in the FIFO */ + + ret = can_xmit(dev); + + /* Are there any threads waiting for space in the TX FIFO? */ + + if (ret == OK && dev->cd_ntxwaiters > 0) + { + /* Yes.. Inform them that new xmit space is available */ + + ret = sem_post(&dev->cd_xmit.tx_sem); + } + } + return ret; +} + +#endif /* CONFIG_CAN */ diff --git a/nuttx/drivers/dev_null.c b/nuttx/drivers/dev_null.c new file mode 100644 index 0000000000..c70370e1e5 --- /dev/null +++ b/nuttx/drivers/dev_null.c @@ -0,0 +1,135 @@ +/**************************************************************************** + * drivers/dev_null.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static ssize_t devnull_read(FAR struct file *, FAR char *, size_t); +static ssize_t devnull_write(FAR struct file *, FAR const char *, size_t); +#ifndef CONFIG_DISABLE_POLL +static int devnull_poll(FAR struct file *filp, FAR struct pollfd *fds, + bool setup); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations devnull_fops = +{ + 0, /* open */ + 0, /* close */ + devnull_read, /* read */ + devnull_write, /* write */ + 0, /* seek */ + 0 /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , devnull_poll /* poll */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: devnull_read + ****************************************************************************/ + +static ssize_t devnull_read(FAR struct file *filp, FAR char *buffer, size_t len) +{ + return 0; /* Return EOF */ +} + +/**************************************************************************** + * Name: devnull_write + ****************************************************************************/ + +static ssize_t devnull_write(FAR struct file *filp, FAR const char *buffer, size_t len) +{ + return len; /* Say that everything was written */ +} + +/**************************************************************************** + * Name: devnull_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static int devnull_poll(FAR struct file *filp, FAR struct pollfd *fds, + bool setup) +{ + if (setup) + { + fds->revents |= (fds->events & (POLLIN|POLLOUT)); + if (fds->revents != 0) + { + sem_post(fds->sem); + } + } + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: devnull_register + * + * Description: + * Register /dev/null + * + ****************************************************************************/ + +void devnull_register(void) +{ + (void)register_driver("/dev/null", &devnull_fops, 0666, NULL); +} diff --git a/nuttx/drivers/dev_zero.c b/nuttx/drivers/dev_zero.c new file mode 100644 index 0000000000..5435f80ea2 --- /dev/null +++ b/nuttx/drivers/dev_zero.c @@ -0,0 +1,135 @@ +/**************************************************************************** + * drivers/dev_null.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static ssize_t devzero_read(FAR struct file *, FAR char *, size_t); +static ssize_t devzero_write(FAR struct file *, FAR const char *, size_t); +#ifndef CONFIG_DISABLE_POLL +static int devzero_poll(FAR struct file *filp, FAR struct pollfd *fds, + bool setup); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations devzero_fops = +{ + 0, /* open */ + 0, /* close */ + devzero_read, /* read */ + devzero_write, /* write */ + 0, /* seek */ + 0 /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , devzero_poll /* poll */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: devzero_read + ****************************************************************************/ + +static ssize_t devzero_read(FAR struct file *filp, FAR char *buffer, size_t len) +{ + memset(buffer, 0, len); + return len; +} + +/**************************************************************************** + * Name: devzero_write + ****************************************************************************/ + +static ssize_t devzero_write(FAR struct file *filp, FAR const char *buffer, size_t len) +{ + return len; +} + +/**************************************************************************** + * Name: devzero_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static int devzero_poll(FAR struct file *filp, FAR struct pollfd *fds, + bool setup) +{ + if (setup) + { + fds->revents |= (fds->events & (POLLIN|POLLOUT)); + if (fds->revents != 0) + { + sem_post(fds->sem); + } + } + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: devzero_register + * + * Description: + * Register /dev/zero + * + ****************************************************************************/ + +void devzero_register(void) +{ + (void)register_driver("/dev/zero", &devzero_fops, 0666, NULL); +} diff --git a/nuttx/drivers/input/Kconfig b/nuttx/drivers/input/Kconfig new file mode 100644 index 0000000000..1303cfbd0f --- /dev/null +++ b/nuttx/drivers/input/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# +config INPUT_TSC2007 + bool "TI TSC2007 touchscreen controller" + default n + select I2C + +config INPUT_ADS7843E + bool "TI ADS7843E touchscreen controller" + default n + select SPI diff --git a/nuttx/drivers/input/Make.defs b/nuttx/drivers/input/Make.defs new file mode 100644 index 0000000000..aaf08b8270 --- /dev/null +++ b/nuttx/drivers/input/Make.defs @@ -0,0 +1,72 @@ +############################################################################ +# drivers/input/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Don't build anything if there is no NX support for input devices + +ifeq ($(CONFIG_INPUT),y) + +# Include the selected touchscreen drivers + +ifeq ($(CONFIG_INPUT_TSC2007),y) + CSRCS += tsc2007.c +endif + +ifeq ($(CONFIG_INPUT_ADS7843E),y) + CSRCS += ads7843e.c +endif + +ifeq ($(CONFIG_INPUT_STMPE811),y) + CSRCS += stmpe811_base.c +ifneq ($(CONFIG_INPUT_STMPE811_TSC_DISABLE),y) + CSRCS += stmpe811_tsc.c +endif +ifneq ($(CONFIG_INPUT_STMPE811_GPIO_DISABLE),y) + CSRCS += stmpe811_gpio.c +endif +ifneq ($(CONFIG_INPUT_STMPE811_ADC_DISABLE),y) + CSRCS += stmpe811_adc.c +endif +ifneq ($(CONFIG_INPUT_STMPE811_TEMP_DISABLE),y) + CSRCS += stmpe811_temp.c +endif +endif + +# Include input device driver build support + +DEPPATH += --dep-path input +VPATH += :input +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/input} +endif + diff --git a/nuttx/drivers/input/ads7843e.c b/nuttx/drivers/input/ads7843e.c new file mode 100644 index 0000000000..750b91ff2e --- /dev/null +++ b/nuttx/drivers/input/ads7843e.c @@ -0,0 +1,1199 @@ +/**************************************************************************** + * drivers/input/ads7843e.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * Diego Sanchez + * + * References: + * "Touch Screen Controller, ADS7843," Burr-Brown Products from Texas + * Instruments, SBAS090B, September 2000, Revised May 2002" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "ads7843e.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* Low-level SPI helpers */ + +static inline void ads7843e_configspi(FAR struct spi_dev_s *spi); +#ifdef CONFIG_SPI_OWNBUS +static inline void ads7843e_select(FAR struct spi_dev_s *spi); +static inline void ads7843e_deselect(FAR struct spi_dev_s *spi); +#else +static void ads7843e_select(FAR struct spi_dev_s *spi); +static void ads7843e_deselect(FAR struct spi_dev_s *spi); +#endif + +static inline void ads7843e_waitbusy(FAR struct ads7843e_dev_s *priv); +static uint16_t ads7843e_sendcmd(FAR struct ads7843e_dev_s *priv, uint8_t cmd); + +/* Interrupts and data sampling */ + +static void ads7843e_notify(FAR struct ads7843e_dev_s *priv); +static int ads7843e_sample(FAR struct ads7843e_dev_s *priv, + FAR struct ads7843e_sample_s *sample); +static int ads7843e_waitsample(FAR struct ads7843e_dev_s *priv, + FAR struct ads7843e_sample_s *sample); +static void ads7843e_worker(FAR void *arg); +static int ads7843e_interrupt(int irq, FAR void *context); + +/* Character driver methods */ + +static int ads7843e_open(FAR struct file *filep); +static int ads7843e_close(FAR struct file *filep); +static ssize_t ads7843e_read(FAR struct file *filep, FAR char *buffer, size_t len); +static int ads7843e_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +#ifndef CONFIG_DISABLE_POLL +static int ads7843e_poll(FAR struct file *filep, struct pollfd *fds, bool setup); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This the the vtable that supports the character driver interface */ + +static const struct file_operations ads7843e_fops = +{ + ads7843e_open, /* open */ + ads7843e_close, /* close */ + ads7843e_read, /* read */ + 0, /* write */ + 0, /* seek */ + ads7843e_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , ads7843e_poll /* poll */ +#endif +}; + +/* If only a single ADS7843E device is supported, then the driver state + * structure may as well be pre-allocated. + */ + +#ifndef CONFIG_ADS7843E_MULTIPLE +static struct ads7843e_dev_s g_ads7843e; + +/* Otherwise, we will need to maintain allocated driver instances in a list */ + +#else +static struct ads7843e_dev_s *g_ads7843elist; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: ads7843e_select + * + * Description: + * Select the SPI, locking and re-configuring if necessary. This function + * must be called before initiating any sequence of SPI operations. If we + * are sharing the SPI bus with other devices (CONFIG_SPI_OWNBUS undefined) + * then we need to lock and configure the SPI bus for each transfer. + * + * Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_OWNBUS +static inline void ads7843e_select(FAR struct spi_dev_s *spi) +{ + /* We own the SPI bus, so just select the chip */ + + SPI_SELECT(spi, SPIDEV_TOUCHSCREEN, true); +} +#else +static void ads7843e_select(FAR struct spi_dev_s *spi) +{ + /* Select ADS7843 chip (locking the SPI bus in case there are multiple + * devices competing for the SPI bus + */ + + (void)SPI_LOCK(spi, true); + SPI_SELECT(spi, SPIDEV_TOUCHSCREEN, true); + + /* Now make sure that the SPI bus is configured for the ADS7843 (it + * might have gotten configured for a different device while unlocked) + */ + + SPI_SETMODE(spi, CONFIG_ADS7843E_SPIMODE); + SPI_SETBITS(spi, 8); + SPI_SETFREQUENCY(spi, CONFIG_ADS7843E_FREQUENCY); +} +#endif + +/**************************************************************************** + * Function: ads7843e_deselect + * + * Description: + * De-select the SPI, unlocking as necessary. This function must be + * after completing a sequence of SPI operations. If we are sharing the SPI + * bus with other devices (CONFIG_SPI_OWNBUS undefined) then we need to + * un-lock the SPI bus for each transfer, possibly losing the current + * configuration. + * + * Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_OWNBUS +static inline void ads7843e_deselect(FAR struct spi_dev_s *spi) +{ + /* We own the SPI bus, so just de-select the chip */ + + SPI_SELECT(spi, SPIDEV_TOUCHSCREEN, false); +} +#else +static void ads7843e_deselect(FAR struct spi_dev_s *spi) +{ + /* De-select ADS7843 chip and relinquish the SPI bus. */ + + SPI_SELECT(spi, SPIDEV_TOUCHSCREEN, false); + (void)SPI_LOCK(spi, false); +} +#endif + +/**************************************************************************** + * Function: ads7843e_configspi + * + * Description: + * Configure the SPI for use with the ADS7843E. This function should be + * called once during touchscreen initialization to configure the SPI + * bus. Note that if CONFIG_SPI_OWNBUS is not defined, then this function + * does nothing. + * + * Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static inline void ads7843e_configspi(FAR struct spi_dev_s *spi) +{ + idbg("Mode: %d Bits: 8 Frequency: %d\n", + CONFIG_ADS7843E_SPIMODE, CONFIG_ADS7843E_FREQUENCY); + + /* Configure SPI for the ADS7843. But only if we own the SPI bus. Otherwise, don't + * bother because it might change. + */ + +#ifdef CONFIG_SPI_OWNBUS + SPI_SELECT(spi, SPIDEV_TOUCHSCREEN, true); + SPI_SETMODE(spi, CONFIG_ADS7843E_SPIMODE); + SPI_SETBITS(spi, 8); + SPI_SETFREQUENCY(spi, CONFIG_ADS7843E_FREQUENCY); + SPI_SELECT(spi, SPIDEV_TOUCHSCREEN, false); +#endif +} + +/**************************************************************************** + * Name: ads7843e_waitbusy + ****************************************************************************/ + +static inline void ads7843e_waitbusy(FAR struct ads7843e_dev_s *priv) +{ + while (priv->config->busy(priv->config)); +} + +/**************************************************************************** + * Name: ads7843e_sendcmd + ****************************************************************************/ + +static uint16_t ads7843e_sendcmd(FAR struct ads7843e_dev_s *priv, uint8_t cmd) +{ + uint8_t buffer[2]; + uint16_t result; + + /* Select the ADS7843E */ + + ads7843e_select(priv->spi); + + /* Send the command */ + + (void)SPI_SEND(priv->spi, cmd); + ads7843e_waitbusy(priv); + + /* Read the data */ + + SPI_RECVBLOCK(priv->spi, buffer, 2); + ads7843e_deselect(priv->spi); + + result = ((uint16_t)buffer[0] << 8) | (uint16_t)buffer[1]; + result = result >> 4; + + ivdbg("cmd:%02x response:%04x\n", cmd, result); + return result; +} + +/**************************************************************************** + * Name: ads7843e_notify + ****************************************************************************/ + +static void ads7843e_notify(FAR struct ads7843e_dev_s *priv) +{ +#ifndef CONFIG_DISABLE_POLL + int i; +#endif + + /* If there are threads waiting for read data, then signal one of them + * that the read data is available. + */ + + if (priv->nwaiters > 0) + { + /* After posting this semaphore, we need to exit because the ADS7843E + * is no longer available. + */ + + sem_post(&priv->waitsem); + } + + /* If there are threads waiting on poll() for ADS7843E data to become available, + * then wake them up now. NOTE: we wake up all waiting threads because we + * do not know that they are going to do. If they all try to read the data, + * then some make end up blocking after all. + */ + +#ifndef CONFIG_DISABLE_POLL + for (i = 0; i < CONFIG_ADS7843E_NPOLLWAITERS; i++) + { + struct pollfd *fds = priv->fds[i]; + if (fds) + { + fds->revents |= POLLIN; + ivdbg("Report events: %02x\n", fds->revents); + sem_post(fds->sem); + } + } +#endif +} + +/**************************************************************************** + * Name: ads7843e_sample + ****************************************************************************/ + +static int ads7843e_sample(FAR struct ads7843e_dev_s *priv, + FAR struct ads7843e_sample_s *sample) +{ + irqstate_t flags; + int ret = -EAGAIN; + + /* Interrupts me be disabled when this is called to (1) prevent posting + * of semaphores from interrupt handlers, and (2) to prevent sampled data + * from changing until it has been reported. + */ + + flags = irqsave(); + + /* Is there new ADS7843E sample data available? */ + + if (priv->penchange) + { + /* Yes.. the state has changed in some way. Return a copy of the + * sampled data. + */ + + memcpy(sample, &priv->sample, sizeof(struct ads7843e_sample_s )); + + /* Now manage state transitions */ + + if (sample->contact == CONTACT_UP) + { + /* Next.. no contact. Increment the ID so that next contact ID + * will be unique. X/Y positions are no longer valid. + */ + + priv->sample.contact = CONTACT_NONE; + priv->sample.valid = false; + priv->id++; + } + else if (sample->contact == CONTACT_DOWN) + { + /* First report -- next report will be a movement */ + + priv->sample.contact = CONTACT_MOVE; + } + + priv->penchange = false; + ret = OK; + } + + irqrestore(flags); + return ret; +} + +/**************************************************************************** + * Name: ads7843e_waitsample + ****************************************************************************/ + +static int ads7843e_waitsample(FAR struct ads7843e_dev_s *priv, + FAR struct ads7843e_sample_s *sample) +{ + irqstate_t flags; + int ret; + + /* Interrupts me be disabled when this is called to (1) prevent posting + * of semaphores from interrupt handlers, and (2) to prevent sampled data + * from changing until it has been reported. + * + * In addition, we will also disable pre-emption to prevent other threads + * from getting control while we muck with the semaphores. + */ + + sched_lock(); + flags = irqsave(); + + /* Now release the semaphore that manages mutually exclusive access to + * the device structure. This may cause other tasks to become ready to + * run, but they cannot run yet because pre-emption is disabled. + */ + + sem_post(&priv->devsem); + + /* Try to get the a sample... if we cannot, then wait on the semaphore + * that is posted when new sample data is available. + */ + + while (ads7843e_sample(priv, sample) < 0) + { + /* Wait for a change in the ADS7843E state */ + + ivdbg("Waiting..\n"); + priv->nwaiters++; + ret = sem_wait(&priv->waitsem); + priv->nwaiters--; + + if (ret < 0) + { + /* If we are awakened by a signal, then we need to return + * the failure now. + */ + + idbg("sem_wait: %d\n", errno); + DEBUGASSERT(errno == EINTR); + ret = -EINTR; + goto errout; + } + } + + ivdbg("Sampled\n"); + + /* Re-acquire the the semaphore that manages mutually exclusive access to + * the device structure. We may have to wait here. But we have our sample. + * Interrupts and pre-emption will be re-enabled while we wait. + */ + + ret = sem_wait(&priv->devsem); + +errout: + /* Then re-enable interrupts. We might get interrupt here and there + * could be a new sample. But no new threads will run because we still + * have pre-emption disabled. + */ + + irqrestore(flags); + + /* Restore pre-emption. We might get suspended here but that is okay + * because we already have our sample. Note: this means that if there + * were two threads reading from the ADS7843E for some reason, the data + * might be read out of order. + */ + + sched_unlock(); + return ret; +} + +/**************************************************************************** + * Name: ads7843e_schedule + ****************************************************************************/ + +static int ads7843e_schedule(FAR struct ads7843e_dev_s *priv) +{ + FAR struct ads7843e_config_s *config; + int ret; + + /* Get a pointer the callbacks for convenience (and so the code is not so + * ugly). + */ + + config = priv->config; + DEBUGASSERT(config != NULL); + + /* Disable further interrupts. ADS7843E interrupts will be re-enabled + * after the worker thread executes. + */ + + config->enable(config, false); + + /* Disable the watchdog timer. It will be re-enabled in the worker thread + * while the pen remains down. + */ + + wd_cancel(priv->wdog); + + /* Transfer processing to the worker thread. Since ADS7843E interrupts are + * disabled while the work is pending, no special action should be required + * to protected the work queue. + */ + + DEBUGASSERT(priv->work.worker == NULL); + ret = work_queue(&priv->work, ads7843e_worker, priv, 0); + if (ret != 0) + { + illdbg("Failed to queue work: %d\n", ret); + } + + return OK; +} + +/**************************************************************************** + * Name: ads7843e_wdog + ****************************************************************************/ + +static void ads7843e_wdog(int argc, uint32_t arg1, ...) +{ + FAR struct ads7843e_dev_s *priv = (FAR struct ads7843e_dev_s *)((uintptr_t)arg1); + (void)ads7843e_schedule(priv); +} + +/**************************************************************************** + * Name: ads7843e_worker + ****************************************************************************/ + +static void ads7843e_worker(FAR void *arg) +{ + FAR struct ads7843e_dev_s *priv = (FAR struct ads7843e_dev_s *)arg; + FAR struct ads7843e_config_s *config; + bool pendown; + + ASSERT(priv != NULL); + + /* Get a pointer the callbacks for convenience (and so the code is not so + * ugly). + */ + + config = priv->config; + DEBUGASSERT(config != NULL); + + /* Disable the watchdog timer */ + + wd_cancel(priv->wdog); + + /* Check for pen up or down by reading the PENIRQ GPIO. */ + + pendown = config->pendown(config); + + /* Handle the change from pen down to pen up */ + + if (!pendown) + { + /* Ignore the interrupt if the pen was already up (CONTACT_NONE == pen up and + * already reported. CONTACT_UP == pen up, but not reported) + */ + + if (priv->sample.contact == CONTACT_NONE) + { + goto errout; + } + + /* The pen is up. NOTE: We know from a previous test, that this is a + * loss of contact condition. This will be changed to CONTACT_NONE + * after the loss of contact is sampled. + */ + + priv->sample.contact = CONTACT_UP; + } + + /* It is a pen down event. If the last loss-of-contact event has not been + * processed yet, then we have to ignore the pen down event (or else it will + * look like a drag event) + */ + + else if (priv->sample.contact == CONTACT_UP) + { + goto errout; + } + else + { + /* Handle pen down events. First, sample positional values. */ + + priv->sample.x = ads7843e_sendcmd(priv, ADS7843_CMD_XPOSITION); + priv->sample.y = ads7843e_sendcmd(priv, ADS7843_CMD_YPOSITION); + + /* The X/Y positional data is now valid */ + + priv->sample.valid = true; + + /* If this is the first (acknowledged) pen down report, then report + * this as the first contact. If contact == CONTACT_DOWN, it will be + * set to set to CONTACT_MOVE after the contact is first sampled. + */ + + if (priv->sample.contact != CONTACT_MOVE) + { + /* First contact */ + + priv->sample.contact = CONTACT_DOWN; + } + + /* Continue to sample the position while the pen is down */ + + wd_start(priv->wdog, ADS7843E_WDOG_DELAY, ads7843e_wdog, 1, (uint32_t)priv); + } + + /* Indicate the availability of new sample data for this ID */ + + priv->sample.id = priv->id; + priv->penchange = true; + + /* Notify any waiters that new ADS7843E data is available */ + + ads7843e_notify(priv); + + /* Exit, re-enabling ADS7843E interrupts */ + +errout: + (void)ads7843e_sendcmd(priv, ADS7843_CMD_ENABPINIRQ); + config->enable(config, true); +} + +/**************************************************************************** + * Name: ads7843e_interrupt + ****************************************************************************/ + +static int ads7843e_interrupt(int irq, FAR void *context) +{ + FAR struct ads7843e_dev_s *priv; + FAR struct ads7843e_config_s *config; + int ret; + + /* Which ADS7843E device caused the interrupt? */ + +#ifndef CONFIG_ADS7843E_MULTIPLE + priv = &g_ads7843e; +#else + for (priv = g_ads7843elist; + priv && priv->configs->irq != irq; + priv = priv->flink); + + ASSERT(priv != NULL); +#endif + + /* Get a pointer the callbacks for convenience (and so the code is not so + * ugly). + */ + + config = priv->config; + DEBUGASSERT(config != NULL); + + /* Schedule sampling to occur on the worker thread */ + + ret = ads7843e_schedule(priv); + + /* Clear any pending interrupts and return success */ + + config->clear(config); + return ret; +} + +/**************************************************************************** + * Name: ads7843e_open + ****************************************************************************/ + +static int ads7843e_open(FAR struct file *filep) +{ +#ifdef CONFIG_ADS7843E_REFCNT + FAR struct inode *inode; + FAR struct ads7843e_dev_s *priv; + uint8_t tmp; + int ret; + + ivdbg("Opening\n"); + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct ads7843e_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Increment the reference count */ + + tmp = priv->crefs + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + goto errout_with_sem; + } + + /* When the reference increments to 1, this is the first open event + * on the driver.. and an opportunity to do any one-time initialization. + */ + + /* Save the new open count on success */ + + priv->crefs = tmp; + +errout_with_sem: + sem_post(&priv->devsem); + return ret; +#else + ivdbg("Opening\n"); + return OK; +#endif +} + +/**************************************************************************** + * Name: ads7843e_close + ****************************************************************************/ + +static int ads7843e_close(FAR struct file *filep) +{ +#ifdef CONFIG_ADS7843E_REFCNT + FAR struct inode *inode; + FAR struct ads7843e_dev_s *priv; + int ret; + + ivdbg("Closing\n"); + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct ads7843e_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Decrement the reference count unless it would decrement a negative + * value. When the count decrements to zero, there are no further + * open references to the driver. + */ + + if (priv->crefs >= 1) + { + priv->crefs--; + } + + sem_post(&priv->devsem); +#endif + ivdbg("Closing\n"); + return OK; +} + +/**************************************************************************** + * Name: ads7843e_read + ****************************************************************************/ + +static ssize_t ads7843e_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + FAR struct inode *inode; + FAR struct ads7843e_dev_s *priv; + FAR struct touch_sample_s *report; + struct ads7843e_sample_s sample; + int ret; + + ivdbg("buffer:%p len:%d\n", buffer, len); + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct ads7843e_dev_s *)inode->i_private; + + /* Verify that the caller has provided a buffer large enough to receive + * the touch data. + */ + + if (len < SIZEOF_TOUCH_SAMPLE_S(1)) + { + /* We could provide logic to break up a touch report into segments and + * handle smaller reads... but why? + */ + + idbg("Unsupported read size: %d\n", len); + return -ENOSYS; + } + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + idbg("sem_wait: %d\n", errno); + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Try to read sample data. */ + + ret = ads7843e_sample(priv, &sample); + if (ret < 0) + { + /* Sample data is not available now. We would ave to wait to get + * receive sample data. If the user has specified the O_NONBLOCK + * option, then just return an error. + */ + + ivdbg("Sample data is not available\n"); + if (filep->f_oflags & O_NONBLOCK) + { + ret = -EAGAIN; + goto errout; + } + + /* Wait for sample data */ + + ret = ads7843e_waitsample(priv, &sample); + if (ret < 0) + { + /* We might have been awakened by a signal */ + + idbg("ads7843e_waitsample: %d\n", ret); + goto errout; + } + } + + /* In any event, we now have sampled ADS7843E data that we can report + * to the caller. + */ + + report = (FAR struct touch_sample_s *)buffer; + memset(report, 0, SIZEOF_TOUCH_SAMPLE_S(1)); + report->npoints = 1; + report->point[0].id = priv->id; + report->point[0].x = sample.x; + report->point[0].y = sample.y; + + /* Report the appropriate flags */ + + if (sample.contact == CONTACT_UP) + { + /* Pen is now up. Is the positional data valid? This is important to + * know because the release will be sent to the window based on its + * last positional data. + */ + + if (sample.valid) + { + report->point[0].flags = TOUCH_UP | TOUCH_ID_VALID | + TOUCH_POS_VALID | TOUCH_PRESSURE_VALID; + } + else + { + report->point[0].flags = TOUCH_UP | TOUCH_ID_VALID; + } + } + else if (sample.contact == CONTACT_DOWN) + { + /* First contact */ + + report->point[0].flags = TOUCH_DOWN | TOUCH_ID_VALID | TOUCH_POS_VALID; + } + else /* if (sample->contact == CONTACT_MOVE) */ + { + /* Movement of the same contact */ + + report->point[0].flags = TOUCH_MOVE | TOUCH_ID_VALID | TOUCH_POS_VALID; + } + + ivdbg(" id: %d\n", report->point[0].id); + ivdbg(" flags: %02x\n", report->point[0].flags); + ivdbg(" x: %d\n", report->point[0].x); + ivdbg(" y: %d\n", report->point[0].y); + + ret = SIZEOF_TOUCH_SAMPLE_S(1); + +errout: + sem_post(&priv->devsem); + ivdbg("Returning: %d\n", ret); + return ret; +} + +/**************************************************************************** + * Name:ads7843e_ioctl + ****************************************************************************/ + +static int ads7843e_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode; + FAR struct ads7843e_dev_s *priv; + int ret; + + ivdbg("cmd: %d arg: %ld\n", cmd, arg); + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct ads7843e_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Process the IOCTL by command */ + + switch (cmd) + { + case TSIOC_SETFREQUENCY: /* arg: Pointer to uint32_t frequency value */ + { + FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg); + DEBUGASSERT(priv->config != NULL && ptr != NULL); + priv->config->frequency = SPI_SETFREQUENCY(priv->spi, *ptr); + } + break; + + case TSIOC_GETFREQUENCY: /* arg: Pointer to uint32_t frequency value */ + { + FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg); + DEBUGASSERT(priv->config != NULL && ptr != NULL); + *ptr = priv->config->frequency; + } + break; + + default: + ret = -ENOTTY; + break; + } + + sem_post(&priv->devsem); + return ret; +} + +/**************************************************************************** + * Name: ads7843e_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static int ads7843e_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct inode *inode; + FAR struct ads7843e_dev_s *priv; + pollevent_t eventset; + int ndx; + int ret = OK; + int i; + + ivdbg("setup: %d\n", (int)setup); + DEBUGASSERT(filep && fds); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct ads7843e_dev_s *)inode->i_private; + + /* Are we setting up the poll? Or tearing it down? */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + if (setup) + { + /* Ignore waits that do not include POLLIN */ + + if ((fds->events & POLLIN) == 0) + { + ret = -EDEADLK; + goto errout; + } + + /* This is a request to set up the poll. Find an available + * slot for the poll structure reference + */ + + for (i = 0; i < CONFIG_ADS7843E_NPOLLWAITERS; i++) + { + /* Find an available slot */ + + if (!priv->fds[i]) + { + /* Bind the poll structure and this slot */ + + priv->fds[i] = fds; + fds->priv = &priv->fds[i]; + break; + } + } + + if (i >= CONFIG_ADS7843E_NPOLLWAITERS) + { + fds->priv = NULL; + ret = -EBUSY; + goto errout; + } + + /* Should we immediately notify on any of the requested events? */ + + if (priv->penchange) + { + ads7843e_notify(priv); + } + } + else if (fds->priv) + { + /* This is a request to tear down the poll. */ + + struct pollfd **slot = (struct pollfd **)fds->priv; + DEBUGASSERT(slot != NULL); + + /* Remove all memory of the poll setup */ + + *slot = NULL; + fds->priv = NULL; + } + +errout: + sem_post(&priv->devsem); + return ret; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ads7843e_register + * + * Description: + * Configure the ADS7843E to use the provided SPI device instance. This + * will register the driver as /dev/inputN where N is the minor device + * number + * + * Input Parameters: + * dev - An SPI driver instance + * config - Persistent board configuration data + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int ads7843e_register(FAR struct spi_dev_s *dev, + FAR struct ads7843e_config_s *config, int minor) +{ + FAR struct ads7843e_dev_s *priv; + char devname[DEV_NAMELEN]; +#ifdef CONFIG_ADS7843E_MULTIPLE + irqstate_t flags; +#endif + int ret; + + ivdbg("dev: %p minor: %d\n", dev, minor); + + /* Debug-only sanity checks */ + + DEBUGASSERT(dev != NULL && config != NULL && minor >= 0 && minor < 100); + + /* Create and initialize a ADS7843E device driver instance */ + +#ifndef CONFIG_ADS7843E_MULTIPLE + priv = &g_ads7843e; +#else + priv = (FAR struct ads7843e_dev_s *)kmalloc(sizeof(struct ads7843e_dev_s)); + if (!priv) + { + idbg("kmalloc(%d) failed\n", sizeof(struct ads7843e_dev_s)); + return -ENOMEM; + } +#endif + + /* Initialize the ADS7843E device driver instance */ + + memset(priv, 0, sizeof(struct ads7843e_dev_s)); + priv->spi = dev; /* Save the SPI device handle */ + priv->config = config; /* Save the board configuration */ + priv->wdog = wd_create(); /* Create a watchdog timer */ + sem_init(&priv->devsem, 0, 1); /* Initialize device structure semaphore */ + sem_init(&priv->waitsem, 0, 0); /* Initialize pen event wait semaphore */ + + /* Make sure that interrupts are disabled */ + + config->clear(config); + config->enable(config, false); + + /* Attach the interrupt handler */ + + ret = config->attach(config, ads7843e_interrupt); + if (ret < 0) + { + idbg("Failed to attach interrupt\n"); + goto errout_with_priv; + } + + /* Configure the SPI interface */ + + ads7843e_configspi(dev); + + /* Enable the PEN IRQ */ + + ads7843e_sendcmd(priv, ADS7843_CMD_ENABPINIRQ); + + /* Register the device as an input device */ + + (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor); + ivdbg("Registering %s\n", devname); + + ret = register_driver(devname, &ads7843e_fops, 0666, priv); + if (ret < 0) + { + idbg("register_driver() failed: %d\n", ret); + goto errout_with_priv; + } + + /* If multiple ADS7843E devices are supported, then we will need to add + * this new instance to a list of device instances so that it can be + * found by the interrupt handler based on the recieved IRQ number. + */ + +#ifdef CONFIG_ADS7843E_MULTIPLE + priv->flink = g_ads7843elist; + g_ads7843elist = priv; + irqrestore(flags); +#endif + + /* Schedule work to perform the initial sampling and to set the data + * availability conditions. + */ + + ret = work_queue(&priv->work, ads7843e_worker, priv, 0); + if (ret != 0) + { + idbg("Failed to queue work: %d\n", ret); + goto errout_with_priv; + } + + /* And return success (?) */ + + return OK; + +errout_with_priv: + sem_destroy(&priv->devsem); +#ifdef CONFIG_ADS7843E_MULTIPLE + kfree(priv); +#endif + return ret; +} diff --git a/nuttx/drivers/input/ads7843e.h b/nuttx/drivers/input/ads7843e.h new file mode 100644 index 0000000000..030d1cb332 --- /dev/null +++ b/nuttx/drivers/input/ads7843e.h @@ -0,0 +1,171 @@ +/******************************************************************************************** + * drivers/input/ads7843e.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "Touch Screen Controller, ADS7843," Burr-Brown Products from Texas + * Instruments, SBAS090B, September 2000, Revised May 2002" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __DRIVERS_INPUT_ADS7843E_H +#define __DRIVERS_INPUT_ADS7843E_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ +/* Configuration ****************************************************************************/ +/* Reference counting is partially implemented, but not needed in the current design. */ + +#undef CONFIG_ADS7843E_REFCNT + +/* ADS7843E Interfaces *********************************************************************/ +/* ADS7843E command bit settings */ + +#define ADS7843E_CMD_PD0 (1 << 0) /* PD0 */ +#define ADS7843E_CMD_PD1 (1 << 1) /* PD1 */ +#define ADS7843E_CMD_DFR (1 << 2) /* SER/DFR */ +#define ADS7843E_CMD_EIGHT_BITS_MOD (1 << 3) /* Mode */ +#define ADS7843E_CMD_START (1 << 7) /* Start Bit */ +#define ADS7843E_CMD_SWITCH_SHIFT 4 /* Address setting */ + +/* ADS7843E Commands */ + +#define ADS7843_CMD_YPOSITION \ + ((1 << ADS7843E_CMD_SWITCH_SHIFT)|ADS7843E_CMD_START|ADS7843E_CMD_PD0|ADS7843E_CMD_PD1) +#define ADS7843_CMD_XPOSITION \ + ((5 << ADS7843E_CMD_SWITCH_SHIFT)|ADS7843E_CMD_START|ADS7843E_CMD_PD0|ADS7843E_CMD_PD1) +#define ADS7843_CMD_ENABPINIRQ \ + ((1 << ADS7843E_CMD_SWITCH_SHIFT)|ADS7843E_CMD_START) + +/* Driver support **************************************************************************/ +/* This format is used to construct the /dev/input[n] device driver path. It + * defined here so that it will be used consistently in all places. + */ + +#define DEV_FORMAT "/dev/input%d" +#define DEV_NAMELEN 16 + +/* Poll the pen position while the pen is down at this rate (50MS): */ + +#define ADS7843E_WDOG_DELAY ((50 + (MSEC_PER_TICK-1))/ MSEC_PER_TICK) + +/******************************************************************************************** + * Public Types + ********************************************************************************************/ + +/* This describes the state of one contact */ + +enum ads7843e_contact_3 +{ + CONTACT_NONE = 0, /* No contact */ + CONTACT_DOWN, /* First contact */ + CONTACT_MOVE, /* Same contact, possibly different position */ + CONTACT_UP, /* Contact lost */ +}; + +/* This structure describes the results of one ADS7843E sample */ + +struct ads7843e_sample_s +{ + uint8_t id; /* Sampled touch point ID */ + uint8_t contact; /* Contact state (see enum ads7843e_contact_e) */ + bool valid; /* True: x,y contain valid, sampled data */ + uint16_t x; /* Measured X position */ + uint16_t y; /* Measured Y position */ +}; + +/* This structure describes the state of one ADS7843E driver instance */ + +struct ads7843e_dev_s +{ +#ifdef CONFIG_ADS7843E_MULTIPLE + FAR struct ads7843e_dev_s *flink; /* Supports a singly linked list of drivers */ +#endif +#ifdef CONFIG_ADS7843E_REFCNT + uint8_t crefs; /* Number of times the device has been opened */ +#endif + uint8_t nwaiters; /* Number of threads waiting for ADS7843E data */ + uint8_t id; /* Current touch point ID */ + volatile bool penchange; /* An unreported event is buffered */ + sem_t devsem; /* Manages exclusive access to this structure */ + sem_t waitsem; /* Used to wait for the availability of data */ + + FAR struct ads7843e_config_s *config; /* Board configuration data */ + FAR struct spi_dev_s *spi; /* Saved SPI driver instance */ + struct work_s work; /* Supports the interrupt handling "bottom half" */ + struct ads7843e_sample_s sample; /* Last sampled touch point data */ + WDOG_ID wdog; /* Poll the position while the pen is down */ + + /* The following is a list if poll structures of threads waiting for + * driver events. The 'struct pollfd' reference for each open is also + * retained in the f_priv field of the 'struct file'. + */ + +#ifndef CONFIG_DISABLE_POLL + struct pollfd *fds[CONFIG_ADS7843E_NPOLLWAITERS]; +#endif +}; + +/******************************************************************************************** + * Public Function Prototypes + ********************************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __DRIVERS_INPUT_ADS7843E_H */ diff --git a/nuttx/drivers/input/stmpe811.h b/nuttx/drivers/input/stmpe811.h new file mode 100644 index 0000000000..f6d646527f --- /dev/null +++ b/nuttx/drivers/input/stmpe811.h @@ -0,0 +1,245 @@ +/******************************************************************************************** + * drivers/input/stmpe811.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "STMPE811 S-Touch® advanced resistive touchscreen controller with 8-bit + * GPIO expander," Doc ID 14489 Rev 6, CD00186725, STMicroelectronics" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __DRIVERS_INPUT_STMPE811_H +#define __DRIVERS_INPUT_STMPE811_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#if defined(CONFIG_INPUT) && defined(CONFIG_INPUT_STMPE811) + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ +/* Configuration ****************************************************************************/ +/* Reference counting is partially implemented, but not needed in the current design. + */ + +#undef CONFIG_STMPE811_REFCNT + +/* No support for the SPI interface yet */ + +#ifdef CONFIG_STMPE811_SPI +# error "Only the STMPE811 I2C interface is supported by this driver" +#endif + +/* Driver support ***************************************************************************/ +/* This format is used to construct the /dev/input[n] device driver path. It defined here + * so that it will be used consistently in all places. + */ + +#define DEV_FORMAT "/dev/input%d" +#define DEV_NAMELEN 16 + +/* STMPE811 Resources ************************************************************************/ +#ifndef CONFIG_STMPE811_TSC_DISABLE +# define STMPE811_ADC_NPINS 4 /* Only pins 0-3 can be used for ADC */ +# define STMPE811_GPIO_NPINS 4 /* Only pins 0-3 can be used as GPIOs */ +#else +# define STMPE811_ADC_NPINS 8 /* All pins can be used for ADC */ +# define STMPE811_GPIO_NPINS 8 /* All pins can be used as GPIOs */ +#endif + +/* Driver flags */ + +#define STMPE811_FLAGS_TSC_INITIALIZED (1 << 0) /* 1: The TSC block has been initialized */ +#define STMPE811_FLAGS_GPIO_INITIALIZED (1 << 1) /* 1: The GIO block has been initialized */ +#define STMPE811_FLAGS_ADC_INITIALIZED (1 << 2) /* 1: The ADC block has been initialized */ +#define STMPE811_FLAGS_TS_INITIALIZED (1 << 3) /* 1: The TS block has been initialized */ + +/* Timeout to detect missing pen up events */ + +#define STMPE811_PENUP_TICKS ((100 + (MSEC_PER_TICK-1)) / MSEC_PER_TICK) + +/******************************************************************************************** + * Public Types + ********************************************************************************************/ +/* This describes the state of one contact */ + +enum stmpe811_contact_3 +{ + CONTACT_NONE = 0, /* No contact */ + CONTACT_DOWN, /* First contact */ + CONTACT_MOVE, /* Same contact, possibly different position */ + CONTACT_UP, /* Contact lost */ +}; + +/* This structure describes the results of one STMPE811 sample */ + +struct stmpe811_sample_s +{ + uint8_t id; /* Sampled touch point ID */ + uint8_t contact; /* Contact state (see enum stmpe811_contact_e) */ + bool valid; /* True: x,y,z contain valid, sampled data */ + uint16_t x; /* Measured X position */ + uint16_t y; /* Measured Y position */ + uint8_t z; /* Measured Z index */ +}; + +/* This structure represents the state of the STMPE811 driver */ + +struct stmpe811_dev_s +{ +#ifdef CONFIG_STMPE811_MULTIPLE + FAR struct stmpe811_dev_s *flink; /* Supports a singly linked list of drivers */ +#endif + + /* Common fields */ + + FAR struct stmpe811_config_s *config; /* Board configuration data */ + sem_t exclsem; /* Manages exclusive access to this structure */ +#ifdef CONFIG_STMPE811_SPI + FAR struct spi_dev_s *spi; /* Saved SPI driver instance */ +#else + FAR struct i2c_dev_s *i2c; /* Saved I2C driver instance */ +#endif + + uint8_t inuse; /* STMPE811 pins in use */ + uint8_t flags; /* See STMPE811_FLAGS_* definitions */ + struct work_s work; /* Supports the interrupt handling "bottom half" */ + + /* Fields that may be disabled to save size if touchscreen support is not used. */ + +#ifndef CONFIG_STMPE811_TSC_DISABLE +#ifdef CONFIG_STMPE811_REFCNT + uint8_t crefs; /* Number of times the device has been opened */ +#endif + uint8_t nwaiters; /* Number of threads waiting for STMPE811 data */ + uint8_t id; /* Current touch point ID */ + uint8_t minor; /* Touchscreen minor device number */ + volatile bool penchange; /* An unreported event is buffered */ + + uint16_t threshx; /* Thresholded X value */ + uint16_t threshy; /* Thresholded Y value */ + sem_t waitsem; /* Used to wait for the availability of data */ + + struct work_s timeout; /* Supports tiemeout work */ + WDOG_ID wdog; /* Timeout to detect missing pen down events */ + struct stmpe811_sample_s sample; /* Last sampled touch point data */ + + /* The following is a list if poll structures of threads waiting for + * driver events. The 'struct pollfd' reference for each open is also + * retained in the f_priv field of the 'struct file'. + */ + +#ifndef CONFIG_DISABLE_POLL + struct pollfd *fds[CONFIG_STMPE811_NPOLLWAITERS]; +#endif +#endif + + /* Fields that may be disabled to save size of GPIO support is not used */ + +#if !defined(CONFIG_STMPE811_GPIO_DISABLE) && !defined(CONFIG_STMPE811_GPIOINT_DISABLE) + stmpe811_handler_t handlers[STMPE811_GPIO_NPINS]; /* GPIO "interrupt handlers" */ +#endif +}; + +/******************************************************************************************** + * Public Function Prototypes + ********************************************************************************************/ + +/******************************************************************************************** + * Name: stmpe811_getreg8 + * + * Description: + * Read from an 8-bit STMPE811 register + * + ********************************************************************************************/ + +uint8_t stmpe811_getreg8(FAR struct stmpe811_dev_s *priv, uint8_t regaddr); + +/******************************************************************************************** + * Name: stmpe811_putreg8 + * + * Description: + * Write a value to an 8-bit STMPE811 register + * + ********************************************************************************************/ + +void stmpe811_putreg8(FAR struct stmpe811_dev_s *priv, uint8_t regaddr, uint8_t regval); + +/******************************************************************************************** + * Name: stmpe811_getreg16 + * + * Description: + * Read 16-bits of data from an STMPE-11 register + * + ********************************************************************************************/ + +uint16_t stmpe811_getreg16(FAR struct stmpe811_dev_s *priv, uint8_t regaddr); + +/******************************************************************************************** + * Name: stmpe811_tscint + * + * Description: + * Handle touchscreen interrupt events (this function actually executes in the context of + * the worker thread). + * + ********************************************************************************************/ + +#ifndef CONFIG_STMPE811_TSC_DISABLE +void stmpe811_tscworker(FAR struct stmpe811_dev_s *priv, uint8_t intsta) weak_function; +#endif + +/******************************************************************************************** + * Name: stmpe811_gpioworker + * + * Description: + * Handle GPIO interrupt events (this function actually executes in the context of the + * worker thread). + * + ********************************************************************************************/ + +#if !defined(CONFIG_STMPE811_GPIO_DISABLE) && !defined(CONFIG_STMPE811_GPIOINT_DISABLE) +void stmpe811_gpioworker(FAR struct stmpe811_dev_s *priv) weak_function; +#endif + +#endif /* CONFIG_INPUT && CONFIG_INPUT_STMPE811 */ +#endif /* __DRIVERS_INPUT_STMPE811_H */ diff --git a/nuttx/drivers/input/stmpe811_adc.c b/nuttx/drivers/input/stmpe811_adc.c new file mode 100644 index 0000000000..1ffe987e64 --- /dev/null +++ b/nuttx/drivers/input/stmpe811_adc.c @@ -0,0 +1,266 @@ +/**************************************************************************** + * drivers/input/stmpe811_adc.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "STMPE811 S-Touch® advanced resistive touchscreen controller with 8-bit + * GPIO expander," Doc ID 14489 Rev 6, CD00186725, STMicroelectronics" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "stmpe811.h" + +#if defined(CONFIG_INPUT) && defined(CONFIG_INPUT_STMPE811) && !defined(CONFIG_STMPE811_ADC_DISABLE) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stmpe811_adcinitialize + * + * Description: + * Configure for ADC mode operation. Set overall ADC ADC timing that + * applies to all pins. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stmpe811_adcinitialize(STMPE811_HANDLE handle) +{ + FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)handle; + uint8_t regval; + int ret; + + DEBUGASSERT(handle); + + /* Get exclusive access to the device structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + int errval = errno; + idbg("sem_wait failed: %d\n", errval); + return -errval; + } + + /* Enable Clocking for ADC */ + + regval = stmpe811_getreg8(priv, STMPE811_SYS_CTRL2); + regval &= ~SYS_CTRL2_ADC_OFF; + stmpe811_putreg8(priv, STMPE811_SYS_CTRL2, regval); + + /* Select Sample Time, bit number and ADC Reference */ + + stmpe811_putreg8(priv, STMPE811_ADC_CTRL1, priv->config->ctrl1); + + /* Wait for 20 ms */ + + up_mdelay(20); + + /* Select the ADC clock speed */ + + stmpe811_putreg8(priv, STMPE811_ADC_CTRL2, priv->config->ctrl2); + + /* Mark ADC initialized */ + + priv->flags |= STMPE811_FLAGS_ADC_INITIALIZED; + sem_post(&priv->exclsem); + return OK; +} + +/**************************************************************************** + * Name: stmpe811_adcconfig + * + * Description: + * Configure a pin for ADC input. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * pin - The ADC pin number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stmpe811_adcconfig(STMPE811_HANDLE handle, int pin) +{ + FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)handle; + uint8_t pinmask = GPIO_PIN(pin); + uint8_t regval; + int ret; + + DEBUGASSERT(handle && (unsigned)pin < STMPE811_ADC_NPINS); + + /* Get exclusive access to the device structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + int errval = errno; + idbg("sem_wait failed: %d\n", errval); + return -errval; + } + + /* Make sure that the pin is not already in use */ + + if ((priv->inuse & pinmask) != 0) + { + idbg("PIN%d is already in-use\n", pin); + sem_post(&priv->exclsem); + return -EBUSY; + } + + /* Clear the alternate function bit for the pin, making it an ADC input + * (or perhaps an an external reference, depending on the state of the + * ADC_CTRL1_REF_SEL bit). + */ + + regval = stmpe811_getreg8(priv, STMPE811_GPIO_AF); + regval &= ~pinmask; + stmpe811_putreg8(priv, STMPE811_GPIO_AF, regval); + + /* Mark the pin as 'in use' */ + + priv->inuse |= pinmask; + sem_post(&priv->exclsem); + return OK; +} + +/**************************************************************************** + * Name: stmpe811_adcread + * + * Description: + * Read the converted analog input value from the select pin. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * pin - The ADC pin number + * + * Returned Value: + * The converted value (there is no error reporting mechanism). + * + ****************************************************************************/ + +uint16_t stmpe811_adcread(STMPE811_HANDLE handle, int pin) +{ + FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)handle; + uint8_t pinmask = GPIO_PIN(pin); + uint8_t regval; + int i; + int ret; + + DEBUGASSERT(handle && (unsigned)pin < 8); + + /* Get exclusive access to the device structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + int errval = errno; + idbg("sem_wait failed: %d\n", errval); + return -errval; + } + + /* Request AD conversion by setting the bit corresponding the pin in the + * ADC CAPT register. + */ + + stmpe811_putreg8(priv, STMPE811_ADC_CAPT, pinmask); + + /* Wait for the conversion to complete. The ADC CAPT register reads '1' + * if conversion is completed. Reads '0' if conversion is in progress. + * Try three times before giving up. + */ + + for (i = 0; i < 3; i++) + { + /* The worst case ADC conversion time is (nominally) 56.4 uS. The + * following usleep() looks nice but in reality, the usleep() + * does not have that kind of precision (it will probably end up + * waiting 10 MS). + */ + + usleep(57); + + /* Check if the conversion is complete */ + + regval = stmpe811_getreg8(priv, STMPE811_ADC_CAPT); + if ((regval & pinmask) != 0) + { + break; + } + } + + /* At the completion of the conversion, return whatever we read from + * from the channel register associated with the pin. + */ + + return stmpe811_getreg16(priv, STMPE811_ADC_DATACH(pin)); +} + +#endif /* CONFIG_INPUT && CONFIG_INPUT_STMPE811 && !CONFIG_STMPE811_ADC_DISABLE */ + diff --git a/nuttx/drivers/input/stmpe811_base.c b/nuttx/drivers/input/stmpe811_base.c new file mode 100644 index 0000000000..72af1575a9 --- /dev/null +++ b/nuttx/drivers/input/stmpe811_base.c @@ -0,0 +1,546 @@ +/**************************************************************************** + * drivers/input/stmpe811_base.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "STMPE811 S-Touch® advanced resistive touchscreen controller with 8-bit + * GPIO expander," Doc ID 14489 Rev 6, CD00186725, STMicroelectronics" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "stmpe811.h" + +#if defined(CONFIG_INPUT) && defined(CONFIG_INPUT_STMPE811) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* If only a single STMPE811 device is supported, then the driver state + * structure may as well be pre-allocated. + */ + +#ifndef CONFIG_STMPE811_MULTIPLE +static struct stmpe811_dev_s g_stmpe811; + +/* Otherwise, we will need to maintain allocated driver instances in a list */ + +#else +static struct stmpe811_dev_s *g_stmpe811list; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stmpe811_worker + * + * Description: + * This is the "bottom half" of the STMPE811 interrupt handler + * + ****************************************************************************/ + +static void stmpe811_worker(FAR void *arg) +{ + FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)arg; + uint8_t regval; + + DEBUGASSERT(priv && priv->config); + + /* Get the global interrupt status */ + + regval = stmpe811_getreg8(priv, STMPE811_INT_STA); + + /* Check for a touchscreen interrupt */ + +#ifndef CONFIG_STMPE811_TSC_DISABLE + if ((regval & (INT_TOUCH_DET|INT_FIFO_TH|INT_FIFO_OFLOW)) != 0) + { + /* Dispatch the touchscreen interrupt if it was brought into the link */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (stmpe811_tscworker) +#endif + { + stmpe811_tscworker(priv, regval); + } + + stmpe811_putreg8(priv, STMPE811_INT_STA, (INT_TOUCH_DET|INT_FIFO_TH|INT_FIFO_OFLOW)); + regval &= ~(INT_TOUCH_DET|INT_FIFO_TH|INT_FIFO_OFLOW); + } +#endif + +#if !defined(CONFIG_STMPE811_GPIO_DISABLE) && !defined(CONFIG_STMPE811_GPIOINT_DISABLE) + if ((regval & INT_GPIO) != 0) + { + /* Dispatch the GPIO interrupt if it was brought into the link */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (stmpe811_gpioworker) +#endif + { + stmpe811_gpioworker(priv); + } + + stmpe811_putreg8(priv, STMPE811_INT_STA, INT_GPIO); + regval &= ~INT_GPIO; + } +#endif + + /* Clear any other residual, unhandled pending interrupt */ + + if (regval != 0) + { + stmpe811_putreg8(priv, STMPE811_INT_STA, regval); + } + + /* Re-enable the STMPE811 GPIO interrupt */ + + priv->config->enable(priv->config, true); +} + +/**************************************************************************** + * Name: stmpe811_interrupt + * + * Description: + * The STMPE811 interrupt handler + * + ****************************************************************************/ + +static int stmpe811_interrupt(int irq, FAR void *context) +{ + FAR struct stmpe811_dev_s *priv; + FAR struct stmpe811_config_s *config; + int ret; + + /* Which STMPE811 device caused the interrupt? */ + +#ifndef CONFIG_STMPE811_MULTIPLE + priv = &g_stmpe811; +#else + for (priv = g_stmpe811list; + priv && priv->config->irq != irq; + priv = priv->flink); + + ASSERT(priv != NULL); +#endif + + /* Get a pointer the callbacks for convenience (and so the code is not so + * ugly). + */ + + config = priv->config; + DEBUGASSERT(config != NULL); + + /* Disable further interrupts */ + + config->enable(config, false); + + /* Check if interrupt work is already queue. If it is already busy, then + * we already have interrupt processing in the pipeline and we need to do + * nothing more. + */ + + if (work_available(&priv->work)) + { + /* Yes.. Transfer processing to the worker thread. Since STMPE811 + * interrupts are disabled while the work is pending, no special + * action should be required to protect the work queue. + */ + + ret = work_queue(&priv->work, stmpe811_worker, priv, 0); + if (ret != 0) + { + illdbg("Failed to queue work: %d\n", ret); + } + } + + /* Clear any pending interrupts and return success */ + + config->clear(config); + return OK; +} + +/**************************************************************************** + * Name: stmpe811_checkid + * + * Description: + * Read and verify the STMPE811 chip ID + * + ****************************************************************************/ + +static int stmpe811_checkid(FAR struct stmpe811_dev_s *priv) +{ + uint16_t devid = 0; + + /* Read device ID */ + + devid = stmpe811_getreg8(priv, STMPE811_CHIP_ID); + devid = (uint32_t)(devid << 8); + devid |= (uint32_t)stmpe811_getreg8(priv, STMPE811_CHIP_ID+1); + ivdbg("devid: %04x\n", devid); + + if (devid != (uint16_t)CHIP_ID) + { + /* ID is not Correct */ + + return -ENODEV; + } + + return OK; +} + +/**************************************************************************** + * Name: stmpe811_reset + * + * Description: + * Reset the STMPE811 + * + ****************************************************************************/ + +static void stmpe811_reset(FAR struct stmpe811_dev_s *priv) +{ + /* Power Down the STMPE811 */ + + stmpe811_putreg8(priv, STMPE811_SYS_CTRL1, SYS_CTRL1_SOFTRESET); + + /* Wait a bit */ + + usleep(20*1000); + + /* Then power on again. All registers will be in their reset state. */ + + stmpe811_putreg8(priv, STMPE811_SYS_CTRL1, 0); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stmpe811_instantiate + * + * Description: + * Instantiate and configure the STMPE811 device driver to use the provided + * I2C or SPIdevice instance. + * + * Input Parameters: + * dev - An I2C or SPI driver instance + * config - Persistant board configuration data + * + * Returned Value: + * A non-zero handle is returned on success. This handle may then be used + * to configure the STMPE811 driver as necessary. A NULL handle value is + * returned on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_STMPE811_SPI +STMPE811_HANDLE stmpe811_instantiate(FAR struct spi_dev_s *dev, + FAR struct stmpe811_config_s *config) +#else +STMPE811_HANDLE stmpe811_instantiate(FAR struct i2c_dev_s *dev, + FAR struct stmpe811_config_s *config) +#endif +{ + FAR struct stmpe811_dev_s *priv; + uint8_t regval; + int ret; + + /* Allocate the device state structure */ + +#ifdef CONFIG_STMPE811_MULTIPLE + priv = (FAR struct stmpe811_dev_s *)kzalloc(sizeof(struct stmpe811_dev_s)); + if (!priv) + { + return NULL; + } + + /* And save the device structure in the list of STMPE811 so that we can find it later */ + + priv->flink = g_stmpe811list; + g_stmpe811list = priv; +#else + + /* Use the one-and-only STMPE811 driver instance */ + + priv = &g_stmpe811; +#endif + + /* Initialize the device state structure */ + + sem_init(&priv->exclsem, 0, 1); + priv->config = config; + +#ifdef CONFIG_STMPE811_SPI + priv->spi = dev; +#else + priv->i2c = dev; + + /* Set the I2C address and frequency. REVISIT: This logic would be + * insufficient if we share the I2C bus with any other devices that also + * modify the address and frequency. + */ + + I2C_SETADDRESS(dev, config->address, 7); + I2C_SETFREQUENCY(dev, config->frequency); +#endif + + /* Read and verify the STMPE811 chip ID */ + + ret = stmpe811_checkid(priv); + if (ret < 0) + { +#ifdef CONFIG_STMPE811_MULTIPLE + kfree(priv); +#endif + return NULL; + } + + /* Generate STMPE811 Software reset */ + + stmpe811_reset(priv); + + /* Configure the interrupt output pin to generate interrupts on high or low level. */ + + regval = stmpe811_getreg8(priv, STMPE811_INT_CTRL); +#ifdef CONFIG_STMPE811_ACTIVELOW + regval &= ~INT_CTRL_INT_POLARITY; /* Pin polarity: Active low / falling edge */ +#else + regval |= INT_CTRL_INT_POLARITY; /* Pin polarity: Active high / rising edge */ +#endif +#ifdef CONFIG_STMPE811_EDGE + regval |= INT_CTRL_INT_TYPE; /* Edge interrupt */ +#else + regval &= ~INT_CTRL_INT_TYPE; /* Level interrupt */ +#endif + stmpe811_putreg8(priv, STMPE811_INT_CTRL, regval); + + /* Attach the STMPE811 interrupt handler. */ + + config->attach(config, stmpe811_interrupt); + + /* Clear any pending interrupts */ + + stmpe811_putreg8(priv, STMPE811_INT_STA, INT_ALL); + config->clear(config); + config->enable(config, true); + + /* Enable global interrupts */ + + regval = stmpe811_getreg8(priv, STMPE811_INT_CTRL); + regval |= INT_CTRL_GLOBAL_INT; + stmpe811_putreg8(priv, STMPE811_INT_CTRL, regval); + + /* Return our private data structure as an opaque handle */ + + return (STMPE811_HANDLE)priv; +} + +/**************************************************************************** + * Name: stmpe811_getreg8 + * + * Description: + * Read from an 8-bit STMPE811 register + * + ****************************************************************************/ + +#ifdef CONFIG_STMPE811_I2C +uint8_t stmpe811_getreg8(FAR struct stmpe811_dev_s *priv, uint8_t regaddr) +{ + /* 8-bit data read sequence: + * + * Start - I2C_Write_Address - STMPE811_Reg_Address - + * Repeated_Start - I2C_Read_Address - STMPE811_Read_Data - STOP + */ + + struct i2c_msg_s msg[2]; + uint8_t regval; + int ret; + + /* Setup 8-bit STMPE811 address write message */ + + msg[0].addr = priv->config->address; /* 7-bit address */ + msg[0].flags = 0; /* Write transaction, beginning with START */ + msg[0].buffer = ®addr; /* Transfer from this address */ + msg[0].length = 1; /* Send one byte following the address + * (no STOP) */ + + /* Set up the 8-bit STMPE811 data read message */ + + msg[1].addr = priv->config->address; /* 7-bit address */ + msg[1].flags = I2C_M_READ; /* Read transaction, beginning with Re-START */ + msg[1].buffer = ®val; /* Transfer to this address */ + msg[1].length = 1; /* Receive one byte following the address + * (then STOP) */ + + /* Perform the transfer */ + + ret = I2C_TRANSFER(priv->i2c, msg, 2); + if (ret < 0) + { + idbg("I2C_TRANSFER failed: %d\n", ret); + return 0; + } + +#ifdef CONFIG_STMPE811_REGDEBUG + dbg("%02x->%02x\n", regaddr, regval); +#endif + return regval; +} +#endif + +/**************************************************************************** + * Name: stmpe811_putreg8 + * + * Description: + * Write a value to an 8-bit STMPE811 register + * + ****************************************************************************/ + +#ifdef CONFIG_STMPE811_I2C +void stmpe811_putreg8(FAR struct stmpe811_dev_s *priv, + uint8_t regaddr, uint8_t regval) +{ + /* 8-bit data read sequence: + * + * Start - I2C_Write_Address - STMPE811_Reg_Address - STMPE811_Write_Data - STOP + */ + + struct i2c_msg_s msg; + uint8_t txbuffer[2]; + int ret; + +#ifdef CONFIG_STMPE811_REGDEBUG + dbg("%02x<-%02x\n", regaddr, regval); +#endif + + /* Setup to the data to be transferred. Two bytes: The STMPE811 register + * address followed by one byte of data. + */ + + txbuffer[0] = regaddr; + txbuffer[1] = regval; + + /* Setup 8-bit STMPE811 address write message */ + + msg.addr = priv->config->address; /* 7-bit address */ + msg.flags = 0; /* Write transaction, beginning with START */ + msg.buffer = txbuffer; /* Transfer from this address */ + msg.length = 2; /* Send two byte following the address + * (then STOP) */ + + /* Perform the transfer */ + + ret = I2C_TRANSFER(priv->i2c, &msg, 1); + if (ret < 0) + { + idbg("I2C_TRANSFER failed: %d\n", ret); + } +} +#endif + +/**************************************************************************** + * Name: stmpe811_getreg16 + * + * Description: + * Read 16-bits of data from an STMPE-11 register + * + ****************************************************************************/ + +#ifdef CONFIG_STMPE811_I2C +uint16_t stmpe811_getreg16(FAR struct stmpe811_dev_s *priv, uint8_t regaddr) +{ + /* 16-bit data read sequence: + * + * Start - I2C_Write_Address - STMPE811_Reg_Address - + * Repeated_Start - I2C_Read_Address - STMPE811_Read_Data_1 - + * STMPE811_Read_Data_2 - STOP + */ + + + struct i2c_msg_s msg[2]; + uint8_t rxbuffer[2]; + int ret; + + /* Setup 8-bit STMPE811 address write message */ + + msg[0].addr = priv->config->address; /* 7-bit address */ + msg[0].flags = 0; /* Write transaction, beginning with START */ + msg[0].buffer = ®addr; /* Transfer from this address */ + msg[0].length = 1; /* Send one byte following the address + * (no STOP) */ + + /* Set up the 8-bit STMPE811 data read message */ + + msg[1].addr = priv->config->address; /* 7-bit address */ + msg[1].flags = I2C_M_READ; /* Read transaction, beginning with Re-START */ + msg[1].buffer = rxbuffer; /* Transfer to this address */ + msg[1].length = 2; /* Receive two bytes following the address + * (then STOP) */ + + /* Perform the transfer */ + + ret = I2C_TRANSFER(priv->i2c, msg, 2); + if (ret < 0) + { + idbg("I2C_TRANSFER failed: %d\n", ret); + return 0; + } + +#ifdef CONFIG_STMPE811_REGDEBUG + dbg("%02x->%02x%02x\n", regaddr, rxbuffer[0], rxbuffer[1]); +#endif + return (uint16_t)rxbuffer[0] << 8 | (uint16_t)rxbuffer[1]; +} +#endif + +#endif /* CONFIG_INPUT && CONFIG_INPUT_STMPE811 */ + diff --git a/nuttx/drivers/input/stmpe811_gpio.c b/nuttx/drivers/input/stmpe811_gpio.c new file mode 100644 index 0000000000..b545828d12 --- /dev/null +++ b/nuttx/drivers/input/stmpe811_gpio.c @@ -0,0 +1,454 @@ +/**************************************************************************** + * drivers/input/stmpe811_gpio.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "STMPE811 S-Touch® advanced resistive touchscreen controller with 8-bit + * GPIO expander," Doc ID 14489 Rev 6, CD00186725, STMicroelectronics" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "stmpe811.h" + +#if defined(CONFIG_INPUT) && defined(CONFIG_INPUT_STMPE811) && !defined(CONFIG_STMPE811_GPIO_DISABLE) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stmpe811_gpioinit + * + * Description: + * Initialize the GPIO interrupt subsystem + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +static void stmpe811_gpioinit(FAR struct stmpe811_dev_s *priv) +{ + uint8_t regval; + + if ((priv->flags & STMPE811_FLAGS_GPIO_INITIALIZED) == 0) + { + /* Enable Clocking for GPIO */ + + regval = stmpe811_getreg8(priv, STMPE811_SYS_CTRL2); + regval &= ~SYS_CTRL2_GPIO_OFF; + stmpe811_putreg8(priv, STMPE811_SYS_CTRL2, regval); + + /* Disable all GPIO interrupts */ + + stmpe811_putreg8(priv, STMPE811_GPIO_EN, 0); + + /* Enable global GPIO interrupts */ + +#ifndef CONFIG_STMPE811_GPIOINT_DISABLE + regval = stmpe811_getreg8(priv, STMPE811_INT_EN); + regval |= INT_GPIO; + stmpe811_putreg8(priv, STMPE811_INT_EN, regval); +#endif + + priv->flags |= STMPE811_FLAGS_GPIO_INITIALIZED; + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stmpe811_gpioconfig + * + * Description: + * Configure an STMPE811 GPIO pin + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * pinconfig - Bit-encoded pin configuration + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stmpe811_gpioconfig(STMPE811_HANDLE handle, uint8_t pinconfig) +{ + FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)handle; + int pin = (pinconfig & STMPE811_GPIO_PIN_MASK) >> STMPE811_GPIO_PIN_SHIFT; + uint8_t pinmask = (1 << pin); + uint8_t regval; + int ret; + + DEBUGASSERT(handle && (unsigned)pin < STMPE811_GPIO_NPINS); + + /* Get exclusive access to the device structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + int errval = errno; + idbg("sem_wait failed: %d\n", errval); + return -errval; + } + + /* Make sure that the pin is not already in use */ + + if ((priv->inuse & pinmask) != 0) + { + idbg("PIN%d is already in-use\n", pin); + sem_post(&priv->exclsem); + return -EBUSY; + } + + /* Make sure that the GPIO block has been initialized */ + + stmpe811_gpioinit(priv); + + /* Set the alternate function bit for the pin, making it a GPIO */ + + regval = stmpe811_getreg8(priv, STMPE811_GPIO_AF); + regval |= pinmask; + stmpe811_putreg8(priv, STMPE811_GPIO_AF, regval); + + /* Is the pin an input or an output? */ + + if ((pinconfig & STMPE811_GPIO_DIR) == STMPE811_GPIO_OUTPUT) + { + /* The pin is an output */ + + regval = stmpe811_getreg8(priv, STMPE811_GPIO_DIR); + regval &= ~pinmask; + stmpe811_putreg8(priv, STMPE811_GPIO_DIR, regval); + + /* Set its initial output value */ + + stmpe811_gpiowrite(handle, pinconfig, + (pinconfig & STMPE811_GPIO_VALUE) != STMPE811_GPIO_ZERO); + } + else + { + /* It is an input */ + + regval = stmpe811_getreg8(priv, STMPE811_GPIO_DIR); + regval |= pinmask; + stmpe811_putreg8(priv, STMPE811_GPIO_DIR, regval); + + /* Set up the falling edge detection */ + + regval = stmpe811_getreg8(priv, STMPE811_GPIO_FE); + if ((pinconfig & STMPE811_GPIO_FALLING) != 0) + { + regval |= pinmask; + } + else + { + regval &= pinmask; + } + stmpe811_putreg8(priv, STMPE811_GPIO_FE, regval); + + /* Set up the rising edge detection */ + + regval = stmpe811_getreg8(priv, STMPE811_GPIO_RE); + if ((pinconfig & STMPE811_GPIO_FALLING) != 0) + { + regval |= pinmask; + } + else + { + regval &= pinmask; + } + stmpe811_putreg8(priv, STMPE811_GPIO_RE, regval); + + /* Disable interrupts for now */ + + regval = stmpe811_getreg8(priv, STMPE811_GPIO_EN); + regval &= ~pinmask; + stmpe811_putreg8(priv, STMPE811_GPIO_EN, regval); + } + + /* Mark the pin as 'in use' */ + + priv->inuse |= pinmask; + sem_post(&priv->exclsem); + return OK; +} + +/**************************************************************************** + * Name: stmpe811_gpiowrite + * + * Description: + * Set or clear the GPIO output + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * pinconfig - Bit-encoded pin configuration + * value = true: write logic '1'; false: write logic '0; + * + * Returned Value: + * None + * + ****************************************************************************/ + +void stmpe811_gpiowrite(STMPE811_HANDLE handle, uint8_t pinconfig, bool value) +{ + FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)handle; + int pin = (pinconfig & STMPE811_GPIO_PIN_MASK) >> STMPE811_GPIO_PIN_SHIFT; + int ret; + + DEBUGASSERT(handle && (unsigned)pin < STMPE811_GPIO_NPINS); + + /* Get exclusive access to the device structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + idbg("sem_wait failed: %d\n", errno); + return; + } + + /* Are we setting or clearing outputs? */ + + if (value) + { + /* Set the output valu(s)e by writing to the SET register */ + + stmpe811_putreg8(priv, STMPE811_GPIO_SETPIN, (1 << pin)); + } + else + { + /* Clear the output value(s) by writing to the CLR register */ + + stmpe811_putreg8(priv, STMPE811_GPIO_CLRPIN, (1 << pin)); + } + + sem_post(&priv->exclsem); +} + +/**************************************************************************** + * Name: stmpe811_gpioread + * + * Description: + * Set or clear the GPIO output + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * pinconfig - Bit-encoded pin configuration + * value - The location to return the state of the GPIO pin + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stmpe811_gpioread(STMPE811_HANDLE handle, uint8_t pinconfig, bool *value) +{ + FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)handle; + int pin = (pinconfig & STMPE811_GPIO_PIN_MASK) >> STMPE811_GPIO_PIN_SHIFT; + uint8_t regval; + int ret; + + DEBUGASSERT(handle && (unsigned)pin < STMPE811_GPIO_NPINS); + + /* Get exclusive access to the device structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + int errval = errno; + idbg("sem_wait failed: %d\n", errval); + return -errval; + } + + regval = stmpe811_getreg8(priv, STMPE811_GPIO_MPSTA); + *value = ((regval & GPIO_PIN(pin)) != 0); + sem_post(&priv->exclsem); + return OK; +} + +/*********************************************************************************** + * Name: stmpe811_gpioattach + * + * Description: + * Attach to a GPIO interrupt input pin and enable interrupts on the pin. Using + * the value NULL for the handler address will disable interrupts from the pin and + * detach the handler. + * + * NOTE: Callbacks do not occur from an interrupt handler but rather from the + * context of the worker thread. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * pinconfig - Bit-encoded pin configuration + * handler - The handler that will be called when the interrupt occurs. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is returned + * to indicate the nature of the failure. + * + ************************************************************************************/ + +#ifndef CONFIG_STMPE811_GPIOINT_DISABLE +int stmpe811_gpioattach(STMPE811_HANDLE handle, uint8_t pinconfig, + stmpe811_handler_t handler) +{ + FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)handle; + int pin = (pinconfig & STMPE811_GPIO_PIN_MASK) >> STMPE811_GPIO_PIN_SHIFT; + uint8_t regval; + int ret; + + DEBUGASSERT(handle && (unsigned)pin < STMPE811_GPIO_NPINS); + + /* Get exclusive access to the device structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + int errval = errno; + idbg("sem_wait failed: %d\n", errval); + return -errval; + } + + /* Make sure that the GPIO interrupt system has been gpioinitialized */ + + stmpe811_gpioinit(priv); + + /* Set/clear the handler */ + + priv->handlers[pin] = handler; + + /* If an handler has provided, then we are enabling interrupts */ + + regval = stmpe811_getreg8(priv, STMPE811_GPIO_EN); + if (handler) + { + /* Enable interrupts for this GPIO */ + + regval &= ~GPIO_PIN(pin); + } + else + { + /* Disable interrupts for this GPIO */ + + regval &= ~GPIO_PIN(pin); + } + stmpe811_putreg8(priv, STMPE811_GPIO_EN, regval); + + sem_post(&priv->exclsem); + return OK; +} +#endif + +/**************************************************************************** + * Name: stmpe811_gpioworker + * + * Description: + * Handle GPIO interrupt events (this function actually executes in the + * context of the worker thread). + * + ****************************************************************************/ + +#ifndef CONFIG_STMPE811_GPIOINT_DISABLE +void stmpe811_gpioworker(FAR struct stmpe811_dev_s *priv) +{ + uint8_t regval; + uint8_t pinmask; + int pin; + + /* Get the set of pending GPIO interrupts */ + + regval = stmpe811_getreg8(priv, STMPE811_GPIO_INTSTA); + + /* Look at each pin */ + + for (pin = 0; pin < STMPE811_GPIO_NPINS; pin++) + { + pinmask = GPIO_INT(pin); + if ((regval & pinmask) != 0) + { + /* Check if we have a handler for this interrupt (there should + * be one) + */ + + if (priv->handlers[pin]) + { + /* Interrupt is pending... dispatch the interrupt to the + * callback + */ + + priv->handlers[pin](pin); + } + else + { + illdbg("No handler for PIN%d, GPIO_INTSTA: %02x\n", pin, regval); + } + + /* Clear the pending GPIO interrupt by writing a '1' to the + * pin position in the status register. + */ + + stmpe811_putreg8(priv, STMPE811_GPIO_INTSTA, pinmask); + } + } +} +#endif + +#endif /* CONFIG_INPUT && CONFIG_INPUT_STMPE811 && !CONFIG_STMPE811_GPIO_DISABLE */ + diff --git a/nuttx/drivers/input/stmpe811_temp.c b/nuttx/drivers/input/stmpe811_temp.c new file mode 100644 index 0000000000..0fefd20699 --- /dev/null +++ b/nuttx/drivers/input/stmpe811_temp.c @@ -0,0 +1,174 @@ +/**************************************************************************** + * drivers/input/stmpe811_temp.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "STMPE811 S-Touch® advanced resistive touchscreen controller with 8-bit + * GPIO expander," Doc ID 14489 Rev 6, CD00186725, STMicroelectronics" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "stmpe811.h" + +#if defined(CONFIG_INPUT) && defined(CONFIG_INPUT_STMPE811) && !defined(CONFIG_STMPE811_TEMP_DISABLE) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stmpe811_tempinitialize + * + * Description: + * Configure the temperature sensor. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stmpe811_tempinitialize(STMPE811_HANDLE handle) +{ + FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)handle; + uint8_t regval; + + /* Enable clocking for ADC and the temperature sensor */ + + regval = stmpe811_getreg8(priv, STMPE811_SYS_CTRL2); + regval &= ~(SYS_CTRL2_TS_OFF | SYS_CTRL2_ADC_OFF); + stmpe811_putreg8(priv, STMPE811_SYS_CTRL2, regval); + + /* Enable the temperature sensor */ + + stmpe811_putreg8(priv, STMPE811_TEMP_CTRL, TEMP_CTRL_ENABLE); + + /* Aquire data enable */ + + stmpe811_putreg8(priv, STMPE811_TEMP_CTRL, (TEMP_CTRL_ACQ|TEMP_CTRL_ENABLE)); + + return OK; +} + +/**************************************************************************** + * Name: stmpe811_tempread + * + * Description: + * Configure the temperature sensor. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +uint16_t stmpe811_tempread(STMPE811_HANDLE handle) +{ + FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)handle; + uint32_t temp = 0; + uint8_t temp1; + uint8_t temp2; + + /* Acquire data enable */ + + stmpe811_putreg8(priv, STMPE811_TEMP_CTRL, (TEMP_CTRL_ACQ|TEMP_CTRL_ENABLE)); + + /* Read the temperature */ + + temp1 = stmpe811_getreg8(priv, STMPE811_SYS_CTRL2); + temp2 = stmpe811_getreg8(priv, STMPE811_SYS_CTRL2+1); + + /* Scale the temperature (where Vio is assumed to be .33) */ + + temp = ((uint32_t)(temp1 & 3) << 8) | temp2; + temp = (uint32_t)((33 * temp * 100) / 751); + temp = (uint32_t)((temp + 5) / 10); + + return (uint16_t)temp; +} + +/**************************************************************************** + * Name: stmpe811_tempinterrupt + * + * Description: + * Configure the temperature sensor to sample the temperature periodically. + * Set the temperature threshold to generate an interrupt and notify + * to the client using the provide callback function pointer. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * threshold - The threshold temperature value + * direction - True: Generate an interrupt if the temperate exceeds the + * threshold value; False: Generate an interrupt if the + * temperature falls below the threshold value. + * callback - The client callback function that will be called when + * the termperature crosses the threshold. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ +/* Not implemented */ + +#endif /* CONFIG_INPUT && CONFIG_INPUT_STMPE811 && !CONFIG_STMPE811_TEMP_DISABLE */ + diff --git a/nuttx/drivers/input/stmpe811_tsc.c b/nuttx/drivers/input/stmpe811_tsc.c new file mode 100644 index 0000000000..e2ab2827d5 --- /dev/null +++ b/nuttx/drivers/input/stmpe811_tsc.c @@ -0,0 +1,1144 @@ +/**************************************************************************** + * drivers/input/stmpe811_tsc.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "STMPE811 S-Touch® advanced resistive touchscreen controller with 8-bit + * GPIO expander," Doc ID 14489 Rev 6, CD00186725, STMicroelectronics" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "stmpe811.h" + +#if defined(CONFIG_INPUT) && defined(CONFIG_INPUT_STMPE811) && !defined(CONFIG_STMPE811_TSC_DISABLE) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define Direction_IN 0x00 +#define Direction_OUT 0x01 + +#define Polarity_Low 0x00 +#define Polarity_High 0x04 +#define Type_Level 0x00 +#define Type_Edge 0x02 + +#define IO_IT_0 0x01 +#define IO_IT_1 0x02 +#define IO_IT_2 0x04 +#define IO_IT_3 0x08 +#define IO_IT_4 0x10 +#define IO_IT_5 0x20 +#define IO_IT_6 0x40 +#define IO_IT_7 0x80 +#define ALL_IT 0xFF +#define IOE_JOY_IT (uint8_t)(IO_IT_3 | IO_IT_4 | IO_IT_5 | IO_IT_6 | IO_IT_7) +#define IOE_TS_IT (uint8_t)(IO_IT_0 | IO_IT_1 | IO_IT_2) +#define IOE_INMEMS_IT (uint8_t)(IO_IT_2 | IO_IT_3) + +#define EDGE_FALLING 0x01 +#define EDGE_RISING 0x02 + +#define TIMEOUT_MAX 0x3000 /*nwaiters > 0) + { + /* After posting this semaphore, we need to exit because the STMPE811 + * is no longer available. + */ + + sem_post(&priv->waitsem); + } + + /* If there are threads waiting on poll() for STMPE811 data to become available, + * then wake them up now. NOTE: we wake up all waiting threads because we + * do not know that they are going to do. If they all try to read the data, + * then some make end up blocking after all. + */ + +#ifndef CONFIG_DISABLE_POLL + for (i = 0; i < CONFIG_STMPE811_NPOLLWAITERS; i++) + { + struct pollfd *fds = priv->fds[i]; + if (fds) + { + fds->revents |= POLLIN; + ivdbg("Report events: %02x\n", fds->revents); + sem_post(fds->sem); + } + } +#endif +} + +/**************************************************************************** + * Name: stmpe811_sample + * + * Description: + * Check if touchscreen sample data is available now and, if so, return + * the sample data. This is part of the stmpe811_read logic. + * + * Assumption: + * Pre-emption is disable to prevent the worker thread from running. + * Otherwise, sampled data may continue to change. + * + ****************************************************************************/ + +static int stmpe811_sample(FAR struct stmpe811_dev_s *priv, + FAR struct stmpe811_sample_s *sample) +{ + int ret = -EAGAIN; + + /* Is there new STMPE811 sample data available? */ + + if (priv->penchange) + { + /* Yes.. the state has changed in some way. Return a copy of the + * sampled data. + */ + + memcpy(sample, &priv->sample, sizeof(struct stmpe811_sample_s)); + + /* Now manage state transitions */ + + if (sample->contact == CONTACT_UP) + { + /* The sampling logic has detected pen-up in some condition other + * than CONTACT_NONE. Set the next state to CONTACT_NONE: Further + * pen-down reports will be ignored. Increment the ID so that + * next contact ID will be unique + */ + + priv->sample.contact = CONTACT_NONE; + priv->sample.valid = false; + priv->id++; + } + else if (sample->contact == CONTACT_DOWN) + { + /* The sampling logic has detected pen-up in some condition other + * than CONTACT_MOVE. Set the next state to CONTACT_MOVE: Further + * samples collected while the pen is down will reported as movement + * events. + */ + + priv->sample.contact = CONTACT_MOVE; + } + + priv->penchange = false; + ret = OK; + } + + return ret; +} + +/**************************************************************************** + * Name: stmpe811_waitsample + * + * Description: + * Wait for a sample to become available (this is really part of the + * stmpe811_read logic). + * + ****************************************************************************/ + +static inline int stmpe811_waitsample(FAR struct stmpe811_dev_s *priv, + FAR struct stmpe811_sample_s *sample) +{ + int ret; + + /* Disable pre-emption to prevent the worker thread from running + * asynchronously. + */ + + sched_lock(); + + /* Now release the semaphore that manages mutually exclusive access to + * the device structure. This may cause other tasks to become ready to + * run, but they cannot run yet because pre-emption is disabled. + */ + + sem_post(&priv->exclsem); + + /* Try to get the a sample... if we cannot, then wait on the semaphore + * that is posted when new sample data is availble. + */ + + while (stmpe811_sample(priv, sample) < 0) + { + /* Wait for a change in the STMPE811 state */ + + priv->nwaiters++; + ret = sem_wait(&priv->waitsem); + priv->nwaiters--; + + /* When we are re-awakened, pre-emption will again be disabled */ + + if (ret < 0) + { +#ifdef CONFIG_DEBUG + // Sample the errno (debug output could change it) + + int errval = errno; + + /* If we are awakened by a signal, then we need to return + * the failure now. + */ + + idbg("ERROR: sem_wait failed: %d\n", errval); + DEBUGASSERT(errval == EINTR); +#endif + ret = -EINTR; + goto errout; + } + } + + /* Re-acquire the the semaphore that manages mutually exclusive access to + * the device structure. We may have to wait here. But we have our sample. + * Interrupts and pre-emption will be re-enabled while we wait. + */ + + ret = sem_wait(&priv->exclsem); + +errout: + /* Restore pre-emption. We might get suspended here but that is okay + * because we already have our sample. Note: this means that if there + * were two threads reading from the STMPE811 for some reason, the data + * might be read out of order. + */ + + sched_unlock(); + return ret; +} + +/**************************************************************************** + * Name: stmpe811_open + * + * Description: + * Standard character driver open method. + * + ****************************************************************************/ + +static int stmpe811_open(FAR struct file *filep) +{ +#ifdef CONFIG_STMPE811_REFCNT + FAR struct inode *inode; + FAR struct stmpe811_dev_s *priv; + uint8_t tmp; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct stmpe811_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Increment the reference count */ + + tmp = priv->crefs + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + goto errout_with_sem; + } + + /* When the reference increments to 1, this is the first open event + * on the driver.. and an opportunity to do any one-time initialization. + */ + + /* Save the new open count on success */ + + priv->crefs = tmp; + +errout_with_sem: + sem_post(&priv->exclsem); + return ret; +#else + return OK; +#endif +} + +/**************************************************************************** + * Name: stmpe811_close + * + * Description: + * Standard character driver close method. + * + ****************************************************************************/ + +static int stmpe811_close(FAR struct file *filep) +{ +#ifdef CONFIG_STMPE811_REFCNT + FAR struct inode *inode; + FAR struct stmpe811_dev_s *priv; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct stmpe811_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Decrement the reference count unless it would decrement a negative + * value. When the count decrements to zero, there are no further + * open references to the driver. + */ + + if (priv->crefs >= 1) + { + priv->crefs--; + } + + sem_post(&priv->exclsem); +#endif + return OK; +} + +/**************************************************************************** + * Name: stmpe811_read + * + * Description: + * Standard character driver read method. + * + ****************************************************************************/ + +static ssize_t stmpe811_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + FAR struct inode *inode; + FAR struct stmpe811_dev_s *priv; + FAR struct touch_sample_s *report; + struct stmpe811_sample_s sample; + int ret; + + ivdbg("len=%d\n", len); + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct stmpe811_dev_s *)inode->i_private; + + /* Verify that the caller has provided a buffer large enough to receive + * the touch data. + */ + + if (len < SIZEOF_TOUCH_SAMPLE_S(1)) + { + /* We could provide logic to break up a touch report into segments and + * handle smaller reads... but why? + */ + + return -ENOSYS; + } + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Try to read sample data. */ + + ret = stmpe811_sample(priv, &sample); + if (ret < 0) + { + /* Sample data is not available now. We would ave to wait to get + * receive sample data. If the user has specified the O_NONBLOCK + * option, then just return an error. + */ + + if (filep->f_oflags & O_NONBLOCK) + { + ret = -EAGAIN; + goto errout; + } + + /* Wait for sample data */ + + ret = stmpe811_waitsample(priv, &sample); + if (ret < 0) + { + /* We might have been awakened by a signal */ + + goto errout; + } + } + + /* In any event, we now have sampled STMPE811 data that we can report + * to the caller. + */ + + report = (FAR struct touch_sample_s *)buffer; + memset(report, 0, SIZEOF_TOUCH_SAMPLE_S(1)); + report->npoints = 1; + report->point[0].id = sample.id; + report->point[0].x = sample.x; + report->point[0].y = sample.y; + report->point[0].pressure = sample.z; + + /* Report the appropriate flags */ + + if (sample.contact == CONTACT_UP) + { + /* Pen is now up. Is the positional data valid? This is important to + * know because the release will be sent to the window based on its + * last positional data. + */ + + if (sample.valid) + { + report->point[0].flags = TOUCH_UP | TOUCH_ID_VALID | + TOUCH_POS_VALID | TOUCH_PRESSURE_VALID; + } + else + { + report->point[0].flags = TOUCH_UP | TOUCH_ID_VALID; + } + } + else if (sample.contact == CONTACT_DOWN) + { + /* First contact */ + + report->point[0].flags = TOUCH_DOWN | TOUCH_ID_VALID | + TOUCH_POS_VALID | TOUCH_PRESSURE_VALID; + } + else /* if (sample->contact == CONTACT_MOVE) */ + { + /* Movement of the same contact */ + + report->point[0].flags = TOUCH_MOVE | TOUCH_ID_VALID | + TOUCH_POS_VALID | TOUCH_PRESSURE_VALID; + } + + ret = SIZEOF_TOUCH_SAMPLE_S(1); + +errout: + sem_post(&priv->exclsem); + return ret; +} + +/**************************************************************************** + * Name: stmpe811_ioctl + * + * Description: + * Standard character driver ioctl method. + * +****************************************************************************/ + +static int stmpe811_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode; + FAR struct stmpe811_dev_s *priv; + int ret; + + ivdbg("cmd: %d arg: %ld\n", cmd, arg); + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct stmpe811_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Process the IOCTL by command */ + + switch (cmd) + { + case TSIOC_SETFREQUENCY: /* arg: Pointer to uint32_t frequency value */ + { + FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg); + DEBUGASSERT(priv->config != NULL && ptr != NULL); + priv->config->frequency = I2C_SETFREQUENCY(priv->i2c, *ptr); + } + break; + + case TSIOC_GETFREQUENCY: /* arg: Pointer to uint32_t frequency value */ + { + FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg); + DEBUGASSERT(priv->config != NULL && ptr != NULL); + *ptr = priv->config->frequency; + } + break; + + default: + ret = -ENOTTY; + break; + } + + sem_post(&priv->exclsem); + return ret; +} + +/**************************************************************************** + * Name: stmpe811_poll + * + * Description: + * Standard character driver poll method. + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static int stmpe811_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct inode *inode; + FAR struct stmpe811_dev_s *priv; + int ret; + int i; + + ivdbg("setup: %d\n", (int)setup); + DEBUGASSERT(filep && fds); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct stmpe811_dev_s *)inode->i_private; + + /* Are we setting up the poll? Or tearing it down? */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + if (setup) + { + /* Ignore waits that do not include POLLIN */ + + if ((fds->events & POLLIN) == 0) + { + idbg("ERROR: Missing POLLIN: revents: %08x\n", fds->revents); + ret = -EDEADLK; + goto errout; + } + + /* This is a request to set up the poll. Find an available + * slot for the poll structure reference + */ + + for (i = 0; i < CONFIG_STMPE811_NPOLLWAITERS; i++) + { + /* Find an available slot */ + + if (!priv->fds[i]) + { + /* Bind the poll structure and this slot */ + + priv->fds[i] = fds; + fds->priv = &priv->fds[i]; + break; + } + } + + if (i >= CONFIG_STMPE811_NPOLLWAITERS) + { + idbg("ERROR: No availabled slot found: %d\n", i); + fds->priv = NULL; + ret = -EBUSY; + goto errout; + } + + /* Should we immediately notify on any of the requested events? */ + + if (priv->penchange) + { + stmpe811_notify(priv); + } + } + else if (fds->priv) + { + /* This is a request to tear down the poll. */ + + struct pollfd **slot = (struct pollfd **)fds->priv; + DEBUGASSERT(slot != NULL); + + /* Remove all memory of the poll setup */ + + *slot = NULL; + fds->priv = NULL; + } + +errout: + sem_post(&priv->exclsem); + return ret; +} +#endif + +/**************************************************************************** + * Name: stmpe811_timeoutworker + * + * Description: + * A timer has expired without receiving a pen up event. Check again. + * + ****************************************************************************/ + +static void stmpe811_timeoutworker(FAR void *arg) +{ + FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)arg; + + DEBUGASSERT(priv); + + /* Treat the timeout just like an interrupt occurred */ + + stmpe811_tscworker(priv, stmpe811_getreg8(priv, STMPE811_INT_STA)); +} + +/**************************************************************************** + * Name: stmpe811_timeout + * + * Description: + * A timer has expired without receiving a pen up event. Schedule work + * to check again. + * + ****************************************************************************/ + +static void stmpe811_timeout(int argc, uint32_t arg1, ...) +{ + FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)((uintptr_t)arg1); + int ret; + + /* Are we still stuck in the pen down state? */ + + if (priv->sample.contact == CONTACT_MOVE || + priv->sample.contact == CONTACT_MOVE) + { + /* Yes... is the worker thread available? If not, then apparently + * we have work already pending? + */ + + if (work_available(&priv->timeout)) + { + /* Yes.. Transfer processing to the worker thread. Since STMPE811 + * interrupts are disabled while the work is pending, no special + * action should be required to protect the work queue. + */ + + ret = work_queue(&priv->timeout, stmpe811_timeoutworker, priv, 0); + if (ret != 0) + { + illdbg("Failed to queue work: %d\n", ret); + } + } + } +} + +/**************************************************************************** + * Name: stmpe811_tscinitialize + * + * Description: + * Initialize the touchscreen controller. This is really a part of the + * stmpe811_register logic, + * + ****************************************************************************/ + +static inline void stmpe811_tscinitialize(FAR struct stmpe811_dev_s *priv) +{ + uint8_t regval; + + ivdbg("Initializing touchscreen controller\n"); + + /* Enable TSC and ADC functions */ + + regval = stmpe811_getreg8(priv, STMPE811_SYS_CTRL2); + regval &= ~(SYS_CTRL2_TSC_OFF | SYS_CTRL2_ADC_OFF); + stmpe811_putreg8(priv, STMPE811_SYS_CTRL2, regval); + + /* Enable the TSC global interrupts */ + + regval = stmpe811_getreg8(priv, STMPE811_INT_EN); + regval |= (uint32_t)(INT_TOUCH_DET | INT_FIFO_TH | INT_FIFO_OFLOW); + stmpe811_putreg8(priv, STMPE811_INT_EN, regval); + + /* Select Sample Time, bit number and ADC Reference */ + + stmpe811_putreg8(priv, STMPE811_ADC_CTRL1, priv->config->ctrl1); + + /* Wait for 20 ms */ + + up_mdelay(20); + + /* Select the ADC clock speed */ + + stmpe811_putreg8(priv, STMPE811_ADC_CTRL2, priv->config->ctrl2); + + /* Select TSC pins in non-GPIO mode (AF=0) */ + + regval = stmpe811_getreg8(priv, STMPE811_GPIO_AF); + regval &= ~(uint8_t)TSC_PIN_SET; + stmpe811_putreg8(priv, STMPE811_GPIO_AF, regval); + + /* Select 2 nF filter capacitor */ + + stmpe811_putreg8(priv, STMPE811_TSC_CFG, + (TSC_CFG_AVE_CTRL_4SAMPLES | TSC_CFG_TOUCH_DELAY_500US | TSC_CFG_SETTLING_500US)); + + /* Select single point reading */ + + stmpe811_putreg8(priv, STMPE811_FIFO_TH, 1); + + /* Reset and clear the FIFO. */ + + stmpe811_putreg8(priv, STMPE811_FIFO_STA, FIFO_STA_FIFO_RESET); + stmpe811_putreg8(priv, STMPE811_FIFO_STA, 0); + + /* set the data format for Z value: 7 fractional part and 1 whole part */ + + stmpe811_putreg8(priv, STMPE811_TSC_FRACTIONZ, 0x01); + + /* Set the driving capability of the device for TSC pins: 50mA */ + + stmpe811_putreg8(priv, STMPE811_TSC_IDRIVE, TSC_IDRIVE_50MA); + + /* Enable the TSC. Use no tracking index, touch-screen controller + * operation mode (XYZ). + */ + + stmpe811_putreg8(priv, STMPE811_TSC_CTRL, TSC_CTRL_EN); + + /* Clear all the status pending bits */ + + stmpe811_putreg8(priv, STMPE811_INT_STA, INT_ALL); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stmpe811_register + * + * Description: + * Enable TSC functionality. GPIO4-7 must be available. This function + * will register the touchsceen driver as /dev/inputN where N is the minor + * device number + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_register + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stmpe811_register(STMPE811_HANDLE handle, int minor) +{ + FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)handle; + char devname[DEV_NAMELEN]; + int ret; + + ivdbg("handle=%p minor=%d\n", handle, minor); + DEBUGASSERT(priv); + + /* Get exclusive access to the device structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + int errval = errno; + idbg("ERROR: sem_wait failed: %d\n", errval); + return -errval; + } + + /* Make sure that the pins (4-7) need by the TSC are not already in use */ + + if ((priv->inuse & TSC_PIN_SET) != 0) + { + idbg("ERROR: TSC pins is already in-use: %02x\n", priv->inuse); + sem_post(&priv->exclsem); + return -EBUSY; + } + + /* Initialize the TS structure fields to their default values */ + + priv->minor = minor; + priv->penchange = false; + priv->threshx = 0; + priv->threshy = 0; + + /* Create a timer for catching missed pen up conditions */ + + priv->wdog = wd_create(); + if (!priv->wdog) + { + idbg("ERROR: Failed to create a watchdog\n", errno); + sem_post(&priv->exclsem); + return -ENOSPC; + } + + /* Register the character driver */ + + snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor); + ret = register_driver(devname, &g_stmpe811fops, 0666, priv); + if (ret < 0) + { + idbg("ERROR: Failed to register driver %s: %d\n", devname, ret); + sem_post(&priv->exclsem); + return ret; + } + + /* Initialize the touchscreen controller */ + + stmpe811_tscinitialize(priv); + + /* Inidicate that the touchscreen controller was successfully initialized */ + + priv->inuse |= TSC_PIN_SET; /* Pins 4-7 are now in-use */ + priv->flags |= STMPE811_FLAGS_TSC_INITIALIZED; /* TSC function is initialized */ + sem_post(&priv->exclsem); + return ret; +} + +/**************************************************************************** + * Name: stmpe811_tscworker + * + * Description: + * This function is called to handle a TSC interrupt. It is not really + * an interrupt handle because it is called from the STMPE811 "bottom half" + * logic that runs on the worker thread. + * + ****************************************************************************/ + +void stmpe811_tscworker(FAR struct stmpe811_dev_s *priv, uint8_t intsta) +{ + FAR struct stmpe811_config_s *config; /* Convenience pointer */ + bool pendown; /* true: pend is down */ + uint16_t xdiff; /* X difference used in thresholding */ + uint16_t ydiff; /* Y difference used in thresholding */ + uint16_t x; /* X position */ + uint16_t y; /* Y position */ + + ASSERT(priv != NULL); + + /* Cancel the missing pen up timer */ + + (void)wd_cancel(priv->wdog); + + /* Get a pointer the callbacks for convenience (and so the code is not so + * ugly). + */ + + config = priv->config; + DEBUGASSERT(config != NULL); + + /* Check for pen up or down from the TSC_STA ibit n the STMPE811_TSC_CTRL register. */ + + pendown = (stmpe811_getreg8(priv, STMPE811_TSC_CTRL) & TSC_CTRL_TSC_STA) != 0; + + /* Handle the change from pen down to pen up */ + + if (!pendown) + { + /* The pen is up.. reset thresholding variables. FIFOs will read zero if + * there is no data available (hence the choice of (0,0)) + */ + + priv->threshx = 0; + priv->threshy = 0; + + /* Ignore the interrupt if the pen was already up (CONTACT_NONE == pen up and + * already reported; CONTACT_UP == pen up, but not reported) + */ + + if (priv->sample.contact == CONTACT_NONE || + priv->sample.contact == CONTACT_UP) + { + goto ignored; + } + + /* A pen-down to up transition has been detected. CONTACT_UP indicates the + * initial loss of contzt. The state will be changed to CONTACT_NONE + * after the loss of contact is sampled. + */ + + priv->sample.contact = CONTACT_UP; + } + + /* The pen is down... check for data in the FIFO */ + + else if ((intsta & (INT_FIFO_TH|INT_FIFO_OFLOW)) != 0) + { + /* Read the next x and y positions from the FIFO. */ + +#ifdef CONFIG_STMPE811_SWAPXY + x = stmpe811_getreg16(priv, STMPE811_TSC_DATAX); + y = stmpe811_getreg16(priv, STMPE811_TSC_DATAY); +#else + x = stmpe811_getreg16(priv, STMPE811_TSC_DATAY); + y = stmpe811_getreg16(priv, STMPE811_TSC_DATAX); +#endif + + /* If we have not yet processed the last pen up event, then we + * cannot handle this pen down event. We will have to discard it. That + * should be okay because there will be another FIFO event right behind + * this one. Other kinds of data overruns are not harmful. + * + * Hmm.. a better design might be to disable FIFO interrupts when we + * detect pen up. Then re-enable them when CONTACT_UP is reported. + * That would save processing interrupts just to discard the data. + */ + + if (priv->sample.contact == CONTACT_UP) + { + /* We have not closed the loop on the last touch ... don't report + * anything. + */ + + goto ignored; + } + + /* Perform a thresholding operation so that the results will be more stable. + * If the difference from the last sample is small, then ignore the event. + * REVISIT: Should a large change in pressure also generate a event? + */ + + xdiff = x > priv->threshx ? (x - priv->threshx) : (priv->threshx - x); + ydiff = y > priv->threshy ? (y - priv->threshy) : (priv->threshy - y); + + if (xdiff < CONFIG_STMPE811_THRESHX && ydiff < CONFIG_STMPE811_THRESHY) + { + /* Little or no change in either direction ... don't report anything. */ + + goto ignored; + } + + /* When we see a big difference, snap to the new x/y thresholds */ + + priv->threshx = x; + priv->threshy = y; + + /* Update the x/y position in the sample data */ + + priv->sample.x = priv->threshx; + priv->sample.y = priv->threshy; + + /* Update the Z pressure index */ + + priv->sample.z = stmpe811_getreg8(priv, STMPE811_TSC_DATAZ); + priv->sample.valid = true; + + /* If this is the first (acknowledged) pen down report, then report + * this as the first contact. If contact == CONTACT_DOWN, it will be + * set to set to CONTACT_MOVE after the contact is first sampled. + */ + + if (priv->sample.contact != CONTACT_MOVE) + { + /* First contact */ + + priv->sample.contact = CONTACT_DOWN; + } + } + + /* Pen down, but no data in FIFO */ + + else + { + /* Ignore the interrupt... wait until there is data in the FIFO */ + + goto ignored; + } + + /* We get here if (1) we just went from a pen down to a pen up state OR (2) + * We just get a measurement from the FIFO in a pen down state. Indicate + * the availability of new sample data for this ID. + */ + + priv->sample.id = priv->id; + priv->penchange = true; + + /* Notify any waiters that new STMPE811 data is available */ + + stmpe811_notify(priv); + + /* If we think that the pend is still down, the start/re-start the pen up + * timer. + */ + +ignored: + if (priv->sample.contact == CONTACT_MOVE || + priv->sample.contact == CONTACT_MOVE) + { + (void)wd_start(priv->wdog, STMPE811_PENUP_TICKS, stmpe811_timeout, + 1, (uint32_t)((uintptr_t)priv)); + } + + /* Reset and clear all data in the FIFO */ + + stmpe811_putreg8(priv, STMPE811_FIFO_STA, FIFO_STA_FIFO_RESET); + stmpe811_putreg8(priv, STMPE811_FIFO_STA, 0); +} + +#endif /* CONFIG_INPUT && CONFIG_INPUT_STMPE811 && !CONFIG_STMPE811_TSC_DISABLE */ + diff --git a/nuttx/drivers/input/tsc2007.c b/nuttx/drivers/input/tsc2007.c new file mode 100644 index 0000000000..07acb53712 --- /dev/null +++ b/nuttx/drivers/input/tsc2007.c @@ -0,0 +1,1336 @@ +/**************************************************************************** + * drivers/input/tsc2007.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "1.2V to 3.6V, 12-Bit, Nanopower, 4-Wire Micro TOUCH SCREEN CONTROLLER + * with I2C Interface," SBAS405A March 2007, Revised, March 2009, Texas + * Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* The TSC2007 is an analog interface circuit for a human interface touch + * screen device. All peripheral functions are controlled through the command + * byte and onboard state machines. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "tsc2007.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* Reference counting is partially implemented, but not needed in the + * current design. + */ + +#undef CONFIG_TSC2007_REFCNT + +/* I don't think that it is necessary to activate the converters before + * making meaurements. However, I will keep this functionality enabled + * until I have a change to prove that that activation is unnecessary. + */ + +#undef CONFIG_TSC2007_ACTIVATE +#define CONFIG_TSC2007_ACTIVATE 1 + +/* Driver support ***********************************************************/ +/* This format is used to construct the /dev/input[n] device driver path. It + * defined here so that it will be used consistently in all places. + */ + +#define DEV_FORMAT "/dev/input%d" +#define DEV_NAMELEN 16 + +/* Commands *****************************************************************/ + +#define TSC2007_SETUP (TSC2007_CMD_FUNC_SETUP) +#ifdef CONFIG_TSC2007_8BIT +# define TSC2007_ACTIVATE_Y (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YON) +# define TSC2007_MEASURE_Y (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YPOS) +# define TSC2007_ACTIVATE_X (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XON) +# define TSC2007_MEASURE_X (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XPOS) +# define TSC2007_ACTIVATE_Z (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YXON) +# define TSC2007_MEASURE_Z1 (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z1POS) +# define TSC2007_MEASURE_Z2 (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z2POS) +# define TSC2007_ENABLE_PENIRQ (TSC2007_CMD_8BIT | TSC2007_CMD_PWRDN_IRQEN) +#else +# define TSC2007_ACTIVATE_Y (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YON) +# define TSC2007_MEASURE_Y (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YPOS) +# define TSC2007_ACTIVATE_X (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XON) +# define TSC2007_MEASURE_X (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XPOS) +# define TSC2007_ACTIVATE_Z (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YXON) +# define TSC2007_MEASURE_Z1 (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z1POS) +# define TSC2007_MEASURE_Z2 (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z2POS) +# define TSC2007_ENABLE_PENIRQ (TSC2007_CMD_12BIT | TSC2007_CMD_PWRDN_IRQEN) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This describes the state of one contact */ + +enum tsc2007_contact_3 +{ + CONTACT_NONE = 0, /* No contact */ + CONTACT_DOWN, /* First contact */ + CONTACT_MOVE, /* Same contact, possibly different position */ + CONTACT_UP, /* Contact lost */ +}; + +/* This structure describes the results of one TSC2007 sample */ + +struct tsc2007_sample_s +{ + uint8_t id; /* Sampled touch point ID */ + uint8_t contact; /* Contact state (see enum tsc2007_contact_e) */ + bool valid; /* True: x,y,pressure contain valid, sampled data */ + uint16_t x; /* Measured X position */ + uint16_t y; /* Measured Y position */ + uint16_t pressure; /* Calculated pressure */ +}; + +/* This structure describes the state of one TSC2007 driver instance */ + +struct tsc2007_dev_s +{ +#ifdef CONFIG_TSC2007_MULTIPLE + FAR struct tsc2007_dev_s *flink; /* Supports a singly linked list of drivers */ +#endif +#ifdef CONFIG_TSC2007_REFCNT + uint8_t crefs; /* Number of times the device has been opened */ +#endif + uint8_t nwaiters; /* Number of threads waiting for TSC2007 data */ + uint8_t id; /* Current touch point ID */ + volatile bool penchange; /* An unreported event is buffered */ + sem_t devsem; /* Manages exclusive access to this structure */ + sem_t waitsem; /* Used to wait for the availability of data */ + + FAR struct tsc2007_config_s *config; /* Board configuration data */ + FAR struct i2c_dev_s *i2c; /* Saved I2C driver instance */ + struct work_s work; /* Supports the interrupt handling "bottom half" */ + struct tsc2007_sample_s sample; /* Last sampled touch point data */ + + /* The following is a list if poll structures of threads waiting for + * driver events. The 'struct pollfd' reference for each open is also + * retained in the f_priv field of the 'struct file'. + */ + +#ifndef CONFIG_DISABLE_POLL + struct pollfd *fds[CONFIG_TSC2007_NPOLLWAITERS]; +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void tsc2007_notify(FAR struct tsc2007_dev_s *priv); +static int tsc2007_sample(FAR struct tsc2007_dev_s *priv, + FAR struct tsc2007_sample_s *sample); +static int tsc2007_waitsample(FAR struct tsc2007_dev_s *priv, + FAR struct tsc2007_sample_s *sample); +#ifdef CONFIG_TSC2007_ACTIVATE +static int tsc2007_activate(FAR struct tsc2007_dev_s *priv, uint8_t cmd); +#endif +static int tsc2007_transfer(FAR struct tsc2007_dev_s *priv, uint8_t cmd); +static void tsc2007_worker(FAR void *arg); +static int tsc2007_interrupt(int irq, FAR void *context); + +/* Character driver methods */ + +static int tsc2007_open(FAR struct file *filep); +static int tsc2007_close(FAR struct file *filep); +static ssize_t tsc2007_read(FAR struct file *filep, FAR char *buffer, size_t len); +static int tsc2007_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +#ifndef CONFIG_DISABLE_POLL +static int tsc2007_poll(FAR struct file *filep, struct pollfd *fds, bool setup); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This the the vtable that supports the character driver interface */ + +static const struct file_operations tsc2007_fops = +{ + tsc2007_open, /* open */ + tsc2007_close, /* close */ + tsc2007_read, /* read */ + 0, /* write */ + 0, /* seek */ + tsc2007_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , tsc2007_poll /* poll */ +#endif +}; + +/* If only a single TSC2007 device is supported, then the driver state + * structure may as well be pre-allocated. + */ + +#ifndef CONFIG_TSC2007_MULTIPLE +static struct tsc2007_dev_s g_tsc2007; + +/* Otherwise, we will need to maintain allocated driver instances in a list */ + +#else +static struct tsc2007_dev_s *g_tsc2007list; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tsc2007_notify + ****************************************************************************/ + +static void tsc2007_notify(FAR struct tsc2007_dev_s *priv) +{ +#ifndef CONFIG_DISABLE_POLL + int i; +#endif + + /* If there are threads waiting for read data, then signal one of them + * that the read data is available. + */ + + if (priv->nwaiters > 0) + { + /* After posting this semaphore, we need to exit because the TSC2007 + * is no longer available. + */ + + sem_post(&priv->waitsem); + } + + /* If there are threads waiting on poll() for TSC2007 data to become available, + * then wake them up now. NOTE: we wake up all waiting threads because we + * do not know that they are going to do. If they all try to read the data, + * then some make end up blocking after all. + */ + +#ifndef CONFIG_DISABLE_POLL + for (i = 0; i < CONFIG_TSC2007_NPOLLWAITERS; i++) + { + struct pollfd *fds = priv->fds[i]; + if (fds) + { + fds->revents |= POLLIN; + ivdbg("Report events: %02x\n", fds->revents); + sem_post(fds->sem); + } + } +#endif +} + +/**************************************************************************** + * Name: tsc2007_sample + ****************************************************************************/ + +static int tsc2007_sample(FAR struct tsc2007_dev_s *priv, + FAR struct tsc2007_sample_s *sample) +{ + irqstate_t flags; + int ret = -EAGAIN; + + /* Interrupts me be disabled when this is called to (1) prevent posting + * of semphores from interrupt handlers, and (2) to prevent sampled data + * from changing until it has been reported. + */ + + flags = irqsave(); + + /* Is there new TSC2007 sample data available? */ + + if (priv->penchange) + { + /* Yes.. the state has changed in some way. Return a copy of the + * sampled data. + */ + + memcpy(sample, &priv->sample, sizeof(struct tsc2007_sample_s )); + + /* Now manage state transitions */ + + if (sample->contact == CONTACT_UP) + { + /* Next.. no contact. Increment the ID so that next contact ID + * will be unique. X/Y positions are no longer valid. + */ + + priv->sample.contact = CONTACT_NONE; + priv->sample.valid = false; + priv->id++; + } + else if (sample->contact == CONTACT_DOWN) + { + /* First report -- next report will be a movement */ + + priv->sample.contact = CONTACT_MOVE; + } + + priv->penchange = false; + ret = OK; + } + + irqrestore(flags); + return ret; +} + +/**************************************************************************** + * Name: tsc2007_waitsample + ****************************************************************************/ + +static int tsc2007_waitsample(FAR struct tsc2007_dev_s *priv, + FAR struct tsc2007_sample_s *sample) +{ + irqstate_t flags; + int ret; + + /* Interrupts me be disabled when this is called to (1) prevent posting + * of semphores from interrupt handlers, and (2) to prevent sampled data + * from changing until it has been reported. + * + * In addition, we will also disable pre-emption to prevent other threads + * from getting control while we muck with the semaphores. + */ + + sched_lock(); + flags = irqsave(); + + /* Now release the semaphore that manages mutually exclusive access to + * the device structure. This may cause other tasks to become ready to + * run, but they cannot run yet because pre-emption is disabled. + */ + + sem_post(&priv->devsem); + + /* Try to get the a sample... if we cannot, then wait on the semaphore + * that is posted when new sample data is availble. + */ + + while (tsc2007_sample(priv, sample) < 0) + { + /* Wait for a change in the TSC2007 state */ + + priv->nwaiters++; + ret = sem_wait(&priv->waitsem); + priv->nwaiters--; + + if (ret < 0) + { + /* If we are awakened by a signal, then we need to return + * the failure now. + */ + + DEBUGASSERT(errno == EINTR); + ret = -EINTR; + goto errout; + } + } + + /* Re-acquire the the semaphore that manages mutually exclusive access to + * the device structure. We may have to wait here. But we have our sample. + * Interrupts and pre-emption will be re-enabled while we wait. + */ + + ret = sem_wait(&priv->devsem); + +errout: + /* Then re-enable interrupts. We might get interrupt here and there + * could be a new sample. But no new threads will run because we still + * have pre-emption disabled. + */ + + irqrestore(flags); + + /* Restore pre-emption. We might get suspended here but that is okay + * because we already have our sample. Note: this means that if there + * were two threads reading from the TSC2007 for some reason, the data + * might be read out of order. + */ + + sched_unlock(); + return ret; +} + +/**************************************************************************** + * Name: tsc2007_activate + ****************************************************************************/ + +#ifdef CONFIG_TSC2007_ACTIVATE +static int tsc2007_activate(FAR struct tsc2007_dev_s *priv, uint8_t cmd) +{ + struct i2c_msg_s msg; + uint8_t data; + int ret; + + /* Send the setup command (with no ACK) followed by the A/D converter + * activation command (ACKed). + */ + + data = TSC2007_SETUP; + + msg.addr = priv->config->address; /* 7-bit address */ + msg.flags = 0; /* Write transaction, beginning with START */ + msg.buffer = &data; /* Transfer from this address */ + msg.length = 1; /* Send one byte following the address */ + + /* Ignore errors from the setup command (because it is not ACKed) */ + + (void)I2C_TRANSFER(priv->i2c, &msg, 1); + + /* Now activate the A/D converter */ + + data = cmd; + + msg.addr = priv->config->address; /* 7-bit address */ + msg.flags = 0; /* Write transaction, beginning with START */ + msg.buffer = &data; /* Transfer from this address */ + msg.length = 1; /* Send one byte following the address */ + + ret = I2C_TRANSFER(priv->i2c, &msg, 1); + if (ret < 0) + { + idbg("I2C_TRANSFER failed: %d\n", ret); + } + return ret; +} +#else +# define tsc2007_activate(p,c) +#endif + +/**************************************************************************** + * Name: tsc2007_transfer + ****************************************************************************/ + +static int tsc2007_transfer(FAR struct tsc2007_dev_s *priv, uint8_t cmd) +{ + struct i2c_msg_s msg; + uint8_t data12[2]; + int ret; + + /* "A conversion/write cycle begins when the master issues the address + * byte containing the slave address of the TSC2007, with the eighth bit + * equal to a 0 (R/W = 0)... Once the eighth bit has been received... + * the TSC2007 issues an acknowledge. + * + * "When the master receives the acknowledge bit from the TSC2007, the + * master writes the command byte to the slave... After the command byte + * is received by the slave, the slave issues another acknowledge bit. + * The master then ends the write cycle by issuing a repeated START or a + * STOP condition... + */ + + msg.addr = priv->config->address; /* 7-bit address */ + msg.flags = 0; /* Write transaction, beginning with START */ + msg.buffer = &cmd; /* Transfer from this address */ + msg.length = 1; /* Send one byte following the address */ + + ret = I2C_TRANSFER(priv->i2c, &msg, 1); + if (ret < 0) + { + idbg("I2C_TRANSFER failed: %d\n", ret); + return ret; + } + + /* "The input multiplexer channel for the A/D converter is selected when + * bits C3 through C0 are clocked in. If the selected channel is an X-,Y-, + * or Z-position measurement, the appropriate drivers turn on once the + * acquisition period begins. + * + * "... the input sample acquisition period starts on the falling edge of + * SCL when the C0 bit of the command byte has been latched, and ends + * when a STOP or repeated START condition has been issued. A/D conversion + * starts immediately after the acquisition period... + * + * "For best performance, the I2C bus should remain in an idle state while + * an A/D conversion is taking place. ... The master should wait for at + * least 10ms before attempting to read data from the TSC2007... + */ + + usleep(10*1000); + + /* "Data access begins with the master issuing a START condition followed + * by the address byte ... with R/W = 1. + * + * "When the eighth bit has been received and the address matches, the + * slave issues an acknowledge. The first byte of serial data then follows + * (D11-D4, MSB first). + * + * "After the first byte has been sent by the slave, it releases the SDA line + * for the master to issue an acknowledge. The slave responds with the + * second byte of serial data upon receiving the acknowledge from the master + * (D3-D0, followed by four 0 bits). The second byte is followed by a NOT + * acknowledge bit (ACK = 1) from the master to indicate that the last + * data byte has been received... + */ + + msg.addr = priv->config->address; /* 7-bit address */ + msg.flags = I2C_M_READ; /* Read transaction, beginning with START */ + msg.buffer = data12; /* Transfer to this address */ + msg.length = 2; /* Read two bytes following the address */ + + ret = I2C_TRANSFER(priv->i2c, &msg, 1); + if (ret < 0) + { + idbg("I2C_TRANSFER failed: %d\n", ret); + return ret; + } + + /* Get the MS 8 bits from the first byte and the remaining LS 4 bits from + * the second byte. The valid range of data is then from 0 to 4095 with + * the LSB unit corresponding to Vref/4096. + */ + + ret = (unsigned int)data12[0] << 4 | (unsigned int)data12[1] >> 4; + ivdbg("data: 0x%04x\n", ret); + return ret; +} + +/**************************************************************************** + * Name: tsc2007_worker + ****************************************************************************/ + +static void tsc2007_worker(FAR void *arg) +{ + FAR struct tsc2007_dev_s *priv = (FAR struct tsc2007_dev_s *)arg; + FAR struct tsc2007_config_s *config; /* Convenience pointer */ + bool pendown; /* true: pend is down */ + uint16_t x; /* X position */ + uint16_t y; /* Y position */ + uint16_t z1; /* Z1 position */ + uint16_t z2; /* Z2 position */ + uint32_t pressure; /* Measured pressure */ + + ASSERT(priv != NULL); + + /* Get a pointer the callbacks for convenience (and so the code is not so + * ugly). + */ + + config = priv->config; + DEBUGASSERT(config != NULL); + + /* Check for pen up or down by reading the PENIRQ GPIO. */ + + pendown = config->pendown(config); + + /* Handle the change from pen down to pen up */ + + if (!pendown) + { + /* Ignore the interrupt if the pen was already down (CONTACT_NONE == pen up and + * already reported. CONTACT_UP == pen up, but not reported) + */ + + if (priv->sample.contact == CONTACT_NONE) + { + goto errout; + } + } + + /* It is a pen down event. If the last loss-of-contact event has not been + * processed yet, then we have to ignore the pen down event (or else it will + * look like a drag event) + */ + + else if (priv->sample.contact == CONTACT_UP) + { + goto errout; + } + else + { + /* Handle all pen down events. First, sample X, Y, Z1, and Z2 values. + * + * "A resistive touch screen operates by applying a voltage across a + * resistor network and measuring the change in resistance at a given + * point on the matrix where the screen is touched by an input (stylus, + * pen, or finger). The change in the resistance ratio marks the location + * on the touch screen. + * + * "The 4-wire touch screen panel works by applying a voltage across the + * vertical or horizontal resistive network. The A/D converter converts + * the voltage measured at the point where the panel is touched. A measurement + * of the Y position of the pointing device is made by connecting the X+ + * input to a data converter chip, turning on the Y+ and Y– drivers, and + * digitizing the voltage seen at the X+ input ..." + * + * "... it is recommended that whenever the host writes to the TSC2007, the + * master processor masks the interrupt associated to PENIRQ. This masking + * prevents false triggering of interrupts when the PENIRQ line is disabled + * in the cases previously listed." + */ + + (void)tsc2007_activate(priv, TSC2007_ACTIVATE_X); + y = tsc2007_transfer(priv, TSC2007_MEASURE_Y); + + + /* "Voltage is then applied to the other axis, and the A/D converter + * converts the voltage representing the X position on the screen. This + * process provides the X and Y coordinates to the associated processor." + */ + + (void)tsc2007_activate(priv, TSC2007_ACTIVATE_Y); + x = tsc2007_transfer(priv, TSC2007_MEASURE_X); + + /* "... To determine pen or finger touch, the pressure of the touch must be + * determined. ... There are several different ways of performing this + * measurement. The TSC2007 supports two methods. The first method requires + * knowing the X-plate resistance, the measurement of the X-position, and two + * additional cross panel measurements (Z2 and Z1) of the touch screen." + * + * Rtouch = Rxplate * (X / 4096)* (Z2/Z1 - 1) + * + * "The second method requires knowing both the X-plate and Y-plate + * resistance, measurement of X-position and Y-position, and Z1 ..." + * + * Rtouch = Rxplate * (X / 4096) * (4096/Z1 - 1) - Ryplate * (1 - Y/4096) + * + * Read Z1 and Z2 values. + */ + + (void)tsc2007_activate(priv, TSC2007_ACTIVATE_Z); + z1 = tsc2007_transfer(priv, TSC2007_MEASURE_Z1); + (void)tsc2007_activate(priv, TSC2007_ACTIVATE_Z); + z2 = tsc2007_transfer(priv, TSC2007_MEASURE_Z2); + + /* Power down ADC and enable PENIRQ */ + + (void)tsc2007_transfer(priv, TSC2007_ENABLE_PENIRQ); + + /* Now calculate the pressure using the first method, reduced to: + * + * Rtouch = X * Rxplate *(Z2 - Z1) * / Z1 / 4096 + */ + + if (z1 == 0) + { + idbg("Z1 zero\n"); + pressure = 0; + } + else + { + pressure = (x * config->rxplate * (z2 - z1)) / z1; + pressure = (pressure + 2048) >> 12; + + ivdbg("Position: (%d,%4d) pressure: %u z1/2: (%d,%d)\n", + x, y, pressure, z1, z2); + + /* Ignore out of range caculcations */ + + if (pressure > 0x0fff) + { + idbg("Dropped out-of-range pressure: %d\n", pressure); + pressure = 0; + } + } + + /* Save the measurements */ + + priv->sample.x = x; + priv->sample.y = y; + priv->sample.pressure = pressure; + priv->sample.valid = true; + } + + /* Note the availability of new measurements */ + + if (pendown) + { + /* If this is the first (acknowledged) pend down report, then report + * this as the first contact. If contact == CONTACT_DOWN, it will be + * set to set to CONTACT_MOVE after the contact is first sampled. + */ + + if (priv->sample.contact != CONTACT_MOVE) + { + /* First contact */ + + priv->sample.contact = CONTACT_DOWN; + } + } + else /* if (priv->sample.contact != CONTACT_NONE) */ + { + /* The pen is up. NOTE: We know from a previous test, that this is a + * loss of contact condition. This will be changed to CONTACT_NONE + * after the loss of contact is sampled. + */ + + priv->sample.contact = CONTACT_UP; + } + + /* Indicate the availability of new sample data for this ID */ + + priv->sample.id = priv->id; + priv->penchange = true; + + /* Notify any waiters that nes TSC2007 data is available */ + + tsc2007_notify(priv); + + /* Exit, re-enabling TSC2007 interrupts */ + +errout: + config->enable(config, true); +} + +/**************************************************************************** + * Name: tsc2007_interrupt + ****************************************************************************/ + +static int tsc2007_interrupt(int irq, FAR void *context) +{ + FAR struct tsc2007_dev_s *priv; + FAR struct tsc2007_config_s *config; + int ret; + + /* Which TSC2007 device caused the interrupt? */ + +#ifndef CONFIG_TSC2007_MULTIPLE + priv = &g_tsc2007; +#else + for (priv = g_tsc2007list; + priv && priv->configs->irq != irq; + priv = priv->flink); + + ASSERT(priv != NULL); +#endif + + /* Get a pointer the callbacks for convenience (and so the code is not so + * ugly). + */ + + config = priv->config; + DEBUGASSERT(config != NULL); + + /* Disable further interrupts */ + + config->enable(config, false); + + /* Transfer processing to the worker thread. Since TSC2007 interrupts are + * disabled while the work is pending, no special action should be required + * to protected the work queue. + */ + + DEBUGASSERT(priv->work.worker == NULL); + ret = work_queue(&priv->work, tsc2007_worker, priv, 0); + if (ret != 0) + { + illdbg("Failed to queue work: %d\n", ret); + } + + /* Clear any pending interrupts and return success */ + + config->clear(config); + return OK; +} + +/**************************************************************************** + * Name: tsc2007_open + ****************************************************************************/ + +static int tsc2007_open(FAR struct file *filep) +{ +#ifdef CONFIG_TSC2007_REFCNT + FAR struct inode *inode; + FAR struct tsc2007_dev_s *priv; + uint8_t tmp; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct tsc2007_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Increment the reference count */ + + tmp = priv->crefs + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + goto errout_with_sem; + } + + /* When the reference increments to 1, this is the first open event + * on the driver.. and an opportunity to do any one-time initialization. + */ + + /* Save the new open count on success */ + + priv->crefs = tmp; + +errout_with_sem: + sem_post(&priv->devsem); + return ret; +#else + return OK; +#endif +} + +/**************************************************************************** + * Name: tsc2007_close + ****************************************************************************/ + +static int tsc2007_close(FAR struct file *filep) +{ +#ifdef CONFIG_TSC2007_REFCNT + FAR struct inode *inode; + FAR struct tsc2007_dev_s *priv; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct tsc2007_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Decrement the reference count unless it would decrement a negative + * value. When the count decrements to zero, there are no further + * open references to the driver. + */ + + if (priv->crefs >= 1) + { + priv->crefs--; + } + + sem_post(&priv->devsem); +#endif + return OK; +} + +/**************************************************************************** + * Name: tsc2007_read + ****************************************************************************/ + +static ssize_t tsc2007_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + FAR struct inode *inode; + FAR struct tsc2007_dev_s *priv; + FAR struct touch_sample_s *report; + struct tsc2007_sample_s sample; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct tsc2007_dev_s *)inode->i_private; + + /* Verify that the caller has provided a buffer large enough to receive + * the touch data. + */ + + if (len < SIZEOF_TOUCH_SAMPLE_S(1)) + { + /* We could provide logic to break up a touch report into segments and + * handle smaller reads... but why? + */ + + return -ENOSYS; + } + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Try to read sample data. */ + + ret = tsc2007_sample(priv, &sample); + if (ret < 0) + { + /* Sample data is not available now. We would ave to wait to get + * receive sample data. If the user has specified the O_NONBLOCK + * option, then just return an error. + */ + + if (filep->f_oflags & O_NONBLOCK) + { + ret = -EAGAIN; + goto errout; + } + + /* Wait for sample data */ + + ret = tsc2007_waitsample(priv, &sample); + if (ret < 0) + { + /* We might have been awakened by a signal */ + + goto errout; + } + } + + /* In any event, we now have sampled TSC2007 data that we can report + * to the caller. + */ + + report = (FAR struct touch_sample_s *)buffer; + memset(report, 0, SIZEOF_TOUCH_SAMPLE_S(1)); + report->npoints = 1; + report->point[0].id = priv->id; + report->point[0].x = sample.x; + report->point[0].y = sample.y; + report->point[0].pressure = sample.pressure; + + /* Report the appropriate flags */ + + if (sample.contact == CONTACT_UP) + { + /* Pen is now up. Is the positional data valid? This is important to + * know because the release will be sent to the window based on its + * last positional data. + */ + + if (sample.valid) + { + report->point[0].flags = TOUCH_UP | TOUCH_ID_VALID | + TOUCH_POS_VALID | TOUCH_PRESSURE_VALID; + } + else + { + report->point[0].flags = TOUCH_UP | TOUCH_ID_VALID; + } + } + else + { + if (sample.contact == CONTACT_DOWN) + { + /* First contact */ + + report->point[0].flags = TOUCH_DOWN | TOUCH_ID_VALID | TOUCH_POS_VALID; + } + else /* if (sample->contact == CONTACT_MOVE) */ + { + /* Movement of the same contact */ + + report->point[0].flags = TOUCH_MOVE | TOUCH_ID_VALID | TOUCH_POS_VALID; + } + + /* A pressure measurement of zero means that pressure is not available */ + + if (report->point[0].pressure != 0) + { + report->point[0].flags |= TOUCH_PRESSURE_VALID; + } + } + + ret = SIZEOF_TOUCH_SAMPLE_S(1); + +errout: + sem_post(&priv->devsem); + return ret; +} + +/**************************************************************************** + * Name:tsc2007_ioctl + ****************************************************************************/ + +static int tsc2007_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode; + FAR struct tsc2007_dev_s *priv; + int ret; + + ivdbg("cmd: %d arg: %ld\n", cmd, arg); + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct tsc2007_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Process the IOCTL by command */ + + switch (cmd) + { + case TSIOC_SETCALIB: /* arg: Pointer to int calibration value */ + { + FAR int *ptr = (FAR int *)((uintptr_t)arg); + DEBUGASSERT(priv->config != NULL && ptr != NULL); + priv->config->rxplate = *ptr; + } + break; + + case TSIOC_GETCALIB: /* arg: Pointer to int calibration value */ + { + FAR int *ptr = (FAR int *)((uintptr_t)arg); + DEBUGASSERT(priv->config != NULL && ptr != NULL); + *ptr = priv->config->rxplate; + } + break; + + case TSIOC_SETFREQUENCY: /* arg: Pointer to uint32_t frequency value */ + { + FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg); + DEBUGASSERT(priv->config != NULL && ptr != NULL); + priv->config->frequency = I2C_SETFREQUENCY(priv->i2c, *ptr); + } + break; + + case TSIOC_GETFREQUENCY: /* arg: Pointer to uint32_t frequency value */ + { + FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg); + DEBUGASSERT(priv->config != NULL && ptr != NULL); + *ptr = priv->config->frequency; + } + break; + + default: + ret = -ENOTTY; + break; + } + + sem_post(&priv->devsem); + return ret; +} + +/**************************************************************************** + * Name: tsc2007_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static int tsc2007_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct inode *inode; + FAR struct tsc2007_dev_s *priv; + int ret; + int i; + + ivdbg("setup: %d\n", (int)setup); + DEBUGASSERT(filep && fds); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct tsc2007_dev_s *)inode->i_private; + + /* Are we setting up the poll? Or tearing it down? */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + if (setup) + { + /* Ignore waits that do not include POLLIN */ + + if ((fds->events & POLLIN) == 0) + { + idbg("Missing POLLIN: revents: %08x\n", fds->revents); + ret = -EDEADLK; + goto errout; + } + + /* This is a request to set up the poll. Find an available + * slot for the poll structure reference + */ + + for (i = 0; i < CONFIG_TSC2007_NPOLLWAITERS; i++) + { + /* Find an available slot */ + + if (!priv->fds[i]) + { + /* Bind the poll structure and this slot */ + + priv->fds[i] = fds; + fds->priv = &priv->fds[i]; + break; + } + } + + if (i >= CONFIG_TSC2007_NPOLLWAITERS) + { + idbg("No availabled slot found: %d\n", i); + fds->priv = NULL; + ret = -EBUSY; + goto errout; + } + + /* Should we immediately notify on any of the requested events? */ + + if (priv->penchange) + { + tsc2007_notify(priv); + } + } + else if (fds->priv) + { + /* This is a request to tear down the poll. */ + + struct pollfd **slot = (struct pollfd **)fds->priv; + DEBUGASSERT(slot != NULL); + + /* Remove all memory of the poll setup */ + + *slot = NULL; + fds->priv = NULL; + } + +errout: + sem_post(&priv->devsem); + return ret; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tsc2007_register + * + * Description: + * Configure the TSC2007 to use the provided I2C device instance. This + * will register the driver as /dev/inputN where N is the minor device + * number + * + * Input Parameters: + * dev - An I2C driver instance + * config - Persistant board configuration data + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int tsc2007_register(FAR struct i2c_dev_s *dev, + FAR struct tsc2007_config_s *config, int minor) +{ + FAR struct tsc2007_dev_s *priv; + char devname[DEV_NAMELEN]; +#ifdef CONFIG_TSC2007_MULTIPLE + irqstate_t flags; +#endif + int ret; + + ivdbg("dev: %p minor: %d\n", dev, minor); + + /* Debug-only sanity checks */ + + DEBUGASSERT(dev != NULL && config != NULL && minor >= 0 && minor < 100); + DEBUGASSERT((config->address & 0xfc) == 0x48); + DEBUGASSERT(config->attach != NULL && config->enable != NULL && + config->clear != NULL && config->pendown != NULL); + + /* Create and initialize a TSC2007 device driver instance */ + +#ifndef CONFIG_TSC2007_MULTIPLE + priv = &g_tsc2007; +#else + priv = (FAR struct tsc2007_dev_s *)kmalloc(sizeof(struct tsc2007_dev_s)); + if (!priv) + { + idbg("kmalloc(%d) failed\n", sizeof(struct tsc2007_dev_s)); + return -ENOMEM; + } +#endif + + /* Initialize the TSC2007 device driver instance */ + + memset(priv, 0, sizeof(struct tsc2007_dev_s)); + priv->i2c = dev; /* Save the I2C device handle */ + priv->config = config; /* Save the board configuration */ + sem_init(&priv->devsem, 0, 1); /* Initialize device structure semaphore */ + sem_init(&priv->waitsem, 0, 0); /* Initialize pen event wait semaphore */ + + /* Set the I2C frequency (saving the actual frequency) */ + + config->frequency = I2C_SETFREQUENCY(dev, config->frequency); + + /* Set the I2C address and address size */ + + ret = I2C_SETADDRESS(dev, config->address, 7); + if (ret < 0) + { + idbg("I2C_SETADDRESS failed: %d\n", ret); + goto errout_with_priv; + } + + /* Make sure that interrupts are disabled */ + + config->clear(config); + config->enable(config, false); + + /* Attach the interrupt handler */ + + ret = config->attach(config, tsc2007_interrupt); + if (ret < 0) + { + idbg("Failed to attach interrupt\n"); + goto errout_with_priv; + } + + /* Power down the ADC and enable PENIRQ. This is the normal state while + * waiting for a touch event. + */ + + ret = tsc2007_transfer(priv, TSC2007_ENABLE_PENIRQ); + if (ret < 0) + { + idbg("tsc2007_transfer failed: %d\n", ret); + goto errout_with_priv; + } + + /* Register the device as an input device */ + + (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor); + ivdbg("Registering %s\n", devname); + + ret = register_driver(devname, &tsc2007_fops, 0666, priv); + if (ret < 0) + { + idbg("register_driver() failed: %d\n", ret); + goto errout_with_priv; + } + + /* If multiple TSC2007 devices are supported, then we will need to add + * this new instance to a list of device instances so that it can be + * found by the interrupt handler based on the recieved IRQ number. + */ + +#ifdef CONFIG_TSC2007_MULTIPLE + flags = irqsave(); + priv->flink = g_tsc2007list; + g_tsc2007list = priv; + irqrestore(flags); +#endif + + /* Schedule work to perform the initial sampling and to set the data + * availability conditions. + */ + + ret = work_queue(&priv->work, tsc2007_worker, priv, 0); + if (ret != 0) + { + idbg("Failed to queue work: %d\n", ret); + goto errout_with_priv; + } + + /* And return success (?) */ + + return OK; + +errout_with_priv: + sem_destroy(&priv->devsem); +#ifdef CONFIG_TSC2007_MULTIPLE + kfree(priv); +#endif + return ret; +} diff --git a/nuttx/drivers/input/tsc2007.h b/nuttx/drivers/input/tsc2007.h new file mode 100644 index 0000000000..76d5962bfc --- /dev/null +++ b/nuttx/drivers/input/tsc2007.h @@ -0,0 +1,120 @@ +/******************************************************************************************** + * drivers/input/tsc2007.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "1.2V to 3.6V, 12-Bit, Nanopower, 4-Wire Micro TOUCH SCREEN CONTROLLER + * with I2C Interface," SBAS405A March 2007, Revised, March 2009, Texas + * Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +/* The TSC2007 is an analog interface circuit for a human interface touch screen device. + * All peripheral functions are controlled through the command byte and onboard state + * machines. + */ + +#ifndef __DRIVERS_INPUT_TSC2007_H +#define __DRIVERS_INPUT_TSC2007_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ + +/* TSC2007 Address */ + +#define TSC2007_ADDRESS_MASK (0xf8) /* Bits 3-7: Invariant part of TSC2007 address */ +#define TSC2007_ADDRESS (0x90) /* Bits 3-7: Always set at '10010' */ +#define TSC2007_A1 (1 << 2) /* Bit 2: A1 */ +#define TSC2007_A0 (1 << 1) /* Bit 1: A1 */ +#define TSC2007_READ (1 << 0) /* Bit0=1: Selects read operation */ +#define TSC2007_WRITE (0) /* Bit0=0: Selects write operation */ + +/* TSC2007 Command Byte */ + +#define TSC2007_CMD_FUNC_SHIFT (4) /* Bits 4-7: Converter function select bits */ +#define TSC2007_CMD_FUNC_MASK (15 << TSC2007_CMD_FUNC_SHIFT) +# define TSC2007_CMD_FUNC_TEMP0 (0 << TSC2007_CMD_FUNC_SHIFT) /* Measure TEMP0 */ +# define TSC2007_CMD_FUNC_AUX (2 << TSC2007_CMD_FUNC_SHIFT) /* Measure AUX */ +# define TSC2007_CMD_FUNC_TEMP1 (4 << TSC2007_CMD_FUNC_SHIFT) /* Measure TEMP1 */ +# define TSC2007_CMD_FUNC_XON (8 << TSC2007_CMD_FUNC_SHIFT) /* Activate X-drivers */ +# define TSC2007_CMD_FUNC_YON (9 << TSC2007_CMD_FUNC_SHIFT) /* Activate Y-drivers */ +# define TSC2007_CMD_FUNC_YXON (10 << TSC2007_CMD_FUNC_SHIFT) /* Activate Y+, X-drivers */ +# define TSC2007_CMD_FUNC_SETUP (11 << TSC2007_CMD_FUNC_SHIFT) /* Setup command */ +# define TSC2007_CMD_FUNC_XPOS (12 << TSC2007_CMD_FUNC_SHIFT) /* Measure X position */ +# define TSC2007_CMD_FUNC_YPOS (13 << TSC2007_CMD_FUNC_SHIFT) /* Measure Y position */ +# define TSC2007_CMD_FUNC_Z1POS (14 << TSC2007_CMD_FUNC_SHIFT) /* Measure Z1 position */ +# define TSC2007_CMD_FUNC_Z2POS (15 << TSC2007_CMD_FUNC_SHIFT) /* Measure Z2 positionn */ +#define TSC2007_CMD_PWRDN_SHIFT (2) /* Bits 2-3: Power-down bits */ +#define TSC2007_CMD_PWRDN_MASK (3 << TSC2007_CMD_PWRDN_SHIFT) +# define TSC2007_CMD_PWRDN_IRQEN (0 << TSC2007_CMD_PWRDN_SHIFT) /* 00: Power down between cycles; PENIRQ enabled */ +# define TSC2007_CMD_ADCON_IRQDIS (1 << TSC2007_CMD_PWRDN_SHIFT) /* 01: A/D converter on; PENIRQ disabled */ +# define TSC2007_CMD_ADCOFF_IRQEN (2 << TSC2007_CMD_PWRDN_SHIFT) /* 10: A/D converter off; PENIRQ enabled. */ + /* 11: A/D converter on; PENIRQ disabled. */ +#define TSC2007_CMD_12BIT (0) /* Bit 1: 0=12-bit */ +#define TSC2007_CMD_8BIT (1 << 1) /* Bit 1: 1=8-bit */ + /* Bit 0: Don't care */ + +/* TSC2007 Setup Command */ + +#define TSC2007_SETUP_CMD TSC2007_CMD_FUNC_SETUP /* Bits 4-7: Setup command */ + /* Bits 2-3: Must be zero */ +#define TSC2007_CMD_USEMAV (0) /* Bit 1: 0: Use the onboard MAV filter (default) */ +#define TSC2007_CMD_BYPASSMAV (1 << 1) /* Bit 1: 1: Bypass the onboard MAV filter */ +#define TSC2007_CMD_PU_50KOHM (0) /* Bit 0: 0: RIRQ = 50kOhm (default). */ +#define TSC2007_CMD_PU_90KOHM (1 << 1) /* Bit 0: 1: 1: RIRQ = 90kOhm */ + +/******************************************************************************************** + * Public Types + ********************************************************************************************/ + +/******************************************************************************************** + * Public Function Prototypes + ********************************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __DRIVERS_INPUT_TSC2007_H */ diff --git a/nuttx/drivers/lcd/Kconfig b/nuttx/drivers/lcd/Kconfig new file mode 100644 index 0000000000..af94ac16a3 --- /dev/null +++ b/nuttx/drivers/lcd/Kconfig @@ -0,0 +1,175 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# +config LCD_MAXCONTRAST + int "LCD maximum contrast" + default 63 if NOKIA6100_S1D15G10 + default 127 if NOKIA6100_PCF8833 + default 255 if LCD_P14201 + default 63 + ---help--- + must be 63 with the Epson controller and 127 with + the Phillips controller. + +config LCD_MAXPOWER + int "LCD maximum power" + default 1 + ---help--- + Maximum value of backlight setting. The backlight + control is managed outside of the 6100 driver so this value has no + meaning to the driver. Board-specific logic may place restrictions on + this value. + +config LCD_P14201 + bool "Rit P1402 series display" + default n + ---help--- + p14201.c. Driver for RiT P14201 series display with SD1329 IC + controller. This OLED is used with older versions of the + TI/Luminary LM3S8962 Evaluation Kit. +if LCD_P14201 +config P14201_NINTERFACES + int "Number of physical P14201 devices" + default 1 + range 1,1 + ---help--- + Specifies the number of physical P14201 + devices that will be supported. + +config P14201_SPIMODE + int "SPI mode" + default 2 + range 0,3 + ---help--- + Controls the SPI mode + +config P14201_FREQUENCY + int "SPI frequency" + default 1000000 + ---help--- + Define to use a different bus frequency,FIXME DEFAULT VALUE OK? + +config P14201_FRAMEBUFFER + bool "Enable P14201 GDDRAM cache" + default y + ---help--- + If defined, accesses will be performed + using an in-memory copy of the OLEDs GDDRAM. This cost of this + buffer is 128 * 96 / 2 = 6Kb. If this is defined, then the driver + will be fully functional. If not, then it will have the following + limitations: + + Reading graphics memory cannot be supported, and + + All pixel writes must be aligned to byte boundaries. + The latter limitation effectively reduces the 128x96 disply to 64x96. +endif + +config LCD_NOKIA6100 + bool "Nokia 6100 display support" + default n + ---help--- + nokia6100.c. Supports the Nokia 6100 display with either the Philips + PCF883 or the Epson S1D15G10 display controller. This LCD is used + with the Olimex LPC1766-STK (but has not been fully integrated). +if LCD_NOKIA6100 +config NOKIA6100_NINTERFACES + int "Number of physical NOKIA6100 devices" + default 1 + range 1,1 + ---help--- + Specifies the number of physical Nokia + 6100 devices that will be supported. + +choice NOKIA6100_CONTROLLER + prompt "Controller Setup" + default NOKIA6100_S1D15G10 +config NOKIA6100_S1D15G10 + bool "S1D15G10 controller" + ---help--- + Selects the Epson S1D15G10 display controller + +config NOKIA6100_PCF8833 + bool "PCF8833 controller" + ---help--- + Selects the Phillips PCF8833 display controller +endchoice + +config NOKIA6100_SPIMODE + int "SPI mode" + default 0 + range 0,3 + ---help--- + Controls the SPI mode + +config NOKIA6100_FREQUENCY + int "SPI frequency" + default 1000000 + ---help--- + Define to use a different bus frequency + +config NOKIA6100_BLINIT + bool "Back light initial" + default n + ---help--- + Initial backlight setting + The following may need to be tuned for your hardware: + +config NOKIA6100_BPP + int "Display bits per pixel" + default 8 + ---help--- + Device supports 8, 12, and 16 bits per pixel. + +config NOKIA6100_INVERT + int "Display inversion" + default 1 + range 0,1 + ---help--- + Display inversion, 0 or 1, Default: 1 + +config NOKIA6100_MY + int "Display row direction" + default 0 + range 0,1 + ---help--- + Display row direction, 0 or 1, Default: 0 + +config NOKIA6100_MX + int "Display column direction" + default 1 + range 0,1 + ---help--- + Display column direction, 0 or 1, Default: 1 + +config NOKIA6100_V + int "Display address direction" + default 0 + range 0,1 + ---help--- + Display address direction, 0 or 1, Default: 0 + +config NOKIA6100_ML + int "Display scan direction" + default 0 + range 0,1 + ---help--- + Display scan direction, 0 or 1, Default: 0 + +config NOKIA6100_RGBORD + int "Display RGB order" + default 0 + range 0,1 + ---help--- + Display RGB order, 0 or 1, Default: 0 + Required LCD driver settings: +endif + +config LCD_UG9664HSWAG01 + bool "9664HSWAG01 OLED Display Module" + default n + ---help--- + ug-9664hswag01.c. OLED Display Module, UG-9664HSWAG01", Univision + Technology Inc. Used with the LPC Xpresso and Embedded Artists + base board. diff --git a/nuttx/drivers/lcd/Make.defs b/nuttx/drivers/lcd/Make.defs new file mode 100644 index 0000000000..26b169391f --- /dev/null +++ b/nuttx/drivers/lcd/Make.defs @@ -0,0 +1,68 @@ +############################################################################ +# drivers/lcd/Make.defs +# +# Copyright (C) 2010-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Don't build anything if there is no NX support for LCD drivers + +ifeq ($(CONFIG_NX_LCDDRIVER),y) + +# Include LCD drivers + +ifeq ($(CONFIG_LCD_P14201),y) + CSRCS += p14201.c +endif + +ifeq ($(CONFIG_LCD_NOKIA6100),y) + CSRCS += nokia6100.c +endif + +ifeq ($(CONFIG_LCD_UG9664HSWAG01),y) + CSRCS += ug-9664hswag01.c +endif + +ifeq ($(CONFIG_LCD_SSD1289),y) + CSRCS += ssd1289.c +endif + +ifeq ($(CONFIG_LCD_MIO283QT2),y) + CSRCS += mio283qt2.c +endif + +# Include LCD driver build support + +DEPPATH += --dep-path lcd +VPATH += :lcd +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/lcd} +endif + diff --git a/nuttx/drivers/lcd/README.txt b/nuttx/drivers/lcd/README.txt new file mode 100644 index 0000000000..77ae536b2b --- /dev/null +++ b/nuttx/drivers/lcd/README.txt @@ -0,0 +1,165 @@ +nuttx/drivers/lcd README +======================== + +This is the README.txt file for the drivers/lcd/ directory. + +Contents +======== + + - LCD Header files + include/nuttx/lcd/lcd.h + struct lcd_dev_s + - Binding LCD Drivers + - Examples: /drivers/lcd/ + - Examples: configs/ + - graphics/ + +LCD Header files +================ + + include/nuttx/lcd/lcd.h + + Structures and APIs needed to work with LCD drivers are provided in + this header file. This header file also depends on some of the same + definitions used for the frame buffer driver as privided in + include/nuttx/fb.h. + + struct lcd_dev_s + + Each LCD device driver must implement an instance of struct lcd_dev_s. + That structure defines a call table with the following methods: + + - Get information about the LCD video controller configuration and the + configuration of each LCD color plane. + + int (*getvideoinfo)(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo); + int (*getplaneinfo)(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo); + + - The following are provided only if the video hardware supports RGB + color mapping: + + int (*getcmap)(FAR struct lcd_dev_s *dev, + FAR struct fb_cmap_s *cmap); + int (*putcmap)(FAR struct lcd_dev_s *dev, + FAR const struct fb_cmap_s *cmap); + + - The following are provided only if the video hardware supports a + hardware cursor: + + int (*getcursor)(FAR struct lcd_dev_s *dev, + FAR struct fb_cursorattrib_s *attrib); + int (*setcursor)(FAR struct lcd_dev_s *dev, + FAR struct fb_setcursor_s *settings); + + - Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER: + full on). On backlit LCDs, this setting may correspond to the + backlight setting. + + int (*getpower)(struct lcd_dev_s *dev); + + - Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: + full on). On backlit LCDs, this setting may correspond to the + backlight setting. + + int (*setpower)(struct lcd_dev_s *dev, int power); + + - Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST) */ + + int (*getcontrast)(struct lcd_dev_s *dev); + + - Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST) + + int (*setcontrast)(struct lcd_dev_s *dev, unsigned int contrast); + +Binding LCD Drivers +=================== + + LCD drivers are not normally directly accessed by user code, but are + usually bound to another, higher level device driver. In general, the + binding sequence is: + + 1. Get an instance of struct lcd_dev_s from the hardware-specific LCD + device driver, and + 2. Provide that instance to the initialization method of the higher + level device driver. + +Examples: /drivers/lcd/ +======================= + +Re-usable LCD drivers reside in the drivers/lcd directory: + + mio283qt2.c. This is a driver for the MI0283QT-2 LCD from Multi-Inno + Technology Co., Ltd. This LCD is based on the Himax HX8347-D LCD + controller. + + nokia6100.c. Supports the Nokia 6100 display with either the Philips + PCF883 or the Epson S1D15G10 display controller. This LCD is used + with the Olimex LPC1766-STK (but has not been fully integrated). + + p14201.c. Driver for RiT P14201 series display with SD1329 IC + controller. This OLED is used with older versions of the + TI/Luminary LM3S8962 Evaluation Kit. + + ssd12989.c. Generic LCD driver for LCDs based on the Solomon Systech + SSD1289 LCD controller. Think of this as a template for an LCD driver + that you will proably ahve to customize for any particular LCD + hardware. (see also configs/hymini-stm32v/src/ssd1289.c below). + + ug-9664hswag01.c. OLED Display Module, UG-9664HSWAG01", Univision + Technology Inc. Used with the LPC Xpresso and Embedded Artists + base board. + +Examples: configs/ +================== + +There are additional LCD drivers in the configs//src directory +that support additional LCDs. LCD drivers in the configuration directory +if they support some differ LCD interface (such as a parallel interface) +that makes then less re-usable: + + configs/compal_e99/src/ssd1783.c + + SSD1783 + + configs/hymini-stm32v/src/ssd1289.c. See also drivers/lcd/ssd1298.c + above. + + SSD1289 + + configs/kwikstik-k40/src/up_lcd.c. Don't waste your time. This is + just a stub. + + configs/olimex-lpc1766stk/src/up_lcd.c. This examples is the + bottom half for the SSD1289 driver at drivers/lcd/nokia6100.c. + This was never completedly debugged ... there are probably issues + with that nasty 9-bit SPI interfaces. + + configs/sam3u-ek/src/up_lcd.c + + The SAM3U-EK developement board features a TFT/Transmissive color + LCD module with touch-screen, FTM280C12D, with integrated driver IC + HX8346. + + configs/skp16c26/src/up_lcd.c. Untested alphanumeric LCD driver. + + configs/stm3210e-eval/src/up_lcd.c + + This driver supports the following LCDs: + + 1. Ampire AM-240320LTNQW00H + 2. Orise Tech SPFD5408B + 3. RenesasSP R61580 + + configs/stm3220g-eval/src/up_lcd.c and configs/stm3240g-eval/src/up_lcd.c. + AM-240320L8TNQW00H (LCD_ILI9320 or LCD_ILI9321) and + AM-240320D5TOQW01H (LCD_ILI9325) + + configs/stm32f4discovery/src/up_ssd1289.c. This examples is the + bottom half for the SSD1289 driver at drivers/lcd/ssd1289.c + +graphics/ +========= + + See also the usage of the LCD driver in the graphics/ directory. diff --git a/nuttx/drivers/lcd/mio283qt2.c b/nuttx/drivers/lcd/mio283qt2.c new file mode 100644 index 0000000000..1758e230c1 --- /dev/null +++ b/nuttx/drivers/lcd/mio283qt2.c @@ -0,0 +1,1014 @@ +/************************************************************************************** + * drivers/lcd/mio283qt2.c + * + * This is a driver for the MI0283QT-2 LCD from Multi-Inno Technology Co., Ltd. This + * LCD is based on the Himax HX8347-D LCD controller. + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * + * References: + * 1) LCD Module Specification, Model : MI0283QT-2, Multi-Inno Technology Co., + * Ltd., Revision 1.0 + * 2) Data Sheet: HX8347-D(T), 240RGB x 320 dot, 262K color, with internal GRAM, TFT + * Mobile Single Chip Driver Version 02 March, Doc No. HX8347-D(T)-DS, Himax + * Technologies, Inc., 2009, + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_LCD_MIO283QT2 + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ +/* Configuration **********************************************************************/ + +/* Check contrast selection */ + +#if !defined(CONFIG_LCD_MAXCONTRAST) +# define CONFIG_LCD_MAXCONTRAST 1 +#endif + +/* Check power setting */ + +#if !defined(CONFIG_LCD_MAXPOWER) || CONFIG_LCD_MAXPOWER < 1 +# define CONFIG_LCD_MAXPOWER 1 +#endif + +#if CONFIG_LCD_MAXPOWER > 255 +# error "CONFIG_LCD_MAXPOWER must be less than 256 to fit in uint8_t" +#endif + +/* Check orientation */ + +#if defined(CONFIG_LCD_PORTRAIT) +# if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) || defined(CONFIG_LCD_RPORTRAIT) +# error "Cannot define both portrait and any other orientations" +# endif +#elif defined(CONFIG_LCD_RPORTRAIT) +# if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) +# error "Cannot define both rportrait and any other orientations" +# endif +#elif defined(CONFIG_LCD_LANDSCAPE) +# ifdef CONFIG_LCD_RLANDSCAPE +# error "Cannot define both landscape and any other orientations" +# endif +#elif !defined(CONFIG_LCD_RLANDSCAPE) +# define CONFIG_LCD_LANDSCAPE 1 +#endif + +/* Define CONFIG_DEBUG_LCD to enable detailed LCD debug output. Verbose debug must + * also be enabled. + */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_GRAPHICS +# undef CONFIG_DEBUG_LCD +#endif + +#ifndef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_LCD +#endif + +/* Display/Color Properties ***********************************************************/ +/* Display Resolution */ + +#if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) +# define MIO283QT2_XRES 320 +# define MIO283QT2_YRES 240 +#else +# define MIO283QT2_XRES 240 +# define MIO283QT2_YRES 320 +#endif + +/* Color depth and format */ + +#define MIO283QT2_BPP 16 +#define MIO283QT2_COLORFMT FB_FMT_RGB16_565 + +/* Hardware LCD/LCD controller definitions ********************************************/ +/* In this driver, I chose to use all literal constants for register address and + * values. Some recent experiences have shown me that during LCD bringup, it is more + * important to know the binary values rather than nice, people friendly names. Sad, + * but true. + */ + +#define HIMAX_ID 0x0047 + +/* LCD Profiles ***********************************************************************/ +/* Many details of the controller initialization must, unfortunately, vary from LCD to + * LCD. I have looked at the spec and at three different drivers for LCDs that have + * MIO283QT2 controllers. I have tried to summarize these differences as "LCD profiles" + * + * Most of the differences between LCDs are nothing more than a few minor bit + * settings. The most significant difference betwen LCD drivers in is the + * manner in which the LCD is powered up and in how the power controls are set. + * My suggestion is that if you have working LCD initialization code, you should + * simply replace the code in mio283qt2_hwinitialize with your working code. + */ + +#if defined (CONFIG_MIO283QT2_PROFILE2) +# undef MIO283QT2_USE_SIMPLE_INIT + + /* PWRCTRL1: AP=smalll-to-medium, DC=Flinex24, BT=+5/-4, DCT=Flinex24 */ + +# define PWRCTRL1_SETTING \ + (MIO283QT2_PWRCTRL1_AP_SMMED | MIO283QT2_PWRCTRL1_DC_FLINEx24 | \ + MIO283QT2_PWRCTRL1_BT_p5m4 | MIO283QT2_PWRCTRL1_DCT_FLINEx24) + + /* PWRCTRL2: 5.1v */ + +# define PWRCTRL2_SETTING MIO283QT2_PWRCTRL2_VRC_5p1V + + /* PWRCTRL3: x 2.165 + * NOTE: Many drivers have bit 8 set which is not defined in the MIO283QT2 spec. + */ + +# define PWRCTRL3_SETTING MIO283QT2_PWRCTRL3_VRH_x2p165 + + /* PWRCTRL4: VDV=9 + VCOMG */ + +# define PWRCTRL4_SETTING (MIO283QT2_PWRCTRL4_VDV(9) | MIO283QT2_PWRCTRL4_VCOMG) + + /* PWRCTRL5: VCM=56 + NOTP */ + +# define PWRCTRL5_SETTING (MIO283QT2_PWRCTRL5_VCM(56) | MIO283QT2_PWRCTRL5_NOTP) + +#elif defined (CONFIG_MIO283QT2_PROFILE3) +# undef MIO283QT2_USE_SIMPLE_INIT + + /* PWRCTRL1: AP=smalll-to-medium, DC=Flinex24, BT=+5/-4, DCT=Flinex24 */ + +# define PWRCTRL1_SETTING \ + (MIO283QT2_PWRCTRL1_AP_SMMED | MIO283QT2_PWRCTRL1_DC_FLINEx24 | \ + MIO283QT2_PWRCTRL1_BT_p5m4 | MIO283QT2_PWRCTRL1_DCT_FLINEx24) + + /* PWRCTRL2: 5.1v */ + +# define PWRCTRL2_SETTING MIO283QT2_PWRCTRL2_VRC_5p1V + + /* PWRCTRL3: x 2.165 + * NOTE: Many drivers have bit 8 set which is not defined in the MIO283QT2 spec. + */ + +# define PWRCTRL3_SETTING MIO283QT2_PWRCTRL3_VRH_x2p165 + + /* PWRCTRL4: VDV=9 + VCOMG */ + +# define PWRCTRL4_SETTING (MIO283QT2_PWRCTRL4_VDV(9) | MIO283QT2_PWRCTRL4_VCOMG) + + /* PWRCTRL5: VCM=56 + NOTP */ + +# define PWRCTRL5_SETTING (MIO283QT2_PWRCTRL5_VCM(56) | MIO283QT2_PWRCTRL5_NOTP) + +#else /* if defined (CONFIG_MIO283QT2_PROFILE1) */ +# undef MIO283QT2_USE_SIMPLE_INIT +# define MIO283QT2_USE_SIMPLE_INIT 1 + + /* PWRCTRL1: AP=medium-to-large, DC=Fosc/4, BT=+5/-4, DCT=Fosc/4 */ + +# define PWRCTRL1_SETTING \ + (MIO283QT2_PWRCTRL1_AP_MEDLG | MIO283QT2_PWRCTRL1_DC_FOSd4 | \ + MIO283QT2_PWRCTRL1_BT_p5m4 | MIO283QT2_PWRCTRL1_DCT_FOSd4) + + /* PWRCTRL2: 5.3v */ + +# define PWRCTRL2_SETTING MIO283QT2_PWRCTRL2_VRC_5p3V + + /* PWRCTRL3: x 2.570 + * NOTE: Many drivers have bit 8 set which is not defined in the MIO283QT2 spec. + */ + +# define PWRCTRL3_SETTING MIO283QT2_PWRCTRL3_VRH_x2p570 + + /* PWRCTRL4: VDV=12 + VCOMG */ + +# define PWRCTRL4_SETTING (MIO283QT2_PWRCTRL4_VDV(12) | MIO283QT2_PWRCTRL4_VCOMG) + + /* PWRCTRL5: VCM=60 + NOTP */ + +# define PWRCTRL5_SETTING (MIO283QT2_PWRCTRL5_VCM(60) | MIO283QT2_PWRCTRL5_NOTP) + +#endif + +/* Debug ******************************************************************************/ + +#ifdef CONFIG_DEBUG_LCD +# define lcddbg dbg +# define lcdvdbg vdbg +#else +# define lcddbg(x...) +# define lcdvdbg(x...) +#endif + +/************************************************************************************** + * Private Type Definition + **************************************************************************************/ + +/* This structure describes the state of this driver */ + +struct mio283qt2_dev_s +{ + /* Publically visible device structure */ + + struct lcd_dev_s dev; + + /* Private LCD-specific information follows */ + + FAR struct mio283qt2_lcd_s *lcd; /* The contained platform-specific, LCD interface */ + uint8_t power; /* Current power setting */ + + /* This is working memory allocated by the LCD driver for each LCD device + * and for each color plane. This memory will hold one raster line of data. + * The size of the allocated run buffer must therefore be at least + * (bpp * xres / 8). Actual alignment of the buffer must conform to the + * bitwidth of the underlying pixel type. + * + * If there are multiple planes, they may share the same working buffer + * because different planes will not be operate on concurrently. However, + * if there are multiple LCD devices, they must each have unique run buffers. + */ + + uint16_t runbuffer[MIO283QT2_XRES]; +}; + +/************************************************************************************** + * Private Function Protototypes + **************************************************************************************/ +/* Low Level LCD access */ + +static void mio283qt2_putreg(FAR struct mio283qt2_lcd_s *lcd, uint8_t regaddr, + uint16_t regval); +#ifndef CONFIG_LCD_NOGETRUN +static uint16_t mio283qt2_readreg(FAR struct mio283qt2_lcd_s *lcd, uint8_t regaddr); +#endif +static inline void mio283qt2_gramwrite(FAR struct mio283qt2_lcd_s *lcd, + uint16_t rgbcolor); +#ifndef CONFIG_LCD_NOGETRUN +static inline void mio283qt2_readsetup(FAR struct mio283qt2_lcd_s *lcd, + FAR uint16_t *accum); +static inline uint16_t mio283qt2_gramread(FAR struct mio283qt2_lcd_s *lcd, + FAR uint16_t *accum); +#endif +static void mio283qt2_setarea(FAR struct mio283qt2_lcd_s *lcd, + uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); + +/* LCD Data Transfer Methods */ + +static int mio283qt2_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels); +static int mio283qt2_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels); + +/* LCD Configuration */ + +static int mio283qt2_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo); +static int mio283qt2_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo); + +/* LCD RGB Mapping */ + +#ifdef CONFIG_FB_CMAP +# error "RGB color mapping not supported by this driver" +#endif + +/* Cursor Controls */ + +#ifdef CONFIG_FB_HWCURSOR +# error "Cursor control not supported by this driver" +#endif + +/* LCD Specific Controls */ + +static int mio283qt2_getpower(FAR struct lcd_dev_s *dev); +static int mio283qt2_setpower(FAR struct lcd_dev_s *dev, int power); +static int mio283qt2_getcontrast(FAR struct lcd_dev_s *dev); +static int mio283qt2_setcontrast(FAR struct lcd_dev_s *dev, unsigned int contrast); + +/* Initialization */ + +static inline int mio283qt2_hwinitialize(FAR struct mio283qt2_dev_s *priv); + +/************************************************************************************** + * Private Data + **************************************************************************************/ + +/* This driver can support only a signal MIO283QT2 device. This is due to an + * unfortunate decision made whent he getrun and putrun methods were designed. The + * following is the single MIO283QT2 driver state instance: + */ + +static struct mio283qt2_dev_s g_lcddev; + +/************************************************************************************** + * Private Functions + **************************************************************************************/ + +/************************************************************************************** + * Name: mio283qt2_putreg(lcd, + * + * Description: + * Write to an LCD register + * + **************************************************************************************/ + +static void mio283qt2_putreg(FAR struct mio283qt2_lcd_s *lcd, + uint8_t regaddr, uint16_t regval) +{ + /* Set the index register to the register address and write the register contents */ + + lcd->index(lcd, regaddr); + lcd->write(lcd, regval); +} + +/************************************************************************************** + * Name: mio283qt2_readreg + * + * Description: + * Read from an LCD register + * + **************************************************************************************/ + +#ifndef CONFIG_LCD_NOGETRUN +static uint16_t mio283qt2_readreg(FAR struct mio283qt2_lcd_s *lcd, uint8_t regaddr) +{ + /* Set the index register to the register address and read the register contents. */ + + lcd->index(lcd, regaddr); + return lcd->read(lcd); +} +#endif + +/************************************************************************************** + * Name: mio283qt2_gramselect + * + * Description: + * Setup to read or write multiple pixels to the GRAM memory + * + **************************************************************************************/ + +static inline void mio283qt2_gramselect(FAR struct mio283qt2_lcd_s *lcd) +{ + lcd->index(lcd, 0x22); +} + +/************************************************************************************** + * Name: mio283qt2_gramwrite + * + * Description: + * Setup to read or write multiple pixels to the GRAM memory + * + **************************************************************************************/ + +static inline void mio283qt2_gramwrite(FAR struct mio283qt2_lcd_s *lcd, uint16_t data) +{ + lcd->write(lcd, data); +} + +/************************************************************************************** + * Name: mio283qt2_readsetup + * + * Description: + * Prime the operation by reading one pixel from the GRAM memory if necessary for + * this LCD type. When reading 16-bit gram data, there may be some shifts in the + * returned data: + * + * - ILI932x: Discard first dummy read; no shift in the return data + * + **************************************************************************************/ + +#ifndef CONFIG_LCD_NOGETRUN +static inline void mio283qt2_readsetup(FAR struct mio283qt2_lcd_s *lcd, + FAR uint16_t *accum) +{ +#if 0 /* Probably not necessary... untested */ + /* Read-ahead one pixel */ + + *accum = lcd->read(lcd); +#endif +} +#endif + +/************************************************************************************** + * Name: mio283qt2_gramread + * + * Description: + * Read one correctly aligned pixel from the GRAM memory. Possibly shifting the + * data and possibly swapping red and green components. + * + * - ILI932x: Unknown -- assuming colors are in the color order + * + **************************************************************************************/ + +#ifndef CONFIG_LCD_NOGETRUN +static inline uint16_t mio283qt2_gramread(FAR struct mio283qt2_lcd_s *lcd, + FAR uint16_t *accum) +{ + /* Read the value (GRAM register already selected) */ + + return lcd->read(lcd); +} +#endif + +/************************************************************************************** + * Name: mio283qt2_setarea + * + * Description: + * Set the cursor position. In landscape mode, the "column" is actually the physical + * Y position and the "row" is the physical X position. + * + **************************************************************************************/ + +static void mio283qt2_setarea(FAR struct mio283qt2_lcd_s *lcd, + uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) +{ + mio283qt2_putreg(lcd, 0x03, (x0 & 0x00ff)); /* set x0 */ + mio283qt2_putreg(lcd, 0x02, (x0 >> 8)); /* set x0 */ + mio283qt2_putreg(lcd, 0x05, (x1 & 0x00ff)); /* set x1 */ + mio283qt2_putreg(lcd, 0x04, (x1 >> 8)); /* set x1 */ + mio283qt2_putreg(lcd, 0x07, (y0 & 0x00ff)); /* set y0 */ + mio283qt2_putreg(lcd, 0x06, (y0 >> 8)); /* set y0 */ + mio283qt2_putreg(lcd, 0x09, (y1 & 0x00ff)); /* set y1 */ + mio283qt2_putreg(lcd, 0x08, (y1 >> 8)); /* set y1 */ +} + +/************************************************************************************** + * Name: mio283qt2_dumprun + * + * Description: + * Dump the contexts of the run buffer: + * + * run - The buffer in containing the run read to be dumped + * npixels - The number of pixels to dump + * + **************************************************************************************/ + +#if 0 /* Sometimes useful */ +static void mio283qt2_dumprun(FAR const char *msg, FAR uint16_t *run, size_t npixels) +{ + int i, j; + + lib_rawprintf("\n%s:\n", msg); + for (i = 0; i < npixels; i += 16) + { + up_putc(' '); + lib_rawprintf(" "); + for (j = 0; j < 16; j++) + { + lib_rawprintf(" %04x", *run++); + } + up_putc('\n'); + } +} +#endif + +/************************************************************************************** + * Name: mio283qt2_putrun + * + * Description: + * This method can be used to write a partial raster line to the LCD: + * + * row - Starting row to write to (range: 0 <= row < yres) + * col - Starting column to write to (range: 0 <= col <= xres-npixels) + * buffer - The buffer containing the run to be written to the LCD + * npixels - The number of pixels to write to the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +static int mio283qt2_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels) +{ + FAR struct mio283qt2_dev_s *priv = &g_lcddev; + FAR struct mio283qt2_lcd_s *lcd = priv->lcd; + FAR const uint16_t *src = (FAR const uint16_t*)buffer; + int i; + + /* Buffer must be provided and aligned to a 16-bit address boundary */ + + lcdvdbg("row: %d col: %d npixels: %d\n", row, col, npixels); + DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); + + /* Select the LCD */ + + lcd->select(lcd); + + /* Write the run to GRAM. */ + + mio283qt2_setarea(lcd, col, row, col + npixels - 1, row); + mio283qt2_gramselect(lcd); + + for (i = 0; i < npixels; i++) + { + mio283qt2_gramwrite(lcd, *src); + src++; + } + + /* De-select the LCD */ + + lcd->deselect(lcd); + return OK; +} + +/************************************************************************************** + * Name: mio283qt2_getrun + * + * Description: + * This method can be used to read a partial raster line from the LCD: + * + * row - Starting row to read from (range: 0 <= row < yres) + * col - Starting column to read read (range: 0 <= col <= xres-npixels) + * buffer - The buffer in which to return the run read from the LCD + * npixels - The number of pixels to read from the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +static int mio283qt2_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels) +{ +#ifndef CONFIG_LCD_NOGETRUN + FAR struct mio283qt2_dev_s *priv = &g_lcddev; + FAR struct mio283qt2_lcd_s *lcd = priv->lcd; + FAR uint16_t *dest = (FAR uint16_t*)buffer; + uint16_t accum; + int i; + + /* Buffer must be provided and aligned to a 16-bit address boundary */ + + lcdvdbg("row: %d col: %d npixels: %d\n", row, col, npixels); + DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); + + /* Select the LCD */ + + lcd->select(lcd); + + /* Read the run from GRAM. */ + + /* Select the LCD */ + + lcd->select(lcd); + + /* Red the run fram GRAM. */ + + mio283qt2_setarea(lcd, col, row, col + npixels - 1, row); + mio283qt2_gramselect(lcd); + + /* Prime the pump for unaligned read data */ + + mio283qt2_readsetup(lcd, &accum); + + for (i = 0; i < npixels; i++) + { + *dest++ = mio283qt2_gramread(lcd, &accum); + } + + /* De-select the LCD */ + + lcd->deselect(lcd); + return OK; +#else + return -ENOSYS; +#endif +} + +/************************************************************************************** + * Name: mio283qt2_getvideoinfo + * + * Description: + * Get information about the LCD video controller configuration. + * + **************************************************************************************/ + +static int mio283qt2_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo) +{ + DEBUGASSERT(dev && vinfo); + lcdvdbg("fmt: %d xres: %d yres: %d nplanes: 1\n", + MIO283QT2_COLORFMT, MIO283QT2_XRES, MIO283QT2_XRES); + + vinfo->fmt = MIO283QT2_COLORFMT; /* Color format: RGB16-565: RRRR RGGG GGGB BBBB */ + vinfo->xres = MIO283QT2_XRES; /* Horizontal resolution in pixel columns */ + vinfo->yres = MIO283QT2_YRES; /* Vertical resolution in pixel rows */ + vinfo->nplanes = 1; /* Number of color planes supported */ + return OK; +} + +/************************************************************************************** + * Name: mio283qt2_getplaneinfo + * + * Description: + * Get information about the configuration of each LCD color plane. + * + **************************************************************************************/ + +static int mio283qt2_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo) +{ + FAR struct mio283qt2_dev_s *priv = (FAR struct mio283qt2_dev_s *)dev; + + DEBUGASSERT(dev && pinfo && planeno == 0); + lcdvdbg("planeno: %d bpp: %d\n", planeno, MIO283QT2_BPP); + + pinfo->putrun = mio283qt2_putrun; /* Put a run into LCD memory */ + pinfo->getrun = mio283qt2_getrun; /* Get a run from LCD memory */ + pinfo->buffer = (uint8_t*)priv->runbuffer; /* Run scratch buffer */ + pinfo->bpp = MIO283QT2_BPP; /* Bits-per-pixel */ + return OK; +} + +/************************************************************************************** + * Name: mio283qt2_getpower + * + * Description: + * Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int mio283qt2_getpower(FAR struct lcd_dev_s *dev) +{ + lcdvdbg("power: %d\n", 0); + return g_lcddev.power; +} + +/************************************************************************************** + * Name: mio283qt2_poweroff + * + * Description: + * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int mio283qt2_poweroff(FAR struct mio283qt2_lcd_s *lcd) +{ + /* Set the backlight off */ + + lcd->backlight(lcd, 0); + + /* Turn the display off */ + + mio283qt2_putreg(lcd, 0x28, 0x0000); /* GON=0, DTE=0, D=0 */ + + /* Remember the power off state */ + + g_lcddev.power = 0; + return OK; +} + +/************************************************************************************** + * Name: mio283qt2_setpower + * + * Description: + * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int mio283qt2_setpower(FAR struct lcd_dev_s *dev, int power) +{ + FAR struct mio283qt2_dev_s *priv = (FAR struct mio283qt2_dev_s *)dev; + FAR struct mio283qt2_lcd_s *lcd = priv->lcd; + + lcdvdbg("power: %d\n", power); + DEBUGASSERT((unsigned)power <= CONFIG_LCD_MAXPOWER); + + /* Set new power level */ + + if (power > 0) + { + /* Set the backlight level */ + + lcd->backlight(lcd, power); + + /* Then turn the display on: + * D=ON(3) CM=0 DTE=1 GON=1 SPT=0 VLE=0 PT=0 + */ + + /* Display on */ + + mio283qt2_putreg(lcd, 0x28, 0x0038); /* GON=1, DTE=1, D=2 */ + up_mdelay(40); + mio283qt2_putreg(lcd, 0x28, 0x003c); /* GON=1, DTE=1, D=3 */ + + g_lcddev.power = power; + } + else + { + /* Turn the display off */ + + mio283qt2_poweroff(lcd); + } + + return OK; +} + +/************************************************************************************** + * Name: mio283qt2_getcontrast + * + * Description: + * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int mio283qt2_getcontrast(FAR struct lcd_dev_s *dev) +{ + lcdvdbg("Not implemented\n"); + return -ENOSYS; +} + +/************************************************************************************** + * Name: mio283qt2_setcontrast + * + * Description: + * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int mio283qt2_setcontrast(FAR struct lcd_dev_s *dev, unsigned int contrast) +{ + lcdvdbg("contrast: %d\n", contrast); + return -ENOSYS; +} + +/************************************************************************************** + * Name: mio283qt2_hwinitialize + * + * Description: + * Initialize the LCD hardware. + * + **************************************************************************************/ + +static inline int mio283qt2_hwinitialize(FAR struct mio283qt2_dev_s *priv) +{ + FAR struct mio283qt2_lcd_s *lcd = priv->lcd; +#ifndef CONFIG_LCD_NOGETRUN + uint16_t id; +#endif + + /* Select the LCD */ + + lcd->select(lcd); + + /* Read the HIMAX ID registger (0x00) */ + +#ifndef CONFIG_LCD_NOGETRUN + id = mio283qt2_readreg(lcd, 0x00); + lcddbg("LCD ID: %04x\n", id); + + /* Check if the ID is for the MIO283QT2 */ + + if (id == HIMAX_ID) +#endif + { + /* Driving ability */ + + mio283qt2_putreg(lcd, 0xea, 0x0000); /* PTBA[15:8] */ + mio283qt2_putreg(lcd, 0xeb, 0x0020); /* PTBA[7:0] */ + mio283qt2_putreg(lcd, 0xec, 0x000c); /* STBA[15:8] */ + mio283qt2_putreg(lcd, 0xed, 0x00c4); /* STBA[7:0] */ + mio283qt2_putreg(lcd, 0xe8, 0x0040); /* OPON[7:0] */ + mio283qt2_putreg(lcd, 0xe9, 0x0038); /* OPON1[7:0] */ + mio283qt2_putreg(lcd, 0xf1, 0x0001); /* OTPS1B */ + mio283qt2_putreg(lcd, 0xf2, 0x0010); /* GEN */ + mio283qt2_putreg(lcd, 0x27, 0x00a3); + + /* Power voltage */ + + mio283qt2_putreg(lcd, 0x1b, 0x001b); /* VRH = 4.65 */ + mio283qt2_putreg(lcd, 0x1a, 0x0001); /* BT */ + mio283qt2_putreg(lcd, 0x24, 0x002f); /* VMH */ + mio283qt2_putreg(lcd, 0x25, 0x0057); /* VML */ + + /* Vcom offset */ + + mio283qt2_putreg(lcd, 0x23, 0x008d); /* For flicker adjust */ + + /* Power on */ + + mio283qt2_putreg(lcd, 0x18, 0x0036); + mio283qt2_putreg(lcd, 0x19, 0x0001); /* Start oscillator */ + mio283qt2_putreg(lcd, 0x01, 0x0000); /* Wakeup */ + mio283qt2_putreg(lcd, 0x1f, 0x0088); + up_mdelay(5); + mio283qt2_putreg(lcd, 0x1f, 0x0080); + up_mdelay(5); + mio283qt2_putreg(lcd, 0x1f, 0x0090); + up_mdelay(5); + mio283qt2_putreg(lcd, 0x1f, 0x00d0); + up_mdelay(5); + + /* Gamma 2.8 setting */ + + mio283qt2_putreg(lcd, 0x40, 0x0000); + mio283qt2_putreg(lcd, 0x41, 0x0000); + mio283qt2_putreg(lcd, 0x42, 0x0001); + mio283qt2_putreg(lcd, 0x43, 0x0013); + mio283qt2_putreg(lcd, 0x44, 0x0010); + mio283qt2_putreg(lcd, 0x45, 0x0026); + mio283qt2_putreg(lcd, 0x46, 0x0008); + mio283qt2_putreg(lcd, 0x47, 0x0051); + mio283qt2_putreg(lcd, 0x48, 0x0002); + mio283qt2_putreg(lcd, 0x49, 0x0012); + mio283qt2_putreg(lcd, 0x4a, 0x0018); + mio283qt2_putreg(lcd, 0x4b, 0x0019); + mio283qt2_putreg(lcd, 0x4c, 0x0014); + + mio283qt2_putreg(lcd, 0x50, 0x0019); + mio283qt2_putreg(lcd, 0x51, 0x002f); + mio283qt2_putreg(lcd, 0x52, 0x002c); + mio283qt2_putreg(lcd, 0x53, 0x003e); + mio283qt2_putreg(lcd, 0x54, 0x003f); + mio283qt2_putreg(lcd, 0x55, 0x003f); + mio283qt2_putreg(lcd, 0x56, 0x002e); + mio283qt2_putreg(lcd, 0x57, 0x0077); + mio283qt2_putreg(lcd, 0x58, 0x000b); + mio283qt2_putreg(lcd, 0x59, 0x0006); + mio283qt2_putreg(lcd, 0x5a, 0x0007); + mio283qt2_putreg(lcd, 0x5b, 0x000d); + mio283qt2_putreg(lcd, 0x5c, 0x001d); + mio283qt2_putreg(lcd, 0x5d, 0x00cc); + + /* 4K Color Selection */ + + mio283qt2_putreg(lcd, 0x17, 0x0003); + mio283qt2_putreg(lcd, 0x17, 0x0005); /* 0x0005=65k, 0x0006=262k */ + + /* Panel characteristics */ + + mio283qt2_putreg(lcd, 0x36, 0x0000); + + /* Display Setting */ + + mio283qt2_putreg(lcd, 0x01, 0x0000); /* IDMON=0, INVON=0, NORON=0, PTLON=0 */ + +#if defined(CONFIG_LCD_LANDSCAPE) + mio283qt2_putreg(lcd, 0x16, 0x00a8); /* MY=1, MX=0, MV=1, ML=0, BGR=1 */ +#elif defined(CONFIG_LCD_PORTRAIT) + mio283qt2_putreg(lcd, 0x16, 0x0008); /* MY=0, MX=0, MV=0, ML=0, BGR=1 */ +#elif defined(CONFIG_LCD_RLANDSCAPE) + mio283qt2_putreg(lcd, 0x16, 0x0068); /* MY=0, MX=1, MV=1, ML=0, BGR=1 */ +#elif defined(CONFIG_LCD_RPORTRAIT) + mio283qt2_putreg(lcd, 0x16, 0x00c8); /* MY=1, MX=0, MV=1, ML=0, BGR=1 */ +#endif + + /* Window setting */ + + mio283qt2_setarea(lcd, 0, 0, (MIO283QT2_XRES-1), (MIO283QT2_YRES-1)); + return OK; + } +#ifndef CONFIG_LCD_NOGETRUN + else + { + lcddbg("Unsupported LCD type\n"); + return -ENODEV; + } +#endif + + /* De-select the LCD */ + + lcd->deselect(lcd); +} + + /************************************************************************************* + * Public Functions + **************************************************************************************/ + +/************************************************************************************** + * Name: mio283qt2_lcdinitialize + * + * Description: + * Initialize the LCD video hardware. The initial state of the LCD is fully + * initialized, display memory cleared, and the LCD ready to use, but with the power + * setting at 0 (full off). + * + **************************************************************************************/ + +FAR struct lcd_dev_s *mio283qt2_lcdinitialize(FAR struct mio283qt2_lcd_s *lcd) +{ + int ret; + + lcdvdbg("Initializing\n"); + + /* If we ccould support multiple MIO283QT2 devices, this is where we would allocate + * a new driver data structure... but we can't. Why not? Because of a bad should + * the form of the getrun() and putrun methods. + */ + + FAR struct mio283qt2_dev_s *priv = &g_lcddev; + + /* Initialize the driver data structure */ + + priv->dev.getvideoinfo = mio283qt2_getvideoinfo; + priv->dev.getplaneinfo = mio283qt2_getplaneinfo; + priv->dev.getpower = mio283qt2_getpower; + priv->dev.setpower = mio283qt2_setpower; + priv->dev.getcontrast = mio283qt2_getcontrast; + priv->dev.setcontrast = mio283qt2_setcontrast; + priv->lcd = lcd; + + /* Configure and enable LCD */ + + ret = mio283qt2_hwinitialize(priv); + if (ret == OK) + { + /* Clear the display (setting it to the color 0=black) */ + + mio283qt2_clear(&priv->dev, 0); + + /* Turn the display off */ + + mio283qt2_poweroff(lcd); + return &g_lcddev.dev; + } + + return NULL; +} + +/************************************************************************************** + * Name: mio283qt2_clear + * + * Description: + * This is a non-standard LCD interface just for the stm3240g-EVAL board. Because + * of the various rotations, clearing the display in the normal way by writing a + * sequences of runs that covers the entire display can be very slow. Here the + * display is cleared by simply setting all GRAM memory to the specified color. + * + **************************************************************************************/ + +void mio283qt2_clear(FAR struct lcd_dev_s *dev, uint16_t color) +{ + FAR struct mio283qt2_dev_s *priv = (FAR struct mio283qt2_dev_s *)dev; + FAR struct mio283qt2_lcd_s *lcd = priv->lcd; + uint32_t i; + + /* Select the LCD and set the drawring area */ + + lcd->select(lcd); + mio283qt2_setarea(lcd, 0, 0, (MIO283QT2_XRES-1), (MIO283QT2_YRES-1)); + + /* Prepare to write GRAM data */ + + mio283qt2_gramselect(lcd); + + /* Copy color into all of GRAM. Orientation does not matter in this case. */ + + for (i = 0; i < MIO283QT2_XRES * MIO283QT2_YRES; i++) + { + mio283qt2_gramwrite(lcd, color); + } + + /* De-select the LCD */ + + lcd->deselect(lcd); +} + +#endif /* CONFIG_LCD_MIO283QT2 */ diff --git a/nuttx/drivers/lcd/nokia6100.c b/nuttx/drivers/lcd/nokia6100.c new file mode 100644 index 0000000000..d450e05dbf --- /dev/null +++ b/nuttx/drivers/lcd/nokia6100.c @@ -0,0 +1,1230 @@ +/************************************************************************************** + * drivers/lcd/nokia6100.c + * Nokia 6100 LCD Display Driver + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "Nokia 6100 LCD Display Driver," Revision 1, James P. Lynch ("Nokia 6100 LCD + * Display Driver.pdf") + * "S1D15G0D08B000," Seiko Epson Corportation, 2002. + * "Data Sheet, PCF8833 STN RGB 132x132x3 driver," Phillips, 2003 Feb 14. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_NOKIA6100_PCF8833 +# include "pcf8833.h" +#endif +#ifdef CONFIG_NOKIA6100_S1D15G10 +# include "s1d15g10.h" +#endif + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ + +/* Configuration **********************************************************************/ +/* Verify that all configuration requirements have been met */ + +/* Nokia 6100 Configuration Settings: + * + * CONFIG_NOKIA6100_SPIMODE - Controls the SPI mode + * CONFIG_NOKIA6100_FREQUENCY - Define to use a different bus frequency + * CONFIG_NOKIA6100_NINTERFACES - Specifies the number of physical Nokia 6100 devices that + * will be supported. + * CONFIG_NOKIA6100_BPP - Device supports 8, 12, and 16 bits per pixel. + * CONFIG_NOKIA6100_S1D15G10 - Selects the Epson S1D15G10 display controller + * CONFIG_NOKIA6100_PCF8833 - Selects the Phillips PCF8833 display controller + * CONFIG_NOKIA6100_BLINIT - Initial backlight setting + * + * The following may need to be tuned for your hardware: + * CONFIG_NOKIA6100_INVERT - Display inversion, 0 or 1, Default: 1 + * CONFIG_NOKIA6100_MY - Display row direction, 0 or 1, Default: 0 + * CONFIG_NOKIA6100_MX - Display column direction, 0 or 1, Default: 1 + * CONFIG_NOKIA6100_V - Display address direction, 0 or 1, Default: 0 + * CONFIG_NOKIA6100_ML - Display scan direction, 0 or 1, Default: 0 + * CONFIG_NOKIA6100_RGBORD - Display RGB order, 0 or 1, Default: 0 + * + * Required LCD driver settings: + * CONFIG_LCD_NOKIA6100 - Enable Nokia 6100 support + * CONFIG_LCD_MAXCONTRAST - must be 63 with the Epson controller and 127 with + * the Phillips controller. + * CONFIG_LCD_MAXPOWER - Maximum value of backlight setting. The backlight control is + * managed outside of the 6100 driver so this value has no meaning to the driver. + */ + +/* Mode 0,0 should be use. However, somtimes you need to tinker with these things. */ + +#ifndef CONFIG_NOKIA6100_SPIMODE +# define CONFIG_NOKIA6100_SPIMODE SPIDEV_MODE0 +#endif + +/* Default frequency: 1Mhz */ + +#ifndef CONFIG_NOKIA6100_FREQUENCY +# define CONFIG_NOKIA6100_FREQUENCY 1000000 +#endif + +/* CONFIG_NOKIA6100_NINTERFACES determines the number of physical interfaces + * that will be supported. + */ + +#ifndef CONFIG_NOKIA6100_NINTERFACES +# define CONFIG_NOKIA6100_NINTERFACES 1 +#endif + +#if CONFIG_NOKIA6100_NINTERFACES != 1 +# error "This implementation supports only a single LCD device" +#endif + +/* Only support for 8 and 12 BPP currently implemented */ + +#if !defined(CONFIG_NOKIA6100_BPP) +# warning "Assuming 8BPP" +# define CONFIG_NOKIA6100_BPP 8 +#endif + +#if CONFIG_NOKIA6100_BPP != 8 && CONFIG_NOKIA6100_BPP != 12 +# if CONFIG_NOKIA6100_BPP == 16 +# error "Support for 16BPP no yet implemented" +# else +# error "LCD supports only 8, 12, and 16BPP" +# endif +#endif + +#if CONFIG_NOKIA6100_BPP == 8 +# ifdef CONFIG_NX_DISABLE_8BPP +# warning "8-bit pixel support needed" +# endif +#elif CONFIG_NOKIA6100_BPP == 12 +# if defined(CONFIG_NX_DISABLE_12BPP) || !defined(CONFIG_NX_PACKEDMSFIRST) +# warning "12-bit, big-endian pixel support needed" +# endif +#elif CONFIG_NOKIA6100_BPP == 16 +# ifdef CONFIG_NX_DISABLE_16BPP +# warning "16-bit pixel support needed" +# endif +#endif + +/* Exactly one LCD controller must be selected. "The Olimex boards have both display + * controllers possible; if the LCD has a GE-12 sticker on it, it’s a Philips PCF8833. + * If it has a GE-8 sticker, it’s an Epson controller." + */ + +#if defined(CONFIG_NOKIA6100_S1D15G10) && defined(CONFIG_NOKIA6100_PCF8833) +# error "Both CONFIG_NOKIA6100_S1D15G10 and CONFIG_NOKIA6100_PCF8833 are defined" +#endif + +#if !defined(CONFIG_NOKIA6100_S1D15G10) && !defined(CONFIG_NOKIA6100_PCF8833) +# error "One of CONFIG_NOKIA6100_S1D15G10 or CONFIG_NOKIA6100_PCF8833 must be defined" +#endif + +/* Delay geometry defaults */ + +#ifndef CONFIG_NOKIA6100_INVERT +# define CONFIG_NOKIA6100_INVERT 1 +#endif + +#ifndef CONFIG_NOKIA6100_MY +# define CONFIG_NOKIA6100_MY 0 +#endif + +#ifndef CONFIG_NOKIA6100_MX +# define CONFIG_NOKIA6100_MX 1 +#endif + +#ifndef CONFIG_NOKIA6100_V +# define CONFIG_NOKIA6100_V 0 +#endif + +#ifndef CONFIG_NOKIA6100_ML +# define CONFIG_NOKIA6100_ML 0 +#endif + +#ifndef CONFIG_NOKIA6100_RGBORD +# define CONFIG_NOKIA6100_RGBORD 0 +#endif + +/* Check contrast selection */ + +#ifdef CONFIG_NOKIA6100_S1D15G10 + +# if !defined(CONFIG_LCD_MAXCONTRAST) +# define CONFIG_LCD_MAXCONTRAST 63 +# endif +# if CONFIG_LCD_MAXCONTRAST != 63 +# error "CONFIG_LCD_MAXCONTRAST must be 63 with the Epson LCD controller" +# endif +# define NOKIA_DEFAULT_CONTRAST 32 + +#else /* CONFIG_NOKIA6100_PCF8833 */ + +# if !defined(CONFIG_LCD_MAXCONTRAST) +# define CONFIG_LCD_MAXCONTRAST 127 +# endif +# if CONFIG_LCD_MAXCONTRAST != 127 +# error "CONFIG_LCD_MAXCONTRAST must be 127 with the Phillips LCD controller" +# endif +# define NOKIA_DEFAULT_CONTRAST 48 + +#endif + +/* Check initial backlight setting */ + +#ifndef CONFIG_NOKIA6100_BLINIT +# define CONFIG_NOKIA6100_BLINIT (NOKIA_DEFAULT_CONTRAST/3) +#endif + +/* Word width must be 9 bits */ + +#if defined(CONFIG_NOKIA6100_WORDWIDTH) && CONFIG_NOKIA6100_WORDWIDTH != 9 +# error "CONFIG_NOKIA6100_WORDWIDTH must be 9" +#endif +#ifndef CONFIG_NOKIA6100_WORDWIDTH +# define CONFIG_NOKIA6100_WORDWIDTH 9 +#endif + +/* If bit 9 is set, the byte is data; clear for commands */ + +#define NOKIA_LCD_DATA (1 << 8) + +/* Define CONFIG_LCD_REGDEBUG to enable register-level debug output. + * (Verbose debug must also be enabled) + */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_GRAPHICS +#endif + +#ifndef CONFIG_DEBUG_VERBOSE +# undef CONFIG_LCD_REGDEBUG +#endif + +/* Controller independent definitions *************************************************/ + +#ifdef CONFIG_NOKIA6100_PCF8833 +# define LCD_NOP PCF8833_NOP +# define LCD_RAMWR PCF8833_RAMWR +# define LCD_PASET PCF8833_PASET +# define LCD_CASET PCF8833_CASET +#endif +#ifdef CONFIG_NOKIA6100_S1D15G10 +# define LCD_NOP S1D15G10_NOP +# define LCD_RAMWR S1D15G10_RAMWR +# define LCD_PASET S1D15G10_PASET +# define LCD_CASET S1D15G10_CASET +#endif + +/* Color Properties *******************************************************************/ + +/* Display Resolution */ + +#define NOKIA_XRES 132 +#define NOKIA_YRES 132 + +/* Color depth and format */ + +#if CONFIG_NOKIA6100_BPP == 8 +# define NOKIA_BPP 8 +# define NOKIA_COLORFMT FB_FMT_RGB8_332 +# define NOKIA_STRIDE NOKIA_XRES +# define NOKIA_PIX2BYTES(p) (p) +#elif CONFIG_NOKIA6100_BPP == 12 +# define NOKIA_BPP 12 +# define NOKIA_COLORFMT FB_FMT_RGB12_444 +# define NOKIA_STRIDE ((3*NOKIA_XRES+1)/2) +# define NOKIA_PIX2BYTES(p) ((3*(p)+1)/2) +#elif CONFIG_NOKIA6100_BPP == 16 +# define NOKIA_BPP 16 +# define NOKIA_COLORFMT FB_FMT_RGB16_565 +# define NOKIA_STRIDE (2*NOKIA_XRES) +# define NOKIA_PIX2BYTES(p) (2*(p)) +#endif + +/* Handle any potential strange behavior at edges */ + +#if 0 /* REVISIT */ +#define NOKIA_PGBIAS 2 /* May not be necessary */ +#define NOKIA_COLBIAS 0 +#define NOKIA_XBIAS 2 /* May not be necessary, if so need to subtract from XRES */ +#define NOKIA_YBIAS 0 +#else +#define NOKIA_PGBIAS 0 +#define NOKIA_COLBIAS 0 +#define NOKIA_XBIAS 0 +#define NOKIA_YBIAS 0 +#endif + +#define NOKIA_ENDPAGE 131 +#define NOKIA_ENDCOL 131 + +/* Debug ******************************************************************************/ + +#ifdef CONFIG_LCD_REGDEBUG +# define lcddbg(format, arg...) llvdbg(format, ##arg) +#else +# define lcddbg(x...) +#endif + +/************************************************************************************** + * Private Type Definition + **************************************************************************************/ + +/* This structure describes the state of this driver */ + +struct nokia_dev_s +{ + /* Publically visible device structure */ + + struct lcd_dev_s dev; + + /* Private LCD-specific information follows */ + + FAR struct spi_dev_s *spi; /* Contained SPI driver instance */ + uint8_t contrast; /* Current contrast setting */ + uint8_t power; /* Current power (backlight) setting */ +}; + +/************************************************************************************** + * Private Function Protototypes + **************************************************************************************/ + +/* SPI support */ + +static inline void nokia_configspi(FAR struct spi_dev_s *spi); +#ifdef CONFIG_SPI_OWNBUS +static inline void nokia_select(FAR struct spi_dev_s *spi); +static inline void nokia_deselect(FAR struct spi_dev_s *spi); +#else +static void nokia_select(FAR struct spi_dev_s *spi); +static void nokia_deselect(FAR struct spi_dev_s *spi); +#endif +static void nokia_sndcmd(FAR struct spi_dev_s *spi, const uint8_t cmd); +static void nokia_cmdarray(FAR struct spi_dev_s *spi, int len, const uint8_t *cmddata); +static void nokia_clrram(FAR struct spi_dev_s *spi); + +/* LCD Data Transfer Methods */ + +static int nokia_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels); +static int nokia_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels); + +/* LCD Configuration */ + +static int nokia_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo); +static int nokia_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo); + +/* LCD RGB Mapping */ + +#ifdef CONFIG_FB_CMAP +# error "RGB color mapping not supported by this driver" +#endif + +/* Cursor Controls */ + +#ifdef CONFIG_FB_HWCURSOR +# error "Cursor control not supported by this driver" +#endif + +/* LCD Specific Controls */ + +static int nokia_getpower(struct lcd_dev_s *dev); +static int nokia_setpower(struct lcd_dev_s *dev, int power); +static int nokia_getcontrast(struct lcd_dev_s *dev); +static int nokia_setcontrast(struct lcd_dev_s *dev, unsigned int contrast); + +/* Initialization */ + +static int nokia_initialize(struct nokia_dev_s *priv); + +/************************************************************************************** + * Private Data + **************************************************************************************/ + +/* This is working memory allocated by the LCD driver for each LCD device + * and for each color plane. This memory will hold one raster line of data. + * The size of the allocated run buffer must therefore be at least + * (bpp * xres / 8). Actual alignment of the buffer must conform to the + * bitwidth of the underlying pixel type. + * + * If there are multiple planes, they may share the same working buffer + * because different planes will not be operate on concurrently. However, + * if there are multiple LCD devices, they must each have unique run buffers. + */ + +#if CONFIG_NOKIA6100_BPP == 8 +static uint8_t g_runbuffer[NOKIA_XRES]; +#elif CONFIG_NOKIA6100_BPP == 12 +static uint8_t g_runbuffer[(3*NOKIA_XRES+1)/2]; +#else /* CONFIG_NOKIA6100_BPP == 16 */ +static uint16_t g_runbuffer[NOKIA_XRES]; +#endif + +/* g_rowbuf is another buffer, but used internally by the Nokia 6100 driver in order + * expand the pixel data into 9-bit data needed by the LCD. There are some + * customizations that would eliminate the need for this extra buffer and for the + * extra expansion/copy, but those customizations would require a special, non-standard + * SPI driver that could expand 8- to 9-bit data on the fly. + */ + +static uint16_t g_rowbuf[NOKIA_STRIDE+1]; + +/* Device Driver Data Structures ******************************************************/ + +/* This structure describes the overall LCD video controller */ + +static const struct fb_videoinfo_s g_videoinfo = +{ + .fmt = NOKIA_COLORFMT, /* Color format: RGB16-565: RRRR RGGG GGGB BBBB */ + .xres = NOKIA_XRES, /* Horizontal resolution in pixel columns */ + .yres = NOKIA_YRES, /* Vertical resolution in pixel rows */ + .nplanes = 1, /* Number of color planes supported */ +}; + +/* This is the standard, NuttX Plane information object */ + +static const struct lcd_planeinfo_s g_planeinfo = +{ + .putrun = nokia_putrun, /* Put a run into LCD memory */ + .getrun = nokia_getrun, /* Get a run from LCD memory */ + .buffer = (uint8_t*)g_runbuffer, /* Run scratch buffer */ + .bpp = NOKIA_BPP, /* Bits-per-pixel */ +}; + +/* This is the standard, NuttX LCD driver object */ + +static struct nokia_dev_s g_lcddev = +{ + .dev = + { + /* LCD Configuration */ + + .getvideoinfo = nokia_getvideoinfo, + .getplaneinfo = nokia_getplaneinfo, + + /* LCD RGB Mapping -- Not supported */ + /* Cursor Controls -- Not supported */ + + /* LCD Specific Controls */ + + .getpower = nokia_getpower, + .setpower = nokia_setpower, + .getcontrast = nokia_getcontrast, + .setcontrast = nokia_setcontrast, + }, +}; + +/* LCD Command Strings ****************************************************************/ + +#ifdef CONFIG_NOKIA6100_S1D15G10 +/* Display control: + * P1: Specifies the CL dividing ratio, F1 and F2 drive-pattern switching period. + * P2: Specifies the duty of the module on block basis + * P3: Specify number of lines to be inversely highlighted on LCD panel + * P4: 0: Dispersion P40= 1: Non-dispersion + */ + +#if 1 // CONFIG_NOKIA6100_BPP == 12 +static const uint8_t g_disctl[] = +{ + S1D15G10_DISCTL, /* Display control */ + DISCTL_CLDIV_2|DISCTL_PERIOD_8, /* P1: Divide clock by 2; switching period = 8 */ +//DISCTL_CLDIV_NONE|DISCTL_PERIOD_8, /* P1: No clock division; switching period = 8 */ + 32, /* P2: nlines/4 - 1 = 132/4 - 1 = 32 */ + 0, /* P3: No inversely highlighted lines */ + 0 /* P4: No disperion */ +}; +#else /* CONFIG_NOKIA6100_BPP == 8 */ +static const uint8_t g_disctl[] = +{ + S1D15G10_DISCTL, /* Display control */ + DISCTL_CLDIV_2|DISCTL_PERIOD_FLD, /* P1: Divide clock by 2; switching period = field */ + 32, /* P2: nlines/4 - 1 = 132/4 - 1 = 32 */ + 0, /* P3: No inversely highlighted lines */ + 0 /* P4: No disperion */ +}; +#endif + +/* Common scan direction: + * P1: Cpecify the common output scan direction. + */ + +static const uint8_t g_comscn[] = +{ + S1D15G10_COMSCN, /* Common scan direction */ + 1 /* 0x01 = Scan 1->68, 132<-69 */ +}; + +/* Power control: + * P1: Turn on or off the liquid crystal driving power circuit, booster/step-down + * circuits and voltage follower circuit. + */ + +static const uint8_t g_pwrctr[] = +{ + S1D15G10_PWRCTR, /* Power control */ + PWCTR_REFVOLTAGE|PWCTR_REGULATOR|PWCTR_BOOSTER2|PWCTR_BOOSTER1 +}; + +/* Data control: + * P1: Specify the normal or inverse display of the page address and also to specify + * the page address scanning direction + * P2: RGB sequence + * P3: Grayscale setup + */ + +static const uint8_t g_datctl[] = +{ + S1D15G10_DATCTL, /* Data control */ + 0 +#if CONFIG_NOKIA6100_MY != 0 /* Display row direction */ + |DATCTL_PGADDR_INV /* Page address inverted */ +#endif +#if CONFIG_NOKIA6100_MX != 0 /* Display column direction */ + |DATCTL_COLADDR_REV /* Column address reversed */ +#endif +#if CONFIG_NOKIA6100_V != 0 /* Display address direction */ + |DATCTL_ADDR_PGDIR /* Address scan in page direction */ +#endif + , +#if CONFIG_NOKIA6100_RGBORD != 0 + DATCTL_BGR, /* RGB->BGR */ +#else + 0, /* RGB->RGB */ +#endif +#if CONFIG_NOKIA6100_BPP == 8 + DATCTL_8GRAY /* Selects 8-bit color */ +#elif CONFIG_NOKIA6100_BPP == 12 + DATCTL_16GRAY_A /* Selects 16-bit color, Type A */ +#else +# error "16-bit mode not yet implemented" +#endif +}; + +/* Voltage control (contrast setting): + * P1: Volume value + * P2: Resistance ratio + * (May need to be tuned for individual displays) + */ + +static const uint8_t g_volctr[] = +{ + S1D15G10_VOLCTR, /* Volume control */ + NOKIA_DEFAULT_CONTRAST, /* Volume value */ + 2 /* Resistance ratio */ +}; + +/* 256-color position set (RGBSET8) */ + +#if CONFIG_NOKIA6100_BPP == 8 +static const uint8_t g_rgbset8[] = +{ + S1D15G10_RGBSET8, /* 256-color position set */ + 0, 2, 4, 6, 9, 11, 13, 15, /* Red tones */ + 0, 2, 4, 6, 9, 11, 13, 15, /* Green tones */ + 0, 5, 10, 15 /* Blue tones */ +}; +#endif + +/* Page address set (PASET) */ + +static const uint8_t g_paset[] = +{ + S1D15G10_PASET, /* Page start address set */ + NOKIA_PGBIAS, + 131 +}; + +/* Column address set (CASET) */ + +static const uint8_t g_caset[] = +{ + S1D15G10_CASET, /* Column start address set */ + NOKIA_COLBIAS, + 131 +}; +#endif /* CONFIG_NOKIA6100_S1D15G10 */ + +#ifdef CONFIG_NOKIA6100_PCF8833 + +/* Color interface pixel format (COLMOD) */ + +#if CONFIG_NOKIA6100_BPP == 12 +static const uint8_t g_colmod[] = +{ + PCF8833_COLMOD, /* Color interface pixel format */ + PCF8833_FMT_12BPS /* 12 bits-per-pixel */ +}; +#else /* CONFIG_NOKIA6100_BPP == 8 */ +static const uint8_t g_colmod[] = +{ + PCF8833_COLMOD, /* Color interface pixel format */ + PCF8833_FMT_8BPS /* 8 bits-per-pixel */ +}; +#endif + +/* Memory data access control(MADCTL) */ + +static const uint8_t g_madctl[] = +{ + PCF8833_MADCTL, /* Memory data access control*/ + 0 +#ifdef CONFIG_NOKIA6100_RGBORD != 0 + |MADCTL_RGB /* RGB->BGR */ +#endif +#ifdef CONFIG_NOKIA6100_MY != 0 /* Display row direction */ + |MADCTL_MY /* Mirror Y */ +#endif +#ifdef CONFIG_NOKIA6100_MX != 0 /* Display column direction */ + |MADCTL_MX /* Mirror X */ +#endif +#ifdef CONFIG_NOKIA6100_V != 0 /* Display address direction */ + |MADCTL_V /* ertical RAM write; in Y direction */ +#endif +#ifdef CONFIG_NOKIA6100_ML != 0 /* Display scan direction */ + |MADCTL_LAO /* Line address order bottom to top */ +#endif +}; + +/* Set contrast (SETCON) */ + +static const uint8_t g_setcon[] = +{ + PCF8833_SETCON, /* Set contrast */ + NOKIA_DEFAULT_CONTRAST +}; + +#endif /* CONFIG_NOKIA6100_PCF8833 */ + +/************************************************************************************** + * Private Functions + **************************************************************************************/ + +/************************************************************************************** + * Function: nokia_configspi + * + * Description: + * Configure the SPI for use with the Nokia 6100 + * + * Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + **************************************************************************************/ + +static inline void nokia_configspi(FAR struct spi_dev_s *spi) +{ + lcddbg("Mode: %d Bits: %d Frequency: %d\n", + CONFIG_NOKIA6100_SPIMODE, CONFIG_NOKIA6100_WORDWIDTH, CONFIG_NOKIA6100_FREQUENCY); + + /* Configure SPI for the Nokia 6100. But only if we own the SPI bus. Otherwise, don't + * bother because it might change. + */ + +#ifdef CONFIG_SPI_OWNBUS + SPI_SETMODE(spi, CONFIG_NOKIA6100_SPIMODE); + SPI_SETBITS(spi, CONFIG_NOKIA6100_WORDWIDTH); + SPI_SETFREQUENCY(spi, CONFIG_NOKIA6100_FREQUENCY) +#endif +} + +/************************************************************************************** + * Function: nokia_select + * + * Description: + * Select the SPI, locking and re-configuring if necessary + * + * Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + **************************************************************************************/ + +#ifdef CONFIG_SPI_OWNBUS +static inline void nokia_select(FAR struct spi_dev_s *spi) +{ + /* We own the SPI bus, so just select the chip */ + + lcddbg("SELECTED\n"); + SPI_SELECT(spi, SPIDEV_DISPLAY, true); +} +#else +static void nokia_select(FAR struct spi_dev_s *spi) +{ + /* Select Nokia 6100 chip (locking the SPI bus in case there are multiple + * devices competing for the SPI bus + */ + + lcddbg("SELECTED\n"); + SPI_LOCK(spi, true); + SPI_SELECT(spi, SPIDEV_DISPLAY, true); + + /* Now make sure that the SPI bus is configured for the Nokia 6100 (it + * might have gotten configured for a different device while unlocked) + */ + + SPI_SETMODE(spi, CONFIG_NOKIA6100_SPIMODE); + SPI_SETBITS(spi, CONFIG_NOKIA6100_WORDWIDTH); + SPI_SETFREQUENCY(spi, CONFIG_NOKIA6100_FREQUENCY); +} +#endif + +/************************************************************************************** + * Function: nokia_deselect + * + * Description: + * De-select the SPI + * + * Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + **************************************************************************************/ + +#ifdef CONFIG_SPI_OWNBUS +static inline void nokia_deselect(FAR struct spi_dev_s *spi) +{ + /* We own the SPI bus, so just de-select the chip */ + + lcddbg("DE-SELECTED\n"); + SPI_SELECT(spi, SPIDEV_DISPLAY, false); +} +#else +static void nokia_deselect(FAR struct spi_dev_s *spi) +{ + /* De-select Nokia 6100 chip and relinquish the SPI bus. */ + + lcddbg("DE-SELECTED\n"); + SPI_SELECT(spi, SPIDEV_DISPLAY, false); + SPI_LOCK(spi, false); +} +#endif + +/************************************************************************************** + * Name: nokia_sndcmd + * + * Description: + * Send a 1-byte command. + * + **************************************************************************************/ + +static void nokia_sndcmd(FAR struct spi_dev_s *spi, const uint8_t cmd) +{ + /* Select the LCD */ + + lcddbg("cmd: %02x\n", cmd); + nokia_select(spi); + + /* Send the command. Bit 8 == 0 denotes a command */ + + (void)SPI_SEND(spi, (uint16_t)cmd); + + /* De-select the LCD */ + + nokia_deselect(spi); +} + +/************************************************************************************** + * Name: nokia_cmddata + * + * Description: + * Send a 1-byte command followed by datlen data bytes. + * + **************************************************************************************/ + +static void nokia_cmddata(FAR struct spi_dev_s *spi, uint8_t cmd, int datlen, + const uint8_t *data) +{ + uint16_t *rowbuf = g_rowbuf; + int i; + + lcddbg("cmd: %02x datlen: %d\n", cmd, datlen); + DEBUGASSERT(datlen <= NOKIA_STRIDE); + + /* Copy the command into the line buffer. Bit 8 == 0 denotes a command. */ + + *rowbuf++ = cmd; + + /* Copy any data after the command into the line buffer */ + + for (i = 0; i < datlen; i++) + { + /* Bit 8 == 1 denotes data */ + + *rowbuf++ = (uint16_t)*data++ | NOKIA_LCD_DATA; + } + + /* Select the LCD */ + + nokia_select(spi); + + /* Send the line buffer. */ + + (void)SPI_SNDBLOCK(spi, g_rowbuf, datlen+1); + + /* De-select the LCD */ + + nokia_deselect(spi); +} + +/************************************************************************************** + * Name: nokia_ramwr + * + * Description: + * Send a RAMWR command followed by datlen data bytes. + * + **************************************************************************************/ + +static void nokia_ramwr(FAR struct spi_dev_s *spi, int datlen, const uint8_t *data) +{ + nokia_cmddata(spi, LCD_RAMWR, datlen, data); +} + +/************************************************************************************** + * Name: nokia_cmdarray + * + * Description: + * Send a RAMWR command followed by len-1 data bytes. + * + **************************************************************************************/ + +static void nokia_cmdarray(FAR struct spi_dev_s *spi, int len, const uint8_t *cmddata) +{ +#ifdef CONFIG_LCD_REGDEBUG + int i; + + for (i = 0; i < len; i++) + { + lcddbg("cmddata[%d]: %02x\n", i, cmddata[i]); + } +#endif + nokia_cmddata(spi, cmddata[0], len-1, &cmddata[1]); +} + +/************************************************************************************** + * Name: nokia_clrram + * + * Description: + * Send a 1-byte command followed by len-1 data bytes. + * + **************************************************************************************/ + +static void nokia_clrram(FAR struct spi_dev_s *spi) +{ + uint16_t *rowbuf = g_rowbuf; + int i; + + /* Set all zero data in the line buffer */ + + for (i = 0; i < NOKIA_STRIDE; i++) + { + /* Bit 8 == 1 denotes data */ + + *rowbuf++ = NOKIA_LCD_DATA; + } + + /* Select the LCD and send the RAMWR command */ + + nokia_select(spi); + SPI_SEND(spi, LCD_RAMWR); + + /* Send the line buffer, once for each row. */ + + for (i = 0; i < NOKIA_YRES; i++) + { + (void)SPI_SNDBLOCK(spi, g_rowbuf, NOKIA_STRIDE); + } + + /* De-select the LCD */ + + nokia_deselect(spi); +} + +/************************************************************************************** + * Name: nokia_putrun + * + * Description: + * This method can be used to write a partial raster line to the LCD: + * + * row - Starting row to write to (range: 0 <= row < yres) + * col - Starting column to write to (range: 0 <= col <= xres-npixels) + * buffer - The buffer containing the run to be written to the LCD + * npixels - The number of pixels to write to the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +static int nokia_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels) +{ + struct nokia_dev_s *priv = &g_lcddev; + FAR struct spi_dev_s *spi = priv->spi; + uint16_t cmd[3]; + + gvdbg("row: %d col: %d npixels: %d\n", row, col, npixels); + +#if NOKIA_XBIAS > 0 + col += NOKIA_XBIAS; +#endif +#if NOKIA_YBIAS > 0 + row += NOKIA_YBIAS; +#endif + DEBUGASSERT(buffer && col >=0 && (col + npixels) <= NOKIA_XRES && row >= 0 && row < NOKIA_YRES); + + /* Set up to write the run. */ + + nokia_select(spi); + cmd[0] = LCD_PASET; + cmd[1] = col | NOKIA_LCD_DATA; + cmd[2] = NOKIA_ENDPAGE | NOKIA_LCD_DATA; + (void)SPI_SNDBLOCK(spi, cmd, 3); + nokia_deselect(spi); + + /* De-select the LCD */ + + nokia_select(spi); + cmd[0] = LCD_CASET; + cmd[1] = row | NOKIA_LCD_DATA; + cmd[2] = NOKIA_ENDCOL | NOKIA_LCD_DATA; + (void)SPI_SNDBLOCK(spi, cmd, 3); + nokia_deselect(spi); + + /* Then send the run */ + + nokia_ramwr(spi, NOKIA_PIX2BYTES(npixels), buffer); + return OK; +} + +/************************************************************************************** + * Name: nokia_getrun + * + * Description: + * This method can be used to read a partial raster line from the LCD: + * + * row - Starting row to read from (range: 0 <= row < yres) + * col - Starting column to read read (range: 0 <= col <= xres-npixels) + * buffer - The buffer in which to return the run read from the LCD + * npixels - The number of pixels to read from the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +static int nokia_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels) +{ + gvdbg("row: %d col: %d npixels: %d\n", row, col, npixels); + DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); + + /* At present, this is a write-only LCD driver */ + +#warning "Not implemented" + return -ENOSYS; +} + +/************************************************************************************** + * Name: nokia_getvideoinfo + * + * Description: + * Get information about the LCD video controller configuration. + * + **************************************************************************************/ + +static int nokia_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo) +{ + DEBUGASSERT(dev && vinfo); + gvdbg("fmt: %d xres: %d yres: %d nplanes: %d\n", + g_videoinfo.fmt, g_videoinfo.xres, g_videoinfo.yres, g_videoinfo.nplanes); + memcpy(vinfo, &g_videoinfo, sizeof(struct fb_videoinfo_s)); + return OK; +} + +/************************************************************************************** + * Name: nokia_getplaneinfo + * + * Description: + * Get information about the configuration of each LCD color plane. + * + **************************************************************************************/ + +static int nokia_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo) +{ + DEBUGASSERT(dev && pinfo && planeno == 0); + gvdbg("planeno: %d bpp: %d\n", planeno, g_planeinfo.bpp); + memcpy(pinfo, &g_planeinfo, sizeof(struct lcd_planeinfo_s)); + return OK; +} + +/************************************************************************************** + * Name: nokia_getpower + * + * Description: + * Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER: full on. On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int nokia_getpower(struct lcd_dev_s *dev) +{ + struct nokia_dev_s *priv = (struct nokia_dev_s *)dev; + gvdbg("power: %d\n", priv->power); + return priv->power; +} + +/************************************************************************************** + * Name: nokia_setpower + * + * Description: + * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int nokia_setpower(struct lcd_dev_s *dev, int power) +{ + struct nokia_dev_s *priv = (struct nokia_dev_s *)dev; + int ret; + + gvdbg("power: %d\n", power); + DEBUGASSERT(power <= CONFIG_LCD_MAXPOWER); + + /* Set new power level. The backlight power is controlled outside of the LCD + * assembly and must be managmed by board-specific logic. + */ + + ret = nokia_backlight(power); + if (ret == OK) + { + priv->power = power; + } + return ret; +} + +/************************************************************************************** + * Name: nokia_getcontrast + * + * Description: + * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int nokia_getcontrast(struct lcd_dev_s *dev) +{ + struct nokia_dev_s *priv = (struct nokia_dev_s *)dev; + gvdbg("contrast: %d\n", priv->contrast); + return priv->contrast; +} + +/************************************************************************************** + * Name: nokia_setcontrast + * + * Description: + * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int nokia_setcontrast(struct lcd_dev_s *dev, unsigned int contrast) +{ + struct nokia_dev_s *priv = (struct nokia_dev_s *)dev; + + if (contrast < CONFIG_LCD_MAXCONTRAST) + { +#ifdef CONFIG_NOKIA6100_S1D15G10 + while (priv->contrast < contrast) + { + nokia_sndcmd(priv->spi, S1D15G10_VOLUP); + priv->contrast++; + } + while (priv->contrast > contrast) + { + nokia_sndcmd(priv->spi, S1D15G10_VOLDOWN); + priv->contrast--; + } +#else /* CONFIG_NOKIA6100_PCF8833 */ + uint8_t cmd[2]; + + cmd[0] = PCF8833_SETCON; + cmd[1] = priv->contrast; + nokia_sndarry(priv->spi, 2, cmd); + priv->contrast = contrast; +#endif + } + + gvdbg("contrast: %d\n", contrast); + return -ENOSYS; +} + +/************************************************************************************** + * Name: nokia_initialize + * + * Description: + * Initialize the LCD controller. + * + **************************************************************************************/ + +#ifdef CONFIG_NOKIA6100_S1D15G10 +static int nokia_initialize(struct nokia_dev_s *priv) +{ + struct spi_dev_s *spi = priv->spi; + + /* Configure the display */ + + nokia_cmdarray(spi, sizeof(g_disctl), g_disctl); /* Display control */ + nokia_cmdarray(spi, sizeof(g_comscn), g_comscn); /* Common scan direction */ + nokia_sndcmd(spi, S1D15G10_OSCON); /* Internal oscilator ON */ + nokia_sndcmd(spi, S1D15G10_SLPOUT); /* Sleep out */ + nokia_cmdarray(spi, sizeof(g_volctr), g_volctr); /* Volume control (contrast) */ + nokia_cmdarray(spi, sizeof(g_pwrctr), g_pwrctr); /* Turn on voltage regulators */ + up_mdelay(100); +#ifdef CONFIG_NOKIA6100_INVERT + nokia_sndcmd(spi, S1D15G10_DISINV); /* Invert display */ +#else + nokia_sndcmd(spi, S1D15G10_DISNOR); /* Normal display */ +#endif + nokia_cmdarray(spi, sizeof(g_datctl), g_datctl); /* Data control */ +#if CONFIG_NOKIA6100_BPP == 8 + nokia_cmdarray(spi, sizeof(g_rgbset8), g_rgbset8); /* Set up color lookup table */ + nokia_sndcmd(spi, S1D15G10_NOP); +#endif + nokia_cmdarray(spi, sizeof(g_paset), g_paset); /* Page address set */ + nokia_cmdarray(spi, sizeof(g_paset), g_caset); /* Column address set */ + nokia_clrram(spi); + nokia_sndcmd(spi, S1D15G10_DISON); /* Display on */ + return OK; +} +#endif + +#ifdef CONFIG_NOKIA6100_PCF8833 +static int nokia_initialize(struct nokia_dev_s *priv) +{ + struct struct spi_dev_s *spi = priv->spi; + + nokia_sndcmd(spi, PCF8833_SLEEPOUT); /* Exit sleep mode */ + nokia_sndcmd(spi, PCF8833_BSTRON); /* Turn on voltage booster */ +#ifdef CONFIG_NOKIA6100_INVERT + nokia_sndcmd(spi, PCF8833_INVON); /* Invert display */ +#else + nokia_sndcmd(spi, PCF8833_INVOFF); /* Don't invert display */ +#endif + nokia_cmdarray(spi, sizeof(g_madctl), g_madctl); /* Memory data access control */ + nokia_cmdarray(spi, sizeof(g_colmod), g_colmod); /* Color interface pixel format */ + nokia_cmdarray(spi, sizeof(g_setcon), g_setcon); /* Set contrast */ + nokia_sndcmd(spi, PCF8833_NOP); /* No operation */ + nokia_clrram(spi); + nokia_sndcmd(spi, PCF8833_DISPON); /* Display on */ + return OK; +} +#endif /* CONFIG_NOKIA6100_PCF8833 */ + +/************************************************************************************** + * Public Functions + **************************************************************************************/ + +/************************************************************************************** + * Name: nokia_lcdinitialize + * + * Description: + * Initialize the NOKIA6100 video hardware. The initial state of the LCD is fully + * initialized, display memory cleared, and the LCD ready to use, but with the power + * setting at 0 (full off == sleep mode). + * + * Input Parameters: + * + * spi - A reference to the SPI driver instance. + * devno - A value in the range of 0 throuh CONFIG_NOKIA6100_NINTERFACES-1. This + * allows support for multiple LCD devices. + * + * Returned Value: + * + * On success, this function returns a reference to the LCD object for the specified + * LCD. NULL is returned on any failure. + * + **************************************************************************************/ + +FAR struct lcd_dev_s *nokia_lcdinitialize(FAR struct spi_dev_s *spi, unsigned int devno) +{ + struct nokia_dev_s *priv = &g_lcddev; + + gvdbg("Initializing\n"); + DEBUGASSERT(devno == 0); + + /* Initialize the driver data structure */ + + priv->spi = spi; /* Save the SPI instance */ + priv->contrast = NOKIA_DEFAULT_CONTRAST; /* Initial contrast setting */ + + /* Configure and enable the LCD controller */ + + nokia_configspi(spi); + if (nokia_initialize(priv) == OK) + { + /* Turn on the backlight */ + + nokia_backlight(CONFIG_NOKIA6100_BLINIT); + return &priv->dev; + } + return NULL; +} diff --git a/nuttx/drivers/lcd/p14201.c b/nuttx/drivers/lcd/p14201.c new file mode 100644 index 0000000000..934d251ca9 --- /dev/null +++ b/nuttx/drivers/lcd/p14201.c @@ -0,0 +1,1246 @@ +/************************************************************************************** + * drivers/lcd/p14201.c + * Driver for RiT P14201 series display (wih sd1329 IC controller) + * + * Copyright (C) 2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "sd1329.h" + +#ifdef CONFIG_LCD_P14201 + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ + +/* Configuration **********************************************************************/ + +/* P14201 Configuration Settings: + * + * CONFIG_P14201_SPIMODE - Controls the SPI mode + * CONFIG_P14201_FREQUENCY - Define to use a different bus frequency + * CONFIG_P14201_NINTERFACES - Specifies the number of physical P14201 devices that + * will be supported. + * CONFIG_P14201_FRAMEBUFFER - If defined, accesses will be performed using an in-memory + * copy of the OLEDs GDDRAM. This cost of this buffer is 128 * 96 / 2 = 6Kb. If this + * is defined, then the driver will be fully functional. If not, then it will have the + * following limitations: + * + * - Reading graphics memory cannot be supported, and + * - All pixel writes must be aligned to byte boundaries. + * + * The latter limitation effectively reduces the 128x96 disply to 64x96. + * + * Required LCD driver settings: + * CONFIG_LCD_P14201 - Enable P14201 support + * CONFIG_LCD_MAXCONTRAST should be 255, but any value >0 and <=255 will be accepted. + * CONFIG_LCD_MAXPOWER must be 1 + * + * Required SPI driver settings: + * CONFIG_SPI_CMDDATA - Include support for cmd/data selection. + */ + +#ifndef CONFIG_SPI_CMDDATA +# error "CONFIG_SPI_CMDDATA must be defined in your NuttX configuration" +#endif + +/* The P14201 spec says that is supports SPI mode 0,0 only. However, + * somtimes you need to tinker with these things. + */ + +#ifndef CONFIG_P14201_SPIMODE +# define CONFIG_P14201_SPIMODE SPIDEV_MODE2 +#endif + +/* CONFIG_P14201_NINTERFACES determines the number of physical interfaces + * that will be supported. + */ + +#ifndef CONFIG_P14201_NINTERFACES +# define CONFIG_P14201_NINTERFACES 1 +#endif + +#if CONFIG_P14201_NINTERFACES != 1 +# error "This implementation supports only a single OLED device" +#endif + +/* Check contrast selection */ + +#if !defined(CONFIG_LCD_MAXCONTRAST) +# define CONFIG_LCD_MAXCONTRAST 255 +#endif + +#if CONFIG_LCD_MAXCONTRAST <= 0|| CONFIG_LCD_MAXCONTRAST > 255 +# error "CONFIG_LCD_MAXCONTRAST exceeds supported maximum" +#endif + +/* Check power setting */ + +#if !defined(CONFIG_LCD_MAXPOWER) +# define CONFIG_LCD_MAXPOWER 1 +#endif + +#if CONFIG_LCD_MAXPOWER != 1 +# warning "CONFIG_LCD_MAXPOWER exceeds supported maximum" +# undef CONFIG_LCD_MAXPOWER +# define CONFIG_LCD_MAXPOWER 1 +#endif + +/* Color is 4bpp greyscale with leftmost column contained in bits 7:4 */ + +#if defined(CONFIG_NX_DISABLE_4BPP) || !defined(CONFIG_NX_PACKEDMSFIRST) +# warning "4-bit, big-endian pixel support needed" +#endif + +/* Define the CONFIG_LCD_RITDEBUG to enable detailed debug output (stuff you would + * never want to see unless you are debugging this file). + * + * Verbose debug must also be enabled + */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_GRAPHICS +#endif + +#ifndef CONFIG_DEBUG_VERBOSE +# undef CONFIG_LCD_RITDEBUG +#endif + +/* Color Properties *******************************************************************/ + +/* Display Resolution */ + +#define RIT_XRES 128 +#define RIT_YRES 96 + +/* Color depth and format */ + +#define RIT_BPP 4 +#define RIT_COLORFMT FB_FMT_Y4 + +/* Default contrast */ + +#define RIT_CONTRAST ((23 * (CONFIG_LCD_MAXCONTRAST+1) / 32) - 1) + +/* Helper Macros **********************************************************************/ + +#define rit_sndcmd(p,b,l) rit_sndbytes(p,b,l,true); +#define rit_snddata(p,b,l) rit_sndbytes(p,b,l,false); + +/* Debug ******************************************************************************/ + +#ifdef CONFIG_LCD_RITDEBUG +# define ritdbg(format, arg...) vdbg(format, ##arg) +#else +# define ritdbg(x...) +#endif + +/************************************************************************************** + * Private Type Definition + **************************************************************************************/ + +/* This structure describes the state of this driver */ + +struct rit_dev_s +{ + struct lcd_dev_s dev; /* Publically visible device structure */ + FAR struct spi_dev_s *spi; /* Cached SPI device reference */ + uint8_t contrast; /* Current contrast setting */ + bool on; /* true: display is on */ +}; + +/************************************************************************************** + * Private Function Protototypes + **************************************************************************************/ + +/* Low-level SPI helpers */ + +static inline void rit_configspi(FAR struct spi_dev_s *spi); +#ifdef CONFIG_SPI_OWNBUS +static inline void rit_select(FAR struct spi_dev_s *spi); +static inline void rit_deselect(FAR struct spi_dev_s *spi); +#else +static void rit_select(FAR struct spi_dev_s *spi); +static void rit_deselect(FAR struct spi_dev_s *spi); +#endif +static void rit_sndbytes(FAR struct rit_dev_s *priv, FAR const uint8_t *buffer, + size_t buflen, bool cmd); +static void rit_sndcmds(FAR struct rit_dev_s *priv, FAR const uint8_t *table); + +/* LCD Data Transfer Methods */ + +static int rit_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels); +static int rit_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels); + +/* LCD Configuration */ + +static int rit_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo); +static int rit_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo); + +/* LCD RGB Mapping */ + +#ifdef CONFIG_FB_CMAP +# error "RGB color mapping not supported by this driver" +#endif + +/* Cursor Controls */ + +#ifdef CONFIG_FB_HWCURSOR +# error "Cursor control not supported by this driver" +#endif + +/* LCD Specific Controls */ + +static int rit_getpower(struct lcd_dev_s *dev); +static int rit_setpower(struct lcd_dev_s *dev, int power); +static int rit_getcontrast(struct lcd_dev_s *dev); +static int rit_setcontrast(struct lcd_dev_s *dev, unsigned int contrast); + +/************************************************************************************** + * Private Data + **************************************************************************************/ + +/* This is working memory allocated by the LCD driver for each LCD device + * and for each color plane. This memory will hold one raster line of data. + * The size of the allocated run buffer must therefore be at least + * (bpp * xres / 8). Actual alignment of the buffer must conform to the + * bitwidth of the underlying pixel type. + * + * If there are multiple planes, they may share the same working buffer + * because different planes will not be operate on concurrently. However, + * if there are multiple LCD devices, they must each have unique run buffers. + */ + +static uint8_t g_runbuffer[RIT_XRES / 2]; + +/* CONFIG_P14201_FRAMEBUFFER - If defined, accesses will be performed using an in-memory + * copy of the OLEDs GDDRAM. This cost of this buffer is 128 * 64 / 2 = 4Kb. If this + * is defined, then the driver will be full functional. If not, then: + * + * - Reading graphics memory cannot be supported, and + * - All pixel writes must be aligned to byte boundaries. + */ + +#ifdef CONFIG_P14201_FRAMEBUFFER +static uint8_t g_framebuffer[RIT_YRES * RIT_XRES / 2]; +#endif + +/* This structure describes the overall LCD video controller */ + +static const struct fb_videoinfo_s g_videoinfo = +{ + .fmt = RIT_COLORFMT, /* Color format: RGB16-565: RRRR RGGG GGGB BBBB */ + .xres = RIT_XRES, /* Horizontal resolution in pixel columns */ + .yres = RIT_YRES, /* Vertical resolution in pixel rows */ + .nplanes = 1, /* Number of color planes supported */ +}; + +/* This is the standard, NuttX Plane information object */ + +static const struct lcd_planeinfo_s g_planeinfo = +{ + .putrun = rit_putrun, /* Put a run into LCD memory */ + .getrun = rit_getrun, /* Get a run from LCD memory */ + .buffer = (uint8_t*)g_runbuffer, /* Run scratch buffer */ + .bpp = RIT_BPP, /* Bits-per-pixel */ +}; + +/* This is the OLED driver instance (only a single device is supported for now) */ + +static struct rit_dev_s g_oleddev = +{ + .dev = + { + /* LCD Configuration */ + + .getvideoinfo = rit_getvideoinfo, + .getplaneinfo = rit_getplaneinfo, + + /* LCD RGB Mapping -- Not supported */ + /* Cursor Controls -- Not supported */ + + /* LCD Specific Controls */ + + .getpower = rit_getpower, + .setpower = rit_setpower, + .getcontrast = rit_getcontrast, + .setcontrast = rit_setcontrast, + }, +}; + +/* A table of magic initialization commands. This initialization sequence is + * derived from RiT Application Note for the P14201 (with a few tweaked values + * as discovered in some Luminary code examples). + */ + +static const uint8_t g_initcmds[] = +{ + 3, SSD1329_CMD_LOCK, /* Set lock command */ + SSD1329_LOCK_OFF, /* Disable locking */ + SSD1329_NOOP, + 2, SSD1329_SLEEP_ON, /* Matrix display OFF */ + SSD1329_NOOP, + 3, SSD1329_ICON_ALL, /* Set all ICONs to OFF */ + SSD1329_ICON_OFF, /* OFF selection */ + SSD1329_NOOP, + 3, SSD1329_MUX_RATIO, /* Set MUX ratio */ + 95, /* 96 MUX */ + SSD1329_NOOP, + 3, SSD1329_SET_CONTRAST, /* Set contrast */ + RIT_CONTRAST, /* Default contrast */ + SSD1329_NOOP, + 3, SSD1329_PRECHRG2_SPEED, /* Set second pre-charge speed */ + (31 << 1) | SSD1329_PRECHRG2_DBL, /* Pre-charge speed == 32, doubled */ + SSD1329_NOOP, + 3, SSD1329_GDDRAM_REMAP, /* Set GDDRAM re-map */ + (SSD1329_COM_SPLIT| /* Enable COM slip even/odd */ + SSD1329_COM_REMAP| /* Enable COM re-map */ + SSD1329_NIBBLE_REMAP), /* Enable nibble re-map */ + SSD1329_NOOP, + 3, SSD1329_VERT_START, /* Set Display Start Line */ + 0, /* Line = 0 */ + SSD1329_NOOP, + 3, SSD1329_VERT_OFFSET, /* Set Display Offset */ + 0, /* Offset = 0 */ + SSD1329_NOOP, + 2, SSD1329_DISP_NORMAL, /* Display mode normal */ + SSD1329_NOOP, + 3, SSD1329_PHASE_LENGTH, /* Set Phase Length */ + 1 | /* Phase 1 period = 1 DCLK */ + (1 << 4), /* Phase 2 period = 1 DCLK */ + SSD1329_NOOP, + 3, SSD1329_FRAME_FREQ, + 35, /* 35 DCLK's per row */ + SSD1329_NOOP, + 3, SSD1329_DCLK_DIV, /* Set Front Clock Divider / Oscillator Frequency */ + 2 | /* Divide ration = 3 */ + (14 << 4), /* Oscillator Frequency, FOSC, setting */ + SSD1329_NOOP, + 17, SSD1329_GSCALE_LOOKUP, /* Look Up Table for Gray Scale Pulse width */ + 1, 2, 3, 4, 5, /* Value for GS1-5 level Pulse width */ + 6, 8, 10, 12, 14, /* Value for GS6-10 level Pulse width */ + 16, 19, 22, 26, 30, /* Value for GS11-15 level Pulse width */ + SSD1329_NOOP, + 3, SSD1329_PRECHRG2_PERIOD, /* Set Second Pre-charge Period */ + 1, /* 1 DCLK */ + SSD1329_NOOP, + 3, SSD1329_PRECHRG1_VOLT, /* Set First Precharge voltage, VP */ + 0x3f, /* 1.00 x Vcc */ + SSD1329_NOOP, + 0 /* Zero length command terminates table */ +}; + +/* Turn the maxtrix display on (sleep mode off) */ + +static const uint8_t g_sleepoff[] = +{ + SSD1329_SLEEP_OFF, /* Matrix display ON */ + SSD1329_NOOP, +}; + +/* Turn the maxtrix display off (sleep mode on) */ + +static const uint8_t g_sleepon[] = +{ + SSD1329_SLEEP_ON, /* Matrix display OFF */ + SSD1329_NOOP, +}; + +/* Set horizontal increment mode */ + +static const uint8_t g_horzinc[] = +{ + SSD1329_GDDRAM_REMAP, + (SSD1329_COM_SPLIT|SSD1329_COM_REMAP|SSD1329_NIBBLE_REMAP), +}; + +/* The following set a window that covers the entire display */ + +static const uint8_t g_setallcol[] = +{ + SSD1329_SET_COLADDR, + 0, + (RIT_XRES/2)-1 +}; + +static const uint8_t g_setallrow[] = +{ + SSD1329_SET_ROWADDR, + 0, + RIT_YRES-1 +}; + +/************************************************************************************** + * Private Functions + **************************************************************************************/ + +/************************************************************************************** + * Name: rit_configspi + * + * Description: + * Configure the SPI for use with the P14201 + * + * Input Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + **************************************************************************************/ + +static inline void rit_configspi(FAR struct spi_dev_s *spi) +{ +#ifdef CONFIG_P14201_FREQUENCY + ritdbg("Mode: %d Bits: 8 Frequency: %d\n", + CONFIG_P14201_SPIMODE, CONFIG_P14201_FREQUENCY); +#else + ritdbg("Mode: %d Bits: 8\n", CONFIG_P14201_SPIMODE); +#endif + + /* Configure SPI for the P14201. But only if we own the SPI bus. Otherwise, don't + * bother because it might change. + */ + +#ifdef CONFIG_SPI_OWNBUS + SPI_SETMODE(spi, CONFIG_P14201_SPIMODE); + SPI_SETBITS(spi, 8); +#ifdef CONFIG_P14201_FREQUENCY + SPI_SETFREQUENCY(spi, CONFIG_P14201_FREQUENCY) +#endif +#endif +} + +/************************************************************************************** + * Name: rit_select + * + * Description: + * Select the SPI, locking and re-configuring if necessary + * + * Input Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + **************************************************************************************/ + +#ifdef CONFIG_SPI_OWNBUS +static inline void rit_select(FAR struct spi_dev_s *spi) +{ + /* We own the SPI bus, so just select the chip */ + + SPI_SELECT(spi, SPIDEV_DISPLAY, true); +} +#else +static void rit_select(FAR struct spi_dev_s *spi) +{ + /* Select P14201 chip (locking the SPI bus in case there are multiple + * devices competing for the SPI bus + */ + + SPI_LOCK(spi, true); + SPI_SELECT(spi, SPIDEV_DISPLAY, true); + + /* Now make sure that the SPI bus is configured for the P14201 (it + * might have gotten configured for a different device while unlocked) + */ + + SPI_SETMODE(spi, CONFIG_P14201_SPIMODE); + SPI_SETBITS(spi, 8); +#ifdef CONFIG_P14201_FREQUENCY + SPI_SETFREQUENCY(spi, CONFIG_P14201_FREQUENCY); +#endif +} +#endif + +/************************************************************************************** + * Name: rit_deselect + * + * Description: + * De-select the SPI + * + * Input Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + **************************************************************************************/ + +#ifdef CONFIG_SPI_OWNBUS +static inline void rit_deselect(FAR struct spi_dev_s *spi) +{ + /* We own the SPI bus, so just de-select the chip */ + + SPI_SELECT(spi, SPIDEV_DISPLAY, false); +} +#else +static void rit_deselect(FAR struct spi_dev_s *spi) +{ + /* De-select P14201 chip and relinquish the SPI bus. */ + + SPI_SELECT(spi, SPIDEV_DISPLAY, false); + SPI_LOCK(spi, false); +} +#endif + +/************************************************************************************** + * Name: rit_sndbytes + * + * Description: + * Send a sequence of command or data bytes to the SSD1329 controller. + * + * Input Parameters: + * spi - Reference to the SPI driver structure + * buffer - A reference to memory containing the command bytes to be sent. + * buflen - The number of command bytes in buffer to be sent + * + * Returned Value: + * None + * + * Assumptions: + * The caller as selected the OLED device. + * + **************************************************************************************/ + +static void rit_sndbytes(FAR struct rit_dev_s *priv, FAR const uint8_t *buffer, + size_t buflen, bool cmd) +{ + FAR struct spi_dev_s *spi = priv->spi; + uint8_t tmp; + + ritdbg("buflen: %d cmd: %s [%02x %02x %02x]\n", + buflen, cmd ? "YES" : "NO", buffer[0], buffer[1], buffer[2] ); + DEBUGASSERT(spi); + + /* Clear/set the D/Cn bit to enable command or data mode */ + + (void)SPI_CMDDATA(spi, SPIDEV_DISPLAY, cmd); + + /* Loop until the entire command/data block is transferred */ + + while (buflen-- > 0) + { + /* Write the next byte to the controller */ + + tmp = *buffer++; + (void)SPI_SEND(spi, tmp); + } +} + +/************************************************************************************** + * Name: rit_sndcmd + * + * Description: + * Send multiple commands from a table of commands. + * + * Input Parameters: + * spi - Reference to the SPI driver structure + * table - A reference to table containing all of the commands to be sent. + * + * Returned Value: + * None + * + * Assumptions: + * + **************************************************************************************/ + +static void rit_sndcmds(FAR struct rit_dev_s *priv, FAR const uint8_t *table) +{ + int cmdlen; + + /* Table terminates with a zero length command */ + + while ((cmdlen = *table++) != 0) + { + ritdbg("command: %02x cmdlen: %d\n", *table, cmdlen); + rit_sndcmd(priv, table, cmdlen); + table += cmdlen; + } +} + +/************************************************************************************** + * Name: rit_clear + * + * Description: + * This method can be used to clear the entire display. + * + * Input Parameters: + * priv - Reference to private driver structure + * + * Assumptions: + * Caller has selected the OLED section. + * + **************************************************************************************/ + +#ifdef CONFIG_P14201_FRAMEBUFFER +static inline void rit_clear(FAR struct rit_dev_s *priv) +{ + FAR uint8_t *ptr = g_framebuffer; + unsigned int row; + + ritdbg("Clear display\n"); + + /* Initialize the framebuffer */ + + memset(g_framebuffer, (RIT_Y4_BLACK << 4) | RIT_Y4_BLACK, RIT_YRES * RIT_XRES / 2); + + /* Set a window to fill the entire display */ + + rit_sndcmd(priv, g_setallcol, sizeof(g_setallcol)); + rit_sndcmd(priv, g_setallrow, sizeof(g_setallrow)); + rit_sndcmd(priv, g_horzinc, sizeof(g_horzinc)); + + /* Display each row */ + + for(row = 0; row < RIT_YRES; row++) + { + /* Display a horizontal run */ + + rit_snddata(priv, ptr, RIT_XRES / 2); + ptr += RIT_XRES / 2; + } +} +#else +static inline void rit_clear(FAR struct rit_dev_s *priv) +{ + unsigned int row; + + ritdbg("Clear display\n"); + + /* Create a black row */ + + memset(g_runbuffer, (RIT_Y4_BLACK << 4) | RIT_Y4_BLACK, RIT_XRES / 2); + + /* Set a window to fill the entire display */ + + rit_sndcmd(priv, g_setallcol, sizeof(g_setallcol)); + rit_sndcmd(priv, g_setallrow, sizeof(g_setallrow)); + rit_sndcmd(priv, g_horzinc, sizeof(g_horzinc)); + + /* Display each row */ + + for(row = 0; row < RIT_YRES; row++) + { + /* Display a horizontal run */ + + rit_snddata(priv, g_runbuffer, RIT_XRES / 2); + } +} +#endif + +/************************************************************************************** + * Name: rit_putrun + * + * Description: + * This method can be used to write a partial raster line to the LCD. + * + * Input Parameters: + * row - Starting row to write to (range: 0 <= row < yres) + * col - Starting column to write to (range: 0 <= col <= xres-npixels) + * buffer - The buffer containing the run to be written to the LCD + * npixels - The number of pixels to write to the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +#ifdef CONFIG_P14201_FRAMEBUFFER +static int rit_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels) +{ + FAR struct rit_dev_s *priv = (FAR struct rit_dev_s *)&g_oleddev; + uint8_t cmd[3]; + uint8_t *run; + int start; + int end; + int aend; + int i; + + ritdbg("row: %d col: %d npixels: %d\n", row, col, npixels); + DEBUGASSERT(buffer); + + /* Toss out the special case of the empty run now */ + + if (npixels < 1) + { + return OK; + } + + /* Get the beginning of the line containing run in the framebuffer */ + + run = g_framebuffer + row * RIT_XRES / 2; + + /* Get the starting and ending byte offsets containing the run. + * the run starts at &run[start] and continues through run[end-1]. + * However, the first and final pixels at these locations may + * not be byte aligned. + */ + + start = col >> 1; + aend = (col + npixels) >> 1; + end = (col + npixels + 1) >> 1; + ritdbg("start: %d aend: %d end: %d\n", start, aend, end); + + /* Copy the run into the framebuffer, handling nibble alignment. + * + * CASE 1: First pixel X position is byte aligned + * + * example col=6 npixels = 8 example col=6 npixels=7 + * + * Run: |AB|AB|AB|AB| |AB|AB|AB|AB| + * GDDRAM row: + * Byte | 0| 1| 2| 3| 4| 5| 6| | 0| 1| 2| 3| 4| 5| 6| + * Pixel: |--|--|--|AB|AB|AB|AB| |--|--|--|AB|AB|AB|A-| + * + * start = 3 start = 3 + * aend = 6 aend = 6 + * end = 6 end = 7 + * + */ + + if ((col & 1) == 0) + { + /* Check for the special case of only 1 pixel being blitted */ + + if (npixels > 1) + { + /* Beginning of buffer is properly aligned, from start to aend */ + + memcpy(&run[start], buffer, aend - start); + } + + /* An even number of byte-aligned pixel pairs have been written (where + * zero counts as an even number). If npixels was was odd (including + * npixels == 1), then handle the final, byte aligned pixel. + */ + + if (aend != end) + { + /* The leftmost column is contained in source bits 7:4 and in + * destination bits 7:4 + */ + + run[aend] = (run[aend] & 0x0f) | (buffer[aend - start] & 0xf0); + } + } + + /* CASE 2: First pixel X position is byte aligned + * + * example col=7 npixels = 8 example col=7 npixels=7 + * + * Run: |AB|AB|AB|AB| |AB|AB|AB|AB| + * GDDRAM row: + * Byte | 0| 1| 2| 3| 4| 5| 6| 7| | 0| 1| 2| 3| 4| 5| 6| + * Pixel: |--|--|--|-A|BA|BA|BA|B-| |--|--|--|-A|BA|BA|BA| + * + * start = 3 start = 3 + * aend = 7 aend = 7 + * end = 8 end = 7 + */ + + else + { + uint8_t curr = buffer[0]; + uint8_t last; + + /* Handle the initial unaligned pixel. Source bits 7:4 into + * destination bits 3:0. In the special case of npixel == 1, + * this finished the job. + */ + + run[start] = (run[start] & 0xf0) | (curr >> 4); + + /* Now construct the rest of the bytes in the run (possibly special + * casing the final, partial byte below). + */ + + for (i = start + 1; i < aend; i++) + { + /* bits 3:0 from previous byte to run bits 7:4; + * bits 7:4 of current byte to run bits 3:0 + */ + + last = curr; + curr = buffer[i-start]; + run[i] = (last << 4) | (curr >> 4); + } + + /* An odd number of unaligned pixel have been written (where npixels + * may have been as small as one). If npixels was was even, then handle + * the final, unaligned pixel. + */ + + if (aend != end) + { + /* The leftmost column is contained in source bits 3:0 and in + * destination bits 7:4 + */ + + run[aend] = (run[aend] & 0x0f) | (curr << 4); + } + } + + /* Select the SD1329 controller */ + + rit_select(priv->spi); + + /* Setup a window that describes a run starting at the specified column + * and row, and ending at the column + npixels on the same row. + */ + + cmd[0] = SSD1329_SET_COLADDR; + cmd[1] = start; + cmd[2] = end - 1; + rit_sndcmd(priv, cmd, 3); + + cmd[0] = SSD1329_SET_ROWADDR; + cmd[1] = row; + cmd[2] = row; + rit_sndcmd(priv, cmd, 3); + + /* Write the run to GDDRAM. */ + + rit_sndcmd(priv, g_horzinc, sizeof(g_horzinc)); + rit_snddata(priv, &run[start], end - start); + + /* De-select the SD1329 controller */ + + rit_deselect(priv->spi); + return OK; +} +#else +static int rit_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels) +{ + FAR struct rit_dev_s *priv = (FAR struct rit_dev_s *)&g_oleddev; + uint8_t cmd[3]; + + ritdbg("row: %d col: %d npixels: %d\n", row, col, npixels); + DEBUGASSERT(buffer); + + if (npixels > 0) + { + /* Check that the X and Y coordinates are within range */ + + DEBUGASSERT(col < RIT_XRES && (col + npixels) <= RIT_XRES && row < RIT_YRES); + + /* Check that the X coordinates are aligned to 8-bit boundaries + * (this needs to get fixed somehow) + */ + + DEBUGASSERT((col & 1) == 0 && (npixels & 1) == 0); + + /* Select the SD1329 controller */ + + rit_select(priv->spi); + + /* Setup a window that describes a run starting at the specified column + * and row, and ending at the column + npixels on the same row. + */ + + cmd[0] = SSD1329_SET_COLADDR; + cmd[1] = col >> 1; + cmd[2] = ((col + npixels) >> 1) - 1; + rit_sndcmd(priv, cmd, 3); + + cmd[0] = SSD1329_SET_ROWADDR; + cmd[1] = row; + cmd[2] = row; + rit_sndcmd(priv, cmd, 3); + + /* Write the run to GDDRAM. */ + + rit_sndcmd(priv, g_horzinc, sizeof(g_horzinc)); + rit_snddata(priv, buffer, npixels >> 1); + + /* De-select the SD1329 controller */ + + rit_deselect(priv->spi); + } + + return OK; +} +#endif + +/************************************************************************************** + * Name: rit_getrun + * + * Description: + * This method can be used to read a partial raster line from the LCD: + * + * row - Starting row to read from (range: 0 <= row < yres) + * col - Starting column to read read (range: 0 <= col <= xres-npixels) + * buffer - The buffer in which to return the run read from the LCD + * npixels - The number of pixels to read from the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +#ifdef CONFIG_P14201_FRAMEBUFFER +static int rit_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels) +{ + uint8_t *run; + int start; + int end; + int aend; + int i; + + ritdbg("row: %d col: %d npixels: %d\n", row, col, npixels); + DEBUGASSERT(buffer); + + /* Can't read from OLED GDDRAM in SPI mode, but we can read from the framebuffer */ + /* Toss out the special case of the empty run now */ + + if (npixels < 1) + { + return OK; + } + + /* Get the beginning of the line containing run in the framebuffer */ + + run = g_framebuffer + row * RIT_XRES / 2; + + /* Get the starting and ending byte offsets containing the run. + * the run starts at &run[start] and continues through run[end-1]. + * However, the first and final pixels at these locations may + * not be byte aligned (see examples in putrun()). + */ + + start = col >> 1; + aend = (col + npixels) >> 1; + end = (col + npixels + 1) >> 1; + + /* Copy the run into the framebuffer, handling nibble alignment */ + + if ((col & 1) == 0) + { + /* Check for the special case of only 1 pixels being copied */ + + if (npixels > 1) + { + /* Beginning of buffer is properly aligned, from start to aend */ + + memcpy(buffer, &run[start], aend - start + 1); + } + + /* Handle any final pixel (including the special case where npixels == 1). */ + + if (aend != end) + { + /* The leftmost column is contained in source bits 7:4 and in + * destination bits 7:4 + */ + + buffer[aend - start] = run[aend] & 0xf0; + } + } + else + { + uint8_t curr = run[start]; + uint8_t last; + + /* Now construct the rest of the bytes in the run (possibly special + * casing the final, partial byte below). + */ + + for (i = start + 1; i < aend; i++) + { + /* bits 3:0 from previous byte to run bits 7:4; + * bits 7:4 of current byte to run bits 3:0 + */ + + last = curr; + curr = run[i]; + *buffer++ = (last << 4) | (curr >> 4); + } + + /* Handle any final pixel (including the special case where npixels == 1). */ + + if (aend != end) + { + /* The leftmost column is contained in source bits 3:0 and in + * destination bits 7:4 + */ + + *buffer = (curr << 4); + } + } + + return OK; +} +#else +static int rit_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels) +{ + /* Can't read from OLED GDDRAM in SPI mode */ + + return -ENOSYS; +} +#endif + +/************************************************************************************** + * Name: rit_getvideoinfo + * + * Description: + * Get information about the LCD video controller configuration. + * + **************************************************************************************/ + +static int rit_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo) +{ + DEBUGASSERT(dev && vinfo); + gvdbg("fmt: %d xres: %d yres: %d nplanes: %d\n", + g_videoinfo.fmt, g_videoinfo.xres, g_videoinfo.yres, g_videoinfo.nplanes); + memcpy(vinfo, &g_videoinfo, sizeof(struct fb_videoinfo_s)); + return OK; +} + +/************************************************************************************** + * Name: rit_getplaneinfo + * + * Description: + * Get information about the configuration of each LCD color plane. + * + **************************************************************************************/ + +static int rit_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo) +{ + DEBUGASSERT(pinfo && planeno == 0); + gvdbg("planeno: %d bpp: %d\n", planeno, g_planeinfo.bpp); + memcpy(pinfo, &g_planeinfo, sizeof(struct lcd_planeinfo_s)); + return OK; +} + +/************************************************************************************** + * Name: rit_getpower + * + * Description: + * Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER: full on. On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int rit_getpower(FAR struct lcd_dev_s *dev) +{ + FAR struct rit_dev_s *priv = (FAR struct rit_dev_s *)dev; + DEBUGASSERT(priv); + + gvdbg("power: %s\n", priv->on ? "ON" : "OFF"); + return priv->on ? CONFIG_LCD_MAXPOWER : 0; +} + +/************************************************************************************** + * Name: rit_setpower + * + * Description: + * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int rit_setpower(struct lcd_dev_s *dev, int power) +{ + struct rit_dev_s *priv = (struct rit_dev_s *)dev; + DEBUGASSERT(priv && (unsigned)power <= CONFIG_LCD_MAXPOWER && priv->spi); + + gvdbg("power: %d\n", power); + + /* Select the SD1329 controller */ + + rit_select(priv->spi); + + /* Only two power settings -- 0: sleep on, 1: sleep off */ + + if (power > 0) + { + /* Re-initialize the SSD1329 controller */ + + rit_sndcmds(priv, g_initcmds); + + /* Take the display out of sleep mode */ + + rit_sndcmd(priv, g_sleepoff, sizeof(g_sleepoff)); + priv->on = true; + } + else + { + /* Put the display into sleep mode */ + + rit_sndcmd(priv, g_sleepon, sizeof(g_sleepon)); + priv->on = false; + } + + /* De-select the SD1329 controller */ + + rit_deselect(priv->spi); + return OK; +} + +/************************************************************************************** + * Name: rit_getcontrast + * + * Description: + * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int rit_getcontrast(struct lcd_dev_s *dev) +{ + struct rit_dev_s *priv = (struct rit_dev_s *)dev; + + gvdbg("contrast: %d\n", priv->contrast); + return priv->contrast; +} + +/************************************************************************************** + * Name: rit_setcontrast + * + * Description: + * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int rit_setcontrast(struct lcd_dev_s *dev, unsigned int contrast) +{ + struct rit_dev_s *priv = (struct rit_dev_s *)dev; + uint8_t cmd[3]; + + gvdbg("contrast: %d\n", contrast); + DEBUGASSERT(contrast <= CONFIG_LCD_MAXCONTRAST); + + /* Select the SD1329 controller */ + + rit_select(priv->spi); + + /* Set new contrast */ + + cmd[0] = SSD1329_SET_CONTRAST; + cmd[1] = contrast; + cmd[2] = SSD1329_NOOP; + rit_sndcmd(priv, cmd, 3); + + /* De-select the SD1329 controller */ + + rit_deselect(priv->spi); + priv->contrast = contrast; + return OK; +} + +/************************************************************************************** + * Public Functions + **************************************************************************************/ + +/************************************************************************************** + * Name: rit_initialize + * + * Description: + * Initialize the P14201 video hardware. The initial state of the OLED is fully + * initialized, display memory cleared, and the OLED ready to use, but with the power + * setting at 0 (full off == sleep mode). + * + * Input Parameters: + * spi - A reference to the SPI driver instance. + * devno - A value in the range of 0 throuh CONFIG_P14201_NINTERFACES-1. This allows + * support for multiple OLED devices. + * + * Returned Value: + * On success, this function returns a reference to the LCD object for the specified + * OLED. NULL is returned on any failure. + * + **************************************************************************************/ + +FAR struct lcd_dev_s *rit_initialize(FAR struct spi_dev_s *spi, unsigned int devno) +{ + FAR struct rit_dev_s *priv = (FAR struct rit_dev_s *)&g_oleddev; + DEBUGASSERT(devno == 0 && spi); + + gvdbg("Initializing devno: %d\n", devno); + + /* Driver state data */ + + priv->spi = spi; + priv->contrast = RIT_CONTRAST; + priv->on = false; + + /* Select the SD1329 controller */ + + rit_configspi(spi); + rit_select(spi); + + /* Clear the display */ + + rit_clear(priv); + + /* Configure (but don't enable) the OLED */ + + rit_sndcmds(priv, g_initcmds); + + /* De-select the SD1329 controller */ + + rit_deselect(spi); + return &priv->dev; +} +#endif /* CONFIG_LCD_P14201 */ diff --git a/nuttx/drivers/lcd/pcf8833.h b/nuttx/drivers/lcd/pcf8833.h new file mode 100644 index 0000000000..b0a7e14d41 --- /dev/null +++ b/nuttx/drivers/lcd/pcf8833.h @@ -0,0 +1,152 @@ +/************************************************************************************** + * drivers/lcd/pcf8833.h + * Definitions for the Phillips PCF8833 LCD controller + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: "Data Sheet, PCF8833 STN RGB 132x132x3 driver," Phillips, 2003 Feb 14. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +#ifndef __DRIVERS_LCD_PCF8833_H +#define __DRIVERS_LCD_PCF8833_H + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ +/* Pixel format codes */ + +#define PCF8833_FMT_8BPS (2) +#define PCF8833_FMT_12BPS (3) +#define PCF8833_FMT_16BPS (5) + +/* LCD Commands */ + +#define PCF8833_NOP 0x00 /* No operation; Data: none */ +#define PCF8833_SWRESET 0x01 /* Software reset ; Data: none */ +#define PCF8833_BSTROFF 0x02 /* Booster voltage off; Data: none */ +#define PCF8833_BSTRON 0x03 /* Booster voltage on; Data: none */ +#define PCF8833_RDDIDIF 0x04 /* Read display identification; Data: none */ +#define PCF8833_RDDST 0x09 /* Read display status; Data: none */ +#define PCF8833_SLEEPIN 0x10 /* Sleep_IN; Data: none */ +#define PCF8833_SLEEPOUT 0x11 /* Sleep_OUT; Data: none */ +#define PCF8833_PTLON 0x12 /* Partial mode on; Data: none */ +#define PCF8833_NORON 0x13 /* Normal Display mode on; Data: none */ +#define PCF8833_INVOFF 0x20 /* Display inversion off; Data: none */ +#define PCF8833_INVON 0x21 /* Display inversion on; Data: none */ +#define PCF8833_DALO 0x22 /* All pixel off; Data: none */ +#define PCF8833_DAL 0x23 /* All pixel on; Data: none */ +#define PCF8833_SETCON 0x25 /* Set contrast; Data: (1) contrast */ +#define PCF8833_DISPOFF 0x28 /* Display off; Data: none */ +#define PCF8833_DISPON 0x29 /* Display on; Data: none */ +#define PCF8833_CASET 0x2a /* Column address set; Data: (1) X start (2) X end */ +#define PCF8833_PASET 0x2b /* Page address set Data: (1) Y start (2) Y end */ +#define PCF8833_RAMWR 0x2c /* Memory write; Data: (1) write data */ +#define PCF8833_RGBSET 0x2d /* Colour set; Data: (1-8) red tones, (9-16) green tones, (17-20) blue tones */ +#define PCF8833_PTLAR 0x30 /* Partial area; Data: (1) start address (2) end address */ +#define PCF8833_VSCRDEF 0x33 /* Vertical scroll definition; Data: (1) top fixed, (2) scrol area, (3) bottom fixed */ +#define PCF8833_TEOFF 0x34 /* Tearing line off; Data: none */ +#define PCF8833_TEON 0x35 /* Tearing line on; Data: (1) don't care */ +#define PCF8833_MADCTL 0x36 /* Memory data access control; Data: (1) access control settings */ +#define PCF8833_SEP 0x37 /* Set Scroll Entry Point; Data: (1) scroll entry point */ +#define PCF8833_IDMOFF 0x38 /* Idle mode off; Data: none */ +#define PCF8833_IDMON 0x39 /* Idle mode on; Data: none */ +#define PCF8833_COLMOD 0x3a /* Interface pixel format; Data: (1) color interface format */ +#define PCF8833_SETVOP 0xb0 /* Set VOP; Data: (1) VOP5-8 (2) VOP0-4 */ +#define PCF8833_BRS 0xb4 /* Bottom Row Swap; Data: none */ +#define PCF8833_TRS 0xb6 /* Top Row Swap; Data: none */ +#define PCF8833_FINV 0xb9 /* Super Frame INVersion; Data: none */ +#define PCF8833_DOR 0xba /* Data ORder; Data: none */ +#define PCF8833_TCDFE 0xbd /* Enable/disable DF temp comp; Data: none */ +#define PCF8833_TCVOPE 0xbf /* Enable or disable VOP temp comp; Data: none */ +#define PCF8833_EC 0xc0 /* Internal or external oscillator; Data: none */ +#define PCF8833_SETMUL 0xc2 /* Set multiplication factor; Data: (1) Multiplication factor */ +#define PCF8833_TCVOPAB 0xc3 /* Set TCVOP slopes A and B; Data: (1) SLB and SLA */ +#define PCF8833_TCVOPCD 0xc4 /* Set TCVOP slopes C and D; Data: (1) SLD and SLC */ +#define PCF8833_TCDF 0xc5 /* Set divider frequency; Data: Divider factor in region (1) A (2) B (3) C (4) D */ +#define PCF8833_DF8COLOR 0xc6 /* Set divider frequency 8-colour mode; Data: (1) DF80-6 */ +#define PCF8833_SETBS 0xc7 /* Set bias system; Data: (1) Bias systems */ +#define PCF8833_RDTEMP 0xc8 /* Temperature read back; Data: none */ +#define PCF8833_NLI 0xc9 /* N-Line Inversion; Data: (1) NLI time slots invervsion */ +#define PCF8833_RDID1 0xda /* Read ID1; Data: none */ +#define PCF8833_RDID2 0xdb /* Read ID2; Data: none */ +#define PCF8833_RDID3 0xdc /* Read ID3; Data: none */ +#define PCF8833_SFD 0xef /* Select factory defaults; Data: none */ +#define PCF8833_ECM 0xf0 /* Enter Calibration mode; Data: (1) Calibration control settings */ +#define PCF8833_OTPSHTIN 0xf1 /* Shift data in OTP shift registers; Data: Any number of bytes */ + +/* Memory data access control (MADCTL) bit definitions */ + +#define MADCTL_RGB (1 << 3) /* Bit 3: BGR */ +#define MADCTL_LAO (1 << 4) /* Bit 4: Line address order bottom to top */ +#define MADCTL_V (1 << 5) /* Bit 5: Vertical RAM write; in Y direction */ +#define MADCTL_MX (1 << 6) /* Bit 6: Mirror X */ +#define MADCTL_MY (1 << 7) /* Bit 7: Mirror Y */ + +/* PCF8833 status register bit definitions */ +/* CMD format: RDDST command followed by four status bytes: */ +/* Byte 1: D31 d30 D29 D28 D27 D26 --- --- */ + +#define PCF8833_ST_RGB (1 << 2) /* Bit 2: D26 - RGB/BGR order */ +#define PCF8833_ST_LINEADDR (1 << 3) /* Bit 3: D27 - Line address order */ +#define PCF8833_ST_ADDRMODE (1 << 4) /* Bit 4: D28 - Vertical/horizontal addressing mode */ +#define PCF8833_ST_XADDR (1 << 5) /* Bit 5: D29 - X address order */ +#define PCF8833_ST_YADDR (1 << 6) /* Bit 6: D30 - Y address order */ +#define PCF8833_ST_BOOSTER (1 << 7) /* Bit 7: D31 - Booster voltage status */ + +/* Byte 2: --- D22 D21 D20 D19 D18 D17 D16 */ + +#define PCF8833_ST_NORMAL (1 << 0) /* Bit 0: D16 - Normal display mode */ +#define PCF8833_ST_SLEEPIN (1 << 1) /* Bit 1: D17 - Sleep in selected */ +#define PCF8833_ST_PARTIAL (1 << 2) /* Bit 2: D18 - Partial mode on */ +#define PCF8833_ST_IDLE (1 << 3) /* Bit 3: D19 - Idle mode selected */ +#define PCF8833_ST_PIXELFMT_SHIFT (4) /* Bits 4-6: D20-D22 - Interface pixel format */ +#define PCF8833_ST_PIXELFMT_MASK (7 << PCF8833_ST_PIXELFMT_SHIFT) +# define PCF8833_ST_PIXELFMT_8BPS (PCF8833_FMT_8BPS << PCF8833_ST_PIXELFMT_SHIFT) +# define PCF8833_ST_PIXELFMT_12BPS (PCF8833_FMT_12BPS << PCF8833_ST_PIXELFMT_SHIFT) +# define PCF8833_ST_PIXELFMT_16BPS (PCF8833_FMT_16BPS << PCF8833_ST_PIXELFMT_SHIFT) + +/* Byte 3: D15 -- D13 D12 D11 D10 D9 --- */ + +#define PCF8833_ST_TEARING (1 << 1) /* Bit 1: D9 - Tearing effect on */ +#define PCF8833_ST_DISPLAYON (1 << 2) /* Bit 2: D10 - Display on */ +#define PCF8833_ST_PIXELSOFF (1 << 3) /* Bit 3: D11 - All pixels off */ +#define PCF8833_ST_PIXELSON (1 << 4) /* Bit 4: D12 - All pixels on */ +#define PCF8833_ST_INV (1 << 5) /* Bit 5: D13 - Display inversion */ +#define PCF8833_ST_VSCROLL (1 << 7) /* Bit 6: D15 - Vertical scroll mode */ + +/* Byte 4: All zero */ + +#endif /* __DRIVERS_LCD_PCF8833_H */ \ No newline at end of file diff --git a/nuttx/drivers/lcd/s1d15g10.h b/nuttx/drivers/lcd/s1d15g10.h new file mode 100644 index 0000000000..df2dd8be27 --- /dev/null +++ b/nuttx/drivers/lcd/s1d15g10.h @@ -0,0 +1,141 @@ +/************************************************************************************** + * drivers/lcd/s1d15g10.h + * Definitions for the Epson S1D15G0 LCD controller + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: S1D15G0D08B000, Seiko Epson Corportation, 2002. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +#ifndef __DRIVERS_LCD_S1D15G10_H +#define __DRIVERS_LCD_S1D15G10_H + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ + +/* Epson S1D15G10 Command Set */ + +#define S1D15G10_DISON 0xaf /* Display on; Data: none */ +#define S1D15G10_DISOFF 0xae /* Display off; Data: none */ +#define S1D15G10_DISNOR 0xa6 /* Normal display; Data: none */ +#define S1D15G10_DISINV 0xa7 /* Inverse display; Data: none */ +#define S1D15G10_COMSCN 0xbb /* Common scan direction; Data: (1) common scan direction */ +#define S1D15G10_DISCTL 0xca /* Display control; Data: Data: (1) CL div, F1/2 pat, (2) duty, (3) FR inverse (4) dispersion */ +#define S1D15G10_SLPIN 0x95 /* Sleep in; Data: none */ +#define S1D15G10_SLPOUT 0x94 /* Sleep out; Data: none */ +#define S1D15G10_PASET 0x75 /* Page address set; Data: (1) start page, (2) end page */ +#define S1D15G10_CASET 0x15 /* Column address set; Data: (1) start addr, (2) end addr */ +#define S1D15G10_DATCTL 0xbc /* Data scan direction, etc.; Data: (1) inverse, scan dir (2) RGB, (3) gray-scale */ +#define S1D15G10_RGBSET8 0xce /* 256-color position set; Data: (1-8) red tones, (9-16) green tones, (17-20) blue tones */ +#define S1D15G10_RAMWR 0x5c /* Writing to memory; Data: (1) write data */ +#define S1D15G10_RAMRD 0x5d /* Reading from memory; Data: (1) read data */ +#define S1D15G10_PTLIN 0xa8 /* Partial display in; Data: (1) start addr, (2) end addr */ +#define S1D15G10_PTLOUT 0xa9 /* Partial display out; Data: none */ +#define S1D15G10_RMWIN 0xe0 /* Read and modify write; Data: none */ +#define S1D15G10_RMWOUT 0xee /* End; Data: none */ +#define S1D15G10_ASCSET 0xaa /* Area scroll set; Data: (1) top addr, (2) bottom addr, (3) Num blocks, (4) scroll mode */ +#define S1D15G10_SCSTART 0xab /* Scroll start set; Data: (1) start block addr */ +#define S1D15G10_OSCON 0xd1 /* Internal oscillation on; Data: none */ +#define S1D15G10_OSCOFF 0xd2 /* Internal oscillation off; Data: none */ +#define S1D15G10_PWRCTR 0x20 /* Power control; Data: (1) LCD drive power */ +#define S1D15G10_VOLCTR 0x81 /* Electronic volume control; Data: (1) volume value, (2) resistance ratio */ +#define S1D15G10_VOLUP 0xd6 /* Increment electronic control by 1; Data: none */ +#define S1D15G10_VOLDOWN 0xd7 /* Decrement electronic control by 1; Data: none */ +#define S1D15G10_TMPGRD 0x82 /* Temperature gradient set; Data: (1-14) temperature gradient */ +#define S1D15G10_EPCTIN 0xcd /* Control EEPROM; Data: (1) read/write */ +#define S1D15G10_EPCOUT 0xcc /* Cancel EEPROM control; Data: none */ +#define S1D15G10_EPMWR 0xfc /* Write into EEPROM; Data: none */ +#define S1D15G10_EPMRD 0xfd /* Read from EEPROM; Data: none */ +#define S1D15G10_EPSRRD1 0x7c /* Read register 1; Data: none */ +#define S1D15G10_EPSRRD2 0x7d /* Read regiser 2; Data: none */ +#define S1D15G10_NOP 0x25 /* NOP intruction (0x45?); Data: none */ +#define S1D15G10_STREAD 0x20 /* Status read; Data: none */ + +/* Display control (DISCTL) bit definitions */ + +#define DISCTL_PERIOD_SHIFT (0) /* P1: Bits 0-1, F1 and F2 drive-pattern switching period */ +#define DISCTL_PERIOD_MASK (3 << DISCTL_PERIOD_SHIFT) +# define DISCTL_PERIOD_8 (0 << DISCTL_PERIOD_SHIFT) +# define DISCTL_PERIOD_4 (1 << DISCTL_PERIOD_SHIFT) +# define DISCTL_PERIOD_16 (2 << DISCTL_PERIOD_SHIFT) +# define DISCTL_PERIOD_FLD (3 << DISCTL_PERIOD_SHIFT) +#define DISCTL_CLDIV_SHIFT (2) /* P1: Bits 2-4, Clock divider */ +#define DISCTL_CLDIV_MASK (7 << DISCTL_CLDIV_SHIFT) +# define DISCTL_CLDIV_2 (0 << DISCTL_CLDIV_SHIFT) +# define DISCTL_CLDIV_4 (1 << DISCTL_CLDIV_SHIFT) +# define DISCTL_CLDIV_8 (2 << DISCTL_CLDIV_SHIFT) +# define DISCTL_CLDIV_NONE (3 << DISCTL_CLDIV_SHIFT) + +/* Power control (PWRCTR) bit definitions */ + +#define PWCTR_REFVOLTAGE (1 << 0) /* P1: Bit 0, Turn on reference voltage generation circuit. */ +#define PWCTR_REGULATOR (1 << 1) /* P1: Bit 1, Turn on voltage regulator and circuit voltage follower. */ +#define PWCTR_BOOSTER2 (1 << 2) /* P1: Bit 2, Turn on secondary booster/step-down circuit. */ +#define PWCTR_BOOSTER1 (1 << 3) /* P1: Bit 3, Turn on primary booster circuit. */ +#define PWCTR_EXTR (1 << 4) /* P1: Bit 4, Use external resistance to adjust voltage. */ + +/* Data control (DATCTL) bit definitions */ + +#define DATCTL_PGADDR_INV (1 << 0) /* P1: Bit 0, Inverse display of the page address. */ +#define DATCTL_COLADDR_REV (1 << 1) /* P1: Bit 1, Reverse turn of column address. */ +#define DATCTL_ADDR_PGDIR (1 << 2) /* P1: Bit 2, Address-scan direction in page (vs column) direction. */ + +#define DATCTL_BGR (1 << 0) /* P2: Bit0, RGB->BGR */ + +#define DATCTL_8GRAY (1) /* P3: Bits 0-2 = 001, 8 gray-scale */ +#define DATCTL_16GRAY_A (2) /* P3: Bits 0-2 = 010, 16 gray-scale display type A */ +#define DATCTL_16GRAY_B (4) /* P3: Bits 0-2 = 100, 16 gray-scale display type B */ + +/* Status register bit definions (after reset or NOP) */ + +#define S1D15G10_SR_PARTIAL (1 << 0) /* Bit 0: Partial display */ +#define S1D15G10_SR_NORMAL (1 << 1) /* Bit 1: Normal (vs. inverse) display */ +#define S1D15G10_SR_EEPROM (1 << 2) /* Bit 2: EEPROM access */ +#define S1D15G10_SR_DISPON (1 << 3) /* Bit 3: Display on */ +#define S1D15G10_SR_COLSCAN (1 << 4) /* Bit 4: Column (vs. page) scan direction */ +#define S1D15G10_SR_RMW (1 << 5) /* Bit 5: Read modify write */ +#define S1D15G10_SR_SCROLL (3 << 6) /* Bits 6-7: Area scroll mode */ + +/* Status register bit definions (after EPSRRD1) */ + +#define S1D15G10_SR_VOLUME 0x3f /* Bits 0-5: Electronic volume control values */ + +/* Status register bit definions (after EPSRRD2) */ + +#define S1D15G10_SR_RRATIO 0x07 /* Bits 0-2: Built-in resistance ratio */ + +#endif /* __DRIVERS_LCD_S1D15G10_H */ \ No newline at end of file diff --git a/nuttx/drivers/lcd/sd1329.h b/nuttx/drivers/lcd/sd1329.h new file mode 100644 index 0000000000..5d2ad4948d --- /dev/null +++ b/nuttx/drivers/lcd/sd1329.h @@ -0,0 +1,527 @@ +/**************************************************************************** + * drivers/lcd/sd1329.h + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_LCD_SD1329_H +#define __DRIVERS_LCD_SD1329_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* SD1329 Commands **********************************************************/ +/* Set column Address. + * + * This triple byte command specifies column start address and end address of + * the display data RAM. This command also sets the column address pointer to + * column start address. This pointer is used to define the current read/write + * column address in graphic display data RAM. If horizontal address increment + * mode is enabled by command 0xa0, after finishing read/write one column data, + * it is incremented automatically to the next column address. Whenever the + * column address pointer finishes accessing the end column address, it is + * reset back to start column address and the row address is incremented to the + * next row. + * + * Byte 1: 0x15 + * Byte 2: A[5:0]: Start Address, range: 0x00-0x3f + * Byte 3: B[5:0]: End Address, range: 0x00-0x3f + */ + +#define SSD1329_SET_COLADDR 0x15 + +/* Set Row Address. + * + * This triple byte command specifies row start address and end address of the + * display data RAM. This command also sets the row address pointer to row + * start address. This pointer is used to define the current read/write row + * address in graphic display data RAM. If vertical address increment mode is + * enabled by command 0xa0, after finishing read/write one row data, it is + * incremented automatically to the next row address. Whenever the row address + * pointer finishes accessing the end row address, it is reset back to start + * row address. + * + * Byte 1: 0x75 + * Byte 2: A[6:0]: Start Address, range: 0x00-0x7f + * Byte 3: B[6:0]: End Address, range: 0x00-0x7f + */ + +#define SSD1329_SET_ROWADDR 0x75 + +/* Set Contract Current + * + * This double byte command is to set Contrast Setting of the display. The + * chip has 256 contrast steps from 0x00 to 0xff. The segment output current + * increases linearly with the increase of contrast step. + * + * Byte 1: 0x81 + * Byte 2: A[7:0]: Contrast Value, range: 0-255 + */ + +#define SSD1329_SET_CONTRAST 0x81 + +/* Set Second Pre-Charge Speed + * + * This command is used to set the speed of second pre-charge in phase 3. + * This speed can be doubled to achieve faster pre-charging through setting + * 0x82 A[0]. + * + * Byte 1: 0x82 + * Byte 2: A[7:1]: Second Pre-charge Speed + * A[0] = 1, Enable doubling the Second Pre-charge speed + */ + +#define SSD1329_PRECHRG2_SPEED 0x82 +# define SSD1329_PRECHRG2_DBL 0x01 + +/* Set Master Icon Control + * + * This double command is used to set the ON / OFF conditions of internal + * charge pump, icon circuits and overall icon status. + * + * Byte 1: 0x90 + * Byte 2: Icon control (OR of bits 0-1,4-5) + */ + +#define SSD1329_ICON_CONTROL 0x90 +# define SSD1329_ICON_NORMAL 0x00 /* A[1:0]1=00: Icon RESET to normal display */ +# define SSD1329_ICON_ALLON 0x01 /* A[1:0]1=01: Icon All ON */ +# define SSD1329_ICON_ALLOFF 0x02 /* A[1:0]=10: Icon All OFF */ +# define SSD1329_ICON_DISABLE 0x00 /* A[4]=0: Disable Icon display */ +# define SSD1329_ICON_ENABLE 0x10 /* A[4]=1: Enable Icon display */ +# define SSD1329_VICON_DISABLE 0x00 /* A[5]=0: Disable VICON charge pump circuit */ +# define SSD1329_VICON_ENABLE 0x20 /* A[5]=1: Enable VICON charge pump circuit */ + +/* Set Icon Current Range + * + * This double byte command is used to set one fix current range for all icons + * between the range of 0uA and 127.5uA. The uniformity improves as the icon + * current range increases. + * + * Byte 1: 0x91 + * Byte 2: A[7:0]: Max icon current: + * 00 = 0.0 uA + * 01 = 0.5 uA + * ... + * ff = 127.5 uA + */ + +#define SSD1329_ICON_CURRRNG 0x91 + +/* Set Individual Icon Current + * + * This multiple byte command is used to fine tune the current for each of the + * 64 icons. Command 0x92 followed by 64 single byte data. These 64 byte data + * have to be entered in order to make this command function. Below is the + * formula for calculating the icon current. + * + * Icon Current = Single byte value / 127 x Maximum icon current set with command 0x91 + * + * Byte 1: 0x92 + * Byte 2-65: An[6:0]: icon current for ICSn, range: 0x00-0x7f + * Icon Current of ICSn = An[6:0]/127) x max icon current + */ + +#define SSD1329_ICON_CURRENT 0x92 + +/* Set Individual Icon ON / OFF Register + * + * This double byte command is used to select one of the 64 icons and choose the + * ON, OFF or blinking condition of the selected icon. + * + * Byte 1: 0x93 + * Byte 2: A[5:0]: Select one of the 64 icons from ICS0 ~ ICS63 + * A[7:6]: OFF/ON/BLINK + */ + +#define SSD1329_ICON_SELECT 0x93 +# define SSD1329_ICON_OFF 0x00 +# define SSD1329_ICON_ON 0x40 +# define SSD1329_ICON_BLINK 0xc0 + +/* Set Icon ON / OFF Registers + * + * This double byte command is used to set the ON / OFF status of all 64 icons. + * + * Byte 1: 0x94 + * Byte 2: A[7:6]: OFF/ON/BLINK (Same as 0x93) + */ + +#define SSD1329_ICON_ALL 0x94 + +/* Set Icon Blinking Cycle + * + * This double byte command is used to set icon oscillator frequency and + * blinking cycle selected with above command 0x93. + * + * Byte 1: 0x95 + * Byte 2: + * - A[2:0]:Icon Blinking cycle + * - A[5:4]:Icon oscillation frequency + */ + +#define SSD1329_ICON_BLINKING 0x95 +# define SSD1329_ICON_BLINK_0p25S 0x00 /* 0.25 sec */ +# define SSD1329_ICON_BLINK_0p50S 0x01 /* 0.50 sec */ +# define SSD1329_ICON_BLINK_0p75S 0x02 /* 0.75 sec */ +# define SSD1329_ICON_BLINK_0p100S 0x03 /* 1.00 sec */ +# define SSD1329_ICON_BLINK_0p125S 0x04 /* 1.25 sec */ +# define SSD1329_ICON_BLINK_0p150S 0x05 /* 1.50 sec */ +# define SSD1329_ICON_BLINK_0p175S 0x06 /* 1.75 sec */ +# define SSD1329_ICON_BLINK_0p200S 0x07 /* 2.00 sec */ +# define SSD1329_ICON_BLINK_61KHZ 0x00 /* 61 KHz */ +# define SSD1329_ICON_BLINK_64KHZ 0x10 /* 64 KHz */ +# define SSD1329_ICON_BLINK_68KHZ 0x20 /* 68 KHz */ +# define SSD1329_ICON_BLINK_73KHZ 0x30 /* 73 KHz */ + +/* Set Icon Duty + * + * This double byte command is used to set the icon frame frequency and icon AC + * drive duty ratio. + * + * Byte 1: 0x96 + * Byte 2: + * - A[2:0]: AC Drive + * - A[7:4]: con frame frequency + */ + +#define SSD1329_ICON_ACDRIVE 0x96 +# define SSD1329_ICON_DUTY_DC 0x00 +# define SSD1329_ICON_DUTY_63_64 0x01 +# define SSD1329_ICON_DUTY_62_64 0x02 +# define SSD1329_ICON_DUTY_61_64 0x03 +# define SSD1329_ICON_DUTY_60_64 0x04 +# define SSD1329_ICON_DUTY_59_64 0x05 +# define SSD1329_ICON_DUTY_58_64 0x06 +# define SSD1329_ICON_DUTY_57_64 0x07 + +/* Set Re-map + * + * This double command has multiple configurations and each bit setting is + * described as follows: + * + * Column Address Remapping (A[0]) + * This bit is made for increase the flexibility layout of segment signals in + * OLED module with segment arranged from left to right (when A[0] is set to 0) + * or from right to left (when A[0] is set to 1). + * + * Nibble Remapping (A[1]) + * When A[1] is set to 1, the two nibbles of the data bus for RAM access are + * re-mapped, such that (D7, D6, D5, D4, D3, D2, D1, D0) acts like (D3, D2, D1, + * D0, D7, D6, D5, D4) If this feature works together with Column Address + * Re-map, it would produce an effect of flipping the outputs from SEG0-127 to + * SEG127-SEG0. + * + * Address increment mode (A[2]) + * When A[2] is set to 0, the driver is set as horizontal address incremen + * mode. After the display RAM is read/written, the column address pointer is + * increased automatically by 1. If the column address pointer reaches column + * end address, the column address pointer is reset to column start address and + * row address pointer is increased by 1. + * + * When A[2] is set to 1, the driver is set to vertical address increment mode. + * After the display RAM is read/written, the row address pointer is increased + * automatically by 1. If the row address pointer reaches the row end address, + * the row address pointer is reset to row start address and column address + * pointer is increased by 1. + * + * COM Remapping (A[4]) + * This bit defines the scanning direction of the common for flexible layout + * of common signals in OLED module either from up to down (when A[4] is set to + * 0) or from bottom to up (when A[4] is set to 1). + * + * Splitting of Odd / Even COM Signals (A[6]) + * This bit is made to match the COM layout connection on the panel. When A[6] + * is set to 0, no splitting odd / even of the COM signal is performed. When + * A[6] is set to 1, splitting odd / even of the COM signal is performed, + * output pin assignment sequence is shown as below (for 128MUX ratio): + * + * Byte 1: 0xa0 + * Byte 2: A[7:0] + */ + +#define SSD1329_GDDRAM_REMAP 0xa0 +# define SSD1329_COLADDR_REMAP 0x01 /* A[0]: Enable column re-map */ +# define SSD1329_NIBBLE_REMAP 0x02 /* A[1]: Enable nibble re-map */ +# define SSD1329_VADDR_INCR 0x04 /* A[1]: Enable vertical address increment */ +# define SSD1329_COM_REMAP 0x10 /* A[4]: Enable COM re-map */ +# define SSD1329_COM_SPLIT 0x40 /* A[6]: Enable COM slip even/odd */ + +/* Set Display Start Line + * + * This double byte command is to set Display Start Line register for + * determining the starting address of display RAM to be displayed by selecting + * a value from 0 to 127. + * + * Byte 1: 0xa1 + * Byte 2: A[6:0]: Vertical scroll by setting the starting address of + * display RAM from 0-127 + */ + +#define SSD1329_VERT_START 0xa1 + +/* Set Display Offset + * + * This double byte command specifies the mapping of display start line (it is + * assumed that COM0 is the display start line, display start line register + * equals to 0) to one of COM0-COM127. + * + * Byte 1: 0xa2 + * Byte 2: A[6:0]: Set vertical offset by COM from 0-127 + */ + +#define SSD1329_VERT_OFFSET 0xa2 + +/* Set Display Mode - Normal, all on, all off, inverse + * + * These are single byte commands and are used to set display status to Normal + * Display, Entire Display ON, Entire Display OFF or Inverse Display. + * + * Normal Display (0xa4) + * Reset the “Entire Display ON, Entire Display OFF or Inverse Display” effects + * and turn the data to ON at the corresponding gray level. + * + * Set Entire Display ON (0xa5) + * Force the entire display to be at gray scale level GS15, regardless of the + * contents of the display data RAM. + * + * Set Entire Display OFF (0xa6) + * Force the entire display to be at gray scale level GS0, regardless of the + * contents of the display data RAM. + * + * Inverse Display (0xa7) + * The gray scale level of display data are swapped such that “GS0” <-> “GS15”, + * “GS1” <-> “GS14”, etc. + * + * Byte 1: Display mode command + */ + +#define SSD1329_DISP_NORMAL 0xa4 +#define SSD1329_DISP_OFF 0xa5 +#define SSD1329_DISP_ON 0xa6 +#define SSD1329_DISP_INVERT 0xa7 + +/* Set MUX Ratio + * + * This double byte command sets multiplex ratio (MUX ratio) from 16MUX to + * 128MUX. In POR, multiplex ratio is 128MUX. + * + * Byte 1: 0xa8 + * Byte 2: A[6:0] 15-127 representing 16-128 MUX + */ + +#define SSD1329_MUX_RATIO 0xa8 + +/* Set Sleep mode ON / OFF + * + * These single byte commands are used to turn the matrix display on the OLED + * panel display either ON or OFF. When the sleep mode is set to ON (0xae), the + * display is OFF, the segment and common output are in high impedance state + * and circuits will be turned OFF. When the sleep mode is set to OFF (0xaf), + * the display is ON. + * + * Byte 1: sleep mode command + */ + +#define SSD1329_SLEEP_ON 0xae +#define SSD1329_SLEEP_OFF 0xaf + +/* Set Phase Length + * + * In the second byte of this double command, lower nibble and higher nibble is + * defined separately. The lower nibble adjusts the phase length of Reset (phase + * 1). The higher nibble is used to select the phase length of first pre-charge + * phase (phase 2). The phase length is ranged from 1 to 16 DCLK's. RESET for + * A[3:0] is set to 3 which means 4 DCLK’s selected for Reset phase. POR for + * A[7:4] is set to 5 which means 6 DCLK’s is selected for first pre-charge + * phase. Please refer to Table 9-1 for detail breakdown levels of each step. + * + * Byte 1: 0xb1 + * Byte 2: A[3:0]: Phase 1 period of 1~16 DCLK’s + * A[7:4]: Phase 2 period of 1~16 DCLK’s + */ + +#define SSD1329_PHASE_LENGTH 0xb1 + +/* Set Frame Frequency + * + * This double byte command is used to set the number of DCLK’s per row between + * the range of 0x14 and 0x7f. Then the Frame frequency of the matrix display + * is equal to DCLK frequency / A[6:0]. + * + * Byte 1: 0xb2 + * Byte 2: A[6:0]:Total number of DCLK’s per row. Ranging from + * 0x14 to 0x4e DCLK’s. frame Frequency = DCLK freq /A[6:0]. + */ + +#define SSD1329_FRAME_FREQ 0xb2 + +/* Set Front Clock Divider / Oscillator Frequency + * + * This double command is used to set the frequency of the internal display + * clocks, DCLK's. It is defined by dividing the oscillator frequency by the + * divide ratio (Value from 1 to 16). Frame frequency is determined by divide + * ratio, number of display clocks per row, MUX ratio and oscillator frequency. + * The lower nibble of the second byte is used to select the oscillator + * frequency. Please refer to Table 9-1 for detail breakdown levels of each + * step. + * + * Byte 1: 0xb3 + * Byte 2: A[3:0]: Define divide ratio (D) of display clock (DCLK) + * Divide ratio=A[3:0]+1 + * A[7:4] : Set the Oscillator Frequency, FOSC. Range:0-15 + */ + +#define SSD1329_DCLK_DIV 0xb3 + +/* Set Default Gray Scale Table + * + * This single byte command is used to set the gray scale table to initial + * default setting. + * + * Byte 1: 0xb7 + */ + +#define SSD1329_GSCALE_TABLE 0xb7 + +/* Look Up Table for Gray Scale Pulse width + * + * This command is used to set each individual gray scale level for the display. + * Except gray scale level GS0 that has no pre-charge and current drive, each + * gray scale level is programmed in the length of current drive stage pulse + * width with unit of DCLK. The longer the length of the pulse width, the + * brighter the OLED pixel when it’s turned ON. + * + * The setting of gray scale table entry can perform gamma correction on OLED + * panel display. Normally, it is desired that the brightness response of the + * panel is linearly proportional to the image data value in display data RAM. + * However, the OLED panel is somehow responded in non-linear way. Appropriate + * gray scale table setting like example below can compensate this effect. + * + * Byte 1: 0xb8 + * Bytes 2-16: An[5:0], value for GSn level Pulse width + */ + +#define SSD1329_GSCALE_LOOKUP 0xb8 + +/* Set Second Pre-charge Period + * + * This double byte command is used to set the phase 3 second pre-charge period. + * The period of phase 3 can be programmed by command 0xbb and it is ranged from + * 0 to 15 DCLK's. + * + * Byte 1: 0xbb + * Byte 2: 0-15 DCLKs + */ + +#define SSD1329_PRECHRG2_PERIOD 0xbb + +/* Set First Precharge voltage, VP + * + * This double byte command is used to set phase 2 first pre-charge voltage + * level. It can be programmed to set the first pre-charge voltage reference to + * VCC or VCOMH. + * + * Byte 1: 0xbc + * Byte 2: A[5] == 0, Pre-charge voltage is (0.30 + A[4:0]) * Vcc + * A{5] == 1, 1.00 x VCC or connect to VCOMH if VCC > VCOMH + */ + +#define SSD1329_PRECHRG1_VOLT 0xbc + +/* Set VCOMH + * + * This double byte command sets the high voltage level of common pins, VCOMH. + * The level of VCOMH is programmed with reference to VCC. + * + * Byte 1: 0xbe + * Byte 2: (0.51 + A[5:0]) * Vcc + */ + +#define SSD1329_COM_HIGH 0xbe + +/* NOOP + * + * This is a no operation command. + * + * Byte 1: 0xe3 + */ + +#define SSD1329_NOOP 0xe3 + +/* Set Command Lock + * + * This command is used to lock the MCU from accepting any command. + * + * Byte 1: 0xfd + * Byte 2: 0x12 | A[2] + * A[2] == 1, Enable locking the MCU from entering command + */ + +#define SSD1329_CMD_LOCK 0xfd +# define SSD1329_LOCK_ON 0x13 +# define SSD1329_LOCK_OFF 0x12 + +/* SD1329 Status ************************************************************/ + +#define SDD1329_STATUS_ON 0x00 /* D[6]=0: indicates the display is ON */ +#define SDD1329_STATUS_OFF 0x40 /* D[6]=1: indicates the display is OFF */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __DRIVERS_LCD_SD1329_H */ diff --git a/nuttx/drivers/lcd/skeleton.c b/nuttx/drivers/lcd/skeleton.c new file mode 100644 index 0000000000..1cb8b5955b --- /dev/null +++ b/nuttx/drivers/lcd/skeleton.c @@ -0,0 +1,401 @@ +/************************************************************************************** + * drivers/lcd/skeleton.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ + +/* Configuration **********************************************************************/ +/* Verify that all configuration requirements have been met */ + +/* Debug ******************************************************************************/ +/* Define the following to enable register-level debug output */ + +#undef CONFIG_LCD_SKELDEBUG + +/* Verbose debug must also be enabled */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_GRAPHICS +#endif + +#ifndef CONFIG_DEBUG_VERBOSE +# undef CONFIG_LCD_SKELDEBUG +#endif + +/* Color Properties *******************************************************************/ + +/* Display Resolution */ + +#define SKEL_XRES 320 +#define SKEL_YRES 240 + +/* Color depth and format */ + +#define SKEL_BPP 16 +#define SKEL_COLORFMT FB_FMT_RGB16_565 + +/* Debug ******************************************************************************/ + +#ifdef CONFIG_LCD_SKELDEBUG +# define skeldbg(format, arg...) vdbg(format, ##arg) +#else +# define skeldbg(x...) +#endif + +/************************************************************************************** + * Private Type Definition + **************************************************************************************/ + +/* This structure describes the state of this driver */ + +struct skel_dev_s +{ + /* Publically visible device structure */ + + struct lcd_dev_s dev; + + /* Private LCD-specific information follows */ +}; + +/************************************************************************************** + * Private Function Protototypes + **************************************************************************************/ + +/* LCD Data Transfer Methods */ + +static int skel_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels); +static int skel_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels); + +/* LCD Configuration */ + +static int skel_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo); +static int skel_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo); + +/* LCD RGB Mapping */ + +#ifdef CONFIG_FB_CMAP +# error "RGB color mapping not supported by this driver" +#endif + +/* Cursor Controls */ + +#ifdef CONFIG_FB_HWCURSOR +# error "Cursor control not supported by this driver" +#endif + +/* LCD Specific Controls */ + +static int skel_getpower(struct lcd_dev_s *dev); +static int skel_setpower(struct lcd_dev_s *dev, int power); +static int skel_getcontrast(struct lcd_dev_s *dev); +static int skel_setcontrast(struct lcd_dev_s *dev, unsigned int contrast); + +/************************************************************************************** + * Private Data + **************************************************************************************/ + +/* This is working memory allocated by the LCD driver for each LCD device + * and for each color plane. This memory will hold one raster line of data. + * The size of the allocated run buffer must therefore be at least + * (bpp * xres / 8). Actual alignment of the buffer must conform to the + * bitwidth of the underlying pixel type. + * + * If there are multiple planes, they may share the same working buffer + * because different planes will not be operate on concurrently. However, + * if there are multiple LCD devices, they must each have unique run buffers. + */ + +static uint16_t g_runbuffer[SKEL_XRES]; + +/* This structure describes the overall LCD video controller */ + +static const struct fb_videoinfo_s g_videoinfo = +{ + .fmt = SKEL_COLORFMT, /* Color format: RGB16-565: RRRR RGGG GGGB BBBB */ + .xres = SKEL_XRES, /* Horizontal resolution in pixel columns */ + .yres = SKEL_YRES, /* Vertical resolution in pixel rows */ + .nplanes = 1, /* Number of color planes supported */ +}; + +/* This is the standard, NuttX Plane information object */ + +static const struct lcd_planeinfo_s g_planeinfo = +{ + .putrun = skel_putrun, /* Put a run into LCD memory */ + .getrun = skel_getrun, /* Get a run from LCD memory */ + .buffer = (uint8_t*)g_runbuffer, /* Run scratch buffer */ + .bpp = SKEL_BPP, /* Bits-per-pixel */ +}; + +/* This is the standard, NuttX LCD driver object */ + +static struct skel_dev_s g_lcddev = +{ + .dev = + { + /* LCD Configuration */ + + .getvideoinfo = skel_getvideoinfo, + .getplaneinfo = skel_getplaneinfo, + + /* LCD RGB Mapping -- Not supported */ + /* Cursor Controls -- Not supported */ + + /* LCD Specific Controls */ + + .getpower = skel_getpower, + .setpower = skel_setpower, + .getcontrast = skel_getcontrast, + .setcontrast = skel_setcontrast, + }, +}; + +/************************************************************************************** + * Private Functions + **************************************************************************************/ + +/************************************************************************************** + * Name: skel_putrun + * + * Description: + * This method can be used to write a partial raster line to the LCD: + * + * row - Starting row to write to (range: 0 <= row < yres) + * col - Starting column to write to (range: 0 <= col <= xres-npixels) + * buffer - The buffer containing the run to be written to the LCD + * npixels - The number of pixels to write to the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +static int skel_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels) +{ + /* Buffer must be provided and aligned to a 16-bit address boundary */ + + gvdbg("row: %d col: %d npixels: %d\n", row, col, npixels); + DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); + + /* Set up to write the run. */ + + /* Write the run to GRAM. */ +#warning "Missing logic" + return OK; +} + +/************************************************************************************** + * Name: skel_getrun + * + * Description: + * This method can be used to read a partial raster line from the LCD: + * + * row - Starting row to read from (range: 0 <= row < yres) + * col - Starting column to read read (range: 0 <= col <= xres-npixels) + * buffer - The buffer in which to return the run read from the LCD + * npixels - The number of pixels to read from the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +static int skel_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels) +{ + /* Buffer must be provided and aligned to a 16-bit address boundary */ + + gvdbg("row: %d col: %d npixels: %d\n", row, col, npixels); + DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); + +#warning "Missing logic" + return -ENOSYS; +} + +/************************************************************************************** + * Name: skel_getvideoinfo + * + * Description: + * Get information about the LCD video controller configuration. + * + **************************************************************************************/ + +static int skel_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo) +{ + DEBUGASSERT(dev && vinfo); + gvdbg("fmt: %d xres: %d yres: %d nplanes: %d\n", + g_videoinfo.fmt, g_videoinfo.xres, g_videoinfo.yres, g_videoinfo.nplanes); + memcpy(vinfo, &g_videoinfo, sizeof(struct fb_videoinfo_s)); + return OK; +} + +/************************************************************************************** + * Name: skel_getplaneinfo + * + * Description: + * Get information about the configuration of each LCD color plane. + * + **************************************************************************************/ + +static int skel_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo) +{ + DEBUGASSERT(dev && pinfo && planeno == 0); + gvdbg("planeno: %d bpp: %d\n", planeno, g_planeinfo.bpp); + memcpy(pinfo, &g_planeinfo, sizeof(struct lcd_planeinfo_s)); + return OK; +} + +/************************************************************************************** + * Name: skel_getpower + * + * Description: + * Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int skel_getpower(struct lcd_dev_s *dev) +{ + struct skel_dev_s *priv = (struct skel_dev_s *)dev; + gvdbg("power: %d\n", 0); +#warning "Missing logic" + return 0; +} + +/************************************************************************************** + * Name: skel_setpower + * + * Description: + * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int skel_setpower(struct lcd_dev_s *dev, int power) +{ + struct skel_dev_s *priv = (struct skel_dev_s *)dev; + + gvdbg("power: %d\n", power); + DEBUGASSERT(power <= CONFIG_LCD_MAXPOWER); + + /* Set new power level */ +#warning "Missing logic" + + return OK; +} + +/************************************************************************************** + * Name: skel_getcontrast + * + * Description: + * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int skel_getcontrast(struct lcd_dev_s *dev) +{ + gvdbg("Not implemented\n"); +#warning "Missing logic" + return -ENOSYS; +} + +/************************************************************************************** + * Name: skel_setcontrast + * + * Description: + * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int skel_setcontrast(struct lcd_dev_s *dev, unsigned int contrast) +{ + gvdbg("contrast: %d\n", contrast); +#warning "Missing logic" + return -ENOSYS; +} + +/************************************************************************************** + * Public Functions + **************************************************************************************/ + +/************************************************************************************** + * Name: up_oledinitialize + * + * Description: + * Initialize the LCD video hardware. The initial state of the LCD is fully + * initialized, display memory cleared, and the LCD ready to use, but with the power + * setting at 0 (full off). + * + **************************************************************************************/ + +FAR struct lcd_dev_s *up_oledinitialize(FAR struct spi_dev_s *spi) +{ + gvdbg("Initializing\n"); + + /* Configure GPIO pins */ +#warning "Missing logic" + + /* Enable clocking */ +#warning "Missing logic" + + /* Configure and enable LCD */ + #warning "Missing logic" + + return &g_lcddev.dev; +} diff --git a/nuttx/drivers/lcd/ssd1289.c b/nuttx/drivers/lcd/ssd1289.c new file mode 100644 index 0000000000..58c6069682 --- /dev/null +++ b/nuttx/drivers/lcd/ssd1289.c @@ -0,0 +1,1279 @@ +/************************************************************************************** + * drivers/lcd/ssd1289.c + * + * Generic LCD driver for LCDs based on the Solomon Systech SSD1289 LCD controller. + * Think of this as a template for an LCD driver that you will proably ahve to + * customize for any particular LCD hardware. + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * + * References: SSD1289, Rev 1.3, Apr 2007, Solomon Systech Limited + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ssd1289.h" + +#ifdef CONFIG_LCD_SSD1289 + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ +/* Configuration **********************************************************************/ + +/* Check contrast selection */ + +#if !defined(CONFIG_LCD_MAXCONTRAST) +# define CONFIG_LCD_MAXCONTRAST 1 +#endif + +/* Check power setting */ + +#if !defined(CONFIG_LCD_MAXPOWER) || CONFIG_LCD_MAXPOWER < 1 +# define CONFIG_LCD_MAXPOWER 1 +#endif + +#if CONFIG_LCD_MAXPOWER > 255 +# error "CONFIG_LCD_MAXPOWER must be less than 256 to fit in uint8_t" +#endif + +/* Check orientation */ + +#if defined(CONFIG_LCD_PORTRAIT) +# if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) || defined(CONFIG_LCD_RPORTRAIT) +# error "Cannot define both portrait and any other orientations" +# endif +#elif defined(CONFIG_LCD_RPORTRAIT) +# if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) +# error "Cannot define both rportrait and any other orientations" +# endif +#elif defined(CONFIG_LCD_LANDSCAPE) +# ifdef CONFIG_LCD_RLANDSCAPE +# error "Cannot define both landscape and any other orientations" +# endif +#elif !defined(CONFIG_LCD_RLANDSCAPE) +# define CONFIG_LCD_LANDSCAPE 1 +#endif + +/* Define CONFIG_DEBUG_LCD to enable detailed LCD debug output. Verbose debug must + * also be enabled. + */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_GRAPHICS +# undef CONFIG_DEBUG_LCD +#endif + +#ifndef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_LCD +#endif + +/* Display/Color Properties ***********************************************************/ +/* Display Resolution */ + +#if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) +# define SSD1289_XRES 320 +# define SSD1289_YRES 240 +#else +# define SSD1289_XRES 240 +# define SSD1289_YRES 320 +#endif + +/* Color depth and format */ + +#define SSD1289_BPP 16 +#define SSD1289_COLORFMT FB_FMT_RGB16_565 + +/* LCD Profiles ***********************************************************************/ +/* Many details of the controller initialization must, unfortunately, vary from LCD to + * LCD. I have looked at the spec and at three different drivers for LCDs that have + * SSD1289 controllers. I have tried to summarize these differences as "LCD profiles" + * + * Most of the differences between LCDs are nothing more than a few minor bit + * settings. The most significant difference betwen LCD drivers in is the + * manner in which the LCD is powered up and in how the power controls are set. + * My suggestion is that if you have working LCD initialization code, you should + * simply replace the code in ssd1289_hwinitialize with your working code. + */ + +#if defined (CONFIG_SSD1289_PROFILE2) +# undef SSD1289_USE_SIMPLE_INIT + + /* PWRCTRL1: AP=smalll-to-medium, DC=Flinex24, BT=+5/-4, DCT=Flinex24 */ + +# define PWRCTRL1_SETTING \ + (SSD1289_PWRCTRL1_AP_SMMED | SSD1289_PWRCTRL1_DC_FLINEx24 | \ + SSD1289_PWRCTRL1_BT_p5m4 | SSD1289_PWRCTRL1_DCT_FLINEx24) + + /* PWRCTRL2: 5.1v */ + +# define PWRCTRL2_SETTING SSD1289_PWRCTRL2_VRC_5p1V + + /* PWRCTRL3: x 2.165 + * NOTE: Many drivers have bit 8 set which is not defined in the SSD1289 spec. + */ + +# define PWRCTRL3_SETTING SSD1289_PWRCTRL3_VRH_x2p165 + + /* PWRCTRL4: VDV=9 + VCOMG */ + +# define PWRCTRL4_SETTING (SSD1289_PWRCTRL4_VDV(9) | SSD1289_PWRCTRL4_VCOMG) + + /* PWRCTRL5: VCM=56 + NOTP */ + +# define PWRCTRL5_SETTING (SSD1289_PWRCTRL5_VCM(56) | SSD1289_PWRCTRL5_NOTP) + +#elif defined (CONFIG_SSD1289_PROFILE3) +# undef SSD1289_USE_SIMPLE_INIT + + /* PWRCTRL1: AP=smalll-to-medium, DC=Flinex24, BT=+5/-4, DCT=Flinex24 */ + +# define PWRCTRL1_SETTING \ + (SSD1289_PWRCTRL1_AP_SMMED | SSD1289_PWRCTRL1_DC_FLINEx24 | \ + SSD1289_PWRCTRL1_BT_p5m4 | SSD1289_PWRCTRL1_DCT_FLINEx24) + + /* PWRCTRL2: 5.1v */ + +# define PWRCTRL2_SETTING SSD1289_PWRCTRL2_VRC_5p1V + + /* PWRCTRL3: x 2.165 + * NOTE: Many drivers have bit 8 set which is not defined in the SSD1289 spec. + */ + +# define PWRCTRL3_SETTING SSD1289_PWRCTRL3_VRH_x2p165 + + /* PWRCTRL4: VDV=9 + VCOMG */ + +# define PWRCTRL4_SETTING (SSD1289_PWRCTRL4_VDV(9) | SSD1289_PWRCTRL4_VCOMG) + + /* PWRCTRL5: VCM=56 + NOTP */ + +# define PWRCTRL5_SETTING (SSD1289_PWRCTRL5_VCM(56) | SSD1289_PWRCTRL5_NOTP) + +#else /* if defined (CONFIG_SSD1289_PROFILE1) */ +# undef SSD1289_USE_SIMPLE_INIT +# define SSD1289_USE_SIMPLE_INIT 1 + + /* PWRCTRL1: AP=medium-to-large, DC=Fosc/4, BT=+5/-4, DCT=Fosc/4 */ + +# define PWRCTRL1_SETTING \ + (SSD1289_PWRCTRL1_AP_MEDLG | SSD1289_PWRCTRL1_DC_FOSd4 | \ + SSD1289_PWRCTRL1_BT_p5m4 | SSD1289_PWRCTRL1_DCT_FOSd4) + + /* PWRCTRL2: 5.3v */ + +# define PWRCTRL2_SETTING SSD1289_PWRCTRL2_VRC_5p3V + + /* PWRCTRL3: x 2.570 + * NOTE: Many drivers have bit 8 set which is not defined in the SSD1289 spec. + */ + +# define PWRCTRL3_SETTING SSD1289_PWRCTRL3_VRH_x2p570 + + /* PWRCTRL4: VDV=12 + VCOMG */ + +# define PWRCTRL4_SETTING (SSD1289_PWRCTRL4_VDV(12) | SSD1289_PWRCTRL4_VCOMG) + + /* PWRCTRL5: VCM=60 + NOTP */ + +# define PWRCTRL5_SETTING (SSD1289_PWRCTRL5_VCM(60) | SSD1289_PWRCTRL5_NOTP) + +#endif + +/* Debug ******************************************************************************/ + +#ifdef CONFIG_DEBUG_LCD +# define lcddbg dbg +# define lcdvdbg vdbg +#else +# define lcddbg(x...) +# define lcdvdbg(x...) +#endif + +/************************************************************************************** + * Private Type Definition + **************************************************************************************/ + +/* This structure describes the state of this driver */ + +struct ssd1289_dev_s +{ + /* Publically visible device structure */ + + struct lcd_dev_s dev; + + /* Private LCD-specific information follows */ + + FAR struct ssd1289_lcd_s *lcd; /* The contained platform-specific, LCD interface */ + uint8_t power; /* Current power setting */ + + /* This is working memory allocated by the LCD driver for each LCD device + * and for each color plane. This memory will hold one raster line of data. + * The size of the allocated run buffer must therefore be at least + * (bpp * xres / 8). Actual alignment of the buffer must conform to the + * bitwidth of the underlying pixel type. + * + * If there are multiple planes, they may share the same working buffer + * because different planes will not be operate on concurrently. However, + * if there are multiple LCD devices, they must each have unique run buffers. + */ + + uint16_t runbuffer[SSD1289_XRES]; +}; + +/************************************************************************************** + * Private Function Protototypes + **************************************************************************************/ +/* Low Level LCD access */ + +static void ssd1289_putreg(FAR struct ssd1289_lcd_s *lcd, uint8_t regaddr, + uint16_t regval); +#ifndef CONFIG_LCD_NOGETRUN +static uint16_t ssd1289_readreg(FAR struct ssd1289_lcd_s *lcd, uint8_t regaddr); +#endif +static inline void ssd1289_gramwrite(FAR struct ssd1289_lcd_s *lcd, uint16_t rgbcolor); +#ifndef CONFIG_LCD_NOGETRUN +static inline void ssd1289_readsetup(FAR struct ssd1289_lcd_s *lcd, FAR uint16_t *accum); +static inline uint16_t ssd1289_gramread(FAR struct ssd1289_lcd_s *lcd, FAR uint16_t *accum); +#endif +static void ssd1289_setcursor(FAR struct ssd1289_lcd_s *lcd, uint16_t column, + uint16_t row); + +/* LCD Data Transfer Methods */ + +static int ssd1289_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels); +static int ssd1289_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels); + +/* LCD Configuration */ + +static int ssd1289_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo); +static int ssd1289_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo); + +/* LCD RGB Mapping */ + +#ifdef CONFIG_FB_CMAP +# error "RGB color mapping not supported by this driver" +#endif + +/* Cursor Controls */ + +#ifdef CONFIG_FB_HWCURSOR +# error "Cursor control not supported by this driver" +#endif + +/* LCD Specific Controls */ + +static int ssd1289_getpower(FAR struct lcd_dev_s *dev); +static int ssd1289_setpower(FAR struct lcd_dev_s *dev, int power); +static int ssd1289_getcontrast(FAR struct lcd_dev_s *dev); +static int ssd1289_setcontrast(FAR struct lcd_dev_s *dev, unsigned int contrast); + +/* Initialization */ + +static inline int ssd1289_hwinitialize(FAR struct ssd1289_dev_s *priv); + +/************************************************************************************** + * Private Data + **************************************************************************************/ + +/* This driver can support only a signal SSD1289 device. This is due to an + * unfortunate decision made whent he getrun and putrun methods were designed. The + * following is the single SSD1289 driver state instance: + */ + +static struct ssd1289_dev_s g_lcddev; + +/************************************************************************************** + * Private Functions + **************************************************************************************/ + +/************************************************************************************** + * Name: ssd1289_putreg(lcd, + * + * Description: + * Write to an LCD register + * + **************************************************************************************/ + +static void ssd1289_putreg(FAR struct ssd1289_lcd_s *lcd, uint8_t regaddr, uint16_t regval) +{ + /* Set the index register to the register address and write the register contents */ + + lcd->index(lcd, regaddr); + lcd->write(lcd, regval); +} + +/************************************************************************************** + * Name: ssd1289_readreg + * + * Description: + * Read from an LCD register + * + **************************************************************************************/ + +#ifndef CONFIG_LCD_NOGETRUN +static uint16_t ssd1289_readreg(FAR struct ssd1289_lcd_s *lcd, uint8_t regaddr) +{ + /* Set the index register to the register address and read the register contents */ + + lcd->index(lcd, regaddr); + return lcd->read(lcd); +} +#endif + +/************************************************************************************** + * Name: ssd1289_gramselect + * + * Description: + * Setup to read or write multiple pixels to the GRAM memory + * + **************************************************************************************/ + +static inline void ssd1289_gramselect(FAR struct ssd1289_lcd_s *lcd) +{ + lcd->index(lcd, SSD1289_DATA); +} + +/************************************************************************************** + * Name: ssd1289_gramwrite + * + * Description: + * Setup to read or write multiple pixels to the GRAM memory + * + **************************************************************************************/ + +static inline void ssd1289_gramwrite(FAR struct ssd1289_lcd_s *lcd, uint16_t data) +{ + lcd->write(lcd, data); +} + +/************************************************************************************** + * Name: ssd1289_readsetup + * + * Description: + * Prime the operation by reading one pixel from the GRAM memory if necessary for + * this LCD type. When reading 16-bit gram data, there may be some shifts in the + * returned data: + * + * - ILI932x: Discard first dummy read; no shift in the return data + * + **************************************************************************************/ + +#ifndef CONFIG_LCD_NOGETRUN +static inline void ssd1289_readsetup(FAR struct ssd1289_lcd_s *lcd, FAR uint16_t *accum) +{ + /* Read-ahead one pixel */ + + *accum = lcd->read(lcd); +} +#endif + +/************************************************************************************** + * Name: ssd1289_gramread + * + * Description: + * Read one correctly aligned pixel from the GRAM memory. Possibly shifting the + * data and possibly swapping red and green components. + * + * - ILI932x: Unknown -- assuming colors are in the color order + * + **************************************************************************************/ + +#ifndef CONFIG_LCD_NOGETRUN +static inline uint16_t ssd1289_gramread(FAR struct ssd1289_lcd_s *lcd, FAR uint16_t *accum) +{ + /* Read the value (GRAM register already selected) */ + + return lcd->read(lcd); +} +#endif + +/************************************************************************************** + * Name: ssd1289_setcursor + * + * Description: + * Set the cursor position. In landscape mode, the "column" is actually the physical + * Y position and the "row" is the physical X position. + * + **************************************************************************************/ + +static void ssd1289_setcursor(FAR struct ssd1289_lcd_s *lcd, uint16_t column, uint16_t row) +{ +#if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT) + ssd1289_putreg(lcd, SSD1289_XADDR, column); /* 0-239 */ + ssd1289_putreg(lcd, SSD1289_YADDR, row); /* 0-319 */ +#elif defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) + ssd1289_putreg(lcd, SSD1289_XADDR, row); /* 0-239 */ + ssd1289_putreg(lcd, SSD1289_YADDR, column); /* 0-319 */ +#endif +} + +/************************************************************************************** + * Name: ssd1289_dumprun + * + * Description: + * Dump the contexts of the run buffer: + * + * run - The buffer in containing the run read to be dumped + * npixels - The number of pixels to dump + * + **************************************************************************************/ + +#if 0 /* Sometimes useful */ +static void ssd1289_dumprun(FAR const char *msg, FAR uint16_t *run, size_t npixels) +{ + int i, j; + + lib_rawprintf("\n%s:\n", msg); + for (i = 0; i < npixels; i += 16) + { + up_putc(' '); + lib_rawprintf(" "); + for (j = 0; j < 16; j++) + { + lib_rawprintf(" %04x", *run++); + } + up_putc('\n'); + } +} +#endif + +/************************************************************************************** + * Name: ssd1289_putrun + * + * Description: + * This method can be used to write a partial raster line to the LCD: + * + * row - Starting row to write to (range: 0 <= row < yres) + * col - Starting column to write to (range: 0 <= col <= xres-npixels) + * buffer - The buffer containing the run to be written to the LCD + * npixels - The number of pixels to write to the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +static int ssd1289_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels) +{ + FAR struct ssd1289_dev_s *priv = &g_lcddev; + FAR struct ssd1289_lcd_s *lcd = priv->lcd; + FAR const uint16_t *src = (FAR const uint16_t*)buffer; + int i; + + /* Buffer must be provided and aligned to a 16-bit address boundary */ + + lcdvdbg("row: %d col: %d npixels: %d\n", row, col, npixels); + DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); + + /* Select the LCD */ + + lcd->select(lcd); + + /* Write the run to GRAM. */ + +#ifdef CONFIG_LCD_LANDSCAPE + /* Convert coordinates -- Here the edge away from the row of buttons on + * the STM3240G-EVAL is used as the top. + */ + + /* Write the GRAM data, manually incrementing X */ + + for (i = 0; i < npixels; i++) + { + /* Write the next pixel to this position */ + + ssd1289_setcursor(lcd, col, row); + ssd1289_gramselect(lcd); + ssd1289_gramwrite(lcd, *src); + + /* Increment to next column */ + + src++; + col++; + } +#elif defined(CONFIG_LCD_RLANDSCAPE) + /* Convert coordinates -- Here the edge next to the row of buttons on + * the STM3240G-EVAL is used as the top. + */ + + col = (SSD1289_XRES-1) - col; + row = (SSD1289_YRES-1) - row; + + /* Set the cursor position */ + + ssd1289_setcursor(lcd, col, row); + + /* Then write the GRAM data, auto-decrementing X */ + + ssd1289_gramselect(lcd); + for (i = 0; i < npixels; i++) + { + /* Write the next pixel to this position (auto-decrements to the next column) */ + + ssd1289_gramwrite(lcd, *src); + src++; + } +#elif defined(CONFIG_LCD_PORTRAIT) + /* Convert coordinates. In this configuration, the top of the display is to the left + * of the buttons (if the board is held so that the buttons are at the botton of the + * board). + */ + + col = (SSD1289_XRES-1) - col; + + /* Then write the GRAM data, manually incrementing Y (which is col) */ + + for (i = 0; i < npixels; i++) + { + /* Write the next pixel to this position */ + + ssd1289_setcursor(lcd, row, col); + ssd1289_gramselect(lcd); + ssd1289_gramwrite(lcd, *src); + + /* Increment to next column */ + + src++; + col--; + } +#else /* CONFIG_LCD_RPORTRAIT */ + /* Convert coordinates. In this configuration, the top of the display is to the right + * of the buttons (if the board is held so that the buttons are at the botton of the + * board). + */ + + row = (SSD1289_YRES-1) - row; + + /* Then write the GRAM data, manually incrementing Y (which is col) */ + + for (i = 0; i < npixels; i++) + { + /* Write the next pixel to this position */ + + ssd1289_setcursor(lcd, row, col); + ssd1289_gramselect(lcd); + ssd1289_gramwrite(lcd, *src); + + /* Decrement to next column */ + + src++; + col++; + } +#endif + + /* De-select the LCD */ + + lcd->deselect(lcd); + return OK; +} + +/************************************************************************************** + * Name: ssd1289_getrun + * + * Description: + * This method can be used to read a partial raster line from the LCD: + * + * row - Starting row to read from (range: 0 <= row < yres) + * col - Starting column to read read (range: 0 <= col <= xres-npixels) + * buffer - The buffer in which to return the run read from the LCD + * npixels - The number of pixels to read from the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +static int ssd1289_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels) +{ +#ifndef CONFIG_LCD_NOGETRUN + FAR struct ssd1289_dev_s *priv = &g_lcddev; + FAR struct ssd1289_lcd_s *lcd = priv->lcd; + FAR uint16_t *dest = (FAR uint16_t*)buffer; + uint16_t accum; + int i; + + /* Buffer must be provided and aligned to a 16-bit address boundary */ + + lcdvdbg("row: %d col: %d npixels: %d\n", row, col, npixels); + DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); + + /* Select the LCD */ + + lcd->select(lcd); + + /* Read the run from GRAM. */ + +#ifdef CONFIG_LCD_LANDSCAPE + /* Convert coordinates -- Here the edge away from the row of buttons on + * the STM3240G-EVAL is used as the top. + */ + + for (i = 0; i < npixels; i++) + { + /* Read the next pixel from this position */ + + ssd1289_setcursor(lcd, row, col); + ssd1289_gramselect(lcd); + ssd1289_readsetup(lcd, &accum); + *dest++ = ssd1289_gramread(lcd, &accum); + + /* Increment to next column */ + + col++; + } +#elif defined(CONFIG_LCD_RLANDSCAPE) + /* Convert coordinates -- Here the edge next to the row of buttons on + * the STM3240G-EVAL is used as the top. + */ + + col = (SSD1289_XRES-1) - col; + row = (SSD1289_YRES-1) - row; + + /* Set the cursor position */ + + ssd1289_setcursor(lcd, col, row); + + /* Then read the GRAM data, auto-decrementing Y */ + + ssd1289_gramselect(lcd); + + /* Prime the pump for unaligned read data */ + + ssd1289_readsetup(lcd, &accum); + + for (i = 0; i < npixels; i++) + { + /* Read the next pixel from this position (autoincrements to the next row) */ + + *dest++ = ssd1289_gramread(lcd, &accum); + } +#elif defined(CONFIG_LCD_PORTRAIT) + /* Convert coordinates. In this configuration, the top of the display is to the left + * of the buttons (if the board is held so that the buttons are at the botton of the + * board). + */ + + col = (SSD1289_XRES-1) - col; + + /* Then read the GRAM data, manually incrementing Y (which is col) */ + + for (i = 0; i < npixels; i++) + { + /* Read the next pixel from this position */ + + ssd1289_setcursor(lcd, row, col); + ssd1289_gramselect(lcd); + ssd1289_readsetup(lcd, &accum); + *dest++ = ssd1289_gramread(lcd, &accum); + + /* Increment to next column */ + + col--; + } +#else /* CONFIG_LCD_RPORTRAIT */ + /* Convert coordinates. In this configuration, the top of the display is to the right + * of the buttons (if the board is held so that the buttons are at the botton of the + * board). + */ + + row = (SSD1289_YRES-1) - row; + + /* Then write the GRAM data, manually incrementing Y (which is col) */ + + for (i = 0; i < npixels; i++) + { + /* Write the next pixel to this position */ + + ssd1289_setcursor(lcd, row, col); + ssd1289_gramselect(lcd); + ssd1289_readsetup(lcd, &accum); + *dest++ = ssd1289_gramread(lcd, &accum); + + /* Decrement to next column */ + + col++; + } +#endif + + /* De-select the LCD */ + + lcd->deselect(lcd); + return OK; +#else + return -ENOSYS; +#endif +} + +/************************************************************************************** + * Name: ssd1289_getvideoinfo + * + * Description: + * Get information about the LCD video controller configuration. + * + **************************************************************************************/ + +static int ssd1289_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo) +{ + DEBUGASSERT(dev && vinfo); + lcdvdbg("fmt: %d xres: %d yres: %d nplanes: 1\n", + SSD1289_COLORFMT, SSD1289_XRES, SSD1289_XRES); + + vinfo->fmt = SSD1289_COLORFMT; /* Color format: RGB16-565: RRRR RGGG GGGB BBBB */ + vinfo->xres = SSD1289_XRES; /* Horizontal resolution in pixel columns */ + vinfo->yres = SSD1289_YRES; /* Vertical resolution in pixel rows */ + vinfo->nplanes = 1; /* Number of color planes supported */ + return OK; +} + +/************************************************************************************** + * Name: ssd1289_getplaneinfo + * + * Description: + * Get information about the configuration of each LCD color plane. + * + **************************************************************************************/ + +static int ssd1289_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo) +{ + FAR struct ssd1289_dev_s *priv = (FAR struct ssd1289_dev_s *)dev; + + DEBUGASSERT(dev && pinfo && planeno == 0); + lcdvdbg("planeno: %d bpp: %d\n", planeno, SSD1289_BPP); + + pinfo->putrun = ssd1289_putrun; /* Put a run into LCD memory */ + pinfo->getrun = ssd1289_getrun; /* Get a run from LCD memory */ + pinfo->buffer = (uint8_t*)priv->runbuffer; /* Run scratch buffer */ + pinfo->bpp = SSD1289_BPP; /* Bits-per-pixel */ + return OK; +} + +/************************************************************************************** + * Name: ssd1289_getpower + * + * Description: + * Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int ssd1289_getpower(FAR struct lcd_dev_s *dev) +{ + lcdvdbg("power: %d\n", 0); + return g_lcddev.power; +} + +/************************************************************************************** + * Name: ssd1289_poweroff + * + * Description: + * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int ssd1289_poweroff(FAR struct ssd1289_lcd_s *lcd) +{ + /* Set the backlight off */ + + lcd->backlight(lcd, 0); + + /* Turn the display off */ + + ssd1289_putreg(lcd, SSD1289_DSPCTRL, 0); + + /* Remember the power off state */ + + g_lcddev.power = 0; + return OK; +} + +/************************************************************************************** + * Name: ssd1289_setpower + * + * Description: + * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int ssd1289_setpower(FAR struct lcd_dev_s *dev, int power) +{ + FAR struct ssd1289_dev_s *priv = (FAR struct ssd1289_dev_s *)dev; + FAR struct ssd1289_lcd_s *lcd = priv->lcd; + + lcdvdbg("power: %d\n", power); + DEBUGASSERT((unsigned)power <= CONFIG_LCD_MAXPOWER); + + /* Set new power level */ + + if (power > 0) + { + /* Set the backlight level */ + + lcd->backlight(lcd, power); + + /* Then turn the display on: + * D=ON(3) CM=0 DTE=1 GON=1 SPT=0 VLE=0 PT=0 + */ + + ssd1289_putreg(lcd, SSD1289_DSPCTRL, + (SSD1289_DSPCTRL_ON | SSD1289_DSPCTRL_GON | + SSD1289_DSPCTRL_DTE | SSD1289_DSPCTRL_VLE(0))); + + g_lcddev.power = power; + } + else + { + /* Turn the display off */ + + ssd1289_poweroff(lcd); + } + + return OK; +} + +/************************************************************************************** + * Name: ssd1289_getcontrast + * + * Description: + * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int ssd1289_getcontrast(FAR struct lcd_dev_s *dev) +{ + lcdvdbg("Not implemented\n"); + return -ENOSYS; +} + +/************************************************************************************** + * Name: ssd1289_setcontrast + * + * Description: + * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int ssd1289_setcontrast(FAR struct lcd_dev_s *dev, unsigned int contrast) +{ + lcdvdbg("contrast: %d\n", contrast); + return -ENOSYS; +} + +/************************************************************************************** + * Name: ssd1289_hwinitialize + * + * Description: + * Initialize the LCD hardware. + * + **************************************************************************************/ + +static inline int ssd1289_hwinitialize(FAR struct ssd1289_dev_s *priv) +{ + FAR struct ssd1289_lcd_s *lcd = priv->lcd; +#ifndef CONFIG_LCD_NOGETRUN + uint16_t id; +#endif + + /* Select the LCD */ + + lcd->select(lcd); + +#ifndef CONFIG_LCD_NOGETRUN + id = ssd1289_readreg(lcd, SSD1289_DEVCODE); + lcddbg("LCD ID: %04x\n", id); + + /* Check if the ID is for the SSD1289 */ + + if (id == SSD1289_DEVCODE_VALUE) +#endif + { + /* LCD controller configuration. Many details of the controller initialization + * must, unfortunately, vary from LCD to LCD. I have looked at the spec and at + * three different drivers for LCDs that have SSD1289 controllers. I have tried + * to summarize these differences as profiles (defined above). Some other + * alternatives are noted below. + * + * Most of the differences between LCDs are nothing more than a few minor bit + * settings. The most significant difference betwen LCD drivers in is the + * manner in which the LCD is powered up and in how the power controls are set. + * My suggestion is that if you have working LCD initialization code, you should + * simply replace the following guesses with your working code. + */ + + /* Most drivers just enable the oscillator */ + +#ifdef SSD1289_USE_SIMPLE_INIT + ssd1289_putreg(lcd, SSD1289_OSCSTART, SSD1289_OSCSTART_OSCEN); +#else + /* But one goes through a more complex start-up sequence. Something like the + * following: + * + * First, put the display in INTERNAL operation: + * D=INTERNAL(1) CM=0 DTE=0 GON=1 SPT=0 VLE=0 PT=0 + */ + + ssd1289_putreg(lcd, SSD1289_DSPCTRL, + (SSD1289_DSPCTRL_INTERNAL | SSD1289_DSPCTRL_GON | + SSD1289_DSPCTRL_VLE(0))); + + /* Then enable the oscillator */ + + ssd1289_putreg(lcd, SSD1289_OSCSTART, SSD1289_OSCSTART_OSCEN); + + /* Turn the display on: + * D=ON(3) CM=0 DTE=0 GON=1 SPT=0 VLE=0 PT=0 + */ + + ssd1289_putreg(lcd, SSD1289_DSPCTRL, + (SSD1289_DSPCTRL_ON | SSD1289_DSPCTRL_GON | + SSD1289_DSPCTRL_VLE(0))); + + /* Take the LCD out of sleep mode */ + + ssd1289_putreg(lcd, SSD1289_SLEEP, 0); + up_mdelay(30); + + /* Turn the display on: + * D=INTERNAL(1) CM=0 DTE=1 GON=1 SPT=0 VLE=0 PT=0 + */ + + ssd1289_putreg(lcd, SSD1289_DSPCTRL, + (SSD1289_DSPCTRL_ON | SSD1289_DSPCTRL_DTE | + SSD1289_DSPCTRL_GON | SSD1289_DSPCTRL_VLE(0))); +#endif + + /* Set up power control registers. There is a lot of variability + * from LCD-to-LCD in how the power registers are configured. + */ + + ssd1289_putreg(lcd, SSD1289_PWRCTRL1, PWRCTRL1_SETTING); + ssd1289_putreg(lcd, SSD1289_PWRCTRL2, PWRCTRL2_SETTING); + + /* One driver adds a delay here.. I doubt that this is really necessary. */ + /* up_mdelay(15); */ + + ssd1289_putreg(lcd, SSD1289_PWRCTRL3, PWRCTRL3_SETTING); + ssd1289_putreg(lcd, SSD1289_PWRCTRL4, PWRCTRL4_SETTING); + ssd1289_putreg(lcd, SSD1289_PWRCTRL5, PWRCTRL5_SETTING); + + /* One driver does an odd setting of the the driver output control. + * No idea why. + */ +#if 0 + ssd1289_putreg(lcd, SSD1289_OUTCTRL, + (SSD1289_OUTCTRL_MUX(12) | SSD1289_OUTCTRL_TB | + SSD1289_OUTCTRL_BGR | SSD1289_OUTCTRL_CAD)); + + /* The same driver does another small delay here */ + + up_mdelay(15); +#endif + + /* After this point, the drivers differ only in some varying register + * bit settings. + */ + + /* Set the driver output control. + * PORTRAIT MODES: + * MUX=319, TB=1, SM=0, BGR=1, CAD=0, REV=1, RL=0 + * LANDSCAPE MODES: + * MUX=319, TB=0, SM=0, BGR=1, CAD=0, REV=1, RL=0 + */ + +#if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT) + ssd1289_putreg(lcd, SSD1289_OUTCTRL, + (SSD1289_OUTCTRL_MUX(319) | SSD1289_OUTCTRL_TB | + SSD1289_OUTCTRL_BGR | SSD1289_OUTCTRL_REV); +#else + ssd1289_putreg(lcd, SSD1289_OUTCTRL, + (SSD1289_OUTCTRL_MUX(319) | SSD1289_OUTCTRL_BGR | + SSD1289_OUTCTRL_REV)); +#endif + + /* Set the LCD driving AC waveform + * NW=0, WSMD=0, EOR=1, BC=1, ENWD=0, FLD=0 + */ + + ssd1289_putreg(lcd, SSD1289_ACCTRL, + (SSD1289_ACCTRL_EOR | SSD1289_ACCTRL_BC)); + + /* Take the LCD out of sleep mode (isn't this redundant in the non- + * simple case?) + */ + + ssd1289_putreg(lcd, SSD1289_SLEEP, 0); + + /* Set entry mode */ + +#if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT) + /* LG=0, AM=0, ID=3, TY=2, DMODE=0, WMODE=0, OEDEF=0, TRANS=0, DRM=3 + * Alternative TY=2 (But TY only applies in 262K color mode anyway) + */ + + ssd1289_putreg(lcd, SSD1289_ENTRY, + (SSD1289_ENTRY_ID_HINCVINC | SSD1289_ENTRY_TY_C | + SSD1289_ENTRY_DMODE_RAM | SSD1289_ENTRY_DFM_65K)); +#else + /* LG=0, AM=1, ID=3, TY=2, DMODE=0, WMODE=0, OEDEF=0, TRANS=0, DRM=3 */ + /* Alternative TY=2 (But TY only applies in 262K color mode anyway) */ + + ssd1289_putreg(lcd, SSD1289_ENTRY, + (SSD1289_ENTRY_AM | SSD1289_ENTRY_ID_HINCVINC | + SSD1289_ENTRY_TY_C | SSD1289_ENTRY_DMODE_RAM | + SSD1289_ENTRY_DFM_65K)); +#endif + + /* Clear compare registers */ + + ssd1289_putreg(lcd, SSD1289_CMP1, 0); + ssd1289_putreg(lcd, SSD1289_CMP2, 0); + + /* One driver puts a huge, 100 millisecond delay here */ + /* up_mdelay(100); */ + + /* Set Horizontal and vertical porch. + * Horizontal porch: 239 pixels per line, delay=28 + * Vertical porch: VBP=3, XFP=0 + */ + + ssd1289_putreg(lcd, SSD1289_HPORCH, + (28 << SSD1289_HPORCH_HBP_SHIFT) | (239 << SSD1289_HPORCH_XL_SHIFT)); + ssd1289_putreg(lcd, SSD1289_VPORCH, + (3 << SSD1289_VPORCH_VBP_SHIFT) | (0 << SSD1289_VPORCH_XFP_SHIFT)); + + /* Set display control. + * D=ON(3), CM=0 (not 8-color), DTE=1, GON=1, SPT=0, VLE=1 PT=0 + */ + + ssd1289_putreg(lcd, SSD1289_DSPCTRL, + (SSD1289_DSPCTRL_ON | SSD1289_DSPCTRL_DTE | + SSD1289_DSPCTRL_GON | SSD1289_DSPCTRL_VLE(1))); + + /* Frame cycle control. Alternative: SSD1289_FCYCCTRL_DIV8 */ + + ssd1289_putreg(lcd, SSD1289_FCYCCTRL, 0); + + /* Gate scan start position = 0 */ + + ssd1289_putreg(lcd, SSD1289_GSTART, 0); + + /* Clear vertical scrolling */ + + ssd1289_putreg(lcd, SSD1289_VSCROLL1, 0); + ssd1289_putreg(lcd, SSD1289_VSCROLL2, 0); + + /* Setup window 1 (0-319) */ + + ssd1289_putreg(lcd, SSD1289_W1START, 0); + ssd1289_putreg(lcd, SSD1289_W1END, 319); + + /* Disable window 2 (0-0) */ + + ssd1289_putreg(lcd, SSD1289_W2START, 0); + ssd1289_putreg(lcd, SSD1289_W2END, 0); + + /* Horizontal start and end (0-239) */ + + ssd1289_putreg(lcd, SSD1289_HADDR, + (0 << SSD1289_HADDR_HSA_SHIFT) | (239 << SSD1289_HADDR_HEA_SHIFT)); + + /* Vertical start and end (0-319) */ + + ssd1289_putreg(lcd, SSD1289_VSTART, 0); + ssd1289_putreg(lcd, SSD1289_VEND, 319); + + /* Gamma controls */ + + ssd1289_putreg(lcd, SSD1289_GAMMA1, 0x0707); + ssd1289_putreg(lcd, SSD1289_GAMMA2, 0x0204); /* Alternative: 0x0704 */ + ssd1289_putreg(lcd, SSD1289_GAMMA3, 0x0204); + ssd1289_putreg(lcd, SSD1289_GAMMA4, 0x0502); + ssd1289_putreg(lcd, SSD1289_GAMMA5, 0x0507); + ssd1289_putreg(lcd, SSD1289_GAMMA6, 0x0204); + ssd1289_putreg(lcd, SSD1289_GAMMA7, 0x0204); + ssd1289_putreg(lcd, SSD1289_GAMMA8, 0x0502); + ssd1289_putreg(lcd, SSD1289_GAMMA9, 0x0302); + ssd1289_putreg(lcd, SSD1289_GAMMA10, 0x0302); /* Alternative: 0x1f00 */ + + /* Clear write mask */ + + ssd1289_putreg(lcd, SSD1289_WRMASK1, 0); + ssd1289_putreg(lcd, SSD1289_WRMASK2, 0); + + /* Set frame frequency = 65Hz (This should not be necessary since this + * is the default POR value) + */ + + ssd1289_putreg(lcd, SSD1289_FFREQ, SSD1289_FFREQ_OSC_FF65); + + /* Set the cursor at the home position and set the index register to + * the gram data register (I can't imagine these are necessary). + */ + + ssd1289_setcursor(lcd, 0, 0); + ssd1289_gramselect(lcd); + + /* One driver has a 50 msec delay here */ + /* up_mdelay(50); */ + + return OK; + } +#ifndef CONFIG_LCD_NOGETRUN + else + { + lcddbg("Unsupported LCD type\n"); + return -ENODEV; + } +#endif + + /* De-select the LCD */ + + lcd->deselect(lcd); +} + + /************************************************************************************* + * Public Functions + **************************************************************************************/ + +/************************************************************************************** + * Name: ssd1289_lcdinitialize + * + * Description: + * Initialize the LCD video hardware. The initial state of the LCD is fully + * initialized, display memory cleared, and the LCD ready to use, but with the power + * setting at 0 (full off). + * + **************************************************************************************/ + +FAR struct lcd_dev_s *ssd1289_lcdinitialize(FAR struct ssd1289_lcd_s *lcd) +{ + int ret; + + lcdvdbg("Initializing\n"); + + /* If we ccould support multiple SSD1289 devices, this is where we would allocate + * a new driver data structure... but we can't. Why not? Because of a bad should + * the form of the getrun() and putrun methods. + */ + + FAR struct ssd1289_dev_s *priv = &g_lcddev; + + /* Initialize the driver data structure */ + + priv->dev.getvideoinfo = ssd1289_getvideoinfo; + priv->dev.getplaneinfo = ssd1289_getplaneinfo; + priv->dev.getpower = ssd1289_getpower; + priv->dev.setpower = ssd1289_setpower; + priv->dev.getcontrast = ssd1289_getcontrast; + priv->dev.setcontrast = ssd1289_setcontrast; + priv->lcd = lcd; + + /* Configure and enable LCD */ + + ret = ssd1289_hwinitialize(priv); + if (ret == OK) + { + /* Clear the display (setting it to the color 0=black) */ + + ssd1289_clear(&priv->dev, 0); + + /* Turn the display off */ + + ssd1289_poweroff(lcd); + return &g_lcddev.dev; + } + + return NULL; +} + +/************************************************************************************** + * Name: ssd1289_clear + * + * Description: + * This is a non-standard LCD interface just for the stm3240g-EVAL board. Because + * of the various rotations, clearing the display in the normal way by writing a + * sequences of runs that covers the entire display can be very slow. Here the + * display is cleared by simply setting all GRAM memory to the specified color. + * + **************************************************************************************/ + +void ssd1289_clear(FAR struct lcd_dev_s *dev, uint16_t color) +{ + FAR struct ssd1289_dev_s *priv = (FAR struct ssd1289_dev_s *)dev; + FAR struct ssd1289_lcd_s *lcd = priv->lcd; + uint32_t i; + + /* Select the LCD and home the cursor position */ + + lcd->select(lcd); + ssd1289_setcursor(lcd, 0, 0); + + /* Prepare to write GRAM data */ + + ssd1289_gramselect(lcd); + + /* Copy color into all of GRAM. Orientation does not matter in this case. */ + + for (i = 0; i < SSD1289_XRES * SSD1289_YRES; i++) + { + ssd1289_gramwrite(lcd, color); + } + + /* De-select the LCD */ + + lcd->deselect(lcd); +} + +#endif /* CONFIG_LCD_SSD1289 */ diff --git a/nuttx/drivers/lcd/ssd1289.h b/nuttx/drivers/lcd/ssd1289.h new file mode 100644 index 0000000000..6d5d1c3cb0 --- /dev/null +++ b/nuttx/drivers/lcd/ssd1289.h @@ -0,0 +1,425 @@ +/************************************************************************************** + * drivers/lcd/ssd1289.h + * Definitions for the Solomon Systech SSD1289 LCD controller + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: SSD1289, Rev 1.3, Apr 2007, Solomon Systech Limited + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +#ifndef __DRIVERS_LCD_SSD1289_H +#define __DRIVERS_LCD_SSD1289_H + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +#include + +#ifdef CONFIG_LCD_SSD1289 + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ + +/* SSD1289 Register Addresses (All with DC=1) */ + +#define SSD1289_OSCSTART 0x00 /* Oscillation Start (write) */ +#define SSD1289_DEVCODE 0x00 /* Oscillation Start (read) */ +#define SSD1289_OUTCTRL 0x01 /* Driver output control */ +#define SSD1289_ACCTRL 0x02 /* LCD drive AC control */ +#define SSD1289_PWRCTRL1 0x03 /* Power control 1 */ +#define SSD1289_CMP1 0x05 /* Compare register 1 */ +#define SSD1289_CMP2 0x06 /* Compare register 2 */ +#define SSD1289_DSPCTRL 0x07 /* Display control */ +#define SSD1289_FCYCCTRL 0x0b /* Frame cycle control */ +#define SSD1289_PWRCTRL2 0x0c /* Power control 2 */ +#define SSD1289_PWRCTRL3 0x0d /* Power control 3 */ +#define SSD1289_PWRCTRL4 0x0e /* Power control 4 */ +#define SSD1289_GSTART 0x0f /* Gate scan start position */ +#define SSD1289_SLEEP 0x10 /* Sleep mode */ +#define SSD1289_ENTRY 0x11 /* Entry mode */ +#define SSD1289_OPT3 0x12 /* Optimize Access Speed 3 */ +#define SSD1289_GIFCTRL 0x15 /* Generic Interface Control */ +#define SSD1289_HPORCH 0x16 /* Horizontal Porch */ +#define SSD1289_VPORCH 0x17 /* Vertical Porch */ +#define SSD1289_PWRCTRL5 0x1e /* Power control 5 */ +#define SSD1289_DATA 0x22 /* RAM data/write data */ +#define SSD1289_WRMASK1 0x23 /* RAM write data mask 1 */ +#define SSD1289_WRMASK2 0x24 /* RAM write data mask 2 */ +#define SSD1289_FFREQ 0x25 /* Frame Frequency */ +#define SSD1289_VCOMOTP1 0x28 /* VCOM OTP */ +#define SSD1289_OPT1 0x28 /* Optimize Access Speed 1 */ +#define SSD1289_VCOMOTP2 0x29 /* VCOM OTP */ +#define SSD1289_OPT2 0x2f /* Optimize Access Speed 2 */ +#define SSD1289_GAMMA1 0x30 /* Gamma control 1 */ +#define SSD1289_GAMMA2 0x31 /* Gamma control 2 */ +#define SSD1289_GAMMA3 0x32 /* Gamma control 3 */ +#define SSD1289_GAMMA4 0x33 /* Gamma control 4 */ +#define SSD1289_GAMMA5 0x34 /* Gamma control 5 */ +#define SSD1289_GAMMA6 0x35 /* Gamma control 6 */ +#define SSD1289_GAMMA7 0x36 /* Gamma control 7 */ +#define SSD1289_GAMMA8 0x37 /* Gamma control 8 */ +#define SSD1289_GAMMA9 0x3a /* Gamma control 9 */ +#define SSD1289_GAMMA10 0x3b /* Gamma control 10 */ +#define SSD1289_VSCROLL1 0x41 /* Vertical scroll control 1 */ +#define SSD1289_VSCROLL2 0x42 /* Vertical scroll control 2 */ +#define SSD1289_HADDR 0x44 /* Horizontal RAM address position */ +#define SSD1289_VSTART 0x45 /* Vertical RAM address start position */ +#define SSD1289_VEND 0x46 /* Vertical RAM address end position */ +#define SSD1289_W1START 0x48 /* First window start */ +#define SSD1289_W1END 0x49 /* First window end */ +#define SSD1289_W2START 0x4a /* Second window start */ +#define SSD1289_W2END 0x4b /* Second window end */ +#define SSD1289_XADDR 0x4e /* Set GDDRAM X address counter */ +#define SSD1289_YADDR 0x4f /* Set GDDRAM Y address counter */ + +/* SSD1289 Register Bit definitions */ + +/* Index register (DC=0) */ + +#define SSD1289_INDEX_MASK 0xff + +/* Device code (read) */ + +#define SSD1289_DEVCODE_VALUE 0x8989 + +/* Oscillation Start (write) */ + +#define SSD1289_OSCSTART_OSCEN (1 << 0) /* Enable oscillator */ + +/* Driver output control */ + +#define SSD1289_OUTCTRL_MUX_SHIFT (0) /* Number of lines for the LCD driver */ +#define SSD1289_OUTCTRL_MUX_MASK (0x1ff << SSD1289_OUTCTRL_MUX_SHIFT) +# define SSD1289_OUTCTRL_MUX(n) ((n) << SSD1289_OUTCTRL_MUX_SHIFT) +#define SSD1289_OUTCTRL_TB (1 << 9) /* Selects the output shift direction of the gate driver */ +#define SSD1289_OUTCTRL_SM (1 << 10) /* Scanning order of gate driver */ +#define SSD1289_OUTCTRL_BGR (1 << 11) /* Order from RGB to BGR in 18-bit GDDRAM data */ +#define SSD1289_OUTCTRL_CAD (1 << 12) /* Retention capacitor configuration of the TFT panel */ +#define SSD1289_OUTCTRL_REV (1 << 13) /* Reversed display */ +#define SSD1289_OUTCTRL_RL (1 << 14) /* RL pin state */ + +/* LCD drive AC control */ + +#define SSD1289_ACCTRL_NW_SHIFT (0) /* Number of lines to alternate in N-line inversion */ +#define SSD1289_ACCTRL_NW_MASK (0xff << SSD1289_ACCTRL_NW_SHIFT) +#define SSD1289_ACCTRL_WSMD (1 << 8) /* Waveform of WSYNC output */ +#define SSD1289_ACCTRL_EOR (1 << 9) /* EOR signals */ +#define SSD1289_ACCTRL_BC (1 << 10) /* Select the liquid crystal drive waveform */ +#define SSD1289_ACCTRL_ENWS (1 << 11) /* Enables WSYNC output pin */ +#define SSD1289_ACCTRL_FLD (1 << 12) /* Set display in interlace drive mode */ + +/* Power control 1 */ + +#define SSD1289_PWRCTRL1_AP_SHIFT (1) /* Current from internal operational amplifier */ +#define SSD1289_PWRCTRL1_AP_MASK (7 << SSD1289_PWRCTRL1_AP_SHIFT) +# define SSD1289_PWRCTRL1_AP_LEAST (0 << SSD1289_PWRCTRL1_AP_SHIFT) +# define SSD1289_PWRCTRL1_AP_SMALL (1 << SSD1289_PWRCTRL1_AP_SHIFT) +# define SSD1289_PWRCTRL1_AP_SMMED (2 << SSD1289_PWRCTRL1_AP_SHIFT) +# define SSD1289_PWRCTRL1_AP_MEDIUM (3 << SSD1289_PWRCTRL1_AP_SHIFT) +# define SSD1289_PWRCTRL1_AP_MEDLG (4 << SSD1289_PWRCTRL1_AP_SHIFT) +# define SSD1289_PWRCTRL1_AP_LARGE (5 << SSD1289_PWRCTRL1_AP_SHIFT) +# define SSD1289_PWRCTRL1_AP_LGMX (6 << SSD1289_PWRCTRL1_AP_SHIFT) +# define SSD1289_PWRCTRL1_AP_MAX (7 << SSD1289_PWRCTRL1_AP_SHIFT) +#define SSD1289_PWRCTRL1_DC_SHIFT (4) /* Set the step-up cycle of the step-up circuit for 262k-color mode */ +#define SSD1289_PWRCTRL1_DC_MASK (15 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FLINEx24 (0 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FLINEx16 (1 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FLINEx12 (2 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FLINEx8 (3 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FLINEx6 (4 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FLINEx5 (5 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FLINEx4 (6 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FLINEx3 (7 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FLINEx2 (8 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FLINEx1 (9 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FOSd4 (10 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FOSd6 (11 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FOSd8 (12 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FOSd10 (13 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FOSd12 (14 << SSD1289_PWRCTRL1_DC_SHIFT) +# define SSD1289_PWRCTRL1_DC_FOSd16 (15 << SSD1289_PWRCTRL1_DC_SHIFT) +#define SSD1289_PWRCTRL1_BT_SHIFT (9) /* Control the step-up factor of the step-up circuit */ +#define SSD1289_PWRCTRL1_BT_MASK (7 << SSD1289_PWRCTRL1_BT_SHIFT) +# define SSD1289_PWRCTRL1_BT_p6m5 (0 << SSD1289_PWRCTRL1_BT_SHIFT) +# define SSD1289_PWRCTRL1_BT_p6m4 (1 << SSD1289_PWRCTRL1_BT_SHIFT) +# define SSD1289_PWRCTRL1_BT_p6m6 (2 << SSD1289_PWRCTRL1_BT_SHIFT) +# define SSD1289_PWRCTRL1_BT_p5m5 (3 << SSD1289_PWRCTRL1_BT_SHIFT) +# define SSD1289_PWRCTRL1_BT_p5m4 (4 << SSD1289_PWRCTRL1_BT_SHIFT) +# define SSD1289_PWRCTRL1_BT_p5m3 (5 << SSD1289_PWRCTRL1_BT_SHIFT) +# define SSD1289_PWRCTRL1_BT_p4m4 (6 << SSD1289_PWRCTRL1_BT_SHIFT) +# define SSD1289_PWRCTRL1_BT_p4m3 (7 << SSD1289_PWRCTRL1_BT_SHIFT) +#define SSD1289_PWRCTRL1_DCT_SHIFT (12) /* Step-up cycle of the step-up circuit for 8-color mode */ +#define SSD1289_PWRCTRL1_DCT_MASK (15 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FLINEx24 (0 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FLINEx16 (1 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FLINEx12 (2 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FLINEx8 (3 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FLINEx6 (4 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FLINEx5 (5 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FLINEx4 (6 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FLINEx3 (7 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FLINEx2 (8 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FLINEx1 (9 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FOSd4 (10 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FOSd6 (11 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FOSd8 (12 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FOSd10 (13 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FOSd12 (14 << SSD1289_PWRCTRL1_DCT_SHIFT) +# define SSD1289_PWRCTRL1_DCT_FOSd16 (15 << SSD1289_PWRCTRL1_DCT_SHIFT) + +/* Compare register 1 and 2 */ + +#define SSD1289_CMP1_CPG_SHIFT (2) +#define SSD1289_CMP1_CPG_MASK (0x3f << SSD1289_CMP1_CPG_SHIFT) +#define SSD1289_CMP1_CPR_SHIFT (10) +#define SSD1289_CMP1_CPR_MASK (0x3f << SSD1289_CMP1_CPR_SHIFT) + +#define SSD1289_CMP2_CPB_SHIFT (2) +#define SSD1289_CMP2_CPB_MASK (0x3f << SSD1289_CMP2_CPB_SHIFT) + +/* Display control */ + +#define SSD1289_DSPCTRL_D_SHIFT (0) /* Display control */ +#define SSD1289_DSPCTRL_D_MASK (3 << SSD1289_DSPCTRL_D_SHIFT) +# define SSD1289_DSPCTRL_OFF (0 << SSD1289_DSPCTRL_D_SHIFT) +# define SSD1289_DSPCTRL_INTERNAL (1 << SSD1289_DSPCTRL_D_SHIFT) +# define SSD1289_DSPCTRL_ON (3 << SSD1289_DSPCTRL_D_SHIFT) +#define SSD1289_DSPCTRL_CM (1 << 3) /* 8-color mode setting */ +#define SSD1289_DSPCTRL_DTE (1 << 4) /* Selected gate level */ +#define SSD1289_DSPCTRL_GON (1 << 5) /* Gate off level */ +#define SSD1289_DSPCTRL_SPT (1 << 8) /* 2-division LCD drive */ +#define SSD1289_DSPCTRL_VLE_SHIFT (9) /* Vertical scroll control */ +#define SSD1289_DSPCTRL_VLE_MASK (3 << SSD1289_DSPCTRL_VLE_SHIFT) +# define SSD1289_DSPCTRL_VLE(n) ((n) << SSD1289_DSPCTRL_VLE_SHIFT) +#define SSD1289_DSPCTRL_PT_SHIFT (11) /* Normalize the source outputs */ +#define SSD1289_DSPCTRL_PT_MASK (3 << SSD1289_DSPCTRL_PT_SHIFT) +# define SSD1289_DSPCTRL_PT(n) ((n) << SSD1289_DSPCTRL_PT_SHIFT) + +/* Frame cycle control */ + +#define SSD1289_FCYCCTRL_RTN_SHIFT (0) /* Number of clocks in each line */ +#define SSD1289_FCYCCTRL_RTN_MASK (3 << SSD1289_FCYCCTRL_RTN_SHIFT) +# define SSD1289_FCYCCTRL_RTN(n) (((n)-16) << SSD1289_FCYCCTRL_RTN_SHIFT) +#define SSD1289_FCYCCTRL_SRTN (1 << 4) /* When SRTN =1, RTN3-0 value will be count */ +#define SSD1289_FCYCCTRL_SDIV (1 << 5) /* When SDIV = 1, DIV1-0 value will be count */ +#define SSD1289_FCYCCTRL_DIV_SHIFT (6) /* Set the division ratio of clocks */ +#define SSD1289_FCYCCTRL_DIV_MASK (3 << SSD1289_FCYCCTRL_DIV_SHIFT) +# define SSD1289_FCYCCTRL_DIV1 (0 << SSD1289_FCYCCTRL_DIV_SHIFT) +# define SSD1289_FCYCCTRL_DIV2 (1 << SSD1289_FCYCCTRL_DIV_SHIFT) +# define SSD1289_FCYCCTRL_DIV4 (2 << SSD1289_FCYCCTRL_DIV_SHIFT) +# define SSD1289_FCYCCTRL_DIV8 (3 << SSD1289_FCYCCTRL_DIV_SHIFT) +#define SSD1289_FCYCCTRL_EQ_SHIFT (8) /* Sets the equalizing period */ +#define SSD1289_FCYCCTRL_EQ_MASK (3 << SSD1289_FCYCCTRL_EQ_SHIFT) +# define SSD1289_FCYCCTRL_EQ(n) (((n)-1) << SSD1289_FCYCCTRL_EQ_SHIFT) /* n = 2-8 clocks */ +#define SSD1289_FCYCCTRL_SDT_SHIFT (12) /* Set delay amount from the gate output */ +#define SSD1289_FCYCCTRL_SDT_MASK (3 << SSD1289_FCYCCTRL_SDT_SHIFT) +# define SSD1289_FCYCCTRL_SDT(n) ((n) << SSD1289_FCYCCTRL_SDT_SHIFT) /* n = 1-3 clocks */ +#define SSD1289_FCYCCTRL_NO_SHIFT (14) /* Sets amount of non-overlap of the gate output */ +#define SSD1289_FCYCCTRL_NO_MASK (3 << SSD1289_FCYCCTRL_NO_SHIFT) +# define SSD1289_FCYCCTRL_NO(n) ((n) << SSD1289_FCYCCTRL_NO_SHIFT) /* n = 1-3 clocks */ + +/* Power control 2 */ + +#define SSD1289_PWRCTRL2_VRC_SHIFT (0) /* Adjust VCIX2 output voltage */ +#define SSD1289_PWRCTRL2_VRC_MASK (7 << SSD1289_PWRCTRL2_VRC_SHIFT) +# define SSD1289_PWRCTRL2_VRC_5p1V (0 << SSD1289_PWRCTRL2_VRC_SHIFT) +# define SSD1289_PWRCTRL2_VRC_5p2V (1 << SSD1289_PWRCTRL2_VRC_SHIFT) +# define SSD1289_PWRCTRL2_VRC_5p3V (2 << SSD1289_PWRCTRL2_VRC_SHIFT) +# define SSD1289_PWRCTRL2_VRC_5p4V (3 << SSD1289_PWRCTRL2_VRC_SHIFT) +# define SSD1289_PWRCTRL2_VRC_5p5V (4 << SSD1289_PWRCTRL2_VRC_SHIFT) +# define SSD1289_PWRCTRL2_VRC_5p6V (5 << SSD1289_PWRCTRL2_VRC_SHIFT) +# define SSD1289_PWRCTRL2_VRC_5p7V (6 << SSD1289_PWRCTRL2_VRC_SHIFT) +# define SSD1289_PWRCTRL2_VRC_5p8V (7 << SSD1289_PWRCTRL2_VRC_SHIFT) + +/* Power control 3 */ + +#define SSD1289_PWRCTRL3_VRH_SHIFT (0) /* Set amplitude magnification of VLCD63 */ +#define SSD1289_PWRCTRL3_VRH_MASK (15 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x1p540 (0 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x1p620 (1 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x1p700 (2 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x1p780 (3 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x1p850 (4 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x1p930 (5 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x2p020 (6 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x2p090 (7 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x2p165 (8 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x2p245 (9 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x2p335 (10 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x2p400 (11 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x2p500 (12 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x2p570 (13 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x2p645 (14 << SSD1289_PWRCTRL3_VRH_SHIFT) +# define SSD1289_PWRCTRL3_VRH_x2p725 (15 << SSD1289_PWRCTRL3_VRH_SHIFT) + +/* Power control 4 */ + +#define SSD1289_PWRCTRL4_VDV_SHIFT (8) /* Set amplitude magnification of VLCD63 */ +#define SSD1289_PWRCTRL4_VDV_MASK (32 << SSD1289_PWRCTRL4_VDV_SHIFT) +# define SSD1289_PWRCTRL4_VDV(n) ((n) << SSD1289_PWRCTRL4_VDV_SHIFT) +#define SSD1289_PWRCTRL4_VCOMG (1 << 13) /* VcomL variable */ + +/* Gate scan start position */ + +#define SSD1289_GSTART_MASK 0x1ff + +/* Sleep mode */ + +#define SSD1289_SLEEP_ON (1 << 0) + +/* Entry mode */ + +#define SSD1289_ENTRY_LG_SHIFT (0) /* Write after comparing */ +#define SSD1289_ENTRY_LG_MASK (7 << SSD1289_ENTRY_LG_SHIFT) +#define SSD1289_ENTRY_AM (1 << 3) /* Address counter direction */ +#define SSD1289_ENTRY_ID_SHIFT (4) /* Address increment mode */ +#define SSD1289_ENTRY_ID_MASK (3 << SSD1289_ENTRY_ID_SHIFT) +# define SSD1289_ENTRY_ID_HDECVDEC (0 << SSD1289_ENTRY_ID_SHIFT) +# define SSD1289_ENTRY_ID_HINCVDEC (1 << SSD1289_ENTRY_ID_SHIFT) +# define SSD1289_ENTRY_ID_HDECVINC (2 << SSD1289_ENTRY_ID_SHIFT) +# define SSD1289_ENTRY_ID_HINCVINC (3 << SSD1289_ENTRY_ID_SHIFT) +#define SSD1289_ENTRY_TY_SHIFT (6) /* RAM data write method */ +#define SSD1289_ENTRY_TY_MASK (3 << SSD1289_ENTRY_TY_SHIFT) +# define SSD1289_ENTRY_TY_A (0 << SSD1289_ENTRY_TY_SHIFT) +# define SSD1289_ENTRY_TY_B (1 << SSD1289_ENTRY_TY_SHIFT) +# define SSD1289_ENTRY_TY_C (2 << SSD1289_ENTRY_TY_SHIFT) +#define SSD1289_ENTRY_DMODE_SHIFT (8) /* Data display mode */ +#define SSD1289_ENTRY_DMODE_MASK (3 << SSD1289_ENTRY_DMODE_SHIFT) +# define SSD1289_ENTRY_DMODE_RAM (0 << SSD1289_ENTRY_DMODE_SHIFT) +# define SSD1289_ENTRY_DMODE_GENERIC (1 << SSD1289_ENTRY_DMODE_SHIFT) +# define SSD1289_ENTRY_DMODE_RAMGEN (2 << SSD1289_ENTRY_DMODE_SHIFT) +# define SSD1289_ENTRY_DMODE_GENRAM (3 << SSD1289_ENTRY_DMODE_SHIFT) +#define SSD1289_ENTRY_WMODE (1 << 10) /* Select source of data in RAM */ +#define SSD1289_ENTRY_OEDEF (1 << 11) /* Define display window */ +#define SSD1289_ENTRY_TRANS (1 << 12) /* Transparent display */ +#define SSD1289_ENTRY_DFM_SHIFT (13) /* Color display mode */ +#define SSD1289_ENTRY_DFM_MASK (3 << SSD1289_ENTRY_DFM_SHIFT) +# define SSD1289_ENTRY_DFM_262K (2 << SSD1289_ENTRY_DFM_SHIFT) +# define SSD1289_ENTRY_DFM_65K (3 << SSD1289_ENTRY_DFM_SHIFT) +#define SSD1289_ENTRY_VSMODE (1 << 15) /* Frame frequency depends on VSYNC */ + +/* Generic Interface Control */ + +#define SSD1289_GIFCTRL_INVVS (1 << 0) /* Sets the signal polarity of DOTCLK pin */ +#define SSD1289_GIFCTRL_INVHS (1 << 1) /* Sets the signal polarity of DEN pin */ +#define SSD1289_GIFCTRL_NVDEN (1 << 2) /* Sets the signal polarity of HSYNC pin */ +#define SSD1289_GIFCTRL_INVDOT (1 << 3) /* Sets the signal polarity of VSYNC pin */ + +/* Horizontal Porch */ + +#define SSD1289_HPORCH_HBP_SHIFT (0) /* Set delay from falling edge of HSYNC signal to data */ +#define SSD1289_HPORCH_HBP_MASK (0xff << SSD1289_HPORCH_HBP_SHIFT) +#define SSD1289_HPORCH_XL_SHIFT (8) /* number of valid pixel per line */ +#define SSD1289_HPORCH_XL_MASK (0xff << SSD1289_HPORCH_XL_SHIFT) + +/* Vertical Porch */ + +#define SSD1289_VPORCH_VBP_SHIFT (0) /* Set delay from falling edge of VSYNC signal to line */ +#define SSD1289_VPORCH_VBP_MASK (0xff << SSD1289_VPORCH_VBP_SHIFT) +#define SSD1289_VPORCH_XFP_SHIFT (8) /* Delay from last line to falling edge of VSYNC of next frame */ +#define SSD1289_VPORCH_XFP_MASK (0xff << SSD1289_VPORCH_XFP_SHIFT) +#define SSD1289_VPORCH_ + +/* Power control 5 */ + +#define SSD1289_PWRCTRL5_VCM_SHIFT (0) /* Set the VcomH voltage */ +#define SSD1289_PWRCTRL5_VCM_MASK (0x3f << SSD1289_PWRCTRL5_VCM_SHIFT) +# define SSD1289_PWRCTRL5_VCM(n) ((n) << SSD1289_PWRCTRL5_VCM_SHIFT) +#define SSD1289_PWRCTRL5_NOTP (1 << 7) /* 1=VCM valid */ + +/* RAM write data mask 1 */ + +#define SSD1289_WRMASK1_WMG_SHIFT (2) +#define SSD1289_WRMASK1_WMG_MASK (0x3f << SSD1289_WRMASK1_WMG_SHIFT) +#define SSD1289_WRMASK1_WMR_SHIFT (10) +#define SSD1289_WRMASK1_WMR_MASK (0x3f << SSD1289_WRMASK1_WMR_SHIFT) + +#define SSD1289_WRMASK2_WMB_SHIFT (2) +#define SSD1289_WRMASK2_WMB_MASK (0x3f << SSD1289_WRMASK2_WMB_SHIFT) + +/* Frame Frequency */ + +#define SSD1289_FFREQ_OSC_SHIFT (12) /* Set the frame frequency */ +#define SSD1289_FFREQ_OSC_MASK (15 << SSD1289_FFREQ_OSC_SHIFT) +# define SSD1289_FFREQ_OSC_FF50 (0 << SSD1289_FFREQ_OSC_SHIFT) +# define SSD1289_FFREQ_OSC_FF55 (2 << SSD1289_FFREQ_OSC_SHIFT) +# define SSD1289_FFREQ_OSC_FF60 (5 << SSD1289_FFREQ_OSC_SHIFT) +# define SSD1289_FFREQ_OSC_FF65 (8 << SSD1289_FFREQ_OSC_SHIFT) +# define SSD1289_FFREQ_OSC_FF70 (10 << SSD1289_FFREQ_OSC_SHIFT) +# define SSD1289_FFREQ_OSC_FF75 (12 << SSD1289_FFREQ_OSC_SHIFT) +# define SSD1289_FFREQ_OSC_FF80 (14 << SSD1289_FFREQ_OSC_SHIFT) + +/* VCOM OTP */ + +#define SSD1289_VCOMOTP1_ACTIVATE 0x0006 +#define SSD1289_VCOMOTP1_FIRE 0x000a +#define SSD1289_VCOMOTP2_ACTIVATE 0x80c0 + +/* Optimize Access Speed 1, 2, 3 (omitted) */ + +/* Gamma control 1-10. Magic values. I won't try to represent the fields. */ + +/* Vertical scroll control 1 and 2 */ + +#define SSD1289_VSCROLL_MASK 0x1ff /* Scroll length */ + +/* Horizontal RAM address position */ + +#define SSD1289_HADDR_HSA_SHIFT (0) /* Window horizontal start address */ +#define SSD1289_HADDR_HSA_MASK (0xff << SSD1289_HADDR_HSA_SHIFT) +#define SSD1289_HADDR_HEA_SHIFT (8) /* Window horizontal end address */ +#define SSD1289_HADDR_HEA_MASK (0xff << SSD1289_HADDR_HEA_SHIFT) + +/* Vertical RAM address start/end position */ + +#define SSD1289_VSTART_MASK 0x1ff /* Window Vertical start address */ +#define SSD1289_VEND_MASK 0x1ff /* Window Vertical end address */ + +/* First window start/end */ + +#define SSD1289_W1START_MASK 0x1ff /* Start line for first screen */ +#define SSD1289_W1END_MASK 0x1ff /* End line for first screen */ + +/* Second window start/end */ + +#define SSD1289_W2START_MASK 0x1ff /* Start line for second screen */ +#define SSD1289_W2END_MASK 0x1ff /* End line for second screen */ + +/* Set GDDRAM X/Y address counter */ + +#define SSD1289_XADDR_MASK 0xff /* GDDRAM X address in the address counter */ +#define SSD1289_YADDR_MASK 0x1ff /* GDDRAM Y address in the address counter */ + +#endif /* CONFIG_LCD_SSD1289 */ +#endif /* __DRIVERS_LCD_SSD1289_H */ diff --git a/nuttx/drivers/lcd/ssd1305.h b/nuttx/drivers/lcd/ssd1305.h new file mode 100644 index 0000000000..87c955de4d --- /dev/null +++ b/nuttx/drivers/lcd/ssd1305.h @@ -0,0 +1,211 @@ +/************************************************************************************** + * drivers/lcd/ssd1305.h + * Definitions for the Solomon Systech SSD1305 132x64 Dot Matrix OLED/PLED + * Segment/Common Driver with C + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: SSD1305.pdf, "Solomon Systech SSD1305 132x64 Dot Matrix OLED/PLED + * Segment/Common Driver with Controller," Solomon Systech Limited, + * http://www.solomon-systech.com, May, 2008. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +#ifndef __DRIVERS_LCD_SSD1305_H +#define __DRIVERS_LCD_SSD1305_H + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ +/* General Definitions ******************************************************/ + +#define SSD1305_COLORA 0 +#define SSD1305_COLORB 1 +#define SSD1305_COLORC 2 +#define SSD1305_COLORD 3 + +/* Fundamental Commands *****************************************************/ +#define SSD1305_SETCOLL 0x00 /* 0x00-0x0f: Set lower column address */ +# define SSD1305_COLL_MASK 0x0f +#define SSD1305_SETCOLH 0x10 /* 0x10-0x1f: Set higher column address */ +# define SSD1305_COLH_MASK 0x0f +#define SSD1305_ADDRMODE 0x20 /* 0x20: Set memory address mode */ +# define SSD1305_ADDRMODE_HOR 0x00 /* Data 1: Set horizontal address mode */ +# define SSD1305_ADDRMODE_VIRT 0x01 /* Data 1: Set virtal address mode */ +# define SSD1305_ADDRMODE_PAGE 0x02 /* Data 1: Set page address mode */ +#define SSD1305_SETCOLADDR 0x21 /* 0x21: Set column address */ + /* Data 1: Column start address: 0-131 */ + /* Data 2: Column end address: 0-131 */ +#define SSD1305_SETPAGEADDR 0x22 /* 0x22: Set page address */ + /* Data 1: Page start address: 0x00-0x7d */ + /* Data 2: Page end address: 0x00-0x7d */ +#define SSD1305_SETSTARTLINE 0x40 /* 0x40-7f: Set display start line */ +# define SSD1305_STARTLINE_MASK 0x3f + +#define SSD1305_SETCONTRAST 0x81 /* 0x81: Set contrast control */ + /* Data 1: Set 1 of 256 contrast steps */ +#define SSD1305_SETBRIGHTNESS 0x82 /* 0x82: Set brightness */ + /* Data 1: Set 1 of 256 contrast steps */ +#define SSD1305_SETLUT 0x91 /* 0x01: Set lookup table */ + /* Data 1: Pulse width: 31-63 */ + /* Data 2: Color A: 31-63 */ + /* Data 3: Color B: 31-63 */ + /* Data 4: Color C: 31-63 */ +#define SSD1305_SETBANKCOLOR1 0x92 /* 0x92: Set bank 1-16 color */ +# define SSD1305_SETBANK1(c) (c) /* Data 1, Bits 0-1: Bank 1 color */ +# define SSD1305_SETBANK2(c) (c << 2) /* Data 1, Bits 2-3: Bank 2 color */ +# define SSD1305_SETBANK3(c) (c << 4) /* Data 1, Bits 4-5: Bank 3 color */ +# define SSD1305_SETBANK4(c) (c << 6) /* Data 1, Bits 6-7: Bank 4 color */ +# define SSD1305_SETBANK5(c) (c) /* Data 2, Bits 0-1: Bank 5 color */ +# define SSD1305_SETBANK6(c) (c << 2) /* Data 2, Bits 2-3: Bank 6 color */ +# define SSD1305_SETBANK7(c) (c << 4) /* Data 2, Bits 4-5: Bank 7 color */ +# define SSD1305_SETBANK8(c) (c << 6) /* Data 2, Bits 6-7: Bank 8 color */ +# define SSD1305_SETBANK9(c) (c) /* Data 3, Bits 0-1: Bank 9 color */ +# define SSD1305_SETBANK10(c) (c << 2) /* Data 3, Bits 2-3: Bank 10 color */ +# define SSD1305_SETBANK11(c) (c << 4) /* Data 3, Bits 4-5: Bank 11 color */ +# define SSD1305_SETBANK12(c) (c << 6) /* Data 3, Bits 6-7: Bank 12 color */ +# define SSD1305_SETBANK13(c) (c) /* Data 4, Bits 0-1: Bank 13 color */ +# define SSD1305_SETBANK14(c) (c << 2) /* Data 4, Bits 2-3: Bank 14 color */ +# define SSD1305_SETBANK15(c) (c << 4) /* Data 4, Bits 4-5: Bank 15 color */ +# define SSD1305_SETBANK16(c) (c << 6) /* Data 4, Bits 6-7: Bank 16 color */ +#define SSD1305_SETBANKCOLOR2 0x93 /* 0x93: Set bank 17-32 color */ +# define SSD1305_SETBANK17(c) (c) /* Data 1, Bits 0-1: Bank 17 color */ +# define SSD1305_SETBANK18(c) (c << 2) /* Data 1, Bits 2-3: Bank 18 color */ +# define SSD1305_SETBANK19(c) (c << 4) /* Data 1, Bits 4-5: Bank 19 color */ +# define SSD1305_SETBANK20(c) (c << 6) /* Data 1, Bits 6-7: Bank 20 color */ +# define SSD1305_SETBANK21(c) (c) /* Data 2, Bits 0-1: Bank 21 color */ +# define SSD1305_SETBANK22(c) (c << 2) /* Data 2, Bits 2-3: Bank 22 color */ +# define SSD1305_SETBANK23(c) (c << 4) /* Data 2, Bits 4-5: Bank 23 color */ +# define SSD1305_SETBANK24(c) (c << 6) /* Data 2, Bits 6-7: Bank 24 color */ +# define SSD1305_SETBANK25(c) (c) /* Data 3, Bits 0-1: Bank 25 color */ +# define SSD1305_SETBANK26(c) (c << 2) /* Data 3, Bits 2-3: Bank 26 color */ +# define SSD1305_SETBANK27(c) (c << 4) /* Data 3, Bits 4-5: Bank 27 color */ +# define SSD1305_SETBANK28(c) (c << 6) /* Data 3, Bits 6-7: Bank 28 color */ +# define SSD1305_SETBANK29(c) (c) /* Data 4, Bits 0-1: Bank 29 color */ +# define SSD1305_SETBANK30(c) (c << 2) /* Data 4, Bits 2-3: Bank 30 color */ +# define SSD1305_SETBANK31(c) (c << 4) /* Data 4, Bits 4-5: Bank 31 color */ +# define SSD1305_SETBANK32(c) (c << 6) /* Data 4, Bits 6-7: Bank 32 color */ +#define SSD1305_MAPCOL0 0xa0 /* 0xa0: Column address 0 is mapped to SEG0 */ +#define SSD1305_MAPCOL131 0xa1 /* 0xa1: Column address 131 is mapped to SEG0 */ +#define SSD1305_DISPRAM 0xa4 /* 0xa4: Resume to RAM content display */ +#define SSD1305_DISPENTIRE 0xa5 /* 0xa5: Entire display ON */ +#define SSD1305_DISPNORMAL 0xa6 /* 0xa6: Normal display */ +#define SSD1305_DISPINVERTED 0xa7 /* 0xa7: Inverse display */ + +#define SSD1305_SETMUX 0xa8 /* 0xa8: Set Multiplex Ratio*/ + /* Data 1: MUX ratio -1: 15-63 */ +#define SSD1305_DIMMODE 0xab /* 0xab: Dim mode setting */ + /* Data 1: Reserverd, must be zero */ + /* Data 2: Contrast for bank1: 0-255 */ + /* Data 3: Brightness for color bank: 0-255 */ +#define SSD1305_MSTRCONFIG 0xad /* 0xad: Master configuration */ +# define SSD1305_MSTRCONFIG_EXTVCC 0x8e /* Data 1: Select external Vcc */ +#define SSD1305_DISPONDIM 0xac /* 0xac: Display ON in dim mode */ +#define SSD1305_DISPOFF 0xae /* 0xae: Display OFF (sleep mode) */ +#define SSD1305_DISPON 0xaf /* 0xaf: Display ON in normal mode */ +#define SSD1305_SETPAGESTART 0xb0 /* 0xb0-b7: Set page start address */ +# define SSD1305_PAGESTART_MASK 0x07 +#define SSD1305_SETCOMNORMAL 0xc0 /* 0xc0: Set COM output, normal mode */ +#define SSD1305_SETCOMREMAPPED 0xc8 /* 0xc8: Set COM output, remapped mode */ + +#define SSD1305_SETOFFSET 0xd3 /* 0xd3: Set display offset */ + /* Data 1: Vertical shift by COM: 0-63 */ +#define SSD1305_SETDCLK 0xd5 /* 0xd5: Set display clock divide ratio/oscillator */ +# define SSD1305_DCLKDIV_SHIFT (0) /* Data 1, Bits 0-3: DCLK divide ratio/frequency*/ +# define SSD1305_DCLKDIV_MASK 0x0f +# define SSD1305_DCLKFREQ_SHIFT (4) /* Data 1, Bits 4-7: DCLK divide oscillator frequency */ +# define SSD1305_DCLKFREQ_MASK 0xf0 +#define SSD1305_SETCOLORMODE 0xd8 /* 0xd: Set area color and low power display modes */ +# define SSD1305_COLORMODE_MONO 0x00 /* Data 1, Bits 4-5: 00=monochrome */ +# define SSD1305_COLORMODE_COLOR 0x30 /* Data 1, Bits 4-5: 11=area color enable */ +# define SSD1305_POWERMODE_NORMAL 0x00 /* Data 1, Bits 0,2: 00=normal power mode */ +# define SSD1305_POWERMODE_LOW 0x05 /* Data 1, Bits 0,2: 11=low power display mode */ +#define SSD1305_SETPRECHARGE 0xd9 /* 0xd9: Set pre-charge period */ +# define SSD1305_PHASE1_SHIFT (0) /* Data 1, Bits 0-3: Phase 1 period of up to 15 DCLK clocks */ +# define SSD1305_PHASE1_MASK 0x0f +# define SSD1305_PHASE2_SHIFT (4) /* Data 1, Bits 4-7: Phase 2 period of up to 15 DCLK clocks */ +# define SSD1305_PHASE2_MASK 0xf0 +#define SSD1305_SETCOMCONFIG 0xda /* 0xda: Set COM configuration */ +# define SSD1305_COMCONFIG_SEQ 0x02 /* Data 1, Bit 4: 0=Sequential COM pin configuration */ +# define SSD1305_COMCONFIG_ALT 0x12 /* Data 1, Bit 4: 1=Alternative COM pin configuration */ +# define SSD1305_COMCONFIG_NOREMAP 0x02 /* Data 1, Bit 5: 0=Disable COM Left/Right remap */ +# define SSD1305_COMCONFIG_REMAP 0x22 /* Data 1, Bit 5: 1=Enable COM Left/Right remap */ +#define SSD1305_SETVCOMHDESEL 0xdb /* 0xdb: Set VCOMH delselect level */ +# define SSD1305_VCOMH_x4p3 0x00 /* Data 1: ~0.43 x Vcc */ +# define SSD1305_VCOMH_x7p7 0x34 /* Data 1: ~0.77 x Vcc */ +# define SSD1305_VCOMH_x8p3 0x3c /* Data 1: ~0.83 x Vcc */ +#define SSD1305_ENTER_RMWMODE 0xe0 /* 0xe0: Enter the Read Modify Write mode */ +#define SSD1305_NOP 0xe3 /* 0xe3: NOP Command for no operation */ +#define SSD1305_EXIT_RMWMODE 0xee /* 0xee: Leave the Read Modify Write mode */ + +/* Graphic Acceleration Commands ********************************************/ + +#define SSD1305_HSCROLL_RIGHT 0x26 /* 0x26: Right horizontal scroll */ +#define SSD1305_HSCROLL_LEFT 0x27 /* 0x27: Left horizontal scroll */ + /* Data 1, Bits 0-2: Column scroll offset: 0-4 */ + /* Data 2, Bits 0-2: Start page address: 0-7 */ +#define SSD1305_HSCROLL_FRAMES6 0x00 /* Data 3, Bits 0-2: Timer interval, 000=6 frames */ +#define SSD1305_HSCROLL_FRAMES32 0x01 /* Data 3, Bits 0-2: Timer interval, 001=32 frames */ +#define SSD1305_HSCROLL_FRAMES64 0x02 /* Data 3, Bits 0-2: Timer interval, 010=64 frames */ +#define SSD1305_HSCROLL_FRAMES128 0x03 /* Data 3, Bits 0-2: Timer interval, 011=128 frames */ +#define SSD1305_HSCROLL_FRAMES3 0x04 /* Data 3, Bits 0-2: Timer interval, 100=3 frames */ +#define SSD1305_HSCROLL_FRAMES4 0x05 /* Data 3, Bits 0-2: Timer interval, 101=4 frames */ +#define SSD1305_HSCROLL_FRAMES2 0x06 /* Data 3, Bits 0-2: Timer interval, 110=2 frames */ + /* Data 4, Bits 0-2: End page address: 0-7 */ + +#define SSD1305_VSCROLL_RIGHT 0x29 /* 0x26: Vertical and right horizontal scroll */ +#define SSD1305_VSCROLL_LEFT 0x2a /* 0x27: Vertical and left horizontal scroll */ + /* Data 1, Bits 0-2: Column scroll offset: 0-4 */ + /* Data 2, Bits 0-2: Start page address: 0-7 */ +#define SSD1305_VSCROLL_FRAMES6 0x00 /* Data 3, Bits 0-2: Timer interval, 000=6 frames */ +#define SSD1305_VSCROLL_FRAMES32 0x01 /* Data 3, Bits 0-2: Timer interval, 001=32 frames */ +#define SSD1305_VSCROLL_FRAMES64 0x02 /* Data 3, Bits 0-2: Timer interval, 010=64 frames */ +#define SSD1305_VSCROLL_FRAMES128 0x03 /* Data 3, Bits 0-2: Timer interval, 011=128 frames */ +#define SSD1305_VSCROLL_FRAMES3 0x04 /* Data 3, Bits 0-2: Timer interval, 100=3 frames */ +#define SSD1305_VSCROLL_FRAMES4 0x05 /* Data 3, Bits 0-2: Timer interval, 101=4 frames */ +#define SSD1305_VSCROLL_FRAMES2 0x06 /* Data 3, Bits 0-2: Timer interval, 110=2 frames */ + /* Data 4, Bits 0-2: End page address: 0-7 */ + /* Data 5, Bits 0-5: Vertical scrolling offset: 0-63 */ +#define SSD1305_SCROLL_STOP 0x2e /* 0x2e: Deactivate scroll */ +#define SSD1305_SCROLL_START 0x2f /* 0x2f: Activate scroll */ +#define SSD1305_VSCROLL_AREA 0xa3 /* 0xa3: Set vertical scroll area */ + /* Data 1: Number of rows in the top fixed area */ + /* Data 1: Number of rows in the scroll area */ + +/* Status register bit definitions ******************************************/ + +#define SSD1305_STATUS_DISPOFF (1 << 6) /* Bit 6: 1=Display off */ + +#endif /* __DRIVERS_LCD_SSD1305_H */ diff --git a/nuttx/drivers/lcd/ug-9664hswag01.c b/nuttx/drivers/lcd/ug-9664hswag01.c new file mode 100644 index 0000000000..bb49f20e6b --- /dev/null +++ b/nuttx/drivers/lcd/ug-9664hswag01.c @@ -0,0 +1,1049 @@ +/************************************************************************************** + * drivers/lcd/ug-9664hswag01.c + * Driver for the Univision UG-9664HSWAG01 Display with the Solomon Systech SSD1305 LCD + * controller. + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Reference: "Product Specification, OEL Display Module, UG-9664HSWAG01", Univision + * Technology Inc., SAS1-6020-B, January 3, 2008. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ssd1305.h" + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ + +/* Configuration **********************************************************************/ +/* UG-9664HSWAG01 Configuration Settings: + * + * CONFIG_UG9664HSWAG01_SPIMODE - Controls the SPI mode + * CONFIG_UG9664HSWAG01_FREQUENCY - Define to use a different bus frequency + * CONFIG_UG9664HSWAG01_NINTERFACES - Specifies the number of physical + * UG-9664HSWAG01 devices that will be supported. NOTE: At present, this + * must be undefined or defined to be 1. + * CONFIG_UG9664HSWAG01_POWER + * If the hardware supports a controllable OLED a power supply, this + * configuration shold be defined. (See ug_power() below). + * CONFIG_LCD_UGDEBUG - Enable detailed UG-9664HSWAG01 debug output + * (CONFIG_DEBUG and CONFIG_VERBOSE must also be enabled). + * + * Required LCD driver settings: + * CONFIG_LCD_UG9664HSWAG01 - Enable UG-9664HSWAG01 support + * CONFIG_LCD_MAXCONTRAST should be 255, but any value >0 and <=255 will be accepted. + * CONFIG_LCD_MAXPOWER should be 2: 0=off, 1=dim, 2=normal + * + * Required SPI driver settings: + * CONFIG_SPI_CMDDATA - Include support for cmd/data selection. + */ + +/* Verify that all configuration requirements have been met */ + +/* The UG-9664HSWAG01 spec says that is supports SPI mode 0,0 only. However, somtimes + * you need to tinker with these things. + */ + +#ifndef CONFIG_UG9664HSWAG01_SPIMODE +# define CONFIG_UG9664HSWAG01_SPIMODE SPIDEV_MODE0 +#endif + +/* SPI frequency */ + +#ifndef CONFIG_UG9664HSWAG01_FREQUENCY +# define CONFIG_UG9664HSWAG01_FREQUENCY 3500000 +#endif + +/* CONFIG_UG9664HSWAG01_NINTERFACES determines the number of physical interfaces + * that will be supported. + */ + +#ifndef CONFIG_UG9664HSWAG01_NINTERFACES +# define CONFIG_UG9664HSWAG01_NINTERFACES 1 +#endif + +#if CONFIG_UG9664HSWAG01_NINTERFACES != 1 +# warning "Only a single UG-9664HSWAG01 interface is supported" +# undef CONFIG_UG9664HSWAG01_NINTERFACES +# define CONFIG_UG9664HSWAG01_NINTERFACES 1 +#endif + +/* Verbose debug must also be enabled to use the extra OLED debug */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_GRAPHICS +#endif + +#ifndef CONFIG_DEBUG_VERBOSE +# undef CONFIG_LCD_UGDEBUG +#endif + +/* Check contrast selection */ + +#ifndef CONFIG_LCD_MAXCONTRAST +# define CONFIG_LCD_MAXCONTRAST 255 +#endif + +#if CONFIG_LCD_MAXCONTRAST <= 0 || CONFIG_LCD_MAXCONTRAST > 255 +# error "CONFIG_LCD_MAXCONTRAST exceeds supported maximum" +#endif + +#if CONFIG_LCD_MAXCONTRAST < 255 +# warning "Optimal setting of CONFIG_LCD_MAXCONTRAST is 255" +#endif + +/* Check power setting */ + +#if !defined(CONFIG_LCD_MAXPOWER) +# define CONFIG_LCD_MAXPOWER 2 +#endif + +#if CONFIG_LCD_MAXPOWER != 2 +# warning "CONFIG_LCD_MAXPOWER should be 2" +# undef CONFIG_LCD_MAXPOWER +# define CONFIG_LCD_MAXPOWER 2 +#endif + +/* The OLED requires CMD/DATA SPI support */ + +#ifndef CONFIG_SPI_CMDDATA +# error "CONFIG_SPI_CMDDATA must be defined in your NuttX configuration" +#endif + +/* Color is 1bpp monochrome with leftmost column contained in bits 0 */ + +#ifdef CONFIG_NX_DISABLE_1BPP +# warning "1 bit-per-pixel support needed" +#endif + +/* Color Properties *******************************************************************/ +/* The SSD1305 display controller can handle a resolution of 132x64. The OLED + * on the base board is 96x64. + */ + +#define UG_DEV_XRES 132 +#define UG_XOFFSET 18 + +/* Display Resolution */ + +#define UG_XRES 96 +#define UG_YRES 64 + +/* Color depth and format */ + +#define UG_BPP 1 +#define UG_COLORFMT FB_FMT_Y1 + +/* Bytes per logical row andactual device row */ + +#define UG_XSTRIDE (UG_XRES >> 3) /* Pixels arrange "horizontally for user" */ +#define UG_YSTRIDE (UG_YRES >> 3) /* But actual device arrangement is "vertical" */ + +/* The size of the shadow frame buffer */ + +#define UG_FBSIZE (UG_XRES * UG_YSTRIDE) + +/* Bit helpers */ + +#define LS_BIT (1 << 0) +#define MS_BIT (1 << 7) + +/* Debug ******************************************************************************/ + +#ifdef CONFIG_LCD_UGDEBUG +# define ugdbg(format, arg...) vdbg(format, ##arg) +#else +# define ugdbg(x...) +#endif + +/************************************************************************************** + * Private Type Definition + **************************************************************************************/ + +/* This structure describes the state of this driver */ + +struct ug_dev_s +{ + /* Publically visible device structure */ + + struct lcd_dev_s dev; + + /* Private LCD-specific information follows */ + + FAR struct spi_dev_s *spi; + uint8_t contrast; + uint8_t powered; + + /* The SSD1305 does not support reading from the display memory in SPI mode. + * Since there is 1 BPP and access is byte-by-byte, it is necessary to keep + * a shadow copy of the framebuffer memory. + */ + + uint8_t fb[UG_FBSIZE]; +}; + +/************************************************************************************** + * Private Function Protototypes + **************************************************************************************/ + +/* SPI helpers */ + +#ifdef CONFIG_SPI_OWNBUS +static inline void ug_select(FAR struct spi_dev_s *spi); +static inline void ug_deselect(FAR struct spi_dev_s *spi); +#else +static void ug_select(FAR struct spi_dev_s *spi); +static void ug_deselect(FAR struct spi_dev_s *spi); +#endif + +/* LCD Data Transfer Methods */ + +static int ug_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels); +static int ug_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels); + +/* LCD Configuration */ + +static int ug_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo); +static int ug_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo); + +/* LCD RGB Mapping */ + +#ifdef CONFIG_FB_CMAP +# error "RGB color mapping not supported by this driver" +#endif + +/* Cursor Controls */ + +#ifdef CONFIG_FB_HWCURSOR +# error "Cursor control not supported by this driver" +#endif + +/* LCD Specific Controls */ + +static int ug_getpower(struct lcd_dev_s *dev); +static int ug_setpower(struct lcd_dev_s *dev, int power); +static int ug_getcontrast(struct lcd_dev_s *dev); +static int ug_setcontrast(struct lcd_dev_s *dev, unsigned int contrast); + +/* Initialization */ + +static inline void up_clear(FAR struct ug_dev_s *priv); + +/************************************************************************************** + * Private Data + **************************************************************************************/ + +/* This is working memory allocated by the LCD driver for each LCD device + * and for each color plane. This memory will hold one raster line of data. + * The size of the allocated run buffer must therefore be at least + * (bpp * xres / 8). Actual alignment of the buffer must conform to the + * bitwidth of the underlying pixel type. + * + * If there are multiple planes, they may share the same working buffer + * because different planes will not be operate on concurrently. However, + * if there are multiple LCD devices, they must each have unique run buffers. + */ + +static uint8_t g_runbuffer[UG_XSTRIDE+1]; + +/* This structure describes the overall LCD video controller */ + +static const struct fb_videoinfo_s g_videoinfo = +{ + .fmt = UG_COLORFMT, /* Color format: RGB16-565: RRRR RGGG GGGB BBBB */ + .xres = UG_XRES, /* Horizontal resolution in pixel columns */ + .yres = UG_YRES, /* Vertical resolution in pixel rows */ + .nplanes = 1, /* Number of color planes supported */ +}; + +/* This is the standard, NuttX Plane information object */ + +static const struct lcd_planeinfo_s g_planeinfo = +{ + .putrun = ug_putrun, /* Put a run into LCD memory */ + .getrun = ug_getrun, /* Get a run from LCD memory */ + .buffer = (uint8_t*)g_runbuffer, /* Run scratch buffer */ + .bpp = UG_BPP, /* Bits-per-pixel */ +}; + +/* This is the standard, NuttX LCD driver object */ + +static struct ug_dev_s g_ugdev = +{ + .dev = + { + /* LCD Configuration */ + + .getvideoinfo = ug_getvideoinfo, + .getplaneinfo = ug_getplaneinfo, + + /* LCD RGB Mapping -- Not supported */ + /* Cursor Controls -- Not supported */ + + /* LCD Specific Controls */ + + .getpower = ug_getpower, + .setpower = ug_setpower, + .getcontrast = ug_getcontrast, + .setcontrast = ug_setcontrast, + }, +}; + +/************************************************************************************** + * Private Functions + **************************************************************************************/ + +/************************************************************************************** + * Name: ug_powerstring + * + * Description: + * Convert the power setting to a string. + * + **************************************************************************************/ + + +static inline FAR const char *ug_powerstring(uint8_t power) +{ + if (power == UG_POWER_OFF) + { + return "OFF"; + } + else if (power == UG_POWER_DIM) + { + return "DIM"; + } + else if (power == UG_POWER_ON) + { + return "ON"; + } + else + { + return "ERROR"; + } +} + +/************************************************************************************** + * Function: ug_select + * + * Description: + * Select the SPI, locking and re-configuring if necessary + * + * Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + **************************************************************************************/ + +#ifdef CONFIG_SPI_OWNBUS +static inline void ug_select(FAR struct spi_dev_s *spi) +{ + /* We own the SPI bus, so just select the chip */ + + SPI_SELECT(spi, SPIDEV_DISPLAY, true); +} +#else +static void ug_select(FAR struct spi_dev_s *spi) +{ + /* Select UG-9664HSWAG01 chip (locking the SPI bus in case there are multiple + * devices competing for the SPI bus + */ + + SPI_LOCK(spi, true); + SPI_SELECT(spi, SPIDEV_DISPLAY, true); + + /* Now make sure that the SPI bus is configured for the UG-9664HSWAG01 (it + * might have gotten configured for a different device while unlocked) + */ + + SPI_SETMODE(spi, CONFIG_UG9664HSWAG01_SPIMODE); + SPI_SETBITS(spi, 8); +#ifdef CONFIG_UG9664HSWAG01_FREQUENCY + SPI_SETFREQUENCY(spi, CONFIG_UG9664HSWAG01_FREQUENCY); +#endif +} +#endif + +/************************************************************************************** + * Function: ug_deselect + * + * Description: + * De-select the SPI + * + * Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + **************************************************************************************/ + +#ifdef CONFIG_SPI_OWNBUS +static inline void ug_deselect(FAR struct spi_dev_s *spi) +{ + /* We own the SPI bus, so just de-select the chip */ + + SPI_SELECT(spi, SPIDEV_DISPLAY, false); +} +#else +static void ug_deselect(FAR struct spi_dev_s *spi) +{ + /* De-select UG-9664HSWAG01 chip and relinquish the SPI bus. */ + + SPI_SELECT(spi, SPIDEV_DISPLAY, false); + SPI_LOCK(spi, false); +} +#endif + +/************************************************************************************** + * Name: ug_putrun + * + * Description: + * This method can be used to write a partial raster line to the LCD: + * + * row - Starting row to write to (range: 0 <= row < yres) + * col - Starting column to write to (range: 0 <= col <= xres-npixels) + * buffer - The buffer containing the run to be written to the LCD + * npixels - The number of pixels to write to the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +static int ug_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels) +{ + /* Because of this line of code, we will only be able to support a single UG device */ + + FAR struct ug_dev_s *priv = &g_ugdev; + FAR uint8_t *fbptr; + FAR uint8_t *ptr; + uint8_t devcol; + uint8_t fbmask; + uint8_t page; + uint8_t usrmask; + uint8_t i; + int pixlen; + + gvdbg("row: %d col: %d npixels: %d\n", row, col, npixels); + DEBUGASSERT(buffer); + + /* Clip the run to the display */ + + pixlen = npixels; + if ((unsigned int)col + (unsigned int)pixlen > (unsigned int)UG_XRES) + { + pixlen = (int)UG_XRES - (int)col; + } + + /* Verify that some portion of the run remains on the display */ + + if (pixlen <= 0 || row > UG_YRES) + { + return OK; + } + + /* Get the page number. The range of 64 lines is divided up into eight + * pages of 8 lines each. + */ + + page = row >> 3; + + /* Update the shadow frame buffer memory. First determine the pixel + * position in the frame buffer memory. Pixels are organized like + * this: + * + * --------+---+---+---+---+-...-+-----+ + * Segment | 0 | 1 | 2 | 3 | ... | 131 | + * --------+---+---+---+---+-...-+-----+ + * Bit 0 | | X | | | | | + * Bit 1 | | X | | | | | + * Bit 2 | | X | | | | | + * Bit 3 | | X | | | | | + * Bit 4 | | X | | | | | + * Bit 5 | | X | | | | | + * Bit 6 | | X | | | | | + * Bit 7 | | X | | | | | + * --------+---+---+---+---+-...-+-----+ + * + * So, in order to draw a white, horizontal line, at row 45. we + * would have to modify all of the bytes in page 45/8 = 5. We + * would have to set bit 45%8 = 5 in every byte in the page. + */ + + fbmask = 1 << (row & 7); + fbptr = &priv->fb[page * UG_XRES + col]; + ptr = fbptr; +#ifdef CONFIG_NX_PACKEDMSFIRST + usrmask = MS_BIT; +#else + usrmask = LS_BIT; +#endif + + for (i = 0; i < pixlen; i++) + { + /* Set or clear the corresponding bit */ + + if ((*buffer & usrmask) != 0) + { + *ptr++ |= fbmask; + } + else + { + *ptr++ &= ~fbmask; + } + + /* Inc/Decrement to the next source pixel */ + +#ifdef CONFIG_NX_PACKEDMSFIRST + if (usrmask == LS_BIT) + { + buffer++; + usrmask = MS_BIT; + } + else + { + usrmask >>= 1; + } +#else + if (usrmask == MS_BIT) + { + buffer++; + usrmask = LS_BIT; + } + else + { + usrmask <<= 1; + } +#endif + } + + /* Offset the column position to account for smaller horizontal + * display range. + */ + + devcol = col + UG_XOFFSET; + + /* Select and lock the device */ + + ug_select(priv->spi); + + /* Select command transfer */ + + SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY, true); + + /* Set the starting position for the run */ + + (void)SPI_SEND(priv->spi, SSD1305_SETPAGESTART+page); /* Set the page start */ + (void)SPI_SEND(priv->spi, SSD1305_SETCOLL + (devcol & 0x0f)); /* Set the low column */ + (void)SPI_SEND(priv->spi, SSD1305_SETCOLH + (devcol >> 4)); /* Set the high column */ + + /* Select data transfer */ + + SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY, false); + + /* Then transfer all of the data */ + + (void)SPI_SNDBLOCK(priv->spi, fbptr, pixlen); + + /* Unlock and de-select the device */ + + ug_deselect(priv->spi); + return OK; +} + +/************************************************************************************** + * Name: ug_getrun + * + * Description: + * This method can be used to read a partial raster line from the LCD: + * + * row - Starting row to read from (range: 0 <= row < yres) + * col - Starting column to read read (range: 0 <= col <= xres-npixels) + * buffer - The buffer in which to return the run read from the LCD + * npixels - The number of pixels to read from the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +static int ug_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels) +{ + /* Because of this line of code, we will only be able to support a single UG device */ + + FAR struct ug_dev_s *priv = &g_ugdev; + FAR uint8_t *fbptr; + uint8_t page; + uint8_t fbmask; + uint8_t usrmask; + uint8_t i; + int pixlen; + + gvdbg("row: %d col: %d npixels: %d\n", row, col, npixels); + DEBUGASSERT(buffer); + + /* Clip the run to the display */ + + pixlen = npixels; + if ((unsigned int)col + (unsigned int)pixlen > (unsigned int)UG_XRES) + { + pixlen = (int)UG_XRES - (int)col; + } + + /* Verify that some portion of the run is actually the display */ + + if (pixlen <= 0 || row > UG_YRES) + { + return -EINVAL; + } + + /* Then transfer the display data from the shadow frame buffer memory */ + /* Get the page number. The range of 64 lines is divided up into eight + * pages of 8 lines each. + */ + + page = row >> 3; + + /* Update the shadow frame buffer memory. First determine the pixel + * position in the frame buffer memory. Pixels are organized like + * this: + * + * --------+---+---+---+---+-...-+-----+ + * Segment | 0 | 1 | 2 | 3 | ... | 131 | + * --------+---+---+---+---+-...-+-----+ + * Bit 0 | | X | | | | | + * Bit 1 | | X | | | | | + * Bit 2 | | X | | | | | + * Bit 3 | | X | | | | | + * Bit 4 | | X | | | | | + * Bit 5 | | X | | | | | + * Bit 6 | | X | | | | | + * Bit 7 | | X | | | | | + * --------+---+---+---+---+-...-+-----+ + * + * So, in order to draw a white, horizontal line, at row 45. we + * would have to modify all of the bytes in page 45/8 = 5. We + * would have to set bit 45%8 = 5 in every byte in the page. + */ + + fbmask = 1 << (row & 7); + fbptr = &priv->fb[page * UG_XRES + col]; +#ifdef CONFIG_NX_PACKEDMSFIRST + usrmask = MS_BIT; +#else + usrmask = LS_BIT; +#endif + + *buffer = 0; + for (i = 0; i < pixlen; i++) + { + /* Set or clear the corresponding bit */ + + uint8_t byte = *fbptr++; + if ((byte & fbmask) != 0) + { + *buffer |= usrmask; + } + + /* Inc/Decrement to the next destination pixel. Hmmmm. It looks like + * this logic could write past the end of the user buffer. Revisit + * this! + */ + +#ifdef CONFIG_NX_PACKEDMSFIRST + if (usrmask == LS_BIT) + { + buffer++; + *buffer = 0; + usrmask = MS_BIT; + } + else + { + usrmask >>= 1; + } +#else + if (usrmask == MS_BIT) + { + buffer++; + *buffer = 0; + usrmask = LS_BIT; + } + else + { + usrmask <<= 1; + } +#endif + } + + return OK; +} + +/************************************************************************************** + * Name: ug_getvideoinfo + * + * Description: + * Get information about the LCD video controller configuration. + * + **************************************************************************************/ + +static int ug_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo) +{ + DEBUGASSERT(dev && vinfo); + gvdbg("fmt: %d xres: %d yres: %d nplanes: %d\n", + g_videoinfo.fmt, g_videoinfo.xres, g_videoinfo.yres, g_videoinfo.nplanes); + memcpy(vinfo, &g_videoinfo, sizeof(struct fb_videoinfo_s)); + return OK; +} + +/************************************************************************************** + * Name: ug_getplaneinfo + * + * Description: + * Get information about the configuration of each LCD color plane. + * + **************************************************************************************/ + +static int ug_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo) +{ + DEBUGASSERT(dev && pinfo && planeno == 0); + gvdbg("planeno: %d bpp: %d\n", planeno, g_planeinfo.bpp); + memcpy(pinfo, &g_planeinfo, sizeof(struct lcd_planeinfo_s)); + return OK; +} + +/************************************************************************************** + * Name: ug_getpower + * + * Description: + * Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int ug_getpower(struct lcd_dev_s *dev) +{ + struct ug_dev_s *priv = (struct ug_dev_s *)dev; + DEBUGASSERT(priv); + gvdbg("powered: %s\n", ug_powerstring(priv->powered)); + return priv->powered; +} + +/************************************************************************************** + * Name: ug_setpower + * + * Description: + * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int ug_setpower(struct lcd_dev_s *dev, int power) +{ + struct ug_dev_s *priv = (struct ug_dev_s *)dev; + + DEBUGASSERT(priv && (unsigned)power <= CONFIG_LCD_MAXPOWER); + gvdbg("power: %s powered: %s\n", + ug_powerstring(power), ug_powerstring(priv->powered)); + + /* Select and lock the device */ + + ug_select(priv->spi); + if (power <= UG_POWER_OFF) + { + /* Turn the display off */ + + (void)SPI_SEND(priv->spi, SSD1305_DISPOFF); /* Display off */ + + /* Remove power to the device */ + + ug_power(0, false); + priv->powered = UG_POWER_OFF; + } + else + { + /* Turn the display on, dim or normal */ + + if (power == UG_POWER_DIM) + { + (void)SPI_SEND(priv->spi, SSD1305_DISPONDIM); /* Display on, dim mode */ + } + else /* if (power > UG_POWER_DIM) */ + { + (void)SPI_SEND(priv->spi, SSD1305_DISPON); /* Display on, normal mode */ + power = UG_POWER_ON; + } + (void)SPI_SEND(priv->spi, SSD1305_DISPRAM); /* Resume to RAM content display */ + + /* Restore power to the device */ + + ug_power(0, true); + priv->powered = power; + } + ug_deselect(priv->spi); + + return OK; +} + +/************************************************************************************** + * Name: ug_getcontrast + * + * Description: + * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int ug_getcontrast(struct lcd_dev_s *dev) +{ + struct ug_dev_s *priv = (struct ug_dev_s *)dev; + DEBUGASSERT(priv); + return (int)priv->contrast; +} + +/************************************************************************************** + * Name: ug_setcontrast + * + * Description: + * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int ug_setcontrast(struct lcd_dev_s *dev, unsigned int contrast) +{ + struct ug_dev_s *priv = (struct ug_dev_s *)dev; + + gvdbg("contrast: %d\n", contrast); + DEBUGASSERT(priv); + + if (contrast > 255) + { + return -EINVAL; + } + + /* Select and lock the device */ + + ug_select(priv->spi); + + /* Select command transfer */ + + SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY, true); + + /* Set the contrast */ + + (void)SPI_SEND(priv->spi, SSD1305_SETCONTRAST); /* Set contrast control register */ + (void)SPI_SEND(priv->spi, contrast); /* Data 1: Set 1 of 256 contrast steps */ + priv->contrast = contrast; + + /* Unlock and de-select the device */ + + ug_deselect(priv->spi); + return OK; +} + +/************************************************************************************** + * Name: up_clear + * + * Description: + * Clear the display. + * + **************************************************************************************/ + +static inline void up_clear(FAR struct ug_dev_s *priv) +{ + FAR struct spi_dev_s *spi = priv->spi; + int page; + int i; + + /* Clear the framebuffer */ + + memset(priv->fb, UG_Y1_BLACK, UG_FBSIZE); + + /* Select and lock the device */ + + ug_select(priv->spi); + + /* Go through all 8 pages */ + + for (page = 0, i = 0; i < 8; i++) + { + /* Select command transfer */ + + SPI_CMDDATA(spi, SPIDEV_DISPLAY, true); + + /* Set the starting position for the run */ + + (void)SPI_SEND(priv->spi, SSD1305_SETPAGESTART+i); + (void)SPI_SEND(priv->spi, SSD1305_SETCOLL + (UG_XOFFSET & 0x0f)); + (void)SPI_SEND(priv->spi, SSD1305_SETCOLH + (UG_XOFFSET >> 4)); + + /* Select data transfer */ + + SPI_CMDDATA(spi, SPIDEV_DISPLAY, false); + + /* Then transfer all 96 columns of data */ + + (void)SPI_SNDBLOCK(priv->spi, &priv->fb[page * UG_XRES], UG_XRES); + } + + /* Unlock and de-select the device */ + + ug_deselect(spi); +} + +/************************************************************************************** + * Public Functions + **************************************************************************************/ + +/************************************************************************************** + * Name: ug_initialize + * + * Description: + * Initialize the UG-9664HSWAG01 video hardware. The initial state of the + * OLED is fully initialized, display memory cleared, and the OLED ready to + * use, but with the power setting at 0 (full off == sleep mode). + * + * Input Parameters: + * + * spi - A reference to the SPI driver instance. + * devno - A value in the range of 0 through CONFIG_UG9664HSWAG01_NINTERFACES-1. + * This allows support for multiple OLED devices. + * + * Returned Value: + * + * On success, this function returns a reference to the LCD object for the specified + * OLED. NULL is returned on any failure. + * + **************************************************************************************/ + +FAR struct lcd_dev_s *ug_initialize(FAR struct spi_dev_s *spi, unsigned int devno) +{ + /* Configure and enable LCD */ + + FAR struct ug_dev_s *priv = &g_ugdev; + + gvdbg("Initializing\n"); + DEBUGASSERT(spi && devno == 0); + + /* Save the reference to the SPI device */ + + priv->spi = spi; + + /* Select and lock the device */ + + ug_select(spi); + + /* Make sure that the OLED off */ + + ug_power(0, false); + + /* Select command transfer */ + + SPI_CMDDATA(spi, SPIDEV_DISPLAY, true); + + /* Set the starting position for the run */ + + (void)SPI_SEND(spi, SSD1305_SETCOLL + 2); /* Set low column address */ + (void)SPI_SEND(spi, SSD1305_SETCOLH + 2); /* Set high column address */ + (void)SPI_SEND(spi, SSD1305_SETSTARTLINE+0); /* Display start set */ + (void)SPI_SEND(spi, SSD1305_SCROLL_STOP); /* Stop horizontal scroll */ + (void)SPI_SEND(spi, SSD1305_SETCONTRAST); /* Set contrast control register */ + (void)SPI_SEND(spi, 0x32); /* Data 1: Set 1 of 256 contrast steps */ + (void)SPI_SEND(spi, SSD1305_SETBRIGHTNESS); /* Brightness for color bank */ + (void)SPI_SEND(spi, 0x80); /* Data 1: Set 1 of 256 contrast steps */ + (void)SPI_SEND(spi, SSD1305_MAPCOL131); /* Set segment re-map */ + (void)SPI_SEND(spi, SSD1305_DISPNORMAL); /* Set normal display */ +/*(void)SPI_SEND(spi, SSD1305_DISPINVERTED); Set inverse display */ + (void)SPI_SEND(spi, SSD1305_SETMUX); /* Set multiplex ratio */ + (void)SPI_SEND(spi, 0x3f); /* Data 1: MUX ratio -1: 15-63 */ + (void)SPI_SEND(spi, SSD1305_SETOFFSET); /* Set display offset */ + (void)SPI_SEND(spi, 0x40); /* Data 1: Vertical shift by COM: 0-63 */ + (void)SPI_SEND(spi, SSD1305_MSTRCONFIG); /* Set dc-dc on/off */ + (void)SPI_SEND(spi, SSD1305_MSTRCONFIG_EXTVCC); /* Data 1: Select external Vcc */ + (void)SPI_SEND(spi, SSD1305_SETCOMREMAPPED); /* Set com output scan direction */ + (void)SPI_SEND(spi, SSD1305_SETDCLK); /* Set display clock divide + * ratio/oscillator/frequency */ + (void)SPI_SEND(spi, 15 << SSD1305_DCLKFREQ_SHIFT | 0 << SSD1305_DCLKDIV_SHIFT); + (void)SPI_SEND(spi, SSD1305_SETCOLORMODE); /* Set area color mode on/off & low power + * display mode */ + (void)SPI_SEND(spi, SSD1305_COLORMODE_MONO | SSD1305_POWERMODE_LOW); + (void)SPI_SEND(spi, SSD1305_SETPRECHARGE); /* Set pre-charge period */ + (void)SPI_SEND(spi, 15 << SSD1305_PHASE2_SHIFT | 1 << SSD1305_PHASE1_SHIFT); + (void)SPI_SEND(spi, SSD1305_SETCOMCONFIG); /* Set COM configuration */ + (void)SPI_SEND(spi, SSD1305_COMCONFIG_ALT); /* Data 1, Bit 4: 1=Alternative COM pin configuration */ + (void)SPI_SEND(spi, SSD1305_SETVCOMHDESEL); /* Set VCOMH deselect level */ + (void)SPI_SEND(spi, SSD1305_VCOMH_x7p7); /* Data 1: ~0.77 x Vcc */ + (void)SPI_SEND(spi, SSD1305_SETLUT); /* Set look up table for area color */ + (void)SPI_SEND(spi, 0x3f); /* Data 1: Pulse width: 31-63 */ + (void)SPI_SEND(spi, 0x3f); /* Data 2: Color A: 31-63 */ + (void)SPI_SEND(spi, 0x3f); /* Data 3: Color B: 31-63 */ + (void)SPI_SEND(spi, 0x3f); /* Data 4: Color C: 31-63 */ + (void)SPI_SEND(spi, SSD1305_DISPON); /* Display on, normal mode */ + (void)SPI_SEND(spi, SSD1305_DISPRAM); /* Resume to RAM content display */ + + /* Let go of the SPI lock and de-select the device */ + + ug_deselect(spi); + + /* Clear the framebuffer */ + + up_mdelay(100); + up_clear(priv); + return &priv->dev; +} diff --git a/nuttx/drivers/loop.c b/nuttx/drivers/loop.c new file mode 100644 index 0000000000..df96da59fb --- /dev/null +++ b/nuttx/drivers/loop.c @@ -0,0 +1,509 @@ +/**************************************************************************** + * drivers/loop.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define loop_semgive(d) sem_post(&(d)->sem) /* To match loop_semtake */ +#define MAX_OPENCNT (255) /* Limit of uint8_t */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct loop_struct_s +{ + sem_t sem; /* For safe read-modify-write operations */ + uint32_t nsectors; /* Number of sectors on device */ + off_t offset; /* Offset (in bytes) to the first sector */ + uint16_t sectsize; /* The size of one sector */ + uint8_t opencnt; /* Count of open references to the loop device */ +#ifdef CONFIG_FS_WRITABLE + bool writeenabled; /* true: can write to device */ +#endif + int fd; /* Descriptor of char device/file */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void loop_semtake(FAR struct loop_struct_s *dev); +static int loop_open(FAR struct inode *inode); +static int loop_close(FAR struct inode *inode); +static ssize_t loop_read(FAR struct inode *inode, unsigned char *buffer, + size_t start_sector, unsigned int nsectors); +#ifdef CONFIG_FS_WRITABLE +static ssize_t loop_write(FAR struct inode *inode, const unsigned char *buffer, + size_t start_sector, unsigned int nsectors); +#endif +static int loop_geometry(FAR struct inode *inode, struct geometry *geometry); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct block_operations g_bops = +{ + loop_open, /* open */ + loop_close, /* close */ + loop_read, /* read */ +#ifdef CONFIG_FS_WRITABLE + loop_write, /* write */ +#else + NULL, /* write */ +#endif + loop_geometry, /* geometry */ + NULL /* ioctl */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: loop_semtake + ****************************************************************************/ + +static void loop_semtake(FAR struct loop_struct_s *dev) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&dev->sem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Name: loop_open + * + * Description: Open the block device + * + ****************************************************************************/ + +static int loop_open(FAR struct inode *inode) +{ + FAR struct loop_struct_s *dev; + int ret = OK; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct loop_struct_s *)inode->i_private; + + /* Make sure we have exclusive access to the state structure */ + + loop_semtake(dev); + if (dev->opencnt == MAX_OPENCNT) + { + return -EMFILE; + } + else + { + /* Increment the open count */ + + dev->opencnt++; + } + + loop_semgive(dev); + return ret; +} + +/**************************************************************************** + * Name: loop_close + * + * Description: close the block device + * + ****************************************************************************/ + +static int loop_close(FAR struct inode *inode) +{ + FAR struct loop_struct_s *dev; + int ret = OK; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct loop_struct_s *)inode->i_private; + + /* Make sure we have exclusive access to the state structure */ + + loop_semtake(dev); + if (dev->opencnt == 0) + { + return -EIO; + } + else + { + /* Decrement the open count */ + + dev->opencnt--; + } + + loop_semgive(dev); + return ret; +} + +/**************************************************************************** + * Name: loop_read + * + * Description: Read the specified numer of sectors + * + ****************************************************************************/ + +static ssize_t loop_read(FAR struct inode *inode, unsigned char *buffer, + size_t start_sector, unsigned int nsectors) +{ + FAR struct loop_struct_s *dev; + size_t nbytesread; + off_t offset; + int ret; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct loop_struct_s *)inode->i_private; + + if (start_sector + nsectors > dev->nsectors) + { + dbg("Read past end of file\n"); + return -EIO; + } + + /* Calculate the offset to read the sectors and seek to the position */ + + offset = start_sector * dev->sectsize + dev->offset; + ret = lseek(dev->fd, offset, SEEK_SET); + if (ret == (off_t)-1) + { + dbg("Seek failed for offset=%d: %d\n", (int)offset, errno); + return -EIO; + } + + /* Then read the requested number of sectors from that position */ + + do + { + nbytesread = read(dev->fd, buffer, nsectors * dev->sectsize); + if (nbytesread < 0 && errno != EINTR) + { + dbg("Read failed: %d\n", errno); + return -errno; + } + } + while (nbytesread < 0); + + /* Return the number of sectors read */ + + return nbytesread / dev->sectsize; +} + +/**************************************************************************** + * Name: loop_write + * + * Description: Write the specified number of sectors + * + ****************************************************************************/ + +#ifdef CONFIG_FS_WRITABLE +static ssize_t loop_write(FAR struct inode *inode, const unsigned char *buffer, + size_t start_sector, unsigned int nsectors) +{ + FAR struct loop_struct_s *dev; + size_t nbyteswritten; + off_t offset; + int ret; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct loop_struct_s *)inode->i_private; + + /* Calculate the offset to write the sectors and seek to the position */ + + offset = start_sector * dev->sectsize + dev->offset; + ret = lseek(dev->fd, offset, SEEK_SET); + if (ret == (off_t)-1) + { + dbg("Seek failed for offset=%d: %d\n", (int)offset, errno); + } + + /* Then write the requested number of sectors to that position */ + + do + { + nbyteswritten = write(dev->fd, buffer, nsectors * dev->sectsize); + if (nbyteswritten < 0 && errno != EINTR) + { + dbg("Write failed: %d\n", errno); + return -errno; + } + } + while (nbyteswritten < 0); + + /* Return the number of sectors written */ + + return nbyteswritten / dev->sectsize; +} +#endif + +/**************************************************************************** + * Name: loop_geometry + * + * Description: Return device geometry + * + ****************************************************************************/ + +static int loop_geometry(FAR struct inode *inode, struct geometry *geometry) +{ + FAR struct loop_struct_s *dev; + + DEBUGASSERT(inode); + if (geometry) + { + dev = (FAR struct loop_struct_s *)inode->i_private; + geometry->geo_available = true; + geometry->geo_mediachanged = false; +#ifdef CONFIG_FS_WRITABLE + geometry->geo_writeenabled = dev->writeenabled; +#else + geometry->geo_writeenabled = false; +#endif + geometry->geo_nsectors = dev->nsectors; + geometry->geo_sectorsize = dev->sectsize; + return OK; + } + + return -EINVAL; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: losetup + * + * Description: + * Setup the loop device so that it exports the file referenced by 'filename' + * as a block device. + * + ****************************************************************************/ + +int losetup(const char *devname, const char *filename, uint16_t sectsize, + off_t offset, bool readonly) +{ + FAR struct loop_struct_s *dev; + struct stat sb; + int ret; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (!devname || !filename || !sectsize) + { + return -EINVAL; + } +#endif + + /* Get the size of the file */ + + ret = stat(filename, &sb); + if (ret < 0) + { + dbg("Failed to stat %s: %d\n", filename, errno); + return -errno; + } + + /* Check if the file system is big enough for one block */ + + if (sb.st_size - offset < sectsize) + { + dbg("File is too small for blocksize\n"); + return -ERANGE; + } + + /* Allocate a loop device structure */ + + dev = (FAR struct loop_struct_s *)kzalloc(sizeof(struct loop_struct_s)); + if (!dev) + { + return -ENOMEM; + } + + /* Initialize the loop device structure. */ + + sem_init(&dev->sem, 0, 1); + dev->nsectors = (sb.st_size - offset) / sectsize; + dev->sectsize = sectsize; + dev->offset = offset; + + /* Open the file. */ + +#ifdef CONFIG_FS_WRITABLE + dev->writeenabled = false; /* Assume failure */ + dev->fd = -1; + + /* First try to open the device R/W access (unless we are asked + * to open it readonly). + */ + + if (!readonly) + { + dev->fd = open(filename, O_RDWR); + } + + if (dev->fd >= 0) + { + dev->writeenabled = true; /* Success */ + } + else +#endif + { + /* If that fails, then try to open the device read-only */ + + dev->fd = open(filename, O_RDWR); + if (dev->fd < 0) + { + dbg("Failed to open %s: %d\n", filename, errno); + ret = -errno; + goto errout_with_dev; + } + } + + /* Inode private data will be reference to the loop device structure */ + + ret = register_blockdriver(devname, &g_bops, 0, dev); + if (ret < 0) + { + fdbg("register_blockdriver failed: %d\n", -ret); + goto errout_with_fd; + } + + return OK; + +errout_with_fd: + close(dev->fd); +errout_with_dev: + kfree(dev); + return ret; +} + +/**************************************************************************** + * Name: loteardown + * + * Description: + * Undo the setup performed by losetup + * + ****************************************************************************/ + +int loteardown(const char *devname) +{ + FAR struct loop_struct_s *dev; + FAR struct inode *inode; + int ret; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (!devname) + { + return -EINVAL; + } +#endif + + /* Open the block driver associated with devname so that we can get the inode + * reference. + */ + + ret = open_blockdriver(devname, MS_RDONLY, &inode); + if (ret < 0) + { + dbg("Failed to open %s: %d\n", devname, -ret); + return ret; + } + + /* Inode private data is a reference to the loop device stgructure */ + + dev = (FAR struct loop_struct_s *)inode->i_private; + close_blockdriver(inode); + + DEBUGASSERT(dev); + + /* Are there still open references to the device */ + + if (dev->opencnt > 0) + { + return -EBUSY; + } + + /* Otherwise, unregister the block device */ + + ret = unregister_blockdriver(devname); + + /* Release the device structure */ + + if (dev->fd >= 0) + { + (void)close(dev->fd); + } + + kfree(dev); + return ret; +} diff --git a/nuttx/drivers/mmcsd/Kconfig b/nuttx/drivers/mmcsd/Kconfig new file mode 100644 index 0000000000..fc682e7068 --- /dev/null +++ b/nuttx/drivers/mmcsd/Kconfig @@ -0,0 +1,77 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# +config MMCSD_NSLOTS + int "Number of MMC/SD slots" + default 1 + ---help--- + Number of MMC/SD slots supported by the + driver. Default is one. + +config MMCSD_READONLY + bool "Disable MMC/SD write access" + default n + ---help--- + Provide read-only access. Default is + Read/Write + +config MMCSD_MULTIBLOCK_DISABLE + bool "Disable MMC/SD multiblock transfer" + default n + ---help--- + Use only the single block transfer method. + This setting is used to work around buggy SDIO drivers that cannot handle + multiple block transfers. + +config MMCSD_MMCSUPPORT + bool "MMC cards support" + default y + ---help--- + Enable support for MMC cards + +config MMCSD_HAVECARDDETECT + bool "MMC/SD card detection" + default y + ---help--- + SDIO driver card detection is + 100% accurate + +config MMCSD_SPI + bool "MMC/SD spi transfer support" + default y + +config MMCSD_SPICLOCK + int "MMC/SD maximum SPI clock" + default 20000000 + depends on MMCSD_SPI + ---help--- + Maximum SPI clock to drive MMC/SD card. + Default is 20MHz. + +config MMCSD_SDIO + bool "MMC/SD sdio transfer support" + default y + +if MMCSD_SDIO +config SDIO_DMA + bool "SDIO dma support" + default n + ---help--- + SDIO driver supports DMA + +config SDIO_MUXBUS + bool "SDIO bus share support" + default n + ---help--- + Set this SDIO interface if the SDIO interface + or hardware resources are shared with other drivers. + +config SDIO_WIDTH_D1_ONLY + bool "SDIO 1-bit transfer" + default n + ---help--- + Select 1-bit transfer mode. Default: + 4-bit transfer mode. +endif + diff --git a/nuttx/drivers/mmcsd/Make.defs b/nuttx/drivers/mmcsd/Make.defs new file mode 100644 index 0000000000..48e5d4fb6e --- /dev/null +++ b/nuttx/drivers/mmcsd/Make.defs @@ -0,0 +1,46 @@ +############################################################################ +# drivers/mmcsd/Make.defs +# +# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Include MMC/SD drivers + +CSRCS += mmcsd_sdio.c mmcsd_spi.c mmcsd_debug.c + +# Include MMC/SD driver build support + +DEPPATH += --dep-path mmcsd +VPATH += :mmcsd +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/mmcsd} + + diff --git a/nuttx/drivers/mmcsd/mmcsd_csd.h b/nuttx/drivers/mmcsd/mmcsd_csd.h new file mode 100644 index 0000000000..e35eacad5b --- /dev/null +++ b/nuttx/drivers/mmcsd/mmcsd_csd.h @@ -0,0 +1,424 @@ +/**************************************************************************** + * drivers/mmcsd/mmcsd_csd.h + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_MMCSD_MMCSD_CSD_H +#define __DRIVERS_MMCSD_MMCSD_CSD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* CSD **********************************************************************/ + +/* The CSD is a 16 byte, / 128-bit packed structure. The following macros + * can be used to extract each packed field from the CSD. Two types of + * macros are supported, selected by CONFIG_MMCSD_BE16: (1) byte data (with + * MS byte first), or (2) 16-bit big-endian data (with MS hword first). + */ + +#ifdef CONFIG_MMCSD_BE16 + +/* CSD_STRUCTURE 126-127 */ + +#define MMCSD_CSD_CSDSTRUCT(csd) (csd[0] >> 14) + +/* SPEC_VERS 122-125 = (word 0, bits 13:10) (MMC) Spec version */ + +#define MMC_CSD_SPECVERS(csd) ((csd[0] >> 10) & 0x0f) + +/* Reserved 120-125 */ + +/* TAAC 112-119 = Data read access-time-1 + * TIME_VALUE 3-6 = Time mantissa + * TIME_UNIT 0-2 = Time exponent + */ + +#define MMCSD_CSD_TAAC_TIMEVALUE(csd) ((csd[0] >> 3) & 0x0f) +#define MMCSD_CSD_TAAC_TIMEUNIT(csd) (csd[0] & 7) + +/* NSAC 111:104 = Data read access-time-2 in CLK cycle(NSAC*100) */ + +#define MMCSD_CSD_NSAC(csd) (csd[1] >> 8) + +/* TRAN_SPEED 96-103 = Max. data transfer rate + * TIME_VALUE 3-6 = Rate exponent + * TRANSFER_RATE_UNIT 0-2 = Rate mantissa + */ + +#define MMCSD_CSD_TRANSPEED_TIMEVALUE(csd) ((csd[1] >> 3) & 0x0f) +#define MMCSD_CSD_TRANSPEED_TRANSFERRATEUNIT(csd) (csd[1] & 7) + +/* CCC 84-95 = Card command classes */ + +#define MMCSD_CSD_CCC(csd) ((csd[2] >> 4) & 0x0fff) + + /* READ_BL_LEN 80-83 = Max. read data block length */ + +#define MMCSD_CSD_READBLLEN(csd) (csd[2] & 0x0f) + +/* READ_BL_PARTIAL 79-79 = Partial blocks for read allowed */ + +#define MMCSD_CSD_READBLPARTIAL(csd) (csd[3] >> 15) + +/* WRITE_BLK_MISALIGN 78-78 = Write block misalignment */ + +#define MMCSD_CSD_WRITEBLKMISALIN(csd) ((csd[3] >> 14) & 1) + +/* READ_BLK_MISALIGN 77:77 = Read block misalignment */ + +#define MMCSD_CSD_READBLKMISALIN(csd) ((csd[3] >> 13) & 1) + +/* DSR_IMP 76-76 = DSR implemented */ + +#define MMCSD_CSD_DSRIMP(csd) ((csd[3] >> 12) & 1) + +/* C_SIZE 62-73 Device size */ + +#define MMCSD_CSD_CSIZE(csd) (((csd[3] & 0x03ff) << 2) | ((csd[4] >> 14) & 3)) + +/* VDD_R_CURR_MIN 59-61 = Max. read current at Vcc min */ + +#define MMCSD_CSD_VDDRCURRMIN(csd) ((csd[4] >> 11) & 7) + +/* VDD_R_CURR_MAX 56-58 = Max. read current at Vcc max */ + +#define MMCSD_CSD_VDDRCURRMAX(csd) ((csd[4] >> 8) & 7) + +/* VDD_W_CURR_MIN 53-55 = Max. write current at Vcc min */ + +#define MMCSD_CSD_VDDWCURRMIN(csd) ((csd[4] >> 5) & 7) + +/* VDD_W_CURR_MAX 50-52 = Max. write current at Vcc max */ + +#define MMCSD_CSD_VDDWCURRMAX(csd) ((csd[4] >> 2) & 7) + +/* C_SIZE_MULT 47-49 Device size multiplier */ + +#define MMCSD_CSD_CSIZEMULT(csd) (((csd[4] & 3) << 1) | (csd[5] >> 15)) + +/* ER_BLK_EN 46-46 =Erase single block enable (SD) */ + +#define SD_CSD_SDERBLKEN(csd) ((csd[5] >> 14) & 1) + +/* SECTOR_SIZE 39-45 = Erase sector size (SD) */ + +#define SD_CSD_SECTORSIZE(csd) ((csd[5] >> 7) & 0x7f) + +/* SECTOR_SIZE 42-46 = Erase sector size (MMC) */ + +#define MMC_CSD_SECTORSIZE(csd) ((csd[5] >> 10) & 0x1f) + +/* ER_GRP_SIZE 37-41 = Erase group size (MMC)*/ + +#define MMC_CSD_ERGRPSIZE(csd) ((csd[5] >> 5) & 0x1f) + +/* WP_GRP_SIZE 32-38 = Write protect group size (SD) */ + +#define SD_CSD_WPGRPSIZE(csd) (csd[5] & 0x7f) + +/* WP_GRP_SIZE 32-36 = Write protect group size (MMC) */ + +#define MMC_CSD_WPGRPSIZE(csd) (csd[5] & 0x1f) + +/* WP_GRP_EN 31-31 = Write protect group enable */ + +#define MMCSD_WPGRPEN(csd) (csd[6] >> 15) + +/* DFLT_ECC 29-30 = Manufacturer default ECC (MMC) */ + +#define MMC_CSD_DFLTECC(csd) ((csd[6] >> 13) & 3) + +/* R2W_FACTOR 26-28 = Write speed factor */ + +#define MMCSD_CSD_R2WFACTOR(csd) ((csd[6] >> 10) & 7) + +/* WRITE_BL_LEN 22-25 = Max. write data block length */ + +#define MMCSD_CSD_WRITEBLLEN(csd) ((csd[6] >> 6) & 0x0f) + +/* WRITE_BL_PARTIAL 21-21 = Partial blocks for write allowed */ + +#define MMCSD_CSD_WRITEBLPARTIAL(csd) ((csd[6] >> 5) & 1) + +/* Reserved 16-20 */ + +/* FILE_FORMAT_GROUP 15-15 = File format group */ + +#define MMCSD_CSD_FILEFORMATGRP(csd) (csd[7] >> 15) + +/* COPY 14-14 = Copy flag (OTP) */ + +#define MMCSD_CSD_COPY(csd) ((csd[7] >> 14) & 1) + +/* PERM_WRITE_PROTECT 13-13 = Permanent write protection */ + +#define MMCSD_CSD_PERMWRITEPROTECT(csd) ((csd[7] >> 13) & 1) + +/* TMP_WRITE_PROTECT 12-12 = Temporary write protection */ + +#define MMCSD_CSD_TMPWRITEPROTECT(csd) ((csd[7] >> 12) & 1) + +/* FILE_FORMAT 10-11 = File format */ + +#define MMCSD_CSD_FILEFORMAT(csd) ((csd[7] >> 10) & 3) + +/* ECC 8-9 = ECC (MMC) */ + +#define MMC_CSD_ECC(csd) ((csd[7] >> 8) & 3) + +/* CRC 1-7 = CRC */ + +#define MMCSD_CSD_CRC(csd) ((csd[7] >> 1) & 0x7f) + +/* Reserved 0-0 */ + +#else /* CONFIG_MMCSD_BE16 */ + +/* CSD_STRUCTURE 126-127 */ + +#define MMCSD_CSD_CSDSTRUCT(csd) (csd[0] >> 6) + +/* SPEC_VERS 122-125 = (word 0, bits 13:10) (MMC) Spec version */ + +#define MMC_CSD_SPECVERS(csd) ((csd[0] >> 2) & 0x0f) + +/* Reserved 120-155 */ + +/* TAAC 112-119 = Data read access-time-1 + * TIME_VALUE 3-6 = Time mantissa + * TIME_UNIT 0-2 = Time exponent + */ + +#define MMCSD_CSD_TAAC_TIMEVALUE(csd) ((csd[1] >> 3) & 0x0f) +#define MMCSD_CSD_TAAC_TIMEUNIT(csd) (csd[1] & 7) + +#define SD20_CSD_TAC_TIMEVALUE(csd) (1) +#define SD20_CSD_TAC_TIMEUNIT(csd) (6) + +/* NSAC 111:104 = Data read access-time-2 in CLK cycle(NSAC*100) */ + +#define MMCSD_CSD_NSAC(csd) (csd[2]) +#define SD20_CSD_NSAC(csd) (0) + +/* TRAN_SPEED 96-103 = Max. data transfer rate + * TIME_VALUE 3-6 = Rate exponent + * TRANSFER_RATE_UNIT 0-2 = Rate mantissa + */ + +#define MMCSD_CSD_TRANSPEED_TIMEVALUE(csd) ((csd[3] >> 3) & 0x0f) +#define MMCSD_CSD_TRANSPEED_TRANSFERRATEUNIT(csd) (csd[3] & 7) + +#define SD20_CSD_TRANSPEED_TIMEVALUE(csd) MMCSD_CSD_TRANSPEED_TIMEVALUE(csd) +#define SD20_CSD_TRANSPEED_TRANSFERRATEUNIT(csd) MMCSD_CSD_TRANSPEED_TRANSFERRATEUNIT(csd) + +/* CCC 84-95 = Card command classes */ + +#define MMCSD_CSD_CCC(csd) (((uint16_t)csd[4] << 4) | ((uint16_t)csd[5] >> 4)) +#define SD20_CSD_CCC(csd) MMCSD_CSD_CCC(csd) + + /* READ_BL_LEN 80-83 = Max. read data block length */ + +#define MMCSD_CSD_READBLLEN(csd) (csd[5] & 0x0f) +#define SD20_CSD_READBLLEN(csd) (9) + +/* READ_BL_PARTIAL 79-79 = Partial blocks for read allowed */ + +#define MMCSD_CSD_READBLPARTIAL(csd) (csd[6] >> 7) +#define SD20_CSD_READBLPARTIAL(csd) (0) + +/* WRITE_BLK_MISALIGN 78-78 = Write block misalignment */ + +#define MMCSD_CSD_WRITEBLKMISALIGN(csd) ((csd[6] >> 6) & 1) +#define SD20_CSD_WRITEBLKMISALIGN(csd) (0) + +/* READ_BLK_MISALIGN 77:77 = Read block misalignment */ + +#define MMCSD_CSD_READBLKMISALIGN(csd) ((csd[6] >> 5) & 1) +#define SD20_CSD_READBLKMISALIGN(csd) (0) + +/* DSR_IMP 76-76 = DSR implemented */ + +#define MMCSD_CSD_DSRIMP(csd) ((csd[6] >> 4) & 1) +#define SD20_CSD_DSRIMP(csd) MMCSD_CSD_DSRIMP(csd) + +/* C_SIZE 62-73 Device size */ + +#define MMCSD_CSD_CSIZE(csd) (((csd[6] & 3) << 10) | (csd[7] << 2) | (csd[8] >> 6)) +#define SD20_CSD_CSIZE(csd) ((((uint32_t)csd[7] & 0x3f) << 16) | (csd[8] << 8) | csd[9]) + +/* VDD_R_CURR_MIN 59-61 = Max. read current at Vcc min */ + +#define MMCSD_CSD_VDDRCURRMIN(csd) ((csd[8] >> 3) & 7) +#define SD20_CSD_VDDRCURRMIN(csd) (7) + +/* VDD_R_CURR_MAX 56-58 = Max. read current at Vcc max */ + +#define MMCSD_CSD_VDDRCURRMAX(csd) (csd[8] & 7) +#define SD20_CSD_VDDRCURRMAX(csd) (6) + +/* VDD_W_CURR_MIN 53-55 = Max. write current at Vcc min */ + +#define MMCSD_CSD_VDDWCURRMIN(csd) ((csd[9] >> 5) & 7) +#define SD20_CSD_VDDWCURRMIN(csd) (7) + +/* VDD_W_CURR_MAX 50-52 = Max. write current at Vcc max */ + +#define MMCSD_CSD_VDDWCURRMAX(csd) ((csd[9] >> 2) & 7) +#define SD20_CSD_VDDWCURRMAX(csd) (6) + +/* C_SIZE_MULT 47-49 Device size multiplier */ + +#define MMCSD_CSD_CSIZEMULT(csd) (((csd[9] & 3) << 1) | (csd[10] >> 7)) +#define SD20_CSD_CSIZEMULT(csd) (10-2) + +/* ER_BLK_EN 46-46 = Erase single block enable (SD) */ + +#define SD_CSD_SDERBLKEN(csd) ((csd[10] >> 6) & 1) +#define SD20_CSD_SDERBLKEN(csd) (1) + +/* SECTOR_SIZE 39-45 = Erase sector size (SD) */ + +#define SD_CSD_SECTORSIZE(csd) (((csd[10] & 0x3f) << 1) | (csd[11] >> 7)) +#define SD20_CSD_SECTORSIZE(csd) (0x7f) + +/* SECTOR_SIZE 42-46 = Erase sector size (MMC) */ + +#define MMC_CSD_SECTORSIZE(csd) ((csd[10] >> 2) & 0x1f) + +/* ER_GRP_SIZE 37-41 = Erase group size (MMC)*/ + +#define MMC_CSD_ERGRPSIZE(csd) (((csd[10] & 3) << 3) | (csd[11] > 5)) + +/* WP_GRP_SIZE 32-38 = Write protect group size (SD) */ + +#define SD_CSD_WPGRPSIZE(csd) (csd[11] & 0x7f) +#define SD20_CSD_WPGRPSIZE(csd) (0) + +/* WP_GRP_SIZE 32-36 = Write protect group size (MMC) */ + +#define MMC_CSD_WPGRPSIZE(csd) (csd[11] & 0x1f) + +/* WP_GRP_EN 31-31 = Write protect group enable */ + +#define MMCSD_WPGRPEN(csd) (csd[12] >> 7) +#define SD20_WPGRPEN(csd) (0) + +/* DFLT_ECC 29-30 = Manufacturer default ECC (MMC) */ + +#define MMC_CSD_DFLTECC(csd) ((csd[12] >> 5) & 3) + +/* R2W_FACTOR 26-28 = Write speed factor */ + +#define MMCSD_CSD_R2WFACTOR(csd) ((csd[12] >> 2) & 7) +#define SD20_CSD_R2WFACTOR(csd) (2) + +/* WRITE_BL_LEN 22-25 = Max. write data block length */ + +#define MMCSD_CSD_WRITEBLLEN(csd) (((csd[12] & 3) << 2) | (csd[13] >> 6)) +#define SD20_CSD_WRITEBLLEN(csd) (9) + +/* WRITE_BL_PARTIAL 21-21 = Partial blocks for write allowed */ + +#define MMCSD_CSD_WRITEBLPARTIAL(csd) ((csd[13] >> 5) & 1) +#define SD20_CSD_WRITEBLPARTIAL(csd) (0) + +/* Reserved 16-20 */ + +/* FILE_FORMAT_GROUP 15-15 = File format group */ + +#define MMCSD_CSD_FILEFORMATGRP(csd) (csd[14] >> 7) +#define SD20_CSD_FILEFORMATGRP(csd) (0) + +/* COPY 14-14 = Copy flag (OTP) */ + +#define MMCSD_CSD_COPY(csd) ((csd[14] >> 6) & 1) +#define SD20_CSD_COPY(csd) MMCSD_CSD_COPY(csd) + +/* PERM_WRITE_PROTECT 13-13 = Permanent write protection */ + +#define MMCSD_CSD_PERMWRITEPROTECT(csd) ((csd[14] >> 5) & 1) +#define SD20_CSD_PERMWRITEPROTECT(csd) MMCSD_CSD_PERMWRITEPROTECT(csd) + +/* TMP_WRITE_PROTECT 12-12 = Temporary write protection */ + +#define MMCSD_CSD_TMPWRITEPROTECT(csd) ((csd[14] >> 4) & 1) +#define SD20_CSD_TMPWRITEPROTECT(csd) MMCSD_CSD_TMPWRITEPROTECT(csd) + +/* FILE_FORMAT 10-11 = File format */ + +#define MMCSD_CSD_FILEFORMAT(csd) ((csd[14] >> 2) & 3) +#define SD20_CSD_FILEFORMAT(csd) (0) + +/* ECC 8-9 = ECC (MMC) */ + +#define MMC_CSD_ECC(csd) (csd[14] & 3) + +/* CRC 1-7 = CRC */ + +#define MMCSD_CSD_CRC(csd) (csd[15] >> 1) +#define SD20_CSD_CRC(csd) MMCSD_CSD_CRC(csd) + +/* Reserved 0-0 */ + +#endif /* CONFIG_MMCSD_BE16 */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __DRIVERS_MMCSD_MMCSD_CSD_H */ diff --git a/nuttx/drivers/mmcsd/mmcsd_debug.c b/nuttx/drivers/mmcsd/mmcsd_debug.c new file mode 100644 index 0000000000..03872f5cf9 --- /dev/null +++ b/nuttx/drivers/mmcsd/mmcsd_debug.c @@ -0,0 +1,183 @@ +/**************************************************************************** + * drivers/mmcsd/mmcsd_debug.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "mmcsd_csd.h" +#include "mmcsd_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* This needs to match the logic in include/debug.h */ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# define message(format, arg...) lib_rawprintf(format, ##arg) +#else +# define message lib_rawprintf +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mmcsd_dmpcsd + * + * Description: + * Dump the contents of the CSD + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) +void mmcsd_dmpcsd(FAR const uint8_t *csd, uint8_t cardtype) +{ + bool mmc = (cardtype == MMCSD_CARDTYPE_MMC); + bool sd2 = (MMCSD_CSD_CSDSTRUCT(csd) == 1); + + fvdbg("CSD\n"); + fvdbg(" CSD_STRUCTURE: 1.%d\n", MMCSD_CSD_CSDSTRUCT(csd)); + if (mmc) + { + fvdbg(" MMC SPEC_VERS: %d\n", MMC_CSD_SPECVERS(csd)); + } + fvdbg(" TAAC:\n", + sd2 ? SD20_CSD_TAC_TIMEVALUE(csd) : MMCSD_CSD_TAAC_TIMEVALUE(csd)); + fvdbg(" TIME_VALUE: 0x%02x\n", + sd2 ? SD20_CSD_TAC_TIMEVALUE(csd) : MMCSD_CSD_TAAC_TIMEVALUE(csd)); + fvdbg(" TIME_UNIT: 0x%02x\n", + sd2 ? SD20_CSD_TAC_TIMEUNIT(csd) : MMCSD_CSD_TAAC_TIMEUNIT(csd)); + fvdbg(" NSAC: 0x%02x\n", + sd2 ? SD20_CSD_NSAC(csd) : MMCSD_CSD_NSAC(csd)); + fvdbg(" TRAN_SPEED:\n"); + fvdbg(" TIME_VALUE: 0x%02x\n", + sd2 ? SD20_CSD_TRANSPEED_TIMEVALUE(csd) : MMCSD_CSD_TRANSPEED_TIMEVALUE(csd)); + fvdbg(" RATE_UNIT: 0x%02x\n", + sd2 ? SD20_CSD_TRANSPEED_TRANSFERRATEUNIT(csd) : MMCSD_CSD_TRANSPEED_TRANSFERRATEUNIT(csd)); + fvdbg(" CCC: 0x%03x\n", + sd2 ? SD20_CSD_CCC(csd) : MMCSD_CSD_CCC(csd)); + fvdbg(" READ_BL_LEN: %d\n", + sd2 ? SD20_CSD_READBLLEN(csd) : MMCSD_CSD_READBLLEN(csd)); + fvdbg(" READ_BL_PARTIAL: %d\n", + sd2 ? SD20_CSD_READBLPARTIAL(csd) : MMCSD_CSD_READBLPARTIAL(csd)); + fvdbg(" WRITE_BLK_MISALIGN: %d\n", + sd2 ? SD20_CSD_WRITEBLKMISALIGN(csd) : MMCSD_CSD_WRITEBLKMISALIGN(csd)); + fvdbg(" READ_BLK_MISALIGN: %d\n", + sd2 ? SD20_CSD_READBLKMISALIGN(csd) : MMCSD_CSD_READBLKMISALIGN(csd)); + fvdbg(" DSR_IMP: %d\n", + sd2 ? SD20_CSD_DSRIMP(csd) : MMCSD_CSD_DSRIMP(csd)); + fvdbg(" C_SIZE: %d\n", + sd2 ? SD20_CSD_CSIZE(csd) : MMCSD_CSD_CSIZE(csd)); + fvdbg(" VDD_R_CURR_MIN: %d\n", + sd2 ? SD20_CSD_VDDRCURRMIN(csd) : MMCSD_CSD_VDDRCURRMIN(csd)); + fvdbg(" VDD_R_CURR_MAX: %d\n", + sd2 ? SD20_CSD_VDDRCURRMAX(csd) : MMCSD_CSD_VDDRCURRMAX(csd)); + fvdbg(" VDD_W_CURR_MIN: %d\n", + sd2 ? SD20_CSD_VDDWCURRMIN(csd) : MMCSD_CSD_VDDWCURRMIN(csd)); + fvdbg(" VDD_W_CURR_MAX: %d\n", + sd2 ? SD20_CSD_VDDWCURRMAX(csd) : MMCSD_CSD_VDDWCURRMAX(csd)); + fvdbg(" C_SIZE_MULT: %d\n", + sd2 ? SD20_CSD_CSIZEMULT(csd) : MMCSD_CSD_CSIZEMULT(csd)); + if (mmc) + { + fvdbg(" MMC SECTOR_SIZE: %d\n", MMC_CSD_SECTORSIZE(csd)); + fvdbg(" MMC ER_GRP_SIZE: %d\n", MMC_CSD_ERGRPSIZE(csd)); + fvdbg(" MMC WP_GRP_SIZE: %d\n", MMC_CSD_WPGRPSIZE(csd)); + fvdbg(" MMC DFLT_ECC: %d\n", MMC_CSD_DFLTECC(csd)); + } + else + { + fvdbg(" SD ER_BLK_EN: %d\n", + sd2 ? SD20_CSD_SDERBLKEN(csd) : SD_CSD_SDERBLKEN(csd)); + fvdbg(" SD SECTOR_SIZE: %d\n", + sd2 ? SD20_CSD_SECTORSIZE(csd) : SD_CSD_SECTORSIZE(csd)); + fvdbg(" SD WP_GRP_SIZE: %d\n", + sd2 ? SD_CSD_WPGRPSIZE(csd) : SD_CSD_WPGRPSIZE(csd)); + } + fvdbg(" WP_GRP_EN: %d\n", + sd2 ? SD20_WPGRPEN(csd) : MMCSD_WPGRPEN(csd)); + fvdbg(" R2W_FACTOR: %d\n", + sd2 ? SD20_CSD_R2WFACTOR(csd) : MMCSD_CSD_R2WFACTOR(csd)); + fvdbg(" WRITE_BL_LEN: %d\n", + sd2 ? SD20_CSD_WRITEBLLEN(csd) : MMCSD_CSD_WRITEBLLEN(csd)); + fvdbg(" WRITE_BL_PARTIAL: %d\n", + sd2 ? SD20_CSD_WRITEBLPARTIAL(csd) : MMCSD_CSD_WRITEBLPARTIAL(csd)); + fvdbg(" FILE_FORMAT_GROUP: %d\n", + sd2 ? SD20_CSD_FILEFORMATGRP(csd) : MMCSD_CSD_FILEFORMATGRP(csd)); + fvdbg(" COPY: %d\n", + sd2 ? SD20_CSD_COPY(csd) : MMCSD_CSD_COPY(csd)); + fvdbg(" PERM_WRITE_PROTECT: %d\n", + sd2 ? SD20_CSD_PERMWRITEPROTECT(csd) : MMCSD_CSD_PERMWRITEPROTECT(csd)); + fvdbg(" TMP_WRITE_PROTECT: %d\n", + sd2 ?SD20_CSD_TMPWRITEPROTECT(csd) : MMCSD_CSD_TMPWRITEPROTECT(csd)); + fvdbg(" FILE_FORMAT: %d\n", + sd2 ? SD20_CSD_FILEFORMAT(csd) : MMCSD_CSD_FILEFORMAT(csd)); + if (mmc) + { + fvdbg(" MMC ECC: %d\n", + sd2 ? MMC_CSD_ECC(csd) : MMC_CSD_ECC(csd)); + } + fvdbg(" CRC: %02x\n", + sd2 ? SD20_CSD_CRC(csd) : MMCSD_CSD_CRC(csd)); +} +#endif diff --git a/nuttx/drivers/mmcsd/mmcsd_internal.h b/nuttx/drivers/mmcsd/mmcsd_internal.h new file mode 100644 index 0000000000..577ebbba93 --- /dev/null +++ b/nuttx/drivers/mmcsd/mmcsd_internal.h @@ -0,0 +1,105 @@ +/**************************************************************************** + * drivers/mmcsd/mmcsd_internal.h + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_MMCSD_MMCSD_INTERNAL_H +#define __DRIVERS_MMCSD_MMCSD_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Enable excessive debug options */ + +#undef CONFIG_MMCSD_DUMPALL /* MUST BE DEFINED MANUALLY */ + +#if !defined(CONFIG_DEBUG_VERBOSE) || !defined(CONFIG_DEBUG_FS) +# undef CONFIG_MMCSD_DUMPALL +#endif + +/* Card type */ + +#define MMCSD_CARDTYPE_UNKNOWN 0 /* Unknown card type */ +#define MMCSD_CARDTYPE_MMC 1 /* Bit 0: MMC card */ +#define MMCSD_CARDTYPE_SDV1 2 /* Bit 1: SD version 1.x */ +#define MMCSD_CARDTYPE_SDV2 4 /* Bit 2: SD version 2.x with byte addressing */ +#define MMCSD_CARDTYPE_BLOCK 8 /* Bit 3: SD version 2.x with block addressing */ + +#define IS_MMC(t) (((t) & MMCSD_CARDTYPE_MMC) != 0) +#define IS_SD(t) (((t) & (MMCSD_CARDTYPE_SDV1|MMCSD_CARDTYPE_SDV2)) != 0) +#define IS_SDV1(t) (((t) & MMCSD_CARDTYPE_SDV1) != 0) +#define IS_SDV2(t) (((t) & MMCSD_CARDTYPE_SDV2) != 0) +#define IS_BLOCK(t) (((t) & MMCSD_CARDTYPE_BLOCK) != 0) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#ifdef CONFIG_MMCSD_DUMPALL +# define mmcsd_dumpbuffer(m,b,l) fvdbgdumpbuffer(m,b,l) +#else +# define mmcsd_dumpbuffer(m,b,l) +#endif + +#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) +EXTERN void mmcsd_dmpcsd(FAR const uint8_t *csd, uint8_t cardtype); +#else +# define mmcsd_dmpcsd(csd,cadtype) +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __DRIVERS_MMCSD_MMCSD_INTERNAL_H */ diff --git a/nuttx/drivers/mmcsd/mmcsd_sdio.c b/nuttx/drivers/mmcsd/mmcsd_sdio.c new file mode 100644 index 0000000000..90c73261a2 --- /dev/null +++ b/nuttx/drivers/mmcsd/mmcsd_sdio.c @@ -0,0 +1,3178 @@ +/**************************************************************************** + * drivers/mmcsd/mmcsd_sdio.c + * + * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mmcsd_internal.h" +#include "mmcsd_sdio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The maximum number of references on the driver (because a uint8_t is used. + * Use a larger type if more references are needed. + */ + +#define MAX_CREFS 0xff + +/* Timing (all in units of microseconds) */ + +#define MMCSD_POWERUP_DELAY ((useconds_t)250) /* 74 clock cycles @ 400KHz = 185uS */ +#define MMCSD_IDLE_DELAY ((useconds_t)50000) /* Short delay to allow change to IDLE state */ +#define MMCSD_DSR_DELAY ((useconds_t)100000) /* Time to wait after setting DSR */ +#define MMCSD_CLK_DELAY ((useconds_t)500000) /* Delay after changing clock speeds */ + +/* Data delays (all in units of milliseconds). + * + * For MMC & SD V1.x, these should be based on Nac = TAAC + NSAC; The maximum + * value of TAAC is 80MS and the maximum value of NSAC is 25.5K clock cycle. + * For SD V2.x, a fixed delay of 100MS is recommend which is pretty close to + * the worst case SD V1.x Nac. Here we just use 100MS delay for all data + * transfers. + */ + +#define MMCSD_SCR_DATADELAY (100) /* Wait up to 100MS to get SCR */ +#define MMCSD_BLOCK_DATADELAY (100) /* Wait up to 100MS to get one data block */ + +#define IS_EMPTY(priv) (priv->type == MMCSD_CARDTYPE_UNKNOWN) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure is contains the unique state of the MMC/SD block driver */ + +struct mmcsd_state_s +{ + FAR struct sdio_dev_s *dev; /* The SDIO device bound to this instance */ + uint8_t crefs; /* Open references on the driver */ + sem_t sem; /* Assures mutually exclusive access to the slot */ + + /* Status flags */ + + uint8_t probed:1; /* true: mmcsd_probe() discovered a card */ + uint8_t widebus:1; /* true: Wide 4-bit bus selected */ + uint8_t mediachanged:1; /* true: Media changed since last check */ + uint8_t wrbusy:1; /* true: Last transfer was a write, card may be busy */ + uint8_t wrprotect:1; /* true: Card is write protected (from CSD) */ + uint8_t locked:1; /* true: Media is locked (from R1) */ + uint8_t dsrimp:1; /* true: card supports CMD4/DSR setting (from CSD) */ +#ifdef CONFIG_SDIO_DMA + uint8_t dma:1; /* true: hardware supports DMA */ +#endif + + uint8_t mode:2; /* (See MMCSDMODE_* definitions) */ + uint8_t type:4; /* Card type (See MMCSD_CARDTYPE_* definitions) */ + uint8_t buswidth:4; /* Bus widthes supported (SD only) */ + uint16_t selblocklen; /* The currently selected block length */ + uint16_t rca; /* Relative Card Address (RCS) register */ + + /* Memory card geometry (extracted from the CSD) */ + + uint8_t blockshift; /* Log2 of blocksize */ + uint16_t blocksize; /* Read block length (== block size) */ + uint32_t nblocks; /* Number of blocks */ + +#ifdef CONFIG_HAVE_LONG_LONG + uint64_t capacity; /* Total capacity of volume */ +#else + uint32_t capacity; /* Total capacity of volume (Limited to 4Gb) */ +#endif + /* Read-ahead and write buffering support */ + +#if defined(CONFIG_FS_WRITEBUFFER) || defined(CONFIG_FS_READAHEAD) + struct rwbuffer_s rwbuffer; +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Misc Helpers *************************************************************/ + +static void mmcsd_takesem(FAR struct mmcsd_state_s *priv); + +#ifndef CONFIG_SDIO_MUXBUS +# define mmcsd_givesem(p) sem_post(&priv->sem); +#endif + +/* Command/response helpers *************************************************/ + +static int mmcsd_sendcmdpoll(FAR struct mmcsd_state_s *priv, + uint32_t cmd, uint32_t arg); +static int mmcsd_recvR1(FAR struct mmcsd_state_s *priv, uint32_t cmd); +static int mmcsd_recvR6(FAR struct mmcsd_state_s *priv, uint32_t cmd); +static int mmcsd_getSCR(FAR struct mmcsd_state_s *priv, uint32_t scr[2]); + +static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, + uint32_t csd[4]); +#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) +static void mmcsd_decodeCID(FAR struct mmcsd_state_s *priv, + uint32_t cid[4]); +#else +# define mmcsd_decodeCID(priv,cid) +#endif +static void mmcsd_decodeSCR(FAR struct mmcsd_state_s *priv, + uint32_t scr[2]); + +static int mmcsd_getR1(FAR struct mmcsd_state_s *priv, FAR uint32_t *r1); +static int mmcsd_verifystate(FAR struct mmcsd_state_s *priv, + uint32_t status); + +/* Transfer helpers *********************************************************/ + +#ifdef CONFIG_FS_WRITABLE +static bool mmcsd_wrprotected(FAR struct mmcsd_state_s *priv); +#endif +static int mmcsd_eventwait(FAR struct mmcsd_state_s *priv, + sdio_eventset_t failevents, uint32_t timeout); +static int mmcsd_transferready(FAR struct mmcsd_state_s *priv); +#ifndef CONFIG_MMCSD_MULTIBLOCK_DISABLE +static int mmcsd_stoptransmission(FAR struct mmcsd_state_s *priv); +#endif +static int mmcsd_setblocklen(FAR struct mmcsd_state_s *priv, + uint32_t blocklen); +static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv, + FAR uint8_t *buffer, off_t startblock); +#ifndef CONFIG_MMCSD_MULTIBLOCK_DISABLE +static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv, + FAR uint8_t *buffer, off_t startblock, size_t nblocks); +#endif +#ifdef CONFIG_FS_READAHEAD +static ssize_t mmcsd_reload(FAR void *dev, FAR uint8_t *buffer, + off_t startblock, size_t nblocks); +#endif +#ifdef CONFIG_FS_WRITABLE +static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv, + FAR const uint8_t *buffer, off_t startblock); +#ifndef CONFIG_MMCSD_MULTIBLOCK_DISABLE +static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, + FAR const uint8_t *buffer, off_t startblock, size_t nblocks); +#endif +#ifdef CONFIG_FS_WRITEBUFFER +static ssize_t mmcsd_flush(FAR void *dev, FAR const uint8_t *buffer, + off_t startblock, size_t nblocks); +#endif +#endif + +/* Block driver methods *****************************************************/ + +static int mmcsd_open(FAR struct inode *inode); +static int mmcsd_close(FAR struct inode *inode); +static ssize_t mmcsd_read(FAR struct inode *inode, FAR unsigned char *buffer, + size_t startsector, unsigned int nsectors); +#ifdef CONFIG_FS_WRITABLE +static ssize_t mmcsd_write(FAR struct inode *inode, + FAR const unsigned char *buffer, size_t startsector, + unsigned int nsectors); +#endif +static int mmcsd_geometry(FAR struct inode *inode, + FAR struct geometry *geometry); +static int mmcsd_ioctl(FAR struct inode *inode, int cmd, + unsigned long arg); + +/* Initialization/uninitialization/reset ************************************/ + +static void mmcsd_mediachange(FAR void *arg); +static int mmcsd_widebus(FAR struct mmcsd_state_s *priv); +#ifdef CONFIG_MMCSD_MMCSUPPORT +static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv); +#endif +static int mmcsd_sdinitialize(FAR struct mmcsd_state_s *priv); +static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv); +static int mmcsd_probe(FAR struct mmcsd_state_s *priv); +static int mmcsd_removed(FAR struct mmcsd_state_s *priv); +static int mmcsd_hwinitialize(FAR struct mmcsd_state_s *priv); +static void mmcsd_hwuninitialize(FAR struct mmcsd_state_s *priv); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct block_operations g_bops = +{ + mmcsd_open, /* open */ + mmcsd_close, /* close */ + mmcsd_read, /* read */ +#ifdef CONFIG_FS_WRITABLE + mmcsd_write, /* write */ +#else + NULL, /* write */ +#endif + mmcsd_geometry, /* geometry */ + mmcsd_ioctl /* ioctl */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Misc Helpers + ****************************************************************************/ + +static void mmcsd_takesem(FAR struct mmcsd_state_s *priv) +{ + /* Take the semaphore, giving exclusive access to the driver (perhaps + * waiting) + */ + + while (sem_wait(&priv->sem) != 0) + { + /* The only case that an error should occur here is if the wait was + * awakened by a signal. + */ + + ASSERT(errno == EINTR); + } + + /* Lock the bus if mutually exclusive access to the SDIO bus is required + * on this platform. + */ + +#ifdef CONFIG_SDIO_MUXBUS + SDIO_LOCK(priv->dev, TRUE); +#endif +} + +#ifdef CONFIG_SDIO_MUXBUS +static void mmcsd_givesem(FAR struct mmcsd_state_s *priv) +{ + /* Release the SDIO bus lock, then the MMC/SD driver semaphore in the + * opposite order that they were taken to assure that no deadlock + * conditions will arise. + */ + + SDIO_LOCK(priv->dev, FALSE); + sem_post(&priv->sem); +} +#endif + +/**************************************************************************** + * Command/Response Helpers + ****************************************************************************/ + +/**************************************************************************** + * Name: mmcsd_sendcmdpoll + * + * Description: + * Send a command and poll-wait for the response. + * + ****************************************************************************/ + +static int mmcsd_sendcmdpoll(FAR struct mmcsd_state_s *priv, uint32_t cmd, + uint32_t arg) +{ + int ret; + + /* Send the command */ + + ret = SDIO_SENDCMD(priv->dev, cmd, arg); + if (ret == OK) + { + /* Then poll-wait until the response is available */ + + ret = SDIO_WAITRESPONSE(priv->dev, cmd); + if (ret != OK) + { + fdbg("ERROR: Wait for response to cmd: %08x failed: %d\n", cmd, ret); + } + } + return ret; +} + +/**************************************************************************** + * Name: mmcsd_sendcmd4 + * + * Description: + * Set the Driver Stage Register (DSR) if (1) a CONFIG_MMCSD_DSR has been + * provided and (2) the card supports a DSR register. If no DSR value + * the card default value (0x0404) will be used. + * + ****************************************************************************/ + +static inline int mmcsd_sendcmd4(FAR struct mmcsd_state_s *priv) +{ + int ret = OK; + +#ifdef CONFIG_MMCSD_DSR + /* The dsr_imp bit from the CSD will tell us if the card supports setting + * the DSR via CMD4 or not. + */ + + if (priv->dsrimp != false) + { + /* CMD4 = SET_DSR will set the cards DSR register. The DSR and CMD4 + * support are optional. However, since this is a broadcast command + * with no response (like CMD0), we will never know if the DSR was + * set correctly or not + */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD4, CONFIG_MMCSD_DSR << 16); + up_udelay(MMCSD_DSR_DELAY); + + /* Send it again to have more confidence */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD4, CONFIG_MMCSD_DSR << 16); + up_udelay(MMCSD_DSR_DELAY); + } +#endif + return ret; +} + +/**************************************************************************** + * Name: mmcsd_recvR1 + * + * Description: + * Receive R1 response and check for errors. + * + ****************************************************************************/ + +static int mmcsd_recvR1(FAR struct mmcsd_state_s *priv, uint32_t cmd) +{ + uint32_t r1; + int ret; + + /* Get the R1 response from the hardware */ + + ret = SDIO_RECVR1(priv->dev, cmd, &r1); + if (ret == OK) + { + /* Check if R1 reports an error */ + + if ((r1 & MMCSD_R1_ERRORMASK) != 0) + { + /* Card locked is considered an error. Save the card locked + * indication for later use. + */ + + fvdbg("ERROR: R1=%08x\n", r1); + priv->locked = ((r1 & MMCSD_R1_CARDISLOCKED) != 0); + ret = -EIO; + } + } + return ret; +} + +/**************************************************************************** + * Name: mmcsd_recvR6 + * + * Description: + * Receive R6 response and check for errors. On success, priv->rca is set + * to the received RCA + * + ****************************************************************************/ + +static int mmcsd_recvR6(FAR struct mmcsd_state_s *priv, uint32_t cmd) +{ + uint32_t r6 = 0; + int ret; + + /* R6 Published RCA Response (48-bit, SD card only) + * 47 0 Start bit + * 46 0 Transmission bit (0=from card) + * 45:40 bit5 - bit0 Command index (0-63) + * 39:8 bit31 - bit0 32-bit Argument Field, consisting of: + * [31:16] New published RCA of card + * [15:0] Card status bits {23,22,19,12:0} + * 7:1 bit6 - bit0 CRC7 + * 0 1 End bit + * + * Get the R1 response from the hardware + */ + + ret = SDIO_RECVR6(priv->dev, cmd, &r6); + if (ret == OK) + { + /* Check if R6 reports an error */ + + if ((r6 & MMCSD_R6_ERRORMASK) == 0) + { + /* No, save the RCA and return success */ + + priv->rca = (uint16_t)(r6 >> 16); + return OK; + } + + /* Otherwise, return an I/O failure */ + + ret = -EIO; + } + + fdbg("ERROR: Failed to get RCA. R6=%08x: %d\n", r6, ret); + return ret; +} + +/**************************************************************************** + * Name: mmcsd_getSCR + * + * Description: + * Obtain the SD card's Configuration Register (SCR) + * + * Returned Value: + * OK on success; a negated ernno on failure. + * + ****************************************************************************/ + +static int mmcsd_getSCR(FAR struct mmcsd_state_s *priv, uint32_t scr[2]) +{ + int ret; + + /* Set Block Size To 8 Bytes */ + + ret = mmcsd_setblocklen(priv, 8); + if (ret != OK) + { + fdbg("ERROR: mmcsd_setblocklen failed: %d\n", ret); + return ret; + } + + /* Send CMD55 APP_CMD with argument as card's RCA */ + + mmcsd_sendcmdpoll(priv, SD_CMD55, (uint32_t)priv->rca << 16); + ret = mmcsd_recvR1(priv, SD_CMD55); + if (ret != OK) + { + fdbg("ERROR: RECVR1 for CMD55 failed: %d\n", ret); + return ret; + } + + /* Setup up to receive data with interrupt mode */ + + SDIO_BLOCKSETUP(priv->dev, 8, 1); + SDIO_RECVSETUP(priv->dev, (FAR uint8_t*)scr, 8); + + /* Send ACMD51 SD_APP_SEND_SCR with argument as 0 to start data receipt */ + + (void)SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR); + mmcsd_sendcmdpoll(priv, SD_ACMD51, 0); + ret = mmcsd_recvR1(priv, SD_ACMD51); + if (ret != OK) + { + fdbg("ERROR: RECVR1 for ACMD51 failed: %d\n", ret); + SDIO_CANCEL(priv->dev); + return ret; + } + + /* Wait for data to be transferred */ + + ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR, MMCSD_SCR_DATADELAY); + if (ret != OK) + { + fdbg("ERROR: mmcsd_eventwait for READ DATA failed: %d\n", ret); + } + return ret; +} + +/**************************************************************************** + * Name: mmcsd_decodeCSD + * + * Description: + * Decode and extract necessary information from the CSD. If debug is + * enabled, then decode and show the full contents of the CSD. + * + * Returned Value: + * OK on success; a negated ernno on failure. On success, the following + * values will be set in the driver state structure: + * + * priv->dsrimp true: card supports CMD4/DSR setting (from CSD) + * priv->wrprotect true: card is write protected (from CSD) + * priv->blocksize Read block length (== block size) + * priv->nblocks Number of blocks + * priv->capacity Total capacity of volume + * + ****************************************************************************/ + +static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, uint32_t csd[4]) +{ +#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) + struct mmcsd_csd_s decoded; +#endif + unsigned int readbllen; + bool permwriteprotect; + bool tmpwriteprotect; + + /* Word 1: Bits 127-96: + * + * CSD_STRUCTURE 127:126 CSD structure + * SPEC_VERS 125:122 (MMC) Spec version + * TAAC 119:112 Data read access-time-1 + * TIME_VALUE 6:3 Time mantissa + * TIME_UNIT 2:0 Time exponent + * NSAC 111:104 Data read access-time-2 in CLK cycle(NSAC*100) + * TRAN_SPEED 103:96 Max. data transfer rate + * TIME_VALUE 6:3 Rate exponent + * TRANSFER_RATE_UNIT 2:0 Rate mantissa + */ + +#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) + memset(&decoded, 0, sizeof(struct mmcsd_csd_s)); + decoded.csdstructure = csd[0] >> 30; + decoded.mmcspecvers = (csd[0] >> 26) & 0x0f; + decoded.taac.timevalue = (csd[0] >> 19) & 0x0f; + decoded.taac.timeunit = (csd[0] >> 16) & 7; + decoded.nsac = (csd[0] >> 8) & 0xff; + decoded.transpeed.timevalue = (csd[0] >> 3) & 0x0f; + decoded.transpeed.transferrateunit = csd[0] & 7; +#endif + + /* Word 2: Bits 64:95 + * CCC 95:84 Card command classes + * READ_BL_LEN 83:80 Max. read data block length + * READ_BL_PARTIAL 79:79 Partial blocks for read allowed + * WRITE_BLK_MISALIGN 78:78 Write block misalignment + * READ_BLK_MISALIGN 77:77 Read block misalignment + * DSR_IMP 76:76 DSR implemented + * Byte addressed SD and MMC: + * C_SIZE 73:62 Device size + * Block addressed SD: + * 75:70 (reserved) + * C_SIZE 48:69 Device size + */ + + priv->dsrimp = (csd[1] >> 12) & 1; + readbllen = (csd[1] >> 16) & 0x0f; + +#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) + decoded.ccc = (csd[1] >> 20) & 0x0fff; + decoded.readbllen = (csd[1] >> 16) & 0x0f; + decoded.readblpartial = (csd[1] >> 15) & 1; + decoded.writeblkmisalign = (csd[1] >> 14) & 1; + decoded.readblkmisalign = (csd[1] >> 13) & 1; + decoded.dsrimp = priv->dsrimp; +#endif + + /* Word 3: Bits 32-63 + * + * Byte addressed SD: + * C_SIZE 73:62 Device size + * VDD_R_CURR_MIN 61:59 Max. read current at Vcc min + * VDD_R_CURR_MAX 58:56 Max. read current at Vcc max + * VDD_W_CURR_MIN 55:53 Max. write current at Vcc min + * VDD_W_CURR_MAX 52:50 Max. write current at Vcc max + * C_SIZE_MULT 49:47 Device size multiplier + * SD_ER_BLK_EN 46:46 Erase single block enable (SD only) + * SD_SECTOR_SIZE 45:39 Erase sector size + * SD_WP_GRP_SIZE 38:32 Write protect group size + * Block addressed SD: + * 75:70 (reserved) + * C_SIZE 48:69 Device size + * 47:47 (reserved) + * SD_ER_BLK_EN 46:46 Erase single block enable (SD only) + * SD_SECTOR_SIZE 45:39 Erase sector size + * SD_WP_GRP_SIZE 38:32 Write protect group size + * MMC: + * C_SIZE 73:62 Device size + * VDD_R_CURR_MIN 61:59 Max. read current at Vcc min + * VDD_R_CURR_MAX 58:56 Max. read current at Vcc max + * VDD_W_CURR_MIN 55:53 Max. write current at Vcc min + * VDD_W_CURR_MAX 52:50 Max. write current at Vcc max + * C_SIZE_MULT 49:47 Device size multiplier + * MMC_SECTOR_SIZE 46:42 Erase sector size + * MMC_ER_GRP_SIZE 41:37 Erase group size (MMC) + * MMC_WP_GRP_SIZE 36:32 Write protect group size + */ + + if (IS_BLOCK(priv->type)) + { + /* Block addressed SD: + * + * C_SIZE: 69:64 from Word 2 and 63:48 from Word 3 + * + * 512 = (1 << 9) + * 1024 = (1 << 10) + * 512*1024 = (1 << 19) + */ + + uint32_t csize = ((csd[1] & 0x3f) << 16) | (csd[2] >> 16); +#ifdef CONFIG_HAVE_LONG_LONG + priv->capacity = ((uint64_t)(csize + 1)) << 19; +#else + priv->capacity = (csize + 1) << 19; +#endif + priv->blockshift = 9; + priv->blocksize = 1 << 9; + priv->nblocks = priv->capacity >> 9; + +#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) + decoded.u.sdblock.csize = csize; + decoded.u.sdblock.sderblen = (csd[2] >> 14) & 1; + decoded.u.sdblock.sdsectorsize = (csd[2] >> 7) & 0x7f; + decoded.u.sdblock.sdwpgrpsize = csd[2] & 0x7f; +#endif + } + else + { + /* Byte addressed SD: + * + * C_SIZE: 73:64 from Word 2 and 63:62 from Word 3 + */ + + uint16_t csize = ((csd[1] & 0x03ff) << 2) | ((csd[2] >> 30) & 3); + uint8_t csizemult = (csd[2] >> 15) & 7; + + priv->nblocks = ((uint32_t)csize + 1) * (1 << (csizemult + 2)); + priv->blockshift = readbllen; + priv->blocksize = (1 << readbllen); + priv->capacity = (priv->nblocks << readbllen); + + /* Some devices, such as 2Gb devices, report blocksizes larger than 512 bytes + * but still expect to be accessed with a 512 byte blocksize. + * + * NOTE: A minor optimization would be to eliminated priv->blocksize and + * priv->blockshift: Those values will be 512 and 9 in all cases anyway. + */ + + if (priv->blocksize > 512) + { + priv->nblocks <<= (priv->blockshift - 9); + priv->blocksize = 512; + priv->blockshift = 9; + } + +#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) + if (IS_SD(priv->type)) + { + decoded.u.sdbyte.csize = csize; + decoded.u.sdbyte.vddrcurrmin = (csd[2] >> 27) & 7; + decoded.u.sdbyte.vddrcurrmax = (csd[2] >> 24) & 7; + decoded.u.sdbyte.vddwcurrmin = (csd[2] >> 21) & 7; + decoded.u.sdbyte.vddwcurrmax = (csd[2] >> 18) & 7; + decoded.u.sdbyte.csizemult = csizemult; + decoded.u.sdbyte.sderblen = (csd[2] >> 14) & 1; + decoded.u.sdbyte.sdsectorsize = (csd[2] >> 7) & 0x7f; + decoded.u.sdbyte.sdwpgrpsize = csd[2] & 0x7f; + } +#ifdef CONFIG_MMCSD_MMCSUPPORT + else if (IS_MMC(priv->type)) + { + decoded.u.mmc.csize = csize; + decoded.u.mmc.vddrcurrmin = (csd[2] >> 27) & 7; + decoded.u.mmc.vddrcurrmax = (csd[2] >> 24) & 7; + decoded.u.mmc.vddwcurrmin = (csd[2] >> 21) & 7; + decoded.u.mmc.vddwcurrmax = (csd[2] >> 18) & 7; + decoded.u.mmc.csizemult = csizemult; + decoded.u.mmc.er.mmc22.sectorsize = (csd[2] >> 10) & 0x1f; + decoded.u.mmc.er.mmc22.ergrpsize = (csd[2] >> 5) & 0x1f; + decoded.u.mmc.mmcwpgrpsize = csd[2] & 0x1f; + } +#endif +#endif + } + + /* Word 4: Bits 0-31 + * WP_GRP_EN 31:31 Write protect group enable + * MMC DFLT_ECC 30:29 Manufacturer default ECC (MMC only) + * R2W_FACTOR 28:26 Write speed factor + * WRITE_BL_LEN 25:22 Max. write data block length + * WRITE_BL_PARTIAL 21:21 Partial blocks for write allowed + * FILE_FORMAT_GROUP 15:15 File format group + * COPY 14:14 Copy flag (OTP) + * PERM_WRITE_PROTECT 13:13 Permanent write protection + * TMP_WRITE_PROTECT 12:12 Temporary write protection + * FILE_FORMAT 10:11 File format + * ECC 9:8 ECC (MMC only) + * CRC 7:1 CRC + * Not used 0:0 + */ + + permwriteprotect = (csd[3] >> 13) & 1; + tmpwriteprotect = (csd[3] >> 12) & 1; + priv->wrprotect = (permwriteprotect || tmpwriteprotect); + +#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) + decoded.wpgrpen = csd[3] >> 31; + decoded.mmcdfltecc = (csd[3] >> 29) & 3; + decoded.r2wfactor = (csd[3] >> 26) & 7; + decoded.writebllen = (csd[3] >> 22) & 0x0f; + decoded.writeblpartial = (csd[3] >> 21) & 1; + decoded.fileformatgrp = (csd[3] >> 15) & 1; + decoded.copy = (csd[3] >> 14) & 1; + decoded.permwriteprotect = permwriteprotect; + decoded.tmpwriteprotect = tmpwriteprotect; + decoded.fileformat = (csd[3] >> 10) & 3; + decoded.mmcecc = (csd[3] >> 8) & 3; + decoded.crc = (csd[3] >> 1) & 0x7f; + + fvdbg("CSD:\n"); + fvdbg(" CSD_STRUCTURE: %d SPEC_VERS: %d (MMC)\n", + decoded.csdstructure, decoded.mmcspecvers); + fvdbg(" TAAC {TIME_UNIT: %d TIME_VALUE: %d} NSAC: %d\n", + decoded.taac.timeunit, decoded.taac.timevalue, decoded.nsac); + fvdbg(" TRAN_SPEED {TRANSFER_RATE_UNIT: %d TIME_VALUE: %d}\n", + decoded.transpeed.transferrateunit, decoded.transpeed.timevalue); + fvdbg(" CCC: %d\n", decoded.ccc); + fvdbg(" READ_BL_LEN: %d READ_BL_PARTIAL: %d\n", + decoded.readbllen, decoded.readblpartial); + fvdbg(" WRITE_BLK_MISALIGN: %d READ_BLK_MISALIGN: %d\n", + decoded.writeblkmisalign, decoded.readblkmisalign); + fvdbg(" DSR_IMP: %d\n", + decoded.dsrimp); + + if (IS_BLOCK(priv->type)) + { + fvdbg(" SD Block Addressing:\n"); + fvdbg(" C_SIZE: %d SD_ER_BLK_EN: %d\n", + decoded.u.sdblock.csize, decoded.u.sdblock.sderblen); + fvdbg(" SD_SECTOR_SIZE: %d SD_WP_GRP_SIZE: %d\n", + decoded.u.sdblock.sdsectorsize, decoded.u.sdblock.sdwpgrpsize); + } + else if (IS_SD(priv->type)) + { + fvdbg(" SD Byte Addressing:\n"); + fvdbg(" C_SIZE: %d C_SIZE_MULT: %d\n", + decoded.u.sdbyte.csize, decoded.u.sdbyte.csizemult); + fvdbg(" VDD_R_CURR_MIN: %d VDD_R_CURR_MAX: %d\n", + decoded.u.sdbyte.vddrcurrmin, decoded.u.sdbyte.vddrcurrmax); + fvdbg(" VDD_W_CURR_MIN: %d VDD_W_CURR_MAX: %d\n", + decoded.u.sdbyte.vddwcurrmin, decoded.u.sdbyte.vddwcurrmax); + fvdbg(" SD_ER_BLK_EN: %d SD_SECTOR_SIZE: %d (SD) SD_WP_GRP_SIZE: %d\n", + decoded.u.sdbyte.sderblen, decoded.u.sdbyte.sdsectorsize, decoded.u.sdbyte.sdwpgrpsize); + } +#ifdef CONFIG_MMCSD_MMCSUPPORT + else if (IS_MMC(priv->type)) + { + fvdbg(" MMC:\n"); + fvdbg(" C_SIZE: %d C_SIZE_MULT: %d\n", + decoded.u.mmc.csize, decoded.u.mmc.csizemult); + fvdbg(" VDD_R_CURR_MIN: %d VDD_R_CURR_MAX: %d\n", + decoded.u.mmc.vddrcurrmin, decoded.u.mmc.vddrcurrmax); + fvdbg(" VDD_W_CURR_MIN: %d VDD_W_CURR_MAX: %d\n", + decoded.u.mmc.vddwcurrmin, decoded.u.mmc.vddwcurrmax); + fvdbg(" MMC_SECTOR_SIZE: %d MMC_ER_GRP_SIZE: %d MMC_WP_GRP_SIZE: %d\n", + decoded.u.mmc.er.mmc22.sectorsize, decoded.u.mmc.er.mmc22.ergrpsize, + decoded.u.mmc.mmcwpgrpsize); + } +#endif + + fvdbg(" WP_GRP_EN: %d MMC DFLT_ECC: %d (MMC) R2W_FACTOR: %d\n", + decoded.wpgrpen, decoded.mmcdfltecc, decoded.r2wfactor); + fvdbg(" WRITE_BL_LEN: %d WRITE_BL_PARTIAL: %d\n", + decoded.writebllen, decoded.writeblpartial); + fvdbg(" FILE_FORMAT_GROUP: %d COPY: %d\n", + decoded.fileformatgrp, decoded.copy); + fvdbg(" PERM_WRITE_PROTECT: %d TMP_WRITE_PROTECT: %d\n", + decoded.permwriteprotect, decoded.tmpwriteprotect); + fvdbg(" FILE_FORMAT: %d ECC: %d (MMC) CRC: %d\n", + decoded.fileformat, decoded.mmcecc, decoded.crc); + + fvdbg("Capacity: %luKb, Block size: %db, nblocks: %d wrprotect: %d\n", + (unsigned long)(priv->capacity / 1024), priv->blocksize, + priv->nblocks, priv->wrprotect); +#endif +} + +/**************************************************************************** + * Name: mmcsd_decodeCID + * + * Description: + * Show the contents of the Card Indentification Data (CID) (for debug + * purposes only) + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) +static void mmcsd_decodeCID(FAR struct mmcsd_state_s *priv, uint32_t cid[4]) +{ + struct mmcsd_cid_s decoded; + + /* Word 1: Bits 127-96: + * mid - 127-120 8-bit Manufacturer ID + * oid - 119-104 16-bit OEM/Application ID (ascii) + * pnm - 103-64 40-bit Product Name (ascii) + null terminator + * pnm[0] 103:96 + */ + + decoded.mid = cid[0] >> 24; + decoded.oid = (cid[0] >> 16) & 0xffff; + decoded.pnm[0] = cid[0] & 0xff; + + /* Word 2: Bits 64:95 + * pnm - 103-64 40-bit Product Name (ascii) + null terminator + * pnm[1] 95:88 + * pnm[2] 87:80 + * pnm[3] 79:72 + * pnm[4] 71:64 + */ + + decoded.pnm[1] = cid[1] >> 24; + decoded.pnm[2] = (cid[1] >> 16) & 0xff; + decoded.pnm[3] = (cid[1] >> 8) & 0xff; + decoded.pnm[4] = cid[1] & 0xff; + decoded.pnm[5] = '\0'; + + /* Word 3: Bits 32-63 + * prv - 63-56 8-bit Product revision + * psn - 55-24 32-bit Product serial number + */ + + decoded.prv = cid[2] >> 24; + decoded.psn = cid[2] << 8; + + /* Word 4: Bits 0-31 + * psn - 55-24 32-bit Product serial number + * 23-20 4-bit (reserved) + * mdt - 19:8 12-bit Manufacturing date + * crc - 7:1 7-bit CRC7 + */ + + decoded.psn |= cid[3] >> 24; + decoded.mdt = (cid[3] >> 8) & 0x0fff; + decoded.crc = (cid[3] >> 1) & 0x7f; + + fvdbg("mid: %02x oid: %04x pnm: %s prv: %d psn: %d mdt: %02x crc: %02x\n", + decoded.mid, decoded.oid, decoded.pnm, decoded.prv, + decoded.psn, decoded.mdt, decoded.crc); +} +#endif + +/**************************************************************************** + * Name: mmcsd_decodeSCR + * + * Description: + * Show the contents of the SD Configuration Register (SCR). The only + * value retained is: priv->buswidth; + * + ****************************************************************************/ + +static void mmcsd_decodeSCR(FAR struct mmcsd_state_s *priv, uint32_t scr[2]) +{ +#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) +struct mmcsd_scr_s decoded; +#endif + + /* Word 1, bits 63:32 + * SCR_STRUCTURE 63:60 4-bit SCR structure version + * SD_VERSION 59:56 4-bit SD memory spec. version + * DATA_STATE_AFTER_ERASE 55:55 1-bit erase status + * SD_SECURITY 54:52 3-bit SD security support level + * SD_BUS_WIDTHS 51:48 4-bit bus width indicator + * Reserved 47:32 16-bit SD reserved space + */ + +#ifdef CONFIG_ENDIAN_BIG /* Card transfers SCR in big-endian order */ + priv->buswidth = (scr[0] >> 16) & 15; +#else + priv->buswidth = (scr[0] >> 8) & 15; +#endif + +#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) +#ifdef CONFIG_ENDIAN_BIG /* Card SCR is big-endian order / CPU also big-endian + * 60 56 52 48 44 40 36 32 + * VVVV SSSS ESSS BBBB RRRR RRRR RRRR RRRR */ + decoded.scrversion = scr[0] >> 28; + decoded.sdversion = (scr[0] >> 24) & 15; + decoded.erasestate = (scr[0] >> 23) & 1; + decoded.security = (scr[0] >> 20) & 7; +#else /* Card SCR is big-endian order / CPU is little-endian + * 36 32 44 40 52 48 60 56 + * RRRR RRRR RRRR RRRR ESSS BBBB VVVV SSSS */ + decoded.scrversion = (scr[0] >> 4) & 15; + decoded.sdversion = scr[0] & 15; + decoded.erasestate = (scr[0] >> 15) & 1; + decoded.security = (scr[0] >> 12) & 7; +#endif + decoded.buswidth = priv->buswidth; +#endif + + /* Word 1, bits 63:32 + * Reserved 31:0 32-bits reserved for manufacturing usage. + */ + +#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) + decoded.mfgdata = scr[1]; /* Might be byte reversed! */ + + fvdbg("SCR:\n"); + fvdbg(" SCR_STRUCTURE: %d SD_VERSION: %d\n", + decoded.scrversion,decoded.sdversion); + fvdbg(" DATA_STATE_AFTER_ERASE: %d SD_SECURITY: %d SD_BUS_WIDTHS: %x\n", + decoded.erasestate, decoded.security, decoded.buswidth); + fvdbg(" Manufacturing data: %08x\n", + decoded.mfgdata); +#endif +} + +/**************************************************************************** + * Name: mmcsd_getR1 + * + * Description: + * Get the R1 status of the card using CMD13 + * + ****************************************************************************/ + +static int mmcsd_getR1(FAR struct mmcsd_state_s *priv, FAR uint32_t *r1) +{ + uint32_t localR1; + int ret; + + DEBUGASSERT(priv != NULL && r1 != NULL); + + /* Send CMD13, SEND_STATUS. The addressed card responds by sending its + * R1 card status register. + */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD13, (uint32_t)priv->rca << 16); + ret = SDIO_RECVR1(priv->dev, MMCSD_CMD13, &localR1); + if (ret == OK) + { + /* Check if R1 reports an error */ + + if ((localR1 & MMCSD_R1_ERRORMASK) != 0) + { + /* Card locked is considered an error. Save the card locked + * indication for later use. + */ + + priv->locked = ((localR1 & MMCSD_R1_CARDISLOCKED) != 0); + ret = -EIO; + } + else + { + /* No errors, return R1 */ + + *r1 = localR1; + } + } + return ret; +} + +/**************************************************************************** + * Name: mmcsd_verifystate + * + * Description: + * Verify that the card is in STANDBY state + * + ****************************************************************************/ + +static int mmcsd_verifystate(FAR struct mmcsd_state_s *priv, uint32_t state) +{ + uint32_t r1; + int ret; + + /* Get the current R1 status from the card */ + + ret = mmcsd_getR1(priv, &r1); + if (ret != OK) + { + fdbg("ERROR: mmcsd_getR1 failed: %d\n", ret); + return ret; + } + + /* Now check if the card is in the expected state. */ + + if (IS_STATE(r1, state)) + { + /* Yes.. return Success */ + + priv->wrbusy = false; + return OK; + } + return -EINVAL; +} + +/**************************************************************************** + * Transfer Helpers + ****************************************************************************/ + +/**************************************************************************** + * Name: mmcsd_wrprotected + * + * Description: + * Return true if the the card is unlocked an not write protected. The + * + * + ****************************************************************************/ + +#ifdef CONFIG_FS_WRITABLE +static bool mmcsd_wrprotected(FAR struct mmcsd_state_s *priv) +{ + /* Check if the card is locked (priv->locked) or write protected either (1) + * via software as reported via the CSD and retained in priv->wrprotect or + * (2) via the mechanical write protect on the card (which we get from the + * SDIO driver via SDIO_WRPROTECTED) + */ + + return (priv->wrprotect || priv->locked || SDIO_WRPROTECTED(priv->dev)); +} +#endif + +/**************************************************************************** + * Name: mmcsd_eventwait + * + * Description: + * Wait for the specified events to occur. Check for wakeup on error events. + * + ****************************************************************************/ + +static int mmcsd_eventwait(FAR struct mmcsd_state_s *priv, + sdio_eventset_t failevents, uint32_t timeout) +{ + sdio_eventset_t wkupevent; + + /* Wait for the set of events enabled by SDIO_EVENTENABLE. */ + + wkupevent = SDIO_EVENTWAIT(priv->dev, timeout); + + /* SDIO_EVENTWAIT returns the event set containing the event(s) that ended + * the wait. It should always be non-zero, but may contain failure as + * well as success events. Check if it contains any failure events. + */ + + if ((wkupevent & failevents) != 0) + { + /* Yes.. the failure event is probably SDIOWAIT_TIMEOUT */ + + fdbg("ERROR: Awakened with %02x\n", wkupevent); + return wkupevent & SDIOWAIT_TIMEOUT ? -ETIMEDOUT : -EIO; + } + + /* Since there are no failure events, we must have been awakened by one + * (or more) success events. + */ + + return OK; +} + +/**************************************************************************** + * Name: mmcsd_transferready + * + * Description: + * Check if the MMC/SD card is ready for the next read or write transfer. + * Ready means: (1) card still in the slot, and (2) if the last transfer + * was a write transfer, the card is no longer busy from that transfer. + * + ****************************************************************************/ + +static int mmcsd_transferready(FAR struct mmcsd_state_s *priv) +{ + uint32_t starttime; + uint32_t elapsed; + uint32_t r1; + int ret; + + /* First, check if the card has been removed. */ + + if (!SDIO_PRESENT(priv->dev)) + { + fdbg("ERROR: Card has been removed\n"); + return -ENODEV; + } + + /* If the last data transfer was not a write, then we do not have to check + * the card status. + */ + + else if (!priv->wrbusy) + { + return OK; + } + + /* The card is still present and the last transfer was a write transfer. + * Loop, querying the card state. Return when (1) the card is in the TRANSFER + * state, (2) the card stays in the PROGRAMMING state too long, or (3) the + * card is in any other state. + * + * The PROGRAMMING state occurs normally after a WRITE operation. During this + * time, the card may be busy completing the WRITE and is not available for + * other operations. The card will transition from the PROGRAMMING state to + * the TRANSFER state when the card completes the WRITE operation. + */ + + starttime = clock_systimer(); + do + { + /* Get the current R1 status from the card */ + + ret = mmcsd_getR1(priv, &r1); + if (ret != OK) + { + fdbg("ERROR: mmcsd_getR1 failed: %d\n", ret); + return ret; + } + + /* Now check if the card is in the expected transfer state. */ + + if (IS_STATE(r1, MMCSD_R1_STATE_TRAN)) + { + /* Yes.. return Success */ + + priv->wrbusy = false; + return OK; + } + + /* Check for the programming state. This is not an error. It means + * that the card is still busy from the last (write) transfer. + */ + + else if (!IS_STATE(r1, MMCSD_R1_STATE_PRG)) + { + /* Any other state would be an error in this context. There is + * a possibility that the card is not selected. In this case, + * it could be in STANDBY or DISCONNECTED state and the fix + * might b to send CMD7 to re-select the card. Consider this + * if this error occurs. + */ + + fdbg("ERROR: Unexpected R1 state: %08x\n", r1); + return -EINVAL; + } + + /* We are still in the programming state. Calculate the elapsed + * time... we can't stay in this loop forever! + */ + + elapsed = clock_systimer() - starttime; + } + while (elapsed < TICK_PER_SEC); + return -ETIMEDOUT; +} + +/**************************************************************************** + * Name: mmcsd_stoptransmission + * + * Description: + * Send STOP_TRANSMISSION + * + ****************************************************************************/ + +#ifndef CONFIG_MMCSD_MULTIBLOCK_DISABLE +static int mmcsd_stoptransmission(FAR struct mmcsd_state_s *priv) +{ + int ret; + + /* Send CMD12, STOP_TRANSMISSION, and verify good R1 return status */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD12, 0); + ret = mmcsd_recvR1(priv, MMCSD_CMD12); + if (ret != OK) + { + fdbg("ERROR: mmcsd_recvR1 for CMD12 failed: %d\n", ret); + } + return ret; +} +#endif + +/**************************************************************************** + * Name: mmcsd_setblocklen + * + * Description: + * Read a single block of data. + * + ****************************************************************************/ + +static int mmcsd_setblocklen(FAR struct mmcsd_state_s *priv, uint32_t blocklen) +{ + int ret = OK; + + /* Is the block length already selected in the card? */ + + if (priv->selblocklen != blocklen) + { + /* Send CMD16 = SET_BLOCKLEN. This command sets the block length (in + * bytes) for all following block commands (read and write). Default + * block length is specified in the CSD. + */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD16, blocklen); + ret = mmcsd_recvR1(priv, MMCSD_CMD16); + if (ret == OK) + { + priv->selblocklen = blocklen; + } + else + { + fdbg("ERROR: mmcsd_recvR1 for CMD16 failed: %d\n", ret); + } + } + + return ret; +} + +/**************************************************************************** + * Name: mmcsd_readsingle + * + * Description: + * Read a single block of data. + * + ****************************************************************************/ + +static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv, + FAR uint8_t *buffer, off_t startblock) +{ + off_t offset; + int ret; + + fvdbg("startblock=%d\n", startblock); + DEBUGASSERT(priv != NULL && buffer != NULL); + + /* Check if the card is locked */ + + if (priv->locked) + { + fdbg("ERROR: Card is locked\n"); + return -EPERM; + } + + /* Verify that the card is ready for the transfer. The card may still be + * busy from the preceding write transfer. It would be simpler to check + * for write busy at the end of each write, rather than at the beginning of + * each read AND write, but putting the busy-wait at the beginning of the + * transfer allows for more overlap and, hopefully, better performance + */ + + ret = mmcsd_transferready(priv); + if (ret != OK) + { + fdbg("ERROR: Card not ready: %d\n", ret); + return ret; + } + + /* If this is a byte addressed SD card, then convert sector start sector + * number to a byte offset + */ + + if (IS_BLOCK(priv->type)) + { + offset = startblock; + } + else + { + offset = startblock << priv->blockshift; + } + fvdbg("offset=%d\n", offset); + + /* Select the block size for the card */ + + ret = mmcsd_setblocklen(priv, priv->blocksize); + if (ret != OK) + { + fdbg("ERROR: mmcsd_setblocklen failed: %d\n", ret); + return ret; + } + + /* Configure SDIO controller hardware for the read transfer */ + + SDIO_BLOCKSETUP(priv->dev, priv->blocksize, 1); + SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR); +#ifdef CONFIG_SDIO_DMA + if (priv->dma) + { + SDIO_DMARECVSETUP(priv->dev, buffer, priv->blocksize); + } + else +#endif + { + SDIO_RECVSETUP(priv->dev, buffer, priv->blocksize); + } + + /* Send CMD17, READ_SINGLE_BLOCK: Read a block of the size selected + * by the mmcsd_setblocklen() and verify that good R1 status is + * returned. The card state should change from Transfer to Sending-Data + * state. + */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD17, offset); + ret = mmcsd_recvR1(priv, MMCSD_CMD17); + if (ret != OK) + { + fdbg("ERROR: mmcsd_recvR1 for CMD17 failed: %d\n", ret); + SDIO_CANCEL(priv->dev); + return ret; + } + + /* Then wait for the data transfer to complete */ + + ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR, MMCSD_BLOCK_DATADELAY); + if (ret != OK) + { + fdbg("ERROR: CMD17 transfer failed: %d\n", ret); + return ret; + } + + /* Return value: One sector read */ + + return 1; +} + +/**************************************************************************** + * Name: mmcsd_readmultiple + * + * Description: + * Read multiple, contiguous blocks of data from the physical device. + * + ****************************************************************************/ + +#ifndef CONFIG_MMCSD_MULTIBLOCK_DISABLE +static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv, + FAR uint8_t *buffer, off_t startblock, + size_t nblocks) +{ + size_t nbytes; + off_t offset; + int ret; + + fvdbg("startblock=%d nblocks=%d\n", startblock, nblocks); + DEBUGASSERT(priv != NULL && buffer != NULL && nblocks > 1); + + /* Check if the card is locked */ + + if (priv->locked) + { + fdbg("ERROR: Card is locked\n"); + return -EPERM; + } + + /* Verify that the card is ready for the transfer. The card may still be + * busy from the preceding write transfer. It would be simpler to check + * for write busy at the end of each write, rather than at the beginning of + * each read AND write, but putting the busy-wait at the beginning of the + * transfer allows for more overlap and, hopefully, better performance + */ + + ret = mmcsd_transferready(priv); + if (ret != OK) + { + fdbg("ERROR: Card not ready: %d\n", ret); + return ret; + } + + /* If this is a byte addressed SD card, then convert both the total transfer + * size to bytes and the sector start sector number to a byte offset + */ + + nbytes = nblocks << priv->blockshift; + if (IS_BLOCK(priv->type)) + { + offset = startblock; + } + else + { + offset = startblock << priv->blockshift; + } + fvdbg("nbytes=%d byte offset=%d\n", nbytes, offset); + + /* Select the block size for the card */ + + ret = mmcsd_setblocklen(priv, priv->blocksize); + if (ret != OK) + { + fdbg("ERROR: mmcsd_setblocklen failed: %d\n", ret); + return ret; + } + + /* Configure SDIO controller hardware for the read transfer */ + + SDIO_BLOCKSETUP(priv->dev, priv->blocksize, nblocks); + SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR); +#ifdef CONFIG_SDIO_DMA + if (priv->dma) + { + SDIO_DMARECVSETUP(priv->dev, buffer, nbytes); + } + else +#endif + { + SDIO_RECVSETUP(priv->dev, buffer, nbytes); + } + + /* Send CMD18, READ_MULT_BLOCK: Read a block of the size selected by + * the mmcsd_setblocklen() and verify that good R1 status is returned + */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD18, offset); + ret = mmcsd_recvR1(priv, MMCSD_CMD18); + if (ret != OK) + { + fdbg("ERROR: mmcsd_recvR1 for CMD18 failed: %d\n", ret); + SDIO_CANCEL(priv->dev); + return ret; + } + + /* Wait for the transfer to complete */ + + ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR, nblocks * MMCSD_BLOCK_DATADELAY); + if (ret != OK) + { + fdbg("ERROR: CMD18 transfer failed: %d\n", ret); + return ret; + } + + /* Send STOP_TRANSMISSION */ + + ret = mmcsd_stoptransmission(priv); + if (ret != OK) + { + fdbg("ERROR: mmcsd_stoptransmission failed: %d\n", ret); + } + + /* On success, return the number of blocks read */ + + return nblocks; +} +#endif + +/**************************************************************************** + * Name: mmcsd_reload + * + * Description: + * Reload the specified number of sectors from the physical device into the + * read-ahead buffer. + * + ****************************************************************************/ + +#ifdef CONFIG_FS_READAHEAD +static ssize_t mmcsd_reload(FAR void *dev, FAR uint8_t *buffer, + off_t startblock, size_t nblocks) +{ + FAR struct mmcsd_state_s *priv = (FAR struct mmcsd_state_s *)dev; +#ifdef CONFIG_MMCSD_MULTIBLOCK_DISABLE + size_t block; + size_t endblock; +#endif + ssize_t ret; + + DEBUGASSERT(priv != NULL && buffer != NULL && nblocks > 0) + +#ifdef CONFIG_MMCSD_MULTIBLOCK_DISABLE + /* Read each block using only the single block transfer method */ + + endblock = startblock + nblocks - 1; + for (block = startblock; block <= endblock; block++) + { + /* Read this block into the user buffer */ + + ret = mmcsd_readsingle(priv, buffer, block); + if (ret < 0) + { + break; + } + + /* Increment the buffer pointer by the block size */ + + buffer += priv->blocksize; + } +#else + /* Use either the single- or muliple-block transfer method */ + + if (nblocks == 1) + { + ret = mmcsd_readsingle(priv, buffer, startblock); + } + else + { + ret = mmcsd_readmultiple(priv, buffer, startblock, nblocks); + } +#endif + + /* On success, return the number of blocks read */ + + return ret; +} +#endif + +/**************************************************************************** + * Name: mmcsd_writesingle + * + * Description: + * Write a single block of data to the physical device. + * + ****************************************************************************/ + +#ifdef CONFIG_FS_WRITABLE +static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv, + FAR const uint8_t *buffer, off_t startblock) +{ + off_t offset; + int ret; + + fvdbg("startblock=%d\n", startblock); + DEBUGASSERT(priv != NULL && buffer != NULL); + + /* Check if the card is locked or write protected (either via software or + * via the mechanical write protect on the card) + */ + + if (mmcsd_wrprotected(priv)) + { + fdbg("ERROR: Card is locked or write protected\n"); + return -EPERM; + } + + /* Verify that the card is ready for the transfer. The card may still be + * busy from the preceding write transfer. It would be simpler to check + * for write busy at the end of each write, rather than at the beginning of + * each read AND write, but putting the busy-wait at the beginning of the + * transfer allows for more overlap and, hopefully, better performance + */ + + ret = mmcsd_transferready(priv); + if (ret != OK) + { + fdbg("ERROR: Card not ready: %d\n", ret); + return ret; + } + + /* If this is a byte addressed SD card, then convert sector start sector + * number to a byte offset + */ + + if (IS_BLOCK(priv->type)) + { + offset = startblock; + } + else + { + offset = startblock << priv->blockshift; + } + fvdbg("offset=%d\n", offset); + + /* Select the block size for the card */ + + ret = mmcsd_setblocklen(priv, priv->blocksize); + if (ret != OK) + { + fdbg("ERROR: mmcsd_setblocklen failed: %d\n", ret); + return ret; + } + + /* Send CMD24, WRITE_BLOCK, and verify that good R1 status is returned */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD24, offset); + ret = mmcsd_recvR1(priv, MMCSD_CMD24); + if (ret != OK) + { + fdbg("ERROR: mmcsd_recvR1 for CMD24 failed: %d\n", ret); + return ret; + } + + /* Configure SDIO controller hardware for the write transfer */ + + SDIO_BLOCKSETUP(priv->dev, priv->blocksize, 1); + SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR); +#ifdef CONFIG_SDIO_DMA + if (priv->dma) + { + SDIO_DMASENDSETUP(priv->dev, buffer, priv->blocksize); + } + else +#endif + { + SDIO_SENDSETUP(priv->dev, buffer, priv->blocksize); + } + + /* Flag that a write transfer is pending that we will have to check for + * write complete at the beginning of the next transfer. + */ + + priv->wrbusy = true; + + /* Wait for the transfer to complete */ + + ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR, MMCSD_BLOCK_DATADELAY); + if (ret != OK) + { + fdbg("ERROR: CMD24 transfer failed: %d\n", ret); + return ret; + } + + /* On success, return the number of blocks written */ + + return 1; +} +#endif + +/**************************************************************************** + * Name: mmcsd_writemultiple + * + * Description: + * Write multiple, contiguous blocks of data to the physical device. + * + ****************************************************************************/ + +#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_MULTIBLOCK_DISABLE) +static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, + FAR const uint8_t *buffer, off_t startblock, + size_t nblocks) +{ + off_t offset; + size_t nbytes; + int ret; + + fvdbg("startblockr=%d nblocks=%d\n", startblock, nblocks); + DEBUGASSERT(priv != NULL && buffer != NULL && nblocks > 1); + + /* Check if the card is locked or write protected (either via software or + * via the mechanical write protect on the card) + */ + + if (mmcsd_wrprotected(priv)) + { + fdbg("ERROR: Card is locked or write protected\n"); + return -EPERM; + } + + /* Verify that the card is ready for the transfer. The card may still be + * busy from the preceding write transfer. It would be simpler to check + * for write busy at the end of each write, rather than at the beginning of + * each read AND write, but putting the busy-wait at the beginning of the + * transfer allows for more overlap and, hopefully, better performance + */ + + ret = mmcsd_transferready(priv); + if (ret != OK) + { + fdbg("ERROR: Card not ready: %d\n", ret); + return ret; + } + + /* If this is a byte addressed SD card, then convert both the total transfer + * size to bytes and the sector start sector number to a byte offset + */ + + nbytes = nblocks << priv->blockshift; + if (IS_BLOCK(priv->type)) + { + offset = startblock; + } + else + { + offset = startblock << priv->blockshift; + } + fvdbg("nbytes=%d byte offset=%d\n", nbytes, offset); + + /* Select the block size for the card */ + + ret = mmcsd_setblocklen(priv, priv->blocksize); + if (ret != OK) + { + fdbg("ERROR: mmcsd_setblocklen failed: %d\n", ret); + return ret; + } + + /* If this is an SD card, then send ACMD23 (SET_WR_BLK_COUNT) just before + * sending CMD25 (WRITE_MULTIPLE_BLOCK). This sets the number of write + * blocks to be pre-erased and might make the following multiple block write + * command faster. + */ + + if (IS_SD(priv->type)) + { + /* Send CMD55, APP_CMD, a verify that good R1 status is retured */ + + mmcsd_sendcmdpoll(priv, SD_CMD55, 0); + ret = mmcsd_recvR1(priv, SD_CMD55); + if (ret != OK) + { + fdbg("ERROR: mmcsd_recvR1 for CMD55 (ACMD23) failed: %d\n", ret); + return ret; + } + + /* Send CMD23, SET_WR_BLK_COUNT, and verify that good R1 status is returned */ + + mmcsd_sendcmdpoll(priv, SD_ACMD23, 0); + ret = mmcsd_recvR1(priv, SD_ACMD23); + if (ret != OK) + { + fdbg("ERROR: mmcsd_recvR1 for ACMD23 failed: %d\n", ret); + return ret; + } + } + + /* Send CMD25, WRITE_MULTIPLE_BLOCK, and verify that good R1 status + * is returned + */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD25, offset); + ret = mmcsd_recvR1(priv, MMCSD_CMD25); + if (ret != OK) + { + fdbg("ERROR: mmcsd_recvR1 for CMD24 failed: %d\n", ret); + return ret; + } + + /* Configure SDIO controller hardware for the write transfer */ + + SDIO_BLOCKSETUP(priv->dev, priv->blocksize, nblocks); + SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR); +#ifdef CONFIG_SDIO_DMA + if (priv->dma) + { + SDIO_DMASENDSETUP(priv->dev, buffer, nbytes); + } + else +#endif + { + SDIO_SENDSETUP(priv->dev, buffer, nbytes); + } + + /* Flag that a write transfer is pending that we will have to check for + * write complete at the beginning of the next transfer. + */ + + priv->wrbusy = true; + + /* Wait for the transfer to complete */ + + ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR, nblocks * MMCSD_BLOCK_DATADELAY); + if (ret != OK) + { + fdbg("ERROR: CMD18 transfer failed: %d\n", ret); + return ret; + } + + /* Send STOP_TRANSMISSION */ + + ret = mmcsd_stoptransmission(priv); + if (ret != OK) + { + fdbg("ERROR: mmcsd_stoptransmission failed: %d\n", ret); + return ret; + } + + /* On success, return the number of blocks read */ + + return nblocks; +} +#endif + +/**************************************************************************** + * Name: mmcsd_flush + * + * Description: + * Flush the specified number of sectors from the write buffer to the card. + * + ****************************************************************************/ + +#if defined(CONFIG_FS_WRITABLE) && defined(CONFIG_FS_WRITEBUFFER) +static ssize_t mmcsd_flush(FAR void *dev, FAR const uint8_t *buffer, + off_t startblock, size_t nblocks) +{ + FAR struct mmcsd_state_s *priv = (FAR struct mmcsd_state_s *)dev; +#ifndef CONFIG_MMCSD_MULTIBLOCK_DISABLE + size_t block; + size_t endblock; +#endif + ssize_t ret; + + DEBUGASSERT(priv != NULL && buffer != NULL && nblocks > 0) + +#ifdef CONFIG_MMCSD_MULTIBLOCK_DISABLE + /* Write each block using only the single block transfer method */ + + endblock = startblock + nblocks - 1; + for (block = startblock; block <= endblock; block++) + { + /* Write this block from the user buffer */ + + ret = mmcsd_writesingle(priv, buffer, block); + if (ret < 0) + { + break; + } + + /* Increment the buffer pointer by the block size */ + + buffer += priv->blocksize; + } +#else + if (nblocks == 1) + { + ret = mmcsd_writesingle(priv, buffer, startblock); + } + else + { + ret = mmcsd_writemultiple(priv, buffer, startblock, nblocks); + } +#endif + + /* On success, return the number of blocks written */ + + return ret; +} +#endif + +/**************************************************************************** + * Block Driver Methods + ****************************************************************************/ +/**************************************************************************** + * Name: mmcsd_open + * + * Description: Open the block device + * + ****************************************************************************/ + +static int mmcsd_open(FAR struct inode *inode) +{ + FAR struct mmcsd_state_s *priv; + + fvdbg("Entry\n"); + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct mmcsd_state_s *)inode->i_private; + + /* Just increment the reference count on the driver */ + + DEBUGASSERT(priv->crefs < MAX_CREFS); + mmcsd_takesem(priv); + priv->crefs++; + mmcsd_givesem(priv); + return OK; +} + +/**************************************************************************** + * Name: mmcsd_close + * + * Description: close the block device + * + ****************************************************************************/ + +static int mmcsd_close(FAR struct inode *inode) +{ + FAR struct mmcsd_state_s *priv; + + fvdbg("Entry\n"); + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct mmcsd_state_s *)inode->i_private; + + /* Decrement the reference count on the block driver */ + + DEBUGASSERT(priv->crefs > 0); + mmcsd_takesem(priv); + priv->crefs--; + mmcsd_givesem(priv); + return OK; +} + +/**************************************************************************** + * Name: mmcsd_read + * + * Description: + * Read the specified numer of sectors from the read-ahead buffer or from + * the physical device. + * + ****************************************************************************/ + +static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer, + size_t startsector, unsigned int nsectors) +{ + FAR struct mmcsd_state_s *priv; +#if !defined(CONFIG_FS_READAHEAD) && defined(CONFIG_MMCSD_MULTIBLOCK_DISABLE) + size_t sector; + size_t endsector; +#endif + ssize_t ret = 0; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct mmcsd_state_s *)inode->i_private; + fvdbg("startsector: %d nsectors: %d sectorsize: %d\n", + startsector, nsectors, priv->blocksize); + + if (nsectors > 0) + { + mmcsd_takesem(priv); + +#if defined(CONFIG_FS_READAHEAD) + /* Get the data from the read-ahead buffer */ + + ret = rwb_read(&priv->rwbuffer, startsector, nsectors, buffer); + +#elif defined(CONFIG_MMCSD_MULTIBLOCK_DISABLE) + /* Read each block using only the single block transfer method */ + + endsector = startsector + nsectors - 1; + for (sector = startsector; sector <= endsector; sector++) + { + /* Read this sector into the user buffer */ + + ret = mmcsd_readsingle(priv, buffer, sector); + if (ret < 0) + { + break; + } + + /* Increment the buffer pointer by the sector size */ + + buffer += priv->blocksize; + } +#else + /* Use either the single- or muliple-block transfer method */ + + if (nsectors == 1) + { + ret = mmcsd_readsingle(priv, buffer, startsector); + } + else + { + ret = mmcsd_readmultiple(priv, buffer, startsector, nsectors); + } +#endif + mmcsd_givesem(priv); + } + + /* On success, return the number of blocks read */ + + return ret; +} + +/**************************************************************************** + * Name: mmcsd_write + * + * Description: + * Write the specified number of sectors to the write buffer or to the + * physical device. + * + ****************************************************************************/ + +#ifdef CONFIG_FS_WRITABLE +static ssize_t mmcsd_write(FAR struct inode *inode, FAR const unsigned char *buffer, + size_t startsector, unsigned int nsectors) +{ + FAR struct mmcsd_state_s *priv; +#if !defined(CONFIG_FS_WRITEBUFFER) && defined(CONFIG_MMCSD_MULTIBLOCK_DISABLE) + size_t sector; + size_t endsector; +#endif + ssize_t ret = 0; + + fvdbg("sector: %d nsectors: %d sectorsize: %d\n"); + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct mmcsd_state_s *)inode->i_private; + + mmcsd_takesem(priv); + +#if defined(CONFIG_FS_WRITEBUFFER) + /* Write the data to the write buffer */ + + ret = rwb_write(&priv->rwbuffer, startsector, nsectors, buffer); + +#elif defined(CONFIG_MMCSD_MULTIBLOCK_DISABLE) + /* Write each block using only the single block transfer method */ + + endsector = startsector + nsectors - 1; + for (sector = startsector; sector <= endsector; sector++) + { + /* Write this block from the user buffer */ + + ret = mmcsd_writesingle(priv, buffer, sector); + if (ret < 0) + { + break; + } + + /* Increment the buffer pointer by the block size */ + + buffer += priv->blocksize; + } +#else + /* Use either the single- or multiple-block transfer method */ + + if (nsectors == 1) + { + ret = mmcsd_writesingle(priv, buffer, startsector); + } + else + { + ret = mmcsd_writemultiple(priv, buffer, startsector, nsectors); + } +#endif + mmcsd_givesem(priv); + + /* On success, return the number of blocks written */ + + return ret; +} +#endif + +/**************************************************************************** + * Name: mmcsd_geometry + * + * Description: Return device geometry + * + ****************************************************************************/ + +static int mmcsd_geometry(FAR struct inode *inode, struct geometry *geometry) +{ + FAR struct mmcsd_state_s *priv; + int ret = -EINVAL; + + fvdbg("Entry\n"); + DEBUGASSERT(inode && inode->i_private); + + if (geometry) + { + /* Is there a (supported) card inserted in the slot? */ + + priv = (FAR struct mmcsd_state_s *)inode->i_private; + mmcsd_takesem(priv); + if (IS_EMPTY(priv)) + { + /* No.. return ENODEV */ + + fvdbg("IS_EMPTY\n"); + ret = -ENODEV; + } + else + { + /* Yes.. return the geometry of the card */ + + geometry->geo_available = true; + geometry->geo_mediachanged = priv->mediachanged; +#ifdef CONFIG_FS_WRITABLE + geometry->geo_writeenabled = !mmcsd_wrprotected(priv); +#else + geometry->geo_writeenabled = false; +#endif + geometry->geo_nsectors = priv->nblocks; + geometry->geo_sectorsize = priv->blocksize; + + fvdbg("available: true mediachanged: %s writeenabled: %s\n", + geometry->geo_mediachanged ? "true" : "false", + geometry->geo_writeenabled ? "true" : "false"); + fvdbg("nsectors: %ld sectorsize: %d\n", + (long)geometry->geo_nsectors, geometry->geo_sectorsize); + + priv->mediachanged = false; + ret = OK; + } + mmcsd_givesem(priv); + } + + return ret; +} + +/**************************************************************************** + * Name: mmcsd_ioctl + * + * Description: Return device geometry + * + ****************************************************************************/ + +static int mmcsd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg) +{ + FAR struct mmcsd_state_s *priv; + int ret; + + fvdbg("Entry\n"); + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct mmcsd_state_s *)inode->i_private; + + /* Process the IOCTL by command */ + + mmcsd_takesem(priv); + switch (cmd) + { + case BIOC_PROBE: /* Check for media in the slot */ + { + fvdbg("BIOC_PROBE\n"); + + /* Probe the MMC/SD slot for media */ + + ret = mmcsd_probe(priv); + if (ret != OK) + { + fdbg("ERROR: mmcsd_probe failed: %d\n", ret); + } + } + break; + + case BIOC_EJECT: /* Media has been removed from the slot */ + { + fvdbg("BIOC_EJECT\n"); + + /* Process the removal of the card */ + + ret = mmcsd_removed(priv); + if (ret != OK) + { + fdbg("ERROR: mmcsd_removed failed: %d\n", ret); + } + + /* Enable logic to detect if a card is re-inserted */ + + SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED); + } + break; + + default: + ret = -ENOTTY; + break; + } + + mmcsd_givesem(priv); + return ret; +} + +/**************************************************************************** + * Initialization/uninitialization/reset + ****************************************************************************/ + +/**************************************************************************** + * Name: mmcsd_mediachange + * + * Description: + * This is a callback function from the SDIO driver that indicates that + * there has been a change in the slot... either a card has been inserted + * or a card has been removed. + * + * Assumptions: + * This callback is NOT supposd to run in the context of an interrupt + * handler; it is probably running in the context of work thread. + * + ****************************************************************************/ + +static void mmcsd_mediachange(FAR void *arg) +{ + FAR struct mmcsd_state_s *priv = (FAR struct mmcsd_state_s *)arg; + + fvdbg("arg: %p\n", arg); + DEBUGASSERT(priv); + + /* Is there a card present in the slot? */ + + mmcsd_takesem(priv); + if (SDIO_PRESENT(priv->dev)) + { + /* No... process the card insertion. This could cause chaos if we think + * that a card is already present and there are mounted filesystems! + * NOTE that mmcsd_probe() will always re-enable callbacks appropriately. + */ + + (void)mmcsd_probe(priv); + } + else + { + /* No... process the card removal. This could have very bad implications + * for any mounted file systems! NOTE that mmcsd_removed() does NOT + * re-enable callbacks so we will need to do that here. + */ + + (void)mmcsd_removed(priv); + + /* Enable logic to detect if a card is re-inserted */ + + SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED); + } + mmcsd_givesem(priv); +} + +/**************************************************************************** + * Name: mmcsd_widebus + * + * Description: + * An SD card has been inserted and its SCR has been obtained. Select wide + * (4-bit) bus operation if the card supports it. + * + * Assumptions: + * This function is called only once per card insertion as part of the SD + * card initialization sequence. It is not necessary to reselect the card + * there is not need to check if wide bus operation has already been + * selected. + * + ****************************************************************************/ + +static int mmcsd_widebus(FAR struct mmcsd_state_s *priv) +{ +#ifndef CONFIG_SDIO_WIDTH_D1_ONLY + int ret; + + /* Check if the SD card supports this feature (as reported in the SCR) */ + + if ((priv->buswidth & MMCSD_SCR_BUSWIDTH_4BIT) != 0) + { + /* Disconnect any CD/DAT3 pull up using ACMD42. ACMD42 is optional and + * need not be supported by all SD calls. + * + * First end CMD55 APP_CMD with argument as card's RCA. + */ + + mmcsd_sendcmdpoll(priv, SD_CMD55, (uint32_t)priv->rca << 16); + ret = mmcsd_recvR1(priv, SD_CMD55); + if (ret != OK) + { + fdbg("ERROR: RECVR1 for CMD55 of ACMD42: %d\n", ret); + return ret; + } + + /* Then send ACMD42 with the argument to disconnect the CD/DAT3 + * pullup + */ + + mmcsd_sendcmdpoll(priv, SD_ACMD42, MMCSD_ACMD42_CD_DISCONNECT); + ret = mmcsd_recvR1(priv, SD_ACMD42); + if (ret != OK) + { + fvdbg("WARNING: SD card does not support ACMD42: %d\n", ret); + return ret; + } + + /* Now send ACMD6 to select wide, 4-bit bus operation, beginning + * with CMD55, APP_CMD: + */ + + mmcsd_sendcmdpoll(priv, SD_CMD55, (uint32_t)priv->rca << 16); + ret = mmcsd_recvR1(priv, SD_CMD55); + if (ret != OK) + { + fdbg("ERROR: RECVR1 for CMD55 of ACMD6: %d\n", ret); + return ret; + } + + /* Then send ACMD6 */ + + mmcsd_sendcmdpoll(priv, SD_ACMD6, MMCSD_ACMD6_BUSWIDTH_4); + ret = mmcsd_recvR1(priv, SD_ACMD6); + if (ret != OK) + { + return ret; + } + + /* Configure the SDIO peripheral */ + + fvdbg("Wide bus operation selected\n"); + SDIO_WIDEBUS(priv->dev, true); + priv->widebus = true; + + SDIO_CLOCK(priv->dev, CLOCK_SD_TRANSFER_4BIT); + up_udelay(MMCSD_CLK_DELAY); + return OK; + } + + /* Wide bus operation not supported */ + + fdbg("WARNING: Card does not support wide-bus operation\n"); + return -ENOSYS; + +#else /* CONFIG_SDIO_WIDTH_D1_ONLY */ + + fvdbg("Wide-bus operation is disabled\n"); + return -ENOSYS; + +#endif /* CONFIG_SDIO_WIDTH_D1_ONLY */ +} + +/**************************************************************************** + * Name: mmcsd_mmcinitialize + * + * Description: + * We believe that there is an MMC card in the slot. Attempt to initialize + * and configure the MMC card. This is called only from mmcsd_probe(). + * + ****************************************************************************/ + +#ifdef CONFIG_MMCSD_MMCSUPPORT +static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv) +{ + uint32_t cid[4]; + uint32_t csd[4]; + int ret; + + /* At this point, slow, ID mode clocking has been supplied to the card + * and CMD0 has been sent successfully. CMD1 succeeded and ACMD41 failed + * so there is good evidence that we have an MMC card inserted into the + * slot. + * + * Send CMD2, ALL_SEND_CID. This implementation supports only one MMC slot. + * If mulitple cards were installed, each card would respond to CMD2 by + * sending its CID (only one card completes the response at a time). The + * driver should send CMD2 and assign an RCAs until no response to + * ALL_SEND_CID is received. CMD2 causes transition to identification state/ + * card-identification mode */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD2, 0); + ret = SDIO_RECVR2(priv->dev, MMCSD_CMD2, cid); + if (ret != OK) + { + fdbg("ERROR: SDIO_RECVR2 for MMC CID failed: %d\n", ret); + return ret; + } + mmcsd_decodeCID(priv, cid); + + /* Send CMD3, SET_RELATIVE_ADDR. This command is used to assign a logical + * address to the card. For MMC, the host assigns the address. CMD3 causes + * transition to standby state/data-transfer mode + */ + + priv->rca = 1; /* There is only one card */ + mmcsd_sendcmdpoll(priv, MMC_CMD3, priv->rca << 16); + ret = mmcsd_recvR1(priv, MMC_CMD3); + if (ret != OK) + { + fdbg("ERROR: mmcsd_recvR1(CMD3) failed: %d\n", ret); + return ret; + } + + /* This should have caused a transition to standby state. However, this will + * not be reflected in the present R1 status. R1/6 contains the state of the + * card when the command was received, not when it completed execution. + * + * Verify that we are in standby state/data-transfer mode + */ + + ret = mmcsd_verifystate(priv, MMCSD_R1_STATE_STBY); + if (ret != OK) + { + fdbg("ERROR: Failed to enter standby state\n"); + return ret; + } + + /* Send CMD9, SEND_CSD in standby state/data-transfer mode to obtain the + * Card Specific Data (CSD) register, e.g., block length, card storage + * capacity, etc. (Stays in standy state/data-transfer mode) + */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD9, priv->rca << 16); + ret = SDIO_RECVR2(priv->dev, MMCSD_CMD9, csd); + if (ret != OK) + { + fdbg("ERROR: Could not get SD CSD register: %d\n", ret); + return ret; + } + mmcsd_decodeCSD(priv, csd); + + /* Set the Driver Stage Register (DSR) if (1) a CONFIG_MMCSD_DSR has been + * provided and (2) the card supports a DSR register. If no DSR value + * the card default value (0x0404) will be used. + */ + + (void)mmcsd_sendcmd4(priv); + + /* Select high speed MMC clocking (which may depend on the DSR setting) */ + + SDIO_CLOCK(priv->dev, CLOCK_MMC_TRANSFER); + up_udelay(MMCSD_CLK_DELAY); + return OK; +} +#endif + +/**************************************************************************** + * Name: mmcsd_sdinitialize + * + * Description: + * We believe that there is an SD card in the slot. Attempt to initialize + * and configure the SD card. This is called only from mmcsd_probe(). + * + ****************************************************************************/ + +static int mmcsd_sdinitialize(FAR struct mmcsd_state_s *priv) +{ + uint32_t cid[4]; + uint32_t csd[4]; + uint32_t scr[2]; + int ret; + + /* At this point, clocking has been supplied to the card, both CMD0 and + * ACMD41 (with OCR=0) have been sent successfully, the card is no longer + * busy and (presumably) in the IDLE state so there is good evidence + * that we have an SD card inserted into the slot. + * + * Send CMD2, ALL_SEND_CID. The SD CMD2 is similar to the MMC CMD2 except + * that the buffer type used to transmit to response of the card (SD Memory + * Card: Push-Pull, MMC: Open-Drain). This implementation supports only a + * single SD card. If multiple cards were installed in the slot, each card + * would respond to CMD2 by sending its CID (only one card completes the + * response at a time). The driver should send CMD2 and obtain RCAs until + * no response to ALL_SEND_CID is received. + * + * When an SD card receives the CMD2 command it should transition to the + * identification state/card-identification mode + */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD2, 0); + ret = SDIO_RECVR2(priv->dev, MMCSD_CMD2, cid); + if (ret != OK) + { + fdbg("ERROR: SDIO_RECVR2 for SD CID failed: %d\n", ret); + return ret; + } + mmcsd_decodeCID(priv, cid); + + /* Send CMD3, SET_RELATIVE_ADDR. In both protocols, this command is used + * to assign a logical address to the card. For MMC, the host assigns the + * address; for SD, the memory card has this responsibility. CMD3 causes + * transition to standby state/data-transfer mode + * + * Send CMD3 with argument 0, SD card publishes its RCA in the response. + */ + + mmcsd_sendcmdpoll(priv, SD_CMD3, 0); + ret = mmcsd_recvR6(priv, SD_CMD3); + if (ret != OK) + { + fdbg("ERROR: mmcsd_recvR2 for SD RCA failed: %d\n", ret); + return ret; + } + fvdbg("RCA: %04x\n", priv->rca); + + /* This should have caused a transition to standby state. However, this will + * not be reflected in the present R1 status. R1/6 contains the state of + * the card when the command was received, not when it completed execution. + * + * Verify that we are in standby state/data-transfer mode + */ + + ret = mmcsd_verifystate(priv, MMCSD_R1_STATE_STBY); + if (ret != OK) + { + fdbg("ERROR: Failed to enter standby state\n"); + return ret; + } + + /* Send CMD9, SEND_CSD, in standby state/data-transfer mode to obtain the + * Card Specific Data (CSD) register. The argument is the RCA that we + * just obtained from CMD3. The card stays in standy state/data-transfer + * mode. + */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD9, (uint32_t)priv->rca << 16); + ret = SDIO_RECVR2(priv->dev, MMCSD_CMD9, csd); + if (ret != OK) + { + fdbg("ERROR: Could not get SD CSD register(%d)\n", ret); + return ret; + } + mmcsd_decodeCSD(priv, csd); + + /* Send CMD7 with the argument == RCA in order to select the card. + * Since we are supporting only a single card, we just leave the + * card selected all of the time. + */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD7S, (uint32_t)priv->rca << 16); + ret = mmcsd_recvR1(priv, MMCSD_CMD7S); + if (ret != OK) + { + fdbg("ERROR: mmcsd_recvR1 for CMD7 failed: %d\n", ret); + return ret; + } + + /* Set the Driver Stage Register (DSR) if (1) a CONFIG_MMCSD_DSR has been + * provided and (2) the card supports a DSR register. If no DSR value + * the card default value (0x0404) will be used. + */ + + (void)mmcsd_sendcmd4(priv); + + /* Select high speed SD clocking (which may depend on the DSR setting) */ + + SDIO_CLOCK(priv->dev, CLOCK_SD_TRANSFER_1BIT); + up_udelay(MMCSD_CLK_DELAY); + + /* Get the SD card Configuration Register (SCR). We need this now because + * that configuration register contains the indication whether or not + * this card supports wide bus operation. + */ + + ret = mmcsd_getSCR(priv, scr); + if (ret != OK) + { + fdbg("ERROR: Could not get SD SCR register(%d)\n", ret); + return ret; + } + mmcsd_decodeSCR(priv, scr); + + /* Select width (4-bit) bus operation (if the card supports it) */ + + ret = mmcsd_widebus(priv); + if (ret != OK) + { + fdbg("WARN: Failed to set wide bus operation: %d\n", ret); + } + + /* TODO: If widebus selected, then send CMD6 to see if the card supports + * high speed mode. A new SDIO method will be needed to set high speed + * mode. + */ + + return OK; +} + +/**************************************************************************** + * Name: mmcsd_cardidentify + * + * Description: + * We believe that there is media in the slot. Attempt to initialize and + * configure the card. This is called only from mmcsd_probe(). + * + ****************************************************************************/ + +static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv) +{ + uint32_t response; + uint32_t start; + uint32_t elapsed; + uint32_t sdcapacity = MMCSD_ACMD41_STDCAPACITY; + int ret; + + /* Assume failure to identify the card */ + + priv->type = MMCSD_CARDTYPE_UNKNOWN; + + /* Check if there is a card present in the slot. This is normally a matter is + * of GPIO sensing. + */ + + if (!SDIO_PRESENT(priv->dev)) + { + fvdbg("No card present\n"); + return -ENODEV; + } + + /* Set ID mode clocking (<400KHz) */ + + SDIO_CLOCK(priv->dev, CLOCK_IDMODE); + + /* After power up at least 74 clock cycles are required prior to starting bus + * communication + */ + + up_udelay(MMCSD_POWERUP_DELAY); + + /* Then send CMD0 (twice just to be sure) */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD0, 0); + mmcsd_sendcmdpoll(priv, MMCSD_CMD0, 0); + up_udelay(MMCSD_IDLE_DELAY); + + /* Check for SDHC Version 2.x. Send CMD8 to verify SD card interface + * operating condition. CMD 8 is reserved on SD version 1.0 and MMC. + * + * CMD8 Argument: + * [31:12]: Reserved (shall be set to '0') * [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V) + * [7:0]: Check Pattern (recommended 0xaa) + * CMD8 Response: R7 + */ + + ret = mmcsd_sendcmdpoll(priv, SD_CMD8, MMCSD_CMD8CHECKPATTERN|MMCSD_CMD8VOLTAGE_27); + if (ret == OK) + { + /* CMD8 was sent successfully... Get the R7 response */ + + ret = SDIO_RECVR7(priv->dev, SD_CMD8, &response); + } + + /* Were both the command sent and response received correctly? */ + + if (ret == OK) + { + /* CMD8 succeeded this is probably a SDHC card. Verify the operating + * voltage and that the check pattern was correctly echoed + */ + + if (((response & MMCSD_R7VOLTAGE_MASK) == MMCSD_R7VOLTAGE_27) && + ((response & MMCSD_R7ECHO_MASK) == MMCSD_R7CHECKPATTERN)) + { + fvdbg("SD V2.x card\n"); + priv->type = MMCSD_CARDTYPE_SDV2; + sdcapacity = MMCSD_ACMD41_HIGHCAPACITY; + } + else + { + fdbg("ERROR: R7: %08x\n", response); + return -EIO; + } + } + + /* At this point, type is either UNKNOWN or SDV2. Try sending + * CMD55 and (maybe) ACMD41 for up to 1 second or until the card + * exits the IDLE state. CMD55 is supported by SD V1.x and SD V2.x, + * but not MMC + */ + + start = clock_systimer(); + elapsed = 0; + do + { + /* We may have already determined that his card is an MMC card from + * an earlier pass through through this loop. In that case, we should + * skip the SD-specific commands. + */ + +#ifdef CONFIG_MMCSD_MMCSUPPORT + if (priv->type != MMCSD_CARDTYPE_MMC) +#endif + { + /* Send CMD55 with argument = 0 */ + + mmcsd_sendcmdpoll(priv, SD_CMD55, 0); + ret = mmcsd_recvR1(priv, SD_CMD55); + if (ret != OK) + { + /* I am a little confused.. I think both SD and MMC cards support + * CMD55 (but maybe only SD cards support CMD55). We'll make the + * the MMC vs. SD decision based on CMD1 and ACMD41. + */ + + fdbg("ERROR: mmcsd_recvR1(CMD55) failed: %d\n", ret); + } + else + { + /* Send ACMD41 */ + + mmcsd_sendcmdpoll(priv, SD_ACMD41, MMCSD_ACMD41_VOLTAGEWINDOW|sdcapacity); + ret = SDIO_RECVR3(priv->dev, SD_ACMD41, &response); + if (ret != OK) + { + /* If the error is a timeout, then it is probably an MMC card, + * but we will make the decision based on CMD1 below + */ + + fdbg("ERROR: ACMD41 RECVR3: %d\n", ret); + } + else + { + /* ACMD41 succeeded. ACMD41 is supported by SD V1.x and SD V2.x, + * but not MMC. If we did not previously determine that this is + * an SD V2.x (via CMD8), then this must be SD V1.x + */ + + fvdbg("R3: %08x\n", response); + if (priv->type == MMCSD_CARDTYPE_UNKNOWN) + { + fvdbg("SD V1.x card\n"); + priv->type = MMCSD_CARDTYPE_SDV1; + } + + /* Check if the card is busy. Very confusing, BUSY is set LOW + * if the card has not finished its initialization, so it really + * means NOT busy. + */ + + if ((response & MMCSD_CARD_BUSY) != 0) + { + /* No.. We really should check the current state to see if + * the SD card successfully made it to the IDLE state, but + * at least for now, we will simply assume that that is the + * case. + * + * Now, check if this is a SD V2.x card that supports block + * addressing + */ + + if ((response & MMCSD_R3_HIGHCAPACITY) != 0) + { + fvdbg("SD V2.x card with block addressing\n"); + DEBUGASSERT(priv->type == MMCSD_CARDTYPE_SDV2); + priv->type |= MMCSD_CARDTYPE_BLOCK; + } + + /* And break out of the loop with an SD card identified */ + + break; + } + } + } + } + + /* If we get here then either (1) CMD55 failed, (2) CMD41 failed, or (3) + * and SD or MMC card has been identified, but it is not yet in the IDLE state. + * If SD card has not been identified, then we might be looking at an + * MMC card. We can send the CMD1 to find out for sure. CMD1 is supported + * by MMC cards, but not by SD cards. + */ +#ifdef CONFIG_MMCSD_MMCSUPPORT + if (priv->type == MMCSD_CARDTYPE_UNKNOWN || priv->type == MMCSD_CARDTYPE_MMC) + { + /* Send the MMC CMD1 to specify the operating voltage. CMD1 causes + * transition to ready state/ card-identification mode. NOTE: If the + * card does not support this voltage range, it will go the inactive + * state. + * + * NOTE: An MMC card will only respond once to CMD1 (unless it is busy). + * This is part of the logic used to determine how many MMC cards are + * connected (This implementation supports only a single MMC card). So + * we cannot re-send CMD1 without first placing the card back into + * stand-by state (if the card is busy, it will automatically + * go back to the the standby state). + */ + + mmcsd_sendcmdpoll(priv, MMC_CMD1, MMCSD_VDD_33_34); + ret = SDIO_RECVR3(priv->dev, MMC_CMD1, &response); + + /* Was the operating range set successfully */ + + if (ret != OK) + { + fdbg("ERROR: CMD1 RECVR3: %d\n", ret); + } + else + { + /* CMD1 succeeded... this must be an MMC card */ + + fdbg("CMD1 succeeded, assuming MMC card\n"); + priv->type = MMCSD_CARDTYPE_MMC; + + /* Check if the card is busy. Very confusing, BUSY is set LOW + * if the card has not finished its initialization, so it really + * means NOT busy. + */ + + if ((response & MMCSD_CARD_BUSY) != 0) + { + /* NO.. We really should check the current state to see if the + * MMC successfully made it to the IDLE state, but at least for now, + * we will simply assume that that is the case. + * + * Then break out of the look with an MMC card identified + */ + + break; + } + } + } +#endif + /* Check the elapsed time. We won't keep trying this forever! */ + + elapsed = clock_systimer() - start; + } + while( elapsed < TICK_PER_SEC ); /* On successful reception while 'breaks', see above. */ + + /* We get here when the above loop completes, either (1) we could not + * communicate properly with the card due to errors (and the loop times + * out), or (3) it is an MMC or SD card that has successfully transitioned + * to the IDLE state (well, at least, it provided its OCR saying that it + * it is no longer busy). + */ + + if (elapsed >= TICK_PER_SEC || priv->type == MMCSD_CARDTYPE_UNKNOWN) + { + fdbg("ERROR: Failed to identify card\n"); + return -EIO; + } + + return OK; +} + +/**************************************************************************** + * Name: mmcsd_probe + * + * Description: + * Check for media inserted in a slot. Called (1) during initialization to + * see if there was a card in the slot at power up, (2) when/if a media + * insertion event occurs, or (3) if the BIOC_PROBE ioctl command is + * received. + * + ****************************************************************************/ + +static int mmcsd_probe(FAR struct mmcsd_state_s *priv) +{ + int ret; + + fvdbg("type: %d probed: %d\n", priv->type, priv->probed); + + /* If we have reliable card detection events and if we have + * already probed the card, then we don't need to do anything + * else + */ + +#ifdef CONFIG_MMCSD_HAVECARDDETECT + if (priv->probed && SDIO_PRESENT(priv->dev)) + { + return OK; + } +#endif + + /* Otherwise, we are going to probe the card. There are lots of + * possibilities here: We may think that there is a card in the slot, + * or not. There may be a card in the slot, or not. If there is + * card in the slot, perhaps it is a different card than we one we + * think is there? The safest thing to do is to process the card + * removal first and start from known place. + */ + + mmcsd_removed(priv); + + /* Now.. is there a card in the slot? */ + + if (SDIO_PRESENT(priv->dev)) + { + /* Yes.. probe it. First, what kind of card was inserted? */ + + ret = mmcsd_cardidentify(priv); + if (ret != OK) + { + fdbg("ERROR: Failed to initialize card: %d\n", ret); +#ifdef CONFIG_MMCSD_HAVECARDDETECT + SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED); +#endif + } + else + { + /* Then initialize the driver according to the identified card type */ + + switch (priv->type) + { + case MMCSD_CARDTYPE_SDV1: /* Bit 1: SD version 1.x */ + case MMCSD_CARDTYPE_SDV2: /* SD version 2.x with byte addressing */ + case MMCSD_CARDTYPE_SDV2|MMCSD_CARDTYPE_BLOCK: /* SD version 2.x with block addressing */ + ret = mmcsd_sdinitialize(priv); + break; + + case MMCSD_CARDTYPE_MMC: /* MMC card */ +#ifdef CONFIG_MMCSD_MMCSUPPORT + ret = mmcsd_mmcinitialize(priv); + break; +#endif + case MMCSD_CARDTYPE_UNKNOWN: /* Unknown card type */ + default: + fdbg("ERROR: Internal confusion: %d\n", priv->type); + ret = -EPERM; + break; + }; + + /* Was the card configured successfully? */ + + if (ret == OK) + { + /* Yes... */ + + fvdbg("Capacity: %lu Kbytes\n", (unsigned long)(priv->capacity / 1024)); + priv->mediachanged = true; + + /* Set up to receive asynchronous, media removal events */ + + SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_EJECTED); + } + } + + /* In any event, we have probed this card */ + + priv->probed = true; + } + else + { + /* There is no card in the slot */ + + fvdbg("No card\n"); +#ifdef CONFIG_MMCSD_HAVECARDDETECT + SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED); +#endif + ret = -ENODEV; + } + + return ret; +} + +/**************************************************************************** + * Name: mmcsd_removed + * + * Description: + * Disable support for media in the slot. Called (1) when/if a media + * removal event occurs, or (2) if the BIOC_EJECT ioctl command is + * received. + * + ****************************************************************************/ + +static int mmcsd_removed(FAR struct mmcsd_state_s *priv) +{ + fvdbg("type: %d present: %d\n", priv->type, SDIO_PRESENT(priv->dev)); + + /* Forget the card geometry, pretend the slot is empty (it might not + * be), and that the card has never been initialized. + */ + + priv->capacity = 0; /* Capacity=0 sometimes means no media */ + priv->blocksize = 0; + priv->mediachanged = false; + priv->type = MMCSD_CARDTYPE_UNKNOWN; + priv->probed = false; + priv->rca = 0; + priv->selblocklen = 0; + + /* Go back to the default 1-bit data bus. */ + + SDIO_WIDEBUS(priv->dev, false); + priv->widebus = false; + + /* Disable clocking to the card */ + + (void)SDIO_CLOCK(priv->dev, CLOCK_SDIO_DISABLED); + return OK; +} + +/**************************************************************************** + * Name: mmcsd_hwinitialize + * + * Description: + * One-time hardware initialization. Called only from sdio_slotinitialize. + * + ****************************************************************************/ + +static int mmcsd_hwinitialize(FAR struct mmcsd_state_s *priv) +{ + int ret; + + mmcsd_takesem(priv); + +#ifdef CONFIG_SDIO_DMA + /* Does this architecture support DMA with the MMC/SD device? */ + + priv->dma = SDIO_DMASUPPORTED(priv->dev); + fvdbg("DMA supported: %d\n", priv->dma); +#endif + + /* Attach and prepare MMC/SD interrupts */ + + if (SDIO_ATTACH(priv->dev)) + { + fdbg("ERROR: Unable to attach MMC/SD interrupts\n"); + mmcsd_givesem(priv); + return -EBUSY; + } + fvdbg("Attached MMC/SD interrupts\n"); + + /* Register a callback so that we get informed if media is inserted or + * removed from the slot (Initially all callbacks are disabled). + */ + + SDIO_REGISTERCALLBACK(priv->dev, mmcsd_mediachange, (FAR void *)priv); + + /* Is there a card in the slot now? For an MMC/SD card, there are three + * possible card detect mechanisms: + * + * 1. Mechanical insertion that can be detected using the WP switch + * that is closed when a card is inserted into then SD slot (SD + * "hot insertion capable" card conector only) + * 2. Electrical insertion that can be sensed using the pull-up resistor + * on CD/DAT3 (both SD/MMC), + * 3. Or by periodic attempts to initialize the card from software. + * + * The behavior of SDIO_PRESENT() is to use whatever information is available + * on the particular platform. If no card insertion information is available + * (polling only), then SDIO_PRESENT() will always return true and we will + * try to initialize the card. + */ + + if (SDIO_PRESENT(priv->dev)) + { + /* Yes... probe for a card in the slot */ + + ret = mmcsd_probe(priv); + if (ret != OK) + { + fvdbg("Slot not empty, but initialization failed: %d\n", ret); + + /* NOTE: The failure to initialize a card does not mean that + * initialization has failed! A card could be installed in the slot + * at a later time. ENODEV is return in this case, + * sdio_slotinitialize will use this return value to set up the + * card inserted callback event. + */ + + ret = -ENODEV; + } + } + else + { + /* ENODEV is returned to indicate that no card is inserted in the slot. + * sdio_slotinitialize will use this return value to set up the card + * inserted callback event. + */ + + ret = -ENODEV; + } + + /* OK is returned only if the slot initialized correctly AND the card in + * the slot was successfully configured. + */ + + mmcsd_givesem(priv); + return ret; +} + +/**************************************************************************** + * Name: mmcsd_hwuninitialize + * + * Description: + * Restore the MMC/SD slot to the uninitialized state. Called only from + * sdio_slotinitialize on a failure to initialize. + * + ****************************************************************************/ + +static void mmcsd_hwuninitialize(FAR struct mmcsd_state_s *priv) +{ + if (priv) + { + mmcsd_removed(priv); + SDIO_RESET(priv->dev); + kfree(priv); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mmcsd_slotinitialize + * + * Description: + * Initialize one slot for operation using the MMC/SD interface + * + * Input Parameters: + * minor - The MMC/SD minor device number. The MMC/SD device will be + * registered as /dev/mmcsdN where N is the minor number + * dev - And instance of an MMC/SD interface. The MMC/SD hardware should + * be initialized and ready to use. + * + ****************************************************************************/ + +int mmcsd_slotinitialize(int minor, FAR struct sdio_dev_s *dev) +{ + FAR struct mmcsd_state_s *priv; + char devname[16]; + int ret = -ENOMEM; + + fvdbg("minor: %d\n", minor); + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (minor < 0 || minor > 255 || !dev) + { + return -EINVAL; + } +#endif + + /* Allocate a MMC/SD state structure */ + + priv = (FAR struct mmcsd_state_s *)kmalloc(sizeof(struct mmcsd_state_s)); + if (priv) + { + /* Initialize the MMC/SD state structure */ + + memset(priv, 0, sizeof(struct mmcsd_state_s)); + sem_init(&priv->sem, 0, 1); + + /* Bind the MMCSD driver to the MMCSD state structure */ + + priv->dev = dev; + + /* Initialize the hardware associated with the slot */ + + ret = mmcsd_hwinitialize(priv); + + /* Was the slot initialized successfully? */ + + if (ret != OK) + { + /* No... But the error ENODEV is returned if hardware initialization + * succeeded but no card is inserted in the slot. In this case, the + * no error occurred, but the driver is still not ready. + */ + + if (ret == -ENODEV) + { + /* No card in the slot (or if there is, we could not recognize + * it).. Setup to receive the media inserted event + */ + + SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED); + + fdbg("MMC/SD slot is empty\n"); + } + else + { + /* Some other non-recoverable bad thing happened */ + + fdbg("ERROR: Failed to initialize MMC/SD slot: %d\n", ret); + goto errout_with_alloc; + } + } + + /* Initialize buffering */ + +#if defined(CONFIG_FS_WRITEBUFFER) || defined(CONFIG_FS_READAHEAD) + + ret = rwb_initialize(&priv->rwbuffer); + if (ret < 0) + { + fdbg("ERROR: Buffer setup failed: %d\n", ret); + goto errout_with_hwinit; + } +#endif + + /* Create a MMCSD device name */ + + snprintf(devname, 16, "/dev/mmcsd%d", minor); + + /* Inode private data is a reference to the MMCSD state structure */ + + ret = register_blockdriver(devname, &g_bops, 0, priv); + if (ret < 0) + { + fdbg("ERROR: register_blockdriver failed: %d\n", ret); + goto errout_with_buffers; + } + } + return OK; + +errout_with_buffers: +#if defined(CONFIG_FS_WRITEBUFFER) || defined(CONFIG_FS_READAHEAD) + rwb_uninitialize(&priv->rwbuffer); +errout_with_hwinit: +#endif + mmcsd_hwuninitialize(priv); +errout_with_alloc: + kfree(priv); + return ret; +} diff --git a/nuttx/drivers/mmcsd/mmcsd_sdio.h b/nuttx/drivers/mmcsd/mmcsd_sdio.h new file mode 100644 index 0000000000..75c97bd65a --- /dev/null +++ b/nuttx/drivers/mmcsd/mmcsd_sdio.h @@ -0,0 +1,339 @@ +/******************************************************************************************** + * drivers/mmcsd/mmcsd_sdio.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __DRIVERS_MMCSD_MMCSD_SDIO_H +#define __DRIVERS_MMCSD_MMCSD_SDIO_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include +#include + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ + +/* CMD8 Argument: + * [31:12]: Reserved (shall be set to '0') + * [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V) + * [7:0]: Check Pattern (recommended 0xaa) + * CMD8 Response: R7 + */ + +#define MMCSD_CMD8VOLTAGE_SHIFT (8) /* Bits 8-11: Supply voltage */ +#define MMCSD_CMD8VOLTAGE_MASK ((uint32_t)0x0f << MMCSD_CMD8VOLTAGE_SHIFT) +# define MMCSD_CMD8VOLTAGE_27 ((uint32_t)0x01 << MMCSD_CMD8VOLTAGE_SHIFT) /* 2.7-3.6V */ +#define MMCSD_CMD8ECHO_SHIFT (0) /* Bits 0-7: Check pattern */ +#define MMCSD_CMD8ECHO_MASK ((uint32_t)0xff << MMCSD_CMD8ECHO_SHIFT) +# define MMCSD_CMD8CHECKPATTERN ((uint32_t)0xaa << MMCSD_CMD8ECHO_SHIFT) + +/* ACMD6 argument */ + +#define MMCSD_ACMD6_BUSWIDTH_1 ((uint32_t)0) /* Bus width = 1-bit */ +#define MMCSD_ACMD6_BUSWIDTH_4 ((uint32_t)2) /* Bus width = 4-bit */ + +/* ACMD41 argument */ + +#define MMCSD_ACMD41_VOLTAGEWINDOW ((uint32_t)0x80100000) +#define MMCSD_ACMD41_HIGHCAPACITY ((uint32_t)1 << 30) +#define MMCSD_ACMD41_STDCAPACITY ((uint32_t)0) + +/* ACMD42 argument */ + +#define MMCSD_ACMD42_CD_DISCONNECT ((uint32_t)0) /* Disconnect card detection logic */ +#define MMCSD_ACMD42_CD_CONNECT ((uint32_t)1) /* Connect card detection logic */ + +/* R1 Card Status bit definitions */ + +#define MMCSD_R1_OUTOFRANGE ((uint32_t)1 << 31) /* Bad argument */ +#define MMCSD_R1_ADDRESSERROR ((uint32_t)1 << 30) /* Bad address */ +#define MMCSD_R1_BLOCKLENERROR ((uint32_t)1 << 29) /* Bad block length */ +#define MMCSD_R1_ERASESEQERROR ((uint32_t)1 << 28) /* Erase cmd error */ +#define MMCSD_R1_ERASEPARAM ((uint32_t)1 << 27) /* Bad write blocks */ +#define MMCSD_R1_WPVIOLATION ((uint32_t)1 << 26) /* Erase access failure */ +#define MMCSD_R1_CARDISLOCKED ((uint32_t)1 << 25) /* Card is locked */ +#define MMCSD_R1_LOCKUNLOCKFAILED ((uint32_t)1 << 24) /* Password error */ +#define MMCSD_R1_COMCRCERROR ((uint32_t)1 << 23) /* CRC error */ +#define MMCSD_R1_ILLEGALCOMMAND ((uint32_t)1 << 22) /* Bad command */ +#define MMCSD_R1_CARDECCFAILED ((uint32_t)1 << 21) /* Failed to correct data */ +#define MMCSD_R1_CCERROR ((uint32_t)1 << 20) /* Card controller error */ +#define MMCSD_R1_ERROR ((uint32_t)1 << 19) /* General error */ +#define MMCSD_R1_UNDERRUN ((uint32_t)1 << 18) /* Underrun (MMC only) */ +#define MMCSD_R1_OVERRRUN ((uint32_t)1 << 17) /* Overrun (MMC only) */ +#define MMCSD_R1_CIDCSDOVERWRITE ((uint32_t)1 << 16) /* CID/CSD error */ +#define MMCSD_R1_WPERASESKIP ((uint32_t)1 << 15) /* Not all erased */ +#define MMCSD_R1_CARDECCDISABLED ((uint32_t)1 << 14) /* Internal ECC not used */ +#define MMCSD_R1_ERASERESET ((uint32_t)1 << 13) /* Reset sequence cleared */ +#define MMCSD_R1_STATE_SHIFT (9) /* Current card state */ +#define MMCSD_R1_STATE_MASK ((uint32_t)15 << MMCSD_R1_STATE_SHIFT) + /* Card identification mode states */ +# define MMCSD_R1_STATE_IDLE ((uint32_t)0 << MMCSD_R1_STATE_SHIFT) /* 0=Idle state */ +# define MMCSD_R1_STATE_READY ((uint32_t)1 << MMCSD_R1_STATE_SHIFT) /* 1=Ready state */ +# define MMCSD_R1_STATE_IDENT ((uint32_t)2 << MMCSD_R1_STATE_SHIFT) /* 2=Identification state */ + /* Data transfer states */ +# define MMCSD_R1_STATE_STBY ((uint32_t)3 << MMCSD_R1_STATE_SHIFT) /* 3=Standby state */ +# define MMCSD_R1_STATE_TRAN ((uint32_t)4 << MMCSD_R1_STATE_SHIFT) /* 4=Transfer state */ +# define MMCSD_R1_STATE_DATA ((uint32_t)5 << MMCSD_R1_STATE_SHIFT) /* 5=Sending data state */ +# define MMCSD_R1_STATE_RCV ((uint32_t)6 << MMCSD_R1_STATE_SHIFT) /* 6=Receiving data state */ +# define MMCSD_R1_STATE_PRG ((uint32_t)7 << MMCSD_R1_STATE_SHIFT) /* 7=Programming state */ +# define MMCSD_R1_STATE_DIS ((uint32_t)8 << MMCSD_R1_STATE_SHIFT) /* 8=Disconnect state */ +#define MMCSD_R1_READYFORDATA ((uint32_t)1 << 8) /* Buffer empty */ +#define MMCSD_R1_APPCMD ((uint32_t)1 << 5) /* Next CMD is ACMD */ +#define MMCSD_R1_AKESEQERROR ((uint32_t)1 << 3) /* Authentication error */ +#define MMCSD_R1_ERRORMASK ((uint32_t)0xfdffe008) /* Error mask */ + +#define IS_STATE(v,s) ((((uint32_t)v)&MMCSD_R1_STATE_MASK)==(s)) + +/* R3 (OCR) */ + +#define MMC_VDD_20_36 ((uint32_t)0x00ffff00) /* VDD voltage 2.0-3.6 */ + +#define MMCSD_VDD_145_150 ((uint32_t)1 << 0) /* VDD voltage 1.45 - 1.50 */ +#define MMCSD_VDD_150_155 ((uint32_t)1 << 1) /* VDD voltage 1.50 - 1.55 */ +#define MMCSD_VDD_155_160 ((uint32_t)1 << 2) /* VDD voltage 1.55 - 1.60 */ +#define MMCSD_VDD_160_165 ((uint32_t)1 << 3) /* VDD voltage 1.60 - 1.65 */ +#define MMCSD_VDD_165_170 ((uint32_t)1 << 4) /* VDD voltage 1.65 - 1.70 */ +#define MMCSD_VDD_17_18 ((uint32_t)1 << 5) /* VDD voltage 1.7 - 1.8 */ +#define MMCSD_VDD_18_19 ((uint32_t)1 << 6) /* VDD voltage 1.8 - 1.9 */ +#define MMCSD_VDD_19_20 ((uint32_t)1 << 7) /* VDD voltage 1.9 - 2.0 */ +#define MMCSD_VDD_20_21 ((uint32_t)1 << 8) /* VDD voltage 2.0-2.1 */ +#define MMCSD_VDD_21_22 ((uint32_t)1 << 9) /* VDD voltage 2.1-2.2 */ +#define MMCSD_VDD_22_23 ((uint32_t)1 << 10) /* VDD voltage 2.2-2.3 */ +#define MMCSD_VDD_23_24 ((uint32_t)1 << 11) /* VDD voltage 2.3-2.4 */ +#define MMCSD_VDD_24_25 ((uint32_t)1 << 12) /* VDD voltage 2.4-2.5 */ +#define MMCSD_VDD_25_26 ((uint32_t)1 << 13) /* VDD voltage 2.5-2.6 */ +#define MMCSD_VDD_26_27 ((uint32_t)1 << 14) /* VDD voltage 2.6-2.7 */ +#define MMCSD_VDD_27_28 ((uint32_t)1 << 15) /* VDD voltage 2.7-2.8 */ +#define MMCSD_VDD_28_29 ((uint32_t)1 << 16) /* VDD voltage 2.8-2.9 */ +#define MMCSD_VDD_29_30 ((uint32_t)1 << 17) /* VDD voltage 2.9-3.0 */ +#define MMCSD_VDD_30_31 ((uint32_t)1 << 18) /* VDD voltage 3.0-3.1 */ +#define MMCSD_VDD_31_32 ((uint32_t)1 << 19) /* VDD voltage 3.1-3.2 */ +#define MMCSD_VDD_32_33 ((uint32_t)1 << 20) /* VDD voltage 3.2-3.3 */ +#define MMCSD_VDD_33_34 ((uint32_t)1 << 21) /* VDD voltage 3.3-3.4 */ +#define MMCSD_VDD_34_35 ((uint32_t)1 << 22) /* VDD voltage 3.4-3.5 */ +#define MMCSD_VDD_35_36 ((uint32_t)1 << 23) /* VDD voltage 3.5-3.6 */ +#define MMCSD_R3_HIGHCAPACITY ((uint32_t)1 << 30) /* true: Card supports block addressing */ +#define MMCSD_CARD_BUSY ((uint32_t)1 << 31) /* Card power-up busy bit */ + +/* R6 Card Status bit definitions */ + +#define MMCSD_R6_RCA_SHIFT (16) /* New published RCA */ +#define MMCSD_R6_RCA_MASK ((uint32_t)0xffff << MMCSD_R6_RCA_SHIFT) +#define MMCSD_R6_COMCRCERROR ((uint32_t)1 << 15) /* CRC error */ +#define MMCSD_R6_ILLEGALCOMMAND ((uint32_t)1 << 14) /* Bad command */ +#define MMCSD_R6_ERROR ((uint32_t)1 << 13) /* General error */ +#define MMCSD_R6_STATE_SHIFT (9) /* Current card state */ +#define MMCSD_R6_STATE_MASK ((uint32_t)15 << MMCSD_R6_STATE_SHIFT) + /* Card identification mode states */ +# define MMCSD_R6_STATE_IDLE ((uint32_t)0 << MMCSD_R6_STATE_SHIFT) /* 0=Idle state */ +# define MMCSD_R6_STATE_READY ((uint32_t)1 << MMCSD_R6_STATE_SHIFT) /* 1=Ready state */ +# define MMCSD_R6_STATE_IDENT ((uint32_t)2 << MMCSD_R6_STATE_SHIFT) /* 2=Identification state */ + /* Data transfer states */ +# define MMCSD_R6_STATE_STBY ((uint32_t)3 << MMCSD_R6_STATE_SHIFT) /* 3=Standby state */ +# define MMCSD_R6_STATE_TRAN ((uint32_t)4 << MMCSD_R6_STATE_SHIFT) /* 4=Transfer state */ +# define MMCSD_R6_STATE_DATA (5(uint32_t) << MMCSD_R6_STATE_SHIFT) /* 5=Sending data state */ +# define MMCSD_R6_STATE_RCV ((uint32_t)6 << MMCSD_R6_STATE_SHIFT) /* 6=Receiving data state */ +# define MMCSD_R6_STATE_PRG ((uint32_t)7 << MMCSD_R6_STATE_SHIFT) /* 7=Programming state */ +# define MMCSD_R6_STATE_DIS ((uint32_t) << MMCSD_R6_STATE_SHIFT) /* 8=Disconnect state */ +#define MMCSD_R6_ERRORMASK ((uint32_t)0x0000e000) /* Error mask */ + +/* SD Configuration Register (SCR) encoding */ + +#define MMCSD_SCR_BUSWIDTH_1BIT (1) +#define MMCSD_SCR_BUSWIDTH_2BIT (2) +#define MMCSD_SCR_BUSWIDTH_4BIT (4) +#define MMCSD_SCR_BUSWIDTH_8BIT (8) + +/* Last 4 bytes of the 48-bit R7 response */ + +#define MMCSD_R7VERSION_SHIFT (28) /* Bits 28-31: Command version number */ +#define MMCSD_R7VERSION_MASK ((uint32_t)0x0f << MMCSD_R7VERSION_SHIFT) +#define MMCSD_R7VOLTAGE_SHIFT (8) /* Bits 8-11: Voltage accepted */ +#define MMCSD_R7VOLTAGE_MASK ((uint32_t)0x0f << MMCSD_R7VOLTAGE_SHIFT) +# define MMCSD_R7VOLTAGE_27 ((uint32_t)0x01 << MMCSD_R7VOLTAGE_SHIFT) /* 2.7-3.6V */ +#define MMCSD_R7ECHO_SHIFT (0) /* Bits 0-7: Echoed check pattern */ +#define MMCSD_R7ECHO_MASK ((uint32_t)0xff << MMCSD_R7ECHO_SHIFT) +# define MMCSD_R7CHECKPATTERN ((uint32_t)0xaa << MMCSD_R7ECHO_SHIFT) + +/******************************************************************************************** + * Public Types + ********************************************************************************************/ + +/* Decoded Card Identification (CID) register */ + +struct mmcsd_cid_s +{ + uint8_t mid; /* 127:120 8-bit Manufacturer ID */ + uint16_t oid; /* 119:104 16-bit OEM/Application ID (ascii) */ + uint8_t pnm[6]; /* 103:64 40-bit Product Name (ascii) + null terminator */ + uint8_t prv; /* 63:56 8-bit Product revision */ + uint32_t psn; /* 55:24 32-bit Product serial number */ + /* 23:20 4-bit (reserved) */ + uint16_t mdt; /* 19:8 12-bit Manufacturing date */ + uint8_t crc; /* 7:1 7-bit CRC7 */ + /* 0:0 1-bit (not used) */ +}; + +/* Decoded Card Specific Data (CSD) register */ + +struct mmcsd_csd_s +{ + uint8_t csdstructure; /* 127:126 CSD structure */ + uint8_t mmcspecvers; /* 125:122 MMC Spec version (MMC only) */ + + struct + { + uint8_t timeunit; /* 2:0 Time exponent */ + uint8_t timevalue; /* 6:3 Time mantissa */ + } taac; /* 119:112 Data read access-time-1 */ + + uint8_t nsac; /* 111:104 Data read access-time-2 in CLK cycle(NSAC*100) */ + + struct + { + uint8_t transferrateunit; /* 2:0 Rate exponent */ + uint8_t timevalue; /* 6:3 Rate mantissa */ + } transpeed; /* 103:96 Max. data transfer rate */ + + uint16_t ccc; /* 95:84 Card command classes */ + uint8_t readbllen; /* 83:80 Max. read data block length */ + uint8_t readblpartial; /* 79:79 Partial blocks for read allowed */ + uint8_t writeblkmisalign; /* 78:78 Write block misalignment */ + uint8_t readblkmisalign; /* 77:77 Read block misalignment */ + uint8_t dsrimp; /* 76:76 DSR implemented */ + + union + { +#ifdef CONFIG_MMCSD_MMCSUPPORT + struct + { + uint16_t csize; /* 73:62 Device size */ + uint8_t vddrcurrmin; /* 61:59 Max. read current at Vdd min */ + uint8_t vddrcurrmax; /* 58:56 Max. read current at Vdd max */ + uint8_t vddwcurrmin; /* 55:53 Max. write current at Vdd min */ + uint8_t vddwcurrmax; /* 52:50 Max. write current at Vdd max */ + uint8_t csizemult; /* 49:47 Device size multiplier */ + + union + { + struct /* MMC system specification version 3.1 */ + { + uint8_t ergrpsize; /* 46:42 Erase group size (MMC 3.1) */ + uint8_t ergrpmult; /* 41:37 Erase group multiplier (MMC 3.1) */ + } mmc31; + struct /* MMC system specification version 2.2 */ + { + uint8_t sectorsize; /* 46:42 Erase sector size (MMC 2.2) */ + uint8_t ergrpsize; /* 41:37 Erase group size (MMC 2.2) */ + } mmc22; + } er; + + uint8_t mmcwpgrpsize; /* 36:32 Write protect group size (MMC) */ + } mmc; +#endif + struct + { + uint16_t csize; /* 73:62 Device size */ + uint8_t vddrcurrmin; /* 61:59 Max. read current at Vdd min */ + uint8_t vddrcurrmax; /* 58:56 Max. read current at Vdd max */ + uint8_t vddwcurrmin; /* 55:53 Max. write current at Vdd min */ + uint8_t vddwcurrmax; /* 52:50 Max. write current at Vdd max */ + uint8_t csizemult; /* 49:47 Device size multiplier */ + uint8_t sderblen; /* 46:46 Erase single block enable (SD) */ + uint8_t sdsectorsize; /* 45:39 Erase sector size (SD) */ + uint8_t sdwpgrpsize; /* 38:32 Write protect group size (SD) */ + } sdbyte; + + struct + { + /* 73:70 (reserved) */ + uint32_t csize; /* 69:48 Device size */ + /* 47:47 (reserved) */ + uint8_t sderblen; /* 46:46 Erase single block enable (SD) */ + uint8_t sdsectorsize; /* 45:39 Erase sector size (SD) */ + uint8_t sdwpgrpsize; /* 38:32 Write protect group size (SD) */ + } sdblock; + } u; + + uint8_t wpgrpen; /* 31:31 Write protect group enable */ + uint8_t mmcdfltecc; /* 30:29 Manufacturer default ECC (MMC) */ + uint8_t r2wfactor; /* 28:26 Write speed factor */ + uint8_t writebllen; /* 25:22 Max. write data block length */ + uint8_t writeblpartial; /* 21:21 Partial blocks for write allowed */ + uint8_t fileformatgrp; /* 15:15 File format group */ + uint8_t copy; /* 14:14 Copy flag (OTP) */ + uint8_t permwriteprotect; /* 13:13 Permanent write protection */ + uint8_t tmpwriteprotect; /* 12:12 Temporary write protection */ + uint8_t fileformat; /* 10:11 File format */ + uint8_t mmcecc; /* 9:8 ECC (MMC) */ + uint8_t crc; /* 7:1 CRC */ + /* 0:0 Not used */ +}; + +struct mmcsd_scr_s +{ + uint8_t scrversion; /* 63:60 Version of SCR structure */ + uint8_t sdversion; /* 59:56 SD memory card physical layer version */ + uint8_t erasestate; /* 55:55 Data state after erase (1 or 0) */ + uint8_t security; /* 54:52 SD security support */ + uint8_t buswidth; /* 51:48 DAT bus widthes supported */ + /* 47:32 SD reserved space */ + uint32_t mfgdata; /* 31:0 Reserved for manufacturing data */ +}; + +/******************************************************************************************** + * Public Data + ********************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/******************************************************************************************** + * Public Functions + ********************************************************************************************/ + + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __DRIVERS_MMCSD_MMCSD_SDIO_H */ diff --git a/nuttx/drivers/mmcsd/mmcsd_spi.c b/nuttx/drivers/mmcsd/mmcsd_spi.c new file mode 100644 index 0000000000..7dbadc55fe --- /dev/null +++ b/nuttx/drivers/mmcsd/mmcsd_spi.c @@ -0,0 +1,1878 @@ +/**************************************************************************** + * drivers/mmcsd/mmcsd_spi.c + * + * Copyright (C) 2008-2010, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mmcsd_spi.h" +#include "mmcsd_csd.h" +#include "mmcsd_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_MMCSD_NSLOTS +# ifdef CONFIG_CPP_HAVE_WARNING +# warning "CONFIG_MMCSD_NSLOTS not defined" +# endif +# define CONFIG_MMCSD_NSLOTS 1 +#endif + +#define MMCSD_IDMODE_CLOCK (400000) + +#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_READONLY) +# define MMCSD_MODE 0666 +#else +# define MMCSD_MODE 0444 +#endif + +#ifndef CONFIG_MMCSD_SPICLOCK +# define CONFIG_MMCSD_SPICLOCK 20000000 +#endif + +#ifndef CONFIG_MMCSD_SECTOR512 +# define CONFIG_MMCSD_SECTOR512 /* Force 512 byte sectors on all cards */ +#endif + +/* Slot struct info *********************************************************/ +/* Slot status definitions */ + +#define MMCSD_SLOTSTATUS_NOTREADY 0x01 /* Card not initialized */ +#define MMCSD_SLOTSTATUS_NODISK 0x02 /* No card in the slot */ +#define MMCSD_SLOTSTATUS_WRPROTECT 0x04 /* Card is write protected */ +#define MMCSD_SLOTSTATUS_MEDIACHGD 0x08 /* Media changed in slot */ + +/* Values in the MMC/SD command table ***************************************/ +/* These define the value returned by the MMC/SD command */ + +#define MMCSD_CMDRESP_R1 0 +#define MMCSD_CMDRESP_R1B 1 +#define MMCSD_CMDRESP_R2 2 +#define MMCSD_CMDRESP_R3 3 +#define MMCSD_CMDRESP_R7 4 + +#ifdef CONFIG_MMCSD_SECTOR512 +# define SECTORSIZE(s) (512) +#else +# define SECTORSIZE(s) ((s)->sectorsize) +#endif + +/* Time delays in units of the system clock. CLK_TCK is the number of clock + * ticks per second. + */ + +#define MMCSD_DELAY_10MS (CLK_TCK/100 + 1) +#define MMCSD_DELAY_50MS (CLK_TCK/20 + 1) +#define MMCSD_DELAY_100MS (CLK_TCK/10 + 1) +#define MMCSD_DELAY_250MS (CLK_TCK/4 + 1) +#define MMCSD_DELAY_500MS (CLK_TCK/2 + 1) +#define MMCSD_DELAY_1SEC (CLK_TCK + 1) +#define MMCSD_DELAY_10SEC (10 * CLK_TCK + 1) + +#define ELAPSED_TIME(t) (clock_systimer()-(t)) +#define START_TIME (clock_systimer()) + +/* SD read timeout: ~100msec, Write Time out ~250ms. Units of clock ticks */ + +#define SD_READACCESS MMCSD_DELAY_100MS +#define SD_WRITEACCESS MMCSD_DELAY_250MS + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure represents the state of one card slot */ + +struct mmcsd_slot_s +{ + FAR struct spi_dev_s *spi; /* SPI port bound to this slot */ + sem_t sem; /* Assures mutually exclusive accesss to card and SPI */ + uint8_t state; /* State of the slot (see MMCSD_SLOTSTATUS_* definitions) */ + uint8_t type; /* Disk type */ + uint8_t csd[16]; /* Copy of card CSD */ +#ifndef CONFIG_MMCSD_SECTOR512 + uint16_t sectorsize; /* Media block size (in bytes) */ +#endif + uint32_t nsectors; /* Number of blocks on the media */ + uint32_t taccess; /* Card access time */ + uint32_t twrite; /* Card write time */ + uint32_t ocr; /* Last 4 bytes of OCR (R3) */ + uint32_t r7; /* Last 4 bytes of R7 */ +}; + +struct mmcsd_cmdinfo_s +{ + uint8_t cmd; + uint8_t resp; + uint8_t chksum; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Misc *********************************************************************/ + +static void mmcsd_semtake(sem_t *sem); + +/* Card SPI interface *******************************************************/ + +static int mmcsd_waitready(FAR struct mmcsd_slot_s *slot); +static uint32_t mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot, + const struct mmcsd_cmdinfo_s *cmd, uint32_t arg); +static void mmcsd_setblklen(FAR struct mmcsd_slot_s *slot, + uint32_t length); +static uint32_t mmcsd_nsac(FAR struct mmcsd_slot_s *slot, uint8_t *csd, + uint32_t frequency); +static uint32_t mmcsd_taac(FAR struct mmcsd_slot_s *slot, uint8_t *csd); +static void mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, uint8_t *csd); +static void mmcsd_checkwrprotect(FAR struct mmcsd_slot_s *slot, + uint8_t *csd); +static int mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, + uint8_t *buffer, const struct mmcsd_cmdinfo_s *cmd); + +#define mmcsd_getcsd(slot, csd) mmcsd_getcardinfo(slot, csd, &g_cmd9); +#define mmcsd_getcid(slot, cid) mmcsd_getcardinfo(slot, cid, &g_cmd10); + +static int mmcsd_recvblock(FAR struct mmcsd_slot_s *slot, + uint8_t *buffer, int nbytes); +#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_READONLY) +static int mmcsd_xmitblock(FAR struct mmcsd_slot_s *slot, + const uint8_t *buffer, int nbytes, uint8_t token); +#endif + +/* Block driver interfaces **************************************************/ + +static int mmcsd_open(FAR struct inode *inode); +static int mmcsd_close(FAR struct inode *inode); +static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer, + size_t start_sector, unsigned int nsectors); +#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_READONLY) +static ssize_t mmcsd_write(FAR struct inode *inode, + const unsigned char *buffer, size_t start_sector, + unsigned int nsectors); +#endif +static int mmcsd_geometry(FAR struct inode *inode, + struct geometry *geometry); + +/* Initialization ***********************************************************/ + +static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot); +static void mmcsd_mediachanged(void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Driver state *************************************************************/ + +/* These are the lock driver methods supported by this file */ + +static const struct block_operations g_bops = +{ + mmcsd_open, /* open */ + mmcsd_close, /* close */ + mmcsd_read, /* read */ +#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_READONLY) + mmcsd_write, /* write */ +#else + NULL, /* write */ +#endif + mmcsd_geometry, /* geometry */ + NULL /* ioctl */ +}; + +/* A slot structure allocated for each configured slot */ + +static struct mmcsd_slot_s g_mmcsdslot[CONFIG_MMCSD_NSLOTS]; + +/* Timing *******************************************************************/ + +/* We will use the TRAN_SPEED from the CSD to determine the maximum SPI + * clocking (TRAN_SPEED defines the maximum transfer rate per bit per data + * line). + * + * The CSD TRAN_SPEED is provided as a 3 bit rate unit (RU) and a 4 bit time + * value (TU). We need the transfer frequency which is: RU*TU bits/sec + * + * g_transpeedru holds RU/10 and g_transpeedtu holds TU*10 so that the + * correct value is returned in the product + */ + +static const uint32_t g_transpeedru[8] = +{ + 10000, /* 0: 10 Kbit/sec / 10 */ + 100000, /* 1: 1 Mbit/sec / 10 */ + 1000000, /* 2: 10 Mbit/sec / 10 */ + 10000000, /* 3: 100 Mbit/sec / 10*/ + + 0, 0, 0, 0 /* 4-7: Reserved values */ +}; + +static const uint32_t g_transpeedtu[16] = +{ + 0, 10, 12, 13, /* 0-3: Reserved, 1.0, 1.1, 1.2, 1.3 */ + 15, 20, 25, 30, /* 4-7: 1.5, 2.0, 2.5, 3.0 */ + 35, 40, 45, 50, /* 8-11: 3.5, 4.0, 4.5, 5.0 */ + 55, 60, 70, 80, /* 12-15: 5.5, 6.0, 7.0, 8.0 */ +}; + +/* The TAAC defines the asynchronous part of the data access time. The + * read access time the sum of the TAAC and the NSAC. These define the + * time from the end bit of the read command to start bit of the data block. + * + * The TAAC consists of a 3-bit time unit (TU) and a 4-bit time value (TV). + * TAAC is in units of time; NSAC is in units of SPI clocks. + * The access time we need is then given by: + * + * taccess = TU*TV + NSAC/spifrequency + * + * g_taactu holds TU in units of nanoseconds and microseconds (you have to use + * the index to distiguish). g_taactv holds TV with 8-bits of fraction. + */ + +#define MAX_USTUNDX 2 +static const uint16_t g_taactu[8] = +{ + /* Units of nanoseconds */ + + 1, /* 0: 1 ns */ + 10, /* 1: 10 ns */ + 100, /* 2: 100 ns */ + + /* Units of microseconds */ + + 1, /* 3: 1 us 1,000 ns */ + 10, /* 4: 10 us 10,000 ns */ + 100, /* 5: 100 us 100,000 ns */ + 1000, /* 6: 1 ms 1,000,000 ns*/ + 10000, /* 7: 10 ms 10,000,000 ns */ +}; + +static const uint16_t g_taactv[] = +{ + 0x000, 0x100, 0x133, 0x14d, /* 0-3: Reserved, 1.0, 1.2, 1.3 */ + 0x180, 0x200, 0x280, 0x300, /* 4-7: 1.5, 2.0, 2.5, 3.0 */ + 0x380, 0x400, 0x480, 0x500, /* 8-11: 3.5, 4.0, 4.5, 5.0 */ + 0x580, 0x600, 0x700, 0x800 /* 12-15: 5.5, 6.0, 7.0, 8.0 */ +}; + +/* Commands *****************************************************************/ + +static const struct mmcsd_cmdinfo_s g_cmd0 = {CMD0, MMCSD_CMDRESP_R1, 0x95}; +static const struct mmcsd_cmdinfo_s g_cmd1 = {CMD1, MMCSD_CMDRESP_R1, 0xff}; +static const struct mmcsd_cmdinfo_s g_cmd8 = {CMD8, MMCSD_CMDRESP_R7, 0x87}; +static const struct mmcsd_cmdinfo_s g_cmd9 = {CMD9, MMCSD_CMDRESP_R1, 0xff}; +static const struct mmcsd_cmdinfo_s g_cmd10 = {CMD10, MMCSD_CMDRESP_R1, 0xff}; +static const struct mmcsd_cmdinfo_s g_cmd12 = {CMD12, MMCSD_CMDRESP_R1, 0xff}; +static const struct mmcsd_cmdinfo_s g_cmd16 = {CMD16, MMCSD_CMDRESP_R1, 0xff}; +static const struct mmcsd_cmdinfo_s g_cmd17 = {CMD17, MMCSD_CMDRESP_R1, 0xff}; +static const struct mmcsd_cmdinfo_s g_cmd18 = {CMD18, MMCSD_CMDRESP_R1, 0xff}; +static const struct mmcsd_cmdinfo_s g_cmd24 = {CMD24, MMCSD_CMDRESP_R1, 0xff}; +static const struct mmcsd_cmdinfo_s g_cmd25 = {CMD25, MMCSD_CMDRESP_R1, 0xff}; +static const struct mmcsd_cmdinfo_s g_cmd55 = {CMD55, MMCSD_CMDRESP_R1, 0xff}; +static const struct mmcsd_cmdinfo_s g_cmd58 = {CMD58, MMCSD_CMDRESP_R3, 0xff}; +static const struct mmcsd_cmdinfo_s g_acmd23 = {ACMD23, MMCSD_CMDRESP_R1, 0xff}; +static const struct mmcsd_cmdinfo_s g_acmd41 = {ACMD41, MMCSD_CMDRESP_R1, 0xff}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mmcsd_semtake + ****************************************************************************/ + +static void mmcsd_semtake(sem_t *sem) +{ + while (sem_wait(sem) != 0) + { + /* The only case that an error should occur here is if the wait was + * awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +#define mmcsd_semgive(sem) sem_post(sem) + +/**************************************************************************** + * Name: mmcsd_waitready + * + * Description: + * Wait until the card is no longer busy + * + * Assumptions: + * MMC/SD card already selected + * + ****************************************************************************/ + +static int mmcsd_waitready(FAR struct mmcsd_slot_s *slot) +{ + FAR struct spi_dev_s *spi = slot->spi; + uint8_t response; + uint32_t start; + uint32_t elapsed; + + /* Wait until the card is no longer busy (up to 500MS) */ + + start = START_TIME; + do + { + response = SPI_SEND(spi, 0xff); + if (response == 0xff) + { + return OK; + } + elapsed = ELAPSED_TIME(start); + } + while (elapsed < MMCSD_DELAY_500MS); + + fdbg("Card still busy, last response: %02x\n", response); + return -EBUSY; +} + +/**************************************************************************** + * Name: mmcsd_sendcmd + * + * Description: + * Send a command to MMC + * + * Assumptions: + * MMC/SD card already selected + * + ****************************************************************************/ + +static uint32_t mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot, + const struct mmcsd_cmdinfo_s *cmd, uint32_t arg) +{ + FAR struct spi_dev_s *spi = slot->spi; + uint32_t result; + uint8_t response = 0xff; + int ret; + int i; + + /* Wait until the card is not busy */ + + ret = mmcsd_waitready(slot); + if (ret != OK) + { + return ret; + } + + /* Send command code */ + + SPI_SEND(spi, cmd->cmd); + + /* Send command's arguments (should be zero if there are no arguements) */ + + SPI_SEND(spi, (arg >> 24) & 0xff); + SPI_SEND(spi, (arg >> 16) & 0xff); + SPI_SEND(spi, (arg >> 8) & 0xff); + SPI_SEND(spi, arg & 0xff); + + /* Send CRC if needed. The SPI interface is initialized in non-protected + * mode. However, the reset command (CMD0) and CMD8 are received by the + * card while it is still in SD mode and, therefore, must have a valid + * CRC field. + */ + + SPI_SEND(spi, cmd->chksum); + + /* Skip stuff byte on CMD12 */ + + if (cmd->cmd == CMD12) + { + SPI_SEND(spi, 0xff); + } + + /* Get the response to the command. A valid response will have bit7=0. + * Usually, the non-response is 0xff, but I have seen 0xc0 too. + */ + + for (i = 0; i < 9 && (response & 0x80) != 0; i++) + { + response = SPI_SEND(spi, 0xff); + } + + if ((response & 0x80) != 0) + { + fdbg("Failed: i=%d response=%02x\n", i, response); + return (uint32_t)-1; + } + + /* Interpret the response according to the command */ + + result = response; + switch (cmd->resp) + { + /* The R1B response is two bytes long */ + + case MMCSD_CMDRESP_R1B: + { + uint32_t busy = 0; + uint32_t start; + uint32_t elapsed; + + start = START_TIME; + do + { + busy = SPI_SEND(spi, 0xff); + elapsed = ELAPSED_TIME(start); + } + while (elapsed < slot->twrite && busy != 0xff); + + if (busy != 0xff) + { + fdbg("Failed: card still busy (%02x)\n", busy); + return (uint32_t)-1; + } + + fvdbg("CMD%d[%08x] R1B=%02x\n", + cmd->cmd & 0x3f, arg, response); + } + break; + + /* The R1 response is a single byte */ + + case MMCSD_CMDRESP_R1: + { + fvdbg("CMD%d[%08x] R1=%02x\n", + cmd->cmd & 0x3f, arg, response); + } + break; + + /* The R2 response is two bytes long */ + + case MMCSD_CMDRESP_R2: + { + result = ((uint32_t)(response & 0xff) << 8); + result |= SPI_SEND(spi, 0xff) & 0xff; + + fvdbg("CMD%d[%08x] R2=%04x\n", + cmd->cmd & 0x3f, arg, result); + } + break; + + /* The R3 response is 5 bytes long */ + + case MMCSD_CMDRESP_R3: + { + slot->ocr = ((uint32_t)(SPI_SEND(spi, 0xff) & 0xff) << 24); + slot->ocr |= ((uint32_t)(SPI_SEND(spi, 0xff) & 0xff) << 16); + slot->ocr |= ((uint32_t)(SPI_SEND(spi, 0xff) & 0xff) << 8); + slot->ocr |= SPI_SEND(spi, 0xff) & 0xff; + + fvdbg("CMD%d[%08x] R1=%02x OCR=%08x\n", + cmd->cmd & 0x3f, arg, response, slot->ocr); + } + + /* The R7 response is 5 bytes long */ + case MMCSD_CMDRESP_R7: + default: + { + slot->r7 = ((uint32_t)(SPI_SEND(spi, 0xff) & 0xff) << 24); + slot->r7 |= ((uint32_t)(SPI_SEND(spi, 0xff) & 0xff) << 16); + slot->r7 |= ((uint32_t)(SPI_SEND(spi, 0xff) & 0xff) << 8); + slot->r7 |= SPI_SEND(spi, 0xff) & 0xff; + + fvdbg("CMD%d[%08x] R1=%02x R7=%08x\n", + cmd->cmd & 0x3f, arg, response, slot->r7); + } + break; + } + + return result; +} + +/**************************************************************************** + * Name: mmcsd_setblklen + * + * Description: + * Set block length + * + * Assumptions: + * MMC/SD card already selected + * + ****************************************************************************/ + +static void mmcsd_setblklen(FAR struct mmcsd_slot_s *slot, uint32_t length) +{ + uint32_t response; + + fvdbg("Set block length to %d\n", length); + response = mmcsd_sendcmd(slot, &g_cmd16, length); + if (response != MMCSD_SPIR1_OK) + { + fdbg("Failed to set block length: %02x\n", response); + } +} + +/**************************************************************************** + * Name: mmcsd_nsac + * + * Description: Convert the value of the NSAC to microseconds + * + ****************************************************************************/ + +static uint32_t mmcsd_nsac(FAR struct mmcsd_slot_s *slot, uint8_t *csd, + uint32_t frequency) +{ + /* NSAC is 8-bits wide and is in units of 100 clock cycles. Therefore, the + * maximum value is 25.5K clock cycles. + */ + + uint32_t nsac = MMCSD_CSD_NSAC(csd) * ((uint32_t)100*1000); + uint32_t fhkz = (frequency + 500) / 1000; + return (nsac + (fhkz >> 1)) / fhkz; +} + +/**************************************************************************** + * Name: mmcsd_taac + * + * Description: Convert the value of the TAAC to microseconds + * + ****************************************************************************/ + +static uint32_t mmcsd_taac(FAR struct mmcsd_slot_s *slot, uint8_t *csd) +{ + int tundx; + + /*The TAAC consists of a 3-bit time unit (TU) and a 4-bit time value (TV). + * TAAC is in units of time; NSAC is in units of SPI clocks. + * The access time we need is then given by: + * + * taccess = TU*TV + NSAC/spifrequency + * + * g_taactu holds TU in units of nanoseconds and microseconds (you have to use + * the index to distiguish. g_taactv holds TV with 8-bits of fraction. + */ + + tundx = MMCSD_CSD_TAAC_TIMEUNIT(csd); + if (tundx <= MAX_USTUNDX) + { + /* The maximum value of the nanosecond TAAC is 800 ns. The rounded + * answer in microseconds will be at most 1. + */ + + return 1; + } + else + { + /* Return the answer in microseconds */ + + return (g_taactu[tundx]*g_taactv[MMCSD_CSD_TAAC_TIMEVALUE(csd)] + 0x80) >> 8; + } +} + +/**************************************************************************** + * Name: mmcsd_decodecsd + * + * Description: + * + ****************************************************************************/ + +static void mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, uint8_t *csd) +{ + FAR struct spi_dev_s *spi = slot->spi; + uint32_t maxfrequency; + uint32_t frequency; + uint32_t readbllen; + uint32_t csizemult; + uint32_t csize; + + /* Calculate SPI max clock */ + + maxfrequency = + g_transpeedtu[MMCSD_CSD_TRANSPEED_TIMEVALUE(csd)] * + g_transpeedru[MMCSD_CSD_TRANSPEED_TRANSFERRATEUNIT(csd)]; + + /* Clip the max frequency to account for board limitations */ + + frequency = maxfrequency; + if (frequency > CONFIG_MMCSD_SPICLOCK) + { + frequency = CONFIG_MMCSD_SPICLOCK; + } + + /* Set the actual SPI frequency as close as possible to that value */ + + frequency = SPI_SETFREQUENCY(spi, frequency); + + /* Now determine the delay to access data */ + + if (slot->type == MMCSD_CARDTYPE_MMC) + { + /* The TAAC consists of a 3-bit time unit (TU) and a 4-bit time value (TV). + * TAAC is in units of time; NSAC is in units of SPI clocks. + * The access time we need is then given by: + * + * taccess = TU*TV + NSAC/spifrequency + * + * Example: TAAC = 1.5 ms, NSAC = 0, r2wfactor = 4, CLK_TCK=100 + * taccessus = 1,500uS + * taccess = (1,500 * 100) / 100,000) + 1 = 2 (ideal, 1.5) + * twrite = (1,500 * 4 * 100) / 100,000) + 1 = 7 (ideal 6.0) + * + * First get the access time in microseconds + */ + + uint32_t taccessus = mmcsd_taac(slot, csd) + mmcsd_nsac(slot, csd, frequency); + + /* Then convert to system clock ticks. The maximum read access is 10 times + * the tacc value: taccess = 10 * (taccessus / 1,000,000) * CLK_TCK, or + */ + + slot->taccess = (taccessus * CLK_TCK) / 100000 + 1; + + /* NOTE that we add one to taccess to assure that we wait at least this + * time. The write access time is larger by the R2WFACTOR: */ + + slot->taccess = (taccessus * MMCSD_CSD_R2WFACTOR(csd) * CLK_TCK) / 100000 + 1; + } + else + { + /* For SD, the average is still given by the TAAC+NSAC, but the + * maximum are the constants 100 and 250MS + */ + + slot->taccess = SD_READACCESS; + slot->twrite = SD_WRITEACCESS; + } + + fvdbg("SPI Frequency\n"); + fvdbg(" Maximum: %d Hz\n", maxfrequency); + fvdbg(" Actual: %d Hz\n", frequency); + fvdbg("Read access time: %d ticks\n", slot->taccess); + fvdbg("Write access time: %d ticks\n", slot->twrite); + + /* Get the physical geometry of the card: sector size and number of + * sectors. The card's total capacity is computed from + * + * capacity = BLOCKNR * BLOCK_LEN + * BLOCKNR = (C_SIZE+1)*MULT + * MULT = 2**(C_SIZE_MULT+2) (C_SIZE_MULT < 8) + * BLOCK_LEN = 2**READ_BL_LEN (READ_BL_LEN < 12) + * + * Or + * + * capacity = ((C_SIZE+1) << (READD_BL_LEN + C_SIZE_MULT + 2)) + * + * In units of the sector size (1 << READ_BL_LEN), then simplifies to + * + * nsectors = ((C_SIZE+1) << (C_SIZE_MULT + 2)) + */ + + if (MMCSD_CSD_CSDSTRUCT(csd) != 0) + { + /* SDC structure ver 2.xx */ + /* Note: On SD card WRITE_BL_LEN is always the same as READ_BL_LEN */ + + readbllen = SD20_CSD_READBLLEN(csd); + csizemult = SD20_CSD_CSIZEMULT(csd) + 2; + csize = SD20_CSD_CSIZE(csd) + 1; + } + else + { + /* MMC or SD structure ver 1.xx */ + /* Note: On SD card WRITE_BL_LEN is always the same as READ_BL_LEN */ + + readbllen = MMCSD_CSD_READBLLEN(csd); + csizemult = MMCSD_CSD_CSIZEMULT(csd) + 2; + csize = MMCSD_CSD_CSIZE(csd) + 1; + } + + /* SDHC ver2.x cards have fixed block transfer size of 512 bytes. SDC + * ver1.x cards with capacity less than 1Gb, will have sector size + * 512 byes. SDC ver1.x cards with capacity of 2Gb will report readbllen + * of 1024 but should use 512 bytes for block transfers. SDC ver1.x 4Gb + * cards will report readbllen of 2048 bytes -- are they also 512 bytes? + */ + +#ifdef CONFIG_MMCSD_SECTOR512 + if (readbllen > 9) + { + csizemult += (readbllen - 9); + } + else + { + DEBUGASSERT(readbllen == 9); + } +#else + if (IS_SDV2(slot->type)) + { + if (readbllen > 9) + { + fdbg("Forcing 512 byte sector size\n"); + csizemult += (readbllen - 9); + readbllen = 9; + } + } + + slot->sectorsize = 1 << readbllen; +#endif + slot->nsectors = csize << csizemult; + fvdbg("Sector size: %d\n", SECTORSIZE(slot)); + fvdbg("Number of sectors: %d\n", slot->nsectors); +} + +/**************************************************************************** + * Name: mmcsd_checkwrprotect + * + * Description: + * + ****************************************************************************/ + +static void mmcsd_checkwrprotect(FAR struct mmcsd_slot_s *slot, uint8_t *csd) +{ + FAR struct spi_dev_s *spi = slot->spi; + + /* Check if (1) the slot is reporting that reporting that write protection + * is set, (2) the card reports permanent write protect, or (2) the card + * reports temporary write protect. + */ + + if ((SPI_STATUS(spi, SPIDEV_MMCSD) & SPI_STATUS_WRPROTECTED) != 0 || + MMCSD_CSD_PERMWRITEPROTECT(csd) || + MMCSD_CSD_TMPWRITEPROTECT(csd)) + { + slot->state |= MMCSD_SLOTSTATUS_WRPROTECT; + } + else + { + slot->state &= ~MMCSD_SLOTSTATUS_WRPROTECT; + } +} + +/**************************************************************************** + * Name: mmcsd_getcardinfo + * + * Description: + * Read CSD or CID registers + * + * Assumptions: + * MMC/SD card already selected + * + ****************************************************************************/ + +static int mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, uint8_t *buffer, + const struct mmcsd_cmdinfo_s *cmd) +{ + FAR struct spi_dev_s *spi = slot->spi; + uint32_t result; + uint8_t response; + int i; + + SPI_SEND(spi, 0xff); + + /* Send the CMD9 or CMD10 */ + + result = mmcsd_sendcmd(slot, cmd, 0); + if (result != MMCSD_SPIR1_OK) + { + fdbg("CMD9/10 failed: R1=%02x\n", result); + return -EIO; + } + + /* Try up to 8 times to find the start of block (or until an error occurs) */ + + for (i = 0; i < 8; i++) + { + response = SPI_SEND(spi, 0xff); + fvdbg("%d. SPI send returned %02x\n", i, response); + + /* If a read operation fails and the card cannot provide the requested + * data, it will send a data error token instead. The 4 least + * significant bits are the same as those in the R2 response. + */ + + if (response != 0 && (response & MMCSD_SPIDET_UPPER) == 0) + { + fdbg("%d. Data transfer error: %02x\n", i, response); + return -EIO; + } + else if (response == MMCSD_SPIDT_STARTBLKSNGL) + { + for (i = 0; i < 16; ++i) + { + *buffer++ = SPI_SEND(spi, 0xff); + } + + /* CRC receive */ + + SPI_SEND(spi, 0xff); + SPI_SEND(spi, 0xff); + return OK; + } + } + + fdbg("%d. Did not find start of block\n"); + return -EIO; +} + +/**************************************************************************** + * Name: mmcsd_recvblock + * + * Description: Receive a data block from the card + * + ****************************************************************************/ + +static int mmcsd_recvblock(FAR struct mmcsd_slot_s *slot, uint8_t *buffer, int nbytes) +{ + FAR struct spi_dev_s *spi = slot->spi; + uint32_t start; + uint32_t elapsed; + uint8_t token; + + /* Wait up to the maximum to receive a valid data token. taccess is the + * time from when the command is sent until the first byte of data is + * received */ + + start = START_TIME; + do + { + token = SPI_SEND(spi, 0xff); + elapsed = ELAPSED_TIME(start); + } + while (token == 0xff && elapsed < slot->taccess); + + if (token == MMCSD_SPIDT_STARTBLKSNGL) + { + /* Receive the block */ + + SPI_RECVBLOCK(spi, buffer, nbytes); + + /* Discard the CRC */ + + SPI_SEND(spi, 0xff); + SPI_SEND(spi, 0xff); + return OK; + } + + fdbg("Did not receive data token (%02x)\n", token); + return ERROR; +} + +/**************************************************************************** + * Name: mmcsd_xmitblock + * + * Description: Transmit a data block to the card + * + ****************************************************************************/ + +#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_READONLY) +static int mmcsd_xmitblock(FAR struct mmcsd_slot_s *slot, const uint8_t *buffer, + int nbytes, uint8_t token) +{ + FAR struct spi_dev_s *spi = slot->spi; + uint8_t response; + + /* Start the block transfer: + * 1. 0xff (sync) + * 2. 0xfe or 0xfc (start of block token) + * 3. Followed by the block of data and 2 byte CRC + */ + + SPI_SEND(spi, 0xff); /* sync */ + SPI_SEND(spi, token); /* data token */ + + /* Transmit the block to the MMC/SD card */ + + (void)SPI_SNDBLOCK(spi, buffer, nbytes); + + /* Add the bogus CRC. By default, the SPI interface is initialized in + * non-protected mode. However, we still have to send bogus CRC values + */ + + SPI_SEND(spi, 0xff); + SPI_SEND(spi, 0xff); + + /* Now get the data response */ + + response = SPI_SEND(spi, 0xff); + if ((response & MMCSD_SPIDR_MASK) != MMCSD_SPIDR_ACCEPTED) + { + fdbg("Bad data response: %02x\n", response); + return -EIO; + } + return OK; +} +#endif /* CONFIG_FS_WRITABLE && !CONFIG_MMCSD_READONLY */ + +/**************************************************************************** + * Block Driver Operations + ****************************************************************************/ + +/**************************************************************************** + * Name: mmcsd_open + * + * Description: Open the block device + * + ****************************************************************************/ + +static int mmcsd_open(FAR struct inode *inode) +{ + FAR struct mmcsd_slot_s *slot; + FAR struct spi_dev_s *spi; + int ret; + + fvdbg("Entry\n"); + +#ifdef CONFIG_DEBUG + if (!inode || !inode->i_private) + { + fdbg("Internal confusion\n"); + return -EIO; + } +#endif + + /* Extract our private data from the inode structure */ + + slot = (FAR struct mmcsd_slot_s *)inode->i_private; + spi = slot->spi; + +#ifdef CONFIG_DEBUG + if (!spi) + { + fdbg("Internal confusion\n"); + return -EIO; + } +#endif + + /* Verify that an MMC/SD card has been inserted */ + + ret = -ENODEV; + mmcsd_semtake(&slot->sem); + if ((SPI_STATUS(spi, SPIDEV_MMCSD) & SPI_STATUS_PRESENT) != 0) + { + /* Yes.. a card is present. Has it been initialized? */ + + if (slot->type == MMCSD_CARDTYPE_UNKNOWN) + { + /* Ininitialize for the media in the slot */ + + ret = mmcsd_mediainitialize(slot); + if (ret < 0) + { + fvdbg("Failed to initialize card\n"); + goto errout_with_sem; + } + } + + /* Make sure that the card is ready */ + + SPI_SELECT(spi, SPIDEV_MMCSD, true); + ret = mmcsd_waitready(slot); + SPI_SELECT(spi, SPIDEV_MMCSD, false); + } + +errout_with_sem: + mmcsd_semgive(&slot->sem); + return ret; +} + +/**************************************************************************** + * Name: mmcsd_close + * + * Description: close the block device + * + ****************************************************************************/ + +static int mmcsd_close(FAR struct inode *inode) +{ + fvdbg("Entry\n"); + return OK; +} + +/**************************************************************************** + * Name: mmcsd_read + * + * Description: Read the specified numer of sectors + * + ****************************************************************************/ + +static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer, + size_t start_sector, unsigned int nsectors) +{ + FAR struct mmcsd_slot_s *slot; + FAR struct spi_dev_s *spi; + size_t nbytes; + off_t offset; + uint8_t response; + int i; + + fvdbg("start_sector=%d nsectors=%d\n", start_sector, nsectors); + +#ifdef CONFIG_DEBUG + if (!buffer) + { + fdbg("Invalid parameters\n"); + return -EINVAL; + } + + if (!inode || !inode->i_private) + { + fdbg("Internal confusion\n"); + return -EIO; + } +#endif + + /* Extract our private data from the inode structure */ + + slot = (FAR struct mmcsd_slot_s *)inode->i_private; + spi = slot->spi; + +#ifdef CONFIG_DEBUG + if (!spi) + { + fdbg("Internal confusion\n"); + return -EIO; + } +#endif + + /* Verify that card is available */ + + if (slot->state & MMCSD_SLOTSTATUS_NOTREADY) + { + fdbg("Slot not ready\n"); + return -ENODEV; + } + + /* Do nothing on zero-length transfer */ + + if (nsectors < 1) + { + return 0; + } + + /* Convert sector and nsectors to nbytes and byte offset */ + + nbytes = nsectors * SECTORSIZE(slot); + if (IS_BLOCK(slot->type)) + { + offset = start_sector; + fvdbg("nbytes=%d sector offset=%d\n", nbytes, offset); + } + else + { + offset = start_sector * SECTORSIZE(slot); + fvdbg("nbytes=%d byte offset=%d\n", nbytes, offset); + } + + /* Select the slave */ + + mmcsd_semtake(&slot->sem); + SPI_SELECT(spi, SPIDEV_MMCSD, true); + + /* Single or multiple block read? */ + + if (nsectors == 1) + { + /* Send CMD17: Reads a block of the size selected by the SET_BLOCKLEN + * command and verify that good R1 status is returned + */ + + response = mmcsd_sendcmd(slot, &g_cmd17, offset); + if (response != MMCSD_SPIR1_OK) + { + fdbg("CMD17 failed: R1=%02x\n", response); + goto errout_with_eio; + } + + /* Receive the block */ + + if (mmcsd_recvblock(slot, buffer, SECTORSIZE(slot)) != 0) + { + fdbg("Failed: to receive the block\n"); + goto errout_with_eio; + } + } + else + { + /* Send CMD18: Reads a block of the size selected by the SET_BLOCKLEN + * command and verify that good R1 status is returned + */ + + response = mmcsd_sendcmd(slot, &g_cmd18, offset); + if (response != MMCSD_SPIR1_OK) + { + fdbg("CMD118 failed: R1=%02x\n", response); + goto errout_with_eio; + } + + /* Receive each block */ + + for (i = 0; i < nsectors; i++) + { + if (mmcsd_recvblock(slot, buffer, SECTORSIZE(slot)) != 0) + { + fdbg("Failed: to receive the block\n"); + goto errout_with_eio; + } + buffer += SECTORSIZE(slot); + } + + /* Send CMD12: Stops transmission */ + + response = mmcsd_sendcmd(slot, &g_cmd12, 0); + } + + /* On success, return the number of sectors transfer */ + + SPI_SELECT(spi, SPIDEV_MMCSD, false); + SPI_SEND(spi, 0xff); + mmcsd_semgive(&slot->sem); + + fvdbg("Read %d bytes:\n", nbytes); + mmcsd_dumpbuffer("Read buffer", buffer, nbytes); + return nsectors; + +errout_with_eio: + SPI_SELECT(spi, SPIDEV_MMCSD, false); + mmcsd_semgive(&slot->sem); + return -EIO; +} + +/**************************************************************************** + * Name: mmcsd_write + * + * Description: + * Write the specified number of sectors + * + ****************************************************************************/ + +#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_READONLY) +static ssize_t mmcsd_write(FAR struct inode *inode, const unsigned char *buffer, + size_t start_sector, unsigned int nsectors) +{ + FAR struct mmcsd_slot_s *slot; + FAR struct spi_dev_s *spi; + size_t nbytes; + off_t offset; + uint8_t response; + int ret; + int i; + + fvdbg("start_sector=%d nsectors=%d\n", start_sector, nsectors); + +#ifdef CONFIG_DEBUG + if (!buffer) + { + fdbg("Invalid parameters\n"); + return -EINVAL; + } + + if (!inode || !inode->i_private) + { + fdbg("Internal confusion\n"); + return -EIO; + } +#endif + + /* Extract our private data from the inode structure */ + + slot = (FAR struct mmcsd_slot_s *)inode->i_private; + spi = slot->spi; + +#ifdef CONFIG_DEBUG + if (!spi) + { + fdbg("Internal confusion\n"); + return -EIO; + } +#endif + + /* Verify that card is available */ + + if (slot->state & MMCSD_SLOTSTATUS_NOTREADY) + { + fdbg("Slot not ready\n"); + return -ENODEV; + } + + /* Verify that the card is write enabled */ + + if (slot->state & MMCSD_SLOTSTATUS_WRPROTECT) + { + fdbg("Not write enabled\n"); + return -EACCES; + } + + /* Do nothing on zero-length transfer */ + + if (nsectors < 1) + { + return 0; + } + + /* Convert sector and nsectors to nbytes and byte offset */ + + nbytes = nsectors * SECTORSIZE(slot); + if (IS_BLOCK(slot->type)) + { + offset = start_sector; + fvdbg("nbytes=%d sector offset=%d\n", nbytes, offset); + } + else + { + offset = start_sector * SECTORSIZE(slot); + fvdbg("nbytes=%d byte offset=%d\n", nbytes, offset); + } + mmcsd_dumpbuffer("Write buffer", buffer, nbytes); + + /* Select the slave */ + + mmcsd_semtake(&slot->sem); + SPI_SELECT(spi, SPIDEV_MMCSD, true); + + /* Single or multiple block transfer? */ + + if (nsectors == 1) + { + /* Send CMD24 (WRITE_BLOCK) and verify that good R1 status is returned */ + + response = mmcsd_sendcmd(slot, &g_cmd24, offset); + if (response != MMCSD_SPIR1_OK) + { + fdbg("CMD24 failed: R1=%02x\n", response); + goto errout_with_sem; + } + + /* Then transfer the sector */ + + if (mmcsd_xmitblock(slot, buffer, SECTORSIZE(slot), 0xfe) != 0) + { + fdbg("Block transfer failed\n"); + goto errout_with_sem; + } + } + else + { + /* Set the number of blocks to be pre-erased (SD only) */ + + if (IS_SD(slot->type)) + { + response = mmcsd_sendcmd(slot, &g_acmd23, nsectors); + if (response != MMCSD_SPIR1_OK) + { + fdbg("ACMD23 failed: R1=%02x\n", response); + goto errout_with_sem; + } + } + + /* Send CMD25: Continuously write blocks of data until the + * tranmission is stopped. + */ + + response = mmcsd_sendcmd(slot, &g_cmd25, offset); + if (response != MMCSD_SPIR1_OK) + { + fdbg("CMD25 failed: R1=%02x\n", response); + goto errout_with_sem; + } + + /* Transmit each block */ + + for (i = 0; i < nsectors; i++) + { + if (mmcsd_xmitblock(slot, buffer, SECTORSIZE(slot), 0xfc) != 0) + { + fdbg("Failed: to receive the block\n"); + goto errout_with_sem; + } + buffer += SECTORSIZE(slot); + } + + /* Send the stop transmission token */ + + SPI_SEND(spi, MMCSD_SPIDT_STOPTRANS); + } + + /* Wait until the card is no longer busy */ + + ret = mmcsd_waitready(slot); + SPI_SELECT(spi, SPIDEV_MMCSD, false); + SPI_SEND(spi, 0xff); + mmcsd_semgive(&slot->sem); + + /* The success return value is the number of sectors written */ + + return nsectors; + +errout_with_sem: + SPI_SELECT(spi, SPIDEV_MMCSD, false); + mmcsd_semgive(&slot->sem); + return -EIO; +} +#endif + +/**************************************************************************** + * Name: mmcsd_geometry + * + * Description: + * Return device geometry + * + ****************************************************************************/ + +static int mmcsd_geometry(FAR struct inode *inode, struct geometry *geometry) +{ + FAR struct mmcsd_slot_s *slot; + FAR struct spi_dev_s *spi; + uint8_t csd[16]; + int ret; + +#ifdef CONFIG_DEBUG + if (!geometry) + { + fdbg("Invalid parameters\n"); + return -EINVAL; + } + + if (!inode || !inode->i_private) + { + fdbg("Internal confusion\n"); + return -EIO; + } +#endif + + /* Extract our private data from the inode structure */ + + slot = (FAR struct mmcsd_slot_s *)inode->i_private; + spi = slot->spi; + +#ifdef CONFIG_DEBUG + if (!spi) + { + fdbg("Internal confusion\n"); + return -EIO; + } +#endif + + /* Re-sample the CSD */ + + mmcsd_semtake(&slot->sem); + SPI_SELECT(spi, SPIDEV_MMCSD, true); + ret = mmcsd_getcsd(slot, csd); + SPI_SELECT(spi, SPIDEV_MMCSD, false); + + if (ret < 0) + { + mmcsd_semgive(&slot->sem); + fdbg("mmcsd_getcsd returned %d\n", ret); + return ret; + } + + /* Check for changes related to write protection */ + + mmcsd_checkwrprotect(slot, csd); + + /* Then return the card geometry */ + + geometry->geo_available = + ((slot->state & (MMCSD_SLOTSTATUS_NOTREADY|MMCSD_SLOTSTATUS_NODISK)) == 0); + geometry->geo_mediachanged = + ((slot->state & MMCSD_SLOTSTATUS_MEDIACHGD) != 0); +#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_READONLY) + geometry->geo_writeenabled = + ((slot->state & MMCSD_SLOTSTATUS_WRPROTECT) == 0); +#else + geometry->geo_writeenabled = false; +#endif + geometry->geo_nsectors = slot->nsectors; + geometry->geo_sectorsize = SECTORSIZE(slot); + + /* After reporting mediachanged, clear the indication so that it is not + * reported again. + */ + + slot->state &= ~MMCSD_SLOTSTATUS_MEDIACHGD; + mmcsd_semgive(&slot->sem); + + fvdbg("geo_available: %d\n", geometry->geo_available); + fvdbg("geo_mediachanged: %d\n", geometry->geo_mediachanged); + fvdbg("geo_writeenabled: %d\n", geometry->geo_writeenabled); + fvdbg("geo_nsectors: %d\n", geometry->geo_nsectors); + fvdbg("geo_sectorsize: %d\n", geometry->geo_sectorsize); + + return OK; +} + +/**************************************************************************** + * Initialization + ****************************************************************************/ + +/**************************************************************************** + * Name: mmcsd_mediainitialize + * + * Description: + * Detect media and initialize + * + ****************************************************************************/ + +static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot) +{ + FAR struct spi_dev_s *spi = slot->spi; + uint8_t csd[16]; + uint32_t result = MMCSD_SPIR1_IDLESTATE; + uint32_t start; + uint32_t elapsed; + int i, j; + + /* Assume that the card is not ready (we'll clear this on successful card + * initialization. + */ + + slot->state |= MMCSD_SLOTSTATUS_NOTREADY; + + /* Check if there is a card present in the slot. This is normally a matter is + * of GPIO sensing and does not really involve SPI, but by putting this + * functionality in the SPI interface, we encapuslate the SPI MMC/SD + * interface + */ + + if ((SPI_STATUS(spi, SPIDEV_MMCSD) & SPI_STATUS_PRESENT) == 0) + { + fdbg("No card present\n"); + slot->state |= MMCSD_SLOTSTATUS_NODISK; + return -ENODEV; + } + + /* Clock Freq. Identification Mode < 400kHz */ + + SPI_SETFREQUENCY(spi, MMCSD_IDMODE_CLOCK); + + /* Set the maximum access time out */ + + slot->taccess = SD_READACCESS; + + /* The SD card wakes up in SD mode. It will enter SPI mode if the chip select signal is + * asserted (negative) during the reception of the reset command (CMD0) and the card is in + * IDLE state. + */ + + for (i = 0; i < 2; i++) + { + /* After power up at least 74 clock cycles are required prior to + * starting bus communication + */ + + for (j = 10; j; j--) + { + SPI_SEND(spi, 0xff); + } + + /* Send CMD0 (GO_TO_IDLE) with CS asserted to put MMC/SD in + * IDLE/SPI mode. Return from CMD0 is R1 which should now + * show IDLE STATE + */ + + fvdbg("Send CMD0\n"); + SPI_SELECT(spi, SPIDEV_MMCSD, true); + result = mmcsd_sendcmd(slot, &g_cmd0, 0); + if (result == MMCSD_SPIR1_IDLESTATE) + { + /* Break out of the loop with card selected */ + + fvdbg("Card is in IDLE state\n"); + break; + } + + /* De-select card and try again */ + + SPI_SELECT(spi, SPIDEV_MMCSD, false); + } + + /* Verify that we exit the above loop with the card reporting IDLE state */ + + if (result != MMCSD_SPIR1_IDLESTATE) + { + fdbg("Send CMD0 failed: R1=%02x\n", result); + SPI_SELECT(spi, SPIDEV_MMCSD, false); + return -EIO; + } + + slot->type = MMCSD_CARDTYPE_UNKNOWN; + + /* Check for SDHC Version 2.x. CMD 8 is reserved on SD version 1.0 and MMC. */ + + fvdbg("Send CMD8\n"); + result = mmcsd_sendcmd(slot, &g_cmd8, 0x1aa); + if (result == MMCSD_SPIR1_IDLESTATE) + { + /* Verify the operating voltage and that the 0xaa was correctly echoed */ + + if (((slot->r7 & MMCSD_SPIR7_VOLTAGE_MASK) == MMCSD_SPIR7_VOLTAGE_27) && + ((slot->r7 & MMCSD_SPIR7_ECHO_MASK) == 0xaa)) + { + /* Try CMD55/ACMD41 for up to 1 second or until the card exits + * the IDLE state + */ + + start = START_TIME; + elapsed = 0; + do + { + fvdbg("%d. Send CMD55/ACMD41\n", elapsed); + result = mmcsd_sendcmd(slot, &g_cmd55, 0); + if (result == MMCSD_SPIR1_IDLESTATE || result == MMCSD_SPIR1_OK) + { + result = mmcsd_sendcmd(slot, &g_acmd41, (uint32_t)1 << 30); + if (result == MMCSD_SPIR1_OK) + { + break; + } + } + elapsed = ELAPSED_TIME(start); + } + while (elapsed < MMCSD_DELAY_1SEC); + + /* Check if ACMD41 was sent successfully */ + + if (elapsed < MMCSD_DELAY_1SEC) + { + fvdbg("Send CMD58\n"); + SPI_SEND(spi, 0xff); + result = mmcsd_sendcmd(slot, &g_cmd58, 0); + if (result == MMCSD_SPIR1_OK) + { + fvdbg("OCR: %08x\n", slot->ocr); + if ((slot->ocr & MMCSD_OCR_CCS) != 0) + { + fdbg("Identified SD ver2 card/with block access\n"); + slot->type = MMCSD_CARDTYPE_SDV2|MMCSD_CARDTYPE_BLOCK; + } + else + { + fdbg("Identified SD ver2 card\n"); + slot->type = MMCSD_CARDTYPE_SDV2; + } + } + } + } + } + + /* Check for SDC version 1.x or MMC */ + + else + { + /* Both the MMC card and the SD card support CMD55 */ + + fvdbg("Send CMD55/ACMD41\n"); + result = mmcsd_sendcmd(slot, &g_cmd55, 0); + if (result == MMCSD_SPIR1_IDLESTATE || result == MMCSD_SPIR1_OK) + { + /* But ACMD41 is supported only on SD */ + + result = mmcsd_sendcmd(slot, &g_acmd41, 0); + if (result == MMCSD_SPIR1_IDLESTATE || result == MMCSD_SPIR1_OK) + { + fdbg("Identified SD ver1 card\n"); + slot->type = MMCSD_CARDTYPE_SDV1; + } + } + + /* Make sure that we are out of the Idle state */ + + start = START_TIME; + elapsed = 0; + do + { + if (IS_SD(slot->type)) + { + fvdbg("%d. Send CMD55/ACMD41\n", elapsed); + result = mmcsd_sendcmd(slot, &g_cmd55, 0); + if (result == MMCSD_SPIR1_IDLESTATE || result == MMCSD_SPIR1_OK) + { + result = mmcsd_sendcmd(slot, &g_acmd41, 0); + if (result == MMCSD_SPIR1_OK) + { + break; + } + } + } + else + { + fvdbg("%d. Send CMD1\n", i); + result = mmcsd_sendcmd(slot, &g_cmd1, 0); + if (result == MMCSD_SPIR1_OK) + { + fdbg("%d. Identified MMC card\n", i); + slot->type = MMCSD_CARDTYPE_MMC; + break; + } + } + elapsed = ELAPSED_TIME(start); + } + while (elapsed < MMCSD_DELAY_1SEC); + + if (elapsed >= MMCSD_DELAY_1SEC) + { + fdbg("Failed to exit IDLE state\n"); + SPI_SELECT(spi, SPIDEV_MMCSD, false); + return -EIO; + } + } + + if (slot->type == MMCSD_CARDTYPE_UNKNOWN) + { + fdbg("Failed to identify card\n"); + SPI_SELECT(spi, SPIDEV_MMCSD, false); + return -EIO; + } + + /* Read CSD. CSD must always be valid */ + + fvdbg("Get CSD\n"); + result = mmcsd_getcsd(slot, csd); + if (result != OK) + { + fdbg("mmcsd_getcsd(CMD9) failed: %d\n", result); + SPI_SELECT(spi, SPIDEV_MMCSD, false); + return -EIO; + } + mmcsd_dmpcsd(csd, slot->type); + + /* CSD data and set block size */ + + mmcsd_decodecsd(slot, csd); + mmcsd_checkwrprotect(slot, csd); + + /* SDHC ver2.x cards have fixed block transfer size of 512 bytes. SDC + * ver1.x cards with capacity less than 1Gb, will have sector size + * 512 byes. SDC ver1.x cards with capacity of 2Gb will report readbllen + * of 1024 but should use 512 bytes for block transfers. SDC ver1.x 4Gb + * cards will report readbllen of 2048 bytes -- are they also 512 bytes? + * I think that none of these high capacity cards support setting the + * block length?? + */ + +#ifdef CONFIG_MMCSD_SECTOR512 + /* Using 512 byte sectors, the maximum ver1.x capacity is 4096 x 512 blocks. + * The saved slot->nsectors is converted to 512 byte blocks, so if slot->nsectors + * exceeds 4096 x 512, then we must be dealing with a card with read_bl_len + * of 1024 or 2048. + */ + + if (!IS_SDV2(slot->type) && slot->nsectors <= ((uint32_t)4096*12)) + { + /* Don't set the block len on high capacity cards (ver1.x or ver2.x) */ + + mmcsd_setblklen(slot, SECTORSIZE(slot)); + } +#else + if (!IS_SDV2(slot->type)) + { + /* Don't set the block len on ver2.x cards */ + + mmcsd_setblklen(slot, SECTORSIZE(slot)); + } +#endif + + slot->state &= ~MMCSD_SLOTSTATUS_NOTREADY; + SPI_SELECT(spi, SPIDEV_MMCSD, false); + return OK; +} + +/**************************************************************************** + * Name: mmcsd_mediachanged + * + * Description: + * Handle initialization/media change events + * + ****************************************************************************/ + +static void mmcsd_mediachanged(void *arg) +{ + struct mmcsd_slot_s *slot = (struct mmcsd_slot_s*)arg; + FAR struct spi_dev_s *spi; + uint8_t oldstate; + int ret; + +#ifdef CONFIG_DEBUG + if (!slot || !slot->spi) + { + fdbg("Internal confusion\n"); + return; + } +#endif + spi = slot->spi; + + /* Save the current slot state and reassess the new state */ + + mmcsd_semtake(&slot->sem); + oldstate = slot->state; + + /* Check if media was removed or inserted */ + + slot->state &= ~(MMCSD_SLOTSTATUS_NODISK|MMCSD_SLOTSTATUS_NOTREADY|MMCSD_SLOTSTATUS_MEDIACHGD); + if ((SPI_STATUS(spi, SPIDEV_MMCSD) & SPI_STATUS_PRESENT) == 0) + { + /* Media is not present */ + + fdbg("No card present\n"); + slot->state |= (MMCSD_SLOTSTATUS_NODISK|MMCSD_SLOTSTATUS_NOTREADY); + + /* Was media removed? */ + + if ((oldstate & MMCSD_SLOTSTATUS_NODISK) == 0) + { + slot->state |= MMCSD_SLOTSTATUS_MEDIACHGD; + } + } + + /* Media is present, was it just inserted? Or, if it was previously not ready, + * then try re-initializing it + */ + + else if ((oldstate & (MMCSD_SLOTSTATUS_NODISK|MMCSD_SLOTSTATUS_NOTREADY)) != 0) + { + /* (Re-)ininitialize for the media in the slot */ + + ret = mmcsd_mediainitialize(slot); + if (ret == 0) + { + fvdbg("mmcsd_mediainitialize returned OK\n"); + slot->state |= MMCSD_SLOTSTATUS_MEDIACHGD; + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mmcsd_spislotinitialize + * + * Description: + * Initialize one slot for operation using the SPI MMC/SD interface + * + * Input Parameters: + * minor - The MMC/SD minor device number. The MMC/SD device will be + * registered as /dev/mmcsdN where N is the minor number + * slotno - The slot number to use. This is only meaningful for architectures + * that support multiple MMC/SD slots. This value must be in the range + * {0, ..., CONFIG_MMCSD_NSLOTS}. + * spi - And instance of an SPI interface obtained by called + * up_spiinitialize() with the appropriate port number (see spi.h) + * + ****************************************************************************/ + +int mmcsd_spislotinitialize(int minor, int slotno, FAR struct spi_dev_s *spi) +{ + struct mmcsd_slot_s *slot; + char devname[16]; + int ret; + +#ifdef CONFIG_DEBUG + if ((unsigned)slotno >= CONFIG_MMCSD_NSLOTS || (unsigned)minor > 255 || !spi) + { + fdbg("Invalid arguments\n"); + return -EINVAL; + } +#endif + + /* Select the slot structure */ + + slot = &g_mmcsdslot[slotno]; + memset(slot, 0, sizeof(struct mmcsd_slot_s)); + sem_init(&slot->sem, 0, 1); + +#ifdef CONFIG_DEBUG + if (slot->spi) + { + fdbg("Already registered\n"); + return -EBUSY; + } +#endif + + /* Bind the SPI port to the slot */ + + slot->spi = spi; + + /* Ininitialize for the media in the slot (if any) */ + + ret = mmcsd_mediainitialize(slot); + if (ret == 0) + { + fvdbg("mmcsd_mediainitialize returned OK\n"); + slot->state |= MMCSD_SLOTSTATUS_MEDIACHGD; + } + + /* Create a MMC/SD device name */ + + snprintf(devname, 16, "/dev/mmcsd%d", minor); + + /* Register the driver, even on a failure condition. A + * card may be inserted later, for example. + */ + + ret = register_blockdriver(devname, &g_bops, MMCSD_MODE, slot); + if (ret < 0) + { + fdbg("register_blockdriver failed: %d\n", -ret); + slot->spi = NULL; + return ret; + } + + /* Register a media change callback to handler insertion and + * removal of cards. + */ + + (void)SPI_REGISTERCALLBACK(spi, mmcsd_mediachanged, (void*)slot); + return OK; +} diff --git a/nuttx/drivers/mmcsd/mmcsd_spi.h b/nuttx/drivers/mmcsd/mmcsd_spi.h new file mode 100644 index 0000000000..055862bebd --- /dev/null +++ b/nuttx/drivers/mmcsd/mmcsd_spi.h @@ -0,0 +1,187 @@ +/**************************************************************************** + * drivers/mmcsd/mmcsd_spi.h + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_MMCSD_MMCSD_SPI_H +#define __DRIVERS_MMCSD_MMCSD_SPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* SPI *******************************************************************/ + +/* SPI Command Set */ + +#define CMD0 0x40 /* GO_IDLE_STATE: Resets all cards to idle state */ +#define CMD1 0x41 /* SEND_OP_COND: Sends capacity support information */ +#define CMD6 0x46 /* SWITCH_FUNC: Checks switchable function */ +#define CMD8 0x48 /* SEND_IF_COND: Sends SD Memory Card interface condition */ +#define CMD9 0x49 /* SEND_CSD: Asks card to send its card specific data (CSD) */ +#define CMD10 0x4a /* SEND_CID: Asks card to send its card identification (CID) */ +#define CMD12 0x4c /* STOP_TRANSMISSION: Forces the card to stop transmission */ +#define CMD13 0x4d /* SEND_STATUS: Asks card to send its status register */ +#define CMD16 0x50 /* SET_BLOCKLEN: Sets a block length (in bytes) */ +#define CMD17 0x51 /* READ_SINGLE_BLOCK: Reads a block of the selected size */ +#define CMD18 0x52 /* READ_MULTIPLE_BLOCK: Continuously transfers blocks from card to host */ +#define CMD20 0x54 /* CMD_WRITEBLOCK: Write block to memory (MMC) */ +#define CMD24 0x58 /* WRITE_BLOCK: Writes a block of the selected size */ +#define CMD25 0x59 /* WRITE_MULTIPLE_BLOCK: Continuously writes blocks of data */ +#define CMD27 0x5b /* PROGRAM_CSD: Set programmable bits of the CSD */ +#define CMD28 0x5c /* SET_WRITE_PROT: Sets the write protection bit of group */ +#define CMD29 0x5d /* CLR_WRITE_PROT: Clears the write protection bit of group */ +#define CMD30 0x5e /* SEND_WRITE_PROT: Asks card to send state of write protection bits */ +#define CMD32 0x60 /* ERASE_WR_BLK_START_ADDR: Sets address of first block to erase */ +#define CMD33 0x61 /* ERASE_WR_BLK_END_ADDR: Sets address of last block to erase */ +#define CMD34 0x62 /* UNTAG_SECTOR: (MMC) */ +#define CMD35 0x63 /* TAG_ERASE_GROUP_START: (MMC) */ +#define CMD36 0x64 /* TAG_ERASE_GOUPR_END: (MMC) */ +#define CMD37 0x65 /* UNTAG_ERASE_GROUP: (MMC) */ +#define CMD38 0x66 /* ERASE: Erases all previously selected write blocks */ +#define CMD40 0x68 /* CRC_ON_OFF: (MMC) */ +#define CMD42 0x6a /* LOCK_UNLOCK: Used to Set/Reset the Password or lock/unlock card */ +#define CMD55 0x77 /* APP_CMD: Tells card that the next command is an application specific command */ +#define CMD56 0x78 /* GEN_CMD: Used transfer a block to or get block from card */ +#define CMD58 0x7a /* READ_OCR :Reads the OCR register of a card */ +#define CMD59 0x7b /* CRC_ON_OFF: Turns the CRC option on or off */ +#define ACMD13 0x4d /* SD_STATUS: Send the SD Status */ +#define ACMD22 0x56 /* SEND_NUM_WR_BLOCKS: Send number of the errorfree blocks */ +#define ACMD23 0x57 /* SET_WR_BLK_ERASE_COUNT: Set number blocks to erase before writing */ +#define ACMD41 0x69 /* SD_SEND_OP_COND: Sends host capacity support information */ +#define ACMD42 0x6a /* SET_CLR_CARD_DETECT: Connect/disconnect pull-up resistor on CS */ +#define ACMD51 0x73 /* SEND_SCR: Reads the SD Configuration Register (SCR) */ + +/* SPI 8-bit R1 response */ + +#define MMCSD_SPIR1_OK 0x00 /* No error bits set */ +#define MMCSD_SPIR1_IDLESTATE 0x01 /* Idle state */ +#define MMCSD_SPIR1_ERASERESET 0x02 /* Erase reset */ +#define MMCSD_SPIR1_ILLEGALCMD 0x04 /* Illegal command */ +#define MMCSD_SPIR1_CRCERROR 0x08 /* Com CRC error */ +#define MMCSD_SPIR1_ERASEERROR 0x10 /* Erase sequence error */ +#define MMCSD_SPIR1_ADDRERROR 0x20 /* Address error */ +#define MMCSD_SPIR1_PARAMERROR 0x40 /* Parameter error */ + +/* SPI 8-bit R2 response */ + +#define MMCSD_SPIR2_CARDLOCKED 0x0001 /* Card is locked */ +#define MMCSD_SPIR2_WPERASESKIP 0x0002 /* WP erase skip */ +#define MMCSD_SPIR2_LOCKFAIL 0x0002 /* Lock/unlock cmd failed */ +#define MMCSD_SPIR2_ERROR 0x0004 /* Error */ +#define MMCSD_SPIR2_CCERROR 0x0008 /* CC error */ +#define MMCSD_SPIR2_CARDECCFAIL 0x0010 /* Card ECC failed */ +#define MMCSD_SPIR2_WPVIOLATION 0x0020 /* WP violoation */ +#define MMCSD_SPIR2_ERASEPARAM 0x0040 /* Erase parameter */ +#define MMCSD_SPIR2_OUTOFRANGE 0x0080 /* Out of range */ +#define MMCSD_SPIR2_CSDOVERWRITE 0x0080 /* CSD overwrite */ +#define MMCSD_SPIR2_IDLESTATE 0x0100 /* In idle state */ +#define MMCSD_SPIR2_ERASERESET 0x0200 /* Erase reset */ +#define MMCSD_SPIR2_ILLEGALCMD 0x0400 /* Illegal command */ +#define MMCSD_SPIR2_CRCERROR 0x0800 /* Com CRC error */ +#define MMCSD_SPIR2_ERASEERROR 0x1000 /* Erase sequence error */ +#define MMCSD_SPIR2_ADDRERROR 0x2000 /* Address error */ +#define MMCSD_SPIR2_PARAMERROR 0x4000 /* Parameter error */ + +/* Last 4 bytes of the 5 byte R7 response */ + +#define MMCSD_SPIR7_VERSION_SHIFT (28) /* Bits 28-31: Command version number */ +#define MMCSD_SPIR7_VERSION_MASK ((uint32_t)0x0f << MMCSD_SPIR7_VERSION_SHIFT) +#define MMCSD_SPIR7_VOLTAGE_SHIFT (8) /* Bits 8-11: Voltage accepted */ +#define MMCSD_SPIR7_VOLTAGE_MASK ((uint32_t)0x0f << MMCSD_SPIR7_VOLTAGE_SHIFT) +#define MMCSD_SPIR7_VOLTAGE_27 ((uint32_t)0x01 << MMCSD_SPIR7_VOLTAGE_SHIFT) /* 2.7-3.6V */ +#define MMCSD_SPIR7_ECHO_SHIFT (0) /* Bits 0-7: Echoed check pattern */ +#define MMCSD_SPIR7_ECHO_MASK ((uint32_t)0xff << MMCSD_SPIR7_ECHO_SHIFT) + +/* Data Response */ + +#define MMCSD_SPIDR_MASK 0x1f /* Mask for valid data response bits */ +#define MMCSD_SPIDR_ACCEPTED 0x05 /* Data accepted */ +#define MMCSD_SPIDR_CRCERROR 0x0b /* Data rejected due to CRC error */ +#define MMCSD_SPIDR_WRERROR 0x0d /* Data rejected due to write error */ + +/* Data Tokens */ + +#define MMCSD_SPIDT_STARTBLKSNGL 0xfe /* First byte of block, single block */ +#define MMCSD_SPIDT_STARTBLKMULTI 0xfc /* First byte of block, multi-block */ +#define MMCSD_SPIDT_STOPTRANS 0xfd /* Stop transmission */ + +/* Data error token */ + +#define MMCSD_SPIDET_UPPER 0xf0 /* The upper four bits are zero */ +#define MMCSD_SPIDET_ERROR 0x01 /* Error */ +#define MMCSD_SPIDET_CCERROR 0x02 /* CC error */ +#define MMCSD_SPIDET_CARDECCFAIL 0x04 /* Card ECC failed */ +#define MMCSD_SPIDET_OUTOFRANGE 0x08 /* Out of range */ + +/* Operating Conditions register */ + +#define MMCSD_OCR_V27 ((uint32_t)1 << 15) /* Bit 15: 2.7-2.8V */ +#define MMCSD_OCR_V28 ((uint32_t)1 << 16) /* Bit 16: 2.8-2.9V */ +#define MMCSD_OCR_V29 ((uint32_t)1 << 17) /* Bit 17: 2.9-3.0V */ +#define MMCSD_OCR_V30 ((uint32_t)1 << 18) /* Bit 18: 3.0-3.1V */ +#define MMCSD_OCR_V31 ((uint32_t)1 << 19) /* Bit 19: 3.1-3.2V */ +#define MMCSD_OCR_V32 ((uint32_t)1 << 20) /* Bit 20: 3.2-3.3V */ +#define MMCSD_OCR_V33 ((uint32_t)1 << 21) /* Bit 21: 3.3-3.4V */ +#define MMCSD_OCR_V34 ((uint32_t)1 << 22) /* Bit 22: 3.4-3.5V */ +#define MMCSD_OCR_V35 ((uint32_t)1 << 23) /* Bit 23: 3.5-3.6V */ +#define MMCSD_OCR_CCS ((uint32_t)1 << 30) /* Bit 30: Card capacity status */ +#define MMCSD_OCR_BUSY ((uint32_t)1 << 31) /* Bit 31: Card powered up status bit */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __DRIVERS_MMCSD_MMCSD_SPI_H */ diff --git a/nuttx/drivers/mtd/Kconfig b/nuttx/drivers/mtd/Kconfig new file mode 100644 index 0000000000..bda5afa84d --- /dev/null +++ b/nuttx/drivers/mtd/Kconfig @@ -0,0 +1,68 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# +config MTD_AT24XX + bool "I2C-based AT24XX eeprom" + default n + select I2C + +config AT24XX_SIZE + int "at24xx size(kByte)" + default 64 + depends on MTD_AT24XX + +config AT24XX_ADDR + hex "at24xx i2c address" + default 0x50 + depends on MTD_AT24XX + +config MTD_AT45DB + bool "SPI-based AT45DB flash" + default n + select SPI + +config AT45DB_FREQUENCY + int "at45db frequency" + default 1000000 + depends on MTD_AT45DB + +config AT45DB_PREWAIT + bool "enables higher performance write logic" + default y + depends on MTD_AT45DB + +config AT45DB_PWRSAVE + bool "enables power save" + default n + depends on MTD_AT45DB + +config MTD_MP25P + bool "SPI-based M25P1 falsh" + default n + select SPI + +config MP25P_SPIMODE + int "mp25p spi mode" + default 0 + depends on MTD_MP25P + +config MP25P_MANUFACTURER + hex "mp25p manufacturers ID" + default 0x20 + depends on MTD_MP25P + ---help--- + Various manufacturers may have produced the parts. 0x20 is the manufacturer ID + for the STMicro MP25x serial FLASH. If, for example, you are using the a Macronix + International MX25 serial FLASH, the correct manufacturer ID would be 0xc2. + +config MTD_RAMTRON + bool "SPI-based RAMTRON NVRAM Devices FM25V10" + default n + select SPI + ---help--- + SPI-based RAMTRON NVRAM Devices FM25V10 + +config MTD_RAM + bool "Memory bus ram" + default n diff --git a/nuttx/drivers/mtd/Make.defs b/nuttx/drivers/mtd/Make.defs new file mode 100644 index 0000000000..866d7c713e --- /dev/null +++ b/nuttx/drivers/mtd/Make.defs @@ -0,0 +1,54 @@ +############################################################################ +# drivers/mtd/Make.defs +# These driver supports various Memory Technology Devices (MTD) using the +# NuttX MTD interface. +# +# Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Include MTD drivers + +CSRCS += at45db.c flash_eraseall.c ftl.c m25px.c rammtd.c ramtron.c + +ifeq ($(CONFIG_MTD_AT24XX),y) +CSRCS += at24xx.c +endif + +ifeq ($(CONFIG_MTD_SST25),y) +CSRCS += sst25.c +endif + +# Include MTD driver support + +DEPPATH += --dep-path mtd +VPATH += :mtd + diff --git a/nuttx/drivers/mtd/at24xx.c b/nuttx/drivers/mtd/at24xx.c new file mode 100644 index 0000000000..d157a9c474 --- /dev/null +++ b/nuttx/drivers/mtd/at24xx.c @@ -0,0 +1,429 @@ +/************************************************************************************ + * drivers/mtd/at24xx.c + * Driver for I2C-based at24cxx EEPROM(at24c32,at24c64,at24c128,at24c256) + * + * Copyright (C) 2011 Li Zhuoyi. All rights reserved. + * Author: Li Zhuoyi + * History: 0.1 2011-08-20 initial version + * + * 2011-11-1 Added support for larger MTD block sizes: Hal Glenn + * + * Derived from drivers/mtd/m25px.c + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_MTD_AT24XX + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* As a minimum, the size of the AT24 part and its 7-bit I2C address are required. */ + +#ifndef CONFIG_AT24XX_SIZE +# warning "Assuming AT24 size 64" +# define CONFIG_AT24XX_SIZE 64 +#endif +#ifndef CONFIG_AT24XX_ADDR +# warning "Assuming AT24 address of 0x50" +# define CONFIG_AT24XX_ADDR 0x50 +#endif + +/* Get the part configuration based on the size configuration */ + +#if CONFIG_AT24XX_SIZE == 32 +# define AT24XX_NPAGES 128 +# define AT24XX_PAGESIZE 32 +#elif CONFIG_AT24XX_SIZE == 48 +# define AT24XX_NPAGES 192 +# define AT24XX_PAGESIZE 32 +#elif CONFIG_AT24XX_SIZE == 64 +# define AT24XX_NPAGES 256 +# define AT24XX_PAGESIZE 32 +#elif CONFIG_AT24XX_SIZE == 128 +# define AT24XX_NPAGES 256 +# define AT24XX_PAGESIZE 64 +#elif CONFIG_AT24XX_SIZE == 256 +# define AT24XX_NPAGES 512 +# define AT24XX_PAGESIZE 64 +#endif + +/* For applications where a file system is used on the AT24, the tiny page sizes + * will result in very inefficient FLASH usage. In such cases, it is better if + * blocks are comprised of "clusters" of pages so that the file system block + * size is, say, 256 or 512 bytes. In any event, the block size *must* be an + * even multiple of the pages. + */ + +#ifndef CONFIG_AT24XX_MTD_BLOCKSIZE +# warning "Assuming driver block size is the same as the FLASH page size" +# define CONFIG_AT24XX_MTD_BLOCKSIZE AT24XX_PAGESIZE +#endif + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/* This type represents the state of the MTD device. The struct mtd_dev_s + * must appear at the beginning of the definition so that you can freely + * cast between pointers to struct mtd_dev_s and struct at24c_dev_s. + */ + +struct at24c_dev_s +{ + struct mtd_dev_s mtd; /* MTD interface */ + FAR struct i2c_dev_s *dev; /* Saved I2C interface instance */ + uint8_t addr; /* I2C address */ + uint16_t pagesize; /* 32, 63 */ + uint16_t npages; /* 128, 256, 512, 1024 */ +}; + +/************************************************************************************ + * Private Function Prototypes + ************************************************************************************/ + +/* MTD driver methods */ + +static int at24c_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks); +static ssize_t at24c_bread(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR uint8_t *buf); +static ssize_t at24c_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR const uint8_t *buf); +static ssize_t at24c_read(FAR struct mtd_dev_s *dev, off_t offset, + size_t nbytes,FAR uint8_t *buffer); +static int at24c_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg); + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +/* At present, only a signal AT24 part is supported. In this case, a statically + * allocated state structure may be used. + */ + +static struct at24c_dev_s g_at24c; + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +static int at24c_eraseall(FAR struct at24c_dev_s *priv) +{ + int startblock = 0; + uint8_t buf[AT24XX_PAGESIZE + 2]; + + memset(&buf[2],0xff,priv->pagesize); + I2C_SETADDRESS(priv->dev,priv->addr,7); + I2C_SETFREQUENCY(priv->dev,100000); + + for (startblock = 0; startblock < priv->npages; startblock++) + { + uint16_t offset = startblock * priv->pagesize; + buf[1] = offset & 0xff; + buf[0] = (offset >> 8) & 0xff; + + while (I2C_WRITE(priv->dev, buf, 2) < 0) + { + usleep(1000); + } + I2C_WRITE(priv->dev, buf, priv->pagesize + 2); + } + + return OK; +} + +/************************************************************************************ + * Name: at24c_erase + ************************************************************************************/ + +static int at24c_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks) +{ + /* EEprom need not erase */ + + return (int)nblocks; +} + +/************************************************************************************ + * Name: at24c_bread + ************************************************************************************/ + +static ssize_t at24c_bread(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR uint8_t *buffer) +{ + FAR struct at24c_dev_s *priv = (FAR struct at24c_dev_s *)dev; + size_t blocksleft; + +#if CONFIG_AT24XX_MTD_BLOCKSIZE > AT24XX_PAGESIZE + startblock *= (CONFIG_AT24XX_MTD_BLOCKSIZE / AT24XX_PAGESIZE); + nblocks *= (CONFIG_AT24XX_MTD_BLOCKSIZE / AT24XX_PAGESIZE); +#endif + blocksleft = nblocks; + + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + if (startblock >= priv->npages) + { + return 0; + } + + if (startblock + nblocks > priv->npages) + { + nblocks = priv->npages - startblock; + } + + I2C_SETADDRESS(priv->dev,priv->addr,7); + I2C_SETFREQUENCY(priv->dev,100000); + + while (blocksleft-- > 0) + { + uint16_t offset = startblock * priv->pagesize; + uint8_t buf[2]; + buf[1] = offset & 0xff; + buf[0] = (offset >> 8) & 0xff; + + while (I2C_WRITE(priv->dev, buf, 2) < 0) + { + fvdbg("wait\n"); + usleep(1000); + } + + I2C_READ(priv->dev, buffer, priv->pagesize); + startblock++; + buffer += priv->pagesize; + } + +#if CONFIG_AT24XX_MTD_BLOCKSIZE > AT24XX_PAGESIZE + return nblocks / (CONFIG_AT24XX_MTD_BLOCKSIZE / AT24XX_PAGESIZE); +#else + return nblocks; +#endif +} + +/************************************************************************************ + * Name: at24c_bwrite + * + * Operates on MTD block's and translates to FLASH pages + * + ************************************************************************************/ + +static ssize_t at24c_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR const uint8_t *buffer) +{ + FAR struct at24c_dev_s *priv = (FAR struct at24c_dev_s *)dev; + size_t blocksleft; + uint8_t buf[AT24XX_PAGESIZE+2]; + +#if CONFIG_AT24XX_MTD_BLOCKSIZE > AT24XX_PAGESIZE + startblock *= (CONFIG_AT24XX_MTD_BLOCKSIZE / AT24XX_PAGESIZE); + nblocks *= (CONFIG_AT24XX_MTD_BLOCKSIZE / AT24XX_PAGESIZE); +#endif + blocksleft = nblocks; + + if (startblock >= priv->npages) + { + return 0; + } + + if (startblock + nblocks > priv->npages) + { + nblocks = priv->npages - startblock; + } + + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + I2C_SETADDRESS(priv->dev, priv->addr, 7); + I2C_SETFREQUENCY(priv->dev, 100000); + + while (blocksleft-- > 0) + { + uint16_t offset = startblock * priv->pagesize; + while (I2C_WRITE(priv->dev, (uint8_t *)&offset, 2) < 0) + { + fvdbg("wait\n"); + usleep(1000); + } + + buf[1] = offset & 0xff; + buf[0] = (offset >> 8) & 0xff; + memcpy(&buf[2], buffer, priv->pagesize); + + I2C_WRITE(priv->dev, buf, priv->pagesize + 2); + startblock++; + buffer += priv->pagesize; + } + +#if CONFIG_AT24XX_MTD_BLOCKSIZE > AT24XX_PAGESIZE + return nblocks / (CONFIG_AT24XX_MTD_BLOCKSIZE / AT24XX_PAGESIZE); +#else + return nblocks; +#endif +} + +/************************************************************************************ + * Name: at24c_ioctl + ************************************************************************************/ + +static int at24c_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg) +{ + FAR struct at24c_dev_s *priv = (FAR struct at24c_dev_s *)dev; + int ret = -EINVAL; /* Assume good command with bad parameters */ + + fvdbg("cmd: %d \n", cmd); + + switch (cmd) + { + case MTDIOC_GEOMETRY: + { + FAR struct mtd_geometry_s *geo = (FAR struct mtd_geometry_s *)((uintptr_t)arg); + if (geo) + { + /* Populate the geometry structure with information need to know + * the capacity and how to access the device. + * + * NOTE: that the device is treated as though it where just an array + * of fixed size blocks. That is most likely not true, but the client + * will expect the device logic to do whatever is necessary to make it + * appear so. + * + * blocksize: + * May be user defined. The block size for the at24XX devices may be + * larger than the page size in order to better support file systems. + * The read and write functions translate BLOCKS to pages for the + * small flash devices + * erasesize: + * It has to be at least as big as the blocksize, bigger serves no + * purpose. + * neraseblocks + * Note that the device size is in kilobits and must be scaled by + * 1024 / 8 + */ + +#if CONFIG_AT24XX_MTD_BLOCKSIZE > AT24XX_PAGESIZE + geo->blocksize = CONFIG_AT24XX_MTD_BLOCKSIZE; + geo->erasesize = CONFIG_AT24XX_MTD_BLOCKSIZE; + geo->neraseblocks = (CONFIG_AT24XX_SIZE * 1024 / 8) / CONFIG_AT24XX_MTD_BLOCKSIZE; +#else + geo->blocksize = priv->pagesize; + geo->erasesize = priv->pagesize; + geo->neraseblocks = priv->npages; +#endif + ret = OK; + + fvdbg("blocksize: %d erasesize: %d neraseblocks: %d\n", + geo->blocksize, geo->erasesize, geo->neraseblocks); + } + } + break; + + case MTDIOC_BULKERASE: + ret=at24c_eraseall(priv); + break; + + case MTDIOC_XIPBASE: + default: + ret = -ENOTTY; /* Bad command */ + break; + } + + return ret; +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: at24c_initialize + * + * Description: + * Create an initialize MTD device instance. MTD devices are not registered + * in the file system, but are created as instances that can be bound to + * other functions (such as a block or character driver front end). + * + ************************************************************************************/ + +FAR struct mtd_dev_s *at24c_initialize(FAR struct i2c_dev_s *dev) +{ + FAR struct at24c_dev_s *priv; + + fvdbg("dev: %p\n", dev); + + /* Allocate a state structure (we allocate the structure instead of using + * a fixed, static allocation so that we can handle multiple FLASH devices. + * The current implementation would handle only one FLASH part per I2C + * device (only because of the SPIDEV_FLASH definition) and so would have + * to be extended to handle multiple FLASH parts on the same I2C bus. + */ + + priv = &g_at24c; + if (priv) + { + /* Initialize the allocated structure */ + + priv->addr = CONFIG_AT24XX_ADDR; + priv->pagesize = AT24XX_PAGESIZE; + priv->npages = AT24XX_NPAGES; + + priv->mtd.erase = at24c_erase; + priv->mtd.bread = at24c_bread; + priv->mtd.bwrite = at24c_bwrite; + priv->mtd.ioctl = at24c_ioctl; + priv->dev = dev; + } + + /* Return the implementation-specific state structure as the MTD device */ + + fvdbg("Return %p\n", priv); + return (FAR struct mtd_dev_s *)priv; +} + +#endif diff --git a/nuttx/drivers/mtd/at45db.c b/nuttx/drivers/mtd/at45db.c new file mode 100644 index 0000000000..f4a695de01 --- /dev/null +++ b/nuttx/drivers/mtd/at45db.c @@ -0,0 +1,899 @@ +/************************************************************************************ + * drivers/mtd/at45db.c + * Driver for SPI-based AT45DB161D (16Mbit) + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/* Ordering Code Detail: + * + * AT 45DB 16 1 D – SS U + * | | | | | | `- Device grade + * | | | | | `- Package Option + * | | | | `- Device revision + * | | | `- Interface: 1=serial + * | | `- Capacity: 16=16Mbit + * | `- Product family + * `- Atmel designator + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Configuration ********************************************************************/ +/* CONFIG_AT45DB_PREWAIT enables higher performance write logic: We leave the chip + * busy after write and erase operations. This improves write and erase performance + * because we do not have to wait as long between transactions (other processing can + * occur while the chip is busy) but means that the chip must stay powered: + */ + +#if defined(CONFIG_AT45DB_PWRSAVE) && defined(CONFIG_AT45DB_PREWAIT) +# error "Both CONFIG_AT45DB_PWRSAVE and CONFIG_AT45DB_PREWAIT are defined" +#endif + +/* If the user has provided no frequency, use 1MHz */ + +#ifndef CONFIG_AT45DB_FREQUENCY +# define CONFIG_AT45DB_FREQUENCY 1000000 +#endif + +/* SPI Commands *********************************************************************/ + +/* Read commands */ + +#define AT45DB_RDMN 0xd2 /* Main Memory Page Read */ +#define AT45DB_RDARRY 0xe8 /* Continuous Array Read (Legacy Command) */ +#define AT45DB_RDARRAYLF 0x03 /* Continuous Array Read (Low Frequency) */ +#define AT45DB_RDARRAYHF 0x0b /* Continuous Array Read (High Frequency) */ +#define AT45DB_RDBF1LF 0xd1 /* Buffer 1 Read (Low Frequency) */ +#define AT45DB_RDBF2LF 0xd3 /* Buffer 2 Read (Low Frequency) */ +#define AT45DB_RDBF1 0xd4 /* Buffer 1 Read */ +#define AT45DB_RDBF2 0xd6 /* Buffer 2 Read */ + +/* Program and Erase Commands */ + +#define AT45DB_WRBF1 0x84 /* Buffer 1 Write */ +#define AT45DB_WRBF2 0x87 /* Buffer 2 Write */ +#define AT45DB_BF1TOMNE 0x83 /* Buffer 1 to Main Memory Page Program with Built-in Erase */ +#define AT45DB_BF2TOMNE 0x86 /* Buffer 2 to Main Memory Page Program with Built-in Erase */ +#define AT45DB_BF1TOMN 0x88 /* Buffer 1 to Main Memory Page Program without Built-in Erase */ +#define AT45DB_BF2TOMN 0x89 /* Buffer 2 to Main Memory Page Program without Built-in Erase */ +#define AT45DB_PGERASE 0x81 /* Page Erase */ +#define AT45DB_BLKERASE 0x50 /* Block Erase */ +#define AT45DB_SECTERASE 0x7c /* Sector Erase */ +#define AT45DB_CHIPERASE1 0xc7 /* Chip Erase - byte 1 */ +# define AT45DB_CHIPERASE2 0x94 /* Chip Erase - byte 2 */ +# define AT45DB_CHIPERASE3 0x80 /* Chip Erase - byte 3 */ +# define AT45DB_CHIPERASE4 0x9a /* Chip Erase - byte 4 */ +#define AT45DB_MNTHRUBF1 0x82 /* Main Memory Page Program Through Buffer 1 */ +#define AT45DB_MNTHRUBF2 0x85 /* Main Memory Page Program Through Buffer 2 */ + +/* Protection and Security Commands */ + +#define AT45DB_ENABPROT1 0x3d /* Enable Sector Protection - byte 1 */ +# define AT45DB_ENABPROT2 0x2a /* Enable Sector Protection - byte 2 */ +# define AT45DB_ENABPROT3 0x7f /* Enable Sector Protection - byte 3 */ +# define AT45DB_ENABPROT4 0xa9 /* Enable Sector Protection - byte 4 */ +#define AT45DB_DISABPROT1 0x3d /* Disable Sector Protection - byte 1 */ +# define AT45DB_DISABPROT2 0x2a /* Disable Sector Protection - byte 2 */ +# define AT45DB_DISABPROT3 0x7f /* Disable Sector Protection - byte 3 */ +# define AT45DB_DISABPROT4 0x9a /* Disable Sector Protection - byte 4 */ +#define AT45DB_ERASEPROT1 0x3d /* Erase Sector Protection Register - byte 1 */ +# define AT45DB_ERASEPROT2 0x2a /* Erase Sector Protection Register - byte 2 */ +# define AT45DB_ERASEPROT3 0x7f /* Erase Sector Protection Register - byte 3 */ +# define AT45DB_ERASEPROT4 0xcf /* Erase Sector Protection Register - byte 4 */ +#define AT45DB_PROGPROT1 0x3d /* Program Sector Protection Register - byte 1 */ +# define AT45DB_PROGPROT2 0x2a /* Program Sector Protection Register - byte 2 */ +# define AT45DB_PROGPROT3 0x7f /* Program Sector Protection Register - byte 3 */ +# define AT45DB_PROGPROT4 0xfc /* Program Sector Protection Register - byte 4 */ +#define AT45DB_RDPROT 0x32 /* Read Sector Protection Register */ +#define AT45DB_LOCKDOWN1 0x3d /* Sector Lockdown - byte 1 */ +# define AT45DB_LOCKDOWN2 0x2a /* Sector Lockdown - byte 2 */ +# define AT45DB_LOCKDOWN3 0x7f /* Sector Lockdown - byte 3 */ +# define AT45DB_LOCKDOWN4 0x30 /* Sector Lockdown - byte 4 */ +#define AT45DB_RDLOCKDOWN 0x35 /* Read Sector Lockdown Register */ +#define AT45DB_PROGSEC1 0x9b /* Program Security Register - byte 1 */ +# define AT45DB_PROGSEC2 0x00 /* Program Security Register - byte 2 */ +# define AT45DB_PROGSEC3 0x00 /* Program Security Register - byte 3 */ +# define AT45DB_PROGSEC4 0x00 /* Program Security Register - byte 4 */ +#define AT45DB_RDSEC 0x77 /* Read Security Register */ + +/* Additional commands */ + +#define AT45DB_MNTOBF1XFR 0x53 /* Main Memory Page to Buffer 1 Transfer */ +#define AT45DB_MNTOBF2XFR 0x55 /* Main Memory Page to Buffer 2 Transfer */ +#define AT45DB_MNBF1CMP 0x60 /* Main Memory Page to Buffer 1 Compare */ +#define AT45DB_MNBF2CMP 0x61 /* Main Memory Page to Buffer 2 Compare */ +#define AT45DB_AUTOWRBF1 0x58 /* Auto Page Rewrite through Buffer 1 */ +#define AT45DB_AUTOWRBF2 0x59 /* Auto Page Rewrite through Buffer 2 */ +#define AT45DB_PWRDOWN 0xb9 /* Deep Power-down */ +#define AT45DB_RESUME 0xab /* Resume from Deep Power-down */ +#define AT45DB_RDSR 0xd7 /* Status Register Read */ +#define AT45DB_RDDEVID 0x9f /* Manufacturer and Device ID Read */ + +#define AT45DB_MANUFACTURER 0x1f /* Manufacturer ID: Atmel */ +#define AT45DB_DEVID1_CAPMSK 0x1f /* Bits 0-4: Capacity */ +#define AT45DB_DEVID1_1MBIT 0x02 /* xxx0 0010 = 1Mbit AT45DB011 */ +#define AT45DB_DEVID1_2MBIT 0x03 /* xxx0 0012 = 2Mbit AT45DB021 */ +#define AT45DB_DEVID1_4MBIT 0x04 /* xxx0 0100 = 4Mbit AT45DB041 */ +#define AT45DB_DEVID1_8MBIT 0x05 /* xxx0 0101 = 8Mbit AT45DB081 */ +#define AT45DB_DEVID1_16MBIT 0x06 /* xxx0 0110 = 16Mbit AT45DB161 */ +#define AT45DB_DEVID1_32MBIT 0x07 /* xxx0 0111 = 32Mbit AT45DB321 */ +#define AT45DB_DEVID1_64MBIT 0x08 /* xxx0 1000 = 32Mbit AT45DB641 */ +#define AT45DB_DEVID1_FAMMSK 0xe0 /* Bits 5-7: Family */ +#define AT45DB_DEVID1_DFLASH 0x20 /* 001x xxxx = Dataflash */ +#define AT45DB_DEVID1_AT26DF 0x40 /* 010x xxxx = AT26DFxxx series (Not supported) */ +#define AT45DB_DEVID2_VERMSK 0x1f /* Bits 0-4: MLC mask */ +#define AT45DB_DEVID2_MLCMSK 0xe0 /* Bits 5-7: MLC mask */ + +/* Status register bit definitions */ + +#define AT45DB_SR_RDY (1 << 7) /* Bit 7: RDY/ Not BUSY */ +#define AT45DB_SR_COMP (1 << 6) /* Bit 6: COMP */ +#define AT45DB_SR_PROTECT (1 << 1) /* Bit 1: PROTECT */ +#define AT45DB_SR_PGSIZE (1 << 0) /* Bit 0: PAGE_SIZE */ + +/* 1 Block = 16 pages; 1 sector = 256 pages */ + +#define PG_PER_BLOCK (16) +#define PG_PER_SECTOR (256) + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/* This type represents the state of the MTD device. The struct mtd_dev_s + * must appear at the beginning of the definition so that you can freely + * cast between pointers to struct mtd_dev_s and struct at45db_dev_s. + */ + +struct at45db_dev_s +{ + struct mtd_dev_s mtd; /* MTD interface */ + FAR struct spi_dev_s *spi; /* Saved SPI interface instance */ + uint8_t pageshift; /* log2 of the page size (eg. 1 << 9 = 512) */ + uint32_t npages; /* Number of pages in the device */ +}; + +/************************************************************************************ + * Private Function Prototypes + ************************************************************************************/ + +/* Lock and per-transaction configuration */ + +static void at45db_lock(struct at45db_dev_s *priv); +static inline void at45db_unlock(struct at45db_dev_s *priv); + +/* Power management */ + +#ifdef CONFIG_AT45DB_PWRSAVE +static void at45db_pwrdown(struct at45db_dev_s *priv); +static void at45db_resume(struct at45db_dev_s *priv); +#else +# define at45db_pwrdown(priv) +# define at45db_resume(priv) +#endif + +/* Low-level AT45DB Helpers */ + +static inline int at45db_rdid(struct at45db_dev_s *priv); +static inline uint8_t at45db_rdsr(struct at45db_dev_s *priv); +static uint8_t at45db_waitbusy(struct at45db_dev_s *priv); +static inline void at45db_pgerase(struct at45db_dev_s *priv, off_t offset); +static inline int at32db_chiperase(struct at45db_dev_s *priv); +static inline void at45db_pgwrite(struct at45db_dev_s *priv, FAR const uint8_t *buffer, + off_t offset); + +/* MTD driver methods */ + +static int at45db_erase(FAR struct mtd_dev_s *mtd, off_t startblock, size_t nblocks); +static ssize_t at45db_bread(FAR struct mtd_dev_s *mtd, off_t startblock, + size_t nblocks, FAR uint8_t *buf); +static ssize_t at45db_bwrite(FAR struct mtd_dev_s *mtd, off_t startblock, + size_t nblocks, FAR const uint8_t *buf); +static ssize_t at45db_read(FAR struct mtd_dev_s *mtd, off_t offset, size_t nbytes, + FAR uint8_t *buffer); +static int at45db_ioctl(FAR struct mtd_dev_s *mtd, int cmd, unsigned long arg); + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +/* Chip erase sequence */ + +#define CHIP_ERASE_SIZE 4 +static const uint8_t g_chiperase[CHIP_ERASE_SIZE] = {0xc7, 0x94, 0x80, 0x9a}; + +/* Sequence to program the device to binary page sizes{256, 512, 1024} */ + +#define BINPGSIZE_SIZE 4 +static const uint8_t g_binpgsize[BINPGSIZE_SIZE] = {0x3d, 0x2a, 0x80, 0xa6}; + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: at45db_lock + ************************************************************************************/ + +static void at45db_lock(struct at45db_dev_s *priv) +{ + /* On SPI busses where there are multiple devices, it will be necessary to + * lock SPI to have exclusive access to the busses for a sequence of + * transfers. The bus should be locked before the chip is selected. + * + * This is a blocking call and will not return until we have exclusiv access to + * the SPI buss. We will retain that exclusive access until the bus is unlocked. + */ + + (void)SPI_LOCK(priv->spi, true); + + /* After locking the SPI bus, the we also need call the setfrequency, setbits, and + * setmode methods to make sure that the SPI is properly configured for the device. + * If the SPI buss is being shared, then it may have been left in an incompatible + * state. + */ + + SPI_SETMODE(priv->spi, SPIDEV_MODE0); + SPI_SETBITS(priv->spi, 8); + (void)SPI_SETFREQUENCY(priv->spi, CONFIG_AT45DB_FREQUENCY); +} + +/************************************************************************************ + * Name: at45db_unlock + ************************************************************************************/ + +static inline void at45db_unlock(struct at45db_dev_s *priv) +{ + (void)SPI_LOCK(priv->spi, false); +} + +/************************************************************************************ + * Name: at45db_pwrdown + ************************************************************************************/ + +#ifdef CONFIG_AT45DB_PWRSAVE +static void at45db_pwrdown(struct at45db_dev_s *priv) +{ + SPI_SELECT(priv->spi, SPIDEV_FLASH, true); + SPI_SEND(priv->spi, AT45DB_PWRDOWN); + SPI_SELECT(priv->spi, SPIDEV_FLASH, false); +} +#endif + +/************************************************************************************ + * Name: at45db_resume + ************************************************************************************/ + +#ifdef CONFIG_AT45DB_PWRSAVE +static void at45db_resume(struct at45db_dev_s *priv) +{ + SPI_SELECT(priv->spi, SPIDEV_FLASH, true); + SPI_SEND(priv->spi, AT45DB_RESUME); + SPI_SELECT(priv->spi, SPIDEV_FLASH, false); + up_udelay(50); +} +#endif + +/************************************************************************************ + * Name: at45db_rdid + ************************************************************************************/ + +static inline int at45db_rdid(struct at45db_dev_s *priv) +{ + uint8_t capacity; + uint8_t devid[3]; + + fvdbg("priv: %p\n", priv); + + /* Configure the bus, and select this FLASH part. (The caller should alread have + * loced the bus for exclusive access) + */ + + SPI_SELECT(priv->spi, SPIDEV_FLASH, true); + + /* Send the " Manufacturer and Device ID Read" command and read the next three + * ID bytes from the FLASH. + */ + + (void)SPI_SEND(priv->spi, AT45DB_RDDEVID); + SPI_RECVBLOCK(priv->spi, devid, 3); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->spi, SPIDEV_FLASH, false); + + fvdbg("manufacturer: %02x devid1: %02x devid2: %02x\n", + devid[0], devid[1], devid[2]); + + /* Check for a valid manufacturer and memory family */ + + if (devid[0] == AT45DB_MANUFACTURER && + (devid[1] & AT45DB_DEVID1_FAMMSK) == AT45DB_DEVID1_DFLASH) + { + /* Okay.. is it a FLASH capacity that we understand? */ + + capacity = devid[1] & AT45DB_DEVID1_CAPMSK; + switch (capacity) + { + case AT45DB_DEVID1_1MBIT: + /* Save the FLASH geometry for the 16Mbit AT45DB011 */ + + priv->pageshift = 8; /* Page size = 256 bytes */ + priv->npages = 512; /* 512 pages */ + return OK; + + case AT45DB_DEVID1_2MBIT: + /* Save the FLASH geometry for the 16Mbit AT45DB021 */ + + priv->pageshift = 8; /* Page size = 256/264 bytes */ + priv->npages = 1024; /* 1024 pages */ + return OK; + + case AT45DB_DEVID1_4MBIT: + /* Save the FLASH geometry for the 16Mbit AT45DB041 */ + + priv->pageshift = 8; /* Page size = 256/264 bytes */ + priv->npages = 2048; /* 2048 pages */ + return OK; + + case AT45DB_DEVID1_8MBIT: + /* Save the FLASH geometry for the 16Mbit AT45DB081 */ + + priv->pageshift = 8; /* Page size = 256/264 bytes */ + priv->npages = 4096; /* 4096 pages */ + return OK; + + case AT45DB_DEVID1_16MBIT: + /* Save the FLASH geometry for the 16Mbit AT45DB161 */ + + priv->pageshift = 9; /* Page size = 512/528 bytes */ + priv->npages = 4096; /* 4096 pages */ + return OK; + + case AT45DB_DEVID1_32MBIT: + /* Save the FLASH geometry for the 16Mbit AT45DB321 */ + + priv->pageshift = 9; /* Page size = 512/528 bytes */ + priv->npages = 8192; /* 8192 pages */ + return OK; + + case AT45DB_DEVID1_64MBIT: + /* Save the FLASH geometry for the 16Mbit AT45DB321 */ + + priv->pageshift = 10; /* Page size = 1024/1056 bytes */ + priv->npages = 8192; /* 8192 pages */ + return OK; + + default: + return -ENODEV; + } + } + + return -ENODEV; +} + +/************************************************************************************ + * Name: at45db_rdsr + ************************************************************************************/ + +static inline uint8_t at45db_rdsr(struct at45db_dev_s *priv) +{ + uint8_t retval; + + SPI_SELECT(priv->spi, SPIDEV_FLASH, true); + SPI_SEND(priv->spi, AT45DB_RDSR); + retval = SPI_SEND(priv->spi, 0xff); + SPI_SELECT(priv->spi, SPIDEV_FLASH, false); + return retval; +} + +/************************************************************************************ + * Name: at45db_waitbusy + ************************************************************************************/ + +static uint8_t at45db_waitbusy(struct at45db_dev_s *priv) +{ + uint8_t sr; + + /* Poll the device, waiting for it to report that it is ready */ + + do + { + up_udelay(10); + sr = (uint8_t)at45db_rdsr(priv); + } + while ((sr & AT45DB_SR_RDY) == 0); + return sr; +} + +/************************************************************************************ + * Name: at45db_pgerase + ************************************************************************************/ + +static inline void at45db_pgerase(struct at45db_dev_s *priv, off_t sector) +{ + uint8_t erasecmd[4]; + off_t offset = sector << priv->pageshift; + + fvdbg("sector: %08lx\n", (long)sector); + + /* Higher performance write logic: We leave the chip busy after write and erase + * operations. This improves write and erase performance because we do not have + * to wait as long between transactions (other processing can occur while the chip + * is busy) but means that the chip must stay powered and that we must check if + * the chip is still busy on each entry point. + */ + +#ifdef CONFIG_AT45DB_PREWAIT + at45db_waitbusy(priv); +#endif + + /* "The Page Erase command can be used to individually erase any page in the main + * memory array allowing the Buffer to Main Memory Page Program to be utilized at a + * later time. ... To perform a page erase in the binary page size ..., the + * opcode 81H must be loaded into the device, followed by three address bytes + * ... When a low-to-high transition occurs on the CS pin, the part will erase the + * selected page (the erased state is a logical 1). ... the status register and the + * RDY/BUSY pin will indicate that the part is busy." + */ + + erasecmd[0] = AT45DB_PGERASE; /* Page erase command */ + erasecmd[1] = (offset >> 16) & 0xff; /* 24-bit offset MS bytes */ + erasecmd[2] = (offset >> 8) & 0xff; /* 24-bit offset middle bytes */ + erasecmd[3] = offset & 0xff; /* 24-bit offset LS bytes */ + + /* Erase the page */ + + SPI_SELECT(priv->spi, SPIDEV_FLASH, true); + SPI_SNDBLOCK(priv->spi, erasecmd, 4); + SPI_SELECT(priv->spi, SPIDEV_FLASH, false); + + /* Wait for any erase to complete if we are not trying to improve write + * performance. (see comments above). + */ + +#ifndef CONFIG_AT45DB_PREWAIT + at45db_waitbusy(priv); +#endif + fvdbg("Erased\n"); +} + +/************************************************************************************ + * Name: at32db_chiperase + ************************************************************************************/ + +static inline int at32db_chiperase(struct at45db_dev_s *priv) +{ + fvdbg("priv: %p\n", priv); + + /* Higher performance write logic: We leave the chip busy after write and erase + * operations. This improves write and erase performance because we do not have + * to wait as long between transactions (other processing can occur while the chip + * is busy) but means that the chip must stay powered and that we must check if + * the chip is still busy on each entry point. + */ + +#ifdef CONFIG_AT45DB_PREWAIT + at45db_waitbusy(priv); +#endif + + /* "The entire main memory can be erased at one time by using the Chip Erase + * command. To execute the Chip Erase command, a 4-byte command sequence C7H, 94H, + * 80H and 9AH must be clocked into the device. ... After the last bit of the opcode + * sequence has been clocked in, the CS pin can be deasserted to start the erase + * process. ... the Status Register will indicate that the device is busy. The Chip + * Erase command will not affect sectors that are protected or locked down... + */ + + SPI_SELECT(priv->spi, SPIDEV_FLASH, true); + SPI_SNDBLOCK(priv->spi, g_chiperase, CHIP_ERASE_SIZE); + SPI_SELECT(priv->spi, SPIDEV_FLASH, false); + + /* Wait for any erase to complete if we are not trying to improve write + * performance. (see comments above). + */ + +#ifndef CONFIG_AT45DB_PREWAIT + at45db_waitbusy(priv); +#endif + return OK; +} + +/************************************************************************************ + * Name: at45db_pgwrite + ************************************************************************************/ + +static inline void at45db_pgwrite(struct at45db_dev_s *priv, FAR const uint8_t *buffer, + off_t page) +{ + uint8_t wrcmd [4]; + off_t offset = page << priv->pageshift; + + fvdbg("page: %08lx offset: %08lx\n", (long)page, (long)offset); + + /* We assume that sectors are not write protected */ + + wrcmd[0] = AT45DB_MNTHRUBF1; /* To main memory through buffer 1 */ + wrcmd[1] = (offset >> 16) & 0xff; /* 24-bit address MS byte */ + wrcmd[2] = (offset >> 8) & 0xff; /* 24-bit address middle byte */ + wrcmd[3] = offset & 0xff; /* 24-bit address LS byte */ + + /* Higher performance write logic: We leave the chip busy after write and erase + * operations. This improves write and erase performance because we do not have + * to wait as long between transactions (other processing can occur while the chip + * is busy) but means that the chip must stay powered and that we must check if + * the chip is still busy on each entry point. + */ + +#ifdef CONFIG_AT45DB_PREWAIT + at45db_waitbusy(priv); +#endif + + SPI_SELECT(priv->spi, SPIDEV_FLASH, true); + SPI_SNDBLOCK(priv->spi, wrcmd, 4); + SPI_SNDBLOCK(priv->spi, buffer, 1 << priv->pageshift); + SPI_SELECT(priv->spi, SPIDEV_FLASH, false); + + /* Wait for any erase to complete if we are not trying to improve write + * performance. (see comments above). + */ + +#ifndef CONFIG_AT45DB_PREWAIT + at45db_waitbusy(priv); +#endif + fvdbg("Written\n"); +} + +/************************************************************************************ + * Name: at45db_erase + ************************************************************************************/ + +static int at45db_erase(FAR struct mtd_dev_s *mtd, off_t startblock, size_t nblocks) +{ + FAR struct at45db_dev_s *priv = (FAR struct at45db_dev_s *)mtd; + size_t pgsleft = nblocks; + + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + /* Take the lock so that we have exclusive access to the bus, then power up the + * FLASH device. + */ + + at45db_lock(priv); + at45db_resume(priv); + + /* Then erase each page */ + + while (pgsleft-- > 0) + { + /* Erase each sector */ + + at45db_pgerase(priv, startblock); + startblock++; + } + + at45db_pwrdown(priv); + at45db_unlock(priv); + return (int)nblocks; +} + +/************************************************************************************ + * Name: at45db_bread + ************************************************************************************/ + +static ssize_t at45db_bread(FAR struct mtd_dev_s *mtd, off_t startblock, size_t nblocks, + FAR uint8_t *buffer) +{ + FAR struct at45db_dev_s *priv = (FAR struct at45db_dev_s *)mtd; + ssize_t nbytes; + + /* On this device, we can handle the block read just like the byte-oriented read */ + + nbytes = at45db_read(mtd, startblock << priv->pageshift, nblocks << priv->pageshift, buffer); + if (nbytes > 0) + { + return nbytes >> priv->pageshift; + } + return nbytes; +} + +/************************************************************************************ + * Name: at45db_bwrite + ************************************************************************************/ + +static ssize_t at45db_bwrite(FAR struct mtd_dev_s *mtd, off_t startblock, size_t nblocks, + FAR const uint8_t *buffer) +{ + FAR struct at45db_dev_s *priv = (FAR struct at45db_dev_s *)mtd; + size_t pgsleft = nblocks; + + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + /* Take the lock so that we have exclusive access to the bus, then power up the + * FLASH device. + */ + + at45db_lock(priv); + at45db_resume(priv); + + /* Write each page to FLASH */ + + while (pgsleft-- > 0) + { + at45db_pgwrite(priv, buffer, startblock); + startblock++; + } + + at45db_pwrdown(priv); + at45db_unlock(priv); + + return nblocks; +} + +/************************************************************************************ + * Name: at45db_read + ************************************************************************************/ + +static ssize_t at45db_read(FAR struct mtd_dev_s *mtd, off_t offset, size_t nbytes, + FAR uint8_t *buffer) +{ + FAR struct at45db_dev_s *priv = (FAR struct at45db_dev_s *)mtd; + uint8_t rdcmd [5]; + + fvdbg("offset: %08lx nbytes: %d\n", (long)offset, (int)nbytes); + + /* Set up for the read */ + + rdcmd[0] = AT45DB_RDARRAYHF; /* FAST_READ is safe at all supported SPI speeds. */ + rdcmd[1] = (offset >> 16) & 0xff; /* 24-bit address upper byte */ + rdcmd[2] = (offset >> 8) & 0xff; /* 24-bit address middle byte */ + rdcmd[3] = offset & 0xff; /* 24-bit address least significant byte */ + rdcmd[4] = 0; /* Dummy byte */ + + /* Take the lock so that we have exclusive access to the bus, then power up the + * FLASH device. + */ + + at45db_lock(priv); + at45db_resume(priv); + + /* Higher performance write logic: We leave the chip busy after write and erase + * operations. This improves write and erase performance because we do not have + * to wait as long between transactions (other processing can occur while the chip + * is busy) but means that the chip must stay powered and that we must check if + * the chip is still busy on each entry point. + */ + +#ifdef CONFIG_AT45DB_PREWAIT + at45db_waitbusy(priv); +#endif + + /* Perform the read */ + + SPI_SELECT(priv->spi, SPIDEV_FLASH, true); + SPI_SNDBLOCK(priv->spi, rdcmd, 5); + SPI_RECVBLOCK(priv->spi, buffer, nbytes); + SPI_SELECT(priv->spi, SPIDEV_FLASH, false); + + at45db_pwrdown(priv); + at45db_unlock(priv); + + fvdbg("return nbytes: %d\n", (int)nbytes); + return nbytes; +} + +/************************************************************************************ + * Name: at45db_ioctl + ************************************************************************************/ + +static int at45db_ioctl(FAR struct mtd_dev_s *mtd, int cmd, unsigned long arg) +{ + FAR struct at45db_dev_s *priv = (FAR struct at45db_dev_s *)mtd; + int ret = -EINVAL; /* Assume good command with bad parameters */ + + fvdbg("cmd: %d \n", cmd); + + switch (cmd) + { + case MTDIOC_GEOMETRY: + { + FAR struct mtd_geometry_s *geo = (FAR struct mtd_geometry_s *)((uintptr_t)arg); + if (geo) + { + /* Populate the geometry structure with information need to know + * the capacity and how to access the device. + * + * NOTE: that the device is treated as though it where just an array + * of fixed size blocks. That is most likely not true, but the client + * will expect the device logic to do whatever is necessary to make it + * appear so. + */ + + geo->blocksize = (1 << priv->pageshift); + geo->erasesize = geo->blocksize; + geo->neraseblocks = priv->npages; + ret = OK; + + fvdbg("blocksize: %d erasesize: %d neraseblocks: %d\n", + geo->blocksize, geo->erasesize, geo->neraseblocks); + } + } + break; + + case MTDIOC_BULKERASE: + { + /* Take the lock so that we have exclusive access to the bus, then + * power up the FLASH device. + */ + + at45db_lock(priv); + at45db_resume(priv); + + /* Erase the entire device */ + + ret = at32db_chiperase(priv); + at45db_pwrdown(priv); + at45db_unlock(priv); + } + break; + + case MTDIOC_XIPBASE: + default: + ret = -ENOTTY; /* Bad command */ + break; + } + + fvdbg("return %d\n", ret); + return ret; +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: at45db_initialize + * + * Description: + * Create an initialize MTD device instance. MTD devices are not registered + * in the file system, but are created as instances that can be bound to + * other functions (such as a block or character driver front end). + * + ************************************************************************************/ + +FAR struct mtd_dev_s *at45db_initialize(FAR struct spi_dev_s *spi) +{ + FAR struct at45db_dev_s *priv; + uint8_t sr; + int ret; + + fvdbg("spi: %p\n", spi); + + /* Allocate a state structure (we allocate the structure instead of using + * a fixed, static allocation so that we can handle multiple FLASH devices. + * The current implementation would handle only one FLASH part per SPI + * device (only because of the SPIDEV_FLASH definition) and so would have + * to be extended to handle multiple FLASH parts on the same SPI bus. + */ + + priv = (FAR struct at45db_dev_s *)kmalloc(sizeof(struct at45db_dev_s)); + if (priv) + { + /* Initialize the allocated structure */ + + priv->mtd.erase = at45db_erase; + priv->mtd.bread = at45db_bread; + priv->mtd.bwrite = at45db_bwrite; + priv->mtd.read = at45db_read; + priv->mtd.ioctl = at45db_ioctl; + priv->spi = spi; + + /* Deselect the FLASH */ + + SPI_SELECT(spi, SPIDEV_FLASH, false); + + /* Lock and configure the SPI bus. */ + + at45db_lock(priv); + at45db_resume(priv); + + /* Identify the FLASH chip and get its capacity */ + + ret = at45db_rdid(priv); + if (ret != OK) + { + /* Unrecognized! Discard all of that work we just did and return NULL */ + + fdbg("Unrecognized\n"); + goto errout; + } + + /* Get the value of the status register (as soon as the device is ready) */ + + sr = at45db_waitbusy(priv); + + /* Check if the device is configured as 256, 512 or 1024 bytes-per-page device */ + + if ((sr & AT45DB_SR_PGSIZE) == 0) + { + /* No, re-program it for the binary page size. NOTE: A power cycle + * is required after the device has be re-programmed. + */ + + fdbg("Reprogramming page size\n"); + SPI_SELECT(priv->spi, SPIDEV_FLASH, true); + SPI_SNDBLOCK(priv->spi, g_binpgsize, BINPGSIZE_SIZE); + SPI_SELECT(priv->spi, SPIDEV_FLASH, false); + goto errout; + } + + /* Release the lock and power down the device */ + + at45db_pwrdown(priv); + at45db_unlock(priv); + } + + fvdbg("Return %p\n", priv); + return (FAR struct mtd_dev_s *)priv; + +/* On any failure, we need free memory allocations and release the lock that + * we hold on the SPI bus. On failures, assume that we cannot talk to the + * device to do any more. + */ + +errout: + at45db_unlock(priv); + kfree(priv); + return NULL; +} diff --git a/nuttx/drivers/mtd/flash_eraseall.c b/nuttx/drivers/mtd/flash_eraseall.c new file mode 100644 index 0000000000..77666ff03d --- /dev/null +++ b/nuttx/drivers/mtd/flash_eraseall.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * drivers/mtd/flash_eraseall.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Private Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: flash_eraseall + * + * Description: + * Call a block driver with the MDIOC_BULKERASE ioctl command. This will + * cause the MTD driver to erase all of the flash. + * + ****************************************************************************/ + +int flash_eraseall(FAR const char *driver) +{ + FAR struct inode *inode; + FAR const struct block_operations *ops; + int ret; + + /* Open the block driver */ + + ret = open_blockdriver(driver ,0, &inode); + if (ret < 0) + { + fdbg("ERROR: Failed to open '%s': %d\n", driver, ret); + return ret; + } + + /* Get the block operations */ + + ops = inode->u.i_bops; + + /* Invoke the block driver ioctl method */ + + ret = -EPERM; + if (ops->ioctl) + { + ret = ops->ioctl(inode, MTDIOC_BULKERASE, 0); + if (ret < 0) + { + fdbg("ERROR: MTD ioctl(%04x) failed: %d\n", MTDIOC_BULKERASE, ret); + } + } + + /* Close the block driver */ + + close_blockdriver(inode); + return ret; +} diff --git a/nuttx/drivers/mtd/ftl.c b/nuttx/drivers/mtd/ftl.c new file mode 100644 index 0000000000..b16397883f --- /dev/null +++ b/nuttx/drivers/mtd/ftl.c @@ -0,0 +1,578 @@ +/**************************************************************************** + * drivers/mtd/ftl.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Private Definitions + ****************************************************************************/ + +#if defined(CONFIG_FS_READAHEAD) || (defined(CONFIG_FS_WRITABLE) && defined(CONFIG_FS_WRITEBUFFER)) +# defined CONFIG_FTL_RWBUFFER 1 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct ftl_struct_s +{ + FAR struct mtd_dev_s *mtd; /* Contained MTD interface */ + struct mtd_geometry_s geo; /* Device geometry */ +#ifdef CONFIG_FTL_RWBUFFER + struct rwbuffer_s rwb; /* Read-ahead/write buffer support */ +#endif + uint16_t blkper; /* R/W blocks per erase block */ +#ifdef CONFIG_FS_WRITABLE + FAR uint8_t *eblock; /* One, in-memory erase block */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int ftl_open(FAR struct inode *inode); +static int ftl_close(FAR struct inode *inode); +static ssize_t ftl_reload(FAR void *priv, FAR uint8_t *buffer, + off_t startblock, size_t nblocks); +static ssize_t ftl_read(FAR struct inode *inode, unsigned char *buffer, + size_t start_sector, unsigned int nsectors); +#ifdef CONFIG_FS_WRITABLE +static ssize_t ftl_flush(FAR void *priv, FAR const uint8_t *buffer, + off_t startblock, size_t nblocks); +static ssize_t ftl_write(FAR struct inode *inode, const unsigned char *buffer, + size_t start_sector, unsigned int nsectors); +#endif +static int ftl_geometry(FAR struct inode *inode, struct geometry *geometry); +static int ftl_ioctl(FAR struct inode *inode, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct block_operations g_bops = +{ + ftl_open, /* open */ + ftl_close, /* close */ + ftl_read, /* read */ +#ifdef CONFIG_FS_WRITABLE + ftl_write, /* write */ +#else + NULL, /* write */ +#endif + ftl_geometry, /* geometry */ + ftl_ioctl /* ioctl */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ftl_open + * + * Description: Open the block device + * + ****************************************************************************/ + +static int ftl_open(FAR struct inode *inode) +{ + fvdbg("Entry\n"); + return OK; +} + +/**************************************************************************** + * Name: ftl_close + * + * Description: close the block device + * + ****************************************************************************/ + +static int ftl_close(FAR struct inode *inode) +{ + fvdbg("Entry\n"); + return OK; +} + +/**************************************************************************** + * Name: ftl_reload + * + * Description: Read the specified numer of sectors + * + ****************************************************************************/ + +static ssize_t ftl_reload(FAR void *priv, FAR uint8_t *buffer, + off_t startblock, size_t nblocks) +{ + struct ftl_struct_s *dev = (struct ftl_struct_s *)priv; + ssize_t nread; + + /* Read the full erase block into the buffer */ + + nread = MTD_BREAD(dev->mtd, startblock, nblocks, buffer); + if (nread != nblocks) + { + fdbg("Read %d blocks starting at block %d failed: %d\n", + nblocks, startblock, nread); + } + return nread; +} + +/**************************************************************************** + * Name: ftl_read + * + * Description: Read the specified numer of sectors + * + ****************************************************************************/ + +static ssize_t ftl_read(FAR struct inode *inode, unsigned char *buffer, + size_t start_sector, unsigned int nsectors) +{ + struct ftl_struct_s *dev; + + fvdbg("sector: %d nsectors: %d\n", start_sector, nsectors); + + DEBUGASSERT(inode && inode->i_private); + dev = (struct ftl_struct_s *)inode->i_private; +#ifdef CONFIG_FS_READAHEAD + return rwb_read(&dev->rwb, start_sector, nsectors, buffer); +#else + return ftl_reload(dev, buffer, start_sector, nsectors); +#endif +} + +/**************************************************************************** + * Name: ftl_flush + * + * Description: Write the specified number of sectors + * + ****************************************************************************/ + +#ifdef CONFIG_FS_WRITABLE +static ssize_t ftl_flush(FAR void *priv, FAR const uint8_t *buffer, + off_t startblock, size_t nblocks) +{ + struct ftl_struct_s *dev = (struct ftl_struct_s *)priv; + off_t alignedblock; + off_t mask; + off_t rwblock; + off_t eraseblock; + off_t offset; + size_t remaining; + size_t nxfrd; + int nbytes; + int ret; + + /* Get the aligned block. Here is is assumed: (1) The number of R/W blocks + * per erase block is a power of 2, and (2) the erase begins with that same + * alignment. + */ + + mask = dev->blkper - 1; + alignedblock = (startblock + mask) & ~mask; + + /* Handle partial erase blocks before the first unaligned block */ + + remaining = nblocks; + if (alignedblock > startblock) + { + /* Read the full erase block into the buffer */ + + rwblock = startblock & ~mask; + nxfrd = MTD_BREAD(dev->mtd, rwblock, dev->blkper, dev->eblock); + if (nxfrd != dev->blkper) + { + fdbg("Read erase block %d failed: %d\n", rwblock, nxfrd); + return -EIO; + } + + /* Then erase the erase block */ + + eraseblock = rwblock / dev->blkper; + ret = MTD_ERASE(dev->mtd, eraseblock, 1); + if (ret < 0) + { + fdbg("Erase block=%d failed: %d\n", eraseblock, ret); + return ret; + } + + /* Copy the user data at the end of the buffered erase block */ + + offset = (startblock & mask) * dev->geo.blocksize; + nbytes = dev->geo.erasesize - offset; + fvdbg("Copy %d bytes into erase block=%d at offset=%d\n", + nbytes, eraseblock, offset); + memcpy(dev->eblock + offset, buffer, nbytes); + + /* And write the erase back to flash */ + + nxfrd = MTD_BWRITE(dev->mtd, rwblock, dev->blkper, dev->eblock); + if (nxfrd != dev->blkper) + { + fdbg("Write erase block %d failed: %d\n", rwblock, nxfrd); + return -EIO; + } + + /* Then update for amount written */ + + remaining -= dev->blkper - (startblock & mask); + buffer += nbytes; + } + + /* How handle full erase pages in the middle */ + + while (remaining >= dev->blkper) + { + /* Erase the erase block */ + + eraseblock = alignedblock / dev->blkper; + ret = MTD_ERASE(dev->mtd, eraseblock, 1); + if (ret < 0) + { + fdbg("Erase block=%d failed: %d\n", eraseblock, ret); + return ret; + } + + /* Write a full erase back to flash */ + + fvdbg("Write %d bytes into erase block=%d at offset=0\n", + dev->geo.erasesize, alignedblock); + nxfrd = MTD_BWRITE(dev->mtd, alignedblock, dev->blkper, buffer); + if (nxfrd != dev->blkper) + { + fdbg("Write erase block %d failed: %d\n", alignedblock, nxfrd); + return -EIO; + } + + /* Then update for amount written */ + + alignedblock += dev->blkper; + remaining -= dev->blkper; + buffer += dev->geo.erasesize; + } + + /* Finally, handler any partial blocks after the last full erase block */ + + if (remaining > 0) + { + /* Read the full erase block into the buffer */ + + nxfrd = MTD_BREAD(dev->mtd, alignedblock, dev->blkper, dev->eblock); + if (nxfrd != dev->blkper) + { + fdbg("Read erase block %d failed: %d\n", alignedblock, nxfrd); + return -EIO; + } + + /* Then erase the erase block */ + + eraseblock = alignedblock / dev->blkper; + ret = MTD_ERASE(dev->mtd, eraseblock, 1); + if (ret < 0) + { + fdbg("Erase block=%d failed: %d\n", eraseblock, ret); + return ret; + } + + /* Copy the user data at the beginning the buffered erase block */ + + nbytes = remaining * dev->geo.blocksize; + fvdbg("Copy %d bytes into erase block=%d at offset=0\n", + nbytes, alignedblock); + memcpy(dev->eblock, buffer, nbytes); + + /* And write the erase back to flash */ + + nxfrd = MTD_BWRITE(dev->mtd, alignedblock, dev->blkper, dev->eblock); + if (nxfrd != dev->blkper) + { + fdbg("Write erase block %d failed: %d\n", alignedblock, nxfrd); + return -EIO; + } + } + + return nblocks; +} +#endif + +/**************************************************************************** + * Name: ftl_write + * + * Description: Write (or buffer) the specified number of sectors + * + ****************************************************************************/ + +#ifdef CONFIG_FS_WRITABLE +static ssize_t ftl_write(FAR struct inode *inode, const unsigned char *buffer, + size_t start_sector, unsigned int nsectors) +{ + struct ftl_struct_s *dev; + + fvdbg("sector: %d nsectors: %d\n", start_sector, nsectors); + + DEBUGASSERT(inode && inode->i_private); + dev = (struct ftl_struct_s *)inode->i_private; +#ifdef CONFIG_FS_WRITEBUFFER + return rwb_write(&dev->rwb, start_sector, nsectors, buffer); +#else + return ftl_flush(dev, buffer, start_sector, nsectors); +#endif +} +#endif + +/**************************************************************************** + * Name: ftl_geometry + * + * Description: Return device geometry + * + ****************************************************************************/ + +static int ftl_geometry(FAR struct inode *inode, struct geometry *geometry) +{ + struct ftl_struct_s *dev; + + fvdbg("Entry\n"); + + DEBUGASSERT(inode); + if (geometry) + { + dev = (struct ftl_struct_s *)inode->i_private; + geometry->geo_available = true; + geometry->geo_mediachanged = false; +#ifdef CONFIG_FS_WRITABLE + geometry->geo_writeenabled = true; +#else + geometry->geo_writeenabled = false; +#endif + geometry->geo_nsectors = dev->geo.neraseblocks * dev->blkper; + geometry->geo_sectorsize = dev->geo.blocksize; + + fvdbg("available: true mediachanged: false writeenabled: %s\n", + geometry->geo_writeenabled ? "true" : "false"); + fvdbg("nsectors: %d sectorsize: %d\n", + geometry->geo_nsectors, geometry->geo_sectorsize); + + return OK; + } + return -EINVAL; +} + +/**************************************************************************** + * Name: ftl_ioctl + * + * Description: Return device geometry + * + ****************************************************************************/ + +static int ftl_ioctl(FAR struct inode *inode, int cmd, unsigned long arg) +{ + struct ftl_struct_s *dev ; + int ret; + + fvdbg("Entry\n"); + DEBUGASSERT(inode && inode->i_private); + + /* Only one block driver ioctl command is supported by this driver (and + * that command is just passed on to the MTD driver in a slightly + * different form). + */ + + if (cmd == BIOC_XIPBASE) + { + /* The argument accompanying the BIOC_XIPBASE should be non-NULL. If + * DEBUG is enabled, we will catch it here instead of in the MTD + * driver. + */ + +#ifdef CONFIG_DEBUG + if (arg == 0) + { + fdbg("ERROR: BIOC_XIPBASE argument is NULL\n"); + return -EINVAL; + } +#endif + + /* Just change the BIOC_XIPBASE command to the MTDIOC_XIPBASE command. */ + + cmd = MTDIOC_XIPBASE; + } + + /* No other block driver ioctl commmands are not recognized by this + * driver. Other possible MTD driver ioctl commands are passed through + * to the MTD driver (unchanged). + */ + + dev = (struct ftl_struct_s *)inode->i_private; + ret = MTD_IOCTL(dev->mtd, cmd, arg); + if (ret < 0) + { + fdbg("ERROR: MTD ioctl(%04x) failed: %d\n", cmd, ret); + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ftl_initialize + * + * Description: + * Initialize to provide a block driver wrapper around an MTD interface + * + * Input Parameters: + * minor - The minor device number. The MTD block device will be + * registered as as /dev/mtdblockN where N is the minor number. + * mtd - The MTD device that supports the FLASH interface. + * + ****************************************************************************/ + +int ftl_initialize(int minor, FAR struct mtd_dev_s *mtd) +{ + struct ftl_struct_s *dev; + char devname[16]; + int ret = -ENOMEM; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (minor < 0 || minor > 255 || !mtd) + { + return -EINVAL; + } +#endif + + /* Allocate a FTL device structure */ + + dev = (struct ftl_struct_s *)kmalloc(sizeof(struct ftl_struct_s)); + if (dev) + { + /* Initialize the FTL device structure */ + + dev->mtd = mtd; + + /* Get the device geometry. (casting to uintptr_t first eliminates + * complaints on some architectures where the sizeof long is different + * from the size of a pointer). + */ + + ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&dev->geo)); + if (ret < 0) + { + fdbg("MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", ret); + kfree(dev); + return ret; + } + + /* Allocate one, in-memory erase block buffer */ + +#ifdef CONFIG_FS_WRITABLE + dev->eblock = (FAR uint8_t *)kmalloc(dev->geo.erasesize); + if (!dev->eblock) + { + fdbg("Failed to allocate an erase block buffer\n"); + kfree(dev); + return -ENOMEM; + } +#endif + + /* Get the number of R/W blocks per erase block */ + + dev->blkper = dev->geo.erasesize / dev->geo.blocksize; + DEBUGASSERT(dev->blkper * dev->geo.blocksize == dev->geo.erasesize); + + /* Configure read-ahead/write buffering */ + +#ifdef CONFIG_FTL_RWBUFFER + dev->rwb.blocksize = dev->geo.blocksize; + dev->rwb.nblocks = dev->geo.neraseblocks * dev->blkper; + dev->rwb.dev = (FAR void *)dev; + +#if defined(CONFIG_FS_WRITABLE) && defined(CONFIG_FS_WRITEBUFFER) + dev->rwb.wrmaxblocks = dev->blkper; + dev->rwb.wrflush = ftl_flush; +#endif + +#ifdef CONFIG_FS_READAHEAD + dev->rwb.rhmaxblocks = dev->blkper; + dev->rwb.rhreload = ftl_reload; +#endif + ret = rwb_initialize(&dev->rwb); + if (ret < 0) + { + fdbg("rwb_initialize failed: %d\n", ret); + kfree(dev); + return ret; + } +#endif + + /* Create a MTD block device name */ + + snprintf(devname, 16, "/dev/mtdblock%d", minor); + + /* Inode private data is a reference to the FTL device structure */ + + ret = register_blockdriver(devname, &g_bops, 0, dev); + if (ret < 0) + { + fdbg("register_blockdriver failed: %d\n", -ret); + kfree(dev); + } + } + return ret; +} diff --git a/nuttx/drivers/mtd/m25px.c b/nuttx/drivers/mtd/m25px.c new file mode 100644 index 0000000000..4f96c5a3b7 --- /dev/null +++ b/nuttx/drivers/mtd/m25px.c @@ -0,0 +1,798 @@ +/************************************************************************************ + * drivers/mtd/m25px.c + * Driver for SPI-based M25P1 (128Kbit), M25P64 (32Mbit), M25P64 (64Mbit), and + * M25P128 (128Mbit) FLASH (and compatible). + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* Per the data sheet, MP25P10 parts can be driven with either SPI mode 0 (CPOL=0 and + * CPHA=0) or mode 3 (CPOL=1 and CPHA=1). But I have heard that other devices can + * operated in mode 0 or 1. So you may need to specify CONFIG_MP25P_SPIMODE to + * select the best mode for your device. If CONFIG_MP25P_SPIMODE is not defined, + * mode 0 will be used. + */ + +#ifndef CONFIG_MP25P_SPIMODE +# define CONFIG_MP25P_SPIMODE SPIDEV_MODE0 +#endif + +/* Various manufacturers may have produced the parts. 0x20 is the manufacturer ID + * for the STMicro MP25x serial FLASH. If, for example, you are using the a Macronix + * International MX25 serial FLASH, the correct manufacturer ID would be 0xc2. + */ + +#ifndef CONFIG_MP25P_MANUFACTURER +# define CONFIG_MP25P_MANUFACTURER 0x20 +#endif + +/* M25P Registers *******************************************************************/ +/* Indentification register values */ + +#define M25P_MANUFACTURER CONFIG_MP25P_MANUFACTURER +#define M25P_MEMORY_TYPE 0x20 +#define M25P_M25P1_CAPACITY 0x11 /* 1 M-bit */ +#define M25P_M25P32_CAPACITY 0x16 /* 32 M-bit */ +#define M25P_M25P64_CAPACITY 0x17 /* 64 M-bit */ +#define M25P_M25P128_CAPACITY 0x18 /* 128 M-bit */ + +/* M25P1 capacity is 131,072 bytes: + * (4 sectors) * (32,768 bytes per sector) + * (512 pages) * (256 bytes per page) + */ + +#define M25P_M25P1_SECTOR_SHIFT 15 /* Sector size 1 << 15 = 65,536 */ +#define M25P_M25P1_NSECTORS 4 +#define M25P_M25P1_PAGE_SHIFT 8 /* Page size 1 << 8 = 256 */ +#define M25P_M25P1_NPAGES 512 + +/* M25P32 capacity is 4,194,304 bytes: + * (64 sectors) * (65,536 bytes per sector) + * (16384 pages) * (256 bytes per page) + */ + +#define M25P_M25P32_SECTOR_SHIFT 16 /* Sector size 1 << 16 = 65,536 */ +#define M25P_M25P32_NSECTORS 64 +#define M25P_M25P32_PAGE_SHIFT 8 /* Page size 1 << 8 = 256 */ +#define M25P_M25P32_NPAGES 16384 + +/* M25P64 capacity is 8,338,608 bytes: + * (128 sectors) * (65,536 bytes per sector) + * (32768 pages) * (256 bytes per page) + */ + +#define M25P_M25P64_SECTOR_SHIFT 16 /* Sector size 1 << 16 = 65,536 */ +#define M25P_M25P64_NSECTORS 128 +#define M25P_M25P64_PAGE_SHIFT 8 /* Page size 1 << 8 = 256 */ +#define M25P_M25P64_NPAGES 32768 + +/* M25P128 capacity is 16,777,216 bytes: + * (64 sectors) * (262,144 bytes per sector) + * (65536 pages) * (256 bytes per page) + */ + +#define M25P_M25P128_SECTOR_SHIFT 18 /* Sector size 1 << 18 = 262,144 */ +#define M25P_M25P128_NSECTORS 64 +#define M25P_M25P128_PAGE_SHIFT 8 /* Page size 1 << 8 = 256 */ +#define M25P_M25P128_NPAGES 65536 + +/* Instructions */ +/* Command Value N Description Addr Dummy Data */ +#define M25P_WREN 0x06 /* 1 Write Enable 0 0 0 */ +#define M25P_WRDI 0x04 /* 1 Write Disable 0 0 0 */ +#define M25P_RDID 0x9f /* 1 Read Identification 0 0 1-3 */ +#define M25P_RDSR 0x05 /* 1 Read Status Register 0 0 >=1 */ +#define M25P_WRSR 0x01 /* 1 Write Status Register 0 0 1 */ +#define M25P_READ 0x03 /* 1 Read Data Bytes 3 0 >=1 */ +#define M25P_FAST_READ 0x0b /* 1 Higher speed read 3 1 >=1 */ +#define M25P_PP 0x02 /* 1 Page Program 3 0 1-256 */ +#define M25P_SE 0xd8 /* 1 Sector Erase 3 0 0 */ +#define M25P_BE 0xc7 /* 1 Bulk Erase 0 0 0 */ +#define M25P_DP 0xb9 /* 2 Deep power down 0 0 0 */ +#define M25P_RES 0xab /* 2 Read Electronic Signature 0 3 >=1 */ + +/* NOTE 1: All parts, NOTE 2: M25P632/M25P64 */ + +/* Status register bit definitions */ + +#define M25P_SR_WIP (1 << 0) /* Bit 0: Write in progress bit */ +#define M25P_SR_WEL (1 << 1) /* Bit 1: Write enable latch bit */ +#define M25P_SR_BP_SHIFT (2) /* Bits 2-4: Block protect bits */ +#define M25P_SR_BP_MASK (7 << M25P_SR_BP_SHIFT) +# define M25P_SR_BP_NONE (0 << M25P_SR_BP_SHIFT) /* Unprotected */ +# define M25P_SR_BP_UPPER64th (1 << M25P_SR_BP_SHIFT) /* Upper 64th */ +# define M25P_SR_BP_UPPER32nd (2 << M25P_SR_BP_SHIFT) /* Upper 32nd */ +# define M25P_SR_BP_UPPER16th (3 << M25P_SR_BP_SHIFT) /* Upper 16th */ +# define M25P_SR_BP_UPPER8th (4 << M25P_SR_BP_SHIFT) /* Upper 8th */ +# define M25P_SR_BP_UPPERQTR (5 << M25P_SR_BP_SHIFT) /* Upper quarter */ +# define M25P_SR_BP_UPPERHALF (6 << M25P_SR_BP_SHIFT) /* Upper half */ +# define M25P_SR_BP_ALL (7 << M25P_SR_BP_SHIFT) /* All sectors */ + /* Bits 5-6: Unused, read zero */ +#define M25P_SR_SRWD (1 << 7) /* Bit 7: Status register write protect */ + +#define M25P_DUMMY 0xa5 + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/* This type represents the state of the MTD device. The struct mtd_dev_s + * must appear at the beginning of the definition so that you can freely + * cast between pointers to struct mtd_dev_s and struct m25p_dev_s. + */ + +struct m25p_dev_s +{ + struct mtd_dev_s mtd; /* MTD interface */ + FAR struct spi_dev_s *dev; /* Saved SPI interface instance */ + uint8_t sectorshift; /* 16 or 18 */ + uint8_t pageshift; /* 8 */ + uint16_t nsectors; /* 128 or 64 */ + uint32_t npages; /* 32,768 or 65,536 */ +}; + +/************************************************************************************ + * Private Function Prototypes + ************************************************************************************/ + +/* Helpers */ + +static void m25p_lock(FAR struct spi_dev_s *dev); +static inline void m25p_unlock(FAR struct spi_dev_s *dev); +static inline int m25p_readid(struct m25p_dev_s *priv); +static void m25p_waitwritecomplete(struct m25p_dev_s *priv); +static void m25p_writeenable(struct m25p_dev_s *priv); +static inline void m25p_sectorerase(struct m25p_dev_s *priv, off_t offset); +static inline int m25p_bulkerase(struct m25p_dev_s *priv); +static inline void m25p_pagewrite(struct m25p_dev_s *priv, FAR const uint8_t *buffer, + off_t offset); + +/* MTD driver methods */ + +static int m25p_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks); +static ssize_t m25p_bread(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR uint8_t *buf); +static ssize_t m25p_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR const uint8_t *buf); +static ssize_t m25p_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes, + FAR uint8_t *buffer); +static int m25p_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg); + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: m25p_lock + ************************************************************************************/ + +static void m25p_lock(FAR struct spi_dev_s *dev) +{ + /* On SPI busses where there are multiple devices, it will be necessary to + * lock SPI to have exclusive access to the busses for a sequence of + * transfers. The bus should be locked before the chip is selected. + * + * This is a blocking call and will not return until we have exclusiv access to + * the SPI buss. We will retain that exclusive access until the bus is unlocked. + */ + + (void)SPI_LOCK(dev, true); + + /* After locking the SPI bus, the we also need call the setfrequency, setbits, and + * setmode methods to make sure that the SPI is properly configured for the device. + * If the SPI buss is being shared, then it may have been left in an incompatible + * state. + */ + + SPI_SETMODE(dev, CONFIG_MP25P_SPIMODE); + SPI_SETBITS(dev, 8); + (void)SPI_SETFREQUENCY(dev, 20000000); +} + +/************************************************************************************ + * Name: m25p_unlock + ************************************************************************************/ + +static inline void m25p_unlock(FAR struct spi_dev_s *dev) +{ + (void)SPI_LOCK(dev, false); +} + +/************************************************************************************ + * Name: m25p_readid + ************************************************************************************/ + +static inline int m25p_readid(struct m25p_dev_s *priv) +{ + uint16_t manufacturer; + uint16_t memory; + uint16_t capacity; + + fvdbg("priv: %p\n", priv); + + /* Lock the SPI bus, configure the bus, and select this FLASH part. */ + + m25p_lock(priv->dev); + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send the "Read ID (RDID)" command and read the first three ID bytes */ + + (void)SPI_SEND(priv->dev, M25P_RDID); + manufacturer = SPI_SEND(priv->dev, M25P_DUMMY); + memory = SPI_SEND(priv->dev, M25P_DUMMY); + capacity = SPI_SEND(priv->dev, M25P_DUMMY); + + /* Deselect the FLASH and unlock the bus */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + m25p_unlock(priv->dev); + + fvdbg("manufacturer: %02x memory: %02x capacity: %02x\n", + manufacturer, memory, capacity); + + /* Check for a valid manufacturer and memory type */ + + if (manufacturer == M25P_MANUFACTURER && memory == M25P_MEMORY_TYPE) + { + /* Okay.. is it a FLASH capacity that we understand? */ + + if (capacity == M25P_M25P1_CAPACITY) + { + /* Save the FLASH geometry */ + + priv->sectorshift = M25P_M25P1_SECTOR_SHIFT; + priv->nsectors = M25P_M25P1_NSECTORS; + priv->pageshift = M25P_M25P1_PAGE_SHIFT; + priv->npages = M25P_M25P1_NPAGES; + return OK; + } + else if (capacity == M25P_M25P32_CAPACITY) + { + /* Save the FLASH geometry */ + + priv->sectorshift = M25P_M25P32_SECTOR_SHIFT; + priv->nsectors = M25P_M25P32_NSECTORS; + priv->pageshift = M25P_M25P32_PAGE_SHIFT; + priv->npages = M25P_M25P32_NPAGES; + return OK; + } + else if (capacity == M25P_M25P64_CAPACITY) + { + /* Save the FLASH geometry */ + + priv->sectorshift = M25P_M25P64_SECTOR_SHIFT; + priv->nsectors = M25P_M25P64_NSECTORS; + priv->pageshift = M25P_M25P64_PAGE_SHIFT; + priv->npages = M25P_M25P64_NPAGES; + return OK; + } + else if (capacity == M25P_M25P128_CAPACITY) + { + /* Save the FLASH geometry */ + + priv->sectorshift = M25P_M25P128_SECTOR_SHIFT; + priv->nsectors = M25P_M25P128_NSECTORS; + priv->pageshift = M25P_M25P128_PAGE_SHIFT; + priv->npages = M25P_M25P128_NPAGES; + return OK; + } + } + + return -ENODEV; +} + +/************************************************************************************ + * Name: m25p_waitwritecomplete + ************************************************************************************/ + +static void m25p_waitwritecomplete(struct m25p_dev_s *priv) +{ + uint8_t status; + + /* Are we the only device on the bus? */ + +#ifdef CONFIG_SPI_OWNBUS + + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Read Status Register (RDSR)" command */ + + (void)SPI_SEND(priv->dev, M25P_RDSR); + + /* Loop as long as the memory is busy with a write cycle */ + + do + { + /* Send a dummy byte to generate the clock needed to shift out the status */ + + status = SPI_SEND(priv->dev, M25P_DUMMY); + } + while ((status & M25P_SR_WIP) != 0); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + +#else + + /* Loop as long as the memory is busy with a write cycle */ + + do + { + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Read Status Register (RDSR)" command */ + + (void)SPI_SEND(priv->dev, M25P_RDSR); + + /* Send a dummy byte to generate the clock needed to shift out the status */ + + status = SPI_SEND(priv->dev, M25P_DUMMY); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + + /* Given that writing could take up to few tens of milliseconds, and erasing + * could take more. The following short delay in the "busy" case will allow + * other peripherals to access the SPI bus. + */ + + if ((status & M25P_SR_WIP) != 0) + { + m25p_unlock(priv->dev); + usleep(1000); + m25p_lock(priv->dev); + } + } + while ((status & M25P_SR_WIP) != 0); +#endif + + fvdbg("Complete\n"); +} + +/************************************************************************************ + * Name: m25p_writeenable + ************************************************************************************/ + +static void m25p_writeenable(struct m25p_dev_s *priv) +{ + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Write Enable (WREN)" command */ + + (void)SPI_SEND(priv->dev, M25P_WREN); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + fvdbg("Enabled\n"); +} + +/************************************************************************************ + * Name: m25p_sectorerase + ************************************************************************************/ + +static inline void m25p_sectorerase(struct m25p_dev_s *priv, off_t sector) +{ + off_t offset = sector << priv->sectorshift; + + fvdbg("sector: %08lx\n", (long)sector); + + /* Wait for any preceding write to complete. We could simplify things by + * perform this wait at the end of each write operation (rather than at + * the beginning of ALL operations), but have the wait first will slightly + * improve performance. + */ + + m25p_waitwritecomplete(priv); + + /* Send write enable instruction */ + + m25p_writeenable(priv); + + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send the "Sector Erase (SE)" instruction */ + + (void)SPI_SEND(priv->dev, M25P_SE); + + /* Send the sector offset high byte first. For all of the supported + * parts, the sector number is completely contained in the first byte + * and the values used in the following two bytes don't really matter. + */ + + (void)SPI_SEND(priv->dev, (offset >> 16) & 0xff); + (void)SPI_SEND(priv->dev, (offset >> 8) & 0xff); + (void)SPI_SEND(priv->dev, offset & 0xff); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + fvdbg("Erased\n"); +} + +/************************************************************************************ + * Name: m25p_bulkerase + ************************************************************************************/ + +static inline int m25p_bulkerase(struct m25p_dev_s *priv) +{ + fvdbg("priv: %p\n", priv); + + /* Wait for any preceding write to complete. We could simplify things by + * perform this wait at the end of each write operation (rather than at + * the beginning of ALL operations), but have the wait first will slightly + * improve performance. + */ + + m25p_waitwritecomplete(priv); + + /* Send write enable instruction */ + + m25p_writeenable(priv); + + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send the "Bulk Erase (BE)" instruction */ + + (void)SPI_SEND(priv->dev, M25P_BE); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + fvdbg("Return: OK\n"); + return OK; +} + +/************************************************************************************ + * Name: m25p_pagewrite + ************************************************************************************/ + +static inline void m25p_pagewrite(struct m25p_dev_s *priv, FAR const uint8_t *buffer, + off_t page) +{ + off_t offset = page << priv->pageshift; + + fvdbg("page: %08lx offset: %08lx\n", (long)page, (long)offset); + + /* Wait for any preceding write to complete. We could simplify things by + * perform this wait at the end of each write operation (rather than at + * the beginning of ALL operations), but have the wait first will slightly + * improve performance. + */ + + m25p_waitwritecomplete(priv); + + /* Enable the write access to the FLASH */ + + m25p_writeenable(priv); + + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Page Program (PP)" command */ + + (void)SPI_SEND(priv->dev, M25P_PP); + + /* Send the page offset high byte first. */ + + (void)SPI_SEND(priv->dev, (offset >> 16) & 0xff); + (void)SPI_SEND(priv->dev, (offset >> 8) & 0xff); + (void)SPI_SEND(priv->dev, offset & 0xff); + + /* Then write the specified number of bytes */ + + SPI_SNDBLOCK(priv->dev, buffer, 1 << priv->pageshift); + + /* Deselect the FLASH: Chip Select high */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + fvdbg("Written\n"); +} + +/************************************************************************************ + * Name: m25p_erase + ************************************************************************************/ + +static int m25p_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks) +{ + FAR struct m25p_dev_s *priv = (FAR struct m25p_dev_s *)dev; + size_t blocksleft = nblocks; + + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + /* Lock access to the SPI bus until we complete the erase */ + + m25p_lock(priv->dev); + while (blocksleft-- > 0) + { + /* Erase each sector */ + + m25p_sectorerase(priv, startblock); + startblock++; + } + m25p_unlock(priv->dev); + return (int)nblocks; +} + +/************************************************************************************ + * Name: m25p_bread + ************************************************************************************/ + +static ssize_t m25p_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR uint8_t *buffer) +{ + FAR struct m25p_dev_s *priv = (FAR struct m25p_dev_s *)dev; + ssize_t nbytes; + + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + /* On this device, we can handle the block read just like the byte-oriented read */ + + nbytes = m25p_read(dev, startblock << priv->pageshift, nblocks << priv->pageshift, buffer); + if (nbytes > 0) + { + return nbytes >> priv->pageshift; + } + return (int)nbytes; +} + +/************************************************************************************ + * Name: m25p_bwrite + ************************************************************************************/ + +static ssize_t m25p_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR const uint8_t *buffer) +{ + FAR struct m25p_dev_s *priv = (FAR struct m25p_dev_s *)dev; + size_t blocksleft = nblocks; + + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + /* Lock the SPI bus and write each page to FLASH */ + + m25p_lock(priv->dev); + while (blocksleft-- > 0) + { + m25p_pagewrite(priv, buffer, startblock); + startblock++; + } + m25p_unlock(priv->dev); + + return nblocks; +} + +/************************************************************************************ + * Name: m25p_read + ************************************************************************************/ + +static ssize_t m25p_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes, + FAR uint8_t *buffer) +{ + FAR struct m25p_dev_s *priv = (FAR struct m25p_dev_s *)dev; + + fvdbg("offset: %08lx nbytes: %d\n", (long)offset, (int)nbytes); + + /* Wait for any preceding write to complete. We could simplify things by + * perform this wait at the end of each write operation (rather than at + * the beginning of ALL operations), but have the wait first will slightly + * improve performance. + */ + + m25p_waitwritecomplete(priv); + + /* Lock the SPI bus and select this FLASH part */ + + m25p_lock(priv->dev); + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Read from Memory " instruction */ + + (void)SPI_SEND(priv->dev, M25P_READ); + + /* Send the page offset high byte first. */ + + (void)SPI_SEND(priv->dev, (offset >> 16) & 0xff); + (void)SPI_SEND(priv->dev, (offset >> 8) & 0xff); + (void)SPI_SEND(priv->dev, offset & 0xff); + + /* Then read all of the requested bytes */ + + SPI_RECVBLOCK(priv->dev, buffer, nbytes); + + /* Deselect the FLASH and unlock the SPI bus */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + m25p_unlock(priv->dev); + fvdbg("return nbytes: %d\n", (int)nbytes); + return nbytes; +} + +/************************************************************************************ + * Name: m25p_ioctl + ************************************************************************************/ + +static int m25p_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg) +{ + FAR struct m25p_dev_s *priv = (FAR struct m25p_dev_s *)dev; + int ret = -EINVAL; /* Assume good command with bad parameters */ + + fvdbg("cmd: %d \n", cmd); + + switch (cmd) + { + case MTDIOC_GEOMETRY: + { + FAR struct mtd_geometry_s *geo = (FAR struct mtd_geometry_s *)((uintptr_t)arg); + if (geo) + { + /* Populate the geometry structure with information need to know + * the capacity and how to access the device. + * + * NOTE: that the device is treated as though it where just an array + * of fixed size blocks. That is most likely not true, but the client + * will expect the device logic to do whatever is necessary to make it + * appear so. + */ + + geo->blocksize = (1 << priv->pageshift); + geo->erasesize = (1 << priv->sectorshift); + geo->neraseblocks = priv->nsectors; + ret = OK; + + fvdbg("blocksize: %d erasesize: %d neraseblocks: %d\n", + geo->blocksize, geo->erasesize, geo->neraseblocks); + } + } + break; + + case MTDIOC_BULKERASE: + { + /* Erase the entire device */ + + m25p_lock(priv->dev); + ret = m25p_bulkerase(priv); + m25p_unlock(priv->dev); + } + break; + + case MTDIOC_XIPBASE: + default: + ret = -ENOTTY; /* Bad command */ + break; + } + + fvdbg("return %d\n", ret); + return ret; +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: m25p_initialize + * + * Description: + * Create an initialize MTD device instance. MTD devices are not registered + * in the file system, but are created as instances that can be bound to + * other functions (such as a block or character driver front end). + * + ************************************************************************************/ + +FAR struct mtd_dev_s *m25p_initialize(FAR struct spi_dev_s *dev) +{ + FAR struct m25p_dev_s *priv; + int ret; + + fvdbg("dev: %p\n", dev); + + /* Allocate a state structure (we allocate the structure instead of using + * a fixed, static allocation so that we can handle multiple FLASH devices. + * The current implementation would handle only one FLASH part per SPI + * device (only because of the SPIDEV_FLASH definition) and so would have + * to be extended to handle multiple FLASH parts on the same SPI bus. + */ + + priv = (FAR struct m25p_dev_s *)kmalloc(sizeof(struct m25p_dev_s)); + if (priv) + { + /* Initialize the allocated structure */ + + priv->mtd.erase = m25p_erase; + priv->mtd.bread = m25p_bread; + priv->mtd.bwrite = m25p_bwrite; + priv->mtd.read = m25p_read; + priv->mtd.ioctl = m25p_ioctl; + priv->dev = dev; + + /* Deselect the FLASH */ + + SPI_SELECT(dev, SPIDEV_FLASH, false); + + /* Identify the FLASH chip and get its capacity */ + + ret = m25p_readid(priv); + if (ret != OK) + { + /* Unrecognized! Discard all of that work we just did and return NULL */ + + fdbg("Unrecognized\n"); + kfree(priv); + priv = NULL; + } + } + + /* Return the implementation-specific state structure as the MTD device */ + + fvdbg("Return %p\n", priv); + return (FAR struct mtd_dev_s *)priv; +} diff --git a/nuttx/drivers/mtd/rammtd.c b/nuttx/drivers/mtd/rammtd.c new file mode 100644 index 0000000000..82a7191ea4 --- /dev/null +++ b/nuttx/drivers/mtd/rammtd.c @@ -0,0 +1,417 @@ +/**************************************************************************** + * drivers/mtd/rammtd.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +#ifndef CONFIG_RAMMTD_BLOCKSIZE +# define CONFIG_RAMMTD_BLOCKSIZE 512 +#endif + +#ifndef CONFIG_RAMMTD_ERASESIZE +# define CONFIG_RAMMTD_ERASESIZE 4096 +#endif + +#ifndef CONFIG_RAMMTD_ERASESTATE +# define CONFIG_RAMMTD_ERASESTATE 0xff +#endif + +#if CONFIG_RAMMTD_ERASESTATE != 0xff && CONFIG_RAMMTD_ERASESTATE != 0x00 +# error "Unsupported value for CONFIG_RAMMTD_ERASESTATE" +#endif + +#if CONFIG_RAMMTD_BLOCKSIZE > CONFIG_RAMMTD_ERASESIZE +# error "Must have CONFIG_RAMMTD_BLOCKSIZE <= CONFIG_RAMMTD_ERASESIZE" +#endif + +#undef CONFIG_RAMMTD_BLKPER +#define CONFIG_RAMMTD_BLKPER (CONFIG_RAMMTD_ERASESIZE/CONFIG_RAMMTD_BLOCKSIZE) + +#if CONFIG_RAMMTD_BLKPER*CONFIG_RAMMTD_BLOCKSIZE != CONFIG_RAMMTD_ERASESIZE +# error "CONFIG_RAMMTD_ERASESIZE must be an even multiple of CONFIG_RAMMTD_BLOCKSIZE" +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This type represents the state of the MTD device. The struct mtd_dev_s + * must appear at the beginning of the definition so that you can freely + * cast between pointers to struct mtd_dev_s and struct ram_dev_s. + */ + +struct ram_dev_s +{ + struct mtd_dev_s mtd; /* MTD device */ + FAR uint8_t *start; /* Start of RAM */ + size_t nblocks; /* Number of erase blocks */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* The RAM MTD driver may be useful just as it is, but another good use of + * the RAM MTD driver is as a FLASH simulation -- to support testing of FLASH + * based logic without having FLASH. CONFIG_RAMMTD_FLASHSIM will add some + * extra logic to improve the level of FLASH simulation. + */ + +#define ram_read(dest, src, len) memcpy(dest, src, len) +#ifdef CONFIG_RAMMTD_FLASHSIM +static void *ram_write(FAR void *dest, FAR const void *src, size_t len); +#else +# define ram_write(dest, src, len) memcpy(dest, src, len) +#endif + +/* MTD driver methods */ + +static int ram_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks); +static ssize_t ram_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR uint8_t *buf); +static ssize_t ram_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR const uint8_t *buf); +static int ram_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ram_write + ****************************************************************************/ + +#ifdef CONFIG_RAMMTD_FLASHSIM +static void *ram_write(FAR void *dest, FAR const void *src, size_t len) +{ + FAR uint8_t *pout = (FAR uint8_t *)dest; + FAR const uint8_t *pin = (FAR const uint8_t *)src; + + while (len-- > 0) + { + /* Get the source and destination values */ + + uint8_t oldvalue = *pout; + uint8_t srcvalue = *pin++; + uint8_t newvalue; + + /* Get the new destination value, accounting for bits that cannot be + * changes because they are not in the erased state. + */ + +#if CONFIG_RAMMTD_ERASESTATE == 0xff + newvalue = oldvalue & srcvalue; /* We can only clear bits */ +#else /* CONFIG_RAMMTD_ERASESTATE == 0x00 */ + newvalue = oldvalue | srcvalue; /* We can only set bits */ +#endif + + /* Report any attempt to change the value of bits that are not in the + * erased state. + */ + +#ifdef CONFIG_DEBUG + if (newvalue != srcvalue) + { + dbg("ERROR: Bad write: source=%02x dest=%02x result=%02x\n", + srcvalue, oldvalue, newvalue); + } +#endif + + /* Write the modified value to simulated FLASH */ + + *pout++ = newvalue; + } + + return dest; +} +#endif + +/**************************************************************************** + * Name: ram_erase + ****************************************************************************/ + +static int ram_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks) +{ + FAR struct ram_dev_s *priv = (FAR struct ram_dev_s *)dev; + off_t offset; + size_t nbytes; + + DEBUGASSERT(dev); + + /* Don't let the erase exceed the size of the ram buffer */ + + if (startblock >= priv->nblocks) + { + return 0; + } + + if (startblock + nblocks > priv->nblocks) + { + nblocks = priv->nblocks - startblock; + } + + /* Convert the erase block to a logical block and the number of blocks + * in logical block numbers + */ + + startblock *= CONFIG_RAMMTD_BLKPER; + nblocks *= CONFIG_RAMMTD_BLKPER; + + /* Get the offset corresponding to the first block and the size + * corresponding to the number of blocks. + */ + + offset = startblock * CONFIG_RAMMTD_BLOCKSIZE; + nbytes = nblocks * CONFIG_RAMMTD_BLOCKSIZE; + + /* Then erase the data in RAM */ + + memset(&priv->start[offset], CONFIG_RAMMTD_ERASESTATE, nbytes); + return OK; +} + +/**************************************************************************** + * Name: ram_bread + ****************************************************************************/ + +static ssize_t ram_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR uint8_t *buf) +{ + FAR struct ram_dev_s *priv = (FAR struct ram_dev_s *)dev; + off_t offset; + off_t maxblock; + size_t nbytes; + + DEBUGASSERT(dev && buf); + + /* Don't let the read exceed the size of the ram buffer */ + + maxblock = priv->nblocks * CONFIG_RAMMTD_BLKPER; + if (startblock >= maxblock) + { + return 0; + } + + if (startblock + nblocks > maxblock) + { + nblocks = maxblock - startblock; + } + + /* Get the offset corresponding to the first block and the size + * corresponding to the number of blocks. + */ + + offset = startblock * CONFIG_RAMMTD_BLOCKSIZE; + nbytes = nblocks * CONFIG_RAMMTD_BLOCKSIZE; + + /* Then read the data frp, RAM */ + + ram_read(buf, &priv->start[offset], nbytes); + return nblocks; +} + +/**************************************************************************** + * Name: ram_bwrite + ****************************************************************************/ + +static ssize_t ram_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR const uint8_t *buf) +{ + FAR struct ram_dev_s *priv = (FAR struct ram_dev_s *)dev; + off_t offset; + off_t maxblock; + size_t nbytes; + + DEBUGASSERT(dev && buf); + + /* Don't let the write exceed the size of the ram buffer */ + + maxblock = priv->nblocks * CONFIG_RAMMTD_BLKPER; + if (startblock >= maxblock) + { + return 0; + } + + if (startblock + nblocks > maxblock) + { + nblocks = maxblock - startblock; + } + + /* Get the offset corresponding to the first block and the size + * corresponding to the number of blocks. + */ + + offset = startblock * CONFIG_RAMMTD_BLOCKSIZE; + nbytes = nblocks * CONFIG_RAMMTD_BLOCKSIZE; + + /* Then write the data to RAM */ + + ram_write(&priv->start[offset], buf, nbytes); + return nblocks; +} + +/**************************************************************************** + * Name: ram_ioctl + ****************************************************************************/ + +static int ram_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg) +{ + FAR struct ram_dev_s *priv = (FAR struct ram_dev_s *)dev; + int ret = -EINVAL; /* Assume good command with bad parameters */ + + switch (cmd) + { + case MTDIOC_GEOMETRY: + { + FAR struct mtd_geometry_s *geo = (FAR struct mtd_geometry_s *)((uintptr_t)arg); + if (geo) + { + /* Populate the geometry structure with information need to know + * the capacity and how to access the device. + */ + + geo->blocksize = CONFIG_RAMMTD_BLOCKSIZE; + geo->erasesize = CONFIG_RAMMTD_ERASESIZE; + geo->neraseblocks = priv->nblocks; + ret = OK; + } + } + break; + + case MTDIOC_XIPBASE: + { + FAR void **ppv = (FAR void**)((uintptr_t)arg); + if (ppv) + { + /* Return (void*) base address of device memory */ + + *ppv = (FAR void*)priv->start; + ret = OK; + } + } + break; + + case MTDIOC_BULKERASE: + { + size_t size = priv->nblocks * CONFIG_RAMMTD_ERASESIZE; + + /* Erase the entire device */ + + memset(priv->start, CONFIG_RAMMTD_ERASESTATE, size); + ret = OK; + } + break; + + default: + ret = -ENOTTY; /* Bad command */ + break; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rammtd_initialize + * + * Description: + * Create and initialize a RAM MTD device instance. + * + * Input Parameters: + * start - Address of the beginning of the allocated RAM regions. + * size - The size in bytes of the allocated RAM region. + * + ****************************************************************************/ + +FAR struct mtd_dev_s *rammtd_initialize(FAR uint8_t *start, size_t size) +{ + FAR struct ram_dev_s *priv; + size_t nblocks; + + /* Create an instance of the RAM MTD device state structure */ + + priv = (FAR struct ram_dev_s *)kmalloc(sizeof(struct ram_dev_s)); + if (!priv) + { + fdbg("Failed to allocate the RAM MTD state structure\n"); + return NULL; + } + + /* Force the size to be an even number of the erase block size */ + + nblocks = size / CONFIG_RAMMTD_ERASESIZE; + if (nblocks <= 0) + { + fdbg("Need to provide at least one full erase block\n"); + return NULL; + } + + /* Perform initialization as necessary */ + + priv->mtd.erase = ram_erase; + priv->mtd.bread = ram_bread; + priv->mtd.bwrite = ram_bwrite; + priv->mtd.ioctl = ram_ioctl; + priv->mtd.erase = ram_erase; + + priv->start = start; + priv->nblocks = nblocks; + return &priv->mtd; +} diff --git a/nuttx/drivers/mtd/ramtron.c b/nuttx/drivers/mtd/ramtron.c new file mode 100644 index 0000000000..074545e2d9 --- /dev/null +++ b/nuttx/drivers/mtd/ramtron.c @@ -0,0 +1,674 @@ +/************************************************************************************ + * drivers/mtd/ramtron.c + * Driver for SPI-based RAMTRON NVRAM Devices FM25V10 and others (not tested) + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Copyright (C) 2009-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Uros Platise + * Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/* OPTIONS: + * - additional non-jedec standard device: FM25H20 + * must be enabled with the CONFIG_RAMTRON_FRAM_NON_JEDEC=y + * + * NOTE: + * - frequency is fixed to desired max by RAMTRON_INIT_CLK_MAX + * if new devices with different speed arrive, then SETFREQUENCY() + * needs to handle freq changes and INIT_CLK_MAX must be reduced + * to fit all devices. Note that STM32_SPI driver is prone to + * too high freq. parameters and limit it within physical constraints. + * + * TODO: + * - add support for sleep + * - add support for faster read FSTRD command + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* RAMTRON devices are flat! + * For purpose of the VFAT file system we emulate the following configuration: + */ + +#define RAMTRON_EMULATE_SECTOR_SHIFT 9 +#define RAMTRON_EMULATE_PAGE_SHIFT 9 + +/* RAMTRON Indentification register values */ + +#define RAMTRON_MANUFACTURER 0x7F +#define RAMTRON_MEMORY_TYPE 0xC2 + +/* Instructions: + * Command Value N Description Addr Dummy Data */ +#define RAMTRON_WREN 0x06 /* 1 Write Enable 0 0 0 */ +#define RAMTRON_WRDI 0x04 /* 1 Write Disable 0 0 0 */ +#define RAMTRON_RDSR 0x05 /* 1 Read Status Register 0 0 >=1 */ +#define RAMTRON_WRSR 0x01 /* 1 Write Status Register 0 0 1 */ +#define RAMTRON_READ 0x03 /* 1 Read Data Bytes A 0 >=1 */ +#define RAMTRON_FSTRD 0x0b /* 1 Higher speed read A 1 >=1 */ +#define RAMTRON_WRITE 0x02 /* 1 Write A 0 1-256 */ +#define RAMTRON_SLEEP 0xb9 // TODO: +#define RAMTRON_RDID 0x9f /* 1 Read Identification 0 0 1-3 */ +#define RAMTRON_SN 0xc3 // TODO: + + +/* Status register bit definitions */ + +#define RAMTRON_SR_WIP (1 << 0) /* Bit 0: Write in progress bit */ +#define RAMTRON_SR_WEL (1 << 1) /* Bit 1: Write enable latch bit */ +#define RAMTRON_SR_BP_SHIFT (2) /* Bits 2-4: Block protect bits */ +#define RAMTRON_SR_BP_MASK (7 << RAMTRON_SR_BP_SHIFT) +# define RAMTRON_SR_BP_NONE (0 << RAMTRON_SR_BP_SHIFT) /* Unprotected */ +# define RAMTRON_SR_BP_UPPER64th (1 << RAMTRON_SR_BP_SHIFT) /* Upper 64th */ +# define RAMTRON_SR_BP_UPPER32nd (2 << RAMTRON_SR_BP_SHIFT) /* Upper 32nd */ +# define RAMTRON_SR_BP_UPPER16th (3 << RAMTRON_SR_BP_SHIFT) /* Upper 16th */ +# define RAMTRON_SR_BP_UPPER8th (4 << RAMTRON_SR_BP_SHIFT) /* Upper 8th */ +# define RAMTRON_SR_BP_UPPERQTR (5 << RAMTRON_SR_BP_SHIFT) /* Upper quarter */ +# define RAMTRON_SR_BP_UPPERHALF (6 << RAMTRON_SR_BP_SHIFT) /* Upper half */ +# define RAMTRON_SR_BP_ALL (7 << RAMTRON_SR_BP_SHIFT) /* All sectors */ +#define RAMTRON_SR_SRWD (1 << 7) /* Bit 7: Status register write protect */ + +#define RAMTRON_DUMMY 0xa5 + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +struct ramtron_parts_s +{ + const char *name; + uint8_t id1; + uint8_t id2; + uint32_t size; + uint8_t addr_len; + uint32_t speed; +}; + +/* This type represents the state of the MTD device. The struct mtd_dev_s + * must appear at the beginning of the definition so that you can freely + * cast between pointers to struct mtd_dev_s and struct ramtron_dev_s. + */ + +struct ramtron_dev_s +{ + struct mtd_dev_s mtd; /* MTD interface */ + FAR struct spi_dev_s *dev; /* Saved SPI interface instance */ + uint8_t sectorshift; + uint8_t pageshift; + uint16_t nsectors; + uint32_t npages; + const struct ramtron_parts_s *part; /* part instance */ +}; + +/************************************************************************************ + * Supported Part Lists + ************************************************************************************/ + +// Defines the initial speed compatible with all devices. In case of RAMTRON +// the defined devices within the part list have all the same speed. +#define RAMTRON_INIT_CLK_MAX 40000000UL + +static struct ramtron_parts_s ramtron_parts[] = +{ + { + "FM25V02", /* name */ + 0x22, /* id1 */ + 0x00, /* id2 */ + 32L*1024L, /* size */ + 2, /* addr_len */ + 40000000 /* speed */ + }, + { + "FM25VN02", /* name */ + 0x22, /* id1 */ + 0x01, /* id2 */ + 32L*1024L, /* size */ + 2, /* addr_len */ + 40000000 /* speed */ + }, + { + "FM25V05", /* name */ + 0x23, /* id1 */ + 0x00, /* id2 */ + 64L*1024L, /* size */ + 2, /* addr_len */ + 40000000 /* speed */ + }, + { + "FM25VN05", /* name */ + 0x23, /* id1 */ + 0x01, /* id2 */ + 64L*1024L, /* size */ + 2, /* addr_len */ + 40000000 /* speed */ + }, + { + "FM25V10", /* name */ + 0x24, /* id1 */ + 0x00, /* id2 */ + 128L*1024L, /* size */ + 3, /* addr_len */ + 40000000 /* speed */ + }, + { + "FM25VN10", /* name */ + 0x24, /* id1 */ + 0x01, /* id2 */ + 128L*1024L, /* size */ + 3, /* addr_len */ + 40000000 /* speed */ + }, +#ifdef CONFIG_RAMTRON_FRAM_NON_JEDEC + { + "FM25H20", /* name */ + 0xff, /* id1 */ + 0xff, /* id2 */ + 256L*1024L, /* size */ + 3, /* addr_len */ + 40000000 /* speed */ + }, + { + NULL, /* name */ + 0, /* id1 */ + 0, /* id2 */ + 0, /* size */ + 0, /* addr_len */ + 0 /* speed */ + } +#endif +}; + + +/************************************************************************************ + * Private Function Prototypes + ************************************************************************************/ + +/* Helpers */ + +static void ramtron_lock(FAR struct spi_dev_s *dev); +static inline void ramtron_unlock(FAR struct spi_dev_s *dev); +static inline int ramtron_readid(struct ramtron_dev_s *priv); +static void ramtron_waitwritecomplete(struct ramtron_dev_s *priv); +static void ramtron_writeenable(struct ramtron_dev_s *priv); +static inline void ramtron_pagewrite(struct ramtron_dev_s *priv, FAR const uint8_t *buffer, + off_t offset); + +/* MTD driver methods */ + +static int ramtron_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks); +static ssize_t ramtron_bread(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR uint8_t *buf); +static ssize_t ramtron_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR const uint8_t *buf); +static ssize_t ramtron_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes, + FAR uint8_t *buffer); +static int ramtron_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg); + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: ramtron_lock + ************************************************************************************/ + +static void ramtron_lock(FAR struct spi_dev_s *dev) +{ + /* On SPI busses where there are multiple devices, it will be necessary to + * lock SPI to have exclusive access to the busses for a sequence of + * transfers. The bus should be locked before the chip is selected. + * + * This is a blocking call and will not return until we have exclusiv access to + * the SPI buss. We will retain that exclusive access until the bus is unlocked. + */ + + (void)SPI_LOCK(dev, true); + + /* After locking the SPI bus, the we also need call the setfrequency, setbits, and + * setmode methods to make sure that the SPI is properly configured for the device. + * If the SPI buss is being shared, then it may have been left in an incompatible + * state. + */ + + SPI_SETMODE(dev, SPIDEV_MODE3); + SPI_SETBITS(dev, 8); + + (void)SPI_SETFREQUENCY(dev, RAMTRON_INIT_CLK_MAX); +} + +/************************************************************************************ + * Name: ramtron_unlock + ************************************************************************************/ + +static inline void ramtron_unlock(FAR struct spi_dev_s *dev) +{ + (void)SPI_LOCK(dev, false); +} + +/************************************************************************************ + * Name: ramtron_readid + ************************************************************************************/ + +static inline int ramtron_readid(struct ramtron_dev_s *priv) +{ + uint16_t manufacturer, memory, capacity, part; + int i; + + fvdbg("priv: %p\n", priv); + + /* Lock the SPI bus, configure the bus, and select this FLASH part. */ + + ramtron_lock(priv->dev); + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send the "Read ID (RDID)" command and read the first three ID bytes */ + + (void)SPI_SEND(priv->dev, RAMTRON_RDID); + for (i=0; i<6; i++) manufacturer = SPI_SEND(priv->dev, RAMTRON_DUMMY); + memory = SPI_SEND(priv->dev, RAMTRON_DUMMY); + capacity = SPI_SEND(priv->dev, RAMTRON_DUMMY); // fram.id1 + part = SPI_SEND(priv->dev, RAMTRON_DUMMY); // fram.id2 + + /* Deselect the FLASH and unlock the bus */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + ramtron_unlock(priv->dev); + + // Select part from the part list + for (priv->part = ramtron_parts; + priv->part->name != NULL && !(priv->part->id1 == capacity && priv->part->id2 == part); + priv->part++); + + if (priv->part->name) { + fvdbg("RAMTRON %s of size %d bytes (mf:%02x mem:%02x cap:%02x part:%02x)\n", + priv->part->name, priv->part->size, manufacturer, memory, capacity, part); + + priv->sectorshift = RAMTRON_EMULATE_SECTOR_SHIFT; + priv->nsectors = priv->part->size / (1 << RAMTRON_EMULATE_SECTOR_SHIFT); + priv->pageshift = RAMTRON_EMULATE_PAGE_SHIFT; + priv->npages = priv->part->size / (1 << RAMTRON_EMULATE_PAGE_SHIFT); + return OK; + } + + fvdbg("RAMTRON device not found\n"); + return -ENODEV; +} + +/************************************************************************************ + * Name: ramtron_waitwritecomplete + ************************************************************************************/ + +static void ramtron_waitwritecomplete(struct ramtron_dev_s *priv) +{ + uint8_t status; + + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Read Status Register (RDSR)" command */ + + (void)SPI_SEND(priv->dev, RAMTRON_RDSR); + + /* Loop as long as the memory is busy with a write cycle */ + + do + { + /* Send a dummy byte to generate the clock needed to shift out the status */ + + status = SPI_SEND(priv->dev, RAMTRON_DUMMY); + } + while ((status & RAMTRON_SR_WIP) != 0); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + fvdbg("Complete\n"); +} + +/************************************************************************************ + * Name: ramtron_writeenable + ************************************************************************************/ + +static void ramtron_writeenable(struct ramtron_dev_s *priv) +{ + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Write Enable (WREN)" command */ + + (void)SPI_SEND(priv->dev, RAMTRON_WREN); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + fvdbg("Enabled\n"); +} + +/************************************************************************************ + * Name: ramtron_sendaddr + ************************************************************************************/ + +static inline void ramtron_sendaddr(const struct ramtron_dev_s *priv, uint32_t addr) +{ + DEBUGASSERT(priv->part->addr_len == 3 || priv->part->addr_len == 2); + + if (priv->part->addr_len == 3) + (void)SPI_SEND(priv->dev, (addr >> 16) & 0xff); + + (void)SPI_SEND(priv->dev, (addr >> 8) & 0xff); + (void)SPI_SEND(priv->dev, addr & 0xff); +} + +/************************************************************************************ + * Name: ramtron_pagewrite + ************************************************************************************/ + +static inline void ramtron_pagewrite(struct ramtron_dev_s *priv, FAR const uint8_t *buffer, + off_t page) +{ + off_t offset = page << priv->pageshift; + + fvdbg("page: %08lx offset: %08lx\n", (long)page, (long)offset); + + /* Wait for any preceding write to complete. We could simplify things by + * perform this wait at the end of each write operation (rather than at + * the beginning of ALL operations), but have the wait first will slightly + * improve performance. + */ + + ramtron_waitwritecomplete(priv); + + /* Enable the write access to the FLASH */ + + ramtron_writeenable(priv); + + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Page Program (PP)" command */ + + (void)SPI_SEND(priv->dev, RAMTRON_WRITE); + + /* Send the page offset high byte first. */ + + ramtron_sendaddr(priv, offset); + + /* Then write the specified number of bytes */ + + SPI_SNDBLOCK(priv->dev, buffer, 1 << priv->pageshift); + + /* Deselect the FLASH: Chip Select high */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + fvdbg("Written\n"); +} + +/************************************************************************************ + * Name: ramtron_erase + ************************************************************************************/ + +static int ramtron_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks) +{ + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + fvdbg("On RAMTRON devices erasing makes no sense, returning as OK\n"); + return (int)nblocks; +} + +/************************************************************************************ + * Name: ramtron_bread + ************************************************************************************/ + +static ssize_t ramtron_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR uint8_t *buffer) +{ + FAR struct ramtron_dev_s *priv = (FAR struct ramtron_dev_s *)dev; + ssize_t nbytes; + + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + /* On this device, we can handle the block read just like the byte-oriented read */ + + nbytes = ramtron_read(dev, startblock << priv->pageshift, nblocks << priv->pageshift, buffer); + if (nbytes > 0) + { + return nbytes >> priv->pageshift; + } + return (int)nbytes; +} + +/************************************************************************************ + * Name: ramtron_bwrite + ************************************************************************************/ + +static ssize_t ramtron_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR const uint8_t *buffer) +{ + FAR struct ramtron_dev_s *priv = (FAR struct ramtron_dev_s *)dev; + size_t blocksleft = nblocks; + + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + /* Lock the SPI bus and write each page to FLASH */ + + ramtron_lock(priv->dev); + while (blocksleft-- > 0) + { + ramtron_pagewrite(priv, buffer, startblock); + startblock++; + } + ramtron_unlock(priv->dev); + + return nblocks; +} + +/************************************************************************************ + * Name: ramtron_read + ************************************************************************************/ + +static ssize_t ramtron_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes, + FAR uint8_t *buffer) +{ + FAR struct ramtron_dev_s *priv = (FAR struct ramtron_dev_s *)dev; + + fvdbg("offset: %08lx nbytes: %d\n", (long)offset, (int)nbytes); + + /* Wait for any preceding write to complete. We could simplify things by + * perform this wait at the end of each write operation (rather than at + * the beginning of ALL operations), but have the wait first will slightly + * improve performance. + */ + + ramtron_waitwritecomplete(priv); + + /* Lock the SPI bus and select this FLASH part */ + + ramtron_lock(priv->dev); + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Read from Memory " instruction */ + + (void)SPI_SEND(priv->dev, RAMTRON_READ); + + /* Send the page offset high byte first. */ + + ramtron_sendaddr(priv, offset); + + /* Then read all of the requested bytes */ + + SPI_RECVBLOCK(priv->dev, buffer, nbytes); + + /* Deselect the FLASH and unlock the SPI bus */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + ramtron_unlock(priv->dev); + fvdbg("return nbytes: %d\n", (int)nbytes); + return nbytes; +} + +/************************************************************************************ + * Name: ramtron_ioctl + ************************************************************************************/ + +static int ramtron_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg) +{ + FAR struct ramtron_dev_s *priv = (FAR struct ramtron_dev_s *)dev; + int ret = -EINVAL; /* Assume good command with bad parameters */ + + fvdbg("cmd: %d \n", cmd); + + switch (cmd) + { + case MTDIOC_GEOMETRY: + { + FAR struct mtd_geometry_s *geo = (FAR struct mtd_geometry_s *)((uintptr_t)arg); + if (geo) + { + /* Populate the geometry structure with information need to know + * the capacity and how to access the device. + * + * NOTE: that the device is treated as though it where just an array + * of fixed size blocks. That is most likely not true, but the client + * will expect the device logic to do whatever is necessary to make it + * appear so. + */ + + geo->blocksize = (1 << priv->pageshift); + geo->erasesize = (1 << priv->sectorshift); + geo->neraseblocks = priv->nsectors; + ret = OK; + + fvdbg("blocksize: %d erasesize: %d neraseblocks: %d\n", + geo->blocksize, geo->erasesize, geo->neraseblocks); + } + } + break; + + case MTDIOC_BULKERASE: + fvdbg("BULDERASE: Makes no sense in ramtron. Let's confirm operation as OK\n"); + ret = OK; + break; + + case MTDIOC_XIPBASE: + default: + ret = -ENOTTY; /* Bad command */ + break; + } + + fvdbg("return %d\n", ret); + return ret; +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: ramtron_initialize + * + * Description: + * Create an initialize MTD device instance. MTD devices are not registered + * in the file system, but are created as instances that can be bound to + * other functions (such as a block or character driver front end). + * + ************************************************************************************/ + +FAR struct mtd_dev_s *ramtron_initialize(FAR struct spi_dev_s *dev) +{ + FAR struct ramtron_dev_s *priv; + + fvdbg("dev: %p\n", dev); + + /* Allocate a state structure (we allocate the structure instead of using + * a fixed, static allocation so that we can handle multiple FLASH devices. + * The current implementation would handle only one FLASH part per SPI + * device (only because of the SPIDEV_FLASH definition) and so would have + * to be extended to handle multiple FLASH parts on the same SPI bus. + */ + + priv = (FAR struct ramtron_dev_s *)kmalloc(sizeof(struct ramtron_dev_s)); + if (priv) + { + /* Initialize the allocated structure */ + + priv->mtd.erase = ramtron_erase; + priv->mtd.bread = ramtron_bread; + priv->mtd.bwrite = ramtron_bwrite; + priv->mtd.read = ramtron_read; + priv->mtd.ioctl = ramtron_ioctl; + priv->dev = dev; + + /* Deselect the FLASH */ + + SPI_SELECT(dev, SPIDEV_FLASH, false); + + /* Identify the FLASH chip and get its capacity */ + + if (ramtron_readid(priv) != OK) + { + /* Unrecognized! Discard all of that work we just did and return NULL */ + kfree(priv); + priv = NULL; + } + } + + /* Return the implementation-specific state structure as the MTD device */ + + fvdbg("Return %p\n", priv); + return (FAR struct mtd_dev_s *)priv; +} diff --git a/nuttx/drivers/mtd/skeleton.c b/nuttx/drivers/mtd/skeleton.c new file mode 100644 index 0000000000..673ddadb35 --- /dev/null +++ b/nuttx/drivers/mtd/skeleton.c @@ -0,0 +1,275 @@ +/**************************************************************************** + * drivers/mtd/skeleton.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This type represents the state of the MTD device. The struct mtd_dev_s + * must appear at the beginning of the definition so that you can freely + * cast between pointers to struct mtd_dev_s and struct skel_dev_s. + */ + +struct skel_dev_s +{ + struct mtd_dev_s mtd; + + /* Other implementation specific data may follow here */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* MTD driver methods */ + +static int skel_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks); +static ssize_t skel_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR uint8_t *buf); +static ssize_t skel_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR const uint8_t *buf); +static ssize_t skel_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes, + FAR uint8_t *buffer); +static int skel_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct skel_dev_s g_skeldev = +{ + { skel_erase, skel_rbead, skel_bwrite, skel_read, skel_ioctl }, + /* Initialization of any other implemenation specific data goes here */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: skel_erase + ****************************************************************************/ + +static int skel_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks) +{ + FAR struct skel_dev_s *priv = (FAR struct skel_dev_s *)dev; + + /* The interface definition assumes that all erase blocks ar the same size. + * If that is not true for this particular device, then transform the + * start block and nblocks as necessary. + */ + + /* Erase the specified blocks and return status (OK or a negated errno) */ + + return OK; +} + +/**************************************************************************** + * Name: skel_bread + ****************************************************************************/ + +static ssize_t skel_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR uint8_t *buf) +{ + FAR struct skel_dev_s *priv = (FAR struct skel_dev_s *)dev; + + /* The interface definition assumes that all read/write blocks ar the same size. + * If that is not true for this particular device, then transform the + * start block and nblocks as necessary. + */ + + /* Read the specified blocks into the provided user buffer and return status + * (The positive, number of blocks actually read or a negated errno). + */ + + return 0; +} + +/**************************************************************************** + * Name: skel_bwrite + ****************************************************************************/ + +static ssize_t skel_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR const uint8_t *buf) +{ + FAR struct skel_dev_s *priv = (FAR struct skel_dev_s *)dev; + + /* The interface definition assumes that all read/write blocks ar the same size. + * If that is not true for this particular device, then transform the + * start block and nblocks as necessary. + */ + + /* Write the specified blocks from the provided user buffer and return status + * (The positive, number of blocks actually written or a negated errno) + */ + + return 0; +} + +/**************************************************************************** + * Name: skel_read + ****************************************************************************/ + +static ssize_t skel_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes, + FAR uint8_t *buffer) +{ + FAR struct skel_dev_s *priv = (FAR struct skel_dev_s *)dev; + + /* Some devices may support byte oriented read (optional). Byte-oriented + * writing is inherently block oriented on most MTD devices and is not supported. + * It is recommended that low-level drivers not support read() if it requires + * buffering -- let the higher level logic handle that. If the read method is + * not implemented, just set the method pointer to NULL in the struct mtd_dev_s + * instance. + */ + + /* The interface definition assumes that all read/write blocks ar the same size. + * If that is not true for this particular device, then transform the + * start block and nblocks as necessary. + */ + + /* Read the specified blocks into the provided user buffer and return status + * (The positive, number of blocks actually read or a negated errno) + */ + + return 0; +} + +/**************************************************************************** + * Name: skel_ioctl + ****************************************************************************/ + +static int skel_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg) +{ + FAR struct skel_dev_s *priv = (FAR struct skel_dev_s *)dev; + int ret = -EINVAL; /* Assume good command with bad parameters */ + + switch (cmd) + { + case MTDIOC_GEOMETRY: + { + FAR struct mtd_geometry_s *geo = (FARstruct mtd_geometry_s *)arg; + if (geo) + { + /* Populate the geometry structure with information need to know + * the capacity and how to access the device. + * + * NOTE: that the device is treated as though it where just an array + * of fixed size blocks. That is most likely not true, but the client + * will expect the device logic to do whatever is necessary to make it + * appear so. + */ + + geo->blocksize = 512; /* Size of one read/write block */ + geo->erasesize = 4096; /* Size of one erase block */ + geo->neraseblocks = 1024; /* Number of erase blocks */ + ret = OK; + } + } + break; + + case MTDIOC_XIPBASE: + { + FAR void **ppv = (FAR void**)arg; + + if (ppv) + { + /* If media is directly acccesible, return (void*) base address + * of device memory. NULL otherwise. It is acceptable to omit + * this case altogether and simply return -ENOTTY. + */ + + *ppv = NULL; + ret = OK; + } + } + break; + + case MTDIOC_BULKERASE: + { + /* Erase the entire device */ + + ret = OK; + } + break; + + default: + ret = -ENOTTY; /* Bad command */ + break; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: skel_initialize + * + * Description: + * Create and initialize an MTD device instance. MTD devices are not + * registered in the file system, but are created as instances that can + * be bound to other functions (such as a block or character driver front + * end). + * + ****************************************************************************/ + +void skel_initialize(void) +{ + /* Perform initialization as necessary */ + + /* Return the implementation-specific state structure as the MTD device */ + + return (FAR struct mtd_dev_s *)&g_skeldev; +} diff --git a/nuttx/drivers/mtd/sst25.c b/nuttx/drivers/mtd/sst25.c new file mode 100644 index 0000000000..01838f078e --- /dev/null +++ b/nuttx/drivers/mtd/sst25.c @@ -0,0 +1,1250 @@ +/************************************************************************************ + * drivers/mtd/m25px.c + * Driver for SPI-based SST25 FLASH. + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* Per the data sheet, the SST25 parts can be driven with either SPI mode 0 (CPOL=0 + * and CPHA=0) or mode 3 (CPOL=1 and CPHA=1). But I have heard that other devices + * can operate in mode 0 or 1. So you may need to specify CONFIG_SST25_SPIMODE to + * select the best mode for your device. If CONFIG_SST25_SPIMODE is not defined, + * mode 0 will be used. + */ + +#ifndef CONFIG_SST25_SPIMODE +# define CONFIG_SST25_SPIMODE SPIDEV_MODE0 +#endif + +/* SPI Frequency. May be up to 25MHz. */ + +#ifndef CONFIG_SST25_SPIFREQUENCY +# define CONFIG_SST25_SPIFREQUENCY 20000000 +#endif + +/* There is a bug in the current code when using the higher speed AAI write sequence. + * The nature of the bug is that the WRDI instruction is not working. At the end + * of the AAI sequence, the status register continues to report that the SST25 is + * write enabled (WEL bit) and in AAI mode (AAI bit). This *must* be fixed in any + * production code if you want to have proper write performance. + */ + +#warning "REVISIT" +#undef CONFIG_SST25_SLOWWRITE +#define CONFIG_SST25_SLOWWRITE 1 + +/* SST25 Instructions ***************************************************************/ +/* Command Value Description Addr Data */ +/* Dummy */ +#define SST25_READ 0x03 /* Read data bytes 3 0 >=1 */ +#define SST25_FAST_READ 0x0b /* Higher speed read 3 1 >=1 */ +#define SST25_SE 0x20 /* 4Kb Sector erase 3 0 0 */ +#define SST25_BE32 0x52 /* 32Kbit block Erase 3 0 0 */ +#define SST25_BE64 0xd8 /* 64Kbit block Erase 3 0 0 */ +#define SST25_CE 0xc7 /* Chip erase 0 0 0 */ +#define SST25_CE_ALT 0x60 /* Chip erase (alternate) 0 0 0 */ +#define SST25_BP 0x02 /* Byte program 3 0 1 */ +#define SST25_AAI 0xad /* Auto address increment 3 0 >=2 */ +#define SST25_RDSR 0x05 /* Read status register 0 0 >=1 */ +#define SST25_EWSR 0x50 /* Write enable status 0 0 0 */ +#define SST25_WRSR 0x01 /* Write Status Register 0 0 1 */ +#define SST25_WREN 0x06 /* Write Enable 0 0 0 */ +#define SST25_WRDI 0x04 /* Write Disable 0 0 0 */ +#define SST25_RDID 0xab /* Read Identification 0 0 >=1 */ +#define SST25_RDID_ALT 0x90 /* Read Identification (alt) 0 0 >=1 */ +#define SST25_JEDEC_ID 0x9f /* JEDEC ID read 0 0 >=3 */ +#define SST25_EBSY 0x70 /* Enable SO RY/BY# status 0 0 0 */ +#define SST25_DBSY 0x80 /* Disable SO RY/BY# status 0 0 0 */ + +/* SST25 Registers ******************************************************************/ +/* Read ID (RDID) register values */ + +#define SST25_MANUFACTURER 0xbf /* SST manufacturer ID */ +#define SST25_VF032_DEVID 0x20 /* SSTVF032B device ID */ + +/* JEDEC Read ID register values */ + +#define SST25_JEDEC_MANUFACTURER 0xbf /* SST manufacturer ID */ +#define SST25_JEDEC_MEMORY_TYPE 0x25 /* SST25 memory type */ +#define SST25_JEDEC_MEMORY_CAPACITY 0x4a /* SST25VF032B memory capacity */ + +/* Status register bit definitions */ + +#define SST25_SR_BUSY (1 << 0) /* Bit 0: Write in progress */ +#define SST25_SR_WEL (1 << 1) /* Bit 1: Write enable latch bit */ +#define SST25_SR_BP_SHIFT (2) /* Bits 2-5: Block protect bits */ +#define SST25_SR_BP_MASK (15 << SST25_SR_BP_SHIFT) +# define SST25_SR_BP_NONE (0 << SST25_SR_BP_SHIFT) /* Unprotected */ +# define SST25_SR_BP_UPPER64th (1 << SST25_SR_BP_SHIFT) /* Upper 64th */ +# define SST25_SR_BP_UPPER32nd (2 << SST25_SR_BP_SHIFT) /* Upper 32nd */ +# define SST25_SR_BP_UPPER16th (3 << SST25_SR_BP_SHIFT) /* Upper 16th */ +# define SST25_SR_BP_UPPER8th (4 << SST25_SR_BP_SHIFT) /* Upper 8th */ +# define SST25_SR_BP_UPPERQTR (5 << SST25_SR_BP_SHIFT) /* Upper quarter */ +# define SST25_SR_BP_UPPERHALF (6 << SST25_SR_BP_SHIFT) /* Upper half */ +# define SST25_SR_BP_ALL (7 << SST25_SR_BP_SHIFT) /* All sectors */ +#define SST25_SR_AAI (1 << 6) /* Bit 6: Auto Address increment programming */ +#define SST25_SR_SRWD (1 << 7) /* Bit 7: Status register write protect */ + +#define SST25_DUMMY 0xa5 + +/* Chip Geometries ******************************************************************/ +/* SST25VF512 capacity is 512Kbit (64Kbit x 8) = 64Kb (8Kb x 8)*/ +/* SST25VF010 capacity is 1Mbit (128Kbit x 8) = 128Kb (16Kb x 8*/ +/* SST25VF520 capacity is 2Mbit (256Kbit x 8) = 256Kb (32Kb x 8) */ +/* SST25VF540 capacity is 4Mbit (512Kbit x 8) = 512Kb (64Kb x 8) */ +/* SST25VF080 capacity is 8Mbit (1024Kbit x 8) = 1Mb (128Kb x 8) */ +/* SST25VF016 capacity is 16Mbit (2048Kbit x 8) = 2Mb (256Kb x 8) */ +/* Not yet supported */ + +/* SST25VF032 capacity is 32Mbit (4096Kbit x 8) = 4Mb (512kb x 8) */ + +#define SST25_VF032_SECTOR_SHIFT 12 /* Sector size 1 << 12 = 4Kb */ +#define SST25_VF032_NSECTORS 1024 /* 1024 sectors x 4096 bytes/sector = 4Mb */ + +#ifdef CONFIG_SST25_SECTOR512 /* Simulate a 512 byte sector */ +# define SST25_SECTOR_SHIFT 9 /* Sector size 1 << 9 = 512 bytes */ +# define SST25_SECTOR_SIZE 512 /* Sector size = 512 bytes */ +#endif + +#define SST25_ERASED_STATE 0xff /* State of FLASH when erased */ + +/* Cache flags */ + +#define SST25_CACHE_VALID (1 << 0) /* 1=Cache has valid data */ +#define SST25_CACHE_DIRTY (1 << 1) /* 1=Cache is dirty */ +#define SST25_CACHE_ERASED (1 << 2) /* 1=Backing FLASH is erased */ + +#define IS_VALID(p) ((((p)->flags) & SST25_CACHE_VALID) != 0) +#define IS_DIRTY(p) ((((p)->flags) & SST25_CACHE_DIRTY) != 0) +#define IS_ERASED(p) ((((p)->flags) & SST25_CACHE_DIRTY) != 0) + +#define SET_VALID(p) do { (p)->flags |= SST25_CACHE_VALID; } while (0) +#define SET_DIRTY(p) do { (p)->flags |= SST25_CACHE_DIRTY; } while (0) +#define SET_ERASED(p) do { (p)->flags |= SST25_CACHE_DIRTY; } while (0) + +#define CLR_VALID(p) do { (p)->flags &= ~SST25_CACHE_VALID; } while (0) +#define CLR_DIRTY(p) do { (p)->flags &= ~SST25_CACHE_DIRTY; } while (0) +#define CLR_ERASED(p) do { (p)->flags &= ~SST25_CACHE_DIRTY; } while (0) + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/* This type represents the state of the MTD device. The struct mtd_dev_s must + * appear at the beginning of the definition so that you can freely cast between + * pointers to struct mtd_dev_s and struct sst25_dev_s. + */ + +struct sst25_dev_s +{ + struct mtd_dev_s mtd; /* MTD interface */ + FAR struct spi_dev_s *dev; /* Saved SPI interface instance */ + uint16_t nsectors; /* Number of erase sectors */ + uint8_t sectorshift; /* Log2 of erase sector size */ + +#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY) + uint8_t flags; /* Buffered sector flags */ + uint16_t esectno; /* Erase sector number in the cache*/ + FAR uint8_t *sector; /* Allocated sector data */ +#endif +}; + +/************************************************************************************ + * Private Function Prototypes + ************************************************************************************/ + +/* Helpers */ + +static void sst25_lock(FAR struct spi_dev_s *dev); +static inline void sst25_unlock(FAR struct spi_dev_s *dev); +static inline int sst25_readid(FAR struct sst25_dev_s *priv); +#ifndef CONFIG_SST25_READONLY +static void sst25_unprotect(FAR struct spi_dev_s *dev); +#endif +static uint8_t sst25_waitwritecomplete(FAR struct sst25_dev_s *priv); +static inline void sst25_wren(FAR struct sst25_dev_s *priv); +static inline void sst25_wrdi(FAR struct sst25_dev_s *priv); +static void sst25_sectorerase(FAR struct sst25_dev_s *priv, off_t offset); +static inline int sst25_chiperase(FAR struct sst25_dev_s *priv); +static void sst25_byteread(FAR struct sst25_dev_s *priv, FAR uint8_t *buffer, + off_t address, size_t nbytes); +#ifndef CONFIG_SST25_READONLY +#ifdef CONFIG_SST25_SLOWWRITE +static void sst25_bytewrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *buffer, + off_t address, size_t nbytes); +#else +static void sst25_wordwrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *buffer, + off_t address, size_t nbytes); +#endif +#ifdef CONFIG_SST25_SECTOR512 +static void sst25_cacheflush(struct sst25_dev_s *priv); +static FAR uint8_t *sst25_cacheread(struct sst25_dev_s *priv, off_t sector); +static void sst25_cacheerase(struct sst25_dev_s *priv, off_t sector); +static void sst25_cachewrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *buffer, + off_t sector, size_t nsectors); +#endif +#endif + +/* MTD driver methods */ + +static int sst25_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks); +static ssize_t sst25_bread(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR uint8_t *buf); +static ssize_t sst25_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR const uint8_t *buf); +static ssize_t sst25_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes, + FAR uint8_t *buffer); +static int sst25_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg); + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: sst25_lock + ************************************************************************************/ + +static void sst25_lock(FAR struct spi_dev_s *dev) +{ + /* On SPI busses where there are multiple devices, it will be necessary to + * lock SPI to have exclusive access to the busses for a sequence of + * transfers. The bus should be locked before the chip is selected. + * + * This is a blocking call and will not return until we have exclusiv access to + * the SPI buss. We will retain that exclusive access until the bus is unlocked. + */ + + (void)SPI_LOCK(dev, true); + + /* After locking the SPI bus, the we also need call the setfrequency, setbits, and + * setmode methods to make sure that the SPI is properly configured for the device. + * If the SPI buss is being shared, then it may have been left in an incompatible + * state. + */ + + SPI_SETMODE(dev, CONFIG_SST25_SPIMODE); + SPI_SETBITS(dev, 8); + (void)SPI_SETFREQUENCY(dev, CONFIG_SST25_SPIFREQUENCY); +} + +/************************************************************************************ + * Name: sst25_unlock + ************************************************************************************/ + +static inline void sst25_unlock(FAR struct spi_dev_s *dev) +{ + (void)SPI_LOCK(dev, false); +} + +/************************************************************************************ + * Name: sst25_readid + ************************************************************************************/ + +static inline int sst25_readid(struct sst25_dev_s *priv) +{ + uint16_t manufacturer; + uint16_t memory; + uint16_t capacity; + + fvdbg("priv: %p\n", priv); + + /* Lock the SPI bus, configure the bus, and select this FLASH part. */ + + sst25_lock(priv->dev); + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send the "Read ID (RDID)" command and read the first three ID bytes */ + + (void)SPI_SEND(priv->dev, SST25_JEDEC_ID); + manufacturer = SPI_SEND(priv->dev, SST25_DUMMY); + memory = SPI_SEND(priv->dev, SST25_DUMMY); + capacity = SPI_SEND(priv->dev, SST25_DUMMY); + + /* Deselect the FLASH and unlock the bus */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + sst25_unlock(priv->dev); + + fvdbg("manufacturer: %02x memory: %02x capacity: %02x\n", + manufacturer, memory, capacity); + + /* Check for a valid manufacturer and memory type */ + + if (manufacturer == SST25_JEDEC_MANUFACTURER && memory == SST25_JEDEC_MEMORY_TYPE) + { + /* Okay.. is it a FLASH capacity that we understand? This should be extended + * support other members of the SST25 family. + */ + + if (capacity == SST25_JEDEC_MEMORY_CAPACITY) + { + /* Save the FLASH geometry */ + + priv->sectorshift = SST25_VF032_SECTOR_SHIFT; + priv->nsectors = SST25_VF032_NSECTORS; + return OK; + } + } + + return -ENODEV; +} + +/************************************************************************************ + * Name: sst25_unprotect + ************************************************************************************/ + +#ifndef CONFIG_SST25_READONLY +static void sst25_unprotect(FAR struct spi_dev_s *dev) +{ + /* Select this FLASH part */ + + SPI_SELECT(dev, SPIDEV_FLASH, true); + + /* Send "Write enable status (EWSR)" */ + + SPI_SEND(dev, SST25_EWSR); + + /* Re-select this FLASH part (This might not be necessary... but is it shown in + * the timing diagrams) + */ + + SPI_SELECT(dev, SPIDEV_FLASH, false); + SPI_SELECT(dev, SPIDEV_FLASH, true); + + /* Send "Write enable status (EWSR)" */ + + SPI_SEND(dev, SST25_WRSR); + + /* Following by the new status value */ + + SPI_SEND(dev, 0); +} +#endif + +/************************************************************************************ + * Name: sst25_waitwritecomplete + ************************************************************************************/ + +static uint8_t sst25_waitwritecomplete(struct sst25_dev_s *priv) +{ + uint8_t status; + + /* Are we the only device on the bus? */ + +#ifdef CONFIG_SPI_OWNBUS + + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Read Status Register (RDSR)" command */ + + (void)SPI_SEND(priv->dev, SST25_RDSR); + + /* Loop as long as the memory is busy with a write cycle */ + + do + { + /* Send a dummy byte to generate the clock needed to shift out the status */ + + status = SPI_SEND(priv->dev, SST25_DUMMY); + } + while ((status & SST25_SR_BUSY) != 0); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + +#else + + /* Loop as long as the memory is busy with a write cycle */ + + do + { + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Read Status Register (RDSR)" command */ + + (void)SPI_SEND(priv->dev, SST25_RDSR); + + /* Send a dummy byte to generate the clock needed to shift out the status */ + + status = SPI_SEND(priv->dev, SST25_DUMMY); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + + /* Given that writing could take up to few tens of milliseconds, and erasing + * could take more. The following short delay in the "busy" case will allow + * other peripherals to access the SPI bus. + */ + +#if 0 /* Makes writes too slow */ + if ((status & SST25_SR_BUSY) != 0) + { + sst25_unlock(priv->dev); + usleep(1000); + sst25_lock(priv->dev); + } +#endif + } + while ((status & SST25_SR_BUSY) != 0); +#endif + + return status; +} + +/************************************************************************************ + * Name: sst25_wren + ************************************************************************************/ + +static inline void sst25_wren(struct sst25_dev_s *priv) +{ + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Write Enable (WREN)" command */ + + (void)SPI_SEND(priv->dev, SST25_WREN); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); +} + +/************************************************************************************ + * Name: sst25_wrdi + ************************************************************************************/ + +static inline void sst25_wrdi(struct sst25_dev_s *priv) +{ + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Write Disable (WRDI)" command */ + + (void)SPI_SEND(priv->dev, SST25_WRDI); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); +} + +/************************************************************************************ + * Name: sst25_sectorerase + ************************************************************************************/ + +static void sst25_sectorerase(struct sst25_dev_s *priv, off_t sector) +{ + off_t address = sector << priv->sectorshift; + + fvdbg("sector: %08lx\n", (long)sector); + + /* Wait for any preceding write or erase operation to complete. */ + + (void)sst25_waitwritecomplete(priv); + + /* Send write enable instruction */ + + sst25_wren(priv); + + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send the "Sector Erase (SE)" instruction */ + + (void)SPI_SEND(priv->dev, SST25_SE); + + /* Send the sector address high byte first. Only the most significant bits (those + * corresponding to the sector) have any meaning. + */ + + (void)SPI_SEND(priv->dev, (address >> 16) & 0xff); + (void)SPI_SEND(priv->dev, (address >> 8) & 0xff); + (void)SPI_SEND(priv->dev, address & 0xff); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); +} + +/************************************************************************************ + * Name: sst25_chiperase + ************************************************************************************/ + +static inline int sst25_chiperase(struct sst25_dev_s *priv) +{ + fvdbg("priv: %p\n", priv); + + /* Wait for any preceding write or erase operation to complete. */ + + (void)sst25_waitwritecomplete(priv); + + /* Send write enable instruction */ + + sst25_wren(priv); + + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send the "Chip Erase (CE)" instruction */ + + (void)SPI_SEND(priv->dev, SST25_CE); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + fvdbg("Return: OK\n"); + return OK; +} + +/************************************************************************************ + * Name: sst25_byteread + ************************************************************************************/ + +static void sst25_byteread(FAR struct sst25_dev_s *priv, FAR uint8_t *buffer, + off_t address, size_t nbytes) +{ + uint8_t status; + + fvdbg("address: %08lx nbytes: %d\n", (long)address, (int)nbytes); + + /* Wait for any preceding write or erase operation to complete. */ + + status = sst25_waitwritecomplete(priv); + DEBUGASSERT((status & (SST25_SR_WEL|SST25_SR_BP_MASK|SST25_SR_AAI)) == 0); + + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Read from Memory " instruction */ + +#ifdef CONFIG_SST25_SLOWREAD + (void)SPI_SEND(priv->dev, SST25_READ); +#else + (void)SPI_SEND(priv->dev, SST25_FAST_READ); +#endif + + /* Send the address high byte first. */ + + (void)SPI_SEND(priv->dev, (address >> 16) & 0xff); + (void)SPI_SEND(priv->dev, (address >> 8) & 0xff); + (void)SPI_SEND(priv->dev, address & 0xff); + + /* Send a dummy byte */ + +#ifndef CONFIG_SST25_SLOWREAD + (void)SPI_SEND(priv->dev, SST25_DUMMY); +#endif + + /* Then read all of the requested bytes */ + + SPI_RECVBLOCK(priv->dev, buffer, nbytes); + + /* Deselect the FLASH */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); +} + +/************************************************************************************ + * Name: sst25_bytewrite + ************************************************************************************/ + +#if defined(CONFIG_SST25_SLOWWRITE) && !defined(CONFIG_SST25_READONLY) +static void sst25_bytewrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer, + off_t address, size_t nbytes) +{ + uint8_t status; + + fvdbg("address: %08lx nwords: %d\n", (long)address, (int)nbytes); + DEBUGASSERT(priv && buffer); + + /* Write each byte individually */ + + for (; nbytes > 0; nbytes--) + { + /* Skip over bytes that are begin written to the erased state */ + + if (*buffer != SST25_ERASED_STATE) + { + /* Wait for any preceding write or erase operation to complete. */ + + status = sst25_waitwritecomplete(priv); + DEBUGASSERT((status & (SST25_SR_WEL|SST25_SR_BP_MASK|SST25_SR_AAI)) == 0); + + /* Enable write access to the FLASH */ + + sst25_wren(priv); + + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Byte Program (BP)" command */ + + (void)SPI_SEND(priv->dev, SST25_BP); + + /* Send the byte address high byte first. */ + + (void)SPI_SEND(priv->dev, (address >> 16) & 0xff); + (void)SPI_SEND(priv->dev, (address >> 8) & 0xff); + (void)SPI_SEND(priv->dev, address & 0xff); + + /* Then write the single byte */ + + (void)SPI_SEND(priv->dev, *buffer); + + /* Deselect the FLASH and setup for the next pass through the loop */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + } + + /* Advance to the next byte */ + + buffer++; + address++; + } +} +#endif + +/************************************************************************************ + * Name: sst25_wordwrite + ************************************************************************************/ + +#if !defined(CONFIG_SST25_SLOWWRITE) && !defined(CONFIG_SST25_READONLY) +static void sst25_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer, + off_t address, size_t nbytes) +{ + size_t nwords = (nbytes + 1) >> 1; + uint8_t status; + + fvdbg("address: %08lx nwords: %d\n", (long)address, (int)nwords); + DEBUGASSERT(priv && buffer); + + /* Loop until all of the bytes have been written */ + + while (nwords > 0) + { + /* Skip over any data that is being written to the erased state */ + + while (nwords > 0 && + buffer[0] == SST25_ERASED_STATE && + buffer[1] == SST25_ERASED_STATE) + { + /* Decrement the word count and advance the write position */ + + nwords--; + buffer += 2; + address += 2; + } + + /* If there are no further non-erased bytes in the user buffer, then + * we are finished. + */ + + if (nwords <= 0) + { + return; + } + + /* Wait for any preceding write or erase operation to complete. */ + + status = sst25_waitwritecomplete(priv); + DEBUGASSERT((status & (SST25_SR_WEL|SST25_SR_BP_MASK|SST25_SR_AAI)) == 0); + + /* Enable write access to the FLASH */ + + sst25_wren(priv); + + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Auto Address Increment (AAI)" command */ + + (void)SPI_SEND(priv->dev, SST25_AAI); + + /* Send the word address high byte first. */ + + (void)SPI_SEND(priv->dev, (address >> 16) & 0xff); + (void)SPI_SEND(priv->dev, (address >> 8) & 0xff); + (void)SPI_SEND(priv->dev, address & 0xff); + + /* Then write one 16-bit word */ + + SPI_SNDBLOCK(priv->dev, buffer, 2); + + /* Deselect the FLASH: Chip Select high */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + + /* Decrement the word count and advance the write position */ + + nwords--; + buffer += 2; + address += 2; + + /* Now loop, writing 16-bits of data on each pass through the loop + * until all of the words have been transferred or until we encounter + * data to be written to the erased state. + */ + + while (nwords > 0 && + (buffer[0] != SST25_ERASED_STATE || + buffer[1] != SST25_ERASED_STATE)) + { + /* Wait for the preceding write to complete. */ + + status = sst25_waitwritecomplete(priv); + DEBUGASSERT((status & (SST25_SR_WEL|SST25_SR_BP_MASK|SST25_SR_AAI)) == (SST25_SR_WEL|SST25_SR_AAI)); + + /* Select this FLASH part */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, true); + + /* Send "Auto Address Increment (AAI)" command with no address */ + + (void)SPI_SEND(priv->dev, SST25_AAI); + + /* Then write one 16-bit word */ + + SPI_SNDBLOCK(priv->dev, buffer, 2); + + /* Deselect the FLASH: Chip Select high */ + + SPI_SELECT(priv->dev, SPIDEV_FLASH, false); + + /* Decrement the word count and advance the write position */ + + nwords--; + buffer += 2; + address += 2; + } + + /* Disable writing */ + + sst25_wrdi(priv); + } +} +#endif + +/************************************************************************************ + * Name: sst25_cacheflush + ************************************************************************************/ + +#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY) +static void sst25_cacheflush(struct sst25_dev_s *priv) +{ + /* If the cached is dirty (meaning that it no longer matches the old FLASH contents) + * or was erased (with the cache containing the correct FLASH contents), then write + * the cached erase block to FLASH. + */ + + if (IS_DIRTY(priv) || IS_ERASED(priv)) + { + /* Write entire erase block to FLASH */ + +#ifdef CONFIG_SST25_SLOWWRITE + sst25_bytewrite(priv, priv->sector, (off_t)priv->esectno << priv->sectorshift, + (1 << priv->sectorshift)); +#else + sst25_wordwrite(priv, priv->sector, (off_t)priv->esectno << priv->sectorshift, + (1 << priv->sectorshift)); +#endif + + /* The case is no long dirty and the FLASH is no longer erased */ + + CLR_DIRTY(priv); + CLR_ERASED(priv); + } +} +#endif + +/************************************************************************************ + * Name: sst25_cacheread + ************************************************************************************/ + +#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY) +static FAR uint8_t *sst25_cacheread(struct sst25_dev_s *priv, off_t sector) +{ + off_t esectno; + int shift; + int index; + + /* Convert from the 512 byte sector to the erase sector size of the device. For + * exmample, if the actual erase sector size if 4Kb (1 << 12), then we first + * shift to the right by 3 to get the sector number in 4096 increments. + */ + + shift = priv->sectorshift - SST25_SECTOR_SHIFT; + esectno = sector >> shift; + fvdbg("sector: %ld esectno: %d shift=%d\n", sector, esectno, shift); + + /* Check if the requested erase block is already in the cache */ + + if (!IS_VALID(priv) || esectno != priv->esectno) + { + /* No.. Flush any dirty erase block currently in the cache */ + + sst25_cacheflush(priv); + + /* Read the erase block into the cache */ + + sst25_byteread(priv, priv->sector, (esectno << priv->sectorshift), 1 << priv->sectorshift); + + /* Mark the sector as cached */ + + priv->esectno = esectno; + + SET_VALID(priv); /* The data in the cache is valid */ + CLR_DIRTY(priv); /* It should match the FLASH contents */ + CLR_ERASED(priv); /* The underlying FLASH has not been erased */ + } + + /* Get the index to the 512 sector in the erase block that holds the argument */ + + index = sector & ((1 << shift) - 1); + + /* Return the address in the cache that holds this sector */ + + return &priv->sector[index << SST25_SECTOR_SHIFT]; +} +#endif + +/************************************************************************************ + * Name: sst25_cacheerase + ************************************************************************************/ + +#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY) +static void sst25_cacheerase(struct sst25_dev_s *priv, off_t sector) +{ + FAR uint8_t *dest; + + /* First, make sure that the erase block containing the 512 byte sector is in + * the cache. + */ + + dest = sst25_cacheread(priv, sector); + + /* Erase the block containing this sector if it is not already erased. + * The erased indicated will be cleared when the data from the erase sector + * is read into the cache and set here when we erase the block. + */ + + if (!IS_ERASED(priv)) + { + off_t esectno = sector >> (priv->sectorshift - SST25_SECTOR_SHIFT); + fvdbg("sector: %ld esectno: %d\n", sector, esectno); + + sst25_sectorerase(priv, esectno); + SET_ERASED(priv); + } + + /* Put the cached sector data into the erase state and mart the cache as dirty + * (but don't update the FLASH yet. The caller will do that at a more optimal + * time). + */ + + memset(dest, SST25_ERASED_STATE, SST25_SECTOR_SIZE); + SET_DIRTY(priv); +} +#endif + +/************************************************************************************ + * Name: sst25_cachewrite + ************************************************************************************/ + +#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY) +static void sst25_cachewrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *buffer, + off_t sector, size_t nsectors) +{ + FAR uint8_t *dest; + + for (; nsectors > 0; nsectors--) + { + /* First, make sure that the erase block containing 512 byte sector is in + * memory. + */ + + dest = sst25_cacheread(priv, sector); + + /* Erase the block containing this sector if it is not already erased. + * The erased indicated will be cleared when the data from the erase sector + * is read into the cache and set here when we erase the sector. + */ + + if (!IS_ERASED(priv)) + { + off_t esectno = sector >> (priv->sectorshift - SST25_SECTOR_SHIFT); + fvdbg("sector: %ld esectno: %d\n", sector, esectno); + + sst25_sectorerase(priv, esectno); + SET_ERASED(priv); + } + + /* Copy the new sector data into cached erase block */ + + memcpy(dest, buffer, SST25_SECTOR_SIZE); + SET_DIRTY(priv); + + /* Set up for the next 512 byte sector */ + + buffer += SST25_SECTOR_SIZE; + sector++; + } + + /* Flush the last erase block left in the cache */ + + sst25_cacheflush(priv); +} +#endif + +/************************************************************************************ + * Name: sst25_erase + ************************************************************************************/ + +static int sst25_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks) +{ +#ifdef CONFIG_SST25_READONLY + return -EACESS +#else + FAR struct sst25_dev_s *priv = (FAR struct sst25_dev_s *)dev; + size_t blocksleft = nblocks; + + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + /* Lock access to the SPI bus until we complete the erase */ + + sst25_lock(priv->dev); + + while (blocksleft-- > 0) + { + /* Erase each sector */ + +#ifdef CONFIG_SST25_SECTOR512 + sst25_cacheerase(priv, startblock); +#else + sst25_sectorerase(priv, startblock); +#endif + startblock++; + } + +#ifdef CONFIG_SST25_SECTOR512 + /* Flush the last erase block left in the cache */ + + sst25_cacheflush(priv); +#endif + + sst25_unlock(priv->dev); + return (int)nblocks; +#endif +} + +/************************************************************************************ + * Name: sst25_bread + ************************************************************************************/ + +static ssize_t sst25_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR uint8_t *buffer) +{ +#ifdef CONFIG_SST25_SECTOR512 + ssize_t nbytes; + + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + /* On this device, we can handle the block read just like the byte-oriented read */ + + nbytes = sst25_read(dev, startblock << SST25_SECTOR_SHIFT, nblocks << SST25_SECTOR_SHIFT, buffer); + if (nbytes > 0) + { + return nbytes >> SST25_SECTOR_SHIFT; + } + + return (int)nbytes; +#else + FAR struct sst25_dev_s *priv = (FAR struct sst25_dev_s *)dev; + ssize_t nbytes; + + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + /* On this device, we can handle the block read just like the byte-oriented read */ + + nbytes = sst25_read(dev, startblock << priv->sectorshift, nblocks << priv->sectorshift, buffer); + if (nbytes > 0) + { + return nbytes >> priv->sectorshift; + } + + return (int)nbytes; +#endif +} + +/************************************************************************************ + * Name: sst25_bwrite + ************************************************************************************/ + +static ssize_t sst25_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR const uint8_t *buffer) +{ +#ifdef CONFIG_SST25_READONLY + return -EACCESS; +#else + FAR struct sst25_dev_s *priv = (FAR struct sst25_dev_s *)dev; + + fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + /* Lock the SPI bus and write all of the pages to FLASH */ + + sst25_lock(priv->dev); + +#if defined(CONFIG_SST25_SECTOR512) + sst25_cachewrite(priv, buffer, startblock, nblocks); +#elif defined(CONFIG_SST25_SLOWWRITE) + sst25_bytewrite(priv, buffer, startblock << priv->sectorshift, + nblocks << priv->sectorshift); +#else + sst25_wordwrite(priv, buffer, startblock << priv->sectorshift, + nblocks << priv->sectorshift); +#endif + sst25_unlock(priv->dev); + + return nblocks; +#endif +} + +/************************************************************************************ + * Name: sst25_read + ************************************************************************************/ + +static ssize_t sst25_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes, + FAR uint8_t *buffer) +{ + FAR struct sst25_dev_s *priv = (FAR struct sst25_dev_s *)dev; + + fvdbg("offset: %08lx nbytes: %d\n", (long)offset, (int)nbytes); + + /* Lock the SPI bus and select this FLASH part */ + + sst25_lock(priv->dev); + sst25_byteread(priv, buffer, offset, nbytes); + sst25_unlock(priv->dev); + + fvdbg("return nbytes: %d\n", (int)nbytes); + return nbytes; +} + +/************************************************************************************ + * Name: sst25_ioctl + ************************************************************************************/ + +static int sst25_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg) +{ + FAR struct sst25_dev_s *priv = (FAR struct sst25_dev_s *)dev; + int ret = -EINVAL; /* Assume good command with bad parameters */ + + fvdbg("cmd: %d \n", cmd); + + switch (cmd) + { + case MTDIOC_GEOMETRY: + { + FAR struct mtd_geometry_s *geo = (FAR struct mtd_geometry_s *)((uintptr_t)arg); + if (geo) + { + /* Populate the geometry structure with information need to know + * the capacity and how to access the device. + * + * NOTE: that the device is treated as though it where just an array + * of fixed size blocks. That is most likely not true, but the client + * will expect the device logic to do whatever is necessary to make it + * appear so. + */ + +#ifdef CONFIG_SST25_SECTOR512 + geo->blocksize = (1 << SST25_SECTOR_SHIFT); + geo->erasesize = (1 << SST25_SECTOR_SHIFT); + geo->neraseblocks = priv->nsectors << (priv->sectorshift - ); +#else + geo->blocksize = (1 << priv->sectorshift); + geo->erasesize = (1 << priv->sectorshift); + geo->neraseblocks = priv->nsectors; +#endif + ret = OK; + + fvdbg("blocksize: %d erasesize: %d neraseblocks: %d\n", + geo->blocksize, geo->erasesize, geo->neraseblocks); + } + } + break; + + case MTDIOC_BULKERASE: + { + /* Erase the entire device */ + + sst25_lock(priv->dev); + ret = sst25_chiperase(priv); + sst25_unlock(priv->dev); + } + break; + + case MTDIOC_XIPBASE: + default: + ret = -ENOTTY; /* Bad command */ + break; + } + + fvdbg("return %d\n", ret); + return ret; +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: sst25_initialize + * + * Description: + * Create an initialize MTD device instance. MTD devices are not registered + * in the file system, but are created as instances that can be bound to + * other functions (such as a block or character driver front end). + * + ************************************************************************************/ + +FAR struct mtd_dev_s *sst25_initialize(FAR struct spi_dev_s *dev) +{ + FAR struct sst25_dev_s *priv; + int ret; + + fvdbg("dev: %p\n", dev); + + /* Allocate a state structure (we allocate the structure instead of using + * a fixed, static allocation so that we can handle multiple FLASH devices. + * The current implementation would handle only one FLASH part per SPI + * device (only because of the SPIDEV_FLASH definition) and so would have + * to be extended to handle multiple FLASH parts on the same SPI bus. + */ + + priv = (FAR struct sst25_dev_s *)kzalloc(sizeof(struct sst25_dev_s)); + if (priv) + { + /* Initialize the allocated structure */ + + priv->mtd.erase = sst25_erase; + priv->mtd.bread = sst25_bread; + priv->mtd.bwrite = sst25_bwrite; + priv->mtd.read = sst25_read; + priv->mtd.ioctl = sst25_ioctl; + priv->dev = dev; + + /* Deselect the FLASH */ + + SPI_SELECT(dev, SPIDEV_FLASH, false); + + /* Identify the FLASH chip and get its capacity */ + + ret = sst25_readid(priv); + if (ret != OK) + { + /* Unrecognized! Discard all of that work we just did and return NULL */ + + fdbg("Unrecognized\n"); + kfree(priv); + priv = NULL; + } + else + { + /* Make sure the the FLASH is unprotected so that we can write into it */ + +#ifndef CONFIG_SST25_READONLY + sst25_unprotect(priv->dev); +#endif + +#ifdef CONFIG_SST25_SECTOR512 /* Simulate a 512 byte sector */ + /* Allocate a buffer for the erase block cache */ + + priv->sector = (FAR uint8_t *)kmalloc(1 << priv->sectorshift); + if (!priv->sector) + { + /* Allocation failed! Discard all of that work we just did and return NULL */ + + fdbg("Allocation failed\n"); + kfree(priv); + priv = NULL; + } +#endif + } + } + + /* Return the implementation-specific state structure as the MTD device */ + + fvdbg("Return %p\n", priv); + return (FAR struct mtd_dev_s *)priv; +} diff --git a/nuttx/drivers/net/Kconfig b/nuttx/drivers/net/Kconfig new file mode 100644 index 0000000000..988b96c948 --- /dev/null +++ b/nuttx/drivers/net/Kconfig @@ -0,0 +1,75 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# +config NET_DM90x0 + bool "Davicom dm9000/dm9010 support" + default n + ---help--- + References: Davicom data sheets (DM9000-DS-F03-041906.pdf, + DM9010-DS-F01-103006.pdf) and looking at lots of other DM90x0 + drivers. + +config NET_CS89x0 + bool "CS89x0 support" + default n + depends on EXPERIMENTAL + ---help--- + Under construction -- do not use + +config ENC28J60 + bool "Microchip ENC28J60 support" + default n + select SPI + ---help--- + References: + ENC28J60 Data Sheet, Stand-Alone Ethernet Controller with SPI Interface, + DS39662C, 2008 Microchip Technology Inc. +if ENC28J60 +config ENC28J60_NINTERFACES + int "Number of physical ENC28J60" + default 1 + range 1,1 + ---help--- + Specifies the number of physical ENC28J60 + devices that will be supported. + +config ENC28J60_SPIMODE + int "SPI mode" + default 2 + ---help--- + Controls the SPI mode + +config ENC28J60_FREQUENCY + int "SPI frequency" + default 20000000 + ---help--- + Define to use a different bus frequency + +config ENC28J60_STATS + bool "Network statistics support" + default n + ---help--- + Collect network statistics + +config ENC28J60_HALFDUPPLEX + bool "Enable half dupplex" + default n + ---help--- + Default is full duplex +endif + +config NET_E1000 + bool "E1000 support" + default n + +config NET_SLIP + bool "SLIP (serial line) support" + default n + ---help--- + Reference: RFC 1055 + +config NET_VNET + bool "VNET support" + default n + diff --git a/nuttx/drivers/net/Make.defs b/nuttx/drivers/net/Make.defs new file mode 100644 index 0000000000..ab256cd8ae --- /dev/null +++ b/nuttx/drivers/net/Make.defs @@ -0,0 +1,71 @@ +############################################################################ +# drivers/net/Make.defs +# +# Copyright (C) 2007, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Include nothing if networking is disabled + +ifeq ($(CONFIG_NET),y) + +# Include network interface drivers + +ifeq ($(CONFIG_NET_DM90x0),y) + CSRCS += dm90x0.c +endif + +ifeq ($(CONFIG_NET_CS89x0),y) + CSRCS += cs89x0.c +endif + +ifeq ($(CONFIG_NET_ENC28J60),y) + CSRCS += enc28j60.c +endif + +ifeq ($(CONFIG_NET_VNET),y) + CSRCS += vnet.c +endif + +ifeq ($(CONFIG_NET_E1000),y) + CSRCS += e1000.c +endif + +ifeq ($(CONFIG_NET_SLIP),y) + CSRCS += slip.c +endif + +# Include network build support + +DEPPATH += --dep-path net +VPATH += :net +endif + diff --git a/nuttx/drivers/net/cs89x0.c b/nuttx/drivers/net/cs89x0.c new file mode 100644 index 0000000000..0f301ee003 --- /dev/null +++ b/nuttx/drivers/net/cs89x0.c @@ -0,0 +1,959 @@ +/**************************************************************************** + * drivers/net/cs89x0.c + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_CS89x0) + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#error "Under construction -- do not use" + +/* CONFIG_CS89x0_NINTERFACES determines the number of physical interfaces + * that will be supported. + */ + +#ifndef CONFIG_CS89x0_NINTERFACES +# define CONFIG_CS89x0_NINTERFACES 1 +#endif + +/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per second */ + +#define CS89x0_WDDELAY (1*CLK_TCK) +#define CS89x0_POLLHSEC (1*2) + +/* TX timeout = 1 minute */ + +#define CS89x0_TXTIMEOUT (60*CLK_TCK) + +/* This is a helper pointer for accessing the contents of the Ethernet header */ + +#define BUF ((struct uip_eth_hdr *)cs89x0->cs_dev.d_buf) + +/* If there is only one CS89x0 instance, then mapping the CS89x0 IRQ to + * a driver state instance is trivial. + */ + +#if CONFIG_CS89x0_NINTERFACES == 1 +# define cs89x0_mapirq(irq) g_cs89x0[0] +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static FAR struct cs89x0_driver_s *g_cs89x0[CONFIG_CS89x0_NINTERFACES]; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* CS89x0 register access */ + +static uint16_t cs89x0_getreg(struct cs89x0_driver_s *cs89x0, int offset); +static void cs89x0_putreg(struct cs89x0_driver_s *cs89x0, int offset, + uint16_t value); +static uint16_t cs89x0_getppreg(struct cs89x0_driver_s *cs89x0, int addr); +static void cs89x0_putppreg(struct cs89x0_driver_s *cs89x0, int addr, + uint16_t value); + +/* Common TX logic */ + +static int cs89x0_transmit(struct cs89x0_driver_s *cs89x0); +static int cs89x0_uiptxpoll(struct uip_driver_s *dev); + +/* Interrupt handling */ + +static void cs89x0_receive(struct cs89x0_driver_s *cs89x0); +static void cs89x0_txdone(struct cs89x0_driver_s *cs89x0, uint16_t isq); +#if CONFIG_CS89x0_NINTERFACES > 1 +static inline FAR struct cs89x0_driver_s *cs89x0_mapirq(int irq); +#endif +static int cs89x0_interrupt(int irq, FAR void *context); + +/* Watchdog timer expirations */ + +static void cs89x0_polltimer(int argc, uint32_t arg, ...); +static void cs89x0_txtimeout(int argc, uint32_t arg, ...); + +/* NuttX callback functions */ + +static int cs89x0_ifup(struct uip_driver_s *dev); +static int cs89x0_ifdown(struct uip_driver_s *dev); +static int cs89x0_txavail(struct uip_driver_s *dev); +#ifdef CONFIG_NET_IGMP +static int cs89x0_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +static int cs89x0_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: cs89x0_getreg and cs89x0_putreg + * + * Description: + * Read from and write to a CS89x0 register + * + * Parameters: + * cs89x0 - Reference to the driver state structure + * offset - Offset to the CS89x0 register + * value - Value to be written (cs89x0_putreg only) + * + * Returned Value: + * cs89x0_getreg: The 16-bit value of the register + * cs89x0_putreg: None + * + ****************************************************************************/ + +static uint16_t cs89x0_getreg(struct cs89x0_driver_s *cs89x0, int offset) +{ +#ifdef CONFIG_CS89x0_ALIGN16 + return getreg16(s89x0->cs_base + offset); +#else + return (uint16_t)getreg32(s89x0->cs_base + offset); +#endif +} + +static void cs89x0_putreg(struct cs89x0_driver_s *cs89x0, int offset, uint16_t value) +{ +#ifdef CONFIG_CS89x0_ALIGN16 + return putreg16(value, s89x0->cs_base + offset); +#else + return (uint16_t)putreg32((uint32_t)value, s89x0->cs_base + offset); +#endif +} + +/**************************************************************************** + * Function: cs89x0_getppreg and cs89x0_putppreg + * + * Description: + * Read from and write to a CS89x0 page packet register + * + * Parameters: + * cs89x0 - Reference to the driver state structure + * addr - Address of the CS89x0 page packet register + * value - Value to be written (cs89x0_putppreg only) + * + * Returned Value: + * cs89x0_getppreg: The 16-bit value of the page packet register + * cs89x0_putppreg: None + * + ****************************************************************************/ + +static uint16_t cs89x0_getppreg(struct cs89x0_driver_s *cs89x0, int addr) +{ + /* In memory mode, the CS89x0's internal registers and frame buffers are mapped + * into a contiguous 4kb block providing direct access to the internal registers + * and frame buffers. + */ + +#ifdef CONFIG_CS89x0_MEMMODE + if (cs89x0->cs_memmode) + { +#ifdef CONFIG_CS89x0_ALIGN16 + return getreg16(s89x0->cs_ppbase + (CS89x0_PDATA_OFFSET << ??)); +#else + return (uint16_t)getreg32(s89x0->cs_ppbase + (CS89x0_PDATA_OFFSET << ??)); +#endif + } + + /* When configured in I/O mode, the CS89x0 is accessed through eight, 16-bit + * I/O ports that in the host system's I/O space. + */ + + else +#endif + { +#ifdef CONFIG_CS89x0_ALIGN16 + putreg16((uint16_t)addr, cs89x0->cs_base + CS89x0_PPTR_OFFSET); + return getreg16(s89x0->cs_base + CS89x0_PDATA_OFFSET); +#else + putreg32((uint32_t)addr, cs89x0->cs_base + CS89x0_PPTR_OFFSET); + return (uint16_t)getreg32(s89x0->cs_base + CS89x0_PDATA_OFFSET); +#endif + } +} + +static void cs89x0_putppreg(struct cs89x0_driver_s *cs89x0, int addr, uint16_t value) +{ + /* In memory mode, the CS89x0's internal registers and frame buffers are mapped + * into a contiguous 4kb block providing direct access to the internal registers + * and frame buffers. + */ + +#ifdef CONFIG_CS89x0_MEMMODE + if (cs89x0->cs_memmode) + { +#ifdef CONFIG_CS89x0_ALIGN16 + putreg16(value), cs89x0->cs_ppbase + (CS89x0_PDATA_OFFSET << ??)); +#else + putreg32((uint32_t)value, cs89x0->cs_ppbase + (CS89x0_PDATA_OFFSET << ??)); +#endif + } + + /* When configured in I/O mode, the CS89x0 is accessed through eight, 16-bit + * I/O ports that in the host system's I/O space. + */ + + else +#endif + { +#ifdef CONFIG_CS89x0_ALIGN16 + putreg16((uint16_t)addr, cs89x0->cs_base + CS89x0_PPTR_OFFSET); + putreg16(value, cs89x0->cs_base + CS89x0_PDATA_OFFSET); +#else + putreg32((uint32_t)addr, cs89x0->cs_base + CS89x0_PPTR_OFFSET); + putreg32((uint32_t)value, cs89x0->cs_base + CS89x0_PDATA_OFFSET); +#endif + } +} + +/**************************************************************************** + * Function: cs89x0_transmit + * + * Description: + * Start hardware transmission. Called either from the txdone interrupt + * handling or from watchdog based polling. + * + * Parameters: + * cs89x0 - Reference to the driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * + ****************************************************************************/ + +static int cs89x0_transmit(struct cs89x0_driver_s *cs89x0) +{ + /* Verify that the hardware is ready to send another packet */ +#warning "Missing logic" + + /* Increment statistics */ +#warning "Missing logic" + + /* Disable Ethernet interrupts */ +#warning "Missing logic" + + /* Send the packet: address=cs89x0->cs_dev.d_buf, length=cs89x0->cs_dev.d_len */ +#warning "Missing logic" + + /* Restore Ethernet interrupts */ +#warning "Missing logic" + + /* Setup the TX timeout watchdog (perhaps restarting the timer) */ + + (void)wd_start(cs89x0->cs_txtimeout, CS89x0_TXTIMEOUT, cs89x0_txtimeout, 1, (uint32_t)cs89x0); + return OK; +} + +/**************************************************************************** + * Function: cs89x0_uiptxpoll + * + * Description: + * The transmitter is available, check if uIP has any outgoing packets ready + * to send. This is a callback from uip_poll(). uip_poll() may be called: + * + * 1. When the preceding TX packet send is complete, + * 2. When the preceding TX packet send timesout and the interface is reset + * 3. During normal TX polling + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * + ****************************************************************************/ + +static int cs89x0_uiptxpoll(struct uip_driver_s *dev) +{ + struct cs89x0_driver_s *cs89x0 = (struct cs89x0_driver_s *)dev->d_private; + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (cs89x0->cs_dev.d_len > 0) + { + uip_arp_out(&cs89x0->cs_dev); + cs89x0_transmit(cs89x0); + + /* Check if there is room in the CS89x0 to hold another packet. If not, + * return a non-zero value to terminate the poll. + */ +#warning "Missing logic" + } + + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + + return 0; +} + +/**************************************************************************** + * Function: cs89x0_receive + * + * Description: + * An interrupt was received indicating the availability of a new RX packet + * + * Parameters: + * cs89x0 - Reference to the driver state structure + * isq - Interrupt status queue value read by interrupt handler + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void cs89x0_receive(struct cs89x0_driver_s *cs89x0, uint16_t isq) +{ + uint16_t *dest; + uint16_t rxlength; + int nbytes; + + /* Check for errors and update statistics */ + + rxlength = cs89x0_getreg(PPR_RXLENGTH); + if ((isq & RX_OK) == 0) + { +#ifdef CONFIG_C89x0_STATISTICS + cd89x0->cs_stats.rx_errors++; + if ((isq & RX_RUNT) != 0) + { + cd89x0->cs_stats.rx_lengtherrors++; + } + if ((isq & RX_EXTRA_DATA) != 0) + { + cd89x0->cs_stats.rx_lengtherrors++; + } + if (isq & RX_CRC_ERROR) != 0) + { + if (!(isq & (RX_EXTRA_DATA|RX_RUNT))) + { + cd89x0->cs_stats.rx_crcerrors++; + } + } + if ((isq & RX_DRIBBLE) != 0) + { + cd89x0->cs_stats.rx_frameerrors++; + } +#endif + return; + } + + /* Check if the packet is a valid size for the uIP buffer configuration */ + + if (rxlength > ???) + { +#ifdef CONFIG_C89x0_STATISTICS + cd89x0->cs_stats.rx_errors++; + cd89x0->cs_stats.rx_lengtherrors++; +#endif + return; + } + + /* Copy the data data from the hardware to cs89x0->cs_dev.d_buf. Set + * amount of data in cs89x0->cs_dev.d_len + */ + + dest = (uint16_t*)cs89x0->cs_dev.d_buf; + for (nbytes = 0; nbytes < rxlength; nbytes += sizeof(uint16_t)) + { + *dest++ = cs89x0_getreg(PPR_RXFRAMELOCATION); + } + +#ifdef CONFIG_C89x0_STATISTICS + cd89x0->cs_stats.rx_packets++; +#endif + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv6 + if (BUF->type == HTONS(UIP_ETHTYPE_IP6)) +#else + if (BUF->type == HTONS(UIP_ETHTYPE_IP)) +#endif + { + uip_arp_ipin(&cs89x0->cs_dev); + uip_input(&cs89x0->cs_dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (cs89x0->cs_dev.d_len > 0) + { + uip_arp_out(&cs89x0->cs_dev); + cs89x0_transmit(cs89x0); + } + } + else if (BUF->type == htons(UIP_ETHTYPE_ARP)) + { + uip_arp_arpin(&cs89x0->cs_dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (cs89x0->cs_dev.d_len > 0) + { + cs89x0_transmit(cs89x0); + } + } +} + +/**************************************************************************** + * Function: cs89x0_txdone + * + * Description: + * An interrupt was received indicating that the last TX packet(s) is done + * + * Parameters: + * cs89x0 - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void cs89x0_txdone(struct cs89x0_driver_s *cs89x0, uint16_t isq) +{ + /* Check for errors and update statistics. The lower 6-bits of the ISQ + * hold the register address causing the interrupt. We got here because + * those bits indicated */ + +#ifdef CONFIG_C89x0_STATISTICS + cd89x0->cs_stats.tx_packets++; + if ((isq & ISQ_TXEVENT_TXOK) == 0) + { + cd89x0->cs_stats.tx_errors++; + } + if ((isq & ISQ_TXEVENT_LOSSOFCRS) != 0) + { + cd89x0->cs_stats.tx_carriererrors++; + } + if ((isq & ISQ_TXEVENT_SQEERROR) != 0) + { + cd89x0->cs_stats.tx_heartbeaterrors++; + } + if (i(sq & ISQ_TXEVENT_OUTWINDOW) != 0) + { + cd89x0->cs_stats.tx_windowerrors++; + } + if (isq & TX_16_COL) + { + cd89x0->cs_stats.tx_abortederrors++; + } +#endif + + /* If no further xmits are pending, then cancel the TX timeout */ + + wd_cancel(cs89x0->cs_txtimeout); + + /* Then poll uIP for new XMIT data */ + + (void)uip_poll(&cs89x0->cs_dev, cs89x0_uiptxpoll); +} + +/**************************************************************************** + * Function: cs89x0_mapirq + * + * Description: + * Map an IRQ number to a CS89x0 device state instance. This is only + * necessary to handler the case where the architecture includes more than + * on CS89x0 chip. + * + * Parameters: + * irq - Number of the IRQ that generated the interrupt + * + * Returned Value: + * A reference to device state structure (NULL if irq does not correspond + * to any CS89x0 device). + * + * Assumptions: + * + ****************************************************************************/ + +#if CONFIG_CS89x0_NINTERFACES > 1 +static inline FAR struct cs89x0_driver_s *cs89x0_mapirq(int irq) +{ + int i; + for (i = 0; i < CONFIG_CS89x0_NINTERFACES; i++) + { + if (g_cs89x0[i] && g_cs89x0[i].irq == irq) + { + return g_cs89x0[i]; + } + } + return NULL; +} +#endif + +/**************************************************************************** + * Function: cs89x0_interrupt + * + * Description: + * Hardware interrupt handler + * + * Parameters: + * irq - Number of the IRQ that generated the interrupt + * context - Interrupt register state save info (architecture-specific) + * + * Returned Value: + * OK on success + * + * Assumptions: + * + ****************************************************************************/ + +static int cs89x0_interrupt(int irq, FAR void *context) +{ + register struct cs89x0_driver_s *cs89x0 = s89x0_mapirq(irq); + uint16_t isq; + +#ifdef CONFIG_DEBUG + if (!cs89x0) + { + return -ENODEV; + } +#endif + + /* Read and process all of the events from the ISQ */ + + while ((isq = cs89x0_getreg(dev, CS89x0_ISQ_OFFSET)) != 0) + { + nvdbg("ISQ: %04x\n", isq); + switch (isq & ISQ_EVENTMASK) + { + case ISQ_RXEVENT: + cs89x0_receive(cs89x0); + break; + + case ISQ_TXEVENT: + cs89x0_txdone(cs89x0, isq); + break; + + case ISQ_BUFEVENT: + if ((isq & ISQ_BUFEVENT_TXUNDERRUN) != 0) + { + ndbg("Transmit underrun\n"); +#ifdef CONFIG_CS89x0_XMITEARLY + cd89x0->cs_txunderrun++; + if (cd89x0->cs_txunderrun == 3) + { + cd89x0->cs_txstart = PPR_TXCMD_TXSTART381; + } + else if (cd89x0->cs_txunderrun == 6) + { + cd89x0->cs_txstart = PPR_TXCMD_TXSTARTFULL; + } +#endif + } + break; + + case ISQ_RXMISSEVENT: +#ifdef CONFIG_C89x0_STATISTICS + cd89x0->cs_stats.rx_missederrors += (isq >>6); +#endif + break; + + case ISQ_TXCOLEVENT: +#ifdef CONFIG_C89x0_STATISTICS + cd89x0->cs_stats.collisions += (isq >>6); +#endif + break; + } + } + return OK; +} + +/**************************************************************************** + * Function: cs89x0_txtimeout + * + * Description: + * Our TX watchdog timed out. Called from the timer interrupt handler. + * The last TX never completed. Reset the hardware and start again. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void cs89x0_txtimeout(int argc, uint32_t arg, ...) +{ + struct cs89x0_driver_s *cs89x0 = (struct cs89x0_driver_s *)arg; + + /* Increment statistics and dump debug info */ +#warning "Missing logic" + + /* Then reset the hardware */ +#warning "Missing logic" + + /* Then poll uIP for new XMIT data */ + + (void)uip_poll(&cs89x0->cs_dev, cs89x0_uiptxpoll); +} + +/**************************************************************************** + * Function: cs89x0_polltimer + * + * Description: + * Periodic timer handler. Called from the timer interrupt handler. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void cs89x0_polltimer(int argc, uint32_t arg, ...) +{ + struct cs89x0_driver_s *cs89x0 = (struct cs89x0_driver_s *)arg; + + /* Check if there is room in the send another TXr packet. */ +#warning "Missing logic" + + /* If so, update TCP timing states and poll uIP for new XMIT data */ + + (void)uip_timer(&cs89x0->cs_dev, cs89x0_uiptxpoll, CS89x0_POLLHSEC); + + /* Setup the watchdog poll timer again */ + + (void)wd_start(cs89x0->cs_txpoll, CS89x0_WDDELAY, cs89x0_polltimer, 1, arg); +} + +/**************************************************************************** + * Function: cs89x0_ifup + * + * Description: + * NuttX Callback: Bring up the Ethernet interface when an IP address is + * provided + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int cs89x0_ifup(struct uip_driver_s *dev) +{ + struct cs89x0_driver_s *cs89x0 = (struct cs89x0_driver_s *)dev->d_private; + + ndbg("Bringing up: %d.%d.%d.%d\n", + dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, + (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 ); + + /* Initialize the Ethernet interface */ +#warning "Missing logic" + + /* Set and activate a timer process */ + + (void)wd_start(cs89x0->cs_txpoll, CS89x0_WDDELAY, cs89x0_polltimer, 1, (uint32_t)cs89x0); + + /* Enable the Ethernet interrupt */ + + cs89x0->cs_bifup = true; + up_enable_irq(CONFIG_CS89x0_IRQ); + return OK; +} + +/**************************************************************************** + * Function: cs89x0_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int cs89x0_ifdown(struct uip_driver_s *dev) +{ + struct cs89x0_driver_s *cs89x0 = (struct cs89x0_driver_s *)dev->d_private; + irqstate_t flags; + + /* Disable the Ethernet interrupt */ + + flags = irqsave(); + up_disable_irq(CONFIG_CS89x0_IRQ); + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(cs89x0->cs_txpoll); + wd_cancel(cs89x0->cs_txtimeout); + + /* Reset the device */ + + cs89x0->cs_bifup = false; + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Function: cs89x0_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int cs89x0_txavail(struct uip_driver_s *dev) +{ + struct cs89x0_driver_s *cs89x0 = (struct cs89x0_driver_s *)dev->d_private; + irqstate_t flags; + + flags = irqsave(); + + /* Ignore the notification if the interface is not yet up */ + + if (cs89x0->cs_bifup) + { + /* Check if there is room in the hardware to hold another outgoing packet. */ +#warning "Missing logic" + + /* If so, then poll uIP for new XMIT data */ + + (void)uip_poll(&cs89x0->cs_dev, cs89x0_uiptxpoll); + } + + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Function: cs89x0_addmac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int cs89x0_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct cs89x0_driver_s *priv = (FAR struct cs89x0_driver_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + +#warning "Multicast MAC support not implemented" + return OK; +} +#endif + +/**************************************************************************** + * Function: cs89x0_rmmac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int cs89x0_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct cs89x0_driver_s *priv = (FAR struct cs89x0_driver_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + +#warning "Multicast MAC support not implemented" + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: cs89x0_initialize + * + * Description: + * Initialize the Ethernet driver + * + * Parameters: + * impl - decribes the implementation of the cs89x00 implementation. + * This reference is retained so so must remain stable throughout the + * life of the driver instance. + * devno - Identifies the device number. This must be a number between + * zero CONFIG_CS89x0_NINTERFACES and the same devno must not be + * initialized twice. The associated network device will be referred + * to with the name "eth" followed by this number (eth0, eth1, etc). + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +/* Initialize the CS89x0 chip and driver */ + +int cs89x0_initialize(FAR const cs89x0_driver_s *cs89x0, int devno) +{ + /* Sanity checks -- only performed with debug enabled */ + +#ifdef CONFIG_DEBUG + if (!cs89x0 || (unsigned)devno > CONFIG_CS89x0_NINTERFACES || g_cs89x00[devno]) + { + return -EINVAL; + } +#endif + + /* Check if a Ethernet chip is recognized at its I/O base */ + +#warning "Missing logic" + + /* Attach the IRQ to the driver */ + + if (irq_attach(cs89x0->irq, cs89x0_interrupt)) + { + /* We could not attach the ISR to the ISR */ + + return -EAGAIN; + } + + /* Initialize the driver structure */ + + g_cs89x[devno] = cs89x0; /* Used to map IRQ back to instance */ + cs89x0->cs_dev.d_ifup = cs89x0_ifup; /* I/F down callback */ + cs89x0->cs_dev.d_ifdown = cs89x0_ifdown; /* I/F up (new IP address) callback */ + cs89x0->cs_dev.d_txavail = cs89x0_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_IGMP + cs89x0->cs_dev.d_addmac = cs89x0_addmac; /* Add multicast MAC address */ + cs89x0->cs_dev.d_rmmac = cs89x0_rmmac; /* Remove multicast MAC address */ +#endif + cs89x0->cs_dev.d_private = (void*)cs89x0; /* Used to recover private state from dev */ + + /* Create a watchdog for timing polling for and timing of transmisstions */ + + cs89x0->cs_txpoll = wd_create(); /* Create periodic poll timer */ + cs89x0->cs_txtimeout = wd_create(); /* Create TX timeout timer */ + + /* Read the MAC address from the hardware into cs89x0->cs_dev.d_mac.ether_addr_octet */ + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + (void)netdev_register(&cs89x0->cs_dev); + return OK; +} + +#endif /* CONFIG_NET && CONFIG_NET_CS89x0 */ + diff --git a/nuttx/drivers/net/cs89x0.h b/nuttx/drivers/net/cs89x0.h new file mode 100644 index 0000000000..c2073eb988 --- /dev/null +++ b/nuttx/drivers/net/cs89x0.h @@ -0,0 +1,326 @@ +/**************************************************************************** + * drivers/net/cs89x0.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_NET_CS89x0_H +#define __DRIVERS_NET_CS89x0_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* CONFIG_CS89x0_ALIGN16/32 determines if the 16-bit CS89x0 registers are + * aligned to 16-bit or 32-bit address boundaries. NOTE: If there multiple + * CS89x00 parts in the board architecture, we assume that the address + * alignment is the same for all implementations. If that is not the + * case, then it will be necessary to move a shift value into + * the cs89x0_driver_s structure and calculate the offsets dynamically in + * the putreg and getreg functions. + */ + +#if defined(CONFIG_CS89x0_ALIGN16) +# define CS89x0_RTDATA_OFFSET (0 << 1) +# define CS89x0_TxCMD_OFFSET (2 << 1) +# define CS89x0_TxLEN_OFFSET (3 << 1) +# define CS89x0_ISQ_OFFSET (4 << 1) +# define CS89x0_PPTR_OFFSET (5 << 1) +# define CS89x0_PDATA_OFFSET (6 << 1) +#elif defined(CONFIG_CS89x0_ALIGN32) +# define CS89x0_RTDATA_OFFSET (0 << 2) +# define CS89x0_TxCMD_OFFSET (2 << 2) +# define CS89x0_TxLEN_OFFSET (3 << 2) +# define CS89x0_ISQ_OFFSET (4 << 2) +# define CS89x0_PPTR_OFFSET (5 << 2) +# define CS89x0_PDATA_OFFSET (6 << 2) +#else +# error "CS89x00 address alignment is not defined" +#endif + +/* ISQ register bit definitions */ + +#define ISQ_EVENTMASK 0x003f /* Bits 0-5 indicate the status register */ +#define ISQ_RXEVENT 0x0004 +#define ISQ_TXEVENT 0x0008 +#define ISQ_BUFEVENT 0x000c +#define ISQ_RXMISSEVENT 0x0010 +#define ISQ_TXCOLEVENT 0x0012 + +/* ISQ register TxEVENT bit definitions*/ + +#define ISQ_RXEVENT_IAHASH (1 << 6) +#define ISQ_RXEVENT_DRIBBLE (1 << 7) +#define ISQ_RXEVENT_RXOK (1 << 8) +#define ISQ_RXEVENT_HASHED (1 << 9) +#define ISQ_RXEVENT_HASHNDX_SHIFT 10 +#define ISQ_RXEVENT_HASHNDX_MASK (0x3f << ISQ_RXEVENT_HASHNDX_SHIFT) + +/* ISQ register TxEVENT bit definitions*/ + +#define ISQ_TXEVENT_LOSSOFCRS (1 << 6) +#define ISQ_TXEVENT_SQEERROR (1 << 7) +#define ISQ_TXEVENT_TXOK (1 << 8) +#define ISQ_TXEVENT_OUTWINDOW (1 << 9) +#define ISQ_TXEVENT_JABBER (1 << 10) +#define ISQ_TXEVENT_NCOLLISION_SHIFT 11 +#define ISQ_TXEVENT_NCOLLISION_MASK (15 << ISQ_TXEVENT_NCOLLISION_SHIFT) +#define ISQ_TXEVENT_16COLL (1 << 15) + +/* ISQ register BufEVENT bit definitions */ + +#define ISQ_BUFEVENT_SWINT (1 << 6) +#define ISQ_BUFEVENT_RXDMAFRAME (1 << 7) +#define ISQ_BUFEVENT_RDY4TX (1 << 8) +#define ISQ_BUFEVENT_TXUNDERRUN (1 << 9) +#define ISQ_BUFEVENT_RXMISS (1 << 10) +#define ISQ_BUFEVENT_RX128 (1 << 11) +#define ISQ_BUFEVENT_RXDEST (1 << 15) + +/* Packet page register offsets *********************************************/ + +/* 0x0000 Bus interface registers */ + +#define PPR_CHIPID 0x0000 /* Chip identifier - must be 0x630E */ +#define PPR_CHIPREV 0x0002 /* Chip revision, model codes */ +#define PPR_IOBASEADDRESS 0x0020 /* I/O Base Address */ +#define PPR_INTREG 0x0022 /* Interrupt configuration */ +# define PPR_INTREG_IRQ0 0x0000 /* Use INTR0 pin */ +# define PPR_INTREG_IRQ1 0x0001 /* Use INTR1 pin */ +# define PPR_INTREG_IRQ2 0x0002 /* Use INTR2 pin */ +# define PPR_INTREG_IRQ3 0x0003 /* Use INTR3 pin */ + +#define PPR_DMACHANNELNUMBER 0x0024 /* DMA Channel Number (0,1, or 2) */ +#define PPR_DMASTARTOFFRAME 0x0026 /* DMA Start of Frame */ +#define PPR_DMAFRAMECOUNT 0x0028 /* DMA Frame Count (12-bits) */ +#define PPR_RXDMABYTECOUNT 0x002a /* Rx DMA Byte Count */ +#define PPR_MEMORYBASEADDRESS 0x002c /* Memory Base Address Register (20-bit) */ +#define PPR_BOOTPROMBASEADDRESS 0x0030 /* Boot PROM Base Address */ +#define PPR_BOOTPROMADDRESSMASK 0x0034 /* Boot PROM Address Mask */ +#define PPR_EEPROMCOMMAND 0x0040 /* EEPROM Command */ +#define PPR_EEPROMDATA 0x0042 /* EEPROM Data */ +#define PPR_RECVFRAMEBYTES 0x0050 /* Received Frame Byte Counter */ + +/* 0x0100 - Configuration and control registers */ + +#define PPR_RXCFG 0x0102 /* Receiver configuration */ +# define PPR_RXCFG_SKIP1 (1 << 6) /* Skip (discard) current frame */ +# define PPR_RXCFG_STREAM (1 << 7) /* Enable streaming mode */ +# define PPR_RXCFG_RXOK (1 << 8) /* RxOK interrupt enable */ +# define PPR_RxCFG_RxDMAonly (1 << 9) /* Use RxDMA for all frames */ +# define PPR_RxCFG_AutoRxDMA (1 << 10) /* Select RxDMA automatically */ +# define PPR_RxCFG_BufferCRC (1 << 11) /* Include CRC characters in frame */ +# define PPR_RxCFG_CRC (1 << 12) /* Enable interrupt on CRC error */ +# define PPR_RxCFG_RUNT (1 << 13) /* Enable interrupt on RUNT frames */ +# define PPR_RxCFG_EXTRA (1 << 14) /* Enable interrupt on frames with extra data */ + +#define PPR_RXCTL 0x0104 /* Receiver control */ +# define PPR_RXCTL_IAHASH (1 << 6) /* Accept frames that match hash */ +# define PPR_RXCTL_PROMISCUOUS (1 << 7) /* Accept any frame */ +# define PPR_RXCTL_RXOK (1 << 8) /* Accept well formed frames */ +# define PPR_RXCTL_MULTICAST (1 << 9) /* Accept multicast frames */ +# define PPR_RXCTL_IA (1 << 10) /* Accept frame that matches IA */ +# define PPR_RXCTL_BROADCAST (1 << 11) /* Accept broadcast frames */ +# define PPR_RXCTL_CRC (1 << 12) /* Accept frames with bad CRC */ +# define PPR_RXCTL_RUNT (1 << 13) /* Accept runt frames */ +# define PPR_RXCTL_EXTRA (1 << 14) /* Accept frames that are too long */ + +#define PPR_TXCFG 0x0106 /* Transmit configuration */ +# define PPR_TXCFG_CRS (1 << 6) /* Enable interrupt on loss of carrier */ +# define PPR_TXCFG_SQE (1 << 7) /* Enable interrupt on Signal Quality Error */ +# define PPR_TXCFG_TXOK (1 << 8) /* Enable interrupt on successful xmits */ +# define PPR_TXCFG_LATE (1 << 9) /* Enable interrupt on "out of window" */ +# define PPR_TXCFG_JABBER (1 << 10) /* Enable interrupt on jabber detect */ +# define PPR_TXCFG_COLLISION (1 << 11) /* Enable interrupt if collision */ +# define PPR_TXCFG_16COLLISIONS (1 << 15) /* Enable interrupt if > 16 collisions */ + +#define PPR_TXCMD 0x0108 /* Transmit command status */ +# define PPR_TXCMD_TXSTART5 (0 << 6) /* Start after 5 bytes in buffer */ +# define PPR_TXCMD_TXSTART381 (1 << 6) /* Start after 381 bytes in buffer */ +# define PPR_TXCMD_TXSTART1021 (2 << 6) /* Start after 1021 bytes in buffer */ +# define PPR_TXCMD_TXSTARTFULL (3 << 6) /* Start after all bytes loaded */ +# define PPR_TXCMD_FORCE (1 << 8) /* Discard any pending packets */ +# define PPR_TXCMD_ONECOLLISION (1 << 9) /* Abort after a single collision */ +# define PPR_TXCMD_NOCRC (1 << 12) /* Do not add CRC */ +# define PPR_TXCMD_NOPAD (1 << 13) /* Do not pad short packets */ + +#define PPR_BUFCFG 0x010a /* Buffer configuration */ +# define PPR_BUFCFG_SWI (1 << 6) /* Force interrupt via software */ +# define PPR_BUFCFG_RXDMA (1 << 7) /* Enable interrupt on Rx DMA */ +# define PPR_BUFCFG_TXRDY (1 << 8) /* Enable interrupt when ready for Tx */ +# define PPR_BUFCFG_TXUE (1 << 9) /* Enable interrupt in Tx underrun */ +# define PPR_BUFCFG_RXMISS (1 << 10) /* Enable interrupt on missed Rx packets */ +# define PPR_BUFCFG_RX128 (1 << 11) /* Enable Rx interrupt after 128 bytes */ +# define PPR_BUFCFG_TXCOL (1 << 12) /* Enable int on Tx collision ctr overflow */ +# define PPR_BUFCFG_MISS (1 << 13) /* Enable int on Rx miss ctr overflow */ +# define PPR_BUFCFG_RXDEST (1 << 15) /* Enable int on Rx dest addr match */ + +#define PPR_LINECTL 0x0112 /* Line control */ +# define PPR_LINECTL_RX (1 << 6) /* Enable receiver */ +# define PPR_LINECTL_TX (1 << 7) /* Enable transmitter */ +# define PPR_LINECTL_AUIONLY (1 << 8) /* AUI interface only */ +# define PPR_LINECTL_AUTOAUI10BT (1 << 9) /* Autodetect AUI or 10BaseT interface */ +# define PPR_LINECTL_MODBACKOFFE (1 << 11) /* Enable modified backoff algorithm */ +# define PPR_LINECTL_POLARITYDIS (1 << 12) /* Disable Rx polarity autodetect */ +# define PPR_LINECTL_2PARTDEFDIS (1 << 13) /* Disable two-part defferal */ +# define PPR_LINECTL_LORXSQUELCH (1 << 14) /* Reduce receiver squelch threshold */ + +#define PPR_SELFCTL 0x0114 /* Chip self control */ +# define PPR_SELFCTL_RESET (1 << 6) /* Self-clearing reset */ +# define PPR_SELFCTL_SWSUSPEND (1 << 8) /* Initiate suspend mode */ +# define PPR_SELFCTL_HWSLEEPE (1 << 9) /* Enable SLEEP input */ +# define PPR_SELFCTL_HWSTANDBYE (1 << 10) /* Enable standby mode */ +# define PPR_SELFCTL_HC0E (1 << 12) /* Use HCB0 for LINK LED */ +# define PPR_SELFCTL_HC1E (1 << 13) /* Use HCB1 for BSTATUS LED */ +# define PPR_SELFCTL_HCB0 (1 << 14) /* Control LINK LED if HC0E set */ +# define PPR_SELFCTL_HCB1 (1 << 15) /* Cntrol BSTATUS LED if HC1E set */ + +#define PPR_BUSCTL 0x0116 /* Bus control */ +# define PPR_BUSCTL_RESETRXDMA (1 << 6) /* Reset RxDMA pointer */ +# define PPR_BUSCTL_DMAEXTEND (1 << 8) /* Extend DMA cycle */ +# define PPR_BUSCTL_USESA (1 << 9) /* Assert MEMCS16 on address decode */ +# define PPR_BUSCTL_MEMORYE (1 << 10) /* Enable memory mode */ +# define PPR_BUSCTL_DMABURST (1 << 11) /* Limit DMA access burst */ +# define PPR_BUSCTL_IOCHRDYE (1 << 12) /* Set IOCHRDY high impedence */ +# define PPR_BUSCTL_RXDMASIZE (1 << 13) /* Set DMA buffer size 64KB */ +# define PPR_BUSCTL_ENABLEIRQ (1 << 15) /* Generate interrupt on interrupt event */ + +#define PPR_TESTCTL 0x0118 /* Test control */ +# define PPR_TESTCTL_DISABLELT (1 << 7) /* Disable link status */ +# define PPR_TESTCTL_ENDECLOOP (1 << 9) /* Internal loopback */ +# define PPR_TESTCTL_AUILOOP (1 << 10) /* AUI loopback */ +# define PPR_TESTCTL_DISBACKOFF (1 << 11) /* Disable backoff algorithm */ +# define PPR_TESTCTL_FDX (1 << 14) /* Enable full duplex mode */ + +/* 0x0120 - Status and Event Registers */ + +#define PPR_ISQ 0x0120 /* Interrupt Status Queue */ +#define PPR_RER 0x0124 /* Receive event */ +# define PPR_RER_IAHASH (1 << 6) /* Frame hash match */ +# define PPR_RER_DRIBBLE (1 << 7) /* Frame had 1-7 extra bits after last byte */ +# define PPR_RER_RXOK (1 << 8) /* Frame received with no errors */ +# define PPR_RER_HASHED (1 << 9) /* Frame address hashed OK */ +# define PPR_RER_IA (1 << 10) /* Frame address matched IA */ +# define PPR_RER_BROADCAST (1 << 11) /* Broadcast frame */ +# define PPR_RER_CRC (1 << 12) /* Frame had CRC error */ +# define PPR_RER_RUNT (1 << 13) /* Runt frame */ +# define PPR_RER_EXTRA (1 << 14) /* Frame was too long */ + +#define PPR_TER 0x0128 /* Transmit event */ +# define PPR_TER_CRS (1 << 6) /* Carrier lost */ +# define PPR_TER_SQE (1 << 7) /* Signal Quality Error */ +# define PPR_TER_TXOK (1 << 8) /* Packet sent without error */ +# define PPR_TER_LATE (1 << 9) /* Out of window */ +# define PPR_TER_JABBER (1 << 10) /* Stuck transmit? */ +# define PPR_TER_NUMCOLLISIONS_SHIFT 11 +# define PPR_TER_NUMCOLLISIONS_MASK (15 << PPR_TER_NUMCOLLISIONS_SHIFT) +# define PPR_TER_16COLLISIONS (1 << 15) /* > 16 collisions */ + +#define PPR_BER 0x012C /* Buffer event */ +# define PPR_BER_SWINT (1 << 6) /* Software interrupt */ +# define PPR_BER_RXDMAFRAME (1 << 7) /* Received framed DMAed */ +# define PPR_BER_RDY4TX (1 << 8) /* Ready for transmission */ +# define PPR_BER_TXUNDERRUN (1 << 9) /* Transmit underrun */ +# define PPR_BER_RXMISS (1 << 10) /* Received frame missed */ +# define PPR_BER_RX128 (1 << 11) /* 128 bytes received */ +# define PPR_BER_RXDEST (1 << 15) /* Received framed passed address filter */ + +#define PPR_RXMISS 0x0130 /* Receiver miss counter */ +#define PPR_TXCOL 0x0132 /* Transmit collision counter */ +#define PPR_LINESTAT 0x0134 /* Line status */ +# define PPR_LINESTAT_LINKOK (1 << 7) /* Line is connected and working */ +# define PPR_LINESTAT_AUI (1 << 8) /* Connected via AUI */ +# define PPR_LINESTAT_10BT (1 << 9) /* Connected via twisted pair */ +# define PPR_LINESTAT_POLARITY (1 << 12) /* Line polarity OK (10BT only) */ +# define PPR_LINESTAT_CRS (1 << 14) /* Frame being received */ + +#define PPR_SELFSTAT 0x0136 /* Chip self status */ +# define PPR_SELFSTAT_33VACTIVE (1 << 6) /* supply voltage is 3.3V */ +# define PPR_SELFSTAT_INITD (1 << 7) /* Chip initialization complete */ +# define PPR_SELFSTAT_SIBSY (1 << 8) /* EEPROM is busy */ +# define PPR_SELFSTAT_EEPROM (1 << 9) /* EEPROM present */ +# define PPR_SELFSTAT_EEPROMOK (1 << 10) /* EEPROM checks out */ +# define PPR_SELFSTAT_ELPRESENT (1 << 11) /* External address latch logic available */ +# define PPR_SELFSTAT_EESIZE (1 << 12) /* Size of EEPROM */ + +#define PPR_BUSSTAT 0x0138 /* Bus status */ +# define PPR_BUSSTAT_TXBID (1 << 7) /* Tx error */ +# define PPR_BUSSTAT_TXRDY (1 << 8) /* Ready for Tx data */ + +#define PPR_TDR 0x013C /* AUI Time Domain Reflectometer */ + +/* 0x0144 - Initiate transmit registers */ + +#define PPR_TXCOMMAND 0x0144 /* Tx Command */ +#define PPR_TXLENGTH 0x0146 /* Tx Length */ + +/* 0x0150 - Address filter registers */ + +#define PPR_LAF 0x0150 /* Logical address filter (6 bytes) */ +#define PPR_IA 0x0158 /* Individual address (MAC) */ + +/* 0x0400 - Frame location registers */ + +#define PPR_RXSTATUS 0x0400 /* Rx Status */ +#define PPR_RXLENGTH 0x0402 /* Rx Length */ +#define PPR_RXFRAMELOCATION 0x0404 /* Rx Frame Location */ +#define PPR_TXFRAMELOCATION 0x0a00 /* Tx Frame Location */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __DRIVERS_NET_CS89x0_H */ diff --git a/nuttx/drivers/net/dm90x0.c b/nuttx/drivers/net/dm90x0.c new file mode 100644 index 0000000000..15433e0f80 --- /dev/null +++ b/nuttx/drivers/net/dm90x0.c @@ -0,0 +1,1815 @@ +/**************************************************************************** + * drivers/net/dm9x.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Davicom data sheets (DM9000-DS-F03-041906.pdf, + * DM9010-DS-F01-103006.pdf) and looking at lots of other DM90x0 + * drivers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_DM90x0) + +/* Only one hardware interface supported at present (although there are + * hooks throughout the design to that extending the support to multiple + * interfaces should not be that difficult) + */ + +#undef CONFIG_DM9X_NINTERFACES +#define CONFIG_DM9X_NINTERFACES 1 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* DM90000 and DM9010 register offets */ + +#define DM9X_NETC 0x00 /* Network control register */ +#define DM9X_NETS 0x01 /* Network Status register */ +#define DM9X_TXC 0x02 /* TX control register */ +#define DM9X_TXS1 0x03 /* TX status register 1 */ +#define DM9X_TXS2 0x03 /* TX status register 2 */ +#define DM9X_RXC 0x05 /* RX control register */ +#define DM9X_RXS 0x06 /* RX status register */ +#define DM9X_RXOVF 0x07 /* Receive overflow counter register */ +#define DM9X_BPTHRES 0x08 /* Back pressure threshold register */ +#define DM9X_FCTHRES 0x09 /* Flow control threshold register */ +#define DM9X_FC 0x0a /* RX/TX flow control register */ +#define DM9X_EEPHYC 0x0b /* EEPROM & PHY control register */ +#define DM9X_EEPHYA 0x0c /* EEPROM & PHY address register */ +#define DM9X_EEPHYDL 0x0d /* EEPROM & PHY data register (lo) */ +#define DM9X_EEPHYDH 0x0e /* EEPROM & PHY data register (hi) */ +#define DM9X_WAKEUP 0x0f /* Wake-up control register */ +#define DM9X_PAB0 0x10 /* Physical address register (byte 0) */ +#define DM9X_PAB1 0x11 /* Physical address register (byte 1) */ +#define DM9X_PAB2 0x12 /* Physical address register (byte 2) */ +#define DM9X_PAB3 0x13 /* Physical address register (byte 3) */ +#define DM9X_PAB4 0x14 /* Physical address register (byte 4) */ +#define DM9X_PAB5 0x15 /* Physical address register (byte 5) */ +#define DM9X_MAB0 0x16 /* Multicast address register (byte 0) */ +#define DM9X_MAB1 0x17 /* Multicast address register (byte 1) */ +#define DM9X_MAB2 0x18 /* Multicast address register (byte 2) */ +#define DM9X_MAB3 0x19 /* Multicast address register (byte 3) */ +#define DM9X_MAB4 0x1a /* Multicast address register (byte 4) */ +#define DM9X_MAB5 0x1b /* Multicast address register (byte 5) */ +#define DM9X_MAB6 0x1c /* Multicast address register (byte 6) */ +#define DM9X_MAB7 0x1d /* Multicast address register (byte 7) */ +#define DM9X_GPC 0x1e /* General purpose control register */ +#define DM9X_GPD 0x1f /* General purpose register */ + +#define DM9X_TRPAL 0x22 /* TX read pointer address (lo) */ +#define DM9X_TRPAH 0x23 /* TX read pointer address (hi) */ +#define DM9X_RWPAL 0x24 /* RX write pointer address (lo) */ +#define DM9X_RWPAH 0x25 /* RX write pointer address (hi) */ + +#define DM9X_VIDL 0x28 /* Vendor ID (lo) */ +#define DM9X_VIDH 0x29 /* Vendor ID (hi) */ +#define DM9X_PIDL 0x2a /* Product ID (lo) */ +#define DM9X_PIDH 0x2b /* Product ID (hi) */ +#define DM9X_CHIPR 0x2c /* Product ID (lo) */ +#define DM9X_TXC2 0x2d /* Transmit control register 2 (dm9010) */ +#define DM9X_OTC 0x2e /* Operation test control register (dm9010) */ +#define DM9X_SMODEC 0x2f /* Special mode control register */ +#define DM9X_ETXCSR 0x30 /* Early transmit control/status register (dm9010) */ +#define DM9X_TCCR 0x31 /* Transmit checksum control register (dm9010) */ +#define DM9X_RCSR 0x32 /* Receive checksum control/status register (dm9010) */ +#define DM9X_EPHYA 0x33 /* External PHY address register (dm9010) */ +#define DM9X_GPC2 0x34 /* General purpose control register 2 (dm9010) */ +#define DM9X_GPD2 0x35 /* General purpose register 2 */ +#define DM9X_GPC3 0x36 /* General purpose control register 3 (dm9010) */ +#define DM9X_GPD3 0x37 /* General purpose register 3 */ +#define DM9X_PBUSC 0x38 /* Processor bus control register (dm9010) */ +#define DM9X_IPINC 0x39 /* INT pin control register (dm9010) */ + +#define DM9X_MON1 0x40 /* Monitor register 1 (dm9010) */ +#define DM9X_MON2 0x41 /* Monitor register 2 (dm9010) */ + +#define DM9X_SCLKC 0x50 /* System clock turn ON control register (dm9010) */ +#define DM9X_SCLKR 0x51 /* Resume system clock control register (dm9010) */ + +#define DM9X_MRCMDX 0xf0 /* Memory data pre-fetch read command without address increment */ +#define DM9X_MRCMDX1 0xf1 /* memory data read command without address increment (dm9010) */ +#define DM9X_MRCMD 0xf2 /* Memory data read command with address increment */ +#define DM9X_MDRAL 0xf4 /* Memory data read address register (lo) */ +#define DM9X_MDRAH 0xf5 /* Memory data read address register (hi) */ +#define DM9X_MWCMDX 0xf6 /* Memory data write command without address increment */ +#define DM9X_MWCMD 0xf8 /* Memory data write command with address increment */ +#define DM9X_MDWAL 0xfa /* Memory data write address register (lo) */ +#define DM9X_MDWAH 0xfb /* Memory data write address register (lo) */ +#define DM9X_TXPLL 0xfc /* Memory data write address register (lo) */ +#define DM9X_TXPLH 0xfd /* Memory data write address register (hi) */ +#define DM9X_ISR 0xfe /* Interrupt status register */ +#define DM9X_IMR 0xff /* Interrupt mask register */ + +/* Network control register bit definitions */ + +#define DM9X_NETC_RST (1 << 0) /* Software reset */ +#define DM9X_NETC_LBKM (3 << 1) /* Loopback mode mask */ +#define DM9X_NETC_LBK0 (0 << 1) /* 0: Normal */ +#define DM9X_NETC_LBK1 (1 << 1) /* 1: MAC internal loopback */ +#define DM9X_NETC_LBK2 (2 << 1) /* 2: Internal PHY 100M mode loopback */ +#define DM9X_NETC_FDX (1 << 3) /* Full dupliex mode */ +#define DM9X_NETC_FCOL (1 << 4) /* Force collision mode */ +#define DM9X_NETC_WAKEEN (1 << 6) /* Wakeup event enable */ +#define DM9X_NETC_EXTPHY (1 << 7) /* Select external PHY */ + +/* Network status bit definitions */ + +#define DM9X_NETS_RXOV (1 << 1) /* RX Fifo overflow */ +#define DM9X_NETS_TX1END (1 << 2) /* TX packet 1 complete status */ +#define DM9X_NETS_TX2END (1 << 3) /* TX packet 2 complete status */ +#define DM9X_NETS_WAKEST (1 << 5) /* Wakeup event status */ +#define DM9X_NETS_LINKST (1 << 6) /* Link status */ +#define DM9X_NETS_SPEED (1 << 7) /* Media speed */ + +/* IMR/ISR bit definitions */ + +#define DM9X_INT_PR (1 << 0) /* Packet received interrupt */ +#define DM9X_INT_PT (1 << 1) /* Packet transmitted interrupt */ +#define DM9X_INT_RO (1 << 2) /* Receive overflow interrupt */ +#define DM9X_INT_ROO (1 << 3) /* Receive overflow counter overflow int */ +#define DM9X_INT_UDRUN (1 << 4) /* Transmit underrun interrupt */ +#define DM9X_INT_LNKCHG (1 << 5) /* Link status change interrupt */ +#define DM9X_INT_ALL (0x3f) + +#define DM9X_IMR_UNUSED (1 << 6) /* (not used) */ +#define DM9X_IMR_PAR (1 << 7) /* Enable auto R/W pointer reset */ + +#define DM9X_ISR_IOMODEM (3 << 6) /* IO mode mask */ +#define DM9X_ISR_IOMODE8 (2 << 6) /* IO mode = 8 bit */ +#define DM9X_ISR_IOMODE16 (0 << 6) /* IO mode = 16 bit */ +#define DM9X_ISR_IOMODE32 (1 << 6) /* IO mode = 32 bit */ + +#define DM9X_IMRENABLE (DM9X_INT_PR|DM9X_INT_PT|DM9X_INT_LNKCHG|DM9X_IMR_PAR) +#define DM9X_IMRRXDISABLE (DM9X_INT_PT|DM9X_INT_LNKCHG|DM9X_IMR_PAR) +#define DM9X_IMRDISABLE (DM9X_IMR_PAR) + +/* EEPROM/PHY control regiser bits */ + +#define DM9X_EEPHYC_ERRE (1 << 0) /* EEPROM (vs PHY) access status */ +#define DM9X_EEPHYC_ERPRW (1 << 1) /* EEPROM/PHY write access */ +#define DM9X_EEPHYC_ERPRR (1 << 2) /* EEPROM/PHY read access */ +#define DM9X_EEPHYC_EPOS (1 << 3) /* EEPROM/PHY operation select */ +#define DM9X_EEPHYC_WEP (1 << 4) /* Write EEPROM enable */ +#define DM9X_EEPHYC_REEP (1 << 5) /* Reload EEPROM */ + +/* Supported values from the vendor and product ID register */ + +#define DM9X_DAVICOMVID 0x0a46 +#define DM9X_DM9000PID 0x9000 +#define DM9X_DM9010PID 0x9010 + +/* RX control register bit settings */ + +#define DM9X_RXC_RXEN (1 << 0) /* RX enable */ +#define DM9X_RXC_PRMSC (1 << 1) /* Promiscuous mode */ +#define DM9X_RXC_RUNT (1 << 2) /* Pass runt packet */ +#define DM9X_RXC_ALL (1 << 3) /* Pass all multicast */ +#define DM9X_RXC_DISCRC (1 << 4) /* Discard CRC error packets */ +#define DM9X_RXC_DISLONG (1 << 5) /* Discard long packets */ +#define DM9X_RXC_WTDIS (1 << 6) /* Disable watchdog timer */ +#define DM9X_RXC_HASHALL (1 << 7) /* Filter all addresses in hash table */ + +#define DM9X_RXCSETUP (DM9X_RXC_DISCRC|DM9X_RXC_DISLONG) + +/* EEPHY bit settings */ + +#define DM9X_EEPHYA_EROA 0x40 /* PHY register address 0x01 */ + +#define DM9X_PKTRDY 0x01 /* Packet ready to receive */ + +/* The RX interrupt will be disabled if more than the following RX + * interrupts are received back-to-back. + */ + +#define DM9X_CRXTHRES 10 + +/* All access is via an index register and a data regist. Select accecss + * according to user supplied base address and bus width. + */ + +#if defined(CONFIG_DM9X_BUSWIDTH8) +# define DM9X_INDEX *(volatile uint8_t*)(CONFIG_DM9X_BASE) +# define DM9X_DATA *(volatile uint8_t*)(CONFIG_DM9X_BASE + 2) +#elif defined(CONFIG_DM9X_BUSWIDTH16) +# define DM9X_INDEX *(volatile uint16_t*)(CONFIG_DM9X_BASE) +# define DM9X_DATA *(volatile uint16_t*)(CONFIG_DM9X_BASE + 2) +#elif defined(CONFIG_DM9X_BUSWIDTH32) +# define DM9X_INDEX *(volatile uint32_t*)(CONFIG_DM9X_BASE) +# define DM9X_DATA *(volatile uint32_t*)(CONFIG_DM9X_BASE + 2) +#endif + +/* Phy operating mode. Default is AUTO, but this setting can be overridden + * in the NuttX configuration file. + */ + +#define DM9X_MODE_AUTO 0 +#define DM9X_MODE_10MHD 1 +#define DM9X_MODE_100MHD 2 +#define DM9X_MODE_10MFD 3 +#define DM9X_MODE_100MFD 4 + +#ifndef CONFIG_DM9X_MODE +# define CONFIG_DM9X_MODE DM9X_MODE_AUTO +#endif + +/* TX poll deley = 1 seconds. CLK_TCK is the number of clock ticks per second */ + +#define DM6X_WDDELAY (1*CLK_TCK) +#define DM6X_POLLHSEC (1*2) + +/* TX timeout = 1 minute */ + +#define DM6X_TXTIMEOUT (60*CLK_TCK) + +/* This is a helper pointer for accessing the contents of the Ethernet header */ + +#define BUF ((struct uip_eth_hdr *)dm9x->dm_dev.d_buf) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +union rx_desc_u +{ + uint8_t rx_buf[4]; + struct + { + uint8_t rx_byte; + uint8_t rx_status; + uint16_t rx_len; + } desc; +}; + +/* The dm9x_driver_s encapsulates all DM90x0 state information for a single + * DM90x0 hardware interface + */ + +struct dm9x_driver_s +{ + bool dm_bifup; /* true:ifup false:ifdown */ + bool dm_b100M; /* true:speed == 100M; false:speed == 10M */ + WDOG_ID dm_txpoll; /* TX poll timer */ + WDOG_ID dm_txtimeout; /* TX timeout timer */ + uint8_t dm_ntxpending; /* Count of packets pending transmission */ + uint8_t ncrxpackets; /* Number of continuous rx packets */ + + /* Mode-dependent function to move data in 8/16/32 I/O modes */ + + void (*dm_read)(uint8_t *ptr, int len); + void (*dm_write)(const uint8_t *ptr, int len); + void (*dm_discard)(int len); + +#if defined(CONFIG_DM9X_STATS) + uint32_t dm_ntxpackets; /* Count of packets sent */ + uint32_t dm_ntxbytes; /* Count of bytes sent */ + uint32_t dm_ntxerrors; /* Count of TX errors */ + uint32_t dm_nrxpackets; /* Count of packets received */ + uint32_t dm_nrxbytes; /* Count of bytes received */ + uint32_t dm_nrxfifoerrors; /* Count of RX FIFO overflow errors */ + uint32_t dm_nrxcrcerrors; /* Count of RX CRC errors */ + uint32_t dm_nrxlengtherrors; /* Count of RX length errors */ + uint32_t dm_nphyserrors; /* Count of physical layer errors */ + uint32_t dm_nresets; /* Counts number of resets */ + uint32_t dm_ntxtimeouts; /* Counts resets caused by TX timeouts */ +#endif + + /* This holds the information visible to uIP/NuttX */ + + struct uip_driver_s dm_dev; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* At present, only a single DM90x0 device is supported. */ + +static struct dm9x_driver_s g_dm9x[CONFIG_DM9X_NINTERFACES]; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Utility functions */ + +static uint8_t getreg(int reg); +static void putreg(int reg, uint8_t value); +static void read8(uint8_t *ptr, int len); +static void read16(uint8_t *ptr, int len); +static void read32(uint8_t *ptr, int len); +static void discard8(int len); +static void discard16(int len); +static void discard32(int len); +static void write8(const uint8_t *ptr, int len); +static void write16(const uint8_t *ptr, int len); +static void write32(const uint8_t *ptr, int len); + +/* static uint16_t dm9x_readsrom(struct dm9x_driver_s *dm9x, int offset); */ +static uint16_t dm9x_phyread(struct dm9x_driver_s *dm9x, int reg); +static void dm9x_phywrite(struct dm9x_driver_s *dm9x, int reg, uint16_t value); + +#if defined(CONFIG_DM9X_STATS) +static void dm9x_resetstatistics(struct dm9x_driver_s *dm9x); +#else +# define dm9x_resetstatistics(dm9x) +#endif + +#if defined(CONFIG_DM9X_STATS) && defined(CONFIG_DEBUG) +static void dm9x_dumpstatistics(struct dm9x_driver_s *dm9x); +#else +# define dm9x_dumpstatistics(dm9x) +#endif + +#if defined(CONFIG_DM9X_CHECKSUM) +static bool dm9x_rxchecksumready(uint8_t); +#else +# define dm9x_rxchecksumready(a) ((a) == 0x01) +#endif + +/* Common TX logic */ + +static int dm9x_transmit(struct dm9x_driver_s *dm9x); +static int dm9x_uiptxpoll(struct uip_driver_s *dev); + +/* Interrupt handling */ + +static void dm9x_receive(struct dm9x_driver_s *dm9x); +static void dm9x_txdone(struct dm9x_driver_s *dm9x); +static int dm9x_interrupt(int irq, FAR void *context); + +/* Watchdog timer expirations */ + +static void dm9x_polltimer(int argc, uint32_t arg, ...); +static void dm9x_txtimeout(int argc, uint32_t arg, ...); + +/* NuttX callback functions */ + +static int dm9x_ifup(struct uip_driver_s *dev); +static int dm9x_ifdown(struct uip_driver_s *dev); +static int dm9x_txavail(struct uip_driver_s *dev); +#ifdef CONFIG_NET_IGMP +static int dm9x_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +static int dm9x_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +#endif + +/* Initialization functions */ + +static void dm9x_bringup(struct dm9x_driver_s *dm9x); +static void dm9x_reset(struct dm9x_driver_s *dm9x); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: getreg and setreg + * + * Description: + * Access to memory-mapped DM90x0 8-bit registers + * + * Parameters: + * reg - Register number + * value - Value to write to the register (setreg only) + * + * Returned Value: + * Value read from the register (getreg only) + * + * Assumptions: + * + ****************************************************************************/ + +static uint8_t getreg(int reg) +{ + DM9X_INDEX = reg; + return DM9X_DATA & 0xff; +} + +static void putreg(int reg, uint8_t value) +{ + DM9X_INDEX = reg; + DM9X_DATA = value & 0xff; +} + +/**************************************************************************** + * Function: read8, read16, read32 + * + * Description: + * Read packet data from the DM90x0 SRAM based on its current I/O mode + * + * Parameters: + * ptr - Location to write the packet data + * len - The number of bytes to read + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void read8(uint8_t *ptr, int len) +{ + nvdbg("Read %d bytes (8-bit mode)\n", len); + for (; len > 0; len--) + { + *ptr++ = DM9X_DATA; + } +} + +static void read16(uint8_t *ptr, int len) +{ + register uint16_t *ptr16 = (uint16_t*)ptr; + nvdbg("Read %d bytes (16-bit mode)\n", len); + for (; len > 0; len -= sizeof(uint16_t)) + { + *ptr16++ = DM9X_DATA; + } +} + +static void read32(uint8_t *ptr, int len) +{ + register uint32_t *ptr32 = (uint32_t*)ptr; + nvdbg("Read %d bytes (32-bit mode)\n", len); + for (; len > 0; len -= sizeof(uint32_t)) + { + *ptr32++ = DM9X_DATA; + } +} + +/**************************************************************************** + * Function: discard8, discard16, discard32 + * + * Description: + * Read and discard packet data in the DM90x0 SRAM based on its current + * I/O mode + * + * Parameters: + * len - The number of bytes to discard + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void discard8(int len) +{ + nvdbg("Discard %d bytes (8-bit mode)\n", len); + for (; len > 0; len--) + { + DM9X_DATA; + } +} + +static void discard16(int len) +{ + nvdbg("Discard %d bytes (16-bit mode)\n", len); + for (; len > 0; len -= sizeof(uint16_t)) + { + DM9X_DATA; + } +} + +static void discard32(int len) +{ + nvdbg("Discard %d bytes (32-bit mode)\n", len); + for (; len > 0; len -= sizeof(uint32_t)) + { + DM9X_DATA; + } +} + +/**************************************************************************** + * Function: write8, write16, write32 + * + * Description: + * Write packet data into the DM90x0 SRAM based on its current I/O mode + * + * Parameters: + * ptr - Location to write the packet data + * len - The number of bytes to read + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void write8(const uint8_t *ptr, int len) +{ + nvdbg("Write %d bytes (8-bit mode)\n", len); + for (; len > 0; len--) + { + DM9X_DATA = (*ptr++ & 0xff); + } +} + +static void write16(const uint8_t *ptr, int len) +{ + register uint16_t *ptr16 = (uint16_t*)ptr; + nvdbg("Write %d bytes (16-bit mode)\n", len); + + for (; len > 0; len -= sizeof(uint16_t)) + { + DM9X_DATA = *ptr16++; + } +} + +static void write32(const uint8_t *ptr, int len) +{ + register uint32_t *ptr32 = (uint32_t*)ptr; + nvdbg("Write %d bytes (32-bit mode)\n", len); + for (; len > 0; len -= sizeof(uint32_t)) + { + DM9X_DATA = *ptr32++; + } +} + +/**************************************************************************** + * Function: dm9x_readsrom + * + * Description: + * Read a word from SROM + * + * Parameters: + * dm9x - Reference to the driver state structure + * offset - SROM offset to read from + * + * Returned Value: + * SROM content at that offset + * + * Assumptions: + * + ****************************************************************************/ + +#if 0 /* Not used */ +static uint16_t dm9x_readsrom(struct dm9x_driver_s *dm9x, int offset) +{ + putreg(DM9X_EEPHYA, offset); + putreg(DM9X_EEPHYC, DM9X_EEPHYC_ERPRR); + up_udelay(200); + putreg(DM9X_EEPHYC, 0x00); + return (getreg(DM9X_EEPHYDL) + (getreg(DM9X_EEPHYDH) << 8) ); +} +#endif + +/**************************************************************************** + * Function: dm9x_phyread and dm9x_phywrite + * + * Description: + * Read/write data from/to the PHY + * + * Parameters: + * dm9x - Reference to the driver state structure + * reg - PHY register offset + * value - The value to write to the PHY register (dm9x_write only) + * + * Returned Value: + * The value read from the PHY (dm9x_read only) + * + * Assumptions: + * + ****************************************************************************/ + +static uint16_t dm9x_phyread(struct dm9x_driver_s *dm9x, int reg) +{ + /* Setup DM9X_EEPHYA, the EEPROM/PHY address register */ + + putreg(DM9X_EEPHYA, DM9X_EEPHYA_EROA | reg); + + /* Issue PHY read command pulse in the EEPROM/PHY control register */ + + putreg(DM9X_EEPHYC, (DM9X_EEPHYC_ERPRR|DM9X_EEPHYC_EPOS)); + up_udelay(100); + putreg(DM9X_EEPHYC, 0x00); + + /* Return the data from the EEPROM/PHY data register pair */ + + return (((uint16_t)getreg(DM9X_EEPHYDH)) << 8) | (uint16_t)getreg(DM9X_EEPHYDL); +} + +static void dm9x_phywrite(struct dm9x_driver_s *dm9x, int reg, uint16_t value) +{ + /* Setup DM9X_EEPHYA, the EEPROM/PHY address register */ + + putreg(DM9X_EEPHYA, DM9X_EEPHYA_EROA | reg); + + /* Put the data to write in the EEPROM/PHY data register pair */ + + putreg(DM9X_EEPHYDL, (value & 0xff)); + putreg(DM9X_EEPHYDH, ((value >> 8) & 0xff)); + + /* Issue PHY write command pulse in the EEPROM/PHY control register */ + + putreg(DM9X_EEPHYC, (DM9X_EEPHYC_ERPRW|DM9X_EEPHYC_EPOS)); + up_udelay(500); + putreg(DM9X_EEPHYC, 0x0); +} + +/**************************************************************************** + * Function: dm9x_resetstatistics + * + * Description: + * Reset all DM90x0 statistics + * + * Parameters: + * dm9x - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_DM9X_STATS) +static void dm9x_resetstatistics(struct dm9x_driver_s *dm9x) +{ + dm9x->dm_ntxpackets = 0; /* Count of packets sent */ + dm9x->dm_ntxbytes = 0; /* Count of bytes sent */ + dm9x->dm_ntxerrors = 0; /* Count of TX errors */ + dm9x->dm_nrxpackets = 0; /* Count of packets received */ + dm9x->dm_nrxbytes = 0; /* Count of bytes received */ + dm9x->dm_nrxfifoerrors = 0; /* Count of RX FIFO overflow errors */ + dm9x->dm_nrxcrcerrors = 0; /* Count of RX CRC errors */ + dm9x->dm_nrxlengtherrors = 0; /* Count of RX length errors */ + dm9x->dm_nphyserrors = 0; /* Count of physical layer errors */ + dm9x->dm_nresets = 0; /* Counts number of resets */ + dm9x->dm_ntxtimeouts = 0; /* Counts resets caused by TX timeouts */ +} +#endif + +/**************************************************************************** + * Function: dm9x_dumpstatistics + * + * Description: + * Print the current value of all DM90x0 statistics + * + * Parameters: + * dm9x - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_DM9X_STATS) && defined(CONFIG_DEBUG) +static void dm9x_dumpstatistics(struct dm9x_driver_s *dm9x) +{ + ndbg("TX packets: %d\n", dm9x->dm_ntxpackets); + ndbg(" bytes: %d\n", dm9x->dm_ntxbytes); + ndbg(" errors: %d\n", dm9x->dm_ntxerrors); + ndbg("RX packets: %d\n", dm9x->dm_nrxpackets); + ndbg(" bytes: %d\n", dm9x->dm_nrxbytes); + ndbg(" FIFO overflows: %d\n", dm9x->dm_nrxfifoerrors); + ndbg(" CRC errors: %d\n", dm9x->dm_nrxcrcerrors); + ndbg(" length errors: %d\n", dm9x->dm_nrxlengtherrors); + ndbg("Physical layer errors: %d\n", dm9x->dm_nphyserrors); + ndbg("Resets: %d\n", dm9x->dm_nresets); + ndbg("TX timeout resets: %d\n", dm9x->dm_ntxtimeouts); +} +#endif + +/**************************************************************************** + * Function: dm9x_rxchecksumready + * + * Description: + * Return true if the RX checksum is available + * + * Parameters: + * rxbyte + * + * Returned Value: + * true: checksum is ready + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_DM9X_CHECKSUM) +static inline bool dm9x_rxchecksumready(uint8_t rxbyte) +{ + if ((rxbyte & 0x01) == 0) + { + return false; + } + + return ((rxbyte >> 4) | 0x01) != 0; +} +#endif + +/**************************************************************************** + * Function: dm9x_transmit + * + * Description: + * Start hardware transmission. Called either from the txdone interrupt + * handling or from watchdog based polling. + * + * Parameters: + * dm9x - Reference to the driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * + ****************************************************************************/ + +static int dm9x_transmit(struct dm9x_driver_s *dm9x) +{ + /* Check if there is room in the DM90x0 to hold another packet. In 100M mode, + * that can be 2 packets, otherwise it is a single packet. + */ + + if (dm9x->dm_ntxpending < 1 || (dm9x->dm_b100M && dm9x->dm_ntxpending < 2)) + { + /* Increment count of packets transmitted */ + + dm9x->dm_ntxpending++; +#if defined(CONFIG_DM9X_STATS) + dm9x->dm_ntxpackets++; + dm9x->dm_ntxbytes += dm9x->dm_dev.d_len; +#endif + + /* Disable all DM90x0 interrupts */ + + putreg(DM9X_IMR, DM9X_IMRDISABLE); + + /* Set the TX length */ + + putreg(DM9X_TXPLL, (dm9x->dm_dev.d_len & 0xff)); + putreg(DM9X_TXPLH, (dm9x->dm_dev.d_len >> 8) & 0xff); + + /* Move the data to be sent into TX SRAM */ + + DM9X_INDEX = DM9X_MWCMD; + dm9x->dm_write(dm9x->dm_dev.d_buf, dm9x->dm_dev.d_len); + +#if !defined(CONFIG_DM9X_ETRANS) + /* Issue TX polling command */ + + putreg(DM9X_TXC, 0x1); /* Cleared after TX complete*/ +#endif + + /* Clear count of back-to-back RX packet transfers */ + + dm9x->ncrxpackets = 0; + + /* Re-enable DM90x0 interrupts */ + + putreg(DM9X_IMR, DM9X_IMRENABLE); + + /* Setup the TX timeout watchdog (perhaps restarting the timer) */ + + (void)wd_start(dm9x->dm_txtimeout, DM6X_TXTIMEOUT, dm9x_txtimeout, 1, (uint32_t)dm9x); + return OK; + } + return -EBUSY; +} + +/**************************************************************************** + * Function: dm9x_uiptxpoll + * + * Description: + * The transmitter is available, check if uIP has any outgoing packets ready + * to send. This is a callback from uip_poll(). uip_poll() may be called: + * + * 1. When the preceding TX packet send is complete, + * 2. When the preceding TX packet send timesout and the DM90x0 is reset + * 3. During normal TX polling + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * + ****************************************************************************/ + +static int dm9x_uiptxpoll(struct uip_driver_s *dev) +{ + struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)dev->d_private; + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (dm9x->dm_dev.d_len > 0) + { + uip_arp_out(&dm9x->dm_dev); + dm9x_transmit(dm9x); + + /* Check if there is room in the DM90x0 to hold another packet. In 100M mode, + * that can be 2 packets, otherwise it is a single packet. + */ + + if (dm9x->dm_ntxpending > 1 || !dm9x->dm_b100M) + { + /* Returning a non-zero value will terminate the poll operation */ + + return 1; + } + } + + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + + return 0; +} + +/**************************************************************************** + * Function: dm9x_receive + * + * Description: + * An interrupt was received indicating the availability of a new RX packet + * + * Parameters: + * dm9x - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void dm9x_receive(struct dm9x_driver_s *dm9x) +{ + union rx_desc_u rx; + bool bchecksumready; + uint8_t mdrah; + uint8_t mdral; + uint8_t rxbyte; + + nvdbg("Packet received\n"); + + do + { + /* Store the value of memory data read address register */ + + mdrah = getreg(DM9X_MDRAH); + mdral = getreg(DM9X_MDRAL); + + getreg(DM9X_MRCMDX); /* Dummy read */ + rxbyte = (uint8_t)DM9X_DATA; /* Get the most up-to-date data */ + + /* Packet ready for receive check */ + + bchecksumready = dm9x_rxchecksumready(rxbyte); + if (!bchecksumready) + { + break; + } + + /* A packet is ready now. Get status/length */ + + DM9X_INDEX = DM9X_MRCMD; /* set read ptr ++ */ + + /* Read packet status & length */ + + dm9x->dm_read((uint8_t*)&rx, 4); + + /* Check if any errors were reported by the hardware */ + + if (rx.desc.rx_status & 0xbf) + { + /* Bad RX packet... update statistics */ + +#if defined(CONFIG_DM9X_STATS) + if (rx.desc.rx_status & 0x01) + { + dm9x->dm_nrxfifoerrors++; + ndbg("RX FIFO error: %d\n", dm9x->dm_nrxfifoerrors); + } + + if (rx.desc.rx_status & 0x02) + { + dm9x->dm_nrxcrcerrors++; + ndbg("RX CRC error: %d\n", dm9x->dm_nrxcrcerrors); + } + + if (rx.desc.rx_status & 0x80) + { + dm9x->dm_nrxlengtherrors++; + ndbg("RX length error: %d\n", dm9x->dm_nrxlengtherrors); + } + + if (rx.desc.rx_status & 0x08) + { + dm9x->dm_nphyserrors++; + ndbg("Physical Layer error: %d\n", dm9x->dm_nphyserrors); + } +#else + ndbg("Received packet with errors: %02x\n", rx.desc.rx_status); +#endif + /* Drop this packet and continue to check the next packet */ + + dm9x->dm_discard(rx.desc.rx_len); + } + + /* Also check if the packet is a valid size for the uIP configuration */ + + else if (rx.desc.rx_len < UIP_LLH_LEN || rx.desc.rx_len > (CONFIG_NET_BUFSIZE + 2)) + { +#if defined(CONFIG_DM9X_STATS) + dm9x->dm_nrxlengtherrors++; + ndbg("RX length error: %d\n", dm9x->dm_nrxlengtherrors); +#endif + /* Drop this packet and continue to check the next packet */ + + dm9x->dm_discard(rx.desc.rx_len); + } + else + { + /* Good packet... Copy the packet data out of SRAM and pass it one to uIP */ + + dm9x->dm_dev.d_len = rx.desc.rx_len; + dm9x->dm_read(dm9x->dm_dev.d_buf, rx.desc.rx_len); + + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv6 + if (BUF->type == HTONS(UIP_ETHTYPE_IP6)) +#else + if (BUF->type == HTONS(UIP_ETHTYPE_IP)) +#endif + { + uip_arp_ipin(&dm9x->dm_dev); + uip_input(&dm9x->dm_dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (dm9x->dm_dev.d_len > 0) + { + uip_arp_out(&dm9x->dm_dev); + dm9x_transmit(dm9x); + } + } + else if (BUF->type == htons(UIP_ETHTYPE_ARP)) + { + uip_arp_arpin(&dm9x->dm_dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (dm9x->dm_dev.d_len > 0) + { + dm9x_transmit(dm9x); + } + } + } + +#if defined(CONFIG_DM9X_STATS) + dm9x->dm_nrxpackets++; + dm9x->dm_nrxbytes += rx.desc.rx_len; +#endif + dm9x->ncrxpackets++; + } + while ((rxbyte & 0x01) == DM9X_PKTRDY && dm9x->ncrxpackets < DM9X_CRXTHRES); + nvdbg("All RX packets processed\n"); +} + +/**************************************************************************** + * Function: dm9x_txdone + * + * Description: + * An interrupt was received indicating that the last TX packet(s) is done + * + * Parameters: + * dm9x - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void dm9x_txdone(struct dm9x_driver_s *dm9x) +{ + int nsr; + + nvdbg("TX done\n"); + + /* Another packet has completed transmission. Decrement the count of + * of pending TX transmissions. + */ + + nsr = getreg(DM9X_NETS); + if (nsr & DM9X_NETS_TX1END) + { + if (dm9x->dm_ntxpending) + { + dm9x->dm_ntxpending--; + } + else + { + ndbg("Bad TX count (TX1END)\n"); + } + } + + if (nsr & DM9X_NETS_TX2END) + { + if (dm9x->dm_ntxpending) + { + dm9x->dm_ntxpending--; + } + else + { + ndbg("Bad TX count (TX2END)\n"); + } + } + + /* Cancel the TX timeout */ + + if (dm9x->dm_ntxpending == 0) + { + wd_cancel(dm9x->dm_txtimeout); + } + + /* Then poll uIP for new XMIT data */ + + (void)uip_poll(&dm9x->dm_dev, dm9x_uiptxpoll); +} + +/**************************************************************************** + * Function: dm9x_interrupt + * + * Description: + * DM90x0 interrupt handler + * + * Parameters: + * irq - Number of the IRQ that generated the interrupt + * context - Interrupt register state save info (architecture-specific) + * + * Returned Value: + * OK on success + * + * Assumptions: + * + ****************************************************************************/ + +static int dm9x_interrupt(int irq, FAR void *context) +{ +#if CONFIG_DM9X_NINTERFACES == 1 + register struct dm9x_driver_s *dm9x = &g_dm9x[0]; +#else +# error "Additional logic needed to support multiple interfaces" +#endif + uint8_t isr; + uint8_t save; + int i; + + /* Save previous register address */ + + save = (uint8_t)DM9X_INDEX; + + /* Disable all DM90x0 interrupts */ + + putreg(DM9X_IMR, DM9X_IMRDISABLE); + + /* Get and clear the DM90x0 interrupt status bits */ + + isr = getreg(DM9X_ISR); + putreg(DM9X_ISR, isr); + nvdbg("Interrupt status: %02x\n", isr); + + /* Check for link status change */ + + if (isr & DM9X_INT_LNKCHG) + { + /* Wait up to 0.5s for link OK */ + + for (i = 0; i < 500; i++) + { + dm9x_phyread(dm9x,0x1); + if (dm9x_phyread(dm9x,0x1) & 0x4) /*Link OK*/ + { + /* Wait to get detected speed */ + + for (i = 0; i < 200; i++) + { + up_mdelay(1); + } + + /* Set the new network speed */ + + if (dm9x_phyread(dm9x, 0) & 0x2000) + { + dm9x->dm_b100M = true; + } + else + { + dm9x->dm_b100M = false; + } + break; + } + up_mdelay(1); + } + ndbg("delay: %dmS speed: %s\n", i, dm9x->dm_b100M ? "100M" : "10M"); + } + + /* Check if we received an incoming packet */ + + if (isr & DM9X_INT_PR) + { + dm9x_receive(dm9x); + } + + /* Check if we are able to transmit a packet */ + + if (isr & DM9X_INT_PT) + { + dm9x_txdone(dm9x); + } + + /* If the number of consecutive receive packets exceeds a threshold, + * then disable the RX interrupt. + */ + + if (dm9x->ncrxpackets >= DM9X_CRXTHRES) + { + /* Eanble all DM90x0 interrupts EXCEPT for RX */ + + putreg(DM9X_IMR, DM9X_IMRRXDISABLE); + } + else + { + /* Enable all DM90x0 interrupts */ + + putreg(DM9X_IMR, DM9X_IMRENABLE); + } + + /* Restore previous register address */ + + DM9X_INDEX = save; + return OK; +} + +/**************************************************************************** + * Function: dm9x_txtimeout + * + * Description: + * Our TX watchdog timed out. Called from the timer interrupt handler. + * The last TX never completed. Reset the DM90x0 and start again. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void dm9x_txtimeout(int argc, uint32_t arg, ...) +{ + struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)arg; + + ndbg("TX timeout\n"); + + /* Increment statistics and dump debug info */ + +#if defined(CONFIG_DM9X_STATS) + dm9x->dm_ntxtimeouts++; + dm9x->dm_ntxerrors++; +#endif + + ndbg(" TX packet count: %d\n", dm9x->dm_ntxpending); +#if defined(CONFIG_DM9X_STATS) + ndbg(" TX timeouts: %d\n", dm9x->dm_ntxtimeouts); +#endif + ndbg(" TX read pointer address: 0x%02x:%02x\n", + getreg(DM9X_TRPAH), getreg(DM9X_TRPAL)); + ndbg(" Memory data write address: 0x%02x:%02x (DM9010)\n", + getreg(DM9X_MDWAH), getreg(DM9X_MDWAL)); + + /* Then reset the DM90x0 */ + + dm9x_reset(dm9x); + + /* Then poll uIP for new XMIT data */ + + (void)uip_poll(&dm9x->dm_dev, dm9x_uiptxpoll); +} + +/**************************************************************************** + * Function: dm9x_polltimer + * + * Description: + * Periodic timer handler. Called from the timer interrupt handler. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void dm9x_polltimer(int argc, uint32_t arg, ...) +{ + struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)arg; + + /* If the number of contiguous RX packets exceeds a threshold, reset the counter and + * re-enable RX interrupts + */ + + if (dm9x->ncrxpackets >= DM9X_CRXTHRES) + { + dm9x->ncrxpackets = 0; + putreg(DM9X_IMR, DM9X_IMRENABLE); + } + + /* Check if there is room in the DM90x0 to hold another packet. In 100M mode, + * that can be 2 packets, otherwise it is a single packet. + */ + + if (dm9x->dm_ntxpending < 1 || (dm9x->dm_b100M && dm9x->dm_ntxpending < 2)) + { + /* If so, update TCP timing states and poll uIP for new XMIT data */ + + (void)uip_timer(&dm9x->dm_dev, dm9x_uiptxpoll, DM6X_POLLHSEC); + } + + /* Setup the watchdog poll timer again */ + + (void)wd_start(dm9x->dm_txpoll, DM6X_WDDELAY, dm9x_polltimer, 1, arg); +} + +/**************************************************************************** + * Function: dm9x_phymode + * + * Description: + * Configure the PHY operating mode + * + * Parameters: + * dm9x - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static inline void dm9x_phymode(struct dm9x_driver_s *dm9x) +{ + uint16_t phyreg0; + uint16_t phyreg4; + +#if CONFIG_DM9X_MODE == DM9X_MODE_AUTO + phyreg0 = 0x1200; /* Auto-negotiation & Restart Auto-negotiation */ + phyreg4 = 0x01e1; /* Default flow control disable*/ +#elif CONFIG_DM9X_MODE == DM9X_MODE_10MHD + phyreg4 = 0x21; + phyreg0 = 0x1000; +#elif CONFIG_DM9X_MODE == DM9X_MODE_10MFD + phyreg4 = 0x41; + phyreg0 = 0x1100; +#elif CONFIG_DM9X_MODE == DM9X_MODE_100MHD + phyreg4 = 0x81; + phyreg0 = 0x3000; +#elif CONFIG_DM9X_MODE == DM9X_MODE_100MFD + phyreg4 = 0x101; + phyreg0 = 0x3100; +#else +# error "Recognized PHY mode" +#endif + + dm9x_phywrite(dm9x, 0, phyreg0); + dm9x_phywrite(dm9x, 4, phyreg4); +} + +/**************************************************************************** + * Function: dm9x_ifup + * + * Description: + * NuttX Callback: Bring up the DM90x0 interface when an IP address is + * provided + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int dm9x_ifup(struct uip_driver_s *dev) +{ + struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)dev->d_private; + uint8_t netstatus; + int i; + + ndbg("Bringing up: %d.%d.%d.%d\n", + dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, + (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 ); + + /* Initilize DM90x0 chip */ + + dm9x_bringup(dm9x); + + /* Check link state and media speed (waiting up to 3s for link OK) */ + + dm9x->dm_b100M = false; + for (i = 0; i < 3000; i++) + { + netstatus = getreg(DM9X_NETS); + if (netstatus & DM9X_NETS_LINKST) + { + /* Link OK... Wait a bit before getting the detected speed */ + + up_mdelay(200); + netstatus = getreg(DM9X_NETS); + if ((netstatus & DM9X_NETS_SPEED) == 0) + { + dm9x->dm_b100M = true; + } + break; + } + i++; + up_mdelay(1); + } + + ndbg("delay: %dmS speed: %s\n", i, dm9x->dm_b100M ? "100M" : "10M"); + + /* Set and activate a timer process */ + + (void)wd_start(dm9x->dm_txpoll, DM6X_WDDELAY, dm9x_polltimer, 1, (uint32_t)dm9x); + + /* Enable the DM9X interrupt */ + + dm9x->dm_bifup = true; + up_enable_irq(CONFIG_DM9X_IRQ); + return OK; +} + +/**************************************************************************** + * Function: dm9x_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int dm9x_ifdown(struct uip_driver_s *dev) +{ + struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)dev->d_private; + irqstate_t flags; + + ndbg("Stopping\n"); + + /* Disable the DM9X interrupt */ + + flags = irqsave(); + up_disable_irq(CONFIG_DM9X_IRQ); + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(dm9x->dm_txpoll); + wd_cancel(dm9x->dm_txtimeout); + + /* Reset the device */ + + dm9x_phywrite(dm9x, 0x00, 0x8000); /* PHY reset */ + putreg(DM9X_GPD, 0x01); /* Power-down PHY (GEPIO0=1) */ + putreg(DM9X_IMR, DM9X_IMRDISABLE); /* Disable all interrupts */ + putreg(DM9X_RXC, 0x00); /* Disable RX */ + putreg(DM9X_ISR, DM9X_INT_ALL); /* Clear interrupt status */ + + dm9x->dm_bifup = false; + irqrestore(flags); + + /* Dump statistics */ + + dm9x_dumpstatistics(dm9x); + return OK; +} + +/**************************************************************************** + * Function: dm9x_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int dm9x_txavail(struct uip_driver_s *dev) +{ + struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)dev->d_private; + irqstate_t flags; + + ndbg("Polling\n"); + flags = irqsave(); + + /* Ignore the notification if the interface is not yet up */ + + if (dm9x->dm_bifup) + { + + /* Check if there is room in the DM90x0 to hold another packet. In 100M + * mode, that can be 2 packets, otherwise it is a single packet. + */ + + if (dm9x->dm_ntxpending < 1 || (dm9x->dm_b100M && dm9x->dm_ntxpending < 2)) + { + /* If so, then poll uIP for new XMIT data */ + + (void)uip_poll(&dm9x->dm_dev, dm9x_uiptxpoll); + } + } + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Function: dm9x_addmac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int dm9x_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct dm9x_driver_s *priv = (FAR struct dm9x_driver_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + +#warning "Multicast MAC support not implemented" + return OK; +} +#endif + +/**************************************************************************** + * Function: dm9x_rmmac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int dm9x_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct dm9x_driver_s *priv = (FAR struct dm9x_driver_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + +#warning "Multicast MAC support not implemented" + return OK; +} +#endif + +/**************************************************************************** + * Function: dm9x_bringup + * + * Description: + * Initialize the dm90x0 chip + * + * Parameters: + * dm9x - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void dm9x_bringup(struct dm9x_driver_s *dm9x) +{ + ndbg("Initializing\n"); + + /* Set the internal PHY power-on, GPIOs normal, and wait 2ms */ + + putreg(DM9X_GPD, 0x01); /* Power-down the PHY (GEPIO0=1) */ + up_udelay(500); + putreg(DM9X_GPD, 0x00); /* Preactivate PHY (GPIO0=0 */ + up_udelay(20); /* Wait 20us for PHY power-on ready */ + + /* Do a software reset and wait 20us (twice). The reset autoclears + * in 10us; 20us guarantees completion of the reset + */ + + putreg(DM9X_NETC, (DM9X_NETC_RST|DM9X_NETC_LBK1)); + up_udelay(20); + putreg(DM9X_NETC, (DM9X_NETC_RST|DM9X_NETC_LBK1)); + up_udelay(20); + + /* Configure I/O mode */ + + switch (getreg(DM9X_ISR) & DM9X_ISR_IOMODEM) + { + case DM9X_ISR_IOMODE8: + dm9x->dm_read = read8; + dm9x->dm_write = write8; + dm9x->dm_discard = discard8; + break; + + case DM9X_ISR_IOMODE16: + dm9x->dm_read = read16; + dm9x->dm_write = write16; + dm9x->dm_discard = discard16; + break; + + case DM9X_ISR_IOMODE32: + dm9x->dm_read = read32; + dm9x->dm_write = write32; + dm9x->dm_discard = discard32; + break; + + default: + break; + } + + /* Program PHY operating mode */ + + dm9x_phymode(dm9x); + + /* Program operating mode */ + + putreg(DM9X_NETC, 0x00); /* Network control */ + putreg(DM9X_TXC, 0x00); /* Clear TX Polling */ + putreg(DM9X_BPTHRES, 0x3f); /* Less 3kb, 600us */ + putreg(DM9X_SMODEC, 0x00); /* Special mode */ + putreg(DM9X_NETS, (DM9X_NETS_WAKEST|DM9X_NETS_TX1END|DM9X_NETS_TX2END)); /* Clear TX status */ + putreg(DM9X_ISR, DM9X_INT_ALL); /* Clear interrupt status */ + +#if defined(CONFIG_DM9X_CHECKSUM) + putreg(DM9X_TCCR, 0x07); /* TX UDP/TCP/IP checksum enable */ + putreg(DM9X_RCSR, 0x02); /* Receive checksum enable */ +#endif + +#if defined(CONFIG_DM9X_ETRANS) + putreg(DM9X_ETXCSR, 0x83); +#endif + + /* Initialize statistics */ + + dm9x->ncrxpackets = 0; /* Number of continuous RX packets */ + dm9x->dm_ntxpending = 0; /* Number of pending TX packets */ + dm9x_resetstatistics(dm9x); + + /* Activate DM9000A/DM9010 */ + + putreg(DM9X_RXC, DM9X_RXCSETUP | 1); /* RX enable */ + putreg(DM9X_IMR, DM9X_IMRENABLE); /* Enable TX/RX interrupts */ +} + +/**************************************************************************** + * Function: dm9x_reset + * + * Description: + * Stop, reset, re-initialize, and restart the DM90x0 chip and driver. At + * present, the chip is only reset after a TX timeout. + * + * Parameters: + * dm9x - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void dm9x_reset(struct dm9x_driver_s *dm9x) +{ + uint8_t save; + int i; + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(dm9x->dm_txpoll); + wd_cancel(dm9x->dm_txtimeout); + + /* Save previous register address */ + + save = (uint8_t)DM9X_INDEX; + +#if defined(CONFIG_DM9X_STATS) + dm9x->dm_nresets++; +#endif + dm9x_bringup(dm9x); + + /* Wait up to 1 second for the link to be OK */ + + dm9x->dm_b100M = false; + for (i = 0; i < 1000; i++) + { + if (dm9x_phyread(dm9x,0x1) & 0x4) + { + if (dm9x_phyread(dm9x, 0) &0x2000) + { + dm9x->dm_b100M = true; + } + break; + } + up_mdelay(1); + } + + /* Restore previous register address */ + + DM9X_INDEX = save; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: dm9x_initialize + * + * Description: + * Initialize the DM90x0 driver + * + * Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +/* Initialize the DM90x0 chip and driver */ + +int dm9x_initialize(void) +{ + uint8_t *mptr; + uint16_t vid; + uint16_t pid; + int i; + int j; + + /* Get the chip vendor ID and product ID */ + + vid = (((uint16_t)getreg(DM9X_VIDH)) << 8) | (uint16_t)getreg(DM9X_VIDL); + pid = (((uint16_t)getreg(DM9X_PIDH)) << 8) | (uint16_t)getreg(DM9X_PIDL); + nlldbg("I/O base: %08x VID: %04x PID: %04x\n", CONFIG_DM9X_BASE, vid, pid); + + /* Check if a DM90x0 chip is recognized at this I/O base */ + + if (vid != DM9X_DAVICOMVID || (pid != DM9X_DM9000PID && pid != DM9X_DM9010PID)) + { + nlldbg("DM90x0 vendor/product ID not found at this base address\n"); + return -ENODEV; + } + + /* Attach the IRQ to the driver */ + + if (irq_attach(CONFIG_DM9X_IRQ, dm9x_interrupt)) + { + /* We could not attach the ISR to the ISR */ + + nlldbg("irq_attach() failed\n"); + return -EAGAIN; + } + + /* Initialize the driver structure */ + + memset(g_dm9x, 0, CONFIG_DM9X_NINTERFACES*sizeof(struct dm9x_driver_s)); + g_dm9x[0].dm_dev.d_ifup = dm9x_ifup; /* I/F down callback */ + g_dm9x[0].dm_dev.d_ifdown = dm9x_ifdown; /* I/F up (new IP address) callback */ + g_dm9x[0].dm_dev.d_txavail = dm9x_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_IGMP + g_dm9x[0].dm_dev.d_addmac = dm9x_addmac; /* Add multicast MAC address */ + g_dm9x[0].dm_dev.d_rmmac = dm9x_rmmac; /* Remove multicast MAC address */ +#endif + g_dm9x[0].dm_dev.d_private = (void*)g_dm9x; /* Used to recover private state from dev */ + + /* Create a watchdog for timing polling for and timing of transmisstions */ + + g_dm9x[0].dm_txpoll = wd_create(); /* Create periodic poll timer */ + g_dm9x[0].dm_txtimeout = wd_create(); /* Create TX timeout timer */ + + /* Read the MAC address */ + + mptr = g_dm9x[0].dm_dev.d_mac.ether_addr_octet; + for (i = 0, j = DM9X_PAB0; i < ETHER_ADDR_LEN; i++, j++) + { + mptr[i] = getreg(j); + } + + nlldbg("MAC: %0x:%0x:%0x:%0x:%0x:%0x\n", + mptr[0], mptr[1], mptr[2], mptr[3], mptr[4], mptr[5]); + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + (void)netdev_register(&g_dm9x[0].dm_dev); + return OK; +} + +#endif /* CONFIG_NET && CONFIG_NET_DM90x0 */ + diff --git a/nuttx/drivers/net/e1000.c b/nuttx/drivers/net/e1000.c new file mode 100644 index 0000000000..ec2b29b6ad --- /dev/null +++ b/nuttx/drivers/net/e1000.c @@ -0,0 +1,1049 @@ +/**************************************************************************** + * drivers/net/e1000.c + * + * Copyright (C) 2011 Yu Qiang. All rights reserved. + * Author: Yu Qiang + * + * This file is a part of NuttX: + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include "e1000.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* TX poll deley = 1 seconds. CLK_TCK is the number of clock ticks per second */ + +#define E1000_WDDELAY (1*CLK_TCK) +#define E1000_POLLHSEC (1*2) + +/* TX timeout = 1 minute */ + +#define E1000_TXTIMEOUT (60*CLK_TCK) + +/* This is a helper pointer for accessing the contents of the Ethernet header */ + +#define BUF ((struct uip_eth_hdr *)e1000->uip_dev.d_buf) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct tx_ring { + struct tx_desc *desc; + char *buf; + int tail; // where to write desc +}; + +struct rx_ring { + struct rx_desc *desc; + char *buf; + int head; // where to read + int tail; // where to release free desc + int free; // number of freed desc +}; + +struct e1000_dev { + uint32_t phy_mem_base; + uint32_t io_mem_base; + uint32_t mem_size; + int pci_dev_id; + unsigned char src_mac[6]; + unsigned char dst_mac[6]; + int irq; + struct irq_action int_desc; + struct tx_ring tx_ring; + struct rx_ring rx_ring; + struct e1000_dev *next; + + // NuttX net data + bool bifup; /* true:ifup false:ifdown */ + WDOG_ID txpoll; /* TX poll timer */ + WDOG_ID txtimeout; /* TX timeout timer */ + + /* This holds the information visible to uIP/NuttX */ + + struct uip_driver_s uip_dev; /* Interface understood by uIP */ +}; + +struct e1000_dev_head { + struct e1000_dev *next; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct e1000_dev_head e1000_list = {0}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Common TX logic */ + +static int e1000_transmit(struct e1000_dev *e1000); +static int e1000_uiptxpoll(struct uip_driver_s *dev); + +/* Interrupt handling */ + +static void e1000_receive(struct e1000_dev *e1000); + +/* Watchdog timer expirations */ + +static void e1000_polltimer(int argc, uint32_t arg, ...); +static void e1000_txtimeout(int argc, uint32_t arg, ...); + +/* NuttX callback functions */ + +static int e1000_ifup(struct uip_driver_s *dev); +static int e1000_ifdown(struct uip_driver_s *dev); +static int e1000_txavail(struct uip_driver_s *dev); +#ifdef CONFIG_NET_IGMP +static int e1000_addmac(struct uip_driver_s *dev, const uint8_t *mac); +static int e1000_rmmac(struct uip_driver_s *dev, const uint8_t *mac); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline void e1000_outl(struct e1000_dev *dev, int reg, uint32_t val) +{ + writel(dev->io_mem_base+reg, val); +} + +static inline uint32_t e1000_inl(struct e1000_dev *dev, int reg) +{ + return readl(dev->io_mem_base+reg); +} + +/****************************** e1000 driver ********************************/ + +void e1000_reset(struct e1000_dev *dev) +{ + uint32_t dev_control; + + // Reset the network controller hardware + dev_control = 0; + dev_control |= (1<<0); // FD-bit (Full Duplex) + dev_control |= (0<<2); // GIOMD-bit (GIO Master Disable) + dev_control |= (1<<3); // LRST-bit (Link Reset) + dev_control |= (1<<6); // SLU-bit (Set Link Up) + dev_control |= (2<<8); // SPEED=2 (1000Mbps) + dev_control |= (0<<11); // FRCSPD-bit (Force Speed) + dev_control |= (0<<12); // FRCDPLX-bit (Force Duplex) + dev_control |= (0<<20); // ADVD3WUC-bit (Advertise D3 Wake Up Cap) + dev_control |= (1<<26); // RST-bit (Device Reset) + dev_control |= (1<<27); // RFCE-bit (Receive Flow Control Enable) + dev_control |= (1<<28); // TFCE-bit (Transmit Flow Control Enable) + dev_control |= (0<<30); // VME-bit (VLAN Mode Enable) + dev_control |= (0<<31); // PHY_RST-bit (PHY Reset) + + e1000_outl(dev, E1000_IMC, 0xFFFFFFFF); + e1000_outl(dev, E1000_STATUS, 0x00000000); + e1000_outl(dev, E1000_CTRL, dev_control); + dev_control &= ~(1<<26); // clear RST-bit (Device Reset) + e1000_outl(dev, E1000_CTRL, dev_control); + up_mdelay(10); + e1000_outl(dev, E1000_CTRL_EXT, 0x001401C0); + e1000_outl(dev, E1000_IMC, 0xFFFFFFFF); +} + +void e1000_turn_on(struct e1000_dev *dev) +{ + int tx_control, rx_control; + uint32_t ims = 0; + + // turn on the controller's receive engine + rx_control = e1000_inl(dev, E1000_RCTL); + rx_control |= (1<<1); + e1000_outl(dev, E1000_RCTL, rx_control); + + // turn on the controller's transmit engine + tx_control = e1000_inl(dev, E1000_TCTL); + tx_control |= (1<<1); + e1000_outl(dev, E1000_TCTL, tx_control); + + // enable the controller's interrupts + e1000_outl(dev, E1000_ICR, 0xFFFFFFFF); + e1000_outl(dev, E1000_IMC, 0xFFFFFFFF); + + ims |= 1<<0; // TXDW + ims |= 1<<1; // TXQE + ims |= 1<<2; // LSC + ims |= 1<<4; // RXDMT0 + ims |= 1<<7; // RXT0 + e1000_outl(dev, E1000_IMS, ims); +} + +void e1000_turn_off(struct e1000_dev *dev) +{ + int tx_control, rx_control; + + // turn off the controller's receive engine + rx_control = e1000_inl(dev, E1000_RCTL); + rx_control &= ~(1<<1); + e1000_outl(dev, E1000_RCTL, rx_control); + + // turn off the controller's transmit engine + tx_control = e1000_inl(dev, E1000_TCTL); + tx_control &= ~(1<<1); + e1000_outl(dev, E1000_TCTL, tx_control); + + // turn off the controller's interrupts + e1000_outl(dev, E1000_IMC, 0xFFFFFFFF); +} + +void e1000_init(struct e1000_dev *dev) +{ + uint32_t rxd_phys, txd_phys, kmem_phys; + uint32_t rx_control, tx_control; + uint32_t pba; + int i; + + e1000_reset(dev); + + // configure the controller's 'receive' engine + rx_control = 0; + rx_control |= (0<<1); // EN-bit (Enable) + rx_control |= (0<<2); // SPB-bit (Store Bad Packets) + rx_control |= (0<<3); // UPE-bit (Unicast Promiscuous Mode) + rx_control |= (1<<4); // MPE-bit (Multicast Promiscuous Mode) + rx_control |= (0<<5); // LPE-bit (Long Packet Enable) + rx_control |= (0<<6); // LBM=0 (Loop-Back Mode) + rx_control |= (0<<8); // RDMTS=0 (Rx Descriptor Min Threshold Size) + rx_control |= (0<<10); // DTYPE=0 (Descriptor Type) + rx_control |= (0<<12); // MO=0 (Multicast Offset) + rx_control |= (1<<15); // BAM-bit (Broadcast Address Mode) + rx_control |= (0<<16); // BSIZE=0 (Buffer Size = 2048) + rx_control |= (0<<18); // VLE-bit (VLAN filter Enable) + rx_control |= (0<<19); // CFIEN-bit (Canonical Form Indicator Enable) + rx_control |= (0<<20); // CFI-bit (Canonical Form Indicator) + rx_control |= (1<<22); // DPF-bit (Discard Pause Frames) + rx_control |= (0<<23); // PMCF-bit (Pass MAC Control Frames) + rx_control |= (0<<25); // BSEX=0 (Buffer Size EXtension) + rx_control |= (1<<26); // SECRC-bit (Strip Ethernet CRC) + rx_control |= (0<<27); // FLEXBUF=0 (Flexible Buffer size) + e1000_outl(dev, E1000_RCTL, rx_control); + + // configure the controller's 'transmit' engine + tx_control = 0; + tx_control |= (0<<1); // EN-bit (Enable) + tx_control |= (1<<3); // PSP-bit (Pad Short Packets) + tx_control |= (15<<4); // CT=15 (Collision Threshold) + tx_control |= (63<<12); // COLD=63 (Collision Distance) + tx_control |= (0<<22); // SWXOFF-bit (Software XOFF) + tx_control |= (1<<24); // RTLC-bit (Re-Transmit on Late Collision) + tx_control |= (0<<25); // UNORTX-bit (Underrun No Re-Transmit) + tx_control |= (0<<26); // TXCSCMT=0 (TxDesc Mininum Threshold) + tx_control |= (0<<28); // MULR-bit (Multiple Request Support) + e1000_outl(dev, E1000_TCTL, tx_control); + + // hardware flow control + pba = e1000_inl(dev, E1000_PBA); + // get receive FIFO size + pba = (pba & 0x000000ff)<<10; + e1000_outl(dev, E1000_FCAL, 0x00C28001); + e1000_outl(dev, E1000_FCAH, 0x00000100); + e1000_outl(dev, E1000_FCT, 0x00008808); + e1000_outl(dev, E1000_FCTTV, 0x00000680); + e1000_outl(dev, E1000_FCRTL, (pba*8/10)|0x80000000); + e1000_outl(dev, E1000_FCRTH, pba*9/10); + + // setup tx rings + txd_phys = PADDR(dev->tx_ring.desc); + kmem_phys = PADDR(dev->tx_ring.buf); + for (i=0; itx_ring.desc[i].base_address = kmem_phys; + dev->tx_ring.desc[i].packet_length = 0; + dev->tx_ring.desc[i].cksum_offset = 0; + dev->tx_ring.desc[i].cksum_origin = 0; + dev->tx_ring.desc[i].desc_status = 1; + dev->tx_ring.desc[i].desc_command = (1<<0)|(1<<1)|(1<<3); + dev->tx_ring.desc[i].special_info = 0; + } + dev->tx_ring.tail = 0; + e1000_outl(dev, E1000_TDT, 0); + e1000_outl(dev, E1000_TDH, 0); + // tell controller the location, size, and fetch-policy for Tx queue + e1000_outl(dev, E1000_TDBAL, txd_phys); + e1000_outl(dev, E1000_TDBAH, 0x00000000); + e1000_outl(dev, E1000_TDLEN, CONFIG_E1000_N_TX_DESC*16); + e1000_outl(dev, E1000_TXDCTL, 0x01010000); + + // setup rx rings + rxd_phys = PADDR(dev->rx_ring.desc); + kmem_phys = PADDR(dev->rx_ring.buf); + for (i=0; irx_ring.desc[i].base_address = kmem_phys; + dev->rx_ring.desc[i].packet_length = 0; + dev->rx_ring.desc[i].packet_cksum = 0; + dev->rx_ring.desc[i].desc_status = 0; + dev->rx_ring.desc[i].desc_errors = 0; + dev->rx_ring.desc[i].vlan_tag = 0; + } + dev->rx_ring.head = 0; + dev->rx_ring.tail = CONFIG_E1000_N_RX_DESC-1; + dev->rx_ring.free = 0; + // give the controller ownership of all receive descriptors + e1000_outl(dev, E1000_RDH, 0); + e1000_outl(dev, E1000_RDT, CONFIG_E1000_N_RX_DESC-1); + // tell controller the location, size, and fetch-policy for RX queue + e1000_outl(dev, E1000_RDBAL, rxd_phys); + e1000_outl(dev, E1000_RDBAH, 0x00000000); + e1000_outl(dev, E1000_RDLEN, CONFIG_E1000_N_RX_DESC*16); + e1000_outl(dev, E1000_RXDCTL, 0x01010000); + + e1000_turn_on(dev); +} + +/**************************************************************************** + * Function: e1000_transmit + * + * Description: + * Start hardware transmission. Called either from the txdone interrupt + * handling or from watchdog based polling. + * + * Parameters: + * e1000 - Reference to the driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int e1000_transmit(struct e1000_dev *e1000) +{ + int tail = e1000->tx_ring.tail; + unsigned char *cp = (unsigned char *) + (e1000->tx_ring.buf + tail * CONFIG_E1000_BUFF_SIZE); + int count = e1000->uip_dev.d_len; + + /* Verify that the hardware is ready to send another packet. If we get + * here, then we are committed to sending a packet; Higher level logic + * must have assured that there is not transmission in progress. + */ + + if (!e1000->tx_ring.desc[tail].desc_status) + return -1; + + /* Increment statistics */ + + /* Send the packet: address=skel->sk_dev.d_buf, length=skel->sk_dev.d_len */ + memcpy(cp, e1000->uip_dev.d_buf, e1000->uip_dev.d_len); + + // prepare the transmit-descriptor + e1000->tx_ring.desc[tail].packet_length = count<60 ? 60:count; + e1000->tx_ring.desc[tail].desc_status = 0; + + // give ownership of this descriptor to the network controller + tail = (tail + 1) % CONFIG_E1000_N_TX_DESC; + e1000->tx_ring.tail = tail; + e1000_outl(e1000, E1000_TDT, tail); + + /* Enable Tx interrupts */ + + /* Setup the TX timeout watchdog (perhaps restarting the timer) */ + + wd_start(e1000->txtimeout, E1000_TXTIMEOUT, e1000_txtimeout, 1, (uint32_t)e1000); + return OK; +} + +/**************************************************************************** + * Function: e1000_uiptxpoll + * + * Description: + * The transmitter is available, check if uIP has any outgoing packets ready + * to send. This is a callback from uip_poll(). uip_poll() may be called: + * + * 1. When the preceding TX packet send is complete, + * 2. When the preceding TX packet send timesout and the interface is reset + * 3. During normal TX polling + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int e1000_uiptxpoll(struct uip_driver_s *dev) +{ + struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private; + int tail = e1000->tx_ring.tail; + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (e1000->uip_dev.d_len > 0) { + uip_arp_out(&e1000->uip_dev); + e1000_transmit(e1000); + + /* Check if there is room in the device to hold another packet. If not, + * return a non-zero value to terminate the poll. + */ + if (!e1000->tx_ring.desc[tail].desc_status) + return -1; + } + + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + + return 0; +} + +/**************************************************************************** + * Function: e1000_receive + * + * Description: + * An interrupt was received indicating the availability of a new RX packet + * + * Parameters: + * e1000 - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void e1000_receive(struct e1000_dev *e1000) +{ + int head = e1000->rx_ring.head; + unsigned char *cp = (unsigned char *) + (e1000->rx_ring.buf + head * CONFIG_E1000_BUFF_SIZE); + int cnt; + + while (e1000->rx_ring.desc[head].desc_status) { + + /* Check for errors and update statistics */ + + // Here we do not handle packets that exceed packet-buffer size + if ((e1000->rx_ring.desc[head].desc_status & 3) == 1) { + cprintf("NIC READ: Oversized packet\n"); + goto next; + } + + /* Check if the packet is a valid size for the uIP buffer configuration */ + + // get the number of actual data-bytes in this packet + cnt = e1000->rx_ring.desc[head].packet_length; + + if (cnt > CONFIG_NET_BUFSIZE || cnt < 14) { + cprintf("NIC READ: invalid package size\n"); + goto next; + } + + /* Copy the data data from the hardware to e1000->uip_dev.d_buf. Set + * amount of data in e1000->uip_dev.d_len + */ + + // now we try to copy these data-bytes to the UIP buffer + memcpy(e1000->uip_dev.d_buf, cp, cnt); + e1000->uip_dev.d_len = cnt; + + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv6 + if (BUF->type == HTONS(UIP_ETHTYPE_IP6)) +#else + if (BUF->type == HTONS(UIP_ETHTYPE_IP)) +#endif + { + uip_arp_ipin(&e1000->uip_dev); + uip_input(&e1000->uip_dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (e1000->uip_dev.d_len > 0) { + uip_arp_out(&e1000->uip_dev); + e1000_transmit(e1000); + } + } + else if (BUF->type == htons(UIP_ETHTYPE_ARP)) { + uip_arp_arpin(&e1000->uip_dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (e1000->uip_dev.d_len > 0) { + e1000_transmit(e1000); + } + } + + next: + e1000->rx_ring.desc[head].desc_status = 0; + e1000->rx_ring.head = (head + 1) % CONFIG_E1000_N_RX_DESC; + e1000->rx_ring.free++; + head = e1000->rx_ring.head; + cp = (unsigned char *)(e1000->rx_ring.buf + head * CONFIG_E1000_BUFF_SIZE); + } +} + +/**************************************************************************** + * Function: e1000_txtimeout + * + * Description: + * Our TX watchdog timed out. Called from the timer interrupt handler. + * The last TX never completed. Reset the hardware and start again. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void e1000_txtimeout(int argc, uint32_t arg, ...) +{ + struct e1000_dev *e1000 = (struct e1000_dev *)arg; + + /* Increment statistics and dump debug info */ + + /* Then reset the hardware */ + e1000_init(e1000); + + /* Then poll uIP for new XMIT data */ + + (void)uip_poll(&e1000->uip_dev, e1000_uiptxpoll); +} + +/**************************************************************************** + * Function: e1000_polltimer + * + * Description: + * Periodic timer handler. Called from the timer interrupt handler. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void e1000_polltimer(int argc, uint32_t arg, ...) +{ + struct e1000_dev *e1000 = (struct e1000_dev *)arg; + int tail = e1000->tx_ring.tail; + + /* Check if there is room in the send another TX packet. We cannot perform + * the TX poll if he are unable to accept another packet for transmission. + */ + if (!e1000->tx_ring.desc[tail].desc_status) + return; + + /* If so, update TCP timing states and poll uIP for new XMIT data. Hmmm.. + * might be bug here. Does this mean if there is a transmit in progress, + * we will missing TCP time state updates? + */ + + (void)uip_timer(&e1000->uip_dev, e1000_uiptxpoll, E1000_POLLHSEC); + + /* Setup the watchdog poll timer again */ + + (void)wd_start(e1000->txpoll, E1000_WDDELAY, e1000_polltimer, 1, arg); +} + +/**************************************************************************** + * Function: e1000_ifup + * + * Description: + * NuttX Callback: Bring up the Ethernet interface when an IP address is + * provided + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int e1000_ifup(struct uip_driver_s *dev) +{ + struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private; + + ndbg("Bringing up: %d.%d.%d.%d\n", + dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, + (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 ); + + /* Initialize PHYs, the Ethernet interface, and setup up Ethernet interrupts */ + e1000_init(e1000); + + /* Set and activate a timer process */ + + (void)wd_start(e1000->txpoll, E1000_WDDELAY, e1000_polltimer, 1, (uint32_t)e1000); + + if (e1000_inl(e1000, E1000_STATUS) & 2) + e1000->bifup = true; + else + e1000->bifup = false; + + return OK; +} + +/**************************************************************************** + * Function: e1000_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int e1000_ifdown(struct uip_driver_s *dev) +{ + struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private; + irqstate_t flags; + + /* Disable the Ethernet interrupt */ + + flags = irqsave(); + + e1000_turn_off(e1000); + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(e1000->txpoll); + wd_cancel(e1000->txtimeout); + + /* Put the the EMAC is its reset, non-operational state. This should be + * a known configuration that will guarantee the skel_ifup() always + * successfully brings the interface back up. + */ + //e1000_reset(e1000); + + /* Mark the device "down" */ + + e1000->bifup = false; + irqrestore(flags); + + return OK; +} + +/**************************************************************************** + * Function: e1000_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int e1000_txavail(struct uip_driver_s *dev) +{ + struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private; + int tail = e1000->tx_ring.tail; + irqstate_t flags; + + /* Disable interrupts because this function may be called from interrupt + * level processing. + */ + + flags = irqsave(); + + /* Ignore the notification if the interface is not yet up */ + + if (e1000->bifup) { + /* Check if there is room in the hardware to hold another outgoing packet. */ + if (e1000->tx_ring.desc[tail].desc_status) + (void)uip_poll(&e1000->uip_dev, e1000_uiptxpoll); + } + + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Function: e1000_addmac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int e1000_addmac(struct uip_driver_s *dev, const uint8_t *mac) +{ + struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + + return OK; +} +#endif + +/**************************************************************************** + * Function: e1000_rmmac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int e1000_rmmac(struct uip_driver_s *dev, const uint8_t *mac) +{ + struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + + return OK; +} +#endif + +irqreturn_t e1000_interrupt_handler(struct Trapframe *tf, void *dev_id) +{ + struct e1000_dev *e1000 = (struct e1000_dev *)dev_id; + + /* Get and clear interrupt status bits */ + int intr_cause = e1000_inl(e1000, E1000_ICR); + e1000_outl(e1000, E1000_ICR, intr_cause); + + // not for me + if (intr_cause == 0) + return IRQ_NONE; + + /* Handle interrupts according to status bit settings */ + + // Link status change + if (intr_cause & (1<<2)) { + if (e1000_inl(e1000, E1000_STATUS) & 2) + e1000->bifup = true; + else + e1000->bifup = false; + } + + /* Check if we received an incoming packet, if so, call skel_receive() */ + + // Rx-descriptor Timer expired + if (intr_cause & (1<<7)) + e1000_receive(e1000); + + // Tx queue empty + if (intr_cause & (1<<1)) + wd_cancel(e1000->txtimeout); + + /* Check is a packet transmission just completed. If so, call skel_txdone. + * This may disable further Tx interrupts if there are no pending + * tansmissions. + */ + + // Tx-descriptor Written back + if (intr_cause & (1<<0)) + uip_poll(&e1000->uip_dev, e1000_uiptxpoll); + + + // Rx-Descriptors Low + if (intr_cause & (1<<4)) { + int tail; + tail = e1000->rx_ring.tail + e1000->rx_ring.free; + tail %= CONFIG_E1000_N_RX_DESC; + e1000->rx_ring.tail = tail; + e1000->rx_ring.free = 0; + e1000_outl(e1000, E1000_RDT, tail); + } + + return IRQ_HANDLED; +} + +/******************************* PCI driver *********************************/ + +static pci_id_t e1000_id_table[] = { + {.sep = {INTEL_VENDERID, E1000_82573L}}, + {.sep = {INTEL_VENDERID, E1000_82540EM}}, + {.sep = {INTEL_VENDERID, E1000_82574L}}, + {.sep = {INTEL_VENDERID, E1000_82567LM}}, + {.sep = {INTEL_VENDERID, E1000_82541PI}}, + {.sep = {0,0}} +}; + +static int e1000_probe(uint16_t addr, pci_id_t id) +{ + uint32_t mmio_base, mmio_size; + uint32_t pci_cmd, size; + int err, irq, flags; + void *kmem, *omem; + struct e1000_dev *dev; + + // alloc e1000_dev memory + dev = kzalloc(sizeof(struct e1000_dev)); + if (dev == NULL) + return -1; + + // enable device + err = pci_enable_device(addr, PCI_RESOURCE_MEM); + if (err) + goto error; + + // get e1000 device type + dev->pci_dev_id = id.join; + + // remap the controller's i/o-memory into kernel's address-space + mmio_base = pci_resource_start(addr, 0); + mmio_size = pci_resource_len(addr, 0); + err = rgmp_memmap_nocache(mmio_base, mmio_size, mmio_base); + if (err) + goto error; + dev->phy_mem_base = mmio_base; + dev->io_mem_base = mmio_base; + dev->mem_size = mmio_size; + + // make sure the controller's Bus Master capability is enabled + pci_cmd = pci_config_readl(addr, PCI_COMMAND); + pci_cmd |= (1<<2); + pci_config_writel(addr, PCI_COMMAND, pci_cmd); + + // MAC address + memset(dev->dst_mac, 0xFF, 6); + memcpy(dev->src_mac, (void *)(dev->io_mem_base+E1000_RA), 6); + + // get e1000 IRQ + flags = 0; + irq = pci_enable_msi(addr); + if (irq == 0) { + irq = pci_read_irq(addr); + flags |= IDC_SHARE; + } + dev->irq = irq; + dev->int_desc.handler = e1000_interrupt_handler; + dev->int_desc.dev_id = dev; + err = rgmp_request_irq(irq, &dev->int_desc, flags); + if (err) + goto err0; + + // Here we alloc a big block of memory once and make it + // aligned to page boundary and multiple of page size. This + // is because the memory can be modified by E1000 DMA and + // should be mapped no-cache which will hugely reduce memory + // access performance. The page size alloc will restrict + // this bad effect only within the memory we alloc here. + size = CONFIG_E1000_N_TX_DESC * sizeof(struct tx_desc) + + CONFIG_E1000_N_TX_DESC * CONFIG_E1000_BUFF_SIZE + + CONFIG_E1000_N_RX_DESC * sizeof(struct rx_desc) + + CONFIG_E1000_N_RX_DESC * CONFIG_E1000_BUFF_SIZE; + size = ROUNDUP(size, PGSIZE); + omem = kmem = memalign(PGSIZE, size); + if (kmem == NULL) { + err = -ENOMEM; + goto err1; + } + rgmp_memremap_nocache((uintptr_t)kmem, size); + + // alloc memory for tx ring + dev->tx_ring.desc = (struct tx_desc*)kmem; + kmem += CONFIG_E1000_N_TX_DESC * sizeof(struct tx_desc); + dev->tx_ring.buf = kmem; + kmem += CONFIG_E1000_N_TX_DESC * CONFIG_E1000_BUFF_SIZE; + + // alloc memory for rx rings + dev->rx_ring.desc = (struct rx_desc*)kmem; + kmem += CONFIG_E1000_N_RX_DESC * sizeof(struct rx_desc); + dev->rx_ring.buf = kmem; + + /* Initialize the driver structure */ + + dev->uip_dev.d_ifup = e1000_ifup; /* I/F up (new IP address) callback */ + dev->uip_dev.d_ifdown = e1000_ifdown; /* I/F down callback */ + dev->uip_dev.d_txavail = e1000_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_IGMP + dev->uip_dev.d_addmac = e1000_addmac; /* Add multicast MAC address */ + dev->uip_dev.d_rmmac = e1000_rmmac; /* Remove multicast MAC address */ +#endif + dev->uip_dev.d_private = dev; /* Used to recover private state from dev */ + + /* Create a watchdog for timing polling for and timing of transmisstions */ + + dev->txpoll = wd_create(); /* Create periodic poll timer */ + dev->txtimeout = wd_create(); /* Create TX timeout timer */ + + // Put the interface in the down state. + // e1000 reset + e1000_reset(dev); + + /* Read the MAC address from the hardware */ + memcpy(dev->uip_dev.d_mac.ether_addr_octet, (void *)(dev->io_mem_base+E1000_RA), 6); + + /* Register the device with the OS so that socket IOCTLs can be performed */ + err = netdev_register(&dev->uip_dev); + if (err) + goto err2; + + // insert into e1000_list + dev->next = e1000_list.next; + e1000_list.next = dev; + cprintf("bring up e1000 device: %04x %08x\n", addr, id.join); + + return 0; + + err2: + rgmp_memremap((uintptr_t)omem, size); + free(omem); + err1: + rgmp_free_irq(irq, &dev->int_desc); + err0: + rgmp_memunmap(mmio_base, mmio_size); + error: + kfree(dev); + cprintf("e1000 device probe fail: %d\n", err); + return err; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void e1000_mod_init(void) +{ + pci_probe_device(e1000_id_table, e1000_probe); +} + +void e1000_mod_exit(void) +{ + uint32_t size; + struct e1000_dev *dev; + + size = CONFIG_E1000_N_TX_DESC * sizeof(struct tx_desc) + + CONFIG_E1000_N_TX_DESC * CONFIG_E1000_BUFF_SIZE + + CONFIG_E1000_N_RX_DESC * sizeof(struct rx_desc) + + CONFIG_E1000_N_RX_DESC * CONFIG_E1000_BUFF_SIZE; + size = ROUNDUP(size, PGSIZE); + + for (dev=e1000_list.next; dev!=NULL; dev=dev->next) { + netdev_unregister(&dev->uip_dev); + e1000_reset(dev); + wd_delete(dev->txpoll); + wd_delete(dev->txtimeout); + rgmp_memremap((uintptr_t)dev->tx_ring.desc, size); + free(dev->tx_ring.desc); + rgmp_free_irq(dev->irq, &dev->int_desc); + rgmp_memunmap((uintptr_t)dev->io_mem_base, dev->mem_size); + kfree(dev); + } + + e1000_list.next = NULL; +} diff --git a/nuttx/drivers/net/e1000.h b/nuttx/drivers/net/e1000.h new file mode 100644 index 0000000000..6614ad77ec --- /dev/null +++ b/nuttx/drivers/net/e1000.h @@ -0,0 +1,123 @@ +/**************************************************************************** + * drivers/net/e1000.h + * + * Copyright (C) 2011 Yu Qiang. All rights reserved. + * Author: Yu Qiang + * + * This file is a part of NuttX: + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_NET_E1000_H +#define __DRIVERS_NET_E1000_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/************** PCI ID ***************/ + +#define INTEL_VENDERID 0x8086 +#define E1000_82573L 0x109a +#define E1000_82540EM 0x100e +#define E1000_82574L 0x10d3 +#define E1000_82567LM 0x10f5 +#define E1000_82541PI 0x107c + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +enum e1000_registers { + E1000_CTRL = 0x0000, // Device Control + E1000_STATUS = 0x0008, // Device Status + E1000_CTRL_EXT = 0x0018, // Device Control Extension + E1000_FCAL = 0x0028, // Flow Control Address Low + E1000_FCAH = 0x002C, // Flow Control Address High + E1000_FCT = 0x0030, // Flow Control Type + E1000_ICR = 0x00C0, // Interrupt Cause Read + E1000_ICS = 0x00C8, // Interrupt Cause Set + E1000_IMS = 0x00D0, // Interrupt Mask Set + E1000_IMC = 0x00D8, // Interrupt Mask Clear + E1000_RCTL = 0x0100, // Receive Control + E1000_FCTTV = 0x0170, // Flow Control Transmit Timer Value + E1000_TCTL = 0x0400, // Transmit Control + E1000_PBA = 0x1000, // Packet Buffer Allocation + E1000_FCRTL = 0x2160, // Flow Control Receive Threshold Low + E1000_FCRTH = 0x2168, // Flow Control Receive Threshold High + E1000_RDBAL = 0x2800, // Rx Descriptor Base Address Low + E1000_RDBAH = 0x2804, // Rx Descriptor Base Address High + E1000_RDLEN = 0x2808, // Rx Descriptor Length + E1000_RDH = 0x2810, // Rx Descriptor Head + E1000_RDT = 0x2818, // Rx Descriptor Tail + E1000_RXDCTL = 0x2828, // Rx Descriptor Control + E1000_TDBAL = 0x3800, // Tx Descriptor Base Address Low + E1000_TDBAH = 0x3804, // Tx Descriptor Base Address High + E1000_TDLEN = 0x3808, // Tx Descriptor Length + E1000_TDH = 0x3810, // Tx Descriptor Head + E1000_TDT = 0x3818, // Tx Descriptor Tail + E1000_TXDCTL = 0x3828, // Tx Descriptor Control + E1000_TPR = 0x40D0, // Total Packets Received + E1000_TPT = 0x40D4, // Total Packets Transmitted + E1000_RA = 0x5400, // Receive-filter Array +}; + +/***************** e1000 device structure *****************/ + +struct tx_desc { + uint64_t base_address; + uint16_t packet_length; + uint8_t cksum_offset; + uint8_t desc_command; + uint8_t desc_status; + uint8_t cksum_origin; + uint16_t special_info; +}; + +struct rx_desc { + uint64_t base_address; + uint16_t packet_length; + uint16_t packet_cksum; + uint8_t desc_status; + uint8_t desc_errors; + uint16_t vlan_tag; +}; + +#endif diff --git a/nuttx/drivers/net/enc28j60.c b/nuttx/drivers/net/enc28j60.c new file mode 100644 index 0000000000..76b0f205b1 --- /dev/null +++ b/nuttx/drivers/net/enc28j60.c @@ -0,0 +1,2221 @@ +/**************************************************************************** + * drivers/net/enc28j60.c + * + * Copyright (C) 2010-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * - ENC28J60 Data Sheet, Stand-Alone Ethernet Controller with SPI Interface, + * DS39662C, 2008 Microchip Technology Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_ENC28J60) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "enc28j60.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* ENC28J60 Configuration Settings: + * + * CONFIG_NET_ENC28J60 - Enabled ENC28J60 support + * CONFIG_ENC28J60_SPIMODE - Controls the SPI mode + * CONFIG_ENC28J60_FREQUENCY - Define to use a different bus frequency + * CONFIG_ENC28J60_NINTERFACES - Specifies the number of physical ENC28J60 + * devices that will be supported. + * CONFIG_ENC28J60_STATS - Collect network statistics + * CONFIG_ENC28J60_HALFDUPPLEX - Default is full duplex + */ + +/* The ENC28J60 spec says that is supports SPI mode 0,0 only. However, + * somtimes you need to tinker with these things. + */ + +#ifndef CONFIG_ENC28J60_SPIMODE +# define CONFIG_ENC28J60_SPIMODE SPIDEV_MODE2 +#endif + +/* CONFIG_ENC28J60_NINTERFACES determines the number of physical interfaces + * that will be supported. + */ + +#ifndef CONFIG_ENC28J60_NINTERFACES +# define CONFIG_ENC28J60_NINTERFACES 1 +#endif + +/* CONFIG_NET_BUFSIZE must always be defined */ + +#if !defined(CONFIG_NET_BUFSIZE) && (CONFIG_NET_BUFSIZE <= MAX_FRAMELEN) +# error "CONFIG_NET_BUFSIZE is not valid for the ENC28J60" +#endif + +/* We need to have the work queue to handle SPI interrupts */ + +#if !defined(CONFIG_SCHED_WORKQUEUE) && !defined(CONFIG_SPI_OWNBUS) +# error "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)" +#endif + +/* CONFIG_ENC28J60_DUMPPACKET will dump the contents of each packet to the console. */ + +#ifdef CONFIG_ENC28J60_DUMPPACKET +# define enc_dumppacket(m,a,n) lib_dumpbuffer(m,a,n) +#else +# define enc_dumppacket(m,a,n) +#endif + +/* Timing *******************************************************************/ + +/* TX poll deley = 1 seconds. CLK_TCK is the number of clock ticks per second */ + +#define ENC_WDDELAY (1*CLK_TCK) +#define ENC_POLLHSEC (1*2) + +/* TX timeout = 1 minute */ + +#define ENC_TXTIMEOUT (60*CLK_TCK) + +/* Poll timeout */ + +#define ENC_POLLTIMEOUT MSEC2TICK(50) + +/* Packet Memory ************************************************************/ + +/* Packet memory layout */ + +#define ALIGNED_BUFSIZE ((CONFIG_NET_BUFSIZE + 255) & ~255) + +#define PKTMEM_TX_START 0x0000 /* Start TX buffer at 0 */ +#define PKTMEM_TX_ENDP1 ALIGNED_BUFSIZE /* Allow TX buffer for one frame + */ +#define PKTMEM_RX_START PKTMEM_TX_ENDP1 /* Followed by RX buffer */ +#define PKTMEM_RX_END PKTMEM_END /* RX buffer goes to the end of SRAM */ + +/* Misc. Helper Macros ******************************************************/ + +#define enc_rdgreg(priv,ctrlreg) \ + enc_rdgreg2(priv, ENC_RCR | GETADDR(ctrlreg)) +#define enc_wrgreg(priv,ctrlreg,wrdata) \ + enc_wrgreg2(priv, ENC_WCR | GETADDR(ctrlreg), wrdata) +#define enc_bfcgreg(priv,ctrlreg,clrbits) \ + enc_wrgreg2(priv, ENC_BFC | GETADDR(ctrlreg), clrbits) +#define enc_bfsgreg(priv,ctrlreg,setbits) \ + enc_wrgreg2(priv, ENC_BFS | GETADDR(ctrlreg), setbits) + +/* This is a helper pointer for accessing the contents of the Ethernet header */ + +#define BUF ((struct uip_eth_hdr *)priv->dev.d_buf) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The enc_driver_s encapsulates all state information for a single hardware + * interface + */ + +struct enc_driver_s +{ + /* Device control */ + + bool bifup; /* true:ifup false:ifdown */ + uint8_t bank; /* Currently selected bank */ + uint16_t nextpkt; /* Next packet address */ + int irq; /* GPIO IRQ configured for the ENC28J60 */ + + /* Timing */ + + WDOG_ID txpoll; /* TX poll timer */ + WDOG_ID txtimeout; /* TX timeout timer */ + + /* We we don't own the SPI bus, then we cannot do SPI accesses from the + * interrupt handler. + */ + +#ifndef CONFIG_SPI_OWNBUS + struct work_s work; /* Work queue support */ +#endif + + /* This is the contained SPI driver intstance */ + + FAR struct spi_dev_s *spi; + + /* This holds the information visible to uIP/NuttX */ + + struct uip_driver_s dev; /* Interface understood by uIP */ + + /* Statistics */ + +#ifdef CONFIG_ENC28J60_STATS + struct enc_stats_s stats; +#endif +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct enc_driver_s g_enc28j60[CONFIG_ENC28J60_NINTERFACES]; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Low-level SPI helpers */ + +static inline void enc_configspi(FAR struct spi_dev_s *spi); +#ifdef CONFIG_SPI_OWNBUS +static inline void enc_select(FAR struct spi_dev_s *spi); +static inline void enc_deselect(FAR struct spi_dev_s *spi); +#else +static void enc_select(FAR struct spi_dev_s *spi); +static void enc_deselect(FAR struct spi_dev_s *spi); +#endif + +/* SPI control register access */ + +static uint8_t enc_rdgreg2(FAR struct enc_driver_s *priv, uint8_t cmd); +static void enc_wrgreg2(FAR struct enc_driver_s *priv, uint8_t cmd, + uint8_t wrdata); +static void enc_setbank(FAR struct enc_driver_s *priv, uint8_t bank); +static uint8_t enc_rdbreg(FAR struct enc_driver_s *priv, uint8_t ctrlreg); +static void enc_wrbreg(FAR struct enc_driver_s *priv, uint8_t ctrlreg, + uint8_t wrdata); +static int enc_waitbreg(FAR struct enc_driver_s *priv, uint8_t ctrlreg, + uint8_t bits, uint8_t value); + +/* SPI buffer transfers */ + +static void enc_rdbuffer(FAR struct enc_driver_s *priv, FAR uint8_t *buffer, + size_t buflen); +static void enc_wrbuffer(FAR struct enc_driver_s *priv, + FAR const uint8_t *buffer, size_t buflen); + +/* PHY register access */ + +static uint16_t enc_rdphy(FAR struct enc_driver_s *priv, uint8_t phyaddr); +static void enc_wrphy(FAR struct enc_driver_s *priv, uint8_t phyaddr, + uint16_t phydata); + +/* Common TX logic */ + +static int enc_transmit(FAR struct enc_driver_s *priv); +static int enc_uiptxpoll(struct uip_driver_s *dev); + +/* Interrupt handling */ + +static void enc_linkstatus(FAR struct enc_driver_s *priv); +static void enc_txif(FAR struct enc_driver_s *priv); +static void enc_txerif(FAR struct enc_driver_s *priv); +static void enc_txerif(FAR struct enc_driver_s *priv); +static void enc_rxerif(FAR struct enc_driver_s *priv); +static void enc_rxdispath(FAR struct enc_driver_s *priv); +static void enc_pktif(FAR struct enc_driver_s *priv); +static void enc_worker(FAR void *arg); +static int enc_interrupt(int irq, FAR void *context); + +/* Watchdog timer expirations */ + +static void enc_polltimer(int argc, uint32_t arg, ...); +static void enc_txtimeout(int argc, uint32_t arg, ...); + +/* NuttX callback functions */ + +static int enc_ifup(struct uip_driver_s *dev); +static int enc_ifdown(struct uip_driver_s *dev); +static int enc_txavail(struct uip_driver_s *dev); +#ifdef CONFIG_NET_IGMP +static int enc_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +static int enc_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +#endif + +/* Initialization */ + +static void enc_pwrsave(FAR struct enc_driver_s *priv); +static void enc_pwrfull(FAR struct enc_driver_s *priv); +static void enc_setmacaddr(FAR struct enc_driver_s *priv); +static int enc_reset(FAR struct enc_driver_s *priv); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: enc_configspi + * + * Description: + * Configure the SPI for use with the ENC28J60 + * + * Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static inline void enc_configspi(FAR struct spi_dev_s *spi) +{ + /* Configure SPI for the ENC28J60. But only if we own the SPI bus. + * Otherwise, don't bother because it might change. + */ + +#ifdef CONFIG_SPI_OWNBUS + SPI_SETMODE(spi, CONFIG_ENC28J60_SPIMODE); + SPI_SETBITS(spi, 8); +#ifdef CONFIG_ENC28J60_FREQUENCY + SPI_SETFREQUENCY(spi, CONFIG_ENC28J60_FREQUENCY) +#endif +#endif +} + +/**************************************************************************** + * Function: enc_select + * + * Description: + * Select the SPI, locking and re-configuring if necessary + * + * Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_OWNBUS +static inline void enc_select(FAR struct spi_dev_s *spi) +{ + /* We own the SPI bus, so just select the chip */ + + SPI_SELECT(spi, SPIDEV_ETHERNET, true); +} +#else +static void enc_select(FAR struct spi_dev_s *spi) +{ + /* Select ENC28J60 chip (locking the SPI bus in case there are multiple + * devices competing for the SPI bus + */ + + SPI_LOCK(spi, true); + SPI_SELECT(spi, SPIDEV_ETHERNET, true); + + /* Now make sure that the SPI bus is configured for the ENC28J60 (it + * might have gotten configured for a different device while unlocked) + */ + + SPI_SETMODE(spi, CONFIG_ENC28J60_SPIMODE); + SPI_SETBITS(spi, 8); +#ifdef CONFIG_ENC28J60_FREQUENCY + SPI_SETFREQUENCY(spi, CONFIG_ENC28J60_FREQUENCY); +#endif +} +#endif + +/**************************************************************************** + * Function: enc_deselect + * + * Description: + * De-select the SPI + * + * Parameters: + * spi - Reference to the SPI driver structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_OWNBUS +static inline void enc_deselect(FAR struct spi_dev_s *spi) +{ + /* We own the SPI bus, so just de-select the chip */ + + SPI_SELECT(spi, SPIDEV_ETHERNET, false); +} +#else +static void enc_deselect(FAR struct spi_dev_s *spi) +{ + /* De-select ENC28J60 chip and relinquish the SPI bus. */ + + SPI_SELECT(spi, SPIDEV_ETHERNET, false); + SPI_LOCK(spi, false); +} +#endif + +/**************************************************************************** + * Function: enc_rdgreg2 + * + * Description: + * Read a global register (EIE, EIR, ESTAT, ECON2, or ECON1). The cmd + * include the CMD 'OR'd with the the global address register. + * + * Parameters: + * priv - Reference to the driver state structure + * cmd - The full command to received (cmd | address) + * + * Returned Value: + * The value read from the register + * + * Assumptions: + * + ****************************************************************************/ + +static uint8_t enc_rdgreg2(FAR struct enc_driver_s *priv, uint8_t cmd) +{ + FAR struct spi_dev_s *spi; + uint8_t rddata; + + DEBUGASSERT(priv && priv->spi); + spi = priv->spi; + + /* Select ENC28J60 chip */ + + enc_select(spi); + + /* Send the read command and collect the data. The sequence requires + * 16-clocks: 8 to clock out the cmd + 8 to clock in the data. + */ + + (void)SPI_SEND(spi, cmd); /* Clock out the command */ + rddata = SPI_SEND(spi, 0); /* Clock in the data */ + + /* De-select ENC28J60 chip */ + + enc_deselect(spi); + return rddata; +} + +/**************************************************************************** + * Function: enc_wrgreg2 + * + * Description: + * Write to a global register (EIE, EIR, ESTAT, ECON2, or ECON1). The cmd + * include the CMD 'OR'd with the the global address register. + * + * Parameters: + * priv - Reference to the driver state structure + * cmd - The full command to received (cmd | address) + * wrdata - The data to send + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_wrgreg2(FAR struct enc_driver_s *priv, uint8_t cmd, + uint8_t wrdata) +{ + FAR struct spi_dev_s *spi; + + DEBUGASSERT(priv && priv->spi); + spi = priv->spi; + + /* Select ENC28J60 chip */ + + enc_select(spi); + + /* Send the write command and data. The sequence requires 16-clocks: + * 8 to clock out the cmd + 8 to clock out the data. + */ + + (void)SPI_SEND(spi, cmd); /* Clock out the command */ + (void)SPI_SEND(spi, wrdata); /* Clock out the data */ + + /* De-select ENC28J60 chip. */ + + enc_deselect(spi); +} + +/**************************************************************************** + * Function: enc_setbank + * + * Description: + * Set the bank for these next control register access. + * + * Assumption: + * The caller has exclusive access to the SPI bus + * + * Parameters: + * priv - Reference to the driver state structure + * bank - The bank to select (0-3) + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_setbank(FAR struct enc_driver_s *priv, uint8_t bank) +{ + /* Check if the bank setting has changed*/ + + if (bank != priv->bank) + { + /* Select bank 0 (just so that all of the bits are cleared) */ + + enc_bfcgreg(priv, ENC_ECON1, ECON1_BSEL_MASK); + + /* Then OR in bits to get the correct bank */ + + if (bank != 0) + { + enc_bfsgreg(priv, ENC_ECON1, (bank << ECON1_BSEL_SHIFT)); + } + + /* Then remember the bank setting */ + + priv->bank = bank; + } +} + +/**************************************************************************** + * Function: enc_rdbreg + * + * Description: + * Read from a banked control register using the RCR command. + * + * Parameters: + * priv - Reference to the driver state structure + * ctrlreg - Bit encoded address of banked register to read + * + * Returned Value: + * The byte read from the banked register + * + * Assumptions: + * + ****************************************************************************/ + +static uint8_t enc_rdbreg(FAR struct enc_driver_s *priv, uint8_t ctrlreg) +{ + FAR struct spi_dev_s *spi; + uint8_t rddata; + + DEBUGASSERT(priv && priv->spi); + spi = priv->spi; + + /* Select ENC28J60 chip */ + + enc_select(spi); + + /* Set the bank */ + + enc_setbank(priv, GETBANK(ctrlreg)); + + /* Send the RCR command and collect the data. How we collect the data + * depends on if this is a PHY/CAN or not. The normal sequence requires + * 16-clocks: 8 to clock out the cmd and 8 to clock in the data. + */ + + (void)SPI_SEND(spi, ENC_RCR | GETADDR(ctrlreg)); /* Clock out the command */ + if (ISPHYMAC(ctrlreg)) + { + /* The PHY/MAC sequence requires 24-clocks: 8 to clock out the cmd, + * 8 dummy bits, and 8 to clock in the PHY/MAC data. + */ + + (void)SPI_SEND(spi,0); /* Clock in the dummy byte */ + } + rddata = SPI_SEND(spi, 0); /* Clock in the data */ + + /* De-select ENC28J60 chip */ + + enc_deselect(spi); + return rddata; +} + +/**************************************************************************** + * Function: enc_wrbreg + * + * Description: + * Write to a banked control register using the WCR command. Unlike + * reading, this same SPI sequence works for normal, MAC, and PHY + * registers. + * + * Parameters: + * priv - Reference to the driver state structure + * ctrlreg - Bit encoded address of banked register to write + * wrdata - The data to send + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_wrbreg(FAR struct enc_driver_s *priv, uint8_t ctrlreg, + uint8_t wrdata) +{ + FAR struct spi_dev_s *spi; + + DEBUGASSERT(priv && priv->spi); + spi = priv->spi; + + /* Select ENC28J60 chip */ + + enc_select(spi); + + /* Set the bank */ + + enc_setbank(priv, GETBANK(ctrlreg)); + + /* Send the WCR command and data. The sequence requires 16-clocks: + * 8 to clock out the cmd + 8 to clock out the data. + */ + + (void)SPI_SEND(spi, ENC_WCR | GETADDR(ctrlreg)); /* Clock out the command */ + (void)SPI_SEND(spi, wrdata); /* Clock out the data */ + + /* De-select ENC28J60 chip. */ + + enc_deselect(spi); +} + +/**************************************************************************** + * Function: enc_waitbreg + * + * Description: + * Wait until banked register bit(s) take a specific value (or a timeout + * occurs). + * + * Parameters: + * priv - Reference to the driver state structure + * ctrlreg - Bit encoded address of banked register to check + * bits - The bits to check (a mask) + * value - The value of the bits to return (value under mask) + * + * Returned Value: + * OK on success, negated errno on failure + * + * Assumptions: + * + ****************************************************************************/ + +static int enc_waitbreg(FAR struct enc_driver_s *priv, uint8_t ctrlreg, + uint8_t bits, uint8_t value) +{ + uint32_t start = clock_systimer(); + uint32_t elapsed; + uint8_t rddata; + + /* Loop until the exit condition is met */ + + do + { + /* Read the byte from the requested banked register */ + + rddata = enc_rdbreg(priv, ctrlreg); + elapsed = clock_systimer() - start; + } + while ((rddata & bits) != value || elapsed > ENC_POLLTIMEOUT); + return (rddata & bits) == value ? -ETIMEDOUT : OK; +} + +/**************************************************************************** + * Function: enc_rdbuffer + * + * Description: + * Read a buffer of data. + * + * Parameters: + * priv - Reference to the driver state structure + * buffer - A pointer to the buffer to read into + * buflen - The number of bytes to read + * + * Returned Value: + * None + * + * Assumptions: + * Read pointer is set to the correct address + * + ****************************************************************************/ + +static void enc_rdbuffer(FAR struct enc_driver_s *priv, FAR uint8_t *buffer, + size_t buflen) +{ + FAR struct spi_dev_s *spi; + + DEBUGASSERT(priv && priv->spi); + spi = priv->spi; + + /* Select ENC28J60 chip */ + + enc_select(spi); + + /* Send the read buffer memory command (ignoring the response) */ + + (void)SPI_SEND(spi, ENC_RBM); + + /* Then read the buffer data */ + + SPI_RECVBLOCK(spi, buffer, buflen); + + /* De-select ENC28J60 chip. */ + + enc_deselect(spi); +} + +/**************************************************************************** + * Function: enc_wrbuffer + * + * Description: + * Write a buffer of data. + * + * Parameters: + * priv - Reference to the driver state structure + * buffer - A pointer to the buffer to write from + * buflen - The number of bytes to write + * + * Returned Value: + * None + * + * Assumptions: + * Read pointer is set to the correct address + * + ****************************************************************************/ + +static void enc_wrbuffer(FAR struct enc_driver_s *priv, + FAR const uint8_t *buffer, size_t buflen) +{ + FAR struct spi_dev_s *spi; + + DEBUGASSERT(priv && priv->spi); + spi = priv->spi; + + /* Select ENC28J60 chip */ + + enc_select(spi); + + /* Send the write buffer memory command (ignoring the response) */ + + (void)SPI_SEND(spi, ENC_WBM); + + /* Then send the buffer */ + + SPI_SNDBLOCK(spi, buffer, buflen); + + /* De-select ENC28J60 chip. */ + + enc_deselect(spi); +} + +/**************************************************************************** + * Function: enc_rdphy + * + * Description: + * Read 16-bits of PHY data. + * + * Parameters: + * priv - Reference to the driver state structure + * phyaddr - The PHY register address + * + * Returned Value: + * 16-bit value read from the PHY + * + * Assumptions: + * + ****************************************************************************/ + +static uint16_t enc_rdphy(FAR struct enc_driver_s *priv, uint8_t phyaddr) +{ + uint16_t data = 0; + + /* Set the PHY address (and start the PHY read operation) */ + + enc_wrbreg(priv, ENC_MIREGADR, phyaddr); + enc_wrbreg(priv, ENC_MICMD, MICMD_MIIRD); + + /* Wait until the PHY read completes */ + + if (enc_waitbreg(priv, ENC_MISTAT, MISTAT_BUSY, 0x00) == OK); + { + /* Terminate reading */ + + enc_wrbreg(priv, ENC_MICMD, 0x00); + + /* Get the PHY data */ + + data = (uint16_t)enc_rdbreg(priv, ENC_MIRDL); + data |= (uint16_t)enc_rdbreg(priv, ENC_MIRDH) << 8; + } + return data; +} + +/**************************************************************************** + * Function: enc_wrphy + * + * Description: + * write 16-bits of PHY data. + * + * Parameters: + * priv - Reference to the driver state structure + * phyaddr - The PHY register address + * phydata - 16-bit data to write to the PHY + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_wrphy(FAR struct enc_driver_s *priv, uint8_t phyaddr, + uint16_t phydata) +{ + /* Set the PHY register address */ + + enc_wrbreg(priv, ENC_MIREGADR, phyaddr); + + /* Write the PHY data */ + + enc_wrbreg(priv, ENC_MIWRL, phydata); + enc_wrbreg(priv, ENC_MIWRH, phydata >> 8); + + /* Wait until the PHY write completes */ + + enc_waitbreg(priv, ENC_MISTAT, MISTAT_BUSY, 0x00); +} + +/**************************************************************************** + * Function: enc_transmit + * + * Description: + * Start hardware transmission. Called either from: + * + * - pkif interrupt when an application responds to the receipt of data + * by trying to send something, or + * - From watchdog based polling. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * + ****************************************************************************/ + +static int enc_transmit(FAR struct enc_driver_s *priv) +{ + uint16_t txend; + + /* Increment statistics */ + + nllvdbg("Sending packet, pktlen: %d\n", priv->dev.d_len); +#ifdef CONFIG_ENC28J60_STATS + priv->stats.txrequests++; +#endif + + /* Verify that the hardware is ready to send another packet. The driver + * starts a transmission process by setting ECON1.TXRTS. When the packet is + * finished transmitting or is aborted due to an error/cancellation, the + * ECON1.TXRTS bit will be cleared. + * + * NOTE: If we got here, then we have committed to sending a packet. + * higher level logic must have assured that (1) there is no transmission + * in progress, and that (2) TX-related interrupts are disabled. + */ + + DEBUGASSERT((enc_rdgreg(priv, ENC_ECON1) & ECON1_TXRTS) == 0); + + /* Send the packet: address=priv->dev.d_buf, length=priv->dev.d_len */ + + enc_dumppacket("Transmit Packet", priv->dev.d_buf, priv->dev.d_len); + + /* Reset the write pointer to start of transmit buffer */ + + enc_wrbreg(priv, ENC_EWRPTL, PKTMEM_TX_START & 0xff); + enc_wrbreg(priv, ENC_EWRPTH, PKTMEM_TX_START >> 8); + + /* Set the TX End pointer based on the size of the packet to send */ + + txend = PKTMEM_TX_START + priv->dev.d_len; + enc_wrbreg(priv, ENC_ETXNDL, txend & 0xff); + enc_wrbreg(priv, ENC_ETXNDH, txend >> 8); + + /* Write the per-packet control byte into the transmit buffer */ + + enc_wrgreg(priv, ENC_WBM, 0x00); + + /* Copy the packet itself into the transmit buffer */ + + enc_wrbuffer(priv, priv->dev.d_buf, priv->dev.d_len); + + /* Set TXRTS to send the packet in the transmit buffer */ + + enc_bfsgreg(priv, ENC_ECON1, ECON1_TXRTS); + + /* Setup the TX timeout watchdog (perhaps restarting the timer). Note: + * Is there a race condition. Could the TXIF interrupt occur before + * the timer is started? + */ + + (void)wd_start(priv->txtimeout, ENC_TXTIMEOUT, enc_txtimeout, 1, (uint32_t)priv); + return OK; +} + +/**************************************************************************** + * Function: enc_uiptxpoll + * + * Description: + * The transmitter is available, check if uIP has any outgoing packets ready + * to send. This is a callback from uip_poll(). uip_poll() may be called: + * + * 1. When the preceding TX packet send is complete, + * 2. When the preceding TX packet send timesout and the interface is reset + * 3. During normal TX polling + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * + ****************************************************************************/ + +static int enc_uiptxpoll(struct uip_driver_s *dev) +{ + FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private; + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + nllvdbg("Poll result: d_len=%d\n", priv->dev.d_len); + if (priv->dev.d_len > 0) + { + uip_arp_out(&priv->dev); + enc_transmit(priv); + + /* Stop the poll now because we can queue only one packet */ + + return -EBUSY; + } + + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + + return OK; +} + +/**************************************************************************** + * Function: enc_linkstatus + * + * Description: + * The current link status can be obtained from the PHSTAT1.LLSTAT or + * PHSTAT2.LSTAT. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_linkstatus(FAR struct enc_driver_s *priv) +{ +#if 0 + uint16_t regval = enc_rdphy(priv, ENC_PHSTAT2); + priv->duplex = ((regval & PHSTAT2_DPXSTAT) != 0); + priv->carrier = ((regval & PHSTAT2_LSTAT) != 0); +#endif +} + +/**************************************************************************** + * Function: enc_txif + * + * Description: + * An TXIF interrupt was received indicating that the last TX packet(s) is + * done + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_txif(FAR struct enc_driver_s *priv) +{ + /* Update statistics */ + +#ifdef CONFIG_ENC28J60_STATS + priv->stats.txifs++; + if (enc_rdgreg(priv, ENC_ESTAT) & ESTAT_TXABRT) + { + priv->stats.txabrts++; + } +#endif + + /* Clear the request to send bit */ + + enc_bfcgreg(priv, ENC_ECON1, ECON1_TXRTS); + + /* If no further xmits are pending, then cancel the TX timeout */ + + wd_cancel(priv->txtimeout); + + /* Then poll uIP for new XMIT data */ + + (void)uip_poll(&priv->dev, enc_uiptxpoll); +} + +/**************************************************************************** + * Function: enc_txerif + * + * Description: + * An TXERIF interrupt was received indicating that a TX abort has occurred. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_txerif(FAR struct enc_driver_s *priv) +{ + /* Update statistics */ + +#ifdef CONFIG_ENC28J60_STATS + priv->stats.txerifs++; +#endif + + /* Reset TX */ + + enc_bfsgreg(priv, ENC_ECON1, ECON1_TXRST); + enc_bfcgreg(priv, ENC_ECON1, ECON1_TXRST | ECON1_TXRTS); + + /* Here we really should re-transmit (I fact, if we want half duplex to + * work right, then it is necessary to do this!): + * + * 1. Read the TSV: + * - Read ETXNDL to get the end pointer + * - Read 7 bytes from that pointer + 1 using ENC_RMB. + * 2. Determine if we need to retransmit. Check the LATE COLLISION bit, if + * set, then we need to transmit. + * 3. Retranmit by resetting ECON1_TXRTS. + */ + +#ifdef CONFIG_ENC28J60_HALFDUPLEX +# error "Missing logic for half duplex" +#endif +} + +/**************************************************************************** + * Function: enc_rxerif + * + * Description: + * An RXERIF interrupt was received indicating that the last TX packet(s) is + * done + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_rxerif(FAR struct enc_driver_s *priv) +{ + /* Update statistics */ + +#ifdef CONFIG_ENC28J60_STATS + priv->stats.rxerifs++; +#endif +} + +/**************************************************************************** + * Function: enc_rxdispath + * + * Description: + * Give the newly received packet to uIP. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_rxdispath(FAR struct enc_driver_s *priv) +{ + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv6 + if (BUF->type == HTONS(UIP_ETHTYPE_IP6)) +#else + if (BUF->type == HTONS(UIP_ETHTYPE_IP)) +#endif + { + nllvdbg("IP packet received (%02x)\n", BUF->type); + uip_arp_ipin(&priv->dev); + uip_input(&priv->dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + uip_arp_out(&priv->dev); + enc_transmit(priv); + } + } + else if (BUF->type == htons(UIP_ETHTYPE_ARP)) + { + nllvdbg("ARP packet received (%02x)\n", BUF->type); + uip_arp_arpin(&priv->dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + enc_transmit(priv); + } + } + else + { + nlldbg("Unsupported packet type dropped (%02x)\n", htons(BUF->type)); + } +} + +/**************************************************************************** + * Function: enc_pktif + * + * Description: + * An interrupt was received indicating the availability of a new RX packet + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_pktif(FAR struct enc_driver_s *priv) +{ + uint8_t rsv[6]; + uint16_t pktlen; + uint16_t rxstat; + + /* Update statistics */ + +#ifdef CONFIG_ENC28J60_STATS + priv->stats.pktifs++; +#endif + + /* Set the read pointer to the start of the received packet */ + + DEBUGASSERT(priv->nextpkt <= PKTMEM_RX_END); + enc_wrbreg(priv, ENC_ERDPTL, (priv->nextpkt)); + enc_wrbreg(priv, ENC_ERDPTH, (priv->nextpkt) >> 8); + + /* Read the next packet pointer and the 4 byte read status vector (RSV) + * at the beginning of the received packet + */ + + enc_rdbuffer(priv, rsv, 6); + + /* Decode the new next packet pointer, and the RSV. The + * RSV is encoded as: + * + * Bits 0-15: Indicates length of the received frame. This includes the + * destination address, source address, type/length, data, + * padding and CRC fields. This field is stored in little- + * endian format. + * Bits 16-31: Bit encoded RX status. + */ + + priv->nextpkt = (uint16_t)rsv[1] << 8 | (uint16_t)rsv[0]; + pktlen = (uint16_t)rsv[3] << 8 | (uint16_t)rsv[2]; + rxstat = (uint16_t)rsv[5] << 8 | (uint16_t)rsv[4]; + nllvdbg("Receiving packet, pktlen: %d\n", pktlen); + + /* Check if the packet was received OK */ + + if ((rxstat & RXSTAT_OK) == 0) + { + nlldbg("ERROR: RXSTAT: %04x\n", rxstat); +#ifdef CONFIG_ENC28J60_STATS + priv->stats.rxnotok++; +#endif + } + + /* Check for a usable packet length (4 added for the CRC) */ + + else if (pktlen > (CONFIG_NET_BUFSIZE + 4) || pktlen <= (UIP_LLH_LEN + 4)) + { + nlldbg("Bad packet size dropped (%d)\n", pktlen); +#ifdef CONFIG_ENC28J60_STATS + priv->stats.rxpktlen++; +#endif + } + + /* Otherwise, read and process the packet */ + + else + { + /* Save the packet length (without the 4 byte CRC) in priv->dev.d_len*/ + + priv->dev.d_len = pktlen - 4; + + /* Copy the data data from the receive buffer to priv->dev.d_buf */ + + enc_rdbuffer(priv, priv->dev.d_buf, priv->dev.d_len); + enc_dumppacket("Received Packet", priv->ld_dev.d_buf, priv->ld_dev.d_len); + + /* Dispatch the packet to uIP */ + + enc_rxdispath(priv); + } + + /* Move the RX read pointer to the start of the next received packet. + * This frees the memory we just read. + */ + + enc_wrbreg(priv, ENC_ERXRDPTL, (priv->nextpkt)); + enc_wrbreg(priv, ENC_ERXRDPTH, (priv->nextpkt) >> 8); + + /* Decrement the packet counter indicate we are done with this packet */ + + enc_bfsgreg(priv, ENC_ECON2, ECON2_PKTDEC); +} + +/**************************************************************************** + * Function: enc_worker + * + * Description: + * Perform interrupt handling logic outside of the interrupt handler (on + * the work queue thread). + * + * Parameters: + * arg - The reference to the driver structure (case to void*) + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_worker(FAR void *arg) +{ + FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)arg; + uint8_t eir; + + DEBUGASSERT(priv); + + /* Disable further interrupts by clearing the global interrup enable bit */ + + enc_bfcgreg(priv, ENC_EIE, EIE_INTIE); + + /* Loop until all interrupts have been processed (EIR==0). Note that + * there is no infinite loop check... if there are always pending interrupts, + * we are just broken. + */ + + while ((eir = enc_rdgreg(priv, ENC_EIR) & EIR_ALLINTS) != 0) + { + /* Handle interrupts according to interrupt register register bit + * settings + * + * DMAIF: The DMA interrupt indicates that the DMA module has completed + * its memory copy or checksum calculation. Additionally, this interrupt + * will be caused if the host controller cancels a DMA operation by + * manually clearing the DMAST bit. Once set, DMAIF can only be cleared + * by the host controller or by a Reset condition. + */ + + if ((eir & EIR_DMAIF) != 0) /* DMA interrupt */ + { + /* Not used by this driver. Just clear the interrupt request. */ + + enc_bfcgreg(priv, ENC_EIR, EIR_DMAIF); + } + + /* LINKIF: The LINKIF indicates that the link status has changed. + * The actual current link status can be obtained from the + * PHSTAT1.LLSTAT or PHSTAT2.LSTAT. Unlike other interrupt sources, the + * link status change interrupt is created in the integrated PHY + * module. + * + * To receive it, the host controller must set the PHIE.PLNKIE and + * PGEIE bits. After setting the two PHY interrupt enable bits, the + * LINKIF bit will then shadow the contents of the PHIR.PGIF bit. + * + * Once LINKIF is set, it can only be cleared by the host controller or + * by a Reset. The LINKIF bit is read-only. Performing an MII read on + * the PHIR register will clear the LINKIF, PGIF and PLNKIF bits + * automatically and allow for future link status change interrupts. + */ + + if ((eir & EIR_LINKIF) != 0) /* Link change interrupt */ + { + enc_linkstatus(priv); /* Get current link status */ + enc_rdphy(priv, ENC_PHIR); /* Clear the LINKIF interrupt */ + } + + /* TXIF: The Transmit Interrupt Flag (TXIF) is used to indicate that + * the requested packet transmission has ended. Upon transmission + * completion, abort or transmission cancellation by the host + * controller, the EIR.TXIF flag will be set to 1. + * + * Once TXIF is set, it can only be cleared by the host controller + * or by a Reset condition. Once processed, the host controller should + * use the BFC command to clear the EIR.TXIF bit. + */ + + if ((eir & EIR_TXIF) != 0) /* Transmit interrupt */ + { + enc_txif(priv); /* Handle TX completion */ + enc_bfcgreg(priv, ENC_EIR, EIR_TXIF); /* Clear the TXIF interrupt */ + } + + /* TXERIF: The Transmit Error Interrupt Flag (TXERIF) is used to + * indicate that a transmit abort has occurred. An abort can occur + * because of any of the following: + * + * 1. Excessive collisions occurred as defined by the Retransmission + * Maximum (RETMAX) bits in the MACLCON1 register. + * 2. A late collision occurred as defined by the Collision Window + * (COLWIN) bits in the MACLCON2 register. + * 3. A collision after transmitting 64 bytes occurred (ESTAT.LATECOL + * set). + * 4. The transmission was unable to gain an opportunity to transmit + * the packet because the medium was constantly occupied for too long. + * The deferral limit (2.4287 ms) was reached and the MACON4.DEFER bit + * was clear. + * 5. An attempt to transmit a packet larger than the maximum frame + * length defined by the MAMXFL registers was made without setting + * the MACON3.HFRMEN bit or per packet POVERRIDE and PHUGEEN bits. + * + * Upon any of these conditions, the EIR.TXERIF flag is set to 1. Once + * set, it can only be cleared by the host controller or by a Reset + * condition. + * + * After a transmit abort, the TXRTS bit will be cleared, the + * ESTAT.TXABRT bit will be set and the transmit status vector will be + * written at ETXND + 1. The MAC will not automatically attempt to + * retransmit the packet. The host controller may wish to read the + * transmit status vector and LATECOL bit to determine the cause of + * the abort. After determining the problem and solution, the host + * controller should clear the LATECOL (if set) and TXABRT bits so + * that future aborts can be detected accurately. + * + * In Full-Duplex mode, condition 5 is the only one that should cause + * this interrupt. Collisions and other problems related to sharing + * the network are not possible on full-duplex networks. The conditions + * which cause the transmit error interrupt meet the requirements of the + * transmit interrupt. As a result, when this interrupt occurs, TXIF + * will also be simultaneously set. + */ + + if ((eir & EIR_TXERIF) != 0) /* Transmit Error Interrupts */ + { + enc_txerif(priv); /* Handle the TX error */ + enc_bfcgreg(priv, ENC_EIR, EIR_TXERIF); /* Clear the TXERIF interrupt */ + } + + /* PKTIF The Receive Packet Pending Interrupt Flag (PKTIF) is used to + * indicate the presence of one or more data packets in the receive + * buffer and to provide a notification means for the arrival of new + * packets. When the receive buffer has at least one packet in it, + * EIR.PKTIF will be set. In other words, this interrupt flag will be + * set anytime the Ethernet Packet Count register (EPKTCNT) is non-zero. + * + * The PKTIF bit can only be cleared by the host controller or by a Reset + * condition. In order to clear PKTIF, the EPKTCNT register must be + * decremented to 0. If the last data packet in the receive buffer is + * processed, EPKTCNT will become zero and the PKTIF bit will automatically + * be cleared. + */ + + /* Ignore PKTIF because is unreliable. Use EPKTCNT instead */ + /* if ((eir & EIR_PKTIF) != 0) */ + { + uint8_t pktcnt = enc_rdbreg(priv, ENC_EPKTCNT); + if (pktcnt > 0) + { +#ifdef CONFIG_ENC28J60_STATS + if (pktcnt > priv->stats.maxpktcnt) + { + priv->stats.maxpktcnt = pktcnt; + } +#endif + /* Handle packet receipt */ + + enc_pktif(priv); + } + } + + /* RXERIF: The Receive Error Interrupt Flag (RXERIF) is used to + * indicate a receive buffer overflow condition. Alternately, this + * interrupt may indicate that too many packets are in the receive + * buffer and more cannot be stored without overflowing the EPKTCNT + * register. When a packet is being received and the receive buffer + * runs completely out of space, or EPKTCNT is 255 and cannot be + * incremented, the packet being received will be aborted (permanently + * lost) and the EIR.RXERIF bit will be set to 1. + * + * Once set, RXERIF can only be cleared by the host controller or by a + * Reset condition. Normally, upon the receive error condition, the + * host controller would process any packets pending from the receive + * buffer and then make additional room for future packets by + * advancing the ERXRDPT registers (low byte first) and decrementing + * the EPKTCNT register. + * + * Once processed, the host controller should use the BFC command to + * clear the EIR.RXERIF bit. + */ + + if ((eir & EIR_RXERIF) != 0) /* Receive Errror Interrupts */ + { + enc_rxerif(priv); /* Handle the RX error */ + enc_bfcgreg(priv, ENC_EIR, EIR_RXERIF); /* Clear the RXERIF interrupt */ + } + + } + + /* Enable Ethernet interrupts */ + + enc_bfsgreg(priv, ENC_EIE, EIE_INTIE); +} + +/**************************************************************************** + * Function: enc_interrupt + * + * Description: + * Hardware interrupt handler + * + * Parameters: + * irq - Number of the IRQ that generated the interrupt + * context - Interrupt register state save info (architecture-specific) + * + * Returned Value: + * OK on success + * + * Assumptions: + * + ****************************************************************************/ + +static int enc_interrupt(int irq, FAR void *context) +{ + register FAR struct enc_driver_s *priv = &g_enc28j60[0]; + + DEBUGASSERT(priv->irq == irq); + +#ifdef CONFIG_SPI_OWNBUS + /* In very simple environments, we own the SPI and can do data transfers + * from the interrupt handler. That is actually a very bad idea in any + * case because it keeps interrupts disabled for a long time. + */ + + enc_worker((FAR void*)priv); + return OK; +#else + /* In complex environments, we cannot do SPI transfers from the interrupt + * handler because semaphores are probably used to lock the SPI bus. In + * this case, we will defer processing to the worker thread. This is also + * much kinder in the use of system resources and is, therefore, probably + * a good thing to do in any event. + */ + + return work_queue(&priv->work, enc_worker, (FAR void *)priv, 0); +#endif +} + +/**************************************************************************** + * Function: enc_txtimeout + * + * Description: + * Our TX watchdog timed out. Called from the timer interrupt handler. + * The last TX never completed. Reset the hardware and start again. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_txtimeout(int argc, uint32_t arg, ...) +{ + FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)arg; + int ret; + + /* Increment statistics and dump debug info */ + + nlldbg("Tx timeout\n"); +#ifdef CONFIG_ENC28J60_STATS + priv->stats.txtimeouts++; +#endif + + /* Then reset the hardware: Take the interface down, then bring it + * back up + */ + + ret = enc_ifdown(&priv->dev); + DEBUGASSERT(ret == OK); + ret = enc_ifup(&priv->dev); + DEBUGASSERT(ret == OK); + + /* Then poll uIP for new XMIT data */ + + (void)uip_poll(&priv->dev, enc_uiptxpoll); +} + +/**************************************************************************** + * Function: enc_polltimer + * + * Description: + * Periodic timer handler. Called from the timer interrupt handler. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_polltimer(int argc, uint32_t arg, ...) +{ + FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)arg; + + /* Verify that the hardware is ready to send another packet. The driver + * start a transmission process by setting ECON1.TXRTS. When the packet is + * finished transmitting or is aborted due to an error/cancellation, the + * ECON1.TXRTS bit will be cleared. + */ + + if ((enc_rdgreg(priv, ENC_ECON1) & ECON1_TXRTS) == 0) + { + /* Yes.. update TCP timing states and poll uIP for new XMIT data. Hmmm.. + * looks like a bug here to me. Does this mean if there is a transmit + * in progress, we will missing TCP time state updates? + */ + + (void)uip_timer(&priv->dev, enc_uiptxpoll, ENC_POLLHSEC); + } + + /* Setup the watchdog poll timer again */ + + (void)wd_start(priv->txpoll, ENC_WDDELAY, enc_polltimer, 1, arg); +} + +/**************************************************************************** + * Function: enc_ifup + * + * Description: + * NuttX Callback: Bring up the Ethernet interface when an IP address is + * provided + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int enc_ifup(struct uip_driver_s *dev) +{ + FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private; + int ret; + + nlldbg("Bringing up: %d.%d.%d.%d\n", + dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, + (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 ); + + /* Initialize Ethernet interface, set the MAC address, and make sure that + * the ENC28J80 is not in power save mode. + */ + + ret = enc_reset(priv); + if (ret == OK) + { + enc_setmacaddr(priv); + enc_pwrfull(priv); + + /* Enable interrupts at the ENC28J60. Interrupts are still disabled + * at the interrupt controller. + */ + + enc_wrphy(priv, ENC_PHIE, PHIE_PGEIE | PHIE_PLNKIE); + enc_bfsgreg(priv, ENC_EIE, EIE_INTIE | EIE_PKTIE); + enc_bfsgreg(priv, ENC_EIR, EIR_DMAIF | EIR_LINKIF | EIR_TXIF | + EIR_TXERIF | EIR_RXERIF | EIR_PKTIF); + enc_wrgreg(priv, ENC_EIE, EIE_INTIE | EIE_PKTIE | EIE_LINKIE | + EIE_TXIE | EIE_TXERIE | EIE_RXERIE); + + /* Enable the receiver */ + + enc_bfsgreg(priv, ENC_ECON1, ECON1_RXEN); + + /* Set and activate a timer process */ + + (void)wd_start(priv->txpoll, ENC_WDDELAY, enc_polltimer, 1, (uint32_t)priv); + + /* Mark the interface up and enable the Ethernet interrupt at the + * controller + */ + + priv->bifup = true; + up_enable_irq(priv->irq); + } + return ret; +} + +/**************************************************************************** + * Function: enc_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int enc_ifdown(struct uip_driver_s *dev) +{ + FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private; + irqstate_t flags; + int ret; + + nlldbg("Taking down: %d.%d.%d.%d\n", + dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, + (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 ); + + /* Disable the Ethernet interrupt */ + + flags = irqsave(); + up_disable_irq(priv->irq); + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(priv->txpoll); + wd_cancel(priv->txtimeout); + + /* Reset the device and leave in the power save state */ + + ret = enc_reset(priv); + enc_pwrsave(priv); + + priv->bifup = false; + irqrestore(flags); + return ret; +} + +/**************************************************************************** + * Function: enc_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int enc_txavail(struct uip_driver_s *dev) +{ + FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private; + irqstate_t flags; + + flags = irqsave(); + + /* Ignore the notification if the interface is not yet up */ + + if (priv->bifup) + { + /* Check if the hardware is ready to send another packet. The driver + * starts a transmission process by setting ECON1.TXRTS. When the packet is + * finished transmitting or is aborted due to an error/cancellation, the + * ECON1.TXRTS bit will be cleared. + */ + + if ((enc_rdgreg(priv, ENC_ECON1) & ECON1_TXRTS) == 0) + { + /* The interface is up and TX is idle; poll uIP for new XMIT data */ + + (void)uip_poll(&priv->dev, enc_uiptxpoll); + } + } + + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Function: enc_addmac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int enc_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + +#warning "Multicast MAC support not implemented" + return OK; +} +#endif + +/**************************************************************************** + * Function: enc_rmmac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int enc_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + +#warning "Multicast MAC support not implemented" + return OK; +} +#endif + +/**************************************************************************** + * Function: enc_pwrsave + * + * Description: + * The ENC28J60 may be commanded to power-down via the SPI interface. + * When powered down, it will no longer be able to transmit and receive + * any packets. To maximize power savings: + * + * 1. Turn off packet reception by clearing ECON1.RXEN. + * 2. Wait for any in-progress packets to finish being received by + * polling ESTAT.RXBUSY. This bit should be clear before proceeding. + * 3. Wait for any current transmissions to end by confirming ECON1.TXRTS + * is clear. + * 4. Set ECON2.VRPS (if not already set). + * 5. Enter Sleep by setting ECON2.PWRSV. All MAC, MII and PHY registers + * become inaccessible as a result. Setting PWRSV also clears + * ESTAT.CLKRDY automatically. + * + * In Sleep mode, all registers and buffer memory will maintain their + * states. The ETH registers and buffer memory will still be accessible + * by the host controller. Additionally, the clock driver will continue + * to operate. The CLKOUT function will be unaffected. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_pwrsave(FAR struct enc_driver_s *priv) +{ + nllvdbg("Set PWRSV\n"); + + /* 1. Turn off packet reception by clearing ECON1.RXEN. */ + + enc_bfcgreg(priv, ENC_ECON1, ECON1_RXEN); + + /* 2. Wait for any in-progress packets to finish being received by + * polling ESTAT.RXBUSY. This bit should be clear before proceeding. + */ + + if (enc_waitbreg(priv, ENC_ESTAT, ESTAT_RXBUSY, 0) == OK) + { + /* 3. Wait for any current transmissions to end by confirming + * ECON1.TXRTS is clear. + */ + + enc_waitbreg(priv, ENC_ECON1, ECON1_TXRTS, 0); + + /* 4. Set ECON2.VRPS (if not already set). */ + /* enc_bfsgreg(priv, ENC_ECON2, ECON2_VRPS); <-- Set in enc_reset() */ + + /* 5. Enter Sleep by setting ECON2.PWRSV. */ + + enc_bfsgreg(priv, ENC_ECON2, ECON2_PWRSV); + } +} + +/**************************************************************************** + * Function: enc_pwrfull + * + * Description: + * When normal operation is desired, the host controller must perform + * a slightly modified procedure: + * + * 1. Wake-up by clearing ECON2.PWRSV. + * 2. Wait at least 300 ìs for the PHY to stabilize. To accomplish the + * delay, the host controller may poll ESTAT.CLKRDY and wait for it + * to become set. + * 3. Restore receive capability by setting ECON1.RXEN. + * + * After leaving Sleep mode, there is a delay of many milliseconds + * before a new link is established (assuming an appropriate link + * partner is present). The host controller may wish to wait until + * the link is established before attempting to transmit any packets. + * The link status can be determined by polling the PHSTAT2.LSTAT bit. + * Alternatively, the link change interrupt may be used if it is + * enabled. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_pwrfull(FAR struct enc_driver_s *priv) +{ + nllvdbg("Clear PWRSV\n"); + + /* 1. Wake-up by clearing ECON2.PWRSV. */ + + enc_bfcgreg(priv, ENC_ECON2, ECON2_PWRSV); + + /* 2. Wait at least 300 ìs for the PHY to stabilize. To accomplish the + * delay, the host controller may poll ESTAT.CLKRDY and wait for it to + * become set. + */ + + enc_waitbreg(priv, ENC_ESTAT, ESTAT_CLKRDY, ESTAT_CLKRDY); + + /* 3. Restore receive capability by setting ECON1.RXEN. + * + * The caller will do this when it is read to receive packets + */ +} + +/**************************************************************************** + * Function: enc_setmacaddr + * + * Description: + * Set the MAC address to the configured value. This is done after ifup + * or after a TX timeout. Note that this means that the interface must + * be down before configuring the MAC addr. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void enc_setmacaddr(FAR struct enc_driver_s *priv) +{ + /* Program the hardware with it's MAC address (for filtering) */ + + enc_wrbreg(priv, ENC_MAADR1, priv->dev.d_mac.ether_addr_octet[5]); + enc_wrbreg(priv, ENC_MAADR2, priv->dev.d_mac.ether_addr_octet[4]); + enc_wrbreg(priv, ENC_MAADR3, priv->dev.d_mac.ether_addr_octet[3]); + enc_wrbreg(priv, ENC_MAADR4, priv->dev.d_mac.ether_addr_octet[2]); + enc_wrbreg(priv, ENC_MAADR5, priv->dev.d_mac.ether_addr_octet[1]); + enc_wrbreg(priv, ENC_MAADR6, priv->dev.d_mac.ether_addr_octet[0]); +} + +/**************************************************************************** + * Function: enc_reset + * + * Description: + * Stop, reset, re-initialize, and restart the ENC28J60. This is done + * initially, on ifup, and after a TX timeout. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int enc_reset(FAR struct enc_driver_s *priv) +{ + uint8_t regval; + + nlldbg("Reset\n"); + + /* Configure SPI for the ENC28J60 */ + + enc_configspi(priv->spi); + + /* Reset the ENC28J60 */ + + enc_wrgreg(priv, ENC_SRC, ENC_SRC); + + /* Check CLKRDY bit to see when the reset is complete. There is an errata + * that says the CLKRDY may be invalid. We'll wait a couple of msec to + * workaround this condition. + */ + + up_mdelay(2); + /* while ((enc_rdgreg(priv, ENC_ESTAT) & ESTAT_CLKRDY) != 0); */ + + /* Initialize ECON1: Clear ECON1 */ + + enc_wrgreg(priv, ENC_ECON1, 0x00); + + /* Initialize ECON2: Enable address auto increment and voltage + * regulator powersave. + */ + + enc_wrgreg(priv, ENC_ECON2, ECON2_AUTOINC | ECON2_VRPS); + + /* Initialize receive buffer. + * First, set the receive buffer start address. + */ + + priv->nextpkt = PKTMEM_RX_START; + enc_wrbreg(priv, ENC_ERXSTL, PKTMEM_RX_START & 0xff); + enc_wrbreg(priv, ENC_ERXSTH, PKTMEM_RX_START >> 8); + + /* Set the receive data pointer */ + + enc_wrbreg(priv, ENC_ERXRDPTL, PKTMEM_RX_START & 0xff); + enc_wrbreg(priv, ENC_ERXRDPTH, PKTMEM_RX_START >> 8); + + /* Set the receive buffer end. */ + + enc_wrbreg(priv, ENC_ERXNDL, PKTMEM_RX_END & 0xff); + enc_wrbreg(priv, ENC_ERXNDH, PKTMEM_RX_END >> 8); + + /* Set transmit buffer start. */ + + enc_wrbreg(priv, ENC_ETXSTL, PKTMEM_TX_START & 0xff); + enc_wrbreg(priv, ENC_ETXSTH, PKTMEM_TX_START >> 8); + + /* Check if we are actually communicating with the ENC28J60. If its + * 0x00 or 0xff, then we are probably not communicating correctly + * via SPI. + */ + + regval = enc_rdbreg(priv, ENC_EREVID); + if (regval == 0x00 || regval == 0xff) + { + nlldbg("Bad Rev ID: %02x\n", regval); + return -ENODEV; + } + nllvdbg("Rev ID: %02x\n", regval); + + /* Set filter mode: unicast OR broadcast AND crc valid */ + + enc_wrbreg(priv, ENC_ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_BCEN); + + /* Enable MAC receive */ + + enc_wrbreg(priv, ENC_MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS); + + /* Enable automatic padding and CRC operations */ + +#ifdef CONFIG_ENC28J60_HALFDUPLEX + enc_wrbreg(priv, ENC_MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN); + enc_wrbreg(priv, ENC_MACON4, MACON4_DEFER); /* Defer transmission enable */ + + /* Set Non-Back-to-Back Inter-Packet Gap */ + + enc_wrbreg(priv, ENC_MAIPGL, 0x12); + enc_wrbreg(priv, ENC_MAIPGH, 0x0c); + + /* Set Back-to-Back Inter-Packet Gap */ + + enc_wrbreg(priv, ENC_MABBIPG, 0x12); +#else + /* Set filter mode: unicast OR broadcast AND crc valid AND Full Duplex */ + + enc_wrbreg(priv, ENC_MACON3, + MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX); + + /* Set Non-Back-to-Back Inter-Packet Gap */ + + enc_wrbreg(priv, ENC_MAIPGL, 0x12); + + /* Set ack-to-Back Inter-Packet Gap */ + + enc_wrbreg(priv, ENC_MABBIPG, 0x15); +#endif + + /* Set the maximum packet size which the controller will accept */ + + enc_wrbreg(priv, ENC_MAMXFLL, CONFIG_NET_BUFSIZE & 0xff); + enc_wrbreg(priv, ENC_MAMXFLH, CONFIG_NET_BUFSIZE >> 8); + + /* Configure LEDs (No, just use the defaults for now) */ + /* enc_wrphy(priv, ENC_PHLCON, ??); */ + + /* Setup up PHCON1 & 2 */ + +#ifdef CONFIG_ENC28J60_HALFDUPLEX + enc_wrphy(priv, ENC_PHCON1, 0x00); + enc_wrphy(priv, ENC_PHCON2, PHCON2_HDLDIS); +#else + enc_wrphy(priv, ENC_PHCON1, PHCON1_PDPXMD); + enc_wrphy(priv, ENC_PHCON2, 0x00); +#endif + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: enc_initialize + * + * Description: + * Initialize the Ethernet driver. The ENC28J60 device is assumed to be + * in the post-reset state upon entry to this function. + * + * Parameters: + * spi - A reference to the platform's SPI driver for the ENC28J60 + * devno - If more than one ENC28J60 is supported, then this is the + * zero based number that identifies the ENC28J60; + * irq - The fully configured GPIO IRQ that ENC28J60 interrupts will be + * asserted on. This driver will attach and entable this IRQ. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +int enc_initialize(FAR struct spi_dev_s *spi, unsigned int devno, unsigned int irq) +{ + FAR struct enc_driver_s *priv ; + int ret; + + DEBUGASSERT(devno < CONFIG_ENC28J60_NINTERFACES); + priv = &g_enc28j60[devno]; + + /* Initialize the driver structure */ + + memset(g_enc28j60, 0, CONFIG_ENC28J60_NINTERFACES*sizeof(struct enc_driver_s)); + priv->dev.d_ifup = enc_ifup; /* I/F down callback */ + priv->dev.d_ifdown = enc_ifdown; /* I/F up (new IP address) callback */ + priv->dev.d_txavail = enc_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_IGMP + priv->dev.d_addmac = enc_addmac; /* Add multicast MAC address */ + priv->dev.d_rmmac = enc_rmmac; /* Remove multicast MAC address */ +#endif + priv->dev.d_private = priv; /* Used to recover private state from dev */ + + /* Create a watchdog for timing polling for and timing of transmisstions */ + + priv->txpoll = wd_create(); /* Create periodic poll timer */ + priv->txtimeout = wd_create(); /* Create TX timeout timer */ + priv->spi = spi; /* Save the SPI instance */ + priv->irq = irq; /* Save the IRQ number */ + + /* Make sure that the interface is in the down state. NOTE: The MAC + * address will not be set up until ifup. That gives the app time to set + * the MAC address before bringing the interface up. + */ + + ret = enc_ifdown(&priv->dev); + if (ret == OK) + { + /* Attach the IRQ to the driver (but don't enable it yet) */ + + if (irq_attach(irq, enc_interrupt)) + { + /* We could not attach the ISR to the interrupt */ + + ret = -EAGAIN; + } + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + (void)netdev_register(&priv->dev); + } + return ret; +} + +/**************************************************************************** + * Function: enc_stats + * + * Description: + * Return accumulated ENC28J60 statistics. Statistics are cleared after + * being returned. + * + * Parameters: + * devno - If more than one ENC28J60 is supported, then this is the + * zero based number that identifies the ENC28J60; + * stats - The user-provided location to return the statistics. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_ENC28J60_STATS +int enc_stats(unsigned int devno, struct enc_stats_s *stats) +{ + FAR struct enc_driver_s *priv ; + irqstate_t flags; + + DEBUGASSERT(devno < CONFIG_ENC28J60_NINTERFACES); + priv = &g_enc28j60[devno]; + + /* Disable the Ethernet interrupt */ + + flags = irqsave(); + memcpy(stats, &priv->stats, sizeof(struct enc_stats_s)); + memset(&priv->stats, 0, sizeof(struct enc_stats_s)); + irqrestore(flags); + return OK; +} +#endif +#endif /* CONFIG_NET && CONFIG_ENC28J60_NET */ + diff --git a/nuttx/drivers/net/enc28j60.h b/nuttx/drivers/net/enc28j60.h new file mode 100644 index 0000000000..408224b22d --- /dev/null +++ b/nuttx/drivers/net/enc28j60.h @@ -0,0 +1,478 @@ +/**************************************************************************** + * drivers/net/enc28j60.h + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * - ENC28J60 Data Sheet, Stand-Alone Ethernet Controller with SPI Interface, + * DS39662C, 2008 Microchip Technology Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_NET_ENC28J60_H +#define __DRIVERS_NET_ENC28J60_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* ENC28J60 Commands ********************************************************/ +/* A total of seven instructions are implemented on the ENC28J60. Where: + * + * aaaaaa is the 5-bit address of a control register, and + * dddddddd is one or more bytes of data that may accompany the command. + */ + +#define ENC_RCR (0x00) /* Read Control Register + * 000 | aaaaa | (Registe value returned)) */ +#define ENC_RBM (0x3a) /* Read Buffer Memory + * 001 | 11010 | (Read buffer data follows) */ +#define ENC_WCR (0x40) /* Write Control Register + * 010 | aaaaa | dddddddd */ +#define ENC_WBM (0x7a) /* Write Buffer Memory + * 011 | 11010 | (Write buffer data follows) */ +#define ENC_BFS (0x80) /* Bit Field Set + * 100 | aaaaa | dddddddd */ +#define ENC_BFC (0xa0) /* Bit Field Clear + * 101 | aaaaa | dddddddd */ +#define ENC_SRC (0xff) /* System Reset + * 111 | 11111 | (No data) */ + +/* Global Control Registers *************************************************/ +/* Control registers are accessed with the RCR, RBM, WCR, BFS, and BFC + * commands. The following identifies all ENC28J60 control registers. The + * control register memory is partitioned into four banks, selectable by the + * bank select bits, BSEL1:BSEL0, in the ECON1 register. + * + * The last five locations (0x1b to 0x1f) of all banks point to a common set + * of registers: EIE, EIR, ESTAT, ECON2 and ECON1. These are key registers + * usedin controlling and monitoring the operation of the device. Their + * common mapping allows easy access without switching the bank. + * + * Control registers for the ENC28J60 are generically grouped as ETH, MAC and + * MII registers. Register names starting with E belong to the ETH group. + * Similarly, registers names starting with MA belong to the MAC group and + * registers prefixed with MI belong to the MII group. + */ + +#define ENC_EIE (0x1b) /* Ethernet Interrupt Enable Register */ +#define ENC_EIR (0x1c) /* Ethernet Interupt Request Register */ +#define ENC_ESTAT (0x1d) /* Ethernet Status Register */ +#define ENC_ECON2 (0x1e) /* Ethernet Control 2 Register */ +#define ENC_ECON1 (0x1f) /* Ethernet Control 1 Register */ + +/* Ethernet Interrupt Enable Register Bit Definitions */ + +#define EIE_RXERIE (1 << 0) /* Bit 0: Receive Error Interrupt Enable */ +#define EIE_TXERIE (1 << 1) /* Bit 1: Transmit Error Interrupt Enable */ + /* Bit 2: Reserved */ +#define EIE_TXIE (1 << 3) /* Bit 3: Transmit Enable */ +#define EIE_LINKIE (1 << 4) /* Bit 4: Link Status Change Interrupt Enable */ +#define EIE_DMAIE (1 << 5) /* Bit 5: DMA Interrupt Enable */ +#define EIE_PKTIE (1 << 6) /* Bit 6: Receive Packet Pending Interrupt Enable */ +#define EIE_INTIE (1 << 7) /* Bit 7: Global INT Interrupt Enable */ + +/* Ethernet Interrupt Request Register Bit Definitions */ + +#define EIR_RXERIF (1 << 0) /* Bit 0: Receive Error Interrupt */ +#define EIR_TXERIF (1 << 1) /* Bit 1: Transmit Error Interrupt */ + /* Bit 2: Reserved */ +#define EIR_TXIF (1 << 3) /* Bit 3: Transmit Interrupt */ +#define EIR_LINKIF (1 << 4) /* Bit 4: Link Change Interrupt */ +#define EIR_DMAIF (1 << 5) /* Bit 5: DMA Interrupt */ +#define EIR_PKTIF (1 << 6) /* Bit 6: Receive Packet Pending Interrupt */ + /* Bit 7: Reserved */ +#define EIR_ALLINTS (0x7b) /* All interrupts */ + +/* Ethernet Status Register Bit Definitions */ + +#define ESTAT_CLKRDY (1 << 0) /* Bit 0: Clock Ready */ +#define ESTAT_TXABRT (1 << 1) /* Bit 1: Transmit Abort Error */ +#define ESTAT_RXBUSY (1 << 2) /* Bit 2: Receive Busy */ + /* Bit 3: Reserved */ +#define ESTAT_LATECOL (1 << 4) /* Bit 4: Late Collision Error */ + /* Bit 5: Reserved */ +#define ESTAT_BUFER (1 << 6) /* Bit 6: Ethernet Buffer Error Status */ +#define ESTAT_INT (1 << 7) /* Bit 7: INT Interrupt */ + +/* Ethernet Control 1 Register Bit Definitions */ + +#define ECON1_BSEL_SHIFT (0) /* Bits 0-1: Bank select */ +#define ECON1_BSEL_MASK (3 << ECON1_BSEL_SHIFT) +# define ECON1_BSEL_BANK0 (0 << 0) /* Bank 0 */ +# define ECON1_BSEL_BANK1 (1 << 1) /* Bank 1 */ +# define ECON1_BSEL_BANK2 (2 << 0) /* Bank 2 */ +# define ECON1_BSEL_BANK3 (3 << 0) /* Bank 3 */ +#define ECON1_RXEN (1 << 2) /* Bit 2: Receive Enable */ +#define ECON1_TXRTS (1 << 3) /* Bit 3: Transmit Request to Send */ +#define ECON1_CSUMEN (1 << 4) /* Bit 4: DMA Checksum Enable */ +#define ECON1_DMAST (1 << 5) /* Bit 5: DMA Start and Busy Status */ +#define ECON1_RXRST (1 << 6) /* Bit 6: Receive Logic Reset */ +#define ECON1_TXRST (1 << 7) /* Bit 7: Transmit Logic Reset */ + +/* Ethernet Control 2 Register */ + /* Bits 0-2: Reserved */ +#define ECON2_VRPS (1 << 3) /* Bit 3: Voltage Regulator Power Save Enable */ + /* Bit 4: Reserved */ +#define ECON2_PWRSV (1 << 5) /* Bit 5: Power Save Enable */ +#define ECON2_PKTDEC (1 << 6) /* Bit 6: Packet Decrement */ +#define ECON2_AUTOINC (1 << 7) /* Bit 7: Automatic Buffer Pointer Increment Enable */ + +/* Banked Control Registers *************************************************/ +/* The remaining control registers are identified with a a 5 bit address and + * a bank selection. We pack the bank number and an indication if this is + * a MAC/PHY register access together with the control register address + * together to keep the design simpler. + */ + +#define ENC_ADDR_SHIFT (0) /* Bits 0-4: Register address */ +#define ENC_ADDR_MASK (0x1f << ENC_ADDR_SHIFT) +#define ENC_BANK_SHIFT (5) /* Bits 5-6: Bank number */ +#define ENC_BANK_MASK (3 << ENC_BSEL_SHIFT) +# define ENC_BANK0 (0 << ENC_BSEL_SHIFT) +# define ENC_BANK1 (1 << ENC_BSEL_SHIFT) +# define ENC_BANK2 (2 << ENC_BSEL_SHIFT) +# define ENC_BANK3 (3 << ENC_BSEL_SHIFT) +#define ENC_PHYMAC_SHIFT (7) /* Bit 7: This is a PHY/MAC command */ +#define ENC_PHYMAC (1 << ENC_PHYMAC_SHIFT) + +#define REGADDR(a,b,m) ((m) << ENC_PHYMAC_SHIFT | (b) << ENC_BANK_SHIFT | (a)) +#define GETADDR(a) ((a) & ENC_ADDR_MASK) +#define GETBANK(a) (((a) >> ENC_BANK_SHIFT) & 3) +#define ISPHYMAC(a) (((a) & ENC_PHYMAC) != 0) + +/* Bank 0 Control Register Addresses */ + +#define ENC_ERDPTL REGADDR(0x00, 0, 0) /* Read Pointer Low Byte (ERDPT<7:0> */ +#define ENC_ERDPTH REGADDR(0x01, 0, 0) /* Read Pointer High Byte (ERDPT<12:8>) */ +#define ENC_EWRPTL REGADDR(0x02, 0, 0) /* Write Pointer Low Byte (EWRPT<7:0>) */ +#define ENC_EWRPTH REGADDR(0x03, 0, 0) /* Write Pointer High Byte (EWRPT<12:8>) */ +#define ENC_ETXSTL REGADDR(0x04, 0, 0) /* TX Start Low Byte (ETXST<7:0>) */ +#define ENC_ETXSTH REGADDR(0x05, 0, 0) /* TX Start High Byte (ETXST<12:8>) */ +#define ENC_ETXNDL REGADDR(0x06, 0, 0) /* TX End Low Byte (ETXND<7:0>) */ +#define ENC_ETXNDH REGADDR(0x07, 0, 0) /* TX End High Byte (ETXND<12:8>) */ +#define ENC_ERXSTL REGADDR(0x08, 0, 0) /* RX Start Low Byte (ERXST<7:0>) */ +#define ENC_ERXSTH REGADDR(0x09, 0, 0) /* RX Start High Byte (ERXST<12:8>) */ +#define ENC_ERXNDL REGADDR(0x0a, 0, 0) /* RX End Low Byte (ERXND<7:0>) */ +#define ENC_ERXNDH REGADDR(0x0b, 0, 0) /* RX End High Byte (ERXND<12:8>) */ +#define ENC_ERXRDPTL REGADDR(0x0c, 0, 0) /* RX RD Pointer Low Byte (ERXRDPT<7:0>) */ +#define ENC_ERXRDPTH REGADDR(0x0d, 0, 0) /* RX RD Pointer High Byte (ERXRDPT<12:8>) */ +#define ENC_ERXWRPTL REGADDR(0x0e, 0, 0) /* RX WR Pointer Low Byte (ERXWRPT<7:0>) */ +#define ENC_ERXWRPTH REGADDR(0x0f, 0, 0) /* RX WR Pointer High Byte (ERXWRPT<12:8>) */ +#define ENC_EDMASTL REGADDR(0x10, 0, 0) /* DMA Start Low Byte (EDMAST<7:0>) */ +#define ENC_EDMASTH REGADDR(0x11, 0, 0) /* DMA Start High Byte (EDMAST<12:8>) */ +#define ENC_EDMANDL REGADDR(0x12, 0, 0) /* DMA End Low Byte (EDMAND<7:0>) */ +#define ENC_EDMANDH REGADDR(0x13, 0, 0) /* DMA End High Byte (EDMAND<12:8>) */ +#define ENC_EDMADSTL REGADDR(0x14, 0, 0) /* DMA Destination Low Byte (EDMADST<7:0>) */ +#define ENC_EDMADSTH REGADDR(0x15, 0, 0) /* DMA Destination High Byte (EDMADST<12:8>) */ +#define ENC_EDMACSL REGADDR(0x16, 0, 0) /* DMA Checksum Low Byte (EDMACS<7:0>) */ +#define ENC_EDMACSH REGADDR(0x17, 0, 0) /* DMA Checksum High Byte (EDMACS<15:8>) */ + /* 0x18-0x1a: Reserved */ + /* 0x1b-0x1f: EIE, EIR, ESTAT, ECON2, ECON1 */ +/* Bank 1 Control Register Addresses */ + +#define ENC_EHT0 REGADDR(0x00, 1, 0) /* Hash Table Byte 0 (EHT<7:0>) */ +#define ENC_EHT1 REGADDR(0x01, 1, 0) /* Hash Table Byte 1 (EHT<15:8>) */ +#define ENC_EHT2 REGADDR(0x02, 1, 0) /* Hash Table Byte 2 (EHT<23:16>) */ +#define ENC_EHT3 REGADDR(0x03, 1, 0) /* Hash Table Byte 3 (EHT<31:24>) */ +#define ENC_EHT4 REGADDR(0x04, 1, 0) /* Hash Table Byte 4 (EHT<39:32>) */ +#define ENC_EHT5 REGADDR(0x05, 1, 0) /* Hash Table Byte 5 (EHT<47:40>) */ +#define ENC_EHT6 REGADDR(0x06, 1, 0) /* Hash Table Byte 6 (EHT<55:48>) */ +#define ENC_EHT7 REGADDR(0x07, 1, 0) /* Hash Table Byte 7 (EHT<63:56>) */ +#define ENC_EPMM0 REGADDR(0x08, 1, 0) /* Pattern Match Mask Byte 0 (EPMM<7:0>) */ +#define ENC_EPMM1 REGADDR(0x09, 1, 0) /* Pattern Match Mask Byte 1 (EPMM<15:8>) */ +#define ENC_EPMM2 REGADDR(0x0a, 1, 0) /* Pattern Match Mask Byte 2 (EPMM<23:16>) */ +#define ENC_EPMM3 REGADDR(0x0b, 1, 0) /* Pattern Match Mask Byte 3 (EPMM<31:24>) */ +#define ENC_EPMM4 REGADDR(0x0c, 1, 0) /* Pattern Match Mask Byte 4 (EPMM<39:32>) */ +#define ENC_EPMM5 REGADDR(0x0d, 1, 0) /* Pattern Match Mask Byte 5 (EPMM<47:40>) */ +#define ENC_EPMM6 REGADDR(0x0e, 1, 0) /* Pattern Match Mask Byte 6 (EPMM<55:48>) */ +#define ENC_EPMM7 REGADDR(0x0f, 1, 0) /* Pattern Match Mask Byte 7 (EPMM<63:56>) */ +#define ENC_EPMCSL REGADDR(0x10, 1, 0) /* Pattern Match Checksum Low Byte (EPMCS<7:0>) */ +#define ENC_EPMCSH REGADDR(0x11, 1, 0) /* Pattern Match Checksum High Byte (EPMCS<15:0>) */ + /* 0x12-0x13: Reserved */ +#define ENC_EPMOL REGADDR(0x14, 1, 0) /* Pattern Match Offset Low Byte (EPMO<7:0>) */ +#define ENC_EPMOH REGADDR(0x15, 1, 0) /* Pattern Match Offset High Byte (EPMO<12:8>) */ + /* 0x16-0x17: Reserved */ +#define ENC_ERXFCON REGADDR(0x18, 1, 0) /* Receive Filter Configuration */ +#define ENC_EPKTCNT REGADDR(0x19, 1, 0) /* Ethernet Packet Count */ + /* 0x1a: Reserved */ + /* 0x1b-0x1f: EIE, EIR, ESTAT, ECON2, ECON1 */ + +/* Receive Filter Configuration Bit Definitions */ + +#define ERXFCON_BCEN (1 << 0) /* Bit 0: Broadcast Filter Enable */ +#define ERXFCON_MCEN (1 << 1) /* Bit 1: Multicast Filter Enable */ +#define ERXFCON_HTEN (1 << 2) /* Bit 2: Hash Table Filter Enable */ +#define ERXFCON_MPEN (1 << 3) /* Bit 3: Magic Packet Filter Enable */ +#define ERXFCON_PMEN (1 << 4) /* Bit 4: Pattern Match Filter Enable */ +#define ERXFCON_CRCEN (1 << 5) /* Bit 5: Post-Filter CRC Check Enable */ +#define ERXFCON_ANDOR (1 << 6) /* Bit 6: AND/OR Filter Select */ +#define ERXFCON_UCEN (1 << 7) /* Bit 7: Unicast Filter Enable */ + +/* Bank 2 Control Register Addresses */ + +#define ENC_MACON1 REGADDR(0x00, 2, 1) /* MAC Control 1 */ + /* 0x01: Reserved */ +#define ENC_MACON3 REGADDR(0x02, 2, 1) /* MAC Control 3 */ +#define ENC_MACON4 REGADDR(0x03, 2, 1) /* MAC Control 4 */ +#define ENC_MABBIPG REGADDR(0x04, 2, 1) /* Back-to-Back Inter-Packet Gap (BBIPG<6:0>) */ + /* 0x05: Reserved */ +#define ENC_MAIPGL REGADDR(0x06, 2, 1) /* Non-Back-to-Back Inter-Packet Gap Low Byte (MAIPGL<6:0>) */ +#define ENC_MAIPGH REGADDR(0x07, 2, 1) /* Non-Back-to-Back Inter-Packet Gap High Byte (MAIPGH<6:0>) */ +#define ENC_MACLCON1 REGADDR(0x08, 2, 1) /* MAC Collision Control 1 */ +#define ENC_MACLCON2 REGADDR(0x09, 2, 1) /* MAC Collision Control 2 */ +#define ENC_MAMXFLL REGADDR(0x0a, 2, 1) /* Maximum Frame Length Low Byte (MAMXFL<7:0>) */ +#define ENC_MAMXFLH REGADDR(0x0b, 2, 1) /* Maximum Frame Length High Byte (MAMXFL<15:8>) */ + /* 0x0c-0x11: Reserved */ +#define ENC_MICMD REGADDR(0x12, 2, 1) /* MII Command Register */ + /* 0x13: Reserved */ +#define ENC_MIREGADR REGADDR(0x14, 2, 1) /* MII Register Address */ + /* 0x15: Reserved */ +#define ENC_MIWRL REGADDR(0x16, 2, 1) /* MII Write Data Low Byte (MIWR<7:0>) */ +#define ENC_MIWRH REGADDR(0x17, 2, 1) /* MII Write Data High Byte (MIWR<15:8>) */ +#define ENC_MIRDL REGADDR(0x18, 2, 1) /* MII Read Data Low Byte (MIRD<7:0>) */ +#define ENC_MIRDH REGADDR(0x19, 2, 1) /* MII Read Data High Byte(MIRD<15:8>) */ + /* 0x1a: Reserved */ + /* 0x1b-0x1f: EIE, EIR, ESTAT, ECON2, ECON1 */ + +/* MAC Control 1 Register Bit Definitions */ + +#define MACON1_MARXEN (1 << 0) /* Bit 0: MAC Receive Enable */ +#define MACON1_PASSALL (1 << 1) /* Bit 1: Pass All Received Frames Enable */ +#define MACON1_RXPAUS (1 << 2) /* Bit 2: Pause Control Frame Reception Enable */ +#define MACON1_TXPAUS (1 << 3) /* Bit 3: Pause Control Frame Transmission Enable */ + /* Bits 4-7: Unimplemented or reserved */ + +/* MAC Control 1 Register Bit Definitions */ + +#define MACON3_FULDPX (1 << 0) /* Bit 0: MAC Full-Duplex Enable */ +#define MACON3_FRMLNEN (1 << 1) /* Bit 1: Frame Length Checking Enable */ +#define MACON3_HFRMLEN (1 << 2) /* Bit 2: Huge Frame Enable */ +#define MACON3_PHDRLEN (1 << 3) /* Bit 3: Proprietary Header Enable */ +#define MACON3_TXCRCEN (1 << 4) /* Bit 4: Transmit CRC Enable */ +#define MACON3_PADCFG0 (1 << 5) /* Bit 5: Automatic Pad and CRC Configuration */ +#define MACON3_PADCFG1 (1 << 6) /* Bit 6: " " " " " " " " " " */ +#define MACON3_PADCFG2 (1 << 7) /* Bit 7: " " " " " " " " " " */ + +/* MAC Control 1 Register Bit Definitions */ + +#define MACON4_NOBKOFF (1 << 4) /* Bit 4: No Backoff Enable */ +#define MACON4_BPEN (1 << 5) /* Bit 5: No Backoff During Backpressure Enable */ +#define MACON4_DEFER (1 << 6) /* Bit 6: Defer Transmission Enable bit */ + +/* MII Command Register Bit Definitions */ + +#define MICMD_MIIRD (1 << 0) /* Bit 0: MII Read Enable */ +#define MICMD_MIISCAN (1 << 1) /* Bit 1: MII Scan Enable */ + +/* Bank 3 Control Register Addresses */ + +#define ENC_MAADR5 REGADDR(0x00, 3, 1) /* MAC Address Byte 5 (MAADR<15:8>) */ +#define ENC_MAADR6 REGADDR(0x01, 3, 1) /* MAC Address Byte 6 (MAADR<7:0>) */ +#define ENC_MAADR3 REGADDR(0x02, 3, 1) /* MAC Address Byte 3 (MAADR<31:24>), OUI Byte 3 */ +#define ENC_MAADR4 REGADDR(0x03, 3, 1) /* MAC Address Byte 4 (MAADR<23:16>) */ +#define ENC_MAADR1 REGADDR(0x04, 3, 1) /* MAC Address Byte 1 (MAADR<47:40>), OUI Byte 1 */ +#define ENC_MAADR2 REGADDR(0x05, 3, 1) /* MAC Address Byte 2 (MAADR<39:32>), OUI Byte */ +#define ENC_EBSTSD REGADDR(0x06, 3, 0) /* Built-in Self-Test Fill Seed (EBSTSD<7:0>) */ +#define ENC_EBSTCON REGADDR(0x07, 3, 0) /* Built-in Self-Test Control */ +#define ENC_EBSTCSL REGADDR(0x08, 3, 0) /* Built-in Self-Test Checksum Low Byte (EBSTCS<7:0>) */ +#define ENC_EBSTCSH REGADDR(0x09, 3, 0) /* Built-in Self-Test Checksum High Byte (EBSTCS<15:8>) */ +#define ENC_MISTAT REGADDR(0x0a, 3, 1) /* MII Status Register */ + /* 0x0b-0x11: Reserved */ +#define ENC_EREVID REGADDR(0x12, 3, 0) /* Ethernet Revision ID */ + /* 0x13-0x14: Reserved */ +#define ENC_ECOCON REGADDR(0x15, 3, 0) /* Clock Output Control */ + /* 0x16: Reserved */ +#define ENC_EFLOCON REGADDR(0x17, 3, 0) /* Ethernet Flow Control */ +#define ENC_EPAUSL REGADDR(0x18, 3, 0) /* Pause Timer Value Low Byte (EPAUS<7:0>) */ +#define ENC_EPAUSH REGADDR(0x19, 3, 0) /* Pause Timer Value High Byte (EPAUS<15:8>) */ + /* 0x1a: Reserved */ + /* 0x1b-0x1f: EIE, EIR, ESTAT, ECON2, ECON1 */ + +/* Built-in Self-Test Control Register Bit Definitions */ + +#define EBSTCON_BISTST (1 << 0) /* Bit 0: Built-in Self-Test Start/Busy */ +#define EBSTCON_TME (1 << 1) /* Bit 1: Test Mode Enable */ +#define EBSTCON_TMSEL0 (1 << 2) /* Bit 2: Test Mode Select */ +#define EBSTCON_TMSEL1 (1 << 3) /* Bit 3: " " " " " " */ +#define EBSTCON_PSEL (1 << 4) /* Bit 4: Port Select */ +#define EBSTCON_PSV0 (1 << 5) /* Bit 5: Pattern Shift Value */ +#define EBSTCON_PSV1 (1 << 6) /* Bit 6: " " " " " */ +#define EBSTCON_PSV2 (1 << 7) /* Bit 7: " " " " " */ + +/* MII Status Register Register Bit Definitions */ + +#define MISTAT_BUSY (1 << 0) /* Bit 0: MII Management Busy */ +#define MISTAT_SCAN (1 << 1) /* Bit 1: MII Management Scan Operation */ +#define MISTAT_NVALID (1 << 2) /* Bit 2: MII Management Read Data Not Valid */ + /* Bits 3-7: Reserved or unimplemented */ + +/* Ethernet Flow Control Register Bit Definitions */ + +#define EFLOCON_FCEN0 (1 << 0) /* Bit 0: Flow Control Enable */ +#define EFLOCON_FCEN1 (1 << 1) /* Bit 1: " " " " " " */ +#define EFLOCON_FULDPXS (1 << 2) /* Bit 2: Read-Only MAC Full-Duplex Shadow */ + /* Bits 3-7: Reserved or unimplemented */ + +/* PHY Registers ************************************************************/ + +#define ENC_PHCON1 (0x00) /* PHY Control Register 1 */ +#define ENC_PHSTAT1 (0x01) /* PHY Status 1 */ +#define ENC_PHID1 (0x02) /* PHY ID Register 1 */ +#define ENC_PHID2 (0x03) /* PHY ID Register 2 */ +#define ENC_PHCON2 (0x10) /* PHY Control Register 2 */ +#define ENC_PHSTAT2 (0x11) /* PHY Status 2 */ +#define ENC_PHIE (0x12) /* PHY Interrupt Enable Register */ +#define ENC_PHIR (0x13) /* PHY Interrupt Request Register */ +#define ENC_PHLCON (0x14) + +/* PHY Control Register 1 Register Bit Definitions */ + +#define PHCON1_PDPXMD (1 << 8) /* Bit 8: PHY Power-Down */ +#define PHCON1_PPWRSV (1 << 11) /* Bit 11: PHY Power-Down */ +#define PHCON1_PLOOPBK (1 << 14) /* Bit 14: PHY Loopback */ +#define PHCON1_PRST (1 << 15) /* Bit 15: PHY Software Reset */ + +/* HY Status 1 Register Bit Definitions */ + +#define PHSTAT1_JBSTAT (1 << 1) /* Bit 1: PHY Latching Jabber Status */ +#define PHSTAT1_LLSTAT (1 << 2) /* Bit 2: PHY Latching Link Status */ +#define PHSTAT1_PHDPX (1 << 11) /* Bit 11: PHY Half-Duplex Capable */ +#define PHSTAT1_PFDPX (1 << 12) /* Bit 12: PHY Full-Duplex Capable */ + +/* PHY Control Register 2 Register Bit Definitions */ + +#define PHCON2_HDLDIS (1 << 8) /* Bit 8: PHY Half-Duplex Loopback Disable */ +#define PHCON2_JABBER (1 << 10) /* Bit 10: Jabber Correction Disable */ +#define PHCON2_TXDIS (1 << 13) /* Bit 13: Twisted-Pair Transmitter Disable */ +#define PHCON2_FRCLINK (1 << 14) /* Bit 14: PHY Force Linkup */ + +/* PHY Status 2 Register Bit Definitions */ + +#define PHSTAT2_PLRITY (1 << 5) /* Bit 5: Polarity Status */ +#define PHSTAT2_DPXSTAT (1 << 9) /* Bit 9: PHY Duplex Status */ +#define PHSTAT2_LSTAT (1 << 10) /* Bit 10: PHY Link Status */ +#define PHSTAT2_COLSTAT (1 << 11) /* Bit 11: PHY Collision Status */ +#define PHSTAT2_RXSTAT (1 << 12) /* Bit 12: PHY Receive Status */ +#define PHSTAT2_TXSTAT (1 << 13) /* Bit 13: PHY Transmit Status */ + +/* PHY Interrupt Enable Register Bit Definitions */ + +#define PHIE_PGEIE (1 << 1) /* Bit 1: PHY Global Interrupt Enable */ +#define PHIE_PLNKIE (1 << 4) /* Bit 4: PHY Link Change Interrupt Enable */ + +/* PHIR Regiser Bit Definitions */ + +#define PHIR_PGIF (1 << 2) /* Bit 2: PHY Global Interrupt */ +#define PHIR_PLNKIF (1 << 4) /* Bit 4: PHY Link Change Interrupt */ + +/* PHLCON Regiser Bit Definitions */ + + /* Bit 0: Reserved */ +#define PHLCON_STRCH (1 << 1) /* Bit 1: LED Pulse Stretching Enable */ +#define PHLCON_LFRQ0 (1 << 2) /* Bit 2: LED Pulse Stretch Time Configuration */ +#define PHLCON_LFRQ1 (1 << 3) /* Bit 3: " " " " " " " " " */ +#define PHLCON_LBCFG0 (1 << 4) /* Bit 4: LEDB Configuration */ +#define PHLCON_LBCFG1 (1 << 5) /* Bit 5: " " " " */ +#define PHLCON_LBCFG2 (1 << 6) /* Bit 6: " " " " */ +#define PHLCON_LBCFG3 (1 << 7) /* Bit 7: " " " " */ +#define PHLCON_LACFG0 (1 << 8) /* Bit 8: LEDA Configuration */ +#define PHLCON_LACFG1 (1 << 9) /* Bit 9: " " " " */ +#define PHLCON_LACFG2 (1 << 10) /* Bit 10: " " " " */ +#define PHLCON_LACFG3 (1 << 11) /* Bit 11: " " " " */ + +/* Packet Memory ************************************************************/ + +/* 8-Kbyte Transmit/Receive Packet Dual Port SRAM */ + +#define PKTMEM_START 0x0000 +#define PKTMEM_END 0x1fff + +/* Ethernet frames are between 64 and 1518 bytes long */ + +#define MIN_FRAMELEN 64 +#define MAX_FRAMELEN 1518 + +/* Packet Control Bits Definitions ******************************************/ + +#define PKTCTRL_POVERRIDE (1 << 0) /* Bit 0: Per Packet Override */ +#define PKTCTRL_PCRCEN (1 << 1) /* Bit 1: Per Packet CRC Enable */ +#define PKTCTRL_PPADEN (1 << 2) /* Bit 2: Per Packet Padding Enable */ +#define PKTCTRL_PHUGEEN (1 << 3) /* Bit 3: Per Packet Huge Frame Enable */ + +/* RX Status Bit Definitions ************************************************/ + +#define RXSTAT_LDEVENT (1 << 0) /* Bit 0: Long event or pack dropped */ + /* Bit 1: Reserved */ +#define RXSTAT_CEPS (1 << 2) /* Bit 2: Carrier event previously seen */ + /* Bit 3: Reserved */ +#define RXSTAT_CRCERROR (1 << 4) /* Bit 4: Frame CRC field bad */ +#define RXSTAT_LENERROR (1 << 5) /* Bit 5: Packet length != data length */ +#define RXSTAT_LENRANGE (1 << 6) /* Bit 6: Type/length field > 1500 bytes */ +#define RXSTAT_OK (1 << 7) /* Bit 7: Packet with valid CRC and no symbol errors */ +#define RXSTAT_MCAST (1 << 8) /* Bit 8: Packet with multicast address */ +#define RXSTAT_BCAST (1 << 9) /* Bit 9: Packet with broadcast address */ +#define RXSTAT_DRIBBLE (1 << 10) /* Bit 10: Additional bits received after packet */ +#define RXSTAT_CTRLFRAME (1 << 11) /* Bit 11: Control frame with valid type/length */ +#define RXSTAT_PAUSE (1 << 12) /* Bit 12: Control frame with pause frame opcde */ +#define RXSTAT_UNKOPCODE (1 << 13) /* Bit 13: Control frame with unknown opcode */ +#define RXSTAT_VLANTYPE (1 << 14) /* Bit 14: Current frame is a VLAN tagged frame */ + /* Bit 15: Zero */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __DRIVERS_NET_ENC28J60_H */ diff --git a/nuttx/drivers/net/skeleton.c b/nuttx/drivers/net/skeleton.c new file mode 100644 index 0000000000..00ebea35f0 --- /dev/null +++ b/nuttx/drivers/net/skeleton.c @@ -0,0 +1,692 @@ +/**************************************************************************** + * drivers/net/skeleton.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_skeleton) + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* CONFIG_skeleton_NINTERFACES determines the number of physical interfaces + * that will be supported. + */ + +#ifndef CONFIG_skeleton_NINTERFACES +# define CONFIG_skeleton_NINTERFACES 1 +#endif + +/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per second */ + +#define skeleton_WDDELAY (1*CLK_TCK) +#define skeleton_POLLHSEC (1*2) + +/* TX timeout = 1 minute */ + +#define skeleton_TXTIMEOUT (60*CLK_TCK) + +/* This is a helper pointer for accessing the contents of the Ethernet header */ + +#define BUF ((struct uip_eth_hdr *)skel->sk_dev.d_buf) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The skel_driver_s encapsulates all state information for a single hardware + * interface + */ + +struct skel_driver_s +{ + bool sk_bifup; /* true:ifup false:ifdown */ + WDOG_ID sk_txpoll; /* TX poll timer */ + WDOG_ID sk_txtimeout; /* TX timeout timer */ + + /* This holds the information visible to uIP/NuttX */ + + struct uip_driver_s sk_dev; /* Interface understood by uIP */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct skel_driver_s g_skel[CONFIG_skeleton_NINTERFACES]; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Common TX logic */ + +static int skel_transmit(FAR struct skel_driver_s *skel); +static int skel_uiptxpoll(struct uip_driver_s *dev); + +/* Interrupt handling */ + +static void skel_receive(FAR struct skel_driver_s *skel); +static void skel_txdone(FAR struct skel_driver_s *skel); +static int skel_interrupt(int irq, FAR void *context); + +/* Watchdog timer expirations */ + +static void skel_polltimer(int argc, uint32_t arg, ...); +static void skel_txtimeout(int argc, uint32_t arg, ...); + +/* NuttX callback functions */ + +static int skel_ifup(struct uip_driver_s *dev); +static int skel_ifdown(struct uip_driver_s *dev); +static int skel_txavail(struct uip_driver_s *dev); +#ifdef CONFIG_NET_IGMP +static int skel_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +static int skel_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: skel_transmit + * + * Description: + * Start hardware transmission. Called either from the txdone interrupt + * handling or from watchdog based polling. + * + * Parameters: + * skel - Reference to the driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int skel_transmit(FAR struct skel_driver_s *skel) +{ + /* Verify that the hardware is ready to send another packet. If we get + * here, then we are committed to sending a packet; Higher level logic + * must have assured that there is no transmission in progress. + */ + + /* Increment statistics */ + + /* Send the packet: address=skel->sk_dev.d_buf, length=skel->sk_dev.d_len */ + + /* Enable Tx interrupts */ + + /* Setup the TX timeout watchdog (perhaps restarting the timer) */ + + (void)wd_start(skel->sk_txtimeout, skeleton_TXTIMEOUT, skel_txtimeout, 1, (uint32_t)skel); + return OK; +} + +/**************************************************************************** + * Function: skel_uiptxpoll + * + * Description: + * The transmitter is available, check if uIP has any outgoing packets ready + * to send. This is a callback from uip_poll(). uip_poll() may be called: + * + * 1. When the preceding TX packet send is complete, + * 2. When the preceding TX packet send timesout and the interface is reset + * 3. During normal TX polling + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int skel_uiptxpoll(struct uip_driver_s *dev) +{ + FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)dev->d_private; + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (skel->sk_dev.d_len > 0) + { + uip_arp_out(&skel->sk_dev); + skel_transmit(skel); + + /* Check if there is room in the device to hold another packet. If not, + * return a non-zero value to terminate the poll. + */ + } + + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + + return 0; +} + +/**************************************************************************** + * Function: skel_receive + * + * Description: + * An interrupt was received indicating the availability of a new RX packet + * + * Parameters: + * skel - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void skel_receive(FAR struct skel_driver_s *skel) +{ + do + { + /* Check for errors and update statistics */ + + /* Check if the packet is a valid size for the uIP buffer configuration */ + + /* Copy the data data from the hardware to skel->sk_dev.d_buf. Set + * amount of data in skel->sk_dev.d_len + */ + + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv6 + if (BUF->type == HTONS(UIP_ETHTYPE_IP6)) +#else + if (BUF->type == HTONS(UIP_ETHTYPE_IP)) +#endif + { + uip_arp_ipin(&skel->sk_dev); + uip_input(&skel->sk_dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (skel->sk_dev.d_len > 0) + { + uip_arp_out(&skel->sk_dev); + skel_transmit(skel); + } + } + else if (BUF->type == htons(UIP_ETHTYPE_ARP)) + { + uip_arp_arpin(&skel->sk_dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (skel->sk_dev.d_len > 0) + { + skel_transmit(skel); + } + } + } + while (); /* While there are more packets to be processed */ +} + +/**************************************************************************** + * Function: skel_txdone + * + * Description: + * An interrupt was received indicating that the last TX packet(s) is done + * + * Parameters: + * skel - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void skel_txdone(FAR struct skel_driver_s *skel) +{ + /* Check for errors and update statistics */ + + /* If no further xmits are pending, then cancel the TX timeout and + * disable further Tx interrupts. + */ + + wd_cancel(skel->sk_txtimeout); + + /* Then poll uIP for new XMIT data */ + + (void)uip_poll(&skel->sk_dev, skel_uiptxpoll); +} + +/**************************************************************************** + * Function: skel_interrupt + * + * Description: + * Hardware interrupt handler + * + * Parameters: + * irq - Number of the IRQ that generated the interrupt + * context - Interrupt register state save info (architecture-specific) + * + * Returned Value: + * OK on success + * + * Assumptions: + * + ****************************************************************************/ + +static int skel_interrupt(int irq, FAR void *context) +{ + register FAR struct skel_driver_s *skel = &g_skel[0]; + + /* Get and clear interrupt status bits */ + + /* Handle interrupts according to status bit settings */ + + /* Check if we received an incoming packet, if so, call skel_receive() */ + + skel_receive(skel); + + /* Check if a packet transmission just completed. If so, call skel_txdone. + * This may disable further Tx interrupts if there are no pending + * tansmissions. + */ + + skel_txdone(skel); + + return OK; +} + +/**************************************************************************** + * Function: skel_txtimeout + * + * Description: + * Our TX watchdog timed out. Called from the timer interrupt handler. + * The last TX never completed. Reset the hardware and start again. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void skel_txtimeout(int argc, uint32_t arg, ...) +{ + FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)arg; + + /* Increment statistics and dump debug info */ + + /* Then reset the hardware */ + + /* Then poll uIP for new XMIT data */ + + (void)uip_poll(&skel->sk_dev, skel_uiptxpoll); +} + +/**************************************************************************** + * Function: skel_polltimer + * + * Description: + * Periodic timer handler. Called from the timer interrupt handler. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void skel_polltimer(int argc, uint32_t arg, ...) +{ + FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)arg; + + /* Check if there is room in the send another TX packet. We cannot perform + * the TX poll if he are unable to accept another packet for transmission. + */ + + /* If so, update TCP timing states and poll uIP for new XMIT data. Hmmm.. + * might be bug here. Does this mean if there is a transmit in progress, + * we will missing TCP time state updates? + */ + + (void)uip_timer(&skel->sk_dev, skel_uiptxpoll, skeleton_POLLHSEC); + + /* Setup the watchdog poll timer again */ + + (void)wd_start(skel->sk_txpoll, skeleton_WDDELAY, skel_polltimer, 1, arg); +} + +/**************************************************************************** + * Function: skel_ifup + * + * Description: + * NuttX Callback: Bring up the Ethernet interface when an IP address is + * provided + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int skel_ifup(struct uip_driver_s *dev) +{ + FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)dev->d_private; + + ndbg("Bringing up: %d.%d.%d.%d\n", + dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, + (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 ); + + /* Initialize PHYs, the Ethernet interface, and setup up Ethernet interrupts */ + + /* Set and activate a timer process */ + + (void)wd_start(skel->sk_txpoll, skeleton_WDDELAY, skel_polltimer, 1, (uint32_t)skel); + + /* Enable the Ethernet interrupt */ + + skel->sk_bifup = true; + up_enable_irq(CONFIG_skeleton_IRQ); + return OK; +} + +/**************************************************************************** + * Function: skel_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int skel_ifdown(struct uip_driver_s *dev) +{ + FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)dev->d_private; + irqstate_t flags; + + /* Disable the Ethernet interrupt */ + + flags = irqsave(); + up_disable_irq(CONFIG_skeleton_IRQ); + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(skel->sk_txpoll); + wd_cancel(skel->sk_txtimeout); + + /* Put the EMAC in its reset, non-operational state. This should be + * a known configuration that will guarantee the skel_ifup() always + * successfully brings the interface back up. + */ + + /* Mark the device "down" */ + + skel->sk_bifup = false; + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Function: skel_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int skel_txavail(struct uip_driver_s *dev) +{ + FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)dev->d_private; + irqstate_t flags; + + /* Disable interrupts because this function may be called from interrupt + * level processing. + */ + + flags = irqsave(); + + /* Ignore the notification if the interface is not yet up */ + + if (skel->sk_bifup) + { + /* Check if there is room in the hardware to hold another outgoing packet. */ + + /* If so, then poll uIP for new XMIT data */ + + (void)uip_poll(&skel->sk_dev, skel_uiptxpoll); + } + + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Function: skel_addmac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int skel_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + + return OK; +} +#endif + +/**************************************************************************** + * Function: skel_rmmac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int skel_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: skel_initialize + * + * Description: + * Initialize the Ethernet controller and driver + * + * Parameters: + * intf - In the case where there are multiple EMACs, this value + * identifies which EMAC is to be initialized. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +int skel_initialize(int intf) +{ + struct skel_driver_s *priv; + + /* Get the interface structure associated with this interface number. */ + + DEBUGASSERT(inf < CONFIG_skeleton_NINTERFACES); + priv = &g_skel[intf]; + + /* Check if a Ethernet chip is recognized at its I/O base */ + + /* Attach the IRQ to the driver */ + + if (irq_attach(CONFIG_skeleton_IRQ, skel_interrupt)) + { + /* We could not attach the ISR to the interrupt */ + + return -EAGAIN; + } + + /* Initialize the driver structure */ + + memset(priv, 0, sizeof(struct skel_driver_s)); + priv->sk_dev.d_ifup = skel_ifup; /* I/F up (new IP address) callback */ + priv->sk_dev.d_ifdown = skel_ifdown; /* I/F down callback */ + priv->sk_dev.d_txavail = skel_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_IGMP + priv->sk_dev.d_addmac = skel_addmac; /* Add multicast MAC address */ + priv->sk_dev.d_rmmac = skel_rmmac; /* Remove multicast MAC address */ +#endif + priv->sk_dev.d_private = (void*)g_skel; /* Used to recover private state from dev */ + + /* Create a watchdog for timing polling for and timing of transmisstions */ + + priv->sk_txpoll = wd_create(); /* Create periodic poll timer */ + priv->sk_txtimeout = wd_create(); /* Create TX timeout timer */ + + /* Put the interface in the down state. This usually amounts to resetting + * the device and/or calling skel_ifdown(). + */ + + /* Read the MAC address from the hardware into priv->sk_dev.d_mac.ether_addr_octet */ + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + (void)netdev_register(&priv->sk_dev); + return OK; +} + +#endif /* CONFIG_NET && CONFIG_NET_skeleton */ diff --git a/nuttx/drivers/net/slip.c b/nuttx/drivers/net/slip.c new file mode 100644 index 0000000000..31f44cbb9e --- /dev/null +++ b/nuttx/drivers/net/slip.c @@ -0,0 +1,1017 @@ +/**************************************************************************** + * drivers/net/slip.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Reference: RFC 1055 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#if defined(CONFIG_NET) && defined(CONFIG_NET_SLIP) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* NOTE: Slip requires UART hardware handshake. If hardware handshake is + * not available with your UART, then you might try the 'slattach' option + * -L which enable "3-wire operation." That allows operation without the + * hardware handshake (but with the possibility of data overrun). + */ + +/* Configuration ************************************************************/ + +#if UIP_LLH_LEN > 0 +# error "UIP_LLH_LEN must be set to zero" +#endif + +#ifndef CONFIG_NET_NOINTS +# warning "CONFIG_NET_NOINTS must be set" +#endif + +#ifndef CONFIG_NET_MULTIBUFFER +# warning "CONFIG_NET_MULTIBUFFER must be set" +#endif + +#ifndef CONFIG_SLIP_STACKSIZE +# define CONFIG_SLIP_STACKSIZE 2048 +#endif + +#ifndef CONFIG_SLIP_DEFPRIO +# define CONFIG_SLIP_DEFPRIO 128 +#endif + +/* The Linux slip module hard-codes its MTU size to 296 (40 bytes for the + * IP+TPC headers plus 256 bytes of data). So you might as well set + * CONFIG_NET_BUFSIZE to 296 as well. + * + * There may be an issue with this setting, however. I see that Linux uses + * a MTU of 296 and window of 256, but actually only sends 168 bytes of data: + * 40 + 128. I believe that is to allow for the 2x worst cast packet + * expansion. Ideally we would like to advertise the 256 MSS, but restrict + * uIP to 128 bytes (possibly by modifying the uip_mss() macro). + */ + +#if CONFIG_NET_BUFSIZE < 296 +# error "CONFIG_NET_BUFSIZE >= 296 is required" +#elif CONFIG_NET_BUFSIZE > 296 +# warning "CONFIG_NET_BUFSIZE == 296 is optimal" +#endif + +/* CONFIG_SLIP_NINTERFACES determines the number of physical interfaces + * that will be supported. + */ + +#ifndef CONFIG_SLIP_NINTERFACES +# define CONFIG_SLIP_NINTERFACES 1 +#endif + +/* SLIP special character codes *******************************************/ + +#define SLIP_END 0300 /* Indicates end of packet */ +#define SLIP_ESC 0333 /* Indicates byte stuffing */ +#define SLIP_ESC_END 0334 /* ESC ESC_END means SLIP_END data byte */ +#define SLIP_ESC_ESC 0335 /* ESC ESC_ESC means ESC data byte */ + +/* General driver definitions **********************************************/ + +/* TX poll delay = 1 second = 1000000 microseconds. */ + +#define SLIP_WDDELAY (1*1000000) +#define SLIP_POLLHSEC (1*2) + +/* Statistics helper */ + +#ifdef CONFIG_NET_STATISTICS +# define SLIP_STAT(p,f) (p->stats.f)++ +#else +# define SLIP_STAT(p,f) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Driver statistics */ + +#ifdef CONFIG_NET_STATISTICS +struct slip_statistics_s +{ + uint32_t transmitted; /* Number of packets transmitted */ + uint32_t received /* Number of packets received */ +}; +#endif + +/* The slip_driver_s encapsulates all state information for a single hardware + * interface + */ + +struct slip_driver_s +{ + volatile bool bifup; /* true:ifup false:ifdown */ + int fd; /* TTY file descriptor */ + pid_t rxpid; /* Receiver thread ID */ + pid_t txpid; /* Transmitter thread ID */ + sem_t waitsem; /* Mutually exclusive access to uIP */ + uint16_t rxlen; /* The number of bytes in rxbuf */ + + /* Driver statistics */ + +#ifdef CONFIG_NET_STATISTICS + struct slip_statistics_s stats; +#endif + + /* This holds the information visible to uIP/NuttX */ + + struct uip_driver_s dev; /* Interface understood by uIP */ + uint8_t rxbuf[CONFIG_NET_BUFSIZE + 2]; + uint8_t txbuf[CONFIG_NET_BUFSIZE + 2]; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + + /* We really should get rid of CONFIG_SLIP_NINTERFACES and, instead, + * kmalloc() new interface instances as needed. + */ + +static struct slip_driver_s g_slip[CONFIG_SLIP_NINTERFACES]; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void slip_semtake(FAR struct slip_driver_s *priv); + +/* Common TX logic */ + +static void slip_write(FAR struct slip_driver_s *priv, const uint8_t *buffer, int len); +static void slip_putc(FAR struct slip_driver_s *priv, int ch); +static int slip_transmit(FAR struct slip_driver_s *priv); +static int slip_uiptxpoll(struct uip_driver_s *dev); +static void slip_txtask(int argc, char *argv[]); + +/* Packet receiver task */ + +static int slip_getc(FAR struct slip_driver_s *priv); +static inline void slip_receive(FAR struct slip_driver_s *priv); +static int slip_rxtask(int argc, char *argv[]); + +/* NuttX callback functions */ + +static int slip_ifup(struct uip_driver_s *dev); +static int slip_ifdown(struct uip_driver_s *dev); +static int slip_txavail(struct uip_driver_s *dev); +#ifdef CONFIG_NET_IGMP +static int slip_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +static int slip_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: slip_semtake + ****************************************************************************/ + +static void slip_semtake(FAR struct slip_driver_s *priv) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&priv->waitsem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +#define slip_semgive(p) sem_post(&(p)->waitsem); + +/**************************************************************************** + * Function: slip_write + * + * Description: + * Just an inline wrapper around fwrite with error checking. + * + * Parameters: + * priv - Reference to the driver state structure + * buffer - Buffer data to send + * len - Buffer length in bytes + * + ****************************************************************************/ + +static inline void slip_write(FAR struct slip_driver_s *priv, + const uint8_t *buffer, int len) +{ + /* Handle the case where the write is awakened by a signal */ + + while (write(priv->fd, buffer, len) < 0) + { + DEBUGASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Function: slip_putc + * + * Description: + * Just an inline wrapper around putc with error checking. + * + * Parameters: + * priv - Reference to the driver state structure + * ch - The character to send + * + ****************************************************************************/ + +static inline void slip_putc(FAR struct slip_driver_s *priv, int ch) +{ + uint8_t buffer = (uint8_t)ch; + slip_write(priv, &buffer, 1); +} + +/**************************************************************************** + * Function: slip_transmit + * + * Description: + * Start hardware transmission. Called either from the txdone interrupt + * handling or from watchdog based polling. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +static int slip_transmit(FAR struct slip_driver_s *priv) +{ + uint8_t *src; + uint8_t *start; + uint8_t esc; + int remaining; + int len; + + /* Increment statistics */ + + nvdbg("Sending packet size %d\n", priv->dev.d_len); + SLIP_STAT(priv, transmitted); + + /* Send an initial END character to flush out any data that may have + * accumulated in the receiver due to line noise + */ + + slip_putc(priv, SLIP_END); + + /* For each byte in the packet, send the appropriate character sequence */ + + src = priv->dev.d_buf; + remaining = priv->dev.d_len; + start = src; + len = 0; + + while (remaining-- > 0) + { + switch (*src) + { + /* If it's the same code as an END character, we send a special two + * character code so as not to make the receiver think we sent an + * END + */ + + case SLIP_END: + esc = SLIP_ESC_END; + goto escape; + + /* If it's the same code as an ESC character, we send a special two + * character code so as not to make the receiver think we sent an + * ESC + */ + + case SLIP_ESC: + esc = SLIP_ESC_ESC; + + escape: + { + /* Flush any unsent data */ + + if (len > 0) + { + slip_write(priv, start, len); + + /* Reset */ + + start = src + 1; + len = 0; + } + + /* Then send the escape sequence */ + + slip_putc(priv, SLIP_ESC); + slip_putc(priv, esc); + } + break; + + /* otherwise, just bump up the count */ + + default: + len++; + break; + } + + /* Point to the next character in the packet */ + + src++; + } + + /* We have looked at every character in the packet. Now flush any unsent + * data + */ + + if (len > 0) + { + slip_write(priv, start, len); + } + + /* And send the END token */ + + slip_putc(priv, SLIP_END); + return OK; +} + +/**************************************************************************** + * Function: slip_uiptxpoll + * + * Description: + * Check if uIP has any outgoing packets ready to send. This is a + * callback from uip_poll(). uip_poll() may be called: + * + * 1. When the preceding TX packet send is complete, or + * 2. When the preceding TX packet send times o ]ut and the interface is reset + * 3. During normal TX polling + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * The initiator of the poll holds the priv->waitsem; + * + ****************************************************************************/ + +static int slip_uiptxpoll(struct uip_driver_s *dev) +{ + FAR struct slip_driver_s *priv = (FAR struct slip_driver_s *)dev->d_private; + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + slip_transmit(priv); + } + + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + + return 0; +} + +/**************************************************************************** + * Function: slip_txtask + * + * Description: + * Polling and transmission is performed on tx thread. + * + * Parameters: + * arg - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void slip_txtask(int argc, char *argv[]) +{ + FAR struct slip_driver_s *priv; + unsigned int index = *(argv[1]) - '0'; + uip_lock_t flags; + + ndbg("index: %d\n", index); + DEBUGASSERT(index < CONFIG_SLIP_NINTERFACES); + + /* Get our private data structure instance and wake up the waiting + * initialization logic. + */ + + priv = &g_slip[index]; + slip_semgive(priv); + + /* Loop forever */ + + for (;;) + { + /* Wait for the timeout to expire (or until we are signaled by by */ + + usleep(SLIP_WDDELAY); + + /* Is the interface up? */ + + if (priv->bifup) + { + /* Get exclusive access to uIP (if it it is already being used + * slip_rxtask, then we have to wait). + */ + + slip_semtake(priv); + + /* Poll uIP for new XMIT data. BUG: We really need to calculate + * the number of hsecs! When we are awakened by slip_txavail, the + * number will be smaller; when we have to wait for the semaphore + * (above), it may be larger. + */ + + flags = uip_lock(); + priv->dev.d_buf = priv->txbuf; + (void)uip_timer(&priv->dev, slip_uiptxpoll, SLIP_POLLHSEC); + uip_unlock(flags); + slip_semgive(priv); + } + } +} + +/**************************************************************************** + * Function: slip_getc + * + * Description: + * Get one byte from the serial input. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * The returned byte + * + ****************************************************************************/ + +static inline int slip_getc(FAR struct slip_driver_s *priv) +{ + uint8_t ch; + + while (read(priv->fd, &ch, 1) < 0) + { + DEBUGASSERT(errno == EINTR); + } + + return (int)ch; +} + +/**************************************************************************** + * Function: slip_receive + * + * Description: + * Read a packet from the serial input + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void slip_receive(FAR struct slip_driver_s *priv) +{ + uint8_t ch; + + /* Copy the data data from the hardware to to the RX buffer until we + * put together a whole packet. Make sure not to copy them into the + * packet if we run out of room. + */ + + nvdbg("Receiving packet\n"); + for (;;) + { + /* Get the next character in the stream. */ + + ch = slip_getc(priv); + + /* Handle bytestuffing if necessary */ + + switch (ch) + { + /* If it's an END character then we're done with the packet. + * (OR we are just starting a packet) + */ + + case SLIP_END: + nvdbg("END\n"); + + /* A minor optimization: if there is no data in the packet, ignore + * it. This is meant to avoid bothering IP with all the empty + * packets generated by the duplicate END characters which are in + * turn sent to try to detect line noise. + */ + + if (priv->rxlen > 0) + { + nvdbg("Received packet size %d\n", priv->rxlen); + return; + } + break; + + /* if it's the same code as an ESC character, wait and get another + * character and then figure out what to store in the packet based + * on that. + */ + + case SLIP_ESC: + nvdbg("ESC\n"); + ch = slip_getc(priv); + + /* if "ch" is not one of these two, then we have a protocol + * violation. The best bet seems to be to leave the byte alone + * and just stuff it into the packet + */ + + switch (ch) + { + case SLIP_ESC_END: + nvdbg("ESC-END\n"); + ch = SLIP_END; + break; + case SLIP_ESC_ESC: + nvdbg("ESC-ESC\n"); + ch = SLIP_ESC; + break; + default: + ndbg("ERROR: Protocol violation: %02x\n", ch); + break; + } + + /* Here we fall into the default handler and let it store the + * character for us + */ + + default: + if (priv->rxlen < CONFIG_NET_BUFSIZE+2) + { + priv->rxbuf[priv->rxlen++] = ch; + } + break; + } + } +} + +/**************************************************************************** + * Function: slip_rxtask + * + * Description: + * Wait for incoming data. + * + * Parameters: + * argc + * argv + * + * Returned Value: + * (Does not return) + * + * Assumptions: + * + ****************************************************************************/ + +static int slip_rxtask(int argc, char *argv[]) +{ + FAR struct slip_driver_s *priv; + unsigned int index = *(argv[1]) - '0'; + uip_lock_t flags; + int ch; + + ndbg("index: %d\n", index); + DEBUGASSERT(index < CONFIG_SLIP_NINTERFACES); + + /* Get our private data structure instance and wake up the waiting + * initialization logic. + */ + + priv = &g_slip[index]; + slip_semgive(priv); + + /* Loop forever */ + + for (;;) + { + /* Wait for the next character to be available on the input stream. */ + + nvdbg("Waiting...\n"); + ch = slip_getc(priv); + + /* Ignore any input that we receive before the interface is up. */ + + if (!priv->bifup) + { + continue; + } + + /* We have something... + * + * END characters may appear at packet boundaries BEFORE as well as + * after the beginning of the packet. This is normal and expected. + */ + + if (ch == SLIP_END) + { + priv->rxlen = 0; + } + + /* Otherwise, we are in danger of being out-of-sync. Apparently the + * leading END character is optional. Let's try to continue. + */ + + else + { + priv->rxbuf[0] = (uint8_t)ch; + priv->rxlen = 1; + } + + /* Copy the data data from the hardware to priv->rxbuf until we put + * together a whole packet. + */ + + slip_receive(priv); + SLIP_STAT(priv, received); + + /* All packets are assumed to be IP packets (we don't have a choice.. + * there is no Ethernet header containing the EtherType). So pass the + * received packet on for IP processing -- but only if it is big + * enough to hold an IP header. + */ + + if (priv->rxlen >= UIP_IPH_LEN) + { + /* Handle the IP input. Get exclusive access to uIP. */ + + slip_semtake(priv); + priv->dev.d_buf = priv->rxbuf; + priv->dev.d_len = priv->rxlen; + + flags = uip_lock(); + uip_input(&priv->dev); + + /* If the above function invocation resulted in data that should + * be sent out on the network, the field d_len will set to a + * value > 0. NOTE that we are transmitting using the RX buffer! + */ + + if (priv->dev.d_len > 0) + { + slip_transmit(priv); + } + uip_unlock(flags); + slip_semgive(priv); + } + else + { + SLIP_STAT(priv, rxsmallpacket); + } + } + + /* We won't get here */ + + return OK; +} + +/**************************************************************************** + * Function: slip_ifup + * + * Description: + * NuttX Callback: Bring up the Ethernet interface when an IP address is + * provided + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int slip_ifup(struct uip_driver_s *dev) +{ + FAR struct slip_driver_s *priv = (FAR struct slip_driver_s *)dev->d_private; + + ndbg("Bringing up: %d.%d.%d.%d\n", + dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, + (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 ); + + /* Mark the interface up */ + + priv->bifup = true; + return OK; +} + +/**************************************************************************** + * Function: slip_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int slip_ifdown(struct uip_driver_s *dev) +{ + FAR struct slip_driver_s *priv = (FAR struct slip_driver_s *)dev->d_private; + + /* Mark the device "down" */ + + priv->bifup = false; + return OK; +} + +/**************************************************************************** + * Function: slip_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int slip_txavail(struct uip_driver_s *dev) +{ + FAR struct slip_driver_s *priv = (FAR struct slip_driver_s *)dev->d_private; + + /* Ignore the notification if the interface is not yet up */ + + if (priv->bifup) + { + /* Wake up the TX polling thread */ + + kill(priv->txpid, SIGALRM); + } + + return OK; +} + +/**************************************************************************** + * Function: slip_addmac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int slip_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct slip_driver_s *priv = (FAR struct slip_driver_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + + return OK; +} +#endif + +/**************************************************************************** + * Function: slip_rmmac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int slip_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct slip_driver_s *priv = (FAR struct slip_driver_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: slip_initialize + * + * Description: + * Instantiate a SLIP network interface. + * + * Parameters: + * intf - In the case where there are multiple SLIP interfaces, this value + * identifies which is to be initialized. The network name will be, + * for example, "/dev/slip5" for intf == 5 + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +int slip_initialize(int intf, const char *devname) +{ + struct slip_driver_s *priv; + char buffer[8]; + const char *argv[2]; + + /* Get the interface structure associated with this interface number. */ + + DEBUGASSERT(intf < CONFIG_SLIP_NINTERFACES); + priv = &g_slip[intf]; + + /* Initialize the driver structure */ + + memset(priv, 0, sizeof(struct slip_driver_s)); + priv->dev.d_ifup = slip_ifup; /* I/F up (new IP address) callback */ + priv->dev.d_ifdown = slip_ifdown; /* I/F down callback */ + priv->dev.d_txavail = slip_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_IGMP + priv->dev.d_addmac = slip_addmac; /* Add multicast MAC address */ + priv->dev.d_rmmac = slip_rmmac; /* Remove multicast MAC address */ +#endif + priv->dev.d_private = priv; /* Used to recover private state from dev */ + + /* Open the device */ + + priv->fd = open(devname, O_RDWR, 0666); + if (priv->fd < 0) + { + ndbg("ERROR: Failed to open %s: %d\n", devname, errno); + return -errno; + } + + /* Initialize the wait semaphore */ + + sem_init(&priv->waitsem, 0, 0); + + /* Put the interface in the down state. This usually amounts to resetting + * the device and/or calling slip_ifdown(). + */ + + slip_ifdown(&priv->dev); + + /* Start the SLIP receiver task */ + + snprintf(buffer, 8, "%d", intf); + argv[0] = buffer; + argv[1] = NULL; + +#ifndef CONFIG_CUSTOM_STACK + priv->rxpid = task_create("rxslip", CONFIG_SLIP_DEFPRIO, + CONFIG_SLIP_STACKSIZE, (main_t)slip_rxtask, argv); +#else + priv->rxpid = task_create("rxslip", CONFIG_SLIP_DEFPRIO, + (main_t)slip_rxtask, argv); +#endif + if (priv->rxpid < 0) + { + ndbg("ERROR: Failed to start receiver task\n"); + return -errno; + } + + /* Wait and make sure that the receive task is started. */ + + slip_semtake(priv); + + /* Start the SLIP transmitter task */ + +#ifndef CONFIG_CUSTOM_STACK + priv->txpid = task_create("txslip", CONFIG_SLIP_DEFPRIO, + CONFIG_SLIP_STACKSIZE, (main_t)slip_txtask, argv); +#else + priv->txpid = task_create("txslip", CONFIG_SLIP_DEFPRIO, + (main_t)slip_txtask, argv); +#endif + if (priv->txpid < 0) + { + ndbg("ERROR: Failed to start receiver task\n"); + return -errno; + } + + /* Wait and make sure that the transmit task is started. */ + + slip_semtake(priv); + + /* Bump the semaphore count so that it can now be used as a mutex */ + + slip_semgive(priv); + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + (void)netdev_register(&priv->dev); + + /* When the RX and TX tasks were created, the TTY file descriptor was + * dup'ed for each task. This task no longer needs the file descriptor + * and we can safely close it. + */ + + close(priv->fd); + return OK; +} + +#endif /* CONFIG_NET && CONFIG_NET_SLIP */ + diff --git a/nuttx/drivers/net/vnet.c b/nuttx/drivers/net/vnet.c new file mode 100644 index 0000000000..f1e2465b96 --- /dev/null +++ b/nuttx/drivers/net/vnet.c @@ -0,0 +1,673 @@ +/**************************************************************************** + * drivers/net/vnet.c + * + * Copyright (C) 2011 Yu Qiang. All rights reserved. + * Author: Yu Qiang + * + * This file is a part of NuttX: + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_VNET) + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* CONFIG_VNET_NINTERFACES determines the number of physical interfaces + * that will be supported. + */ + +#ifndef CONFIG_VNET_NINTERFACES +# define CONFIG_VNET_NINTERFACES 1 +#endif + +/* TX poll deley = 1 seconds. CLK_TCK is the number of clock ticks per second */ + +#define VNET_WDDELAY (1*CLK_TCK) +#define VNET_POLLHSEC (1*2) + +/* TX timeout = 1 minute */ + +#define VNET_TXTIMEOUT (60*CLK_TCK) + +/* This is a helper pointer for accessing the contents of the Ethernet header */ + +#define BUF ((struct uip_eth_hdr *)vnet->sk_dev.d_buf) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The vnet_driver_s encapsulates all state information for a single hardware + * interface + */ + +struct vnet_driver_s +{ + bool sk_bifup; /* true:ifup false:ifdown */ + WDOG_ID sk_txpoll; /* TX poll timer */ + //WDOG_ID sk_txtimeout; /* TX timeout timer */ + + /* This holds the information visible to uIP/NuttX */ + struct rgmp_vnet *vnet; + struct uip_driver_s sk_dev; /* Interface understood by uIP */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct vnet_driver_s g_vnet[CONFIG_VNET_NINTERFACES]; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Common TX logic */ + +static int vnet_transmit(FAR struct vnet_driver_s *vnet); +static int vnet_uiptxpoll(struct uip_driver_s *dev); + +/* Interrupt handling */ + +static void vnet_txdone(FAR struct vnet_driver_s *vnet); + +/* Watchdog timer expirations */ + +static void vnet_polltimer(int argc, uint32_t arg, ...); +static void vnet_txtimeout(int argc, uint32_t arg, ...); + +/* NuttX callback functions */ + +static int vnet_ifup(struct uip_driver_s *dev); +static int vnet_ifdown(struct uip_driver_s *dev); +static int vnet_txavail(struct uip_driver_s *dev); +#ifdef CONFIG_NET_IGMP +static int vnet_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +static int vnet_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: vnet_transmit + * + * Description: + * Start hardware transmission. Called either from the txdone interrupt + * handling or from watchdog based polling. + * + * Parameters: + * vnet - Reference to the driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int vnet_transmit(FAR struct vnet_driver_s *vnet) +{ + int err; + + /* Verify that the hardware is ready to send another packet. If we get + * here, then we are committed to sending a packet; Higher level logic + * must have assured that there is not transmission in progress. + */ + + /* Increment statistics */ + + /* Send the packet: address=vnet->sk_dev.d_buf, length=vnet->sk_dev.d_len */ + err = vnet_xmit(vnet->vnet, (char *)vnet->sk_dev.d_buf, vnet->sk_dev.d_len); + if (err) { + /* Setup the TX timeout watchdog (perhaps restarting the timer) */ + //(void)wd_start(vnet->sk_txtimeout, VNET_TXTIMEOUT, vnet_txtimeout, 1, (uint32_t)vnet); + + // When vnet_xmit fail, it means TX buffer is full. Watchdog + // is of no use here because no TX done INT will happen. So + // we reset the TX buffer directly. +#ifdef CONFIG_DEBUG + cprintf("VNET: TX buffer is full\n"); +#endif + return ERROR; + } + else { + // this step may be unnecessary here + vnet_txdone(vnet); + } + + return OK; +} + +/**************************************************************************** + * Function: vnet_uiptxpoll + * + * Description: + * The transmitter is available, check if uIP has any outgoing packets ready + * to send. This is a callback from uip_poll(). uip_poll() may be called: + * + * 1. When the preceding TX packet send is complete, + * 2. When the preceding TX packet send timesout and the interface is reset + * 3. During normal TX polling + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int vnet_uiptxpoll(struct uip_driver_s *dev) +{ + FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)dev->d_private; + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (vnet->sk_dev.d_len > 0) + { + uip_arp_out(&vnet->sk_dev); + vnet_transmit(vnet); + + /* Check if there is room in the device to hold another packet. If not, + * return a non-zero value to terminate the poll. + */ + if (vnet_is_txbuff_full(vnet->vnet)) + return 1; + } + + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + + return 0; +} + +/**************************************************************************** + * Function: rtos_vnet_recv + * + * Description: + * An interrupt was received indicating the availability of a new RX packet + * + * Parameters: + * vnet - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +void rtos_vnet_recv(struct rgmp_vnet *vnet_dummy, char *data, int len) +{ + // now only support 1 vnet + struct vnet_driver_s *vnet = &g_vnet[0]; + + do { + /* Check for errors and update statistics */ + + /* Check if the packet is a valid size for the uIP buffer configuration */ + if (len > CONFIG_NET_BUFSIZE || len < 14) { +#ifdef CONFIG_DEBUG + cprintf("VNET: receive invalid packet of size %d\n", len); +#endif + return; + } + + // Copy the data data from the hardware to vnet->sk_dev.d_buf. Set + // amount of data in vnet->sk_dev.d_len + memcpy(vnet->sk_dev.d_buf, data, len); + vnet->sk_dev.d_len = len; + + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv6 + if (BUF->type == HTONS(UIP_ETHTYPE_IP6)) +#else + if (BUF->type == HTONS(UIP_ETHTYPE_IP)) +#endif + { + uip_arp_ipin(&vnet->sk_dev); + uip_input(&vnet->sk_dev); + + // If the above function invocation resulted in data that should be + // sent out on the network, the field d_len will set to a value > 0. + if (vnet->sk_dev.d_len > 0) { + uip_arp_out(&vnet->sk_dev); + vnet_transmit(vnet); + } + } + else if (BUF->type == htons(UIP_ETHTYPE_ARP)) { + uip_arp_arpin(&vnet->sk_dev); + + // If the above function invocation resulted in data that should be + // sent out on the network, the field d_len will set to a value > 0. + if (vnet->sk_dev.d_len > 0) { + vnet_transmit(vnet); + } + } + } + while (0); /* While there are more packets to be processed */ +} + +/**************************************************************************** + * Function: vnet_txdone + * + * Description: + * An interrupt was received indicating that the last TX packet(s) is done + * + * Parameters: + * vnet - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void vnet_txdone(FAR struct vnet_driver_s *vnet) +{ + /* Check for errors and update statistics */ + + /* If no further xmits are pending, then cancel the TX timeout and + * disable further Tx interrupts. + */ + + //wd_cancel(vnet->sk_txtimeout); + + /* Then poll uIP for new XMIT data */ + + (void)uip_poll(&vnet->sk_dev, vnet_uiptxpoll); +} + +/**************************************************************************** + * Function: vnet_txtimeout + * + * Description: + * Our TX watchdog timed out. Called from the timer interrupt handler. + * The last TX never completed. Reset the hardware and start again. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void vnet_txtimeout(int argc, uint32_t arg, ...) +{ + FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)arg; + + /* Increment statistics and dump debug info */ + + /* Then reset the hardware */ + + /* Then poll uIP for new XMIT data */ + + (void)uip_poll(&vnet->sk_dev, vnet_uiptxpoll); +} + +/**************************************************************************** + * Function: vnet_polltimer + * + * Description: + * Periodic timer handler. Called from the timer interrupt handler. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void vnet_polltimer(int argc, uint32_t arg, ...) +{ + FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)arg; + + /* Check if there is room in the send another TX packet. We cannot perform + * the TX poll if he are unable to accept another packet for transmission. + */ + if (vnet_is_txbuff_full(vnet->vnet)) { +#ifdef CONFIG_DEBUG + cprintf("VNET: TX buffer is full\n"); +#endif + return; + } + + /* If so, update TCP timing states and poll uIP for new XMIT data. Hmmm.. + * might be bug here. Does this mean if there is a transmit in progress, + * we will missing TCP time state updates? + */ + + (void)uip_timer(&vnet->sk_dev, vnet_uiptxpoll, VNET_POLLHSEC); + + /* Setup the watchdog poll timer again */ + + (void)wd_start(vnet->sk_txpoll, VNET_WDDELAY, vnet_polltimer, 1, arg); +} + +/**************************************************************************** + * Function: vnet_ifup + * + * Description: + * NuttX Callback: Bring up the Ethernet interface when an IP address is + * provided + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int vnet_ifup(struct uip_driver_s *dev) +{ + FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)dev->d_private; + + ndbg("Bringing up: %d.%d.%d.%d\n", + dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, + (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 ); + + /* Initialize PHYs, the Ethernet interface, and setup up Ethernet interrupts */ + + /* Set and activate a timer process */ + + (void)wd_start(vnet->sk_txpoll, VNET_WDDELAY, vnet_polltimer, 1, (uint32_t)vnet); + + vnet->sk_bifup = true; + return OK; +} + +/**************************************************************************** + * Function: vnet_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int vnet_ifdown(struct uip_driver_s *dev) +{ + FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)dev->d_private; + irqstate_t flags; + + /* Disable the Ethernet interrupt */ + + flags = irqsave(); + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(vnet->sk_txpoll); + //wd_cancel(vnet->sk_txtimeout); + + /* Put the the EMAC is its reset, non-operational state. This should be + * a known configuration that will guarantee the vnet_ifup() always + * successfully brings the interface back up. + */ + + /* Mark the device "down" */ + + vnet->sk_bifup = false; + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Function: vnet_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int vnet_txavail(struct uip_driver_s *dev) +{ + FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)dev->d_private; + irqstate_t flags; + + /* Disable interrupts because this function may be called from interrupt + * level processing. + */ + + flags = irqsave(); + + /* Ignore the notification if the interface is not yet up */ + + if (vnet->sk_bifup) + { + /* Check if there is room in the hardware to hold another outgoing packet. */ + if (vnet_is_txbuff_full(vnet->vnet)) { +#ifdef CONFIG_DEBUG + cprintf("VNET: TX buffer is full\n"); +#endif + goto out; + } + + /* If so, then poll uIP for new XMIT data */ + + (void)uip_poll(&vnet->sk_dev, vnet_uiptxpoll); + } + + out: + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Function: vnet_addmac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int vnet_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + + return OK; +} +#endif + +/**************************************************************************** + * Function: vnet_rmmac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int vnet_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: vnet_initialize + * + * Description: + * Initialize the Ethernet controller and driver + * + * Parameters: + * intf - In the case where there are multiple EMACs, this value + * identifies which EMAC is to be initialized. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +void vnet_initialize(void) +{ + struct vnet_driver_s *priv; + struct rgmp_vnet *vnet = vnet_list.next; + int i; + + for (i=0; isk_dev.d_ifup = vnet_ifup; /* I/F down callback */ + priv->sk_dev.d_ifdown = vnet_ifdown; /* I/F up (new IP address) callback */ + priv->sk_dev.d_txavail = vnet_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_IGMP + priv->sk_dev.d_addmac = vnet_addmac; /* Add multicast MAC address */ + priv->sk_dev.d_rmmac = vnet_rmmac; /* Remove multicast MAC address */ +#endif + priv->sk_dev.d_private = (void*)g_vnet; /* Used to recover private state from dev */ + + /* Create a watchdog for timing polling for and timing of transmisstions */ + + priv->sk_txpoll = wd_create(); /* Create periodic poll timer */ + //priv->sk_txtimeout = wd_create(); /* Create TX timeout timer */ + + priv->vnet = vnet; + + /* Register the device with the OS */ + + (void)netdev_register(&priv->sk_dev); + vnet = vnet->next; + } +} + +#endif /* CONFIG_NET && CONFIG_NET_VNET */ diff --git a/nuttx/drivers/pipes/Kconfig b/nuttx/drivers/pipes/Kconfig new file mode 100644 index 0000000000..ae2bf31307 --- /dev/null +++ b/nuttx/drivers/pipes/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# diff --git a/nuttx/drivers/pipes/Make.defs b/nuttx/drivers/pipes/Make.defs new file mode 100644 index 0000000000..836505481b --- /dev/null +++ b/nuttx/drivers/pipes/Make.defs @@ -0,0 +1,46 @@ +############################################################################ +# drivers/pipes/Make.defs +# +# Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifneq ($(CONFIG_NFILE_DESCRIPTORS),0) + +# Include pipe driver + +CSRCS += pipe.c fifo.c pipe_common.c + +# Include pipe build support + +DEPPATH += --dep-path pipes +VPATH += :pipes +endif diff --git a/nuttx/drivers/pipes/fifo.c b/nuttx/drivers/pipes/fifo.c new file mode 100644 index 0000000000..03aafd0f0a --- /dev/null +++ b/nuttx/drivers/pipes/fifo.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * drivers/pipes/fifo.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "pipe_common.h" + +#if CONFIG_DEV_PIPE_SIZE > 0 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations fifo_fops = +{ + pipecommon_open, /* open */ + pipecommon_close, /* close */ + pipecommon_read, /* read */ + pipecommon_write, /* write */ + 0, /* seek */ + 0 /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , pipecommon_poll /* poll */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mkfifo + * + * Description: + * mkfifo() makes a FIFO device driver file with name 'pathname.' Unlike + * Linux, a NuttX FIFO is not a special file type but simply a device driver + * instance. 'mode' specifies the FIFO's permissions. + * + * Once the FIFO has been created by mkfifo(), any thread can open it for + * reading or writing, in the same way as an ordinary file. However, it must + * have been opened from both reading and writing before input or output + * can be performed. This FIFO implementation will block all attempts to + * open a FIFO read-only until at least one thread has opened the FIFO for + * writing. + * + * If all threads that write to the FIFO have closed, subsequent calls to + * read() on the FIFO will return 0 (end-of-file). + * + * Inputs: + * pathname - The full path to the FIFO instance to attach to or to create + * (if not already created). + * mode - Ignored for now + * + * Return: + * 0 is returned on success; otherwise, -1 is returned with errno set + * appropriately. + * + ****************************************************************************/ + +int mkfifo(FAR const char *pathname, mode_t mode) +{ + struct pipe_dev_s *dev; + int ret; + + /* Allocate and initialize a new device structure instance */ + + dev = pipecommon_allocdev(); + if (!dev) + { + return -ENOMEM; + } + + ret = register_driver(pathname, &fifo_fops, mode, (void*)dev); + if (ret != 0) + { + pipecommon_freedev(dev); + } + + return ret; +} + +#endif /* CONFIG_DEV_PIPE_SIZE > 0 */ diff --git a/nuttx/drivers/pipes/pipe.c b/nuttx/drivers/pipes/pipe.c new file mode 100644 index 0000000000..20c160475b --- /dev/null +++ b/nuttx/drivers/pipes/pipe.c @@ -0,0 +1,286 @@ +/**************************************************************************** + * drivers/pipes/pipe.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pipe_common.h" + +#if CONFIG_DEV_PIPE_SIZE > 0 + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define MAX_PIPES 32 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int pipe_close(FAR struct file *filep); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations pipe_fops = +{ + pipecommon_open, /* open */ + pipe_close, /* close */ + pipecommon_read, /* read */ + pipecommon_write, /* write */ + 0, /* seek */ + 0 /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , pipecommon_poll /* poll */ +#endif +}; + +static sem_t g_pipesem = { 1 }; +static uint32_t g_pipeset = 0; +static uint32_t g_pipecreated = 0; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pipe_allocate + ****************************************************************************/ + +static inline int pipe_allocate(void) +{ + int pipeno; + int ret = -ENFILE; + + for (pipeno = 0; pipeno < MAX_PIPES; pipeno++) + { + if ((g_pipeset & (1 << pipeno)) == 0) + { + g_pipeset |= (1 << pipeno); + ret = pipeno; + break; + } + } + + return ret; +} + +/**************************************************************************** + * Name: pipe_free + ****************************************************************************/ + +static inline void pipe_free(int pipeno) +{ + int ret = sem_wait(&g_pipesem); + if (ret == 0) + { + g_pipeset &= ~(1 << pipeno); + (void)sem_post(&g_pipesem); + } +} + +/**************************************************************************** + * Name: pipe_close + ****************************************************************************/ + +static int pipe_close(FAR struct file *filep) +{ + struct inode *inode = filep->f_inode; + struct pipe_dev_s *dev = inode->i_private; + int ret; + + /* Some sanity checking */ +#if CONFIG_DEBUG + if (!dev) + { + return -EBADF; + } +#endif + + /* Perform common close operations */ + + ret = pipecommon_close(filep); + if (ret == 0 && dev->d_refs == 0) + { + /* Release the pipe when there are no further open references to it. */ + + pipe_free(dev->d_pipeno); + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pipe + * + * Description: + * pipe() creates a pair of file descriptors, pointing to a pipe inode, and + * places them in the array pointed to by 'filedes'. filedes[0] is for reading, + * filedes[1] is for writing. + * + * Inputs: + * filedes[2] - The user provided array in which to catch the pipe file + * descriptors + * + * Return: + * 0 is returned on success; otherwise, -1 is returned with errno set + * appropriately. + * + ****************************************************************************/ + +int pipe(int filedes[2]) +{ + struct pipe_dev_s *dev = NULL; + char devname[16]; + int pipeno; + int err; + int ret; + + /* Get exclusive access to the pipe allocation data */ + + ret = sem_wait(&g_pipesem); + if (ret < 0) + { + /* sem_wait() will have already set errno */ + + return ERROR; + } + + /* Allocate a minor number for the pipe device */ + + pipeno = pipe_allocate(); + if (pipeno < 0) + { + (void)sem_post(&g_pipesem); + err = -pipeno; + goto errout; + } + + /* Create a pathname to the pipe device */ + + sprintf(devname, "/dev/pipe%d", pipeno); + + /* Check if the pipe device has already been created */ + + if ((g_pipecreated & (1 << pipeno)) == 0) + { + /* No.. Allocate and initialize a new device structure instance */ + + dev = pipecommon_allocdev(); + if (!dev) + { + (void)sem_post(&g_pipesem); + err = ENOMEM; + goto errout_with_pipe; + } + + dev->d_pipeno = pipeno; + + /* Register the pipe device */ + + ret = register_driver(devname, &pipe_fops, 0666, (void*)dev); + if (ret != 0) + { + (void)sem_post(&g_pipesem); + err = -ret; + goto errout_with_dev; + } + + /* Remember that we created this device */ + + g_pipecreated |= (1 << pipeno); + } + + (void)sem_post(&g_pipesem); + + /* Get a write file descriptor */ + + filedes[1] = open(devname, O_WRONLY); + if (filedes[1] < 0) + { + err = -filedes[1]; + goto errout_with_driver; + } + + /* Get a read file descriptor */ + + filedes[0] = open(devname, O_RDONLY); + if (filedes[0] < 0) + { + err = -filedes[0]; + goto errout_with_wrfd; + } + + return OK; + +errout_with_wrfd: + close(filedes[1]); +errout_with_driver: + unregister_driver(devname); +errout_with_dev: + pipecommon_freedev(dev); +errout_with_pipe: + pipe_free(pipeno); +errout: + errno = err; + return ERROR; +} + +#endif /* CONFIG_DEV_PIPE_SIZE > 0 */ diff --git a/nuttx/drivers/pipes/pipe_common.c b/nuttx/drivers/pipes/pipe_common.c new file mode 100644 index 0000000000..5f61fdd8e3 --- /dev/null +++ b/nuttx/drivers/pipes/pipe_common.c @@ -0,0 +1,682 @@ +/**************************************************************************** + * drivers/pipes/pipe_common.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#if CONFIG_DEBUG +# include +#endif + +#include "pipe_common.h" + +#if CONFIG_DEV_PIPE_SIZE > 0 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* CONFIG_DEV_PIPEDUMP will dump the contents of each transfer into and out + * of the pipe. + */ + +#ifdef CONFIG_DEV_PIPEDUMP +# define pipe_dumpbuffer(m,a,n) lib_dumpbuffer(m,a,n) +#else +# define pipe_dumpbuffer(m,a,n) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void pipecommon_semtake(sem_t *sem); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pipecommon_semtake + ****************************************************************************/ + +static void pipecommon_semtake(sem_t *sem) +{ + while (sem_wait(sem) != 0) + { + /* The only case that an error should occur here is if the wait was + * awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Name: pipecommon_pollnotify + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static void pipecommon_pollnotify(FAR struct pipe_dev_s *dev, pollevent_t eventset) +{ + int i; + + for (i = 0; i < CONFIG_DEV_PIPE_NPOLLWAITERS; i++) + { + struct pollfd *fds = dev->d_fds[i]; + if (fds) + { + fds->revents |= (fds->events & eventset); + if (fds->revents != 0) + { + fvdbg("Report events: %02x\n", fds->revents); + sem_post(fds->sem); + } + } + } +} +#else +# define pipecommon_pollnotify(dev,event) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pipecommon_allocdev + ****************************************************************************/ + +FAR struct pipe_dev_s *pipecommon_allocdev(void) +{ + struct pipe_dev_s *dev; + + /* Allocate a private structure to manage the pipe */ + + dev = (struct pipe_dev_s *)kmalloc(sizeof(struct pipe_dev_s)); + if (dev) + { + /* Initialize the private structure */ + + memset(dev, 0, sizeof(struct pipe_dev_s)); + sem_init(&dev->d_bfsem, 0, 1); + sem_init(&dev->d_rdsem, 0, 0); + sem_init(&dev->d_wrsem, 0, 0); + } + + return dev; +} + +/**************************************************************************** + * Name: pipecommon_freedev + ****************************************************************************/ + +void pipecommon_freedev(FAR struct pipe_dev_s *dev) +{ + sem_destroy(&dev->d_bfsem); + sem_destroy(&dev->d_rdsem); + sem_destroy(&dev->d_wrsem); + kfree(dev); +} + +/**************************************************************************** + * Name: pipecommon_open + ****************************************************************************/ + +int pipecommon_open(FAR struct file *filep) +{ + struct inode *inode = filep->f_inode; + struct pipe_dev_s *dev = inode->i_private; + int sval; + int ret; + + /* Some sanity checking */ +#if CONFIG_DEBUG + if (!dev) + { + return -EBADF; + } +#endif + + /* Make sure that we have exclusive access to the device structure. The + * sem_wait() call should fail only if we are awakened by a signal. + */ + + ret = sem_wait(&dev->d_bfsem); + if (ret != OK) + { + fdbg("sem_wait failed: %d\n", errno); + DEBUGASSERT(errno > 0); + return -errno; + } + + /* If this the first reference on the device, then allocate the buffer */ + + if (dev->d_refs == 0) + { + dev->d_buffer = (uint8_t*)kmalloc(CONFIG_DEV_PIPE_SIZE); + if (!dev->d_buffer) + { + (void)sem_post(&dev->d_bfsem); + return -ENOMEM; + } + } + + /* Increment the reference count on the pipe instance */ + + dev->d_refs++; + + /* If opened for writing, increment the count of writers on on the pipe instance */ + + if ((filep->f_oflags & O_WROK) != 0) + { + dev->d_nwriters++; + + /* If this this is the first writer, then the read semaphore indicates the + * number of readers waiting for the first writer. Wake them all up. + */ + + if (dev->d_nwriters == 1) + { + while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval < 0) + { + sem_post(&dev->d_rdsem); + } + } + } + + /* If opened for read-only, then wait for at least one writer on the pipe */ + + sched_lock(); + (void)sem_post(&dev->d_bfsem); + if ((filep->f_oflags & O_RDWR) == O_RDONLY && dev->d_nwriters < 1) + { + /* NOTE: d_rdsem is normally used when the read logic waits for more + * data to be written. But until the first writer has opened the + * pipe, the meaning is different: it is used prevent O_RDONLY open + * calls from returning until there is at least one writer on the pipe. + * This is required both by spec and also because it prevents + * subsequent read() calls from returning end-of-file because there is + * no writer on the pipe. + */ + + ret = sem_wait(&dev->d_rdsem); + if (ret != OK) + { + /* The sem_wait() call should fail only if we are awakened by + * a signal. + */ + + fdbg("sem_wait failed: %d\n", errno); + DEBUGASSERT(errno > 0); + ret = -errno; + + /* Immediately close the pipe that we just opened */ + + (void)pipecommon_close(filep); + } + } + + sched_unlock(); + return ret; +} + +/**************************************************************************** + * Name: pipecommon_close + ****************************************************************************/ + +int pipecommon_close(FAR struct file *filep) +{ + struct inode *inode = filep->f_inode; + struct pipe_dev_s *dev = inode->i_private; + int sval; + + /* Some sanity checking */ +#if CONFIG_DEBUG + if (!dev) + { + return -EBADF; + } +#endif + + /* Make sure that we have exclusive access to the device structure. + * NOTE: close() is supposed to return EINTR if interrupted, however + * I've never seen anyone check that. + */ + + pipecommon_semtake(&dev->d_bfsem); + + /* Check if the decremented reference count would go to zero */ + + if (dev->d_refs > 1) + { + /* No.. then just decrement the reference count */ + + dev->d_refs--; + + /* If opened for writing, decrement the count of writers on on the pipe instance */ + + if ((filep->f_oflags & O_WROK) != 0) + { + /* If there are no longer any writers on the pipe, then notify all of the + * waiting readers that they must return end-of-file. + */ + + if (--dev->d_nwriters <= 0) + { + while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval < 0) + { + sem_post(&dev->d_rdsem); + } + } + } + } + else + { + /* Yes... deallocate the buffer */ + + kfree(dev->d_buffer); + dev->d_buffer = NULL; + + /* And reset all counts and indices */ + + dev->d_wrndx = 0; + dev->d_rdndx = 0; + dev->d_refs = 0; + dev->d_nwriters = 0; + } + + sem_post(&dev->d_bfsem); + return OK; +} + +/**************************************************************************** + * Name: pipecommon_read + ****************************************************************************/ + +ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + struct inode *inode = filep->f_inode; + struct pipe_dev_s *dev = inode->i_private; +#ifdef CONFIG_DEV_PIPEDUMP + FAR uint8_t *start = (uint8_t*)buffer; +#endif + ssize_t nread = 0; + int sval; + int ret; + + /* Some sanity checking */ +#if CONFIG_DEBUG + if (!dev) + { + return -ENODEV; + } +#endif + + /* Make sure that we have exclusive access to the device structure */ + + if (sem_wait(&dev->d_bfsem) < 0) + { + return ERROR; + } + + /* If the pipe is empty, then wait for something to be written to it */ + + while (dev->d_wrndx == dev->d_rdndx) + { + /* If O_NONBLOCK was set, then return EGAIN */ + + if (filep->f_oflags & O_NONBLOCK) + { + sem_post(&dev->d_bfsem); + return -EAGAIN; + } + + /* If there are no writers on the pipe, then return end of file */ + + if (dev->d_nwriters <= 0) + { + sem_post(&dev->d_bfsem); + return 0; + } + + /* Otherwise, wait for something to be written to the pipe */ + + sched_lock(); + sem_post(&dev->d_bfsem); + ret = sem_wait(&dev->d_rdsem); + sched_unlock(); + + if (ret < 0 || sem_wait(&dev->d_bfsem) < 0) + { + return ERROR; + } + } + + /* Then return whatever is available in the pipe (which is at least one byte) */ + + nread = 0; + while (nread < len && dev->d_wrndx != dev->d_rdndx) + { + *buffer++ = dev->d_buffer[dev->d_rdndx]; + if (++dev->d_rdndx >= CONFIG_DEV_PIPE_SIZE) + { + dev->d_rdndx = 0; + } + nread++; + } + + /* Notify all waiting writers that bytes have been removed from the buffer */ + + while (sem_getvalue(&dev->d_wrsem, &sval) == 0 && sval < 0) + { + sem_post(&dev->d_wrsem); + } + + /* Notify all poll/select waiters that they can write to the FIFO */ + + pipecommon_pollnotify(dev, POLLOUT); + + sem_post(&dev->d_bfsem); + pipe_dumpbuffer("From PIPE:", start, nread); + return nread; +} + +/**************************************************************************** + * Name: pipecommon_write + ****************************************************************************/ + +ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer, size_t len) +{ + struct inode *inode = filep->f_inode; + struct pipe_dev_s *dev = inode->i_private; + ssize_t nwritten = 0; + ssize_t last; + int nxtwrndx; + int sval; + + /* Some sanity checking */ + +#if CONFIG_DEBUG + if (!dev) + { + return -ENODEV; + } +#endif + + pipe_dumpbuffer("To PIPE:", (uint8_t*)buffer, len); + + /* At present, this method cannot be called from interrupt handlers. That is + * because it calls sem_wait (via pipecommon_semtake below) and sem_wait cannot + * be called from interrupt level. This actually happens fairly commonly + * IF dbg() is called from interrupt handlers and stdout is being redirected + * via a pipe. In that case, the debug output will try to go out the pipe + * (interrupt handlers should use the lldbg() APIs). + * + * On the other hand, it would be very valuable to be able to feed the pipe + * from an interrupt handler! TODO: Consider disabling interrupts instead + * of taking semaphores so that pipes can be written from interupt handlers + */ + + DEBUGASSERT(up_interrupt_context() == false) + + /* Make sure that we have exclusive access to the device structure */ + + if (sem_wait(&dev->d_bfsem) < 0) + { + return ERROR; + } + + /* Loop until all of the bytes have been written */ + + last = 0; + for (;;) + { + /* Calculate the write index AFTER the next byte is written */ + + nxtwrndx = dev->d_wrndx + 1; + if (nxtwrndx >= CONFIG_DEV_PIPE_SIZE) + { + nxtwrndx = 0; + } + + /* Would the next write overflow the circular buffer? */ + + if (nxtwrndx != dev->d_rdndx) + { + /* No... copy the byte */ + + dev->d_buffer[dev->d_wrndx] = *buffer++; + dev->d_wrndx = nxtwrndx; + + /* Is the write complete? */ + + if (++nwritten >= len) + { + /* Yes.. Notify all of the waiting readers that more data is available */ + + while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval < 0) + { + sem_post(&dev->d_rdsem); + } + + /* Notify all poll/select waiters that they can write to the FIFO */ + + pipecommon_pollnotify(dev, POLLIN); + + /* Return the number of bytes written */ + + sem_post(&dev->d_bfsem); + return len; + } + } + else + { + /* There is not enough room for the next byte. Was anything written in this pass? */ + + if (last < nwritten) + { + /* Yes.. Notify all of the waiting readers that more data is available */ + + while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval < 0) + { + sem_post(&dev->d_rdsem); + } + } + last = nwritten; + + /* If O_NONBLOCK was set, then return partial bytes written or EGAIN */ + + if (filep->f_oflags & O_NONBLOCK) + { + if (nwritten == 0) + { + nwritten = -EAGAIN; + } + sem_post(&dev->d_bfsem); + return nwritten; + } + + /* There is more to be written.. wait for data to be removed from the pipe */ + + sched_lock(); + sem_post(&dev->d_bfsem); + pipecommon_semtake(&dev->d_wrsem); + sched_unlock(); + pipecommon_semtake(&dev->d_bfsem); + } + } +} + +/**************************************************************************** + * Name: pipecommon_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct pipe_dev_s *dev = inode->i_private; + pollevent_t eventset; + pipe_ndx_t nbytes; + int ret = OK; + int i; + + /* Some sanity checking */ + +#if CONFIG_DEBUG + if (!dev || !fds) + { + return -ENODEV; + } +#endif + + /* Are we setting up the poll? Or tearing it down? */ + + pipecommon_semtake(&dev->d_bfsem); + if (setup) + { + /* This is a request to set up the poll. Find an available + * slot for the poll structure reference + */ + + for (i = 0; i < CONFIG_DEV_PIPE_NPOLLWAITERS; i++) + { + /* Find an available slot */ + + if (!dev->d_fds[i]) + { + /* Bind the poll structure and this slot */ + + dev->d_fds[i] = fds; + fds->priv = &dev->d_fds[i]; + break; + } + } + + if (i >= CONFIG_DEV_PIPE_NPOLLWAITERS) + { + fds->priv = NULL; + ret = -EBUSY; + goto errout; + } + + /* Should immediately notify on any of the requested events? + * First, determine how many bytes are in the buffer + */ + + if (dev->d_wrndx >= dev->d_rdndx) + { + nbytes = dev->d_wrndx - dev->d_rdndx; + } + else + { + nbytes = (CONFIG_DEV_PIPE_SIZE-1) + dev->d_wrndx - dev->d_rdndx; + } + + /* Notify the POLLOUT event if the pipe is not full */ + + eventset = 0; + if (nbytes < (CONFIG_DEV_PIPE_SIZE-1)) + { + eventset |= POLLOUT; + } + + /* Notify the POLLIN event if the pipe is not empty */ + + if (nbytes > 0) + { + eventset |= POLLIN; + } + + if (eventset) + { + pipecommon_pollnotify(dev, eventset); + } + } + else + { + /* This is a request to tear down the poll. */ + + struct pollfd **slot = (struct pollfd **)fds->priv; + +#ifdef CONFIG_DEBUG + if (!slot) + { + ret = -EIO; + goto errout; + } +#endif + + /* Remove all memory of the poll setup */ + + *slot = NULL; + fds->priv = NULL; + } + +errout: + sem_post(&dev->d_bfsem); + return ret; +} +#endif + +#endif /* CONFIG_DEV_PIPE_SIZE > 0 */ diff --git a/nuttx/drivers/pipes/pipe_common.h b/nuttx/drivers/pipes/pipe_common.h new file mode 100644 index 0000000000..44822e07f8 --- /dev/null +++ b/nuttx/drivers/pipes/pipe_common.h @@ -0,0 +1,139 @@ +/**************************************************************************** + * drivers/pipe/pipe_common.h + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_PIPES_PIPE_COMMON_H +#define __DRIVERS_PIPES_PIPE_COMMON_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#ifndef CONFIG_DEV_PIPE_SIZE +# define CONFIG_DEV_PIPE_SIZE 1024 +#endif + +#if CONFIG_DEV_PIPE_SIZE > 0 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Maximum number of threads than can be waiting for POLL events */ + +#ifndef CONFIG_DEV_PIPE_NPOLLWAITERS +# define CONFIG_DEV_PIPE_NPOLLWAITERS 2 +#endif + +/* Maximum number of open's supported on pipe */ + +#define CONFIG_DEV_PIPE_MAXUSER 255 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Make the buffer index as small as possible for the configured pipe size */ + +#if CONFIG_DEV_PIPE_SIZE > 65535 +typedef uint32_t pipe_ndx_t; /* 32-bit index */ +#elif CONFIG_DEV_PIPE_SIZE > 255 +typedef uint16_t pipe_ndx_t; /* 16-bit index */ +#else +typedef uint8_t pipe_ndx_t; /* 8-bit index */ +#endif + +/* This structure represents the state of one pipe. A reference to this + * structure is retained in the i_private field of the inode whenthe pipe/fifo + * device is registered. + */ + +struct pipe_dev_s +{ + sem_t d_bfsem; /* Used to serialize access to d_buffer and indices */ + sem_t d_rdsem; /* Empty buffer - Reader waits for data write */ + sem_t d_wrsem; /* Full buffer - Writer waits for data read */ + pipe_ndx_t d_wrndx; /* Index in d_buffer to save next byte written */ + pipe_ndx_t d_rdndx; /* Index in d_buffer to return the next byte read */ + uint8_t d_refs; /* References counts on pipe (limited to 255) */ + uint8_t d_nwriters; /* Number of reference counts for write access */ + uint8_t d_pipeno; /* Pipe minor number */ + uint8_t *d_buffer; /* Buffer allocated when device opened */ + + /* The following is a list if poll structures of threads waiting for + * driver events. The 'struct pollfd' reference for each open is also + * retained in the f_priv field of the 'struct file'. + */ + +#ifndef CONFIG_DISABLE_POLL + struct pollfd *d_fds[CONFIG_DEV_PIPE_NPOLLWAITERS]; +#endif +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +# define EXTERN extern "C" +extern "C" { +#else +# define EXTERN extern +#endif + +EXTERN FAR struct pipe_dev_s *pipecommon_allocdev(void); +EXTERN void pipecommon_freedev(FAR struct pipe_dev_s *dev); +EXTERN int pipecommon_open(FAR struct file *filep); +EXTERN int pipecommon_close(FAR struct file *filep); +EXTERN ssize_t pipecommon_read(FAR struct file *, FAR char *, size_t); +EXTERN ssize_t pipecommon_write(FAR struct file *, FAR const char *, size_t); +#ifndef CONFIG_DISABLE_POLL +EXTERN int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_DEV_PIPE_SIZE > 0 */ +#endif /* __DRIVERS_PIPES_PIPE_COMMON_H */ diff --git a/nuttx/drivers/power/Kconfig b/nuttx/drivers/power/Kconfig new file mode 100644 index 0000000000..ac76331b6b --- /dev/null +++ b/nuttx/drivers/power/Kconfig @@ -0,0 +1,23 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# +config BATTERY + bool "Battery support" + default n + +config MAX1704X + bool "MAX1704X Battery charger support" + default n + select I2C + select I2C_MAX1704X + depends on BATTERY + ---help--- + The MAX17040/MAX17041 are ultra-compact, low-cost, host-side fuel-gauge + systems for lithium-ion (Li+) batteries in handheld and portable equipment. + The MAX17040 is configured to operate with a single lithium cell and the + MAX17041 is configured for a dual-cell 2S pack. + +config I2C_MAX1704X + bool + default y if MAX1704X diff --git a/nuttx/drivers/power/Make.defs b/nuttx/drivers/power/Make.defs new file mode 100644 index 0000000000..45c6aebc32 --- /dev/null +++ b/nuttx/drivers/power/Make.defs @@ -0,0 +1,84 @@ +############################################################################ +# drivers/power/Make.defs +# +# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +POWER_DEPPATH = +POWER_VPATH = +POWER_CFLAGS = + +# Include power management sources + +ifeq ($(CONFIG_PM),y) + +CSRCS += pm_activity.c pm_changestate.c pm_checkstate.c pm_initialize.c pm_register.c pm_update.c + +# Include power management in the build + +POWER_DEPPATH := --dep-path power +POWER_VPATH := :power +POWER_CFLAGS := ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/power} + +endif + +# Add battery drivers + +ifeq ($(CONFIG_BATTERY),y) + +CSRCS += battery.c + +# Add I2C-based battery drivers + +ifeq ($(CONFIG_I2C),y) + +# Add the MAX1704x I2C-based battery driver + +ifeq ($(CONFIG_I2C_MAX1704X),y) +CSRCS += max1704x.c +endif + +endif + +# Include battery suport in the build + +POWER_DEPPATH := --dep-path power +POWER_VPATH := :power +POWER_CFLAGS := ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/power} + +endif + +# Include power management in the build + +DEPPATH += $(POWER_DEPPATH) +VPATH += $(POWER_VPATH) +CFLAGS += $(POWER_CFLAGS) diff --git a/nuttx/drivers/power/battery.c b/nuttx/drivers/power/battery.c new file mode 100644 index 0000000000..698e5571b0 --- /dev/null +++ b/nuttx/drivers/power/battery.c @@ -0,0 +1,254 @@ +/**************************************************************************** + * drivers/power/battery.c + * Upper-half, character driver for batteries. + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +/* This driver requires: + * + * CONFIG_BATTERY - Upper half battery driver support + */ + +#if defined(CONFIG_BATTERY) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Character driver methods */ + +static int bat_open(FAR struct file *filep); +static int bat_close(FAR struct file *filep); +static ssize_t bat_read(FAR struct file *, FAR char *, size_t nbytes); +static ssize_t bat_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); +static int bat_ioctl(FAR struct file *filep,int cmd,unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_batteryops = +{ + bat_open, + bat_close, + bat_read, + bat_write, + 0, + bat_ioctl +#ifndef CONFIG_DISABLE_POLL + , 0 +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: bat_open + * + * Description: + * This function is called whenever the battery device is opened. + * + ****************************************************************************/ + +static int bat_open(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: bat_close + * + * Description: + * This routine is called when the battery device is closed. + * + ****************************************************************************/ + +static int bat_close(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: bat_read + ****************************************************************************/ + +static ssize_t bat_read(FAR struct file *filep, FAR char *buffer, size_t buflen) +{ + /* Return nothing read */ + + return 0; +} + +/**************************************************************************** + * Name: bat_write + ****************************************************************************/ + +static ssize_t bat_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + /* Return nothing written */ + + return 0; +} + +/**************************************************************************** + * Name: bat_ioctl + ****************************************************************************/ + +static int bat_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct battery_dev_s *dev = inode->i_private; + int ret = -EINVAL; + + /* Inforce mutually exclusive access to the battery driver */ + + ret = sem_wait(&dev->batsem); + if (ret < 0) + { + return -errno; /* Probably EINTR */ + } + + /* Procss the IOCTL command */ + + ret = -EINVAL; /* Assume a bad argument */ + switch (cmd) + { + case BATIOC_STATE: + { + FAR int *ptr = (FAR int *)((uintptr_t)arg); + if (ptr) + { + ret = dev->ops->state(dev, ptr); + } + } + break; + + case BATIOC_ONLINE: + { + FAR bool *ptr = (FAR bool *)((uintptr_t)arg); + if (ptr) + { + ret = dev->ops->online(dev, ptr); + } + } + break; + + case BATIOC_VOLTAGE: + { + FAR b16_t *ptr = (FAR b16_t *)((uintptr_t)arg); + if (ptr) + { + ret = dev->ops->voltage(dev, ptr); + } + } + break; + + case BATIOC_CAPACITY: + { + FAR b16_t *ptr = (FAR b16_t *)((uintptr_t)arg); + if (ptr) + { + ret = dev->ops->capacity(dev, ptr); + } + } + break; + + default: + dbg("Unrecognized cmd: %d\n", cmd); + ret = -ENOTTY; + break; + } + + sem_post(&dev->batsem); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: battery_register + * + * Description: + * Register a lower half battery driver with the common, upper-half + * battery driver. + * + * Input parameters: + * devpath - The location in the pseudo-filesystem to create the driver. + * Recommended standard is "/dev/bat0", "/dev/bat1", etc. + * dev - An instance of the battery state structure . + * + * Returned value: + * Zero on success or a negated errno value on failure. + * + ****************************************************************************/ + +int battery_register(FAR const char *devpath, FAR struct battery_dev_s *dev) +{ + int ret; + + /* Register the character driver */ + + ret = register_driver(devpath, &g_batteryops, 0555, dev); + if (ret < 0) + { + dbg("Failed to register driver: %d\n", ret); + } + return ret; +} +#endif /* CONFIG_BATTERY */ diff --git a/nuttx/drivers/power/max1704x.c b/nuttx/drivers/power/max1704x.c new file mode 100644 index 0000000000..ec50515e6e --- /dev/null +++ b/nuttx/drivers/power/max1704x.c @@ -0,0 +1,564 @@ +/**************************************************************************** + * drivers/power/max1704x.c + * Lower half driver for MAX1704x battery charger + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* "The MAX17040/MAX17041 are ultra-compact, low-cost, host-side fuel-gauge + * systems for lithium-ion (Li+) batteries in handheld and portable equipment. + * The MAX17040 is configured to operate with a single lithium cell and the + * MAX17041 is configured for a dual-cell 2S pack. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +/* This driver requires: + * + * CONFIG_BATTERY - Upper half battery driver support + * CONFIG_I2C - I2C support + * CONFIG_I2C_MAX1704X - And the driver must be explictly selected. + */ + +#if defined(CONFIG_BATTERY) && defined(CONFIG_I2C) && defined(CONFIG_I2C_MAX1704X) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_I2C_MAX17040 or CONFIG_I2C_MAX17041 - The driver must know which + * chip is on the board in order to scale the voltage correctly. + */ + +#if !defined(CONFIG_I2C_MAX17040) && !defined(CONFIG_I2C_MAX17041) +# warning "Assuming CONFIG_I2C_MAX17040" +# define CONFIG_I2C_MAX17040 1 +#endif + +/* MAX1704x Register Definitions ********************************************/ +/* "All host interaction with the MAX17040/MAX17041 is handled by writing to + * and reading from register locations. The MAX17040/MAX17041 have six 16-bit + * registers: SOC, VCELL, MODE, VERSION, RCOMP, and COMMAND. Register reads + * and writes are only valid if all 16 bits are transferred..." + */ + +/* "VCELL Register. Battery voltage is measured at the CELL pin input with + * respect to GND over a 0 to 5.00V range for the MAX17040 and 0 to 10.00V + * for the MAX17041 with resolutions of 1.25mV and 2.50mV, respectively..." + */ + +#define MAX1407X_VCELL_ADDR 0x02 /* Bits 4-15: Bits 0-11 of the battery voltage */ + +/* VCELL conversion macros */ + +#define MAX14700_VCELL_CONV 82 /* 0.00125 v * 65536 */ +#define MAX14070_VCELL(v) ((b16_t)(v) * MAX14700_VCELL_CONV) + +#define MAX14701_VCELL_CONV 163 /* 0.0025 v * 65536 */ +#define MAX14071_VCELL(v) ((b16_t)(v) * MAX14701_VCELL_CONV) + +#ifdef CONFIG_I2C_MAX17040 +# define MAX1407X_VCELL(v) MAX14070_VCELL(v) +#else +# define MAX1407X_VCELL(v) MAX14071_VCELL(v) +#endif + +/* "SOC Register. The SOC register is a read-only register that displays the + * state of charge of the cell as calculated by the ModelGauge algorithm. The + * result is displayed as a percentage of the cell’s full capacity... + * + * "...Units of % can be directly determined by observing only the high byte + * of the SOC register. The low byte provides additional resolution in units + * 1/256%. + */ + +#define MAX1407X_SOC_ADDR 0x04 /* Bits 0-15: Full SOC */ + +/* SoC conversion macros */ + +#define MAX1407X_SOC(s) ((b16_t)(s) << 8) +#define MAX17040_SOC_FULL itob16(95) /* We say full if Soc >= 95% */ + +/* "MODE Register.The MODE register allows the host processor to send special + * commands to the IC." + */ + +#define MAX1407X_MODE_ADDR 0x06 /* Bits 0-15: 16-bit MODE */ + +/* Supported modes */ + +#define MAX1407X_MODE_QUICKSTART 0x4000 + +/* "The VERSION register is a read-only register that contains a value + * indicating the production version of the MAX17040/MAX17041." + */ + +#define MAX1407X_VERSION_ADDR 0x08 /* Bits 0-15: 16-bit VERSION */ + +/* "RCOMP Register. RCOMP is a 16-bit value used to compensate the ModelGauge + * algorithm. RCOMP can be adjusted to optimize performance for different + * lithium chemistries or different operating temperatures... The factory- + * default value for RCOMP is 9700h." + */ + +#define MAX1407X_RCOMP_ADDR 0x0c /* Bits 0-15: 16-bit RCOMP */ + +/* "COMMAND Register. The COMMAND register allows the host processor to send + * special commands to the IC..." + */ + +#define MAX1407X_COMMAND_ADDR 0xfe /* Bits 0-7: 16-bit COMMAND */ + +/* Supported copmmands */ + +#define MAX1407X_COMMAND_POR 0x5400 + +/* Debug ********************************************************************/ + +#ifdef CONFIG_DEBUG_MAX1704X +# define batdbg dbg +#else +# ifdef CONFIG_CPP_HAVE_VARARGS +# define batdbg(x...) +# else +# define batdbg (void) +# endif +#endif + +/**************************************************************************** + * Private + ****************************************************************************/ + +struct max1704x_dev_s +{ + /* The common part of the battery driver visible to the upper-half driver */ + + FAR const struct battery_operations_s *ops; /* Battery operations */ + sem_t batsem; /* Enforce mutually exclusive access */ + + /* Data fields specific to the lower half MAX1704x driver follow */ + + FAR struct i2c_dev_s *i2c; /* I2C interface */ + uint8_t addr; /* I2C address */ + uint32_t frequency; /* I2C frequency */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* I2C support */ + +static int max1704x_getreg16(FAR struct max1704x_dev_s *priv, uint8_t regaddr, + FAR uint16_t *regval); +static int max1704x_putreg16(FAR struct max1704x_dev_s *priv, uint8_t regaddr, + uint16_t regval); + +static inline int max1704x_getvcell(FAR struct max1704x_dev_s *priv, + b16_t *vcell); +static inline int max1704x_getsoc(FAR struct max1704x_dev_s *priv, + b16_t *soc); +static inline int max1704x_setquikstart(FAR struct max1704x_dev_s *priv); +static inline int max1704x_getversion(FAR struct max1704x_dev_s *priv, + uint16_t *version); +static inline int max1704x_reset(FAR struct max1704x_dev_s *priv); + +/* Battery driver lower half methods */ + +static int max1704x_state(struct battery_dev_s *dev, int *status); +static int max1704x_online(struct battery_dev_s *dev, bool *status); +static int max1704x_voltage(struct battery_dev_s *dev, b16_t *value); +static int max1704x_capacity(struct battery_dev_s *dev, b16_t *value); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct battery_operations_s g_max1704xops = +{ + max1704x_state, + max1704x_online, + max1704x_voltage, + max1704x_capacity +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: max1704x_getreg16 + * + * Description: + * Read a 16-bit value from a MAX1704x register pair. + * + * START ACK ACK + * REPEATED-START ACK Data0 ACK Data1 NO-ACK STOP + * + ****************************************************************************/ + +static int max1704x_getreg16(FAR struct max1704x_dev_s *priv, uint8_t regaddr, + FAR uint16_t *regval) +{ + uint8_t buffer[2]; + int ret; + + /* Set the I2C address and address size */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + + /* Write the register address */ + + ret = I2C_WRITE(priv->i2c, ®addr, 1); + if (ret < 0) + { + batdbg("I2C_WRITE failed: %d\n", ret); + return ret; + } + + /* Restart and read 16-bits from the register */ + + ret = I2C_READ(priv->i2c, buffer, 2); + if (ret < 0) + { + batdbg("I2C_READ failed: %d\n", ret); + return ret; + } + + /* Return the 16-bit value */ + + return (uint16_t)buffer[0] << 8 | (uint16_t)buffer[1]; + return OK; +} + +/**************************************************************************** + * Name: max1704x_putreg16 + * + * Description: + * Write a 16-bit value to a MAX1704x register pair. + * + * START ACK ACK Data0 ACK Data1 ACK STOP + * + ****************************************************************************/ + +static int max1704x_putreg16(FAR struct max1704x_dev_s *priv, uint8_t regaddr, + uint16_t regval) +{ + uint8_t buffer[3]; + + batdbg("addr: %02x regval: %08x\n", regaddr, regval); + + /* Set up a 3 byte message to send */ + + buffer[0] = regaddr; + buffer[1] = (uint8_t)(regval >> 8); + buffer[2] = (uint8_t)(regval & 0xff); + + /* Set the I2C address and address size */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + + /* Write the register address followed by the data (no RESTART) */ + + return I2C_WRITE(priv->i2c, buffer, 3); +} + +/**************************************************************************** + * Name: max1704x_getvcell + * + * Description: + * Read the VCELL register and scale the returned value + * + ****************************************************************************/ + +static inline int max1704x_getvcell(FAR struct max1704x_dev_s *priv, + b16_t *vcell) +{ + uint16_t regval = 0; + int ret; + + ret = max1704x_getreg16(priv, MAX1407X_VCELL_ADDR, ®val); + if (ret == OK) + { + *vcell = MAX1407X_VCELL(regval); + } + return ret; +} + +/**************************************************************************** + * Name: max1704x_getsoc + * + * Description: + * Read the SOC register and scale the returned value + * + ****************************************************************************/ + +static inline int max1704x_getsoc(FAR struct max1704x_dev_s *priv, + b16_t *soc) +{ + uint16_t regval = 0; + int ret; + + ret = max1704x_getreg16(priv, MAX1407X_VCELL_ADDR, ®val); + if (ret == OK) + { + *soc = MAX1407X_SOC(regval); + } + return ret; +} + +/**************************************************************************** + * Name: max1704x_setquikstart + * + * Description: + * Set Quickstart mode + * + ****************************************************************************/ + +static inline int max1704x_setquikstart(FAR struct max1704x_dev_s *priv) +{ + return max1704x_putreg16(priv, MAX1407X_MODE_ADDR, MAX1407X_MODE_QUICKSTART); +} + +/**************************************************************************** + * Name: max1704x_getversion + * + * Description: + * Read the SOC register and scale the returned value + * + ****************************************************************************/ + +static inline int max1704x_getversion(FAR struct max1704x_dev_s *priv, + uint16_t *version) +{ + return max1704x_getreg16(priv, MAX1407X_VCELL_ADDR, version); +} + +/**************************************************************************** + * Name: max1704x_setrcomp + * + * Description: + * Set Quickstart mode + * + ****************************************************************************/ + +static inline int max1704x_setrcomp(FAR struct max1704x_dev_s *priv, uint16_t rcomp) +{ + return max1704x_putreg16(priv, MAX1407X_RCOMP_ADDR, rcomp); +} + +/**************************************************************************** + * Name: max1704x_reset + * + * Description: + * Reset the MAX1704x + * + ****************************************************************************/ + +static inline int max1704x_reset(FAR struct max1704x_dev_s *priv) +{ + return max1704x_putreg16(priv, MAX1407X_COMMAND_ADDR, MAX1407X_COMMAND_POR); +} + +/**************************************************************************** + * Name: max1704x_state + * + * Description: + * Return the current battery state + * + ****************************************************************************/ + +static int max1704x_state(struct battery_dev_s *dev, int *status) +{ + FAR struct max1704x_dev_s *priv = (FAR struct max1704x_dev_s *)dev; + b16_t soc = 0; + int ret; + + /* Only a few of the possible battery states are supported by this driver: + * + * BATTERY_UNKNOWN - Returned on error conditions + * BATTERY_IDLE - This is what will usually be reported + * BATTERY_FULL - This will be reported if the SoC is greater than 95% + * BATTERY_CHARGING and BATTERY_DISCHARGING - I don't think this hardware + * knows anything about current (charging or dischargin). + */ + + ret = max1704x_getsoc(priv, &soc); + if (ret < 0) + { + *status = BATTERY_UNKNOWN; + return ret; + } + + /* Is the battery fully charged? */ + + if (soc > MAX17040_SOC_FULL) + { + *status = BATTERY_FULL; + } + else + { + *status = BATTERY_IDLE; + } + + return OK; +} + +/**************************************************************************** + * Name: max1704x_online + * + * Description: + * Return true if the batter is online + * + ****************************************************************************/ + +static int max1704x_online(struct battery_dev_s *dev, bool *status) +{ + /* There is no concept of online/offline in this driver */ + + *status = true; + return OK; +} + +/**************************************************************************** + * Name: max1704x_voltage + * + * Description: + * Current battery voltage + * + ****************************************************************************/ + +static int max1704x_voltage(struct battery_dev_s *dev, b16_t *value) +{ + FAR struct max1704x_dev_s *priv = (FAR struct max1704x_dev_s *)dev; + return max1704x_getvcell(priv, value); +} + +/**************************************************************************** + * Name: max1704x_capacity + * + * Description: + * Battery capacity + * + ****************************************************************************/ + +static int max1704x_capacity(struct battery_dev_s *dev, b16_t *value) +{ + FAR struct max1704x_dev_s *priv = (FAR struct max1704x_dev_s *)dev; + return max1704x_getsoc(priv, value); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: max1704x_initialize + * + * Description: + * Initialize the MAX1704x battery driver and return an instance of the + * lower_half interface that may be used with battery_register(); + * + * This driver requires: + * + * CONFIG_BATTERY - Upper half battery driver support + * CONFIG_I2C - I2C support + * CONFIG_I2C_MAX1704X - And the driver must be explictly selected. + * CONFIG_I2C_MAX17040 or CONFIG_I2C_MAX17041 - The driver must know which + * chip is on the board in order to scale the voltage correctly. + * + * Input Parameters: + * i2c - An instance of the I2C interface to use to communicate with the MAX1704x + * addr - The I2C address of the MAX1704x (Better be 0x36). + * frequency - The I2C frequency + * + * Returned Value: + * A pointer to the intialized lower-half driver instance. A NULL pointer + * is returned on a failure to initialize the MAX1704x lower half. + * + ****************************************************************************/ + +FAR struct battery_dev_s *max1704x_initialize(FAR struct i2c_dev_s *i2c, + uint8_t addr, uint32_t frequency) +{ + FAR struct max1704x_dev_s *priv; +#if 0 + int ret; +#endif + + /* Initialize the MAX1704x device structure */ + + priv = (FAR struct max1704x_dev_s *)kzalloc(sizeof(struct max1704x_dev_s)); + if (priv) + { + /* Initialize the MAX1704x device structure */ + + sem_init(&priv->batsem, 0, 1); + priv->ops = &g_max1704xops; + priv->i2c = i2c; + priv->addr = addr; + priv->frequency = frequency; + + /* Set the I2C frequency (ignoring the returned, actual frequency) */ + + (void)I2C_SETFREQUENCY(i2c, priv->frequency); + + /* Reset the MAX1704x (mostly just to make sure that we can talk to it) */ + +#if 0 + ret = max1704x_reset(priv); + if (ret < 0) + { + batdbg("Failed to reset the MAX1704x: %d\n", ret); + kfree(priv); + return NULL; + } +#endif + } + return (FAR struct battery_dev_s *)priv; +} + +#endif /* CONFIG_BATTERY && CONFIG_I2C && CONFIG_I2C_MAX1704X */ diff --git a/nuttx/drivers/power/pm_activity.c b/nuttx/drivers/power/pm_activity.c new file mode 100644 index 0000000000..f52fc93ff3 --- /dev/null +++ b/nuttx/drivers/power/pm_activity.c @@ -0,0 +1,166 @@ +/**************************************************************************** + * drivers/power/pm_activity.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "pm_internal.h" + +#ifdef CONFIG_PM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pm_activity + * + * Description: + * This function is called by a device driver to indicate that it is + * performing meaningful activities (non-idle). This increments an activity + * count and/or will restart a idle timer and prevent entering reduced + * power states. + * + * Input Parameters: + * priority - Activity priority, range 0-9. Larger values correspond to + * higher priorities. Higher priority activity can prevent the system + * from entering reduced power states for a longer period of time. + * + * As an example, a button press might be higher priority activity because + * it means that the user is actively interacting with the device. + * + * Returned Value: + * None. + * + * Assumptions: + * This function may be called from an interrupt handler (this is the ONLY + * PM function that may be called from an interrupt handler!). + * + ****************************************************************************/ + +void pm_activity(int priority) +{ + uint32_t now; + uint32_t accum; + irqstate_t flags; + + /* Just increment the activity count in the current time slice. The priority + * is simply the number of counts that are added. + */ + + if (priority > 0) + { + /* Add the priority to the accumulated counts in a critical section. */ + + flags = irqsave(); + accum = (uint32_t)g_pmglobals.accum + priority; + + /* Make sure that we do not overflow the underlying uint16_t representation */ + + if (accum > INT16_MAX) + { + accum = INT16_MAX; + } + + /* Save the updated count */ + + g_pmglobals.accum = (int16_t)accum; + + /* Check the elapsed time. In periods of low activity, time slicing is + * controlled by IDLE loop polling; in periods of higher activity, time + * slicing is controlled by driver activity. In either case, the duration + * of the time slice is only approximate; during times of heavy activity, + * time slices may be become longer and the activity level may be over- + * estimated. + */ + + now = clock_systimer(); + if (now - g_pmglobals.stime >= TIME_SLICE_TICKS) + { + int16_t tmp; + + /* Sample the count, reset the time and count, and assess the PM + * state. This is an atomic operation because interrupts are + * still disabled. + */ + + tmp = g_pmglobals.accum; + g_pmglobals.stime = now; + g_pmglobals.accum = 0; + + /* Reassessing the PM state may require some computation. However, + * the work will actually be performed on a worker thread at a user- + * controlled priority. + */ + + (void)pm_update(accum); + } + + irqrestore(flags); + } +} + +#endif /* CONFIG_PM */ \ No newline at end of file diff --git a/nuttx/drivers/power/pm_changestate.c b/nuttx/drivers/power/pm_changestate.c new file mode 100644 index 0000000000..f64760f55b --- /dev/null +++ b/nuttx/drivers/power/pm_changestate.c @@ -0,0 +1,227 @@ +/**************************************************************************** + * drivers/power/pm_changestate.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "pm_internal.h" + +#ifdef CONFIG_PM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pm_prepall + * + * Description: + * Prepare every driver for the state change. + * + * Input Parameters: + * newstate - Identifies the new PM state + * + * Returned Value: + * 0 (OK) means that the callback function for all registered drivers + * returned OK (meaning that they accept the state change). Non-zero + * means that one of the drivers refused the state change. In this case, + * the system will revert to the preceding state. + * + * Assumptions: + * Interrupts are disabled. + * + ****************************************************************************/ + +static int pm_prepall(enum pm_state_e newstate) +{ + FAR sq_entry_t *entry; + int ret = OK; + + /* Visit each registered callback structure. */ + + for (entry = sq_peek(&g_pmglobals.registry); + entry && ret == OK; + entry = sq_next(entry)) + { + /* Is the prepare callback supported? */ + + FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry; + if (cb->prepare) + { + /* Yes.. prepare the driver */ + + ret = cb->prepare(cb, newstate); + } + } + + return ret; +} + +/**************************************************************************** + * Name: pm_changeall + * + * Description: + * Inform all drivers of the state change. + * + * Input Parameters: + * newstate - Identifies the new PM state + * + * Returned Value: + * None + * + * Assumptions: + * Interrupts are disabled. + * + ****************************************************************************/ + +static inline void pm_changeall(enum pm_state_e newstate) +{ + FAR sq_entry_t *entry; + + /* Visit each registered callback structure. */ + + for (entry = sq_peek(&g_pmglobals.registry); entry; entry = sq_next(entry)) + { + /* Is the notification callback supported? */ + + FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry; + if (cb->notify) + { + /* Yes.. notify the driver */ + + cb->notify(cb, newstate); + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pm_changestate + * + * Description: + * This function is used by platform-specific power management logic. It + * will announce the power management power management state change to all + * drivers that have registered for power management event callbacks. + * + * Input Parameters: + * newstate - Identifies the new PM state + * + * Returned Value: + * 0 (OK) means that the callback function for all registered drivers + * returned OK (meaning that they accept the state change). Non-zero + * means that one of the drivers refused the state change. In this case, + * the system will revert to the preceding state. + * + * Assumptions: + * It is assumed that interrupts are disabled when this function is + * called. This function is probably called from the IDLE loop... the + * lowest priority task in the system. Changing driver power management + * states may result in renewed system activity and, as a result, can + * suspend the IDLE thread before it completes the entire state change + * unless interrupts are disabled throughout the state change. + * + ****************************************************************************/ + +int pm_changestate(enum pm_state_e newstate) +{ + irqstate_t flags; + int ret; + + /* Disable interrupts throught this operation... changing driver states + * could cause additional driver activity that might interfere with the + * state change. When the state change is complete, interrupts will be + * re-enabled. + */ + + flags = irqsave(); + + /* First, prepare the drivers for the state change. In this phase, + * drivers may refuse the state state change. + */ + + ret = pm_prepall(newstate); + if (ret != OK) + { + /* One or more drivers is not ready for this state change. Revert to + * the preceding state. + */ + + newstate = g_pmglobals.state; + (void)pm_prepall(newstate); + } + + /* All drivers have agreed to the state change (or, one or more have + * disagreed and the state has been reverted). Set the new state. + */ + + pm_changeall(newstate); + g_pmglobals.state = newstate; + + /* Restore the interrupt state */ + + irqrestore(flags); + return ret; +} + +#endif /* CONFIG_PM */ diff --git a/nuttx/drivers/power/pm_checkstate.c b/nuttx/drivers/power/pm_checkstate.c new file mode 100644 index 0000000000..9b0e1045e7 --- /dev/null +++ b/nuttx/drivers/power/pm_checkstate.c @@ -0,0 +1,161 @@ +/**************************************************************************** + * drivers/power/pm_checkstate.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "pm_internal.h" + +#ifdef CONFIG_PM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pm_checkstate + * + * Description: + * This function is called from the MCU-specific IDLE loop to monitor the + * the power management conditions. This function returns the "recommended" + * power management state based on the PM configuration and activity + * reported in the last sampling periods. The power management state is + * not automatically changed, however. The IDLE loop must call + * pm_changestate() in order to make the state change. + * + * These two steps are separated because the plaform-specific IDLE loop may + * have additional situational information that is not available to the + * the PM sub-system. For example, the IDLE loop may know that the + * battery charge level is very low and may force lower power states + * even if there is activity. + * + * NOTE: That these two steps are separated in time and, hence, the IDLE + * loop could be suspended for a long period of time between calling + * pm_checkstate() and pm_changestate(). The IDLE loop may need to make + * these calls atomic by either disabling interrupts until the state change + * is completed. + * + * Input Parameters: + * None + * + * Returned Value: + * The recommended power management state. + * + ****************************************************************************/ + +enum pm_state_e pm_checkstate(void) +{ + uint32_t now; + irqstate_t flags; + + /* Check for the end of the current time slice. This must be performed + * with interrupts disabled so that it does not conflict with the similar + * logic in pm_activity(). + */ + + flags = irqsave(); + + /* Check the elapsed time. In periods of low activity, time slicing is + * controlled by IDLE loop polling; in periods of higher activity, time + * slicing is controlled by driver activity. In either case, the duration + * of the time slice is only approximate; during times of heavy activity, + * time slices may be become longer and the activity level may be over- + * estimated. + */ + + now = clock_systimer(); + if (now - g_pmglobals.stime >= TIME_SLICE_TICKS) + { + int16_t accum; + + /* Sample the count, reset the time and count, and assess the PM + * state. This is an atomic operation because interrupts are + * still disabled. + */ + + accum = g_pmglobals.accum; + g_pmglobals.stime = now; + g_pmglobals.accum = 0; + + /* Reassessing the PM state may require some computation. However, + * the work will actually be performed on a worker thread at a user- + * controlled priority. + */ + + (void)pm_update(accum); + } + irqrestore(flags); + + /* Return the recommended state. Assuming that we are called from the + * IDLE thread at the lowest priority level, any updates scheduled on the + * worker thread above should have already been peformed and the recommended + * state should be current: + */ + + return g_pmglobals.recommended; +} + +#endif /* CONFIG_PM */ diff --git a/nuttx/drivers/power/pm_initialize.c b/nuttx/drivers/power/pm_initialize.c new file mode 100644 index 0000000000..9401fba9e8 --- /dev/null +++ b/nuttx/drivers/power/pm_initialize.c @@ -0,0 +1,112 @@ +/**************************************************************************** + * drivers/power/pm_initialize.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "pm_internal.h" + +#ifdef CONFIG_PM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* All PM global data: */ + +struct pm_global_s g_pmglobals; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pm_initialize + * + * Description: + * This function is called by MCU-specific one-time at power on reset in + * order to initialize the power management capabilities. This function + * must be called *very* early in the intialization sequence *before* any + * other device drivers are initialize (since they may attempt to register + * with the power management subsystem). + * + * Input parameters: + * None. + * + * Returned value: + * None. + * + ****************************************************************************/ + +void pm_initialize(void) +{ + /* Initialize the registry and the PM global data structures. The PM + * global data structure resides in .bss which is zeroed at boot time. So + * it is only required to initialize non-zero elements of the PM global + * data structure here. + */ + + sq_init(&g_pmglobals.registry); + sem_init(&g_pmglobals.regsem, 0, 1); +} + +#endif /* CONFIG_PM */ \ No newline at end of file diff --git a/nuttx/drivers/power/pm_internal.h b/nuttx/drivers/power/pm_internal.h new file mode 100644 index 0000000000..f98624f150 --- /dev/null +++ b/nuttx/drivers/power/pm_internal.h @@ -0,0 +1,210 @@ +/**************************************************************************** + * drivers/power/pm_internal.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_POWER_PM_INTERNAL_H +#define __DRIVERS_POWER_PM_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#ifdef CONFIG_PM + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +#ifndef CONFIG_SCHED_WORKQUEUE +# warning "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)" +#endif + +/* Convert the time slice interval into system clock ticks. + * + * CONFIG_PM_SLICEMS provides the duration of one time slice in milliseconds. + * CLOCKS_PER_SEC provides the number of timer ticks in one second. + * + * slice ticks = (CONFIG_PM_SLICEMS msec / 1000 msec/sec) / + * (CLOCKS_PER_SEC ticks/sec) + */ + +#define TIME_SLICE_TICKS ((CONFIG_PM_SLICEMS * CLOCKS_PER_SEC) / 1000) + +/* Function-like macros *****************************************************/ +/**************************************************************************** + * Name: pm_lock + * + * Descripton: + * Lock the power management registry. NOTE: This function may return + * an error if a signal is received while what (errno == EINTR). + * + ****************************************************************************/ + +#define pm_lock() sem_wait(&g_pmglobals.regsem); + +/**************************************************************************** + * Name: pm_unlock + * + * Descripton: + * Unlock the power management registry. + * + ****************************************************************************/ + +#define pm_unlock() sem_post(&g_pmglobals.regsem); + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* This structure encapsulates all of the global data used by the PM module */ + +struct pm_global_s +{ + /* state - The current state (as determined by an explicit call to + * pm_changestate() + * recommended - The recommended state based on the PM algorithm in + * function pm_update(). + * mndex - The index to the next slot in the memory[] array to use. + * mcnt - A tiny counter used only at start up. The actual + * algorithm cannot be applied until CONFIG_PM_MEMORY + * samples have been collected. + */ + + uint8_t state; + uint8_t recommended; + uint8_t mndx; + uint8_t mcnt; + + /* accum - The accumulated counts in this time interval + * thrcnt - The number of below threshold counts seen. + */ + + int16_t accum; + uint16_t thrcnt; + + /* This is the averaging "memory." The averaging algorithm is simply: + * Y = (An*X + SUM(Ai*Yi))/SUM(Aj), where i = 1..n-1 and j= 1..n, n is the + * length of the "memory", Ai is the weight applied to each value, and X is + * the current activity. + * + * CONFIG_PM_MEMORY provides the memory for the algorithm. Default: 2 + * CONFIG_PM_COEFn provides weight for each sample. Default: 1 + */ + +#if CONFIG_PM_MEMORY > 1 + int16_t memory[CONFIG_PM_MEMORY-1]; +#endif + + /* stime - The time (in ticks) at the start of the current time slice */ + + uint32_t stime; + + /* This semaphore manages mutually exclusive access to the power management + * registry. It must be initialized to the value 1. + */ + + sem_t regsem; + + /* For work that has been deferred to the worker thread */ + + struct work_s work; + + /* registry is a singly-linked list of registered power management + * callback structures. To ensure mutually exclusive access, this list + * must be locked by calling pm_lock() before it is accessed. + */ + + sq_queue_t registry; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" +{ +#else +# define EXTERN extern +#endif + +/* All PM global data: */ + +EXTERN struct pm_global_s g_pmglobals; + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +/**************************************************************************** + * Name: pm_update + * + * Description: + * This internal function is called at the end of a time slice in order to + * update driver activity metrics and recommended states. + * + * Input Parameters: + * accum - The value of the activity accumulator at the end of the time + * slice. + * + * Returned Value: + * None. + * + * Assumptions: + * This function may be called from a driver, perhaps even at the interrupt + * level. It may also be called from the IDLE loop at the lowest possible + * priority level. To reconcile these various conditions, all work is + * performed on the worker thread at a user-selectable priority. + * + ****************************************************************************/ + +EXTERN void pm_update(int16_t accum); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* CONFIG_PM */ +#endif /* #define __DRIVERS_POWER_PM_INTERNAL_H */ diff --git a/nuttx/drivers/power/pm_register.c b/nuttx/drivers/power/pm_register.c new file mode 100644 index 0000000000..19f94cb026 --- /dev/null +++ b/nuttx/drivers/power/pm_register.c @@ -0,0 +1,112 @@ +/**************************************************************************** + * drivers/power/pm_register.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "pm_internal.h" + +#ifdef CONFIG_PM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pm_register + * + * Description: + * This function is called by a device driver in order to register to + * receive power management event callbacks. + * + * Input parameters: + * callbacks - An instance of struct pm_callback_s providing the driver + * callback functions. + * + * Returned value: + * Zero (OK) on success; otherwise a negater errno value is returned. + * + ****************************************************************************/ + +int pm_register(FAR struct pm_callback_s *callbacks) +{ + int ret; + + DEBUGASSERT(callbacks); + + /* Add the new entry to the end of the list of registered callbacks */ + + ret = pm_lock(); + if (ret == OK) + { + sq_addlast(&callbacks->entry, &g_pmglobals.registry); + pm_unlock(); + } + return ret; +} + +#endif /* CONFIG_PM */ \ No newline at end of file diff --git a/nuttx/drivers/power/pm_update.c b/nuttx/drivers/power/pm_update.c new file mode 100644 index 0000000000..ae5e1f8409 --- /dev/null +++ b/nuttx/drivers/power/pm_update.c @@ -0,0 +1,334 @@ +/**************************************************************************** + * drivers/power/pm_update.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "pm_internal.h" + +#ifdef CONFIG_PM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* CONFIG_PM_MEMORY is the total number of time slices (including the current + * time slice. The histor or previous values is then CONFIG_PM_MEMORY-1. + */ + +#if CONFIG_PM_MEMORY > 1 +static const int16_t g_pmcoeffs[CONFIG_PM_MEMORY-1] = +{ + CONFIG_PM_COEF1 +#if CONFIG_PM_MEMORY > 2 + , CONFIG_PM_COEF2 +#endif +#if CONFIG_PM_MEMORY > 3 + , CONFIG_PM_COEF3 +#endif +#if CONFIG_PM_MEMORY > 4 + , CONFIG_PM_COEF4 +#endif +#if CONFIG_PM_MEMORY > 5 + , CONFIG_PM_COEF5 +#endif +#if CONFIG_PM_MEMORY > 6 +# warning "This logic needs to be extended" +#endif +}; +#endif + +/* Threshold activity values to enter into the next lower power consumption + * state. Indexing is next state 0:IDLE, 1:STANDBY, 2:SLEEP. + */ + +static const int16_t g_pmenterthresh[3] = +{ + CONFIG_PM_IDLEENTER_THRESH, + CONFIG_PM_STANDBYENTER_THRESH, + CONFIG_PM_SLEEPENTER_THRESH +}; + +/* Threshold activity values to leave the current low power consdumption + * state. Indexing is current state 0:IDLE, 1: STANDBY, 2: SLEEP. + */ + +static const int16_t g_pmexitthresh[3] = +{ + CONFIG_PM_IDLEEXIT_THRESH, + CONFIG_PM_STANDBYEXIT_THRESH, + CONFIG_PM_SLEEPEXIT_THRESH +}; + +/* Threshold time slice count to enter the next low power consdumption + * state. Indexing is next state 0:IDLE, 1: STANDBY, 2: SLEEP. + */ + +static const uint16_t g_pmcount[3] = +{ + CONFIG_PM_IDLEENTER_COUNT, + CONFIG_PM_STANDBYENTER_COUNT, + CONFIG_PM_SLEEPENTER_COUNT +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pm_worker + * + * Description: + * This worker function is queue at the end of a time slice in order to + * update driver activity metrics and recommended states. + * + * Input Parameters: + * arg - The value of the activity accumulator at the end of the time + * slice. + * + * Returned Value: + * None. + * + * Assumptions: + * This function runs on the worker thread. + * + ****************************************************************************/ + +void pm_worker(FAR void *arg) +{ + int16_t accum = (int16_t)((intptr_t)arg); + int32_t Y; + int index; + +#if CONFIG_PM_MEMORY > 1 + int32_t denom; + int i, j; + + /* We won't bother to do anything until we have accumulated + * CONFIG_PM_MEMORY-1 samples. + */ + + if (g_pmglobals.mcnt < CONFIG_PM_MEMORY-1) + { + g_pmglobals.memory[g_pmglobals.mcnt] = accum; + g_pmglobals.mcnt++; + return; + } + + /* The averaging algorithm is simply: Y = (An*X + SUM(Ai*Yi))/SUM(Aj), where + * i = 1..n-1 and j= 1..n, n is the length of the "memory", Ai is the + * weight applied to each value, and X is the current activity. + * + * CONFIG_PM_MEMORY provides the memory for the algorithm. Default: 2 + * CONFIG_PM_COEFn provides weight for each sample. Default: 1 + * + * First, calclate Y = An*X + */ + + Y = CONFIG_PM_COEFN * accum; + denom = CONFIG_PM_COEFN; + + /* Then calculate Y += SUM(Ai*Yi), i = 1..n-1. The oldest sample will + * reside at g_pmglobals.mndx (and this is the value that we will overwrite + * with the new value). + */ + + for (i = 0, j = g_pmglobals.mndx; i < CONFIG_PM_MEMORY-1; i++, j++) + { + if (j >= CONFIG_PM_MEMORY-1) + { + j = 0; + } + + Y += g_pmcoeffs[i] * g_pmglobals.memory[j]; + denom += g_pmcoeffs[i]; + } + + /* Compute and save the new activity value */ + + Y /= denom; + g_pmglobals.memory[g_pmglobals.mndx] = Y; + g_pmglobals.mndx++; + if (g_pmglobals.mndx >= CONFIG_PM_MEMORY-1) + { + g_pmglobals.mndx = 0; + } + +#else + + /* No smoothing */ + + Y = accum; + +#endif + + /* First check if increased activity should cause us to return to the + * normal operating state. This would be unlikely for the lowest power + * consumption states because the CPU is probably asleep. However this + * probably does apply for the IDLE state. + */ + + if (g_pmglobals.state > PM_NORMAL) + { + /* Get the table index for the current state (which will be the + * current state minus one) + */ + + index = g_pmglobals.state - 1; + + /* Has the threshold to return to normal power consumption state been + * exceeded? + */ + + if (Y > g_pmexitthresh[index]) + { + /* Yes... reset the count and recommend the normal state. */ + + g_pmglobals.thrcnt = 0; + g_pmglobals.recommended = PM_NORMAL; + return; + } + } + + /* Now, compare this new activity level to the thresholds and counts for + * the next lower power consumption state. If we are already in the SLEEP + * state, then there is nothing more to be done (in fact, I would be + * surprised to be executing!). + */ + + if (g_pmglobals.state < PM_SLEEP) + { + unsigned int nextstate; + + /* Get the next state and the table index for the next state (which will + * be the current state) + */ + + index = g_pmglobals.state; + nextstate = g_pmglobals.state + 1; + + /* Has the threshold to enter the next lower power consumption state + * been exceeded? + */ + + if (Y > g_pmenterthresh[index]) + { + /* No... reset the count and recommend the current state */ + + g_pmglobals.thrcnt = 0; + g_pmglobals.recommended = g_pmglobals.state; + } + + /* Yes.. have we already recommended this state? If so, do nothing */ + + else if (g_pmglobals.recommended < nextstate) + { + /* No.. increment the count. Has is passed the the count required + * for a state transition? + */ + + if (++g_pmglobals.thrcnt >= g_pmcount[index]) + { + /* Yes, recommend the new state and set up for the next + * transition. + */ + + g_pmglobals.thrcnt = 0; + g_pmglobals.recommended = nextstate; + } + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pm_update + * + * Description: + * This internal function is called at the end of a time slice in order to + * update driver activity metrics and recommended states. + * + * Input Parameters: + * accum - The value of the activity accumulator at the end of the time + * slice. + * + * Returned Value: + * None. + * + * Assumptions: + * This function may be called from a driver, perhaps even at the interrupt + * level. It may also be called from the IDLE loop at the lowest possible + * priority level. To reconcile these various conditions, all work is + * performed on the worker thread at a user-selectable priority. This will + * also serialize all of the updates and eliminate any need for additional + * protection. + * + ****************************************************************************/ + +void pm_update(int16_t accum) +{ + /* The work will be performed on the worker thread */ + + DEBUGASSERT(g_pmglobals.work.worker == NULL); + (void)work_queue(&g_pmglobals.work, pm_worker, (FAR void*)((intptr_t)accum), 0); +} + +#endif /* CONFIG_PM */ \ No newline at end of file diff --git a/nuttx/drivers/pwm.c b/nuttx/drivers/pwm.c new file mode 100644 index 0000000000..62fb4d2fb2 --- /dev/null +++ b/nuttx/drivers/pwm.c @@ -0,0 +1,676 @@ +/**************************************************************************** + * drivers/pwm.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#ifdef CONFIG_PWM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Debug ********************************************************************/ +/* Non-standard debug that may be enabled just for testing PWM */ + +#ifdef CONFIG_DEBUG_PWM +# define pwmdbg dbg +# define pwmvdbg vdbg +# define pwmlldbg lldbg +# define pwmllvdbg llvdbg +#else +# define pwmdbg(x...) +# define pwmvdbg(x...) +# define pwmlldbg(x...) +# define pwmllvdbg(x...) +#endif + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +/* This structure describes the state of the upper half driver */ + +struct pwm_upperhalf_s +{ + uint8_t crefs; /* The number of times the device has been opened */ + volatile bool started; /* True: pulsed output is being generated */ +#ifdef CONFIG_PWM_PULSECOUNT + volatile bool waiting; /* True: Caller is waiting for the pulse count to expire */ +#endif + sem_t exclsem; /* Supports mutual exclusion */ +#ifdef CONFIG_PWM_PULSECOUNT + sem_t waitsem; /* Used to wait for the pulse count to expire */ +#endif + struct pwm_info_s info; /* Pulsed output characteristics */ + FAR struct pwm_lowerhalf_s *dev; /* lower-half state */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int pwm_open(FAR struct file *filep); +static int pwm_close(FAR struct file *filep); +static ssize_t pwm_read(FAR struct file *filep, FAR char *buffer, size_t buflen); +static ssize_t pwm_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); +static int pwm_start(FAR struct pwm_upperhalf_s *upper, unsigned int oflags); +static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_pwmops = +{ + pwm_open, /* open */ + pwm_close, /* close */ + pwm_read, /* read */ + pwm_write, /* write */ + 0, /* seek */ + pwm_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , 0 /* poll */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/************************************************************************************ + * Name: pwm_open + * + * Description: + * This function is called whenever the PWM device is opened. + * + ************************************************************************************/ + +static int pwm_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct pwm_upperhalf_s *upper = inode->i_private; + uint8_t tmp; + int ret; + + pwmvdbg("crefs: %d\n", upper->crefs); + + /* Get exclusive access to the device structures */ + + ret = sem_wait(&upper->exclsem); + if (ret < 0) + { + ret = -errno; + goto errout; + } + + /* Increment the count of references to the device. If this the first + * time that the driver has been opened for this device, then initialize + * the device. + */ + + tmp = upper->crefs + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + goto errout_with_sem; + } + + /* Check if this is the first time that the driver has been opened. */ + + if (tmp == 1) + { + FAR struct pwm_lowerhalf_s *lower = upper->dev; + + /* Yes.. perform one time hardware initialization. */ + + DEBUGASSERT(lower->ops->setup != NULL); + pwmvdbg("calling setup\n"); + + ret = lower->ops->setup(lower); + if (ret < 0) + { + goto errout_with_sem; + } + } + + /* Save the new open count on success */ + + upper->crefs = tmp; + ret = OK; + +errout_with_sem: + sem_post(&upper->exclsem); + +errout: + return ret; +} + +/************************************************************************************ + * Name: pwm_close + * + * Description: + * This function is called when the PWM device is closed. + * + ************************************************************************************/ + +static int pwm_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct pwm_upperhalf_s *upper = inode->i_private; + int ret; + + pwmvdbg("crefs: %d\n", upper->crefs); + + /* Get exclusive access to the device structures */ + + ret = sem_wait(&upper->exclsem); + if (ret < 0) + { + ret = -errno; + goto errout; + } + + /* Decrement the references to the driver. If the reference count will + * decrement to 0, then uninitialize the driver. + */ + + if (upper->crefs > 1) + { + upper->crefs--; + } + else + { + FAR struct pwm_lowerhalf_s *lower = upper->dev; + + /* There are no more references to the port */ + + upper->crefs = 0; + + /* Disable the PWM device */ + + DEBUGASSERT(lower->ops->shutdown != NULL); + pwmvdbg("calling shutdown: %d\n"); + + lower->ops->shutdown(lower); + } + ret = OK; + +//errout_with_sem: + sem_post(&upper->exclsem); + +errout: + return ret; +} + +/************************************************************************************ + * Name: pwm_read + * + * Description: + * A dummy read method. This is provided only to satsify the VFS layer. + * + ************************************************************************************/ + +static ssize_t pwm_read(FAR struct file *filep, FAR char *buffer, size_t buflen) +{ + /* Return zero -- usually meaning end-of-file */ + + return 0; +} + +/************************************************************************************ + * Name: pwm_write + * + * Description: + * A dummy write method. This is provided only to satsify the VFS layer. + * + ************************************************************************************/ + +static ssize_t pwm_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) +{ + return 0; +} + +/************************************************************************************ + * Name: pwm_start + * + * Description: + * Handle the PWMIOC_START ioctl command + * + ************************************************************************************/ + +#ifdef CONFIG_PWM_PULSECOUNT +static int pwm_start(FAR struct pwm_upperhalf_s *upper, unsigned int oflags) +{ + FAR struct pwm_lowerhalf_s *lower = upper->dev; + irqstate_t flags; + int ret = OK; + + DEBUGASSERT(upper != NULL && lower->ops->start != NULL); + + /* Verify that the PWM is not already running */ + + if (!upper->started) + { + /* Disable interrupts to avoid race conditions */ + + flags = irqsave(); + + /* Indicate that if will be waiting for the pulse count to complete. + * Note that we will only wait if a non-zero pulse count is specified + * and if the PWM driver was opened in normal, blocking mode. Also + * assume for now that the pulse train will be successfully started. + * + * We do these things before starting the PWM to avoid race conditions. + */ + + upper->waiting = (upper->info.count > 0) && ((oflags & O_NONBLOCK) == 0); + upper->started = true; + + /* Invoke the bottom half method to start the pulse train */ + + ret = lower->ops->start(lower, &upper->info, upper); + + /* A return value of zero means that the pulse train was started + * successfully. + */ + + if (ret == OK) + { + /* Should we wait for the pulse output to complete? Loop in + * in case the wakeup form sem_wait() is a false alarm. + */ + + while (upper->waiting) + { + /* Wait until we are awakened by pwm_expired(). When + * pwm_expired is called, it will post the waitsem and + * clear the waiting flag. + */ + + int tmp = sem_wait(&upper->waitsem); + DEBUGASSERT(tmp == OK || errno == EINTR); + } + } + else + { + /* Looks like we won't be waiting after all */ + + pwmvdbg("start failed: %d\n", ret); + upper->started = false; + upper->waiting = false; + } + + irqrestore(flags); + } + + return ret; +} +#else +static int pwm_start(FAR struct pwm_upperhalf_s *upper, unsigned int oflags) +{ + FAR struct pwm_lowerhalf_s *lower = upper->dev; + int ret = OK; + + DEBUGASSERT(upper != NULL && lower->ops->start != NULL); + + /* Verify that the PWM is not already running */ + + if (!upper->started) + { + /* Invoke the bottom half method to start the pulse train */ + + ret = lower->ops->start(lower, &upper->info); + + /* A return value of zero means that the pulse train was started + * successfully. + */ + + if (ret == OK) + { + /* Indicate that the pulse train has started */ + + upper->started = true; + } + } + + return ret; +} +#endif + +/************************************************************************************ + * Name: pwm_ioctl + * + * Description: + * The standard ioctl method. This is where ALL of the PWM work is done. + * + ************************************************************************************/ + +static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct pwm_upperhalf_s *upper = inode->i_private; + FAR struct pwm_lowerhalf_s *lower = upper->dev; + int ret; + + pwmvdbg("cmd: %d arg: %ld\n", cmd, arg); + + /* Get exclusive access to the device structures */ + + ret = sem_wait(&upper->exclsem); + if (ret < 0) + { + return ret; + } + + /* Handle built-in ioctl commands */ + + switch (cmd) + { + /* PWMIOC_SETCHARACTERISTICS - Set the characteristics of the next pulsed + * output. This command will neither start nor stop the pulsed output. + * It will either setup the configuration that will be used when the + * output is started; or it will change the characteristics of the pulsed + * output on the fly if the timer is already started. + * + * ioctl argument: A read-only reference to struct pwm_info_s that provides + * the characteristics of the pulsed output. + */ + + case PWMIOC_SETCHARACTERISTICS: + { + FAR const struct pwm_info_s *info = (FAR const struct pwm_info_s*)((uintptr_t)arg); + DEBUGASSERT(info != NULL && lower->ops->start != NULL); + +#ifdef CONFIG_PWM_PULSECOUNT + pwmvdbg("PWMIOC_SETCHARACTERISTICS frequency: %d duty: %08x count: %d started: %d\n", + info->frequency, info->duty, info->count, upper->started); +#else + pwmvdbg("PWMIOC_SETCHARACTERISTICS frequency: %d duty: %08x started: %d\n", + info->frequency, info->duty, upper->started); +#endif + + /* Save the pulse train characteristics */ + + memcpy(&upper->info, info, sizeof(struct pwm_info_s)); + + /* If PWM is already running, then re-start it with the new characteristics */ + + if (upper->started) + { +#ifdef CONFIG_PWM_PULSECOUNT + ret = lower->ops->start(lower, &upper->info, upper); +#else + ret = lower->ops->start(lower, &upper->info); +#endif + } + } + break; + + /* PWMIOC_GETCHARACTERISTICS - Get the currently selected characteristics of + * the pulsed output (independent of whether the output is start or stopped). + * + * ioctl argument: A reference to struct pwm_info_s to recevie the + * characteristics of the pulsed output. + */ + + case PWMIOC_GETCHARACTERISTICS: + { + FAR struct pwm_info_s *info = (FAR struct pwm_info_s*)((uintptr_t)arg); + DEBUGASSERT(info != NULL); + + memcpy(info, &upper->info, sizeof(struct pwm_info_s)); + +#ifdef CONFIG_PWM_PULSECOUNT + pwmvdbg("PWMIOC_GETCHARACTERISTICS frequency: %d duty: %08x count: %d\n", + info->frequency, info->duty, info->count); +#else + pwmvdbg("PWMIOC_GETCHARACTERISTICS frequency: %d duty: %08x\n", + info->frequency, info->duty); +#endif + } + break; + + /* PWMIOC_START - Start the pulsed output. The PWMIOC_SETCHARACTERISTICS + * command must have previously been sent. + * + * ioctl argument: None + */ + + case PWMIOC_START: + { +#ifdef CONFIG_PWM_PULSECOUNT + pwmvdbg("PWMIOC_START frequency: %d duty: %08x count: %d started: %d\n", + upper->info.frequency, upper->info.duty, upper->info.count, + upper->started); +#else + pwmvdbg("PWMIOC_START frequency: %d duty: %08x started: %d\n", + upper->info.frequency, upper->info.duty, upper->started); +#endif + DEBUGASSERT(lower->ops->start != NULL); + + /* Start the pulse train */ + + ret = pwm_start(upper, filep->f_oflags); + } + break; + + /* PWMIOC_STOP - Stop the pulsed output. + * + * ioctl argument: None + */ + + case PWMIOC_STOP: + { + pwmvdbg("PWMIOC_STOP: started: %d\n", upper->started); + DEBUGASSERT(lower->ops->stop != NULL); + + if (upper->started) + { + ret = lower->ops->stop(lower); + upper->started = false; +#ifdef CONFIG_PWM_PULSECOUNT + if (upper->waiting) + { + upper->waiting = FALSE; + } +#endif + } + } + break; + + /* Any unrecognized IOCTL commands might be platform-specific ioctl commands */ + + default: + { + pwmvdbg("Forwarding unrecognized cmd: %d arg: %ld\n", cmd, arg); + DEBUGASSERT(lower->ops->ioctl != NULL); + ret = lower->ops->ioctl(lower, cmd, arg); + } + break; + } + + sem_post(&upper->exclsem); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pwm_register + * + * Description: + * This function binds an instance of a "lower half" timer driver with the + * "upper half" PWM device and registers that device so that can be used + * by application code. + * + * When this function is called, the "lower half" driver should be in the + * reset state (as if the shutdown() method had already been called). + * + * Input parameters: + * path - The full path to the driver to be registers in the NuttX pseudo- + * filesystem. The recommended convention is to name all PWM drivers + * as "/dev/pwm0", "/dev/pwm1", etc. where the driver path differs only + * in the "minor" number at the end of the device name. + * dev - A pointer to an instance of lower half timer driver. This instance + * is bound to the PWM driver and must persists as long as the driver + * persists. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +int pwm_register(FAR const char *path, FAR struct pwm_lowerhalf_s *dev) +{ + FAR struct pwm_upperhalf_s *upper; + + /* Allocate the upper-half data structure */ + + upper = (FAR struct pwm_upperhalf_s *)zalloc(sizeof(struct pwm_upperhalf_s)); + if (!upper) + { + pwmdbg("Allocation failed\n"); + return -ENOMEM; + } + + /* Initialize the PWM device structure (it was already zeroed by zalloc()) */ + + sem_init(&upper->exclsem, 0, 1); +#ifdef CONFIG_PWM_PULSECOUNT + sem_init(&upper->waitsem, 0, 0); +#endif + upper->dev = dev; + + /* Register the PWM device */ + + pwmvdbg("Registering %s\n", path); + return register_driver(path, &g_pwmops, 0666, upper); +} + +/**************************************************************************** + * Name: pwm_expired + * + * Description: + * If CONFIG_PWM_PULSECOUNT is defined and the pulse count was configured + * to a non-zero value, then the "upper half" driver will wait for the + * pulse count to expire. The sequence of expected events is as follows: + * + * 1. The upper half driver calls the start method, providing the lower + * half driver with the pulse train characteristics. If a fixed + * number of pulses is required, the 'count' value will be nonzero. + * 2. The lower half driver's start() methoc must verify that it can + * support the request pulse train (frequency, duty, AND pulse count). + * It it cannot, it should return an error. If the pulse count is + * non-zero, it should set up the hardware for that number of pulses + * and return success. NOTE: That is CONFIG_PWM_PULSECOUNT is + * defined, the start() method receives an additional parameter + * that must be used in this callback. + * 3. When the start() method returns success, the upper half driver + * will "sleep" until the pwm_expired method is called. + * 4. When the lower half detects that the pulse count has expired + * (probably through an interrupt), it must call the pwm_expired + * interface using the handle that was previously passed to the + * start() method + * + * Input parameters: + * handle - This is the handle that was provided to the lower-half + * start() method. + * + * Returned Value: + * None + * + * Assumptions: + * This function may be called from an interrupt handler. + * + ****************************************************************************/ + +#ifdef CONFIG_PWM_PULSECOUNT +void pwm_expired(FAR void *handle) +{ + FAR struct pwm_upperhalf_s *upper = (FAR struct pwm_upperhalf_s *)handle; + + pwmllvdbg("started: %d waiting: %d\n", upper->started, upper->waiting); + + /* Make sure that the PWM is started */ + + if (upper->started) + { + /* Is there a thread waiting for the pulse train to complete? */ + + if (upper->waiting) + { + /* Yes.. clear the waiting flag and awakened the waiting thread */ + + upper->waiting = false; + sem_post(&upper->waitsem); + } + + /* The PWM is now stopped */ + + upper->started = false; + } +} +#endif + +#endif /* CONFIG_PWM */ diff --git a/nuttx/drivers/ramdisk.c b/nuttx/drivers/ramdisk.c new file mode 100644 index 0000000000..91912b25c2 --- /dev/null +++ b/nuttx/drivers/ramdisk.c @@ -0,0 +1,342 @@ +/**************************************************************************** + * drivers/ramdisk.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Private Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct rd_struct_s +{ + uint32_t rd_nsectors; /* Number of sectors on device */ + uint16_t rd_sectsize; /* The size of one sector */ +#ifdef CONFIG_FS_WRITABLE + bool rd_writeenabled; /* true: can write to ram disk */ + uint8_t *rd_buffer; /* RAM disk backup memory */ +#else + const uint8_t *rd_buffer; /* ROM disk backup memory */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int rd_open(FAR struct inode *inode); +static int rd_close(FAR struct inode *inode); +static ssize_t rd_read(FAR struct inode *inode, unsigned char *buffer, + size_t start_sector, unsigned int nsectors); +#ifdef CONFIG_FS_WRITABLE +static ssize_t rd_write(FAR struct inode *inode, const unsigned char *buffer, + size_t start_sector, unsigned int nsectors); +#endif +static int rd_geometry(FAR struct inode *inode, struct geometry *geometry); +static int rd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct block_operations g_bops = +{ + rd_open, /* open */ + rd_close, /* close */ + rd_read, /* read */ +#ifdef CONFIG_FS_WRITABLE + rd_write, /* write */ +#else + NULL, /* write */ +#endif + rd_geometry, /* geometry */ + rd_ioctl /* ioctl */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rd_open + * + * Description: Open the block device + * + ****************************************************************************/ + +static int rd_open(FAR struct inode *inode) +{ + fvdbg("Entry\n"); + return OK; +} + +/**************************************************************************** + * Name: rd_closel + * + * Description: close the block device + * + ****************************************************************************/ + +static int rd_close(FAR struct inode *inode) +{ + fvdbg("Entry\n"); + return OK; +} + +/**************************************************************************** + * Name: rd_read + * + * Description: Read the specified numer of sectors + * + ****************************************************************************/ + +static ssize_t rd_read(FAR struct inode *inode, unsigned char *buffer, + size_t start_sector, unsigned int nsectors) +{ + struct rd_struct_s *dev; + + DEBUGASSERT(inode && inode->i_private); + dev = (struct rd_struct_s *)inode->i_private; + + fvdbg("sector: %d nsectors: %d sectorsize: %d\n", + start_sector, dev->rd_sectsize, nsectors); + + if (start_sector < dev->rd_nsectors && + start_sector + nsectors <= dev->rd_nsectors) + { + fvdbg("Transfer %d bytes from %p\n", + nsectors * dev->rd_sectsize, + &dev->rd_buffer[start_sector * dev->rd_sectsize]); + + memcpy(buffer, + &dev->rd_buffer[start_sector * dev->rd_sectsize], + nsectors * dev->rd_sectsize); + return nsectors; + } + + return -EINVAL; +} + +/**************************************************************************** + * Name: rd_write + * + * Description: Write the specified number of sectors + * + ****************************************************************************/ + +#ifdef CONFIG_FS_WRITABLE +static ssize_t rd_write(FAR struct inode *inode, const unsigned char *buffer, + size_t start_sector, unsigned int nsectors) +{ + struct rd_struct_s *dev; + + DEBUGASSERT(inode && inode->i_private); + dev = (struct rd_struct_s *)inode->i_private; + + fvdbg("sector: %d nsectors: %d sectorsize: %d\n", + start_sector, dev->rd_sectsize, nsectors); + + if (!dev->rd_writeenabled) + { + return -EACCES; + } + else if (start_sector < dev->rd_nsectors && + start_sector + nsectors <= dev->rd_nsectors) + { + fvdbg("Transfer %d bytes from %p\n", + nsectors * dev->rd_sectsize, + &dev->rd_buffer[start_sector * dev->rd_sectsize]); + + memcpy(&dev->rd_buffer[start_sector * dev->rd_sectsize], + buffer, + nsectors * dev->rd_sectsize); + return nsectors; + } + + return -EFBIG; +} +#endif + +/**************************************************************************** + * Name: rd_geometry + * + * Description: Return device geometry + * + ****************************************************************************/ + +static int rd_geometry(FAR struct inode *inode, struct geometry *geometry) +{ + struct rd_struct_s *dev; + + fvdbg("Entry\n"); + + DEBUGASSERT(inode); + if (geometry) + { + dev = (struct rd_struct_s *)inode->i_private; + geometry->geo_available = true; + geometry->geo_mediachanged = false; +#ifdef CONFIG_FS_WRITABLE + geometry->geo_writeenabled = dev->rd_writeenabled; +#else + geometry->geo_writeenabled = false; +#endif + geometry->geo_nsectors = dev->rd_nsectors; + geometry->geo_sectorsize = dev->rd_sectsize; + + fvdbg("available: true mediachanged: false writeenabled: %s\n", + geometry->geo_writeenabled ? "true" : "false"); + fvdbg("nsectors: %d sectorsize: %d\n", + geometry->geo_nsectors, geometry->geo_sectorsize); + + return OK; + } + + return -EINVAL; +} + +/**************************************************************************** + * Name: rd_ioctl + * + * Description: Return device geometry + * + ****************************************************************************/ + +static int rd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg) +{ + struct rd_struct_s *dev ; + void **ppv = (void**)((uintptr_t)arg); + + fvdbg("Entry\n"); + + /* Only one ioctl command is supported */ + + DEBUGASSERT(inode && inode->i_private); + if (cmd == BIOC_XIPBASE && ppv) + { + dev = (struct rd_struct_s *)inode->i_private; + *ppv = (void*)dev->rd_buffer; + + fvdbg("ppv: %p\n", *ppv); + return OK; + } + + return -ENOTTY; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ramdisk_register + * + * Description: Register the a ramdisk + + ****************************************************************************/ + +#ifdef CONFIG_FS_WRITABLE +int ramdisk_register(int minor, uint8_t *buffer, uint32_t nsectors, + uint16_t sectsize, bool writeenabled) +#else +int romdisk_register(int minor, uint8_t *buffer, uint32_t nsectors, + uint16_t sectsize) +#endif +{ + struct rd_struct_s *dev; + char devname[16]; + int ret = -ENOMEM; + + fvdbg("buffer: %p nsectors: %d sectsize: %d\n", buffer, nsectors, sectsize); + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (minor < 0 || minor > 255 || !buffer || !nsectors || !sectsize) + { + return -EINVAL; + } +#endif + + /* Allocate a ramdisk device structure */ + + dev = (struct rd_struct_s *)kmalloc(sizeof(struct rd_struct_s)); + if (dev) + { + /* Initialize the ramdisk device structure */ + + dev->rd_nsectors = nsectors; /* Number of sectors on device */ + dev->rd_sectsize = sectsize; /* The size of one sector */ +#ifdef CONFIG_FS_WRITABLE + dev->rd_writeenabled = writeenabled; /* true: can write to ram disk */ +#endif + dev->rd_buffer = buffer; /* RAM disk backup memory */ + + /* Create a ramdisk device name */ + + snprintf(devname, 16, "/dev/ram%d", minor); + + /* Inode private data is a reference to the ramdisk device stgructure */ + + ret = register_blockdriver(devname, &g_bops, 0, dev); + if (ret < 0) + { + fdbg("register_blockdriver failed: %d\n", -ret); + kfree(dev); + } + } + return ret; +} diff --git a/nuttx/drivers/rwbuffer.c b/nuttx/drivers/rwbuffer.c new file mode 100644 index 0000000000..1d924e2a05 --- /dev/null +++ b/nuttx/drivers/rwbuffer.c @@ -0,0 +1,682 @@ +/**************************************************************************** + * drivers/rwbuffer.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if defined(CONFIG_FS_WRITEBUFFER) || defined(CONFIG_FS_READAHEAD) + +/**************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_SCHED_WORKQUEUE +# error "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)" +#endif + +#ifndef CONFIG_FS_WRDELAY +# define CONFIG_FS_WRDELAY 350 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rwb_semtake + ****************************************************************************/ + +static void rwb_semtake(sem_t *sem) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(sem) != 0) + { + /* The only case that an error should occr here is if + * the wait was awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Name: rwb_semgive + ****************************************************************************/ + +#define rwb_semgive(s) sem_post(s) + +/**************************************************************************** + * Name: rwb_overlap + ****************************************************************************/ + +static inline bool rwb_overlap(off_t blockstart1, size_t nblocks1, + off_t blockstart2, size_t nblocks2) +{ + off_t blockend1 = blockstart1 + nblocks1; + off_t blockend2 = blockstart2 + nblocks2; + + /* If the buffer 1 is wholly outside of buffer 2, return false */ + + if ((blockend1 < blockstart2) || /* Wholly "below" */ + (blockstart1 > blockend2)) /* Wholly "above" */ + { + return false; + } + else + { + return true; + } +} + +/**************************************************************************** + * Name: rwb_resetwrbuffer + ****************************************************************************/ + +#ifdef CONFIG_FS_WRITEBUFFER +static inline void rwb_resetwrbuffer(struct rwbuffer_s *rwb) +{ + /* We assume that the caller holds the wrsem */ + + rwb->wrnblocks = 0; + rwb->wrblockstart = (off_t)-1; + rwb->wrexpectedblock = (off_t)-1; +} +#endif + +/**************************************************************************** + * Name: rwb_wrflush + ****************************************************************************/ + +#ifdef CONFIG_FS_WRITEBUFFER +static void rwb_wrflush(struct rwbuffer_s *rwb) +{ + int ret; + + fvdbg("Timeout!\n"); + + rwb_semtake(&rwb->wrsem); + if (rwb->wrnblocks) + { + fvdbg("Flushing: blockstart=0x%08lx nblocks=%d from buffer=%p\n", + (long)rwb->wrblockstart, rwb->wrnblocks, rwb->wrbuffer); + + /* Flush cache. On success, the flush method will return the number + * of blocks written. Anything other than the number requested is + * an error. + */ + + ret = rwb->wrflush(rwb->dev, rwb->wrbuffer, rwb->wrblockstart, rwb->wrnblocks); + if (ret != rwb->wrnblocks) + { + fdbg("ERROR: Error flushing write buffer: %d\n", ret); + } + + rwb_resetwrbuffer(rwb); + } + + rwb_semgive(&rwb->wrsem); +} +#endif + +/**************************************************************************** + * Name: rwb_wrtimeout + ****************************************************************************/ + +static void rwb_wrtimeout(FAR void *arg) +{ + /* The following assumes that the size of a pointer is 4-bytes or less */ + + FAR struct rwbuffer_s *rwb = (struct rwbuffer_s *)arg; + DEBUGASSERT(rwb != NULL); + + /* If a timeout elpases with with write buffer activity, this watchdog + * handler function will be evoked on the thread of execution of the + * worker thread. + */ + + rwb_wrflush(rwb); +} + +/**************************************************************************** + * Name: rwb_wrstarttimeout + ****************************************************************************/ + +static void rwb_wrstarttimeout(FAR struct rwbuffer_s *rwb) +{ + /* CONFIG_FS_WRDELAY provides the delay period in milliseconds. CLK_TCK + * provides the clock tick of the system (frequency in Hz). + */ + + int ticks = (CONFIG_FS_WRDELAY + CLK_TCK/2) / CLK_TCK; + (void)work_queue(&rwb->work, rwb_wrtimeout, (FAR void *)rwb, ticks); +} + +/**************************************************************************** + * Name: rwb_wrcanceltimeout + ****************************************************************************/ + +static inline void rwb_wrcanceltimeout(struct rwbuffer_s *rwb) +{ + (void)work_cancel(&rwb->work); +} + +/**************************************************************************** + * Name: rwb_writebuffer + ****************************************************************************/ + +#ifdef CONFIG_FS_WRITEBUFFER +static ssize_t rwb_writebuffer(FAR struct rwbuffer_s *rwb, + off_t startblock, uint32_t nblocks, + FAR const uint8_t *wrbuffer) +{ + int ret; + + /* Write writebuffer Logic */ + + rwb_wrcanceltimeout(rwb); + + /* First: Should we flush out our cache? We would do that if (1) we already + * buffering blocks and the next block writing is not in the same sequence, + * or (2) the number of blocks would exceed our allocated buffer capacity + */ + + if (((startblock != rwb->wrexpectedblock) && (rwb->wrnblocks)) || + ((rwb->wrnblocks + nblocks) > rwb->wrmaxblocks)) + { + fvdbg("writebuffer miss, expected: %08x, given: %08x\n", + rwb->wrexpectedblock, startblock); + + /* Flush the write buffer */ + + ret = rwb->wrflush(rwb, rwb->wrbuffer, rwb->wrblockstart, rwb->wrnblocks); + if (ret < 0) + { + fdbg("ERROR: Error writing multiple from cache: %d\n", -ret); + return ret; + } + + rwb_resetwrbuffer(rwb); + } + + /* writebuffer is empty? Then initialize it */ + + if (!rwb->wrnblocks) + { + fvdbg("Fresh cache starting at block: 0x%08x\n", startblock); + rwb->wrblockstart = startblock; + } + + /* Add data to cache */ + + fvdbg("writebuffer: copying %d bytes from %p to %p\n", + nblocks * wrb->blocksize, wrbuffer, + &rwb->wrbuffer[rwb->wrnblocks * rwb->blocksize]); + memcpy(&rwb->wrbuffer[rwb->wrnblocks * rwb->blocksize], + wrbuffer, nblocks * rwb->blocksize); + + rwb->wrnblocks += nblocks; + rwb->wrexpectedblock = rwb->wrblockstart + rwb->wrnblocks; + rwb_wrstarttimeout(rwb); + return nblocks; +} +#endif + +/**************************************************************************** + * Name: rwb_resetrhbuffer + ****************************************************************************/ + +#ifdef CONFIG_FS_READAHEAD +static inline void rwb_resetrhbuffer(struct rwbuffer_s *rwb) +{ + /* We assume that the caller holds the readAheadBufferSemphore */ + + rwb->rhnblocks = 0; + rwb->rhblockstart = (off_t)-1; +} +#endif + +/**************************************************************************** + * Name: rwb_bufferread + ****************************************************************************/ + +#ifdef CONFIG_FS_READAHEAD +static inline void +rwb_bufferread(struct rwbuffer_s *rwb, off_t startblock, + size_t nblocks, uint8_t **rdbuffer) +{ + /* We assume that (1) the caller holds the readAheadBufferSemphore, and (2) + * that the caller already knows that all of the blocks are in the + * read-ahead buffer. + */ + + /* Convert the units from blocks to bytes */ + + off_t blockoffset = startblock - rwb->rhblockstart; + off_t byteoffset = rwb->blocksize * blockoffset; + size_t nbytes = rwb->blocksize * nblocks; + + /* Get the byte address in the read-ahead buffer */ + + uint8_t *rhbuffer = rwb->rhbuffer + byteoffset; + + /* Copy the data from the read-ahead buffer into the IO buffer */ + + memcpy(*rdbuffer, rhbuffer, nbytes); + + /* Update the caller's copy for the next address */ + + *rdbuffer += nbytes; +} +#endif + +/**************************************************************************** + * Name: rwb_rhreload + ****************************************************************************/ + +#ifdef CONFIG_FS_READAHEAD +static int rwb_rhreload(struct rwbuffer_s *rwb, off_t startblock) +{ + /* Get the block number +1 of the last block that will fit in the + * read-ahead buffer + */ + + off_t endblock = startblock + rwb->rhmaxblocks; + size_t nblocks; + int ret; + + /* Reset the read buffer */ + + rwb_resetrhbuffer(rwb); + + /* Make sure that we don't read past the end of the device */ + + if (endblock > rwb->nblocks) + { + endblock = rwb->nblocks; + } + + nblocks = endblock - startblock; + + /* Now perform the read */ + + ret = rwb->rhreload(rwb->dev, rwb->rhbuffer, startblock, nblocks); + if (ret == nblocks) + { + /* Update information about what is in the read-ahead buffer */ + + rwb->rhnblocks = nblocks; + rwb->rhblockstart = startblock; + + /* The return value is not the number of blocks we asked to be loaded. */ + + return nblocks; + } + + return -EIO; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: rwb_initialize + ****************************************************************************/ + +int rwb_initialize(FAR struct rwbuffer_s *rwb) +{ + uint32_t allocsize; + + /* Sanity checking */ + + DEBUGASSERT(rwb != NULL); + DEBUGASSERT(rwb->blocksize > 0); + DEBUGASSERT(rwb->nblocks > 0); + DEBUGASSERT(rwb->dev != NULL); + + /* Setup so that rwb_uninitialize can handle a failure */ + +#ifdef CONFIG_FS_WRITEBUFFER + DEBUGASSERT(rwb->wrflush!= NULL); + rwb->wrbuffer = NULL; +#endif +#ifdef CONFIG_FS_READAHEAD + DEBUGASSERT(rwb->rhreload != NULL); + rwb->rhbuffer = NULL; +#endif + +#ifdef CONFIG_FS_WRITEBUFFER + fvdbg("Initialize the write buffer\n"); + + /* Initialize the write buffer access semaphore */ + + sem_init(&rwb->wrsem, 0, 1); + + /* Initialize write buffer parameters */ + + rwb_resetwrbuffer(rwb); + + /* Allocate the write buffer */ + + rwb->wrbuffer = NULL; + if (rwb->wrmaxblocks > 0) + { + allocsize = rwb->wrmaxblocks * rwb->blocksize; + rwb->wrbuffer = kmalloc(allocsize); + if (!rwb->wrbuffer) + { + fdbg("Write buffer kmalloc(%d) failed\n", allocsizee); + return -ENOMEM; + } + } + + fvdbg("Write buffer size: %d bytes\n", allocsize); +#endif /* CONFIG_FS_WRITEBUFFER */ + +#ifdef CONFIG_FS_READAHEAD + fvdbg("Initialize the read-ahead buffer\n"); + + /* Initialize the read-ahead buffer access semaphore */ + + sem_init(&rwb->rhsem, 0, 1); + + /* Initialize read-ahead buffer parameters */ + + rwb_resetrhbuffer(rwb); + + /* Allocate the read-ahead buffer */ + + rwb->rhbuffer = NULL; + if (rwb->rhmaxblocks > 0) + { + allocsize = rwb->rhmaxblocks * rwb->blocksize; + rwb->rhbuffer = kmalloc(allocsize); + if (!rwb->rhbuffer) + { + fdbg("Read-ahead buffer kmalloc(%d) failed\n", allocsize); + return -ENOMEM; + } + } + + fvdbg("Read-ahead buffer size: %d bytes\n", allocsize); +#endif /* CONFIG_FS_READAHEAD */ + return 0; +} + +/**************************************************************************** + * Name: rwb_uninitialize + ****************************************************************************/ + +void rwb_uninitialize(FAR struct rwbuffer_s *rwb) +{ +#ifdef CONFIG_FS_WRITEBUFFER + rwb_wrcanceltimeout(rwb); + sem_destroy(&rwb->wrsem); + if (rwb->wrbuffer) + { + kfree(rwb->wrbuffer); + } +#endif + +#ifdef CONFIG_FS_READAHEAD + sem_destroy(&rwb->rhsem); + if (rwb->rhbuffer) + { + kfree(rwb->rhbuffer); + } +#endif +} + +/**************************************************************************** + * Name: rwb_read + ****************************************************************************/ + +int rwb_read(FAR struct rwbuffer_s *rwb, off_t startblock, uint32_t nblocks, + FAR uint8_t *rdbuffer) +{ + uint32_t remaining; + + fvdbg("startblock=%ld nblocks=%ld rdbuffer=%p\n", + (long)startblock, (long)nblocks, rdbuffer); + +#ifdef CONFIG_FS_WRITEBUFFER + /* If the new read data overlaps any part of the write buffer, then + * flush the write data onto the physical media before reading. We + * could attempt some more exotic handling -- but this simple logic + * is well-suited for simple streaming applications. + */ + + if (rwb->wrmaxblocks > 0) + { + /* If the write buffer overlaps the block(s) requested, then flush the + * write buffer. + */ + + rwb_semtake(&rwb->wrsem); + if (rwb_overlap(rwb->wrblockstart, rwb->wrnblocks, startblock, nblocks)) + { + rwb_wrflush(rwb); + } + rwb_semgive(&rwb->wrsem); + } +#endif + +#ifdef CONFIG_FS_READAHEAD + /* Loop until we have read all of the requested blocks */ + + rwb_semtake(&rwb->rhsem); + for (remaining = nblocks; remaining > 0;) + { + /* Is there anything in the read-ahead buffer? */ + + if (rwb->rhnblocks > 0) + { + off_t startblock = startblock; + size_t nbufblocks = 0; + off_t bufferend; + + /* Loop for each block we find in the read-head buffer. Count the + * number of buffers that we can read from read-ahead buffer. + */ + + bufferend = rwb->rhblockstart + rwb->rhnblocks; + + while ((startblock >= rwb->rhblockstart) && + (startblock < bufferend) && + (remaining > 0)) + { + /* This is one more that we will read from the read ahead buffer */ + + nbufblocks++; + + /* And one less that we will read from the media */ + + startblock++; + remaining--; + } + + /* Then read the data from the read-ahead buffer */ + + rwb_bufferread(rwb, startblock, nbufblocks, &rdbuffer); + } + + /* If we did not get all of the data from the buffer, then we have to refill + * the buffer and try again. + */ + + if (remaining > 0) + { + int ret = rwb_rhreload(rwb, startblock); + if (ret < 0) + { + fdbg("ERROR: Failed to fill the read-ahead buffer: %d\n", -ret); + return ret; + } + } + } + + /* On success, return the number of blocks that we were requested to read. + * This is for compatibility with the normal return of a block driver read + * method + */ + + rwb_semgive(&rwb->rhsem); + return 0; +#else + return rwb->rhreload(rwb->dev, startblock, nblocks, rdbuffer); +#endif +} + +/**************************************************************************** + * Name: rwb_write + ****************************************************************************/ + +int rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock, + size_t nblocks, FAR const uint8_t *wrbuffer) +{ + int ret; + +#ifdef CONFIG_FS_READAHEAD + /* If the new write data overlaps any part of the read buffer, then + * flush the data from the read buffer. We could attempt some more + * exotic handling -- but this simple logic is well-suited for simple + * streaming applications. + */ + + rwb_semtake(&rwb->rhsem); + if (rwb_overlap(rwb->rhblockstart, rwb->rhnblocks, startblock, nblocks)) + { + rwb_resetrhbuffer(rwb); + } + rwb_give(&rwb->rhsem); +#endif + +#ifdef CONFIG_FS_WRITEBUFFER + fvdbg("startblock=%d wrbuffer=%p\n", startblock, wrbuffer); + + /* Use the block cache unless the buffer size is bigger than block cache */ + + if (nblocks > rwb->wrmaxblocks) + { + /* First flush the cache */ + + rwb_semtake(&rwb->wrsem); + rwb_wrflush(rwb); + rwb_semgive(&rwb->wrsem); + + /* Then transfer the data directly to the media */ + + ret = rwb->wrflush(rwb->dev, startblock, nblocks, wrbuffer); + } + else + { + /* Buffer the data in the write buffer */ + + ret = rwb_writebuffer(rwb, startblock, nblocks, wrbuffer); + } + + /* On success, return the number of blocks that we were requested to write. + * This is for compatibility with the normal return of a block driver write + * method + */ + + return ret; + +#else + + return rwb->wrflush(rwb->dev, startblock, nblocks, wrbuffer); + +#endif +} + +/**************************************************************************** + * Name: rwb_mediaremoved + * + * Description: + * The following function is called when media is removed + * + ****************************************************************************/ + +int rwb_mediaremoved(FAR struct rwbuffer_s *rwb) +{ +#ifdef CONFIG_FS_WRITEBUFFER + rwb_semtake(&rwb->wrsem); + rwb_resetwrbuffer(rwb); + rwb_semgive(&rwb->wrsem); +#endif + +#ifdef CONFIG_FS_READAHEAD + rwb_semtake(&rwb->rhsem); + rwb_resetrhbuffer(rwb); + rwb_semgive(&rwb->rhsem); +#endif + return 0; +} + +#endif /* CONFIG_FS_WRITEBUFFER || CONFIG_FS_READAHEAD */ + diff --git a/nuttx/drivers/sensors/Kconfig b/nuttx/drivers/sensors/Kconfig new file mode 100644 index 0000000000..386cdc3a81 --- /dev/null +++ b/nuttx/drivers/sensors/Kconfig @@ -0,0 +1,33 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# +config LIS331DL + bool "ST LIS331DL device support" + default n + select I2C + +config I2C_LM75 + bool + default y if LM75 + +config LM75 + bool "STMicro LM-75 Temperature Sensor support" + default n + select I2C + select I2C_LM75 + +config DEBUG_LM75 + bool "Enable LM-75 debug" + default n + depends on LM75 + +config QENCODER + bool "Qencoder" + default n + +config DEBUG_QENCODER + bool "Enable Qencoder Debug" + default n + depends on QENCODER + diff --git a/nuttx/drivers/sensors/Make.defs b/nuttx/drivers/sensors/Make.defs new file mode 100644 index 0000000000..bd28ba0709 --- /dev/null +++ b/nuttx/drivers/sensors/Make.defs @@ -0,0 +1,57 @@ +############################################################################ +# drivers/sensors/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Include sensor drivers +# These drivers depend on I2C support + +ifeq ($(CONFIG_I2C),y) + CSRCS += lis331dl.c + +ifeq ($(CONFIG_I2C_LM75),y) + CSRCS += lm75.c +endif +endif + +# Quadrature encoder upper half + +ifeq ($(CONFIG_QENCODER),y) + CSRCS += qencoder.c +endif + +# Include sensor driver build support + +DEPPATH += --dep-path sensors +VPATH += :sensors +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/sensors} diff --git a/nuttx/drivers/sensors/lis331dl.c b/nuttx/drivers/sensors/lis331dl.c new file mode 100644 index 0000000000..2117a7ebd7 --- /dev/null +++ b/nuttx/drivers/sensors/lis331dl.c @@ -0,0 +1,320 @@ +/**************************************************************************** + * drivers/sensors/lis331dl.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * + * Authors: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** \file + * \author Uros Platise + * \brief ST LIS331DL I2C Device Driver + **/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +/************************************************************************************ + * LIS331DL Internal Registers + ************************************************************************************/ + +#define ST_LIS331DL_WHOAMI 0x0F /* who am I register */ +#define ST_LIS331DL_WHOAMI_VALUE 0x3B /* Valid result is 0x3B */ + +#define ST_LIS331DL_CTRL_REG1 0x20 +#define ST_LIS331DL_CR1_DR 0x80 /* Data-rate selection 0: 100 Hz, 1: 400 Hz */ +#define ST_LIS331DL_CR1_PD 0x40 /* Active Mode (1) / Power-down (0) */ +#define ST_LIS331DL_CR1_FS 0x20 /* Full Scale (1) +-9g or Normal Scale (0) +-2g */ +#define ST_LIS331DL_CR1_ST 0x18 /* Self test enable */ +#define ST_LIS331DL_CR1_ZEN 0x04 /* Z-Axis Enable */ +#define ST_LIS331DL_CR1_YEN 0x02 /* Y-Axis Enable */ +#define ST_LIS331DL_CR1_XEN 0x01 /* X-Axis Enable */ + +#define ST_LIS331DL_CTRL_REG2 0x21 +#define ST_LIS331DL_CTRL_REG3 0x22 + +#define ST_LIS331DL_HP_FILTER_RESET 0x23 + +#define ST_LIS331DL_STATUS_REG 0x27 /* Status Register */ +#define ST_LIS331DL_SR_ZYXOR 0x80 /* OR'ed X,Y and Z data over-run */ +#define ST_LIS331DL_SR_ZOR 0x40 /* individual data over-run ... */ +#define ST_LIS331DL_SR_YOR 0x20 +#define ST_LIS331DL_SR_XOR 0x10 +#define ST_LIS331DL_SR_ZYXDA 0x08 /* OR'ed X,Y and Z data available */ +#define ST_LIS331DL_SR_ZDA 0x04 /* individual data available ... */ +#define ST_LIS331DL_SR_YDA 0x02 +#define ST_LIS331DL_SR_XDA 0x01 + +#define ST_LIS331DL_OUT_X 0x29 +#define ST_LIS331DL_OUT_Y 0x2B +#define ST_LIS331DL_OUT_Z 0x2D + + +/************************************************************************************ + * Private Data Types + ************************************************************************************/ + +struct lis331dl_dev_s { + struct i2c_dev_s * i2c; + + uint8_t address; + struct lis331dl_vector_s a; + uint8_t cr1; + uint8_t cr2; + uint8_t cr3; +}; + + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/** LIS331DL Access with range check + * + * \param dev LIS331 DL Private Structure + * \param subaddr LIS331 Sub Address + * \param buf Pointer to buffer, either for read or write access + * \param length when >0 it denotes read access, when <0 it denotes write access of -length + * \return OK on success or errno is set. + **/ +int lis331dl_access(struct lis331dl_dev_s * dev, uint8_t subaddr, uint8_t *buf, int length) +{ + uint16_t flags = 0; + int retval; + + if (length > 0) { + flags = I2C_M_READ; + } + else { + flags = I2C_M_NORESTART; + length = -length; + } + + /* Check valid address ranges and set auto address increment flag */ + + if (subaddr == 0x0F) { + if (length > 1) length = 1; + } + else if (subaddr >= 0x20 && subaddr < 0x24) { + if (length > (0x24 - subaddr) ) length = 0x24 - subaddr; + } + else if (subaddr >= 0x27 && subaddr < 0x2E) { + if (length > (0x2E - subaddr) ) length = 0x2E - subaddr; + } + else if (subaddr >= 0x30 && subaddr < 0x40) { + if (length > (0x40 - subaddr) ) length = 0x40 - subaddr; + } + else { + errno = EFAULT; + return ERROR; + } + + if (length > 1) subaddr |= 0x80; + + /* Create message and send */ + + struct i2c_msg_s msgv[2] = { + { + .addr = dev->address, + .flags = 0, + .buffer = &subaddr, + .length = 1 + }, + { + .addr = dev->address, + .flags = flags, + .buffer = buf, + .length = length + } + }; + + if ( (retval = I2C_TRANSFER(dev->i2c, msgv, 2)) == OK ) + return length; + + return retval; +} + + +int lis331dl_readregs(struct lis331dl_dev_s * dev) +{ + if (lis331dl_access(dev, ST_LIS331DL_CTRL_REG1, &dev->cr1, 3) != 3) return ERROR; + return OK; +} + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +struct lis331dl_dev_s * lis331dl_init(struct i2c_dev_s * i2c, uint16_t address) +{ + struct lis331dl_dev_s * dev; + uint8_t retval; + + ASSERT(i2c); + ASSERT(address); + + if ( (dev = kmalloc( sizeof(struct lis331dl_dev_s) )) == NULL ) { + errno = ENOMEM; + return NULL; + } + + memset(dev, 0, sizeof(struct lis331dl_dev_s)); + dev->i2c = i2c; + dev->address = address; + + /* Probe device */ + + if (lis331dl_access(dev, ST_LIS331DL_WHOAMI, &retval, 1) > 0) { + + /* Check chip identification, in the future several more compatible parts + * may be added here. + */ + + if (retval == ST_LIS331DL_WHOAMI_VALUE) { + + /* Copy LIS331DL registers to our private structure and power-up device */ + + if (lis331dl_readregs(dev)==OK && lis331dl_powerup(dev)==OK) { + + /* Normal exit point */ + errno = 0; + return dev; + } + retval = errno; + } + + /* Otherwise, we mark an invalid device found at given address */ + retval = ENODEV; + } + else { + /* No response at given address is marked as */ + retval = EFAULT; + } + + /* Error exit */ + kfree(dev); + errno = retval; + return NULL; +} + + +int lis331dl_deinit(struct lis331dl_dev_s * dev) +{ + ASSERT(dev); + + lis331dl_powerdown(dev); + kfree(dev); + + return OK; +} + + +int lis331dl_powerup(struct lis331dl_dev_s * dev) +{ + dev->cr1 = ST_LIS331DL_CR1_PD | + ST_LIS331DL_CR1_ZEN | ST_LIS331DL_CR1_YEN | ST_LIS331DL_CR1_XEN; + dev->cr2 = 0; + dev->cr3 = 0; + + if (lis331dl_access(dev, ST_LIS331DL_CTRL_REG1, &dev->cr1, -3) == 3) return OK; + return ERROR; +} + + +int lis331dl_powerdown(struct lis331dl_dev_s * dev) +{ + dev->cr1 = ST_LIS331DL_CR1_ZEN | ST_LIS331DL_CR1_YEN | ST_LIS331DL_CR1_XEN; + dev->cr2 = 0; + dev->cr3 = 0; + + if (lis331dl_access(dev, ST_LIS331DL_CTRL_REG1, &dev->cr1, -3) == 3) return OK; + return ERROR; +} + + +int lis331dl_setconversion(struct lis331dl_dev_s * dev, bool full, bool fast) +{ + dev->cr1 = ST_LIS331DL_CR1_PD | + (full ? ST_LIS331DL_CR1_FS : 0) | (fast ? ST_LIS331DL_CR1_DR : 0) | + ST_LIS331DL_CR1_ZEN | ST_LIS331DL_CR1_YEN | ST_LIS331DL_CR1_XEN; + + if (lis331dl_access(dev, ST_LIS331DL_CTRL_REG1, &dev->cr1, -1) == 1) return OK; + return ERROR; +} + + +int lis331dl_getprecision(struct lis331dl_dev_s * dev) +{ + if (dev->cr1 & ST_LIS331DL_CR1_FS) + return 9200/127; /* typ. 9.2g full scale */ + return 2300/127; /* typ. 2.3g full scale */ +} + + +int lis331dl_getsamplerate(struct lis331dl_dev_s * dev) +{ + if (dev->cr1 & ST_LIS331DL_CR1_DR) + return 400; + return 100; +} + + +const struct lis331dl_vector_s * lis331dl_getreadings(struct lis331dl_dev_s * dev) +{ + uint8_t retval[7]; + + ASSERT(dev); + + if (lis331dl_access(dev, ST_LIS331DL_STATUS_REG, retval, 7) == 7) { + + /* If result is not yet ready, return NULL */ + + if ( !(retval[0] & ST_LIS331DL_SR_ZYXDA) ) { + errno = EAGAIN; + return NULL; + } + + dev->a.x = retval[2]; + dev->a.y = retval[4]; + dev->a.z = retval[6]; + return &dev->a; + } + + return NULL; +} diff --git a/nuttx/drivers/sensors/lm75.c b/nuttx/drivers/sensors/lm75.c new file mode 100644 index 0000000000..8e1a0fb4b6 --- /dev/null +++ b/nuttx/drivers/sensors/lm75.c @@ -0,0 +1,537 @@ +/**************************************************************************** + * drivers/sensors/lm75.c + * Character driver for the STMicro LM-75 Temperature Sensor + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#if defined(CONFIG_I2C) && defined(CONFIG_I2C_LM75) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Centigrade to Fahrenheit conversion: F = 9*C/5 + 32 */ + +#define B16_9DIV5 (9 * 65536 / 5) +#define B16_32 (32 * 65536) + +/* Debug for this file only */ + +#ifdef CONFIG_DEBUG_LM75 +# define lm75dbg dbg +#else +# ifdef CONFIG_CPP_HAVE_VARARGS +# define lm75dbg(x...) +# else +# define lm75dbg (void) +# endif +#endif + +/**************************************************************************** + * Private + ****************************************************************************/ + +struct lm75_dev_s +{ + FAR struct i2c_dev_s *i2c; /* I2C interface */ + uint8_t addr; /* I2C address */ + bool fahrenheit; /* true: temperature will be reported in fahrenheit */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* I2C Helpers */ + +static int lm75_readb16(FAR struct lm75_dev_s *priv, uint8_t regaddr, + FAR b16_t *regvalue); +static int lm75_writeb16(FAR struct lm75_dev_s *priv, uint8_t regaddr, + b16_t regval); +static int lm75_readtemp(FAR struct lm75_dev_s *priv, FAR b16_t *temp); +static int lm75_readconf(FAR struct lm75_dev_s *priv, FAR uint8_t *conf); +static int lm75_writeconf(FAR struct lm75_dev_s *priv, uint8_t conf); + +/* Character driver methods */ + +static int lm75_open(FAR struct file *filep); +static int lm75_close(FAR struct file *filep); +static ssize_t lm75_read(FAR struct file *, FAR char *, size_t); +static ssize_t lm75_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); +static int lm75_ioctl(FAR struct file *filep,int cmd,unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_lm75fops = +{ + lm75_open, + lm75_close, + lm75_read, + lm75_write, + 0, + lm75_ioctl +#ifndef CONFIG_DISABLE_POLL + , 0 +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: lm75_readb16 + * + * Description: + * Read a 16-bit register (LM75_TEMP_REG, LM75_THYS_REG, or LM75_TOS_REG) + * + ****************************************************************************/ + +static int lm75_readb16(FAR struct lm75_dev_s *priv, uint8_t regaddr, + FAR b16_t *regvalue) +{ + uint8_t buffer[2]; + int ret; + + /* Write the register address */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + ret = I2C_WRITE(priv->i2c, ®addr, 1); + if (ret < 0) + { + lm75dbg("I2C_WRITE failed: %d\n", ret); + return ret; + } + + /* Restart and read 16-bits from the register (discarding 7) */ + + ret = I2C_READ(priv->i2c, buffer, 2); + if (ret < 0) + { + lm75dbg("I2C_READ failed: %d\n", ret); + return ret; + } + + /* Data format is: TTTTTTTT Txxxxxxx where TTTTTTTTT is a nine-bit, + * signed temperature value with LSB = 0.5 degrees centigrade. So the + * raw data is b8_t + */ + + *regvalue = b8tob16((b8_t)buffer[0] << 8 | (b8_t)buffer[1]); + lm75dbg("addr: %02x value: %08x ret: %d\n", regaddr, *regvalue, ret); + return OK; +} + +/**************************************************************************** + * Name: lm75_writeb16 + * + * Description: + * Write to a 16-bit register (LM75_TEMP_REG, LM75_THYS_REG, or LM75_TOS_REG) + * + ****************************************************************************/ + +static int lm75_writeb16(FAR struct lm75_dev_s *priv, uint8_t regaddr, + b16_t regval) +{ + uint8_t buffer[3]; + b8_t regb8; + + lm75dbg("addr: %02x value: %08x\n", regaddr, regval); + + /* Set up a 3 byte message to send */ + + buffer[0] = regaddr; + + regb8 = b16tob8(regval); + buffer[1] = (uint8_t)(regb8 >> 8); + buffer[2] = (uint8_t)regb8; + + /* Write the register address followed by the data (no RESTART) */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + return I2C_WRITE(priv->i2c, buffer, 3); +} + +/**************************************************************************** + * Name: lm75_readtemp + * + * Description: + * Read the temperature register with special scaling (LM75_TEMP_REG) + * + ****************************************************************************/ + +static int lm75_readtemp(FAR struct lm75_dev_s *priv, FAR b16_t *temp) +{ + b16_t temp16; + int ret; + + /* Read the raw temperature data (b16_t) */ + + ret = lm75_readb16(priv, LM75_TEMP_REG, &temp16); + if (ret < 0) + { + lm75dbg("lm75_readb16 failed: %d\n", ret); + return ret; + } + lm75dbg("Centigrade: %08x\n", temp16); + + /* Was fahrenheit requested? */ + + if (priv->fahrenheit) + { + /* Centigrade to Fahrenheit conversion: F = 9*C/5 + 32 */ + + temp16 = b16mulb16(temp16, B16_9DIV5) + B16_32; + lm75dbg("Fahrenheit: %08x\n", temp16); + } + + *temp = temp16; + return OK; +} + +/**************************************************************************** + * Name: lm75_readconf + * + * Description: + * Read the 8-bit LM75 configuration register + * + ****************************************************************************/ + +static int lm75_readconf(FAR struct lm75_dev_s *priv, FAR uint8_t *conf) +{ + uint8_t buffer; + int ret; + + /* Write the configuration register address */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + + buffer = LM75_CONF_REG; + ret = I2C_WRITE(priv->i2c, &buffer, 1); + if (ret < 0) + { + lm75dbg("I2C_WRITE failed: %d\n", ret); + return ret; + } + + /* Restart and read 8-bits from the register */ + + ret = I2C_READ(priv->i2c, conf, 1); + lm75dbg("conf: %02x ret: %d\n", *conf, ret); + return ret; +} + +/**************************************************************************** + * Name: lm75_writeconf + * + * Description: + * Write to a 8-bit LM75 configuration register. + * + ****************************************************************************/ + +static int lm75_writeconf(FAR struct lm75_dev_s *priv, uint8_t conf) +{ + uint8_t buffer[2]; + + lm75dbg("conf: %02x\n", conf); + + /* Set up a 2 byte message to send */ + + buffer[0] = LM75_CONF_REG; + buffer[1] = conf; + + /* Write the register address followed by the data (no RESTART) */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + return I2C_WRITE(priv->i2c, buffer, 2); +} + +/**************************************************************************** + * Name: lm75_open + * + * Description: + * This function is called whenever the LM-75 device is opened. + * + ****************************************************************************/ + +static int lm75_open(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: lm75_close + * + * Description: + * This routine is called when the LM-75 device is closed. + * + ****************************************************************************/ + +static int lm75_close(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: lm75_read + ****************************************************************************/ + +static ssize_t lm75_read(FAR struct file *filep, FAR char *buffer, size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct lm75_dev_s *priv = inode->i_private; + FAR b16_t *ptr; + ssize_t nsamples; + int i; + int ret; + + /* How many samples were requested to get? */ + + nsamples = buflen / sizeof(b16_t); + ptr = (FAR b16_t *)buffer; + + lm75dbg("buflen: %d nsamples: %d\n", buflen, nsamples); + + /* Get the requested number of samples */ + + for (i = 0; i < nsamples; i++) + { + b16_t temp; + + /* Read the next b16_t temperature value */ + + ret = lm75_readtemp(priv, &temp); + if (ret < 0) + { + lm75dbg("lm75_readtemp failed: %d\n",ret); + return (ssize_t)ret; + } + + /* Save the temperature value in the user buffer */ + + *ptr++ = temp; + } + + return nsamples * sizeof(b16_t); +} + +/**************************************************************************** + * Name: lm75_write + ****************************************************************************/ + +static ssize_t lm75_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + return -ENOSYS; +} + +/**************************************************************************** + * Name: lm75_ioctl + ****************************************************************************/ + +static int lm75_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct lm75_dev_s *priv = inode->i_private; + int ret = OK; + + switch (cmd) + { + /* Read from the configuration register. Arg: uint8_t* pointer */ + + case SNIOC_READCONF: + { + FAR uint8_t *ptr = (FAR uint8_t *)((uintptr_t)arg); + ret = lm75_readconf(priv, ptr); + lm75dbg("conf: %02x ret: %d\n", *ptr, ret); + } + break; + + /* Wrtie to the configuration register. Arg: uint8_t value */ + + case SNIOC_WRITECONF: + ret = lm75_writeconf(priv, (uint8_t)arg); + lm75dbg("conf: %02x ret: %d\n", *(uint8_t*)arg, ret); + break; + + /* Shutdown the LM75, Arg: None */ + + case SNIOC_SHUTDOWN: + { + uint8_t conf; + ret = lm75_readconf(priv, &conf); + if (ret == OK) + { + ret = lm75_writeconf(priv, conf | LM75_CONF_SHUTDOWN); + } + lm75dbg("conf: %02x ret: %d\n", conf | LM75_CONF_SHUTDOWN, ret); + } + break; + + /* Powerup the LM75, Arg: None */ + + case SNIOC_POWERUP: + { + uint8_t conf; + ret = lm75_readconf(priv, &conf); + if (ret == OK) + { + ret = lm75_writeconf(priv, conf & ~LM75_CONF_SHUTDOWN); + } + lm75dbg("conf: %02x ret: %d\n", conf & ~LM75_CONF_SHUTDOWN, ret); + } + break; + + /* Report samples in Fahrenheit */ + + case SNIOC_FAHRENHEIT: + priv->fahrenheit = true; + lm75dbg("Fahrenheit\n"); + break; + + /* Report Samples in Centigrade */ + + case SNIOC_CENTIGRADE: + priv->fahrenheit = false; + lm75dbg("Centigrade\n"); + break; + + /* Read THYS temperature register. Arg: b16_t* pointer */ + + case SNIOC_READTHYS: + { + FAR b16_t *ptr = (FAR b16_t *)((uintptr_t)arg); + ret = lm75_readb16(priv, LM75_THYS_REG, ptr); + lm75dbg("THYS: %08x ret: %d\n", *ptr, ret); + } + break; + + /* Write THYS temperature register. Arg: b16_t value */ + + case SNIOC_WRITETHYS: + ret = lm75_writeb16(priv, LM75_THYS_REG, (b16_t)arg); + lm75dbg("THYS: %08x ret: %d\n", (b16_t)arg, ret); + break; + + /* Read TOS (Over-temp Shutdown Threshold) Register. Arg: b16_t* pointer */ + + case SNIOC_READTOS: + { + FAR b16_t *ptr = (FAR b16_t *)((uintptr_t)arg); + ret = lm75_readb16(priv, LM75_TOS_REG, ptr); + lm75dbg("TOS: %08x ret: %d\n", *ptr, ret); + } + break; + + /* Write TOS (Over-temp Shutdown Threshold) Register. Arg: b16_t value */ + + case SNIOC_WRITRETOS: + ret = lm75_writeb16(priv, LM75_TOS_REG, (b16_t)arg); + lm75dbg("TOS: %08x ret: %d\n", (b16_t)arg, ret); + break; + + default: + lm75dbg("Unrecognized cmd: %d\n", cmd); + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lm75_register + * + * Description: + * Register the LM-75 character device as 'devpath' + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/temp0" + * i2c - An instance of the I2C interface to use to communicate with LM75 + * addr - The I2C address of the LM-75. The base I2C address of the LM75 + * is 0x48. Bits 0-3 can be controlled to get 8 unique addresses from 0x48 + * through 0x4f. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int lm75_register(FAR const char *devpath, FAR struct i2c_dev_s *i2c, uint8_t addr) +{ + FAR struct lm75_dev_s *priv; + int ret; + + /* Initialize the LM-75 device structure */ + + priv = (FAR struct lm75_dev_s *)malloc(sizeof(struct lm75_dev_s)); + if (!priv) + { + lm75dbg("Failed to allocate instance\n"); + return -ENOMEM; + } + + priv->i2c = i2c; + priv->addr = addr; + priv->fahrenheit = false; + + /* Register the character driver */ + + ret = register_driver(devpath, &g_lm75fops, 0666, priv); + if (ret < 0) + { + lm75dbg("Failed to register driver: %d\n", ret); + free(priv); + } + return ret; +} +#endif /* CONFIG_I2C && CONFIG_I2C_LM75 */ diff --git a/nuttx/drivers/sensors/qencoder.c b/nuttx/drivers/sensors/qencoder.c new file mode 100644 index 0000000000..a56adec9ae --- /dev/null +++ b/nuttx/drivers/sensors/qencoder.c @@ -0,0 +1,402 @@ +/**************************************************************************** + * drivers/sensors/qencoder.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#ifdef CONFIG_QENCODER + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Debug ********************************************************************/ +/* Non-standard debug that may be enabled just for testing PWM */ + +#ifdef CONFIG_DEBUG_QENCODER +# define qedbg dbg +# define qevdbg vdbg +# define qelldbg lldbg +# define qellvdbg llvdbg +#else +# define qedbg(x...) +# define qevdbg(x...) +# define qelldbg(x...) +# define qellvdbg(x...) +#endif + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +/* This structure describes the state of the upper half drivere */ + +struct qe_upperhalf_s +{ + uint8_t crefs; /* The number of times the device has been opened */ + sem_t exclsem; /* Supports mutual exclusion */ + FAR struct qe_lowerhalf_s *lower; /* lower-half state */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int qe_open(FAR struct file *filep); +static int qe_close(FAR struct file *filep); +static ssize_t qe_read(FAR struct file *filep, FAR char *buffer, size_t buflen); +static ssize_t qe_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); +static int qe_ioctl(FAR struct file *filep, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_qeops = +{ + qe_open, /* open */ + qe_close, /* close */ + qe_read, /* read */ + qe_write, /* write */ + 0, /* seek */ + qe_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , 0 /* poll */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/************************************************************************************ + * Name: qe_open + * + * Description: + * This function is called whenever the PWM device is opened. + * + ************************************************************************************/ + +static int qe_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct qe_upperhalf_s *upper = inode->i_private; + uint8_t tmp; + int ret; + + qevdbg("crefs: %d\n", upper->crefs); + + /* Get exclusive access to the device structures */ + + ret = sem_wait(&upper->exclsem); + if (ret < 0) + { + ret = -errno; + goto errout; + } + + /* Increment the count of references to the device. If this the first + * time that the driver has been opened for this device, then initialize + * the device. + */ + + tmp = upper->crefs + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + goto errout_with_sem; + } + + /* Check if this is the first time that the driver has been opened. */ + + if (tmp == 1) + { + FAR struct qe_lowerhalf_s *lower = upper->lower; + + /* Yes.. perform one time hardware initialization. */ + + DEBUGASSERT(lower->ops->setup != NULL); + qevdbg("calling setup\n"); + + ret = lower->ops->setup(lower); + if (ret < 0) + { + goto errout_with_sem; + } + } + + /* Save the new open count on success */ + + upper->crefs = tmp; + ret = OK; + +errout_with_sem: + sem_post(&upper->exclsem); + +errout: + return ret; +} + +/************************************************************************************ + * Name: qe_close + * + * Description: + * This function is called when the PWM device is closed. + * + ************************************************************************************/ + +static int qe_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct qe_upperhalf_s *upper = inode->i_private; + int ret; + + qevdbg("crefs: %d\n", upper->crefs); + + /* Get exclusive access to the device structures */ + + ret = sem_wait(&upper->exclsem); + if (ret < 0) + { + ret = -errno; + goto errout; + } + + /* Decrement the references to the driver. If the reference count will + * decrement to 0, then uninitialize the driver. + */ + + if (upper->crefs > 1) + { + upper->crefs--; + } + else + { + FAR struct qe_lowerhalf_s *lower = upper->lower; + + /* There are no more references to the port */ + + upper->crefs = 0; + + /* Disable the PWM device */ + + DEBUGASSERT(lower->ops->shutdown != NULL); + qevdbg("calling shutdown: %d\n"); + + lower->ops->shutdown(lower); + } + ret = OK; + +//errout_with_sem: + sem_post(&upper->exclsem); + +errout: + return ret; +} + +/************************************************************************************ + * Name: qe_read + * + * Description: + * A dummy read method. This is provided only to satsify the VFS layer. + * + ************************************************************************************/ + +static ssize_t qe_read(FAR struct file *filep, FAR char *buffer, size_t buflen) +{ + /* Return zero -- usually meaning end-of-file */ + + return 0; +} + +/************************************************************************************ + * Name: qe_write + * + * Description: + * A dummy write method. This is provided only to satsify the VFS layer. + * + ************************************************************************************/ + +static ssize_t qe_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) +{ + /* Return a failure */ + + return -EPERM; +} + +/************************************************************************************ + * Name: qe_ioctl + * + * Description: + * The standard ioctl method. This is where ALL of the PWM work is done. + * + ************************************************************************************/ + +static int qe_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct qe_upperhalf_s *upper = inode->i_private; + FAR struct qe_lowerhalf_s *lower = upper->lower; + int ret; + + qevdbg("cmd: %d arg: %ld\n", cmd, arg); + DEBUGASSERT(upper && lower); + + /* Get exclusive access to the device structures */ + + ret = sem_wait(&upper->exclsem); + if (ret < 0) + { + return ret; + } + + /* Handle built-in ioctl commands */ + + switch (cmd) + { + /* QEIOC_POSITION - Get the current position from the encoder. + * Argument: int32_t pointer to the location to return the position. + */ + + case QEIOC_POSITION: + { + FAR int32_t *ptr = (FAR int32_t *)((uintptr_t)arg); + DEBUGASSERT(lower->ops->position != NULL && ptr); + ret = lower->ops->position(lower, ptr); + } + break; + + /* QEIOC_RESET - Reset the position to zero. + * Argument: None + */ + + case QEIOC_RESET: + { + DEBUGASSERT(lower->ops->reset != NULL); + ret = lower->ops->reset(lower); + } + break; + + /* Any unrecognized IOCTL commands might be platform-specific ioctl commands */ + + default: + { + qevdbg("Forwarding unrecognized cmd: %d arg: %ld\n", cmd, arg); + DEBUGASSERT(lower->ops->ioctl != NULL); + ret = lower->ops->ioctl(lower, cmd, arg); + } + break; + } + + sem_post(&upper->exclsem); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: qe_register + * + * Description: + * Register the Quadrature Encoder lower half device as 'devpath' + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/qe0" + * lower - An instance of the lower half interface + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. The following + * possible error values may be returned (most are returned by + * register_driver()): + * + * EINVAL - 'path' is invalid for this operation + * EEXIST - An inode already exists at 'path' + * ENOMEM - Failed to allocate in-memory resources for the operation + * + ****************************************************************************/ + +int qe_register(FAR const char *devpath, FAR struct qe_lowerhalf_s *lower) +{ + FAR struct qe_upperhalf_s *upper; + + /* Allocate the upper-half data structure */ + + upper = (FAR struct qe_upperhalf_s *)zalloc(sizeof(struct qe_upperhalf_s)); + if (!upper) + { + qedbg("Allocation failed\n"); + return -ENOMEM; + } + + /* Initialize the PWM device structure (it was already zeroed by zalloc()) */ + + sem_init(&upper->exclsem, 0, 1); + upper->lower = lower; + + /* Register the PWM device */ + + qevdbg("Registering %s\n", devpath); + return register_driver(devpath, &g_qeops, 0666, upper); +} + +#endif /* CONFIG_QENCODER */ diff --git a/nuttx/drivers/sercomm/Kconfig b/nuttx/drivers/sercomm/Kconfig new file mode 100644 index 0000000000..ae2bf31307 --- /dev/null +++ b/nuttx/drivers/sercomm/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# diff --git a/nuttx/drivers/sercomm/Make.defs b/nuttx/drivers/sercomm/Make.defs new file mode 100644 index 0000000000..3585f53146 --- /dev/null +++ b/nuttx/drivers/sercomm/Make.defs @@ -0,0 +1,55 @@ +############################################################################ +# drivers/serial/Make.defs +# +# Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# File descriptor support is needed for this driver + +ifneq ($(CONFIG_NFILE_DESCRIPTORS),0) + +# The sercomm driver should not be build for all platforms. Only build it +# is so configured + +ifeq ($(CONFIG_SERCOMM_CONSOLE),y) + +# Include serial drivers + +CSRCS += console.c uart.c + +# Include sercomm build support + +DEPPATH += --dep-path sercomm +VPATH += :sercomm + +endif +endif diff --git a/nuttx/drivers/sercomm/README.txt b/nuttx/drivers/sercomm/README.txt new file mode 100755 index 0000000000..a9239a2041 --- /dev/null +++ b/nuttx/drivers/sercomm/README.txt @@ -0,0 +1,19 @@ +drivers/sercomm README +====================== + +If CONFIG_SERCOMM_CONSOLE is defined in the NuttX configuration file, NuttX +will attempt to use sercomm (HDLC protocol) to communicate with the +host system. Sercomm is the transport used by osmocom-bb that runs on top +of serial. See http://bb.osmocom.org/trac/wiki/nuttx-bb/run for detailed +the usage of nuttx with sercomm. + +The drivers/sercomm build that you have the osmocom-bb project directory +at same level as the nuttx project: + + |- nuttx + |- apps + `- osmocom-bb + +If you attempt to build this driver without osmocom-bb, you will get +compilation errors because ofheader files that are needed from the +osmocom-bb directory. diff --git a/nuttx/drivers/sercomm/console.c b/nuttx/drivers/sercomm/console.c new file mode 100644 index 0000000000..3d038af7cd --- /dev/null +++ b/nuttx/drivers/sercomm/console.c @@ -0,0 +1,182 @@ +/**************************************************************************** + * drivers/sercomm/console.c + * Driver for NuttX Console + * + * (C) 2010 by Harald Welte + * (C) 2011 Stefan Richter + * + * This source code is derivated from Osmocom-BB project and was + * relicensed as BSD with permission from original authors. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include + +#include "uart.h" +#include + +/* stubs to make serial driver happy */ +void sercomm_recvchars(void *a) { } +void sercomm_xmitchars(void *a) { } + +/* Stubs to make memory allocator happy */ +void cons_puts(void *foo){} +void delay_ms(int ms){} + +/************************************************************************************ + * Fileops Prototypes and Structures + ************************************************************************************/ + +typedef FAR struct file file_t; + +static ssize_t sc_console_read(file_t *filep, FAR char *buffer, size_t buflen); +static ssize_t sc_console_write(file_t *filep, FAR const char *buffer, size_t buflen); +static int sc_console_ioctl(file_t *filep, int cmd, unsigned long arg); +#ifndef CONFIG_DISABLE_POLL +static int sc_console_poll(file_t *filep, FAR struct pollfd *fds, bool setup); +#endif + +static const struct file_operations g_sercom_console_ops = +{ + 0, /* open, always opened */ + 0, /* close, stays open */ + sc_console_read, /* read */ + sc_console_write, /* write */ + 0, /* seek, not supported */ + sc_console_ioctl, /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + sc_console_poll /* poll */ +#endif +}; + +/**************************************************************************** + * Helper functions + ****************************************************************************/ +static FAR uart_dev_t *readdev = NULL; +static struct msgb *recvmsg = NULL; +static void recv_cb(uint8_t dlci, struct msgb *msg) +{ + sem_post(&readdev->recvsem); + recvmsg = msg; +} + +/**************************************************************************** + * Fileops + ****************************************************************************/ + +/* XXX: recvmsg is overwritten when multiple msg arrive! */ +static ssize_t sc_console_read(file_t *filep, FAR char *buffer, size_t buflen) +{ + size_t len; + struct msgb *tmp; + + /* Wait until data is received */ + while(recvmsg == NULL) { + sem_wait(&readdev->recvsem); + } + + len = recvmsg->len > buflen ? buflen : recvmsg->len; + memcpy(buffer, msgb_get(recvmsg, len), len); + + if(recvmsg->len == 0) { + /* prevent inconsistent msg by first invalidating it, then free it */ + tmp = recvmsg; + recvmsg = NULL; + msgb_free(tmp); + } + + return len; +} + +/* XXX: redirect to old Osmocom-BB comm/sercomm_cons.c -> 2 buffers */ +extern int sercomm_puts(const char *s); +static ssize_t sc_console_write(file_t *filep, FAR const char *buffer, size_t buflen) +{ + int i, cnt; + char dstbuf[32]; + + if (buflen >= 31) + cnt = 31; + else + cnt = buflen; + + memcpy(dstbuf, buffer, cnt); + dstbuf[cnt] = '\0'; + + /* print part of our buffer */ + sercomm_puts(dstbuf); + + /* wait a little bit to get data transfered */ + up_mdelay(1); + + return cnt; +} + +/* Forward ioctl to uart driver */ +static int sc_console_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR uart_dev_t *dev = inode->i_private; + + return dev->ops->ioctl(filep, cmd, arg); +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/* Use sercomm on uart driver, register console driver */ +int sercomm_register(FAR const char *path, FAR uart_dev_t *dev) +{ + /* XXX: initialize MODEMUART to be used for sercomm*/ + uart_init(SERCOMM_UART_NR, 1); + uart_baudrate(SERCOMM_UART_NR, UART_115200); + readdev = dev; + sercomm_register_rx_cb(SC_DLCI_LOADER, &recv_cb); + + sem_init(&dev->xmit.sem, 0, 1); + sem_init(&dev->recv.sem, 0, 1); + sem_init(&dev->closesem, 0, 1); + sem_init(&dev->xmitsem, 0, 0); + sem_init(&dev->recvsem, 0, 0); +#ifndef CONFIG_DISABLE_POLL + sem_init(&dev->pollsem, 0, 1); +#endif + + dbg("Registering %s\n", path); + return register_driver(path, &g_sercom_console_ops, 0666, NULL); +} diff --git a/nuttx/drivers/sercomm/loadwriter.py b/nuttx/drivers/sercomm/loadwriter.py new file mode 100644 index 0000000000..6234d6f0d3 --- /dev/null +++ b/nuttx/drivers/sercomm/loadwriter.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +from socket import * +import time + +SOCKET_NAME = '/tmp/osmocom_loader' + +s = socket(AF_UNIX, SOCK_STREAM) +s.connect(SOCKET_NAME) + +while 1: + try: + x = raw_input(">") + y = len(x) + 1 + s.send(chr(y>>8) + chr(y&255) + x + "\n") + except: + print '' + break + +s.close() diff --git a/nuttx/drivers/sercomm/uart.c b/nuttx/drivers/sercomm/uart.c new file mode 100644 index 0000000000..691bba9ecb --- /dev/null +++ b/nuttx/drivers/sercomm/uart.c @@ -0,0 +1,469 @@ +/**************************************************************************** + * drivers/sercomm/uart.c + * Calypso DBB internal UART Driver + * + * (C) 2010 by Harald Welte + * (C) 2010 by Ingo Albrecht + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************/ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +//#include +#include + +#include "uart.h" + +#define BASE_ADDR_UART_MODEM 0xffff5000 +#define OFFSET_IRDA 0x800 + +#define UART_REG(n,m) (BASE_ADDR_UART_MODEM + ((n)*OFFSET_IRDA)+(m)) + +#define LCR7BIT 0x80 +#define LCRBFBIT 0x40 +#define MCR6BIT 0x20 +#define REG_OFFS(m) ((m) & ~(LCR7BIT|LCRBFBIT|MCR6BIT)) +/* read access LCR[7] = 0 */ +enum uart_reg { + RHR = 0, + IER = 1, + IIR = 2, + LCR = 3, + MCR = 4, + LSR = 5, + MSR = 6, + SPR = 7, + MDR1 = 8, + DMR2 = 9, + SFLSR = 0x0a, + RESUME = 0x0b, + SFREGL = 0x0c, + SFREGH = 0x0d, + BLR = 0x0e, + ACREG = 0x0f, + SCR = 0x10, + SSR = 0x11, + EBLR = 0x12, +/* read access LCR[7] = 1 */ + DLL = RHR | LCR7BIT, + DLH = IER | LCR7BIT, + DIV1_6 = ACREG | LCR7BIT, +/* read/write access LCR[7:0] = 0xbf */ + EFR = IIR | LCRBFBIT, + XON1 = MCR | LCRBFBIT, + XON2 = LSR | LCRBFBIT, + XOFF1 = MSR | LCRBFBIT, + XOFF2 = SPR | LCRBFBIT, +/* read/write access if EFR[4] = 1 and MCR[6] = 1 */ + TCR = MSR | MCR6BIT, + TLR = SPR | MCR6BIT, +}; +/* write access LCR[7] = 0 */ +#define THR RHR +#define FCR IIR /* only if EFR[4] = 1 */ +#define TXFLL SFLSR +#define TXFLH RESUME +#define RXFLL SFREGL +#define RXFLH SFREGH + +enum fcr_bits { + FIFO_EN = (1 << 0), + RX_FIFO_CLEAR = (1 << 1), + TX_FIFO_CLEAR = (1 << 2), + DMA_MODE = (1 << 3), +}; +#define TX_FIFO_TRIG_SHIFT 4 +#define RX_FIFO_TRIG_SHIFT 6 + +enum iir_bits { + IIR_INT_PENDING = 0x01, + IIR_INT_TYPE = 0x3E, + IIR_INT_TYPE_RX_STATUS_ERROR = 0x06, + IIR_INT_TYPE_RX_TIMEOUT = 0x0C, + IIR_INT_TYPE_RHR = 0x04, + IIR_INT_TYPE_THR = 0x02, + IIR_INT_TYPE_MSR = 0x00, + IIR_INT_TYPE_XOFF = 0x10, + IIR_INT_TYPE_FLOW = 0x20, + IIR_FCR0_MIRROR = 0xC0, +}; + +#define UART_REG_UIR 0xffff6000 + +/* enable or disable the divisor latch for access to DLL, DLH */ +static void uart_set_lcr7bit(int uart, int on) +{ + uint8_t reg; + + reg = readb(UART_REG(uart, LCR)); + if (on) + reg |= (1 << 7); + else + reg &= ~(1 << 7); + writeb(reg, UART_REG(uart, LCR)); +} + +static uint8_t old_lcr; +static void uart_set_lcr_bf(int uart, int on) +{ + if (on) { + old_lcr = readb(UART_REG(uart, LCR)); + writeb(0xBF, UART_REG(uart, LCR)); + } else { + writeb(old_lcr, UART_REG(uart, LCR)); + } +} + +/* Enable or disable the TCR_TLR latch bit in MCR[6] */ +static void uart_set_mcr6bit(int uart, int on) +{ + uint8_t mcr; + /* we assume EFR[4] is always set to 1 */ + mcr = readb(UART_REG(uart, MCR)); + if (on) + mcr |= (1 << 6); + else + mcr &= ~(1 << 6); + writeb(mcr, UART_REG(uart, MCR)); +} + +static void uart_reg_write(int uart, enum uart_reg reg, uint8_t val) +{ + if (reg & LCRBFBIT) + uart_set_lcr_bf(uart, 1); + else if (reg & LCR7BIT) + uart_set_lcr7bit(uart, 1); + else if (reg & MCR6BIT) + uart_set_mcr6bit(uart, 1); + + writeb(val, UART_REG(uart, REG_OFFS(reg))); + + if (reg & LCRBFBIT) + uart_set_lcr_bf(uart, 0); + else if (reg & LCR7BIT) + uart_set_lcr7bit(uart, 0); + else if (reg & MCR6BIT) + uart_set_mcr6bit(uart, 0); +} + +/* read from a UART register, applying any required latch bits */ +static uint8_t uart_reg_read(int uart, enum uart_reg reg) +{ + uint8_t ret; + + if (reg & LCRBFBIT) + uart_set_lcr_bf(uart, 1); + else if (reg & LCR7BIT) + uart_set_lcr7bit(uart, 1); + else if (reg & MCR6BIT) + uart_set_mcr6bit(uart, 1); + + ret = readb(UART_REG(uart, REG_OFFS(reg))); + + if (reg & LCRBFBIT) + uart_set_lcr_bf(uart, 0); + else if (reg & LCR7BIT) + uart_set_lcr7bit(uart, 0); + else if (reg & MCR6BIT) + uart_set_mcr6bit(uart, 0); + + return ret; +} + +#if 0 +static void uart_irq_handler_cons(__unused enum irq_nr irqnr) +{ + const uint8_t uart = CONS_UART_NR; + uint8_t iir; + + //uart_putchar_nb(uart, 'U'); + + iir = uart_reg_read(uart, IIR); + if (iir & IIR_INT_PENDING) + return; + + switch (iir & IIR_INT_TYPE) { + case IIR_INT_TYPE_RHR: + break; + case IIR_INT_TYPE_THR: + if (cons_rb_flush() == 1) { + /* everything was flushed, disable THR IRQ */ + uint8_t ier = uart_reg_read(uart, IER); + ier &= ~(1 << 1); + uart_reg_write(uart, IER, ier); + } + break; + case IIR_INT_TYPE_MSR: + break; + case IIR_INT_TYPE_RX_STATUS_ERROR: + break; + case IIR_INT_TYPE_RX_TIMEOUT: + break; + case IIR_INT_TYPE_XOFF: + break; + } +} +#endif + +static void uart_irq_handler_sercomm(__unused enum irq_nr irqnr, __unused void *context) +{ + const uint8_t uart = SERCOMM_UART_NR; + uint8_t iir, ch; + + //uart_putchar_nb(uart, 'U'); + + iir = uart_reg_read(uart, IIR); + if (iir & IIR_INT_PENDING) + return; + + switch (iir & IIR_INT_TYPE) { + case IIR_INT_TYPE_RX_TIMEOUT: + case IIR_INT_TYPE_RHR: + /* as long as we have rx data available */ + while (uart_getchar_nb(uart, &ch)) { + if (sercomm_drv_rx_char(ch) < 0) { + /* sercomm cannot receive more data right now */ + uart_irq_enable(uart, UART_IRQ_RX_CHAR, 0); + } + } + break; + case IIR_INT_TYPE_THR: + /* as long as we have space in the FIFO */ + while (!uart_tx_busy(uart)) { + /* get a byte from sercomm */ + if (!sercomm_drv_pull(&ch)) { + /* no more bytes in sercomm, stop TX interrupts */ + uart_irq_enable(uart, UART_IRQ_TX_EMPTY, 0); + break; + } + /* write the byte into the TX FIFO */ + uart_putchar_nb(uart, ch); + } + break; + case IIR_INT_TYPE_MSR: + printf("UART IRQ MSR\n"); + break; + case IIR_INT_TYPE_RX_STATUS_ERROR: + printf("UART IRQ RX_SE\n"); + break; + case IIR_INT_TYPE_XOFF: + printf("UART IRQXOFF\n"); + break; + } +} + +static const uint8_t uart2irq[] = { + [0] = IRQ_UART_IRDA, + [1] = IRQ_UART_MODEM, +}; + +void uart_init(uint8_t uart, uint8_t interrupts) +{ + uint8_t irq = uart2irq[uart]; + + uart_reg_write(uart, IER, 0x00); + + if (uart == SERCOMM_UART_NR) { + sercomm_init(); + irq_attach(IRQ_UART_MODEM, (xcpt_t)uart_irq_handler_sercomm); + up_enable_irq(IRQ_UART_MODEM); + uart_irq_enable(uart, UART_IRQ_RX_CHAR, 1); + } + +#if 0 + if (uart == CONS_UART_NR) { + cons_init(); + if(interrupts) { + irq_register_handler(irq, &uart_irq_handler_cons); + irq_config(irq, 0, 0, 0xff); + irq_enable(irq); + } + } else { + sercomm_init(); + if(interrupts) { + irq_register_handler(irq, &uart_irq_handler_sercomm); + irq_config(irq, 0, 0, 0xff); + irq_enable(irq); + } + uart_irq_enable(uart, UART_IRQ_RX_CHAR, 1); + } +#endif +#if 0 + if (uart == 1) { + /* assign UART to MCU and unmask interrupts*/ + writeb(UART_REG_UIR, 0x00); + } +#endif + + /* if we don't initialize these, we get strange corruptions in the + received data... :-( */ + uart_reg_write(uart, MDR1, 0x07); /* turn off UART */ + uart_reg_write(uart, XON1, 0x00); /* Xon1/Addr Register */ + uart_reg_write(uart, XON2, 0x00); /* Xon2/Addr Register */ + uart_reg_write(uart, XOFF1, 0x00); /* Xoff1 Register */ + uart_reg_write(uart, XOFF2, 0x00); /* Xoff2 Register */ + uart_reg_write(uart, EFR, 0x00); /* Enhanced Features Register */ + + /* select UART mode */ + uart_reg_write(uart, MDR1, 0); + /* no XON/XOFF flow control, ENHANCED_EN, no auto-RTS/CTS */ + uart_reg_write(uart, EFR, (1 << 4)); + /* enable Tx/Rx FIFO, Tx trigger at 56 spaces, Rx trigger at 60 chars */ + uart_reg_write(uart, FCR, FIFO_EN | RX_FIFO_CLEAR | TX_FIFO_CLEAR | + (3 << TX_FIFO_TRIG_SHIFT) | (3 << RX_FIFO_TRIG_SHIFT)); + + /* THR interrupt only when TX FIFO and TX shift register are empty */ + uart_reg_write(uart, SCR, (1 << 0));// | (1 << 3)); + + /* 8 bit, 1 stop bit, no parity, no break */ + uart_reg_write(uart, LCR, 0x03); + + uart_set_lcr7bit(uart, 0); +} + +void uart_poll(uint8_t uart) { +/* if(uart == CONS_UART_NR) { + uart_irq_handler_cons(0); + } else +*/ { + uart_irq_handler_sercomm(0, NULL); + } +} + +void uart_irq_enable(uint8_t uart, enum uart_irq irq, int on) +{ + uint8_t ier = uart_reg_read(uart, IER); + uint8_t mask = 0; + + switch (irq) { + case UART_IRQ_TX_EMPTY: + mask = (1 << 1); + break; + case UART_IRQ_RX_CHAR: + mask = (1 << 0); + break; + } + + if (on) + ier |= mask; + else + ier &= ~mask; + + uart_reg_write(uart, IER, ier); +} + + +void uart_putchar_wait(uint8_t uart, int c) +{ + /* wait while TX FIFO indicates full */ + while (readb(UART_REG(uart, SSR)) & 0x01) { } + + /* put character in TX FIFO */ + writeb(c, UART_REG(uart, THR)); +} + +int uart_putchar_nb(uint8_t uart, int c) +{ + /* if TX FIFO indicates full, abort */ + if (readb(UART_REG(uart, SSR)) & 0x01) + return 0; + + writeb(c, UART_REG(uart, THR)); + return 1; +} + +int uart_getchar_nb(uint8_t uart, uint8_t *ch) +{ + uint8_t lsr; + + lsr = readb(UART_REG(uart, LSR)); + + /* something strange happened */ + if (lsr & 0x02) + printf("LSR RX_OE\n"); + if (lsr & 0x04) + printf("LSR RX_PE\n"); + if (lsr & 0x08) + printf("LSR RX_FE\n"); + if (lsr & 0x10) + printf("LSR RX_BI\n"); + if (lsr & 0x80) + printf("LSR RX_FIFO_STS\n"); + + /* is the Rx FIFO empty? */ + if (!(lsr & 0x01)) + return 0; + + *ch = readb(UART_REG(uart, RHR)); + //printf("getchar_nb(%u) = %02x\n", uart, *ch); + return 1; +} + +int uart_tx_busy(uint8_t uart) +{ + if (readb(UART_REG(uart, SSR)) & 0x01) + return 1; + return 0; +} + +static const uint16_t divider[] = { + [UART_38400] = 21, /* 38,690 */ + [UART_57600] = 14, /* 58,035 */ + [UART_115200] = 7, /* 116,071 */ + [UART_230400] = 4, /* 203,125! (-3% would be 223,488) */ + [UART_460800] = 2, /* 406,250! (-3% would be 446,976) */ + [UART_921600] = 1, /* 812,500! (-3% would be 893,952) */ +}; + +int uart_baudrate(uint8_t uart, enum uart_baudrate bdrt) +{ + uint16_t div; + + if (bdrt > ARRAY_SIZE(divider)) + return -1; + + div = divider[bdrt]; + uart_set_lcr7bit(uart, 1); + writeb(div & 0xff, UART_REG(uart, DLL)); + writeb(div >> 8, UART_REG(uart, DLH)); + uart_set_lcr7bit(uart, 0); + + return 0; +} diff --git a/nuttx/drivers/sercomm/uart.h b/nuttx/drivers/sercomm/uart.h new file mode 100644 index 0000000000..81d7a15609 --- /dev/null +++ b/nuttx/drivers/sercomm/uart.h @@ -0,0 +1,32 @@ +#ifndef _UART_H +#define _UART_H + +#include + +enum uart_baudrate { + UART_38400, + UART_57600, + UART_115200, + UART_230400, + UART_460800, + UART_614400, + UART_921600, +}; + +void uart_init(uint8_t uart, uint8_t interrupts); +void uart_putchar_wait(uint8_t uart, int c); +int uart_putchar_nb(uint8_t uart, int c); +int uart_getchar_nb(uint8_t uart, uint8_t *ch); +int uart_tx_busy(uint8_t uart); +int uart_baudrate(uint8_t uart, enum uart_baudrate bdrt); + +enum uart_irq { + UART_IRQ_TX_EMPTY, + UART_IRQ_RX_CHAR, +}; + +void uart_irq_enable(uint8_t uart, enum uart_irq irq, int on); + +void uart_poll(uint8_t uart); + +#endif /* _UART_H */ diff --git a/nuttx/drivers/serial/Kconfig b/nuttx/drivers/serial/Kconfig new file mode 100644 index 0000000000..b8867bd3f7 --- /dev/null +++ b/nuttx/drivers/serial/Kconfig @@ -0,0 +1,285 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config LOWLEVEL_CONSOLE + bool "Low-level console support" + default n + depends on ARCH_LOWPUTC + +config 16550_UART + bool "16550 UART Chip support" + default n + +if 16550_UART +config 16550_UART0 + bool "16550 UART0" + default n + +if 16550_UART0 +config 16550_UART0_BASE + hex "16550 UART0 base address" + +config 16550_UART0_CLOCK + int "16550 UART0 clock" + +config 16550_UART0_IRQ + int "16550 UART0 IRQ number" + +config 16550_UART0_BAUD + int "16550 UART0 BAUD" + default 115200 + +config 16550_UART0_PARITY + int "16550 UART0 parity" + default 0 + ---help--- + 16550 UART0 parity. 0=None, 1=Odd, 2=Even. Default: None + +config 16550_UART0_BITS + int "16550 UART0 number of bits" + default 8 + ---help--- + 16550 UART0 number of bits. Default: 8 + +config 16550_UART0_2STOP + bool "16550 UART0 two stop bits" + default n + ---help--- + 16550 UART0 two stop bits. Default: 1 + +config 16550_UART0_RXBUFSIZE + int "16550 UART0 Rx buffer size" + default 256 + ---help--- + 16550 UART0 Rx buffer size. Default: 256 + +config 16550_UART0_TXBUFSIZE + int "16550 UART0 Tx buffer size" + default 256 + ---help--- + 16550 UART0 Tx buffer size. Default: 256 + +endif + +config 16550_UART1 + bool "16550 UART1" + default n + +if 16550_UART1 +config 16550_UART1_BASE + hex "16550 UART1 base address" + +config 16550_UART1_CLOCK + int "16550 UART1 clock" + +config 16550_UART1_IRQ + int "16550 UART1 IRQ number" + +config 16550_UART1_BAUD + int "16550 UART1 BAUD" + default 115200 + +config 16550_UART1_PARITY + int "16550 UART1 parity" + default 0 + ---help--- + 16550 UART1 parity. 0=None, 1=Odd, 2=Even. Default: None + +config 16550_UART1_BITS + int "16550 UART1 number of bits" + default 8 + ---help--- + 16550 UART1 number of bits. Default: 8 + +config 16550_UART1_2STOP + bool "16550 UART1 two stop bits" + default n + ---help--- + 16550 UART1 two stop bits. Default: 1 + +config 16550_UART1_RXBUFSIZE + int "16550 UART1 Rx buffer size" + default 256 + ---help--- + 16550 UART1 Rx buffer size. Default: 256 + +config 16550_UART1_TXBUFSIZE + int "16550 UART1 Tx buffer size" + default 256 + ---help--- + 16550 UART1 Tx buffer size. Default: 256 + +endif + +config 16550_UART2 + bool "16550 UART2" + default n + +if 16550_UART2 +config 16550_UART2_BASE + hex "16550 UART2 base address" + +config 16550_UART2_CLOCK + int "16550 UART2 clock" + +config 16550_UART2_IRQ + int "16550 UART2 IRQ number" + +config 16550_UART2_BAUD + int "16550 UART2 BAUD" + default 115200 + +config 16550_UART2_PARITY + int "16550 UART2 parity" + default 0 + ---help--- + 16550 UART2 parity. 0=None, 1=Odd, 2=Even. Default: None + +config 16550_UART2_BITS + int "16550 UART2 number of bits" + default 8 + ---help--- + 16550 UART2 number of bits. Default: 8 + +config 16550_UART2_2STOP + bool "16550 UART2 two stop bits" + default n + ---help--- + 16550 UART2 two stop bits. Default: 1 + +config 16550_UART2_RXBUFSIZE + int "16550 UART2 Rx buffer size" + default 256 + ---help--- + 16550 UART2 Rx buffer size. Default: 256 + +config 16550_UART2_TXBUFSIZE + int "16550 UART2 Tx buffer size" + default 256 + ---help--- + 16550 UART2 Tx buffer size. Default: 256 + +endif + +config 16550_UART3 + bool "16550 UART3" + default n + +if 16550_UART3 +config 16550_UART3_BASE + hex "16550 UART3 base address" + +config 16550_UART3_CLOCK + int "16550 UART3 clock" + +config 16550_UART3_IRQ + int "16550 UART3 IRQ number" + +config 16550_UART3_BAUD + int "16550 UART3 BAUD" + default 115200 + +config 16550_UART3_PARITY + int "16550 UART3 parity" + default 0 + ---help--- + 16550 UART3 parity. 0=None, 1=Odd, 2=Even. Default: None + +config 16550_UART3_BITS + int "16550 UART3 number of bits" + default 8 + ---help--- + 16550 UART3 number of bits. Default: 8 + +config 16550_UART3_2STOP + bool "16550 UART3 two stop bits" + default n + ---help--- + 16550 UART3 two stop bits. Default: 1 + +config 16550_UART3_RXBUFSIZE + int "16550 UART3 Rx buffer size" + default 256 + ---help--- + 16550 UART3 Rx buffer size. Default: 256 + +config 16550_UART3_TXBUFSIZE + int "16550 UART3 Tx buffer size" + default 256 + ---help--- + 16550 UART3 Tx buffer size. Default: 256 + +endif + +choice + prompt "16550 Serial Console" + default NO_SERIAL_CONSOLE + +config UART0_SERIAL_CONSOLE + bool "16550 UART0 serial console" + depends on 16550_UART0 + +config UART1_SERIAL_CONSOLE + bool "16550 UART1 serial console" + depends on 16550_UART1 + +config UART2_SERIAL_CONSOLE + bool "16550 UART2 serial console" + depends on 16550_UART2 + +config UART3_SERIAL_CONSOLE + bool "16550 UART3 serial console" + depends on 16550_UART3 + +config NO_SERIAL_CONSOLE + bool "No 16550 serial console" + +endchoice + +config 16550_SUPRESS_CONFIG + bool "Suppress 16550 configuration" + default n + ---help--- + This option is useful, for example, if you are using a bootloader + that configures the 16550_UART. In that case, you may want to + just leave the existing console configuration in place. Default: n + +config 16550_REGINCR + int "Address increment between 16550 registers" + default 1 + ---help--- + The address increment between 16550 registers. Options are 1, 2, or 4. + Default: 1 + +config 16550_REGWIDTH + int "Bit width of 16550 registers" + default 8 + ---help--- + The bit width of registers. Options are 8, 16, or 32. Default: 8 + +config 16550_ADDRWIDTH + int "Address width of 16550 registers" + default 8 + ---help--- + The bit width of registers. Options are 8, 16, or 32. Default: 8 + +endif + +config STANDARD_SERIAL + bool "Standard serial" + default y if !LOWLEVEL_CONSOLE && !16550_UART + +if STANDARD_SERIAL +config CONFIG_SERIAL_NPOLLWAITERS + int "Number of poll threads" + default 2 + depends on !DISABLE_POLL + ---help--- + Maximum number of threads than can be waiting for POLL events. + Default: 2 + +endif + + diff --git a/nuttx/drivers/serial/Make.defs b/nuttx/drivers/serial/Make.defs new file mode 100644 index 0000000000..b99f4eb362 --- /dev/null +++ b/nuttx/drivers/serial/Make.defs @@ -0,0 +1,50 @@ +############################################################################ +# drivers/serial/Make.defs +# +# Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifneq ($(CONFIG_NFILE_DESCRIPTORS),0) + +# Include serial drivers + +CSRCS += serial.c serialirq.c lowconsole.c + +ifeq ($(CONFIG_16550_UART),y) + CSRCS += uart_16550.c +endif + +# Include serial build support + +DEPPATH += --dep-path serial +VPATH += :serial +endif diff --git a/nuttx/drivers/serial/lowconsole.c b/nuttx/drivers/serial/lowconsole.c new file mode 100644 index 0000000000..1fac49a571 --- /dev/null +++ b/nuttx/drivers/serial/lowconsole.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * drivers/serial/lowconsole.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* The architecture must provide up_putc for this driver */ + +#ifndef CONFIG_ARCH_LOWPUTC +# error "Architecture must provide up_putc() for this driver" +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static ssize_t lowconsole_read(struct file *filep, char *buffer, size_t buflen); +static ssize_t lowconsole_write(struct file *filep, const char *buffer, size_t buflen); +static int lowconsole_ioctl(struct file *filep, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +static const struct file_operations g_consoleops = +{ + 0, /* open */ + 0, /* close */ + lowconsole_read, /* read */ + lowconsole_write, /* write */ + 0, /* seek */ + lowconsole_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , 0 /* poll */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lowconsole_ioctl + ****************************************************************************/ + +static int lowconsole_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + return -ENOTTY; +} + +/**************************************************************************** + * Name: lowconsole_read + ****************************************************************************/ + +static ssize_t lowconsole_read(struct file *filep, char *buffer, size_t buflen) +{ + return 0; +} + +/**************************************************************************** + * Name: lowconsole_write + ****************************************************************************/ + +static ssize_t lowconsole_write(struct file *filep, const char *buffer, size_t buflen) +{ + ssize_t ret = buflen; + + for (; buflen; buflen--) + { + up_putc(*buffer++); + } + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lowconsole_init +****************************************************************************/ + +void lowconsole_init(void) +{ + (void)register_driver("/dev/console", &g_consoleops, 0666, NULL); +} diff --git a/nuttx/drivers/serial/serial.c b/nuttx/drivers/serial/serial.c new file mode 100644 index 0000000000..ea4ceb0c06 --- /dev/null +++ b/nuttx/drivers/serial/serial.c @@ -0,0 +1,855 @@ +/************************************************************************************ + * drivers/serial/serial.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/* The architecture must provide up_putc for this driver */ + +#ifndef CONFIG_ARCH_LOWPUTC +# error "Architecture must provide up_putc() for this driver" +#endif + +#define uart_putc(ch) up_putc(ch) + +#define HALF_SECOND_MSEC 500 +#define HALF_SECOND_USEC 500000L + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/************************************************************************************ + * Private Function Prototypes + ************************************************************************************/ + +static int uart_open(FAR struct file *filep); +static int uart_close(FAR struct file *filep); +static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen); +static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); +static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +#ifndef CONFIG_DISABLE_POLL +static int uart_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup); +#endif + +/************************************************************************************ + * Private Variables + ************************************************************************************/ + +static const struct file_operations g_serialops = +{ + uart_open, /* open */ + uart_close, /* close */ + uart_read, /* read */ + uart_write, /* write */ + 0, /* seek */ + uart_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , uart_poll /* poll */ +#endif +}; + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: uart_takesem + ************************************************************************************/ + +static void uart_takesem(FAR sem_t *sem) +{ + while (sem_wait(sem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(get_errno() == EINTR); + } +} + +/************************************************************************************ + * Name: uart_givesem + ************************************************************************************/ + +#define uart_givesem(sem) (void)sem_post(sem) + +/**************************************************************************** + * Name: uart_pollnotify + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static void uart_pollnotify(FAR uart_dev_t *dev, pollevent_t eventset) +{ + int i; + + for (i = 0; i < CONFIG_SERIAL_NPOLLWAITERS; i++) + { + struct pollfd *fds = dev->fds[i]; + if (fds) + { + fds->revents |= (fds->events & eventset); + if (fds->revents != 0) + { + fvdbg("Report events: %02x\n", fds->revents); + sem_post(fds->sem); + } + } + } +} +#else +# define uart_pollnotify(dev,event) +#endif + +/************************************************************************************ + * Name: uart_putxmitchar + ************************************************************************************/ + +static void uart_putxmitchar(FAR uart_dev_t *dev, int ch) +{ + irqstate_t flags; + int nexthead; + + /* Increment to see what the next head pointer will be. We need to use the "next" + * head pointer to determine when the circular buffer would overrun + */ + + nexthead = dev->xmit.head + 1; + if (nexthead >= dev->xmit.size) + { + nexthead = 0; + } + + /* Loop until we are able to add the character to the TX buffer */ + + for (;;) + { + if (nexthead != dev->xmit.tail) + { + dev->xmit.buffer[dev->xmit.head] = ch; + dev->xmit.head = nexthead; + return; + } + else + { + /* Inform the interrupt level logic that we are waiting. + * This and the following steps must be atomic. + */ + + flags = irqsave(); + dev->xmitwaiting = true; + + /* Wait for some characters to be sent from the buffer + * with the TX interrupt enabled. When the TX interrupt + * is enabled, uart_xmitchars should execute and remove + * some of the data from the TX buffer. + */ + + uart_enabletxint(dev); + uart_takesem(&dev->xmitsem); + uart_disabletxint(dev); + irqrestore(flags); + } + } +} + +/************************************************************************************ + * Name: uart_irqwrite + ************************************************************************************/ + +static ssize_t uart_irqwrite(FAR uart_dev_t *dev, FAR const char *buffer, size_t buflen) +{ + ssize_t ret = buflen; + + /* Force each character through the low level interface */ + + for (; buflen; buflen--) + { + int ch = *buffer++; + uart_putc(ch); + + /* If this is the console, then we should replace LF with LF-CR */ + + if (ch == '\n') + { + uart_putc('\r'); + } + } + + return ret; +} + +/************************************************************************************ + * Name: uart_write + ************************************************************************************/ + +static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR uart_dev_t *dev = inode->i_private; + ssize_t ret = buflen; + + /* We may receive console writes through this path from + * interrupt handlers and from debug output in the IDLE task! + * In these cases, we will need to do things a little + * differently. + */ + + if (up_interrupt_context() || getpid() == 0) + { + if (dev->isconsole) + { + irqstate_t flags = irqsave(); + ret = uart_irqwrite(dev, buffer, buflen); + irqrestore(flags); + return ret; + } + else + { + return ERROR; + } + } + + /* Only one user can be accessing dev->xmit.head at once */ + + uart_takesem(&dev->xmit.sem); + + /* Loop while we still have data to copy to the transmit buffer. + * we add data to the head of the buffer; uart_xmitchars takes the + * data from the end of the buffer. + */ + + uart_disabletxint(dev); + for (; buflen; buflen--) + { + int ch = *buffer++; + + /* Put the character into the transmit buffer */ + + uart_putxmitchar(dev, ch); + + /* If this is the console, then we should replace LF with LF-CR */ + + if ((dev->termios_s.c_oflag && ONLCR) && ch == '\n') + { + uart_putxmitchar(dev, '\r'); + } + } + + if (dev->xmit.head != dev->xmit.tail) + { + uart_enabletxint(dev); + } + + uart_givesem(&dev->xmit.sem); + return ret; +} + +/************************************************************************************ + * Name: uart_read + ************************************************************************************/ + +static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR uart_dev_t *dev = inode->i_private; + irqstate_t flags; + ssize_t recvd = 0; + int16_t tail; + + /* Only one user can be accessing dev->recv.tail at once */ + + uart_takesem(&dev->recv.sem); + + /* Loop while we still have data to copy to the receive buffer. + * we add data to the head of the buffer; uart_xmitchars takes the + * data from the end of the buffer. + */ + + while (recvd < buflen) + { + /* Check if there is more data to return in the circular buffer. + * NOTE: Rx interrupt handling logic may aynchronously increment + * the head index but must not modify the tail index. The tail + * index is only modified in this function. Therefore, no + * special handshaking is required here. + * + * The head and tail pointers are 16-bit values. The only time that + * the following could be unsafe is if the CPU made two non-atomic + * 8-bit accesses to obtain the 16-bit head index. + */ + + tail = dev->recv.tail; + if (dev->recv.head != tail) + { + /* Take the next character from the tail of the buffer */ + + *buffer++ = dev->recv.buffer[tail]; + recvd++; + + /* Increment the tail index. Most operations are done using the + * local variable 'tail' so that the final dev->recv.tail update + * is atomic. + */ + + if (++tail >= dev->recv.size) + { + tail = 0; + } + dev->recv.tail = tail; + } + +#ifdef CONFIG_DEV_SERIAL_FULLBLOCKS + /* No... then we would have to wait to get receive more data. + * If the user has specified the O_NONBLOCK option, then just + * return what we have. + */ + + else if (filep->f_oflags & O_NONBLOCK) + { + /* If nothing was transferred, then return the -EAGAIN + * error (not zero which means end of file). + */ + + if (recvd < 1) + { + recvd = -EAGAIN; + } + break; + } +#else + /* No... the circular buffer is empty. Have we returned anything + * to the caller? + */ + + else if (recvd > 0) + { + /* Yes.. break out of the loop and return the number of bytes + * received up to the wait condition. + */ + + break; + } + + /* No... then we would have to wait to get receive some data. + * If the user has specified the O_NONBLOCK option, then do not + * wait. + */ + + else if (filep->f_oflags & O_NONBLOCK) + { + /* Break out of the loop returning -EAGAIN */ + + recvd = -EAGAIN; + break; + } +#endif + /* Otherwise we are going to have to wait for data to arrive */ + + else + { + /* Disable Rx interrupts and test again... */ + + uart_disablerxint(dev); + + /* If the Rx ring buffer still empty? Bytes may have been addded + * between the last time that we checked and when we disabled Rx + * interrupts. + */ + + if (dev->recv.head == dev->recv.tail) + { + /* Yes.. the buffer is still empty. Wait for some characters + * to be received into the buffer with the RX interrupt re- + * enabled. All interrupts are disabled briefly to assure + * that the following operations are atomic. + */ + + flags = irqsave(); + dev->recvwaiting = true; + uart_enablerxint(dev); + + /* Now wait with the Rx interrupt re-enabled. NuttX will + * automatically re-enable global interrupts when this + * thread goes to sleep. + */ + + uart_takesem(&dev->recvsem); + irqrestore(flags); + } + else + { + /* No... the ring buffer is no longer empty. Just re-enable Rx + * interrupts and accept the new data on the next time through + * the loop. + */ + + uart_enablerxint(dev); + } + } + } + + uart_givesem(&dev->recv.sem); + return recvd; +} + +/************************************************************************************ + * Name: uart_ioctl + ************************************************************************************/ + +static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR uart_dev_t *dev = inode->i_private; + + /* Handle TTY-level IOCTLs here */ + /* Let low-level driver handle the call first */ + int ret = dev->ops->ioctl(filep, cmd, arg); + /* Append any higher level TTY flags */ + switch (cmd) + { + case TCGETS: + { + struct termios *termiosp = (struct termios*)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* Fetch the out flags */ + termiosp->c_oflag = dev->termios_s.c_oflag; + /* Fetch the in flags */ + termiosp->c_iflag = dev->termios_s.c_iflag; + } + break; + + case TCSETS: + { + struct termios *termiosp = (struct termios*)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* Set the out flags */ + dev->termios_s.c_oflag = termiosp->c_oflag; + /* Set the in flags */ + dev->termios_s.c_iflag = termiosp->c_iflag; + } + break; + } + return ret; +} + +/**************************************************************************** + * Name: uart_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +int uart_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) +{ + FAR struct inode *inode = filep->f_inode; + FAR uart_dev_t *dev = inode->i_private; + pollevent_t eventset; + int ndx; + int ret = OK; + int i; + + /* Some sanity checking */ + +#if CONFIG_DEBUG + if (!dev || !fds) + { + return -ENODEV; + } +#endif + + /* Are we setting up the poll? Or tearing it down? */ + + uart_takesem(&dev->pollsem); + if (setup) + { + /* This is a request to set up the poll. Find an available + * slot for the poll structure reference + */ + + for (i = 0; i < CONFIG_SERIAL_NPOLLWAITERS; i++) + { + /* Find an available slot */ + + if (!dev->fds[i]) + { + /* Bind the poll structure and this slot */ + + dev->fds[i] = fds; + fds->priv = &dev->fds[i]; + break; + } + } + + if (i >= CONFIG_SERIAL_NPOLLWAITERS) + { + fds->priv = NULL; + ret = -EBUSY; + goto errout; + } + + /* Should immediately notify on any of the requested events? + * First, check if the xmit buffer is full. + */ + + eventset = 0; + + uart_takesem(&dev->xmit.sem); + ndx = dev->xmit.head + 1; + if (ndx >= dev->xmit.size) + { + ndx = 0; + } + if (ndx != dev->xmit.tail) + { + eventset |= POLLOUT; + } + uart_givesem(&dev->xmit.sem); + + /* Check if the receive buffer is empty */ + + uart_takesem(&dev->recv.sem); + if (dev->recv.head != dev->recv.tail) + { + eventset |= POLLIN; + } + uart_givesem(&dev->recv.sem); + + if (eventset) + { + uart_pollnotify(dev, eventset); + } + + } + else if (fds->priv) + { + /* This is a request to tear down the poll. */ + + struct pollfd **slot = (struct pollfd **)fds->priv; + +#ifdef CONFIG_DEBUG + if (!slot) + { + ret = -EIO; + goto errout; + } +#endif + + /* Remove all memory of the poll setup */ + + *slot = NULL; + fds->priv = NULL; + } + +errout: + uart_givesem(&dev->pollsem); + return ret; +} +#endif + +/************************************************************************************ + * Name: uart_close + * + * Description: + * This routine is called when the serial port gets closed. + * It waits for the last remaining data to be sent. + * + ************************************************************************************/ + +static int uart_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR uart_dev_t *dev = inode->i_private; + irqstate_t flags; + + uart_takesem(&dev->closesem); + if (dev->open_count > 1) + { + dev->open_count--; + uart_givesem(&dev->closesem); + return OK; + } + + /* There are no more references to the port */ + + dev->open_count = 0; + + /* Stop accepting input */ + + uart_disablerxint(dev); + + /* Now we wait for the transmit buffer to clear */ + + while (dev->xmit.head != dev->xmit.tail) + { +#ifndef CONFIG_DISABLE_SIGNALS + usleep(HALF_SECOND_USEC); +#else + up_mdelay(HALF_SECOND_MSEC); +#endif + } + + /* And wait for the TX fifo to drain */ + + while (!uart_txempty(dev)) + { +#ifndef CONFIG_DISABLE_SIGNALS + usleep(HALF_SECOND_USEC); +#else + up_mdelay(HALF_SECOND_MSEC); +#endif + } + + /* Free the IRQ and disable the UART */ + + flags = irqsave(); /* Disable interrupts */ + uart_detach(dev); /* Detach interrupts */ + if (!dev->isconsole) /* Check for the serial console UART */ + { + uart_shutdown(dev); /* Disable the UART */ + } + irqrestore(flags); + + uart_givesem(&dev->closesem); + return OK; + } + +/************************************************************************************ + * Name: uart_open + * + * Description: + * This routine is called whenever a serial port is opened. + * + ************************************************************************************/ + +static int uart_open(FAR struct file *filep) +{ + struct inode *inode = filep->f_inode; + uart_dev_t *dev = inode->i_private; + uint8_t tmp; + int ret = OK; + + /* If the port is the middle of closing, wait until the close is finished */ + + uart_takesem(&dev->closesem); + + /* Start up serial port */ + /* Increment the count of references to the device. */ + + tmp = dev->open_count + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + goto errout_with_sem; + } + + /* Check if this is the first time that the driver has been opened. */ + + if (tmp == 1) + { + irqstate_t flags = irqsave(); + + /* If this is the console, then the UART has already been initialized. */ + + if (!dev->isconsole) + { + /* Perform one time hardware initialization */ + + ret = uart_setup(dev); + if (ret < 0) + { + irqrestore(flags); + goto errout_with_sem; + } + } + + /* In any event, we do have to configure for interrupt driven mode of + * operation. Attach the hardware IRQ(s). Hmm.. should shutdown() the + * the device in the rare case that uart_attach() fails, tmp==1, and + * this is not the console. + */ + + ret = uart_attach(dev); + if (ret < 0) + { + uart_shutdown(dev); + irqrestore(flags); + goto errout_with_sem; + } + + /* Mark the io buffers empty */ + + dev->xmit.head = 0; + dev->xmit.tail = 0; + dev->recv.head = 0; + dev->recv.tail = 0; + + /* Enable the RX interrupt */ + + uart_enablerxint(dev); + irqrestore(flags); + } + + /* Save the new open count on success */ + + dev->open_count = tmp; + +errout_with_sem: + uart_givesem(&dev->closesem); + return ret; +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: uart_register + * + * Description: + * Register serial console and serial ports. + * + ************************************************************************************/ + +int uart_register(FAR const char *path, FAR uart_dev_t *dev) +{ + sem_init(&dev->xmit.sem, 0, 1); + sem_init(&dev->recv.sem, 0, 1); + sem_init(&dev->closesem, 0, 1); + sem_init(&dev->xmitsem, 0, 0); + sem_init(&dev->recvsem, 0, 0); +#ifndef CONFIG_DISABLE_POLL + sem_init(&dev->pollsem, 0, 1); +#endif + /* Setup termios flags */ + memset(&dev->termios_s, 0, sizeof(dev->termios_s)); + if (dev->isconsole == true) + { + /* Device is console, set up termios flags */ + dev->termios_s.c_oflag |= ONLCR; + } + + dbg("Registering %s\n", path); + return register_driver(path, &g_serialops, 0666, dev); +} + +/************************************************************************************ + * Name: uart_datareceived + * + * Description: + * This function is called from uart_recvchars when new serial data is place in + * the driver's circular buffer. This function will wake-up any stalled read() + * operations that are waiting for incoming data. + * + ************************************************************************************/ + +void uart_datareceived(FAR uart_dev_t *dev) +{ + /* Awaken any awaiting read() operations */ + + if (dev->recvwaiting) + { + dev->recvwaiting = false; + (void)sem_post(&dev->recvsem); + } + + /* Notify all poll/select waiters that they can read from the recv buffer */ + + uart_pollnotify(dev, POLLIN); + +} + +/************************************************************************************ + * Name: uart_datasent + * + * Description: + * This function is called from uart_xmitchars after serial data has been sent, + * freeing up some space in the driver's circular buffer. This function will + * wake-up any stalled write() operations that was waiting for space to buffer + * outgoing data. + * + ************************************************************************************/ + +void uart_datasent(FAR uart_dev_t *dev) +{ + if (dev->xmitwaiting) + { + dev->xmitwaiting = false; + (void)sem_post(&dev->xmitsem); + } + + /* Notify all poll/select waiters that they can write to xmit buffer */ + + uart_pollnotify(dev, POLLOUT); +} + + diff --git a/nuttx/drivers/serial/serialirq.c b/nuttx/drivers/serial/serialirq.c new file mode 100644 index 0000000000..fda5b4afb5 --- /dev/null +++ b/nuttx/drivers/serial/serialirq.c @@ -0,0 +1,186 @@ +/************************************************************************************ + * drivers/serial/serialirq.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/************************************************************************************ + * Private Function Prototypes + ************************************************************************************/ + +/************************************************************************************ + * Private Variables + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: uart_xmitchars + * + * Description: + * This function is called from the UART interrupt handler when an interrupt + * is received indicating that there is more space in the transmit FIFO. This + * function will send characters from the tail of the xmit buffer while the driver + * write() logic adds data to the head of the xmit buffer. + * + ************************************************************************************/ + +void uart_xmitchars(FAR uart_dev_t *dev) +{ + uint16_t nbytes = 0; + + /* Send while we still have data & room in the fifo */ + + while (dev->xmit.head != dev->xmit.tail && uart_txready(dev)) + { + /* Send the next byte */ + + uart_send(dev, dev->xmit.buffer[dev->xmit.tail]); + nbytes++; + + /* Increment the tail index */ + + if (++(dev->xmit.tail) >= dev->xmit.size) + { + dev->xmit.tail = 0; + } + } + + /* When all of the characters have been sent from the buffer disable the TX + * interrupt. + */ + + if (dev->xmit.head == dev->xmit.tail) + { + uart_disabletxint(dev); + } + + /* If any bytes were removed from the buffer, inform any waiters there there is + * space available. + */ + + if (nbytes) + { + uart_datasent(dev); + } +} + +/************************************************************************************ + * Name: uart_receivechars + * + * Description: + * This function is called from the UART interrupt handler when an interrupt + * is received indicating that are bytes available in the receive fifo. This + * function will add chars to head of receive buffer. Driver read() logic will + * take characters from the tail of the buffer. + * + ************************************************************************************/ + +void uart_recvchars(FAR uart_dev_t *dev) +{ + unsigned int status; + int nexthead = dev->recv.head + 1; + uint16_t nbytes = 0; + + if (nexthead >= dev->recv.size) + { + nexthead = 0; + } + + /* Loop putting characters into the receive buffer until either there are no + * further characters to available. + */ + + while (uart_rxavailable(dev)) + { + char ch = uart_receive(dev, &status); + + /* If the RX buffer becomes full, then the serial data is discarded. This is + * necessary because on most serial hardware, you must read the data in order + * to clear the RX interrupt. An option on some hardware might be to simply + * disable RX interrupts until the RX buffer becomes non-FULL. However, that + * would probably just cause the overrun to occur in hardware (unless it has + * some large internal buffering). + */ + + if (nexthead != dev->recv.tail) + { + /* Add the character to the buffer */ + + dev->recv.buffer[dev->recv.head] = ch; + nbytes++; + + /* Increment the head index */ + + dev->recv.head = nexthead; + if (++nexthead >= dev->recv.size) + { + nexthead = 0; + } + } + } + + /* If any bytes were added to the buffer, inform any waiters there there is new + * incoming data available. + */ + + if (nbytes) + { + uart_datareceived(dev); + } +} diff --git a/nuttx/drivers/serial/uart_16550.c b/nuttx/drivers/serial/uart_16550.c new file mode 100644 index 0000000000..ea7d944f3a --- /dev/null +++ b/nuttx/drivers/serial/uart_16550.c @@ -0,0 +1,1164 @@ +/**************************************************************************** + * drivers/serial/uart_16550.c + * Serial driver for 16550 UART + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_16550_UART + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct u16550_s +{ + uart_addrwidth_t uartbase; /* Base address of UART registers */ +#ifndef CONFIG_16550_SUPRESS_CONFIG + uint32_t baud; /* Configured baud */ + uint32_t uartclk; /* UART clock frequency */ +#endif +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + uart_datawidth_t ier; /* Saved IER value */ + uint8_t irq; /* IRQ associated with this UART */ +#endif +#ifndef CONFIG_16550_SUPRESS_CONFIG + uint8_t parity; /* 0=none, 1=odd, 2=even */ + uint8_t bits; /* Number of bits (7 or 8) */ + bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int u16550_setup(struct uart_dev_s *dev); +static void u16550_shutdown(struct uart_dev_s *dev); +static int u16550_attach(struct uart_dev_s *dev); +static void u16550_detach(struct uart_dev_s *dev); +#ifndef CONFIG_SUPPRESS_SERIAL_INTS +static int u16550_interrupt(int irq, void *context); +#endif +static int u16550_ioctl(struct file *filep, int cmd, unsigned long arg); +static int u16550_receive(struct uart_dev_s *dev, uint32_t *status); +static void u16550_rxint(struct uart_dev_s *dev, bool enable); +static bool u16550_rxavailable(struct uart_dev_s *dev); +static void u16550_send(struct uart_dev_s *dev, int ch); +static void u16550_txint(struct uart_dev_s *dev, bool enable); +static bool u16550_txready(struct uart_dev_s *dev); +static bool u16550_txempty(struct uart_dev_s *dev); + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +struct uart_ops_s g_uart_ops = +{ + .setup = u16550_setup, + .shutdown = u16550_shutdown, + .attach = u16550_attach, + .detach = u16550_detach, + .ioctl = u16550_ioctl, + .receive = u16550_receive, + .rxint = u16550_rxint, + .rxavailable = u16550_rxavailable, + .send = u16550_send, + .txint = u16550_txint, + .txready = u16550_txready, + .txempty = u16550_txempty, +}; + +/* I/O buffers */ + +#ifdef CONFIG_16550_UART0 +static char g_uart0rxbuffer[CONFIG_UART0_RXBUFSIZE]; +static char g_uart0txbuffer[CONFIG_UART0_TXBUFSIZE]; +#endif +#ifdef CONFIG_16550_UART1 +static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE]; +static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE]; +#endif +#ifdef CONFIG_16550_UART2 +static char g_uart2rxbuffer[CONFIG_UART1_RXBUFSIZE]; +static char g_uart2txbuffer[CONFIG_UART1_TXBUFSIZE]; +#endif +#ifdef CONFIG_16550_UART3 +static char g_uart3rxbuffer[CONFIG_UART1_RXBUFSIZE]; +static char g_uart3txbuffer[CONFIG_UART1_TXBUFSIZE]; +#endif + +/* This describes the state of the LPC17xx uart0 port. */ + +#ifdef CONFIG_16550_UART0 +static struct u16550_s g_uart0priv = +{ + .uartbase = CONFIG_16550_UART0_BASE, +#ifndef CONFIG_16550_SUPRESS_CONFIG + .baud = CONFIG_UART0_BAUD, + .uartclk = CONFIG_16550_UART0_CLOCK, +#endif +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + .irq = CONFIG_16550_UART0_IRQ, +#endif +#ifndef CONFIG_16550_SUPRESS_CONFIG + .parity = CONFIG_UART0_PARITY, + .bits = CONFIG_UART0_BITS, + .stopbits2 = CONFIG_UART0_2STOP, +#endif +}; + +static uart_dev_t g_uart0port = +{ + .recv = + { + .size = CONFIG_UART0_RXBUFSIZE, + .buffer = g_uart0rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART0_TXBUFSIZE, + .buffer = g_uart0txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart0priv, +}; +#endif + +/* This describes the state of the LPC17xx uart1 port. */ + +#ifdef CONFIG_16550_UART1 +static struct u16550_s g_uart1priv = +{ + .uartbase = CONFIG_16550_UART1_BASE, +#ifndef CONFIG_16550_SUPRESS_CONFIG + .baud = CONFIG_UART1_BAUD, + .uartclk = CONFIG_16550_UART1_CLOCK, +#endif +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + .irq = CONFIG_16550_UART1_IRQ, +#endif +#ifndef CONFIG_16550_SUPRESS_CONFIG + .parity = CONFIG_UART1_PARITY, + .bits = CONFIG_UART1_BITS, + .stopbits2 = CONFIG_UART1_2STOP, +#endif +}; + +static uart_dev_t g_uart1port = +{ + .recv = + { + .size = CONFIG_UART1_RXBUFSIZE, + .buffer = g_uart1rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART1_TXBUFSIZE, + .buffer = g_uart1txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart1priv, +}; +#endif + +/* This describes the state of the LPC17xx uart1 port. */ + +#ifdef CONFIG_16550_UART2 +static struct u16550_s g_uart2priv = +{ + .uartbase = CONFIG_16550_UART2_BASE, +#ifndef CONFIG_16550_SUPRESS_CONFIG + .baud = CONFIG_UART2_BAUD, + .uartclk = CONFIG_16550_UART2_CLOCK, +#endif +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + .irq = CONFIG_16550_UART2_IRQ, +#endif +#ifndef CONFIG_16550_SUPRESS_CONFIG + .parity = CONFIG_UART2_PARITY, + .bits = CONFIG_UART2_BITS, + .stopbits2 = CONFIG_UART2_2STOP, +#endif +}; + +static uart_dev_t g_uart2port = +{ + .recv = + { + .size = CONFIG_UART2_RXBUFSIZE, + .buffer = g_uart2rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART2_TXBUFSIZE, + .buffer = g_uart2txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart2priv, +}; +#endif + +/* This describes the state of the LPC17xx uart1 port. */ + +#ifdef CONFIG_16550_UART3 +static struct u16550_s g_uart3priv = +{ + .uartbase = CONFIG_16550_UART3_BASE, +#ifndef CONFIG_16550_SUPRESS_CONFIG + .baud = CONFIG_UART3_BAUD, + .uartclk = CONFIG_16550_UART3_CLOCK, +#endif +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + .irq = CONFIG_16550_UART3_IRQ, +#endif +#ifndef CONFIG_16550_SUPRESS_CONFIG + .parity = CONFIG_UART3_PARITY, + .bits = CONFIG_UART3_BITS, + .stopbits2 = CONFIG_UART3_2STOP, +#endif +}; + +static uart_dev_t g_uart3port = +{ + .recv = + { + .size = CONFIG_UART3_RXBUFSIZE, + .buffer = g_uart3rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART3_TXBUFSIZE, + .buffer = g_uart3txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart3priv, +}; +#endif + +/* Which UART with be tty0/console and which tty1? tty2? tty3? */ + +#if defined(CONFIG_UART0_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart0port /* UART0=console */ +# define TTYS0_DEV g_uart0port /* UART0=ttyS0 */ +# ifdef CONFIG_16550_UART1 +# define TTYS1_DEV g_uart1port /* UART0=ttyS0;UART1=ttyS1 */ +# ifdef CONFIG_16550_UART2 +# define TTYS2_DEV g_uart2port /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS2 */ +# ifdef CONFIG_16550_UART3 +# define TTYS3_DEV g_uart3port /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS2;UART3=ttyS3 */ +# else +# undef TTYS3_DEV /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS;No ttyS3 */ +# endif +# else +# ifdef CONFIG_16550_UART3 +# define TTYS2_DEV g_uart3port /* UART0=ttyS0;UART1=ttyS1;UART3=ttys2;No ttyS3 */ +# else +# undef TTYS2_DEV /* UART0=ttyS0;UART1=ttyS1;No ttyS2;No ttyS3 */ +# endif +# undef TTYS3_DEV /* No ttyS3 */ +# endif +# else +# ifdef CONFIG_16550_UART2 +# define TTYS1_DEV g_uart2port /* UART0=ttyS0;UART2=ttyS1;No ttyS3 */ +# ifdef CONFIG_16550_UART3 +# define TTYS2_DEV g_uart3port /* UART0=ttyS0;UART2=ttyS1;UART3=ttyS2;No ttyS3 */ +# else +# undef TTYS2_DEV /* UART0=ttyS0;UART2=ttyS1;No ttyS2;No ttyS3 */ +# endif +# undef TTYS3_DEV /* No ttyS3 */ +# else +# ifdef CONFIG_16550_UART3 +# define TTYS1_DEV g_uart3port /* UART0=ttyS0;UART3=ttyS1;No ttyS2;No ttyS3 */ +# else +# undef TTYS1_DEV /* UART0=ttyS0;No ttyS1;No ttyS2;No ttyS3 */ +# endif +# undef TTYS2_DEV /* No ttyS2 */ +# undef TTYS3_DEV /* No ttyS3 */ +# endif +# endif +#elif defined(CONFIG_UART1_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart1port /* UART1=console */ +# define TTYS0_DEV g_uart1port /* UART1=ttyS0 */ +# ifdef CONFIG_16550_UART +# define TTYS1_DEV g_uart0port /* UART1=ttyS0;UART0=ttyS1 */ +# ifdef CONFIG_16550_UART2 +# define TTYS2_DEV g_uart2port /* UART1=ttyS0;UART0=ttyS1;UART2=ttyS2 */ +# ifdef CONFIG_16550_UART3 +# define TTYS3_DEV g_uart3port /* UART1=ttyS0;UART0=ttyS1;UART2=ttyS2;UART3=ttyS3 */ +# else +# undef TTYS3_DEV /* UART1=ttyS0;UART0=ttyS1;UART2=ttyS;No ttyS3 */ +# endif +# else +# ifdef CONFIG_16550_UART3 +# define TTYS2_DEV g_uart3port /* UART1=ttyS0;UART0=ttyS1;UART3=ttys2;No ttyS3 */ +# else +# undef TTYS2_DEV /* UART1=ttyS0;UART0=ttyS1;No ttyS2;No ttyS3 */ +# endif +# undef TTYS3_DEV /* No ttyS3 */ +# endif +# else +# ifdef CONFIG_16550_UART2 +# define TTYS1_DEV g_uart2port /* UART1=ttyS0;UART2=ttyS1 */ +# ifdef CONFIG_16550_UART3 +# define TTYS2_DEV g_uart3port /* UART1=ttyS0;UART2=ttyS1;UART3=ttyS2;No ttyS3 */ +# else +# undef TTYS2_DEV /* UART1=ttyS0;UART2=ttyS1;No ttyS2;No ttyS3 */ +# endif +# undef TTYS3_DEV /* No ttyS3 */ +# else +# ifdef CONFIG_16550_UART3 +# define TTYS1_DEV g_uart3port /* UART1=ttyS0;UART3=ttyS1;No ttyS2;No ttyS3 */ +# else +# undef TTYS1_DEV /* UART1=ttyS0;No ttyS1;No ttyS2;No ttyS3 */ +# endif +# undef TTYS2_DEV /* No ttyS2 */ +# undef TTYS3_DEV /* No ttyS3 */ +# endif +# endif +#elif defined(CONFIG_UART2_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart2port /* UART2=console */ +# define TTYS0_DEV g_uart2port /* UART2=ttyS0 */ +# ifdef CONFIG_16550_UART +# define TTYS1_DEV g_uart0port /* UART2=ttyS0;UART0=ttyS1 */ +# ifdef CONFIG_16550_UART1 +# define TTYS2_DEV g_uart1port /* UART2=ttyS0;UART0=ttyS1;UART1=ttyS2 */ +# ifdef CONFIG_16550_UART3 +# define TTYS3_DEV g_uart3port /* UART2=ttyS0;UART0=ttyS1;UART1=ttyS2;UART3=ttyS3 */ +# else +# undef TTYS3_DEV /* UART2=ttyS0;UART0=ttyS1;UART1=ttyS;No ttyS3 */ +# endif +# else +# ifdef CONFIG_16550_UART3 +# define TTYS2_DEV g_uart3port /* UART2=ttyS0;UART0=ttyS1;UART3=ttys2;No ttyS3 */ +# else +# undef TTYS2_DEV /* UART2=ttyS0;UART0=ttyS1;No ttyS2;No ttyS3 */ +# endif +# undef TTYS3_DEV /* No ttyS3 */ +# endif +# else +# ifdef CONFIG_16550_UART1 +# define TTYS1_DEV g_uart1port /* UART2=ttyS0;UART1=ttyS1 */ +# ifdef CONFIG_16550_UART3 +# define TTYS2_DEV g_uart3port /* UART2=ttyS0;UART1=ttyS1;UART3=ttyS2 */ +# else +# undef TTYS2_DEV /* UART2=ttyS0;UART1=ttyS1;No ttyS2;No ttyS3 */ +# endif +# undef TTYS3_DEV /* No ttyS3 */ +# else +# ifdef CONFIG_16550_UART3 +# define TTYS1_DEV g_uart3port /* UART2=ttyS0;UART3=ttyS1;No ttyS3 */ +# else +# undef TTYS1_DEV /* UART2=ttyS0;No ttyS1;No ttyS2;No ttyS3 */ +# endif +# undef TTYS2_DEV /* No ttyS2 */ +# undef TTYS3_DEV /* No ttyS3 */ +# endif +# endif +#elif defined(CONFIG_UART3_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart3port /* UART3=console */ +# define TTYS0_DEV g_uart3port /* UART3=ttyS0 */ +# ifdef CONFIG_16550_UART +# define TTYS1_DEV g_uart0port /* UART3=ttyS0;UART0=ttyS1 */ +# ifdef CONFIG_16550_UART1 +# define TTYS2_DEV g_uart1port /* UART3=ttyS0;UART0=ttyS1;UART1=ttyS2 */ +# ifdef CONFIG_16550_UART2 +# define TTYS3_DEV g_uart2port /* UART3=ttyS0;UART0=ttyS1;UART1=ttyS2;UART2=ttyS3 */ +# else +# undef TTYS3_DEV /* UART3=ttyS0;UART0=ttyS1;UART1=ttyS;No ttyS3 */ +# endif +# else +# ifdef CONFIG_16550_UART2 +# define TTYS2_DEV g_uart2port /* UART3=ttyS0;UART0=ttyS1;UART2=ttys2;No ttyS3 */ +# else +# undef TTYS2_DEV /* UART3=ttyS0;UART0=ttyS1;No ttyS2;No ttyS3 */ +# endif +# undef TTYS3_DEV /* No ttyS3 */ +# endif +# else +# ifdef CONFIG_16550_UART1 +# define TTYS1_DEV g_uart1port /* UART3=ttyS0;UART1=ttyS1 */ +# ifdef CONFIG_16550_UART2 +# define TTYS2_DEV g_uart2port /* UART3=ttyS0;UART1=ttyS1;UART2=ttyS2;No ttyS3 */ +# else +# undef TTYS2_DEV /* UART3=ttyS0;UART1=ttyS1;No ttyS2;No ttyS3 */ +# endif +# undef TTYS3_DEV /* No ttyS3 */ +# else +# ifdef CONFIG_16550_UART2 +# define TTYS1_DEV g_uart2port /* UART3=ttyS0;UART2=ttyS1;No ttyS3;No ttyS3 */ +# undef TTYS3_DEV /* UART3=ttyS0;UART2=ttyS1;No ttyS2;No ttyS3 */ +# else +# undef TTYS1_DEV /* UART3=ttyS0;No ttyS1;No ttyS2;No ttyS3 */ +# endif +# undef TTYS2_DEV /* No ttyS2 */ +# undef TTYS3_DEV /* No ttyS3 */ +# endif +# endif +#endif + +/************************************************************************************ + * Inline Functions + ************************************************************************************/ + +/**************************************************************************** + * Name: u16550_serialin + ****************************************************************************/ + +static inline uart_datawidth_t u16550_serialin(struct u16550_s *priv, int offset) +{ + return uart_getreg(priv->uartbase, offset); +} + +/**************************************************************************** + * Name: u16550_serialout + ****************************************************************************/ + +static inline void u16550_serialout(struct u16550_s *priv, int offset, uart_datawidth_t value) +{ + uart_putreg(priv->uartbase, offset, value); +} + +/**************************************************************************** + * Name: u16550_disableuartint + ****************************************************************************/ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS +static inline void u16550_disableuartint(struct u16550_s *priv, uart_datawidth_t *ier) +{ + if (ier) + { + *ier = priv->ier & UART_IER_ALLIE; + } + + priv->ier &= ~UART_IER_ALLIE; + u16550_serialout(priv, UART_IER_OFFSET, priv->ier); +} +#else +# define u16550_disableuartint(priv,ier) +#endif + +/**************************************************************************** + * Name: u16550_restoreuartint + ****************************************************************************/ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS +static inline void u16550_restoreuartint(struct u16550_s *priv, uint32_t ier) +{ + priv->ier |= ier & UART_IER_ALLIE; + u16550_serialout(priv, UART_IER_OFFSET, priv->ier); +} +#else +# define u16550_restoreuartint(priv,ier) +#endif + +/**************************************************************************** + * Name: u16550_enablebreaks + ****************************************************************************/ + +static inline void u16550_enablebreaks(struct u16550_s *priv, bool enable) +{ + uint32_t lcr = u16550_serialin(priv, UART_LCR_OFFSET); + if (enable) + { + lcr |= UART_LCR_BRK; + } + else + { + lcr &= ~UART_LCR_BRK; + } + u16550_serialout(priv, UART_LCR_OFFSET, lcr); +} + +/************************************************************************************ + * Name: u16550_divisor + * + * Descrption: + * Select a divider to produce the BAUD from the UART_CLK. + * + * BAUD = UART_CLK / (16 * DL), or + * DIV = UART_CLK / BAUD / 16 + * + * Ignoring the fractional divider for now. + * + ************************************************************************************/ + +#ifndef CONFIG_16550_SUPRESS_CONFIG +static inline uint32_t u16550_divisor(struct u16550_s *priv) +{ + return (priv->uartclk + (priv->baud << 3)) / (priv->baud << 4); +} +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: u16550_setup + * + * Description: + * Configure the UART baud, bits, parity, fifos, etc. This + * method is called the first time that the serial port is + * opened. + * + ****************************************************************************/ + +static int u16550_setup(struct uart_dev_s *dev) +{ +#ifndef CONFIG_16550_SUPRESS_CONFIG + struct u16550_s *priv = (struct u16550_s*)dev->priv; + uint16_t div; + uint32_t lcr; + + /* Clear fifos */ + + u16550_serialout(priv, UART_FCR_OFFSET, (UART_FCR_RXRST|UART_FCR_TXRST)); + + /* Set trigger */ + + u16550_serialout(priv, UART_FCR_OFFSET, (UART_FCR_FIFOEN|UART_FCR_RXTRIGGER_8)); + + /* Set up the IER */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->ier = u16550_serialin(priv, UART_IER_OFFSET); +#endif + + /* Set up the LCR */ + + lcr = 0; + switch (priv->bits) + { + case 5 : + lcr |= UART_LCR_WLS_7BIT; + break; + + case 6 : + lcr |= UART_LCR_WLS_7BIT; + break; + + case 7 : + lcr |= UART_LCR_WLS_7BIT; + break; + + default: + case 8 : + lcr |= UART_LCR_WLS_7BIT; + break; + } + + if (priv->stopbits2) + { + lcr |= UART_LCR_STB; + } + + if (priv->parity == 1) + { + lcr |= UART_LCR_PEN; + } + else if (priv->parity == 2) + { + lcr |= (UART_LCR_PEN|UART_LCR_EPS); + } + + /* Enter DLAB=1 */ + + u16550_serialout(priv, UART_LCR_OFFSET, (lcr | UART_LCR_DLAB)); + + /* Set the BAUD divisor */ + + div = u16550_divisor(priv); + u16550_serialout(priv, UART_DLM_OFFSET, div >> 8); + u16550_serialout(priv, UART_DLL_OFFSET, div & 0xff); + + /* Clear DLAB */ + + u16550_serialout(priv, UART_LCR_OFFSET, lcr); + + /* Configure the FIFOs */ + + u16550_serialout(priv, UART_FCR_OFFSET, + (UART_FCR_RXTRIGGER_8|UART_FCR_TXRST|UART_FCR_RXRST|UART_FCR_FIFOEN)); +#endif + return OK; +} + +/**************************************************************************** + * Name: u16550_shutdown + * + * Description: + * Disable the UART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +static void u16550_shutdown(struct uart_dev_s *dev) +{ + struct u16550_s *priv = (struct u16550_s*)dev->priv; + u16550_disableuartint(priv, NULL); +} + +/**************************************************************************** + * Name: u16550_attach + * + * Description: + * Configure the UART to operation in interrupt driven mode. This method is + * called when the serial port is opened. Normally, this is just after the + * the setup() method is called, however, the serial console may operate in + * a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled when by the attach method (unless the + * hardware supports multiple levels of interrupt enabling). The RX and TX + * interrupts are not enabled until the txint() and rxint() methods are called. + * + ****************************************************************************/ + +static int u16550_attach(struct uart_dev_s *dev) +{ +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + struct u16550_s *priv = (struct u16550_s*)dev->priv; + int ret; + + /* Attach and enable the IRQ */ + + ret = irq_attach(priv->irq, u16550_interrupt); +#ifndef CONFIG_ARCH_NOINTC + if (ret == OK) + { + /* Enable the interrupt (RX and TX interrupts are still disabled + * in the UART + */ + + up_enable_irq(priv->irq); + } +#endif + return ret; +#else + return OK; +#endif +} + +/**************************************************************************** + * Name: u16550_detach + * + * Description: + * Detach UART interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called. The exception is + * the serial console which is never shutdown. + * + ****************************************************************************/ + +static void u16550_detach(struct uart_dev_s *dev) +{ +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + struct u16550_s *priv = (struct u16550_s*)dev->priv; +#ifndef CONFIG_ARCH_NOINTC + up_disable_irq(priv->irq); +#endif + irq_detach(priv->irq); +#endif +} + +/**************************************************************************** + * Name: u16550_interrupt + * + * Description: + * This is the UART interrupt handler. It will be invoked when an + * interrupt received on the 'irq' It should call uart_transmitchars or + * uart_receivechar to perform the appropriate data transfers. The + * interrupt handling logic must be able to map the 'irq' number into the + * appropriate u16550_s structure in order to call these functions. + * + ****************************************************************************/ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS +static int u16550_interrupt(int irq, void *context) +{ + struct uart_dev_s *dev = NULL; + struct u16550_s *priv; + uint32_t status; + int passes; + +#ifdef CONFIG_16550_UART0 + if (g_uart0priv.irq == irq) + { + dev = &g_uart0port; + } + else +#endif +#ifdef CONFIG_16550_UART1 + if (g_uart1priv.irq == irq) + { + dev = &g_uart1port; + } + else +#endif +#ifdef CONFIG_16550_UART2 + if (g_uart2priv.irq == irq) + { + dev = &g_uart2port; + } + else +#endif +#ifdef CONFIG_16550_UART3 + if (g_uart3priv.irq == irq) + { + dev = &g_uart3port; + } +#endif + ASSERT(dev != NULL); + priv = (struct u16550_s*)dev->priv; + + /* Loop until there are no characters to be transferred or, + * until we have been looping for a long time. + */ + + for (passes = 0; passes < 256; passes++) + { + /* Get the current UART status and check for loop + * termination conditions + */ + + status = u16550_serialin(priv, UART_IIR_OFFSET); + + /* The UART_IIR_INTSTATUS bit should be zero if there are pending + * interrupts + */ + + if ((status & UART_IIR_INTSTATUS) != 0) + { + /* Break out of the loop when there is no longer a + * pending interrupt + */ + + break; + } + + /* Handle the interrupt by its interrupt ID field */ + + switch (status & UART_IIR_INTID_MASK) + { + /* Handle incoming, receive bytes (with or without timeout) */ + + case UART_IIR_INTID_RDA: + case UART_IIR_INTID_CTI: + { + uart_recvchars(dev); + break; + } + + /* Handle outgoing, transmit bytes */ + + case UART_IIR_INTID_THRE: + { + uart_xmitchars(dev); + break; + } + + /* Just clear modem status interrupts (UART1 only) */ + + case UART_IIR_INTID_MSI: + { + /* Read the modem status register (MSR) to clear */ + + status = u16550_serialin(priv, UART_MSR_OFFSET); + vdbg("MSR: %02x\n", status); + break; + } + + /* Just clear any line status interrupts */ + + case UART_IIR_INTID_RLS: + { + /* Read the line status register (LSR) to clear */ + + status = u16550_serialin(priv, UART_LSR_OFFSET); + vdbg("LSR: %02x\n", status); + break; + } + + /* There should be no other values */ + + default: + { + dbg("Unexpected IIR: %02x\n", status); + break; + } + } + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: u16550_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int u16550_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + struct inode *inode = filep->f_inode; + struct uart_dev_s *dev = inode->i_private; + struct u16550_s *priv = (struct u16550_s*)dev->priv; + int ret = OK; + + switch (cmd) + { + case TIOCSERGSTRUCT: + { + struct u16550_s *user = (struct u16550_s*)arg; + if (!user) + { + set_errno(EINVAL); + ret = ERROR; + } + else + { + memcpy(user, dev, sizeof(struct u16550_s)); + } + } + break; + + case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ + { + irqstate_t flags = irqsave(); + u16550_enablebreaks(priv, true); + irqrestore(flags); + } + break; + + case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ + { + irqstate_t flags; + flags = irqsave(); + u16550_enablebreaks(priv, false); + irqrestore(flags); + } + break; + + default: + set_errno(ENOTTY); + ret = ERROR; + break; + } + + return ret; +} + +/**************************************************************************** + * Name: u16550_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the UART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +static int u16550_receive(struct uart_dev_s *dev, uint32_t *status) +{ + struct u16550_s *priv = (struct u16550_s*)dev->priv; + uint32_t rbr; + + *status = u16550_serialin(priv, UART_LSR_OFFSET); + rbr = u16550_serialin(priv, UART_RBR_OFFSET); + return rbr; +} + +/**************************************************************************** + * Name: u16550_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void u16550_rxint(struct uart_dev_s *dev, bool enable) +{ +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + struct u16550_s *priv = (struct u16550_s*)dev->priv; + if (enable) + { + priv->ier |= UART_IER_ERBFI; + } + else + { + priv->ier &= ~UART_IER_ERBFI; + } + u16550_serialout(priv, UART_IER_OFFSET, priv->ier); +#endif +} + +/**************************************************************************** + * Name: u16550_rxavailable + * + * Description: + * Return true if the receive fifo is not empty + * + ****************************************************************************/ + +static bool u16550_rxavailable(struct uart_dev_s *dev) +{ + struct u16550_s *priv = (struct u16550_s*)dev->priv; + return ((u16550_serialin(priv, UART_LSR_OFFSET) & UART_LSR_DR) != 0); +} + +/**************************************************************************** + * Name: u16550_send + * + * Description: + * This method will send one byte on the UART + * + ****************************************************************************/ + +static void u16550_send(struct uart_dev_s *dev, int ch) +{ + struct u16550_s *priv = (struct u16550_s*)dev->priv; + u16550_serialout(priv, UART_THR_OFFSET, (uart_datawidth_t)ch); +} + +/**************************************************************************** + * Name: u16550_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void u16550_txint(struct uart_dev_s *dev, bool enable) +{ +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + struct u16550_s *priv = (struct u16550_s*)dev->priv; + irqstate_t flags; + + flags = irqsave(); + if (enable) + { + priv->ier |= UART_IER_ETBEI; + u16550_serialout(priv, UART_IER_OFFSET, priv->ier); + + /* Fake a TX interrupt here by just calling uart_xmitchars() with + * interrupts disabled (note this may recurse). + */ + + uart_xmitchars(dev); + } + else + { + priv->ier &= ~UART_IER_ETBEI; + u16550_serialout(priv, UART_IER_OFFSET, priv->ier); + } + + irqrestore(flags); +#endif +} + +/**************************************************************************** + * Name: u16550_txready + * + * Description: + * Return true if the tranmsit fifo is not full + * + ****************************************************************************/ + +static bool u16550_txready(struct uart_dev_s *dev) +{ + struct u16550_s *priv = (struct u16550_s*)dev->priv; + return ((u16550_serialin(priv, UART_LSR_OFFSET) & UART_LSR_THRE) != 0); +} + +/**************************************************************************** + * Name: u16550_txempty + * + * Description: + * Return true if the transmit fifo is empty + * + ****************************************************************************/ + +static bool u16550_txempty(struct uart_dev_s *dev) +{ + struct u16550_s *priv = (struct u16550_s*)dev->priv; + return ((u16550_serialin(priv, UART_LSR_OFFSET) & UART_LSR_THRE) != 0); +} + +/**************************************************************************** + * Name: u16550_putc + * + * Description: + * Write one character to the UART (polled) + * + ****************************************************************************/ + +static void u16550_putc(struct u16550_s *priv, int ch) +{ + while ((u16550_serialin(priv, UART_LSR_OFFSET) & UART_LSR_THRE) != 0); + u16550_serialout(priv, UART_THR_OFFSET, (uart_datawidth_t)ch); +} + +/**************************************************************************** + * Public Funtions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before uart_serialinit. + * + * NOTE: Configuration of the CONSOLE UART was performed by uart_lowsetup() + * very early in the boot sequence. + * + ****************************************************************************/ + +void up_earlyserialinit(void) +{ + /* Configure all UARTs (except the CONSOLE UART) and disable interrupts */ + +#ifdef CONFIG_16550_UART0 + u16550_disableuartint(&g_uart0priv, NULL); +#endif +#ifdef CONFIG_16550_UART1 + u16550_disableuartint(&g_uart1priv, NULL); +#endif +#ifdef CONFIG_16550_UART2 + u16550_disableuartint(&g_uart2priv, NULL); +#endif +#ifdef CONFIG_16550_UART3 + u16550_disableuartint(&g_uart3priv, NULL); +#endif + + /* Configuration whichever one is the console */ + +#ifdef CONSOLE_DEV + CONSOLE_DEV.isconsole = true; + u16550_setup(&CONSOLE_DEV); +#endif +} + +/**************************************************************************** + * Name: up_serialinit + * + * Description: + * Register serial console and serial ports. This assumes that + * up_earlyserialinit was called previously. + * + ****************************************************************************/ + +void up_serialinit(void) +{ +#ifdef CONSOLE_DEV + (void)uart_register("/dev/console", &CONSOLE_DEV); +#endif +#ifdef TTYS0_DEV + (void)uart_register("/dev/ttyS0", &TTYS0_DEV); +#endif +#ifdef TTYS1_DEV + (void)uart_register("/dev/ttyS1", &TTYS1_DEV); +#endif +#ifdef TTYS2_DEV + (void)uart_register("/dev/ttyS2", &TTYS2_DEV); +#endif +#ifdef TTYS3_DEV + (void)uart_register("/dev/ttyS3", &TTYS3_DEV); +#endif +} + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +#ifdef HAVE_16550_CONSOLE +int up_putc(int ch) +{ + struct u16550_s *priv = (struct u16550_s*)CONSOLE_DEV.priv; +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + uart_datawidth_t ier; + + u16550_disableuartint(priv, &ier); +#endif + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + u16550_putc(priv, '\r'); + } + + u16550_putc(priv, ch); +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + u16550_restoreuartint(priv, ier); +#endif + return ch; +} +#endif + +#endif /* CONFIG_UART_16550 */ diff --git a/nuttx/drivers/syslog/Kconfig b/nuttx/drivers/syslog/Kconfig new file mode 100644 index 0000000000..3ec8c7490f --- /dev/null +++ b/nuttx/drivers/syslog/Kconfig @@ -0,0 +1,73 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +comment "System Logging" + +config RAMLOG + bool "RAM log device support" + default n + ---help--- + This is a driver that was intended to support debugging output, + aka syslogging, when the normal serial output is not available. + For example, if you are using a telnet or USB serial console, + the debug output will get lost. However, the RAMLOG device should + be usable even if system logging is disabled. + + This driver is similar to a pipe in that it saves the debugging + output in a FIFO in RAM. It differs from a pipe in numerous + details as needed to support logging. + +if RAMLOG +config RAMLOG_SYSLOG + bool "Use RAMLOG for SYSLOG" + default n + depends on SYSLOG + ---help--- + Use the RAM logging device for the syslogging interface. If this feature + is enabled (along with SYSLOG), then all debug output (only) will be re-directed + to the circular buffer in RAM. This RAM log can be view from NSH using the + 'dmesg'command. + + Do not enable more than one SYSLOG device. + +config RAMLOG_CONSOLE + bool "Use RAMLOG for /dev/console" + default n + depends on DEV_CONSOLE + ---help--- + Use the RAM logging device as a system console. If this feature is enabled (along + with DEV_CONSOLE), then all console output will be re-directed to a circular + buffer in RAM. This is useful, for example, if the only console is a Telnet + console. Then in that case, console output from non-Telnet threads will go to + the circular buffer and can be viewed using the NSH 'dmesg' command. + +config RAMLOG_CONSOLE_BUFSIZE + int "RAMLOG buffer size" + default 1024 + depends on RAMLOG_SYSLOG || RAMLOG_CONSOLE + ---help--- + Size of the console RAM log. Default: 1024 + +config RAMLOG_CRLF + bool "RAMLOG CR/LF" + default n + ---help--- + Pre-pend a carriage return before every linefeed that goes into the RAM log. + +config RAMLOG_NONBLOCKING + bool "RAMLOG non-block reads" + default y + ---help--- + Reading from the RAMLOG will never block if the RAMLOG is empty. If the RAMLOG + is empty, then zero is returned (usually interpreted as end-of-file). + +config RAMLOG_NPOLLWAITERS + int "RAMLOG number of poll waiters" + default 4 + depends on !DISABLE_POLL + ---help--- + The maximum number of threads that may be waiting on the poll method. + +endif diff --git a/nuttx/drivers/syslog/Make.defs b/nuttx/drivers/syslog/Make.defs new file mode 100644 index 0000000000..aa0ab19b88 --- /dev/null +++ b/nuttx/drivers/syslog/Make.defs @@ -0,0 +1,68 @@ +############################################################################ +# drivers/syslog/Make.defs +# These drivers support system logging devices +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Include SYSLOG drivers (only one should be enabled) + +ifeq ($(CONFIG_SYSLOG),y) + +# If no special loggin devices are implemented, then the default SYSLOG +# logic at fs/fs_syslog.c will be used + +# (Add other SYSLOG drivers here) + +ifeq ($(CONFIG_RAMLOG),y) + CSRCS += ramlog.c +endif + +# Include SYSLOG build support + +DEPPATH += --dep-path syslog +VPATH += :syslog + +else + +# The RAMLOG can be used even if system logging is not enabled. + +ifeq ($(CONFIG_RAMLOG),y) + +# Include RAMLOG build support + +CSRCS += ramlog.c +DEPPATH += --dep-path syslog +VPATH += :syslog + +endif +endif diff --git a/nuttx/drivers/syslog/README.txt b/nuttx/drivers/syslog/README.txt new file mode 100644 index 0000000000..bfef73ae80 --- /dev/null +++ b/nuttx/drivers/syslog/README.txt @@ -0,0 +1,64 @@ +drivers/syslog README File +========================== + +This README file discusses the SYLOG drivers that can be found in the +drivers/syslog directory. In NuttX, syslog output is equivalent to +debug output and, therefore, the syslogging interfaces are defined in the +header file include/debug.h. + +By default, all system log output goes to console (/dev/console). But that +behavior can be changed by the defining CONFIG_SYSLOG in the NuttX +configuration. In that, case all low-level debug output will go through +syslog_putc(). + +One version of syslog_putc() is defined in fs/fs_syslog.c; that version is +used when CONFIG_SYSLOG_CHAR is defined. That version of syslog_putc() +just integrates with the file system to re-direct debug output to a +character device or to a file. A disadvantage of using the generic character +device for the SYSLOG is that it cannot handle debug output generated from +interrupt level handles. + +If CONFIG_SYSLOG_CHAR is not defined, then other custom SYSLOG drivers +can be used. These custom SYSLOG drivers can do things like handle +unusual logging media and since they can avoid the general file system +interfaces, can be designed to support debug output from interrupt handlers. + +Those custom SYSLOG drivers reside in this directory. + +ramlog.c +-------- + The RAM logging driver is a driver that was intended to support debugging + output (syslogging) when the normal serial output is not available. For + example, if you are using a telnet or USB serial console, the debug + output will get lost. + + The RAM logging driver is similar to a pipe in that it saves the + debugging output in a FIFO in RAM. It differs from a pipe in numerous + details as needed to support logging. + + This driver is built when CONFIG_RAMLOG is defined in the Nuttx + configuration. + + Configuration options: + + CONFIG_RAMLOG - Enables the RAM logging feature + CONFIG_RAMLOG_CONSOLE - Use the RAM logging device as a system console. + If this feature is enabled (along with CONFIG_DEV_CONSOLE), then all + console output will be re-directed to a circular buffer in RAM. This + is useful, for example, if the only console is a Telnet console. Then + in that case, console output from non-Telnet threads will go to the + circular buffer and can be viewed using the NSH 'dmesg' command. + CONFIG_RAMLOG_SYSLOG - Use the RAM logging device for the syslogging + interface. If this feature is enabled (along with CONFIG_SYSLOG), + then all debug output (only) will be re-directed to the circular + buffer in RAM. This RAM log can be view from NSH using the 'dmesg' + command. NOTE: Unlike the limited, generic character driver SYSLOG + device, the RAMLOG *can* be used to generate debug output from interrupt + level handlers. + CONFIG_RAMLOG_NPOLLWAITERS - The number of threads than can be waiting + for this driver on poll(). Default: 4 + + If CONFIG_RAMLOG_CONSOLE or CONFIG_RAMLOG_SYSLOG is selected, then the + following may also be provided: + + CONFIG_RAMLOG_CONSOLE_BUFSIZE - Size of the console RAM log. Default: 1024 diff --git a/nuttx/drivers/syslog/ramlog.c b/nuttx/drivers/syslog/ramlog.c new file mode 100644 index 0000000000..b3a2ad0f52 --- /dev/null +++ b/nuttx/drivers/syslog/ramlog.c @@ -0,0 +1,770 @@ +/**************************************************************************** + * drivers/syslog/ramlog.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_RAMLOG + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct ramlog_dev_s +{ +#ifndef CONFIG_RAMLOG_NONBLOCKING + volatile uint8_t rl_nwaiters; /* Number of threads waiting for data */ +#endif + volatile uint16_t rl_head; /* The head index (where data is added) */ + volatile uint16_t rl_tail; /* The tail index (where data is removed) */ + sem_t rl_exclsem; /* Enforces mutually exclusive access */ +#ifndef CONFIG_RAMLOG_NONBLOCKING + sem_t rl_waitsem; /* Used to wait for data */ +#endif + size_t rl_bufsize; /* Size of the RAM buffer */ + FAR char *rl_buffer; /* Circular RAM buffer */ + + /* The following is a list if poll structures of threads waiting for + * driver events. The 'struct pollfd' reference for each open is also + * retained in the f_priv field of the 'struct file'. + */ + +#ifndef CONFIG_DISABLE_POLL + struct pollfd *rl_fds[CONFIG_RAMLOG_NPOLLWAITERS]; +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* Helper functions */ + +#ifndef CONFIG_DISABLE_POLL +static void ramlog_pollnotify(FAR struct ramlog_dev_s *priv, + pollevent_t eventset); +#endif +static ssize_t ramlog_addchar(FAR struct ramlog_dev_s *priv, char ch); + +/* Character driver methods */ + +static ssize_t ramlog_read(FAR struct file *, FAR char *, size_t); +static ssize_t ramlog_write(FAR struct file *, FAR const char *, size_t); +#ifndef CONFIG_DISABLE_POLL +static int ramlog_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_ramlogfops = +{ + 0, /* open */ + 0, /* close */ + ramlog_read, /* read */ + ramlog_write, /* write */ + 0, /* seek */ + 0 /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , ramlog_poll /* poll */ +#endif +}; + +/* This is the pre-allocated buffer used for the console RAM log and/or + * for the syslogging function. + */ + +#if defined(CONFIG_RAMLOG_CONSOLE) || defined(CONFIG_RAMLOG_SYSLOG) +static char g_sysbuffer[CONFIG_RAMLOG_CONSOLE_BUFSIZE]; + +/* This is the device structure for the console or syslogging function. It + * must be statically initialized because the RAMLOG syslog_putc function + * could be called before the driver initialization logic executes. + */ + +static struct ramlog_dev_s g_sysdev = +{ +#ifndef CONFIG_RAMLOG_NONBLOCKING + 0, /* rl_nwaiters */ +#endif + 0, /* rl_head */ + 0, /* rl_tail */ + SEM_INITIALIZER(1), /* rl_exclsem */ +#ifndef CONFIG_RAMLOG_NONBLOCKING + SEM_INITIALIZER(0), /* rl_waitsem */ +#endif + CONFIG_RAMLOG_CONSOLE_BUFSIZE, /* rl_bufsize */ + g_sysbuffer /* rl_buffer */ +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ramlog_pollnotify + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static void ramlog_pollnotify(FAR struct ramlog_dev_s *priv, + pollevent_t eventset) +{ + FAR struct pollfd *fds; + irqstate_t flags; + int i; + + /* This function may be called from an interrupt handler */ + + for (i = 0; i < CONFIG_RAMLOG_NPOLLWAITERS; i++) + { + flags = irqsave(); + fds = priv->rl_fds[i]; + if (fds) + { + fds->revents |= (fds->events & eventset); + if (fds->revents != 0) + { + sem_post(fds->sem); + } + } + irqrestore(flags); + } +} +#else +# define ramlog_pollnotify(priv,event) +#endif + +/**************************************************************************** + * Name: ramlog_addchar + ****************************************************************************/ + +static int ramlog_addchar(FAR struct ramlog_dev_s *priv, char ch) +{ + irqstate_t flags; + int nexthead; + + /* Disable interrupts (in case we are NOT called from interrupt handler) */ + + flags = irqsave(); + + /* Calculate the write index AFTER the next byte is written */ + + nexthead = priv->rl_head + 1; + if (nexthead >= priv->rl_bufsize) + { + nexthead = 0; + } + + /* Would the next write overflow the circular buffer? */ + + if (nexthead == priv->rl_tail) + { + /* Yes... Return an indication that nothing was saved in the buffer. */ + + irqrestore(flags); + return -EBUSY; + } + + /* No... copy the byte and re-enable interrupts */ + + priv->rl_buffer[priv->rl_head] = ch; + priv->rl_head = nexthead; + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Name: ramlog_read + ****************************************************************************/ + +static ssize_t ramlog_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + struct inode *inode = filep->f_inode; + struct ramlog_dev_s *priv; + ssize_t nread; + char ch; + int ret; + + /* Some sanity checking */ + + DEBUGASSERT(inode && inode->i_private); + priv = inode->i_private; + + /* If the circular buffer is empty, then wait for something to be written + * to it. This function may NOT be called from an interrupt handler. + */ + + DEBUGASSERT(!up_interrupt_context()); + + /* Get exclusive access to the rl_tail index */ + + ret = sem_wait(&priv->rl_exclsem); + if (ret < 0) + { + return ret; + } + + /* Loop until something is read */ + + for (nread = 0; nread < len; ) + { + /* Get the next byte from the buffer */ + + if (priv->rl_head == priv->rl_tail) + { + /* The circular buffer is empty. */ + +#ifdef CONFIG_RAMLOG_NONBLOCKING + /* Return what we have (with zero mean the end-of-file) */ + + break; +#else + /* Did we read anything? */ + + if (nread > 0) + { + /* Yes.. re-enable interrupts and the break out to return what + * we have. + */ + + break; + } + + /* If the driver was opened with O_NONBLOCK option, then don't wait. + * Re-enable interrupts and return EGAIN. + */ + + if (filep->f_oflags & O_NONBLOCK) + { + nread = -EAGAIN; + break; + } + + /* Otherwise, wait for something to be written to the circular + * buffer. Increment the number of waiters so that the ramlog_write() + * will not that it needs to post the semaphore to wake us up. + */ + + sched_lock(); + priv->rl_nwaiters++; + sem_post(&priv->rl_exclsem); + + /* We may now be pre-empted! But that should be okay because we + * have already incremented nwaiters. Pre-emptions is disabled + * but will be re-enabled while we are waiting. + */ + + ret = sem_wait(&priv->rl_waitsem); + + /* Interrupts will be disabled when we return. So the decrementing + * rl_nwaiters here is safe. + */ + + priv->rl_nwaiters--; + sched_unlock(); + + /* Did we successfully get the rl_waitsem? */ + + if (ret >= 0) + { + /* Yes... then retake the mutual exclusion semaphore */ + + ret = sem_wait(&priv->rl_exclsem); + } + + /* Was the semaphore wait successful? Did we successful re-take the + * mutual exclusion semaphore? + */ + + if (ret < 0) + { + /* No.. One of the two sem_wait's failed. */ + + int errval = errno; + + /* Were we awakened by a signal? Did we read anything before + * we received the signal? + */ + + if (errval != EINTR || nread >= 0) + { + /* Yes.. return the error. */ + + nread = -errval; + } + + /* Break out to return what we have. Note, we can't exactly + * "break" out because whichever error occurred, we do not hold + * the exclusion semaphore. + */ + + goto errout_without_sem; + } +#endif /* CONFIG_RAMLOG_NONBLOCKING */ + } + else + { + /* The circular buffer is not empty, get the next byte from the + * tail index. + */ + + ch = priv->rl_buffer[priv->rl_tail]; + + /* Increment the tail index and re-enable interrupts */ + + if (++priv->rl_tail >= priv->rl_bufsize) + { + priv->rl_tail = 0; + } + + /* Add the character to the user buffer */ + + buffer[nread] = ch; + nread++; + } + } + + /* Relinquish the mutual exclusion semaphore */ + + sem_post(&priv->rl_exclsem); + + /* Notify all poll/select waiters that they can write to the FIFO */ + +#ifndef CONFIG_RAMLOG_NONBLOCKING +errout_without_sem: +#endif + +#ifndef CONFIG_DISABLE_POLL + if (nread > 0) + { + ramlog_pollnotify(priv, POLLOUT); + } +#endif + + /* Return the number of characters actually read */ + + return nread; +} + +/**************************************************************************** + * Name: ramlog_write + ****************************************************************************/ + +static ssize_t ramlog_write(FAR struct file *filep, FAR const char *buffer, size_t len) +{ + struct inode *inode = filep->f_inode; + struct ramlog_dev_s *priv; + ssize_t nwritten; + char ch; + int ret; + + /* Some sanity checking */ + + DEBUGASSERT(inode && inode->i_private); + priv = inode->i_private; + + /* Loop until all of the bytes have been written. This function may be + * called from an interrupt handler! Semaphores cannot be used! + * + * The write logic only needs to modify the rl_head index. Therefore, + * there is a difference in the way that rl_head and rl_tail are protected: + * rl_tail is protected with a semaphore; rl_tail is protected by disabling + * interrupts. + */ + + for (nwritten = 0; nwritten < len; nwritten++) + { + /* Get the next character to output */ + + ch = buffer[nwritten]; + + /* Ignore carriage returns */ + +#ifdef CONFIG_RAMLOG_CRLF + if (ch == '\r') + { + continue; + } + + /* Pre-pend a carriage before a linefeed */ + + if (ch == '\n') + { + ret = ramlog_addchar(priv, '\r'); + if (ret < 0) + { + /* The buffer is full and nothing was saved. Break out of the + * loop to return the number of bytes written up to this point. + * The data to be written is dropped on the floor. + */ + + break; + } + } +#endif + + /* Then output the character */ + + ret = ramlog_addchar(priv,ch); + if (ret < 0) + { + /* The buffer is full and nothing was saved. Break out of the + * loop to return the number of bytes written up to this point. + * The data to be written is dropped on the floor. + */ + + break; + } + } + + /* Was anything written? */ + +#if !defined(CONFIG_RAMLOG_NONBLOCKING) || !defined(CONFIG_DISABLE_POLL) + if (nwritten > 0) + { + irqstate_t flags; +#ifndef CONFIG_RAMLOG_NONBLOCKING + int i; +#endif + + /* Are there threads waiting for read data? */ + + flags = irqsave(); +#ifndef CONFIG_RAMLOG_NONBLOCKING + for (i = 0; i < priv->rl_nwaiters; i++) + { + /* Yes.. Notify all of the waiting readers that more data is available */ + + sem_post(&priv->rl_waitsem); + } +#endif + + /* Notify all poll/select waiters that they can write to the FIFO */ + + ramlog_pollnotify(priv, POLLIN); + irqrestore(flags); + } +#endif + + /* We always have to return the number of bytes requested and NOT the + * number of bytes that were actually written. Otherwise, callers + * will think that this is a short write and probably retry (causing + */ + + return len; +} + +/**************************************************************************** + * Name: ramlog_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +int ramlog_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct ramlog_dev_s *priv; + pollevent_t eventset; + int ndx; + int ret; + int i; + + /* Some sanity checking */ + + DEBUGASSERT(inode && inode->i_private); + priv = inode->i_private; + + /* Get exclusive access to the poll structures */ + + ret = sem_wait(&priv->rl_exclsem); + if (ret < 0) + { + int errval = errno; + return -errval; + } + + /* Are we setting up the poll? Or tearing it down? */ + + if (setup) + { + /* This is a request to set up the poll. Find an available + * slot for the poll structure reference + */ + + for (i = 0; i < CONFIG_RAMLOG_NPOLLWAITERS; i++) + { + /* Find an available slot */ + + if (!priv->rl_fds[i]) + { + /* Bind the poll structure and this slot */ + + priv->rl_fds[i] = fds; + fds->priv = &priv->rl_fds[i]; + break; + } + } + + if (i >= CONFIG_RAMLOG_NPOLLWAITERS) + { + fds->priv = NULL; + ret = -EBUSY; + goto errout; + } + + /* Should immediately notify on any of the requested events? + * First, check if the xmit buffer is full. + */ + + eventset = 0; + + ndx = priv->rl_head + 1; + if (ndx >= priv->rl_bufsize) + { + ndx = 0; + } + + if (ndx != priv->rl_tail) + { + eventset |= POLLOUT; + } + + /* Check if the receive buffer is empty */ + + if (priv->rl_head != priv->rl_tail) + { + eventset |= POLLIN; + } + + if (eventset) + { + ramlog_pollnotify(priv, eventset); + } + + } + else if (fds->priv) + { + /* This is a request to tear down the poll. */ + + struct pollfd **slot = (struct pollfd **)fds->priv; + +#ifdef CONFIG_DEBUG + if (!slot) + { + ret = -EIO; + goto errout; + } +#endif + + /* Remove all memory of the poll setup */ + + *slot = NULL; + fds->priv = NULL; + } + +errout: + sem_post(&priv->rl_exclsem); + return ret; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ramlog_register + * + * Description: + * Create the RAM logging device and register it at the specified path. + * Mostly likely this path will be /dev/console + * + ****************************************************************************/ + +#if !defined(CONFIG_RAMLOG_CONSOLE) && !defined(CONFIG_RAMLOG_SYSLOG) +int ramlog_register(FAR const char *devpath, FAR char *buffer, size_t buflen) +{ + FAR struct ramlog_dev_s *priv; + int ret = -ENOMEM; + + /* Sanity checking */ + + DEBUGASSERT(devpath && buffer && buflen > 1); + + /* Allocate a RAM logging device structure */ + + priv = (struct ramlog_dev_s *)kzalloc(sizeof(struct ramlog_dev_s)); + if (priv) + { + /* Initialize the non-zero values in the RAM logging device structure */ + + sem_init(&priv->rl_exclsem, 0, 1); +#ifndef CONFIG_RAMLOG_NONBLOCKING + sem_init(&priv->rl_waitsem, 0, 0); +#endif + priv->rl_bufsize = buflen; + priv->rl_buffer = buffer; + + /* Register the character driver */ + + ret = register_driver(devpath, &g_ramlogfops, 0666, priv); + if (ret < 0) + { + kfree(priv); + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: ramlog_consoleinit + * + * Description: + * Create the RAM logging device and register it at the specified path. + * Mostly likely this path will be /dev/console + * + ****************************************************************************/ + +#ifdef CONFIG_RAMLOG_CONSOLE +int ramlog_consoleinit(void) +{ + FAR struct ramlog_dev_s *priv = &g_sysdev; + int ret; + + /* Register the console character driver */ + + ret = register_driver("/dev/console", &g_ramlogfops, 0666, priv); +} +#endif + +/**************************************************************************** + * Name: ramlog_sysloginit + * + * Description: + * Create the RAM logging device and register it at the specified path. + * Mostly likely this path will be CONFIG_RAMLOG_SYSLOG + * + * If CONFIG_RAMLOG_CONSOLE is also defined, then this functionality is + * performed when ramlog_consoleinit() is called. + * + ****************************************************************************/ + +#ifdef CONFIG_RAMLOG_SYSLOG +int ramlog_sysloginit(void) +{ + /* Register the syslog character driver */ + + return register_driver(CONFIG_SYSLOG_DEVPATH, &g_ramlogfops, 0666, &g_sysdev); +} +#endif + +/**************************************************************************** + * Name: syslog_putc + * + * Description: + * This is the low-level system logging interface. The debugging/syslogging + * interfaces are lib_rawprintf() and lib_lowprinf(). The difference is + * the lib_rawprintf() writes to fd=1 (stdout) and lib_lowprintf() uses + * a lower level interface that works from interrupt handlers. This + * function is a a low-level interface used to implement lib_lowprintf() + * when CONFIG_RAMLOG_SYSLOG=y and CONFIG_SYSLOG=y + * + ****************************************************************************/ + +#if defined(CONFIG_RAMLOG_CONSOLE) || defined(CONFIG_RAMLOG_SYSLOG) +int syslog_putc(int ch) +{ + FAR struct ramlog_dev_s *priv = &g_sysdev; + int ret; + + /* Ignore carriage returns */ + +#ifdef CONFIG_RAMLOG_CRLF + if (ch == '\r') + { + return ch; + } + + /* Pre-pend a newline with a carriage return */ + + if (ch == '\n') + { + ret = ramlog_addchar(priv, '\r'); + if (ret < 0) + { + /* The buffer is full and nothing was saved. */ + + return ch; + } + } +#endif + + (void)ramlog_addchar(priv, ch); + return ch; +} +#endif + +#endif /* CONFIG_RAMLOG */ diff --git a/nuttx/drivers/usbdev/Kconfig b/nuttx/drivers/usbdev/Kconfig new file mode 100644 index 0000000000..24b13f378b --- /dev/null +++ b/nuttx/drivers/usbdev/Kconfig @@ -0,0 +1,452 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# +menuconfig USBDEV_COMPOSITE + bool "USB composite device support" + default n + ---help--- + Enables USB composite device support +if USBDEV_COMPOSITE +#config COMPOSITE_IAD +# bool "" +# default n +# ---help--- +# If one of the members of the composite has multiple interfaces +# (such as CDC/ACM), then an Interface Association Descriptor (IAD) +# will be necessary. Default: IAD will be used automatically if +# needed. It should not be necessary to set this. + +config COMPOSITE_EP0MAXPACKET + int "Max packet size for endpoint 0" + default 64 + ---help--- + Max packet size for endpoint 0 + +config COMPOSITE_VENDORID + hex "Composite vendor ID" + default 0 + +config COMPOSITE_VENDORSTR + string "Composite vendor ID" + default "Nuttx" + ---help--- + The vendor ID code/string + +config COMPOSITE_PRODUCTID + hex "Composite product id" + default 0 + +config COMPOSITE_PRODUCTSTR + string "Composite product string" + default "Composite device" + ---help--- + The product ID code/string + +config COMPOSITE_SERIALSTR + string "Composite serial string" + default "001" + ---help--- + Device serial number string + +config COMPOSITE_CONFIGSTR + string "Configuration string" + default "Nuttx COMPOSITE config" + ---help--- + Configuration string + +config COMPOSITE_VERSIONNO + string "Composite version number" + default "" + ---help--- + Interface version number. +endif + +config USBDEV_ISOCHRONOUS + bool "Enable isochronous" + default n + ---help--- + Build in extra support for isochronous endpoints + +config USBDEV_DUALSPEED + bool "Enable high and full speed" + default n + ---help--- + Hardware handles high and full speed + operation (USB 2.0) + +choice USBDEV_POWERED + prompt "Select USB device powered" + default USBDEV_SELFPOWERED +config USBDEV_SELFPOWERED + bool "Self powerd" + ---help--- + Will cause USB features to indicate + that the device is self-powered + +config USBDEV_BUSPOWERED + bool "Bus powerd" + ---help--- + Will cause USB features to indicate + that the device is self-powered +endchoice +config USBDEV_MAXPOWER + int "Maximum power consumption in mA" + default 100 + depends on USBDEV_BUSPOWERED + ---help--- + Maximum power consumption in mA + +config USBDEV_TRACE + bool "Enable USB tracing for debug" + default n + ---help--- + Enables USB tracing for debug + +config USBDEV_TRACE_NRECORDS + int "Number of trace entries to remember" + default 32 + depends on USBDEV_TRACE + ---help--- + Number of trace entries to remember + +menuconfig PL2303 + bool "Emulates the Prolific PL2303 serial/USB converter" + default n + ---help--- + This logic emulates the Prolific PL2303 serial/USB converter +if PL2303 +config PL2303_EPINTIN + int "Logical endpoint numbers" + default 1 + +config PL2303_EPBULKOUT + int "Endpoint Bulkout" + default 2 + +config PL2303_EPBULKIN + int "Endpoint Bulkin" + default 3 + +config PL2303_EP0MAXPACKET + int "Packet and request buffer sizes" + default 64 + +config PL2303_NWRREQS + int "Number of read requests that can be in flight" + default 4 + ---help--- + The number of read requests that can be in flight + +config PL2303_NRDREQS + int "Number of write requests that can be in flight" + default 4 + ---help--- + The number of write/read requests that can be in flight + +config PL2303_RXBUFSIZE + int "Receive buffer size" + default 256 + ---help--- + Size of the serial receive/transmit buffers + +config PL2303_TXBUFSIZE + int "Transmit buffer size" + default 256 + ---help--- + Size of the serial receive/transmit buffers + +config PL2303_VENDORID + hex "Vendor ID" + default 0x067b + +config PL2303_PRODUCTID + hex "Product ID" + default 0x2303 + +config PL2303_VENDORSTR + string "Vendor string" + default "NuttX" + +config PL2303_PRODUCTSTR + string "Product string" + default "USBdev Serial" +endif + +menuconfig CDCACM + bool "USB Modem (CDC ACM) support" + default n + ---help--- + Enables USB Modem (CDC ACM) support +if CDCACM +config CDCACM_COMPOSITE + bool "CDCACM composite support" + default n + depends on USBDEV_COMPOSITE + ---help--- + Configure the CDC serial driver as part of a composite driver + (only if CONFIG_USBDEV_COMPOSITE is also defined) + +config CDCACM_IFNOBASE + int "Offset the CDC/ACM interface numbers" + default 0 + depends on CDCACM_COMPOSITE + ---help--- + If the CDC driver is part of a composite device, then this may need to + be defined to offset the CDC/ACM interface numbers so that they are + unique and contiguous. When used with the Mass Storage driver, the + correct value for this offset is zero. + +config CDCACM_STRBASE + int "Offset the CDC/ACM string numbers" + default 0 + depends on CDCACM_COMPOSITE + ---help--- + If the CDC driver is part of a composite device, then this may need to + be defined to offset the CDC/ACM string numbers so that they are + unique and contiguous. When used with the Mass Storage driver, the + correct value for this offset is four (this value actuallly only needs + to be defined if names are provided for the Notification interface, + config CDCACM_NOTIFSTR, or the data interface, CONFIG_CDCACM_DATAIFSTR). + +config CDCACM_EP0MAXPACKET + int "Endpoint 0 max packet size" + default 64 + ---help--- + Endpoint 0 max packet size. Default 64. + +config CDCACM_EPINTIN + int "Hardware endpoint that supports interrupt IN operation" + default 2 + ---help--- + The logical 7-bit address of a hardware endpoint that supports + interrupt IN operation. Default 2. + +config CDCACM_EPINTIN_FSSIZE + int "Endpoint in full speed size" + default 64 + ---help--- + Max package size for the interrupt IN endpoint if full speed mode. + Default 64. + +config CDCACM_EPINTIN_HSSIZE + int "Endpoint in high speed size" + default 64 + ---help--- + Max package size for the interrupt IN endpoint if high speed mode. + Default 64. + +config CDCACM_EPBULKOUT + int "Endpoint bulk out" + default 0 + ---help--- + The logical 7-bit address of a hardware endpoint that supports + bulk OUT operation + +config CDCACM_EPBULKOUT_FSSIZE + int "Endpoint bulk out full speed size" + default 64 + ---help--- + Max package size for the bulk OUT endpoint if full speed mode. + Default 64. + +config CDCACM_EPBULKOUT_HSSIZE + int "Endpoint bulk out high speed size" + default 512 + ---help--- + Max package size for the bulk OUT endpoint if high speed mode. + Default 512. + +config CDCACM_EPBULKIN + int "Endpoint bulk in" + default 0 + ---help--- + The logical 7-bit address of a hardware endpoint that supports + bulk IN operation + +config CDCACM_EPBULKIN_FSSIZE + int "Endpoint bulk in full speed size" + default 64 + ---help--- + Max package size for the bulk IN endpoint if full speed mode. + Default 64. + +config CDCACM_EPBULKIN_HSSIZE + int "Endpoint bulk in high speed size" + default 512 + ---help--- + Max package size for the bulk IN endpoint if high speed mode. + Default 512. + +config CDCACM_NWRREQS + int "Number of read requests that can be in flight" + default 4 + ---help--- + The number of read requests that can be in flight + +config CDCACM_NRDREQS + int "Number of write requests that can be in flight" + default 4 + ---help--- + The number of write/read requests that can be in flight + +config CDCACM_RXBUFSIZE + int "Receive buffer size" + default 256 + ---help--- + Size of the serial receive/transmit buffers + +config CDCACM_TXBUFSIZE + bool "Transmit buffer size" + default 256 + ---help--- + Size of the serial receive/transmit buffers + +config CDCACM_VENDORID + hex "Vendor ID" + default 0x0525 + ---help--- + The vendor ID code/string. Default 0x0525 and "NuttX" + 0x0525 is the Netchip vendor and should not be used in any + products. This default VID was selected for compatibility with + the Linux CDC ACM default VID. + +config CDCACM_PRODUCTID + hex "Product ID" + default 0xa4a7 + ---help--- + The product ID code/string. Default 0xa4a7 and "CDC/ACM Serial" + 0xa4a7 was selected for compatibility with the Linux CDC ACM + default PID. + +config CDCACM_VENDORSTR + string "Vendor string" + default "NuttX" + +config CDCACM_PRODUCTSTR + string "Product string" + default "USBdev Serial" +endif + +menuconfig USBMSC + bool "USB Mass storage class device" + default n + ---help--- + References: + "Universal Serial Bus Mass Storage Class, Specification Overview," + Revision 1.2, USB Implementer's Forum, June 23, 2003. + + "Universal Serial Bus Mass Storage Class, Bulk-Only Transport," + Revision 1.0, USB Implementer's Forum, September 31, 1999. + + "SCSI Primary Commands - 3 (SPC-3)," American National Standard + for Information Technology, May 4, 2005 + + "SCSI Primary Commands - 4 (SPC-4)," American National Standard + for Information Technology, July 19, 2008 + + "SCSI Block Commands -2 (SBC-2)," American National Standard + for Information Technology, November 13, 2004 + + "SCSI Multimedia Commands - 3 (MMC-3)," American National Standard + for Information Technology, November 12, 2001 + +if USBMSC +config USBMSC_COMPOSITE + bool "Mass storage composite support" + default n + depends on USBDEV_COMPOSITE + ---help--- + Configure the mass storage driver as part of a composite driver + (only if CONFIG_USBDEV_COMPOSITE is also defined) + +config USBMSC_IFNOBASE + int "Offset the mass storage interface number" + default 2 + depends on USBMSC_COMPOSITE + ---help--- + If the CDC driver is part of a composite device, then this may need to + be defined to offset the mass storage interface number so that it is + unique and contiguous. When used with the CDC/ACM driver, the + correct value for this offset is two (because of the two CDC/ACM + interfaces that will precede it). + +config USBMSC_STRBASE + int "Offset the mass storage string numbers" + default 2 + depends on USBMSC_COMPOSITE + ---help--- + If the CDC driver is part of a composite device, then this may need to + be defined to offset the mass storage string numbers so that they are + unique and contiguous. When used with the CDC/ACM driver, the + correct value for this offset is four (or perhaps 5 or 6, depending + on if CONFIG_CDCACM_NOTIFSTR or CONFIG_CDCACM_DATAIFSTR are defined). + +config USBMSC_EP0MAXPACKET + int "Max packet size for endpoint 0" + default 64 + ---help--- + Max packet size for endpoint 0 + +config USBMSC_EPBULKOUT + int "Endpoint bulk out" + default 0 + ---help--- + The logical 7-bit address of a hardware endpoints that support + bulk OUT and IN operations + +config USBMSC_EPBULKIN + int "Endpoint bulk in" + default 0 + ---help--- + The logical 7-bit address of a hardware endpoints that support + bulk OUT and IN operations + +config USBMSC_NWRREQS + int "The number of write requests that can be in flight" + default 4 + ---help--- + The number of write/read requests that can be in flight +config USBMSC_NRDREQS + int "The number of read requests that can be in flight" + default 4 + ---help--- + The number of write/read requests that can be in flight + +config USBMSC_BULKINREQLEN + int "Bulk in request size" + default 512 + +config USBMSC_BULKOUTREQLEN + int "Bulk out request size" + default 512 + ---help--- + The size of the buffer in each write/read request. This + value needs to be at least as large as the endpoint + maxpacket and ideally as large as a block device sector. + +config USBMSC_VENDORID + hex "Mass stroage Vendor ID" + default 0x00 + +config USBMSC_VENDORSTR + string "Mass stroage vendor string" + default "Nuttx" + ---help--- + The vendor ID code/string + +config USBMSC_PRODUCTID + hex "Mass stroage Product ID" + default 0x00 + +config USBMSC_PRODUCTSTR + string "Mass stroage product string" + default "Mass stroage" + +config USBMSC_REMOVABLE + bool "Mass stroage remove able" + default n + ---help--- + Select if the media is removable + USB Composite Device Configuration +endif diff --git a/nuttx/drivers/usbdev/Make.defs b/nuttx/drivers/usbdev/Make.defs new file mode 100644 index 0000000000..f1b3c405ae --- /dev/null +++ b/nuttx/drivers/usbdev/Make.defs @@ -0,0 +1,63 @@ +############################################################################ +# drivers/usbdev/Make.defs +# +# Copyright (C) 2008, 2010-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_USBDEV),y) + +# Include USB device drivers + +ifeq ($(CONFIG_PL2303),y) + CSRCS += pl2303.c +endif + +ifeq ($(CONFIG_CDCACM),y) + CSRCS += cdcacm.c cdcacm_desc.c +endif + +ifeq ($(CONFIG_USBMSC),y) + CSRCS += usbmsc.c usbmsc_desc.c usbmsc_scsi.c +endif + +ifeq ($(CONFIG_USBDEV_COMPOSITE),y) + CSRCS += composite.c composite_desc.c +endif + +CSRCS += usbdev_trace.c usbdev_trprintf.c + +# Include USB device build support + +DEPPATH += --dep-path usbdev +VPATH += :usbdev +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/usbdev} +endif diff --git a/nuttx/drivers/usbdev/cdcacm.c b/nuttx/drivers/usbdev/cdcacm.c new file mode 100644 index 0000000000..97c9d7c773 --- /dev/null +++ b/nuttx/drivers/usbdev/cdcacm.c @@ -0,0 +1,2212 @@ +/**************************************************************************** + * drivers/usbdev/cdcacm.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "cdcacm.h" + +#ifdef CONFIG_USBMSC_COMPOSITE +# include +# include "composite.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Container to support a list of requests */ + +struct cdcacm_req_s +{ + FAR struct cdcacm_req_s *flink; /* Implements a singly linked list */ + FAR struct usbdev_req_s *req; /* The contained request */ +}; + +/* This structure describes the internal state of the driver */ + +struct cdcacm_dev_s +{ + FAR struct uart_dev_s serdev; /* Serial device structure */ + FAR struct usbdev_s *usbdev; /* usbdev driver pointer */ + + uint8_t config; /* Configuration number */ + uint8_t nwrq; /* Number of queue write requests (in reqlist)*/ + uint8_t nrdq; /* Number of queue read requests (in epbulkout) */ + uint8_t minor; /* The device minor number */ + bool rxenabled; /* true: UART RX "interrupts" enabled */ + int16_t rxhead; /* Working head; used when rx int disabled */ + + uint8_t ctrlline; /* Buffered control line state */ + struct cdc_linecoding_s linecoding; /* Buffered line status */ + cdcacm_callback_t callback; /* Serial event callback function */ + + FAR struct usbdev_ep_s *epintin; /* Interrupt IN endpoint structure */ + FAR struct usbdev_ep_s *epbulkin; /* Bulk IN endpoint structure */ + FAR struct usbdev_ep_s *epbulkout; /* Bulk OUT endpoint structure */ + FAR struct usbdev_req_s *ctrlreq; /* Allocoated control request */ + struct sq_queue_s reqlist; /* List of write request containers */ + + /* Pre-allocated write request containers. The write requests will + * be linked in a free list (reqlist), and used to send requests to + * EPBULKIN; Read requests will be queued in the EBULKOUT. + */ + + struct cdcacm_req_s wrreqs[CONFIG_CDCACM_NWRREQS]; + struct cdcacm_req_s rdreqs[CONFIG_CDCACM_NWRREQS]; + + /* Serial I/O buffers */ + + char rxbuffer[CONFIG_CDCACM_RXBUFSIZE]; + char txbuffer[CONFIG_CDCACM_TXBUFSIZE]; +}; + +/* The internal version of the class driver */ + +struct cdcacm_driver_s +{ + struct usbdevclass_driver_s drvr; + FAR struct cdcacm_dev_s *dev; +}; + +/* This is what is allocated */ + +struct cdcacm_alloc_s +{ + struct cdcacm_dev_s dev; + struct cdcacm_driver_s drvr; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Transfer helpers *********************************************************/ + +static uint16_t cdcacm_fillrequest(FAR struct cdcacm_dev_s *priv, + uint8_t *reqbuf, uint16_t reqlen); +static int cdcacm_sndpacket(FAR struct cdcacm_dev_s *priv); +static inline int cdcacm_recvpacket(FAR struct cdcacm_dev_s *priv, + uint8_t *reqbuf, uint16_t reqlen); + +/* Request helpers *********************************************************/ + +static struct usbdev_req_s *cdcacm_allocreq(FAR struct usbdev_ep_s *ep, + uint16_t len); +static void cdcacm_freereq(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); + +/* Configuration ***********************************************************/ + +static void cdcacm_resetconfig(FAR struct cdcacm_dev_s *priv); +#ifdef CONFIG_USBDEV_DUALSPEED +static int cdcacm_epconfigure(FAR struct usbdev_ep_s *ep, + enum cdcacm_epdesc_e epid, uint16_t mxpacket, bool last); +#endif +static int cdcacm_setconfig(FAR struct cdcacm_dev_s *priv, + uint8_t config); + +/* Completion event handlers ***********************************************/ + +static void cdcacm_ep0incomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); +static void cdcacm_rdcomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); +static void cdcacm_wrcomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); + +/* USB class device ********************************************************/ + +static int cdcacm_bind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); +static void cdcacm_unbind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); +static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, + size_t outlen); +static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); + +/* UART Operations **********************************************************/ + +static int cdcuart_setup(FAR struct uart_dev_s *dev); +static void cdcuart_shutdown(FAR struct uart_dev_s *dev); +static int cdcuart_attach(FAR struct uart_dev_s *dev); +static void cdcuart_detach(FAR struct uart_dev_s *dev); +static int cdcuart_ioctl(FAR struct file *filep,int cmd,unsigned long arg); +static void cdcuart_rxint(FAR struct uart_dev_s *dev, bool enable); +static void cdcuart_txint(FAR struct uart_dev_s *dev, bool enable); +static bool cdcuart_txempty(FAR struct uart_dev_s *dev); + +/**************************************************************************** + * Private Variables + ****************************************************************************/ +/* USB class device *********************************************************/ + +static const struct usbdevclass_driverops_s g_driverops = +{ + cdcacm_bind, /* bind */ + cdcacm_unbind, /* unbind */ + cdcacm_setup, /* setup */ + cdcacm_disconnect, /* disconnect */ + NULL, /* suspend */ + NULL, /* resume */ +}; + +/* Serial port **************************************************************/ + +static const struct uart_ops_s g_uartops = +{ + cdcuart_setup, /* setup */ + cdcuart_shutdown, /* shutdown */ + cdcuart_attach, /* attach */ + cdcuart_detach, /* detach */ + cdcuart_ioctl, /* ioctl */ + NULL, /* receive */ + cdcuart_rxint, /* rxinit */ + NULL, /* rxavailable */ + NULL, /* send */ + cdcuart_txint, /* txinit */ + NULL, /* txready */ + cdcuart_txempty /* txempty */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cdcacm_fillrequest + * + * Description: + * If there is data to send it is copied to the given buffer. Called + * either to initiate the first write operation, or from the completion + * interrupt handler service consecutive write operations. + * + * NOTE: The USB serial driver does not use the serial drivers + * uart_xmitchars() API. That logic is essentially duplicated here because + * unlike UART hardware, we need to be able to handle writes not byte-by-byte, + * but packet-by-packet. Unfortunately, that decision also exposes some + * internals of the serial driver in the following. + * + ****************************************************************************/ + +static uint16_t cdcacm_fillrequest(FAR struct cdcacm_dev_s *priv, uint8_t *reqbuf, + uint16_t reqlen) +{ + FAR uart_dev_t *serdev = &priv->serdev; + FAR struct uart_buffer_s *xmit = &serdev->xmit; + irqstate_t flags; + uint16_t nbytes = 0; + + /* Disable interrupts */ + + flags = irqsave(); + + /* Transfer bytes while we have bytes available and there is room in the request */ + + while (xmit->head != xmit->tail && nbytes < reqlen) + { + *reqbuf++ = xmit->buffer[xmit->tail]; + nbytes++; + + /* Increment the tail pointer */ + + if (++(xmit->tail) >= xmit->size) + { + xmit->tail = 0; + } + } + + /* When all of the characters have been sent from the buffer + * disable the "TX interrupt". + */ + + if (xmit->head == xmit->tail) + { + uart_disabletxint(serdev); + } + + /* If any bytes were removed from the buffer, inform any waiters + * there there is space available. + */ + + if (nbytes) + { + uart_datasent(serdev); + } + + irqrestore(flags); + return nbytes; +} + +/**************************************************************************** + * Name: cdcacm_sndpacket + * + * Description: + * This function obtains write requests, transfers the TX data into the + * request, and submits the requests to the USB controller. This continues + * untils either (1) there are no further packets available, or (2) thre is + * no further data to send. + * + ****************************************************************************/ + +static int cdcacm_sndpacket(FAR struct cdcacm_dev_s *priv) +{ + FAR struct usbdev_ep_s *ep; + FAR struct usbdev_req_s *req; + FAR struct cdcacm_req_s *reqcontainer; + uint16_t reqlen; + irqstate_t flags; + int len; + int ret = OK; + +#ifdef CONFIG_DEBUG + if (priv == NULL) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return -ENODEV; + } +#endif + + flags = irqsave(); + + /* Use our IN endpoint for the transfer */ + + ep = priv->epbulkin; + + /* Loop until either (1) we run out or write requests, or (2) cdcacm_fillrequest() + * is unable to fill the request with data (i.e., until there is no more data + * to be sent). + */ + + uvdbg("head=%d tail=%d nwrq=%d empty=%d\n", + priv->serdev.xmit.head, priv->serdev.xmit.tail, + priv->nwrq, sq_empty(&priv->reqlist)); + + /* Get the maximum number of bytes that will fit into one bulk IN request */ + +#ifdef CONFIG_CDCACM_BULKREQLEN + reqlen = MAX(CONFIG_CDCACM_BULKREQLEN, ep->maxpacket); +#else + reqlen = ep->maxpacket; +#endif + + while (!sq_empty(&priv->reqlist)) + { + /* Peek at the request in the container at the head of the list */ + + reqcontainer = (struct cdcacm_req_s *)sq_peek(&priv->reqlist); + req = reqcontainer->req; + + /* Fill the request with serial TX data */ + + len = cdcacm_fillrequest(priv, req->buf, reqlen); + if (len > 0) + { + /* Remove the empty container from the request list */ + + (void)sq_remfirst(&priv->reqlist); + priv->nwrq--; + + /* Then submit the request to the endpoint */ + + req->len = len; + req->priv = reqcontainer; + req->flags = USBDEV_REQFLAGS_NULLPKT; + ret = EP_SUBMIT(ep, req); + if (ret != OK) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_SUBMITFAIL), (uint16_t)-ret); + break; + } + } + else + { + break; + } + } + + irqrestore(flags); + return ret; +} + +/**************************************************************************** + * Name: cdcacm_recvpacket + * + * Description: + * A normal completion event was received by the read completion handler + * at the interrupt level (with interrupts disabled). This function handles + * the USB packet and provides the received data to the uart RX buffer. + * + * Assumptions: + * Called from the USB interrupt handler with interrupts disabled. + * + ****************************************************************************/ + +static inline int cdcacm_recvpacket(FAR struct cdcacm_dev_s *priv, + uint8_t *reqbuf, uint16_t reqlen) +{ + FAR uart_dev_t *serdev = &priv->serdev; + FAR struct uart_buffer_s *recv = &serdev->recv; + uint16_t currhead; + uint16_t nexthead; + uint16_t nbytes = 0; + + uvdbg("head=%d tail=%d nrdq=%d reqlen=%d\n", + priv->serdev.recv.head, priv->serdev.recv.tail, priv->nrdq, reqlen); + + /* Get the next head index. During the time that RX interrupts are disabled, the + * the serial driver will be extracting data from the circular buffer and modifying + * recv.tail. During this time, we should avoid modifying recv.head; Instead we will + * use a shadow copy of the index. When interrupts are restored, the real recv.head + * will be updated with this indes. + */ + + if (priv->rxenabled) + { + currhead = recv->head; + } + else + { + currhead = priv->rxhead; + } + + /* Pre-calculate the head index and check for wrap around. We need to do this + * so that we can determine if the circular buffer will overrun BEFORE we + * overrun the buffer! + */ + + nexthead = currhead + 1; + if (nexthead >= recv->size) + { + nexthead = 0; + } + + /* Then copy data into the RX buffer until either: (1) all of the data has been + * copied, or (2) the RX buffer is full. NOTE: If the RX buffer becomes full, + * then we have overrun the serial driver and data will be lost. + */ + + while (nexthead != recv->tail && nbytes < reqlen) + { + /* Copy one byte to the head of the circular RX buffer */ + + recv->buffer[currhead] = *reqbuf++; + + /* Update counts and indices */ + + currhead = nexthead; + nbytes++; + + /* Increment the head index and check for wrap around */ + + nexthead = currhead + 1; + if (nexthead >= recv->size) + { + nexthead = 0; + } + } + + /* Write back the head pointer using the shadow index if RX "interrupts" + * are disabled. + */ + + if (priv->rxenabled) + { + recv->head = currhead; + } + else + { + priv->rxhead = currhead; + } + + /* If data was added to the incoming serial buffer, then wake up any + * threads is waiting for incoming data. If we are running in an interrupt + * handler, then the serial driver will not run until the interrupt handler + * returns. + */ + + if (priv->rxenabled && nbytes > 0) + { + uart_datareceived(serdev); + } + + /* Return an error if the entire packet could not be transferred */ + + if (nbytes < reqlen) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RXOVERRUN), 0); + return -ENOSPC; + } + return OK; +} + +/**************************************************************************** + * Name: cdcacm_allocreq + * + * Description: + * Allocate a request instance along with its buffer + * + ****************************************************************************/ + +static struct usbdev_req_s *cdcacm_allocreq(FAR struct usbdev_ep_s *ep, + uint16_t len) +{ + FAR struct usbdev_req_s *req; + + req = EP_ALLOCREQ(ep); + if (req != NULL) + { + req->len = len; + req->buf = EP_ALLOCBUFFER(ep, len); + if (!req->buf) + { + EP_FREEREQ(ep, req); + req = NULL; + } + } + return req; +} + +/**************************************************************************** + * Name: cdcacm_freereq + * + * Description: + * Free a request instance along with its buffer + * + ****************************************************************************/ + +static void cdcacm_freereq(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req) +{ + if (ep != NULL && req != NULL) + { + if (req->buf != NULL) + { + EP_FREEBUFFER(ep, req->buf); + } + EP_FREEREQ(ep, req); + } +} + +/**************************************************************************** + * Name: cdcacm_resetconfig + * + * Description: + * Mark the device as not configured and disable all endpoints. + * + ****************************************************************************/ + +static void cdcacm_resetconfig(FAR struct cdcacm_dev_s *priv) +{ + /* Are we configured? */ + + if (priv->config != CDCACM_CONFIGIDNONE) + { + /* Yes.. but not anymore */ + + priv->config = CDCACM_CONFIGIDNONE; + + /* Disable endpoints. This should force completion of all pending + * transfers. + */ + + EP_DISABLE(priv->epintin); + EP_DISABLE(priv->epbulkin); + EP_DISABLE(priv->epbulkout); + } +} + +/**************************************************************************** + * Name: cdcacm_epconfigure + * + * Description: + * Configure one endpoint. + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +static int cdcacm_epconfigure(FAR struct usbdev_ep_s *ep, + enum cdcacm_epdesc_e epid, uint16_t mxpacket, + bool last) +{ + struct usb_epdesc_s epdesc; + cdcacm_mkepdesc(epid, mxpacket, &epdesc); + return EP_CONFIGURE(ep, &epdesc, last); +} +#endif + +/**************************************************************************** + * Name: cdcacm_setconfig + * + * Description: + * Set the device configuration by allocating and configuring endpoints and + * by allocating and queue read and write requests. + * + ****************************************************************************/ + +static int cdcacm_setconfig(FAR struct cdcacm_dev_s *priv, uint8_t config) +{ + FAR struct usbdev_req_s *req; + int i; + int ret = 0; + +#if CONFIG_DEBUG + if (priv == NULL) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return -EIO; + } +#endif + + if (config == priv->config) + { + /* Already configured -- Do nothing */ + + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_ALREADYCONFIGURED), 0); + return 0; + } + + /* Discard the previous configuration data */ + + cdcacm_resetconfig(priv); + + /* Was this a request to simply discard the current configuration? */ + + if (config == CDCACM_CONFIGIDNONE) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_CONFIGNONE), 0); + return 0; + } + + /* We only accept one configuration */ + + if (config != CDCACM_CONFIGID) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_CONFIGIDBAD), 0); + return -EINVAL; + } + + /* Configure the IN interrupt endpoint */ + +#ifdef CONFIG_USBDEV_DUALSPEED + if (priv->usbdev->speed == USB_SPEED_HIGH) + { + ret = cdcacm_epconfigure(priv->epintin, CDCACM_EPINTIN, + CONFIG_CDCACM_EPINTIN_HSSIZE, false); + } + else +#endif + { + ret = EP_CONFIGURE(priv->epintin, + cdcacm_getepdesc(CDCACM_EPINTIN), false); + } + + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPINTINCONFIGFAIL), 0); + goto errout; + } + priv->epintin->priv = priv; + + /* Configure the IN bulk endpoint */ + +#ifdef CONFIG_USBDEV_DUALSPEED + if (priv->usbdev->speed == USB_SPEED_HIGH) + { + ret = cdcacm_epconfigure(priv->epbulkin, CDCACM_EPBULKIN, + CONFIG_CDCACM_EPBULKIN_HSSIZE, false); + } + else +#endif + { + ret = EP_CONFIGURE(priv->epbulkin, + cdcacm_getepdesc(CDCACM_EPBULKIN), false); + } + + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKINCONFIGFAIL), 0); + goto errout; + } + + priv->epbulkin->priv = priv; + + /* Configure the OUT bulk endpoint */ + +#ifdef CONFIG_USBDEV_DUALSPEED + if (priv->usbdev->speed == USB_SPEED_HIGH) + { + ret = cdcacm_epconfigure(priv->epbulkout, CDCACM_EPBULKOUT, + CONFIG_CDCACM_EPBULKOUT_HSSIZE, true); + } + else +#endif + { + ret = EP_CONFIGURE(priv->epbulkout, + cdcacm_getepdesc(CDCACM_EPBULKOUT), true); + } + + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKOUTCONFIGFAIL), 0); + goto errout; + } + + priv->epbulkout->priv = priv; + + /* Queue read requests in the bulk OUT endpoint */ + + DEBUGASSERT(priv->nrdq == 0); + for (i = 0; i < CONFIG_CDCACM_NRDREQS; i++) + { + req = priv->rdreqs[i].req; + req->callback = cdcacm_rdcomplete; + ret = EP_SUBMIT(priv->epbulkout, req); + if (ret != OK) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-ret); + goto errout; + } + priv->nrdq++; + } + + priv->config = config; + return OK; + +errout: + cdcacm_resetconfig(priv); + return ret; +} + +/**************************************************************************** + * Name: cdcacm_ep0incomplete + * + * Description: + * Handle completion of EP0 control operations + * + ****************************************************************************/ + +static void cdcacm_ep0incomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req) +{ + if (req->result || req->xfrd != req->len) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_REQRESULT), (uint16_t)-req->result); + } +} + +/**************************************************************************** + * Name: cdcacm_rdcomplete + * + * Description: + * Handle completion of read request on the bulk OUT endpoint. This + * is handled like the receipt of serial data on the "UART" + * + ****************************************************************************/ + +static void cdcacm_rdcomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req) +{ + FAR struct cdcacm_dev_s *priv; + irqstate_t flags; + int ret; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (!ep || !ep->priv || !req) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract references to private data */ + + priv = (FAR struct cdcacm_dev_s*)ep->priv; + + /* Process the received data unless this is some unusual condition */ + + flags = irqsave(); + switch (req->result) + { + case 0: /* Normal completion */ + usbtrace(TRACE_CLASSRDCOMPLETE, priv->nrdq); + cdcacm_recvpacket(priv, req->buf, req->xfrd); + break; + + case -ESHUTDOWN: /* Disconnection */ + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSHUTDOWN), 0); + priv->nrdq--; + irqrestore(flags); + return; + + default: /* Some other error occurred */ + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDUNEXPECTED), (uint16_t)-req->result); + break; + }; + + /* Requeue the read request */ + +#ifdef CONFIG_CDCACM_BULKREQLEN + req->len = MAX(CONFIG_CDCACM_BULKREQLEN, ep->maxpacket); +#else + req->len = ep->maxpacket; +#endif + + ret = EP_SUBMIT(ep, req); + if (ret != OK) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-req->result); + } + irqrestore(flags); +} + +/**************************************************************************** + * Name: cdcacm_wrcomplete + * + * Description: + * Handle completion of write request. This function probably executes + * in the context of an interrupt handler. + * + ****************************************************************************/ + +static void cdcacm_wrcomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req) +{ + FAR struct cdcacm_dev_s *priv; + FAR struct cdcacm_req_s *reqcontainer; + irqstate_t flags; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (!ep || !ep->priv || !req || !req->priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract references to our private data */ + + priv = (FAR struct cdcacm_dev_s *)ep->priv; + reqcontainer = (FAR struct cdcacm_req_s *)req->priv; + + /* Return the write request to the free list */ + + flags = irqsave(); + sq_addlast((sq_entry_t*)reqcontainer, &priv->reqlist); + priv->nwrq++; + irqrestore(flags); + + /* Send the next packet unless this was some unusual termination + * condition + */ + + switch (req->result) + { + case OK: /* Normal completion */ + usbtrace(TRACE_CLASSWRCOMPLETE, priv->nwrq); + cdcacm_sndpacket(priv); + break; + + case -ESHUTDOWN: /* Disconnection */ + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_WRSHUTDOWN), priv->nwrq); + break; + + default: /* Some other error occurred */ + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_WRUNEXPECTED), (uint16_t)-req->result); + break; + } +} + +/**************************************************************************** + * USB Class Driver Methods + ****************************************************************************/ + +/**************************************************************************** + * Name: cdcacm_bind + * + * Description: + * Invoked when the driver is bound to a USB device driver + * + ****************************************************************************/ + +static int cdcacm_bind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct cdcacm_dev_s *priv = ((FAR struct cdcacm_driver_s*)driver)->dev; + FAR struct cdcacm_req_s *reqcontainer; + irqstate_t flags; + uint16_t reqlen; + int ret; + int i; + + usbtrace(TRACE_CLASSBIND, 0); + + /* Bind the structures */ + + priv->usbdev = dev; + + /* Save the reference to our private data structure in EP0 so that it + * can be recovered in ep0 completion events (Unless we are part of + * a composite device and, in that case, the composite device owns + * EP0). + */ + +#ifndef CONFIG_USBMSC_COMPOSITE + dev->ep0->priv = priv; +#endif + + /* Preallocate control request */ + + priv->ctrlreq = cdcacm_allocreq(dev->ep0, CDCACM_MXDESCLEN); + if (priv->ctrlreq == NULL) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_ALLOCCTRLREQ), 0); + ret = -ENOMEM; + goto errout; + } + priv->ctrlreq->callback = cdcacm_ep0incomplete; + + /* Pre-allocate all endpoints... the endpoints will not be functional + * until the SET CONFIGURATION request is processed in cdcacm_setconfig. + * This is done here because there may be calls to kmalloc and the SET + * CONFIGURATION processing probably occurrs within interrupt handling + * logic where kmalloc calls will fail. + */ + + /* Pre-allocate the IN interrupt endpoint */ + + priv->epintin = DEV_ALLOCEP(dev, CDCACM_EPINTIN_ADDR, true, USB_EP_ATTR_XFER_INT); + if (!priv->epintin) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPINTINALLOCFAIL), 0); + ret = -ENODEV; + goto errout; + } + priv->epintin->priv = priv; + + /* Pre-allocate the IN bulk endpoint */ + + priv->epbulkin = DEV_ALLOCEP(dev, CDCACM_EPINBULK_ADDR, true, USB_EP_ATTR_XFER_BULK); + if (!priv->epbulkin) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKINALLOCFAIL), 0); + ret = -ENODEV; + goto errout; + } + priv->epbulkin->priv = priv; + + /* Pre-allocate the OUT bulk endpoint */ + + priv->epbulkout = DEV_ALLOCEP(dev, CDCACM_EPOUTBULK_ADDR, false, USB_EP_ATTR_XFER_BULK); + if (!priv->epbulkout) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKOUTALLOCFAIL), 0); + ret = -ENODEV; + goto errout; + } + priv->epbulkout->priv = priv; + + /* Pre-allocate read requests */ + +#ifdef CONFIG_CDCACM_BULKREQLEN + reqlen = MAX(CONFIG_CDCACM_BULKREQLEN, priv->epbulkout->maxpacket); +#else + reqlen = priv->epbulkout->maxpacket; +#endif + + for (i = 0; i < CONFIG_CDCACM_NRDREQS; i++) + { + reqcontainer = &priv->rdreqs[i]; + reqcontainer->req = cdcacm_allocreq(priv->epbulkout, reqlen); + if (reqcontainer->req == NULL) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDALLOCREQ), -ENOMEM); + ret = -ENOMEM; + goto errout; + } + reqcontainer->req->priv = reqcontainer; + reqcontainer->req->callback = cdcacm_rdcomplete; + } + + /* Pre-allocate write request containers and put in a free list */ + +#ifdef CONFIG_CDCACM_BULKREQLEN + reqlen = MAX(CONFIG_CDCACM_BULKREQLEN, priv->epbulkin->maxpacket); +#else + reqlen = priv->epbulkin->maxpacket; +#endif + + for (i = 0; i < CONFIG_CDCACM_NWRREQS; i++) + { + reqcontainer = &priv->wrreqs[i]; + reqcontainer->req = cdcacm_allocreq(priv->epbulkin, reqlen); + if (reqcontainer->req == NULL) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_WRALLOCREQ), -ENOMEM); + ret = -ENOMEM; + goto errout; + } + reqcontainer->req->priv = reqcontainer; + reqcontainer->req->callback = cdcacm_wrcomplete; + + flags = irqsave(); + sq_addlast((sq_entry_t*)reqcontainer, &priv->reqlist); + priv->nwrq++; /* Count of write requests available */ + irqrestore(flags); + } + + /* Report if we are selfpowered (unless we are part of a composite device) */ + +#ifndef CONFIG_CDCACM_COMPOSITE +#ifdef CONFIG_USBDEV_SELFPOWERED + DEV_SETSELFPOWERED(dev); +#endif + + /* And pull-up the data line for the soft connect function (unless we are + * part of a composite device) + */ + + DEV_CONNECT(dev); +#endif + return OK; + +errout: + cdcacm_unbind(driver, dev); + return ret; +} + +/**************************************************************************** + * Name: cdcacm_unbind + * + * Description: + * Invoked when the driver is unbound from a USB device driver + * + ****************************************************************************/ + +static void cdcacm_unbind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct cdcacm_dev_s *priv; + FAR struct cdcacm_req_s *reqcontainer; + irqstate_t flags; + int i; + + usbtrace(TRACE_CLASSUNBIND, 0); + +#ifdef CONFIG_DEBUG + if (!driver || !dev) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = ((FAR struct cdcacm_driver_s*)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EP0NOTBOUND), 0); + return; + } +#endif + + /* Make sure that we are not already unbound */ + + if (priv != NULL) + { + /* Make sure that the endpoints have been unconfigured. If + * we were terminated gracefully, then the configuration should + * already have been reset. If not, then calling cdcacm_resetconfig + * should cause the endpoints to immediately terminate all + * transfers and return the requests to us (with result == -ESHUTDOWN) + */ + + cdcacm_resetconfig(priv); + up_mdelay(50); + + /* Free the interrupt IN endpoint */ + + if (priv->epintin) + { + DEV_FREEEP(dev, priv->epintin); + priv->epintin = NULL; + } + + /* Free the bulk IN endpoint */ + + if (priv->epbulkin) + { + DEV_FREEEP(dev, priv->epbulkin); + priv->epbulkin = NULL; + } + + /* Free the pre-allocated control request */ + + if (priv->ctrlreq != NULL) + { + cdcacm_freereq(dev->ep0, priv->ctrlreq); + priv->ctrlreq = NULL; + } + + /* Free pre-allocated read requests (which should all have + * been returned to the free list at this time -- we don't check) + */ + + DEBUGASSERT(priv->nrdq == 0); + for (i = 0; i < CONFIG_CDCACM_NRDREQS; i++) + { + reqcontainer = &priv->rdreqs[i]; + if (reqcontainer->req) + { + cdcacm_freereq(priv->epbulkout, reqcontainer->req); + reqcontainer->req = NULL; + } + } + + /* Free the bulk OUT endpoint */ + + if (priv->epbulkout) + { + DEV_FREEEP(dev, priv->epbulkout); + priv->epbulkout = NULL; + } + + /* Free write requests that are not in use (which should be all + * of them) + */ + + flags = irqsave(); + DEBUGASSERT(priv->nwrq == CONFIG_CDCACM_NWRREQS); + while (!sq_empty(&priv->reqlist)) + { + reqcontainer = (struct cdcacm_req_s *)sq_remfirst(&priv->reqlist); + if (reqcontainer->req != NULL) + { + cdcacm_freereq(priv->epbulkin, reqcontainer->req); + priv->nwrq--; /* Number of write requests queued */ + } + } + DEBUGASSERT(priv->nwrq == 0); + irqrestore(flags); + } + + /* Clear out all data in the circular buffer */ + + priv->serdev.xmit.head = 0; + priv->serdev.xmit.tail = 0; +} + +/**************************************************************************** + * Name: cdcacm_setup + * + * Description: + * Invoked for ep0 control requests. This function probably executes + * in the context of an interrupt handler. + * + ****************************************************************************/ + +static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, + FAR uint8_t *dataout, size_t outlen) +{ + FAR struct cdcacm_dev_s *priv; + FAR struct usbdev_req_s *ctrlreq; + uint16_t value; + uint16_t index; + uint16_t len; + int ret = -EOPNOTSUPP; + +#ifdef CONFIG_DEBUG + if (!driver || !dev || !ctrl) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return -EIO; + } +#endif + + /* Extract reference to private data */ + + usbtrace(TRACE_CLASSSETUP, ctrl->req); + priv = ((FAR struct cdcacm_driver_s*)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv || !priv->ctrlreq) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EP0NOTBOUND), 0); + return -ENODEV; + } +#endif + ctrlreq = priv->ctrlreq; + + /* Extract the little-endian 16-bit values to host order */ + + value = GETUINT16(ctrl->value); + index = GETUINT16(ctrl->index); + len = GETUINT16(ctrl->len); + + uvdbg("type=%02x req=%02x value=%04x index=%04x len=%04x\n", + ctrl->type, ctrl->req, value, index, len); + + if ((ctrl->type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) + { + /*********************************************************************** + * Standard Requests + ***********************************************************************/ + + switch (ctrl->req) + { + case USB_REQ_GETDESCRIPTOR: + { + /* The value field specifies the descriptor type in the MS byte and the + * descriptor index in the LS byte (order is little endian) + */ + + switch (ctrl->value[1]) + { + /* If the serial device is used in as part of a composite device, + * then the device descriptor is provided by logic in the composite + * device implementation. + */ + +#ifndef CONFIG_CDCACM_COMPOSITE + case USB_DESC_TYPE_DEVICE: + { + ret = USB_SIZEOF_DEVDESC; + memcpy(ctrlreq->buf, cdcacm_getdevdesc(), ret); + } + break; +#endif + + /* If the serial device is used in as part of a composite device, + * then the device qualifier descriptor is provided by logic in the + * composite device implementation. + */ + +#if !defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED) + case USB_DESC_TYPE_DEVICEQUALIFIER: + { + ret = USB_SIZEOF_QUALDESC; + memcpy(ctrlreq->buf, cdcacm_getqualdesc(), ret); + } + break; + + case USB_DESC_TYPE_OTHERSPEEDCONFIG: +#endif + + /* If the serial device is used in as part of a composite device, + * then the configuration descriptor is provided by logic in the + * composite device implementation. + */ + +#ifndef CONFIG_CDCACM_COMPOSITE + case USB_DESC_TYPE_CONFIG: + { +#ifdef CONFIG_USBDEV_DUALSPEED + ret = cdcacm_mkcfgdesc(ctrlreq->buf, dev->speed, ctrl->req); +#else + ret = cdcacm_mkcfgdesc(ctrlreq->buf); +#endif + } + break; +#endif + + /* If the serial device is used in as part of a composite device, + * then the language string descriptor is provided by logic in the + * composite device implementation. + */ + +#ifndef CONFIG_CDCACM_COMPOSITE + case USB_DESC_TYPE_STRING: + { + /* index == language code. */ + + ret = cdcacm_mkstrdesc(ctrl->value[0], (struct usb_strdesc_s *)ctrlreq->buf); + } + break; +#endif + + default: + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_GETUNKNOWNDESC), value); + } + break; + } + } + break; + + case USB_REQ_SETCONFIGURATION: + { + if (ctrl->type == 0) + { + ret = cdcacm_setconfig(priv, value); + } + } + break; + + /* If the serial device is used in as part of a composite device, + * then the overall composite class configuration is managed by logic + * in the composite device implementation. + */ + +#ifndef CONFIG_CDCACM_COMPOSITE + case USB_REQ_GETCONFIGURATION: + { + if (ctrl->type == USB_DIR_IN) + { + *(uint8_t*)ctrlreq->buf = priv->config; + ret = 1; + } + } + break; +#endif + + case USB_REQ_SETINTERFACE: + { + if (ctrl->type == USB_REQ_RECIPIENT_INTERFACE && + priv->config == CDCACM_CONFIGID) + { + if ((index == CDCACM_NOTIFID && value == CDCACM_NOTALTIFID) || + (index == CDCACM_DATAIFID && value == CDCACM_DATAALTIFID)) + { + cdcacm_resetconfig(priv); + cdcacm_setconfig(priv, priv->config); + ret = 0; + } + } + } + break; + + case USB_REQ_GETINTERFACE: + { + if (ctrl->type == (USB_DIR_IN|USB_REQ_RECIPIENT_INTERFACE) && + priv->config == CDCACM_CONFIGIDNONE) + { + if ((index == CDCACM_NOTIFID && value == CDCACM_NOTALTIFID) || + (index == CDCACM_DATAIFID && value == CDCACM_DATAALTIFID)) + { + *(uint8_t*) ctrlreq->buf = value; + ret = 1; + } + else + { + ret = -EDOM; + } + } + } + break; + + default: + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDSTDREQ), ctrl->req); + break; + } + } + + else if ((ctrl->type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_CLASS) + { + /*********************************************************************** + * CDC ACM-Specific Requests + ***********************************************************************/ + + switch (ctrl->req) + { + /* ACM_GET_LINE_CODING requests current DTE rate, stop-bits, parity, and + * number-of-character bits. (Optional) + */ + + case ACM_GET_LINE_CODING: + { + if (ctrl->type == (USB_DIR_IN|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE) && + index == CDCACM_NOTIFID) + { + /* Return the current line status from the private data structure */ + + memcpy(ctrlreq->buf, &priv->linecoding, SIZEOF_CDC_LINECODING); + ret = SIZEOF_CDC_LINECODING; + } + else + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDCLASSREQ), ctrl->type); + } + } + break; + + /* ACM_SET_LINE_CODING configures DTE rate, stop-bits, parity, and + * number-of-character bits. (Optional) + */ + + case ACM_SET_LINE_CODING: + { + if (ctrl->type == (USB_DIR_OUT|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE) && + len == SIZEOF_CDC_LINECODING && /* dataout && len == outlen && */ + index == CDCACM_NOTIFID) + { + /* Save the new line coding in the private data structure. NOTE: + * that this is conditional now because not all device controller + * drivers supported provisioni of EP0 OUT data with the setup + * command. + */ + + if (dataout && len <= SIZEOF_CDC_LINECODING) /* REVISIT */ + { + memcpy(&priv->linecoding, dataout, SIZEOF_CDC_LINECODING); + } + ret = 0; + + /* If there is a registered callback to receive line status info, then + * callout now. + */ + + if (priv->callback) + { + priv->callback(CDCACM_EVENT_LINECODING); + } + } + else + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDCLASSREQ), ctrl->type); + } + } + break; + + /* ACM_SET_CTRL_LINE_STATE: RS-232 signal used to tell the DCE device the + * DTE device is now present. (Optional) + */ + + case ACM_SET_CTRL_LINE_STATE: + { + if (ctrl->type == (USB_DIR_OUT|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE) && + index == CDCACM_NOTIFID) + { + /* Save the control line state in the private data structure. Only bits + * 0 and 1 have meaning. + */ + + priv->ctrlline = value & 3; + ret = 0; + + /* If there is a registered callback to receive control line status info, + * then callout now. + */ + + if (priv->callback) + { + priv->callback(CDCACM_EVENT_CTRLLINE); + } + } + else + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDCLASSREQ), ctrl->type); + } + } + break; + + /* Sends special carrier*/ + + case ACM_SEND_BREAK: + { + if (ctrl->type == (USB_DIR_OUT|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE) && + index == CDCACM_NOTIFID) + { + /* If there is a registered callback to handle the SendBreak request, + * then callout now. + */ + + ret = 0; + if (priv->callback) + { + priv->callback(CDCACM_EVENT_SENDBREAK); + } + } + else + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDCLASSREQ), ctrl->type); + } + } + break; + + default: + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDCLASSREQ), ctrl->req); + break; + } + } + else + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDTYPE), ctrl->type); + } + + /* Respond to the setup command if data was returned. On an error return + * value (ret < 0), the USB driver will stall. + */ + + if (ret >= 0) + { + /* Configure the response */ + + ctrlreq->len = MIN(len, ret); + ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT; + + /* Send the response -- either directly to the USB controller or + * indirectly in the case where this class is a member of a composite + * device. + */ + +#ifndef CONFIG_CDCACM_COMPOSITE + ret = EP_SUBMIT(dev->ep0, ctrlreq); +#else + ret = composite_ep0submit(driver, dev, ctrlreq); +#endif + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPRESPQ), (uint16_t)-ret); + ctrlreq->result = OK; + cdcacm_ep0incomplete(dev->ep0, ctrlreq); + } + } + return ret; +} + +/**************************************************************************** + * Name: cdcacm_disconnect + * + * Description: + * Invoked after all transfers have been stopped, when the host is + * disconnected. This function is probably called from the context of an + * interrupt handler. + * + ****************************************************************************/ + +static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct cdcacm_dev_s *priv; + irqstate_t flags; + + usbtrace(TRACE_CLASSDISCONNECT, 0); + +#ifdef CONFIG_DEBUG + if (!driver || !dev || !dev->ep0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = ((FAR struct cdcacm_driver_s*)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EP0NOTBOUND), 0); + return; + } +#endif + + /* Reset the configuration */ + + flags = irqsave(); + cdcacm_resetconfig(priv); + + /* Clear out all data in the circular buffer */ + + priv->serdev.xmit.head = 0; + priv->serdev.xmit.tail = 0; + irqrestore(flags); + + /* Perform the soft connect function so that we will we can be + * re-enumerated (unless we are part of a composite device) + */ + +#ifndef CONFIG_CDCACM_COMPOSITE + DEV_CONNECT(dev); +#endif +} + +/**************************************************************************** + * Serial Device Methods + ****************************************************************************/ + +/**************************************************************************** + * Name: cdcuart_setup + * + * Description: + * This method is called the first time that the serial port is opened. + * + ****************************************************************************/ + +static int cdcuart_setup(FAR struct uart_dev_s *dev) +{ + FAR struct cdcacm_dev_s *priv; + + usbtrace(CDCACM_CLASSAPI_SETUP, 0); + + /* Sanity check */ + +#if CONFIG_DEBUG + if (!dev || !dev->priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return -EIO; + } +#endif + + /* Extract reference to private data */ + + priv = (FAR struct cdcacm_dev_s*)dev->priv; + + /* Check if we have been configured */ + + if (priv->config == CDCACM_CONFIGIDNONE) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_SETUPNOTCONNECTED), 0); + return -ENOTCONN; + } + + return OK; +} + +/**************************************************************************** + * Name: cdcuart_shutdown + * + * Description: + * This method is called when the serial port is closed. This operation + * is very simple for the USB serial backend because the serial driver + * has already assured that the TX data has full drained -- it calls + * cdcuart_txempty() until that function returns true before calling this + * function. + * + ****************************************************************************/ + +static void cdcuart_shutdown(FAR struct uart_dev_s *dev) +{ + usbtrace(CDCACM_CLASSAPI_SHUTDOWN, 0); + + /* Sanity check */ + +#if CONFIG_DEBUG + if (!dev || !dev->priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + } +#endif +} + +/**************************************************************************** + * Name: cdcuart_attach + * + * Description: + * Does not apply to the USB serial class device + * + ****************************************************************************/ + +static int cdcuart_attach(FAR struct uart_dev_s *dev) +{ + usbtrace(CDCACM_CLASSAPI_ATTACH, 0); + return OK; +} + +/**************************************************************************** + * Name: cdcuart_detach + * + * Description: +* Does not apply to the USB serial class device + * + ****************************************************************************/ + +static void cdcuart_detach(FAR struct uart_dev_s *dev) +{ + usbtrace(CDCACM_CLASSAPI_DETACH, 0); +} + +/**************************************************************************** + * Name: cdcuart_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int cdcuart_ioctl(FAR struct file *filep,int cmd,unsigned long arg) +{ + struct inode *inode = filep->f_inode; + struct cdcacm_dev_s *priv = inode->i_private; + int ret = OK; + + switch (cmd) + { + /* CAICO_REGISTERCB + * Register a callback for serial event notification. Argument: + * cdcacm_callback_t. See cdcacm_callback_t type definition below. + * NOTE: The callback will most likely invoked at the interrupt level. + * The called back function should, therefore, limit its operations to + * invoking some kind of IPC to handle the serial event in some normal + * task environment. + */ + + case CAIOC_REGISTERCB: + { + /* Save the new callback function */ + + priv->callback = (cdcacm_callback_t)((uintptr_t)arg); + } + break; + + /* CAIOC_GETLINECODING + * Get current line coding. Argument: struct cdc_linecoding_s*. + * See include/nuttx/usb/cdc.h for structure definition. This IOCTL + * should be called to get the data associated with the + * CDCACM_EVENT_LINECODING event). + */ + + case CAIOC_GETLINECODING: + { + FAR struct cdc_linecoding_s *ptr = (FAR struct cdc_linecoding_s *)((uintptr_t)arg); + if (ptr) + { + memcpy(ptr, &priv->linecoding, sizeof(struct cdc_linecoding_s)); + } + else + { + ret = -EINVAL; + } + } + break; + + /* CAIOC_GETCTRLLINE + * Get control line status bits. Argument FAR int*. See + * include/nuttx/usb/cdc.h for bit definitions. This IOCTL should be + * called to get the data associated CDCACM_EVENT_CTRLLINE event. + */ + + case CAIOC_GETCTRLLINE: + { + FAR int *ptr = (FAR int *)((uintptr_t)arg); + if (ptr) + { + *ptr = priv->ctrlline; + } + else + { + ret = -EINVAL; + } + } + break; + + /* CAIOC_NOTIFY + * Send a serial state to the host via the Interrupt IN endpoint. + * Argument: int. This includes the current state of the carrier detect, + * DSR, break, and ring signal. See "Table 69: UART State Bitmap Values" + * and CDC_UART_definitions in include/nuttx/usb/cdc.h. + */ + + case CAIOC_NOTIFY: + { + /* Not yet implemented. I probably won't bother to implement until + * I comr up with a usage model that needs it. + * + * Here is what the needs to be done: + * + * 1. Format and send a request header with: + * + * bmRequestType: + * USB_REQ_DIR_IN|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE + * bRequest: ACM_SERIAL_STATE + * wValue: 0 + * wIndex: 0 + * wLength: Length of data + * + * 2. Followed by the notification data (in a separate packet) + */ + + ret = -ENOSYS; + } + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Name: cdcuart_rxint + * + * Description: + * Called by the serial driver to enable or disable RX interrupts. We, of + * course, have no RX interrupts but must behave consistently. This method + * is called under the conditions: + * + * 1. With enable==true when the port is opened (just after cdcuart_setup + * and cdcuart_attach are called called) + * 2. With enable==false while transferring data from the RX buffer + * 2. With enable==true while waiting for more incoming data + * 3. With enable==false when the port is closed (just before cdcuart_detach + * and cdcuart_shutdown are called). + * + ****************************************************************************/ + +static void cdcuart_rxint(FAR struct uart_dev_s *dev, bool enable) +{ + FAR struct cdcacm_dev_s *priv; + FAR uart_dev_t *serdev; + irqstate_t flags; + + usbtrace(CDCACM_CLASSAPI_RXINT, (uint16_t)enable); + + /* Sanity check */ + +#if CONFIG_DEBUG + if (!dev || !dev->priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = (FAR struct cdcacm_dev_s*)dev->priv; + serdev = &priv->serdev; + + /* We need exclusive access to the RX buffer and private structure + * in the following. + */ + + flags = irqsave(); + if (enable) + { + /* RX "interrupts" are enabled. Is this a transition from disabled + * to enabled state? + */ + + if (!priv->rxenabled) + { + /* Yes. During the time that RX interrupts are disabled, the + * the serial driver will be extracting data from the circular + * buffer and modifying recv.tail. During this time, we + * should avoid modifying recv.head; When interrupts are restored, + * we can update the head pointer for all of the data that we + * put into cicular buffer while "interrupts" were disabled. + */ + + if (priv->rxhead != serdev->recv.head) + { + serdev->recv.head = priv->rxhead; + + /* Yes... signal the availability of new data */ + + uart_datareceived(serdev); + } + + /* RX "interrupts are no longer disabled */ + + priv->rxenabled = true; + } + } + + /* RX "interrupts" are disabled. Is this a transition from enabled + * to disabled state? + */ + + else if (priv->rxenabled) + { + /* Yes. During the time that RX interrupts are disabled, the + * the serial driver will be extracting data from the circular + * buffer and modifying recv.tail. During this time, we + * should avoid modifying recv.head; When interrupts are disabled, + * we use a shadow index and continue adding data to the circular + * buffer. + */ + + priv->rxhead = serdev->recv.head; + priv->rxenabled = false; + } + irqrestore(flags); +} + +/**************************************************************************** + * Name: cdcuart_txint + * + * Description: + * Called by the serial driver to enable or disable TX interrupts. We, of + * course, have no TX interrupts but must behave consistently. Initially, + * TX interrupts are disabled. This method is called under the conditions: + * + * 1. With enable==false while transferring data into the TX buffer + * 2. With enable==true when data may be taken from the buffer. + * 3. With enable==false when the TX buffer is empty + * + ****************************************************************************/ + +static void cdcuart_txint(FAR struct uart_dev_s *dev, bool enable) +{ + FAR struct cdcacm_dev_s *priv; + + usbtrace(CDCACM_CLASSAPI_TXINT, (uint16_t)enable); + + /* Sanity checks */ + +#if CONFIG_DEBUG + if (!dev || !dev->priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract references to private data */ + + priv = (FAR struct cdcacm_dev_s*)dev->priv; + + /* If the new state is enabled and if there is data in the XMIT buffer, + * send the next packet now. + */ + + uvdbg("enable=%d head=%d tail=%d\n", + enable, priv->serdev.xmit.head, priv->serdev.xmit.tail); + + if (enable && priv->serdev.xmit.head != priv->serdev.xmit.tail) + { + cdcacm_sndpacket(priv); + } +} + +/**************************************************************************** + * Name: cdcuart_txempty + * + * Description: + * Return true when all data has been sent. This is called from the + * serial driver when the driver is closed. It will call this API + * periodically until it reports true. NOTE that the serial driver takes all + * responsibility for flushing TX data through the hardware so we can be + * a bit sloppy about that. + * + ****************************************************************************/ + +static bool cdcuart_txempty(FAR struct uart_dev_s *dev) +{ + FAR struct cdcacm_dev_s *priv = (FAR struct cdcacm_dev_s*)dev->priv; + + usbtrace(CDCACM_CLASSAPI_TXEMPTY, 0); + +#if CONFIG_DEBUG + if (!priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return true; + } +#endif + + /* When all of the allocated write requests have been returned to the + * reqlist, then there is no longer any TX data in flight. + */ + + return priv->nwrq >= CONFIG_CDCACM_NWRREQS; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cdcacm_classobject + * + * Description: + * Register USB serial port (and USB serial console if so configured) and + * return the class object. + * + * Input Parameter: + * minor - Device minor number. E.g., minor 0 would correspond to + * /dev/ttyACM0. + * classdev - The location to return the CDC serial class' device + * instance. + * + * Returned Value: + * A pointer to the allocated class object (NULL on failure). + * + ****************************************************************************/ + +#ifndef CONFIG_CDCACM_COMPOSITE +static +#endif +int cdcacm_classobject(int minor, FAR struct usbdevclass_driver_s **classdev) +{ + FAR struct cdcacm_alloc_s *alloc; + FAR struct cdcacm_dev_s *priv; + FAR struct cdcacm_driver_s *drvr; + char devname[CDCACM_DEVNAME_SIZE]; + int ret; + + /* Allocate the structures needed */ + + alloc = (FAR struct cdcacm_alloc_s*)kmalloc(sizeof(struct cdcacm_alloc_s)); + if (!alloc) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_ALLOCDEVSTRUCT), 0); + return -ENOMEM; + } + + /* Convenience pointers into the allocated blob */ + + priv = &alloc->dev; + drvr = &alloc->drvr; + + /* Initialize the USB serial driver structure */ + + memset(priv, 0, sizeof(struct cdcacm_dev_s)); + sq_init(&priv->reqlist); + + priv->minor = minor; + + /* Fake line status */ + + priv->linecoding.baud[0] = (115200) & 0xff; /* Baud=115200 */ + priv->linecoding.baud[1] = (115200 >> 8) & 0xff; + priv->linecoding.baud[2] = (115200 >> 16) & 0xff; + priv->linecoding.baud[3] = (115200 >> 24) & 0xff; + priv->linecoding.stop = CDC_CHFMT_STOP1; /* One stop bit */ + priv->linecoding.parity = CDC_PARITY_NONE; /* No parity */ + priv->linecoding.nbits = 8; /* 8 data bits */ + + /* Initialize the serial driver sub-structure */ + + priv->serdev.recv.size = CONFIG_CDCACM_RXBUFSIZE; + priv->serdev.recv.buffer = priv->rxbuffer; + priv->serdev.xmit.size = CONFIG_CDCACM_TXBUFSIZE; + priv->serdev.xmit.buffer = priv->txbuffer; + priv->serdev.ops = &g_uartops; + priv->serdev.priv = priv; + + /* Initialize the USB class driver structure */ + +#ifdef CONFIG_USBDEV_DUALSPEED + drvr->drvr.speed = USB_SPEED_HIGH; +#else + drvr->drvr.speed = USB_SPEED_FULL; +#endif + drvr->drvr.ops = &g_driverops; + drvr->dev = priv; + + /* Register the USB serial console */ + +#ifdef CONFIG_CDCACM_CONSOLE + priv->serdev.isconsole = true; + ret = uart_register("/dev/console", &priv->serdev); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_CONSOLEREGISTER), (uint16_t)-ret); + goto errout_with_class; + } +#endif + + /* Register the CDC/ACM TTY device */ + + sprintf(devname, CDCACM_DEVNAME_FORMAT, minor); + ret = uart_register(devname, &priv->serdev); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UARTREGISTER), (uint16_t)-ret); + goto errout_with_class; + } + + *classdev = &drvr->drvr; + return OK; + +errout_with_class: + kfree(alloc); + return ret; +} + +/**************************************************************************** + * Name: cdcacm_initialize + * + * Description: + * Register USB serial port (and USB serial console if so configured). + * + * Input Parameter: + * minor - Device minor number. E.g., minor 0 would correspond to + * /dev/ttyACM0. + * handle - An optional opaque reference to the CDC/ACM class object that + * may subsequently be used with cdcacm_uninitialize(). + * + * Returned Value: + * Zero (OK) means that the driver was successfully registered. On any + * failure, a negated errno value is retured. + * + ****************************************************************************/ + +#ifndef CONFIG_CDCACM_COMPOSITE +int cdcacm_initialize(int minor, FAR void **handle) +{ + FAR struct usbdevclass_driver_s *drvr = NULL; + int ret; + + /* Get an instance of the serial driver class object */ + + ret = cdcacm_classobject(minor, &drvr); + if (ret == OK) + { + /* Register the USB serial class driver */ + + ret = usbdev_register(drvr); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_DEVREGISTER), (uint16_t)-ret); + } + } + + /* Return the driver instance (if any) if the caller has requested it + * by provided a pointer to the location to return it. + */ + + if (handle) + { + *handle = (FAR void*)drvr; + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: cdcacm_uninitialize + * + * Description: + * Un-initialize the USB storage class driver. This function is used + * internally by the USB composite driver to unitialized the CDC/ACM + * driver. This same interface is available (with an untyped input + * parameter) when the CDC/ACM driver is used standalone. + * + * Input Parameters: + * There is one parameter, it differs in typing depending upon whether the + * CDC/ACM driver is an internal part of a composite device, or a standalone + * USB driver: + * + * classdev - The class object returned by board_cdcclassobject() or + * cdcacm_classobject() + * handle - The opaque handle represetning the class object returned by + * a previous call to cdcacm_initialize(). + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_CDCACM_COMPOSITE +void cdcacm_uninitialize(FAR struct usbdevclass_driver_s *classdev) +#else +void cdcacm_uninitialize(FAR void *handle) +#endif +{ +#ifdef CONFIG_CDCACM_COMPOSITE + FAR struct cdcacm_driver_s *drvr = (FAR struct cdcacm_driver_s *)classdev; +#else + FAR struct cdcacm_driver_s *drvr = (FAR struct cdcacm_driver_s *)handle; +#endif + FAR struct cdcacm_dev_s *priv = drvr->dev; + char devname[CDCACM_DEVNAME_SIZE]; + int ret; + + /* Un-register the CDC/ACM TTY device */ + + sprintf(devname, CDCACM_DEVNAME_FORMAT, priv->minor); + ret = unregister_driver(devname); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UARTUNREGISTER), (uint16_t)-ret); + } + + /* Unregister the driver (unless we are a part of a composite device). The + * device unregister logic will (1) return all of the requests to us then + * (2) all the unbind method. + * + * The same thing will happen in the composite case except that: (1) the + * composite driver will call usbdev_unregister() which will (2) return the + * requests for all members of the composite, and (3) call the unbind + * method in the composite device which will (4) call the unbind method + * for this device. + */ + +#ifndef CONFIG_CDCACM_COMPOSITE + usbdev_unregister(&drvr->drvr); +#endif + + /* And free the driver structure */ + + kfree(priv); +} diff --git a/nuttx/drivers/usbdev/cdcacm.h b/nuttx/drivers/usbdev/cdcacm.h new file mode 100644 index 0000000000..8b06ca9f3f --- /dev/null +++ b/nuttx/drivers/usbdev/cdcacm.h @@ -0,0 +1,350 @@ +/**************************************************************************** + * drivers/usbdev/cdcacm.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_USBDEV_CDCACM_H +#define __DRIVERS_USBDEV_CDCACM_H 1 + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* If the serial device is configured as part of a composite device than both + * CONFIG_USBDEV_COMPOSITE and CONFIG_CDCACM_COMPOSITE must be defined. + */ + +#ifndef CONFIG_USBDEV_COMPOSITE +# undef CONFIG_CDCACM_COMPOSITE +#endif + +#if defined(CONFIG_CDCACM_COMPOSITE) && !defined(CONFIG_CDCACM_STRBASE) +# define CONFIG_CDCACM_STRBASE (4) +#endif + +#if defined(CONFIG_CDCACM_COMPOSITE) && !defined(CONFIG_COMPOSITE_IAD) +# warning "CONFIG_COMPOSITE_IAD may be needed" +#endif + +/* Packet and request buffer sizes */ + +#ifndef CONFIG_CDCACM_COMPOSITE +# ifndef CONFIG_CDCACM_EP0MAXPACKET +# define CONFIG_CDCACM_EP0MAXPACKET 64 +# endif +#endif + +/* Interface IDs. If the serial driver is built as a component of a composite + * device, then the interface IDs may need to be offset. + */ + +#ifndef CONFIG_CDCACM_COMPOSITE +# undef CONFIG_CDCACM_IFNOBASE +# define CONFIG_CDCACM_IFNOBASE 0 +#endif + +#ifndef CONFIG_CDCACM_IFNOBASE +# define CONFIG_CDCACM_IFNOBASE 0 +#endif + +/* Descriptors **************************************************************/ +/* These settings are not modifiable via the NuttX configuration */ + +#define CDC_VERSIONNO 0x0110 /* CDC version number 1.10 (BCD) */ +#define CDCACM_CONFIGIDNONE (0) /* Config ID means to return to address mode */ + +/* Interface IDs: + * + * CDCACM_NINTERFACES Two interfaces + * CDCACM_NOTIFID ID of the notifier interface + * CDCACM_NOTALTIFID No alternate for the notifier interface + * CDCACM_DATAIFID ID of the data interface + * CDCACM_DATAALTIFID No alternate for the data interface + */ + +#define CDCACM_NINTERFACES (2) /* Number of interfaces in the configuration */ +#define CDCACM_NOTIFID (CONFIG_CDCACM_IFNOBASE+0) +#define CDCACM_NOTALTIFID (0) +#define CDCACM_DATAIFID (CONFIG_CDCACM_IFNOBASE+1) +#define CDCACM_DATAALTIFID (0) + +/* Configuration descriptor values */ + +#define CDCACM_CONFIGID (1) /* The only supported configuration ID */ + +/* Buffer big enough for any of our descriptors (the config descriptor is the + * biggest). + */ + +#define CDCACM_MXDESCLEN (64) + +/* Device descriptor values */ + +#define CDCACM_VERSIONNO (0x0101) /* Device version number 1.1 (BCD) */ +#define CDCACM_NCONFIGS (1) /* Number of configurations supported */ + +/* String language */ + +#define CDCACM_STR_LANGUAGE (0x0409) /* en-us */ + +/* Descriptor strings. If there serial device is part of a composite device + * then the manufacturer, product, and serial number strings will be provided + * by the composite logic. + */ + +#ifndef CONFIG_CDCACM_COMPOSITE +# define CDCACM_MANUFACTURERSTRID (1) +# define CDCACM_PRODUCTSTRID (2) +# define CDCACM_SERIALSTRID (3) +# define CDCACM_CONFIGSTRID (4) + +# define CDCACM_LASTBASESTRID (4) +# undef CONFIG_CDCACM_STRBASE +# define CONFIG_CDCACM_STRBASE (0) +#else +# define CDCACM_LASTBASESTRID CONFIG_CDCACM_STRBASE +#endif + +/* These string IDs only exist if a user-defined string is provided */ + +#ifdef CONFIG_CDCACM_NOTIFSTR +# define CDCACM_NOTIFSTRID (CDCACM_LASTBASESTRID+1) +#else +# define CDCACM_NOTIFSTRID CDCACM_LASTBASESTRID +#endif + +#ifdef CONFIG_CDCACM_DATAIFSTR +# define CDCACM_DATAIFSTRID (CDCACM_NOTIFSTRID+1) +#else +# define CDCACM_DATAIFSTRID CDCACM_NOTIFSTRID +#endif + +#define CDCACM_LASTSTRID CDCACM_DATAIFSTRID +#define CDCACM_NSTRIDS (CDCACM_LASTSTRID - CONFIG_CDCACM_STRBASE) + +/* Configuration descriptor size */ + +#if !defined(CONFIG_CDCACM_COMPOSITE) + +/* Number of individual descriptors in the configuration descriptor: + * Configuration descriptor + (2) interface descriptors + (3) endpoint + * descriptors + (3) ACM descriptors. + */ + +# define CDCACM_CFGGROUP_SIZE (9) + +/* The size of the config descriptor: (9 + 2*9 + 3*7 + 4 + 5 + 5) = 62 */ + +# define SIZEOF_CDCACM_CFGDESC \ + (USB_SIZEOF_CFGDESC + 2*USB_SIZEOF_IFDESC + 3*USB_SIZEOF_EPDESC + \ + SIZEOF_ACM_FUNCDESC + SIZEOF_HDR_FUNCDESC + SIZEOF_UNION_FUNCDESC(1)) + +#elif defined(CONFIG_COMPOSITE_IAD) + +/* Number of individual descriptors in the configuration descriptor: + * (1) interface association descriptor + (2) interface descriptors + + * (3) endpoint descriptors + (3) ACM descriptors. + */ + +# define CDCACM_CFGGROUP_SIZE (9) + +/* The size of the config descriptor: (8 + 2*9 + 3*7 + 4 + 5 + 5) = 61 */ + +# define SIZEOF_CDCACM_CFGDESC \ + (USB_SIZEOF_IADDESC +2*USB_SIZEOF_IFDESC + 3*USB_SIZEOF_EPDESC + \ + SIZEOF_ACM_FUNCDESC + SIZEOF_HDR_FUNCDESC + SIZEOF_UNION_FUNCDESC(1)) + +#else + +/* Number of individual descriptors in the configuration descriptor: + * (2) interface descriptors + (3) endpoint descriptors + (3) ACM descriptors. + */ + +# define CDCACM_CFGGROUP_SIZE (8) + +/* The size of the config descriptor: (2*9 + 3*7 + 4 + 5 + 5) = 53 */ + +# define SIZEOF_CDCACM_CFGDESC \ + (2*USB_SIZEOF_IFDESC + 3*USB_SIZEOF_EPDESC + SIZEOF_ACM_FUNCDESC + \ + SIZEOF_HDR_FUNCDESC + SIZEOF_UNION_FUNCDESC(1)) +#endif + +/* Endpoint configuration ****************************************************/ + +#define CDCACM_EPINTIN_ADDR (USB_DIR_IN|CONFIG_CDCACM_EPINTIN) +#define CDCACM_EPINTIN_ATTR (USB_EP_ATTR_XFER_INT) + +#define CDCACM_EPOUTBULK_ADDR (CONFIG_CDCACM_EPBULKOUT) +#define CDCACM_EPOUTBULK_ATTR (USB_EP_ATTR_XFER_BULK) + +#define CDCACM_EPINBULK_ADDR (USB_DIR_IN|CONFIG_CDCACM_EPBULKIN) +#define CDCACM_EPINBULK_ATTR (USB_EP_ATTR_XFER_BULK) + +/* Device driver definitions ************************************************/ +/* A CDC/ACM device is specific by a minor number in the range of 0-255. + * This maps to a character device at /dev/ttyACMx, x=0..255. + */ + +#define CDCACM_DEVNAME_FORMAT "/dev/ttyACM%d" +#define CDCACM_DEVNAME_SIZE 16 + +/* Misc Macros **************************************************************/ +/* MIN/MAX macros */ + +#ifndef MIN +# define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + +#ifndef MAX +# define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +/* Trace values *************************************************************/ + +#define CDCACM_CLASSAPI_SETUP TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_SETUP) +#define CDCACM_CLASSAPI_SHUTDOWN TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_SHUTDOWN) +#define CDCACM_CLASSAPI_ATTACH TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_ATTACH) +#define CDCACM_CLASSAPI_DETACH TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_DETACH) +#define CDCACM_CLASSAPI_IOCTL TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_IOCTL) +#define CDCACM_CLASSAPI_RECEIVE TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_RECEIVE) +#define CDCACM_CLASSAPI_RXINT TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_RXINT) +#define CDCACM_CLASSAPI_RXAVAILABLE TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_RXAVAILABLE) +#define CDCACM_CLASSAPI_SEND TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_SEND) +#define CDCACM_CLASSAPI_TXINT TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_TXINT) +#define CDCACM_CLASSAPI_TXREADY TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_TXREADY) +#define CDCACM_CLASSAPI_TXEMPTY TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_TXEMPTY) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +enum cdcacm_epdesc_e +{ + CDCACM_EPINTIN = 0, /* Interrupt IN endpoint descriptor */ + CDCACM_EPBULKOUT, /* Bulk OUT endpoint descriptor */ + CDCACM_EPBULKIN /* Bulk IN endpoint descriptor */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: cdcacm_mkstrdesc + * + * Description: + * Construct a string descriptor + * + ****************************************************************************/ + +int cdcacm_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc); + +/**************************************************************************** + * Name: cdcacm_getepdesc + * + * Description: + * Return a pointer to the raw device descriptor + * + ****************************************************************************/ + +#ifndef CONFIG_CDCACM_COMPOSITE +FAR const struct usb_devdesc_s *cdcacm_getdevdesc(void); +#endif + +/**************************************************************************** + * Name: cdcacm_getepdesc + * + * Description: + * Return a pointer to the raw endpoint descriptor (used for configuring + * endpoints) + * + ****************************************************************************/ + +FAR const struct usb_epdesc_s *cdcacm_getepdesc(enum cdcacm_epdesc_e epid); + +/**************************************************************************** + * Name: cdcacm_mkepdesc + * + * Description: + * Construct the endpoint descriptor using the correct max packet size. + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +void cdcacm_mkepdesc(enum cdcacm_epdesc_e epid, + uint16_t mxpacket, FAR struct usb_epdesc_s *outdesc); +#endif + +/**************************************************************************** + * Name: cdcacm_mkcfgdesc + * + * Description: + * Construct the configuration descriptor + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf, uint8_t speed, uint8_t type); +#else +int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf); +#endif + +/**************************************************************************** + * Name: cdcacm_getqualdesc + * + * Description: + * Return a pointer to the raw qual descriptor + * + ****************************************************************************/ + +#if !defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED) +FAR const struct usb_qualdesc_s *cdcacm_getqualdesc(void); +#endif + +#endif /* __DRIVERS_USBDEV_CDCACM_H */ diff --git a/nuttx/drivers/usbdev/cdcacm_desc.c b/nuttx/drivers/usbdev/cdcacm_desc.c new file mode 100644 index 0000000000..fde13bfd3c --- /dev/null +++ b/nuttx/drivers/usbdev/cdcacm_desc.c @@ -0,0 +1,613 @@ +/**************************************************************************** + * drivers/usbdev/cdcacm_desc.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "cdcacm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Describes one description in the group of descriptors forming the + * total configuration descriptor. + */ + +struct cfgdecsc_group_s +{ + uint16_t descsize; /* Size of the descriptor in bytes */ + uint16_t hsepsize; /* High speed max packet size */ + FAR void *desc; /* A pointer to the descriptor */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* USB descriptor templates these will be copied and modified **************/ +/* Device Descriptor. If the USB serial device is configured as part of + * composite device, then the device descriptor will be provided by the + * composite device logic. + */ + +#ifndef CONFIG_CDCACM_COMPOSITE +static const struct usb_devdesc_s g_devdesc = +{ + USB_SIZEOF_DEVDESC, /* len */ + USB_DESC_TYPE_DEVICE, /* type */ + { /* usb */ + LSBYTE(0x0200), + MSBYTE(0x0200) + }, + USB_CLASS_CDC, /* class */ + CDC_SUBCLASS_NONE, /* subclass */ + CDC_PROTO_NONE, /* protocol */ + CONFIG_CDCACM_EP0MAXPACKET, /* maxpacketsize */ + { + LSBYTE(CONFIG_CDCACM_VENDORID), /* vendor */ + MSBYTE(CONFIG_CDCACM_VENDORID) + }, + { + LSBYTE(CONFIG_CDCACM_PRODUCTID), /* product */ + MSBYTE(CONFIG_CDCACM_PRODUCTID) + }, + { + LSBYTE(CDCACM_VERSIONNO), /* device */ + MSBYTE(CDCACM_VERSIONNO) + }, + CDCACM_MANUFACTURERSTRID, /* imfgr */ + CDCACM_PRODUCTSTRID, /* iproduct */ + CDCACM_SERIALSTRID, /* serno */ + CDCACM_NCONFIGS /* nconfigs */ +}; +#endif + +/* Configuration descriptor. If the USB serial device is configured as part of + * composite device, then the configuration descriptor will be provided by the + * composite device logic. + */ + +#ifndef CONFIG_CDCACM_COMPOSITE +static const struct usb_cfgdesc_s g_cfgdesc = +{ + USB_SIZEOF_CFGDESC, /* len */ + USB_DESC_TYPE_CONFIG, /* type */ + { + LSBYTE(SIZEOF_CDCACM_CFGDESC), /* LS totallen */ + MSBYTE(SIZEOF_CDCACM_CFGDESC) /* MS totallen */ + }, + CDCACM_NINTERFACES, /* ninterfaces */ + CDCACM_CONFIGID, /* cfgvalue */ + CDCACM_CONFIGSTRID, /* icfg */ + USB_CONFIG_ATTR_ONE|SELFPOWERED|REMOTEWAKEUP, /* attr */ + (CONFIG_USBDEV_MAXPOWER + 1) / 2 /* mxpower */ +}; +#endif + +/* Interface association descriptor */ + +#if defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_COMPOSITE_IAD) +static const struct usb_iaddesc_s g_iaddesc = +{ + USB_SIZEOF_IADDESC, /* len */ + USB_DESC_TYPE_INTERFACEASSOCIATION, /* type */ + CONFIG_CDCACM_IFNOBASE, /* firstif */ + CDCACM_NINTERFACES, /* nifs */ + USB_CLASS_CDC, /* class */ + CDC_SUBCLASS_ACM, /* subclass */ + CDC_PROTO_NONE, /* protocol */ + 0 /* ifunction */ +}; +#endif + +/* Notification interface */ + +static const struct usb_ifdesc_s g_notifdesc = +{ + USB_SIZEOF_IFDESC, /* len */ + USB_DESC_TYPE_INTERFACE, /* type */ + CDCACM_NOTIFID, /* ifno */ + CDCACM_NOTALTIFID, /* alt */ + 1, /* neps */ + USB_CLASS_CDC, /* class */ + CDC_SUBCLASS_ACM, /* subclass */ + CDC_PROTO_ATM, /* proto */ +#ifdef CONFIG_CDCACM_NOTIFSTR + CDCACM_NOTIFSTRID /* iif */ +#else + 0 /* iif */ +#endif +}; + +/* Header functional descriptor */ + +static const struct cdc_hdr_funcdesc_s g_funchdr = +{ + SIZEOF_HDR_FUNCDESC, /* size */ + USB_DESC_TYPE_CSINTERFACE, /* type */ + CDC_DSUBTYPE_HDR, /* subtype */ + { + LSBYTE(CDC_VERSIONNO), /* LS cdc */ + MSBYTE(CDC_VERSIONNO) /* MS cdc */ + } +}; + +/* ACM functional descriptor */ + +static const struct cdc_acm_funcdesc_s g_acmfunc = +{ + SIZEOF_ACM_FUNCDESC, /* size */ + USB_DESC_TYPE_CSINTERFACE, /* type */ + CDC_DSUBTYPE_ACM, /* subtype */ + 0x06 /* caps */ +}; + +/* Union functional descriptor */ + +static const struct cdc_union_funcdesc_s g_unionfunc = +{ + SIZEOF_UNION_FUNCDESC(1), /* size */ + USB_DESC_TYPE_CSINTERFACE, /* type */ + CDC_DSUBTYPE_UNION, /* subtype */ + 0, /* master */ + {1} /* slave[0] */ +}; + +/* Interrupt IN endpoint descriptor */ + +static const struct usb_epdesc_s g_epintindesc = +{ + USB_SIZEOF_EPDESC, /* len */ + USB_DESC_TYPE_ENDPOINT, /* type */ + CDCACM_EPINTIN_ADDR, /* addr */ + CDCACM_EPINTIN_ATTR, /* attr */ + { + LSBYTE(CONFIG_CDCACM_EPINTIN_FSSIZE), /* maxpacket (full speed) */ + MSBYTE(CONFIG_CDCACM_EPINTIN_FSSIZE) + }, + 0xff /* interval */ +}; + +/* Data interface descriptor */ + +static const struct usb_ifdesc_s g_dataifdesc = +{ + USB_SIZEOF_IFDESC, /* len */ + USB_DESC_TYPE_INTERFACE, /* type */ + CDCACM_DATAIFID, /* ifno */ + CDCACM_DATAALTIFID, /* alt */ + 2, /* neps */ + USB_CLASS_CDC_DATA, /* class */ + CDC_DATA_SUBCLASS_NONE, /* subclass */ + CDC_DATA_PROTO_NONE, /* proto */ +#ifdef CONFIG_CDCACM_DATAIFSTR + CDCACM_DATAIFSTRID /* iif */ +#else + 0 /* iif */ +#endif +}; + +/* Bulk OUT endpoint descriptor */ + +static const struct usb_epdesc_s g_epbulkoutdesc = +{ + USB_SIZEOF_EPDESC, /* len */ + USB_DESC_TYPE_ENDPOINT, /* type */ + CDCACM_EPOUTBULK_ADDR, /* addr */ + CDCACM_EPOUTBULK_ATTR, /* attr */ + { + LSBYTE(CONFIG_CDCACM_EPBULKOUT_FSSIZE), /* maxpacket (full speed) */ + MSBYTE(CONFIG_CDCACM_EPBULKOUT_FSSIZE) + }, + 1 /* interval */ +}; + +/* Bulk IN endpoint descriptor */ + +static const struct usb_epdesc_s g_epbulkindesc = +{ + USB_SIZEOF_EPDESC, /* len */ + USB_DESC_TYPE_ENDPOINT, /* type */ + CDCACM_EPINBULK_ADDR, /* addr */ + CDCACM_EPINBULK_ATTR, /* attr */ + { + LSBYTE(CONFIG_CDCACM_EPBULKIN_FSSIZE), /* maxpacket (full speed) */ + MSBYTE(CONFIG_CDCACM_EPBULKIN_FSSIZE) + }, + 1 /* interval */ +}; + +/* The components of the the configuration descriptor are maintained as + * a collection of separate descriptor structure coordinated by the + * following array. These descriptors could have been combined into + * one larger "super" configuration descriptor structure. However, I + * have concerns about compiler-dependent alignment and packing. Since + * the individual structures consist only of byte types, alignment and + * packing is not an issue. And since the are concatentated at run time + * instead of compile time, there should no issues there either. + */ + +static const struct cfgdecsc_group_s g_cfggroup[CDCACM_CFGGROUP_SIZE] = +{ + /* Configuration Descriptor. If the serial device is used in as part + * or a composite device, then the configuration descriptor is + * provided by the composite device logic. + */ + +#if !defined(CONFIG_CDCACM_COMPOSITE) + { + USB_SIZEOF_CFGDESC, /* 1. Configuration descriptor */ + 0, + (FAR void *)&g_cfgdesc + }, + + /* If the serial device is part of a composite device, then it should + * begin with an interface association descriptor (IAD) because the + * CDC/ACM device consists of more than one interface. The IAD associates + * the two CDC/ACM interfaces with the same CDC/ACM device. + */ + +#elif defined(CONFIG_COMPOSITE_IAD) + { + USB_SIZEOF_IADDESC, /* 1. Interface association descriptor */ + 0, + (FAR void *)&g_iaddesc + }, +#endif + { + USB_SIZEOF_IFDESC, /* 2. Notification interface */ + 0, + (FAR void *)&g_notifdesc + }, + { + SIZEOF_HDR_FUNCDESC, /* 3. Header functional descriptor */ + 0, + (FAR void *)&g_funchdr + }, + { + SIZEOF_ACM_FUNCDESC, /* 4. ACM functional descriptor */ + 0, + (FAR void *)&g_acmfunc + }, + { + SIZEOF_UNION_FUNCDESC(1), /* 5. Union functional descriptor */ + 0, + (FAR void *)&g_unionfunc + }, + { + USB_SIZEOF_EPDESC, /* 6. Interrupt IN endpoint descriptor */ + CONFIG_CDCACM_EPINTIN_HSSIZE, + (FAR void *)&g_epintindesc + }, + { + USB_SIZEOF_IFDESC, /* 7. Data interface descriptor */ + 0, + (FAR void *)&g_dataifdesc + }, + { + USB_SIZEOF_EPDESC, /* 8. Bulk OUT endpoint descriptor */ + CONFIG_CDCACM_EPBULKOUT_HSSIZE, + (FAR void *)&g_epbulkoutdesc + }, + { + USB_SIZEOF_EPDESC, /* 9. Bulk OUT endpoint descriptor */ + CONFIG_CDCACM_EPBULKIN_HSSIZE, + (FAR void *)&g_epbulkindesc + } +}; + +#if !defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED) +static const struct usb_qualdesc_s g_qualdesc = +{ + USB_SIZEOF_QUALDESC, /* len */ + USB_DESC_TYPE_DEVICEQUALIFIER, /* type */ + { /* usb */ + LSBYTE(0x0200), + MSBYTE(0x0200) + }, + USB_CLASS_VENDOR_SPEC, /* class */ + 0, /* subclass */ + 0, /* protocol */ + CONFIG_CDCACM_EP0MAXPACKET, /* mxpacketsize */ + CDCACM_NCONFIGS, /* nconfigs */ + 0, /* reserved */ +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cdcacm_mkstrdesc + * + * Description: + * Construct a string descriptor + * + ****************************************************************************/ + +int cdcacm_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc) +{ +#if !defined(CONFIG_CDCACM_COMPOSITE) || defined(CONFIG_CDCACM_NOTIFSTR) || \ + defined(CONFIG_CDCACM_DATAIFSTR) + + const char *str; + int len; + int ndata; + int i; + + switch (id) + { +#ifndef CONFIG_CDCACM_COMPOSITE + case 0: + { + /* Descriptor 0 is the language id */ + + strdesc->len = 4; + strdesc->type = USB_DESC_TYPE_STRING; + strdesc->data[0] = LSBYTE(CDCACM_STR_LANGUAGE); + strdesc->data[1] = MSBYTE(CDCACM_STR_LANGUAGE); + return 4; + } + + case CDCACM_MANUFACTURERSTRID: + str = CONFIG_CDCACM_VENDORSTR; + break; + + case CDCACM_PRODUCTSTRID: + str = CONFIG_CDCACM_PRODUCTSTR; + break; + + case CDCACM_SERIALSTRID: + str = CONFIG_CDCACM_SERIALSTR; + break; + + case CDCACM_CONFIGSTRID: + str = CONFIG_CDCACM_CONFIGSTR; + break; +#endif + +#ifdef CONFIG_CDCACM_NOTIFSTR + case CDCACM_NOTIFSTRID: + str = CONFIG_CDCACM_NOTIFSTR; + break; +#endif + +#ifdef CONFIG_CDCACM_DATAIFSTR + case CDCACM_DATAIFSTRID: + str = CONFIG_CDCACM_DATAIFSTR; + break; +#endif + + default: + return -EINVAL; + } + + /* The string is utf16-le. The poor man's utf-8 to utf16-le + * conversion below will only handle 7-bit en-us ascii + */ + + len = strlen(str); + for (i = 0, ndata = 0; i < len; i++, ndata += 2) + { + strdesc->data[ndata] = str[i]; + strdesc->data[ndata+1] = 0; + } + + strdesc->len = ndata+2; + strdesc->type = USB_DESC_TYPE_STRING; + return strdesc->len; +#else + return -EINVAL; +#endif +} + +/**************************************************************************** + * Name: cdcacm_getepdesc + * + * Description: + * Return a pointer to the raw device descriptor + * + ****************************************************************************/ + +#ifndef CONFIG_CDCACM_COMPOSITE +FAR const struct usb_devdesc_s *cdcacm_getdevdesc(void) +{ + return &g_devdesc; +} +#endif + +/**************************************************************************** + * Name: cdcacm_getepdesc + * + * Description: + * Return a pointer to the raw endpoint struct (used for configuring + * endpoints) + * + ****************************************************************************/ + +FAR const struct usb_epdesc_s *cdcacm_getepdesc(enum cdcacm_epdesc_e epid) +{ + switch (epid) + { + case CDCACM_EPINTIN: /* Interrupt IN endpoint */ + return &g_epintindesc; + + case CDCACM_EPBULKOUT: /* Bulk OUT endpoint */ + return &g_epbulkoutdesc; + + case CDCACM_EPBULKIN: /* Bulk IN endpoint */ + return &g_epbulkindesc; + + default: + return NULL; + } +} + +/**************************************************************************** + * Name: cdcacm_mkepdesc + * + * Description: + * Construct the endpoint descriptor using the correct max packet size. + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +void cdcacm_mkepdesc(num cdcacm_epdesc_e epid, uint16_t mxpacket, + FAR struct usb_epdesc_s *outdesc) +{ + FAR const struct usb_epdesc_s *indesc; + + /* Copy the "canned" descriptor */ + + indesc = cdcacm_getepdesc(epid) + memcpy(outdesc, indesc, USB_SIZEOF_EPDESC); + + /* Then add the correct max packet size */ + + outdesc->mxpacketsize[0] = LSBYTE(mxpacket); + outdesc->mxpacketsize[1] = MSBYTE(mxpacket); +} +#endif + +/**************************************************************************** + * Name: cdcacm_mkcfgdesc + * + * Description: + * Construct the configuration descriptor + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf, uint8_t speed, uint8_t type) +#else +int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf) +#endif +{ + FAR const struct cfgdecsc_group_s *group; + FAR uint8_t *dest = buf; + int i; + +#ifdef CONFIG_USBDEV_DUALSPEED + bool hispeed = (speed == USB_SPEED_HIGH); + + /* Check for switches between high and full speed */ + + if (type == USB_DESC_TYPE_OTHERSPEEDCONFIG) + { + hispeed = !hispeed; + } +#endif + + /* Copy all of the descriptors in the group */ + + for (i = 0, dest = buf; i < CDCACM_CFGGROUP_SIZE; i++) + { + group = &g_cfggroup[i]; + + /* The "canned" descriptors all have full speed endpoint maxpacket + * sizes. If high speed is selected, we will have to change the + * endpoint maxpacket size. + * + * Is there a alternative high speed maxpacket size in the table? + * If so, that is sufficient proof that the descriptor that we + * just copied is an endpoint descriptor and needs the fixup + */ + +#ifdef CONFIG_USBDEV_DUALSPEED + if (highspeed && group->hsepsize != 0) + { + cdcacm_mkepdesc(group->desc, group->hsepsize, + (FAR struct usb_epdesc_s*)dest); + } + else +#endif + /* Copy the "canned" descriptor with the full speed max packet + * size + */ + + { + memcpy(dest, group->desc, group->descsize); + } + + /* Advance to the destination location for the next descriptor */ + + dest += group->descsize; + } + + return SIZEOF_CDCACM_CFGDESC; +} + +/**************************************************************************** + * Name: cdcacm_getqualdesc + * + * Description: + * Return a pointer to the raw qual descriptor + * + ****************************************************************************/ + +#if !defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED) +FAR const struct usb_qualdesc_s *cdcacm_getqualdesc(void) +{ + return &g_qualdesc; +} +#endif diff --git a/nuttx/drivers/usbdev/composite.c b/nuttx/drivers/usbdev/composite.c new file mode 100644 index 0000000000..4cad8af864 --- /dev/null +++ b/nuttx/drivers/usbdev/composite.c @@ -0,0 +1,933 @@ +/**************************************************************************** + * drivers/usbdev/composite.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "composite.h" + +#ifdef CONFIG_USBDEV_COMPOSITE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure describes the internal state of the driver */ + +struct composite_dev_s +{ + FAR struct usbdev_s *usbdev; /* usbdev driver pointer */ + uint8_t config; /* Configuration number */ + FAR struct usbdev_req_s *ctrlreq; /* Allocated control request */ + struct usbdevclass_driver_s *dev1; /* Device 1 class object */ + struct usbdevclass_driver_s *dev2; /* Device 2 class object */ +}; + +/* The internal version of the class driver */ + +struct composite_driver_s +{ + struct usbdevclass_driver_s drvr; + FAR struct composite_dev_s *dev; +}; + +/* This is what is allocated */ + +struct composite_alloc_s +{ + struct composite_dev_s dev; + struct composite_driver_s drvr; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* USB helps ****************************************************************/ + +static void composite_ep0incomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); +static int composite_classsetup(FAR struct composite_dev_s *priv, + FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, + size_t outlen); +static struct usbdev_req_s *composite_allocreq(FAR struct usbdev_ep_s *ep, + uint16_t len); +static void composite_freereq(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); + +/* USB class device ********************************************************/ + +static int composite_bind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); +static void composite_unbind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); +static int composite_setup(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, + size_t outlen); +static void composite_disconnect(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); +static void composite_suspend(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); +static void composite_resume(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* USB class device *********************************************************/ + +static const struct usbdevclass_driverops_s g_driverops = +{ + composite_bind, /* bind */ + composite_unbind, /* unbind */ + composite_setup, /* setup */ + composite_disconnect, /* disconnect */ + composite_suspend, /* suspend */ + composite_resume, /* resume */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const char g_compvendorstr[] = CONFIG_COMPOSITE_VENDORSTR; +const char g_compproductstr[] = CONFIG_COMPOSITE_PRODUCTSTR; +const char g_compserialstr[] = CONFIG_COMPOSITE_SERIALSTR; + + /**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Helpers + ****************************************************************************/ + +/**************************************************************************** + * Name: composite_ep0incomplete + * + * Description: + * Handle completion of the composite driver's EP0 control operations + * + ****************************************************************************/ + +static void composite_ep0incomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req) +{ + /* Just check the result of the transfer */ + + if (req->result || req->xfrd != req->len) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_REQRESULT), (uint16_t)-req->result); + } +} + +/**************************************************************************** + * Name: composite_classsetup + * + * Description: + * Forward a setup command to the appropriate component device + * + ****************************************************************************/ + +static int composite_classsetup(FAR struct composite_dev_s *priv, + FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, + FAR uint8_t *dataout, size_t outlen) +{ + uint16_t index; + uint8_t interface; + int ret = -EOPNOTSUPP; + + index = GETUINT16(ctrl->index); + interface = (uint8_t)(index & 0xff); + + if (interface >= DEV1_FIRSTINTERFACE && interface < (DEV1_FIRSTINTERFACE + DEV1_NINTERFACES)) + { + ret = CLASS_SETUP(priv->dev1, dev, ctrl, dataout, outlen); + } + else if (interface >= DEV2_FIRSTINTERFACE && interface < (DEV2_FIRSTINTERFACE + DEV2_NINTERFACES)) + { + ret = CLASS_SETUP(priv->dev2, dev, ctrl, dataout, outlen); + } + + return ret; +} + +/**************************************************************************** + * Name: composite_allocreq + * + * Description: + * Allocate a request instance along with its buffer + * + ****************************************************************************/ + +static struct usbdev_req_s *composite_allocreq(FAR struct usbdev_ep_s *ep, + uint16_t len) +{ + FAR struct usbdev_req_s *req; + + req = EP_ALLOCREQ(ep); + if (req != NULL) + { + req->len = len; + req->buf = EP_ALLOCBUFFER(ep, len); + if (!req->buf) + { + EP_FREEREQ(ep, req); + req = NULL; + } + } + return req; +} + +/**************************************************************************** + * Name: composite_freereq + * + * Description: + * Free a request instance along with its buffer + * + ****************************************************************************/ + +static void composite_freereq(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req) +{ + if (ep != NULL && req != NULL) + { + if (req->buf != NULL) + { + EP_FREEBUFFER(ep, req->buf); + } + EP_FREEREQ(ep, req); + } +} + +/**************************************************************************** + * USB Class Driver Methods + ****************************************************************************/ + +/**************************************************************************** + * Name: composite_bind + * + * Description: + * Invoked when the driver is bound to a USB device driver + * + ****************************************************************************/ + +static int composite_bind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct composite_dev_s *priv = ((FAR struct composite_driver_s*)driver)->dev; + int ret; + + usbtrace(TRACE_CLASSBIND, 0); + + /* Bind the structures */ + + priv->usbdev = dev; + + /* Save the reference to our private data structure in EP0 so that it + * can be recovered in ep0 completion events. + */ + + dev->ep0->priv = priv; + + /* Preallocate one control request */ + + priv->ctrlreq = composite_allocreq(dev->ep0, COMPOSITE_CFGDESCSIZE); + if (priv->ctrlreq == NULL) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_ALLOCCTRLREQ), 0); + ret = -ENOMEM; + goto errout; + } + + /* Initialize the pre-allocated control request */ + + priv->ctrlreq->callback = composite_ep0incomplete; + + /* Then bind each of the constituent class drivers */ + + ret = CLASS_BIND(priv->dev1, dev); + if (ret < 0) + { + goto errout; + } + + ret = CLASS_BIND(priv->dev2, dev); + if (ret < 0) + { + goto errout; + } + + /* Report if we are selfpowered */ + +#ifdef CONFIG_USBDEV_SELFPOWERED + DEV_SETSELFPOWERED(dev); +#endif + + /* And pull-up the data line for the soft connect function */ + + DEV_CONNECT(dev); + return OK; + +errout: + composite_unbind(driver, dev); + return ret; +} + +/**************************************************************************** + * Name: composite_unbind + * + * Description: + * Invoked when the driver is unbound from a USB device driver + * + ****************************************************************************/ + +static void composite_unbind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct composite_dev_s *priv; + irqstate_t flags; + + usbtrace(TRACE_CLASSUNBIND, 0); + +#ifdef CONFIG_DEBUG + if (!driver || !dev || !dev->ep0) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = ((FAR struct composite_driver_s*)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0); + return; + } +#endif + + /* Make sure that we are not already unbound */ + + if (priv != NULL) + { + /* Unbind the constituent class drivers */ + + flags = irqsave(); + CLASS_UNBIND(priv->dev1, dev); + CLASS_UNBIND(priv->dev2, dev); + + /* Free the pre-allocated control request */ + + priv->config = COMPOSITE_CONFIGIDNONE; + if (priv->ctrlreq != NULL) + { + composite_freereq(dev->ep0, priv->ctrlreq); + priv->ctrlreq = NULL; + } + irqrestore(flags); + } +} + +/**************************************************************************** + * Name: composite_setup + * + * Description: + * Invoked for ep0 control requests. This function probably executes + * in the context of an interrupt handler. + * + ****************************************************************************/ + +static int composite_setup(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, + FAR uint8_t *dataout, size_t outlen) +{ + FAR struct composite_dev_s *priv; + FAR struct usbdev_req_s *ctrlreq; + uint16_t value; + uint16_t index; + uint16_t len; + bool dispatched = false; + int ret = -EOPNOTSUPP; + +#ifdef CONFIG_DEBUG + if (!driver || !dev || !dev->ep0 || !ctrl) + { + usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_SETUPINVALIDARGS), 0); + return -EIO; + } +#endif + + /* Extract a reference to private data */ + + usbtrace(TRACE_CLASSSETUP, ctrl->req); + priv = ((FAR struct composite_driver_s*)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv) + { + usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_EP0NOTBOUND2), 0); + return -ENODEV; + } +#endif + ctrlreq = priv->ctrlreq; + + /* Extract the little-endian 16-bit values to host order */ + + value = GETUINT16(ctrl->value); + index = GETUINT16(ctrl->index); + len = GETUINT16(ctrl->len); + + uvdbg("type=%02x req=%02x value=%04x index=%04x len=%04x\n", + ctrl->type, ctrl->req, value, index, len); + + if ((ctrl->type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) + { + /********************************************************************** + * Standard Requests + **********************************************************************/ + + switch (ctrl->req) + { + case USB_REQ_GETDESCRIPTOR: + { + /* The value field specifies the descriptor type in the MS byte and the + * descriptor index in the LS byte (order is little endian) + */ + + switch (ctrl->value[1]) + { + case USB_DESC_TYPE_DEVICE: + { + ret = USB_SIZEOF_DEVDESC; + memcpy(ctrlreq->buf, composite_getdevdesc(), ret); + } + break; + +#ifdef CONFIG_USBDEV_DUALSPEED + case USB_DESC_TYPE_DEVICEQUALIFIER: + { + ret = USB_SIZEOF_QUALDESC; + memcpy(ctrlreq->buf, composite_getqualdesc(), ret); + } + break; + + case USB_DESC_TYPE_OTHERSPEEDCONFIG: +#endif + + case USB_DESC_TYPE_CONFIG: + { +#ifdef CONFIG_USBDEV_DUALSPEED + ret = composite_mkcfgdesc(ctrlreq->buf, dev->speed, + ctrl->value[1]); +#else + ret = composite_mkcfgdesc(ctrlreq->buf); +#endif + } + break; + + case USB_DESC_TYPE_STRING: + { + /* value == string index. Zero is the language ID. */ + + uint8_t strid = ctrl->value[0]; + FAR struct usb_strdesc_s *buf = (FAR struct usb_strdesc_s *)ctrlreq->buf; + + if (strid <= COMPOSITE_NSTRIDS) + { + ret = composite_mkstrdesc(strid, buf); + } +#if DEV1_NSTRIDS > 0 + else if (strid <= DEV1_STRIDBASE + DEV1_NSTRIDS) + { + ret = DEV1_MKSTRDESC(strid, buf); + } +#endif +#if DEV2_NSTRIDS > 0 + else if (strid <= DEV2_STRIDBASE + DEV2_NSTRIDS) + { + ret = DEV2_MKSTRDESC(strid, buf); + } +#endif + } + break; + + default: + { + usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_GETUNKNOWNDESC), value); + } + break; + } + } + break; + + case USB_REQ_SETCONFIGURATION: + { + if (ctrl->type == 0) + { + /* Save the configuration and inform the constituent classes */ + + ret = CLASS_SETUP(priv->dev1, dev, ctrl); + dispatched = true; + + if (ret >= 0) + { + ret = CLASS_SETUP(priv->dev2, dev, ctrl); + if (ret >= 0) + { + priv->config = value; + } + } + } + } + break; + + case USB_REQ_GETCONFIGURATION: + { + if (ctrl->type == USB_DIR_IN) + { + ctrlreq->buf[0] = priv->config; + ret = 1; + } + } + break; + + case USB_REQ_SETINTERFACE: + { + if (ctrl->type == USB_REQ_RECIPIENT_INTERFACE && + priv->config == COMPOSITE_CONFIGID) + { + ret = composite_classsetup(priv, dev, ctrl, dataout, outlen); + dispatched = true; + } + } + break; + + case USB_REQ_GETINTERFACE: + { + if (ctrl->type == (USB_DIR_IN|USB_REQ_RECIPIENT_INTERFACE) && + priv->config == COMPOSITE_CONFIGIDNONE) + { + ret = composite_classsetup(priv, dev, ctrl, dataout, outlen); + dispatched = true; + } + } + break; + + default: + usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_UNSUPPORTEDSTDREQ), ctrl->req); + break; + } + } + else + { + uint8_t recipient; + + /********************************************************************** + * Non-Standard Class Requests + **********************************************************************/ + + /* Class implementations should handle there own interface and endpoint + * requests. + */ + + recipient = ctrl->type & USB_REQ_RECIPIENT_MASK; + if (recipient == USB_REQ_RECIPIENT_INTERFACE || recipient == USB_REQ_RECIPIENT_ENDPOINT) + { + ret = composite_classsetup(priv, dev, ctrl, dataout, outlen); + dispatched = true; + } + } + + + /* Respond to the setup command if (1) data was returned, and (2) the request was + * NOT successfully dispatched to the component class driver. On an error return + * value (ret < 0), the USB driver will stall EP0. + */ + + if (ret >= 0 && !dispatched) + { + /* Setup the request */ + + ctrlreq->len = MIN(len, ret); + ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT; + + /* And submit the request to the USB controller driver */ + + ret = EP_SUBMIT(dev->ep0, ctrlreq); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_EPRESPQ), (uint16_t)-ret); + ctrlreq->result = OK; + composite_ep0incomplete(dev->ep0, ctrlreq); + } + } + + return ret; +} + +/**************************************************************************** + * Name: composite_disconnect + * + * Description: + * Invoked after all transfers have been stopped, when the host is + * disconnected. This function is probably called from the context of an + * interrupt handler. + * + ****************************************************************************/ + +static void composite_disconnect(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct composite_dev_s *priv; + irqstate_t flags; + + usbtrace(TRACE_CLASSDISCONNECT, 0); + +#ifdef CONFIG_DEBUG + if (!driver || !dev) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = ((FAR struct composite_driver_s*)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0); + return; + } +#endif + + /* Reset the configuration and inform the constituent class drivers of + * the disconnection. + */ + + flags = irqsave(); + priv->config = COMPOSITE_CONFIGIDNONE; + CLASS_DISCONNECT(priv->dev1, dev); + CLASS_DISCONNECT(priv->dev2, dev); + irqrestore(flags); + + /* Perform the soft connect function so that we will we can be + * re-enumerated. + */ + + DEV_CONNECT(dev); +} + +/**************************************************************************** + * Name: composite_suspend + * + * Description: + * Invoked on a USB suspend event. + * + ****************************************************************************/ + +static void composite_suspend(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct composite_dev_s *priv; + irqstate_t flags; + + usbtrace(TRACE_CLASSSUSPEND, 0); + +#ifdef CONFIG_DEBUG + if (!dev) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = ((FAR struct composite_driver_s*)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0); + return; + } +#endif + + /* Forward the suspend event to the constituent devices */ + + flags = irqsave(); + CLASS_SUSPEND(priv->dev1, priv->usbdev); + CLASS_SUSPEND(priv->dev2, priv->usbdev); + irqrestore(flags); +} + +/**************************************************************************** + * Name: composite_resume + * + * Description: + * Invoked on a USB resume event. + * + ****************************************************************************/ + +static void composite_resume(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct composite_dev_s *priv = NULL; + irqstate_t flags; + +#ifdef CONFIG_DEBUG + if (!dev) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = ((FAR struct composite_driver_s*)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0); + return; + } +#endif + + /* Forward the resume event to the constituent devices */ + + flags = irqsave(); + CLASS_RESUME(priv->dev1, priv->usbdev); + CLASS_RESUME(priv->dev2, priv->usbdev); + irqrestore(flags); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: composite_initialize + * + * Description: + * Register USB composite device as configured. This function will call + * board-specific implementations in order to obtain the class objects for + * each of the members of the composite (see board_mscclassobject(), + * board_cdcclassobjec(), ...) + * + * Input Parameter: + * None + * + * Returned Value: + * A non-NULL "handle" is returned on success. This handle may be used + * later with composite_uninitialize() in order to removed the composite + * device. This handle is the (untyped) internal representation of the + * the class driver instance. + * + * NULL is returned on any failure. + * + ****************************************************************************/ + +FAR void *composite_initialize(void) +{ + FAR struct composite_alloc_s *alloc; + FAR struct composite_dev_s *priv; + FAR struct composite_driver_s *drvr; + int ret; + + /* Allocate the structures needed */ + + alloc = (FAR struct composite_alloc_s*)kmalloc(sizeof(struct composite_alloc_s)); + if (!alloc) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_ALLOCDEVSTRUCT), 0); + return NULL; + } + + /* Convenience pointers into the allocated blob */ + + priv = &alloc->dev; + drvr = &alloc->drvr; + + /* Initialize the USB composite driver structure */ + + memset(priv, 0, sizeof(struct composite_dev_s)); + + /* Get the constitueat class driver objects */ + + ret = DEV1_CLASSOBJECT(&priv->dev1); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_CLASSOBJECT), (uint16_t)-ret); + goto errout_with_alloc; + } + + ret = DEV2_CLASSOBJECT(&priv->dev2); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_CLASSOBJECT), (uint16_t)-ret); + goto errout_with_alloc; + } + + /* Initialize the USB class driver structure */ + +#ifdef CONFIG_USBDEV_DUALSPEED + drvr->drvr.speed = USB_SPEED_HIGH; +#else + drvr->drvr.speed = USB_SPEED_FULL; +#endif + drvr->drvr.ops = &g_driverops; + drvr->dev = priv; + + /* Register the USB composite class driver */ + + ret = usbdev_register(&drvr->drvr); + if (ret) + { + usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_DEVREGISTER), (uint16_t)-ret); + goto errout_with_alloc; + } + + return (FAR void *)alloc; + +errout_with_alloc: + kfree(alloc); + return NULL; +} + +/**************************************************************************** + * Name: composite_uninitialize + * + * Description: + * Un-initialize the USB composite driver. The handle is the USB composite + * class' device object as was returned by composite_initialize(). This + * function will call board-specific implementations in order to free the + * class objects for each of the members of the composite (see + * board_mscuninitialize(), board_cdcuninitialize(), ...) + * + * Input Parameters: + * handle - The handle returned by a previous call to composite_initialize(). + * + * Returned Value: + * None + * + ***************************************************************************/ + +void composite_uninitialize(FAR void *handle) +{ + FAR struct composite_alloc_s *alloc = (FAR struct composite_alloc_s *)handle; + FAR struct composite_dev_s *priv; + + DEBUGASSERT(alloc != NULL); + + /* Uninitialize each of the member classes */ + + priv = &alloc->dev; + if (priv->dev1) + { + DEV1_UNINITIALIZE(priv->dev1); + priv->dev1 = NULL; + } + + if (priv->dev2) + { + DEV1_UNINITIALIZE(priv->dev2); + priv->dev2 = NULL; + } + + /* Then unregister and destroy the composite class */ + + usbdev_unregister(&alloc->drvr.drvr); + + /* Free any resources used by the composite driver */ + /* None */ + + /* Then free the composite driver state structure itself */ + + kfree(priv); +} + +/**************************************************************************** + * Name: composite_ep0submit + * + * Description: + * Members of the composite cannot send on EP0 directly because EP0 is + * is "owned" by the composite device. Instead, when configured as members + * of a composite device, those classes should call this method so that + * the composite device can send on EP0 onbehalf of the class. + * + ****************************************************************************/ + +int composite_ep0submit(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev, + FAR struct usbdev_req_s *ctrlreq) +{ + /* This function is not really necessary in the current design. However, + * keeping this will provide us a little flexibility in the future if + * it becomes necessary to manage the completion callbacks. + */ + + return EP_SUBMIT(dev->ep0, ctrlreq); +} + +#endif /* CONFIG_USBDEV_COMPOSITE */ diff --git a/nuttx/drivers/usbdev/composite.h b/nuttx/drivers/usbdev/composite.h new file mode 100644 index 0000000000..0c022427c5 --- /dev/null +++ b/nuttx/drivers/usbdev/composite.h @@ -0,0 +1,326 @@ +/**************************************************************************** + * drivers/usbdev/composite.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_USBDEV_COMPOSITE_H +#define __DRIVERS_USBDEV_COMPOSITE_H 1 + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#ifdef CONFIG_USBDEV_COMPOSITE + +#ifdef CONFIG_CDCACM_COMPOSITE +# include +# include "cdcacm.h" +#endif + +#ifdef CONFIG_USBMSC_COMPOSITE +# include "usbmsc.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* Packet sizes */ + +#ifndef CONFIG_COMPOSITE_EP0MAXPACKET +# define CONFIG_COMPOSITE_EP0MAXPACKET 64 +#endif + +/* Vendor and product IDs and strings */ + +#ifndef CONFIG_COMPOSITE_COMPOSITE +# ifndef CONFIG_COMPOSITE_VENDORID +# warning "CONFIG_COMPOSITE_VENDORID not defined" +# define CONFIG_COMPOSITE_VENDORID 0x03eb +# endif + +# ifndef CONFIG_COMPOSITE_PRODUCTID +# warning "CONFIG_COMPOSITE_PRODUCTID not defined" +# define CONFIG_COMPOSITE_PRODUCTID 0x2022 +# endif + +# ifndef CONFIG_COMPOSITE_VERSIONNO +# define CONFIG_COMPOSITE_VERSIONNO (0x0101) +# endif + +# ifndef CONFIG_COMPOSITE_VENDORSTR +# warning "No Vendor string specified" +# define CONFIG_COMPOSITE_VENDORSTR "NuttX" +# endif + +# ifndef CONFIG_COMPOSITE_PRODUCTSTR +# warning "No Product string specified" +# define CONFIG_COMPOSITE_PRODUCTSTR "Composite Device" +# endif + +# undef CONFIG_COMPOSITE_SERIALSTR +# define CONFIG_COMPOSITE_SERIALSTR "0101" +#endif + +#undef CONFIG_COMPOSITE_CONFIGSTR +#define CONFIG_COMPOSITE_CONFIGSTR "Composite" + +/* Constituent devices ******************************************************/ + +#undef DEV1_IS_CDCACM +#undef DEV1_IS_USBMSC + +#undef DEV2_IS_CDCACM +#undef DEV2_IS_USBMSC + +/* Pick the first device in the composite. At present, this may only be + * the CDC serial device or the mass storage device. + */ + +#if defined(CONFIG_CDCACM_COMPOSITE) +# define DEV1_IS_CDCACM 1 +# define DEV1_MKCFGDESC cdcacm_mkcfgdesc +# define DEV1_MKSTRDESC cdcacm_mkstrdesc +# define DEV1_CLASSOBJECT board_cdcclassobject +# define DEV1_UNINITIALIZE board_cdcuninitialize +# define DEV1_NCONFIGS CDCACM_NCONFIGS +# define DEV1_CONFIGID CDCACM_CONFIGID +# define DEV1_FIRSTINTERFACE CONFIG_CDCACM_IFNOBASE +# define DEV1_NINTERFACES CDCACM_NINTERFACES +# define DEV1_STRIDBASE CONFIG_CDCACM_STRBASE +# define DEV1_NSTRIDS CDCACM_NSTRIDS +# define DEV1_CFGDESCSIZE SIZEOF_CDCACM_CFGDESC +#elif defined(CONFIG_CDCACM_COMPOSITE) +# define DEV1_IS_USBMSC 1 +# define DEV1_MKCFGDESC usbmsc_mkcfgdesc +# define DEV1_MKSTRDESC usbmsc_mkstrdesc +# define DEV1_CLASSOBJECT board_mscclassobject +# define DEV1_UNINITIALIZE board_mscuninitialize +# define DEV1_NCONFIGS USBMSC_NCONFIGS +# define DEV1_CONFIGID USBMSC_CONFIGID +# define DEV1_FIRSTINTERFACE CONFIG_USBMSC_IFNOBASE +# define DEV1_NINTERFACES USBMSC_NINTERFACES +# define DEV1_STRIDBASE CONFIG_USBMSC_IFNOBASE +# define DEV1_NSTRIDS USBMSC_NSTRIDS +# define DEV1_CFGDESCSIZE SIZEOF_USBMSC_CFGDESC +#else +# error "No members of the composite defined" +#endif + +/* Pick the second device in the composite. At present, this may only be + * the CDC serial device or the mass storage device. + */ + +#if defined(CONFIG_CDCACM_COMPOSITE) && !defined(DEV1_IS_CDCACM) +# define DEV2_IS_CDCACM 1 +# define DEV2_MKCFGDESC cdcacm_mkcfgdesc +# define DEV2_MKSTRDESC cdcacm_mkstrdesc +# define DEV2_CLASSOBJECT board_cdcclassobject +# define DEV2_UNINITIALIZE board_cdcuninitialize +# define DEV2_NCONFIGS CDCACM_NCONFIGS +# define DEV2_CONFIGID CDCACM_CONFIGID +# define DEV2_FIRSTINTERFACE CONFIG_CDCACM_IFNOBASE +# define DEV2_NINTERFACES CDCACM_NINTERFACES +# define DEV2_STRIDBASE CONFIG_CDCACM_STRBASE +# define DEV2_NSTRIDS CDCACM_NSTRIDS +# define DEV2_CFGDESCSIZE SIZEOF_CDCACM_CFGDESC +#elif defined(CONFIG_CDCACM_COMPOSITE) && !defined(DEV1_IS_USBMSC) +# define DEV2_IS_USBMSC 1 +# define DEV2_MKCFGDESC usbmsc_mkcfgdesc +# define DEV2_MKSTRDESC usbmsc_mkstrdesc +# define DEV2_UNINITIALIZE board_mscuninitialize +# define DEV2_CLASSOBJECT board_mscclassobject +# define DEV2_NCONFIGS USBMSC_NCONFIGS +# define DEV2_CONFIGID USBMSC_CONFIGID +# define DEV2_FIRSTINTERFACE CONFIG_USBMSC_IFNOBASE +# define DEV2_NINTERFACES USBMSC_NINTERFACES +# define DEV2_STRIDBASE CONFIG_USBMSC_STRBASE +# define DEV2_NSTRIDS USBMSC_NSTRIDS +# define DEV2_CFGDESCSIZE SIZEOF_USBMSC_CFGDESC +#else +# error "Insufficient members of the composite defined" +#endif + +/* Verify interface configuration */ + +#if DEV1_FIRSTINTERFACE != 0 +# warning "The first interface number should be zero" +#endif + +#if (DEV1_FIRSTINTERFACE + DEV1_NINTERFACES) != DEV2_FIRSTINTERFACE +# warning "Interface numbers are not contiguous" +#endif + +/* Check if an IAD is needed */ + +#ifdef CONFIG_COMPOSITE_IAD +# if DEV1_NINTERFACES == 1 && DEV2_NINTERFACES == 1 +# warning "CONFIG_COMPOSITE_IAD not needed" +# endif +#endif + +#if !defined(CONFIG_COMPOSITE_IAD) && DEV1_NINTERFACES > 1 && DEV2_NINTERFACES > 1 +# warning "CONFIG_COMPOSITE_IAD may be needed" +#endif + +/* Total size of the configuration descriptor: */ + +#define COMPOSITE_CFGDESCSIZE (USB_SIZEOF_CFGDESC + DEV1_CFGDESCSIZE + DEV2_CFGDESCSIZE) + +/* The total number of interfaces */ + +#define COMPOSITE_NINTERFACES (DEV1_NINTERFACES + DEV2_NINTERFACES) + +/* Composite configuration ID value */ + +#if DEV1_NCONFIGS != 1 || DEV1_CONFIGID != 1 +# error "DEV1: Only a single configuration is supported" +#endif + +#if DEV2_NCONFIGS != 1 || DEV2_CONFIGID != 1 +# error "DEV2: Only a single configuration is supported" +#endif + +/* Descriptors **************************************************************/ +/* These settings are not modifiable via the NuttX configuration */ + +#define COMPOSITE_CONFIGIDNONE (0) /* Config ID = 0 means to return to address mode */ +#define COMPOSITE_NCONFIGS (1) /* The number of configurations supported */ +#define COMPOSITE_CONFIGID (1) /* The only supported configuration ID */ + +/* String language */ + +#define COMPOSITE_STR_LANGUAGE (0x0409) /* en-us */ + +/* Descriptor strings */ + +#define COMPOSITE_MANUFACTURERSTRID (1) +#define COMPOSITE_PRODUCTSTRID (2) +#define COMPOSITE_SERIALSTRID (3) +#define COMPOSITE_CONFIGSTRID (4) +#define COMPOSITE_NSTRIDS (4) + +/* Verify string configuration */ + +#if COMPOSITE_NSTRIDS != DEV1_STRIDBASE +# warning "The DEV1 string base should be COMPOSITE_NSTRIDS" +#endif + +#if (DEV1_STRIDBASE + DEV1_NSTRIDS) != DEV2_STRIDBASE +# warning "String IDs are not contiguous" +#endif + +/* Everpresent MIN/MAX macros ***********************************************/ + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern const char g_compvendorstr[]; +extern const char g_compproductstr[]; +extern const char g_compserialstr[]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: composite_mkstrdesc + * + * Description: + * Construct a string descriptor + * + ****************************************************************************/ + +int composite_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc); + +/**************************************************************************** + * Name: composite_getepdesc + * + * Description: + * Return a pointer to the composite device descriptor + * + ****************************************************************************/ + +#ifndef CONFIG_COMPOSITE_COMPOSITE +FAR const struct usb_devdesc_s *composite_getdevdesc(void); +#endif + +/**************************************************************************** + * Name: composite_mkcfgdesc + * + * Description: + * Construct the composite configuration descriptor + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +int16_t composite_mkcfgdesc(uint8_t *buf, uint8_t speed, uint8_t type); +#else +int16_t composite_mkcfgdesc(uint8_t *buf); +#endif + +/**************************************************************************** + * Name: composite_getqualdesc + * + * Description: + * Return a pointer to the composite qual descriptor + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +FAR const struct usb_qualdesc_s *composite_getqualdesc(void); +#endif + +#endif /* CONFIG_USBDEV_COMPOSITE */ +#endif /* __DRIVERS_USBDEV_COMPOSITE_H */ diff --git a/nuttx/drivers/usbdev/composite_desc.c b/nuttx/drivers/usbdev/composite_desc.c new file mode 100644 index 0000000000..0a0cd4a6ad --- /dev/null +++ b/nuttx/drivers/usbdev/composite_desc.c @@ -0,0 +1,291 @@ +/**************************************************************************** + * drivers/usbdev/composite_desc.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include "composite.h" + +#ifdef CONFIG_USBDEV_COMPOSITE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +typedef int16_t (*mkcfgdesc)(FAR uint8_t *buf, uint8_t speed, uint8_t type); +#else +typedef int16_t (*mkcfgdesc)(FAR uint8_t *buf); +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* Device Descriptor */ + +static const struct usb_devdesc_s g_devdesc = +{ + USB_SIZEOF_DEVDESC, /* len */ + USB_DESC_TYPE_DEVICE, /* type */ + { /* usb */ + LSBYTE(0x0200), + MSBYTE(0x0200) + }, +#ifdef CONFIG_COMPOSITE_IAD + USB_CLASS_MISC, /* classid */ + 2, /* subclass */ + 1, /* protocol */ +#else + USB_CLASS_PER_INTERFACE, /* classid */ + 0, /* subclass */ + 0, /* protocol */ +#endif + CONFIG_COMPOSITE_EP0MAXPACKET, /* maxpacketsize */ + { + LSBYTE(CONFIG_COMPOSITE_VENDORID), /* vendor */ + MSBYTE(CONFIG_COMPOSITE_VENDORID) + }, + { + LSBYTE(CONFIG_COMPOSITE_PRODUCTID), /* product */ + MSBYTE(CONFIG_COMPOSITE_PRODUCTID) + }, + { + LSBYTE(CONFIG_COMPOSITE_VERSIONNO), /* device */ + MSBYTE(CONFIG_COMPOSITE_VERSIONNO) + }, + COMPOSITE_MANUFACTURERSTRID, /* imfgr */ + COMPOSITE_PRODUCTSTRID, /* iproduct */ + COMPOSITE_SERIALSTRID, /* serno */ + COMPOSITE_NCONFIGS /* nconfigs */ +}; + +/* Configuration descriptor for the composite device */ + +static const struct usb_cfgdesc_s g_cfgdesc = +{ + USB_SIZEOF_CFGDESC, /* len */ + USB_DESC_TYPE_CONFIG, /* type */ + { + LSBYTE(COMPOSITE_CFGDESCSIZE), /* LS totallen */ + MSBYTE(COMPOSITE_CFGDESCSIZE) /* MS totallen */ + }, + COMPOSITE_NINTERFACES, /* ninterfaces */ + COMPOSITE_CONFIGID, /* cfgvalue */ + COMPOSITE_CONFIGSTRID, /* icfg */ + USB_CONFIG_ATTR_ONE|SELFPOWERED|REMOTEWAKEUP, /* attr */ + (CONFIG_USBDEV_MAXPOWER + 1) / 2 /* mxpower */ +}; + +#ifdef CONFIG_USBDEV_DUALSPEED +static const struct usb_qualdesc_s g_qualdesc = +{ + USB_SIZEOF_QUALDESC, /* len */ + USB_DESC_TYPE_DEVICEQUALIFIER, /* type */ + { /* usb */ + LSBYTE(0x0200), + MSBYTE(0x0200) + }, + USB_CLASS_VENDOR_SPEC, /* classid */ + 0, /* subclass */ + 0, /* protocol */ + CONFIG_COMPOSITE_EP0MAXPACKET, /* mxpacketsize */ + COMPOSITE_NCONFIGS, /* nconfigs */ + 0, /* reserved */ +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: composite_mkstrdesc + * + * Description: + * Construct a string descriptor + * + ****************************************************************************/ + +int composite_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc) +{ + const char *str; + int len; + int ndata; + int i; + + switch (id) + { + case 0: + { + /* Descriptor 0 is the language id */ + + strdesc->len = 4; + strdesc->type = USB_DESC_TYPE_STRING; + strdesc->data[0] = LSBYTE(COMPOSITE_STR_LANGUAGE); + strdesc->data[1] = MSBYTE(COMPOSITE_STR_LANGUAGE); + return 4; + } + + case COMPOSITE_MANUFACTURERSTRID: + str = g_compvendorstr; + break; + + case COMPOSITE_PRODUCTSTRID: + str = g_compproductstr; + break; + + case COMPOSITE_SERIALSTRID: + str = g_compserialstr; + break; + + case COMPOSITE_CONFIGSTRID: + str = CONFIG_COMPOSITE_CONFIGSTR; + break; + + default: + return -EINVAL; + } + + /* The string is utf16-le. The poor man's utf-8 to utf16-le + * conversion below will only handle 7-bit en-us ascii + */ + + len = strlen(str); + for (i = 0, ndata = 0; i < len; i++, ndata += 2) + { + strdesc->data[ndata] = str[i]; + strdesc->data[ndata+1] = 0; + } + + strdesc->len = ndata+2; + strdesc->type = USB_DESC_TYPE_STRING; + return strdesc->len; +} + +/**************************************************************************** + * Name: composite_getepdesc + * + * Description: + * Return a pointer to the raw device descriptor + * + ****************************************************************************/ + +FAR const struct usb_devdesc_s *composite_getdevdesc(void) +{ + return &g_devdesc; +} + +/**************************************************************************** + * Name: composite_mkcfgdesc + * + * Description: + * Construct the configuration descriptor + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +int16_t composite_mkcfgdesc(uint8_t *buf, uint8_t speed, uint8_t type) +#else +int16_t composite_mkcfgdesc(uint8_t *buf) +#endif +{ + int16_t len; + int16_t total; + + /* Configuration descriptor -- Copy the canned configuration descriptor. */ + + memcpy(buf, &g_cfgdesc, USB_SIZEOF_CFGDESC); + total = USB_SIZEOF_CFGDESC; + buf += USB_SIZEOF_CFGDESC; + + /* Copy DEV1/DEV2 interface descriptors */ + +#ifdef CONFIG_USBDEV_DUALSPEED + len = DEV1_MKCFGDESC(buf, speed, type); + total += len; + buf += len; + total += DEV2_MKCFGDESC(buf, speed, type); +#else + len = DEV1_MKCFGDESC(buf); + total += len; + buf += len; + total += DEV2_MKCFGDESC(buf); +#endif + + DEBUGASSERT(total == COMPOSITE_CFGDESCSIZE); + return total; +} + +/**************************************************************************** + * Name: composite_getqualdesc + * + * Description: + * Return a pointer to the raw qual descriptor + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +FAR const struct usb_qualdesc_s *composite_getqualdesc(void) +{ + return &g_qualdesc; +} +#endif + +#endif /* CONFIG_USBDEV_COMPOSITE */ diff --git a/nuttx/drivers/usbdev/pl2303.c b/nuttx/drivers/usbdev/pl2303.c new file mode 100644 index 0000000000..69bf879656 --- /dev/null +++ b/nuttx/drivers/usbdev/pl2303.c @@ -0,0 +1,2242 @@ +/**************************************************************************** + * drivers/usbdev/pl2303.c + * + * Copyright (C) 2008-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This logic emulates the Prolific PL2303 serial/USB converter + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Number of requests in the write queue */ + +#ifndef CONFIG_PL2303_NWRREQS +# define CONFIG_PL2303_NWRREQS 4 +#endif + +/* Number of requests in the read queue */ + +#ifndef CONFIG_PL2303_NRDREQS +# define CONFIG_PL2303_NRDREQS 4 +#endif + +/* Logical endpoint numbers / max packet sizes */ + +#ifndef CONFIG_PL2303_EPINTIN +# warning "EPINTIN not defined in the configuration" +# define CONFIG_PL2303_EPINTIN 1 +#endif + +#ifndef CONFIG_PL2303_EPBULKOUT +# warning "EPBULKOUT not defined in the configuration" +# define CONFIG_PL2303_EPBULKOUT 2 +#endif + +#ifndef CONFIG_PL2303_EPBULKIN +# warning "EPBULKIN not defined in the configuration" +# define CONFIG_PL2303_EPBULKIN 3 +#endif + +/* Packet and request buffer sizes */ + +#ifndef CONFIG_PL2303_EP0MAXPACKET +# define CONFIG_PL2303_EP0MAXPACKET 64 +#endif + +#undef CONFIG_PL2303_BULKREQLEN + +/* Vendor and product IDs and strings */ + +#ifndef CONFIG_PL2303_VENDORID +# define CONFIG_PL2303_VENDORID 0x067b +#endif + +#ifndef CONFIG_PL2303_PRODUCTID +# define CONFIG_PL2303_PRODUCTID 0x2303 +#endif + +#ifndef CONFIG_PL2303_VENDORSTR +# warning "No Vendor string specified" +# define CONFIG_PL2303_VENDORSTR "NuttX" +#endif + +#ifndef CONFIG_PL2303_PRODUCTSTR +# warning "No Product string specified" +# define CONFIG_PL2303_PRODUCTSTR "USBdev Serial" +#endif + +#undef CONFIG_PL2303_SERIALSTR +#define CONFIG_PL2303_SERIALSTR "0" + +#undef CONFIG_PL2303_CONFIGSTR +#define CONFIG_PL2303_CONFIGSTR "Bulk" + +/* USB Controller */ + +#ifndef CONFIG_USBDEV_SELFPOWERED +# define SELFPOWERED USB_CONFIG_ATT_SELFPOWER +#else +# define SELFPOWERED (0) +#endif + +#ifndef CONFIG_USBDEV_REMOTEWAKEUP +# define REMOTEWAKEUP USB_CONFIG_ATTR_WAKEUP +#else +# define REMOTEWAKEUP (0) +#endif + +#ifndef CONFIG_USBDEV_MAXPOWER +# define CONFIG_USBDEV_MAXPOWER 100 +#endif + +/* Descriptors ****************************************************************/ + +/* These settings are not modifiable via the NuttX configuration */ + +#define PL2303_VERSIONNO (0x0202) /* Device version number */ +#define PL2303_CONFIGIDNONE (0) /* Config ID means to return to address mode */ +#define PL2303_CONFIGID (1) /* The only supported configuration ID */ +#define PL2303_NCONFIGS (1) /* Number of configurations supported */ +#define PL2303_INTERFACEID (0) +#define PL2303_ALTINTERFACEID (0) +#define PL2303_NINTERFACES (1) /* Number of interfaces in the configuration */ +#define PL2303_NENDPOINTS (3) /* Number of endpoints in the interface */ + +/* Endpoint configuration */ + +#define PL2303_EPINTIN_ADDR (USB_DIR_IN|CONFIG_PL2303_EPINTIN) +#define PL2303_EPINTIN_ATTR (USB_EP_ATTR_XFER_INT) +#define PL2303_EPINTIN_MXPACKET (10) + +#define PL2303_EPOUTBULK_ADDR (CONFIG_PL2303_EPBULKOUT) +#define PL2303_EPOUTBULK_ATTR (USB_EP_ATTR_XFER_BULK) + +#define PL2303_EPINBULK_ADDR (USB_DIR_IN|CONFIG_PL2303_EPBULKIN) +#define PL2303_EPINBULK_ATTR (USB_EP_ATTR_XFER_BULK) + +/* String language */ + +#define PL2303_STR_LANGUAGE (0x0409) /* en-us */ + +/* Descriptor strings */ + +#define PL2303_MANUFACTURERSTRID (1) +#define PL2303_PRODUCTSTRID (2) +#define PL2303_SERIALSTRID (3) +#define PL2303_CONFIGSTRID (4) + +/* Buffer big enough for any of our descriptors */ + +#define PL2303_MXDESCLEN (64) + +/* Vender specific control requests *******************************************/ + +#define PL2303_CONTROL_TYPE (0x20) +#define PL2303_SETLINEREQUEST (0x20) /* OUT, Recipient interface */ +#define PL2303_GETLINEREQUEST (0x21) /* IN, Recipient interface */ +#define PL2303_SETCONTROLREQUEST (0x22) /* OUT, Recipient interface */ +#define PL2303_BREAKREQUEST (0x23) /* OUT, Recipient interface */ + +/* Vendor read/write */ + +#define PL2303_RWREQUEST_TYPE (0x40) +#define PL2303_RWREQUEST (0x01) /* IN/OUT, Recipient device */ + +/* Misc Macros ****************************************************************/ + +/* min/max macros */ + +#ifndef min +# define min(a,b) ((a)<(b)?(a):(b)) +#endif + +#ifndef max +# define max(a,b) ((a)>(b)?(a):(b)) +#endif + +/* Trace values *************************************************************/ + +#define PL2303_CLASSAPI_SETUP TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_SETUP) +#define PL2303_CLASSAPI_SHUTDOWN TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_SHUTDOWN) +#define PL2303_CLASSAPI_ATTACH TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_ATTACH) +#define PL2303_CLASSAPI_DETACH TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_DETACH) +#define PL2303_CLASSAPI_IOCTL TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_IOCTL) +#define PL2303_CLASSAPI_RECEIVE TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_RECEIVE) +#define PL2303_CLASSAPI_RXINT TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_RXINT) +#define PL2303_CLASSAPI_RXAVAILABLE TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_RXAVAILABLE) +#define PL2303_CLASSAPI_SEND TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_SEND) +#define PL2303_CLASSAPI_TXINT TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_TXINT) +#define PL2303_CLASSAPI_TXREADY TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_TXREADY) +#define PL2303_CLASSAPI_TXEMPTY TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_TXEMPTY) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Container to support a list of requests */ + +struct pl2303_req_s +{ + FAR struct pl2303_req_s *flink; /* Implements a singly linked list */ + FAR struct usbdev_req_s *req; /* The contained request */ +}; + +/* This structure describes the internal state of the driver */ + +struct pl2303_dev_s +{ + FAR struct uart_dev_s serdev; /* Serial device structure */ + FAR struct usbdev_s *usbdev; /* usbdev driver pointer */ + + uint8_t config; /* Configuration number */ + uint8_t nwrq; /* Number of queue write requests (in reqlist)*/ + uint8_t nrdq; /* Number of queue read requests (in epbulkout) */ + bool rxenabled; /* true: UART RX "interrupts" enabled */ + uint8_t linest[7]; /* Fake line status */ + int16_t rxhead; /* Working head; used when rx int disabled */ + + FAR struct usbdev_ep_s *epintin; /* Interrupt IN endpoint structure */ + FAR struct usbdev_ep_s *epbulkin; /* Bulk IN endpoint structure */ + FAR struct usbdev_ep_s *epbulkout; /* Bulk OUT endpoint structure */ + FAR struct usbdev_req_s *ctrlreq; /* Control request */ + struct sq_queue_s reqlist; /* List of write request containers */ + + /* Pre-allocated write request containers. The write requests will + * be linked in a free list (reqlist), and used to send requests to + * EPBULKIN; Read requests will be queued in the EBULKOUT. + */ + + struct pl2303_req_s wrreqs[CONFIG_PL2303_NWRREQS]; + struct pl2303_req_s rdreqs[CONFIG_PL2303_NWRREQS]; + + /* Serial I/O buffers */ + + char rxbuffer[CONFIG_PL2303_RXBUFSIZE]; + char txbuffer[CONFIG_PL2303_TXBUFSIZE]; +}; + +/* The internal version of the class driver */ + +struct pl2303_driver_s +{ + struct usbdevclass_driver_s drvr; + FAR struct pl2303_dev_s *dev; +}; + +/* This is what is allocated */ + +struct pl2303_alloc_s +{ + struct pl2303_dev_s dev; + struct pl2303_driver_s drvr; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Transfer helpers *********************************************************/ + +static uint16_t usbclass_fillrequest(FAR struct pl2303_dev_s *priv, + uint8_t *reqbuf, uint16_t reqlen); +static int usbclass_sndpacket(FAR struct pl2303_dev_s *priv); +static inline int usbclass_recvpacket(FAR struct pl2303_dev_s *priv, + uint8_t *reqbuf, uint16_t reqlen); + +/* Request helpers *********************************************************/ + +static struct usbdev_req_s *usbclass_allocreq(FAR struct usbdev_ep_s *ep, + uint16_t len); +static void usbclass_freereq(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); + +/* Configuration ***********************************************************/ + +static int usbclass_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc); +#ifdef CONFIG_USBDEV_DUALSPEED +static void usbclass_mkepbulkdesc(const struct usb_epdesc_s *indesc, + uint16_t mxpacket, struct usb_epdesc_s *outdesc); +static int16_t usbclass_mkcfgdesc(uint8_t *buf, uint8_t speed, uint8_t type); +#else +static int16_t usbclass_mkcfgdesc(uint8_t *buf); +#endif +static void usbclass_resetconfig(FAR struct pl2303_dev_s *priv); +static int usbclass_setconfig(FAR struct pl2303_dev_s *priv, + uint8_t config); + +/* Completion event handlers ***********************************************/ + +static void usbclass_ep0incomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); +static void usbclass_rdcomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); +static void usbclass_wrcomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); + +/* USB class device ********************************************************/ + +static int usbclass_bind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); +static void usbclass_unbind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); +static int usbclass_setup(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, + size_t outlen); +static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); + +/* Serial port *************************************************************/ + +static int usbser_setup(FAR struct uart_dev_s *dev); +static void usbser_shutdown(FAR struct uart_dev_s *dev); +static int usbser_attach(FAR struct uart_dev_s *dev); +static void usbser_detach(FAR struct uart_dev_s *dev); +static void usbser_rxint(FAR struct uart_dev_s *dev, bool enable); +static void usbser_txint(FAR struct uart_dev_s *dev, bool enable); +static bool usbser_txempty(FAR struct uart_dev_s *dev); + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/* USB class device ********************************************************/ + +static const struct usbdevclass_driverops_s g_driverops = +{ + usbclass_bind, /* bind */ + usbclass_unbind, /* unbind */ + usbclass_setup, /* setup */ + usbclass_disconnect, /* disconnect */ + NULL, /* suspend */ + NULL, /* resume */ +}; + +/* Serial port *************************************************************/ + +static const struct uart_ops_s g_uartops = +{ + usbser_setup, /* setup */ + usbser_shutdown, /* shutdown */ + usbser_attach, /* attach */ + usbser_detach, /* detach */ + NULL, /* ioctl */ + NULL, /* receive */ + usbser_rxint, /* rxinit */ + NULL, /* rxavailable */ + NULL, /* send */ + usbser_txint, /* txinit */ + NULL, /* txready */ + usbser_txempty /* txempty */ +}; + +/* USB descriptor templates these will be copied and modified **************/ + +static const struct usb_devdesc_s g_devdesc = +{ + USB_SIZEOF_DEVDESC, /* len */ + USB_DESC_TYPE_DEVICE, /* type */ + {LSBYTE(0x0200), MSBYTE(0x0200)}, /* usb */ + USB_CLASS_PER_INTERFACE, /* classid */ + 0, /* subclass */ + 0, /* protocol */ + CONFIG_PL2303_EP0MAXPACKET, /* maxpacketsize */ + { LSBYTE(CONFIG_PL2303_VENDORID), /* vendor */ + MSBYTE(CONFIG_PL2303_VENDORID) }, + { LSBYTE(CONFIG_PL2303_PRODUCTID), /* product */ + MSBYTE(CONFIG_PL2303_PRODUCTID) }, + { LSBYTE(PL2303_VERSIONNO), /* device */ + MSBYTE(PL2303_VERSIONNO) }, + PL2303_MANUFACTURERSTRID, /* imfgr */ + PL2303_PRODUCTSTRID, /* iproduct */ + PL2303_SERIALSTRID, /* serno */ + PL2303_NCONFIGS /* nconfigs */ +}; + +static const struct usb_cfgdesc_s g_cfgdesc = +{ + USB_SIZEOF_CFGDESC, /* len */ + USB_DESC_TYPE_CONFIG, /* type */ + {0, 0}, /* totallen -- to be provided */ + PL2303_NINTERFACES, /* ninterfaces */ + PL2303_CONFIGID, /* cfgvalue */ + PL2303_CONFIGSTRID, /* icfg */ + USB_CONFIG_ATTR_ONE|SELFPOWERED|REMOTEWAKEUP, /* attr */ + (CONFIG_USBDEV_MAXPOWER + 1) / 2 /* mxpower */ +}; + +static const struct usb_ifdesc_s g_ifdesc = +{ + USB_SIZEOF_IFDESC, /* len */ + USB_DESC_TYPE_INTERFACE, /* type */ + 0, /* ifno */ + 0, /* alt */ + PL2303_NENDPOINTS, /* neps */ + USB_CLASS_VENDOR_SPEC, /* classid */ + 0, /* subclass */ + 0, /* protocol */ + PL2303_CONFIGSTRID /* iif */ +}; + +static const struct usb_epdesc_s g_epintindesc = +{ + USB_SIZEOF_EPDESC, /* len */ + USB_DESC_TYPE_ENDPOINT, /* type */ + PL2303_EPINTIN_ADDR, /* addr */ + PL2303_EPINTIN_ATTR, /* attr */ + { LSBYTE(PL2303_EPINTIN_MXPACKET), /* maxpacket */ + MSBYTE(PL2303_EPINTIN_MXPACKET) }, + 1 /* interval */ +}; + +static const struct usb_epdesc_s g_epbulkoutdesc = +{ + USB_SIZEOF_EPDESC, /* len */ + USB_DESC_TYPE_ENDPOINT, /* type */ + PL2303_EPOUTBULK_ADDR, /* addr */ + PL2303_EPOUTBULK_ATTR, /* attr */ + { LSBYTE(64), MSBYTE(64) }, /* maxpacket -- might change to 512*/ + 0 /* interval */ +}; + +static const struct usb_epdesc_s g_epbulkindesc = +{ + USB_SIZEOF_EPDESC, /* len */ + USB_DESC_TYPE_ENDPOINT, /* type */ + PL2303_EPINBULK_ADDR, /* addr */ + PL2303_EPINBULK_ATTR, /* attr */ + { LSBYTE(64), MSBYTE(64) }, /* maxpacket -- might change to 512*/ + 0 /* interval */ +}; + +#ifdef CONFIG_USBDEV_DUALSPEED +static const struct usb_qualdesc_s g_qualdesc = +{ + USB_SIZEOF_QUALDESC, /* len */ + USB_DESC_TYPE_DEVICEQUALIFIER, /* type */ + {LSBYTE(0x0200), MSBYTE(0x0200) }, /* USB */ + USB_CLASS_VENDOR_SPEC, /* classid */ + 0, /* subclass */ + 0, /* protocol */ + CONFIG_PL2303_EP0MAXPACKET, /* mxpacketsize */ + PL2303_NCONFIGS, /* nconfigs */ + 0, /* reserved */ +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/************************************************************************************ + * Name: usbclass_fillrequest + * + * Description: + * If there is data to send it is copied to the given buffer. Called either + * to initiate the first write operation, or from the completion interrupt handler + * service consecutive write operations. + * + * NOTE: The USB serial driver does not use the serial drivers uart_xmitchars() + * API. That logic is essentially duplicated here because unlike UART hardware, + * we need to be able to handle writes not byte-by-byte, but packet-by-packet. + * Unfortunately, that decision also exposes some internals of the serial driver + * in the following. + * + ************************************************************************************/ + +static uint16_t usbclass_fillrequest(FAR struct pl2303_dev_s *priv, uint8_t *reqbuf, + uint16_t reqlen) +{ + FAR uart_dev_t *serdev = &priv->serdev; + FAR struct uart_buffer_s *xmit = &serdev->xmit; + irqstate_t flags; + uint16_t nbytes = 0; + + /* Disable interrupts */ + + flags = irqsave(); + + /* Transfer bytes while we have bytes available and there is room in the request */ + + while (xmit->head != xmit->tail && nbytes < reqlen) + { + *reqbuf++ = xmit->buffer[xmit->tail]; + nbytes++; + + /* Increment the tail pointer */ + + if (++(xmit->tail) >= xmit->size) + { + xmit->tail = 0; + } + } + + /* When all of the characters have been sent from the buffer + * disable the "TX interrupt". + */ + + if (xmit->head == xmit->tail) + { + uart_disabletxint(serdev); + } + + /* If any bytes were removed from the buffer, inform any waiters + * there there is space available. + */ + + if (nbytes) + { + uart_datasent(serdev); + } + + irqrestore(flags); + return nbytes; +} + +/************************************************************************************ + * Name: usbclass_sndpacket + * + * Description: + * This function obtains write requests, transfers the TX data into the request, + * and submits the requests to the USB controller. This continues untils either + * (1) there are no further packets available, or (2) thre is not further data + * to send. + * + ************************************************************************************/ + +static int usbclass_sndpacket(FAR struct pl2303_dev_s *priv) +{ + FAR struct usbdev_ep_s *ep; + FAR struct usbdev_req_s *req; + FAR struct pl2303_req_s *reqcontainer; + uint16_t reqlen; + irqstate_t flags; + int len; + int ret = OK; + +#ifdef CONFIG_DEBUG + if (priv == NULL) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return -ENODEV; + } +#endif + + flags = irqsave(); + + /* Use our IN endpoint for the transfer */ + + ep = priv->epbulkin; + + /* Loop until either (1) we run out or write requests, or (2) usbclass_fillrequest() + * is unable to fill the request with data (i.e., until there is no more data + * to be sent). + */ + + uvdbg("head=%d tail=%d nwrq=%d empty=%d\n", + priv->serdev.xmit.head, priv->serdev.xmit.tail, + priv->nwrq, sq_empty(&priv->reqlist)); + + /* Get the maximum number of bytes that will fit into one bulk IN request */ + +#ifdef CONFIG_PL2303_BULKREQLEN + reqlen = MAX(CONFIG_PL2303_BULKREQLEN, ep->maxpacket); +#else + reqlen = ep->maxpacket; +#endif + + while (!sq_empty(&priv->reqlist)) + { + /* Peek at the request in the container at the head of the list */ + + reqcontainer = (struct pl2303_req_s *)sq_peek(&priv->reqlist); + req = reqcontainer->req; + + /* Fill the request with serial TX data */ + + len = usbclass_fillrequest(priv, req->buf, reqlen); + if (len > 0) + { + /* Remove the empty container from the request list */ + + (void)sq_remfirst(&priv->reqlist); + priv->nwrq--; + + /* Then submit the request to the endpoint */ + + req->len = len; + req->priv = reqcontainer; + req->flags = USBDEV_REQFLAGS_NULLPKT; + ret = EP_SUBMIT(ep, req); + if (ret != OK) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_SUBMITFAIL), (uint16_t)-ret); + break; + } + } + else + { + break; + } + } + + irqrestore(flags); + return ret; +} + +/************************************************************************************ + * Name: usbclass_recvpacket + * + * Description: + * A normal completion event was received by the read completion handler at the + * interrupt level (with interrupts disabled). This function handles the USB packet + * and provides the received data to the uart RX buffer. + * + * Assumptions: + * Called from the USB interrupt handler with interrupts disabled. + * + ************************************************************************************/ + +static inline int usbclass_recvpacket(FAR struct pl2303_dev_s *priv, + uint8_t *reqbuf, uint16_t reqlen) +{ + FAR uart_dev_t *serdev = &priv->serdev; + FAR struct uart_buffer_s *recv = &serdev->recv; + uint16_t currhead; + uint16_t nexthead; + uint16_t nbytes = 0; + + /* Get the next head index. During the time that RX interrupts are disabled, the + * the serial driver will be extracting data from the circular buffer and modifying + * recv.tail. During this time, we should avoid modifying recv.head; Instead we will + * use a shadow copy of the index. When interrupts are restored, the real recv.head + * will be updated with this indes. + */ + + if (priv->rxenabled) + { + currhead = recv->head; + } + else + { + currhead = priv->rxhead; + } + + /* Pre-calculate the head index and check for wrap around. We need to do this + * so that we can determine if the circular buffer will overrun BEFORE we + * overrun the buffer! + */ + + nexthead = currhead + 1; + if (nexthead >= recv->size) + { + nexthead = 0; + } + + /* Then copy data into the RX buffer until either: (1) all of the data has been + * copied, or (2) the RX buffer is full. NOTE: If the RX buffer becomes full, + * then we have overrun the serial driver and data will be lost. + */ + + while (nexthead != recv->tail && nbytes < reqlen) + { + /* Copy one byte to the head of the circular RX buffer */ + + recv->buffer[currhead] = *reqbuf++; + + /* Update counts and indices */ + + currhead = nexthead; + nbytes++; + + /* Increment the head index and check for wrap around */ + + nexthead = currhead + 1; + if (nexthead >= recv->size) + { + nexthead = 0; + } + } + + /* Write back the head pointer using the shadow index if RX "interrupts" + * are disabled. + */ + + if (priv->rxenabled) + { + recv->head = currhead; + } + else + { + priv->rxhead = currhead; + } + + /* If data was added to the incoming serial buffer, then wake up any + * threads is waiting for incoming data. If we are running in an interrupt + * handler, then the serial driver will not run until the interrupt handler + * returns. + */ + + if (priv->rxenabled && nbytes > 0) + { + uart_datareceived(serdev); + } + + /* Return an error if the entire packet could not be transferred */ + + if (nbytes < reqlen) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RXOVERRUN), 0); + return -ENOSPC; + } + return OK; +} + +/**************************************************************************** + * Name: usbclass_allocreq + * + * Description: + * Allocate a request instance along with its buffer + * + ****************************************************************************/ + +static struct usbdev_req_s *usbclass_allocreq(FAR struct usbdev_ep_s *ep, + uint16_t len) +{ + FAR struct usbdev_req_s *req; + + req = EP_ALLOCREQ(ep); + if (req != NULL) + { + req->len = len; + req->buf = EP_ALLOCBUFFER(ep, len); + if (!req->buf) + { + EP_FREEREQ(ep, req); + req = NULL; + } + } + return req; +} + +/**************************************************************************** + * Name: usbclass_freereq + * + * Description: + * Free a request instance along with its buffer + * + ****************************************************************************/ + +static void usbclass_freereq(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req) +{ + if (ep != NULL && req != NULL) + { + if (req->buf != NULL) + { + EP_FREEBUFFER(ep, req->buf); + } + EP_FREEREQ(ep, req); + } +} + +/**************************************************************************** + * Name: usbclass_mkstrdesc + * + * Description: + * Construct a string descriptor + * + ****************************************************************************/ + +static int usbclass_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc) +{ + const char *str; + int len; + int ndata; + int i; + + switch (id) + { + case 0: + { + /* Descriptor 0 is the language id */ + + strdesc->len = 4; + strdesc->type = USB_DESC_TYPE_STRING; + strdesc->data[0] = LSBYTE(PL2303_STR_LANGUAGE); + strdesc->data[1] = MSBYTE(PL2303_STR_LANGUAGE); + return 4; + } + + case PL2303_MANUFACTURERSTRID: + str = CONFIG_PL2303_VENDORSTR; + break; + + case PL2303_PRODUCTSTRID: + str = CONFIG_PL2303_PRODUCTSTR; + break; + + case PL2303_SERIALSTRID: + str = CONFIG_PL2303_SERIALSTR; + break; + + case PL2303_CONFIGSTRID: + str = CONFIG_PL2303_CONFIGSTR; + break; + + default: + return -EINVAL; + } + + /* The string is utf16-le. The poor man's utf-8 to utf16-le + * conversion below will only handle 7-bit en-us ascii + */ + + len = strlen(str); + for (i = 0, ndata = 0; i < len; i++, ndata += 2) + { + strdesc->data[ndata] = str[i]; + strdesc->data[ndata+1] = 0; + } + + strdesc->len = ndata+2; + strdesc->type = USB_DESC_TYPE_STRING; + return strdesc->len; +} + +/**************************************************************************** + * Name: usbclass_mkepbulkdesc + * + * Description: + * Construct the endpoint descriptor + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +static inline void usbclass_mkepbulkdesc(const FAR struct usb_epdesc_s *indesc, + uint16_t mxpacket, + FAR struct usb_epdesc_s *outdesc) +{ + /* Copy the canned descriptor */ + + memcpy(outdesc, indesc, USB_SIZEOF_EPDESC); + + /* Then add the correct max packet size */ + + outdesc->mxpacketsize[0] = LSBYTE(mxpacket); + outdesc->mxpacketsize[1] = MSBYTE(mxpacket); +} +#endif + +/**************************************************************************** + * Name: usbclass_mkcfgdesc + * + * Description: + * Construct the configuration descriptor + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +static int16_t usbclass_mkcfgdesc(uint8_t *buf, uint8_t speed, uint8_t type) +#else +static int16_t usbclass_mkcfgdesc(uint8_t *buf) +#endif +{ + FAR struct usb_cfgdesc_s *cfgdesc = (struct usb_cfgdesc_s*)buf; +#ifdef CONFIG_USBDEV_DUALSPEED + bool hispeed = (speed == USB_SPEED_HIGH); + uint16_t bulkmxpacket; +#endif + uint16_t totallen; + + /* This is the total length of the configuration (not necessarily the + * size that we will be sending now. + */ + + totallen = USB_SIZEOF_CFGDESC + USB_SIZEOF_IFDESC + PL2303_NENDPOINTS * USB_SIZEOF_EPDESC; + + /* Configuration descriptor -- Copy the canned descriptor and fill in the + * type (we'll also need to update the size below + */ + + memcpy(cfgdesc, &g_cfgdesc, USB_SIZEOF_CFGDESC); + buf += USB_SIZEOF_CFGDESC; + + /* Copy the canned interface descriptor */ + + memcpy(buf, &g_ifdesc, USB_SIZEOF_IFDESC); + buf += USB_SIZEOF_IFDESC; + + /* Make the three endpoint configurations. First, check for switches + * between high and full speed + */ + +#ifdef CONFIG_USBDEV_DUALSPEED + if (type == USB_DESC_TYPE_OTHERSPEEDCONFIG) + { + hispeed = !hispeed; + } +#endif + + memcpy(buf, &g_epintindesc, USB_SIZEOF_EPDESC); + buf += USB_SIZEOF_EPDESC; + +#ifdef CONFIG_USBDEV_DUALSPEED + if (hispeed) + { + bulkmxpacket = 512; + } + else + { + bulkmxpacket = 64; + } + + usbclass_mkepbulkdesc(&g_epbulkoutdesc, bulkmxpacket, (struct usb_epdesc_s*)buf); + buf += USB_SIZEOF_EPDESC; + usbclass_mkepbulkdesc(&g_epbulkindesc, bulkmxpacket, (struct usb_epdesc_s*)buf); +#else + memcpy(buf, &g_epbulkoutdesc, USB_SIZEOF_EPDESC); + buf += USB_SIZEOF_EPDESC; + memcpy(buf, &g_epbulkindesc, USB_SIZEOF_EPDESC); +#endif + + /* Finally, fill in the total size of the configuration descriptor */ + + cfgdesc->totallen[0] = LSBYTE(totallen); + cfgdesc->totallen[1] = MSBYTE(totallen); + return totallen; +} + +/**************************************************************************** + * Name: usbclass_resetconfig + * + * Description: + * Mark the device as not configured and disable all endpoints. + * + ****************************************************************************/ + +static void usbclass_resetconfig(FAR struct pl2303_dev_s *priv) +{ + /* Are we configured? */ + + if (priv->config != PL2303_CONFIGIDNONE) + { + /* Yes.. but not anymore */ + + priv->config = PL2303_CONFIGIDNONE; + + /* Disable endpoints. This should force completion of all pending + * transfers. + */ + + EP_DISABLE(priv->epintin); + EP_DISABLE(priv->epbulkin); + EP_DISABLE(priv->epbulkout); + } +} + +/**************************************************************************** + * Name: usbclass_setconfig + * + * Description: + * Set the device configuration by allocating and configuring endpoints and + * by allocating and queue read and write requests. + * + ****************************************************************************/ + +static int usbclass_setconfig(FAR struct pl2303_dev_s *priv, uint8_t config) +{ + FAR struct usbdev_req_s *req; +#ifdef CONFIG_USBDEV_DUALSPEED + struct usb_epdesc_s epdesc; + uint16_t bulkmxpacket; +#endif + int i; + int ret = 0; + +#if CONFIG_DEBUG + if (priv == NULL) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return -EIO; + } +#endif + + if (config == priv->config) + { + /* Already configured -- Do nothing */ + + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_ALREADYCONFIGURED), 0); + return 0; + } + + /* Discard the previous configuration data */ + + usbclass_resetconfig(priv); + + /* Was this a request to simply discard the current configuration? */ + + if (config == PL2303_CONFIGIDNONE) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_CONFIGNONE), 0); + return 0; + } + + /* We only accept one configuration */ + + if (config != PL2303_CONFIGID) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_CONFIGIDBAD), 0); + return -EINVAL; + } + + /* Configure the IN interrupt endpoint */ + + ret = EP_CONFIGURE(priv->epintin, &g_epintindesc, false); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPINTINCONFIGFAIL), 0); + goto errout; + } + priv->epintin->priv = priv; + + /* Configure the IN bulk endpoint */ + +#ifdef CONFIG_USBDEV_DUALSPEED + if (priv->usbdev->speed == USB_SPEED_HIGH) + { + bulkmxpacket = 512; + } + else + { + bulkmxpacket = 64; + } + + usbclass_mkepbulkdesc(&g_epbulkindesc, bulkmxpacket, &epdesc); + ret = EP_CONFIGURE(priv->epbulkin, &epdesc, false); +#else + ret = EP_CONFIGURE(priv->epbulkin, &g_epbulkindesc, false); +#endif + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKINCONFIGFAIL), 0); + goto errout; + } + + priv->epbulkin->priv = priv; + + /* Configure the OUT bulk endpoint */ + +#ifdef CONFIG_USBDEV_DUALSPEED + usbclass_mkepbulkdesc(&g_epbulkoutdesc, bulkmxpacket, &epdesc); + ret = EP_CONFIGURE(priv->epbulkout, &epdesc, true); +#else + ret = EP_CONFIGURE(priv->epbulkout, &g_epbulkoutdesc, true); +#endif + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKOUTCONFIGFAIL), 0); + goto errout; + } + + priv->epbulkout->priv = priv; + + /* Queue read requests in the bulk OUT endpoint */ + + DEBUGASSERT(priv->nrdq == 0); + for (i = 0; i < CONFIG_PL2303_NRDREQS; i++) + { + req = priv->rdreqs[i].req; + req->callback = usbclass_rdcomplete; + ret = EP_SUBMIT(priv->epbulkout, req); + if (ret != OK) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-ret); + goto errout; + } + priv->nrdq++; + } + + priv->config = config; + return OK; + +errout: + usbclass_resetconfig(priv); + return ret; +} + +/**************************************************************************** + * Name: usbclass_ep0incomplete + * + * Description: + * Handle completion of EP0 control operations + * + ****************************************************************************/ + +static void usbclass_ep0incomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req) +{ + if (req->result || req->xfrd != req->len) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_REQRESULT), (uint16_t)-req->result); + } +} + +/**************************************************************************** + * Name: usbclass_rdcomplete + * + * Description: + * Handle completion of read request on the bulk OUT endpoint. This + * is handled like the receipt of serial data on the "UART" + * + ****************************************************************************/ + +static void usbclass_rdcomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req) +{ + FAR struct pl2303_dev_s *priv; + irqstate_t flags; + int ret; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (!ep || !ep->priv || !req) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract references to private data */ + + priv = (FAR struct pl2303_dev_s*)ep->priv; + + /* Process the received data unless this is some unusual condition */ + + flags = irqsave(); + switch (req->result) + { + case 0: /* Normal completion */ + usbtrace(TRACE_CLASSRDCOMPLETE, priv->nrdq); + usbclass_recvpacket(priv, req->buf, req->xfrd); + break; + + case -ESHUTDOWN: /* Disconnection */ + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSHUTDOWN), 0); + priv->nrdq--; + irqrestore(flags); + return; + + default: /* Some other error occurred */ + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDUNEXPECTED), (uint16_t)-req->result); + break; + }; + + /* Requeue the read request */ + +#ifdef CONFIG_PL2303_BULKREQLEN + req->len = max(CONFIG_PL2303_BULKREQLEN, ep->maxpacket); +#else + req->len = ep->maxpacket; +#endif + + ret = EP_SUBMIT(ep, req); + if (ret != OK) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-req->result); + } + irqrestore(flags); +} + +/**************************************************************************** + * Name: usbclass_wrcomplete + * + * Description: + * Handle completion of write request. This function probably executes + * in the context of an interrupt handler. + * + ****************************************************************************/ + +static void usbclass_wrcomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req) +{ + FAR struct pl2303_dev_s *priv; + FAR struct pl2303_req_s *reqcontainer; + irqstate_t flags; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (!ep || !ep->priv || !req || !req->priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract references to our private data */ + + priv = (FAR struct pl2303_dev_s *)ep->priv; + reqcontainer = (FAR struct pl2303_req_s *)req->priv; + + /* Return the write request to the free list */ + + flags = irqsave(); + sq_addlast((sq_entry_t*)reqcontainer, &priv->reqlist); + priv->nwrq++; + irqrestore(flags); + + /* Send the next packet unless this was some unusual termination + * condition + */ + + switch (req->result) + { + case OK: /* Normal completion */ + usbtrace(TRACE_CLASSWRCOMPLETE, priv->nwrq); + usbclass_sndpacket(priv); + break; + + case -ESHUTDOWN: /* Disconnection */ + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_WRSHUTDOWN), priv->nwrq); + break; + + default: /* Some other error occurred */ + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_WRUNEXPECTED), (uint16_t)-req->result); + break; + } +} + +/**************************************************************************** + * USB Class Driver Methods + ****************************************************************************/ + +/**************************************************************************** + * Name: usbclass_bind + * + * Description: + * Invoked when the driver is bound to a USB device driver + * + ****************************************************************************/ + +static int usbclass_bind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct pl2303_dev_s *priv = ((FAR struct pl2303_driver_s*)driver)->dev; + FAR struct pl2303_req_s *reqcontainer; + irqstate_t flags; + uint16_t reqlen; + int ret; + int i; + + usbtrace(TRACE_CLASSBIND, 0); + + /* Bind the structures */ + + priv->usbdev = dev; + + /* Save the reference to our private data structure in EP0 so that it + * can be recovered in ep0 completion events (Unless we are part of + * a composite device and, in that case, the composite device owns + * EP0). + */ + + dev->ep0->priv = priv; + + /* Preallocate control request */ + + priv->ctrlreq = usbclass_allocreq(dev->ep0, PL2303_MXDESCLEN); + if (priv->ctrlreq == NULL) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_ALLOCCTRLREQ), 0); + ret = -ENOMEM; + goto errout; + } + priv->ctrlreq->callback = usbclass_ep0incomplete; + + /* Pre-allocate all endpoints... the endpoints will not be functional + * until the SET CONFIGURATION request is processed in usbclass_setconfig. + * This is done here because there may be calls to kmalloc and the SET + * CONFIGURATION processing probably occurrs within interrupt handling + * logic where kmalloc calls will fail. + */ + + /* Pre-allocate the IN interrupt endpoint */ + + priv->epintin = DEV_ALLOCEP(dev, PL2303_EPINTIN_ADDR, true, USB_EP_ATTR_XFER_INT); + if (!priv->epintin) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPINTINALLOCFAIL), 0); + ret = -ENODEV; + goto errout; + } + priv->epintin->priv = priv; + + /* Pre-allocate the IN bulk endpoint */ + + priv->epbulkin = DEV_ALLOCEP(dev, PL2303_EPINBULK_ADDR, true, USB_EP_ATTR_XFER_BULK); + if (!priv->epbulkin) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKINALLOCFAIL), 0); + ret = -ENODEV; + goto errout; + } + priv->epbulkin->priv = priv; + + /* Pre-allocate the OUT bulk endpoint */ + + priv->epbulkout = DEV_ALLOCEP(dev, PL2303_EPOUTBULK_ADDR, false, USB_EP_ATTR_XFER_BULK); + if (!priv->epbulkout) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKOUTALLOCFAIL), 0); + ret = -ENODEV; + goto errout; + } + priv->epbulkout->priv = priv; + + /* Pre-allocate read requests */ + +#ifdef CONFIG_PL2303_BULKREQLEN + reqlen = max(CONFIG_PL2303_BULKREQLEN, priv->epbulkout->maxpacket); +#else + reqlen = priv->epbulkout->maxpacket; +#endif + + for (i = 0; i < CONFIG_PL2303_NRDREQS; i++) + { + reqcontainer = &priv->rdreqs[i]; + reqcontainer->req = usbclass_allocreq(priv->epbulkout, reqlen); + if (reqcontainer->req == NULL) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDALLOCREQ), -ENOMEM); + ret = -ENOMEM; + goto errout; + } + reqcontainer->req->priv = reqcontainer; + reqcontainer->req->callback = usbclass_rdcomplete; + } + + /* Pre-allocate write request containers and put in a free list */ + +#ifdef CONFIG_PL2303_BULKREQLEN + reqlen = max(CONFIG_PL2303_BULKREQLEN, priv->epbulkin->maxpacket); +#else + reqlen = priv->epbulkin->maxpacket; +#endif + + for (i = 0; i < CONFIG_PL2303_NWRREQS; i++) + { + reqcontainer = &priv->wrreqs[i]; + reqcontainer->req = usbclass_allocreq(priv->epbulkin, reqlen); + if (reqcontainer->req == NULL) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_WRALLOCREQ), -ENOMEM); + ret = -ENOMEM; + goto errout; + } + reqcontainer->req->priv = reqcontainer; + reqcontainer->req->callback = usbclass_wrcomplete; + + flags = irqsave(); + sq_addlast((sq_entry_t*)reqcontainer, &priv->reqlist); + priv->nwrq++; /* Count of write requests available */ + irqrestore(flags); + } + + /* Report if we are selfpowered */ + +#ifdef CONFIG_USBDEV_SELFPOWERED + DEV_SETSELFPOWERED(dev); +#endif + + /* And pull-up the data line for the soft connect function */ + + DEV_CONNECT(dev); + return OK; + +errout: + usbclass_unbind(driver, dev); + return ret; +} + +/**************************************************************************** + * Name: usbclass_unbind + * + * Description: + * Invoked when the driver is unbound from a USB device driver + * + ****************************************************************************/ + +static void usbclass_unbind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct pl2303_dev_s *priv; + FAR struct pl2303_req_s *reqcontainer; + irqstate_t flags; + int i; + + usbtrace(TRACE_CLASSUNBIND, 0); + +#ifdef CONFIG_DEBUG + if (!driver || !dev || !dev->ep0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = ((FAR struct pl2303_driver_s*)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EP0NOTBOUND), 0); + return; + } +#endif + + /* Make sure that we are not already unbound */ + + if (priv != NULL) + { + /* Make sure that the endpoints have been unconfigured. If + * we were terminated gracefully, then the configuration should + * already have been reset. If not, then calling usbclass_resetconfig + * should cause the endpoints to immediately terminate all + * transfers and return the requests to us (with result == -ESHUTDOWN) + */ + + usbclass_resetconfig(priv); + up_mdelay(50); + + /* Free the interrupt IN endpoint */ + + if (priv->epintin) + { + DEV_FREEEP(dev, priv->epintin); + priv->epintin = NULL; + } + + /* Free the bulk IN endpoint */ + + if (priv->epbulkin) + { + DEV_FREEEP(dev, priv->epbulkin); + priv->epbulkin = NULL; + } + + /* Free the pre-allocated control request */ + + if (priv->ctrlreq != NULL) + { + usbclass_freereq(dev->ep0, priv->ctrlreq); + priv->ctrlreq = NULL; + } + + /* Free pre-allocated read requests (which should all have + * been returned to the free list at this time -- we don't check) + */ + + DEBUGASSERT(priv->nrdq == 0); + for (i = 0; i < CONFIG_PL2303_NRDREQS; i++) + { + reqcontainer = &priv->rdreqs[i]; + if (reqcontainer->req) + { + usbclass_freereq(priv->epbulkout, reqcontainer->req); + reqcontainer->req = NULL; + } + } + + /* Free the bulk OUT endpoint */ + + if (priv->epbulkout) + { + DEV_FREEEP(dev, priv->epbulkout); + priv->epbulkout = NULL; + } + + /* Free write requests that are not in use (which should be all + * of them + */ + + flags = irqsave(); + DEBUGASSERT(priv->nwrq == CONFIG_PL2303_NWRREQS); + while (!sq_empty(&priv->reqlist)) + { + reqcontainer = (struct pl2303_req_s *)sq_remfirst(&priv->reqlist); + if (reqcontainer->req != NULL) + { + usbclass_freereq(priv->epbulkin, reqcontainer->req); + priv->nwrq--; /* Number of write requests queued */ + } + } + DEBUGASSERT(priv->nwrq == 0); + irqrestore(flags); + } + + /* Clear out all data in the circular buffer */ + + priv->serdev.xmit.head = 0; + priv->serdev.xmit.tail = 0; +} + +/**************************************************************************** + * Name: usbclass_setup + * + * Description: + * Invoked for ep0 control requests. This function probably executes + * in the context of an interrupt handler. + * + ****************************************************************************/ + +static int usbclass_setup(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, + FAR uint8_t *dataout, size_t outlen) +{ + FAR struct pl2303_dev_s *priv; + FAR struct usbdev_req_s *ctrlreq; + uint16_t value; + uint16_t index; + uint16_t len; + int ret = -EOPNOTSUPP; + +#ifdef CONFIG_DEBUG + if (!driver || !dev || !dev->ep0 || !ctrl) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return -EIO; + } +#endif + + /* Extract reference to private data */ + + usbtrace(TRACE_CLASSSETUP, ctrl->req); + priv = ((FAR struct pl2303_driver_s*)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv || !priv->ctrlreq) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EP0NOTBOUND), 0); + return -ENODEV; + } +#endif + ctrlreq = priv->ctrlreq; + + /* Extract the little-endian 16-bit values to host order */ + + value = GETUINT16(ctrl->value); + index = GETUINT16(ctrl->index); + len = GETUINT16(ctrl->len); + + uvdbg("type=%02x req=%02x value=%04x index=%04x len=%04x\n", + ctrl->type, ctrl->req, value, index, len); + + switch (ctrl->type & USB_REQ_TYPE_MASK) + { + /*********************************************************************** + * Standard Requests + ***********************************************************************/ + + case USB_REQ_TYPE_STANDARD: + { + switch (ctrl->req) + { + case USB_REQ_GETDESCRIPTOR: + { + /* The value field specifies the descriptor type in the MS byte and the + * descriptor index in the LS byte (order is little endian) + */ + + switch (ctrl->value[1]) + { + case USB_DESC_TYPE_DEVICE: + { + ret = USB_SIZEOF_DEVDESC; + memcpy(ctrlreq->buf, &g_devdesc, ret); + } + break; + +#ifdef CONFIG_USBDEV_DUALSPEED + case USB_DESC_TYPE_DEVICEQUALIFIER: + { + ret = USB_SIZEOF_QUALDESC; + memcpy(ctrlreq->buf, &g_qualdesc, ret); + } + break; + + case USB_DESC_TYPE_OTHERSPEEDCONFIG: +#endif /* CONFIG_USBDEV_DUALSPEED */ + + case USB_DESC_TYPE_CONFIG: + { +#ifdef CONFIG_USBDEV_DUALSPEED + ret = usbclass_mkcfgdesc(ctrlreq->buf, dev->speed, ctrl->req); +#else + ret = usbclass_mkcfgdesc(ctrlreq->buf); +#endif + } + break; + + case USB_DESC_TYPE_STRING: + { + /* index == language code. */ + + ret = usbclass_mkstrdesc(ctrl->value[0], (struct usb_strdesc_s *)ctrlreq->buf); + } + break; + + default: + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_GETUNKNOWNDESC), value); + } + break; + } + } + break; + + case USB_REQ_SETCONFIGURATION: + { + if (ctrl->type == 0) + { + ret = usbclass_setconfig(priv, value); + } + } + break; + + case USB_REQ_GETCONFIGURATION: + { + if (ctrl->type == USB_DIR_IN) + { + *(uint8_t*)ctrlreq->buf = priv->config; + ret = 1; + } + } + break; + + case USB_REQ_SETINTERFACE: + { + if (ctrl->type == USB_REQ_RECIPIENT_INTERFACE) + { + if (priv->config == PL2303_CONFIGID && + index == PL2303_INTERFACEID && + value == PL2303_ALTINTERFACEID) + { + usbclass_resetconfig(priv); + usbclass_setconfig(priv, priv->config); + ret = 0; + } + } + } + break; + + case USB_REQ_GETINTERFACE: + { + if (ctrl->type == (USB_DIR_IN|USB_REQ_RECIPIENT_INTERFACE) && + priv->config == PL2303_CONFIGIDNONE) + { + if (index != PL2303_INTERFACEID) + { + ret = -EDOM; + } + else + { + *(uint8_t*) ctrlreq->buf = PL2303_ALTINTERFACEID; + ret = 1; + } + } + } + break; + + default: + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDSTDREQ), ctrl->req); + break; + } + } + break; + + /*********************************************************************** + * PL2303 Vendor-Specific Requests + ***********************************************************************/ + + case PL2303_CONTROL_TYPE: + { + if ((ctrl->type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_INTERFACE) + { + switch (ctrl->req) + { + case PL2303_SETLINEREQUEST: + { + memcpy(priv->linest, ctrlreq->buf, min(len, 7)); + ret = 0; + } + break; + + + case PL2303_GETLINEREQUEST: + { + memcpy(ctrlreq->buf, priv->linest, 7); + ret = 7; + } + break; + + case PL2303_SETCONTROLREQUEST: + case PL2303_BREAKREQUEST: + { + ret = 0; + } + break; + + default: + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDCLASSREQ), ctrl->type); + break; + } + } + } + break; + + case PL2303_RWREQUEST_TYPE: + { + if ((ctrl->type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE) + { + if (ctrl->req == PL2303_RWREQUEST) + { + if ((ctrl->type & USB_DIR_IN) != 0) + { + *(uint32_t*)ctrlreq->buf = 0xdeadbeef; + ret = 4; + } + else + { + ret = 0; + } + } + else + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDCLASSREQ), ctrl->type); + } + } + } + break; + + default: + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDTYPE), ctrl->type); + break; + } + + /* Respond to the setup command if data was returned. On an error return + * value (ret < 0), the USB driver will stall. + */ + + if (ret >= 0) + { + ctrlreq->len = min(len, ret); + ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT; + ret = EP_SUBMIT(dev->ep0, ctrlreq); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPRESPQ), (uint16_t)-ret); + ctrlreq->result = OK; + usbclass_ep0incomplete(dev->ep0, ctrlreq); + } + } + + return ret; +} + +/**************************************************************************** + * Name: usbclass_disconnect + * + * Description: + * Invoked after all transfers have been stopped, when the host is + * disconnected. This function is probably called from the context of an + * interrupt handler. + * + ****************************************************************************/ + +static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct pl2303_dev_s *priv; + irqstate_t flags; + + usbtrace(TRACE_CLASSDISCONNECT, 0); + +#ifdef CONFIG_DEBUG + if (!driver || !dev || !dev->ep0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = ((FAR struct pl2303_driver_s*)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EP0NOTBOUND), 0); + return; + } +#endif + + /* Reset the configuration */ + + flags = irqsave(); + usbclass_resetconfig(priv); + + /* Clear out all data in the circular buffer */ + + priv->serdev.xmit.head = 0; + priv->serdev.xmit.tail = 0; + irqrestore(flags); + + /* Perform the soft connect function so that we will we can be + * re-enumerated. + */ + + DEV_CONNECT(dev); +} + +/**************************************************************************** + * Serial Device Methods + ****************************************************************************/ + +/**************************************************************************** + * Name: usbser_setup + * + * Description: + * This method is called the first time that the serial port is opened. + * + ****************************************************************************/ + +static int usbser_setup(FAR struct uart_dev_s *dev) +{ + FAR struct pl2303_dev_s *priv; + + usbtrace(PL2303_CLASSASPI_SETUP, 0); + + /* Sanity check */ + +#if CONFIG_DEBUG + if (!dev || !dev->priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return -EIO; + } +#endif + + /* Extract reference to private data */ + + priv = (FAR struct pl2303_dev_s*)dev->priv; + + /* Check if we have been configured */ + + if (priv->config == PL2303_CONFIGIDNONE) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_SETUPNOTCONNECTED), 0); + return -ENOTCONN; + } + + return OK; +} + +/**************************************************************************** + * Name: usbser_shutdown + * + * Description: + * This method is called when the serial port is closed. This operation + * is very simple for the USB serial backend because the serial driver + * has already assured that the TX data has full drained -- it calls + * usbser_txempty() until that function returns true before calling this + * function. + * + ****************************************************************************/ + +static void usbser_shutdown(FAR struct uart_dev_s *dev) +{ + usbtrace(PL2303_CLASSASPI_SHUTDOWN, 0); + + /* Sanity check */ + +#if CONFIG_DEBUG + if (!dev || !dev->priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + } +#endif +} + +/**************************************************************************** + * Name: usbser_attach + * + * Description: + * Does not apply to the USB serial class device + * + ****************************************************************************/ + +static int usbser_attach(FAR struct uart_dev_s *dev) +{ + usbtrace(PL2303_CLASSASPI_ATTACH, 0); + return OK; +} + +/**************************************************************************** + * Name: usbser_detach + * + * Description: +* Does not apply to the USB serial class device + * + ****************************************************************************/ + +static void usbser_detach(FAR struct uart_dev_s *dev) +{ + usbtrace(PL2303_CLASSASPI_DETACH, 0); +} + +/**************************************************************************** + * Name: usbser_rxint + * + * Description: + * Called by the serial driver to enable or disable RX interrupts. We, of + * course, have no RX interrupts but must behave consistently. This method + * is called under the conditions: + * + * 1. With enable==true when the port is opened (just after usbser_setup + * and usbser_attach are called called) + * 2. With enable==false while transferring data from the RX buffer + * 2. With enable==true while waiting for more incoming data + * 3. With enable==false when the port is closed (just before usbser_detach + * and usbser_shutdown are called). + * + ****************************************************************************/ + +static void usbser_rxint(FAR struct uart_dev_s *dev, bool enable) +{ + FAR struct pl2303_dev_s *priv; + FAR uart_dev_t *serdev; + irqstate_t flags; + + usbtrace(PL2303_CLASSASPI_RXINT, (uint16_t)enable); + + /* Sanity check */ + +#if CONFIG_DEBUG + if (!dev || !dev->priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = (FAR struct pl2303_dev_s*)dev->priv; + serdev = &priv->serdev; + + /* We need exclusive access to the RX buffer and private structure + * in the following. + */ + + flags = irqsave(); + if (enable) + { + /* RX "interrupts" are enabled. Is this a transition from disabled + * to enabled state? + */ + + if (!priv->rxenabled) + { + /* Yes. During the time that RX interrupts are disabled, the + * the serial driver will be extracting data from the circular + * buffer and modifying recv.tail. During this time, we + * should avoid modifying recv.head; When interrupts are restored, + * we can update the head pointer for all of the data that we + * put into cicular buffer while "interrupts" were disabled. + */ + + if (priv->rxhead != serdev->recv.head) + { + serdev->recv.head = priv->rxhead; + + /* Yes... signal the availability of new data */ + + uart_datareceived(serdev); + } + + /* RX "interrupts are no longer disabled */ + + priv->rxenabled = true; + } + } + + /* RX "interrupts" are disabled. Is this a transition from enabled + * to disabled state? + */ + + else if (priv->rxenabled) + { + /* Yes. During the time that RX interrupts are disabled, the + * the serial driver will be extracting data from the circular + * buffer and modifying recv.tail. During this time, we + * should avoid modifying recv.head; When interrupts are disabled, + * we use a shadow index and continue adding data to the circular + * buffer. + */ + + priv->rxhead = serdev->recv.head; + priv->rxenabled = false; + } + irqrestore(flags); +} + +/**************************************************************************** + * Name: usbser_txint + * + * Description: + * Called by the serial driver to enable or disable TX interrupts. We, of + * course, have no TX interrupts but must behave consistently. Initially, + * TX interrupts are disabled. This method is called under the conditions: + * + * 1. With enable==false while transferring data into the TX buffer + * 2. With enable==true when data may be taken from the buffer. + * 3. With enable==false when the TX buffer is empty + * + ****************************************************************************/ + +static void usbser_txint(FAR struct uart_dev_s *dev, bool enable) +{ + FAR struct pl2303_dev_s *priv; + + usbtrace(PL2303_CLASSASPI_TXINT, (uint16_t)enable); + + /* Sanity checks */ + +#if CONFIG_DEBUG + if (!dev || !dev->priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract references to private data */ + + priv = (FAR struct pl2303_dev_s*)dev->priv; + + /* If the new state is enabled and if there is data in the XMIT buffer, + * send the next packet now. + */ + + uvdbg("enable=%d head=%d tail=%d\n", + enable, priv->serdev.xmit.head, priv->serdev.xmit.tail); + + if (enable && priv->serdev.xmit.head != priv->serdev.xmit.tail) + { + usbclass_sndpacket(priv); + } +} + +/**************************************************************************** + * Name: usbser_txempty + * + * Description: + * Return true when all data has been sent. This is called from the + * serial driver when the driver is closed. It will call this API + * periodically until it reports true. NOTE that the serial driver takes all + * responsibility for flushing TX data through the hardware so we can be + * a bit sloppy about that. + * + ****************************************************************************/ + +static bool usbser_txempty(FAR struct uart_dev_s *dev) +{ + FAR struct pl2303_dev_s *priv = (FAR struct pl2303_dev_s*)dev->priv; + + usbtrace(PL2303_CLASSASPI_TXEMPTY, 0); + +#if CONFIG_DEBUG + if (!priv) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return true; + } +#endif + + /* When all of the allocated write requests have been returned to the + * reqlist, then there is no longer any TX data in flight. + */ + + return priv->nwrq >= CONFIG_PL2303_NWRREQS; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbdev_serialinitialize + * + * Description: + * Register USB serial port (and USB serial console if so configured). + * + ****************************************************************************/ + +int usbdev_serialinitialize(int minor) +{ + FAR struct pl2303_alloc_s *alloc; + FAR struct pl2303_dev_s *priv; + FAR struct pl2303_driver_s *drvr; + char devname[16]; + int ret; + + /* Allocate the structures needed */ + + alloc = (FAR struct pl2303_alloc_s*)kmalloc(sizeof(struct pl2303_alloc_s)); + if (!alloc) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_ALLOCDEVSTRUCT), 0); + return -ENOMEM; + } + + /* Convenience pointers into the allocated blob */ + + priv = &alloc->dev; + drvr = &alloc->drvr; + + /* Initialize the USB serial driver structure */ + + memset(priv, 0, sizeof(struct pl2303_dev_s)); + sq_init(&priv->reqlist); + + /* Fake line status */ + + priv->linest[0] = (115200) & 0xff; /* Baud=115200 */ + priv->linest[1] = (115200 >> 8) & 0xff; + priv->linest[2] = (115200 >> 16) & 0xff; + priv->linest[3] = (115200 >> 24) & 0xff; + priv->linest[4] = 0; /* One stop bit */ + priv->linest[5] = 0; /* No parity */ + priv->linest[6] = 8; /*8 data bits */ + + /* Initialize the serial driver sub-structure */ + + priv->serdev.recv.size = CONFIG_PL2303_RXBUFSIZE; + priv->serdev.recv.buffer = priv->rxbuffer; + priv->serdev.xmit.size = CONFIG_PL2303_TXBUFSIZE; + priv->serdev.xmit.buffer = priv->txbuffer; + priv->serdev.ops = &g_uartops; + priv->serdev.priv = priv; + + /* Initialize the USB class driver structure */ + +#ifdef CONFIG_USBDEV_DUALSPEED + drvr->drvr.speed = USB_SPEED_HIGH; +#else + drvr->drvr.speed = USB_SPEED_FULL; +#endif + drvr->drvr.ops = &g_driverops; + drvr->dev = priv; + + /* Register the USB serial class driver */ + + ret = usbdev_register(&drvr->drvr); + if (ret) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_DEVREGISTER), (uint16_t)-ret); + goto errout_with_alloc; + } + + /* Register the USB serial console */ + +#ifdef CONFIG_PL2303_CONSOLE + priv->serdev.isconsole = true; + ret = uart_register("/dev/console", &priv->serdev); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_CONSOLEREGISTER), (uint16_t)-ret); + goto errout_with_class; + } +#endif + + /* Register the single port supported by this implementation */ + + sprintf(devname, "/dev/ttyUSB%d", minor); + ret = uart_register(devname, &priv->serdev); + if (ret) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UARTREGISTER), (uint16_t)-ret); + goto errout_with_class; + } + return OK; + +errout_with_class: + usbdev_unregister(&drvr->drvr); +errout_with_alloc: + kfree(alloc); + return ret; +} diff --git a/nuttx/drivers/usbdev/usbdev_trace.c b/nuttx/drivers/usbdev/usbdev_trace.c new file mode 100644 index 0000000000..c8cc092925 --- /dev/null +++ b/nuttx/drivers/usbdev/usbdev_trace.c @@ -0,0 +1,233 @@ +/**************************************************************************** + * drivers/usbdev/usbdev_trace.c + * + * Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#undef usbtrace + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_USBDEV_TRACE_NRECORDS +# define CONFIG_USBDEV_TRACE_NRECORDS 128 +#endif + +#ifndef CONFIG_USBDEV_TRACE_INITIALIDSET +# define CONFIG_USBDEV_TRACE_INITIALIDSET 0 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_TRACE +static struct usbtrace_s g_trace[CONFIG_USBDEV_TRACE_NRECORDS]; +static uint16_t g_head = 0; +static uint16_t g_tail = 0; +#endif + +#if defined(CONFIG_USBDEV_TRACE) || (defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_USB)) +static usbtrace_idset_t g_maskedidset = CONFIG_USBDEV_TRACE_INITIALIDSET; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/******************************************************************************* + * Name: usbtrace_enable + * + * Description: + * Enable/disable tracing per trace ID. The initial state is all IDs enabled. + * + * Input Parameters: + * idset - The bitset of IDs to be masked. TRACE_ALLIDS enables all IDS; zero + * masks all IDs. + * + * Returned Value: + * The previous idset value. + * + * Assumptions: + * - May be called from an interrupt handler + * + *******************************************************************************/ + +#if defined(CONFIG_USBDEV_TRACE) || (defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_USB)) +usbtrace_idset_t usbtrace_enable(usbtrace_idset_t idset) +{ + irqstate_t flags; + usbtrace_idset_t ret; + + /* The following read and write must be atomic */ + + flags = irqsave(); + ret = g_maskedidset; + g_maskedidset = idset; + irqrestore(flags); + return ret; +} +#endif /* CONFIG_USBDEV_TRACE || CONFIG_DEBUG && CONFIG_DEBUG_USB */ + +/******************************************************************************* + * Name: usbtrace + * + * Description: + * Record a USB event (tracing must be enabled) + * + * Assumptions: + * May be called from an interrupt handler + * + *******************************************************************************/ + +#if defined(CONFIG_USBDEV_TRACE) || (defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_USB)) +void usbtrace(uint16_t event, uint16_t value) +{ + irqstate_t flags; + + /* Check if tracing is enabled for this ID */ + + flags = irqsave(); + if ((g_maskedidset & TRACE_ID2BIT(event)) != 0) + { +#ifdef CONFIG_USBDEV_TRACE + /* Yes... save the new trace data at the head */ + + g_trace[g_head].event = event; + g_trace[g_head].value = value; + + /* Increment the head and (probably) the tail index */ + + if (++g_head >= CONFIG_USBDEV_TRACE_NRECORDS) + { + g_head = 0; + } + + if (g_head == g_tail) + { + if (++g_tail >= CONFIG_USBDEV_TRACE_NRECORDS) + { + g_tail = 0; + } + } +#else + /* Just print the data using lib_lowprintf */ + + usbtrace_trprintf((trprintf_t)lib_lowprintf, event, value); +#endif + } + irqrestore(flags); +} +#endif /* CONFIG_USBDEV_TRACE || CONFIG_DEBUG && CONFIG_DEBUG_USB */ + +/******************************************************************************* + * Name: usbtrace_enumerate + * + * Description: + * Enumerate all buffer trace data (will temporarily disable tracing) + * + * Assumptions: + * NEVER called from an interrupt handler + * + *******************************************************************************/ + +#ifdef CONFIG_USBDEV_TRACE +int usbtrace_enumerate(trace_callback_t callback, void *arg) +{ + uint16_t ndx; + uint32_t idset; + int ret = OK; + + /* Temporarily disable tracing */ + + idset = usbtrace_enable(0); + + /* Visit every entry, starting with the tail */ + + for (ndx = g_tail; ndx != g_head; ) + { + /* Call the user provided callback */ + + ret = callback(&g_trace[ndx], arg); + if (ret != OK) + { + /* Abort the enumeration */ + + break; + } + + /* Increment the index */ + + if (++ndx >= CONFIG_USBDEV_TRACE_NRECORDS) + { + ndx = 0; + } + } + + /* Discard the trace data after it has been reported */ + + g_tail = g_head; + + /* Restore tracing state */ + + (void)usbtrace_enable(idset); + return ret; +} +#endif /* CONFIG_USBDEV_TRACE */ diff --git a/nuttx/drivers/usbdev/usbdev_trprintf.c b/nuttx/drivers/usbdev/usbdev_trprintf.c new file mode 100644 index 0000000000..2a9921f985 --- /dev/null +++ b/nuttx/drivers/usbdev/usbdev_trprintf.c @@ -0,0 +1,253 @@ +/**************************************************************************** + * drivers/usbdev/usbdev_trprintf.c + * + * Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/******************************************************************************* + * Name: usbtrace_trprintf + * + * Description: + * Print the trace record using the supplied printing function + * + *******************************************************************************/ + +void usbtrace_trprintf(trprintf_t trprintf, uint16_t event, uint16_t value) +{ + switch (event) + { + case TRACE_DEVINIT: + trprintf("USB controller initialization: %04x\n", value); + break; + + case TRACE_DEVUNINIT: + trprintf("USB controller un-initialization: %04x\n", value); + break; + + case TRACE_DEVREGISTER: + trprintf("usbdev_register(): %04x\n", value); + break; + + case TRACE_DEVUNREGISTER: + trprintf("usbdev_unregister(): %04x\n", value); + break; + + case TRACE_EPCONFIGURE: + trprintf("Endpoint configure(): %04x\n", value); + break; + + case TRACE_EPDISABLE: + trprintf("Endpoint disable(): %04x\n", value); + break; + + case TRACE_EPALLOCREQ: + trprintf("Endpoint allocreq(): %04x\n", value); + break; + + case TRACE_EPFREEREQ: + trprintf("Endpoint freereq(): %04x\n", value); + break; + + case TRACE_EPALLOCBUFFER: + trprintf("Endpoint allocbuffer(): %04x\n", value); + break; + + case TRACE_EPFREEBUFFER: + trprintf("Endpoint freebuffer(): %04x\n", value); + break; + + case TRACE_EPSUBMIT: + trprintf("Endpoint submit(): %04x\n", value); + break; + + case TRACE_EPCANCEL: + trprintf("Endpoint cancel(): %04x\n", value); + break; + + case TRACE_EPSTALL: + trprintf("Endpoint stall(true): %04x\n", value); + break; + + case TRACE_EPRESUME: + trprintf("Endpoint stall(false): %04x\n", value); + break; + + case TRACE_DEVALLOCEP: + trprintf("Device allocep(): %04x\n", value); + break; + + case TRACE_DEVFREEEP: + trprintf("Device freeep(): %04x\n", value); + break; + + case TRACE_DEVGETFRAME: + trprintf("Device getframe(): %04x\n", value); + break; + + case TRACE_DEVWAKEUP: + trprintf("Device wakeup(): %04x\n", value); + break; + + case TRACE_DEVSELFPOWERED: + trprintf("Device selfpowered(): %04x\n", value); + break; + + case TRACE_DEVPULLUP: + trprintf("Device pullup(): %04x\n", value); + break; + + case TRACE_CLASSBIND: + trprintf("Class bind(): %04x\n", value); + break; + + case TRACE_CLASSUNBIND: + trprintf("Class unbind(): %04x\n", value); + break; + + case TRACE_CLASSDISCONNECT: + trprintf("Class disconnect(): %04x\n", value); + break; + + case TRACE_CLASSSETUP: + trprintf("Class setup(): %04x\n", value); + break; + + case TRACE_CLASSSUSPEND: + trprintf("Class suspend(): %04x\n", value); + break; + + case TRACE_CLASSRESUME: + trprintf("Class resume(): %04x\n", value); + break; + + case TRACE_CLASSRDCOMPLETE: + trprintf("Class RD request complete: %04x\n", value); + break; + + case TRACE_CLASSWRCOMPLETE: + trprintf("Class WR request complete: %04x\n", value); + break; + + default: + switch (TRACE_ID(event)) + { + case TRACE_CLASSAPI_ID: /* Other class driver system API calls */ + trprintf("Class API call %d: %04x\n", TRACE_DATA(event), value); + break; + + case TRACE_CLASSSTATE_ID: /* Track class driver state changes */ + trprintf("Class state %d: %04x\n", TRACE_DATA(event), value); + break; + + case TRACE_INTENTRY_ID: /* Interrupt handler entry */ + trprintf("Interrupt %d entry: %04x\n", TRACE_DATA(event), value); + break; + + case TRACE_INTDECODE_ID: /* Decoded interrupt event */ + trprintf("Interrupt decode %d: %04x\n", TRACE_DATA(event), value); + break; + + case TRACE_INTEXIT_ID: /* Interrupt handler exit */ + trprintf("Interrupt %d exit: %04x\n", TRACE_DATA(event), value); + break; + + case TRACE_OUTREQQUEUED_ID: /* Request queued for OUT endpoint */ + trprintf("EP%d OUT request queued: %04x\n", TRACE_DATA(event), value); + break; + + case TRACE_INREQQUEUED_ID: /* Request queued for IN endpoint */ + trprintf("EP%d IN request queued: %04x\n", TRACE_DATA(event), value); + break; + + case TRACE_READ_ID: /* Read (OUT) action */ + trprintf("EP%d OUT read: %04x\n", TRACE_DATA(event), value); + break; + + case TRACE_WRITE_ID: /* Write (IN) action */ + trprintf("EP%d IN write: %04x\n", TRACE_DATA(event), value); + break; + + case TRACE_COMPLETE_ID: /* Request completed */ + trprintf("EP%d request complete: %04x\n", TRACE_DATA(event), value); + break; + + case TRACE_DEVERROR_ID: /* USB controller driver error event */ + trprintf("Controller error: %02x:%04x\n", TRACE_DATA(event), value); + break; + + case TRACE_CLSERROR_ID: /* USB class driver error event */ + trprintf("Class error: %02x:%04x\n", TRACE_DATA(event), value); + break; + + default: + trprintf("Unrecognized event: %02x:%02x:%04x\n", + TRACE_ID(event) >> 8, TRACE_DATA(event), value); + break; + } + } +} diff --git a/nuttx/drivers/usbdev/usbmsc.c b/nuttx/drivers/usbdev/usbmsc.c new file mode 100644 index 0000000000..68b61814a7 --- /dev/null +++ b/nuttx/drivers/usbdev/usbmsc.c @@ -0,0 +1,1778 @@ +/**************************************************************************** + * drivers/usbdev/usbmsc.c + * + * Copyright (C) 2008-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Mass storage class device. Bulk-only with SCSI subclass. + * + * References: + * "Universal Serial Bus Mass Storage Class, Specification Overview," + * Revision 1.2, USB Implementer's Forum, June 23, 2003. + * + * "Universal Serial Bus Mass Storage Class, Bulk-Only Transport," + * Revision 1.0, USB Implementer's Forum, September 31, 1999. + * + * "SCSI Primary Commands - 3 (SPC-3)," American National Standard + * for Information Technology, May 4, 2005 + * + * "SCSI Primary Commands - 4 (SPC-4)," American National Standard + * for Information Technology, July 19, 2008 + * + * "SCSI Block Commands -2 (SBC-2)," American National Standard + * for Information Technology, November 13, 2004 + * + * "SCSI Multimedia Commands - 3 (MMC-3)," American National Standard + * for Information Technology, November 12, 2001 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "usbmsc.h" + +#ifdef CONFIG_USBMSC_COMPOSITE +# include +# include "composite.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The internal version of the class driver */ + +struct usbmsc_driver_s +{ + struct usbdevclass_driver_s drvr; + FAR struct usbmsc_dev_s *dev; +}; + +/* This is what is allocated */ + +struct usbmsc_alloc_s +{ + struct usbmsc_dev_s dev; + struct usbmsc_driver_s drvr; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Class Driver Support *****************************************************/ + +static void usbmsc_ep0incomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); +static struct usbdev_req_s *usbmsc_allocreq(FAR struct usbdev_ep_s *ep, + uint16_t len); +static void usbmsc_freereq(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); + +/* Class Driver Operations (most at interrupt level) ************************/ + +static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); +static void usbmsc_unbind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); +static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, + size_t outlen); +static void usbmsc_disconnect(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); + +/* Initialization/Uninitialization ******************************************/ + +static void usbmsc_lununinitialize(struct usbmsc_lun_s *lun); +#ifdef CONFIG_USBMSC_COMPOSITE +static int usbmsc_exportluns(FAR void *handle); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Driver operations ********************************************************/ + +static struct usbdevclass_driverops_s g_driverops = +{ + usbmsc_bind, /* bind */ + usbmsc_unbind, /* unbind */ + usbmsc_setup, /* setup */ + usbmsc_disconnect, /* disconnect */ + NULL, /* suspend */ + NULL /* resume */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Class Driver Support + ****************************************************************************/ +/**************************************************************************** + * Name: usbmsc_ep0incomplete + * + * Description: + * Handle completion of EP0 control operations + * + ****************************************************************************/ + +static void usbmsc_ep0incomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req) +{ + if (req->result || req->xfrd != req->len) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_REQRESULT), + (uint16_t)-req->result); + } +} + +/**************************************************************************** + * Name: usbmsc_allocreq + * + * Description: + * Allocate a request instance along with its buffer + * + ****************************************************************************/ + +static struct usbdev_req_s *usbmsc_allocreq(FAR struct usbdev_ep_s *ep, + uint16_t len) +{ + FAR struct usbdev_req_s *req; + + req = EP_ALLOCREQ(ep); + if (req != NULL) + { + req->len = len; + req->buf = EP_ALLOCBUFFER(ep, len); + if (!req->buf) + { + EP_FREEREQ(ep, req); + req = NULL; + } + } + return req; +} + +/**************************************************************************** + * Name: usbmsc_freereq + * + * Description: + * Free a request instance along with its buffer + * + ****************************************************************************/ + +static void usbmsc_freereq(FAR struct usbdev_ep_s *ep, struct usbdev_req_s *req) +{ + if (ep != NULL && req != NULL) + { + if (req->buf != NULL) + { + EP_FREEBUFFER(ep, req->buf); + } + EP_FREEREQ(ep, req); + } +} + +/**************************************************************************** + * Class Driver Interfaces + ****************************************************************************/ +/**************************************************************************** + * Name: usbmsc_bind + * + * Description: + * Invoked when the driver is bound to a USB device driver + * + ****************************************************************************/ + +static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct usbmsc_dev_s *priv = ((FAR struct usbmsc_driver_s*)driver)->dev; + FAR struct usbmsc_req_s *reqcontainer; + irqstate_t flags; + int ret = OK; + int i; + + usbtrace(TRACE_CLASSBIND, 0); + + /* Bind the structures */ + + priv->usbdev = dev; + + /* Save the reference to our private data structure in EP0 so that it + * can be recovered in ep0 completion events (Unless we are part of + * a composite device and, in that case, the composite device owns + * EP0). + */ + +#ifndef CONFIG_USBMSC_COMPOSITE + dev->ep0->priv = priv; +#endif + + /* The configured EP0 size should match the reported EP0 size. We could + * easily adapt to the reported EP0 size, but then we could not use the + * const, canned descriptors. + */ + + DEBUGASSERT(CONFIG_USBMSC_EP0MAXPACKET == dev->ep0->maxpacket); + + /* Preallocate control request */ + + priv->ctrlreq = usbmsc_allocreq(dev->ep0, USBMSC_MXDESCLEN); + if (priv->ctrlreq == NULL) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALLOCCTRLREQ), 0); + ret = -ENOMEM; + goto errout; + } + priv->ctrlreq->callback = usbmsc_ep0incomplete; + + /* Pre-allocate all endpoints... the endpoints will not be functional + * until the SET CONFIGURATION request is processed in usbmsc_setconfig. + * This is done here because there may be calls to kmalloc and the SET + * CONFIGURATION processing probably occurrs within interrupt handling + * logic where kmalloc calls will fail. + */ + + /* Pre-allocate the IN bulk endpoint */ + + priv->epbulkin = DEV_ALLOCEP(dev, USBMSC_EPINBULK_ADDR, true, USB_EP_ATTR_XFER_BULK); + if (!priv->epbulkin) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPBULKINALLOCFAIL), 0); + ret = -ENODEV; + goto errout; + } + priv->epbulkin->priv = priv; + + /* Pre-allocate the OUT bulk endpoint */ + + priv->epbulkout = DEV_ALLOCEP(dev, USBMSC_EPOUTBULK_ADDR, false, USB_EP_ATTR_XFER_BULK); + if (!priv->epbulkout) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPBULKOUTALLOCFAIL), 0); + ret = -ENODEV; + goto errout; + } + priv->epbulkout->priv = priv; + + /* Pre-allocate read requests */ + + for (i = 0; i < CONFIG_USBMSC_NRDREQS; i++) + { + reqcontainer = &priv->rdreqs[i]; + reqcontainer->req = usbmsc_allocreq(priv->epbulkout, CONFIG_USBMSC_BULKOUTREQLEN); + if (reqcontainer->req == NULL) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDALLOCREQ), + (uint16_t)-ret); + ret = -ENOMEM; + goto errout; + } + reqcontainer->req->priv = reqcontainer; + reqcontainer->req->callback = usbmsc_rdcomplete; + } + + /* Pre-allocate write request containers and put in a free list */ + + for (i = 0; i < CONFIG_USBMSC_NWRREQS; i++) + { + reqcontainer = &priv->wrreqs[i]; + reqcontainer->req = usbmsc_allocreq(priv->epbulkin, CONFIG_USBMSC_BULKINREQLEN); + if (reqcontainer->req == NULL) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRALLOCREQ), + (uint16_t)-ret); + ret = -ENOMEM; + goto errout; + } + reqcontainer->req->priv = reqcontainer; + reqcontainer->req->callback = usbmsc_wrcomplete; + + flags = irqsave(); + sq_addlast((sq_entry_t*)reqcontainer, &priv->wrreqlist); + irqrestore(flags); + } + + /* Report if we are selfpowered (unless we are part of a composite device) */ + +#ifndef CONFIG_USBMSC_COMPOSITE +#ifdef CONFIG_USBDEV_SELFPOWERED + DEV_SETSELFPOWERED(dev); +#endif + + /* And pull-up the data line for the soft connect function (unless we are + * part of a composite device) + */ + + DEV_CONNECT(dev); +#endif + return OK; + +errout: + usbmsc_unbind(driver, dev); + return ret; +} + +/**************************************************************************** + * Name: usbmsc_unbind + * + * Description: + * Invoked when the driver is unbound from a USB device driver + * + ****************************************************************************/ + +static void usbmsc_unbind(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct usbmsc_dev_s *priv; + FAR struct usbmsc_req_s *reqcontainer; + irqstate_t flags; + int i; + + usbtrace(TRACE_CLASSUNBIND, 0); + +#ifdef CONFIG_DEBUG + if (!driver || !dev || !dev->ep0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNBINDINVALIDARGS), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = ((FAR struct usbmsc_driver_s*)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EP0NOTBOUND1), 0); + return; + } +#endif + + /* The worker thread should have already been stopped by the + * driver un-initialize logic. + */ + + DEBUGASSERT(priv->thstate == USBMSC_STATE_TERMINATED); + + /* Make sure that we are not already unbound */ + + if (priv != NULL) + { + /* Make sure that the endpoints have been unconfigured. If + * we were terminated gracefully, then the configuration should + * already have been reset. If not, then calling usbmsc_resetconfig + * should cause the endpoints to immediately terminate all + * transfers and return the requests to us (with result == -ESHUTDOWN) + */ + + usbmsc_resetconfig(priv); + up_mdelay(50); + + /* Free the pre-allocated control request */ + + if (priv->ctrlreq != NULL) + { + usbmsc_freereq(dev->ep0, priv->ctrlreq); + priv->ctrlreq = NULL; + } + + /* Free pre-allocated read requests (which should all have + * been returned to the free list at this time -- we don't check) + */ + + for (i = 0; i < CONFIG_USBMSC_NRDREQS; i++) + { + reqcontainer = &priv->rdreqs[i]; + if (reqcontainer->req) + { + usbmsc_freereq(priv->epbulkout, reqcontainer->req); + reqcontainer->req = NULL; + } + } + + /* Free the bulk OUT endpoint */ + + if (priv->epbulkout) + { + DEV_FREEEP(dev, priv->epbulkout); + priv->epbulkout = NULL; + } + + /* Free write requests that are not in use (which should be all + * of them + */ + + flags = irqsave(); + while (!sq_empty(&priv->wrreqlist)) + { + reqcontainer = (struct usbmsc_req_s *)sq_remfirst(&priv->wrreqlist); + if (reqcontainer->req != NULL) + { + usbmsc_freereq(priv->epbulkin, reqcontainer->req); + } + } + + /* Free the bulk IN endpoint */ + + if (priv->epbulkin) + { + DEV_FREEEP(dev, priv->epbulkin); + priv->epbulkin = NULL; + } + + irqrestore(flags); + } +} + +/**************************************************************************** + * Name: usbmsc_setup + * + * Description: + * Invoked for ep0 control requests. This function probably executes + * in the context of an interrupt handler. + * + ****************************************************************************/ + +static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, + FAR uint8_t *dataout, size_t outlen) +{ + FAR struct usbmsc_dev_s *priv; + FAR struct usbdev_req_s *ctrlreq; + uint16_t value; + uint16_t index; + uint16_t len; + int ret = -EOPNOTSUPP; + +#ifdef CONFIG_DEBUG + if (!driver || !dev || !dev->ep0 || !ctrl) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_SETUPINVALIDARGS), 0); + return -EIO; + } +#endif + + /* Extract reference to private data */ + + usbtrace(TRACE_CLASSSETUP, ctrl->req); + priv = ((FAR struct usbmsc_driver_s *)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv || !priv->ctrlreq) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EP0NOTBOUND2), 0); + return -ENODEV; + } +#endif + ctrlreq = priv->ctrlreq; + + /* Extract the little-endian 16-bit values to host order */ + + value = GETUINT16(ctrl->value); + index = GETUINT16(ctrl->index); + len = GETUINT16(ctrl->len); + + uvdbg("type=%02x req=%02x value=%04x index=%04x len=%04x\n", + ctrl->type, ctrl->req, value, index, len); + + if ((ctrl->type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) + { + /********************************************************************** + * Standard Requests + **********************************************************************/ + + switch (ctrl->req) + { + case USB_REQ_GETDESCRIPTOR: + { + /* The value field specifies the descriptor type in the MS byte and the + * descriptor index in the LS byte (order is little endian) + */ + + switch (ctrl->value[1]) + { + /* If the mass storage device is used in as part of a composite + * device, then the device descriptor is is provided by logic + * in the composite device implementation. + */ + +#ifndef CONFIG_USBMSC_COMPOSITE + case USB_DESC_TYPE_DEVICE: + { + ret = USB_SIZEOF_DEVDESC; + memcpy(ctrlreq->buf, usbmsc_getdevdesc(), ret); + } + break; +#endif + + /* If the mass storage device is used in as part of a composite device, + * then the device qualifier descriptor is provided by logic in the + * composite device implementation. + */ + +#if !defined(CONFIG_USBMSC_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED) + case USB_DESC_TYPE_DEVICEQUALIFIER: + { + ret = USB_SIZEOF_QUALDESC; + memcpy(ctrlreq->buf, usbmsc_getqualdesc(), ret); + } + break; + + case USB_DESC_TYPE_OTHERSPEEDCONFIG: +#endif + + /* If the mass storage device is used in as part of a composite device, + * then the configuration descriptor is provided by logic in the + * composite device implementation. + */ + +#ifndef CONFIG_USBMSC_COMPOSITE + case USB_DESC_TYPE_CONFIG: + { +#ifdef CONFIG_USBDEV_DUALSPEED + ret = usbmsc_mkcfgdesc(ctrlreq->buf, dev->speed, ctrl->value[1]); +#else + ret = usbmsc_mkcfgdesc(ctrlreq->buf); +#endif + } + break; +#endif + + /* If the mass storage device is used in as part of a composite device, + * then the language string descriptor is provided by logic in the + * composite device implementation. + */ + +#ifndef CONFIG_USBMSC_COMPOSITE + case USB_DESC_TYPE_STRING: + { + /* index == language code. */ + + ret = usbmsc_mkstrdesc(ctrl->value[0], (struct usb_strdesc_s *)ctrlreq->buf); + } + break; +#endif + + default: + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_GETUNKNOWNDESC), value); + } + break; + } + } + break; + + case USB_REQ_SETCONFIGURATION: + { + if (ctrl->type == 0) + { + /* Signal the worker thread to instantiate the new configuration */ + + priv->theventset |= USBMSC_EVENT_CFGCHANGE; + priv->thvalue = value; + pthread_cond_signal(&priv->cond); + + /* Return here... the response will be provided later by the + * worker thread. + */ + + return OK; + } + } + break; + + /* If the mass storage device is used in as part of a composite device, + * then the overall composite class configuration is managed by logic + * in the composite device implementation. + */ + +#ifndef CONFIG_USBMSC_COMPOSITE + case USB_REQ_GETCONFIGURATION: + { + if (ctrl->type == USB_DIR_IN) + { + ctrlreq->buf[0] = priv->config; + ret = 1; + } + } + break; +#endif + + case USB_REQ_SETINTERFACE: + { + if (ctrl->type == USB_REQ_RECIPIENT_INTERFACE) + { + if (priv->config == USBMSC_CONFIGID && + index == USBMSC_INTERFACEID && + value == USBMSC_ALTINTERFACEID) + { + /* Signal to instantiate the interface change */ + + priv->theventset |= USBMSC_EVENT_IFCHANGE; + pthread_cond_signal(&priv->cond); + + /* Return here... the response will be provided later by the + * worker thread. + */ + + return OK; + } + } + } + break; + + case USB_REQ_GETINTERFACE: + { + if (ctrl->type == (USB_DIR_IN|USB_REQ_RECIPIENT_INTERFACE) && + priv->config == USBMSC_CONFIGIDNONE) + { + if (index != USBMSC_INTERFACEID) + { + ret = -EDOM; + } + else + { + ctrlreq->buf[0] = USBMSC_ALTINTERFACEID; + ret = 1; + } + } + } + break; + + default: + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNSUPPORTEDSTDREQ), ctrl->req); + break; + } + } + else if ((ctrl->type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_CLASS) + { + /********************************************************************** + * Bulk-Only Mass Storage Class Requests + **********************************************************************/ + + /* Verify that we are configured */ + + if (!priv->config) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_NOTCONFIGURED), 0); + return ret; + } + + switch (ctrl->req) + { + case USBMSC_REQ_MSRESET: /* Reset mass storage device and interface */ + { + if (ctrl->type == USBMSC_TYPE_SETUPOUT && value == 0 && len == 0) + { + /* Only one interface is supported */ + + if (index != USBMSC_INTERFACEID) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_MSRESETNDX), index); + ret = -EDOM; + } + else + { + /* Signal to stop the current operation and reinitialize state */ + + priv->theventset |= USBMSC_EVENT_RESET; + pthread_cond_signal(&priv->cond); + + /* Return here... the response will be provided later by the + * worker thread. + */ + + return OK; + } + } + } + break; + + case USBMSC_REQ_GETMAXLUN: /* Return number LUNs supported */ + { + if (ctrl->type == USBMSC_TYPE_SETUPIN && value == 0 && len == 1) + { + /* Only one interface is supported */ + + if (index != USBMSC_INTERFACEID) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_GETMAXLUNNDX), index); + ret = -EDOM; + } + else + { + ctrlreq->buf[0] = priv->nluns - 1; + ret = 1; + } + } + } + break; + + default: + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BADREQUEST), ctrl->req); + break; + } + } + else + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNSUPPORTEDTYPE), ctrl->type); + } + + /* Respond to the setup command if data was returned. On an error return + * value (ret < 0), the USB driver will stall EP0. + */ + + if (ret >= 0) + { + /* Configure the response */ + + ctrlreq->len = MIN(len, ret); + ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT; + + /* Send the response -- either directly to the USB controller or + * indirectly in the case where this class is a member of a composite + * device. + */ + +#ifndef CONFIG_USBMSC_COMPOSITE + ret = EP_SUBMIT(dev->ep0, ctrlreq); +#else + ret = composite_ep0submit(driver, dev, ctrlreq); +#endif + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPRESPQ), (uint16_t)-ret); +#if 0 /* Not necessary */ + ctrlreq->result = OK; + usbmsc_ep0incomplete(dev->ep0, ctrlreq); +#endif + } + } + + return ret; +} + +/**************************************************************************** + * Name: usbmsc_disconnect + * + * Description: + * Invoked after all transfers have been stopped, when the host is + * disconnected. This function is probably called from the context of an + * interrupt handler. + * + ****************************************************************************/ + +static void usbmsc_disconnect(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + struct usbmsc_dev_s *priv; + irqstate_t flags; + + usbtrace(TRACE_CLASSDISCONNECT, 0); + +#ifdef CONFIG_DEBUG + if (!driver || !dev || !dev->ep0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_DISCONNECTINVALIDARGS), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = ((FAR struct usbmsc_driver_s *)driver)->dev; + +#ifdef CONFIG_DEBUG + if (!priv) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EP0NOTBOUND3), 0); + return; + } +#endif + + /* Reset the configuration */ + + flags = irqsave(); + usbmsc_resetconfig(priv); + + /* Signal the worker thread */ + + priv->theventset |= USBMSC_EVENT_DISCONNECT; + pthread_cond_signal(&priv->cond); + irqrestore(flags); + + /* Perform the soft connect function so that we will we can be + * re-enumerated (unless we are part of a composite device) + */ + +#ifndef CONFIG_USBMSC_COMPOSITE + DEV_CONNECT(dev); +#endif +} + +/**************************************************************************** + * Initialization/Un-Initialization + ****************************************************************************/ +/**************************************************************************** + * Name: usbmsc_lununinitialize + ****************************************************************************/ + +static void usbmsc_lununinitialize(struct usbmsc_lun_s *lun) +{ + /* Has a block driver has been bound to the LUN? */ + + if (lun->inode) + { + /* Close the block driver */ + + (void)close_blockdriver(lun->inode); + } + + memset(lun, 0, sizeof(struct usbmsc_lun_s *)); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Internal Interfaces + ****************************************************************************/ + +/**************************************************************************** + * Name: usbmsc_setconfig + * + * Description: + * Set the device configuration by allocating and configuring endpoints and + * by allocating and queuing read and write requests. + * + ****************************************************************************/ + +int usbmsc_setconfig(FAR struct usbmsc_dev_s *priv, uint8_t config) +{ + FAR struct usbmsc_req_s *privreq; + FAR struct usbdev_req_s *req; +#ifdef CONFIG_USBDEV_DUALSPEED + FAR const struct usb_epdesc_s *epdesc; + bool hispeed = (priv->usbdev->speed == USB_SPEED_HIGH); + uint16_t bulkmxpacket; +#endif + int i; + int ret = 0; + +#if CONFIG_DEBUG + if (priv == NULL) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_SETCONFIGINVALIDARGS), 0); + return -EIO; + } +#endif + + if (config == priv->config) + { + /* Already configured -- Do nothing */ + + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALREADYCONFIGURED), 0); + return OK; + } + + /* Discard the previous configuration data */ + + usbmsc_resetconfig(priv); + + /* Was this a request to simply discard the current configuration? */ + + if (config == USBMSC_CONFIGIDNONE) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CONFIGNONE), 0); + return OK; + } + + /* We only accept one configuration */ + + if (config != USBMSC_CONFIGID) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CONFIGIDBAD), 0); + return -EINVAL; + } + + /* Configure the IN bulk endpoint */ + +#ifdef CONFIG_USBDEV_DUALSPEED + bulkmxpacket = USBMSC_BULKMAXPACKET(hispeed); + epdesc = USBMSC_EPBULKINDESC(hispeed); + ret = EP_CONFIGURE(priv->epbulkin, epdesc, false); +#else + ret = EP_CONFIGURE(priv->epbulkin, + usbmsc_getepdesc(USBMSC_EPFSBULKIN), false); +#endif + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPBULKINCONFIGFAIL), 0); + goto errout; + } + + priv->epbulkin->priv = priv; + + /* Configure the OUT bulk endpoint */ + +#ifdef CONFIG_USBDEV_DUALSPEED + epdesc = USBMSC_EPBULKOUTDESC(hispeed); + ret = EP_CONFIGURE(priv->epbulkout, epdesc, true); +#else + ret = EP_CONFIGURE(priv->epbulkout, + usbmsc_getepdesc(USBMSC_EPFSBULKOUT), true); +#endif + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPBULKOUTCONFIGFAIL), 0); + goto errout; + } + + priv->epbulkout->priv = priv; + + /* Queue read requests in the bulk OUT endpoint */ + + for (i = 0; i < CONFIG_USBMSC_NRDREQS; i++) + { + privreq = &priv->rdreqs[i]; + req = privreq->req; + req->len = CONFIG_USBMSC_BULKOUTREQLEN; + req->priv = privreq; + req->callback = usbmsc_rdcomplete; + ret = EP_SUBMIT(priv->epbulkout, req); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDSUBMIT), (uint16_t)-ret); + goto errout; + } + } + + priv->config = config; + return OK; + +errout: + usbmsc_resetconfig(priv); + return ret; +} + +/**************************************************************************** + * Name: usbmsc_resetconfig + * + * Description: + * Mark the device as not configured and disable all endpoints. + * + ****************************************************************************/ + +void usbmsc_resetconfig(FAR struct usbmsc_dev_s *priv) +{ + /* Are we configured? */ + + if (priv->config != USBMSC_CONFIGIDNONE) + { + /* Yes.. but not anymore */ + + priv->config = USBMSC_CONFIGIDNONE; + + /* Disable endpoints. This should force completion of all pending + * transfers. + */ + + EP_DISABLE(priv->epbulkin); + EP_DISABLE(priv->epbulkout); + } +} + +/**************************************************************************** + * Name: usbmsc_wrcomplete + * + * Description: + * Handle completion of write request. This function probably executes + * in the context of an interrupt handler. + * + ****************************************************************************/ + +void usbmsc_wrcomplete(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req) +{ + FAR struct usbmsc_dev_s *priv; + FAR struct usbmsc_req_s *privreq; + irqstate_t flags; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (!ep || !ep->priv || !req || !req->priv) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRCOMPLETEINVALIDARGS), 0); + return; + } +#endif + + /* Extract references to private data */ + + priv = (FAR struct usbmsc_dev_s*)ep->priv; + privreq = (FAR struct usbmsc_req_s *)req->priv; + + /* Return the write request to the free list */ + + flags = irqsave(); + sq_addlast((sq_entry_t*)privreq, &priv->wrreqlist); + irqrestore(flags); + + /* Process the received data unless this is some unusual condition */ + + switch (req->result) + { + case OK: /* Normal completion */ + usbtrace(TRACE_CLASSWRCOMPLETE, req->xfrd); + break; + + case -ESHUTDOWN: /* Disconnection */ + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRSHUTDOWN), 0); + break; + + default: /* Some other error occurred */ + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRUNEXPECTED), + (uint16_t)-req->result); + break; + }; + + /* Inform the worker thread that a write request has been returned */ + + priv->theventset |= USBMSC_EVENT_WRCOMPLETE; + pthread_cond_signal(&priv->cond); +} + +/**************************************************************************** + * Name: usbmsc_rdcomplete + * + * Description: + * Handle completion of read request on the bulk OUT endpoint. This + * is handled like the receipt of serial data on the "UART" + * + ****************************************************************************/ + +void usbmsc_rdcomplete(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req) +{ + FAR struct usbmsc_dev_s *priv; + FAR struct usbmsc_req_s *privreq; + irqstate_t flags; + int ret; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (!ep || !ep->priv || !req || !req->priv) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDCOMPLETEINVALIDARGS), 0); + return; + } +#endif + + /* Extract references to private data */ + + priv = (FAR struct usbmsc_dev_s*)ep->priv; + privreq = (FAR struct usbmsc_req_s *)req->priv; + + /* Process the received data unless this is some unusual condition */ + + switch (req->result) + { + case 0: /* Normal completion */ + { + usbtrace(TRACE_CLASSRDCOMPLETE, req->xfrd); + + /* Add the filled read request from the rdreqlist */ + + flags = irqsave(); + sq_addlast((sq_entry_t*)privreq, &priv->rdreqlist); + irqrestore(flags); + + /* Signal the worker thread that there is received data to be processed */ + + priv->theventset |= USBMSC_EVENT_RDCOMPLETE; + pthread_cond_signal(&priv->cond); + } + break; + + case -ESHUTDOWN: /* Disconnection */ + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDSHUTDOWN), 0); + + /* Drop the read request... it will be cleaned up later */ + } + break; + + default: /* Some other error occurred */ + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDUNEXPECTED), + (uint16_t)-req->result); + + /* Return the read request to the bulk out endpoint for re-filling */ + + req = privreq->req; + req->priv = privreq; + req->callback = usbmsc_rdcomplete; + + ret = EP_SUBMIT(priv->epbulkout, req); + if (ret != OK) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDCOMPLETERDSUBMIT), + (uint16_t)-ret); + } + } + break; + } +} + +/**************************************************************************** + * Name: usbmsc_deferredresponse + * + * Description: + * Some EP0 setup request cannot be responded to immediately becuase they + * require some asynchronous action from the SCSI worker thread. This + * function is provided for the SCSI thread to make that deferred response. + * The specific requests that require this deferred response are: + * + * 1. USB_REQ_SETCONFIGURATION, + * 2. USB_REQ_SETINTERFACE, or + * 3. USBMSC_REQ_MSRESET + * + * In all cases, the success reponse is a zero-length packet; the failure + * response is an EP0 stall. + * + * Input parameters: + * priv - Private state structure for this USB storage instance + * stall - true is the action failed and a stall is required + * + ****************************************************************************/ + +void usbmsc_deferredresponse(FAR struct usbmsc_dev_s *priv, bool failed) +{ + FAR struct usbdev_s *dev; + FAR struct usbdev_req_s *ctrlreq; + int ret; + +#ifdef CONFIG_DEBUG + if (!priv || !priv->usbdev || !priv->ctrlreq) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_DEFERREDRESPINVALIDARGS), 0); + return; + } +#endif + + dev = priv->usbdev; + ctrlreq = priv->ctrlreq; + + /* If no error occurs, respond to the deferred setup command with a null + * packet. + */ + + if (!failed) + { + ctrlreq->len = 0; + ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT; + ret = EP_SUBMIT(dev->ep0, ctrlreq); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_DEFERREDRESPSUBMIT), + (uint16_t)-ret); +#if 0 /* Not necessary */ + ctrlreq->result = OK; + usbmsc_ep0incomplete(dev->ep0, ctrlreq); +#endif + } + } + else + { + /* On a failure, the USB driver will stall. */ + + usbtrace(TRACE_DEVERROR(USBMSC_TRACEERR_DEFERREDRESPSTALLED), 0); + EP_STALL(dev->ep0); + } +} + +/**************************************************************************** + * User Interfaces + ****************************************************************************/ +/**************************************************************************** + * Name: usbmsc_configure + * + * Description: + * One-time initialization of the USB storage driver. The initialization + * sequence is as follows: + * + * 1. Call usbmsc_configure to perform one-time initialization specifying + * the number of luns. + * 2. Call usbmsc_bindlun to configure each supported LUN + * 3. Call usbmsc_exportluns when all LUNs are configured + * + * Input Parameters: + * nluns - the number of LUNs that will be registered + * handle - Location to return a handle that is used in other API calls. + * + * Returned Value: + * 0 on success; a negated errno on failure + * + ****************************************************************************/ + +int usbmsc_configure(unsigned int nluns, void **handle) +{ + FAR struct usbmsc_alloc_s *alloc; + FAR struct usbmsc_dev_s *priv; + FAR struct usbmsc_driver_s *drvr; + int ret; + +#ifdef CONFIG_DEBUG + if (nluns > 15) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_TOOMANYLUNS), 0); + return -EDOM; + } +#endif + + /* Allocate the structures needed */ + + alloc = (FAR struct usbmsc_alloc_s*)kmalloc(sizeof(struct usbmsc_alloc_s)); + if (!alloc) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALLOCDEVSTRUCT), 0); + return -ENOMEM; + } + + /* Initialize the USB storage driver structure */ + + priv = &alloc->dev; + memset(priv, 0, sizeof(struct usbmsc_dev_s)); + + pthread_mutex_init(&priv->mutex, NULL); + pthread_cond_init(&priv->cond, NULL); + sq_init(&priv->wrreqlist); + + priv->nluns = nluns; + + /* Allocate the LUN table */ + + priv->luntab = (struct usbmsc_lun_s*)kmalloc(priv->nluns*sizeof(struct usbmsc_lun_s)); + if (!priv->luntab) + { + ret = -ENOMEM; + goto errout; + } + memset(priv->luntab, 0, priv->nluns * sizeof(struct usbmsc_lun_s)); + + /* Initialize the USB class driver structure */ + + drvr = &alloc->drvr; +#ifdef CONFIG_USBDEV_DUALSPEED + drvr->drvr.speed = USB_SPEED_HIGH; +#else + drvr->drvr.speed = USB_SPEED_FULL; +#endif + drvr->drvr.ops = &g_driverops; + drvr->dev = priv; + + /* Return the handle and success */ + + *handle = (FAR void*)alloc; + return OK; + +errout: + usbmsc_uninitialize(alloc); + return ret; +} + +/**************************************************************************** + * Name: usbmsc_bindlun + * + * Description: + * Bind the block driver specified by drvrpath to a USB storage LUN. + * + * Input Parameters: + * handle - The handle returned by a previous call to usbmsc_configure(). + * drvrpath - the full path to the block driver + * startsector - A sector offset into the block driver to the start of the + * partition on drvrpath (0 if no partitions) + * nsectors - The number of sectors in the partition (if 0, all sectors + * to the end of the media will be exported). + * lunno - the LUN to bind to + * + * Returned Value: + * 0 on success; a negated errno on failure. + * + ****************************************************************************/ + +int usbmsc_bindlun(FAR void *handle, FAR const char *drvrpath, + unsigned int lunno, off_t startsector, size_t nsectors, + bool readonly) +{ + FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle; + FAR struct usbmsc_dev_s *priv; + FAR struct usbmsc_lun_s *lun; + FAR struct inode *inode; + struct geometry geo; + int ret; + +#ifdef CONFIG_DEBUG + if (!alloc || !drvrpath || startsector < 0 || nsectors < 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BINLUNINVALIDARGS1), 0); + return -EINVAL; + } +#endif + + priv = &alloc->dev; + +#ifdef CONFIG_DEBUG + if (!priv->luntab) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_INTERNALCONFUSION1), 0); + return -EIO; + } + + if (lunno > priv->nluns) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BINDLUNINVALIDARGS2), 0); + return -EINVAL; + } +#endif + + lun = &priv->luntab[lunno]; + +#ifdef CONFIG_DEBUG + if (lun->inode != NULL) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_LUNALREADYBOUND), 0); + return -EBUSY; + } +#endif + + /* Open the block driver */ + + ret = open_blockdriver(drvrpath, 0, &inode); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BLKDRVEOPEN), 0); + return ret; + } + + /* Get the drive geometry */ + + if (!inode || !inode->u.i_bops || !inode->u.i_bops->geometry || + inode->u.i_bops->geometry(inode, &geo) != OK || !geo.geo_available) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_NOGEOMETRY), 0); + return -ENODEV; + } + + /* Verify that the partition parameters are valid */ + + if (startsector >= geo.geo_nsectors) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BINDLUNINVALIDARGS3), 0); + return -EDOM; + } + else if (nsectors == 0) + { + nsectors = geo.geo_nsectors - startsector; + } + else if (startsector + nsectors >= geo.geo_nsectors) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BINDLUNINVALIDARGS4), 0); + return -EDOM; + } + + /* Initialize the LUN structure */ + + memset(lun, 0, sizeof(struct usbmsc_lun_s *)); + + /* Allocate an I/O buffer big enough to hold one hardware sector. SCSI commands + * are processed one at a time so all LUNs may share a single I/O buffer. The + * I/O buffer will be allocated so that is it as large as the largest block + * device sector size + */ + + if (!priv->iobuffer) + { + priv->iobuffer = (uint8_t*)kmalloc(geo.geo_sectorsize); + if (!priv->iobuffer) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALLOCIOBUFFER), geo.geo_sectorsize); + return -ENOMEM; + } + priv->iosize = geo.geo_sectorsize; + } + else if (priv->iosize < geo.geo_sectorsize) + { + void *tmp; + tmp = (uint8_t*)realloc(priv->iobuffer, geo.geo_sectorsize); + if (!tmp) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_REALLOCIOBUFFER), geo.geo_sectorsize); + return -ENOMEM; + } + + priv->iobuffer = (uint8_t*)tmp; + priv->iosize = geo.geo_sectorsize; + } + + lun->inode = inode; + lun->startsector = startsector; + lun->nsectors = nsectors; + lun->sectorsize = geo.geo_sectorsize; + + /* If the driver does not support the write method, then this is read-only */ + + if (!inode->u.i_bops->write) + { + lun->readonly = true; + } + return OK; +} + +/**************************************************************************** + * Name: usbmsc_unbindlun + * + * Description: + * Un-bind the block driver for the specified LUN + * + * Input Parameters: + * handle - The handle returned by a previous call to usbmsc_configure(). + * lun - the LUN to unbind from + * + * Returned Value: + * 0 on success; a negated errno on failure. + * + ****************************************************************************/ + +int usbmsc_unbindlun(FAR void *handle, unsigned int lunno) +{ + FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle; + FAR struct usbmsc_dev_s *priv; + FAR struct usbmsc_lun_s *lun; + int ret; + +#ifdef CONFIG_DEBUG + if (!alloc) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNBINDLUNINVALIDARGS1), 0); + return -EINVAL; + } +#endif + + priv = &alloc->dev; + +#ifdef CONFIG_DEBUG + if (!priv->luntab) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_INTERNALCONFUSION2), 0); + return -EIO; + } + + if (lunno > priv->nluns) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNBINDLUNINVALIDARGS2), 0); + return -EINVAL; + } +#endif + + lun = &priv->luntab[lunno]; + pthread_mutex_lock(&priv->mutex); + +#ifdef CONFIG_DEBUG + if (lun->inode == NULL) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_LUNNOTBOUND), 0); + ret = -EBUSY; + } + else +#endif + { + /* Close the block driver */ + + usbmsc_lununinitialize(lun); + ret = OK; + } + + pthread_mutex_unlock(&priv->mutex); + return ret; +} + +/**************************************************************************** + * Name: usbmsc_exportluns + * + * Description: + * After all of the LUNs have been bound, this function may be called + * in order to export those LUNs in the USB storage device. + * + * Input Parameters: + * handle - The handle returned by a previous call to usbmsc_configure(). + * + * Returned Value: + * 0 on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_USBMSC_COMPOSITE +static +#endif +int usbmsc_exportluns(FAR void *handle) +{ + FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle; + FAR struct usbmsc_dev_s *priv; + FAR struct usbmsc_driver_s *drvr; + irqstate_t flags; +#ifdef SDCC + pthread_attr_t attr; +#endif + int ret; + +#ifdef CONFIG_DEBUG + if (!alloc) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EXPORTLUNSINVALIDARGS), 0); + return -ENXIO; + } +#endif + + priv = &alloc->dev; + drvr = &alloc->drvr; + + /* Start the worker thread */ + + pthread_mutex_lock(&priv->mutex); + priv->thstate = USBMSC_STATE_NOTSTARTED; + priv->theventset = USBMSC_EVENT_NOEVENTS; + +#ifdef SDCC + (void)pthread_attr_init(&attr); + ret = pthread_create(&priv->thread, &attr, usbmsc_workerthread, (pthread_addr_t)priv); +#else + ret = pthread_create(&priv->thread, NULL, usbmsc_workerthread, (pthread_addr_t)priv); +#endif + if (ret != OK) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_THREADCREATE), (uint16_t)-ret); + goto errout_with_mutex; + } + + /* Register the USB storage class driver (unless we are part of a composite device) */ + +#ifndef CONFIG_USBMSC_COMPOSITE + ret = usbdev_register(&drvr->drvr); + if (ret != OK) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_DEVREGISTER), (uint16_t)-ret); + goto errout_with_mutex; + } +#endif + + /* Signal to start the thread */ + + flags = irqsave(); + priv->theventset |= USBMSC_EVENT_READY; + pthread_cond_signal(&priv->cond); + irqrestore(flags); + +errout_with_mutex: + pthread_mutex_unlock(&priv->mutex); + return ret; +} + +/**************************************************************************** + * Name: usbmsc_classobject + * + * Description: + * Register USB mass storage device and return the class object. + * + * Input Parameters: + * classdev - The location to return the CDC serial class' device + * instance. + * + * Returned Value: + * 0 on success; a negated errno on failure + + * + ****************************************************************************/ + +#ifdef CONFIG_USBMSC_COMPOSITE +int usbmsc_classobject(FAR void *handle, + FAR struct usbdevclass_driver_s **classdev) +{ + FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle; + int ret; + + DEBUGASSERT(handle && classdev); + + /* Export the LUNs as with the "standalone" USB mass storage driver, but + * don't register the class instance with the USB device infrastructure. + */ + + ret = usbmsc_exportluns(handle); + if (ret == OK) + { + /* On sucess, return an (typed) instance of the class instance */ + + *classdev = &alloc->drvr.drvr; + } + return ret; +} +#endif + +/**************************************************************************** + * Name: usbmsc_uninitialize + * + * Description: + * Un-initialize the USB storage class driver + * + * Input Parameters: + * handle - The handle returned by a previous call to usbmsc_configure(). + * + * Returned Value: + * None + * + ****************************************************************************/ + +void usbmsc_uninitialize(FAR void *handle) +{ + FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle; + FAR struct usbmsc_dev_s *priv; + irqstate_t flags; +#ifdef SDCC + pthread_addr_t result1, result2; + pthread_attr_t attr; +#endif + void *value; + int i; + +#ifdef CONFIG_DEBUG + if (!handle) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNINITIALIZEINVALIDARGS), 0); + return; + } +#endif + priv = &alloc->dev; + + /* If the thread hasn't already exitted, tell it to exit now */ + + if (priv->thstate != USBMSC_STATE_NOTSTARTED) + { + /* The thread was started.. Is it still running? */ + + pthread_mutex_lock(&priv->mutex); + if (priv->thstate != USBMSC_STATE_TERMINATED) + { + /* Yes.. Ask the thread to stop */ + + flags = irqsave(); + priv->theventset |= USBMSC_EVENT_TERMINATEREQUEST; + pthread_cond_signal(&priv->cond); + irqrestore(flags); + } + pthread_mutex_unlock(&priv->mutex); + + /* Wait for the thread to exit. This is necessary even if the + * thread has already exitted in order to collect the join + * garbage + */ + + (void)pthread_join(priv->thread, &value); + } + priv->thread = 0; + + /* Unregister the driver (unless we are a part of a composite device */ + +#ifndef CONFIG_USBMSC_COMPOSITE + usbdev_unregister(&alloc->drvr.drvr); +#endif + + /* Uninitialize and release the LUNs */ + + for (i = 0; i < priv->nluns; ++i) + { + usbmsc_lununinitialize(&priv->luntab[i]); + } + kfree(priv->luntab); + + /* Release the I/O buffer */ + + if (priv->iobuffer) + { + kfree(priv->iobuffer); + } + + /* Uninitialize and release the driver structure */ + + pthread_mutex_destroy(&priv->mutex); + pthread_cond_destroy(&priv->cond); + + kfree(priv); +} diff --git a/nuttx/drivers/usbdev/usbmsc.h b/nuttx/drivers/usbdev/usbmsc.h new file mode 100644 index 0000000000..6a5530d9d9 --- /dev/null +++ b/nuttx/drivers/usbdev/usbmsc.h @@ -0,0 +1,694 @@ +/**************************************************************************** + * drivers/usbdev/usbmsc.h + * + * Copyright (C) 2008-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Mass storage class device. Bulk-only with SCSI subclass. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_USBDEV_USBMSC_H +#define __DRIVERS_USBDEV_USBMSC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* If the USB mass storage device is configured as part of a composite device + * then both CONFIG_USBDEV_COMPOSITE and CONFIG_USBMSC_COMPOSITE must be + * defined. + */ + +#ifndef CONFIG_USBDEV_COMPOSITE +# undef CONFIG_USBMSC_COMPOSITE +#endif + +#if defined(CONFIG_USBMSC_COMPOSITE) && !defined(CONFIG_USBMSC_STRBASE) +# define CONFIG_USBMSC_STRBASE (4) +#endif + +/* Interface IDs. If the mass storage driver is built as a component of a + * composite device, then the interface IDs may need to be offset. + */ + +#ifndef CONFIG_USBMSC_COMPOSITE +# undef CONFIG_USBMSC_IFNOBASE +# define CONFIG_USBMSC_IFNOBASE 0 +#endif + +#ifndef CONFIG_USBMSC_IFNOBASE +# define CONFIG_USBMSC_IFNOBASE 0 +#endif + +/* Number of requests in the write queue */ + +#ifndef CONFIG_USBMSC_NWRREQS +# define CONFIG_USBMSC_NWRREQS 4 +#endif + +/* Number of requests in the read queue */ + +#ifndef CONFIG_USBMSC_NRDREQS +# define CONFIG_USBMSC_NRDREQS 4 +#endif + +/* Logical endpoint numbers / max packet sizes */ + +#ifndef CONFIG_USBMSC_EPBULKOUT +# warning "EPBULKOUT not defined in the configuration" +# define CONFIG_USBMSC_EPBULKOUT 2 +#endif + +#ifndef CONFIG_USBMSC_EPBULKIN +# warning "EPBULKIN not defined in the configuration" +# define CONFIG_USBMSC_EPBULKIN 3 +#endif + +/* Packet and request buffer sizes */ + +#ifndef CONFIG_USBMSC_COMPOSITE +# ifndef CONFIG_USBMSC_EP0MAXPACKET +# define CONFIG_USBMSC_EP0MAXPACKET 64 +# endif +#endif + +#ifndef CONFIG_USBMSC_BULKINREQLEN +# ifdef CONFIG_USBDEV_DUALSPEED +# define CONFIG_USBMSC_BULKINREQLEN 512 +# else +# define CONFIG_USBMSC_BULKINREQLEN 64 +# endif +#else +# ifdef CONFIG_USBDEV_DUALSPEED +# if CONFIG_USBMSC_BULKINREQLEN < 512 +# warning "Bulk in buffer size smaller than max packet" +# undef CONFIG_USBMSC_BULKINREQLEN +# define CONFIG_USBMSC_BULKINREQLEN 512 +# endif +# else +# if CONFIG_USBMSC_BULKINREQLEN < 64 +# warning "Bulk in buffer size smaller than max packet" +# undef CONFIG_USBMSC_BULKINREQLEN +# define CONFIG_USBMSC_BULKINREQLEN 64 +# endif +# endif +#endif + +#ifndef CONFIG_USBMSC_BULKOUTREQLEN +# ifdef CONFIG_USBDEV_DUALSPEED +# define CONFIG_USBMSC_BULKOUTREQLEN 512 +# else +# define CONFIG_USBMSC_BULKOUTREQLEN 64 +# endif +#else +# ifdef CONFIG_USBDEV_DUALSPEED +# if CONFIG_USBMSC_BULKOUTREQLEN < 512 +# warning "Bulk in buffer size smaller than max packet" +# undef CONFIG_USBMSC_BULKOUTREQLEN +# define CONFIG_USBMSC_BULKOUTREQLEN 512 +# endif +# else +# if CONFIG_USBMSC_BULKOUTREQLEN < 64 +# warning "Bulk in buffer size smaller than max packet" +# undef CONFIG_USBMSC_BULKOUTREQLEN +# define CONFIG_USBMSC_BULKOUTREQLEN 64 +# endif +# endif +#endif + +/* Vendor and product IDs and strings */ + +#ifndef CONFIG_USBMSC_COMPOSITE +# ifndef CONFIG_USBMSC_VENDORID +# warning "CONFIG_USBMSC_VENDORID not defined" +# define CONFIG_USBMSC_VENDORID 0x584e +# endif + +# ifndef CONFIG_USBMSC_PRODUCTID +# warning "CONFIG_USBMSC_PRODUCTID not defined" +# define CONFIG_USBMSC_PRODUCTID 0x5342 +# endif + +# ifndef CONFIG_USBMSC_VERSIONNO +# define CONFIG_USBMSC_VERSIONNO (0x0399) +# endif + +# ifndef CONFIG_USBMSC_VENDORSTR +# warning "No Vendor string specified" +# define CONFIG_USBMSC_VENDORSTR "NuttX" +# endif + +# ifndef CONFIG_USBMSC_PRODUCTSTR +# warning "No Product string specified" +# define CONFIG_USBMSC_PRODUCTSTR "USBdev Storage" +# endif + +# undef CONFIG_USBMSC_SERIALSTR +# define CONFIG_USBMSC_SERIALSTR "0101" +#endif + +#undef CONFIG_USBMSC_CONFIGSTR +#define CONFIG_USBMSC_CONFIGSTR "Bulk" + +/* Debug -- must be consistent with include/debug.h */ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_DEBUG +# ifdef CONFIG_ARCH_LOWPUTC +# define dbgprintf(format, arg...) lib_lowprintf(format, ##arg) +# else +# define dbgprintf(format, arg...) lib_rawprintf(format, ##arg) +# endif +# else +# define dbgprintf(x...) +# endif +#else +# ifdef CONFIG_DEBUG +# ifdef CONFIG_ARCH_LOWPUTC +# define dbgprintf lib_lowprintf +# else +# define dbgprintf lib_rawprintf +# endif +# else +# define dbgprintf (void) +# endif +#endif + +/* Packet and request buffer sizes */ + +#ifndef CONFIG_USBMSC_EP0MAXPACKET +# define CONFIG_USBMSC_EP0MAXPACKET 64 +#endif + +/* USB Controller */ + +#ifndef CONFIG_USBDEV_SELFPOWERED +# define SELFPOWERED USB_CONFIG_ATT_SELFPOWER +#else +# define SELFPOWERED (0) +#endif + +#ifndef CONFIG_USBDEV_REMOTEWAKEUP +# define REMOTEWAKEUP USB_CONFIG_ATTR_WAKEUP +#else +# define REMOTEWAKEUP (0) +#endif + +#ifndef CONFIG_USBDEV_MAXPOWER +# define CONFIG_USBDEV_MAXPOWER 100 +#endif + +/* Current state of the worker thread */ + +#define USBMSC_STATE_NOTSTARTED (0) /* Thread has not yet been started */ +#define USBMSC_STATE_STARTED (1) /* Started, but is not yet initialized */ +#define USBMSC_STATE_IDLE (2) /* Started and waiting for commands */ +#define USBMSC_STATE_CMDPARSE (3) /* Processing a received command */ +#define USBMSC_STATE_CMDREAD (4) /* Processing a SCSI read command */ +#define USBMSC_STATE_CMDWRITE (5) /* Processing a SCSI write command */ +#define USBMSC_STATE_CMDFINISH (6) /* Finish command processing */ +#define USBMSC_STATE_CMDSTATUS (7) /* Processing the final status of the command */ +#define USBMSC_STATE_TERMINATED (8) /* Thread has exitted */ + +/* Event communicated to worker thread */ + +#define USBMSC_EVENT_NOEVENTS (0) /* There are no outstanding events */ +#define USBMSC_EVENT_READY (1 << 0) /* Initialization is complete */ +#define USBMSC_EVENT_RDCOMPLETE (1 << 1) /* A read has completed there is data to be processed */ +#define USBMSC_EVENT_WRCOMPLETE (1 << 2) /* A write has completed and a request is available */ +#define USBMSC_EVENT_TERMINATEREQUEST (1 << 3) /* Shutdown requested */ +#define USBMSC_EVENT_DISCONNECT (1 << 4) /* USB disconnect received */ +#define USBMSC_EVENT_RESET (1 << 5) /* USB storage setup reset received */ +#define USBMSC_EVENT_CFGCHANGE (1 << 6) /* USB setup configuration change received */ +#define USBMSC_EVENT_IFCHANGE (1 << 7) /* USB setup interface change received */ +#define USBMSC_EVENT_ABORTBULKOUT (1 << 8) /* SCSI receive failure */ + +/* SCSI command flags (passed to usbmsc_setupcmd()) */ + +#define USBMSC_FLAGS_DIRMASK (0x03) /* Bits 0-1: Data direction */ +#define USBMSC_FLAGS_DIRNONE (0x00) /* No data to send */ +#define USBMSC_FLAGS_DIRHOST2DEVICE (0x01) /* Host-to-device */ +#define USBMSC_FLAGS_DIRDEVICE2HOST (0x02) /* Device-to-host */ +#define USBMSC_FLAGS_BLOCKXFR (0x04) /* Bit 2: Command is a block transfer request */ +#define USBMSC_FLAGS_LUNNOTNEEDED (0x08) /* Bit 3: Command does not require a valid LUN */ +#define USBMSC_FLAGS_UACOKAY (0x10) /* Bit 4: Command OK if unit attention condition */ +#define USBMSC_FLAGS_RETAINSENSEDATA (0x20) /* Bit 5: Do not clear sense data */ + +/* Descriptors **************************************************************/ + +/* Big enough to hold our biggest descriptor */ + +#define USBMSC_MXDESCLEN (64) + +/* String language */ + +#define USBMSC_STR_LANGUAGE (0x0409) /* en-us */ + +/* Descriptor strings */ + +#ifndef CONFIG_USBMSC_COMPOSITE +# define USBMSC_MANUFACTURERSTRID (1) +# define USBMSC_PRODUCTSTRID (2) +# define USBMSC_SERIALSTRID (3) +# define USBMSC_CONFIGSTRID (4) +# define USBMSC_INTERFACESTRID USBMSC_CONFIGSTRID + +# undef CONFIG_USBMSC_STRBASE +# define CONFIG_USBMSC_STRBASE (0) +#else +# define USBMSC_INTERFACESTRID (CONFIG_USBMSC_STRBASE+1) +#endif + +#define USBMSC_LASTSTRID USBMSC_INTERFACESTRID +#define USBMSC_NSTRIDS (USBMSC_LASTSTRID - CONFIG_USBMSC_STRBASE) + +#define USBMSC_NCONFIGS (1) /* Number of configurations supported */ + +/* Configuration Descriptor */ + +#define USBMSC_NINTERFACES (1) /* Number of interfaces in the configuration */ +#define USBMSC_INTERFACEID (CONFIG_USBMSC_IFNOBASE+0) +#define USBMSC_ALTINTERFACEID (0) + +#define USBMSC_CONFIGIDNONE (0) /* Config ID means to return to address mode */ +#define USBMSC_CONFIGID (1) /* The only supported configuration ID */ + +/* Interface description */ + +#define USBMSC_NENDPOINTS (2) /* Number of endpoints in the interface */ + +/* Endpoint configuration */ + +#define USBMSC_EPOUTBULK_ADDR (CONFIG_USBMSC_EPBULKOUT) +#define USBMSC_EPOUTBULK_ATTR (USB_EP_ATTR_XFER_BULK) + +#define USBMSC_EPINBULK_ADDR (USB_DIR_IN|CONFIG_USBMSC_EPBULKIN) +#define USBMSC_EPINBULK_ATTR (USB_EP_ATTR_XFER_BULK) + +#define USBMSC_HSBULKMAXPACKET (512) +#define USBMSC_HSBULKMXPKTSHIFT (9) +#define USBMSC_HSBULKMXPKTMASK (0x000001ff) +#define USBMSC_FSBULKMAXPACKET (64) +#define USBMSC_FSBULKMXPKTSHIFT (6) +#define USBMSC_FSBULKMXPKTMASK (0x0000003f) + +/* Macros for dual speed vs. full speed only operation */ + +#ifdef CONFIG_USBDEV_DUALSPEED +# define USBMSC_EPBULKINDESC(hs) \ + usbmsc_getepdesc((hs) ? USBMSC_EPHSBULKIN : USBMSC_EPFSBULKIN) +# define USBMSC_EPBULKOUTDESC(hs) \ + usbmsc_getepdesc((hs) ? USBMSC_EPHSBULKOUT : USBMSC_EPFSBULKOUT) +# define USBMSC_BULKMAXPACKET(hs) \ + ((hs) ? USBMSC_HSBULKMAXPACKET : USBMSC_FSBULKMAXPACKET) +# define USBMSC_BULKMXPKTSHIFT(d) \ + (((d)->speed==USB_SPEED_HIGH) ? USBMSC_HSBULKMXPKTSHIFT : USBMSC_FSBULKMXPKTSHIFT) +# define USBMSC_BULKMXPKTMASK(d) \ + (((d)->speed==USB_SPEED_HIGH) ? USBMSC_HSBULKMXPKTMASK : USBMSC_FSBULKMXPKTMASK) +#else +# define USBMSC_EPBULKINDESC(d) usbmsc_getepdesc(USBMSC_EPFSBULKIN) +# define USBMSC_EPBULKOUTDESC(d) usbmsc_getepdesc(USBMSC_EPFSBULKOUT) +# define USBMSC_BULKMAXPACKET(hs) USBMSC_FSBULKMAXPACKET +# define USBMSC_BULKMXPKTSHIFT(d) USBMSC_FSBULKMXPKTSHIFT +# define USBMSC_BULKMXPKTMASK(d) USBMSC_FSBULKMXPKTMASK +#endif + +/* Configuration descriptor size */ + +#ifndef CONFIG_USBMSC_COMPOSITE + +/* Number of individual descriptors in the configuration descriptor: + * (1) Configuration descriptor + (1) interface descriptor + (2) interface + * descriptors. + */ + +# define USBMSC_CFGGROUP_SIZE (4) + +/* The size of the config descriptor: (9 + 9 + 2*7) = 32 */ + +# define SIZEOF_USBMSC_CFGDESC \ + (USB_SIZEOF_CFGDESC + USB_SIZEOF_IFDESC + USBMSC_NENDPOINTS * USB_SIZEOF_EPDESC) + +#else + +/* Number of individual descriptors in the configuration descriptor: + * (1) interface descriptor + (2) interface descriptors. + */ + +# define USBMSC_CFGGROUP_SIZE (3) + +/* The size of the config descriptor: (9 + 2*7) = 23 */ + +# define SIZEOF_USBMSC_CFGDESC \ + (USB_SIZEOF_IFDESC + USBMSC_NENDPOINTS * USB_SIZEOF_EPDESC) + +#endif + +/* Block driver helpers *****************************************************/ + +#define USBMSC_DRVR_READ(l,b,s,n) ((l)->inode->u.i_bops->read((l)->inode,b,s,n)) +#define USBMSC_DRVR_WRITE(l,b,s,n) ((l)->inode->u.i_bops->write((l)->inode,b,s,n)) +#define USBMSC_DRVR_GEOMETRY(l,g) ((l)->inode->u.i_bops->geometry((l)->inode,g)) + +/* Everpresent MIN/MAX macros ***********************************************/ + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* Endpoint descriptors */ + +enum usbmsc_epdesc_e +{ + USBMSC_EPFSBULKOUT = 0, /* Full speed bulk OUT endpoint descriptor */ + USBMSC_EPFSBULKIN /* Full speed bulk IN endpoint descriptor */ +#ifdef CONFIG_USBDEV_DUALSPEED + , + USBMSC_EPHSBULKOUT, /* High speed bulk OUT endpoint descriptor */ + USBMSC_EPHSBULKIN /* High speed bulk IN endpoint descriptor */ +#endif +}; + +/* Container to support a list of requests */ + +struct usbmsc_req_s +{ + FAR struct usbmsc_req_s *flink; /* Implements a singly linked list */ + FAR struct usbdev_req_s *req; /* The contained request */ +}; + +/* This structure describes one LUN: */ + +struct usbmsc_lun_s +{ + struct inode *inode; /* Inode structure of open'ed block driver */ + uint8_t readonly:1; /* Media is read-only */ + uint8_t locked:1; /* Media removal is prevented */ + uint16_t sectorsize; /* The size of one sector */ + uint32_t sd; /* Sense data */ + uint32_t sdinfo; /* Sense data information */ + uint32_t uad; /* Unit needs attention data */ + off_t startsector; /* Sector offset to start of partition */ + size_t nsectors; /* Number of sectors in the partition */ +}; + +/* Describes the overall state of the driver */ + +struct usbmsc_dev_s +{ + FAR struct usbdev_s *usbdev; /* usbdev driver pointer (Non-null if registered) */ + + /* Worker thread interface */ + + pthread_t thread; /* The worker thread */ + pthread_mutex_t mutex; /* Mutually exclusive access to resources*/ + pthread_cond_t cond; /* Used to signal worker thread */ + volatile uint8_t thstate; /* State of the worker thread */ + volatile uint16_t theventset; /* Set of pending events signaled to worker thread */ + volatile uint8_t thvalue; /* Value passed with the event (must persist) */ + + /* Storage class configuration and state */ + + uint8_t nluns:4; /* Number of LUNs */ + uint8_t config; /* Configuration number */ + + /* Endpoints */ + + FAR struct usbdev_ep_s *epbulkin; /* Bulk IN endpoint structure */ + FAR struct usbdev_ep_s *epbulkout; /* Bulk OUT endpoint structure */ + FAR struct usbdev_req_s *ctrlreq; /* Control request (for ep0 setup responses) */ + + /* SCSI command processing */ + + struct usbmsc_lun_s *lun; /* Currently selected LUN */ + struct usbmsc_lun_s *luntab; /* Allocated table of all LUNs */ + uint8_t cdb[USBMSC_MAXCDBLEN]; /* Command data (cdb[]) from CBW */ + uint8_t phaseerror:1; /* Need to send phase sensing status */ + uint8_t shortpacket:1; /* Host transmission stopped unexpectedly */ + uint8_t cbwdir:2; /* Direction from CBW. See USBMSC_FLAGS_DIR* definitions */ + uint8_t cdblen; /* Length of cdb[] from CBW */ + uint8_t cbwlun; /* LUN from the CBW */ + uint16_t nsectbytes; /* Bytes buffered in iobuffer[] */ + uint16_t nreqbytes; /* Bytes buffered in head write requests */ + uint16_t iosize; /* Size of iobuffer[] */ + uint32_t cbwlen; /* Length of data from CBW */ + uint32_t cbwtag; /* Tag from the CBW */ + union + { + uint32_t xfrlen; /* Read/Write: Sectors remaining to be transferred */ + uint32_t alloclen; /* Other device-to-host: Host allocation length */ + } u; + uint32_t sector; /* Current sector (relative to lun->startsector) */ + uint32_t residue; /* Untransferred amount reported in the CSW */ + uint8_t *iobuffer; /* Buffer for data transfers */ + + /* Write request list */ + + struct sq_queue_s wrreqlist; /* List of empty write request containers */ + struct sq_queue_s rdreqlist; /* List of filled read request containers */ + + /* Pre-allocated write request containers. The write requests will + * be linked in a free list (wrreqlist), and used to send requests to + * EPBULKIN; Read requests will be queued in the EBULKOUT. + */ + + struct usbmsc_req_s wrreqs[CONFIG_USBMSC_NWRREQS]; + struct usbmsc_req_s rdreqs[CONFIG_USBMSC_NRDREQS]; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" +{ +#else +# define EXTERN extern +#endif + +/* String *******************************************************************/ + +/* Mass storage class vendor/product/serial number strings */ + +#ifndef CONFIG_USBMSC_COMPOSITE +EXTERN const char g_mscvendorstr[]; +EXTERN const char g_mscproductstr[]; +EXTERN const char g_mscserialstr[]; + +/* If we are using a composite device, then vendor/product/serial number strings + * are provided by the composite device logic. + */ + +#else +EXTERN const char g_compvendorstr[]; +EXTERN const char g_compproductstr[]; +EXTERN const char g_compserialstr[]; + +#define g_mscvendorstr g_compvendorstr +#define g_mscproductstr g_compproductstr +#define g_mscserialstr g_compserialstr +#endif +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +/************************************************************************************ + * Name: usbmsc_mkstrdesc + * + * Description: + * Construct a string descriptor + * + ************************************************************************************/ + +struct usb_strdesc_s; +int usbmsc_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc); + +/************************************************************************************ + * Name: usbmsc_getepdesc + * + * Description: + * Return a pointer to the raw device descriptor + * + ************************************************************************************/ + +#ifndef CONFIG_USBMSC_COMPOSITE +FAR const struct usb_devdesc_s *usbmsc_getdevdesc(void); +#endif + +/************************************************************************************ + * Name: usbmsc_getepdesc + * + * Description: + * Return a pointer to the raw endpoint descriptor (used for configuring endpoints) + * + ************************************************************************************/ + +struct usb_epdesc_s; +FAR const struct usb_epdesc_s *usbmsc_getepdesc(enum usbmsc_epdesc_e epid); + +/************************************************************************************ + * Name: usbmsc_mkcfgdesc + * + * Description: + * Construct the configuration descriptor + * + ************************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +int16_t usbmsc_mkcfgdesc(FAR uint8_t *buf, uint8_t speed, uint8_t type); +#else +int16_t usbmsc_mkcfgdesc(FAR uint8_t *buf); +#endif + +/************************************************************************************ + * Name: usbmsc_getqualdesc + * + * Description: + * Return a pointer to the raw qual descriptor + * + ************************************************************************************/ + +#if !defined(CONFIG_USBMSC_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED) +FAR const struct usb_qualdesc_s *usbmsc_getqualdesc(void); +#endif + +/**************************************************************************** + * Name: usbmsc_workerthread + * + * Description: + * This is the main function of the USB storage worker thread. It loops + * until USB-related events occur, then processes those events accordingly + * + ****************************************************************************/ + +EXTERN void *usbmsc_workerthread(void *arg); + +/**************************************************************************** + * Name: usbmsc_setconfig + * + * Description: + * Set the device configuration by allocating and configuring endpoints and + * by allocating and queue read and write requests. + * + ****************************************************************************/ + +EXTERN int usbmsc_setconfig(FAR struct usbmsc_dev_s *priv, uint8_t config); + +/**************************************************************************** + * Name: usbmsc_resetconfig + * + * Description: + * Mark the device as not configured and disable all endpoints. + * + ****************************************************************************/ + +EXTERN void usbmsc_resetconfig(FAR struct usbmsc_dev_s *priv); + +/**************************************************************************** + * Name: usbmsc_wrcomplete + * + * Description: + * Handle completion of write request. This function probably executes + * in the context of an interrupt handler. + * + ****************************************************************************/ + +EXTERN void usbmsc_wrcomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); + +/**************************************************************************** + * Name: usbmsc_rdcomplete + * + * Description: + * Handle completion of read request on the bulk OUT endpoint. This + * is handled like the receipt of serial data on the "UART" + * + ****************************************************************************/ + +EXTERN void usbmsc_rdcomplete(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); + +/**************************************************************************** + * Name: usbmsc_deferredresponse + * + * Description: + * Some EP0 setup request cannot be responded to immediately becuase they + * require some asynchronous action from the SCSI worker thread. This + * function is provided for the SCSI thread to make that deferred response. + * The specific requests that require this deferred response are: + * + * 1. USB_REQ_SETCONFIGURATION, + * 2. USB_REQ_SETINTERFACE, or + * 3. USBMSC_REQ_MSRESET + * + * In all cases, the success reponse is a zero-length packet; the failure + * response is an EP0 stall. + * + * Input parameters: + * priv - Private state structure for this USB storage instance + * stall - true is the action failed and a stall is required + * + ****************************************************************************/ + +EXTERN void usbmsc_deferredresponse(FAR struct usbmsc_dev_s *priv, bool failed); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* #define __DRIVERS_USBDEV_USBMSC_H */ diff --git a/nuttx/drivers/usbdev/usbmsc_desc.c b/nuttx/drivers/usbdev/usbmsc_desc.c new file mode 100644 index 0000000000..6d7561b3f1 --- /dev/null +++ b/nuttx/drivers/usbdev/usbmsc_desc.c @@ -0,0 +1,421 @@ +/**************************************************************************** + * drivers/usbdev/usbmsc_desc.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "usbmsc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* Descriptors **************************************************************/ +/* Device descriptor. If the USB mass storage device is configured as part + * of a composite device, then the device descriptor will be provided by the + * composite device logic. + */ + +#ifndef CONFIG_USBMSC_COMPOSITE +static const struct usb_devdesc_s g_devdesc = +{ + USB_SIZEOF_DEVDESC, /* len */ + USB_DESC_TYPE_DEVICE, /* type */ + {LSBYTE(0x0200), MSBYTE(0x0200)}, /* usb */ + USB_CLASS_PER_INTERFACE, /* classid */ + 0, /* subclass */ + 0, /* protocol */ + CONFIG_USBMSC_EP0MAXPACKET, /* maxpacketsize */ + { /* vendor */ + LSBYTE(CONFIG_USBMSC_VENDORID), + MSBYTE(CONFIG_USBMSC_VENDORID) + }, + { /* product */ + LSBYTE(CONFIG_USBMSC_PRODUCTID), + MSBYTE(CONFIG_USBMSC_PRODUCTID) }, + { /* device */ + LSBYTE(CONFIG_USBMSC_VERSIONNO), + MSBYTE(CONFIG_USBMSC_VERSIONNO) + }, + USBMSC_MANUFACTURERSTRID, /* imfgr */ + USBMSC_PRODUCTSTRID, /* iproduct */ + USBMSC_SERIALSTRID, /* serno */ + USBMSC_NCONFIGS /* nconfigs */ +}; +#endif + +/* Configuration descriptor If the USB mass storage device is configured as part + * of a composite device, then the configuration descriptor will be provided by the + * composite device logic. + */ + +#ifndef CONFIG_USBMSC_COMPOSITE +static const struct usb_cfgdesc_s g_cfgdesc = +{ + USB_SIZEOF_CFGDESC, /* len */ + USB_DESC_TYPE_CONFIG, /* type */ + { /* totallen */ + LSBYTE(SIZEOF_USBMSC_CFGDESC), + MSBYTE(SIZEOF_USBMSC_CFGDESC) + }, + USBMSC_NINTERFACES, /* ninterfaces */ + USBMSC_CONFIGID, /* cfgvalue */ + USBMSC_CONFIGSTRID, /* icfg */ + USB_CONFIG_ATTR_ONE|SELFPOWERED|REMOTEWAKEUP, /* attr */ + (CONFIG_USBDEV_MAXPOWER + 1) / 2 /* mxpower */ +}; +#endif + +/* Single interface descriptor */ + +static const struct usb_ifdesc_s g_ifdesc = +{ + USB_SIZEOF_IFDESC, /* len */ + USB_DESC_TYPE_INTERFACE, /* type */ + USBMSC_INTERFACEID, /* ifno */ + USBMSC_ALTINTERFACEID, /* alt */ + USBMSC_NENDPOINTS, /* neps */ + USB_CLASS_MASS_STORAGE, /* classid */ + USBMSC_SUBCLASS_SCSI, /* subclass */ + USBMSC_PROTO_BULKONLY, /* protocol */ + USBMSC_INTERFACESTRID /* iif */ +}; + +/* Endpoint descriptors */ + +static const struct usb_epdesc_s g_fsepbulkoutdesc = +{ + USB_SIZEOF_EPDESC, /* len */ + USB_DESC_TYPE_ENDPOINT, /* type */ + USBMSC_EPOUTBULK_ADDR, /* addr */ + USBMSC_EPOUTBULK_ATTR, /* attr */ + { /* maxpacket */ + LSBYTE(USBMSC_FSBULKMAXPACKET), + MSBYTE(USBMSC_FSBULKMAXPACKET) + }, + 0 /* interval */ +}; + +static const struct usb_epdesc_s g_fsepbulkindesc = +{ + USB_SIZEOF_EPDESC, /* len */ + USB_DESC_TYPE_ENDPOINT, /* type */ + USBMSC_EPINBULK_ADDR, /* addr */ + USBMSC_EPINBULK_ATTR, /* attr */ + { /* maxpacket */ + LSBYTE(USBMSC_FSBULKMAXPACKET), + MSBYTE(USBMSC_FSBULKMAXPACKET) + }, + 0 /* interval */ +}; + +#ifdef CONFIG_USBDEV_DUALSPEED +#ifndef CONFIG_USBMSC_COMPOSITE +static const struct usb_qualdesc_s g_qualdesc = +{ + USB_SIZEOF_QUALDESC, /* len */ + USB_DESC_TYPE_DEVICEQUALIFIER, /* type */ + { /* usb */ + LSBYTE(0x0200), + MSBYTE(0x0200) + }, + USB_CLASS_PER_INTERFACE, /* classid */ + 0, /* subclass */ + 0, /* protocol */ + CONFIG_USBMSC_EP0MAXPACKET, /* mxpacketsize */ + USBMSC_NCONFIGS, /* nconfigs */ + 0, /* reserved */ +}; +#endif + +static const struct usb_epdesc_s g_hsepbulkoutdesc = +{ + USB_SIZEOF_EPDESC, /* len */ + USB_DESC_TYPE_ENDPOINT, /* type */ + USBMSC_EPOUTBULK_ADDR, /* addr */ + USBMSC_EPOUTBULK_ATTR, /* attr */ + { /* maxpacket */ + LSBYTE(USBMSC_HSBULKMAXPACKET), + MSBYTE(USBMSC_HSBULKMAXPACKET) + }, + 0 /* interval */ +}; + +static const struct usb_epdesc_s g_hsepbulkindesc = +{ + USB_SIZEOF_EPDESC, /* len */ + USB_DESC_TYPE_ENDPOINT, /* type */ + USBMSC_EPINBULK_ADDR, /* addr */ + USBMSC_EPINBULK_ATTR, /* attr */ + { /* maxpacket */ + LSBYTE(USBMSC_HSBULKMAXPACKET), + MSBYTE(USBMSC_HSBULKMAXPACKET) + }, + 0 /* interval */ +}; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ +/* Strings ******************************************************************/ + +#ifndef CONFIG_USBMSC_COMPOSITE +const char g_mscvendorstr[] = CONFIG_USBMSC_VENDORSTR; +const char g_mscproductstr[] = CONFIG_USBMSC_PRODUCTSTR; +const char g_mscserialstr[] = CONFIG_USBMSC_SERIALSTR; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbmsc_mkstrdesc + * + * Description: + * Construct a string descriptor + * + ****************************************************************************/ + +int usbmsc_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc) +{ + const char *str; + int len; + int ndata; + int i; + + switch (id) + { +#ifndef CONFIG_USBMSC_COMPOSITE + case 0: + { + /* Descriptor 0 is the language id */ + + strdesc->len = 4; + strdesc->type = USB_DESC_TYPE_STRING; + strdesc->data[0] = LSBYTE(USBMSC_STR_LANGUAGE); + strdesc->data[1] = MSBYTE(USBMSC_STR_LANGUAGE); + return 4; + } + + case USBMSC_MANUFACTURERSTRID: + str = g_mscvendorstr; + break; + + case USBMSC_PRODUCTSTRID: + str = g_mscproductstr; + break; + + case USBMSC_SERIALSTRID: + str = g_mscserialstr; + break; +#endif + + /* case USBMSC_CONFIGSTRID: */ + case USBMSC_INTERFACESTRID: + str = CONFIG_USBMSC_CONFIGSTR; + break; + + default: + return -EINVAL; + } + + /* The string is utf16-le. The poor man's utf-8 to utf16-le + * conversion below will only handle 7-bit en-us ascii + */ + + len = strlen(str); + for (i = 0, ndata = 0; i < len; i++, ndata += 2) + { + strdesc->data[ndata] = str[i]; + strdesc->data[ndata+1] = 0; + } + + strdesc->len = ndata+2; + strdesc->type = USB_DESC_TYPE_STRING; + return strdesc->len; +} + +/**************************************************************************** + * Name: usbmsc_getepdesc + * + * Description: + * Return a pointer to the raw device descriptor + * + ****************************************************************************/ + +#ifndef CONFIG_USBMSC_COMPOSITE +FAR const struct usb_devdesc_s *usbmsc_getdevdesc(void) +{ + return &g_devdesc; +} +#endif + +/**************************************************************************** + * Name: usbmsc_getepdesc + * + * Description: + * Return a pointer to the raw endpoint descriptor (used for configuring + * endpoints) + * + ****************************************************************************/ + +FAR const struct usb_epdesc_s *usbmsc_getepdesc(enum usbmsc_epdesc_e epid) +{ + switch (epid) + { + case USBMSC_EPFSBULKOUT: /* Full speed bulk OUT endpoint descriptor */ + return &g_fsepbulkoutdesc; + + case USBMSC_EPFSBULKIN: /* Full speed bulk IN endpoint descriptor */ + return &g_fsepbulkindesc; + +#ifdef CONFIG_USBDEV_DUALSPEED + case USBMSC_EPHSBULKOUT: /* High speed bulk OUT endpoint descriptor */ + return &g_hsepbulkoutdesc; + + case USBMSC_EPHSBULKIN: /* High speed bulk IN endpoint descriptor */ + return &g_hsepbulkindesc; +#endif + default: + return NULL; + } +}; + +/**************************************************************************** + * Name: usbmsc_mkcfgdesc + * + * Description: + * Construct the configuration descriptor + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DUALSPEED +int16_t usbmsc_mkcfgdesc(uint8_t *buf, uint8_t speed, uint8_t type) +#else +int16_t usbmsc_mkcfgdesc(uint8_t *buf) +#endif +{ +#ifdef CONFIG_USBDEV_DUALSPEED + FAR const struct usb_epdesc_s *epdesc; + bool hispeed = (speed == USB_SPEED_HIGH); + uint16_t bulkmxpacket; +#endif + + /* Configuration descriptor. If the USB mass storage device is + * configured as part of a composite device, then the configuration + * descriptor will be provided by the composite device logic. + */ + +#ifndef CONFIG_USBMSC_COMPOSITE + memcpy(buf, &g_cfgdesc, USB_SIZEOF_CFGDESC); + buf += USB_SIZEOF_CFGDESC; +#endif + + /* Copy the canned interface descriptor */ + + memcpy(buf, &g_ifdesc, USB_SIZEOF_IFDESC); + buf += USB_SIZEOF_IFDESC; + + /* Make the two endpoint configurations */ + +#ifdef CONFIG_USBDEV_DUALSPEED + /* Check for switches between high and full speed */ + + hispeed = (speed == USB_SPEED_HIGH); + if (type == USB_DESC_TYPE_OTHERSPEEDCONFIG) + { + hispeed = !hispeed; + } + + bulkmxpacket = USBMSC_BULKMAXPACKET(hispeed); + epdesc = USBMSC_EPBULKINDESC(hispeed); + memcpy(buf, epdesc, USB_SIZEOF_EPDESC); + buf += USB_SIZEOF_EPDESC; + + epdesc = USBMSC_EPBULKOUTDESC(hispeed); + memcpy(buf, epdesc, USB_SIZEOF_EPDESC); +#else + memcpy(buf, &g_fsepbulkoutdesc, USB_SIZEOF_EPDESC); + buf += USB_SIZEOF_EPDESC; + memcpy(buf, &g_fsepbulkindesc, USB_SIZEOF_EPDESC); +#endif + + return SIZEOF_USBMSC_CFGDESC; +} + +/**************************************************************************** + * Name: usbmsc_getqualdesc + * + * Description: + * Return a pointer to the raw qual descriptor + * + ****************************************************************************/ + +#if !defined(CONFIG_USBMSC_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED) +FAR const struct usb_qualdesc_s *usbmsc_getqualdesc(void) +{ + return &g_qualdesc; +} +#endif + diff --git a/nuttx/drivers/usbdev/usbmsc_scsi.c b/nuttx/drivers/usbdev/usbmsc_scsi.c new file mode 100644 index 0000000000..ccc9676189 --- /dev/null +++ b/nuttx/drivers/usbdev/usbmsc_scsi.c @@ -0,0 +1,2667 @@ +/**************************************************************************** + * drivers/usbdev/usbmsc_scsi.c + * + * Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Mass storage class device. Bulk-only with SCSI subclass. + * + * References: + * "Universal Serial Bus Mass Storage Class, Specification Overview," + * Revision 1.2, USB Implementer's Forum, June 23, 2003. + * + * "Universal Serial Bus Mass Storage Class, Bulk-Only Transport," + * Revision 1.0, USB Implementer's Forum, September 31, 1999. + * + * "SCSI Primary Commands - 3 (SPC-3)," American National Standard + * for Information Technology, May 4, 2005 + * + * "SCSI Primary Commands - 4 (SPC-4)," American National Standard + * for Information Technology, July 19, 2008 + * + * "SCSI Block Commands -2 (SBC-2)," American National Standard + * for Information Technology, November 13, 2004 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "usbmsc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Race condition workaround found by David Hewson. This race condition + * "seems to relate to stalling the endpoint when a short response is + * generated which causes a residue to exist when the CSW would be returned. + * I think there's two issues here. The first being if the transfer which + * had just been queued before the stall had not completed then it wouldn’t + * then complete once the endpoint was stalled? The second is that the + * subsequent transfer for the CSW would be dropped on the floor (by the + * epsubmit() function) if the end point was still stalled as the control + * transfer to resume it hadn't occurred." + */ + +#define CONFIG_USBMSC_RACEWAR 1 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Debug ********************************************************************/ + +#if defined(CONFIG_DEBUG_VERBOSE) && defined (CONFIG_DEBUG_USB) +static void usbmsc_dumpdata(const char *msg, const uint8_t *buf, + int buflen); +#else +# define usbmsc_dumpdata(msg, buf, len) +#endif + +/* Utility Support Functions ************************************************/ + +static uint16_t usbmsc_getbe16(uint8_t *buf); +static uint32_t usbmsc_getbe32(uint8_t *buf); +static void usbmsc_putbe16(uint8_t * buf, uint16_t val); +static void usbmsc_putbe24(uint8_t *buf, uint32_t val); +static void usbmsc_putbe32(uint8_t *buf, uint32_t val); +#if 0 /* not used */ +static uint16_t usbmsc_getle16(uint8_t *buf); +#endif +static uint32_t usbmsc_getle32(uint8_t *buf); +#if 0 /* not used */ +static void usbmsc_putle16(uint8_t * buf, uint16_t val); +#endif +static void usbmsc_putle32(uint8_t *buf, uint32_t val); + +/* SCSI Command Processing **************************************************/ + +static inline int usbmsc_cmdtestunitready(FAR struct usbmsc_dev_s *priv); +static inline int usbmsc_cmdrequestsense(FAR struct usbmsc_dev_s *priv, + FAR uint8_t *buf); +static inline int usbmsc_cmdread6(FAR struct usbmsc_dev_s *priv); +static inline int usbmsc_cmdwrite6(FAR struct usbmsc_dev_s *priv); +static inline int usbmsc_cmdinquiry(FAR struct usbmsc_dev_s *priv, + FAR uint8_t *buf); +static inline int usbmsc_cmdmodeselect6(FAR struct usbmsc_dev_s *priv); +static int usbmsc_modepage(FAR struct usbmsc_dev_s *priv, + FAR uint8_t *buf, uint8_t pcpgcode, int *mdlen); +static inline int usbmsc_cmdmodesense6(FAR struct usbmsc_dev_s *priv, + FAR uint8_t *buf); +static inline int usbmsc_cmdstartstopunit(FAR struct usbmsc_dev_s *priv); +static inline int usbmsc_cmdpreventmediumremoval(FAR struct usbmsc_dev_s *priv); +static inline int usbmsc_cmdreadformatcapacity(FAR struct usbmsc_dev_s *priv, + FAR uint8_t *buf); +static inline int usbmsc_cmdreadcapacity10(FAR struct usbmsc_dev_s *priv, + FAR uint8_t *buf); +static inline int usbmsc_cmdread10(FAR struct usbmsc_dev_s *priv); +static inline int usbmsc_cmdwrite10(FAR struct usbmsc_dev_s *priv); +static inline int usbmsc_cmdverify10(FAR struct usbmsc_dev_s *priv); +static inline int usbmsc_cmdsynchronizecache10(FAR struct usbmsc_dev_s *priv); +static inline int usbmsc_cmdmodeselect10(FAR struct usbmsc_dev_s *priv); +static inline int usbmsc_cmdmodesense10(FAR struct usbmsc_dev_s *priv, + FAR uint8_t *buf); +static inline int usbmsc_cmdread12(FAR struct usbmsc_dev_s *priv); +static inline int usbmsc_cmdwrite12(FAR struct usbmsc_dev_s *priv); +static inline int usbmsc_setupcmd(FAR struct usbmsc_dev_s *priv, + uint8_t cdblen, uint8_t flags); + +/* SCSI Worker Thread *******************************************************/ + +static int usbmsc_idlestate(FAR struct usbmsc_dev_s *priv); +static int usbmsc_cmdparsestate(FAR struct usbmsc_dev_s *priv); +static int usbmsc_cmdreadstate(FAR struct usbmsc_dev_s *priv); +static int usbmsc_cmdwritestate(FAR struct usbmsc_dev_s *priv); +static int usbmsc_cmdfinishstate(FAR struct usbmsc_dev_s *priv); +static int usbmsc_cmdstatusstate(FAR struct usbmsc_dev_s *priv); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Debug + ****************************************************************************/ + +/**************************************************************************** + * Name: usbmsc_dumpdata + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_VERBOSE) && defined (CONFIG_DEBUG_USB) +static void usbmsc_dumpdata(const char *msg, const uint8_t *buf, int buflen) +{ + int i; + + dbgprintf("%s:", msg); + for (i = 0; i < buflen; i++) + { + dbgprintf(" %02x", buf[i]); + } + dbgprintf("\n"); +} +#endif + +/**************************************************************************** + * Utility Support Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbmsc_getbe16 + * + * Description: + * Get a 16-bit big-endian value reference by the byte pointer + * + ****************************************************************************/ + +static uint16_t usbmsc_getbe16(uint8_t *buf) +{ + return ((uint16_t)buf[0] << 8) | ((uint16_t)buf[1]); +} + +/**************************************************************************** + * Name: usbmsc_getbe32 + * + * Description: + * Get a 32-bit big-endian value reference by the byte pointer + * + ****************************************************************************/ + +static uint32_t usbmsc_getbe32(uint8_t *buf) +{ + return ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | + ((uint32_t)buf[2] << 8) | ((uint32_t)buf[3]); +} + +/**************************************************************************** + * Name: usbmsc_putbe16 + * + * Description: + * Store a 16-bit value in big-endian order to the location specified by + * a byte pointer + * + ****************************************************************************/ + +static void usbmsc_putbe16(uint8_t * buf, uint16_t val) +{ + buf[0] = val >> 8; + buf[1] = val; +} + +/**************************************************************************** + * Name: usbmsc_putbe24 + * + * Description: + * Store a 32-bit value in big-endian order to the location specified by + * a byte pointer + * + ****************************************************************************/ + +static void usbmsc_putbe24(uint8_t *buf, uint32_t val) +{ + buf[0] = val >> 16; + buf[1] = val >> 8; + buf[2] = val; +} + +/**************************************************************************** + * Name: usbmsc_putbe32 + * + * Description: + * Store a 32-bit value in big-endian order to the location specified by + * a byte pointer + * + ****************************************************************************/ + +static void usbmsc_putbe32(uint8_t *buf, uint32_t val) +{ + buf[0] = val >> 24; + buf[1] = val >> 16; + buf[2] = val >> 8; + buf[3] = val; +} + +/**************************************************************************** + * Name: usbmsc_getle16 + * + * Description: + * Get a 16-bit little-endian value reference by the byte pointer + * + ****************************************************************************/ + +#if 0 /* not used */ +static uint16_t usbmsc_getle16(uint8_t *buf) +{ + return ((uint16_t)buf[1] << 8) | ((uint16_t)buf[0]); +} +#endif + +/**************************************************************************** + * Name: usbmsc_getle32 + * + * Description: + * Get a 32-bit little-endian value reference by the byte pointer + * + ****************************************************************************/ + +static uint32_t usbmsc_getle32(uint8_t *buf) +{ + return ((uint32_t)buf[3] << 24) | ((uint32_t)buf[2] << 16) | + ((uint32_t)buf[1] << 8) | ((uint32_t)buf[0]); +} + +/**************************************************************************** + * Name: usbmsc_putle16 + * + * Description: + * Store a 16-bit value in little-endian order to the location specified by + * a byte pointer + * + ****************************************************************************/ + +#if 0 /* not used */ +static void usbmsc_putle16(uint8_t * buf, uint16_t val) +{ + buf[0] = val; + buf[1] = val >> 8; +} +#endif + +/**************************************************************************** + * Name: usbmsc_putle32 + * + * Description: + * Store a 32-bit value in little-endian order to the location specified by + * a byte pointer + * + ****************************************************************************/ + +static void usbmsc_putle32(uint8_t *buf, uint32_t val) +{ + buf[0] = val; + buf[1] = val >> 8; + buf[2] = val >> 16; + buf[3] = val >> 24; +} + +/**************************************************************************** + * SCSI Worker Thread + ****************************************************************************/ + +/**************************************************************************** + * Name: usbmsc_cmdtestunitready + * + * Description: + * Handle the SCSI_CMD_TESTUNITREADY command + * + ****************************************************************************/ + +static inline int usbmsc_cmdtestunitready(FAR struct usbmsc_dev_s *priv) +{ + int ret; + + priv->u.alloclen = 0; + ret = usbmsc_setupcmd(priv, 6, USBMSC_FLAGS_DIRNONE); + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdrequestsense + * + * Description: + * Handle the SCSI_CMD_REQUESTSENSE command + * + ****************************************************************************/ + +static inline int usbmsc_cmdrequestsense(FAR struct usbmsc_dev_s *priv, + FAR uint8_t *buf) +{ + FAR struct scsicmd_requestsense_s *request = (FAR struct scsicmd_requestsense_s *)priv->cdb; + FAR struct scsiresp_fixedsensedata_s *response = (FAR struct scsiresp_fixedsensedata_s *)buf; + FAR struct usbmsc_lun_s *lun; + uint32_t sd; + uint32_t sdinfo; + uint8_t cdblen; + int ret; + + /* Extract the host allocation length */ + + priv->u.alloclen = request->alloclen; + + /* Get the expected length of the command (with hack for MS-Windows 12-byte + * REQUEST SENSE command. + */ + + cdblen = SCSICMD_REQUESTSENSE_SIZEOF; + if (cdblen != priv->cdblen) + { + /* Try MS-Windows REQUEST SENSE with cbw->cdblen == 12 */ + + cdblen = SCSICMD_REQUESTSENSE_MSSIZEOF; + } + + ret = usbmsc_setupcmd(priv, cdblen, + USBMSC_FLAGS_DIRDEVICE2HOST|USBMSC_FLAGS_LUNNOTNEEDED| + USBMSC_FLAGS_UACOKAY|USBMSC_FLAGS_RETAINSENSEDATA); + if (ret == OK) + { + lun = priv->lun; + if (!lun) + { + sd = SCSI_KCQIR_INVALIDLUN; + sdinfo = 0; + } + else + { + /* Get the saved sense data from the LUN structure */ + + sd = lun->sd; + sdinfo = lun->sdinfo; + + /* Discard the sense data */ + + lun->sd = SCSI_KCQ_NOSENSE; + lun->sdinfo = 0; + } + + /* Create the fixed sense data response */ + + memset(response, 0, SCSIRESP_FIXEDSENSEDATA_SIZEOF); + + response->code = SCSIRESP_SENSEDATA_RESPVALID|SCSIRESP_SENSEDATA_CURRENTFIXED; + response->flags = (uint8_t)(sd >> 16); + usbmsc_putbe32(response->info, sdinfo); + response->len = SCSIRESP_FIXEDSENSEDATA_SIZEOF - 7; + response->code2 = (uint8_t)(sd >> 8); + response->qual2 = (uint8_t)sd; + + priv->nreqbytes = SCSIRESP_FIXEDSENSEDATA_SIZEOF; + ret = OK; + } + + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdread6 + * + * Description: + * Handle the SCSI_CMD_READ6 command + * + ****************************************************************************/ + +static inline int usbmsc_cmdread6(FAR struct usbmsc_dev_s *priv) +{ + FAR struct scsicmd_read6_s *read6 = (FAR struct scsicmd_read6_s*)priv->cdb; + FAR struct usbmsc_lun_s *lun = priv->lun; + int ret; + + priv->u.xfrlen = (uint16_t)read6->xfrlen; + if (priv->u.xfrlen == 0) + { + priv->u.xfrlen = 256; + } + + ret = usbmsc_setupcmd(priv, SCSICMD_READ6_SIZEOF, USBMSC_FLAGS_DIRDEVICE2HOST|USBMSC_FLAGS_BLOCKXFR); + if (ret == OK) + { + /* Get the Logical Block Address (LBA) from cdb[] as the starting sector */ + + priv->sector = (uint32_t)(read6->mslba & SCSICMD_READ6_MSLBAMASK) << 16 | (uint32_t)usbmsc_getbe16(read6->lslba); + + /* Verify that a block driver has been bound to the LUN */ + + if (!lun->inode) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_READ6MEDIANOTPRESENT), 0); + lun->sd = SCSI_KCQNR_MEDIANOTPRESENT; + ret = -EINVAL; + } + + /* Verify that sector lies in the range supported by the block driver */ + + else if (priv->sector >= lun->nsectors) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_READ6LBARANGE), 0); + lun->sd = SCSI_KCQIR_LBAOUTOFRANGE; + ret = -EINVAL; + } + + /* Looks like we are good to go */ + + else + { + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDPARSECMDREAD6), priv->cdb[0]); + priv->thstate = USBMSC_STATE_CMDREAD; + } + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdwrite6 + * + * Description: + * Handle the SCSI_CMD_WRITE6 command + * + ****************************************************************************/ + +static inline int usbmsc_cmdwrite6(FAR struct usbmsc_dev_s *priv) +{ + FAR struct scsicmd_write6_s *write6 = (FAR struct scsicmd_write6_s *)priv->cdb; + FAR struct usbmsc_lun_s *lun = priv->lun; + int ret; + + priv->u.xfrlen = (uint16_t)write6->xfrlen; + if (priv->u.xfrlen == 0) + { + priv->u.xfrlen = 256; + } + + ret = usbmsc_setupcmd(priv, SCSICMD_WRITE6_SIZEOF, USBMSC_FLAGS_DIRHOST2DEVICE|USBMSC_FLAGS_BLOCKXFR); + if (ret == OK) + { + /* Get the Logical Block Address (LBA) from cdb[] as the starting sector */ + + priv->sector = (uint32_t)(write6->mslba & SCSICMD_WRITE6_MSLBAMASK) << 16 | (uint32_t)usbmsc_getbe16(write6->lslba); + + /* Verify that a block driver has been bound to the LUN */ + + if (!lun->inode) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE6MEDIANOTPRESENT), 0); + lun->sd = SCSI_KCQNR_MEDIANOTPRESENT; + ret = -EINVAL; + } + + /* Check for attempts to write to a read-only device */ + + else if (lun->readonly) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE6READONLY), 0); + lun->sd = SCSI_KCQWP_COMMANDNOTALLOWED; + ret = -EINVAL; + } + + /* Verify that sector lies in the range supported by the block driver */ + + else if (priv->sector >= lun->nsectors) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE6LBARANGE), 0); + lun->sd = SCSI_KCQIR_LBAOUTOFRANGE; + ret = -EINVAL; + } + + /* Looks like we are good to go */ + + else + { + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDPARSECMDWRITE6), priv->cdb[0]); + priv->thstate = USBMSC_STATE_CMDWRITE; + } + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdinquiry + * + * Description: + * Handle SCSI_CMD_INQUIRY command + * + ****************************************************************************/ + +static inline int usbmsc_cmdinquiry(FAR struct usbmsc_dev_s *priv, + FAR uint8_t *buf) +{ + FAR struct scscicmd_inquiry_s *inquiry = (FAR struct scscicmd_inquiry_s *)priv->cdb; + FAR struct scsiresp_inquiry_s *response = (FAR struct scsiresp_inquiry_s *)buf; + int len; + int ret; + + priv->u.alloclen = usbmsc_getbe16(inquiry->alloclen); + ret = usbmsc_setupcmd(priv, SCSICMD_INQUIRY_SIZEOF, + USBMSC_FLAGS_DIRDEVICE2HOST|USBMSC_FLAGS_LUNNOTNEEDED|USBMSC_FLAGS_UACOKAY); + if (ret == OK) + { + if (!priv->lun) + { + response->qualtype = SCSIRESP_INQUIRYPQ_NOTCAPABLE|SCSIRESP_INQUIRYPD_UNKNOWN; + } + else if ((inquiry->flags != 0) || (inquiry->pagecode != 0)) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_INQUIRYFLAGS), 0); + priv->lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA; + ret = -EINVAL; + } + else + { + memset(response, 0, SCSIRESP_INQUIRY_SIZEOF); + priv->nreqbytes = SCSIRESP_INQUIRY_SIZEOF; + +#ifdef CONFIG_USBMSC_REMOVABLE + response->flags1 = SCSIRESP_INQUIRYFLAGS1_RMB; +#endif + response->version = 2; /* SCSI-2 */ + response->flags2 = 2; /* SCSI-2 INQUIRY response data format */ + response->len = SCSIRESP_INQUIRY_SIZEOF - 5; + + /* Strings */ + + memset(response->vendorid, ' ', 8+16+4); + + len = strlen(g_mscvendorstr); + DEBUGASSERT(len <= 8); + memcpy(response->vendorid, g_mscvendorstr, len); + + len = strlen(g_mscproductstr); + DEBUGASSERT(len <= 16); + memcpy(response->productid, g_mscproductstr, len); + + len = strlen(g_mscserialstr); + DEBUGASSERT(len <= 4); + memcpy(response->revision, g_mscserialstr, len); + } + } + + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdmodeselect6 + * + * Description: + * Handle SCSI_CMD_MODESELECT6 command + * + ****************************************************************************/ + +static inline int usbmsc_cmdmodeselect6(FAR struct usbmsc_dev_s *priv) +{ + FAR struct scsicmd_modeselect6_s *modeselect = (FAR struct scsicmd_modeselect6_s *)priv->cdb; + + priv->u.alloclen = modeselect->plen; + (void)usbmsc_setupcmd(priv, SCSICMD_MODESELECT6_SIZEOF, USBMSC_FLAGS_DIRHOST2DEVICE); + + /* Not supported */ + + priv->lun->sd = SCSI_KCQIR_INVALIDCOMMAND; + return -EINVAL; +} + +/**************************************************************************** + * Name: usbmsc_modepage + * + * Description: + * Common logic for usbmsc_cmdmodesense6() and usbmsc_cmdmodesense10() + * + ****************************************************************************/ + +static int usbmsc_modepage(FAR struct usbmsc_dev_s *priv, FAR uint8_t *buf, + uint8_t pcpgcode, int *mdlen) +{ + FAR struct scsiresp_cachingmodepage_s *cmp = (FAR struct scsiresp_cachingmodepage_s *)buf; + + /* Saving parms not supported */ + + if ((pcpgcode & SCSICMD_MODESENSE_PCMASK) == SCSICMD_MODESENSE_PCSAVED) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_PCSAVED), 0); + priv->lun->sd = SCSI_KCQIR_SAVINGPARMSNOTSUPPORTED; + return -EINVAL; + } + + /* Only the caching mode page is supported: */ + + if ((pcpgcode & SCSICMD_MODESENSE_PGCODEMASK) == SCSIRESP_MODESENSE_PGCCODE_CACHING || + (pcpgcode & SCSICMD_MODESENSE_PGCODEMASK) == SCSIRESP_MODESENSE_PGCCODE_RETURNALL) + { + memset(cmp, 0, 12); + cmp->pgcode = SCSIRESP_MODESENSE_PGCCODE_CACHING; + cmp->len = 10; /* n-2 */ + + /* None of the fields are changeable */ + + if (((pcpgcode & SCSICMD_MODESENSE_PCMASK) != SCSICMD_MODESENSE_PCCHANGEABLE)) + { + cmp->flags1 = SCSIRESP_CACHINGMODEPG_WCE; /* Write cache enable */ + cmp->dpflen[0] = 0xff; /* Disable prefetch transfer length = 0xffffffff */ + cmp->dpflen[1] = 0xff; + cmp->maxpf[0] = 0xff; /* Maximum pre-fetch = 0xffffffff */ + cmp->maxpf[1] = 0xff; + cmp->maxpfc[0] = 0xff; /* Maximum pref-fetch ceiling = 0xffffffff */ + cmp->maxpfc[1] = 0xff; + } + + /* Return the mode data length */ + + *mdlen = 12; /* Only the first 12-bytes of caching mode page sent */ + return OK; + } + else + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_MODEPAGEFLAGS), pcpgcode); + priv->lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA; + return -EINVAL; + } +} + +/**************************************************************************** + * Name: usbmsc_cmdmodesense6 + * + * Description: + * Handle SCSI_CMD_MODESENSE6 command + * + ****************************************************************************/ + +static int inline usbmsc_cmdmodesense6(FAR struct usbmsc_dev_s *priv, + FAR uint8_t *buf) +{ + FAR struct scsicmd_modesense6_s *modesense = (FAR struct scsicmd_modesense6_s *)priv->cdb; + FAR struct scsiresp_modeparameterhdr6_s *mph = (FAR struct scsiresp_modeparameterhdr6_s *)buf; + int mdlen; + int ret; + + priv->u.alloclen = modesense->alloclen; + ret = usbmsc_setupcmd(priv, SCSICMD_MODESENSE6_SIZEOF, USBMSC_FLAGS_DIRDEVICE2HOST); + if (ret == OK) + { + if ((modesense->flags & ~SCSICMD_MODESENSE6_DBD) != 0 || modesense->subpgcode != 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_MODESENSE6FLAGS), 0); + priv->lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA; + ret = -EINVAL; + } + else + { + /* The response consists of: + * + * (1) A MODESENSE6-specific mode parameter header, + * (2) A variable length list of block descriptors, and + * (3) A variable length list of mode page formats + */ + + mph->type = 0; /* Medium type */ + mph->param = (priv->lun->readonly ? SCSIRESP_MODEPARMHDR_DAPARM_WP : 0x00); + mph->bdlen = 0; /* Block descriptor length */ + + /* There are no block descriptors, only the following mode page: */ + + ret = usbmsc_modepage(priv, &buf[SCSIRESP_MODEPARAMETERHDR6_SIZEOF], modesense->pcpgcode, &mdlen); + if (ret == OK) + { + /* Store the mode data length and return the total message size */ + + mph->mdlen = mdlen - 1; + priv->nreqbytes = mdlen + SCSIRESP_MODEPARAMETERHDR6_SIZEOF; + } + } + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdstartstopunit + * + * Description: + * Handle SCSI_CMD_STARTSTOPUNIT command + * + ****************************************************************************/ + +static inline int usbmsc_cmdstartstopunit(FAR struct usbmsc_dev_s *priv) +{ + int ret; + + priv->u.alloclen = 0; + ret = usbmsc_setupcmd(priv, SCSICMD_STARTSTOPUNIT_SIZEOF, USBMSC_FLAGS_DIRNONE); + if (ret == OK) + { +#ifndef CONFIG_USBMSC_REMOVABLE + /* This command is not valid if the media is not removable */ + + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_NOTREMOVABLE), 0); + lun->sd = SCSI_KCQIR_INVALIDCOMMAND; + ret = -EINVAL; +#endif + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdpreventmediumremoval + * + * Description: + * Handle SCSI_CMD_PREVENTMEDIAREMOVAL command + * + ****************************************************************************/ + +static inline int usbmsc_cmdpreventmediumremoval(FAR struct usbmsc_dev_s *priv) +{ +#ifdef CONFIG_USBMSC_REMOVABLE + FAR struct scsicmd_preventmediumremoval_s *pmr = (FAR struct scsicmd_preventmediumremoval_s *)priv->cdb; + FAR struct usbmsc_lun_s *lun = priv->lun; +#endif + int ret; + + priv->u.alloclen = 0; + ret = usbmsc_setupcmd(priv, SCSICMD_PREVENTMEDIUMREMOVAL_SIZEOF, USBMSC_FLAGS_DIRNONE); + if (ret == OK) + { +#ifndef CONFIG_USBMSC_REMOVABLE + lun->sd = SCSI_KCQIR_INVALIDCOMMAND; + ret = -EINVAL; +#else + if ((pmr->prevent & ~SCSICMD_PREVENTMEDIUMREMOVAL_TRANSPORT) != 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_PREVENTMEDIUMREMOVALPREVENT), 0); + lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA; + ret = -EINVAL; + } + + lun->locked = pmr->prevent & SCSICMD_PREVENTMEDIUMREMOVAL_TRANSPORT; +#endif + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdreadformatcapacity + * + * Description: + * Handle SCSI_CMD_READFORMATCAPACITIES command (MMC) + * + ****************************************************************************/ + +static inline int usbmsc_cmdreadformatcapacity(FAR struct usbmsc_dev_s *priv, + FAR uint8_t *buf) +{ + FAR struct scsicmd_readformatcapcacities_s *rfc = (FAR struct scsicmd_readformatcapcacities_s *)priv->cdb; + FAR struct scsiresp_readformatcapacities_s *hdr; + FAR struct usbmsc_lun_s *lun = priv->lun; + int ret; + + priv->u.alloclen = usbmsc_getbe16(rfc->alloclen); + ret = usbmsc_setupcmd(priv, SCSICMD_READFORMATCAPACITIES_SIZEOF, USBMSC_FLAGS_DIRDEVICE2HOST); + if (ret == OK) + { + hdr = (FAR struct scsiresp_readformatcapacities_s *)buf; + memset(hdr, 0, SCSIRESP_READFORMATCAPACITIES_SIZEOF); + hdr->listlen = SCSIRESP_CURRCAPACITYDESC_SIZEOF; + + /* Only the Current/Maximum Capacity Descriptor follows the header */ + + usbmsc_putbe32(hdr->nblocks, lun->nsectors); + hdr->type = SCIRESP_RDFMTCAPACITIES_FORMATED; + usbmsc_putbe24(hdr->blocklen, lun->sectorsize); + priv->nreqbytes = SCSIRESP_READFORMATCAPACITIES_SIZEOF; + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdreadcapacity10 + * + * Description: + * Handle SCSI_CMD_READCAPACITY10 command + * + ****************************************************************************/ + +static int inline usbmsc_cmdreadcapacity10(FAR struct usbmsc_dev_s *priv, + FAR uint8_t *buf) +{ + FAR struct scsicmd_readcapacity10_s *rcc = (FAR struct scsicmd_readcapacity10_s *)priv->cdb; + FAR struct scsiresp_readcapacity10_s *rcr = (FAR struct scsiresp_readcapacity10_s *)buf; + FAR struct usbmsc_lun_s *lun = priv->lun; + uint32_t lba; + int ret; + + priv->u.alloclen = SCSIRESP_READCAPACITY10_SIZEOF; /* Fake the allocation length */ + ret = usbmsc_setupcmd(priv, SCSICMD_READCAPACITY10_SIZEOF, USBMSC_FLAGS_DIRDEVICE2HOST); + if (ret == OK) + { + /* Check the PMI and LBA fields */ + + lba = usbmsc_getbe32(rcc->lba); + + if (rcc->pmi > 1 || (rcc->pmi == 0 && lba != 0)) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_READCAPACITYFLAGS), 0); + lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA; + ret = -EINVAL; + } + else + { + usbmsc_putbe32(rcr->lba, lun->nsectors - 1); + usbmsc_putbe32(&buf[4], lun->sectorsize); + priv->nreqbytes = SCSIRESP_READCAPACITY10_SIZEOF; + } + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdread10 + * + * Description: + * Handle SCSI_CMD_READ10 command + * + ****************************************************************************/ + +static inline int usbmsc_cmdread10(FAR struct usbmsc_dev_s *priv) +{ + struct scsicmd_read10_s *read10 = (struct scsicmd_read10_s*)priv->cdb; + FAR struct usbmsc_lun_s *lun = priv->lun; + int ret; + + priv->u.xfrlen = usbmsc_getbe16(read10->xfrlen); + ret = usbmsc_setupcmd(priv, SCSICMD_READ10_SIZEOF, USBMSC_FLAGS_DIRDEVICE2HOST|USBMSC_FLAGS_BLOCKXFR); + if (ret == OK) + { + /* Get the Logical Block Address (LBA) from cdb[] as the starting sector */ + + priv->sector = usbmsc_getbe32(read10->lba); + + /* Verify that we can support this read command */ + + if ((read10->flags & ~(SCSICMD_READ10FLAGS_DPO|SCSICMD_READ10FLAGS_FUA)) != 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_READ10FLAGS), 0); + lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA; + ret = -EINVAL; + } + + /* Verify that a block driver has been bound to the LUN */ + + else if (!lun->inode) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_READ10MEDIANOTPRESENT), 0); + lun->sd = SCSI_KCQNR_MEDIANOTPRESENT; + ret = -EINVAL; + } + + /* Verify that LBA lies in the range supported by the block driver */ + + else if (priv->sector >= lun->nsectors) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_READ10LBARANGE), 0); + lun->sd = SCSI_KCQIR_LBAOUTOFRANGE; + ret = -EINVAL; + } + + /* Looks like we are good to go */ + + else + { + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDPARSECMDREAD10), priv->cdb[0]); + priv->thstate = USBMSC_STATE_CMDREAD; + } + } + + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdwrite10 + * + * Description: + * Handle SCSI_CMD_WRITE10 command + * + ****************************************************************************/ + +static inline int usbmsc_cmdwrite10(FAR struct usbmsc_dev_s *priv) +{ + struct scsicmd_write10_s *write10 = (struct scsicmd_write10_s *)priv->cdb; + FAR struct usbmsc_lun_s *lun = priv->lun; + int ret; + + priv->u.xfrlen = usbmsc_getbe16(write10->xfrlen); + ret = usbmsc_setupcmd(priv, SCSICMD_WRITE10_SIZEOF, USBMSC_FLAGS_DIRHOST2DEVICE|USBMSC_FLAGS_BLOCKXFR); + if (ret == OK) + { + /* Get the Logical Block Address (LBA) from cdb[] as the starting sector */ + + priv->sector = usbmsc_getbe32(write10->lba); + + /* Verify that we can support this write command */ + + if ((write10->flags & ~(SCSICMD_WRITE10FLAGS_DPO|SCSICMD_WRITE10FLAGS_FUA)) != 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE10FLAGS), 0); + lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA; + ret = -EINVAL; + } + + /* Verify that a block driver has been bound to the LUN */ + + else if (!lun->inode) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE10MEDIANOTPRESENT), 0); + lun->sd = SCSI_KCQNR_MEDIANOTPRESENT; + ret = -EINVAL; + } + + /* Check for attempts to write to a read-only device */ + + else if (lun->readonly) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE10READONLY), 0); + lun->sd = SCSI_KCQWP_COMMANDNOTALLOWED; + ret = -EINVAL; + } + + /* Verify that LBA lies in the range supported by the block driver */ + + else if (priv->sector >= lun->nsectors) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE10LBARANGE), 0); + lun->sd = SCSI_KCQIR_LBAOUTOFRANGE; + ret = -EINVAL; + } + + /* Looks like we are good to go */ + + else + { + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDPARSECMDWRITE10), priv->cdb[0]); + priv->thstate = USBMSC_STATE_CMDWRITE; + } + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdverify10 + * + * Description: + * Handle SCSI_CMD_VERIFY10 command + * + ****************************************************************************/ + +static inline int usbmsc_cmdverify10(FAR struct usbmsc_dev_s *priv) +{ + FAR struct scsicmd_verify10_s *verf = (FAR struct scsicmd_verify10_s *)priv->cdb; + FAR struct usbmsc_lun_s *lun = priv->lun; + uint32_t lba; + uint16_t blocks; + size_t sector; + ssize_t nread; + int ret; + int i; + + priv->u.alloclen = 0; + ret = usbmsc_setupcmd(priv, SCSICMD_VERIFY10_SIZEOF, USBMSC_FLAGS_DIRNONE); + if (ret == OK) + { + /* Verify the starting and ending LBA */ + + lba = usbmsc_getbe32(verf->lba); + blocks = usbmsc_getbe16(verf->len); + + if ((verf->flags & ~SCSICMD_VERIFY10_DPO) != 0 || verf->groupno != 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_VERIFY10FLAGS), 0); + lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA; + ret = -EINVAL; + } + else if (blocks == 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_VERIFY10NOBLOCKS), 0); + ret = -EIO; /* No reply */ + } + + /* Verify that a block driver has been bound to the LUN */ + + else if (!lun->inode) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_VERIFY10MEDIANOTPRESENT), 0); + lun->sd = SCSI_KCQNR_MEDIANOTPRESENT; + ret = -EINVAL; + } + + /* Verify that LBA lies in the range supported by the block driver */ + + else if (lba >= lun->nsectors || lba + blocks > lun->nsectors) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_VERIFY10LBARANGE), 0); + lun->sd = SCSI_KCQIR_LBAOUTOFRANGE; + ret = -EINVAL; + } + else + { + /* Try to read the requested blocks */ + + for (i = 0, sector = lba + lun->startsector; i < blocks; i++, sector++) + { + nread = USBMSC_DRVR_READ(lun, priv->iobuffer, sector, 1); + if (nread < 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_VERIFY10READFAIL), i); + lun->sd = SCSI_KCQME_UNRRE1; + lun->sdinfo = sector; + ret = -EIO; + break; + } + } + } + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdsynchronizecache10 + * + * Description: + * Handle SCSI_CMD_SYNCHCACHE10 command + * + ****************************************************************************/ + +static inline int usbmsc_cmdsynchronizecache10(FAR struct usbmsc_dev_s *priv) +{ + int ret; + + priv->u.alloclen = 0; + + /* Verify that we have the LUN structure and the block driver has been bound */ + + if (!priv->lun->inode) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_SYNCCACHEMEDIANOTPRESENT), 0); + priv->lun->sd = SCSI_KCQNR_MEDIANOTPRESENT; + ret = -EINVAL; + } + else + { + ret = usbmsc_setupcmd(priv, SCSICMD_SYNCHRONIZECACHE10_SIZEOF, USBMSC_FLAGS_DIRNONE); + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdmodeselect10 + * + * Description: + * Handle SCSI_CMD_MODESELECT10 command + * + ****************************************************************************/ + +static inline int usbmsc_cmdmodeselect10(FAR struct usbmsc_dev_s *priv) +{ + FAR struct scsicmd_modeselect10_s *modeselect = (FAR struct scsicmd_modeselect10_s *)priv->cdb; + + priv->u.alloclen = usbmsc_getbe16(modeselect->parmlen); + (void)usbmsc_setupcmd(priv, SCSICMD_MODESELECT10_SIZEOF, USBMSC_FLAGS_DIRHOST2DEVICE); + + /* Not supported */ + + priv->lun->sd = SCSI_KCQIR_INVALIDCOMMAND; + return -EINVAL; +} + +/**************************************************************************** + * Name: usbmsc_cmdmodesense10 + * + * Description: + * Handle SCSI_CMD_MODESENSE10 command + * + ****************************************************************************/ + +static int inline usbmsc_cmdmodesense10(FAR struct usbmsc_dev_s *priv, + FAR uint8_t *buf) +{ + FAR struct scsicmd_modesense10_s *modesense = (FAR struct scsicmd_modesense10_s *)priv->cdb; + FAR struct scsiresp_modeparameterhdr10_s *mph = (FAR struct scsiresp_modeparameterhdr10_s *)buf; + int mdlen; + int ret; + + priv->u.alloclen = usbmsc_getbe16(modesense->alloclen); + ret = usbmsc_setupcmd(priv, SCSICMD_MODESENSE10_SIZEOF, USBMSC_FLAGS_DIRDEVICE2HOST); + if (ret == OK) + { + if ((modesense->flags & ~SCSICMD_MODESENSE10_DBD) != 0 || modesense->subpgcode != 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_MODESENSE10FLAGS), 0); + priv->lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA; + ret = -EINVAL; + } + else + { + /* The response consists of: + * + * (1) A MODESENSE6-specific mode parameter header, + * (2) A variable length list of block descriptors, and + * (3) A variable lengtth list of mode page formats + */ + + memset(mph, 0, SCSIRESP_MODEPARAMETERHDR10_SIZEOF); + mph->param = (priv->lun->readonly ? SCSIRESP_MODEPARMHDR_DAPARM_WP : 0x00); + + /* There are no block descriptors, only the following mode page: */ + + ret = usbmsc_modepage(priv, &buf[SCSIRESP_MODEPARAMETERHDR10_SIZEOF], modesense->pcpgcode, &mdlen); + if (ret == OK) + { + /* Store the mode data length and return the total message size */ + + usbmsc_putbe16(mph->mdlen, mdlen - 2); + priv->nreqbytes = mdlen + SCSIRESP_MODEPARAMETERHDR10_SIZEOF; + } + } + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdread12 + * + * Description: + * Handle SCSI_CMD_READ12 command + * + ****************************************************************************/ + +static inline int usbmsc_cmdread12(FAR struct usbmsc_dev_s *priv) +{ + struct scsicmd_read12_s *read12 = (struct scsicmd_read12_s*)priv->cdb; + FAR struct usbmsc_lun_s *lun = priv->lun; + int ret; + + priv->u.xfrlen = usbmsc_getbe32(read12->xfrlen); + ret = usbmsc_setupcmd(priv, SCSICMD_READ12_SIZEOF, USBMSC_FLAGS_DIRDEVICE2HOST|USBMSC_FLAGS_BLOCKXFR); + if (ret == OK) + { + /* Get the Logical Block Address (LBA) from cdb[] as the starting sector */ + + priv->sector = usbmsc_getbe32(read12->lba); + + /* Verify that we can support this read command */ + + if ((read12->flags & ~(SCSICMD_READ12FLAGS_DPO|SCSICMD_READ12FLAGS_FUA)) != 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_READ12FLAGS), 0); + lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA; + ret = -EINVAL; + } + + /* Verify that a block driver has been bound to the LUN */ + + else if (!lun->inode) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_READ12MEDIANOTPRESENT), 0); + lun->sd = SCSI_KCQNR_MEDIANOTPRESENT; + ret = -EINVAL; + } + + /* Verify that LBA lies in the range supported by the block driver */ + + else if (priv->sector >= lun->nsectors) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_READ12LBARANGE), 0); + lun->sd = SCSI_KCQIR_LBAOUTOFRANGE; + ret = -EINVAL; + } + + /* Looks like we are good to go */ + + else + { + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDPARSECMDREAD12), priv->cdb[0]); + priv->thstate = USBMSC_STATE_CMDREAD; + } + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdwrite12 + * + * Description: + * Handle SCSI_CMD_WRITE12 command + * + ****************************************************************************/ + +static inline int usbmsc_cmdwrite12(FAR struct usbmsc_dev_s *priv) +{ + struct scsicmd_write12_s *write12 = (struct scsicmd_write12_s *)priv->cdb; + FAR struct usbmsc_lun_s *lun = priv->lun; + int ret; + + priv->u.xfrlen = usbmsc_getbe32(write12->xfrlen); + ret = usbmsc_setupcmd(priv, SCSICMD_WRITE12_SIZEOF, USBMSC_FLAGS_DIRHOST2DEVICE|USBMSC_FLAGS_BLOCKXFR); + if (ret == OK) + { + /* Get the Logical Block Address (LBA) from cdb[] as the starting sector */ + + priv->sector = usbmsc_getbe32(write12->lba); + + /* Verify that we can support this write command */ + + if ((write12->flags & ~(SCSICMD_WRITE12FLAGS_DPO|SCSICMD_WRITE12FLAGS_FUA)) != 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE12FLAGS), 0); + lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA; + } + + /* Verify that a block driver has been bound to the LUN */ + + else if (!lun->inode) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE12MEDIANOTPRESENT), 0); + lun->sd = SCSI_KCQNR_MEDIANOTPRESENT; + ret = -EINVAL; + } + + /* Check for attempts to write to a read-only device */ + + else if (lun->readonly) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE12READONLY), 0); + lun->sd = SCSI_KCQWP_COMMANDNOTALLOWED; + } + + /* Verify that LBA lies in the range supported by the block driver */ + + else if (priv->sector >= lun->nsectors) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE12LBARANGE), 0); + lun->sd = SCSI_KCQIR_LBAOUTOFRANGE; + } + + /* Looks like we are good to go */ + + else + { + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDPARSECMDWRITE12), priv->cdb[0]); + priv->thstate = USBMSC_STATE_CMDWRITE; + return OK; + } + } + + return ret; +} + +/**************************************************************************** + * Name: usbmsc_setupcmd + * + * Description: + * Called after each SCSI command is identified in order to perform setup + * and verification operations that are common to all SCSI commands. This + * function performs the following common setup operations: + * + * 1. Determine the direction of the response + * 2. Verify lengths + * 3. Setup and verify the LUN + * + * Includes special logic for INQUIRY and REQUESTSENSE commands + * + ****************************************************************************/ + +static int inline usbmsc_setupcmd(FAR struct usbmsc_dev_s *priv, uint8_t cdblen, uint8_t flags) +{ + FAR struct usbmsc_lun_s *lun = NULL; + uint32_t datlen; + uint8_t dir = flags & USBMSC_FLAGS_DIRMASK; + int ret = OK; + + /* Verify the LUN and set up the current LUN reference in the + * device structure + */ + + if (priv->cbwlun < priv->nluns) + { + /* LUN number is valid in a valid range, but the LUN is not necessarily + * bound to a block driver. That will be checked as necessary in each + * individual command. + */ + + lun = &priv->luntab[priv->cbwlun]; + priv->lun = lun; + } + + /* Only a few commands may specify unsupported LUNs */ + + else if ((flags & USBMSC_FLAGS_LUNNOTNEEDED) == 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDBADLUN), priv->cbwlun); + ret = -EINVAL; + } + + /* Extract the direction and data transfer length */ + + dir = flags & USBMSC_FLAGS_DIRMASK; /* Expected data direction */ + datlen = 0; + if ((flags & USBMSC_FLAGS_BLOCKXFR) == 0) + { + /* Non-block transfer. Data length: Host allocation to receive data + * (only for device-to-host transfers. At present, alloclen is set + * to zero for all host-to-device, non-block transfers. + */ + + datlen = priv->u.alloclen; + } + else if (lun) + { + /* Block transfer: Calculate the total size of all sectors to be transferred */ + + datlen = priv->u.alloclen * lun->sectorsize; + } + + /* Check the data direction. This was set up at the end of the + * IDLE state when the CBW was parsed, but if there is no data, + * then the direction is none. + */ + + if (datlen == 0) + { + /* No data.. then direction is none */ + + dir = USBMSC_FLAGS_DIRNONE; + } + + /* Compare the expected data length in the command to the data length + * in the CBW. + */ + + else if (priv->cbwlen < datlen) + { + /* Clip to the length in the CBW and declare a phase error */ + + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_PHASEERROR1), priv->cdb[0]); + if ((flags & USBMSC_FLAGS_BLOCKXFR) != 0) + { + priv->u.alloclen = priv->cbwlen; + } + else + { + priv->u.xfrlen = priv->cbwlen / lun->sectorsize; + } + + priv->phaseerror = 1; + } + + /* Initialize the residue */ + + priv->residue = priv->cbwlen; + + /* Conflicting data directions is a phase error */ + + if (priv->cbwdir != dir && datlen > 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_PHASEERROR2), priv->cdb[0]); + priv->phaseerror = 1; + ret = -EINVAL; + } + + /* Compare the length of data in the cdb[] with the expected length + * of the command. + */ + + if (cdblen != priv->cdblen) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_PHASEERROR3), priv->cdb[0]); + priv->phaseerror = 1; + ret = -EINVAL; + } + + if (lun) + { + /* Retain the sense data for the REQUEST SENSE command */ + + if ((flags & USBMSC_FLAGS_RETAINSENSEDATA) == 0) + { + /* Discard the sense data */ + + lun->sd = SCSI_KCQ_NOSENSE; + lun->sdinfo = 0; + } + + /* If a unit attention condition exists, then only a restricted set of + * commands is permitted. + */ + + if (lun->uad != SCSI_KCQ_NOSENSE && (flags & USBMSC_FLAGS_UACOKAY) != 0) + { + /* Command not permitted */ + + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDUNEVIOLATION), priv->cbwlun); + lun->sd = lun->uad; + lun->uad = SCSI_KCQ_NOSENSE; + ret = -EINVAL; + } + } + + /* The final, 1-byte field of every SCSI command is the Control field which + * must be zero + */ + + if (priv->cdb[cdblen-1] != 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_SCSICMDCONTROL), 0); + if (lun) + { + lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA; + } + ret = -EINVAL; + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_idlestate + * + * Description: + * Called from the worker thread in the USBMSC_STATE_IDLE state. Checks + * for the receipt of a bulk CBW. + * + * Returned value: + * If no new, valid CBW is available, this function returns a negated errno. + * Otherwise, when a new CBW is successfully parsed, this function sets + * priv->thstate to USBMSC_STATE_CMDPARSE and returns OK. + * + ****************************************************************************/ + +static int usbmsc_idlestate(FAR struct usbmsc_dev_s *priv) +{ + FAR struct usbmsc_req_s *privreq; + FAR struct usbdev_req_s *req; + FAR struct usbmsc_cbw_s *cbw; + irqstate_t flags; + int ret = -EINVAL; + + /* Take a request from the rdreqlist */ + + flags = irqsave(); + privreq = (FAR struct usbmsc_req_s *)sq_remfirst(&priv->rdreqlist); + irqrestore(flags); + + /* Has anything been received? If not, just return an error. + * This will cause us to remain in the IDLE state. When a USB request is + * received, the worker thread will be awakened in the USBMSC_STATE_IDLE + * and we will be called again. + */ + + if (!privreq) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_IDLERDREQLISTEMPTY), 0); + return -ENOMEM; + } + + req = privreq->req; + cbw = (FAR struct usbmsc_cbw_s *)req->buf; + + /* Handle the CBW */ + + usbmsc_dumpdata("SCSCI CBW", (uint8_t*)cbw, USBMSC_CBW_SIZEOF - USBMSC_MAXCDBLEN); + usbmsc_dumpdata(" CDB", cbw->cdb, MIN(cbw->cdblen, USBMSC_MAXCDBLEN)); + + /* Check for properly formatted CBW? */ + + if (req->xfrd != USBMSC_CBW_SIZEOF || + cbw->signature[0] != 'U' || + cbw->signature[1] != 'S' || + cbw->signature[2] != 'B' || + cbw->signature[3] != 'C') + { + /* CBS BAD: Stall the bulk endpoints. If the CBW is bad we must stall the + * bulk IN endpoint and either (1) stall the bulk OUT endpoint, or + * (2) discard data from the endpoint. + */ + + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_INVALIDCBWSIGNATURE), 0); + EP_STALL(priv->epbulkout); + EP_STALL(priv->epbulkin); + } + + /* Is the CBW meaningful? */ + + else if (cbw->lun >= priv->nluns || (cbw->flags & ~USBMSC_CBWFLAG_IN) != 0 || + cbw->cdblen < 6 || cbw->cdblen > USBMSC_MAXCDBLEN) + { + /* CBS BAD: Stall the bulk endpoints. If the CBW is bad we must stall the + * bulk IN endpoint and either (1) stall the bulk OUT endpoint, or + * (2) discard data from the endpoint. + */ + + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_INVALIDCBWCONTENT), 0); + EP_STALL(priv->epbulkout); + EP_STALL(priv->epbulkin); + } + + /* Save the information from the CBW */ + + else + { + /* Extract the CDB and copy the whole CBD[] for later use */ + + priv->cdblen = cbw->cdblen; + memcpy(priv->cdb, cbw->cdb, priv->cdblen); + + /* Extract the data direction */ + + if ((cbw->flags & USBMSC_CBWFLAG_IN) != 0) + { + /* IN: Device-to-host */ + + priv->cbwdir = USBMSC_FLAGS_DIRDEVICE2HOST; + } + else + { + /* OUT: Host-to-device */ + + priv->cbwdir = USBMSC_FLAGS_DIRHOST2DEVICE; + } + + /* Get the max size of the data response */ + + priv->cbwlen = usbmsc_getle32(cbw->datlen); + if (priv->cbwlen == 0) + { + /* No length? Then no direction either */ + + priv->cbwdir = USBMSC_FLAGS_DIRNONE; + } + + /* Extract and save the LUN index and TAG value */ + + priv->cbwlun = cbw->lun; + priv->cbwtag = usbmsc_getle32(cbw->tag); + + /* Return the read request to the bulk out endpoint for re-filling */ + + req = privreq->req; + req->len = CONFIG_USBMSC_BULKOUTREQLEN; + req->priv = privreq; + req->callback = usbmsc_rdcomplete; + + /* Change to the CMDPARSE state and return success */ + + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_IDLECMDPARSE), priv->cdb[0]); + priv->thstate = USBMSC_STATE_CMDPARSE; + ret = OK; + } + + /* In any event, return the request to be refilled */ + + if (EP_SUBMIT(priv->epbulkout, req) != OK) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_IDLERDSUBMIT), (uint16_t)-ret); + } + + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdparsestate + * + * Description: + * Called from the worker thread in the USBMSC_STATE_CMDPARSE state. + * This state is entered when usbmsc_idlestate obtains a valid CBW + * containing SCSI commands. This function processes those SCSI commands. + * + * Returned value: + * If no write request is available or certain other errors occur, this + * function returns a negated errno and stays in the USBMSC_STATE_CMDPARSE + * state. Otherwise, when the new CBW is successfully process, this + * function sets priv->thstate to one of USBMSC_STATE_CMDREAD, + * USBMSC_STATE_CMDWRITE, or USBMSC_STATE_CMDFINISH and returns OK. + * + ****************************************************************************/ + +static int usbmsc_cmdparsestate(FAR struct usbmsc_dev_s *priv) +{ + FAR struct usbmsc_req_s *privreq; + FAR uint8_t *buf; + int ret = -EINVAL; + + usbmsc_dumpdata("SCSCI CDB", priv->cdb, priv->cdblen); + + /* Check if there is a request in the wrreqlist that we will be able to + * use for data or status. + */ + + privreq = (FAR struct usbmsc_req_s *)sq_peek(&priv->wrreqlist); + + /* If there no request structures available, then just return an error. + * This will cause us to remain in the CMDPARSE state. When a request is + * returned, the worker thread will be awakened in the USBMSC_STATE_CMDPARSE + * and we will be called again. + */ + + if (!privreq) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDPARSEWRREQLISTEMPTY), 0); + return -ENOMEM; + } + + DEBUGASSERT(privreq->req && privreq->req->buf); + buf = privreq->req->buf; + + /* Assume that no errors will be encountered */ + + priv->phaseerror = 0; + priv->shortpacket = 0; + + /* No data is buffered */ + + priv->nsectbytes = 0; + priv->nreqbytes = 0; + + /* Get exclusive access to the block driver */ + + pthread_mutex_lock(&priv->mutex); + switch (priv->cdb[0]) + { + case SCSI_CMD_TESTUNITREADY: /* 0x00 Mandatory */ + ret = usbmsc_cmdtestunitready(priv); + break; + + /* case SCSI_CMD_REZEROUNIT: * 0x01 Obsolete + * * 0x02 Vendor-specific */ + + case SCSI_CMD_REQUESTSENSE: /* 0x03 Mandatory */ + ret = usbmsc_cmdrequestsense(priv, buf); + break; + + /* case SCSI_CMD_FORMAT_UNIT: * 0x04 Mandatory, but not implemented + * * 0x05 Vendor specific + * * 0x06 Vendor specific + * case SCSI_CMD_REASSIGNBLOCKS: * 0x07 Optional */ + + case SCSI_CMD_READ6: /* 0x08 Mandatory */ + ret = usbmsc_cmdread6(priv); + break; + + /* * 0x09 Vendor specific */ + + case SCSI_CMD_WRITE6: /* 0x0a Optional */ + ret = usbmsc_cmdwrite6(priv); + break; + + /* case SCSI_CMD_SEEK6: * 0x0b Obsolete + * * 0x0c-0x10 Vendor specific + * case SCSI_CMD_SPACE6: * 0x11 Vendor specific */ + + case SCSI_CMD_INQUIRY: /* 0x12 Mandatory */ + ret = usbmsc_cmdinquiry(priv, buf); + break; + + /* * 0x13-0x14 Vendor specific */ + + case SCSI_CMD_MODESELECT6: /* 0x15 Optional */ + ret = usbmsc_cmdmodeselect6(priv); + break; + + /* case SCSI_CMD_RESERVE6: * 0x16 Obsolete + * case SCSI_CMD_RELEASE6: * 0x17 Obsolete + * case SCSI_CMD_COPY: * 0x18 Obsolete + * * 0x19 Vendor specific */ + + case SCSI_CMD_MODESENSE6: /* 0x1a Optional */ + ret = usbmsc_cmdmodesense6(priv, buf); + break; + + case SCSI_CMD_STARTSTOPUNIT: /* 0x1b Optional */ + ret = usbmsc_cmdstartstopunit(priv); + break; + + /* case SCSI_CMD_RECEIVEDIAGNOSTICRESULTS: * 0x1c Optional + * case SCSI_CMD_SENDDIAGNOSTIC: * 0x1d Mandatory, but not implemented */ + + case SCSI_CMD_PREVENTMEDIAREMOVAL: /* 0x1e Optional */ + ret = usbmsc_cmdpreventmediumremoval(priv); + break; + + /* * 0x20-22 Vendor specific */ + case SCSI_CMD_READFORMATCAPACITIES: /* 0x23 Vendor-specific (defined in MMC spec) */ + ret = usbmsc_cmdreadformatcapacity(priv, buf); + break; + /* * 0x24 Vendor specific */ + + case SCSI_CMD_READCAPACITY10: /* 0x25 Mandatory */ + ret = usbmsc_cmdreadcapacity10(priv, buf); + break; + + /* * 0x26-27 Vendor specific */ + case SCSI_CMD_READ10: /* 0x28 Mandatory */ + ret = usbmsc_cmdread10(priv); + break; + + /* * 0x29 Vendor specific */ + + case SCSI_CMD_WRITE10: /* 0x2a Optional */ + ret = usbmsc_cmdwrite10(priv); + break; + + /* case SCSI_CMD_SEEK10: * 0x2b Obsolete + * * 0x2c-2d Vendor specific + * case SCSI_CMD_WRITEANDVERIFY: * 0x2e Optional */ + + case SCSI_CMD_VERIFY10: /* 0x2f Optional, but needed my MS Windows */ + ret = usbmsc_cmdverify10(priv); + break; + + /* case SCSI_CMD_SEARCHDATAHIGH: * 0x30 Obsolete + * case SCSI_CMD_SEARCHDATAEQUAL: * 0x31 Obsolete + * case SCSI_CMD_SEARCHDATALOW: * 0x32 Obsolete + * case SCSI_CMD_SETLIMITS10: * 0x33 Obsolete + * case SCSI_CMD_PREFETCH10: * 0x34 Optional */ + + case SCSI_CMD_SYNCHCACHE10: /* 0x35 Optional */ + ret = usbmsc_cmdsynchronizecache10(priv); + break; + + /* case SCSI_CMD_LOCKCACHE: * 0x36 Obsolete + * case SCSI_CMD_READDEFECTDATA10: * 0x37 Optional + * case SCSI_CMD_COMPARE: * 0x39 Obsolete + * case SCSI_CMD_COPYANDVERIFY: * 0x3a Obsolete + * case SCSI_CMD_WRITEBUFFER: * 0x3b Optional + * case SCSI_CMD_READBUFFER: * 0x3c Optional + * case SCSI_CMD_READLONG10: * 0x3e Optional + * case SCSI_CMD_WRITELONG10: * 0x3f Optional + * case SCSI_CMD_CHANGEDEFINITION: * 0x40 Obsolete + * case SCSI_CMD_WRITESAME10: * 0x41 Optional + * case SCSI_CMD_LOGSELECT: * 0x4c Optional + * case SCSI_CMD_LOGSENSE: * 0x4d Optional + * case SCSI_CMD_XDWRITE10: * 0x50 Optional + * case SCSI_CMD_XPWRITE10: * 0x51 Optional + * case SCSI_CMD_XDREAD10: * 0x52 Optional */ + + case SCSI_CMD_MODESELECT10: /* 0x55 Optional */ + ret = usbmsc_cmdmodeselect10(priv); + break; + + /* case SCSI_CMD_RESERVE10: * 0x56 Obsolete + * case SCSI_CMD_RELEASE10: * 0x57 Obsolete */ + + case SCSI_CMD_MODESENSE10: /* 0x5a Optional */ + ret = usbmsc_cmdmodesense10(priv, buf); + break; + + /* case SCSI_CMD_PERSISTENTRESERVEIN: * 0x5e Optional + * case SCSI_CMD_PERSISTENTRESERVEOUT: * 0x5f Optional + * case SCSI_CMD_32: * 0x7f Optional + * case SCSI_CMD_XDWRITEEXTENDED: * 0x80 Obsolete + * case SCSI_CMD_REBUILD: * 0x81 Obsolete + * case SCSI_CMD_REGENERATE: * 0x82 Obsolete + * case SCSI_CMD_EXTENDEDCOPY: * 0x83 Optional + * case SCSI_CMD_COPYRESULTS: * 0x84 Optional + * case SCSI_CMD_ACCESSCONTROLIN: * 0x86 Optional + * case SCSI_CMD_ACCESSCONTROLOUT: * 0x87 Optional + * case SCSI_CMD_READ16: * 0x88 Optional + * case SCSI_CMD_WRITE16: * 0x8a Optional + * case SCSI_CMD_READATTRIBUTE: * 0x8c Optional + * case SCSI_CMD_WRITEATTRIBUTE: * 0x8d Optional + * case SCSI_CMD_WRITEANDVERIFY16: * 0x8e Optional + * case SCSI_CMD_SYNCHCACHE16: * 0x91 Optional + * case SCSI_CMD_LOCKUNLOCKACACHE: * 0x92 Optional + * case SCSI_CMD_WRITESAME16: * 0x93 Optional + * case SCSI_CMD_READCAPACITY16: * 0x9e Optional + * case SCSI_CMD_READLONG16: * 0x9e Optional + * case SCSI_CMD_WRITELONG16 * 0x9f Optional + * case SCSI_CMD_REPORTLUNS: * 0xa0 Mandatory, but not implemented + * case SCSI_CMD_MAINTENANCEIN: * 0xa3 Optional (SCCS==0) + * case SCSI_CMD_MAINTENANCEOUT: * 0xa4 Optional (SCCS==0) + * case SCSI_CMD_MOVEMEDIUM: * 0xa5 ? + * case SCSI_CMD_MOVEMEDIUMATTACHED: * 0xa7 Optional (MCHNGR==0) */ + + case SCSI_CMD_READ12: /* 0xa8 Optional */ + ret = usbmsc_cmdread12(priv); + break; + + case SCSI_CMD_WRITE12: /* 0xaa Optional */ + ret = usbmsc_cmdwrite12(priv); + break; + + /* case SCSI_CMD_READMEDIASERIALNUMBER: * 0xab Optional + * case SCSI_CMD_WRITEANDVERIFY12: * 0xae Optional + * case SCSI_CMD_VERIFY12: * 0xaf Optional + * case SCSI_CMD_SETLIMITS12 * 0xb3 Obsolete + * case SCSI_CMD_READELEMENTSTATUS: * 0xb4 Optional (MCHNGR==0) + * case SCSI_CMD_READDEFECTDATA12: * 0xb7 Optional + * case SCSI_CMD_REDUNDANCYGROUPIN: * 0xba Optional + * case SCSI_CMD_REDUNDANCYGROUPOUT: * 0xbb Optional + * case SCSI_CMD_SPAREIN: * 0xbc Optional (SCCS==0) + * case SCSI_CMD_SPAREOUT: * 0xbd Optional (SCCS==0) + * case SCSI_CMD_VOLUMESETIN: * 0xbe Optional (SCCS==0) + * case SCSI_CMD_VOLUMESETOUT: * 0xbe Optional (SCCS==0) + * * 0xc0-0xff Vendor specific */ + + default: + priv->u.alloclen = 0; + if (ret == OK) + { + priv->lun->sd = SCSI_KCQIR_INVALIDCOMMAND; + ret = -EINVAL; + } + break; + } + pthread_mutex_unlock(&priv->mutex); + + /* Is a response required? (Not for read6/10/12 and write6/10/12). */ + + if (priv->thstate == USBMSC_STATE_CMDPARSE) + { + /* All commands come through this path (EXCEPT read6/10/12 and write6/10/12). + * For all other commands, the following setup is expected for the response + * based on data direction: + * + * For direction NONE: + * 1. priv->u.alloclen == 0 + * 2. priv->nreqbytes == 0 + * + * For direction = device-to-host: + * 1. priv->u.alloclen == allocation length; space set aside by the + * host to receive the device data. The size of the response + * cannot exceed this value. + * 2. response data is in the request currently at the head of + * the priv->wrreqlist queue. priv->nreqbytes is set to the length + * of data in the response. + * + * For direction host-to-device + * At present, there are no supported commands that should have host-to-device + * transfers (except write6/10/12 and that command logic does not take this + * path. The 'residue' is left at the full host-to-device data size. + * + * For all: + * ret set to <0 if an error occurred in parsing the commands. + */ + + /* For from device-to-hose operations, the residue is the expected size + * (the initial value of 'residue') minus the amount actually returned + * in the response: + */ + + if (priv->cbwdir == USBMSC_FLAGS_DIRDEVICE2HOST) + { + /* The number of bytes in the response cannot exceed the host + * 'allocation length' in the command. + */ + + if (priv->nreqbytes > priv->u.alloclen) + { + priv->nreqbytes = priv->u.alloclen; + } + + /* The residue is then the number of bytes that were not sent */ + + priv->residue -= priv->nreqbytes; + } + + /* On return, we need the following: + * + * 1. Setup for CMDFINISH state if appropriate + * 2. priv->thstate set to either CMDPARSE if no buffer was available or + * CMDFINISH to send the response + * 3. Return OK to continue; <0 to wait for the next event + */ + + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDPARSECMDFINISH), priv->cdb[0]); + priv->thstate = USBMSC_STATE_CMDFINISH; + ret = OK; + } + return ret; +} + +/**************************************************************************** + * Name: usbmsc_cmdreadstate + * + * Description: + * Called from the worker thread in the USBMSC_STATE_CMDREAD state. + * The USBMSC_STATE_CMDREAD state is entered when usbmsc_cmdparsestate + * obtains a valid SCSI read command. This state is really a continuation + * of the USBMSC_STATE_CMDPARSE state that handles extended SCSI read + * command handling. + * + * Returned value: + * If no USBDEV write request is available or certain other errors occur, this + * function returns a negated errno and stays in the USBMSC_STATE_CMDREAD + * state. Otherwise, when the new SCSI read command is fully processed, + * this function sets priv->thstate to USBMSC_STATE_CMDFINISH and returns OK. + * + * State variables: + * xfrlen - holds the number of sectors read to be read. + * sector - holds the sector number of the next sector to be read + * nsectbytes - holds the number of bytes buffered for the current sector + * nreqbytes - holds the number of bytes currently buffered in the request + * at the head of the wrreqlist. + * + ****************************************************************************/ + +static int usbmsc_cmdreadstate(FAR struct usbmsc_dev_s *priv) +{ + FAR struct usbmsc_lun_s *lun = priv->lun; + FAR struct usbmsc_req_s *privreq; + FAR struct usbdev_req_s *req; + irqstate_t flags; + ssize_t nread; + uint8_t *src; + uint8_t *dest; + int nbytes; + int ret; + + /* Loop transferring data until either (1) all of the data has been + * transferred, or (2) we have used up all of the write requests that we have + * available. + */ + + while (priv->u.xfrlen > 0 || priv->nsectbytes > 0) + { + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDREAD), priv->u.xfrlen); + + /* Is the I/O buffer empty? */ + + if (priv->nsectbytes <= 0) + { + /* Yes.. read the next sector */ + + nread = USBMSC_DRVR_READ(lun, priv->iobuffer, priv->sector, 1); + if (nread < 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDREADREADFAIL), -nread); + lun->sd = SCSI_KCQME_UNRRE1; + lun->sdinfo = priv->sector; + break; + } + + priv->nsectbytes = lun->sectorsize; + priv->u.xfrlen--; + priv->sector++; + } + + /* Check if there is a request in the wrreqlist that we will be able to + * use for data transfer. + */ + + privreq = (FAR struct usbmsc_req_s *)sq_peek(&priv->wrreqlist); + + /* If there no request structures available, then just return an error. + * This will cause us to remain in the CMDREAD state. When a request is + * returned, the worker thread will be awakened in the USBMSC_STATE_CMDREAD + * and we will be called again. + */ + + if (!privreq) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDREADWRRQEMPTY), 0); + priv->nreqbytes = 0; + return -ENOMEM; + } + req = privreq->req; + + /* Transfer all of the data that will (1) fit into the request buffer, OR (2) + * all of the data available in the sector buffer. + */ + + src = &priv->iobuffer[lun->sectorsize - priv->nsectbytes]; + dest = &req->buf[priv->nreqbytes]; + + nbytes = MIN(CONFIG_USBMSC_BULKINREQLEN - priv->nreqbytes, priv->nsectbytes); + + /* Copy the data from the sector buffer to the USB request and update counts */ + + memcpy(dest, src, nbytes); + priv->nreqbytes += nbytes; + priv->nsectbytes -= nbytes; + + /* If (1) the request buffer is full OR (2) this is the final request full of data, + * then submit the request + */ + + if (priv->nreqbytes >= CONFIG_USBMSC_BULKINREQLEN || + (priv->u.xfrlen <= 0 && priv->nsectbytes <= 0)) + { + /* Remove the request that we just filled from wrreqlist (we've already checked + * that is it not NULL + */ + + flags = irqsave(); + privreq = (FAR struct usbmsc_req_s *)sq_remfirst(&priv->wrreqlist); + irqrestore(flags); + + /* And submit the request to the bulk IN endpoint */ + + req->len = priv->nreqbytes; + req->priv = privreq; + req->callback = usbmsc_wrcomplete; + req->flags = 0; + + ret = EP_SUBMIT(priv->epbulkin, req); + if (ret != OK) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDREADSUBMIT), (uint16_t)-ret); + lun->sd = SCSI_KCQME_UNRRE1; + lun->sdinfo = priv->sector; + break; + } + + /* Assume success... residue should probably really be decremented in + * wrcomplete when we know that the transfer completed successfully. + */ + + priv->residue -= priv->nreqbytes; + priv->nreqbytes = 0; + } + } + + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDREADCMDFINISH), priv->u.xfrlen); + priv->thstate = USBMSC_STATE_CMDFINISH; + return OK; +} + +/**************************************************************************** + * Name: usbmsc_cmdwritestate + * + * Description: + * Called from the worker thread in the USBMSC_STATE_CMDWRITE state. + * The USBMSC_STATE_CMDWRITE state is entered when usbmsc_cmdparsestate + * obtains a valid SCSI write command. This state is really a continuation + * of the USBMSC_STATE_CMDPARSE state that handles extended SCSI write + * command handling. + * + * Returned value: + * If no USBDEV write request is available or certain other errors occur, this + * function returns a negated errno and stays in the USBMSC_STATE_CMDWRITE + * state. Otherwise, when the new SCSI write command is fully processed, + * this function sets priv->thstate to USBMSC_STATE_CMDFINISH and returns OK. + * + * State variables: + * xfrlen - holds the number of sectors read to be written. + * sector - holds the sector number of the next sector to write + * nsectbytes - holds the number of bytes buffered for the current sector + * nreqbytes - holds the number of untransferred bytes currently in the + * request at the head of the rdreqlist. + * + ****************************************************************************/ + +static int usbmsc_cmdwritestate(FAR struct usbmsc_dev_s *priv) +{ + FAR struct usbmsc_lun_s *lun = priv->lun; + FAR struct usbmsc_req_s *privreq; + FAR struct usbdev_req_s *req; + ssize_t nwritten; + uint16_t xfrd; + uint8_t *src; + uint8_t *dest; + int nbytes; + int ret; + + /* Loop transferring data until either (1) all of the data has been + * transferred, or (2) we have written all of the data in the available + * read requests. + */ + + while (priv->u.xfrlen > 0) + { + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDWRITE), priv->u.xfrlen); + + /* Check if there is a request in the rdreqlist containing additional + * data to be written. + */ + + privreq = (FAR struct usbmsc_req_s *)sq_remfirst(&priv->rdreqlist); + + /* If there no request data available, then just return an error. + * This will cause us to remain in the CMDWRITE state. When a filled request is + * received, the worker thread will be awakened in the USBMSC_STATE_CMDWRITE + * and we will be called again. + */ + + if (!privreq) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDWRITERDRQEMPTY), 0); + priv->nreqbytes = 0; + return -ENOMEM; + } + + req = privreq->req; + xfrd = req->xfrd; + priv->nreqbytes = xfrd; + + /* Now loop until all of the data in the read request has been tranferred + * to the block driver OR all of the request data has been transferred. + */ + + while (priv->nreqbytes > 0 && priv->u.xfrlen > 0) + { + /* Copy the data received in the read request into the sector I/O buffer */ + + src = &req->buf[xfrd - priv->nreqbytes]; + dest = &priv->iobuffer[priv->nsectbytes]; + + nbytes = MIN(lun->sectorsize - priv->nsectbytes, priv->nreqbytes); + + /* Copy the data from the sector buffer to the USB request and update counts */ + + memcpy(dest, src, nbytes); + priv->nsectbytes += nbytes; + priv->nreqbytes -= nbytes; + + /* Is the I/O buffer full? */ + + if (priv->nsectbytes >= lun->sectorsize) + { + /* Yes.. Write the next sector */ + + nwritten = USBMSC_DRVR_WRITE(lun, priv->iobuffer, priv->sector, 1); + if (nwritten < 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDWRITEWRITEFAIL), -nwritten); + lun->sd = SCSI_KCQME_WRITEFAULTAUTOREALLOCFAILED; + lun->sdinfo = priv->sector; + goto errout; + } + + priv->nsectbytes = 0; + priv->residue -= lun->sectorsize; + priv->u.xfrlen--; + priv->sector++; + } + } + + /* In either case, we are finished with this read request and can return it + * to the endpoint. Then we will go back to the top of the top and attempt + * to get the next read request. + */ + + req->len = CONFIG_USBMSC_BULKOUTREQLEN; + req->priv = privreq; + req->callback = usbmsc_rdcomplete; + + ret = EP_SUBMIT(priv->epbulkout, req); + if (ret != OK) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDWRITERDSUBMIT), (uint16_t)-ret); + } + + /* Did the host decide to stop early? */ + + if (xfrd != CONFIG_USBMSC_BULKOUTREQLEN) + { + priv->shortpacket = 1; + goto errout; + } + } + +errout: + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDWRITECMDFINISH), priv->u.xfrlen); + priv->thstate = USBMSC_STATE_CMDFINISH; + return OK; +} + +/**************************************************************************** + * Name: usbmsc_cmdfinishstate + * + * Description: + * Called from the worker thread in the USBMSC_STATE_CMDFINISH state. + * The USBMSC_STATE_CMDFINISH state is entered when processing of a + * command has finished but before status has been returned. + * + * Returned value: + * If no USBDEV write request is available or certain other errors occur, this + * function returns a negated errno and stays in the USBMSC_STATE_CMDFINISH + * state. Otherwise, when the command is fully processed, this function + * sets priv->thstate to USBMSC_STATE_CMDSTATUS and returns OK. + * + ****************************************************************************/ + +static int usbmsc_cmdfinishstate(FAR struct usbmsc_dev_s *priv) +{ + FAR struct usbmsc_req_s *privreq; + irqstate_t flags; + int ret = OK; + + /* Check if there is a request in the wrreqlist that we will be able to + * use for data transfer. + */ + + privreq = (FAR struct usbmsc_req_s *)sq_peek(&priv->wrreqlist); + + /* If there no request structures available, then just return an error. + * This will cause us to remain in the CMDREAD state. When a request is + * returned, the worker thread will be awakened in the USBMSC_STATE_CMDREAD + * and we will be called again. + */ + + if (!privreq) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDFINISHRQEMPTY), 0); + return -ENOMEM; + } + + /* Finish the final stages of the reply */ + + switch (priv->cbwdir) + { + /* Device-to-host: All but the last data buffer has been sent */ + + case USBMSC_FLAGS_DIRDEVICE2HOST: + if (priv->cbwlen > 0) + { + /* On most commands (the exception is outgoing, write commands), + * the data has not not yet been sent. + */ + + if (priv->nreqbytes > 0) + { + struct usbdev_req_s *req; + + /* Take a request from the wrreqlist (we've already checked + * that is it not NULL) + */ + + flags = irqsave(); + privreq = (FAR struct usbmsc_req_s *)sq_remfirst(&priv->wrreqlist); + irqrestore(flags); + + /* Send the write request */ + + req = privreq->req; + req->len = priv->nreqbytes; + req->callback = usbmsc_wrcomplete; + req->priv = privreq; + req->flags = USBDEV_REQFLAGS_NULLPKT; + + ret = EP_SUBMIT(priv->epbulkin, privreq->req); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDFINISHSUBMIT), (uint16_t)-ret); + } + } + + /* Stall the BULK In endpoint if there is a residue */ + + if (priv->residue > 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDFINISHRESIDUE), (uint16_t)priv->residue); + +#ifdef CONFIG_USBMSC_RACEWAR + /* (See description of the workaround at the top of the file). + * First, wait for the transfer to complete, then stall the endpoint + */ + + usleep (100000); + (void)EP_STALL(priv->epbulkin); + + /* now wait for stall to go away .... */ + + usleep (100000); +#else + (void)EP_STALL(priv->epbulkin); +#endif + } + } + break; + + /* Host-to-device: We have processed all we want of the host data. */ + + case USBMSC_FLAGS_DIRHOST2DEVICE: + if (priv->residue > 0) + { + /* Did the host stop sending unexpectedly early? */ + + flags = irqsave(); + if (priv->shortpacket) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDFINISHSHORTPKT), (uint16_t)priv->residue); + } + + /* Unprocessed incoming data: STALL and cancel requests. */ + + else + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDFINSHSUBMIT), (uint16_t)priv->residue); + EP_STALL(priv->epbulkout); + } + + priv->theventset |= USBMSC_EVENT_ABORTBULKOUT; + irqrestore(flags); + } + break; + + default: + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDFINSHDIR), priv->cbwdir); + case USBMSC_FLAGS_DIRNONE: /* Nothing to send */ + break; + } + + /* Return to the IDLE state */ + + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDFINISHCMDSTATUS), 0); + priv->thstate = USBMSC_STATE_CMDSTATUS; + return OK; +} + +/**************************************************************************** + * Name: usbmsc_cmdstatusstate + * + * Description: + * Called from the worker thread in the USBMSC_STATE_CMDSTATUS state. + * That state is after a CBW has been fully processed. This function sends + * the concluding CSW. + * + * Returned value: + * If no write request is available or certain other errors occur, this + * function returns a negated errno and stays in the USBMSC_STATE_CMDSTATUS + * state. Otherwise, when the SCSI statis is successfully returned, this + * function sets priv->thstate to USBMSC_STATE_IDLE and returns OK. + * + ****************************************************************************/ + +static int usbmsc_cmdstatusstate(FAR struct usbmsc_dev_s *priv) +{ + FAR struct usbmsc_lun_s *lun = priv->lun; + FAR struct usbmsc_req_s *privreq; + FAR struct usbdev_req_s *req; + FAR struct usbmsc_csw_s *csw; + irqstate_t flags; + uint32_t sd; + uint8_t status = USBMSC_CSWSTATUS_PASS; + int ret; + + /* Take a request from the wrreqlist */ + + flags = irqsave(); + privreq = (FAR struct usbmsc_req_s *)sq_remfirst(&priv->wrreqlist); + irqrestore(flags); + + /* If there no request structures available, then just return an error. + * This will cause us to remain in the CMDSTATUS status. When a request is + * returned, the worker thread will be awakened in the USBMSC_STATE_CMDSTATUS + * and we will be called again. + */ + + if (!privreq) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDSTATUSRDREQLISTEMPTY), 0); + return -ENOMEM; + } + + req = privreq->req; + csw = (struct usbmsc_csw_s*)req->buf; + + /* Extract the sense data from the LUN structure */ + + if (lun) + { + sd = lun->sd; + } + else + { + sd = SCSI_KCQIR_INVALIDLUN; + } + + /* Determine the CSW status: PASS, PHASEERROR, or FAIL */ + + if (priv->phaseerror) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_SNDPHERROR), 0); + status = USBMSC_CSWSTATUS_PHASEERROR; + sd = SCSI_KCQIR_INVALIDCOMMAND; + } + else if (sd != SCSI_KCQ_NOSENSE) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_SNDCSWFAIL), 0); + status = USBMSC_CSWSTATUS_FAIL; + } + + /* Format and submit the CSW */ + + csw->signature[0] = 'U'; + csw->signature[1] = 'S'; + csw->signature[2] = 'B'; + csw->signature[3] = 'S'; + usbmsc_putle32(csw->tag, priv->cbwtag); + usbmsc_putle32(csw->residue, priv->residue); + csw->status = status; + + usbmsc_dumpdata("SCSCI CSW", (uint8_t*)csw, USBMSC_CSW_SIZEOF); + + req->len = USBMSC_CSW_SIZEOF; + req->callback = usbmsc_wrcomplete; + req->priv = privreq; + req->flags = USBDEV_REQFLAGS_NULLPKT; + + ret = EP_SUBMIT(priv->epbulkin, req); + if (ret < 0) + { + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_SNDSTATUSSUBMIT), (uint16_t)-ret); + flags = irqsave(); + (void)sq_addlast((sq_entry_t*)privreq, &priv->wrreqlist); + irqrestore(flags); + } + + /* Return to the IDLE state */ + + usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDSTATUSIDLE), 0); + priv->thstate = USBMSC_STATE_IDLE; + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbmsc_workerthread + * + * Description: + * This is the main function of the USB storage worker thread. It loops + * until USB-related events occur, then processes those events accordingly + * + ****************************************************************************/ + +void *usbmsc_workerthread(void *arg) +{ + struct usbmsc_dev_s *priv = (struct usbmsc_dev_s *)arg; + irqstate_t flags; + uint16_t eventset; + int ret; + + /* This thread is started before the USB storage class is fully initialized. + * wait here until we are told to begin. Start in the NOTINITIALIZED state + */ + + pthread_mutex_lock(&priv->mutex); + priv->thstate = USBMSC_STATE_STARTED; + while ((priv->theventset & USBMSC_EVENT_READY) != 0 && + (priv->theventset & USBMSC_EVENT_TERMINATEREQUEST) != 0) + { + pthread_cond_wait(&priv->cond, &priv->mutex); + } + + /* Transition to the INITIALIZED/IDLE state */ + + priv->thstate = USBMSC_STATE_IDLE; + eventset = priv->theventset; + priv->theventset = USBMSC_EVENT_NOEVENTS; + pthread_mutex_unlock(&priv->mutex); + + /* Then loop until we are asked to terminate */ + + while ((eventset & USBMSC_EVENT_TERMINATEREQUEST) == 0) + { + /* Wait for some interesting event. Note that we must both take the + * lock (to eliminate race conditions with other threads) and disable + * interrupts (to eliminate race conditions with USB interrupt handling. + */ + + pthread_mutex_lock(&priv->mutex); + flags = irqsave(); + if (priv->theventset == USBMSC_EVENT_NOEVENTS) + { + pthread_cond_wait(&priv->cond, &priv->mutex); + } + + /* Sample any events before re-enabling interrupts. Any events that + * occur after re-enabling interrupts will have to be handled in the + * next time through the loop. + */ + + eventset = priv->theventset; + priv->theventset = USBMSC_EVENT_NOEVENTS; + pthread_mutex_unlock(&priv->mutex); + + /* Were we awakened by some event that requires immediate action? + * + * - The USBMSC_EVENT_DISCONNECT is signalled from the disconnect method + * after all transfers have been stopped, when the host is disconnected. + * + * - The CUSBMSC_EVENT_RESET is signalled when the bulk-storage-specific + * USBMSC_REQ_MSRESET EP0 setup received. We must stop the current + * operation and reinialize state. + * + * - The USBMSC_EVENT_CFGCHANGE is signaled when the EP0 setup logic + * receives a valid USB_REQ_SETCONFIGURATION request + * + * - The USBMSC_EVENT_IFCHANGE is signaled when the EP0 setup logic + * receives a valid USB_REQ_SETINTERFACE request + * + * - The USBMSC_EVENT_ABORTBULKOUT event is signalled by the CMDFINISH + * logic when there is a residue after processing a host-to-device + * transfer. We need to discard all incoming request. + * + * All other events are just wakeup calls and are intended only + * drive the state machine. + */ + + if ((eventset & (USBMSC_EVENT_DISCONNECT|USBMSC_EVENT_RESET|USBMSC_EVENT_CFGCHANGE| + USBMSC_EVENT_IFCHANGE|USBMSC_EVENT_ABORTBULKOUT)) != 0) + { + /* These events require that the current configuration be reset */ + + if ((eventset & USBMSC_EVENT_IFCHANGE) != 0) + { + usbmsc_resetconfig(priv); + } + + /* These events require that a new configuration be established */ + + if ((eventset & (USBMSC_EVENT_CFGCHANGE|USBMSC_EVENT_IFCHANGE)) != 0) + { + usbmsc_setconfig(priv, priv->thvalue); + } + + /* These events required that we send a deferred EP0 setup response */ + + if ((eventset & (USBMSC_EVENT_RESET|USBMSC_EVENT_CFGCHANGE|USBMSC_EVENT_IFCHANGE)) != 0) + { + usbmsc_deferredresponse(priv, false); + } + + /* For all of these events... terminate any transactions in progress */ + + priv->thstate = USBMSC_STATE_IDLE; + } + irqrestore(flags); + + /* Loop processing each SCSI command state. Each state handling + * function will do the following: + * + * - If it must block for an event, it will return a negated errno value + * - If it completes the processing for that state, it will (1) set + * the next appropriate state value and (2) return OK. + * + * So the following will loop until we must block for an event in + * a particular state. When we are awakened by an event (above) we + * will resume processing in the same state. + */ + + do + { + switch (priv->thstate) + { + case USBMSC_STATE_IDLE: /* Started and waiting for commands */ + ret = usbmsc_idlestate(priv); + break; + + case USBMSC_STATE_CMDPARSE: /* Parsing the received a command */ + ret = usbmsc_cmdparsestate(priv); + break; + + case USBMSC_STATE_CMDREAD: /* Continuing to process a SCSI read command */ + ret = usbmsc_cmdreadstate(priv); + break; + + case USBMSC_STATE_CMDWRITE: /* Continuing to process a SCSI write command */ + ret = usbmsc_cmdwritestate(priv); + break; + + case USBMSC_STATE_CMDFINISH: /* Finish command processing */ + ret = usbmsc_cmdfinishstate(priv); + break; + + case USBMSC_STATE_CMDSTATUS: /* Processing the status phase of a command */ + ret = usbmsc_cmdstatusstate(priv); + break; + + case USBMSC_STATE_NOTSTARTED: /* Thread has not yet been started */ + case USBMSC_STATE_STARTED: /* Started, but is not yet initialized */ + case USBMSC_STATE_TERMINATED: /* Thread has exitted */ + default: + usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_INVALIDSTATE), priv->thstate); + priv->thstate = USBMSC_STATE_IDLE; + ret = OK; + break; + } + } + while (ret == OK); + } + + /* Transition to the TERMINATED state and exit */ + + priv->thstate = USBMSC_STATE_TERMINATED; + return NULL; +} diff --git a/nuttx/drivers/usbhost/Kconfig b/nuttx/drivers/usbhost/Kconfig new file mode 100644 index 0000000000..35695d7501 --- /dev/null +++ b/nuttx/drivers/usbhost/Kconfig @@ -0,0 +1,92 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# +config USBHOST_NPREALLOC + int "Number of pre-allocated class instances" + default 4 + ---help--- + Number of pre-allocated class instances + +config USBHOST_BULK_DISABLE + bool "Disable bulk endpoint support" + default n + ---help--- + On some architectures, selecting this setting will reduce driver size + by disabling bulk endpoint support + +config USBHOST_INT_DISABLE + bool "Disable interrupt endpoint support" + default n + ---help--- + On some architectures, selecting this setting will reduce driver size + by disabling interrupt endpoint support + +config USBHOST_ISOC_DISABLE + bool "Disable isochronous endpoint support" + default n + ---help--- + On some architectures, selecting this setting will reduce driver size + by disabling isochronous endpoint support + +config USBHOST_HIDKBD + bool "HID keyboad class support" + default n + depends on !USBHOST_INT_DISABLE && SCHED_WORKQUEUE && !DISABLE_SIGNALS + +if USBHOST_HIDKBD +config HIDKBD_POLLUSEC + bool "" + default n + ---help--- + Device poll rate in microseconds. Default: 100 milliseconds. + +config HIDKBD_DEFPRIO + bool "" + default n + ---help--- + Priority of the polling thread. Default: 50. + +config HIDKBD_STACKSIZE + bool "" + default n + ---help--- + Stack size for polling thread. Default: 1024 + +config HIDKBD_BUFSIZE + bool "" + default n + ---help--- + Scancode buffer size. Default: 64. + +config HIDKBD_NPOLLWAITERS + bool "" + default n + ---help--- + If the poll() method is enabled, this defines the maximum number + of threads that can be waiting for keyboard events. Default: 2. + +config HIDKBD_RAWSCANCODES + bool "" + default n + ---help--- + If set to y no conversion will be made on the raw keyboard scan + codes. Default: ASCII conversion. + +config HIDKBD_ALLSCANCODES + bool "" + default n + ---help--- + If set to y all 231 possible scancodes will be converted to + something. Default: 104 key US keyboard. + +config HIDKBD_NODEBOUNCE + bool "" + default n + ---help--- + If set to y normal debouncing is disabled. Default: + Debounce enabled (No repeat keys). + USB host mass storage class driver. Requires USBHOST=y, + config USBHOST_BULK_DISABLE=n, NFILE_DESCRIPTORS > 0, + and SCHED_WORKQUEUE=y +endif diff --git a/nuttx/drivers/usbhost/Make.defs b/nuttx/drivers/usbhost/Make.defs new file mode 100644 index 0000000000..cc28e874d4 --- /dev/null +++ b/nuttx/drivers/usbhost/Make.defs @@ -0,0 +1,57 @@ +############################################################################ +# drivers/usbhost/Make.defs +# +# Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +CSRCS += hid_parser.c + +ifeq ($(CONFIG_USBHOST),y) + +# Include built-in USB host driver logic + +CSRCS += usbhost_registry.c usbhost_registerclass.c usbhost_findclass.c +CSRCS += usbhost_enumerate.c usbhost_storage.c usbhost_hidkbd.c + +# Include add-on USB host driver logic (see misc/drivers) + +ifeq ($(CONFIG_NET),y) + RTL8187_CSRC := ${shell if [ -f usbhost/rtl8187x.c ]; then echo "rtl8187x.c"; fi} + CSRCS += $(RTL8187_CSRC) +endif +endif + +# Include USB host driver build logic + +DEPPATH += --dep-path usbhost +VPATH += :usbhost +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/usbhost} diff --git a/nuttx/drivers/usbhost/hid_parser.c b/nuttx/drivers/usbhost/hid_parser.c new file mode 100644 index 0000000000..a0ca6066bc --- /dev/null +++ b/nuttx/drivers/usbhost/hid_parser.c @@ -0,0 +1,529 @@ +/**************************************************************************** + * drivers/usbhost/hid_parser.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * + * Adapted from the LUFA Library: + * + * Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + * dean [at] fourwalledcubicle [dot] com, www.lufa-lib.org + * + * Permission to use, copy, modify, distribute, and sell this + * software and its documentation for any purpose is hereby granted + * without fee, provided that the above copyright notice appear in + * all copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct hid_state_s +{ + struct hid_rptitem_attributes_s attrib; + uint8_t rptcount; + uint8_t id; +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: hid_parsereport + * + * Description: + * Function to process a given HID report returned from an attached device, + * and store it into a given struct hid_rptinfo_s structure. + * + * Input Parameters: + * report Buffer containing the device's HID report table. + * rptlen Size in bytes of the HID report table. + * filter Callback function to decide if an item should be retained + * rptinfo Pointer to a struct hid_rptinfo_s instance for the parser output. + * + * Returned Value: + * Zero on success, otherwise a negated errno value. + ****************************************************************************/ + +int hid_parsereport(FAR const uint8_t *report, int rptlen, + hid_rptfilter_t filter, FAR struct hid_rptinfo_s *rptinfo) +{ + struct hid_state_s state[CONFIG_HID_STATEDEPTH]; + struct hid_state_s *currstate = &state[0]; + struct hid_collectionpath_s *collectionpath = NULL; + struct hid_rptsizeinfo_s *rptidinfo = &rptinfo->rptsize[0]; + uint16_t usage[CONFIG_HID_USAGEDEPTH]; + uint8_t nusage = 0; + struct hid_range_s usage_range = { 0, 0 }; + int i; + + DEBUGASSERT(report && filter && rptinfo); + + memset(rptinfo, 0x00, sizeof(struct hid_rptinfo_s)); + memset(currstate, 0x00, sizeof(struct hid_state_s)); + memset(rptidinfo, 0x00, sizeof(struct hid_rptsizeinfo_s)); + + rptinfo->nreports = 1; + + while (rptlen > 0) + { + uint8_t item = *report; + uint32_t data = 0; + + report++; + rptlen--; + + switch (item & USBHID_RPTITEM_SIZE_MASK) + { + case USBHID_RPTITEM_SIZE_4: /* 4 bytes of little endian data follow */ + data = (uint32_t)(*report++); + data |= (uint32_t)(*report++) << 8; + data |= (uint32_t)(*report++) << 16; + data |= (uint32_t)(*report++) << 24; + rptlen -= 4; + break; + + case USBHID_RPTITEM_SIZE_2: /* 2 bytes of little endian data follow */ + data = (uint32_t)(*report++); + data |= (uint32_t)(*report++) << 8; + rptlen -= 2; + break; + + case USBHID_RPTITEM_SIZE_1: /* 1 byte of data follows */ + data = (uint32_t)(*report++); + rptlen -= 1; + break; + + case USBHID_RPTITEM_SIZE_0: /* No data follows */ + default: + break; + } + + switch (item & ~USBHID_RPTITEM_SIZE_MASK) + { + case USBHID_GLOBAL_PUSH_PREFIX: + if (currstate == &state[CONFIG_HID_STATEDEPTH - 1]) + { + return -E2BIG; + } + + memcpy((currstate + 1), + currstate, sizeof(struct hid_rptitem_s)); + + currstate++; + break; + + case USBHID_GLOBAL_POP_PREFIX: + if (currstate == &state[0]) + { + return -EINVAL; /* Pop without push? */ + } + + currstate--; + break; + + case USBHID_GLOBAL_USAGEPAGE_PREFIX: + if ((item & USBHID_RPTITEM_SIZE_MASK) == USBHID_RPTITEM_SIZE_4) + { + currstate->attrib.usage.page = (data >> 16); + } + + currstate->attrib.usage.page = data; + break; + + case USBHID_GLOBAL_LOGICALMIN_PREFIX: + currstate->attrib.logical.min = data; + break; + + case USBHID_GLOBAL_LOGICALMAX_PREFIX: + currstate->attrib.logical.max = data; + break; + + case USBHID_GLOBAL_PHYSICALMIN_PREFIX: + currstate->attrib.physical.min = data; + break; + + case USBHID_GLOBAL_PHYSMICALAX_PREFIX: + currstate->attrib.physical.max = data; + break; + + case USBHID_GLOBAL_UNITEXP_PREFIX: + currstate->attrib.unit.exponent = data; + break; + + case USBHID_GLOBAL_UNIT_PREFIX: + currstate->attrib.unit.type = data; + break; + + case USBHID_GLOBAL_REPORTSIZE_PREFIX: + currstate->attrib.bitsize = data; + break; + + case USBHID_GLOBAL_REPORTCOUNT_PREFIX: + currstate->rptcount = data; + break; + + case USBHID_GLOBAL_REPORTID_PREFIX: + currstate->id = data; + + if (rptinfo->haverptid) + { + rptidinfo = NULL; + + for (i = 0; i < rptinfo->nreports; i++) + { + if (rptinfo->rptsize[i].id == currstate->id) + { + rptidinfo = &rptinfo->rptsize[i]; + break; + } + } + + if (rptidinfo == NULL) + { + if (rptinfo->nreports == CONFIG_HID_MAXIDS) + { + return -EINVAL; + } + + rptidinfo = &rptinfo->rptsize[rptinfo->nreports++]; + memset(rptidinfo, 0x00, sizeof(struct hid_rptsizeinfo_s)); + } + } + + rptinfo->haverptid = true; + + rptidinfo->id = currstate->id; + break; + + case USBHID_LOCAL_USAGE_PREFIX: + if (nusage == CONFIG_HID_USAGEDEPTH) + { + return -E2BIG; + } + + usage[nusage++] = data; + break; + + case USBHID_LOCAL_USAGEMIN_PREFIX: + usage_range.min = data; + break; + + case USBHID_LOCAL_USAGEMAX_PREFIX: + usage_range.max = data; + break; + + case USBHID_MAIN_COLLECTION_PREFIX: + if (collectionpath == NULL) + { + collectionpath = &rptinfo->collectionpaths[0]; + } + else + { + struct hid_collectionpath_s *ParentCollectionPath = collectionpath; + + collectionpath = &rptinfo->collectionpaths[1]; + + while (collectionpath->parent != NULL) + { + if (collectionpath == &rptinfo->collectionpaths[CONFIG_HID_MAXCOLLECTIONS - 1]) + { + return -EINVAL; + } + + collectionpath++; + } + + collectionpath->parent = ParentCollectionPath; + } + + collectionpath->type = data; + collectionpath->usage.page = currstate->attrib.usage.page; + + if (nusage) + { + collectionpath->usage.usage = usage[0]; + + for (i = 0; i < nusage; i++) + usage[i] = usage[i + 1]; + + nusage--; + } + else if (usage_range.min <= usage_range.max) + { + collectionpath->usage.usage = usage_range.min++; + } + + break; + + case USBHID_MAIN_ENDCOLLECTION_PREFIX: + if (collectionpath == NULL) + { + return -EINVAL; + } + + collectionpath = collectionpath->parent; + break; + + case USBHID_MAIN_INPUT_PREFIX: + case USBHID_MAIN_OUTPUT_PREFIX: + case USBHID_MAIN_FEATURE_PREFIX: + { + int itemno; + for (itemno = 0; itemno < currstate->rptcount; itemno++) + { + struct hid_rptitem_s newitem; + uint8_t tag; + + memcpy(&newitem.attrib, &currstate->attrib, + sizeof(struct hid_rptitem_attributes_s)); + + newitem.flags = data; + newitem.collectionpath = collectionpath; + newitem.id = currstate->id; + + if (nusage) + { + newitem.attrib.usage.usage = usage[0]; + + for (i = 0; i < nusage; i++) + { + usage[i] = usage[i + 1]; + } + nusage--; + } + else if (usage_range.min <= usage_range.max) + { + newitem.attrib.usage.usage = usage_range.min++; + } + + tag = (item & ~USBHID_RPTITEM_SIZE_MASK); + if (tag == USBHID_MAIN_INPUT_PREFIX) + { + newitem.type = HID_REPORT_ITEM_IN; + } + else if (tag == USBHID_MAIN_OUTPUT_PREFIX) + { + newitem.type = HID_REPORT_ITEM_OUT; + } + else + { + newitem.type = HID_REPORT_ITEM_FEATURE; + } + + newitem.bitoffset = rptidinfo->size[newitem.type]; + rptidinfo->size[newitem.type] += currstate->attrib.bitsize; + + /* Accumulate the maximum report size */ + + if (rptinfo->maxrptsize < newitem.bitoffset) + { + rptinfo->maxrptsize = newitem.bitoffset; + } + + if ((data & USBHID_MAIN_CONSTANT) == 0 && filter(&newitem)) + { + if (rptinfo->nitems == CONFIG_HID_MAXITEMS) + { + return -EINVAL; + } + + memcpy(&rptinfo->items[rptinfo->nitems], + &newitem, sizeof(struct hid_rptitem_s)); + + rptinfo->nitems++; + } + } + } + break; + } + + if ((item & USBHID_RPTITEM_TYPE_MASK) == USBHID_RPTITEM_TYPE_MAIN) + { + usage_range.min = 0; + usage_range.max = 0; + nusage = 0; + } + } + + if (!(rptinfo->nitems)) + { + return -ENOENT; + } + + return OK; +} + +/**************************************************************************** + * Name: hid_getitem + * + * Description: + * Extracts the given report item's value out of the given HID report and + * places it into the value member of the report item's struct hid_rptitem_s + * structure. + * + * When called on a report with an item that exists in that report, this + * copies the report item's Value to it's previous element for easy + * checking to see if an item's value has changed before processing a + * report. If the given item does not exist in the report, the function + * does not modify the report item's data. + * + * Input Parameters + * report Buffer containing an IN or FEATURE report from an attached + * device. + * item Pointer to the report item of interest in a struct hid_rptinfo_s + * item array. + * + * Returned Value: + * Zero on success, otherwise a negated errno value. + * + ****************************************************************************/ + +int hid_getitem(FAR const uint8_t *report, FAR struct hid_rptitem_s *item) +{ + uint16_t remaining = item->attrib.bitsize; + uint16_t offset = item->bitoffset; + uint32_t mask = (1 << 0); + + if (item->id) + { + if (item->id != report[0]) + { + return -ENOENT; + } + + report++; + } + + item->previous = item->value; + item->value = 0; + + while (remaining--) + { + if (report[offset >> 3] & (1 << (offset & 7))) + { + item->value |= mask; + } + + offset++; + mask <<= 1; + } + + return OK; +} + +/**************************************************************************** + * Name: hid_putitem + * + * Desription: + * Retrieves the given report item's value out of the Value member of the + * report item's struct hid_rptitem_s structure and places it into the correct + * position in the HID report buffer. The report buffer is assumed to have + * the appropriate bits cleared before calling this function (i.e., the + * buffer should be explicitly cleared before report values are added). + * + * When called, this copies the report item's Value element to it's + * previous element for easy checking to see if an item's value has + * changed before sending a report. + * + * If the device has multiple HID reports, the first byte in the report is + * set to the report ID of the given item. + * + * Input Parameters: + * report Buffer holding the current OUT or FEATURE report data. + * item Pointer to the report item of interest in a struct hid_rptinfo_s + * item array. + * + ****************************************************************************/ + +#if 0 /* Not needed by host */ +void hid_putitem(FAR uint8_t *report, struct hid_rptitem_s *item) +{ + uint16_t remaining = item->attrib.bitsize; + uint16_t offset = item->bitoffset; + uint32_t mask = (1 << 0); + + if (item->id) + { + report[0] = item->id; + report++; + } + + item->previous = item->value; + + while (remaining--) + { + if (item->value & (1 << (offset & 7))) + { + report[offset >> 3] |= mask; + } + + offset++; + mask <<= 1; + } +} +#endif + +/**************************************************************************** + * Name: hid_reportsize + * + * Description: + * Retrieves the size of a given HID report in bytes from it's Report ID. + * + * InputParameters: + * rptinfo Pointer to a struct hid_rptinfo_s instance containing the parser output. + * id Report ID of the report whose size is to be retrieved. + * rpttype Type of the report whose size is to be determined, a valued from the + * HID_ReportItemTypes_t enum. + * + * Size of the report in bytes, or 0 if the report does not exist. + * + ****************************************************************************/ + +size_t hid_reportsize(FAR struct hid_rptinfo_s *rptinfo, uint8_t id, uint8_t rpttype) +{ + int i; + for (i = 0; i < CONFIG_HID_MAXIDS; i++) + { + size_t size = rptinfo->rptsize[i].size[rpttype]; + + if (rptinfo->rptsize[i].id == id) + { + return ((size >> 3) + ((size & 0x07) ? 1 : 0)); + } + } + + return 0; +} diff --git a/nuttx/drivers/usbhost/usbhost_enumerate.c b/nuttx/drivers/usbhost/usbhost_enumerate.c new file mode 100644 index 0000000000..8e1cd80e71 --- /dev/null +++ b/nuttx/drivers/usbhost/usbhost_enumerate.c @@ -0,0 +1,517 @@ +/******************************************************************************* + * drivers/usbhost/usbhost_enumerate.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +/******************************************************************************* + * Included Files + *******************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/******************************************************************************* + * Definitions + *******************************************************************************/ + +/******************************************************************************* + * Private Types + *******************************************************************************/ + +/******************************************************************************* + * Private Function Prototypes + *******************************************************************************/ + +static inline uint16_t usbhost_getle16(const uint8_t *val); +static void usbhost_putle16(uint8_t *dest, uint16_t val); + +static inline int usbhost_devdesc(const struct usb_devdesc_s *devdesc, + struct usbhost_id_s *id); +static inline int usbhost_configdesc(const uint8_t *configdesc, int desclen, + struct usbhost_id_s *id); +static inline int usbhost_classbind(FAR struct usbhost_driver_s *drvr, + const uint8_t *configdesc, int desclen, + struct usbhost_id_s *id, uint8_t funcaddr, + FAR struct usbhost_class_s **class); + +/******************************************************************************* + * Private Data + *******************************************************************************/ + +/******************************************************************************* + * Public Data + *******************************************************************************/ + +/******************************************************************************* + * Private Functions + *******************************************************************************/ + +/**************************************************************************** + * Name: usbhost_getle16 + * + * Description: + * Get a (possibly unaligned) 16-bit little endian value. + * + *******************************************************************************/ + +static inline uint16_t usbhost_getle16(const uint8_t *val) +{ + return (uint16_t)val[1] << 8 | (uint16_t)val[0]; +} + +/**************************************************************************** + * Name: usbhost_putle16 + * + * Description: + * Put a (possibly unaligned) 16-bit little endian value. + * + *******************************************************************************/ + +static void usbhost_putle16(uint8_t *dest, uint16_t val) +{ + dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */ + dest[1] = val >> 8; +} + +/******************************************************************************* + * Name: usbhost_devdesc + * + * Description: + * A configuration descriptor has been obtained from the device. Find the + * ID information for the class that supports this device. + * + *******************************************************************************/ + +static inline int usbhost_devdesc(const struct usb_devdesc_s *devdesc, + struct usbhost_id_s *id) +{ + /* Clear the ID info */ + + memset(id, 0, sizeof(struct usbhost_id_s)); + + /* Pick off the class ID info */ + + id->base = devdesc->class; + id->subclass = devdesc->subclass; + id->proto = devdesc->protocol; + + /* Pick off the VID and PID as well (for vendor specfic devices) */ + + id->vid = usbhost_getle16(devdesc->vendor); + id->pid = usbhost_getle16(devdesc->product); + + uvdbg("class:%d subclass:%04x protocol:%04x vid:%d pid:%d\n", + id->base, id->subclass, id->proto, id->vid, id->pid); + return OK; +} + +/******************************************************************************* + * Name: usbhost_configdesc + * + * Description: + * A configuration descriptor has been obtained from the device. Find the + * ID information for the class that supports this device. + * + *******************************************************************************/ + +static inline int usbhost_configdesc(const uint8_t *configdesc, int cfglen, + struct usbhost_id_s *id) +{ + struct usb_cfgdesc_s *cfgdesc; + struct usb_ifdesc_s *ifdesc; + int remaining; + + DEBUGASSERT(configdesc != NULL && cfglen >= USB_SIZEOF_CFGDESC); + + /* Verify that we were passed a configuration descriptor */ + + cfgdesc = (struct usb_cfgdesc_s *)configdesc; + uvdbg("cfg len:%d total len:%d\n", cfgdesc->len, cfglen); + + if (cfgdesc->type != USB_DESC_TYPE_CONFIG) + { + return -EINVAL; + } + + /* Skip to the next entry descriptor */ + + configdesc += cfgdesc->len; + remaining = cfglen - cfgdesc->len; + + /* Loop where there are more dscriptors to examine */ + + memset(id, 0, sizeof(FAR struct usb_desc_s)); + while (remaining >= sizeof(struct usb_desc_s)) + { + /* What is the next descriptor? Is it an interface descriptor? */ + + ifdesc = (struct usb_ifdesc_s *)configdesc; + if (ifdesc->type == USB_DESC_TYPE_INTERFACE) + { + /* Yes, extract the class information from the interface descriptor. + * Typically these values are zero meaning that the "real" ID + * information resides in the device descriptor. + */ + + DEBUGASSERT(remaining >= sizeof(struct usb_ifdesc_s)); + id->base = ifdesc->class; + id->subclass = ifdesc->subclass; + id->proto = ifdesc->protocol; + uvdbg("class:%d subclass:%d protocol:%d\n", + id->base, id->subclass, id->proto); + return OK; + } + + /* Increment the address of the next descriptor */ + + configdesc += ifdesc->len; + remaining -= ifdesc->len; + } + + return -ENOENT; +} + +/******************************************************************************* + * Name: usbhost_classbind + * + * Description: + * A configuration descriptor has been obtained from the device. Try to + * bind this configuration descriptor with a supported class. + * + *******************************************************************************/ + +static inline int usbhost_classbind(FAR struct usbhost_driver_s *drvr, + const uint8_t *configdesc, int desclen, + struct usbhost_id_s *id, uint8_t funcaddr, + FAR struct usbhost_class_s **class) +{ + FAR struct usbhost_class_s *devclass; + const struct usbhost_registry_s *reg; + int ret = -EINVAL; + + /* Is there is a class implementation registered to support this device. */ + + reg = usbhost_findclass(id); + uvdbg("usbhost_findclass: %p\n", reg); + if (reg) + { + /* Yes.. there is a class for this device. Get an instance of + * its interface. + */ + + ret = -ENOMEM; + devclass = CLASS_CREATE(reg, drvr, id); + uvdbg("CLASS_CREATE: %p\n", devclass); + if (devclass) + { + /* Then bind the newly instantiated class instance */ + + ret = CLASS_CONNECT(devclass, configdesc, desclen, funcaddr); + if (ret != OK) + { + /* On failures, call the class disconnect method which + * should then free the allocated devclass instance. + */ + + udbg("CLASS_CONNECT failed: %d\n", ret); + CLASS_DISCONNECTED(devclass); + } + else + { + *class = devclass; + } + } + } + + uvdbg("Returning: %d\n", ret); + return ret; +} + +/******************************************************************************* + * Public Functions + *******************************************************************************/ + +/******************************************************************************* + * Name: usbhost_enumerate + * + * Description: + * Enumerate the connected device. As part of this enumeration process, + * the driver will (1) get the device's configuration descriptor, (2) + * extract the class ID info from the configuration descriptor, (3) call + * usbhost_findclass() to find the class that supports this device, (4) + * call the create() method on the struct usbhost_registry_s interface + * to get a class instance, and finally (5) call the configdesc() method + * of the struct usbhost_class_s interface. After that, the class is in + * charge of the sequence of operations. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * funcaddr - The USB address of the function containing the endpoint that EP0 + * controls + * class - If the class driver for the device is successful located + * and bound to the driver, the allocated class instance is returned into + * this caller-provided memory location. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * - Only a single class bound to a single device is supported. + * - Called from a single thread so no mutual exclusion is required. + * - Never called from an interrupt handler. + * + *******************************************************************************/ + +int usbhost_enumerate(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, + FAR struct usbhost_class_s **class) +{ + struct usb_ctrlreq_s *ctrlreq; + struct usbhost_id_s id; + size_t maxlen; + unsigned int cfglen; + uint8_t maxpacketsize; + uint8_t *buffer; + int ret; + + DEBUGASSERT(drvr && class); + + /* Allocate TD buffers for use in this function. We will need two: + * One for the request and one for the data buffer. + */ + + ret = DRVR_ALLOC(drvr, (FAR uint8_t **)&ctrlreq, &maxlen); + if (ret != OK) + { + udbg("DRVR_ALLOC failed: %d\n", ret); + return ret; + } + + ret = DRVR_ALLOC(drvr, &buffer, &maxlen); + if (ret != OK) + { + udbg("DRVR_ALLOC failed: %d\n", ret); + goto errout; + } + + /* Set max pkt size = 8 */ + + DRVR_EP0CONFIGURE(drvr, 0, 8); + + /* Read first 8 bytes of the device descriptor */ + + ctrlreq->type = USB_REQ_DIR_IN|USB_REQ_RECIPIENT_DEVICE; + ctrlreq->req = USB_REQ_GETDESCRIPTOR; + usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_DEVICE << 8)); + usbhost_putle16(ctrlreq->index, 0); + usbhost_putle16(ctrlreq->len, 8); + + ret = DRVR_CTRLIN(drvr, ctrlreq, buffer); + if (ret != OK) + { + udbg("ERROR: GETDESCRIPTOR/DEVICE, DRVR_CTRLIN returned %d\n", ret); + goto errout; + } + + /* Extract the correct max packetsize from the device descriptor */ + + maxpacketsize = ((struct usb_devdesc_s *)buffer)->mxpacketsize; + uvdbg("maxpacksetsize: %d\n", maxpacketsize); + + /* And reconfigure EP0 */ + + DRVR_EP0CONFIGURE(drvr, 0, maxpacketsize); + + /* Now read the full device descriptor */ + + ctrlreq->type = USB_REQ_DIR_IN|USB_REQ_RECIPIENT_DEVICE; + ctrlreq->req = USB_REQ_GETDESCRIPTOR; + usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_DEVICE << 8)); + usbhost_putle16(ctrlreq->index, 0); + usbhost_putle16(ctrlreq->len, USB_SIZEOF_DEVDESC); + + ret = DRVR_CTRLIN(drvr, ctrlreq, buffer); + if (ret != OK) + { + udbg("ERROR: GETDESCRIPTOR/DEVICE, DRVR_CTRLIN returned %d\n", ret); + goto errout; + } + + /* Get class identification information from the device descriptor. Most + * devices set this to USB_CLASS_PER_INTERFACE (zero) and provide the + * identification informatino in the interface descriptor(s). That allows + * a device to support multiple, different classes. + */ + + (void)usbhost_devdesc((struct usb_devdesc_s *)buffer, &id); + + /* Set the USB device address to the value in the 'funcaddr' input */ + + ctrlreq->type = USB_REQ_DIR_OUT|USB_REQ_RECIPIENT_DEVICE; + ctrlreq->req = USB_REQ_SETADDRESS; + usbhost_putle16(ctrlreq->value, (uint16_t)funcaddr); + usbhost_putle16(ctrlreq->index, 0); + usbhost_putle16(ctrlreq->len, 0); + + ret = DRVR_CTRLOUT(drvr, ctrlreq, NULL); + if (ret != OK) + { + udbg("ERROR: SETADDRESS DRVR_CTRLOUT returned %d\n", ret); + goto errout; + } + up_mdelay(2); + + /* Modify control pipe with the provided USB device address */ + + DRVR_EP0CONFIGURE(drvr, funcaddr, maxpacketsize); + + /* Get the configuration descriptor (only), index == 0. Should not be + * hard-coded! More logic is needed in order to handle devices with + * multiple configurations. + */ + + ctrlreq->type = USB_REQ_DIR_IN|USB_REQ_RECIPIENT_DEVICE; + ctrlreq->req = USB_REQ_GETDESCRIPTOR; + usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_CONFIG << 8)); + usbhost_putle16(ctrlreq->index, 0); + usbhost_putle16(ctrlreq->len, USB_SIZEOF_CFGDESC); + + ret = DRVR_CTRLIN(drvr, ctrlreq, buffer); + if (ret != OK) + { + udbg("ERROR: GETDESCRIPTOR/CONFIG, DRVR_CTRLIN returned %d\n", ret); + goto errout; + } + + /* Extract the full size of the configuration data */ + + cfglen = (unsigned int)usbhost_getle16(((struct usb_cfgdesc_s *)buffer)->totallen); + uvdbg("sizeof config data: %d\n", cfglen); + + /* Get all of the configuration descriptor data, index == 0 (Should not be + * hard-coded!) + */ + + ctrlreq->type = USB_REQ_DIR_IN|USB_REQ_RECIPIENT_DEVICE; + ctrlreq->req = USB_REQ_GETDESCRIPTOR; + usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_CONFIG << 8)); + usbhost_putle16(ctrlreq->index, 0); + usbhost_putle16(ctrlreq->len, cfglen); + + ret = DRVR_CTRLIN(drvr, ctrlreq, buffer); + if (ret != OK) + { + udbg("ERROR: GETDESCRIPTOR/CONFIG, DRVR_CTRLIN returned %d\n", ret); + goto errout; + } + + /* Select device configuration 1 (Should not be hard-coded!) */ + + ctrlreq->type = USB_REQ_DIR_OUT|USB_REQ_RECIPIENT_DEVICE; + ctrlreq->req = USB_REQ_SETCONFIGURATION; + usbhost_putle16(ctrlreq->value, 1); + usbhost_putle16(ctrlreq->index, 0); + usbhost_putle16(ctrlreq->len, 0); + + ret = DRVR_CTRLOUT(drvr, ctrlreq, NULL); + if (ret != OK) + { + udbg("ERROR: SETCONFIGURATION, DRVR_CTRLOUT returned %d\n", ret); + goto errout; + } + + /* Free the TD that we were using for the request buffer. It is not needed + * further here but it may be needed by the class driver during its connection + * operations. + */ + + DRVR_FREE(drvr, (uint8_t*)ctrlreq); + ctrlreq = NULL; + + /* Was the class identification information provided in the device descriptor? + * Or do we need to find it in the interface descriptor(s)? + */ + + if (id.base == USB_CLASS_PER_INTERFACE) + { + /* Get the class identification information for this device from the + * interface descriptor(s). Hmmm.. More logic is need to handle the + * case of multiple interface descriptors. + */ + + ret = usbhost_configdesc(buffer, cfglen, &id); + if (ret != OK) + { + udbg("ERROR: usbhost_configdesc returned %d\n", ret); + goto errout; + } + } + + /* Some devices may require this delay before initialization */ + + up_mdelay(100); + + /* Parse the configuration descriptor and bind to the class instance for the + * device. This needs to be the last thing done because the class driver + * will begin configuring the device. + */ + + ret = usbhost_classbind(drvr, buffer, cfglen, &id, funcaddr, class); + if (ret != OK) + { + udbg("ERROR: usbhost_classbind returned %d\n", ret); + } + +errout: + if (buffer) + { + DRVR_FREE(drvr, buffer); + } + + if (ctrlreq) + { + DRVR_FREE(drvr, (uint8_t*)ctrlreq); + } + return ret; +} diff --git a/nuttx/drivers/usbhost/usbhost_findclass.c b/nuttx/drivers/usbhost/usbhost_findclass.c new file mode 100644 index 0000000000..f08aff580e --- /dev/null +++ b/nuttx/drivers/usbhost/usbhost_findclass.c @@ -0,0 +1,199 @@ +/**************************************************************************** + * drivers/usbhost/usbhost_findclass.c + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "usbhost_registry.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbhost_idmatch + * + * Description: + * Check if the class ID matches what the host controller found. + * + * Input Parameters: + * classid - ID info for the class under consideration. + * devid - ID info reported by the device. + * + * Returned Values: + * TRUE - the class will support this device. + * + ****************************************************************************/ + +static bool usbhost_idmatch(const struct usbhost_id_s *classid, + const struct usbhost_id_s *devid) +{ + uvdbg("Compare to class:%d subclass:%d protocol:%d vid:%04x pid:%04x\n", + classid->base, classid->subclass, classid->proto, + classid->vid, classid->pid); + + /* The base class ID, subclass and protocol have to match up in any event */ + + if (devid->base == classid->base && + devid->subclass == classid->subclass && + devid->proto == classid->proto) + { + /* If this is a vendor-specific class ID, then the VID and PID have to + * match as well. + */ + + if (devid->base == USB_CLASS_VENDOR_SPEC) + { + /* Vendor specific... do the VID and PID also match? */ + + if (devid->vid == classid->vid && devid->pid == classid->pid) + { + /* Yes.. then we have a match */ + + return true; + } + } + else + { + /* Not vendor specific? Then we have a match */ + + return true; + } + } + + /* No match.. not supported */ + + return false; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbhost_findclass + * + * Description: + * Find a USB host class implementation previously registered by + * usbhost_registerclass(). On success, an instance of struct + * usbhost_registry_s will be returned. That instance will contain all of + * the information that will be needed to obtain and bind a struct + * usbhost_class_s instance for the device. + * + * Input Parameters: + * id - Identifies the USB device class that has connect to the USB host. + * + * Returned Values: + * On success this function will return a non-NULL instance of struct + * usbhost_registry_s. NULL will be returned on failure. This function + * can only fail if (1) id is NULL, or (2) no USB host class is registered + * that matches the device class ID. + * + ****************************************************************************/ + +const struct usbhost_registry_s *usbhost_findclass(const struct usbhost_id_s *id) +{ + struct usbhost_registry_s *class; + irqstate_t flags; + int ndx; + + DEBUGASSERT(id); + uvdbg("Looking for class:%d subclass:%d protocol:%d vid:%04x pid:%04x\n", + id->base, id->subclass, id->proto, id->vid, id->pid); + + /* g_classregistry is a singly-linkedlist of class ID information added by + * calls to usbhost_registerclass(). Since this list is accessed from USB + * host controller interrupt handling logic, accesses to this list must be + * protected by disabling interrupts. + */ + + flags = irqsave(); + + /* Examine each register class in the linked list */ + + for (class = g_classregistry; class; class = class->flink) + { + /* If the registered class supports more than one ID, subclass, or + * protocol, then try each. + */ + + uvdbg("Checking class:%p nids:%d\n", class, class->nids); + for (ndx = 0; ndx < class->nids; ndx++) + { + /* Did we find a matching ID? */ + + if (usbhost_idmatch(&class->id[ndx], id)) + { + /* Yes.. restore interrupts and return the class info */ + + irqrestore(flags); + return class; + } + } + } + + /* Not found... restore interrupts and return NULL */ + + irqrestore(flags); + return NULL; +} + diff --git a/nuttx/drivers/usbhost/usbhost_hidkbd.c b/nuttx/drivers/usbhost/usbhost_hidkbd.c new file mode 100644 index 0000000000..ce951e1e63 --- /dev/null +++ b/nuttx/drivers/usbhost/usbhost_hidkbd.c @@ -0,0 +1,2048 @@ +/**************************************************************************** + * drivers/usbhost/usbhost_hidkbd.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +/* Don't compile if prerequisites are not met */ + +#if defined(CONFIG_USBHOST) && !defined(CONFIG_USBHOST_INT_DISABLE) && CONFIG_NFILE_DESCRIPTORS > 0 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* This determines how often the USB keyboard will be polled in units of + * of microseconds. The default is 100MS. + */ + +#ifndef CONFIG_HIDKBD_POLLUSEC +# define CONFIG_HIDKBD_POLLUSEC (100*1000) +#endif + +/* Worker thread is needed, unfortunately, to handle some cornercase failure + * conditions. This is kind of wasteful and begs for a re-design. + */ + +#ifndef CONFIG_SCHED_WORKQUEUE +# warning "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)" +#endif + +/* Signals must not be disabled as they are needed by usleep. Need to have + * CONFIG_DISABLE_SIGNALS=n + */ + +#ifdef CONFIG_DISABLE_SIGNALS +# warning "Signal support is required (CONFIG_DISABLE_SIGNALS)" +#endif + +/* Provide some default values for other configuration settings */ + +#ifndef CONFIG_HIDKBD_DEFPRIO +# define CONFIG_HIDKBD_DEFPRIO 50 +#endif + +#ifndef CONFIG_HIDKBD_STACKSIZE +# define CONFIG_HIDKBD_STACKSIZE 1024 +#endif + +#ifndef CONFIG_HIDKBD_BUFSIZE +# define CONFIG_HIDKBD_BUFSIZE 64 +#endif + +#ifndef CONFIG_HIDKBD_NPOLLWAITERS +# define CONFIG_HIDKBD_NPOLLWAITERS 2 +#endif + +/* The default is to support scancode mapping for the standard 104 key + * keyboard. Setting CONFIG_HIDKBD_RAWSCANCODES will disable all scancode + * mapping; Setting CONFIG_HIDKBD_ALLSCANCODES will enable mapping of all + * scancodes; + */ + +#ifndef CONFIG_HIDKBD_RAWSCANCODES +# ifdef CONFIG_HIDKBD_ALLSCANCODES +# define USBHID_NUMSCANCODES (USBHID_KBDUSE_MAX+1) +# else +# define USBHID_NUMSCANCODES 104 +# endif +#endif + +/* Driver support ***********************************************************/ +/* This format is used to construct the /dev/kbd[n] device driver path. It + * defined here so that it will be used consistently in all places. + */ + +#define DEV_FORMAT "/dev/kbd%c" +#define DEV_NAMELEN 11 + +/* Used in usbhost_cfgdesc() */ + +#define USBHOST_IFFOUND 0x01 /* Required I/F descriptor found */ +#define USBHOST_EPINFOUND 0x02 /* Required interrupt IN EP descriptor found */ +#define USBHOST_EPOUTFOUND 0x04 /* Optional interrupt OUT EP descriptor found */ +#define USBHOST_RQDFOUND (USBHOST_IFFOUND|USBHOST_EPINFOUND) +#define USBHOST_ALLFOUND (USBHOST_RQDFOUND|USBHOST_EPOUTFOUND) + +#define USBHOST_MAX_CREFS 0x7fff + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure contains the internal, private state of the USB host + * keyboard storage class. + */ + +struct usbhost_state_s +{ + /* This is the externally visible portion of the state */ + + struct usbhost_class_s class; + + /* This is an instance of the USB host driver bound to this class instance */ + + struct usbhost_driver_s *drvr; + + /* The remainder of the fields are provide o the keyboard class driver */ + + char devchar; /* Character identifying the /dev/kbd[n] device */ + volatile bool disconnected; /* TRUE: Device has been disconnected */ + volatile bool polling; /* TRUE: Poll thread is running */ + volatile bool open; /* TRUE: The keyboard device is open */ + volatile bool waiting; /* TRUE: waiting for keyboard data */ + uint8_t ifno; /* Interface number */ + int16_t crefs; /* Reference count on the driver instance */ + sem_t exclsem; /* Used to maintain mutual exclusive access */ + sem_t waitsem; /* Used to wait for keyboard data */ + FAR uint8_t *tbuffer; /* The allocated transfer buffer */ + size_t tbuflen; /* Size of the allocated transfer buffer */ + pid_t pollpid; /* PID of the poll task */ + struct work_s work; /* For cornercase error handling by the worker thread */ + + /* Endpoints: + * EP0 (Control): + * - Receiving and responding to requests for USB control and class data. + * - IN data when polled by the HID class driver (Get_Report) + * - OUT data from the host. + * EP Interrupt IN: + * - Receiving asynchronous (unrequested) IN data from the device. + * EP Interrrupt OUT (optional): + * - Transmitting low latency OUT data to the device. + * - If not present, EP0 used. + */ + + usbhost_ep_t epin; /* Interrupt IN endpoint */ + usbhost_ep_t epout; /* Optional interrupt OUT endpoint */ + + /* The following is a list if poll structures of threads waiting for + * driver events. The 'struct pollfd' reference for each open is also + * retained in the f_priv field of the 'struct file'. + */ + +#ifndef CONFIG_DISABLE_POLL + struct pollfd *fds[CONFIG_HIDKBD_NPOLLWAITERS]; +#endif + + /* Buffer used to collect and buffer incoming keyboard characters */ + + volatile uint16_t headndx; /* Buffer head index */ + volatile uint16_t tailndx; /* Buffer tail index */ + uint8_t kbdbuffer[CONFIG_HIDKBD_BUFSIZE]; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Semaphores */ + +static void usbhost_takesem(sem_t *sem); +#define usbhost_givesem(s) sem_post(s); + +/* Polling support */ + +#ifndef CONFIG_DISABLE_POLL +static void usbhost_pollnotify(FAR struct usbhost_state_s *dev); +#else +# define usbhost_pollnotify(dev) +#endif + +/* Memory allocation services */ + +static inline FAR struct usbhost_state_s *usbhost_allocclass(void); +static inline void usbhost_freeclass(FAR struct usbhost_state_s *class); + +/* Device name management */ + +static int usbhost_allocdevno(FAR struct usbhost_state_s *priv); +static void usbhost_freedevno(FAR struct usbhost_state_s *priv); +static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname); + +/* Keyboard polling thread */ + +static void usbhost_destroy(FAR void *arg); +static inline uint8_t usbhost_mapscancode(uint8_t scancode, uint8_t modifier); +static int usbhost_kbdpoll(int argc, char *argv[]); + +/* Helpers for usbhost_connect() */ + +static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv, + FAR const uint8_t *configdesc, int desclen, + uint8_t funcaddr); +static inline int usbhost_devinit(FAR struct usbhost_state_s *priv); + +/* (Little Endian) Data helpers */ + +static inline uint16_t usbhost_getle16(const uint8_t *val); +static inline void usbhost_putle16(uint8_t *dest, uint16_t val); +static inline uint32_t usbhost_getle32(const uint8_t *val); +static void usbhost_putle32(uint8_t *dest, uint32_t val); + +/* Transfer descriptor memory management */ + +static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv); +static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv); + +/* struct usbhost_registry_s methods */ + +static struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *drvr, + FAR const struct usbhost_id_s *id); + +/* struct usbhost_class_s methods */ + +static int usbhost_connect(FAR struct usbhost_class_s *class, + FAR const uint8_t *configdesc, int desclen, + uint8_t funcaddr); +static int usbhost_disconnected(FAR struct usbhost_class_s *class); + +/* Driver methods. We export the keyboard as a standard character driver */ + +static int usbhost_open(FAR struct file *filep); +static int usbhost_close(FAR struct file *filep); +static ssize_t usbhost_read(FAR struct file *filep, + FAR char *buffer, size_t len); +static ssize_t usbhost_write(FAR struct file *filep, + FAR const char *buffer, size_t len); +#ifndef CONFIG_DISABLE_POLL +static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This structure provides the registry entry ID informatino that will be + * used to associate the USB host keyboard class driver to a connected USB + * device. + */ + +static const const struct usbhost_id_s g_id = +{ + USB_CLASS_HID, /* base */ + USBHID_SUBCLASS_BOOTIF, /* subclass */ + USBHID_PROTOCOL_KEYBOARD, /* proto */ + 0, /* vid */ + 0 /* pid */ +}; + +/* This is the USB host storage class's registry entry */ + +static struct usbhost_registry_s g_skeleton = +{ + NULL, /* flink */ + usbhost_create, /* create */ + 1, /* nids */ + &g_id /* id[] */ +}; + +static const struct file_operations usbhost_fops = +{ + usbhost_open, /* open */ + usbhost_close, /* close */ + usbhost_read, /* read */ + usbhost_write, /* write */ + 0, /* seek */ + 0 /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , usbhost_poll /* poll */ +#endif +}; + +/* This is a bitmap that is used to allocate device names /dev/kbda-z. */ + +static uint32_t g_devinuse; + +/* The following are used to managed the class creation operation */ + +static sem_t g_exclsem; /* For mutually exclusive thread creation */ +static sem_t g_syncsem; /* Thread data passing interlock */ +static struct usbhost_state_s *g_priv; /* Data passed to thread */ + +/* The following tables map keyboard scan codes to printable ASIC + * characters. There is no support here for function keys or cursor + * controls. + */ + +#ifndef CONFIG_HIDKBD_RAWSCANCODES +static const uint8_t ucmap[USBHID_NUMSCANCODES] = +{ + 0, 0, 0, 0, 'A', 'B', 'C', 'D', /* 0x00-0x07: Reserved, errors, A-D */ + 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', /* 0x08-0x0f: E-L */ + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 0x10-0x17: M-T */ + 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', /* 0x18-0x1f: U-Z,!,@ */ + '#', '$', '%', '^', '&', '*', '(', ')', /* 0x20-0x27: #,$,%,^,&,*,(,) */ + '\n', '\033', '\177', 0, ' ', '_', '+', '{', /* 0x28-0x2f: Enter,escape,del,back-tab,space,_,+,{ */ + '}', '|', 0, ':', '"', 0, '<', '>', /* 0x30-0x37: },|,Non-US tilde,:,",grave tidle,<,> */ + '?', 0, 0, 0, 0, 0, 0, 0, /* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,sScrollLock */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */ + 0, 0, 0, 0, '/', '*', '-', '+', /* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */ + '\n', '1', '2', '3', '4', '4', '6', '7', /* 0x58-0x5f: Enter,1-7 */ + '8', '9', '0', '.', 0, 0, 0, '=', /* 0x60-0x67: 8-9,0,.,Non-US \,Application,Power,= */ +#ifdef CONFIG_HIDKBD_ALLSCANCODES + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x68-0x6f: F13,F14,F15,F16,F17,F18,F19,F20 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77: F21,F22,F23,F24,Execute,Help,Menu,Select */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x78-0x7f: Stop,Again,Undo,Cut,Copy,Paste,Find,Mute */ + 0, 0, 0, 0, 0, ',', 0, 0, /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x88-0x8f: International 2-9 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x97: LAN 1-8 */ + 0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Ease,SysReq,Cancel,Clear,Prior,Return,Separator */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa8-0xaf: (reserved) */ + 0, 0, 0, 0, 0, 0, '(', ')', /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */ + '{', '}', '\t', \177, 'A', 'B', 'C', 'D', /* 0xb8-0xbf: {,},tab,backspace,A-D */ + 'F', 'F', 0, '^', '%', '<', '>', '&', /* 0xc0-0xc7: E-F,XOR,^,%,<,>,& */ + 0, '|', 0, ':', '%', ' ', '@', '!', /* 0xc8-0xcf: &&,|,||,:,#, ,@,! */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0-0xd7: Memory Store,Recall,Clear,Add,Subtract,Muliply,Divide,+/- */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd8-0xdf: Clear,ClearEntry,Binary,Octal,Decimal,Hexadecimal */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0-0xe7: Left Ctrl,Shift,Alt,GUI, Right Ctrl,Shift,Alt,GUI */ +#endif +}; + +static const uint8_t lcmap[USBHID_NUMSCANCODES] = +{ + 0, 0, 0, 0, 'a', 'b', 'c', 'd', /* 0x00-0x07: Reserved, errors, a-d */ + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', /* 0x08-0x0f: e-l */ + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', /* 0x10-0x17: m-t */ + 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', /* 0x18-0x1f: u-z,1-2 */ + '3', '4', '5', '6', '7', '8', '9', '0', /* 0x20-0x27: 3-9,0 */ + '\n', '\033', '\177', '\t', ' ', '-', '=', '[', /* 0x28-0x2f: Enter,escape,del,tab,space,-,=,[ */ + ']', '\\', '\234', ';', '\'', 0, ',', '.', /* 0x30-0x37: ],\,Non-US pound,;,',grave accent,,,. */ + '/', 0, 0, 0, 0, 0, 0, 0, /* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,ScrollLock */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */ + 0, 0, 0, 0, '/', '*', '-', '+', /* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */ + '\n', '1', '2', '3', '4', '4', '6', '7', /* 0x58-0x5f: Enter,1-7 */ + '8', '9', '0', '.', 0, 0, 0, '=', /* 0x60-0x67: 8-9,0,.,Non-US \,Application,Power,= */ +#ifdef CONFIG_HIDKBD_ALLSCANCODES + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x68-0x6f: F13,F14,F15,F16,F17,F18,F19,F20 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77: F21,F22,F23,F24,Execute,Help,Menu,Select */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x78-0x7f: Stop,Again,Undo,Cut,Copy,Paste,Find,Mute */ + 0, 0, 0, 0, 0, ',', 0, 0, /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x88-0x8f: International 2-9 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x97: LAN 1-8 */ + 0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Ease,SysReq,Cancel,Clear,Prior,Return,Separator */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa8-0xaf: (reserved) */ + 0, 0, 0, 0, 0, 0, '(', ')', /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */ + '{', '}', '\t', '\177', 'A', 'B', 'C', 'D', /* 0xb8-0xbf: {,},tab,backspace,A-D */ + 'F', 'F', 0, '^', '%', '<', '>', '&', /* 0xc0-0xc7: E-F,XOR,^,%,<,>,& */ + 0, '|', 0, ':', '%', ' ', '@', '!', /* 0xc8-0xcf: &&,|,||,:,#, ,@,! */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0-0xd7: Memory Store,Recall,Clear,Add,Subtract,Muliply,Divide,+/- */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd8-0xdf: Clear,ClearEntry,Binary,Octal,Decimal,Hexadecimal */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0-0xe7: Left Ctrl,Shift,Alt,GUI, Right Ctrl,Shift,Alt,GUI */ +#endif +}; +#endif /* CONFIG_HIDKBD_RAWSCANCODES */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbhost_takesem + * + * Description: + * This is just a wrapper to handle the annoying behavior of semaphore + * waits that return due to the receipt of a signal. + * + ****************************************************************************/ + +static void usbhost_takesem(sem_t *sem) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(sem) != 0) + { + /* The only case that an error should occr here is if the wait was + * awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Name: usbhost_pollnotify + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static void usbhost_pollnotify(FAR struct usbhost_state_s *priv) +{ + int i; + + for (i = 0; i < CONFIG_HIDKBD_NPOLLWAITERS; i++) + { + struct pollfd *fds = priv->fds[i]; + if (fds) + { + fds->revents |= (fds->events & POLLIN); + if (fds->revents != 0) + { + uvdbg("Report events: %02x\n", fds->revents); + sem_post(fds->sem); + } + } + } +} +#endif + +/**************************************************************************** + * Name: usbhost_allocclass + * + * Description: + * This is really part of the logic that implements the create() method + * of struct usbhost_registry_s. This function allocates memory for one + * new class instance. + * + * Input Parameters: + * None + * + * Returned Values: + * On success, this function will return a non-NULL instance of struct + * usbhost_class_s. NULL is returned on failure; this function will + * will fail only if there are insufficient resources to create another + * USB host class instance. + * + ****************************************************************************/ + +static inline FAR struct usbhost_state_s *usbhost_allocclass(void) +{ + FAR struct usbhost_state_s *priv; + + DEBUGASSERT(!up_interrupt_context()); + priv = (FAR struct usbhost_state_s *)kmalloc(sizeof(struct usbhost_state_s)); + uvdbg("Allocated: %p\n", priv);; + return priv; +} + +/**************************************************************************** + * Name: usbhost_freeclass + * + * Description: + * Free a class instance previously allocated by usbhost_allocclass(). + * + * Input Parameters: + * class - A reference to the class instance to be freed. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline void usbhost_freeclass(FAR struct usbhost_state_s *class) +{ + DEBUGASSERT(class != NULL); + + /* Free the class instance. */ + + uvdbg("Freeing: %p\n", class);; + kfree(class); +} + +/**************************************************************************** + * Name: Device name management + * + * Description: + * Some tiny functions to coordinate management of device names. + * + ****************************************************************************/ + +static int usbhost_allocdevno(FAR struct usbhost_state_s *priv) +{ + irqstate_t flags; + int devno; + + flags = irqsave(); + for (devno = 0; devno < 26; devno++) + { + uint32_t bitno = 1 << devno; + if ((g_devinuse & bitno) == 0) + { + g_devinuse |= bitno; + priv->devchar = 'a' + devno; + irqrestore(flags); + return OK; + } + } + + irqrestore(flags); + return -EMFILE; +} + +static void usbhost_freedevno(FAR struct usbhost_state_s *priv) +{ + int devno = 'a' - priv->devchar; + + if (devno >= 0 && devno < 26) + { + irqstate_t flags = irqsave(); + g_devinuse &= ~(1 << devno); + irqrestore(flags); + } +} + +static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname) +{ + (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->devchar); +} + +/**************************************************************************** + * Name: usbhost_destroy + * + * Description: + * The USB device has been disconnected and the refernce count on the USB + * host class instance has gone to 1.. Time to destroy the USB host class + * instance. + * + * Input Parameters: + * arg - A reference to the class instance to be destroyed. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void usbhost_destroy(FAR void *arg) +{ + FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)arg; + char devname[DEV_NAMELEN]; + + DEBUGASSERT(priv != NULL); + uvdbg("crefs: %d\n", priv->crefs); + + /* Unregister the driver */ + + uvdbg("Unregister driver\n"); + usbhost_mkdevname(priv, devname); + (void)unregister_driver(devname); + + /* Release the device name used by this connection */ + + usbhost_freedevno(priv); + + /* Free the interrupt endpoints */ + + if (priv->epin) + { + DRVR_EPFREE(priv->drvr, priv->epin); + } + + if (priv->epout) + { + DRVR_EPFREE(priv->drvr, priv->epout); + } + + /* Free any transfer buffers */ + + usbhost_tdfree(priv); + + /* Destroy the semaphores */ + + sem_destroy(&priv->exclsem); + sem_destroy(&priv->waitsem); + + /* Disconnect the USB host device */ + + DRVR_DISCONNECT(priv->drvr); + + /* And free the class instance. Hmmm.. this may execute on the worker + * thread and the work structure is part of what is getting freed. That + * should be okay because once the work contained is removed from the + * queue, it should not longer be accessed by the worker thread. + */ + + usbhost_freeclass(priv); +} + +/**************************************************************************** + * Name: usbhost_mapscancode + * + * Description: + * Map a keyboard scancode to a printable ASCII character. There is no + * support here for function keys or cursor controls in this version of + * the driver. + * + * Input Parameters: + * scancode - Scan code to be mapped. + * modifier - Ctrl,Alt,Shift,GUI modifier bits + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline uint8_t usbhost_mapscancode(uint8_t scancode, uint8_t modifier) +{ +#ifndef CONFIG_HIDKBD_RAWSCANCODES + /* Range check */ + + if (scancode >= USBHID_NUMSCANCODES) + { + return 0; + } + + /* Is either shift key pressed? */ + + if ((modifier & (USBHID_MODIFER_LSHIFT|USBHID_MODIFER_RSHIFT)) != 0) + { + return ucmap[scancode]; + } + else + { + return lcmap[scancode]; + } +#else + return scancode; +#endif +} + +/**************************************************************************** + * Name: usbhost_kbdpoll + * + * Description: + * Periodically check for new keyboard data. + * + * Input Parameters: + * arg - A reference to the class instance to be destroyed. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static int usbhost_kbdpoll(int argc, char *argv[]) +{ + FAR struct usbhost_state_s *priv; + FAR struct usb_ctrlreq_s *ctrlreq; +#ifndef CONFIG_HIDKBD_NODEBOUNCE + uint8_t lastkey[6] = {0, 0, 0, 0, 0, 0}; +#endif +#if defined(CONFIG_DEBUG_USB) && defined(CONFIG_DEBUG_VERBOSE) + unsigned int npolls = 0; +#endif + unsigned int nerrors; + int ret; + + uvdbg("Started\n"); + + /* Synchronize with the start-up logic. Get the private instance, re-start + * the start-up logic, and wait a bit to make sure that all of the class + * creation logic has a chance to run to completion. + * + * NOTE: that the reference count is incremented here. Therefore, we know + * that the driver data structure will remain stable while this thread is + * running. + */ + + priv = g_priv; + DEBUGASSERT(priv != NULL); + + priv->polling = true; + priv->crefs++; + usbhost_givesem(&g_syncsem); + sleep(1); + + /* Loop here until the device is disconnected */ + + uvdbg("Entering poll loop\n"); + while (!priv->disconnected) + { + /* Make sure that we have exclusive access to the private data + * structure. There may now be other tasks with the character driver + * open and actively trying to interact with the class driver. + */ + + usbhost_takesem(&priv->exclsem); + + /* Format the HID report request: + * + * bmRequestType 10100001 + * bRequest GET_REPORT (0x01) + * wValue Report Type and Report Index + * wIndex Interface Number + * wLength Descriptor Length + * Data Descriptor Data + */ + + ctrlreq = (struct usb_ctrlreq_s *)priv->tbuffer; + ctrlreq->type = USB_REQ_DIR_IN|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE; + ctrlreq->req = USBHID_REQUEST_GETREPORT; + + usbhost_putle16(ctrlreq->value, (USBHID_REPORTTYPE_INPUT << 8)); + usbhost_putle16(ctrlreq->index, priv->ifno); + usbhost_putle16(ctrlreq->len, sizeof(struct usbhid_kbdreport_s)); + + /* Send HID report request */ + + ret = DRVR_CTRLIN(priv->drvr, ctrlreq, priv->tbuffer); + usbhost_givesem(&priv->exclsem); + + /* Check for errors -- Bail if an excessive number of errors + * are encountered. + */ + + if (ret != OK) + { + nerrors++; + udbg("ERROR: GETREPORT/INPUT, DRVR_CTRLIN returned: %d/%d\n", + ret, nerrors); + + if (nerrors > 200) + { + udbg("Too many errors... aborting: %d\n", nerrors); + break; + } + } + + /* The report was received correctly. But ignore the keystrokes if no + * task has opened the driver. + */ + + else if (priv->open) + { + struct usbhid_kbdreport_s *rpt = (struct usbhid_kbdreport_s *)priv->tbuffer; + unsigned int head; + unsigned int tail; + uint8_t ascii; + int i; + + /* Add the newly received keystrokes to our internal buffer */ + + usbhost_takesem(&priv->exclsem); + head = priv->headndx; + tail = priv->tailndx; + + for (i = 0; i < 6; i++) + { + /* Is this key pressed? But not pressed last time? + * HID spec: "The order of keycodes in array fields has no + * significance. Order determination is done by the host + * software comparing the contents of the previous report to + * the current report. If two or more keys are reported in + * one report, their order is indeterminate. Keyboards may + * buffer events that would have otherwise resulted in + * multiple event in a single report. + * + * "'Repeat Rate' and 'Delay Before First Repeat' are + * implemented by the host and not in the keyboard (this + * means the BIOS in legacy mode). The host may use the + * device report rate and the number of reports to determine + * how long a key is being held down. Alternatively, the host + * may use its own clock or the idle request for the timing + * of these features." + */ + + if (rpt->key[i] != USBHID_KBDUSE_NONE +#ifndef CONFIG_HIDKBD_NODEBOUNCE + && rpt->key[i] != lastkey[i] +#endif + ) + { + /* Yes.. Add it to the buffer. */ + + /* Map the keyboard scancode to a printable ASCII + * character. There is no support here for function keys + * or cursor controls in this version of the driver. + */ + + ascii = usbhost_mapscancode(rpt->key[i], rpt->modifier); + uvdbg("Key %d: %02x ASCII:%c modifier: %02x\n", + i, rpt->key[i], ascii ? ascii : ' ', rpt->modifier); + + /* Zero at this point means that the key does not map to a + * printable character. + */ + + if (ascii != 0) + { + /* Handle control characters. Zero after this means + * a valid, NUL character. + */ + + if ((rpt->modifier & (USBHID_MODIFER_LCTRL|USBHID_MODIFER_RCTRL)) != 0) + { + ascii &= 0x1f; + } + + /* Copy the next keyboard character into the user + * buffer. + */ + + priv->kbdbuffer[head] = ascii; + + /* Increment the head index */ + + if (++head >= CONFIG_HIDKBD_BUFSIZE) + { + head = 0; + } + + /* If the buffer is full, then increment the tail + * index to make space. Is it better to lose old + * keystrokes or new? + */ + + if (tail == head) + { + if (++tail >= CONFIG_HIDKBD_BUFSIZE) + { + tail = 0; + } + } + } + } + /* Save the scancode (or lack thereof) for key debouncing on + * next keyboard report. + */ + +#ifndef CONFIG_HIDKBD_NODEBOUNCE + lastkey[i] = rpt->key[i]; +#endif + } + + /* Did we just transition from no data available to data available? */ + + if (head != tail && priv->headndx == priv->tailndx) + { + /* Yes.. Is there a thread waiting for keyboard data now? */ + + if (priv->waiting) + { + /* Yes.. wake it up */ + + usbhost_givesem(&priv->waitsem); + priv->waiting = false; + } + + /* And wake up any threads waiting for the POLLIN event */ + + usbhost_pollnotify(priv); + } + + /* Update the head/tail indices */ + + priv->headndx = head; + priv->tailndx = tail; + usbhost_givesem(&priv->exclsem); + } + + /* If USB debug is on, then provide some periodic indication that + * polling is still happening. + */ + +#if defined(CONFIG_DEBUG_USB) && defined(CONFIG_DEBUG_VERBOSE) + npolls++; + if ((npolls & 31) == 0) + { + udbg("Still polling: %d\n", npolls); + } +#endif + /* Wait for the required amount (or until a signal is received). We + * will wake up when either the delay elapses or we are signalled that + * the device has been disconnected. + */ + + usleep(CONFIG_HIDKBD_POLLUSEC); + } + + /* We get here when the driver is removed.. or when too many errors have + * been encountered. + * + * Make sure that we have exclusive access to the private data structure. + * There may now be other tasks with the character driver open and actively + * trying to interact with the class driver. + */ + + usbhost_takesem(&priv->exclsem); + + /* Indicate that we are no longer running and decrement the reference + * count help by this thread. If there are no other users of the class, + * we can destroy it now. Otherwise, we have to wait until the all + * of the file descriptors are closed. + */ + + udbg("Keyboard removed, polling halted\n"); + priv->polling = false; + if (--priv->crefs < 2) + { + /* Destroy the instance (while we hold the semaphore!) */ + + usbhost_destroy(priv); + } + else + { + /* No, we will destroy the driver instance when it is finally closed */ + + usbhost_givesem(&priv->exclsem); + } + return 0; +} + +/**************************************************************************** + * Name: usbhost_cfgdesc + * + * Description: + * This function implements the connect() method of struct + * usbhost_class_s. This method is a callback into the class + * implementation. It is used to provide the device's configuration + * descriptor to the class so that the class may initialize properly + * + * Input Parameters: + * priv - The USB host class instance. + * configdesc - A pointer to a uint8_t buffer container the configuration descripor. + * desclen - The length in bytes of the configuration descriptor. + * funcaddr - The USB address of the function containing the endpoint that EP0 + * controls + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ****************************************************************************/ + +static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv, + FAR const uint8_t *configdesc, int desclen, + uint8_t funcaddr) +{ + FAR struct usb_cfgdesc_s *cfgdesc; + FAR struct usb_desc_s *desc; + FAR struct usbhost_epdesc_s epindesc; + FAR struct usbhost_epdesc_s epoutdesc; + int remaining; + uint8_t found = 0; + bool done = false; + int ret; + + DEBUGASSERT(priv != NULL && + configdesc != NULL && + desclen >= sizeof(struct usb_cfgdesc_s)); + + /* Verify that we were passed a configuration descriptor */ + + cfgdesc = (FAR struct usb_cfgdesc_s *)configdesc; + if (cfgdesc->type != USB_DESC_TYPE_CONFIG) + { + return -EINVAL; + } + + /* Get the total length of the configuration descriptor (little endian). + * It might be a good check to get the number of interfaces here too. + */ + + remaining = (int)usbhost_getle16(cfgdesc->totallen); + + /* Skip to the next entry descriptor */ + + configdesc += cfgdesc->len; + remaining -= cfgdesc->len; + + /* Loop where there are more dscriptors to examine */ + + while (remaining >= sizeof(struct usb_desc_s) && !done) + { + /* What is the next descriptor? */ + + desc = (FAR struct usb_desc_s *)configdesc; + switch (desc->type) + { + /* Interface descriptor. We really should get the number of endpoints + * from this descriptor too. + */ + + case USB_DESC_TYPE_INTERFACE: + { + FAR struct usb_ifdesc_s *ifdesc = (FAR struct usb_ifdesc_s *)configdesc; + + uvdbg("Interface descriptor\n"); + DEBUGASSERT(remaining >= USB_SIZEOF_IFDESC); + + /* Did we already find what we needed from a preceding interface? */ + + if ((found & USBHOST_RQDFOUND) == USBHOST_RQDFOUND) + { + /* Yes.. then break out of the loop and use the preceding + * interface. + */ + + done = true; + } + else + { + /* Otherwise, save the interface number and discard any + * endpoints previously found + */ + + priv->ifno = ifdesc->ifno; + found = USBHOST_IFFOUND; + } + } + break; + + /* HID descriptor */ + + case USBHID_DESCTYPE_HID: + uvdbg("HID descriptor\n"); + break; + + /* Endpoint descriptor. We expect one or two interrupt endpoints, + * a required IN endpoint and an optional OUT endpoint. + */ + + case USB_DESC_TYPE_ENDPOINT: + { + FAR struct usb_epdesc_s *epdesc = (FAR struct usb_epdesc_s *)configdesc; + + uvdbg("Endpoint descriptor\n"); + DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC); + + /* Check for an interrupt endpoint. */ + + if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_INT) + { + /* Yes.. it is a interrupt endpoint. IN or OUT? */ + + if (USB_ISEPOUT(epdesc->addr)) + { + /* It is an interrupt OUT endpoint. There not be more than one + * interrupt OUT endpoint. + */ + + if ((found & USBHOST_EPOUTFOUND) != 0) + { + /* Oops.. more than one endpoint. We don't know what to do with this. */ + + return -EINVAL; + } + found |= USBHOST_EPOUTFOUND; + + /* Save the interrupt OUT endpoint information */ + + epoutdesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK; + epoutdesc.in = false; + epoutdesc.funcaddr = funcaddr; + epoutdesc.xfrtype = USB_EP_ATTR_XFER_INT; + epoutdesc.interval = epdesc->interval; + epoutdesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize); + uvdbg("Interrupt OUT EP addr:%d mxpacketsize:%d\n", + epoutdesc.addr, epoutdesc.mxpacketsize); + } + else + { + /* It is an interrupt IN endpoint. There should be only + * one interrupt IN endpoint. + */ + + if ((found & USBHOST_EPINFOUND) != 0) + { + /* Oops.. more than one endpint. We don't know what + * to do with this. + */ + + return -EINVAL; + } + found |= USBHOST_EPINFOUND; + + /* Save the interrupt IN endpoint information */ + + epindesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK; + epindesc.in = 1; + epindesc.funcaddr = funcaddr; + epindesc.xfrtype = USB_EP_ATTR_XFER_INT; + epindesc.interval = epdesc->interval; + epindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize); + uvdbg("Interrupt IN EP addr:%d mxpacketsize:%d\n", + epindesc.addr, epindesc.mxpacketsize); + } + } + } + break; + + /* Other descriptors are just ignored for now */ + + default: + uvdbg("Other descriptor: %d\n", desc->type); + break; + } + + /* What we found everything that we are going to find? */ + + if (found == USBHOST_ALLFOUND) + { + /* Yes.. then break out of the loop and use the preceding interface */ + + done = true; + } + + /* Increment the address of the next descriptor */ + + configdesc += desc->len; + remaining -= desc->len; + } + + /* Sanity checking... did we find all of things that we need? */ + + if ((found & USBHOST_RQDFOUND) != USBHOST_RQDFOUND) + { + ulldbg("ERROR: Found IF:%s EPIN:%s\n", + (found & USBHOST_IFFOUND) != 0 ? "YES" : "NO", + (found & USBHOST_EPINFOUND) != 0 ? "YES" : "NO"); + return -EINVAL; + } + + /* We are good... Allocate the endpoints. First, the required interrupt + * IN endpoint. + */ + + ret = DRVR_EPALLOC(priv->drvr, &epindesc, &priv->epin); + if (ret != OK) + { + udbg("ERROR: Failed to allocate interrupt IN endpoint\n"); + return ret; + } + + /* Then the optional interrupt OUT endpoint */ + + ullvdbg("Found EPOOUT:%s\n", + (found & USBHOST_EPOUTFOUND) != 0 ? "YES" : "NO"); + + if ((found & USBHOST_EPOUTFOUND) != 0) + { + ret = DRVR_EPALLOC(priv->drvr, &epoutdesc, &priv->epout); + if (ret != OK) + { + udbg("ERROR: Failed to allocate interrupt OUT endpoint\n"); + (void)DRVR_EPFREE(priv->drvr, priv->epin); + return ret; + } + } + + ullvdbg("Endpoints allocated\n"); + return OK; +} + +/**************************************************************************** + * Name: usbhost_devinit + * + * Description: + * The USB device has been successfully connected. This completes the + * initialization operations. It is first called after the + * configuration descriptor has been received. + * + * This function is called from the connect() method. This function always + * executes on the thread of the caller of connect(). + * + * Input Parameters: + * priv - A reference to the class instance. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline int usbhost_devinit(FAR struct usbhost_state_s *priv) +{ + char devname[DEV_NAMELEN]; + int ret; + + /* Set aside a transfer buffer for exclusive use by the keyboard class driver */ + + ret = usbhost_tdalloc(priv); + if (ret != OK) + { + udbg("ERROR: Failed to allocate transfer buffer\n"); + return ret; + } + + /* Increment the reference count. This will prevent usbhost_destroy() from + * being called asynchronously if the device is removed. + */ + + priv->crefs++; + DEBUGASSERT(priv->crefs == 2); + + /* Start a worker task to poll the USB device. It would be nice to used the + * the NuttX worker thread to do this, but this task needs to wait for events + * and activities on the worker thread should not involve significant waiting. + * Having a dedicated thread is more efficient in this sense, but requires more + * memory resources, primarily for the dedicated stack (CONFIG_HIDKBD_STACKSIZE). + */ + + uvdbg("user_start: Start poll task\n"); + + /* The inputs to a task started by task_create() are very awkard for this + * purpose. They are really designed for command line tasks (argc/argv). So + * the following is kludge pass binary data when the keyboard poll task + * is started. + * + * First, make sure we have exclusive access to g_priv (what is the likelihood + * of this being used? About zero, but we protect it anyway). + */ + + usbhost_takesem(&g_exclsem); + g_priv = priv; + +#ifndef CONFIG_CUSTOM_STACK + priv->pollpid = task_create("usbhost", CONFIG_HIDKBD_DEFPRIO, + CONFIG_HIDKBD_STACKSIZE, + (main_t)usbhost_kbdpoll, (const char **)NULL); +#else + priv->pollpid = task_create("usbhost", CONFIG_HIDKBD_DEFPRIO, + (main_t)usbhost_kbdpoll, (const char **)NULL); +#endif + if (priv->pollpid == ERROR) + { + /* Failed to started the poll thread... probably due to memory resources */ + + usbhost_givesem(&g_exclsem); + ret = -ENOMEM; + goto errout; + } + + /* Now wait for the poll task to get properly initialized */ + + usbhost_takesem(&g_syncsem); + usbhost_givesem(&g_exclsem); + + /* Register the driver */ + + uvdbg("Register driver\n"); + usbhost_mkdevname(priv, devname); + ret = register_driver(devname, &usbhost_fops, 0666, priv); + + /* We now have to be concerned about asynchronous modification of crefs + * because the driver has been registerd. + */ + +errout: + usbhost_takesem(&priv->exclsem); + priv->crefs--; + usbhost_givesem(&priv->exclsem); + return ret; +} + +/**************************************************************************** + * Name: usbhost_getle16 + * + * Description: + * Get a (possibly unaligned) 16-bit little endian value. + * + * Input Parameters: + * val - A pointer to the first byte of the little endian value. + * + * Returned Values: + * A uint16_t representing the whole 16-bit integer value + * + ****************************************************************************/ + +static inline uint16_t usbhost_getle16(const uint8_t *val) +{ + return (uint16_t)val[1] << 8 | (uint16_t)val[0]; +} + +/**************************************************************************** + * Name: usbhost_putle16 + * + * Description: + * Put a (possibly unaligned) 16-bit little endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the little endian value. + * val - The 16-bit value to be saved. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void usbhost_putle16(uint8_t *dest, uint16_t val) +{ + dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */ + dest[1] = val >> 8; +} + +/**************************************************************************** + * Name: usbhost_getle32 + * + * Description: + * Get a (possibly unaligned) 32-bit little endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the big endian value. + * val - The 32-bit value to be saved. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline uint32_t usbhost_getle32(const uint8_t *val) +{ + /* Little endian means LS halfword first in byte stream */ + + return (uint32_t)usbhost_getle16(&val[2]) << 16 | (uint32_t)usbhost_getle16(val); +} + +/**************************************************************************** + * Name: usbhost_putle32 + * + * Description: + * Put a (possibly unaligned) 32-bit little endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the little endian value. + * val - The 32-bit value to be saved. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void usbhost_putle32(uint8_t *dest, uint32_t val) +{ + /* Little endian means LS halfword first in byte stream */ + + usbhost_putle16(dest, (uint16_t)(val & 0xffff)); + usbhost_putle16(dest+2, (uint16_t)(val >> 16)); +} + +/**************************************************************************** + * Name: usbhost_tdalloc + * + * Description: + * Allocate transfer buffer memory. + * + * Input Parameters: + * priv - A reference to the class instance. + * + * Returned Values: + * On sucess, zero (OK) is returned. On failure, an negated errno value + * is returned to indicate the nature of the failure. + * + ****************************************************************************/ + +static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv) +{ + DEBUGASSERT(priv && priv->tbuffer == NULL); + return DRVR_ALLOC(priv->drvr, &priv->tbuffer, &priv->tbuflen); +} + +/**************************************************************************** + * Name: usbhost_tdfree + * + * Description: + * Free transfer buffer memory. + * + * Input Parameters: + * priv - A reference to the class instance. + * + * Returned Values: + * On sucess, zero (OK) is returned. On failure, an negated errno value + * is returned to indicate the nature of the failure. + * + ****************************************************************************/ + +static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv) +{ + int result = OK; + DEBUGASSERT(priv); + + if (priv->tbuffer) + { + DEBUGASSERT(priv->drvr); + result = DRVR_FREE(priv->drvr, priv->tbuffer); + priv->tbuffer = NULL; + priv->tbuflen = 0; + } + return result; +} + +/**************************************************************************** + * struct usbhost_registry_s methods + ****************************************************************************/ + +/**************************************************************************** + * Name: usbhost_create + * + * Description: + * This function implements the create() method of struct usbhost_registry_s. + * The create() method is a callback into the class implementation. It is + * used to (1) create a new instance of the USB host class state and to (2) + * bind a USB host driver "session" to the class instance. Use of this + * create() method will support environments where there may be multiple + * USB ports and multiple USB devices simultaneously connected. + * + * Input Parameters: + * drvr - An instance of struct usbhost_driver_s that the class + * implementation will "bind" to its state structure and will + * subsequently use to communicate with the USB host driver. + * id - In the case where the device supports multiple base classes, + * subclasses, or protocols, this specifies which to configure for. + * + * Returned Values: + * On success, this function will return a non-NULL instance of struct + * usbhost_class_s that can be used by the USB host driver to communicate + * with the USB host class. NULL is returned on failure; this function + * will fail only if the drvr input parameter is NULL or if there are + * insufficient resources to create another USB host class instance. + * + ****************************************************************************/ + +static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *drvr, + FAR const struct usbhost_id_s *id) +{ + FAR struct usbhost_state_s *priv; + + /* Allocate a USB host class instance */ + + priv = usbhost_allocclass(); + if (priv) + { + /* Initialize the allocated storage class instance */ + + memset(priv, 0, sizeof(struct usbhost_state_s)); + + /* Assign a device number to this class instance */ + + if (usbhost_allocdevno(priv) == OK) + { + /* Initialize class method function pointers */ + + priv->class.connect = usbhost_connect; + priv->class.disconnected = usbhost_disconnected; + + /* The initial reference count is 1... One reference is held by the driver */ + + priv->crefs = 1; + + /* Initialize semaphores */ + + sem_init(&priv->exclsem, 0, 1); + sem_init(&priv->waitsem, 0, 0); + + /* Bind the driver to the storage class instance */ + + priv->drvr = drvr; + + /* Return the instance of the USB keyboard class driver */ + + return &priv->class; + } + } + + /* An error occurred. Free the allocation and return NULL on all failures */ + + if (priv) + { + usbhost_freeclass(priv); + } + return NULL; +} + +/**************************************************************************** + * struct usbhost_class_s methods + ****************************************************************************/ +/**************************************************************************** + * Name: usbhost_connect + * + * Description: + * This function implements the connect() method of struct + * usbhost_class_s. This method is a callback into the class + * implementation. It is used to provide the device's configuration + * descriptor to the class so that the class may initialize properly + * + * Input Parameters: + * class - The USB host class entry previously obtained from a call to create(). + * configdesc - A pointer to a uint8_t buffer container the configuration descripor. + * desclen - The length in bytes of the configuration descriptor. + * funcaddr - The USB address of the function containing the endpoint that EP0 + * controls + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * NOTE that the class instance remains valid upon return with a failure. It is + * the responsibility of the higher level enumeration logic to call + * CLASS_DISCONNECTED to free up the class driver resources. + * + * Assumptions: + * - This function will *not* be called from an interrupt handler. + * - If this function returns an error, the USB host controller driver + * must call to DISCONNECTED method to recover from the error + * + ****************************************************************************/ + +static int usbhost_connect(FAR struct usbhost_class_s *class, + FAR const uint8_t *configdesc, int desclen, + uint8_t funcaddr) +{ + FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)class; + int ret; + + DEBUGASSERT(priv != NULL && + configdesc != NULL && + desclen >= sizeof(struct usb_cfgdesc_s)); + + /* Parse the configuration descriptor to get the endpoints */ + + ret = usbhost_cfgdesc(priv, configdesc, desclen, funcaddr); + if (ret != OK) + { + udbg("usbhost_cfgdesc() failed: %d\n", ret); + } + else + { + /* Now configure the device and register the NuttX driver */ + + ret = usbhost_devinit(priv); + if (ret != OK) + { + udbg("usbhost_devinit() failed: %d\n", ret); + } + } + + /* ERROR handling: Do nothing. If we return and error during connection, + * the driver is required to call the DISCONNECT method. Possibilities: + * + * - Failure occurred before the kbdpoll task was started successfully. + * In this case, the disconnection will have to be handled on the worker + * task. + * - Failure occured after the kbdpoll task was started succesffuly. In + * this case, the disconnetion can be performed on the kbdpoll thread. + */ + + return ret; +} + +/**************************************************************************** + * Name: usbhost_disconnected + * + * Description: + * This function implements the disconnected() method of struct + * usbhost_class_s. This method is a callback into the class + * implementation. It is used to inform the class that the USB device has + * been disconnected. + * + * Input Parameters: + * class - The USB host class entry previously obtained from a call to + * create(). + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value + * is returned indicating the nature of the failure + * + * Assumptions: + * This function may be called from an interrupt handler. + * + ****************************************************************************/ + +static int usbhost_disconnected(struct usbhost_class_s *class) +{ + FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)class; + + DEBUGASSERT(priv != NULL); + + /* Set an indication to any users of the keyboard device that the device + * is no longer available. + */ + + priv->disconnected = true; + ullvdbg("Disconnected\n"); + + /* Is there a thread waiting for keyboard data that will never come? */ + + if (priv->waiting) + { + /* Yes.. wake it up */ + + usbhost_givesem(&priv->waitsem); + priv->waiting = false; + } + + /* Possibilities: + * + * - Failure occurred before the kbdpoll task was started successfully. + * In this case, the disconnection will have to be handled on the worker + * task. + * - Failure occured after the kbdpoll task was started succesffuly. In + * this case, the disconnetion can be performed on the kbdpoll thread. + */ + + if (priv->polling) + { + /* The polling task is still alive. Signal the keyboard polling task. + * When that task wakes up, it will decrement the reference count and, + * perhaps, destroy the class instance. Then it will exit. + */ + + (void)kill(priv->pollpid, SIGALRM); + } + else + { + /* In the case where the failure occurs before the polling task was + * started. Now what? We are probably executing from an interrupt + * handler here. We will use the worker thread. This is kind of + * wasteful and begs for a re-design. + */ + + DEBUGASSERT(priv->work.worker == NULL); + (void)work_queue(&priv->work, usbhost_destroy, priv, 0); + } + + return OK; +} + +/**************************************************************************** + * Character driver methods + ****************************************************************************/ +/**************************************************************************** + * Name: usbhost_open + * + * Description: + * Standard character driver open method. + * + ****************************************************************************/ + +static int usbhost_open(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct usbhost_state_s *priv; + irqstate_t flags; + int ret; + + uvdbg("Entry\n"); + DEBUGASSERT(filep && filep->f_inode); + inode = filep->f_inode; + priv = inode->i_private; + + /* Make sure that we have exclusive access to the private data structure */ + + DEBUGASSERT(priv && priv->crefs > 0 && priv->crefs < USBHOST_MAX_CREFS); + usbhost_takesem(&priv->exclsem); + + /* Check if the keyboard device is still connected. We need to disable + * interrupts momentarily to assure that there are no asynchronous disconnect + * events. + */ + + flags = irqsave(); + if (priv->disconnected) + { + /* No... the driver is no longer bound to the class. That means that + * the USB storage device is no longer connected. Refuse any further + * attempts to open the driver. + */ + + ret = -ENODEV; + } + else + { + /* Otherwise, just increment the reference count on the driver */ + + priv->crefs++; + priv->open = true; + ret = OK; + } + irqrestore(flags); + + usbhost_givesem(&priv->exclsem); + return ret; +} + +/**************************************************************************** + * Name: usbhost_close + * + * Description: + * Standard character driver close method. + * + ****************************************************************************/ + +static int usbhost_close(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct usbhost_state_s *priv; + + uvdbg("Entry\n"); + DEBUGASSERT(filep && filep->f_inode); + inode = filep->f_inode; + priv = inode->i_private; + + /* Decrement the reference count on the driver */ + + DEBUGASSERT(priv->crefs > 1); + usbhost_takesem(&priv->exclsem); + priv->crefs--; + + /* Is this the last reference (other than the one held by the USB host + * controller driver) + */ + + if (priv->crefs <= 1) + { + irqstate_t flags; + + /* Yes.. then the driver is no longer open */ + + priv->open = false; + priv->headndx = 0; + priv->tailndx = 0; + + /* We need to disable interrupts momentarily to assure that there are + * no asynchronous disconnect events. + */ + + flags = irqsave(); + + /* Check if the USB keyboard device is still connected. If the device is + * no longer connected, then unregister the driver and free the driver + * class instance. + */ + + if (priv->disconnected) + { + /* Destroy the class instance (we can't use priv after this; we can't + * 'give' the semapore) + */ + + usbhost_destroy(priv); + irqrestore(flags); + return OK; + } + irqrestore(flags); + } + + usbhost_givesem(&priv->exclsem); + return OK; +} + +/**************************************************************************** + * Name: usbhost_read + * + * Description: + * Standard character driver read method. + * + ****************************************************************************/ + +static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + FAR struct inode *inode; + FAR struct usbhost_state_s *priv; + size_t nbytes; + unsigned int tail; + int ret; + + uvdbg("Entry\n"); + DEBUGASSERT(filep && filep->f_inode && buffer); + inode = filep->f_inode; + priv = inode->i_private; + + /* Make sure that we have exclusive access to the private data structure */ + + DEBUGASSERT(priv && priv->crefs > 0 && priv->crefs < USBHOST_MAX_CREFS); + usbhost_takesem(&priv->exclsem); + + /* Check if the keyboard is still connected. We need to disable interrupts + * momentarily to assure that there are no asynchronous disconnect events. + */ + + if (priv->disconnected) + { + /* No... the driver is no longer bound to the class. That means that + * the USB keybaord is no longer connected. Refuse any further attempts + * to access the driver. + */ + + ret = -ENODEV; + } + else + { + /* Is there keyboard data now? */ + + while (priv->tailndx == priv->headndx) + { + /* No.. were we open non-blocking? */ + + if (filep->f_oflags & O_NONBLOCK) + { + /* Yes.. then return a failure */ + + ret = -EAGAIN; + goto errout; + } + + /* Wait for data to be available */ + + uvdbg("Waiting...\n"); + priv->waiting = true; + usbhost_givesem(&priv->exclsem); + usbhost_takesem(&priv->waitsem); + usbhost_takesem(&priv->exclsem); + + /* Did the keyboard become disconnected while we were waiting */ + + if (priv->disconnected) + { + ret = -ENODEV; + goto errout; + } + } + + /* Read data from our internal buffer of received characters */ + + for (tail = priv->tailndx, nbytes = 0; + tail != priv->headndx && nbytes < len; + nbytes++) + { + /* Copy the next keyboard character into the user buffer */ + + *buffer++ = priv->kbdbuffer[tail]; + + /* Handle wrap-around of the tail index */ + + if (++tail >= CONFIG_HIDKBD_BUFSIZE) + { + tail = 0; + } + } + ret = nbytes; + + /* Update the tail index (pehaps marking the buffer empty) */ + + priv->tailndx = tail; + } + +errout: + usbhost_givesem(&priv->exclsem); + return (ssize_t)ret; +} + +/**************************************************************************** + * Name: usbhost_write + * + * Description: + * Standard character driver write method. + * + ****************************************************************************/ + +static ssize_t usbhost_write(FAR struct file *filep, FAR const char *buffer, size_t len) +{ + /* We won't try to write to the keyboard */ + + return -ENOSYS; +} + +/**************************************************************************** + * Name: usbhost_poll + * + * Description: + * Standard character driver poll method. + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct inode *inode; + FAR struct usbhost_state_s *priv; + int ret = OK; + int i; + + uvdbg("Entry\n"); + DEBUGASSERT(filep && filep->f_inode && fds); + inode = filep->f_inode; + priv = inode->i_private; + + /* Make sure that we have exclusive access to the private data structure */ + + DEBUGASSERT(priv); + usbhost_takesem(&priv->exclsem); + + /* Check if the keyboard is still connected. We need to disable interrupts + * momentarily to assure that there are no asynchronous disconnect events. + */ + + if (priv->disconnected) + { + /* No... the driver is no longer bound to the class. That means that + * the USB keybaord is no longer connected. Refuse any further attempts + * to access the driver. + */ + + ret = -ENODEV; + } + else if (setup) + { + /* This is a request to set up the poll. Find an availableslot for + * the poll structure reference + */ + + for (i = 0; i < CONFIG_HIDKBD_NPOLLWAITERS; i++) + { + /* Find an available slot */ + + if (!priv->fds[i]) + { + /* Bind the poll structure and this slot */ + + priv->fds[i] = fds; + fds->priv = &priv->fds[i]; + break; + } + } + + if (i >= CONFIG_HIDKBD_NPOLLWAITERS) + { + fds->priv = NULL; + ret = -EBUSY; + goto errout; + } + + /* Should we immediately notify on any of the requested events? Notify + * the POLLIN event if there is buffered keyboard data. + */ + + if (priv->headndx != priv->tailndx) + { + usbhost_pollnotify(priv); + } + } + else + { + /* This is a request to tear down the poll. */ + + struct pollfd **slot = (struct pollfd **)fds->priv; + DEBUGASSERT(slot); + + /* Remove all memory of the poll setup */ + + *slot = NULL; + fds->priv = NULL; + } + +errout: + sem_post(&priv->exclsem); + return ret; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbhost_kbdinit + * + * Description: + * Initialize the USB storage HID keyboard class driver. This function + * should be called be platform-specific code in order to initialize and + * register support for the USB host HID keyboard class device. + * + * Input Parameters: + * None + * + * Returned Values: + * On success this function will return zero (OK); A negated errno value + * will be returned on failure. + * + ****************************************************************************/ + +int usbhost_kbdinit(void) +{ + /* Perform any one-time initialization of the class implementation */ + + sem_init(&g_exclsem, 0, 1); + sem_init(&g_syncsem, 0, 0); + + /* Advertise our availability to support (certain) devices */ + + return usbhost_registerclass(&g_skeleton); +} + +#endif /* CONFIG_USBHOST)&& !CONFIG_USBHOST_INT_DISABLE && CONFIG_NFILE_DESCRIPTORS */ + + diff --git a/nuttx/drivers/usbhost/usbhost_registerclass.c b/nuttx/drivers/usbhost/usbhost_registerclass.c new file mode 100644 index 0000000000..76ef511af8 --- /dev/null +++ b/nuttx/drivers/usbhost/usbhost_registerclass.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * drivers/usbhost/usbhost_registerclass.c + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "usbhost_registry.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbhost_registerclass + * + * Description: + * Register a USB host class implementation. The caller provides an + * instance of struct usbhost_registry_s that contains all of the + * information that will be needed later to (1) associate the USB host + * class implementation with a connected USB device, and (2) to obtain and + * bind a struct usbhost_class_s instance for the device. + * + * Input Parameters: + * class - An write-able instance of struct usbhost_registry_s that will be + * maintained in a registry. + * + * Returned Values: + * On success, this function will return zero (OK). Otherwise, a negated + * errno value is returned. + * + ****************************************************************************/ + +int usbhost_registerclass(struct usbhost_registry_s *class) +{ + irqstate_t flags; + + uvdbg("Registering class:%p nids:%d\n", class, class->nids); + + /* g_classregistry is a singly-linkedlist of class ID information added by + * calls to usbhost_registerclass(). Since this list is accessed from USB + * host controller interrupt handling logic, accesses to this list must be + * protected by disabling interrupts. + */ + + flags = irqsave(); + + /* Add the new class ID info to the head of the list */ + + class->flink = g_classregistry; + g_classregistry = class; + + irqrestore(flags); + return OK; +} + diff --git a/nuttx/drivers/usbhost/usbhost_registry.c b/nuttx/drivers/usbhost/usbhost_registry.c new file mode 100644 index 0000000000..56c03e2dc5 --- /dev/null +++ b/nuttx/drivers/usbhost/usbhost_registry.c @@ -0,0 +1,80 @@ +/**************************************************************************** + * drivers/usbhost/usbhost_registry.c + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "usbhost_registry.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* g_classregistry is a singly-linkedlist of class ID information added by + * calls to usbhost_registerclass(). Since this list is accessed from USB + * host controller interrupt handling logic, accesses to this list must be + * protected by disabling interrupts. + */ + +struct usbhost_registry_s *g_classregistry; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/nuttx/drivers/usbhost/usbhost_registry.h b/nuttx/drivers/usbhost/usbhost_registry.h new file mode 100644 index 0000000000..63436af5d6 --- /dev/null +++ b/nuttx/drivers/usbhost/usbhost_registry.h @@ -0,0 +1,87 @@ +/**************************************************************************** + * drivers/usbhost/usbdev_registry.h + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_USBHOST_USBHOST_REGISTRY_H +#define __DRIVERS_USBHOST_USBHOST_REGISTRY_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" +{ +#else +# define EXTERN extern +#endif + +/* g_classregistry is a singly-linkedlist of class ID information added by + * calls to usbhost_registerclass(). Since this list is accessed from USB + * host controller interrupt handling logic, accesses to this list must be + * protected by disabling interrupts. + */ + +EXTERN struct usbhost_registry_s *g_classregistry; + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* #define __DRIVERS_USBHOST_USBHOST_REGISTRY_H */ diff --git a/nuttx/drivers/usbhost/usbhost_skeleton.c b/nuttx/drivers/usbhost/usbhost_skeleton.c new file mode 100644 index 0000000000..0a88a4f1ba --- /dev/null +++ b/nuttx/drivers/usbhost/usbhost_skeleton.c @@ -0,0 +1,1060 @@ +/**************************************************************************** + * drivers/usbhost/usbhost_skeleton.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_SCHED_WORKQUEUE +# warning "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)" +#endif + +/* Driver support ***********************************************************/ +/* This format is used to construct the /dev/skel[n] device driver path. It + * defined here so that it will be used consistently in all places. + */ + +#define DEV_FORMAT "/dev/skel%c" +#define DEV_NAMELEN 12 + +/* Used in usbhost_cfgdesc() */ + +#define USBHOST_IFFOUND 0x01 +#define USBHOST_BINFOUND 0x02 +#define USBHOST_BOUTFOUND 0x04 +#define USBHOST_ALLFOUND 0x07 + +#define USBHOST_MAX_CREFS 0x7fff + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure contains the internal, private state of the USB host class + * driver. + */ + +struct usbhost_state_s +{ + /* This is the externally visible portion of the state */ + + struct usbhost_class_s class; + + /* This is an instance of the USB host driver bound to this class instance */ + + struct usbhost_driver_s *drvr; + + /* The remainder of the fields are provide to the class driver */ + + char devchar; /* Character identifying the /dev/skel[n] device */ + volatile bool disconnected; /* TRUE: Device has been disconnected */ + uint8_t ifno; /* Interface number */ + int16_t crefs; /* Reference count on the driver instance */ + sem_t exclsem; /* Used to maintain mutual exclusive access */ + struct work_s work; /* For interacting with the worker thread */ + FAR uint8_t *tbuffer; /* The allocated transfer buffer */ + size_t tbuflen; /* Size of the allocated transfer buffer */ + usbhost_ep_t epin; /* IN endpoint */ + usbhost_ep_t epout; /* OUT endpoint */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Semaphores */ + +static void usbhost_takesem(sem_t *sem); +#define usbhost_givesem(s) sem_post(s); + +/* Memory allocation services */ + +static inline FAR struct usbhost_state_s *usbhost_allocclass(void); +static inline void usbhost_freeclass(FAR struct usbhost_state_s *class); + +/* Device name management */ + +static int usbhost_allocdevno(FAR struct usbhost_state_s *priv); +static void usbhost_freedevno(FAR struct usbhost_state_s *priv); +static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname); + +/* Worker thread actions */ + +static void usbhost_destroy(FAR void *arg); + +/* Helpers for usbhost_connect() */ + +static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv, + FAR const uint8_t *configdesc, int desclen, + uint8_t funcaddr); +static inline int usbhost_devinit(FAR struct usbhost_state_s *priv); + +/* (Little Endian) Data helpers */ + +static inline uint16_t usbhost_getle16(const uint8_t *val); +static inline void usbhost_putle16(uint8_t *dest, uint16_t val); +static inline uint32_t usbhost_getle32(const uint8_t *val); +static void usbhost_putle32(uint8_t *dest, uint32_t val); + +/* Transfer descriptor memory management */ + +static inline int usbhost_talloc(FAR struct usbhost_state_s *priv); +static inline int usbhost_tfree(FAR struct usbhost_state_s *priv); + +/* struct usbhost_registry_s methods */ + +static struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *drvr, + FAR const struct usbhost_id_s *id); + +/* struct usbhost_class_s methods */ + +static int usbhost_connect(FAR struct usbhost_class_s *class, + FAR const uint8_t *configdesc, int desclen, + uint8_t funcaddr); +static int usbhost_disconnected(FAR struct usbhost_class_s *class); + +/* Driver methods -- depend upon the type of NuttX driver interface exported */ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This structure provides the registry entry ID informatino that will be + * used to associate the USB class driver to a connected USB device. + */ + +static const const struct usbhost_id_s g_id = +{ + 0, /* base -- Must be one of the USB_CLASS_* definitions in usb.h */ + 0, /* subclass -- depends on the device */ + 0, /* proto -- depends on the device */ + 0, /* vid */ + 0 /* pid */ +}; + +/* This is the USB host storage class's registry entry */ + +static struct usbhost_registry_s g_skeleton = +{ + NULL, /* flink */ + usbhost_create, /* create */ + 1, /* nids */ + &g_id /* id[] */ +}; + +/* This is a bitmap that is used to allocate device names /dev/skela-z. */ + +static uint32_t g_devinuse; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbhost_takesem + * + * Description: + * This is just a wrapper to handle the annoying behavior of semaphore + * waits that return due to the receipt of a signal. + * + ****************************************************************************/ + +static void usbhost_takesem(sem_t *sem) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(sem) != 0) + { + /* The only case that an error should occr here is if the wait was + * awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Name: usbhost_allocclass + * + * Description: + * This is really part of the logic that implements the create() method + * of struct usbhost_registry_s. This function allocates memory for one + * new class instance. + * + * Input Parameters: + * None + * + * Returned Values: + * On success, this function will return a non-NULL instance of struct + * usbhost_class_s. NULL is returned on failure; this function will + * will fail only if there are insufficient resources to create another + * USB host class instance. + * + ****************************************************************************/ + +static inline FAR struct usbhost_state_s *usbhost_allocclass(void) +{ + FAR struct usbhost_state_s *priv; + + DEBUGASSERT(!up_interrupt_context()); + priv = (FAR struct usbhost_state_s *)kmalloc(sizeof(struct usbhost_state_s)); + uvdbg("Allocated: %p\n", priv);; + return priv; +} + +/**************************************************************************** + * Name: usbhost_freeclass + * + * Description: + * Free a class instance previously allocated by usbhost_allocclass(). + * + * Input Parameters: + * class - A reference to the class instance to be freed. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline void usbhost_freeclass(FAR struct usbhost_state_s *class) +{ + DEBUGASSERT(class != NULL); + + /* Free the class instance (perhaps calling sched_free() in case we are + * executing from an interrupt handler. + */ + + uvdbg("Freeing: %p\n", class);; + kfree(class); +} + +/**************************************************************************** + * Name: Device name management + * + * Description: + * Some tiny functions to coordinate management of device names. + * + ****************************************************************************/ + +static int usbhost_allocdevno(FAR struct usbhost_state_s *priv) +{ + irqstate_t flags; + int devno; + + flags = irqsave(); + for (devno = 0; devno < 26; devno++) + { + uint32_t bitno = 1 << devno; + if ((g_devinuse & bitno) == 0) + { + g_devinuse |= bitno; + priv->devchar = 'a' + devno; + irqrestore(flags); + return OK; + } + } + + irqrestore(flags); + return -EMFILE; +} + +static void usbhost_freedevno(FAR struct usbhost_state_s *priv) +{ + int devno = 'a' - priv->devchar; + + if (devno >= 0 && devno < 26) + { + irqstate_t flags = irqsave(); + g_devinuse &= ~(1 << devno); + irqrestore(flags); + } +} + +static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname) +{ + (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->devchar); +} + +/**************************************************************************** + * Name: usbhost_destroy + * + * Description: + * The USB device has been disconnected and the refernce count on the USB + * host class instance has gone to 1.. Time to destroy the USB host class + * instance. + * + * Input Parameters: + * arg - A reference to the class instance to be destroyed. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void usbhost_destroy(FAR void *arg) +{ + FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)arg; + + DEBUGASSERT(priv != NULL); + uvdbg("crefs: %d\n", priv->crefs); + + /* Unregister the driver */ + + /* Release the device name used by this connection */ + + usbhost_freedevno(priv); + + /* Free the endpoints */ + + /* Free any transfer buffers */ + + /* Destroy the semaphores */ + + /* Disconnect the USB host device */ + + DRVR_DISCONNECT(priv->drvr); + + /* And free the class instance. Hmmm.. this may execute on the worker + * thread and the work structure is part of what is getting freed. That + * should be okay because once the work contained is removed from the + * queue, it should not longer be accessed by the worker thread. + */ + + usbhost_freeclass(priv); +} + +/**************************************************************************** + * Name: usbhost_cfgdesc + * + * Description: + * This function implements the connect() method of struct + * usbhost_class_s. This method is a callback into the class + * implementation. It is used to provide the device's configuration + * descriptor to the class so that the class may initialize properly + * + * Input Parameters: + * priv - The USB host class instance. + * configdesc - A pointer to a uint8_t buffer container the configuration descripor. + * desclen - The length in bytes of the configuration descriptor. + * funcaddr - The USB address of the function containing the endpoint that EP0 + * controls + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ****************************************************************************/ + +static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv, + FAR const uint8_t *configdesc, int desclen, + uint8_t funcaddr) +{ + FAR struct usb_cfgdesc_s *cfgdesc; + FAR struct usb_desc_s *desc; + FAR struct usbhost_epdesc_s bindesc; + FAR struct usbhost_epdesc_s boutdesc; + int remaining; + uint8_t found = 0; + int ret; + + DEBUGASSERT(priv != NULL && + configdesc != NULL && + desclen >= sizeof(struct usb_cfgdesc_s)); + + /* Verify that we were passed a configuration descriptor */ + + cfgdesc = (FAR struct usb_cfgdesc_s *)configdesc; + if (cfgdesc->type != USB_DESC_TYPE_CONFIG) + { + return -EINVAL; + } + + /* Get the total length of the configuration descriptor (little endian). + * It might be a good check to get the number of interfaces here too. + */ + + remaining = (int)usbhost_getle16(cfgdesc->totallen); + + /* Skip to the next entry descriptor */ + + configdesc += cfgdesc->len; + remaining -= cfgdesc->len; + + /* Loop where there are more dscriptors to examine */ + + while (remaining >= sizeof(struct usb_desc_s)) + { + /* What is the next descriptor? */ + + desc = (FAR struct usb_desc_s *)configdesc; + switch (desc->type) + { + /* Interface descriptor. We really should get the number of endpoints + * from this descriptor too. + */ + + case USB_DESC_TYPE_INTERFACE: + { + FAR struct usb_ifdesc_s *ifdesc = (FAR struct usb_ifdesc_s *)configdesc; + + uvdbg("Interface descriptor\n"); + DEBUGASSERT(remaining >= USB_SIZEOF_IFDESC); + + /* Save the interface number and mark ONLY the interface found */ + + priv->ifno = ifdesc->ifno; + found = USBHOST_IFFOUND; + } + break; + + /* Endpoint descriptor. Here, we expect two bulk endpoints, an IN + * and an OUT. + */ + + case USB_DESC_TYPE_ENDPOINT: + { + FAR struct usb_epdesc_s *epdesc = (FAR struct usb_epdesc_s *)configdesc; + + uvdbg("Endpoint descriptor\n"); + DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC); + + /* Check for a bulk endpoint. */ + + if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_BULK) + { + /* Yes.. it is a bulk endpoint. IN or OUT? */ + + if (USB_ISEPOUT(epdesc->addr)) + { + /* It is an OUT bulk endpoint. There should be only one + * bulk OUT endpoint. + */ + + if ((found & USBHOST_BOUTFOUND) != 0) + { + /* Oops.. more than one endpoint. We don't know + * what to do with this. + */ + + return -EINVAL; + } + found |= USBHOST_BOUTFOUND; + + /* Save the bulk OUT endpoint information */ + + boutdesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK; + boutdesc.in = false; + boutdesc.funcaddr = funcaddr; + boutdesc.xfrtype = USB_EP_ATTR_XFER_BULK; + boutdesc.interval = epdesc->interval; + boutdesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize); + uvdbg("Bulk OUT EP addr:%d mxpacketsize:%d\n", + boutdesc.addr, boutdesc.mxpacketsize); + } + else + { + /* It is an IN bulk endpoint. There should be only one + * bulk IN endpoint. + */ + + if ((found & USBHOST_BINFOUND) != 0) + { + /* Oops.. more than one endpoint. We don't know + * what to do with this. + */ + + return -EINVAL; + } + found |= USBHOST_BINFOUND; + + /* Save the bulk IN endpoint information */ + + bindesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK; + bindesc.in = 1; + bindesc.funcaddr = funcaddr; + bindesc.xfrtype = USB_EP_ATTR_XFER_BULK; + bindesc.interval = epdesc->interval; + bindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize); + uvdbg("Bulk IN EP addr:%d mxpacketsize:%d\n", + bindesc.addr, bindesc.mxpacketsize); + } + } + } + break; + + /* Other descriptors are just ignored for now */ + + default: + break; + } + + /* If we found everything we need with this interface, then break out + * of the loop early. + */ + + if (found == USBHOST_ALLFOUND) + { + break; + } + + /* Increment the address of the next descriptor */ + + configdesc += desc->len; + remaining -= desc->len; + } + + /* Sanity checking... did we find all of things that we need? */ + + if (found != USBHOST_ALLFOUND) + { + ulldbg("ERROR: Found IF:%s BIN:%s BOUT:%s\n", + (found & USBHOST_IFFOUND) != 0 ? "YES" : "NO", + (found & USBHOST_BINFOUND) != 0 ? "YES" : "NO", + (found & USBHOST_BOUTFOUND) != 0 ? "YES" : "NO"); + return -EINVAL; + } + + /* We are good... Allocate the endpoints */ + + ret = DRVR_EPALLOC(priv->drvr, &boutdesc, &priv->epout); + if (ret != OK) + { + udbg("ERROR: Failed to allocate Bulk OUT endpoint\n"); + return ret; + } + + ret = DRVR_EPALLOC(priv->drvr, &bindesc, &priv->epin); + if (ret != OK) + { + udbg("ERROR: Failed to allocate Bulk IN endpoint\n"); + (void)DRVR_EPFREE(priv->drvr, priv->epout); + return ret; + } + + ullvdbg("Endpoints allocated\n"); + return OK; +} + +/**************************************************************************** + * Name: usbhost_devinit + * + * Description: + * The USB device has been successfully connected. This completes the + * initialization operations. It is first called after the + * configuration descriptor has been received. + * + * This function is called from the connect() method. This function always + * executes on the thread of the caller of connect(). + * + * Input Parameters: + * priv - A reference to the class instance. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline int usbhost_devinit(FAR struct usbhost_state_s *priv) +{ + int ret = OK; + + /* Set aside a transfer buffer for exclusive use by the class driver */ + + /* Increment the reference count. This will prevent usbhost_destroy() from + * being called asynchronously if the device is removed. + */ + + priv->crefs++; + DEBUGASSERT(priv->crefs == 2); + + /* Configure the device */ + + /* Register the driver */ + + if (ret == OK) + { + char devname[DEV_NAMELEN]; + + uvdbg("Register block driver\n"); + usbhost_mkdevname(priv, devname); + // ret = register_blockdriver(devname, &g_bops, 0, priv); + } + + /* Check if we successfully initialized. We now have to be concerned + * about asynchronous modification of crefs because the block + * driver has been registerd. + */ + + if (ret == OK) + { + usbhost_takesem(&priv->exclsem); + DEBUGASSERT(priv->crefs >= 2); + + /* Handle a corner case where (1) open() has been called so the + * reference count is > 2, but the device has been disconnected. + * In this case, the class instance needs to persist until close() + * is called. + */ + + if (priv->crefs <= 2 && priv->disconnected) + { + /* We don't have to give the semaphore because it will be + * destroyed when usb_destroy is called. + */ + + ret = -ENODEV; + } + else + { + /* Ready for normal operation as a block device driver */ + + uvdbg("Successfully initialized\n"); + priv->crefs--; + usbhost_givesem(&priv->exclsem); + } + } + + return ret; +} + +/**************************************************************************** + * Name: usbhost_getle16 + * + * Description: + * Get a (possibly unaligned) 16-bit little endian value. + * + * Input Parameters: + * val - A pointer to the first byte of the little endian value. + * + * Returned Values: + * A uint16_t representing the whole 16-bit integer value + * + ****************************************************************************/ + +static inline uint16_t usbhost_getle16(const uint8_t *val) +{ + return (uint16_t)val[1] << 8 | (uint16_t)val[0]; +} + +/**************************************************************************** + * Name: usbhost_putle16 + * + * Description: + * Put a (possibly unaligned) 16-bit little endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the little endian value. + * val - The 16-bit value to be saved. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void usbhost_putle16(uint8_t *dest, uint16_t val) +{ + dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */ + dest[1] = val >> 8; +} + +/**************************************************************************** + * Name: usbhost_getle32 + * + * Description: + * Get a (possibly unaligned) 32-bit little endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the big endian value. + * val - The 32-bit value to be saved. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline uint32_t usbhost_getle32(const uint8_t *val) +{ + /* Little endian means LS halfword first in byte stream */ + + return (uint32_t)usbhost_getle16(&val[2]) << 16 | (uint32_t)usbhost_getle16(val); +} + +/**************************************************************************** + * Name: usbhost_putle32 + * + * Description: + * Put a (possibly unaligned) 32-bit little endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the little endian value. + * val - The 32-bit value to be saved. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void usbhost_putle32(uint8_t *dest, uint32_t val) +{ + /* Little endian means LS halfword first in byte stream */ + + usbhost_putle16(dest, (uint16_t)(val & 0xffff)); + usbhost_putle16(dest+2, (uint16_t)(val >> 16)); +} + +/**************************************************************************** + * Name: usbhost_talloc + * + * Description: + * Allocate transfer buffer memory. + * + * Input Parameters: + * priv - A reference to the class instance. + * + * Returned Values: + * On sucess, zero (OK) is returned. On failure, an negated errno value + * is returned to indicate the nature of the failure. + * + ****************************************************************************/ + +static inline int usbhost_talloc(FAR struct usbhost_state_s *priv) +{ + DEBUGASSERT(priv && priv->tbuffer == NULL); + return DRVR_ALLOC(priv->drvr, &priv->tbuffer, &priv->tbuflen); +} + +/**************************************************************************** + * Name: usbhost_tfree + * + * Description: + * Free transfer buffer memory. + * + * Input Parameters: + * priv - A reference to the class instance. + * + * Returned Values: + * On sucess, zero (OK) is returned. On failure, an negated errno value + * is returned to indicate the nature of the failure. + * + ****************************************************************************/ + +static inline int usbhost_tfree(FAR struct usbhost_state_s *priv) +{ + int result = OK; + DEBUGASSERT(priv); + + if (priv->tbuffer) + { + DEBUGASSERT(priv->drvr); + result = DRVR_FREE(priv->drvr, priv->tbuffer); + priv->tbuffer = NULL; + priv->tbuflen = 0; + } + return result; +} + +/**************************************************************************** + * struct usbhost_registry_s methods + ****************************************************************************/ + +/**************************************************************************** + * Name: usbhost_create + * + * Description: + * This function implements the create() method of struct usbhost_registry_s. + * The create() method is a callback into the class implementation. It is + * used to (1) create a new instance of the USB host class state and to (2) + * bind a USB host driver "session" to the class instance. Use of this + * create() method will support environments where there may be multiple + * USB ports and multiple USB devices simultaneously connected. + * + * Input Parameters: + * drvr - An instance of struct usbhost_driver_s that the class + * implementation will "bind" to its state structure and will + * subsequently use to communicate with the USB host driver. + * id - In the case where the device supports multiple base classes, + * subclasses, or protocols, this specifies which to configure for. + * + * Returned Values: + * On success, this function will return a non-NULL instance of struct + * usbhost_class_s that can be used by the USB host driver to communicate + * with the USB host class. NULL is returned on failure; this function + * will fail only if the drvr input parameter is NULL or if there are + * insufficient resources to create another USB host class instance. + * + ****************************************************************************/ + +static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *drvr, + FAR const struct usbhost_id_s *id) +{ + FAR struct usbhost_state_s *priv; + + /* Allocate a USB host class instance */ + + priv = usbhost_allocclass(); + if (priv) + { + /* Initialize the allocated storage class instance */ + + memset(priv, 0, sizeof(struct usbhost_state_s)); + + /* Assign a device number to this class instance */ + + if (usbhost_allocdevno(priv) == OK) + { + /* Initialize class method function pointers */ + + priv->class.connect = usbhost_connect; + priv->class.disconnected = usbhost_disconnected; + + /* The initial reference count is 1... One reference is held by the driver */ + + priv->crefs = 1; + + /* Initialize semphores (this works okay in the interrupt context) */ + + sem_init(&priv->exclsem, 0, 1); + + /* Bind the driver to the storage class instance */ + + priv->drvr = drvr; + + /* Return the instance of the USB class driver */ + + return &priv->class; + } + } + + /* An error occurred. Free the allocation and return NULL on all failures */ + + if (priv) + { + usbhost_freeclass(priv); + } + return NULL; +} + +/**************************************************************************** + * struct usbhost_class_s methods + ****************************************************************************/ +/**************************************************************************** + * Name: usbhost_connect + * + * Description: + * This function implements the connect() method of struct + * usbhost_class_s. This method is a callback into the class + * implementation. It is used to provide the device's configuration + * descriptor to the class so that the class may initialize properly + * + * Input Parameters: + * class - The USB host class entry previously obtained from a call to create(). + * configdesc - A pointer to a uint8_t buffer container the configuration descripor. + * desclen - The length in bytes of the configuration descriptor. + * funcaddr - The USB address of the function containing the endpoint that EP0 + * controls + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * NOTE that the class instance remains valid upon return with a failure. It is + * the responsibility of the higher level enumeration logic to call + * CLASS_DISCONNECTED to free up the class driver resources. + * + * Assumptions: + * - This function will *not* be called from an interrupt handler. + * - If this function returns an error, the USB host controller driver + * must call to DISCONNECTED method to recover from the error + * + ****************************************************************************/ + +static int usbhost_connect(FAR struct usbhost_class_s *class, + FAR const uint8_t *configdesc, int desclen, + uint8_t funcaddr) +{ + FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)class; + int ret; + + DEBUGASSERT(priv != NULL && + configdesc != NULL && + desclen >= sizeof(struct usb_cfgdesc_s)); + + /* Parse the configuration descriptor to get the endpoints */ + + ret = usbhost_cfgdesc(priv, configdesc, desclen, funcaddr); + if (ret != OK) + { + udbg("usbhost_cfgdesc() failed: %d\n", ret); + } + else + { + /* Now configure the device and register the NuttX driver */ + + ret = usbhost_devinit(priv); + if (ret != OK) + { + udbg("usbhost_devinit() failed: %d\n", ret); + } + } + + return ret; +} + +/**************************************************************************** + * Name: usbhost_disconnected + * + * Description: + * This function implements the disconnected() method of struct + * usbhost_class_s. This method is a callback into the class + * implementation. It is used to inform the class that the USB device has + * been disconnected. + * + * Input Parameters: + * class - The USB host class entry previously obtained from a call to + * create(). + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value + * is returned indicating the nature of the failure + * + * Assumptions: + * This function may be called from an interrupt handler. + * + ****************************************************************************/ + +static int usbhost_disconnected(struct usbhost_class_s *class) +{ + FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)class; + irqstate_t flags; + + DEBUGASSERT(priv != NULL); + + /* Set an indication to any users of the device that the device is no + * longer available. + */ + + flags = irqsave(); + priv->disconnected = true; + + /* Now check the number of references on the class instance. If it is one, + * then we can free the class instance now. Otherwise, we will have to + * wait until the holders of the references free them by closing the + * block driver. + */ + + ullvdbg("crefs: %d\n", priv->crefs); + if (priv->crefs == 1) + { + /* Destroy the class instance. If we are executing from an interrupt + * handler, then defer the destruction to the worker thread. + * Otherwise, destroy the instance now. + */ + + if (up_interrupt_context()) + { + /* Destroy the instance on the worker thread. */ + + uvdbg("Queuing destruction: worker %p->%p\n", priv->work.worker, usbhost_destroy); + DEBUGASSERT(priv->work.worker == NULL); + (void)work_queue(&priv->work, usbhost_destroy, priv, 0); + } + else + { + /* Do the work now */ + + usbhost_destroy(priv); + } + } + + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbhost_skelinit + * + * Description: + * Initialize the USB class driver. This function should be called + * be platform-specific code in order to initialize and register support + * for the USB host class device. + * + * Input Parameters: + * None + * + * Returned Values: + * On success this function will return zero (OK); A negated errno value + * will be returned on failure. + * + ****************************************************************************/ + +int usbhost_skelinit(void) +{ + /* Perform any one-time initialization of the class implementation */ + + /* Advertise our availability to support (certain) devices */ + + return usbhost_registerclass(&g_skeleton); +} diff --git a/nuttx/drivers/usbhost/usbhost_storage.c b/nuttx/drivers/usbhost/usbhost_storage.c new file mode 100644 index 0000000000..2817c24462 --- /dev/null +++ b/nuttx/drivers/usbhost/usbhost_storage.c @@ -0,0 +1,2233 @@ +/**************************************************************************** + * drivers/usbhost/usbhost_storage.c + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Don't compile if prerequisites are not met */ + +#if defined(CONFIG_USBHOST) && !defined(CONFIG_USBHOST_BULK_DISABLE) && \ + !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_SCHED_WORKQUEUE +# warning "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)" +#endif + +/* If the create() method is called by the USB host device driver from an + * interrupt handler, then it will be unable to call kmalloc() in order to + * allocate a new class instance. If the create() method is called from the + * interrupt level, then class instances must be pre-allocated. + */ + +#ifndef CONFIG_USBHOST_NPREALLOC +# define CONFIG_USBHOST_NPREALLOC 0 +#endif + +#if CONFIG_USBHOST_NPREALLOC > 26 +# error "Currently limited to 26 devices /dev/sda-z" +#endif + +/* Driver support ***********************************************************/ +/* This format is used to construct the /dev/sd[n] device driver path. It + * defined here so that it will be used consistently in all places. + */ + +#define DEV_FORMAT "/dev/sd%c" +#define DEV_NAMELEN 10 + +/* Used in usbhost_connect() */ + +#define USBHOST_IFFOUND 0x01 +#define USBHOST_BINFOUND 0x02 +#define USBHOST_BOUTFOUND 0x04 +#define USBHOST_ALLFOUND 0x07 + +#define USBHOST_MAX_RETRIES 100 +#define USBHOST_MAX_CREFS 0x7fff + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure contains the internal, private state of the USB host mass + * storage class. + */ + +struct usbhost_state_s +{ + /* This is the externally visible portion of the state */ + + struct usbhost_class_s class; + + /* This is an instance of the USB host driver bound to this class instance */ + + struct usbhost_driver_s *drvr; + + /* The remainder of the fields are provide to the mass storage class */ + + char sdchar; /* Character identifying the /dev/sd[n] device */ + volatile bool disconnected; /* TRUE: Device has been disconnected */ + uint8_t ifno; /* Interface number */ + int16_t crefs; /* Reference count on the driver instance */ + uint16_t blocksize; /* Block size of USB mass storage device */ + uint32_t nblocks; /* Number of blocks on the USB mass storage device */ + sem_t exclsem; /* Used to maintain mutual exclusive access */ + struct work_s work; /* For interacting with the worker thread */ + FAR uint8_t *tbuffer; /* The allocated transfer buffer */ + size_t tbuflen; /* Size of the allocated transfer buffer */ + usbhost_ep_t bulkin; /* Bulk IN endpoint */ + usbhost_ep_t bulkout; /* Bulk OUT endpoint */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Semaphores */ + +static void usbhost_takesem(sem_t *sem); +#define usbhost_givesem(s) sem_post(s); + +/* Memory allocation services */ + +static inline FAR struct usbhost_state_s *usbhost_allocclass(void); +static inline void usbhost_freeclass(FAR struct usbhost_state_s *class); + +/* Device name management */ + +static int usbhost_allocdevno(FAR struct usbhost_state_s *priv); +static void usbhost_freedevno(FAR struct usbhost_state_s *priv); +static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname); + +/* CBW/CSW debug helpers */ + +#if defined(CONFIG_DEBUG_USB) && defined(CONFIG_DEBUG_VERBOSE) +static void usbhost_dumpcbw(FAR struct usbmsc_cbw_s *cbw); +static void usbhost_dumpcsw(FAR struct usbmsc_csw_s *csw); +#else +# define usbhost_dumpcbw(cbw); +# define usbhost_dumpcsw(csw); +#endif + +/* CBW helpers */ + +static inline void usbhost_requestsensecbw(FAR struct usbmsc_cbw_s *cbw); +static inline void usbhost_testunitreadycbw(FAR struct usbmsc_cbw_s *cbw); +static inline void usbhost_readcapacitycbw(FAR struct usbmsc_cbw_s *cbw); +static inline void usbhost_inquirycbw (FAR struct usbmsc_cbw_s *cbw); +static inline void usbhost_readcbw (size_t startsector, uint16_t blocksize, + unsigned int nsectors, + FAR struct usbmsc_cbw_s *cbw); +static inline void usbhost_writecbw(size_t startsector, uint16_t blocksize, + unsigned int nsectors, + FAR struct usbmsc_cbw_s *cbw); +/* Command helpers */ + +static inline int usbhost_maxlunreq(FAR struct usbhost_state_s *priv); +static inline int usbhost_testunitready(FAR struct usbhost_state_s *priv); +static inline int usbhost_requestsense(FAR struct usbhost_state_s *priv); +static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv); +static inline int usbhost_inquiry(FAR struct usbhost_state_s *priv); + +/* Worker thread actions */ + +static void usbhost_destroy(FAR void *arg); + +/* Helpers for usbhost_connect() */ + +static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv, + FAR const uint8_t *configdesc, int desclen, + uint8_t funcaddr); +static inline int usbhost_initvolume(FAR struct usbhost_state_s *priv); + +/* (Little Endian) Data helpers */ + +static inline uint16_t usbhost_getle16(const uint8_t *val); +static inline uint16_t usbhost_getbe16(const uint8_t *val); +static inline void usbhost_putle16(uint8_t *dest, uint16_t val); +static inline void usbhost_putbe16(uint8_t *dest, uint16_t val); +static inline uint32_t usbhost_getle32(const uint8_t *val); +static inline uint32_t usbhost_getbe32(const uint8_t *val); +static void usbhost_putle32(uint8_t *dest, uint32_t val); +static void usbhost_putbe32(uint8_t *dest, uint32_t val); + +/* Transfer descriptor memory management */ + +static inline int usbhost_talloc(FAR struct usbhost_state_s *priv); +static inline int usbhost_tfree(FAR struct usbhost_state_s *priv); +static FAR struct usbmsc_cbw_s *usbhost_cbwalloc(FAR struct usbhost_state_s *priv); + +/* struct usbhost_registry_s methods */ + +static struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *drvr, + FAR const struct usbhost_id_s *id); + +/* struct usbhost_class_s methods */ + +static int usbhost_connect(FAR struct usbhost_class_s *class, + FAR const uint8_t *configdesc, int desclen, + uint8_t funcaddr); +static int usbhost_disconnected(FAR struct usbhost_class_s *class); + +/* struct block_operations methods */ + +static int usbhost_open(FAR struct inode *inode); +static int usbhost_close(FAR struct inode *inode); +static ssize_t usbhost_read(FAR struct inode *inode, FAR unsigned char *buffer, + size_t startsector, unsigned int nsectors); +#ifdef CONFIG_FS_WRITABLE +static ssize_t usbhost_write(FAR struct inode *inode, + FAR const unsigned char *buffer, size_t startsector, + unsigned int nsectors); +#endif +static int usbhost_geometry(FAR struct inode *inode, + FAR struct geometry *geometry); +static int usbhost_ioctl(FAR struct inode *inode, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This structure provides the registry entry ID informatino that will be + * used to associate the USB host mass storage class to a connected USB + * device. + */ + +static const const struct usbhost_id_s g_id = +{ + USB_CLASS_MASS_STORAGE, /* base */ + USBMSC_SUBCLASS_SCSI, /* subclass */ + USBMSC_PROTO_BULKONLY, /* proto */ + 0, /* vid */ + 0 /* pid */ +}; + +/* This is the USB host storage class's registry entry */ + +static struct usbhost_registry_s g_storage = +{ + NULL, /* flink */ + usbhost_create, /* create */ + 1, /* nids */ + &g_id /* id[] */ +}; + +/* Block driver operations. This is the interface exposed to NuttX by the + * class that permits it to behave like a block driver. + */ + +static const struct block_operations g_bops = +{ + usbhost_open, /* open */ + usbhost_close, /* close */ + usbhost_read, /* read */ +#ifdef CONFIG_FS_WRITABLE + usbhost_write, /* write */ +#else + NULL, /* write */ +#endif + usbhost_geometry, /* geometry */ + usbhost_ioctl /* ioctl */ +}; + +/* This is an array of pre-allocated USB host storage class instances */ + +#if CONFIG_USBHOST_NPREALLOC > 0 +static struct usbhost_state_s g_prealloc[CONFIG_USBHOST_NPREALLOC]; +#endif + +/* This is a list of free, pre-allocated USB host storage class instances */ + +#if CONFIG_USBHOST_NPREALLOC > 0 +static struct usbhost_state_s *g_freelist; +#endif + +/* This is a bitmap that is used to allocate device names /dev/sda-z. */ + +static uint32_t g_devinuse; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbhost_takesem + * + * Description: + * This is just a wrapper to handle the annoying behavior of semaphore + * waits that return due to the receipt of a signal. + * + ****************************************************************************/ + +static void usbhost_takesem(sem_t *sem) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(sem) != 0) + { + /* The only case that an error should occr here is if the wait was + * awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Name: usbhost_allocclass + * + * Description: + * This is really part of the logic that implements the create() method + * of struct usbhost_registry_s. This function allocates memory for one + * new class instance. + * + * Input Parameters: + * None + * + * Returned Values: + * On success, this function will return a non-NULL instance of struct + * usbhost_class_s. NULL is returned on failure; this function will + * will fail only if there are insufficient resources to create another + * USB host class instance. + * + ****************************************************************************/ + +#if CONFIG_USBHOST_NPREALLOC > 0 +static inline FAR struct usbhost_state_s *usbhost_allocclass(void) +{ + struct usbhost_state_s *priv; + irqstate_t flags; + + /* We may be executing from an interrupt handler so we need to take one of + * our pre-allocated class instances from the free list. + */ + + flags = irqsave(); + priv = g_freelist; + if (priv) + { + g_freelist = priv->class.flink; + priv->class.flink = NULL; + } + irqrestore(flags); + ullvdbg("Allocated: %p\n", priv);; + return priv; +} +#else +static inline FAR struct usbhost_state_s *usbhost_allocclass(void) +{ + FAR struct usbhost_state_s *priv; + + /* We are not executing from an interrupt handler so we can just call + * kmalloc() to get memory for the class instance. + */ + + DEBUGASSERT(!up_interrupt_context()); + priv = (FAR struct usbhost_state_s *)kmalloc(sizeof(struct usbhost_state_s)); + uvdbg("Allocated: %p\n", priv);; + return priv; +} +#endif + +/**************************************************************************** + * Name: usbhost_freeclass + * + * Description: + * Free a class instance previously allocated by usbhost_allocclass(). + * + * Input Parameters: + * class - A reference to the class instance to be freed. + * + * Returned Values: + * None + * + ****************************************************************************/ + +#if CONFIG_USBHOST_NPREALLOC > 0 +static inline void usbhost_freeclass(FAR struct usbhost_state_s *class) +{ + irqstate_t flags; + DEBUGASSERT(class != NULL); + + ullvdbg("Freeing: %p\n", class);; + + /* Just put the pre-allocated class structure back on the freelist */ + + flags = irqsave(); + class->class.flink = g_freelist; + g_freelist = class; + irqrestore(flags); +} +#else +static inline void usbhost_freeclass(FAR struct usbhost_state_s *class) +{ + DEBUGASSERT(class != NULL); + + /* Free the class instance (calling sched_free() in case we are executing + * from an interrupt handler. + */ + + uvdbg("Freeing: %p\n", class);; + kfree(class); +} +#endif + +/**************************************************************************** + * Name: Device name management + * + * Description: + * Some tiny functions to coordinate management of mass storage device names. + * + ****************************************************************************/ + +static int usbhost_allocdevno(FAR struct usbhost_state_s *priv) +{ + irqstate_t flags; + int devno; + + flags = irqsave(); + for (devno = 0; devno < 26; devno++) + { + uint32_t bitno = 1 << devno; + if ((g_devinuse & bitno) == 0) + { + g_devinuse |= bitno; + priv->sdchar = 'a' + devno; + irqrestore(flags); + return OK; + } + } + + irqrestore(flags); + return -EMFILE; +} + +static void usbhost_freedevno(FAR struct usbhost_state_s *priv) +{ + int devno = 'a' - priv->sdchar; + + if (devno >= 0 && devno < 26) + { + irqstate_t flags = irqsave(); + g_devinuse &= ~(1 << devno); + irqrestore(flags); + } +} + +static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname) +{ + (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->sdchar); +} + +/**************************************************************************** + * Name: CBW/CSW debug helpers + * + * Description: + * The following functions are helper functions used to dump CBWs and CSWs. + * + * Input Parameters: + * cbw/csw - A reference to the CBW/CSW to dump. + * + * Returned Values: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_USB) && defined(CONFIG_DEBUG_VERBOSE) +static void usbhost_dumpcbw(FAR struct usbmsc_cbw_s *cbw) +{ + int i; + + uvdbg("CBW:\n"); + uvdbg(" signature: %08x\n", usbhost_getle32(cbw->signature)); + uvdbg(" tag: %08x\n", usbhost_getle32(cbw->tag)); + uvdbg(" datlen: %08x\n", usbhost_getle32(cbw->datlen)); + uvdbg(" flags: %02x\n", cbw->flags); + uvdbg(" lun: %02x\n", cbw->lun); + uvdbg(" cdblen: %02x\n", cbw->cdblen); + + uvdbg("CDB:\n"); + for (i = 0; i < cbw->cdblen; i += 8) + { + uvdbg(" %02x %02x %02x %02x %02x %02x %02x %02x\n", + cbw->cdb[i], cbw->cdb[i+1], cbw->cdb[i+2], cbw->cdb[i+3], + cbw->cdb[i+4], cbw->cdb[i+5], cbw->cdb[i+6], cbw->cdb[i+7]); + } +} + +static void usbhost_dumpcsw(FAR struct usbmsc_csw_s *csw) +{ + uvdbg("CSW:\n"); + uvdbg(" signature: %08x\n", usbhost_getle32(csw->signature)); + uvdbg(" tag: %08x\n", usbhost_getle32(csw->tag)); + uvdbg(" residue: %08x\n", usbhost_getle32(csw->residue)); + uvdbg(" status: %02x\n", csw->status); +} +#endif + +/**************************************************************************** + * Name: CBW helpers + * + * Description: + * The following functions are helper functions used to format CBWs. + * + * Input Parameters: + * cbw - A reference to allocated and initialized CBW to be built. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline void usbhost_requestsensecbw(FAR struct usbmsc_cbw_s *cbw) +{ + FAR struct scsicmd_requestsense_s *reqsense; + + /* Format the CBW */ + + usbhost_putle32(cbw->datlen, SCSIRESP_FIXEDSENSEDATA_SIZEOF); + cbw->flags = USBMSC_CBWFLAG_IN; + cbw->cdblen = SCSICMD_REQUESTSENSE_SIZEOF; + + /* Format the CDB */ + + reqsense = (FAR struct scsicmd_requestsense_s *)cbw->cdb; + reqsense->opcode = SCSI_CMD_REQUESTSENSE; + reqsense->alloclen = SCSIRESP_FIXEDSENSEDATA_SIZEOF; + + usbhost_dumpcbw(cbw); +} + +static inline void usbhost_testunitreadycbw(FAR struct usbmsc_cbw_s *cbw) +{ + /* Format the CBW */ + + cbw->cdblen = SCSICMD_TESTUNITREADY_SIZEOF; + + /* Format the CDB */ + + cbw->cdb[0] = SCSI_CMD_TESTUNITREADY; + + usbhost_dumpcbw(cbw); +} + +static inline void usbhost_readcapacitycbw(FAR struct usbmsc_cbw_s *cbw) +{ + FAR struct scsicmd_readcapacity10_s *rcap10; + + /* Format the CBW */ + + usbhost_putle32(cbw->datlen, SCSIRESP_READCAPACITY10_SIZEOF); + cbw->flags = USBMSC_CBWFLAG_IN; + cbw->cdblen = SCSICMD_READCAPACITY10_SIZEOF; + + /* Format the CDB */ + + rcap10 = (FAR struct scsicmd_readcapacity10_s *)cbw->cdb; + rcap10->opcode = SCSI_CMD_READCAPACITY10; + + usbhost_dumpcbw(cbw); +} + +static inline void usbhost_inquirycbw (FAR struct usbmsc_cbw_s *cbw) +{ + FAR struct scscicmd_inquiry_s *inq; + + /* Format the CBW */ + + usbhost_putle32(cbw->datlen, SCSIRESP_INQUIRY_SIZEOF); + cbw->flags = USBMSC_CBWFLAG_IN; + cbw->cdblen = SCSICMD_INQUIRY_SIZEOF; + + /* Format the CDB */ + + inq = (FAR struct scscicmd_inquiry_s *)cbw->cdb; + inq->opcode = SCSI_CMD_INQUIRY; + usbhost_putbe16(inq->alloclen, SCSIRESP_INQUIRY_SIZEOF); + + usbhost_dumpcbw(cbw); +} + +static inline void +usbhost_readcbw (size_t startsector, uint16_t blocksize, + unsigned int nsectors, FAR struct usbmsc_cbw_s *cbw) +{ + FAR struct scsicmd_read10_s *rd10; + + /* Format the CBW */ + + usbhost_putle32(cbw->datlen, blocksize * nsectors); + cbw->flags = USBMSC_CBWFLAG_IN; + cbw->cdblen = SCSICMD_READ10_SIZEOF; + + /* Format the CDB */ + + rd10 = (FAR struct scsicmd_read10_s *)cbw->cdb; + rd10->opcode = SCSI_CMD_READ10; + usbhost_putbe32(rd10->lba, startsector); + usbhost_putbe16(rd10->xfrlen, nsectors); + + usbhost_dumpcbw(cbw); +} + +static inline void +usbhost_writecbw(size_t startsector, uint16_t blocksize, + unsigned int nsectors, FAR struct usbmsc_cbw_s *cbw) +{ + FAR struct scsicmd_write10_s *wr10; + + /* Format the CBW */ + + usbhost_putle32(cbw->datlen, blocksize * nsectors); + cbw->cdblen = SCSICMD_WRITE10_SIZEOF; + + /* Format the CDB */ + + wr10 = (FAR struct scsicmd_write10_s *)cbw->cdb; + wr10->opcode = SCSI_CMD_WRITE10; + usbhost_putbe32(wr10->lba, startsector); + usbhost_putbe16(wr10->xfrlen, nsectors); + + usbhost_dumpcbw(cbw); +} + +/**************************************************************************** + * Name: Command helpers + * + * Description: + * The following functions are helper functions used to send commands. + * + * Input Parameters: + * priv - A reference to the class instance. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline int usbhost_maxlunreq(FAR struct usbhost_state_s *priv) +{ + FAR struct usb_ctrlreq_s *req = (FAR struct usb_ctrlreq_s *)priv->tbuffer; + DEBUGASSERT(priv && priv->tbuffer); + int ret; + + /* Request maximum logical unit number. NOTE: On an IN transaction, The + * req and buffer pointers passed to DRVR_CTRLIN may refer to the same + * allocated memory. + */ + + uvdbg("Request maximum logical unit number\n"); + memset(req, 0, sizeof(struct usb_ctrlreq_s)); + req->type = USB_DIR_IN|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE; + req->req = USBMSC_REQ_GETMAXLUN; + usbhost_putle16(req->len, 1); + + ret = DRVR_CTRLIN(priv->drvr, req, priv->tbuffer); + if (ret != OK) + { + /* Devices that do not support multiple LUNs may stall this command. + * On a failure, a single LUN is assumed. + */ + + *(priv->tbuffer) = 0; + } + return OK; +} + +static inline int usbhost_testunitready(FAR struct usbhost_state_s *priv) +{ + FAR struct usbmsc_cbw_s *cbw; + int result; + + /* Initialize a CBW (re-using the allocated transfer buffer) */ + + cbw = usbhost_cbwalloc(priv); + if (!cbw) + { + udbg("ERROR: Failed to create CBW\n"); + return -ENOMEM; + } + + /* Construct and send the CBW */ + + usbhost_testunitreadycbw(cbw); + result = DRVR_TRANSFER(priv->drvr, priv->bulkout, + (uint8_t*)cbw, USBMSC_CBW_SIZEOF); + if (result == OK) + { + /* Receive the CSW */ + + result = DRVR_TRANSFER(priv->drvr, priv->bulkin, + priv->tbuffer, USBMSC_CSW_SIZEOF); + if (result == OK) + { + usbhost_dumpcsw((FAR struct usbmsc_csw_s *)priv->tbuffer); + } + } + return result; +} + +static inline int usbhost_requestsense(FAR struct usbhost_state_s *priv) +{ + FAR struct usbmsc_cbw_s *cbw; + int result; + + /* Initialize a CBW (re-using the allocated transfer buffer) */ + + cbw = usbhost_cbwalloc(priv); + if (!cbw) + { + udbg("ERROR: Failed to create CBW\n"); + return -ENOMEM; + } + + /* Construct and send the CBW */ + + usbhost_requestsensecbw(cbw); + result = DRVR_TRANSFER(priv->drvr, priv->bulkout, + (uint8_t*)cbw, USBMSC_CBW_SIZEOF); + if (result == OK) + { + /* Receive the sense data response */ + + result = DRVR_TRANSFER(priv->drvr, priv->bulkin, + priv->tbuffer, SCSIRESP_FIXEDSENSEDATA_SIZEOF); + if (result == OK) + { + /* Receive the CSW */ + + result = DRVR_TRANSFER(priv->drvr, priv->bulkin, + priv->tbuffer, USBMSC_CSW_SIZEOF); + if (result == OK) + { + usbhost_dumpcsw((FAR struct usbmsc_csw_s *)priv->tbuffer); + } + } + } + + return result; +} + +static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv) +{ + FAR struct usbmsc_cbw_s *cbw; + FAR struct scsiresp_readcapacity10_s *resp; + int result; + + /* Initialize a CBW (re-using the allocated transfer buffer) */ + + cbw = usbhost_cbwalloc(priv); + if (!cbw) + { + udbg("ERROR: Failed to create CBW\n"); + return -ENOMEM; + } + + /* Construct and send the CBW */ + + usbhost_readcapacitycbw(cbw); + result = DRVR_TRANSFER(priv->drvr, priv->bulkout, + (uint8_t*)cbw, USBMSC_CBW_SIZEOF); + if (result == OK) + { + /* Receive the read capacity CBW IN response */ + + result = DRVR_TRANSFER(priv->drvr, priv->bulkin, + priv->tbuffer, SCSIRESP_READCAPACITY10_SIZEOF); + if (result == OK) + { + /* Save the capacity information */ + + resp = (FAR struct scsiresp_readcapacity10_s *)priv->tbuffer; + priv->nblocks = usbhost_getbe32(resp->lba) + 1; + priv->blocksize = usbhost_getbe32(resp->blklen); + + /* Receive the CSW */ + + result = DRVR_TRANSFER(priv->drvr, priv->bulkin, + priv->tbuffer, USBMSC_CSW_SIZEOF); + if (result == OK) + { + usbhost_dumpcsw((FAR struct usbmsc_csw_s *)priv->tbuffer); + } + } + } + + return result; +} + +static inline int usbhost_inquiry(FAR struct usbhost_state_s *priv) +{ + FAR struct usbmsc_cbw_s *cbw; + FAR struct scsiresp_inquiry_s *resp; + int result; + + /* Initialize a CBW (re-using the allocated transfer buffer) */ + + cbw = usbhost_cbwalloc(priv); + if (!cbw) + { + udbg("ERROR: Failed to create CBW\n"); + return -ENOMEM; + } + + /* Construct and send the CBW */ + + usbhost_inquirycbw(cbw); + result = DRVR_TRANSFER(priv->drvr, priv->bulkout, + (uint8_t*)cbw, USBMSC_CBW_SIZEOF); + if (result == OK) + { + /* Receive the CBW IN response */ + + result = DRVR_TRANSFER(priv->drvr, priv->bulkin, + priv->tbuffer, SCSIRESP_INQUIRY_SIZEOF); + if (result == OK) + { + /* TODO: If USB debug is enabled, dump the response data here */ + + resp = (FAR struct scsiresp_inquiry_s *)priv->tbuffer; + + /* Receive the CSW */ + + result = DRVR_TRANSFER(priv->drvr, priv->bulkin, + priv->tbuffer, USBMSC_CSW_SIZEOF); + if (result == OK) + { + usbhost_dumpcsw((FAR struct usbmsc_csw_s *)priv->tbuffer); + } + } + } + + return result; +} + +/**************************************************************************** + * Name: usbhost_destroy + * + * Description: + * The USB mass storage device has been disconnected and the refernce count + * on the USB host class instance has gone to 1.. Time to destroy the USB + * host class instance. + * + * Input Parameters: + * arg - A reference to the class instance to be destroyed. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void usbhost_destroy(FAR void *arg) +{ + FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)arg; + char devname[DEV_NAMELEN]; + + DEBUGASSERT(priv != NULL); + uvdbg("crefs: %d\n", priv->crefs); + + /* Unregister the block driver */ + + usbhost_mkdevname(priv, devname); + (void)unregister_blockdriver(devname); + + /* Release the device name used by this connection */ + + usbhost_freedevno(priv); + + /* Free the bulk endpoints */ + + if (priv->bulkout) + { + DRVR_EPFREE(priv->drvr, priv->bulkout); + } + + if (priv->bulkin) + { + DRVR_EPFREE(priv->drvr, priv->bulkin); + } + + /* Free any transfer buffers */ + + usbhost_tfree(priv); + + /* Destroy the semaphores */ + + sem_destroy(&priv->exclsem); + + /* Disconnect the USB host device */ + + DRVR_DISCONNECT(priv->drvr); + + /* And free the class instance. Hmmm.. this may execute on the worker + * thread and the work structure is part of what is getting freed. That + * should be okay because once the work contained is removed from the + * queue, it should not longer be accessed by the worker thread. + */ + + usbhost_freeclass(priv); +} + +/**************************************************************************** + * Name: usbhost_cfgdesc + * + * Description: + * This function implements the connect() method of struct + * usbhost_class_s. This method is a callback into the class + * implementation. It is used to provide the device's configuration + * descriptor to the class so that the class may initialize properly + * + * Input Parameters: + * priv - The USB host class instance. + * configdesc - A pointer to a uint8_t buffer container the configuration descripor. + * desclen - The length in bytes of the configuration descriptor. + * funcaddr - The USB address of the function containing the endpoint that EP0 + * controls + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ****************************************************************************/ + +static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv, + FAR const uint8_t *configdesc, int desclen, + uint8_t funcaddr) +{ + FAR struct usb_cfgdesc_s *cfgdesc; + FAR struct usb_desc_s *desc; + FAR struct usbhost_epdesc_s bindesc; + FAR struct usbhost_epdesc_s boutdesc; + int remaining; + uint8_t found = 0; + int ret; + + DEBUGASSERT(priv != NULL && + configdesc != NULL && + desclen >= sizeof(struct usb_cfgdesc_s)); + + /* Verify that we were passed a configuration descriptor */ + + cfgdesc = (FAR struct usb_cfgdesc_s *)configdesc; + if (cfgdesc->type != USB_DESC_TYPE_CONFIG) + { + return -EINVAL; + } + + /* Get the total length of the configuration descriptor (little endian). + * It might be a good check to get the number of interfaces here too. + */ + + remaining = (int)usbhost_getle16(cfgdesc->totallen); + + /* Skip to the next entry descriptor */ + + configdesc += cfgdesc->len; + remaining -= cfgdesc->len; + + /* Loop where there are more dscriptors to examine */ + + while (remaining >= sizeof(struct usb_desc_s)) + { + /* What is the next descriptor? */ + + desc = (FAR struct usb_desc_s *)configdesc; + switch (desc->type) + { + /* Interface descriptor. We really should get the number of endpoints + * from this descriptor too. + */ + + case USB_DESC_TYPE_INTERFACE: + { + FAR struct usb_ifdesc_s *ifdesc = (FAR struct usb_ifdesc_s *)configdesc; + + uvdbg("Interface descriptor\n"); + DEBUGASSERT(remaining >= USB_SIZEOF_IFDESC); + + /* Save the interface number and mark ONLY the interface found */ + + priv->ifno = ifdesc->ifno; + found = USBHOST_IFFOUND; + } + break; + + /* Endpoint descriptor. We expect two bulk endpoints, an IN and an + * OUT. + */ + + case USB_DESC_TYPE_ENDPOINT: + { + FAR struct usb_epdesc_s *epdesc = (FAR struct usb_epdesc_s *)configdesc; + + uvdbg("Endpoint descriptor\n"); + DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC); + + /* Check for a bulk endpoint. We only support the bulk-only + * protocol so I suppose anything else should really be an error. + */ + + if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_BULK) + { + /* Yes.. it is a bulk endpoint. IN or OUT? */ + + if (USB_ISEPOUT(epdesc->addr)) + { + /* It is an OUT bulk endpoint. There should be only one + * bulk OUT endpoint. + */ + + if ((found & USBHOST_BOUTFOUND) != 0) + { + /* Oops.. more than one endpoint. We don't know + * what to do with this. + */ + + return -EINVAL; + } + found |= USBHOST_BOUTFOUND; + + /* Save the bulk OUT endpoint information */ + + boutdesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK; + boutdesc.in = false; + boutdesc.funcaddr = funcaddr; + boutdesc.xfrtype = USB_EP_ATTR_XFER_BULK; + boutdesc.interval = epdesc->interval; + boutdesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize); + uvdbg("Bulk OUT EP addr:%d mxpacketsize:%d\n", + boutdesc.addr, boutdesc.mxpacketsize); + } + else + { + /* It is an IN bulk endpoint. There should be only one + * bulk IN endpoint. + */ + + if ((found & USBHOST_BINFOUND) != 0) + { + /* Oops.. more than one endpoint. We don't know + * what to do with this. + */ + + return -EINVAL; + } + found |= USBHOST_BINFOUND; + + /* Save the bulk IN endpoint information */ + + bindesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK; + bindesc.in = 1; + bindesc.funcaddr = funcaddr; + bindesc.xfrtype = USB_EP_ATTR_XFER_BULK; + bindesc.interval = epdesc->interval; + bindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize); + uvdbg("Bulk IN EP addr:%d mxpacketsize:%d\n", + bindesc.addr, bindesc.mxpacketsize); + } + } + } + break; + + /* Other descriptors are just ignored for now */ + + default: + break; + } + + /* If we found everything we need with this interface, then break out + * of the loop early. + */ + + if (found == USBHOST_ALLFOUND) + { + break; + } + + /* Increment the address of the next descriptor */ + + configdesc += desc->len; + remaining -= desc->len; + } + + /* Sanity checking... did we find all of things that we need? Hmmm.. I wonder.. + * can we work read-only or write-only if only one bulk endpoint found? + */ + + if (found != USBHOST_ALLFOUND) + { + ulldbg("ERROR: Found IF:%s BIN:%s BOUT:%s\n", + (found & USBHOST_IFFOUND) != 0 ? "YES" : "NO", + (found & USBHOST_BINFOUND) != 0 ? "YES" : "NO", + (found & USBHOST_BOUTFOUND) != 0 ? "YES" : "NO"); + return -EINVAL; + } + + /* We are good... Allocate the endpoints */ + + ret = DRVR_EPALLOC(priv->drvr, &boutdesc, &priv->bulkout); + if (ret != OK) + { + udbg("ERROR: Failed to allocate Bulk OUT endpoint\n"); + return ret; + } + + ret = DRVR_EPALLOC(priv->drvr, &bindesc, &priv->bulkin); + if (ret != OK) + { + udbg("ERROR: Failed to allocate Bulk IN endpoint\n"); + (void)DRVR_EPFREE(priv->drvr, priv->bulkout); + return ret; + } + + ullvdbg("Endpoints allocated\n"); + return OK; +} + +/**************************************************************************** + * Name: usbhost_initvolume + * + * Description: + * The USB mass storage device has been successfully connected. This + * completes the initialization operations. It is first called after the + * configuration descriptor has been received. + * + * This function is called from the connect() method. This function always + * executes on the thread of the caller of connect(). + * + * Input Parameters: + * priv - A reference to the class instance. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline int usbhost_initvolume(FAR struct usbhost_state_s *priv) +{ + FAR struct usbmsc_csw_s *csw; + unsigned int retries; + int ret = OK; + + DEBUGASSERT(priv != NULL); + + /* Set aside a transfer buffer for exclusive use by the mass storage driver */ + + ret = usbhost_talloc(priv); + if (ret != OK) + { + udbg("ERROR: Failed to allocate transfer buffer\n"); + return ret; + } + + /* Increment the reference count. This will prevent usbhost_destroy() from + * being called asynchronously if the device is removed. + */ + + priv->crefs++; + DEBUGASSERT(priv->crefs == 2); + + /* Request the maximum logical unit number */ + + uvdbg("Get max LUN\n"); + ret = usbhost_maxlunreq(priv); + + /* Wait for the unit to be ready */ + + for (retries = 0; retries < USBHOST_MAX_RETRIES && ret == OK; retries++) + { + uvdbg("Test unit ready, retries=%d\n", retries); + + /* Send TESTUNITREADY to see the unit is ready */ + + ret = usbhost_testunitready(priv); + if (ret == OK) + { + /* Is the unit is ready */ + + csw = (FAR struct usbmsc_csw_s *)priv->tbuffer; + if (csw->status == 0) + { + /* Yes... break out of the loop */ + + break; + } + + /* No.. Request mode sense information. The REQUEST SENSE command + * is sent only "to clear interlocked unit attention conditions." + * The returned status is ignored here. + */ + + uvdbg("Request sense\n"); + ret = usbhost_requestsense(priv); + } + } + + /* Did the unit become ready? Did an error occur? Or did we time out? */ + + if (retries >= USBHOST_MAX_RETRIES) + { + udbg("ERROR: Timeout!\n"); + ret = -ETIMEDOUT; + } + + if (ret == OK) + { + /* Get the capacity of the volume */ + + uvdbg("Read capacity\n"); + ret = usbhost_readcapacity(priv); + if (ret == OK) + { + /* Check the CSW for errors */ + + csw = (FAR struct usbmsc_csw_s *)priv->tbuffer; + if (csw->status != 0) + { + udbg("ERROR: CSW status error: %d\n", csw->status); + ret = -ENODEV; + } + } + } + + /* Get information about the volume */ + + if (ret == OK) + { + /* Inquiry */ + + uvdbg("Inquiry\n"); + ret = usbhost_inquiry(priv); + if (ret == OK) + { + /* Check the CSW for errors */ + + csw = (FAR struct usbmsc_csw_s *)priv->tbuffer; + if (csw->status != 0) + { + udbg("ERROR: CSW status error: %d\n", csw->status); + ret = -ENODEV; + } + } + } + + /* Register the block driver */ + + if (ret == OK) + { + char devname[DEV_NAMELEN]; + + uvdbg("Register block driver\n"); + usbhost_mkdevname(priv, devname); + ret = register_blockdriver(devname, &g_bops, 0, priv); + } + + /* Check if we successfully initialized. We now have to be concerned + * about asynchronous modification of crefs because the block + * driver has been registerd. + */ + + if (ret == OK) + { + usbhost_takesem(&priv->exclsem); + DEBUGASSERT(priv->crefs >= 2); + + /* Decrement the reference count */ + + priv->crefs--; + + /* Handle a corner case where (1) open() has been called so the + * reference count was > 2, but the device has been disconnected. + * In this case, the class instance needs to persist until close() + * is called. + */ + + if (priv->crefs <= 1 && priv->disconnected) + { + /* The will cause the enumeration logic to disconnect + * the class driver. + */ + + ret = -ENODEV; + } + + /* Release the semaphore... there is a race condition here. + * Decrementing the reference count and releasing the semaphore + * allows usbhost_destroy() to execute (on the worker thread); + * the class driver instance could get destoryed before we are + * ready to handle it! + */ + + usbhost_givesem(&priv->exclsem); + } + + return ret; +} + +/**************************************************************************** + * Name: usbhost_getle16 + * + * Description: + * Get a (possibly unaligned) 16-bit little endian value. + * + * Input Parameters: + * val - A pointer to the first byte of the little endian value. + * + * Returned Values: + * A uint16_t representing the whole 16-bit integer value + * + ****************************************************************************/ + +static inline uint16_t usbhost_getle16(const uint8_t *val) +{ + return (uint16_t)val[1] << 8 | (uint16_t)val[0]; +} + +/**************************************************************************** + * Name: usbhost_getbe16 + * + * Description: + * Get a (possibly unaligned) 16-bit big endian value. + * + * Input Parameters: + * val - A pointer to the first byte of the big endian value. + * + * Returned Values: + * A uint16_t representing the whole 16-bit integer value + * + ****************************************************************************/ + +static inline uint16_t usbhost_getbe16(const uint8_t *val) +{ + return (uint16_t)val[0] << 8 | (uint16_t)val[1]; +} + +/**************************************************************************** + * Name: usbhost_putle16 + * + * Description: + * Put a (possibly unaligned) 16-bit little endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the little endian value. + * val - The 16-bit value to be saved. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void usbhost_putle16(uint8_t *dest, uint16_t val) +{ + dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */ + dest[1] = val >> 8; +} + +/**************************************************************************** + * Name: usbhost_putbe16 + * + * Description: + * Put a (possibly unaligned) 16-bit big endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the big endian value. + * val - The 16-bit value to be saved. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void usbhost_putbe16(uint8_t *dest, uint16_t val) +{ + dest[0] = val >> 8; /* Big endian means MS byte first in byte stream */ + dest[1] = val & 0xff; +} + +/**************************************************************************** + * Name: usbhost_getle32 + * + * Description: + * Get a (possibly unaligned) 32-bit little endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the big endian value. + * val - The 32-bit value to be saved. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline uint32_t usbhost_getle32(const uint8_t *val) +{ + /* Little endian means LS halfword first in byte stream */ + + return (uint32_t)usbhost_getle16(&val[2]) << 16 | (uint32_t)usbhost_getle16(val); +} + +/**************************************************************************** + * Name: usbhost_getbe32 + * + * Description: + * Get a (possibly unaligned) 32-bit big endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the big endian value. + * val - The 32-bit value to be saved. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline uint32_t usbhost_getbe32(const uint8_t *val) +{ + /* Big endian means MS halfword first in byte stream */ + + return (uint32_t)usbhost_getbe16(val) << 16 | (uint32_t)usbhost_getbe16(&val[2]); +} + +/**************************************************************************** + * Name: usbhost_putle32 + * + * Description: + * Put a (possibly unaligned) 32-bit little endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the little endian value. + * val - The 32-bit value to be saved. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void usbhost_putle32(uint8_t *dest, uint32_t val) +{ + /* Little endian means LS halfword first in byte stream */ + + usbhost_putle16(dest, (uint16_t)(val & 0xffff)); + usbhost_putle16(dest+2, (uint16_t)(val >> 16)); +} + +/**************************************************************************** + * Name: usbhost_putbe32 + * + * Description: + * Put a (possibly unaligned) 32-bit big endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the big endian value. + * val - The 32-bit value to be saved. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void usbhost_putbe32(uint8_t *dest, uint32_t val) +{ + /* Big endian means MS halfword first in byte stream */ + + usbhost_putbe16(dest, (uint16_t)(val >> 16)); + usbhost_putbe16(dest+2, (uint16_t)(val & 0xffff)); +} + +/**************************************************************************** + * Name: usbhost_talloc + * + * Description: + * Allocate transfer buffer memory. + * + * Input Parameters: + * priv - A reference to the class instance. + * + * Returned Values: + * On sucess, zero (OK) is returned. On failure, an negated errno value + * is returned to indicate the nature of the failure. + * + ****************************************************************************/ + +static inline int usbhost_talloc(FAR struct usbhost_state_s *priv) +{ + DEBUGASSERT(priv && priv->tbuffer == NULL); + return DRVR_ALLOC(priv->drvr, &priv->tbuffer, &priv->tbuflen); +} + +/**************************************************************************** + * Name: usbhost_tfree + * + * Description: + * Free transfer buffer memory. + * + * Input Parameters: + * priv - A reference to the class instance. + * + * Returned Values: + * On sucess, zero (OK) is returned. On failure, an negated errno value + * is returned to indicate the nature of the failure. + * + ****************************************************************************/ + +static inline int usbhost_tfree(FAR struct usbhost_state_s *priv) +{ + int result = OK; + DEBUGASSERT(priv); + + if (priv->tbuffer) + { + DEBUGASSERT(priv->drvr); + result = DRVR_FREE(priv->drvr, priv->tbuffer); + priv->tbuffer = NULL; + priv->tbuflen = 0; + } + return result; +} + +/**************************************************************************** + * Name: usbhost_cbwalloc + * + * Description: + * Initialize a CBW (re-using the allocated transfer buffer). Upon + * successful return, the CBW is cleared and has the CBW signature in place. + * + * Input Parameters: + * priv - A reference to the class instance. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static FAR struct usbmsc_cbw_s *usbhost_cbwalloc(FAR struct usbhost_state_s *priv) +{ + FAR struct usbmsc_cbw_s *cbw = NULL; + + DEBUGASSERT(priv->tbuffer && priv->tbuflen >= sizeof(struct usbmsc_cbw_s)) + + /* Intialize the CBW sructure */ + + cbw = (FAR struct usbmsc_cbw_s *)priv->tbuffer; + memset(cbw, 0, sizeof(struct usbmsc_cbw_s)); + usbhost_putle32(cbw->signature, USBMSC_CBW_SIGNATURE); + return cbw; +} + +/**************************************************************************** + * struct usbhost_registry_s methods + ****************************************************************************/ + +/**************************************************************************** + * Name: usbhost_create + * + * Description: + * This function implements the create() method of struct usbhost_registry_s. + * The create() method is a callback into the class implementation. It is + * used to (1) create a new instance of the USB host class state and to (2) + * bind a USB host driver "session" to the class instance. Use of this + * create() method will support environments where there may be multiple + * USB ports and multiple USB devices simultaneously connected. + * + * Input Parameters: + * drvr - An instance of struct usbhost_driver_s that the class + * implementation will "bind" to its state structure and will + * subsequently use to communicate with the USB host driver. + * id - In the case where the device supports multiple base classes, + * subclasses, or protocols, this specifies which to configure for. + * + * Returned Values: + * On success, this function will return a non-NULL instance of struct + * usbhost_class_s that can be used by the USB host driver to communicate + * with the USB host class. NULL is returned on failure; this function + * will fail only if the drvr input parameter is NULL or if there are + * insufficient resources to create another USB host class instance. + * + ****************************************************************************/ + +static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *drvr, + FAR const struct usbhost_id_s *id) +{ + FAR struct usbhost_state_s *priv; + + /* Allocate a USB host mass storage class instance */ + + priv = usbhost_allocclass(); + if (priv) + { + /* Initialize the allocated storage class instance */ + + memset(priv, 0, sizeof(struct usbhost_state_s)); + + /* Assign a device number to this class instance */ + + if (usbhost_allocdevno(priv) == OK) + { + /* Initialize class method function pointers */ + + priv->class.connect = usbhost_connect; + priv->class.disconnected = usbhost_disconnected; + + /* The initial reference count is 1... One reference is held by the driver */ + + priv->crefs = 1; + + /* Initialize semphores (this works okay in the interrupt context) */ + + sem_init(&priv->exclsem, 0, 1); + + /* Bind the driver to the storage class instance */ + + priv->drvr = drvr; + + /* NOTE: We do not yet know the geometry of the USB mass storage device */ + + /* Return the instance of the USB mass storage class */ + + return &priv->class; + } + } + + /* An error occurred. Free the allocation and return NULL on all failures */ + + if (priv) + { + usbhost_freeclass(priv); + } + return NULL; +} + +/**************************************************************************** + * struct usbhost_class_s methods + ****************************************************************************/ +/**************************************************************************** + * Name: usbhost_connect + * + * Description: + * This function implements the connect() method of struct + * usbhost_class_s. This method is a callback into the class + * implementation. It is used to provide the device's configuration + * descriptor to the class so that the class may initialize properly + * + * Input Parameters: + * class - The USB host class entry previously obtained from a call to create(). + * configdesc - A pointer to a uint8_t buffer container the configuration descripor. + * desclen - The length in bytes of the configuration descriptor. + * funcaddr - The USB address of the function containing the endpoint that EP0 + * controls + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * NOTE that the class instance remains valid upon return with a failure. It is + * the responsibility of the higher level enumeration logic to call + * CLASS_DISCONNECTED to free up the class driver resources. + * + * Assumptions: + * - This function will *not* be called from an interrupt handler. + * - If this function returns an error, the USB host controller driver + * must call to DISCONNECTED method to recover from the error + * + ****************************************************************************/ + +static int usbhost_connect(FAR struct usbhost_class_s *class, + FAR const uint8_t *configdesc, int desclen, + uint8_t funcaddr) +{ + FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)class; + int ret; + + DEBUGASSERT(priv != NULL && + configdesc != NULL && + desclen >= sizeof(struct usb_cfgdesc_s)); + + /* Parse the configuration descriptor to get the bulk I/O endpoints */ + + ret = usbhost_cfgdesc(priv, configdesc, desclen, funcaddr); + if (ret != OK) + { + udbg("usbhost_cfgdesc() failed: %d\n", ret); + } + else + { + /* Now configure the LUNs and register the block driver(s) */ + + ret = usbhost_initvolume(priv); + if (ret != OK) + { + udbg("usbhost_initvolume() failed: %d\n", ret); + } + } + + return ret; +} + +/**************************************************************************** + * Name: usbhost_disconnected + * + * Description: + * This function implements the disconnected() method of struct + * usbhost_class_s. This method is a callback into the class + * implementation. It is used to inform the class that the USB device has + * been disconnected. + * + * Input Parameters: + * class - The USB host class entry previously obtained from a call to + * create(). + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value + * is returned indicating the nature of the failure + * + * Assumptions: + * This function may be called from an interrupt handler. + * + ****************************************************************************/ + +static int usbhost_disconnected(struct usbhost_class_s *class) +{ + FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)class; + irqstate_t flags; + + DEBUGASSERT(priv != NULL); + + /* Set an indication to any users of the mass storage device that the device + * is no longer available. + */ + + flags = irqsave(); + priv->disconnected = true; + + /* Now check the number of references on the class instance. If it is one, + * then we can free the class instance now. Otherwise, we will have to + * wait until the holders of the references free them by closing the + * block driver. + */ + + ullvdbg("crefs: %d\n", priv->crefs); + if (priv->crefs == 1) + { + /* Destroy the class instance. If we are executing from an interrupt + * handler, then defer the destruction to the worker thread. + * Otherwise, destroy the instance now. + */ + + if (up_interrupt_context()) + { + /* Destroy the instance on the worker thread. */ + + uvdbg("Queuing destruction: worker %p->%p\n", priv->work.worker, usbhost_destroy); + DEBUGASSERT(priv->work.worker == NULL); + (void)work_queue(&priv->work, usbhost_destroy, priv, 0); + } + else + { + /* Do the work now */ + + usbhost_destroy(priv); + } + } + + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * struct block_operations methods + ****************************************************************************/ +/**************************************************************************** + * Name: usbhost_open + * + * Description: Open the block device + * + ****************************************************************************/ + +static int usbhost_open(FAR struct inode *inode) +{ + FAR struct usbhost_state_s *priv; + irqstate_t flags; + int ret; + + uvdbg("Entry\n"); + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct usbhost_state_s *)inode->i_private; + + /* Make sure that we have exclusive access to the private data structure */ + + DEBUGASSERT(priv->crefs > 0 && priv->crefs < USBHOST_MAX_CREFS); + usbhost_takesem(&priv->exclsem); + + /* Check if the mass storage device is still connected. We need to disable + * interrupts momentarily to assure that there are no asynchronous disconnect + * events. + */ + + flags = irqsave(); + if (priv->disconnected) + { + /* No... the block driver is no longer bound to the class. That means that + * the USB storage device is no longer connected. Refuse any further + * attempts to open the driver. + */ + + ret = -ENODEV; + } + else + { + /* Otherwise, just increment the reference count on the driver */ + + priv->crefs++; + ret = OK; + } + irqrestore(flags); + + usbhost_givesem(&priv->exclsem); + return ret; +} + +/**************************************************************************** + * Name: usbhost_close + * + * Description: close the block device + * + ****************************************************************************/ + +static int usbhost_close(FAR struct inode *inode) +{ + FAR struct usbhost_state_s *priv; + irqstate_t flags; + + uvdbg("Entry\n"); + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct usbhost_state_s *)inode->i_private; + + /* Decrement the reference count on the block driver */ + + DEBUGASSERT(priv->crefs > 1); + usbhost_takesem(&priv->exclsem); + priv->crefs--; + + /* Release the semaphore. The following operations when crefs == 1 are + * safe because we know that there is no outstanding open references to + * the block driver. + */ + + usbhost_givesem(&priv->exclsem); + + /* We need to disable interrupts momentarily to assure that there are + * no asynchronous disconnect events. + */ + + flags = irqsave(); + + /* Check if the USB mass storage device is still connected. If the + * storage device is not connected and the reference count just + * decremented to one, then unregister the block driver and free + * the class instance. + */ + + if (priv->crefs <= 1 && priv->disconnected) + { + /* Destroy the class instance */ + + DEBUGASSERT(priv->crefs == 1); + usbhost_destroy(priv); + } + + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Name: usbhost_read + * + * Description: + * Read the specified numer of sectors from the read-ahead buffer or from + * the physical device. + * + ****************************************************************************/ + +static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer, + size_t startsector, unsigned int nsectors) +{ + FAR struct usbhost_state_s *priv; + ssize_t ret = 0; + int result; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct usbhost_state_s *)inode->i_private; + uvdbg("startsector: %d nsectors: %d sectorsize: %d\n", + startsector, nsectors, priv->blocksize); + + /* Check if the mass storage device is still connected */ + + if (priv->disconnected) + { + /* No... the block driver is no longer bound to the class. That means that + * the USB storage device is no longer connected. Refuse any attempt to read + * from the device. + */ + + ret = -ENODEV; + } + else if (nsectors > 0) + { + FAR struct usbmsc_cbw_s *cbw; + + usbhost_takesem(&priv->exclsem); + + /* Assume allocation failure */ + + ret = -ENOMEM; + + /* Initialize a CBW (re-using the allocated transfer buffer) */ + + cbw = usbhost_cbwalloc(priv); + if (cbw) + { + /* Assume some device failure */ + + ret = -ENODEV; + + /* Construct and send the CBW */ + + usbhost_readcbw(startsector, priv->blocksize, nsectors, cbw); + result = DRVR_TRANSFER(priv->drvr, priv->bulkout, + (uint8_t*)cbw, USBMSC_CBW_SIZEOF); + if (result == OK) + { + /* Receive the user data */ + + result = DRVR_TRANSFER(priv->drvr, priv->bulkin, + buffer, priv->blocksize * nsectors); + if (result == OK) + { + /* Receive the CSW */ + + result = DRVR_TRANSFER(priv->drvr, priv->bulkin, + priv->tbuffer, USBMSC_CSW_SIZEOF); + if (result == OK) + { + FAR struct usbmsc_csw_s *csw; + + /* Check the CSW status */ + + csw = (FAR struct usbmsc_csw_s *)priv->tbuffer; + if (csw->status == 0) + { + ret = nsectors; + } + } + } + } + } + + usbhost_givesem(&priv->exclsem); + } + + /* On success, return the number of blocks read */ + + return ret; +} + +/**************************************************************************** + * Name: usbhost_write + * + * Description: + * Write the specified number of sectors to the write buffer or to the + * physical device. + * + ****************************************************************************/ + +#ifdef CONFIG_FS_WRITABLE +static ssize_t usbhost_write(FAR struct inode *inode, const unsigned char *buffer, + size_t startsector, unsigned int nsectors) +{ + FAR struct usbhost_state_s *priv; + ssize_t ret; + int result; + + uvdbg("sector: %d nsectors: %d sectorsize: %d\n"); + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct usbhost_state_s *)inode->i_private; + + /* Check if the mass storage device is still connected */ + + if (priv->disconnected) + { + /* No... the block driver is no longer bound to the class. That means that + * the USB storage device is no longer connected. Refuse any attempt to + * write to the device. + */ + + ret = -ENODEV; + } + else + { + FAR struct usbmsc_cbw_s *cbw; + + usbhost_takesem(&priv->exclsem); + + /* Assume allocation failure */ + + ret = -ENOMEM; + + /* Initialize a CBW (re-using the allocated transfer buffer) */ + + cbw = usbhost_cbwalloc(priv); + if (cbw) + { + /* Assume some device failure */ + + ret = -ENODEV; + + /* Construct and send the CBW */ + + usbhost_writecbw(startsector, priv->blocksize, nsectors, cbw); + result = DRVR_TRANSFER(priv->drvr, priv->bulkout, + (uint8_t*)cbw, USBMSC_CBW_SIZEOF); + if (result == OK) + { + /* Send the user data */ + + result = DRVR_TRANSFER(priv->drvr, priv->bulkout, + (uint8_t*)buffer, priv->blocksize * nsectors); + if (result == OK) + { + /* Receive the CSW */ + + result = DRVR_TRANSFER(priv->drvr, priv->bulkin, + priv->tbuffer, USBMSC_CSW_SIZEOF); + if (result == OK) + { + FAR struct usbmsc_csw_s *csw; + + /* Check the CSW status */ + + csw = (FAR struct usbmsc_csw_s *)priv->tbuffer; + if (csw->status == 0) + { + ret = nsectors; + } + } + } + } + } + + usbhost_givesem(&priv->exclsem); + } + + /* On success, return the number of blocks written */ + + return ret; +} +#endif + +/**************************************************************************** + * Name: usbhost_geometry + * + * Description: Return device geometry + * + ****************************************************************************/ + +static int usbhost_geometry(FAR struct inode *inode, struct geometry *geometry) +{ + FAR struct usbhost_state_s *priv; + int ret = -EINVAL; + + uvdbg("Entry\n"); + DEBUGASSERT(inode && inode->i_private); + + /* Check if the mass storage device is still connected */ + + priv = (FAR struct usbhost_state_s *)inode->i_private; + if (priv->disconnected) + { + /* No... the block driver is no longer bound to the class. That means that + * the USB storage device is no longer connected. Refuse to return any + * geometry info. + */ + + ret = -ENODEV; + } + else if (geometry) + { + /* Return the geometry of the USB mass storage device */ + + usbhost_takesem(&priv->exclsem); + + geometry->geo_available = true; + geometry->geo_mediachanged = false; +#ifdef CONFIG_FS_WRITABLE + geometry->geo_writeenabled = true; +#else + geometry->geo_writeenabled = false; +#endif + geometry->geo_nsectors = priv->nblocks; + geometry->geo_sectorsize = priv->blocksize; + usbhost_givesem(&priv->exclsem); + + uvdbg("nsectors: %ld sectorsize: %d\n", + (long)geometry->geo_nsectors, geometry->geo_sectorsize); + + ret = OK; + } + + return ret; +} + +/**************************************************************************** + * Name: usbhost_ioctl + * + * Description: Return device geometry + * + ****************************************************************************/ + +static int usbhost_ioctl(FAR struct inode *inode, int cmd, unsigned long arg) +{ + FAR struct usbhost_state_s *priv; + int ret; + + uvdbg("Entry\n"); + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct usbhost_state_s *)inode->i_private; + + /* Check if the mass storage device is still connected */ + + if (priv->disconnected) + { + /* No... the block driver is no longer bound to the class. That means that + * the USB storage device is no longer connected. Refuse to process any + * ioctl commands. + */ + + ret = -ENODEV; + } + else + { + /* Process the IOCTL by command */ + + usbhost_takesem(&priv->exclsem); + switch (cmd) + { + /* Add support for ioctl commands here */ + + default: + ret = -ENOTTY; + break; + } + usbhost_givesem(&priv->exclsem); + } + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbhost_storageinit + * + * Description: + * Initialize the USB host storage class. This function should be called + * be platform-specific code in order to initialize and register support + * for the USB host storage class. + * + * Input Parameters: + * None + * + * Returned Values: + * On success this function will return zero (OK); A negated errno value + * will be returned on failure. + * + ****************************************************************************/ + +int usbhost_storageinit(void) +{ + /* If we have been configured to use pre-allocated storage class instances, + * then place all of the pre-allocated USB host storage class instances + * into a free list. + */ + +#if CONFIG_USBHOST_NPREALLOC > 0 + int i; + + g_freelist = NULL; + for (i = 0; i < CONFIG_USBHOST_NPREALLOC; i++) + { + struct usbhost_state_s *class = &g_prealloc[i]; + class->class.flink = g_freelist; + g_freelist = class; + } +#endif + + /* Advertise our availability to support (certain) mass storage devices */ + + return usbhost_registerclass(&g_storage); +} + +#endif /* CONFIG_USBHOST && !CONFIG_USBHOST_BULK_DISABLE && !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 */ diff --git a/nuttx/drivers/watchdog.c b/nuttx/drivers/watchdog.c new file mode 100644 index 0000000000..4f73574443 --- /dev/null +++ b/nuttx/drivers/watchdog.c @@ -0,0 +1,575 @@ +/**************************************************************************** + * drivers/watchdog.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_WATCHDOG + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Debug ********************************************************************/ +/* Non-standard debug that may be enabled just for testing the watchdog driver */ + +#ifdef CONFIG_DEBUG_WATCHDOG +# define wddbg dbg +# define wdvdbg vdbg +# define wdlldbg lldbg +# define wdllvdbg llvdbg +#else +# define wddbg(x...) +# define wdvdbg(x...) +# define wdlldbg(x...) +# define wdllvdbg(x...) +#endif + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +/* This structure describes the state of the upper half driver */ + +struct watchdog_upperhalf_s +{ + uint8_t crefs; /* The number of times the device has been opened */ + sem_t exclsem; /* Supports mutual exclusion */ + FAR char *path; /* Registration path */ + + /* The contained lower-half driver */ + + FAR struct watchdog_lowerhalf_s *lower; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int wdog_open(FAR struct file *filep); +static int wdog_close(FAR struct file *filep); +static ssize_t wdog_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t wdog_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +static int wdog_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_wdogops = +{ + wdog_open, /* open */ + wdog_close, /* close */ + wdog_read, /* read */ + wdog_write, /* write */ + 0, /* seek */ + wdog_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , 0 /* poll */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/************************************************************************************ + * Name: wdog_open + * + * Description: + * This function is called whenever the watchdog timer device is opened. + * + ************************************************************************************/ + +static int wdog_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct watchdog_upperhalf_s *upper = inode->i_private; + uint8_t tmp; + int ret; + + wdvdbg("crefs: %d\n", upper->crefs); + + /* Get exclusive access to the device structures */ + + ret = sem_wait(&upper->exclsem); + if (ret < 0) + { + ret = -errno; + goto errout; + } + + /* Increment the count of references to the device. If this the first + * time that the driver has been opened for this device, then initialize + * the device. + */ + + tmp = upper->crefs + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + goto errout_with_sem; + } + + /* Save the new open count */ + + upper->crefs = tmp; + ret = OK; + +errout_with_sem: + sem_post(&upper->exclsem); + +errout: + return ret; +} + +/************************************************************************************ + * Name: wdog_close + * + * Description: + * This function is called when the watchdog timer device is closed. + * + ************************************************************************************/ + +static int wdog_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct watchdog_upperhalf_s *upper = inode->i_private; + int ret; + + wdvdbg("crefs: %d\n", upper->crefs); + + /* Get exclusive access to the device structures */ + + ret = sem_wait(&upper->exclsem); + if (ret < 0) + { + ret = -errno; + goto errout; + } + + /* Decrement the references to the driver. If the reference count will + * decrement to 0, then uninitialize the driver. + */ + + if (upper->crefs > 0) + { + upper->crefs--; + } + + sem_post(&upper->exclsem); + ret = OK; + +errout: + return ret; +} + +/************************************************************************************ + * Name: wdog_read + * + * Description: + * A dummy read method. This is provided only to satsify the VFS layer. + * + ************************************************************************************/ + +static ssize_t wdog_read(FAR struct file *filep, FAR char *buffer, size_t buflen) +{ + /* Return zero -- usually meaning end-of-file */ + + return 0; +} + +/************************************************************************************ + * Name: wdog_write + * + * Description: + * A dummy write method. This is provided only to satsify the VFS layer. + * + ************************************************************************************/ + +static ssize_t wdog_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) +{ + return 0; +} + +/************************************************************************************ + * Name: wdog_ioctl + * + * Description: + * The standard ioctl method. This is where ALL of the watchdog timer work is + * done. + * + ************************************************************************************/ + +static int wdog_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct watchdog_upperhalf_s *upper = inode->i_private; + FAR struct watchdog_lowerhalf_s *lower = upper->lower; + int ret; + + wdvdbg("cmd: %d arg: %ld\n", cmd, arg); + DEBUGASSERT(upper && lower); + + /* Get exclusive access to the device structures */ + + ret = sem_wait(&upper->exclsem); + if (ret < 0) + { + return ret; + } + + /* Handle built-in ioctl commands */ + + switch (cmd) + { + /* cmd: WDIOC_START + * Description: Start the watchdog timer + * Argument: Ignored + */ + + case WDIOC_START: + { + /* Start the watchdog timer, resetting the time to the current timeout */ + + DEBUGASSERT(lower->ops->start); /* Required */ + ret = lower->ops->start(lower); + } + break; + + /* cmd: WDIOC_STOP + * Description: Stop the watchdog timer + * Argument: Ignored + */ + + case WDIOC_STOP: + { + /* Stop the watchdog timer */ + + DEBUGASSERT(lower->ops->stop); /* Required */ + ret = lower->ops->stop(lower); + } + break; + + /* cmd: WDIOC_GETSTATUS + * Description: et the status of the watchdog timer. + * Argument: A writeable pointer to struct watchdog_status_s. + */ + + case WDIOC_GETSTATUS: + { + FAR struct watchdog_status_s *status; + + /* Get the current watchdog timer status */ + + if (lower->ops->getstatus) /* Optional */ + { + status = (FAR struct watchdog_status_s *)((uintptr_t)arg); + if (status) + { + ret = lower->ops->getstatus(lower, status); + } + else + { + ret = -EINVAL; + } + } + else + { + ret = -ENOSYS; + } + } + break; + + /* cmd: WDIOC_SETTIMEOUT + * Description: Reset the watchdog timeout to this value + * Argument: A 32-bit timeout value in milliseconds. + */ + + case WDIOC_SETTIMEOUT: + { + /* Set a new timeout value (and reset the watchdog timer) */ + + if (lower->ops->settimeout) /* Optional */ + { + ret = lower->ops->settimeout(lower, (uint32_t)arg); + } + else + { + ret = -ENOSYS; + } + } + break; + + /* cmd: WDIOC_CAPTURE + * Description: Do not reset. Instead, called this handler. + * Argument: A pointer to struct watchdog_capture_s. + */ + + case WDIOC_CAPTURE: + { + FAR struct watchdog_capture_s *capture; + + /* Don't reset on watchdog timer timeout; instead, call this user + * provider timeout handler. NOTE: Providing handler==NULL will + * restore the reset behavior. + */ + + if (lower->ops->capture) /* Optional */ + { + capture = (FAR struct watchdog_capture_s *)((uintptr_t)arg); + if (capture) + { + capture->oldhandler = + lower->ops->capture(lower, capture->newhandler); + ret = OK; + } + else + { + ret = -EINVAL; + } + } + else + { + ret = -ENOSYS; + } + } + break; + + /* cmd: WDIOC_KEEPALIVE + * Description: Reset the watchdog timer ("ping", "pet the dog") + * Argument: Argument: Ignored + */ + + case WDIOC_KEEPALIVE: + { + /* Reset the watchdog timer to the current timeout value, prevent any + * imminent watchdog timeouts. This is sometimes referred as + * "pinging" the watchdog timer or "petting the dog". + */ + + if (lower->ops->keepalive) /* Optional */ + { + ret = lower->ops->keepalive(lower); + } + else + { + ret = -ENOSYS; + } + } + break; + + + /* Any unrecognized IOCTL commands might be platform-specific ioctl commands */ + + default: + { + wdvdbg("Forwarding unrecognized cmd: %d arg: %ld\n", cmd, arg); + + /* An ioctl commands that are not recognized by the "upper-half" + * driver are forwarded to the lower half driver through this + * method. + */ + + if (lower->ops->ioctl) /* Optional */ + { + ret = lower->ops->ioctl(lower, cmd, arg); + } + else + { + ret = -ENOSYS; + } + } + break; + } + + sem_post(&upper->exclsem); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: watchdog_register + * + * Description: + * This function binds an instance of a "lower half" watchdog driver with the + * "upper half" watchdog device and registers that device so that can be used + * by application code. + * + * When this function is called, the "lower half" driver should be in the + * disabled state (as if the stop() method had already been called). + * + * Input parameters: + * dev path - The full path to the driver to be registers in the NuttX + * pseudo-filesystem. The recommended convention is to name all watchdog + * drivers as "/dev/watchdog0", "/dev/watchdog1", etc. where the driver + * path differs only in the "minor" number at the end of the device name. + * lower - A pointer to an instance of lower half watchdog driver. This + * instance is bound to the watchdog driver and must persists as long as + * the driver persists. + * + * Returned Value: + * On success, a non-NULL handle is returned to the caller. In the event + * of any failure, a NULL value is returned. + * + ****************************************************************************/ + +FAR void *watchdog_register(FAR const char *path, + FAR struct watchdog_lowerhalf_s *lower) +{ + FAR struct watchdog_upperhalf_s *upper; + int ret; + + DEBUGASSERT(path && lower); + wdvdbg("Entry: path=%s\n", path); + + /* Allocate the upper-half data structure */ + + upper = (FAR struct watchdog_upperhalf_s *) + kzalloc(sizeof(struct watchdog_upperhalf_s)); + if (!upper) + { + wddbg("Upper half allocation failed\n"); + goto errout; + } + + /* Initialize the watchdog timer device structure (it was already zeroed + * by kzalloc()). + */ + + sem_init(&upper->exclsem, 0, 1); + upper->lower = lower; + + /* Copy the registration path */ + + upper->path = strdup(path); + if (!upper->path) + { + wddbg("Path allocation failed\n"); + goto errout_with_upper; + } + + /* Register the watchdog timer device */ + + ret = register_driver(path, &g_wdogops, 0666, upper); + if (ret < 0) + { + wddbg("register_driver failed: %d\n", ret); + goto errout_with_path; + } + + return (FAR void *)upper; + +errout_with_path: + kfree(upper->path); + +errout_with_upper: + sem_destroy(&upper->exclsem); + kfree(upper); + +errout: + return NULL; +} + +/**************************************************************************** + * Name: watchdog_unregister + * + * Description: + * This function can be called to disable and unregister the watchdog + * device driver. + * + * Input parameters: + * handle - This is the handle that was returned by watchdog_register() + * + * Returned Value: + * None + * + ****************************************************************************/ + +void watchdog_unregister(FAR void *handle) +{ + FAR struct watchdog_upperhalf_s *upper; + FAR struct watchdog_lowerhalf_s *lower; + + /* Recover the pointer to the upper-half driver state */ + + upper = (FAR struct watchdog_upperhalf_s *)handle; + lower = upper->lower; + DEBUGASSERT(upper && lower); + + wdvdbg("Unregistering: %s\n", upper->path); + + /* Disable the watchdog timer */ + + DEBUGASSERT(lower->ops->stop); /* Required */ + (void)lower->ops->stop(lower); + + /* Unregister the watchdog timer device */ + + (void)unregister_driver(upper->path); + + /* Then free all of the driver resources */ + + kfree(upper->path); + sem_destroy(&upper->exclsem); + kfree(upper); +} + +#endif /* CONFIG_WATCHDOG */ diff --git a/nuttx/drivers/wireless/Kconfig b/nuttx/drivers/wireless/Kconfig new file mode 100644 index 0000000000..ae2bf31307 --- /dev/null +++ b/nuttx/drivers/wireless/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# diff --git a/nuttx/drivers/wireless/Make.defs b/nuttx/drivers/wireless/Make.defs new file mode 100644 index 0000000000..ac73c8d85e --- /dev/null +++ b/nuttx/drivers/wireless/Make.defs @@ -0,0 +1,47 @@ +############################################################################ +# drivers/wireless/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_WIRELESS),y) + +# Include wireless drivers + +CSRCS += cc1101.c ISM1_868MHzGFSK100kbps.c ISM2_905MHzGFSK250kbps.c + +# Include wireless build support + +DEPPATH += --dep-path wireless/cc1101 +VPATH += :wireless/cc1101 +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/wireless/cc1101} +endif diff --git a/nuttx/drivers/wireless/cc1101/ISM1_868MHzGFSK100kbps.c b/nuttx/drivers/wireless/cc1101/ISM1_868MHzGFSK100kbps.c new file mode 100644 index 0000000000..5c4c58ab20 --- /dev/null +++ b/nuttx/drivers/wireless/cc1101/ISM1_868MHzGFSK100kbps.c @@ -0,0 +1,113 @@ +/**************************************************************************** + * drivers/wireless/cc1101/ISM1_868MHzGFSK100kbps.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Copyright (C) 2011 Ales Verbic. All rights reserved. + * + * Authors: Uros Platise + * Ales Verbic + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include + +/** Settings for 868 MHz, GFSK at 100kbps + * + * ISM Region 1 (Europe) only, Band 868–870 MHz + * + * Frequency ERP Duty Cycle Bandwidth Remarks + * 868 – 868.6 MHz +14 dBm < 1% No limits + * 868.7 – 869.2 MHz +14 dBm < 0.1% No limits + * 869.3 – 869.4 MHz +10 dBm No limits < 25 kHz Appropriate access protocol required + * 869.4 – 869.65 MHz +27 dBm < 10% < 25 kHz Channels may be combined to one high speed channel + * 869.7 -870 MHz +7 dBm No limits No limits + * + * Deviation = 46.142578 + * Base frequency = 867.999985 + * Carrier frequency = 867.999985 + * Channel number = 0 + * Carrier frequency = 867.999985 + * Modulated = true + * Modulation format = GFSK + * Manchester enable = false + * Sync word qualifier mode = 30/32 sync word bits detected + * Preamble count = 4 + * Channel spacing = 199.813843 + * Carrier frequency = 867.999985 + * Data rate = 99.9069 + * RX filter BW = 210.937500 + * Data format = Normal mode + * Length config = Fixed packet length mode. Length configured in PKTLEN register + * CRC enable = true + * Packet length = 62 + * Device address = 00 + * Address config = NO Address check, no broadcast + * CRC autoflush = true + * PA ramping = false + * TX power = 0 + */ +const struct c1101_rfsettings_s cc1101_rfsettings_ISM1_868MHzGFSK100kbps = { + .FSCTRL1 = 0x08, // FSCTRL1 Frequency Synthesizer Control + .FSCTRL0 = 0x00, // FSCTRL0 Frequency Synthesizer Control + + .FREQ2 = 0x20, // FREQ2 Frequency Control Word, High Byte + .FREQ1 = 0x25, // FREQ1 Frequency Control Word, Middle Byte + .FREQ0 = 0xED, // FREQ0 Frequency Control Word, Low Byte + + .MDMCFG4 = 0x8B, // MDMCFG4 Modem Configuration + .MDMCFG3 = 0xE5, // MDMCFG3 Modem Configuration + .MDMCFG2 = 0x13, // MDMCFG2 Modem Configuration + .MDMCFG1 = 0x22, // MDMCFG1 Modem Configuration + .MDMCFG0 = 0xE5, // MDMCFG0 Modem Configuration + + .DEVIATN = 0x46, // DEVIATN Modem Deviation Setting + + .FOCCFG = 0x1D, // FOCCFG Frequency Offset Compensation Configuration + + .BSCFG = 0x1C, // BSCFG Bit Synchronization Configuration + + .AGCCTRL2= 0xC7, // AGCCTRL2 AGC Control + .AGCCTRL1= 0x00, // AGCCTRL1 AGC Control + .AGCCTRL0= 0xB2, // AGCCTRL0 AGC Control + + .FREND1 = 0xB6, // FREND1 Front End RX Configuration + .FREND0 = 0x10, // FREND0 Front End TX Configuration + + .FSCAL3 = 0xEA, // FSCAL3 Frequency Synthesizer Calibration + .FSCAL2 = 0x2A, // FSCAL2 Frequency Synthesizer Calibration + .FSCAL1 = 0x00, // FSCAL1 Frequency Synthesizer Calibration + .FSCAL0 = 0x1F, // FSCAL0 Frequency Synthesizer Calibration + + .CHMIN = 0, // Fix at 9th channel: 869.80 MHz +- 100 kHz RF Bandwidth + .CHMAX = 9, // single channel + + .PAMAX = 8, // 0 means power OFF, 8 represents PA[7] + .PA = {0x03, 0x0F, 0x1E, 0x27, 0x67, 0x50, 0x81, 0xC2} +}; diff --git a/nuttx/drivers/wireless/cc1101/ISM2_905MHzGFSK250kbps.c b/nuttx/drivers/wireless/cc1101/ISM2_905MHzGFSK250kbps.c new file mode 100644 index 0000000000..e5655bed6b --- /dev/null +++ b/nuttx/drivers/wireless/cc1101/ISM2_905MHzGFSK250kbps.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * drivers/wireless/cc1101/ISM2_905MHzGFSK250kbps.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Copyright (C) 2011 Ales Verbic. All rights reserved. + * + * Authors: Uros Platise + * Ales Verbic + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include + +/** Settings for 905 MHz, GFSK at 250kbps + * + * ISM Region 2 (America) only, Band 902–928 MHz + * + * Cordless phones 1 W + * Microwave ovens 750 W + * Industrial heaters 100 kW + * Military radar 1000 kW + * + * Deviation = 126.953125 + * Base frequency = 901.999969 + * Carrier frequency = 905.998993 + * Channel number = 20 + * Carrier frequency = 905.998993 + * Modulated = true + * Modulation format = GFSK + * Manchester enable = false + * Sync word qualifier mode = 30/32 sync word bits detected + * Preamble count = 4 + * Channel spacing = 199.951172 + * Carrier frequency = 905.998993 + * Data rate = 249.939 + * RX filter BW = 541.666667 + * Data format = Normal mode + * Length config = Variable packet length mode. Packet length configured by the first byte after sync word + * CRC enable = true + * Packet length = 61 + * Device address = 0 + * Address config = No address check + * CRC autoflush = false + * PA ramping = false + * TX power = 0 + */ +const struct c1101_rfsettings_s cc1101_rfsettings_ISM2_905MHzGFSK250kbps = { + .FSCTRL1 = 0x0C, // FSCTRL1 Frequency Synthesizer Control + .FSCTRL0 = 0x00, // FSCTRL0 Frequency Synthesizer Control + + .FREQ2 = 0x22, // FREQ2 Frequency Control Word, High Byte + .FREQ1 = 0xB1, // FREQ1 Frequency Control Word, Middle Byte + .FREQ0 = 0x3B, // FREQ0 Frequency Control Word, Low Byte + + .MDMCFG4 = 0x2D, // MDMCFG4 Modem Configuration + .MDMCFG3 = 0x3B, // MDMCFG3 Modem Configuration + .MDMCFG2 = 0x13, // MDMCFG2 Modem Configuration + .MDMCFG1 = 0x22, // MDMCFG1 Modem Configuration + .MDMCFG0 = 0xF8, // MDMCFG0 Modem Configuration + + .DEVIATN = 0x62, // DEVIATN Modem Deviation Setting + + .FOCCFG = 0x1D, // FOCCFG Frequency Offset Compensation Configuration + + .BSCFG = 0x1C, // BSCFG Bit Synchronization Configuration + + .AGCCTRL2= 0xC7, // AGCCTRL2 AGC Control + .AGCCTRL1= 0x00, // AGCCTRL1 AGC Control + .AGCCTRL0= 0xB0, // AGCCTRL0 AGC Control + + .FREND1 = 0xB6, // FREND1 Front End RX Configuration + .FREND0 = 0x10, // FREND0 Front End TX Configuration + + .FSCAL3 = 0xEA, // FSCAL3 Frequency Synthesizer Calibration + .FSCAL2 = 0x2A, // FSCAL2 Frequency Synthesizer Calibration + .FSCAL1 = 0x00, // FSCAL1 Frequency Synthesizer Calibration + .FSCAL0 = 0x1F, // FSCAL0 Frequency Synthesizer Calibration + + .CHMIN = 0, // VERIFY REGULATIONS! + .CHMAX = 0xFF, + + .PAMAX = 8, // 0 means power OFF, 8 represents PA[7] + .PA = {0x03, 0x0E, 0x1E, 0x27, 0x39, 0x8E, 0xCD, 0xC0} +}; diff --git a/nuttx/drivers/wireless/cc1101/Kconfig b/nuttx/drivers/wireless/cc1101/Kconfig new file mode 100644 index 0000000000..ae2bf31307 --- /dev/null +++ b/nuttx/drivers/wireless/cc1101/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# diff --git a/nuttx/drivers/wireless/cc1101/cc1101.c b/nuttx/drivers/wireless/cc1101/cc1101.c new file mode 100755 index 0000000000..45faaecd28 --- /dev/null +++ b/nuttx/drivers/wireless/cc1101/cc1101.c @@ -0,0 +1,812 @@ +/**************************************************************************** + * drivers/wireless/cc1101/cc1101.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * + * Authors: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** \file + * \author Uros Platise + * \brief Chipcon CC1101 Device Driver + * + * Features: + * - Maximum data length: 61 bytes CC1101_PACKET_MAXDATALEN + * - Packet length includes two additional bytes: CC1101_PACKET_MAXTOTALLEN + * - Requires one GDO to trigger end-of-packets in RX and TX modes. + * - Variable packet length with data payload between 1..61 bytes + * (three bytes are reserved for packet length, and RSSI and LQI + * appended at the end of RXFIFO after each reception) + * - Support for General Digital Outputs with overload protection + * (single XOSC pin is allowed, otherwise error is returned) + * - Loadable RF settings, one for ISM Region 1 (Europe) and one for + * ISM Region 2 (Complete America) + * + * Todo: + * - Extend max packet length up to 255 bytes or rather infinite < 4096 bytes + * - Power up/down modes + * - Sequencing between states or add protection for correct termination of + * various different state (so that CC1101 does not block in case of improper use) + * + * \par RSSI and LQI value interpretation + * + * The LQI can be read from the LQI status register or it can be appended + * to the received packet in the RX FIFO. LQI is a metric of the current + * quality of the received signal. The LQI gives an estimate of how easily + * a received signal can be demodulated by accumulating the magnitude of + * the error between ideal constellations and the received signal over + * the 64 symbols immediately following the sync word. LQI is best used + * as a relative measurement of the link quality (a high value indicates + * a better link than what a low value does), since the value is dependent + * on the modulation format. + * + * To simplify: If the received modulation is FSK or GFSK, the receiver + * will measure the frequency of each "bit" and compare it with the + * expected frequency based on the channel frequency and the deviation + * and the measured frequency offset. If other modulations are used, the + * error of the modulated parameter (frequency for FSK/GFSK, phase for + * MSK, amplitude for ASK etc) will be measured against the expected + * ideal value + * + * RSSI (Received Signal Strength Indicator) is a signal strength + * indication. It does not care about the "quality" or "correctness" of + * the signal. LQI does not care about the actual signal strength, but + * the signal quality often is linked to signal strength. This is because + * a strong signal is likely to be less affected by noise and thus will + * be seen as "cleaner" or more "correct" by the receiver. + * + * There are four to five "extreme cases" that can be used to illustrate + * how RSSI and LQI work: + * 1. A weak signal in the presence of noise may give low RSSI and low LQI. + * 2. A weak signal in "total" absence of noise may give low RSSI and high LQI. + * 3. Strong noise (usually coming from an interferer) may give high RSSI and low LQI. + * 4. A strong signal without much noise may give high RSSI and high LQI. + * 5. A very strong signal that causes the receiver to saturate may give + * high RSSI and low LQI. + * + * Note that both RSSI and LQI are best used as relative measurements since + * the values are dependent on the modulation format. + **/ + +#include +#include +#include +#include +#include +#include + +#include +#include + + +/**************************************************************************** + * Declarations + ****************************************************************************/ + +#define CC1101_SPIFREQ_BURST 6500000 /* Hz, no delay */ +#define CC1101_SPIFREQ_SINGLE 9000000 /* Hz, single access only - no delay */ + +#define CC1101_MCSM0_VALUE 0x1C + +/**************************************************************************** + * Chipcon CC1101 Internal Registers + ****************************************************************************/ + +/* Configuration Registers */ + +#define CC1101_IOCFG2 0x00 /* GDO2 output pin configuration */ +#define CC1101_IOCFG1 0x01 /* GDO1 output pin configuration */ +#define CC1101_IOCFG0 0x02 /* GDO0 output pin configuration */ +#define CC1101_FIFOTHR 0x03 /* RX FIFO and TX FIFO thresholds */ +#define CC1101_SYNC1 0x04 /* Sync word, high byte */ +#define CC1101_SYNC0 0x05 /* Sync word, low byte */ +#define CC1101_PKTLEN 0x06 /* Packet length */ +#define CC1101_PKTCTRL1 0x07 /* Packet automation control */ +#define CC1101_PKTCTRL0 0x08 /* Packet automation control */ +#define CC1101_ADDR 0x09 /* Device address */ +#define CC1101_CHANNR 0x0A /* Channel number */ +#define CC1101_FSCTRL1 0x0B /* Frequency synthesizer control */ +#define CC1101_FSCTRL0 0x0C /* Frequency synthesizer control */ +#define CC1101_FREQ2 0x0D /* Frequency control word, high byte */ +#define CC1101_FREQ1 0x0E /* Frequency control word, middle byte */ +#define CC1101_FREQ0 0x0F /* Frequency control word, low byte */ +#define CC1101_MDMCFG4 0x10 /* Modem configuration */ +#define CC1101_MDMCFG3 0x11 /* Modem configuration */ +#define CC1101_MDMCFG2 0x12 /* Modem configuration */ +#define CC1101_MDMCFG1 0x13 /* Modem configuration */ +#define CC1101_MDMCFG0 0x14 /* Modem configuration */ +#define CC1101_DEVIATN 0x15 /* Modem deviation setting */ +#define CC1101_MCSM2 0x16 /* Main Radio Cntrl State Machine config */ +#define CC1101_MCSM1 0x17 /* Main Radio Cntrl State Machine config */ +#define CC1101_MCSM0 0x18 /* Main Radio Cntrl State Machine config */ +#define CC1101_FOCCFG 0x19 /* Frequency Offset Compensation config */ +#define CC1101_BSCFG 0x1A /* Bit Synchronization configuration */ +#define CC1101_AGCCTRL2 0x1B /* AGC control */ +#define CC1101_AGCCTRL1 0x1C /* AGC control */ +#define CC1101_AGCCTRL0 0x1D /* AGC control */ +#define CC1101_WOREVT1 0x1E /* High byte Event 0 timeout */ +#define CC1101_WOREVT0 0x1F /* Low byte Event 0 timeout */ +#define CC1101_WORCTRL 0x20 /* Wake On Radio control */ +#define CC1101_FREND1 0x21 /* Front end RX configuration */ +#define CC1101_FREND0 0x22 /* Front end TX configuration */ +#define CC1101_FSCAL3 0x23 /* Frequency synthesizer calibration */ +#define CC1101_FSCAL2 0x24 /* Frequency synthesizer calibration */ +#define CC1101_FSCAL1 0x25 /* Frequency synthesizer calibration */ +#define CC1101_FSCAL0 0x26 /* Frequency synthesizer calibration */ +#define CC1101_RCCTRL1 0x27 /* RC oscillator configuration */ +#define CC1101_RCCTRL0 0x28 /* RC oscillator configuration */ +#define CC1101_FSTEST 0x29 /* Frequency synthesizer cal control */ +#define CC1101_PTEST 0x2A /* Production test */ +#define CC1101_AGCTEST 0x2B /* AGC test */ +#define CC1101_TEST2 0x2C /* Various test settings */ +#define CC1101_TEST1 0x2D /* Various test settings */ +#define CC1101_TEST0 0x2E /* Various test settings */ + +/* Status registers */ + +#define CC1101_PARTNUM (0x30 | 0xc0) /* Part number */ +#define CC1101_VERSION (0x31 | 0xc0) /* Current version number */ +#define CC1101_FREQEST (0x32 | 0xc0) /* Frequency offset estimate */ +#define CC1101_LQI (0x33 | 0xc0) /* Demodulator estimate for link quality */ +#define CC1101_RSSI (0x34 | 0xc0) /* Received signal strength indication */ +#define CC1101_MARCSTATE (0x35 | 0xc0) /* Control state machine state */ +#define CC1101_WORTIME1 (0x36 | 0xc0) /* High byte of WOR timer */ +#define CC1101_WORTIME0 (0x37 | 0xc0) /* Low byte of WOR timer */ +#define CC1101_PKTSTATUS (0x38 | 0xc0) /* Current GDOx status and packet status */ +#define CC1101_VCO_VC_DAC (0x39 | 0xc0) /* Current setting from PLL cal module */ +#define CC1101_TXBYTES (0x3A | 0xc0) /* Underflow and # of bytes in TXFIFO */ +#define CC1101_RXBYTES (0x3B | 0xc0) /* Overflow and # of bytes in RXFIFO */ +#define CC1101_RCCTRL1_STATUS (0x3C | 0xc0) /* Last RC oscilator calibration results */ +#define CC1101_RCCTRL0_STATUS (0x3D | 0xc0) /* Last RC oscilator calibration results */ + +/* Multi byte memory locations */ + +#define CC1101_PATABLE 0x3E +#define CC1101_TXFIFO 0x3F +#define CC1101_RXFIFO 0x3F + +/* Definitions for burst/single access to registers */ + +#define CC1101_WRITE_BURST 0x40 +#define CC1101_READ_SINGLE 0x80 +#define CC1101_READ_BURST 0xC0 + +/* Strobe commands */ + +#define CC1101_SRES 0x30 /* Reset chip. */ +#define CC1101_SFSTXON 0x31 /* Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). */ +#define CC1101_SXOFF 0x32 /* Turn off crystal oscillator. */ +#define CC1101_SCAL 0x33 /* Calibrate frequency synthesizer and turn it off */ +#define CC1101_SRX 0x34 /* Enable RX. Perform calibration first if switching from IDLE and MCSM0.FS_AUTOCAL=1. */ +#define CC1101_STX 0x35 /* Enable TX. Perform calibration first if IDLE and MCSM0.FS_AUTOCAL=1. */ + /* If switching from RX state and CCA is enabled then go directly to TX if channel is clear. */ +#define CC1101_SIDLE 0x36 /* Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable. */ +#define CC1101_SAFC 0x37 /* Perform AFC adjustment of the frequency synthesizer */ +#define CC1101_SWOR 0x38 /* Start automatic RX polling sequence (Wake-on-Radio) */ +#define CC1101_SPWD 0x39 /* Enter power down mode when CSn goes high. */ +#define CC1101_SFRX 0x3A /* Flush the RX FIFO buffer. */ +#define CC1101_SFTX 0x3B /* Flush the TX FIFO buffer. */ +#define CC1101_SWORRST 0x3C /* Reset real time clock. */ +#define CC1101_SNOP 0x3D /* No operation. */ + +/* Modem Control */ + +#define CC1101_MCSM0_XOSC_FORCE_ON 0x01 + + +/* + * Chip Status Byte + */ + +/* Bit fields in the chip status byte */ + +#define CC1101_STATUS_CHIP_RDYn_BM 0x80 +#define CC1101_STATUS_STATE_BM 0x70 +#define CC1101_STATUS_FIFO_BYTES_AVAILABLE_BM 0x0F + +/* Chip states */ + +#define CC1101_STATE_MASK 0x70 +#define CC1101_STATE_IDLE 0x00 +#define CC1101_STATE_RX 0x10 +#define CC1101_STATE_TX 0x20 +#define CC1101_STATE_FSTXON 0x30 +#define CC1101_STATE_CALIBRATE 0x40 +#define CC1101_STATE_SETTLING 0x50 +#define CC1101_STATE_RX_OVERFLOW 0x60 +#define CC1101_STATE_TX_UNDERFLOW 0x70 + +/* Values of the MACRSTATE register */ + +#define CC1101_MARCSTATE_SLEEP 0x00 +#define CC1101_MARCSTATE_IDLE 0x01 +#define CC1101_MARCSTATE_XOFF 0x02 +#define CC1101_MARCSTATE_VCOON_MC 0x03 +#define CC1101_MARCSTATE_REGON_MC 0x04 +#define CC1101_MARCSTATE_MANCAL 0x05 +#define CC1101_MARCSTATE_VCOON 0x06 +#define CC1101_MARCSTATE_REGON 0x07 +#define CC1101_MARCSTATE_STARTCAL 0x08 +#define CC1101_MARCSTATE_BWBOOST 0x09 +#define CC1101_MARCSTATE_FS_LOCK 0x0A +#define CC1101_MARCSTATE_IFADCON 0x0B +#define CC1101_MARCSTATE_ENDCAL 0x0C +#define CC1101_MARCSTATE_RX 0x0D +#define CC1101_MARCSTATE_RX_END 0x0E +#define CC1101_MARCSTATE_RX_RST 0x0F +#define CC1101_MARCSTATE_TXRX_SWITCH 0x10 +#define CC1101_MARCSTATE_RXFIFO_OVERFLOW 0x11 +#define CC1101_MARCSTATE_FSTXON 0x12 +#define CC1101_MARCSTATE_TX 0x13 +#define CC1101_MARCSTATE_TX_END 0x14 +#define CC1101_MARCSTATE_RXTX_SWITCH 0x15 +#define CC1101_MARCSTATE_TXFIFO_UNDERFLOW 0x16 + +/* Part number and version */ + +#define CC1101_PARTNUM_VALUE 0x00 +#define CC1101_VERSION_VALUE 0x04 + +/* + * Others ... + */ + +#define CC1101_LQI_CRC_OK_BM 0x80 +#define CC1101_LQI_EST_BM 0x7F + + +/**************************************************************************** + * Private Data Types + ****************************************************************************/ + +#define FLAGS_RXONLY 1 /* Indicates receive operation only */ +#define FLAGS_XOSCENABLED 2 /* Indicates that one pin is configured as XOSC/n */ + +struct cc1101_dev_s { + const struct c1101_rfsettings_s *rfsettings; + + struct spi_dev_s * spi; + uint8_t isrpin; /* CC1101 pin used to trigger interrupts */ + uint32_t pinset; /* GPIO of the MCU */ + uint8_t flags; + uint8_t channel; + uint8_t power; +}; + + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +void cc1101_access_begin(struct cc1101_dev_s * dev) +{ + (void)SPI_LOCK(dev->spi, true); + SPI_SELECT(dev->spi, SPIDEV_WIRELESS, true); + SPI_SETMODE(dev->spi, SPIDEV_MODE0); /* CPOL=0, CPHA=0 */ + SPI_SETBITS(dev->spi, 8); +} + + +void cc1101_access_end(struct cc1101_dev_s * dev) +{ + SPI_SELECT(dev->spi, SPIDEV_WIRELESS, false); + (void)SPI_LOCK(dev->spi, false); +} + + +/** CC1101 Access with Range Check + * + * \param dev CC1101 Private Structure + * \param addr CC1101 Address + * \param buf Pointer to buffer, either for read or write access + * \param length when >0 it denotes read access, when <0 it denotes write + * access of -length. abs(length) greater of 1 implies burst mode, + * however + * \return OK on success or errno is set. + */ +int cc1101_access(struct cc1101_dev_s * dev, uint8_t addr, uint8_t *buf, int length) +{ + int stabyte; + + /* Address cannot explicitly define READ command while length WRITE. + * Also access to these cells is only permitted as one byte, eventhough + * transfer is marked as BURST! + */ + + if ( (addr & CC1101_READ_SINGLE) && length != 1 ) + return ERROR; + + /* Prepare SPI */ + + cc1101_access_begin(dev); + + if (length>1 || length < -1) + SPI_SETFREQUENCY(dev->spi, CC1101_SPIFREQ_BURST); + else SPI_SETFREQUENCY(dev->spi, CC1101_SPIFREQ_SINGLE); + + /* Transfer */ + + if (length <= 0) { /* 0 length are command strobes */ + if (length < -1) + addr |= CC1101_WRITE_BURST; + + stabyte = SPI_SEND(dev->spi, addr); + if (length) { + SPI_SNDBLOCK(dev->spi, buf, -length); + } + } + else { + addr |= CC1101_READ_SINGLE; + if (length > 1) + addr |= CC1101_READ_BURST; + + stabyte = SPI_SEND(dev->spi, addr); + SPI_RECVBLOCK(dev->spi, buf, length); + } + + cc1101_access_end(dev); + + return stabyte; +} + + +/** Strobes command and returns chip status byte + * + * By default commands are send as Write. To a command, + * CC1101_READ_SINGLE may be OR'ed to obtain the number of RX bytes + * pending in RX FIFO. + */ +inline uint8_t cc1101_strobe(struct cc1101_dev_s * dev, uint8_t command) +{ + uint8_t status; + + cc1101_access_begin(dev); + SPI_SETFREQUENCY(dev->spi, CC1101_SPIFREQ_SINGLE); + + status = SPI_SEND(dev->spi, command); + + cc1101_access_end(dev); + + return status; +} + + +int cc1101_reset(struct cc1101_dev_s * dev) +{ + cc1101_strobe(dev, CC1101_SRES); + return OK; +} + + +int cc1101_checkpart(struct cc1101_dev_s * dev) +{ + uint8_t partnum, version; + + if (cc1101_access(dev, CC1101_PARTNUM, &partnum, 1) < 0 || + cc1101_access(dev, CC1101_VERSION, &version, 1) < 0) + return ERROR; + + if (partnum == CC1101_PARTNUM_VALUE && version == CC1101_VERSION_VALUE) + return OK; + + return ERROR; +} + + +void cc1101_dumpregs(struct cc1101_dev_s * dev, uint8_t addr, uint8_t length) +{ + uint8_t buf[0x30], i; + + cc1101_access(dev, addr, buf, length); + + printf("CC1101[%2x]: ", addr); + for (i=0; i RX, RX -> RX: 0x3F */ + values[2] = CC1101_MCSM0_VALUE; /* Calibrate on IDLE -> RX/TX, OSC Timeout = ~500 us + TODO: has XOSC_FORCE_ON */ + cc1101_access(dev, CC1101_MCSM2, values, -3); + + /* Wake-On Radio Control */ + + // Not used yet. + + // WOREVT1:WOREVT0 - 16-bit timeout register +} + + +/**************************************************************************** + * Callbacks + ****************************************************************************/ + +volatile int cc1101_interrupt = 0; + +/** External line triggers this callback + * + * The concept todo is: + * - GPIO provides EXTI Interrupt + * - It should handle EXTI Interrupts in ISR, to which chipcon can + * register a callback (and others). The ISR then foreach() calls a + * its callback, and it is up to peripheral to find, whether the cause + * of EXTI ISR was itself. + **/ + +int cc1101_eventcb(int irq, FAR void *context) +{ + cc1101_interrupt++; + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +struct cc1101_dev_s * cc1101_init(struct spi_dev_s * spi, uint8_t isrpin, + uint32_t pinset, const struct c1101_rfsettings_s * rfsettings) +{ + struct cc1101_dev_s * dev; + + ASSERT(spi); + + if ( (dev = kmalloc( sizeof(struct cc1101_dev_s) )) == NULL) { + errno = ENOMEM; + return NULL; + } + + dev->rfsettings = rfsettings; + dev->spi = spi; + dev->isrpin = isrpin; + dev->pinset = pinset; + dev->flags = 0; + dev->channel = rfsettings->CHMIN; + dev->power = rfsettings->PAMAX; + + /* Reset chip, check status bytes */ + + if ( cc1101_reset(dev) < 0 ) { + kfree(dev); + errno = EFAULT; + return NULL; + } + + /* Check part compatibility */ + + if ( cc1101_checkpart(dev) < 0 ) { + kfree(dev); + errno = ENODEV; + return NULL; + } + + /* Configure CC1101: + * - disable GDOx for best performance + * - load RF + * - and packet control + */ + + cc1101_setgdo(dev, CC1101_PIN_GDO0, CC1101_GDO_HIZ); + cc1101_setgdo(dev, CC1101_PIN_GDO1, CC1101_GDO_HIZ); + cc1101_setgdo(dev, CC1101_PIN_GDO2, CC1101_GDO_HIZ); + cc1101_setrf(dev, rfsettings); + cc1101_setpacketctrl(dev); + + /* Set the ISR to be triggerred on falling edge of the: + * + * 6 (0x06) Asserts when sync word has been sent / received, and + * de-asserts at the end of the packet. In RX, the pin will de-assert + * when the optional address check fails or the RX FIFO overflows. + * In TX the pin will de-assert if the TX FIFO underflows. + */ + + cc1101_setgdo(dev, dev->isrpin, CC1101_GDO_SYNC); + + /* Bind to external interrupt line */ + + // depends on STM32: TODO: Make that config within pinset and + // provide general gpio interface + //stm32_gpiosetevent(pinset, false, true, true, cc1101_eventcb); + + return dev; +} + + +int cc1101_deinit(struct cc1101_dev_s * dev) +{ + ASSERT(dev); + + /* Release interrupt */ + //stm32_gpiosetevent(pinset, false, false, false, NULL); + + /* Power down chip */ + cc1101_powerdown(dev); + + /* Release external interrupt line */ + kfree(dev); + + return 0; +} + + +int cc1101_powerup(struct cc1101_dev_s * dev) +{ + ASSERT(dev); + return 0; +} + + +int cc1101_powerdown(struct cc1101_dev_s * dev) +{ + ASSERT(dev); + return 0; +} + + +int cc1101_setgdo(struct cc1101_dev_s * dev, uint8_t pin, uint8_t function) +{ + ASSERT(dev); + ASSERT(pin <= CC1101_IOCFG0); + + if (function >= CC1101_GDO_CLK_XOSC1) { + + /* Only one pin can be enabled at a time as XOSC/n */ + + if (dev->flags & FLAGS_XOSCENABLED) return -EPERM; + + /* Force XOSC to stay active even in sleep mode */ + + int value = CC1101_MCSM0_VALUE | CC1101_MCSM0_XOSC_FORCE_ON; + cc1101_access(dev, CC1101_MCSM0, &value, -1); + + dev->flags |= FLAGS_XOSCENABLED; + } + else if (dev->flags & FLAGS_XOSCENABLED) { + + /* Disable XOSC in sleep mode */ + + int value = CC1101_MCSM0_VALUE; + cc1101_access(dev, CC1101_MCSM0, &value, -1); + + dev->flags &= ~FLAGS_XOSCENABLED; + } + + return cc1101_access(dev, pin, &function, -1); +} + + +int cc1101_setrf(struct cc1101_dev_s * dev, const struct c1101_rfsettings_s *settings) +{ + ASSERT(dev); + ASSERT(settings); + + if (cc1101_access(dev, CC1101_FSCTRL1, &settings->FSCTRL1, -11) < 0) return ERROR; + if (cc1101_access(dev, CC1101_FOCCFG, &settings->FOCCFG, -5) < 0) return ERROR; + if (cc1101_access(dev, CC1101_FREND1, &settings->FREND1, -6) < 0) return ERROR; + + /* Load Power Table */ + + if (cc1101_access(dev, CC1101_PATABLE, settings->PA, -8) < 0) return ERROR; + + /* If channel is out of valid range, mark that. Limit power. + * We are not allowed to send any data, but are allowed to listen + * and receive. + */ + + cc1101_setchannel(dev, dev->channel); + cc1101_setpower(dev, dev->power); + + return OK; +} + + +int cc1101_setchannel(struct cc1101_dev_s * dev, uint8_t channel) +{ + ASSERT(dev); + + /* Store localy in further checks */ + + dev->channel = channel; + + /* If channel is out of valid, we are allowed to listen and receive only */ + + if (channel < dev->rfsettings->CHMIN || channel > dev->rfsettings->CHMAX) + dev->flags |= FLAGS_RXONLY; + else dev->flags &= ~FLAGS_RXONLY; + + cc1101_access(dev, CC1101_CHANNR, &dev->channel, -1); + + return dev->flags & FLAGS_RXONLY; +} + + +uint8_t cc1101_setpower(struct cc1101_dev_s * dev, uint8_t power) +{ + ASSERT(dev); + + if (power > dev->rfsettings->PAMAX) + power = dev->rfsettings->PAMAX; + + dev->power = power; + + if (power == 0) { + dev->flags |= FLAGS_RXONLY; + return 0; + } + else dev->flags &= ~FLAGS_RXONLY; + + /* Add remaining part from RF table (to get rid of readback) */ + + power--; + power |= dev->rfsettings->FREND0; + + /* On error, report that as zero power */ + + if (cc1101_access(dev, CC1101_FREND0, &power, -1) < 0) + dev->power = 0; + + return dev->power; +} + + +int cc1101_calcRSSIdBm(int rssi) +{ + if (rssi >= 128) rssi -= 256; + return (rssi >> 1) - 74; +} + + +int cc1101_receive(struct cc1101_dev_s * dev) +{ + ASSERT(dev); + + /* \todo Wait for IDLE before going into another state? */ + + cc1101_interrupt = 0; + + cc1101_strobe(dev, CC1101_SRX | CC1101_READ_SINGLE); + + return 0; +} + + +int cc1101_read(struct cc1101_dev_s * dev, uint8_t * buf, size_t size) +{ + ASSERT(dev); + + if (buf==NULL) { + if (size==0) return 64; + // else received packet size + return 0; + } + + if (cc1101_interrupt == 0) return 0; + + int status = cc1101_strobe(dev, CC1101_SNOP | CC1101_READ_SINGLE); + + if (status & CC1101_STATUS_FIFO_BYTES_AVAILABLE_BM && + (status & CC1101_STATE_MASK) == CC1101_STATE_IDLE) { + + uint8_t nbytes; + + cc1101_access(dev, CC1101_RXFIFO, &nbytes, 1); + + nbytes += 2; /* RSSI and LQI */ + + cc1101_access(dev, CC1101_RXFIFO, buf, (nbytes > size) ? size : nbytes); + + /* Flush remaining bytes, if there is no room to receive + * or if there is a BAD CRC + */ + + if (nbytes > size || (nbytes <= size && !(buf[nbytes-1]&0x80)) ) { + printf("Flushing RX FIFO\n"); + cc1101_strobe(dev, CC1101_SFRX); + } + + return nbytes; + } + + return 0; +} + + +int cc1101_write(struct cc1101_dev_s * dev, const uint8_t * buf, size_t size) +{ + uint8_t packetlen; + + ASSERT(dev); + ASSERT(buf); + + if (dev->flags & FLAGS_RXONLY) return -EPERM; + + /* Present limit */ + if (size > CC1101_PACKET_MAXDATALEN) + packetlen = CC1101_PACKET_MAXDATALEN; + else packetlen = size; + + cc1101_access(dev, CC1101_TXFIFO, &packetlen, -1); + cc1101_access(dev, CC1101_TXFIFO, buf, -size); + + return 0; +} + + +int cc1101_send(struct cc1101_dev_s * dev) +{ + ASSERT(dev); + + if (dev->flags & FLAGS_RXONLY) return -EPERM; + + cc1101_interrupt = 0; + + cc1101_strobe(dev, CC1101_STX); + + /* wait until send, going to IDLE */ + + while( cc1101_interrupt == 0 ); + + return 0; +} + + +int cc1101_idle(struct cc1101_dev_s * dev) +{ + ASSERT(dev); + cc1101_strobe(dev, CC1101_SIDLE); + return 0; +} diff --git a/nuttx/fs/Kconfig b/nuttx/fs/Kconfig new file mode 100644 index 0000000000..1d10467351 --- /dev/null +++ b/nuttx/fs/Kconfig @@ -0,0 +1,41 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +comment "File system configuration" + +source fs/fat/Kconfig +source fs/mmap/Kconfig +source fs/nfs/Kconfig +source fs/nxffs/Kconfig +source fs/romfs/Kconfig + +comment "System Logging" + +config SYSLOG + bool "System logging" + default n + ---help--- + Enables generic system logging features. + +config SYSLOG_DEVPATH + string "System log device" + default "/dev/syslog" + depends on SYSLOG + ---help--- + The full path to the system logging device. For the RAMLOG SYSLOG device, + this is normally "/dev/ramlog". For character SYSLOG devices, it should be + some other existing character device (or file) supported by the configuration + (such as "/dev/ttyS1")/ + +config SYSLOG_CHAR + bool "System log character device support" + default y + depends on SYSLOG + ---help--- + Enable the generic character device for the SYSLOG. The full path to the + SYSLOG device is provided by SYSLOG_DEVPATH. A valid character device (or + file) must exist at this path. It will by opened by syslog_initialize. + + Do not enable more than one SYSLOG device. diff --git a/nuttx/fs/Makefile b/nuttx/fs/Makefile new file mode 100644 index 0000000000..ce952e06f9 --- /dev/null +++ b/nuttx/fs/Makefile @@ -0,0 +1,144 @@ +############################################################################ +# fs/Makefile +# +# Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ASRCS = +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +CSRCS = + +# If there are no file descriptors configured, then a small part of the +# logic in this directory may still apply to socket descriptors + +ifeq ($(CONFIG_NFILE_DESCRIPTORS),0) +ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0) + +# Socket descriptor support + +CSRCS += fs_close.c fs_read.c fs_write.c fs_ioctl.c fs_poll.c fs_select.c +endif + +# Support for network access using streams + +ifneq ($(CONFIG_NFILE_STREAMS),0) +CSRCS += fs_fdopen.c +endif + +else + +# Common file/socket descriptor support + +CSRCS += fs_close.c fs_closedir.c fs_dup.c fs_dup2.c fs_fcntl.c \ + fs_filedup.c fs_filedup2.c fs_ioctl.c fs_lseek.c fs_open.c \ + fs_opendir.c fs_poll.c fs_read.c fs_readdir.c fs_rewinddir.c \ + fs_seekdir.c fs_stat.c fs_statfs.c fs_select.c fs_write.c +CSRCS += fs_files.c fs_foreachinode.c fs_inode.c fs_inodeaddref.c \ + fs_inodefind.c fs_inoderelease.c fs_inoderemove.c \ + fs_inodereserve.c +CSRCS += fs_registerdriver.c fs_unregisterdriver.c +CSRCS += fs_registerblockdriver.c fs_unregisterblockdriver.c \ + fs_findblockdriver.c fs_openblockdriver.c fs_closeblockdriver.c + +include mmap/Make.defs + +# Stream support + +ifneq ($(CONFIG_NFILE_STREAMS),0) +CSRCS += fs_fdopen.c +endif + +# System logging to a character device (or file) + +ifeq ($(CONFIG_SYSLOG),y) +ifeq ($(CONFIG_SYSLOG_CHAR),y) +CSRCS += fs_syslog.c +endif +endif + +# Additional files required is mount-able file systems are supported + +ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y) +CSRCS += fs_fsync.c fs_mkdir.c fs_mount.c fs_rename.c fs_rmdir.c \ + fs_umount.c fs_unlink.c +CSRCS += fs_foreachmountpoint.c +include fat/Make.defs +include romfs/Make.defs +include nxffs/Make.defs +include nfs/Make.defs +endif +endif + +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = libfs$(LIBEXT) + +SUBDIRS = mmap fat romfs nxffs:nfs +VPATH = mmap:fat:romfs:nxffs:nfs + +all: $(BIN) + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +.depend: Makefile $(SRCS) + @$(MKDEP) --dep-path . $(MMAPDEPPATH) $(FATDEPPATH) $(ROMFSDEPPATH) $(NXFFSDEPPATH) $(NFSDEPPATH) \ + $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f $(BIN) *~ .*.swp + $(call CLEAN) + @( for dir in $(SUBDIRS); do \ + rm -f $${dir}/*~ $${dir}/.*.swp; \ + done ; ) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/fs/fat/Kconfig b/nuttx/fs/fat/Kconfig new file mode 100644 index 0000000000..30983799d7 --- /dev/null +++ b/nuttx/fs/fat/Kconfig @@ -0,0 +1,55 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config FS_FAT + bool "FAT file system" + default n + depends on !DISABLE_MOUNTPOINT + ---help--- + Enable FAT filesystem support + +if FS_FAT +config FAT_SECTORSIZE + int "FAT sector size" + default 512 + ---help--- + Max supported sector size + +config FAT_LCNAMES + bool "FAT upper/lower names" + default n + ---help--- + Enable use of the NT-style upper/lower case 8.3 + file name support. + +config FAT_LFN + bool "FAT long file names" + default n + ---help--- + Enable FAT long file names. NOTE: Microsoft claims + patents on FAT long file name technology. Please read the + disclaimer in the top-level COPYING file and only enable this + feature if you understand these issues. + +config FAT_MAXFNAME + int "FAT maximum file name size" + depends on FAT_LFN + ---help--- + If CONFIG_FAT_LFN is defined, then the default, maximum long file + name is 255 bytes. This can eat up a lot of memory (especially stack + space). If you are willing to live with some non-standard, short long + file names, then define this value to be something more reasonable. A + good choice would be the same value as selected for NAME_MAX which will + limit the visibility of longer file names anyway. + +config FS_FATTIME + bool "FAT timestamps" + default n + ---help--- + Support FAT date and time. NOTE: There is not + much sense in supporting FAT date and time unless you have a + hardware RTC or other way to get the time and date. + +endif diff --git a/nuttx/fs/fat/Make.defs b/nuttx/fs/fat/Make.defs new file mode 100644 index 0000000000..96be439614 --- /dev/null +++ b/nuttx/fs/fat/Make.defs @@ -0,0 +1,50 @@ +############################################################################ +# Make.defs +# +# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name Nuttx nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_FS_FAT),y) +# Files required for FAT file system support + +ASRCS += +CSRCS += fs_fat32.c fs_fat32dirent.c fs_fat32attrib.c fs_fat32util.c + +# Files required for mkfatfs utility function + +ASRCS += +CSRCS += fs_mkfatfs.c fs_configfat.c fs_writefat.c + +# Argument for dependency checking + +FATDEPPATH = --dep-path fat +endif diff --git a/nuttx/fs/fat/fs_configfat.c b/nuttx/fs/fat/fs_configfat.c new file mode 100644 index 0000000000..3a55a5215c --- /dev/null +++ b/nuttx/fs/fat/fs_configfat.c @@ -0,0 +1,963 @@ +/**************************************************************************** + * fs/fat/fs_configfat.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "fs_internal.h" +#include "fs_fat32.h" +#include "fs_mkfatfs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NDX12 0 +#define NDX16 1 +#define NDX32 2 + +#define fatconfig12 fatconfig[NDX12] +#define fatconfig16 fatconfig[NDX16] +#define fatconfig32 fatconfig[NDX32] + +/* JMP rel8 and NOP opcodes */ + +#define OPCODE_JMP_REL8 0xeb +#define OPCODE_NOP 0x90 + +#define BOOTCODE_MSGOFFSET 29 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct fat_config_s +{ + uint32_t fc_navailsects; /* The number of available sectors */ + uint32_t fc_nfatsects; /* The number of sectors in one FAT */ + uint32_t fc_nclusters; /* The number of clusters in the filesystem */ + uint32_t fc_rsvdseccount; /* The number of reserved sectors */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Reverse engineered, generic boot message logic for non-bootable disk. + * Message begins at offset 29; Sector relative offset must be poked into + * offset 3. + */ + +static uint8_t g_bootcodeblob[] = +{ + 0x0e, 0x1f, 0xbe, 0x00, 0x7c, 0xac, 0x22, 0xc0, 0x74, 0x0b, 0x56, + 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0x5e, 0xeb, 0xf0, 0x32, + 0xe4, 0xcd, 0x16, 0xcd, 0x19, 0xeb, 0xfe, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x62, + 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x64, 0x69, 0x73, + 0x6b, 0x2e, 0x20, 0x20, 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, + 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6f, + 0x6f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x70, + 0x70, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x70, 0x72, 0x65, + 0x73, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, + 0x74, 0x6f, 0x20, 0x74, 0x72, 0x79, 0x20, 0x61, 0x67, 0x61, 0x69, + 0x6e, 0x20, 0x2e, 0x2e, 0x2e, 0x0d, 0x0a, 0x00 +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mkfatfs_nfatsect12 + * + * Description: + * Calculate the number of sectors need for one fat in a FAT12 file system. + * + * Input: + * fmt - Caller specified format parameters + * var - Other format parameters that are not caller specifiable. (Most + * set by mkfatfs_configfatfs()). + * navailsects - The number of sectors available for both FAT and data. + * This is a precalculated value equal to the total number of sectors + * minus the number of root directory sectors and minus the number of + * reserved sectors. + * + * Return: + * 0: That calculation would have overflowed + * >0: The size of one FAT in sectors. + * + ****************************************************************************/ +static inline uint32_t +mkfatfs_nfatsect12(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var, + uint32_t navailsects) +{ +#ifdef CONFIG_HAVE_LONG_LONG + uint64_t denom; + uint64_t numer; +#else + uint32_t denom; + uint32_t numer; +#endif + + /* For FAT12, the cluster number is held in a 12-bit number or 1.5 bytes per + * cluster reference. So each FAT sector will hold sectorsize/1.5 cluster + * references (except for the first sector of each FAT which has two reserved + * 12-bit values). And the total number of FAT sectors needed is: + * + * nfatsects = (1.5 * (ndataclust + 2) / sectorsize) + * + * where: + * + * ndataclust = ndatasect / clustsize + * nvailsects = nfatsects + ndatasect + * + * The solution to this set of linear equations is: + * + * nfatsects = (3 * navailsects + 6 * clustersize) / + * (3 * nfats + 2 * sectorsize * clustersize) + * + * The numerator would overflow uint32_t if: + * + * 3 * navailsects + 6 * clustersize > 0xffffffff + * + * Or + * + * navailsects > 0x55555555 - 2 * clustersize + */ + +#ifndef CONFIG_HAVE_LONG_LONG + if (navailsects <= (0x55555555 - (1 << (fmt->ff_clustshift + 1)))) + { +#endif + + denom = (fmt->ff_nfats << 1) + fmt->ff_nfats + + (var->fv_sectorsize << (fmt->ff_clustshift + 1)); + numer = (navailsects << 1) + navailsects + + (1 << (fmt->ff_clustshift + 2)) + (1 << (fmt->ff_clustshift + 1)); + return (uint32_t)((numer + denom - 1) / denom); + +#ifndef CONFIG_HAVE_LONG_LONG + } + else + { + return 0; + } +#endif +} + +/**************************************************************************** + * Name: mkfatfs_nfatsect16 + * + * Description: + * Calculate the number of sectors need for one fat in a FAT16 file system. + * + * Input: + * fmt - Caller specified format parameters + * var - Other format parameters that are not caller specifiable. (Most + * set by mkfatfs_configfatfs()). + * navailsects - The number of sectors available for both FAT and data. + * This is a precalculated value equal to the total number of sectors + * minus the number of root directory sectors and minus the number of + * reserved sectors. + * + * Return: + * The size of one FAT in sectors. + * + ****************************************************************************/ +static inline uint32_t +mkfatfs_nfatsect16(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var, + uint32_t navailsects) +{ +#ifdef CONFIG_HAVE_LONG_LONG + uint64_t denom; + uint64_t numer; +#else + uint32_t denom; + uint32_t numer; +#endif + + /* For FAT16, the cluster number is held in a 16-bit number or 2 bytes per + * cluster reference. So each FAT sector will hold sectorsize/2 cluster + * references (except for the first sector of each FAT which has two reserved + * 16-bit values). And the total number of FAT sectors needed is: + * + * nfatsects = (2 * (ndataclust + 2) / sectorsize) + * + * where: + * + * ndataclust = ndatasect / clustsize + * nvailsects = nfatsects + ndatasect + * + * The solution to this set of linear equations is: + * + * nfatsects = (navailsects + 2 * clustersize) / + * (nfats + sectorsize * clustersize / 2) + * + * Overflow in the calculation of the numerator could occur if: + * + * navailsects > 0xffffffff - 2 * clustersize + */ + + if (fmt->ff_clustshift == 0) + { + denom = fmt->ff_nfats + (var->fv_sectorsize >> 1); + numer = navailsects + 2; + } + else + { + denom = fmt->ff_nfats + (var->fv_sectorsize << (fmt->ff_clustshift - 1)); + numer = navailsects + (1 << (fmt->ff_clustshift + 1)); + } + return (uint32_t)((numer + denom - 1) / denom); +} + +/**************************************************************************** + * Name: mkfatfs_nfatsect32 + * + * Description: + * Calculate the number of sectors need for one fat in a FAT32 file system. + * + * Input: + * fmt - Caller specified format parameters + * var - Other format parameters that are not caller specifiable. (Most + * set by mkfatfs_configfatfs()). + * navailsects - The number of sectors available for both FAT and data. + * This is a precalculated value equal to the total number of sectors + * minus the number of root directory sectors and minus the number of + * reserved sectors. + * + * Return: + * The size of one FAT in sectors. + * + ****************************************************************************/ +static inline uint32_t +mkfatfs_nfatsect32(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var, + uint32_t navailsects) +{ +#ifdef CONFIG_HAVE_LONG_LONG + uint64_t denom; + uint64_t numer; +#else + uint32_t denom; + uint32_t numer; +#endif + + /* For FAT32, the cluster number is held in a 32-bit number or 4 bytes per + * cluster reference. So each FAT sector will hold sectorsize/4 cluster + * references (except for the first sector of each FAT which has three reserved + * 32-bit values). And the total number of FAT sectors needed is: + * + * nfatsects = (4 * (ndataclust + 3) / sectorsize) + * + * where: + * + * ndataclust = ndatasect / clustsize + * nvailsects = nfatsects + ndatasect + * + * The solution to this set of linear equations is: + * + * nfatsects = (navailsects + 3 * clustersize) / + * (nfats + sectorsize * clustersize / 4) + * + * Overflow in the 32-bit calculation of the numerator could occur if: + * + * navailsects > 0xffffffff - 3 * clustersize + */ + + if (fmt->ff_clustshift == 0) + { + denom = fmt->ff_nfats + (var->fv_sectorsize >> 2); + numer = navailsects + 3; + } + else if (fmt->ff_clustshift == 1) + { + denom = fmt->ff_nfats + (var->fv_sectorsize >> 1); + numer = navailsects + 6; + } + else + { + denom = fmt->ff_nfats + (var->fv_sectorsize << (fmt->ff_clustshift - 2)); + numer = navailsects + (1 << (fmt->ff_clustshift + 1)) + (1 << fmt->ff_clustshift); + } + return (uint32_t)((numer + denom - 1) / denom); +} + +/**************************************************************************** + * Name: mkfatfs_clustersearchlimits + * + * Description: + * Pick the starting and ending cluster size to use in the search for the + * the optimal cluster size. + * + * Input: + * fmt - Caller specified format parameters + * var - Other format parameters that are not caller specifiable. (Most + * set by mkfatfs_configfatfs()). + * + * Return: + * Starting cluster size is set in fmt->ff_clustshift; Final cluster + * size is the returned value. + * + ****************************************************************************/ +static inline uint8_t +mkfatfs_clustersearchlimits(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var) +{ + uint8_t mxclustshift; + + /* Did the caller already pick the cluster size? If not, the clustshift value + * will be 0xff + */ + + if (fmt->ff_clustshift == 0xff) + { + /* Pick a starting size based on the number of sectors on the device */ + + if (fmt->ff_nsectors < 2048) + { + /* 2k sectors, start wit 1 sector/cluster. */ + fmt->ff_clustshift = 0; + } + else if (fmt->ff_nsectors < 4096) + { + /* 4k sectors, start with 2 sector/cluster. */ + fmt->ff_clustshift = 1; + } + else if (fmt->ff_nsectors < 8192) + { + /* 8k sectors, start with 4 sector/cluster. */ + fmt->ff_clustshift = 2; + } + else if (fmt->ff_nsectors < 16384) + { + /* 16k sectors, start with 8 sector/cluster. */ + fmt->ff_clustshift = 3; + } + else if (fmt->ff_nsectors < 32768) + { + /* 32k sectors, start with 16 sector/cluster. */ + fmt->ff_clustshift = 4; + } + else + { + /* Otherwise, 32 sector/cluster. */ + fmt->ff_clustshift = 5; + } + + /* Wherever the search starts, it will end with the maximum of + * 128 sectors per cluster + */ + + mxclustshift = 7; + } + else + { + /* The caller has selected a cluster size. There will be no search! + * Just set the maximum to the caller specificed value. + */ + + mxclustshift = fmt->ff_clustshift; + } + return mxclustshift; +} + +/**************************************************************************** + * Name: mkfatfs_try12 + * + * Description: + * Try to define a FAT12 filesystem on the device using the candidate + * sectors per cluster + * + * Input: + * fmt - Caller specified format parameters + * var - Other format parameters that are not caller specifiable. (Most + * set by mkfatfs_configfatfs()). + * fatconfig - FAT12-specific configuration + * + * Return: + * Zero on success configuration of a FAT12 file system; negated errno + * on failure + * + ****************************************************************************/ +static inline int +mkfatfs_tryfat12(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var, + FAR struct fat_config_s *config) +{ + uint32_t maxnclusters; + + /* Calculate the number sectors in one FAT required to access all of the + * available sectors. + */ + + config->fc_nfatsects = mkfatfs_nfatsect12(fmt, var, config->fc_navailsects); + if (config->fc_nfatsects > 0) + { + /* Calculate the number of clusters available given the number of available + * sectors and the number of those that will be used for FAT: + */ + + config->fc_nclusters = + (config->fc_navailsects - + fmt->ff_nfats * config->fc_nfatsects) >> fmt->ff_clustshift; + + /* Calculate the maximum number of clusters that could be supported by a + * FAT of this size. + * + * maxnclusters = nfatsects * sectorsize / 1.5 - 2 + */ + + maxnclusters = (config->fc_nfatsects >> (var->fv_sectshift + 1)) / 3; + if (maxnclusters > FAT_MAXCLUST12) + { + maxnclusters = FAT_MAXCLUST12; + } + fvdbg("nfatsects=%u nclusters=%u (max=%u)\n", + config->fc_nfatsects, config->fc_nclusters, maxnclusters); + + /* Check if this number of clusters would overflow the maximum for + * FAT12 (remembering that two FAT cluster slots are reserved). + */ + + if (config->fc_nclusters > maxnclusters - 2) + { + fvdbg("Too many clusters for FAT12\n"); + return -ENFILE; + } + } + return 0; +} + +/**************************************************************************** + * Name: mkfatfs_try16 + * + * Description: + * Try to define a FAT16 filesystem on the device using the candidate + * sectors per cluster + * + * Input: + * fmt - Caller specified format parameters + * var - Other format parameters that are not caller specifiable. (Most + * set by mkfatfs_configfatfs()). + * fatconfig - FAT16-specific configuration + * + * Return: + * Zero on success configuration of a FAT16 file system; negated errno + * on failure + * + ****************************************************************************/ +static inline int +mkfatfs_tryfat16(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var, + FAR struct fat_config_s *config) +{ + uint32_t maxnclusters; + + /* Calculate the number sectors in one FAT required to access all of the + * available sectors. + */ + + config->fc_nfatsects = mkfatfs_nfatsect16(fmt, var, config->fc_navailsects); + if (config->fc_nfatsects > 0) + { + /* Calculate the number of clusters available given the number of available + * sectors and the number of those that will be used for FAT: + */ + + config->fc_nclusters = + (config->fc_navailsects - + fmt->ff_nfats * config->fc_nfatsects) >> fmt->ff_clustshift; + + /* Calculate the maximum number of clusters that could be supported by a + * FAT of this size. + * + * maxnclusters = nfatsects * sectorsize / 2 - 2 + */ + + maxnclusters = config->fc_nfatsects << (var->fv_sectorsize - 1); + if (maxnclusters > FAT_MAXCLUST16) + { + maxnclusters = FAT_MAXCLUST16; + } + fvdbg("nfatsects=%u nclusters=%u (min=%u max=%u)\n", + config->fc_nfatsects, config->fc_nclusters, FAT_MINCLUST16, maxnclusters); + + /* Check if this number of clusters would overflow the maximum for + * FAT16 (remembering that two FAT cluster slots are reserved). + * Check the lower limit as well. The FAT12 is distinguished from FAT16 + * by comparing the number of clusters on the device agains a known + * threshold. If a small FAT16 file system were created, then it would + * be confused as a FAT12 at mount time. + */ + + if ((config->fc_nclusters > maxnclusters - 2) || + (config->fc_nclusters < FAT_MINCLUST16)) + { + fvdbg("Too few or too many clusters for FAT16\n"); + return -ENFILE; + } + } + return 0; +} + +/**************************************************************************** + * Name: mkfatfs_try32 + * + * Description: + * Try to define a FAT32 filesystem on the device using the candidate + * sectors per cluster + * + * Input: + * fmt - Caller specified format parameters + * var - Other format parameters that are not caller specifiable. (Most + * set by mkfatfs_configfatfs()). + * fatconfig - FAT32-specific configuration + * + * Return: + * Zero on success configuration of a FAT32 file system; negated errno + * on failure + * + ****************************************************************************/ +static inline int +mkfatfs_tryfat32(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var, + FAR struct fat_config_s *config) +{ + uint32_t maxnclusters; + + /* Calculate the number sectors in one FAT required to access all of the + * available sectors. + */ + + config->fc_nfatsects = mkfatfs_nfatsect32(fmt, var, config->fc_navailsects); + if (config->fc_nfatsects > 0) + { + /* Calculate the number of clusters available given the number of available + * sectors and the number of those that will be used for FAT: + */ + + config->fc_nclusters = + (config->fc_navailsects - + fmt->ff_nfats * config->fc_nfatsects) >> fmt->ff_clustshift; + + /* Calculate the maximum number of clusters that could be supported by a + * FAT of this size. + * + * maxnclusters = nfatsects * sectorsize / 4 - 2 + */ + + maxnclusters = (config->fc_nfatsects >> (var->fv_sectshift - 2)); + if (maxnclusters > FAT_MAXCLUST32) + { + maxnclusters = FAT_MAXCLUST32; + } + fvdbg("nfatsects=%u nclusters=%u (max=%u)\n", + config->fc_nfatsects, config->fc_nclusters, maxnclusters); + + /* Check if this number of clusters would overflow the maximum for + * FAT32 (remembering that two FAT cluster slots are reserved). + */ + + if ((config->fc_nclusters > maxnclusters - 3) || + (config->fc_nclusters < FAT_MINCLUST32 && fmt->ff_fattype != 32)) + { + fvdbg("Too few or too many clusters for FAT32\n"); + return -ENFILE; + } + } + return 0; +} + +/**************************************************************************** + * Name: mkfatfs_selectfat + * + * Description: + * The cluster search has succeeded, select the specified FAT FS + * + * Input: + * fattype - The FAT size selected + * fmt - Caller specified format parameters + * var - Format parameters that are not caller specifiable. + * + * Return: + * None + * + ****************************************************************************/ + +static inline void +mkfatfs_selectfat(int fattype, FAR struct fat_format_s *fmt, + FAR struct fat_var_s *var, FAR struct fat_config_s *config) +{ + /* Return the appropriate information about the selected file system. */ + + fdbg("Selected FAT%d\n", fattype); + var->fv_fattype = fattype; + var->fv_nclusters = config->fc_nclusters; + var->fv_nfatsects = config->fc_nfatsects; + fmt->ff_rsvdseccount = config->fc_rsvdseccount; +} + +/**************************************************************************** + * Name: mkfatfs_clustersearch + * + * Description: + * Search to find the smallest (reasonable) cluster size for the FAT file + * system. + * + * Input: + * fmt - Caller specified format parameters + * var - Other format parameters that are not caller specifiable. (Most + * set by mkfatfs_configfatfs()). + * + * Return: + * Zero on success; negated errno on failure + * + ****************************************************************************/ + +static inline int +mkfatfs_clustersearch(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var) +{ + struct fat_config_s fatconfig[3]; + uint8_t mxclustshift; + + memset(fatconfig, 0, 3*sizeof(struct fat_config_s)); + + /* Select the reserved sector count for each FAT size */ + + if (fmt->ff_rsvdseccount) + { + fatconfig12.fc_rsvdseccount = fmt->ff_rsvdseccount; + fatconfig16.fc_rsvdseccount = fmt->ff_rsvdseccount; + + if (fmt->ff_rsvdseccount < 2) + { + fvdbg("At least 2 reserved sectors needed by FAT32\n"); + fatconfig32.fc_rsvdseccount = 2; + } + else + { + fatconfig32.fc_rsvdseccount = fmt->ff_rsvdseccount; + } + } + else + { + fatconfig12.fc_rsvdseccount = 1; + fatconfig16.fc_rsvdseccount = 1; + fatconfig32.fc_rsvdseccount = 32; + } + + /* Determine the number of sectors needed by the root directory. + * This is a constant value, independent of cluster size for FAT12/16 + */ + + if (var->fv_fattype != 32) + { + /* Calculate the number of sectors reqired to contain the selected + * number of root directory entries. This value is save in the var + * structure but will be overwritten if FAT32 is selected. FAT32 uses + * a cluster chain for the root directory, so the concept of the number + * of root directory entries does not apply to FAT32 + */ + + var->fv_nrootdirsects = + ((fmt->ff_rootdirentries << DIR_SHIFT) + var->fv_sectorsize - 1) >> var->fv_sectshift; + + /* The number of data sectors available (includes the fat itself) + * This value is a constant for FAT12/16, but not FAT32 because the + * size of the root directory cluster changes + */ + + fatconfig12.fc_navailsects = + fatconfig16.fc_navailsects = + fmt->ff_nsectors - var->fv_nrootdirsects - fatconfig12.fc_rsvdseccount; + } + + /* Select an initial and terminal clustersize to use in the search (if these + * values were not provided by the caller) + */ + + mxclustshift = mkfatfs_clustersearchlimits(fmt, var); + + do + { + fvdbg("Configuring with %d sectors/cluster...\n", 1 << fmt->ff_clustshift); + + /* Check if FAT12 has not been excluded */ + + if (var->fv_fattype == 0 || var->fv_fattype == 12) + { + /* Try to configure a FAT12 filesystem with this cluster size */ + + if (mkfatfs_tryfat12(fmt, var, &fatconfig12) != 0) + { + { + fvdbg("Cannot format FAT12 at %u sectors/cluster\n", 1 << fmt->ff_clustshift); + fatconfig12.fc_nfatsects = 0; + fatconfig12.fc_nclusters = 0; + } + } + } + + /* Check if FAT16 has not been excluded */ + + if (var->fv_fattype == 0 || var->fv_fattype == 16) + { + /* Try to configure a FAT16 filesystem with this cluster size */ + + if (mkfatfs_tryfat16(fmt, var, &fatconfig16) != 0) + { + { + fvdbg("Cannot format FAT16 at %u sectors/cluster\n", 1 << fmt->ff_clustshift); + fatconfig16.fc_nfatsects = 0; + fatconfig16.fc_nclusters = 0; + } + } + } + + /* If either FAT12 or 16 was configured at this sector/cluster setting, + * then finish the configuration and break out now + */ + + if (fatconfig12.fc_nclusters || fatconfig16.fc_nclusters) + { + if ((!var->fv_fattype && fatconfig16.fc_nclusters > fatconfig12.fc_nclusters) || + (var ->fv_fattype == 16)) + { + /* The caller has selected FAT16 -OR- no FAT type has been selected, but + * the FAT16 selection has more clusters. Select FAT16. + */ + + mkfatfs_selectfat(16, fmt, var, &fatconfig16); + } + else + { + /* The caller has selected FAT12 -OR- no FAT type has been selected, but + * the FAT12 selected has more clusters. Selected FAT12 + */ + + mkfatfs_selectfat(12, fmt, var, &fatconfig12); + } + return OK; + } + + /* Check if FAT32 has not been excluded */ + + if (var->fv_fattype == 0 || var->fv_fattype == 32) + { + /* The number of data sectors available (includes the fat itself) + * This value is a constant with respect to cluster sizefor FAT12/16, but not FAT32 + * because the size of the root directory cluster changes with cluster size. + */ + + fatconfig32.fc_navailsects = fmt->ff_nsectors - (1 << fmt->ff_clustshift) - fatconfig32.fc_rsvdseccount; + + /* Try to configure a FAT32 filesystem with this cluster size */ + + if (mkfatfs_tryfat32(fmt, var, &fatconfig32) != 0) + { + { + fvdbg("Cannot format FAT32 at %u sectors/cluster\n", 1 << fmt->ff_clustshift); + fatconfig32.fc_nfatsects = 0; + fatconfig32.fc_nclusters = 0; + } + } + else + { + /* Select FAT32 if we have not already done so */ + + mkfatfs_selectfat(32, fmt, var, &fatconfig32); + return OK; + } + } + + /* Otherwise, bump up the sectors/cluster for the next time around the loop. */ + + fmt->ff_clustshift++; + } + while (fmt->ff_clustshift <= mxclustshift); + return -ENFILE; +} + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mkfatfs_configfatfs + * + * Description: + * Based on the geometry of the block device and upon the caller-selected + * values, configure the FAT filesystem for the device. + * + * Input: + * fmt - Caller specified format parameters + * var - Holds disk geomtry data. Also, the location to return FAT + * configuration data + * + * Return: + * Zero on success; negated errno on failure + * + ****************************************************************************/ +int mkfatfs_configfatfs(FAR struct fat_format_s *fmt, + FAR struct fat_var_s *var) +{ + int ret; + + /* Select the number of root directory entries (FAT12/16 only). If FAT32 is selected, + * this value will be cleared later + */ + + if (!fmt->ff_rootdirentries) + { + /* The caller did not specify the number of root directory entries; use a default of 512. */ + + fmt->ff_rootdirentries = 512; + } + + /* Search to determine the smallest (reasonable) cluster size. A by-product + * of this search will be the selection of the FAT size (12/16/32) if the + * caller has not specified the FAT size + */ + + ret = mkfatfs_clustersearch(fmt, var); + if (ret < 0) + { + fdbg("Failed to set cluster size\n"); + return ret; + } + + /* Perform FAT specific initialization */ + + /* Set up boot jump assuming FAT 12/16 offset to bootcode */ + + var->fv_jump[0] = OPCODE_JMP_REL8; + var->fv_jump[2] = OPCODE_NOP; + var->fv_bootcode = g_bootcodeblob; + var->fv_bootcodesize = sizeof(g_bootcodeblob); + + if (var->fv_fattype != 32) + { + /* Set up additional, non-zero FAT12/16 fields */ + + /* Patch in the correct offset to the boot code */ + + var->fv_jump[1] = BS16_BOOTCODE - 2; + g_bootcodeblob[3] = BS16_BOOTCODE + BOOTCODE_MSGOFFSET; + } + else + { + /* Patch in the correct offset to the boot code */ + + var->fv_jump[1] = BS32_BOOTCODE - 2; + g_bootcodeblob[3] = BS32_BOOTCODE + BOOTCODE_MSGOFFSET; + + /* The root directory is a cluster chain... its is initialize size is one cluster */ + + var->fv_nrootdirsects = 1 << fmt->ff_clustshift; + + /* The number of reported root directory entries should should be zero for + * FAT32 because the root directory is a cluster chain. + */ + + fmt->ff_rootdirentries = 0; + + /* Verify the caller's backupboot selection */ + + if (fmt->ff_backupboot <= 1 || fmt->ff_backupboot >= fmt->ff_rsvdseccount) + { + fdbg("Invalid backup boot sector: %d\n", fmt->ff_backupboot); + fmt->ff_backupboot = 0; + } + + /* Check if the caller has selected a location for the backup boot record */ + + if (!fmt->ff_backupboot) + { + /* There must be reserved sectors in order to have a backup boot sector */ + + if (fmt->ff_rsvdseccount > 0 && fmt->ff_rsvdseccount >= 2) + { + /* Sector 0 is the MBR; 1... ff_rsvdseccount are reserved. Try the next + * the last reserved sector. + */ + + fmt->ff_backupboot = fmt->ff_rsvdseccount - 1; + if (fmt->ff_backupboot > 6) + { + /* Limit the location to within the first 7 */ + + fmt->ff_backupboot = 6; + } + } + } + } + + /* Report the selected fat type */ + + fmt->ff_fattype = var->fv_fattype; + + /* Describe the configured filesystem */ + +#ifdef CONFIG_DEBUG + fdbg("Sector size: %d bytes\n", var->fv_sectorsize); + fdbg("Number of sectors: %d sectors\n", fmt->ff_nsectors); + fdbg("FAT size: %d bits\n", var->fv_fattype); + fdbg("Number FATs: %d\n", fmt->ff_nfats); + fdbg("Sectors per cluster: %d sectors\n", 1 << fmt->ff_clustshift); + fdbg("FS size: %d sectors\n", var->fv_nfatsects); + fdbg(" %d clusters\n", var->fv_nclusters); + if (var->fv_fattype != 32) + { + fdbg("Root directory slots: %d\n", fmt->ff_rootdirentries); + } + fdbg("Volume ID: %08x\n", fmt->ff_volumeid); + fdbg("Volume Label: \"%c%c%c%c%c%c%c%c%c%c%c\"\n", + fmt->ff_volumelabel[0], fmt->ff_volumelabel[1], fmt->ff_volumelabel[2], + fmt->ff_volumelabel[3], fmt->ff_volumelabel[4], fmt->ff_volumelabel[5], + fmt->ff_volumelabel[6], fmt->ff_volumelabel[7], fmt->ff_volumelabel[8], + fmt->ff_volumelabel[9], fmt->ff_volumelabel[10]); +#endif + return OK; +} + diff --git a/nuttx/fs/fat/fs_fat32.c b/nuttx/fs/fat/fs_fat32.c new file mode 100644 index 0000000000..f0845070ba --- /dev/null +++ b/nuttx/fs/fat/fs_fat32.c @@ -0,0 +1,2281 @@ +/**************************************************************************** + * fs/fat/fs_fat32.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * Microsoft FAT documentation + * Some good ideas were leveraged from the FAT implementation: + * 'Copyright (C) 2007, ChaN, all right reserved.' + * which has an unrestricted license. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "fs_internal.h" +#include "fs_fat32.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int fat_open(FAR struct file *filep, const char *relpath, + int oflags, mode_t mode); +static int fat_close(FAR struct file *filep); +static ssize_t fat_read(FAR struct file *filep, char *buffer, size_t buflen); +static ssize_t fat_write(FAR struct file *filep, const char *buffer, + size_t buflen); +static off_t fat_seek(FAR struct file *filep, off_t offset, int whence); +static int fat_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +static int fat_sync(FAR struct file *filep); + +static int fat_opendir(struct inode *mountpt, const char *relpath, + struct fs_dirent_s *dir); +static int fat_readdir(struct inode *mountpt, struct fs_dirent_s *dir); +static int fat_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir); + +static int fat_bind(FAR struct inode *blkdriver, const void *data, + void **handle); +static int fat_unbind(void *handle, FAR struct inode **blkdriver); +static int fat_statfs(struct inode *mountpt, struct statfs *buf); + +static int fat_unlink(struct inode *mountpt, const char *relpath); +static int fat_mkdir(struct inode *mountpt, const char *relpath, + mode_t mode); +static int fat_rmdir(struct inode *mountpt, const char *relpath); +static int fat_rename(struct inode *mountpt, const char *oldrelpath, + const char *newrelpath); +static int fat_stat(struct inode *mountpt, const char *relpath, struct stat *buf); + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* See fs_mount.c -- this structure is explicitly externed there. + * We use the old-fashioned kind of initializers so that this will compile + * with any compiler. + */ + +const struct mountpt_operations fat_operations = +{ + fat_open, + fat_close, + fat_read, + fat_write, + fat_seek, + fat_ioctl, + fat_sync, + + fat_opendir, + NULL, + fat_readdir, + fat_rewinddir, + + fat_bind, + fat_unbind, + fat_statfs, + + fat_unlink, + fat_mkdir, + fat_rmdir, + fat_rename, + fat_stat +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fat_open + ****************************************************************************/ + +static int fat_open(FAR struct file *filep, const char *relpath, + int oflags, mode_t mode) +{ + struct fat_dirinfo_s dirinfo; + struct inode *inode; + struct fat_mountpt_s *fs; + struct fat_file_s *ff; + uint8_t *direntry; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL); + + /* Get the mountpoint inode reference from the file structure and the + * mountpoint private data from the inode structure + */ + + inode = filep->f_inode; + fs = inode->i_private; + + DEBUGASSERT(fs != NULL); + + /* Check if the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Initialize the directory info structure */ + + memset(&dirinfo, 0, sizeof(struct fat_dirinfo_s)); + + /* Locate the directory entry for this path */ + + ret = fat_finddirentry(fs, &dirinfo, relpath); + + /* Three possibililities: (1) a node exists for the relpath and + * dirinfo describes the directory entry of the entity, (2) the + * node does not exist, or (3) some error occurred. + */ + + if (ret == OK) + { + bool readonly; + + /* The name exists -- but is it a file or a directory? */ + + direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset]; + if (dirinfo.fd_root || + (DIR_GETATTRIBUTES(direntry) & FATATTR_DIRECTORY)) + { + /* It is a directory */ + + ret = -EISDIR; + goto errout_with_semaphore; + } + + /* It would be an error if we are asked to create it exclusively */ + + if ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) + { + /* Already exists -- can't create it exclusively */ + + ret = -EEXIST; + goto errout_with_semaphore; + } + +#ifdef CONFIG_FILE_MODE +# warning "Missing check for privileges based on inode->i_mode" +#endif + + /* Check if the caller has sufficient privileges to open the file */ + + readonly = ((DIR_GETATTRIBUTES(direntry) & FATATTR_READONLY) != 0); + if (((oflags & O_WRONLY) != 0) && readonly) + { + ret = -EACCES; + goto errout_with_semaphore; + } + + /* If O_TRUNC is specified and the file is opened for writing, + * then truncate the file. This operation requires that the file is + * writable, but we have already checked that. O_TRUNC without write + * access is ignored. + */ + + if ((oflags & (O_TRUNC|O_WRONLY)) == (O_TRUNC|O_WRONLY)) + { + /* Truncate the file to zero length */ + + ret = fat_dirtruncate(fs, &dirinfo); + if (ret < 0) + { + goto errout_with_semaphore; + } + } + + /* fall through to finish the file open operations */ + } + else if (ret == -ENOENT) + { + /* The file does not exist. Were we asked to create it? */ + + if ((oflags & O_CREAT) == 0) + { + /* No.. then we fail with -ENOENT */ + + ret = -ENOENT; + goto errout_with_semaphore; + } + + /* Yes.. create the file */ + + ret = fat_dircreate(fs, &dirinfo); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Fall through to finish the file open operation */ + + direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset]; + } + else + { + /* An error occurred while checking for file existence -- + * such as if an invalid path were provided. + */ + + goto errout_with_semaphore; + } + + /* Create an instance of the file private date to describe the opened + * file. + */ + + ff = (struct fat_file_s *)kzalloc(sizeof(struct fat_file_s)); + if (!ff) + { + ret = -ENOMEM; + goto errout_with_semaphore; + } + + /* Create a file buffer to support partial sector accesses */ + + ff->ff_buffer = (uint8_t*)kmalloc(fs->fs_hwsectorsize); + if (!ff->ff_buffer) + { + ret = -ENOMEM; + goto errout_with_struct; + } + + /* Initialize the file private data (only need to initialize non-zero elements) */ + + ff->ff_open = true; + ff->ff_oflags = oflags; + + /* Save information that can be used later to recover the directory entry */ + + ff->ff_dirsector = fs->fs_currentsector; + ff->ff_dirindex = dirinfo.dir.fd_index; + + /* File cluster/size info */ + + ff->ff_startcluster = + ((uint32_t)DIR_GETFSTCLUSTHI(direntry) << 16) | + DIR_GETFSTCLUSTLO(direntry); + + ff->ff_currentcluster = ff->ff_startcluster; + ff->ff_sectorsincluster = fs->fs_fatsecperclus; + ff->ff_size = DIR_GETFILESIZE(direntry); + + /* Attach the private date to the struct file instance */ + + filep->f_priv = ff; + + /* Then insert the new instance into the mountpoint structure. + * It needs to be there (1) to handle error conditions that effect + * all files, and (2) to inform the umount logic that we are busy + * (but a simple reference count could have done that). + */ + + ff->ff_next = fs->fs_head; + fs->fs_head = ff->ff_next; + + fat_semgive(fs); + + /* In write/append mode, we need to set the file pointer to the end of the file */ + + if ((oflags & (O_APPEND|O_WRONLY)) == (O_APPEND|O_WRONLY)) + { + off_t offset = fat_seek(filep, ff->ff_size, SEEK_SET); + if (offset < 0) + { + kfree(ff); + return (int)offset; + } + } + + return OK; + + /* Error exits -- goto's are nasty things, but they sure can make error + * handling a lot simpler. + */ + +errout_with_struct: + kfree(ff); + +errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_close + ****************************************************************************/ + +static int fat_close(FAR struct file *filep) +{ + struct inode *inode; + struct fat_file_s *ff; + int ret = OK; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + ff = filep->f_priv; + inode = filep->f_inode; + + /* Do not check if the mount is healthy. We must support closing of + * the file even when there is healthy mount. + */ + + /* Synchronize the file buffers and disk content; update times */ + + ret = fat_sync(filep); + + /* Then deallocate the memory structures created when the open method + * was called. + * + * Free the sector buffer that was used to manage partial sector accesses. + */ + + if (ff->ff_buffer) + { + kfree(ff->ff_buffer); + } + + /* Then free the file structure itself. */ + + kfree(ff); + filep->f_priv = NULL; + return ret; +} + +/**************************************************************************** + * Name: fat_read + ****************************************************************************/ + +static ssize_t fat_read(FAR struct file *filep, char *buffer, size_t buflen) +{ + struct inode *inode; + struct fat_mountpt_s *fs; + struct fat_file_s *ff; + unsigned int bytesread; + unsigned int readsize; + unsigned int nsectors; + size_t bytesleft; + int32_t cluster; + uint8_t *userbuffer = (uint8_t*)buffer; + int sectorindex; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + ff = filep->f_priv; + inode = filep->f_inode; + fs = inode->i_private; + + DEBUGASSERT(fs != NULL); + + /* Make sure that the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Check if the file was opened with read access */ + + if ((ff->ff_oflags & O_RDOK) == 0) + { + ret = -EACCES; + goto errout_with_semaphore; + } + + /* Get the number of bytes left in the file */ + + bytesleft = ff->ff_size - filep->f_pos; + + /* Truncate read count so that it does not exceed the number + * of bytes left in the file. + */ + + if (buflen > bytesleft) + { + buflen = bytesleft; + } + + /* Get the first sector to read from. */ + + if (!ff->ff_currentsector) + { + /* The current sector can be determined from the current cluster + * and the file offset. + */ + + ret = fat_currentsector(fs, ff, filep->f_pos); + if (ret < 0) + { + return ret; + } + } + + /* Loop until either (1) all data has been transferred, or (2) an + * error occurs. We assume we start with the current sector + * (ff_currentsector) which may be uninitialized. + */ + + readsize = 0; + sectorindex = filep->f_pos & SEC_NDXMASK(fs); + + while (buflen > 0) + { + bytesread = 0; + + /* Check if the user has provided a buffer large enough to + * hold one or more complete sectors -AND- the read is + * aligned to a sector boundary. + */ + + nsectors = buflen / fs->fs_hwsectorsize; + if (nsectors > 0 && sectorindex == 0) + { + /* Read maximum contiguous sectors directly to the user's + * buffer without using our tiny read buffer. + * + * Limit the number of sectors that we read on this time + * through the loop to the remaining contiguous sectors + * in this cluster + */ + + if (nsectors > ff->ff_sectorsincluster) + { + nsectors = ff->ff_sectorsincluster; + } + + /* We are not sure of the state of the file buffer so + * the safest thing to do is just invalidate it + */ + + (void)fat_ffcacheinvalidate(fs, ff); + + /* Read all of the sectors directly into user memory */ + + ret = fat_hwread(fs, userbuffer, ff->ff_currentsector, nsectors); + if (ret < 0) + { + goto errout_with_semaphore; + } + + ff->ff_sectorsincluster -= nsectors; + ff->ff_currentsector += nsectors; + bytesread = nsectors * fs->fs_hwsectorsize; + } + else + { + /* We are reading a partial sector. First, read the whole sector + * into the file data buffer. This is a caching buffer so if + * it is already there then all is well. + */ + + ret = fat_ffcacheread(fs, ff, ff->ff_currentsector); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Copy the partial sector into the user buffer */ + + bytesread = fs->fs_hwsectorsize - sectorindex; + if (bytesread > buflen) + { + /* We will not read to the end of the buffer */ + + bytesread = buflen; + } + else + { + /* We will read to the end of the buffer (or beyond) */ + + ff->ff_sectorsincluster--; + ff->ff_currentsector++; + } + + memcpy(userbuffer, &ff->ff_buffer[sectorindex], bytesread); + } + + /* Set up for the next sector read */ + + userbuffer += bytesread; + filep->f_pos += bytesread; + readsize += bytesread; + buflen -= bytesread; + sectorindex = filep->f_pos & SEC_NDXMASK(fs); + + /* Check if the current read stream has incremented to the next + * cluster boundary + */ + + if (ff->ff_sectorsincluster < 1) + { + /* Find the next cluster in the FAT. */ + + cluster = fat_getcluster(fs, ff->ff_currentcluster); + if (cluster < 2 || cluster >= fs->fs_nclusters) + { + ret = -EINVAL; /* Not the right error */ + goto errout_with_semaphore; + } + + /* Setup to read the first sector from the new cluster */ + + ff->ff_currentcluster = cluster; + ff->ff_currentsector = fat_cluster2sector(fs, cluster); + ff->ff_sectorsincluster = fs->fs_fatsecperclus; + } + } + + fat_semgive(fs); + return readsize; + +errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_write + ****************************************************************************/ + +static ssize_t fat_write(FAR struct file *filep, const char *buffer, + size_t buflen) +{ + struct inode *inode; + struct fat_mountpt_s *fs; + struct fat_file_s *ff; + int32_t cluster; + unsigned int byteswritten; + unsigned int writesize; + unsigned int nsectors; + uint8_t *userbuffer = (uint8_t*)buffer; + int sectorindex; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + ff = filep->f_priv; + inode = filep->f_inode; + fs = inode->i_private; + + DEBUGASSERT(fs != NULL); + + /* Make sure that the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Check if the file was opened for write access */ + + if ((ff->ff_oflags & O_WROK) == 0) + { + ret = -EACCES; + goto errout_with_semaphore; + } + + /* Check if the file size would exceed the range of off_t */ + + if (ff->ff_size + buflen < ff->ff_size) + { + ret = -EFBIG; + goto errout_with_semaphore; + } + + /* Get the first sector to write to. */ + + if (!ff->ff_currentsector) + { + /* Has the starting cluster been defined? */ + + if (ff->ff_startcluster == 0) + { + /* No.. we have to create a new cluster chain */ + + ff->ff_startcluster = fat_createchain(fs); + ff->ff_currentcluster = ff->ff_startcluster; + ff->ff_sectorsincluster = fs->fs_fatsecperclus; + } + + /* The current sector can then be determined from the currentcluster + * and the file offset. + */ + + ret = fat_currentsector(fs, ff, filep->f_pos); + if (ret < 0) + { + return ret; + } + } + + /* Loop until either (1) all data has been transferred, or (2) an + * error occurs. We assume we start with the current sector in + * cache (ff_currentsector) + */ + + byteswritten = 0; + sectorindex = filep->f_pos & SEC_NDXMASK(fs); + + while (buflen > 0) + { + /* Check if the user has provided a buffer large enough to + * hold one or more complete sectors. + */ + + nsectors = buflen / fs->fs_hwsectorsize; + if (nsectors > 0 && sectorindex == 0) + { + /* Write maximum contiguous sectors directly from the user's + * buffer without using our tiny read buffer. + * + * Limit the number of sectors that we write on this time + * through the loop to the remaining contiguous sectors + * in this cluster + */ + + if (nsectors > ff->ff_sectorsincluster) + { + nsectors = ff->ff_sectorsincluster; + } + + /* We are not sure of the state of the sector cache so the + * safest thing to do is write back any dirty, cached sector + * and invalidate the current cache content. + */ + + (void)fat_ffcacheinvalidate(fs, ff); + + /* Write all of the sectors directly from user memory */ + + ret = fat_hwwrite(fs, userbuffer, ff->ff_currentsector, nsectors); + if (ret < 0) + { + goto errout_with_semaphore; + } + + ff->ff_sectorsincluster -= nsectors; + ff->ff_currentsector += nsectors; + writesize = nsectors * fs->fs_hwsectorsize; + ff->ff_bflags |= FFBUFF_MODIFIED; + } + else + { + /* We are writing a partial sector -OR- the current sector + * has not yet been filled. + * + * We will first have to read the full sector in memory as + * part of a read-modify-write operation. NOTE we don't + * have to read the data on a rare case: When we are extending + * the file (filep->f_pos == ff->ff_size) -AND- the new data + * happens to be aligned at the beginning of the sector + * (sectorindex == 0). + */ + + if (filep->f_pos < ff->ff_size || sectorindex != 0) + { + /* Read the current sector into memory (perhaps first flushing + * the old, dirty sector to disk). + */ + + ret = fat_ffcacheread(fs, ff, ff->ff_currentsector); + if (ret < 0) + { + goto errout_with_semaphore; + } + } + else + { + /* Flush unwritten data in the sector cache. */ + + ret = fat_ffcacheflush(fs, ff); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Now mark the clean cache buffer as the current sector. */ + + ff->ff_cachesector = ff->ff_currentsector; + } + + /* Copy the partial sector from the user buffer */ + + writesize = fs->fs_hwsectorsize - sectorindex; + if (writesize > buflen) + { + /* We will not write to the end of the buffer. Set + * write size to the size of the user buffer. + */ + + writesize = buflen; + } + else + { + /* We will write to the end of the buffer (or beyond). Bump + * up the current sector number (actually the next sector number). + */ + + ff->ff_sectorsincluster--; + ff->ff_currentsector++; + } + + /* Copy the data into the cached sector and make sure that the + * cached sector is marked "dirty" + */ + + memcpy(&ff->ff_buffer[sectorindex], userbuffer, writesize); + ff->ff_bflags |= (FFBUFF_DIRTY|FFBUFF_VALID|FFBUFF_MODIFIED); + } + + /* Set up for the next write */ + + userbuffer += writesize; + filep->f_pos += writesize; + byteswritten += writesize; + buflen -= writesize; + sectorindex = filep->f_pos & SEC_NDXMASK(fs); + + /* Check if the current read stream has incremented to the next + * cluster boundary + */ + + if (ff->ff_sectorsincluster < 1) + { + /* Extend the current cluster by one (unless lseek was used to + * move the file position back from the end of the file) + */ + + cluster = fat_extendchain(fs, ff->ff_currentcluster); + + /* Verify the cluster number */ + + if (cluster < 0) + { + ret = cluster; + goto errout_with_semaphore; + } + else if (cluster < 2 || cluster >= fs->fs_nclusters) + { + ret = -ENOSPC; + goto errout_with_semaphore; + } + + /* Setup to write the first sector from the new cluster */ + + ff->ff_currentcluster = cluster; + ff->ff_sectorsincluster = fs->fs_fatsecperclus; + ff->ff_currentsector = fat_cluster2sector(fs, cluster); + } + } + + /* The transfer has completed without error. Update the file size */ + + if (filep->f_pos > ff->ff_size) + { + ff->ff_size = filep->f_pos; + } + + fat_semgive(fs); + return byteswritten; + +errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_seek + ****************************************************************************/ + +static off_t fat_seek(FAR struct file *filep, off_t offset, int whence) +{ + struct inode *inode; + struct fat_mountpt_s *fs; + struct fat_file_s *ff; + int32_t cluster; + off_t position; + unsigned int clustersize; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + ff = filep->f_priv; + inode = filep->f_inode; + fs = inode->i_private; + + DEBUGASSERT(fs != NULL); + + /* Map the offset according to the whence option */ + switch (whence) + { + case SEEK_SET: /* The offset is set to offset bytes. */ + position = offset; + break; + + case SEEK_CUR: /* The offset is set to its current location plus + * offset bytes. */ + + position = offset + filep->f_pos; + break; + + case SEEK_END: /* The offset is set to the size of the file plus + * offset bytes. */ + + position = offset + ff->ff_size; + break; + + default: + return -EINVAL; + } + + /* Make sure that the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Check if there is unwritten data in the file buffer */ + + ret = fat_ffcacheflush(fs, ff); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Attempts to set the position beyound the end of file will + * work if the file is open for write access. + */ + + if (position > ff->ff_size && (ff->ff_oflags & O_WROK) == 0) + { + /* Otherwise, the position is limited to the file size */ + + position = ff->ff_size; + } + + /* Set file position to the beginning of the file (first cluster, + * first sector in cluster) + */ + + filep->f_pos = 0; + ff->ff_sectorsincluster = fs->fs_fatsecperclus; + + /* Get the start cluster of the file */ + + cluster = ff->ff_startcluster; + + /* Create a new cluster chain if the file does not have one (and + * if we are seeking beyond zero + */ + + if (!cluster && position > 0) + { + cluster = fat_createchain(fs); + if (cluster < 0) + { + ret = cluster; + goto errout_with_semaphore; + } + ff->ff_startcluster = cluster; + } + + /* Move file position if necessary */ + + if (cluster) + { + /* If the file has a cluster chain, follow it to the + * requested position. + */ + + clustersize = fs->fs_fatsecperclus * fs->fs_hwsectorsize; + for (;;) + { + /* Skip over clusters prior to the one containing + * the requested position. + */ + + ff->ff_currentcluster = cluster; + if (position < clustersize) + { + break; + } + + /* Extend the cluster chain if write in enabled. NOTE: + * this is not consistent with the lseek description: + * "The lseek() function allows the file offset to be + * set beyond the end of the file (but this does not + * change the size of the file). If data is later written + * at this point, subsequent reads of the data in the + * gap (a "hole") return null bytes ('\0') until data + * is actually written into the gap." + */ + + if ((ff->ff_oflags & O_WROK) != 0) + { + /* Extend the cluster chain (fat_extendchain + * will follow the existing chain or add new + * clusters as needed. + */ + + cluster = fat_extendchain(fs, cluster); + } + else + { + /* Otherwise we can only follong the existing chain */ + + cluster = fat_getcluster(fs, cluster); + } + + if (cluster < 0) + { + /* An error occurred getting the cluster */ + + ret = cluster; + goto errout_with_semaphore; + } + + /* Zero means that there is no further clusters available + * in the chain. + */ + + if (cluster == 0) + { + /* At the position to the current locaiton and + * break out. + */ + + position = clustersize; + break; + } + + if (cluster >= fs->fs_nclusters) + { + ret = -ENOSPC; + goto errout_with_semaphore; + } + + /* Otherwise, update the position and continue looking */ + + filep->f_pos += clustersize; + position -= clustersize; + } + + /* We get here after we have found the sector containing + * the requested position. + * + * Save the new file position + */ + + filep->f_pos += position; + + /* Then get the current sector from the cluster and the offset + * into the cluster from the position + */ + + (void)fat_currentsector(fs, ff, filep->f_pos); + + /* Load the sector corresponding to the position */ + + if ((position & SEC_NDXMASK(fs)) != 0) + { + ret = fat_ffcacheread(fs, ff, ff->ff_currentsector); + if (ret < 0) + { + goto errout_with_semaphore; + } + } + } + + /* If we extended the size of the file, then mark the file as modified. */ + + if ((ff->ff_oflags & O_WROK) != 0 && filep->f_pos > ff->ff_size) + { + ff->ff_size = filep->f_pos; + ff->ff_bflags |= FFBUFF_MODIFIED; + } + + fat_semgive(fs); + return OK; + +errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_ioctl + ****************************************************************************/ + +static int fat_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + struct inode *inode; + struct fat_mountpt_s *fs; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + inode = filep->f_inode; + fs = inode->i_private; + + DEBUGASSERT(fs != NULL); + + /* Make sure that the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + fat_semgive(fs); + return ret; + } + + /* ioctl calls are just passed through to the contained block driver */ + + fat_semgive(fs); + return -ENOSYS; +} + +/**************************************************************************** + * Name: fat_sync + * + * Description: Synchronize the file state on disk to match internal, in- + * memory state. + * + ****************************************************************************/ + +static int fat_sync(FAR struct file *filep) +{ + struct inode *inode; + struct fat_mountpt_s *fs; + struct fat_file_s *ff; + uint32_t wrttime; + uint8_t *direntry; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + ff = filep->f_priv; + inode = filep->f_inode; + fs = inode->i_private; + + DEBUGASSERT(fs != NULL); + + /* Make sure that the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Check if the has been modified in any way */ + + if ((ff->ff_bflags & FFBUFF_MODIFIED) != 0) + { + /* Flush any unwritten data in the file buffer */ + + ret = fat_ffcacheflush(fs, ff); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Update the directory entry. First read the directory + * entry into the fs_buffer (preserving the ff_buffer) + */ + + ret = fat_fscacheread(fs, ff->ff_dirsector); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Recover a pointer to the specific directory entry + * in the sector using the saved directory index. + */ + + direntry = &fs->fs_buffer[(ff->ff_dirindex & DIRSEC_NDXMASK(fs)) * DIR_SIZE]; + + /* Set the archive bit, set the write time, and update + * anything that may have* changed in the directory + * entry: the file size, and the start cluster + */ + + direntry[DIR_ATTRIBUTES] |= FATATTR_ARCHIVE; + + DIR_PUTFILESIZE(direntry, ff->ff_size); + DIR_PUTFSTCLUSTLO(direntry, ff->ff_startcluster); + DIR_PUTFSTCLUSTHI(direntry, ff->ff_startcluster >> 16); + + wrttime = fat_systime2fattime(); + DIR_PUTWRTTIME(direntry, wrttime & 0xffff); + DIR_PUTWRTDATE(direntry, wrttime >> 16); + + /* Clear the modified bit in the flags */ + + ff->ff_bflags &= ~FFBUFF_MODIFIED; + + /* Flush these change to disk and update FSINFO (if + * appropriate. + */ + + fs->fs_dirty = true; + ret = fat_updatefsinfo(fs); + } + +errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_opendir + * + * Description: Open a directory for read access + * + ****************************************************************************/ + +static int fat_opendir(struct inode *mountpt, const char *relpath, struct fs_dirent_s *dir) +{ + struct fat_mountpt_s *fs; + struct fat_dirinfo_s dirinfo; + uint8_t *direntry; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover our private data from the inode instance */ + + fs = mountpt->i_private; + + /* Make sure that the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Find the requested directory */ + + ret = fat_finddirentry(fs, &dirinfo, relpath); + if (ret < 0) + { + goto errout_with_semaphore; + } + direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset]; + + /* Check if this is the root directory */ + + if (dirinfo.fd_root) + { + /* Handle the FAT12/16/32 root directory using the values setup by + * fat_finddirentry() above. + */ + + dir->u.fat.fd_startcluster = dirinfo.dir.fd_startcluster; + dir->u.fat.fd_currcluster = dirinfo.dir.fd_currcluster; + dir->u.fat.fd_currsector = dirinfo.dir.fd_currsector; + dir->u.fat.fd_index = dirinfo.dir.fd_index; + } + + /* This is not the root directory. Verify that it is some kind of directory */ + + else if ((DIR_GETATTRIBUTES(direntry) & FATATTR_DIRECTORY) == 0) + { + /* The entry is not a directory */ + + ret = -ENOTDIR; + goto errout_with_semaphore; + } + else + { + /* The entry is a directory (but not the root directory) */ + + dir->u.fat.fd_startcluster = + ((uint32_t)DIR_GETFSTCLUSTHI(direntry) << 16) | + DIR_GETFSTCLUSTLO(direntry); + dir->u.fat.fd_currcluster = dir->u.fat.fd_startcluster; + dir->u.fat.fd_currsector = fat_cluster2sector(fs, dir->u.fat.fd_currcluster); + dir->u.fat.fd_index = 2; + } + + fat_semgive(fs); + return OK; + +errout_with_semaphore: + fat_semgive(fs); + return ERROR; +} + +/**************************************************************************** + * Name: fat_readdir + * + * Description: Read the next directory entry + * + ****************************************************************************/ + +static int fat_readdir(struct inode *mountpt, struct fs_dirent_s *dir) +{ + struct fat_mountpt_s *fs; + unsigned int dirindex; + uint8_t *direntry; + uint8_t ch; + uint8_t attribute; + bool found; + int ret = OK; + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover our private data from the inode instance */ + + fs = mountpt->i_private; + + /* Make sure that the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Read the next directory entry */ + + dir->fd_dir.d_name[0] = '\0'; + found = false; + + while (dir->u.fat.fd_currsector && !found) + { + ret = fat_fscacheread(fs, dir->u.fat.fd_currsector); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Get a reference to the current directory entry */ + + dirindex = (dir->u.fat.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE; + direntry = &fs->fs_buffer[dirindex]; + + /* Has it reached to end of the directory */ + + ch = *direntry; + if (ch == DIR0_ALLEMPTY) + { + /* We signal the end of the directory by returning the + * special error -ENOENT + */ + + ret = -ENOENT; + goto errout_with_semaphore; + } + + /* No, is the current entry a valid entry? */ + + attribute = DIR_GETATTRIBUTES(direntry); + +#ifdef CONFIG_FAT_LFN + if (ch != DIR0_EMPTY && + ((attribute & FATATTR_VOLUMEID) == 0 || + ((ch & LDIR0_LAST) != 0 && attribute == LDDIR_LFNATTR))) +#else + if (ch != DIR0_EMPTY && (attribute & FATATTR_VOLUMEID) == 0) +#endif + { + /* Yes.. get the name from the directory entry. NOTE: For the case + * of the long file name entry, this will advance the several + * several directory entries. + */ + + ret = fat_dirname2path(fs, dir); + if (ret == OK) + { + /* The name was successfully extracted. Re-read the + * attributes: If this is long directory entry, then the + * attributes that we need will be the the final, short file + * name entry and not in the directory entry where we started + * looking for the file name. We can be assured that, on + * success, fat_dirname2path() will leave the short file name + * entry in the cache regardless of the kind of directory + * entry. We simply have to re-read it to cover the the long + * file name case. + */ + +#ifdef CONFIG_FAT_LFN + + /* Get a reference to the current, short file name directory + * entry. + */ + + dirindex = (dir->u.fat.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE; + direntry = &fs->fs_buffer[dirindex]; + + /* Then re-read the attributes from the short file name entry */ + + attribute = DIR_GETATTRIBUTES(direntry); +#endif + /* Now get the file type from the directory attributes. */ + + if ((attribute & FATATTR_DIRECTORY) == 0) + { + dir->fd_dir.d_type = DTYPE_FILE; + } + else + { + dir->fd_dir.d_type = DTYPE_DIRECTORY; + } + + /* Mark the entry found. We will set up the next directory index, + * and then exit with success. + */ + + found = true; + } + } + + /* Set up the next directory index */ + + if (fat_nextdirentry(fs, &dir->u.fat) != OK) + { + ret = -ENOENT; + goto errout_with_semaphore; + } + } + + fat_semgive(fs); + return OK; + +errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_rewindir + * + * Description: Reset directory read to the first entry + * + ****************************************************************************/ + +static int fat_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir) +{ + struct fat_mountpt_s *fs; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover our private data from the inode instance */ + + fs = mountpt->i_private; + + /* Make sure that the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Check if this is the root directory. If it is the root directory, we + * reset the fd_index to 0, starting with the initial, entry. + */ + + if (fs->fs_type != FSTYPE_FAT32 && + dir->u.fat.fd_startcluster == 0) + { + /* Handle the FAT12/16 root directory */ + + dir->u.fat.fd_currcluster = 0; + dir->u.fat.fd_currsector = fs->fs_rootbase; + dir->u.fat.fd_index = 0; + } + else if (fs->fs_type == FSTYPE_FAT32 && + dir->u.fat.fd_startcluster == fs->fs_rootbase) + { + /* Handle the FAT32 root directory */ + + dir->u.fat.fd_currcluster = dir->u.fat.fd_startcluster; + dir->u.fat.fd_currsector = fat_cluster2sector(fs, fs->fs_rootbase); + dir->u.fat.fd_index = 0; + } + + /* This is not the root directory. Here the fd_index is set to 2, skipping over + * both the "." and ".." entries. + */ + + else + { + dir->u.fat.fd_currcluster = dir->u.fat.fd_startcluster; + dir->u.fat.fd_currsector = fat_cluster2sector(fs, dir->u.fat.fd_currcluster); + dir->u.fat.fd_index = 2; + } + + fat_semgive(fs); + return OK; + +errout_with_semaphore: + fat_semgive(fs); + return ERROR; +} + +/**************************************************************************** + * Name: fat_bind + * + * Description: This implements a portion of the mount operation. This + * function allocates and initializes the mountpoint private data and + * binds the blockdriver inode to the filesystem private data. The final + * binding of the private data (containing the blockdriver) to the + * mountpoint is performed by mount(). + * + ****************************************************************************/ + +static int fat_bind(FAR struct inode *blkdriver, const void *data, + void **handle) +{ + struct fat_mountpt_s *fs; + int ret; + + /* Open the block driver */ + + if (!blkdriver || !blkdriver->u.i_bops) + { + return -ENODEV; + } + + if (blkdriver->u.i_bops->open && + blkdriver->u.i_bops->open(blkdriver) != OK) + { + return -ENODEV; + } + + /* Create an instance of the mountpt state structure */ + + fs = (struct fat_mountpt_s *)kzalloc(sizeof(struct fat_mountpt_s)); + if (!fs) + { + return -ENOMEM; + } + + /* Initialize the allocated mountpt state structure. The filesystem is + * responsible for one reference ont the blkdriver inode and does not + * have to addref() here (but does have to release in ubind(). + */ + + fs->fs_blkdriver = blkdriver; /* Save the block driver reference */ + sem_init(&fs->fs_sem, 0, 0); /* Initialize the semaphore that controls access */ + + /* Then get information about the FAT32 filesystem on the devices managed + * by this block driver. + */ + + ret = fat_mount(fs, true); + if (ret != 0) + { + sem_destroy(&fs->fs_sem); + kfree(fs); + return ret; + } + + *handle = (void*)fs; + fat_semgive(fs); + return OK; +} + +/**************************************************************************** + * Name: fat_unbind + * + * Description: This implements the filesystem portion of the umount + * operation. + * + ****************************************************************************/ + +static int fat_unbind(void *handle, FAR struct inode **blkdriver) +{ + struct fat_mountpt_s *fs = (struct fat_mountpt_s*)handle; + int ret; + + if (!fs) + { + return -EINVAL; + } + + /* Check if there are sill any files opened on the filesystem. */ + + ret = OK; /* Assume success */ + fat_semtake(fs); + if (fs->fs_head) + { + /* We cannot unmount now.. there are open files */ + + ret = -EBUSY; + } + else + { + /* Unmount ... close the block driver */ + + if (fs->fs_blkdriver) + { + struct inode *inode = fs->fs_blkdriver; + if (inode) + { + if (inode->u.i_bops && inode->u.i_bops->close) + { + (void)inode->u.i_bops->close(inode); + } + + /* We hold a reference to the block driver but should + * not but mucking with inodes in this context. So, we will just return + * our contained reference to the block driver inode and let the umount + * logic dispose of it. + */ + + if (blkdriver) + { + *blkdriver = inode; + } + } + } + + /* Release the mountpoint private data */ + + if (fs->fs_buffer) + { + kfree(fs->fs_buffer); + } + kfree(fs); + } + + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_statfs + * + * Description: Return filesystem statistics + * + ****************************************************************************/ + +static int fat_statfs(struct inode *mountpt, struct statfs *buf) +{ + struct fat_mountpt_s *fs; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + /* Check if the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Fill in the statfs info */ + + memset(buf, 0, sizeof(struct statfs)); + buf->f_type = MSDOS_SUPER_MAGIC; + + /* We will claim that the optimal transfer size is the size of a cluster in bytes */ + + buf->f_bsize = fs->fs_fatsecperclus * fs->fs_hwsectorsize; + + /* Everything else follows in units of clusters */ + + ret = fat_nfreeclusters(fs, &buf->f_bfree); /* Free blocks in the file system */ + if (ret >= 0) + { + buf->f_blocks = fs->fs_nclusters; /* Total data blocks in the file system */ + buf->f_bavail = buf->f_bfree; /* Free blocks avail to non-superuser */ + buf->f_namelen = (8+1+3); /* Maximum length of filenames */ + } + +errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_unlink + * + * Description: Remove a file + * + ****************************************************************************/ + +static int fat_unlink(struct inode *mountpt, const char *relpath) +{ + struct fat_mountpt_s *fs; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + /* Check if the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret == OK) + { + /* If the file is open, the correct behavior is to remove the file + * name, but to keep the file cluster chain in place until the last + * open reference to the file is closed. + */ + +#ifdef CONFIG_CPP_HAVE_WARNING +# warning "Need to defer deleting cluster chain if the file is open" +#endif + + /* Remove the file */ + + ret = fat_remove(fs, relpath, false); + } + + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_mkdir + * + * Description: Create a directory + * + ****************************************************************************/ + +static int fat_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) +{ + struct fat_mountpt_s *fs; + struct fat_dirinfo_s dirinfo; + uint8_t *direntry; + uint8_t *direntry2; + off_t parentsector; + off_t dirsector; + int32_t dircluster; + uint32_t parentcluster; + uint32_t crtime; + unsigned int i; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + /* Check if the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Find the directory where the new directory should be created. */ + + ret = fat_finddirentry(fs, &dirinfo, relpath); + + /* If anything exists at this location, then we fail with EEXIST */ + + if (ret == OK) + { + ret = -EEXIST; + goto errout_with_semaphore; + } + + /* What we want to see is for fat_finddirentry to fail with -ENOENT. + * This error means that no failure occurred but that nothing exists + * with this name. NOTE: The name has already been set in dirinfo + * structure. + */ + + if (ret != -ENOENT) + { + goto errout_with_semaphore; + } + + /* NOTE: There is no check that dirinfo.fd_name contains the final + * directory name. We could be creating an intermediate directory + * in the full relpath. + */ + + /* Allocate a directory entry for the new directory in this directory */ + + ret = fat_allocatedirentry(fs, &dirinfo); + if (ret != OK) + { + goto errout_with_semaphore; + } + parentsector = fs->fs_currentsector; + + /* Allocate a cluster for new directory */ + + dircluster = fat_createchain(fs); + if (dircluster < 0) + { + ret = dircluster; + goto errout_with_semaphore; + } + else if (dircluster < 2) + { + ret = -ENOSPC; + goto errout_with_semaphore; + } + + dirsector = fat_cluster2sector(fs, dircluster); + if (dirsector < 0) + { + ret = dirsector; + goto errout_with_semaphore; + } + + /* Flush any existing, dirty data in fs_buffer (because we need + * it to create the directory entries. + */ + + ret = fat_fscacheflush(fs); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Get a pointer to the first directory entry in the sector */ + + direntry = fs->fs_buffer; + + /* Now erase the contents of fs_buffer */ + + fs->fs_currentsector = dirsector; + memset(direntry, 0, fs->fs_hwsectorsize); + + /* Now clear all sectors in the new directory cluster (except for the first) */ + + for (i = 1; i < fs->fs_fatsecperclus; i++) + { + ret = fat_hwwrite(fs, direntry, ++dirsector, 1); + if (ret < 0) + { + goto errout_with_semaphore; + } + } + + /* Now create the "." directory entry in the first directory slot. These + * are special directory entries and are not handled by the normal directory + * management routines. + */ + + memset(&direntry[DIR_NAME], ' ', DIR_MAXFNAME); + direntry[DIR_NAME] = '.'; + DIR_PUTATTRIBUTES(direntry, FATATTR_DIRECTORY); + + crtime = fat_systime2fattime(); + DIR_PUTCRTIME(direntry, crtime & 0xffff); + DIR_PUTWRTTIME(direntry, crtime & 0xffff); + DIR_PUTCRDATE(direntry, crtime >> 16); + DIR_PUTWRTDATE(direntry, crtime >> 16); + + /* Create ".." directory entry in the second directory slot */ + + direntry2 = direntry + DIR_SIZE; + + /* So far, the two entries are nearly the same */ + + memcpy(direntry2, direntry, DIR_SIZE); + direntry2[DIR_NAME+1] = '.'; + + /* Now add the cluster information to both directory entries */ + + DIR_PUTFSTCLUSTHI(direntry, dircluster >> 16); + DIR_PUTFSTCLUSTLO(direntry, dircluster); + + parentcluster = dirinfo.dir.fd_startcluster; + if (fs->fs_type != FSTYPE_FAT32 && parentcluster == fs->fs_rootbase) + { + parentcluster = 0; + } + + DIR_PUTFSTCLUSTHI(direntry2, parentcluster >> 16); + DIR_PUTFSTCLUSTLO(direntry2, parentcluster); + + /* Save the first sector of the directory cluster and re-read + * the parentsector + */ + + fs->fs_dirty = true; + ret = fat_fscacheread(fs, parentsector); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Write the new entry directory entry in the parent directory */ + + ret = fat_dirwrite(fs, &dirinfo, FATATTR_DIRECTORY, crtime); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Set subdirectory start cluster. We assume that fat_dirwrite() did not + * change the sector in the cache. + */ + + direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset]; + DIR_PUTFSTCLUSTLO(direntry, dircluster); + DIR_PUTFSTCLUSTHI(direntry, dircluster >> 16); + fs->fs_dirty = true; + + /* Now update the FAT32 FSINFO sector */ + + ret = fat_updatefsinfo(fs); + if (ret < 0) + { + goto errout_with_semaphore; + } + + fat_semgive(fs); + return OK; + +errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_rmdir + * + * Description: Remove a directory + * + ****************************************************************************/ + +int fat_rmdir(struct inode *mountpt, const char *relpath) +{ + struct fat_mountpt_s *fs; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + /* Check if the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret == OK) + { + /* If the directory is open, the correct behavior is to remove the directory + * name, but to keep the directory cluster chain in place until the last + * open reference to the directory is closed. + */ + +#ifdef CONFIG_CPP_HAVE_WARNING +# warning "Need to defer deleting cluster chain if the directory is open" +#endif + + /* Remove the directory */ + + ret = fat_remove(fs, relpath, true); + } + + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_rename + * + * Description: Rename a file or directory + * + ****************************************************************************/ + +int fat_rename(struct inode *mountpt, const char *oldrelpath, + const char *newrelpath) +{ + struct fat_mountpt_s *fs; + struct fat_dirinfo_s dirinfo; + struct fat_dirseq_s dirseq; + uint8_t *direntry; + uint8_t dirstate[DIR_SIZE-DIR_ATTRIBUTES]; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + /* Check if the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Find the directory entry for the oldrelpath (there may be multiple + * directory entries if long file name support is enabled). + */ + + ret = fat_finddirentry(fs, &dirinfo, oldrelpath); + if (ret != OK) + { + /* Some error occurred -- probably -ENOENT */ + + goto errout_with_semaphore; + } + + /* One more check: Make sure that the oldrelpath does not refer to the + * root directory. We can't rename the root directory. + */ + + if (dirinfo.fd_root) + { + ret = -EXDEV; + goto errout_with_semaphore; + } + + /* Save the information that will need to recover the directory sector and + * directory entry offset to the old directory. + * + * Save the positional information of the old directory entry. + */ + + memcpy(&dirseq, &dirinfo.fd_seq, sizeof(struct fat_dirseq_s)); + + /* Save the non-name-related portion of the directory entry intact */ + + direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset]; + memcpy(dirstate, &direntry[DIR_ATTRIBUTES], DIR_SIZE-DIR_ATTRIBUTES); + + /* Now find the directory where we should create the newpath object */ + + ret = fat_finddirentry(fs, &dirinfo, newrelpath); + if (ret == OK) + { + /* It is an error if the object at newrelpath already exists */ + + ret = -EEXIST; + goto errout_with_semaphore; + } + + /* What we expect is -ENOENT mean that the full directory path was + * followed but that the object does not exists in the terminal directory. + */ + + if (ret != -ENOENT) + { + goto errout_with_semaphore; + } + + /* Reserve a directory entry. If long file name support is enabled, then + * this might, in fact, allocate a sequence of directory entries. A side + * effect of fat_allocatedirentry() in either case is that it leaves the + * short file name entry in the sector cache. + */ + + ret = fat_allocatedirentry(fs, &dirinfo); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Then write the new file name into the directory entry. This, of course, + * may involve writing multiple directory entries if long file name + * support is enabled. A side effect of fat_allocatedirentry() in either + * case is that it leaves the short file name entry in the sector cache. + */ + + ret = fat_dirnamewrite(fs, &dirinfo); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Copy the unchanged information into the new short file name entry. */ + + direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset]; + memcpy(&direntry[DIR_ATTRIBUTES], dirstate, DIR_SIZE-DIR_ATTRIBUTES); + fs->fs_dirty = true; + + /* Remove the old entry, flushing the new directory entry to disk. If + * the old file name was a long file name, then multiple directory + * entries may be freed. + */ + + ret = fat_freedirentry(fs, &dirseq); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Write the old entry to disk and update FSINFO if necessary */ + + ret = fat_updatefsinfo(fs); + if (ret < 0) + { + goto errout_with_semaphore; + } + + fat_semgive(fs); + return OK; + +errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_stat + * + * Description: Return information about a file or directory + * + ****************************************************************************/ + +static int fat_stat(struct inode *mountpt, const char *relpath, struct stat *buf) +{ + struct fat_mountpt_s *fs; + struct fat_dirinfo_s dirinfo; + uint16_t fatdate; + uint16_t date2; + uint16_t fattime; + uint8_t *direntry; + uint8_t attribute; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + /* Check if the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Find the directory entry corresponding to relpath. */ + + ret = fat_finddirentry(fs, &dirinfo, relpath); + + /* If nothing was found, then we fail with the reported error */ + + if (ret < 0) + { + goto errout_with_semaphore; + } + + memset(buf, 0, sizeof(struct stat)); + if (dirinfo.fd_root) + { + /* It's directory name of the mount point */ + + buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR|S_IWOTH|S_IWGRP|S_IWUSR; + ret = OK; + goto errout_with_semaphore; + } + + /* Get the FAT attribute and map it so some meaningful mode_t values */ + + direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset]; + attribute = DIR_GETATTRIBUTES(direntry); + if ((attribute & FATATTR_VOLUMEID) != 0) + { + ret = -ENOENT; + goto errout_with_semaphore; + } + + /* Set the access permissions. The file/directory is always readable + * by everyone but may be writeable by no-one. + */ + + buf->st_mode = S_IROTH|S_IRGRP|S_IRUSR; + if ((attribute & FATATTR_READONLY) == 0) + { + buf->st_mode |= S_IWOTH|S_IWGRP|S_IWUSR; + } + + /* We will report only types file or directory */ + + if ((attribute & FATATTR_DIRECTORY) != 0) + { + buf->st_mode |= S_IFDIR; + } + else + { + buf->st_mode |= S_IFREG; + } + + /* File/directory size, access block size */ + + buf->st_size = DIR_GETFILESIZE(direntry); + buf->st_blksize = fs->fs_fatsecperclus * fs->fs_hwsectorsize; + buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize; + + /* Times */ + + fatdate = DIR_GETWRTDATE(direntry); + fattime = DIR_GETWRTTIME(direntry); + buf->st_mtime = fat_fattime2systime(fattime, fatdate); + + date2 = DIR_GETLASTACCDATE(direntry); + if (fatdate == date2) + { + buf->st_atime = buf->st_mtime; + } + else + { + buf->st_atime = fat_fattime2systime(0, date2); + } + + fatdate = DIR_GETCRDATE(direntry); + fattime = DIR_GETCRTIME(direntry); + buf->st_ctime = fat_fattime2systime(fattime, fatdate); + + ret = OK; + +errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + diff --git a/nuttx/fs/fat/fs_fat32.h b/nuttx/fs/fat/fs_fat32.h new file mode 100644 index 0000000000..5b82ff7016 --- /dev/null +++ b/nuttx/fs/fat/fs_fat32.h @@ -0,0 +1,910 @@ +/**************************************************************************** + * fs/fat/fs_fat32.h + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_FAT_FS_FAT32_H +#define __FS_FAT_FS_FAT32_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * These offsets describes the master boot record. + * + * The folowing fields are common to FAT12/16/32 (but all value descriptions + * refer to the interpretation under FAT32. + */ + +#define BS_JUMP 0 /* 3@0: Jump instruction to boot code (ignored) */ +#define BS_OEMNAME 3 /* 8@3: Usually "MSWIN4.1" */ +#define BS_BYTESPERSEC 11 /* 2@11: Bytes per sector: 512, 1024, 2048, 4096 */ +#define BS_SECPERCLUS 13 /* 1@13: Sectors per allocation unit: 2**n, n=0..7 */ +#define BS_RESVDSECCOUNT 14 /* 2@14: Reserved sector count: Usually 32 */ +#define BS_NUMFATS 16 /* 1@16: Number of FAT data structures: always 2 */ +#define BS_ROOTENTCNT 17 /* 2@17: FAT12/16: Must be 0 for FAT32 */ +#define BS_TOTSEC16 19 /* 2@19: FAT12/16: Must be 0, see BS_TOTSEC32 */ +#define BS_MEDIA 21 /* 1@21: Media code: f0, f8, f9-fa, fc-ff */ +#define BS_FATSZ16 22 /* 2@22: FAT12/16: Must be 0, see BS_FATSZ32 */ +#define BS_SECPERTRK 24 /* 2@24: Sectors per track geometry value */ +#define BS_NUMHEADS 26 /* 2@26: Number of heads geometry value */ +#define BS_HIDSEC 28 /* 4@28: Count of hidden sectors preceding FAT */ +#define BS_TOTSEC32 32 /* 4@32: Total count of sectors on the volume */ + +/* The following fields are only valid for FAT12/16 */ + +#define BS16_DRVNUM 36 /* 1@36: Drive number for MSDOS bootstrap */ + /* 1@37: Reserved (zero) */ +#define BS16_BOOTSIG 38 /* 1@38: Extended boot signature: 0x29 if following valid */ +#define BS16_VOLID 39 /* 4@39: Volume serial number */ +#define BS16_VOLLAB 43 /* 11@43: Volume label */ +#define BS16_FILESYSTYPE 54 /* 8@54: "FAT12 ", "FAT16 ", or "FAT " */ + +#define BS16_BOOTCODE 62 /* Boot code may be placed in the remainder of the sector */ +#define BS16_BOOTCODESIZE 448 + +/* The following fields are only valid for FAT32 */ + +#define BS32_FATSZ32 36 /* 4@36: Count of sectors occupied by one FAT */ +#define BS32_EXTFLAGS 40 /* 2@40: 0-3:Active FAT, 7=0 both FATS, 7=1 one FAT */ +#define BS32_FSVER 42 /* 2@42: MSB:Major LSB:Minor revision number (0.0) */ +#define BS32_ROOTCLUS 44 /* 4@44: Cluster no. of 1st cluster of root dir */ +#define BS32_FSINFO 48 /* 2@48: Sector number of fsinfo structure. Usually 1. */ +#define BS32_BKBOOTSEC 50 /* 2@50: Sector number of boot record. Usually 6 */ + /* 12@52: Reserved (zero) */ +#define BS32_DRVNUM 64 /* 1@64: Drive number for MSDOS bootstrap */ + /* 1@65: Reserved (zero) */ +#define BS32_BOOTSIG 66 /* 1@66: Extended boot signature: 0x29 if following valid */ +#define BS32_VOLID 67 /* 4@67: Volume serial number */ +#define BS32_VOLLAB 71 /* 11@71: Volume label */ +#define BS32_FILESYSTYPE 82 /* 8@82: "FAT12 ", "FAT16 ", or "FAT " */ + +#define BS32_BOOTCODE 90 /* Boot code may be placed in the remainder of the sector */ +#define BS32_BOOTCODESIZE 420 + +/* If the sector is not an MBR, then it could have a partition table at + * this offset. + */ + +#define MBR_TABLE 446 + +/* The magic bytes at the end of the MBR are common to FAT12/16/32 */ + +#define BS_SIGNATURE 510 /* 2@510: Valid MBRs have 0x55aa here */ + +#define BOOT_SIGNATURE16 0xaa55 +#define BOOT_SIGNATURE32 0xaa550000 + +/* The extended boot signature (BS16/32_BOOTSIG) */ + +#define EXTBOOT_SIGNATURE 0x29 + +/**************************************************************************** + * These offsets describes the partition table. + */ + /* 446@0: Generally unused and zero; but may + * include IDM Boot Manager menu entry at 8@394 */ +#define PART_ENTRY(n) (446+((n) << 4)) /* n = 0,1,2,3 */ +#define PART_ENTRY1 446 /* 16@446: Partition table, first entry */ +#define PART_ENTRY2 462 /* 16@462: Partition table, second entry */ +#define PART_ENTRY3 478 /* 16@478: Partition table, third entry */ +#define PART_ENTRY4 494 /* 16@494: Partition table, fourth entry */ +#define PART_SIGNATURE 510 /* 2@510: Valid partitions have 0x55aa here */ + +/**************************************************************************** + * These offsets describes one partition table entry. NOTE that ent entries + * are aligned to 16-bit offsets so that the STARTSECTOR and SIZE values are + * not properly aligned. + */ + +#define PART_BOOTINDICATOR 0 /* 1@0: Boot indicator (0x80: active;0x00:otherwise) */ +#define PART_STARTCHS 1 /* 3@1: Starting Cylinder/Head/Sector values */ +#define PART_TYPE 4 /* 1@4: Partition type description */ +#define PART_ENDCHS 5 /* 3@5: Ending Cylinder/Head/Sector values */ +#define PART_STARTSECTOR 8 /* 4@8: Starting sector */ +#define PART_SIZE 12 /* 4@12: Partition size (in sectors) */ + +/**************************************************************************** + * Partition table types. + */ + +#define PART_TYPE_NONE 0 /* No partition */ +#define PART_TYPE_FAT12 1 /* FAT12 */ +#define PART_TYPE_FAT16A 4 /* FAT16 (Partition smaller than 32MB) */ +#define PART_TYPE_EXT 5 /* Extended MS-DOS Partition */ +#define PART_TYPE_FAT16B 6 /* FAT16 (Partition larger than 32MB) */ +#define PART_TYPE_FAT32 11 /* FAT32 (Partition up to 2048Gb) */ +#define PART_TYPE_FAT32X 12 /* Same as 11, but uses LBA1 0x13 extensions */ +#define PART_TYPE_FAT16X 14 /* Same as 6, but uses LBA1 0x13 extensions */ +#define PART_TYPE_EXTX 15 /* Same as 5, but uses LBA1 0x13 extensions */ + +/**************************************************************************** + * Each FAT "short" 8.3 file name directory entry is 32-bytes long. + * + * Sizes and limits + */ + +/**************************************************************************** + * Each FAT "short" 8.3 file name directory entry is 32-bytes long. + * + * Sizes and limits + */ + +#define DIR_MAXFNAME 11 /* Max short name size is 8+3 = 11 */ + +/* The following define offsets relative to the beginning of a directory + * entry. + */ + +#define DIR_NAME 0 /* 11@ 0: NAME: 8 bytes + 3 byte extension */ +#define DIR_ATTRIBUTES 11 /* 1@11: File attibutes (see below) */ +#define DIR_NTRES 12 /* 1@12: Reserved for use by NT */ +#define DIR_CRTTIMETENTH 13 /* 1@13: Tenth sec creation timestamp */ +#define DIR_CRTIME 14 /* 2@14: Time file created */ +#define DIR_CRDATE 16 /* 2@16: Date file created */ +#define DIR_LASTACCDATE 18 /* 2@19: Last access date */ +#define DIR_FSTCLUSTHI 20 /* 2@20: MS first cluster number */ +#define DIR_WRTTIME 22 /* 2@22: Time of last write */ +#define DIR_WRTDATE 24 /* 2@24: Date of last write */ +#define DIR_FSTCLUSTLO 26 /* 2@26: LS first cluster number */ +#define DIR_FILESIZE 28 /* 4@28: File size in bytes */ +#define DIR_SIZE 32 /* The size of one directory entry */ +#define DIR_SHIFT 5 /* log2 of DIR_SIZE */ + +/* First byte of the directory name has special meanings: */ + +#define DIR0_EMPTY 0xe5 /* The directory entry is empty */ +#define DIR0_ALLEMPTY 0x00 /* This entry and all following are empty */ +#define DIR0_E5 0x05 /* The actual value is 0xe5 */ + +/* NTRES flags in the FAT directory */ + +#define FATNTRES_LCNAME 0x08 /* Lower case in name */ +#define FATNTRES_LCEXT 0x10 /* Lower case in extension */ + +/* Directory indexing helper. Each directory entry is 32-bytes in length. + * The number of directory entries in a sector then varies with the size + * of the sector supported in hardware. + */ + +#define DIRSEC_NDXMASK(f) (((f)->fs_hwsectorsize - 1) >> 5) +#define DIRSEC_NDIRS(f) (((f)->fs_hwsectorsize) >> 5) +#define DIRSEC_BYTENDX(f,i) (((i) & DIRSEC_NDXMASK(fs)) << 5) + +#define SEC_NDXMASK(f) ((f)->fs_hwsectorsize - 1) +#define SEC_NSECTORS(f,n) ((n) / (f)->fs_hwsectorsize) + +#define CLUS_NDXMASK(f) ((f)->fs_fatsecperclus - 1) + +/**************************************************************************** + * The FAT "long" file name (LFN) directory entry */ + +#ifdef CONFIG_FAT_LFN + +/* Sizes and limits */ + +# ifndef CONFIG_FAT_MAXFNAME /* The maximum support filename can be limited */ +# define LDIR_MAXFNAME 255 /* Max unicode characters in file name */ +# elif CONFIG_FAT_MAXFNAME <= 255 +# define LDIR_MAXFNAME CONFIG_FAT_MAXFNAME +# else +# error "Illegal value for CONFIG_FAT_MAXFNAME" +# endif + +# define LDIR_MAXLFNCHARS 13 /* Max unicode characters in one LFN entry */ +# define LDIR_MAXLFNS 20 /* Max number of LFN entries */ + +/* LFN directory entry offsets */ + +# define LDIR_SEQ 0 /* 1@ 0: Sequence number */ +# define LDIR_WCHAR1_5 1 /* 10@ 1: File name characters 1-5 (5 Unicode characters) */ +# define LDIR_ATTRIBUTES 11 /* 1@11: File attributes (always 0x0f) */ +# define LDIR_NTRES 12 /* 1@12: Reserved for use by NT (always 0x00) */ +# define LDIR_CHECKSUM 13 /* 1@13: Checksum of the DOS filename */ +# define LDIR_WCHAR6_11 14 /* 12@14: File name characters 6-11 (6 Unicode characters) */ +# define LDIR_FSTCLUSTLO 26 /* 2@26: First cluster (always 0x0000) */ +# define LDIR_WCHAR12_13 28 /* 4@28: File name characters 12-13 (2 Unicode characters) */ + +/* LFN sequence number and allocation status */ + +# define LDIR0_EMPTY DIR0_EMPTY /* The directory entry is empty */ +# define LDIR0_ALLEMPTY DIR0_ALLEMPTY /* This entry and all following are empty */ +# define LDIR0_E5 DIR0_E5 /* The actual value is 0xe5 */ +# define LDIR0_LAST 0x40 /* Last LFN in file name (appears first) */ +# define LDIR0_SEQ_MASK 0x1f /* Mask for sequence number (1-20) */ + +/* The LFN entry attribute */ + +# define LDDIR_LFNATTR 0x0f +#endif + +/**************************************************************************** + * File system types */ + +#define FSTYPE_FAT12 0 +#define FSTYPE_FAT16 1 +#define FSTYPE_FAT32 2 + +/* File buffer flags */ + +#define FFBUFF_VALID 1 +#define FFBUFF_DIRTY 2 +#define FFBUFF_MODIFIED 4 + +/**************************************************************************** + * These offset describe the FSINFO sector + */ + +#define FSI_LEADSIG 0 /* 4@0: 0x41615252 = "RRaA" */ + /* 480@4: Reserved (zero) */ +#define FSI_STRUCTSIG 484 /* 4@484: 0x61417272 = "rrAa" */ +#define FSI_FREECOUNT 488 /* 4@488: Last free cluster count on volume */ +#define FSI_NXTFREE 492 /* 4@492: Cluster number of 1st free cluster */ + /* 12@496: Reserved (zero) */ +#define FSI_TRAILSIG 508 /* 4@508: 0xaa550000 */ + +/**************************************************************************** + * FAT values + */ + +#define FAT_EOF 0x0ffffff8 +#define FAT_BAD 0x0ffffff7 + +/**************************************************************************** + * Maximum cluster by FAT type. This is the key value used to distinquish + * between FAT12, 16, and 32. + */ + +/* FAT12: For M$, the calculation is ((1 << 12) - 19). But we will follow the + * Linux tradition of allowing slightly more clusters for FAT12. + */ + +#define FAT_MAXCLUST12 ((1 << 12) - 16) + +/* FAT16: For M$, the calculation is ((1 << 16) - 19). (The uint32_t cast is + * needed for architectures where int is only 16 bits). + */ + +#define FAT_MINCLUST16 (FAT_MAXCLUST12 + 1) +#define FAT_MAXCLUST16 (((uint32_t)1 << 16) - 16) + +/* FAT32: M$ reserves the MS 4 bits of a FAT32 FAT entry so only 18 bits are + * available. For M$, the calculation is ((1 << 28) - 19). (The uint32_t cast + * is needed for architectures where int is only 16 bits). + */ + +#define FAT_MINCLUST32 65524 +/* #define FAT_MINCLUST32 (FAT_MAXCLUST16 + 1) */ +#define FAT_MAXCLUST32 (((uint32_t)1 << 28) - 16) + +/**************************************************************************** + * Access to data in raw sector data */ + +#define UBYTE_VAL(p,o) (((uint8_t*)(p))[o]) +#define UBYTE_PTR(p,o) &UBYTE_VAL(p,o) +#define UBYTE_PUT(p,o,v) (UBYTE_VAL(p,o)=(uint8_t)(v)) + +#define UINT16_PTR(p,o) ((uint16_t*)UBYTE_PTR(p,o)) +#define UINT16_VAL(p,o) (*UINT16_PTR(p,o)) +#define UINT16_PUT(p,o,v) (UINT16_VAL(p,o)=(uint16_t)(v)) + +#define UINT32_PTR(p,o) ((uint32_t*)UBYTE_PTR(p,o)) +#define UINT32_VAL(p,o) (*UINT32_PTR(p,o)) +#define UINT32_PUT(p,o,v) (UINT32_VAL(p,o)=(uint32_t)(v)) + +/* Regardless of the endian-ness of the target or alignment of the data, no + * special operations are required for byte, string or byte array accesses. + * The FAT data stream is little endian so multiple byte values must be + * accessed byte-by-byte for big-endian targets. + */ + +#define MBR_GETSECPERCLUS(p) UBYTE_VAL(p,BS_SECPERCLUS) +#define MBR_GETNUMFATS(p) UBYTE_VAL(p,BS_NUMFATS) +#define MBR_GETMEDIA(p) UBYTE_VAL(p,BS_MEDIA) +#define MBR_GETDRVNUM16(p) UBYTE_VAL(p,BS16_DRVNUM) +#define MBR_GETDRVNUM32(p) UBYTE_VAL(p,BS32_DRVNUM) +#define MBR_GETBOOTSIG16(p) UBYTE_VAL(p,BS16_BOOTSIG) +#define MBR_GETBOOTSIG32(p) UBYTE_VAL(p,BS32_BOOTSIG) + +#define PART_GETTYPE(n,p) UBYTE_VAL(p,PART_ENTRY(n)+PART_TYPE) +#define PART1_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY1+PART_TYPE) +#define PART2_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY2+PART_TYPE) +#define PART3_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY3+PART_TYPE) +#define PART4_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY4+PART_TYPE) + +#define DIR_GETATTRIBUTES(p) UBYTE_VAL(p,DIR_ATTRIBUTES) +#define DIR_GETNTRES(p) UBYTE_VAL(p,DIR_NTRES) +#define DIR_GETCRTTIMETENTH(p) UBYTE_VAL(p,DIR_CRTTIMETENTH) + +#ifdef CONFIG_FAT_LFN +# define LDIR_GETSEQ(p) UBYTE_VAL(p,LDIR_SEQ) +# define LDIR_GETATTRIBUTES(p) UBYTE_VAL(p,LDIR_ATTRIBUTES) +# define LDIR_GETNTRES(p) UBYTE_VAL(p,LDIR_NTRES) +# define LDIR_GETCHECKSUM(p) UBYTE_VAL(p,LDIR_CHECKSUM) +#endif + +#define MBR_PUTSECPERCLUS(p,v) UBYTE_PUT(p,BS_SECPERCLUS,v) +#define MBR_PUTNUMFATS(p,v) UBYTE_PUT(p,BS_NUMFATS,v) +#define MBR_PUTMEDIA(p,v) UBYTE_PUT(p,BS_MEDIA,v) +#define MBR_PUTDRVNUM16(p,v) UBYTE_PUT(p,BS16_DRVNUM,v) +#define MBR_PUTDRVNUM32(p,v) UBYTE_PUT(p,BS32_DRVNUM,v) +#define MBR_PUTBOOTSIG16(p,v) UBYTE_PUT(p,BS16_BOOTSIG,v) +#define MBR_PUTBOOTSIG32(p,v) UBYTE_PUT(p,BS32_BOOTSIG,v) + +#define PART_PUTTYPE(n,p,v) UBYTE_PUT(p,PART_ENTRY(n)+PART_TYPE,v) +#define PART1_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY1+PART_TYPE,v) +#define PART2_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY2+PART_TYPE,v) +#define PART3_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY3+PART_TYPE,v) +#define PART4_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY4+PART_TYPE,v) + +#define DIR_PUTATTRIBUTES(p,v) UBYTE_PUT(p,DIR_ATTRIBUTES,v) +#define DIR_PUTNTRES(p,v) UBYTE_PUT(p,DIR_NTRES,v) +#define DIR_PUTCRTTIMETENTH(p,v) UBYTE_PUT(p,DIR_CRTTIMETENTH,v) + +#ifdef CONFIG_FAT_LFN +# define LDIR_PUTSEQ(p,v) UBYTE_PUT(p,LDIR_SEQ,v) +# define LDIR_PUTATTRIBUTES(p,v) UBYTE_PUT(p,LDIR_ATTRIBUTES,v) +# define LDIR_PUTNTRES(p,v) UBYTE_PUT(p,LDIR_NTRES,v) +# define LDIR_PUTCHECKSUM(p,v) UBYTE_PUT(p,LDIR_CHECKSUM,v) +#endif + +/* For the all targets, unaligned values need to be accessed byte-by-byte. + * Some architectures may handle unaligned accesses with special interrupt + * handlers. But even in that case, it is more efficient to avoid the traps. + */ + +/* Unaligned multi-byte access macros */ + +#define MBR_GETBYTESPERSEC(p) fat_getuint16(UBYTE_PTR(p,BS_BYTESPERSEC)) +#define MBR_GETROOTENTCNT(p) fat_getuint16(UBYTE_PTR(p,BS_ROOTENTCNT)) +#define MBR_GETTOTSEC16(p) fat_getuint16(UBYTE_PTR(p,BS_TOTSEC16)) +#define MBR_GETVOLID16(p) fat_getuint32(UBYTE_PTR(p,BS16_VOLID)) +#define MBR_GETVOLID32(p) fat_getuint32(UBYTE_PTR(p,BS32_VOLID)) + +#define PART_GETSTARTSECTOR(n,p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY(n)+PART_STARTSECTOR)) +#define PART_GETSIZE(n,p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY(n)+PART_SIZE)) +#define PART1_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY1+PART_STARTSECTOR)) +#define PART1_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY1+PART_SIZE)) +#define PART2_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY2+PART_STARTSECTOR)) +#define PART2_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY2+PART_SIZE)) +#define PART3_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY3+PART_STARTSECTOR)) +#define PART3_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY3+PART_SIZE)) +#define PART4_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY4+PART_STARTSECTOR)) +#define PART4_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY4+PART_SIZE)) + +#define MBR_PUTBYTESPERSEC(p,v) fat_putuint16(UBYTE_PTR(p,BS_BYTESPERSEC),v) +#define MBR_PUTROOTENTCNT(p,v) fat_putuint16(UBYTE_PTR(p,BS_ROOTENTCNT),v) +#define MBR_PUTTOTSEC16(p,v) fat_putuint16(UBYTE_PTR(p,BS_TOTSEC16),v) +#define MBR_PUTVOLID16(p,v) fat_putuint32(UBYTE_PTR(p,BS16_VOLID),v) +#define MBR_PUTVOLID32(p,v) fat_putuint32(UBYTE_PTR(p,BS32_VOLID),v) + +#define PART_PUTSTARTSECTOR(n,p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY(n)+PART_STARTSECTOR),v) +#define PART_PUTSIZE(n,p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY(n)+PART_SIZE),v) +#define PART1_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY1+PART_STARTSECTOR),v) +#define PART1_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY1+PART_SIZE),v) +#define PART2_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY2+PART_STARTSECTOR),v) +#define PART2_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY2+PART_SIZE),v) +#define PART3_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY3+PART_STARTSECTOR),v) +#define PART3_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY3+PART_SIZE),v) +#define PART4_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY4+PART_STARTSECTOR),v) +#define PART4_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY4+PART_SIZE),v) + +#ifdef CONFIG_FAT_LFN +# define LDIR_PTRWCHAR1_5(p) UBYTE_PTR(p,LDIR_WCHAR1_5) +# define LDIR_PTRWCHAR6_11(p) UBYTE_PTR(p,LDIR_WCHAR6_11) +# define LDIR_PTRWCHAR12_13(p) UBYTE_PTR(p,LDIR_WCHAR12_13) +#endif + +/* But for multi-byte values, the endian-ness of the target vs. the little + * endian order of the byte stream or alignment of the data within the byte + * stream can force special, byte-by-byte accesses. + */ + +#ifdef CONFIG_ENDIAN_BIG + +/* If the target is big-endian, then even aligned multi-byte values must be + * accessed byte-by-byte. + */ + +# define MBR_GETRESVDSECCOUNT(p) fat_getuint16(UBYTE_PTR(p,BS_RESVDSECCOUNT)) +# define MBR_GETFATSZ16(p) fat_getuint16(UBYTE_PTR(p,BS_FATSZ16)) +# define MBR_GETSECPERTRK(p) fat_getuint16(UBYTE_PTR(p,BS_SECPERTRK)) +# define MBR_GETNUMHEADS(p) fat_getuint16(UBYTE_PTR(p,BS_NUMHEADS)) +# define MBR_GETHIDSEC(p) fat_getuint32(UBYTE_PTR(p,BS_HIDSEC)) +# define MBR_GETTOTSEC32(p) fat_getuint32(UBYTE_PTR(p,BS_TOTSEC32)) +# define MBR_GETFATSZ32(p) fat_getuint32(UBYTE_PTR(p,BS32_FATSZ32)) +# define MBR_GETEXTFLAGS(p) fat_getuint16(UBYTE_PTR(p,BS32_EXTFLAGS)) +# define MBR_GETFSVER(p) fat_getuint16(UBYTE_PTR(p,BS32_FSVER)) +# define MBR_GETROOTCLUS(p) fat_getuint32(UBYTE_PTR(p,BS32_ROOTCLUS)) +# define MBR_GETFSINFO(p) fat_getuint16(UBYTE_PTR(p,BS32_FSINFO)) +# define MBR_GETBKBOOTSEC(p) fat_getuint16(UBYTE_PTR(p,BS32_BKBOOTSEC)) +# define MBR_GETSIGNATURE(p) fat_getuint16(UBYTE_PTR(p,BS_SIGNATURE)) + +# define FSI_GETLEADSIG(p) fat_getuint32(UBYTE_PTR(p,FSI_LEADSIG)) +# define FSI_GETSTRUCTSIG(p) fat_getuint32(UBYTE_PTR(p,FSI_STRUCTSIG)) +# define FSI_GETFREECOUNT(p) fat_getuint32(UBYTE_PTR(p,FSI_FREECOUNT)) +# define FSI_GETNXTFREE(p) fat_getuint32(UBYTE_PTR(p,FSI_NXTFREE)) +# define FSI_GETTRAILSIG(p) fat_getuint32(UBYTE_PTR(p,FSI_TRAILSIG)) + +# define DIR_GETCRTIME(p) fat_getuint16(UBYTE_PTR(p,DIR_CRTIME)) +# define DIR_GETCRDATE(p) fat_getuint16(UBYTE_PTR(p,DIR_CRDATE)) +# define DIR_GETLASTACCDATE(p) fat_getuint16(UBYTE_PTR(p,DIR_LASTACCDATE)) +# define DIR_GETFSTCLUSTHI(p) fat_getuint16(UBYTE_PTR(p,DIR_FSTCLUSTHI)) +# define DIR_GETWRTTIME(p) fat_getuint16(UBYTE_PTR(p,DIR_WRTTIME)) +# define DIR_GETWRTDATE(p) fat_getuint16(UBYTE_PTR(p,DIR_WRTDATE)) +# define DIR_GETFSTCLUSTLO(p) fat_getuint16(UBYTE_PTR(p,DIR_FSTCLUSTLO)) +# define DIR_GETFILESIZE(p) fat_getuint32(UBYTE_PTR(p,DIR_FILESIZE)) + +# ifdef CONFIG_FAT_LFN +# define LDIR_GETWCHAR1(p) fat_getuint16(UBYTE_PTR(p,LDIR_WCHAR1_5)) +# define LDIR_GETWCHAR2(p) fat_getuint16(UBYTE_PTR(p,LDIR_WCHAR1_5+2)) +# define LDIR_GETWCHAR3(p) fat_getuint16(UBYTE_PTR(p,LDIR_WCHAR1_5+4)) +# define LDIR_GETWCHAR4(p) fat_getuint16(UBYTE_PTR(p,LDIR_WCHAR1_5+6)) +# define LDIR_GETWCHAR5(p) fat_getuint16(UBYTE_PTR(p,LDIR_WCHAR1_5+8)) +# define LDIR_GETWCHAR6(p) fat_getuint16(UBYTE_PTR(p,LDIR_WCHAR6_11)) +# define LDIR_GETWCHAR7(p) fat_getuint16(UBYTE_PTR(p,LDIR_WCHAR6_11+2)) +# define LDIR_GETWCHAR8(p) fat_getuint16(UBYTE_PTR(p,LDIR_WCHAR6_11+4)) +# define LDIR_GETWCHAR8(p) fat_getuint16(UBYTE_PTR(p,LDIR_WCHAR6_11+6)) +# define LDIR_GETWCHAR10(p) fat_getuint16(UBYTE_PTR(p,LDIR_WCHAR6_11+8)) +# define LDIR_GETWCHAR11(p) fat_getuint16(UBYTE_PTR(p,LDIR_WCHAR6_11+10)) +# define LDIR_GETWCHAR12(p) fat_getuint16(UBYTE_PTR(p,LDIR_WCHAR12_13)) +# define LDIR_GETWCHAR13(p) fat_getuint16(UBYTE_PTR(p,LDIR_WCHAR12_13+2)) +# define LDIR_GETFSTCLUSTLO(p) fat_getuint16(UBYTE_PTR(p,LDIR_FSTCLUSTLO)) +# endif + +# define FSI_GETLEADSIG(p) fat_getuint32(UBYTE_PTR(p,FSI_LEADSIG)) +# define FSI_GETSTRUCTSIG(p) fat_getuint32(UBYTE_PTR(p,FSI_STRUCTSIG)) +# define FSI_GETFREECOUNT(p) fat_getuint32(UBYTE_PTR(p,FSI_FREECOUNT)) +# define FSI_GETNXTFREE(p) fat_getuint32(UBYTE_PTR(p,FSI_NXTFREE)) +# define FSI_GETTRAILSIG(p) fat_getuint32(UBYTE_PTR(p,FSI_TRAILSIG)) + +# define FAT_GETFAT16(p,i) fat_getuint16(UBYTE_PTR(p,i)) +# define FAT_GETFAT32(p,i) fat_getuint32(UBYTE_PTR(p,i)) + +# define MBR_PUTRESVDSECCOUNT(p,v) fat_putuint16(UBYTE_PTR(p,BS_RESVDSECCOUNT),v) +# define MBR_PUTFATSZ16(p,v) fat_putuint16(UBYTE_PTR(p,BS_FATSZ16),v) +# define MBR_PUTSECPERTRK(p,v) fat_putuint16(UBYTE_PTR(p,BS_SECPERTRK),v) +# define MBR_PUTNUMHEADS(p,v) fat_putuint16(UBYTE_PTR(p,BS_NUMHEADS),v) +# define MBR_PUTHIDSEC(p,v) fat_putuint32(UBYTE_PTR(p,BS_HIDSEC),v) +# define MBR_PUTTOTSEC32(p,v) fat_putuint32(UBYTE_PTR(p,BS_TOTSEC32),v) +# define MBR_PUTFATSZ32(p,v) fat_putuint32(UBYTE_PTR(p,BS32_FATSZ32),v) +# define MBR_PUTEXTFLAGS(p,v) fat_putuint16(UBYTE_PTR(p,BS32_EXTFLAGS),v) +# define MBR_PUTFSVER(p,v) fat_putuint16(UBYTE_PTR(p,BS32_FSVER),v) +# define MBR_PUTROOTCLUS(p,v) fat_putuint32(UBYTE_PTR(p,BS32_ROOTCLUS),v) +# define MBR_PUTFSINFO(p,v) fat_putuint16(UBYTE_PTR(p,BS32_FSINFO),v) +# define MBR_PUTBKBOOTSEC(p,v) fat_putuint16(UBYTE_PTR(p,BS32_BKBOOTSEC),v) +# define MBR_PUTSIGNATURE(p,v) fat_putuint16(UBYTE_PTR(p,BS_SIGNATURE),v) + +# define FSI_PUTLEADSIG(p,v) fat_putuint32(UBYTE_PTR(p,FSI_LEADSIG),v) +# define FSI_PUTSTRUCTSIG(p,v) fat_putuint32(UBYTE_PTR(p,FSI_STRUCTSIG),v) +# define FSI_PUTFREECOUNT(p,v) fat_putuint32(UBYTE_PTR(p,FSI_FREECOUNT),v) +# define FSI_PUTNXTFREE(p,v) fat_putuint32(UBYTE_PTR(p,FSI_NXTFREE),v) +# define FSI_PUTTRAILSIG(p,v) fat_putuint32(UBYTE_PTR(p,FSI_TRAILSIG),v) + +# define DIR_PUTCRTIME(p,v) fat_putuint16(UBYTE_PTR(p,DIR_CRTIME),v) +# define DIR_PUTCRDATE(p,v) fat_putuint16(UBYTE_PTR(p,DIR_CRDATE),v) +# define DIR_PUTLASTACCDATE(p,v) fat_putuint16(UBYTE_PTR(p,DIR_LASTACCDATE),v) +# define DIR_PUTFSTCLUSTHI(p,v) fat_putuint16(UBYTE_PTR(p,DIR_FSTCLUSTHI),v) +# define DIR_PUTWRTTIME(p,v) fat_putuint16(UBYTE_PTR(p,DIR_WRTTIME),v) +# define DIR_PUTWRTDATE(p,v) fat_putuint16(UBYTE_PTR(p,DIR_WRTDATE),v) +# define DIR_PUTFSTCLUSTLO(p,v) fat_putuint16(UBYTE_PTR(p,DIR_FSTCLUSTLO),v) +# define DIR_PUTFILESIZE(p,v) fat_putuint32(UBYTE_PTR(p,DIR_FILESIZE),v) + +# ifdef CONFIG_FAT_LFN +# define LDIR_PUTWCHAR1(p) fat_putuint16(UBYTE_PTR(p,LDIR_WCHAR1_5),v) +# define LDIR_PUTWCHAR2(p) fat_putuint16(UBYTE_PTR(p,LDIR_WCHAR1_5+2),v) +# define LDIR_PUTWCHAR3(p) fat_putuint16(UBYTE_PTR(p,LDIR_WCHAR1_5+4),v) +# define LDIR_PUTWCHAR4(p) fat_putuint16(UBYTE_PTR(p,LDIR_WCHAR1_5+6),v) +# define LDIR_PUTWCHAR5(p) fat_putuint16(UBYTE_PTR(p,LDIR_WCHAR1_5+8),v) +# define LDIR_PUTWCHAR6(p) fat_putuint16(UBYTE_PTR(p,LDIR_WCHAR6_11),v) +# define LDIR_PUTWCHAR7(p) fat_putuint16(UBYTE_PTR(p,LDIR_WCHAR6_11+2),v) +# define LDIR_PUTWCHAR8(p) fat_putuint16(UBYTE_PTR(p,LDIR_WCHAR6_11+4),v) +# define LDIR_PUTWCHAR8(p) fat_putuint16(UBYTE_PTR(p,LDIR_WCHAR6_11+6),v) +# define LDIR_PUTWCHAR10(p) fat_putuint16(UBYTE_PTR(p,LDIR_WCHAR6_11+8),v) +# define LDIR_PUTWCHAR11(p) fat_putuint16(UBYTE_PTR(p,LDIR_WCHAR6_11+10),v) +# define LDIR_PUTWCHAR12(p) fat_putuint16(UBYTE_PTR(p,LDIR_WCHAR12_13),v) +# define LDIR_PUTWCHAR13(p) fat_putuint16(UBYTE_PTR(p,LDIR_WCHAR12_13+2),v) +# endif + +# define FSI_PUTLEADSIG(p,v) fat_putuint32(UBYTE_PTR(p,FSI_LEADSIG),v) +# define FSI_PUTSTRUCTSIG(p,v) fat_putuint32(UBYTE_PTR(p,FSI_STRUCTSIG),v) +# define FSI_PUTFREECOUNT(p,v) fat_putuint32(UBYTE_PTR(p,FSI_FREECOUNT),v) +# define FSI_PUTNXTFREE(p,v) fat_putuint32(UBYTE_PTR(p,FSI_NXTFREE),v) +# define FSI_PUTTRAILSIG(p,v) fat_putuint32(UBYTE_PTR(p,FSI_TRAILSIG),v) + +# define FAT_PUTFAT16(p,i,v) fat_putuint16(UBYTE_PTR(p,i),v) +# define FAT_PUTFAT32(p,i,v) fat_putuint32(UBYTE_PTR(p,i),v) + +#else + +/* But nothing special has to be done for the little endian-case for access + * to aligned mulitbyte values. + */ + +# define MBR_GETRESVDSECCOUNT(p) UINT16_VAL(p,BS_RESVDSECCOUNT) +# define MBR_GETFATSZ16(p) UINT16_VAL(p,BS_FATSZ16) +# define MBR_GETSECPERTRK(p) UINT16_VAL(p,BS_SECPERTRK) +# define MBR_GETNUMHEADS(p) UINT16_VAL(p,BS_NUMHEADS) +# define MBR_GETHIDSEC(p) UINT32_VAL(p,BS_HIDSEC) +# define MBR_GETTOTSEC32(p) UINT32_VAL(p,BS_TOTSEC32) +# define MBR_GETFATSZ32(p) UINT32_VAL(p,BS32_FATSZ32) +# define MBR_GETEXTFLAGS(p) UINT16_VAL(p,BS32_EXTFLAGS) +# define MBR_GETFSVER(p) UINT16_VAL(p,BS32_FSVER) +# define MBR_GETROOTCLUS(p) UINT32_VAL(p,BS32_ROOTCLUS) +# define MBR_GETFSINFO(p) UINT16_VAL(p,BS32_FSINFO) +# define MBR_GETBKBOOTSEC(p) UINT16_VAL(p,BS32_BKBOOTSEC) +# define MBR_GETSIGNATURE(p) UINT16_VAL(p,BS_SIGNATURE) + +# define FSI_GETLEADSIG(p) UINT32_VAL(p,FSI_LEADSIG) +# define FSI_GETSTRUCTSIG(p) UINT32_VAL(p,FSI_STRUCTSIG) +# define FSI_GETFREECOUNT(p) UINT32_VAL(p,FSI_FREECOUNT) +# define FSI_GETNXTFREE(p) UINT32_VAL(p,FSI_NXTFREE) +# define FSI_GETTRAILSIG(p) UINT32_VAL(p,FSI_TRAILSIG) + +# define DIR_GETCRTIME(p) UINT16_VAL(p,DIR_CRTIME) +# define DIR_GETCRDATE(p) UINT16_VAL(p,DIR_CRDATE) +# define DIR_GETLASTACCDATE(p) UINT16_VAL(p,DIR_LASTACCDATE) +# define DIR_GETFSTCLUSTHI(p) UINT16_VAL(p,DIR_FSTCLUSTHI) +# define DIR_GETWRTTIME(p) UINT16_VAL(p,DIR_WRTTIME) +# define DIR_GETWRTDATE(p) UINT16_VAL(p,DIR_WRTDATE) +# define DIR_GETFSTCLUSTLO(p) UINT16_VAL(p,DIR_FSTCLUSTLO) +# define DIR_GETFILESIZE(p) UINT32_VAL(p,DIR_FILESIZE) + +# ifdef CONFIG_FAT_LFN +# define LDIR_GETWCHAR1(p) UINT16_VAL(p,LDIR_WCHAR1_5) +# define LDIR_GETWCHAR2(p) UINT16_VAL(p,LDIR_WCHAR1_5+2) +# define LDIR_GETWCHAR3(p) UINT16_VAL(p,LDIR_WCHAR1_5+4) +# define LDIR_GETWCHAR4(p) UINT16_VAL(p,LDIR_WCHAR1_5+6) +# define LDIR_GETWCHAR5(p) UINT16_VAL(p,LDIR_WCHAR1_5+8) +# define LDIR_GETWCHAR6(p) UINT16_VAL(p,LDIR_WCHAR6_11) +# define LDIR_GETWCHAR7(p) UINT16_VAL(p,LDIR_WCHAR6_11+2) +# define LDIR_GETWCHAR8(p) UINT16_VAL(p,LDIR_WCHAR6_11+4) +# define LDIR_GETWCHAR9(p) UINT16_VAL(p,LDIR_WCHAR6_11+6) +# define LDIR_GETWCHAR10(p) UINT16_VAL(p,LDIR_WCHAR6_11+8) +# define LDIR_GETWCHAR11(p) UINT16_VAL(p,LDIR_WCHAR6_11+10) +# define LDIR_GETWCHAR12(p) UINT16_VAL(p,LDIR_WCHAR12_13) +# define LDIR_GETWCHAR13(p) UINT16_VAL(p,LDIR_WCHAR12_13+2) +# endif + +# define FSI_GETLEADSIG(p) UINT32_VAL(p,FSI_LEADSIG) +# define FSI_GETSTRUCTSIG(p) UINT32_VAL(p,FSI_STRUCTSIG) +# define FSI_GETFREECOUNT(p) UINT32_VAL(p,FSI_FREECOUNT) +# define FSI_GETNXTFREE(p) UINT32_VAL(p,FSI_NXTFREE) +# define FSI_GETTRAILSIG(p) UINT32_VAL(p,FSI_TRAILSIG) + +# define FAT_GETFAT16(p,i) UINT16_VAL(p,i) +# define FAT_GETFAT32(p,i) UINT32_VAL(p,i) + +# define MBR_PUTRESVDSECCOUNT(p,v) UINT16_PUT(p,BS_RESVDSECCOUNT,v) +# define MBR_PUTFATSZ16(p,v) UINT16_PUT(p,BS_FATSZ16,v) +# define MBR_PUTSECPERTRK(p,v) UINT16_PUT(p,BS_SECPERTRK,v) +# define MBR_PUTNUMHEADS(p,v) UINT16_PUT(p,BS_NUMHEADS,v) +# define MBR_PUTHIDSEC(p,v) UINT32_PUT(p,BS_HIDSEC,v) +# define MBR_PUTTOTSEC32(p,v) UINT32_PUT(p,BS_TOTSEC32,v) +# define MBR_PUTFATSZ32(p,v) UINT32_PUT(p,BS32_FATSZ32,v) +# define MBR_PUTEXTFLAGS(p,v) UINT16_PUT(p,BS32_EXTFLAGS,v) +# define MBR_PUTFSVER(p,v) UINT16_PUT(p,BS32_FSVER,v) +# define MBR_PUTROOTCLUS(p,v) UINT32_PUT(p,BS32_ROOTCLUS,v) +# define MBR_PUTFSINFO(p,v) UINT16_PUT(p,BS32_FSINFO,v) +# define MBR_PUTBKBOOTSEC(p,v) UINT16_PUT(p,BS32_BKBOOTSEC,v) +# define MBR_PUTSIGNATURE(p,v) UINT16_PUT(p,BS_SIGNATURE,v) + +# define FSI_PUTLEADSIG(p,v) UINT32_PUT(p,FSI_LEADSIG,v) +# define FSI_PUTSTRUCTSIG(p,v) UINT32_PUT(p,FSI_STRUCTSIG,v) +# define FSI_PUTFREECOUNT(p,v) UINT32_PUT(p,FSI_FREECOUNT,v) +# define FSI_PUTNXTFREE(p,v) UINT32_PUT(p,FSI_NXTFREE,v) +# define FSI_PUTTRAILSIG(p,v) UINT32_PUT(p,FSI_TRAILSIG,v) + +# define DIR_PUTCRTIME(p,v) UINT16_PUT(p,DIR_CRTIME,v) +# define DIR_PUTCRDATE(p,v) UINT16_PUT(p,DIR_CRDATE,v) +# define DIR_PUTLASTACCDATE(p,v) UINT16_PUT(p,DIR_LASTACCDATE,v) +# define DIR_PUTFSTCLUSTHI(p,v) UINT16_PUT(p,DIR_FSTCLUSTHI,v) +# define DIR_PUTWRTTIME(p,v) UINT16_PUT(p,DIR_WRTTIME,v) +# define DIR_PUTWRTDATE(p,v) UINT16_PUT(p,DIR_WRTDATE,v) +# define DIR_PUTFSTCLUSTLO(p,v) UINT16_PUT(p,DIR_FSTCLUSTLO,v) +# define DIR_PUTFILESIZE(p,v) UINT32_PUT(p,DIR_FILESIZE,v) + +# ifdef CONFIG_FAT_LFN +# define LDIR_PUTWCHAR1(p,v) UINT16_PUT(p,LDIR_WCHAR1_5,v) +# define LDIR_PUTWCHAR2(p,v) UINT16_PUT(p,LDIR_WCHAR1_5+2,v) +# define LDIR_PUTWCHAR3(p,v) UINT16_PUT(p,LDIR_WCHAR1_5+4,v) +# define LDIR_PUTWCHAR4(p,v) UINT16_PUT(p,LDIR_WCHAR1_5+6,v) +# define LDIR_PUTWCHAR5(p,v) UINT16_PUT(p,LDIR_WCHAR1_5+8,v) +# define LDIR_PUTWCHAR6(p,v) UINT16_PUT(p,LDIR_WCHAR6_11,v) +# define LDIR_PUTWCHAR7(p,v) UINT16_PUT(p,LDIR_WCHAR6_11+2,v) +# define LDIR_PUTWCHAR8(p,v) UINT16_PUT(p,LDIR_WCHAR6_11+4,v) +# define LDIR_PUTWCHAR9(p,v) UINT16_PUT(p,LDIR_WCHAR6_11+6,v) +# define LDIR_PUTWCHAR10(p,v) UINT16_PUT(p,LDIR_WCHAR6_11+8,v) +# define LDIR_PUTWCHAR11(p,v) UINT16_PUT(p,LDIR_WCHAR6_11+10,v) +# define LDIR_PUTWCHAR12(p,v) UINT16_PUT(p,LDIR_WCHAR12_13,v) +# define LDIR_PUTWCHAR13(p,v) UINT16_PUT(p,LDIR_WCHAR12_13+2,v) +# endif + +# define FSI_PUTLEADSIG(p,v) UINT32_PUT(p,FSI_LEADSIG,v) +# define FSI_PUTSTRUCTSIG(p,v) UINT32_PUT(p,FSI_STRUCTSIG,v) +# define FSI_PUTFREECOUNT(p,v) UINT32_PUT(p,FSI_FREECOUNT,v) +# define FSI_PUTNXTFREE(p,v) UINT32_PUT(p,FSI_NXTFREE,v) +# define FSI_PUTTRAILSIG(p,v) UINT32_PUT(p,FSI_TRAILSIG,v) + +# define FAT_PUTFAT16(p,i,v) UINT16_PUT(p,i,v) +# define FAT_PUTFAT32(p,i,v) UINT32_PUT(p,i,v) + +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This structure represents the overall mountpoint state. An instance of this + * structure is retained as inode private data on each mountpoint that is + * mounted with a fat32 filesystem. + */ + +struct fat_file_s; +struct fat_mountpt_s +{ + struct inode *fs_blkdriver; /* The block driver inode that hosts the FAT32 fs */ + struct fat_file_s *fs_head; /* A list to all files opened on this mountpoint */ + + sem_t fs_sem; /* Used to assume thread-safe access */ + off_t fs_hwsectorsize; /* HW: Sector size reported by block driver*/ + off_t fs_hwnsectors; /* HW: The number of sectors reported by the hardware */ + off_t fs_fatbase; /* Logical block of start of filesystem (past resd sectors) */ + off_t fs_rootbase; /* MBR: Cluster no. of 1st cluster of root dir */ + off_t fs_database; /* Logical block of start data sectors */ + off_t fs_fsinfo; /* MBR: Sector number of FSINFO sector */ + off_t fs_currentsector; /* The sector number buffered in fs_buffer */ + uint32_t fs_nclusters; /* Maximum number of data clusters */ + uint32_t fs_nfatsects; /* MBR: Count of sectors occupied by one fat */ + uint32_t fs_fattotsec; /* MBR: Total count of sectors on the volume */ + uint32_t fs_fsifreecount; /* FSI: Last free cluster count on volume */ + uint32_t fs_fsinextfree; /* FSI: Cluster number of 1st free cluster */ + uint16_t fs_fatresvdseccount; /* MBR: The total number of reserved sectors */ + uint16_t fs_rootentcnt; /* MBR: Count of 32-bit root directory entries */ + bool fs_mounted; /* true: The file system is ready */ + bool fs_dirty; /* true: fs_buffer is dirty */ + bool fs_fsidirty; /* true: FSINFO sector must be written to disk */ + uint8_t fs_type; /* FSTYPE_FAT12, FSTYPE_FAT16, or FSTYPE_FAT32 */ + uint8_t fs_fatnumfats; /* MBR: Number of FATs (probably 2) */ + uint8_t fs_fatsecperclus; /* MBR: Sectors per allocation unit: 2**n, n=0..7 */ + uint8_t *fs_buffer; /* This is an allocated buffer to hold one sector + * from the device */ +}; + +/* This structure represents on open file under the mountpoint. An instance + * of this structure is retained as struct file specific information on each + * opened file. + */ + +struct fat_file_s +{ + struct fat_file_s *ff_next; /* Retained in a singly linked list */ + bool ff_open; /* true: The file is (still) open */ + uint8_t ff_bflags; /* The file buffer flags */ + uint8_t ff_oflags; /* Flags provided when file was opened */ + uint8_t ff_sectorsincluster; /* Sectors remaining in cluster */ + uint16_t ff_dirindex; /* Index into ff_dirsector to directory entry */ + uint32_t ff_currentcluster; /* Current cluster being accessed */ + off_t ff_dirsector; /* Sector containing the directory entry */ + off_t ff_size; /* Size of the file in bytes */ + off_t ff_startcluster; /* Start cluster of file on media */ + off_t ff_currentsector; /* Current sector being operated on */ + off_t ff_cachesector; /* Current sector in the file buffer */ + uint8_t *ff_buffer; /* File buffer (for partial sector accesses) */ +}; + +/* This structure holds the sequency of directory entries used by one + * file element (directory or file). For short file names, this is + * single diretory entry. But for long file names, the is a sequence + * of directory entries. Long directory name entries appear in reverse + * order: Last, next-to-last, ..., first. The "first" long file name + * directory is then following by the short directory name entry. The + * short file name entry contains the real meat of the file data. + * + * So it takes the sector number and entry offset of the last long + * file name entry and of the short file name entry to define the + * sequence. In the case of short file names, the sector number and + * offset will be the same. + */ + +struct fat_dirseq_s +{ + /* Sector offsets */ + + uint16_t ds_offset; /* Sector offset to short file name entry */ +#ifdef CONFIG_FAT_LFN + uint16_t ds_lfnoffset; /* Sector offset to last long file name entry */ +#endif + + /* Sector and cluster numbers */ + + off_t ds_sector; /* Sector of the short file name entry */ +#ifdef CONFIG_FAT_LFN + off_t ds_cluster; /* Cluster containing the short file name entry */ + off_t ds_lfnsector; /* Sector of the last long name entry */ + off_t ds_lfncluster; /* Cluster containing the long file name entry */ + off_t ds_startsector; /* Starting sector of the directory */ +#endif +}; + +/* This structure is used internally for describing directory entries */ + +struct fat_dirinfo_s +{ + /* The file/directory name */ + +#ifdef CONFIG_FAT_LFN + uint8_t fd_lfname[LDIR_MAXFNAME+1]; /* Long filename with terminator */ +#endif + uint8_t fd_name[DIR_MAXFNAME]; /* Short 8.3 alias filename (no terminator) */ + + /* NT flags are not used */ + +#ifdef CONFIG_FAT_LCNAMES + uint8_t fd_ntflags; /* NTRes lower case flags */ +#endif + + /* TRUE if this is the root directory */ + + bool fd_root; + + /* The following provides the sequence of directory entries used by the + * file or directory. + */ + + struct fat_dirseq_s fd_seq; /* Directory sequence */ + + /* This is part of the opendir, readdir, ... logic */ + + struct fs_fatdir_s dir; /* Used with opendir, readdir, etc. */ +}; + +/* Generic helper macros ****************************************************/ + +#ifndef MIN +# define MIN(a,b) (a < b ? a : b) +#endif + +#ifndef MAX +# define MAX(a,b) (a > b ? a : b) +#endif + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Utitilies to handle unaligned or byte swapped accesses */ + +EXTERN uint16_t fat_getuint16(uint8_t *ptr); +EXTERN uint32_t fat_getuint32(uint8_t *ptr); +EXTERN void fat_putuint16(uint8_t *ptr, uint16_t value16); +EXTERN void fat_putuint32(uint8_t *ptr, uint32_t value32); + +/* Manage the per-mount semaphore that protects access to shared resources */ + +EXTERN void fat_semtake(struct fat_mountpt_s *fs); +EXTERN void fat_semgive(struct fat_mountpt_s *fs); + +/* Get the current time for FAT creation and write times */ + +EXTERN uint32_t fat_systime2fattime(void); +EXTERN time_t fat_fattime2systime(uint16_t fattime, uint16_t fatdate); + +/* Handle hardware interactions for mounting */ + +EXTERN int fat_mount(struct fat_mountpt_s *fs, bool writeable); +EXTERN int fat_checkmount(struct fat_mountpt_s *fs); + +/* low-level hardware access */ + +EXTERN int fat_hwread(struct fat_mountpt_s *fs, uint8_t *buffer, + off_t sector, unsigned int nsectors); +EXTERN int fat_hwwrite(struct fat_mountpt_s *fs, uint8_t *buffer, + off_t sector, unsigned int nsectors); + +/* Cluster / cluster chain access helpers */ + +EXTERN off_t fat_cluster2sector(struct fat_mountpt_s *fs, uint32_t cluster); +EXTERN off_t fat_getcluster(struct fat_mountpt_s *fs, uint32_t clusterno); +EXTERN int fat_putcluster(struct fat_mountpt_s *fs, uint32_t clusterno, + off_t startsector); +EXTERN int fat_removechain(struct fat_mountpt_s *fs, uint32_t cluster); +EXTERN int32_t fat_extendchain(struct fat_mountpt_s *fs, uint32_t cluster); + +#define fat_createchain(fs) fat_extendchain(fs, 0) + +/* Help for traversing directory trees and accessing directory entries */ + +EXTERN int fat_nextdirentry(struct fat_mountpt_s *fs, struct fs_fatdir_s *dir); +EXTERN int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo, + const char *path); +EXTERN int fat_dirnamewrite(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo); +EXTERN int fat_dirwrite(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo, + uint8_t attributes, uint32_t fattime); +EXTERN int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo); +EXTERN int fat_freedirentry(struct fat_mountpt_s *fs, struct fat_dirseq_s *seq); +EXTERN int fat_dirname2path(struct fat_mountpt_s *fs, struct fs_dirent_s *dir); + +/* File creation and removal helpers */ + +EXTERN int fat_dirtruncate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo); +EXTERN int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo); +EXTERN int fat_remove(struct fat_mountpt_s *fs, const char *relpath, bool directory); + +/* Mountpoint and file buffer cache (for partial sector accesses) */ + +EXTERN int fat_fscacheflush(struct fat_mountpt_s *fs); +EXTERN int fat_fscacheread(struct fat_mountpt_s *fs, off_t sector); +EXTERN int fat_ffcacheflush(struct fat_mountpt_s *fs, struct fat_file_s *ff); +EXTERN int fat_ffcacheread(struct fat_mountpt_s *fs, struct fat_file_s *ff, off_t sector); +EXTERN int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff); + +/* FSINFO sector support */ + +EXTERN int fat_updatefsinfo(struct fat_mountpt_s *fs); +EXTERN int fat_nfreeclusters(struct fat_mountpt_s *fs, off_t *pfreeclusters); +EXTERN int fat_currentsector(struct fat_mountpt_s *fs, struct fat_file_s *ff, off_t position); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __FS_FAT_FS_FAT32_H */ diff --git a/nuttx/fs/fat/fs_fat32attrib.c b/nuttx/fs/fat/fs_fat32attrib.c new file mode 100644 index 0000000000..f58ed81bb2 --- /dev/null +++ b/nuttx/fs/fat/fs_fat32attrib.c @@ -0,0 +1,189 @@ +/**************************************************************************** + * fs/fat/fs_fat32attrib.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "fs_internal.h" +#include "fs_fat32.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fat_attrib + ****************************************************************************/ + +static int fat_attrib(const char *path, fat_attrib_t *retattrib, + fat_attrib_t setbits, fat_attrib_t clearbits) +{ + struct fat_mountpt_s *fs; + struct fat_dirinfo_s dirinfo; + FAR struct inode *inode; + const char *relpath = NULL; + uint8_t *direntry; + uint8_t oldattributes; + uint8_t newattributes; + int ret; + + /* Get an inode for this file */ + + inode = inode_find(path, &relpath); + if (!inode) + { + /* There is no mountpoint that includes in this path */ + + ret = ENOENT; + goto errout; + } + + /* Verify that the inode is a valid mountpoint. */ + + if (!INODE_IS_MOUNTPT(inode) || !inode->u.i_mops || !inode->i_private) + { + ret = ENXIO; + goto errout_with_inode; + } + + /* Get the mountpoint private data from the inode structure */ + + fs = inode->i_private; + + /* Check if the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Find the file/directory entry for the oldrelpath */ + + ret = fat_finddirentry(fs, &dirinfo, relpath); + if (ret != OK) + { + /* Some error occurred -- probably -ENOENT */ + + goto errout_with_semaphore; + } + + /* Make sure that we found some valid file or directory */ + + if (dirinfo.fd_root) + { + /* Ooops.. we found the root directory */ + + ret = EACCES; + goto errout_with_semaphore; + } + + /* Get the current attributes */ + + direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset]; + oldattributes = DIR_GETATTRIBUTES(direntry); + newattributes = oldattributes; + + /* Set or clear any bits as requested */ + + newattributes &= ~(clearbits & (FATATTR_READONLY|FATATTR_HIDDEN|FATATTR_SYSTEM|FATATTR_ARCHIVE)); + newattributes |= (setbits & (FATATTR_READONLY|FATATTR_HIDDEN|FATATTR_SYSTEM|FATATTR_ARCHIVE)); + + /* Did any thingchange? */ + + if (newattributes != oldattributes) + { + DIR_PUTATTRIBUTES(direntry, newattributes); + fs->fs_dirty = true; + ret = fat_updatefsinfo(fs); + if (ret != OK) + { + ret = -ret; + goto errout_with_semaphore; + } + } + + /* Success */ + + if (retattrib) + { + *retattrib = newattributes; + } + + fat_semgive(fs); + inode_release(inode); + return OK; + +errout_with_semaphore: + fat_semgive(fs); +errout_with_inode: + inode_release(inode); +errout: + *get_errno_ptr() = ret; + return ERROR; +} + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fat_getattrib + ****************************************************************************/ + +int fat_getattrib(const char *path, fat_attrib_t *attrib) +{ + return fat_attrib(path, attrib, 0, 0); +} + +/**************************************************************************** + * Name: fat_setattrib + ****************************************************************************/ + +int fat_setattrib(const char *path, fat_attrib_t setbits, fat_attrib_t clearbits) +{ + return fat_attrib(path, NULL, setbits, clearbits); +} + diff --git a/nuttx/fs/fat/fs_fat32dirent.c b/nuttx/fs/fat/fs_fat32dirent.c new file mode 100644 index 0000000000..742fa1eeb3 --- /dev/null +++ b/nuttx/fs/fat/fs_fat32dirent.c @@ -0,0 +1,2947 @@ +/**************************************************************************** + * fs/fat/fs_fat32dirent.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * NOTE: If CONFIG_FAT_LFN is defined, then there may be some legal, patent + * issues. The following was extracted from the entry "File Allocation Table + * from Wikipedia, the free encyclopedia: + * + * "On December 3, 2003 Microsoft announced it would be offering licenses + * for use of its FAT specification and 'associated intellectual property', + * at the cost of a US$0.25 royalty per unit sold, with a $250,000 maximum + * royalty per license agreement. + * + * o "U.S. Patent 5,745,902 (http://www.google.com/patents?vid=5745902) - + * Method and system for accessing a file using file names having + * different file name formats. ... + * o "U.S. Patent 5,579,517 (http://www.google.com/patents?vid=5579517) - + * Common name space for long and short filenames. ... + * o "U.S. Patent 5,758,352 (http://www.google.com/patents?vid=5758352) - + * Common name space for long and short filenames. ... + * o "U.S. Patent 6,286,013 (http://www.google.com/patents?vid=6286013) - + * Method and system for providing a common name space for long and + * short file names in an operating system. ... + * + * "Many technical commentators have concluded that these patents only cover + * FAT implementations that include support for long filenames, and that + * removable solid state media and consumer devices only using short names + * would be unaffected. ..." + * + * So you have been forewarned: Use the long filename at your own risk! + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "fs_internal.h" +#include "fs_fat32.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +enum fat_case_e +{ + FATCASE_UNKNOWN = 0, + FATCASE_UPPER, + FATCASE_LOWER +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static uint8_t fat_lfnchecksum(const uint8_t *sfname); +#endif +static inline int fat_parsesfname(const char **path, + struct fat_dirinfo_s *dirinfo, + char *terminator); +#ifdef CONFIG_FAT_LFN +static inline int fat_parselfname(const char **path, + struct fat_dirinfo_s *dirinfo, + char *terminator); +static inline int fat_createalias(struct fat_dirinfo_s *dirinfo); +static inline int fat_findalias(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo); +static inline int fat_uniquealias(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo); +#endif +static int fat_path2dirname(const char **path, struct fat_dirinfo_s *dirinfo, + char *terminator); +static int fat_findsfnentry(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo); +#ifdef CONFIG_FAT_LFN +static bool fat_cmplfnchunk(uint8_t *chunk, const uint8_t *substr, int nchunk); +static bool fat_cmplfname(const uint8_t *direntry, const uint8_t *substr); +static inline int fat_findlfnentry(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo); + +#endif +static inline int fat_allocatesfnentry(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo); +#ifdef CONFIG_FAT_LFN +static inline int fat_allocatelfnentry(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo); +#endif +static inline int fat_getsfname(uint8_t *direntry, char *buffer, + unsigned int buflen); +#ifdef CONFIG_FAT_LFN +static void fat_getlfnchunk(uint8_t *chunk, uint8_t *dest, int nchunk); +static inline int fat_getlfname(struct fat_mountpt_s *fs, struct fs_dirent_s *dir); +#endif +static int fat_putsfname(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo); +#ifdef CONFIG_FAT_LFN +static void fat_initlfname(uint8_t *chunk, int nchunk); +static void fat_putlfnchunk(uint8_t *chunk, const uint8_t *src, int nchunk); +static int fat_putlfname(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo); +#endif +static int fat_putsfdirentry(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo, + uint8_t attributes, uint32_t fattime); + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fat_lfnchecksum + * + * Desciption: Caculate the checksum of . + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static uint8_t fat_lfnchecksum(const uint8_t *sfname) +{ + uint8_t sum = 0; + int i; + + for (i = DIR_MAXFNAME; i; i--) + { + sum = ((sum & 1) << 7) + (sum >> 1) + *sfname++; + } + + return sum; +} +#endif + +/**************************************************************************** + * Name: fat_parsesfname + * + * Desciption: Convert a user filename into a properly formatted FAT + * (short 8.3) filename as it would appear in a directory entry. Here are + * the rules for the 8+3 short file name in the directory: + * + * The first byte: + * + * 0xe5 = The directory is free + * 0x00 = This directory and all following directories are free + * 0x05 = Really 0xe5 + * 0x20 = May NOT be ' ' + * + * Other characters may be any characters except for the following: + * + * 0x00-0x1f = (except for 0x00 and 0x05 in the first byte) + * 0x22 = '"' + * 0x2a-0x2c = '*', '+', ',' + * 0x2e-0x2f = '.', '/' + * 0x3a-0x3f = ':', ';', '<', '=', '>', '?' + * 0x5b-0x5d = '[', '\\', ;]' + * 0x7c = '|' + * + * '.' May only occur once within string and only within the first 9 + * bytes. The '.' is not save in the directory, but is implicit in + * 8+3 format. + * + * Lower case characters are not allowed in directory names (without some + * poorly documented operations on the NTRes directory byte). Lower case + * codes may represent different characters in other character sets ("DOS + * code pages". The logic below does not, at present, support any other + * character sets. + * + * Returned value: + * OK - The path refers to a valid 8.3 FAT file name and has been properly + * converted and stored in dirinfo. + * <0 - Otherwise an negated error is returned meaning that the string is + * not a valid 8+3 because: + * + * 1. Contains characters not in the printable character set, + * 2. Contains forbidden characters or multiple '.' characters + * 3. File name or extension is too long. + * + * If CONFIG_FAT_LFN is defined and CONFIG_FAT_LCNAMES is NOT + * defined, then: + * + * 4a. File name or extension contains lower case characters. + * + * If CONFIG_FAT_LFN is defined and CONFIG_FAT_LCNAMES is defined, + * then: + * + * 4b. File name or extension is not all the same case. + * + ****************************************************************************/ + +static inline int fat_parsesfname(const char **path, + struct fat_dirinfo_s *dirinfo, + char *terminator) +{ +#ifdef CONFIG_FAT_LCNAMES + unsigned int ntlcenable = FATNTRES_LCNAME | FATNTRES_LCEXT; + unsigned int ntlcfound = 0; +#ifdef CONFIG_FAT_LFN + enum fat_case_e namecase = FATCASE_UNKNOWN; + enum fat_case_e extcase = FATCASE_UNKNOWN; +#endif +#endif + const char *node = *path; + int endndx; + uint8_t ch; + int ndx = 0; + + /* Initialized the name with all spaces */ + + memset(dirinfo->fd_name, ' ', DIR_MAXFNAME); + + /* Loop until the name is successfully parsed or an error occurs */ + + endndx = 8; + for (;;) + { + /* Get the next byte from the path */ + + ch = *node++; + + /* Check if this the last byte in this node of the name */ + + if ((ch == '\0' || ch == '/') && ndx != 0 ) + { + /* Return the accumulated NT flags and the terminating character */ + +#ifdef CONFIG_FAT_LCNAMES + dirinfo->fd_ntflags = ntlcfound & ntlcenable; +#endif + *terminator = ch; + *path = node; + return OK; + } + + /* Accept only the printable character set (excluding space). Note + * that the first byte of the name could be 0x05 meaning that is it + * 0xe5, but this is not a printable character in this character in + * either case. + */ + + else if (!isgraph(ch)) + { + goto errout; + } + + /* Check for transition from name to extension. Only one '.' is + * permitted and it must be within first 9 characters + */ + + else if (ch == '.' && endndx == 8) + { + /* Starting the extension */ + + ndx = 8; + endndx = 11; + continue; + } + + /* Reject printable characters forbidden by FAT */ + + else if (ch == '"' || (ch >= '*' && ch <= ',') || + ch == '.' || ch == '/' || + (ch >= ':' && ch <= '?') || + (ch >= '[' && ch <= ']') || + (ch == '|')) + { + goto errout; + } + + /* Check for upper case characters */ + +#ifdef CONFIG_FAT_LCNAMES + else if (isupper(ch)) + { + /* Some or all of the characters in the name or extension + * are upper case. Force all of the characters to be interpreted + * as upper case. + */ + + if (endndx == 8) + { + /* Is there mixed case in the name? */ + +#ifdef CONFIG_FAT_LFN + if (namecase == FATCASE_LOWER) + { + /* Mixed case in the name -- use the long file name */ + + goto errout; + } + + /* So far, only upper case in the name*/ + + namecase = FATCASE_UPPER; +#endif + + /* Clear lower case name bit in mask*/ + + ntlcenable &= ~FATNTRES_LCNAME; + } + else + { + /* Is there mixed case in the extension? */ + +#ifdef CONFIG_FAT_LFN + if (extcase == FATCASE_LOWER) + { + /* Mixed case in the extension -- use the long file name */ + + goto errout; + } + + /* So far, only upper case in the extension*/ + + extcase = FATCASE_UPPER; +#endif + + /* Clear lower case extension in mask */ + + ntlcenable &= ~FATNTRES_LCEXT; + } + } +#endif + + /* Check for lower case characters */ + + else if (islower(ch)) + { +#if defined(CONFIG_FAT_LFN) && !defined(CONFIG_FAT_LCNAMES) + /* If lower case characters are present, then a long file + * name will be constructed. + */ + + goto errout; +#else + /* Convert the character to upper case */ + + ch = toupper(ch); + + /* Some or all of the characters in the name or extension + * are lower case. They can be interpreted as lower case if + * only if all of the characters in the name or extension are + * lower case. + */ + +#ifdef CONFIG_FAT_LCNAMES + if (endndx == 8) + { + /* Is there mixed case in the name? */ + +#ifdef CONFIG_FAT_LFN + if (namecase == FATCASE_UPPER) + { + /* Mixed case in the name -- use the long file name */ + + goto errout; + } + + /* So far, only lower case in the name*/ + + namecase = FATCASE_LOWER; +#endif + + /* Set lower case name bit */ + + ntlcfound |= FATNTRES_LCNAME; + } + else + { + /* Is there mixed case in the extension? */ + +#ifdef CONFIG_FAT_LFN + if (extcase == FATCASE_UPPER) + { + /* Mixed case in the extension -- use the long file name */ + + goto errout; + } + + /* So far, only lower case in the extension*/ + + extcase = FATCASE_LOWER; +#endif + + /* Set lower case extension bit */ + + ntlcfound |= FATNTRES_LCEXT; + } +#endif +#endif /* CONFIG_FAT_LFN && !CONFIG_FAT_LCNAMES */ + } + + /* Check if the file name exceeds the size permitted (without + * long file name support). + */ + + if (ndx >= endndx) + { + goto errout; + } + + /* Save next character in the accumulated name */ + + dirinfo->fd_name[ndx++] = ch; + } + + errout: + return -EINVAL; +} + +/**************************************************************************** + * Name: fat_parselfname + * + * Desciption: Convert a user filename into a properly formatted FAT + * long filename as it would appear in a directory entry. Here are + * the rules for the long file name in the directory: + * + * Valid characters are the same as for short file names EXCEPT: + * + * 1. '+', ',', ';', '=', '[', and ']' are accepted in the file name + * 2. '.' (dot) can occur more than once in a filename. Extension is + * the substring after the last dot. + * + * Returned value: + * OK - The path refers to a valid long file name and has been properly + * stored in dirinfo. + * <0 - Otherwise an negated error is returned meaning that the string is + * not a valid long file name: + * + * 1. Contains characters not in the printable character set, + * 2. Contains forbidden characters + * 3. File name is too long. + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static inline int fat_parselfname(const char **path, + struct fat_dirinfo_s *dirinfo, + char *terminator) +{ + const char *node = *path; + uint8_t ch; + int ndx = 0; + + /* Loop until the name is successfully parsed or an error occurs */ + + for (;;) + { + /* Get the next byte from the path */ + + ch = *node++; + + /* Check if this the last byte in this node of the name */ + + if ((ch == '\0' || ch == '/') && ndx != 0 ) + { + /* Null terminate the string */ + + dirinfo->fd_lfname[ndx] = '\0'; + + /* Return the remaining sub-string and the terminating character. */ + + *terminator = ch; + *path = node; + return OK; + } + + /* Accept only the printable character set (including space) */ + + else if (!isprint(ch)) + { + goto errout; + } + + /* Reject printable characters forbidden by FAT */ + + else if (ch == '"' || ch == '*' || ch == '/' || ch == ':' || + ch == '<' || ch == '>' || ch == '?' || ch == '\\' || + ch == '|') + { + goto errout; + } + + /* Check if the file name exceeds the size permitted. */ + + if (ndx >= LDIR_MAXFNAME) + { + goto errout; + } + + /* Save next character in the accumulated name */ + + dirinfo->fd_lfname[ndx++] = ch; + } + + errout: + dirinfo->fd_lfname[0] = '\0'; + return -EINVAL; +} +#endif + +/**************************************************************************** + * Name: fat_createalias + * + * Desciption: Given a valid long file name, create a short filename alias. + * Here are the rules for creation of the alias: + * + * 1. All uppercase + * 2. All dots except the last deleted + * 3. First 6 (uppercase) characters used as a base + * 4. Then ~1. The number is increased if the file already exists in the + * directory. If the number exeeds >10, then character stripped off the + * base. + * 5. The extension is the first 3 uppercase chars of extension. + * + * This function is called only from fat_putlfname() + * + * Returned value: + * OK - The alias was created correctly. + * <0 - Otherwise an negated error is returned. + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static inline int fat_createalias(struct fat_dirinfo_s *dirinfo) +{ + uint8_t ch; /* Current character being processed */ + char *ext; /* Pointer to the extension substring */ + char *src; /* Pointer to the long file name source */ + int len; /* Total length of the long file name */ + int namechars; /* Number of characters available in long name */ + int extchars; /* Number of characters available in long name extension */ + int endndx; /* Maximum index into the short name array */ + int ndx; /* Index to store next character */ + + /* First, let's decide what is name and what is extension */ + + len = strlen((char*)dirinfo->fd_lfname); + ext = strrchr((char*)dirinfo->fd_lfname, '.'); + if (ext) + { + ptrdiff_t tmp; + + /* ext points to the final '.'. The difference in bytes from the + * beginning of the string is then the name length. + */ + + tmp = ext - (char*)dirinfo->fd_lfname; + namechars = tmp; + + /* And the rest, exluding the '.' is the extension. */ + + extchars = len - namechars - 1; + ext++; + } + else + { + /* No '.' found. It is all name and no extension. */ + + namechars = len; + extchars = 0; + } + + /* Alias are always all upper case */ + +#ifdef CONFIG_FAT_LCNAMES + dirinfo->fd_ntflags = 0; +#endif + + /* Initialized the short name with all spaces */ + + memset(dirinfo->fd_name, ' ', DIR_MAXFNAME); + + /* Handle a special case where there is no name. Windows seems to use + * the extension plus random stuff then ~1 to pat to 8 bytes. Some + * examples: + * + * a.b -> a.b No long name + * a., -> A26BE~1._ Padded name to make unique, _ replaces , + * .b -> B1DD2~1 Extension used as name + * .bbbbbbb -> BBBBBB~1 Extension used as name + * a.bbbbbbb -> AAD39~1.BBB Padded name to make unique. + * aaa.bbbbbbb -> AAA~1.BBBB Not padded, already unique? + * ,.bbbbbbb -> _82AF~1.BBB _ replaces , + * +[],.bbbbbbb -> ____~1.BBB _ replaces +[], + */ + + if (namechars < 1) + { + /* Use the extension as the name */ + + DEBUGASSERT(ext && extchars > 0); + src = ext; + ext = NULL; + namechars = extchars; + extchars = 0; + } + else + { + src = (char*)dirinfo->fd_lfname; + } + + /* Then copy the name and extension, handling upper case conversions and + * excluding forbidden characters. + */ + + ndx = 0; /* Position to write the next name character */ + endndx = 6; /* Maximum index before we write ~! and switch to the extension */ + + for (;;) + { + /* Get the next byte from the path. Break out of the loop if we + * encounter the end of null-terminated the long file name string. + */ + + ch = *src++; + if (ch == '\0') + { + /* This is the end of the source string. Do we need to add ~1. We + * will do that if we were parsing the name part when the endo of + * string was encountered. + */ + + if (endndx == 6) + { + /* Write the ~1 at the end of the name */ + + dirinfo->fd_name[ndx++] = '~'; + dirinfo->fd_name[ndx] = '1'; + } + + /* In any event, we are done */ + + return OK; + } + + /* Exclude those few characters included in long file names, but + * excluded in short file name: '+', ',', ';', '=', '[', ']', and '.' + */ + + if (ch == '+' || ch == ',' || ch == '.' || ch == ';' || + ch == '=' || ch == '[' || ch == ']' || ch == '|') + { + /* Use the underbar character instead */ + + ch = '_'; + } + + /* Handle lower case characters */ + + ch = toupper(ch); + + /* We now have a valid character to add to the name or extension. */ + + dirinfo->fd_name[ndx++] = ch; + + /* Did we just add a character to the name? */ + + if (endndx == 6) + { + /* Decrement the number of characters available in the name + * portion of the long name. + */ + + namechars--; + + /* Is it time to add ~1 to the string? We will do that if + * either (1) we have already added the maximum number of + * characters to the short name, or (2) if there are no further + * characters available in the name portion of the long name. + */ + + if (namechars < 1 || ndx == 6) + { + /* Write the ~1 at the end of the name */ + + dirinfo->fd_name[ndx++] = '~'; + dirinfo->fd_name[ndx] = '1'; + + /* Then switch to the extension (if there is one) */ + + if (!ext || extchars < 1) + { + return OK; + } + + ndx = 8; + endndx = 11; + src = ext; + } + } + + /* No.. we just added a character to the extension */ + + else + { + /* Decrement the number of characters available in the name + * portion of the long name + */ + + extchars--; + + /* Is the extension complete? */ + + if (extchars < 1 || ndx == 11) + { + return OK; + } + } + } +} +#endif + +/**************************************************************************** + * Name: fat_findalias + * + * Desciption: Make sure that the short alias for the long file name is + * unique, ie., that there is no other + * + * NOTE: This function does not restore the directory entry that was in the + * sector cache + * + * Returned value: + * OK - The alias is unique. + * <0 - Otherwise an negated error is returned. + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static inline int fat_findalias(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo) +{ + struct fat_dirinfo_s tmpinfo; + + /* Save the current directory info. */ + + memcpy(&tmpinfo, dirinfo, sizeof(struct fat_dirinfo_s)); + + /* Then re-initialize to the beginning of the current directory, starting + * with the first entry. + */ + + tmpinfo.dir.fd_startcluster = tmpinfo.dir.fd_currcluster; + tmpinfo.dir.fd_currsector = tmpinfo.fd_seq.ds_startsector; + tmpinfo.dir.fd_index = 0; + + /* Search for the single short file name directory entry in this directory */ + + return fat_findsfnentry(fs, &tmpinfo); +} +#endif + +/**************************************************************************** + * Name: fat_uniquealias + * + * Desciption: Make sure that the short alias for the long file name is + * unique, modifying the alias as necessary to assure uniqueness. + * + * NOTE: This function does not restore the directory entry that was in the + * sector cache + * + * information upon return. + * Returned value: + * OK - The alias is unique. + * <0 - Otherwise an negated error is returned. + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static inline int fat_uniquealias(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo) +{ + int tilde; + int lsdigit; + int ret; + int i; + + /* Find the position of the tilde character in the short name. The tilde + * can not occur in positions 0 or 7: + */ + + for (tilde = 1; tilde < 7 && dirinfo->fd_name[tilde] != '~'; tilde++); + if (tilde >= 7) + { + return -EINVAL; + } + + /* The least significant number follows the digit (and must be '1') */ + + lsdigit = tilde + 1; + DEBUGASSERT(dirinfo->fd_name[lsdigit] == '1'); + + /* Search for the single short file name directory entry in this directory */ + + while ((ret = fat_findalias(fs, dirinfo)) == OK) + { + /* Adjust the numeric value after the '~' to make the file name unique */ + + for (i = lsdigit; i > 0; i--) + { + /* If we have backed up to the tilde position, then we have to move + * the tilde back one position. + */ + + if (i == tilde) + { + /* Is there space to back up the tilde? */ + + if (tilde <= 1) + { + /* No.. then we cannot add the name to the directory. + * What is the likelihood of that happening? + */ + + return -ENOSPC; + } + + /* Back up the tilde and break out of the inner loop */ + + tilde--; + dirinfo->fd_name[tilde] = '~'; + dirinfo->fd_name[tilde+1] = '1'; + break; + } + + /* We are not yet at the tilde,. Check if this digit has already + * reached its maximum value. + */ + + else if (dirinfo->fd_name[i] < '9') + { + /* No, it has not.. just increment the LS digit and break out of + * the inner loop. + */ + + dirinfo->fd_name[i]++; + break; + } + + /* Yes.. Reset the digit to '0' and loop to adjust the digit before + * this one. + */ + + else + { + dirinfo->fd_name[i] = '0'; + } + } + } + + /* The while loop terminated because of an error; fat_findalias() + * returned something other than OK. The only acceptable error is + * -ENOENT, meaning that the short file name directory does not + * exist in this directory. + */ + + if (ret == -ENOENT) + { + ret = OK; + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: fat_path2dirname + * + * Desciption: Convert a user filename into a properly formatted FAT + * (short 8.3) filename as it would appear in a directory entry. + * + ****************************************************************************/ + +static int fat_path2dirname(const char **path, struct fat_dirinfo_s *dirinfo, + char *terminator) +{ +#ifdef CONFIG_FAT_LFN + int ret; + + /* Assume no long file name */ + + dirinfo->fd_lfname[0] = '\0'; + + /* Then parse the (assumed) 8+3 short file name */ + + ret = fat_parsesfname(path, dirinfo, terminator); + if (ret < 0) + { + /* No, the name is not a valid short 8+3 file name. Try parsing + * the long file name. + */ + + ret = fat_parselfname(path, dirinfo, terminator); + } + + return ret; +#else + /* Only short, 8+3 filenames supported */ + + return fat_parsesfname(path, dirinfo, terminator); +#endif +} + +/**************************************************************************** + * Name: fat_findsfnentry + * + * Desciption: Find a short file name directory entry. Returns OK if the + * directory exists; -ENOENT if it does not. + * + ****************************************************************************/ + +static int fat_findsfnentry(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo) +{ + uint16_t diroffset; + uint8_t *direntry; +#ifdef CONFIG_FAT_LFN + off_t startsector; +#endif + int ret; + + /* Save the starting sector of the directory. This is not really needed + * for short name entries, but this keeps things consistent with long + * file name entries.. + */ + +#ifdef CONFIG_FAT_LFN + startsector = dirinfo->dir.fd_currsector; +#endif + + /* Search, beginning with the current sector, for a directory entry with + * the matching short name + */ + + for (;;) + { + /* Read the next sector into memory */ + + ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector); + if (ret < 0) + { + return ret; + } + + /* Get a pointer to the directory entry */ + + diroffset = DIRSEC_BYTENDX(fs, dirinfo->dir.fd_index); + direntry = &fs->fs_buffer[diroffset]; + + /* Check if we are at the end of the directory */ + + if (direntry[DIR_NAME] == DIR0_ALLEMPTY) + { + return -ENOENT; + } + + /* Check if we have found the directory entry that we are looking for */ + + if (direntry[DIR_NAME] != DIR0_EMPTY && + !(DIR_GETATTRIBUTES(direntry) & FATATTR_VOLUMEID) && + !memcmp(&direntry[DIR_NAME], dirinfo->fd_name, DIR_MAXFNAME) ) + { + /* Yes.. Return success */ + + dirinfo->fd_seq.ds_sector = fs->fs_currentsector; + dirinfo->fd_seq.ds_offset = diroffset; +#ifdef CONFIG_FAT_LFN + dirinfo->fd_seq.ds_cluster = dirinfo->dir.fd_currcluster; + dirinfo->fd_seq.ds_startsector = startsector; + + /* Position the last long file name directory entry at the same + * position. + */ + + dirinfo->fd_seq.ds_lfnsector = dirinfo->fd_seq.ds_sector; + dirinfo->fd_seq.ds_lfnoffset = dirinfo->fd_seq.ds_offset; + dirinfo->fd_seq.ds_lfncluster = dirinfo->fd_seq.ds_cluster; +#endif + return OK; + } + + /* No... get the next directory index and try again */ + + if (fat_nextdirentry(fs, &dirinfo->dir) != OK) + { + return -ENOENT; + } + } +} + +/**************************************************************************** + * Name: fat_cmplfnchunk + * + * Desciption: There are 13 characters per LFN entry, broken up into three + * chunks for characts 1-5, 6-11, and 12-13. This function will perform + * the comparison of a single chunk. + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static bool fat_cmplfnchunk(uint8_t *chunk, const uint8_t *substr, int nchunk) +{ + wchar_t wch; + uint8_t ch; + int i; + + /* Check bytes 1-nchunk */ + + for (i = 0; i < nchunk; i++) + { + /* Get the next character from the name string (which might be the NUL + * terminating character). + */ + + if (*substr == '\0') + { + ch = '\0'; + } + else + { + ch = *substr++; + } + + /* Get the next unicode character from the chunk. We only handle + * ASCII. For ASCII, the upper byte should be zero and the lower + * should match the ASCII code. + */ + + wch = (wchar_t)fat_getuint16((uint8_t*)chunk); + if ((wch & 0xff) != (wchar_t)ch) + { + return false; + } + + /* The characters match. If we just matched the NUL terminating + * character, then the strings match and we are finished. + */ + + if (ch == '\0') + { + return true; + } + + /* Try the next character from the directory entry. */ + + chunk += sizeof(wchar_t); + } + + /* All of the characters in the chunk match.. Return success */ + + return true; +} +#endif + +/**************************************************************************** + * Name: fat_cmplfname + * + * Desciption: Given an LFN directory entry, compare a substring of the name + * to a portion in the directory entry. + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static bool fat_cmplfname(const uint8_t *direntry, const uint8_t *substr) +{ + uint8_t *chunk; + int len; + bool match; + + /* How much of string do we have to compare? (including the NUL + * terminator). + */ + + len = strlen((char*)substr) + 1; + + /* Check bytes 1-5 */ + + chunk = LDIR_PTRWCHAR1_5(direntry); + match = fat_cmplfnchunk(chunk, substr, 5); + if (match && len > 5) + { + /* Check bytes 6-11 */ + + chunk = LDIR_PTRWCHAR6_11(direntry); + match = fat_cmplfnchunk(chunk, &substr[5], 6); + if (match && len > 11) + { + /* Check bytes 12-13 */ + + chunk = LDIR_PTRWCHAR12_13(direntry); + match = fat_cmplfnchunk(chunk, &substr[11], 2); + } + } + + return match; +} +#endif + +/**************************************************************************** + * Name: fat_findlfnentry + * + * Desciption: Find a sequence of long file name directory entries. + * + * NOTE: As a side effect, this function returns with the sector containing + * the short file name directory entry in the cache. + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static inline int fat_findlfnentry(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo) +{ + uint16_t diroffset; + uint8_t *direntry; + uint8_t lastseq; + uint8_t seqno; + uint8_t nfullentries; + uint8_t nentries; + uint8_t remainder; + uint8_t checksum = 0; + off_t startsector; + int offset; + int namelen; + int ret; + + /* Get the length of the long file name (size of the fd_lfname array is + * LDIR_MAXFNAME+1 we do not have to check the length of the string). + */ + + namelen = strlen((char*)dirinfo->fd_lfname); + DEBUGASSERT(namelen <= LDIR_MAXFNAME+1); + + /* How many LFN directory entries are we expecting? */ + + nfullentries = namelen / LDIR_MAXLFNCHARS; + remainder = namelen - nfullentries * LDIR_MAXLFNCHARS; + nentries = nfullentries; + if (remainder > 0) + { + nentries++; + } + DEBUGASSERT(nentries > 0 && nentries <= LDIR_MAXLFNS); + + /* This is the first sequency number we are looking for, the sequence + * number of the last LFN entry (remember that they appear in reverse + * order.. from last to first). + */ + + lastseq = LDIR0_LAST | nentries; + seqno = lastseq; + + /* Save the starting sector of the directory. This is needed later to + * re-scan the directory, looking duplicate short alias names. + */ + + startsector = dirinfo->dir.fd_currsector; + + /* Search, beginning with the current sector, for a directory entry this + * the match shore name + */ + + for (;;) + { + /* Read the next sector into memory */ + + ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector); + if (ret < 0) + { + return ret; + } + + /* Get a pointer to the directory entry */ + + diroffset = DIRSEC_BYTENDX(fs, dirinfo->dir.fd_index); + direntry = &fs->fs_buffer[diroffset]; + + /* Check if we are at the end of the directory */ + + if (direntry[DIR_NAME] == DIR0_ALLEMPTY) + { + return -ENOENT; + } + + /* Is this an LFN entry? Does it have the sequence number we are + * looking for? + */ + + if (LDIR_GETATTRIBUTES(direntry) != LDDIR_LFNATTR || + LDIR_GETSEQ(direntry) != seqno) + { + /* No, restart the search at the next entry */ + + seqno = lastseq; + goto next_entry; + } + + /* Yes.. If this is not the "last" LFN entry, then the checksum must + * also be the same. + */ + + if (seqno == lastseq) + { + /* Just save the checksum for subsequent checks */ + + checksum = LDIR_GETCHECKSUM(direntry); + } + + /* Not the first entry in the sequence. Does the checksum match the + * previous sequences? + */ + + else if (checksum != LDIR_GETCHECKSUM(direntry)) + { + /* No, restart the search at the next entry */ + + seqno = lastseq; + goto next_entry; + } + + /* Check if the name substring in this LFN matches the corresponding + * substring of the name we are looking for. + */ + + offset = ((seqno & LDIR0_SEQ_MASK) - 1) * LDIR_MAXLFNCHARS; + if (fat_cmplfname(direntry, &dirinfo->fd_lfname[offset])) + { + /* Yes.. it matches. Check the sequence number. Is this the + * "last" LFN entry (i.e., the one that appears first)? + */ + + if (seqno == lastseq) + { + /* Yes.. Save information about this LFN entry position */ + + dirinfo->fd_seq.ds_lfnsector = fs->fs_currentsector; + dirinfo->fd_seq.ds_lfnoffset = diroffset; + dirinfo->fd_seq.ds_lfncluster = dirinfo->dir.fd_currcluster; + dirinfo->fd_seq.ds_startsector = startsector; + seqno &= LDIR0_SEQ_MASK; + } + + /* Is this the first sequence number (i.e., the LFN entry that + * will appear last)? + */ + + if (seqno == 1) + { + /* We have found all of the LFN entries. The next directory + * entry should be the one containing the short file name + * alias and all of the meat about the file or directory. + */ + + if (fat_nextdirentry(fs, &dirinfo->dir) != OK) + { + return -ENOENT; + } + + /* Make sure that the directory entry is in the sector cache */ + + ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector); + if (ret < 0) + { + return ret; + } + + /* Get a pointer to the directory entry */ + + diroffset = DIRSEC_BYTENDX(fs, dirinfo->dir.fd_index); + direntry = &fs->fs_buffer[diroffset]; + + /* Verify the checksum */ + + if (fat_lfnchecksum(&direntry[DIR_NAME]) == checksum) + { + /* Success! Save the position of the directory entry and + * return success. + */ + + dirinfo->fd_seq.ds_sector = fs->fs_currentsector; + dirinfo->fd_seq.ds_offset = diroffset; + dirinfo->fd_seq.ds_cluster = dirinfo->dir.fd_currcluster; + return OK; + } + + /* Bad news.. reset and continue with this entry (which is + * probably not an LFN entry unless the file systen is + * seriously corrupted. + */ + + seqno = lastseq; + continue; + } + + /* No.. there are more LFN entries to go. Decrement the sequence + * number and check the next directory entry. + */ + + seqno--; + } + else + { + /* No.. the names do not match. Restart the search at the next + * entry. + */ + + seqno = lastseq; + } + + /* Continue at the next directory entry */ + +next_entry: + if (fat_nextdirentry(fs, &dirinfo->dir) != OK) + { + return -ENOENT; + } + } +} +#endif + +/**************************************************************************** + * Name: fat_allocatesfnentry + * + * Desciption: Find a free directory entry for a short file name entry. + * + ****************************************************************************/ + +static inline int fat_allocatesfnentry(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo) +{ + uint16_t diroffset; + uint8_t *direntry; +#ifdef CONFIG_FAT_LFN + off_t startsector; +#endif + uint8_t ch; + int ret; + + /* Save the sector number of the first sector of the directory. We don't + * really need this for short file name entries; this is just done for + * consistency with the long file name logic. + */ + +#ifdef CONFIG_FAT_LFN + startsector = dirinfo->dir.fd_currsector; +#endif + + /* Then search for a free short file name directory entry */ + + for (;;) + { + /* Read the directory sector into fs_buffer */ + + ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector); + if (ret < 0) + { + /* Make sure that the return value is NOT -ENOSPC */ + + return -EIO; + } + + /* Get a pointer to the entry at fd_index */ + + diroffset = (dirinfo->dir.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE; + direntry = &fs->fs_buffer[diroffset]; + + /* Check if this directory entry is empty */ + + ch = direntry[DIR_NAME]; + if (ch == DIR0_ALLEMPTY || ch == DIR0_EMPTY) + { + /* It is empty -- we have found a directory entry */ + + dirinfo->fd_seq.ds_sector = fs->fs_currentsector; + dirinfo->fd_seq.ds_offset = diroffset; +#ifdef CONFIG_FAT_LFN + dirinfo->fd_seq.ds_cluster = dirinfo->dir.fd_currcluster; + dirinfo->fd_seq.ds_startsector = startsector; + + /* Set the "last" long file name offset to the same entry */ + + dirinfo->fd_seq.ds_lfnsector = dirinfo->fd_seq.ds_sector; + dirinfo->fd_seq.ds_lfnoffset = dirinfo->fd_seq.ds_offset; + dirinfo->fd_seq.ds_lfncluster = dirinfo->fd_seq.ds_cluster; +#endif + return OK; + } + + /* It is not empty try the next one */ + + ret = fat_nextdirentry(fs, &dirinfo->dir); + if (ret < 0) + { + /* This will return -ENOSPC if we have examined all of the + * directory entries without finding a free entry. + */ + + return ret; + } + } +} + +/**************************************************************************** + * Name: fat_allocatelfnentry + * + * Desciption: Find a sequence of free directory entries for a several long + * and one short file name entry. + * + * On entry, dirinfo.dir refers to the first interesting entry the directory. + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static inline int fat_allocatelfnentry(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo) +{ + uint16_t diroffset; + uint8_t *direntry; + off_t startsector; + uint8_t nentries; + uint8_t remainder; + uint8_t needed; + uint8_t ch; + int namelen; + int ret; + + /* Get the length of the long file name (size of the fd_lfname array is + * LDIR_MAXFNAME+1 we do not have to check the length of the string). + */ + + namelen = strlen((char *)dirinfo->fd_lfname); + DEBUGASSERT(namelen <= LDIR_MAXFNAME+1); + + /* How many LFN directory entries are we expecting? */ + + nentries = namelen / LDIR_MAXLFNCHARS; + remainder = namelen - nentries * LDIR_MAXLFNCHARS; + if (remainder > 0) + { + nentries++; + } + DEBUGASSERT(nentries > 0 && nentries <= LDIR_MAXLFNS); + + /* Plus another for short file name entry that follows the sequence of LFN + * entries. + */ + + nentries++; + + /* Save the sector number of the first sector of the directory. We will + * need this later for re-scanning the directory to verify that a FAT file + * name is unique. + */ + + startsector = dirinfo->dir.fd_currsector; + + /* Now, search the directory looking for a sequence for free entries that + * long. + */ + + needed = nentries; + for (;;) + { + /* Read the directory sector into fs_buffer */ + + ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector); + if (ret < 0) + { + /* Make sure that the return value is NOT -ENOSPC */ + + return -EIO; + } + + /* Get a pointer to the entry at fd_index */ + + diroffset = (dirinfo->dir.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE; + direntry = &fs->fs_buffer[diroffset]; + + /* Check if this directory entry is empty */ + + ch = LDIR_GETSEQ(direntry); + if (ch == DIR0_ALLEMPTY || ch == DIR0_EMPTY) + { + /* It is empty -- we have found a directory entry. Is this the + * "last" LFN entry (i.e., the one that occurs first)? + */ + + if (needed == nentries) + { + /* Yes.. remember the position of this entry */ + + dirinfo->fd_seq.ds_lfnsector = fs->fs_currentsector; + dirinfo->fd_seq.ds_lfnoffset = diroffset; + dirinfo->fd_seq.ds_lfncluster = dirinfo->dir.fd_currcluster; + dirinfo->fd_seq.ds_startsector = startsector; + } + + /* Is this last entry we need (i.e., the entry for the short + * file name entry)? + */ + + if (needed <= 1) + { + /* Yes.. remember the position of this entry and return + * success. + */ + + dirinfo->fd_seq.ds_sector = fs->fs_currentsector; + dirinfo->fd_seq.ds_offset = diroffset; + dirinfo->fd_seq.ds_cluster = dirinfo->dir.fd_currcluster; + return OK; + } + + /* Otherwise, just decrement the number of directory entries + * needed and continue looking. + */ + + needed--; + } + + /* The directory entry is not available */ + + else + { + /* Reset the search and continue looking */ + + needed = nentries; + } + + /* Try the next directory entry */ + + ret = fat_nextdirentry(fs, &dirinfo->dir); + if (ret < 0) + { + /* This will return -ENOSPC if we have examined all of the + * directory entries without finding a free entry. + */ + + return ret; + } + } +} +#endif + +/**************************************************************************** + * Name: fat_getsfname + * + * Desciption: Get the 8.3 filename from a directory entry. On entry, the + * short file name entry is already in the cache. + * + ****************************************************************************/ + +static inline int fat_getsfname(uint8_t *direntry, char *buffer, + unsigned int buflen) +{ +#ifdef CONFIG_FAT_LCNAMES + uint8_t ntflags; +#endif + int ch; + int ndx; + + /* Check if we will be doing upper to lower case conversions */ + +#ifdef CONFIG_FAT_LCNAMES + ntflags = DIR_GETNTRES(direntry); +#endif + + /* Reserve a byte for the NUL terminator */ + + buflen--; + + /* Get the 8-byte filename */ + + for (ndx = 0; ndx < 8 && buflen > 0; ndx++) + { + /* Get the next filename character from the directory entry */ + + ch = direntry[ndx]; + + /* Any space (or ndx==8) terminates the filename */ + + if (ch == ' ') + { + break; + } + + /* In this version, we never write 0xe5 in the directory filenames + * (because we do not handle any character sets where 0xe5 is valid + * in a filaname), but we could encounted this in a filesystem + * written by some other system + */ + + if (ndx == 0 && ch == DIR0_E5) + { + ch = 0xe5; + } + + /* Check if we should perform upper to lower case conversion + * of the (whole) filename. + */ + +#ifdef CONFIG_FAT_LCNAMES + if (ntflags & FATNTRES_LCNAME && isupper(ch)) + { + ch = tolower(ch); + } +#endif + /* Copy the next character into the filename */ + + *buffer++ = ch; + buflen--; + } + + /* Check if there is an extension */ + + if (direntry[8] != ' ' && buflen > 0) + { + /* Yes, output the dot before the extension */ + + *buffer++ = '.'; + buflen--; + + /* Then output the (up to) 3 character extension */ + + for (ndx = 8; ndx < 11 && buflen > 0; ndx++) + { + /* Get the next extensions character from the directory entry */ + + ch = direntry[DIR_NAME + ndx]; + + /* Any space (or ndx==11) terminates the extension */ + + if (ch == ' ') + { + break; + } + + /* Check if we should perform upper to lower case conversion + * of the (whole) filename. + */ + +#ifdef CONFIG_FAT_LCNAMES + if (ntflags & FATNTRES_LCEXT && isupper(ch)) + { + ch = tolower(ch); + } +#endif + /* Copy the next character into the filename */ + + *buffer++ = ch; + buflen--; + } + } + + /* Put a null terminator at the end of the filename. We don't have to + * check if there is room because we reserved a byte for the NUL + * terminator at the beginning of this function. + */ + + *buffer = '\0'; + return OK; +} + +/**************************************************************************** + * Name: fat_getlfnchunk + * + * Desciption: There are 13 characters per LFN entry, broken up into three + * chunks for characts 1-5, 6-11, and 12-13. This function will get the + * file name characters from one chunk. + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static void fat_getlfnchunk(uint8_t *chunk, uint8_t *dest, int nchunk) +{ + wchar_t wch; + int i; + + /* Copy bytes 1-nchunk */ + + for (i = 0; i < nchunk; i++) + { + /* Get the next unicode character from the chunk. We only handle ASCII. + * For ASCII, the upper byte should be zero and the lower should match + * the ASCII code. + */ + + wch = (wchar_t)fat_getuint16(chunk); + *dest++ = (uint8_t)(wch & 0xff); + chunk += sizeof(wchar_t); + } +} +#endif + +/**************************************************************************** + * Name: fat_getlfname + * + * Desciption: Get the long filename from a sequence of directory entries. + * On entry, the "last" long file name entry is in the cache. Returns with + * the short file name entry in the cache. + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static inline int fat_getlfname(struct fat_mountpt_s *fs, struct fs_dirent_s *dir) +{ + uint8_t lfname[LDIR_MAXLFNCHARS]; + uint16_t diroffset; + uint8_t *direntry; + uint8_t seqno; + uint8_t rawseq; + uint8_t offset; + uint8_t checksum; + int nsrc; + int ret; + int i; + + /* Get a reference to the current directory entry */ + + diroffset = (dir->u.fat.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE; + direntry = &fs->fs_buffer[diroffset]; + + /* Get the starting sequence number */ + + seqno = LDIR_GETSEQ(direntry); + DEBUGASSERT((seqno & LDIR0_LAST) != 0); + + /* Sanity check */ + + rawseq = (seqno & LDIR0_SEQ_MASK); + if (rawseq < 1 || rawseq > LDIR_MAXLFNS) + { + return -EINVAL; + } + + /* Save the checksum value */ + + checksum = LDIR_GETCHECKSUM(direntry); + + /* Loop until the whole file name has been transferred */ + + for (;;) + { + /* Get the string offset associated with the "last" entry. */ + + offset = (rawseq - 1) * LDIR_MAXLFNCHARS; + + /* Will any of this file name fit into the destination buffer? */ + + if (offset < NAME_MAX) + { + /* Yes.. extract and convert the unicode name */ + + fat_getlfnchunk(LDIR_PTRWCHAR1_5(direntry), lfname, 5); + fat_getlfnchunk(LDIR_PTRWCHAR6_11(direntry), &lfname[5], 6); + fat_getlfnchunk(LDIR_PTRWCHAR12_13(direntry), &lfname[11], 2); + + /* Ignore trailing spaces on the "last" directory entry. The + * number of characters avaiable is LDIR_MAXLFNCHARS or that + * minus the number of trailing spaces on the "last" directory + * entry. + */ + + nsrc = LDIR_MAXLFNCHARS; + if ((seqno & LDIR0_LAST) != 0) + { + /* Reduce the number of characters by the number of trailing + * spaces. + */ + + for (; nsrc > 0 && lfname[nsrc-1] == ' '; nsrc--); + + /* Further reduce the length so that it fits in the destination + * buffer. + */ + + if (offset + nsrc > NAME_MAX) + { + nsrc = NAME_MAX - offset; + } + + /* Add a null terminator to the destination string (the actual + * length of the destination buffer is NAME_MAX+1, so the NUL + * terminator will fit). + */ + + dir->fd_dir.d_name[offset+nsrc] = '\0'; + } + + /* Then transfer the characters */ + + for (i = 0; i < nsrc && offset+i < NAME_MAX; i++) + { + dir->fd_dir.d_name[offset+i] = lfname[i]; + } + } + + /* Read next directory entry */ + + if (fat_nextdirentry(fs, &dir->u.fat) != OK) + { + return -ENOENT; + } + + /* Make sure that the directory sector into the sector cache */ + + ret = fat_fscacheread(fs, dir->u.fat.fd_currsector); + if (ret < 0) + { + return ret; + } + + /* Get a reference to the current directory entry */ + + diroffset = (dir->u.fat.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE; + direntry = &fs->fs_buffer[diroffset]; + + /* Get the next expected sequence number. */ + + seqno = --rawseq; + if (seqno < 1) + { + /* We just completed processing the "first" long file name entry + * and we just read the short file name entry. Verify that the + * checksum of the short file name matches the checksum that we + * found in the long file name entries. + */ + + if (fat_lfnchecksum(direntry) == checksum) + { + /* Yes.. return success! */ + + return OK; + } + + /* No, the checksum is bad. */ + + return -EINVAL; + } + + /* Verify the next long file name entry. Is this an LFN entry? Does it + * have the sequence number we are looking for? Does the checksum + * match the previous entries? + */ + + if (LDIR_GETATTRIBUTES(direntry) != LDDIR_LFNATTR || + LDIR_GETSEQ(direntry) != seqno || + LDIR_GETCHECKSUM(direntry) != checksum) + { + return -EINVAL; + } + } +} +#endif + +/**************************************************************************** + * Name: fat_putsfname + * + * Desciption: Write the short directory entry name. + * + * Assumption: The directory sector is in the cache. + * + ****************************************************************************/ + +static int fat_putsfname(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo) +{ + uint8_t *direntry = &fs->fs_buffer[dirinfo->fd_seq.ds_offset]; + + /* Write the short directory entry */ + + memcpy(&direntry[DIR_NAME], dirinfo->fd_name, DIR_MAXFNAME); +#ifdef CONFIG_FAT_LCNAMES + DIR_PUTNTRES(direntry, dirinfo->fd_ntflags); +#else + DIR_PUTNTRES(direntry, 0); +#endif + fs->fs_dirty = true; + return OK; +} + +/**************************************************************************** + * Name: fat_initlfname + * + * Desciption: There are 13 characters per LFN entry, broken up into three + * chunks for characts 1-5, 6-11, and 12-13. This function will put the + * 0xffff characters into one chunk. + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static void fat_initlfname(uint8_t *chunk, int nchunk) +{ + int i; + + /* Initialize unicode characters 1-nchunk */ + + for (i = 0; i < nchunk; i++) + { + /* The write the 16-bit 0xffff character into the directory entry. */ + + fat_putuint16((uint8_t *)chunk, (uint16_t)0xffff); + chunk += sizeof(wchar_t); + } +} +#endif + +/**************************************************************************** + * Name: fat_putlfnchunk + * + * Desciption: There are 13 characters per LFN entry, broken up into three + * chunks for characts 1-5, 6-11, and 12-13. This function will put the + * file name characters into one chunk. + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static void fat_putlfnchunk(uint8_t *chunk, const uint8_t *src, int nchunk) +{ + uint16_t wch; + int i; + + /* Write bytes 1-nchunk */ + + for (i = 0; i < nchunk; i++) + { + /* Get the next ascii character from the name substring and convert it + * to unicode. The upper byte should be zero and the lower should be + * the ASCII code. The write the unicode character into the directory + * entry. + */ + + wch = (uint16_t)*src++; + fat_putuint16(chunk, wch); + chunk += sizeof(wchar_t); + } +} +#endif + +/**************************************************************************** + * Name: fat_putlfname + * + * Desciption: Write the long filename into a sequence of directory entries. + * On entry, the "last" long file name entry is in the cache. Returns with + * the short file name entry in the cache. + * + ****************************************************************************/ + +#ifdef CONFIG_FAT_LFN +static int fat_putlfname(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo) +{ + uint16_t diroffset; + uint8_t *direntry; + uint8_t nfullentries; + uint8_t nentries; + uint8_t remainder; + uint8_t offset; + uint8_t seqno; + uint8_t checksum; + int namelen; + int ret; + + /* Get the length of the long file name (size of the fd_lfname array is + * LDIR_MAXFNAME+1 we do not have to check the length of the string). + * NOTE that remainder is conditionally incremented to include the NUL + * terminating character that may also need be written to the directory + * entry. NUL terminating is not required if length is multiple of + * LDIR_MAXLFNCHARS (13). + */ + + namelen = strlen((char*)dirinfo->fd_lfname); + DEBUGASSERT(namelen <= LDIR_MAXFNAME+1); + + /* How many LFN directory entries do we need to write? */ + + nfullentries = namelen / LDIR_MAXLFNCHARS; + remainder = namelen - nfullentries * LDIR_MAXLFNCHARS; + nentries = nfullentries; + if (remainder > 0) + { + nentries++; + remainder++; + } + DEBUGASSERT(nentries > 0 && nentries <= LDIR_MAXLFNS); + + /* Create the short file name alias */ + + ret = fat_createalias(dirinfo); + if (ret < 0) + { + return ret; + } + + /* Set up the initial positional data */ + + dirinfo->dir.fd_currcluster = dirinfo->fd_seq.ds_lfncluster; + dirinfo->dir.fd_currsector = dirinfo->fd_seq.ds_lfnsector; + dirinfo->dir.fd_index = dirinfo->fd_seq.ds_lfnoffset / DIR_SIZE; + + /* Make sure that the alias is unique in this directory*/ + + ret = fat_uniquealias(fs, dirinfo); + if (ret < 0) + { + return ret; + } + + /* Get the short file name checksum */ + + checksum = fat_lfnchecksum(dirinfo->fd_name); + + /* Setup the starting sequence number */ + + seqno = LDIR0_LAST | nentries; + + /* Make sure that the sector containing the "last" long file name entry + * is in the sector cache (it probably is not). + */ + + ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector); + if (ret < 0) + { + return ret; + } + + /* Now loop, writing each long file name entry */ + + for (;;) + { + /* Get the string offset associated with the directory entry. */ + + offset = (nentries - 1) * LDIR_MAXLFNCHARS; + + /* Get a reference to the current directory entry */ + + diroffset = (dirinfo->dir.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE; + direntry = &fs->fs_buffer[diroffset]; + + /* Is this the "last" LFN directory entry? */ + + if ((seqno & LDIR0_LAST) != 0 && remainder != 0) + { + int nbytes; + + /* Initialize the "last" directory entry name to all 0xffff */ + + fat_initlfname(LDIR_PTRWCHAR1_5(direntry), 5); + fat_initlfname(LDIR_PTRWCHAR6_11(direntry), 6); + fat_initlfname(LDIR_PTRWCHAR12_13(direntry), 2); + + /* Store the tail portion of the long file name in directory entry */ + + nbytes = MIN(5, remainder); + fat_putlfnchunk(LDIR_PTRWCHAR1_5(direntry), + &dirinfo->fd_lfname[offset], nbytes); + remainder -= nbytes; + + if (remainder > 0) + { + nbytes = MIN(6, remainder); + fat_putlfnchunk(LDIR_PTRWCHAR6_11(direntry), + &dirinfo->fd_lfname[offset+5], nbytes); + remainder -= nbytes; + } + + if (remainder > 0) + { + nbytes = MIN(2, remainder); + fat_putlfnchunk(LDIR_PTRWCHAR12_13(direntry), + &dirinfo->fd_lfname[offset+11], nbytes); + remainder -= nbytes; + } + + /* The remainder should now be zero */ + + DEBUGASSERT(remainder == 0); + } + else + { + /* Store a portion long file name in this directory entry */ + + fat_putlfnchunk(LDIR_PTRWCHAR1_5(direntry), + &dirinfo->fd_lfname[offset], 5); + fat_putlfnchunk(LDIR_PTRWCHAR6_11(direntry), + &dirinfo->fd_lfname[offset+5], 6); + fat_putlfnchunk(LDIR_PTRWCHAR12_13(direntry), + &dirinfo->fd_lfname[offset+11], 2); + } + + /* Write the remaining directory entries */ + + LDIR_PUTSEQ(direntry, seqno); + LDIR_PUTATTRIBUTES(direntry, LDDIR_LFNATTR); + LDIR_PUTNTRES(direntry, 0); + LDIR_PUTCHECKSUM(direntry, checksum); + fs->fs_dirty = true; + + /* Read next directory entry */ + + if (fat_nextdirentry(fs, &dirinfo->dir) != OK) + { + return -ENOENT; + } + + /* Make sure that the sector containing the directory entry is in the + * sector cache + */ + + ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector); + if (ret < 0) + { + return ret; + } + + /* Decrement the number of entries and get the next sequence number. */ + + if (--nentries <= 0) + { + /* We have written all of the long file name entries to the media + * and we have the short file name entry in the cache. We can + * just return success. + */ + + return OK; + } + + /* The sequence number is just the number of entries left to be + * written. + */ + + seqno = nentries; + } +} +#endif + +/**************************************************************************** + * Name: fat_putsfdirentry + * + * Desciption: Write a short file name directory entry + * + * Assumption: The directory sector is in the cache. The caller will write + * sector information. + * + ****************************************************************************/ + +static int fat_putsfdirentry(struct fat_mountpt_s *fs, + struct fat_dirinfo_s *dirinfo, + uint8_t attributes, uint32_t fattime) +{ + uint8_t *direntry; + + /* Initialize the 32-byte directory entry */ + + direntry = &fs->fs_buffer[dirinfo->fd_seq.ds_offset]; + memset(direntry, 0, DIR_SIZE); + + /* Directory name info */ + + (void)fat_putsfname(fs, dirinfo); + + /* Set the attribute attribute, write time, creation time */ + + DIR_PUTATTRIBUTES(direntry, attributes); + + /* Set the time information */ + + DIR_PUTWRTTIME(direntry, fattime & 0xffff); + DIR_PUTCRTIME(direntry, fattime & 0xffff); + DIR_PUTWRTDATE(direntry, fattime >> 16); + DIR_PUTCRDATE(direntry, fattime >> 16); + + fs->fs_dirty = true; + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fat_finddirentry + * + * Desciption: Given a path to something that may or may not be in the file + * system, return the description of the directory entry of the requested + * item. + * + * NOTE: As a side effect, this function returns with the sector containing + * the short file name directory entry in the cache. + * + ****************************************************************************/ + +int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo, + const char *path) +{ + off_t cluster; + uint8_t *direntry; + char terminator; + int ret; + + /* Initialize to traverse the chain. Set it to the cluster of the root + * directory + */ + + cluster = fs->fs_rootbase; + if (fs->fs_type == FSTYPE_FAT32) + { + /* For FAT32, the root directory is variable sized and is a cluster + * chain like any other directory. fs_rootbase holds the first + * cluster of the root directory. + */ + + dirinfo->dir.fd_startcluster = cluster; + dirinfo->dir.fd_currcluster = cluster; + dirinfo->dir.fd_currsector = fat_cluster2sector(fs, cluster); + } + else + { + /* For FAT12/16, the first sector of the root directory is a sector + * relative to the first sector of the fat volume. + */ + + dirinfo->dir.fd_startcluster = 0; + dirinfo->dir.fd_currcluster = 0; + dirinfo->dir.fd_currsector = cluster; + } + + /* fd_index is the index into the current directory table. It is set to the + * the first, entry in the root directory. + */ + + dirinfo->dir.fd_index = 0; + + /* If no path was provided, then the root directory must be exactly what + * the caller is looking for. + */ + + if (*path == '\0') + { + dirinfo->fd_root = true; + return OK; + } + + /* This is not the root directory */ + + dirinfo->fd_root = false; + + /* Now loop until the directory entry corresponding to the path is found */ + + for (;;) + { + /* Convert the next the path segment name into the kind of name that + * we would see in the directory entry. + */ + + ret = fat_path2dirname(&path, dirinfo, &terminator); + if (ret < 0) + { + /* ERROR: The filename contains invalid characters or is + * too long. + */ + + return ret; + } + + /* Is this a path segment a long or a short file. Was a long file + * name parsed? + */ + +#ifdef CONFIG_FAT_LFN + if (dirinfo->fd_lfname[0] != '\0') + { + /* Yes.. Search for the sequence of long file name directory + * entries. NOTE: As a side effect, this function returns with + * the sector containing the short file name directory entry + * in the cache. + */ + + ret = fat_findlfnentry(fs, dirinfo); + } + else +#endif + { + /* No.. Search for the single short file name directory entry */ + + ret = fat_findsfnentry(fs, dirinfo); + } + + /* Did we find the directory entries? */ + + if (ret < 0) + { + return ret; + } + + /* If the terminator character in the path was the end of the string + * then we have successfully found the directory entry that describes + * the path. + */ + + if (!terminator) + { + /* Return success meaning that the description the matching + * directory entry is in dirinfo. + */ + + return OK; + } + + /* No.. then we have found one of the intermediate directories on + * the way to the final path target. In this case, make sure + * the thing that we found is, indeed, a directory. + */ + + direntry = &fs->fs_buffer[dirinfo->fd_seq.ds_offset]; + if (!(DIR_GETATTRIBUTES(direntry) & FATATTR_DIRECTORY)) + { + /* Ooops.. we found something else */ + + return -ENOTDIR; + } + + /* Get the cluster number of this directory */ + + cluster = + ((uint32_t)DIR_GETFSTCLUSTHI(direntry) << 16) | + DIR_GETFSTCLUSTLO(direntry); + + /* Then restart scanning at the new directory, skipping over both the + * '.' and '..' entries that exist in all directories EXCEPT the root + * directory. + */ + + dirinfo->dir.fd_startcluster = cluster; + dirinfo->dir.fd_currcluster = cluster; + dirinfo->dir.fd_currsector = fat_cluster2sector(fs, cluster); + dirinfo->dir.fd_index = 2; + } +} + +/**************************************************************************** + * Name: fat_allocatedirentry + * + * Desciption: Find a free directory entry + * + ****************************************************************************/ + +int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo) +{ + int32_t cluster; + off_t sector; + int ret; + int i; + + /* Re-initialize directory object */ + + cluster = dirinfo->dir.fd_startcluster; + + /* Loop until we successfully allocate the sequence of directory entries + * or until to fail to extend the directory cluster chain. + */ + + for (;;) + { + /* Can this cluster chain be extended */ + + if (cluster) + { + /* Cluster chain can be extended */ + + dirinfo->dir.fd_currcluster = cluster; + dirinfo->dir.fd_currsector = fat_cluster2sector(fs, cluster); + } + else + { + /* Fixed size FAT12/16 root directory is at fixed offset/size */ + + dirinfo->dir.fd_currsector = fs->fs_rootbase; + } + + /* Start at the first entry in the root directory. */ + + dirinfo->dir.fd_index = 0; + + /* Is this a path segment a long or a short file. Was a long file + * name parsed? + */ + +#ifdef CONFIG_FAT_LFN + if (dirinfo->fd_lfname[0] != '\0') + { + /* Yes.. Allocate for the sequence of long file name directory + * entries plus a short file name directory entry. + */ + + ret = fat_allocatelfnentry(fs, dirinfo); + } + + /* No.. Allocate only a short file name directory entry */ + + else +#endif + { + ret = fat_allocatesfnentry(fs, dirinfo); + } + + /* Did we successfully allocate the directory entries? If the error + * value is -ENOSPC, then we can try to extend the directory cluster + * (we can't handle other return values) + */ + + if (ret == OK || ret != -ENOSPC) + { + return ret; + } + + /* If we get here, then we have reached the end of the directory table + * in this sector without finding a free directory entry. + * + * It this is a fixed size directory entry, then this is an error. + * Otherwise, we can try to extend the directory cluster chain to + * make space for the new directory entry. + */ + + if (!cluster) + { + /* The size is fixed */ + + return -ENOSPC; + } + + /* Try to extend the cluster chain for this directory */ + + cluster = fat_extendchain(fs, dirinfo->dir.fd_currcluster); + if (cluster < 0) + { + return cluster; + } + + /* Flush out any cached data in fs_buffer.. we are going to use + * it to initialize the new directory cluster. + */ + + ret = fat_fscacheflush(fs); + if (ret < 0) + { + return ret; + } + + /* Clear all sectors comprising the new directory cluster */ + + fs->fs_currentsector = fat_cluster2sector(fs, cluster); + memset(fs->fs_buffer, 0, fs->fs_hwsectorsize); + + sector = fs->fs_currentsector; + for (i = fs->fs_fatsecperclus; i; i--) + { + ret = fat_hwwrite(fs, fs->fs_buffer, sector, 1); + if (ret < 0) + { + return ret; + } + sector++; + } + } +} + +/**************************************************************************** + * Name: fat_freedirentry + * + * Desciption: Free the directory entry. + * + * NOTE: As a side effect, this function returns with the sector containing + * the deleted short file name directory entry in the cache. + * + ****************************************************************************/ + +int fat_freedirentry(struct fat_mountpt_s *fs, struct fat_dirseq_s *seq) +{ +#ifdef CONFIG_FAT_LFN + struct fs_fatdir_s dir; + uint16_t diroffset; + uint8_t *direntry; + int ret; + + /* Set it to the cluster containing the "last" LFN entry (that appears + * first on the media). + */ + + dir.fd_currcluster = seq->ds_lfncluster; + dir.fd_currsector = seq->ds_lfnsector; + dir.fd_index = seq->ds_lfnoffset / DIR_SIZE; + + /* Free all of the directory entries used for the sequence of long file name + * and for the single short file name entry. + */ + + for (;;) + { + /* Read the directory sector into the sector cache */ + + ret = fat_fscacheread(fs, dir.fd_currsector); + if (ret < 0) + { + return ret; + } + + /* Get a pointer to the directory entry */ + + diroffset = (dir.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE; + direntry = &fs->fs_buffer[diroffset]; + + /* Then mark the entry as deleted */ + + direntry[DIR_NAME] = DIR0_EMPTY; + fs->fs_dirty = true; + + /* Did we just free the single short file name entry? */ + + if (dir.fd_currsector == seq->ds_sector && + diroffset == seq->ds_offset) + { + /* Yes.. then we are finished. flush anything remaining in the + * cache and return, probably successfully. + */ + + return fat_fscacheflush(fs); + } + + /* There are more entries to go.. Try the next directory entry */ + + ret = fat_nextdirentry(fs, &dir); + if (ret < 0) + { + return ret; + } + } + +#else + uint8_t *direntry; + int ret; + + /* Free the single short file name entry. + * + * Make sure that the sector containing the directory entry is in the + * cache. + */ + + ret = fat_fscacheread(fs, seq->ds_sector); + if (ret == OK) + { + /* Then mark the entry as deleted */ + + direntry = &fs->fs_buffer[seq->ds_offset]; + direntry[DIR_NAME] = DIR0_EMPTY; + fs->fs_dirty = true; + } + + return ret; +#endif +} + +/**************************************************************************** + * Name: fat_dirname2path + * + * Desciption: Convert a filename in a raw directory entry into a user + * filename. This is essentially the inverse operation of that performed + * by fat_path2dirname. See that function for more details. + * + ****************************************************************************/ + +int fat_dirname2path(struct fat_mountpt_s *fs, struct fs_dirent_s *dir) +{ + uint16_t diroffset; + uint8_t *direntry; +#ifdef CONFIG_FAT_LFN + uint8_t attribute; +#endif + + /* Get a reference to the current directory entry */ + + diroffset = (dir->u.fat.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE; + direntry = &fs->fs_buffer[diroffset]; + + /* Does this entry refer to the last entry of a long file name? */ + +#ifdef CONFIG_FAT_LFN + attribute = DIR_GETATTRIBUTES(direntry); + if (((*direntry & LDIR0_LAST) != 0 && attribute == LDDIR_LFNATTR)) + { + /* Yes.. Get the name from a sequence of long file name directory + * entries. + */ + + return fat_getlfname(fs, dir); + } + else +#endif + { + /* No.. Get the name from a short file name directory entries */ + + return fat_getsfname(direntry, dir->fd_dir.d_name, NAME_MAX+1); + } +} + +/**************************************************************************** + * Name: fat_dirnamewrite + * + * Desciption: Write the (possibly long) directory entry name. This function + * is called only from fat_rename to write the new file name. + * + * Assumption: The directory sector containing the short file name entry + * is in the cache. *NOT* the sector containing the last long file name + * entry! + * + ****************************************************************************/ + +int fat_dirnamewrite(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo) +{ +#ifdef CONFIG_FAT_LFN + int ret; + + /* Is this a long file name? */ + + if (dirinfo->fd_lfname[0] != '\0') + { + /* Write the sequence of long file name directory entries (this function + * also creates the short file name alias). + */ + + ret = fat_putlfname(fs, dirinfo); + if (ret != OK) + { + return ret; + } + } + + /* On return, fat_lfsfname() will leave the short file name entry in the + * cache. So we can just fall throught to write that directory entry, perhaps + * using the short file name alias for the long file name. + */ +#endif + + return fat_putsfname(fs, dirinfo); +} + +/**************************************************************************** + * Name: fat_dirwrite + * + * Desciption: Write a directory entry, possibly with a long file name. + * Called from: + * + * fat_mkdir() to write the new FAT directory entry. + * fat_dircreate() to create any new directory entry. + * + * Assumption: The directory sector is in the cache. The caller will write + * sector information. + * + ****************************************************************************/ + +int fat_dirwrite(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo, + uint8_t attributes, uint32_t fattime) +{ +#ifdef CONFIG_FAT_LFN + int ret; + + /* Does this directory entry have a long file name? */ + + if (dirinfo->fd_lfname[0] != '\0') + { + /* Write the sequence of long file name directory entries (this function + * also creates the short file name alias). + */ + + ret = fat_putlfname(fs, dirinfo); + if (ret != OK) + { + return ret; + } + } + + /* On return, fat_lfsfname() will leave the short file name entry in the + * cache. So we can just fall throught to write that directory entry, perhaps + * using the short file name alias for the long file name. + */ +#endif + + /* Put the short file name entry data */ + + return fat_putsfdirentry(fs, dirinfo, attributes, fattime); +} + +/**************************************************************************** + * Name: fat_dircreate + * + * Desciption: Create a directory entry for a new file + * + ****************************************************************************/ + +int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo) +{ + uint32_t fattime; + int ret; + + /* Allocate a directory entry. If long file name support is enabled, then + * this might, in fact, allocate a sequence of directory entries. + */ + + ret = fat_allocatedirentry(fs, dirinfo); + if (ret != OK) + { + /* Failed to allocate the required directory entry or entries. */ + + return ret; + } + + /* Write the directory entry (or entries) with the current time and the + * ARCHIVE attribute. + */ + + fattime = fat_systime2fattime(); + return fat_dirwrite(fs, dirinfo, FATATTR_ARCHIVE, fattime); +} + +/**************************************************************************** + * Name: fat_remove + * + * Desciption: Remove a directory or file from the file system. This + * implements both rmdir() and unlink(). + * + ****************************************************************************/ + +int fat_remove(struct fat_mountpt_s *fs, const char *relpath, bool directory) +{ + struct fat_dirinfo_s dirinfo; + uint32_t dircluster; + uint8_t *direntry; + int ret; + + /* Find the directory entry referring to the entry to be deleted */ + + ret = fat_finddirentry(fs, &dirinfo, relpath); + if (ret != OK) + { + /* No such path */ + + return -ENOENT; + } + + /* Check if this is a FAT12/16 root directory */ + + if (dirinfo.fd_root) + { + /* The root directory cannot be removed */ + + return -EPERM; + } + + /* The object has to have write access to be deleted */ + + direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset]; + if ((DIR_GETATTRIBUTES(direntry) & FATATTR_READONLY) != 0) + { + /* It is a read-only entry */ + + return -EACCES; + } + + /* Get the directory sector and cluster containing the entry to be deleted. */ + + dircluster = + ((uint32_t)DIR_GETFSTCLUSTHI(direntry) << 16) | + DIR_GETFSTCLUSTLO(direntry); + + /* Is this entry a directory? */ + + if (DIR_GETATTRIBUTES(direntry) & FATATTR_DIRECTORY) + { + /* It is a sub-directory. Check if we are be asked to remove + * a directory or a file. + */ + + if (!directory) + { + /* We are asked to delete a file */ + + return -EISDIR; + } + + /* We are asked to delete a directory. Check if this sub-directory is + * empty (i.e., that there are no valid entries other than the initial + * '.' and '..' entries). + */ + + dirinfo.dir.fd_currcluster = dircluster; + dirinfo.dir.fd_currsector = fat_cluster2sector(fs, dircluster); + dirinfo.dir.fd_index = 2; + + /* Loop until either (1) an entry is found in the directory (error), + * (2) the directory is found to be empty, or (3) some error occurs. + */ + + for (;;) + { + unsigned int subdirindex; + uint8_t *subdirentry; + + /* Make sure that the sector containing the of the subdirectory + * sector is in the cache + */ + + ret = fat_fscacheread(fs, dirinfo.dir.fd_currsector); + if (ret < 0) + { + return ret; + } + + /* Get a reference to the next entry in the directory */ + + subdirindex = (dirinfo.dir.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE; + subdirentry = &fs->fs_buffer[subdirindex]; + + /* Is this the last entry in the direcory? */ + + if (subdirentry[DIR_NAME] == DIR0_ALLEMPTY) + { + /* Yes then the directory is empty. Break out of the + * loop and delete the directory. + */ + + break; + } + + /* Check if the next entry refers to a file or directory */ + + if (subdirentry[DIR_NAME] != DIR0_EMPTY && + !(DIR_GETATTRIBUTES(subdirentry) & FATATTR_VOLUMEID)) + { + /* The directory is not empty */ + + return -ENOTEMPTY; + } + + /* Get the next directory entry */ + + ret = fat_nextdirentry(fs, &dirinfo.dir); + if (ret < 0) + { + return ret; + } + } + } + else + { + /* It is a file. Check if we are be asked to remove a directory + * or a file. + */ + + if (directory) + { + /* We are asked to remove a directory */ + + return -ENOTDIR; + } + } + + /* Mark the directory entry 'deleted'. If long file name support is + * enabled, then multiple directory entries may be freed. + */ + + ret = fat_freedirentry(fs, &dirinfo.fd_seq); + if (ret < 0) + { + return ret; + } + + /* And remove the cluster chain making up the subdirectory */ + + ret = fat_removechain(fs, dircluster); + if (ret < 0) + { + return ret; + } + + /* Update the FSINFO sector (FAT32) */ + + ret = fat_updatefsinfo(fs); + if (ret < 0) + { + return ret; + } + + return OK; +} diff --git a/nuttx/fs/fat/fs_fat32util.c b/nuttx/fs/fat/fs_fat32util.c new file mode 100644 index 0000000000..397467c417 --- /dev/null +++ b/nuttx/fs/fat/fs_fat32util.c @@ -0,0 +1,1856 @@ +/**************************************************************************** + * fs/fat/fs_fat32util.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * Microsoft FAT documentation + * Some good ideas were leveraged from the FAT implementation: + * 'Copyright (C) 2007, ChaN, all right reserved.' + * which has an unrestricted license. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "fs_internal.h" +#include "fs_fat32.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fat_checkfsinfo + * + * Desciption: Read the FAT32 FSINFO sector + * + ****************************************************************************/ + +static int fat_checkfsinfo(struct fat_mountpt_s *fs) +{ + /* Make sure that the fsinfo sector is in the cache */ + + if (fat_fscacheread(fs, fs->fs_fsinfo) == OK) + { + /* Verify that this is, indeed, an FSINFO sector */ + + if (FSI_GETLEADSIG(fs->fs_buffer) == 0x41615252 && + FSI_GETSTRUCTSIG(fs->fs_buffer) == 0x61417272 && + FSI_GETTRAILSIG(fs->fs_buffer) == BOOT_SIGNATURE32) + { + fs->fs_fsinextfree = FSI_GETFREECOUNT(fs->fs_buffer); + fs->fs_fsifreecount = FSI_GETNXTFREE(fs->fs_buffer); + return OK; + } + } + + return -ENODEV; +} + +/**************************************************************************** + * Name: fat_checkbootrecord + * + * Desciption: Read a sector and verify that it is a a FAT boot record. + * + ****************************************************************************/ + +static int fat_checkbootrecord(struct fat_mountpt_s *fs) +{ + uint32_t ndatasectors; + uint32_t ntotalfatsects; + uint16_t rootdirsectors = 0; + bool notfat32 = false; + + /* Verify the MBR signature at offset 510 in the sector (true even + * if the sector size is greater than 512. All FAT file systems have + * this signature. On a FAT32 volume, the RootEntCount , FatSz16, and + * FatSz32 values should always be zero. The FAT sector size should + * match the reported hardware sector size. + */ + + if (MBR_GETSIGNATURE(fs->fs_buffer) != BOOT_SIGNATURE16 || + MBR_GETBYTESPERSEC(fs->fs_buffer) != fs->fs_hwsectorsize) + { + fdbg("ERROR: Signature: %04x FS sectorsize: %d HW sectorsize: %d\n", + MBR_GETSIGNATURE(fs->fs_buffer), MBR_GETBYTESPERSEC(fs->fs_buffer), + fs->fs_hwsectorsize); + + return -EINVAL; + } + + /* Verify the FAT32 file system type. The determination of the file + * system type is based on the number of clusters on the volume: FAT12 + * volume has <= FAT_MAXCLUST12 (4084) clusters, a FAT16 volume has <= + * FAT_MINCLUST16 (microsfoft says < 65,525) clusters, and any larger + * is FAT32. + * + * Get the number of 32-bit directory entries in root directory (zero + * for FAT32). + */ + + fs->fs_rootentcnt = MBR_GETROOTENTCNT(fs->fs_buffer); + if (fs->fs_rootentcnt != 0) + { + notfat32 = true; /* Must be zero for FAT32 */ + rootdirsectors = (32 * fs->fs_rootentcnt + fs->fs_hwsectorsize - 1) / fs->fs_hwsectorsize; + } + + /* Determine the number of sectors in a FAT. */ + + fs->fs_nfatsects = MBR_GETFATSZ16(fs->fs_buffer); /* Should be zero */ + if (fs->fs_nfatsects) + { + notfat32 = true; /* Must be zero for FAT32 */ + } + else + { + fs->fs_nfatsects = MBR_GETFATSZ32(fs->fs_buffer); + } + + if (!fs->fs_nfatsects || fs->fs_nfatsects >= fs->fs_hwnsectors) + { + fdbg("ERROR: fs_nfatsects %d fs_hwnsectors: %d\n", + fs->fs_nfatsects, fs->fs_hwnsectors); + + return -EINVAL; + } + + /* Get the total number of sectors on the volume. */ + + fs->fs_fattotsec = MBR_GETTOTSEC16(fs->fs_buffer); /* Should be zero */ + if (fs->fs_fattotsec) + { + notfat32 = true; /* Must be zero for FAT32 */ + } + else + { + fs->fs_fattotsec = MBR_GETTOTSEC32(fs->fs_buffer); + } + + if (!fs->fs_fattotsec || fs->fs_fattotsec > fs->fs_hwnsectors) + { + fdbg("ERROR: fs_fattotsec %d fs_hwnsectors: %d\n", + fs->fs_fattotsec, fs->fs_hwnsectors); + + return -EINVAL; + } + + /* Get the total number of reserved sectors */ + + fs->fs_fatresvdseccount = MBR_GETRESVDSECCOUNT(fs->fs_buffer); + if (fs->fs_fatresvdseccount > fs->fs_hwnsectors) + { + fdbg("ERROR: fs_fatresvdseccount %d fs_hwnsectors: %d\n", + fs->fs_fatresvdseccount, fs->fs_hwnsectors); + + return -EINVAL; + } + + /* Get the number of FATs. This is probably two but could have other values */ + + fs->fs_fatnumfats = MBR_GETNUMFATS(fs->fs_buffer); + ntotalfatsects = fs->fs_fatnumfats * fs->fs_nfatsects; + + /* Get the total number of data sectors */ + + ndatasectors = fs->fs_fattotsec - fs->fs_fatresvdseccount - ntotalfatsects - rootdirsectors; + if (ndatasectors > fs->fs_hwnsectors) + { + fdbg("ERROR: ndatasectors %d fs_hwnsectors: %d\n", + ndatasectors, fs->fs_hwnsectors); + + return -EINVAL; + } + + /* Get the sectors per cluster */ + + fs->fs_fatsecperclus = MBR_GETSECPERCLUS(fs->fs_buffer); + + /* Calculate the number of clusters */ + + fs->fs_nclusters = ndatasectors / fs->fs_fatsecperclus; + + /* Finally, the test: */ + + if (fs->fs_nclusters <= FAT_MAXCLUST12) + { + fs->fs_fsinfo = 0; + fs->fs_type = FSTYPE_FAT12; + } + else if (fs->fs_nclusters <= FAT_MAXCLUST16) + { + fs->fs_fsinfo = 0; + fs->fs_type = FSTYPE_FAT16; + } + else if (!notfat32) + { + fs->fs_fsinfo = fs->fs_fatbase + MBR_GETFSINFO(fs->fs_buffer); + fs->fs_type = FSTYPE_FAT32; + } + else + { + fdbg("ERROR: notfat32: %d fs_nclusters: %d\n", + notfat32, fs->fs_nclusters); + + return -EINVAL; + } + + /* We have what appears to be a valid FAT filesystem! Save a few more things + * from the boot record that we will need later. + */ + + fs->fs_fatbase += fs->fs_fatresvdseccount; + + if (fs->fs_type == FSTYPE_FAT32) + { + fs->fs_rootbase = MBR_GETROOTCLUS(fs->fs_buffer); + } + else + { + fs->fs_rootbase = fs->fs_fatbase + ntotalfatsects; + } + + fs->fs_database = fs->fs_fatbase + ntotalfatsects + fs->fs_rootentcnt / DIRSEC_NDIRS(fs); + fs->fs_fsifreecount = 0xffffffff; + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fat_getuint16 + ****************************************************************************/ + +uint16_t fat_getuint16(uint8_t *ptr) +{ +#ifdef CONFIG_ENDIAN_BIG + /* The bytes always have to be swapped if the target is big-endian */ + + return ((uint16_t)ptr[0] << 8) | ptr[1]; +#else + /* Byte-by-byte transfer is still necessary if the address is un-aligned */ + + return ((uint16_t)ptr[1] << 8) | ptr[0]; +#endif +} + +/**************************************************************************** + * Name: fat_getuint32 + ****************************************************************************/ + +uint32_t fat_getuint32(uint8_t *ptr) +{ +#ifdef CONFIG_ENDIAN_BIG + /* The bytes always have to be swapped if the target is big-endian */ + + return ((uint32_t)fat_getuint16(&ptr[0]) << 16) | fat_getuint16(&ptr[2]); +#else + /* Byte-by-byte transfer is still necessary if the address is un-aligned */ + + return ((uint32_t)fat_getuint16(&ptr[2]) << 16) | fat_getuint16(&ptr[0]); +#endif +} + +/**************************************************************************** + * Name: fat_putuint16 + ****************************************************************************/ + +void fat_putuint16(uint8_t *ptr, uint16_t value16) +{ + uint8_t *val = (uint8_t*)&value16; +#ifdef CONFIG_ENDIAN_BIG + /* The bytes always have to be swapped if the target is big-endian */ + + ptr[0] = val[1]; + ptr[1] = val[0]; +#else + /* Byte-by-byte transfer is still necessary if the address is un-aligned */ + + ptr[0] = val[0]; + ptr[1] = val[1]; +#endif +} + +/**************************************************************************** + * Name: fat_putuint32 + ****************************************************************************/ + +void fat_putuint32(uint8_t *ptr, uint32_t value32) +{ + uint16_t *val = (uint16_t*)&value32; +#ifdef CONFIG_ENDIAN_BIG + /* The bytes always have to be swapped if the target is big-endian */ + + fat_putuint16(&ptr[0], val[2]); + fat_putuint16(&ptr[2], val[0]); +#else + /* Byte-by-byte transfer is still necessary if the address is un-aligned */ + + fat_putuint16(&ptr[0], val[0]); + fat_putuint16(&ptr[2], val[2]); +#endif +} + +/**************************************************************************** + * Name: fat_semtake + ****************************************************************************/ + +void fat_semtake(struct fat_mountpt_s *fs) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&fs->fs_sem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(*get_errno_ptr() == EINTR); + } +} + +/**************************************************************************** + * Name: fat_semgive + ****************************************************************************/ + +void fat_semgive(struct fat_mountpt_s *fs) +{ + sem_post(&fs->fs_sem); +} + +/**************************************************************************** + * Name: fat_systime2fattime + * + * Desciption: Get the system time convert to a time and and date suitble + * for writing into the FAT FS. + * + * TIME in LS 16-bits: + * Bits 0:4 = 2 second count (0-29 representing 0-58 seconds) + * Bits 5-10 = minutes (0-59) + * Bits 11-15 = hours (0-23) + * DATE in MS 16-bits + * Bits 0:4 = Day of month (1-31) + * Bits 5:8 = Month of year (1-12) + * Bits 9:15 = Year from 1980 (0-127 representing 1980-2107) + * + ****************************************************************************/ + +uint32_t fat_systime2fattime(void) +{ + /* Unless you have a hardware RTC or some other to get accurate time, then + * there is no reason to support FAT time. + */ + +#ifdef CONFIG_FS_FATTIME + struct timespec ts; + struct tm tm; + int ret; + + /* Get the current time in seconds and nanoseconds */ + + ret = clock_gettime(CLOCK_REALTIME, &ts); + if (ret == OK) + { + /* Break done the seconds in date and time units */ + + if (gmtime_r((FAR const time_t *)&ts.tv_sec, &tm) != NULL) + { + /* FAT can only represent dates since 1980. struct tm can + * represent dates since 1900. + */ + + if (tm.tm_year >= 80) + { + uint16_t fattime; + uint16_t fatdate; + + fattime = (tm.tm_sec >> 1) & 0x001f; /* Bits 0-4: 2 second count (0-29) */ + fattime |= (tm.tm_min << 5) & 0x07e0; /* Bits 5-10: minutes (0-59) */ + fattime |= (tm.tm_hour << 11) & 0xf800; /* Bits 11-15: hours (0-23) */ + + fatdate = tm.tm_mday & 0x001f; /* Bits 0-4: Day of month (1-31) */ + fatdate |= ((tm.tm_mon+1) << 5) & 0x01e0; /* Bits 5-8: Month of year (1-12) */ + fatdate |= ((tm.tm_year-80) << 9) & 0xfe00; /* Bits 9-15: Year from 1980 */ + + return (uint32_t)fatdate << 16 | (uint32_t)fattime; + } + } + } +#endif + return 0; +} + +/**************************************************************************** + * Name: fat_fattime2systime + * + * Desciption: Convert FAT data and time to a system time_t + * + * 16-bit FAT time: + * Bits 0:4 = 2 second count (0-29 representing 0-58 seconds) + * Bits 5-10 = minutes (0-59) + * Bits 11-15 = hours (0-23) + * 16-bit FAT date: + * Bits 0:4 = Day of month (1-31) + * Bits 5:8 = Month of year (1-12) + * Bits 9:15 = Year from 1980 (0-127 representing 1980-2107) + * + ****************************************************************************/ + +time_t fat_fattime2systime(uint16_t fattime, uint16_t fatdate) +{ + /* Unless you have a hardware RTC or some other to get accurate time, then + * there is no reason to support FAT time. + */ + +#ifdef CONFIG_FS_FATTIME + struct tm tm; + unsigned int tmp; + + /* Break out the date and time */ + + tm.tm_sec = (fattime & 0x001f) << 1; /* Bits 0-4: 2 second count (0-29) */ + tm.tm_min = (fattime & 0x07e0) >> 5; /* Bits 5-10: minutes (0-59) */ + tm.tm_hour = (fattime & 0xf800) >> 11; /* Bits 11-15: hours (0-23) */ + + tm.tm_mday = (fatdate & 0x001f); /* Bits 0-4: Day of month (1-31) */ + tmp = ((fatdate & 0x01e0) >> 5); /* Bits 5-8: Month of year (1-12) */ + tm.tm_mon = tmp > 0 ? tmp-1 : 0; + tm.tm_year = ((fatdate & 0xfe00) >> 9) + 80; /* Bits 9-15: Year from 1980 */ + + /* Then convert the broken out time into seconds since the epoch */ + + return mktime(&tm); +#else + return 0; +#endif +} + +/**************************************************************************** + * Name: fat_mount + * + * Desciption: This function is called only when the mountpoint is first + * established. It initializes the mountpoint structure and verifies + * that a valid FAT32 filesystem is provided by the block driver. + * + * The caller should hold the mountpoint semaphore + * + ****************************************************************************/ + +int fat_mount(struct fat_mountpt_s *fs, bool writeable) +{ + FAR struct inode *inode; + struct geometry geo; + int ret; + + /* Assume that the mount is successful */ + + fs->fs_mounted = true; + + /* Check if there is media available */ + + inode = fs->fs_blkdriver; + if (!inode || !inode->u.i_bops || !inode->u.i_bops->geometry || + inode->u.i_bops->geometry(inode, &geo) != OK || !geo.geo_available) + { + ret = -ENODEV; + goto errout; + } + + /* Make sure that that the media is write-able (if write access is needed) */ + + if (writeable && !geo.geo_writeenabled) + { + ret = -EACCES; + goto errout; + } + + /* Save the hardware geometry */ + + fs->fs_hwsectorsize = geo.geo_sectorsize; + fs->fs_hwnsectors = geo.geo_nsectors; + + /* Allocate a buffer to hold one hardware sector */ + + fs->fs_buffer = (uint8_t*)kmalloc(fs->fs_hwsectorsize); + if (!fs->fs_buffer) + { + ret = -ENOMEM; + goto errout; + } + + /* Search FAT boot record on the drive. First check at sector zero. This + * could be either the boot record or a partition that refers to the boot + * record. + * + * First read sector zero. This will be the first access to the drive and a + * likely failure point. + */ + + fs->fs_fatbase = 0; + ret = fat_hwread(fs, fs->fs_buffer, 0, 1); + if (ret < 0) + { + goto errout_with_buffer; + } + + ret = fat_checkbootrecord(fs); + if (ret != OK) + { + /* The contents of sector 0 is not a boot record. It could be a + * partition, however. Assume it is a partition and get the offset + * into the partition table. This table is at offset MBR_TABLE and is + * indexed by 16x the partition number. + */ + + int i; + for (i = 0; i < 4; i++) + { + /* Check if the partition exists and, if so, get the bootsector for that + * partition and see if we can find the boot record there. + */ + + uint8_t part = PART_GETTYPE(i, fs->fs_buffer); + fvdbg("Partition %d, offset %d, type %d\n", i, PART_ENTRY(i), part); + + if (part == 0) + { + fvdbg("No partition %d\n", i); + continue; + } + + /* There appears to be a partition, get the sector number of the + * partition (LBA) + */ + + fs->fs_fatbase = PART_GETSTARTSECTOR(i, fs->fs_buffer); + + /* Read the new candidate boot sector */ + + ret = fat_hwread(fs, fs->fs_buffer, fs->fs_fatbase, 1); + if (ret < 0) + { + /* Failed to read the sector */ + + goto errout_with_buffer; + } + + /* Check if this is a boot record */ + + ret = fat_checkbootrecord(fs); + if (ret == OK) + { + /* Break out of the loop if a valid boot record is found */ + + fvdbg("MBR found in partition %d\n", i); + break; + } + + /* Re-read sector 0 so that we can check the next partition */ + + fvdbg("Partition %d is not an MBR\n", i); + ret = fat_hwread(fs, fs->fs_buffer, 0, 1); + if (ret < 0) + { + goto errout_with_buffer; + } + } + + if (i > 3) + { + fdbg("No valid MBR\n"); + goto errout_with_buffer; + } + } + + /* We have what appears to be a valid FAT filesystem! Now read the + * FSINFO sector (FAT32 only) + */ + + if (fs->fs_type == FSTYPE_FAT32) + { + ret = fat_checkfsinfo(fs); + if (ret != OK) + { + goto errout_with_buffer; + } + } + + /* We did it! */ + + fdbg("FAT%d:\n", fs->fs_type == 0 ? 12 : fs->fs_type == 1 ? 16 : 32); + fdbg("\tHW sector size: %d\n", fs->fs_hwsectorsize); + fdbg("\t sectors: %d\n", fs->fs_hwnsectors); + fdbg("\tFAT reserved: %d\n", fs->fs_fatresvdseccount); + fdbg("\t sectors: %d\n", fs->fs_fattotsec); + fdbg("\t start sector: %d\n", fs->fs_fatbase); + fdbg("\t root sector: %d\n", fs->fs_rootbase); + fdbg("\t root entries: %d\n", fs->fs_rootentcnt); + fdbg("\t data sector: %d\n", fs->fs_database); + fdbg("\t FSINFO sector: %d\n", fs->fs_fsinfo); + fdbg("\t Num FATs: %d\n", fs->fs_fatnumfats); + fdbg("\t FAT sectors: %d\n", fs->fs_nfatsects); + fdbg("\t sectors/cluster: %d\n", fs->fs_fatsecperclus); + fdbg("\t max clusters: %d\n", fs->fs_nclusters); + fdbg("\tFSI free count %d\n", fs->fs_fsifreecount); + fdbg("\t next free %d\n", fs->fs_fsinextfree); + + return OK; + + errout_with_buffer: + kfree(fs->fs_buffer); + fs->fs_buffer = 0; + errout: + fs->fs_mounted = false; + return ret; +} + +/**************************************************************************** + * Name: fat_checkmount + * + * Desciption: Check if the mountpoint is still valid. + * + * The caller should hold the mountpoint semaphore + * + ****************************************************************************/ + +int fat_checkmount(struct fat_mountpt_s *fs) +{ + /* If the fs_mounted flag is false, then we have already handled the loss + * of the mount. + */ + + if (fs && fs->fs_mounted) + { + struct fat_file_s *file; + + /* We still think the mount is healthy. Check an see if this is + * still the case + */ + + if (fs->fs_blkdriver) + { + struct inode *inode = fs->fs_blkdriver; + if (inode && inode->u.i_bops && inode->u.i_bops->geometry) + { + struct geometry geo; + int errcode = inode->u.i_bops->geometry(inode, &geo); + if (errcode == OK && geo.geo_available && !geo.geo_mediachanged) + { + return OK; + } + } + } + + /* If we get here, the mount is NOT healthy */ + + fs->fs_mounted = false; + + /* Make sure that this is flagged in every opened file */ + + for (file = fs->fs_head; file; file = file->ff_next) + { + file->ff_open = false; + } + } + return -ENODEV; +} + +/**************************************************************************** + * Name: fat_hwread + * + * Desciption: Read the specified sector into the sector buffer + * + ****************************************************************************/ + +int fat_hwread(struct fat_mountpt_s *fs, uint8_t *buffer, off_t sector, + unsigned int nsectors) +{ + int ret = -ENODEV; + if (fs && fs->fs_blkdriver ) + { + struct inode *inode = fs->fs_blkdriver; + if (inode && inode->u.i_bops && inode->u.i_bops->read) + { + ssize_t nSectorsRead = inode->u.i_bops->read(inode, buffer, + sector, nsectors); + if (nSectorsRead == nsectors) + { + ret = OK; + } + else if (nSectorsRead < 0) + { + ret = nSectorsRead; + } + } + } + return ret; +} + +/**************************************************************************** + * Name: fat_hwwrite + * + * Desciption: Write the sector buffer to the specified sector + * + ****************************************************************************/ + +int fat_hwwrite(struct fat_mountpt_s *fs, uint8_t *buffer, off_t sector, + unsigned int nsectors) +{ + int ret = -ENODEV; + if (fs && fs->fs_blkdriver ) + { + struct inode *inode = fs->fs_blkdriver; + if (inode && inode->u.i_bops && inode->u.i_bops->write) + { + ssize_t nSectorsWritten = + inode->u.i_bops->write(inode, buffer, sector, nsectors); + + if (nSectorsWritten == nsectors) + { + ret = OK; + } + else if (nSectorsWritten < 0) + { + ret = nSectorsWritten; + } + } + } + return ret; +} + +/**************************************************************************** + * Name: fat_cluster2sector + * + * Desciption: Convert a cluster number to a start sector number + * + ****************************************************************************/ + +off_t fat_cluster2sector(struct fat_mountpt_s *fs, uint32_t cluster ) +{ + cluster -= 2; + if (cluster >= fs->fs_nclusters - 2) + { + return -EINVAL; + } + return cluster * fs->fs_fatsecperclus + fs->fs_database; +} + +/**************************************************************************** + * Name: fat_getcluster + * + * Desciption: Get the next cluster start from the FAT. + * + * Return: <0: error, 0:cluster unassigned, >=0: start sector of cluster + * + ****************************************************************************/ + +off_t fat_getcluster(struct fat_mountpt_s *fs, uint32_t clusterno) +{ + /* Verify that the cluster number is within range */ + + if (clusterno >= 2 && clusterno < fs->fs_nclusters) + { + /* Okay.. Read the next cluster from the FAT. The way we will do + * this depends on the type of FAT filesystm we are dealing with. + */ + + switch (fs->fs_type) + { + case FSTYPE_FAT12 : + { + off_t fatsector; + unsigned int fatoffset; + unsigned int cluster; + unsigned int fatindex; + + /* FAT12 is more complex because it has 12-bits (1.5 bytes) + * per FAT entry. Get the offset to the first byte: + */ + + fatoffset = (clusterno * 3) / 2; + fatsector = fs->fs_fatbase + SEC_NSECTORS(fs, fatoffset); + + /* Read the sector at this offset */ + + if (fat_fscacheread(fs, fatsector) < 0) + { + /* Read error */ + + break; + } + + /* Get the first, LS byte of the cluster from the FAT */ + + fatindex = fatoffset & SEC_NDXMASK(fs); + cluster = fs->fs_buffer[fatindex]; + + /* With FAT12, the second byte of the cluster number may lie in + * a different sector than the first byte. + */ + + fatindex++; + if (fatindex >= fs->fs_hwsectorsize) + { + fatsector++; + fatindex = 0; + + if (fat_fscacheread(fs, fatsector) < 0) + { + /* Read error */ + + break; + } + } + + /* Get the second, MS byte of the cluster for 16-bits. The + * does not depend on the endian-ness of the target, but only + * on the fact that the byte stream is little-endian. + */ + + cluster |= (unsigned int)fs->fs_buffer[fatindex] << 8; + + /* Now, pick out the correct 12 bit cluster start sector value */ + + if ((clusterno & 1) != 0) + { + /* Odd.. take the MS 12-bits */ + + cluster >>= 4; + } + else + { + /* Even.. take the LS 12-bits */ + + cluster &= 0x0fff; + } + return cluster; + } + + case FSTYPE_FAT16 : + { + unsigned int fatoffset = 2 * clusterno; + off_t fatsector = fs->fs_fatbase + SEC_NSECTORS(fs, fatoffset); + unsigned int fatindex = fatoffset & SEC_NDXMASK(fs); + + if (fat_fscacheread(fs, fatsector) < 0) + { + /* Read error */ + break; + } + return FAT_GETFAT16(fs->fs_buffer, fatindex); + } + + case FSTYPE_FAT32 : + { + unsigned int fatoffset = 4 * clusterno; + off_t fatsector = fs->fs_fatbase + SEC_NSECTORS(fs, fatoffset); + unsigned int fatindex = fatoffset & SEC_NDXMASK(fs); + + if (fat_fscacheread(fs, fatsector) < 0) + { + /* Read error */ + break; + } + return FAT_GETFAT32(fs->fs_buffer, fatindex) & 0x0fffffff; + } + default: + break; + } + } + + /* There is no cluster information, or an error occured */ + + return (off_t)-EINVAL; +} + +/**************************************************************************** + * Name: fat_putcluster + * + * Desciption: Write a new cluster into the FAT + * + ****************************************************************************/ + +int fat_putcluster(struct fat_mountpt_s *fs, uint32_t clusterno, off_t nextcluster) +{ + /* Verify that the cluster number is within range. Zero erases the cluster. */ + + if (clusterno == 0 || (clusterno >= 2 && clusterno < fs->fs_nclusters)) + { + /* Okay.. Write the next cluster into the FAT. The way we will do + * this depends on the type of FAT filesystm we are dealing with. + */ + + switch (fs->fs_type) + { + case FSTYPE_FAT12 : + { + off_t fatsector; + unsigned int fatoffset; + unsigned int fatindex; + uint8_t value; + + /* FAT12 is more complex because it has 12-bits (1.5 bytes) + * per FAT entry. Get the offset to the first byte: + */ + + fatoffset = (clusterno * 3) / 2; + fatsector = fs->fs_fatbase + SEC_NSECTORS(fs, fatoffset); + + /* Make sure that the sector at this offset is in the cache */ + + if (fat_fscacheread(fs, fatsector)< 0) + { + /* Read error */ + + break; + } + + /* Get the LS byte first handling the 12-bit alignment within + * the 16-bits + */ + + fatindex = fatoffset & SEC_NDXMASK(fs); + if ((clusterno & 1) != 0) + { + /* Save the LS four bits of the next cluster */ + + value = (fs->fs_buffer[fatindex] & 0x0f) | nextcluster << 4; + } + else + { + /* Save the LS eight bits of the next cluster */ + + value = (uint8_t)nextcluster; + } + + fs->fs_buffer[fatindex] = value; + + /* With FAT12, the second byte of the cluster number may lie in + * a different sector than the first byte. + */ + + fatindex++; + if (fatindex >= fs->fs_hwsectorsize) + { + /* Read the next sector */ + + fatsector++; + fatindex = 0; + + /* Set the dirty flag to make sure the sector that we + * just modified is written out. + */ + + fs->fs_dirty = true; + if (fat_fscacheread(fs, fatsector) < 0) + { + /* Read error */ + + break; + } + } + + /* Output the MS byte first handling the 12-bit alignment within + * the 16-bits + */ + + if ((clusterno & 1) != 0) + { + /* Save the MS eight bits of the next cluster */ + + value = (uint8_t)(nextcluster >> 4); + } + else + { + /* Save the MS four bits of the next cluster */ + + value = (fs->fs_buffer[fatindex] & 0xf0) | ((nextcluster >> 8) & 0x0f); + } + + fs->fs_buffer[fatindex] = value; + } + break; + + case FSTYPE_FAT16 : + { + unsigned int fatoffset = 2 * clusterno; + off_t fatsector = fs->fs_fatbase + SEC_NSECTORS(fs, fatoffset); + unsigned int fatindex = fatoffset & SEC_NDXMASK(fs); + + if (fat_fscacheread(fs, fatsector) < 0) + { + /* Read error */ + + break; + } + FAT_PUTFAT16(fs->fs_buffer, fatindex, nextcluster & 0xffff); + } + break; + + case FSTYPE_FAT32 : + { + unsigned int fatoffset = 4 * clusterno; + off_t fatsector = fs->fs_fatbase + SEC_NSECTORS(fs, fatoffset); + unsigned int fatindex = fatoffset & SEC_NDXMASK(fs); + + if (fat_fscacheread(fs, fatsector) < 0) + { + /* Read error */ + + break; + } + FAT_PUTFAT32(fs->fs_buffer, fatindex, nextcluster & 0x0fffffff); + } + break; + + default: + return -EINVAL; + } + + /* Mark the modified sector as "dirty" and return success */ + + fs->fs_dirty = true; + return OK; + } + + return -EINVAL; +} + +/**************************************************************************** + * Name: fat_removechain + * + * Desciption: Remove an entire chain of clusters, starting with 'cluster' + * + ****************************************************************************/ + +int fat_removechain(struct fat_mountpt_s *fs, uint32_t cluster) +{ + int32_t nextcluster; + int ret; + + /* Loop while there are clusters in the chain */ + + while (cluster >= 2 && cluster < fs->fs_nclusters) + { + /* Get the next cluster after the current one */ + + nextcluster = fat_getcluster(fs, cluster); + if (nextcluster < 0) + { + /* Error! */ + return nextcluster; + } + + /* Then nullify current cluster -- removing it from the chain */ + + ret = fat_putcluster(fs, cluster, 0); + if (ret < 0) + { + return ret; + } + + /* Update FSINFINFO data */ + + if (fs->fs_fsifreecount != 0xffffffff) + { + fs->fs_fsifreecount++; + fs->fs_fsidirty = 1; + } + + /* Then set up to remove the next cluster */ + + cluster = nextcluster; + } + + return OK; +} + +/**************************************************************************** + * Name: fat_extendchain + * + * Desciption: Add a new cluster to the chain following cluster (if cluster + * is non-NULL). if cluster is zero, then a new chain is created. + * + * Return: <0:error, 0: no free cluster, >=2: new cluster number + * + ****************************************************************************/ + +int32_t fat_extendchain(struct fat_mountpt_s *fs, uint32_t cluster) +{ + off_t startsector; + uint32_t newcluster; + uint32_t startcluster; + int ret; + + /* The special value 0 is used when the new chain should start */ + + if (cluster == 0) + { + /* The FSINFO NextFree entry should be a good starting point + * in the search for a new cluster + */ + + startcluster = fs->fs_fsinextfree; + if (startcluster == 0 || startcluster >= fs->fs_nclusters) + { + /* But it is bad.. we have to start at the beginning */ + startcluster = 1; + } + } + else + { + /* We are extending an existing chain. Verify that this + * is a valid cluster by examining its start sector. + */ + + startsector = fat_getcluster(fs, cluster); + if (startsector < 0) + { + /* An error occurred, return the error value */ + + return startsector; + } + else if (startsector < 2) + { + /* Oops.. this cluster does not exist. */ + + return 0; + } + else if (startsector < fs->fs_nclusters) + { + /* It is already followed by next cluster */ + + return startsector; + } + + /* Okay.. it checks out */ + + startcluster = cluster; + } + + /* Loop until (1) we discover that there are not free clusters + * (return 0), an errors occurs (return -errno), or (3) we find + * the next cluster (return the new cluster number). + */ + + newcluster = startcluster; + for (;;) + { + /* Examine the next cluster in the FAT */ + + newcluster++; + if (newcluster >= fs->fs_nclusters) + { + /* If we hit the end of the available clusters, then + * wrap back to the beginning because we might have + * started at a non-optimal place. But don't continue + * past the start cluster. + */ + + newcluster = 2; + if (newcluster > startcluster) + { + /* We are back past the starting cluster, then there + * is no free cluster. + */ + + return 0; + } + } + + /* We have a candidate cluster. Check if the cluster number is + * mapped to a group of sectors. + */ + + startsector = fat_getcluster(fs, newcluster); + if (startsector == 0) + { + /* Found have found a free cluster break out*/ + break; + } + else if (startsector < 0) + { + /* Some error occurred, return the error number */ + return startsector; + } + + /* We wrap all the back to the starting cluster? If so, then + * there are no free clusters. + */ + + if (newcluster == startcluster) + { + return 0; + } + } + + /* We get here only if we break out with an available cluster + * number in 'newcluster' Now mark that cluster as in-use. + */ + + ret = fat_putcluster(fs, newcluster, 0x0fffffff); + if (ret < 0) + { + /* An error occurred */ + return ret; + } + + /* And link if to the start cluster (if any)*/ + + if (cluster) + { + /* There is a start cluster -- link it */ + + ret = fat_putcluster(fs, cluster, newcluster); + if (ret < 0) + { + return ret; + } + } + + /* And update the FINSINFO for the next time we have to search */ + + fs->fs_fsinextfree = newcluster; + if (fs->fs_fsifreecount != 0xffffffff) + { + fs->fs_fsifreecount--; + fs->fs_fsidirty = 1; + } + + /* Return then number of the new cluster that was added to the chain */ + + return newcluster; +} + +/**************************************************************************** + * Name: fat_nextdirentry + * + * Desciption: Read the next directory entry from the sector in cache, + * reading the next sector(s) in the cluster as necessary. This function + * must return -ENOSPC if if fails because there are no further entries + * available in the directory. + * + ****************************************************************************/ + +int fat_nextdirentry(struct fat_mountpt_s *fs, struct fs_fatdir_s *dir) +{ + unsigned int cluster; + unsigned int ndx; + + /* Increment the index to the next 32-byte directory entry */ + + ndx = dir->fd_index + 1; + + /* Check if all of the directory entries in this sectory have + * been examined. + */ + + if ((ndx & (DIRSEC_NDIRS(fs)-1)) == 0) + { + /* Yes, then we will have to read the next sector */ + + dir->fd_currsector++; + + /* For FAT12/16, the root directory is a group of sectors relative + * to the first sector of the fat volume. + */ + + if (!dir->fd_currcluster) + { + /* For FAT12/16, the boot record tells us number of 32-bit directories + * that are contained in the root directory. This should correspond to + * an even number of sectors. + */ + + if (ndx >= fs->fs_rootentcnt) + { + /* When we index past this count, we have examined all of the entries in + * the root directory. + */ + + return -ENOSPC; + } + } + else + { + /* Not a FAT12/16 root directory, check if we have examined the entire + * cluster comprising the directory. + * + * The current sector within the cluster is the entry number divided + * byte the number of entries per sector + */ + + int sector = ndx / DIRSEC_NDIRS(fs); + + /* We are finished with the cluster when the last sector of the cluster + * has been examined. + */ + + if ((sector & (fs->fs_fatsecperclus-1)) == 0) + { + /* Get next cluster */ + + cluster = fat_getcluster(fs, dir->fd_currcluster); + + /* Check if a valid cluster was obtained. */ + + if (cluster < 2 || cluster >= fs->fs_nclusters) + { + /* No, we have probably reached the end of the cluster list */ + + return -ENOSPC; + } + + /* Initialize for new cluster */ + + dir->fd_currcluster = cluster; + dir->fd_currsector = fat_cluster2sector(fs, cluster); + } + } + } + + /* Save the new index into dir->fd_currsector */ + + dir->fd_index = ndx; + return OK; +} + +/**************************************************************************** + * Name: fat_dirtruncate + * + * Desciption: Truncate an existing file to zero length + * + * Assumptions: The caller holds mountpoint semaphore, fs_buffer holds + * the directory entry, the directory entry sector (fd_sector) is + * currently in the sector cache. + * + ****************************************************************************/ + +int fat_dirtruncate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo) +{ + unsigned int startcluster; + uint32_t writetime; + uint8_t *direntry; + off_t savesector; + int ret; + + /* Get start cluster of the file to truncate */ + + direntry = &fs->fs_buffer[dirinfo->fd_seq.ds_offset]; + startcluster = + ((uint32_t)DIR_GETFSTCLUSTHI(direntry) << 16) | + DIR_GETFSTCLUSTLO(direntry); + + /* Clear the cluster start value in the directory and set the file size + * to zero. This makes the file look empty but also have to dispose of + * all of the clusters in the chain. + */ + + DIR_PUTFSTCLUSTHI(direntry, 0); + DIR_PUTFSTCLUSTLO(direntry, 0); + DIR_PUTFILESIZE(direntry, 0); + + /* Set the ARCHIVE attribute and update the write time */ + + DIR_PUTATTRIBUTES(direntry, FATATTR_ARCHIVE); + + writetime = fat_systime2fattime(); + DIR_PUTWRTTIME(direntry, writetime & 0xffff); + DIR_PUTWRTDATE(direntry, writetime > 16); + + /* This sector needs to be written back to disk eventually */ + + fs->fs_dirty = true; + + /* Now remove the entire cluster chain comprising the file */ + + savesector = fs->fs_currentsector; + ret = fat_removechain(fs, startcluster); + if (ret < 0) + { + return ret; + } + + /* Setup FSINFO to resuse this cluster next */ + + fs->fs_fsinextfree = startcluster - 1; + + /* Make sure that the directory is still in the cache */ + + return fat_fscacheread(fs, savesector); +} + +/**************************************************************************** + * Name: fat_fscacheflush + * + * Desciption: Flush any dirty sector if fs_buffer as necessary + * + ****************************************************************************/ + +int fat_fscacheflush(struct fat_mountpt_s *fs) +{ + int ret; + + /* Check if the fs_buffer is dirty. In this case, we will write back the + * contents of fs_buffer. + */ + + if (fs->fs_dirty) + { + /* Write the dirty sector */ + + ret = fat_hwwrite(fs, fs->fs_buffer, fs->fs_currentsector, 1); + if (ret < 0) + { + return ret; + } + + /* Does the sector lie in the FAT region? */ + + if (fs->fs_currentsector >= fs->fs_fatbase && + fs->fs_currentsector < fs->fs_fatbase + fs->fs_nfatsects) + { + /* Yes, then make the change in the FAT copy as well */ + int i; + + for (i = fs->fs_fatnumfats; i >= 2; i--) + { + fs->fs_currentsector += fs->fs_nfatsects; + ret = fat_hwwrite(fs, fs->fs_buffer, fs->fs_currentsector, 1); + if (ret < 0) + { + return ret; + } + } + } + + /* No longer dirty */ + + fs->fs_dirty = false; + } + return OK; +} + +/**************************************************************************** + * Name: fat_fscacheread + * + * Desciption: Read the specified sector into the sector cache, flushing any + * existing dirty sectors as necessary. + * + ****************************************************************************/ + +int fat_fscacheread(struct fat_mountpt_s *fs, off_t sector) +{ + int ret; + + /* fs->fs_currentsector holds the current sector that is buffered in + * fs->fs_buffer. If the requested sector is the same as this sector, then + * we do nothing. Otherwise, we will have to read the new sector. + */ + + if (fs->fs_currentsector != sector) + { + /* We will need to read the new sector. First, flush the cached + * sector if it is dirty. + */ + + ret = fat_fscacheflush(fs); + if (ret < 0) + { + return ret; + } + + /* Then read the specified sector into the cache */ + + ret = fat_hwread(fs, fs->fs_buffer, sector, 1); + if (ret < 0) + { + return ret; + } + + /* Update the cached sector number */ + + fs->fs_currentsector = sector; + } + + return OK; +} + +/**************************************************************************** + * Name: fat_ffcacheflush + * + * Desciption: Flush any dirty sectors as necessary + * + ****************************************************************************/ + +int fat_ffcacheflush(struct fat_mountpt_s *fs, struct fat_file_s *ff) +{ + int ret; + + /* Check if the ff_buffer is dirty. In this case, we will write back the + * contents of ff_buffer. + */ + + if (ff->ff_cachesector && + ff->ff_bflags && (FFBUFF_DIRTY|FFBUFF_VALID) == (FFBUFF_DIRTY|FFBUFF_VALID)) + { + /* Write the dirty sector */ + + ret = fat_hwwrite(fs, ff->ff_buffer, ff->ff_cachesector, 1); + if (ret < 0) + { + return ret; + } + + /* No longer dirty, but still valid */ + + ff->ff_bflags &= ~FFBUFF_DIRTY; + } + + return OK; +} + +/**************************************************************************** + * Name: fat_ffcacheread + * + * Desciption: Read the specified sector into the sector cache, flushing any + * existing dirty sectors as necessary. + * + ****************************************************************************/ + +int fat_ffcacheread(struct fat_mountpt_s *fs, struct fat_file_s *ff, off_t sector) +{ + int ret; + + /* ff->ff_cachesector holds the current sector that is buffered in + * ff->ff_buffer. If the requested sector is the same as this sector, then + * we do nothing. Otherwise, we will have to read the new sector. + */ + + if (ff->ff_cachesector != sector || (ff->ff_bflags & FFBUFF_VALID) == 0) + { + /* We will need to read the new sector. First, flush the cached + * sector if it is dirty. + */ + + ret = fat_ffcacheflush(fs, ff); + if (ret < 0) + { + return ret; + } + + /* Then read the specified sector into the cache */ + + ret = fat_hwread(fs, ff->ff_buffer, sector, 1); + if (ret < 0) + { + return ret; + } + + /* Update the cached sector number */ + + ff->ff_cachesector = sector; + ff->ff_bflags |= FFBUFF_VALID; + } + return OK; +} + +/**************************************************************************** + * Name: fat_ffcacheread + * + * Desciption: Invalidate the current file buffer contents + * + ****************************************************************************/ + +int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff) +{ + int ret; + + /* Is there anything valid in the buffer now? */ + + if ((ff->ff_bflags & FFBUFF_VALID) != 0) + { + /* We will invalidate the buffered sector */ + + ret = fat_ffcacheflush(fs, ff); + if (ret < 0) + { + return ret; + } + + /* Then discard the current cache contents */ + + ff->ff_bflags &= ~FFBUFF_VALID; + ff->ff_cachesector = 0; + } + return OK; +} + +/**************************************************************************** + * Name: fat_updatefsinfo + * + * Desciption: Flush evertyhing buffered for the mountpoint and update + * the FSINFO sector, if appropriate + * + ****************************************************************************/ + +int fat_updatefsinfo(struct fat_mountpt_s *fs) +{ + int ret; + + /* Flush the fs_buffer if it is dirty */ + + ret = fat_fscacheflush(fs); + if (ret == OK) + { + /* The FSINFO sector only has to be update for the case of a FAT32 file + * system. Check if the file system type.. If this is a FAT32 file + * system then the fs_fsidirty flag will indicate if the FSINFO sector + * needs to be re-written. + */ + + if (fs->fs_type == FSTYPE_FAT32 && fs->fs_fsidirty) + { + /* Create an image of the FSINFO sector in the fs_buffer */ + + memset(fs->fs_buffer, 0, fs->fs_hwsectorsize); + FSI_PUTLEADSIG(fs->fs_buffer, 0x41615252); + FSI_PUTSTRUCTSIG(fs->fs_buffer, 0x61417272); + FSI_PUTFREECOUNT(fs->fs_buffer, fs->fs_fsifreecount); + FSI_PUTNXTFREE(fs->fs_buffer, fs->fs_fsinextfree); + FSI_PUTTRAILSIG(fs->fs_buffer, BOOT_SIGNATURE32); + + /* Then flush this to disk */ + + fs->fs_currentsector = fs->fs_fsinfo; + fs->fs_dirty = true; + ret = fat_fscacheflush(fs); + + /* No longer dirty */ + + fs->fs_fsidirty = false; + } + } + return ret; +} + +/**************************************************************************** + * Name: fat_nfreeclusters + * + * Desciption: Get the number of free clusters + * + ****************************************************************************/ + +int fat_nfreeclusters(struct fat_mountpt_s *fs, off_t *pfreeclusters) +{ + uint32_t nfreeclusters; + + /* If number of the first free cluster is valid, then just return that value. */ + + if (fs->fs_fsifreecount <= fs->fs_nclusters - 2) + { + *pfreeclusters = fs->fs_fsifreecount; + return OK; + } + + /* Otherwise, we will have to count the number of free clusters */ + + nfreeclusters = 0; + if (fs->fs_type == FSTYPE_FAT12) + { + off_t sector; + + /* Examine every cluster in the fat */ + + for (sector = 2; sector < fs->fs_nclusters; sector++) + { + + /* If the cluster is unassigned, then increment the count of free clusters */ + + if ((uint16_t)fat_getcluster(fs, sector) == 0) + { + nfreeclusters++; + } + } + } + else + { + unsigned int cluster; + off_t fatsector; + unsigned int offset; + int ret; + + fatsector = fs->fs_fatbase; + offset = fs->fs_hwsectorsize; + + /* Examine each cluster in the fat */ + + for (cluster = fs->fs_nclusters; cluster > 0; cluster--) + { + /* If we are starting a new sector, then read the new sector in fs_buffer */ + + if (offset >= fs->fs_hwsectorsize) + { + ret = fat_fscacheread(fs, fatsector++); + if (ret < 0) + { + return ret; + } + + /* Reset the offset to the next FAT entry. + * Increment the sector number to read next time around. + */ + + offset = 0; + fatsector++; + } + + /* FAT16 and FAT32 differ only on the size of each cluster start + * sector number in the FAT. + */ + + if (fs->fs_type == FSTYPE_FAT16) + { + if (FAT_GETFAT16(fs->fs_buffer, offset) == 0) + { + nfreeclusters++; + } + offset += 2; + } + else + { + if (FAT_GETFAT32(fs->fs_buffer, offset) == 0) + { + nfreeclusters++; + } + + offset += 4; + } + } + } + + fs->fs_fsifreecount = nfreeclusters; + if (fs->fs_type == FSTYPE_FAT32) + { + fs->fs_fsidirty = true; + } + + *pfreeclusters = nfreeclusters; + return OK; +} + +/**************************************************************************** + * Name: fat_nfreeclusters + * + * Desciption: + * Given the file position, set the correct current sector to access. + * + ****************************************************************************/ + +int fat_currentsector(struct fat_mountpt_s *fs, struct fat_file_s *ff, + off_t position) +{ + int sectoroffset; + + if (position <= ff->ff_size ) + { + /* sectoroffset is the sector number offset into the current cluster */ + + sectoroffset = SEC_NSECTORS(fs, position) & CLUS_NDXMASK(fs); + + /* The current cluster is the first sector of the cluster plus + * the sector offset + */ + + ff->ff_currentsector = fat_cluster2sector(fs, ff->ff_currentcluster) + + sectoroffset; + + /* The remainder is the number of sectors left in the cluster to be + * read/written + */ + + ff->ff_sectorsincluster = fs->fs_fatsecperclus - sectoroffset; + + fvdbg("position=%d currentsector=%d sectorsincluster=%d\n", + position, ff->ff_currentsector, ff->ff_sectorsincluster); + + return OK; + } + + /* The position does not lie within the file */ + + return -ENOSPC; +} + + diff --git a/nuttx/fs/fat/fs_mkfatfs.c b/nuttx/fs/fat/fs_mkfatfs.c new file mode 100644 index 0000000000..7a8b2ab921 --- /dev/null +++ b/nuttx/fs/fat/fs_mkfatfs.c @@ -0,0 +1,312 @@ +/**************************************************************************** + * fs/fat/fs_writefat.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "fs_internal.h" +#include "fs_fat32.h" +#include "fs_mkfatfs.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mkfatfs_getgeometry + * + * Description: + * Get the sector size and number of sectors of the underlying block + * device. + * + * Input: + * fmt - Caller specified format parameters + * var - Other format parameters that are not caller specifiable. (Most + * set by mkfatfs_configfatfs()). + * + * Return: + * Zero on success; negated errno on failure + * + ****************************************************************************/ + +static inline int mkfatfs_getgeometry(FAR struct fat_format_s *fmt, + FAR struct fat_var_s *var) +{ + struct geometry geometry; + int ret; + + /* Get the device geometry */ + + ret = DEV_GEOMETRY(geometry); + if (ret < 0) + { + fdbg("geometry() returned %d\n", ret); + return ret; + } + + if (!geometry.geo_available || !geometry.geo_writeenabled) + { + fdbg("Media is not available\n", ret); + return -ENODEV; + } + + /* Check if the user provided maxblocks was provided and, if so, that is it less than + * the actual number of blocks on the device. + */ + + if (fmt->ff_nsectors != 0) + { + if (fmt->ff_nsectors > geometry.geo_nsectors) + { + fdbg("User maxblocks (%d) exceeds blocks on device (%d)\n", + fmt->ff_nsectors, geometry.geo_nsectors); + return -EINVAL; + } + } + else + { + /* Use the actual number of blocks on the device */ + + fmt->ff_nsectors = geometry.geo_nsectors; + } + + /* Verify that we can handle this sector size */ + + var->fv_sectorsize = geometry.geo_sectorsize; + switch (var->fv_sectorsize) + { + case 512: + var->fv_sectshift = 9; + break; + + case 1024: + var->fv_sectshift = 10; + break; + + case 2048: + var->fv_sectshift = 11; + break; + + case 4096: + var->fv_sectshift = 12; + break; + + default: + fdbg("Unsupported sector size: %d\n", var->fv_sectorsize); + return -EPERM; + } + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mkfatfs + * + * Description: + * Make a FAT file system image on the specified block device + * + * Inputs: + * pathname - the full path to a registered block driver + * fmt - Describes characteristics of the desired filesystem + * + * Return: + * Zero (OK) on success; -1 (ERROR) on failure with errno set appropriately: + * + * EINVAL - NULL block driver string, bad number of FATS in 'fmt', bad FAT + * size in 'fmt', bad cluster size in 'fmt' + * ENOENT - 'pathname' does not refer to anything in the filesystem. + * ENOTBLK - 'pathname' does not refer to a block driver + * EACCES - block driver does not support wrie or geometry methods + * + * Assumptions: + * - The caller must assure that the block driver is not mounted and not in + * use when this function is called. The result of formatting a mounted + * device is indeterminate (but likely not good). + * + ****************************************************************************/ +int mkfatfs(FAR const char *pathname, FAR struct fat_format_s *fmt) +{ + struct fat_var_s var; + int ret; + + /* Initialize */ + + memset(&var, 0, sizeof(struct fat_var_s)); + + /* Get the filesystem creation time */ + + var.fv_createtime = fat_systime2fattime(); + + /* Verify format options (only when DEBUG enabled) */ + +#ifdef CONFIG_DEBUG + if (!pathname) + { + fdbg("No block driver path\n"); + ret = -EINVAL; + goto errout; + } + + if (fmt->ff_nfats < 1 || fmt->ff_nfats > 4) + { + fdbg("Invalid number of fats: %d\n", fmt->ff_nfats); + ret = -EINVAL; + goto errout; + } + + if (fmt->ff_fattype != 0 && fmt->ff_fattype != 12 && + fmt->ff_fattype != 16 && fmt->ff_fattype != 32) + { + fdbg("Invalid FAT size: %d\n", fmt->ff_fattype); + ret = -EINVAL; + goto errout; + } +#endif + var.fv_fattype = fmt->ff_fattype; + + /* The valid range off ff_clustshift is {0,1,..7} corresponding to + * cluster sizes of {1,2,..128} sectors. The special value of 0xff + * means that we should autoselect the cluster sizel. + */ +#ifdef CONFIG_DEBUG + if (fmt->ff_clustshift > 7 && fmt->ff_clustshift != 0xff) + { + fdbg("Invalid cluster shift value: %d\n", fmt->ff_clustshift); + ret = -EINVAL; + goto errout; + } + + if (fmt->ff_rootdirentries != 0 && (fmt->ff_rootdirentries < 16 || fmt->ff_rootdirentries > 32767)) + { + fdbg("Invalid number of root dir entries: %d\n", fmt->ff_rootdirentries); + ret = -EINVAL; + goto errout; + } + + if (fmt->ff_rsvdseccount != 0 && (fmt->ff_rsvdseccount < 1 || fmt->ff_rsvdseccount > 32767)) + { + fdbg("Invalid number of reserved sectors: %d\n", fmt->ff_rsvdseccount); + ret = -EINVAL; + goto errout; + } +#endif + + /* Find the inode of the block driver indentified by 'source' */ + + ret = open_blockdriver(pathname, 0, &var.fv_inode); + if (ret < 0) + { + fdbg("Failed to open %s\n", pathname); + goto errout; + } + + /* Make sure that the inode supports the write and geometry methods at a minimum */ + + if (!var.fv_inode->u.i_bops->write || !var.fv_inode->u.i_bops->geometry) + { + fdbg("%s does not support write or geometry methods\n", pathname); + ret = -EACCES; + goto errout_with_driver; + } + + /* Determine the volume configuration based upon the input values and upon the + * reported device geometry. + */ + + ret = mkfatfs_getgeometry(fmt, &var); + if (ret < 0) + { + goto errout_with_driver; + } + + /* Configure the file system */ + + ret = mkfatfs_configfatfs(fmt, &var); + if (ret < 0) + { + goto errout_with_driver; + } + + /* Allocate a buffer that will be working sector memory */ + + var.fv_sect = (uint8_t*)malloc(var.fv_sectorsize); + if (!var.fv_sect) + { + fdbg("Failed to allocate working buffers\n"); + goto errout_with_driver; + } + + /* Write the filesystem to media */ + + ret = mkfatfs_writefatfs(fmt, &var); + +errout_with_driver: + /* Close the driver */ + + (void)close_blockdriver(var.fv_inode); + +errout: + /* Release all allocated memory */ + + if (var.fv_sect) + { + free(var.fv_sect); + } + + /* Return any reported errors */ + + if (ret < 0) + { + errno = -ret; + return ERROR; + } + return OK; +} diff --git a/nuttx/fs/fat/fs_mkfatfs.h b/nuttx/fs/fat/fs_mkfatfs.h new file mode 100644 index 0000000000..214697c519 --- /dev/null +++ b/nuttx/fs/fat/fs_mkfatfs.h @@ -0,0 +1,170 @@ +/**************************************************************************** + * fs/fat/fs_mkfat.h + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_FAT_FS_MKATFS_H +#define __FS_FAT_FS_MKATFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Only the "hard drive" media type is used */ + +#define FAT_DEFAULT_MEDIA_TYPE 0xf8 + +/* Default hard driver geometry */ + +#define FAT_DEFAULT_SECPERTRK 63 +#define FAT_DEFAULT_NUMHEADS 255 + +/* FSINFO is always at this sector */ + +#define FAT_DEFAULT_FSINFO_SECTOR 1 + +/* FAT32 foot cluster number */ + +#define FAT32_DEFAULT_ROOT_CLUSTER 2 + +/* Macros to simplify direct block driver access */ + +#define DEV_OPEN() \ + var->fb_inode->u.i_bops->open ? \ + var->fv_inode->u.i_bops->open(var->fv_inode) : \ + 0 +#define DEV_CLOSE() \ + var->fb_inode->u.i_bops->close ? \ + var->fv_inode->u.i_bops->close(var->fv_inode) : \ + 0 +#define DEV_READ(buf, sect, nsect) \ + var->fv_inode->u.i_bops->read(var->fv_inode, buf, sect, nsect) +#define DEV_WRITE(buf, sect, nsect) \ + var->fv_inode->u.i_bops->write(var->fv_inode, buf, sect, nsect) +#define DEV_GEOMETRY(geo) \ + var->fv_inode->u.i_bops->geometry(var->fv_inode, &geo) +#define DEV_IOCTL(cmd, arg) \ + var->fv_inode->u.i_bops->ioctl(var->fv_inode, cmd, arg) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This structure (plus the user-provided struct fat_format_s) describes + * the format FAT file system. All "global" variables used in the format + * logic are contained in this structure so that is possible to format two + * block devices concurrently. + */ + +struct fat_var_s +{ + struct inode *fv_inode; /* The block driver "handle" */ + uint8_t fv_jump[3]; /* 3-byte boot jump instruction */ + uint8_t fv_sectshift; /* Log2 of fv_sectorsize */ + uint8_t fv_nrootdirsects; /* Number of root directory sectors */ + uint8_t fv_fattype; /* FAT size: 0 (not determined), 12, 16, or 32 */ + uint16_t fv_bootcodesize; /* Size of array at fv_bootcode */ + uint32_t fv_createtime; /* Creation time */ + uint32_t fv_sectorsize; /* Size of one hardware sector */ + uint32_t fv_nfatsects; /* Number of sectors in each FAT */ + uint32_t fv_nclusters; /* Number of clusters */ + uint8_t *fv_sect; /* Allocated working sector buffer */ + const uint8_t *fv_bootcode; /* Points to boot code to put into MBR */ +}; + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: mkfatfs_configfatfs + * + * Description: + * Based on the geometry of the block device and upon the caller-selected + * values, configure the FAT filesystem for the device. + * + * Input: + * fmt - Caller specified format parameters + * var - Holds disk geomtry data. Also, the location to return FAT + * configuration data + * + * Return: + * Zero on success; negated errno on failure + * + ****************************************************************************/ +EXTERN int mkfatfs_configfatfs(FAR struct fat_format_s *fmt, + FAR struct fat_var_s *var); + +/**************************************************************************** + * Name: mkfatfs_writefat + * + * Description: + * Write the configured fat filesystem to the block device + * + * Input: + * fmt - Caller specified format parameters + * var - Other format parameters that are not caller specifiable. (Most + * set by mkfatfs_configfatfs()). + * + * Return: + * Zero on success; negated errno on failure + * + ****************************************************************************/ +EXTERN int mkfatfs_writefatfs(FAR struct fat_format_s *fmt, + FAR struct fat_var_s *var); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __FS_FAT_FS_MKATFS_H */ diff --git a/nuttx/fs/fat/fs_writefat.c b/nuttx/fs/fat/fs_writefat.c new file mode 100644 index 0000000000..02d55d6258 --- /dev/null +++ b/nuttx/fs/fat/fs_writefat.c @@ -0,0 +1,544 @@ +/**************************************************************************** + * fs/fat/fs_writefat.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "fs_internal.h" +#include "fs_fat32.h" +#include "fs_mkfatfs.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mkfatfs_initmbr + * + * Description: + * Initialize the sector image of a masterbood record + * + * Input: + * fmt - User specified format parameters + * var - Other format parameters that are not user specifiable + * + * Return: + * None; caller is responsible for providing valid parameters. + * + ****************************************************************************/ +static inline void mkfatfs_initmbr(FAR struct fat_format_s *fmt, + FAR struct fat_var_s *var) +{ + memset(var->fv_sect, 0, var->fv_sectorsize); + + /* 3@0: Jump instruction to boot code */ + + memcpy(&var->fv_sect[BS_JUMP], var->fv_jump, 3); + + /* 8@3: Usually "MSWIN4.1" */ + + strcpy((char*)&var->fv_sect[BS_OEMNAME], "NUTTX "); + + /* 2@11: Bytes per sector: 512, 1024, 2048, 4096 */ + + MBR_PUTBYTESPERSEC(var->fv_sect, var->fv_sectorsize); + + /* 1@13: Sectors per allocation unit: 2**n, n=0..7 */ + + MBR_PUTSECPERCLUS(var->fv_sect, (1 << fmt->ff_clustshift)); + + /* 2@14: Reserved sector count: Usually 32 */ + + MBR_PUTRESVDSECCOUNT(var->fv_sect, fmt->ff_rsvdseccount); + + /* 1@16: Number of FAT data structures: always 2 */ + + MBR_PUTNUMFATS(var->fv_sect, fmt->ff_nfats); + + /* 2@17: FAT12/16: Must be 0 for FAT32 */ + + MBR_PUTROOTENTCNT(var->fv_sect, fmt->ff_rootdirentries); + + /* 2@19: FAT12/16: Must be 0, see BS_TOTSEC32. + * Handled with 4@32: Total count of sectors on the volume */ + + if (fmt->ff_nsectors >= 65536) + { + MBR_PUTTOTSEC32(var->fv_sect, fmt->ff_nsectors); + } + else + { + MBR_PUTTOTSEC16(var->fv_sect, (uint16_t)fmt->ff_nsectors); + } + + /* 1@21: Media code: f0, f8, f9-fa, fc-ff */ + + MBR_PUTMEDIA(var->fv_sect, FAT_DEFAULT_MEDIA_TYPE); /* Only "hard drive" supported */ + + /* 2@22: FAT12/16: Must be 0, see BS32_FATSZ32 -- handled in FAT specific logic */ + + /* 2@24: Sectors per track geometry value and 2@26: Number of heads geometry value */ + + MBR_PUTSECPERTRK(var->fv_sect, FAT_DEFAULT_SECPERTRK); + MBR_PUTNUMHEADS(var->fv_sect, FAT_DEFAULT_NUMHEADS); + + /* 4@28: Count of hidden sectors preceding FAT */ + + MBR_PUTHIDSEC(var->fv_sect, fmt->ff_hidsec); + + /* 4@32: Total count of sectors on the volume -- handled above */ + + /* Most of the rest of the sector depends on the FAT size */ + + if (fmt->ff_fattype != 32) + { + /* 2@22: FAT12/16: Must be 0, see BS32_FATSZ32 */ + + MBR_PUTFATSZ16(var->fv_sect, (uint16_t)var->fv_nfatsects); + + /* The following fields are only valid for FAT12/16 */ + /* 1@36: Drive number for MSDOS bootstrap -- left zero */ + /* 1@37: Reserved (zero) */ + /* 1@38: Extended boot signature: 0x29 if following valid */ + + MBR_PUTBOOTSIG16(var->fv_sect, EXTBOOT_SIGNATURE); + + /* 4@39: Volume serial number */ + + MBR_PUTVOLID16(var->fv_sect, fmt->ff_volumeid); + + /* 11@43: Volume label */ + + memcpy(&var->fv_sect[BS16_VOLLAB], fmt->ff_volumelabel, 11); + + /* 8@54: "FAT12 ", "FAT16 ", or "FAT " */ + + if (fmt->ff_fattype == 12) + { + memcpy(&var->fv_sect[BS16_FILESYSTYPE], "FAT12 ", 8); + } + else /* if (fmt->ff_fattype == 16) */ + { + memcpy(&var->fv_sect[BS16_FILESYSTYPE], "FAT16 ", 8); + } + + /* Boot code may be placed in the remainder of the sector */ + + memcpy(&var->fv_sect[BS16_BOOTCODE], var->fv_bootcode, var->fv_bootcodesize); + } + else + { + /* The following fields are only valid for FAT32 */ + /* 4@36: Count of sectors occupied by one FAT */ + + MBR_PUTFATSZ32(var->fv_sect, var->fv_nfatsects); + + /* 2@40: 0-3:Active FAT, 7=0 both FATS, 7=1 one FAT -- left zero*/ + /* 2@42: MSB:Major LSB:Minor revision number (0.0) -- left zero */ + /* 4@44: Cluster no. of 1st cluster of root dir */ + + MBR_PUTROOTCLUS(var->fv_sect, FAT32_DEFAULT_ROOT_CLUSTER); + + /* 2@48: Sector number of fsinfo structure. Usually 1. */ + + MBR_PUTFSINFO(var->fv_sect, FAT_DEFAULT_FSINFO_SECTOR); + + /* 2@50: Sector number of boot record. Usually 6 */ + + MBR_PUTBKBOOTSEC(var->fv_sect, fmt->ff_backupboot); + + /* 12@52: Reserved (zero) */ + /* 1@64: Drive number for MSDOS bootstrap -- left zero */ + /* 1@65: Reserved (zero) */ + /* 1@66: Extended boot signature: 0x29 if following valid */ + + MBR_PUTBOOTSIG32(var->fv_sect, EXTBOOT_SIGNATURE); + + /* 4@67: Volume serial number */ + + MBR_PUTVOLID32(var->fv_sect, fmt->ff_volumeid); + + /* 11@71: Volume label */ + + memcpy(&var->fv_sect[BS32_VOLLAB], fmt->ff_volumelabel, 11); + + /* 8@82: "FAT12 ", "FAT16 ", or "FAT " */ + + memcpy(&var->fv_sect[BS32_FILESYSTYPE], "FAT32 ", 8); + + /* Boot code may be placed in the remainder of the sector */ + + memcpy(&var->fv_sect[BS16_BOOTCODE], var->fv_bootcode, var->fv_bootcodesize); + } + + /* The magic bytes at the end of the MBR are common to FAT12/16/32 */ + /* 2@510: Valid MBRs have 0x55aa here */ + + MBR_PUTSIGNATURE(var->fv_sect, BOOT_SIGNATURE16); +} + +/**************************************************************************** + * Name: mkfatfs_initfsinfo + * + * Description: + * Initialize the FAT32 FSINFO sector image + * + * Input: + * fmt - User specified format parameters + * var - Other format parameters that are not user specifiable + * + * Return: + * None; caller is responsible for providing valid parameters. + * + ****************************************************************************/ +static inline void mkfatfs_initfsinfo(FAR struct fat_format_s *fmt, + FAR struct fat_var_s *var) +{ + memset(var->fv_sect, 0, var->fv_sectorsize); + + /* 4@0: 0x41615252 = "RRaA" */ + + FSI_PUTLEADSIG(var->fv_sect, 0x41615252); + + /* 480@4: Reserved (zero) */ + /* 4@484: 0x61417272 = "rrAa" */ + + FSI_PUTSTRUCTSIG(var->fv_sect, 0x61417272); + + /* 4@488: Last free cluster count on volume */ + + FSI_PUTFREECOUNT(var->fv_sect, var->fv_nclusters - 1); + + /* 4@492: Cluster number of 1st free cluster */ + + FSI_PUTNXTFREE(var->fv_sect, FAT32_DEFAULT_ROOT_CLUSTER); + + /* 12@496: Reserved (zero) */ + /* 4@508: 0xaa550000 */ + + FSI_PUTTRAILSIG(var->fv_sect, BOOT_SIGNATURE32); +} + +/**************************************************************************** + * Name: mkfatfs_initrootdir + * + * Description: + * Initialize one root directory sector image + * + * Input: + * fmt - User specified format parameters + * var - Other format parameters that are not user specifiable + * sectno - On FAT32, the root directory is a cluster chain. + * This value indicates which sector of the cluster should be produced. + * + * Return: + * None; caller is responsible for providing valid parameters. + * + ****************************************************************************/ +static inline void mkfatfs_initrootdir(FAR struct fat_format_s *fmt, + FAR struct fat_var_s *var, int sectno) +{ + memset(var->fv_sect, 0, var->fv_sectorsize); + if (sectno == 0) + { + /* It is only necessary to set data in the first sector of the directory */ + + if (memcmp(fmt->ff_volumelabel, " ", 11)) + { + memcpy(&var->fv_sect[DIR_NAME], fmt->ff_volumelabel, 11); + } + + DIR_PUTATTRIBUTES(var->fv_sect, FATATTR_VOLUMEID); + DIR_PUTCRTIME(var->fv_sect, var->fv_createtime & 0xffff); + DIR_PUTWRTTIME(var->fv_sect, var->fv_createtime & 0xffff); + DIR_PUTCRDATE(var->fv_sect, var->fv_createtime >> 16); + DIR_PUTWRTDATE(var->fv_sect, var->fv_createtime >> 16); + } +} + +/**************************************************************************** + * Name: mkfatfs_writembr + * + * Description: + * Write the master boot record and, for FAT32, the backup boot record and + * the fsinfo sector. + * + * Input: + * fmt - User specified format parameters + * var - Other format parameters that are not user specifiable + * + * Return: + * Zero on success; negated errno on failure + * + ****************************************************************************/ + +static inline int mkfatfs_writembr(FAR struct fat_format_s *fmt, + FAR struct fat_var_s *var) +{ + int sectno; + int ret; + + /* Create an image of the configured master boot record */ + + mkfatfs_initmbr(fmt, var); + + /* Write the master boot record as sector zero */ + + ret = DEV_WRITE(var->fv_sect, 0, 1); + + /* Write all of the reserved sectors */ + + memset(var->fv_sect, 0, var->fv_sectorsize); + for (sectno = 1; sectno < fmt->ff_rsvdseccount && ret >= 0; sectno++) + { + ret = DEV_WRITE(var->fv_sect, sectno, 1); + } + + /* Write FAT32-specific sectors */ + + if (ret >= 0 && fmt->ff_fattype == 32) + { + /* Write the backup master boot record */ + + if (fmt->ff_backupboot != 0) + { + /* Create another copy of the configured master boot record */ + + mkfatfs_initmbr(fmt, var); + + /* Write it to the backup location */ + + ret = DEV_WRITE(var->fv_sect, fmt->ff_backupboot, 1); + } + + if (ret >= 0) + { + /* Create an image of the fsinfo sector*/ + + mkfatfs_initfsinfo(fmt, var); + + /* Write the fsinfo sector */ + + ret = DEV_WRITE(var->fv_sect, FAT_DEFAULT_FSINFO_SECTOR, 1); + } + } + + return ret; +} + +/**************************************************************************** + * Name: mkfatfs_writefat + * + * Description: + * Write the FAT sectors + * + * Input: + * fmt - User specified format parameters + * var - Other format parameters that are not user specifiable + * + * Return: + * Zero on success; negated errno on failure + * + ****************************************************************************/ + +static inline int mkfatfs_writefat(FAR struct fat_format_s *fmt, + FAR struct fat_var_s *var) +{ + off_t offset = fmt->ff_rsvdseccount; + int fatno; + int sectno; + int ret; + + /* Loop for each FAT copy */ + + for (fatno = 0; fatno < fmt->ff_nfats; fatno++) + { + /* Loop for each sector in the FAT */ + + for (sectno = 0; sectno < var->fv_nfatsects; sectno++) + { + memset(var->fv_sect, 0, var->fv_sectorsize); + + /* Mark cluster allocations in sector one of each FAT */ + + if (sectno == 0) + { + memset(var->fv_sect, 0, var->fv_sectorsize); + switch(fmt->ff_fattype) + { + case 12: + /* Mark the first two full FAT entries -- 24 bits, 3 bytes total */ + + memset(var->fv_sect, 0xff, 3); + break; + + case 16: + /* Mark the first two full FAT entries -- 32 bits, 4 bytes total */ + + memset(var->fv_sect, 0xff, 4); + break; + + case 32: + default: /* Shouldn't happen */ + /* Mark the first two full FAT entries -- 64 bits, 8 bytes total */ + + memset(var->fv_sect, 0xff, 8); + + /* Cluster 2 is used as the root directory. Mark as EOF */ + + var->fv_sect[8] = 0xf8; + memset(&var->fv_sect[9], 0xff, 3); + break; + } + + /* Save the media type in the first byte of the FAT */ + + var->fv_sect[0] = FAT_DEFAULT_MEDIA_TYPE; + } + + /* Write the FAT sector */ + + ret = DEV_WRITE(var->fv_sect, offset, 1); + if (ret < 0) + { + return ret; + } + offset++; + } + } + return OK; +} + +/**************************************************************************** + * Name: mkfatfs_writerootdir + * + * Description: + * Write the root directory sectors + * + * Input: + * fmt - User specified format parameters + * var - Other format parameters that are not user specifiable + * + * Return: + * Zero on success; negated errno on failure + * + ****************************************************************************/ + +static inline int mkfatfs_writerootdir(FAR struct fat_format_s *fmt, + FAR struct fat_var_s *var) +{ + off_t offset = fmt->ff_rsvdseccount + fmt->ff_nfats * var->fv_nfatsects; + int ret; + int i; + + /* Write the root directory after the last FAT. This is the root directory + * area for FAT12/16, and the first cluster on FAT32. + */ + + for (i = 0; i < var->fv_nrootdirsects; i++) + { + /* Format the next sector of the root directory */ + + mkfatfs_initrootdir(fmt, var, i); + + /* Write the next sector of the root directory */ + + ret = DEV_WRITE(var->fv_sect, offset, 1); + if (ret < 0) + { + return ret; + } + offset++; + } + return 0; +} + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mkfatfs_writefat + * + * Description: + * Write the configured fat filesystem to the block device + * + * Input: + * fmt - Caller specified format parameters + * var - Other format parameters that are not caller specifiable. (Most + * set by mkfatfs_configfatfs()). + * + * Return: + * Zero on success; negated errno on failure + * + ****************************************************************************/ + +int mkfatfs_writefatfs(FAR struct fat_format_s *fmt, + FAR struct fat_var_s *var) +{ + int ret; + + /* Write the master boot record (also the backup and fsinfo sectors) */ + + ret = mkfatfs_writembr(fmt, var); + + /* Write FATs */ + + if (ret >= 0) + { + ret = mkfatfs_writefat(fmt, var); + } + + /* Write the root directory after the last FAT. */ + + if (ret >= 0) + { + ret = mkfatfs_writerootdir(fmt, var); + } + return ret; +} + diff --git a/nuttx/fs/fs_close.c b/nuttx/fs/fs_close.c new file mode 100644 index 0000000000..7f08995dee --- /dev/null +++ b/nuttx/fs/fs_close.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * fs/fs_close.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 +# include +#endif + +#include "fs_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: close + * + * Description: + * close() closes a file descriptor, so that it no longer refers to any + * file and may be reused. Any record locks (see fcntl(2)) held on the file + * it was associated with, and owned by the process, are removed (regardless + * of the file descriptor that was used to obtain the lock). + * + * If fd is the last copy of a particular file descriptor the resources + * associated with it are freed; if the descriptor was the last reference + * to a file which has been removed using unlink(2) the file is deleted. + * + * Parameters: + * fd file descriptor to close + * + * Returned Value: + * 0 on success; -1 on error with errno set appropriately. + * + * Assumptions: + * + ****************************************************************************/ + +int close(int fd) +{ + int err; +#if CONFIG_NFILE_DESCRIPTORS > 0 + int ret; + + /* Did we get a valid file descriptor? */ + + if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) +#endif + { + /* Close a socket descriptor */ + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS)) + { + return net_close(fd); + } + else +#endif + { + err = EBADF; + goto errout; + } + } + +#if CONFIG_NFILE_DESCRIPTORS > 0 + /* Close the driver or mountpoint. NOTES: (1) there is no + * exclusion mechanism here , the driver or mountpoint must be + * able to handle concurrent operations internally, (2) The driver + * may have been opened numerous times (for different file + * descriptors) and must also handle being closed numerous times. + * (3) for the case of the mountpoint, we depend on the close + * methods bing identical in signature and position in the operations + * vtable. + */ + + ret = files_close(fd); + if (ret < 0) + { + /* An error occurred while closing the driver */ + + err = -ret; + goto errout; + } + return OK; + +#endif + +errout: + set_errno(err); + return ERROR; +} + diff --git a/nuttx/fs/fs_closeblockdriver.c b/nuttx/fs/fs_closeblockdriver.c new file mode 100644 index 0000000000..2151b04df9 --- /dev/null +++ b/nuttx/fs/fs_closeblockdriver.c @@ -0,0 +1,112 @@ +/**************************************************************************** + * fs/fs_closeblockdriver.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in pathname and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of pathname code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: close_blockdriver + * + * Description: + * Call the close method and release the inode + * + * Inputs: + * inode - reference to the inode of a block driver opened by open_blockdriver + * + * Return: + * Returns zero on success or a negated errno on failure: + * + * EINVAL - inode is NULL + * ENOTBLK - The inode is not a block driver + * + ****************************************************************************/ + +int close_blockdriver(FAR struct inode *inode) +{ + int ret = 0; /* Assume success */ + + /* Sanity checks */ + +#ifdef CONFIG_DEBUG + if (!inode || !inode->u.i_bops) + { + ret = -EINVAL; + goto errout; + } +#endif + + /* Verify that the inode is a block driver. */ + + if (!INODE_IS_BLOCK(inode)) + { + fdbg("inode is not a block driver\n"); + ret = -ENOTBLK; + goto errout; + } + + /* Close the block driver. Not that no mutually exclusive access + * to the driver is enforced here. That must be done in the driver + * if needed. + */ + + if (inode->u.i_bops->close) + { + ret = inode->u.i_bops->close(inode); + } + + /* Then release the reference on the inode */ + + inode_release(inode); + +errout: + return ret; +} diff --git a/nuttx/fs/fs_closedir.c b/nuttx/fs/fs_closedir.c new file mode 100644 index 0000000000..fe09944787 --- /dev/null +++ b/nuttx/fs/fs_closedir.c @@ -0,0 +1,148 @@ +/**************************************************************************** + * fs/fs_closedir.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: closedir + * + * Description: + * The closedir() function closes the directory stream associated with + * 'dirp'. The directory stream descriptor 'dirp' is not available after + * this call. + * + * Inputs: + * dirp -- An instance of type DIR created by a previous call to opendir(); + * + * Return: + * The closedir() function returns 0 on success. On error, -1 is + * returned, and errno is set appropriately. + * + ****************************************************************************/ + +int closedir(FAR DIR *dirp) +{ + struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp; + struct inode *inode; + int ret; + + if (!idir || !idir->fd_root) + { + ret = EBADF; + goto errout; + } + + /* This is the 'root' inode of the directory. This means different + * things wih different filesystems. + */ + + inode = idir->fd_root; + + /* The way that we handle the close operation depends on what kind of root + * inode we have open. + */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + if (INODE_IS_MOUNTPT(inode) && !DIRENT_ISPSUEDONODE(idir->fd_flags)) + { + /* The node is a file system mointpoint. Verify that the mountpoint + * supports the closedir() method (not an error if it does not) + */ + + if (inode->u.i_mops && inode->u.i_mops->closedir) + { + /* Perform the closedir() operation */ + + ret = inode->u.i_mops->closedir(inode, idir); + if (ret < 0) + { + ret = -ret; + goto errout_with_inode; + } + } + } + else +#endif + { + /* The node is part of the root psuedo file system, release + * our contained reference to the 'next' inode. + */ + + if (idir->u.psuedo.fd_next) + { + inode_release(idir->u.psuedo.fd_next); + } + } + + /* Release our references on the contained 'root' inode */ + + inode_release(idir->fd_root); + + /* Then release the container */ + + kfree(idir); + return OK; + +#ifndef CONFIG_DISABLE_MOUNTPOINT +errout_with_inode: + inode_release(inode); + kfree(idir); +#endif + +errout: + set_errno(ret); + return ERROR; +} diff --git a/nuttx/fs/fs_dup.c b/nuttx/fs/fs_dup.c new file mode 100644 index 0000000000..890da039bc --- /dev/null +++ b/nuttx/fs/fs_dup.c @@ -0,0 +1,107 @@ +/**************************************************************************** + * fs/fs_dup.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dup + * + * Description: + * Clone a file or socket descriptor to an arbitray descriptor number + * + ****************************************************************************/ + +int dup(int fildes) +{ + int ret = OK; + + /* Check the range of the descriptor to see if we got a file or a socket + * descriptor. */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + if ((unsigned int)fildes < CONFIG_NFILE_DESCRIPTORS) + { + /* Its a valid file descriptor.. dup the file descriptor using any + * other file descriptor*/ + + ret = file_dup(fildes, 0); + } + else +#endif + { + /* Not a vailid file descriptor. Did we get a valid socket descriptor? */ + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + if ((unsigned int)fildes < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS)) + { + /* Yes.. dup the socket descriptor */ + + ret = net_dup(fildes, CONFIG_NFILE_DESCRIPTORS); + } + else +#endif + { + /* No.. then it is a bad descriptor number */ + + set_errno(EBADF); + ret = ERROR; + } + } + + return ret; +} diff --git a/nuttx/fs/fs_dup2.c b/nuttx/fs/fs_dup2.c new file mode 100644 index 0000000000..45ff2bb738 --- /dev/null +++ b/nuttx/fs/fs_dup2.c @@ -0,0 +1,109 @@ +/**************************************************************************** + * fs/fs_dup2.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "fs_internal.h" + +/* This logic in this applies only when both socket and file descriptors are + * in that case, this function descriminates which type of dup2 is being + * performed. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dup2 + * + * Description: + * Clone a file descriptor or socket descriptor to a specific descriptor + * number + * + ****************************************************************************/ + +int dup2(int fildes1, int fildes2) +{ + /* Check the range of the descriptor to see if we got a file or a socket + * descriptor. + */ + + if ((unsigned int)fildes1 >= CONFIG_NFILE_DESCRIPTORS) + { + /* Not a valid file descriptor. Did we get a valid socket descriptor? */ + + if ((unsigned int)fildes1 < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS)) + { + /* Yes.. dup the socket descriptor */ + + return net_dup2(fildes1, fildes2); + } + else + { + /* No.. then it is a bad descriptor number */ + + set_errno(EBADF); + return ERROR; + } + } + else + { + /* Its a valid file descriptor.. dup the file descriptor */ + + return file_dup2(fildes1, fildes2); + } +} + +#endif /* CONFIG_NFILE_DESCRIPTORS > 0 ... */ + diff --git a/nuttx/fs/fs_fcntl.c b/nuttx/fs/fs_fcntl.c new file mode 100644 index 0000000000..ff53b0f205 --- /dev/null +++ b/nuttx/fs/fs_fcntl.c @@ -0,0 +1,264 @@ +/**************************************************************************** + * fs/fs_fcntl.c + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: file_vfcntl + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static inline int file_vfcntl(int fildes, int cmd, va_list ap) +{ + FAR struct filelist *list; + FAR struct file *this_file; + int err = 0; + int ret = OK; + + /* Get the thread-specific file list */ + + list = sched_getfiles(); + if (!list) + { + err = EMFILE; + goto errout; + } + + /* Was this file opened ? */ + + this_file = &list->fl_files[fildes]; + if (!this_file->f_inode) + { + err = EBADF; + goto errout; + } + + switch (cmd) + { + case F_DUPFD: + /* Return a new file descriptor which shall be the lowest numbered + * available (that is, not already open) file descriptor greater than + * or equal to the third argument, arg, taken as an integer of type + * int. The new file descriptor shall refer to the same open file + * description as the original file descriptor, and shall share any + * locks. The FD_CLOEXEC flag associated with the new file descriptor + * shall be cleared to keep the file open across calls to one of the + * exec functions. + */ + + { + ret = file_dup(fildes, va_arg(ap, int)); + } + break; + + case F_GETFD: + /* Get the file descriptor flags defined in that are associated + * with the file descriptor fildes. File descriptor flags are associated + * with a single file descriptor and do not affect other file descriptors + * that refer to the same file. + */ + + case F_SETFD: + /* Set the file descriptor flags defined in , that are associated + * with fildes, to the third argument, arg, taken as type int. If the + * FD_CLOEXEC flag in the third argument is 0, the file shall remain open + * across the exec functions; otherwise, the file shall be closed upon + * successful execution of one of the exec functions. + */ + + err = ENOSYS; + break; + + case F_GETFL: + /* Get the file status flags and file access modes, defined in , + * for the file description associated with fildes. The file access modes + * can be extracted from the return value using the mask O_ACCMODE, which is + * defined in . File status flags and file access modes are associated + * with the file description and do not affect other file descriptors that + * refer to the same file with different open file descriptions. + */ + + { + ret = this_file->f_oflags; + } + break; + + case F_SETFL: + /* Set the file status flags, defined in , for the file description + * associated with fildes from the corresponding bits in the third argument, + * arg, taken as type int. Bits corresponding to the file access mode and + * the file creation flags, as defined in , that are set in arg shall + * be ignored. If any bits in arg other than those mentioned here are changed + * by the application, the result is unspecified. + */ + + { + this_file->f_oflags = va_arg(ap, int); + } + break; + + case F_GETOWN: + /* If fildes refers to a socket, get the process or process group ID specified + * to receive SIGURG signals when out-of-band data is available. Positive values + * indicate a process ID; negative values, other than -1, indicate a process group + * ID. If fildes does not refer to a socket, the results are unspecified. + */ + + case F_SETOWN: + /* If fildes refers to a socket, set the process or process group ID specified + * to receive SIGURG signals when out-of-band data is available, using the value + * of the third argument, arg, taken as type int. Positive values indicate a + * process ID; negative values, other than -1, indicate a process group ID. If + * fildes does not refer to a socket, the results are unspecified. + */ + + err = EBADF; /* Only valid on socket descriptors */ + break; + + case F_GETLK: + /* Get the first lock which blocks the lock description pointed to by the third + * argument, arg, taken as a pointer to type struct flock, defined in . + * The information retrieved shall overwrite the information passed to fcntl() in + * the structure flock. If no lock is found that would prevent this lock from being + * created, then the structure shall be left unchanged except for the lock type + * which shall be set to F_UNLCK. + */ + + case F_SETLK: + /* Set or clear a file segment lock according to the lock description pointed to + * by the third argument, arg, taken as a pointer to type struct flock, defined in + * . F_SETLK can establish shared (or read) locks (F_RDLCK) or exclusive + * (or write) locks (F_WRLCK), as well as to remove either type of lock (F_UNLCK). + * F_RDLCK, F_WRLCK, and F_UNLCK are defined in . If a shared or exclusive + * lock cannot be set, fcntl() shall return immediately with a return value of -1. + */ + + case F_SETLKW: + /* This command shall be equivalent to F_SETLK except that if a shared or exclusive + * lock is blocked by other locks, the thread shall wait until the request can be + * satisfied. If a signal that is to be caught is received while fcntl() is waiting + * for a region, fcntl() shall be interrupted. Upon return from the signal handler, + * fcntl() shall return -1 with errno set to [EINTR], and the lock operation shall + * not be done. + */ + + err = ENOSYS; /* Not implemented */ + break; + + default: + err = EINVAL; + break; + } + +errout: + if (err != 0) + { + set_errno(err); + return ERROR; + } + + return ret; +} +#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fcntl + ****************************************************************************/ + +int fcntl(int fildes, int cmd, ...) +{ + va_list ap; + int ret; + + /* Setup to access the variable argument list */ + + va_start(ap, cmd); + + /* Did we get a valid file descriptor? */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + if ((unsigned int)fildes < CONFIG_NFILE_DESCRIPTORS) + { + /* Yes.. defer file operations to file_vfcntl() */ + + ret = file_vfcntl(fildes, cmd, ap); + } + else +#endif + { + /* No... check for operations on a socket descriptor */ + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + if ((unsigned int)fildes < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS)) + { + /* Yes.. defer socket descriptor operations to net_vfcntl() */ + + ret = net_vfcntl(fildes, cmd, ap); + } + else +#endif + { + /* No.. this descriptor number is out of range */ + + ret = EBADF; + } + } + + va_end(ap); + return ret; +} + diff --git a/nuttx/fs/fs_fdopen.c b/nuttx/fs/fs_fdopen.c new file mode 100644 index 0000000000..ee6440bf5f --- /dev/null +++ b/nuttx/fs/fs_fdopen.c @@ -0,0 +1,261 @@ +/**************************************************************************** + * fs/fs_fdopen.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fs_checkfd + * + * Description: + * Check if the file descriptor is valid for the provided TCB and if it + * supports the requested access. + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static inline int fs_checkfd(FAR _TCB *tcb, int fd, int oflags) +{ + FAR struct filelist *flist; + FAR struct inode *inode; + + /* Get the file list from the TCB */ + + flist = tcb->filelist; + + /* Get the inode associated with the file descriptor. This should + * normally be the case if fd >= 0. But not in the case where the + * called attempts to explictly stdin with fdopen(0) but stdin has + * been closed. + */ + + inode = flist->fl_files[fd].f_inode; + if (!inode) + { + /* No inode -- descriptor does not correspond to an open file */ + + return -ENOENT; + } + + /* Make sure that the inode supports the requested access. In + * the case of fdopen, we are not actually creating the file -- in + * particular w and w+ do not truncate the file and any files have + * already been created. + */ + + if (inode_checkflags(inode, oflags) != OK) + { + /* Cannot support the requested access */ + + return -EACCES; + } + + /* Looks good to me */ + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fs_fdopen + * + * Description: + * This function does the core operations for fopen and fdopen. + * + ****************************************************************************/ + +FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR _TCB *tcb) +{ + FAR struct streamlist *slist; + FAR FILE *stream; + int err = OK; + int ret; + int i; + + /* Check input parameters */ + + if (fd < 0) + { + err = EBADF; + goto errout; + } + + /* A NULL TCB pointer means to use this threads TCB. This is a little + * hack the let's this function be called from user-space (via a syscall) + * without having access to the TCB. + */ + + if (!tcb) + { + tcb = sched_self(); + } + + /* Verify that this is a valid file/socket descriptor and that the + * requested access can be support. + * + * Is this fd in the range of valid file descriptors? Socket descriptors + * lie in a different range. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) +#endif + { + /* No.. If networking is enabled then this might be a socket + * descriptor. + */ + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + ret = net_checksd(fd, oflags); +#else + /* No networking... it is just a bad descriptor */ + + err = EBADF; + goto errout; +#endif + } + + /* The descriptor is in a valid range to file descriptor... perform some more checks */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + else + { + ret = fs_checkfd(tcb, fd, oflags); + } +#endif + + /* Do we have a good descriptor of some sort? */ + + if (ret < 0) + { + /* No... return the reported error */ + + err = -ret; + goto errout; + } + + /* Get the stream list from the TCB */ + + slist = tcb->streams; + + /* Find an unallocated FILE structure in the stream list */ + + ret = sem_wait(&slist->sl_sem); + if (ret != OK) + { + goto errout_with_errno; + } + + for (i = 0 ; i < CONFIG_NFILE_STREAMS; i++) + { + stream = &slist->sl_streams[i]; + if (stream->fs_filedes < 0) + { + /* Zero the structure */ + +#if CONFIG_STDIO_BUFFER_SIZE > 0 + memset(stream, 0, sizeof(FILE)); +#elif CONFIG_NUNGET_CHARS > 0 + stream->fs_nungotten = 0; +#endif + +#if CONFIG_STDIO_BUFFER_SIZE > 0 + /* Initialize the semaphore the manages access to the buffer */ + + (void)sem_init(&stream->fs_sem, 0, 1); + + /* Allocate the IO buffer */ + + stream->fs_bufstart = kmalloc(CONFIG_STDIO_BUFFER_SIZE); + if (!stream) + { + err = ENOMEM; + goto errout_with_sem; + } + + /* Set up pointers */ + + stream->fs_bufend = &stream->fs_bufstart[CONFIG_STDIO_BUFFER_SIZE]; + stream->fs_bufpos = stream->fs_bufstart; + stream->fs_bufpos = stream->fs_bufstart; + stream->fs_bufread = stream->fs_bufstart; +#endif + /* Save the file description and open flags. Setting the + * file descriptor locks this stream. + */ + + stream->fs_filedes = fd; + stream->fs_oflags = (uint16_t)oflags; + + sem_post(&slist->sl_sem); + return stream; + } + } + + /* No free stream available.. report ENFILE */ + + err = ENFILE; + +#if CONFIG_STDIO_BUFFER_SIZE > 0 +errout_with_sem: +#endif + sem_post(&slist->sl_sem); + +errout: + set_errno(err); +errout_with_errno: + return NULL; +} diff --git a/nuttx/fs/fs_filedup.c b/nuttx/fs/fs_filedup.c new file mode 100644 index 0000000000..b7eeb7addc --- /dev/null +++ b/nuttx/fs/fs_filedup.c @@ -0,0 +1,122 @@ +/**************************************************************************** + * fs/fs_filedup.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "fs_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define DUP_ISOPEN(fd, list) \ + ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS && \ + list->fl_files[fd].f_inode != NULL) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: file_dup OR dup + * + * Description: + * Clone a file descriptor 'fd' to an arbitray descriptor number (any value + * greater than or equal to 'minfd'). If socket descriptors are + * implemented, then this is called by dup() for the case of file + * descriptors. If socket descriptors are not implemented, then this + * function IS dup(). + * + ****************************************************************************/ + +int file_dup(int fildes, int minfd) +{ + FAR struct filelist *list; + int fildes2; + + /* Get the thread-specific file list */ + + list = sched_getfiles(); + if (!list) + { + set_errno(EMFILE); + return ERROR; + } + + /* Verify that fildes is a valid, open file descriptor */ + + if (!DUP_ISOPEN(fildes, list)) + { + set_errno(EBADF); + return ERROR; + } + + /* Increment the reference count on the contained inode */ + + inode_addref(list->fl_files[fildes].f_inode); + + /* Then allocate a new file descriptor for the inode */ + + fildes2 = files_allocate(list->fl_files[fildes].f_inode, + list->fl_files[fildes].f_oflags, + list->fl_files[fildes].f_pos, + minfd); + if (fildes2 < 0) + { + set_errno(EMFILE); + inode_release(list->fl_files[fildes].f_inode); + return ERROR; + } + + return fildes2; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */ + diff --git a/nuttx/fs/fs_filedup2.c b/nuttx/fs/fs_filedup2.c new file mode 100644 index 0000000000..d064aa08be --- /dev/null +++ b/nuttx/fs/fs_filedup2.c @@ -0,0 +1,121 @@ +/**************************************************************************** + * fs/fs_filedup2.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "fs_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define DUP_ISOPEN(fd, list) \ + ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS && \ + list->fl_files[fd].f_inode != NULL) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: file_dup2 OR dup2 + * + * Description: + * Clone a file descriptor to a specific descriptor number. If socket + * descriptors are implemented, then this is called by dup2() for the + * case of file descriptors. If socket descriptors are not implemented, + * then this function IS dup2(). + * + ****************************************************************************/ + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 +int file_dup2(int fildes1, int fildes2) +#else +int dup2(int fildes1, int fildes2) +#endif +{ + FAR struct filelist *list; + + /* Get the thread-specific file list */ + + list = sched_getfiles(); + if (!list) + { + set_errno(EMFILE); + return ERROR; + } + + /* Verify that fildes is a valid, open file descriptor */ + + if (!DUP_ISOPEN(fildes1, list)) + { + set_errno(EBADF); + return ERROR; + } + + /* Handle a special case */ + + if (fildes1 == fildes2) + { + return fildes1; + } + + /* Verify fildes2 */ + + if ((unsigned int)fildes2 >= CONFIG_NFILE_DESCRIPTORS) + { + set_errno(EBADF); + return ERROR; + } + + return files_dup(&list->fl_files[fildes1], &list->fl_files[fildes2]); +} + +#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */ + diff --git a/nuttx/fs/fs_files.c b/nuttx/fs/fs_files.c new file mode 100644 index 0000000000..033cd8c63b --- /dev/null +++ b/nuttx/fs/fs_files.c @@ -0,0 +1,479 @@ +/**************************************************************************** + * fs/fs_files.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _files_semtake + ****************************************************************************/ + +static void _files_semtake(FAR struct filelist *list) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&list->fl_sem) != 0) + { + /* The only case that an error should occr here is if + * the wait was awakened by a signal. + */ + + ASSERT(get_errno() == EINTR); + } +} + +/**************************************************************************** + * Name: _files_semgive + ****************************************************************************/ + +#define _files_semgive(list) sem_post(&list->fl_sem) + +/**************************************************************************** + * Name: _files_close + * + * Description: + * Close an inode (if open) + * + * Assumuptions: + * Caller holds the list semaphore because the file descriptor will be freed. + * + ****************************************************************************/ + +static int _files_close(FAR struct file *filep) +{ + struct inode *inode = filep->f_inode; + int ret = OK; + + /* Check if the struct file is open (i.e., assigned an inode) */ + + if (inode) + { + /* Close the file, driver, or mountpoint. */ + + if (inode->u.i_ops && inode->u.i_ops->close) + { + /* Perform the close operation */ + + ret = inode->u.i_ops->close(filep); + } + + /* And release the inode */ + + inode_release(inode); + + /* Release the file descriptor */ + + filep->f_oflags = 0; + filep->f_pos = 0; + filep->f_inode = NULL; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: files_initialize + * + * Description: + * This is called from the FS initialization logic to configure the files. + * + ****************************************************************************/ + +void files_initialize(void) +{ +} + +/**************************************************************************** + * Name: files_alloclist + * + * Description: Allocate a list of files for a new task + * + ****************************************************************************/ + +FAR struct filelist *files_alloclist(void) +{ + FAR struct filelist *list; + list = (FAR struct filelist*)kzalloc(sizeof(struct filelist)); + if (list) + { + /* Start with a reference count of one */ + + list->fl_crefs = 1; + + /* Initialize the list access mutex */ + + (void)sem_init(&list->fl_sem, 0, 1); + } + + return list; +} + +/**************************************************************************** + * Name: files_addreflist + * + * Description: + * Increase the reference count on a file list + * + ****************************************************************************/ + +int files_addreflist(FAR struct filelist *list) +{ + if (list) + { + /* Increment the reference count on the list. + * NOTE: that we disable interrupts to do this + * (vs. taking the list semaphore). We do this + * because file cleanup operations often must be + * done from the IDLE task which cannot wait + * on semaphores. + */ + + register irqstate_t flags = irqsave(); + list->fl_crefs++; + irqrestore(flags); + } + + return OK; +} + +/**************************************************************************** + * Name: files_releaselist + * + * Description: + * Release a reference to the file list + * + ****************************************************************************/ + +int files_releaselist(FAR struct filelist *list) +{ + int crefs; + if (list) + { + /* Decrement the reference count on the list. + * NOTE: that we disable interrupts to do this + * (vs. taking the list semaphore). We do this + * because file cleanup operations often must be + * done from the IDLE task which cannot wait + * on semaphores. + */ + + register irqstate_t flags = irqsave(); + crefs = --(list->fl_crefs); + irqrestore(flags); + + /* If the count decrements to zero, then there is no reference + * to the structure and it should be deallocated. Since there + * are references, it would be an error if any task still held + * a reference to the list's semaphore. + */ + + if (crefs <= 0) + { + int i; + + /* Close each file descriptor .. Normally, you would need + * take the list semaphore, but it is safe to ignore the + * semaphore in this context because there are no references + */ + + for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + { + (void)_files_close(&list->fl_files[i]); + } + + /* Destroy the semaphore and release the filelist */ + + (void)sem_destroy(&list->fl_sem); + sched_free(list); + } + } + + return OK; +} + +/**************************************************************************** + * Name: files_dup + * + * Description: + * Assign an inode to a specific files structure. This is the heart of + * dup2. + * + ****************************************************************************/ + +int files_dup(FAR struct file *filep1, FAR struct file *filep2) +{ + FAR struct filelist *list; + FAR struct inode *inode; + int err; + int ret; + + if (!filep1 || !filep1->f_inode || !filep2) + { + err = EBADF; + goto errout; + } + +#ifndef CONFIG_DISABLE_MOUNTPOINT + if (INODE_IS_MOUNTPT(filep1->f_inode)) + { + err = ENOSYS; /* Not yet supported */ + goto errout; + } +#endif + + list = sched_getfiles(); + if (!list) + { + err = EMFILE; + goto errout; + } + + _files_semtake(list); + + /* If there is already an inode contained in the new file structure, + * close the file and release the inode. + */ + + ret = _files_close(filep2); + if (ret < 0) + { + /* An error occurred while closing the driver */ + + goto errout_with_ret; + } + + /* Increment the reference count on the contained inode */ + + inode = filep1->f_inode; + inode_addref(inode); + + /* Then clone the file structure */ + + filep2->f_oflags = filep1->f_oflags; + filep2->f_pos = filep1->f_pos; + filep2->f_inode = inode; + + /* Call the open method on the file, driver, mountpoint so that it + * can maintain the correct open counts. + */ + + if (inode->u.i_ops && inode->u.i_ops->open) + { +#ifndef CONFIG_DISABLE_MOUNTPOINT +#if 0 /* Not implemented */ + if (INODE_IS_MOUNTPT(inode)) + { + /* Open a file on the mountpoint */ + + ret = inode->u.i_mops->open(filep2, ?, filep2->f_oflags, ?); + } + else +#endif +#endif + { + /* Open the psuedo file or device driver */ + + ret = inode->u.i_ops->open(filep2); + } + + /* Handle open failures */ + + if (ret < 0) + { + goto errout_with_inode; + } + } + + _files_semgive(list); + return OK; + +/* Handler various error conditions */ + +errout_with_inode: + inode_release(filep2->f_inode); + filep2->f_oflags = 0; + filep2->f_pos = 0; + filep2->f_inode = NULL; + +errout_with_ret: + err = -ret; + _files_semgive(list); + +errout: + set_errno(err); + return ERROR; +} + +/**************************************************************************** + * Name: files_allocate + * + * Description: + * Allocate a struct files instance and associate it with an inode instance. + * Returns the file descriptor == index into the files array. + * + ****************************************************************************/ + +int files_allocate(FAR struct inode *inode, int oflags, off_t pos, int minfd) +{ + FAR struct filelist *list; + int i; + + list = sched_getfiles(); + if (list) + { + _files_semtake(list); + for (i = minfd; i < CONFIG_NFILE_DESCRIPTORS; i++) + { + if (!list->fl_files[i].f_inode) + { + list->fl_files[i].f_oflags = oflags; + list->fl_files[i].f_pos = pos; + list->fl_files[i].f_inode = inode; + _files_semgive(list); + return i; + } + } + + _files_semgive(list); + } + + return ERROR; +} + +/**************************************************************************** + * Name: files_close + * + * Description: + * Close an inode (if open) + * + * Assumuptions: + * Caller holds the list semaphore because the file descriptor will be freed. + * + ****************************************************************************/ + +int files_close(int filedes) +{ + FAR struct filelist *list; + int ret; + + /* Get the thread-specific file list */ + + list = sched_getfiles(); + if (!list) + { + return -EMFILE; + } + + /* If the file was properly opened, there should be an inode assigned */ + + if (filedes < 0 || filedes >= CONFIG_NFILE_DESCRIPTORS || !list->fl_files[filedes].f_inode) + { + return -EBADF; + } + + /* Perform the protected close operation */ + + _files_semtake(list); + ret = _files_close(&list->fl_files[filedes]); + _files_semgive(list); + return ret; +} + +/**************************************************************************** + * Name: files_release + * + * Assumuptions: + * Similar to files_close(). Called only from open() logic on error + * conditions. + * + ****************************************************************************/ + +void files_release(int filedes) +{ + FAR struct filelist *list; + + list = sched_getfiles(); + if (list) + { + if (filedes >=0 && filedes < CONFIG_NFILE_DESCRIPTORS) + { + _files_semtake(list); + list->fl_files[filedes].f_oflags = 0; + list->fl_files[filedes].f_pos = 0; + list->fl_files[filedes].f_inode = NULL; + _files_semgive(list); + } + } +} + diff --git a/nuttx/fs/fs_findblockdriver.c b/nuttx/fs/fs_findblockdriver.c new file mode 100644 index 0000000000..febf28a7ef --- /dev/null +++ b/nuttx/fs/fs_findblockdriver.c @@ -0,0 +1,131 @@ +/**************************************************************************** + * fs/fs_openblockdriver.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in pathname and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of pathname code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: find_blockdriver + * + * Description: + * Return the inode of the block driver specified by 'pathname' + * + * Inputs: + * pathname - the full path to the block driver to be located + * mountflags - if MS_RDONLY is not set, then driver must support write + * operations (see include/sys/mount.h) + * ppinode - address of the location to return the inode reference + * + * Return: + * Returns zero on success or a negated errno on failure: + * + * EINVAL - pathname or pinode is NULL + * ENOENT - No block driver of this name is registered + * ENOTBLK - The inode associated with the pathname is not a block driver + * EACCESS - The MS_RDONLY option was not set but this driver does not + * support write access + * + ****************************************************************************/ + +int find_blockdriver(FAR const char *pathname, int mountflags, FAR struct inode **ppinode) +{ + FAR struct inode *inode; + int ret = 0; /* Assume success */ + + /* Sanity checks */ + +#ifdef CONFIG_DEBUG + if (!pathname || !ppinode) + { + ret = -EINVAL; + goto errout; + } +#endif + + /* Find the inode registered with this pathname */ + + inode = inode_find(pathname, NULL); + if (!inode) + { + fdbg("Failed to find %s\n", pathname); + ret = -ENOENT; + goto errout; + } + + /* Verify that the inode is a block driver. */ + + if (!INODE_IS_BLOCK(inode)) + { + fdbg("%s is not a block driver\n", pathname); + ret = -ENOTBLK; + goto errout_with_inode; + } + + /* Make sure that the inode supports the requested access */ + + if (!inode->u.i_bops || !inode->u.i_bops->read || + (!inode->u.i_bops->write && (mountflags & MS_RDONLY) == 0)) + { + fdbg("%s does not support requested access\n", pathname); + ret = -EACCES; + goto errout_with_inode; + } + + *ppinode = inode; + return OK; + +errout_with_inode: + inode_release(inode); +errout: + return ret; +} diff --git a/nuttx/fs/fs_foreachinode.c b/nuttx/fs/fs_foreachinode.c new file mode 100644 index 0000000000..08630263b2 --- /dev/null +++ b/nuttx/fs/fs_foreachinode.c @@ -0,0 +1,233 @@ +/**************************************************************************** + * fs/fs_foreachinode.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Is it better to allocate the struct inode_path_s from the heap? or + * from the stack? This decision depends on how often this is down and + * how much stack space you can afford. + */ + +#define ENUM_INODE_ALLOC 1 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure manages the full path to the inode. */ + +struct inode_path_s +{ + foreach_inode_t handler; + FAR void *arg; + char path[CONFIG_PATH_MAX]; +}; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: foreach_inodelevel + * + * Description: + * This is the recursive 'heart' of foreach_inode. It will visit each + * inode at this level in the hierarchy and recurse handle each inode + * at the next level down. + * + * Assumptions: + * The caller holds the inode semaphore. + * + ****************************************************************************/ + +int foreach_inodelevel(FAR struct inode *node, struct inode_path_s *info) +{ + int ret = OK; + + /* Visit each node at this level */ + + for (; node; node = node->i_peer) + { + /* Give the next inode to the callback */ + + ret = info->handler(node, info->path, info->arg); + + /* Break out of the looop early if the handler returns a non-zero + * value + */ + + if (ret != 0) + { + break; + } + + /* If there is a level 'beneath' this one, then recurse to visit all + * of the inodes at that level. + */ + + if (node->i_child) + { + /* Construct the path to the next level */ + + int pathlen = strlen(info->path); + int namlen = strlen(node->i_name) + 1; + + /* Make sure that this would not exceed the maximum path length */ + + if (pathlen + namlen > PATH_MAX) + { + ret = -ENAMETOOLONG; + break; + } + + /* Append the path segment to this inode and recurse */ + + sprintf(&info->path[pathlen], "/%s", node->i_name); + ret = foreach_inodelevel(node->i_child, info); + + /* Truncate the path name back to the correct length */ + + info->path[pathlen] = '\0'; + + /* Return early if the handler at the lower level returned a non- + * zero value + */ + + if (ret != 0) + { + break; + } + } + } + + /* Return the result of the traversal. */ + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: foreach_inode + * + * Description: + * Visit each inode in the pseudo-file system. The traversal is terminated + * when the callback 'handler' returns a non-zero value, or when all of + * the inodes have been visited. + * + * NOTE 1: Use with caution... The psuedo-file system is locked throughout + * the traversal. + * NOTE 2: The search algorithm is recursive and could, in principle, use + * an indeterminant amount of stack space. This will not usually be a + * real work issue. + * + ****************************************************************************/ + +int foreach_inode(foreach_inode_t handler, FAR void *arg) +{ +#ifdef ENUM_INODE_ALLOC + FAR struct inode_path_s *info; + int ret; + + /* Allocate the mountpoint info structure */ + + info = (FAR struct inode_path_s *)malloc(sizeof(struct inode_path_s)); + if (!info) + { + return -ENOMEM; + } + + /* Initialize the info structure */ + + info->handler = handler; + info->arg = arg; + info->path[0] = '\0'; + + /* Start the recursion at the root inode */ + + inode_semtake(); + ret = foreach_inodelevel(root_inode, info); + inode_semgive(); + + /* Free the info structure and return the result */ + + free(info); + return ret; + +#else + struct inode_path_s info; + int ret; + + /* Initialize the info structure */ + + info.handler = handler; + info.arg = arg; + info.path[0] = '\0'; + + /* Start the recursion at the root inode */ + + inode_semtake(); + ret = foreach_inodelevel(root_inode, &info); + inode_semgive(); + + return ret; + +#endif +} + diff --git a/nuttx/fs/fs_foreachmountpoint.c b/nuttx/fs/fs_foreachmountpoint.c new file mode 100644 index 0000000000..e7a6206506 --- /dev/null +++ b/nuttx/fs/fs_foreachmountpoint.c @@ -0,0 +1,177 @@ +/**************************************************************************** + * fs/fs_foreachmountpoint.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include "fs_internal.h" + +#ifndef CONFIG_DISABLE_MOUNTPOUNT + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure just remembers the final consumer of the mountpoint + * information (and its argument). + */ + +struct enum_mountpoint_s +{ + foreach_mountpoint_t handler; + FAR void *arg; +}; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int mountpoint_filter(FAR struct inode *node, + FAR char dirpath[PATH_MAX], FAR void *arg) +{ + FAR struct enum_mountpoint_s *info = (FAR struct enum_mountpoint_s *)arg; + struct statfs statbuf; + int pathlen; + int namlen; + int ret = OK; + + DEBUGASSERT(node && info && info->handler); + + /* Check if the inode is a mountpoint. Mountpoints must support statfs. + * If this one does not for some reason, then it will be ignored. + * + * The root node is a special case: It has no operations (u.i_mops == NULL) + */ + + if (INODE_IS_MOUNTPT(node) && node->u.i_mops && node->u.i_mops->statfs) + { + /* Yes... get the full path to the inode by concatenating the inode + * name and the path to the directory containing the inode. + */ + + pathlen = strlen(dirpath); + namlen = strlen(node->i_name) + 1; + + /* Make sure that this would not exceed the maximum path length */ + + if (pathlen + namlen > PATH_MAX) + { + return -ENAMETOOLONG; + } + + /* Append the inode name to the directory path */ + + sprintf(&dirpath[pathlen], "/%s", node->i_name); + + /* Get the status of the file system */ + + ret = node->u.i_mops->statfs(node, &statbuf); + if (ret == OK) + { + /* And pass the full path and file system status to the handler */ + + ret = info->handler(dirpath, &statbuf, info->arg); + } + + /* Truncate the path name back to the correct length */ + + dirpath[pathlen] = '\0'; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + /**************************************************************************** + * Name: foreach_mountpoint + * + * Description: + * Visit each mountpoint in the pseudo-file system. The traversal is + * terminated when the callback 'handler' returns a non-zero value, or when + * all of the mountpoints have been visited. + * + * This is just a front end "filter" to foreach_inode() that forwards only + * mountpoint inodes. It is intended to support the mount() command to + * when the mount command is used to enumerate mounts. + * + * NOTE 1: Use with caution... The psuedo-file system is locked throughout + * the traversal. + * NOTE 2: The search algorithm is recursive and could, in principle, use + * an indeterminant amount of stack space. This will not usually be a + * real work issue. + * + ****************************************************************************/ + +int foreach_mountpoint(foreach_mountpoint_t handler, FAR void *arg) +{ + struct enum_mountpoint_s info; + + /* Let foreach_inode do the real work */ + + info.handler = handler; + info.arg = arg; + + return foreach_inode(mountpoint_filter, (FAR void *)&info); +} + +#endif diff --git a/nuttx/fs/fs_fsync.c b/nuttx/fs/fs_fsync.c new file mode 100644 index 0000000000..877c33a838 --- /dev/null +++ b/nuttx/fs/fs_fsync.c @@ -0,0 +1,138 @@ +/**************************************************************************** + * fs/fs_fsync.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fsync + * + * Description: + * This func simply binds inode sync methods to the sync system call. + * + ****************************************************************************/ + +int fsync(int fd) +{ + FAR struct filelist *list; + FAR struct file *this_file; + struct inode *inode; + int ret; + + /* Get the thread-specific file list */ + + list = sched_getfiles(); + if (!list) + { + ret = EMFILE; + goto errout; + } + + /* Did we get a valid file descriptor? */ + + if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) + { + ret = EBADF; + goto errout; + } + + /* Was this file opened for write access? */ + + this_file = &list->fl_files[fd]; + if ((this_file->f_oflags & O_WROK) == 0) + { + ret = EBADF; + goto errout; + } + + /* Is this inode a registered mountpoint? Does it support the + * sync operations may be relevant to device drivers but only + * the mountpoint operations vtable contains a sync method. + */ + + inode = this_file->f_inode; + if (!inode || !INODE_IS_MOUNTPT(inode) || + !inode->u.i_mops || !inode->u.i_mops->sync) + { + ret = EINVAL; + goto errout; + } + + /* Yes, then tell the mountpoint to sync this file */ + + ret = inode->u.i_mops->sync(this_file); + if (ret >= 0) + { + return OK; + } + + ret = -ret; + +errout: + set_errno(ret); + return ERROR; +} + diff --git a/nuttx/fs/fs_inode.c b/nuttx/fs/fs_inode.c new file mode 100644 index 0000000000..14da54ceab --- /dev/null +++ b/nuttx/fs/fs_inode.c @@ -0,0 +1,377 @@ +/**************************************************************************** + * fs/fs_inode.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +static sem_t tree_sem; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +FAR struct inode *root_inode = NULL; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _inode_compare + * + * Description: + * Compare two inode names + * + ****************************************************************************/ + +static int _inode_compare(FAR const char *fname, + FAR struct inode *node) +{ + char *nname = node->i_name; + + if (!nname) + { + return 1; + } + + if (!fname) + { + return -1; + } + + for (;;) + { + /* At end of node name? */ + + if (!*nname) + { + /* Yes.. also end of find name? */ + + if (!*fname || *fname == '/') + { + /* Yes.. return match */ + + return 0; + } + else + { + /* No... return find name > node name */ + + return 1; + } + } + + /* At end of find name?*/ + + else if (!*fname || *fname == '/') + { + /* Yes... return find name < node name */ + + return -1; + } + + /* Check for non-matching characters */ + + else if (*fname > *nname) + { + return 1; + } + else if (*fname < *nname) + { + return -1; + } + + /* Not at the end of either string and all of the + * characters still match. keep looking. + */ + + else + { + fname++; + nname++; + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fs_initialize + * + * Description: + * This is called from the OS initialization logic to configure the file + * system. + * + ****************************************************************************/ + +void fs_initialize(void) +{ + /* Initialize the semaphore to one (to support one-at- + * a-time access to the inode tree). + */ + + (void)sem_init(&tree_sem, 0, 1); + + /* Initialize files array (if it is used) */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (files_initialize != NULL) +#endif + { + files_initialize(); + } +} + +/**************************************************************************** + * Name: inode_semtake + * + * Description: + * Get exclusive access to the in-memory inode tree (tree_sem). + * + ****************************************************************************/ + +void inode_semtake(void) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&tree_sem) != 0) + { + /* The only case that an error should occr here is if + * the wait was awakened by a signal. + */ + + ASSERT(get_errno() == EINTR); + } +} + +/**************************************************************************** + * Name: inode_semgive + * + * Description: + * Relinquish exclusive access to the in-memory inode tree (tree_sem). + * + ****************************************************************************/ + +void inode_semgive(void) +{ + sem_post(&tree_sem); +} + +/**************************************************************************** + * Name: inode_search + * + * Description: + * Find the inode associated with 'path' returning the inode references + * and references to its companion nodes. + * + * Assumptions: + * The caller holds the tree_sem + * + ****************************************************************************/ + +FAR struct inode *inode_search(const char **path, + FAR struct inode **peer, + FAR struct inode **parent, + const char **relpath) +{ + const char *name = *path + 1; /* Skip over leading '/' */ + FAR struct inode *node = root_inode; + FAR struct inode *left = NULL; + FAR struct inode *above = NULL; + + while (node) + { + int result = _inode_compare(name, node); + + /* Case 1: The name is less than the name of the node. + * Since the names are ordered, these means that there + * is no peer node with this name and that there can be + * no match in the fileystem. + */ + + if (result < 0) + { + node = NULL; + break; + } + + /* Case 2: the name is greater than the name of the node. + * In this case, the name may still be in the list to the + * "right" + */ + + else if (result > 0) + { + left = node; + node = node->i_peer; + } + + /* The names match */ + + else + { + /* Now there are three more possibilities: + * (1) This is the node that we are looking for or, + * (2) The node we are looking for is "below" this one. + * (3) This node is a mountpoint and will absorb all request + * below this one + */ + + name = inode_nextname(name); + if (!*name || INODE_IS_MOUNTPT(node)) + { + /* Either (1) we are at the end of the path, so this must be the + * node we are looking for or else (2) this node is a mountpoint + * and will handle the remaining part of the pathname + */ + + if (relpath) + { + *relpath = name; + } + break; + } + else + { + /* More to go, keep looking at the next level "down" */ + + above = node; + left = NULL; + node = node->i_child; + } + } + } + + /* node is null. This can happen in one of four cases: + * With node = NULL + * (1) We went left past the final peer: The new node + * name is larger than any existing node name at + * that level. + * (2) We broke out in the middle of the list of peers + * because the name was not found in the ordered + * list. + * (3) We went down past the final parent: The new node + * name is "deeper" than anything that we currently + * have in the tree. + * with node != NULL + * (4) When the node matching the full path is found + */ + + if (peer) + { + *peer = left; + } + + if (parent) + { + *parent = above; + } + + *path = name; + return node; +} + +/**************************************************************************** + * Name: inode_free + * + * Description: + * Free resources used by an inode + * + ****************************************************************************/ + +void inode_free(FAR struct inode *node) +{ + if (node) + { + inode_free(node->i_peer); + inode_free(node->i_child); + kfree(node); + } +} + +/**************************************************************************** + * Name: inode_nextname + * + * Description: + * Given a path with node names separated by '/', return the next node + * name. + * + ****************************************************************************/ + +FAR const char *inode_nextname(FAR const char *name) +{ + /* Search for the '/' delimiter or the NUL terminator at the end of the + * string. + */ + + while (*name && *name != '/') + { + name++; + } + + /* If we found the '/' delimiter, then the path segment we want begins at + * the next character (which might also be the NUL terminator). + */ + + if (*name) + { + name++; + } + + return name; +} + diff --git a/nuttx/fs/fs_inodeaddref.c b/nuttx/fs/fs_inodeaddref.c new file mode 100644 index 0000000000..32d4426d26 --- /dev/null +++ b/nuttx/fs/fs_inodeaddref.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * fs_inodeaddref.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: inode_addref + * + * Description: + * Increment the reference count on an inode (as when a file descriptor + * is dup'ed). + * + ****************************************************************************/ + +void inode_addref(FAR struct inode *inode) +{ + if (inode) + { + inode_semtake(); + inode->i_crefs++; + inode_semgive(); + } +} diff --git a/nuttx/fs/fs_inodefind.c b/nuttx/fs/fs_inodefind.c new file mode 100644 index 0000000000..9055393661 --- /dev/null +++ b/nuttx/fs/fs_inodefind.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * fs/fs_inodefind.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: inode_find + * + * Description: + * This is called from the open() logic to get a reference to the inode + * associated with a path. + * + ****************************************************************************/ + +FAR struct inode *inode_find(FAR const char *path, FAR const char **relpath) +{ + FAR struct inode *node; + + if (!*path || path[0] != '/') + { + return NULL; + } + + /* Find the node matching the path. If found, increment the count of + * references on the node. + */ + + inode_semtake(); + node = inode_search(&path, (FAR struct inode**)NULL, (FAR struct inode**)NULL, relpath); + if (node) + { + node->i_crefs++; + } + + inode_semgive(); + return node; +} + diff --git a/nuttx/fs/fs_inoderelease.c b/nuttx/fs/fs_inoderelease.c new file mode 100644 index 0000000000..bc50265347 --- /dev/null +++ b/nuttx/fs/fs_inoderelease.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * fs_inoderelease.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: inode_release + * + * Description: + * This is called from close() logic when it no longer refers to the inode. + * + ****************************************************************************/ + +void inode_release(FAR struct inode *node) +{ + if (node) + { + /* Decrement the references of the inode */ + + inode_semtake(); + if (node->i_crefs) + { + node->i_crefs--; + } + + /* If the subtree was previously deleted and the reference + * count has decrement to zero, then delete the inode + * now. + */ + + if (node->i_crefs <= 0 && (node->i_flags & FSNODEFLAG_DELETED) != 0) + { + inode_semgive(); + inode_free(node->i_child); + kfree(node); + } + else + { + inode_semgive(); + } + } +} + diff --git a/nuttx/fs/fs_inoderemove.c b/nuttx/fs/fs_inoderemove.c new file mode 100644 index 0000000000..c349b17595 --- /dev/null +++ b/nuttx/fs/fs_inoderemove.c @@ -0,0 +1,161 @@ +/**************************************************************************** + * fs/fs_inoderemove.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: inode_unlink + ****************************************************************************/ + +static void inode_unlink(struct inode *node, + struct inode *peer, + struct inode *parent) +{ + /* If peer is non-null, then remove the node from the right of + * of that peer node. + */ + + if (peer) + { + peer->i_peer = node->i_peer; + } + + /* If parent is non-null, then remove the node from head of + * of the list of children. + */ + + else if (parent) + { + parent->i_child = node->i_peer; + } + + /* Otherwise, we must be removing the root inode. */ + + else + { + root_inode = node->i_peer; + } + + node->i_peer = NULL; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: inode_remove + * + * Description: + * Remove a node from the in-memory, inode tree + * + * NOTE: Caller must hold the inode semaphore + * + ****************************************************************************/ + +int inode_remove(FAR const char *path) +{ + const char *name = path; + FAR struct inode *node; + FAR struct inode *left; + FAR struct inode *parent; + + if (!*path || path[0] != '/') + { + return -EINVAL; + } + + /* Find the node to delete */ + + node = inode_search(&name, &left, &parent, (const char **)NULL); + if (node) + { + /* Found it, now remove it from the tree */ + + inode_unlink(node, left, parent); + + /* We cannot delete it if there reference to the inode */ + + if (node->i_crefs) + { + /* In that case, we will mark it deleted, when the FS + * releases the inode, we will then, finally delete + * the subtree. + */ + + node->i_flags |= FSNODEFLAG_DELETED; + return -EBUSY; + } + else + { + /* And delete it now -- recursively to delete all of its children */ + + inode_free(node->i_child); + kfree(node); + return OK; + } + } + + /* The node does not exist or it has references */ + + return -ENOENT; +} diff --git a/nuttx/fs/fs_inodereserve.c b/nuttx/fs/fs_inodereserve.c new file mode 100644 index 0000000000..73e0fff281 --- /dev/null +++ b/nuttx/fs/fs_inodereserve.c @@ -0,0 +1,237 @@ +/**************************************************************************** + * fs/fs_registerreserve.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: inode_namelen + ****************************************************************************/ + +static int inode_namelen(FAR const char *name) +{ + const char *tmp = name; + while(*tmp && *tmp != '/') tmp++; + return tmp - name; +} + +/**************************************************************************** + * Name: inode_namecpy + ****************************************************************************/ + +static void inode_namecpy(char *dest, const char *src) +{ + while(*src && *src != '/') *dest++ = *src++; + *dest='\0'; +} + +/**************************************************************************** + * Name: inode_alloc + ****************************************************************************/ + +static FAR struct inode *inode_alloc(FAR const char *name) +{ + int namelen = inode_namelen(name); + FAR struct inode *node = (FAR struct inode*)kzalloc(FSNODE_SIZE(namelen)); + if (node) + { + inode_namecpy(node->i_name, name); + } + + return node; +} + +/**************************************************************************** + * Name: inode_insert + ****************************************************************************/ + +static void inode_insert(FAR struct inode *node, + FAR struct inode *peer, + FAR struct inode *parent) +{ + /* If peer is non-null, then new node simply goes to the right + * of that peer node. + */ + + if (peer) + { + node->i_peer = peer->i_peer; + peer->i_peer = node; + } + + /* If parent is non-null, then it must go at the head of its + * list of children. + */ + + else if (parent) + { + node->i_peer = parent->i_child; + parent->i_child = node; + } + + /* Otherwise, this must be the new root_inode */ + + else + { + node->i_peer = root_inode; + root_inode = node; + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: inode_reserve + * + * Description: + * Reserve an (initialized) inode the pseudo file system. + * + * NOTE: Caller must hold the inode semaphore + * + * Input parameters: + * path - The path to the inode to create + * inode - The location to return the inode pointer + * + * Returned Value: + * Zero on success (with the inode point in 'inode'); A negated errno + * value is returned on failure: + * + * EINVAL - 'path' is invalid for this operation + * EEXIST - An inode already exists at 'path' + * ENOMEM - Failed to allocate in-memory resources for the operation + * + ****************************************************************************/ + +int inode_reserve(FAR const char *path, FAR struct inode **inode) +{ + const char *name = path; + FAR struct inode *left; + FAR struct inode *parent; + + /* Assume failure */ + + DEBUGASSERT(path && inode); + *inode = NULL; + + /* Handle paths that are interpreted as the root directory */ + + if (!*path || path[0] != '/') + { + return -EINVAL; + } + + /* Find the location to insert the new subtree */ + + if (inode_search(&name, &left, &parent, (FAR const char **)NULL) != NULL) + { + /* It is an error if the node already exists in the tree */ + + return -EEXIST; + } + + /* Now we now where to insert the subtree */ + + for (;;) + { + FAR struct inode *node; + + /* Create a new node -- we need to know if this is the + * the leaf node or some intermediary. We can find this + * by looking at the next name. + */ + + FAR const char *next_name = inode_nextname(name); + if (*next_name) + { + /* Insert an operationless node */ + + node = inode_alloc(name); + if (node) + { + inode_insert(node, left, parent); + + /* Set up for the next time through the loop */ + + name = next_name; + left = NULL; + parent = node; + continue; + } + } + else + { + node = inode_alloc(name); + if (node) + { + inode_insert(node, left, parent); + *inode = node; + return OK; + } + } + + /* We get here on failures to allocate node memory */ + + return -ENOMEM; + } +} diff --git a/nuttx/fs/fs_internal.h b/nuttx/fs/fs_internal.h new file mode 100644 index 0000000000..dbabb63d1b --- /dev/null +++ b/nuttx/fs/fs_internal.h @@ -0,0 +1,327 @@ +/**************************************************************************** + * fs/fs_internal.h + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_FS_INTERNAL_H +#define __FS_FS_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define FSNODEFLAG_TYPE_MASK 0x00000003 +#define FSNODEFLAG_TYPE_DRIVER 0x00000000 +#define FSNODEFLAG_TYPE_BLOCK 0x00000001 +#define FSNODEFLAG_TYPE_MOUNTPT 0x00000002 +#define FSNODEFLAG_DELETED 0x00000004 + +#define INODE_IS_DRIVER(i) \ + (((i)->i_flags & FSNODEFLAG_TYPE_MASK) == FSNODEFLAG_TYPE_DRIVER) +#define INODE_IS_BLOCK(i) \ + (((i)->i_flags & FSNODEFLAG_TYPE_BLOCK) == FSNODEFLAG_TYPE_BLOCK) +#define INODE_IS_MOUNTPT(i) \ + (((i)->i_flags & FSNODEFLAG_TYPE_MOUNTPT) == FSNODEFLAG_TYPE_MOUNTPT) + +#define INODE_SET_DRIVER(i) \ + ((i)->i_flags &= ~FSNODEFLAG_TYPE_MASK) +#define INODE_SET_BLOCK(i) \ + ((i)->i_flags = (((i)->i_flags & ~FSNODEFLAG_TYPE_MASK) | FSNODEFLAG_TYPE_BLOCK)) +#define INODE_SET_MOUNTPT(i) \ + ((i)->i_flags = (((i)->i_flags & ~FSNODEFLAG_TYPE_MASK) | FSNODEFLAG_TYPE_MOUNTPT)) + +/* Mountpoint fd_flags values */ + +#define DIRENTFLAGS_PSUEDONODE 1 + +#define DIRENT_SETPSUEDONODE(f) do (f) |= DIRENTFLAGS_PSUEDONODE; while (0) +#define DIRENT_ISPSUEDONODE(f) (((f) & DIRENTFLAGS_PSUEDONODE) != 0) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Callback used by foreach_inode to traverse all inodes in the pseudo- + * file system. + */ + +typedef int (*foreach_inode_t)(FAR struct inode *node, + FAR char dirpath[PATH_MAX], + FAR void *arg); + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +extern FAR struct inode *root_inode; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* fs_inode.c ***************************************************************/ +/**************************************************************************** + * Name: inode_semtake + * + * Description: + * Get exclusive access to the in-memory inode tree (tree_sem). + * + ****************************************************************************/ + +EXTERN void inode_semtake(void); + +/**************************************************************************** + * Name: inode_semgive + * + * Description: + * Relinquish exclusive access to the in-memory inode tree (tree_sem). + * + ****************************************************************************/ + +EXTERN void inode_semgive(void); + +/**************************************************************************** + * Name: inode_search + * + * Description: + * Find the inode associated with 'path' returning the inode references + * and references to its companion nodes. + * + * Assumptions: + * The caller holds the tree_sem + * + ****************************************************************************/ + +EXTERN FAR struct inode *inode_search(FAR const char **path, + FAR struct inode **peer, + FAR struct inode **parent, + FAR const char **relpath); + +/**************************************************************************** + * Name: inode_free + * + * Description: + * Free resources used by an inode + * + ****************************************************************************/ + +EXTERN void inode_free(FAR struct inode *node); + +/**************************************************************************** + * Name: inode_nextname + * + * Description: + * Given a path with node names separated by '/', return the next node + * name. + * + ****************************************************************************/ + +EXTERN const char *inode_nextname(FAR const char *name); + +/* fs_inodereserver.c *******************************************************/ +/**************************************************************************** + * Name: inode_reserve + * + * Description: + * Reserve an (initialized) inode the pseudo file system. + * + * NOTE: Caller must hold the inode semaphore + * + * Input parameters: + * path - The path to the inode to create + * inode - The location to return the inode pointer + * + * Returned Value: + * Zero on success (with the inode point in 'inode'); A negated errno + * value is returned on failure: + * + * EINVAL - 'path' is invalid for this operation + * EEXIST - An inode already exists at 'path' + * ENOMEM - Failed to allocate in-memory resources for the operation + * + ****************************************************************************/ + +EXTERN int inode_reserve(FAR const char *path, FAR struct inode **inode); + +/* fs_inoderemove.c *********************************************************/ +/**************************************************************************** + * Name: inode_remove + * + * Description: + * Remove a node from the in-memory, inode tree + * + * NOTE: Caller must hold the inode semaphore + * + ****************************************************************************/ + +EXTERN int inode_remove(FAR const char *path); + +/* fs_inodefind.c ***********************************************************/ +/**************************************************************************** + * Name: inode_find + * + * Description: + * This is called from the open() logic to get a reference to the inode + * associated with a path. + * + ****************************************************************************/ + +EXTERN FAR struct inode *inode_find(FAR const char *path, const char **relpath); + +/* fs_inodeaddref.c *********************************************************/ + +EXTERN void inode_addref(FAR struct inode *inode); + +/* fs_inoderelease.c ********************************************************/ + +EXTERN void inode_release(FAR struct inode *inode); + +/* fs_foreachinode.c ********************************************************/ +/**************************************************************************** + * Name: foreach_inode + * + * Description: + * Visit each inode in the pseudo-file system. The traversal is terminated + * when the callback 'handler' returns a non-zero value, or when all of + * the inodes have been visited. + * + * NOTE 1: Use with caution... The psuedo-file system is locked throughout + * the traversal. + * NOTE 2: The search algorithm is recursive and could, in principle, use + * an indeterminant amount of stack space. This will not usually be a + * real work issue. + * + ****************************************************************************/ + +EXTERN int foreach_inode(foreach_inode_t handler, FAR void *arg); + +/* fs_files.c ***************************************************************/ +/**************************************************************************** + * Name: files_initialize + * + * Description: + * This is called from the FS initialization logic to configure the files. + * + ****************************************************************************/ + +EXTERN void weak_function files_initialize(void); + +/**************************************************************************** + * Name: files_allocate + * + * Description: + * Allocate a struct files instance and associate it with an inode instance. + * Returns the file descriptor == index into the files array. + * + ****************************************************************************/ + +EXTERN int files_allocate(FAR struct inode *inode, int oflags, off_t pos, int minfd); + +/**************************************************************************** + * Name: files_close + * + * Description: + * Close an inode (if open) + * + * Assumuptions: + * Caller holds the list semaphore because the file descriptor will be freed. + * + ****************************************************************************/ + +EXTERN int files_close(int filedes); + +/**************************************************************************** + * Name: files_release + * + * Assumuptions: + * Similar to files_close(). Called only from open() logic on error + * conditions. + * + ****************************************************************************/ + +EXTERN void files_release(int filedes); + +/* fs_findblockdriver.c *****************************************************/ +/**************************************************************************** + * Name: find_blockdriver + * + * Description: + * Return the inode of the block driver specified by 'pathname' + * + * Inputs: + * pathname - the full path to the block driver to be located + * mountflags - if MS_RDONLY is not set, then driver must support write + * operations (see include/sys/mount.h) + * ppinode - address of the location to return the inode reference + * + * Return: + * Returns zero on success or a negated errno on failure: + * + * EINVAL - pathname or pinode is NULL + * ENOENT - No block driver of this name is registered + * ENOTBLK - The inode associated with the pathname is not a block driver + * EACCESS - The MS_RDONLY option was not set but this driver does not + * support write access + * + ****************************************************************************/ + +EXTERN int find_blockdriver(FAR const char *pathname, int mountflags, + FAR struct inode **ppinode); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __FS_FS_INTERNAL_H */ diff --git a/nuttx/fs/fs_ioctl.c b/nuttx/fs/fs_ioctl.c new file mode 100644 index 0000000000..3440bc0d0b --- /dev/null +++ b/nuttx/fs/fs_ioctl.c @@ -0,0 +1,150 @@ +/**************************************************************************** + * fs/fs_ioctl.c + * + * Copyright (C) 2007-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 +# include +#endif + +#include "fs_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ioctl + * + * Description: + * Perform device specific operations. + * + * Parameters: + * fd File/socket descriptor of device + * req The ioctl command + * arg The argument of the ioctl cmd + * + * Return: + * >=0 on success (positive non-zero values are cmd-specific) + * -1 on failure withi errno set properly: + * + * EBADF + * 'fd' is not a valid descriptor. + * EFAULT + * 'arg' references an inaccessible memory area. + * EINVAL + * 'cmd' or 'arg' is not valid. + * ENOTTY + * 'fd' is not associated with a character special device. + * ENOTTY + * The specified request does not apply to the kind of object that the + * descriptor 'fd' references. + * + ****************************************************************************/ + +int ioctl(int fd, int req, unsigned long arg) +{ + int err; +#if CONFIG_NFILE_DESCRIPTORS > 0 + FAR struct filelist *list; + FAR struct file *this_file; + FAR struct inode *inode; + int ret = OK; + + /* Did we get a valid file descriptor? */ + + if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) +#endif + { + /* Perform the socket ioctl */ + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS)) + { + return netdev_ioctl(fd, req, arg); + } + else +#endif + { + err = EBADF; + goto errout; + } + } + +#if CONFIG_NFILE_DESCRIPTORS > 0 + /* Get the thread-specific file list */ + + list = sched_getfiles(); + if (!list) + { + err = EMFILE; + goto errout; + } + + /* Is a driver registered? Does it support the ioctl method? */ + + this_file = &list->fl_files[fd]; + inode = this_file->f_inode; + + if (inode && inode->u.i_ops && inode->u.i_ops->ioctl) + { + /* Yes, then let it perform the ioctl */ + + ret = (int)inode->u.i_ops->ioctl(this_file, req, arg); + if (ret < 0) + { + err = -ret; + goto errout; + } + } + + return ret; +#endif + +errout: + set_errno(err); + return ERROR; +} + diff --git a/nuttx/fs/fs_lseek.c b/nuttx/fs/fs_lseek.c new file mode 100644 index 0000000000..c576584349 --- /dev/null +++ b/nuttx/fs/fs_lseek.c @@ -0,0 +1,176 @@ +/**************************************************************************** + * fs/fs_lseek.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "fs_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lseek + * + * Description: + * The lseek() function repositions the offset of the open file associated + * with the file descriptor fildes to the argument 'offset' according to the + * directive 'whence' as follows: + * + * SEEK_SET + * The offset is set to offset bytes. + * SEEK_CUR + * The offset is set to its current location plus offset bytes. + * SEEK_END + * The offset is set to the size of the file plus offset bytes. + * + * The lseek() function allows the file offset to be set beyond the end of the + * file (but this does not change the size of the file). If data is later written + * at this point, subsequent reads of the data in the gap (a "hole") return null + * bytes ('\0') until data is actually written into the gap. + * + * Parameters: + * fd File descriptor of device + * offset Defines the offset to position to + * whence Defines how to use offset + * + * Return: + * The resulting offset on success. -1 on failure withi errno set properly: + * + * EBADF fildes is not an open file descriptor. + * EINVAL whence is not one of SEEK_SET, SEEK_CUR, SEEK_END; or the + * resulting file offset would be negative, or beyond the end of a + * seekable device. + * EOVERFLOW The resulting file offset cannot be represented in an off_t. + * ESPIPE fildes is associated with a pipe, socket, or FIFO. + * + ****************************************************************************/ + +off_t lseek(int fd, off_t offset, int whence) +{ + FAR struct filelist *list; + FAR struct file *filep; + FAR struct inode *inode; + int err; + + /* Did we get a valid file descriptor? */ + + if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) + { + err = EBADF; + goto errout; + } + + /* Get the thread-specific file list */ + + list = sched_getfiles(); + if (!list) + { + err = EMFILE; + goto errout; + } + + /* Is a driver registered? */ + + filep = &list->fl_files[fd]; + inode = filep->f_inode; + + if (inode && inode->u.i_ops) + { + /* Does it support the seek method */ + + if (inode->u.i_ops->seek) + { + /* Yes, then let it perform the seek */ + + err = (int)inode->u.i_ops->seek(filep, offset, whence); + if (err < 0) + { + err = -err; + goto errout; + } + } + else + { + /* No... there are a couple of default actions we can take */ + + switch (whence) + { + case SEEK_CUR: + offset += filep->f_pos; + + case SEEK_SET: + if (offset >= 0) + { + filep->f_pos = offset; /* Might be beyond the end-of-file */ + break; + } + else + { + err = EINVAL; + goto errout; + } + break; + + case SEEK_END: + err = ENOSYS; + goto errout; + + default: + err = EINVAL; + goto errout; + } + } + } + + return filep->f_pos; + +errout: + set_errno(err); + return (off_t)ERROR; +} + +#endif diff --git a/nuttx/fs/fs_mkdir.c b/nuttx/fs/fs_mkdir.c new file mode 100644 index 0000000000..6e201ce345 --- /dev/null +++ b/nuttx/fs/fs_mkdir.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * fs/fs_mkdir.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mkdir + * + * Description: Create a directory + * + ****************************************************************************/ + +int mkdir(const char *pathname, mode_t mode) +{ + FAR struct inode *inode; + const char *relpath = NULL; + int ret; + + /* Get an inode for this file */ + + inode = inode_find(pathname, &relpath); + if (!inode) + { + /* There is no mountpoint that includes in this path */ + + ret = ENOENT; + goto errout; + } + + /* Verify that the inode is a valid mountpoint. */ + + if (!INODE_IS_MOUNTPT(inode) || !inode->u.i_mops) + { + ret = ENXIO; + goto errout_with_inode; + } + + /* Perform the mkdir operation using the relative path + * at the mountpoint. + */ + + if (inode->u.i_mops->mkdir) + { + ret = inode->u.i_mops->mkdir(inode, relpath, mode); + if (ret < 0) + { + ret = -ret; + goto errout_with_inode; + } + } + else + { + ret = ENOSYS; + goto errout_with_inode; + } + + /* Directory successfully created */ + + inode_release(inode); + return OK; + + errout_with_inode: + inode_release(inode); + errout: + set_errno(ret); + return ERROR; +} + diff --git a/nuttx/fs/fs_mount.c b/nuttx/fs/fs_mount.c new file mode 100644 index 0000000000..228c1fc6ec --- /dev/null +++ b/nuttx/fs/fs_mount.c @@ -0,0 +1,397 @@ +/**************************************************************************** + * fs/fs_mount.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_APPS_BINDIR +# include +#endif + +#include "fs_internal.h" + +/* At least one filesystem must be defined, or this file will not compile. + * It may be desire-able to make filesystems dynamically registered at + * some time in the future, but at present, this file needs to know about + * every configured filesystem. + */ + +#ifdef CONFIG_FS_READABLE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* In the canonical case, a file system is bound to a block driver. However, + * some less typical cases a block driver is not required. Examples are + * pseudo file systems (like BINFS) and MTD file systems (like NXFFS). + * + * These file systems all require block drivers: + */ + +#if defined(CONFIG_FS_FAT) || defined(CONFIG_FS_ROMFS) +# define BDFS_SUPPORT 1 +#endif + +/* These file systems do not require block drivers */ + +#if defined(CONFIG_FS_NXFFS) || defined(CONFIG_APPS_BINDIR) || defined(CONFIG_NFS) +# define NONBDFS_SUPPORT +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct fsmap_t +{ + FAR const char *fs_filesystemtype; + FAR const struct mountpt_operations *fs_mops; +}; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +#ifdef BDFS_SUPPORT +#ifdef CONFIG_FS_FAT +extern const struct mountpt_operations fat_operations; +#endif +#ifdef CONFIG_FS_ROMFS +extern const struct mountpt_operations romfs_operations; +#endif + +static const struct fsmap_t g_bdfsmap[] = +{ +#ifdef CONFIG_FS_FAT + { "vfat", &fat_operations }, +#endif +#ifdef CONFIG_FS_ROMFS + { "romfs", &romfs_operations }, +#endif + { NULL, NULL }, +}; +#endif /* BDFS_SUPPORT*/ + +#ifdef NONBDFS_SUPPORT +#ifdef CONFIG_FS_NXFFS +extern const struct mountpt_operations nxffs_operations; +#endif +#ifdef CONFIG_NFS +extern const struct mountpt_operations nfs_operations; +#endif + +static const struct fsmap_t g_nonbdfsmap[] = +{ +#ifdef CONFIG_FS_NXFFS + { "nxffs", &nxffs_operations }, +#endif +#ifdef CONFIG_NFS + { "nfs", &nfs_operations }, +#endif +#ifdef CONFIG_APPS_BINDIR + { "binfs", &binfs_operations }, +#endif + { NULL, NULL }, +}; +#endif /* NONBDFS_SUPPORT */ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mount_findfs + * + * Description: + * find the specified filesystem + * + ****************************************************************************/ + +#if defined(BDFS_SUPPORT) || defined(NONBDFS_SUPPORT) +static FAR const struct mountpt_operations * +mount_findfs(FAR const struct fsmap_t *fstab, FAR const char *filesystemtype) +{ + FAR const struct fsmap_t *fsmap; + + for (fsmap = fstab; fsmap->fs_filesystemtype; fsmap++) + { + if (strcmp(filesystemtype, fsmap->fs_filesystemtype) == 0) + { + return fsmap->fs_mops; + } + } + + return NULL; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mount + * + * Description: + * mount() attaches the filesystem specified by the 'source' block device + * name into the root file system at the path specified by 'target.' + * + * Return: + * Zero is returned on success; -1 is returned on an error and errno is + * set appropriately: + * + * EACCES A component of a path was not searchable or mounting a read-only + * filesystem was attempted without giving the MS_RDONLY flag. + * EBUSY 'source' is already mounted. + * EFAULT One of the pointer arguments points outside the user address + * space. + * EINVAL 'source' had an invalid superblock. + * ENODEV 'filesystemtype' not configured + * ENOENT A pathname was empty or had a nonexistent component. + * ENOMEM Could not allocate a memory to copy filenames or data into. + * ENOTBLK 'source' is not a block device + * + ****************************************************************************/ + +int mount(FAR const char *source, FAR const char *target, + FAR const char *filesystemtype, unsigned long mountflags, + FAR const void *data) +{ +#if defined(BDFS_SUPPORT) || defined(NONBDFS_SUPPORT) +#ifdef BDFS_SUPPORT + FAR struct inode *blkdrvr_inode = NULL; +#endif + FAR struct inode *mountpt_inode; + FAR const struct mountpt_operations *mops; + void *fshandle; + int errcode; + int ret; + + /* Verify required pointer arguments */ + + DEBUGASSERT(target && filesystemtype); + + /* Find the specified filesystem. Try the block driver file systems first */ + +#ifdef BDFS_SUPPORT + if ((mops = mount_findfs(g_bdfsmap, filesystemtype)) != NULL) + { + /* Make sure that a block driver argument was provided */ + + DEBUGASSERT(source); + + /* Find the block driver */ + + ret = find_blockdriver(source, mountflags, &blkdrvr_inode); + if (ret < 0) + { + fdbg("Failed to find block driver %s\n", source); + errcode = -ret; + goto errout; + } + } + else +#endif /* BDFS_SUPPORT */ +#ifdef NONBDFS_SUPPORT + if ((mops = mount_findfs(g_nonbdfsmap, filesystemtype)) != NULL) + { + } + else +#endif /* NONBDFS_SUPPORT */ + { + fdbg("Failed to find file system %s\n", filesystemtype); + errcode = ENODEV; + goto errout; + } + + /* Insert a dummy node -- we need to hold the inode semaphore + * to do this because we will have a momentarily bad structure. + */ + + inode_semtake(); + ret = inode_reserve(target, &mountpt_inode); + if (ret < 0) + { + /* inode_reserve can fail for a couple of reasons, but the most likely + * one is that the inode already exists. inode_reserve may return: + * + * -EINVAL - 'path' is invalid for this operation + * -EEXIST - An inode already exists at 'path' + * -ENOMEM - Failed to allocate in-memory resources for the operation + */ + + fdbg("Failed to reserve inode\n"); + errcode = -ret; + goto errout_with_semaphore; + } + + /* Bind the block driver to an instance of the file system. The file + * system returns a reference to some opaque, fs-dependent structure + * that encapsulates this binding. + */ + + if (!mops->bind) + { + /* The filesystem does not support the bind operation ??? */ + + fdbg("Filesystem does not support bind\n"); + errcode = EINVAL; + goto errout_with_mountpt; + } + + /* Increment reference count for the reference we pass to the file system */ + +#ifdef BDFS_SUPPORT +#ifdef NONBDFS_SUPPORT + if (blkdrvr_inode) +#endif + { + blkdrvr_inode->i_crefs++; + } +#endif + + /* On failure, the bind method returns -errorcode */ + +#ifdef BDFS_SUPPORT + ret = mops->bind(blkdrvr_inode, data, &fshandle); +#else + ret = mops->bind(NULL, data, &fshandle); +#endif + if (ret != 0) + { + /* The inode is unhappy with the blkdrvr for some reason. Back out + * the count for the reference we failed to pass and exit with an + * error. + */ + + fdbg("Bind method failed: %d\n", ret); +#ifdef BDFS_SUPPORT +#ifdef NONBDFS_SUPPORT + if (blkdrvr_inode) +#endif + { + blkdrvr_inode->i_crefs--; + } +#endif + errcode = -ret; + goto errout_with_mountpt; + } + + /* We have it, now populate it with driver specific information. */ + + INODE_SET_MOUNTPT(mountpt_inode); + + mountpt_inode->u.i_mops = mops; +#ifdef CONFIG_FILE_MODE + mountpt_inode->i_mode = mode; +#endif + mountpt_inode->i_private = fshandle; + inode_semgive(); + + /* We can release our reference to the blkdrver_inode, if the filesystem + * wants to retain the blockdriver inode (which it should), then it must + * have called inode_addref(). There is one reference on mountpt_inode + * that will persist until umount() is called. + */ + +#ifdef BDFS_SUPPORT +#ifdef NONBDFS_SUPPORT + if (blkdrvr_inode) +#endif + { + inode_release(blkdrvr_inode); + } +#endif + + return OK; + + /* A lot of goto's! But they make the error handling much simpler */ + +errout_with_mountpt: + mountpt_inode->i_crefs = 0; + inode_remove(target); + inode_semgive(); +#ifdef BDFS_SUPPORT +#ifdef NONBDFS_SUPPORT + if (blkdrvr_inode) +#endif + { + inode_release(blkdrvr_inode); + } +#endif + + inode_release(mountpt_inode); + goto errout; + +errout_with_semaphore: + inode_semgive(); +#ifdef BDFS_SUPPORT +#ifdef NONBDFS_SUPPORT + if (blkdrvr_inode) +#endif + { + inode_release(blkdrvr_inode); + } +#endif + +errout: + set_errno(errcode); + return ERROR; + +#else + fdbg("No filesystems enabled\n"); + set_errno(ENOSYS); + return error; +#endif /* BDFS_SUPPORT || NONBDFS_SUPPORT */ +} + +#endif /* CONFIG_FS_READABLE */ + diff --git a/nuttx/fs/fs_open.c b/nuttx/fs/fs_open.c new file mode 100644 index 0000000000..5b318b7025 --- /dev/null +++ b/nuttx/fs/fs_open.c @@ -0,0 +1,206 @@ +/**************************************************************************** + * fs_open.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#ifdef CONFIG_FILE_MODE +#include +#endif +#include +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: inode_checkflags + * + * Description: + * Check if the access described by 'oflags' is supported on 'inode' + * + ****************************************************************************/ + +int inode_checkflags(FAR struct inode *inode, int oflags) +{ + if (((oflags & O_RDOK) != 0 && !inode->u.i_ops->read) || + ((oflags & O_WROK) != 0 && !inode->u.i_ops->write)) + { + return -EACCES; + } + else + { + return OK; + } +} + +/**************************************************************************** + * Name: open + * + * Description: + * Standard 'open' interface + * + ****************************************************************************/ + +int open(const char *path, int oflags, ...) +{ + FAR struct filelist *list; + FAR struct inode *inode; + FAR const char *relpath = NULL; +#if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT) + mode_t mode = 0666; +#endif + int ret; + int fd; + + /* Get the thread-specific file list */ + + list = sched_getfiles(); + if (!list) + { + ret = EMFILE; + goto errout; + } + +#ifdef CONFIG_FILE_MODE +# ifdef CONFIG_CPP_HAVE_WARNING +# warning "File creation not implemented" +# endif + + /* If the file is opened for creation, then get the mode bits */ + + if (oflags & (O_WRONLY|O_CREAT) != 0) + { + va_list ap; + va_start(ap, oflags); + mode = va_arg(ap, mode_t); + va_end(ap); + } +#endif + + /* Get an inode for this file */ + + inode = inode_find(path, &relpath); + if (!inode) + { + /* "O_CREAT is not set and the named file does not exist. Or, a + * directory component in pathname does not exist or is a dangling + * symbolic link." + */ + + ret = ENOENT; + goto errout; + } + + /* Verify that the inode is valid and either a "normal" or a mountpoint. We + * specifically exclude block drivers. + */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) || !inode->u.i_ops) +#else + if (!INODE_IS_DRIVER(inode) || !inode->u.i_ops) +#endif + { + ret = ENXIO; + goto errout_with_inode; + } + + /* Make sure that the inode supports the requested access */ + + ret = inode_checkflags(inode, oflags); + if (ret < 0) + { + ret = -ret; + goto errout_with_inode; + } + + /* Associate the inode with a file structure */ + + fd = files_allocate(inode, oflags, 0, 0); + if (fd < 0) + { + ret = EMFILE; + goto errout_with_inode; + } + + /* Perform the driver open operation. NOTE that the open method may be + * called many times. The driver/mountpoint logic should handled this + * because it may also be closed that many times. + */ + + ret = OK; + if (inode->u.i_ops->open) + { +#ifndef CONFIG_DISABLE_MOUNTPOINT + if (INODE_IS_MOUNTPT(inode)) + { + ret = inode->u.i_mops->open((FAR struct file*)&list->fl_files[fd], + relpath, oflags, mode); + } + else +#endif + { + ret = inode->u.i_ops->open((FAR struct file*)&list->fl_files[fd]); + } + } + + if (ret < 0) + { + ret = -ret; + goto errout_with_fd; + } + + return fd; + + errout_with_fd: + files_release(fd); + errout_with_inode: + inode_release(inode); + errout: + set_errno(ret); + return ERROR; +} diff --git a/nuttx/fs/fs_openblockdriver.c b/nuttx/fs/fs_openblockdriver.c new file mode 100644 index 0000000000..c59a255b00 --- /dev/null +++ b/nuttx/fs/fs_openblockdriver.c @@ -0,0 +1,128 @@ +/**************************************************************************** + * fs/fs_openblockdriver.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in pathname and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of pathname code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: open_blockdriver + * + * Description: + * Return the inode of the block driver specified by 'pathname' + * + * Inputs: + * pathname - the full path to the block driver to be opened + * mountflags - if MS_RDONLY is not set, then driver must support write + * operations (see include/sys/mount.h) + * ppinode - address of the location to return the inode reference + * + * Return: + * Returns zero on success or a negated errno on failure: + * + * EINVAL - pathname or pinode is NULL + * ENOENT - No block driver of this name is registered + * ENOTBLK - The inode associated with the pathname is not a block driver + * EACCESS - The MS_RDONLY option was not set but this driver does not + * support write access + * + ****************************************************************************/ + +int open_blockdriver(FAR const char *pathname, int mountflags, + FAR struct inode **ppinode) +{ + FAR struct inode *inode; + int ret; + + /* Minimal sanity checks */ + +#ifdef CONFIG_DEBUG + if (!ppinode) + { + ret = -EINVAL; + goto errout; + } +#endif + + /* Find the inode associated with this block driver name. find_blockdriver + * will perform all additional error checking. + */ + + ret = find_blockdriver(pathname, mountflags, &inode); + if (ret < 0) + { + fdbg("Failed to file %s block driver\n", pathname); + goto errout; + } + + /* Open the block driver. Note that no mutually exclusive access + * to the driver is enforced here. That must be done in the driver + * if needed. + */ + + if (inode->u.i_bops->open) + { + ret = inode->u.i_bops->open(inode); + if (ret < 0) + { + fdbg("%s driver open failed\n", pathname); + goto errout_with_inode; + } + } + + *ppinode = inode; + return OK; + +errout_with_inode: + inode_release(inode); +errout: + return ret; +} diff --git a/nuttx/fs/fs_opendir.c b/nuttx/fs/fs_opendir.c new file mode 100644 index 0000000000..a52c538fe2 --- /dev/null +++ b/nuttx/fs/fs_opendir.c @@ -0,0 +1,312 @@ +/**************************************************************************** + * fs/fs_opendir.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: open_mountpoint + * + * Description: + * Handle the case where the inode to be opened is within a mountpoint. + * + * Inputs: + * inode -- the inode of the mountpoint to open + * relpath -- the relative path within the mountpoint to open + * dir -- the dirent structure to be initialized + * + * Return: + * On success, OK is returned; Otherwise, a positive errno is returned. + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_MOUNTPOINT +static inline int open_mountpoint(FAR struct inode *inode, + FAR const char *relpath, + FAR struct fs_dirent_s *dir) +{ + int ret; + + /* The inode itself as the 'root' of mounted volume. The actually + * directory is at relpath into the* mounted filesystem. + * + * Verify that the mountpoint inode supports the opendir() method + */ + + if (!inode->u.i_mops || !inode->u.i_mops->opendir) + { + return ENOSYS; + } + + /* Take reference to the mountpoint inode (fd_root). Note that we do + * not use inode_addref() because we already hold the tree semaphore. + */ + + inode->i_crefs++; + + /* Perform the opendir() operation */ + + ret = inode->u.i_mops->opendir(inode, relpath, dir); + if (ret < 0) + { + /* We now need to back off our reference to the inode. We can't + * call inode_release() to do that unless we release the tree + * semaphore. The following should be safe because: (1) after the + * reference count was incremented above it should be >=1 so it should + * not decrement below zero, and (2) we hold the tree semaphore so no + * other thread should be able to change the reference count. + */ + + inode->i_crefs--; + DEBUGASSERT(inode->i_crefs >= 0); + + /* Negate the error value so that it can be used to set errno */ + + return -ret; + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: open_pseudodir + * + * Description: + * Handle the case where the inode to be opened is within the top-level + * pseudo-file system. + * + * Inputs: + * inode -- the inode of the mountpoint to open + * dir -- the dirent structure to be initialized + * + * Return: + * On success, OK is returned; Otherwise, a positive errno is returned. + * + ****************************************************************************/ + +static void open_pseudodir(FAR struct inode *inode, FAR struct fs_dirent_s *dir) +{ + /* We have a valid psuedo-filesystem node. Take two references on the + * inode -- one for the parent (fd_root) and one for the child (fd_next). + * Note that we do not call inode_addref because we are holding the tree + * semaphore and that would result in deadlock. + */ + + inode->i_crefs += 2; + dir->u.psuedo.fd_next = inode; /* This is the next node to use for readdir() */ + + /* Flag the inode as belonging to the psuedo-filesystem */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + DIRENT_SETPSUEDONODE(dir->fd_flags); +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: opendir + * + * Description: + * The opendir() function opens a directory stream corresponding to the + * directory name, and returns a pointer to the directory stream. The + * stream is positioned at the first entry in the directory. + * + * Inputs: + * path -- the directory to open + * + * Return: + * The opendir() function returns a pointer to the directory stream. On + * error, NULL is returned, and errno is set appropriately. + * + * EACCES - Permission denied. + * EMFILE - Too many file descriptors in use by process. + * ENFILE - Too many files are currently open in the + * system. + * ENOENT - Directory does not exist, or name is an empty + * string. + * ENOMEM - Insufficient memory to complete the operation. + * ENOTDIR - 'path' is not a directory. + * + ****************************************************************************/ + +FAR DIR *opendir(FAR const char *path) +{ + FAR struct inode *inode = NULL; + FAR struct fs_dirent_s *dir; + FAR const char *relpath; + bool bisroot = false; + int ret; + + /* If we are given 'nothing' then we will interpret this as + * request for the root inode. + */ + + inode_semtake(); + if (!path || *path == 0 || strcmp(path, "/") == 0) + { + inode = root_inode; + bisroot = true; + relpath = NULL; + } + else + { + /* We don't know what to do with relative pathes */ + + if (*path != '/') + { + ret = -ENOTDIR; + goto errout_with_semaphore; + } + + /* Find the node matching the path. */ + + inode = inode_search(&path, (FAR struct inode**)NULL, (FAR struct inode**)NULL, &relpath); + } + + /* Did we get an inode? */ + + if (!inode) + { + /* 'path' is not a does not exist.*/ + + ret = ENOTDIR; + goto errout_with_semaphore; + } + + /* Allocate a type DIR -- which is little more than an inode + * container. + */ + + dir = (FAR struct fs_dirent_s *)kzalloc(sizeof(struct fs_dirent_s)); + if (!dir) + { + /* Insufficient memory to complete the operation.*/ + + ret = ENOMEM; + goto errout_with_semaphore; + } + + /* Populate the DIR structure and return it to the caller. The way that + * we do this depends on whenever this is a "normal" psuedo-file-system + * inode or a file system mountpoint. + */ + + dir->fd_root = inode; /* Save the inode where we start */ + dir->fd_position = 0; /* This is the position in the read stream */ + + /* First, handle the special case of the root inode. This must be + * special-cased here because the root inode might ALSO be a mountpoint. + */ + + if (bisroot) + { + /* Whatever payload the root inode carries, the root inode is always + * a directory inode in the pseudo-file system + */ + + open_pseudodir(inode, dir); + } + + /* Is this a node in the psuedo filesystem? Or a mountpoint? If the node + * is the root (bisroot == TRUE), then this is a special case. + */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + else if (INODE_IS_MOUNTPT(inode)) + { + /* Yes, the node is a file system mointpoint. */ + + ret = open_mountpoint(inode, relpath, dir); + if (ret != OK) + { + goto errout_with_direntry; + } + } +#endif + else + { + /* The node is part of the root psuedo file system. Does the inode have a child? + * If so that the child would be the 'root' of a list of nodes under + * the directory. + */ + + inode = inode->i_child; + if (!inode) + { + ret = ENOTDIR; + goto errout_with_direntry; + } + + /* It looks we have a valid psuedo-filesystem directory node. */ + + open_pseudodir(inode, dir); + } + + inode_semgive(); + return ((DIR*)dir); + + /* Nasty goto's make error handling simpler */ + +errout_with_direntry: + kfree(dir); + +errout_with_semaphore: + inode_semgive(); + set_errno(ret); + return NULL; +} diff --git a/nuttx/fs/fs_poll.c b/nuttx/fs/fs_poll.c new file mode 100644 index 0000000000..2e3adeb5da --- /dev/null +++ b/nuttx/fs/fs_poll.c @@ -0,0 +1,327 @@ +/**************************************************************************** + * fs/fs_poll.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "fs_internal.h" + +#ifndef CONFIG_DISABLE_POLL + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define poll_semgive(sem) sem_post(sem) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: poll_semtake + ****************************************************************************/ + +static void poll_semtake(FAR sem_t *sem) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(sem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(get_errno() == EINTR); + } +} + +/**************************************************************************** + * Name: poll_fdsetup + * + * Description: + * Configure (or unconfigure) one file/socket descriptor for the poll + * operation. If fds and sem are non-null, then the poll is being setup. + * if fds and sem are NULL, then the poll is being torn down. + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static int poll_fdsetup(int fd, FAR struct pollfd *fds, bool setup) +{ + FAR struct filelist *list; + FAR struct file *this_file; + FAR struct inode *inode; + int ret = -ENOSYS; + + /* Check for a valid file descriptor */ + + if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) + { + /* Perform the socket ioctl */ + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS)) + { + return net_poll(fd, fds, setup); + } + else +#endif + { + return -EBADF; + } + } + + /* Get the thread-specific file list */ + + list = sched_getfiles(); + if (!list) + { + return -EMFILE; + } + + /* Is a driver registered? Does it support the poll method? + * If not, return -ENOSYS + */ + + this_file = &list->fl_files[fd]; + inode = this_file->f_inode; + + if (inode && inode->u.i_ops && inode->u.i_ops->poll) + { + /* Yes, then setup the poll */ + + ret = (int)inode->u.i_ops->poll(this_file, fds, setup); + } + return ret; +} +#endif + +/**************************************************************************** + * Name: poll_setup + * + * Description: + * Setup the poll operation for each descriptor in the list. + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static inline int poll_setup(FAR struct pollfd *fds, nfds_t nfds, sem_t *sem) +{ + int ret; + int i; + + /* Process each descriptor in the list */ + + for (i = 0; i < nfds; i++) + { + /* Setup the poll descriptor */ + + fds[i].sem = sem; + fds[i].revents = 0; + fds[i].priv = NULL; + + /* Set up the poll */ + + ret = poll_fdsetup(fds[i].fd, &fds[i], true); + if (ret < 0) + { + return ret; + } + } + return OK; +} +#endif + +/**************************************************************************** + * Name: poll_teardown + * + * Description: + * Teardown the poll operation for each descriptor in the list and return + * the count of non-zero poll events. + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static inline int poll_teardown(FAR struct pollfd *fds, nfds_t nfds, int *count) +{ + int status; + int ret = OK; + int i; + + /* Process each descriptor in the list */ + + *count = 0; + for (i = 0; i < nfds; i++) + { + /* Teardown the poll */ + + status = poll_fdsetup(fds[i].fd, &fds[i], false); + if (status < 0) + { + ret = status; + } + + /* Check if any events were posted */ + + if (fds[i].revents != 0) + { + (*count)++; + } + + /* Un-initialize the poll structure */ + + fds[i].sem = NULL; + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: poll_timeout + * + * Description: + * The wdog expired before any other events were received. + * + ****************************************************************************/ + +static void poll_timeout(int argc, uint32_t isem, ...) +{ + /* Wake up the poller */ + + FAR sem_t *sem = (FAR sem_t *)isem; + poll_semgive(sem); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: poll + * + * Description: + * poll() waits for one of a set of file descriptors to become ready to + * perform I/O. If none of the events requested (and no error) has + * occurred for any of the file descriptors, then poll() blocks until + * one of the events occurs. + * + * Inputs: + * fds - List of structures describing file descriptors to be monitored + * nfds - The number of entries in the list + * timeout - Specifies an upper limit on the time for which poll() will + * block in milliseconds. A negative value of timeout means an infinite + * timeout. + * + * Return: + * On success, the number of structures that have nonzero revents fields. + * A value of 0 indicates that the call timed out and no file descriptors + * were ready. On error, -1 is returned, and errno is set appropriately: + * + * EBADF - An invalid file descriptor was given in one of the sets. + * EFAULT - The fds address is invalid + * EINTR - A signal occurred before any requested event. + * EINVAL - The nfds value exceeds a system limit. + * ENOMEM - There was no space to allocate internal data structures. + * ENOSYS - One or more of the drivers supporting the file descriptor + * does not support the poll method. + * + ****************************************************************************/ + +int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout) +{ + WDOG_ID wdog; + sem_t sem; + int count = 0; + int ret; + + sem_init(&sem, 0, 0); + ret = poll_setup(fds, nfds, &sem); + if (ret >= 0) + { + if (timeout >= 0) + { + /* Wait for the poll event with a timeout. Note that the + * millisecond timeout has to be converted to system clock + * ticks for wd_start + */ + + wdog = wd_create(); + wd_start(wdog, MSEC2TICK(timeout), poll_timeout, 1, (uint32_t)&sem); + poll_semtake(&sem); + wd_delete(wdog); + } + else + { + /* Wait for the poll event with no timeout */ + + poll_semtake(&sem); + } + + /* Teardown the poll operation and get the count of events */ + + ret = poll_teardown(fds, nfds, &count); + } + + sem_destroy(&sem); + + /* Check for errors */ + + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return count; +} + +#endif /* CONFIG_DISABLE_POLL */ diff --git a/nuttx/fs/fs_read.c b/nuttx/fs/fs_read.c new file mode 100644 index 0000000000..30dd4af03e --- /dev/null +++ b/nuttx/fs/fs_read.c @@ -0,0 +1,147 @@ +/**************************************************************************** + * fs_read.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static inline ssize_t file_read(int fd, FAR void *buf, size_t nbytes) +{ + FAR struct filelist *list; + int ret = -EBADF; + + /* Get the thread-specific file list */ + + list = sched_getfiles(); + if (!list) + { + /* Failed to get the file list */ + + ret = -EMFILE; + } + + /* Were we given a valid file descriptor? */ + + else if ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS) + { + FAR struct file *this_file = &list->fl_files[fd]; + FAR struct inode *inode = this_file->f_inode; + + /* Yes.. Was this file opened for read access? */ + + if ((this_file->f_oflags & O_RDOK) == 0) + { + /* No.. File is not read-able */ + + ret = -EACCES; + } + + /* Is a driver or mountpoint registered? If so, does it support + * the read method? + */ + + else if (inode && inode->u.i_ops && inode->u.i_ops->read) + { + /* Yes.. then let it perform the read. NOTE that for the case + * of the mountpoint, we depend on the read methods bing + * identical in signature and position in the operations vtable. + */ + + ret = (int)inode->u.i_ops->read(this_file, (char*)buf, (size_t)nbytes); + } + } + + /* If an error occurred, set errno and return -1 (ERROR) */ + + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + /* Otherwise, return the number of bytes read */ + + return ret; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +ssize_t read(int fd, FAR void *buf, size_t nbytes) +{ + /* Did we get a valid file descriptor? */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) +#endif + { + /* No.. If networking is enabled, read() is the same as recv() with + * the flags parameter set to zero. + */ + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + return recv(fd, buf, nbytes, 0); +#else + /* No networking... it is a bad descriptor in any event */ + + set_errno(EBADF); + return ERROR; +#endif + } + + /* The descriptor is in a valid range to file descriptor... do the read */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + return file_read(fd, buf, nbytes); +#endif +} diff --git a/nuttx/fs/fs_readdir.c b/nuttx/fs/fs_readdir.c new file mode 100644 index 0000000000..8df1bf655d --- /dev/null +++ b/nuttx/fs/fs_readdir.c @@ -0,0 +1,230 @@ +/**************************************************************************** + * fs/fs_readdir.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: readpsuedodir + ****************************************************************************/ + +static inline int readpsuedodir(struct fs_dirent_s *idir) +{ + FAR struct inode *prev; + + /* Check if we are at the end of the list */ + + if (!idir->u.psuedo.fd_next) + { + /* End of file and error conditions are not distinguishable + * with readdir. Here we return -ENOENT to signal the end + * of the directory. + */ + + return -ENOENT; + } + + /* Copy the inode name into the dirent structure */ + + strncpy(idir->fd_dir.d_name, idir->u.psuedo.fd_next->i_name, NAME_MAX+1); + + /* If the node has file operations, we will say that it is + * a file. + */ + + idir->fd_dir.d_type = 0; + if (idir->u.psuedo.fd_next->u.i_ops) + { +#ifndef CONFIG_DISABLE_MOUNTPOINT + if (INODE_IS_BLOCK(idir->u.psuedo.fd_next)) + { + idir->fd_dir.d_type |= DTYPE_BLK; + } + if (INODE_IS_MOUNTPT(idir->u.psuedo.fd_next)) + { + idir->fd_dir.d_type |= DTYPE_DIRECTORY; + } + else +#endif + { + idir->fd_dir.d_type |= DTYPE_CHR; + } + } + + /* If the node has child node(s), then we will say that it + * is a directory. NOTE: that the node can be both! + */ + + if (idir->u.psuedo.fd_next->i_child || !idir->u.psuedo.fd_next->u.i_ops) + { + idir->fd_dir.d_type |= DTYPE_DIRECTORY; + } + + /* Now get the inode to vist next time that readdir() is called */ + + inode_semtake(); + + prev = idir->u.psuedo.fd_next; + idir->u.psuedo.fd_next = prev->i_peer; /* The next node to visit */ + + if (idir->u.psuedo.fd_next) + { + /* Increment the reference count on this next node */ + + idir->u.psuedo.fd_next->i_crefs++; + } + + inode_semgive(); + + if (prev) + { + inode_release(prev); + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: readdir + * + * Description: + * The readdir() function returns a pointer to a dirent structure + * representing the next directory entry in the directory stream pointed + * to by dir. It returns NULL on reaching the end-of-file or if an error + * occurred. + * + * Inputs: + * dirp -- An instance of type DIR created by a previous call to opendir(); + * + * Return: + * The readdir() function returns a pointer to a dirent structure, or NULL + * if an error occurs or end-of-file is reached. On error, errno is set + * appropriately. + * + * EBADF - Invalid directory stream descriptor dir + * + ****************************************************************************/ + +FAR struct dirent *readdir(DIR *dirp) +{ + FAR struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp; +#ifndef CONFIG_DISABLE_MOUNTPOINT + struct inode *inode; +#endif + int ret; + + /* Sanity checks */ + + if (!idir || !idir->fd_root) + { + ret = EBADF; + goto errout; + } + + /* The way we handle the readdir depends on the type of inode + * that we are dealing with. + */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + inode = idir->fd_root; + if (INODE_IS_MOUNTPT(inode) && !DIRENT_ISPSUEDONODE(idir->fd_flags)) + { + /* The node is a file system mointpoint. Verify that the mountpoint + * supports the readdir() method + */ + + if (!inode->u.i_mops || !inode->u.i_mops->readdir) + { + ret = EACCES; + goto errout; + } + + /* Perform the readdir() operation */ + + ret = inode->u.i_mops->readdir(inode, idir); + } + else +#endif + { + /* The node is part of the root psuedo file system */ + + ret = readpsuedodir(idir); + } + + /* ret < 0 is an error. Special case: ret = -ENOENT is end of file */ + + if ( ret < 0) + { + if (ret == -ENOENT) + { + ret = OK; + } + else + { + ret = -ret; + } + goto errout; + } + + /* Success */ + + idir->fd_position++; + return &idir->fd_dir; + +errout: + set_errno(ret); + return NULL; +} + diff --git a/nuttx/fs/fs_registerblockdriver.c b/nuttx/fs/fs_registerblockdriver.c new file mode 100644 index 0000000000..bb5a3121b0 --- /dev/null +++ b/nuttx/fs/fs_registerblockdriver.c @@ -0,0 +1,124 @@ +/**************************************************************************** + * fs/fs_registerblockdriver.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: register_blockdriver + * + * Description: + * Register a block driver inode the pseudo file system. + * + * Input parameters: + * path - The path to the inode to create + * bops - The block driver operations structure + * mode - inmode priviledges (not used) + * priv - Private, user data that will be associated with the inode. + * + * Returned Value: + * Zero on success (with the inode point in 'inode'); A negated errno + * value is returned on a failure (all error values returned by + * inode_reserve): + * + * EINVAL - 'path' is invalid for this operation + * EEXIST - An inode already exists at 'path' + * ENOMEM - Failed to allocate in-memory resources for the operation + * + ****************************************************************************/ + +int register_blockdriver(FAR const char *path, + FAR const struct block_operations *bops, + mode_t mode, FAR void *priv) +{ + FAR struct inode *node; + int ret; + + /* Insert an inode for the device driver -- we need to hold the inode + * semaphore to prevent access to the tree while we this. This is because + * we will have a momentarily bad true until we populate the inode with + * valid data. + */ + + inode_semtake(); + ret = inode_reserve(path, &node); + if (ret >= 0) + { + /* We have it, now populate it with block driver specific information. */ + + INODE_SET_BLOCK(node); + + node->u.i_bops = bops; +#ifdef CONFIG_FILE_MODE + node->i_mode = mode; +#endif + node->i_private = priv; + ret = OK; + } + + inode_semgive(); + return ret; +} + diff --git a/nuttx/fs/fs_registerdriver.c b/nuttx/fs/fs_registerdriver.c new file mode 100644 index 0000000000..cc1759ee72 --- /dev/null +++ b/nuttx/fs/fs_registerdriver.c @@ -0,0 +1,120 @@ +/**************************************************************************** + * fs/fs_registerdriver.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: register_driver + * + * Description: + * Register a character driver inode the pseudo file system. + * + * Input parameters: + * path - The path to the inode to create + * fops - The file operations structure + * mode - inmode priviledges (not used) + * priv - Private, user data that will be associated with the inode. + * + * Returned Value: + * Zero on success (with the inode point in 'inode'); A negated errno + * value is returned on a failure (all error values returned by + * inode_reserve): + * + * EINVAL - 'path' is invalid for this operation + * EEXIST - An inode already exists at 'path' + * ENOMEM - Failed to allocate in-memory resources for the operation + * + ****************************************************************************/ + +int register_driver(FAR const char *path, FAR const struct file_operations *fops, + mode_t mode, FAR void *priv) +{ + FAR struct inode *node; + int ret; + + /* Insert a dummy node -- we need to hold the inode semaphore because we + * will have a momentarily bad structure. + */ + + inode_semtake(); + ret = inode_reserve(path, &node); + if (ret >= 0) + { + /* We have it, now populate it with driver specific information. */ + + INODE_SET_DRIVER(node); + + node->u.i_ops = fops; +#ifdef CONFIG_FILE_MODE + node->i_mode = mode; +#endif + node->i_private = priv; + ret = OK; + } + + inode_semgive(); + return ret; +} diff --git a/nuttx/fs/fs_rename.c b/nuttx/fs/fs_rename.c new file mode 100644 index 0000000000..157775132c --- /dev/null +++ b/nuttx/fs/fs_rename.c @@ -0,0 +1,153 @@ +/**************************************************************************** + * fs/fs_rename.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rename + * + * Description: Remove a file managed a mountpoint + * + ****************************************************************************/ + +int rename(FAR const char *oldpath, FAR const char *newpath) +{ + FAR struct inode *oldinode; + FAR struct inode *newinode; + const char *oldrelpath = NULL; + const char *newrelpath = NULL; + int ret; + + /* Get an inode for the old relpath */ + + oldinode = inode_find(oldpath, &oldrelpath); + if (!oldinode) + { + /* There is no mountpoint that includes in this path */ + + ret = ENOENT; + goto errout; + } + + /* Verify that the old inode is a valid mountpoint. */ + + if (!INODE_IS_MOUNTPT(oldinode) || !oldinode->u.i_mops) + { + ret = ENXIO; + goto errout_with_oldinode; + } + + /* Get an inode for the new relpath -- it should like on the same mountpoint */ + + newinode = inode_find(newpath, &newrelpath); + if (!newinode) + { + /* There is no mountpoint that includes in this path */ + + ret = ENOENT; + goto errout_with_oldinode; + } + + /* Verify that the two pathes lie on the same mountpt inode */ + + if (oldinode != newinode) + { + ret = EXDEV; + goto errout_with_newinode; + } + + /* Perform the rename operation using the relative pathes + * at the common mountpoint. + */ + + if (oldinode->u.i_mops->rename) + { + ret = oldinode->u.i_mops->rename(oldinode, oldrelpath, newrelpath); + if (ret < 0) + { + ret = -ret; + goto errout_with_newinode; + } + } + else + { + ret = ENOSYS; + goto errout_with_newinode; + } + + /* Successfully renamed */ + + inode_release(oldinode); + inode_release(newinode); + return OK; + + errout_with_newinode: + inode_release(newinode); + errout_with_oldinode: + inode_release(oldinode); + errout: + set_errno(ret); + return ERROR; +} diff --git a/nuttx/fs/fs_rewinddir.c b/nuttx/fs/fs_rewinddir.c new file mode 100644 index 0000000000..a0e2be7d88 --- /dev/null +++ b/nuttx/fs/fs_rewinddir.c @@ -0,0 +1,145 @@ +/**************************************************************************** + * fs/fs_rewinddir.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rewindpsuedodir + ****************************************************************************/ + +static inline void rewindpsuedodir(struct fs_dirent_s *idir) +{ + struct inode *prev; + + inode_semtake(); + + /* Reset the position to the beginning */ + + prev = idir->u.psuedo.fd_next; /* (Save to delete later) */ + idir->u.psuedo.fd_next = idir->fd_root; /* The next node to visit */ + idir->fd_position = 0; /* Reset position */ + + /* Increment the reference count on the root=next node. We + * should now have two references on the inode. + */ + + idir->fd_root->i_crefs++; + inode_semgive(); + + /* Then release the reference to the old next inode */ + + if (prev) + { + inode_release(prev); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rewinddir + * + * Description: + * The rewinddir() function resets the position of the + * directory stream dir to the beginning of the directory. + * + * Inputs: + * dirp -- An instance of type DIR created by a previous + * call to opendir(); + * + * Return: + * None + * + ****************************************************************************/ + +void rewinddir(FAR DIR *dirp) +{ + struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp; +#ifndef CONFIG_DISABLE_MOUNTPOINT + struct inode *inode; +#endif + + /* Sanity checks */ + + if (!idir || !idir->fd_root) + { + return; + } + + /* The way we handle the readdir depends on the type of inode + * that we are dealing with. + */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + inode = idir->fd_root; + if (INODE_IS_MOUNTPT(inode)) + { + /* The node is a file system mointpoint. Verify that the mountpoint + * supports the rewinddir() method + */ + + if (inode->u.i_mops && inode->u.i_mops->rewinddir) + { + /* Perform the rewinddir() operation */ + + inode->u.i_mops->rewinddir(inode, idir); + } + } + else +#endif + { + /* The node is part of the root psuedo file system */ + + rewindpsuedodir(idir); + } +} diff --git a/nuttx/fs/fs_rmdir.c b/nuttx/fs/fs_rmdir.c new file mode 100644 index 0000000000..6c64de5cf2 --- /dev/null +++ b/nuttx/fs/fs_rmdir.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * fs/fs_rmdir.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rmdir + * + * Description: Remove a file managed a mountpoint + * + ****************************************************************************/ + +int rmdir(FAR const char *pathname) +{ + FAR struct inode *inode; + const char *relpath = NULL; + int ret; + + /* Get an inode for this file */ + + inode = inode_find(pathname, &relpath); + if (!inode) + { + /* There is no mountpoint that includes in this path */ + + ret = ENOENT; + goto errout; + } + + /* Verify that the inode is a valid mountpoint. */ + + if (!INODE_IS_MOUNTPT(inode) || !inode->u.i_mops) + { + ret = ENXIO; + goto errout_with_inode; + } + + /* Perform the rmdir operation using the relative path + * at the mountpoint. + */ + + if (inode->u.i_mops->rmdir) + { + ret = inode->u.i_mops->rmdir(inode, relpath); + if (ret < 0) + { + ret = -ret; + goto errout_with_inode; + } + } + else + { + ret = ENOSYS; + goto errout_with_inode; + } + + /* Successfully removed the directory */ + + inode_release(inode); + return OK; + + errout_with_inode: + inode_release(inode); + errout: + set_errno(ret); + return ERROR; +} + diff --git a/nuttx/fs/fs_seekdir.c b/nuttx/fs/fs_seekdir.c new file mode 100644 index 0000000000..ec530c67d0 --- /dev/null +++ b/nuttx/fs/fs_seekdir.c @@ -0,0 +1,230 @@ +/**************************************************************************** + * fs/fs_seekdir.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: seekpsuedodir + ****************************************************************************/ + +static inline void seekpsuedodir(struct fs_dirent_s *idir, off_t offset) +{ + struct inode *curr; + struct inode *prev; + off_t pos; + + /* Determine a starting point for the seek. If the seek + * is "forward" from the current position, then we will + * start at the current poisition. Otherwise, we will + * "rewind" to the root dir. + */ + + if ( offset < idir->fd_position ) + { + pos = 0; + curr = idir->fd_root; + } + else + { + pos = idir->fd_position; + curr = idir->u.psuedo.fd_next; + } + + /* Traverse the peer list starting at the 'root' of the + * the list until we find the node at 'offset". If devices + * are being registered and unregistered, then this can + * be a very unpredictable operation. + */ + + inode_semtake(); + for (; curr && pos != offset; pos++, curr = curr->i_peer); + + /* Now get the inode to vist next time that readdir() is called */ + + prev = idir->u.psuedo.fd_next; + idir->u.psuedo.fd_next = curr; /* The next node to visit (might be null) */ + idir->fd_position = pos; /* Might be beyond the last dirent */ + + if (curr) + { + /* Increment the reference count on this next node */ + + curr->i_crefs++; + } + + inode_semgive(); + + if (prev) + { + inode_release(prev); + } +} + +/**************************************************************************** + * Name: seekmountptdir + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_MOUNTPOINT +static inline void seekmountptdir(struct fs_dirent_s *idir, off_t offset) +{ + struct inode *inode; + off_t pos; + + /* Determine a starting point for the seek. If the seek + * is "forward" from the current position, then we will + * start at the current poisition. Otherwise, we will + * "rewind" to the root dir. + */ + + inode = idir->fd_root; + if ( offset < idir->fd_position ) + { + if (inode->u.i_mops && inode->u.i_mops->rewinddir) + { + /* Perform the rewinddir() operation */ + + inode->u.i_mops->rewinddir(inode, idir); + pos = 0; + } + else + { + /* We can't do the seek and there is no way to return + * an error indication. + */ + + return; + } + } + else + { + pos = idir->fd_position; + } + + /* This is a brute force approach... we will just read + * directory entries until we are at the desired position. + */ + + while (pos < offset) + { + if (!inode->u.i_mops || !inode->u.i_mops->readdir || + inode->u.i_mops->readdir(inode, idir) < 0) + { + /* We can't read the next entry and there is no way to return + * an error indication. + */ + + return; + } + + /* Increment the position on each successful read */ + + pos++; + } + + /* If we get here the directory position has been successfully set */ + + idir->fd_position = pos; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: seekdir + * + * Description: + * The seekdir() function sets the location in the directory stream from + * which the next readdir() call will start. seekdir() should be used with + * an offset returned by telldir(). + * + * Inputs: + * dirp -- An instance of type DIR created by a previous + * call to opendir(); + * offset -- offset to seek to + * + * Return: + * None + * + ****************************************************************************/ + +void seekdir(FAR DIR *dirp, off_t offset) +{ + struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp; + + /* Sanity checks */ + + if (!idir || !idir->fd_root) + { + return; + } + + /* The way we handle the readdir depends on the type of inode + * that we are dealing with. + */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + if (INODE_IS_MOUNTPT(idir->fd_root)) + { + /* The node is a file system mointpoint */ + + seekmountptdir(idir, offset); + } + else +#endif + { + /* The node is part of the root psuedo file system */ + + seekpsuedodir(idir, offset); + } +} diff --git a/nuttx/fs/fs_select.c b/nuttx/fs/fs_select.c new file mode 100644 index 0000000000..e40c5bc137 --- /dev/null +++ b/nuttx/fs/fs_select.c @@ -0,0 +1,239 @@ +/**************************************************************************** + * fs/fs_select.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "fs_internal.h" + +#ifndef CONFIG_DISABLE_POLL + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: select + * + * Description: + * select() allows a program to monitor multiple file descriptors, waiting + * until one or more of the file descriptors become "ready" for some class + * of I/O operation (e.g., input possible). A file descriptor is + * considered ready if it is possible to perform the corresponding I/O + * operation (e.g., read(2)) without blocking. + * + * NOTE: poll() is the fundamental API for performing such monitoring + * operation under NuttX. select() is provided for compatibility and + * is simply a layer of added logic on top of poll(). As such, select() + * is more wasteful of resources and poll() is the recommended API to be + * used. + * + * Input parameters: + * nfds - the maximum fd number (+1) of any descriptor in any of the + * three sets. + * readfds - the set of descriptions to monitor for read-ready events + * writefds - the set of descriptions to monitor for write-ready events + * exceptfds - the set of descriptions to monitor for error events + * timeout - Return at this time if none of these events of interest + * occur. + * + * Return: + * 0: Timer expired + * >0: The number of bits set in the three sets of descriptors + * -1: An error occurred (errno will be set appropriately) + * + ****************************************************************************/ + +int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds, + FAR fd_set *exceptfds, FAR struct timeval *timeout) +{ + struct pollfd *pollset; + int fd; + int npfds; + int msec; + int ndx; + int ret; + + /* Allocate the descriptor list for poll() */ + + pollset = (struct pollfd *)kzalloc(nfds * sizeof(struct pollfd)); + if (!pollset) + { + set_errno(ENOMEM); + return ERROR; + } + + /* Initialize the descriptor list for poll() */ + + for (fd = 0, npfds = 0; fd < nfds; fd++) + { + int incr = 0; + + /* The readfs set holds the set of FDs that the caller can be assured + * of reading from without blocking. Note that POLLHUP is included as + * a read-able condition. POLLHUP will be reported at the end-of-file + * or when a connection is lost. In either case, the read() can then + * be performed without blocking. + */ + + if (readfds && FD_ISSET(fd, readfds)) + { + pollset[npfds].fd = fd; + pollset[npfds].events |= POLLIN; + incr = 1; + } + + /* The writefds set holds the set of FDs that the caller can be assured + * of writing to without blocking. + */ + + if (writefds && FD_ISSET(fd, writefds)) + { + pollset[npfds].fd = fd; + pollset[npfds].events |= POLLOUT; + incr = 1; + } + + /* The exceptfds set holds the set of FDs that are watched for exceptions */ + + if (exceptfds && FD_ISSET(fd, exceptfds)) + { + pollset[npfds].fd = fd; + incr = 1; + } + + npfds += incr; + } + + /* Convert the timeout to milliseconds */ + + msec = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; + + /* Then let poll do all of the real work. */ + + ret = poll(pollset, npfds, msec); + + /* Now set up the return values */ + + if (readfds) + { + memset(readfds, 0, sizeof(fd_set)); + } + + if (writefds) + { + memset(writefds, 0, sizeof(fd_set)); + } + + if (exceptfds) + { + memset(exceptfds, 0, sizeof(fd_set)); + } + + /* Convert the poll descriptor list back into selects 3 bitsets */ + + if (ret > 0) + { + ret = 0; + for (ndx = 0; ndx < npfds; ndx++) + { + /* Check for read conditions. Note that POLLHUP is included as a + * read condition. POLLHUP will be reported when no more data will + * be available (such as when a connection is lost). In either + * case, the read() can then be performed without blocking. + */ + + if (readfds) + { + if (pollset[ndx].revents & (POLLIN|POLLHUP)) + { + FD_SET(pollset[ndx].fd, readfds); + ret++; + } + } + + /* Check for write conditions */ + + if (writefds) + { + if (pollset[ndx].revents & POLLOUT) + { + FD_SET(pollset[ndx].fd, writefds); + ret++; + } + } + + /* Check for exceptions */ + + if (exceptfds) + { + if (pollset[ndx].revents & POLLERR) + { + FD_SET(pollset[ndx].fd, exceptfds); + ret++; + } + } + } + } + + kfree(pollset); + return ret; +} + +#endif /* CONFIG_DISABLE_POLL */ + diff --git a/nuttx/fs/fs_stat.c b/nuttx/fs/fs_stat.c new file mode 100644 index 0000000000..5cb3420818 --- /dev/null +++ b/nuttx/fs/fs_stat.c @@ -0,0 +1,223 @@ +/**************************************************************************** + * fs/fs_stat.c + * + * Copyright (C) 2007-2009 , 2012Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: statpsuedo + ****************************************************************************/ + +static inline int statpsuedo(FAR struct inode *inode, FAR struct stat *buf) +{ + /* Most of the stat entries just do not apply */ + + memset(buf, 0, sizeof(struct stat) ); + if (inode->u.i_ops) + { + if (inode->u.i_ops->read) + { + buf->st_mode = S_IROTH|S_IRGRP|S_IRUSR; + } + + if (inode->u.i_ops->write) + { + buf->st_mode |= S_IWOTH|S_IWGRP|S_IWUSR; + } + + if (INODE_IS_MOUNTPT(inode)) + { + buf->st_mode |= S_IFDIR; + } + else if (INODE_IS_BLOCK(inode)) + { + /* What is it also has child inodes? */ + + buf->st_mode |= S_IFBLK; + } + else + { + /* What is it if it also has child inodes? */ + + buf->st_mode |= S_IFCHR; + } + } + else + { + /* If it has no operations, then it must just be a intermediate + * node in the inode tree. It is something like a directory. + * We'll say that all psuedo-directories are read-able but not + * write-able. + */ + + buf->st_mode |= S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR; + } + + return OK; +} + +/**************************************************************************** + * Name: statroot + ****************************************************************************/ + +static inline int statroot(FAR struct stat *buf) +{ + /* There is no inode associated with the fake root directory */ + + memset(buf, 0, sizeof(struct stat) ); + buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR; + return OK; +} + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stat + * + * Return: Zero on success; -1 on failure with errno set: + * + * EACCES Search permission is denied for one of the directories in the + * path prefix of path. + * EFAULT Bad address. + * ENOENT A component of the path path does not exist, or the path is an + * empty string. + * ENOMEM Out of memory + * ENOTDIR A component of the path is not a directory. + * + ****************************************************************************/ + +int stat(const char *path, FAR struct stat *buf) +{ + FAR struct inode *inode; + const char *relpath = NULL; + int ret = OK; + + /* Sanity checks */ + + if (!path || !buf) + { + ret = EFAULT; + goto errout; + } + + if (!path[0]) + { + ret = ENOENT; + goto errout; + } + + /* Check for the fake root directory (which has no inode) */ + + if (strcmp(path, "/") == 0) + { + return statroot(buf); + } + + /* Get an inode for this file */ + + inode = inode_find(path, &relpath); + if (!inode) + { + /* This name does not refer to a psudeo-inode and there is no + * mountpoint that includes in this path. + */ + + ret = ENOENT; + goto errout; + } + + /* The way we handle the stat depends on the type of inode that we + * are dealing with. + */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + if (INODE_IS_MOUNTPT(inode)) + { + /* The node is a file system mointpoint. Verify that the mountpoint + * supports the stat() method + */ + + if (inode->u.i_mops && inode->u.i_mops->stat) + { + /* Perform the stat() operation */ + + ret = inode->u.i_mops->stat(inode, relpath, buf); + } + } + else +#endif + { + /* The node is part of the root psuedo file system */ + + ret = statpsuedo(inode, buf); + } + + /* Check if the stat operation was successful */ + + if (ret < 0) + { + ret = -ret; + goto errout_with_inode; + } + + /* Successfully stat'ed the file */ + + inode_release(inode); + return OK; + +/* Failure conditions always set the errno appropriately */ + +errout_with_inode: + inode_release(inode); +errout: + set_errno(ret); + return ERROR; +} diff --git a/nuttx/fs/fs_statfs.c b/nuttx/fs/fs_statfs.c new file mode 100644 index 0000000000..540eb86bb3 --- /dev/null +++ b/nuttx/fs/fs_statfs.c @@ -0,0 +1,165 @@ +/**************************************************************************** + * fs/fs_statfs.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: statpsuedo + ****************************************************************************/ + +static inline int statpsuedofs(FAR struct inode *inode, FAR struct statfs *buf) +{ + memset(buf, 0, sizeof(struct statfs)); + buf->f_type = PROC_SUPER_MAGIC; + buf->f_namelen = NAME_MAX; + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stat + * + * Return: Zero on success; -1 on failure with errno set: + * + * EACCES Search permission is denied for one of the directories in the + * path prefix of path. + * EFAULT Bad address. + * ENOENT A component of the path path does not exist, or the path is an + * empty string. + * ENOMEM Out of memory + * ENOTDIR A component of the path is not a directory. + * ENOSYS The file system does not support this call. + * + ****************************************************************************/ + +int statfs(FAR const char *path, FAR struct statfs *buf) +{ + FAR struct inode *inode; + FAR const char *relpath = NULL; + int ret = OK; + + /* Sanity checks */ + + if (!path || !buf) + { + ret = EFAULT; + goto errout; + } + + if (!path[0]) + { + ret = ENOENT; + goto errout; + } + + /* Get an inode for this file */ + + inode = inode_find(path, &relpath); + if (!inode) + { + /* This name does not refer to a psudeo-inode and there is no + * mountpoint that includes in this path. + */ + + ret = ENOENT; + goto errout; + } + + /* The way we handle the statfs depends on the type of inode that we + * are dealing with. + */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + if (INODE_IS_MOUNTPT(inode)) + { + /* The node is a file system mointpoint. Verify that the mountpoint + * supports the statfs() method + */ + + if (inode->u.i_mops && inode->u.i_mops->statfs) + { + /* Perform the statfs() operation */ + + ret = inode->u.i_mops->statfs(inode, buf); + } + } + else +#endif + { + /* The node is part of the root psuedo file system */ + + ret = statpsuedofs(inode, buf); + } + + /* Check if the statfs operation was successful */ + + if (ret < 0) + { + ret = -ret; + goto errout_with_inode; + } + + /* Successfully statfs'ed the file */ + + inode_release(inode); + return OK; + +/* Failure conditions always set the errno appropriately */ + +errout_with_inode: + inode_release(inode); +errout: + set_errno(ret); + return ERROR; +} diff --git a/nuttx/fs/fs_syslog.c b/nuttx/fs/fs_syslog.c new file mode 100644 index 0000000000..1fe8c03a1c --- /dev/null +++ b/nuttx/fs/fs_syslog.c @@ -0,0 +1,515 @@ +/**************************************************************************** + * fs/syslog.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "fs_internal.h" + +#if defined(CONFIG_SYSLOG) && defined(CONFIG_SYSLOG_CHAR) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + + /* Open the device/file write-only, try to create (file) it if it doesn't + * exist, if the file that already exists, then append the new log data to + * end of the file. + */ + +#define SYSLOG_OFLAGS (O_WRONLY | O_CREAT | O_APPEND) + +/* An invalid thread ID */ + +#define NO_HOLDER ((pid_t)-1) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This enumeration represents the state of the SYSLOG device interface */ + +enum syslog_state_e +{ + SYSLOG_UNINITIALIZED = 0, /* SYSLOG has not been initialized */ + SYSLOG_INITIALIZING, /* SYSLOG is being initialized */ + SYSLOG_REOPEN, /* SYSLOG open failed... try again later */ + SYSLOG_FAILURE, /* SYSLOG open failed... don't try again */ + SYSLOG_OPENED, /* SYSLOG device is open and ready to use */ +}; + +/* This structure contains all SYSLOGing state information */ + +struct syslog_dev_s +{ + uint8_t sl_state; /* See enum syslog_state_e */ + sem_t sl_sem; /* Enforces mutually exclusive access */ + pid_t sl_holder; /* PID of the thread that holds the semaphore */ + struct file sl_file; /* The syslog file structure */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This is the device structure for the console or syslogging function. */ + +static struct syslog_dev_s g_sysdev; +static const uint8_t g_syscrlf[2] = { '\r', '\n' }; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: syslog_takesem + * + * Description: + * Write to the syslog device + * + ****************************************************************************/ + +static inline int syslog_takesem(void) +{ + pid_t me = getpid(); + int ret; + + /* Does this thread already hold the semaphore? That could happen if + * we wer called recursively, i.e., if the logic kicked off by + * syslog_write() where to generate more debug output. Return an error + * in that case. + */ + + if (g_sysdev.sl_holder == me) + { + /* Return an error (instead of deadlocking) */ + + return -EWOULDBLOCK; + } + + /* Either the semaphore is available or is currently held by another + * thread. Wait for it to become available. + */ + + ret = sem_wait(&g_sysdev.sl_sem); + if (ret < 0) + { + return -get_errno(); + } + + /* We hold the semaphore. We can safely mark ourself as the holder + * of the semaphore. + */ + + g_sysdev.sl_holder = me; + return OK; +} + +/**************************************************************************** + * Name: syslog_givesem + * + * Description: + * Write to the syslog device + * + ****************************************************************************/ + +static inline void syslog_givesem(void) +{ + pid_t me = getpid(); + DEBUGASSERT(g_sysdev.sl_holder == me); + + /* Relinquish the semaphore */ + + g_sysdev.sl_holder = NO_HOLDER; + sem_post(&g_sysdev.sl_sem); +} + +/**************************************************************************** + * Name: syslog_write + * + * Description: + * Write to the syslog device + * + ****************************************************************************/ + +static inline ssize_t syslog_write(FAR const void *buf, size_t nbytes) +{ + FAR struct inode *inode; + + /* Let the driver perform the write */ + + inode = g_sysdev.sl_file.f_inode; + return inode->u.i_ops->write(&g_sysdev.sl_file, buf, nbytes); +} + +/**************************************************************************** + * Name: syslog_flush + * + * Description: + * Flush any buffer data in the file system to media. + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_MOUNTPOINT +static inline void syslog_flush(void) +{ + FAR struct inode *inode = g_sysdev.sl_file.f_inode; + + /* Is this a mountpoint? Does it support the sync method? */ + + if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops->sync) + { + /* Yes... synchronize to the stream */ + + (void)inode->u.i_mops->sync(&g_sysdev.sl_file); + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: syslog_initialize + * + * Description: + * Initialize to use the character device (or file) at + * CONFIG_SYSLOG_DEVPATH as the SYSLOG sink. + * + * NOTE that this implementation excludes using a network connection as + * SYSLOG device. That would be a good extension. + * + ****************************************************************************/ + +int syslog_initialize(void) +{ + FAR struct inode *inode; + FAR const char *relpath = NULL; + int ret; + + /* At this point, the only expected states are SYSLOG_UNINITIALIZED or + * SYSLOG_REOPEN.. Not SYSLOG_INITIALIZING, SYSLOG_FAILURE, SYSLOG_OPENED. + */ + + DEBUGASSERT(g_sysdev.sl_state == SYSLOG_UNINITIALIZED || + g_sysdev.sl_state == SYSLOG_REOPEN); + + g_sysdev.sl_state = SYSLOG_INITIALIZING; + + /* Try to open the device. + * + * Note that we cannot just call open. The syslog device must work on all + * threads. Open returns a file descriptor that is valid only for the + * task that opened the device (and its pthread children). Instead, we + * essentially re-implement the guts of open() here so that we can get to + * the thread-independent structures of the inode. + */ + + /* Get an inode for this file/device */ + + inode = inode_find(CONFIG_SYSLOG_DEVPATH, &relpath); + if (!inode) + { + /* The inode was not found. In this case, we will attempt to re-open + * the device repeatedly. The assumption is that the device path is + * value but that the driver has not yet been registered. + */ + + g_sysdev.sl_state = SYSLOG_REOPEN; + return -ENOENT; + } + + /* Verify that the inode is valid and either a character driver or a + * mountpoint. + */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode))) +#else + if (!INODE_IS_DRIVER(inode)) +#endif + { + ret = ENXIO; + goto errout_with_inode; + } + + /* Make sure that the "entity" at this inode supports write access */ + + if (!inode->u.i_ops || !inode->u.i_ops->write) + { + return -EACCES; + goto errout_with_inode; + } + + /* Initialize the file structure */ + + g_sysdev.sl_file.f_oflags = SYSLOG_OFLAGS; + g_sysdev.sl_file.f_pos = 0; + g_sysdev.sl_file.f_inode = inode; + + /* Perform the low-level open operation. */ + + ret = OK; + if (inode->u.i_ops->open) + { + /* Is the inode a mountpoint? */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + if (INODE_IS_MOUNTPT(inode)) + { + /* Yes. Open the device write-only, try to create it if it + * doesn't exist, if the file that already exists, then append the + * new log data to end of the file. + */ + + ret = inode->u.i_mops->open(&g_sysdev.sl_file, relpath, + SYSLOG_OFLAGS, 0666); + } + + /* No... then it must be a character driver in the NuttX psuedo- + * file system. + */ + + else +#endif + { + ret = inode->u.i_ops->open(&g_sysdev.sl_file); + } + } + + /* Was the file/device successfully opened? */ + + if (ret < 0) + { + ret = -ret; + goto errout_with_inode; + } + + /* The SYSLOG device is open and ready for writing. */ + + sem_init(&g_sysdev.sl_sem, 0, 1); + g_sysdev.sl_holder = NO_HOLDER; + g_sysdev.sl_state = SYSLOG_OPENED; + return OK; + + errout_with_inode: + g_sysdev.sl_state = SYSLOG_FAILURE; + inode_release(inode); + return ret; +} + +/**************************************************************************** + * Name: syslog_putc + * + * Description: + * This is the low-level system logging interface. The debugging/syslogging + * interfaces are lib_rawprintf() and lib_lowprinf(). The difference is + * the lib_rawprintf() writes to fd=1 (stdout) and lib_lowprintf() uses + * a lower level interface that works from interrupt handlers. This + * function is a a low-level interface used to implement lib_lowprintf(). + * + ****************************************************************************/ + +int syslog_putc(int ch) +{ + ssize_t nbytes; + int ret; + + /* Ignore any output: + * + * (1) Before the SYSLOG device has been initialized. This could happen + * from debug output that occurs early in the boot sequence before + * syslog_initialize() is called (SYSLOG_UNINITIALIZED). + * (2) While the device is being initialized. The case could happen if + * debug output is generated while syslog_initialize() executes + * (SYSLOG_INITIALIZING). + * (3) While we are generating SYSLOG output. The case could happen if + * debug output is generated while syslog_putc() executes + * (This case is actually handled inside of syslog_semtake()). + * (4) Any debug output generated from interrupt handlers. A disadvantage + * of using the generic character device for the SYSLOG is that it + * cannot handle debug output generated from interrupt level handlers. + * (5) If an irrecoverable failure occurred during initialization. In + * this case, we won't ever bother to try again (ever). + * + * NOTE: That the third case is different. It applies only to the thread + * that currently holds the sl_sem sempaphore. Other threads should wait. + * that is why that case is handled in syslog_semtake(). + */ + + /* Case (4) */ + + if (up_interrupt_context()) + { + return -ENOSYS; /* Not supported */ + } + + /* We can save checks in the usual case: That after the SYSLOG device + * has been successfully opened. + */ + + if (g_sysdev.sl_state != SYSLOG_OPENED) + { + /* Case (1) and (2) */ + + if (g_sysdev.sl_state == SYSLOG_UNINITIALIZED || + g_sysdev.sl_state == SYSLOG_INITIALIZING) + { + return -EAGAIN; /* Can't access the SYSLOG now... maybe next time? */ + } + + /* Case (5) */ + + if (g_sysdev.sl_state == SYSLOG_FAILURE) + { + return -ENXIO; /* There is no SYSLOG device */ + } + + /* syslog_initialize() is called as soon as enough of the operating + * system is in place to support the open operation... but it is + * possible that the SYSLOG device is not yet registered at that time. + * In this case, we know that the system is sufficiently initialized + * to support an attempt to re-open the SYSLOG device. + * + * NOTE that the scheduler is locked. That is because we do not have + * fully initialized semaphore capability until the SYSLOG device is + * successfully initialized + */ + + sched_lock(); + if (g_sysdev.sl_state == SYSLOG_REOPEN) + { + /* Try again to initialize the device. We may do this repeatedly + * because the log device might be something that was not ready + * the first time that syslog_intialize() was called (such as a + * USB serial device that has not yet been connected or a file in + * an NFS mounted file system that has not yet been mounted). + */ + + ret = syslog_initialize(); + if (ret < 0) + { + sched_unlock(); + return ret; + } + } + + sched_unlock(); + DEBUGASSERT(g_sysdev.sl_state == SYSLOG_OPENED); + } + + /* Ignore carriage returns */ + + if (ch == '\r') + { + return ch; + } + + /* The syslog device is ready for writing and we have something of + * value to write. + */ + + ret = syslog_takesem(); + if (ret < 0) + { + /* We probably already hold the semaphore and were probably + * re-entered by the logic kicked off by syslog_write(). + * We might also have been interrupted by a signal. Either + * way, we are outta here. + */ + + return ret; + } + + /* Pre-pend a newline with a carriage return. */ + + if (ch == '\n') + { + /* Write the CR-LF sequence */ + + nbytes = syslog_write(g_syscrlf, 2); + + /* Synchronize the file when each CR-LF is encountered (i.e., + * implements line buffering always). + */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + if (nbytes > 0) + { + syslog_flush(); + } +#endif + } + else + { + /* Write the non-newline character (and don't flush) */ + + nbytes = syslog_write(&ch, 1); + } + + syslog_givesem(); + + /* Check if the write was successful */ + + if (nbytes < 0) + { + return nbytes; + } + + return ch; +} + +#endif /* CONFIG_SYSLOG && CONFIG_SYSLOG_CHAR */ diff --git a/nuttx/fs/fs_umount.c b/nuttx/fs/fs_umount.c new file mode 100644 index 0000000000..5bf44e4f77 --- /dev/null +++ b/nuttx/fs/fs_umount.c @@ -0,0 +1,206 @@ +/**************************************************************************** + * fs/fs_umount.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: umount + * + * Description: + * umount() detaches the filesystem mounted at the path specified by + * 'target.' + * + * Return: + * Zero is returned on success; -1 is returned on an error and errno is + * set appropriately: + * + * EACCES A component of a path was not searchable or mounting a read-only + * filesystem was attempted without giving the MS_RDONLY flag. + * EBUSY The target could not be unmounted because it is busy. + * EFAULT The pointer argument points outside the user address space. + * + ****************************************************************************/ + +int umount(const char *target) +{ + FAR struct inode *mountpt_inode; + FAR struct inode *blkdrvr_inode = NULL; + int errcode = OK; + int status; + + /* Verify required pointer arguments */ + + if (!target) + { + errcode = EFAULT; + goto errout; + } + + /* Find the mountpt */ + + mountpt_inode = inode_find(target, NULL); + if (!mountpt_inode) + { + errcode = ENOENT; + goto errout; + } + + /* Verify that the inode is a mountpoint */ + + if (!INODE_IS_MOUNTPT(mountpt_inode)) + { + errcode = EINVAL; + goto errout_with_mountpt; + } + + /* Unbind the block driver from the file system (destroying any fs + * private data. + */ + + if (!mountpt_inode->u.i_mops->unbind) + { + /* The filesystem does not support the unbind operation ??? */ + + errcode = EINVAL; + goto errout_with_mountpt; + } + + /* The unbind method returns the number of references to the + * filesystem (i.e., open files), zero if the unbind was + * performed, or a negated error code on a failure. + */ + + inode_semtake(); /* Hold the semaphore through the unbind logic */ + status = mountpt_inode->u.i_mops->unbind( mountpt_inode->i_private, &blkdrvr_inode); + if (status < 0) + { + /* The inode is unhappy with the blkdrvr for some reason */ + + errcode = -status; + goto errout_with_semaphore; + } + else if (status > 0) + { + errcode = EBUSY; + goto errout_with_semaphore; + } + + /* Successfully unbound */ + + mountpt_inode->i_private = NULL; + + /* Successfully unbound, remove the mountpoint inode from + * the inode tree. The inode will not be deleted yet because + * there is still at least reference on it (from the mount) + */ + + status = inode_remove(target); + inode_semgive(); + + /* The return value of -EBUSY is normal (in fact, it should + * not be OK) + */ + + if (status != OK && status != -EBUSY) + { + errcode = -status; + goto errout_with_mountpt; + } + + /* Release the mountpoint inode and any block driver inode + * returned by the file system unbind above. This should cause + * the inode to be deleted (unless there are other references) + */ + + inode_release(mountpt_inode); + + /* Did the unbind method return a contained block driver */ + + if (blkdrvr_inode) + { + inode_release(blkdrvr_inode); + } + + return OK; + + /* A lot of goto's! But they make the error handling much simpler */ + +errout_with_semaphore: + inode_semgive(); +errout_with_mountpt: + inode_release(mountpt_inode); + if (blkdrvr_inode) + { + inode_release(blkdrvr_inode); + } +errout: + set_errno(errcode); + return ERROR; +} + diff --git a/nuttx/fs/fs_unlink.c b/nuttx/fs/fs_unlink.c new file mode 100644 index 0000000000..f57bd33b57 --- /dev/null +++ b/nuttx/fs/fs_unlink.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * fs_unlink.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: unlink + * + * Description: Remove a file managed a mountpoint + * + ****************************************************************************/ + +int unlink(FAR const char *pathname) +{ + FAR struct inode *inode; + const char *relpath = NULL; + int ret; + + /* Get an inode for this file */ + + inode = inode_find(pathname, &relpath); + if (!inode) + { + /* There is no mountpoint that includes in this path */ + + ret = ENOENT; + goto errout; + } + + /* Verify that the inode is a valid mountpoint. */ + + if (!INODE_IS_MOUNTPT(inode) || !inode->u.i_mops) + { + ret = ENXIO; + goto errout_with_inode; + } + + /* Perform the unlink operation using the relative path + * at the mountpoint. + */ + + if (inode->u.i_mops->unlink) + { + ret = inode->u.i_mops->unlink(inode, relpath); + if (ret < 0) + { + ret = -ret; + goto errout_with_inode; + } + } + else + { + ret = ENOSYS; + goto errout_with_inode; + } + + /* Successfully unlinked */ + + inode_release(inode); + return OK; + + errout_with_inode: + inode_release(inode); + errout: + set_errno(ret); + return ERROR; +} + diff --git a/nuttx/fs/fs_unregisterblockdriver.c b/nuttx/fs/fs_unregisterblockdriver.c new file mode 100644 index 0000000000..4ee9016fce --- /dev/null +++ b/nuttx/fs/fs_unregisterblockdriver.c @@ -0,0 +1,86 @@ +/**************************************************************************** + * fs/fs_unregisterblockdriver.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: unregister_blockdriver + * + * Description: + * Remove the block driver inode at 'path' from the psuedo-file system + * + ****************************************************************************/ + +int unregister_blockdriver(const char *path) +{ + int ret; + + inode_semtake(); + ret = inode_remove(path); + inode_semgive(); + return ret; +} diff --git a/nuttx/fs/fs_unregisterdriver.c b/nuttx/fs/fs_unregisterdriver.c new file mode 100644 index 0000000000..7537274b54 --- /dev/null +++ b/nuttx/fs/fs_unregisterdriver.c @@ -0,0 +1,86 @@ +/**************************************************************************** + * fs/fs_unregisterdriver.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "fs_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: unregister_driver + * + * Description: + * Remove the character driver inode at 'path' from the psuedo-file system + * + ****************************************************************************/ + +int unregister_driver(FAR const char *path) +{ + int ret; + + inode_semtake(); + ret = inode_remove(path); + inode_semgive(); + return ret; +} diff --git a/nuttx/fs/fs_write.c b/nuttx/fs/fs_write.c new file mode 100644 index 0000000000..93dad92c4f --- /dev/null +++ b/nuttx/fs/fs_write.c @@ -0,0 +1,188 @@ +/**************************************************************************** + * fs/fs_write.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 +# include +#endif + +#include "fs_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static inline ssize_t file_write(int fd, FAR const void *buf, size_t nbytes) +{ + FAR struct filelist *list; + FAR struct file *this_file; + FAR struct inode *inode; + int ret; + int err; + + /* Get the thread-specific file list */ + + list = sched_getfiles(); + if (!list) + { + err = EMFILE; + goto errout; + } + + /* Was this file opened for write access? */ + + this_file = &list->fl_files[fd]; + if ((this_file->f_oflags & O_WROK) == 0) + { + err = EBADF; + goto errout; + } + + /* Is a driver registered? Does it support the write method? */ + + inode = this_file->f_inode; + if (!inode || !inode->u.i_ops || !inode->u.i_ops->write) + { + err = EBADF; + goto errout; + } + + /* Yes, then let the driver perform the write */ + + ret = inode->u.i_ops->write(this_file, buf, nbytes); + if (ret < 0) + { + err = -ret; + goto errout; + } + + return ret; + +errout: + set_errno(err); + return ERROR; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/*************************************************************************** + * Name: write + * + * Description: + * write() writes up to nytes bytes to the file referenced by the file + * descriptor fd from the buffer starting at buf. + * + * Parameters: + * fd file descriptor (or socket descriptor) to write to + * buf Data to write + * nbytes Length of data to write + * + * Returned Value: + * On success, the number of bytes written are returned (zero indicates + * nothing was written). On error, -1 is returned, and errno is set appro- + * priately: + * + * EAGAIN + * Non-blocking I/O has been selected using O_NONBLOCK and the write + * would block. + * EBADF + * fd is not a valid file descriptor or is not open for writing. + * EFAULT + * buf is outside your accessible address space. + * EFBIG + * An attempt was made to write a file that exceeds the implementation + * defined maximum file size or the process' file size limit, or + * to write at a position past the maximum allowed offset. + * EINTR + * The call was interrupted by a signal before any data was written. + * EINVAL + * fd is attached to an object which is unsuitable for writing; or + * the file was opened with the O_DIRECT flag, and either the address + * specified in buf, the value specified in count, or the current + * file offset is not suitably aligned. + * EIO + * A low-level I/O error occurred while modifying the inode. + * ENOSPC + * The device containing the file referred to by fd has no room for + * the data. + * EPIPE + * fd is connected to a pipe or socket whose reading end is closed. + * When this happens the writing process will also receive a SIGPIPE + * signal. (Thus, the write return value is seen only if the program + * catches, blocks or ignores this signal.) + * + * Assumptions: + * + ********************************************************************************************/ + +ssize_t write(int fd, FAR const void *buf, size_t nbytes) +{ + /* Did we get a valid file descriptor? */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) +#endif + { + /* Write to a socket descriptor is equivalent to send with flags == 0 */ + +#if defined(CONFIG_NET_TCP) && CONFIG_NSOCKET_DESCRIPTORS > 0 + return send(fd, buf, nbytes, 0); +#else + set_errno(EBADF); + return ERROR; +#endif + } + + /* The descriptor is in the right range to be a file descriptor... write to the file */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + return file_write(fd, buf, nbytes); +#endif +} + diff --git a/nuttx/fs/mmap/Kconfig b/nuttx/fs/mmap/Kconfig new file mode 100644 index 0000000000..03482e2d81 --- /dev/null +++ b/nuttx/fs/mmap/Kconfig @@ -0,0 +1,27 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config FS_RAMMAP + bool "File mapping emulation" + default n + ---help--- + NuttX operates in a flat open address space and is focused on MCUs that do + support Memory Management Units (MMUs). Therefore, NuttX generally does not + require mmap() functionality and the MCUs generally cannot support true + memory-mapped files. + + However, memory mapping of files is the mechanism used by NXFLAT, the NuttX + tiny binary format, to get files into memory in order to execute them. + mmap() support is therefore required to support NXFLAT. + + If FS_RAMMAP is defined in the configuration, then mmap() will + support simulation of memory mapped files by copying files whole + into RAM. These copied files have some of the properties of + standard memory mapped files. + + See nuttx/fs/mmap/README.txt for additonal information. + +if FS_RAMMAP +endif diff --git a/nuttx/fs/mmap/Make.defs b/nuttx/fs/mmap/Make.defs new file mode 100644 index 0000000000..2d3d006949 --- /dev/null +++ b/nuttx/fs/mmap/Make.defs @@ -0,0 +1,43 @@ +############################################################################ +# fs/mmap/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name Nuttx nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ASRCS += +CSRCS += fs_mmap.c + +ifeq ($(CONFIG_FS_RAMMAP),y) +CSRCS += fs_munmap.c fs_rammap.c +endif + +MMAPDEPPATH = --dep-path mmap diff --git a/nuttx/fs/mmap/README.txt b/nuttx/fs/mmap/README.txt new file mode 100755 index 0000000000..cf4c51e9e8 --- /dev/null +++ b/nuttx/fs/mmap/README.txt @@ -0,0 +1,78 @@ +fs/mmap README File +=================== + +NuttX operates in a flat open address space and is focused on MCUs that do +support Memory Management Units (MMUs). Therefore, NuttX generally does not +require mmap() functionality and the MCUs generally cannot support true +memory-mapped files. + +However, memory mapping of files is the mechanism used by NXFLAT, the NuttX +tiny binary format, to get files into memory in order to execute them. +mmap() support is therefore required to support NXFLAT. There are two +conditions where mmap() can be supported: + +1. mmap can be used to support eXecute In Place (XIP) on random access media + under the following very restrictive conditions: + + a. The filesystem supports the FIOC_MMAP ioctl command. Any file + system that maps files contiguously on the media should support + this ioctl. (vs. file system that scatter files over the media + in non-contiguous sectors). As of this writing, ROMFS is the + only file system that meets this requirement. + + b. The underlying block driver supports the BIOC_XIPBASE ioctl + command that maps the underlying media to a randomly accessible + address. At present, only the RAM/ROM disk driver does this. + + Some limitations of this approach are as follows: + + a. Since no real mapping occurs, all of the file contents are "mapped" + into memory. + + b. All mapped files are read-only. + + c. There are no access privileges. + +2. If CONFIG_FS_RAMMAP is defined in the configuration, then mmap() will + support simulation of memory mapped files by copying files whole + into RAM. These copied files have some of the properties of + standard memory mapped files. There are many, many exceptions + exceptions, however. Some of these include: + + a. The goal is to have a single region of memory that represents a single + file and can be shared by many threads. That is, given a filename a + thread should be able to open the file, get a file descriptor, and + call mmap() to get a memory region. Different file descriptors opened + with the same file path should get the same memory region when mapped. + + The limitation in the current design is that there is insufficient + knowledge to know that these different file descriptors correspond to + the same file. So, for the time being, a new memory region is created + each time that rammap() is called. Not very useful! + + b. The entire mapped portion of the file must be present in memory. + Since it is assumed the the MCU does not have an MMU, on-demanding + paging in of file blocks cannot be supported. Since the while mapped + portion of the file must be present in memory, there are limitations + in the size of files that may be memory mapped (especially on MCUs + with no significant RAM resources). + + c. All mapped files are read-only. You can write to the in-memory image, + but the file contents will not change. + + d. There are no access privileges. + + e. Since there are no processes in NuttX, all mmap() and munmap() + operations have immediate, global effects. Under Linux, for example, + munmap() would eliminate only the mapping with a process; the mappings + to the same file in other processes would not be effected. + + f. Like true mapped file, the region will persist after closing the file + descriptor. However, at present, these ram copied file regions are + *not* automatically "unmapped" (i.e., freed) when a thread is terminated. + This is primarily because it is not possible to know how many users + of the mapped region there are and, therefore, when would be the + appropriate time to free the region (other than when munmap is called). + + NOTE: Note, if the design limitation of a) were solved, then it would be + easy to solve exception d) as well. diff --git a/nuttx/fs/mmap/fs_mmap.c b/nuttx/fs/mmap/fs_mmap.c new file mode 100644 index 0000000000..5764b16f1d --- /dev/null +++ b/nuttx/fs/mmap/fs_mmap.c @@ -0,0 +1,174 @@ +/**************************************************************************** + * fs/mmap/fs_mmap.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "fs_internal.h" +#include "fs_rammap.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mmap + * + * Description: + * NuttX operates in a flat open address space. Therefore, it generally + * does not require mmap() functionality. There are two exceptions: + * + * 1. mmap() is the API that is used to support direct access to random + * access media under the following very restrictive conditions: + * + * a. The filesystem supports the FIOC_MMAP ioctl command. Any file + * system that maps files contiguously on the media should support + * this ioctl. (vs. file system that scatter files over the media + * in non-contiguous sectors). As of this writing, ROMFS is the + * only file system that meets this requirement. + * b. The underlying block driver supports the BIOC_XIPBASE ioctl + * command that maps the underlying media to a randomly accessible + * address. At present, only the RAM/ROM disk driver does this. + * + * 2. If CONFIG_FS_RAMMAP is defined in the configuration, then mmap() will + * support simulation of memory mapped files by copying files whole + * into RAM. + * + * Parameters: + * start A hint at where to map the memory -- ignored. The address + * of the underlying media is fixed and cannot be re-mapped without + * MMU support. + * length The length of the mapping. For exception #1 above, this length + * ignored: The entire underlying media is always accessible. + * prot See the PROT_* definitions in sys/mman.h. + * PROT_NONE - Will cause an error + * PROT_READ - PROT_WRITE and PROT_EXEC also assumed + * PROT_WRITE - PROT_READ and PROT_EXEC also assumed + * PROT_EXEC - PROT_READ and PROT_WRITE also assumed + * flags See the MAP_* definitions in sys/mman.h. + * MAP_SHARED - Required + * MAP_PRIVATE - Will cause an error + * MAP_FIXED - Will cause an error + * MAP_FILE - Ignored + * MAP_ANONYMOUS - Will cause an error + * MAP_ANON - Will cause an error + * MAP_GROWSDOWN - Ignored + * MAP_DENYWRITE - Will cause an error + * MAP_EXECUTABLE - Ignored + * MAP_LOCKED - Ignored + * MAP_NORESERVE - Ignored + * MAP_POPULATE - Ignored + * MAP_NONBLOCK - Ignored + * fd file descriptor of the backing file -- required. + * offset The offset into the file to map + * + * Returned Value: + * On success, mmap() returns a pointer to the mapped area. On error, the + * value MAP_FAILED is returned, and errno is set appropriately. + * + * ENOSYS + * Returned if any of the unsupported mmap() features are attempted + * EBADF + * 'fd' is not a valid file descriptor. + * EINVAL + * Length is 0. flags contained neither MAP_PRIVATE or MAP_SHARED, or + * contained both of these values. + * ENODEV + * The underlying filesystem of the specified file does not support + * memory mapping. + * + ****************************************************************************/ + +FAR void *mmap(FAR void *start, size_t length, int prot, int flags, + int fd, off_t offset) +{ + FAR void *addr; + int ret; + + /* Since only a tiny subset of mmap() functionality, we have to verify many + * things. + */ + +#ifdef CONFIG_DEBUG + if (prot == PROT_NONE || + (flags & (MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_DENYWRITE)) != 0) + { + fdbg("Unsupported options, prot=%x flags=%04x\n", prot, flags); + errno = ENOSYS; + return MAP_FAILED; + } + + if (length == 0 || (flags & MAP_SHARED) == 0) + { + fdbg("Invalid options, lengt=%d flags=%04x\n", length, flags); + errno = EINVAL; + return MAP_FAILED; + } +#endif + + /* Okay now we can assume a shared mapping from a file. This is the + * only option supported + * + * Perform the ioctl to get the base address of the file in 'mapped' + * in memory. (casting to uintptr_t first eliminates complaints on some + * architectures where the sizeof long is different from the size of + * a pointer). + */ + + ret = ioctl(fd, FIOC_MMAP, (unsigned long)((uintptr_t)&addr)); + if (ret < 0) + { +#ifdef CONFIG_FS_RAMMAP + return rammap(fd, length, offset); +#else + fdbg("ioctl(FIOC_MMAP) failed: %d\n", errno); + return MAP_FAILED; +#endif + } + + /* Return the offset address */ + + return (void*)(((uint8_t*)addr) + offset); +} diff --git a/nuttx/fs/mmap/fs_munmap.c b/nuttx/fs/mmap/fs_munmap.c new file mode 100644 index 0000000000..a4b9dc6091 --- /dev/null +++ b/nuttx/fs/mmap/fs_munmap.c @@ -0,0 +1,212 @@ +/**************************************************************************** + * fs/mmap/fs_munmap.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include "fs_internal.h" +#include "fs_rammap.h" + +#ifdef CONFIG_FS_RAMMAP + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: munmap + * + * Description: + * + * munmap() system call deletes mappings for the specified address range. + * All memory starting with 'start' and continuing for a length of 'length' + * bytes are removed. + * + * NuttX operates in a flat open address space. Therefore, it generally + * does not require mmap() and, hence, munmap functionality. There are + * two exceptions where mmap() is available: + * + * 1. mmap() is the API that is used to support direct access to random + * access media under the following very restrictive conditions: + * + * a. The filesystem supports the FIOC_MMAP ioctl command. Any file + * system that maps files contiguously on the media should support + * this ioctl. (vs. file system that scatter files over the media + * in non-contiguous sectors). As of this writing, ROMFS is the + * only file system that meets this requirement. + * b. The underlying block driver supports the BIOC_XIPBASE ioctl + * command that maps the underlying media to a randomly accessible + * address. At present, only the RAM/ROM disk driver does this. + * + * munmap() is still not required in this first case. In this first + * The mapped address is a static address in the MCUs address space + * does not need to be munmapped. Support for munmap() in this case + * provided by the simple definition in sys/mman.h: + * + * #define munmap(start, length) + * + * 2. If CONFIG_FS_RAMMAP is defined in the configuration, then mmap() will + * support simulation of memory mapped files by copying files whole + * into RAM. munmap() is required in this case to free the allocated + * memory holding the shared copy of the file. + * + * Parameters: + * start The start address of the mapping to delete. For this + * simplified munmap() implementation, the *must* be the start + * address of the memory region (the same address returned by + * mmap()). + * length The length region to be umapped. + * + * Returned Value: + * On success, munmap() returns 0, on failure -1, and errno is set + * (probably to EINVAL). + * + ****************************************************************************/ + +int munmap(FAR void *start, size_t length) +{ + FAR struct fs_rammap_s *prev; + FAR struct fs_rammap_s *curr; + FAR void *newaddr; + unsigned int offset; + int ret; + int err; + + /* Find a region containing this start and length in the list of regions */ + + rammap_initialize(); + ret = sem_wait(&g_rammaps.exclsem); + if (ret < 0) + { + return ERROR; + } + + /* Seach the list of regions */ + + for (prev = NULL, curr = g_rammaps.head; curr; prev = curr, curr = curr->flink) + { + /* Does this region include any part of the specified range? */ + + if ((uintptr_t)start < (uintptr_t)curr->addr + curr->length && + (uintptr_t)start + length >= (uintptr_t)curr->addr) + { + break; + } + } + + /* Did we find the region */ + + if (!curr) + { + fdbg("Region not found\n"); + err = EINVAL; + goto errout_with_semaphore; + } + + /* Get the offset from the beginning of the region and the actual number + * of bytes to "unmap". All mappings must extend to the end of the region. + * There is no support for free a block of memory but leaving a block of + * memory at the end. This is a consequence of using realloc() to + * simulate the unmapping. + */ + + offset = start - curr->addr; + if (offset + length < curr->length) + { + fdbg("Cannot umap without unmapping to the end\n"); + err = ENOSYS; + goto errout_with_semaphore; + } + + /* Okay.. the region is beging umapped to the end. Make sure the length + * indicates that. + */ + + length = curr->length - offset; + + /* Are we unmapping the entire region (offset == 0)? */ + + if (length >= curr->length) + { + /* Yes.. remove the mapping from the list */ + + if (prev) + { + prev->flink = curr->flink; + } + else + { + g_rammaps.head = curr->flink; + } + + /* Then free the region */ + + kfree(curr); + } + + /* No.. We have been asked to "unmap' only a portion of the memory + * (offset > 0). + */ + + else + { + newaddr = krealloc(curr->addr, sizeof(struct fs_rammap_s) + length); + DEBUGASSERT(newaddr == (FAR void*)(curr->addr)); + curr->length = length; + } + + sem_post(&g_rammaps.exclsem); + return OK; + +errout_with_semaphore: + sem_post(&g_rammaps.exclsem); + errno = err; + return ERROR; +} + +#endif /* CONFIG_FS_RAMMAP */ diff --git a/nuttx/fs/mmap/fs_rammap.c b/nuttx/fs/mmap/fs_rammap.c new file mode 100644 index 0000000000..0eaf313b59 --- /dev/null +++ b/nuttx/fs/mmap/fs_rammap.c @@ -0,0 +1,238 @@ +/**************************************************************************** + * fs/mmap/fs_rammmap.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include "fs_internal.h" +#include "fs_rammap.h" + +#ifdef CONFIG_FS_RAMMAP + +/**************************************************************************** + * Global Data + ****************************************************************************/ + +/* This is the list of all mapped files */ + +struct fs_allmaps_s g_rammaps; + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rammap_initialize + * + * Description: + * Verified that this capability has been initialized. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void rammap_initialize(void) +{ + if (!g_rammaps.initialized) + { + sem_init(&g_rammaps.exclsem, 0, 1); + g_rammaps.initialized = true; + } +} + +/**************************************************************************** + * Name: rammmap + * + * Description: + * Support simulation of memory mapped files by copying files into RAM. + * + * Parameters: + * fd file descriptor of the backing file -- required. + * length The length of the mapping. For exception #1 above, this length + * ignored: The entire underlying media is always accessible. + * offset The offset into the file to map + * + * Returned Value: + * On success, rammmap() returns a pointer to the mapped area. On error, the + * value MAP_FAILED is returned, and errno is set appropriately. + * + * EBADF + * 'fd' is not a valid file descriptor. + * EINVAL + * 'length' or 'offset' are invalid + * ENOMEM + * Insufficient memory is available to map the file. + * + ****************************************************************************/ + +FAR void *rammap(int fd, size_t length, off_t offset) +{ + FAR struct fs_rammap_s *map; + FAR uint8_t *alloc; + FAR uint8_t *rdbuffer; + ssize_t nread; + off_t fpos; + int err; + int ret; + + /* There is a major design flaw that I have not yet thought of fix for: + * The goal is to have a single region of memory that represents a single + * file and can be shared by many threads. That is, given a filename a + * thread should be able to open the file, get a file descriptor, and + * call mmap() to get a memory region. Different file descriptors opened + * with the same file path should get the same memory region when mapped. + * + * The design flaw is that I don't have sufficient knowledge to know that + * these different file descriptors map to the same file. So, for the time + * being, a new memory region is created each time that rammap() is called. + * Not very useful! + */ + + /* Allocate a region of memory of the specified size */ + + alloc = (FAR uint8_t *)kmalloc(sizeof(struct fs_rammap_s) + length); + if (!alloc) + { + fdbg("Region allocation failed, length: %d\n", (int)length); + err = ENOMEM; + goto errout; + } + + /* Initialize the region */ + + map = (FAR struct fs_rammap_s *)alloc; + memset(map, 0, sizeof(struct fs_rammap_s)); + map->addr = alloc + sizeof(struct fs_rammap_s); + map->length = length; + map->offset = offset; + + /* Seek to the specified file offset */ + + fpos = lseek(fd, offset, SEEK_SET); + if (fpos == (off_t)-1) + { + /* Seek failed... errno has already been set, but EINVAL is probably + * the correct response. + */ + + fdbg("Seek to position %d failed\n", (int)offset); + err = ENOMEM; + goto errout_with_region; + } + + /* Read the file data into the memory region */ + + rdbuffer = map->addr; + while (length > 0) + { + nread = read(fd, rdbuffer, length); + if (nread < 0) + { + /* Handle the special case where the read was interrupted by a + * signal. + */ + + if (nread != EINTR) + { + /* All other read errors are bad. errno is already set. + * (but maybe should be forced to EINVAL?) + */ + + fdbg("Read failed: %d\n", (int)offset); + goto errout_with_errno; + } + + /* Check for end of file. */ + + if (nread == 0) + { + break; + } + + /* Increment number of bytes read */ + + rdbuffer += nread; + length -= nread; + } + } + + /* Zero any memory beyond the amount read from the file */ + + memset(rdbuffer, 0, length); + + /* Add the buffer to the list of regions */ + + rammap_initialize(); + ret = sem_wait(&g_rammaps.exclsem); + if (ret < 0) + { + goto errout_with_errno; + } + + map->flink = g_rammaps.head; + g_rammaps.head = map; + + sem_post(&g_rammaps.exclsem); + return map->addr; + +errout_with_region: + kfree(alloc); +errout: + errno = err; + return MAP_FAILED; + +errout_with_errno: + kfree(alloc); + return MAP_FAILED; +} + +#endif /* CONFIG_FS_RAMMAP */ diff --git a/nuttx/fs/mmap/fs_rammap.h b/nuttx/fs/mmap/fs_rammap.h new file mode 100644 index 0000000000..9076d73432 --- /dev/null +++ b/nuttx/fs/mmap/fs_rammap.h @@ -0,0 +1,150 @@ +/**************************************************************************** + * fs/mmap/rammap.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_MMAP_RAMMAP_H +#define __FS_MMAP_RAMMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#ifdef CONFIG_FS_RAMMAP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This structure describes one file that has been copied to memory and + * managed as a share-able "memory mapped" file. This functionality is + * intended to provide a substitute for memory mapped files for architectures + * that do not have MMUs and, hence, cannot support on demand paging of + * blocks of a file. + * + * This copied file has many of the properties of a standard memory mapped + * file except: + * + * - All of the file must be present in memory. This limits the size of + * files that may be memory mapped (especially on MCUs with no significant + * RAM resources). + * - All mapped files are read-only. You can write to the in-memory image, + * but the file contents will not change. + * - There are not access privileges. + */ + +struct fs_rammap_s +{ + struct fs_rammap_s *flink; /* Implements a singly linked list */ + FAR void *addr; /* Start of allocated memory */ + size_t length; /* Length of region */ + off_t offset; /* File offset */ +}; + +/* This structure defines all "mapped" files */ + +struct fs_allmaps_s +{ + bool initialized; /* True: This structure has been initialized */ + sem_t exclsem; /* Provides exclusive access the list */ + struct fs_rammap_s *head; /* List of mapped files */ +}; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* This is the list of all mapped files */ + +extern struct fs_allmaps_s g_rammaps; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: rammap_initialize + * + * Description: + * Verified that this capability has been initialized. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +extern void rammap_initialize(void); + +/**************************************************************************** + * Name: rammmap + * + * Description: + * Support simulation of memory mapped files by copying files into RAM. + * + * Parameters: + * fd file descriptor of the backing file -- required. + * length The length of the mapping. For exception #1 above, this length + * ignored: The entire underlying media is always accessible. + * offset The offset into the file to map + * + * Returned Value: + * On success, rammmap() returns a pointer to the mapped area. On error, the + * value MAP_FAILED is returned, and errno is set appropriately. + * + * EBADF + * 'fd' is not a valid file descriptor. + * EINVAL + * 'length' or 'offset' are invalid + * ENOMEM + * Insufficient memory is available to map the file. + * + ****************************************************************************/ + +extern FAR void *rammap(int fd, size_t length, off_t offset); + +#endif /* CONFIG_FS_RAMMAP */ +#endif /* __FS_MMAP_RAMMAP_H */ diff --git a/nuttx/fs/nfs/Kconfig b/nuttx/fs/nfs/Kconfig new file mode 100644 index 0000000000..3838efffa6 --- /dev/null +++ b/nuttx/fs/nfs/Kconfig @@ -0,0 +1,24 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config NFS + bool "NFS client file system" + default n + depends on NET && !DISABLE_MOUNTPOINT + ---help--- + Enable network file system (NFS) client file system + +#if NFS + +config NFS_STATISTICS + bool "NFS Stastics" + default n + depends on NFS + ---help--- + Collect support for NFS statistics. There is no user interface to + obtain these statistics, however. So they would only be of value + if you add debug instrumentation or use a debugger. + +#endif diff --git a/nuttx/fs/nfs/Make.defs b/nuttx/fs/nfs/Make.defs new file mode 100644 index 0000000000..fc4682f855 --- /dev/null +++ b/nuttx/fs/nfs/Make.defs @@ -0,0 +1,50 @@ +############################################################################ +# Make.defs +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name Nuttx nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_NFS),y) +# Files required for NFS file system support + +ASRCS += +CSRCS += + +# Files required for NFS RPC + +ASRCS += +CSRCS += rpc_clnt.c nfs_util.c nfs_vfsops.c + +# Argument for dependency checking + +NFSDEPPATH = --dep-path nfs +endif diff --git a/nuttx/fs/nfs/nfs.h b/nuttx/fs/nfs/nfs.h new file mode 100644 index 0000000000..af24357a40 --- /dev/null +++ b/nuttx/fs/nfs/nfs.h @@ -0,0 +1,149 @@ +/**************************************************************************** + * fs/nfs/nfs.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. + * Author: Jose Pablo Rojas Vargas + * Gregory Nutt + * + * Leveraged from OpenBSD: + * + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_NFS_NFS_H +#define __FS_NFS_NFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "nfs_mount.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NFS_TICKINTVL MSEC_PER_TICK /* Smallest that we can get */ +#define NFS_TICKS 1 /* Number of system ticks */ +#define NFS_HZ CLOCKS_PER_SEC /* Ticks/sec */ +#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */ +#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */ +#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */ +#define NFS_TIMEOUTMUL 2 /* Timeout/Delay multiplier */ +#define NFS_MAXREXMIT 100 /* Stop counting after this many */ +#define NFS_RETRANS 10 /* Num of retrans for soft mounts */ +#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */ +#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */ +#define NFS_READDIRSIZE 8192 /* Def. readdir size */ +#define NFS_NPROCS 23 + +/* Ideally, NFS_DIRBLKSIZ should be bigger, but I've seen servers with + * broken NFS/ethernet drivers that won't work with anything bigger (Linux..) + */ + +#define NFS_DIRBLKSIZ 1024 /* Must be a multiple of DIRBLKSIZ */ + +/* Increment NFS statistics */ + +#ifdef CONFIG_NFS_STATISTICS +# define nfs_statistics(n) do { nfsstats.rpccnt[n]++; } while (0) +#else +# define nfs_statistics(n) +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern uint32_t nfs_true; +extern uint32_t nfs_false; +extern uint32_t nfs_xdrneg1; +#ifdef CONFIG_NFS_STATISTICS +extern struct nfsstats nfsstats; +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* NFS statistics structure */ + +struct nfsstats +{ + uint64_t rpccnt[NFS_NPROCS]; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN void nfs_semtake(FAR struct nfsmount *nmp); +EXTERN void nfs_semgive(FAR struct nfsmount *nmp); +EXTERN int nfs_checkmount(FAR struct nfsmount *nmp); +EXTERN int nfs_fsinfo(FAR struct nfsmount *nmp); +EXTERN int nfs_request(struct nfsmount *nmp, int procnum, + FAR void *request, size_t reqlen, + FAR void *response, size_t resplen); +EXTERN int nfs_lookup(FAR struct nfsmount *nmp, FAR const char *filename, + FAR struct file_handle *fhandle, + FAR struct nfs_fattr *obj_attributes, + FAR struct nfs_fattr *dir_attributes); +EXTERN int nfs_findnode(FAR struct nfsmount *nmp, FAR const char *relpath, + FAR struct file_handle *fhandle, + FAR struct nfs_fattr *obj_attributes, + FAR struct nfs_fattr *dir_attributes); +EXTERN int nfs_finddir(FAR struct nfsmount *nmp, FAR const char *relpath, + FAR struct file_handle *fhandle, + FAR struct nfs_fattr *attributes, FAR char *filename); +EXTERN void nfs_attrupdate(FAR struct nfsnode *np, + FAR struct nfs_fattr *attributes); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* _NFS_NFS_H */ diff --git a/nuttx/fs/nfs/nfs_mount.h b/nuttx/fs/nfs/nfs_mount.h new file mode 100644 index 0000000000..8f1f7be539 --- /dev/null +++ b/nuttx/fs/nfs/nfs_mount.h @@ -0,0 +1,140 @@ +/**************************************************************************** + * fs/nfs/nfs_mount.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. + * Author: Jose Pablo Rojas Vargas + * Gregory Nutt + * + * Leveraged from OpenBSD: + * + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_NFS_NFS_MOUNT_H +#define __FS_NFS_NFS_MOUNT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "rpc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Mount structure. One mount structure is allocated for each NFS mount. This + * structure holds NFS specific information for mount. + */ + +struct nfsmount +{ + struct nfsnode *nm_head; /* A list of all files opened on this mountpoint */ + sem_t nm_sem; /* Used to assure thread-safe access */ + nfsfh_t nm_fh; /* File handle of root dir */ + char nm_path[90]; /* server's path of the directory being mounted */ + struct nfs_fattr nm_fattr; /* nfs file attribute cache */ + struct rpcclnt *nm_rpcclnt; /* RPC state */ + struct socket *nm_so; /* RPC socket */ + struct sockaddr nm_nam; /* Addr of server */ + bool nm_mounted; /* true: The file system is ready */ + uint8_t nm_fhsize; /* Size of root file handle (host order) */ + uint8_t nm_sotype; /* Type of socket */ + uint8_t nm_retry; /* Max retries */ + uint16_t nm_timeo; /* Timeout value (in system clock ticks) */ + uint16_t nm_rsize; /* Max size of read RPC */ + uint16_t nm_wsize; /* Max size of write RPC */ + uint16_t nm_readdirsize; /* Size of a readdir RPC */ + uint16_t nm_buflen; /* Size of I/O buffer */ + + /* Set aside memory on the stack to hold the largest call message. NOTE + * that for the case of the write call message, it is the reply message that + * is in this union. + */ + + union + { + struct rpc_call_pmap pmap; + struct rpc_call_mount mountd; + struct rpc_call_create create; + struct rpc_call_lookup lookup; + struct rpc_call_read read; + struct rpc_call_remove removef; + struct rpc_call_rename renamef; + struct rpc_call_mkdir mkdir; + struct rpc_call_rmdir rmdir; + struct rpc_call_readdir readdir; + struct rpc_call_fs fsstat; + struct rpc_call_setattr setattr; + struct rpc_call_fs fs; + struct rpc_reply_write write; + } nm_msgbuffer; + + /* I/O buffer (must be a aligned to 32-bit boundaries). This buffer used for all + * reply messages EXCEPT for the WRITE RPC. In that case it is used for the WRITE + * call message that contains the data to be written. This buffer must be + * dynamically sized based on the characteristics of the server and upon the + * configuration of the NuttX network. It must be sized to hold the largest + * possible WRITE call message or READ response message. + */ + + uint32_t nm_iobuffer[1]; /* Actual size is given by nm_buflen */ +}; + +/* The size of the nfsmount structure will debug on the size of the allocated I/O + * buffer. + */ + +#define SIZEOF_nfsmount(n) (sizeof(struct nfsmount) + ((n + 3) & ~3) - sizeof(uint32_t)) + +/* Mount parameters structure. This structure is use in nfs_decode_args funtion before one + * mount structure is allocated in each NFS mount. + */ + +struct nfs_mount_parameters +{ + uint8_t timeo; /* Timeout value (in deciseconds) */ + uint8_t retry; /* Max retries */ + uint16_t rsize; /* Max size of read RPC */ + uint16_t wsize; /* Max size of write RPC */ + uint16_t readdirsize; /* Size of a readdir RPC */ +}; + +#endif diff --git a/nuttx/fs/nfs/nfs_node.h b/nuttx/fs/nfs/nfs_node.h new file mode 100644 index 0000000000..4ae9e162c2 --- /dev/null +++ b/nuttx/fs/nfs/nfs_node.h @@ -0,0 +1,82 @@ +/**************************************************************************** + * fs/nfs/nfs_node.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. + * Author: Jose Pablo Rojas Vargas + * Gregory Nutt + * + * Leveraged from OpenBSD: + * + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_NFS_NFS_NODE_H +#define __FS_NFS_NFS_NODE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "nfs_proto.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Flags for struct nfsnode n_flag */ + +#define NFSNODE_OPEN (1 << 0) /* File is still open */ +#define NFSNODE_MODIFIED (1 << 1) /* Might have a modified buffer */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* There is a unique nfsnode allocated for each active file. An nfsnode is + * 'named' by its file handle. + */ + +struct nfsnode +{ + struct nfsnode *n_next; /* Retained in a singly linked list. */ + uint8_t n_type; /* File type */ + uint8_t n_fhsize; /* Size in bytes of the file handle */ + uint8_t n_flags; /* Node flags */ + struct timespec n_mtime; /* File modification time (see NOTE) */ + time_t n_ctime; /* File creation time (see NOTE) */ + nfsfh_t n_fhandle; /* NFS File Handle */ + uint64_t n_size; /* Current size of file (see NOTE) */ +}; + +#endif /* __FS_NFS_NFS_NODE_H */ diff --git a/nuttx/fs/nfs/nfs_proto.h b/nuttx/fs/nfs/nfs_proto.h new file mode 100644 index 0000000000..676ee62320 --- /dev/null +++ b/nuttx/fs/nfs/nfs_proto.h @@ -0,0 +1,571 @@ +/**************************************************************************** + * fs/nfs/nfs_proto.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. + * Author: Jose Pablo Rojas Vargas + * Gregory Nutt + * + * Leveraged from OpenBSD: + * + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_NFS_NFS_PROTO_H +#define __FS_NFS_NFS_PROTO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Constants as defined in the Sun NFS Version 2 and 3 specs. + * "NFS: Network File System Protocol Specification" RFC1094 + * and in the "NFS: Network File System Version 3 Protocol + * Specification" + */ + +#define NFS_PORT 2049 +#define NFS_PROG 100003 +#define NFS_VER2 2 +#define NFS_VER3 3 +#define NFS_VER4 4 +#define NFS_MAXDGRAMDATA 32768 +#define MAXBSIZE 64000 +#define NFS_MAXDATA MAXBSIZE +#define NFS_MAXPATHLEN 1024 +#define NFS_MAXNAMLEN 255 +#define NFS_MAXPKTHDR 404 +#define NFS_MAXPACKET (NFS_MAXPKTHDR + NFS_MAXDATA) +#define NFS_MINPACKET 20 +#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */ + +/* Stat numbers for rpc returns (version 2 and 3) */ + +#define NFS_OK 0 +#define NFSERR_PERM 1 +#define NFSERR_NOENT 2 +#define NFSERR_IO 5 +#define NFSERR_NXIO 6 +#define NFSERR_ACCES 13 +#define NFSERR_EXIST 17 +#define NFSERR_XDEV 18 /* Version 3 only */ +#define NFSERR_NODEV 19 +#define NFSERR_NOTDIR 20 +#define NFSERR_ISDIR 21 +#define NFSERR_INVAL 22 /* Version 3 only */ +#define NFSERR_FBIG 27 +#define NFSERR_NOSPC 28 +#define NFSERR_ROFS 30 +#define NFSERR_MLINK 31 /* Version 3 only */ +#define NFSERR_NAMETOL 63 +#define NFSERR_NOTEMPTY 66 +#define NFSERR_DQUOT 69 +#define NFSERR_STALE 70 +#define NFSERR_REMOTE 71 /* Version 3 only */ +#define NFSERR_WFLUSH 99 /* Version 2 only */ +#define NFSERR_BADHANDLE 10001 /* The rest Version 3 only */ +#define NFSERR_NOT_SYNC 10002 +#define NFSERR_BAD_COOKIE 10003 +#define NFSERR_NOTSUPP 10004 +#define NFSERR_TOOSMALL 10005 +#define NFSERR_SERVERFAULT 10006 +#define NFSERR_BADTYPE 10007 +#define NFSERR_JUKEBOX 10008 +#define NFSERR_TRYLATER NFSERR_JUKEBOX +#define NFSERR_STALEWRITEVERF 30001 /* Fake return for nfs_commit() */ + +#define NFSERR_RETVOID 0x20000000 /* Return void, not error */ +#define NFSERR_AUTHERR 0x40000000 /* Mark an authentication error */ +#define NFSERR_RETERR 0x80000000 /* Mark an error return for V3 */ + +/* Sizes in bytes of various nfs rpc components */ + +#define NFSX_UNSIGNED 4 + +/* Specific to NFS Version 3 */ + +#define NFSX_V3FH (sizeof (fhandle_t)) /* size this server uses */ +#define NFSX_V3FHMAX 64 /* max. allowed by protocol */ +#define NFSX_V3FATTR 84 +#define NFSX_V3SATTR 60 /* max. all fields filled in */ +#define NFSX_V3SRVSATTR (sizeof (struct nfsv3_sattr)) +#define NFSX_V3POSTOPATTR (NFSX_V3FATTR + NFSX_UNSIGNED) +#define NFSX_V3WCCDATA (NFSX_V3POSTOPATTR + 8 * NFSX_UNSIGNED) +#define NFSX_V3COOKIEVERF 8 +#define NFSX_V3WRITEVERF 8 +#define NFSX_V3CREATEVERF 8 +#define NFSX_V3STATFS 52 +#define NFSX_V3FSINFO 48 +#define NFSX_V3PATHCONF 24 + +/* NFS RPC procedure numbers (before version mapping) */ + +#define NFSPROC_NULL 0 +#define NFSPROC_GETATTR 1 +#define NFSPROC_SETATTR 2 +#define NFSPROC_LOOKUP 3 +#define NFSPROC_ACCESS 4 +#define NFSPROC_READLINK 5 +#define NFSPROC_READ 6 +#define NFSPROC_WRITE 7 +#define NFSPROC_CREATE 8 +#define NFSPROC_MKDIR 9 +#define NFSPROC_SYMLINK 10 +#define NFSPROC_MKNOD 11 +#define NFSPROC_REMOVE 12 +#define NFSPROC_RMDIR 13 +#define NFSPROC_RENAME 14 +#define NFSPROC_LINK 15 +#define NFSPROC_READDIR 16 +#define NFSPROC_READDIRPLUS 17 +#define NFSPROC_FSSTAT 18 +#define NFSPROC_FSINFO 19 +#define NFSPROC_PATHCONF 20 +#define NFSPROC_COMMIT 21 +#define NFSPROC_NOOP 22 +#define NFS_NPROCS 23 + + +/* Constants used by the Version 3 protocol for various RPCs */ + +#define NFSV3SATTRTIME_DONTCHANGE 0 +#define NFSV3SATTRTIME_TOSERVER 1 +#define NFSV3SATTRTIME_TOCLIENT 2 + +#define NFSV3ACCESS_READ 0x01 +#define NFSV3ACCESS_LOOKUP 0x02 +#define NFSV3ACCESS_MODIFY 0x04 +#define NFSV3ACCESS_EXTEND 0x08 +#define NFSV3ACCESS_DELETE 0x10 +#define NFSV3ACCESS_EXECUTE 0x20 + +#define NFSV3WRITE_UNSTABLE 0 +#define NFSV3WRITE_DATASYNC 1 +#define NFSV3WRITE_FILESYNC 2 + +#define NFSV3CREATE_UNCHECKED 0 +#define NFSV3CREATE_GUARDED 1 +#define NFSV3CREATE_EXCLUSIVE 2 + +#define NFSV3FSINFO_LINK 0x01 +#define NFSV3FSINFO_SYMLINK 0x02 +#define NFSV3FSINFO_HOMOGENEOUS 0x08 +#define NFSV3FSINFO_CANSETTIME 0x10 + +/* Conversion macros */ + +#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777) +#define nfstov_mode(a) (fxdr_unsigned(u_int16_t, (a))&07777) +#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((int32_t)(a))]) +#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(uint32_t,(a))&0x7] + +/* Mode bit values */ + +#define NFSMODE_IXOTH (1 << 0) /* Execute permission for others on a file */ +#define NFSMODE_IWOTH (1 << 1) /* Write permission for others */ +#define NFSMODE_IROTH (1 << 2) /* Read permission for others */ +#define NFSMODE_IXGRP (1 << 3) /* Execute permission for group on a file */ +#define NFSMODE_IWGRP (1 << 4) /* Write permission for group */ +#define NFSMODE_IRGRP (1 << 5) /* Read permission for group */ +#define NFSMODE_IXUSR (1 << 6) /* Execute permission for owner on a file */ +#define NFSMODE_IWUSR (1 << 7) /* Write permission for owner */ +#define NFSMODE_IRUSR (1 << 8) /* Read permission for owner */ +#define NFSMODE_SAVETEXT (1 << 9) /* Save swapped text */ +#define NFSMODE_ISGID (1 << 10) /* Set group ID on execution */ +#define NFSMODE_ISUID (1 << 11) /* Set user ID on execution */ + +/* File identifier */ + +#define MAXFIDSZ 16 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* File types */ + +typedef enum +{ + NFNON = 0, /* Unknown type */ + NFREG = 1, /* Regular file */ + NFDIR = 2, /* Directory */ + NFBLK = 3, /* Block special device file */ + NFCHR = 4, /* Character special device file */ + NFLNK = 5, /* Symbolic link */ + NFSOCK = 6, /* Socket */ + NFFIFO = 7 /* Named FIFO */ +} nfstype; + +/* File Handle variable is up to 64 bytes for version 3. This structures a + * ariable sized and are provided only for setting aside maximum memory + * allocations for a file handle. + */ + +struct nfsfh +{ + uint8_t fh_bytes[NFSX_V3FHMAX]; +}; +typedef struct nfsfh nfsfh_t; +#define SIZEOF_nfsfh_t(n) (n) + +struct nfsv3_time +{ + uint32_t nfsv3_sec; + uint32_t nfsv3_nsec; +}; +typedef struct nfsv3_time nfstime3; + +/* Quads are defined as arrays of 2 longs to ensure dense packing for the + * protocol and to facilitate xdr conversion. + */ + +struct nfs_uquad +{ + uint32_t nfsuquad[2]; +}; +typedef struct nfs_uquad nfsuint64; + +/* NFS Version 3 special file number. */ + +struct nfsv3_spec +{ + uint32_t specdata1; + uint32_t specdata2; +}; +typedef struct nfsv3_spec nfsv3spec; + +/* File attributes and setable attributes. These structures cover both + * NFS version 2 and the version 3 protocol. Note that the union is only + * used so that one pointer can refer to both variants. These structures + * go out on the wire and must be densely packed, so no quad data types + * are used. (all fields are longs or u_longs or structures of same) + */ + +struct nfs_fattr +{ + uint32_t fa_type; + uint32_t fa_mode; + uint32_t fa_nlink; + uint32_t fa_uid; + uint32_t fa_gid; + nfsuint64 fa_size; + nfsuint64 fa_used; + nfsv3spec fa_rdev; + nfsuint64 fa_fsid; + nfsuint64 fa_fileid; + nfstime3 fa_atime; + nfstime3 fa_mtime; + nfstime3 fa_ctime; +}; + +/* NFS Version 3 sattr structure for the new node creation case. This is the + * maximum size of the attributes; the actual size may vary if values are not + * include. + */ + +struct nfsv3_sattr +{ + uint32_t sa_modefollows; /* TRUE: Mode value follows */ + uint32_t sa_mode; /* Mode value */ + uint32_t sa_uidfollows; /* TRUE: Uid value follows */ + uint32_t sa_uid; /* Uid value */ + uint32_t sa_gidfollows; /* TRUE: Mode value follows */ + uint32_t sa_gid; /* Mode value */ + uint32_t sa_sizefollows; /* TRUE: Size value follows */ + uint32_t sa_size; /* Size value */ + uint32_t sa_atimetype; /* Don't change, use server timer, or use client time */ + nfstime3 sa_atime; /* Client time */ + uint32_t sa_mtimetype; /* Don't change, use server timer, or use client time */ + nfstime3 sa_mtime; /* Client time */ +}; + +struct nfs_statfs +{ + struct nfs_fattr obj_attributes; + nfsuint64 sf_tbytes; + nfsuint64 sf_fbytes; + nfsuint64 sf_abytes; + nfsuint64 sf_tfiles; + nfsuint64 sf_ffiles; + nfsuint64 sf_afiles; + uint32_t sf_invarsec; +}; + +struct post_attr +{ + uint32_t obj_attributesfalse; + struct nfs_fattr attributes; +}; + +struct nfsv3_fsinfo +{ +//struct post_attr obj_attributes; + uint32_t obj_attributesfalse; + uint32_t fs_rtmax; + uint32_t fs_rtpref; + uint32_t fs_rtmult; + uint32_t fs_wtmax; + uint32_t fs_wtpref; + uint32_t fs_wtmult; + uint32_t fs_dtpref; + nfsuint64 fs_maxfilesize; + nfstime3 fs_timedelta; + uint32_t fs_properties; +}; + +/* NFS procedures args */ + +struct wcc_attr +{ + nfsuint64 size; + nfstime3 mtime; + nfstime3 ctime; +}; + +struct wcc_data +{ + uint32_t wcc_attr_follows; /* True if data follows */ + struct wcc_attr before; + uint32_t nfs_attr_follow; /* True if attributes present */ + struct nfs_fattr after; +}; + +struct file_handle +{ + uint32_t length; + nfsfh_t handle; +}; +#define SIZEOF_file_handle(n) (sizeof(uint32_t) + SIZEOF_nfsfh_t(n)) + +struct diropargs3 +{ + struct file_handle fhandle; /* Variable length */ + uint32_t length; /* Size of name[] */ + uint32_t name[(NAME_MAX+3) >> 2]; /* Variable length */ +}; + +struct CREATE3args +{ + struct diropargs3 where; + uint32_t create_mode; + struct nfsv3_sattr how; +}; + +struct CREATE3resok +{ + uint32_t handle_follows; /* True, handle follows */ + struct file_handle fhandle; /* Variable length */ + uint32_t attributes_follows; /* True, attributes follows */ + struct nfs_fattr attributes; /* File attributes */ + struct wcc_data dir_wcc; +}; + +/* The actual size of the lookup argument is variable. These structures are, therefore, + * only useful in setting aside maximum memory usage for the LOOKUP arguments. + */ + +struct LOOKUP3filename +{ + uint32_t namelen; /* Size of name[] */ + uint32_t name[(NAME_MAX+3) >> 2]; /* Variable length */ +}; + +struct LOOKUP3args +{ + struct file_handle dirhandle; /* Variable length */ + struct LOOKUP3filename name; /* Variable length */ +}; + +struct SETATTR3args +{ + struct file_handle fhandle; /* Variable length */ + struct nfsv3_sattr new_attributes; /* Variable length */ + uint32_t guard; /* Guard value */ +}; + +struct SETATTR3resok +{ + struct wcc_data wcc_data; +}; + +/* Actual size of LOOKUP3args */ + +#define SIZEOF_LOOKUP3filename(b) (sizeof(uint32_t) + (((b)+3) & ~3)) +#define SIZEOF_LOOKUP3args(a,b) (SIZEOF_file_handle(a) + SIZEOF_LOOKUP3filename(b)) + +struct LOOKUP3resok +{ + struct file_handle fhandle; + uint32_t obj_attributes_follow; + struct nfs_fattr obj_attributes; + uint32_t dir_attributes_follow; + struct nfs_fattr dir_attributes; +}; + +struct READ3args +{ + struct file_handle fhandle; /* Variable length */ + uint64_t offset; + uint32_t count; +}; + +struct nfs_rdhdr_s +{ + uint32_t attributes_follow; + struct nfs_fattr attributes; /* Will not be present if attributes_follow == 0 */ + uint32_t count; /* Number of bytes read */ + uint32_t eof; /* Non-zero if at the end of file */ + uint32_t length; /* Length of data (same as count?) */ +}; + +struct READ3resok +{ + struct nfs_rdhdr_s hdr; + uint8_t data[1]; /* Actual data size depends on count */ +}; +#define SIZEOF_READ3resok(n) (sizeof(struct nfs_rdhdr_s) + (n)) + +struct nfs_wrhdr_s +{ + struct file_handle fhandle; /* Variable length */ + uint64_t offset; + uint32_t count; + uint32_t stable; +}; + +struct WRITE3args +{ + struct nfs_wrhdr_s hdr; + uint8_t data[1]; /* Actual data size depends on count */ +}; +#define SIZEOF_WRITE3args(n) (sizeof(struct nfs_wrhdr_s) + (n)) + +struct WRITE3resok +{ + struct wcc_data file_wcc; + uint32_t count; + uint32_t committed; + uint8_t verf[NFSX_V3WRITEVERF]; +}; + +struct REMOVE3args +{ + struct diropargs3 object; +}; + +struct REMOVE3resok +{ + struct wcc_data dir_wcc; +}; + +struct RENAME3args +{ + struct diropargs3 from; + struct diropargs3 to; +}; + +struct RENAME3resok +{ + struct wcc_data fromdir_wcc; + struct wcc_data todir_wcc; +}; + +struct MKDIR3args +{ + struct diropargs3 where; + struct nfsv3_sattr how; +}; + +struct MKDIR3resok +{ + uint32_t handle_follows; /* True, handle follows */ + struct file_handle fhandle; /* Variable length */ + uint32_t attributes_follows; /* True, attributes follows */ + struct nfs_fattr attributes; /* Directory attributes */ + struct wcc_data dir_wcc; +}; + +struct RMDIR3args +{ + struct diropargs3 object; +}; + +struct RMDIR3resok +{ + struct wcc_data dir_wcc; +}; + +/* The actual size of the lookup argument is variable. This structures is, therefore, + * only useful in setting aside maximum memory usage for the LOOKUP arguments. + */ + +struct READDIR3args +{ + struct file_handle dir; /* Variable length */ + nfsuint64 cookie; + uint8_t cookieverf[NFSX_V3COOKIEVERF]; + uint32_t count; +}; + +/* The READDIR reply is variable length and consists of multiple entries, each + * of form: + * + * EOF - OR - + * + * File ID (8 bytes) + * Name length (4 bytes) + * Name string (varaiable size but in multiples of 4 bytes) + * Cookie (8 bytes) + * next entry (4 bytes) + */ + +struct READDIR3resok +{ + uint32_t attributes_follow; + struct nfs_fattr dir_attributes; + uint8_t cookieverf[NFSX_V3COOKIEVERF]; + uint32_t value_follows; + uint32_t reply[1]; /* Variable length reply begins here */ +}; + +struct FS3args +{ + struct file_handle fsroot; +}; + +#endif /* __FS_NFS_NFS_PROTO_H */ + diff --git a/nuttx/fs/nfs/nfs_util.c b/nuttx/fs/nfs/nfs_util.c new file mode 100644 index 0000000000..33c5f0a899 --- /dev/null +++ b/nuttx/fs/nfs/nfs_util.c @@ -0,0 +1,608 @@ +/**************************************************************************** + * fs/nfs/nfs_util.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "rpc.h" +#include "nfs.h" +#include "nfs_proto.h" +#include "nfs_mount.h" +#include "nfs_node.h" +#include "xdr_subs.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline int nfs_pathsegment(FAR const char **path, FAR char *buffer, + FAR char *terminator) +{ + FAR const char *src = *path; + FAR char *dest = buffer; + int nbytes = 0; + char ch; + + /* Loop until the name is successfully parsed or an error occurs */ + + for (;;) + { + /* Get the next byte from the path */ + + ch = *src++; + + /* Check if this the last byte in this segment name */ + + if (ch == '\0' || ch == '/') + { + /* This logic just suppors "//" sequences in the path name */ + + if (ch == '\0' || nbytes > 0 ) + { + /* NULL terminate the parsed path segment */ + + *dest = '\0'; + + /* Return next path and the terminating character */ + + *terminator = ch; + *path = src; + return OK; + } + + /* Just skip over any leading '/' characters */ + } + else if (nbytes >= NAME_MAX) + { + fdbg("File name segment is too long: %d\n", *path); + return EFBIG; + } + else + { + /* Save next character in the accumulated name */ + + *dest++ = ch; + nbytes++; + } + } +} +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nfs_semtake + ****************************************************************************/ + +void nfs_semtake(struct nfsmount *nmp) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&nmp->nm_sem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(*get_errno_ptr() == EINTR); + } +} + +/**************************************************************************** + * Name: nfs_semgive + ****************************************************************************/ + +void nfs_semgive(struct nfsmount *nmp) +{ + sem_post(&nmp->nm_sem); +} + +/**************************************************************************** + * Name: nfs_checkmount + * + * Desciption: Check if the mountpoint is still valid. + * + * The caller should hold the mountpoint semaphore + * + ****************************************************************************/ + +int nfs_checkmount(struct nfsmount *nmp) +{ + struct nfsnode *file; + + /* If the nm_mounted flag is false, then we have already handled the loss + * of the mount. + */ + + DEBUGASSERT(nmp); + if (!nmp->nm_mounted) + { + /* Make sure that this is flagged in every opened file */ + + for (file = nmp->nm_head; file; file = file->n_next) + { + file->n_flags &= ~NFSNODE_OPEN; + } + + return -ENODEV; + } + + return 0; +} + +/**************************************************************************** + * Name: nfs_request + * + * Desciption: + * Perform the NFS request. On successful receipt, it verifies the NFS level of the + * returned values. + * + * Return Value: + * Zero on success; a positive errno value on failure. + * + ****************************************************************************/ + +int nfs_request(struct nfsmount *nmp, int procnum, + FAR void *request, size_t reqlen, + FAR void *response, size_t resplen) +{ + struct rpcclnt *clnt = nmp->nm_rpcclnt; + struct nfs_reply_header replyh; + int trylater_delay; + int error; + +tryagain: + error = rpcclnt_request(clnt, procnum, NFS_PROG, NFS_VER3, + request, reqlen, response, resplen); + if (error != 0) + { + fdbg("ERROR: rpcclnt_request failed: %d\n", error); + return error; + } + + memcpy(&replyh, response, sizeof(struct nfs_reply_header)); + + if (replyh.nfs_status != 0) + { + if (fxdr_unsigned(uint32_t, replyh.nfs_status) > 32) + { + error = EOPNOTSUPP; + } + else + { + /* NFS_ERRORS are the same as NuttX errno values */ + + error = fxdr_unsigned(uint32_t, replyh.nfs_status); + } + + return error; + } + + if (replyh.rpc_verfi.authtype != 0) + { + error = fxdr_unsigned(int, replyh.rpc_verfi.authtype); + + if (error == EAGAIN) + { + error = 0; + trylater_delay *= NFS_TIMEOUTMUL; + if (trylater_delay > NFS_MAXTIMEO) + { + trylater_delay = NFS_MAXTIMEO; + } + + goto tryagain; + } + + fdbg("ERROR: NFS error %d from server\n", error); + return error; + } + + fvdbg("NFS_SUCCESS\n"); + return OK; +} + +/**************************************************************************** + * Name: nfs_lookup + * + * Desciption: + * Given a directory file handle, and the path to file in the directory, + * return the file handle of the path and attributes of both the file and + * the directory containing the file. + * + * NOTE: The LOOKUP call differs from other RPC messages in that the + * call message is variable length, depending upon the size of the path + * name. + * + ****************************************************************************/ + +int nfs_lookup(struct nfsmount *nmp, FAR const char *filename, + FAR struct file_handle *fhandle, + FAR struct nfs_fattr *obj_attributes, + FAR struct nfs_fattr *dir_attributes) +{ + FAR uint32_t *ptr; + uint32_t value; + int reqlen; + int namelen; + int error = 0; + + DEBUGASSERT(nmp && filename && fhandle); + + /* Get the length of the string to be sent */ + + namelen = strlen(filename); + if (namelen > NAME_MAX) + { + fdbg("Length of the string is too big: %d\n", namelen); + return E2BIG; + } + + /* Initialize the request */ + + ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.lookup.lookup; + reqlen = 0; + + /* Copy the variable length, directory file handle */ + + *ptr++ = txdr_unsigned(fhandle->length); + reqlen += sizeof(uint32_t); + + memcpy(ptr, &fhandle->handle, fhandle->length); + reqlen += fhandle->length; + ptr += uint32_increment(fhandle->length); + + /* Copy the variable-length file name */ + + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); + + memcpy(ptr, filename, namelen); + reqlen += uint32_alignup(namelen); + + /* Request LOOKUP from the server */ + + nfs_statistics(NFSPROC_LOOKUP); + error = nfs_request(nmp, NFSPROC_LOOKUP, + (FAR void *)&nmp->nm_msgbuffer.lookup, reqlen, + (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); + + if (error) + { + fdbg("ERROR: nfs_request failed: %d\n", error); + return error; + } + + /* Return the data to the caller's buffers. NOTE: Here we ignore the + * the exact layout of the rpc_reply_lookup structure. File handles + * may differ in size whereas struct rpc_reply_lookup uses a fixed size. + */ + + ptr = (FAR uint32_t *)&((FAR struct rpc_reply_lookup *)nmp->nm_iobuffer)->lookup; + + /* Get the length of the file handle */ + + value = *ptr++; + value = fxdr_unsigned(uint32_t, value); + if (value > NFSX_V3FHMAX) + { + fdbg("ERROR: Bad file handle length: %d\n", value); + return EIO; + } + + /* Return the file handle */ + + fhandle->length = value; + memcpy(&fhandle->handle, ptr, value); + ptr += uint32_increment(value); + + /* Check if there are object attributes and, if so, copy them to the user + * buffer + */ + + value = *ptr++; + if (value) + { + if (obj_attributes) + { + memcpy(obj_attributes, ptr, sizeof(struct nfs_fattr)); + } + ptr += uint32_increment(sizeof(struct nfs_fattr)); + } + + /* Check if there are directory attributes and, if so, copy them to the + * user buffer + */ + + value = *ptr++; + if (value && dir_attributes) + { + memcpy(dir_attributes, ptr, sizeof(struct nfs_fattr)); + } + + return OK; +} + +/**************************************************************************** + * Name: nfs_findnode + * + * Desciption: + * Given a path to something that may or may not be in the file system, + * return the handle of the directory entry of the requested object. + * + * Return Value: + * Zero on success; a positive errno value on failure. + * + ****************************************************************************/ + +int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath, + FAR struct file_handle *fhandle, FAR struct nfs_fattr *obj_attributes, + FAR struct nfs_fattr *dir_attributes) +{ + FAR const char *path = relpath; + char buffer[NAME_MAX+1]; + char terminator; + uint32_t tmp; + int error; + + /* Start with the file handle of the root directory. */ + + fhandle->length = nmp->nm_fhsize; + memcpy(&fhandle->handle, &nmp->nm_fh, nmp->nm_fhsize); + + /* If no path was provided, then the root directory must be exactly what + * the caller is looking for. + */ + + if (*path == '\0' || strlen(path) == 0) + { + /* Return the root directory attributes */ + + if (obj_attributes) + { + memcpy(obj_attributes, &nmp->nm_fattr, sizeof(struct nfs_fattr)); + } + + if (dir_attributes) + { + memcpy(dir_attributes, &nmp->nm_fattr, sizeof(struct nfs_fattr)); + } + + return OK; + } + + /* This is not the root directory. Loop until the directory entry corresponding + * to the path is found. + */ + + for (;;) + { + /* Extract the next path segment name. */ + + error = nfs_pathsegment(&path, buffer, &terminator); + if (error != OK) + { + /* The filename segment contains is too long. */ + + fdbg("nfs_pathsegment of \"%s\" failed after \"%s\": %d\n", + relpath, buffer, error); + return error; + } + + /* Look-up this path segment */ + + error = nfs_lookup(nmp, buffer, fhandle, obj_attributes, dir_attributes); + if (error != OK) + { + fdbg("nfs_lookup of \"%s\" failed at \"%s\": %d\n", + relpath, buffer, error); + return error; + } + + /* If the terminator character in the path was the end of the string + * then we have successfully found the directory entry that describes + * the path. + */ + + if (!terminator) + { + /* Return success meaning that the description the matching + * directory entry is in fhandle, obj_attributes, and dir_attributes. + */ + + return OK; + } + + /* No.. then we have found one of the intermediate directories on + * the way to the final path target. In this case, make sure + * the thing that we found is, indeed, a directory. + */ + + tmp = fxdr_unsigned(uint32_t, obj_attributes->fa_type); + if (tmp != NFDIR) + { + /* Ooops.. we found something else */ + + fdbg("ERROR: Intermediate segment \"%s\" of \'%s\" is not a directory\n", + buffer, path); + return ENOTDIR; + } + } +} + +/**************************************************************************** + * Name: nfs_finddir + * + * Desciption: + * Given a path to something that may or may not be in the file system, + * return the handle of the entry of the directory containing the requested +* object. + * + * Return Value: + * Zero on success; a positive errno value on failure. + * + ****************************************************************************/ + +int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath, + FAR struct file_handle *fhandle, + FAR struct nfs_fattr *attributes, FAR char *filename) +{ + FAR const char *path = relpath; + uint32_t tmp; + char terminator; + int error; + + /* Verify that a path was provided */ + + if (*path == '\0' || strlen(path) == 0) + { + /* Return the root directory attributes */ + + return ENOENT; + } + + /* Start with the file handle of the root directory. */ + + fhandle->length = nmp->nm_fhsize; + memcpy(&fhandle->handle, &nmp->nm_fh, nmp->nm_fhsize); + memcpy(attributes, &nmp->nm_fattr, sizeof(struct nfs_fattr)); + + /* Loop until the directory entry containing the path is found. */ + + for (;;) + { + /* Extract the next path segment name. */ + + error = nfs_pathsegment(&path, filename, &terminator); + if (error != OK) + { + /* The filename segment contains is too long. */ + + fdbg("nfs_pathsegment of \"%s\" failed after \"%s\": %d\n", + relpath, filename, error); + return error; + } + + /* If the terminator character in the path was the end of the string + * then we have successfully found the directory that contains the name + * of interest. + */ + + if (!terminator) + { + /* Return success meaning that the description of the directory + * containing the object is in fhandle and attributes. + */ + + return OK; + } + + /* Look-up the next path segment */ + + error = nfs_lookup(nmp, filename, fhandle, attributes, NULL); + if (error != OK) + { + fdbg("nfs_lookup of \"%s\" failed at \"%s\": %d\n", + relpath, filename, error); + return error; + } + + /* Make sure the thing that we found is, indeed, a directory. */ + + tmp = fxdr_unsigned(uint32_t, attributes->fa_type); + if (tmp != NFDIR) + { + /* Ooops.. we found something else */ + + fdbg("ERROR: Intermediate segment \"%s\" of \'%s\" is not a directory\n", + filename, path); + return ENOTDIR; + } + } +} + +/**************************************************************************** + * Name: nfs_attrupdate + * + * Desciption: + * Update file attributes on write or after the file is modified. + * + * Return Value: + * None. + * + ****************************************************************************/ + +void nfs_attrupdate(FAR struct nfsnode *np, FAR struct nfs_fattr *attributes) +{ + /* Save a few of the files attribute values in file structur (host order) */ + + np->n_type = fxdr_unsigned(uint32_t, attributes->fa_type); + np->n_size = fxdr_hyper(&attributes->fa_size); + fxdr_nfsv3time(&attributes->fa_mtime, &np->n_mtime) + np->n_ctime = fxdr_hyper(&attributes->fa_ctime); +} diff --git a/nuttx/fs/nfs/nfs_vfsops.c b/nuttx/fs/nfs/nfs_vfsops.c new file mode 100644 index 0000000000..3cd5a47dc3 --- /dev/null +++ b/nuttx/fs/nfs/nfs_vfsops.c @@ -0,0 +1,2531 @@ +/**************************************************************************** + * fs/nfs/nfs_vfsops.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. + * Author: Jose Pablo Rojas Vargas + * Gregory Nutt + * + * Leveraged from OpenBSD: + * + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#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 "nfs.h" +#include "rpc.h" +#include "nfs_proto.h" +#include "nfs_node.h" +#include "nfs_mount.h" +#include "xdr_subs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The V3 EXCLUSIVE file creation logic is not fully supported. */ + +#define USE_GUARDED_CREATE 1 + +/* include/nuttx/fs/dirent.h has its own version of these lengths. They must + * match the NFS versions. + */ + +#if NFSX_V3FHMAX != DIRENT_NFS_MAXHANDLE +# error "Length of file handle in fs_dirent_s is incorrect" +#endif + +#if NFSX_V3COOKIEVERF != DIRENT_NFS_VERFLEN +# error "Length of cookie verify in fs_dirent_s is incorrect" +#endif + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +uint32_t nfs_true; +uint32_t nfs_false; +uint32_t nfs_xdrneg1; + +#ifdef CONFIG_NFS_STATISTICS +struct nfsstats nfsstats; +#endif + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np, + FAR const char *relpath, mode_t mode); +static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np); +static int nfs_fileopen(FAR struct nfsmount *nmp, struct nfsnode *np, + FAR const char *relpath, int oflags, mode_t mode); +static int nfs_open(FAR struct file *filep, const char *relpath, + int oflags, mode_t mode); +static int nfs_close(FAR struct file *filep); +static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen); +static ssize_t nfs_write(FAR struct file *filep, const char *buffer, + size_t buflen); +static int nfs_opendir(struct inode *mountpt, const char *relpath, + struct fs_dirent_s *dir); +static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir); +static int nfs_rewinddir(FAR struct inode *mountpt, + FAR struct fs_dirent_s *dir); +static void nfs_decode_args(FAR struct nfs_mount_parameters *nprmt, + FAR struct nfs_args *argp); +static int nfs_bind(FAR struct inode *blkdriver, const void *data, + void **handle); +static int nfs_unbind(void *handle, FAR struct inode **blkdriver); +static int nfs_statfs(struct inode *mountpt, struct statfs *buf); +static int nfs_remove(struct inode *mountpt, const char *relpath); +static int nfs_mkdir(struct inode *mountpt, const char *relpath, + mode_t mode); +static int nfs_rmdir(struct inode *mountpt, const char *relpath); +static int nfs_rename(struct inode *mountpt, const char *oldrelpath, + const char *newrelpath); +static int nfs_stat(struct inode *mountpt, const char *relpath, + struct stat *buf); + +/**************************************************************************** + * Public Data + ****************************************************************************/ +/* nfs vfs operations. */ + +const struct mountpt_operations nfs_operations = +{ + nfs_open, /* open */ + nfs_close, /* close */ + nfs_read, /* read */ + nfs_write, /* write */ + NULL, /* seek */ + NULL, /* ioctl */ + NULL, /* sync */ + + nfs_opendir, /* opendir */ + NULL, /* closedir */ + nfs_readdir, /* readdir */ + nfs_rewinddir, /* rewinddir */ + + nfs_bind, /* bind */ + nfs_unbind, /* unbind */ + nfs_statfs, /* statfs */ + + nfs_remove, /* unlink */ + nfs_mkdir, /* mkdir */ + nfs_rmdir, /* rmdir */ + nfs_rename, /* rename */ + nfs_stat /* stat */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nfs_filecreate + * + * Description: + * Create a file. This is part of the file open logic that is executed if + * the user asks to create a file. + * + * Returned Value: + * 0 on success; a positive errno value on failure. + * + ****************************************************************************/ + +static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np, + FAR const char *relpath, mode_t mode) +{ + struct file_handle fhandle; + struct nfs_fattr fattr; + char filename[NAME_MAX + 1]; + FAR uint32_t *ptr; + uint32_t tmp; + int namelen; + int reqlen; + int error; + + /* Find the NFS node of the directory containing the file to be created */ + + error = nfs_finddir(nmp, relpath, &fhandle, &fattr, filename); + if (error != OK) + { + fdbg("ERROR: nfs_finddir returned: %d\n", error); + return error; + } + + /* Create the CREATE RPC call arguments */ + + ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.create.create; + reqlen = 0; + + /* Copy the variable length, directory file handle */ + + *ptr++ = txdr_unsigned(fhandle.length); + reqlen += sizeof(uint32_t); + + memcpy(ptr, &fhandle.handle, fhandle.length); + reqlen += (int)fhandle.length; + ptr += uint32_increment(fhandle.length); + + /* Copy the variable-length file name */ + + namelen = strlen(filename); + + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); + + memcpy(ptr, filename, namelen); + ptr += uint32_increment(namelen); + reqlen += uint32_alignup(namelen); + + /* Set the creation mode */ + + if ((mode & O_CREAT) != 0) + { +#ifdef USE_GUARDED_CREATE + *ptr++ = HTONL(NFSV3CREATE_GUARDED); +#else + *ptr++ = HTONL(NFSV3CREATE_EXCLUSIVE); +#endif + } + else + { + *ptr++ = HTONL(NFSV3CREATE_UNCHECKED); + } + reqlen += sizeof(uint32_t); + + /* Mode information is not provided if EXCLUSIVE creation is used. + * in this case, we must call SETATTR after successfully creating + * the file. + */ + +#ifndef USE_GUARDED_CREATE + if ((mode & O_CREAT) == 0) +#endif + { + /* Set the mode. NOTE: Here we depend on the fact that the NuttX and NFS + * bit settings are the same (at least for the bits of interest). + */ + + *ptr++ = nfs_true; /* True: mode value follows */ + reqlen += sizeof(uint32_t); + + tmp = mode & (NFSMODE_IWOTH | NFSMODE_IROTH | NFSMODE_IWGRP | + NFSMODE_IRGRP | NFSMODE_IWUSR | NFSMODE_IRUSR); + *ptr++ = txdr_unsigned(tmp); + reqlen += sizeof(uint32_t); + + /* Set the user ID to zero */ + + *ptr++ = nfs_true; /* True: Uid value follows */ + *ptr++ = 0; /* UID = 0 (nobody) */ + reqlen += 2*sizeof(uint32_t); + + /* Set the group ID to one */ + + *ptr++ = nfs_true; /* True: Gid value follows */ + *ptr++ = HTONL(1); /* GID = 1 (nogroup) */ + reqlen += 2*sizeof(uint32_t); + + /* Set the size to zero */ + + *ptr++ = nfs_true; /* True: Size value follows */ + *ptr++ = 0; /* Size = 0 */ + *ptr++ = 0; + reqlen += 3*sizeof(uint32_t); + + /* Don't change times */ + + *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change atime */ + *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */ + reqlen += 2*sizeof(uint32_t); + } + + /* Send the NFS request. Note there is special logic here to handle version 3 + * exclusive open semantics. + */ + + do + { + nfs_statistics(NFSPROC_CREATE); + error = nfs_request(nmp, NFSPROC_CREATE, + (FAR void *)&nmp->nm_msgbuffer.create, reqlen, + (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); + } +#ifdef USE_GUARDED_CREATE + while (0); +#else + while (((mode & O_CREAT) != 0) && error == EOPNOTSUPP); +#endif + + /* Check for success */ + + if (error == OK) + { + /* Parse the returned data */ + + ptr = (FAR uint32_t *)&((FAR struct rpc_reply_create *)nmp->nm_iobuffer)->create; + + /* Save the file handle in the file data structure */ + + tmp = *ptr++; /* handle_follows */ + if (!tmp) + { + fdbg("ERROR: no file handle follows\n"); + return EINVAL; + } + + tmp = *ptr++; + tmp = fxdr_unsigned(uint32_t, tmp); + DEBUGASSERT(tmp <= NFSX_V3FHMAX); + + np->n_fhsize = (uint8_t)tmp; + memcpy(&np->n_fhandle, ptr, tmp); + ptr += uint32_increment(tmp); + + /* Save the attributes in the file data structure */ + + tmp = *ptr++; /* handle_follows */ + if (!tmp) + { + fdbg("WARNING: no file attributes\n"); + } + else + { + /* Initialize the file attributes */ + + nfs_attrupdate(np, (FAR struct nfs_fattr *)ptr); + ptr += uint32_increment(sizeof(struct nfs_fattr)); + } + + /* Any following dir_wcc data is ignored for now */ + } + + return error; +} + +/**************************************************************************** + * Name: nfs_fileopen + * + * Description: + * Truncate an open file to zero length. This is part of the file open + * logic. + * + * Returned Value: + * 0 on success; a positive errno value on failure. + * + ****************************************************************************/ + +static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np) +{ + FAR uint32_t *ptr; + int reqlen; + int error; + + fvdbg("Truncating file\n"); + + /* Create the SETATTR RPC call arguments */ + + ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.setattr.setattr; + reqlen = 0; + + /* Copy the variable length, directory file handle */ + + *ptr++ = txdr_unsigned(np->n_fhsize); + reqlen += sizeof(uint32_t); + + memcpy(ptr, &np->n_fhandle, np->n_fhsize); + reqlen += (int)np->n_fhsize; + ptr += uint32_increment(np->n_fhsize); + + /* Copy the variable-length attribtes */ + + *ptr++ = nfs_false; /* Don't change mode */ + *ptr++ = nfs_false; /* Don't change uid */ + *ptr++ = nfs_false; /* Don't change gid */ + *ptr++ = nfs_true; /* Use the following size */ + *ptr++ = 0; /* Truncate to zero length */ + *ptr++ = 0; + *ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */ + *ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */ + *ptr++ = nfs_false; /* No guard value */ + reqlen += 9*sizeof(uint32_t) + + /* Perform the SETATTR RPC */ + + nfs_statistics(NFSPROC_SETATTR); + error = nfs_request(nmp, NFSPROC_SETATTR, + (FAR void *)&nmp->nm_msgbuffer.setattr, reqlen, + (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); + if (error != OK) + { + fdbg("ERROR: nfs_request failed: %d\n", error); + return error; + } + + /* Indicate that the file now has zero length */ + + np->n_size = 0; + return OK; +} + +/**************************************************************************** + * Name: nfs_fileopen + * + * Description: + * Open a file. This is part of the file open logic that attempts to open + * an existing file. + * + * Returned Value: + * 0 on success; a positive errno value on failure. + * + ****************************************************************************/ + +static int nfs_fileopen(FAR struct nfsmount *nmp, struct nfsnode *np, + FAR const char *relpath, int oflags, mode_t mode) +{ + struct file_handle fhandle; + struct nfs_fattr fattr; + uint32_t tmp; + int error = 0; + + /* Find the NFS node associate with the path */ + + error = nfs_findnode(nmp, relpath, &fhandle, &fattr, NULL); + if (error != OK) + { + fdbg("ERROR: nfs_findnode returned: %d\n", error); + return error; + } + + /* Check if the object is a directory */ + + tmp = fxdr_unsigned(uint32_t, fattr.fa_type); + if (tmp == NFDIR) + { + /* Exit with EISDIR if we attempt to open a directory */ + + fdbg("ERROR: Path is a directory\n"); + return EISDIR; + } + + /* Check if the caller has sufficient privileges to open the file */ + + if ((oflags & O_WRONLY) != 0) + { + /* Check if anyone has priveleges to write to the file -- owner, + * group, or other (we are probably "other" and may still not be + * able to write). + */ + + tmp = fxdr_unsigned(uint32_t, fattr.fa_mode); + if ((tmp & (NFSMODE_IWOTH|NFSMODE_IWGRP|NFSMODE_IWUSR)) == 0) + { + fdbg("ERROR: File is read-only: %08x\n", tmp); + return EACCES; + } + } + + /* It would be an error if we are asked to create the file exclusively */ + + if ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) + { + /* Already exists -- can't create it exclusively */ + + fdbg("ERROR: File exists\n"); + return EEXIST; + } + + /* Initialize the file private data */ + /* Copy the file handle */ + + np->n_fhsize = (uint8_t)fhandle.length; + memcpy(&np->n_fhandle, &fhandle.handle, fhandle.length); + + /* Save the file attributes */ + + nfs_attrupdate(np, &fattr); + + /* If O_TRUNC is specified and the file is opened for writing, + * then truncate the file. This operation requires that the file is + * writable, but we have already checked that. O_TRUNC without write + * access is ignored. + */ + + if ((oflags & (O_TRUNC|O_WRONLY)) == (O_TRUNC|O_WRONLY)) + { + /* Truncate the file to zero length. I think we can do this with + * the SETATTR call by setting the length to zero. + */ + + return nfs_filetruncate(nmp, np); + } + + return OK; +} + +/**************************************************************************** + * Name: nfs_open + * + * Description: + * If oflags == O_CREAT it creates a file, if not it check to see if the + * type is ok and that deletion is not in progress. + * + * Returned Value: + * 0 on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nfs_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode) +{ + struct nfsmount *nmp; + struct nfsnode *np = NULL; + int error; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_inode != NULL); + + /* Get the mountpoint inode reference from the file structure and the + * mountpoint private data from the inode structure + */ + + nmp = (struct nfsmount*)filep->f_inode->i_private; + DEBUGASSERT(nmp != NULL); + + /* Pre-allocate the file private data to describe the opened file. */ + + np = (struct nfsnode *)kzalloc(sizeof(struct nfsnode)); + if (!np) + { + fdbg("ERROR: Failed to allocate private data\n"); + return -ENOMEM; + } + + /* Check if the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + fdbg("ERROR: nfs_checkmount failed: %d\n", error); + goto errout_with_semaphore; + } + + /* Try to open an existing file at that path */ + + error = nfs_fileopen(nmp, np, relpath, oflags, mode); + if (error != OK) + { + /* An error occurred while trying to open the existing file. Check if + * the open failed because the file does not exist. That is not + * necessarily an error; that may only mean that we have to create the + * file. + */ + + if (error != ENOENT) + { + fdbg("ERROR: nfs_findnode failed: %d\n", error); + goto errout_with_semaphore; + } + + /* The file does not exist. Check if we were asked to create the file. If + * the O_CREAT bit is set in the oflags then we should create the file if it + * does not exist. + */ + + if ((oflags & O_CREAT) == 0) + { + /* Return ENOENT if the file does not exist and we were not asked + * to create it. + */ + + fdbg("ERROR: File does not exist\n"); + error = ENOENT; + goto errout_with_semaphore; + } + + /* Create the file */ + + error = nfs_filecreate(nmp, np, relpath, mode); + if (error != OK) + { + fdbg("ERROR: nfs_filecreate failed: %d\n", error); + goto errout_with_semaphore; + } + } + + /* Initialize the file private data (only need to initialize + * non-zero elements) + */ + + /* Attach the private data to the struct file instance */ + + filep->f_priv = np; + + /* Then insert the new instance at the head of the list in the mountpoint + * tructure. It needs to be there (1) to handle error conditions that effect + * all files, and (2) to inform the umount logic that we are busy. We + * cannot unmount the file system if this list is not empty! + */ + + np->n_next = nmp->nm_head; + nmp->nm_head = np; + + np->n_flags |= (NFSNODE_OPEN | NFSNODE_MODIFIED); + nfs_semgive(nmp); + return OK; + +errout_with_semaphore: + if (np) + { + kfree(np); + } + nfs_semgive(nmp); + return -error; +} + +/**************************************************************************** + * Name: nfs_close + * + * Description: + * Close a file. + * + * Returned Value: + * 0 on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nfs_close(FAR struct file *filep) +{ + FAR struct nfsmount *nmp; + FAR struct nfsnode *np; + FAR struct nfsnode *prev; + FAR struct nfsnode *curr; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + nmp = (struct nfsmount*) filep->f_inode->i_private; + np = (struct nfsnode*) filep->f_priv; + + DEBUGASSERT(nmp != NULL); + + /* Get exclusive access to the mount structure. */ + + nfs_semtake(nmp); + + /* Find our file structure in the list of file structures containted in the + * mount structure. + */ + + for (prev = NULL, curr = nmp->nm_head; curr; prev = curr, curr = curr->n_next) + { + /* Check if this node is ours */ + + if (np == curr) + { + /* Yes.. remove it from the list of file structures */ + + if (prev) + { + /* Remove from mid-list */ + + prev->n_next = np->n_next; + } + else + { + /* Remove from the head of the list */ + + nmp->nm_head = np->n_next; + } + + /* Then deallocate the file structure and return success */ + + kfree(np); + nfs_semgive(nmp); + return OK; + } + } + + fdbg("ERROR: file structure not found in list: %p\n", np); + nfs_semgive(nmp); + return EINVAL; +} + +/**************************************************************************** + * Name: nfs_read + * + * Returned Value: + * The (non-negative) number of bytes read on success; a negated errno + * value on failure. + * + ****************************************************************************/ + +static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen) +{ + FAR struct nfsmount *nmp; + FAR struct nfsnode *np; + ssize_t readsize; + ssize_t tmp; + ssize_t bytesread; + size_t reqlen; + FAR uint32_t *ptr; + int error = 0; + + fvdbg("Read %d bytes from offset %d\n", buflen, filep->f_pos); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + nmp = (struct nfsmount*) filep->f_inode->i_private; + np = (struct nfsnode*) filep->f_priv; + + DEBUGASSERT(nmp != NULL); + + /* Make sure that the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + fdbg("nfs_checkmount failed: %d\n", error); + goto errout_with_semaphore; + } + + /* Get the number of bytes left in the file and truncate read count so that + * it does not exceed the number of bytes left in the file. + */ + + tmp = np->n_size - filep->f_pos; + if (buflen > tmp) + { + buflen = tmp; + fvdbg("Read size truncated to %d\n", buflen); + } + + /* Now loop until we fill the user buffer (or hit the end of the file) */ + + for (bytesread = 0; bytesread < buflen; ) + { + /* Make sure that the attempted read size does not exceed the RPC maximum */ + + readsize = buflen; + if (readsize > nmp->nm_rsize) + { + readsize = nmp->nm_rsize; + } + + /* Make sure that the attempted read size does not exceed the IO buffer size */ + + tmp = SIZEOF_rpc_reply_read(readsize); + if (tmp > nmp->nm_buflen) + { + readsize -= (tmp - nmp->nm_buflen); + } + + /* Initialize the request */ + + ptr = (FAR uint32_t*)&nmp->nm_msgbuffer.read.read; + reqlen = 0; + + /* Copy the variable length, file handle */ + + *ptr++ = txdr_unsigned((uint32_t)np->n_fhsize); + reqlen += sizeof(uint32_t); + + memcpy(ptr, &np->n_fhandle, np->n_fhsize); + reqlen += (int)np->n_fhsize; + ptr += uint32_increment((int)np->n_fhsize); + + /* Copy the file offset */ + + txdr_hyper((uint64_t)filep->f_pos, ptr); + ptr += 2; + reqlen += 2*sizeof(uint32_t); + + /* Set the readsize */ + + *ptr = txdr_unsigned(readsize); + reqlen += sizeof(uint32_t); + + /* Perform the read */ + + fvdbg("Reading %d bytes\n", readsize); + nfs_statistics(NFSPROC_READ); + error = nfs_request(nmp, NFSPROC_READ, + (FAR void *)&nmp->nm_msgbuffer.read, reqlen, + (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); + if (error) + { + fdbg("ERROR: nfs_request failed: %d\n", error); + goto errout_with_semaphore; + } + + /* The read was successful. Get a pointer to the beginning of the NFS + * response data. + */ + + ptr = (FAR uint32_t *)&((FAR struct rpc_reply_read *)nmp->nm_iobuffer)->read; + + /* Check if attributes are included in the responses */ + + tmp = *ptr++; + if (*ptr != 0) + { + /* Yes... just skip over the attributes for now */ + + ptr += uint32_increment(sizeof(struct nfs_fattr)); + } + + /* This is followed by the count of data read. Isn't this + * the same as the length that is included in the read data? + * + * Just skip over if for now. + */ + + ptr++; + + /* Next comes an EOF indication. Save that in tmp for now. */ + + tmp = *ptr++; + + /* Then the length of the read data followed by the read data itself */ + + readsize = fxdr_unsigned(uint32_t, *ptr); + ptr++; + + /* Copy the read data into the user buffer */ + + memcpy(buffer, ptr, readsize); + + /* Update the read state data */ + + filep->f_pos += readsize; + bytesread += readsize; + buffer += readsize; + + /* Check if we hit the end of file */ + + if (tmp != 0) + { + break; + } + } + + fvdbg("Read %d bytes\n", bytesread); + nfs_semgive(nmp); + return bytesread; + +errout_with_semaphore: + nfs_semgive(nmp); + return -error; +} + +/**************************************************************************** + * Name: nfs_write + * + * Returned Value: + * The (non-negative) number of bytes written on success; a negated errno + * value on failure. + * + ****************************************************************************/ + +static ssize_t nfs_write(FAR struct file *filep, const char *buffer, + size_t buflen) +{ + struct nfsmount *nmp; + struct nfsnode *np; + ssize_t writesize; + ssize_t bufsize; + ssize_t byteswritten; + size_t reqlen; + FAR uint32_t *ptr; + uint32_t tmp; + int commit = 0; + int committed = NFSV3WRITE_FILESYNC; + int error; + + fvdbg("Write %d bytes to offset %d\n", buflen, filep->f_pos); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + nmp = (struct nfsmount*)filep->f_inode->i_private; + np = (struct nfsnode*)filep->f_priv; + + DEBUGASSERT(nmp != NULL); + + /* Make sure that the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + fdbg("nfs_checkmount failed: %d\n", error); + goto errout_with_semaphore; + } + + /* Check if the file size would exceed the range of off_t */ + + if (np->n_size + buflen < np->n_size) + { + error = EFBIG; + goto errout_with_semaphore; + } + + /* Now loop until we send the entire user buffer */ + + writesize = 0; + for (byteswritten = 0; byteswritten < buflen; ) + { + /* Make sure that the attempted write size does not exceed the RPC maximum */ + + writesize = buflen; + if (writesize > nmp->nm_wsize) + { + writesize = nmp->nm_wsize; + } + + /* Make sure that the attempted read size does not exceed the IO buffer size */ + + bufsize = SIZEOF_rpc_call_write(writesize); + if (bufsize > nmp->nm_buflen) + { + writesize -= (bufsize - nmp->nm_buflen); + } + + /* Initialize the request. Here we need an offset pointer to the write + * arguments, skipping over the RPC header. Write is unique among the + * RPC calls in that the entry RPC calls messasge lies in the I/O buffer + */ + + ptr = (FAR uint32_t *)&((FAR struct rpc_call_write *)nmp->nm_iobuffer)->write; + reqlen = 0; + + /* Copy the variable length, file handle */ + + *ptr++ = txdr_unsigned((uint32_t)np->n_fhsize); + reqlen += sizeof(uint32_t); + + memcpy(ptr, &np->n_fhandle, np->n_fhsize); + reqlen += (int)np->n_fhsize; + ptr += uint32_increment((int)np->n_fhsize); + + /* Copy the file offset */ + + txdr_hyper((uint64_t)filep->f_pos, ptr); + ptr += 2; + reqlen += 2*sizeof(uint32_t); + + /* Copy the count and stable values */ + + *ptr++ = txdr_unsigned(buflen); + *ptr++ = txdr_unsigned(committed); + reqlen += 2*sizeof(uint32_t); + + /* Copy a chunk of the user data into the I/O buffer */ + + *ptr++ = txdr_unsigned(buflen); + reqlen += sizeof(uint32_t); + memcpy(ptr, buffer, writesize); + reqlen += uint32_alignup(writesize); + + /* Perform the write */ + + nfs_statistics(NFSPROC_WRITE); + error = nfs_request(nmp, NFSPROC_WRITE, + (FAR void *)nmp->nm_iobuffer, reqlen, + (FAR void *)&nmp->nm_msgbuffer.write, sizeof(struct rpc_reply_write)); + if (error) + { + fdbg("ERROR: nfs_request failed: %d\n", error); + goto errout_with_semaphore; + } + + /* Get a pointer to the WRITE reply data */ + + ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.write.write; + + /* Parse file_wcc. First, check if WCC attributes follow. */ + + tmp = *ptr++; + if (tmp != 0) + { + /* Yes.. WCC attributes follow. But we just skip over them. */ + + ptr += uint32_increment(sizeof(struct wcc_attr)); + } + + /* Check if normal file attributes follow */ + + tmp = *ptr++; + if (tmp != 0) + { + /* Yes.. Update the cached file status in the file structure. */ + + nfs_attrupdate(np, (FAR struct nfs_fattr *)ptr); + ptr += uint32_increment(sizeof(struct nfs_fattr)); + } + + /* Get the count of bytes actually written */ + + tmp = fxdr_unsigned(uint32_t, *ptr); + ptr++; + + if (tmp < 1 || tmp > writesize) + { + error = EIO; + goto errout_with_semaphore; + } + + writesize = tmp; + + /* Determine the lowest committment level obtained by any of the RPCs. */ + + commit = *ptr++; + if (committed == NFSV3WRITE_FILESYNC) + { + committed = commit; + } + else if (committed == NFSV3WRITE_DATASYNC && + commit == NFSV3WRITE_UNSTABLE) + { + committed = commit; + } + + /* Update the read state data */ + + filep->f_pos += writesize; + byteswritten += writesize; + buffer += writesize; + } + + nfs_semgive(nmp); + return writesize; + +errout_with_semaphore: + nfs_semgive(nmp); + return -error; +} + +/**************************************************************************** + * Name: nfs_opendir + * + * Description: + * Open a directory for read access + * + * Returned Value: + * 0 on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nfs_opendir(struct inode *mountpt, const char *relpath, + struct fs_dirent_s *dir) +{ + struct nfsmount *nmp; + struct file_handle fhandle; + struct nfs_fattr obj_attributes; + uint32_t objtype; + int error; + + fvdbg("relpath: \"%s\"\n", relpath ? relpath : "NULL"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL && dir); + + /* Recover our private data from the inode instance */ + + nmp = mountpt->i_private; + + /* Initialize the NFS-specific portions of dirent structure to zero */ + + memset(&dir->u.nfs, 0, sizeof(struct nfsdir_s)); + + /* Make sure that the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + fdbg("ERROR: nfs_checkmount failed: %d\n", error); + goto errout_with_semaphore; + } + + /* Find the NFS node associate with the path */ + + error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, NULL); + if (error != OK) + { + fdbg("ERROR: nfs_findnode failed: %d\n", error); + goto errout_with_semaphore; + } + + /* The entry is a directory */ + + objtype = fxdr_unsigned(uint32_t, obj_attributes.fa_type); + if (objtype != NFDIR) + { + fdbg("ERROR: Not a directory, type=%d\n", objtype); + error = ENOTDIR; + goto errout_with_semaphore; + } + + /* Save the directory information in struct fs_dirent_s so that it can be + * used later when readdir() is called. + */ + + dir->u.nfs.nfs_fhsize = (uint8_t)fhandle.length; + DEBUGASSERT(fhandle.length <= DIRENT_NFS_MAXHANDLE); + + memcpy(dir->u.nfs.nfs_fhandle, &fhandle.handle, DIRENT_NFS_MAXHANDLE); + error = OK; + +errout_with_semaphore: + nfs_semgive(nmp); + return -error; +} + +/**************************************************************************** + * Name: nfs_readdir + * + * Description: Read from directory + * + * Returned Value: + * 0 on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) +{ + struct nfsmount *nmp; + struct file_handle fhandle; + struct nfs_fattr obj_attributes; + uint32_t tmp; + uint32_t *ptr; + uint8_t *name; + unsigned int length; + int reqlen; + int error = 0; + + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover our private data from the inode instance */ + + nmp = mountpt->i_private; + + /* Make sure that the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + fdbg("ERROR: nfs_checkmount failed: %d\n", error); + goto errout_with_semaphore; + } + + /* Request a block directory entries, copying directory information from + * the dirent structure. + */ + + ptr = (FAR uint32_t*)&nmp->nm_msgbuffer.readdir.readdir; + reqlen = 0; + + /* Copy the variable length, directory file handle */ + + *ptr++ = txdr_unsigned((uint32_t)dir->u.nfs.nfs_fhsize); + reqlen += sizeof(uint32_t); + + memcpy(ptr, dir->u.nfs.nfs_fhandle, dir->u.nfs.nfs_fhsize); + reqlen += (int)dir->u.nfs.nfs_fhsize; + ptr += uint32_increment((int)dir->u.nfs.nfs_fhsize); + + /* Cookie and cookie verifier */ + + ptr[0] = dir->u.nfs.nfs_cookie[0]; + ptr[1] = dir->u.nfs.nfs_cookie[1]; + ptr += 2; + reqlen += 2*sizeof(uint32_t); + + memcpy(ptr, dir->u.nfs.nfs_verifier, DIRENT_NFS_VERFLEN); + ptr += uint32_increment(DIRENT_NFS_VERFLEN); + reqlen += DIRENT_NFS_VERFLEN; + + /* Number of directory entries (We currently only process one entry at a time) */ + + *ptr = txdr_unsigned(nmp->nm_readdirsize); + reqlen += sizeof(uint32_t); + + /* And read the directory */ + + nfs_statistics(NFSPROC_READDIR); + error = nfs_request(nmp, NFSPROC_READDIR, + (FAR void *)&nmp->nm_msgbuffer.readdir, reqlen, + (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); + if (error != OK) + { + fdbg("ERROR: nfs_request failed: %d\n", error); + goto errout_with_semaphore; + } + + /* A new group of entries was successfully read. Process the + * information contained in the response header. This information + * includes: + * + * 1) Attributes follow indication - 4 bytes + * 2) Directory attributes - sizeof(struct nfs_fattr) + * 3) Cookie verifier - NFSX_V3COOKIEVERF bytes + * 4) Values follows indication - 4 bytes + */ + + ptr = (uint32_t *)&((FAR struct rpc_reply_readdir *)nmp->nm_iobuffer)->readdir; + + /* Check if attributes follow, if 0 so Skip over the attributes */ + + tmp = *ptr++; + if (tmp != 0) + { + /* Attributes are not currently used */ + + ptr += uint32_increment(sizeof(struct nfs_fattr)); + } + + /* Save the verification cookie */ + + memcpy(dir->u.nfs.nfs_verifier, ptr, DIRENT_NFS_VERFLEN); + ptr += uint32_increment(DIRENT_NFS_VERFLEN); + + /* Check if values follow. If no values follow, then the EOF indication + * will appear next. + */ + + tmp = *ptr++; + if (tmp == 0) + { + /* No values follow, then the reply should consist only of a 4-byte + * end-of-directory indication. + */ + + tmp = *ptr++; + if (tmp != 0) + { + fvdbg("End of directory\n"); + error = ENOENT; + } + + /* What would it mean if there were not data and we not at the end of + * file? + */ + + else + { + fvdbg("No data but not end of directory???\n"); + error = EAGAIN; + } + + goto errout_with_semaphore; + } + + /* If we are not at the end of the directory listing, then a set of entries + * will follow the header. Each entry is of the form: + * + * File ID (8 bytes) + * Name length (4 bytes) + * Name string (varaiable size but in multiples of 4 bytes) + * Cookie (8 bytes) + * next entry (4 bytes) + */ + + /* There is an entry. Skip over the file ID and point to the length */ + + ptr += 2; + + /* Get the length and point to the name */ + + tmp = *ptr++; + length = fxdr_unsigned(uint32_t, tmp); + name = (uint8_t*)ptr; + + /* Increment the pointer past the name (allowing for padding). ptr + * now points to the cookie. + */ + + ptr += uint32_increment(length); + + /* Save the cookie and increment the pointer to the next entry */ + + dir->u.nfs.nfs_cookie[0] = *ptr++; + dir->u.nfs.nfs_cookie[1] = *ptr++; + + ptr++; /* Just skip over the nextentry for now */ + + /* Return the name of the node to the caller */ + + if (length > NAME_MAX) + { + length = NAME_MAX; + } + + memcpy(dir->fd_dir.d_name, name, length); + dir->fd_dir.d_name[length] = '\0'; + fvdbg("name: \"%s\"\n", dir->fd_dir.d_name); + + /* Get the file attributes associated with this name and return + * the file type. + */ + + fhandle.length = (uint32_t)dir->u.nfs.nfs_fhsize; + memcpy(&fhandle.handle, dir->u.nfs.nfs_fhandle, DIRENT_NFS_MAXHANDLE); + + error = nfs_lookup(nmp, dir->fd_dir.d_name, &fhandle, &obj_attributes, NULL); + if (error != OK) + { + fdbg("nfs_lookup failed: %d\n", error); + goto errout_with_semaphore; + } + + /* Set the dirent file type */ + + tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_type); + switch (tmp) + { + default: + case NFNON: /* Unknown type */ + case NFSOCK: /* Socket */ + case NFLNK: /* Symbolic link */ + break; + + case NFREG: /* Regular file */ + dir->fd_dir.d_type = DTYPE_FILE; + break; + + case NFDIR: /* Directory */ + dir->fd_dir.d_type = DTYPE_DIRECTORY; + break; + + case NFBLK: /* Block special device file */ + dir->fd_dir.d_type = DTYPE_BLK; + break; + + case NFFIFO: /* Named FIFO */ + case NFCHR: /* Character special device file */ + dir->fd_dir.d_type = DTYPE_CHR; + break; + } + fvdbg("type: %d->%d\n", (int)tmp, dir->fd_dir.d_type); + +errout_with_semaphore: + nfs_semgive(nmp); + return -error; +} + +/**************************************************************************** + * Name: nfs_rewinddir + * + * Description: + * Reset the directory traveral logic to the first entry in the open + * directory. + * + * Returned Value: + * 0 on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nfs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir) +{ + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && dir != NULL); + + /* Reset the NFS-specific portions of dirent structure, retaining only the + * file handle. + */ + + memset(&dir->u.nfs.nfs_verifier, 0, DIRENT_NFS_VERFLEN); + dir->u.nfs.nfs_cookie[0] = 0; + dir->u.nfs.nfs_cookie[1] = 0; + return OK; +} + +/**************************************************************************** + * Name: nfs_decode_args + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void nfs_decode_args(FAR struct nfs_mount_parameters *nprmt, + FAR struct nfs_args *argp) +{ + int maxio; + + /* Get the selected timeout value */ + + if ((argp->flags & NFSMNT_TIMEO) != 0 && argp->timeo > 0) + { + uint32_t tmp = ((uint32_t)argp->timeo * NFS_HZ + 5) / 10; + if (tmp < NFS_MINTIMEO) + { + tmp = NFS_MINTIMEO; + } + else if (tmp > NFS_MAXTIMEO) + { + tmp = NFS_MAXTIMEO; + } + nprmt->timeo = tmp; + } + + /* Get the selected retransmission count */ + + if ((argp->flags & NFSMNT_RETRANS) != 0 && argp->retrans > 1) + { + if (argp->retrans < NFS_MAXREXMIT) + { + nprmt->retry = argp->retrans; + } + else + { + nprmt->retry = NFS_MAXREXMIT; + } + } + + if ((argp->flags & NFSMNT_SOFT) == 0) + { + nprmt->retry = NFS_MAXREXMIT + 1; /* Past clip limit */ + } + + /* Get the maximum amount of data that can be transferred in one packet */ + + if ((argp->sotype == SOCK_DGRAM) != 0) + { + maxio = NFS_MAXDGRAMDATA; + } + else + { + fdbg("ERROR: Only SOCK_DRAM is supported\n"); + maxio = NFS_MAXDATA; + } + + /* Get the maximum amount of data that can be transferred in one write transfer */ + + if ((argp->flags & NFSMNT_WSIZE) != 0 && argp->wsize > 0) + { + nprmt->wsize = argp->wsize; + + /* Round down to multiple of blocksize */ + + nprmt->wsize &= ~(NFS_FABLKSIZE - 1); + if (nprmt->wsize <= 0) + { + nprmt->wsize = NFS_FABLKSIZE; + } + } + + if (nprmt->wsize > maxio) + { + nprmt->wsize = maxio; + } + + if (nprmt->wsize > MAXBSIZE) + { + nprmt->wsize = MAXBSIZE; + } + + /* Get the maximum amount of data that can be transferred in one read transfer */ + + if ((argp->flags & NFSMNT_RSIZE) != 0 && argp->rsize > 0) + { + nprmt->rsize = argp->rsize; + + /* Round down to multiple of blocksize */ + + nprmt->rsize &= ~(NFS_FABLKSIZE - 1); + if (nprmt->rsize <= 0) + { + nprmt->rsize = NFS_FABLKSIZE; + } + } + + if (nprmt->rsize > maxio) + { + nprmt->rsize = maxio; + } + + if (nprmt->rsize > MAXBSIZE) + { + nprmt->rsize = MAXBSIZE; + } + + /* Get the maximum amount of data that can be transferred in directory transfer */ + + if ((argp->flags & NFSMNT_READDIRSIZE) != 0 && argp->readdirsize > 0) + { + nprmt->readdirsize = argp->readdirsize; + + /* Round down to multiple of blocksize */ + + nprmt->readdirsize &= ~(NFS_DIRBLKSIZ - 1); + if (nprmt->readdirsize < NFS_DIRBLKSIZ) + { + nprmt->readdirsize = NFS_DIRBLKSIZ; + } + } + else if (argp->flags & NFSMNT_RSIZE) + { + nprmt->readdirsize = nprmt->rsize; + } + + if (nprmt->readdirsize > maxio) + { + nprmt->readdirsize = maxio; + } +} + +/**************************************************************************** + * Name: nfs_bind + * + * Description: + * This implements a portion of the mount operation. This function allocates + * and initializes the mountpoint private data and gets mount information + * from the NFS server. The final binding of the private data (containing + * NFS server mount information) to the mountpoint is performed by mount(). + * + * Returned Value: + * 0 on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data, + FAR void **handle) +{ + FAR struct nfs_args *argp = (FAR struct nfs_args *)data; + FAR struct nfsmount *nmp; + struct rpcclnt *rpc; + struct rpc_call_fs getattr; + struct rpc_reply_getattr resok; + struct nfs_mount_parameters nprmt; + uint32_t buflen; + uint32_t tmp; + int error = 0; + + DEBUGASSERT(data && handle); + + /* Set default values of the parameters. These may be overridden by + * settings in the argp->flags. + */ + + nprmt.timeo = NFS_TIMEO; + nprmt.retry = NFS_RETRANS; + nprmt.wsize = NFS_WSIZE; + nprmt.rsize = NFS_RSIZE; + nprmt.readdirsize = NFS_READDIRSIZE; + + nfs_decode_args(&nprmt, argp); + + /* Determine the size of a buffer that will hold one RPC data transfer. + * First, get the maximum size of a read and a write transfer */ + + buflen = SIZEOF_rpc_call_write(nprmt.wsize); + tmp = SIZEOF_rpc_reply_read(nprmt.rsize); + + /* The buffer size will be the maximum of those two sizes */ + + if (tmp > buflen) + { + buflen = tmp; + } + + /* But don't let the buffer size exceed the MSS of the socket type */ + + if (buflen > UIP_UDP_MSS) + { + buflen = UIP_UDP_MSS; + } + + /* Create an instance of the mountpt state structure */ + + nmp = (FAR struct nfsmount *)kzalloc(SIZEOF_nfsmount(buflen)); + if (!nmp) + { + fdbg("ERROR: Failed to allocate mountpoint structure\n"); + return ENOMEM; + } + + /* Save the allocated I/O buffer size */ + + nmp->nm_buflen = (uint16_t)buflen; + + /* Initialize the allocated mountpt state structure. */ + + /* Initialize the semaphore that controls access. The initial count + * is zero, but nfs_semgive() is called at the completion of initialization, + * incrementing the count to one. + */ + + sem_init(&nmp->nm_sem, 0, 0); /* Initialize the semaphore that controls access */ + + /* Initialize NFS */ + + nfs_true = txdr_unsigned(TRUE); + nfs_false = txdr_unsigned(FALSE); + nfs_xdrneg1 = txdr_unsigned(-1); + + rpcclnt_init(); + + /* Set initial values of other fields */ + + nmp->nm_timeo = nprmt.timeo; + nmp->nm_retry = nprmt.retry; + nmp->nm_wsize = nprmt.wsize; + nmp->nm_rsize = nprmt.rsize; + nmp->nm_readdirsize = nprmt.readdirsize; + nmp->nm_fhsize = NFSX_V3FHMAX; + + strncpy(nmp->nm_path, argp->path, 90); + memcpy(&nmp->nm_nam, &argp->addr, argp->addrlen); + + /* Set up the sockets and per-host congestion */ + + nmp->nm_sotype = argp->sotype; + + if (nmp->nm_sotype == SOCK_DGRAM) + { + /* Connection-less... connect now */ + + /* Create an instance of the rpc state structure */ + + rpc = (struct rpcclnt *)kzalloc(sizeof(struct rpcclnt)); + if (!rpc) + { + fdbg("ERROR: Failed to allocate rpc structure\n"); + return ENOMEM; + } + + fvdbg("Connecting\n"); + + /* Translate nfsmnt flags -> rpcclnt flags */ + + rpc->rc_path = nmp->nm_path; + rpc->rc_name = &nmp->nm_nam; + rpc->rc_sotype = nmp->nm_sotype; + rpc->rc_retry = nmp->nm_retry; + + nmp->nm_rpcclnt = rpc; + + error = rpcclnt_connect(nmp->nm_rpcclnt); + if (error != OK) + { + fdbg("ERROR: nfs_connect failed: %d\n", error); + goto bad; + } + } + + nmp->nm_mounted = true; + nmp->nm_so = nmp->nm_rpcclnt->rc_so; + memcpy(&nmp->nm_fh, &nmp->nm_rpcclnt->rc_fh, sizeof(nfsfh_t)); + + /* Get the file attributes */ + + getattr.fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize); + memcpy(&getattr.fs.fsroot.handle, &nmp->nm_fh, sizeof(nfsfh_t)); + + error = nfs_request(nmp, NFSPROC_GETATTR, + (FAR void *)&getattr, sizeof(struct FS3args), + (FAR void*)&resok, sizeof(struct rpc_reply_getattr)); + if (error) + { + fdbg("ERROR: nfs_request failed: %d\n", error); + goto bad; + } + + /* Save the file attributes */ + + memcpy(&nmp->nm_fattr, &resok.attr, sizeof(struct nfs_fattr)); + + /* Mounted! */ + + *handle = (void*)nmp; + nfs_semgive(nmp); + + fvdbg("Successfully mounted\n"); + return OK; + +bad: + if (nmp) + { + /* Disconnect from the server */ + + rpcclnt_disconnect(nmp->nm_rpcclnt); + + /* Free connection-related resources */ + + sem_destroy(&nmp->nm_sem); + if (nmp->nm_so) + { + kfree(nmp->nm_so); + } + if (nmp->nm_rpcclnt) + { + kfree(nmp->nm_rpcclnt); + } + kfree(nmp); + } + return error; +} + +/**************************************************************************** + * Name: nfs_unbind + * + * Description: This implements the filesystem portion of the umount + * operation. + * + * Returned Value: + * 0 on success; a negated errno value on failure. + * + ****************************************************************************/ + +int nfs_unbind(FAR void *handle, FAR struct inode **blkdriver) +{ + FAR struct nfsmount *nmp = (FAR struct nfsmount *)handle; + int error; + + fvdbg("Entry\n"); + DEBUGASSERT(nmp); + + /* Get exclusive access to the mount structure */ + + nfs_semtake(nmp); + + /* Are there any open files? We can tell if there are open files by looking + * at the list of file structures in the mount structure. If this list + * not empty, then there are open files and we cannot unmount now (or a + * crash is sure to follow). + */ + + if (nmp->nm_head != NULL) + { + fdbg("ERROR; There are open files: %p\n", nmp->nm_head); + error = EBUSY; + goto errout_with_semaphore; + } + + /* No open file... Umount the file system. */ + + error = rpcclnt_umount(nmp->nm_rpcclnt); + if (error) + { + fdbg("ERROR: rpcclnt_umount failed: %d\n", error); + } + + /* Disconnect from the server */ + + rpcclnt_disconnect(nmp->nm_rpcclnt); + + /* And free any allocated resources */ + + sem_destroy(&nmp->nm_sem); + kfree(nmp->nm_so); + kfree(nmp->nm_rpcclnt); + kfree(nmp); + + return -error; + +errout_with_semaphore: + nfs_semgive(nmp); + return -error; +} + +/**************************************************************************** + * Name: nfs_fsinfo + * + * Description: + * Return information about root directory. + * + * Returned Value: + * 0 on success; positive errno value on failure + * + * Assumptions: + * The caller has exclusive access to the NFS mount structure + * + ****************************************************************************/ + +int nfs_fsinfo(FAR struct nfsmount *nmp) +{ + struct rpc_call_fs fsinfo; + struct rpc_reply_fsinfo fsp; + uint32_t pref; + uint32_t max; + int error = 0; + + fsinfo.fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize); + fsinfo.fs.fsroot.handle = nmp->nm_fh; + + /* Request FSINFO from the server */ + + nfs_statistics(NFSPROC_FSINFO); + error = nfs_request(nmp, NFSPROC_FSINFO, + (FAR void *)&fsinfo, sizeof(struct FS3args), + (FAR void *)&fsp, sizeof(struct rpc_reply_fsinfo)); + if (error) + { + return error; + } + + /* Save the root file system attributes */ + +//memcpy(&nmp->nm_fattr. &fsp.obj_attributes, sizeof(struct nfs_fattr)); + + pref = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_wtpref); + if (pref < nmp->nm_wsize) + { + nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); + } + + max = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_wtmax); + if (max < nmp->nm_wsize) + { + nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); + if (nmp->nm_wsize == 0) + { + nmp->nm_wsize = max; + } + } + + pref = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_rtpref); + if (pref < nmp->nm_rsize) + { + nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); + } + + max = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_rtmax); + if (max < nmp->nm_rsize) + { + nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); + if (nmp->nm_rsize == 0) + { + nmp->nm_rsize = max; + } + } + + pref = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_dtpref); + if (pref < nmp->nm_readdirsize) + { + nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) & ~(NFS_DIRBLKSIZ - 1); + } + + if (max < nmp->nm_readdirsize) + { + nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1); + if (nmp->nm_readdirsize == 0) + { + nmp->nm_readdirsize = max; + } + } + + return OK; +} + +/**************************************************************************** + * Name: nfs_statfs + * + * Description: + * Return filesystem statistics + * + * Returned Value: + * 0 on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nfs_statfs(FAR struct inode *mountpt, FAR struct statfs *sbp) +{ + FAR struct nfsmount *nmp; + FAR struct rpc_call_fs *fsstat; + FAR struct rpc_reply_fsstat *sfp; + int error = 0; + uint64_t tquad; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + nmp = (struct nfsmount*)mountpt->i_private; + + /* Check if the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + fdbg("ERROR: nfs_checkmount failed: %d\n", error); + goto errout_with_semaphore; + } + + /* Fill in the statfs info */ + + sbp->f_type = NFS_SUPER_MAGIC; + + (void)nfs_fsinfo(nmp); + + fsstat = &nmp->nm_msgbuffer.fsstat; + fsstat->fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize); + memcpy(&fsstat->fs.fsroot.handle, &nmp->nm_fh, sizeof(nfsfh_t)); + + nfs_statistics(NFSPROC_FSSTAT); + error = nfs_request(nmp, NFSPROC_FSSTAT, + (FAR void *)fsstat, sizeof(struct FS3args), + (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); + if (error) + { + goto errout_with_semaphore; + } + + sfp = (FAR struct rpc_reply_fsstat *)nmp->nm_iobuffer; + sbp->f_bsize = NFS_FABLKSIZE; + tquad = fxdr_hyper(&sfp->fsstat.sf_tbytes); + sbp->f_blocks = tquad / (uint64_t) NFS_FABLKSIZE; + tquad = fxdr_hyper(&sfp->fsstat.sf_fbytes); + sbp->f_bfree = tquad / (uint64_t) NFS_FABLKSIZE; + tquad = fxdr_hyper(&sfp->fsstat.sf_abytes); + sbp->f_bavail = tquad / (uint64_t) NFS_FABLKSIZE; + tquad = fxdr_hyper(&sfp->fsstat.sf_tfiles); + sbp->f_files = tquad; + tquad = fxdr_hyper(&sfp->fsstat.sf_ffiles); + sbp->f_ffree = tquad; + sbp->f_namelen = NAME_MAX; + +errout_with_semaphore: + nfs_semgive(nmp); + return -error; +} + +/**************************************************************************** + * Name: nfs_remove + * + * Description: + * Remove a file + * + * Returned Value: + * 0 on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nfs_remove(struct inode *mountpt, const char *relpath) +{ + FAR struct nfsmount *nmp; + struct file_handle fhandle; + struct nfs_fattr fattr; + char filename[NAME_MAX + 1]; + FAR uint32_t *ptr; + int namelen; + int reqlen; + int error; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + nmp = (struct nfsmount*)mountpt->i_private; + + /* Check if the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + fdbg("ERROR: nfs_checkmount failed: %d\n", error); + goto errout_with_semaphore; + } + + /* Find the NFS node of the directory containing the file to be deleted */ + + error = nfs_finddir(nmp, relpath, &fhandle, &fattr, filename); + if (error != OK) + { + fdbg("ERROR: nfs_finddir returned: %d\n", error); + goto errout_with_semaphore; + } + + /* Create the REMOVE RPC call arguments */ + + ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.removef.remove; + reqlen = 0; + + /* Copy the variable length, directory file handle */ + + *ptr++ = txdr_unsigned(fhandle.length); + reqlen += sizeof(uint32_t); + + memcpy(ptr, &fhandle.handle, fhandle.length); + reqlen += (int)fhandle.length; + ptr += uint32_increment(fhandle.length); + + /* Copy the variable-length file name */ + + namelen = strlen(filename); + + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); + + memcpy(ptr, filename, namelen); + reqlen += uint32_alignup(namelen); + + /* Perform the REMOVE RPC call */ + + nfs_statistics(NFSPROC_REMOVE); + error = nfs_request(nmp, NFSPROC_REMOVE, + (FAR void *)&nmp->nm_msgbuffer.removef, reqlen, + (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); + +errout_with_semaphore: + nfs_semgive(nmp); + return -error; +} + +/**************************************************************************** + * Name: nfs_mkdir + * + * Description: + * Create a directory + * + * Returned Value: + * 0 on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) +{ + struct nfsmount *nmp; + struct file_handle fhandle; + struct nfs_fattr fattr; + char dirname[NAME_MAX + 1]; + FAR uint32_t *ptr; + uint32_t tmp; + int namelen; + int reqlen; + int error; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + nmp = (struct nfsmount*) mountpt->i_private; + + /* Check if the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + fdbg("ERROR: nfs_checkmount: %d\n", error); + goto errout_with_semaphore; + } + + /* Find the NFS node of the directory containing the directory to be created */ + + error = nfs_finddir(nmp, relpath, &fhandle, &fattr, dirname); + if (error != OK) + { + fdbg("ERROR: nfs_finddir returned: %d\n", error); + return error; + } + + /* Format the MKDIR call message arguments */ + + ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.mkdir.mkdir; + reqlen = 0; + + /* Copy the variable length, directory file handle */ + + *ptr++ = txdr_unsigned(fhandle.length); + reqlen += sizeof(uint32_t); + + memcpy(ptr, &fhandle.handle, fhandle.length); + ptr += uint32_increment(fhandle.length); + reqlen += (int)fhandle.length; + + /* Copy the variable-length directory name */ + + namelen = strlen(dirname); + + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); + + memcpy(ptr, dirname, namelen); + ptr += uint32_increment(namelen); + reqlen += uint32_alignup(namelen); + + /* Set the mode. NOTE: Here we depend on the fact that the NuttX and NFS + * bit settings are the same (at least for the bits of interest). + */ + + *ptr++ = nfs_true; /* True: mode value follows */ + reqlen += sizeof(uint32_t); + + tmp = mode & (NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH | + NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP | + NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR); + *ptr++ = txdr_unsigned(tmp); + reqlen += sizeof(uint32_t); + + /* Set the user ID to zero */ + + *ptr++ = nfs_true; /* True: Uid value follows */ + *ptr++ = 0; /* UID = 0 (nobody) */ + reqlen += 2*sizeof(uint32_t); + + /* Set the group ID to one */ + + *ptr++ = nfs_true; /* True: Gid value follows */ + *ptr++ = HTONL(1); /* GID = 1 (nogroup) */ + reqlen += 2*sizeof(uint32_t); + + /* No size */ + + *ptr++ = nfs_false; /* False: No size value follows */ + reqlen += sizeof(uint32_t); + + /* Don't change times */ + + *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change atime */ + *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */ + reqlen += 2*sizeof(uint32_t); + + /* Perform the MKDIR RPC */ + + nfs_statistics(NFSPROC_MKDIR); + error = nfs_request(nmp, NFSPROC_MKDIR, + (FAR void *)&nmp->nm_msgbuffer.mkdir, reqlen, + (FAR void *)&nmp->nm_iobuffer, nmp->nm_buflen); + if (error) + { + fdbg("ERROR: nfs_request failed: %d\n", error); + } + +errout_with_semaphore: + nfs_semgive(nmp); + return -error; +} + +/**************************************************************************** + * Name: nfs_rmdir + * + * Description: + * Remove a directory + * + * Returned Value: + * 0 on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nfs_rmdir(struct inode *mountpt, const char *relpath) +{ + struct nfsmount *nmp; + struct file_handle fhandle; + struct nfs_fattr fattr; + char dirname[NAME_MAX + 1]; + FAR uint32_t *ptr; + int namelen; + int reqlen; + int error; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + nmp = (struct nfsmount *)mountpt->i_private; + + /* Check if the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + fdbg("ERROR: nfs_checkmount failed: %d\n", error); + goto errout_with_semaphore; + } + + /* Find the NFS node of the directory containing the directory to be removed */ + + error = nfs_finddir(nmp, relpath, &fhandle, &fattr, dirname); + if (error != OK) + { + fdbg("ERROR: nfs_finddir returned: %d\n", error); + return error; + } + + /* Set up the RMDIR call message arguments */ + + ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.rmdir.rmdir; + reqlen = 0; + + /* Copy the variable length, directory file handle */ + + *ptr++ = txdr_unsigned(fhandle.length); + reqlen += sizeof(uint32_t); + + memcpy(ptr, &fhandle.handle, fhandle.length); + reqlen += (int)fhandle.length; + ptr += uint32_increment(fhandle.length); + + /* Copy the variable-length directory name */ + + namelen = strlen(dirname); + + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); + + memcpy(ptr, dirname, namelen); + reqlen += uint32_alignup(namelen); + + /* Perform the RMDIR RPC */ + + nfs_statistics(NFSPROC_RMDIR); + error = nfs_request(nmp, NFSPROC_RMDIR, + (FAR void *)&nmp->nm_msgbuffer.rmdir, reqlen, + (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); + +errout_with_semaphore: + nfs_semgive(nmp); + return -error; +} + +/**************************************************************************** + * Name: nfs_rename + * + * Description: + * Rename a file or directory + * + * Returned Value: + * 0 on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nfs_rename(struct inode *mountpt, const char *oldrelpath, + const char *newrelpath) +{ + struct nfsmount *nmp; + struct file_handle from_handle; + struct file_handle to_handle; + char from_name[NAME_MAX+1]; + char to_name[NAME_MAX+1]; + struct nfs_fattr fattr; + FAR uint32_t *ptr; + int namelen; + int reqlen; + int error; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + nmp = (struct nfsmount *)mountpt->i_private; + + /* Check if the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + fdbg("ERROR: nfs_checkmount returned: %d\n", error); + goto errout_with_semaphore; + } + + /* Find the NFS node of the directory containing the 'from' object */ + + error = nfs_finddir(nmp, oldrelpath, &from_handle, &fattr, from_name); + if (error != OK) + { + fdbg("ERROR: nfs_finddir returned: %d\n", error); + return error; + } + + /* Find the NFS node of the directory containing the 'from' object */ + + error = nfs_finddir(nmp, newrelpath, &to_handle, &fattr, to_name); + if (error != OK) + { + fdbg("ERROR: nfs_finddir returned: %d\n", error); + return error; + } + + /* Format the RENAME RPC arguments */ + + ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.renamef.rename; + reqlen = 0; + + /* Copy the variable length, 'from' directory file handle */ + + *ptr++ = txdr_unsigned(from_handle.length); + reqlen += sizeof(uint32_t); + + memcpy(ptr, &from_handle.handle, from_handle.length); + reqlen += (int)from_handle.length; + ptr += uint32_increment(from_handle.length); + + /* Copy the variable-length 'from' object name */ + + namelen = strlen(from_name); + + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); + + memcpy(ptr, from_name, namelen); + reqlen += uint32_alignup(namelen); + ptr += uint32_increment(namelen); + + /* Copy the variable length, 'to' directory file handle */ + + *ptr++ = txdr_unsigned(to_handle.length); + reqlen += sizeof(uint32_t); + + memcpy(ptr, &to_handle.handle, to_handle.length); + ptr += uint32_increment(to_handle.length); + reqlen += (int)to_handle.length; + + /* Copy the variable-length 'to' object name */ + + namelen = strlen(to_name); + + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); + + memcpy(ptr, to_name, namelen); + reqlen += uint32_alignup(namelen); + + /* Perform the RENAME RPC */ + + nfs_statistics(NFSPROC_RENAME); + error = nfs_request(nmp, NFSPROC_RENAME, + (FAR void *)&nmp->nm_msgbuffer.renamef, reqlen, + (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); + +errout_with_semaphore: + nfs_semgive(nmp); + return -error; +} + +/**************************************************************************** + * Name: nfs_stat + * + * Description: + * Return information about the file system object at 'relpath' + * + * Returned Value: + * 0 on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nfs_stat(struct inode *mountpt, const char *relpath, + struct stat *buf) +{ + struct nfsmount *nmp; + struct file_handle fhandle; + struct nfs_fattr obj_attributes; + uint32_t tmp; + uint32_t mode; + int error; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + nmp = (struct nfsmount*)mountpt->i_private; + DEBUGASSERT(nmp && buf); + + /* Check if the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + fdbg("ERROR: nfs_checkmount failed: %d\n", error); + goto errout_with_semaphore; + } + + /* Get the file handle attributes of the requested node */ + + error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, NULL); + if (error != OK) + { + fdbg("ERROR: nfs_findnode failed: %d\n", error); + goto errout_with_semaphore; + } + + /* Construct the file mode. This is a 32-bit, encoded value containing + * both the access mode and the file type. + */ + + tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_mode); + + /* Here we exploit the fact that most mode bits are the same in NuttX + * as in the NFSv3 spec. + */ + + mode = tmp & (NFSMODE_IXOTH|NFSMODE_IWOTH|NFSMODE_IROTH| + NFSMODE_IXGRP|NFSMODE_IWGRP|NFSMODE_IRGRP| + NFSMODE_IXUSR|NFSMODE_IWUSR|NFSMODE_IRUSR); + + /* Handle the cases that are not the same */ + + if ((mode & NFSMODE_ISGID) != 0) + { + mode |= S_ISGID; + } + + if ((mode & NFSMODE_ISUID) != 0) + { + mode |= S_ISUID; + } + + /* Now OR in the file type */ + + tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_type); + switch (tmp) + { + default: + case NFNON: /* Unknown type */ + break; + + case NFREG: /* Regular file */ + mode |= S_IFREG; + break; + + case NFDIR: /* Directory */ + mode |= S_IFDIR; + break; + + case NFBLK: /* Block special device file */ + mode |= S_IFBLK; + break; + + case NFCHR: /* Character special device file */ + mode |= S_IFCHR; + break; + + case NFLNK: /* Symbolic link */ + mode |= S_IFLNK; + break; + + case NFSOCK: /* Socket */ + mode |= S_IFSOCK; + break; + + case NFFIFO: /* Named pipe */ + mode |= S_IFMT; + break; + } + + buf->st_mode = mode; + buf->st_size = fxdr_hyper(&obj_attributes.fa_size); + buf->st_blksize = 0; + buf->st_blocks = 0; + buf->st_mtime = fxdr_hyper(&obj_attributes.fa_mtime); + buf->st_atime = fxdr_hyper(&obj_attributes.fa_atime); + buf->st_ctime = fxdr_hyper(&obj_attributes.fa_ctime); + +errout_with_semaphore: + nfs_semgive(nmp); + return -error; +} diff --git a/nuttx/fs/nfs/rpc.h b/nuttx/fs/nfs/rpc.h new file mode 100644 index 0000000000..27366557d4 --- /dev/null +++ b/nuttx/fs/nfs/rpc.h @@ -0,0 +1,491 @@ +/**************************************************************************** + * fs/nfs/rpc.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. + * Author: Jose Pablo Rojas Vargas + * Gregory Nutt + * + * Leveraged from OpenBSD: + * + * copyright (c) 2003 + * the regents of the university of michigan + * all rights reserved + * + * permission is granted to use, copy, create derivative works and redistribute + * this software and such derivative works for any purpose, so long as the name + * of the university of michigan is not used in any advertising or publicity + * pertaining to the use or distribution of this software without specific, + * written prior authorization. if the above copyright notice or any other + * identification of the university of michigan is included in any copy of any + * portion of this software, then the disclaimer below must also be included. + * + * this software is provided as is, without representation from the university + * of michigan as to its fitness for any purpose, and without warranty by the + * university of michigan of any kind, either express or implied, including + * without limitation the implied warranties of merchantability and fitness for + * a particular purpose. the regents of the university of michigan shall not be + * liable for any damages, including special, indirect, incidental, or + * consequential damages, with respect to any claim arising out of or in + * connection with the use of the software, even if it has been or is hereafter + * advised of the possibility of such damages. + * + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_NFS_RPC_H +#define __FS_NFS_RPC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "nfs_proto.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Version # */ + +#define RPC_VER2 2 + +/* Authentication */ + +#define RPCAUTH_NULL 0 +#define RPCAUTH_UNIX 1 +#define RPCAUTH_SHORT 2 +#define RPCAUTH_KERB4 4 +#define RPCAUTH_MAXSIZ 400 +#define RPCVERF_MAXSIZ 12 + /* For Kerb, can actually be 400 */ +#define RPCAUTH_UNIXGIDS 16 + +/* Constants associated with authentication flavours. */ + +#define RPCAKN_FULLNAME 0 +#define RPCAKN_NICKNAME 1 + +/* RPC Constants */ + +#define RPC_CALL 0 +#define RPC_REPLY 1 +#define RPC_MSGACCEPTED 0 +#define RPC_MSGDENIED 1 +#define RPC_PROGUNAVAIL 1 +#define RPC_PROGMISMATCH 2 +#define RPC_PROCUNAVAIL 3 +#define RPC_GARBAGE 4 + +#define RPC_MISMATCH 0 +#define RPC_AUTHERR 1 + +/* Authentication failures */ + +#define AUTH_BADCRED 1 +#define AUTH_REJECTCRED 2 +#define AUTH_BADVERF 3 +#define AUTH_REJECTVERF 4 +#define AUTH_TOOWEAK 5 + +/* Sizes of RPC header parts */ + +#define RPC_SIZ 24 +#define RPC_REPLYSIZ 28 + +/* RPC Prog definitions */ + +#define RPCPROG_MNT 100005 +#define RPCMNT_VER1 1 +#define RPCMNT_VER3 3 +#define RPCMNT_MOUNT 1 +#define RPCMNT_DUMP 2 +#define RPCMNT_UMOUNT 3 +#define RPCMNT_UMNTALL 4 +#define RPCMNT_EXPORT 5 +#define RPCMNT_NAMELEN 255 +#define RPCMNT_PATHLEN 1024 +#define RPCPROG_NFS 100003 + +/* RPC definitions for the portmapper. */ + +#define PMAPPORT 111 +#define PMAPPROG 100000 +#define PMAPVERS 2 + +#define PMAPPROC_NULL 0 +#define PMAPPROC_SET 1 +#define PMAPPROC_UNSET 2 +#define PMAPPROC_GETPORT 3 +#define PMAPPROC_DUMP 4 +#define PMAPPROC_CALLIT 5 + +#define RPC_SUCCESS 0 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Global RPC statistics */ + +#ifdef CONFIG_NFS_STATISTICS +struct rpcstats +{ + int rpcretries; + int rpcrequests; + int rpctimeouts; + int rpcinvalid; +}; +#endif + +/* PMAP headers */ + +struct call_args_pmap +{ + uint32_t prog; + uint32_t vers; + uint32_t proc; + uint32_t port; +}; + +struct call_result_pmap +{ + uint32_t port; +}; + +/* MOUNTD headers */ + +struct call_args_mount +{ + uint32_t len; + char rpath[90]; +}; + +struct call_args_umount +{ + uint32_t len; + char rpath[90]; +}; + +struct call_result_mount +{ + uint32_t status; + nfsfh_t fhandle; +}; + +/* Generic RPC call headers */ + +enum auth_flavor +{ + AUTH_NONE = 0, + AUTH_SYS = 1, + AUTH_SHORT = 2 + /* and more to be defined */ +}; + +struct rpc_auth_info +{ + uint32_t authtype; /* auth type */ + uint32_t authlen; /* auth length */ +}; + +struct auth_unix +{ + int32_t stamp; + uint8_t hostname; /* null */ + int32_t uid; + int32_t gid; + int32_t gidlist; /* null */ +}; + +struct rpc_call_header +{ + uint32_t rp_xid; /* request transaction id */ + int32_t rp_direction; /* call direction (0) */ + uint32_t rp_rpcvers; /* RPC version (2) */ + uint32_t rp_prog; /* program */ + uint32_t rp_vers; /* version */ + uint32_t rp_proc; /* procedure */ + struct rpc_auth_info rpc_auth; + struct rpc_auth_info rpc_verf; +}; + +struct rpc_call_pmap +{ + struct rpc_call_header ch; + struct call_args_pmap pmap; +}; + +struct rpc_call_mount +{ + struct rpc_call_header ch; + struct call_args_mount mount; +}; + +struct rpc_call_umount +{ + struct rpc_call_header ch; + struct call_args_umount umount; +}; + +struct rpc_call_create +{ + struct rpc_call_header ch; + struct CREATE3args create; +}; + +struct rpc_call_lookup +{ + struct rpc_call_header ch; + struct LOOKUP3args lookup; +}; +#define SIZEOF_rpc_call_lookup(n) (sizeof(struct rpc_call_header) + SIZEOF_LOOKUP3args(n)) + +struct rpc_call_read +{ + struct rpc_call_header ch; + struct READ3args read; +}; + +struct rpc_call_write +{ + struct rpc_call_header ch; + struct WRITE3args write; /* Variable length */ +}; +#define SIZEOF_rpc_call_write(n) (sizeof(struct rpc_call_header) + SIZEOF_WRITE3args(n)) + +struct rpc_call_remove +{ + struct rpc_call_header ch; + struct REMOVE3args remove; +}; + +struct rpc_call_rename +{ + struct rpc_call_header ch; + struct RENAME3args rename; +}; + +struct rpc_call_mkdir +{ + struct rpc_call_header ch; + struct MKDIR3args mkdir; +}; + +struct rpc_call_rmdir +{ + struct rpc_call_header ch; + struct RMDIR3args rmdir; +}; + +struct rpc_call_readdir +{ + struct rpc_call_header ch; + struct READDIR3args readdir; +}; + +struct rpc_call_setattr +{ + struct rpc_call_header ch; + struct SETATTR3args setattr; +}; + +struct rpc_call_fs +{ + struct rpc_call_header ch; + struct FS3args fs; +}; + +/* Generic RPC reply headers */ + +struct rpc_reply_header +{ + uint32_t rp_xid; /* Request transaction id */ + uint32_t rp_direction; /* Call direction (1) */ + uint32_t type; + struct rpc_auth_info rpc_verfi; + uint32_t status; +}; + +struct nfs_reply_header +{ + uint32_t rp_xid; /* Request transaction id */ + uint32_t rp_direction; /* Call direction (1) */ + uint32_t type; + struct rpc_auth_info rpc_verfi; + uint32_t status; + uint32_t nfs_status; +}; + +struct rpc_reply_pmap +{ + struct rpc_reply_header rh; + struct call_result_pmap pmap; +}; + +struct rpc_reply_mount +{ + struct rpc_reply_header rh; + struct call_result_mount mount; +}; + +struct rpc_reply_umount +{ + struct rpc_reply_header rh; +}; + +struct rpc_reply_create +{ + struct rpc_reply_header rh; + uint32_t status; + struct CREATE3resok create; +}; + +struct rpc_reply_lookup +{ + struct rpc_reply_header rh; + uint32_t status; + struct LOOKUP3resok lookup; +}; + +struct rpc_reply_write +{ + struct rpc_reply_header rh; + uint32_t status; + struct WRITE3resok write; /* Variable length */ +}; + +struct rpc_reply_read +{ + struct rpc_reply_header rh; + uint32_t status; + struct READ3resok read; /* Variable length */ +}; +#define SIZEOF_rpc_reply_read(n) (sizeof(struct rpc_reply_header) + sizeof(uint32_t) + SIZEOF_READ3resok(n)) + +struct rpc_reply_remove +{ + struct rpc_reply_header rh; + uint32_t status; + struct REMOVE3resok remove; +}; + +struct rpc_reply_rename +{ + struct rpc_reply_header rh; + uint32_t status; + struct RENAME3resok rename; +}; + +struct rpc_reply_mkdir +{ + struct rpc_reply_header rh; + uint32_t status; + struct MKDIR3resok mkdir; +}; + +struct rpc_reply_rmdir +{ + struct rpc_reply_header rh; + uint32_t status; + struct RMDIR3resok rmdir; +}; + +struct rpc_reply_readdir +{ + struct rpc_reply_header rh; + uint32_t status; + struct READDIR3resok readdir; +}; + +struct rpc_reply_fsinfo +{ + struct rpc_reply_header rh; + uint32_t status; + struct nfsv3_fsinfo fsinfo; +}; + +struct rpc_reply_fsstat +{ + struct rpc_reply_header rh; + uint32_t status; + struct nfs_statfs fsstat; +}; + +struct rpc_reply_getattr +{ + struct rpc_reply_header rh; + uint32_t status; + struct nfs_fattr attr; +}; + +struct rpc_reply_setattr +{ + struct rpc_reply_header rh; + uint32_t status; + struct SETATTR3resok setattr; +}; + +struct rpcclnt +{ + nfsfh_t rc_fh; /* File handle of the root directory */ + char *rc_path; /* Server's path of the mounted directory */ + + struct sockaddr *rc_name; + struct socket *rc_so; /* RPC socket */ + + bool rc_timeout; /* Receipt of reply timed out */ + uint8_t rc_sotype; /* Type of socket */ + uint8_t rc_retry; /* Max retries */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void rpcclnt_init(void); +int rpcclnt_connect(FAR struct rpcclnt *rpc); +int rpcclnt_reconnect(FAR struct rpcclnt *rpc); +void rpcclnt_disconnect(FAR struct rpcclnt *rpc); +int rpcclnt_umount(FAR struct rpcclnt *rpc); +void rpcclnt_safedisconnect(FAR struct rpcclnt *rpc); +int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, int version, + FAR void *request, size_t reqlen, + FAR void *response, size_t resplen); + +#endif /* __FS_NFS_RPC_H */ diff --git a/nuttx/fs/nfs/rpc_clnt.c b/nuttx/fs/nfs/rpc_clnt.c new file mode 100644 index 0000000000..0e2a394bad --- /dev/null +++ b/nuttx/fs/nfs/rpc_clnt.c @@ -0,0 +1,807 @@ +/**************************************************************************** + * fs/nfs/rpc_clnt.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. + * Author: Jose Pablo Rojas Vargas + * Gregory Nutt + * + * Leveraged from OpenBSD: + * + * Copyright (c) 2004 The Regents of the University of Michigan. + * All rights reserved. + * + * Copyright (c) 2004 Weston Andros Adamson . + * Copyright (c) 2004 Marius Aamodt Eriksen . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright (c) 1989, 1991, 1993, 1995 The Regents of the University of + * California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by Rick Macklem at + * The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. 3. All advertising + * materials mentioning features or use of this software must display the + * following acknowledgement: This product includes software developed by the + * University of California, Berkeley and its contributors. 4. Neither the + * name of the University nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xdr_subs.h" +#include "nfs_proto.h" +#include "rpc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Increment RPC statistics */ + +#ifdef CONFIG_NFS_STATISTICS +# define rpc_statistics(n) do { rpcstats.(n)++; } while (0) +#else +# define rpc_statistics(n) +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Static data, mostly RPC constants in XDR form */ + +static uint32_t rpc_reply; +static uint32_t rpc_call; +static uint32_t rpc_vers; +static uint32_t rpc_msgdenied; +static uint32_t rpc_mismatch; +static uint32_t rpc_auth_unix; +static uint32_t rpc_msgaccepted; +static uint32_t rpc_autherr; +static uint32_t rpc_auth_null; + +/* Global statics for all client instances. Cleared by NuttX on boot-up. */ + +#ifdef CONFIG_NFS_STATISTICS +static struct rpcstats rpcstats; +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog, + FAR void *call, int reqlen); +static int rpcclnt_receive(FAR struct rpcclnt *rpc, struct sockaddr *aname, + int proc, int program, void *reply, size_t resplen); +static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog, + void *reply, size_t resplen); +static uint32_t rpcclnt_newxid(void); +static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, + uint32_t xid, int procid, int prog, int vers); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rpcclnt_send + * + * Description: + * This is the nfs send routine. + * + * Returned Value: + * Returns zero on success or a (positive) errno value on failure. + * + ****************************************************************************/ + +static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog, + FAR void *call, int reqlen) +{ + ssize_t nbytes; + int error = OK; + + /* Send the call message + * + * On success, psock_sendto returns the number of bytes sent; + * On failure, it returns -1 with the specific error in errno. + */ + + nbytes = psock_sendto(rpc->rc_so, call, reqlen, 0, + rpc->rc_name, sizeof(struct sockaddr)); + if (nbytes < 0) + { + /* psock_sendto failed */ + + error = errno; + fdbg("ERROR: psock_sendto failed: %d\n", error); + } + + return error; +} + +/**************************************************************************** + * Name: rpcclnt_receive + * + * Description: + * Receive a Sun RPC Request/Reply. For SOCK_DGRAM, the work is all done + * by psock_recvfrom(). + * + ****************************************************************************/ + +static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname, + int proc, int program, FAR void *reply, + size_t resplen) +{ + ssize_t nbytes; + int error = 0; + + socklen_t fromlen = sizeof(struct sockaddr); + nbytes = psock_recvfrom(rpc->rc_so, reply, resplen, 0, aname, &fromlen); + if (nbytes < 0) + { + error = errno; + fdbg("ERROR: psock_recvfrom failed: %d\n", error); + } + + return error; +} + +/**************************************************************************** + * Name: rpcclnt_reply + * + * Description: + * Received the RPC reply on the socket. + * + ****************************************************************************/ + +static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog, + FAR void *reply, size_t resplen) +{ + FAR struct rpc_reply_header *replyheader; + uint32_t rxid; + int error; + + /* Get the next RPC reply from the socket */ + + error = rpcclnt_receive(rpc, rpc->rc_name, procid, prog, reply, resplen); + if (error != 0) + { + fdbg("ERROR: rpcclnt_receive returned: %d\n", error); + + /* If we failed because of a timeout, then try sending the CALL + * message again. + */ + + if (error == EAGAIN || error == ETIMEDOUT) + { + rpc->rc_timeout = true; + } + } + + /* Get the xid and check that it is an RPC replysvr */ + + else + { + replyheader = (FAR struct rpc_reply_header *)reply; + rxid = replyheader->rp_xid; + + if (replyheader->rp_direction != rpc_reply) + { + fdbg("ERROR: Different RPC REPLY returned\n"); + rpc_statistics(rpcinvalid); + error = EPROTO; + } + } + + return OK; +} + +/**************************************************************************** + * Name: rpcclnt_newxid + * + * Description: + * Get a new (non-zero) xid + * + ****************************************************************************/ + +static uint32_t rpcclnt_newxid(void) +{ + static uint32_t rpcclnt_xid = 0; + static uint32_t rpcclnt_xid_touched = 0; + int xidp = 0; + + srand(time(NULL)); + if ((rpcclnt_xid == 0) && (rpcclnt_xid_touched == 0)) + { + rpcclnt_xid = rand(); + rpcclnt_xid_touched = 1; + } + else + { + do + { + xidp = rand(); + } + while ((xidp % 256) == 0); + + rpcclnt_xid += xidp; + } + + return rpcclnt_xid; +} + +/**************************************************************************** + * Name: rpcclnt_fmtheader + * + * Description: + * Format the common part of the call header + * + ****************************************************************************/ + +static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, + uint32_t xid, int prog, int vers, int procid) +{ + /* Format the call header */ + + ch->rp_xid = txdr_unsigned(xid); + ch->rp_direction = rpc_call; + ch->rp_rpcvers = rpc_vers; + ch->rp_prog = txdr_unsigned(prog); + ch->rp_vers = txdr_unsigned(vers); + ch->rp_proc = txdr_unsigned(procid); + + /* rpc_auth part (auth_null) */ + + ch->rpc_auth.authtype = rpc_auth_null; + ch->rpc_auth.authlen = 0; + + /* rpc_verf part (auth_null) */ + + ch->rpc_verf.authtype = rpc_auth_null; + ch->rpc_verf.authlen = 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rpcclnt_init + * + * Description: + * Initialize the RPC client + * + ****************************************************************************/ + +void rpcclnt_init(void) +{ + /* RPC constants how about actually using more than one of these! */ + + rpc_reply = txdr_unsigned(RPC_REPLY); + rpc_vers = txdr_unsigned(RPC_VER2); + rpc_call = txdr_unsigned(RPC_CALL); + rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED); + rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED); + rpc_mismatch = txdr_unsigned(RPC_MISMATCH); + rpc_autherr = txdr_unsigned(RPC_AUTHERR); + rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX); + rpc_auth_null = txdr_unsigned(RPCAUTH_NULL); + + fvdbg("RPC initialized\n"); +} + +/**************************************************************************** + * Name: rpcclnt_connect + * + * Description: + * Initialize sockets for a new RPC connection. We do not free the + * sockaddr if an error occurs. + * + ****************************************************************************/ + +int rpcclnt_connect(struct rpcclnt *rpc) +{ + struct socket *so; + int error; + struct sockaddr *saddr; + struct sockaddr_in sin; + struct sockaddr_in *sa; + + union + { + struct rpc_call_pmap sdata; + struct rpc_call_mount mountd; + } request; + + union + { + struct rpc_reply_pmap rdata; + struct rpc_reply_mount mdata; + } response; + + struct timeval tv; + uint16_t tport; + int errval; + + fvdbg("Connecting\n"); + + /* Create the socket */ + + saddr = rpc->rc_name; + + /* Create an instance of the socket state structure */ + + so = (struct socket *)kzalloc(sizeof(struct socket)); + if (!so) + { + fdbg("ERROR: Failed to allocate socket structure\n"); + return ENOMEM; + } + + error = psock_socket(saddr->sa_family, rpc->rc_sotype, IPPROTO_UDP, so); + if (error < 0) + { + errval = errno; + fdbg("ERROR: psock_socket failed: %d", errval); + return error; + } + + so->s_crefs = 1; + rpc->rc_so = so; + + /* Always set receive timeout to detect server crash and reconnect. + * Otherwise, we can get stuck in psock_receive forever. + */ + + tv.tv_sec = 1; + tv.tv_usec = 0; + + error = psock_setsockopt(rpc->rc_so, SOL_SOCKET, SO_RCVTIMEO, + (const void *)&tv, sizeof(tv)); + if (error < 0) + { + errval = errno; + fdbg("ERROR: psock_setsockopt failed: %d\n", errval); + goto bad; + } + + /* Some servers require that the client port be a reserved port + * number. We always allocate a reserved port, as this prevents + * filehandle disclosure through UDP port capture. + */ + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + tport = 1024; + + errval = 0; + do + { + tport--; + sin.sin_port = htons(tport); + error = psock_bind(rpc->rc_so, (struct sockaddr *)&sin, sizeof(sin)); + if (error < 0) + { + errval = errno; + fdbg("ERROR: psock_bind failed: %d\n", errval); + } + } + while (errval == EADDRINUSE && tport > 1024 / 2); + + if (error) + { + fdbg("ERROR: psock_bind failed: %d\n", errval); + goto bad; + } + + /* Protocols that do not require connections may be optionally left + * unconnected for servers that reply from a port other than + * NFS_PORT. + */ + + error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); + if (error < 0) + { + errval = errno; + fdbg("ERROR: psock_connect to PMAP port failed: %d", errval); + goto bad; + } + + /* Do the RPC to get a dynamic bounding with the server using ppmap. + * Get port number for MOUNTD. + */ + + request.sdata.pmap.prog = txdr_unsigned(RPCPROG_MNT); + request.sdata.pmap.vers = txdr_unsigned(RPCMNT_VER1); + request.sdata.pmap.proc = txdr_unsigned(IPPROTO_UDP); + request.sdata.pmap.port = 0; + + error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, + (FAR void *)&request.sdata, sizeof(struct call_args_pmap), + (FAR void *)&response.rdata, sizeof(struct rpc_reply_pmap)); + if (error != 0) + { + fdbg("ERROR: rpcclnt_request failed: %d\n", error); + goto bad; + } + + sa = (FAR struct sockaddr_in *)saddr; + sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); + + error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); + if (error < 0) + { + errval = errno; + fdbg("ERROR: psock_connect MOUNTD port failed: %d\n", errval); + goto bad; + } + + /* Do RPC to mountd. */ + + strncpy(request.mountd.mount.rpath, rpc->rc_path, 90); + request.mountd.mount.len = txdr_unsigned(sizeof(request.mountd.mount.rpath)); + + error = rpcclnt_request(rpc, RPCMNT_MOUNT, RPCPROG_MNT, RPCMNT_VER1, + (FAR void *)&request.mountd, sizeof(struct call_args_mount), + (FAR void *)&response.mdata, sizeof(struct rpc_reply_mount)); + if (error != 0) + { + fdbg("ERROR: rpcclnt_request failed: %d\n", error); + goto bad; + } + + error = fxdr_unsigned(uint32_t, response.mdata.mount.status); + if (error != 0) + { + fdbg("ERROR: Bad mount status: %d\n", error); + goto bad; + } + + memcpy(&rpc->rc_fh, &response.mdata.mount.fhandle, sizeof(nfsfh_t)); + + /* Do the RPC to get a dynamic bounding with the server using PMAP. + * NFS port in the socket. + */ + + sa->sin_port = htons(PMAPPORT); + + error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); + if (error < 0) + { + errval = errno; + fdbg("ERROR: psock_connect PMAP port failed: %d\n", errval); + goto bad; + } + + request.sdata.pmap.prog = txdr_unsigned(NFS_PROG); + request.sdata.pmap.vers = txdr_unsigned(NFS_VER3); + request.sdata.pmap.proc = txdr_unsigned(IPPROTO_UDP); + request.sdata.pmap.port = 0; + + error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, + (FAR void *)&request.sdata, sizeof(struct call_args_pmap), + (FAR void *)&response.rdata, sizeof(struct rpc_reply_pmap)); + if (error != 0) + { + fdbg("ERROR: rpcclnt_request failed: %d\n", error); + goto bad; + } + + sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); + + error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); + if (error) + { + fdbg("psock_connect NFS port returns %d\n", error); + goto bad; + } + + return OK; + +bad: + rpcclnt_disconnect(rpc); + return error; +} + +/**************************************************************************** + * Name: rpcclnt_disconnect + * + * Description: + * Disconnect from the NFS server. + * + ****************************************************************************/ + +void rpcclnt_disconnect(struct rpcclnt *rpc) +{ + if (rpc->rc_so != NULL) + { + (void)psock_close(rpc->rc_so); + } +} + +/**************************************************************************** + * Name: rpcclnt_umount + * + * Description: + * Un-mount the NFS file system. + * + ****************************************************************************/ + +int rpcclnt_umount(struct rpcclnt *rpc) +{ + struct sockaddr *saddr; + struct sockaddr_in *sa; + + union + { + struct rpc_call_pmap sdata; + struct rpc_call_umount mountd; + } request; + + union + { + struct rpc_reply_pmap rdata; + struct rpc_reply_umount mdata; + } response; + + int error; + int ret; + + saddr = rpc->rc_name; + sa = (FAR struct sockaddr_in *)saddr; + + /* Do the RPC to get a dynamic bounding with the server using ppmap. + * Get port number for MOUNTD. + */ + + sa->sin_port = htons(PMAPPORT); + + ret = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); + if (ret < 0) + { + error = errno; + fdbg("ERROR: psock_connect failed [port=%d]: %d\n", + ntohs(sa->sin_port), error); + goto bad; + } + + request.sdata.pmap.prog = txdr_unsigned(RPCPROG_MNT); + request.sdata.pmap.vers = txdr_unsigned(RPCMNT_VER1); + request.sdata.pmap.proc = txdr_unsigned(IPPROTO_UDP); + request.sdata.pmap.port = 0; + + error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, + (FAR void *)&request.sdata, sizeof(struct call_args_pmap), + (FAR void *)&response.rdata, sizeof(struct rpc_reply_pmap)); + if (error != 0) + { + fdbg("ERROR: rpcclnt_request failed: %d\n", error); + goto bad; + } + + sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); + + ret = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); + if (ret < 0) + { + error = errno; + fdbg("ERROR: psock_connect failed [port=%d]: %d\n", + ntohs(sa->sin_port), error); + goto bad; + } + + /* Do RPC to umountd. */ + + strncpy(request.mountd.umount.rpath, rpc->rc_path, 92); + request.mountd.umount.len = txdr_unsigned(sizeof(request.mountd.umount.rpath)); + + error = rpcclnt_request(rpc, RPCMNT_UMOUNT, RPCPROG_MNT, RPCMNT_VER1, + (FAR void *)&request.mountd, sizeof(struct call_args_umount), + (FAR void *)&response.mdata, sizeof(struct rpc_reply_umount)); + if (error != 0) + { + fdbg("ERROR: rpcclnt_request failed: %d\n", error); + goto bad; + } + + return OK; + +bad: + rpcclnt_disconnect(rpc); + return error; +} + +/**************************************************************************** + * Name: rpcclnt_request + * + * Description: + * Perform the RPC request. Logic formats the RPC CALL message and calls + * rpcclnt_send to send the RPC CALL message. It then calls rpcclnt_reply() + * to get the response. It may attempt to re-send the CALL message on + * certain errors. + * + * On successful receipt, it verifies the RPC level of the returned values. + * (There may still be be NFS layer errors that will be deted by calling + * logic). + * + ****************************************************************************/ + +int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, + int version, FAR void *request, size_t reqlen, + FAR void *response, size_t resplen) +{ + struct rpc_reply_header *replymsg; + uint32_t tmp; + uint32_t xid; + int retries; + int error = 0; + + /* Get a new (non-zero) xid */ + + xid = rpcclnt_newxid(); + + /* Initialize the RPC header fields */ + + rpcclnt_fmtheader((FAR struct rpc_call_header *)request, + xid, prog, version, procnum); + + /* Get the full size of the message (the size of variable data plus the size of + * the messages header). + */ + + reqlen += sizeof(struct rpc_call_header); + + /* Send the RPC call messsages and receive the RPC response. A limited + * number of re-tries will be attempted, but only for the case of response + * timeouts. + */ + + retries = 0; + do + { + /* Do the client side RPC. */ + + rpc_statistics(rpcrequests); + rpc->rc_timeout = false; + + /* Send the RPC CALL message */ + + error = rpcclnt_send(rpc, procnum, prog, request, reqlen); + if (error != OK) + { + fvdbg("ERROR rpcclnt_send failed: %d\n", error); + } + + /* Wait for the reply from our send */ + + else + { + error = rpcclnt_reply(rpc, procnum, prog, response, resplen); + if (error != OK) + { + fvdbg("ERROR rpcclnt_reply failed: %d\n", error); + } + } + + retries++; + } + while (rpc->rc_timeout && retries <= rpc->rc_retry); + + if (error != OK) + { + fdbg("ERROR: RPC failed: %d\n", error); + return error; + } + + /* Break down the RPC header and check if it is OK */ + + replymsg = (FAR struct rpc_reply_header *)response; + + tmp = fxdr_unsigned(uint32_t, replymsg->type); + if (tmp == RPC_MSGDENIED) + { + tmp = fxdr_unsigned(uint32_t, replymsg->status); + switch (tmp) + { + case RPC_MISMATCH: + fdbg("RPC_MSGDENIED: RPC_MISMATCH error\n"); + return EOPNOTSUPP; + + case RPC_AUTHERR: + fdbg("RPC_MSGDENIED: RPC_AUTHERR error\n"); + return EACCES; + + default: + return EOPNOTSUPP; + } + } + else if (tmp != RPC_MSGACCEPTED) + { + return EOPNOTSUPP; + } + + tmp = fxdr_unsigned(uint32_t, replymsg->status); + if (tmp == RPC_SUCCESS) + { + fvdbg("RPC_SUCCESS\n"); + } + else if (tmp == RPC_PROGMISMATCH) + { + fdbg("RPC_MSGACCEPTED: RPC_PROGMISMATCH error\n"); + return EOPNOTSUPP; + } + else if (tmp > 5) + { + fdbg("ERROR: Other RPC type: %d\n", tmp); + return EOPNOTSUPP; + } + + return OK; +} diff --git a/nuttx/fs/nfs/xdr_subs.h b/nuttx/fs/nfs/xdr_subs.h new file mode 100644 index 0000000000..891af004c9 --- /dev/null +++ b/nuttx/fs/nfs/xdr_subs.h @@ -0,0 +1,128 @@ +/**************************************************************************** + * fs/nfs/xdr_subs.h + * Definitions for Sun RPC Version 2, from + * "RPC: Remote Procedure Call Protocol Specification" RFC1057 + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. + * Author: Jose Pablo Rojas Vargas + * Gregory Nutt + * + * Leveraged from OpenBSD: + * + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_NFS_XDR_SUBS_H +#define __FS_NFS_XDR_SUBS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Macros used for conversion to/from xdr representation by nfs... + * These use the MACHINE DEPENDENT routines ntohl, htonl + * As defined by "XDR: External Data Representation Standard" RFC1014 + * + * To simplify the implementation, we use ntohl/htonl even on big-endian + * machines, and count on them being `#define'd away. Some of these + * might be slightly more efficient as int64_t copies on a big-endian, + * but we cannot count on their alignment anyway. + */ + +#define fxdr_unsigned(t, v) ((t)ntohl(v)) +#define txdr_unsigned(v) (htonl(v)) + +#define fxdr_nfsv2time(f, t) \ +{ \ + (t)->tv_sec = ntohl(((struct nfsv2_time *)(f))->nfsv2_sec); \ + if (((struct nfsv2_time *)(f))->nfsv2_usec != 0xffffffff) \ + (t)->tv_nsec = 1000 * ntohl(((struct nfsv2_time *)(f))->nfsv2_usec); \ + else \ + (t)->tv_nsec = 0; \ +} + +#define txdr_nfsv2time(f, t) \ +{ \ + ((struct nfsv2_time *)(t))->nfsv2_sec = htonl((f)->tv_sec); \ + if ((f)->tv_nsec != -1) \ + ((struct nfsv2_time *)(t))->nfsv2_usec = htonl((f)->tv_nsec / 1000); \ + else \ + ((struct nfsv2_time *)(t))->nfsv2_usec = 0xffffffff; \ +} + +#define fxdr_nfsv3time(f, t) \ +{ \ + (t)->tv_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \ + (t)->tv_nsec = ntohl(((struct nfsv3_time *)(f))->nfsv3_nsec); \ +} + +#define fxdr_nfsv3time2(f, t) { \ + (t)->nfsv3_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \ + (t)->nfsv3_nsec = ntohl(((struct nfsv3_time *)(f))->nfsv3_nsec); \ +} + +#define txdr_nfsv3time(f, t) \ +{ \ + ((struct nfsv3_time *)(t))->nfsv3_sec = htonl((f)->tv_sec); \ + ((struct nfsv3_time *)(t))->nfsv3_nsec = htonl((f)->tv_nsec); \ +} + +#define txdr_nfsv3time2(f, t) \ +{ \ + ((struct nfsv3_time *)(t))->nfsv3_sec = htonl((f)->nfsv3_sec); \ + ((struct nfsv3_time *)(t))->nfsv3_nsec = htonl((f)->nfsv3_nsec); \ +} + +#define fxdr_hyper(f) \ + ((((uint64_t)ntohl(((uint32_t *)(f))[0])) << 32) | \ + (uint64_t)(ntohl(((uint32_t *)(f))[1]))) + +#define txdr_hyper(f, t) \ +{ \ + ((uint32_t *)(t))[0] = htonl((uint32_t)((f) >> 32)); \ + ((uint32_t *)(t))[1] = htonl((uint32_t)((f) & 0xffffffff)); \ +} + +/* Macros for dealing with byte data saved in uint32_t aligned memory */ + +#define uint32_aligndown(b) ((b) & ~3) +#define uint32_alignup(b) (((b) + 3) & ~3) +#define uint32_increment(b) (((b) + 3) >> 2) + +#endif /* __FS_NFS_XDR_SUBS_H */ diff --git a/nuttx/fs/nxffs/Kconfig b/nuttx/fs/nxffs/Kconfig new file mode 100644 index 0000000000..b233e85ea0 --- /dev/null +++ b/nuttx/fs/nxffs/Kconfig @@ -0,0 +1,51 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config FS_NXFFS + bool "NXFFS file system" + default n + depends on !DISABLE_MOUNTPOINT + ---help--- + Enable NuttX FLASH file system (NXFF) support. + +if FS_NXFFS +config NXFFS_ERASEDSTATE + bool "FLASH erased state" + default n + ---help--- + The erased state of FLASH. + This must have one of the values of 0xff or 0x00. + Default: 0xff. + +config NXFFS_PACKTHRESHOLD + bool "Re-packing threshold" + default n + ---help--- + When packing flash file data, + don't both with file chunks smaller than this number of data bytes. + Default: 32. + +config NXFFS_MAXNAMLEN + bool "Maximum file name length" + default n + ---help--- + The maximum size of an NXFFS file name. + Default: 255. + +config NXFFS_TAILTHRESHOLD + bool "Tail threshold" + default n + ---help--- + clean-up can either mean + packing files together toward the end of the file or, if file are + deleted at the end of the file, clean up can simply mean erasing + the end of FLASH memory so that it can be re-used again. However, + doing this can also harm the life of the FLASH part because it can + mean that the tail end of the FLASH is re-used too often. This + threshold determines if/when it is worth erased the tail end of FLASH + and making it available for re-use (and possible over-wear). + Default: 8192. + +endif diff --git a/nuttx/fs/nxffs/Make.defs b/nuttx/fs/nxffs/Make.defs new file mode 100644 index 0000000000..a73950c3f6 --- /dev/null +++ b/nuttx/fs/nxffs/Make.defs @@ -0,0 +1,46 @@ +############################################################################ +# fs/nxffs/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name Nuttx nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_FS_NXFFS),y) +ASRCS += +CSRCS += nxffs_block.c nxffs_blockstats.c nxffs_cache.c nxffs_dirent.c \ + nxffs_dump.c nxffs_initialize.c nxffs_inode.c nxffs_ioctl.c \ + nxffs_open.c nxffs_pack.c nxffs_read.c nxffs_reformat.c \ + nxffs_stat.c nxffs_unlink.c nxffs_util.c nxffs_write.c + +# Argument for dependency checking + +NXFFSDEPPATH = --dep-path nxffs +endif diff --git a/nuttx/fs/nxffs/README.txt b/nuttx/fs/nxffs/README.txt new file mode 100755 index 0000000000..a257351107 --- /dev/null +++ b/nuttx/fs/nxffs/README.txt @@ -0,0 +1,171 @@ +NXFFS README +^^^^^^^^^^^^ + +This README file contains information about the implemenation of the NuttX +wear-leveling FLASH file system, NXFFS. + +Contents: + + General NXFFS organization + General operation + Headers + NXFFS Limitations + Multiple Writers + ioctls + Things to Do + +General NXFFS organization +========================== + +The following example assumes 4 logical blocks per FLASH erase block. The +actual relationship is determined by the FLASH geometry reported by the MTD +driver. + +ERASE LOGICAL Inodes begin with a inode header. inode may +BLOCK BLOCK CONTENTS be marked as "deleted," pending re-packing. + n 4*n --+--------------+ + |BBBBBBBBBBBBBB| Logic block header + |IIIIIIIIIIIIII| Inodes begin with a inode header + |DDDDDDDDDDDDDD| Data block containing inode data block + | (Inode Data) | + 4*n+1 --+--------------+ + |BBBBBBBBBBBBBB| Logic block header + |DDDDDDDDDDDDDD| Inodes may consist of multiple data blocks + | (Inode Data) | + |IIIIIIIIIIIIII| Next inode header + | | Possibly a few unused bytes at the end of a block + 4*n+2 --+--------------+ + |BBBBBBBBBBBBBB| Logic block header + |DDDDDDDDDDDDDD| + | (Inode Data) | + 4*n+3 --+--------------+ + |BBBBBBBBBBBBBB| Logic block header + |IIIIIIIIIIIIII| Next inode header + |DDDDDDDDDDDDDD| + | (Inode Data) | + n+1 4*(n+1) --+--------------+ + |BBBBBBBBBBBBBB| Logic block header + | | All FLASH is unused after the end of the final + | | inode. + --+--------------+ + +General operation +================= + + Inodes are written starting at the beginning of FLASH. As inodes are + deleted, they are marked as deleted but not removed. As new inodes are + written, allocations proceed to toward the end of the FLASH -- thus, + supporting wear leveling by using all FLASH blocks equally. + + When the FLASH becomes full (no more space at the end of the FLASH), a + re-packing operation must be performed: All inodes marked deleted are + finally removed and the remaining inodes are packed at the beginning of + the FLASH. Allocations then continue at the freed FLASH memory at the + end of the FLASH. + +Headers +======= + BLOCK HEADER: + The block header is used to determine if the block has every been + formatted and also indicates bad blocks which should never be used. + + INODE HEADER: + Each inode begins with an inode header that contains, among other things, + the name of the inode, the offset to the first data block, and the + length of the inode data. + + At present, the only kind of inode support is a file. So for now, the + term file and inode are interchangeable. + + INODE DATA HEADER: + Inode data is enclosed in a data header. For a given inode, there + is at most one inode data block per logical block. If the inode data + spans more than one logical block, then the inode data may be enclosed + in multiple data blocks, one per logical block. + +NXFFS Limitations +================= + +This implementation is very simple as, as a result, has several limitations +that you should be aware before opting to use NXFFS: + +1. Since the files are contiguous in FLASH and since allocations always + proceed toward the end of the FLASH, there can only be one file opened + for writing at a time. Multiple files may be opened for reading. + +2. Files may not be increased in size after they have been closed. The + O_APPEND open flag is not supported. + +3. Files are always written sequential. Seeking within a file opened for + writing will not work. + +4. There are no directories, however, '/' may be used within a file name + string providing some illusion of directories. + +5. Files may be opened for reading or for writing, but not both: The O_RDWR + open flag is not supported. + +6. The re-packing process occurs only during a write when the free FLASH + memory at the end of the FLASH is exhausted. Thus, occasionally, file + writing may take a long time. + +7. Another limitation is that there can be only a single NXFFS volume + mounted at any time. This has to do with the fact that we bind to + an MTD driver (instead of a block driver) and bypass all of the normal + mount operations. + +Multiple Writers +================ + +As mentioned in the limitations above, there can be only one file opened +for writing at a time. If one thread has a file opened for writing and +another thread attempts to open a file for writing, then that second +thread will be blocked and will have to wait for the first thread to +close the file. + +Such behavior may or may not be a problem for your application, depending +(1) how long the first thread keeps the file open for writing and (2) how +critical the behavior of the second thread is. Note that writing to FLASH +can always trigger a major FLASH reorganization and, hence, there is no +way to guarantee the first condition: The first thread may have the file +open for a long time even if it only intends to write a small amount. + +Also note that a deadlock condition would occur if the SAME thread +attempted to open two files for writing. The thread would would be +blocked waiting for itself to close the first file. + +ioctls +====== + +The file system supports to ioctls: + +FIOC_REFORMAT: Will force the flash to be erased and a fresh, empty + NXFFS file system to be written on it. +FIOC_OPTIMIZE: Will force immediate repacking of the file system. This + will increase the amount of wear on the FLASH if you use this! + +Things to Do +============ + +- The statfs() implementation is minimal. It whould have some calcuation + of the f_bfree, f_bavail, f_files, f_ffree return values. +- There are too many allocs and frees. More structures may need to be + pre-allocated. +- The file name is always extracted and held in allocated, variable-length + memory. The file name is not used during reading and eliminating the + file name in the entry structure would improve performance. +- There is a big inefficient in reading. On each read, the logic searches + for the read position from the beginning of the file each time. This + may be necessary whenever an lseek() is done, but not in general. Read + performance could be improved by keeping FLASH offset and read positional + information in the read open file structure. +- Fault tolerance must be improved. We need to be absolutely certain that + any FLASH errors do not cause the file system to behavior incorrectly. +- Wear leveling might be improved (?). Files are re-packed at the front + of FLASH as part of the clean-up operation. However, that means the files + that are not modified often become fixed in place at the beginning of + FLASH. This reduces the size of the pool moving files at the end of the + FLASH. As the file system becomes more filled with fixed files at the + front of the device, the level of wear on the blocks at the end of the + FLASH increases. + diff --git a/nuttx/fs/nxffs/nxffs.h b/nuttx/fs/nxffs/nxffs.h new file mode 100644 index 0000000000..616dc7197b --- /dev/null +++ b/nuttx/fs/nxffs/nxffs.h @@ -0,0 +1,1083 @@ +/**************************************************************************** + * fs/nxffs/nxffs.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_NXFFS_NXFFS_H +#define __FS_NXFFS_NXFFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* NXFFS Definitions ********************************************************/ +/* General NXFFS organization. The following example assumes 4 logical + * blocks per FLASH erase block. The actual relationship is determined by + * the FLASH geometry reported by the MTD driver. + * + * ERASE LOGICAL Inodes begin with a inode header. inode may + * BLOCK BLOCK CONTENTS be marked as "deleted," pending re-packing. + * n 4*n --+--------------+ + * |BBBBBBBBBBBBBB| Logic block header + * |IIIIIIIIIIIIII| Inodes begin with a inode header + * |DDDDDDDDDDDDDD| Data block containing inode data block + * | (Inode Data) | + * 4*n+1 --+--------------+ + * |BBBBBBBBBBBBBB| Logic block header + * |DDDDDDDDDDDDDD| Inodes may consist of multiple data blocks + * | (Inode Data) | + * |IIIIIIIIIIIIII| Next inode header + * | | Possibly a few unused bytes at the end of a block + * 4*n+2 --+--------------+ + * |BBBBBBBBBBBBBB| Logic block header + * |DDDDDDDDDDDDDD| + * | (Inode Data) | + * 4*n+3 --+--------------+ + * |BBBBBBBBBBBBBB| Logic block header + * |IIIIIIIIIIIIII| Next inode header + * |DDDDDDDDDDDDDD| + * | (Inode Data) | + * n+1 4*(n+1) --+--------------+ + * |BBBBBBBBBBBBBB| Logic block header + * | | All FLASH is unused after the end of the final + * | | inode. + * --+--------------+ + * + * General operation: + * Inodes are written starting at the beginning of FLASH. As inodes are + * deleted, they are marked as deleted but not removed. As new inodes are + * written, allocations proceed to toward the end of the FLASH -- thus, + * supporting wear leveling by using all FLASH blocks equally. + * + * When the FLASH becomes full (no more space at the end of the FLASH), a + * re-packing operation must be performed: All inodes marked deleted are + * finally removed and the remaining inodes are packed at the beginning of + * the FLASH. Allocations then continue at the freed FLASH memory at the + * end of the FLASH. + * + * BLOCK HEADER: + * The block header is used to determine if the block has every been + * formatted and also indicates bad blocks which should never be used. + * + * INODE HEADER: + * Each inode begins with an inode header that contains, among other things, + * the name of the inode, the offset to the first data block, and the + * length of the inode data. + * + * At present, the only kind of inode support is a file. So for now, the + * term file and inode are interchangeable. + * + * INODE DATA HEADER: + * Inode data is enclosed in a data header. For a given inode, there + * is at most one inode data block per logical block. If the inode data + * spans more than one logical block, then the inode data may be enclosed + * in multiple data blocks, one per logical block. + * + * NXFFS Limitations: + * 1. Since the files are contiguous in FLASH and since allocations always + * proceed toward the end of the FLASH, there can only be one file opened + * for writing at a time. Multiple files may be opened for reading. + * 2. Files may not be increased in size after they have been closed. The + * O_APPEND open flag is not supported. + * 3. Files are always written sequential. Seeking within a file opened for + * writing will not work. + * 4. There are no directories, however, '/' may be used within a file name + * string providing some illusion of directories. + * 5. Files may be opened for reading or for writing, but not both: The O_RDWR + * open flag is not supported. + * 6. The re-packing process occurs only during a write when the free FLASH + * memory at the end of the FLASH is exhausted. Thus, occasionally, file + * writing may take a long time. + * 7. Another limitation is that there can be only a single NXFFS volume + * mounted at any time. This has to do with the fact that we bind to + * an MTD driver (instead of a block driver) and bypass all of the normal + * mount operations. + */ + +/* Values for logical block state. Basically, there are only two, perhaps + * three, states: + * + * BLOCK_STATE_GOOD - The block is not known to be bad. + * BLOCK_STATE_BAD - An error was found on the block and it is marked bad. + * Other values - The block is bad and has an invalid state. + * + * Care is taken so that the GOOD to BAD transition only involves burning + * bits from the erased to non-erased state. + */ + +#define BLOCK_STATE_GOOD (CONFIG_NXFFS_ERASEDSTATE ^ 0x44) +#define BLOCK_STATE_BAD (CONFIG_NXFFS_ERASEDSTATE ^ 0x55) + +/* Values for NXFFS inode state. Similar there are 2 (maybe 3) inode states: + * + * INODE_STATE_FILE - The inode is a valid usuable, file + * INODE_STATE_DELETED - The inode has been deleted. + * Other values - The inode is bad and has an invalid state. + * + * Care is taken so that the VALID to DELETED transition only involves burning + * bits from the erased to non-erased state. + */ + +#define INODE_STATE_FILE (CONFIG_NXFFS_ERASEDSTATE ^ 0x22) +#define INODE_STATE_DELETED (CONFIG_NXFFS_ERASEDSTATE ^ 0xaa) + +/* Number of bytes in an the NXFFS magic sequences */ + +#define NXFFS_MAGICSIZE 4 + +/* When we allocate FLASH for a new inode data block, we will require that + * space is available to hold this minimum number of data bytes in addition + * to the size of the data block headeer. + */ + +#define NXFFS_MINDATA 16 + +/* Internal definitions *****************************************************/ +/* If we encounter this number of erased bytes, we assume that all of the + * flash beyond this point is erased. + */ + +#define NXFFS_NERASED 128 + +/* Quasi-standard definitions */ + +#ifndef MIN +# define MIN(a,b) (a < b ? a : b) +#endif + +#ifndef MAX +# define MAX(a,b) (a > b ? a : b) +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This structure defines each packed block on the FLASH media */ + +struct nxffs_block_s +{ + uint8_t magic[4]; /* 0-3: Magic number for valid block */ + uint8_t state; /* 4: Block state: See BLOCK_STATE_* */ +}; +#define SIZEOF_NXFFS_BLOCK_HDR 5 + +/* This structure defines each packed NXFFS inode header on the FLASH media */ + +struct nxffs_inode_s +{ + uint8_t magic[4]; /* 0-3: Magic number for valid inode */ + uint8_t state; /* 4: Inode state: See INODE_STATE_* */ + uint8_t namlen; /* 5: Length of the inode name */ + uint8_t noffs[4]; /* 6-9: FLASH offset to the file name */ + uint8_t doffs[4]; /* 10-13: FLASH offset to the first data block */ + uint8_t utc[4]; /* 14-17: Creation time */ + uint8_t crc[4]; /* 18-21: CRC32 */ + uint8_t datlen[4]; /* 22-25: Length of data in bytes */ +}; +#define SIZEOF_NXFFS_INODE_HDR 26 + +/* This structure defines each packed NXFFS data header on the FLASH media */ + +struct nxffs_data_s +{ + uint8_t magic[4]; /* 0-3: Magic number for valid data */ + uint8_t crc[4]; /* 4-7: CRC32 */ + uint8_t datlen[2]; /* 8-9: Length of data in bytes */ +}; +#define SIZEOF_NXFFS_DATA_HDR 10 + +/* This is an in-memory representation of the NXFFS inode as extracted from + * FLASH and with additional state information. + */ + +struct nxffs_entry_s +{ + off_t hoffset; /* FLASH offset to the inode header */ + off_t noffset; /* FLASH offset to the inode name */ + off_t doffset; /* FLASH offset to the first data header */ + FAR char *name; /* inode name */ + uint32_t utc; /* Time stamp */ + uint32_t datlen; /* Length of inode data */ +}; + +/* This structure describes int in-memory representation of the data block */ + +struct nxffs_blkentry_s +{ + off_t hoffset; /* Offset to the block data header */ + uint16_t datlen; /* Length of data following the header */ + uint16_t foffset; /* Offset to start of data */ +}; + +/* This structure describes the state of one open file. This structure + * is protected by the volume semaphore. + */ + +struct nxffs_ofile_s +{ + struct nxffs_ofile_s *flink; /* Supports a singly linked list */ + int16_t crefs; /* Reference count */ + mode_t oflags; /* Open mode */ + struct nxffs_entry_s entry; /* Describes the NXFFS inode entry */ +}; + +/* A file opened for writing require some additional information */ + +struct nxffs_wrfile_s +{ + /* The following fields provide the common open file information. */ + + struct nxffs_ofile_s ofile; + + /* The following fields are required to support the write operation */ + + bool truncate; /* Delete a file of the same name */ + uint16_t datlen; /* Number of bytes written in data block */ + off_t doffset; /* FLASH offset to the current data header */ + uint32_t crc; /* Accumulated data block CRC */ +}; + +/* This structure represents the overall state of on NXFFS instance. */ + +struct nxffs_volume_s +{ + FAR struct mtd_dev_s *mtd; /* Supports FLASH access */ + sem_t exclsem; /* Used to assure thread-safe access */ + sem_t wrsem; /* Enforces single writer restriction */ + struct mtd_geometry_s geo; /* Device geometry */ + uint8_t blkper; /* R/W blocks per erase block */ + uint16_t iooffset; /* Next offset in read/write access (in ioblock) */ + off_t inoffset; /* Offset to the first valid inode header */ + off_t froffset; /* Offset to the first free byte */ + off_t nblocks; /* Number of R/W blocks on volume */ + off_t ioblock; /* Current block number being accessed */ + off_t cblock; /* Starting block number in cache */ + FAR struct nxffs_ofile_s *ofiles; /* A singly-linked list of open files */ + FAR uint8_t *cache; /* On cached erase block for general I/O */ + FAR uint8_t *pack; /* A full erase block to support packing */ +}; + +/* This structure describes the state of the blocks on the NXFFS volume */ + +struct nxffs_blkstats_s +{ + off_t nblocks; /* Total number of FLASH blocks */ + off_t ngood; /* Number of good FLASH blocks found */ + off_t nbad; /* Number of well-formatted FLASH blocks marked as bad */ + off_t nunformat; /* Number of unformatted FLASH blocks */ + off_t ncorrupt; /* Number of blocks with correupted format info */ +}; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* The magic number that appears that the beginning of each NXFFS (logical) + * block + */ + +extern const uint8_t g_blockmagic[NXFFS_MAGICSIZE]; + +/* The magic number that appears that the beginning of each NXFFS inode */ + +extern const uint8_t g_inodemagic[NXFFS_MAGICSIZE]; + +/* The magic number that appears that the beginning of each NXFFS inode + * data block. + */ + +extern const uint8_t g_datamagic[NXFFS_MAGICSIZE]; + +/* If CONFIG_NXFSS_PREALLOCATED is defined, then this is the single, pre- + * allocated NXFFS volume instance. + */ + +#ifdef CONFIG_NXFSS_PREALLOCATED +extern struct nxffs_volume_s g_volume; +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_limits + * + * Description: + * Recalculate file system limits: (1) the FLASH offset to the first, + * valid inode, and (2) the FLASH offset to the first, unused byte after + * the last inode (invalid or not). + * + * The first, lower limit must be recalculated: (1) initially, (2) + * whenever the first inode is deleted, or (3) whenever inode is moved + * as part of the file system packing operation. + * + * The second, upper limit must be (1) incremented whenever new file + * data is written, or (2) recalculated as part of the file system packing + * operation. + * + * Input Parameters: + * volume - Identifies the NXFFS volume + * + * Returned Value: + * Zero on success. Otherwise, a negated error is returned indicating the + * nature of the failure. + * + * Defined in nxffs_initialize.c + * + ****************************************************************************/ + +extern int nxffs_limits(FAR struct nxffs_volume_s *volume); + +/**************************************************************************** + * Name: nxffs_rdle16 + * + * Description: + * Get a (possibly unaligned) 16-bit little endian value. + * + * Input Parameters: + * val - A pointer to the first byte of the little endian value. + * + * Returned Values: + * A uint16_t representing the whole 16-bit integer value + * + * Defined in nxffs_util.c + * + ****************************************************************************/ + +extern uint16_t nxffs_rdle16(FAR const uint8_t *val); + +/**************************************************************************** + * Name: nxffs_wrle16 + * + * Description: + * Put a (possibly unaligned) 16-bit little endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the little endian value. + * val - The 16-bit value to be saved. + * + * Returned Values: + * None + * + * Defined in nxffs_util.c + * + ****************************************************************************/ + +extern void nxffs_wrle16(uint8_t *dest, uint16_t val); + +/**************************************************************************** + * Name: nxffs_rdle32 + * + * Description: + * Get a (possibly unaligned) 32-bit little endian value. + * + * Input Parameters: + * val - A pointer to the first byte of the little endian value. + * + * Returned Values: + * A uint32_t representing the whole 32-bit integer value + * + * Defined in nxffs_util.c + * + ****************************************************************************/ + +extern uint32_t nxffs_rdle32(FAR const uint8_t *val); + +/**************************************************************************** + * Name: nxffs_wrle32 + * + * Description: + * Put a (possibly unaligned) 32-bit little endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the little endian value. + * val - The 32-bit value to be saved. + * + * Returned Value: + * None + * + * Defined in nxffs_util.c + * + ****************************************************************************/ + +extern void nxffs_wrle32(uint8_t *dest, uint32_t val); + +/**************************************************************************** + * Name: nxffs_erased + * + * Description: + * Check if a block of memory is in the erased state. + * + * Input Parameters: + * buffer - Address of the start of the memory to check. + * buflen - The number of bytes to check. + * + * Returned Values: + * The number of erased bytes found at the beginning of the memory region. + * + * Defined in nxffs_util.c + * + ****************************************************************************/ + +extern size_t nxffs_erased(FAR const uint8_t *buffer, size_t buflen); + +/**************************************************************************** + * Name: nxffs_rdcache + * + * Description: + * Read one I/O block into the volume cache memory. + * + * Input Parameters: + * volume - Describes the current volume + * block - The first logical block to read + * + * Returned Value: + * Negated errnos are returned only in the case of MTD reported failures. + * Nothing in the volume data itself will generate errors. + * + * Defined in nxffs_cache.c + * + ****************************************************************************/ + +extern int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block); + +/**************************************************************************** + * Name: nxffs_wrcache + * + * Description: + * Write one or more logical blocks from the volume cache memory. + * + * Input Parameters: + * volume - Describes the current volume + * + * Returned Value: + * Negated errnos are returned only in the case of MTD reported failures. + * + * Defined in nxffs_cache.c + * + ****************************************************************************/ + +extern int nxffs_wrcache(FAR struct nxffs_volume_s *volume); + +/**************************************************************************** + * Name: nxffs_ioseek + * + * Description: + * Seek to a position in FLASH memory. This simply sets up the offsets + * and pointer values. This is a necessary step prior to using + * nxffs_getc(). + * + * Input Parameters: + * volume - Describes the NXFFS volume + * offset - The physical offset in bytes from the beginning of the FLASH + * in bytes. + * + * Defined in nxffs_cache.c + * + ****************************************************************************/ + +extern void nxffs_ioseek(FAR struct nxffs_volume_s *volume, off_t offset); + +/**************************************************************************** + * Name: nxffs_iotell + * + * Description: + * Report the current position. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * + * Returned Value: + * The offset from the beginning of FLASH to the current seek position. + * + * Defined in nxffs_cache.c + * + ****************************************************************************/ + +extern off_t nxffs_iotell(FAR struct nxffs_volume_s *volume); + +/**************************************************************************** + * Name: nxffs_getc + * + * Description: + * Get the next byte from FLASH. This function allows the data in the + * formatted FLASH blocks to be read as a continuous byte stream, skipping + * over bad blocks and block headers as necessary. + * + * Input Parameters: + * volume - Describes the NXFFS volume. The paramters ioblock and iooffset + * in the volume structure determine the behavior of nxffs_getc(). + * reserve - If less than this much space is available at the end of the + * block, then skip to the next block. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno indicating the + * nature of the failure. + * + * Defined in nxffs_cache.c + * + ****************************************************************************/ + +extern int nxffs_getc(FAR struct nxffs_volume_s *volume, uint16_t reserve); + +/**************************************************************************** + * Name: nxffs_freeentry + * + * Description: + * The inode values returned by nxffs_nextentry() include allocated memory + * (specifically, the file name string). This function should be called + * to dispose of that memory when the inode entry is no longer needed. + * + * Note that the nxffs_entry_s containing structure is not freed. The + * caller may call kfree upon return of this function if necessary to + * free the entry container. + * + * Input parameters: + * entry - The entry to be freed. + * + * Returned Value: + * None + * + * Defined in nxffs_inode.c + * + ****************************************************************************/ + +extern void nxffs_freeentry(FAR struct nxffs_entry_s *entry); + +/**************************************************************************** + * Name: nxffs_nextentry + * + * Description: + * Search for the next valid inode starting at the provided FLASH offset. + * + * Input Parameters: + * volume - Describes the NXFFS volume. + * offset - The FLASH memory offset to begin searching. + * entry - A pointer to memory provided by the caller in which to return + * the inode description. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno is returned + * that indicates the nature of the failure. + * + * Defined in nxffs_inode.c + * + ****************************************************************************/ + +extern int nxffs_nextentry(FAR struct nxffs_volume_s *volume, off_t offset, + FAR struct nxffs_entry_s *entry); + +/**************************************************************************** + * Name: nxffs_findinode + * + * Description: + * Search for an inode with the provided name starting with the first + * valid inode and proceeding to the end FLASH or until the matching + * inode is found. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * name - The name of the inode to find + * entry - The location to return information about the inode. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno is returned + * that indicates the nature of the failure. + * + * Defined in nxffs_inode.c + * + ****************************************************************************/ + +extern int nxffs_findinode(FAR struct nxffs_volume_s *volume, + FAR const char *name, + FAR struct nxffs_entry_s *entry); + +/**************************************************************************** + * Name: nxffs_inodeend + * + * Description: + * Return an *approximiate* FLASH offset to end of the inode data. The + * returned value is guaranteed to be be less then or equal to the offset + * of the thing-of-interest in FLASH. Parsing for interesting things + * can begin at that point. + * + * Assumption: The inode header has been verified by the caller and is + * known to contain valid data. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * entry - Describes the inode. + * + * Returned Value: + * A FLASH offset to the (approximate) end of the inode data. No errors + * are detected. + * + * Defined in nxffs_inode.c + * + ****************************************************************************/ + +extern off_t nxffs_inodeend(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_entry_s *entry); + +/**************************************************************************** + * Name: nxffs_verifyblock + * + * Description: + * Assure the the provided (logical) block number is in the block cache + * and that it has a valid block header (i.e., proper magic and + * marked good) + * + * Input Parameters: + * volume - Describes the NXFFS volume + * block - The (logical) block number to load and verify. + * + * Returned Values: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. + * + * Defined in nxffs_block.c + * + ****************************************************************************/ + +extern int nxffs_verifyblock(FAR struct nxffs_volume_s *volume, off_t block); + +/**************************************************************************** + * Name: nxffs_validblock + * + * Description: + * Find the next valid (logical) block in the volume. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * block - On entry, this provides the starting block number. If the + * function is succesfful, then this memory location will hold the + * block number of the next valid block on return. + * + * Returned Value: + * Zero on success otherwise a negated errno value indicating the nature + * of the failure. + * + * Defined in nxffs_block.c + * + ****************************************************************************/ + +extern int nxffs_validblock(struct nxffs_volume_s *volume, off_t *block); + +/**************************************************************************** + * Name: nxffs_blockstats + * + * Description: + * Analyze the NXFFS volume. This operation must be performed when the + * volume is first mounted in order to detect if the volume has been + * formatted and contains a usable NXFFS file system. + * + * Input Parameters: + * volume - Describes the current NXFFS volume. + * stats - On return, will hold nformation describing the state of the + * volume. + * + * Returned Value: + * Negated errnos are returned only in the case of MTD reported failures. + * Nothing in the volume data itself will generate errors. + * + * Defined in nxffs_blockstats.c + * + ****************************************************************************/ + +extern int nxffs_blockstats(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_blkstats_s *stats); + +/**************************************************************************** + * Name: nxffs_reformat + * + * Description: + * Erase and reformat the entire volume. Verify each block and mark + * improperly erased blocks as bad. + * + * Input Parameters: + * volume - Describes the NXFFS volume to be reformatted. + * + * Returned Value: + * Zero on success or a negated errno on a failure. Failures will be + * returned n the case of MTD reported failures o. + * Nothing in the volume data itself will generate errors. + * + * Defined in nxffs_reformat.c + * + ****************************************************************************/ + +extern int nxffs_reformat(FAR struct nxffs_volume_s *volume); + +/**************************************************************************** + * Name: nxffs_findofile + * + * Description: + * Search the list of already opened files to see if the inode of this + * name is one of the opened files. + * + * Input Parameters: + * volume - Describes the NXFFS volume. + * name - The name of the inode to check. + * + * Returned Value: + * If an inode of this name is found in the list of opened inodes, then + * a reference to the open file structure is returned. NULL is returned + * otherwise. + * + * Defined in nxffs_open.c + * + ****************************************************************************/ + +extern FAR struct nxffs_ofile_s *nxffs_findofile(FAR struct nxffs_volume_s *volume, + FAR const char *name); + +/**************************************************************************** + * Name: nxffs_findwriter + * + * Description: + * Search the list of already opened files and return the open file + * instance for the write. + * + * Input Parameters: + * volume - Describes the NXFFS volume. + * + * Returned Value: + * If there is an active writer of the volume, its open file instance is + * returned. NULL is returned otherwise. + * + * Defined in nxffs_open.c + * + ****************************************************************************/ + +extern FAR struct nxffs_wrfile_s *nxffs_findwriter(FAR struct nxffs_volume_s *volume); + +/**************************************************************************** + * Name: nxffs_wrinode + * + * Description: + * Write the inode header (only to FLASH. This is done in two contexts: + * + * 1. When an inode is closed, or + * 2. As part of the file system packing logic when an inode is moved. + * + * Note that in either case, the inode name has already been written to + * FLASH. + * + * Input parameters + * volume - Describes the NXFFS volume + * entry - Describes the inode header to write + * + * Returned Value: + * Zero is returned on success; Otherwise, a negated errno value is returned + * indicating the nature of the failure. + * + * Defined in nxffs_open.c + * + ****************************************************************************/ + +extern int nxffs_wrinode(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_entry_s *entry); + +/**************************************************************************** + * Name: nxffs_updateinode + * + * Description: + * The packing logic has moved an inode. Check if any open files are using + * this inode and, if so, move the data in the open file structure as well. + * + * Input parameters + * volume - Describes the NXFFS volume + * entry - Describes the new inode entry + * + * Returned Value: + * Zero is returned on success; Otherwise, a negated errno value is returned + * indicating the nature of the failure. + * + ****************************************************************************/ + +extern int nxffs_updateinode(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_entry_s *entry); + +/**************************************************************************** + * Name: nxffs_wrreserve + * + * Description: + * Find a valid location for a file system object of 'size'. A valid + * location will have these properties: + * + * 1. It will lie in the free flash region. + * 2. It will have enough contiguous memory to hold the entire object + * 3. The memory at this location will be fully erased. + * + * This function will only perform the checks of 1) and 2). The + * end-of-filesystem offset, froffset, is update past this memory which, + * in effect, reserves the memory. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * size - The size of the object to be reserved. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. Of special interest + * the return error of -ENOSPC which means that the FLASH volume is + * full and should be repacked. + * + * On successful return the following are also valid: + * + * volume->ioblock - Read/write block number of the block containing the + * candidate oject position + * volume->iooffset - The offset in the block to the candidate object + * position. + * volume->froffset - Updated offset to the first free FLASH block after + * the reserved memory. + * + * Defined in nxffs_write.c + * + ****************************************************************************/ + +extern int nxffs_wrreserve(FAR struct nxffs_volume_s *volume, size_t size); + +/**************************************************************************** + * Name: nxffs_wrverify + * + * Description: + * Find a valid location for the object. A valid location will have + * these properties: + * + * 1. It will lie in the free flash region. + * 2. It will have enough contiguous memory to hold the entire header + * (excluding the file name which may lie in the next block). + * 3. The memory at this location will be fully erased. + * + * This function will only perform the check 3). On entry it assumes the + * following settings (left by nxffs_wrreserve()): + * + * volume->ioblock - Read/write block number of the block containing the + * candidate oject position + * volume->iooffset - The offset in the block to the candidate object + * position. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * size - The size of the object to be verifed. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. Of special interest + * the return error of -ENOSPC which means that the FLASH volume is + * full and should be repacked. + * + * On successful return the following are also valid: + * + * volume->ioblock - Read/write block number of the block containing the + * verified object position + * volume->iooffset - The offset in the block to the verified object + * position. + * volume->froffset - Updated offset to the first free FLASH block. + * + * Defined in nxffs_write.c + * + ****************************************************************************/ + +extern int nxffs_wrverify(FAR struct nxffs_volume_s *volume, size_t size); + +/**************************************************************************** + * Name: nxffs_wrblkhdr + * + * Description: + * Write the block header information. This is done (1) whenever the end- + * block is encountered and (2) also when the file is closed in order to + * flush the final block of data to FLASH. + * + * Input Parameters: + * volume - Describes the state of the NXFFS volume + * wrfile - Describes the state of the open file + * + * Returned Value: + * Zero is returned on success; Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + * Defined in nxffs_write.c + * + ****************************************************************************/ + +extern int nxffs_wrblkhdr(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_wrfile_s *wrfile); + +/**************************************************************************** + * Name: nxffs_nextblock + * + * Description: + * Search for the next valid data block starting at the provided + * FLASH offset. + * + * Input Parameters: + * volume - Describes the NXFFS volume. + * datlen - A memory location to return the data block length. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno is returned + * that indicates the nature of the failure. + * + * Defined in nxffs_read.c + * + ****************************************************************************/ + +extern int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset, + FAR struct nxffs_blkentry_s *blkentry); + +/**************************************************************************** + * Name: nxffs_rdblkhdr + * + * Description: + * Read and verify the data block header at the specified offset. + * + * Input Parameters: + * volume - Describes the current volume. + * offset - The byte offset from the beginning of FLASH where the data block + * header is expected. + * datlen - A memory location to return the data block length. + * + * Returned Value: + * Zero on success. Otherwise, a negated errno value is returned + * indicating the nature of the failure. + * + * Defined in nxffs_read.c + * + ****************************************************************************/ + +extern int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset, + FAR uint16_t *datlen); + +/**************************************************************************** + * Name: nxffs_rminode + * + * Description: + * Remove an inode from FLASH. This is the internal implementation of + * the file system unlinke operation. + * + * Input Parameters: + * volume - Describes the NXFFS volume. + * name - the name of the inode to be deleted. + * + * Returned Value: + * Zero is returned if the inode is successfully deleted. Otherwise, a + * negated errno value is returned indicating the nature of the failure. + * + ****************************************************************************/ + +extern int nxffs_rminode(FAR struct nxffs_volume_s *volume, FAR const char *name); + +/**************************************************************************** + * Name: nxffs_pack + * + * Description: + * Pack and re-write the filesystem in order to free up memory at the end + * of FLASH. + * + * Input Parameters: + * volume - The volume to be packed. + * + * Returned Values: + * Zero on success; Otherwise, a negated errno value is returned to + * indicate the nature of the failure. + * + ****************************************************************************/ + +extern int nxffs_pack(FAR struct nxffs_volume_s *volume); + +/**************************************************************************** + * Standard mountpoint operation methods + * + * Description: + * See include/nuttx/fs/fs.h + * + * - nxffs_open() and nxffs_close() are defined in nxffs_open.c + * - nxffs_read() is defined in nxffs_read.c + * - nxffs_write() is defined in nxffs_write.c + * - nxffs_ioctl() is defined in nxffs_ioctl.c + * - nxffs_opendir(), nxffs_readdir(), and nxffs_rewindir() are defined in + * nxffs_dirent.c + * - nxffs_bind() and nxffs_unbind() are defined in nxffs_initialize.c + * - nxffs_stat() and nxffs_statfs() are defined in nxffs_stat.c + * - nxffs_unlink() is defined nxffs_unlink.c + * + ****************************************************************************/ + +struct file; /* Forward references */ +struct inode; +struct fs_dirent_s; +struct statfs; +struct stat; + +extern int nxffs_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode); +extern int nxffs_close(FAR struct file *filep); +extern ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +extern ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +extern int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +extern int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath, + FAR struct fs_dirent_s *dir); +extern int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); +extern int nxffs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); +extern int nxffs_bind(FAR struct inode *blkdriver, FAR const void *data, + FAR void **handle); +extern int nxffs_unbind(FAR void *handle, FAR struct inode **blkdriver); +extern int nxffs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf); +extern int nxffs_stat(FAR struct inode *mountpt, FAR const char *relpath, + FAR struct stat *buf); +extern int nxffs_unlink(FAR struct inode *mountpt, FAR const char *relpath); + +#endif /* __FS_NXFFS_NXFFS_H */ + + diff --git a/nuttx/fs/nxffs/nxffs_block.c b/nuttx/fs/nxffs/nxffs_block.c new file mode 100644 index 0000000000..a069048b89 --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_block.c @@ -0,0 +1,186 @@ +/**************************************************************************** + * fs/nxffs/nxffs_block.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_verifyblock + * + * Description: + * Assure the the provided (logical) block number is in the block cache + * and that it has a valid block header (i.e., proper magic and + * marked good) + * + * Input Parameters: + * volume - Describes the NXFFS volume + * block - The (logical) block number to load and verify. + * + * Returned Values: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. -ENOENT is returned + * if the block is a bad block. + * + ****************************************************************************/ + +int nxffs_verifyblock(FAR struct nxffs_volume_s *volume, off_t block) +{ + FAR struct nxffs_block_s *blkhdr; + int ret; + + /* Make sure the the block is in the cache */ + + ret = nxffs_rdcache(volume, block); + if (ret < 0) + { + /* Perhaps we are at the end of the media */ + + fvdbg("Failed to read data into cache: %d\n", ret); + return ret; + } + + /* Check if the block has a magic number (meaning that it is not + * erased) and that it is valid (meaning that it is not marked + * for deletion) + */ + + blkhdr = (FAR struct nxffs_block_s *)volume->cache; + if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) == 0) + { + /* This does appear to be a block */ + + if (blkhdr->state == BLOCK_STATE_GOOD) + { + /* The block is valid */ + + return OK; + } + else if (blkhdr->state == BLOCK_STATE_BAD) + { + /* -ENOENT is a special indication that this is a properly marked + * bad block + */ + + return -ENOENT; + } + } + + /* Whatever is here where a block header should be is invalid */ + + return -EINVAL; +} + +/**************************************************************************** + * Name: nxffs_validblock + * + * Description: + * Find the next valid (logical) block in the volume. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * block - On entry, this provides the starting block number. If the + * function is succesfful, then this memory location will hold the + * block number of the next valid block on return. + * + * Returned Value: + * Zero on success otherwise a negated errno value indicating the nature + * of the failure. + * + ****************************************************************************/ + +int nxffs_validblock(struct nxffs_volume_s *volume, off_t *block) +{ + off_t i; + int ret; + + DEBUGASSERT(volume && block); + + /* Loop for each possible block or until a valid block is found */ + + for (i = *block; i < volume->nblocks; i++) + { + /* Loop until we find a valid block */ + + ret = nxffs_verifyblock(volume, i); + if (ret == OK) + { + /* We found it, return the block number */ + + *block = i; + return OK; + } + } + + /* ENOSPC is special return value that means that there is no further, + * valid blocks left in the volume. + */ + + fdbg("No valid block found\n"); + return -ENOSPC; +} diff --git a/nuttx/fs/nxffs/nxffs_blockstats.c b/nuttx/fs/nxffs/nxffs_blockstats.c new file mode 100644 index 0000000000..590aa2ad03 --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_blockstats.c @@ -0,0 +1,152 @@ +/**************************************************************************** + * fs/nxffs/nxffs_blockstats.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_blockstats + * + * Description: + * Analyze the NXFFS volume. This operation must be performed when the + * volume is first mounted in order to detect if the volume has been + * formatted and contains a usable NXFFS file system. + * + * Input Parameters: + * volume - Describes the current NXFFS volume. + * stats - On return, will hold nformation describing the state of the + * volume. + * + * Returned Value: + * Negated errnos are returned only in the case of MTD reported failures. + * Nothing in the volume data itself will generate errors. + * + ****************************************************************************/ + +int nxffs_blockstats(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_blkstats_s *stats) +{ + FAR uint8_t *bptr; /* Pointer to next block data */ + off_t ioblock; /* I/O block number */ + int lblock; /* Logical block index */ + int ret; + + /* Process each erase block */ + + memset(stats, 0, sizeof(struct nxffs_blkstats_s)); + + for (ioblock = 0; ioblock < volume->nblocks; ioblock += volume->blkper) + { + /* Read the full erase block */ + + ret = MTD_BREAD(volume->mtd, ioblock, volume->blkper, volume->pack); + if (ret < volume->blkper) + { + fdbg("Failed to read erase block %d: %d\n", ioblock / volume->blkper, -ret); + return ret; + } + + /* Process each logical block */ + + for (bptr = volume->pack, lblock = 0; + lblock < volume->blkper; + bptr += volume->geo.blocksize, lblock++) + { + FAR struct nxffs_block_s *blkhdr = (FAR struct nxffs_block_s*)bptr; + + /* Collect statistics */ + + stats->nblocks++; + if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) != 0) + { + stats->nunformat++; + } + else if (blkhdr->state == BLOCK_STATE_BAD) + { + stats->nbad++; + } + else if (blkhdr->state == BLOCK_STATE_GOOD) + { + stats-> ngood++; + } + else + { + stats->ncorrupt++; + } + } + } + + fdbg("Number blocks: %d\n", stats->nblocks); + fdbg(" Good blocks: %d\n", stats->ngood); + fdbg(" Bad blocks: %d\n", stats->nbad); + fdbg(" Unformatted blocks: %d\n", stats->nunformat); + fdbg(" Corrupt blocks: %d\n", stats->ncorrupt); + return OK; +} + + diff --git a/nuttx/fs/nxffs/nxffs_cache.c b/nuttx/fs/nxffs/nxffs_cache.c new file mode 100644 index 0000000000..5c5cbaa187 --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_cache.c @@ -0,0 +1,261 @@ +/**************************************************************************** + * fs/nxffs/nxffs_cache.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_rdcache + * + * Description: + * Read one I/O block into the volume block cache memory. + * + * Input Parameters: + * volume - Describes the current volume + * block - The first logical block to read + * + * Returned Value: + * Negated errnos are returned only in the case of MTD reported failures. + * Nothing in the volume data itself will generate errors. + * + ****************************************************************************/ + +int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block) +{ + size_t nxfrd; + + /* Check if the requested data is already in the cache */ + + if (block != volume->cblock) + { + /* Read the specified blocks into cache */ + + nxfrd = MTD_BREAD(volume->mtd, block, 1, volume->cache); + if (nxfrd != 1) + { + fvdbg("Read block %d failed: %d\n", block, nxfrd); + return -EIO; + } + + /* Remember what is in the cache */ + + volume->cblock = block; + } + return OK; +} + +/**************************************************************************** + * Name: nxffs_wrcache + * + * Description: + * Write one or more logical blocks from the volume cache memory. + * + * Input Parameters: + * volume - Describes the current volume + * + * Returned Value: + * Negated errnos are returned only in the case of MTD reported failures. + * + ****************************************************************************/ + +int nxffs_wrcache(FAR struct nxffs_volume_s *volume) +{ + size_t nxfrd; + + /* Write the current block from the cache */ + + nxfrd = MTD_BWRITE(volume->mtd, volume->cblock, 1, volume->cache); + if (nxfrd != 1) + { + fdbg("Write block %d failed: %d\n", volume->cblock, nxfrd); + return -EIO; + } + + /* Write was successful */ + + return OK; +} + +/**************************************************************************** + * Name: nxffs_ioseek + * + * Description: + * Seek to a position in FLASH memory. This simply sets up the offsets + * and pointer values. This is a necessary step prior to using + * nxffs_getc(). + * + * Input Parameters: + * volume - Describes the NXFFS volume + * offset - The physical offset in bytes from the beginning of the FLASH + * in bytes. + * + ****************************************************************************/ + +void nxffs_ioseek(FAR struct nxffs_volume_s *volume, off_t offset) +{ + /* Convert the offset into a block number and a byte offset into the + * block. + */ + + volume->ioblock = offset / volume->geo.blocksize; + volume->iooffset = offset - volume->geo.blocksize * volume->ioblock; +} + +/**************************************************************************** + * Name: nxffs_iotell + * + * Description: + * Report the current position. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * + * Returned Value: + * The offset from the beginning of FLASH to the current seek position. + * + ****************************************************************************/ + +off_t nxffs_iotell(FAR struct nxffs_volume_s *volume) +{ + return volume->ioblock * volume->geo.blocksize + volume->iooffset; +} + +/**************************************************************************** + * Name: nxffs_getc + * + * Description: + * Get the next byte from FLASH. This function allows the data in the + * formatted FLASH blocks to be read as a continuous byte stream, skipping + * over bad blocks and block headers as necessary. + * + * Input Parameters: + * volume - Describes the NXFFS volume. The paramters ioblock and iooffset + * in the volume structure determine the behavior of nxffs_getc(). + * reserve - If less than this much space is available at the end of the + * block, then skip to the next block. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno indicating the + * nature of the failure. + * + ****************************************************************************/ + +int nxffs_getc(FAR struct nxffs_volume_s *volume, uint16_t reserve) +{ + int ret; + + DEBUGASSERT(reserve > 0); + + /* Loop to skip over bad blocks */ + + do + { + /* Check if we have the reserve amount at the end of the current block */ + + if (volume->iooffset + reserve > volume->geo.blocksize) + { + /* Check for attempt to read past the end of FLASH */ + + off_t nextblock = volume->ioblock + 1; + if (nextblock >= volume->nblocks) + { + fvdbg("End of FLASH encountered\n"); + return -ENOSPC; + } + + /* Set up the seek to the data just after the header in the + * next block. + */ + + volume->ioblock = nextblock; + volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR; + } + + /* Make sure that the block is in the cache. The special error + * -ENOENT indicates the block was read successfully but was not + * marked as a good block. In this case we need to skip to the + * next block. All other errors are fatal. + */ + + ret = nxffs_verifyblock(volume, volume->ioblock); + if (ret < 0 && ret != -ENOENT) + { + fvdbg("Failed to read valid data into cache: %d\n", ret); + return ret; + } + } + while (ret != OK); + + /* Return the the character at this offset. Note that on return, + * iooffset could point to the byte outside of the current block. + */ + + ret = (int)volume->cache[volume->iooffset]; + volume->iooffset++; + return ret; +} diff --git a/nuttx/fs/nxffs/nxffs_dirent.c b/nuttx/fs/nxffs/nxffs_dirent.c new file mode 100644 index 0000000000..562a5320b9 --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_dirent.c @@ -0,0 +1,217 @@ +/**************************************************************************** + * fs/nxffs/nxffs_dirent.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_opendir + * + * Description: + * Open a directory for read access + * + ****************************************************************************/ + +int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath, + FAR struct fs_dirent_s *dir) +{ + struct nxffs_volume_s *volume; + int ret; + + fvdbg("relpath: \"%s\"\n", relpath ? relpath : "NULL"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover the file system state from the NuttX inode instance */ + + volume = mountpt->i_private; + ret = sem_wait(&volume->exclsem); + if (ret != OK) + { + goto errout; + } + + /* The requested directory must be the volume-relative "root" directory */ + + if (relpath && relpath[0] != '\0') + { + ret = -ENOENT; + goto errout_with_semaphore; + } + + /* Set the offset to the offset to the first valid inode */ + + dir->u.nxffs.nx_offset = volume->inoffset; + ret = OK; + +errout_with_semaphore: + sem_post(&volume->exclsem); +errout: + return ret; +} + +/**************************************************************************** + * Name: nxffs_readdir + * + * Description: Read the next directory entry + * + ****************************************************************************/ + +int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir) +{ + FAR struct nxffs_volume_s *volume; + FAR struct nxffs_entry_s entry; + off_t offset; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover the file system state from the NuttX inode instance */ + + volume = mountpt->i_private; + ret = sem_wait(&volume->exclsem); + if (ret != OK) + { + goto errout; + } + + /* Read the next inode header from the offset */ + + offset = dir->u.nxffs.nx_offset; + ret = nxffs_nextentry(volume, offset, &entry); + + /* If the read was successful, then handle the reported inode. Note + * that when the last inode has been reported, the value -ENOENT will + * be returned.. which is correct for the readdir() method. + */ + + if (ret == OK) + { + /* Return the filename and file type */ + + fvdbg("Offset %d: \"%s\"\n", entry.hoffset, entry.name); + dir->fd_dir.d_type = DTYPE_FILE; + strncpy(dir->fd_dir.d_name, entry.name, NAME_MAX+1); + + /* Discard this entry and set the next offset. */ + + dir->u.nxffs.nx_offset = nxffs_inodeend(volume, &entry); + nxffs_freeentry(&entry); + ret = OK; + } + + sem_post(&volume->exclsem); +errout: + return ret; +} + +/**************************************************************************** + * Name: nxffs_rewindir + * + * Description: + * Reset directory read to the first entry + * + ****************************************************************************/ + +int nxffs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir) +{ + FAR struct nxffs_volume_s *volume; + int ret; + + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover the file system state from the NuttX inode instance */ + + volume = mountpt->i_private; + ret = sem_wait(&volume->exclsem); + if (ret != OK) + { + goto errout; + } + + /* Reset the offset to the FLASH offset to the first valid inode */ + + dir->u.nxffs.nx_offset = volume->inoffset; + ret = OK; + + sem_post(&volume->exclsem); +errout: + return ret; +} diff --git a/nuttx/fs/nxffs/nxffs_dump.c b/nuttx/fs/nxffs/nxffs_dump.c new file mode 100644 index 0000000000..d816ba6ca9 --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_dump.c @@ -0,0 +1,479 @@ +/**************************************************************************** + * fs/nxffs/nxffs_dump.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Re-define fdbg so that the output does not have so much diagnostic info. + * This should still, however, always agree with the defintion in debug.h. + */ + +#undef fdbg +#define fdbg lib_rawprintf + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nxffs_blkinfo_s +{ + struct mtd_geometry_s geo; + FAR uint8_t *buffer; + off_t nblocks; + off_t block; + off_t offset; + bool verbose; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char g_hdrformat[] = " BLOCK:OFFS TYPE STATE LENGTH\n"; +static const char g_format[] = " %5d:%-5d %s %s %5d\n"; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_analyzeinode + * + * Description: + * Analyze one candidate inode found in the block. + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_FS) +static inline ssize_t nxffs_analyzeinode(FAR struct nxffs_blkinfo_s *blkinfo, + int offset) +{ + FAR struct nxffs_inode_s inode; + off_t nextblock; + uint8_t state; + uint32_t noffs; + uint32_t doffs; + uint32_t utc; + uint32_t ecrc; + uint32_t datlen; + uint32_t crc; + size_t spaceleft; + + /* Verify that there is space for an inode header remaining in the block */ + + if (offset + SIZEOF_NXFFS_INODE_HDR > blkinfo->geo.blocksize) + { + /* No.. then this can't be an inode header */ + + return ERROR; + } + + /* Unpack the header */ + + memcpy(&inode, &blkinfo->buffer[offset], SIZEOF_NXFFS_INODE_HDR); + noffs = nxffs_rdle32(inode.noffs); + doffs = nxffs_rdle32(inode.doffs); + utc = nxffs_rdle32(inode.utc); + ecrc = nxffs_rdle32(inode.crc); + datlen = nxffs_rdle32(inode.datlen); + + /* Misc. sanity checks */ + + if (noffs < blkinfo->offset + offset + SIZEOF_NXFFS_BLOCK_HDR) + { + /* The name begins before the inode header. This can't can't be + * a real inode header (or it is a corrupted one). + */ + + return ERROR; + } + + + /* Can we verify the inode? We need to have the inode name in the same + * block to do that (or get access to the next block) + */ + + if (doffs < blkinfo->offset + offset + SIZEOF_NXFFS_BLOCK_HDR) + { + /* The first data block begins before the inode header. This can't can't + * be a real inode header (or it is a corrupted one). + */ + + return ERROR; + } + + spaceleft = (blkinfo->nblocks - blkinfo->block) * blkinfo->geo.blocksize; + spaceleft -= (offset + SIZEOF_NXFFS_BLOCK_HDR); + if (datlen > spaceleft) + { + /* The data length is greater than what would fit in the rest of FLASH + * (even ignoring block and data header sizes. + */ + + return ERROR; + } + + /* The name begins after the inode header. Does it begin in this block? */ + + nextblock = blkinfo->offset + blkinfo->geo.blocksize; + if (noffs > nextblock) + { + /* Not than we cannot verify the inode header */ + + if (blkinfo->verbose) + { + fdbg(g_format, blkinfo->block, offset, "INODE", "UNVERFD", datlen); + } + return ERROR; + } + + /* The name begins in this block. Does it also end in this block? */ + + if (noffs + inode.namlen > nextblock) + { + /* No.. Assume that this is not an inode. */ + + return ERROR; + } + + /* Calculate the CRC */ + + state = inode.state; + inode.state = CONFIG_NXFFS_ERASEDSTATE; + nxffs_wrle32(inode.crc, 0); + + crc = crc32((FAR const uint8_t *)&inode, SIZEOF_NXFFS_INODE_HDR); + crc = crc32part(&blkinfo->buffer[noffs - blkinfo->offset], inode.namlen, crc); + + if (crc != ecrc) + { + fdbg(g_format, blkinfo->block, offset, "INODE", "CRC BAD", datlen); + return ERROR; + } + + /* If must be a good header */ + + if (state == INODE_STATE_FILE) + { + if (blkinfo->verbose) + { + fdbg(g_format, blkinfo->block, offset, "INODE", "OK ", datlen); + } + } + else if (state == INODE_STATE_DELETED) + { + if (blkinfo->verbose) + { + fdbg(g_format, blkinfo->block, offset, "INODE", "DELETED", datlen); + } + } + else + { + fdbg(g_format, blkinfo->block, offset, "INODE", "CORRUPT", datlen); + } + + /* Return the block-relative offset to the next byte after the inode name */ + + return noffs + inode.namlen - offset - blkinfo->offset; +} +#endif + +/**************************************************************************** + * Name: nxffs_analyzedata + * + * Description: + * Analyze one candidate inode found in the block. + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_FS) +static inline ssize_t nxffs_analyzedata(FAR struct nxffs_blkinfo_s *blkinfo, + int offset) +{ + struct nxffs_data_s dathdr; + uint32_t ecrc; + uint16_t datlen; + uint32_t crc; + + /* Copy and unpack the data block header */ + + memcpy(&dathdr, &blkinfo->buffer[offset], SIZEOF_NXFFS_DATA_HDR); + ecrc = nxffs_rdle32(dathdr.crc); + datlen = nxffs_rdle16(dathdr.datlen); + + /* Sanity checks */ + + if (offset + SIZEOF_NXFFS_DATA_HDR + datlen > blkinfo->geo.blocksize) + { + /* Data does not fit in within the block, this can't be a data block */ + + return ERROR; + } + + /* Calculate the CRC */ + + nxffs_wrle32(dathdr.crc, 0); + + crc = crc32((FAR const uint8_t *)&dathdr, SIZEOF_NXFFS_DATA_HDR); + crc = crc32part(&blkinfo->buffer[offset + SIZEOF_NXFFS_DATA_HDR], datlen, crc); + + if (crc != ecrc) + { + fdbg(g_format, blkinfo->block, offset, "DATA ", "CRC BAD", datlen); + return ERROR; + } + + /* If must be a good header */ + + if (blkinfo->verbose) + { + fdbg(g_format, blkinfo->block, offset, "DATA ", "OK ", datlen); + } + return SIZEOF_NXFFS_DATA_HDR + datlen; +} +#endif + +/**************************************************************************** + * Name: nxffs_analyze + * + * Description: + * Analyze the content of one block. + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_FS) +static inline void nxffs_analyze(FAR struct nxffs_blkinfo_s *blkinfo) +{ + FAR struct nxffs_block_s *blkhdr; + ssize_t nbytes; + int hdrndx; + int datndx; + int inndx; + int i; + + /* Verify that there is a header on the block */ + + blkhdr = (FAR struct nxffs_block_s *)blkinfo->buffer; + if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) != 0) + { + fdbg(g_format, blkinfo->block, 0, "BLOCK", "NO FRMT", + blkinfo->geo.blocksize); + } + else if (blkhdr->state == BLOCK_STATE_GOOD) + { + size_t datsize = blkinfo->geo.blocksize - SIZEOF_NXFFS_BLOCK_HDR; + size_t nerased = nxffs_erased(blkinfo->buffer + SIZEOF_NXFFS_BLOCK_HDR, datsize); + if (nerased == datsize) + { + if (blkinfo->verbose) + { + fdbg(g_format, blkinfo->block, 0, "BLOCK", "ERASED ", + blkinfo->geo.blocksize); + } + return; + } +#if 0 /* Too much output, to little information */ + else + { + fdbg(g_format, blkinfo->block, 0, "BLOCK", "IN USE ", + blkinfo->geo.blocksize); + } +#endif + } + else if (blkhdr->state == BLOCK_STATE_BAD) + { + fdbg(g_format, blkinfo->block, 0, "BLOCK", "BAD ", + blkinfo->geo.blocksize); + } + else + { + fdbg(g_format, blkinfo->block, 0, "BLOCK", "CORRUPT", + blkinfo->geo.blocksize); + } + + /* Serach for Inode and data block headers. */ + + inndx = 0; + datndx = 0; + + for (i = SIZEOF_NXFFS_BLOCK_HDR; i < blkinfo->geo.blocksize; i++) + { + uint8_t ch = blkinfo->buffer[i]; + + if (ch == g_inodemagic[inndx]) + { + inndx++; + datndx = 0; + + if (inndx == NXFFS_MAGICSIZE) + { + hdrndx = i - NXFFS_MAGICSIZE + 1; + nbytes = nxffs_analyzeinode(blkinfo, hdrndx); + if (nbytes > 0) + { + i = hdrndx + nbytes - 1; + } + inndx = 0; + } + } + else if (ch == g_datamagic[datndx]) + { + datndx++; + inndx = 0; + + if (datndx == NXFFS_MAGICSIZE) + { + hdrndx = i - NXFFS_MAGICSIZE + 1; + nbytes = nxffs_analyzedata(blkinfo, hdrndx); + if (nbytes > 0) + { + i = hdrndx + nbytes - 1; + } + datndx = 0; + } + } + } + +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_dump + * + * Description: + * Dump a summary of the contents of an NXFFS file system. CONFIG_DEBUG + * and CONFIG_DEBUG_FS must be enabled for this function to do anything. + * + * Input Parameters: + * mtd - The MTD device that provides the interface to NXFFS-formatted + * media. + * verbose - FALSE: only show errors + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int nxffs_dump(FAR struct mtd_dev_s *mtd, bool verbose) +{ +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_FS) + struct nxffs_blkinfo_s blkinfo; + int ret; + + /* Get the volume geometry. (casting to uintptr_t first eliminates + * complaints on some architectures where the sizeof long is different + * from the size of a pointer). + */ + + memset(&blkinfo, 0, sizeof(struct nxffs_blkinfo_s)); + ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&blkinfo.geo)); + if (ret < 0) + { + fdbg("ERROR: MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", -ret); + goto errout; + } + + /* Save the verbose output indication */ + + blkinfo.verbose = verbose; + + /* Allocate a buffer to hold one block */ + + blkinfo.buffer = (FAR uint8_t *)kmalloc(blkinfo.geo.blocksize); + if (!blkinfo.buffer) + { + fdbg("ERROR: Failed to allocate block cache\n"); + ret = -ENOMEM; + goto errout; + } + + /* Now read every block on the device */ + + fdbg("NXFFS Dump:\n"); + fdbg(g_hdrformat); + + blkinfo.nblocks = blkinfo.geo.erasesize * blkinfo.geo.neraseblocks / blkinfo.geo.blocksize; + for (blkinfo.block = 0, blkinfo.offset = 0; + blkinfo.block < blkinfo.nblocks; + blkinfo.block++, blkinfo.offset += blkinfo.geo.blocksize) + { + /* Read the next block */ + + ret = MTD_BREAD(mtd, blkinfo.block, 1, blkinfo.buffer); + if (ret < 0) + { + fdbg("ERROR: Failed to read block %d\n", blkinfo.block); + goto errout_with_block; + } + + /* Analyze the block */ + + nxffs_analyze(&blkinfo); + } + fdbg("%d blocks analyzed\n", blkinfo.nblocks); + +errout_with_block: + kfree(blkinfo.buffer); +errout: + return ret; + +#else + return -ENOSYS; +#endif +} diff --git a/nuttx/fs/nxffs/nxffs_initialize.c b/nuttx/fs/nxffs/nxffs_initialize.c new file mode 100644 index 0000000000..6d93a318aa --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_initialize.c @@ -0,0 +1,520 @@ +/**************************************************************************** + * fs/nxffs/nxffs_initialize.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/* See fs_mount.c -- this structure is explicitly externed there. + * We use the old-fashioned kind of initializers so that this will compile + * with any compiler. + */ + +const struct mountpt_operations nxffs_operations = +{ + nxffs_open, /* open */ + nxffs_close, /* close */ + nxffs_read, /* read */ + nxffs_write, /* write */ + NULL, /* seek -- Use f_pos in struct file */ + nxffs_ioctl, /* ioctl */ + NULL, /* sync -- No buffered data */ + + nxffs_opendir, /* opendir */ + NULL, /* closedir */ + nxffs_readdir, /* readdir */ + nxffs_rewinddir, /* rewinddir */ + + nxffs_bind, /* bind */ + nxffs_unbind, /* unbind */ + nxffs_statfs, /* statfs */ + + nxffs_unlink, /* unlink */ + NULL, /* mkdir -- no directories */ + NULL, /* rmdir -- no directories */ + NULL, /* rename -- cannot rename in place if name is longer */ + nxffs_stat /* stat */ +}; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* The magic number that appears that the beginning of each NXFFS (logical) + * block + */ + +const uint8_t g_blockmagic[NXFFS_MAGICSIZE] = { 'B', 'l', 'c', 'k' }; + +/* The magic number that appears that the beginning of each NXFFS inode */ + +const uint8_t g_inodemagic[NXFFS_MAGICSIZE] = { 'I', 'n', 'o', 'd' }; + +/* The magic number that appears that the beginning of each NXFFS inode + * data block. + */ + +const uint8_t g_datamagic[NXFFS_MAGICSIZE] = { 'D', 'a', 't', 'a' }; + +/* If CONFIG_NXFSS_PREALLOCATED is defined, then this is the single, pre- + * allocated NXFFS volume instance. + */ + +#ifdef CONFIG_NXFSS_PREALLOCATED +struct nxffs_volume_s g_volume; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_initialize + * + * Description: + * Initialize to provide NXFFS on an MTD interface + * + * Input Parameters: + * mtd - The MTD device that supports the FLASH interface. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int nxffs_initialize(FAR struct mtd_dev_s *mtd) +{ + FAR struct nxffs_volume_s *volume; + struct nxffs_blkstats_s stats; + off_t threshold; + int ret; + + /* If CONFIG_NXFSS_PREALLOCATED is defined, then this is the single, pre- + * allocated NXFFS volume instance. + */ + +#ifdef CONFIG_NXFSS_PREALLOCATED + + volume = &g_volume; + memset(volume, 0, sizeof(struct nxffs_volume_s)); + +#else + + /* Allocate a NXFFS volume structure */ + + volume = (FAR struct nxffs_volume_s *)kzalloc(sizeof(struct nxffs_volume_s)); + if (!volume) + { + ret = -ENOMEM; + goto errout; + } +#endif + + /* Initialize the NXFFS volume structure */ + + volume->mtd = mtd; + volume->cblock = (off_t)-1; + sem_init(&volume->exclsem, 0, 1); + sem_init(&volume->wrsem, 0, 1); + + /* Get the volume geometry. (casting to uintptr_t first eliminates + * complaints on some architectures where the sizeof long is different + * from the size of a pointer). + */ + + ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&volume->geo)); + if (ret < 0) + { + fdbg("MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", -ret); + goto errout_with_volume; + } + + /* Allocate one I/O block buffer to general files system access */ + + volume->cache = (FAR uint8_t *)kmalloc(volume->geo.blocksize); + if (!volume->cache) + { + fdbg("Failed to allocate an erase block buffer\n"); + ret = -ENOMEM; + goto errout_with_volume; + } + + /* Pre-allocate one, full, in-memory erase block. This is needed for filesystem + * packing (but is useful in other places as well). This buffer is not needed + * often, but is best to have pre-allocated and in-place. + */ + + volume->pack = (FAR uint8_t *)kmalloc(volume->geo.erasesize); + if (!volume->pack) + { + fdbg("Failed to allocate an I/O block buffer\n"); + ret = -ENOMEM; + goto errout_with_cache; + } + + /* Get the number of R/W blocks per erase block and the total number o + * R/W blocks + */ + + volume->blkper = volume->geo.erasesize / volume->geo.blocksize; + volume->nblocks = volume->geo.neraseblocks * volume->blkper; + DEBUGASSERT((off_t)volume->blkper * volume->geo.blocksize == volume->geo.erasesize); + + /* Check if there is a valid NXFFS file system on the flash */ + + ret = nxffs_blockstats(volume, &stats); + if (ret < 0) + { + fdbg("Failed to collect block statistics: %d\n", -ret); + goto errout_with_buffer; + } + + /* If the proportion of good blocks is low or the proportion of unformatted + * blocks is high, then reformat the FLASH. + */ + + threshold = stats.nblocks / 5; + if (stats.ngood < threshold || stats.nunformat > threshold) + { + /* Reformat the volume */ + + ret = nxffs_reformat(volume); + if (ret < 0) + { + fdbg("Failed to reformat the volume: %d\n", -ret); + goto errout_with_buffer; + } + + /* Get statistics on the re-formatted volume */ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_FS) + ret = nxffs_blockstats(volume, &stats); + if (ret < 0) + { + fdbg("Failed to collect block statistics: %d\n", -ret); + goto errout_with_buffer; + } +#endif + } + + /* Get the file system limits */ + + ret = nxffs_limits(volume); + if (ret == OK) + { + return OK; + } + fdbg("Failed to calculate file system limits: %d\n", -ret); + +errout_with_buffer: + kfree(volume->pack); +errout_with_cache: + kfree(volume->cache); +errout_with_volume: +#ifndef CONFIG_NXFSS_PREALLOCATED + kfree(volume); +#endif + return ret; +} + +/**************************************************************************** + * Name: nxffs_limits + * + * Description: + * Recalculate file system limits: (1) the FLASH offset to the first, + * valid inode, and (2) the FLASH offset to the first, unused byte after + * the last inode (invalid or not). + * + * The first, lower limit must be recalculated: (1) initially, (2) + * whenever the first inode is deleted, or (3) whenever inode is moved + * as part of the file system packing operation. + * + * The second, upper limit must be (1) incremented whenever new file + * data is written, or (2) recalculated as part of the file system packing + * operation. + * + * Input Parameters: + * volume - Identifies the NXFFS volume + * + * Returned Value: + * Zero on success. Otherwise, a negated error is returned indicating the + * nature of the failure. + * + ****************************************************************************/ + +int nxffs_limits(FAR struct nxffs_volume_s *volume) +{ + FAR struct nxffs_entry_s entry; + off_t block; + off_t offset; + bool noinodes = false; + int nerased; + int ret; + + /* Get the offset to the first valid block on the FLASH */ + + block = 0; + ret = nxffs_validblock(volume, &block); + if (ret < 0) + { + fdbg("Failed to find a valid block: %d\n", -ret); + return ret; + } + + /* Then find the first valid inode in or beyond the first valid block */ + + offset = block * volume->geo.blocksize; + ret = nxffs_nextentry(volume, offset, &entry); + if (ret < 0) + { + /* The value -ENOENT is special. This simply means that the FLASH + * was searched to the end and no valid inode was found... the file + * system is empty (or, in more perverse cases, all inodes are + * deleted or corrupted). + */ + + if (ret != -ENOENT) + { + fdbg("nxffs_nextentry failed: %d\n", -ret); + return ret; + } + + /* Set a flag the just indicates that no inodes were found. Later, + * we will set the location of the first inode to be the same as + * the location of the free FLASH region. + */ + + fvdbg("No inodes found\n"); + noinodes = true; + } + else + { + /* Save the offset to the first inode */ + + volume->inoffset = entry.hoffset; + fvdbg("First inode at offset %d\n", volume->inoffset); + + /* Discard this entry and set the next offset. */ + + offset = nxffs_inodeend(volume, &entry); + nxffs_freeentry(&entry); + } + + /* Now, search for the last valid entry */ + + if (!noinodes) + { + while ((ret = nxffs_nextentry(volume, offset, &entry)) == OK) + { + /* Discard the entry and guess the next offset. */ + + offset = nxffs_inodeend(volume, &entry); + nxffs_freeentry(&entry); + } + fvdbg("Last inode before offset %d\n", offset); + } + + /* No inodes were found after this offset. Now search for a block of + * erased flash. + */ + + nxffs_ioseek(volume, offset); + nerased = 0; + for (;;) + { + int ch = nxffs_getc(volume, 1); + if (ch < 0) + { + /* Failed to read the next byte... this could mean that the FLASH + * is full? + */ + + if (volume->ioblock + 1 >= volume->nblocks && + volume->iooffset + 1 >= volume->geo.blocksize) + { + /* Yes.. the FLASH is full. Force the offsets to the end of FLASH */ + + volume->froffset = volume->nblocks * volume->geo.blocksize; + fvdbg("Assume no free FLASH, froffset: %d\n", volume->froffset); + if (noinodes) + { + volume->inoffset = volume->froffset; + fvdbg("No inodes, inoffset: %d\n", volume->inoffset); + } + return OK; + } + + // No? Then it is some other failure that we do not know how to handle + + fdbg("nxffs_getc failed: %d\n", -ch); + return ch; + } + + /* Check for another erased byte */ + + else if (ch == CONFIG_NXFFS_ERASEDSTATE) + { + /* If we have encountered NXFFS_NERASED number of consecutive + * erased bytes, then presume we have reached the end of valid + * data. + */ + + if (++nerased >= NXFFS_NERASED) + { + /* Okay.. we have a long stretch of erased FLASH in a valid + * FLASH block. Let's say that this is the beginning of + * the free FLASH region. + */ + + volume->froffset = offset; + fvdbg("Free FLASH region begins at offset: %d\n", volume->froffset); + if (noinodes) + { + volume->inoffset = offset; + fvdbg("First inode at offset %d\n", volume->inoffset); + } + return OK; + } + } + else + { + offset += nerased + 1; + nerased = 0; + } + } + + /* Won't get here */ + + return OK; +} + +/**************************************************************************** + * Name: nxffs_bind + * + * Description: + * This function implements a portion of the mount operation. Normmally, + * the bind() method allocates and initializes the mountpoint private data + * then binds the blockdriver inode to the filesystem private data. The + * final binding of the private data (containing the blockdriver) to the + * mountpoint is performed by mount(). + * + * For the NXFFS, this sequence is quite different for the following + * reasons: + * + * 1. A block driver is not used. Instead, an MTD instance was provided + * to nxfs_initialize prior to mounting. So, in this sense, the NXFFS + * file system is already bound. + * + * 2. Since the volume was already bound to the MTD driver, all allocations + * and initializations have already been performed. Essentially, all + * mount operations have been bypassed and now we just need to provide + * the pre-allocated volume instance. + * + * 3. The tricky thing is that there is no mechanism to associate multiple + * NXFFS volumes to the multiple volumes bound to different MTD drivers. + * Hence, the limitation of a single NXFFS volume. + * + ****************************************************************************/ + +int nxffs_bind(FAR struct inode *blkdriver, FAR const void *data, + FAR void **handle) +{ +#ifndef CONFIG_NXFSS_PREALLOCATED +# error "No design to support dynamic allocation of volumes" +#else + + /* If CONFIG_NXFSS_PREALLOCATED is defined, then this is the single, pre- + * allocated NXFFS volume instance. + */ + + DEBUGASSERT(g_volume.cache); + *handle = &g_volume; +#endif + return OK; +} + +/**************************************************************************** + * Name: nxffs_unbind + * + * Description: This implements the filesystem portion of the umount + * operation. + * + ****************************************************************************/ + +int nxffs_unbind(FAR void *handle, FAR struct inode **blkdriver) +{ +#ifndef CONFIG_NXFSS_PREALLOCATED +# error "No design to support dynamic allocation of volumes" +#else + return g_volume.ofiles ? -EBUSY : OK; +#endif +} diff --git a/nuttx/fs/nxffs/nxffs_inode.c b/nuttx/fs/nxffs/nxffs_inode.c new file mode 100644 index 0000000000..505a6c6863 --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_inode.c @@ -0,0 +1,502 @@ +/**************************************************************************** + * fs/nxffs/nxffs_inode.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_rdentry + * + * Description: + * Read the inode entry at this offset. Called only from nxffs_nextentry(). + * + * Input Parameters: + * volume - Describes the current volume. + * offset - The byte offset from the beginning of FLASH where the inode + * header is expected. + * entry - A memory location to return the expanded inode header + * information. + * + * Returned Value: + * Zero on success. Otherwise, a negated errno value is returned + * indicating the nature of the failure. + * + * On return, the + * + ****************************************************************************/ + +static int nxffs_rdentry(FAR struct nxffs_volume_s *volume, off_t offset, + FAR struct nxffs_entry_s *entry) +{ + struct nxffs_inode_s inode; + uint32_t ecrc; + uint32_t crc; + uint8_t state; + int namlen; + int ret; + + DEBUGASSERT(volume && entry); + memset(entry, 0, sizeof(struct nxffs_entry_s)); + + /* Read the header at the FLASH offset */ + + nxffs_ioseek(volume, offset); + memcpy(&inode, &volume->cache[volume->iooffset], SIZEOF_NXFFS_INODE_HDR); + + /* Check if the file state is recognized. */ + + state = inode.state; + if (state != INODE_STATE_FILE && state != INODE_STATE_DELETED) + { + /* This can't be a valid inode.. don't bother with the rest */ + + ret = -ENOENT; + goto errout_no_offset; + } + + /* Copy the packed header into the user-friendly buffer */ + + entry->hoffset = offset; + entry->noffset = nxffs_rdle32(inode.noffs); + entry->doffset = nxffs_rdle32(inode.doffs); + entry->utc = nxffs_rdle32(inode.utc); + entry->datlen = nxffs_rdle32(inode.datlen); + + /* Modify the packed header and perform the (partial) CRC calculation */ + + ecrc = nxffs_rdle32(inode.crc); + inode.state = CONFIG_NXFFS_ERASEDSTATE; + memset(inode.crc, 0, 4); + crc = crc32((FAR const uint8_t *)&inode, SIZEOF_NXFFS_INODE_HDR); + + /* Allocate memory to hold the variable-length file name */ + + namlen = inode.namlen; + entry->name = (FAR char *)kmalloc(namlen + 1); + if (!entry->name) + { + fdbg("Failed to allocate name, namlen: %d\n", namlen); + ret = -ENOMEM; + goto errout_no_offset; + } + + /* Seek to the expected location of the name in FLASH */ + + nxffs_ioseek(volume, entry->noffset); + + /* Make sure that the block is in memory (the name may not be in the + * same block as the inode header. + */ + + ret = nxffs_rdcache(volume, volume->ioblock); + if (ret < 0) + { + fdbg("nxffsx_rdcache failed: %d\n", -ret); + goto errout_with_name; + } + + /* Read the file name from the expected offset in FLASH */ + + memcpy(entry->name, &volume->cache[volume->iooffset], namlen); + entry->name[namlen] = '\0'; + + /* Finish the CRC calculation and verify the entry */ + + crc = crc32part((FAR const uint8_t *)entry->name, namlen, crc); + if (crc != ecrc) + { + fdbg("CRC entry: %08x CRC calculated: %08x\n", ecrc, crc); + ret = -EIO; + goto errout_with_name; + } + + /* We have a good inode header.. but it still could a deleted file. + * Check the file state. + */ + + if (state != INODE_STATE_FILE) + { + /* It is a deleted file. But still, the data offset and the + * start size are good so we can use this information to advance + * further in FLASH memory and reduce the search time. + */ + + offset = nxffs_inodeend(volume, entry); + nxffs_freeentry(entry); + ret = -ENOENT; + goto errout; + } + + /* Everything is good.. leave the offset pointing to the valid inode + * header. + */ + + return OK; + + /* On errors where we are suspicious of the validity of the inode header, + * we need to increment the file position to just after the "good" magic + * word. + */ + +errout_with_name: + nxffs_freeentry(entry); +errout_no_offset: + offset += NXFFS_MAGICSIZE; +errout: + nxffs_ioseek(volume, offset); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_freeentry + * + * Description: + * The inode values returned by nxffs_nextentry() include allocated memory + * (specifically, the file name string). This function should be called + * to dispose of that memory when the inode entry is no longer needed. + * + * Note that the nxffs_entry_s containing structure is not freed. The + * caller may call kfree upon return of this function if necessary to + * free the entry container. + * + * Input parameters: + * entry - The entry to be freed. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void nxffs_freeentry(FAR struct nxffs_entry_s *entry) +{ + if (entry->name) + { + kfree(entry->name); + entry->name = NULL; + } +} + +/**************************************************************************** + * Name: nxffs_nextentry + * + * Description: + * Search for the next valid inode starting at the provided FLASH offset. + * + * Input Parameters: + * volume - Describes the NXFFS volume. + * offset - The FLASH memory offset to begin searching. + * entry - A pointer to memory provided by the caller in which to return + * the inode description. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno is returned + * that indicates the nature of the failure. + * + ****************************************************************************/ + +int nxffs_nextentry(FAR struct nxffs_volume_s *volume, off_t offset, + FAR struct nxffs_entry_s *entry) +{ + int nmagic; + int ch; + int nerased; + int ret; + + /* Seek to the first FLASH offset provided by the caller. */ + + nxffs_ioseek(volume, offset); + + /* Then begin searching */ + + nerased = 0; + nmagic = 0; + for (;;) + { + /* Read the next character */ + + ch = nxffs_getc(volume, SIZEOF_NXFFS_INODE_HDR - nmagic); + if (ch < 0) + { + fvdbg("nxffs_getc failed: %d\n", -ch); + return ch; + } + + /* Check for another erased byte */ + + else if (ch == CONFIG_NXFFS_ERASEDSTATE) + { + /* If we have encountered NXFFS_NERASED number of consecutive + * erased bytes, then presume we have reached the end of valid + * data. + */ + + if (++nerased >= NXFFS_NERASED) + { + fvdbg("No entry found\n"); + return -ENOENT; + } + } + else + { + nerased = 0; + + /* Check for the magic sequence indicating the start of an NXFFS + * inode. There is the possibility of this magic sequnce occurring + * in FLASH data. However, the header CRC should distinguish + * between real NXFFS inode headers and such false alarms. + */ + + if (ch != g_inodemagic[nmagic]) + { + /* Ooops... this is the not the right character for the magic + * Sequence. Check if we need to restart or to cancel the sequence: + */ + + if (ch == g_inodemagic[0]) + { + nmagic = 1; + } + else + { + nmagic = 0; + } + } + else if (nmagic < NXFFS_MAGICSIZE - 1) + { + /* We have one more character in the magic sequence */ + + nmagic++; + } + + /* We have found the magic sequence in the FLASH data that may + * indicate the beginning of an NXFFS inode. + */ + + else + { + /* The the FLASH offset where we found the matching magic number */ + + offset = nxffs_iotell(volume) - NXFFS_MAGICSIZE; + + /* Try to extract the inode header from that position */ + + ret = nxffs_rdentry(volume, offset, entry); + if (ret == OK) + { + fvdbg("Found a valid fileheader, offset: %d\n", offset); + return OK; + } + + /* False alarm.. keep looking */ + + nmagic = 0; + } + } + } + + /* We won't get here, but to keep some compilers happy: */ + + return -ENOENT; +} + +/**************************************************************************** + * Name: nxffs_findinode + * + * Description: + * Search for an inode with the provided name starting with the first + * valid inode and proceeding to the end FLASH or until the matching + * inode is found. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * name - The name of the inode to find + * entry - The location to return information about the inode. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno is returned + * that indicates the nature of the failure. + * + ****************************************************************************/ + +int nxffs_findinode(FAR struct nxffs_volume_s *volume, FAR const char *name, + FAR struct nxffs_entry_s *entry) +{ + off_t offset; + int ret; + + /* Start with the first valid inode that was discovered when the volume + * was created (or modified after the last file system re-packing). + */ + + offset = volume->inoffset; + + /* Loop, checking each NXFFS inode until either: (1) we find the NXFFS inode + * with the matching name, or (2) we reach the end of data written on the + * media. + */ + + for (;;) + { + /* Get the next, valid NXFFS inode entry */ + + ret = nxffs_nextentry(volume, offset, entry); + if (ret < 0) + { + fvdbg("No inode found: %d\n", -ret); + return ret; + } + + /* Is this the NXFFS inode we are looking for? */ + + else if (strcmp(name, entry->name) == 0) + { + /* Yes, return success with the entry data in 'entry' */ + + return OK; + } + + /* Discard this entry and try the next one. Here we set the + * next offset using the raw data length as the offset + * increment. This is, of course, not accurate because it + * does not account for the data headers that enclose the + * data. But it is guaranteed to be less than or equal to + * the correct offset and, hence, better then searching + * byte-for-byte. + */ + + offset = nxffs_inodeend(volume, entry); + nxffs_freeentry(entry); + } + + /* We won't get here, but for some compilers: */ + + return -ENOENT; +} + +/**************************************************************************** + * Name: nxffs_inodeend + * + * Description: + * Return an *approximiate* FLASH offset to end of the inode data. The + * returned value is guaranteed to be be less then or equal to the offset + * of the thing-of-interest in FLASH. Parsing for interesting things + * can begin at that point. + * + * Assumption: The inode header has been verified by the caller and is + * known to contain valid data. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * entry - Describes the inode. + * + * Returned Value: + * A FLASH offset to the (approximate) end of the inode data. No errors + * are detected. + * + ****************************************************************************/ + +off_t nxffs_inodeend(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_entry_s *entry) +{ + /* A zero length file will have no data blocks */ + + if (entry->doffset) + { + /* This is the maximum size of one data block. It is the physcal size + * of the block minus the minimum number of headers: block sna data + */ + + uint16_t maxsize = volume->geo.blocksize - SIZEOF_NXFFS_BLOCK_HDR - SIZEOF_NXFFS_DATA_HDR; + + /* This is the minimum number of blocks require to span all of the + * inode data. One additional block could possibly be required -- we + * could make this accurate by looking at the size of the first, perhaps + * partial, data block. + */ + + off_t minblocks = (entry->datlen + maxsize - 1) / maxsize; + + /* And this is our best, simple guess at the end of the inode data */ + + return entry->doffset + entry->datlen + minblocks * SIZEOF_NXFFS_DATA_HDR; + } + + /* Otherwise, return an offset that accounts only for the inode header and + * the inode name. + */ + + /* All valid inodes will have a name associated with them */ + + DEBUGASSERT(entry->noffset); + return entry->noffset + strlen(entry->name); +} + + diff --git a/nuttx/fs/nxffs/nxffs_ioctl.c b/nuttx/fs/nxffs/nxffs_ioctl.c new file mode 100644 index 0000000000..41fabfbeef --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_ioctl.c @@ -0,0 +1,150 @@ +/**************************************************************************** + * fs/nxffs/nxffs_ioctl.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_ioctl + * + * Description: + * Standard mountpoint ioctl method. + * + ****************************************************************************/ + +int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct nxffs_volume_s *volume; + int ret; + + fvdbg("cmd: %d arg: %08lx\n", cmd, arg); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover the file system state from the open file */ + + volume = filep->f_inode->i_private; + DEBUGASSERT(volume != NULL); + + /* Get exclusive access to the volume. Note that the volume exclsem + * protects the open file list. + */ + + ret = sem_wait(&volume->exclsem); + if (ret != OK) + { + ret = -errno; + fdbg("sem_wait failed: %d\n", ret); + goto errout; + } + + /* Only a reformat and optimize commands are supported */ + + if (cmd == FIOC_REFORMAT) + { + fvdbg("Reformat command\n"); + + /* We cannot reformat the volume if there are any open inodes */ + + if (volume->ofiles) + { + fdbg("Open files\n"); + ret = -EBUSY; + goto errout_with_semaphore; + } + + /* Re-format the volume -- all is lost */ + + ret = nxffs_reformat(volume); + } + + else if (cmd == FIOC_OPTIMIZE) + { + fvdbg("Optimize command\n"); + + /* Pack the volume */ + + ret = nxffs_pack(volume); + } + else + { + /* No other commands supported */ + + ret = -ENOTTY; + } + +errout_with_semaphore: + sem_post(&volume->exclsem); +errout: + return ret; +} diff --git a/nuttx/fs/nxffs/nxffs_open.c b/nuttx/fs/nxffs/nxffs_open.c new file mode 100644 index 0000000000..339e25edc7 --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_open.c @@ -0,0 +1,1263 @@ +/**************************************************************************** + * fs/nxffs/nxffs_open.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Since we are limited to a single file opened for writing, it makes sense + * to pre-allocate the write state structure. + */ + +#ifdef CONFIG_NXFSS_PREALLOCATED +static struct nxffs_wrfile_s g_wrfile; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_hdrpos + * + * Description: + * Find a valid location for the inode header. A valid location will have + * these properties: + * + * 1. It will lie in the free flash region. + * 2. It will have enough contiguous memory to hold the entire header + * (excluding the file name which may lie in the next block). + * 3. The memory at this location will be fully erased. + * + * This function will only perform the checks of 1) and 2). + * + * Input Parameters: + * volume - Describes the NXFFS volume + * wrfile - Contains the current guess for the header position. On + * successful return, this field will hold the selected header + * position. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. Of special interest + * the return error of -ENOSPC which means that the FLASH volume is + * full and should be repacked. + * + * On successful return the following are also valid: + * + * wrfile->ofile.entry.hoffset - FLASH offset to candidate header position + * volume->ioblock - Read/write block number of the block containing the + * header position + * volume->iooffset - The offset in the block to the candidate header + * position. + * volume->froffset - Updated offset to the first free FLASH block. + * + ****************************************************************************/ + +static inline int nxffs_hdrpos(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_wrfile_s *wrfile) +{ + int ret; + + /* Reserve memory for the object */ + + ret = nxffs_wrreserve(volume, SIZEOF_NXFFS_INODE_HDR); + if (ret == OK) + { + /* Save the offset to the FLASH region reserved for the inode header */ + + wrfile->ofile.entry.hoffset = nxffs_iotell(volume); + } + return ret; +} + +/**************************************************************************** + * Name: nxffs_nampos + * + * Description: + * Find a valid location for the inode name. A valid location will have + * these properties: + * + * 1. It will lie in the free flash region. + * 2. It will have enough contiguous memory to hold the entire name + * 3. The memory at this location will be fully erased. + * + * This function will only perform the checks of 1) and 2). + * + * Input Parameters: + * volume - Describes the NXFFS volume + * wrfile - Contains the current guess for the name position. On + * successful return, this field will hold the selected name + * position. + * namlen - The length of the name. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. Of special interest + * the return error of -ENOSPC which means that the FLASH volume is + * full and should be repacked. + * + * On successful return the following are also valid: + * + * wrfile->ofile.entry.noffset - FLASH offset to candidate name position + * volume->ioblock - Read/write block number of the block containing the + * name position + * volume->iooffset - The offset in the block to the candidate name + * position. + * volume->froffset - Updated offset to the first free FLASH block. + * + ****************************************************************************/ + +static inline int nxffs_nampos(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_wrfile_s *wrfile, + int namlen) +{ + int ret; + + /* Reserve memory for the object */ + + ret = nxffs_wrreserve(volume, namlen); + if (ret == OK) + { + /* Save the offset to the FLASH region reserved for the inode name */ + + wrfile->ofile.entry.noffset = nxffs_iotell(volume); + } + return ret; +} + +/**************************************************************************** + * Name: nxffs_hdrerased + * + * Description: + * Find a valid location for the inode header. A valid location will have + * these properties: + * + * 1. It will lie in the free flash region. + * 2. It will have enough contiguous memory to hold the entire header + * (excluding the file name which may lie in the next block). + * 3. The memory at this location will be fully erased. + * + * This function will only perform the check 3). + * + * On entry it assumes: + * + * volume->ioblock - Read/write block number of the block containing the + * header position + * volume->iooffset - The offset in the block to the candidate header + * position. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * wrfile - Contains the current guess for the header position. On + * successful return, this field will hold the selected header + * position. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. Of special interest + * the return error of -ENOSPC which means that the FLASH volume is + * full and should be repacked. + * + * On successful return the following are also valid: + * + * wrfile->ofile.entry.hoffset - FLASH offset to candidate header position + * volume->ioblock - Read/write block number of the block containing the + * header position + * volume->iooffset - The offset in the block to the candidate header + * position. + * volume->froffset - Updated offset to the first free FLASH block. + * + ****************************************************************************/ + +static inline int nxffs_hdrerased(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_wrfile_s *wrfile) +{ + int ret; + + /* Find a valid location to save the inode header */ + + ret = nxffs_wrverify(volume, SIZEOF_NXFFS_INODE_HDR); + if (ret == OK) + { + /* This is where we will put the header */ + + wrfile->ofile.entry.hoffset = nxffs_iotell(volume); + } + return ret; +} + +/**************************************************************************** + * Name: nxffs_namerased + * + * Description: + * Find a valid location for the inode name. A valid location will have + * these properties: + * + * 1. It will lie in the free flash region. + * 2. It will have enough contiguous memory to hold the entire name + * (excluding the file name which may lie in the next block). + * 3. The memory at this location will be fully erased. + * + * This function will only perform the check 3). + * + * On entry it assumes: + * + * volume->ioblock - Read/write block number of the block containing the + * name position + * volume->iooffset - The offset in the block to the candidate name + * position. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * wrfile - Contains the current guess for the name position. On + * successful return, this field will hold the selected name + * position. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. Of special interest + * the return error of -ENOSPC which means that the FLASH volume is + * full and should be repacked. + * + * On successful return the following are also valid: + * + * wrfile->ofile.entry.noffset - FLASH offset to candidate name position + * volume->ioblock - Read/write block number of the block containing the + * name position + * volume->iooffset - The offset in the block to the candidate name + * position. + * volume->froffset - Updated offset to the first free FLASH block. + * + ****************************************************************************/ + +static inline int nxffs_namerased(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_wrfile_s *wrfile, + int namlen) +{ + int ret; + + /* Find a valid location to save the inode name */ + + ret = nxffs_wrverify(volume, namlen); + if (ret == OK) + { + /* This is where we will put the name */ + + wrfile->ofile.entry.noffset = nxffs_iotell(volume); + } + return ret; +} + +/**************************************************************************** + * Name: nxffs_wrname + * + * Description: + * Write the inode name to cache at the position verified by + * nxffs_namerased(). + * + * On entry it assumes: + * + * entry->noffset - FLASH offset to final name position + * volume->ioblock - Read/write block number of the block containing the + * name position + * volume->iooffset - The offset in the block to the candidate name + * position. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * entry - Describes the entry to be written. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. + * + ****************************************************************************/ + +static inline int nxffs_wrname(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_entry_s *entry, + int namlen) +{ + int ret; + + /* Seek to the inode name position and assure that it is in the volume + * cache. + */ + + nxffs_ioseek(volume, entry->noffset); + ret = nxffs_rdcache(volume, volume->ioblock); + if (ret < 0) + { + fdbg("Failed to read inode name block %d: %d\n", + volume->ioblock, -ret); + return ret; + } + + /* Copy the inode name to the volume cache and write the inode name block */ + + memcpy(&volume->cache[volume->iooffset], entry->name, namlen); + ret = nxffs_wrcache(volume); + if (ret < 0) + { + fdbg("Failed to write inode header block %d: %d\n", + volume->ioblock, -ret); + } + + return ret; +} + +/**************************************************************************** + * Name: nxffs_wropen + * + * Description: + * Handle opening for writing. Only a single writer is permitted and only + * file creation is supported. + * + ****************************************************************************/ + +static inline int nxffs_wropen(FAR struct nxffs_volume_s *volume, + FAR const char *name, mode_t oflags, + FAR struct nxffs_ofile_s **ppofile) +{ + FAR struct nxffs_wrfile_s *wrfile; + FAR struct nxffs_entry_s entry; + bool packed; + bool truncate = false; + int namlen; + int ret; + + /* Limitation: Only a single writer is permitted. Writing may involve + * extension of the file system in FLASH. Since files are contiguous + * in FLASH, only a single file may be extending the FLASH region. + */ + + ret = sem_wait(&volume->wrsem); + if (ret != OK) + { + fdbg("sem_wait failed: %d\n", ret); + ret = -errno; + goto errout; + } + + /* Get exclusive access to the volume. Note that the volume exclsem + * protects the open file list. Note that exclsem is ALWAYS taken + * after wrsem to avoid deadlocks. + */ + + ret = sem_wait(&volume->exclsem); + if (ret != OK) + { + fdbg("sem_wait failed: %d\n", ret); + ret = -errno; + goto errout_with_wrsem; + } + + /* Check if the file exists */ + + ret = nxffs_findinode(volume, name, &entry); + if (ret == OK) + { + FAR struct nxffs_ofile_s *ofile; + + /* It exists. Is the file already open for reading? */ + + ofile = nxffs_findofile(volume, name); + if (ofile) + { + /* The file is already open. + * Limitation: Files cannot be open both for reading and writing. + */ + + fdbg("File is open for reading\n"); + ret = -ENOSYS; + goto errout_with_exclsem; + } + + /* It would be an error if we are asked to create the file + * exclusively. + */ + + else if ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) + { + fdbg("File exists, can't create O_EXCL\n"); + ret = -EEXIST; + goto errout_with_exclsem; + } + + /* Were we asked to truncate the file? NOTE: Don't truncate the + * file if we were not also asked to created it. See below... + * we will not re-create the file unless O_CREAT is also specified. + */ + + else if ((oflags & (O_CREAT|O_TRUNC)) == (O_CREAT|O_TRUNC)) + { + /* Just schedule the removal the file and fall through to re-create it. + * Note that the old file of the same name will not actually be removed + * until the new file is successfully written. + */ + + truncate = true; + } + + /* The file exists and we were not asked to truncate (and recreate) it. + * Limitation: Cannot write to existing files. + */ + + else + { + fdbg("File %s exists and we were not asked to truncate it\n"); + ret = -ENOSYS; + goto errout_with_exclsem; + } + } + + /* Okay, the file is not open and does not exists (maybe because we deleted + * it). Now, make sure that we were asked to created it. + */ + + if ((oflags & O_CREAT) == 0) + { + fdbg("Not asked to create the file\n"); + ret = -ENOENT; + goto errout_with_exclsem; + } + + /* Make sure that the length of the file name will fit in a uint8_t */ + + namlen = strlen(name); + if (namlen > CONFIG_NXFFS_MAXNAMLEN) + { + fdbg("Name is too long: %d\n", namlen); + ret = -EINVAL; + goto errout_with_exclsem; + } + + /* Yes.. Create a new structure that will describe the state of this open + * file. NOTE that a special variant of the open file structure is used + * that includes additional information to support the write operation. + */ + +#ifdef CONFIG_NXFSS_PREALLOCATED + wrfile = &g_wrfile; + memset(wrfile, 0, sizeof(struct nxffs_wrfile_s)); +#else + wrfile = (FAR struct nxffs_wrfile_s *)kzalloc(sizeof(struct nxffs_wrfile_s)); + if (!wrfile) + { + ret = -ENOMEM; + goto errout_with_exclsem; + } +#endif + + /* Initialize the open file state structure */ + + wrfile->ofile.crefs = 1; + wrfile->ofile.oflags = oflags; + wrfile->ofile.entry.utc = time(NULL); + wrfile->truncate = truncate; + + /* Save a copy of the inode name. */ + + wrfile->ofile.entry.name = strdup(name); + if (!wrfile->ofile.entry.name) + { + ret = -ENOMEM; + goto errout_with_ofile; + } + + /* Allocate FLASH memory for the file and set up for the write. + * + * Loop until the inode header is configured or until a failure occurs. + * Note that nothing is written to FLASH. The inode header is not + * written until the file is closed. + */ + + packed = false; + for (;;) + { + /* File a valid location to position the inode header. Start with the + * first byte in the free FLASH region. + */ + + ret = nxffs_hdrpos(volume, wrfile); + if (ret == OK) + { + /* Find a region of memory in the block that is fully erased */ + + ret = nxffs_hdrerased(volume, wrfile); + if (ret == OK) + { + /* Valid memory for the inode header was found. Break out of + * the loop. + */ + + break; + } + } + + /* If no valid memory is found searching to the end of the volume, + * then -ENOSPC will be returned. Other errors are not handled. + */ + + if (ret != -ENOSPC || packed) + { + fdbg("Failed to find inode header memory: %d\n", -ret); + goto errout_with_name; + } + + /* -ENOSPC is a special case.. It means that the volume is full. + * Try to pack the volume in order to free up some space. + */ + + ret = nxffs_pack(volume); + if (ret < 0) + { + fdbg("Failed to pack the volume: %d\n", -ret); + goto errout_with_name; + } + + /* After packing the volume, froffset will be updated to point to the + * new free flash region. Try again. + */ + + packed = true; + } + + /* Loop until the inode name is configured or until a failure occurs. + * Note that nothing is written to FLASH. + */ + + for (;;) + { + /* File a valid location to position the inode name. Start with the + * first byte in the free FLASH region. + */ + + ret = nxffs_nampos(volume, wrfile, namlen); + if (ret == OK) + { + /* Find a region of memory in the block that is fully erased */ + + ret = nxffs_namerased(volume, wrfile, namlen); + if (ret == OK) + { + /* Valid memory for the inode header was found. Write the + * inode name to this location. + */ + + ret = nxffs_wrname(volume, &wrfile->ofile.entry, namlen); + if (ret < 0) + { + fdbg("Failed to write the inode name: %d\n", -ret); + goto errout_with_name; + } + + /* Then just break out of the loop reporting success. Note + * that the alllocated inode name string is retained; it + * will be needed later to calculate the inode CRC. + */ + + break; + } + } + + /* If no valid memory is found searching to the end of the volume, + * then -ENOSPC will be returned. Other errors are not handled. + */ + + if (ret != -ENOSPC || packed) + { + fdbg("Failed to find inode name memory: %d\n", -ret); + goto errout_with_name; + } + + /* -ENOSPC is a special case.. It means that the volume is full. + * Try to pack the volume in order to free up some space. + */ + + ret = nxffs_pack(volume); + if (ret < 0) + { + fdbg("Failed to pack the volume: %d\n", -ret); + goto errout_with_name; + } + + /* After packing the volume, froffset will be updated to point to the + * new free flash region. Try again. + */ + + packed = true; + } + + /* Add the open file structure to the head of the list of open files */ + + wrfile->ofile.flink = volume->ofiles; + volume->ofiles = &wrfile->ofile; + + /* Indicate that the volume is open for writing and return the open file + * instance. Releasing exclsem allows other readers while the write is + * in progress. But wrsem is still held for this open file, preventing + * any further writers until this inode is closed.s + */ + + *ppofile = &wrfile->ofile; + sem_post(&volume->exclsem); + return OK; + +errout_with_name: + kfree(wrfile->ofile.entry.name); +errout_with_ofile: +#ifndef CONFIG_NXFSS_PREALLOCATED + kfree(wrfile); +#endif + +errout_with_exclsem: + sem_post(&volume->exclsem); +errout_with_wrsem: + sem_post(&volume->wrsem); +errout: + return ret; +} + +/**************************************************************************** + * Name: nxffs_rdopen + * + * Description: + * Open an existing file for reading. + * + ****************************************************************************/ + +static inline int nxffs_rdopen(FAR struct nxffs_volume_s *volume, + FAR const char *name, + FAR struct nxffs_ofile_s **ppofile) +{ + FAR struct nxffs_ofile_s *ofile; + int ret; + + /* Get exclusive access to the volume. Note that the volume exclsem + * protects the open file list. + */ + + ret = sem_wait(&volume->exclsem); + if (ret != OK) + { + fdbg("sem_wait failed: %d\n", ret); + ret = -errno; + goto errout; + } + + /* Check if the file has already been opened (for reading) */ + + ofile = nxffs_findofile(volume, name); + if (ofile) + { + /* The file is already open. + * Limitation: Files cannot be open both for reading and writing. + */ + + if ((ofile->oflags & O_WROK) != 0) + { + fdbg("File is open for writing\n"); + ret = -ENOSYS; + goto errout_with_exclsem; + } + + /* Just increment the reference count on the ofile */ + + ofile->crefs++; + fdbg("crefs: %d\n", ofile->crefs); + } + + /* The file has not yet been opened. + * Limitation: The file must exist. We do not support creation of files + * read-only. + */ + + else + { + /* Not already open.. create a new open structure */ + + ofile = (FAR struct nxffs_ofile_s *)kzalloc(sizeof(struct nxffs_ofile_s)); + if (!ofile) + { + fdbg("ofile allocation failed\n"); + ret = -ENOMEM; + goto errout_with_exclsem; + } + + /* Initialize the open file state structure */ + + ofile->crefs = 1; + ofile->oflags = O_RDOK; + + /* Find the file on this volume associated with this file name */ + + ret = nxffs_findinode(volume, name, &ofile->entry); + if (ret != OK) + { + fvdbg("Inode '%s' not found: %d\n", name, -ret); + goto errout_with_ofile; + } + + /* Add the open file structure to the head of the list of open files */ + + ofile->flink = volume->ofiles; + volume->ofiles = ofile; + } + + /* Return the open file state structure */ + + *ppofile = ofile; + sem_post(&volume->exclsem); + return OK; + +errout_with_ofile: + kfree(ofile); +errout_with_exclsem: + sem_post(&volume->exclsem); +errout: + return ret; +} + +/**************************************************************************** + * Name: nxffs_remofile + * + * Description: + * Remove an entry from the open file list. + * + ****************************************************************************/ + +static inline void nxffs_remofile(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_ofile_s *ofile) +{ + FAR struct nxffs_ofile_s *prev; + FAR struct nxffs_ofile_s *curr; + + /* Find the open file structure to be removed */ + + for (prev = NULL, curr = volume->ofiles; + curr && curr != ofile; + prev = curr, curr = curr->flink); + + /* Was it found? */ + + if (curr) + { + /* Yes.. at the head of the list? */ + + if (prev) + { + prev->flink = ofile->flink; + } + else + { + volume->ofiles = ofile->flink; + } + } + else + { + fdbg("ERROR: Open inode %p not found\n", ofile); + } +} + +/**************************************************************************** + * Name: nxffs_freeofile + * + * Description: + * Free resources held by an open file. + * + ****************************************************************************/ + +static inline void nxffs_freeofile(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_ofile_s *ofile) +{ + /* Release the open file entry */ + + nxffs_freeentry(&ofile->entry); + + /* Then free the open file container (unless this the pre-alloated + * write-only open file container) + */ + +#ifdef CONFIG_NXFSS_PREALLOCATED + if ((FAR struct nxffs_wrfile_s*)ofile != &g_wrfile) +#endif + { + kfree(ofile); + } +} + +/**************************************************************************** + * Name: nxffs_wrclose + * + * Description: + * Perform special operations when a file is closed: + * 1. Write the file block header + * 2. Remove any file with the same name that was discovered when the + * file was open for writing, and finally, + * 3. Write the new file inode. + * + * Input parameters + * volume - Describes the NXFFS volume + * wrfile - Describes the state of the open file + * + ****************************************************************************/ + +static inline int nxffs_wrclose(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_wrfile_s *wrfile) +{ + int ret; + + /* Is there an unfinalized write data? */ + + if (wrfile->datlen > 0) + { + /* Yes.. Write the final file block header */ + + ret = nxffs_wrblkhdr(volume, wrfile); + if (ret < 0) + { + fdbg("Failed to write the final block of the file: %d\n", -ret); + goto errout; + } + } + + /* Truncation is implemented by writing the new file, then deleting the + * older version of the file. Note that we removed the entry from the + * open file list earlier in the close sequence; this will prevent the + * open file check from failing when we remove the old version of the + * file. + */ + + if (wrfile->truncate && wrfile->ofile.entry.name) + { + fvdbg("Removing old file: %s\n", wrfile->ofile.entry.name); + + ret = nxffs_rminode(volume, wrfile->ofile.entry.name); + if (ret < 0) + { + fdbg("nxffs_rminode failed: %d\n", -ret); + goto errout; + } + } + + /* Write the inode header to FLASH */ + + ret = nxffs_wrinode(volume, &wrfile->ofile.entry); + + /* The volume is now available for other writers */ + +errout: + sem_post(&volume->wrsem); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_findofile + * + * Description: + * Search the list of already opened files to see if the inode of this + * name is one of the opened files. + * + * Input Parameters: + * name - The name of the inode to check. + * + * Returned Value: + * If an inode of this name is found in the list of opened inodes, then + * a reference to the open file structure is returned. NULL is returned + * otherwise. + * + ****************************************************************************/ + +FAR struct nxffs_ofile_s *nxffs_findofile(FAR struct nxffs_volume_s *volume, + FAR const char *name) +{ + FAR struct nxffs_ofile_s *ofile; + + /* Check every open file. Note that the volume exclsem protects the + * list of open files. + */ + + for (ofile = volume->ofiles; ofile; ofile = ofile->flink) + { + /* Check for a name match */ + + if (strcmp(name, ofile->entry.name) == 0) + { + return ofile; + } + } + + return NULL; +} + +/**************************************************************************** + * Name: nxffs_findwriter + * + * Description: + * Search the list of already opened files and return the open file + * instance for the write. + * + * Input Parameters: + * volume - Describes the NXFFS volume. + * + * Returned Value: + * If there is an active writer of the volume, its open file instance is + * returned. NULL is returned otherwise. + * + ****************************************************************************/ + +FAR struct nxffs_wrfile_s *nxffs_findwriter(FAR struct nxffs_volume_s *volume) +{ + /* We can tell if the write is in-use because it will have an allocated + * name attached. + */ + +#ifdef CONFIG_NXFSS_PREALLOCATED + return g_wrfile.ofile.entry.name != NULL ? &g_wrfile : NULL; +#else +# error "Missing implementation" +#endif +} + +/**************************************************************************** + * Name: nxffs_open + * + * Description: + * This is the standard mountpoint open method. + * + ****************************************************************************/ + +int nxffs_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode) +{ + FAR struct nxffs_volume_s *volume; + FAR struct nxffs_ofile_s *ofile = NULL; + int ret; + + fvdbg("Open '%s'\n", relpath); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL); + + /* Get the mountpoint private data from the NuttX inode reference in the + * file structure + */ + + volume = (FAR struct nxffs_volume_s*)filep->f_inode->i_private; + DEBUGASSERT(volume != NULL); + +#ifdef CONFIG_FILE_MODE +# warning "Missing check for privileges based on inode->i_mode" +#endif + + /* Limitation: A file must be opened for reading or writing, but not both. + * There is no general for extending the size of of a file. Extending the + * file size of possible if the file to be extended is the last in the + * sequence on FLASH, but since that case is not the general case, no file + * extension is supported. + */ + + switch (oflags & (O_WROK|O_RDOK)) + { + case 0: + default: + fdbg("One of O_WRONLY/O_RDONLY must be provided\n"); + return -EINVAL; + + case O_WROK: + ret = nxffs_wropen(volume, relpath, oflags, &ofile); + break; + + case O_RDOK: + ret = nxffs_rdopen(volume, relpath, &ofile); + break; + + case O_WROK|O_RDOK: + fdbg("O_RDWR is not supported\n"); + return -ENOSYS; + } + + /* Save the reference to the open-specific state in filep->f_priv */ + + if (ret == OK) + { + filep->f_priv = ofile; + } + return ret; +} + +/**************************************************************************** + * Name: nxffs_close + * + * Description: + * This is the standard mountpoint close method. + * + ****************************************************************************/ + +int nxffs_close(FAR struct file *filep) +{ + FAR struct nxffs_volume_s *volume; + FAR struct nxffs_ofile_s *ofile; + int ret = -ENOSYS; + + fvdbg("Closing\n"); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover the open file state from the struct file instance */ + + ofile = (FAR struct nxffs_ofile_s *)filep->f_priv; + + /* Recover the volume state from the open file */ + + volume = (FAR struct nxffs_volume_s *)filep->f_inode->i_private; + DEBUGASSERT(volume != NULL); + + /* Get exclusive access to the volume. Note that the volume exclsem + * protects the open file list. + */ + + ret = sem_wait(&volume->exclsem); + if (ret != OK) + { + ret = -errno; + fdbg("sem_wait failed: %d\n", ret); + goto errout; + } + + /* Decrement the reference count on the open file */ + + ret = OK; + if (ofile->crefs == 1) + { + /* Decrementing the reference count would take it zero. + * + * Remove the entry from the open file list. We do this early + * to avoid some chick-and-egg problems with file truncation. + */ + + nxffs_remofile(volume, ofile); + + /* Handle special finalization of the write operation. */ + + if ((ofile->oflags & O_WROK) != 0) + { + ret = nxffs_wrclose(volume, (FAR struct nxffs_wrfile_s *)ofile); + } + + /* Release all resouces held by the open file */ + + nxffs_freeofile(volume, ofile); + } + else + { + /* Just decrement the reference count */ + + ofile->crefs--; + } + + filep->f_priv = NULL; + + sem_post(&volume->exclsem); +errout: + return ret; +} + +/**************************************************************************** + * Name: nxffs_wrinode + * + * Description: + * Write the inode header (only to FLASH. This is done in two contexts: + * + * 1. When an inode is closed, or + * 2. As part of the file system packing logic when an inode is moved. + * + * Note that in either case, the inode name has already been written to + * FLASH. + * + * Input parameters + * volume - Describes the NXFFS volume + * entry - Describes the inode header to write + * + * Returned Value: + * Zero is returned on success; Otherwise, a negated errno value is returned + * indicating the nature of the failure. + * + ****************************************************************************/ + +int nxffs_wrinode(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_entry_s *entry) +{ + FAR struct nxffs_inode_s *inode; + uint32_t crc; + int namlen; + int ret; + + /* Seek to the inode header position and assure that it is in the volume + * cache. + */ + + nxffs_ioseek(volume, entry->hoffset); + ret = nxffs_rdcache(volume, volume->ioblock); + if (ret < 0) + { + fdbg("Failed to read inode header block %d: %d\n", + volume->ioblock, -ret); + goto errout; + } + + /* Get the length of the inode name */ + + namlen = strlen(entry->name); + DEBUGASSERT(namlen < CONFIG_NXFFS_MAXNAMLEN); /* This was verified earlier */ + + /* Initialize the inode header */ + + inode = (FAR struct nxffs_inode_s *)&volume->cache[volume->iooffset]; + memcpy(inode->magic, g_inodemagic, NXFFS_MAGICSIZE); + + inode->state = CONFIG_NXFFS_ERASEDSTATE; + inode->namlen = namlen; + + nxffs_wrle32(inode->noffs, entry->noffset); + nxffs_wrle32(inode->doffs, entry->doffset); + nxffs_wrle32(inode->utc, entry->utc); + nxffs_wrle32(inode->crc, 0); + nxffs_wrle32(inode->datlen, entry->datlen); + + /* Calculate the CRC */ + + crc = crc32((FAR const uint8_t *)inode, SIZEOF_NXFFS_INODE_HDR); + crc = crc32part((FAR const uint8_t *)entry->name, namlen, crc); + + /* Finish the inode header */ + + inode->state = INODE_STATE_FILE; + nxffs_wrle32(inode->crc, crc); + + /* Write the block with the inode header */ + + ret = nxffs_wrcache(volume); + if (ret < 0) + { + fdbg("Failed to write inode header block %d: %d\n", + volume->ioblock, -ret); + } + + /* The volume is now available for other writers */ + +errout: + sem_post(&volume->wrsem); + return ret; +} + +/**************************************************************************** + * Name: nxffs_updateinode + * + * Description: + * The packing logic has moved an inode. Check if any open files are using + * this inode and, if so, move the data in the open file structure as well. + * + * Input parameters + * volume - Describes the NXFFS volume + * entry - Describes the new inode entry + * + * Returned Value: + * Zero is returned on success; Otherwise, a negated errno value is returned + * indicating the nature of the failure. + * + ****************************************************************************/ + +int nxffs_updateinode(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_entry_s *entry) +{ + FAR struct nxffs_ofile_s *ofile; + + /* Find the open inode structure matching this name */ + + ofile = nxffs_findofile(volume, entry->name); + if (ofile) + { + /* Yes.. the file is open. Update the FLASH offsets to inode headers */ + + ofile->entry.hoffset = entry->hoffset; + ofile->entry.noffset = entry->noffset; + ofile->entry.doffset = entry->doffset; + } + return OK; +} + diff --git a/nuttx/fs/nxffs/nxffs_pack.c b/nuttx/fs/nxffs/nxffs_pack.c new file mode 100644 index 0000000000..5a82ae4fd3 --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_pack.c @@ -0,0 +1,1572 @@ +/**************************************************************************** + * fs/nxffs/nxffs_pack.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* This structure supports access to one inode data stream */ + +struct nxffs_packstream_s +{ + struct nxffs_entry_s entry; /* Describes the inode header */ + off_t fpos; /* Current file position */ + off_t blkoffset; /* Offset to the current data block */ + uint16_t blklen; /* Size of this block */ + uint16_t blkpos; /* Position in block corresponding to fpos */ +}; + +/* The structure supports the overall packing operation */ + +struct nxffs_pack_s +{ + /* These describe the source and destination streams */ + + struct nxffs_packstream_s src; + struct nxffs_packstream_s dest; + + /* These describe the state of the current contents of the (destination) + * volume->pack buffer. + */ + + FAR uint8_t *iobuffer; /* I/O block start position */ + off_t ioblock; /* I/O block number */ + off_t block0; /* First I/O block number in the erase block */ + uint16_t iooffset; /* I/O block offset */ +}; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_getblock + * + * Description: + * Return the I/O block number that includes the provided offset. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * offset - FLASH offset + * + * Returned Value: + * The I/O block number. + * + ****************************************************************************/ + +static off_t nxffs_getblock(FAR struct nxffs_volume_s *volume, off_t offset) +{ + return offset / volume->geo.blocksize; +} + +/**************************************************************************** + * Name: nxffs_getoffset + * + * Description: + * Given an I/O block number return the block offset corresponding to the + * FLASH offset; + * + * Input Parameters: + * volume - Describes the NXFFS volume + * offset - FLASH offset + * + * Returned Value: + * The I/O block number. + * + ****************************************************************************/ + +static off_t nxffs_getoffset(FAR struct nxffs_volume_s *volume, + off_t offset, off_t block) +{ + return offset - block * volume->geo.blocksize; +} + +/**************************************************************************** + * Name: nxffs_packtell + * + * Description: + * Report the current destination position in the pack buffer. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * pack - The volume packing state structure. + * + * Returned Value: + * The offset from the beginning of FLASH to the current seek position. + * + ****************************************************************************/ + +static off_t nxffs_packtell(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack) +{ + return pack->ioblock * volume->geo.blocksize + pack->iooffset; +} + +/**************************************************************************** + * Name: nxffs_packvalid + * + * Description: + * Check if the current destination block is valid. + * + * Input Parameters: + * pack - The volume packing state structure. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline bool nxffs_packvalid(FAR struct nxffs_pack_s *pack) +{ + FAR struct nxffs_block_s *blkhdr; + + blkhdr = (FAR struct nxffs_block_s *)pack->iobuffer; + return (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) == 0 && + blkhdr->state == BLOCK_STATE_GOOD); +} + +/**************************************************************************** + * Name: nxffs_mediacheck + * + * Description: + * Verify that there is at least one valid block and at least one valid + * inode header on the media. On successful return, the volume packing + * structure is initialized and contains the offset to the first valid + * inode header is returned. + * + * Input Parameters: + * volume - The volume to be packed. + * pack - The volume packing state structure. + * + * Returned Values: + * The offset to the data area on the first valid block. Zero is return + * if there are no valid blocks or if there are no valid inode headers + * after the first valid block. + * + ****************************************************************************/ + +static inline off_t nxffs_mediacheck(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack) +{ + off_t froffset; + int ret; + + /* Initialize the packing structure to all zero */ + + memset(pack, 0, sizeof(struct nxffs_pack_s)); + + /* Find the FLASH offset to the first valid block */ + + volume->ioblock = 0; + ret = nxffs_validblock(volume, &volume->ioblock); + if (ret < 0) + { + /* No valid blocks? Return offset zero. */ + + return 0; + } + + /* The offset to the free location to pack is then just after the block + * header in this block. + */ + + volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR; + froffset = nxffs_iotell(volume); + + /* Get the offset to the first valid inode entry after this free offset */ + + ret = nxffs_nextentry(volume, froffset, &pack->src.entry); + if (ret < 0) + { + /* No valid entries on the media -- Return offset zero */ + + return 0; + } + + /* Okay.. the start block and first entry have been found */ + + return froffset; +} + +/**************************************************************************** + * Name: nxffs_startpos + * + * Description: + * Find the position in FLASH memory where we should begin packing. That + * position is the place where there is a gap between the last and the next + * valid inode. On entry, the volume packing structure should be as it + * was initialized by nxffx_mediacheck. on successful return, the volume + * packing state structure will be updated to begin the packing operation. + * + * Input Parameters: + * volume - The volume to be packed + * pack - The volume packing state structure. + * froffset - On input, this is the location where we should be searching + * for the location to begin packing. On successful return, froffset + * will be set the the offset in FLASH where the first inode should be + * copied to. If -ENOSPC is returned -- meaning that the FLASH is full + * -- then no packing can be performed. In this case, then the free + * flash offset is returned through this location. + * + * Returned Values: + * Zero on success; Otherwise, a negated errno value is returned to + * indicate the nature of the failure. If -ENOSPC is returned then the + * free FLASH offset is also returned. + * + ****************************************************************************/ + +static inline int nxffs_startpos(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack, + off_t *froffset) +{ + struct nxffs_blkentry_s blkentry; + off_t offset = *froffset; + off_t wasted; + off_t nbytes; + int ret; + + /* Loop until we find a gap of unused FLASH large enough to warrant + * compacting. + */ + + for(;;) + { + /* Is there wasted space between the offset where the we could have + * valid data and the offset to the beginning of the first valid + * inode header? NOTE: The threshold check is not accurate, there + * may or may not be intervening block headers making the separation + * seem larger than it is. + */ + + DEBUGASSERT(pack->src.entry.hoffset >= offset); + wasted = pack->src.entry.hoffset - offset; + if (wasted > CONFIG_NXFFS_PACKTHRESHOLD) + { + /* This is where we must begin packing. Describe the destination + * inode header (only non-zero entries need to be initialized). + */ + + pack->dest.entry.name = pack->src.entry.name; + pack->dest.entry.utc = pack->src.entry.utc; + pack->dest.entry.datlen = pack->src.entry.datlen; + + /* The destination entry now "owns" the name string */ + + pack->src.entry.name = NULL; + + /* Return the FLASH offset to the destination inode header */ + + *froffset = offset; + return OK; + } + + /* Free the allocated memory in the entry */ + + nxffs_freeentry(&pack->src.entry); + + /* Update the offset to the first byte at the end of the last data + * block. + */ + + nbytes = 0; + offset = pack->src.entry.doffset; + + while (nbytes < pack->src.entry.datlen) + { + /* Read the next data block header */ + + ret = nxffs_nextblock(volume, offset, &blkentry); + if (ret < 0) + { + fdbg("Failed to find next data block: %d\n", -ret); + return ret; + } + + /* Get the number of blocks and pointer to where the next + * data block might lie. + */ + + nbytes += blkentry.datlen; + offset = blkentry.hoffset + SIZEOF_NXFFS_DATA_HDR + blkentry.datlen; + } + + /* Make sure there is space at this location for an inode header */ + + nxffs_ioseek(volume, offset); + if (volume->iooffset + SIZEOF_NXFFS_INODE_HDR > volume->geo.blocksize) + { + /* No.. not enough space here. Find the next valid block */ + + volume->ioblock++; + ret = nxffs_validblock(volume, &volume->ioblock); + if (ret < 0) + { + /* No valid blocks? Then there is nothing we can do. Return + * the end-of-flash indication. + */ + + *froffset = volume->froffset; + return -ENOSPC; + } + + volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR; + offset = nxffs_iotell(volume); + } + + /* Get the offset to the next valid inode entry */ + + ret = nxffs_nextentry(volume, offset, &pack->src.entry); + if (ret < 0) + { + /* No more valid inode entries. Just return an end-of-flash error + * indication. However, there could be many deleted inodes; set + * volume->froffset to indicate the true free FLASH position. + */ + + *froffset = offset; + return -ENOSPC; + } + } + + /* We won't get here */ + + return -ENOSYS; +} + +/**************************************************************************** + * Name: nxffs_srcsetup + * + * Description: + * Given a valid src inode, configure the src data stream. + * + * Input Parameters: + * volume - The volume to be packed + * pack - The volume packing state structure. + * offset - FLASH offset to the data block header (will be zero for zero- + * files. + * + * Returned Values: + * Zero on success; Otherwise, a negated errno value is returned to + * indicate the nature of the failure. + * + ****************************************************************************/ + +static int nxffs_srcsetup(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack, off_t offset) +{ + /* Start with the first data block */ + + pack->src.blkoffset = offset; + pack->src.blkpos = 0; + + /* Zero-length files have no valid data block offset */ + + if (offset > 0) + { + /* Seek to the data block header, read and verify the block header */ + + int ret = nxffs_rdblkhdr(volume, offset, &pack->src.blklen); + if (ret < 0) + { + fdbg("Failed to verify the data block header: %d\n", -ret); + } + return ret; + } + + DEBUGASSERT(pack->src.entry.datlen == 0); + return OK; +} + +/**************************************************************************** + * Name: nxffs_destsetup + * + * Description: + * Given a valid dest inode, configure the dest data stream. + * + * Input Parameters: + * volume - The volume to be packed + * pack - The volume packing state structure. + * + * Returned Values: + * Zero on success; Otherwise, a negated errno value is returned to + * indicate the nature of the failure. + * + ****************************************************************************/ + +static int nxffs_destsetup(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack) +{ + size_t mindata; + int namlen; + int ret; + + /* The destination can be in one of three of states: + * + * State 1: The inode position was not yet been found. This condition can + * only occur on initial entry into nxffs_packblock() when there we no space + * for the inode header at the end of the previous block. We must now be + * at the beginning of a shiny new I/O block, so we should always have + * space for a new inode header right here. + */ + + if (pack->dest.entry.hoffset == 0) + { + /* Is there room for an inode structure in this block? */ + + if(pack->iooffset + SIZEOF_NXFFS_INODE_HDR > volume->geo.blocksize) + { + /* No.. that inode name will not fit in this block. Return an + * indication that we are at the end of the block and try again + * later. + */ + + return -ENOSPC; + } + + /* The inode header will be placed at this position (but not until + * we are finished. + */ + + pack->dest.entry.hoffset = nxffs_packtell(volume, pack); + + /* Make sure that the initialize state of the inode header memory is + * erased. This is important because we may not write to inode header + * until it has already been written to FLASH. + */ + + memset(&pack->iobuffer[pack->iooffset], CONFIG_NXFFS_ERASEDSTATE, + SIZEOF_NXFFS_INODE_HDR); + + /* Then set the new FLASH offset */ + + pack->iooffset += SIZEOF_NXFFS_INODE_HDR; + } + + /* State 2: inode position found, inode header not written, inode name + * position not determined. + */ + + if (pack->dest.entry.noffset == 0) + { + /* Find the offset to the string memory. Will if fit in this block? + * Note: iooffset has already been incremented to account for the + * size of the inode header. + */ + + namlen = strlen(pack->dest.entry.name); + if (pack->iooffset + namlen > volume->geo.blocksize) + { + /* No.. that inode name will not fit in this block. Return an + * indication that we are at the end of the block and try again + * later. + */ + + return -ENOSPC; + } + + /* Yes.. Write the inode name to the volume packing buffer now, but do + * not free the name string memory yet; it will be needed later to\ + * calculate the header CRC. + */ + + memcpy(&pack->iobuffer[pack->iooffset], pack->dest.entry.name, namlen); + + /* Reserve space for the inode name */ + + pack->dest.entry.noffset = nxffs_packtell(volume, pack); + pack->iooffset += namlen; + } + + /* State 3: Inode header not-written, inode name written. Still need the position + * of the first data block. + * + * Deal with the special case where the source inode is a zero length file + * with no data blocks to be transferred. + */ + + if (pack->src.entry.doffset > 0) + { + if (pack->dest.entry.doffset == 0) + { + /* Will the data block header plus a minimal amount of data fit in this + * block? (or the whole file if the file is very small). + */ + + mindata = MIN(NXFFS_MINDATA, pack->dest.entry.datlen); + if (pack->iooffset + SIZEOF_NXFFS_DATA_HDR + mindata > volume->geo.blocksize) + { + /* No.. return an indication that we are at the end of the block + * and try again later. + */ + + ret = -ENOSPC; + goto errout; + } + + /* Yes.. reserve space for the data block header */ + + pack->dest.entry.doffset = nxffs_packtell(volume, pack); + pack->iooffset += SIZEOF_NXFFS_DATA_HDR; + + /* Initialize the output data stream to start with the first data block */ + + pack->dest.blkoffset = pack->dest.entry.doffset; + pack->dest.blklen = 0; + pack->dest.blkpos = 0; + } + + /* State 4: Starting a new block. Verify that there is space in the current + * block for another (minimal sized) block + */ + + if (pack->dest.blkoffset == 0) + { + /* Will the data block header plus a minimal amount of data fit in this + * block? (or the whole file if the file is very small). + */ + + mindata = MIN(NXFFS_MINDATA, pack->dest.entry.datlen); + if (pack->iooffset + SIZEOF_NXFFS_DATA_HDR + mindata > volume->geo.blocksize) + { + /* No.. return an indication that we are at the end of the block + * and try again later. + */ + + ret = -ENOSPC; + goto errout; + } + + /* Yes.. reserve space for the data block header */ + + pack->dest.blkoffset = nxffs_packtell(volume, pack); + pack->iooffset += SIZEOF_NXFFS_DATA_HDR; + pack->dest.blklen = 0; + pack->dest.blkpos = 0; + } + } + + ret = OK; + +errout: + volume->froffset = nxffs_packtell(volume, pack); + return ret; +} + +/**************************************************************************** + * Name: nxffs_wrinodehdr + * + * Description: + * Write the destination inode header (only) to FLASH. Note that the inode + * name has already been written to FLASH (thus greatly simplifying the + * the complexity of this operation). + * + * Input Parameters: + * volume - The volume to be packed + * pack - The volume packing state structure. + * + * Returned Values: + * Zero on success; Otherwise, a negated errno value is returned to + * indicate the nature of the failure (not used). + * + ****************************************************************************/ + +static int nxffs_wrinodehdr(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack) +{ + FAR struct nxffs_inode_s *inode; + off_t ioblock; + uint16_t iooffset; + uint32_t crc; + int namlen; + int ret; + + /* Get seek positions corresponding to the inode header location */ + + ioblock = nxffs_getblock(volume, pack->dest.entry.hoffset); + iooffset = nxffs_getoffset(volume, pack->dest.entry.hoffset, ioblock); + + /* The inode header is not written until all of the inode data has been + * packed into its new location. As a result, there are two possibilities: + * + * 1. The inode header lies in the current, unwritten erase block, + * 2. The inode header resides in an earlier erase block and has already + * been written to FLASH. + * + * Recall that the inode name has already been written to FLASH. If that + * were not the case, then there would be other complex possibilities. + * + * Case 2: Does the inode header reside in a block before the beginning + * of the current erase block? + */ + + if (ioblock < pack->block0) + { + /* Case 2: The inode header lies in an earlier erase block that has + * already been written to FLASH. In this case, if we are very + * careful, we can just use the standard routine to write the inode + * header that is called during the normal file close operation: + */ + + ret = nxffs_wrinode(volume, &pack->dest.entry); + } + else + { + /* Cases 1: Both the inode header and name are in the unwritten cache + * memory. + * + * Initialize the inode header. + */ + + iooffset += (ioblock - pack->block0) * volume->geo.blocksize; + inode = (FAR struct nxffs_inode_s *)&volume->pack[iooffset]; + memcpy(inode->magic, g_inodemagic, NXFFS_MAGICSIZE); + + nxffs_wrle32(inode->noffs, pack->dest.entry.noffset); + nxffs_wrle32(inode->doffs, pack->dest.entry.doffset); + nxffs_wrle32(inode->utc, pack->dest.entry.utc); + nxffs_wrle32(inode->crc, 0); + nxffs_wrle32(inode->datlen, pack->dest.entry.datlen); + + /* Get the length of the inode name */ + + namlen = strlen(pack->dest.entry.name); + DEBUGASSERT(namlen < CONFIG_NXFFS_MAXNAMLEN); + + inode->state = CONFIG_NXFFS_ERASEDSTATE; + inode->namlen = namlen; + + /* Calculate the CRC */ + + crc = crc32((FAR const uint8_t *)inode, SIZEOF_NXFFS_INODE_HDR); + crc = crc32part((FAR const uint8_t *)pack->dest.entry.name, namlen, crc); + + /* Finish the inode header */ + + inode->state = INODE_STATE_FILE; + nxffs_wrle32(inode->crc, crc); + + /* If any open files reference this inode, then update the open file + * state. + */ + + ret = nxffs_updateinode(volume, &pack->dest.entry); + if (ret < 0) + { + fdbg("Failed to update inode info: %s\n", -ret); + } + } + + /* Reset the dest inode information */ + + nxffs_freeentry(&pack->dest.entry); + memset(&pack->dest, 0, sizeof(struct nxffs_packstream_s)); + return ret; +} + +/**************************************************************************** + * Name: nxffs_wrdatthdr + * + * Description: + * Write the destination data block header to FLASH. + * + * Input Parameters: + * volume - The volume to be packed + * pack - The volume packing state structure. + * + * Returned Values: + * Zero on success; Otherwise, a negated errno value is returned to + * indicate the nature of the failure. + * + ****************************************************************************/ + +static void nxffs_wrdathdr(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack) +{ + FAR struct nxffs_data_s *dathdr; + off_t ioblock; + uint16_t iooffset; + uint32_t crc; + + if (pack->dest.blklen > 0) + { + /* Get the offset in the block corresponding to the location of the data + * block header. NOTE: This must lie in the same block as we currently have + * buffered. + */ + + ioblock = nxffs_getblock(volume, pack->dest.blkoffset); + iooffset = nxffs_getoffset(volume, pack->dest.blkoffset, ioblock); + DEBUGASSERT(pack->dest.blkoffset && ioblock == pack->ioblock); + + /* Write the data block header to memory */ + + dathdr = (FAR struct nxffs_data_s *)&pack->iobuffer[iooffset]; + memcpy(dathdr->magic, g_datamagic, NXFFS_MAGICSIZE); + nxffs_wrle32(dathdr->crc, 0); + nxffs_wrle16(dathdr->datlen, pack->dest.blklen); + + /* Update the entire data block CRC (including the header) */ + + crc = crc32(&pack->iobuffer[iooffset], pack->dest.blklen + SIZEOF_NXFFS_DATA_HDR); + nxffs_wrle32(dathdr->crc, crc); + } + + /* Setup state to allocate the next data block */ + + pack->dest.blkoffset = 0; + pack->dest.blklen = 0; + pack->dest.blkpos = 0; +} + +/**************************************************************************** + * Name: nxffs_packtransfer + * + * Description: + * Transfer data from the source to the destination buffer. + * + * Input Parameters: + * volume - The volume to be packed + * pack - The volume packing state structure. + * + * Returned Values: + * None. + * + ****************************************************************************/ + +static void nxffs_packtransfer(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack) +{ + /* Determine how much data is available in the dest pack buffer */ + + uint16_t destlen = volume->geo.blocksize - pack->iooffset; + + /* Dermined how much data is available in the src data block */ + + uint16_t srclen = pack->src.blklen - pack->src.blkpos; + + /* Transfer the smaller of the two amounts data */ + + uint16_t xfrlen = MIN(srclen, destlen); + if (xfrlen > 0) + { + nxffs_ioseek(volume, pack->src.blkoffset + SIZEOF_NXFFS_DATA_HDR + pack->src.blkpos); + memcpy(&pack->iobuffer[pack->iooffset], &volume->cache[volume->iooffset], xfrlen); + + /* Increment counts and offset for this data transfer */ + + pack->src.fpos += xfrlen; /* Source data offsets */ + pack->src.blkpos += xfrlen; + pack->dest.fpos += xfrlen; /* Destination data offsets */ + pack->dest.blkpos += xfrlen; + pack->dest.blklen += xfrlen; /* Destination data block size */ + pack->iooffset += xfrlen; /* Destination I/O block offset */ + volume->iooffset += xfrlen; /* Source I/O block offset */ + volume->froffset += xfrlen; /* Free FLASH offset */ + } +} + +/**************************************************************************** + * Name: nxffs_endsrcblock + * + * Description: + * The end of a source data block has been encountered. Locate the next + * source block and setup to continue the transfer. + * + * Input Parameters: + * volume - The volume to be packed + * pack - The volume packing state structure. + * + * Returned Values: + * Zero on success; Otherwise, a negated errno value is returned to + * indicate the nature of the failure. + * + ****************************************************************************/ + +static int nxffs_endsrcblock(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack) +{ + struct nxffs_blkentry_s blkentry; + off_t offset; + int ret; + + /* Yes.. find the next data block in the source input stream. */ + + offset = pack->src.blkoffset + SIZEOF_NXFFS_DATA_HDR + pack->src.blklen; + ret = nxffs_nextblock(volume, offset, &blkentry); + if (ret < 0) + { + fdbg("Failed to find next data block: %d\n", -ret); + return ret; + } + + /* Set up the source stream */ + + pack->src.blkoffset = blkentry.hoffset; + pack->src.blklen = blkentry.datlen; + pack->src.blkpos = 0; + return OK; +} + +/**************************************************************************** + * Name: nxffs_packblock + * + * Description: + * Resume packing from the source stream into the newly identified + * destination block. + * + * Input Parameters: + * volume - The volume to be packed + * pack - The volume packing state structure. + * + * Returned Values: + * Zero on success; Otherwise, a negated errno value is returned to + * indicate the nature of the failure. + * + ****************************************************************************/ + +static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack) +{ + off_t offset; + int ret; + + /* Are we currently processing a block from the source stream? */ + + if (pack->src.blkoffset == 0) + { + /* No.. setup the source stream */ + + ret = nxffs_srcsetup(volume, pack, pack->src.entry.doffset); + if (ret < 0) + { + fdbg("Failed to configure the src stream: %d\n", -ret); + return ret; + } + } + + /* We enter here on a new block every time, so we always have to setup + * the dest data stream. There should never be data block allocated at + * this point in time. + */ + + DEBUGASSERT(pack->dest.blkoffset == 0 && pack->dest.blkpos == 0); + + ret = nxffs_destsetup(volume, pack); + if (ret < 0) + { + /* -ENOSPC is a special return value which simply means that all of + * the FLASH has been used up to the end of the current. We need to + * return OK in this case and resume at the next block. + */ + + if (ret == -ENOSPC) + { + return OK; + } + else + { + fdbg("Failed to configure the dest stream: %d\n", -ret); + return ret; + } + } + + /* Loop, transferring data from the source block to the destination pack + * buffer until either (1) the source stream is exhausted, (2) the destination + * block is full, or (3) an error occurs. + */ + + for (;;) + { + /* Transfer data from the source buffer to the destination buffer */ + + nxffs_packtransfer(volume, pack); + + /* Now, either the (1) src block has been fully transferred, (2) all + * of the source data has been transferred, or (3) the the destination + * block is full, .. or all three. + * + * Check if all of the bytes in the source inode have been transferred. + */ + + if (pack->src.fpos >= pack->src.entry.datlen) + { + /* Write the final destination data block header and inode + * headers. + */ + + nxffs_wrdathdr(volume, pack); + nxffs_wrinodehdr(volume, pack); + + /* Find the next valid source inode */ + + offset = pack->src.blkoffset + pack->src.blklen; + memset(&pack->src, 0, sizeof(struct nxffs_packstream_s)); + + ret = nxffs_nextentry(volume, offset, &pack->src.entry); + if (ret < 0) + { + /* No more valid inode entries. Just return an end-of-flash error + * indication. + */ + + return -ENOSPC; + } + + /* Setup the new source stream */ + + ret = nxffs_srcsetup(volume, pack, pack->src.entry.doffset); + if (ret < 0) + { + return ret; + } + + /* Setup the dest stream */ + + memset(&pack->dest, 0, sizeof(struct nxffs_packstream_s)); + pack->dest.entry.name = pack->src.entry.name; + pack->dest.entry.utc = pack->src.entry.utc; + pack->dest.entry.datlen = pack->src.entry.datlen; + pack->src.entry.name = NULL; + + /* Is there sufficient space at the end of the I/O block to hold + * the inode header? + */ + + if (pack->iooffset + SIZEOF_NXFFS_INODE_HDR > volume->geo.blocksize) + { + /* No, just return success... we will handle this condition when + * this function is called on the next I/O block. + */ + + return OK; + } + + /* Configure the destination stream */ + + ret = nxffs_destsetup(volume, pack); + if (ret < 0) + { + /* -ENOSPC is a special return value which simply means that all of the + * has been used up to the end. We need to return OK in this case and + * resume at the next block. + */ + + if (ret == -ENOSPC) + { + return OK; + } + else + { + fdbg("Failed to configure the dest stream: %d\n", -ret); + return ret; + } + } + } + + /* Not at the end of the source data stream. Check if we are at the + * end of the current source data block. + */ + + else if (pack->src.blkpos >= pack->src.blklen) + { + ret = nxffs_endsrcblock(volume, pack); + if (ret < 0) + { + return ret; + } + } + + /* Check if the destination block is full */ + + if (pack->iooffset >= volume->geo.blocksize) + { + /* Yes.. Write the destination data block header and return success */ + + nxffs_wrdathdr(volume, pack); + return OK; + } + } + + return -ENOSYS; +} + +/**************************************************************************** + * Name: nxffs_setupwriter + * + * Description: + * Writing is performed at the end of the free FLASH region. When we + * finish packing the other inodes, we still need to pack the partially + * written file at the end of FLASH. This function performs the setup + * necessary to perform that packing phase. + * + * Input Parameters: + * volume - The volume to be packed + * pack - The volume packing state structure. + * + * Returned Values: + * If there is an active writer of the volume, its open file instance is + * returned. NULL is returned otherwise. + * + ****************************************************************************/ + +static FAR struct nxffs_wrfile_s * +nxffs_setupwriter(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack) +{ + FAR struct nxffs_wrfile_s *wrfile; + + /* Is there a writer? */ + + wrfile = nxffs_findwriter(volume); + if (wrfile) + { + /* Yes... It is the activity of this write that probably initiated + * this packing activity. The writer may have failed in one of several + * different stages: + * + * hoffset == 0: The write failed early before even FLASH for the inode + * header was set aside. + * noffset == 0: The write failed after the inode header was set aside, + * but before the inode name was written. + * doffset == 0: The write failed after writing the inode name, bue + * before any data blocks were written to FLASH. + * + * If no FLASH has been set aside for the write, then we don't need to + * do anything here. + */ + + if (wrfile->ofile.entry.hoffset > 0) + { + /* Initialize for the packing operation. */ + + memset(&pack->dest, 0, sizeof(struct nxffs_packstream_s)); + pack->dest.entry.name = strdup(wrfile->ofile.entry.name); + pack->dest.entry.utc = wrfile->ofile.entry.utc; + pack->dest.entry.datlen = wrfile->ofile.entry.datlen; + + memset(&pack->src, 0, sizeof(struct nxffs_packstream_s)); + memcpy(&pack->src.entry, &wrfile->ofile.entry, sizeof(struct nxffs_entry_s)); + pack->src.entry.name = NULL; + return wrfile; + } + } + + return NULL; +} + +/**************************************************************************** + * Name: nxffs_packwriter + * + * Description: + * There is a write in progress at the time that the volume is packed. + * This is the normal case because it is the write failures that trigger + * the packing operation to begin with. + * + * Writing is performed at the end of the free FLASH region and this + * implemenation is restricted to a single writer. The new inode is not + * written to FLASH until the the writer is closed and so will not be + * found by nxffs_packblock(). + * + * Input Parameters: + * volume - The volume to be packed + * pack - The volume packing state structure. + * + * Returned Values: + * Zero on success; Otherwise, a negated errno value is returned to + * indicate the nature of the failure. + * + ****************************************************************************/ + +static inline int nxffs_packwriter(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack, + FAR struct nxffs_wrfile_s *wrfile) +{ + int ret; + + /* Are we currently processing a block from the source stream? */ + + if (pack->src.blkoffset == 0) + { + /* No.. setup the source stream */ + + ret = nxffs_srcsetup(volume, pack, pack->src.entry.doffset); + if (ret < 0) + { + fdbg("Failed to configure the src stream: %d\n", -ret); + return ret; + } + } + + /* We enter here on a new block every time, so we always have to setup + * the dest data stream. There should never be data block allocated at + * this point in time. + */ + + DEBUGASSERT(pack->dest.blkoffset == 0 && pack->dest.blkpos == 0); + + ret = nxffs_destsetup(volume, pack); + if (ret < 0) + { + /* -ENOSPC is a special return value which simply means that all of the + * has been used up to the end. We need to return OK in this case and + * resume at the next block. + */ + + if (ret == -ENOSPC) + { + return OK; + } + else + { + fdbg("Failed to configure the dest stream: %d\n", -ret); + return ret; + } + } + + /* Loop, transferring data from the source block to the destination pack + * buffer until either (1) the source stream is exhausted, (2) the destination + * block is full, or (3) an error occurs. + */ + + for (;;) + { + /* Transfer data from the source buffer to the destination buffer */ + + nxffs_packtransfer(volume, pack); + + /* Now, either the (1) src block has been fully transferred, (2) all + * of the source data has been transferred, or (3) the the destination + * block is full, .. or all three. + * + * Check if all of the bytes in the source inode have been transferred. + */ + + if (pack->src.fpos >= pack->src.entry.datlen) + { + /* Write the final destination data block header and inode + * headers. + */ + + nxffs_wrdathdr(volume, pack); + + /* Set the new offsets in the open file instance. */ + + wrfile->ofile.entry.hoffset = pack->dest.entry.hoffset; + wrfile->ofile.entry.noffset = pack->dest.entry.noffset; + wrfile->ofile.entry.doffset = pack->dest.entry.doffset; + + /* Return an end-of-flash error to indicate that all of the write + * data has been transferred. + */ + + return -ENOSPC; + } + + /* Not at the end of the source data stream. Check if we are at the + * end of the current source data block. + */ + + else if (pack->src.blkpos >= pack->src.blklen) + { + ret = nxffs_endsrcblock(volume, pack); + if (ret < 0) + { + return ret; + } + } + + /* Check if the destination block is full */ + + if (pack->iooffset >= volume->geo.blocksize) + { + /* Yes.. Write the destination data block header and return success */ + + nxffs_wrdathdr(volume, pack); + return OK; + } + } + + return -ENOSYS; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_pack + * + * Description: + * Pack and re-write the filesystem in order to free up memory at the end + * of FLASH. + * + * Input Parameters: + * volume - The volume to be packed. + * + * Returned Values: + * Zero on success; Otherwise, a negated errno value is returned to + * indicate the nature of the failure. + * + ****************************************************************************/ + +int nxffs_pack(FAR struct nxffs_volume_s *volume) +{ + struct nxffs_pack_s pack; + FAR struct nxffs_wrfile_s *wrfile; + off_t iooffset; + off_t eblock; + off_t block; + bool packed; + int i; + int ret; + + /* Get the offset to the first valid inode entry */ + + wrfile = NULL; + packed = false; + + iooffset = nxffs_mediacheck(volume, &pack); + if (iooffset == 0) + { + /* Offset zero is only returned if no valid blocks were found on the + * FLASH media or if there are no valid inode entries on the FLASH after + * the first valid block. There are two possibilities: (1) there + * really is nothing on the FLASH, or (2) there is a file being written + * to the FLASH now. + */ + + /* Is there a writer? */ + + wrfile = nxffs_setupwriter(volume, &pack); + if (wrfile) + { + /* If there is a write, just set ioffset to the offset of data in + * first block. Setting 'packed' to true will supress normal inode + * packing operation. Then we can start compacting the FLASH. + */ + + iooffset = SIZEOF_NXFFS_BLOCK_HDR; + packed = true; + goto start_pack; + } + else + { + /* No, there is no write in progress. We just have an empty flash + * full of deleted files. In this case, the media needs to be re- + * formatted. + */ + + ret = nxffs_reformat(volume); + if (ret == OK) + { + /* The free flash offset will be in the first valid block of + * the FLASH. + */ + + block = 0; + ret = nxffs_validblock(volume, &block); + if (ret == OK) + { + /* Set to the offset past the block header in the first + * valid block + */ + + volume->froffset = + block * volume->geo.blocksize + SIZEOF_NXFFS_BLOCK_HDR; + } + } + + return ret; + } + } + + /* There is a valid format and valid inodes on the media.. setup up to + * begin the packing operation. + */ + + ret = nxffs_startpos(volume, &pack, &iooffset); + if (ret < 0) + { + /* This is a normal situation if the volume is full */ + + if (ret == -ENOSPC) + { + /* In the case where the volume is full, nxffs_startpos() will + * recalculate the free FLASH offset and store it in iooffset. There + * may be deleted files at the end of FLASH. In this case, we don't + * have to pack any files, we simply have to erase FLASH at the end. + * But don't do this unless there is some particularly big FLASH + * savings (otherwise, we risk wearing out these final blocks). + */ + + if (iooffset + CONFIG_NXFFS_TAILTHRESHOLD < volume->froffset) + { + /* Setting 'packed' to true will supress normal inode packing + * operation. + */ + + packed = true; + + /* Writing is performed at the end of the free FLASH region. + * If we are not packing files, we could still need to pack + * the partially written file at the end of FLASH. + */ + + wrfile = nxffs_setupwriter(volume, &pack); + } + + /* Otherwise return OK.. meaning that there is nothing more we can + * do to recover FLASH space. + */ + + else + { + return OK; + } + } + else + { + fvdbg("Failed to find a packing position: %d\n", -ret); + return ret; + } + } + + /* Otherwise, begin pack at this src/dest block combination. Initialize + * ioblock and iooffset with the position of the first inode header. In + * this case, the FLASH offset to the first inode header is return in + * iooffset. + */ + +start_pack: + + pack.ioblock = nxffs_getblock(volume, iooffset); + pack.iooffset = nxffs_getoffset(volume, iooffset, pack.ioblock); + volume->froffset = iooffset; + + /* Then pack all erase blocks starting with the erase block that contains + * the ioblock and through the final erase block on the FLASH. + */ + + for (eblock = pack.ioblock / volume->blkper; + eblock < volume->geo.neraseblocks; + eblock++) + { + /* Read the erase block into the pack buffer. We need to do this even + * if we are overwriting the entire block so that we skip over + * previously marked bad blocks. + */ + + pack.block0 = eblock * volume->blkper; + ret = MTD_BREAD(volume->mtd, pack.block0, volume->blkper, volume->pack); + if (ret < 0) + { + fdbg("Failed to read erase block %d: %d\n", eblock, -ret); + goto errout_with_pack; + } + + /* Pack each I/O block */ + + for (i = 0, block = pack.block0, pack.iobuffer = volume->pack; + i < volume->blkper; + i++, block++, pack.iobuffer += volume->geo.blocksize) + { + /* The first time here, the ioblock may point to an offset into + * the erase block. We just need to skip over those cases. + */ + + if (block >= pack.ioblock) + { + /* Set the I/O position. Note on the first time we get + * pack.iooffset will hold the offset in the first I/O block + * to the first inode header. After that, it will always + * refer to the first byte after the block header. + */ + + pack.ioblock = block; + + /* If this is not a valid block or if we have already + * finished packing the valid inode entries, then just fall + * through, reset the FLASH memory to the erase state, and + * write the reset values to FLASH. (The first block that + * we want to process will always be valid -- we have + * already verified that). + */ + + if (nxffs_packvalid(&pack)) + { + /* Have we finished packing inodes? */ + + if (!packed) + { + DEBUGASSERT(wrfile == NULL); + + /* Pack inode data into this block */ + + ret = nxffs_packblock(volume, &pack); + if (ret < 0) + { + /* The error -ENOSPC is a special value that simply + * means that there is nothing further to be packed. + */ + + if (ret == -ENOSPC) + { + packed = true; + + /* Writing is performed at the end of the free + * FLASH region and this implemenation is restricted + * to a single writer. The new inode is not + * written to FLASH until the the writer is closed + * and so will not be found by nxffs_packblock(). + */ + + wrfile = nxffs_setupwriter(volume, &pack); + } + else + { + /* Otherwise, something really bad happened */ + + fdbg("Failed to pack into block %d: %d\n", + block, ret); + goto errout_with_pack; + } + } + } + + /* If all of the "normal" inodes have been packed, then check if + * we need to pack the current, in-progress write operation. + */ + + if (wrfile) + { + DEBUGASSERT(packed == true); + + /* Pack write data into this block */ + + ret = nxffs_packwriter(volume, &pack, wrfile); + if (ret < 0) + { + /* The error -ENOSPC is a special value that simply + * means that there is nothing further to be packed. + */ + + if (ret == -ENOSPC) + { + wrfile = NULL; + } + else + { + /* Otherwise, something really bad happened */ + + fdbg("Failed to pack into block %d: %d\n", + block, ret); + goto errout_with_pack; + } + } + } + } + + /* Set any unused portion at the end of the block to the + * erased state. + */ + + if (pack.iooffset < volume->geo.blocksize) + { + memset(&pack.iobuffer[pack.iooffset], + CONFIG_NXFFS_ERASEDSTATE, + volume->geo.blocksize - pack.iooffset); + } + + /* Next time through the loop, pack.iooffset will point to the + * first byte after the block header. + */ + + pack.iooffset = SIZEOF_NXFFS_BLOCK_HDR; + } + } + + /* We now have an in-memory image of how we want this erase block to + * appear. Now it is safe to erase the block. + */ + + ret = MTD_ERASE(volume->mtd, eblock, 1); + if (ret < 0) + { + fdbg("Failed to erase block %d [%d]: %d\n", + eblock, pack.block0, -ret); + goto errout_with_pack; + } + + /* Write the packed I/O block to FLASH */ + + ret = MTD_BWRITE(volume->mtd, pack.block0, volume->blkper, volume->pack); + if (ret < 0) + { + fdbg("Failed to write erase block %d [%]: %d\n", + eblock, pack.block0, -ret); + goto errout_with_pack; + } + } + +errout_with_pack: + nxffs_freeentry(&pack.src.entry); + nxffs_freeentry(&pack.dest.entry); + return ret; +} diff --git a/nuttx/fs/nxffs/nxffs_read.c b/nuttx/fs/nxffs/nxffs_read.c new file mode 100644 index 0000000000..6ba49ca72f --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_read.c @@ -0,0 +1,473 @@ +/**************************************************************************** + * fs/nxffs/nxffs_read.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_rdseek + * + * Description: + * Seek to the file position before read or write access. Note that the + * simplier nxffs_ioseek() cannot be used for this purpose. File offsets + * are not easily mapped to FLASH offsets due to intervening block and + * data headers. + * + * Input Parameters: + * volume - Describes the current volume + * entry - Describes the open inode + * fpos - The desired file position + * blkentry - Describes the block entry that we are positioned in + * + ****************************************************************************/ + +static ssize_t nxffs_rdseek(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_entry_s *entry, + off_t fpos, + FAR struct nxffs_blkentry_s *blkentry) +{ + size_t datstart; + size_t datend; + off_t offset; + int ret; + + /* The initial FLASH offset will be the offset to first data block of + * the inode + */ + + offset = entry->doffset; + if (offset == 0) + { + /* Zero length files will have no data blocks */ + + return -ENOSPC; + } + + /* Loop until we read the data block containing the desired position */ + + datend = 0; + do + { + /* Check if the next data block contains the sought after file position */ + + ret = nxffs_nextblock(volume, offset, blkentry); + if (ret < 0) + { + fdbg("nxffs_nextblock failed: %d\n", -ret); + return ret; + } + + /* Get the range of data offsets for this data block */ + + datstart = datend; + datend += blkentry->datlen; + + /* Offset to search for the the next data block */ + + offset = blkentry->hoffset + SIZEOF_NXFFS_DATA_HDR + blkentry->datlen; + } + while (datend <= fpos); + + /* Return the offset to the data within the current data block */ + + blkentry->foffset = fpos - datstart; + nxffs_ioseek(volume, blkentry->hoffset + SIZEOF_NXFFS_DATA_HDR + blkentry->foffset); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: nxffs_read + * + * Description: + * This is an implementation of the NuttX standard file system read + * method. + * + ****************************************************************************/ + +ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer, size_t buflen) +{ + FAR struct nxffs_volume_s *volume; + FAR struct nxffs_ofile_s *ofile; + struct nxffs_blkentry_s blkentry; + ssize_t total; + size_t available; + size_t readsize; + int ret; + + fvdbg("Read %d bytes from offset %d\n", buflen, filep->f_pos); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover the open file state from the struct file instance */ + + ofile = (FAR struct nxffs_ofile_s *)filep->f_priv; + + /* Recover the volume state from the open file */ + + volume = (FAR struct nxffs_volume_s *)filep->f_inode->i_private; + DEBUGASSERT(volume != NULL); + + /* Get exclusive access to the volume. Note that the volume exclsem + * protects the open file list. + */ + + ret = sem_wait(&volume->exclsem); + if (ret != OK) + { + ret = -errno; + fdbg("sem_wait failed: %d\n", ret); + goto errout; + } + + /* Check if the file was opened with read access */ + + if ((ofile->oflags & O_RDOK) == 0) + { + fdbg("File not open for read access\n"); + ret = -EACCES; + goto errout_with_semaphore; + } + + /* Loop until all bytes have been read */ + + for (total = 0; total < buflen; ) + { + /* Don't seek past the end of the file */ + + if (filep->f_pos >= ofile->entry.datlen) + { + /* Return the partial read */ + + filep->f_pos = ofile->entry.datlen; + break; + } + + /* Seek to the current file offset */ + + ret = nxffs_rdseek(volume, &ofile->entry, filep->f_pos, &blkentry); + if (ret < 0) + { + fdbg("nxffs_rdseek failed: %d\n", -ret); + ret = -EACCES; + goto errout_with_semaphore; + } + + /* How many bytes are available at this offset */ + + available = blkentry.datlen - blkentry.foffset; + + /* Don't read more than we need to */ + + readsize = buflen - total; + if (readsize > available) + { + readsize = available; + } + + /* Read data from that file offset */ + + memcpy(&buffer[total], &volume->cache[volume->iooffset], readsize); + + /* Update the file offset */ + + filep->f_pos += readsize; + total += readsize; + } + + sem_post(&volume->exclsem); + return total; + +errout_with_semaphore: + sem_post(&volume->exclsem); +errout: + return (ssize_t)ret; +} + +/**************************************************************************** + * Name: nxffs_nextblock + * + * Description: + * Search for the next valid data block starting at the provided + * FLASH offset. + * + * Input Parameters: + * volume - Describes the NXFFS volume. + * datlen - A memory location to return the data block length. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno is returned + * that indicates the nature of the failure. + * + ****************************************************************************/ + +int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset, + FAR struct nxffs_blkentry_s *blkentry) +{ + int nmagic; + int ch; + int nerased; + int ret; + + /* Seek to the first FLASH offset provided by the caller. */ + + nxffs_ioseek(volume, offset); + + /* Skip the block header */ + + if (volume->iooffset < SIZEOF_NXFFS_BLOCK_HDR) + { + volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR; + } + + /* Then begin searching */ + + nerased = 0; + nmagic = 0; + + for (;;) + { + /* Read the next character */ + + ch = nxffs_getc(volume, SIZEOF_NXFFS_DATA_HDR - nmagic); + if (ch < 0) + { + fvdbg("nxffs_getc failed: %d\n", -ch); + return ch; + } + + /* Check for another erased byte */ + + else if (ch == CONFIG_NXFFS_ERASEDSTATE) + { + /* If we have encountered NXFFS_NERASED number of consecutive + * erased bytes, then presume we have reached the end of valid + * data. + */ + + if (++nerased >= NXFFS_NERASED) + { + fvdbg("No entry found\n"); + return -ENOENT; + } + } + else + { + nerased = 0; + + /* Check for the magic sequence indicating the start of an NXFFS + * data block or start of the next inode. There is the possibility + * of this magic sequnce occurring in FLASH data. However, the + * data block CRC should distinguish between real NXFFS data blocks + * headers and such false alarms. + */ + + if (ch != g_datamagic[nmagic]) + { + /* Ooops... this is the not the right character for the magic + * Sequence. Check if we need to restart or to cancel the sequence: + */ + + if (ch == g_datamagic[0]) + { + nmagic = 1; + } + else + { + nmagic = 0; + } + } + else if (nmagic < NXFFS_MAGICSIZE - 1) + { + /* We have one more character in the magic sequence */ + + nmagic++; + } + + /* We have found the magic sequence in the FLASH data that may + * indicate the beginning of an NXFFS data block. + */ + + else + { + /* The offset to the header must be 4 bytes before the current + * FLASH seek location. + */ + + blkentry->hoffset = nxffs_iotell(volume) - NXFFS_MAGICSIZE; + + /* Read the block header and verify the block at that address */ + + ret = nxffs_rdblkhdr(volume, blkentry->hoffset, &blkentry->datlen); + if (ret == OK) + { + fvdbg("Found a valid data block, offset: %d datlen: %d\n", + blkentry->hoffset, blkentry->datlen); + return OK; + } + + /* False alarm.. Restore the volume cache position (that was + * destroyed by nxfs_rdblkhdr()) and keep looking. + */ + + nxffs_ioseek(volume, blkentry->hoffset + NXFFS_MAGICSIZE); + nmagic = 0; + } + } + } + + /* We won't get here, but to keep some compilers happy: */ + + return -ENOENT; +} + +/**************************************************************************** + * Name: nxffs_rdblkhdr + * + * Description: + * Read and verify the data block header at the specified offset. + * + * Input Parameters: + * volume - Describes the current volume. + * offset - The byte offset from the beginning of FLASH where the data block + * header is expected. + * datlen - A memory location to return the data block length. + * + * Returned Value: + * Zero on success. Otherwise, a negated errno value is returned + * indicating the nature of the failure. + * + ****************************************************************************/ + +int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset, + FAR uint16_t *datlen) +{ + struct nxffs_data_s blkhdr; + uint32_t ecrc; + uint32_t crc; + uint16_t doffset; + uint16_t dlen; + int ret; + + /* Make sure the the block containing the data block header is in the cache */ + + nxffs_ioseek(volume, offset); + ret = nxffs_rdcache(volume, volume->ioblock); + if (ret < 0) + { + fvdbg("Failed to read data into cache: %d\n", ret); + return ret; + } + + /* Read the header at the FLASH offset */ + + doffset = volume->iooffset; + memcpy(&blkhdr, &volume->cache[doffset], SIZEOF_NXFFS_DATA_HDR); + + /* Extract the data length */ + + dlen = nxffs_rdle16(blkhdr.datlen); + + /* Get the offset to the beginning of the data */ + + doffset += SIZEOF_NXFFS_DATA_HDR; + + /* Make sure that all of the data fits within the block */ + + if ((uint32_t)doffset + (uint32_t)dlen > (uint32_t)volume->geo.blocksize) + { + fdbg("Data length=%d is unreasonable at offset=%d\n", dlen, doffset); + return -EIO; + } + + /* Extract the expected CRC and calculate the CRC of the data block */ + + ecrc = nxffs_rdle32(blkhdr.crc); + + nxffs_wrle32(blkhdr.crc, 0); + crc = crc32((FAR const uint8_t *)&blkhdr, SIZEOF_NXFFS_DATA_HDR); + crc = crc32part(&volume->cache[doffset], dlen, crc); + + if (crc != ecrc) + { + fdbg("CRC failure\n"); + return -EIO; + } + + /* Looks good! Return the data length and success */ + + *datlen = dlen; + return OK; +} + + + diff --git a/nuttx/fs/nxffs/nxffs_reformat.c b/nuttx/fs/nxffs/nxffs_reformat.c new file mode 100644 index 0000000000..cb10862ff0 --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_reformat.c @@ -0,0 +1,267 @@ +/**************************************************************************** + * fs/nxffs/nxffs_reformat.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_format + * + * Description: + * Erase and reformat the entire volume. + * + * Input Parameters: + * volume - Describes the NXFFS volume to be reformatted. + * + * Returned Value: + * Zero on success or a negated errno on a failure. Failures will be + * returned n the case of MTD reported failures o. + * Nothing in the volume data itself will generate errors. + * + ****************************************************************************/ + +static int nxffs_format(FAR struct nxffs_volume_s *volume) +{ + FAR uint8_t *blkptr; /* Pointer to next block data */ + off_t eblock; /* Erase block number */ + off_t lblock; /* Logical block number */ + ssize_t nxfrd; /* Number of blocks transferred */ + int i; + int ret; + + /* Create an image of one properly formatted erase sector */ + + memset(volume->pack, CONFIG_NXFFS_ERASEDSTATE, volume->geo.erasesize); + for (blkptr = volume->pack, i = 0; + i < volume->blkper; + blkptr += volume->geo.blocksize, i++) + { + FAR struct nxffs_block_s *blkhdr = (FAR struct nxffs_block_s*)blkptr; + memcpy(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE); + blkhdr->state = BLOCK_STATE_GOOD; + } + + /* Erase and format each erase block */ + + for (eblock = 0; eblock < volume->geo.neraseblocks; eblock++) + { + /* Erase the block */ + + ret = MTD_ERASE(volume->mtd, eblock, 1); + if (ret < 0) + { + fdbg("Erase block %d failed: %d\n", eblock, ret); + return ret; + } + + /* Write the formatted image to the erase block */ + + lblock = eblock * volume->blkper; + nxfrd = MTD_BWRITE(volume->mtd, lblock, volume->blkper, volume->pack); + if (nxfrd != volume->blkper) + { + fdbg("Write erase block %d failed: %d\n", lblock, nxfrd); + return -EIO; + } + } + + return OK; +} + +/**************************************************************************** + * Name: nxffs_badblocks + * + * Description: + * Verify each block and mark improperly erased blocks as bad. + * + * Input Parameters: + * volume - Describes the NXFFS volume to be reformatted. + * + * Returned Value: + * Zero on success or a negated errno on a failure. Failures will be + * returned n the case of MTD reported failures o. + * Nothing in the volume data itself will generate errors. + * + ****************************************************************************/ + +static int nxffs_badblocks(FAR struct nxffs_volume_s *volume) +{ + FAR uint8_t *blkptr; /* Pointer to next block data */ + off_t eblock; /* Erase block number */ + off_t lblock; /* Logical block number */ + ssize_t nxfrd; /* Number of blocks transferred */ + bool good; /* TRUE: block is good */ + bool modified; /* TRUE: The erase block has been modified */ + int i; + + /* Read and verify each erase block */ + + for (eblock = 0; eblock < volume->geo.neraseblocks; eblock++) + { + /* Read the entire erase block */ + + lblock = eblock * volume->blkper; + nxfrd = MTD_BREAD(volume->mtd, lblock, volume->blkper, volume->pack); + if (nxfrd != volume->blkper) + { + fdbg("Read erase block %d failed: %d\n", lblock, nxfrd); + return -EIO; + } + + /* Process each logical block */ + + modified = false; + for (blkptr = volume->pack, i = 0; + i < volume->blkper; + blkptr += volume->geo.blocksize, i++) + { + FAR struct nxffs_block_s *blkhdr = (FAR struct nxffs_block_s*)blkptr; + + /* Check block header */ + + good = true; + if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) != 0 || + blkhdr->state != BLOCK_STATE_GOOD) + { + good = false; + } + + /* Check that block data is erased */ + + else + { + size_t blocksize = volume->geo.blocksize - SIZEOF_NXFFS_BLOCK_HDR; + size_t erasesize = nxffs_erased(&blkptr[SIZEOF_NXFFS_BLOCK_HDR], blocksize); + good = (blocksize == erasesize); + } + + /* If the block is bad, attempt to re-write the block header indicating + * a bad block (of course, if the block has failed, this may not be + * possible, depending upon failure modes. + */ + + if (!good) + { + memcpy(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE); + blkhdr->state = BLOCK_STATE_BAD; + modified = true; + } + } + + /* If the erase block was modified, then re-write it */ + + nxfrd = MTD_BWRITE(volume->mtd, lblock, volume->blkper, volume->pack); + if (nxfrd != volume->blkper) + { + fdbg("Write erase block %d failed: %d\n", lblock, nxfrd); + return -EIO; + } + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_reformat + * + * Description: + * Erase and reformat the entire volume. Verify each block and mark + * improperly erased blocks as bad. + * + * Input Parameters: + * volume - Describes the NXFFS volume to be reformatted. + * + * Returned Value: + * Zero on success or a negated errno on a failure. Failures will be + * returned n the case of MTD reported failures o. + * Nothing in the volume data itself will generate errors. + * + ****************************************************************************/ + +int nxffs_reformat(FAR struct nxffs_volume_s *volume) +{ + int ret; + + /* Erase and reformat the entire volume */ + + ret = nxffs_format(volume); + if (ret < 0) + { + fdbg("Failed to reformat the volume: %d\n", -ret); + return ret; + } + + /* Check for bad blocks */ + + ret = nxffs_badblocks(volume); + if (ret < 0) + { + fdbg("Bad block check failed: %d\n", -ret); + } + return ret; +} diff --git a/nuttx/fs/nxffs/nxffs_stat.c b/nuttx/fs/nxffs/nxffs_stat.c new file mode 100644 index 0000000000..afb18093ca --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_stat.c @@ -0,0 +1,186 @@ +/**************************************************************************** + * fs/nxffs/nxffs_stat.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_statfs + * + * Description: Return filesystem statistics + * + ****************************************************************************/ + +int nxffs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf) +{ + FAR struct nxffs_volume_s *volume; + int ret; + + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the NuttX inode structure */ + + volume = mountpt->i_private; + ret = sem_wait(&volume->exclsem); + if (ret != OK) + { + goto errout; + } + + /* Fill in the statfs info */ +#warning "Need f_bfree, f_bavail, f_files, f_ffree calculation" + + memset(buf, 0, sizeof(struct statfs)); + buf->f_type = NXFFS_MAGIC; + buf->f_bsize = volume->geo.blocksize; + buf->f_blocks = volume->nblocks; + buf->f_namelen = volume->geo.blocksize - SIZEOF_NXFFS_BLOCK_HDR - SIZEOF_NXFFS_INODE_HDR; + ret = OK; + + sem_post(&volume->exclsem); +errout: + return ret; +} + +/**************************************************************************** + * Name: nxffs_stat + * + * Description: Return information about a file or directory + * + ****************************************************************************/ + +int nxffs_stat(FAR struct inode *mountpt, FAR const char *relpath, + FAR struct stat *buf) +{ + FAR struct nxffs_volume_s *volume; + struct nxffs_entry_s entry; + int ret; + + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private && buf); + + /* Get the mountpoint private data from the NuttX inode structure */ + + volume = mountpt->i_private; + ret = sem_wait(&volume->exclsem); + if (ret != OK) + { + goto errout; + } + + /* Initialize the return stat instance */ + + memset(buf, 0, sizeof(struct stat)); + buf->st_blksize = volume->geo.blocksize; + buf->st_blocks = entry.datlen / (volume->geo.blocksize - SIZEOF_NXFFS_BLOCK_HDR); + + /* The requested directory must be the volume-relative "root" directory */ + + if (relpath && relpath[0] != '\0') + { + /* Not the top directory.. find the NXFFS inode with this name */ + + ret = nxffs_findinode(volume, relpath, &entry); + if (ret < 0) + { + fdbg("Inode '%s' not found: %d\n", -ret); + goto errout_with_semaphore; + } + + buf->st_mode = S_IFREG|S_IXOTH|S_IXGRP|S_IXUSR; + buf->st_size = entry.datlen; + buf->st_atime = entry.utc; + buf->st_mtime = entry.utc; + buf->st_ctime = entry.utc; + } + else + { + /* It's a read/execute-only directory name */ + + buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR|S_IXOTH|S_IXGRP|S_IXUSR; + } + + ret = OK; + +errout_with_semaphore: + sem_post(&volume->exclsem); +errout: + return ret; +} diff --git a/nuttx/fs/nxffs/nxffs_unlink.c b/nuttx/fs/nxffs/nxffs_unlink.c new file mode 100644 index 0000000000..9d0d5b49e3 --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_unlink.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * fs/nxffs/nxffs_unlink.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_rminode + * + * Description: + * Remove an inode from FLASH. This is the internal implementation of + * the file system unlinke operation. + * + * Input Parameters: + * volume - Describes the NXFFS volume. + * name - the name of the inode to be deleted. + * + * Returned Value: + * Zero is returned if the inode is successfully deleted. Otherwise, a + * negated errno value is returned indicating the nature of the failure. + * + ****************************************************************************/ + +int nxffs_rminode(FAR struct nxffs_volume_s *volume, FAR const char *name) +{ + FAR struct nxffs_ofile_s *ofile; + FAR struct nxffs_inode_s *inode; + struct nxffs_entry_s entry; + int ret; + + /* Check if the file is open */ + + ofile = nxffs_findofile(volume, name); + if (ofile) + { + /* We can't remove the inode if it is open */ + + fdbg("Inode '%s' is open\n", name); + ret = -EBUSY; + goto errout; + } + + /* Find the NXFFS inode */ + + ret = nxffs_findinode(volume, name, &entry); + if (ret < 0) + { + fdbg("Inode '%s' not found\n", name); + goto errout; + } + + /* Set the position to the FLASH offset of the file header (nxffs_findinode + * should have left the block in the cache). + */ + + nxffs_ioseek(volume, entry.hoffset); + + /* Make sure the the block is in the cache */ + + ret = nxffs_rdcache(volume, volume->ioblock); + if (ret < 0) + { + fdbg("Failed to read data into cache: %d\n", ret); + goto errout_with_entry; + } + + /* Change the file status... it is no longer valid */ + + inode = (FAR struct nxffs_inode_s *)&volume->cache[volume->iooffset]; + inode->state = INODE_STATE_DELETED; + + /* Then write the cached block back to FLASH */ + + ret = nxffs_wrcache(volume); + if (ret < 0) + { + fdbg("Failed to read data into cache: %d\n", ret); + } + +errout_with_entry: + nxffs_freeentry(&entry); +errout: + return ret; +} + +/**************************************************************************** + * Name: nxffs_unlink + * + * Description: Remove a file + * + ****************************************************************************/ + +int nxffs_unlink(FAR struct inode *mountpt, FAR const char *relpath) +{ + FAR struct nxffs_volume_s *volume; + int ret; + + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the NuttX inode structure */ + + volume = mountpt->i_private; + ret = sem_wait(&volume->exclsem); + if (ret != OK) + { + goto errout; + } + + /* Then remove the NXFFS inode */ + + ret = nxffs_rminode(volume, relpath); + + sem_post(&volume->exclsem); +errout: + return ret; +} diff --git a/nuttx/fs/nxffs/nxffs_util.c b/nuttx/fs/nxffs/nxffs_util.c new file mode 100644 index 0000000000..ea2e97967e --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_util.c @@ -0,0 +1,181 @@ +/**************************************************************************** + * fs/nxffs/nxffs_util.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_rdle16 + * + * Description: + * Get a (possibly unaligned) 16-bit little endian value. + * + * Input Parameters: + * val - A pointer to the first byte of the little endian value. + * + * Returned Value: + * A uint16_t representing the whole 16-bit integer value + * + ****************************************************************************/ + +uint16_t nxffs_rdle16(FAR const uint8_t *val) +{ + return (uint16_t)val[1] << 8 | (uint16_t)val[0]; +} + +/**************************************************************************** + * Name: nxffs_wrle16 + * + * Description: + * Put a (possibly unaligned) 16-bit little endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the little endian value. + * val - The 16-bit value to be saved. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void nxffs_wrle16(uint8_t *dest, uint16_t val) +{ + dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */ + dest[1] = val >> 8; +} + +/**************************************************************************** + * Name: nxffs_rdle32 + * + * Description: + * Get a (possibly unaligned) 32-bit little endian value. + * + * Input Parameters: + * val - A pointer to the first byte of the little endian value. + * + * Returned Value: + * A uint32_t representing the whole 32-bit integer value + * + ****************************************************************************/ + +uint32_t nxffs_rdle32(FAR const uint8_t *val) +{ + /* Little endian means LS halfword first in byte stream */ + + return (uint32_t)nxffs_rdle16(&val[2]) << 16 | (uint32_t)nxffs_rdle16(val); +} + +/**************************************************************************** + * Name: nxffs_wrle32 + * + * Description: + * Put a (possibly unaligned) 32-bit little endian value. + * + * Input Parameters: + * dest - A pointer to the first byte to save the little endian value. + * val - The 32-bit value to be saved. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void nxffs_wrle32(uint8_t *dest, uint32_t val) +{ + /* Little endian means LS halfword first in byte stream */ + + nxffs_wrle16(dest, (uint16_t)(val & 0xffff)); + nxffs_wrle16(dest+2, (uint16_t)(val >> 16)); +} + +/**************************************************************************** + * Name: nxffs_erased + * + * Description: + * Check if a block of memory is in the erased state. + * + * Input Parameters: + * buffer - Address of the start of the memory to check. + * buflen - The number of bytes to check. + * + * Returned Values: + * The number of erased bytes found at the beginning of the memory region. + * + ****************************************************************************/ + +size_t nxffs_erased(FAR const uint8_t *buffer, size_t buflen) +{ + size_t nerased = 0; + + for (; nerased < buflen; nerased++) + { + if (*buffer != CONFIG_NXFFS_ERASEDSTATE) + { + break; + } + buffer++; + } + + return nerased; +} diff --git a/nuttx/fs/nxffs/nxffs_write.c b/nuttx/fs/nxffs/nxffs_write.c new file mode 100644 index 0000000000..bf32b0fb45 --- /dev/null +++ b/nuttx/fs/nxffs/nxffs_write.c @@ -0,0 +1,853 @@ +/**************************************************************************** + * fs/nxffs/nxffs_write.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "nxffs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_hdrpos + * + * Description: + * Find a valid location for the data block header. A valid location will + * have these properties: + * + * 1. It will lie in the free flash region. + * 2. It will have enough contiguous memory to hold the entire header + * PLUS some meaningful amount of data (NXFFS_MINDATA). + * 3. The memory at this location will be fully erased. + * + * This function will only perform the checks of 1) and 2). + * + * Input Parameters: + * volume - Describes the NXFFS volume + * wrfile - Contains the current guess for the header position. On + * successful return, this field will hold the selected header + * position. + * size - The minimum size of the current write. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. Of special interest + * the return error of -ENOSPC which means that the FLASH volume is + * full and should be repacked. + * + * On successful return the following are also valid: + * + * wrfile->doffset - Flash offset to candidate data block header position + * volume->ioblock - Read/write block number of the block containing the + * header position + * volume->iooffset - The offset in the block to the candidate header + * position. + * volume->froffset - Updated offset to the first free FLASH block. + * + ****************************************************************************/ + +static inline int nxffs_hdrpos(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_wrfile_s *wrfile, + size_t size) +{ + int ret; + + /* Reserve memory for the object */ + + ret = nxffs_wrreserve(volume, SIZEOF_NXFFS_DATA_HDR + size); + if (ret == OK) + { + /* Save the offset to the FLASH region reserved for the data block + * header + */ + + wrfile->doffset = nxffs_iotell(volume); + } + return ret; +} + +/**************************************************************************** + * Name: nxffs_hdrerased + * + * Description: + * Find a valid location for the data block header. A valid location will + * have these properties: + * + * 1. It will lie in the free flash region. + * 2. It will have enough contiguous memory to hold the entire header + * PLUS some meaningful amount of data (NXFFS_MINDATA). + * 3. The memory at this location will be fully erased. + * + * This function will only perform the check 3). On entry it assumes: + * + * volume->ioblock - Read/write block number of the block containing the + * header position + * volume->iooffset - The offset in the block to the candidate header + * position. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * wrfile - Contains the current guess for the header position. On + * successful return, this field will hold the selected header + * position. + * size - The minimum size of the current write. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. Of special interest + * the return error of -ENOSPC which means that the FLASH volume is + * full and should be repacked. + * + * On successful return the following are also valid: + * + * wrfile->doffset - Flash offset to candidate data block header position + * volume->ioblock - Read/write block number of the block containing the + * header position + * volume->iooffset - The offset in the block to the candidate header + * position. + * volume->froffset - Updated offset to the first free FLASH block. + * + ****************************************************************************/ + +static inline int nxffs_hdrerased(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_wrfile_s *wrfile, + size_t size) +{ + int ret; + + /* Find a valid location to save the inode header */ + + ret = nxffs_wrverify(volume, SIZEOF_NXFFS_DATA_HDR + size); + if (ret == OK) + { + /* This is where we will put the data block header */ + + wrfile->doffset = nxffs_iotell(volume); + } + return ret; +} + +/**************************************************************************** + * Name: nxffs_wralloc + * + * Description: + * Allocate FLASH memory for the data block. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * wrfile - Describes the open file to be written. + * size - Size of the current write operation. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. + * + ****************************************************************************/ + +static inline int nxffs_wralloc(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_wrfile_s *wrfile, + size_t size) +{ + bool packed; + int ret; + + /* Allocate FLASH memory for the data block. + * + * Loop until the data block header is configured or until a failure + * occurs. Note that nothing is written to FLASH. The data block header + * is not written until either (1) the file is closed, or (2) the data + * region is fully populated. + */ + + packed = false; + for (;;) + { + size_t mindata = MIN(NXFFS_MINDATA, size); + + /* File a valid location to position the data block. Start with + * the first byte in the free FLASH region. + */ + + ret = nxffs_hdrpos(volume, wrfile, mindata); + if (ret == OK) + { + /* Find a region of memory in the block that is fully erased */ + + ret = nxffs_hdrerased(volume, wrfile, mindata); + if (ret == OK) + { + /* Valid memory for the data block was found. Return success. */ + + return OK; + } + } + + /* If no valid memory is found searching to the end of the volume, + * then -ENOSPC will be returned. Other errors are not handled. + */ + + if (ret != -ENOSPC || packed) + { + fdbg("Failed to find inode header memory: %d\n", -ret); + return -ENOSPC; + } + + /* -ENOSPC is a special case.. It means that the volume is full. + * Try to pack the volume in order to free up some space. + */ + + ret = nxffs_pack(volume); + if (ret < 0) + { + fdbg("Failed to pack the volume: %d\n", -ret); + return ret; + } + + /* After packing the volume, froffset will be updated to point to the + * new free flash region. Try again. + */ + + nxffs_ioseek(volume, volume->froffset); + packed = true; + } + + /* Can't get here */ + + return OK; +} + +/**************************************************************************** + * Name: nxffs_reverify + * + * Description: + * Verify that the partial flash data block in the volume cache is valid. + * On entry, this function assumes: + * + * volume->ioblock - Read/write block number of the block containing the + * data block. + * volume->iooffset - The offset in the block to the data block. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * wrfile - Describes the open file to be written. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. + * + ****************************************************************************/ + +static inline int nxffs_reverify(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_wrfile_s *wrfile) +{ + uint32_t crc; + off_t offset; + + if (wrfile->datlen > 0) + { + /* Get the offset to the start of the data */ + + offset = volume->iooffset + SIZEOF_NXFFS_DATA_HDR; + DEBUGASSERT(offset + wrfile->datlen < volume->geo.blocksize); + + /* Calculate the CRC of the partial data block */ + + crc = crc32(&volume->cache[offset], wrfile->datlen); + + /* It must match the previoulsy calculated CRC value */ + + if (crc != wrfile->crc) + { + fdbg("CRC failure\n"); + return -EIO; + } + } + return OK; +} + +/**************************************************************************** + * Name: nxffs_wrappend + * + * Description: + * Append FLASH data to the data block. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * wrfile - Describes the open file to be written. + * buffer - Address of buffer of data to be written. + * buflen - The number of bytes remaimining to be written + * + * Returned Value: + * The number of bytes written is returned on success. Otherwise, a + * negated errno value is returned indicating the nature of the failure. + * + ****************************************************************************/ + +static inline ssize_t nxffs_wrappend(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_wrfile_s *wrfile, + FAR const char *buffer, size_t buflen) +{ + ssize_t maxsize; + size_t nbytestowrite; + ssize_t nbytesleft; + off_t offset; + int ret; + + /* Get the offset to the start of unwritten data */ + + offset = volume->iooffset + wrfile->datlen + SIZEOF_NXFFS_DATA_HDR; + + /* Determine that maximum amount of data that can be written to this + * block. + */ + + maxsize = volume->geo.blocksize - offset; + DEBUGASSERT(maxsize > 0); + + /* But don't try to write over any unerased bytes */ + + maxsize = nxffs_erased(&volume->cache[offset], maxsize); + + /* Write as many bytes as we can into the data buffer */ + + nbytestowrite = MIN(maxsize, buflen); + nbytesleft = maxsize - nbytestowrite; + + if (nbytestowrite > 0) + { + /* Copy the data into the volume write cache */ + + memcpy(&volume->cache[offset], buffer, nbytestowrite); + + /* Increment the number of bytes written to the data block */ + + wrfile->datlen += nbytestowrite; + + /* Re-calculate the CRC */ + + offset = volume->iooffset + SIZEOF_NXFFS_DATA_HDR; + wrfile->crc = crc32(&volume->cache[offset], wrfile->datlen); + + /* And write the partial write block to FLASH -- unless the data + * block is full. In that case, the block will be written below. + */ + + if (nbytesleft > 0) + { + ret = nxffs_wrcache(volume); + if (ret < 0) + { + fdbg("nxffs_wrcache failed: %d\n", -ret); + return ret; + } + } + } + + /* Check if the data block is now full */ + + if (nbytesleft <= 0) + { + /* The data block is full, write the block to FLASH */ + + ret = nxffs_wrblkhdr(volume, wrfile); + if (ret < 0) + { + fdbg("nxffs_wrblkdhr failed: %d\n", -ret); + return ret; + } + } + + /* Return the number of bytes written to FLASH this time */ + + return nbytestowrite; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_write + * + * Description: + * This is an implementation of the NuttX standard file system write + * method. + * + ****************************************************************************/ + +ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) +{ + FAR struct nxffs_volume_s *volume; + FAR struct nxffs_wrfile_s *wrfile; + ssize_t remaining; + ssize_t nwritten; + ssize_t total; + int ret; + + fvdbg("Write %d bytes to offset %d\n", buflen, filep->f_pos); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover the open file state from the struct file instance */ + + wrfile = (FAR struct nxffs_wrfile_s *)filep->f_priv; + + /* Recover the volume state from the open file */ + + volume = (FAR struct nxffs_volume_s *)filep->f_inode->i_private; + DEBUGASSERT(volume != NULL); + + /* Get exclusive access to the volume. Note that the volume exclsem + * protects the open file list. + */ + + ret = sem_wait(&volume->exclsem); + if (ret != OK) + { + ret = -errno; + fdbg("sem_wait failed: %d\n", ret); + goto errout; + } + + /* Check if the file was opened with write access */ + + if ((wrfile->ofile.oflags & O_WROK) == 0) + { + fdbg("File not open for write access\n"); + ret = -EACCES; + goto errout_with_semaphore; + } + + /* Loop until we successfully appended all of the data to the file (or an + * error occurs) + */ + + for (total = 0; total < buflen; ) + { + remaining = buflen - total; + + /* Have we already allocated the data block? */ + + if (wrfile->doffset == 0) + { + /* No, allocate the data block now, re-packing if necessary. */ + + wrfile->datlen = 0; + ret = nxffs_wralloc(volume, wrfile, remaining); + if (ret < 0) + { + fdbg("Failed to allocate a data block: %d\n", -ret); + goto errout_with_semaphore; + } + } + + /* Seek to the FLASH block containing the data block */ + + nxffs_ioseek(volume, wrfile->doffset); + + /* Verify that the FLASH data that was previously written is still intact */ + + ret = nxffs_reverify(volume, wrfile); + if (ret < 0) + { + fdbg("Failed to verify FLASH data block: %d\n", -ret); + goto errout_with_semaphore; + } + + /* Append the data to the end of the data block and write the updated + * block to flash. + */ + + nwritten = nxffs_wrappend(volume, wrfile, &buffer[total], remaining); + if (nwritten < 0) + { + fdbg("Failed to append to FLASH to a data block: %d\n", -ret); + goto errout_with_semaphore; + } + + /* Decrement the number of bytes remaining to be written */ + + total += nwritten; + } + + /* Success.. return the number of bytes written */ + + ret = total; + filep->f_pos = wrfile->datlen; + +errout_with_semaphore: + sem_post(&volume->exclsem); +errout: + return ret; +} + +/**************************************************************************** + * Name: nxffs_wrreserve + * + * Description: + * Find a valid location for a file system object of 'size'. A valid + * location will have these properties: + * + * 1. It will lie in the free flash region. + * 2. It will have enough contiguous memory to hold the entire object + * 3. The memory at this location will be fully erased. + * + * This function will only perform the checks of 1) and 2). The + * end-of-filesystem offset, froffset, is update past this memory which, + * in effect, reserves the memory. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * size - The size of the object to be reserved. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. Of special interest + * the return error of -ENOSPC which means that the FLASH volume is + * full and should be repacked. + * + * On successful return the following are also valid: + * + * volume->ioblock - Read/write block number of the block containing the + * candidate oject position + * volume->iooffset - The offset in the block to the candidate object + * position. + * volume->froffset - Updated offset to the first free FLASH block after + * the reserved memory. + * + ****************************************************************************/ + +int nxffs_wrreserve(FAR struct nxffs_volume_s *volume, size_t size) +{ + int ret; + + /* Seek to the beginning of the free FLASH region */ + + nxffs_ioseek(volume, volume->froffset); + + /* Check for a seek past the end of the volume */ + + if (volume->ioblock >= volume->nblocks) + { + /* Return -ENOSPC to indicate that the volume is full */ + + return -ENOSPC; + } + + /* Skip over block headers */ + + if (volume->iooffset < SIZEOF_NXFFS_BLOCK_HDR) + { + volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR; + } + + /* Make sure that there is space there to hold the entire object */ + + if (volume->iooffset + size > volume->geo.blocksize) + { + /* We will need to skip to the next block. But first, check if we are + * already at the final block. + */ + + if (volume->ioblock + 1 >= volume->nblocks) + { + /* Return -ENOSPC to indicate that the volume is full */ + + fdbg("No space in last block\n"); + return -ENOSPC; + } + + /* This is not the last block in the volume, so just seek to the + * beginning of the next, valid block. + */ + + volume->ioblock++; + ret = nxffs_validblock(volume, &volume->ioblock); + if (ret < 0) + { + fdbg("No more valid blocks\n"); + return ret; + } + volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR; + } + + /* Update the pointer to the first next free FLASH memory -- reserving this + * block of memory. + */ + + volume->froffset = nxffs_iotell(volume) + size; + return OK; +} + +/**************************************************************************** + * Name: nxffs_wrverify + * + * Description: + * Find a valid location for the object. A valid location will have + * these properties: + * + * 1. It will lie in the free flash region. + * 2. It will have enough contiguous memory to hold the entire header + * (excluding the file name which may lie in the next block). + * 3. The memory at this location will be fully erased. + * + * This function will only perform the check 3). On entry it assumes the + * following settings (left by nxffs_wrreserve()): + * + * volume->ioblock - Read/write block number of the block containing the + * candidate oject position + * volume->iooffset - The offset in the block to the candidate object + * position. + * + * Input Parameters: + * volume - Describes the NXFFS volume + * size - The size of the object to be verifed. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned indicating the nature of the failure. Of special interest + * the return error of -ENOSPC which means that the FLASH volume is + * full and should be repacked. + * + * On successful return the following are also valid: + * + * volume->ioblock - Read/write block number of the block containing the + * verified object position + * volume->iooffset - The offset in the block to the verified object + * position. + * volume->froffset - Updated offset to the first free FLASH block. + * + ****************************************************************************/ + +int nxffs_wrverify(FAR struct nxffs_volume_s *volume, size_t size) +{ + uint16_t iooffset; + int nerased; + int ret; + int i; + + /* Search to the very last block in the volume if we have to */ + + while (volume->ioblock < volume->nblocks) + { + /* Make sure that the block is in memory */ + + ret = nxffs_rdcache(volume, volume->ioblock); + if (ret < 0) + { + fdbg("Failed to read block %d: %d\n", volume->ioblock, -ret); + return ret; + } + + /* Search to the very end of this block if we have to */ + + iooffset = volume->iooffset; + nerased = 0; + + for (i = volume->iooffset; i < volume->geo.blocksize; i++) + { + /* Is this byte erased? */ + + if (volume->cache[i] == CONFIG_NXFFS_ERASEDSTATE) + { + /* Yes.. increment the count of contiguous, erased bytes */ + + nerased++; + + /* Is the whole header memory erased? */ + + if (nerased >= size) + { + /* Yes.. this this is where we will put the object */ + + off_t offset = volume->ioblock * volume->geo.blocksize + iooffset; + + /* Update the free flash offset and return success */ + + volume->froffset = offset + size; + return OK; + } + } + + /* This byte is not erased! (It should be unless the block is bad) */ + + else + { + nerased = 0; + iooffset = i + 1; + } + } + + /* If we get here, then we have looked at every byte in the the block + * and did not find any sequence of erased bytes long enough to hold + * the object. Skip to the next, valid block. + */ + + volume->ioblock++; + ret = nxffs_validblock(volume, &volume->ioblock); + if (ret < 0) + { + fdbg("No more valid blocks\n"); + return ret; + } + + volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR; + volume->froffset = volume->ioblock * volume->geo.blocksize + SIZEOF_NXFFS_BLOCK_HDR; + } + + /* Return -ENOSPC if there is no erased memory left in the volume for + * the object. + */ + + fdbg("Not enough memory left to hold the file header\n"); + return -ENOSPC; +} + +/**************************************************************************** + * Name: nxffs_wrblkhdr + * + * Description: + * Write the block header information. This is done (1) whenever the end- + * block is encountered and (2) also when the file is closed in order to + * flush the final block of data to FLASH. + * + * Input Parameters: + * volume - Describes the state of the NXFFS volume + * wrfile - Describes the state of the open file + * + * Returned Value: + * Zero is returned on success; Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int nxffs_wrblkhdr(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_wrfile_s *wrfile) +{ + FAR struct nxffs_data_s *dathdr; + int ret; + + /* Write the data block header to memory */ + + nxffs_ioseek(volume, wrfile->doffset); + dathdr = (FAR struct nxffs_data_s *)&volume->cache[volume->iooffset]; + memcpy(dathdr->magic, g_datamagic, NXFFS_MAGICSIZE); + nxffs_wrle32(dathdr->crc, 0); + nxffs_wrle16(dathdr->datlen, wrfile->datlen); + + /* Update the entire data block CRC (including the header) */ + + wrfile->crc = crc32(&volume->cache[volume->iooffset], wrfile->datlen + SIZEOF_NXFFS_DATA_HDR); + nxffs_wrle32(dathdr->crc, wrfile->crc); + + /* And write the data block to FLASH */ + + ret = nxffs_wrcache(volume); + if (ret < 0) + { + fdbg("nxffs_wrcache failed: %d\n", -ret); + goto errout; + } + + /* After the block has been successfully written to flash, update the inode + * statistics and reset the write state. + * + * volume: + * froffset - The offset the next free FLASH region. Set to just after + * the inode data block that we just wrote. This is where we will + * begin the search for the next inode header or data block. + */ + + volume->froffset = (wrfile->doffset + wrfile->datlen + SIZEOF_NXFFS_DATA_HDR); + + /* wrfile->file.entry: + * datlen: Total file length accumulated so far. When the file is + * closed, this will hold the file length. + * doffset: Offset to the first data block. Only the offset to the + * first data block is saved. + */ + + wrfile->ofile.entry.datlen += wrfile->datlen; + if (wrfile->ofile.entry.doffset == 0) + { + wrfile->ofile.entry.doffset = wrfile->doffset; + } + + /* Return success */ + + ret = OK; + +errout: + wrfile->crc = 0; + wrfile->doffset = 0; + wrfile->datlen = 0; + return ret; +} + diff --git a/nuttx/fs/romfs/Kconfig b/nuttx/fs/romfs/Kconfig new file mode 100644 index 0000000000..6a91011abf --- /dev/null +++ b/nuttx/fs/romfs/Kconfig @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config FS_ROMFS + bool "ROMFS file system" + default n + depends on !DISABLE_MOUNTPOINT + ---help--- + Enable ROMFS filesystem support + +if FS_ROMFS +endif diff --git a/nuttx/fs/romfs/Make.defs b/nuttx/fs/romfs/Make.defs new file mode 100644 index 0000000000..56b4c9862a --- /dev/null +++ b/nuttx/fs/romfs/Make.defs @@ -0,0 +1,45 @@ +############################################################################ +# fs/romfs/Make.defs +# +# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name Nuttx nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_FS_ROMFS),y) +# Files required for ROMFS file system support + +ASRCS += +CSRCS += fs_romfs.c fs_romfsutil.c + +# Argument for dependency checking + +ROMFSDEPPATH = --dep-path romfs +endif diff --git a/nuttx/fs/romfs/fs_romfs.c b/nuttx/fs/romfs/fs_romfs.c new file mode 100644 index 0000000000..8a2e696654 --- /dev/null +++ b/nuttx/fs/romfs/fs_romfs.c @@ -0,0 +1,1090 @@ +/**************************************************************************** + * rm/romfs/fs_romfs.h + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "fs_romfs.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int romfs_open(FAR struct file *filep, const char *relpath, + int oflags, mode_t mode); +static int romfs_close(FAR struct file *filep); +static ssize_t romfs_read(FAR struct file *filep, char *buffer, size_t buflen); +static off_t romfs_seek(FAR struct file *filep, off_t offset, int whence); +static int romfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg); + +static int romfs_opendir(struct inode *mountpt, const char *relpath, + struct fs_dirent_s *dir); +static int romfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir); +static int romfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir); + +static int romfs_bind(FAR struct inode *blkdriver, const void *data, + void **handle); +static int romfs_unbind(void *handle, FAR struct inode **blkdriver); +static int romfs_statfs(struct inode *mountpt, struct statfs *buf); + +static int romfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf); + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* See fs_mount.c -- this structure is explicitly externed there. + * We use the old-fashioned kind of initializers so that this will compile + * with any compiler. + */ + +const struct mountpt_operations romfs_operations = +{ + romfs_open, /* open */ + romfs_close, /* close */ + romfs_read, /* read */ + NULL, /* write */ + romfs_seek, /* seek */ + romfs_ioctl, /* ioctl */ + NULL, /* sync */ + + romfs_opendir, /* opendir */ + NULL, /* closedir */ + romfs_readdir, /* readdir */ + romfs_rewinddir, /* rewinddir */ + + romfs_bind, /* bind */ + romfs_unbind, /* unbind */ + romfs_statfs, /* statfs */ + + NULL, /* unlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* rename */ + romfs_stat /* stat */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: romfs_open + ****************************************************************************/ + +static int romfs_open(FAR struct file *filep, const char *relpath, + int oflags, mode_t mode) +{ + struct romfs_dirinfo_s dirinfo; + struct romfs_mountpt_s *rm; + struct romfs_file_s *rf; + int ret; + + fvdbg("Open '%s'\n", relpath); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL); + + /* mountpoint private data from the inode reference from the file + * structure + */ + + rm = (struct romfs_mountpt_s*)filep->f_inode->i_private; + + DEBUGASSERT(rm != NULL); + + /* Check if the mount is still healthy */ + + romfs_semtake(rm); + ret = romfs_checkmount(rm); + if (ret != OK) + { + fdbg("romfs_checkmount failed: %d\n", ret); + goto errout_with_semaphore; + } + + /* ROMFS is read-only. Any attempt to open with any kind of write + * access is not permitted. + */ + + if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0) + { + fdbg("Only O_RDONLY supported\n"); + ret = -EACCES; + goto errout_with_semaphore; + } + + /* Initialize the directory info structure */ + + memset(&dirinfo, 0, sizeof(struct romfs_dirinfo_s)); + + /* Locate the directory entry for this path */ + + ret = romfs_finddirentry(rm, &dirinfo, relpath); + if (ret < 0) + { + fdbg("Failed to find directory directory entry for '%s': %d\n", + relpath, ret); + goto errout_with_semaphore; + } + + /* The full path exists -- but is the final component a file + * or a directory? + */ + + if (IS_DIRECTORY(dirinfo.rd_next)) + { + /* It is a directory */ + + ret = -EISDIR; + fdbg("'%s' is a directory\n", relpath); + goto errout_with_semaphore; + } + +#ifdef CONFIG_FILE_MODE +# warning "Missing check for privileges based on inode->i_mode" +#endif + + /* Create an instance of the file private data to describe the opened + * file. + */ + + rf = (struct romfs_file_s *)zalloc(sizeof(struct romfs_file_s)); + if (!rf) + { + fdbg("Failed to allocate private data\n", ret); + ret = -ENOMEM; + goto errout_with_semaphore; + } + + /* Initialize the file private data (only need to initialize + * non-zero elements) + */ + + rf->rf_open = true; + rf->rf_size = dirinfo.rd_size; + + /* Get the start of the file data */ + + ret = romfs_datastart(rm, dirinfo.rd_dir.fr_curroffset, + &rf->rf_startoffset); + if (ret < 0) + { + fdbg("Failed to locate start of file data: %d\n", ret); + goto errout_with_semaphore; + } + + /* Configure buffering to support access to this file */ + + ret = romfs_fileconfigure(rm, rf); + if (ret < 0) + { + fdbg("Failed configure buffering: %d\n", ret); + goto errout_with_semaphore; + } + + /* Attach the private date to the struct file instance */ + + filep->f_priv = rf; + + /* Then insert the new instance into the mountpoint structure. + * It needs to be there (1) to handle error conditions that effect + * all files, and (2) to inform the umount logic that we are busy + * (but a simple reference count could have done that). + */ + + rf->rf_next = rm->rm_head; + rm->rm_head = rf->rf_next; + + romfs_semgive(rm); + return OK; + + /* Error exits */ + +errout_with_semaphore: + romfs_semgive(rm); + return ret; +} + +/**************************************************************************** + * Name: romfs_close + ****************************************************************************/ + +static int romfs_close(FAR struct file *filep) +{ + struct romfs_mountpt_s *rm; + struct romfs_file_s *rf; + int ret = OK; + + fvdbg("Closing\n"); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + rf = filep->f_priv; + rm = filep->f_inode->i_private; + + DEBUGASSERT(rm != NULL); + + /* Do not check if the mount is healthy. We must support closing of + * the file even when there is healthy mount. + */ + + /* Deallocate the memory structures created when the open method + * was called. + * + * Free the sector buffer that was used to manage partial sector + * accesses. + */ + + if (!rm->rm_xipbase && rf->rf_buffer) + { + free(rf->rf_buffer); + } + + /* Then free the file structure itself. */ + + free(rf); + filep->f_priv = NULL; + return ret; +} + +/**************************************************************************** + * Name: romfs_read + ****************************************************************************/ + +static ssize_t romfs_read(FAR struct file *filep, char *buffer, size_t buflen) +{ + struct romfs_mountpt_s *rm; + struct romfs_file_s *rf; + unsigned int bytesread; + unsigned int readsize; + unsigned int nsectors; + uint32_t offset; + size_t bytesleft; + off_t sector; + uint8_t *userbuffer = (uint8_t*)buffer; + int sectorndx; + int ret; + + fvdbg("Read %d bytes from offset %d\n", buflen, filep->f_pos); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + rf = filep->f_priv; + rm = filep->f_inode->i_private; + + DEBUGASSERT(rm != NULL); + + /* Make sure that the mount is still healthy */ + + romfs_semtake(rm); + ret = romfs_checkmount(rm); + if (ret != OK) + { + fdbg("romfs_checkmount failed: %d\n", ret); + goto errout_with_semaphore; + } + + /* Get the number of bytes left in the file */ + + bytesleft = rf->rf_size - filep->f_pos; + + /* Truncate read count so that it does not exceed the number + * of bytes left in the file. + */ + + if (buflen > bytesleft) + { + buflen = bytesleft; + } + + /* Loop until either (1) all data has been transferred, or (2) an + * error occurs. + */ + + readsize = 0; + while (buflen > 0) + { + /* Get the first sector and index to read from. */ + + offset = rf->rf_startoffset + filep->f_pos; + sector = SEC_NSECTORS(rm, offset); + sectorndx = offset & SEC_NDXMASK(rm); + bytesread = 0; + + /* Check if the user has provided a buffer large enough to + * hold one or more complete sectors -AND- the read is + * aligned to a sector boundary. + */ + + nsectors = SEC_NSECTORS(rm, buflen); + if (nsectors > 0 && sectorndx == 0) + { + /* Read maximum contiguous sectors directly to the user's + * buffer without using our tiny read buffer. + */ + + /* Read all of the sectors directly into user memory */ + + fvdbg("Read %d sectors starting with %d\n", nsectors, sector); + ret = romfs_hwread(rm, userbuffer, sector, nsectors); + if (ret < 0) + { + fdbg("romfs_hwread failed: %d\n", ret); + goto errout_with_semaphore; + } + + sector += nsectors; + bytesread = nsectors * rm->rm_hwsectorsize; + } + else + { + /* We are reading a partial sector. First, read the whole sector + * into the file data buffer. This is a caching buffer so if + * it is already there then all is well. + */ + + fvdbg("Read sector %d\n", sector); + ret = romfs_filecacheread(rm, rf, sector); + if (ret < 0) + { + fdbg("romfs_filecacheread failed: %d\n", ret); + goto errout_with_semaphore; + } + + /* Copy the partial sector into the user buffer */ + + bytesread = rm->rm_hwsectorsize - sectorndx; + if (bytesread > buflen) + { + /* We will not read to the end of the buffer */ + + bytesread = buflen; + } + else + { + /* We will read to the end of the buffer (or beyond) */ + + sector++; + } + + fvdbg("Return %d bytes from sector offset %d\n", bytesread, sectorndx); + memcpy(userbuffer, &rf->rf_buffer[sectorndx], bytesread); + } + + /* Set up for the next sector read */ + + userbuffer += bytesread; + filep->f_pos += bytesread; + readsize += bytesread; + buflen -= bytesread; + } + + romfs_semgive(rm); + return readsize; + +errout_with_semaphore: + romfs_semgive(rm); + return ret; +} + +/**************************************************************************** + * Name: romfs_seek + ****************************************************************************/ + +static off_t romfs_seek(FAR struct file *filep, off_t offset, int whence) +{ + struct romfs_mountpt_s *rm; + struct romfs_file_s *rf; + off_t position; + int ret; + + fvdbg("Seek to offset: %d whence: %d\n", offset, whence); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + rf = filep->f_priv; + rm = filep->f_inode->i_private; + + DEBUGASSERT(rm != NULL); + + /* Map the offset according to the whence option */ + + switch (whence) + { + case SEEK_SET: /* The offset is set to offset bytes. */ + position = offset; + break; + + case SEEK_CUR: /* The offset is set to its current location plus + * offset bytes. */ + + position = offset + filep->f_pos; + break; + + case SEEK_END: /* The offset is set to the size of the file plus + * offset bytes. */ + + position = offset + rf->rf_size; + break; + + default: + fdbg("Whence is invalid: %d\n", whence); + return -EINVAL; + } + + /* Make sure that the mount is still healthy */ + + romfs_semtake(rm); + ret = romfs_checkmount(rm); + if (ret != OK) + { + fdbg("romfs_checkmount failed: %d\n", ret); + goto errout_with_semaphore; + } + + /* Limit positions to the end of the file. */ + + if (position > rf->rf_size) + { + /* Otherwise, the position is limited to the file size */ + + position = rf->rf_size; + } + + /* Set file position and return success */ + + filep->f_pos = position; + fvdbg("New file position: %d\n", filep->f_pos); + + romfs_semgive(rm); + return OK; + +errout_with_semaphore: + romfs_semgive(rm); + return ret; +} + +/**************************************************************************** + * Name: romfs_ioctl + ****************************************************************************/ + +static int romfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + struct romfs_mountpt_s *rm; + struct romfs_file_s *rf; + FAR void **ppv = (FAR void**)arg; + + fvdbg("cmd: %d arg: %08lx\n", cmd, arg); + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + rf = filep->f_priv; + rm = filep->f_inode->i_private; + + DEBUGASSERT(rm != NULL); + + /* Only one ioctl command is supported */ + + if (cmd == FIOC_MMAP && rm->rm_xipbase && ppv) + { + /* Return the address on the media corresponding to the start of + * the file. + */ + + *ppv = (void*)(rm->rm_xipbase + rf->rf_startoffset); + return OK; + } + + fdbg("Invalid cmd: %d \n", cmd); + return -ENOTTY; +} + +/**************************************************************************** + * Name: romfs_opendir + * + * Description: + * Open a directory for read access + * + ****************************************************************************/ + +static int romfs_opendir(struct inode *mountpt, const char *relpath, + struct fs_dirent_s *dir) +{ + struct romfs_mountpt_s *rm; + struct romfs_dirinfo_s dirinfo; + int ret; + + fvdbg("relpath: '%s'\n", relpath); + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover our private data from the inode instance */ + + rm = mountpt->i_private; + + /* Make sure that the mount is still healthy */ + + romfs_semtake(rm); + ret = romfs_checkmount(rm); + if (ret != OK) + { + fdbg("romfs_checkmount failed: %d\n", ret); + goto errout_with_semaphore; + } + + /* Find the requested directory */ + + ret = romfs_finddirentry(rm, &dirinfo, relpath); + if (ret < 0) + { + fdbg("Failed to find directory '%s': %d\n", relpath, ret); + goto errout_with_semaphore; + } + + /* Verify that it is some kind of directory */ + + if (!IS_DIRECTORY(dirinfo.rd_next)) + { + /* The entry is not a directory */ + + fdbg("'%s' is not a directory: %d\n", relpath); + ret = -ENOTDIR; + goto errout_with_semaphore; + } + + /* The entry is a directory */ + + memcpy(&dir->u.romfs, &dirinfo.rd_dir, sizeof(struct fs_romfsdir_s)); + romfs_semgive(rm); + return OK; + +errout_with_semaphore: + romfs_semgive(rm); + return ERROR; +} + +/**************************************************************************** + * Name: romfs_readdir + * + * Description: Read the next directory entry + * + ****************************************************************************/ + +static int romfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) +{ + struct romfs_mountpt_s *rm; + uint32_t linkoffset; + uint32_t next; + uint32_t info; + uint32_t size; + int ret; + + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover our private data from the inode instance */ + + rm = mountpt->i_private; + + /* Make sure that the mount is still healthy */ + + romfs_semtake(rm); + ret = romfs_checkmount(rm); + if (ret != OK) + { + fdbg("romfs_checkmount failed: %d\n", ret); + goto errout_with_semaphore; + } + + /* Loop, skipping over unsupported items in the file system */ + + for (;;) + { + /* Have we reached the end of the directory */ + + if (!dir->u.romfs.fr_curroffset) + { + /* We signal the end of the directory by returning the + * special error -ENOENT + */ + + fdbg("End of directory\n"); + ret = -ENOENT; + goto errout_with_semaphore; + } + + /* Parse the directory entry */ + + ret = romfs_parsedirentry(rm, dir->u.romfs.fr_curroffset, &linkoffset, + &next, &info, &size); + if (ret < 0) + { + fdbg("romfs_parsedirentry failed: %d\n", ret); + goto errout_with_semaphore; + } + + /* Save the filename */ + + ret = romfs_parsefilename(rm, dir->u.romfs.fr_curroffset, dir->fd_dir.d_name); + if (ret < 0) + { + fdbg("romfs_parsefilename failed: %d\n", ret); + goto errout_with_semaphore; + } + + /* Set up the next directory entry offset */ + + dir->u.romfs.fr_curroffset = next & RFNEXT_OFFSETMASK; + + /* Check the file type */ + + if (IS_DIRECTORY(next)) + { + dir->fd_dir.d_type = DTYPE_DIRECTORY; + break; + } + else if (IS_FILE(next)) + { + dir->fd_dir.d_type = DTYPE_FILE; + break; + } + } + +errout_with_semaphore: + romfs_semgive(rm); + return ret; +} + +/**************************************************************************** + * Name: romfs_rewindir + * + * Description: Reset directory read to the first entry + * + ****************************************************************************/ + +static int romfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir) +{ + struct romfs_mountpt_s *rm; + int ret; + + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover our private data from the inode instance */ + + rm = mountpt->i_private; + + /* Make sure that the mount is still healthy */ + + romfs_semtake(rm); + ret = romfs_checkmount(rm); + if (ret == OK) + { + dir->u.romfs.fr_curroffset = dir->u.romfs.fr_firstoffset; + } + + romfs_semgive(rm); + return ret; +} + +/**************************************************************************** + * Name: romfs_bind + * + * Description: This implements a portion of the mount operation. This + * function allocates and initializes the mountpoint private data and + * binds the blockdriver inode to the filesystem private data. The final + * binding of the private data (containing the blockdriver) to the + * mountpoint is performed by mount(). + * + ****************************************************************************/ + +static int romfs_bind(FAR struct inode *blkdriver, const void *data, + void **handle) +{ + struct romfs_mountpt_s *rm; + int ret; + + fvdbg("Entry\n"); + + /* Open the block driver */ + + if (!blkdriver || !blkdriver->u.i_bops) + { + fdbg("No block driver/ops\n"); + return -ENODEV; + } + + if (blkdriver->u.i_bops->open && + blkdriver->u.i_bops->open(blkdriver) != OK) + { + fdbg("No open method\n"); + return -ENODEV; + } + + /* Create an instance of the mountpt state structure */ + + rm = (struct romfs_mountpt_s *)zalloc(sizeof(struct romfs_mountpt_s)); + if (!rm) + { + fdbg("Failed to allocate mountpoint structure\n"); + return -ENOMEM; + } + + /* Initialize the allocated mountpt state structure. The filesystem is + * responsible for one reference ont the blkdriver inode and does not + * have to addref() here (but does have to release in ubind(). + */ + + sem_init(&rm->rm_sem, 0, 0); /* Initialize the semaphore that controls access */ + rm->rm_blkdriver = blkdriver; /* Save the block driver reference */ + + /* Get the hardware configuration and setup buffering appropriately */ + + ret = romfs_hwconfigure(rm); + if (ret < 0) + { + fdbg("romfs_hwconfigure failed: %d\n", ret); + goto errout_with_sem; + } + + /* Then complete the mount by getting the ROMFS configuratrion from + * the ROMF header + */ + + ret = romfs_fsconfigure(rm); + if (ret < 0) + { + fdbg("romfs_fsconfigure failed: %d\n", ret); + goto errout_with_buffer; + } + + /* Mounted! */ + + *handle = (void*)rm; + romfs_semgive(rm); + return OK; + +errout_with_buffer: + if (!rm->rm_xipbase) + { + free(rm->rm_buffer); + } + +errout_with_sem: + sem_destroy(&rm->rm_sem); + free(rm); + return ret; +} + +/**************************************************************************** + * Name: romfs_unbind + * + * Description: This implements the filesystem portion of the umount + * operation. + * + ****************************************************************************/ + +static int romfs_unbind(void *handle, FAR struct inode **blkdriver) +{ + struct romfs_mountpt_s *rm = (struct romfs_mountpt_s*)handle; + int ret; + + fvdbg("Entry\n"); + +#ifdef CONFIG_DEBUG + if (!rm) + { + return -EINVAL; + } +#endif + + /* Check if there are sill any files opened on the filesystem. */ + + romfs_semtake(rm); + if (rm->rm_head) + { + /* We cannot unmount now.. there are open files */ + + fdbg("There are open files\n"); + ret = -EBUSY; + } + else + { + /* Unmount ... close the block driver */ + + if (rm->rm_blkdriver) + { + struct inode *inode = rm->rm_blkdriver; + if (inode) + { + if (inode->u.i_bops && inode->u.i_bops->close) + { + (void)inode->u.i_bops->close(inode); + } + + /* We hold a reference to the block driver but should + * not but mucking with inodes in this context. So, we will just return + * our contained reference to the block driver inode and let the umount + * logic dispose of it. + */ + + if (blkdriver) + { + *blkdriver = inode; + } + } + } + + /* Release the mountpoint private data */ + + if (!rm->rm_xipbase && rm->rm_buffer) + { + free(rm->rm_buffer); + } + + sem_destroy(&rm->rm_sem); + free(rm); + return OK; + } + + romfs_semgive(rm); + return ret; +} + +/**************************************************************************** + * Name: romfs_statfs + * + * Description: Return filesystem statistics + * + ****************************************************************************/ + +static int romfs_statfs(struct inode *mountpt, struct statfs *buf) +{ + struct romfs_mountpt_s *rm; + int ret; + + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + rm = mountpt->i_private; + + /* Check if the mount is still healthy */ + + romfs_semtake(rm); + ret = romfs_checkmount(rm); + if (ret < 0) + { + fdbg("romfs_checkmount failed: %d\n", ret); + goto errout_with_semaphore; + } + + /* Fill in the statfs info */ + + memset(buf, 0, sizeof(struct statfs)); + buf->f_type = ROMFS_MAGIC; + + /* We will claim that the optimal transfer size is the size of one sector */ + + buf->f_bsize = rm->rm_hwsectorsize; + + /* Everything else follows in units of sectors */ + + buf->f_blocks = SEC_NSECTORS(rm, rm->rm_volsize + SEC_NDXMASK(rm)); + buf->f_bfree = 0; + buf->f_bavail = 0; + buf->f_namelen = NAME_MAX; + + romfs_semgive(rm); + return OK; + +errout_with_semaphore: + romfs_semgive(rm); + return ret; +} + +/**************************************************************************** + * Name: romfs_stat + * + * Description: Return information about a file or directory + * + ****************************************************************************/ + +static int romfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf) +{ + struct romfs_mountpt_s *rm; + struct romfs_dirinfo_s dirinfo; + int ret; + + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + rm = mountpt->i_private; + + /* Check if the mount is still healthy */ + + romfs_semtake(rm); + ret = romfs_checkmount(rm); + if (ret != OK) + { + fdbg("romfs_checkmount failed: %d\n", ret); + goto errout_with_semaphore; + } + + /* Find the directory entry corresponding to relpath. */ + + ret = romfs_finddirentry(rm, &dirinfo, relpath); + + /* If nothing was found, then we fail with EEXIST */ + + if (ret < 0) + { + fvdbg("Failed to find directory: %d\n", ret); + goto errout_with_semaphore; + } + + memset(buf, 0, sizeof(struct stat)); + if (IS_DIRECTORY(dirinfo.rd_next)) + { + /* It's a read-only directory name */ + + buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR; + if (IS_EXECUTABLE(dirinfo.rd_next)) + { + buf->st_mode |= S_IXOTH|S_IXGRP|S_IXUSR; + } + } + else if (IS_FILE(dirinfo.rd_next)) + { + /* It's a read-only file name */ + + buf->st_mode = S_IFREG|S_IROTH|S_IRGRP|S_IRUSR; + if (IS_EXECUTABLE(dirinfo.rd_next)) + { + buf->st_mode |= S_IXOTH|S_IXGRP|S_IXUSR; + } + } + else + { + /* Otherwise, pretend like the unsupported node does not exist */ + + fvdbg("Unsupported inode: %d\n", dirinfo.rd_next); + ret = -ENOENT; + goto errout_with_semaphore; + } + + /* File/directory size, access block size */ + + buf->st_size = dirinfo.rd_size; + buf->st_blksize = rm->rm_hwsectorsize; + buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize; + + ret = OK; + +errout_with_semaphore: + romfs_semgive(rm); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/nuttx/fs/romfs/fs_romfs.h b/nuttx/fs/romfs/fs_romfs.h new file mode 100644 index 0000000000..f89196ff7a --- /dev/null +++ b/nuttx/fs/romfs/fs_romfs.h @@ -0,0 +1,231 @@ +/**************************************************************************** + * fs/romfs/fs_romfs.h + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_ROMFS_FS_ROMFS_H +#define __FS_ROMFS_FS_ROMFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "../fs_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Volume header (multi-byte values are big-endian) */ + +#define ROMFS_VHDR_ROM1FS 0 /* 0-7: "-rom1fs-" */ +#define ROMFS_VHDR_SIZE 8 /* 8-11: Number of accessible bytes in this fs. */ +#define ROMFS_VHDR_CHKSUM 12 /* 12-15: Checksum of the first 512 bytes. */ +#define ROMFS_VHDR_VOLNAME 16 /* 16-..: Zero terminated volume name, padded to + * 16 byte boundary. */ + +#define ROMFS_VHDR_MAGIC "-rom1fs-" + +/* File header offset (multi-byte values are big-endian) */ + +#define ROMFS_FHDR_NEXT 0 /* 0-3: Offset of the next file header + * (zero if no more files) */ +#define ROMFS_FHDR_INFO 4 /* 4-7: Info for directories/hard links/ + * devices */ +#define ROMFS_FHDR_SIZE 8 /* 8-11: Size of this file in bytes */ +#define ROMFS_FHDR_CHKSUM 12 /* 12-15: Checksum covering the meta data, + * including the file name, and + * padding. */ +#define ROMFS_FHDR_NAME 16 /* 16-..: Zero terminated volume name, padded + * to 16 byte boundary. */ + +/* Bits 0-3 of the rf_next offset provide mode information. These are the + * values specified in */ + +#define RFNEXT_MODEMASK 7 /* Bits 0-2: Mode; bit 3: Executable */ +#define RFNEXT_ALLMODEMASK 15 /* Bits 0-3: All mode bits */ +#define RFNEXT_OFFSETMASK (~15) /* Bits n-3: Offset to next entry */ + +#define RFNEXT_HARDLINK 0 /* rf_info = Link destination file header */ +#define RFNEXT_DIRECTORY 1 /* rf_info = First file's header */ +#define RFNEXT_FILE 2 /* rf_info = Unused, must be zero */ +#define RFNEXT_SOFTLINK 3 /* rf_info = Unused, must be zero */ +#define RFNEXT_BLOCKDEV 4 /* rf_info = 16/16 bits major/minor number */ +#define RFNEXT_CHARDEV 5 /* rf_info = 16/16 bits major/minor number */ +#define RFNEXT_SOCKET 6 /* rf_info = Unused, must be zero */ +#define RFNEXT_FIFO 7 /* rf_info = Unused, must be zero */ +#define RFNEXT_EXEC 8 /* Modifier of RFNEXT_DIRECTORY and RFNEXT_FILE */ + +#define IS_MODE(rfn,mode) ((((uint32_t)(rfn))&RFNEXT_MODEMASK)==(mode)) +#define IS_HARDLINK(rfn) IS_MODE(rfn,RFNEXT_HARDLINK) +#define IS_DIRECTORY(rfn) IS_MODE(rfn,RFNEXT_DIRECTORY) +#define IS_FILE(rfn) IS_MODE(rfn,RFNEXT_FILE) +#define IS_EXECUTABLE(rfn) (((rfn) & RFNEXT_EXEC) != 0) + +/* RFNEXT_SOFTLINK, RFNEXT_BLOCKDEV, RFNEXT_CHARDEV, RFNEXT_SOCKET, and + * RFNEXT_FIFO are not presently supported in NuttX. + */ + +/* Alignment macros */ + +#define ROMFS_ALIGNMENT 16 +#define ROMFS_MAXPADDING (ROMFS_ALIGNMENT-1) +#define ROMFS_ALIGNMASK (~ROMFS_MAXPADDING) +#define ROMFS_ALIGNUP(addr) ((((uint32_t)(addr))+ROMFS_MAXPADDING)&ROMFS_ALIGNMASK) +#define ROMFS_ALIGNDOWN(addr) (((uint32_t)(addr))&ROMFS_ALIGNMASK) + +/* Offset and sector conversions */ + +#define SEC_NDXMASK(r) ((r)->rm_hwsectorsize - 1) +#define SEC_NSECTORS(r,o) ((o) / (r)->rm_hwsectorsize) +#define SEC_ALIGN(r,o) ((o) & ~SEC_NDXMASK(r)) + +/* Maximum numbr of links that will be followed before we decide that there + * is a problem. + */ + +#define ROMF_MAX_LINKS 64 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This structure represents the overall mountpoint state. An instance of this + * structure is retained as inode private data on each mountpoint that is + * mounted with a fat32 filesystem. + */ + +struct romfs_file_s; +struct romfs_mountpt_s +{ + struct inode *rm_blkdriver; /* The block driver inode that hosts the FAT32 fs */ + struct romfs_file_s *rm_head; /* A list to all files opened on this mountpoint */ + + bool rm_mounted; /* true: The file system is ready */ + uint16_t rm_hwsectorsize; /* HW: Sector size reported by block driver*/ + sem_t rm_sem; /* Used to assume thread-safe access */ + uint32_t rm_rootoffset; /* Saved offset to the first root directory entry */ + uint32_t rm_hwnsectors; /* HW: The number of sectors reported by the hardware */ + uint32_t rm_volsize; /* Size of the ROMFS volume */ + uint32_t rm_cachesector; /* Current sector in the rm_buffer */ + uint8_t *rm_xipbase; /* Base address of directly accessible media */ + uint8_t *rm_buffer; /* Device sector buffer, allocated if rm_xipbase==0 */ +}; + +/* This structure represents on open file under the mountpoint. An instance + * of this structure is retained as struct file specific information on each + * opened file. + */ + +struct romfs_file_s +{ + struct romfs_file_s *rf_next; /* Retained in a singly linked list */ + bool rf_open; /* true: The file is (still) open */ + uint32_t rf_startoffset; /* Offset to the start of the file data */ + uint32_t rf_size; /* Size of the file in bytes */ + uint32_t rf_cachesector; /* Current sector in the rf_buffer */ + uint8_t *rf_buffer; /* File sector buffer, allocated if rm_xipbase==0 */ +}; + +/* This structure is used internally for describing the result of + * walking a path + */ + +struct romfs_dirinfo_s +{ + /* These values describe the directory containing the terminal + * path component (of the terminal component itself if it is + * a directory. + */ + + struct fs_romfsdir_s rd_dir; /* Describes directory. */ + + /* Values from the ROMFS file entry */ + + uint32_t rd_next; /* Offset of the next file header+flags */ + uint32_t rd_size; /* Size (if file) */ +}; + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN void romfs_semtake(struct romfs_mountpt_s *rm); +EXTERN void romfs_semgive(struct romfs_mountpt_s *rm); +EXTERN int romfs_hwread(struct romfs_mountpt_s *rm, uint8_t *buffer, + uint32_t sector, unsigned int nsectors); +EXTERN int romfs_filecacheread(struct romfs_mountpt_s *rm, + struct romfs_file_s *rf, uint32_t sector); +EXTERN int romfs_hwconfigure(struct romfs_mountpt_s *rm); +EXTERN int romfs_fsconfigure(struct romfs_mountpt_s *rm); +EXTERN int romfs_fileconfigure(struct romfs_mountpt_s *rm, + struct romfs_file_s *rf); +EXTERN int romfs_checkmount(struct romfs_mountpt_s *rm); +EXTERN int romfs_finddirentry(struct romfs_mountpt_s *rm, + struct romfs_dirinfo_s *dirinfo, + const char *path); +EXTERN int romfs_parsedirentry(struct romfs_mountpt_s *rm, + uint32_t offset, uint32_t *poffset, uint32_t *pnext, + uint32_t *pinfo, uint32_t *psize); +EXTERN int romfs_parsefilename(struct romfs_mountpt_s *rm, uint32_t offset, + char *pname); +EXTERN int romfs_datastart(struct romfs_mountpt_s *rm, uint32_t offset, + uint32_t *start); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __FS_ROMFS_FS_ROMFS_H */ diff --git a/nuttx/fs/romfs/fs_romfsutil.c b/nuttx/fs/romfs/fs_romfsutil.c new file mode 100644 index 0000000000..ec009da89d --- /dev/null +++ b/nuttx/fs/romfs/fs_romfsutil.c @@ -0,0 +1,979 @@ +/**************************************************************************** + * rm/romfs/fs_romfsutil.h + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: Linux/Documentation/filesystems/romfs.txt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "fs_romfs.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: romfs_swap32 + * + * Desciption: + * Convert the 32-bit big endian value to little endian + * + ****************************************************************************/ + +#ifndef CONFIG_ENDIAN_BIG +static inline uint32_t romfs_swap32(uint32_t value) +{ + return ((((value) & 0x000000ff) << 24) | (((value) & 0x0000ff00) << 8) | + (((value) & 0x00ff0000) >> 8) | (((value) & 0xff000000) >> 24)); +} +#endif + +/**************************************************************************** + * Name: romfs_devread32 + * + * Desciption: + * Read the big-endian 32-bit value from the mount device buffer + * + * Assumption: + * All values are aligned to 32-bit boundaries + * + ****************************************************************************/ + +static uint32_t romfs_devread32(struct romfs_mountpt_s *rm, int ndx) +{ + /* Extract the value */ + + uint32_t value = *(uint32_t*)&rm->rm_buffer[ndx]; + + /* Value is begin endian -- return the native host endian-ness. */ +#ifdef CONFIG_ENDIAN_BIG + return value; +#else + return romfs_swap32(value); +#endif +} + +/**************************************************************************** + * Name: romfs_checkentry + * + * Desciption: + * Check if the entry at offset is a directory or file path segment + * + ****************************************************************************/ + +static inline int romfs_checkentry(struct romfs_mountpt_s *rm, uint32_t offset, + const char *entryname, int entrylen, + struct romfs_dirinfo_s *dirinfo) +{ + char name[NAME_MAX+1]; + uint32_t linkoffset; + uint32_t next; + uint32_t info; + uint32_t size; + int ret; + + /* Parse the directory entry at this offset (which may be re-directed + * to some other entry if HARLINKED). + */ + + ret = romfs_parsedirentry(rm, offset, &linkoffset, &next, &info, &size); + if (ret < 0) + { + return ret; + } + + /* Now we are pointing to the real entry of interest. Is it a + * directory? Or a file? + */ + + if (IS_DIRECTORY(next) || IS_FILE(next)) + { + /* Get the name of the directory entry. */ + + ret = romfs_parsefilename(rm, offset, name); + if (ret < 0) + { + return ret; + } + + /* Then check if this the name segment we are looking for. The + * string comparison is awkward because there is no terminator + * on entryname (there is a terminator on name, however) + */ + + if (memcmp(entryname, name, entrylen) == 0 && + strlen(name) == entrylen) + { + /* Found it -- save the component info and return success */ + + if (IS_DIRECTORY(next)) + { + dirinfo->rd_dir.fr_firstoffset = info; + dirinfo->rd_dir.fr_curroffset = info; + dirinfo->rd_size = 0; + } + else + { + dirinfo->rd_dir.fr_curroffset = offset; + dirinfo->rd_size = size; + } + dirinfo->rd_next = next; + return OK; + } + } + + /* The entry is not a directory or it does not have the matching name */ + + return -ENOENT; +} + +/**************************************************************************** + * Name: romfs_devcacheread + * + * Desciption: + * Read the specified sector for specified offset into the sector cache. + * Return the index into the sector corresponding to the offset + * + ****************************************************************************/ + +int16_t romfs_devcacheread(struct romfs_mountpt_s *rm, uint32_t offset) +{ + uint32_t sector; + int ret; + + /* rm->rm_cachesector holds the current sector that is buffer in or referenced + * by rm->tm_buffer. If the requested sector is the same as this sector, + * then we do nothing. + */ + + sector = SEC_NSECTORS(rm, offset); + if (rm->rm_cachesector != sector) + { + /* Check the access mode */ + + if (rm->rm_xipbase) + { + /* In XIP mode, rf_buffer is just an offset pointer into the device + * address space. + */ + + rm->rm_buffer = rm->rm_xipbase + SEC_ALIGN(rm, offset); + } + else + { + /* In non-XIP mode, we will have to read the new sector.*/ + + ret = romfs_hwread(rm, rm->rm_buffer, sector, 1); + if (ret < 0) + { + return (int16_t)ret; + } + } + + /* Update the cached sector number */ + + rm->rm_cachesector = sector; + } + + /* Return the offset */ + + return offset & SEC_NDXMASK(rm); +} + +/**************************************************************************** + * Name: romfs_followhardlinks + * + * Desciption: + * Given the offset to a file header, check if the file is a hardlink. + * If so, traverse the hard links until the terminal, non-linked header + * so found and return that offset. + * + ****************************************************************************/ + +static int romfs_followhardlinks(struct romfs_mountpt_s *rm, uint32_t offset, + uint32_t *poffset) +{ + uint32_t next; + int16_t ndx; + int i; + + /* Loop while we are redirected by hardlinks */ + + for (i = 0; i < ROMF_MAX_LINKS; i++) + { + /* Read the sector containing the offset into memory */ + + ndx = romfs_devcacheread(rm, offset); + if (ndx < 0) + { + return ndx; + } + + /* Check if this is a hard link */ + + next = romfs_devread32(rm, ndx + ROMFS_FHDR_NEXT); + if (!IS_HARDLINK(next)) + { + *poffset = offset; + return OK; + } + + /* Follow the hard-link */ + + offset = romfs_devread32(rm, ndx + ROMFS_FHDR_INFO); + } + + return -ELOOP; +} + +/**************************************************************************** + * Name: romfs_searchdir + * + * Desciption: + * This is part of the romfs_finddirentry log. Search the directory + * beginning at dirinfo->fr_firstoffset for entryname. + * + ****************************************************************************/ + +static inline int romfs_searchdir(struct romfs_mountpt_s *rm, + const char *entryname, int entrylen, + struct romfs_dirinfo_s *dirinfo) +{ + uint32_t offset; + uint32_t next; + int16_t ndx; + int ret; + + /* Then loop through the current directory until the directory + * with the matching name is found. Or until all of the entries + * the directory have been examined. + */ + + offset = dirinfo->rd_dir.fr_firstoffset; + do + { + /* Read the sector into memory (do this before calling + * romfs_checkentry() so we won't have to read the sector + * twice in the event that the offset refers to a hardlink). + */ + + ndx = romfs_devcacheread(rm, offset); + if (ndx < 0) + { + return ndx; + } + + /* Because everything is chunked and aligned to 16-bit boundaries, + * we know that most the basic node info fits into the sector. + */ + + next = romfs_devread32(rm, ndx + ROMFS_FHDR_NEXT) & RFNEXT_OFFSETMASK; + + /* Check if the name this entry is a directory with the matching + * name + */ + + ret = romfs_checkentry(rm, offset, entryname, entrylen, dirinfo); + if (ret == OK) + { + /* Its a match! Return success */ + + return OK; + } + + /* No match... select the offset to the next entry */ + + offset = next; + } + while (next != 0); + + /* There is nothing in this directoy with that name */ + + return -ENOENT; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: romfs_semtake + ****************************************************************************/ + +void romfs_semtake(struct romfs_mountpt_s *rm) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&rm->rm_sem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(*get_errno_ptr() == EINTR); + } +} + +/**************************************************************************** + * Name: romfs_semgive + ****************************************************************************/ + +void romfs_semgive(struct romfs_mountpt_s *rm) +{ + sem_post(&rm->rm_sem); +} + +/**************************************************************************** + * Name: romfs_hwread + * + * Desciption: Read the specified sector into the sector buffer + * + ****************************************************************************/ + +int romfs_hwread(struct romfs_mountpt_s *rm, uint8_t *buffer, uint32_t sector, + unsigned int nsectors) +{ + int ret = -ENODEV; + + /* Check the access mode */ + + if (rm->rm_xipbase) + { + /* In XIP mode, we just copy the requested data */ + + memcpy(buffer, + rm->rm_xipbase + sector*rm->rm_hwsectorsize, + nsectors*rm->rm_hwsectorsize); + ret = OK; + } + else + { + /* In non-XIP mode, we have to read the data from the device */ + + struct inode *inode = rm->rm_blkdriver; + ssize_t nsectorsread; + + DEBUGASSERT(inode); + if (inode->u.i_bops && inode->u.i_bops->read) + { + nsectorsread = + inode->u.i_bops->read(inode, buffer, sector, nsectors); + + if (nsectorsread == (ssize_t)nsectors) + { + ret = OK; + } + else if (nsectorsread < 0) + { + ret = nsectorsread; + } + } + } + return ret; +} + +/**************************************************************************** + * Name: romfs_filecacheread + * + * Desciption: + * Read the specified sector into the sector cache + * + ****************************************************************************/ + +int romfs_filecacheread(struct romfs_mountpt_s *rm, struct romfs_file_s *rf, uint32_t sector) +{ + int ret; + + fvdbg("sector: %d cached: %d sectorsize: %d XIP base: %p buffer: %p\n", + sector, rf->rf_cachesector, rm->rm_hwsectorsize, + rm->rm_xipbase, rf->rf_buffer); + + /* rf->rf_cachesector holds the current sector that is buffer in or referenced + * by rf->rf_buffer. If the requested sector is the same as this sector, + * then we do nothing. + */ + + if (rf->rf_cachesector != sector) + { + /* Check the access mode */ + + if (rm->rm_xipbase) + { + /* In XIP mode, rf_buffer is just an offset pointer into the device + * address space. + */ + + rf->rf_buffer = rm->rm_xipbase + sector * rm->rm_hwsectorsize; + fvdbg("XIP buffer: %p\n", rf->rf_buffer); + } + else + { + /* In non-XIP mode, we will have to read the new sector.*/ + + fvdbg("Calling romfs_hwread\n"); + ret = romfs_hwread(rm, rf->rf_buffer, sector, 1); + if (ret < 0) + { + fdbg("romfs_hwread failed: %d\n", ret); + return ret; + } + } + + /* Update the cached sector number */ + + rf->rf_cachesector = sector; + } + + return OK; +} + +/**************************************************************************** + * Name: romfs_hwconfigure + * + * Desciption: + * This function is called as part of the ROMFS mount operation It + * configures the ROMFS filestem for use on this block driver. This includes + * the accounting for the geometry of the device, setting up any XIP modes + * of operation, and/or allocating any cache buffers. + * + ****************************************************************************/ + +int romfs_hwconfigure(struct romfs_mountpt_s *rm) +{ + struct inode *inode = rm->rm_blkdriver; + struct geometry geo; + int ret; + + /* Get the underlying device geometry */ + +#ifdef CONFIG_DEBUG + if (!inode || !inode->u.i_bops || !inode->u.i_bops->geometry) + { + return -ENODEV; + } +#endif + + ret = inode->u.i_bops->geometry(inode, &geo); + if (ret != OK) + { + return ret; + } + + if (!geo.geo_available) + { + return -EBUSY; + } + + /* Save that information in the mount structure */ + + rm->rm_hwsectorsize = geo.geo_sectorsize; + rm->rm_hwnsectors = geo.geo_nsectors; + + /* Determine if block driver supports the XIP mode of operation */ + + rm->rm_cachesector = (uint32_t)-1; + + if (inode->u.i_bops->ioctl) + { + ret = inode->u.i_bops->ioctl(inode, BIOC_XIPBASE, + (unsigned long)&rm->rm_xipbase); + if (ret == OK && rm->rm_xipbase) + { + /* Yes.. Then we will directly access the media (vs. + * copying into an allocated sector buffer. + */ + + rm->rm_buffer = rm->rm_xipbase; + rm->rm_cachesector = 0; + return OK; + } + } + + /* Allocate the device cache buffer for normal sector accesses */ + + rm->rm_buffer = (uint8_t*)malloc(rm->rm_hwsectorsize); + if (!rm->rm_buffer) + { + return -ENOMEM; + } + + return OK; +} + +/**************************************************************************** + * Name: romfs_fsconfigure + * + * Desciption: + * This function is called as part of the ROMFS mount operation It + * sets up the mount structure to include configuration information contained + * in the ROMFS header. This is the place where we actually determine if + * the media contains a ROMFS filesystem. + * + ****************************************************************************/ + +int romfs_fsconfigure(struct romfs_mountpt_s *rm) +{ + const char *name; + int16_t ndx; + + /* Then get information about the ROMFS filesystem on the devices managed + * by this block driver. Read sector zero which contains the volume header. + */ + + ndx = romfs_devcacheread(rm, 0); + if (ndx < 0) + { + return ndx; + } + + /* Verify the magic number at that identifies this as a ROMFS filesystem */ + + if (memcmp(rm->rm_buffer, ROMFS_VHDR_MAGIC, 8) != 0) + { + return -EINVAL; + } + + /* Then extract the values we need from the header and return success */ + + rm->rm_volsize = romfs_devread32(rm, ROMFS_VHDR_SIZE); + + /* The root directory entry begins right after the header */ + + name = (const char*)&rm->rm_buffer[ROMFS_VHDR_VOLNAME]; + rm->rm_rootoffset = ROMFS_ALIGNUP(ROMFS_VHDR_VOLNAME + strlen(name) + 1); + + /* and return success */ + + rm->rm_mounted = true; + return OK; +} + +/**************************************************************************** + * Name: romfs_ffileconfigure + * + * Desciption: + * This function is called as part of the ROMFS file open operation It + * sets up the file structure to handle buffer appropriately, depending + * upon XIP mode or not. + * + ****************************************************************************/ + +int romfs_fileconfigure(struct romfs_mountpt_s *rm, struct romfs_file_s *rf) +{ + /* Check if XIP access mode is supported. If so, then we do not need + * to allocate anything. + */ + + if (rm->rm_xipbase) + { + /* We'll put a valid address in rf_buffer just in case. */ + + rf->rf_cachesector = 0; + rf->rf_buffer = rm->rm_xipbase; + } + else + { + /* Nothing in the cache buffer */ + + rf->rf_cachesector = (uint32_t)-1; + + /* Create a file buffer to support partial sector accesses */ + + rf->rf_buffer = (uint8_t*)malloc(rm->rm_hwsectorsize); + if (!rf->rf_buffer) + { + return -ENOMEM; + } + } + return OK; +} + +/**************************************************************************** + * Name: romfs_checkmount + * + * Desciption: Check if the mountpoint is still valid. + * + * The caller should hold the mountpoint semaphore + * + ****************************************************************************/ + +int romfs_checkmount(struct romfs_mountpt_s *rm) +{ + struct romfs_file_s *file; + struct inode *inode; + struct geometry geo; + int ret; + + /* If the fs_mounted flag is false, then we have already handled the loss + * of the mount. + */ + + DEBUGASSERT(rm && rm->rm_blkdriver); + if (rm->rm_mounted) + { + /* We still think the mount is healthy. Check an see if this is + * still the case + */ + + inode = rm->rm_blkdriver; + if (inode->u.i_bops && inode->u.i_bops->geometry) + { + ret = inode->u.i_bops->geometry(inode, &geo); + if (ret == OK && geo.geo_available && !geo.geo_mediachanged) + { + return OK; + } + } + + /* If we get here, the mount is NOT healthy */ + + rm->rm_mounted = false; + + /* Make sure that this is flagged in every opened file */ + + for (file = rm->rm_head; file; file = file->rf_next) + { + file->rf_open = false; + } + } + return -ENODEV; +} + +/**************************************************************************** + * Name: romfs_finddirentry + * + * Desciption: + * Given a path to something that may or may not be in the file system, + * return the directory entry of the item. + * + ****************************************************************************/ + +int romfs_finddirentry(struct romfs_mountpt_s *rm, struct romfs_dirinfo_s *dirinfo, + const char *path) +{ + const char *entryname; + const char *terminator; + int entrylen; + int ret; + + /* Start with the first element after the root directory */ + + dirinfo->rd_dir.fr_firstoffset = rm->rm_rootoffset; + dirinfo->rd_dir.fr_curroffset = rm->rm_rootoffset; + dirinfo->rd_next = RFNEXT_DIRECTORY; + dirinfo->rd_size = 0; + + /* The root directory is a special case */ + + if (!path || path[0] == '\0') + { + return OK; + } + + /* Then loop for each directory/file component in the full path */ + + entryname = path; + terminator = NULL; + + for (;;) + { + /* Find the start of the next path component */ + + while (*entryname == '/') entryname++; + + /* Find the end of the next path component */ + + terminator = strchr(entryname, '/'); + if (!terminator) + { + entrylen = strlen(entryname); + } + else + { + entrylen = terminator - entryname; + } + + /* Long path segment names will be truncated to NAME_MAX */ + + if (entrylen > NAME_MAX) + { + entrylen = NAME_MAX; + } + + /* Then find the entry in the current directory with the + * matching name. + */ + + ret = romfs_searchdir(rm, entryname, entrylen, dirinfo); + if (ret < 0) + { + return ret; + } + + /* Was that the last path component? */ + + if (!terminator) + { + /* Yes.. return success */ + + return OK; + } + + /* No... If that was not the last path component, then it had + * better have been a directory + */ + + if (!IS_DIRECTORY(dirinfo->rd_next)) + { + return -ENOTDIR; + } + + /* Setup to search the next directory for the next component + * of the path + */ + + entryname = terminator; + } + + return ERROR; /* Won't get here */ +} + +/**************************************************************************** + * Name: romfs_parsedirentry + * + * Desciption: + * Return the directory entry at this offset. If rf is NULL, then the + * mount device resources are used. Otherwise, file resources are used. + * + ****************************************************************************/ + +int romfs_parsedirentry(struct romfs_mountpt_s *rm, uint32_t offset, uint32_t *poffset, + uint32_t *pnext, uint32_t *pinfo, uint32_t *psize) +{ + uint32_t save; + uint32_t next; + int16_t ndx; + int ret; + + /* Read the sector into memory */ + + ndx = romfs_devcacheread(rm, offset); + if (ndx < 0) + { + return ndx; + } + + /* Yes.. Save the first 'next' value. That has the offset needed to + * traverse the parent directory. But we may need to change the type + * after we follow the hard links. + */ + + save = romfs_devread32(rm, ndx + ROMFS_FHDR_NEXT); + + /* Traverse hardlinks as necesssary to get to the real file header */ + + ret = romfs_followhardlinks(rm, offset, poffset); + if (ret < 0) + { + return ret; + } + + /* Because everything is chunked and aligned to 16-bit boundaries, + * we know that most the basic node info fits into the sector. The + * associated name may not, however. + */ + + next = romfs_devread32(rm, ndx + ROMFS_FHDR_NEXT); + *pnext = (save & RFNEXT_OFFSETMASK) | (next & RFNEXT_ALLMODEMASK); + *pinfo = romfs_devread32(rm, ndx + ROMFS_FHDR_INFO); + *psize = romfs_devread32(rm, ndx + ROMFS_FHDR_SIZE); + return OK; +} + +/**************************************************************************** + * Name: romfs_parsefilename + * + * Desciption: + * Return the filename from directory entry at this offset + * + ****************************************************************************/ + +int romfs_parsefilename(struct romfs_mountpt_s *rm, uint32_t offset, char *pname) +{ + int16_t ndx; + uint16_t namelen; + uint16_t chunklen; + bool done; + + /* Loop until the whole name is obtained or until NAME_MAX characters + * of the name have been parsed. + */ + + offset += ROMFS_FHDR_NAME; + for (namelen = 0, done = false; namelen < NAME_MAX && !done;) + { + /* Read the sector into memory */ + + ndx = romfs_devcacheread(rm, offset); + if (ndx < 0) + { + return ndx; + } + + /* Is the name terminated in this 16-byte block */ + + if (rm->rm_buffer[ndx + 15] == '\0') + { + /* Yes.. then this chunk is less than 16 */ + + chunklen = strlen((char*)&rm->rm_buffer[ndx]); + done = true; + } + else + { + /* No.. then this chunk is 16 bytes in length */ + + chunklen = 16; + } + + /* Check if we would exceed the NAME_MAX */ + + if (namelen + chunklen > NAME_MAX) + { + chunklen = NAME_MAX - namelen; + done = true; + } + + /* Copy the chunk */ + + memcpy(&pname[namelen], &rm->rm_buffer[ndx], chunklen); + namelen += chunklen; + } + + /* Terminate the name (NAME_MAX+1 chars total) and return success */ + + pname[namelen] = '\0'; + return OK; +} + +/**************************************************************************** + * Name: romfs_datastart + * + * Desciption: + * Given the offset to a file header, return the offset to the start of + * the file data + * + ****************************************************************************/ + +int romfs_datastart(struct romfs_mountpt_s *rm, uint32_t offset, uint32_t *start) +{ + int16_t ndx; + int ret; + + /* Traverse hardlinks as necesssary to get to the real file header */ + + ret = romfs_followhardlinks(rm, offset, &offset); + if (ret < 0) + { + return ret; + } + + /* Loop until the header size is obtained. */ + + offset += ROMFS_FHDR_NAME; + for (;;) + { + /* Read the sector into memory */ + + ndx = romfs_devcacheread(rm, offset); + if (ndx < 0) + { + return ndx; + } + + /* Get the offset to the next chunk */ + + offset += 16; + if (offset >= rm->rm_volsize) + { + return -EIO; + } + + /* Is the name terminated in this 16-byte block */ + + if (rm->rm_buffer[ndx + 15] == '\0') + { + /* Yes.. then the data starts at the next chunk */ + + *start = offset; + return OK; + } + } + + return -EINVAL; /* Won't get here */ +} + diff --git a/nuttx/graphics/Kconfig b/nuttx/graphics/Kconfig new file mode 100644 index 0000000000..ae2bf31307 --- /dev/null +++ b/nuttx/graphics/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# diff --git a/nuttx/graphics/Makefile b/nuttx/graphics/Makefile new file mode 100644 index 0000000000..6e549c1dd7 --- /dev/null +++ b/nuttx/graphics/Makefile @@ -0,0 +1,215 @@ +############################################################################ +# graphics/Makefile +# +# Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs + +DEPPATH = --dep-path . + +ifeq ($(WINTOOL),y) +INCDIROPT = -w +endif + +include nxglib/Make.defs +DEPPATH += --dep-path nxglib +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/graphics/nxglib} + +include nxbe/Make.defs +DEPPATH += --dep-path nxbe +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/graphics/nxbe} + +ifeq ($(CONFIG_NX_MULTIUSER),y) +include nxmu/Make.defs +DEPPATH += --dep-path nxmu +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/graphics/nxmu} +else +include nxsu/Make.defs +DEPPATH += --dep-path nxsu +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/graphics/nxsu} +endif + +include nxtk/Make.defs +DEPPATH += --dep-path nxtk +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/graphics/nxtk} + +include nxfonts/Make.defs +DEPPATH += --dep-path nxfonts +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/graphics/nxfonts} + +ifeq ($(CONFIG_NXCONSOLE),y) +include nxconsole/Make.defs +DEPPATH += --dep-path nxconsole +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/graphics/nxconsole} +endif + +ASRCS = $(NXGLIB_ASRCS) $(NXBE_ASRCS) $(NX_ASRCS) $(NXTK_ASRCS) $(NXFONTS_ASRCS) $(NXCON_ASRCS) +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +CSRCS = $(NXGLIB_CSRCS) $(NXBE_CSRCS) $(NX_CSRCS) $(NXTK_CSRCS) $(NXFONTS_CSRCS) $(NXCON_CSRCS) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = libgraphics$(LIBEXT) + +ifeq ($(CONFIG_NX_MULTIUSER),y) +VPATH = nxglib:nxbe:nxmu:nxtk:nxfonts:nxconsole +else +VPATH = nxglib:nxbe:nxsu:nxtk:nxfonts:nxconsole +endif + +all: mklibgraphics +.PHONY : context depend clean distclean mklibgraphics gensources gen1bppsources \ + gen2bppsource gen4bppsource gen8bppsource gen16bppsource gen24bppsource \ + gen32bppsources genfontsources + +gen1bppsources: + @$(MAKE) -C nxglib -f Makefile.sources TOPDIR=$(TOPDIR) NXGLIB_BITSPERPIXEL=1 EXTRADEFINES=$(EXTRADEFINES) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_BITSPERPIXEL=1 EXTRADEFINES=$(EXTRADEFINES) + +gen2bppsource: + @$(MAKE) -C nxglib -f Makefile.sources TOPDIR=$(TOPDIR) NXGLIB_BITSPERPIXEL=2 EXTRADEFINES=$(EXTRADEFINES) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_BITSPERPIXEL=2 EXTRADEFINES=$(EXTRADEFINES) + +gen4bppsource: + @$(MAKE) -C nxglib -f Makefile.sources TOPDIR=$(TOPDIR) NXGLIB_BITSPERPIXEL=4 EXTRADEFINES=$(EXTRADEFINES) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_BITSPERPIXEL=4 EXTRADEFINES=$(EXTRADEFINES) + +gen8bppsource: + @$(MAKE) -C nxglib -f Makefile.sources TOPDIR=$(TOPDIR) NXGLIB_BITSPERPIXEL=8 EXTRADEFINES=$(EXTRADEFINES) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_BITSPERPIXEL=8 EXTRADEFINES=$(EXTRADEFINES) + +gen16bppsource: + @$(MAKE) -C nxglib -f Makefile.sources TOPDIR=$(TOPDIR) NXGLIB_BITSPERPIXEL=16 EXTRADEFINES=$(EXTRADEFINES) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_BITSPERPIXEL=16 EXTRADEFINES=$(EXTRADEFINES) + +gen24bppsource: + @$(MAKE) -C nxglib -f Makefile.sources TOPDIR=$(TOPDIR) NXGLIB_BITSPERPIXEL=24 EXTRADEFINES=$(EXTRADEFINES) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_BITSPERPIXEL=24 EXTRADEFINES=$(EXTRADEFINES) + +gen32bppsources: + @$(MAKE) -C nxglib -f Makefile.sources TOPDIR=$(TOPDIR) NXGLIB_BITSPERPIXEL=32 EXTRADEFINES=$(EXTRADEFINES) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_BITSPERPIXEL=32 EXTRADEFINES=$(EXTRADEFINES) + +genfontsources: +ifeq ($(CONFIG_NXFONT_SANS23X27),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=1 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SANS22X29),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=2 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SANS28X37),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=3 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SANS39X48),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=4 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SANS17X23B),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=16 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SANS20X27B),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=17 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SANS22X29B),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=5 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SANS28X37B),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=6 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SANS40X49B),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=7 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SERIF22X29),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=8 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SERIF29X37),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=9 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SERIF38X48),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=10 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SERIF22X28B),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=11 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SERIF27X38B),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=12 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SERIF38X49B),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=13 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SANS17X22),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=14 EXTRADEFINES=$(EXTRADEFINES) +endif +ifeq ($(CONFIG_NXFONT_SANS20X26),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=15 EXTRADEFINES=$(EXTRADEFINES) +endif + +gensources: gen1bppsources gen2bppsource gen4bppsource gen8bppsource gen16bppsource gen24bppsource gen32bppsources genfontsources + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +mklibgraphics: gensources $(BIN) + +.depend: gensources Makefile $(SRCS) + @$(MKDEP) $(DEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +context: gensources + +clean: + @$(MAKE) -C nxglib -f Makefile.sources clean TOPDIR=$(TOPDIR) EXTRADEFINES=$(EXTRADEFINES) + @$(MAKE) -C nxfonts -f Makefile.sources clean TOPDIR=$(TOPDIR) EXTRADEFINES=$(EXTRADEFINES) + @rm -f $(BIN) *~ .*.swp + $(call CLEAN) + +distclean: clean + @$(MAKE) -C nxglib -f Makefile.sources distclean TOPDIR=$(TOPDIR) EXTRADEFINES=$(EXTRADEFINES) + @$(MAKE) -C nxfonts -f Makefile.sources distclean TOPDIR=$(TOPDIR) EXTRADEFINES=$(EXTRADEFINES) + @rm -f Make.dep .depend + +-include Make.dep + diff --git a/nuttx/graphics/README.txt b/nuttx/graphics/README.txt new file mode 100644 index 0000000000..18aebadbd8 --- /dev/null +++ b/nuttx/graphics/README.txt @@ -0,0 +1,401 @@ +README +^^^^^^ + +This directory contains tiny graphics support for NuttX. The contents of this directory +are only build if CONFIG_NX is defined in the NuttX configuration file. + +Contents +^^^^^^^^ + Roadmap + Related Header Files + Directories + Installing New Fonts + Configuration Settings + +Roadmap +^^^^^^^ + +This directory holds NuttX graphic packages. Not all of these packages are implemented +at the present, but here is the longer term roadmap: + + NxWidgets - NxWidgets is a higher level, C++, object-oriented library for object- + oriented access to graphics "widgets." NxWidgets is provided as a separate + package. NxWidgets is built on top of the core NuttX graphics subsystem, + but is not a part of the core graphics subystems. + NXTOOLKIT - A set of C graphics tools that provide higher-level window drawing + operations. The toolkit can be used for window-oriented graphics + without NxWidgets and is built on top of NX. + NXFONTS - A set of C graphics tools for present (bitmap) font images. + NX - The tiny NuttX windowing system. This includes both a small-footprint, + single user implementaton (NXSU as described below) and a somewhat + larger multi-user implentation (NXMU as described below). Both + conform to the same APIs as defined in include/nuttx/nx/nx.h and, hence, + are more-or-less interchangable. NX can be used without NxWidgets + and without NXTOOLKIT for raw access to window memory. + NXGLIB - Low level graphics utilities and direct framebuffer rendering logic. + NX is built on top of NXGLIB. + NxConsole - NxConsole is a write-only character device that is built on top of + an NX window. This character device can be used to provide stdout + and stderr and, hence, can provide the output side of NuttX console. + NxConsole is only available when the multi-user NX implementation is + selected (CONFIG_NX_MULTIUSERs). + + +Related Header Files +^^^^^^^^^^^^^^^^^^^^ + +include/nuttx/nx/nxglib.h -- Describes the NXGLIB C interfaces +include/nuttx/nx/nx.h -- Describes the NX C interfaces +include/nuttx/nx/nxtk.h -- Describe the NXTOOLKIT C interfaces +include/nuttx/nx/nxfont.h -- Describe sthe NXFONT C interfaces + +Directories +^^^^^^^^^^^ + +graphics/nxglib + The NuttX tiny graphics library. The directory contains generic utilities + support operations on primitive graphics objects and logic to rasterize directly + into a framebuffer. It has no concept of windows (other than the one, framebuffer + window). + +graphics/nxbe + This is the "back-end" of a tiny windowing system. It can be used with either of + two front-ends to complete a windowing system (see nxmu and nxsu below). It + contains most of the important window management logic: clipping, window controls, + window drawing, etc. + +graphics/nxsu + This is the NX single user "front end". When combined with the generic "back-end" + (nxbe), it implements a single thread, single user windowing system. The files + in this directory present the window APIs described in include/nuttx/nx/nx.h. The + single user front-end is selected when CONFIG_NX_MULTIUSER is not defined in the + NuttX configuration file. + +graphics/nxmu + This is the NX multi user "front end". When combined with the generic "back-end" + (nxbe), it implements a multi-threaded, multi-user windowing system. The files + in this directory present the window APIs described in include/nuttx/nx/nx.h. The + multi-user front end includes a graphics server that executes on its own thread; + multiple graphics clients then communicate with the server via a POSIX message + queue to serialize window operations from many threads. The multi-user front-end + is selected when CONFIG_NX_MULTIUSER is defined in the NuttX configuration file. + +graphics/nxfonts + This is where the NXFONTS implementation resides. This is a relatively low- + level set of charset set/glyph management APIs. See include/nuttx/nx/nxfonts.h + +graphics/nxtk + This is where the NXTOOLKIT implementation resides. This toolkit is built on + top of NX and works with either the single-user or multi-user NX version. See + include/nuttx/nx/nxtk.h + +nuttx/../NxWidgets + The NxWidgets code is provided as a separate package located outside of the + NuttX source tree (probably at this location). + +Installing New Fonts +^^^^^^^^^^^^^^^^^^^^ + + There is a tool called bdf-converter in the directory tools/. The bdf-converter + program be used to convert fonts in Bitmap Distribution Format (BDF) + into fonts that can be used in the NX graphics system. + + Below are general instructions for creating and installing a new font + in the NX graphic system: + + 1. Locate a font in BDF format, + 2. Use the bdf-converter program to convert the BDF font to the NuttX + font format. This will result in a C header file containing + defintions. That header file should be installed at, for example, + graphics/nxfonts/nxfonts_myfont.h. + + Create a new NuttX configuration variable. For example, suppose + you define the following variable: CONFIG_NXFONT_MYFONT. Then + you would need to: + + 3. Define CONFIG_NXFONT_MYFONT=y in your NuttX configuration file. + + A font ID number has to be assigned for each new font. The font ID + is defined in the file include/nuttx/nx/nxfonts.h. Those definitions + have to be extended to support your new font. Look at how the font ID + enabled by CONFIG_NXFONT_SANS23X27 is defined and add an ID for your + new font in a similar fashion: + + 4. include/nuttx/nx/nxfonts.h. Add you new font as a possible system + default font: + + #if defined(CONFIG_NXFONT_SANS23X27) + # define NXFONT_DEFAULT FONTID_SANS23X27 + #elif defined(CONFIG_NXFONT_MYFONT) + # define NXFONT_DEFAULT FONTID_MYFONT + #endif + + Then define the actual font ID. Make sure that the font ID value + is unique: + + enum nx_fontid_e + { + FONTID_DEFAULT = 0 /* The default font */ + #ifdef CONFIG_NXFONT_SANS23X27 + , FONTID_SANS23X27 = 1 /* The 23x27 sans serif font */ + #endif + #ifdef CONFIG_NXFONT_MYFONT + , FONTID_MYFONT = 2 /* My shiny, new font */ + #endif + ... + + New Add the font to the NX build system. There are several files that + you have to modify to to this. Look how the build system uses the + font CONFIG_NXFONT_SANS23X27 for examaples: + + 5. nuttx/graphics/Makefile. This file needs logic to auto-generate + a C source file from the header file that you generated with the + the bdf-converter program. Notice NXFONTS_FONTID=2; this must be + set to the same font ID value that you defined in the + include/nuttx/nx/nxfonts.h file. + + genfontsources: + ifeq ($(CONFIG_NXFONT_SANS23X27),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=1 EXTRADEFINES=$(EXTRADEFINES) + endif + ifeq ($(CONFIG_NXFONT_MYFONT),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=2 EXTRADEFINES=$(EXTRADEFINES) + endif + + 6. nuttx/graphics/nxfonts/Make.defs. Set the make variable NXFSET_CSRCS. + NXFSET_CSRCS determines the name of the font C file to build when + NXFONTS_FONTID=2: + + ifeq ($(CONFIG_NXFONT_SANS23X27),y) + NXFSET_CSRCS += nxfonts_bitmaps_sans23x27.c + endif + ifeq ($(CONFIG_NXFONT_MYFONT),y) + NXFSET_CSRCS += nxfonts_bitmaps_myfont.c + endif + + 7. nuttx/graphics/nxfonts/Makefile.sources. This is the Makefile used + in step 5 that will actually generate the font C file. So, given + your NXFONTS_FONTID=2, it needs to determine a prefix to use for + auto-generated variable and function names and (again) the name of + the autogenerated file to create (this must be the same name that + was used in nuttx/graphics/nxfonts/Make.defs): + + ifeq ($(NXFONTS_FONTID),1) + NXFONTS_PREFIX := g_sans23x27_ + GEN_CSRC = nxfonts_bitmaps_sans23x27.c + endif + ifeq ($(NXFONTS_FONTID),2) + NXFONTS_PREFIX := g_myfont_ + GEN_CSRC = nxfonts_bitmaps_myfont.c + endif + + 8. graphics/nxfonts/nxfonts_bitmaps.c. This is the file that contains + the generic font structures. It is used as a "template" file by + nuttx/graphics/nxfonts/Makefile.sources to create your customized + font data set. + + #if NXFONTS_FONTID == 1 + # include "nxfonts_sans23x27.h" + #elif NXFONTS_FONTID == 2 + # include "nxfonts_myfont.h" + #else + # error "No font ID specified" + #endif + + Where nxfonts_myfont.h is the NuttX font file that we generated in + step 2 using the bdf-converter tool. + + 9. graphics/nxfonts/nxfonts_getfont.c. Finally, we need to extend the + logic that does the run-time font lookups so that can find our new + font. The lookup function is NXHANDLE nxf_getfonthandle(enum nx_fontid_e fontid). + The new font information needs to be added to data structures used by + that function: + + #ifdef CONFIG_NXFONT_SANS23X27 + extern const struct nx_fontpackage_s g_sans23x27_package; + #endif + #ifdef CONFIG_NXFONT_MYFONT + extern const struct nx_fontpackage_s g_myfont_package; + #endif + + static FAR const struct nx_fontpackage_s *g_fontpackages[] = + { + #ifdef CONFIG_NXFONT_SANS23X27 + &g_sans23x27_package, + #endif + #ifdef CONFIG_NXFONT_MYFONT + &g_myfont_package, + #endif + NULL + }; + +Configuration Settings +^^^^^^^^^^^^^^^^^^^^^^ + +General NX Settings +------------------- + +CONFIG_NX + Enables overall support for graphics library and NX +CONFIG_NX_MULTIUSER + Configures NX in multi-user mode +CONFIG_NX_NPLANES + Some YUV color formats requires support for multiple planes, one for each + color component. Unless you have such special hardware, this value should be + undefined or set to 1. +CONFIG_NX_WRITEONLY + Define if the underlying graphics device does not support read operations. + Automatically defined if CONFIG_NX_LCDDRIVER and CONFIG_LCD_NOGETRUN are + defined. +CONFIG_NX_DISABLE_1BPP, CONFIG_NX_DISABLE_2BPP, +CONFIG_NX_DISABLE_4BPP, CONFIG_NX_DISABLE_8BPP, +CONFIG_NX_DISABLE_16BPP, CONFIG_NX_DISABLE_24BPP, and +CONFIG_NX_DISABLE_32BPP + NX supports a variety of pixel depths. You can save some memory by disabling + support for unused color depths. +CONFIG_NX_PACKEDMSFIRST + If a pixel depth of less than 8-bits is used, then NX needs to know if the + pixels pack from the MS to LS or from LS to MS +CONFIG_NX_MOUSE + Build in support for mouse input. +CONFIG_NX_KBD + Build in support of keypad/keyboard input. +CONFIG_NXTK_BORDERWIDTH + Specifies with with of the border (in pixels) used with framed windows. + The default is 4. +CONFIG_NXTK_BORDERCOLOR1, CONFIG_NXTK_BORDERCOLOR2, CONFIG_NXTK_BORDERCOLOR3 + Specify the colors of the border used with framed windows. + CONFIG_NXTK_BORDERCOLOR2 is the shadow side color and so is normally darker. + CONFIG_NXTK_BORDERCOLOR3 is the shiny side color and so is normally brighter. + The default is mediumdark grey, and light grey, respectively +CONFIG_NXTK_AUTORAISE + If set, a window will be raised to the top if the mouse position is over a + visible portion of the window. Default: A mouse button must be clicked over + a visible portion of the window. +CONFIG_NXFONTS_CHARBITS + The number of bits in the character set. Current options are only 7 and 8. + The default is 7. + +Font Selections +--------------- + +CONFIG_NXFONT_SANS17X22 + This option enables support for a tiny, 17x22 san serif font + (font ID FONTID_SANS17X22 == 14). +CONFIG_NXFONT_SANS20X26 + This option enables support for a tiny, 20x26 san serif font + (font ID FONTID_SANS20X26 == 15). +CONFIG_NXFONT_SANS23X27 + This option enables support for a tiny, 23x27 san serif font + (font ID FONTID_SANS23X27 == 1). +CONFIG_NXFONT_SANS22X29 + This option enables support for a small, 22x29 san serif font + (font ID FONTID_SANS22X29 == 2). +CONFIG_NXFONT_SANS28X37 + This option enables support for a medium, 28x37 san serif font + (font ID FONTID_SANS28X37 == 3). +CONFIG_NXFONT_SANS39X48 + This option enables support for a large, 39x48 san serif font + (font ID FONTID_SANS39X48 == 4). +CONFIG_NXFONT_SANS17X23B + This option enables support for a tiny, 17x23 san serif bold font + (font ID FONTID_SANS17X23B == 16). +CONFIG_NXFONT_SANS20X27B + This option enables support for a tiny, 20x27 san serif bold font + (font ID FONTID_SANS20X27B == 17). +CONFIG_NXFONT_SANS22X29B + This option enables support for a small, 22x29 san serif bold font + (font ID FONTID_SANS22X29B == 5). +CONFIG_NXFONT_SANS28X37B + This option enables support for a medium, 28x37 san serif bold font + (font ID FONTID_SANS28X37B == 6). +CONFIG_NXFONT_SANS40X49B + This option enables support for a large, 40x49 san serif bold font + (font ID FONTID_SANS40X49B == 7). +CONFIG_NXFONT_SERIF22X29 + This option enables support for a small, 22x29 font (with serifs) + (font ID FONTID_SERIF22X29 == 8). +CONFIG_NXFONT_SERIF29X37 + This option enables support for a medium, 29x37 font (with serifs) + (font ID FONTID_SERIF29X37 == 9). +CONFIG_NXFONT_SERIF38X48 + This option enables support for a large, 38x48 font (with serifs) + (font ID FONTID_SERIF38X48 == 10). +CONFIG_NXFONT_SERIF22X28B + This option enables support for a small, 27x38 bold font (with serifs) + (font ID FONTID_SERIF22X28B == 11). +CONFIG_NXFONT_SERIF27X38B + This option enables support for a medium, 27x38 bold font (with serifs) + (font ID FONTID_SERIF27X38B == 12). +CONFIG_NXFONT_SERIF38X49B + This option enables support for a large, 38x49 bold font (with serifs) + (font ID FONTID_SERIF38X49B == 13). + +NxConsole Configuration Settings +-------------------------------- + +CONFIG_NXCONSOLE + Enables building of the NxConsole driver. + +NxConsole output text/graphics options: + +CONFIG_NXCONSOLE_BPP + Currently, NxConsole supports only a single pixel depth. This + configuration setting must be provided to support that single pixel depth. + Default: The smallest enabled pixel depth. (see CONFIG_NX_DISABLE_*BPP) +CONFIG_NXCONSOLE_CURSORCHAR + The bitmap code to use as the cursor. Default '_' +CONFIG_NXCONSOLE_MXCHARS + NxConsole needs to remember every character written to the console so + that it can redraw the window. This setting determines the size of some + internal memory allocations used to hold the character data. Default: 128. +CONFIG_NXCONSOLE_CACHESIZE + NxConsole supports caching of rendered fonts. This font caching is required + for two reasons: (1) First, it improves text performance, but more + importantly (2) it preserves the font memory. Since the NX server runs on + a separate server thread, it requires that the rendered font memory persist + until the server has a chance to render the font. Unfortunately, the font + cache would be quite large if all fonts were saved. The CONFIG_NXCONSOLE_CACHESIZE + setting will control the size of the font cache (in number of glyphs). Only that + number of the most recently used glyphs will be retained. Default: 16. + NOTE: There can still be a race condition between the NxConsole driver and the + NX task. If you every see character corruption (especially when printing + a lot of data or scrolling), then increasing the value of CONFIG_NXCONSOLE_CACHESIZE + is something that you should try. Alternatively, you can reduce the size of + CONFIG_MQ_MAXMSGSIZE which will force NxConsole task to pace the server task. + CONFIG_NXCONSOLE_CACHESIZE should be larger than ONFIG_MQ_MAXMSGSIZE in any event. +CONFIG_NXCONSOLE_LINESEPARATION + This the space (in rows) between each row of test. Default: 0 +CONFIG_NXCONSOLE_NOWRAP + By default, lines will wrap when the test reaches the right hand side + of the window. This setting can be defining to change this behavior so + that the text is simply truncated until a new line is encountered. + +NxConsole Input options + +CONFIG_NXCONSOLE_NXKBDIN + Take input from the NX keyboard input callback. By default, keyboard + input is taken from stdin (/dev/console). If this option is set, then + the interface nxcon_kdbin() is enabled. That interface may be driven + by window callback functions so that keyboard input *only* goes to the + top window. +CONFIG__NXCONSOLE_KBDBUFSIZE + If CONFIG_NXCONSOLE_NXKBDIN is enabled, then this value may be used to + define the size of the per-window keyboard input buffer. Default: 16 +CONFIG_NXCONSOLE_NPOLLWAITERS + The number of threads that can be waiting for read data available. + Default: 4 + +NX Multi-user only options +-------------------------- + +CONFIG_NX_BLOCKING + Open the client message queues in blocking mode. In this case, + nx_eventhandler() will not return until a message is received and processed. +CONFIG_NX_MXSERVERMSGS and CONFIG_NX_MXCLIENTMSGS + Specifies the maximum number of messages that can fit in the message queues. + No additional resources are allocated, but this can be set to prevent + flooding of the client or server with too many messages (CONFIG_PREALLOC_MQ_MSGS + controls how many messages are pre-allocated). + + diff --git a/nuttx/graphics/nxbe/Make.defs b/nuttx/graphics/nxbe/Make.defs new file mode 100644 index 0000000000..53fdf96640 --- /dev/null +++ b/nuttx/graphics/nxbe/Make.defs @@ -0,0 +1,41 @@ +############################################################################ +# graphics/nxbe/Make.defs +# +# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +NXBE_ASRCS = +NXBE_CSRCS = nxbe_bitmap.c nxbe_configure.c nxbe_colormap.c nxbe_clipper.c \ + nxbe_closewindow.c nxbe_fill.c nxbe_filltrapezoid.c \ + nxbe_getrectangle.c nxbe_lower.c nxbe_move.c nxbe_raise.c \ + nxbe_redraw.c nxbe_redrawbelow.c nxbe_setpixel.c nxbe_setposition.c \ + nxbe_setsize.c nxbe_visible.c diff --git a/nuttx/graphics/nxbe/nxbe.h b/nuttx/graphics/nxbe/nxbe.h new file mode 100644 index 0000000000..aff42d6b32 --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe.h @@ -0,0 +1,533 @@ +/**************************************************************************** + * graphics/nxbe/nxbe.h + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXBE_NXBE_H +#define __GRAPHICS_NXBE_NXBE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_NX_NPLANES +# define CONFIG_NX_NPLANES 1 /* Max number of color planes supported */ +#endif + +#ifndef CONFIG_NX_NCOLORS +# define CONFIG_NX_NCOLORS 256 +#endif + +/* NXBE Definitions *********************************************************/ +/* These are the values for the clipping order provided to nx_clipper */ + +#define NX_CLIPORDER_TLRB (0) /* Top-left-right-bottom */ +#define NX_CLIPORDER_TRLB (1) /* Top-right-left-bottom */ +#define NX_CLIPORDER_BLRT (2) /* Bottom-left-right-top */ +#define NX_CLIPORDER_BRLT (3) /* Bottom-right-left-top */ +#define NX_CLIPORDER_DEFAULT NX_CLIPORDER_TLRB + +/* Window flags and helper macros */ + +#define NXBE_WINDOW_BLOCKED (1 << 0) /* The window is blocked and will not + * receive further input. */ + +#define NXBE_ISBLOCKED(wnd) (((wnd)->flags & NXBE_WINDOW_BLOCKED) != 0) +#define NXBE_SETBLOCKED(wnd) do { (wnd)->flags |= NXBE_WINDOW_BLOCKED; } while (0) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Rasterization ************************************************************/ + +/* A tiny vtable of raster operation function pointers. The types of the + * function points must match the rasterizer types exported by nxglib + */ + +struct nxbe_plane_s +{ + /* Raster operation callbacks for this bits-per-pixel value */ + + void (*setpixel)(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_point_s *pos, + nxgl_mxpixel_t color); + void (*fillrectangle)(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t color); + void (*getrectangle)(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR void *dest, unsigned int deststride); + void (*filltrapezoid)(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_trapezoid_s *trap, + FAR const struct nxgl_rect_s *bounds, + nxgl_mxpixel_t color); + void (*moverectangle)(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR struct nxgl_point_s *offset); + void (*copyrectangle)(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *dest, + FAR const void *src, + FAR const struct nxgl_point_s *origin, + unsigned int srcstride); + + /* Framebuffer plane info describing destination video plane */ + + NX_PLANEINFOTYPE pinfo; +}; + +/* Clipping *****************************************************************/ + +/* Clipping callback functions called nxbe_clipper for each visible and + * obscured region of a rectangle within a window. + */ + +struct nxbe_clipops_s +{ + void (*visible)(FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane, + FAR const struct nxgl_rect_s *rect); + + void (*obscured)(FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane, + FAR const struct nxgl_rect_s *rect); +}; + +/* Windows ******************************************************************/ + +/* This structure represents one window. */ + +struct nxbe_state_s; +struct nxfe_conn_s; +struct nxbe_window_s +{ + /* State information */ + + FAR struct nxbe_state_s *be; /* The back-end state structure */ +#ifdef CONFIG_NX_MULTIUSER + FAR struct nxfe_conn_s *conn; /* Connection to the window client */ +#endif + FAR const struct nx_callback_s *cb; /* Event handling callbacks */ + + /* The following links provide the window's vertical position using a + * singly linked list. + */ + + FAR struct nxbe_window_s *above; /* The window "above" this window */ + FAR struct nxbe_window_s *below; /* The window "below this one */ + + /* Window geometry. The window is described by a rectangle in the + * absolute screen coordinate system (0,0)->(xres,yres) + */ + + struct nxgl_rect_s bounds; /* The bounding rectangle of window */ + + /* Window flags (see the NXBE_* bit definitions above) */ + +#ifdef CONFIG_NX_MULTIUSER /* Currently used only in multi-user mode */ + uint8_t flags; +#endif + + /* Client state information this is provide in window callbacks */ + + FAR void *arg; +}; + +/* Back-end state ***********************************************************/ + +/* This structure describes the overall back-end window state */ + +struct nxbe_state_s +{ + /* The window list (with the background window always at the bottom) */ + + FAR struct nxbe_window_s *topwnd; /* The window at the top of the display */ + struct nxbe_window_s bkgd; /* The background window is always at the bottom */ + + /* At present, only a solid colored background is supported for refills. The + * following provides the background color. It would be nice to support + * background bitmap images as well. + */ + + nxgl_mxpixel_t bgcolor[CONFIG_NX_NPLANES]; + + /* vinfo describes the video controller and plane[n].pinfo describes color + * plane 'n' supported by the video controller. Most common color models + * fit in one plane, but this array provides future support for hardware + * with planar YUV types with 3 or 4 color planes. + */ + + struct fb_videoinfo_s vinfo; + + /* Rasterizing functions selected to match the BPP reported in pinfo[] */ + + struct nxbe_plane_s plane[CONFIG_NX_NPLANES]; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_colormap + * + * Description: + * Set the harware color map to the palette expected by NX + * + ****************************************************************************/ + +#ifdef CONFIG_FB_CMAP +EXTERN int nxbe_colormap(FAR NX_DRIVERTYPE *dev); +#endif + +/**************************************************************************** + * Name: nx_configure + * + * Description: + * Configure the back end state structure based on information from the + * framebuffer or LCD driver + * + ****************************************************************************/ + +EXTERN int nxbe_configure(FAR NX_DRIVERTYPE *dev, + FAR struct nxbe_state_s *be); + +/**************************************************************************** + * Name: nxbe_closewindow + * + * Description: + * Close an existing window + * + * Input Parameters: + * wnd - The window to be closed (and deallocated) + * + * Return: + * None + * + ****************************************************************************/ + +EXTERN void nxbe_closewindow(struct nxbe_window_s *wnd); + +/**************************************************************************** + * Name: nxbe_setposition + * + * Descripton: + * This function checks for intersections and redraws the display after + * a change in the position of a window. + * + ****************************************************************************/ + +EXTERN void nxbe_setposition(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_point_s *pos); + +/**************************************************************************** + * Name: nxbe_setsize + * + * Descripton: + * This function checks for intersections and redraws the display after + * a change in the size of a window. + * + ****************************************************************************/ + +EXTERN void nxbe_setsize(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_size_s *size); + +/**************************************************************************** + * Name: nxbe_raise + * + * Description: + * Bring the specified window to the top of the display. + * + ****************************************************************************/ + +EXTERN void nxbe_raise(FAR struct nxbe_window_s *wnd); + +/**************************************************************************** + * Name: nxbe_lower + * + * Description: + * Lower the specified window to the bottom of the display. + * + ****************************************************************************/ + +EXTERN void nxbe_lower(FAR struct nxbe_window_s *wnd); + +/**************************************************************************** + * Name: nxbe_setpixel + * + * Description: + * Set a single pixel in the window to the specified color. This is simply + * a degenerate case of nxbe_fill(), but may be optimized in some architectures. + * + * Input Parameters: + * wnd - The window structure reference + * pos - The pixel location to be set + * col - The color to use in the set + * + * Return: + * None + * + ****************************************************************************/ + +EXTERN void nxbe_setpixel(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_point_s *pos, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxbe_fill + * + * Description: + * Fill the specified rectangle in the window with the specified color + * + * Input Parameters: + * wnd - The window structure reference + * rect - The location to be filled + * col - The color to use in the fill + * + * Return: + * None + * + ****************************************************************************/ + +EXTERN void nxbe_fill(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxbe_filltrapezoid + * + * Description: + * Fill the specified rectangle in the window with the specified color + * + * Input Parameters: + * wnd - The window structure reference + * clip - Clipping region (may be null) + * rect - The location to be filled + * col - The color to use in the fill + * + * Return: + * None + * + ****************************************************************************/ + +EXTERN void nxbe_filltrapezoid(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *clip, + FAR const struct nxgl_trapezoid_s *trap, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxbe_getrectangle + * + * Description: + * Get the raw contents of graphic memory within a rectangular region. NOTE: + * Since raw graphic memory is returned, the returned memory content may be + * the memory of windows above this one and may not necessarily belong to + * this window unless you assure that this is the top window. + * + * Input Parameters: + * wnd - The window structure reference + * rect - The location to be copied + * plane - Specifies the color plane to get from. + * dest - The location to copy the memory region + * deststride - The width, in bytes, the the dest memory + * + * Return: + * None + * + ****************************************************************************/ + +EXTERN void nxbe_getrectangle(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *rect, + unsigned int plane, + FAR uint8_t *dest, unsigned int deststride); + +/**************************************************************************** + * Name: nxbe_move + * + * Description: + * Move a rectangular region within the window + * + * Input Parameters: + * wnd - The window within which the move is to be done + * rect - Describes the rectangular region to move + * offset - The offset to move the region + * + * Return: + * None + * + ****************************************************************************/ + +EXTERN void nxbe_move(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset); + +/**************************************************************************** + * Name: nxbe_bitmap + * + * Description: + * Copy a rectangular region of a larger image into the rectangle in the + * specified window. + * + * Input Parameters: + * wnd - The window that will receive the bitmap image + * dest - Describes the rectangular on the display that will receive the + * the bit map. + * src - The start of the source image. + * origin - The origin of the upper, left-most corner of the full bitmap. + * Both dest and origin are in window coordinates, however, origin + * may lie outside of the display. + * stride - The width of the full source image in pixels. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN void nxbe_bitmap(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, + unsigned int stride); + +/**************************************************************************** + * Name: nxbe_redraw + * + * Descripton: + * Re-draw the visible portions of the rectangular region for the + * specified window + * + ****************************************************************************/ + +EXTERN void nxbe_redraw(FAR struct nxbe_state_s *be, + FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *rect); + +/**************************************************************************** + * Name: nxbe_redrawbelow + * + * Descripton: + * Re-draw the visible portions of the rectangular region for all windows + * below (and including) the specified window. This function is called + * whenever a window is closed, moved, lowered or re-sized in order to + * expose newly visible portions of lower windows. + * + ****************************************************************************/ + +EXTERN void nxbe_redrawbelow(FAR struct nxbe_state_s *be, + FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *rect); + +/**************************************************************************** + * Name: nxbe_visible + * + * Descripton: + * Return true if the point, pt, in window wnd is visible. pt is in + * absolute screen coordinates + * + ****************************************************************************/ + +EXTERN bool nxbe_visible(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_point_s *pos); + +/**************************************************************************** + * Name: nxbe_clipper + * + * Descripton: + * Perform flexible clipping operations. Callbacks are executed for + * each oscured and visible portions of the window. + * + * Input Parameters: + * wnd - The window to be clipped. + * rect - The region of concern within the window + * order - Specifies the order to process the parts of the non-intersecting + * sub-rectangles. + * cops - The callbacks to handle obscured and visible parts of the + * sub-rectangles. + * plane - The raster operations to be used by the callback functions. + * These may vary with different color formats. + * + * Returned Value: + * None + * + ****************************************************************************/ + +EXTERN void nxbe_clipper(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *dest, uint8_t order, + FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane); + +/**************************************************************************** + * Name: nxbe_clipnull + * + * Descripton: + * The do-nothing clipping callback function + * + ****************************************************************************/ + +EXTERN void nxbe_clipnull(FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane, + FAR const struct nxgl_rect_s *rect); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXBE_NXBE_H */ + diff --git a/nuttx/graphics/nxbe/nxbe_bitmap.c b/nuttx/graphics/nxbe/nxbe_bitmap.c new file mode 100644 index 0000000000..991b91d82c --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_bitmap.c @@ -0,0 +1,192 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_bitmap.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxbe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nx_bitmap_s +{ + struct nxbe_clipops_s cops; + FAR const void *src; /* The start of the source image. */ + struct nxgl_point_s origin; /* Offset into the source image data */ + unsigned int stride; /* The width of the full source image in pixels. */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxs_clipcopy + * + * Description: + * Called from nxbe_clipper() to performed the fill operation on visible portions + * of the rectangle. + * + ****************************************************************************/ + +static void nxs_clipcopy(FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane, + FAR const struct nxgl_rect_s *rect) +{ + struct nx_bitmap_s *bminfo = (struct nx_bitmap_s *)cops; + plane->copyrectangle(&plane->pinfo, rect, bminfo->src, + &bminfo->origin, bminfo->stride); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_bitmap + * + * Description: + * Copy a rectangular region of a larger image into the rectangle in the + * specified window. + * + * Input Parameters: + * wnd - The window that will receive the bitmap image + * dest - Describes the rectangular on the display that will receive the + * the bit map. + * src - The start of the source image. + * origin - The origin of the upper, left-most corner of the full bitmap. + * Both dest and origin are in window coordinates, however, origin + * may lie outside of the display. + * stride - The width of the full source image in pixels. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +void nxbe_bitmap(FAR struct nxbe_window_s *wnd, FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, unsigned int stride) +{ + struct nx_bitmap_s info; + struct nxgl_rect_s bounds; + struct nxgl_point_s offset; + struct nxgl_rect_s remaining; + unsigned int deststride; + int i; + +#ifdef CONFIG_DEBUG + if (!wnd || !dest || !src || !origin) + { + return; + } +#endif + + /* Verify that the destination rectangle begins "below" and to the "right" + * of the origin + */ + + if (dest->pt1.x < origin->x || dest->pt1.y < origin->y) + { + gdbg("Bad dest start position\n"); + return; + } + + /* Verify that the width of the destination rectangle does not exceed the + * width of the source bitmap data (taking into account the bitmap origin) + */ + + deststride = (((dest->pt2.x - origin->x + 1) * wnd->be->plane[0].pinfo.bpp + 7) >> 3); + if (deststride > stride) + { + gdbg("Bad dest width\n"); + return; + } + + /* Offset the rectangle and image origin by the window origin */ + + nxgl_rectoffset(&bounds, dest, wnd->bounds.pt1.x, wnd->bounds.pt1.y); + nxgl_vectoradd(&offset, origin, &wnd->bounds.pt1); + + /* Clip to the limits of the window and of the background screen */ + + nxgl_rectintersect(&remaining, &bounds, &wnd->bounds); + nxgl_rectintersect(&remaining, &remaining, &wnd->be->bkgd.bounds); + if (nxgl_nullrect(&remaining)) + { + return; + } + + /* Then perform the clipped fill */ + +#if CONFIG_NX_NPLANES > 1 + for (i = 0; i < wnd->be->vinfo.nplanes; i++) +#else + i = 0; +#endif + { + info.cops.visible = nxs_clipcopy; + info.cops.obscured = nxbe_clipnull; + info.src = src[i]; + info.origin.x = offset.x; + info.origin.y = offset.y; + info.stride = stride; + + nxbe_clipper(wnd->above, &remaining, NX_CLIPORDER_DEFAULT, + &info.cops, &wnd->be->plane[i]); + } +} + diff --git a/nuttx/graphics/nxbe/nxbe_clipper.c b/nuttx/graphics/nxbe/nxbe_clipper.c new file mode 100644 index 0000000000..580c8bc4c8 --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_clipper.c @@ -0,0 +1,278 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_clipper.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include "nxbe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#define NX_INITIAL_STACKSIZE (32) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure is a container that retains an associated between a + * window instance and a rectangle. + */ + +struct nxbe_cliprect_s +{ + FAR struct nxbe_window_s *wnd; + struct nxgl_rect_s rect; +}; + +/* This is the stack of pending clip operations */ + +struct nxbe_clipstack_s +{ + uint16_t npushed; /* Number of deferred rectangles in stack */ + uint16_t mxrects; /* The capacity of the stack */ + struct nxbe_cliprect_s *stack; /* The stack of deferred rectangles */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint8_t g_nxcliporder[4][4] = +{ + { NX_TOP_NDX, NX_LEFT_NDX, NX_RIGHT_NDX, NX_BOTTOM_NDX }, /* index = NX_CLIPORDER_TLRB */ + { NX_TOP_NDX, NX_RIGHT_NDX, NX_LEFT_NDX, NX_BOTTOM_NDX }, /* NX_CLIPORDER_TRLB */ + { NX_BOTTOM_NDX, NX_LEFT_NDX, NX_RIGHT_NDX, NX_TOP_NDX }, /* NX_CLIPORDER_BLRT */ + { NX_BOTTOM_NDX, NX_RIGHT_NDX, NX_LEFT_NDX, NX_TOP_NDX } /* NX_CLIPORDER_BRLT */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_pushrectangle + ****************************************************************************/ + +static inline void nxbe_pushrectangle(FAR struct nxbe_clipstack_s *stack, + FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *rect) +{ + /* Check if there is room on the stack to hold another rectangle */ + + if ((stack->npushed + 1) > stack->mxrects) + { + /* No then we will need to reallocate the stack to hole more */ + + int mxrects = stack->mxrects ? 2 * stack->mxrects : NX_INITIAL_STACKSIZE; + struct nxbe_cliprect_s *newstack; + + newstack = realloc(stack->stack, sizeof(struct nxbe_cliprect_s) * mxrects); + if (!newstack) + { + gdbg("Failed to reallocate stack\n"); + return; + } + + stack->stack = newstack; + stack->mxrects = mxrects; + } + + /* Then push the new rectangle onto the stack */ + + stack->stack[stack->npushed].wnd = wnd; + nxgl_rectcopy(&stack->stack[stack->npushed].rect, rect); + stack->npushed++; +} + +/**************************************************************************** + * Name: nxbe_poprectangle + ****************************************************************************/ + +static inline bool nxbe_poprectangle(struct nxbe_clipstack_s *stack, + FAR struct nxbe_window_s **wnd, + struct nxgl_rect_s *rect) +{ + if(stack->npushed > 0) + { + stack->npushed--; + *wnd = stack->stack[stack->npushed].wnd; + nxgl_rectcopy(rect, &stack->stack[stack->npushed].rect); + return true; + } + return false; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_clipper + * + * Descripton: + * Perform flexible clipping operations. Callbacks are executed for + * each oscured and visible portions of the window. + * + * Input Parameters: + * wnd - The window to be clipped. + * rect - The region of concern within the window + * order - Specifies the order to process the parts of the non-intersecting + * sub-rectangles. + * cops - The callbacks to handle obscured and visible parts of the + * sub-rectangles. + * plane - The raster operations to be used by the callback functions. + * These may vary with different color formats. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void nxbe_clipper(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *dest, uint8_t order, + FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane) +{ + struct nxbe_clipstack_s stack; + FAR struct nxbe_window_s *currw; + struct nxgl_rect_s rect; + struct nxgl_rect_s obscuredrect; + struct nxgl_rect_s currbounds; + struct nxgl_rect_s nonoverlapped[4]; + int i; + + /* Initialize the stack where we will keep deferred rectangle operations */ + + stack.npushed = 0; + stack.mxrects = 0; + stack.stack = NULL; + + /* Loop until there are no further pending operations */ + + nxgl_rectcopy(&rect, dest); /* Start with the whole dest rectangle */ + do + { + /* Loop for every window from the current window and above. Only windows + * above the current window can obscure the current window + */ + + for (currw = wnd; currw; currw = currw->above) + { + /* Does the current window overlap the dest rectangle? */ + + currbounds = currw->bounds; + if (nxgl_rectoverlap(&rect, &currbounds)) + { + /* Yes.. then it obscures all or part of the dest rectangle. + * Divide the potentially visible, non-overlapping regions into 4 + * smaller rectangles and push them onto the stack for processing + * on the next time through the outer loop. + */ + + nxgl_nonintersecting(nonoverlapped, &rect, &currbounds); + for (i = 3; i >= 0; i--) + { + /* Push the rectangles in the order specific by the input + * argument of that name. + */ + + struct nxgl_rect_s *candidate = &nonoverlapped[g_nxcliporder[order][i]]; + if (!nxgl_nullrect(candidate)) + { + nxbe_pushrectangle(&stack, currw->above, candidate); + } + } + + /* Now performed any required processing on the obscurred, + * overlapped region. + */ + + nxgl_rectintersect(&obscuredrect, &rect, &currbounds); + cops->obscured(cops, plane, &obscuredrect); + + /* Break out of the loop to process the pushed rectangles */ + + break; + } + } + + /* If there are no other windows overlapping this rectangle, then this + * rectangular region must be visible. + */ + + if (!currw && !nxgl_nullrect(&rect)) + { + cops->visible(cops, plane, &rect); + } + } + while (nxbe_poprectangle(&stack, &wnd, &rect)); + + /* Done! If any stack was allocated, then free it before exit-ting */ + + if (stack.stack) + { + free(stack.stack); + } +} + +/**************************************************************************** + * Name: nxbe_clipnull + * + * Descripton: + * The do-nothing clipping callback function + * + ****************************************************************************/ + +void nxbe_clipnull(FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane, + FAR const struct nxgl_rect_s *rect) +{ +} + diff --git a/nuttx/graphics/nxbe/nxbe_closewindow.c b/nuttx/graphics/nxbe/nxbe_closewindow.c new file mode 100644 index 0000000000..3c583fcfbf --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_closewindow.c @@ -0,0 +1,137 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_closewindow.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxbe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_closewindow + * + * Description: + * Close an existing window + * + * Input Parameters: + * wnd - The window to be closed (and deallocated) + * + * Return: + * None + * + ****************************************************************************/ + +void nxbe_closewindow(struct nxbe_window_s *wnd) +{ + FAR struct nxbe_state_s *be; + +#ifdef CONFIG_DEBUG + if (!wnd) + { + return; + } +#endif + be = wnd->be; + + /* The background window should never be closed */ + + DEBUGASSERT(wnd != &be->bkgd); + + /* Is there a window above the one being closed? */ + + if (wnd->above) + { + /* Yes, now the window below that one is the window below + * the one being closed. + */ + + wnd->above->below = wnd->below; + } + else + { + /* No, then the top window is the one below this (which + * can never be NULL because the background window is + * always at the true bottom of the list + */ + + be->topwnd = wnd->below; + } + + /* There is always a window below the one being closed (because + * the background is never closed. Now, the window above that + * is the window above the one that is being closed. + */ + + wnd->below->above = wnd->above; + + /* Redraw the windows that were below us (and may now be exposed) */ + + nxbe_redrawbelow(be, wnd->below, &wnd->bounds); + + /* Then discard the window structure */ + + free(wnd); +} diff --git a/nuttx/graphics/nxbe/nxbe_colormap.c b/nuttx/graphics/nxbe/nxbe_colormap.c new file mode 100644 index 0000000000..1443175190 --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_colormap.c @@ -0,0 +1,155 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_colormap.c + * + * Copyright (C) 2008-2009,2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "nxbe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_colormap + * + * Description: + * Set the harware color map to the palette expected by NX + * + ****************************************************************************/ + +#if CONFIG_FB_CMAP +int nxbe_colormap(FAR NX_DRIVERTYPE *dev) +{ + struct fb_cmap_s cmap; + uint8_t *alloc; + uint8_t *red; + uint8_t *green; + uint8_t *blue; + uint8_t rval; + uint8_t gval; + int size; + int ndx; + int ret; + int i, j, k; + + /* Allocate the color map tables in one allocation: + * + * size = 3 colors x CONFIG_NX_COLORS each x 8-bits per color + */ + + size = 3 * CONFIG_NX_NCOLORS * sizeof(uint8_t); + alloc = (uint8_t*)malloc(size); + if (alloc == NULL) + { + return -ENOMEM; + } + memset(alloc, 0xff, size); + + /* Then get pointers to each color table */ + + red = alloc; + green = &alloc[CONFIG_NX_NCOLORS]; + blue = &alloc[2*CONFIG_NX_NCOLORS]; + + /* Initialize the color map tables. 6*6*6 = 216, the rest + * are (0xff, 0xfff 0xff) + */ + + ndx = 0; + for (i = 0; i < 6; i++) + { + rval = (i * (CONFIG_NX_NCOLORS-1) / 5) << 8; + for (j = 0; j < 6; j++) + { + gval = (j * (CONFIG_NX_NCOLORS-1) / 5) << 8; + for (k = 0; k < 6; k++) + { + red[ndx] = rval; + green[ndx] = gval; + blue[ndx] = k * (CONFIG_NX_NCOLORS-1) / 5; + ndx++; + } + } + } + + /* Now configure the cmap structure */ + + cmap.first = 0; + cmap.len = CONFIG_NX_NCOLORS; + cmap.red = red; + cmap.green = green; + cmap.blue = blue; +#ifdef CONFIG_FB_TRANSPARENCY + cmap.transp = NULL; +#endif + + /* Then set the color map */ + + ret = dev->putcmap(dev, &cmap); + + free(alloc); + return ret; +} +#endif diff --git a/nuttx/graphics/nxbe/nxbe_configure.c b/nuttx/graphics/nxbe/nxbe_configure.c new file mode 100644 index 0000000000..80c71db3a5 --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_configure.c @@ -0,0 +1,219 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_configure.c + * + * Copyright (C) 2008-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "nxbe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_configure + * + * Description: + * Configure the back end state structure based on information from the + * framebuffer driver + * + ****************************************************************************/ + +int nxbe_configure(FAR NX_DRIVERTYPE *dev, FAR struct nxbe_state_s *be) +{ + int ret; + int i; + + /* Get the video controller configuration */ + + ret = dev->getvideoinfo(dev, &be->vinfo); + if (ret < 0) + { + gdbg("Failed to get vinfo\n"); + return ret; + } + + /* Check the number of color planes */ + +#ifdef CONFIG_DEBUG + if (be->vinfo.nplanes > CONFIG_NX_NPLANES) + { + gdbg("NX configured for only %d planes, controller wants %d\n", + CONFIG_NX_NPLANES, be->vinfo.nplanes); + return -E2BIG; + } + else if (be->vinfo.nplanes < CONFIG_NX_NPLANES) + { + gdbg("NX configured for %d planes, controller only needs %d\n", + CONFIG_NX_NPLANES, be->vinfo.nplanes); + } +#endif + + /* Then get information about each color plane */ + + for (i = 0; i < be->vinfo.nplanes; i++) + { + ret = dev->getplaneinfo(dev, i, &be->plane[i].pinfo); + if (ret < 0) + { + gdbg("Failed to get pinfo[%d]\n", i); + return ret; + } + + /* Select rasterizers to match the BPP reported for this plane. + * NOTE that there are configuration options to eliminate support + * for unused BPP values. If the unused BPP values are not suppressed + * in this way, then ALL rasterizers will be drawn into the link and + * will signicantly increase the size + */ + +#ifndef CONFIG_NX_DISABLE_1BPP + if (be->plane[i].pinfo.bpp == 1) + { + be->plane[i].setpixel = nxgl_setpixel_1bpp; + be->plane[i].fillrectangle = nxgl_fillrectangle_1bpp; + be->plane[i].getrectangle = nxgl_getrectangle_1bpp; + be->plane[i].filltrapezoid = nxgl_filltrapezoid_1bpp; + be->plane[i].moverectangle = nxgl_moverectangle_1bpp; + be->plane[i].copyrectangle = nxgl_copyrectangle_1bpp; + } + else +#endif +#ifndef CONFIG_NX_DISABLE_2BPP + if (be->plane[i].pinfo.bpp == 2) + { + be->plane[i].setpixel = nxgl_setpixel_2bpp; + be->plane[i].fillrectangle = nxgl_fillrectangle_2bpp; + be->plane[i].getrectangle = nxgl_getrectangle_2bpp; + be->plane[i].filltrapezoid = nxgl_filltrapezoid_2bpp; + be->plane[i].moverectangle = nxgl_moverectangle_2bpp; + be->plane[i].copyrectangle = nxgl_copyrectangle_2bpp; + } + else +#endif +#ifndef CONFIG_NX_DISABLE_4BPP + if (be->plane[i].pinfo.bpp == 4) + { + be->plane[i].setpixel = nxgl_setpixel_4bpp; + be->plane[i].fillrectangle = nxgl_fillrectangle_4bpp; + be->plane[i].getrectangle = nxgl_getrectangle_4bpp; + be->plane[i].filltrapezoid = nxgl_filltrapezoid_4bpp; + be->plane[i].moverectangle = nxgl_moverectangle_4bpp; + be->plane[i].copyrectangle = nxgl_copyrectangle_4bpp; + } + else +#endif +#ifndef CONFIG_NX_DISABLE_8BPP + if (be->plane[i].pinfo.bpp == 8) + { + be->plane[i].setpixel = nxgl_setpixel_8bpp; + be->plane[i].fillrectangle = nxgl_fillrectangle_8bpp; + be->plane[i].getrectangle = nxgl_getrectangle_8bpp; + be->plane[i].filltrapezoid = nxgl_filltrapezoid_8bpp; + be->plane[i].moverectangle = nxgl_moverectangle_8bpp; + be->plane[i].copyrectangle = nxgl_copyrectangle_8bpp; + } + else +#endif +#ifndef CONFIG_NX_DISABLE_16BPP + if (be->plane[i].pinfo.bpp == 16) + { + be->plane[i].setpixel = nxgl_setpixel_16bpp; + be->plane[i].fillrectangle = nxgl_fillrectangle_16bpp; + be->plane[i].getrectangle = nxgl_getrectangle_16bpp; + be->plane[i].filltrapezoid = nxgl_filltrapezoid_16bpp; + be->plane[i].moverectangle = nxgl_moverectangle_16bpp; + be->plane[i].copyrectangle = nxgl_copyrectangle_16bpp; + } + else +#endif +#ifndef CONFIG_NX_DISABLE_24BPP + if (be->plane[i].pinfo.bpp == 24) + { + be->plane[i].setpixel = nxgl_setpixel_24bpp; + be->plane[i].fillrectangle = nxgl_fillrectangle_24bpp; + be->plane[i].getrectangle = nxgl_getrectangle_24bpp; + be->plane[i].filltrapezoid = nxgl_filltrapezoid_24bpp; + be->plane[i].moverectangle = nxgl_moverectangle_24bpp; + be->plane[i].copyrectangle = nxgl_copyrectangle_24bpp; + } + else +#endif +#ifndef CONFIG_NX_DISABLE_32BPP + if (be->plane[i].pinfo.bpp == 32) + { + be->plane[i].setpixel = nxgl_setpixel_32bpp; + be->plane[i].fillrectangle = nxgl_fillrectangle_32bpp; + be->plane[i].getrectangle = nxgl_getrectangle_32bpp; + be->plane[i].filltrapezoid = nxgl_filltrapezoid_32bpp; + be->plane[i].moverectangle = nxgl_moverectangle_32bpp; + be->plane[i].copyrectangle = nxgl_copyrectangle_32bpp; + } + else +#endif + { + gdbg("Unsupported pinfo[%d] BPP: %d\n", i, be->plane[i].pinfo.bpp); + return -ENOSYS; + } + } + return OK; +} diff --git a/nuttx/graphics/nxbe/nxbe_fill.c b/nuttx/graphics/nxbe/nxbe_fill.c new file mode 100644 index 0000000000..f4aec74773 --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_fill.c @@ -0,0 +1,157 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_fill.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "nxbe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nxbe_fill_s +{ + struct nxbe_clipops_s cops; + nxgl_mxpixel_t color; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_clipfill + * + * Description: + * Called from nxbe_clipper() to performed the fill operation on visible portions + * of the rectangle. + * + ****************************************************************************/ + +static void nxbe_clipfill(FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane, + FAR const struct nxgl_rect_s *rect) +{ + struct nxbe_fill_s *fillinfo = (struct nxbe_fill_s *)cops; + plane->fillrectangle(&plane->pinfo, rect, fillinfo->color); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_fill + * + * Description: + * Fill the specified rectangle in the window with the specified color + * + * Input Parameters: + * wnd - The window structure reference + * rect - The location to be filled + * col - The color to use in the fill + * + * Return: + * None + * + ****************************************************************************/ + +void nxbe_fill(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + struct nxbe_fill_s info; + struct nxgl_rect_s remaining; + int i; + +#ifdef CONFIG_DEBUG + if (!wnd || !rect) + { + return; + } +#endif + + /* Offset the rectangle by the window origin to convert it into a + * bounding box + */ + + nxgl_rectoffset(&remaining, rect, wnd->bounds.pt1.x, wnd->bounds.pt1.y); + + /* Clip to the bounding box to the limits of the window and of the + * background screen + */ + + nxgl_rectintersect(&remaining, &remaining, &wnd->bounds); + nxgl_rectintersect(&remaining, &remaining, &wnd->be->bkgd.bounds); + + /* Then clip the bounding box due to other windows above this one. + * Render the portions of the trapezoid exposed in visible regions. + */ + + if (!nxgl_nullrect(&remaining)) + { +#if CONFIG_NX_NPLANES > 1 + for (i = 0; i < wnd->be->vinfo.nplanes; i++) +#else + i = 0; +#endif + { + info.cops.visible = nxbe_clipfill; + info.cops.obscured = nxbe_clipnull; + info.color = color[i]; + + nxbe_clipper(wnd->above, &remaining, NX_CLIPORDER_DEFAULT, + &info.cops, &wnd->be->plane[i]); + } + } +} diff --git a/nuttx/graphics/nxbe/nxbe_filltrapezoid.c b/nuttx/graphics/nxbe/nxbe_filltrapezoid.c new file mode 100644 index 0000000000..68dad838cd --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_filltrapezoid.c @@ -0,0 +1,173 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_filltrapezoid.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "nxbe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nxbe_filltrap_s +{ + struct nxbe_clipops_s cops; + struct nxgl_trapezoid_s trap; + nxgl_mxpixel_t color; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_clipfilltrapezoid + * + * Description: + * Called from nxbe_clipper() to performed the fill operation on visible portions + * of the rectangle. + * + ****************************************************************************/ + +static void nxbe_clipfilltrapezoid(FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane, + FAR const struct nxgl_rect_s *rect) +{ + struct nxbe_filltrap_s *fillinfo = (struct nxbe_filltrap_s *)cops; + plane->filltrapezoid(&plane->pinfo, &fillinfo->trap, rect, fillinfo->color); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_filltrapezoid + * + * Description: + * Fill the specified rectangle in the window with the specified color + * + * Input Parameters: + * wnd - The window structure reference + * clip - Clipping region (in relative window coordinates) + * rect - The location to be filled (in relative window coordinates) + * col - The color to use in the fill + * + * Return: + * None + * + ****************************************************************************/ + +void nxbe_filltrapezoid(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *clip, + FAR const struct nxgl_trapezoid_s *trap, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + struct nxbe_filltrap_s info; + struct nxgl_rect_s remaining; + int i; + +#ifdef CONFIG_DEBUG + if (!wnd || !trap) + { + return; + } +#endif + + /* Offset the trapezoid by the window origin to position it within + * the framebuffer region + */ + + nxgl_trapoffset(&info.trap, trap, wnd->bounds.pt1.x, wnd->bounds.pt1.y); + + /* Create a bounding box that contains the trapezoid */ + + remaining.pt1.x = b16toi(ngl_min(info.trap.top.x1, info.trap.bot.x1)); + remaining.pt1.y = info.trap.top.y; + remaining.pt2.x = b16toi(ngl_max(info.trap.top.x2, info.trap.bot.x2)); + remaining.pt2.y = info.trap.bot.y; + + /* Clip to any user specified clipping window */ + + if (clip) + { + struct nxgl_rect_s tmp; + nxgl_rectoffset(&tmp, clip, wnd->bounds.pt1.x, wnd->bounds.pt1.y); + nxgl_rectintersect(&remaining, &remaining, &tmp); + } + + /* Clip to the limits of the window and of the background screen */ + + nxgl_rectintersect(&remaining, &remaining, &wnd->bounds); + nxgl_rectintersect(&remaining, &remaining, &wnd->be->bkgd.bounds); + + if (!nxgl_nullrect(&remaining)) + { + info.cops.visible = nxbe_clipfilltrapezoid; + info.cops.obscured = nxbe_clipnull; + + /* Then process each color plane */ + +#if CONFIG_NX_NPLANES > 1 + for (i = 0; i < wnd->be->vinfo.nplanes; i++) +#else + i = 0; +#endif + { + info.color = color[i]; + nxbe_clipper(wnd->above, &remaining, NX_CLIPORDER_DEFAULT, + &info.cops, &wnd->be->plane[i]); + } + } +} diff --git a/nuttx/graphics/nxbe/nxbe_getrectangle.c b/nuttx/graphics/nxbe/nxbe_getrectangle.c new file mode 100644 index 0000000000..84f010cd5f --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_getrectangle.c @@ -0,0 +1,138 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_fill.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "nxbe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nxbe_fill_s +{ + struct nxbe_clipops_s cops; + nxgl_mxpixel_t color; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_getrectangle + * + * Description: + * Get the raw contents of graphic memory within a rectangular region. NOTE: + * Since raw graphic memory is returned, the returned memory content may be + * the memory of windows above this one and may not necessarily belong to + * this window unless you assure that this is the top window. + * + * Input Parameters: + * wnd - The window structure reference + * rect - The location to be copied + * plane - Specifies the color plane to get from. + * dest - The location to copy the memory region + * deststride - The width, in bytes, the the dest memory + * + * Return: + * None + * + ****************************************************************************/ + +void nxbe_getrectangle(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *rect, unsigned int plane, + FAR uint8_t *dest, unsigned int deststride) +{ + struct nxgl_rect_s remaining; + +#ifdef CONFIG_DEBUG + if (!wnd || !rect || ! rect || plane >= wnd->be->vinfo.nplanes) + { + gvdbg("Invalid parameters\n"); + return; + } +#endif + + /* Offset the rectangle by the window origin to convert it into a + * bounding box + */ + + nxgl_rectoffset(&remaining, rect, wnd->bounds.pt1.x, wnd->bounds.pt1.y); + + /* Clip to the bounding box to the limits of the window and of the + * background screen + */ + + nxgl_rectintersect(&remaining, &remaining, &wnd->bounds); + nxgl_rectintersect(&remaining, &remaining, &wnd->be->bkgd.bounds); + + /* The return the graphics memory at this location. NOTE: Since raw + * graphic memory is returned, the returned memory content may be + * the memory of windows above this one and may not necessarily belong + * to this window. + */ + + if (!nxgl_nullrect(&remaining)) + { + FAR struct nxbe_plane_s *pplane = &wnd->be->plane[plane]; + pplane->getrectangle(&pplane->pinfo, &remaining, dest, deststride); + } +} diff --git a/nuttx/graphics/nxbe/nxbe_lower.c b/nuttx/graphics/nxbe/nxbe_lower.c new file mode 100644 index 0000000000..545342d5bf --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_lower.c @@ -0,0 +1,125 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_lower.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxbe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_lower + * + * Description: + * Lower the specified window to the bottom of the display. + * + ****************************************************************************/ + +void nxbe_lower(FAR struct nxbe_window_s *wnd) +{ + FAR struct nxbe_state_s *be = wnd->be; + FAR struct nxbe_window_s *below; + + /* If the window is already at the bottom, then there is nothing to do */ + + if (!wnd->below || wnd->below == &be->bkgd) + { + return; + } + + /* Remove the window from its current position in the list */ + + wnd->below->above = wnd->above; + + /* Was it at the top of the display? */ + + if (wnd->above) + { + /* No... it was in the middle somewhere */ + + wnd->above->below = wnd->below; + } + else + { + /* Yes.. set the new top window */ + + be->topwnd = wnd->below; + be->topwnd->above = NULL; + } + + /* Remember the window that was just below us */ + + below = wnd->below; + + /* Then put the lowered window at the bottom (just above the background window) */ + + wnd->below = &be->bkgd; + wnd->above = be->bkgd.above; + be->bkgd.above = wnd; + + /* Redraw the windows that were below us (but now are above) */ + + nxbe_redrawbelow(be, below, &wnd->bounds); +} diff --git a/nuttx/graphics/nxbe/nxbe_move.c b/nuttx/graphics/nxbe/nxbe_move.c new file mode 100644 index 0000000000..193b174c2d --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_move.c @@ -0,0 +1,284 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_move.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "nxbe.h" +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nxbe_move_s +{ + struct nxbe_clipops_s cops; + struct nxgl_point_s offset; + FAR struct nxbe_window_s *wnd; + struct nxgl_rect_s srcrect; + uint8_t order; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_clipmovesrc + * + * Description: + * Called from nxbe_clipper() to performed the move operation on visible regions + * of the rectangle. + * + ****************************************************************************/ + +static void nxbe_clipmovesrc(FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane, + FAR const struct nxgl_rect_s *rect) +{ + struct nxbe_move_s *info = (struct nxbe_move_s *)cops; + struct nxgl_point_s offset; + + if (info->offset.x != 0 || info->offset.y != 0) + { + /* Offset is the destination position of the moved rectangle */ + + offset.x = rect->pt1.x + info->offset.x; + offset.y = rect->pt1.y + info->offset.y; + + plane->moverectangle(&plane->pinfo, rect, &offset); + } +} + +/**************************************************************************** + * Name: nxbe_clipmoveobscured + * + * Description: + * Called from nxbe_clipper() to performed the move operation on obsrured regions + * of the rectangle. + * + ****************************************************************************/ + +static void nxbe_clipmoveobscured(FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane, + FAR const struct nxgl_rect_s *rect) +{ + struct nxbe_move_s *info = (struct nxbe_move_s *)cops; + struct nxgl_rect_s dst; + + nxgl_rectoffset(&dst, rect, info->offset.x, info->offset.y); + nxfe_redrawreq(info->wnd, &dst); +} + +/**************************************************************************** + * Name: nxbe_clipmovedest + * + * Description: + * Called from nxbe_clipper() to performed the move operation on visible + * regions of the source rectangle. + * + ****************************************************************************/ + +static void nxbe_clipmovedest(FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane, + FAR const struct nxgl_rect_s *rect) +{ + struct nxbe_move_s *dstdata = (struct nxbe_move_s *)cops; + struct nxbe_window_s *wnd = dstdata->wnd; + struct nxgl_point_s offset = dstdata->offset; + struct nxgl_rect_s src; + struct nxgl_rect_s tmprect1; + struct nxgl_rect_s tmprect2; + struct nxgl_rect_s nonintersecting[4]; + int i; + + /* Redraw dest regions where the source is outside of the bounds of the + * background window + */ + + nxgl_rectoffset(&tmprect1, &dstdata->srcrect, offset.x, offset.y); + nxgl_rectintersect(&tmprect2, &tmprect1, &wnd->be->bkgd.bounds); + nxgl_nonintersecting(nonintersecting, rect, &tmprect2); + + for (i = 0; i < 4; i++) + { + if (!nxgl_nullrect(&nonintersecting[i])) + { + nxfe_redrawreq(dstdata->wnd, &nonintersecting[i]); + } + } + + /* Clip to determine what is inside the bounds */ + + nxgl_rectintersect(&src, rect, &dstdata->srcrect); + + if (!nxgl_nullrect(&src)) + { + struct nxbe_move_s srcinfo; + + srcinfo.cops.visible = nxbe_clipmovesrc; + srcinfo.cops.obscured = nxbe_clipmoveobscured; + srcinfo.offset = offset; + srcinfo.wnd = wnd; + + nxbe_clipper(dstdata->wnd->above, &src, dstdata->order, + &srcinfo.cops, plane); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_move + * + * Description: + * Move a rectangular region within the window + * + * Input Parameters: + * wnd - The window within which the move is to be done + * rect - Describes the rectangular region to move + * offset - The offset to move the region + * + * Return: + * None + * + ****************************************************************************/ + +void nxbe_move(FAR struct nxbe_window_s *wnd, FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset) +{ + struct nxbe_move_s info; + int i; + +#ifdef CONFIG_DEBUG + if (!wnd || !rect) + { + return; + } +#endif + + /* Offset the rectangle by the window origin to create a bounding box */ + + nxgl_rectoffset(&info.srcrect, rect, wnd->bounds.pt1.x, wnd->bounds.pt1.y); + + /* Clip to the limits of the window and of the background screen */ + + nxgl_rectintersect(&info.srcrect, &info.srcrect, &wnd->bounds); + nxgl_rectintersect(&info.srcrect, &info.srcrect, &wnd->be->bkgd.bounds); + + if (nxgl_nullrect(&info.srcrect)) + { + return; + } + + info.cops.visible = nxbe_clipmovedest; + info.cops.obscured = nxbe_clipnull; + info.offset.x = offset->x; + info.offset.y = offset->y; + info.wnd = wnd; + + /* The clip order depends up the direction that the rectangle is being + * moved. + */ + + if (offset->y < 0) + { + /* Moving rectangle up */ + + if (offset->x < 0) + { + /* Moving to upper-left */ + + info.order = NX_CLIPORDER_TLRB; /* Top-left-right-bottom */ + } + else + { + /* Moving to upper-right (or just up) */ + + info.order = NX_CLIPORDER_TRLB; /* Top-right-left-bottom */ + } + } + else + { + /* Moving rectangle down (or just left/right) */ + + if (offset->x < 0) + { + /* Moving to lower-left */ + + info.order = NX_CLIPORDER_BLRT; /* Bottom-left-right-top */ + } + else + { + /* Moving to lower-right */ + + info.order = NX_CLIPORDER_BRLT; /* Bottom-right-left-top */ + } + } + + /* Then perform the move */ + +#if CONFIG_NX_NPLANES > 1 + for (i = 0; i < wnd->be->vinfo.nplanes; i++) +#else + i = 0; +#endif + { + nxbe_clipper(wnd->above, &info.srcrect, info.order, + &info.cops, &wnd->be->plane[i]); + } +} diff --git a/nuttx/graphics/nxbe/nxbe_raise.c b/nuttx/graphics/nxbe/nxbe_raise.c new file mode 100644 index 0000000000..ef4c392c03 --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_raise.c @@ -0,0 +1,116 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_raise.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "nxbe.h" +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nxbe_raise_s +{ + struct nxbe_clipops_s cops; + FAR struct nxbe_window_s *wnd; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_raise + * + * Description: + * Bring the specified window to the top of the display. + * + ****************************************************************************/ + +void nxbe_raise(FAR struct nxbe_window_s *wnd) +{ + FAR struct nxbe_state_s *be = wnd->be; + + /* If this window is already at the top of the display, then do nothing */ + + if (!wnd->above) + { + return; + } + + /* Remove window from the list. Note that there is always + * some below this window (it may only be the background window) + */ + + wnd->above->below = wnd->below; + wnd->below->above = wnd->above; + + /* Then put it back in the list at the top */ + + wnd->above = NULL; + wnd->below = be->topwnd; + + be->topwnd->above = wnd; + be->topwnd = wnd; + + /* This window is now at the top of the display, we know, therefore, that + * it is not obscured by another window + */ + + nxfe_redrawreq(wnd, &wnd->bounds); +} diff --git a/nuttx/graphics/nxbe/nxbe_redraw.c b/nuttx/graphics/nxbe/nxbe_redraw.c new file mode 100644 index 0000000000..3226ccf328 --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_redraw.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_redraw.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "nxbe.h" +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nxbe_redraw_s +{ + struct nxbe_clipops_s cops; + FAR struct nxbe_window_s *wnd; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_clipredraw + ****************************************************************************/ + +static void nxbe_clipredraw(FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane, + FAR const struct nxgl_rect_s *rect) +{ + FAR struct nxbe_window_s *wnd = ((struct nxbe_redraw_s *)cops)->wnd; + if (wnd) + { + nxfe_redrawreq(wnd, rect); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_redraw + * + * Descripton: + * Re-draw the visible portions of the rectangular region for the + * specified window + * + ****************************************************************************/ + +void nxbe_redraw(FAR struct nxbe_state_s *be, + FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *rect) +{ + struct nxbe_redraw_s info; + struct nxgl_rect_s remaining; +#if CONFIG_NX_NPLANES > 1 + int i; +#endif + + /* Clip to the limits of the window and of the background screen */ + + nxgl_rectintersect(&remaining, rect, &be->bkgd.bounds); + nxgl_rectintersect(&remaining, &remaining, &wnd->bounds); + if (!nxgl_nullrect(&remaining)) + { + /* Now, request to re-draw any visible rectangular regions not obscured + * by windows above this one. + */ + + info.cops.visible = nxbe_clipredraw; + info.cops.obscured = nxbe_clipnull; + info.wnd = wnd; + +#if CONFIG_NX_NPLANES > 1 + for (i = 0; i < be->vinfo.nplanes; i++) + { + nxbe_clipper(wnd->above, &remaining, NX_CLIPORDER_DEFAULT, + &info.cops, &be->plane[i]); + } +#else + nxbe_clipper(wnd->above, &remaining, NX_CLIPORDER_DEFAULT, + &info.cops, &be->plane[0]); +#endif + } +} diff --git a/nuttx/graphics/nxbe/nxbe_redrawbelow.c b/nuttx/graphics/nxbe/nxbe_redrawbelow.c new file mode 100644 index 0000000000..c795e5fed3 --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_redrawbelow.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_redraw.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "nxbe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_redrawbelow + * + * Descripton: + * Re-draw the visible portions of the rectangular region for all windows + * below (and including) the specified window. This function is called + * whenever a window is closed, moved, lowered or re-sized in order to + * expose newly visible portions of lower windows. + * + ****************************************************************************/ + +void nxbe_redrawbelow(FAR struct nxbe_state_s *be, FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *rect) +{ + FAR struct nxbe_window_s *currwnd; + + for (currwnd = wnd; currwnd; currwnd = currwnd->below) + { + nxbe_redraw(be, currwnd, rect); + } +} diff --git a/nuttx/graphics/nxbe/nxbe_setpixel.c b/nuttx/graphics/nxbe/nxbe_setpixel.c new file mode 100644 index 0000000000..d333b9b76c --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_setpixel.c @@ -0,0 +1,158 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_setpixel.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "nxbe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nxbe_setpixel_s +{ + struct nxbe_clipops_s cops; + nxgl_mxpixel_t color; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_clipfill + * + * Description: + * Called from nxbe_clipper() to performed the fill operation on visible portions + * of the rectangle. + * + ****************************************************************************/ + +static void nxbe_clipfill(FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane, + FAR const struct nxgl_rect_s *rect) +{ + struct nxbe_setpixel_s *fillinfo = (struct nxbe_setpixel_s *)cops; + plane->setpixel(&plane->pinfo, &rect->pt1, fillinfo->color); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_fill + * + * Description: + * Fill the specified rectangle in the window with the specified color + * + * Input Parameters: + * wnd - The window structure reference + * rect - The location to be filled + * col - The color to use in the fill + * + * Return: + * None + * + ****************************************************************************/ + +void nxbe_setpixel(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_point_s *pos, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + struct nxbe_setpixel_s info; + struct nxgl_rect_s rect; + int i; + +#ifdef CONFIG_DEBUG + if (!wnd || !pos) + { + return; + } +#endif + + /* Offset the position by the window origin */ + + nxgl_vectoradd(&rect.pt1, pos, &wnd->bounds.pt1); + + /* Make sure that the point is within the limits of the window + * and of the background screen + */ + + if (!nxgl_rectinside(&wnd->bounds, &rect.pt1) || + !nxgl_rectinside(&wnd->be->bkgd.bounds, &rect.pt1)) + { + return; + } + + /* Then create a bounding box and render the point if there it + * is exposed. + */ + + rect.pt2.x = rect.pt1.x; + rect.pt2.y = rect.pt1.y; + +#if CONFIG_NX_NPLANES > 1 + for (i = 0; i < wnd->be->vinfo.nplanes; i++) +#else + i = 0; +#endif + { + info.cops.visible = nxbe_clipfill; + info.cops.obscured = nxbe_clipnull; + info.color = color[i]; + + nxbe_clipper(wnd->above, &rect, NX_CLIPORDER_DEFAULT, + &info.cops, &wnd->be->plane[i]); + } +} diff --git a/nuttx/graphics/nxbe/nxbe_setposition.c b/nuttx/graphics/nxbe/nxbe_setposition.c new file mode 100644 index 0000000000..f407eea3fa --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_setposition.c @@ -0,0 +1,119 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_setposition.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "nxbe.h" +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_setposition + * + * Descripton: + * This function checks for intersections and redraws the display after + * a change in the position of a window. + * + ****************************************************************************/ + +void nxbe_setposition(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_point_s *pos) +{ + struct nxgl_rect_s before; + struct nxgl_rect_s rect; + +#ifdef CONFIG_DEBUG + if (!wnd) + { + return; + } +#endif + + /* Back out the old window origin position from the bounding box */ + + nxgl_rectoffset(&rect, &wnd->bounds, -wnd->bounds.pt1.x, -wnd->bounds.pt1.y); + + /* Add the new window origin into the bounding box */ + + nxgl_rectcopy(&before, &wnd->bounds); + nxgl_rectoffset(&wnd->bounds, &rect, pos->x, pos->y); + + /* Get the union of the 'before' bounding box and the 'after' bounding + * this union is the region of the display that must be updated. + */ + + nxgl_rectunion(&rect, &before, &wnd->bounds); + nxgl_rectintersect(&rect, &rect, &wnd->be->bkgd.bounds); + + /* Report the new size/position */ + + nxfe_reportposition(wnd); + + /* Then redraw this window AND all windows below it. Having moved the + * window, we may have exposed previoulsy obscured portions of windows + * below this one. + */ + + nxbe_redrawbelow(wnd->be, wnd, &rect); +} diff --git a/nuttx/graphics/nxbe/nxbe_setsize.c b/nuttx/graphics/nxbe/nxbe_setsize.c new file mode 100644 index 0000000000..367f5d7dc9 --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_setsize.c @@ -0,0 +1,121 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_setsize.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "nxbe.h" +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_setsize + * + * Descripton: + * This function checks for intersections and redraws the display after + * a change in the size of a window. + * + ****************************************************************************/ + +void nxbe_setsize(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_size_s *size) +{ + struct nxgl_rect_s bounds; + +#ifdef CONFIG_DEBUG + if (!wnd) + { + return; + } +#endif + + /* Save the before size of the window's bounding box */ + + nxgl_rectcopy(&bounds, &wnd->bounds); + + /* Add the window origin to the supplied size get the new window bounding box */ + + wnd->bounds.pt2.x = wnd->bounds.pt1.x + size->w - 1; + wnd->bounds.pt2.y = wnd->bounds.pt1.y + size->h - 1; + + /* Clip the new bounding box so that lies within the background screen */ + + nxgl_rectintersect(&wnd->bounds, &wnd->bounds, &wnd->be->bkgd.bounds); + + /* We need to update the larger of the two rectangles. That will be the + * union of the before and after sizes. + */ + + nxgl_rectunion(&bounds, &bounds, &wnd->bounds); + + /* Report the new size/position */ + + nxfe_reportposition(wnd); + + /* Then redraw this window AND all windows below it. Having resized the + * window, we may have exposed previoulsy obscured portions of windows + * below this one. + */ + + nxbe_redrawbelow(wnd->be, wnd, &bounds); +} diff --git a/nuttx/graphics/nxbe/nxbe_visible.c b/nuttx/graphics/nxbe/nxbe_visible.c new file mode 100644 index 0000000000..6b8b9291bb --- /dev/null +++ b/nuttx/graphics/nxbe/nxbe_visible.c @@ -0,0 +1,134 @@ +/**************************************************************************** + * graphics/nxbe/nxbe_redraw.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "nxbe.h" +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nxbe_visible_s +{ + struct nxbe_clipops_s cops; + bool visible; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_clipvisible + ****************************************************************************/ + +static void nxbe_clipvisible(FAR struct nxbe_clipops_s *cops, + FAR struct nxbe_plane_s *plane, + FAR const struct nxgl_rect_s *rect) +{ + FAR struct nxbe_visible_s *info = (FAR struct nxbe_visible_s *)cops; + info->visible = true; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxbe_visible + * + * Descripton: + * Return true if the point, pt, in window wnd is visible. pt is in + * absolute screen coordinates + * + ****************************************************************************/ + +bool nxbe_visible(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_point_s *pos) +{ + struct nxbe_visible_s info; + + /* Check if the absolute position lies within the window */ + + if (!nxgl_rectinside(&wnd->bounds, pos)) + { + return false; + } + + /* If this is the top window, then the psition is visible */ + + if (!wnd->above) + { + return true; + } + + /* The position within the window range, but the window is not at + * the top. We will have to work harder to determine if the point + * visible + */ + + info.cops.visible = nxbe_clipvisible; + info.cops.obscured = nxbe_clipnull; + info.visible = false; + + nxbe_clipper(wnd->above, &wnd->bounds, NX_CLIPORDER_DEFAULT, + &info.cops, &wnd->be->plane[0]); + + return info.visible; +} diff --git a/nuttx/graphics/nxconsole/Make.defs b/nuttx/graphics/nxconsole/Make.defs new file mode 100644 index 0000000000..a57b228850 --- /dev/null +++ b/nuttx/graphics/nxconsole/Make.defs @@ -0,0 +1,48 @@ +############################################################################ +# graphics/nxconsole/Make.defs +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +NXCON_ASRCS = +NXCON_CSRCS = nx_register.c nxcon_driver.c nxcon_font.c nxcon_putc.c +NXCON_CSRCS += nxcon_redraw.c nxcon_register.c nxcon_scroll.c +NXCON_CSRCS += nxcon_vt100.c nxcon_unregister.c nxtk_register.c +NXCON_CSRCS += nxtool_register.c + +ifeq ($(CONFIG_NXCONSOLE_NXKBDIN),y) +NXCON_CSRCS += nxcon_kbdin.c +endif + +ifeq ($(CONFIG_DEBUG),y) +NXCON_CSRCS += nxcon_sem.c +endif diff --git a/nuttx/graphics/nxconsole/nx_register.c b/nuttx/graphics/nxconsole/nx_register.c new file mode 100644 index 0000000000..8ebe0c0d5e --- /dev/null +++ b/nuttx/graphics/nxconsole/nx_register.c @@ -0,0 +1,193 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nx_register.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "nxcon_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int nxcon_fill(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t wcolor[CONFIG_NX_NPLANES]); +#ifndef CONFIG_NX_WRITEONLY +static int nxcon_move(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset); +#endif +static int nxcon_bitmap(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, + unsigned int stride); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct nxcon_operations_s g_nxops = +{ + nxcon_fill, +#ifndef CONFIG_NX_WRITEONLY + nxcon_move, +#endif + nxcon_bitmap +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_fill + * + * Description: + * Fill the specified rectangle in the window with the specified color + * + * Input Parameters: + * priv - The driver state structure. + * rect - The location to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +static int nxcon_fill(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t wcolor[CONFIG_NX_NPLANES]) +{ + return nx_fill((NXWINDOW)priv->handle, rect, wcolor); +} + +/**************************************************************************** + * Name: nxcon_move + * + * Description: + * Move a rectangular region within the window + * + * Input Parameters: + * priv - The driver state structure. + * rect - Describes the rectangular region to move + * offset - The offset to move the region. The rectangular region will be + * moved so that the origin is translated by this amount. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +#ifndef CONFIG_NX_WRITEONLY +static int nxcon_move(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset) +{ + return nx_move((NXWINDOW)priv->handle, rect, offset); +} +#endif + +/**************************************************************************** + * Name: nxcon_bitmap + * + * Description: + * Copy a rectangular region of a larger image into the rectangle in the + * specified window. + * + * Input Parameters: + * priv - The driver state structure. + * dest - Describes the rectangular region on the display that will + * receive the bit map. + * src - The start of the source image. This is an array source + * images of size CONFIG_NX_NPLANES. + * origin - The origin of the upper, left-most corner of the full bitmap. + * Both dest and origin are in window coordinates, however, origin + * may lie outside of the display. + * stride - The width of the full source image in bytes. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +static int nxcon_bitmap(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, + unsigned int stride) +{ + return nx_bitmap((NXWINDOW)priv->handle, dest, src, origin, stride); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_register + * + * Description: + * Register a console device on a raw NX window. The device will be + * registered at /dev/nxconN where N is the provided minor number. + * + * Input Parameters: + * hwnd - A handle that will be used to access the window. The window must + * persist and this handle must be valid for the life of the NX console. + * wndo - Describes the window and font to be used + * minor - The device minor number + * + * Return: + * A non-NULL handle is returned on success. + * + ****************************************************************************/ + +NXCONSOLE nx_register(NXWINDOW hwnd, FAR struct nxcon_window_s *wndo, int minor) +{ + return nxcon_register((NXCONSOLE)hwnd, wndo, &g_nxops, minor); +} + diff --git a/nuttx/graphics/nxconsole/nxcon_driver.c b/nuttx/graphics/nxconsole/nxcon_driver.c new file mode 100755 index 0000000000..c647f97bba --- /dev/null +++ b/nuttx/graphics/nxconsole/nxcon_driver.c @@ -0,0 +1,257 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nxcon_driver.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "nxcon_internal.h" + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int nxcon_open(FAR struct file *filep); +static ssize_t nxcon_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); + +/**************************************************************************** + * Public Data + ****************************************************************************/ +/* This is the common NX driver file operations */ + +#ifdef CONFIG_NXCONSOLE_NXKBDIN + +const struct file_operations g_nxcon_drvrops = +{ + nxcon_open, /* open */ + 0, /* close */ + nxcon_read, /* read */ + nxcon_write, /* write */ + 0, /* seek */ + 0 /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , + nxcon_poll /* poll */ +#endif +}; + +#else /* CONFIG_NXCONSOLE_NXKBDIN */ + +const struct file_operations g_nxcon_drvrops = +{ + nxcon_open, /* open */ + 0, /* close */ + 0, /* read */ + nxcon_write, /* write */ + 0, /* seek */ + 0 /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , + 0 /* poll */ +#endif +}; + +#endif /* CONFIG_NXCONSOLE_NXKBDIN */ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_open + ****************************************************************************/ + +static int nxcon_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct nxcon_state_s *priv = inode->i_private; + + DEBUGASSERT(filep && filep->f_inode); + + /* Get the driver structure from the inode */ + + inode = filep->f_inode; + priv = (FAR struct nxcon_state_s *)inode->i_private; + DEBUGASSERT(priv); + + /* Verify that the driver is opened for write-only access */ + +#ifndef CONFIG_NXCONSOLE_NXKBDIN + if ((filep->f_oflags & O_RDOK) != 0) + { + gdbg("ERROR: Attempted open with read access\n"); + return -EACCES; + } +#endif + + /* Assign the driver structure to the file */ + + filep->f_priv = priv; + return OK; +} + +/**************************************************************************** + * Name: nxcon_write + ****************************************************************************/ + +static ssize_t nxcon_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + FAR struct nxcon_state_s *priv; + enum nxcon_vt100state_e state; + ssize_t remaining; + char ch; + int ret; + + /* Recover our private state structure */ + + DEBUGASSERT(filep && filep->f_priv); + priv = (FAR struct nxcon_state_s *)filep->f_priv; + + /* Get exclusive access */ + + ret = nxcon_semwait(priv); + if (ret < 0) + { + return ret; + } + + /* Hide the cursor while we update the display */ + + nxcon_hidecursor(priv); + + /* Loop writing each character to the display */ + + for (remaining = (ssize_t)buflen; remaining > 0; remaining--) + { + /* Get the next character from the user buffer */ + + ch = *buffer++; + + /* Check if this character is part of a VT100 escape sequence */ + + do + { + /* Is the character part of a VT100 escape sequnce? */ + + state = nxcon_vt100(priv, ch); + switch (state) + { + /* Character is not part of a VT100 escape sequence (and no + * characters are buffer. + */ + + default: + case VT100_NOT_CONSUMED: + { + /* We can output the character to the window */ + + nxcon_putc(priv, (uint8_t)ch); + } + break; + + /* The full VT100 escape sequence was processed (and the new + * character was consumed) + */ + + case VT100_PROCESSED: + + /* Character was consumed as part of the VT100 escape processing + * (but the escape sequence is still incomplete. + */ + + case VT100_CONSUMED: + { + /* Do nothing... the VT100 logic owns the character */ + } + break; + + /* Invalid/unsupported character in escape sequence */ + + case VT100_ABORT: + { + int i; + + /* Add the first unhandled character to the window */ + + nxcon_putc(priv, (uint8_t)priv->seq[0]); + + /* Move all buffer characters down one */ + + for (i = 1; i < priv->nseq; i++) + { + priv->seq[i-1] = priv->seq[i]; + } + priv->nseq--; + + /* Then loop again and check if what remains is part of a + * VT100 escape sequence. We could speed this up by + * checking if priv->seq[0] == ASCII_ESC. + */ + } + break; + } + } + while (state == VT100_ABORT); + } + + /* Show the cursor at its new position */ + + nxcon_showcursor(priv); + nxcon_sempost(priv); + return (ssize_t)buflen; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + diff --git a/nuttx/graphics/nxconsole/nxcon_font.c b/nuttx/graphics/nxconsole/nxcon_font.c new file mode 100644 index 0000000000..2bdf21cf6c --- /dev/null +++ b/nuttx/graphics/nxconsole/nxcon_font.c @@ -0,0 +1,651 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nxcon_font.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "nxcon_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Select renderer -- Some additional logic would be required to support + * pixel depths that are not directly addressable (1,2,4, and 24). + */ + +#if CONFIG_NXCONSOLE_BPP == 1 +# define RENDERER nxf_convert_1bpp +#elif CONFIG_NXCONSOLE_BPP == 2 +# define RENDERER nxf_convert_2bpp +#elif CONFIG_NXCONSOLE_BPP == 4 +# define RENDERER nxf_convert_4bpp +#elif CONFIG_NXCONSOLE_BPP == 8 +# define RENDERER nxf_convert_8bpp +#elif CONFIG_NXCONSOLE_BPP == 16 +# define RENDERER nxf_convert_16bpp +#elif CONFIG_NXCONSOLE_BPP == 24 +# define RENDERER nxf_convert_24bpp +#elif CONFIG_NXCONSOLE_BPP == 32 +# define RENDERER nxf_convert_32bpp +#else +# error "Unsupported CONFIG_NXCONSOLE_BPP" +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_freeglyph + ****************************************************************************/ + +static void nxcon_freeglyph(FAR struct nxcon_glyph_s *glyph) +{ + if (glyph->bitmap) + { + kfree(glyph->bitmap); + } + memset(glyph, 0, sizeof(struct nxcon_glyph_s)); +} + +/**************************************************************************** + * Name: nxcon_allocglyph + ****************************************************************************/ + +static inline FAR struct nxcon_glyph_s * +nxcon_allocglyph(FAR struct nxcon_state_s *priv) +{ + FAR struct nxcon_glyph_s *glyph = NULL; + FAR struct nxcon_glyph_s *luglyph = NULL; + uint8_t luusecnt; + int i; + + /* Search through the glyph cache looking for an unused glyph. Also, keep + * track of the least used glyph as well. We need that if we have to replace + * a glyph in the cache. + */ + + for (i = 0; i < priv->maxglyphs; i++) + { + /* Is this glyph in use? */ + + glyph = &priv->glyph[i]; + if (!glyph->usecnt) + { + /* No.. return this glyph with a use count of one */ + + glyph->usecnt = 1; + return glyph; + } + + /* Yes.. check for the least recently used */ + + if (!luglyph || glyph->usecnt < luglyph->usecnt) + { + luglyph = glyph; + } + } + + /* If we get here, the glyph cache is full. We replace the least used + * glyph with the one we need now. (luglyph can't be NULL). + */ + + luusecnt = luglyph->usecnt; + nxcon_freeglyph(luglyph); + + /* But lets decrement all of the usecnts so that the new one one be so + * far behind in the counts as the older ones. + */ + + if (luusecnt > 1) + { + uint8_t decr = luusecnt - 1; + + for (i = 0; i < priv->maxglyphs; i++) + { + /* Is this glyph in use? */ + + glyph = &priv->glyph[i]; + if (glyph->usecnt > decr) + { + glyph->usecnt -= decr; + } + } + } + + /* Then return the least used glyph */ + + luglyph->usecnt = 1; + return luglyph; +} + +/**************************************************************************** + * Name: nxcon_findglyph + ****************************************************************************/ + +static FAR struct nxcon_glyph_s * +nxcon_findglyph(FAR struct nxcon_state_s *priv, uint8_t ch) +{ + int i; + + /* First, try to find the glyph in the cache of pre-rendered glyphs */ + + for (i = 0; i < priv->maxglyphs; i++) + { + FAR struct nxcon_glyph_s *glyph = &priv->glyph[i]; + if (glyph->usecnt > 0 && glyph->code == ch) + { + /* Increment the use count (unless it is already at the max) */ + + if (glyph->usecnt < MAX_USECNT) + { + glyph->usecnt++; + } + + /* And return the glyph that we found */ + + return glyph; + } + } + return NULL; +} + +/**************************************************************************** + * Name: nxcon_renderglyph + ****************************************************************************/ + +static inline FAR struct nxcon_glyph_s * +nxcon_renderglyph(FAR struct nxcon_state_s *priv, + FAR const struct nx_fontbitmap_s *fbm, uint8_t ch) +{ + FAR struct nxcon_glyph_s *glyph = NULL; + FAR nxgl_mxpixel_t *ptr; +#if CONFIG_NXCONSOLE_BPP < 8 + nxgl_mxpixel_t pixel; +#endif + int bmsize; + int row; + int col; + int ret; + + /* Allocate the glyph (always succeeds) */ + + glyph = nxcon_allocglyph(priv); + glyph->code = ch; + + /* Get the dimensions of the glyph */ + + glyph->width = fbm->metric.width + fbm->metric.xoffset; + glyph->height = fbm->metric.height + fbm->metric.yoffset; + + /* Get the physical width of the glyph in bytes */ + + glyph->stride = (glyph->width * CONFIG_NXCONSOLE_BPP + 7) / 8; + + /* Allocate memory to hold the glyph with its offsets */ + + bmsize = glyph->stride * glyph->height; + glyph->bitmap = (FAR uint8_t *)kmalloc(bmsize); + + if (glyph->bitmap) + { + /* Initialize the glyph memory to the background color using the + * hard-coded bits-per-pixel (BPP). + * + * TODO: The rest of NX is configured to support multiple devices + * with differing BPP. They logic should be extended to support + * differing BPP's as well. + */ + +#if CONFIG_NXCONSOLE_BPP < 8 + pixel = priv->wcolor[0]; + +# if CONFIG_NXCONSOLE_BPP == 1 + + /* Pack 1-bit pixels into a 2-bits */ + + pixel &= 0x01; + pixel = (pixel) << 1 | pixel; + +# endif +# if CONFIG_NXCONSOLE_BPP < 4 + + /* Pack 2-bit pixels into a nibble */ + + pixel &= 0x03; + pixel = (pixel) << 2 | pixel; + +# endif + + /* Pack 4-bit nibbles into a byte */ + + pixel &= 0x0f; + pixel = (pixel) << 4 | pixel; + + ptr = (FAR nxgl_mxpixel_t *)glyph->bitmap; + for (row = 0; row < glyph->height; row++) + { + for (col = 0; col < glyph->stride; col++) + { + /* Transfer the packed bytes into the buffer */ + + *ptr++ = pixel; + } + } + +#elif CONFIG_NXCONSOLE_BPP == 24 +# error "Additional logic is needed here for 24bpp support" + +#else /* CONFIG_NXCONSOLE_BPP = {8,16,32} */ + + ptr = (FAR nxgl_mxpixel_t *)glyph->bitmap; + for (row = 0; row < glyph->height; row++) + { + /* Just copy the color value into the glyph memory */ + + for (col = 0; col < glyph->width; col++) + { + *ptr++ = priv->wndo.wcolor[0]; + } + } +#endif + + /* Then render the glyph into the allocated memory */ + + ret = RENDERER((FAR nxgl_mxpixel_t*)glyph->bitmap, + glyph->height, glyph->width, glyph->stride, + fbm, priv->wndo.fcolor[0]); + if (ret < 0) + { + /* Actually, the RENDERER never returns a failure */ + + gdbg("nxcon_renderglyph: RENDERER failed\n"); + nxcon_freeglyph(glyph); + glyph = NULL; + } + } + + return glyph; +} + +/**************************************************************************** + * Name: nxcon_fontsize + ****************************************************************************/ + +static int nxcon_fontsize(NXHANDLE hfont, uint8_t ch, FAR struct nxgl_size_s *size) +{ + FAR const struct nx_fontbitmap_s *fbm; + + /* No, it is not cached... Does the code map to a font? */ + + fbm = nxf_getbitmap(hfont, ch); + if (fbm) + { + /* Yes.. return the font size */ + + size->w = fbm->metric.width + fbm->metric.xoffset; + size->h = fbm->metric.height + fbm->metric.yoffset; + return OK; + } + + return ERROR; +} + +/**************************************************************************** + * Name: nxcon_getglyph + ****************************************************************************/ + +static FAR struct nxcon_glyph_s * +nxcon_getglyph(NXHANDLE hfont, FAR struct nxcon_state_s *priv, uint8_t ch) +{ + FAR struct nxcon_glyph_s *glyph; + FAR const struct nx_fontbitmap_s *fbm; + + /* First, try to find the glyph in the cache of pre-rendered glyphs */ + + glyph = nxcon_findglyph(priv, ch); + if (glyph) + { + /* We found it in the cache .. return the cached glyph */ + + return glyph; + } + + /* No, it is not cached... Does the code map to a font? */ + + fbm = nxf_getbitmap(hfont, ch); + if (fbm) + { + /* Yes.. render the glyph */ + + glyph = nxcon_renderglyph(priv, fbm, ch); + } + + return glyph; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_addchar + * + * Description: + * This is part of the nxcon_putc logic. It creates and positions a + * the character and renders (or re-uses) a glyph for font. + * + ****************************************************************************/ + +FAR const struct nxcon_bitmap_s * +nxcon_addchar(NXHANDLE hfont, FAR struct nxcon_state_s *priv, uint8_t ch) +{ + FAR struct nxcon_bitmap_s *bm = NULL; + FAR struct nxcon_glyph_s *glyph; + + /* Is there space for another character on the display? */ + + if (priv->nchars < priv->maxchars) + { + /* Yes, setup the bitmap information */ + + bm = &priv->bm[priv->nchars]; + bm->code = ch; + bm->flags = 0; + bm->pos.x = priv->fpos.x; + bm->pos.y = priv->fpos.y; + + /* Find (or create) the matching glyph */ + + glyph = nxcon_getglyph(hfont, priv, ch); + if (!glyph) + { + /* No, there is no font for this code. Just mark this as a space. */ + + bm->flags |= BMFLAGS_NOGLYPH; + + /* Set up the next character position */ + + priv->fpos.x += priv->spwidth; + } + else + { + /* Set up the next character position */ + + priv->fpos.x += glyph->width; + } + + /* Success.. increment nchars to retain this character */ + + priv->nchars++; + } + + return bm; +} + +/**************************************************************************** + * Name: nxcon_hidechar + * + * Description: + * Erase a character from the window. + * + ****************************************************************************/ +int nxcon_hidechar(FAR struct nxcon_state_s *priv, + FAR const struct nxcon_bitmap_s *bm) +{ + struct nxgl_rect_s bounds; + struct nxgl_size_s fsize; + int ret; + + /* Get the size of the font glyph. If nxcon_fontsize, then the + * character will have been rendered as a space, and no display + * modification is required (not an error). + */ + + ret = nxcon_fontsize(priv->font, bm->code, &fsize); + if (ret < 0) + { + /* It was rendered as a space. */ + + return OK; + } + + /* Construct a bounding box for the glyph */ + + bounds.pt1.x = bm->pos.x; + bounds.pt1.y = bm->pos.y; + bounds.pt2.x = bm->pos.x + fsize.w - 1; + bounds.pt2.y = bm->pos.y + fsize.h - 1; + + /* Fill the bitmap region with the background color, erasing the + * character from the display. NOTE: This region might actually + * be obscured... NX will handle that case. + */ + + return priv->ops->fill(priv, &bounds, priv->wndo.wcolor); +} + +/**************************************************************************** + * Name: nxcon_backspace + * + * Description: + * Remove the last character from the window. + * + ****************************************************************************/ + +int nxcon_backspace(FAR struct nxcon_state_s *priv) +{ + FAR struct nxcon_bitmap_s *bm; + int ndx; + int ret = -ENOENT; + + /* Is there a character on the display? */ + + if (priv->nchars > 0) + { + /* Yes.. Get the index to the last bitmap on the display */ + + ndx = priv->nchars - 1; + bm = &priv->bm[ndx]; + + /* Erase the character from the display */ + + ret = nxcon_hidechar(priv, bm); + + /* The current position to the location where the last character was */ + + priv->fpos.x = bm->pos.x; + priv->fpos.y = bm->pos.y; + + /* Decrement nchars to discard this character */ + + priv->nchars = ndx; + } + + return ret; +} + +/**************************************************************************** + * Name: nxcon_home + * + * Description: + * Set the next character position to the top-left corner of the display. + * + ****************************************************************************/ + +void nxcon_home(FAR struct nxcon_state_s *priv) +{ + /* The first character is one space from the left */ + + priv->fpos.x = priv->spwidth; + + /* And CONFIG_NXCONSOLE_LINESEPARATION lines from the top */ + + priv->fpos.y = CONFIG_NXCONSOLE_LINESEPARATION; +} + +/**************************************************************************** + * Name: nxcon_newline + * + * Description: + * Set the next character position to the beginning of the next line. + * + ****************************************************************************/ + +void nxcon_newline(FAR struct nxcon_state_s *priv) +{ + /* Carriage return: The first character is one space from the left */ + + priv->fpos.x = priv->spwidth; + + /* Linefeed: Down the max font height + CONFIG_NXCONSOLE_LINESEPARATION */ + + priv->fpos.y += (priv->fheight + CONFIG_NXCONSOLE_LINESEPARATION); +} + +/**************************************************************************** + * Name: nxcon_fillchar + * + * Description: + * This implements the character display. It is part of the nxcon_putc + * operation but may also be used when redrawing an existing display. + * + ****************************************************************************/ + +void nxcon_fillchar(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + FAR const struct nxcon_bitmap_s *bm) +{ + FAR struct nxcon_glyph_s *glyph; + struct nxgl_rect_s bounds; + struct nxgl_rect_s intersection; + struct nxgl_size_s fsize; + int ret; + + /* Handle the special case of spaces which have no glyph bitmap */ + + if (BM_ISSPACE(bm)) + { + return; + } + + /* Get the size of the font glyph (which may not have been created yet) */ + + ret = nxcon_fontsize(priv->font, bm->code, &fsize); + if (ret < 0) + { + /* This would mean that there is no bitmap for the character code and + * that the font would be rendered as a space. But this case should + * never happen here because the BM_ISSPACE() should have already + * found all such cases. + */ + + return; + } + + /* Construct a bounding box for the glyph */ + + bounds.pt1.x = bm->pos.x; + bounds.pt1.y = bm->pos.y; + bounds.pt2.x = bm->pos.x + fsize.w - 1; + bounds.pt2.y = bm->pos.y + fsize.h - 1; + + /* Should this also be clipped to a region in the window? */ + + if (rect) + { + /* Get the intersection of the redraw region and the character bitmap */ + + nxgl_rectintersect(&intersection, rect, &bounds); + } + else + { + /* The intersection is the whole glyph */ + + nxgl_rectcopy(&intersection, &bounds); + } + + /* Check for empty intersections */ + + if (!nxgl_nullrect(&intersection)) + { + FAR const void *src; + + /* Find (or create) the glyph that goes with this font */ + + glyph = nxcon_getglyph(priv->font, priv, bm->code); + if (!glyph) + { + /* Shouldn't happen */ + + return; + } + + /* Blit the font bitmap into the window */ + + src = (FAR const void *)glyph->bitmap; + ret = priv->ops->bitmap(priv, &intersection, &src, + &bm->pos, (unsigned int)glyph->stride); + DEBUGASSERT(ret >= 0); + } +} + diff --git a/nuttx/graphics/nxconsole/nxcon_internal.h b/nuttx/graphics/nxconsole/nxcon_internal.h new file mode 100644 index 0000000000..dc976a6620 --- /dev/null +++ b/nuttx/graphics/nxconsole/nxcon_internal.h @@ -0,0 +1,254 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nxcon_internal.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXCONSOLE_NXCON_INTERNAL_H +#define __GRAPHICS_NXCONSOLE_NXCON_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* NxConsole Definitions ****************************************************/ +/* Bitmap flags */ + +#define BMFLAGS_NOGLYPH (1 << 0) /* No glyph available, use space */ +#define BM_ISSPACE(bm) (((bm)->flags & BMFLAGS_NOGLYPH) != 0) + +/* Sizes and maximums */ + +#define MAX_USECNT 255 /* Limit to range of a uint8_t */ + +/* Device path formats */ + +#define NX_DEVNAME_FORMAT "/dev/nxcon%d" +#define NX_DEVNAME_SIZE 16 + +/* Semaphore protection */ + +#define NO_HOLDER (pid_t)-1 + +/* VT100 escape sequence processing */ + +#define VT100_MAX_SEQUENCE 3 + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* Identifies the state of the VT100 escape sequence processing */ + +enum nxcon_vt100state_e +{ + VT100_NOT_CONSUMED = 0, /* Character is not part of a VT100 escape sequence */ + VT100_CONSUMED, /* Character was consumed as part of the VT100 escape processing */ + VT100_PROCESSED, /* The full VT100 escape sequence was processed */ + VT100_ABORT /* Invalid/unsupported character in buffered escape sequence */ +}; + +/* Describes on set of console window callbacks */ + +struct nxcon_state_s; +struct nxcon_operations_s +{ + int (*fill)(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t wcolor[CONFIG_NX_NPLANES]); +#ifndef CONFIG_NX_WRITEONLY + int (*move)(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset); +#endif + int (*bitmap)(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, + unsigned int stride); +}; + +/* Describes one cached glyph bitmap */ + +struct nxcon_glyph_s +{ + uint8_t code; /* Character code */ + uint8_t height; /* Height of this glyph (in rows) */ + uint8_t width; /* Width of this glyph (in pixels) */ + uint8_t stride; /* Width of the glyph row (in bytes) */ + uint8_t usecnt; /* Use count */ + FAR uint8_t *bitmap; /* Allocated bitmap memory */ +}; + +/* Describes on character on the display */ + +struct nxcon_bitmap_s +{ + uint8_t code; /* Character code */ + uint8_t flags; /* See BMFLAGS_* */ + struct nxgl_point_s pos; /* Character position */ +}; + +/* Describes the state of one NX console driver*/ + +struct nxcon_state_s +{ + FAR const struct nxcon_operations_s *ops; /* Window operations */ + FAR void *handle; /* The window handle */ + FAR struct nxcon_window_s wndo; /* Describes the window and font */ + NXHANDLE font; /* The current font handle */ + sem_t exclsem; /* Forces mutually exclusive access */ +#ifdef CONFIG_DEBUG + pid_t holder; /* Deadlock avoidance */ +#endif + uint8_t minor; /* Device minor number */ + + /* Text output support */ + + uint8_t fheight; /* Max height of a font in pixels */ + uint8_t fwidth; /* Max width of a font in pixels */ + uint8_t spwidth; /* The width of a space */ + uint8_t maxglyphs; /* Size of the glyph[] array */ + + uint16_t maxchars; /* Size of the bm[] array */ + uint16_t nchars; /* Number of chars in the bm[] array */ + + struct nxgl_point_s fpos; /* Next display position */ + + /* VT100 escape sequence processing */ + + char seq[VT100_MAX_SEQUENCE]; /* Buffered characters */ + uint8_t nseq; /* Number of buffered characters */ + + /* Font cache data storage */ + + struct nxcon_bitmap_s cursor; + struct nxcon_bitmap_s bm[CONFIG_NXCONSOLE_MXCHARS]; + + /* Glyph cache data storage */ + + struct nxcon_glyph_s glyph[CONFIG_NXCONSOLE_CACHESIZE]; + + /* Keyboard input support */ + +#ifdef CONFIG_NXCONSOLE_NXKBDIN + sem_t waitsem; /* Supports waiting for input data */ + uint8_t nwaiters; /* Number of threads waiting for data */ + uint8_t head; /* rxbuffer head/input index */ + uint8_t tail; /* rxbuffer tail/output index */ + + uint8_t rxbuffer[CONFIG_NXCONSOLE_KBDBUFSIZE]; + + /* The following is a list if poll structures of threads waiting for + * driver events. The 'struct pollfd' reference for each open is also + * retained in the f_priv field of the 'struct file'. + */ + +#ifndef CONFIG_DISABLE_POLL + struct pollfd *fds[CONFIG_RAMLOG_NPOLLWAITERS]; +#endif +#endif /* CONFIG_NXCONSOLE_NXKBDIN */ +}; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* This is the common NX driver file operations */ + +extern const struct file_operations g_nxcon_drvrops; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +/* Semaphore helpers */ + +#ifdef CONFIG_DEBUG +int nxcon_semwait(FAR struct nxcon_state_s *priv); +int nxcon_sempost(FAR struct nxcon_state_s *priv); +#else +# define nxcon_semwait(p) sem_wait(&p->exclsem) +# define nxcon_sempost(p) sem_post(&p->exclsem) +#endif + +/* Common device registration */ + +FAR struct nxcon_state_s *nxcon_register(NXCONSOLE handle, + FAR struct nxcon_window_s *wndo, FAR const struct nxcon_operations_s *ops, + int minor); + +#ifdef CONFIG_NXCONSOLE_NXKBDIN +ssize_t nxcon_read(FAR struct file *filep, FAR char *buffer, size_t len); +#ifndef CONFIG_DISABLE_POLL +int nxcon_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup); +#endif +#endif + +/* VT100 Terminal emulation */ + +enum nxcon_vt100state_e nxcon_vt100(FAR struct nxcon_state_s *priv, char ch); + +/* Generic text display helpers */ + +void nxcon_home(FAR struct nxcon_state_s *priv); +void nxcon_newline(FAR struct nxcon_state_s *priv); +FAR const struct nxcon_bitmap_s *nxcon_addchar(NXHANDLE hfont, + FAR struct nxcon_state_s *priv, uint8_t ch); +int nxcon_hidechar(FAR struct nxcon_state_s *priv, + FAR const struct nxcon_bitmap_s *bm); +int nxcon_backspace(FAR struct nxcon_state_s *priv); +void nxcon_fillchar(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, FAR const struct nxcon_bitmap_s *bm); + +void nxcon_putc(FAR struct nxcon_state_s *priv, uint8_t ch); +void nxcon_showcursor(FAR struct nxcon_state_s *priv); +void nxcon_hidecursor(FAR struct nxcon_state_s *priv); + +/* Scrolling support */ + +void nxcon_scroll(FAR struct nxcon_state_s *priv, int scrollheight); + +#endif /* __GRAPHICS_NXCONSOLE_NXCON_INTERNAL_H */ diff --git a/nuttx/graphics/nxconsole/nxcon_kbdin.c b/nuttx/graphics/nxconsole/nxcon_kbdin.c new file mode 100644 index 0000000000..f4b116c467 --- /dev/null +++ b/nuttx/graphics/nxconsole/nxcon_kbdin.c @@ -0,0 +1,489 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nxcon_kbdin.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "nxcon_internal.h" + +#ifdef CONFIG_NXCONSOLE_NXKBDIN + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_pollnotify + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static void nxcon_pollnotify(FAR struct nxcon_state_s *priv, pollevent_t eventset) +{ + FAR struct pollfd *fds; + irqstate_t flags; + int i; + + /* This function may be called from an interrupt handler */ + + for (i = 0; i < CONFIG_NXCONSOLE_NPOLLWAITERS; i++) + { + flags = irqsave(); + fds = priv->fds[i]; + if (fds) + { + fds->revents |= (fds->events & eventset); + if (fds->revents != 0) + { + sem_post(fds->sem); + } + } + irqrestore(flags); + } +} +#else +# define nxcon_pollnotify(priv,event) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_read + * + * Description: + * The optional NxConsole read method + * + ****************************************************************************/ + +ssize_t nxcon_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + FAR struct nxcon_state_s *priv; + ssize_t nread; + char ch; + int ret; + + /* Recover our private state structure */ + + DEBUGASSERT(filep && filep->f_priv); + priv = (FAR struct nxcon_state_s *)filep->f_priv; + + /* Get exclusive access to the driver structure */ + + ret = nxcon_semwait(priv); + if (ret < 0) + { + gdbg("ERROR: nxcon_semwait failed\n"); + return ret; + } + + /* Loop until something is read */ + + for (nread = 0; nread < len; ) + { + /* Get the next byte from the buffer */ + + if (priv->head == priv->tail) + { + /* The circular buffer is empty. Did we read anything? */ + + if (nread > 0) + { + /* Yes.. break out to return what we have. */ + + break; + } + + /* If the driver was opened with O_NONBLOCK option, then don't wait. + * Just return EGAIN. + */ + + if (filep->f_oflags & O_NONBLOCK) + { + nread = -EAGAIN; + break; + } + + /* Otherwise, wait for something to be written to the circular + * buffer. Increment the number of waiters so that the nxcon_write() + * will not that it needs to post the semaphore to wake us up. + */ + + sched_lock(); + priv->nwaiters++; + nxcon_sempost(priv); + + /* We may now be pre-empted! But that should be okay because we + * have already incremented nwaiters. Pre-emption is disabled + * but will be re-enabled while we are waiting. + */ + + ret = sem_wait(&priv->waitsem); + + /* Pre-emption will be disabled when we return. So the decrementing + * nwaiters here is safe. + */ + + priv->nwaiters--; + sched_unlock(); + + /* Did we successfully get the waitsem? */ + + if (ret >= 0) + { + /* Yes... then retake the mutual exclusion semaphore */ + + ret = nxcon_semwait(priv); + } + + /* Was the semaphore wait successful? Did we successful re-take the + * mutual exclusion semaphore? + */ + + if (ret < 0) + { + /* No.. One of the two sem_wait's failed. */ + + int errval = errno; + + gdbg("ERROR: nxcon_semwait failed\n"); + + /* Were we awakened by a signal? Did we read anything before + * we received the signal? + */ + + if (errval != EINTR || nread >= 0) + { + /* Yes.. return the error. */ + + nread = -errval; + } + + /* Break out to return what we have. Note, we can't exactly + * "break" out because whichever error occurred, we do not hold + * the exclusion semaphore. + */ + + goto errout_without_sem; + } + } + else + { + /* The circular buffer is not empty, get the next byte from the + * tail index. + */ + + ch = priv->rxbuffer[priv->tail]; + + /* Increment the tail index and re-enable interrupts */ + + if (++priv->tail >= CONFIG_NXCONSOLE_KBDBUFSIZE) + { + priv->tail = 0; + } + + /* Add the character to the user buffer */ + + buffer[nread] = ch; + nread++; + } + } + + /* Relinquish the mutual exclusion semaphore */ + + nxcon_sempost(priv); + + /* Notify all poll/select waiters that they can write to the FIFO */ + +errout_without_sem: + +#ifndef CONFIG_DISABLE_POLL + if (nread > 0) + { + nxcon_pollnotify(priv, POLLOUT); + } +#endif + + /* Return the number of characters actually read */ + + return nread; +} + +/**************************************************************************** + * Name: nxcon_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +int nxcon_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct nxcon_state_s *priv; + pollevent_t eventset; + int ndx; + int ret; + int i; + + /* Some sanity checking */ + + DEBUGASSERT(inode && inode->i_private); + priv = inode->i_private; + + /* Get exclusive access to the driver structure */ + + ret = nxcon_semwait(priv); + if (ret < 0) + { + gdbg("ERROR: nxcon_semwait failed\n"); + return ret; + } + + /* Are we setting up the poll? Or tearing it down? */ + + if (setup) + { + /* This is a request to set up the poll. Find an available + * slot for the poll structure reference + */ + + for (i = 0; i < CONFIG_NXCONSOLE_NPOLLWAITERS; i++) + { + /* Find an available slot */ + + if (!priv->fds[i]) + { + /* Bind the poll structure and this slot */ + + priv->fds[i] = fds; + fds->priv = &priv->fds[i]; + break; + } + } + + if (i >= CONFIG_NXCONSOLE_NPOLLWAITERS) + { + gdbg("ERROR: Too many poll waiters\n"); + + fds->priv = NULL; + ret = -EBUSY; + goto errout; + } + + /* Should immediately notify on any of the requested events? + * This driver is always available for transmission. + */ + + eventset = POLLOUT; + + /* Check if the receive buffer is empty */ + + if (priv->head != priv->tail) + { + eventset |= POLLIN; + } + + if (eventset) + { + nxcon_pollnotify(priv, eventset); + } + + } + else if (fds->priv) + { + /* This is a request to tear down the poll. */ + + struct pollfd **slot = (struct pollfd **)fds->priv; + +#ifdef CONFIG_DEBUG + if (!slot) + { + gdbg("ERROR: No slot\n"); + + ret = -EIO; + goto errout; + } +#endif + + /* Remove all memory of the poll setup */ + + *slot = NULL; + fds->priv = NULL; + } + +errout: + nxcon_sempost(priv); + return ret; +} +#endif + +/**************************************************************************** + * Name: nxcon_kbdin + * + * Description: + * This function should be driven by the window kbdin callback function + * (see nx.h). When the NxConsole is the top window and keyboard input is + * received on the top window, that window callback should be directed to + * this function. This function will buffer the keyboard data and may + * it available to the NxConsole as stdin. + * + * If CONFIG_NXCONSOLE_NXKBDIN is not selected, then the NxConsole will + * receive its input from stdin (/dev/console). This works great but + * cannot be shared between different windows. Chaos will ensue if you + * try to support multiple NxConsole windows without CONFIG_NXCONSOLE_NXKBDIN + * + * Input Parameters: + * handle - A handle previously returned by nx_register, nxtk_register, or + * nxtool_register. + * buffer - The array of characters + * buflen - The number of characters that are available in buffer[] + * + * Returned Value: + * None + * + ****************************************************************************/ + +void nxcon_kbdin(NXCONSOLE handle, FAR const uint8_t *buffer, uint8_t buflen) +{ + FAR struct nxcon_state_s *priv; + ssize_t nwritten; + int nexthead; + char ch; + int ret; + + gvdbg("buflen=%d\n"); + DEBUGASSERT(handle); + + /* Get the reference to the driver structure from the handle */ + + priv = (FAR struct nxcon_state_s *)handle; + + /* Get exclusive access to the driver structure */ + + ret = nxcon_semwait(priv); + if (ret < 0) + { + gdbg("ERROR: nxcon_semwait failed\n"); + return; + } + + /* Loop until all of the bytes have been written. This function may be + * called from an interrupt handler! Semaphores cannot be used! + * + * The write logic only needs to modify the head index. Therefore, + * there is a difference in the way that head and tail are protected: + * tail is protected with a semaphore; tail is protected by disabling + * interrupts. + */ + + for (nwritten = 0; nwritten < buflen; nwritten++) + { + /* Add the next character */ + + ch = buffer[nwritten]; + + /* Calculate the write index AFTER the next byte is add to the ring + * buffer + */ + + nexthead = priv->head + 1; + if (nexthead >= CONFIG_NXCONSOLE_KBDBUFSIZE) + { + nexthead = 0; + } + + /* Would the next write overflow the circular buffer? */ + + if (nexthead == priv->tail) + { + /* Yes... Return an indication that nothing was saved in the buffer. */ + + gdbg("ERROR: Keyboard data overrun\n"); + break; + } + + /* No... copy the byte */ + + priv->rxbuffer[priv->head] = ch; + priv->head = nexthead; + } + + /* Was anything written? */ + + if (nwritten > 0) + { + int i; + + /* Are there threads waiting for read data? */ + + sched_lock(); + for (i = 0; i < priv->nwaiters; i++) + { + /* Yes.. Notify all of the waiting readers that more data is available */ + + sem_post(&priv->waitsem); + } + + /* Notify all poll/select waiters that they can write to the FIFO */ + +#ifndef CONFIG_DISABLE_POLL + nxcon_pollnotify(priv, POLLIN); +#endif + sched_unlock(); + } + + nxcon_sempost(priv); +} + +#endif /* CONFIG_NXCONSOLE_NXKBDIN */ diff --git a/nuttx/graphics/nxconsole/nxcon_putc.c b/nuttx/graphics/nxconsole/nxcon_putc.c new file mode 100644 index 0000000000..d51d79c794 --- /dev/null +++ b/nuttx/graphics/nxconsole/nxcon_putc.c @@ -0,0 +1,203 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nxcon_putc.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "nxcon_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_putc + * + * Description: + * Render the specified character at the current display position. + * + ****************************************************************************/ + +void nxcon_putc(FAR struct nxcon_state_s *priv, uint8_t ch) +{ + FAR const struct nxcon_bitmap_s *bm; + int lineheight; + + /* Ignore carriage returns */ + + if (ch == '\r') + { + return; + } + + /* Handle backspace (treating both BS and DEL as backspace) */ + + if (ch == ASCII_BS || ch == ASCII_DEL) + { + nxcon_backspace(priv); + return; + } + + /* Will another character fit on this line? */ + + if (priv->fpos.x + priv->fwidth > priv->wndo.wsize.w) + { +#ifndef CONFIG_NXCONSOLE_NOWRAP + /* No.. move to the next line */ + + nxcon_newline(priv); + + /* If we were about to output a newline character, then don't */ + + if (ch == '\n') + { + return; + } +#else + /* No.. Ignore all further characters until a newline is encountered */ + + if (ch != '\n') + { + return; + } +#endif + } + + /* If it is a newline character, then just perform the logical newline + * operation. + */ + + if (ch == '\n') + { + nxcon_newline(priv); + return; + } + + /* Check if we need to scroll up */ + + lineheight = (priv->fheight + CONFIG_NXCONSOLE_LINESEPARATION); + while (priv->fpos.y >= priv->wndo.wsize.h - lineheight) + { + nxcon_scroll(priv, lineheight); + } + + /* Find the glyph associated with the character and render it onto the + * display. + */ + + bm = nxcon_addchar(priv->font, priv, ch); + if (bm) + { + nxcon_fillchar(priv, NULL, bm); + } +} + +/**************************************************************************** + * Name: nxcon_showcursor + * + * Description: + * Render the cursor character at the current display position. + * + ****************************************************************************/ + +void nxcon_showcursor(FAR struct nxcon_state_s *priv) +{ + int lineheight; + + /* Will another character fit on this line? */ + + if (priv->fpos.x + priv->fwidth > priv->wndo.wsize.w) + { +#ifndef CONFIG_NXCONSOLE_NOWRAP + /* No.. move to the next line */ + + nxcon_newline(priv); +#else + return; +#endif + } + + /* Check if we need to scroll up */ + + lineheight = (priv->fheight + CONFIG_NXCONSOLE_LINESEPARATION); + while (priv->fpos.y >= priv->wndo.wsize.h - lineheight) + { + nxcon_scroll(priv, lineheight); + } + + /* Render the cursor glyph onto the display. */ + + priv->cursor.pos.x = priv->fpos.x; + priv->cursor.pos.y = priv->fpos.y; + nxcon_fillchar(priv, NULL, &priv->cursor); +} + +/**************************************************************************** + * Name: nxcon_hidecursor + * + * Description: + * Render the cursor cursor character from the display. + * + ****************************************************************************/ + +void nxcon_hidecursor(FAR struct nxcon_state_s *priv) +{ + (void)nxcon_hidechar(priv, &priv->cursor); +} diff --git a/nuttx/graphics/nxconsole/nxcon_redraw.c b/nuttx/graphics/nxconsole/nxcon_redraw.c new file mode 100755 index 0000000000..05f0a47f89 --- /dev/null +++ b/nuttx/graphics/nxconsole/nxcon_redraw.c @@ -0,0 +1,152 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nxcon_bkgd.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "nxcon_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_redraw + * + * Description: + * Re-draw a portion of the NX console. This function should be called + * from the appropriate window callback logic. + * + * Input Parameters: + * handle - A handle previously returned by nx_register, nxtk_register, or + * nxtool_register. + * rect - The rectangle that needs to be re-drawn (in window relative + * coordinates) + * more - true: More re-draw requests will follow + * + * Returned Value: + * None + * + ****************************************************************************/ + +void nxcon_redraw(NXCONSOLE handle, FAR const struct nxgl_rect_s *rect, bool more) +{ + FAR struct nxcon_state_s *priv; + int ret; + int i; + + DEBUGASSERT(handle && rect); + gvdbg("rect={(%d,%d),(%d,%d)} more=%s\n", + rect->pt1.x, rect->pt1.y, rect->pt2.x, rect->pt2.y, + more ? "true" : "false"); + + /* Recover our private state structure */ + + priv = (FAR struct nxcon_state_s *)handle; + + /* Get exclusive access to the state structure */ + + do + { + ret = nxcon_semwait(priv); + + /* Check for errors */ + + if (ret < 0) + { + /* The only expected error is if the wait failed because of it + * was interrupted by a signal. + */ + + DEBUGASSERT(errno == EINTR); + } + } + while (ret < 0); + + /* Fill the rectangular region with the window background color */ + + ret = priv->ops->fill(priv, rect, priv->wndo.wcolor); + if (ret < 0) + { + gdbg("fill failed: %d\n", errno); + } + + /* Then redraw each character on the display (Only the characters within + * the rectangle will actually be redrawn). + */ + + for (i = 0; i < priv->nchars; i++) + { + nxcon_fillchar(priv, rect, &priv->bm[i]); + } + ret = nxcon_sempost(priv); +} diff --git a/nuttx/graphics/nxconsole/nxcon_register.c b/nuttx/graphics/nxconsole/nxcon_register.c new file mode 100644 index 0000000000..cadda73941 --- /dev/null +++ b/nuttx/graphics/nxconsole/nxcon_register.c @@ -0,0 +1,160 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nxcon_register.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "nxcon_internal.h" + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_allocate + ****************************************************************************/ + +FAR struct nxcon_state_s * + nxcon_register(NXCONSOLE handle, FAR struct nxcon_window_s *wndo, + FAR const struct nxcon_operations_s *ops, int minor) +{ + FAR struct nxcon_state_s *priv; + char devname[NX_DEVNAME_SIZE]; + int ret; + + DEBUGASSERT(handle && wndo && ops && (unsigned)minor < 256); + + /* Allocate the driver structure */ + + priv = (FAR struct nxcon_state_s *)kzalloc(sizeof(struct nxcon_state_s)); + if (!priv) + { + gdbg("Failed to allocate the NX driver structure\n"); + return NULL; + } + + /* Initialize the driver structure */ + + priv->ops = ops; + priv->handle = handle; + priv->minor = minor; + memcpy(&priv->wndo, wndo, sizeof( struct nxcon_window_s)); + + sem_init(&priv->exclsem, 0, 1); +#ifdef CONFIG_DEBUG + priv->holder = NO_HOLDER; +#endif + +#ifdef CONFIG_NXCONSOLE_NXKBDIN + sem_init(&priv->waitsem, 0, 0); +#endif + + /* Select the font */ + + priv->font = nxf_getfonthandle(wndo->fontid); + if (!priv->font) + { + gdbg("Failed to get font ID %d: %d\n", wndo->fontid, errno); + goto errout; + } + + FAR const struct nx_font_s *fontset; + + /* Get information about the font set being used and save this in the + * state structure + */ + + fontset = nxf_getfontset(priv->font); + priv->fheight = fontset->mxheight; + priv->fwidth = fontset->mxwidth; + priv->spwidth = fontset->spwidth; + + /* Set up the text cache */ + + priv->maxchars = CONFIG_NXCONSOLE_MXCHARS; + + /* Set up the font glyph bitmap cache */ + + priv->maxglyphs = CONFIG_NXCONSOLE_CACHESIZE; + + /* Set the initial display position */ + + nxcon_home(priv); + + /* Show the cursor */ + + priv->cursor.code = CONFIG_NXCONSOLE_CURSORCHAR; + nxcon_showcursor(priv); + + /* Register the driver */ + + snprintf(devname, NX_DEVNAME_SIZE, NX_DEVNAME_FORMAT, minor); + ret = register_driver(devname, &g_nxcon_drvrops, 0666, priv); + if (ret < 0) + { + gdbg("Failed to register %s\n", devname); + } + return (NXCONSOLE)priv; + +errout: + kfree(priv); + return NULL; +} diff --git a/nuttx/graphics/nxconsole/nxcon_scroll.c b/nuttx/graphics/nxconsole/nxcon_scroll.c new file mode 100755 index 0000000000..c1a0fec950 --- /dev/null +++ b/nuttx/graphics/nxconsole/nxcon_scroll.c @@ -0,0 +1,239 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nxcon_scroll.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "nxcon_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_movedisplay + * + * Description: + * This function implements the data movement for the scroll operation. If + * we can read the displays framebuffer memory, then the job is pretty + * easy. However, many displays (such as SPI-based LCDs) are often read- + * only. + ****************************************************************************/ + +#ifdef CONFIG_NX_WRITEONLY +static inline void nxcon_movedisplay(FAR struct nxcon_state_s *priv, + int bottom, int scrollheight) +{ + FAR struct nxcon_bitmap_s *bm; + struct nxgl_rect_s rect; + nxgl_coord_t row; + int ret; + int i; + + /* Move each row, one at a time. They could all be moved at once (by calling + * nxcon_redraw), but the since the region is cleared, then re-written, the + * effect would not be good. Below the region is also cleared and re-written, + * however, in much smaller chunks. + */ + + rect.pt1.x = 0; + rect.pt2.x = priv->wndo.wsize.w - 1; + + for (row = CONFIG_NXCONSOLE_LINESEPARATION; row < bottom; row += scrollheight) + { + /* Create a bounding box the size of one row of characters */ + + rect.pt1.y = row; + rect.pt2.y = row + scrollheight - 1; + + /* Clear the region */ + + ret = priv->ops->fill(priv, &rect, priv->wndo.wcolor); + if (ret < 0) + { + gdbg("fill failed: %d\n", errno); + } + + /* Fill each character that might lie within in the bounding box */ + + for (i = 0; i < priv->nchars; i++) + { + bm = &priv->bm[i]; + if (bm->pos.y <= rect.pt2.y && bm->pos.y + priv->fheight >= rect.pt1.y) + { + nxcon_fillchar(priv, &rect, bm); + } + } + } + + /* Finally, clear the bottom part of the display */ + + rect.pt1.y = bottom; + rect.pt2.y = priv->wndo.wsize.h- 1; + + ret = priv->ops->fill(priv, &rect, priv->wndo.wcolor); + if (ret < 0) + { + gdbg("nxcon_movedisplay: fill failed: %d\n", errno); + } +} +#else +static inline void nxcon_movedisplay(FAR struct nxcon_state_s *priv, + int bottom, int scrollheight) +{ + struct nxgl_rect_s rect; + struct nxgl_point_s offset; + int ret; + + /* Move the display in the range of 0-height up one scrollheight. The + * line at the bottom will be reset to the background color automatically. + * + * The source rectangle to be moved. + */ + + rect.pt1.x = 0; + rect.pt1.y = scrollheight + CONFIG_NXCONSOLE_LINESEPARATION; + rect.pt2.x = priv->wndo.wsize.w - 1; + rect.pt2.y = priv->wndo.wsize.h - 1; + + /* The offset that determines how far to move the source rectangle */ + + offset.x = 0; + offset.y = -scrollheight; + + /* Move the source rectangle */ + + ret = priv->ops->move(priv, &rect, &offset); + if (ret < 0) + { + gdbg("move failed: %d\n", errno); + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_scroll + ****************************************************************************/ + +void nxcon_scroll(FAR struct nxcon_state_s *priv, int scrollheight) +{ + int i; + int j; + + /* Adjust the vertical position of each character */ + + for (i = 0; i < priv->nchars; ) + { + FAR struct nxcon_bitmap_s *bm = &priv->bm[i]; + + /* Has any part of this character scrolled off the screen? */ + + if (bm->pos.y < scrollheight + CONFIG_NXCONSOLE_LINESEPARATION) + { + /* Yes... Delete the character by moving all of the data */ + + for (j = i; j < priv->nchars-1; j++) + { + memcpy(&priv->bm[j], &priv->bm[j+1], sizeof(struct nxcon_bitmap_s)); + } + + /* Decrement the number of cached characters ('i' is not incremented + * in this case because it already points to the next character) + */ + + priv->nchars--; + } + + /* No.. just decrement its vertical position (moving it "up" the + * display by one line). + */ + + else + { + bm->pos.y -= scrollheight; + + /* We are keeping this one so increment to the next character */ + + i++; + } + } + + /* And move the next display position up by one line as well */ + + priv->fpos.y -= scrollheight; + + /* Move the display in the range of 0-height up one scrollheight. */ + + nxcon_movedisplay(priv, priv->fpos.y, scrollheight); +} diff --git a/nuttx/graphics/nxconsole/nxcon_sem.c b/nuttx/graphics/nxconsole/nxcon_sem.c new file mode 100644 index 0000000000..4cf960971d --- /dev/null +++ b/nuttx/graphics/nxconsole/nxcon_sem.c @@ -0,0 +1,129 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nxcon_sem.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "nxcon_internal.h" + +#ifdef CONFIG_DEBUG + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_semwait and nxcon_sempost + * + * Description: + * If debug is on, then lower level code may attempt console output while + * we are doing console output! In this case, we will toss the nested + * output to avoid deadlocks and infinite loops. + * + * Input Parameters: + * priv - Driver data structure + * + * Returned Value: + * + * + ****************************************************************************/ + +int nxcon_semwait(FAR struct nxcon_state_s *priv) +{ + pid_t me; + int ret; + + /* Does I already hold the semaphore */ + + me = getpid(); + if (priv->holder != me) + { + /* No.. then wait until the thread that does hold it is finished with it */ + + ret = sem_wait(&priv->exclsem); + if (ret == OK) + { + /* No I hold the semaphore */ + + priv->holder = me; + } + return ret; + } + + /* Abort, abort, abort! I have been re-entered */ + + set_errno(EBUSY); + return ERROR; +} + +int nxcon_sempost(FAR struct nxcon_state_s *priv) +{ + pid_t me = getpid(); + + /* Make sure that I really hold the semaphore */ + + ASSERT(priv->holder == me); + + /* Then let go of it */ + + priv->holder = NO_HOLDER; + return sem_post(&priv->exclsem); +} + +#endif /* CONFIG_DEBUG */ diff --git a/nuttx/graphics/nxconsole/nxcon_unregister.c b/nuttx/graphics/nxconsole/nxcon_unregister.c new file mode 100644 index 0000000000..af6a533701 --- /dev/null +++ b/nuttx/graphics/nxconsole/nxcon_unregister.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nxcon_unregister.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "nxcon_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_unregister + * + * Description: + * Un-register to NX console device. + * + * Input Parameters: + * handle - A handle previously returned by nx_register, nxtk_register, or + * nxtool_register. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void nxcon_unregister(NXCONSOLE handle) +{ + FAR struct nxcon_state_s *priv; + char devname[NX_DEVNAME_SIZE]; + int i; + + DEBUGASSERT(handle); + + /* Get the reference to the driver structure from the handle */ + + priv = (FAR struct nxcon_state_s *)handle; + sem_destroy(&priv->exclsem); +#ifdef CONFIG_NXCONSOLE_NXKBDIN + sem_destroy(&priv->waitsem); +#endif + + /* Free all allocated glyph bitmap */ + + for (i = 0; i < CONFIG_NXCONSOLE_CACHESIZE; i++) + { + FAR struct nxcon_glyph_s *glyph = &priv->glyph[i]; + if (glyph->bitmap) + { + kfree(glyph->bitmap); + } + } + + /* Unregister the driver */ + + snprintf(devname, NX_DEVNAME_SIZE, NX_DEVNAME_FORMAT, priv->minor); + (void)unregister_driver(devname); + + /* Free the private data structure */ + + kfree(handle); +} diff --git a/nuttx/graphics/nxconsole/nxcon_vt100.c b/nuttx/graphics/nxconsole/nxcon_vt100.c new file mode 100644 index 0000000000..3e3374dce7 --- /dev/null +++ b/nuttx/graphics/nxconsole/nxcon_vt100.c @@ -0,0 +1,289 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nxcon_vt100.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "nxcon_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +typedef int (*seqhandler_t)(FAR struct nxcon_state_s *priv); + +struct vt100_sequence_s +{ + FAR const char *seq; + seqhandler_t handler; + uint8_t size; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int nxcon_erasetoeol(FAR struct nxcon_state_s *priv); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* All recognized VT100 escape sequences. Very little as present, this is + * a placeholder for a future, more complete VT100 emulation. + */ + +/* [K is the VT100 command erases to the end of the line. */ + +static const char g_erasetoeol[] = VT100_CLEAREOL; + +/* The list of all VT100 sequences supported by the emulation */ + +static const struct vt100_sequence_s g_vt100sequences[] = +{ + {g_erasetoeol, nxcon_erasetoeol, sizeof(g_erasetoeol)}, + {NULL, NULL, 0} +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_erasetoeol + * + * Description: + * Handle the erase-to-eol VT100 escapte sequence + * + * Input Parameters: + * priv - Driver data structure + * + * Returned Value: + * The index of the match in g_vt100sequences[] + * + ****************************************************************************/ + +static int nxcon_erasetoeol(FAR struct nxcon_state_s *priv) +{ + /* Does nothing yet (other than consume the sequence) */ + + return OK; +} + +/**************************************************************************** + * Name: nxcon_vt100part + * + * Description: + * Return the next entry that is a partial match to the sequence. + * + * Input Parameters: + * priv - Driver data structure + * seqsize - The number of bytes in the sequence + * startndx - The index to start searching + * + * Returned Value: + * A pointer to the matching sequence in g_vt100sequences[] + * + ****************************************************************************/ + +FAR const struct vt100_sequence_s * +nxcon_vt100part(FAR struct nxcon_state_s *priv, int seqsize) +{ + FAR const struct vt100_sequence_s *seq; + int ndx; + + /* Search from the beginning of the sequence table */ + + for (ndx = 0; g_vt100sequences[ndx].seq; ndx++) + { + /* Is this sequence big enough? */ + + seq = &g_vt100sequences[ndx]; + if (seq->size >= seqsize) + { + /* Yes... are the first 'seqsize' bytes the same */ + + if (memcmp(seq->seq, priv->seq, seqsize) == 0) + { + /* Yes.. return the match */ + + return seq; + } + } + } + return NULL; +} + +/**************************************************************************** + * Name: nxcon_vt100seq + * + * Description: + * Determine if the new sequence is a part of a supported VT100 escape + * sequence. + * + * Input Parameters: + * priv - Driver data structure + * seqsize - The number of bytes in the sequence + * + * Returned Value: + * state - See enum nxcon_vt100state_e; + * + ****************************************************************************/ + +static enum nxcon_vt100state_e nxcon_vt100seq(FAR struct nxcon_state_s *priv, + int seqsize) +{ + FAR const struct vt100_sequence_s *seq; + enum nxcon_vt100state_e ret; + + /* Is there any VT100 escape sequence that matches what we have + * buffered so far? + */ + + seq = nxcon_vt100part(priv, seqsize); + if (seq) + { + /* Yes.. if the size of that escape sequence is the same as what we + * have buffered, then we have an exact match. + */ + + if (seq->size == seqsize) + { + /* Process the VT100 sequence */ + + seq->handler(priv); + priv->nseq = 0; + return VT100_PROCESSED; + } + + /* The 'seqsize' is still smaller than the potential match(es). We + * will need to collect more characters before we can make a decision. + * Retun an indication that we have consumed the character. + */ + + return VT100_CONSUMED; + } + + /* We get here on a failure. The buffer sequence is not part of any + * supported VT100 escape sequence. If seqsize > 1 then we need to + * return a special value because we have to re-process the buffered + * data. + */ + + ret = seqsize > 1 ? VT100_ABORT : VT100_NOT_CONSUMED; + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxcon_vt100 + * + * Description: + * Test if the newly received byte is part of a VT100 escape sequence + * + * Input Parameters: + * priv - Driver data structure + * ch - The newly received character + * + * Returned Value: + * state - See enum nxcon_vt100state_e; + * + ****************************************************************************/ + +enum nxcon_vt100state_e nxcon_vt100(FAR struct nxcon_state_s *priv, char ch) +{ + enum nxcon_vt100state_e ret; + int seqsize; + + DEBUGASSERT(priv && priv->nseq < VT100_MAX_SEQUENCE); + + /* If we have no buffered characters, then 'ch' must be the first character + * of an escape sequence. + */ + + if (priv->nseq < 1) + { + /* The first character of an escape sequence must be an an escape + * character (duh). + */ + + if (ch != ASCII_ESC) + { + return VT100_NOT_CONSUMED; + } + + /* Add the escape character to the buffer but don't bother with any + * further checking. + */ + + priv->seq[0] = ASCII_ESC; + priv->nseq = 1; + return VT100_CONSUMED; + } + + /* Temporarily add the next character to the buffer */ + + seqsize = priv->nseq; + priv->seq[seqsize] = ch; + + /* Then check if this sequence is part of an a valid escape sequence */ + + seqsize++; + ret = nxcon_vt100seq(priv, seqsize); + if (ret == VT100_CONSUMED) + { + /* The newly added character is indeed part of a VT100 escape sequence + * (which is still incomplete). Keep it in the buffer. + */ + + priv->nseq = seqsize; + } + return ret; +} diff --git a/nuttx/graphics/nxconsole/nxtk_register.c b/nuttx/graphics/nxconsole/nxtk_register.c new file mode 100644 index 0000000000..0a11fc6cfe --- /dev/null +++ b/nuttx/graphics/nxconsole/nxtk_register.c @@ -0,0 +1,192 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nxtk_register.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "nxcon_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int nxtkcon_fill(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t wcolor[CONFIG_NX_NPLANES]); +#ifndef CONFIG_NX_WRITEONLY +static int nxtkcon_move(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset); +#endif +static int nxtkcon_bitmap(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, + unsigned int stride); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct nxcon_operations_s g_nxtkops = +{ + nxtkcon_fill, +#ifndef CONFIG_NX_WRITEONLY + nxtkcon_move, +#endif + nxtkcon_bitmap +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtkcon_fill + * + * Description: + * Fill the specified rectangle in the window with the specified color + * + * Input Parameters: + * priv - The driver state structure. + * rect - The location to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +static int nxtkcon_fill(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t wcolor[CONFIG_NX_NPLANES]) +{ + return nxtk_fillwindow((NXTKWINDOW)priv->handle, rect, wcolor); +} + +/**************************************************************************** + * Name: nxtkcon_move + * + * Description: + * Move a rectangular region within the window + * + * Input Parameters: + * priv - The driver state structure. + * rect - Describes the rectangular region to move + * offset - The offset to move the region. The rectangular region will be + * moved so that the origin is translated by this amount. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +#ifndef CONFIG_NX_WRITEONLY +static int nxtkcon_move(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset) +{ + return nxtk_movewindow((NXTKWINDOW)priv->handle, rect, offset); +} +#endif + +/**************************************************************************** + * Name: nxtkcon_bitmap + * + * Description: + * Copy a rectangular region of a larger image into the rectangle in the + * specified window. + * + * Input Parameters: + * priv - The driver state structure. + * dest - Describes the rectangular region on the display that will + * receive the bit map. + * src - The start of the source image. This is an array source + * images of size CONFIG_NX_NPLANES. + * origin - The origin of the upper, left-most corner of the full bitmap. + * Both dest and origin are in window coordinates, however, origin + * may lie outside of the display. + * stride - The width of the full source image in bytes. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +static int nxtkcon_bitmap(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, + unsigned int stride) +{ + return nxtk_bitmapwindow((NXTKWINDOW)priv->handle, dest, src, origin, stride); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_register + * + * Description: + * Register a console device on a framed NX window. The device will be + * registered at /dev/nxtkN where N is the provided minor number. + * + * Input Parameters: + * hfwnd - A handle that will be used to access the window. The window must + * persist and this handle must be valid for the life of the NX console. + * wndo - Describes the window and font to be used + * minor - The device minor number + * + * Return: + * A non-NULL handle is returned on success. + * + ****************************************************************************/ + +NXCONSOLE nxtk_register(NXTKWINDOW hfwnd, FAR struct nxcon_window_s *wndo, int minor) +{ + return nxcon_register((NXCONSOLE)hfwnd, wndo, &g_nxtkops, minor); +} diff --git a/nuttx/graphics/nxconsole/nxtool_register.c b/nuttx/graphics/nxconsole/nxtool_register.c new file mode 100644 index 0000000000..b063d5a613 --- /dev/null +++ b/nuttx/graphics/nxconsole/nxtool_register.c @@ -0,0 +1,195 @@ +/**************************************************************************** + * nuttx/graphics/nxconsole/nxtool_register.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "nxcon_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int nxtool_fill(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t wcolor[CONFIG_NX_NPLANES]); +#ifndef CONFIG_NX_WRITEONLY +static int nxtool_move(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset); +#endif +static int nxtool_bitmap(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, + unsigned int stride); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct nxcon_operations_s g_nxtoolops = +{ + nxtool_fill, +#ifndef CONFIG_NX_WRITEONLY + nxtool_move, +#endif + nxtool_bitmap +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtool_fill + * + * Description: + * Fill the specified rectangle in the window with the specified color + * + * Input Parameters: + * priv - The driver state structure. + * rect - The location to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +static int nxtool_fill(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t wcolor[CONFIG_NX_NPLANES]) +{ + return nxtk_filltoolbar((NXTKWINDOW)priv->handle, rect, wcolor); +} + +/**************************************************************************** + * Name: nxtool_move + * + * Description: + * Move a rectangular region within the window + * + * Input Parameters: + * priv - The driver state structure. + * rect - Describes the rectangular region to move + * offset - The offset to move the region. The rectangular region will be + * moved so that the origin is translated by this amount. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +#ifndef CONFIG_NX_WRITEONLY +static int nxtool_move(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset) +{ + return nxtk_movetoolbar((NXTKWINDOW)priv->handle, rect, offset); +} +#endif + +/**************************************************************************** + * Name: nxtool_bitmap + * + * Description: + * Copy a rectangular region of a larger image into the rectangle in the + * specified window. + * + * Input Parameters: + * priv - The driver state structure. + * dest - Describes the rectangular region on the display that will + * receive the bit map. + * src - The start of the source image. This is an array source + * images of size CONFIG_NX_NPLANES. + * origin - The origin of the upper, left-most corner of the full bitmap. + * Both dest and origin are in window coordinates, however, origin + * may lie outside of the display. + * stride - The width of the full source image in bytes. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +static int nxtool_bitmap(FAR struct nxcon_state_s *priv, + FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, + unsigned int stride) +{ + return nxtk_bitmaptoolbar((NXTKWINDOW)priv->handle, dest, src, origin, stride); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtool_register + * + * Description: + * Register a console device on a toolbar of a framed NX window. The + * device will be registered at /dev/nxtoolN where N is the provided minor + * number. + * + * Input Parameters: + * hfwnd - A handle that will be used to access the toolbar. The toolbar + * must persist and this handle must be valid for the life of the NX + * console. + * wndo - Describes the window and font to be used + * minor - The device minor number + * + * Return: + * A non-NULL handle is returned on success. + * + ****************************************************************************/ + +NXCONSOLE nxtool_register(NXTKWINDOW hfwnd, FAR struct nxcon_window_s *wndo, int minor) +{ + return nxcon_register((NXCONSOLE)hfwnd, wndo, &g_nxtoolops, minor); +} + diff --git a/nuttx/graphics/nxfonts/Make.defs b/nuttx/graphics/nxfonts/Make.defs new file mode 100644 index 0000000000..95665ad362 --- /dev/null +++ b/nuttx/graphics/nxfonts/Make.defs @@ -0,0 +1,122 @@ +############################################################################ +# graphics/nxfonts/Make.defs +# +# Copyright (C) 2008 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +NXFCONV_ASRCS = +NXFCONV_CSRCS = nxfonts_convert_1bpp.c nxfonts_convert_2bpp.c \ + nxfonts_convert_4bpp.c nxfonts_convert_8bpp.c \ + nxfonts_convert_16bpp.c nxfonts_convert_24bpp.c \ + nxfonts_convert_32bpp.c + +NXFSET_ASRCS = +NXFSET_CSRCS = + +# Sans serif fonts + +ifeq ($(CONFIG_NXFONT_SANS17X22),y) +NXFSET_CSRCS += nxfonts_bitmaps_sans17x22.c +endif + +ifeq ($(CONFIG_NXFONT_SANS20X26),y) +NXFSET_CSRCS += nxfonts_bitmaps_sans20x26.c +endif + +ifeq ($(CONFIG_NXFONT_SANS23X27),y) +NXFSET_CSRCS += nxfonts_bitmaps_sans23x27.c +endif + +ifeq ($(CONFIG_NXFONT_SANS22X29),y) +NXFSET_CSRCS += nxfonts_bitmaps_sans22x29.c +endif + +ifeq ($(CONFIG_NXFONT_SANS28X37),y) +NXFSET_CSRCS += nxfonts_bitmaps_sans28x37.c +endif + +ifeq ($(CONFIG_NXFONT_SANS39X48),y) +NXFSET_CSRCS += nxfonts_bitmaps_sans39x48.c +endif + +# Sans serif bold fonts + +ifeq ($(CONFIG_NXFONT_SANS17X23B),y) +NXFSET_CSRCS += nxfonts_bitmaps_sans17x23b.c +endif + +ifeq ($(CONFIG_NXFONT_SANS20X27B),y) +NXFSET_CSRCS += nxfonts_bitmaps_sans20x27b.c +endif + +ifeq ($(CONFIG_NXFONT_SANS22X29B),y) +NXFSET_CSRCS += nxfonts_bitmaps_sans22x29b.c +endif + +ifeq ($(CONFIG_NXFONT_SANS28X37B),y) +NXFSET_CSRCS += nxfonts_bitmaps_sans28x37b.c +endif + +ifeq ($(CONFIG_NXFONT_SANS40X49B),y) +NXFSET_CSRCS += nxfonts_bitmaps_sans40x49b.c +endif + +# Serif fonts + +ifeq ($(CONFIG_NXFONT_SERIF22X29),y) +NXFSET_CSRCS += nxfonts_bitmaps_serif22x29.c +endif + +ifeq ($(CONFIG_NXFONT_SERIF29X37),y) +NXFSET_CSRCS += nxfonts_bitmaps_serif29x37.c +endif + +ifeq ($(CONFIG_NXFONT_SERIF38X48),y) +NXFSET_CSRCS += nxfonts_bitmaps_serif38x48.c +endif + +# Serif bold fonts + +ifeq ($(CONFIG_NXFONT_SERIF22X28B),y) +NXFSET_CSRCS += nxfonts_bitmaps_serif22x28b.c +endif + +ifeq ($(CONFIG_NXFONT_SERIF27X38B),y) +NXFSET_CSRCS += nxfonts_bitmaps_serif27x38b.c +endif + +ifeq ($(CONFIG_NXFONT_SERIF38X49B),y) +NXFSET_CSRCS += nxfonts_bitmaps_serif38x49b.c +endif + +NXFONTS_ASRCS = $(NXFCONV_ASRCS) $(NXFSET_ASRCS) +NXFONTS_CSRCS = nxfonts_getfont.c $(NXFCONV_CSRCS) $(NXFSET_CSRCS) diff --git a/nuttx/graphics/nxfonts/Makefile.sources b/nuttx/graphics/nxfonts/Makefile.sources new file mode 100644 index 0000000000..2867425798 --- /dev/null +++ b/nuttx/graphics/nxfonts/Makefile.sources @@ -0,0 +1,189 @@ +############################################################################ +# graphics/nxfonts/Makefile.sources +# +# Copyright (C) 2008 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs + +ifdef NXFONTS_BITSPERPIXEL +ifeq ($(NXFONTS_BITSPERPIXEL),1) +NXFONTS_SUFFIX := _1bpp +GEN_CSRC := nxfonts_convert_1bpp.c +endif +ifeq ($(NXFONTS_BITSPERPIXEL),2) +NXFONTS_SUFFIX := _2bpp +GEN_CSRC := nxfonts_convert_2bpp.c +endif +ifeq ($(NXFONTS_BITSPERPIXEL),4) +NXFONTS_SUFFIX := _4bpp +GEN_CSRC := nxfonts_convert_4bpp.c +endif +ifeq ($(NXFONTS_BITSPERPIXEL),8) +NXFONTS_SUFFIX := _8bpp +GEN_CSRC := nxfonts_convert_8bpp.c +endif +ifeq ($(NXFONTS_BITSPERPIXEL),16) +NXFONTS_SUFFIX := _16bpp +GEN_CSRC := nxfonts_convert_16bpp.c +endif +ifeq ($(NXFONTS_BITSPERPIXEL),24) +NXFONTS_SUFFIX := _24bpp +GEN_CSRC := nxfonts_convert_24bpp.c +endif +ifeq ($(NXFONTS_BITSPERPIXEL),32) +NXFONTS_SUFFIX := _32bpp +GEN_CSRC := nxfonts_convert_32bpp.c +endif + +DEPENDENCY := nxfonts_convert.c +CPPFLAGS += -DNXFONTS_BITSPERPIXEL=$(NXFONTS_BITSPERPIXEL) +CPPFLAGS += -DNXFONTS_SUFFIX=$(NXFONTS_SUFFIX) +endif + +ifdef NXFONTS_FONTID + +# SANS + +ifeq ($(NXFONTS_FONTID),14) +NXFONTS_PREFIX := g_sans17x22_ +GEN_CSRC = nxfonts_bitmaps_sans17x22.c +endif + +ifeq ($(NXFONTS_FONTID),15) +NXFONTS_PREFIX := g_sans20x26_ +GEN_CSRC = nxfonts_bitmaps_sans20x26.c +endif + +ifeq ($(NXFONTS_FONTID),1) +NXFONTS_PREFIX := g_sans23x27_ +GEN_CSRC = nxfonts_bitmaps_sans23x27.c +endif + +ifeq ($(NXFONTS_FONTID),2) +NXFONTS_PREFIX := g_sans22x29_ +GEN_CSRC = nxfonts_bitmaps_sans22x29.c +endif + +ifeq ($(NXFONTS_FONTID),3) +NXFONTS_PREFIX := g_sans28x37_ +GEN_CSRC = nxfonts_bitmaps_sans28x37.c +endif + +ifeq ($(NXFONTS_FONTID),4) +NXFONTS_PREFIX := g_sans39x48_ +GEN_CSRC = nxfonts_bitmaps_sans39x48.c +endif + +# SANS-BOLD + +ifeq ($(NXFONTS_FONTID),16) +NXFONTS_PREFIX := g_sans17x23b_ +GEN_CSRC = nxfonts_bitmaps_sans17x23b.c +endif + +ifeq ($(NXFONTS_FONTID),17) +NXFONTS_PREFIX := g_sans20x27b_ +GEN_CSRC = nxfonts_bitmaps_sans20x27b.c +endif + +ifeq ($(NXFONTS_FONTID),5) +NXFONTS_PREFIX := g_sans22x29b_ +GEN_CSRC = nxfonts_bitmaps_sans22x29b.c +endif + +ifeq ($(NXFONTS_FONTID),6) +NXFONTS_PREFIX := g_sans28x37b_ +GEN_CSRC = nxfonts_bitmaps_sans28x37b.c +endif + +ifeq ($(NXFONTS_FONTID),7) +NXFONTS_PREFIX := g_sans40x49b_ +GEN_CSRC = nxfonts_bitmaps_sans40x49b.c +endif + +# SERIF + +ifeq ($(NXFONTS_FONTID),8) +NXFONTS_PREFIX := g_serif22x29_ +GEN_CSRC = nxfonts_bitmaps_serif22x29.c +endif + +ifeq ($(NXFONTS_FONTID),9) +NXFONTS_PREFIX := g_serif29x37_ +GEN_CSRC = nxfonts_bitmaps_serif29x37.c +endif + +ifeq ($(NXFONTS_FONTID),10) +NXFONTS_PREFIX := g_serif38x48_ +GEN_CSRC = nxfonts_bitmaps_serif38x48.c +endif + +# SERIF-BOLD + +ifeq ($(NXFONTS_FONTID),11) +NXFONTS_PREFIX := g_serif22x28b_ +GEN_CSRC = nxfonts_bitmaps_serif22x28b.c +endif + +ifeq ($(NXFONTS_FONTID),12) +NXFONTS_PREFIX := g_serif27x38b_ +GEN_CSRC = nxfonts_bitmaps_serif27x38b.c +endif + +ifeq ($(NXFONTS_FONTID),13) +NXFONTS_PREFIX := g_serif38x49b_ +GEN_CSRC = nxfonts_bitmaps_serif38x49b.c +endif + +DEPENDENCY := nxfonts_bitmaps.c +CPPFLAGS += -DNXFONTS_FONTID=$(NXFONTS_FONTID) +CPPFLAGS += -DNXFONTS_PREFIX=$(NXFONTS_PREFIX) +endif + +GEN_TMP = $(GEN_CSRC:.c=.i) + +all: $(GEN_CSRC) +.PHONY : clean distclean + +$(GEN_CSRC) : $(DEPENDENCY) + @$(call PREPROCESS, $<, $(GEN_TMP)) + @cat $(GEN_TMP) | sed -e "/^#/d" >$@ + @rm -f $(GEN_TMP) + +clean: + @rm -f *~ .*.swp *.i + +distclean: clean + @rm -f nxfonts_convert_*bpp.c + @rm -f nxfonts_bitmaps_*.c diff --git a/nuttx/graphics/nxfonts/nxfonts_bitmaps.c b/nuttx/graphics/nxfonts/nxfonts_bitmaps.c new file mode 100644 index 0000000000..9b255b97a6 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_bitmaps.c @@ -0,0 +1,1689 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_bitmaps.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "nxfonts_internal.h" + +/* Pick the fontset */ + +#if NXFONTS_FONTID == 1 +# include "nxfonts_sans23x27.h" +#elif NXFONTS_FONTID == 2 +# include "nxfonts_sans22x29.h" +#elif NXFONTS_FONTID == 3 +# include "nxfonts_sans28x37.h" +#elif NXFONTS_FONTID == 4 +# include "nxfonts_sans39x48.h" +#elif NXFONTS_FONTID == 5 +# include "nxfonts_sans22x29b.h" +#elif NXFONTS_FONTID == 6 +# include "nxfonts_sans28x37b.h" +#elif NXFONTS_FONTID == 7 +# include "nxfonts_sans40x49b.h" +#elif NXFONTS_FONTID == 8 +# include "nxfonts_serif22x29.h" +#elif NXFONTS_FONTID == 9 +# include "nxfonts_serif29x37.h" +#elif NXFONTS_FONTID == 10 +# include "nxfonts_serif38x48.h" +#elif NXFONTS_FONTID == 11 +# include "nxfonts_serif22x28b.h" +#elif NXFONTS_FONTID == 12 +# include "nxfonts_serif27x38b.h" +#elif NXFONTS_FONTID == 13 +# include "nxfonts_serif38x49b.h" +#elif NXFONTS_FONTID == 14 +# include "nxfonts_sans17x22.h" +#elif NXFONTS_FONTID == 15 +# include "nxfonts_sans20x26.h" +#elif NXFONTS_FONTID == 16 +# include "nxfonts_sans17x23b.h" +#elif NXFONTS_FONTID == 17 +# include "nxfonts_sans20x27b.h" +#else +# error "No font ID specified" +#endif + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#define NXFONT_N7BITFONTS (NXFONT_MAX7BIT - NXFONT_MIN7BIT + 1) +#define NXFONT_N8BITFONTS (NXFONT_MAX8BIT - NXFONT_MIN8BIT + 1) + +#define NXFONT_CONCAT(a,b) a##b +#define NXFONT_DEFBITMAP(n) \ +static const uint8_t NXFONT_CONCAT(g_bitmap_,n)[] = NXFONT_CONCAT(NXFONT_BITMAP_,n) +#define NXFONT_DEFMETRIC(n) \ + { NXFONT_CONCAT(NXFONT_METRICS_,n), NXFONT_CONCAT(g_bitmap_,n) } +#define NXF_SYMNAME(a,b) NXFONT_CONCAT(a,b) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if NXFONT_MIN7BIT <= 0 && NXFONT_MAX7BIT >= 0 +NXFONT_DEFBITMAP(0); +#endif +#if NXFONT_MIN7BIT <= 1 && NXFONT_MAX7BIT >= 1 +NXFONT_DEFBITMAP(1); +#endif +#if NXFONT_MIN7BIT <= 2 && NXFONT_MAX7BIT >= 2 +NXFONT_DEFBITMAP(2); +#endif +#if NXFONT_MIN7BIT <= 3 && NXFONT_MAX7BIT >= 3 +NXFONT_DEFBITMAP(3); +#endif +#if NXFONT_MIN7BIT <= 4 && NXFONT_MAX7BIT >= 4 +NXFONT_DEFBITMAP(4); +#endif +#if NXFONT_MIN7BIT <= 5 && NXFONT_MAX7BIT >= 5 +NXFONT_DEFBITMAP(5); +#endif +#if NXFONT_MIN7BIT <= 6 && NXFONT_MAX7BIT >= 6 +NXFONT_DEFBITMAP(6); +#endif +#if NXFONT_MIN7BIT <= 7 && NXFONT_MAX7BIT >= 7 +NXFONT_DEFBITMAP(7); +#endif +#if NXFONT_MIN7BIT <= 8 && NXFONT_MAX7BIT >= 8 +NXFONT_DEFBITMAP(8); +#endif +#if NXFONT_MIN7BIT <= 9 && NXFONT_MAX7BIT >= 9 +NXFONT_DEFBITMAP(9); +#endif +#if NXFONT_MIN7BIT <= 10 && NXFONT_MAX7BIT >= 10 +NXFONT_DEFBITMAP(10); +#endif +#if NXFONT_MIN7BIT <= 11 && NXFONT_MAX7BIT >= 11 +NXFONT_DEFBITMAP(11); +#endif +#if NXFONT_MIN7BIT <= 12 && NXFONT_MAX7BIT >= 12 +NXFONT_DEFBITMAP(12); +#endif +#if NXFONT_MIN7BIT <= 13 && NXFONT_MAX7BIT >= 13 +NXFONT_DEFBITMAP(13); +#endif +#if NXFONT_MIN7BIT <= 14 && NXFONT_MAX7BIT >= 14 +NXFONT_DEFBITMAP(14); +#endif +#if NXFONT_MIN7BIT <= 15 && NXFONT_MAX7BIT >= 15 +NXFONT_DEFBITMAP(15); +#endif +#if NXFONT_MIN7BIT <= 16 && NXFONT_MAX7BIT >= 16 +NXFONT_DEFBITMAP(16); +#endif +#if NXFONT_MIN7BIT <= 17 && NXFONT_MAX7BIT >= 17 +NXFONT_DEFBITMAP(17); +#endif +#if NXFONT_MIN7BIT <= 18 && NXFONT_MAX7BIT >= 18 +NXFONT_DEFBITMAP(18); +#endif +#if NXFONT_MIN7BIT <= 19 && NXFONT_MAX7BIT >= 19 +NXFONT_DEFBITMAP(19); +#endif +#if NXFONT_MIN7BIT <= 20 && NXFONT_MAX7BIT >= 20 +NXFONT_DEFBITMAP(20); +#endif +#if NXFONT_MIN7BIT <= 21 && NXFONT_MAX7BIT >= 21 +NXFONT_DEFBITMAP(21); +#endif +#if NXFONT_MIN7BIT <= 22 && NXFONT_MAX7BIT >= 22 +NXFONT_DEFBITMAP(22); +#endif +#if NXFONT_MIN7BIT <= 23 && NXFONT_MAX7BIT >= 23 +NXFONT_DEFBITMAP(23); +#endif +#if NXFONT_MIN7BIT <= 24 && NXFONT_MAX7BIT >= 24 +NXFONT_DEFBITMAP(24); +#endif +#if NXFONT_MIN7BIT <= 25 && NXFONT_MAX7BIT >= 25 +NXFONT_DEFBITMAP(25); +#endif +#if NXFONT_MIN7BIT <= 26 && NXFONT_MAX7BIT >= 26 +NXFONT_DEFBITMAP(26); +#endif +#if NXFONT_MIN7BIT <= 27 && NXFONT_MAX7BIT >= 27 +NXFONT_DEFBITMAP(27); +#endif +#if NXFONT_MIN7BIT <= 28 && NXFONT_MAX7BIT >= 28 +NXFONT_DEFBITMAP(28); +#endif +#if NXFONT_MIN7BIT <= 29 && NXFONT_MAX7BIT >= 29 +NXFONT_DEFBITMAP(29); +#endif +#if NXFONT_MIN7BIT <= 30 && NXFONT_MAX7BIT >= 30 +NXFONT_DEFBITMAP(30); +#endif +#if NXFONT_MIN7BIT <= 31 && NXFONT_MAX7BIT >= 31 +NXFONT_DEFBITMAP(31); +#endif +#if NXFONT_MIN7BIT <= 32 && NXFONT_MAX7BIT >= 32 +NXFONT_DEFBITMAP(32); +#endif +#if NXFONT_MIN7BIT <= 33 && NXFONT_MAX7BIT >= 33 +NXFONT_DEFBITMAP(33); +#endif +#if NXFONT_MIN7BIT <= 34 && NXFONT_MAX7BIT >= 34 +NXFONT_DEFBITMAP(34); +#endif +#if NXFONT_MIN7BIT <= 35 && NXFONT_MAX7BIT >= 35 +NXFONT_DEFBITMAP(35); +#endif +#if NXFONT_MIN7BIT <= 36 && NXFONT_MAX7BIT >= 36 +NXFONT_DEFBITMAP(36); +#endif +#if NXFONT_MIN7BIT <= 37 && NXFONT_MAX7BIT >= 37 +NXFONT_DEFBITMAP(37); +#endif +#if NXFONT_MIN7BIT <= 38 && NXFONT_MAX7BIT >= 38 +NXFONT_DEFBITMAP(38); +#endif +#if NXFONT_MIN7BIT <= 39 && NXFONT_MAX7BIT >= 39 +NXFONT_DEFBITMAP(39); +#endif +#if NXFONT_MIN7BIT <= 40 && NXFONT_MAX7BIT >= 40 +NXFONT_DEFBITMAP(40); +#endif +#if NXFONT_MIN7BIT <= 41 && NXFONT_MAX7BIT >= 41 +NXFONT_DEFBITMAP(41); +#endif +#if NXFONT_MIN7BIT <= 42 && NXFONT_MAX7BIT >= 42 +NXFONT_DEFBITMAP(42); +#endif +#if NXFONT_MIN7BIT <= 43 && NXFONT_MAX7BIT >= 43 +NXFONT_DEFBITMAP(43); +#endif +#if NXFONT_MIN7BIT <= 44 && NXFONT_MAX7BIT >= 44 +NXFONT_DEFBITMAP(44); +#endif +#if NXFONT_MIN7BIT <= 45 && NXFONT_MAX7BIT >= 45 +NXFONT_DEFBITMAP(45); +#endif +#if NXFONT_MIN7BIT <= 46 && NXFONT_MAX7BIT >= 46 +NXFONT_DEFBITMAP(46); +#endif +#if NXFONT_MIN7BIT <= 47 && NXFONT_MAX7BIT >= 47 +NXFONT_DEFBITMAP(47); +#endif +#if NXFONT_MIN7BIT <= 48 && NXFONT_MAX7BIT >= 48 +NXFONT_DEFBITMAP(48); +#endif +#if NXFONT_MIN7BIT <= 49 && NXFONT_MAX7BIT >= 49 +NXFONT_DEFBITMAP(49); +#endif +#if NXFONT_MIN7BIT <= 50 && NXFONT_MAX7BIT >= 50 +NXFONT_DEFBITMAP(50); +#endif +#if NXFONT_MIN7BIT <= 51 && NXFONT_MAX7BIT >= 51 +NXFONT_DEFBITMAP(51); +#endif +#if NXFONT_MIN7BIT <= 52 && NXFONT_MAX7BIT >= 52 +NXFONT_DEFBITMAP(52); +#endif +#if NXFONT_MIN7BIT <= 53 && NXFONT_MAX7BIT >= 53 +NXFONT_DEFBITMAP(53); +#endif +#if NXFONT_MIN7BIT <= 54 && NXFONT_MAX7BIT >= 54 +NXFONT_DEFBITMAP(54); +#endif +#if NXFONT_MIN7BIT <= 55 && NXFONT_MAX7BIT >= 55 +NXFONT_DEFBITMAP(55); +#endif +#if NXFONT_MIN7BIT <= 56 && NXFONT_MAX7BIT >= 56 +NXFONT_DEFBITMAP(56); +#endif +#if NXFONT_MIN7BIT <= 57 && NXFONT_MAX7BIT >= 57 +NXFONT_DEFBITMAP(57); +#endif +#if NXFONT_MIN7BIT <= 58 && NXFONT_MAX7BIT >= 58 +NXFONT_DEFBITMAP(58); +#endif +#if NXFONT_MIN7BIT <= 59 && NXFONT_MAX7BIT >= 59 +NXFONT_DEFBITMAP(59); +#endif +#if NXFONT_MIN7BIT <= 60 && NXFONT_MAX7BIT >= 60 +NXFONT_DEFBITMAP(60); +#endif +#if NXFONT_MIN7BIT <= 61 && NXFONT_MAX7BIT >= 61 +NXFONT_DEFBITMAP(61); +#endif +#if NXFONT_MIN7BIT <= 62 && NXFONT_MAX7BIT >= 62 +NXFONT_DEFBITMAP(62); +#endif +#if NXFONT_MIN7BIT <= 63 && NXFONT_MAX7BIT >= 63 +NXFONT_DEFBITMAP(63); +#endif +#if NXFONT_MIN7BIT <= 64 && NXFONT_MAX7BIT >= 64 +NXFONT_DEFBITMAP(64); +#endif +#if NXFONT_MIN7BIT <= 65 && NXFONT_MAX7BIT >= 65 +NXFONT_DEFBITMAP(65); +#endif +#if NXFONT_MIN7BIT <= 66 && NXFONT_MAX7BIT >= 66 +NXFONT_DEFBITMAP(66); +#endif +#if NXFONT_MIN7BIT <= 67 && NXFONT_MAX7BIT >= 67 +NXFONT_DEFBITMAP(67); +#endif +#if NXFONT_MIN7BIT <= 68 && NXFONT_MAX7BIT >= 68 +NXFONT_DEFBITMAP(68); +#endif +#if NXFONT_MIN7BIT <= 69 && NXFONT_MAX7BIT >= 69 +NXFONT_DEFBITMAP(69); +#endif +#if NXFONT_MIN7BIT <= 70 && NXFONT_MAX7BIT >= 70 +NXFONT_DEFBITMAP(70); +#endif +#if NXFONT_MIN7BIT <= 71 && NXFONT_MAX7BIT >= 71 +NXFONT_DEFBITMAP(71); +#endif +#if NXFONT_MIN7BIT <= 72 && NXFONT_MAX7BIT >= 72 +NXFONT_DEFBITMAP(72); +#endif +#if NXFONT_MIN7BIT <= 73 && NXFONT_MAX7BIT >= 73 +NXFONT_DEFBITMAP(73); +#endif +#if NXFONT_MIN7BIT <= 74 && NXFONT_MAX7BIT >= 74 +NXFONT_DEFBITMAP(74); +#endif +#if NXFONT_MIN7BIT <= 75 && NXFONT_MAX7BIT >= 75 +NXFONT_DEFBITMAP(75); +#endif +#if NXFONT_MIN7BIT <= 76 && NXFONT_MAX7BIT >= 76 +NXFONT_DEFBITMAP(76); +#endif +#if NXFONT_MIN7BIT <= 77 && NXFONT_MAX7BIT >= 77 +NXFONT_DEFBITMAP(77); +#endif +#if NXFONT_MIN7BIT <= 78 && NXFONT_MAX7BIT >= 78 +NXFONT_DEFBITMAP(78); +#endif +#if NXFONT_MIN7BIT <= 79 && NXFONT_MAX7BIT >= 79 +NXFONT_DEFBITMAP(79); +#endif +#if NXFONT_MIN7BIT <= 80 && NXFONT_MAX7BIT >= 80 +NXFONT_DEFBITMAP(80); +#endif +#if NXFONT_MIN7BIT <= 81 && NXFONT_MAX7BIT >= 81 +NXFONT_DEFBITMAP(81); +#endif +#if NXFONT_MIN7BIT <= 82 && NXFONT_MAX7BIT >= 82 +NXFONT_DEFBITMAP(82); +#endif +#if NXFONT_MIN7BIT <= 83 && NXFONT_MAX7BIT >= 83 +NXFONT_DEFBITMAP(83); +#endif +#if NXFONT_MIN7BIT <= 84 && NXFONT_MAX7BIT >= 84 +NXFONT_DEFBITMAP(84); +#endif +#if NXFONT_MIN7BIT <= 85 && NXFONT_MAX7BIT >= 85 +NXFONT_DEFBITMAP(85); +#endif +#if NXFONT_MIN7BIT <= 86 && NXFONT_MAX7BIT >= 86 +NXFONT_DEFBITMAP(86); +#endif +#if NXFONT_MIN7BIT <= 87 && NXFONT_MAX7BIT >= 87 +NXFONT_DEFBITMAP(87); +#endif +#if NXFONT_MIN7BIT <= 88 && NXFONT_MAX7BIT >= 88 +NXFONT_DEFBITMAP(88); +#endif +#if NXFONT_MIN7BIT <= 89 && NXFONT_MAX7BIT >= 89 +NXFONT_DEFBITMAP(89); +#endif +#if NXFONT_MIN7BIT <= 90 && NXFONT_MAX7BIT >= 90 +NXFONT_DEFBITMAP(90); +#endif +#if NXFONT_MIN7BIT <= 91 && NXFONT_MAX7BIT >= 91 +NXFONT_DEFBITMAP(91); +#endif +#if NXFONT_MIN7BIT <= 92 && NXFONT_MAX7BIT >= 92 +NXFONT_DEFBITMAP(92); +#endif +#if NXFONT_MIN7BIT <= 93 && NXFONT_MAX7BIT >= 93 +NXFONT_DEFBITMAP(93); +#endif +#if NXFONT_MIN7BIT <= 94 && NXFONT_MAX7BIT >= 94 +NXFONT_DEFBITMAP(94); +#endif +#if NXFONT_MIN7BIT <= 95 && NXFONT_MAX7BIT >= 95 +NXFONT_DEFBITMAP(95); +#endif +#if NXFONT_MIN7BIT <= 96 && NXFONT_MAX7BIT >= 96 +NXFONT_DEFBITMAP(96); +#endif +#if NXFONT_MIN7BIT <= 97 && NXFONT_MAX7BIT >= 97 +NXFONT_DEFBITMAP(97); +#endif +#if NXFONT_MIN7BIT <= 98 && NXFONT_MAX7BIT >= 98 +NXFONT_DEFBITMAP(98); +#endif +#if NXFONT_MIN7BIT <= 99 && NXFONT_MAX7BIT >= 99 +NXFONT_DEFBITMAP(99); +#endif +#if NXFONT_MIN7BIT <= 100 && NXFONT_MAX7BIT >= 100 +NXFONT_DEFBITMAP(100); +#endif +#if NXFONT_MIN7BIT <= 101 && NXFONT_MAX7BIT >= 101 +NXFONT_DEFBITMAP(101); +#endif +#if NXFONT_MIN7BIT <= 102 && NXFONT_MAX7BIT >= 102 +NXFONT_DEFBITMAP(102); +#endif +#if NXFONT_MIN7BIT <= 103 && NXFONT_MAX7BIT >= 103 +NXFONT_DEFBITMAP(103); +#endif +#if NXFONT_MIN7BIT <= 104 && NXFONT_MAX7BIT >= 104 +NXFONT_DEFBITMAP(104); +#endif +#if NXFONT_MIN7BIT <= 105 && NXFONT_MAX7BIT >= 105 +NXFONT_DEFBITMAP(105); +#endif +#if NXFONT_MIN7BIT <= 106 && NXFONT_MAX7BIT >= 106 +NXFONT_DEFBITMAP(106); +#endif +#if NXFONT_MIN7BIT <= 107 && NXFONT_MAX7BIT >= 107 +NXFONT_DEFBITMAP(107); +#endif +#if NXFONT_MIN7BIT <= 108 && NXFONT_MAX7BIT >= 108 +NXFONT_DEFBITMAP(108); +#endif +#if NXFONT_MIN7BIT <= 109 && NXFONT_MAX7BIT >= 109 +NXFONT_DEFBITMAP(109); +#endif +#if NXFONT_MIN7BIT <= 110 && NXFONT_MAX7BIT >= 110 +NXFONT_DEFBITMAP(110); +#endif +#if NXFONT_MIN7BIT <= 111 && NXFONT_MAX7BIT >= 111 +NXFONT_DEFBITMAP(111); +#endif +#if NXFONT_MIN7BIT <= 112 && NXFONT_MAX7BIT >= 112 +NXFONT_DEFBITMAP(112); +#endif +#if NXFONT_MIN7BIT <= 113 && NXFONT_MAX7BIT >= 113 +NXFONT_DEFBITMAP(113); +#endif +#if NXFONT_MIN7BIT <= 114 && NXFONT_MAX7BIT >= 114 +NXFONT_DEFBITMAP(114); +#endif +#if NXFONT_MIN7BIT <= 115 && NXFONT_MAX7BIT >= 115 +NXFONT_DEFBITMAP(115); +#endif +#if NXFONT_MIN7BIT <= 116 && NXFONT_MAX7BIT >= 116 +NXFONT_DEFBITMAP(116); +#endif +#if NXFONT_MIN7BIT <= 117 && NXFONT_MAX7BIT >= 117 +NXFONT_DEFBITMAP(117); +#endif +#if NXFONT_MIN7BIT <= 118 && NXFONT_MAX7BIT >= 118 +NXFONT_DEFBITMAP(118); +#endif +#if NXFONT_MIN7BIT <= 119 && NXFONT_MAX7BIT >= 119 +NXFONT_DEFBITMAP(119); +#endif +#if NXFONT_MIN7BIT <= 120 && NXFONT_MAX7BIT >= 120 +NXFONT_DEFBITMAP(120); +#endif +#if NXFONT_MIN7BIT <= 121 && NXFONT_MAX7BIT >= 121 +NXFONT_DEFBITMAP(121); +#endif +#if NXFONT_MIN7BIT <= 122 && NXFONT_MAX7BIT >= 122 +NXFONT_DEFBITMAP(122); +#endif +#if NXFONT_MIN7BIT <= 123 && NXFONT_MAX7BIT >= 123 +NXFONT_DEFBITMAP(123); +#endif +#if NXFONT_MIN7BIT <= 124 && NXFONT_MAX7BIT >= 124 +NXFONT_DEFBITMAP(124); +#endif +#if NXFONT_MIN7BIT <= 125 && NXFONT_MAX7BIT >= 125 +NXFONT_DEFBITMAP(125); +#endif +#if NXFONT_MIN7BIT <= 126 && NXFONT_MAX7BIT >= 126 +NXFONT_DEFBITMAP(126); +#endif +#if NXFONT_MIN7BIT <= 127 && NXFONT_MAX7BIT >= 127 +NXFONT_DEFBITMAP(127); +#endif + +#if CONFIG_NXFONTS_CHARBITS >= 8 +#if NXFONT_MIN8BIT <= 128 && NXFONT_MAX8BIT >= 128 +NXFONT_DEFBITMAP(128); +#endif +#if NXFONT_MIN8BIT <= 129 && NXFONT_MAX8BIT >= 129 +NXFONT_DEFBITMAP(129); +#endif +#if NXFONT_MIN8BIT <= 130 && NXFONT_MAX8BIT >= 130 +NXFONT_DEFBITMAP(130); +#endif +#if NXFONT_MIN8BIT <= 131 && NXFONT_MAX8BIT >= 131 +NXFONT_DEFBITMAP(131); +#endif +#if NXFONT_MIN8BIT <= 132 && NXFONT_MAX8BIT >= 132 +NXFONT_DEFBITMAP(132); +#endif +#if NXFONT_MIN8BIT <= 133 && NXFONT_MAX8BIT >= 133 +NXFONT_DEFBITMAP(133); +#endif +#if NXFONT_MIN8BIT <= 134 && NXFONT_MAX8BIT >= 134 +NXFONT_DEFBITMAP(134); +#endif +#if NXFONT_MIN8BIT <= 135 && NXFONT_MAX8BIT >= 135 +NXFONT_DEFBITMAP(135); +#endif +#if NXFONT_MIN8BIT <= 136 && NXFONT_MAX8BIT >= 136 +NXFONT_DEFBITMAP(136); +#endif +#if NXFONT_MIN8BIT <= 137 && NXFONT_MAX8BIT >= 137 +NXFONT_DEFBITMAP(137); +#endif +#if NXFONT_MIN8BIT <= 138 && NXFONT_MAX8BIT >= 138 +NXFONT_DEFBITMAP(138); +#endif +#if NXFONT_MIN8BIT <= 139 && NXFONT_MAX8BIT >= 139 +NXFONT_DEFBITMAP(139); +#endif +#if NXFONT_MIN8BIT <= 140 && NXFONT_MAX8BIT >= 140 +NXFONT_DEFBITMAP(140); +#endif +#if NXFONT_MIN8BIT <= 141 && NXFONT_MAX8BIT >= 141 +NXFONT_DEFBITMAP(141); +#endif +#if NXFONT_MIN8BIT <= 142 && NXFONT_MAX8BIT >= 142 +NXFONT_DEFBITMAP(142); +#endif +#if NXFONT_MIN8BIT <= 143 && NXFONT_MAX8BIT >= 143 +NXFONT_DEFBITMAP(143); +#endif +#if NXFONT_MIN8BIT <= 144 && NXFONT_MAX8BIT >= 144 +NXFONT_DEFBITMAP(144); +#endif +#if NXFONT_MIN8BIT <= 145 && NXFONT_MAX8BIT >= 145 +NXFONT_DEFBITMAP(145); +#endif +#if NXFONT_MIN8BIT <= 146 && NXFONT_MAX8BIT >= 146 +NXFONT_DEFBITMAP(146); +#endif +#if NXFONT_MIN8BIT <= 147 && NXFONT_MAX8BIT >= 147 +NXFONT_DEFBITMAP(147); +#endif +#if NXFONT_MIN8BIT <= 148 && NXFONT_MAX8BIT >= 148 +NXFONT_DEFBITMAP(148); +#endif +#if NXFONT_MIN8BIT <= 149 && NXFONT_MAX8BIT >= 149 +NXFONT_DEFBITMAP(149); +#endif +#if NXFONT_MIN8BIT <= 150 && NXFONT_MAX8BIT >= 150 +NXFONT_DEFBITMAP(150); +#endif +#if NXFONT_MIN8BIT <= 151 && NXFONT_MAX8BIT >= 151 +NXFONT_DEFBITMAP(151); +#endif +#if NXFONT_MIN8BIT <= 152 && NXFONT_MAX8BIT >= 152 +NXFONT_DEFBITMAP(152); +#endif +#if NXFONT_MIN8BIT <= 153 && NXFONT_MAX8BIT >= 153 +NXFONT_DEFBITMAP(153); +#endif +#if NXFONT_MIN8BIT <= 154 && NXFONT_MAX8BIT >= 154 +NXFONT_DEFBITMAP(154); +#endif +#if NXFONT_MIN8BIT <= 155 && NXFONT_MAX8BIT >= 155 +NXFONT_DEFBITMAP(155); +#endif +#if NXFONT_MIN8BIT <= 156 && NXFONT_MAX8BIT >= 156 +NXFONT_DEFBITMAP(156); +#endif +#if NXFONT_MIN8BIT <= 157 && NXFONT_MAX8BIT >= 157 +NXFONT_DEFBITMAP(157); +#endif +#if NXFONT_MIN8BIT <= 158 && NXFONT_MAX8BIT >= 158 +NXFONT_DEFBITMAP(158); +#endif +#if NXFONT_MIN8BIT <= 159 && NXFONT_MAX8BIT >= 159 +NXFONT_DEFBITMAP(159); +#endif +#if NXFONT_MIN8BIT <= 160 && NXFONT_MAX8BIT >= 160 +NXFONT_DEFBITMAP(160); +#endif +#if NXFONT_MIN8BIT <= 161 && NXFONT_MAX8BIT >= 161 +NXFONT_DEFBITMAP(161); +#endif +#if NXFONT_MIN8BIT <= 162 && NXFONT_MAX8BIT >= 162 +NXFONT_DEFBITMAP(162); +#endif +#if NXFONT_MIN8BIT <= 163 && NXFONT_MAX8BIT >= 163 +NXFONT_DEFBITMAP(163); +#endif +#if NXFONT_MIN8BIT <= 164 && NXFONT_MAX8BIT >= 164 +NXFONT_DEFBITMAP(164); +#endif +#if NXFONT_MIN8BIT <= 165 && NXFONT_MAX8BIT >= 165 +NXFONT_DEFBITMAP(165); +#endif +#if NXFONT_MIN8BIT <= 166 && NXFONT_MAX8BIT >= 166 +NXFONT_DEFBITMAP(166); +#endif +#if NXFONT_MIN8BIT <= 167 && NXFONT_MAX8BIT >= 167 +NXFONT_DEFBITMAP(167); +#endif +#if NXFONT_MIN8BIT <= 168 && NXFONT_MAX8BIT >= 168 +NXFONT_DEFBITMAP(168); +#endif +#if NXFONT_MIN8BIT <= 169 && NXFONT_MAX8BIT >= 169 +NXFONT_DEFBITMAP(169); +#endif +#if NXFONT_MIN8BIT <= 170 && NXFONT_MAX8BIT >= 170 +NXFONT_DEFBITMAP(170); +#endif +#if NXFONT_MIN8BIT <= 171 && NXFONT_MAX8BIT >= 171 +NXFONT_DEFBITMAP(171); +#endif +#if NXFONT_MIN8BIT <= 172 && NXFONT_MAX8BIT >= 172 +NXFONT_DEFBITMAP(172); +#endif +#if NXFONT_MIN8BIT <= 173 && NXFONT_MAX8BIT >= 173 +NXFONT_DEFBITMAP(173); +#endif +#if NXFONT_MIN8BIT <= 174 && NXFONT_MAX8BIT >= 174 +NXFONT_DEFBITMAP(174); +#endif +#if NXFONT_MIN8BIT <= 175 && NXFONT_MAX8BIT >= 175 +NXFONT_DEFBITMAP(175); +#endif +#if NXFONT_MIN8BIT <= 176 && NXFONT_MAX8BIT >= 176 +NXFONT_DEFBITMAP(176); +#endif +#if NXFONT_MIN8BIT <= 177 && NXFONT_MAX8BIT >= 177 +NXFONT_DEFBITMAP(177); +#endif +#if NXFONT_MIN8BIT <= 178 && NXFONT_MAX8BIT >= 178 +NXFONT_DEFBITMAP(178); +#endif +#if NXFONT_MIN8BIT <= 179 && NXFONT_MAX8BIT >= 179 +NXFONT_DEFBITMAP(179); +#endif +#if NXFONT_MIN8BIT <= 180 && NXFONT_MAX8BIT >= 180 +NXFONT_DEFBITMAP(180); +#endif +#if NXFONT_MIN8BIT <= 181 && NXFONT_MAX8BIT >= 181 +NXFONT_DEFBITMAP(181); +#endif +#if NXFONT_MIN8BIT <= 182 && NXFONT_MAX8BIT >= 182 +NXFONT_DEFBITMAP(182); +#endif +#if NXFONT_MIN8BIT <= 183 && NXFONT_MAX8BIT >= 183 +NXFONT_DEFBITMAP(183); +#endif +#if NXFONT_MIN8BIT <= 184 && NXFONT_MAX8BIT >= 184 +NXFONT_DEFBITMAP(184); +#endif +#if NXFONT_MIN8BIT <= 185 && NXFONT_MAX8BIT >= 185 +NXFONT_DEFBITMAP(185); +#endif +#if NXFONT_MIN8BIT <= 186 && NXFONT_MAX8BIT >= 186 +NXFONT_DEFBITMAP(186); +#endif +#if NXFONT_MIN8BIT <= 187 && NXFONT_MAX8BIT >= 187 +NXFONT_DEFBITMAP(187); +#endif +#if NXFONT_MIN8BIT <= 188 && NXFONT_MAX8BIT >= 188 +NXFONT_DEFBITMAP(188); +#endif +#if NXFONT_MIN8BIT <= 189 && NXFONT_MAX8BIT >= 189 +NXFONT_DEFBITMAP(189); +#endif +#if NXFONT_MIN8BIT <= 190 && NXFONT_MAX8BIT >= 190 +NXFONT_DEFBITMAP(190); +#endif +#if NXFONT_MIN8BIT <= 191 && NXFONT_MAX8BIT >= 191 +NXFONT_DEFBITMAP(191); +#endif +#if NXFONT_MIN8BIT <= 192 && NXFONT_MAX8BIT >= 192 +NXFONT_DEFBITMAP(192); +#endif +#if NXFONT_MIN8BIT <= 193 && NXFONT_MAX8BIT >= 193 +NXFONT_DEFBITMAP(193); +#endif +#if NXFONT_MIN8BIT <= 194 && NXFONT_MAX8BIT >= 194 +NXFONT_DEFBITMAP(194); +#endif +#if NXFONT_MIN8BIT <= 195 && NXFONT_MAX8BIT >= 195 +NXFONT_DEFBITMAP(195); +#endif +#if NXFONT_MIN8BIT <= 196 && NXFONT_MAX8BIT >= 196 +NXFONT_DEFBITMAP(196); +#endif +#if NXFONT_MIN8BIT <= 197 && NXFONT_MAX8BIT >= 197 +NXFONT_DEFBITMAP(197); +#endif +#if NXFONT_MIN8BIT <= 198 && NXFONT_MAX8BIT >= 198 +NXFONT_DEFBITMAP(198); +#endif +#if NXFONT_MIN8BIT <= 199 && NXFONT_MAX8BIT >= 199 +NXFONT_DEFBITMAP(199); +#endif +#if NXFONT_MIN8BIT <= 200 && NXFONT_MAX8BIT >= 200 +NXFONT_DEFBITMAP(200); +#endif +#if NXFONT_MIN8BIT <= 201 && NXFONT_MAX8BIT >= 201 +NXFONT_DEFBITMAP(201); +#endif +#if NXFONT_MIN8BIT <= 202 && NXFONT_MAX8BIT >= 202 +NXFONT_DEFBITMAP(202); +#endif +#if NXFONT_MIN8BIT <= 203 && NXFONT_MAX8BIT >= 203 +NXFONT_DEFBITMAP(203); +#endif +#if NXFONT_MIN8BIT <= 204 && NXFONT_MAX8BIT >= 204 +NXFONT_DEFBITMAP(204); +#endif +#if NXFONT_MIN8BIT <= 205 && NXFONT_MAX8BIT >= 205 +NXFONT_DEFBITMAP(205); +#endif +#if NXFONT_MIN8BIT <= 206 && NXFONT_MAX8BIT >= 206 +NXFONT_DEFBITMAP(206); +#endif +#if NXFONT_MIN8BIT <= 207 && NXFONT_MAX8BIT >= 207 +NXFONT_DEFBITMAP(207); +#endif +#if NXFONT_MIN8BIT <= 208 && NXFONT_MAX8BIT >= 208 +NXFONT_DEFBITMAP(208); +#endif +#if NXFONT_MIN8BIT <= 209 && NXFONT_MAX8BIT >= 209 +NXFONT_DEFBITMAP(209); +#endif +#if NXFONT_MIN8BIT <= 210 && NXFONT_MAX8BIT >= 210 +NXFONT_DEFBITMAP(210); +#endif +#if NXFONT_MIN8BIT <= 211 && NXFONT_MAX8BIT >= 211 +NXFONT_DEFBITMAP(211); +#endif +#if NXFONT_MIN8BIT <= 212 && NXFONT_MAX8BIT >= 212 +NXFONT_DEFBITMAP(212); +#endif +#if NXFONT_MIN8BIT <= 213 && NXFONT_MAX8BIT >= 213 +NXFONT_DEFBITMAP(213); +#endif +#if NXFONT_MIN8BIT <= 214 && NXFONT_MAX8BIT >= 214 +NXFONT_DEFBITMAP(214); +#endif +#if NXFONT_MIN8BIT <= 215 && NXFONT_MAX8BIT >= 215 +NXFONT_DEFBITMAP(215); +#endif +#if NXFONT_MIN8BIT <= 216 && NXFONT_MAX8BIT >= 216 +NXFONT_DEFBITMAP(216); +#endif +#if NXFONT_MIN8BIT <= 217 && NXFONT_MAX8BIT >= 217 +NXFONT_DEFBITMAP(217); +#endif +#if NXFONT_MIN8BIT <= 218 && NXFONT_MAX8BIT >= 218 +NXFONT_DEFBITMAP(218); +#endif +#if NXFONT_MIN8BIT <= 219 && NXFONT_MAX8BIT >= 219 +NXFONT_DEFBITMAP(219); +#endif +#if NXFONT_MIN8BIT <= 220 && NXFONT_MAX8BIT >= 220 +NXFONT_DEFBITMAP(220); +#endif +#if NXFONT_MIN8BIT <= 221 && NXFONT_MAX8BIT >= 221 +NXFONT_DEFBITMAP(221); +#endif +#if NXFONT_MIN8BIT <= 222 && NXFONT_MAX8BIT >= 222 +NXFONT_DEFBITMAP(222); +#endif +#if NXFONT_MIN8BIT <= 223 && NXFONT_MAX8BIT >= 223 +NXFONT_DEFBITMAP(223); +#endif +#if NXFONT_MIN8BIT <= 224 && NXFONT_MAX8BIT >= 224 +NXFONT_DEFBITMAP(224); +#endif +#if NXFONT_MIN8BIT <= 225 && NXFONT_MAX8BIT >= 225 +NXFONT_DEFBITMAP(225); +#endif +#if NXFONT_MIN8BIT <= 226 && NXFONT_MAX8BIT >= 226 +NXFONT_DEFBITMAP(226); +#endif +#if NXFONT_MIN8BIT <= 227 && NXFONT_MAX8BIT >= 227 +NXFONT_DEFBITMAP(227); +#endif +#if NXFONT_MIN8BIT <= 228 && NXFONT_MAX8BIT >= 228 +NXFONT_DEFBITMAP(228); +#endif +#if NXFONT_MIN8BIT <= 229 && NXFONT_MAX8BIT >= 229 +NXFONT_DEFBITMAP(229); +#endif +#if NXFONT_MIN8BIT <= 230 && NXFONT_MAX8BIT >= 230 +NXFONT_DEFBITMAP(230); +#endif +#if NXFONT_MIN8BIT <= 231 && NXFONT_MAX8BIT >= 231 +NXFONT_DEFBITMAP(231); +#endif +#if NXFONT_MIN8BIT <= 232 && NXFONT_MAX8BIT >= 232 +NXFONT_DEFBITMAP(232); +#endif +#if NXFONT_MIN8BIT <= 233 && NXFONT_MAX8BIT >= 233 +NXFONT_DEFBITMAP(233); +#endif +#if NXFONT_MIN8BIT <= 234 && NXFONT_MAX8BIT >= 234 +NXFONT_DEFBITMAP(234); +#endif +#if NXFONT_MIN8BIT <= 235 && NXFONT_MAX8BIT >= 235 +NXFONT_DEFBITMAP(235); +#endif +#if NXFONT_MIN8BIT <= 236 && NXFONT_MAX8BIT >= 236 +NXFONT_DEFBITMAP(236); +#endif +#if NXFONT_MIN8BIT <= 237 && NXFONT_MAX8BIT >= 237 +NXFONT_DEFBITMAP(237); +#endif +#if NXFONT_MIN8BIT <= 238 && NXFONT_MAX8BIT >= 238 +NXFONT_DEFBITMAP(238); +#endif +#if NXFONT_MIN8BIT <= 239 && NXFONT_MAX8BIT >= 239 +NXFONT_DEFBITMAP(239); +#endif +#if NXFONT_MIN8BIT <= 240 && NXFONT_MAX8BIT >= 240 +NXFONT_DEFBITMAP(240); +#endif +#if NXFONT_MIN8BIT <= 241 && NXFONT_MAX8BIT >= 241 +NXFONT_DEFBITMAP(241); +#endif +#if NXFONT_MIN8BIT <= 242 && NXFONT_MAX8BIT >= 242 +NXFONT_DEFBITMAP(242); +#endif +#if NXFONT_MIN8BIT <= 243 && NXFONT_MAX8BIT >= 243 +NXFONT_DEFBITMAP(243); +#endif +#if NXFONT_MIN8BIT <= 244 && NXFONT_MAX8BIT >= 244 +NXFONT_DEFBITMAP(244); +#endif +#if NXFONT_MIN8BIT <= 245 && NXFONT_MAX8BIT >= 245 +NXFONT_DEFBITMAP(245); +#endif +#if NXFONT_MIN8BIT <= 246 && NXFONT_MAX8BIT >= 246 +NXFONT_DEFBITMAP(246); +#endif +#if NXFONT_MIN8BIT <= 247 && NXFONT_MAX8BIT >= 247 +NXFONT_DEFBITMAP(247); +#endif +#if NXFONT_MIN8BIT <= 248 && NXFONT_MAX8BIT >= 248 +NXFONT_DEFBITMAP(248); +#endif +#if NXFONT_MIN8BIT <= 249 && NXFONT_MAX8BIT >= 249 +NXFONT_DEFBITMAP(249); +#endif +#if NXFONT_MIN8BIT <= 250 && NXFONT_MAX8BIT >= 250 +NXFONT_DEFBITMAP(250); +#endif +#if NXFONT_MIN8BIT <= 251 && NXFONT_MAX8BIT >= 251 +NXFONT_DEFBITMAP(251); +#endif +#if NXFONT_MIN8BIT <= 252 && NXFONT_MAX8BIT >= 252 +NXFONT_DEFBITMAP(252); +#endif +#if NXFONT_MIN8BIT <= 253 && NXFONT_MAX8BIT >= 253 +NXFONT_DEFBITMAP(253); +#endif +#if NXFONT_MIN8BIT <= 254 && NXFONT_MAX8BIT >= 254 +NXFONT_DEFBITMAP(254); +#endif +#if NXFONT_MIN8BIT <= 255 && NXFONT_MAX8BIT >= 255 +NXFONT_DEFBITMAP(255); +#endif +#endif + +static const struct nx_fontbitmap_s NXF_SYMNAME(NXFONTS_PREFIX,7bitmaps)[NXFONT_N7BITFONTS] = +{ +#if NXFONT_MIN7BIT <= 0 && NXFONT_MAX7BIT >= 0 +NXFONT_DEFMETRIC(0), +#endif +#if NXFONT_MIN7BIT <= 1 && NXFONT_MAX7BIT >= 1 +NXFONT_DEFMETRIC(1), +#endif +#if NXFONT_MIN7BIT <= 2 && NXFONT_MAX7BIT >= 2 +NXFONT_DEFMETRIC(2), +#endif +#if NXFONT_MIN7BIT <= 3 && NXFONT_MAX7BIT >= 3 +NXFONT_DEFMETRIC(3), +#endif +#if NXFONT_MIN7BIT <= 4 && NXFONT_MAX7BIT >= 4 +NXFONT_DEFMETRIC(4), +#endif +#if NXFONT_MIN7BIT <= 5 && NXFONT_MAX7BIT >= 5 +NXFONT_DEFMETRIC(5), +#endif +#if NXFONT_MIN7BIT <= 6 && NXFONT_MAX7BIT >= 6 +NXFONT_DEFMETRIC(6), +#endif +#if NXFONT_MIN7BIT <= 7 && NXFONT_MAX7BIT >= 7 +NXFONT_DEFMETRIC(7), +#endif +#if NXFONT_MIN7BIT <= 8 && NXFONT_MAX7BIT >= 8 +NXFONT_DEFMETRIC(8), +#endif +#if NXFONT_MIN7BIT <= 9 && NXFONT_MAX7BIT >= 9 +NXFONT_DEFMETRIC(9), +#endif +#if NXFONT_MIN7BIT <= 10 && NXFONT_MAX7BIT >= 10 +NXFONT_DEFMETRIC(10), +#endif +#if NXFONT_MIN7BIT <= 11 && NXFONT_MAX7BIT >= 11 +NXFONT_DEFMETRIC(11), +#endif +#if NXFONT_MIN7BIT <= 12 && NXFONT_MAX7BIT >= 12 +NXFONT_DEFMETRIC(12), +#endif +#if NXFONT_MIN7BIT <= 13 && NXFONT_MAX7BIT >= 13 +NXFONT_DEFMETRIC(13), +#endif +#if NXFONT_MIN7BIT <= 14 && NXFONT_MAX7BIT >= 14 +NXFONT_DEFMETRIC(14), +#endif +#if NXFONT_MIN7BIT <= 15 && NXFONT_MAX7BIT >= 15 +NXFONT_DEFMETRIC(15), +#endif +#if NXFONT_MIN7BIT <= 16 && NXFONT_MAX7BIT >= 16 +NXFONT_DEFMETRIC(16), +#endif +#if NXFONT_MIN7BIT <= 17 && NXFONT_MAX7BIT >= 17 +NXFONT_DEFMETRIC(17), +#endif +#if NXFONT_MIN7BIT <= 18 && NXFONT_MAX7BIT >= 18 +NXFONT_DEFMETRIC(18), +#endif +#if NXFONT_MIN7BIT <= 19 && NXFONT_MAX7BIT >= 19 +NXFONT_DEFMETRIC(19), +#endif +#if NXFONT_MIN7BIT <= 20 && NXFONT_MAX7BIT >= 20 +NXFONT_DEFMETRIC(20), +#endif +#if NXFONT_MIN7BIT <= 21 && NXFONT_MAX7BIT >= 21 +NXFONT_DEFMETRIC(21), +#endif +#if NXFONT_MIN7BIT <= 22 && NXFONT_MAX7BIT >= 22 +NXFONT_DEFMETRIC(22), +#endif +#if NXFONT_MIN7BIT <= 23 && NXFONT_MAX7BIT >= 23 +NXFONT_DEFMETRIC(23), +#endif +#if NXFONT_MIN7BIT <= 24 && NXFONT_MAX7BIT >= 24 +NXFONT_DEFMETRIC(24), +#endif +#if NXFONT_MIN7BIT <= 25 && NXFONT_MAX7BIT >= 25 +NXFONT_DEFMETRIC(25), +#endif +#if NXFONT_MIN7BIT <= 26 && NXFONT_MAX7BIT >= 26 +NXFONT_DEFMETRIC(26), +#endif +#if NXFONT_MIN7BIT <= 27 && NXFONT_MAX7BIT >= 27 +NXFONT_DEFMETRIC(27), +#endif +#if NXFONT_MIN7BIT <= 28 && NXFONT_MAX7BIT >= 28 +NXFONT_DEFMETRIC(28), +#endif +#if NXFONT_MIN7BIT <= 29 && NXFONT_MAX7BIT >= 29 +NXFONT_DEFMETRIC(29), +#endif +#if NXFONT_MIN7BIT <= 30 && NXFONT_MAX7BIT >= 30 +NXFONT_DEFMETRIC(30), +#endif +#if NXFONT_MIN7BIT <= 31 && NXFONT_MAX7BIT >= 31 +NXFONT_DEFMETRIC(31), +#endif +#if NXFONT_MIN7BIT <= 32 && NXFONT_MAX7BIT >= 32 +NXFONT_DEFMETRIC(32), +#endif +#if NXFONT_MIN7BIT <= 33 && NXFONT_MAX7BIT >= 33 +NXFONT_DEFMETRIC(33), +#endif +#if NXFONT_MIN7BIT <= 34 && NXFONT_MAX7BIT >= 34 +NXFONT_DEFMETRIC(34), +#endif +#if NXFONT_MIN7BIT <= 35 && NXFONT_MAX7BIT >= 35 +NXFONT_DEFMETRIC(35), +#endif +#if NXFONT_MIN7BIT <= 36 && NXFONT_MAX7BIT >= 36 +NXFONT_DEFMETRIC(36), +#endif +#if NXFONT_MIN7BIT <= 37 && NXFONT_MAX7BIT >= 37 +NXFONT_DEFMETRIC(37), +#endif +#if NXFONT_MIN7BIT <= 38 && NXFONT_MAX7BIT >= 38 +NXFONT_DEFMETRIC(38), +#endif +#if NXFONT_MIN7BIT <= 39 && NXFONT_MAX7BIT >= 39 +NXFONT_DEFMETRIC(39), +#endif +#if NXFONT_MIN7BIT <= 40 && NXFONT_MAX7BIT >= 40 +NXFONT_DEFMETRIC(40), +#endif +#if NXFONT_MIN7BIT <= 41 && NXFONT_MAX7BIT >= 41 +NXFONT_DEFMETRIC(41), +#endif +#if NXFONT_MIN7BIT <= 42 && NXFONT_MAX7BIT >= 42 +NXFONT_DEFMETRIC(42), +#endif +#if NXFONT_MIN7BIT <= 43 && NXFONT_MAX7BIT >= 43 +NXFONT_DEFMETRIC(43), +#endif +#if NXFONT_MIN7BIT <= 44 && NXFONT_MAX7BIT >= 44 +NXFONT_DEFMETRIC(44), +#endif +#if NXFONT_MIN7BIT <= 45 && NXFONT_MAX7BIT >= 45 +NXFONT_DEFMETRIC(45), +#endif +#if NXFONT_MIN7BIT <= 46 && NXFONT_MAX7BIT >= 46 +NXFONT_DEFMETRIC(46), +#endif +#if NXFONT_MIN7BIT <= 47 && NXFONT_MAX7BIT >= 47 +NXFONT_DEFMETRIC(47), +#endif +#if NXFONT_MIN7BIT <= 48 && NXFONT_MAX7BIT >= 48 +NXFONT_DEFMETRIC(48), +#endif +#if NXFONT_MIN7BIT <= 49 && NXFONT_MAX7BIT >= 49 +NXFONT_DEFMETRIC(49), +#endif +#if NXFONT_MIN7BIT <= 50 && NXFONT_MAX7BIT >= 50 +NXFONT_DEFMETRIC(50), +#endif +#if NXFONT_MIN7BIT <= 51 && NXFONT_MAX7BIT >= 51 +NXFONT_DEFMETRIC(51), +#endif +#if NXFONT_MIN7BIT <= 52 && NXFONT_MAX7BIT >= 52 +NXFONT_DEFMETRIC(52), +#endif +#if NXFONT_MIN7BIT <= 53 && NXFONT_MAX7BIT >= 53 +NXFONT_DEFMETRIC(53), +#endif +#if NXFONT_MIN7BIT <= 54 && NXFONT_MAX7BIT >= 54 +NXFONT_DEFMETRIC(54), +#endif +#if NXFONT_MIN7BIT <= 55 && NXFONT_MAX7BIT >= 55 +NXFONT_DEFMETRIC(55), +#endif +#if NXFONT_MIN7BIT <= 56 && NXFONT_MAX7BIT >= 56 +NXFONT_DEFMETRIC(56), +#endif +#if NXFONT_MIN7BIT <= 57 && NXFONT_MAX7BIT >= 57 +NXFONT_DEFMETRIC(57), +#endif +#if NXFONT_MIN7BIT <= 58 && NXFONT_MAX7BIT >= 58 +NXFONT_DEFMETRIC(58), +#endif +#if NXFONT_MIN7BIT <= 59 && NXFONT_MAX7BIT >= 59 +NXFONT_DEFMETRIC(59), +#endif +#if NXFONT_MIN7BIT <= 60 && NXFONT_MAX7BIT >= 60 +NXFONT_DEFMETRIC(60), +#endif +#if NXFONT_MIN7BIT <= 61 && NXFONT_MAX7BIT >= 61 +NXFONT_DEFMETRIC(61), +#endif +#if NXFONT_MIN7BIT <= 62 && NXFONT_MAX7BIT >= 62 +NXFONT_DEFMETRIC(62), +#endif +#if NXFONT_MIN7BIT <= 63 && NXFONT_MAX7BIT >= 63 +NXFONT_DEFMETRIC(63), +#endif +#if NXFONT_MIN7BIT <= 64 && NXFONT_MAX7BIT >= 64 +NXFONT_DEFMETRIC(64), +#endif +#if NXFONT_MIN7BIT <= 65 && NXFONT_MAX7BIT >= 65 +NXFONT_DEFMETRIC(65), +#endif +#if NXFONT_MIN7BIT <= 66 && NXFONT_MAX7BIT >= 66 +NXFONT_DEFMETRIC(66), +#endif +#if NXFONT_MIN7BIT <= 67 && NXFONT_MAX7BIT >= 67 +NXFONT_DEFMETRIC(67), +#endif +#if NXFONT_MIN7BIT <= 68 && NXFONT_MAX7BIT >= 68 +NXFONT_DEFMETRIC(68), +#endif +#if NXFONT_MIN7BIT <= 69 && NXFONT_MAX7BIT >= 69 +NXFONT_DEFMETRIC(69), +#endif +#if NXFONT_MIN7BIT <= 70 && NXFONT_MAX7BIT >= 70 +NXFONT_DEFMETRIC(70), +#endif +#if NXFONT_MIN7BIT <= 71 && NXFONT_MAX7BIT >= 71 +NXFONT_DEFMETRIC(71), +#endif +#if NXFONT_MIN7BIT <= 72 && NXFONT_MAX7BIT >= 72 +NXFONT_DEFMETRIC(72), +#endif +#if NXFONT_MIN7BIT <= 73 && NXFONT_MAX7BIT >= 73 +NXFONT_DEFMETRIC(73), +#endif +#if NXFONT_MIN7BIT <= 74 && NXFONT_MAX7BIT >= 74 +NXFONT_DEFMETRIC(74), +#endif +#if NXFONT_MIN7BIT <= 75 && NXFONT_MAX7BIT >= 75 +NXFONT_DEFMETRIC(75), +#endif +#if NXFONT_MIN7BIT <= 76 && NXFONT_MAX7BIT >= 76 +NXFONT_DEFMETRIC(76), +#endif +#if NXFONT_MIN7BIT <= 77 && NXFONT_MAX7BIT >= 77 +NXFONT_DEFMETRIC(77), +#endif +#if NXFONT_MIN7BIT <= 78 && NXFONT_MAX7BIT >= 78 +NXFONT_DEFMETRIC(78), +#endif +#if NXFONT_MIN7BIT <= 79 && NXFONT_MAX7BIT >= 79 +NXFONT_DEFMETRIC(79), +#endif +#if NXFONT_MIN7BIT <= 80 && NXFONT_MAX7BIT >= 80 +NXFONT_DEFMETRIC(80), +#endif +#if NXFONT_MIN7BIT <= 81 && NXFONT_MAX7BIT >= 81 +NXFONT_DEFMETRIC(81), +#endif +#if NXFONT_MIN7BIT <= 82 && NXFONT_MAX7BIT >= 82 +NXFONT_DEFMETRIC(82), +#endif +#if NXFONT_MIN7BIT <= 83 && NXFONT_MAX7BIT >= 83 +NXFONT_DEFMETRIC(83), +#endif +#if NXFONT_MIN7BIT <= 84 && NXFONT_MAX7BIT >= 84 +NXFONT_DEFMETRIC(84), +#endif +#if NXFONT_MIN7BIT <= 85 && NXFONT_MAX7BIT >= 85 +NXFONT_DEFMETRIC(85), +#endif +#if NXFONT_MIN7BIT <= 86 && NXFONT_MAX7BIT >= 86 +NXFONT_DEFMETRIC(86), +#endif +#if NXFONT_MIN7BIT <= 87 && NXFONT_MAX7BIT >= 87 +NXFONT_DEFMETRIC(87), +#endif +#if NXFONT_MIN7BIT <= 88 && NXFONT_MAX7BIT >= 88 +NXFONT_DEFMETRIC(88), +#endif +#if NXFONT_MIN7BIT <= 89 && NXFONT_MAX7BIT >= 89 +NXFONT_DEFMETRIC(89), +#endif +#if NXFONT_MIN7BIT <= 90 && NXFONT_MAX7BIT >= 90 +NXFONT_DEFMETRIC(90), +#endif +#if NXFONT_MIN7BIT <= 91 && NXFONT_MAX7BIT >= 91 +NXFONT_DEFMETRIC(91), +#endif +#if NXFONT_MIN7BIT <= 92 && NXFONT_MAX7BIT >= 92 +NXFONT_DEFMETRIC(92), +#endif +#if NXFONT_MIN7BIT <= 93 && NXFONT_MAX7BIT >= 93 +NXFONT_DEFMETRIC(93), +#endif +#if NXFONT_MIN7BIT <= 94 && NXFONT_MAX7BIT >= 94 +NXFONT_DEFMETRIC(94), +#endif +#if NXFONT_MIN7BIT <= 95 && NXFONT_MAX7BIT >= 95 +NXFONT_DEFMETRIC(95), +#endif +#if NXFONT_MIN7BIT <= 96 && NXFONT_MAX7BIT >= 96 +NXFONT_DEFMETRIC(96), +#endif +#if NXFONT_MIN7BIT <= 97 && NXFONT_MAX7BIT >= 97 +NXFONT_DEFMETRIC(97), +#endif +#if NXFONT_MIN7BIT <= 98 && NXFONT_MAX7BIT >= 98 +NXFONT_DEFMETRIC(98), +#endif +#if NXFONT_MIN7BIT <= 99 && NXFONT_MAX7BIT >= 99 +NXFONT_DEFMETRIC(99), +#endif +#if NXFONT_MIN7BIT <= 100 && NXFONT_MAX7BIT >= 100 +NXFONT_DEFMETRIC(100), +#endif +#if NXFONT_MIN7BIT <= 101 && NXFONT_MAX7BIT >= 101 +NXFONT_DEFMETRIC(101), +#endif +#if NXFONT_MIN7BIT <= 102 && NXFONT_MAX7BIT >= 102 +NXFONT_DEFMETRIC(102), +#endif +#if NXFONT_MIN7BIT <= 103 && NXFONT_MAX7BIT >= 103 +NXFONT_DEFMETRIC(103), +#endif +#if NXFONT_MIN7BIT <= 104 && NXFONT_MAX7BIT >= 104 +NXFONT_DEFMETRIC(104), +#endif +#if NXFONT_MIN7BIT <= 105 && NXFONT_MAX7BIT >= 105 +NXFONT_DEFMETRIC(105), +#endif +#if NXFONT_MIN7BIT <= 106 && NXFONT_MAX7BIT >= 106 +NXFONT_DEFMETRIC(106), +#endif +#if NXFONT_MIN7BIT <= 107 && NXFONT_MAX7BIT >= 107 +NXFONT_DEFMETRIC(107), +#endif +#if NXFONT_MIN7BIT <= 108 && NXFONT_MAX7BIT >= 108 +NXFONT_DEFMETRIC(108), +#endif +#if NXFONT_MIN7BIT <= 109 && NXFONT_MAX7BIT >= 109 +NXFONT_DEFMETRIC(109), +#endif +#if NXFONT_MIN7BIT <= 110 && NXFONT_MAX7BIT >= 110 +NXFONT_DEFMETRIC(110), +#endif +#if NXFONT_MIN7BIT <= 111 && NXFONT_MAX7BIT >= 111 +NXFONT_DEFMETRIC(111), +#endif +#if NXFONT_MIN7BIT <= 112 && NXFONT_MAX7BIT >= 112 +NXFONT_DEFMETRIC(112), +#endif +#if NXFONT_MIN7BIT <= 113 && NXFONT_MAX7BIT >= 113 +NXFONT_DEFMETRIC(113), +#endif +#if NXFONT_MIN7BIT <= 114 && NXFONT_MAX7BIT >= 114 +NXFONT_DEFMETRIC(114), +#endif +#if NXFONT_MIN7BIT <= 115 && NXFONT_MAX7BIT >= 115 +NXFONT_DEFMETRIC(115), +#endif +#if NXFONT_MIN7BIT <= 116 && NXFONT_MAX7BIT >= 116 +NXFONT_DEFMETRIC(116), +#endif +#if NXFONT_MIN7BIT <= 117 && NXFONT_MAX7BIT >= 117 +NXFONT_DEFMETRIC(117), +#endif +#if NXFONT_MIN7BIT <= 118 && NXFONT_MAX7BIT >= 118 +NXFONT_DEFMETRIC(118), +#endif +#if NXFONT_MIN7BIT <= 119 && NXFONT_MAX7BIT >= 119 +NXFONT_DEFMETRIC(119), +#endif +#if NXFONT_MIN7BIT <= 120 && NXFONT_MAX7BIT >= 120 +NXFONT_DEFMETRIC(120), +#endif +#if NXFONT_MIN7BIT <= 121 && NXFONT_MAX7BIT >= 121 +NXFONT_DEFMETRIC(121), +#endif +#if NXFONT_MIN7BIT <= 122 && NXFONT_MAX7BIT >= 122 +NXFONT_DEFMETRIC(122), +#endif +#if NXFONT_MIN7BIT <= 123 && NXFONT_MAX7BIT >= 123 +NXFONT_DEFMETRIC(123), +#endif +#if NXFONT_MIN7BIT <= 124 && NXFONT_MAX7BIT >= 124 +NXFONT_DEFMETRIC(124), +#endif +#if NXFONT_MIN7BIT <= 125 && NXFONT_MAX7BIT >= 125 +NXFONT_DEFMETRIC(125), +#endif +#if NXFONT_MIN7BIT <= 126 && NXFONT_MAX7BIT >= 126 +NXFONT_DEFMETRIC(126), +#endif +#if NXFONT_MIN7BIT <= 127 && NXFONT_MAX7BIT >= 127 +NXFONT_DEFMETRIC(127), +#endif +}; + +#if CONFIG_NXFONTS_CHARBITS >= 8 +static const struct nx_fontbitmap_s NXF_SYMNAME(NXFONTS_PREFIX,8bitmaps)[NXFONT_N8BITFONTS] = +{ +#if NXFONT_MIN8BIT <= 128 && NXFONT_MAX8BIT >= 128 +NXFONT_DEFMETRIC(128), +#endif +#if NXFONT_MIN8BIT <= 129 && NXFONT_MAX8BIT >= 129 +NXFONT_DEFMETRIC(129), +#endif +#if NXFONT_MIN8BIT <= 130 && NXFONT_MAX8BIT >= 130 +NXFONT_DEFMETRIC(130), +#endif +#if NXFONT_MIN8BIT <= 131 && NXFONT_MAX8BIT >= 131 +NXFONT_DEFMETRIC(131), +#endif +#if NXFONT_MIN8BIT <= 132 && NXFONT_MAX8BIT >= 132 +NXFONT_DEFMETRIC(132), +#endif +#if NXFONT_MIN8BIT <= 133 && NXFONT_MAX8BIT >= 133 +NXFONT_DEFMETRIC(133), +#endif +#if NXFONT_MIN8BIT <= 134 && NXFONT_MAX8BIT >= 134 +NXFONT_DEFMETRIC(134), +#endif +#if NXFONT_MIN8BIT <= 135 && NXFONT_MAX8BIT >= 135 +NXFONT_DEFMETRIC(135), +#endif +#if NXFONT_MIN8BIT <= 136 && NXFONT_MAX8BIT >= 136 +NXFONT_DEFMETRIC(136), +#endif +#if NXFONT_MIN8BIT <= 137 && NXFONT_MAX8BIT >= 137 +NXFONT_DEFMETRIC(137), +#endif +#if NXFONT_MIN8BIT <= 138 && NXFONT_MAX8BIT >= 138 +NXFONT_DEFMETRIC(138), +#endif +#if NXFONT_MIN8BIT <= 139 && NXFONT_MAX8BIT >= 139 +NXFONT_DEFMETRIC(139), +#endif +#if NXFONT_MIN8BIT <= 140 && NXFONT_MAX8BIT >= 140 +NXFONT_DEFMETRIC(140), +#endif +#if NXFONT_MIN8BIT <= 141 && NXFONT_MAX8BIT >= 141 +NXFONT_DEFMETRIC(141), +#endif +#if NXFONT_MIN8BIT <= 142 && NXFONT_MAX8BIT >= 142 +NXFONT_DEFMETRIC(142), +#endif +#if NXFONT_MIN8BIT <= 143 && NXFONT_MAX8BIT >= 143 +NXFONT_DEFMETRIC(143), +#endif +#if NXFONT_MIN8BIT <= 144 && NXFONT_MAX8BIT >= 144 +NXFONT_DEFMETRIC(144), +#endif +#if NXFONT_MIN8BIT <= 145 && NXFONT_MAX8BIT >= 145 +NXFONT_DEFMETRIC(145), +#endif +#if NXFONT_MIN8BIT <= 146 && NXFONT_MAX8BIT >= 146 +NXFONT_DEFMETRIC(146), +#endif +#if NXFONT_MIN8BIT <= 147 && NXFONT_MAX8BIT >= 147 +NXFONT_DEFMETRIC(147), +#endif +#if NXFONT_MIN8BIT <= 148 && NXFONT_MAX8BIT >= 148 +NXFONT_DEFMETRIC(148), +#endif +#if NXFONT_MIN8BIT <= 149 && NXFONT_MAX8BIT >= 149 +NXFONT_DEFMETRIC(149), +#endif +#if NXFONT_MIN8BIT <= 150 && NXFONT_MAX8BIT >= 150 +NXFONT_DEFMETRIC(150), +#endif +#if NXFONT_MIN8BIT <= 151 && NXFONT_MAX8BIT >= 151 +NXFONT_DEFMETRIC(151), +#endif +#if NXFONT_MIN8BIT <= 152 && NXFONT_MAX8BIT >= 152 +NXFONT_DEFMETRIC(152), +#endif +#if NXFONT_MIN8BIT <= 153 && NXFONT_MAX8BIT >= 153 +NXFONT_DEFMETRIC(153), +#endif +#if NXFONT_MIN8BIT <= 154 && NXFONT_MAX8BIT >= 154 +NXFONT_DEFMETRIC(154), +#endif +#if NXFONT_MIN8BIT <= 155 && NXFONT_MAX8BIT >= 155 +NXFONT_DEFMETRIC(155), +#endif +#if NXFONT_MIN8BIT <= 156 && NXFONT_MAX8BIT >= 156 +NXFONT_DEFMETRIC(156), +#endif +#if NXFONT_MIN8BIT <= 157 && NXFONT_MAX8BIT >= 157 +NXFONT_DEFMETRIC(157), +#endif +#if NXFONT_MIN8BIT <= 158 && NXFONT_MAX8BIT >= 158 +NXFONT_DEFMETRIC(158), +#endif +#if NXFONT_MIN8BIT <= 159 && NXFONT_MAX8BIT >= 159 +NXFONT_DEFMETRIC(159), +#endif +#if NXFONT_MIN8BIT <= 160 && NXFONT_MAX8BIT >= 160 +NXFONT_DEFMETRIC(160), +#endif +#if NXFONT_MIN8BIT <= 161 && NXFONT_MAX8BIT >= 161 +NXFONT_DEFMETRIC(161), +#endif +#if NXFONT_MIN8BIT <= 162 && NXFONT_MAX8BIT >= 162 +NXFONT_DEFMETRIC(162), +#endif +#if NXFONT_MIN8BIT <= 163 && NXFONT_MAX8BIT >= 163 +NXFONT_DEFMETRIC(163), +#endif +#if NXFONT_MIN8BIT <= 164 && NXFONT_MAX8BIT >= 164 +NXFONT_DEFMETRIC(164), +#endif +#if NXFONT_MIN8BIT <= 165 && NXFONT_MAX8BIT >= 165 +NXFONT_DEFMETRIC(165), +#endif +#if NXFONT_MIN8BIT <= 166 && NXFONT_MAX8BIT >= 166 +NXFONT_DEFMETRIC(166), +#endif +#if NXFONT_MIN8BIT <= 167 && NXFONT_MAX8BIT >= 167 +NXFONT_DEFMETRIC(167), +#endif +#if NXFONT_MIN8BIT <= 168 && NXFONT_MAX8BIT >= 168 +NXFONT_DEFMETRIC(168), +#endif +#if NXFONT_MIN8BIT <= 169 && NXFONT_MAX8BIT >= 169 +NXFONT_DEFMETRIC(169), +#endif +#if NXFONT_MIN8BIT <= 170 && NXFONT_MAX8BIT >= 170 +NXFONT_DEFMETRIC(170), +#endif +#if NXFONT_MIN8BIT <= 171 && NXFONT_MAX8BIT >= 171 +NXFONT_DEFMETRIC(171), +#endif +#if NXFONT_MIN8BIT <= 172 && NXFONT_MAX8BIT >= 172 +NXFONT_DEFMETRIC(172), +#endif +#if NXFONT_MIN8BIT <= 173 && NXFONT_MAX8BIT >= 173 +NXFONT_DEFMETRIC(173), +#endif +#if NXFONT_MIN8BIT <= 174 && NXFONT_MAX8BIT >= 174 +NXFONT_DEFMETRIC(174), +#endif +#if NXFONT_MIN8BIT <= 175 && NXFONT_MAX8BIT >= 175 +NXFONT_DEFMETRIC(175), +#endif +#if NXFONT_MIN8BIT <= 176 && NXFONT_MAX8BIT >= 176 +NXFONT_DEFMETRIC(176), +#endif +#if NXFONT_MIN8BIT <= 177 && NXFONT_MAX8BIT >= 177 +NXFONT_DEFMETRIC(177), +#endif +#if NXFONT_MIN8BIT <= 178 && NXFONT_MAX8BIT >= 178 +NXFONT_DEFMETRIC(178), +#endif +#if NXFONT_MIN8BIT <= 179 && NXFONT_MAX8BIT >= 179 +NXFONT_DEFMETRIC(179), +#endif +#if NXFONT_MIN8BIT <= 180 && NXFONT_MAX8BIT >= 180 +NXFONT_DEFMETRIC(180), +#endif +#if NXFONT_MIN8BIT <= 181 && NXFONT_MAX8BIT >= 181 +NXFONT_DEFMETRIC(181), +#endif +#if NXFONT_MIN8BIT <= 182 && NXFONT_MAX8BIT >= 182 +NXFONT_DEFMETRIC(182), +#endif +#if NXFONT_MIN8BIT <= 183 && NXFONT_MAX8BIT >= 183 +NXFONT_DEFMETRIC(183), +#endif +#if NXFONT_MIN8BIT <= 184 && NXFONT_MAX8BIT >= 184 +NXFONT_DEFMETRIC(184), +#endif +#if NXFONT_MIN8BIT <= 185 && NXFONT_MAX8BIT >= 185 +NXFONT_DEFMETRIC(185), +#endif +#if NXFONT_MIN8BIT <= 186 && NXFONT_MAX8BIT >= 186 +NXFONT_DEFMETRIC(186), +#endif +#if NXFONT_MIN8BIT <= 187 && NXFONT_MAX8BIT >= 187 +NXFONT_DEFMETRIC(187), +#endif +#if NXFONT_MIN8BIT <= 188 && NXFONT_MAX8BIT >= 188 +NXFONT_DEFMETRIC(188), +#endif +#if NXFONT_MIN8BIT <= 189 && NXFONT_MAX8BIT >= 189 +NXFONT_DEFMETRIC(189), +#endif +#if NXFONT_MIN8BIT <= 190 && NXFONT_MAX8BIT >= 190 +NXFONT_DEFMETRIC(190), +#endif +#if NXFONT_MIN8BIT <= 191 && NXFONT_MAX8BIT >= 191 +NXFONT_DEFMETRIC(191), +#endif +#if NXFONT_MIN8BIT <= 192 && NXFONT_MAX8BIT >= 192 +NXFONT_DEFMETRIC(192), +#endif +#if NXFONT_MIN8BIT <= 193 && NXFONT_MAX8BIT >= 193 +NXFONT_DEFMETRIC(193), +#endif +#if NXFONT_MIN8BIT <= 194 && NXFONT_MAX8BIT >= 194 +NXFONT_DEFMETRIC(194), +#endif +#if NXFONT_MIN8BIT <= 195 && NXFONT_MAX8BIT >= 195 +NXFONT_DEFMETRIC(195), +#endif +#if NXFONT_MIN8BIT <= 196 && NXFONT_MAX8BIT >= 196 +NXFONT_DEFMETRIC(196), +#endif +#if NXFONT_MIN8BIT <= 197 && NXFONT_MAX8BIT >= 197 +NXFONT_DEFMETRIC(197), +#endif +#if NXFONT_MIN8BIT <= 198 && NXFONT_MAX8BIT >= 198 +NXFONT_DEFMETRIC(198), +#endif +#if NXFONT_MIN8BIT <= 199 && NXFONT_MAX8BIT >= 199 +NXFONT_DEFMETRIC(199), +#endif +#if NXFONT_MIN8BIT <= 200 && NXFONT_MAX8BIT >= 200 +NXFONT_DEFMETRIC(200), +#endif +#if NXFONT_MIN8BIT <= 201 && NXFONT_MAX8BIT >= 201 +NXFONT_DEFMETRIC(201), +#endif +#if NXFONT_MIN8BIT <= 202 && NXFONT_MAX8BIT >= 202 +NXFONT_DEFMETRIC(202), +#endif +#if NXFONT_MIN8BIT <= 203 && NXFONT_MAX8BIT >= 203 +NXFONT_DEFMETRIC(203), +#endif +#if NXFONT_MIN8BIT <= 204 && NXFONT_MAX8BIT >= 204 +NXFONT_DEFMETRIC(204), +#endif +#if NXFONT_MIN8BIT <= 205 && NXFONT_MAX8BIT >= 205 +NXFONT_DEFMETRIC(205), +#endif +#if NXFONT_MIN8BIT <= 206 && NXFONT_MAX8BIT >= 206 +NXFONT_DEFMETRIC(206), +#endif +#if NXFONT_MIN8BIT <= 207 && NXFONT_MAX8BIT >= 207 +NXFONT_DEFMETRIC(207), +#endif +#if NXFONT_MIN8BIT <= 208 && NXFONT_MAX8BIT >= 208 +NXFONT_DEFMETRIC(208), +#endif +#if NXFONT_MIN8BIT <= 209 && NXFONT_MAX8BIT >= 209 +NXFONT_DEFMETRIC(209), +#endif +#if NXFONT_MIN8BIT <= 210 && NXFONT_MAX8BIT >= 210 +NXFONT_DEFMETRIC(210), +#endif +#if NXFONT_MIN8BIT <= 211 && NXFONT_MAX8BIT >= 211 +NXFONT_DEFMETRIC(211), +#endif +#if NXFONT_MIN8BIT <= 212 && NXFONT_MAX8BIT >= 212 +NXFONT_DEFMETRIC(212), +#endif +#if NXFONT_MIN8BIT <= 213 && NXFONT_MAX8BIT >= 213 +NXFONT_DEFMETRIC(213), +#endif +#if NXFONT_MIN8BIT <= 214 && NXFONT_MAX8BIT >= 214 +NXFONT_DEFMETRIC(214), +#endif +#if NXFONT_MIN8BIT <= 215 && NXFONT_MAX8BIT >= 215 +NXFONT_DEFMETRIC(215), +#endif +#if NXFONT_MIN8BIT <= 216 && NXFONT_MAX8BIT >= 216 +NXFONT_DEFMETRIC(216), +#endif +#if NXFONT_MIN8BIT <= 217 && NXFONT_MAX8BIT >= 217 +NXFONT_DEFMETRIC(217), +#endif +#if NXFONT_MIN8BIT <= 218 && NXFONT_MAX8BIT >= 218 +NXFONT_DEFMETRIC(218), +#endif +#if NXFONT_MIN8BIT <= 219 && NXFONT_MAX8BIT >= 219 +NXFONT_DEFMETRIC(219), +#endif +#if NXFONT_MIN8BIT <= 220 && NXFONT_MAX8BIT >= 220 +NXFONT_DEFMETRIC(220), +#endif +#if NXFONT_MIN8BIT <= 221 && NXFONT_MAX8BIT >= 221 +NXFONT_DEFMETRIC(221), +#endif +#if NXFONT_MIN8BIT <= 222 && NXFONT_MAX8BIT >= 222 +NXFONT_DEFMETRIC(222), +#endif +#if NXFONT_MIN8BIT <= 223 && NXFONT_MAX8BIT >= 223 +NXFONT_DEFMETRIC(223), +#endif +#if NXFONT_MIN8BIT <= 224 && NXFONT_MAX8BIT >= 224 +NXFONT_DEFMETRIC(224), +#endif +#if NXFONT_MIN8BIT <= 225 && NXFONT_MAX8BIT >= 225 +NXFONT_DEFMETRIC(225), +#endif +#if NXFONT_MIN8BIT <= 226 && NXFONT_MAX8BIT >= 226 +NXFONT_DEFMETRIC(226), +#endif +#if NXFONT_MIN8BIT <= 227 && NXFONT_MAX8BIT >= 227 +NXFONT_DEFMETRIC(227), +#endif +#if NXFONT_MIN8BIT <= 228 && NXFONT_MAX8BIT >= 228 +NXFONT_DEFMETRIC(228), +#endif +#if NXFONT_MIN8BIT <= 229 && NXFONT_MAX8BIT >= 229 +NXFONT_DEFMETRIC(229), +#endif +#if NXFONT_MIN8BIT <= 230 && NXFONT_MAX8BIT >= 230 +NXFONT_DEFMETRIC(230), +#endif +#if NXFONT_MIN8BIT <= 231 && NXFONT_MAX8BIT >= 231 +NXFONT_DEFMETRIC(231), +#endif +#if NXFONT_MIN8BIT <= 232 && NXFONT_MAX8BIT >= 232 +NXFONT_DEFMETRIC(232), +#endif +#if NXFONT_MIN8BIT <= 233 && NXFONT_MAX8BIT >= 233 +NXFONT_DEFMETRIC(233), +#endif +#if NXFONT_MIN8BIT <= 234 && NXFONT_MAX8BIT >= 234 +NXFONT_DEFMETRIC(234), +#endif +#if NXFONT_MIN8BIT <= 235 && NXFONT_MAX8BIT >= 235 +NXFONT_DEFMETRIC(235), +#endif +#if NXFONT_MIN8BIT <= 236 && NXFONT_MAX8BIT >= 236 +NXFONT_DEFMETRIC(236), +#endif +#if NXFONT_MIN8BIT <= 237 && NXFONT_MAX8BIT >= 237 +NXFONT_DEFMETRIC(237), +#endif +#if NXFONT_MIN8BIT <= 238 && NXFONT_MAX8BIT >= 238 +NXFONT_DEFMETRIC(238), +#endif +#if NXFONT_MIN8BIT <= 239 && NXFONT_MAX8BIT >= 239 +NXFONT_DEFMETRIC(239), +#endif +#if NXFONT_MIN8BIT <= 240 && NXFONT_MAX8BIT >= 240 +NXFONT_DEFMETRIC(240), +#endif +#if NXFONT_MIN8BIT <= 241 && NXFONT_MAX8BIT >= 241 +NXFONT_DEFMETRIC(241), +#endif +#if NXFONT_MIN8BIT <= 242 && NXFONT_MAX8BIT >= 242 +NXFONT_DEFMETRIC(242), +#endif +#if NXFONT_MIN8BIT <= 243 && NXFONT_MAX8BIT >= 243 +NXFONT_DEFMETRIC(243), +#endif +#if NXFONT_MIN8BIT <= 244 && NXFONT_MAX8BIT >= 244 +NXFONT_DEFMETRIC(244), +#endif +#if NXFONT_MIN8BIT <= 245 && NXFONT_MAX8BIT >= 245 +NXFONT_DEFMETRIC(245), +#endif +#if NXFONT_MIN8BIT <= 246 && NXFONT_MAX8BIT >= 246 +NXFONT_DEFMETRIC(246), +#endif +#if NXFONT_MIN8BIT <= 247 && NXFONT_MAX8BIT >= 247 +NXFONT_DEFMETRIC(247), +#endif +#if NXFONT_MIN8BIT <= 248 && NXFONT_MAX8BIT >= 248 +NXFONT_DEFMETRIC(248), +#endif +#if NXFONT_MIN8BIT <= 249 && NXFONT_MAX8BIT >= 249 +NXFONT_DEFMETRIC(249), +#endif +#if NXFONT_MIN8BIT <= 250 && NXFONT_MAX8BIT >= 250 +NXFONT_DEFMETRIC(250), +#endif +#if NXFONT_MIN8BIT <= 251 && NXFONT_MAX8BIT >= 251 +NXFONT_DEFMETRIC(251), +#endif +#if NXFONT_MIN8BIT <= 252 && NXFONT_MAX8BIT >= 252 +NXFONT_DEFMETRIC(252), +#endif +#if NXFONT_MIN8BIT <= 253 && NXFONT_MAX8BIT >= 253 +NXFONT_DEFMETRIC(253), +#endif +#if NXFONT_MIN8BIT <= 254 && NXFONT_MAX8BIT >= 254 +NXFONT_DEFMETRIC(254), +#endif +#if NXFONT_MIN8BIT <= 255 && NXFONT_MAX8BIT >= 255 +NXFONT_DEFMETRIC(255), +#endif +}; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct nx_fontpackage_s NXF_SYMNAME(NXFONTS_PREFIX,package) = +{ + NXFONT_ID, /* The font ID */ + { /* Font set metrics: */ + NXFONT_MAXHEIGHT, /* Max. height of a glyph in rows */ + NXFONT_MAXWIDTH, /* Max. width of a glyph in pixels */ + CONFIG_NXFONTS_CHARBITS, /* Max number of bits per character code */ + NXFONT_SPACEWIDTH, /* The width of a space in pixels */ + }, + { /* Fonts for 7-bit encoding */ + NXFONT_MIN7BIT, /* First glyph code */ + NXFONT_N7BITFONTS, /* Number of bitmap glyphs */ + NXF_SYMNAME(NXFONTS_PREFIX,7bitmaps) /* List of glyphs */ + } +#if CONFIG_NXFONTS_CHARBITS >= 8 +, { /* Fonts for 8-bit encoding */ + NXFONT_MIN8BIT, /* First glyph code */ + NXFONT_N8BITFONTS, /* Number of bitmap glyphs */ + NXF_SYMNAME(NXFONTS_PREFIX,8bitmaps) /* List of glyphs */ + } +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + diff --git a/nuttx/graphics/nxfonts/nxfonts_convert.c b/nuttx/graphics/nxfonts/nxfonts_convert.c new file mode 100644 index 0000000000..00cd61a6cd --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_convert.c @@ -0,0 +1,290 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_convert.c + * + * Copyright (C) 2008-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfonts_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Make sure the bits-per-pixel value has been set */ + +#ifndef NXFONTS_BITSPERPIXEL +# error "NXFONTS_BITSPERPIXEL must be defined on the command line" +#endif + +/* Set up bit blit macros for this BPP */ + +#if NXFONTS_BITSPERPIXEL == 1 + +# define NXF_PIXELMASK 0x01 +# define NXF_SCALEX(x) ((x) >> 3) +# define NXF_PIXEL_T uint8_t +# define NXF_MULTIPIXEL(p) ((p) ? 0xff : 0x00) + +#elif NXFONTS_BITSPERPIXEL == 2 + +# define NXF_PIXELMASK 0x03 +# define NXF_SCALEX(x) ((x) >> 2) +# define NXF_PIXEL_T uint8_t +# define NXF_MULTIPIXEL(p) ((uint8_t)(p) << 6 | (uint8_t)(p) << 4 | (uint8_t)(p) << 2 | (p)) + +#elif NXFONTS_BITSPERPIXEL == 4 + +# define NXF_PIXELMASK 0x0f +# define NXF_SCALEX(x) ((x) >> 1) +# define NXF_PIXEL_T uint8_t +# define NXF_MULTIPIXEL(p) ((uint8_t)(p) << 4 | (p)) + +#elif NXFONTS_BITSPERPIXEL == 8 + +# define NXF_SCALEX(x) (x) +# define NXF_PIXEL_T uint8_t + +#elif NXFONTS_BITSPERPIXEL == 16 + +# define NXF_SCALEX(x) ((x) << 1) +# define NXF_PIXEL_T uint16_t + +#elif NXFONTS_BITSPERPIXEL == 24 + +# define NXF_SCALEX(x) (((x) << 1) + (x)) +# define NXF_PIXEL_T uint32_t + +#elif NXFONTS_BITSPERPIXEL == 32 + +# define NXF_SCALEX(x) ((x) << 2) +# define NXF_PIXEL_T uint32_t + +#endif + +#if NXFONTS_BITSPERPIXEL < 8 +# ifdef CONFIG_NX_PACKEDMSFIRST +# define NXF_INITMASK (NXF_PIXELMASK << (8 - NXFONTS_BITSPERPIXEL)) +# else +# define NXF_INITMASK NXF_PIXELMASK +# endif +#endif + +/* Form a function name by concatenating two strings */ + +#define _NXF_FUNCNAME(a,b) a ## b +#define NXF_FUNCNAME(a,b) _NXF_FUNCNAME(a,b) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxf_convert_*bpp + * + * Description: + * Convert the 1BPP font to a new pixel depth + * + * Input Parameters: + * dest - The destination buffer provided by the caller. + * height - The max height of the returned char in rows + * width - The max width of the returned char in pixels + * stride - The width of the destination buffer in bytes + * bm - Describes the character glyph to convert + * color - The color to use for '1' bits in the font bitmap + * (0 bits are transparent) + * + * Returned Value: + * OK on Success, ERROR: on failure with errno set appropriately. + * (never fails) + * + ****************************************************************************/ + +int NXF_FUNCNAME(nxf_convert,NXFONTS_SUFFIX) +(FAR NXF_PIXEL_T *dest, uint16_t height, uint16_t width, uint16_t stride, + FAR const struct nx_fontbitmap_s *bm, nxgl_mxpixel_t color) +{ + FAR uint8_t *line; + FAR NXF_PIXEL_T *dptr; + FAR const uint8_t *sptr; + uint8_t bmbyte; + int bmbit; + int row; + int col; + int bmndx; + +#if NXFONTS_BITSPERPIXEL < 8 + NXF_PIXEL_T mpixel; + NXF_PIXEL_T mask; + NXF_PIXEL_T pixel; + int nbits; +#endif + + /* Get the starting position */ + + line = (uint8_t*)dest + bm->metric.yoffset * stride + NXF_SCALEX(bm->metric.xoffset); + + /* Then copy the font */ + + height = ngl_min(bm->metric.height, height - bm->metric.yoffset); + width = ngl_min(bm->metric.width, width - bm->metric.xoffset); + + /* Render each row of the glyph */ + + sptr = bm->bitmap; +#if NXFONTS_BITSPERPIXEL < 8 + mpixel = NXF_MULTIPIXEL(color); + + /* Handle each row in both the input and output */ + + for (row = 0; row < height; row++) + { + /* Process each byte in the glyph row */ + + col = 0; + dptr = (FAR NXF_PIXEL_T*)line; + pixel = *dptr; + mask = NXF_INITMASK; + nbits = 0; + + for (bmndx = 0; bmndx < bm->metric.stride && col < width; bmndx++) + { + bmbyte = *sptr++; + + /* Process each bit in one byte */ + + for (bmbit = 7; bmbit >= 0 && col < width; bmbit--, col++) + { + /* Is the bit set? */ + + if (bmbyte & (1 << bmbit)) + { + /* Yes.. set the bit to 'color' in the output */ + + pixel = ((pixel & ~mask) | (mpixel & mask)); + } + +#ifdef CONFIG_NX_PACKEDMSFIRST + mask >>= NXFONTS_BITSPERPIXEL; +#else + mask <<= NXFONTS_BITSPERPIXEL; +#endif + nbits += NXFONTS_BITSPERPIXEL; + if (nbits >= 8) + { + *dptr++ = pixel; + pixel = *dptr; + mask = NXF_INITMASK; + nbits = 0; + } + } + } + + /* The entire glyph row has been rendered. Handle any fractional bytes at + * the end of the row + */ + + if (nbits > 0) + { + *dptr = pixel; + } + + /* Point to the beginning of the next row */ + + line += stride; + } +#else + /* Handle each row in both the input and output */ + + for (row = 0; row < height; row++) + { + /* Process each byte in the glyph */ + + col = 0; + dptr = (FAR NXF_PIXEL_T*)line; + + for (bmndx = 0; bmndx < bm->metric.stride && col < width; bmndx++) + { + bmbyte = *sptr++; + + /* Process each bit in the byte */ + + for (bmbit = 7; bmbit >= 0 && col < width; bmbit--, col++) + { + /* Is the bit set? */ + + if (bmbyte & (1 << bmbit)) + { + /* Yes.. set the bit to 'color' in the output */ + + *dptr++ = color; + } + else + { + /* No... keep the background color in the output */ + + dptr++; + } + } + } + + /* Advance to the beginning of the next line in the destination */ + + line += stride; + } +#endif + return OK; +} diff --git a/nuttx/graphics/nxfonts/nxfonts_getfont.c b/nuttx/graphics/nxfonts/nxfonts_getfont.c new file mode 100644 index 0000000000..e17d3be310 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_getfont.c @@ -0,0 +1,411 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_getfont.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfonts_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* SANS */ + +#ifdef CONFIG_NXFONT_SANS17X22 +extern const struct nx_fontpackage_s g_sans17x22_package; +#endif + +#ifdef CONFIG_NXFONT_SANS20X26 +extern const struct nx_fontpackage_s g_sans20x26_package; +#endif + +#ifdef CONFIG_NXFONT_SANS23X27 +extern const struct nx_fontpackage_s g_sans23x27_package; +#endif + +#ifdef CONFIG_NXFONT_SANS22X29 +extern const struct nx_fontpackage_s g_sans22x29_package; +#endif + +#ifdef CONFIG_NXFONT_SANS28X37 +extern const struct nx_fontpackage_s g_sans28x37_package; +#endif + +#ifdef CONFIG_NXFONT_SANS39X48 +extern const struct nx_fontpackage_s g_sans39x48_package; +#endif + +/* SANS-BOLD */ + +#ifdef CONFIG_NXFONT_SANS17X23B +extern const struct nx_fontpackage_s g_sans17x23b_package; +#endif + +#ifdef CONFIG_NXFONT_SANS20X27B +extern const struct nx_fontpackage_s g_sans20x27b_package; +#endif + +#ifdef CONFIG_NXFONT_SANS22X29B +extern const struct nx_fontpackage_s g_sans22x29b_package; +#endif + +#ifdef CONFIG_NXFONT_SANS28X37B +extern const struct nx_fontpackage_s g_sans28x37b_package; +#endif + +#ifdef CONFIG_NXFONT_SANS40X49B +extern const struct nx_fontpackage_s g_sans40x49b_package; +#endif + +/* SERIF */ + +#ifdef CONFIG_NXFONT_SERIF22X29 +extern const struct nx_fontpackage_s g_serif22x29_package; +#endif + +#ifdef CONFIG_NXFONT_SERIF29X37 +extern const struct nx_fontpackage_s g_serif29x37_package; +#endif + +#ifdef CONFIG_NXFONT_SERIF38X48 +extern const struct nx_fontpackage_s g_serif38x48_package; +#endif + +/* SERIF-BOLD */ + +#ifdef CONFIG_NXFONT_SERIF22X28B +extern const struct nx_fontpackage_s g_serif22x28b_package; +#endif + +#ifdef CONFIG_NXFONT_SERIF27X38B +extern const struct nx_fontpackage_s g_serif27x38b_package; +#endif + +#ifdef CONFIG_NXFONT_SERIF38X49 +extern const struct nx_fontpackage_s g_serif38x49b_package; +#endif + +static FAR const struct nx_fontpackage_s *g_fontpackages[] = +{ + +/* SANS */ + +#ifdef CONFIG_NXFONT_SANS17X22 + &g_sans17x22_package, +#endif + +#ifdef CONFIG_NXFONT_SANS20X26 + &g_sans20x26_package, +#endif + +#ifdef CONFIG_NXFONT_SANS23X27 + &g_sans23x27_package, +#endif + +#ifdef CONFIG_NXFONT_SANS22X29 + &g_sans22x29_package, +#endif + +#ifdef CONFIG_NXFONT_SANS28X37 + &g_sans28x37_package, +#endif + +#ifdef CONFIG_NXFONT_SANS39X48 + &g_sans39x48_package, +#endif + +/* SANS-BOLD */ + +#ifdef CONFIG_NXFONT_SANS17X23B + &g_sans17x23b_package, +#endif + +#ifdef CONFIG_NXFONT_SANS20X27B + &g_sans20x27b_package, +#endif + +#ifdef CONFIG_NXFONT_SANS22X29B + &g_sans22x29b_package, +#endif + +#ifdef CONFIG_NXFONT_SANS28X37B + &g_sans28x37b_package, +#endif + +#ifdef CONFIG_NXFONT_SANS40X49B + &g_sans40x49b_package, +#endif + +/* SERIF */ + +#ifdef CONFIG_NXFONT_SERIF22X29 + &g_serif22x29_package, +#endif + +#ifdef CONFIG_NXFONT_SERIF29X37 + &g_serif29x37_package, +#endif + +#ifdef CONFIG_NXFONT_SERIF38X48 + &g_serif38x48_package, +#endif + +/* SERIF-BOLD */ + +#ifdef CONFIG_NXFONT_SERIF22X28B + &g_serif22x28b_package, +#endif + +#ifdef CONFIG_NXFONT_SERIF27X38B + &g_serif27x38b_package, +#endif + +#ifdef CONFIG_NXFONT_SERIF38X49B + &g_serif38x49b_package, +#endif + + NULL +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxf_getglyphset + * + * Description: + * Return information about the font set containtined he selected + * character encoding. + * + * Input Parameters: + * ch: character code + * package: The selected font package + * + ****************************************************************************/ + +static inline FAR const struct nx_fontset_s * + nxf_getglyphset(uint16_t ch, FAR const struct nx_fontpackage_s *package) +{ + FAR const struct nx_fontset_s *fontset; + + /* Select the 7- or 8-bit font set */ + + if (ch < 128) + { + /* Select the 7-bit font set */ + + fontset = &package->font7; + } + else if (ch < 256) + { +#if CONFIG_NXFONTS_CHARBITS >= 8 + /* Select the 8-bit font set */ + + fontset = &package->font8; +#else + gdbg("8-bit font support disabled: %d\n", ch); + return NULL; +#endif + } + else + { + /* Someday, perhaps 16-bit fonts will go here */ + + gdbg("16-bit font not currently supported\n"); + return NULL; + } + + /* Then verify that the character actually resides in the font */ + + if (ch >= fontset->first && ch < fontset->first +fontset->nchars) + { + return fontset; + } + + gdbg("No bitmap for code %02x\n", ch); + return NULL; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxf_getfonthandle + * + * Description: + * Given a numeric font ID, return a handle that may be subsequently be + * used to access the font data sets. + * + * Input Parameters: + * fontid: Identifies the font set to get + * + ****************************************************************************/ + +NXHANDLE nxf_getfonthandle(enum nx_fontid_e fontid) +{ + FAR const struct nx_fontpackage_s **pkglist; + FAR const struct nx_fontpackage_s *package; + FAR const struct nx_fontpackage_s *defpkg = NULL; + + /* Handle the default font package */ + + if (fontid == FONTID_DEFAULT) + { + fontid = NXFONT_DEFAULT; + } + + /* Then search for the font package with this ID */ + + for (pkglist = g_fontpackages; *pkglist; pkglist++) + { + /* Is this the package with the matching font ID? */ + + package = *pkglist; + if (package->id == fontid) + { + /* Yes.. return a pointer to the package as the handle */ + + return (NXHANDLE)package; + } + + /* No.. is it the default font? */ + + else if (package->id == NXFONT_DEFAULT) + { + /* Yes.. save the pointer to the default font. We will return the + * default font if the requested font cannot be found. + */ + + defpkg = package; + } + } + + /* Return a pointer to the default font as the handle. */ + + return (NXHANDLE)defpkg; +} + +/**************************************************************************** + * Name: nxf_getfontset + * + * Description: + * Return information about the current font set + * + * Input Parameters: + * handle: A font handle previously returned by nxf_getfonthandle + * + ****************************************************************************/ + +FAR const struct nx_font_s *nxf_getfontset(NXHANDLE handle) +{ + FAR const struct nx_fontpackage_s *package = + (FAR const struct nx_fontpackage_s *)handle; + + /* Find the font package associated with this font ID */ + + if (package) + { + /* Found... return the font set metrics for this font package */ + + return &package->metrics; + } + + return NULL; +} + +/**************************************************************************** + * Name: nxf_getbitmap + * + * Description: + * Return font bitmap information for the selected character encoding. + * + * Input Parameters: + * handle: A font handle previously returned by nxf_getfonthandle + * ch: Character code whose bitmap is requested + * + * Returned Value: + * An instance of struct nx_fontbitmap_s describing the glyph. + * + ****************************************************************************/ + +FAR const struct nx_fontbitmap_s *nxf_getbitmap(NXHANDLE handle, uint16_t ch) +{ + FAR const struct nx_fontpackage_s *package = + (FAR const struct nx_fontpackage_s *)handle; + FAR const struct nx_fontset_s *fontset; + FAR const struct nx_fontbitmap_s *bm = NULL; + + /* Verify that the handle is a font package */ + + if (package) + { + /* Now get the fontset from the package */ + + fontset = nxf_getglyphset(ch, package); + if (fontset) + { + /* Then get the bitmap from the font set */ + + bm = &fontset->bitmap[ch - fontset->first]; + } + } + + return bm; +} diff --git a/nuttx/graphics/nxfonts/nxfonts_internal.h b/nuttx/graphics/nxfonts/nxfonts_internal.h new file mode 100644 index 0000000000..fa7864170d --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_internal.h @@ -0,0 +1,88 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_internal.h + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_INTERNAL_H +#define __GRAPHICS_NXFONTS_NXFONTS_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_NXFONTS_CHARBITS +# define CONFIG_NXFONTS_CHARBITS 7 +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" { +#else +# define EXTERN extern +#endif + +EXTERN struct nx_fontset_s g_7bitfonts; +#if CONFIG_NXFONTS_CHARBITS >= 8 +EXTERN struct nx_fontset_s g_8bitfonts; +#endif +EXTERN struct nx_font_s g_fonts; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_INTERNAL_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_sans17x22.h b/nuttx/graphics/nxfonts/nxfonts_sans17x22.h new file mode 100644 index 0000000000..cea027447b --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_sans17x22.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_serif30x26.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SANS17X22_H +#define __GRAPHICS_NXFONTS_NXFONTS_SANS17X22_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SANS17X22 + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 22 +#define NXFONT_MAXWIDTH 17 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 4 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 1, 11, 2, 6, 0} +#define NXFONT_BITMAP_33 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0, 0x80, 0x80} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {1, 3, 3, 1, 6, 0} +#define NXFONT_BITMAP_34 {0xa0, 0xa0, 0xa0} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {1, 7, 10, 0, 7, 0} +#define NXFONT_BITMAP_35 {0x14, 0x14, 0x14, 0x7e, 0x28, 0x28, 0xfc, 0x50, 0x50, 0x50} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {1, 7, 14, 0, 5, 0} +#define NXFONT_BITMAP_36 {0x10, 0x7c, 0x92, 0x92, 0x90, 0x50, 0x38, 0x14, 0x12, 0x92, 0x92, 0x7c, 0x10, 0x10} + +/* percent (37) */ +#define NXFONT_METRICS_37 {2, 11, 11, 0, 6, 0} +#define NXFONT_BITMAP_37 {0x70, 0x80, 0x89, 0x0, 0x89, 0x0, 0x72, 0x0, 0x2, 0x0, 0x4, 0x0, 0x8, 0x0, 0x9, 0xc0, 0x12, 0x20, 0x12, 0x20, 0x21, 0xc0} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {1, 8, 10, 1, 7, 0} +#define NXFONT_BITMAP_38 {0x30, 0x48, 0x48, 0x30, 0x20, 0x52, 0x8a, 0x84, 0x8a, 0x71} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 1, 3, 1, 6, 0} +#define NXFONT_BITMAP_39 {0x80, 0x80, 0x80} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 3, 14, 1, 6, 0} +#define NXFONT_BITMAP_40 {0x20, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x20} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 3, 14, 1, 6, 0} +#define NXFONT_BITMAP_41 {0x80, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x80} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {1, 5, 5, 1, 6, 0} +#define NXFONT_BITMAP_42 {0x20, 0xa8, 0x70, 0xa8, 0x20} + +/* plus (43) */ +#define NXFONT_METRICS_43 {1, 7, 7, 1, 9, 0} +#define NXFONT_BITMAP_43 {0x10, 0x10, 0x10, 0xfe, 0x10, 0x10, 0x10} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 2, 4, 0, 15, 0} +#define NXFONT_BITMAP_44 {0x40, 0x40, 0x40, 0x80} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 3, 1, 0, 12, 0} +#define NXFONT_BITMAP_45 {0xe0} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 1, 2, 1, 15, 0} +#define NXFONT_BITMAP_46 {0x80, 0x80} + +/* slash (47) */ +#define NXFONT_METRICS_47 {1, 4, 11, 0, 6, 0} +#define NXFONT_BITMAP_47 {0x10, 0x10, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80} + +/* zero (48) */ +#define NXFONT_METRICS_48 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_48 {0x78, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x78} + +/* one (49) */ +#define NXFONT_METRICS_49 {1, 3, 11, 2, 6, 0} +#define NXFONT_BITMAP_49 {0x20, 0xe0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20} + +/* two (50) */ +#define NXFONT_METRICS_50 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_50 {0x78, 0x84, 0x84, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x80, 0xfc} + +/* three (51) */ +#define NXFONT_METRICS_51 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_51 {0x78, 0x84, 0x84, 0x4, 0x4, 0x38, 0x4, 0x4, 0x84, 0x84, 0x78} + +/* four (52) */ +#define NXFONT_METRICS_52 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_52 {0x4, 0xc, 0x14, 0x24, 0x44, 0x84, 0x84, 0xfe, 0x4, 0x4, 0x4} + +/* five (53) */ +#define NXFONT_METRICS_53 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_53 {0xfc, 0x80, 0x80, 0x80, 0xf8, 0x4, 0x4, 0x4, 0x84, 0x84, 0x78} + +/* six (54) */ +#define NXFONT_METRICS_54 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_54 {0x78, 0x84, 0x80, 0x80, 0xb8, 0xc4, 0x84, 0x84, 0x84, 0x84, 0x78} + +/* seven (55) */ +#define NXFONT_METRICS_55 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_55 {0xfc, 0x4, 0x8, 0x8, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x40} + +/* eight (56) */ +#define NXFONT_METRICS_56 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_56 {0x78, 0x84, 0x84, 0x84, 0x84, 0x78, 0x84, 0x84, 0x84, 0x84, 0x78} + +/* nine (57) */ +#define NXFONT_METRICS_57 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_57 {0x78, 0x84, 0x84, 0x84, 0x84, 0x7c, 0x4, 0x4, 0x84, 0x84, 0x78} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 1, 8, 1, 9, 0} +#define NXFONT_BITMAP_58 {0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 2, 10, 0, 9, 0} +#define NXFONT_BITMAP_59 {0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x40, 0x40, 0x40, 0x80} + +/* less (60) */ +#define NXFONT_METRICS_60 {1, 6, 5, 1, 10, 0} +#define NXFONT_BITMAP_60 {0xc, 0x30, 0xc0, 0x30, 0xc} + +/* equal (61) */ +#define NXFONT_METRICS_61 {1, 6, 3, 1, 11, 0} +#define NXFONT_BITMAP_61 {0xfc, 0x0, 0xfc} + +/* greater (62) */ +#define NXFONT_METRICS_62 {1, 6, 5, 1, 10, 0} +#define NXFONT_BITMAP_62 {0xc0, 0x30, 0xc, 0x30, 0xc0} + +/* question (63) */ +#define NXFONT_METRICS_63 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_63 {0x30, 0xcc, 0x84, 0x84, 0x4, 0x8, 0x10, 0x20, 0x0, 0x20, 0x20} + +/* at (64) */ +#define NXFONT_METRICS_64 {2, 11, 12, 1, 6, 0} +#define NXFONT_BITMAP_64 {0xf, 0x0, 0x30, 0xc0, 0x40, 0x20, 0x46, 0xa0, 0x89, 0x20, 0x91, 0x20, 0x91, 0x20, 0x93, 0x40, 0x8d, 0x80, 0x40, 0x0, 0x60, 0x80, 0x1f, 0x0} + +/* A (65) */ +#define NXFONT_METRICS_65 {2, 9, 11, 0, 6, 0} +#define NXFONT_BITMAP_65 {0x8, 0x0, 0x1c, 0x0, 0x14, 0x0, 0x14, 0x0, 0x22, 0x0, 0x22, 0x0, 0x41, 0x0, 0x7f, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80} + +/* B (66) */ +#define NXFONT_METRICS_66 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_66 {0xfc, 0x86, 0x82, 0x82, 0x84, 0xf8, 0x84, 0x82, 0x82, 0x86, 0xfc} + +/* C (67) */ +#define NXFONT_METRICS_67 {1, 8, 11, 1, 6, 0} +#define NXFONT_BITMAP_67 {0x1c, 0x63, 0x41, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x63, 0x1c} + +/* D (68) */ +#define NXFONT_METRICS_68 {1, 8, 11, 1, 6, 0} +#define NXFONT_BITMAP_68 {0xf8, 0x86, 0x82, 0x81, 0x81, 0x81, 0x81, 0x81, 0x82, 0x86, 0xf8} + +/* E (69) */ +#define NXFONT_METRICS_69 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_69 {0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe} + +/* F (70) */ +#define NXFONT_METRICS_70 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_70 {0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* G (71) */ +#define NXFONT_METRICS_71 {2, 9, 11, 1, 6, 0} +#define NXFONT_BITMAP_71 {0x1e, 0x0, 0x61, 0x80, 0x40, 0x80, 0x80, 0x0, 0x80, 0x0, 0x87, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40, 0x80, 0x63, 0x80, 0x1c, 0x80} + +/* H (72) */ +#define NXFONT_METRICS_72 {1, 8, 11, 1, 6, 0} +#define NXFONT_BITMAP_72 {0x81, 0x81, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 1, 11, 2, 6, 0} +#define NXFONT_BITMAP_73 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* J (74) */ +#define NXFONT_METRICS_74 {1, 6, 11, 0, 6, 0} +#define NXFONT_BITMAP_74 {0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x84, 0x84, 0x78} + +/* K (75) */ +#define NXFONT_METRICS_75 {1, 8, 11, 1, 6, 0} +#define NXFONT_BITMAP_75 {0x82, 0x84, 0x88, 0x90, 0xa0, 0xe0, 0x90, 0x88, 0x84, 0x82, 0x81} + +/* L (76) */ +#define NXFONT_METRICS_76 {1, 6, 11, 2, 6, 0} +#define NXFONT_BITMAP_76 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xfc} + +/* M (77) */ +#define NXFONT_METRICS_77 {2, 11, 11, 0, 6, 0} +#define NXFONT_BITMAP_77 {0x80, 0x20, 0xc0, 0x60, 0xc0, 0x60, 0xa0, 0xa0, 0xa0, 0xa0, 0x91, 0x20, 0x91, 0x20, 0x8a, 0x20, 0x8a, 0x20, 0x84, 0x20, 0x84, 0x20} + +/* N (78) */ +#define NXFONT_METRICS_78 {1, 8, 11, 1, 6, 0} +#define NXFONT_BITMAP_78 {0xc1, 0xa1, 0xa1, 0x91, 0x91, 0x89, 0x89, 0x85, 0x85, 0x83, 0x83} + +/* O (79) */ +#define NXFONT_METRICS_79 {2, 9, 11, 1, 6, 0} +#define NXFONT_BITMAP_79 {0x1c, 0x0, 0x63, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x0, 0x63, 0x0, 0x1c, 0x0} + +/* P (80) */ +#define NXFONT_METRICS_80 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_80 {0xfc, 0x86, 0x82, 0x82, 0x86, 0xfc, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* Q (81) */ +#define NXFONT_METRICS_81 {2, 9, 11, 1, 6, 0} +#define NXFONT_BITMAP_81 {0x1c, 0x0, 0x63, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x88, 0x80, 0x84, 0x80, 0x43, 0x0, 0x63, 0x0, 0x1c, 0x80} + +/* R (82) */ +#define NXFONT_METRICS_82 {1, 8, 11, 1, 6, 0} +#define NXFONT_BITMAP_82 {0xfe, 0x83, 0x81, 0x81, 0x82, 0xfc, 0x82, 0x81, 0x81, 0x81, 0x81} + +/* S (83) */ +#define NXFONT_METRICS_83 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_83 {0x38, 0xc6, 0x82, 0x80, 0x60, 0x18, 0x6, 0x2, 0x82, 0xc6, 0x38} + +/* T (84) */ +#define NXFONT_METRICS_84 {2, 9, 11, 0, 6, 0} +#define NXFONT_BITMAP_84 {0xff, 0x80, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* U (85) */ +#define NXFONT_METRICS_85 {1, 8, 11, 1, 6, 0} +#define NXFONT_BITMAP_85 {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c} + +/* V (86) */ +#define NXFONT_METRICS_86 {2, 9, 11, 0, 6, 0} +#define NXFONT_BITMAP_86 {0x80, 0x80, 0x80, 0x80, 0x41, 0x0, 0x41, 0x0, 0x63, 0x0, 0x22, 0x0, 0x22, 0x0, 0x14, 0x0, 0x14, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {2, 13, 11, 0, 6, 0} +#define NXFONT_BITMAP_87 {0x82, 0x8, 0x82, 0x8, 0x85, 0x8, 0x45, 0x10, 0x45, 0x10, 0x45, 0x10, 0x28, 0xa0, 0x28, 0xa0, 0x28, 0xa0, 0x10, 0x40, 0x10, 0x40} + +/* X (88) */ +#define NXFONT_METRICS_88 {2, 9, 11, 0, 6, 0} +#define NXFONT_BITMAP_88 {0x80, 0x80, 0x41, 0x0, 0x22, 0x0, 0x14, 0x0, 0x8, 0x0, 0x8, 0x0, 0x14, 0x0, 0x22, 0x0, 0x41, 0x0, 0x41, 0x0, 0x80, 0x80} + +/* Y (89) */ +#define NXFONT_METRICS_89 {2, 9, 11, 0, 6, 0} +#define NXFONT_BITMAP_89 {0x80, 0x80, 0xc1, 0x80, 0x41, 0x0, 0x22, 0x0, 0x22, 0x0, 0x14, 0x0, 0x1c, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_90 {0xfe, 0x2, 0x4, 0x8, 0x18, 0x10, 0x20, 0x60, 0x40, 0x80, 0xfe} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 3, 14, 1, 6, 0} +#define NXFONT_BITMAP_91 {0xe0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe0} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {1, 4, 11, 0, 6, 0} +#define NXFONT_BITMAP_92 {0x80, 0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 3, 14, 0, 6, 0} +#define NXFONT_BITMAP_93 {0xe0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xe0} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {1, 5, 5, 1, 6, 0} +#define NXFONT_BITMAP_94 {0x20, 0x50, 0x50, 0x88, 0x88} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {1, 8, 1, 0, 19, 0} +#define NXFONT_BITMAP_95 {0xff} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 2, 2, 1, 6, 0} +#define NXFONT_BITMAP_96 {0x80, 0x40} + +/* a (97) */ +#define NXFONT_METRICS_97 {1, 7, 8, 1, 9, 0} +#define NXFONT_BITMAP_97 {0x78, 0xcc, 0x4, 0x7c, 0xc4, 0x84, 0xcc, 0x76} + +/* b (98) */ +#define NXFONT_METRICS_98 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_98 {0x80, 0x80, 0x80, 0xb8, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0xb8} + +/* c (99) */ +#define NXFONT_METRICS_99 {1, 6, 8, 1, 9, 0} +#define NXFONT_BITMAP_99 {0x78, 0xcc, 0x80, 0x80, 0x80, 0x84, 0xcc, 0x78} + +/* d (100) */ +#define NXFONT_METRICS_100 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_100 {0x4, 0x4, 0x4, 0x74, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x74} + +/* e (101) */ +#define NXFONT_METRICS_101 {1, 6, 8, 1, 9, 0} +#define NXFONT_BITMAP_101 {0x78, 0xcc, 0x84, 0xfc, 0x80, 0x80, 0xcc, 0x78} + +/* f (102) */ +#define NXFONT_METRICS_102 {1, 4, 11, 0, 6, 0} +#define NXFONT_BITMAP_102 {0x30, 0x40, 0x40, 0xe0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* g (103) */ +#define NXFONT_METRICS_103 {1, 6, 11, 1, 9, 0} +#define NXFONT_BITMAP_103 {0x74, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x74, 0x4, 0xcc, 0x78} + +/* h (104) */ +#define NXFONT_METRICS_104 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_104 {0x80, 0x80, 0x80, 0xb8, 0xcc, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 1, 11, 1, 6, 0} +#define NXFONT_BITMAP_105 {0x80, 0x80, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* j (106) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_106 {1, 3, 14, 0, 6, 0} +#define NXFONT_BITMAP_106 {0x20, 0x20, 0x0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xc0} + +/* k (107) */ +#define NXFONT_METRICS_107 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_107 {0x80, 0x80, 0x80, 0x88, 0x90, 0xa0, 0xc0, 0xa0, 0x90, 0x88, 0x84} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 1, 11, 1, 6, 0} +#define NXFONT_BITMAP_108 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* m (109) */ +#define NXFONT_METRICS_109 {2, 9, 8, 1, 9, 0} +#define NXFONT_BITMAP_109 {0xb3, 0x0, 0xcc, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80} + +/* n (110) */ +#define NXFONT_METRICS_110 {1, 6, 8, 1, 9, 0} +#define NXFONT_BITMAP_110 {0xb8, 0xcc, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84} + +/* o (111) */ +#define NXFONT_METRICS_111 {1, 6, 8, 1, 9, 0} +#define NXFONT_BITMAP_111 {0x78, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78} + +/* p (112) */ +#define NXFONT_METRICS_112 {1, 6, 11, 1, 9, 0} +#define NXFONT_BITMAP_112 {0xb8, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0xb8, 0x80, 0x80, 0x80} + +/* q (113) */ +#define NXFONT_METRICS_113 {1, 6, 11, 1, 9, 0} +#define NXFONT_BITMAP_113 {0x74, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x74, 0x4, 0x4, 0x4} + +/* r (114) */ +#define NXFONT_METRICS_114 {1, 4, 8, 1, 9, 0} +#define NXFONT_BITMAP_114 {0xb0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* s (115) */ +#define NXFONT_METRICS_115 {1, 5, 8, 1, 9, 0} +#define NXFONT_BITMAP_115 {0x70, 0x88, 0xc0, 0x70, 0x18, 0x8, 0x88, 0x70} + +/* t (116) */ +#define NXFONT_METRICS_116 {1, 4, 10, 0, 7, 0} +#define NXFONT_BITMAP_116 {0x40, 0x40, 0xe0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x30} + +/* u (117) */ +#define NXFONT_METRICS_117 {1, 6, 8, 1, 9, 0} +#define NXFONT_BITMAP_117 {0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x74} + +/* v (118) */ +#define NXFONT_METRICS_118 {1, 7, 8, 0, 9, 0} +#define NXFONT_BITMAP_118 {0x82, 0x82, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10} + +/* w (119) */ +#define NXFONT_METRICS_119 {2, 9, 8, 0, 9, 0} +#define NXFONT_BITMAP_119 {0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x49, 0x0, 0x49, 0x0, 0x55, 0x0, 0x22, 0x0, 0x22, 0x0} + +/* x (120) */ +#define NXFONT_METRICS_120 {1, 7, 8, 0, 9, 0} +#define NXFONT_BITMAP_120 {0xc6, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0xc6} + +/* y (121) */ +#define NXFONT_METRICS_121 {1, 7, 11, 0, 9, 0} +#define NXFONT_BITMAP_121 {0x82, 0xc2, 0x44, 0x44, 0x24, 0x28, 0x18, 0x10, 0x10, 0x30, 0x60} + +/* z (122) */ +#define NXFONT_METRICS_122 {1, 6, 8, 0, 9, 0} +#define NXFONT_BITMAP_122 {0xfc, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0xfc} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {1, 5, 14, 0, 6, 0} +#define NXFONT_BITMAP_123 {0x18, 0x20, 0x20, 0x20, 0x20, 0x40, 0x80, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x18} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 1, 14, 1, 6, 0} +#define NXFONT_BITMAP_124 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 5, 14, 0, 6, 0} +#define NXFONT_BITMAP_125 {0xc0, 0x20, 0x20, 0x20, 0x20, 0x10, 0x8, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0xc0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {1, 6, 3, 1, 11, 0} +#define NXFONT_BITMAP_126 {0x64, 0xb4, 0x98} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 1, 11, 1, 9, 0} +#define NXFONT_BITMAP_161 {0x80, 0x80, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* cent (162) */ +#define NXFONT_METRICS_162 {1, 6, 10, 1, 8, 0} +#define NXFONT_BITMAP_162 {0x4, 0x78, 0xcc, 0x90, 0x90, 0xa0, 0xa4, 0xcc, 0x78, 0x80} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {1, 7, 11, 0, 6, 0} +#define NXFONT_BITMAP_163 {0x38, 0x44, 0x40, 0x40, 0xf8, 0x20, 0x20, 0x20, 0x40, 0x62, 0xdc} + +/* currency (164) */ +#define NXFONT_METRICS_164 {1, 6, 6, 1, 9, 0} +#define NXFONT_BITMAP_164 {0x84, 0x78, 0x48, 0x48, 0x78, 0x84} + +/* yen (165) */ +#define NXFONT_METRICS_165 {1, 7, 11, 0, 6, 0} +#define NXFONT_BITMAP_165 {0x82, 0x82, 0x82, 0x44, 0x44, 0x28, 0xfe, 0x10, 0xfe, 0x10, 0x10} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 1, 14, 1, 6, 0} +#define NXFONT_BITMAP_166 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* section (167) */ +#define NXFONT_METRICS_167 {1, 5, 14, 2, 6, 0} +#define NXFONT_BITMAP_167 {0x70, 0xd8, 0x88, 0xc0, 0x70, 0x98, 0x88, 0x88, 0xc8, 0x70, 0x18, 0x88, 0xd8, 0x70} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 5, 1, 0, 7, 0} +#define NXFONT_BITMAP_168 {0xd8} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {2, 10, 11, 1, 6, 0} +#define NXFONT_BITMAP_169 {0x1e, 0x0, 0x61, 0x80, 0x5c, 0x80, 0xa2, 0xc0, 0xa2, 0x40, 0xa0, 0x40, 0xa2, 0x40, 0x9c, 0x40, 0x40, 0x80, 0x61, 0x80, 0x1e, 0x0} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {1, 4, 7, 1, 6, 0} +#define NXFONT_BITMAP_170 {0xe0, 0x10, 0x70, 0x90, 0xd0, 0x0, 0xf0} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {1, 6, 5, 1, 10, 0} +#define NXFONT_BITMAP_171 {0x24, 0x48, 0x90, 0x48, 0x24} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {1, 7, 4, 1, 11, 0} +#define NXFONT_BITMAP_172 {0xfe, 0x2, 0x2, 0x2} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 3, 1, 0, 12, 0} +#define NXFONT_BITMAP_173 {0xe0} + +/* registered (174) */ +#define NXFONT_METRICS_174 {2, 10, 11, 1, 6, 0} +#define NXFONT_BITMAP_174 {0x1e, 0x0, 0x61, 0x80, 0x5c, 0x80, 0x92, 0x40, 0x92, 0x40, 0x9c, 0x40, 0x92, 0x40, 0x92, 0x40, 0x40, 0x80, 0x61, 0x80, 0x1e, 0x0} + +/* macron (175) */ +#define NXFONT_METRICS_175 {1, 4, 1, 0, 7, 0} +#define NXFONT_BITMAP_175 {0xf0} + +/* degree (176) */ +#define NXFONT_METRICS_176 {1, 4, 4, 1, 6, 0} +#define NXFONT_BITMAP_176 {0x60, 0x90, 0x90, 0x60} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {1, 7, 9, 1, 8, 0} +#define NXFONT_BITMAP_177 {0x10, 0x10, 0x10, 0xfe, 0x10, 0x10, 0x10, 0x0, 0xfe} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {1, 4, 6, 0, 6, 0} +#define NXFONT_BITMAP_178 {0x60, 0x90, 0x10, 0x20, 0x40, 0xf0} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {1, 4, 6, 0, 6, 0} +#define NXFONT_BITMAP_179 {0x60, 0x90, 0x20, 0x10, 0x90, 0x60} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 2, 2, 2, 6, 0} +#define NXFONT_BITMAP_180 {0x40, 0x80} + +/* mu (181) */ +#define NXFONT_METRICS_181 {1, 6, 11, 1, 9, 0} +#define NXFONT_BITMAP_181 {0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0xcc, 0xb4, 0x80, 0x80, 0x80} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {1, 7, 14, 0, 6, 0} +#define NXFONT_BITMAP_182 {0x3e, 0x74, 0xf4, 0xf4, 0xf4, 0x74, 0x34, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 2, 1, 1, 12, 0} +#define NXFONT_BITMAP_183 {0xc0} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 4, 3, 0, 17, 0} +#define NXFONT_BITMAP_184 {0x20, 0x90, 0x60} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 2, 6, 1, 6, 0} +#define NXFONT_BITMAP_185 {0x40, 0xc0, 0x40, 0x40, 0x40, 0x40} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {1, 4, 7, 1, 6, 0} +#define NXFONT_BITMAP_186 {0x60, 0x90, 0x90, 0x90, 0x60, 0x0, 0xf0} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {1, 6, 5, 1, 10, 0} +#define NXFONT_BITMAP_187 {0x90, 0x48, 0x24, 0x48, 0x90} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {2, 10, 11, 1, 6, 0} +#define NXFONT_BITMAP_188 {0x42, 0x0, 0xc2, 0x0, 0x44, 0x0, 0x44, 0x0, 0x48, 0x0, 0x48, 0x80, 0x9, 0x80, 0x12, 0x80, 0x14, 0x80, 0x27, 0xc0, 0x20, 0x80} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {2, 9, 11, 1, 6, 0} +#define NXFONT_BITMAP_189 {0x42, 0x0, 0xc2, 0x0, 0x44, 0x0, 0x44, 0x0, 0x48, 0x0, 0x4b, 0x0, 0x14, 0x80, 0x10, 0x80, 0x11, 0x0, 0x22, 0x0, 0x27, 0x80} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {2, 11, 11, 0, 6, 0} +#define NXFONT_BITMAP_190 {0x61, 0x0, 0x91, 0x0, 0x22, 0x0, 0x12, 0x0, 0x94, 0x0, 0x64, 0x40, 0x4, 0xc0, 0x9, 0x40, 0xa, 0x40, 0x13, 0xe0, 0x10, 0x40} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {1, 6, 11, 1, 9, 0} +#define NXFONT_BITMAP_191 {0x10, 0x10, 0x0, 0x10, 0x20, 0x40, 0x80, 0x84, 0x84, 0xcc, 0x30} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {2, 9, 14, 0, 3, 0} +#define NXFONT_BITMAP_192 {0x10, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x0, 0x1c, 0x0, 0x14, 0x0, 0x14, 0x0, 0x22, 0x0, 0x22, 0x0, 0x41, 0x0, 0x7f, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {2, 9, 14, 0, 3, 0} +#define NXFONT_BITMAP_193 {0x4, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x0, 0x1c, 0x0, 0x14, 0x0, 0x14, 0x0, 0x22, 0x0, 0x22, 0x0, 0x41, 0x0, 0x7f, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {2, 9, 14, 0, 3, 0} +#define NXFONT_BITMAP_194 {0xc, 0x0, 0x12, 0x0, 0x0, 0x0, 0x8, 0x0, 0x1c, 0x0, 0x14, 0x0, 0x14, 0x0, 0x22, 0x0, 0x22, 0x0, 0x41, 0x0, 0x7f, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {2, 9, 14, 0, 3, 0} +#define NXFONT_BITMAP_195 {0x1a, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x8, 0x0, 0x1c, 0x0, 0x14, 0x0, 0x14, 0x0, 0x22, 0x0, 0x22, 0x0, 0x41, 0x0, 0x7f, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {2, 9, 13, 0, 4, 0} +#define NXFONT_BITMAP_196 {0x36, 0x0, 0x0, 0x0, 0x8, 0x0, 0x1c, 0x0, 0x14, 0x0, 0x14, 0x0, 0x22, 0x0, 0x22, 0x0, 0x41, 0x0, 0x7f, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {2, 9, 14, 0, 3, 0} +#define NXFONT_BITMAP_197 {0xc, 0x0, 0x12, 0x0, 0x12, 0x0, 0xc, 0x0, 0xc, 0x0, 0x14, 0x0, 0x14, 0x0, 0x22, 0x0, 0x22, 0x0, 0x41, 0x0, 0x7f, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80} + +/* AE (198) */ +#define NXFONT_METRICS_198 {2, 12, 11, 1, 6, 0} +#define NXFONT_BITMAP_198 {0x1f, 0xf0, 0x12, 0x0, 0x12, 0x0, 0x22, 0x0, 0x22, 0x0, 0x23, 0xf0, 0x7e, 0x0, 0x42, 0x0, 0x42, 0x0, 0x82, 0x0, 0x83, 0xf0} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {1, 8, 14, 1, 6, 0} +#define NXFONT_BITMAP_199 {0x1c, 0x63, 0x41, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x63, 0x1c, 0x8, 0x24, 0x18} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {1, 7, 14, 1, 3, 0} +#define NXFONT_BITMAP_200 {0x20, 0x10, 0x0, 0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {1, 7, 14, 1, 3, 0} +#define NXFONT_BITMAP_201 {0x8, 0x10, 0x0, 0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {1, 7, 14, 1, 3, 0} +#define NXFONT_BITMAP_202 {0x18, 0x24, 0x0, 0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {1, 7, 13, 1, 4, 0} +#define NXFONT_BITMAP_203 {0x6c, 0x0, 0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {1, 2, 14, 1, 3, 0} +#define NXFONT_BITMAP_204 {0x80, 0x40, 0x0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 2, 14, 2, 3, 0} +#define NXFONT_BITMAP_205 {0x40, 0x80, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* Icircumflex (206) */ +#define NXFONT_METRICS_206 {1, 4, 14, 1, 3, 0} +#define NXFONT_BITMAP_206 {0x60, 0x90, 0x0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {1, 5, 13, 0, 4, 0} +#define NXFONT_BITMAP_207 {0xd8, 0x0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20} + +/* Eth (208) */ +#define NXFONT_METRICS_208 {2, 9, 11, 0, 6, 0} +#define NXFONT_BITMAP_208 {0x7c, 0x0, 0x43, 0x0, 0x41, 0x0, 0x40, 0x80, 0x40, 0x80, 0xf0, 0x80, 0x40, 0x80, 0x40, 0x80, 0x41, 0x0, 0x43, 0x0, 0x7c, 0x0} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {1, 8, 14, 1, 3, 0} +#define NXFONT_BITMAP_209 {0x1a, 0x2c, 0x0, 0xc1, 0xa1, 0xa1, 0x91, 0x91, 0x89, 0x89, 0x85, 0x85, 0x83, 0x83} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {2, 9, 14, 1, 3, 0} +#define NXFONT_BITMAP_210 {0x10, 0x0, 0x8, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x63, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x0, 0x63, 0x0, 0x1c, 0x0} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {2, 9, 14, 1, 3, 0} +#define NXFONT_BITMAP_211 {0x4, 0x0, 0x8, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x63, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x0, 0x63, 0x0, 0x1c, 0x0} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {2, 9, 14, 1, 3, 0} +#define NXFONT_BITMAP_212 {0xc, 0x0, 0x12, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x63, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x0, 0x63, 0x0, 0x1c, 0x0} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {2, 9, 14, 1, 3, 0} +#define NXFONT_BITMAP_213 {0x1a, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x63, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x0, 0x63, 0x0, 0x1c, 0x0} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {2, 9, 13, 1, 4, 0} +#define NXFONT_BITMAP_214 {0x33, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x63, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x0, 0x63, 0x0, 0x1c, 0x0} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {1, 7, 7, 1, 9, 0} +#define NXFONT_BITMAP_215 {0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {2, 11, 11, 0, 6, 0} +#define NXFONT_BITMAP_216 {0xe, 0x20, 0x31, 0xc0, 0x20, 0x80, 0x41, 0x40, 0x42, 0x40, 0x44, 0x40, 0x48, 0x40, 0x50, 0x40, 0x20, 0x80, 0x71, 0x80, 0x8e, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {1, 8, 14, 1, 3, 0} +#define NXFONT_BITMAP_217 {0x10, 0x8, 0x0, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {1, 8, 14, 1, 3, 0} +#define NXFONT_BITMAP_218 {0x4, 0x8, 0x0, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {1, 8, 14, 1, 3, 0} +#define NXFONT_BITMAP_219 {0x18, 0x24, 0x0, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {1, 8, 13, 1, 4, 0} +#define NXFONT_BITMAP_220 {0x66, 0x0, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {2, 9, 14, 0, 3, 0} +#define NXFONT_BITMAP_221 {0x4, 0x0, 0x8, 0x0, 0x0, 0x0, 0x80, 0x80, 0xc1, 0x80, 0x41, 0x0, 0x22, 0x0, 0x22, 0x0, 0x14, 0x0, 0x1c, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_222 {0x80, 0x80, 0xfc, 0x86, 0x82, 0x82, 0x86, 0xfc, 0x80, 0x80, 0x80} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {1, 5, 11, 1, 6, 0} +#define NXFONT_BITMAP_223 {0x70, 0x88, 0x88, 0x88, 0xb0, 0x90, 0x88, 0x88, 0x88, 0x88, 0xb0} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_224 {0x20, 0x10, 0x0, 0x78, 0xcc, 0x4, 0x7c, 0xc4, 0x84, 0xcc, 0x76} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_225 {0x10, 0x20, 0x0, 0x78, 0xcc, 0x4, 0x7c, 0xc4, 0x84, 0xcc, 0x76} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_226 {0x30, 0x48, 0x0, 0x78, 0xcc, 0x4, 0x7c, 0xc4, 0x84, 0xcc, 0x76} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_227 {0x34, 0x58, 0x0, 0x78, 0xcc, 0x4, 0x7c, 0xc4, 0x84, 0xcc, 0x76} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_228 {0x48, 0x48, 0x0, 0x78, 0xcc, 0x4, 0x7c, 0xc4, 0x84, 0xcc, 0x76} + +/* aring (229) */ +#define NXFONT_METRICS_229 {1, 7, 12, 1, 5, 0} +#define NXFONT_BITMAP_229 {0x30, 0x48, 0x30, 0x0, 0x78, 0xcc, 0x4, 0x7c, 0xc4, 0x84, 0xcc, 0x76} + +/* ae (230) */ +#define NXFONT_METRICS_230 {2, 11, 8, 1, 9, 0} +#define NXFONT_BITMAP_230 {0x7b, 0xc0, 0xc6, 0x60, 0x4, 0x20, 0x7f, 0xe0, 0xc4, 0x0, 0x84, 0x0, 0xce, 0x60, 0x7b, 0xc0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {1, 6, 11, 1, 9, 0} +#define NXFONT_BITMAP_231 {0x78, 0xcc, 0x80, 0x80, 0x80, 0x84, 0xcc, 0x78, 0x10, 0x48, 0x30} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_232 {0x20, 0x10, 0x0, 0x78, 0xcc, 0x84, 0xfc, 0x80, 0x80, 0xcc, 0x78} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_233 {0x10, 0x20, 0x0, 0x78, 0xcc, 0x84, 0xfc, 0x80, 0x80, 0xcc, 0x78} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_234 {0x30, 0x48, 0x0, 0x78, 0xcc, 0x84, 0xfc, 0x80, 0x80, 0xcc, 0x78} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_235 {0x48, 0x48, 0x0, 0x78, 0xcc, 0x84, 0xfc, 0x80, 0x80, 0xcc, 0x78} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 2, 11, 1, 6, 0} +#define NXFONT_BITMAP_236 {0x80, 0x40, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 2, 11, 1, 6, 0} +#define NXFONT_BITMAP_237 {0x40, 0x80, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* icircumflex (238) */ +#define NXFONT_METRICS_238 {1, 4, 11, 0, 6, 0} +#define NXFONT_BITMAP_238 {0x60, 0x90, 0x0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 3, 11, 0, 6, 0} +#define NXFONT_BITMAP_239 {0xa0, 0xa0, 0x0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* eth (240) */ +#define NXFONT_METRICS_240 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_240 {0xd8, 0x70, 0x90, 0x78, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_241 {0x68, 0xb0, 0x0, 0xb8, 0xcc, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_242 {0x20, 0x10, 0x0, 0x78, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_243 {0x10, 0x20, 0x0, 0x78, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_244 {0x30, 0x48, 0x0, 0x78, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_245 {0x68, 0xb0, 0x0, 0x78, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_246 {0x48, 0x48, 0x0, 0x78, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78} + +/* divide (247) */ +#define NXFONT_METRICS_247 {1, 7, 7, 1, 9, 0} +#define NXFONT_BITMAP_247 {0x10, 0x10, 0x0, 0xfe, 0x0, 0x10, 0x10} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {1, 8, 8, 0, 9, 0} +#define NXFONT_BITMAP_248 {0x3d, 0x62, 0x46, 0x4a, 0x52, 0x62, 0x46, 0xbc} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_249 {0x20, 0x10, 0x0, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x74} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_250 {0x10, 0x20, 0x0, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x74} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_251 {0x30, 0x48, 0x0, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x74} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_252 {0x48, 0x48, 0x0, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x74} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {1, 7, 14, 0, 6, 0} +#define NXFONT_BITMAP_253 {0x8, 0x10, 0x0, 0x82, 0xc2, 0x44, 0x44, 0x24, 0x28, 0x18, 0x10, 0x10, 0x30, 0x60} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {1, 6, 14, 1, 6, 0} +#define NXFONT_BITMAP_254 {0x80, 0x80, 0x80, 0xb8, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0xb8, 0x80, 0x80, 0x80} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {1, 7, 14, 0, 6, 0} +#define NXFONT_BITMAP_255 {0x24, 0x24, 0x0, 0x82, 0xc2, 0x44, 0x44, 0x24, 0x28, 0x18, 0x10, 0x10, 0x30, 0x60} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SANS17X22_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_sans17x23b.h b/nuttx/graphics/nxfonts/nxfonts_sans17x23b.h new file mode 100644 index 0000000000..007986399d --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_sans17x23b.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_serif17x23b.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SANS17X23B_H +#define __GRAPHICS_NXFONTS_NXFONTS_SANS17X23B_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SANS17X23B + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 23 +#define NXFONT_MAXWIDTH 17 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 4 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 2, 11, 1, 6, 0} +#define NXFONT_BITMAP_33 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x0, 0xc0, 0xc0} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {1, 5, 3, 1, 6, 0} +#define NXFONT_BITMAP_34 {0xd8, 0xd8, 0x90} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {2, 9, 10, 0, 7, 0} +#define NXFONT_BITMAP_35 {0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x7f, 0x80, 0x36, 0x0, 0x36, 0x0, 0xff, 0x0, 0x6c, 0x0, 0x6c, 0x0, 0x6c, 0x0} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {1, 7, 14, 0, 5, 0} +#define NXFONT_BITMAP_36 {0x10, 0x7c, 0xd6, 0xd6, 0xd0, 0xf0, 0x78, 0x1c, 0x16, 0xd6, 0xd6, 0x7c, 0x10, 0x10} + +/* percent (37) */ +#define NXFONT_METRICS_37 {2, 12, 11, 0, 6, 0} +#define NXFONT_BITMAP_37 {0x78, 0x40, 0xcc, 0xc0, 0xcd, 0x80, 0x79, 0x0, 0x3, 0x0, 0x6, 0x0, 0x4, 0x0, 0xd, 0xe0, 0xb, 0x30, 0x1b, 0x30, 0x11, 0xe0} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {2, 9, 10, 1, 7, 0} +#define NXFONT_BITMAP_38 {0x38, 0x0, 0x6c, 0x0, 0x6c, 0x0, 0x38, 0x0, 0x73, 0x0, 0xfb, 0x0, 0xce, 0x0, 0xc6, 0x0, 0xcf, 0x0, 0x7d, 0x80} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 2, 3, 1, 6, 0} +#define NXFONT_BITMAP_39 {0xc0, 0xc0, 0x80} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 4, 14, 1, 6, 0} +#define NXFONT_BITMAP_40 {0x30, 0x60, 0x60, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0x60, 0x30} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 4, 14, 0, 6, 0} +#define NXFONT_BITMAP_41 {0xc0, 0x60, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0x60, 0xc0} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {1, 5, 4, 0, 6, 0} +#define NXFONT_BITMAP_42 {0x20, 0xf8, 0x70, 0xd8} + +/* plus (43) */ +#define NXFONT_METRICS_43 {1, 8, 7, 0, 9, 0} +#define NXFONT_BITMAP_43 {0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 3, 3, 0, 15, 0} +#define NXFONT_BITMAP_44 {0x60, 0x60, 0xc0} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 3, 1, 0, 12, 0} +#define NXFONT_BITMAP_45 {0xe0} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 2, 2, 1, 15, 0} +#define NXFONT_BITMAP_46 {0xc0, 0xc0} + +/* slash (47) */ +#define NXFONT_METRICS_47 {1, 4, 11, 0, 6, 0} +#define NXFONT_BITMAP_47 {0x10, 0x10, 0x30, 0x20, 0x20, 0x60, 0x40, 0x40, 0xc0, 0x80, 0x80} + +/* zero (48) */ +#define NXFONT_METRICS_48 {1, 7, 11, 0, 6, 0} +#define NXFONT_BITMAP_48 {0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38} + +/* one (49) */ +#define NXFONT_METRICS_49 {1, 4, 11, 1, 6, 0} +#define NXFONT_BITMAP_49 {0x30, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* two (50) */ +#define NXFONT_METRICS_50 {1, 7, 11, 0, 6, 0} +#define NXFONT_BITMAP_50 {0x7c, 0xc6, 0xc6, 0x6, 0xe, 0xc, 0x18, 0x30, 0x60, 0xc0, 0xfe} + +/* three (51) */ +#define NXFONT_METRICS_51 {1, 7, 11, 0, 6, 0} +#define NXFONT_BITMAP_51 {0x7c, 0xc6, 0xc6, 0x6, 0x6, 0x3c, 0x6, 0x6, 0xc6, 0xc6, 0x7c} + +/* four (52) */ +#define NXFONT_METRICS_52 {1, 8, 11, 0, 6, 0} +#define NXFONT_BITMAP_52 {0x6, 0xe, 0x1e, 0x36, 0x66, 0xc6, 0xc6, 0xff, 0x6, 0x6, 0x6} + +/* five (53) */ +#define NXFONT_METRICS_53 {1, 7, 11, 0, 6, 0} +#define NXFONT_BITMAP_53 {0x7e, 0x60, 0x60, 0xc0, 0xfc, 0xe, 0x6, 0x6, 0xc6, 0xcc, 0x78} + +/* six (54) */ +#define NXFONT_METRICS_54 {1, 7, 11, 0, 6, 0} +#define NXFONT_BITMAP_54 {0x3c, 0x66, 0x66, 0xc0, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c} + +/* seven (55) */ +#define NXFONT_METRICS_55 {1, 7, 11, 0, 6, 0} +#define NXFONT_BITMAP_55 {0xfe, 0x6, 0xc, 0xc, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x60} + +/* eight (56) */ +#define NXFONT_METRICS_56 {1, 7, 11, 0, 6, 0} +#define NXFONT_BITMAP_56 {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c} + +/* nine (57) */ +#define NXFONT_METRICS_57 {1, 7, 11, 0, 6, 0} +#define NXFONT_BITMAP_57 {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x6, 0xc6, 0xcc, 0x78} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 2, 8, 2, 9, 0} +#define NXFONT_BITMAP_58 {0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 3, 9, 1, 9, 0} +#define NXFONT_BITMAP_59 {0x60, 0x60, 0x0, 0x0, 0x0, 0x0, 0x60, 0x60, 0xc0} + +/* less (60) */ +#define NXFONT_METRICS_60 {1, 6, 5, 1, 10, 0} +#define NXFONT_BITMAP_60 {0x1c, 0x70, 0xc0, 0x70, 0x1c} + +/* equal (61) */ +#define NXFONT_METRICS_61 {1, 7, 3, 1, 11, 0} +#define NXFONT_BITMAP_61 {0xfe, 0x0, 0xfe} + +/* greater (62) */ +#define NXFONT_METRICS_62 {1, 6, 5, 1, 10, 0} +#define NXFONT_BITMAP_62 {0xe0, 0x38, 0xc, 0x38, 0xe0} + +/* question (63) */ +#define NXFONT_METRICS_63 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_63 {0x7c, 0xc6, 0xc6, 0x6, 0xc, 0x18, 0x30, 0x30, 0x0, 0x30, 0x30} + +/* at (64) */ +#define NXFONT_METRICS_64 {2, 13, 12, 0, 6, 0} +#define NXFONT_BITMAP_64 {0xf, 0x80, 0x38, 0xe0, 0x70, 0x70, 0x66, 0xb0, 0xcd, 0x98, 0xd9, 0x98, 0xdb, 0x18, 0xdb, 0x30, 0xce, 0xe0, 0x60, 0x0, 0x31, 0x80, 0x1f, 0x0} + +/* A (65) */ +#define NXFONT_METRICS_65 {2, 10, 11, 0, 6, 0} +#define NXFONT_BITMAP_65 {0xc, 0x0, 0xc, 0x0, 0x1e, 0x0, 0x12, 0x0, 0x33, 0x0, 0x33, 0x0, 0x61, 0x80, 0x7f, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0} + +/* B (66) */ +#define NXFONT_METRICS_66 {1, 8, 11, 1, 6, 0} +#define NXFONT_BITMAP_66 {0xfe, 0xc7, 0xc3, 0xc3, 0xc6, 0xfc, 0xc6, 0xc3, 0xc3, 0xc7, 0xfe} + +/* C (67) */ +#define NXFONT_METRICS_67 {2, 9, 11, 1, 6, 0} +#define NXFONT_BITMAP_67 {0x1f, 0x0, 0x7b, 0x80, 0x60, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0x60, 0x80, 0x7b, 0x80, 0x1f, 0x0} + +/* D (68) */ +#define NXFONT_METRICS_68 {2, 9, 11, 1, 6, 0} +#define NXFONT_BITMAP_68 {0xfc, 0x0, 0xc7, 0x0, 0xc3, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc3, 0x0, 0xc7, 0x0, 0xfc, 0x0} + +/* E (69) */ +#define NXFONT_METRICS_69 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_69 {0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe} + +/* F (70) */ +#define NXFONT_METRICS_70 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_70 {0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* G (71) */ +#define NXFONT_METRICS_71 {2, 9, 11, 1, 6, 0} +#define NXFONT_BITMAP_71 {0x1f, 0x0, 0x7b, 0x80, 0x60, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc7, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x61, 0x80, 0x7b, 0x80, 0x1e, 0x80} + +/* H (72) */ +#define NXFONT_METRICS_72 {1, 8, 11, 1, 6, 0} +#define NXFONT_BITMAP_72 {0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 2, 11, 1, 6, 0} +#define NXFONT_BITMAP_73 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* J (74) */ +#define NXFONT_METRICS_74 {1, 7, 11, 0, 6, 0} +#define NXFONT_BITMAP_74 {0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0xc6, 0xc6, 0xee, 0x7c} + +/* K (75) */ +#define NXFONT_METRICS_75 {2, 9, 11, 1, 6, 0} +#define NXFONT_BITMAP_75 {0xc3, 0x0, 0xc6, 0x0, 0xcc, 0x0, 0xd8, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xd8, 0x0, 0xcc, 0x0, 0xc6, 0x0, 0xc3, 0x0, 0xc1, 0x80} + +/* L (76) */ +#define NXFONT_METRICS_76 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_76 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe} + +/* M (77) */ +#define NXFONT_METRICS_77 {2, 11, 11, 1, 6, 0} +#define NXFONT_BITMAP_77 {0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xe0, 0xd1, 0x60, 0xd1, 0x60, 0xdb, 0x60, 0xca, 0x60, 0xce, 0x60, 0xc4, 0x60} + +/* N (78) */ +#define NXFONT_METRICS_78 {2, 9, 11, 1, 6, 0} +#define NXFONT_BITMAP_78 {0xc1, 0x80, 0xe1, 0x80, 0xe1, 0x80, 0xd1, 0x80, 0xd9, 0x80, 0xc9, 0x80, 0xcd, 0x80, 0xc5, 0x80, 0xc3, 0x80, 0xc3, 0x80, 0xc1, 0x80} + +/* O (79) */ +#define NXFONT_METRICS_79 {2, 10, 11, 1, 6, 0} +#define NXFONT_BITMAP_79 {0x1e, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* P (80) */ +#define NXFONT_METRICS_80 {1, 8, 11, 1, 6, 0} +#define NXFONT_BITMAP_80 {0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {2, 10, 11, 1, 6, 0} +#define NXFONT_BITMAP_81 {0x1e, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0xc0, 0x63, 0x80, 0x73, 0x80, 0x1e, 0xc0} + +/* R (82) */ +#define NXFONT_METRICS_82 {2, 9, 11, 1, 6, 0} +#define NXFONT_BITMAP_82 {0xfe, 0x0, 0xc7, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xc6, 0x0, 0xfe, 0x0, 0xc7, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xc1, 0x80} + +/* S (83) */ +#define NXFONT_METRICS_83 {1, 8, 11, 1, 6, 0} +#define NXFONT_BITMAP_83 {0x7e, 0xe7, 0xc3, 0xe0, 0x78, 0x1e, 0x7, 0x3, 0xc3, 0xee, 0x7c} + +/* T (84) */ +#define NXFONT_METRICS_84 {1, 8, 11, 0, 6, 0} +#define NXFONT_BITMAP_84 {0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18} + +/* U (85) */ +#define NXFONT_METRICS_85 {2, 9, 11, 1, 6, 0} +#define NXFONT_BITMAP_85 {0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x3e, 0x0} + +/* V (86) */ +#define NXFONT_METRICS_86 {2, 10, 11, 0, 6, 0} +#define NXFONT_BITMAP_86 {0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x61, 0x80, 0x73, 0x80, 0x33, 0x0, 0x33, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xc, 0x0, 0xc, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {2, 14, 11, 0, 6, 0} +#define NXFONT_BITMAP_87 {0xc3, 0xc, 0xc3, 0xc, 0xc3, 0xc, 0x67, 0x98, 0x64, 0x98, 0x64, 0x98, 0x6c, 0xd8, 0x2c, 0xd0, 0x38, 0x70, 0x18, 0x60, 0x18, 0x60} + +/* X (88) */ +#define NXFONT_METRICS_88 {2, 9, 11, 0, 6, 0} +#define NXFONT_BITMAP_88 {0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x36, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x36, 0x0, 0x63, 0x0, 0x63, 0x0, 0xc1, 0x80, 0xc1, 0x80} + +/* Y (89) */ +#define NXFONT_METRICS_89 {2, 10, 11, 0, 6, 0} +#define NXFONT_BITMAP_89 {0xc0, 0xc0, 0x61, 0x80, 0x61, 0x80, 0x33, 0x0, 0x33, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {1, 8, 11, 0, 6, 0} +#define NXFONT_BITMAP_90 {0xff, 0x3, 0x6, 0xc, 0x1c, 0x18, 0x30, 0x70, 0x60, 0xc0, 0xff} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 4, 14, 1, 6, 0} +#define NXFONT_BITMAP_91 {0xf0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf0} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {1, 4, 11, 0, 6, 0} +#define NXFONT_BITMAP_92 {0x80, 0x80, 0xc0, 0x40, 0x40, 0x60, 0x20, 0x20, 0x30, 0x10, 0x10} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 4, 14, 0, 6, 0} +#define NXFONT_BITMAP_93 {0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {1, 6, 5, 1, 6, 0} +#define NXFONT_BITMAP_94 {0x30, 0x78, 0x48, 0xcc, 0xcc} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {1, 8, 1, 0, 19, 0} +#define NXFONT_BITMAP_95 {0xff} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 3, 2, 1, 6, 0} +#define NXFONT_BITMAP_96 {0xc0, 0x60} + +/* a (97) */ +#define NXFONT_METRICS_97 {1, 7, 8, 1, 9, 0} +#define NXFONT_BITMAP_97 {0x78, 0xcc, 0xc, 0x7c, 0xcc, 0xcc, 0xdc, 0x76} + +/* b (98) */ +#define NXFONT_METRICS_98 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_98 {0xc0, 0xc0, 0xc0, 0xd8, 0xec, 0xc6, 0xc6, 0xc6, 0xc6, 0xec, 0xd8} + +/* c (99) */ +#define NXFONT_METRICS_99 {1, 6, 8, 1, 9, 0} +#define NXFONT_BITMAP_99 {0x38, 0x6c, 0xcc, 0xc0, 0xc0, 0xcc, 0x6c, 0x38} + +/* d (100) */ +#define NXFONT_METRICS_100 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_100 {0x6, 0x6, 0x6, 0x36, 0x6e, 0xc6, 0xc6, 0xc6, 0xc6, 0x6e, 0x36} + +/* e (101) */ +#define NXFONT_METRICS_101 {1, 6, 8, 1, 9, 0} +#define NXFONT_BITMAP_101 {0x78, 0xcc, 0xcc, 0xfc, 0xc0, 0xc0, 0xec, 0x78} + +/* f (102) */ +#define NXFONT_METRICS_102 {1, 5, 11, 0, 6, 0} +#define NXFONT_BITMAP_102 {0x38, 0x60, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* g (103) */ +#define NXFONT_METRICS_103 {1, 7, 11, 1, 9, 0} +#define NXFONT_BITMAP_103 {0x3a, 0x6e, 0xc6, 0xc6, 0xc6, 0xc6, 0x6e, 0x36, 0x6, 0xce, 0x7c} + +/* h (104) */ +#define NXFONT_METRICS_104 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_104 {0xc0, 0xc0, 0xc0, 0xdc, 0xee, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 2, 11, 1, 6, 0} +#define NXFONT_BITMAP_105 {0xc0, 0xc0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* j (106) */ +#define NXFONT_METRICS_106 {1, 3, 14, 0, 6, 0} +#define NXFONT_BITMAP_106 {0x60, 0x60, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xe0, 0xc0} + +/* k (107) */ +#define NXFONT_METRICS_107 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_107 {0xc0, 0xc0, 0xc0, 0xcc, 0xd8, 0xf0, 0xf0, 0xd8, 0xd8, 0xcc, 0xcc} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 2, 11, 1, 6, 0} +#define NXFONT_BITMAP_108 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* m (109) */ +#define NXFONT_METRICS_109 {2, 10, 8, 1, 9, 0} +#define NXFONT_BITMAP_109 {0xdb, 0x80, 0xee, 0xc0, 0xcc, 0xc0, 0xcc, 0xc0, 0xcc, 0xc0, 0xcc, 0xc0, 0xcc, 0xc0, 0xcc, 0xc0} + +/* n (110) */ +#define NXFONT_METRICS_110 {1, 7, 8, 1, 9, 0} +#define NXFONT_BITMAP_110 {0xdc, 0xee, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6} + +/* o (111) */ +#define NXFONT_METRICS_111 {1, 7, 8, 1, 9, 0} +#define NXFONT_BITMAP_111 {0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38} + +/* p (112) */ +#define NXFONT_METRICS_112 {1, 7, 11, 1, 9, 0} +#define NXFONT_BITMAP_112 {0xd8, 0xec, 0xc6, 0xc6, 0xc6, 0xc6, 0xec, 0xd8, 0xc0, 0xc0, 0xc0} + +/* q (113) */ +#define NXFONT_METRICS_113 {1, 7, 11, 1, 9, 0} +#define NXFONT_BITMAP_113 {0x36, 0x6e, 0xc6, 0xc6, 0xc6, 0xc6, 0x6e, 0x36, 0x6, 0x6, 0x6} + +/* r (114) */ +#define NXFONT_METRICS_114 {1, 5, 8, 1, 9, 0} +#define NXFONT_BITMAP_114 {0xd8, 0xf8, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* s (115) */ +#define NXFONT_METRICS_115 {1, 6, 8, 1, 9, 0} +#define NXFONT_BITMAP_115 {0x78, 0xcc, 0xe0, 0x78, 0x1c, 0xc, 0xec, 0x78} + +/* t (116) */ +#define NXFONT_METRICS_116 {1, 5, 10, 0, 7, 0} +#define NXFONT_BITMAP_116 {0x60, 0x60, 0xf8, 0x60, 0x60, 0x60, 0x60, 0x60, 0x68, 0x30} + +/* u (117) */ +#define NXFONT_METRICS_117 {1, 7, 8, 1, 9, 0} +#define NXFONT_BITMAP_117 {0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xee, 0x76} + +/* v (118) */ +#define NXFONT_METRICS_118 {1, 8, 8, 0, 9, 0} +#define NXFONT_BITMAP_118 {0xc3, 0xc3, 0x66, 0x66, 0x24, 0x3c, 0x18, 0x18} + +/* w (119) */ +#define NXFONT_METRICS_119 {2, 10, 8, 0, 9, 0} +#define NXFONT_BITMAP_119 {0xcc, 0xc0, 0xcc, 0xc0, 0xcc, 0xc0, 0x6d, 0x80, 0x6d, 0x80, 0x33, 0x0, 0x33, 0x0, 0x33, 0x0} + +/* x (120) */ +#define NXFONT_METRICS_120 {1, 7, 8, 0, 9, 0} +#define NXFONT_BITMAP_120 {0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0xc6} + +/* y (121) */ +#define NXFONT_METRICS_121 {1, 8, 11, 0, 9, 0} +#define NXFONT_BITMAP_121 {0xc3, 0xc3, 0x66, 0x66, 0x24, 0x3c, 0x18, 0x18, 0x18, 0x30, 0x70} + +/* z (122) */ +#define NXFONT_METRICS_122 {1, 6, 8, 0, 9, 0} +#define NXFONT_BITMAP_122 {0xfc, 0xc, 0x18, 0x30, 0x30, 0x60, 0xc0, 0xfc} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {1, 5, 14, 0, 6, 0} +#define NXFONT_BITMAP_123 {0x18, 0x30, 0x30, 0x30, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 1, 14, 2, 6, 0} +#define NXFONT_BITMAP_124 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 5, 14, 1, 6, 0} +#define NXFONT_BITMAP_125 {0xc0, 0x60, 0x60, 0x60, 0x60, 0x30, 0x18, 0x30, 0x60, 0x60, 0x60, 0x60, 0x60, 0xc0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {1, 7, 3, 1, 11, 0} +#define NXFONT_BITMAP_126 {0x72, 0xde, 0x8c} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 2, 11, 1, 9, 0} +#define NXFONT_BITMAP_161 {0xc0, 0xc0, 0x0, 0x40, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* cent (162) */ +#define NXFONT_METRICS_162 {1, 7, 10, 0, 8, 0} +#define NXFONT_BITMAP_162 {0x4, 0x3c, 0x6e, 0xc8, 0xd0, 0xd0, 0xe6, 0x66, 0x7c, 0x40} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {1, 8, 11, 0, 6, 0} +#define NXFONT_BITMAP_163 {0x3c, 0x66, 0x66, 0x60, 0xfc, 0x30, 0x30, 0x30, 0x60, 0xfb, 0xde} + +/* currency (164) */ +#define NXFONT_METRICS_164 {1, 7, 7, 0, 8, 0} +#define NXFONT_BITMAP_164 {0x82, 0x7c, 0x6c, 0x6c, 0x6c, 0x7c, 0x82} + +/* yen (165) */ +#define NXFONT_METRICS_165 {1, 8, 11, 0, 6, 0} +#define NXFONT_BITMAP_165 {0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x3c, 0x7e, 0x18, 0x7e, 0x18, 0x18} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 1, 14, 2, 6, 0} +#define NXFONT_BITMAP_166 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* section (167) */ +#define NXFONT_METRICS_167 {1, 6, 14, 1, 6, 0} +#define NXFONT_BITMAP_167 {0x78, 0xcc, 0xcc, 0xe0, 0x78, 0xdc, 0xcc, 0xcc, 0xec, 0x78, 0x1c, 0xcc, 0xcc, 0x78} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 5, 2, 0, 6, 0} +#define NXFONT_BITMAP_168 {0xd8, 0xd8} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {2, 10, 11, 1, 6, 0} +#define NXFONT_BITMAP_169 {0x1e, 0x0, 0x61, 0x80, 0x4c, 0x80, 0xd2, 0xc0, 0x90, 0x40, 0x90, 0x40, 0x90, 0x40, 0x92, 0x40, 0x4c, 0x80, 0x61, 0x80, 0x1e, 0x0} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {1, 5, 7, 0, 6, 0} +#define NXFONT_BITMAP_170 {0x70, 0x90, 0x70, 0xd0, 0xf8, 0x0, 0xf8} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {1, 7, 5, 1, 10, 0} +#define NXFONT_BITMAP_171 {0x36, 0x6c, 0xd8, 0x6c, 0x36} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {1, 7, 4, 1, 11, 0} +#define NXFONT_BITMAP_172 {0xfe, 0xfe, 0x2, 0x2} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 3, 1, 0, 12, 0} +#define NXFONT_BITMAP_173 {0xe0} + +/* registered (174) */ +#define NXFONT_METRICS_174 {2, 10, 11, 1, 6, 0} +#define NXFONT_BITMAP_174 {0x1e, 0x0, 0x61, 0x80, 0x5c, 0x80, 0x92, 0x40, 0x92, 0x40, 0x9c, 0x40, 0x92, 0x40, 0x92, 0x40, 0x52, 0x80, 0x61, 0x80, 0x1e, 0x0} + +/* macron (175) */ +#define NXFONT_METRICS_175 {1, 5, 1, 0, 7, 0} +#define NXFONT_BITMAP_175 {0xf8} + +/* degree (176) */ +#define NXFONT_METRICS_176 {1, 4, 4, 1, 6, 0} +#define NXFONT_BITMAP_176 {0x60, 0x90, 0x90, 0x60} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {1, 8, 9, 0, 8, 0} +#define NXFONT_BITMAP_177 {0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x0, 0xff} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {1, 4, 6, 0, 6, 0} +#define NXFONT_BITMAP_178 {0x60, 0xb0, 0x30, 0x60, 0xc0, 0xf0} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {1, 4, 6, 0, 6, 0} +#define NXFONT_BITMAP_179 {0x60, 0xb0, 0x60, 0x30, 0xb0, 0x60} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 3, 2, 1, 6, 0} +#define NXFONT_BITMAP_180 {0x60, 0xc0} + +/* mu (181) */ +#define NXFONT_METRICS_181 {1, 7, 11, 1, 9, 0} +#define NXFONT_BITMAP_181 {0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xee, 0xf6, 0xc0, 0xc0, 0xc0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {1, 8, 14, 0, 6, 0} +#define NXFONT_BITMAP_182 {0x3f, 0x7a, 0xfa, 0xfa, 0xfa, 0x7a, 0x3a, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 2, 2, 1, 12, 0} +#define NXFONT_BITMAP_183 {0xc0, 0xc0} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 5, 3, 0, 17, 0} +#define NXFONT_BITMAP_184 {0x18, 0xd8, 0x70} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 3, 6, 0, 6, 0} +#define NXFONT_BITMAP_185 {0x60, 0xe0, 0x60, 0x60, 0x60, 0x60} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {1, 5, 7, 0, 6, 0} +#define NXFONT_BITMAP_186 {0x70, 0xd8, 0xd8, 0xd8, 0x70, 0x0, 0xf8} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {1, 7, 5, 1, 10, 0} +#define NXFONT_BITMAP_187 {0xd8, 0x6c, 0x36, 0x6c, 0xd8} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {2, 12, 11, 0, 6, 0} +#define NXFONT_BITMAP_188 {0x61, 0x80, 0xe1, 0x80, 0x63, 0x0, 0x63, 0x0, 0x66, 0x0, 0x66, 0x20, 0x6, 0x60, 0xc, 0xe0, 0xd, 0x60, 0x19, 0xf0, 0x18, 0x60} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {2, 11, 11, 0, 6, 0} +#define NXFONT_BITMAP_189 {0x61, 0x80, 0xe1, 0x80, 0x63, 0x0, 0x63, 0x0, 0x66, 0x0, 0x66, 0xc0, 0x7, 0x60, 0xc, 0x60, 0xc, 0xc0, 0x19, 0x80, 0x19, 0xe0} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {2, 12, 11, 0, 6, 0} +#define NXFONT_BITMAP_190 {0x61, 0x80, 0xb1, 0x80, 0x63, 0x0, 0x33, 0x0, 0xb6, 0x0, 0x66, 0x20, 0x6, 0x60, 0xc, 0xe0, 0xd, 0x60, 0x19, 0xf0, 0x18, 0x60} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {1, 7, 11, 1, 9, 0} +#define NXFONT_BITMAP_191 {0x18, 0x18, 0x0, 0x18, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {2, 10, 14, 0, 3, 0} +#define NXFONT_BITMAP_192 {0x18, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0x1e, 0x0, 0x12, 0x0, 0x33, 0x0, 0x33, 0x0, 0x61, 0x80, 0x7f, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {2, 10, 14, 0, 3, 0} +#define NXFONT_BITMAP_193 {0x6, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0x1e, 0x0, 0x12, 0x0, 0x33, 0x0, 0x33, 0x0, 0x61, 0x80, 0x7f, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {2, 10, 14, 0, 3, 0} +#define NXFONT_BITMAP_194 {0xe, 0x0, 0x1b, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0x1e, 0x0, 0x12, 0x0, 0x33, 0x0, 0x33, 0x0, 0x61, 0x80, 0x7f, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {2, 10, 14, 0, 3, 0} +#define NXFONT_BITMAP_195 {0xd, 0x0, 0x16, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0x1e, 0x0, 0x12, 0x0, 0x33, 0x0, 0x33, 0x0, 0x61, 0x80, 0x7f, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {2, 10, 14, 0, 3, 0} +#define NXFONT_BITMAP_196 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0x1e, 0x0, 0x12, 0x0, 0x33, 0x0, 0x33, 0x0, 0x61, 0x80, 0x7f, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {2, 10, 14, 0, 3, 0} +#define NXFONT_BITMAP_197 {0xc, 0x0, 0x12, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0x1e, 0x0, 0x12, 0x0, 0x33, 0x0, 0x33, 0x0, 0x61, 0x80, 0x7f, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0} + +/* AE (198) */ +#define NXFONT_METRICS_198 {2, 14, 11, 0, 6, 0} +#define NXFONT_BITMAP_198 {0xf, 0xfc, 0xf, 0x0, 0x1b, 0x0, 0x13, 0x0, 0x33, 0x0, 0x33, 0xf8, 0x63, 0x0, 0x7f, 0x0, 0x63, 0x0, 0xc3, 0x0, 0xc3, 0xfc} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {2, 9, 14, 1, 6, 0} +#define NXFONT_BITMAP_199 {0x1f, 0x0, 0x7b, 0x80, 0x60, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0x60, 0x80, 0x7b, 0x80, 0x1f, 0x0, 0x6, 0x0, 0x36, 0x0, 0x1c, 0x0} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {1, 7, 14, 1, 3, 0} +#define NXFONT_BITMAP_200 {0x30, 0x18, 0x0, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {1, 7, 14, 1, 3, 0} +#define NXFONT_BITMAP_201 {0xc, 0x18, 0x0, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {1, 7, 14, 1, 3, 0} +#define NXFONT_BITMAP_202 {0x1c, 0x36, 0x0, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {1, 7, 14, 1, 3, 0} +#define NXFONT_BITMAP_203 {0x6c, 0x6c, 0x0, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {1, 3, 14, 0, 3, 0} +#define NXFONT_BITMAP_204 {0xc0, 0x60, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 3, 14, 1, 3, 0} +#define NXFONT_BITMAP_205 {0x60, 0xc0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* Icircumflex (206) */ +#define NXFONT_METRICS_206 {1, 5, 14, 0, 3, 0} +#define NXFONT_BITMAP_206 {0x70, 0xd8, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {1, 5, 14, 0, 3, 0} +#define NXFONT_BITMAP_207 {0xd8, 0xd8, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* Eth (208) */ +#define NXFONT_METRICS_208 {2, 10, 11, 0, 6, 0} +#define NXFONT_BITMAP_208 {0x7e, 0x0, 0x63, 0x80, 0x61, 0x80, 0x60, 0xc0, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x61, 0x80, 0x63, 0x80, 0x7e, 0x0} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {2, 9, 14, 1, 3, 0} +#define NXFONT_BITMAP_209 {0x1a, 0x0, 0x2c, 0x0, 0x0, 0x0, 0xc1, 0x80, 0xe1, 0x80, 0xe1, 0x80, 0xd1, 0x80, 0xd9, 0x80, 0xc9, 0x80, 0xcd, 0x80, 0xc5, 0x80, 0xc3, 0x80, 0xc3, 0x80, 0xc1, 0x80} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {2, 10, 14, 1, 3, 0} +#define NXFONT_BITMAP_210 {0x18, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {2, 10, 14, 1, 3, 0} +#define NXFONT_BITMAP_211 {0x6, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {2, 10, 14, 1, 3, 0} +#define NXFONT_BITMAP_212 {0xe, 0x0, 0x1b, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {2, 10, 14, 1, 3, 0} +#define NXFONT_BITMAP_213 {0xd, 0x0, 0x16, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {2, 10, 14, 1, 3, 0} +#define NXFONT_BITMAP_214 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {1, 8, 7, 0, 9, 0} +#define NXFONT_BITMAP_215 {0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {2, 12, 11, 0, 6, 0} +#define NXFONT_BITMAP_216 {0xf, 0x30, 0x39, 0xe0, 0x30, 0xc0, 0x61, 0xe0, 0x63, 0x60, 0x66, 0x60, 0x6c, 0x60, 0x78, 0x60, 0x30, 0xc0, 0x79, 0xc0, 0xcf, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {2, 9, 14, 1, 3, 0} +#define NXFONT_BITMAP_217 {0x18, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x3e, 0x0} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {2, 9, 14, 1, 3, 0} +#define NXFONT_BITMAP_218 {0x6, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x3e, 0x0} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {2, 9, 14, 1, 3, 0} +#define NXFONT_BITMAP_219 {0x1c, 0x0, 0x36, 0x0, 0x0, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x3e, 0x0} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {2, 9, 14, 1, 3, 0} +#define NXFONT_BITMAP_220 {0x63, 0x0, 0x63, 0x0, 0x0, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x3e, 0x0} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {2, 10, 14, 0, 3, 0} +#define NXFONT_BITMAP_221 {0x6, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0x61, 0x80, 0x61, 0x80, 0x33, 0x0, 0x33, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {1, 8, 11, 1, 6, 0} +#define NXFONT_BITMAP_222 {0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_223 {0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xd8, 0xcc, 0xcc, 0xcc, 0xcc, 0xd8} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_224 {0x30, 0x18, 0x0, 0x78, 0xcc, 0xc, 0x7c, 0xcc, 0xcc, 0xdc, 0x76} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_225 {0x18, 0x30, 0x0, 0x78, 0xcc, 0xc, 0x7c, 0xcc, 0xcc, 0xdc, 0x76} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_226 {0x38, 0x6c, 0x0, 0x78, 0xcc, 0xc, 0x7c, 0xcc, 0xcc, 0xdc, 0x76} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_227 {0x34, 0x58, 0x0, 0x78, 0xcc, 0xc, 0x7c, 0xcc, 0xcc, 0xdc, 0x76} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_228 {0x6c, 0x6c, 0x0, 0x78, 0xcc, 0xc, 0x7c, 0xcc, 0xcc, 0xdc, 0x76} + +/* aring (229) */ +#define NXFONT_METRICS_229 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_229 {0x30, 0x48, 0x30, 0x78, 0xcc, 0xc, 0x7c, 0xcc, 0xcc, 0xdc, 0x76} + +/* ae (230) */ +#define NXFONT_METRICS_230 {2, 11, 8, 1, 9, 0} +#define NXFONT_BITMAP_230 {0x7b, 0xc0, 0xce, 0x60, 0xc, 0x60, 0x7f, 0xe0, 0xcc, 0x0, 0xcc, 0x0, 0xde, 0x60, 0x77, 0xc0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {1, 7, 11, 1, 9, 0} +#define NXFONT_BITMAP_231 {0x3c, 0x66, 0xc6, 0xc0, 0xc0, 0xc6, 0x66, 0x3c, 0x18, 0x58, 0x70} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_232 {0x60, 0x30, 0x0, 0x78, 0xcc, 0xcc, 0xfc, 0xc0, 0xc0, 0xec, 0x78} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_233 {0x18, 0x30, 0x0, 0x78, 0xcc, 0xcc, 0xfc, 0xc0, 0xc0, 0xec, 0x78} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_234 {0x38, 0x6c, 0x0, 0x78, 0xcc, 0xcc, 0xfc, 0xc0, 0xc0, 0xec, 0x78} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {1, 6, 11, 1, 6, 0} +#define NXFONT_BITMAP_235 {0x6c, 0x6c, 0x0, 0x78, 0xcc, 0xcc, 0xfc, 0xc0, 0xc0, 0xec, 0x78} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 3, 11, 0, 6, 0} +#define NXFONT_BITMAP_236 {0xc0, 0x60, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 3, 11, 1, 6, 0} +#define NXFONT_BITMAP_237 {0x60, 0xc0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* icircumflex (238) */ +#define NXFONT_METRICS_238 {1, 5, 11, 0, 6, 0} +#define NXFONT_BITMAP_238 {0x70, 0xd8, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 5, 11, 0, 6, 0} +#define NXFONT_BITMAP_239 {0xd8, 0xd8, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* eth (240) */ +#define NXFONT_METRICS_240 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_240 {0x6c, 0x38, 0x48, 0x3c, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_241 {0x34, 0x58, 0x0, 0xdc, 0xee, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_242 {0x30, 0x18, 0x0, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_243 {0x18, 0x30, 0x0, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_244 {0x38, 0x6c, 0x0, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_245 {0x34, 0x58, 0x0, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_246 {0x6c, 0x6c, 0x0, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38} + +/* divide (247) */ +#define NXFONT_METRICS_247 {1, 8, 7, 0, 9, 0} +#define NXFONT_BITMAP_247 {0x18, 0x18, 0x0, 0xff, 0x0, 0x18, 0x18} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {1, 7, 8, 1, 9, 0} +#define NXFONT_BITMAP_248 {0x3a, 0x6c, 0xce, 0xd6, 0xd6, 0xe6, 0x6c, 0xb8} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_249 {0x30, 0x18, 0x0, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xee, 0x76} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_250 {0xc, 0x18, 0x0, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xee, 0x76} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_251 {0x38, 0x6c, 0x0, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xee, 0x76} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {1, 7, 11, 1, 6, 0} +#define NXFONT_BITMAP_252 {0x6c, 0x6c, 0x0, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xee, 0x76} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {1, 8, 14, 0, 6, 0} +#define NXFONT_BITMAP_253 {0xc, 0x18, 0x0, 0xc3, 0xc3, 0x66, 0x66, 0x24, 0x3c, 0x18, 0x18, 0x18, 0x30, 0x70} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {1, 7, 14, 1, 6, 0} +#define NXFONT_BITMAP_254 {0xc0, 0xc0, 0xc0, 0xd8, 0xec, 0xc6, 0xc6, 0xc6, 0xc6, 0xec, 0xd8, 0xc0, 0xc0, 0xc0} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {1, 8, 14, 0, 6, 0} +#define NXFONT_BITMAP_255 {0x36, 0x36, 0x0, 0xc3, 0xc3, 0x66, 0x66, 0x24, 0x3c, 0x18, 0x18, 0x18, 0x30, 0x70} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SANS17X23B_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_sans20x26.h b/nuttx/graphics/nxfonts/nxfonts_sans20x26.h new file mode 100644 index 0000000000..c887da5e57 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_sans20x26.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_serif30x26.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SANS20X26_H +#define __GRAPHICS_NXFONTS_NXFONTS_SANS20X26_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SANS20X26 + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 26 +#define NXFONT_MAXWIDTH 20 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 5 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 1, 12, 2, 8, 0} +#define NXFONT_BITMAP_33 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0, 0x80, 0x80} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {1, 4, 4, 1, 8, 0} +#define NXFONT_BITMAP_34 {0x90, 0x90, 0x90, 0x90} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {1, 8, 11, 0, 9, 0} +#define NXFONT_BITMAP_35 {0x12, 0x12, 0x12, 0x7f, 0x24, 0x24, 0x24, 0xfe, 0x48, 0x48, 0x48} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {1, 7, 15, 1, 7, 0} +#define NXFONT_BITMAP_36 {0x10, 0x7c, 0x92, 0x92, 0x90, 0x50, 0x30, 0x18, 0x14, 0x12, 0x92, 0x92, 0x7c, 0x10, 0x10} + +/* percent (37) */ +#define NXFONT_METRICS_37 {2, 12, 12, 0, 8, 0} +#define NXFONT_BITMAP_37 {0x70, 0x40, 0x88, 0x80, 0x88, 0x80, 0x89, 0x0, 0x72, 0x0, 0x2, 0x0, 0x4, 0x0, 0x4, 0xe0, 0x9, 0x10, 0x11, 0x10, 0x11, 0x10, 0x20, 0xe0} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {2, 10, 12, 0, 8, 0} +#define NXFONT_BITMAP_38 {0x18, 0x0, 0x24, 0x0, 0x42, 0x0, 0x42, 0x0, 0x24, 0x0, 0x18, 0x0, 0x29, 0x0, 0x45, 0x0, 0x82, 0x0, 0x83, 0x0, 0x44, 0x80, 0x38, 0x40} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 2, 4, 0, 8, 0} +#define NXFONT_BITMAP_39 {0xc0, 0xc0, 0x40, 0x40} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 3, 16, 1, 8, 0} +#define NXFONT_BITMAP_40 {0x20, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x20} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 3, 16, 1, 8, 0} +#define NXFONT_BITMAP_41 {0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x80} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {1, 5, 5, 0, 8, 0} +#define NXFONT_BITMAP_42 {0x20, 0xa8, 0x70, 0x50, 0x88} + +/* plus (43) */ +#define NXFONT_METRICS_43 {2, 9, 9, 0, 11, 0} +#define NXFONT_BITMAP_43 {0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xff, 0x80, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 2, 4, 1, 18, 0} +#define NXFONT_BITMAP_44 {0x40, 0x40, 0x40, 0x80} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 4, 1, 0, 15, 0} +#define NXFONT_BITMAP_45 {0xf0} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 1, 2, 2, 18, 0} +#define NXFONT_BITMAP_46 {0x80, 0x80} + +/* slash (47) */ +#define NXFONT_METRICS_47 {1, 4, 12, 0, 8, 0} +#define NXFONT_BITMAP_47 {0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80} + +/* zero (48) */ +#define NXFONT_METRICS_48 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_48 {0x38, 0x44, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x44, 0x38} + +/* one (49) */ +#define NXFONT_METRICS_49 {1, 3, 12, 3, 8, 0} +#define NXFONT_BITMAP_49 {0x20, 0x20, 0x60, 0xa0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20} + +/* two (50) */ +#define NXFONT_METRICS_50 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_50 {0x38, 0x44, 0x82, 0x82, 0x2, 0x4, 0x8, 0x30, 0x40, 0x80, 0x80, 0xfe} + +/* three (51) */ +#define NXFONT_METRICS_51 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_51 {0x38, 0x44, 0x82, 0x82, 0x4, 0x38, 0x4, 0x2, 0x82, 0x82, 0x44, 0x38} + +/* four (52) */ +#define NXFONT_METRICS_52 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_52 {0xc, 0x14, 0x14, 0x24, 0x24, 0x44, 0x44, 0x84, 0xff, 0x4, 0x4, 0x4} + +/* five (53) */ +#define NXFONT_METRICS_53 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_53 {0x3e, 0x20, 0x20, 0x40, 0x78, 0x44, 0x2, 0x2, 0x2, 0x82, 0x44, 0x38} + +/* six (54) */ +#define NXFONT_METRICS_54 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_54 {0x3c, 0x42, 0x82, 0x80, 0xb8, 0xc4, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* seven (55) */ +#define NXFONT_METRICS_55 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_55 {0xff, 0x1, 0x2, 0x4, 0x4, 0x8, 0x8, 0x10, 0x10, 0x10, 0x20, 0x20} + +/* eight (56) */ +#define NXFONT_METRICS_56 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_56 {0x38, 0x44, 0x82, 0x82, 0x44, 0x38, 0x44, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* nine (57) */ +#define NXFONT_METRICS_57 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_57 {0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x46, 0x3a, 0x2, 0x82, 0x84, 0x78} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 1, 9, 2, 11, 0} +#define NXFONT_BITMAP_58 {0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 2, 11, 1, 11, 0} +#define NXFONT_BITMAP_59 {0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x40, 0x40, 0x80} + +/* less (60) */ +#define NXFONT_METRICS_60 {2, 9, 9, 0, 11, 0} +#define NXFONT_BITMAP_60 {0x1, 0x80, 0x6, 0x0, 0x18, 0x0, 0x60, 0x0, 0x80, 0x0, 0x60, 0x0, 0x18, 0x0, 0x6, 0x0, 0x1, 0x80} + +/* equal (61) */ +#define NXFONT_METRICS_61 {1, 8, 4, 0, 14, 0} +#define NXFONT_BITMAP_61 {0xff, 0x0, 0x0, 0xff} + +/* greater (62) */ +#define NXFONT_METRICS_62 {2, 9, 9, 1, 11, 0} +#define NXFONT_BITMAP_62 {0xc0, 0x0, 0x30, 0x0, 0xc, 0x0, 0x3, 0x0, 0x0, 0x80, 0x3, 0x0, 0xc, 0x0, 0x30, 0x0, 0xc0, 0x0} + +/* question (63) */ +#define NXFONT_METRICS_63 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_63 {0x38, 0x44, 0x82, 0x82, 0x2, 0x4, 0x8, 0x10, 0x10, 0x0, 0x10, 0x10} + +/* at (64) */ +#define NXFONT_METRICS_64 {2, 13, 14, 1, 8, 0} +#define NXFONT_BITMAP_64 {0x7, 0x80, 0x18, 0x60, 0x20, 0x10, 0x43, 0xd0, 0x4c, 0x48, 0x88, 0x48, 0x90, 0x88, 0x90, 0x88, 0x90, 0x90, 0x99, 0x90, 0x4e, 0x60, 0x40, 0x0, 0x30, 0x60, 0xf, 0x80} + +/* A (65) */ +#define NXFONT_METRICS_65 {2, 10, 12, 0, 8, 0} +#define NXFONT_BITMAP_65 {0xc, 0x0, 0xc, 0x0, 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0x21, 0x0, 0x21, 0x0, 0x7f, 0x80, 0x40, 0x80, 0x40, 0x80, 0x80, 0x40, 0x80, 0x40} + +/* B (66) */ +#define NXFONT_METRICS_66 {2, 9, 12, 1, 8, 0} +#define NXFONT_BITMAP_66 {0xfc, 0x0, 0x82, 0x0, 0x81, 0x0, 0x81, 0x0, 0x82, 0x0, 0xfe, 0x0, 0x81, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x0, 0xfe, 0x0} + +/* C (67) */ +#define NXFONT_METRICS_67 {2, 10, 12, 1, 8, 0} +#define NXFONT_BITMAP_67 {0xf, 0x0, 0x30, 0x80, 0x40, 0x40, 0x40, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x40, 0x0, 0x40, 0x40, 0x30, 0x80, 0xf, 0x0} + +/* D (68) */ +#define NXFONT_METRICS_68 {2, 10, 12, 1, 8, 0} +#define NXFONT_BITMAP_68 {0xfc, 0x0, 0x83, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x80, 0x80, 0x80, 0x83, 0x0, 0xfc, 0x0} + +/* E (69) */ +#define NXFONT_METRICS_69 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_69 {0xff, 0x80, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff} + +/* F (70) */ +#define NXFONT_METRICS_70 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_70 {0xfe, 0x80, 0x80, 0x80, 0x80, 0xfe, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* G (71) */ +#define NXFONT_METRICS_71 {2, 10, 12, 1, 8, 0} +#define NXFONT_BITMAP_71 {0xe, 0x0, 0x31, 0x80, 0x40, 0x40, 0x40, 0x0, 0x80, 0x0, 0x80, 0x0, 0x87, 0xc0, 0x80, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x31, 0x40, 0xe, 0x40} + +/* H (72) */ +#define NXFONT_METRICS_72 {2, 9, 12, 1, 8, 0} +#define NXFONT_BITMAP_72 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 1, 12, 1, 8, 0} +#define NXFONT_BITMAP_73 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* J (74) */ +#define NXFONT_METRICS_74 {1, 6, 12, 0, 8, 0} +#define NXFONT_BITMAP_74 {0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x84, 0x84, 0x84, 0x78} + +/* K (75) */ +#define NXFONT_METRICS_75 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_75 {0x81, 0x82, 0x84, 0x88, 0x90, 0xb0, 0xc8, 0x88, 0x84, 0x82, 0x82, 0x81} + +/* L (76) */ +#define NXFONT_METRICS_76 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_76 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xfe} + +/* M (77) */ +#define NXFONT_METRICS_77 {2, 11, 12, 1, 8, 0} +#define NXFONT_BITMAP_77 {0x80, 0x20, 0xc0, 0x60, 0xc0, 0x60, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x91, 0x20, 0x91, 0x20, 0x91, 0x20, 0x8a, 0x20, 0x8a, 0x20, 0x84, 0x20} + +/* N (78) */ +#define NXFONT_METRICS_78 {2, 9, 12, 1, 8, 0} +#define NXFONT_BITMAP_78 {0x80, 0x80, 0xc0, 0x80, 0xa0, 0x80, 0xa0, 0x80, 0x90, 0x80, 0x88, 0x80, 0x88, 0x80, 0x84, 0x80, 0x82, 0x80, 0x82, 0x80, 0x81, 0x80, 0x80, 0x80} + +/* O (79) */ +#define NXFONT_METRICS_79 {2, 11, 12, 1, 8, 0} +#define NXFONT_BITMAP_79 {0xe, 0x0, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x40, 0x40, 0x40, 0x40, 0x31, 0x80, 0xe, 0x0} + +/* P (80) */ +#define NXFONT_METRICS_80 {1, 8, 12, 2, 8, 0} +#define NXFONT_BITMAP_80 {0xfc, 0x82, 0x81, 0x81, 0x82, 0xfc, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* Q (81) */ +#define NXFONT_METRICS_81 {2, 11, 13, 1, 8, 0} +#define NXFONT_BITMAP_81 {0xe, 0x0, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x40, 0x40, 0x42, 0x40, 0x31, 0x80, 0xe, 0x80, 0x0, 0x40} + +/* R (82) */ +#define NXFONT_METRICS_82 {2, 9, 12, 2, 8, 0} +#define NXFONT_BITMAP_82 {0xfc, 0x0, 0x82, 0x0, 0x81, 0x0, 0x81, 0x0, 0x82, 0x0, 0xfc, 0x0, 0x82, 0x0, 0x81, 0x0, 0x81, 0x0, 0x81, 0x0, 0x81, 0x0, 0x80, 0x80} + +/* S (83) */ +#define NXFONT_METRICS_83 {2, 9, 12, 1, 8, 0} +#define NXFONT_BITMAP_83 {0x3e, 0x0, 0x41, 0x0, 0x80, 0x80, 0x80, 0x80, 0x40, 0x0, 0x30, 0x0, 0xe, 0x0, 0x1, 0x0, 0x80, 0x80, 0x80, 0x80, 0x41, 0x0, 0x3e, 0x0} + +/* T (84) */ +#define NXFONT_METRICS_84 {2, 9, 12, 0, 8, 0} +#define NXFONT_BITMAP_84 {0xff, 0x80, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* U (85) */ +#define NXFONT_METRICS_85 {2, 9, 12, 1, 8, 0} +#define NXFONT_BITMAP_85 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x0, 0x3e, 0x0} + +/* V (86) */ +#define NXFONT_METRICS_86 {2, 10, 12, 0, 8, 0} +#define NXFONT_BITMAP_86 {0x80, 0x40, 0x80, 0x40, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x21, 0x0, 0x21, 0x0, 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0xc, 0x0, 0xc, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {2, 13, 12, 1, 8, 0} +#define NXFONT_BITMAP_87 {0x82, 0x8, 0x82, 0x8, 0x82, 0x8, 0x45, 0x10, 0x45, 0x10, 0x45, 0x10, 0x28, 0xa0, 0x28, 0xa0, 0x28, 0xa0, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40} + +/* X (88) */ +#define NXFONT_METRICS_88 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_88 {0x81, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x42, 0x42, 0x81} + +/* Y (89) */ +#define NXFONT_METRICS_89 {2, 9, 12, 1, 8, 0} +#define NXFONT_BITMAP_89 {0x80, 0x80, 0x41, 0x0, 0x41, 0x0, 0x22, 0x0, 0x22, 0x0, 0x14, 0x0, 0x1c, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {2, 9, 12, 0, 8, 0} +#define NXFONT_BITMAP_90 {0x7f, 0x80, 0x1, 0x0, 0x3, 0x0, 0x2, 0x0, 0x4, 0x0, 0xc, 0x0, 0x8, 0x0, 0x10, 0x0, 0x30, 0x0, 0x20, 0x0, 0x40, 0x0, 0xff, 0x80} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 3, 15, 1, 8, 0} +#define NXFONT_BITMAP_91 {0xe0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe0} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {1, 4, 12, 0, 8, 0} +#define NXFONT_BITMAP_92 {0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 3, 15, 0, 8, 0} +#define NXFONT_BITMAP_93 {0xe0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xe0} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {1, 7, 7, 0, 8, 0} +#define NXFONT_BITMAP_94 {0x10, 0x28, 0x28, 0x44, 0x44, 0x82, 0x82} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {2, 9, 1, 0, 22, 0} +#define NXFONT_BITMAP_95 {0xff, 0x80} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 3, 3, 0, 7, 0} +#define NXFONT_BITMAP_96 {0x80, 0xc0, 0x20} + +/* a (97) */ +#define NXFONT_METRICS_97 {1, 8, 9, 1, 11, 0} +#define NXFONT_BITMAP_97 {0x7c, 0x82, 0x2, 0x6, 0x7a, 0x82, 0x82, 0x86, 0x7b} + +/* b (98) */ +#define NXFONT_METRICS_98 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_98 {0x80, 0x80, 0x80, 0xb8, 0xc4, 0x82, 0x82, 0x82, 0x82, 0x82, 0xc4, 0xb8} + +/* c (99) */ +#define NXFONT_METRICS_99 {1, 7, 9, 1, 11, 0} +#define NXFONT_BITMAP_99 {0x38, 0x44, 0x82, 0x80, 0x80, 0x80, 0x82, 0x44, 0x38} + +/* d (100) */ +#define NXFONT_METRICS_100 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_100 {0x2, 0x2, 0x2, 0x3a, 0x46, 0x82, 0x82, 0x82, 0x82, 0x82, 0x46, 0x3a} + +/* e (101) */ +#define NXFONT_METRICS_101 {1, 7, 9, 1, 11, 0} +#define NXFONT_BITMAP_101 {0x38, 0x44, 0x82, 0x82, 0xfe, 0x80, 0x82, 0x44, 0x38} + +/* f (102) */ +#define NXFONT_METRICS_102 {1, 4, 12, 1, 8, 0} +#define NXFONT_BITMAP_102 {0x30, 0x40, 0x40, 0xf0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* g (103) */ +#define NXFONT_METRICS_103 {1, 7, 13, 1, 11, 0} +#define NXFONT_BITMAP_103 {0x3a, 0x46, 0x82, 0x82, 0x82, 0x82, 0x82, 0x46, 0x3a, 0x2, 0x82, 0x84, 0x78} + +/* h (104) */ +#define NXFONT_METRICS_104 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_104 {0x80, 0x80, 0x80, 0xbc, 0xc2, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 1, 12, 1, 8, 0} +#define NXFONT_BITMAP_105 {0x80, 0x80, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* j (106) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_106 {1, 3, 16, 0, 8, 0} +#define NXFONT_BITMAP_106 {0x20, 0x20, 0x0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xc0} + +/* k (107) */ +#define NXFONT_METRICS_107 {1, 7, 12, 0, 8, 0} +#define NXFONT_BITMAP_107 {0x80, 0x80, 0x80, 0x84, 0x88, 0x90, 0xa0, 0xe0, 0x90, 0x88, 0x84, 0x82} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 1, 12, 1, 8, 0} +#define NXFONT_BITMAP_108 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* m (109) */ +#define NXFONT_METRICS_109 {2, 11, 9, 2, 11, 0} +#define NXFONT_BITMAP_109 {0xb9, 0xc0, 0xc6, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20} + +/* n (110) */ +#define NXFONT_METRICS_110 {1, 7, 9, 1, 11, 0} +#define NXFONT_BITMAP_110 {0xbc, 0xc2, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82} + +/* o (111) */ +#define NXFONT_METRICS_111 {1, 7, 9, 1, 11, 0} +#define NXFONT_BITMAP_111 {0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* p (112) */ +#define NXFONT_METRICS_112 {1, 7, 13, 1, 11, 0} +#define NXFONT_BITMAP_112 {0xb8, 0xc4, 0x82, 0x82, 0x82, 0x82, 0x82, 0xc4, 0xb8, 0x80, 0x80, 0x80, 0x80} + +/* q (113) */ +#define NXFONT_METRICS_113 {1, 7, 13, 1, 11, 0} +#define NXFONT_BITMAP_113 {0x3a, 0x46, 0x82, 0x82, 0x82, 0x82, 0x82, 0x46, 0x3a, 0x2, 0x2, 0x2, 0x2} + +/* r (114) */ +#define NXFONT_METRICS_114 {1, 4, 9, 1, 11, 0} +#define NXFONT_BITMAP_114 {0xb0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* s (115) */ +#define NXFONT_METRICS_115 {1, 6, 9, 1, 11, 0} +#define NXFONT_BITMAP_115 {0x78, 0x84, 0x84, 0xc0, 0x30, 0xc, 0x84, 0x84, 0x78} + +/* t (116) */ +#define NXFONT_METRICS_116 {1, 4, 11, 1, 9, 0} +#define NXFONT_BITMAP_116 {0x40, 0x40, 0xf0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x30} + +/* u (117) */ +#define NXFONT_METRICS_117 {1, 7, 9, 1, 11, 0} +#define NXFONT_BITMAP_117 {0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x86, 0x7a} + +/* v (118) */ +#define NXFONT_METRICS_118 {1, 7, 9, 0, 11, 0} +#define NXFONT_BITMAP_118 {0x82, 0x82, 0x44, 0x44, 0x44, 0x28, 0x28, 0x38, 0x10} + +/* w (119) */ +#define NXFONT_METRICS_119 {2, 11, 9, 0, 11, 0} +#define NXFONT_BITMAP_119 {0x84, 0x20, 0x84, 0x20, 0x44, 0x40, 0x4e, 0x40, 0x4a, 0x40, 0x2a, 0x80, 0x2a, 0x80, 0x11, 0x0, 0x11, 0x0} + +/* x (120) */ +#define NXFONT_METRICS_120 {1, 7, 9, 0, 11, 0} +#define NXFONT_BITMAP_120 {0x82, 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x82} + +/* y (121) */ +#define NXFONT_METRICS_121 {1, 7, 12, 0, 11, 0} +#define NXFONT_BITMAP_121 {0x82, 0x82, 0x44, 0x44, 0x28, 0x28, 0x38, 0x10, 0x10, 0x20, 0x20, 0xc0} + +/* z (122) */ +#define NXFONT_METRICS_122 {1, 6, 9, 1, 11, 0} +#define NXFONT_BITMAP_122 {0xfc, 0x4, 0x8, 0x10, 0x20, 0x20, 0x40, 0x80, 0xfc} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {1, 3, 16, 1, 8, 0} +#define NXFONT_BITMAP_123 {0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x80, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 1, 16, 1, 8, 0} +#define NXFONT_BITMAP_124 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 3, 16, 1, 8, 0} +#define NXFONT_BITMAP_125 {0x80, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x80} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {1, 8, 2, 1, 14, 0} +#define NXFONT_BITMAP_126 {0x71, 0x8e} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 1, 12, 2, 11, 0} +#define NXFONT_BITMAP_161 {0x80, 0x80, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* cent (162) */ +#define NXFONT_METRICS_162 {1, 7, 13, 1, 9, 0} +#define NXFONT_BITMAP_162 {0x4, 0x4, 0x38, 0x4c, 0x8a, 0x90, 0x90, 0x90, 0xa2, 0x64, 0x38, 0x40, 0x40} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_163 {0xe, 0x11, 0x21, 0x20, 0x20, 0x10, 0x7e, 0x8, 0x10, 0x20, 0x79, 0x86} + +/* currency (164) */ +#define NXFONT_METRICS_164 {1, 8, 7, 0, 10, 0} +#define NXFONT_BITMAP_164 {0xbd, 0x66, 0x42, 0x42, 0x42, 0x66, 0xbd} + +/* yen (165) */ +#define NXFONT_METRICS_165 {2, 9, 12, 0, 8, 0} +#define NXFONT_BITMAP_165 {0x80, 0x80, 0x41, 0x0, 0x41, 0x0, 0x22, 0x0, 0x22, 0x0, 0x14, 0x0, 0x7f, 0x0, 0x8, 0x0, 0x7f, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 1, 16, 1, 8, 0} +#define NXFONT_BITMAP_166 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* section (167) */ +#define NXFONT_METRICS_167 {1, 7, 15, 1, 8, 0} +#define NXFONT_BITMAP_167 {0x38, 0x44, 0x46, 0x60, 0x98, 0x8c, 0x86, 0xc2, 0x62, 0x32, 0x1c, 0x4, 0xc4, 0x44, 0x38} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 3, 2, 1, 8, 0} +#define NXFONT_BITMAP_168 {0xa0, 0xa0} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {2, 12, 12, 0, 8, 0} +#define NXFONT_BITMAP_169 {0xf, 0x0, 0x30, 0xc0, 0x47, 0x20, 0x48, 0xa0, 0x90, 0x10, 0x90, 0x10, 0x90, 0x10, 0x90, 0x10, 0x48, 0xa0, 0x47, 0x20, 0x30, 0xc0, 0xf, 0x0} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {1, 5, 7, 1, 8, 0} +#define NXFONT_BITMAP_170 {0x60, 0x90, 0x70, 0x90, 0x78, 0x0, 0xf8} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {1, 6, 6, 1, 12, 0} +#define NXFONT_BITMAP_171 {0x24, 0x48, 0x90, 0x90, 0x48, 0x24} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {1, 8, 5, 0, 14, 0} +#define NXFONT_BITMAP_172 {0xff, 0x1, 0x1, 0x1, 0x1} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 4, 1, 0, 15, 0} +#define NXFONT_BITMAP_173 {0xf0} + +/* registered (174) */ +#define NXFONT_METRICS_174 {2, 12, 12, 0, 8, 0} +#define NXFONT_BITMAP_174 {0xf, 0x0, 0x30, 0xc0, 0x40, 0x20, 0x4f, 0x20, 0x88, 0x90, 0x88, 0x90, 0x8f, 0x10, 0x8a, 0x10, 0x49, 0x20, 0x48, 0xa0, 0x30, 0xc0, 0xf, 0x0} + +/* macron (175) */ +#define NXFONT_METRICS_175 {1, 5, 1, 0, 9, 0} +#define NXFONT_BITMAP_175 {0xf8} + +/* degree (176) */ +#define NXFONT_METRICS_176 {1, 5, 5, 1, 8, 0} +#define NXFONT_BITMAP_176 {0x70, 0x88, 0x88, 0x88, 0x70} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {2, 9, 11, 0, 9, 0} +#define NXFONT_BITMAP_177 {0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xff, 0x80, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x0, 0x0, 0xff, 0x80} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {1, 5, 7, 0, 8, 0} +#define NXFONT_BITMAP_178 {0x70, 0x88, 0x88, 0x10, 0x60, 0x80, 0xf8} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {1, 5, 7, 0, 8, 0} +#define NXFONT_BITMAP_179 {0x70, 0x88, 0x8, 0x30, 0x8, 0x88, 0x70} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 3, 3, 1, 7, 0} +#define NXFONT_BITMAP_180 {0x20, 0x60, 0x80} + +/* mu (181) */ +#define NXFONT_METRICS_181 {1, 7, 13, 1, 11, 0} +#define NXFONT_BITMAP_181 {0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x86, 0xfa, 0x80, 0x80, 0x80, 0x80} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {1, 7, 15, 1, 8, 0} +#define NXFONT_BITMAP_182 {0x3e, 0x74, 0xf4, 0xf4, 0xf4, 0xf4, 0x74, 0x34, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 1, 2, 2, 14, 0} +#define NXFONT_BITMAP_183 {0x80, 0x80} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 4, 4, 0, 20, 0} +#define NXFONT_BITMAP_184 {0x20, 0x20, 0x90, 0x60} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 3, 7, 0, 8, 0} +#define NXFONT_BITMAP_185 {0x20, 0xe0, 0x20, 0x20, 0x20, 0x20, 0x20} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {1, 4, 7, 1, 8, 0} +#define NXFONT_BITMAP_186 {0x60, 0x90, 0x90, 0x90, 0x60, 0x0, 0xf0} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {1, 6, 6, 1, 12, 0} +#define NXFONT_BITMAP_187 {0x90, 0x48, 0x24, 0x24, 0x48, 0x90} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {2, 12, 12, 0, 8, 0} +#define NXFONT_BITMAP_188 {0x20, 0x40, 0xe0, 0x80, 0x20, 0x80, 0x21, 0x0, 0x22, 0x0, 0x22, 0x20, 0x24, 0x60, 0x4, 0xa0, 0x9, 0x20, 0x11, 0xf0, 0x10, 0x20, 0x20, 0x20} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {2, 12, 13, 0, 7, 0} +#define NXFONT_BITMAP_189 {0x0, 0x40, 0x20, 0x80, 0xe0, 0x80, 0x21, 0x0, 0x22, 0x0, 0x22, 0x0, 0x24, 0xe0, 0x25, 0x10, 0x9, 0x10, 0x8, 0x20, 0x10, 0xc0, 0x21, 0x0, 0x21, 0xf0} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {2, 13, 12, 0, 8, 0} +#define NXFONT_BITMAP_190 {0x70, 0x40, 0x88, 0x40, 0x8, 0x80, 0x30, 0x80, 0x9, 0x0, 0x89, 0x10, 0x72, 0x30, 0x2, 0x50, 0x4, 0x90, 0x4, 0xf8, 0x8, 0x10, 0x8, 0x10} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {1, 7, 12, 1, 11, 0} +#define NXFONT_BITMAP_191 {0x10, 0x10, 0x0, 0x10, 0x10, 0x20, 0x40, 0x80, 0x82, 0x82, 0x44, 0x38} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {2, 10, 16, 0, 4, 0} +#define NXFONT_BITMAP_192 {0x10, 0x0, 0x18, 0x0, 0x4, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0x21, 0x0, 0x21, 0x0, 0x7f, 0x80, 0x40, 0x80, 0x40, 0x80, 0x80, 0x40, 0x80, 0x40} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {2, 10, 16, 0, 4, 0} +#define NXFONT_BITMAP_193 {0x2, 0x0, 0x6, 0x0, 0x8, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0x21, 0x0, 0x21, 0x0, 0x7f, 0x80, 0x40, 0x80, 0x40, 0x80, 0x80, 0x40, 0x80, 0x40} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {2, 10, 16, 0, 4, 0} +#define NXFONT_BITMAP_194 {0x4, 0x0, 0xe, 0x0, 0x11, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0x21, 0x0, 0x21, 0x0, 0x7f, 0x80, 0x40, 0x80, 0x40, 0x80, 0x80, 0x40, 0x80, 0x40} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {2, 10, 15, 0, 5, 0} +#define NXFONT_BITMAP_195 {0x1a, 0x0, 0x2c, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0x21, 0x0, 0x21, 0x0, 0x7f, 0x80, 0x40, 0x80, 0x40, 0x80, 0x80, 0x40, 0x80, 0x40} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {2, 10, 15, 0, 5, 0} +#define NXFONT_BITMAP_196 {0x12, 0x0, 0x12, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0x21, 0x0, 0x21, 0x0, 0x7f, 0x80, 0x40, 0x80, 0x40, 0x80, 0x80, 0x40, 0x80, 0x40} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {2, 10, 15, 0, 5, 0} +#define NXFONT_BITMAP_197 {0xc, 0x0, 0x12, 0x0, 0x12, 0x0, 0xc, 0x0, 0xc, 0x0, 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0x21, 0x0, 0x21, 0x0, 0x7f, 0x80, 0x40, 0x80, 0x40, 0x80, 0x80, 0x40, 0x80, 0x40} + +/* AE (198) */ +#define NXFONT_METRICS_198 {2, 14, 12, 0, 8, 0} +#define NXFONT_BITMAP_198 {0x7, 0xfc, 0x9, 0x0, 0x9, 0x0, 0x11, 0x0, 0x11, 0x0, 0x21, 0xfc, 0x21, 0x0, 0x7f, 0x0, 0x41, 0x0, 0x41, 0x0, 0x81, 0x0, 0x81, 0xfc} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {2, 10, 16, 1, 8, 0} +#define NXFONT_BITMAP_199 {0xf, 0x0, 0x30, 0x80, 0x40, 0x40, 0x40, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x40, 0x0, 0x40, 0x40, 0x30, 0x80, 0xf, 0x0, 0x4, 0x0, 0x4, 0x0, 0x12, 0x0, 0xc, 0x0} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {1, 8, 16, 1, 4, 0} +#define NXFONT_BITMAP_200 {0x20, 0x30, 0x8, 0x0, 0xff, 0x80, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {1, 8, 16, 1, 4, 0} +#define NXFONT_BITMAP_201 {0x4, 0xc, 0x10, 0x0, 0xff, 0x80, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {1, 8, 16, 1, 4, 0} +#define NXFONT_BITMAP_202 {0x10, 0x38, 0x44, 0x0, 0xff, 0x80, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {1, 8, 15, 1, 5, 0} +#define NXFONT_BITMAP_203 {0x24, 0x24, 0x0, 0xff, 0x80, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {1, 3, 16, 0, 4, 0} +#define NXFONT_BITMAP_204 {0x80, 0xc0, 0x20, 0x0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 3, 16, 0, 4, 0} +#define NXFONT_BITMAP_205 {0x20, 0x60, 0x80, 0x0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* Icircumflex (206) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_206 {1, 5, 16, 0, 4, 0} +#define NXFONT_BITMAP_206 {0x20, 0x70, 0x88, 0x0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {1, 3, 15, 0, 5, 0} +#define NXFONT_BITMAP_207 {0xa0, 0xa0, 0x0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* Eth (208) */ +#define NXFONT_METRICS_208 {2, 12, 12, 0, 8, 0} +#define NXFONT_BITMAP_208 {0x3f, 0x0, 0x20, 0xc0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0xf8, 0x10, 0x20, 0x10, 0x20, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0xc0, 0x3f, 0x0} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {2, 9, 15, 1, 5, 0} +#define NXFONT_BITMAP_209 {0x1a, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x80, 0x80, 0xc0, 0x80, 0xa0, 0x80, 0xa0, 0x80, 0x90, 0x80, 0x88, 0x80, 0x88, 0x80, 0x84, 0x80, 0x82, 0x80, 0x82, 0x80, 0x81, 0x80, 0x80, 0x80} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {2, 11, 16, 1, 4, 0} +#define NXFONT_BITMAP_210 {0x8, 0x0, 0xc, 0x0, 0x2, 0x0, 0x0, 0x0, 0xe, 0x0, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x40, 0x40, 0x40, 0x40, 0x31, 0x80, 0xe, 0x0} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {2, 11, 16, 1, 4, 0} +#define NXFONT_BITMAP_211 {0x1, 0x0, 0x3, 0x0, 0x4, 0x0, 0x0, 0x0, 0xe, 0x0, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x40, 0x40, 0x40, 0x40, 0x31, 0x80, 0xe, 0x0} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {2, 11, 16, 1, 4, 0} +#define NXFONT_BITMAP_212 {0x4, 0x0, 0xe, 0x0, 0x11, 0x0, 0x0, 0x0, 0xe, 0x0, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x40, 0x40, 0x40, 0x40, 0x31, 0x80, 0xe, 0x0} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {2, 11, 15, 1, 5, 0} +#define NXFONT_BITMAP_213 {0xd, 0x0, 0x16, 0x0, 0x0, 0x0, 0xe, 0x0, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x40, 0x40, 0x40, 0x40, 0x31, 0x80, 0xe, 0x0} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {2, 11, 15, 1, 5, 0} +#define NXFONT_BITMAP_214 {0x11, 0x0, 0x11, 0x0, 0x0, 0x0, 0xe, 0x0, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x40, 0x40, 0x40, 0x40, 0x31, 0x80, 0xe, 0x0} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {1, 8, 8, 1, 12, 0} +#define NXFONT_BITMAP_215 {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {2, 11, 14, 1, 7, 0} +#define NXFONT_BITMAP_216 {0x0, 0x40, 0xe, 0x80, 0x31, 0x80, 0x41, 0x40, 0x42, 0x40, 0x82, 0x20, 0x84, 0x20, 0x84, 0x20, 0x88, 0x20, 0x48, 0x40, 0x50, 0x40, 0x31, 0x80, 0x2e, 0x0, 0x40, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {2, 9, 16, 1, 4, 0} +#define NXFONT_BITMAP_217 {0x20, 0x0, 0x30, 0x0, 0x8, 0x0, 0x0, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x0, 0x3e, 0x0} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {2, 9, 16, 1, 4, 0} +#define NXFONT_BITMAP_218 {0x2, 0x0, 0x6, 0x0, 0x8, 0x0, 0x0, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x0, 0x3e, 0x0} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {2, 9, 16, 1, 4, 0} +#define NXFONT_BITMAP_219 {0x8, 0x0, 0x1c, 0x0, 0x22, 0x0, 0x0, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x0, 0x3e, 0x0} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {2, 9, 15, 1, 5, 0} +#define NXFONT_BITMAP_220 {0x22, 0x0, 0x22, 0x0, 0x0, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x0, 0x3e, 0x0} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {2, 9, 16, 1, 4, 0} +#define NXFONT_BITMAP_221 {0x2, 0x0, 0x6, 0x0, 0x8, 0x0, 0x0, 0x0, 0x80, 0x80, 0x41, 0x0, 0x41, 0x0, 0x22, 0x0, 0x22, 0x0, 0x14, 0x0, 0x1c, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {1, 8, 12, 2, 8, 0} +#define NXFONT_BITMAP_222 {0x80, 0x80, 0xfc, 0x82, 0x81, 0x81, 0x82, 0xfc, 0x80, 0x80, 0x80, 0x80} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {1, 7, 12, 2, 8, 0} +#define NXFONT_BITMAP_223 {0x78, 0x84, 0x82, 0x82, 0x84, 0xbc, 0x86, 0x82, 0x82, 0x82, 0x84, 0xb8} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_224 {0x20, 0x30, 0x8, 0x0, 0x7c, 0x82, 0x2, 0x6, 0x7a, 0x82, 0x82, 0x86, 0x7b} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_225 {0x4, 0xc, 0x10, 0x0, 0x7c, 0x82, 0x2, 0x6, 0x7a, 0x82, 0x82, 0x86, 0x7b} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_226 {0x10, 0x38, 0x44, 0x0, 0x7c, 0x82, 0x2, 0x6, 0x7a, 0x82, 0x82, 0x86, 0x7b} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_227 {0x34, 0x58, 0x0, 0x7c, 0x82, 0x2, 0x6, 0x7a, 0x82, 0x82, 0x86, 0x7b} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_228 {0x28, 0x28, 0x0, 0x7c, 0x82, 0x2, 0x6, 0x7a, 0x82, 0x82, 0x86, 0x7b} + +/* aring (229) */ +#define NXFONT_METRICS_229 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_229 {0x10, 0x28, 0x10, 0x0, 0x7c, 0x82, 0x2, 0x6, 0x7a, 0x82, 0x82, 0x86, 0x7b} + +/* ae (230) */ +#define NXFONT_METRICS_230 {2, 13, 9, 1, 11, 0} +#define NXFONT_BITMAP_230 {0x7c, 0xe0, 0x83, 0x10, 0x2, 0x8, 0x6, 0x8, 0x7b, 0xf8, 0x82, 0x0, 0x82, 0x8, 0x87, 0x10, 0x78, 0xe0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {1, 7, 13, 1, 11, 0} +#define NXFONT_BITMAP_231 {0x38, 0x44, 0x82, 0x80, 0x80, 0x80, 0x82, 0x44, 0x38, 0x10, 0x10, 0x48, 0x30} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {1, 7, 13, 1, 7, 0} +#define NXFONT_BITMAP_232 {0x40, 0x60, 0x10, 0x0, 0x38, 0x44, 0x82, 0x82, 0xfe, 0x80, 0x82, 0x44, 0x38} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {1, 7, 13, 1, 7, 0} +#define NXFONT_BITMAP_233 {0x8, 0x18, 0x20, 0x0, 0x38, 0x44, 0x82, 0x82, 0xfe, 0x80, 0x82, 0x44, 0x38} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {1, 7, 13, 1, 7, 0} +#define NXFONT_BITMAP_234 {0x10, 0x38, 0x44, 0x0, 0x38, 0x44, 0x82, 0x82, 0xfe, 0x80, 0x82, 0x44, 0x38} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_235 {0x28, 0x28, 0x0, 0x38, 0x44, 0x82, 0x82, 0xfe, 0x80, 0x82, 0x44, 0x38} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 3, 13, 1, 7, 0} +#define NXFONT_BITMAP_236 {0x80, 0xc0, 0x20, 0x0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 3, 13, 1, 7, 0} +#define NXFONT_BITMAP_237 {0x20, 0x60, 0x80, 0x0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* icircumflex (238) */ +#define NXFONT_METRICS_238 {1, 5, 13, 0, 7, 0} +#define NXFONT_BITMAP_238 {0x20, 0x70, 0x88, 0x0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 3, 12, 1, 8, 0} +#define NXFONT_BITMAP_239 {0xa0, 0xa0, 0x0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* eth (240) */ +#define NXFONT_METRICS_240 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_240 {0x48, 0x30, 0x58, 0x3c, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_241 {0x34, 0x58, 0x0, 0xbc, 0xc2, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {1, 7, 13, 1, 7, 0} +#define NXFONT_BITMAP_242 {0x20, 0x30, 0x8, 0x0, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {1, 7, 13, 1, 7, 0} +#define NXFONT_BITMAP_243 {0x8, 0x18, 0x20, 0x0, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {1, 7, 13, 1, 7, 0} +#define NXFONT_BITMAP_244 {0x10, 0x38, 0x44, 0x0, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_245 {0x34, 0x58, 0x0, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_246 {0x28, 0x28, 0x0, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* divide (247) */ +#define NXFONT_METRICS_247 {1, 7, 9, 1, 11, 0} +#define NXFONT_BITMAP_247 {0x10, 0x10, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x10, 0x10} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {1, 7, 10, 1, 10, 0} +#define NXFONT_BITMAP_248 {0x2, 0x3c, 0x44, 0x8a, 0x92, 0x92, 0xa2, 0xa2, 0x44, 0xb8} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {1, 7, 13, 1, 7, 0} +#define NXFONT_BITMAP_249 {0x20, 0x30, 0x8, 0x0, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x86, 0x7a} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {1, 7, 13, 1, 7, 0} +#define NXFONT_BITMAP_250 {0x4, 0xc, 0x10, 0x0, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x86, 0x7a} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {1, 7, 13, 1, 7, 0} +#define NXFONT_BITMAP_251 {0x10, 0x38, 0x44, 0x0, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x86, 0x7a} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_252 {0x28, 0x28, 0x0, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x86, 0x7a} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {1, 7, 16, 0, 7, 0} +#define NXFONT_BITMAP_253 {0x8, 0x18, 0x20, 0x0, 0x82, 0x82, 0x44, 0x44, 0x28, 0x28, 0x38, 0x10, 0x10, 0x20, 0x20, 0xc0} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {1, 7, 16, 1, 8, 0} +#define NXFONT_BITMAP_254 {0x80, 0x80, 0x80, 0xb8, 0xc4, 0x82, 0x82, 0x82, 0x82, 0x82, 0xc4, 0xb8, 0x80, 0x80, 0x80, 0x80} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {1, 7, 15, 0, 8, 0} +#define NXFONT_BITMAP_255 {0x28, 0x28, 0x0, 0x82, 0x82, 0x44, 0x44, 0x28, 0x28, 0x38, 0x10, 0x10, 0x20, 0x20, 0xc0} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SANS20X26_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_sans20x27b.h b/nuttx/graphics/nxfonts/nxfonts_sans20x27b.h new file mode 100644 index 0000000000..b9a8ea65de --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_sans20x27b.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_serif20x27b.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SANS20X27B_H +#define __GRAPHICS_NXFONTS_NXFONTS_SANS20X27B_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SANS20X27B + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 27 +#define NXFONT_MAXWIDTH 20 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 5 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 2, 12, 2, 8, 0} +#define NXFONT_BITMAP_33 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x0, 0xc0, 0xc0} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {1, 5, 4, 1, 8, 0} +#define NXFONT_BITMAP_34 {0xd8, 0xd8, 0xd8, 0x48} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {2, 9, 12, 0, 8, 0} +#define NXFONT_BITMAP_35 {0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x7f, 0x80, 0x7f, 0x80, 0x36, 0x0, 0x36, 0x0, 0xff, 0x0, 0xff, 0x0, 0x6c, 0x0, 0x6c, 0x0, 0x6c, 0x0} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {1, 7, 14, 1, 7, 0} +#define NXFONT_BITMAP_36 {0x10, 0x7c, 0xfe, 0xd6, 0xd0, 0xf0, 0x78, 0x3c, 0x1e, 0x16, 0xd6, 0xfe, 0x7c, 0x10} + +/* percent (37) */ +#define NXFONT_METRICS_37 {2, 13, 12, 0, 8, 0} +#define NXFONT_BITMAP_37 {0x30, 0x40, 0x78, 0x80, 0xcc, 0x80, 0xcd, 0x0, 0x79, 0x0, 0x32, 0x0, 0x2, 0x60, 0x4, 0xf0, 0x5, 0x98, 0x9, 0x98, 0x8, 0xf0, 0x10, 0x60} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {2, 10, 12, 1, 8, 0} +#define NXFONT_BITMAP_38 {0x3c, 0x0, 0x7e, 0x0, 0x66, 0x0, 0x66, 0x0, 0x3c, 0x0, 0x38, 0xc0, 0x7d, 0xc0, 0xcf, 0x80, 0xc7, 0x0, 0xc7, 0x0, 0x7f, 0x80, 0x39, 0xc0} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 2, 4, 1, 8, 0} +#define NXFONT_BITMAP_39 {0xc0, 0xc0, 0xc0, 0x40} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 4, 15, 1, 8, 0} +#define NXFONT_BITMAP_40 {0x30, 0x70, 0x60, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0x70, 0x30} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 4, 15, 0, 8, 0} +#define NXFONT_BITMAP_41 {0xc0, 0xe0, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0xe0, 0xc0} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {1, 5, 5, 0, 8, 0} +#define NXFONT_BITMAP_42 {0x20, 0xa8, 0x70, 0x70, 0x88} + +/* plus (43) */ +#define NXFONT_METRICS_43 {1, 8, 8, 1, 12, 0} +#define NXFONT_BITMAP_43 {0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 2, 5, 1, 18, 0} +#define NXFONT_BITMAP_44 {0xc0, 0xc0, 0x40, 0x40, 0x80} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 4, 2, 0, 15, 0} +#define NXFONT_BITMAP_45 {0xf0, 0xf0} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 2, 2, 1, 18, 0} +#define NXFONT_BITMAP_46 {0xc0, 0xc0} + +/* slash (47) */ +#define NXFONT_METRICS_47 {1, 4, 12, 0, 8, 0} +#define NXFONT_BITMAP_47 {0x10, 0x10, 0x30, 0x20, 0x20, 0x60, 0x40, 0x40, 0xc0, 0x80, 0x80, 0x80} + +/* zero (48) */ +#define NXFONT_METRICS_48 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_48 {0x3c, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e, 0x3c} + +/* one (49) */ +#define NXFONT_METRICS_49 {1, 5, 12, 1, 8, 0} +#define NXFONT_BITMAP_49 {0x8, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18} + +/* two (50) */ +#define NXFONT_METRICS_50 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_50 {0x3c, 0x7e, 0xe7, 0xc3, 0xc3, 0x7, 0xe, 0x1c, 0x38, 0x70, 0xff, 0xff} + +/* three (51) */ +#define NXFONT_METRICS_51 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_51 {0x3c, 0x7e, 0xe7, 0xc3, 0x7, 0x1e, 0x1e, 0x7, 0xc3, 0xe7, 0x7e, 0x3c} + +/* four (52) */ +#define NXFONT_METRICS_52 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_52 {0xe, 0x1e, 0x36, 0x36, 0x66, 0x66, 0xc6, 0xff, 0xff, 0x6, 0x6, 0x6} + +/* five (53) */ +#define NXFONT_METRICS_53 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_53 {0x3f, 0x3f, 0x30, 0x30, 0x7c, 0x7e, 0x47, 0x3, 0x3, 0xe7, 0x7e, 0x3c} + +/* six (54) */ +#define NXFONT_METRICS_54 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_54 {0x3c, 0x7e, 0xe7, 0xc0, 0xdc, 0xfe, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0x3c} + +/* seven (55) */ +#define NXFONT_METRICS_55 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_55 {0xff, 0xff, 0x6, 0x6, 0xc, 0xc, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30} + +/* eight (56) */ +#define NXFONT_METRICS_56 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_56 {0x3c, 0x7e, 0xe7, 0xc3, 0x66, 0x3c, 0x7e, 0xe7, 0xc3, 0xe7, 0x7e, 0x3c} + +/* nine (57) */ +#define NXFONT_METRICS_57 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_57 {0x3c, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7f, 0x3b, 0x3, 0xe7, 0x7e, 0x3c} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 2, 8, 2, 12, 0} +#define NXFONT_BITMAP_58 {0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 2, 11, 2, 12, 0} +#define NXFONT_BITMAP_59 {0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0x40, 0x40, 0x80} + +/* less (60) */ +#define NXFONT_METRICS_60 {1, 8, 8, 1, 12, 0} +#define NXFONT_BITMAP_60 {0x3, 0xf, 0x3c, 0xe0, 0xe0, 0x3c, 0xf, 0x3} + +/* equal (61) */ +#define NXFONT_METRICS_61 {1, 8, 6, 1, 13, 0} +#define NXFONT_BITMAP_61 {0xff, 0xff, 0x0, 0x0, 0xff, 0xff} + +/* greater (62) */ +#define NXFONT_METRICS_62 {1, 8, 8, 1, 12, 0} +#define NXFONT_BITMAP_62 {0xc0, 0xf0, 0x3c, 0x7, 0x7, 0x3c, 0xf0, 0xc0} + +/* question (63) */ +#define NXFONT_METRICS_63 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_63 {0x7c, 0xfe, 0xc6, 0xc6, 0x6, 0xe, 0xc, 0x18, 0x18, 0x0, 0x18, 0x18} + +/* at (64) */ +#define NXFONT_METRICS_64 {2, 13, 14, 1, 8, 0} +#define NXFONT_BITMAP_64 {0xf, 0xc0, 0x38, 0x60, 0x60, 0x10, 0x47, 0xd8, 0xcc, 0x48, 0x88, 0xc8, 0x98, 0xc8, 0x98, 0x88, 0x99, 0x98, 0xc9, 0x90, 0x46, 0x60, 0x60, 0x0, 0x38, 0xc0, 0xf, 0x80} + +/* A (65) */ +#define NXFONT_METRICS_65 {2, 11, 12, 0, 8, 0} +#define NXFONT_BITMAP_65 {0xe, 0x0, 0xe, 0x0, 0x1f, 0x0, 0x1b, 0x0, 0x3b, 0x80, 0x31, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0x7f, 0xc0, 0xff, 0xe0, 0xc0, 0x60, 0xc0, 0x60} + +/* B (66) */ +#define NXFONT_METRICS_66 {2, 9, 12, 1, 8, 0} +#define NXFONT_BITMAP_66 {0xfe, 0x0, 0xff, 0x0, 0xc3, 0x80, 0xc1, 0x80, 0xc3, 0x80, 0xff, 0x0, 0xff, 0x0, 0xc3, 0x80, 0xc1, 0x80, 0xc3, 0x80, 0xff, 0x0, 0xfe, 0x0} + +/* C (67) */ +#define NXFONT_METRICS_67 {2, 10, 12, 1, 8, 0} +#define NXFONT_BITMAP_67 {0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* D (68) */ +#define NXFONT_METRICS_68 {2, 10, 12, 1, 8, 0} +#define NXFONT_BITMAP_68 {0xfc, 0x0, 0xff, 0x0, 0xc3, 0x80, 0xc1, 0x80, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0xc1, 0x80, 0xc3, 0x80, 0xff, 0x0, 0xfc, 0x0} + +/* E (69) */ +#define NXFONT_METRICS_69 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_69 {0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xfe, 0xfe, 0xc0, 0xc0, 0xc0, 0xff, 0xff} + +/* F (70) */ +#define NXFONT_METRICS_70 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_70 {0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xfe, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* G (71) */ +#define NXFONT_METRICS_71 {2, 10, 12, 1, 8, 0} +#define NXFONT_BITMAP_71 {0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0x0, 0xc0, 0x0, 0xc3, 0xc0, 0xe3, 0xc0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0xc0, 0x1e, 0xc0} + +/* H (72) */ +#define NXFONT_METRICS_72 {2, 10, 12, 1, 8, 0} +#define NXFONT_BITMAP_72 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 2, 12, 1, 8, 0} +#define NXFONT_BITMAP_73 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* J (74) */ +#define NXFONT_METRICS_74 {1, 7, 12, 1, 8, 0} +#define NXFONT_BITMAP_74 {0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0xc6, 0xc6, 0xfe, 0x7c} + +/* K (75) */ +#define NXFONT_METRICS_75 {2, 11, 12, 1, 8, 0} +#define NXFONT_BITMAP_75 {0xc1, 0xc0, 0xc3, 0x80, 0xc7, 0x0, 0xce, 0x0, 0xdc, 0x0, 0xf8, 0x0, 0xfc, 0x0, 0xce, 0x0, 0xc7, 0x0, 0xc3, 0x80, 0xc1, 0xc0, 0xc0, 0xe0} + +/* L (76) */ +#define NXFONT_METRICS_76 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_76 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff} + +/* M (77) */ +#define NXFONT_METRICS_77 {2, 11, 12, 1, 8, 0} +#define NXFONT_BITMAP_77 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0xd1, 0x60, 0xdb, 0x60, 0xdb, 0x60, 0xca, 0x60, 0xce, 0x60, 0xce, 0x60, 0xc4, 0x60} + +/* N (78) */ +#define NXFONT_METRICS_78 {2, 10, 12, 1, 8, 0} +#define NXFONT_BITMAP_78 {0xe0, 0xc0, 0xf0, 0xc0, 0xf0, 0xc0, 0xd8, 0xc0, 0xd8, 0xc0, 0xcc, 0xc0, 0xcc, 0xc0, 0xc6, 0xc0, 0xc6, 0xc0, 0xc3, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0} + +/* O (79) */ +#define NXFONT_METRICS_79 {2, 11, 12, 1, 8, 0} +#define NXFONT_BITMAP_79 {0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* P (80) */ +#define NXFONT_METRICS_80 {2, 9, 12, 1, 8, 0} +#define NXFONT_BITMAP_80 {0xfe, 0x0, 0xff, 0x0, 0xc3, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc3, 0x80, 0xff, 0x0, 0xfe, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {2, 11, 13, 1, 8, 0} +#define NXFONT_BITMAP_81 {0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xe2, 0x60, 0x67, 0xc0, 0x73, 0xc0, 0x3f, 0x80, 0x1f, 0xc0, 0x0, 0x80} + +/* R (82) */ +#define NXFONT_METRICS_82 {2, 10, 12, 1, 8, 0} +#define NXFONT_BITMAP_82 {0xff, 0x0, 0xff, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc3, 0x80, 0xff, 0x0, 0xff, 0x0, 0xc3, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0xc0, 0xc1, 0xc0} + +/* S (83) */ +#define NXFONT_METRICS_83 {2, 9, 12, 1, 8, 0} +#define NXFONT_BITMAP_83 {0x3e, 0x0, 0x7f, 0x0, 0xe3, 0x80, 0xc1, 0x80, 0xf0, 0x0, 0x7e, 0x0, 0x1f, 0x0, 0x3, 0x80, 0xc1, 0x80, 0xe3, 0x80, 0x7f, 0x0, 0x3e, 0x0} + +/* T (84) */ +#define NXFONT_METRICS_84 {2, 10, 12, 0, 8, 0} +#define NXFONT_BITMAP_84 {0xff, 0xc0, 0xff, 0xc0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0} + +/* U (85) */ +#define NXFONT_METRICS_85 {2, 10, 12, 1, 8, 0} +#define NXFONT_BITMAP_85 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe1, 0xc0, 0x7f, 0x80, 0x3f, 0x0} + +/* V (86) */ +#define NXFONT_METRICS_86 {2, 10, 12, 0, 8, 0} +#define NXFONT_BITMAP_86 {0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xc, 0x0, 0xc, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {2, 14, 12, 0, 8, 0} +#define NXFONT_BITMAP_87 {0xc3, 0xc, 0xc3, 0xc, 0xc3, 0xc, 0x63, 0x18, 0x67, 0x98, 0x67, 0x98, 0x34, 0xb0, 0x3c, 0xf0, 0x3c, 0xf0, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60} + +/* X (88) */ +#define NXFONT_METRICS_88 {2, 9, 12, 1, 8, 0} +#define NXFONT_BITMAP_88 {0xc1, 0x80, 0xe3, 0x80, 0x63, 0x0, 0x36, 0x0, 0x3e, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0x36, 0x0, 0x63, 0x0, 0xe3, 0x80, 0xc1, 0x80} + +/* Y (89) */ +#define NXFONT_METRICS_89 {2, 10, 12, 0, 8, 0} +#define NXFONT_BITMAP_89 {0xc0, 0xc0, 0xe1, 0xc0, 0x61, 0x80, 0x33, 0x0, 0x33, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_90 {0xff, 0xff, 0x7, 0x6, 0xc, 0x1c, 0x38, 0x30, 0x60, 0xe0, 0xff, 0xff} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 4, 15, 1, 8, 0} +#define NXFONT_BITMAP_91 {0xf0, 0xf0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf0, 0xf0} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {1, 4, 12, 0, 8, 0} +#define NXFONT_BITMAP_92 {0x80, 0x80, 0xc0, 0x40, 0x40, 0x60, 0x20, 0x20, 0x30, 0x10, 0x10, 0x10} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 4, 15, 0, 8, 0} +#define NXFONT_BITMAP_93 {0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {1, 8, 7, 1, 8, 0} +#define NXFONT_BITMAP_94 {0x18, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0xc3} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {2, 9, 1, 0, 22, 0} +#define NXFONT_BITMAP_95 {0xff, 0x80} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 3, 3, 2, 7, 0} +#define NXFONT_BITMAP_96 {0x80, 0xc0, 0x20} + +/* a (97) */ +#define NXFONT_METRICS_97 {1, 8, 9, 1, 11, 0} +#define NXFONT_BITMAP_97 {0x7c, 0xfe, 0xc6, 0xe, 0x7e, 0xe6, 0xc6, 0xfe, 0x77} + +/* b (98) */ +#define NXFONT_METRICS_98 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_98 {0xc0, 0xc0, 0xc0, 0xdc, 0xfe, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0xfe, 0xdc} + +/* c (99) */ +#define NXFONT_METRICS_99 {1, 8, 9, 1, 11, 0} +#define NXFONT_BITMAP_99 {0x3c, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e, 0x3c} + +/* d (100) */ +#define NXFONT_METRICS_100 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_100 {0x3, 0x3, 0x3, 0x3f, 0x7f, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0x7f, 0x3b} + +/* e (101) */ +#define NXFONT_METRICS_101 {1, 8, 9, 1, 11, 0} +#define NXFONT_BITMAP_101 {0x3c, 0x7e, 0xc3, 0xff, 0xff, 0xc0, 0xe7, 0x7e, 0x3c} + +/* f (102) */ +#define NXFONT_METRICS_102 {1, 4, 12, 1, 8, 0} +#define NXFONT_BITMAP_102 {0x30, 0x70, 0x60, 0xf0, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* g (103) */ +#define NXFONT_METRICS_103 {1, 8, 13, 1, 11, 0} +#define NXFONT_BITMAP_103 {0x3b, 0x7f, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0x7f, 0x3b, 0x3, 0xe7, 0x7e, 0x3c} + +/* h (104) */ +#define NXFONT_METRICS_104 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_104 {0xc0, 0xc0, 0xc0, 0xde, 0xff, 0xe3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 2, 12, 1, 8, 0} +#define NXFONT_BITMAP_105 {0xc0, 0xc0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* j (106) */ +#define NXFONT_METRICS_106 {1, 3, 16, 1, 8, 0} +#define NXFONT_BITMAP_106 {0x60, 0x60, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xe0, 0xc0} + +/* k (107) */ +#define NXFONT_METRICS_107 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_107 {0xc0, 0xc0, 0xc0, 0xc7, 0xce, 0xdc, 0xf8, 0xfc, 0xec, 0xce, 0xc6, 0xc7} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 2, 12, 1, 8, 0} +#define NXFONT_BITMAP_108 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* m (109) */ +#define NXFONT_METRICS_109 {2, 12, 9, 1, 11, 0} +#define NXFONT_BITMAP_109 {0xde, 0xe0, 0xff, 0xf0, 0xe7, 0x30, 0xc6, 0x30, 0xc6, 0x30, 0xc6, 0x30, 0xc6, 0x30, 0xc6, 0x30, 0xc6, 0x30} + +/* n (110) */ +#define NXFONT_METRICS_110 {1, 8, 9, 1, 11, 0} +#define NXFONT_BITMAP_110 {0xde, 0xff, 0xe3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3} + +/* o (111) */ +#define NXFONT_METRICS_111 {1, 8, 9, 1, 11, 0} +#define NXFONT_BITMAP_111 {0x3c, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e, 0x3c} + +/* p (112) */ +#define NXFONT_METRICS_112 {1, 8, 13, 1, 11, 0} +#define NXFONT_BITMAP_112 {0xdc, 0xfe, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0xfe, 0xdc, 0xc0, 0xc0, 0xc0, 0xc0} + +/* q (113) */ +#define NXFONT_METRICS_113 {1, 8, 13, 1, 11, 0} +#define NXFONT_BITMAP_113 {0x3b, 0x7f, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0x7f, 0x3b, 0x3, 0x3, 0x3, 0x3} + +/* r (114) */ +#define NXFONT_METRICS_114 {1, 5, 9, 1, 11, 0} +#define NXFONT_BITMAP_114 {0xd8, 0xf8, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* s (115) */ +#define NXFONT_METRICS_115 {1, 7, 9, 1, 11, 0} +#define NXFONT_BITMAP_115 {0x7c, 0xfe, 0xc6, 0xf0, 0x7c, 0xe, 0xc6, 0xfe, 0x7c} + +/* t (116) */ +#define NXFONT_METRICS_116 {1, 4, 11, 1, 9, 0} +#define NXFONT_BITMAP_116 {0x60, 0x60, 0xf0, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x70, 0x30} + +/* u (117) */ +#define NXFONT_METRICS_117 {1, 8, 9, 1, 11, 0} +#define NXFONT_BITMAP_117 {0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xff, 0x7b} + +/* v (118) */ +#define NXFONT_METRICS_118 {1, 8, 9, 0, 11, 0} +#define NXFONT_BITMAP_118 {0xc3, 0xc3, 0x66, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x18} + +/* w (119) */ +#define NXFONT_METRICS_119 {2, 12, 9, 0, 11, 0} +#define NXFONT_BITMAP_119 {0xc6, 0x30, 0xc6, 0x30, 0x66, 0x60, 0x66, 0x60, 0x6f, 0x60, 0x3f, 0xc0, 0x39, 0xc0, 0x19, 0x80, 0x19, 0x80} + +/* x (120) */ +#define NXFONT_METRICS_120 {1, 7, 9, 1, 11, 0} +#define NXFONT_BITMAP_120 {0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x7c, 0x6c, 0xc6, 0xc6} + +/* y (121) */ +#define NXFONT_METRICS_121 {1, 8, 13, 0, 11, 0} +#define NXFONT_BITMAP_121 {0xc3, 0xc3, 0x63, 0x66, 0x36, 0x36, 0x3c, 0x1c, 0x18, 0x18, 0x18, 0x70, 0x60} + +/* z (122) */ +#define NXFONT_METRICS_122 {1, 7, 9, 0, 11, 0} +#define NXFONT_BITMAP_122 {0xfe, 0xfe, 0xe, 0x1c, 0x18, 0x38, 0x70, 0xfe, 0xfe} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {1, 4, 15, 1, 8, 0} +#define NXFONT_BITMAP_123 {0x30, 0x70, 0x60, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x70, 0x30} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 1, 16, 1, 8, 0} +#define NXFONT_BITMAP_124 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 4, 15, 1, 8, 0} +#define NXFONT_BITMAP_125 {0xc0, 0xe0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x30, 0x60, 0x60, 0x60, 0x60, 0x60, 0xe0, 0xc0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {1, 8, 3, 1, 14, 0} +#define NXFONT_BITMAP_126 {0x71, 0x99, 0x8e} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 2, 12, 1, 11, 0} +#define NXFONT_BITMAP_161 {0xc0, 0xc0, 0x0, 0x40, 0x40, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* cent (162) */ +#define NXFONT_METRICS_162 {1, 8, 11, 0, 10, 0} +#define NXFONT_BITMAP_162 {0x4, 0x3c, 0x7e, 0xef, 0xc8, 0xd8, 0xd0, 0xf7, 0x7e, 0x3c, 0x20} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_163 {0x1c, 0x3e, 0x63, 0x63, 0x60, 0x30, 0x7c, 0x30, 0x30, 0x20, 0x7f, 0xff} + +/* currency (164) */ +#define NXFONT_METRICS_164 {1, 7, 7, 1, 11, 0} +#define NXFONT_BITMAP_164 {0xba, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xba} + +/* yen (165) */ +#define NXFONT_METRICS_165 {1, 8, 12, 0, 8, 0} +#define NXFONT_BITMAP_165 {0xc3, 0xc3, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 1, 16, 2, 8, 0} +#define NXFONT_BITMAP_166 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* section (167) */ +#define NXFONT_METRICS_167 {1, 8, 15, 0, 8, 0} +#define NXFONT_BITMAP_167 {0x3c, 0x7e, 0x66, 0x60, 0x78, 0x7e, 0xc7, 0xc3, 0xf3, 0x7e, 0x1e, 0x6, 0x66, 0x7e, 0x3c} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 5, 2, 0, 8, 0} +#define NXFONT_BITMAP_168 {0xd8, 0xd8} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {2, 12, 12, 0, 8, 0} +#define NXFONT_BITMAP_169 {0xf, 0x0, 0x39, 0xc0, 0x60, 0x60, 0x4f, 0x20, 0xd9, 0xb0, 0x90, 0x10, 0x90, 0x10, 0xd9, 0xb0, 0x4f, 0x20, 0x60, 0x20, 0x39, 0xc0, 0xf, 0x0} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {1, 5, 7, 1, 8, 0} +#define NXFONT_BITMAP_170 {0x60, 0x90, 0x70, 0x90, 0x78, 0x0, 0xf8} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {1, 8, 6, 0, 12, 0} +#define NXFONT_BITMAP_171 {0x33, 0x66, 0xcc, 0xcc, 0x66, 0x33} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {1, 8, 5, 0, 13, 0} +#define NXFONT_BITMAP_172 {0xff, 0xff, 0x3, 0x3, 0x3} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 4, 2, 0, 15, 0} +#define NXFONT_BITMAP_173 {0xf0, 0xf0} + +/* registered (174) */ +#define NXFONT_METRICS_174 {2, 12, 12, 0, 8, 0} +#define NXFONT_BITMAP_174 {0xf, 0x0, 0x39, 0xc0, 0x60, 0x60, 0x5f, 0x20, 0xd9, 0xb0, 0x99, 0x90, 0x9e, 0x10, 0xdb, 0x30, 0x5b, 0x20, 0x60, 0x60, 0x39, 0xc0, 0xf, 0x0} + +/* macron (175) */ +#define NXFONT_METRICS_175 {1, 5, 1, 0, 9, 0} +#define NXFONT_BITMAP_175 {0xf8} + +/* degree (176) */ +#define NXFONT_METRICS_176 {1, 4, 5, 1, 8, 0} +#define NXFONT_BITMAP_176 {0x60, 0x90, 0x90, 0x90, 0x60} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {1, 8, 11, 1, 9, 0} +#define NXFONT_BITMAP_177 {0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x0, 0xff, 0xff} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {1, 5, 7, 0, 8, 0} +#define NXFONT_BITMAP_178 {0x70, 0xd8, 0xd8, 0x30, 0x60, 0xf8, 0xf8} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {1, 5, 7, 0, 8, 0} +#define NXFONT_BITMAP_179 {0x70, 0xd8, 0x18, 0x30, 0x18, 0xd8, 0x70} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 3, 3, 1, 7, 0} +#define NXFONT_BITMAP_180 {0x20, 0x60, 0x80} + +/* mu (181) */ +#define NXFONT_METRICS_181 {1, 8, 12, 1, 11, 0} +#define NXFONT_BITMAP_181 {0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xff, 0xfb, 0xc0, 0xc0, 0xc0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {1, 8, 15, 0, 8, 0} +#define NXFONT_BITMAP_182 {0x7f, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x72, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 2, 2, 1, 14, 0} +#define NXFONT_BITMAP_183 {0xc0, 0xc0} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 5, 4, 0, 20, 0} +#define NXFONT_BITMAP_184 {0x20, 0x30, 0x98, 0x70} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 4, 7, 1, 8, 0} +#define NXFONT_BITMAP_185 {0x30, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {1, 5, 7, 0, 8, 0} +#define NXFONT_BITMAP_186 {0x70, 0xd8, 0x88, 0xd8, 0x70, 0x0, 0xf8} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {1, 8, 6, 1, 12, 0} +#define NXFONT_BITMAP_187 {0xcc, 0x66, 0x33, 0x33, 0x66, 0xcc} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {2, 13, 12, 1, 8, 0} +#define NXFONT_BITMAP_188 {0x30, 0xc0, 0xf0, 0x80, 0xf1, 0x80, 0x31, 0x0, 0x33, 0x30, 0x32, 0x70, 0x36, 0xf0, 0x4, 0xb0, 0xd, 0xb0, 0x9, 0xf8, 0x18, 0x30, 0x10, 0x30} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {2, 12, 12, 0, 8, 0} +#define NXFONT_BITMAP_189 {0x30, 0x80, 0xf1, 0x80, 0xf1, 0x0, 0x33, 0x0, 0x32, 0x0, 0x36, 0xe0, 0x35, 0xb0, 0xd, 0xb0, 0x8, 0x60, 0x18, 0xc0, 0x11, 0xf0, 0x31, 0xf0} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {2, 13, 12, 0, 8, 0} +#define NXFONT_BITMAP_190 {0x70, 0x40, 0xd8, 0xc0, 0x18, 0x80, 0x31, 0x80, 0x19, 0x30, 0xdb, 0x70, 0x72, 0xf0, 0x6, 0xb0, 0x5, 0xb0, 0xd, 0xf8, 0x8, 0x30, 0x18, 0x30} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {1, 7, 12, 1, 11, 0} +#define NXFONT_BITMAP_191 {0x30, 0x30, 0x0, 0x30, 0x30, 0x60, 0xe0, 0xc0, 0xc6, 0xc6, 0xfe, 0x7c} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {2, 11, 16, 0, 4, 0} +#define NXFONT_BITMAP_192 {0x10, 0x0, 0x18, 0x0, 0x4, 0x0, 0x0, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1f, 0x0, 0x1b, 0x0, 0x3b, 0x80, 0x31, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0x7f, 0xc0, 0xff, 0xe0, 0xc0, 0x60, 0xc0, 0x60} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {2, 11, 16, 0, 4, 0} +#define NXFONT_BITMAP_193 {0x2, 0x0, 0x6, 0x0, 0x8, 0x0, 0x0, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1f, 0x0, 0x1b, 0x0, 0x3b, 0x80, 0x31, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0x7f, 0xc0, 0xff, 0xe0, 0xc0, 0x60, 0xc0, 0x60} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {2, 11, 16, 0, 4, 0} +#define NXFONT_BITMAP_194 {0x4, 0x0, 0xe, 0x0, 0x11, 0x0, 0x0, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1f, 0x0, 0x1b, 0x0, 0x3b, 0x80, 0x31, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0x7f, 0xc0, 0xff, 0xe0, 0xc0, 0x60, 0xc0, 0x60} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {2, 11, 15, 0, 5, 0} +#define NXFONT_BITMAP_195 {0xe, 0x80, 0x17, 0x0, 0x0, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1f, 0x0, 0x1b, 0x0, 0x3b, 0x80, 0x31, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0x7f, 0xc0, 0xff, 0xe0, 0xc0, 0x60, 0xc0, 0x60} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {2, 11, 15, 0, 5, 0} +#define NXFONT_BITMAP_196 {0x31, 0x80, 0x31, 0x80, 0x0, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1f, 0x0, 0x1b, 0x0, 0x3b, 0x80, 0x31, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0x7f, 0xc0, 0xff, 0xe0, 0xc0, 0x60, 0xc0, 0x60} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {2, 11, 16, 0, 4, 0} +#define NXFONT_BITMAP_197 {0xc, 0x0, 0x12, 0x0, 0x12, 0x0, 0xc, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1f, 0x0, 0x1b, 0x0, 0x3b, 0x80, 0x31, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0x7f, 0xc0, 0xff, 0xe0, 0xc0, 0x60, 0xc0, 0x60} + +/* AE (198) */ +#define NXFONT_METRICS_198 {2, 14, 12, 0, 8, 0} +#define NXFONT_BITMAP_198 {0x1f, 0xfc, 0x1f, 0xfc, 0x1b, 0x0, 0x33, 0x0, 0x33, 0x0, 0x33, 0xf8, 0x63, 0xf8, 0x7f, 0x0, 0x7f, 0x0, 0xc3, 0x0, 0xc3, 0xfc, 0xc3, 0xfc} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {2, 10, 16, 1, 8, 0} +#define NXFONT_BITMAP_199 {0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0, 0x4, 0x0, 0x6, 0x0, 0x13, 0x0, 0xe, 0x0} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {1, 8, 16, 1, 4, 0} +#define NXFONT_BITMAP_200 {0x20, 0x30, 0x8, 0x0, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xfe, 0xfe, 0xc0, 0xc0, 0xc0, 0xff, 0xff} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {1, 8, 16, 1, 4, 0} +#define NXFONT_BITMAP_201 {0x4, 0xc, 0x10, 0x0, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xfe, 0xfe, 0xc0, 0xc0, 0xc0, 0xff, 0xff} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {1, 8, 16, 1, 4, 0} +#define NXFONT_BITMAP_202 {0x8, 0x1c, 0x22, 0x0, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xfe, 0xfe, 0xc0, 0xc0, 0xc0, 0xff, 0xff} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {1, 8, 15, 1, 5, 0} +#define NXFONT_BITMAP_203 {0x66, 0x66, 0x0, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xfe, 0xfe, 0xc0, 0xc0, 0xc0, 0xff, 0xff} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {1, 3, 16, 0, 4, 0} +#define NXFONT_BITMAP_204 {0x80, 0xc0, 0x20, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 3, 16, 1, 4, 0} +#define NXFONT_BITMAP_205 {0x20, 0x60, 0x80, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* Icircumflex (206) */ +#define NXFONT_METRICS_206 {1, 5, 16, 0, 4, 0} +#define NXFONT_BITMAP_206 {0x20, 0x70, 0x88, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* Idieresis (207) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_207 {1, 6, 15, 0, 5, 0} +#define NXFONT_BITMAP_207 {0xcc, 0xcc, 0x0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* Eth (208) */ +#define NXFONT_METRICS_208 {2, 12, 12, 0, 8, 0} +#define NXFONT_BITMAP_208 {0x3f, 0x0, 0x3f, 0xc0, 0x30, 0xe0, 0x30, 0x60, 0x30, 0x70, 0xfc, 0x30, 0xfc, 0x30, 0x30, 0x70, 0x30, 0x60, 0x30, 0xe0, 0x3f, 0xc0, 0x3f, 0x0} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {2, 10, 15, 1, 5, 0} +#define NXFONT_BITMAP_209 {0x1d, 0x0, 0x2e, 0x0, 0x0, 0x0, 0xe0, 0xc0, 0xf0, 0xc0, 0xf0, 0xc0, 0xd8, 0xc0, 0xd8, 0xc0, 0xcc, 0xc0, 0xcc, 0xc0, 0xc6, 0xc0, 0xc6, 0xc0, 0xc3, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {2, 11, 16, 1, 4, 0} +#define NXFONT_BITMAP_210 {0x8, 0x0, 0xc, 0x0, 0x2, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {2, 11, 16, 1, 4, 0} +#define NXFONT_BITMAP_211 {0x1, 0x0, 0x3, 0x0, 0x4, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {2, 11, 16, 1, 4, 0} +#define NXFONT_BITMAP_212 {0x4, 0x0, 0xe, 0x0, 0x11, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {2, 11, 15, 1, 5, 0} +#define NXFONT_BITMAP_213 {0xe, 0x80, 0x17, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {2, 11, 15, 1, 5, 0} +#define NXFONT_BITMAP_214 {0x19, 0x80, 0x19, 0x80, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {2, 9, 9, 0, 11, 0} +#define NXFONT_BITMAP_215 {0x41, 0x0, 0xe3, 0x80, 0x77, 0x0, 0x3e, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0x77, 0x0, 0xe3, 0x80, 0x41, 0x0} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {2, 11, 12, 1, 8, 0} +#define NXFONT_BITMAP_216 {0x1f, 0x20, 0x3f, 0xc0, 0x70, 0xc0, 0x61, 0xc0, 0xe3, 0x60, 0xc6, 0x60, 0xcc, 0x60, 0xd8, 0xe0, 0x70, 0xc0, 0x61, 0xc0, 0x7f, 0x80, 0x9f, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {2, 10, 16, 1, 4, 0} +#define NXFONT_BITMAP_217 {0x10, 0x0, 0x18, 0x0, 0x4, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe1, 0xc0, 0x7f, 0x80, 0x3f, 0x0} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {2, 10, 16, 1, 4, 0} +#define NXFONT_BITMAP_218 {0x2, 0x0, 0x6, 0x0, 0x8, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe1, 0xc0, 0x7f, 0x80, 0x3f, 0x0} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {2, 10, 16, 1, 4, 0} +#define NXFONT_BITMAP_219 {0x4, 0x0, 0xe, 0x0, 0x11, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe1, 0xc0, 0x7f, 0x80, 0x3f, 0x0} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {2, 10, 15, 1, 5, 0} +#define NXFONT_BITMAP_220 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe1, 0xc0, 0x7f, 0x80, 0x3f, 0x0} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {2, 10, 16, 0, 4, 0} +#define NXFONT_BITMAP_221 {0x2, 0x0, 0x6, 0x0, 0x8, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xe1, 0xc0, 0x61, 0x80, 0x33, 0x0, 0x33, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {2, 9, 12, 1, 8, 0} +#define NXFONT_BITMAP_222 {0xc0, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xc3, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc3, 0x80, 0xff, 0x0, 0xfe, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_223 {0x7c, 0xfe, 0xc6, 0xc6, 0xdc, 0xde, 0xc3, 0xc3, 0xc3, 0xc3, 0xde, 0xdc} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_224 {0x20, 0x30, 0x8, 0x0, 0x7c, 0xfe, 0xc6, 0xe, 0x7e, 0xe6, 0xc6, 0xfe, 0x77} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_225 {0x4, 0xc, 0x10, 0x0, 0x7c, 0xfe, 0xc6, 0xe, 0x7e, 0xe6, 0xc6, 0xfe, 0x77} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_226 {0x10, 0x38, 0x44, 0x0, 0x7c, 0xfe, 0xc6, 0xe, 0x7e, 0xe6, 0xc6, 0xfe, 0x77} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_227 {0x3a, 0x5c, 0x0, 0x7c, 0xfe, 0xc6, 0xe, 0x7e, 0xe6, 0xc6, 0xfe, 0x77} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_228 {0x6c, 0x6c, 0x0, 0x7c, 0xfe, 0xc6, 0xe, 0x7e, 0xe6, 0xc6, 0xfe, 0x77} + +/* aring (229) */ +#define NXFONT_METRICS_229 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_229 {0x18, 0x24, 0x24, 0x18, 0x7c, 0xfe, 0xc6, 0xe, 0x7e, 0xe6, 0xc6, 0xfe, 0x77} + +/* ae (230) */ +#define NXFONT_METRICS_230 {2, 13, 9, 1, 11, 0} +#define NXFONT_BITMAP_230 {0x7d, 0xe0, 0xff, 0xf0, 0xc6, 0x18, 0xf, 0xf8, 0x7f, 0xf8, 0xe6, 0x0, 0xcf, 0x38, 0xff, 0xf0, 0x79, 0xe0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {1, 8, 13, 1, 11, 0} +#define NXFONT_BITMAP_231 {0x3c, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e, 0x3c, 0x10, 0x18, 0x4c, 0x38} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_232 {0x20, 0x30, 0x8, 0x0, 0x3c, 0x7e, 0xc3, 0xff, 0xff, 0xc0, 0xe7, 0x7e, 0x3c} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_233 {0x4, 0xc, 0x10, 0x0, 0x3c, 0x7e, 0xc3, 0xff, 0xff, 0xc0, 0xe7, 0x7e, 0x3c} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_234 {0x8, 0x1c, 0x22, 0x0, 0x3c, 0x7e, 0xc3, 0xff, 0xff, 0xc0, 0xe7, 0x7e, 0x3c} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_235 {0x36, 0x36, 0x0, 0x3c, 0x7e, 0xc3, 0xff, 0xff, 0xc0, 0xe7, 0x7e, 0x3c} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 3, 13, 0, 7, 0} +#define NXFONT_BITMAP_236 {0x80, 0xc0, 0x20, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 3, 13, 1, 7, 0} +#define NXFONT_BITMAP_237 {0x20, 0x60, 0x80, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* icircumflex (238) */ +#define NXFONT_METRICS_238 {1, 5, 13, 0, 7, 0} +#define NXFONT_BITMAP_238 {0x20, 0x70, 0x88, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 5, 12, 0, 8, 0} +#define NXFONT_BITMAP_239 {0xd8, 0xd8, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* eth (240) */ +#define NXFONT_METRICS_240 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_240 {0x60, 0x7c, 0xf8, 0x1c, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e, 0x3c} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_241 {0x3a, 0x5c, 0x0, 0xde, 0xff, 0xe3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_242 {0x20, 0x30, 0x8, 0x0, 0x3c, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e, 0x3c} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_243 {0x8, 0x18, 0x20, 0x0, 0x3c, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e, 0x3c} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_244 {0x10, 0x38, 0x44, 0x0, 0x3c, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e, 0x3c} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_245 {0x3a, 0x5c, 0x0, 0x3c, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e, 0x3c} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_246 {0x6c, 0x6c, 0x0, 0x3c, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e, 0x3c} + +/* divide (247) */ +#define NXFONT_METRICS_247 {1, 8, 8, 1, 12, 0} +#define NXFONT_BITMAP_247 {0x18, 0x18, 0x0, 0xff, 0xff, 0x0, 0x18, 0x18} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {1, 8, 9, 1, 11, 0} +#define NXFONT_BITMAP_248 {0x3d, 0x7f, 0xe7, 0xcf, 0xdb, 0xf3, 0xe7, 0xfe, 0xbc} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_249 {0x20, 0x30, 0x8, 0x0, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xff, 0x7b} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_250 {0x8, 0x18, 0x20, 0x0, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xff, 0x7b} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {1, 8, 13, 1, 7, 0} +#define NXFONT_BITMAP_251 {0x10, 0x38, 0x44, 0x0, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xff, 0x7b} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {1, 8, 12, 1, 8, 0} +#define NXFONT_BITMAP_252 {0x6c, 0x6c, 0x0, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xff, 0x7b} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {1, 8, 17, 0, 7, 0} +#define NXFONT_BITMAP_253 {0x4, 0xc, 0x10, 0x0, 0xc3, 0xc3, 0x63, 0x66, 0x36, 0x36, 0x3c, 0x1c, 0x18, 0x18, 0x18, 0x70, 0x60} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {1, 8, 16, 1, 8, 0} +#define NXFONT_BITMAP_254 {0xc0, 0xc0, 0xc0, 0xdc, 0xfe, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0xfe, 0xdc, 0xc0, 0xc0, 0xc0, 0xc0} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {1, 8, 16, 0, 8, 0} +#define NXFONT_BITMAP_255 {0x36, 0x36, 0x0, 0xc3, 0xc3, 0x63, 0x66, 0x36, 0x36, 0x3c, 0x1c, 0x18, 0x18, 0x18, 0x70, 0x60} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SANS20X27B_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_sans22x29.h b/nuttx/graphics/nxfonts/nxfonts_sans22x29.h new file mode 100644 index 0000000000..e47020bbd3 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_sans22x29.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_sans22x29.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Jose Pablo Carballo Gomez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SANS22X29_H +#define __GRAPHICS_NXFONTS_NXFONTS_SANS22X29_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SANS22X29 + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 29 +#define NXFONT_MAXWIDTH 22 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 5 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 2, 14, 2, 8, 0} +#define NXFONT_BITMAP_33 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x0, 0x0, 0xc0, 0xc0} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {1, 5, 5, 0, 8, 0} +#define NXFONT_BITMAP_34 {0xd8, 0xd8, 0xd8, 0xd8, 0xd8} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {2, 10, 13, 0, 9, 0} +#define NXFONT_BITMAP_35 {0x9, 0x0, 0x9, 0x0, 0x9, 0x0, 0x7f, 0xc0, 0x7f, 0xc0, 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0xff, 0x80, 0xff, 0x80, 0x24, 0x0, 0x24, 0x0, 0x24, 0x0} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {2, 9, 16, 1, 8, 0} +#define NXFONT_BITMAP_36 {0x8, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0xcb, 0x0, 0xc8, 0x0, 0xe8, 0x0, 0x78, 0x0, 0x3e, 0x0, 0xf, 0x0, 0x9, 0x80, 0xc9, 0x80, 0xeb, 0x80, 0x7f, 0x0, 0x3e, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* percent (37) */ +#define NXFONT_METRICS_37 {2, 14, 13, 1, 9, 0} +#define NXFONT_BITMAP_37 {0x78, 0x60, 0xcc, 0xc0, 0xcc, 0xc0, 0xcd, 0x80, 0xcd, 0x80, 0x7b, 0x0, 0x3, 0x0, 0x6, 0x78, 0x6, 0xcc, 0xc, 0xcc, 0xc, 0xcc, 0x18, 0xcc, 0x18, 0x78} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {2, 12, 13, 1, 9, 0} +#define NXFONT_BITMAP_38 {0x3c, 0x0, 0x7e, 0x0, 0x66, 0x0, 0x66, 0x0, 0x3c, 0x0, 0x7c, 0x0, 0xee, 0xc0, 0xc6, 0xc0, 0xc3, 0xc0, 0xc3, 0x80, 0xe7, 0xc0, 0x7e, 0xe0, 0x3c, 0x70} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 1, 5, 1, 8, 0} +#define NXFONT_BITMAP_39 {0x80, 0x80, 0x80, 0x80, 0x80} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 4, 18, 0, 8, 0} +#define NXFONT_BITMAP_40 {0x10, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0x60, 0x30, 0x10} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 4, 18, 1, 8, 0} +#define NXFONT_BITMAP_41 {0x80, 0xc0, 0x60, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0x60, 0xc0, 0x80} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {1, 5, 7, 1, 8, 0} +#define NXFONT_BITMAP_42 {0x20, 0xa8, 0xf8, 0x20, 0xf8, 0xa8, 0x20} + +/* plus (43) */ +#define NXFONT_METRICS_43 {1, 8, 10, 1, 12, 0} +#define NXFONT_BITMAP_43 {0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 2, 5, 1, 20, 0} +#define NXFONT_BITMAP_44 {0xc0, 0xc0, 0x40, 0x40, 0x80} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 5, 1, 0, 16, 0} +#define NXFONT_BITMAP_45 {0xf8} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 2, 2, 1, 20, 0} +#define NXFONT_BITMAP_46 {0xc0, 0xc0} + +/* slash (47) */ +#define NXFONT_METRICS_47 {1, 5, 14, 0, 8, 0} +#define NXFONT_BITMAP_47 {0x18, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x60, 0x60, 0x60, 0xc0, 0xc0, 0xc0, 0xc0} + +/* zero (48) */ +#define NXFONT_METRICS_48 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_48 {0x3c, 0x7e, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x7e, 0x3c} + +/* one (49) */ +#define NXFONT_METRICS_49 {1, 5, 13, 2, 9, 0} +#define NXFONT_BITMAP_49 {0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18} + +/* two (50) */ +#define NXFONT_METRICS_50 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_50 {0x3c, 0xfe, 0xc3, 0x3, 0x7, 0xe, 0x1c, 0x38, 0x70, 0xe0, 0xc0, 0xff, 0xff} + +/* three (51) */ +#define NXFONT_METRICS_51 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_51 {0x3e, 0x7f, 0xc3, 0xc3, 0x6, 0x1c, 0x1e, 0x7, 0x3, 0xc3, 0xc7, 0x7e, 0x3c} + +/* four (52) */ +#define NXFONT_METRICS_52 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_52 {0x3, 0x0, 0x7, 0x0, 0xf, 0x0, 0x1b, 0x0, 0x33, 0x0, 0x33, 0x0, 0x63, 0x0, 0xc3, 0x0, 0xff, 0x80, 0xff, 0x80, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0} + +/* five (53) */ +#define NXFONT_METRICS_53 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_53 {0xfe, 0xfe, 0xc0, 0xc0, 0xfc, 0xfe, 0xc7, 0x3, 0x3, 0xc3, 0xc7, 0xfe, 0x7c} + +/* six (54) */ +#define NXFONT_METRICS_54 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_54 {0x3c, 0x7f, 0x63, 0xc0, 0xc0, 0xdc, 0xfe, 0xc3, 0xc3, 0xc3, 0xe3, 0x7e, 0x3c} + +/* seven (55) */ +#define NXFONT_METRICS_55 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_55 {0xff, 0xff, 0x3, 0x6, 0xc, 0xc, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x60} + +/* eight (56) */ +#define NXFONT_METRICS_56 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_56 {0x3c, 0x7e, 0xe7, 0xc3, 0xc3, 0x66, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0x3c} + +/* nine (57) */ +#define NXFONT_METRICS_57 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_57 {0x3c, 0x7e, 0xc7, 0xc3, 0xc3, 0xc3, 0x7f, 0x3b, 0x3, 0x3, 0xc6, 0xfe, 0x7c} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 2, 10, 1, 12, 0} +#define NXFONT_BITMAP_58 {0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 2, 13, 1, 12, 0} +#define NXFONT_BITMAP_59 {0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0x40, 0x40, 0x80} + +/* less (60) */ +#define NXFONT_METRICS_60 {1, 8, 9, 1, 13, 0} +#define NXFONT_BITMAP_60 {0x3, 0xf, 0x3c, 0x70, 0xc0, 0x70, 0x3c, 0xf, 0x3} + +/* equal (61) */ +#define NXFONT_METRICS_61 {1, 7, 5, 2, 15, 0} +#define NXFONT_BITMAP_61 {0xfe, 0xfe, 0x0, 0xfe, 0xfe} + +/* greater (62) */ +#define NXFONT_METRICS_62 {1, 8, 9, 1, 13, 0} +#define NXFONT_BITMAP_62 {0xc0, 0xf0, 0x3c, 0xe, 0x3, 0xe, 0x3c, 0xf0, 0xc0} + +/* question (63) */ +#define NXFONT_METRICS_63 {1, 7, 14, 1, 8, 0} +#define NXFONT_BITMAP_63 {0x7c, 0xfe, 0xc6, 0xc6, 0xe, 0x1c, 0x38, 0x30, 0x30, 0x30, 0x0, 0x0, 0x30, 0x30} + +/* at (64) */ +#define NXFONT_METRICS_64 {2, 16, 17, 1, 8, 0} +#define NXFONT_BITMAP_64 {0x3, 0xf0, 0xf, 0xfc, 0x1c, 0xe, 0x30, 0x6, 0x63, 0xd3, 0x67, 0x73, 0xc6, 0x33, 0xcc, 0x63, 0xcc, 0x66, 0xcc, 0x66, 0xcc, 0xcc, 0xcf, 0xf8, 0x67, 0x70, 0x70, 0x0, 0x38, 0x0, 0x1f, 0xf0, 0x7, 0xe0} + +/* A (65) */ +#define NXFONT_METRICS_65 {2, 12, 14, 0, 8, 0} +#define NXFONT_BITMAP_65 {0x6, 0x0, 0x6, 0x0, 0xf, 0x0, 0xf, 0x0, 0x19, 0x80, 0x19, 0x80, 0x30, 0xc0, 0x30, 0xc0, 0x3f, 0xc0, 0x7f, 0xe0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30} + +/* B (66) */ +#define NXFONT_METRICS_66 {2, 11, 14, 1, 8, 0} +#define NXFONT_BITMAP_66 {0xff, 0x0, 0xff, 0x80, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0x80, 0xff, 0x80, 0xff, 0xc0, 0xc0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0xe0, 0xff, 0xc0, 0xff, 0x80} + +/* C (67) */ +#define NXFONT_METRICS_67 {2, 12, 14, 1, 8, 0} +#define NXFONT_BITMAP_67 {0xf, 0x80, 0x3f, 0xe0, 0x70, 0x70, 0x60, 0x30, 0xe0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x60, 0x30, 0x70, 0x70, 0x3f, 0xe0, 0xf, 0x80} + +/* D (68) */ +#define NXFONT_METRICS_68 {2, 12, 14, 1, 8, 0} +#define NXFONT_BITMAP_68 {0xff, 0x80, 0xff, 0xc0, 0xc0, 0xe0, 0xc0, 0x60, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x60, 0xc0, 0xe0, 0xff, 0xc0, 0xff, 0x80} + +/* E (69) */ +#define NXFONT_METRICS_69 {2, 10, 14, 2, 8, 0} +#define NXFONT_BITMAP_69 {0xff, 0xc0, 0xff, 0xc0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0x80, 0xff, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* F (70) */ +#define NXFONT_METRICS_70 {2, 9, 14, 2, 8, 0} +#define NXFONT_BITMAP_70 {0xff, 0x80, 0xff, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* G (71) */ +#define NXFONT_METRICS_71 {2, 13, 14, 1, 8, 0} +#define NXFONT_BITMAP_71 {0xf, 0xc0, 0x3f, 0xf0, 0x70, 0x38, 0x60, 0x18, 0xe0, 0x18, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0xf8, 0xc0, 0xf8, 0xe0, 0x18, 0x60, 0x18, 0x70, 0x38, 0x3f, 0xf8, 0xf, 0xd8} + +/* H (72) */ +#define NXFONT_METRICS_72 {2, 11, 14, 1, 8, 0} +#define NXFONT_BITMAP_72 {0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xff, 0xe0, 0xff, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 2, 14, 2, 8, 0} +#define NXFONT_BITMAP_73 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* J (74) */ +#define NXFONT_METRICS_74 {1, 8, 14, 0, 8, 0} +#define NXFONT_BITMAP_74 {0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0xc3, 0xc3, 0xe7, 0x7e, 0x3c} + +/* K (75) */ +#define NXFONT_METRICS_75 {2, 12, 14, 2, 8, 0} +#define NXFONT_BITMAP_75 {0xc0, 0xe0, 0xc1, 0xc0, 0xc3, 0x80, 0xc7, 0x0, 0xce, 0x0, 0xdc, 0x0, 0xf8, 0x0, 0xfc, 0x0, 0xce, 0x0, 0xc7, 0x0, 0xc3, 0x80, 0xc1, 0xc0, 0xc0, 0xe0, 0xc0, 0x70} + +/* L (76) */ +#define NXFONT_METRICS_76 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_76 {0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0x80, 0xff, 0x80} + +/* M (77) */ +#define NXFONT_METRICS_77 {2, 14, 14, 1, 8, 0} +#define NXFONT_BITMAP_77 {0xc0, 0xc, 0xc0, 0xc, 0xe0, 0x1c, 0xe0, 0x1c, 0xf0, 0x3c, 0xf0, 0x3c, 0xd8, 0x6c, 0xd8, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0xc4, 0x8c, 0xc7, 0x8c, 0xc3, 0xc, 0xc3, 0xc} + +/* N (78) */ +#define NXFONT_METRICS_78 {2, 11, 14, 1, 8, 0} +#define NXFONT_BITMAP_78 {0xc0, 0x60, 0xe0, 0x60, 0xf0, 0x60, 0xf0, 0x60, 0xd8, 0x60, 0xcc, 0x60, 0xcc, 0x60, 0xc6, 0x60, 0xc6, 0x60, 0xc3, 0x60, 0xc1, 0xe0, 0xc1, 0xe0, 0xc0, 0xe0, 0xc0, 0x60} + +/* O (79) */ +#define NXFONT_METRICS_79 {2, 13, 14, 1, 8, 0} +#define NXFONT_BITMAP_79 {0xf, 0x80, 0x3f, 0xe0, 0x70, 0x70, 0x60, 0x30, 0xe0, 0x38, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xe0, 0x38, 0x60, 0x30, 0x70, 0x70, 0x3f, 0xe0, 0xf, 0x80} + +/* P (80) */ +#define NXFONT_METRICS_80 {2, 10, 14, 2, 8, 0} +#define NXFONT_BITMAP_80 {0xff, 0x0, 0xff, 0x80, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0xff, 0x80, 0xff, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {2, 13, 15, 1, 8, 0} +#define NXFONT_BITMAP_81 {0xf, 0x80, 0x3f, 0xe0, 0x70, 0x70, 0x60, 0x30, 0xe0, 0x38, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xe1, 0xb8, 0x61, 0xb0, 0x70, 0xf0, 0x3f, 0xe0, 0xf, 0xb0, 0x0, 0x30} + +/* R (82) */ +#define NXFONT_METRICS_82 {2, 11, 14, 1, 8, 0} +#define NXFONT_BITMAP_82 {0xff, 0x80, 0xff, 0xc0, 0xc0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0xe0, 0xff, 0xc0, 0xff, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60} + +/* S (83) */ +#define NXFONT_METRICS_83 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_83 {0x1e, 0x0, 0x7f, 0x80, 0xe1, 0xc0, 0xc0, 0xc0, 0xe0, 0x0, 0x7c, 0x0, 0x1f, 0x0, 0x3, 0x80, 0x1, 0xc0, 0x0, 0xc0, 0xc0, 0xc0, 0xe1, 0xc0, 0x7f, 0x80, 0x3f, 0x0} + +/* T (84) */ +#define NXFONT_METRICS_84 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_84 {0xff, 0xc0, 0xff, 0xc0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0} + +/* U (85) */ +#define NXFONT_METRICS_85 {2, 11, 14, 1, 8, 0} +#define NXFONT_BITMAP_85 {0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0x60, 0xc0, 0x7f, 0xc0, 0x1f, 0x0} + +/* V (86) */ +#define NXFONT_METRICS_86 {2, 12, 14, 0, 8, 0} +#define NXFONT_BITMAP_86 {0xc0, 0x30, 0xc0, 0x30, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x19, 0x80, 0x19, 0x80, 0x19, 0x80, 0xf, 0x0, 0xf, 0x0, 0x6, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {2, 16, 14, 1, 8, 0} +#define NXFONT_BITMAP_87 {0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc3, 0xc3, 0x63, 0xc6, 0x62, 0x46, 0x66, 0x66, 0x66, 0x66, 0x36, 0x6c, 0x36, 0x6c, 0x34, 0x2c, 0x1c, 0x38, 0x18, 0x18, 0x18, 0x18} + +/* X (88) */ +#define NXFONT_METRICS_88 {2, 11, 14, 1, 8, 0} +#define NXFONT_BITMAP_88 {0xc0, 0x60, 0xc0, 0x60, 0x60, 0xc0, 0x71, 0xc0, 0x31, 0x80, 0x1b, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1b, 0x0, 0x31, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xc0, 0x60, 0xc0, 0x60} + +/* Y (89) */ +#define NXFONT_METRICS_89 {2, 12, 14, 0, 8, 0} +#define NXFONT_BITMAP_89 {0xc0, 0x30, 0xc0, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0xc0, 0x39, 0xc0, 0x19, 0x80, 0xf, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_90 {0xff, 0xc0, 0xff, 0xc0, 0x0, 0xc0, 0x1, 0x80, 0x3, 0x0, 0x6, 0x0, 0xc, 0x0, 0x1c, 0x0, 0x18, 0x0, 0x30, 0x0, 0x60, 0x0, 0xc0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 4, 18, 0, 8, 0} +#define NXFONT_BITMAP_91 {0xf0, 0xf0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf0, 0xf0} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {1, 5, 14, 0, 8, 0} +#define NXFONT_BITMAP_92 {0xc0, 0xc0, 0xc0, 0x60, 0x60, 0x60, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x18} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 4, 18, 0, 8, 0} +#define NXFONT_BITMAP_93 {0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {1, 7, 6, 1, 9, 0} +#define NXFONT_BITMAP_94 {0x10, 0x38, 0x6c, 0x6c, 0xc6, 0xc6} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {2, 11, 2, 0, 24, 0} +#define NXFONT_BITMAP_95 {0xff, 0xe0, 0xff, 0xe0} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 4, 3, 0, 8, 0} +#define NXFONT_BITMAP_96 {0xc0, 0x60, 0x30} + +/* a (97) */ +#define NXFONT_METRICS_97 {2, 9, 10, 1, 12, 0} +#define NXFONT_BITMAP_97 {0x7e, 0x0, 0xe7, 0x0, 0xc3, 0x0, 0x7, 0x0, 0x7f, 0x0, 0xe3, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xe7, 0x80, 0x79, 0x80} + +/* b (98) */ +#define NXFONT_METRICS_98 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_98 {0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xde, 0x0, 0xff, 0x0, 0xe3, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xe3, 0x0, 0xff, 0x0, 0xde, 0x0} + +/* c (99) */ +#define NXFONT_METRICS_99 {1, 8, 10, 1, 12, 0} +#define NXFONT_BITMAP_99 {0x3e, 0x7f, 0x63, 0xc0, 0xc0, 0xc0, 0xc0, 0x63, 0x7f, 0x3e} + +/* d (100) */ +#define NXFONT_METRICS_100 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_100 {0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x3d, 0x80, 0x7f, 0x80, 0x63, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x80, 0x7f, 0x80, 0x3d, 0x80} + +/* e (101) */ +#define NXFONT_METRICS_101 {1, 8, 10, 1, 12, 0} +#define NXFONT_BITMAP_101 {0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0xc0, 0xc0, 0xe3, 0x7f, 0x3c} + +/* f (102) */ +#define NXFONT_METRICS_102 {1, 6, 14, 0, 8, 0} +#define NXFONT_BITMAP_102 {0x1c, 0x3c, 0x30, 0x30, 0xfc, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* g (103) */ +#define NXFONT_METRICS_103 {2, 9, 14, 1, 12, 0} +#define NXFONT_BITMAP_103 {0x3d, 0x80, 0x7f, 0x80, 0x61, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x80, 0x7f, 0x80, 0x3d, 0x80, 0x1, 0x80, 0x63, 0x0, 0x7f, 0x0, 0x1c, 0x0} + +/* h (104) */ +#define NXFONT_METRICS_104 {1, 8, 14, 1, 8, 0} +#define NXFONT_BITMAP_104 {0xc0, 0xc0, 0xc0, 0xc0, 0xde, 0xff, 0xe3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 2, 14, 1, 8, 0} +#define NXFONT_BITMAP_105 {0xc0, 0xc0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* j (106) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_106 {1, 4, 18, 0, 8, 0} +#define NXFONT_BITMAP_106 {0x30, 0x30, 0x0, 0x0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xe0} + +/* k (107) */ +#define NXFONT_METRICS_107 {1, 8, 14, 1, 8, 0} +#define NXFONT_BITMAP_107 {0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0xf0, 0xf8, 0xd8, 0xcc, 0xce, 0xc6, 0xc7} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 2, 14, 1, 8, 0} +#define NXFONT_BITMAP_108 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* m (109) */ +#define NXFONT_METRICS_109 {2, 14, 10, 1, 12, 0} +#define NXFONT_BITMAP_109 {0xde, 0x78, 0xff, 0xfc, 0xe3, 0x8c, 0xc3, 0xc, 0xc3, 0xc, 0xc3, 0xc, 0xc3, 0xc, 0xc3, 0xc, 0xc3, 0xc, 0xc3, 0xc} + +/* n (110) */ +#define NXFONT_METRICS_110 {1, 8, 10, 1, 12, 0} +#define NXFONT_BITMAP_110 {0xde, 0xff, 0xe3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3} + +/* o (111) */ +#define NXFONT_METRICS_111 {2, 9, 10, 1, 12, 0} +#define NXFONT_BITMAP_111 {0x3e, 0x0, 0x7f, 0x0, 0x63, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x7f, 0x0, 0x3e, 0x0} + +/* p (112) */ +#define NXFONT_METRICS_112 {2, 9, 14, 1, 12, 0} +#define NXFONT_BITMAP_112 {0xde, 0x0, 0xff, 0x0, 0xe3, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xe3, 0x0, 0xff, 0x0, 0xde, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* q (113) */ +#define NXFONT_METRICS_113 {2, 9, 14, 1, 12, 0} +#define NXFONT_BITMAP_113 {0x3d, 0x80, 0x7f, 0x80, 0x63, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x80, 0x7f, 0x80, 0x3d, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80} + +/* r (114) */ +#define NXFONT_METRICS_114 {1, 5, 10, 1, 12, 0} +#define NXFONT_BITMAP_114 {0xd8, 0xd8, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* s (115) */ +#define NXFONT_METRICS_115 {1, 7, 10, 1, 12, 0} +#define NXFONT_BITMAP_115 {0x3c, 0x7e, 0xc6, 0xc0, 0xfc, 0x3e, 0x6, 0xc6, 0xfc, 0x78} + +/* t (116) */ +#define NXFONT_METRICS_116 {1, 6, 13, 0, 9, 0} +#define NXFONT_BITMAP_116 {0x30, 0x30, 0x30, 0xfc, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x1c} + +/* u (117) */ +#define NXFONT_METRICS_117 {1, 8, 10, 1, 12, 0} +#define NXFONT_BITMAP_117 {0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xff, 0x7b} + +/* v (118) */ +#define NXFONT_METRICS_118 {1, 8, 10, 1, 12, 0} +#define NXFONT_BITMAP_118 {0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x66, 0x24, 0x3c, 0x18, 0x18} + +/* w (119) */ +#define NXFONT_METRICS_119 {2, 12, 10, 1, 12, 0} +#define NXFONT_BITMAP_119 {0xc6, 0x30, 0xc6, 0x30, 0xc6, 0x30, 0x66, 0x60, 0x66, 0x60, 0x69, 0x60, 0x29, 0x40, 0x39, 0xc0, 0x19, 0x80, 0x19, 0x80} + +/* x (120) */ +#define NXFONT_METRICS_120 {1, 8, 10, 1, 12, 0} +#define NXFONT_BITMAP_120 {0xc3, 0xe7, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0xe7, 0xc3} + +/* y (121) */ +#define NXFONT_METRICS_121 {1, 8, 14, 1, 12, 0} +#define NXFONT_BITMAP_121 {0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x66, 0x24, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x70, 0x70} + +/* z (122) */ +#define NXFONT_METRICS_122 {1, 7, 10, 1, 12, 0} +#define NXFONT_BITMAP_122 {0xfe, 0xfe, 0x6, 0xc, 0x18, 0x30, 0x60, 0xc0, 0xfe, 0xfe} + +/* braceleft (123) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_123 {1, 6, 18, 0, 8, 0} +#define NXFONT_BITMAP_123 {0xc, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0xc} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 2, 18, 1, 8, 0} +#define NXFONT_BITMAP_124 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 6, 18, 0, 8, 0} +#define NXFONT_BITMAP_125 {0xc0, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0xc, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0xc0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {1, 8, 3, 1, 15, 0} +#define NXFONT_BITMAP_126 {0x73, 0xff, 0xce} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 2, 14, 2, 12, 0} +#define NXFONT_BITMAP_161 {0xc0, 0xc0, 0x0, 0x0, 0x40, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* cent (162) */ +#define NXFONT_METRICS_162 {1, 8, 14, 1, 10, 0} +#define NXFONT_BITMAP_162 {0x4, 0x4, 0x3e, 0x7f, 0x6b, 0xc8, 0xc8, 0xc8, 0xc8, 0x6b, 0x7f, 0x3e, 0x10, 0x10} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_163 {0x1e, 0x0, 0x3f, 0x0, 0x61, 0x80, 0x61, 0x80, 0x60, 0x0, 0x30, 0x0, 0x7e, 0x0, 0x18, 0x0, 0x18, 0x0, 0x30, 0x0, 0x60, 0x80, 0xff, 0x80, 0xdf, 0x0} + +/* currency (164) */ +#define NXFONT_METRICS_164 {1, 8, 7, 1, 12, 0} +#define NXFONT_BITMAP_164 {0xc3, 0xff, 0x66, 0x66, 0x66, 0xff, 0xc3} + +/* yen (165) */ +#define NXFONT_METRICS_165 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_165 {0xc3, 0xc3, 0x66, 0x66, 0x66, 0x3c, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 2, 18, 1, 8, 0} +#define NXFONT_BITMAP_166 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* section (167) */ +#define NXFONT_METRICS_167 {1, 8, 18, 1, 8, 0} +#define NXFONT_BITMAP_167 {0x3c, 0x7e, 0xc3, 0xc3, 0xf0, 0x7c, 0x6e, 0xc7, 0xc3, 0xe3, 0x73, 0x3e, 0xe, 0x7, 0xc3, 0xc3, 0x7e, 0x3c} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 5, 2, 0, 8, 0} +#define NXFONT_BITMAP_168 {0xd8, 0xd8} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {2, 13, 14, 1, 8, 0} +#define NXFONT_BITMAP_169 {0xf, 0x80, 0x30, 0x60, 0x40, 0x10, 0x47, 0x10, 0x88, 0x88, 0x90, 0x88, 0x90, 0x8, 0x90, 0x8, 0x90, 0x8, 0x88, 0x88, 0x47, 0x10, 0x40, 0x10, 0x30, 0x60, 0xf, 0x80} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {1, 5, 8, 1, 8, 0} +#define NXFONT_BITMAP_170 {0x70, 0x98, 0x38, 0x48, 0xd8, 0x68, 0x0, 0xf8} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {1, 7, 6, 1, 14, 0} +#define NXFONT_BITMAP_171 {0x36, 0x6c, 0xd8, 0xd8, 0x6c, 0x36} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {2, 9, 5, 1, 14, 0} +#define NXFONT_BITMAP_172 {0xff, 0x80, 0xff, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 5, 1, 0, 16, 0} +#define NXFONT_BITMAP_173 {0xf8} + +/* registered (174) */ +#define NXFONT_METRICS_174 {2, 13, 14, 0, 8, 0} +#define NXFONT_BITMAP_174 {0xf, 0x80, 0x30, 0x60, 0x40, 0x10, 0x4f, 0x90, 0x88, 0x48, 0x88, 0x48, 0x88, 0x48, 0x8f, 0x88, 0x89, 0x8, 0x88, 0x88, 0x48, 0x50, 0x40, 0x10, 0x30, 0x60, 0xf, 0x80} + +/* macron (175) */ +#define NXFONT_METRICS_175 {1, 5, 1, 0, 9, 0} +#define NXFONT_BITMAP_175 {0xf8} + +/* degree (176) */ +#define NXFONT_METRICS_176 {1, 5, 5, 1, 9, 0} +#define NXFONT_BITMAP_176 {0x70, 0xd8, 0x88, 0xd8, 0x70} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {1, 8, 11, 1, 11, 0} +#define NXFONT_BITMAP_177 {0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x0, 0xff, 0xff} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {1, 5, 8, 0, 9, 0} +#define NXFONT_BITMAP_178 {0x70, 0xf8, 0x98, 0x18, 0x30, 0x60, 0xf8, 0xf8} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {1, 5, 8, 0, 9, 0} +#define NXFONT_BITMAP_179 {0x70, 0xf8, 0x98, 0x30, 0x30, 0x98, 0xf8, 0x70} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 4, 3, 0, 8, 0} +#define NXFONT_BITMAP_180 {0x30, 0x60, 0xc0} + +/* mu (181) */ +#define NXFONT_METRICS_181 {1, 8, 14, 1, 12, 0} +#define NXFONT_BITMAP_181 {0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0xff, 0xdb, 0xc0, 0xc0, 0xc0, 0xc0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {1, 8, 18, 1, 8, 0} +#define NXFONT_BITMAP_182 {0x3f, 0x72, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x72, 0x32, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 2, 2, 1, 16, 0} +#define NXFONT_BITMAP_183 {0xc0, 0xc0} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 5, 5, 0, 21, 0} +#define NXFONT_BITMAP_184 {0x60, 0x70, 0x18, 0xd8, 0xf0} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 4, 8, 0, 9, 0} +#define NXFONT_BITMAP_185 {0x30, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {1, 5, 8, 1, 8, 0} +#define NXFONT_BITMAP_186 {0x70, 0xd8, 0x88, 0x88, 0xd8, 0x70, 0x0, 0xf8} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {1, 7, 6, 1, 14, 0} +#define NXFONT_BITMAP_187 {0xd8, 0x6c, 0x36, 0x36, 0x6c, 0xd8} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {2, 14, 13, 0, 9, 0} +#define NXFONT_BITMAP_188 {0x30, 0x30, 0xf0, 0x30, 0xf0, 0x60, 0x30, 0xc0, 0x30, 0xc0, 0x31, 0x88, 0x31, 0x18, 0x33, 0x38, 0x6, 0x78, 0x6, 0xd8, 0xc, 0xfc, 0x18, 0x18, 0x18, 0x18} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {2, 14, 13, 0, 9, 0} +#define NXFONT_BITMAP_189 {0x30, 0x30, 0xf0, 0x30, 0xf0, 0x60, 0x30, 0xc0, 0x30, 0xc0, 0x31, 0xb8, 0x31, 0x7c, 0x33, 0x4c, 0x6, 0xc, 0x6, 0x18, 0xc, 0x30, 0x18, 0x7c, 0x18, 0x7c} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {2, 14, 13, 0, 9, 0} +#define NXFONT_BITMAP_190 {0x70, 0x30, 0xf8, 0x30, 0x98, 0x60, 0x30, 0xc0, 0x30, 0xc0, 0x99, 0x88, 0xf9, 0x18, 0x73, 0x38, 0x6, 0x78, 0x6, 0xd8, 0xc, 0xfc, 0x18, 0x18, 0x18, 0x18} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {1, 7, 14, 1, 12, 0} +#define NXFONT_BITMAP_191 {0x18, 0x18, 0x0, 0x0, 0x18, 0x18, 0x18, 0x38, 0x70, 0xe0, 0xc6, 0xc6, 0xfe, 0x7c} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {2, 12, 18, 0, 4, 0} +#define NXFONT_BITMAP_192 {0x18, 0x0, 0xc, 0x0, 0x6, 0x0, 0x0, 0x0, 0x6, 0x0, 0x6, 0x0, 0xf, 0x0, 0xf, 0x0, 0x19, 0x80, 0x19, 0x80, 0x30, 0xc0, 0x30, 0xc0, 0x3f, 0xc0, 0x7f, 0xe0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {2, 12, 18, 0, 4, 0} +#define NXFONT_BITMAP_193 {0x1, 0x80, 0x3, 0x0, 0x6, 0x0, 0x0, 0x0, 0x6, 0x0, 0x6, 0x0, 0xf, 0x0, 0xf, 0x0, 0x19, 0x80, 0x19, 0x80, 0x30, 0xc0, 0x30, 0xc0, 0x3f, 0xc0, 0x7f, 0xe0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {2, 12, 18, 0, 4, 0} +#define NXFONT_BITMAP_194 {0x6, 0x0, 0xf, 0x0, 0x19, 0x80, 0x0, 0x0, 0x6, 0x0, 0x6, 0x0, 0xf, 0x0, 0xf, 0x0, 0x19, 0x80, 0x19, 0x80, 0x30, 0xc0, 0x30, 0xc0, 0x3f, 0xc0, 0x7f, 0xe0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {2, 12, 18, 0, 4, 0} +#define NXFONT_BITMAP_195 {0xc, 0x80, 0x16, 0x80, 0x13, 0x0, 0x0, 0x0, 0x6, 0x0, 0x6, 0x0, 0xf, 0x0, 0xf, 0x0, 0x19, 0x80, 0x19, 0x80, 0x30, 0xc0, 0x30, 0xc0, 0x3f, 0xc0, 0x7f, 0xe0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {2, 12, 17, 0, 5, 0} +#define NXFONT_BITMAP_196 {0x19, 0x80, 0x19, 0x80, 0x0, 0x0, 0x6, 0x0, 0x6, 0x0, 0xf, 0x0, 0xf, 0x0, 0x19, 0x80, 0x19, 0x80, 0x30, 0xc0, 0x30, 0xc0, 0x3f, 0xc0, 0x7f, 0xe0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {2, 12, 17, 0, 5, 0} +#define NXFONT_BITMAP_197 {0x6, 0x0, 0x9, 0x0, 0x9, 0x0, 0x6, 0x0, 0x6, 0x0, 0xf, 0x0, 0xf, 0x0, 0x19, 0x80, 0x19, 0x80, 0x30, 0xc0, 0x30, 0xc0, 0x3f, 0xc0, 0x7f, 0xe0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30} + +/* AE (198) */ +#define NXFONT_METRICS_198 {2, 16, 14, 1, 8, 0} +#define NXFONT_BITMAP_198 {0x7, 0xff, 0x7, 0xff, 0xd, 0x80, 0xd, 0x80, 0x19, 0x80, 0x19, 0x80, 0x31, 0xfe, 0x31, 0xfe, 0x3f, 0x80, 0x7f, 0x80, 0x61, 0x80, 0x61, 0x80, 0xc1, 0xff, 0xc1, 0xff} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {2, 12, 18, 1, 8, 0} +#define NXFONT_BITMAP_199 {0xf, 0x80, 0x3f, 0xe0, 0x70, 0x70, 0x60, 0x30, 0xe0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x60, 0x30, 0x70, 0x70, 0x3f, 0xe0, 0xf, 0x80, 0x6, 0x0, 0x3, 0x0, 0x1b, 0x0, 0x1e, 0x0} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {2, 10, 18, 2, 4, 0} +#define NXFONT_BITMAP_200 {0x30, 0x0, 0x18, 0x0, 0xc, 0x0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0x80, 0xff, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {2, 10, 18, 2, 4, 0} +#define NXFONT_BITMAP_201 {0x3, 0x0, 0x6, 0x0, 0xc, 0x0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0x80, 0xff, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {2, 10, 18, 2, 4, 0} +#define NXFONT_BITMAP_202 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0x80, 0xff, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {2, 10, 17, 2, 5, 0} +#define NXFONT_BITMAP_203 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0x80, 0xff, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {1, 4, 18, 0, 4, 0} +#define NXFONT_BITMAP_204 {0xc0, 0x60, 0x30, 0x0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 4, 18, 2, 4, 0} +#define NXFONT_BITMAP_205 {0x30, 0x60, 0xc0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* Icircumflex (206) */ +#define NXFONT_METRICS_206 {1, 6, 18, 0, 4, 0} +#define NXFONT_BITMAP_206 {0x30, 0x78, 0x84, 0x0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {1, 6, 17, 0, 5, 0} +#define NXFONT_BITMAP_207 {0xcc, 0xcc, 0x0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* Eth (208) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_208 {2, 14, 14, 0, 8, 0} +#define NXFONT_BITMAP_208 {0x3f, 0xe0, 0x3f, 0xf0, 0x30, 0x38, 0x30, 0x18, 0x30, 0xc, 0x30, 0xc, 0xfe, 0xc, 0xfe, 0xc, 0x30, 0xc, 0x30, 0xc, 0x30, 0x18, 0x30, 0x38, 0x3f, 0xf0, 0x3f, 0xe0} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {2, 11, 18, 1, 4, 0} +#define NXFONT_BITMAP_209 {0xc, 0x80, 0x16, 0x80, 0x13, 0x0, 0x0, 0x0, 0xc0, 0x60, 0xe0, 0x60, 0xf0, 0x60, 0xf0, 0x60, 0xd8, 0x60, 0xcc, 0x60, 0xcc, 0x60, 0xc6, 0x60, 0xc6, 0x60, 0xc3, 0x60, 0xc1, 0xe0, 0xc1, 0xe0, 0xc0, 0xe0, 0xc0, 0x60} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {2, 13, 18, 1, 4, 0} +#define NXFONT_BITMAP_210 {0x18, 0x0, 0xc, 0x0, 0x6, 0x0, 0x0, 0x0, 0xf, 0x80, 0x3f, 0xe0, 0x70, 0x70, 0x60, 0x30, 0xe0, 0x38, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xe0, 0x38, 0x60, 0x30, 0x70, 0x70, 0x3f, 0xe0, 0xf, 0x80} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {2, 13, 18, 1, 4, 0} +#define NXFONT_BITMAP_211 {0x1, 0x80, 0x3, 0x0, 0x6, 0x0, 0x0, 0x0, 0xf, 0x80, 0x3f, 0xe0, 0x70, 0x70, 0x60, 0x30, 0xe0, 0x38, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xe0, 0x38, 0x60, 0x30, 0x70, 0x70, 0x3f, 0xe0, 0xf, 0x80} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {2, 13, 18, 1, 4, 0} +#define NXFONT_BITMAP_212 {0x3, 0x0, 0x7, 0x80, 0xc, 0xc0, 0x0, 0x0, 0xf, 0x80, 0x3f, 0xe0, 0x70, 0x70, 0x60, 0x30, 0xe0, 0x38, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xe0, 0x38, 0x60, 0x30, 0x70, 0x70, 0x3f, 0xe0, 0xf, 0x80} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {2, 13, 18, 1, 4, 0} +#define NXFONT_BITMAP_213 {0x6, 0x40, 0xb, 0x40, 0x9, 0x80, 0x0, 0x0, 0xf, 0x80, 0x3f, 0xe0, 0x70, 0x70, 0x60, 0x30, 0xe0, 0x38, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xe0, 0x38, 0x60, 0x30, 0x70, 0x70, 0x3f, 0xe0, 0xf, 0x80} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {2, 13, 17, 1, 5, 0} +#define NXFONT_BITMAP_214 {0xc, 0xc0, 0xc, 0xc0, 0x0, 0x0, 0xf, 0x80, 0x3f, 0xe0, 0x70, 0x70, 0x60, 0x30, 0xe0, 0x38, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xe0, 0x38, 0x60, 0x30, 0x70, 0x70, 0x3f, 0xe0, 0xf, 0x80} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {2, 10, 9, 0, 13, 0} +#define NXFONT_BITMAP_215 {0xc0, 0xc0, 0x61, 0x80, 0x33, 0x0, 0x1e, 0x0, 0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x61, 0x80, 0xc0, 0xc0} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {2, 14, 14, 0, 8, 0} +#define NXFONT_BITMAP_216 {0x7, 0xcc, 0x1f, 0xf8, 0x38, 0x30, 0x30, 0x78, 0x70, 0xdc, 0x61, 0x8c, 0x63, 0xc, 0x62, 0xc, 0x66, 0xc, 0x6c, 0x1c, 0x38, 0x18, 0x38, 0x38, 0x6f, 0xf0, 0xc7, 0xc0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {2, 11, 18, 1, 4, 0} +#define NXFONT_BITMAP_217 {0x18, 0x0, 0xc, 0x0, 0x6, 0x0, 0x0, 0x0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0x60, 0xc0, 0x7f, 0xc0, 0x1f, 0x0} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {2, 11, 18, 1, 4, 0} +#define NXFONT_BITMAP_218 {0x3, 0x0, 0x6, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0x60, 0xc0, 0x7f, 0xc0, 0x1f, 0x0} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {2, 11, 18, 1, 4, 0} +#define NXFONT_BITMAP_219 {0x6, 0x0, 0xf, 0x0, 0x19, 0x80, 0x0, 0x0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0x60, 0xc0, 0x7f, 0xc0, 0x1f, 0x0} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {2, 11, 17, 1, 5, 0} +#define NXFONT_BITMAP_220 {0x31, 0x80, 0x31, 0x80, 0x0, 0x0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0x60, 0xc0, 0x7f, 0xc0, 0x1f, 0x0} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {2, 12, 18, 0, 4, 0} +#define NXFONT_BITMAP_221 {0x1, 0x80, 0x3, 0x0, 0x6, 0x0, 0x0, 0x0, 0xc0, 0x30, 0xc0, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0xc0, 0x39, 0xc0, 0x19, 0x80, 0xf, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_222 {0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0x0, 0xff, 0x80, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0xff, 0x80, 0xff, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {1, 7, 14, 1, 8, 0} +#define NXFONT_BITMAP_223 {0x38, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xdc, 0xdc, 0xc6, 0xc6, 0xc6, 0xc6, 0xde, 0xdc} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_224 {0x30, 0x0, 0x18, 0x0, 0xc, 0x0, 0x0, 0x0, 0x7e, 0x0, 0xe7, 0x0, 0xc3, 0x0, 0x7, 0x0, 0x7f, 0x0, 0xe3, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xe7, 0x80, 0x79, 0x80} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_225 {0xc, 0x0, 0x18, 0x0, 0x30, 0x0, 0x0, 0x0, 0x7e, 0x0, 0xe7, 0x0, 0xc3, 0x0, 0x7, 0x0, 0x7f, 0x0, 0xe3, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xe7, 0x80, 0x79, 0x80} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_226 {0x18, 0x0, 0x3c, 0x0, 0x66, 0x0, 0x0, 0x0, 0x7e, 0x0, 0xe7, 0x0, 0xc3, 0x0, 0x7, 0x0, 0x7f, 0x0, 0xe3, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xe7, 0x80, 0x79, 0x80} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_227 {0x32, 0x0, 0x5a, 0x0, 0x4c, 0x0, 0x0, 0x0, 0x7e, 0x0, 0xe7, 0x0, 0xc3, 0x0, 0x7, 0x0, 0x7f, 0x0, 0xe3, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xe7, 0x80, 0x79, 0x80} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_228 {0x66, 0x0, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7e, 0x0, 0xe7, 0x0, 0xc3, 0x0, 0x7, 0x0, 0x7f, 0x0, 0xe3, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xe7, 0x80, 0x79, 0x80} + +/* aring (229) */ +#define NXFONT_METRICS_229 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_229 {0x18, 0x0, 0x24, 0x0, 0x24, 0x0, 0x18, 0x0, 0x7e, 0x0, 0xe7, 0x0, 0xc3, 0x0, 0x7, 0x0, 0x7f, 0x0, 0xe3, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xe7, 0x80, 0x79, 0x80} + +/* ae (230) */ +#define NXFONT_METRICS_230 {2, 14, 10, 2, 12, 0} +#define NXFONT_BITMAP_230 {0x7e, 0xf0, 0xe7, 0xf8, 0xc3, 0xc, 0x7, 0xc, 0x7f, 0xfc, 0xe3, 0x0, 0xc3, 0x0, 0xc3, 0x8c, 0xe7, 0xfc, 0x7a, 0xf0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {1, 8, 14, 1, 12, 0} +#define NXFONT_BITMAP_231 {0x3e, 0x7f, 0x63, 0xc0, 0xc0, 0xc0, 0xc0, 0x63, 0x7f, 0x3e, 0x18, 0xc, 0x6c, 0x78} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {1, 8, 14, 1, 8, 0} +#define NXFONT_BITMAP_232 {0x30, 0x18, 0xc, 0x0, 0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0xc0, 0xc0, 0xe3, 0x7f, 0x3c} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {1, 8, 14, 1, 8, 0} +#define NXFONT_BITMAP_233 {0xc, 0x18, 0x30, 0x0, 0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0xc0, 0xc0, 0xe3, 0x7f, 0x3c} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {1, 8, 14, 1, 8, 0} +#define NXFONT_BITMAP_234 {0x18, 0x3c, 0x66, 0x0, 0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0xc0, 0xc0, 0xe3, 0x7f, 0x3c} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {1, 8, 14, 1, 8, 0} +#define NXFONT_BITMAP_235 {0x66, 0x66, 0x0, 0x0, 0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0xc0, 0xc0, 0xe3, 0x7f, 0x3c} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 4, 14, 0, 8, 0} +#define NXFONT_BITMAP_236 {0xc0, 0x60, 0x30, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 4, 14, 0, 8, 0} +#define NXFONT_BITMAP_237 {0x30, 0x60, 0xc0, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* icircumflex (238) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_238 {1, 6, 14, 0, 8, 0} +#define NXFONT_BITMAP_238 {0x30, 0x78, 0xcc, 0x0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 5, 14, 0, 8, 0} +#define NXFONT_BITMAP_239 {0xd8, 0xd8, 0x0, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* eth (240) */ +#define NXFONT_METRICS_240 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_240 {0x60, 0x0, 0x36, 0x0, 0x38, 0x0, 0x4c, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0x63, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x7f, 0x0, 0x3e, 0x0} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {1, 8, 14, 1, 8, 0} +#define NXFONT_BITMAP_241 {0x32, 0x5a, 0x4c, 0x0, 0xde, 0xff, 0xe3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_242 {0x30, 0x0, 0x18, 0x0, 0xc, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0x63, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x7f, 0x0, 0x3e, 0x0} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_243 {0x6, 0x0, 0xc, 0x0, 0x18, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0x63, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x7f, 0x0, 0x3e, 0x0} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_244 {0x18, 0x0, 0x3c, 0x0, 0x66, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0x63, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x7f, 0x0, 0x3e, 0x0} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_245 {0x32, 0x0, 0x5a, 0x0, 0x4c, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0x63, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x7f, 0x0, 0x3e, 0x0} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_246 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0x63, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x7f, 0x0, 0x3e, 0x0} + +/* divide (247) */ +#define NXFONT_METRICS_247 {1, 8, 8, 1, 13, 0} +#define NXFONT_BITMAP_247 {0x18, 0x18, 0x0, 0xff, 0xff, 0x0, 0x18, 0x18} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {2, 11, 10, 0, 12, 0} +#define NXFONT_BITMAP_248 {0xe, 0x60, 0x3f, 0xc0, 0x31, 0x80, 0x63, 0xc0, 0x66, 0xc0, 0x6c, 0xc0, 0x78, 0xc0, 0x31, 0x80, 0x7f, 0x80, 0xce, 0x0} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {1, 8, 14, 1, 8, 0} +#define NXFONT_BITMAP_249 {0x30, 0x18, 0xc, 0x0, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xff, 0x7b} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {1, 8, 14, 1, 8, 0} +#define NXFONT_BITMAP_250 {0x6, 0xc, 0x18, 0x0, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xff, 0x7b} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {1, 8, 14, 1, 8, 0} +#define NXFONT_BITMAP_251 {0x18, 0x3c, 0x66, 0x0, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xff, 0x7b} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {1, 8, 14, 1, 8, 0} +#define NXFONT_BITMAP_252 {0x66, 0x66, 0x0, 0x0, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xff, 0x7b} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {1, 8, 18, 1, 8, 0} +#define NXFONT_BITMAP_253 {0x6, 0xc, 0x18, 0x0, 0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x66, 0x24, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x70, 0x70} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {2, 9, 18, 1, 8, 0} +#define NXFONT_BITMAP_254 {0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xde, 0x0, 0xff, 0x0, 0xe3, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xe3, 0x0, 0xff, 0x0, 0xde, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {1, 8, 18, 1, 8, 0} +#define NXFONT_BITMAP_255 {0x66, 0x66, 0x0, 0x0, 0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x66, 0x24, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x70, 0x70} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SANS22X29_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_sans22x29b.h b/nuttx/graphics/nxfonts/nxfonts_sans22x29b.h new file mode 100644 index 0000000000..c2e29bff07 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_sans22x29b.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_sans22x29b.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Jose Pablo Carballo Gomez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SANS22X29B_H +#define __GRAPHICS_NXFONTS_NXFONTS_SANS22X29B_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SANS22X29B + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 29 +#define NXFONT_MAXWIDTH 22 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 5 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 3, 14, 1, 8, 0} +#define NXFONT_BITMAP_33 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0x0, 0xe0, 0xe0, 0xe0} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {1, 5, 5, 1, 8, 0} +#define NXFONT_BITMAP_34 {0xd8, 0xd8, 0xd8, 0xd8, 0x90} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {2, 11, 13, 0, 9, 0} +#define NXFONT_BITMAP_35 {0xd, 0x80, 0xd, 0x80, 0xd, 0x80, 0x7f, 0xe0, 0x7f, 0xe0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0x36, 0x0, 0x36, 0x0, 0x36, 0x0} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {2, 10, 16, 0, 8, 0} +#define NXFONT_BITMAP_36 {0x4, 0x0, 0x3f, 0x0, 0x7f, 0x80, 0xe5, 0x80, 0xe4, 0x0, 0xe4, 0x0, 0x7c, 0x0, 0x3f, 0x0, 0xf, 0x80, 0x9, 0xc0, 0xe9, 0xc0, 0xe9, 0xc0, 0x7f, 0x80, 0x3f, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* percent (37) */ +#define NXFONT_METRICS_37 {2, 13, 13, 1, 9, 0} +#define NXFONT_BITMAP_37 {0x78, 0x60, 0xfc, 0x60, 0xcc, 0xc0, 0xcc, 0x80, 0xfd, 0x80, 0x7b, 0x0, 0x2, 0x0, 0x6, 0xf0, 0xd, 0xf8, 0x9, 0x98, 0x19, 0x98, 0x31, 0xf8, 0x30, 0xf0} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {2, 13, 14, 1, 8, 0} +#define NXFONT_BITMAP_38 {0x1e, 0x0, 0x3f, 0x0, 0x73, 0x80, 0x61, 0x80, 0x73, 0x0, 0x3e, 0x0, 0x1c, 0x60, 0x7e, 0x60, 0xe7, 0xe0, 0xc3, 0xc0, 0xc1, 0xc0, 0xe3, 0xe0, 0x7f, 0x70, 0x3e, 0x38} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 2, 5, 1, 8, 0} +#define NXFONT_BITMAP_39 {0xc0, 0xc0, 0xc0, 0xc0, 0x80} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 6, 18, 1, 8, 0} +#define NXFONT_BITMAP_40 {0x1c, 0x38, 0x30, 0x70, 0x60, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x60, 0x70, 0x30, 0x38, 0x1c} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 6, 18, 0, 8, 0} +#define NXFONT_BITMAP_41 {0xe0, 0x70, 0x30, 0x38, 0x18, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x18, 0x38, 0x30, 0x70, 0xe0} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {1, 7, 6, 1, 8, 0} +#define NXFONT_BITMAP_42 {0x10, 0xd6, 0x7c, 0x38, 0x6c, 0x44} + +/* plus (43) */ +#define NXFONT_METRICS_43 {1, 8, 8, 1, 13, 0} +#define NXFONT_BITMAP_43 {0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 3, 6, 1, 19, 0} +#define NXFONT_BITMAP_44 {0xe0, 0xe0, 0xe0, 0x60, 0xc0, 0x80} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 5, 3, 0, 15, 0} +#define NXFONT_BITMAP_45 {0xf8, 0xf8, 0xf8} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 3, 3, 1, 19, 0} +#define NXFONT_BITMAP_46 {0xe0, 0xe0, 0xe0} + +/* slash (47) */ +#define NXFONT_METRICS_47 {1, 5, 14, 0, 8, 0} +#define NXFONT_BITMAP_47 {0x18, 0x18, 0x18, 0x38, 0x30, 0x30, 0x30, 0x70, 0x60, 0x60, 0xe0, 0xc0, 0xc0, 0xc0} + +/* zero (48) */ +#define NXFONT_METRICS_48 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_48 {0x1c, 0x0, 0x7f, 0x0, 0x77, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x77, 0x0, 0x7f, 0x0, 0x1c, 0x0} + +/* one (49) */ +#define NXFONT_METRICS_49 {1, 6, 13, 1, 9, 0} +#define NXFONT_BITMAP_49 {0x1c, 0x3c, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c} + +/* two (50) */ +#define NXFONT_METRICS_50 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_50 {0x3e, 0x0, 0x7f, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0x3, 0x80, 0x7, 0x0, 0x1f, 0x0, 0x3e, 0x0, 0x78, 0x0, 0x70, 0x0, 0xe0, 0x0, 0xff, 0x80, 0xff, 0x80} + +/* three (51) */ +#define NXFONT_METRICS_51 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_51 {0x3e, 0x0, 0x7f, 0x0, 0xe7, 0x0, 0xe3, 0x0, 0x7, 0x0, 0x1e, 0x0, 0x1f, 0x0, 0x7, 0x80, 0x3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0x7f, 0x0, 0x3e, 0x0} + +/* four (52) */ +#define NXFONT_METRICS_52 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_52 {0x7, 0x0, 0xf, 0x0, 0x1f, 0x0, 0x3f, 0x0, 0x37, 0x0, 0x77, 0x0, 0x67, 0x0, 0xe7, 0x0, 0xff, 0x80, 0xff, 0x80, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0} + +/* five (53) */ +#define NXFONT_METRICS_53 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_53 {0xff, 0x0, 0xff, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xe7, 0x80, 0x3, 0x80, 0x3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0x0, 0x7e, 0x0} + +/* six (54) */ +#define NXFONT_METRICS_54 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_54 {0x3f, 0x0, 0x7f, 0x80, 0x71, 0x80, 0xe0, 0x0, 0xee, 0x0, 0xff, 0x0, 0xf3, 0x80, 0xe1, 0x80, 0xe1, 0x80, 0xe1, 0x80, 0xf3, 0x80, 0x7f, 0x0, 0x3e, 0x0} + +/* seven (55) */ +#define NXFONT_METRICS_55 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_55 {0xff, 0x80, 0xff, 0x80, 0x3, 0x80, 0x7, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x38, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0} + +/* eight (56) */ +#define NXFONT_METRICS_56 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_56 {0x3e, 0x0, 0x7f, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x7f, 0x0, 0x3e, 0x0, 0x77, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x7f, 0x0, 0x3e, 0x0} + +/* nine (57) */ +#define NXFONT_METRICS_57 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_57 {0x3e, 0x0, 0x7f, 0x0, 0xe7, 0x80, 0xc3, 0x80, 0xc3, 0x80, 0xc3, 0x80, 0xe7, 0x80, 0x7f, 0x80, 0x3b, 0x80, 0x3, 0x80, 0xc7, 0x0, 0xff, 0x0, 0x7e, 0x0} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 3, 10, 1, 12, 0} +#define NXFONT_BITMAP_58 {0xe0, 0xe0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0xe0, 0xe0} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 3, 13, 1, 12, 0} +#define NXFONT_BITMAP_59 {0xe0, 0xe0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0xe0, 0xe0, 0x60, 0xc0, 0x80} + +/* less (60) */ +#define NXFONT_METRICS_60 {2, 9, 9, 1, 13, 0} +#define NXFONT_BITMAP_60 {0x3, 0x80, 0xf, 0x80, 0x3e, 0x0, 0x78, 0x0, 0xe0, 0x0, 0x78, 0x0, 0x3e, 0x0, 0xf, 0x80, 0x3, 0x80} + +/* equal (61) */ +#define NXFONT_METRICS_61 {2, 9, 5, 1, 14, 0} +#define NXFONT_BITMAP_61 {0xff, 0x80, 0xff, 0x80, 0x0, 0x0, 0xff, 0x80, 0xff, 0x80} + +/* greater (62) */ +#define NXFONT_METRICS_62 {2, 9, 9, 1, 13, 0} +#define NXFONT_BITMAP_62 {0xe0, 0x0, 0xf8, 0x0, 0x3e, 0x0, 0xf, 0x0, 0x3, 0x80, 0xf, 0x0, 0x3e, 0x0, 0xf8, 0x0, 0xe0, 0x0} + +/* question (63) */ +#define NXFONT_METRICS_63 {1, 8, 14, 1, 8, 0} +#define NXFONT_BITMAP_63 {0x7e, 0xff, 0xe7, 0xe7, 0xe, 0x1e, 0x1c, 0x38, 0x38, 0x38, 0x0, 0x38, 0x38, 0x38} + +/* at (64) */ +#define NXFONT_METRICS_64 {2, 16, 17, 1, 8, 0} +#define NXFONT_BITMAP_64 {0x7, 0xf0, 0x1f, 0xfc, 0x3c, 0x1e, 0x70, 0x6, 0x63, 0xb7, 0xe7, 0xf3, 0xc6, 0x63, 0xcc, 0x63, 0xcc, 0xc3, 0xcc, 0xc6, 0xcc, 0xc6, 0xef, 0xfc, 0xe7, 0xb8, 0x70, 0x0, 0x3c, 0x0, 0x1f, 0xf0, 0x7, 0xf0} + +/* A (65) */ +#define NXFONT_METRICS_65 {2, 12, 14, 1, 8, 0} +#define NXFONT_BITMAP_65 {0xf, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x19, 0x80, 0x19, 0x80, 0x39, 0xc0, 0x39, 0xc0, 0x30, 0xc0, 0x70, 0xe0, 0x7f, 0xe0, 0x7f, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70} + +/* B (66) */ +#define NXFONT_METRICS_66 {2, 11, 14, 2, 8, 0} +#define NXFONT_BITMAP_66 {0xfe, 0x0, 0xff, 0x80, 0xe3, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe3, 0x80, 0xff, 0x80, 0xff, 0xc0, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xff, 0xc0, 0xff, 0x0} + +/* C (67) */ +#define NXFONT_METRICS_67 {2, 12, 14, 1, 8, 0} +#define NXFONT_BITMAP_67 {0xf, 0x80, 0x3f, 0xe0, 0x78, 0xe0, 0x70, 0x70, 0xf0, 0x70, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xf0, 0x70, 0x70, 0x70, 0x78, 0xe0, 0x3f, 0xe0, 0xf, 0x80} + +/* D (68) */ +#define NXFONT_METRICS_68 {2, 12, 14, 1, 8, 0} +#define NXFONT_BITMAP_68 {0xff, 0x0, 0xff, 0xc0, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0xe0, 0xe1, 0xe0, 0xff, 0xc0, 0xff, 0x0} + +/* E (69) */ +#define NXFONT_METRICS_69 {2, 10, 14, 2, 8, 0} +#define NXFONT_BITMAP_69 {0xff, 0xc0, 0xff, 0xc0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0x80, 0xff, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* F (70) */ +#define NXFONT_METRICS_70 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_70 {0xff, 0xc0, 0xff, 0xc0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0x80, 0xff, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* G (71) */ +#define NXFONT_METRICS_71 {2, 12, 14, 1, 8, 0} +#define NXFONT_BITMAP_71 {0xf, 0x80, 0x3f, 0xe0, 0x78, 0xe0, 0x70, 0x70, 0xf0, 0x70, 0xe0, 0x0, 0xe0, 0x0, 0xe3, 0xf0, 0xe3, 0xf0, 0xf0, 0x70, 0x70, 0x70, 0x78, 0xf0, 0x3f, 0xf0, 0x1f, 0xb0} + +/* H (72) */ +#define NXFONT_METRICS_72 {2, 12, 14, 1, 8, 0} +#define NXFONT_BITMAP_72 {0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xff, 0xf0, 0xff, 0xf0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 3, 14, 1, 8, 0} +#define NXFONT_BITMAP_73 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* J (74) */ +#define NXFONT_METRICS_74 {2, 9, 14, 0, 8, 0} +#define NXFONT_BITMAP_74 {0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xf7, 0x80, 0x7f, 0x0, 0x3e, 0x0} + +/* K (75) */ +#define NXFONT_METRICS_75 {2, 13, 14, 1, 8, 0} +#define NXFONT_BITMAP_75 {0xe0, 0xf0, 0xe1, 0xe0, 0xe3, 0xc0, 0xe7, 0x80, 0xef, 0x0, 0xfe, 0x0, 0xfc, 0x0, 0xfe, 0x0, 0xef, 0x0, 0xe7, 0x80, 0xe3, 0xc0, 0xe1, 0xe0, 0xe0, 0xf0, 0xe0, 0x78} + +/* L (76) */ +#define NXFONT_METRICS_76 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_76 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0x80, 0xff, 0x80} + +/* M (77) */ +#define NXFONT_METRICS_77 {2, 14, 14, 1, 8, 0} +#define NXFONT_BITMAP_77 {0xe0, 0x1c, 0xe0, 0x1c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf8, 0x7c, 0xf8, 0x7c, 0xf8, 0x7c, 0xec, 0xdc, 0xec, 0xdc, 0xec, 0xdc, 0xe7, 0x9c, 0xe7, 0x9c, 0xe3, 0x1c, 0xe3, 0x1c} + +/* N (78) */ +#define NXFONT_METRICS_78 {2, 12, 14, 1, 8, 0} +#define NXFONT_BITMAP_78 {0xe0, 0x70, 0xf0, 0x70, 0xf0, 0x70, 0xf8, 0x70, 0xfc, 0x70, 0xec, 0x70, 0xee, 0x70, 0xe6, 0x70, 0xe7, 0x70, 0xe3, 0x70, 0xe1, 0xf0, 0xe1, 0xf0, 0xe0, 0xf0, 0xe0, 0x70} + +/* O (79) */ +#define NXFONT_METRICS_79 {2, 13, 14, 1, 8, 0} +#define NXFONT_BITMAP_79 {0xf, 0x80, 0x3f, 0xe0, 0x78, 0xf0, 0x70, 0x70, 0xf0, 0x78, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xf0, 0x78, 0x70, 0x70, 0x78, 0xf0, 0x3f, 0xe0, 0xf, 0x80} + +/* P (80) */ +#define NXFONT_METRICS_80 {2, 11, 14, 1, 8, 0} +#define NXFONT_BITMAP_80 {0xff, 0x0, 0xff, 0xc0, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xff, 0xc0, 0xff, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {2, 13, 15, 1, 8, 0} +#define NXFONT_BITMAP_81 {0xf, 0x80, 0x3f, 0xe0, 0x78, 0xf0, 0x70, 0x70, 0xf0, 0x78, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xf3, 0x78, 0x73, 0xf0, 0x79, 0xf0, 0x3f, 0xe0, 0xf, 0xf0, 0x0, 0x30} + +/* R (82) */ +#define NXFONT_METRICS_82 {2, 12, 14, 1, 8, 0} +#define NXFONT_BITMAP_82 {0xff, 0x0, 0xff, 0xc0, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xff, 0xc0, 0xff, 0x80, 0xe1, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0} + +/* S (83) */ +#define NXFONT_METRICS_83 {2, 11, 14, 1, 8, 0} +#define NXFONT_BITMAP_83 {0x3f, 0x80, 0x7f, 0xc0, 0xf1, 0xe0, 0xe0, 0xe0, 0xf0, 0x0, 0x7e, 0x0, 0x3f, 0x80, 0xf, 0xc0, 0x1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xe0, 0x7f, 0xc0, 0x3f, 0x80} + +/* T (84) */ +#define NXFONT_METRICS_84 {2, 11, 14, 0, 8, 0} +#define NXFONT_BITMAP_84 {0xff, 0xe0, 0xff, 0xe0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0} + +/* U (85) */ +#define NXFONT_METRICS_85 {2, 12, 14, 1, 8, 0} +#define NXFONT_BITMAP_85 {0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x7f, 0xe0, 0x1f, 0x80} + +/* V (86) */ +#define NXFONT_METRICS_86 {2, 13, 14, 0, 8, 0} +#define NXFONT_BITMAP_86 {0xe0, 0x38, 0xe0, 0x38, 0x70, 0x70, 0x70, 0x70, 0x30, 0x60, 0x38, 0xe0, 0x38, 0xe0, 0x1d, 0xc0, 0x1d, 0xc0, 0xd, 0x80, 0xf, 0x80, 0xf, 0x80, 0x7, 0x0, 0x7, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {2, 15, 14, 1, 8, 0} +#define NXFONT_BITMAP_87 {0xe3, 0x8e, 0xe3, 0x8e, 0xe3, 0x8e, 0xe3, 0x8e, 0x73, 0x9c, 0x73, 0x9c, 0x73, 0x9c, 0x76, 0xdc, 0x36, 0xd8, 0x36, 0xd8, 0x3e, 0xf8, 0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x70} + +/* X (88) */ +#define NXFONT_METRICS_88 {2, 12, 14, 0, 8, 0} +#define NXFONT_BITMAP_88 {0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x79, 0xe0, 0x19, 0x80, 0x1f, 0x80, 0xf, 0x0, 0x1f, 0x80, 0x19, 0x80, 0x39, 0xc0, 0x70, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70} + +/* Y (89) */ +#define NXFONT_METRICS_89 {2, 13, 14, 0, 8, 0} +#define NXFONT_BITMAP_89 {0xe0, 0x38, 0xe0, 0x38, 0x70, 0x70, 0x38, 0xe0, 0x38, 0xe0, 0x1d, 0xc0, 0x1d, 0xc0, 0xf, 0x80, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_90 {0xff, 0xc0, 0xff, 0xc0, 0x1, 0xc0, 0x3, 0x80, 0x7, 0x0, 0x7, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x38, 0x0, 0x70, 0x0, 0xe0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 5, 18, 1, 8, 0} +#define NXFONT_BITMAP_91 {0xf8, 0xf8, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf8, 0xf8} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {1, 5, 14, 0, 8, 0} +#define NXFONT_BITMAP_92 {0xc0, 0xc0, 0xc0, 0xe0, 0x60, 0x60, 0x60, 0x70, 0x30, 0x30, 0x38, 0x18, 0x18, 0x18} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 5, 18, 0, 8, 0} +#define NXFONT_BITMAP_93 {0xf8, 0xf8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xf8, 0xf8} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {2, 10, 7, 0, 9, 0} +#define NXFONT_BITMAP_94 {0xc, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x73, 0x80, 0x61, 0x80, 0xe1, 0xc0} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {2, 10, 2, 0, 24, 0} +#define NXFONT_BITMAP_95 {0xff, 0xc0, 0xff, 0xc0} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 5, 3, 0, 8, 0} +#define NXFONT_BITMAP_96 {0xe0, 0x70, 0x38} + +/* a (97) */ +#define NXFONT_METRICS_97 {2, 10, 10, 1, 12, 0} +#define NXFONT_BITMAP_97 {0x3e, 0x0, 0x7f, 0x0, 0x63, 0x80, 0x7, 0x80, 0x3f, 0x80, 0x7b, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xfb, 0x80, 0x7b, 0xc0} + +/* b (98) */ +#define NXFONT_METRICS_98 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_98 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xef, 0x0, 0xff, 0x80, 0xf3, 0x80, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xf3, 0x80, 0xff, 0x80, 0xef, 0x0} + +/* c (99) */ +#define NXFONT_METRICS_99 {2, 9, 10, 1, 12, 0} +#define NXFONT_BITMAP_99 {0x1e, 0x0, 0x7f, 0x80, 0x73, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* d (100) */ +#define NXFONT_METRICS_100 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_100 {0x1, 0xc0, 0x1, 0xc0, 0x1, 0xc0, 0x1, 0xc0, 0x3d, 0xc0, 0x7f, 0xc0, 0x73, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0x73, 0xc0, 0x7f, 0xc0, 0x3d, 0xc0} + +/* e (101) */ +#define NXFONT_METRICS_101 {2, 9, 10, 1, 12, 0} +#define NXFONT_BITMAP_101 {0x1e, 0x0, 0x7f, 0x0, 0x73, 0x80, 0xe1, 0x80, 0xff, 0x80, 0xff, 0x80, 0xe0, 0x0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* f (102) */ +#define NXFONT_METRICS_102 {1, 7, 14, 0, 8, 0} +#define NXFONT_BITMAP_102 {0x1e, 0x3e, 0x38, 0x38, 0xfe, 0xfe, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38} + +/* g (103) */ +#define NXFONT_METRICS_103 {2, 10, 14, 1, 12, 0} +#define NXFONT_BITMAP_103 {0x3d, 0xc0, 0x7f, 0xc0, 0x73, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0x73, 0xc0, 0x7f, 0xc0, 0x3d, 0xc0, 0x1, 0xc0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* h (104) */ +#define NXFONT_METRICS_104 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_104 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xef, 0x0, 0xff, 0x80, 0xf3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 3, 14, 1, 8, 0} +#define NXFONT_BITMAP_105 {0xe0, 0xe0, 0xe0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* j (106) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_106 {1, 5, 18, 0, 8, 0} +#define NXFONT_BITMAP_106 {0x38, 0x38, 0x38, 0x0, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xf8, 0xf0} + +/* k (107) */ +#define NXFONT_METRICS_107 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_107 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe7, 0x0, 0xee, 0x0, 0xfc, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xfc, 0x0, 0xee, 0x0, 0xe7, 0x0, 0xe7, 0x80, 0xe3, 0x80} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 3, 14, 1, 8, 0} +#define NXFONT_BITMAP_108 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* m (109) */ +#define NXFONT_METRICS_109 {2, 15, 10, 1, 12, 0} +#define NXFONT_BITMAP_109 {0xef, 0x3c, 0xff, 0xfe, 0xf3, 0xce, 0xe3, 0x8e, 0xe3, 0x8e, 0xe3, 0x8e, 0xe3, 0x8e, 0xe3, 0x8e, 0xe3, 0x8e, 0xe3, 0x8e} + +/* n (110) */ +#define NXFONT_METRICS_110 {2, 9, 10, 1, 12, 0} +#define NXFONT_BITMAP_110 {0xef, 0x0, 0xff, 0x80, 0xf3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80} + +/* o (111) */ +#define NXFONT_METRICS_111 {2, 10, 10, 1, 12, 0} +#define NXFONT_BITMAP_111 {0x1e, 0x0, 0x7f, 0x80, 0x73, 0x80, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* p (112) */ +#define NXFONT_METRICS_112 {2, 10, 14, 1, 12, 0} +#define NXFONT_BITMAP_112 {0xef, 0x0, 0xff, 0x80, 0xf3, 0x80, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xf3, 0x80, 0xff, 0x80, 0xef, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* q (113) */ +#define NXFONT_METRICS_113 {2, 10, 14, 1, 12, 0} +#define NXFONT_BITMAP_113 {0x3d, 0xc0, 0x7f, 0xc0, 0x73, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0x73, 0xc0, 0x7f, 0xc0, 0x3d, 0xc0, 0x1, 0xc0, 0x1, 0xc0, 0x1, 0xc0, 0x1, 0xc0} + +/* r (114) */ +#define NXFONT_METRICS_114 {1, 6, 10, 1, 12, 0} +#define NXFONT_BITMAP_114 {0xec, 0xfc, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* s (115) */ +#define NXFONT_METRICS_115 {2, 9, 10, 1, 12, 0} +#define NXFONT_BITMAP_115 {0x3f, 0x0, 0x7f, 0x80, 0xe3, 0x80, 0xe0, 0x0, 0xff, 0x0, 0x3f, 0x80, 0x3, 0x80, 0xe3, 0x80, 0xff, 0x0, 0x7e, 0x0} + +/* t (116) */ +#define NXFONT_METRICS_116 {1, 6, 13, 0, 9, 0} +#define NXFONT_BITMAP_116 {0x70, 0x70, 0x70, 0xfc, 0xfc, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x7c, 0x3c} + +/* u (117) */ +#define NXFONT_METRICS_117 {2, 9, 10, 1, 12, 0} +#define NXFONT_BITMAP_117 {0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0x80, 0x7b, 0x80} + +/* v (118) */ +#define NXFONT_METRICS_118 {2, 9, 10, 0, 12, 0} +#define NXFONT_BITMAP_118 {0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x77, 0x0, 0x77, 0x0, 0x77, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x1c, 0x0, 0x1c, 0x0} + +/* w (119) */ +#define NXFONT_METRICS_119 {2, 15, 10, 0, 12, 0} +#define NXFONT_BITMAP_119 {0xe3, 0x8e, 0xe3, 0x8e, 0xe3, 0x8e, 0x73, 0x9c, 0x77, 0xdc, 0x76, 0xdc, 0x3e, 0xf8, 0x3c, 0x78, 0x1c, 0x70, 0x1c, 0x70} + +/* x (120) */ +#define NXFONT_METRICS_120 {2, 9, 10, 1, 12, 0} +#define NXFONT_BITMAP_120 {0xe3, 0x80, 0xe3, 0x80, 0x77, 0x0, 0x3e, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0x77, 0x0, 0x77, 0x0, 0xe3, 0x80, 0xe3, 0x80} + +/* y (121) */ +#define NXFONT_METRICS_121 {2, 9, 14, 1, 12, 0} +#define NXFONT_BITMAP_121 {0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x77, 0x0, 0x77, 0x0, 0x77, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x18, 0x0, 0x78, 0x0, 0x70, 0x0} + +/* z (122) */ +#define NXFONT_METRICS_122 {1, 8, 10, 1, 12, 0} +#define NXFONT_BITMAP_122 {0xff, 0xff, 0x7, 0xe, 0x1c, 0x38, 0x70, 0xe0, 0xff, 0xff} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {1, 7, 18, 1, 8, 0} +#define NXFONT_BITMAP_123 {0xe, 0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x70, 0xe0, 0x70, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x1c, 0xe} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 2, 18, 1, 8, 0} +#define NXFONT_BITMAP_124 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 7, 18, 0, 8, 0} +#define NXFONT_BITMAP_125 {0xe0, 0x70, 0x38, 0x38, 0x38, 0x38, 0x38, 0x1c, 0xe, 0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x70, 0xe0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {2, 9, 3, 1, 15, 0} +#define NXFONT_BITMAP_126 {0x79, 0x80, 0xff, 0x80, 0xcf, 0x0} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 3, 14, 2, 12, 0} +#define NXFONT_BITMAP_161 {0xe0, 0xe0, 0xe0, 0x0, 0x60, 0x60, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* cent (162) */ +#define NXFONT_METRICS_162 {1, 8, 14, 1, 10, 0} +#define NXFONT_BITMAP_162 {0x2, 0x2, 0x3e, 0x7f, 0xe7, 0xc8, 0xc8, 0xd0, 0xd0, 0xe3, 0x7f, 0x7e, 0x40, 0x40} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {2, 10, 13, 0, 9, 0} +#define NXFONT_BITMAP_163 {0x1f, 0x0, 0x3f, 0xc0, 0x71, 0xc0, 0x70, 0x0, 0x70, 0x0, 0x38, 0x0, 0x7f, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x70, 0xc0, 0xff, 0xc0, 0xef, 0x80} + +/* currency (164) */ +#define NXFONT_METRICS_164 {2, 9, 8, 1, 12, 0} +#define NXFONT_BITMAP_164 {0xc1, 0x80, 0xff, 0x80, 0x77, 0x0, 0x63, 0x0, 0x63, 0x0, 0x77, 0x0, 0xff, 0x80, 0xc1, 0x80} + +/* yen (165) */ +#define NXFONT_METRICS_165 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_165 {0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x77, 0x0, 0x77, 0x0, 0x3e, 0x0, 0xff, 0x80, 0x1c, 0x0, 0xff, 0x80, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 2, 18, 1, 8, 0} +#define NXFONT_BITMAP_166 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* section (167) */ +#define NXFONT_METRICS_167 {2, 9, 18, 0, 8, 0} +#define NXFONT_BITMAP_167 {0x3e, 0x0, 0x7f, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0xf0, 0x0, 0x7c, 0x0, 0xfe, 0x0, 0xc7, 0x0, 0xc3, 0x80, 0xe1, 0x80, 0x71, 0x80, 0x3f, 0x80, 0xf, 0x0, 0x7, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x7f, 0x0, 0x3e, 0x0} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 5, 2, 1, 8, 0} +#define NXFONT_BITMAP_168 {0xd8, 0xd8} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {2, 14, 14, 1, 8, 0} +#define NXFONT_BITMAP_169 {0xf, 0xc0, 0x38, 0x70, 0x60, 0x18, 0xc7, 0x8c, 0xcf, 0xcc, 0x98, 0xc4, 0x98, 0x4, 0x98, 0x4, 0x98, 0x44, 0xcf, 0xcc, 0xc7, 0x8c, 0x60, 0x18, 0x38, 0x70, 0xf, 0xc0} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {1, 6, 9, 1, 8, 0} +#define NXFONT_BITMAP_170 {0x78, 0x8c, 0x7c, 0xcc, 0xcc, 0x74, 0x0, 0xfc, 0xfc} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {2, 10, 8, 0, 13, 0} +#define NXFONT_BITMAP_171 {0x1d, 0xc0, 0x3b, 0x80, 0x77, 0x0, 0xee, 0x0, 0xee, 0x0, 0x77, 0x0, 0x3b, 0x80, 0x1d, 0xc0} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {2, 9, 5, 1, 14, 0} +#define NXFONT_BITMAP_172 {0xff, 0x80, 0xff, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 5, 3, 0, 15, 0} +#define NXFONT_BITMAP_173 {0xf8, 0xf8, 0xf8} + +/* registered (174) */ +#define NXFONT_METRICS_174 {2, 13, 14, 1, 8, 0} +#define NXFONT_BITMAP_174 {0xf, 0x80, 0x30, 0x60, 0x60, 0x10, 0x5f, 0x90, 0x99, 0xc8, 0x98, 0xc8, 0x99, 0xc8, 0x9f, 0x8, 0x99, 0x88, 0x99, 0x88, 0x58, 0xd0, 0x60, 0x30, 0x38, 0xe0, 0xf, 0x80} + +/* macron (175) */ +#define NXFONT_METRICS_175 {1, 5, 2, 1, 8, 0} +#define NXFONT_BITMAP_175 {0xf8, 0xf8} + +/* degree (176) */ +#define NXFONT_METRICS_176 {1, 6, 6, 0, 9, 0} +#define NXFONT_BITMAP_176 {0x78, 0xfc, 0xcc, 0xcc, 0xfc, 0x78} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {2, 9, 9, 1, 13, 0} +#define NXFONT_BITMAP_177 {0x1c, 0x0, 0x1c, 0x0, 0xff, 0x80, 0xff, 0x80, 0x1c, 0x0, 0x1c, 0x0, 0x0, 0x0, 0xff, 0x80, 0xff, 0x80} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {1, 6, 8, 0, 9, 0} +#define NXFONT_BITMAP_178 {0x78, 0xfc, 0xcc, 0x1c, 0x78, 0xe0, 0xfc, 0xfc} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {1, 6, 8, 0, 9, 0} +#define NXFONT_BITMAP_179 {0x78, 0xfc, 0xcc, 0x38, 0x3c, 0xcc, 0xfc, 0x78} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 5, 3, 0, 8, 0} +#define NXFONT_BITMAP_180 {0x38, 0x70, 0xe0} + +/* mu (181) */ +#define NXFONT_METRICS_181 {2, 9, 14, 1, 12, 0} +#define NXFONT_BITMAP_181 {0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0x80, 0xfb, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {2, 9, 18, 0, 8, 0} +#define NXFONT_BITMAP_182 {0x3f, 0x80, 0x7b, 0x0, 0xfb, 0x0, 0xfb, 0x0, 0xfb, 0x0, 0xfb, 0x0, 0xfb, 0x0, 0x7b, 0x0, 0x3b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 2, 2, 1, 14, 0} +#define NXFONT_BITMAP_183 {0xc0, 0xc0} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 5, 5, 1, 22, 0} +#define NXFONT_BITMAP_184 {0x60, 0x70, 0x18, 0xf8, 0xf0} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 4, 8, 0, 9, 0} +#define NXFONT_BITMAP_185 {0x30, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {1, 6, 9, 1, 8, 0} +#define NXFONT_BITMAP_186 {0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x0, 0xfc, 0xfc} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {2, 10, 8, 0, 13, 0} +#define NXFONT_BITMAP_187 {0xee, 0x0, 0x77, 0x0, 0x3b, 0x80, 0x1d, 0xc0, 0x1d, 0xc0, 0x3b, 0x80, 0x77, 0x0, 0xee, 0x0} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {2, 14, 13, 0, 9, 0} +#define NXFONT_BITMAP_188 {0x30, 0x60, 0xf0, 0x60, 0xf0, 0xc0, 0x30, 0xc0, 0x31, 0x80, 0x31, 0x98, 0x33, 0x38, 0x36, 0x38, 0x6, 0x78, 0xc, 0xd8, 0xc, 0xfc, 0x18, 0x18, 0x18, 0x18} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {2, 15, 13, 0, 9, 0} +#define NXFONT_BITMAP_189 {0x30, 0x60, 0xf0, 0x60, 0xf0, 0xc0, 0x30, 0xc0, 0x31, 0x80, 0x31, 0xbc, 0x33, 0x7e, 0x36, 0x66, 0x6, 0xe, 0xc, 0x3c, 0xc, 0x70, 0x18, 0x7e, 0x18, 0x7e} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {2, 14, 13, 0, 9, 0} +#define NXFONT_BITMAP_190 {0x78, 0x30, 0xfc, 0x30, 0xcc, 0x60, 0x38, 0x60, 0x3c, 0xc0, 0xcc, 0xd8, 0xfd, 0xb8, 0x7b, 0x38, 0x3, 0x78, 0x6, 0xd8, 0x6, 0xfc, 0xc, 0x18, 0xc, 0x18} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {1, 8, 14, 1, 12, 0} +#define NXFONT_BITMAP_191 {0x1c, 0x1c, 0x1c, 0x0, 0x1c, 0x1c, 0x1c, 0x38, 0x78, 0x70, 0xe7, 0xe7, 0xff, 0x7e} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {2, 12, 18, 1, 4, 0} +#define NXFONT_BITMAP_192 {0x38, 0x0, 0x1c, 0x0, 0x6, 0x0, 0x0, 0x0, 0xf, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x19, 0x80, 0x19, 0x80, 0x39, 0xc0, 0x39, 0xc0, 0x30, 0xc0, 0x70, 0xe0, 0x7f, 0xe0, 0x7f, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {2, 12, 18, 1, 4, 0} +#define NXFONT_BITMAP_193 {0x1, 0xc0, 0x3, 0x80, 0x6, 0x0, 0x0, 0x0, 0xf, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x19, 0x80, 0x19, 0x80, 0x39, 0xc0, 0x39, 0xc0, 0x30, 0xc0, 0x70, 0xe0, 0x7f, 0xe0, 0x7f, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {2, 12, 18, 1, 4, 0} +#define NXFONT_BITMAP_194 {0x7, 0x0, 0xf, 0x80, 0x1d, 0xc0, 0x0, 0x0, 0xf, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x19, 0x80, 0x19, 0x80, 0x39, 0xc0, 0x39, 0xc0, 0x30, 0xc0, 0x70, 0xe0, 0x7f, 0xe0, 0x7f, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {2, 12, 18, 1, 4, 0} +#define NXFONT_BITMAP_195 {0xe, 0x20, 0x1f, 0xc0, 0x23, 0x80, 0x0, 0x0, 0xf, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x19, 0x80, 0x19, 0x80, 0x39, 0xc0, 0x39, 0xc0, 0x30, 0xc0, 0x70, 0xe0, 0x7f, 0xe0, 0x7f, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {2, 12, 18, 1, 4, 0} +#define NXFONT_BITMAP_196 {0x19, 0x80, 0x19, 0x80, 0x19, 0x80, 0x0, 0x0, 0xf, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x19, 0x80, 0x19, 0x80, 0x39, 0xc0, 0x39, 0xc0, 0x30, 0xc0, 0x70, 0xe0, 0x7f, 0xe0, 0x7f, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {2, 12, 18, 1, 4, 0} +#define NXFONT_BITMAP_197 {0xf, 0x0, 0x19, 0x80, 0x19, 0x80, 0xf, 0x0, 0xf, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x19, 0x80, 0x19, 0x80, 0x39, 0xc0, 0x39, 0xc0, 0x30, 0xc0, 0x70, 0xe0, 0x7f, 0xe0, 0x7f, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70} + +/* AE (198) */ +#define NXFONT_METRICS_198 {2, 16, 14, 1, 8, 0} +#define NXFONT_BITMAP_198 {0xf, 0xff, 0xf, 0xff, 0x1f, 0x80, 0x1b, 0x80, 0x3b, 0x80, 0x3b, 0x80, 0x33, 0xfe, 0x73, 0xfe, 0x73, 0x80, 0x7f, 0x80, 0xff, 0x80, 0xe3, 0x80, 0xe3, 0xff, 0xe3, 0xff} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {2, 12, 19, 1, 8, 0} +#define NXFONT_BITMAP_199 {0xf, 0x80, 0x3f, 0xe0, 0x78, 0xe0, 0x70, 0x70, 0xf0, 0x70, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xf0, 0x70, 0x70, 0x70, 0x78, 0xe0, 0x3f, 0xe0, 0xf, 0x80, 0xc, 0x0, 0xe, 0x0, 0x3, 0x0, 0x1f, 0x0, 0x1e, 0x0} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {2, 10, 18, 2, 4, 0} +#define NXFONT_BITMAP_200 {0x38, 0x0, 0x1c, 0x0, 0x6, 0x0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0x80, 0xff, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {2, 10, 18, 2, 4, 0} +#define NXFONT_BITMAP_201 {0x3, 0x80, 0x7, 0x0, 0xc, 0x0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0x80, 0xff, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {2, 10, 18, 2, 4, 0} +#define NXFONT_BITMAP_202 {0xe, 0x0, 0x1f, 0x0, 0x3b, 0x80, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0x80, 0xff, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {2, 10, 18, 2, 4, 0} +#define NXFONT_BITMAP_203 {0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0x80, 0xff, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* Igrave (204) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_204 {1, 5, 18, 0, 4, 0} +#define NXFONT_BITMAP_204 {0xe0, 0x70, 0x18, 0x0, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 5, 18, 1, 4, 0} +#define NXFONT_BITMAP_205 {0x38, 0x70, 0xc0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* Icircumflex (206) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_206 {1, 7, 18, 0, 4, 0} +#define NXFONT_BITMAP_206 {0x38, 0x7c, 0xee, 0x0, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {1, 6, 18, 0, 4, 0} +#define NXFONT_BITMAP_207 {0xcc, 0xcc, 0xcc, 0x0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70} + +/* Eth (208) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_208 {2, 14, 14, 0, 8, 0} +#define NXFONT_BITMAP_208 {0x3f, 0xc0, 0x3f, 0xf0, 0x38, 0x78, 0x38, 0x38, 0x38, 0x1c, 0x38, 0x1c, 0xff, 0x1c, 0xff, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x38, 0x38, 0x78, 0x3f, 0xf0, 0x3f, 0xc0} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {2, 12, 18, 1, 4, 0} +#define NXFONT_BITMAP_209 {0xe, 0x20, 0x1f, 0xc0, 0x23, 0x80, 0x0, 0x0, 0xe0, 0x70, 0xf0, 0x70, 0xf0, 0x70, 0xf8, 0x70, 0xfc, 0x70, 0xec, 0x70, 0xee, 0x70, 0xe6, 0x70, 0xe7, 0x70, 0xe3, 0x70, 0xe1, 0xf0, 0xe1, 0xf0, 0xe0, 0xf0, 0xe0, 0x70} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {2, 13, 18, 1, 4, 0} +#define NXFONT_BITMAP_210 {0x1c, 0x0, 0xe, 0x0, 0x3, 0x0, 0x0, 0x0, 0xf, 0x80, 0x3f, 0xe0, 0x78, 0xf0, 0x70, 0x70, 0xf0, 0x78, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xf0, 0x78, 0x70, 0x70, 0x78, 0xf0, 0x3f, 0xe0, 0xf, 0x80} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {2, 13, 18, 1, 4, 0} +#define NXFONT_BITMAP_211 {0x1, 0xc0, 0x3, 0x80, 0x6, 0x0, 0x0, 0x0, 0xf, 0x80, 0x3f, 0xe0, 0x78, 0xf0, 0x70, 0x70, 0xf0, 0x78, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xf0, 0x78, 0x70, 0x70, 0x78, 0xf0, 0x3f, 0xe0, 0xf, 0x80} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {2, 13, 18, 1, 4, 0} +#define NXFONT_BITMAP_212 {0x7, 0x0, 0xf, 0x80, 0x1d, 0xc0, 0x0, 0x0, 0xf, 0x80, 0x3f, 0xe0, 0x78, 0xf0, 0x70, 0x70, 0xf0, 0x78, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xf0, 0x78, 0x70, 0x70, 0x78, 0xf0, 0x3f, 0xe0, 0xf, 0x80} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {2, 13, 18, 1, 4, 0} +#define NXFONT_BITMAP_213 {0x7, 0x10, 0xf, 0xe0, 0x11, 0xc0, 0x0, 0x0, 0xf, 0x80, 0x3f, 0xe0, 0x78, 0xf0, 0x70, 0x70, 0xf0, 0x78, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xf0, 0x78, 0x70, 0x70, 0x78, 0xf0, 0x3f, 0xe0, 0xf, 0x80} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {2, 13, 18, 1, 4, 0} +#define NXFONT_BITMAP_214 {0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0x0, 0x0, 0xf, 0x80, 0x3f, 0xe0, 0x78, 0xf0, 0x70, 0x70, 0xf0, 0x78, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xf0, 0x78, 0x70, 0x70, 0x78, 0xf0, 0x3f, 0xe0, 0xf, 0x80} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {2, 10, 8, 0, 13, 0} +#define NXFONT_BITMAP_215 {0xe1, 0xc0, 0x73, 0x80, 0x3f, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x3f, 0x0, 0x73, 0x80, 0xe1, 0xc0} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {2, 15, 14, 0, 8, 0} +#define NXFONT_BITMAP_216 {0x7, 0xc6, 0x1f, 0xfc, 0x3c, 0x38, 0x38, 0x78, 0x78, 0xdc, 0x71, 0x9c, 0x71, 0x1c, 0x73, 0x1c, 0x76, 0x1c, 0x7c, 0x3c, 0x38, 0x38, 0x3c, 0x78, 0x7f, 0xf0, 0xc7, 0xc0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {2, 12, 18, 1, 4, 0} +#define NXFONT_BITMAP_217 {0x1c, 0x0, 0xe, 0x0, 0x3, 0x0, 0x0, 0x0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x7f, 0xe0, 0x1f, 0x80} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {2, 12, 18, 1, 4, 0} +#define NXFONT_BITMAP_218 {0x1, 0xc0, 0x3, 0x80, 0x6, 0x0, 0x0, 0x0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x7f, 0xe0, 0x1f, 0x80} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {2, 12, 18, 1, 4, 0} +#define NXFONT_BITMAP_219 {0x7, 0x0, 0xf, 0x80, 0x1d, 0xc0, 0x0, 0x0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x7f, 0xe0, 0x1f, 0x80} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {2, 12, 18, 1, 4, 0} +#define NXFONT_BITMAP_220 {0x19, 0x80, 0x19, 0x80, 0x19, 0x80, 0x0, 0x0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x7f, 0xe0, 0x1f, 0x80} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {2, 13, 18, 0, 4, 0} +#define NXFONT_BITMAP_221 {0x1, 0xc0, 0x3, 0x80, 0x6, 0x0, 0x0, 0x0, 0xe0, 0x38, 0xe0, 0x38, 0x70, 0x70, 0x38, 0xe0, 0x38, 0xe0, 0x1d, 0xc0, 0x1d, 0xc0, 0xf, 0x80, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {2, 11, 14, 1, 8, 0} +#define NXFONT_BITMAP_222 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0x0, 0xff, 0xc0, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xff, 0xc0, 0xff, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {1, 8, 14, 1, 8, 0} +#define NXFONT_BITMAP_223 {0x3c, 0x7e, 0xe7, 0xe7, 0xe7, 0xe7, 0xee, 0xee, 0xe7, 0xe7, 0xe7, 0xe7, 0xef, 0xee} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_224 {0x70, 0x0, 0x38, 0x0, 0xc, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0x73, 0x80, 0x7, 0x80, 0x3f, 0x80, 0x7b, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xfb, 0x80, 0x7b, 0xc0} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_225 {0x3, 0x80, 0x7, 0x0, 0xc, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0x73, 0x80, 0x7, 0x80, 0x3f, 0x80, 0x7b, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xfb, 0x80, 0x7b, 0xc0} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_226 {0x1c, 0x0, 0x3e, 0x0, 0x77, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0x73, 0x80, 0x7, 0x80, 0x3f, 0x80, 0x7b, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xfb, 0x80, 0x7b, 0xc0} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_227 {0x3b, 0x0, 0x7f, 0x0, 0x6e, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0x73, 0x80, 0x7, 0x80, 0x3f, 0x80, 0x7b, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xfb, 0x80, 0x7b, 0xc0} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_228 {0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0x73, 0x80, 0x7, 0x80, 0x3f, 0x80, 0x7b, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xfb, 0x80, 0x7b, 0xc0} + +/* aring (229) */ +#define NXFONT_METRICS_229 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_229 {0x3c, 0x0, 0x66, 0x0, 0x66, 0x0, 0x3c, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0x73, 0x80, 0x7, 0x80, 0x3f, 0x80, 0x7b, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xfb, 0x80, 0x7b, 0xc0} + +/* ae (230) */ +#define NXFONT_METRICS_230 {2, 14, 10, 1, 12, 0} +#define NXFONT_BITMAP_230 {0x3d, 0xf0, 0x7f, 0xf8, 0x67, 0x1c, 0xf, 0x1c, 0x3f, 0xfc, 0x77, 0x0, 0xe7, 0x0, 0xef, 0x9c, 0xff, 0xfc, 0x79, 0xf0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {2, 9, 15, 1, 12, 0} +#define NXFONT_BITMAP_231 {0x1e, 0x0, 0x7f, 0x80, 0x73, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0, 0x18, 0x0, 0x1c, 0x0, 0x6, 0x0, 0x3e, 0x0, 0x3c, 0x0} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_232 {0x70, 0x0, 0x38, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x7f, 0x0, 0x73, 0x80, 0xe1, 0x80, 0xff, 0x80, 0xff, 0x80, 0xe0, 0x0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_233 {0x3, 0x80, 0x7, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x7f, 0x0, 0x73, 0x80, 0xe1, 0x80, 0xff, 0x80, 0xff, 0x80, 0xe0, 0x0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_234 {0x1c, 0x0, 0x3e, 0x0, 0x77, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x7f, 0x0, 0x73, 0x80, 0xe1, 0x80, 0xff, 0x80, 0xff, 0x80, 0xe0, 0x0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_235 {0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x7f, 0x0, 0x73, 0x80, 0xe1, 0x80, 0xff, 0x80, 0xff, 0x80, 0xe0, 0x0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* igrave (236) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_236 {1, 5, 14, 0, 8, 0} +#define NXFONT_BITMAP_236 {0xe0, 0x70, 0x18, 0x0, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 5, 14, 1, 8, 0} +#define NXFONT_BITMAP_237 {0x38, 0x70, 0xc0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* icircumflex (238) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_238 {1, 7, 14, 0, 8, 0} +#define NXFONT_BITMAP_238 {0x38, 0x7c, 0xee, 0x0, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 5, 14, 0, 8, 0} +#define NXFONT_BITMAP_239 {0xd8, 0xd8, 0xd8, 0x0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70} + +/* eth (240) */ +#define NXFONT_METRICS_240 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_240 {0x60, 0x0, 0x37, 0x0, 0x3c, 0x0, 0x66, 0x0, 0x1f, 0x0, 0x7f, 0x80, 0x73, 0x80, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_241 {0x3b, 0x0, 0x7f, 0x0, 0x6e, 0x0, 0x0, 0x0, 0xef, 0x0, 0xff, 0x80, 0xf3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_242 {0x70, 0x0, 0x38, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x7f, 0x80, 0x73, 0x80, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_243 {0x3, 0x80, 0x7, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x7f, 0x80, 0x73, 0x80, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_244 {0x1c, 0x0, 0x3e, 0x0, 0x77, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x7f, 0x80, 0x73, 0x80, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_245 {0x3b, 0x0, 0x7f, 0x0, 0x6e, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x7f, 0x80, 0x73, 0x80, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {2, 10, 14, 1, 8, 0} +#define NXFONT_BITMAP_246 {0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x7f, 0x80, 0x73, 0x80, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0x73, 0x80, 0x7f, 0x80, 0x1e, 0x0} + +/* divide (247) */ +#define NXFONT_METRICS_247 {2, 9, 8, 1, 13, 0} +#define NXFONT_BITMAP_247 {0x1c, 0x0, 0x1c, 0x0, 0x0, 0x0, 0xff, 0x80, 0xff, 0x80, 0x0, 0x0, 0x1c, 0x0, 0x1c, 0x0} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {2, 12, 10, 0, 12, 0} +#define NXFONT_BITMAP_248 {0xf, 0x30, 0x3f, 0xe0, 0x39, 0xc0, 0x73, 0xe0, 0x77, 0xe0, 0x7e, 0xe0, 0x7c, 0xe0, 0x39, 0xc0, 0x7f, 0xc0, 0xcf, 0x0} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_249 {0x70, 0x0, 0x38, 0x0, 0xc, 0x0, 0x0, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0x80, 0x7b, 0x80} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_250 {0x3, 0x80, 0x7, 0x0, 0xc, 0x0, 0x0, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0x80, 0x7b, 0x80} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_251 {0x1c, 0x0, 0x3e, 0x0, 0x77, 0x0, 0x0, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0x80, 0x7b, 0x80} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {2, 9, 14, 1, 8, 0} +#define NXFONT_BITMAP_252 {0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0x80, 0x7b, 0x80} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {2, 9, 18, 1, 8, 0} +#define NXFONT_BITMAP_253 {0x7, 0x0, 0xe, 0x0, 0x18, 0x0, 0x0, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x77, 0x0, 0x77, 0x0, 0x77, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x18, 0x0, 0x78, 0x0, 0x70, 0x0} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {2, 10, 18, 1, 8, 0} +#define NXFONT_BITMAP_254 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xef, 0x0, 0xff, 0x80, 0xf3, 0x80, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xf3, 0x80, 0xff, 0x80, 0xef, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {2, 9, 18, 1, 8, 0} +#define NXFONT_BITMAP_255 {0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x77, 0x0, 0x77, 0x0, 0x77, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x18, 0x0, 0x78, 0x0, 0x70, 0x0} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SANS22X29B_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_sans23x27.h b/nuttx/graphics/nxfonts/nxfonts_sans23x27.h new file mode 100644 index 0000000000..5feb39d9c9 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_sans23x27.h @@ -0,0 +1,859 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_sans23x27.h + * + * Copyright (C) 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SANS23X27_H +#define __GRAPHICS_NXFONTS_NXFONTS_SANS23X27_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SANS23X27 + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 23 +#define NXFONT_MAXWIDTH 27 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 4 + +/* A sans serif font kind of like Lucida */ + +/* Space (32) */ + +/* Exclamation point (33) */ +#define NXFONT_METRICS_33 {1, 1, 9, 2, 5, 0} +#define NXFONT_BITMAP_33 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80} + +/* Double quote (34) */ +#define NXFONT_METRICS_34 {1, 3, 3, 1, 4, 0} +#define NXFONT_BITMAP_34 {0xa0, 0xa0, 0xa0} + +/* Number sign (35) */ +#define NXFONT_METRICS_35 {1, 7, 9, 1, 5, 0} +#define NXFONT_BITMAP_35 {0x24, 0x24, 0x24, 0xfe, 0x28, 0xfe, 0x48, 0x48, 0x48} + +/* Dollar sign (36) */ +#define NXFONT_METRICS_36 {1, 6, 11, 1, 4, 0} +#define NXFONT_BITMAP_36 {0x10, 0x78, 0x94, 0x90, 0x50, 0x30, 0x28, 0x24, 0xa4, 0x78, 0x20} + +/* Percent sign (37) */ +#define NXFONT_METRICS_37 {1, 7, 9, 1, 5, 0} +#define NXFONT_BITMAP_37 {0x60, 0x92, 0x94, 0x68, 0x10, 0x2c, 0x52, 0x92, 0x0c} + +/* Ampersand (38) */ +#define NXFONT_METRICS_38 {1, 7, 9, 1, 5, 0} +#define NXFONT_BITMAP_38 {0x30, 0x48, 0x48, 0x30, 0x66, 0x94, 0x88, 0x88, 0x76} + +/* Single quote (39) */ +#define NXFONT_METRICS_39 {1, 1, 3, 1, 4, 0} +#define NXFONT_BITMAP_39 {0x80, 0x80, 0x80} + +/* Left parenthis (40) */ +#define NXFONT_METRICS_40 {1, 3, 10, 1, 5, 0} +#define NXFONT_BITMAP_40 {0x20, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x20} + +/* Right parenthis (41) */ +#define NXFONT_METRICS_41 {1, 3, 11, 0, 5, 0} +#define NXFONT_BITMAP_41 {0x80, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x80} + +/* Asterisk (42) */ +#define NXFONT_METRICS_42 {1, 5, 5, 1, 5, 0} +#define NXFONT_BITMAP_42 {0x20, 0xa8, 0x50, 0xa8, 0x20} + +/* Plus (43) */ +#define NXFONT_METRICS_43 {1, 7, 7, 1, 7, 0} +#define NXFONT_BITMAP_43 {0x10, 0x10, 0x10, 0xfe, 0x10, 0x10, 0x10} + +/* Comma (44) */ +#define NXFONT_METRICS_44 {1, 2, 4, 1, 12, 0} +#define NXFONT_BITMAP_44 {0x40, 0x40, 0x80, 0x80} + +/* Hyphen (45) */ +#define NXFONT_METRICS_45 {1, 5, 1, 1, 10, 0} +#define NXFONT_BITMAP_45 {0xf8} + +/* Period (46) */ +#define NXFONT_METRICS_46 {1, 1, 2, 2, 12, 0} +#define NXFONT_BITMAP_46 {0x80, 0x80} + +/* Forward slash (47) */ +#define NXFONT_METRICS_47 {1, 4, 11, 1, 5, 0} +#define NXFONT_BITMAP_47 {0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x80, 0x80} + +/* '0' (48) */ +#define NXFONT_METRICS_48 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_48 {0x30, 0x48, 0x84, 0x84, 0x84, 0x84, 0x84, 0x48, 0x30} + +/* '1' (49) */ +#define NXFONT_METRICS_49 {1, 5, 9, 2, 5, 0} +#define NXFONT_BITMAP_49 {0x20, 0xe0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xf8} + +/* '2' (50) */ +#define NXFONT_METRICS_50 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_50 {0x78, 0x84, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0xfc} + +/* '3' (51) */ +#define NXFONT_METRICS_51 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_51 {0x78, 0x84, 0x04, 0x04, 0x38, 0x04, 0x04, 0x84, 0x78} + +/* '4' (52) */ +#define NXFONT_METRICS_52 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_52 {0x08, 0x18, 0x28, 0x48, 0x88, 0x88, 0xfc, 0x08, 0x08} + +/* '5' (53) */ +#define NXFONT_METRICS_53 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_53 {0xfc, 0x80, 0x80, 0xf0, 0x08, 0x04, 0x04, 0x84, 0x78} + +/* '6' (54) */ +#define NXFONT_METRICS_54 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_54 {0x3c, 0x40, 0x80, 0xb8, 0xc4, 0x84, 0x84, 0x44, 0x38} + +/* '7' (55) */ +#define NXFONT_METRICS_55 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_55 {0xfc, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40} + +/* '8' (56) */ +#define NXFONT_METRICS_56 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_56 {0x78, 0x84, 0x84, 0x84, 0x78, 0x84, 0x84, 0x84, 0x78} + +/* '9' (57) */ +#define NXFONT_METRICS_57 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_57 {0x70, 0x88, 0x84, 0x84, 0x8c, 0x74, 0x04, 0x08, 0xf0} + +/* Colon (58) */ +#define NXFONT_METRICS_58 {1, 1, 7, 2, 7, 0} +#define NXFONT_BITMAP_58 {0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80} + +/* Semicolon (59) */ +#define NXFONT_METRICS_59 {1, 2, 9, 1, 7, 0} +#define NXFONT_BITMAP_59 {0x40, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40, 0x80, 0x80} + +/* Less than sign (60) */ +#define NXFONT_METRICS_60 {1, 6, 7, 2, 7, 0} +#define NXFONT_BITMAP_60 {0x04, 0x18, 0x20, 0xc0, 0x20, 0x18, 0x04} + +/* Equal to sign (61) */ +#define NXFONT_METRICS_61 {1, 7, 3, 1, 9, 0} +#define NXFONT_BITMAP_61 {0xfe, 0x00, 0xfe} + +/* Greater than sign (62) */ +#define NXFONT_METRICS_62 {1, 6, 7, 2, 7, 0} +#define NXFONT_BITMAP_62 {0x80, 0x60, 0x10, 0x0c, 0x10, 0x60, 0x80} + +/* Question mark (63) */ +#define NXFONT_METRICS_63 {1, 4, 9, 1, 5, 0} +#define NXFONT_BITMAP_63 {0xe0, 0x10, 0x10, 0x60, 0x40, 0x40, 0x00, 0x40, 0x40} + +/* at sign (64) */ +#define NXFONT_METRICS_64 { 2, 9, 9, 1, 5, 0} +#define NXFONT_BITMAP_64 {0x1e, 0x00, 0x21, 0x00, 0x4c, 0x80, 0x92, 0x80, 0xa4, 0x80, 0xad, 0x00,\ + 0x96, 0x00, 0x40, 0x00, 0x3c, 0x00} + +/* 'A' (65) */ +#define NXFONT_METRICS_65 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_65 {0x30, 0x30, 0x48, 0x48, 0x48, 0xfc, 0x84, 0x84, 0x84} + +/* 'B' (66) */ +#define NXFONT_METRICS_66 {1, 5, 9, 1, 5, 0} +#define NXFONT_BITMAP_66 {0xf0, 0x88, 0x88, 0x88, 0xf0, 0x88, 0x88, 0x88, 0xf0} + +/* 'C' (67) */ +#define NXFONT_METRICS_67 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_67 {0x3c, 0x40, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40, 0x3c} + +/* 'D' (68) */ +#define NXFONT_METRICS_68 {1, 7, 9, 1, 5, 0} +#define NXFONT_BITMAP_68 {0xf8, 0x84, 0x82, 0x82, 0x82, 0x82, 0x82, 0x84, 0xf8} + +/* 'E' (69) */ +#define NXFONT_METRICS_69 {1, 5, 9, 1, 5, 0} +#define NXFONT_BITMAP_69 {0xf8, 0x80, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80, 0xf8} + +/* 'F' (70) */ +#define NXFONT_METRICS_70 {1, 4, 9, 1, 5, 0} +#define NXFONT_BITMAP_70 {0xf0, 0x80, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80, 0x80} + +/* 'G' (71) */ +#define NXFONT_METRICS_71 {1, 7, 9, 1, 5, 0} +#define NXFONT_BITMAP_71 {0x3e, 0x40, 0x80, 0x80, 0x82, 0x82, 0x82, 0x42, 0x3e} + +/* 'H' (72) */ +#define NXFONT_METRICS_72 {1, 7, 9, 1, 5, 0} +#define NXFONT_BITMAP_72 {0x82, 0x82, 0x82, 0x82, 0xfe, 0x82, 0x82, 0x82, 0x82} + +/* 'I' (73) */ +#define NXFONT_METRICS_73 {1, 1, 9, 1, 5, 0} +#define NXFONT_BITMAP_73 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* 'J' (74) */ +#define NXFONT_METRICS_74 {1, 3, 11, 0, 5, 0} +#define NXFONT_BITMAP_74 {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xc0} + +/* 'K' (75) */ +#define NXFONT_METRICS_75 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_75 {0x84, 0x88, 0x90, 0xa0, 0xe0, 0x90, 0x88, 0x84, 0x84} + +/* 'L' (76) */ +#define NXFONT_METRICS_76 {1, 5, 9, 1, 5, 0} +#define NXFONT_BITMAP_76 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf8} + +/* 'M' (77) */ +#define NXFONT_METRICS_77 {1, 8, 9, 1, 5, 0} +#define NXFONT_BITMAP_77 {0x81, 0xc3, 0xc3, 0xa5, 0xa5, 0x99, 0x99, 0x81, 0x81} + +/* 'N' (78) */ +#define NXFONT_METRICS_78 {1, 7, 9, 1, 5, 0} +#define NXFONT_BITMAP_78 {0x82, 0xc2, 0xc2, 0xa2, 0x92, 0x8a, 0x86, 0x86, 0x82} + +/* 'O' (79) */ +#define NXFONT_METRICS_79 {1, 7, 9, 1, 5, 0} +#define NXFONT_BITMAP_79 {0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* 'P' (80) */ +#define NXFONT_METRICS_80 {1, 5, 9, 1, 5, 0} +#define NXFONT_BITMAP_80 {0xf0, 0x88, 0x88, 0x88, 0x88, 0xf0, 0x80, 0x80, 0x80} + +/* 'Q' (81) */ +#define NXFONT_METRICS_81 {1, 8, 11, 1, 5, 0} +#define NXFONT_BITMAP_81 {0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38, 0x04, 0x03} + +/* 'R' (82) */ +#define NXFONT_METRICS_82 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_82 {0xf0, 0x88, 0x88, 0x88, 0xf0, 0x90, 0x88, 0x84, 0x84} + +/* 'S' (83) */ +#define NXFONT_METRICS_83 {1, 5, 9, 1, 5, 0} +#define NXFONT_BITMAP_83 {0x78, 0x80, 0x80, 0x40, 0x20, 0x10, 0x08, 0x08, 0xf0} + +/* 'T' (84) */ +#define NXFONT_METRICS_84 {1, 7, 9, 1, 5, 0} +#define NXFONT_BITMAP_84 {0xfe, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10} + +/* 'U' (85) */ +#define NXFONT_METRICS_85 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_85 {0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x48, 0x30} + +/* 'V' (86) */ +#define NXFONT_METRICS_86 {1, 7, 9, 1, 5, 0} +#define NXFONT_BITMAP_86 {0x82, 0x82, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10} + +/* 'W' (87) */ +#define NXFONT_METRICS_87 {2, 9, 9, 1, 5, 0} +#define NXFONT_BITMAP_87 {0x80, 0x80, 0x88, 0x80, 0x88, 0x80, 0x55, 0x00, 0x55, 0x00, 0x55, 0x00,\ + 0x22, 0x00, 0x22, 0x00, 0x22, 0x00} + +/* 'X' (88) */ +#define NXFONT_METRICS_88 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_88 {0x84, 0x84, 0x48, 0x28, 0x30, 0x50, 0x48, 0x84, 0x84} + +/* 'Y' (89) */ +#define NXFONT_METRICS_89 {1, 7, 9, 0, 5, 0} +#define NXFONT_BITMAP_89 {0x82, 0x82, 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10} + +/* 'Z' (90) */ +#define NXFONT_METRICS_90 {1, 5, 9, 1, 5, 0} +#define NXFONT_BITMAP_90 {0xf8, 0x08, 0x10, 0x10, 0x20, 0x40, 0x40, 0x80, 0xf8} + +/* Left bracket (91) */ +#define NXFONT_METRICS_91 {1, 2, 11, 1, 5, 0} +#define NXFONT_BITMAP_91 {0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0} + +/* Back slash (92) */ +#define NXFONT_METRICS_92 {1, 4, 11, 1, 5, 0} +#define NXFONT_BITMAP_92 {0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10} + +/* Right bracket (93) */ +#define NXFONT_METRICS_93 {1, 2, 11, 1, 5, 0} +#define NXFONT_BITMAP_93 {0xc0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0} + +/* ascii circumflex (94) */ +#define NXFONT_METRICS_94 {1, 6, 6, 1, 5, 0} +#define NXFONT_BITMAP_94 {0x30, 0x30, 0x48, 0x48, 0x84, 0x84} + +/* Underscore (95) */ +#define NXFONT_METRICS_95 {1, 6, 1, 0, 14, 0} +#define NXFONT_BITMAP_95 {0xfc} + +/* Grave (96) */ +#define NXFONT_METRICS_96 {1, 3, 2, 2, 4, 0} +#define NXFONT_BITMAP_96 {0xc0, 0x20} + +/* 'a' (97) */ +#define NXFONT_METRICS_97 {1, 6, 7, 1, 7, 0} +#define NXFONT_BITMAP_97 {0x70, 0x88, 0x08, 0x78, 0x88, 0x88, 0x74} + +/* 'b' (98) */ +#define NXFONT_METRICS_98 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_98 {0x80, 0x80, 0x80, 0xb8, 0xc4, 0x84, 0x84, 0x84, 0xc4, 0xb8} + +/* 'c' (99) */ +#define NXFONT_METRICS_99 {1, 4, 7, 1, 7, 0} +#define NXFONT_BITMAP_99 {0x70, 0x80, 0x80, 0x80, 0x80, 0x80, 0x70} + +/* 'd' (100) */ +#define NXFONT_METRICS_100 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_100 {0x04, 0x04, 0x04, 0x74, 0x8c, 0x84, 0x84, 0x84, 0x8c, 0x74} + +/* 'e' (101) */ +#define NXFONT_METRICS_101 {1, 5, 7, 1, 7, 0} +#define NXFONT_BITMAP_101 {0x70, 0x88, 0x88, 0xf8, 0x80, 0x80, 0x78} + +/* 'f' (102) */ +#define NXFONT_METRICS_102 {1, 4, 10, 0, 4, 0} +#define NXFONT_BITMAP_102 {0x30, 0x40, 0x40, 0x40, 0xf0, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* 'g' (103) */ +#define NXFONT_METRICS_103 {1, 5, 9, 1, 7, 0} +#define NXFONT_BITMAP_103 {0x68, 0x98, 0x88, 0x88, 0x98, 0x68, 0x08, 0x08, 0xf0} + +/* 'h' (104) */ +#define NXFONT_METRICS_104 {1, 5, 9, 1, 5, 0} +#define NXFONT_BITMAP_104 {0x80, 0x80, 0xb0, 0xc8, 0x88, 0x88, 0x88, 0x88, 0x88} + +/* 'i' (105) */ +#define NXFONT_METRICS_105 {1, 1, 9, 1, 5, 0} +#define NXFONT_BITMAP_105 {0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* 'j' (106) */ +#define NXFONT_METRICS_106 {1, 3, 11, 0, 5, 0} +#define NXFONT_BITMAP_106 {0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xc0} + +/* 'k' (107) */ +#define NXFONT_METRICS_107 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_107 {0x80, 0x80, 0x80, 0x88, 0x90, 0xa0, 0xe0, 0x90, 0x88, 0x84} + +/* 'l' (108) */ +#define NXFONT_METRICS_108 {1, 1, 10, 1, 4, 0} +#define NXFONT_BITMAP_108 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* 'm' (109) */ +#define NXFONT_METRICS_109 {2, 9, 7, 1, 7, 0} +#define NXFONT_BITMAP_109 {0xb3, 0x00, 0xcc, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80,\ + 0x88, 0x80} +/* 'n' (110) */ +#define NXFONT_METRICS_110 {1, 5, 7, 1, 7, 0} +#define NXFONT_BITMAP_110 {0xb0, 0xc8, 0x88, 0x88, 0x88, 0x88, 0x88} + +/* 'o' (111) */ +#define NXFONT_METRICS_111 {1, 6, 7, 1, 7, 0} +#define NXFONT_BITMAP_111 {0x30, 0x48, 0x84, 0x84, 0x84, 0x48, 0x30} + +/* 'p' (112) */ +#define NXFONT_METRICS_112 {1, 6, 9, 1, 7, 0} +#define NXFONT_BITMAP_112 {0xb8, 0xc4, 0x84, 0x84, 0x84, 0xc4, 0xb8, 0x80, 0x80} + +/* 'q' (113) */ +#define NXFONT_METRICS_113 {1, 6, 9, 1, 7, 0} +#define NXFONT_BITMAP_113 {0x74, 0x8c, 0x84, 0x84, 0x84, 0x9c, 0x74, 0x04, 0x04} + +/* 'r' (114) */ +#define NXFONT_METRICS_114 {1, 4, 7, 1, 7, 0} +#define NXFONT_BITMAP_114 {0xb0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* 's' (115) */ +#define NXFONT_METRICS_115 {1, 4, 7, 1, 7, 0} +#define NXFONT_BITMAP_115 {0x70, 0x80, 0x80, 0x60, 0x10, 0x10, 0xe0} + +/* 't' (116) */ +#define NXFONT_METRICS_116 {1, 4, 9, 0, 5, 0} +#define NXFONT_BITMAP_116 {0x40, 0x40, 0xf0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x30} + +/* 'u' (117) */ +#define NXFONT_METRICS_117 {1, 5, 7, 1, 7, 0} +#define NXFONT_BITMAP_117 {0x88, 0x88, 0x88, 0x88, 0x88, 0x98, 0x68} + +/* 'v' (118) */ +#define NXFONT_METRICS_118 {1, 5, 7, 1, 7, 0} +#define NXFONT_BITMAP_118 {0x88, 0x88, 0x88, 0x50, 0x50, 0x20, 0x20} + +/* 'w' (119) */ +#define NXFONT_METRICS_119 {2, 9, 7, 0, 7, 0} +#define NXFONT_BITMAP_119 {0x80, 0x80, 0x88, 0x80, 0x49, 0x00, 0x55, 0x00, 0x55, 0x00, 0x22, 0x00,\ + 0x22, 0x00} + +/* 'x' (120) */ +#define NXFONT_METRICS_120 {1, 5, 7, 1, 7, 0} +#define NXFONT_BITMAP_120 {0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88} + +/* 'y' (121) */ +#define NXFONT_METRICS_121 {1, 5, 9, 1, 7, 0} +#define NXFONT_BITMAP_121 {0x88, 0x88, 0x88, 0x50, 0x50, 0x20, 0x20, 0x40, 0xc0} + +/* 'z' (122) */ +#define NXFONT_METRICS_122 {1, 5, 7, 1, 7, 0} +#define NXFONT_BITMAP_122 {0xf8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xf8} + +/* Left brace (123) */ +#define NXFONT_METRICS_123 {1, 4, 11, 0, 5, 0} +#define NXFONT_BITMAP_123 {0x30, 0x40, 0x40, 0x40, 0x20, 0xc0, 0x20, 0x40, 0x40, 0x40, 0x30} + +/* Vertical bar (124) */ +#define NXFONT_METRICS_124 {1, 1, 11, 2, 5, 0} +#define NXFONT_BITMAP_124 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* Right brace (125) */ +#define NXFONT_METRICS_125 {1, 4, 11, 0, 5, 0} +#define NXFONT_BITMAP_125 {0xc0, 0x20, 0x20, 0x20, 0x40, 0x30, 0x40, 0x20, 0x20, 0x20, 0xc0} + +/* Tilde (126) */ +#define NXFONT_METRICS_126 {1, 6, 3, 1, 9, 0} +#define NXFONT_BITMAP_126 {0x44, 0xb4, 0x88} + +/* Space (160) */ + +/* Down exclamation point (161) */ +#define NXFONT_METRICS_161 {1, 1, 9, 1, 7, 0} +#define NXFONT_BITMAP_161 {0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* Cent (162) */ +#define NXFONT_METRICS_162 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_162 {0x10, 0x3c, 0x50, 0x90, 0x90, 0x90, 0x50, 0x3c, 0x10} + +/* Sterling (163) */ +#define NXFONT_METRICS_163 {1, 6, 9, 1, 5, 0} +#define NXFONT_BITMAP_163 {0x1c, 0x20, 0x20, 0x20, 0x78, 0x20, 0x20, 0x40, 0xfc} + +/* Currency (164) */ +#define NXFONT_METRICS_164 {1, 5, 7, 1, 6, 0} +#define NXFONT_BITMAP_164 {0x88, 0x70, 0x88, 0x88, 0x88, 0x70, 0x88} + +/* Yen (165) */ +#define NXFONT_METRICS_165 {1, 7, 9, 0, 5, 0} +#define NXFONT_BITMAP_165 {0x82, 0x44, 0x28, 0x10, 0x7c, 0x10, 0x7c, 0x10, 0x10} + +/* Broken bar (166) */ +#define NXFONT_METRICS_166 {1, 1, 11, 2, 5, 0} +#define NXFONT_BITMAP_166 {0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* Section (167) */ +#define NXFONT_METRICS_167 {1, 5, 11, 1, 5, 0} +#define NXFONT_BITMAP_167 {0x78, 0x80, 0x80, 0x60, 0x98, 0x88, 0xc8, 0x30, 0x08, 0x08, 0xf0} + +/* Dieresis (168) */ +#define NXFONT_METRICS_168 {1, 3, 2, 2, 4, 0} +#define NXFONT_BITMAP_168 {0xa0, 0xa0} + +/* Copyright (169) */ +#define NXFONT_METRICS_169 {2, 9, 9, 1, 5, 0} +#define NXFONT_BITMAP_169 {0x3e, 0x00, 0x41, 0x00, 0x9c, 0x80, 0xa0, 0x80, 0xa0, 0x80, 0xa0, 0x80,\ + 0x9c, 0x80, 0x41, 0x00, 0x3e, 0x00} +/* Ord feminine (170) */ +#define NXFONT_METRICS_170 {1, 3, 5, 1, 4, 0} +#define NXFONT_BITMAP_170 {0xc0, 0x20, 0xe0, 0xa0, 0xe0} + +/* Left guillemot (171) */ +#define NXFONT_METRICS_171 {1, 4, 6, 1, 8, 0} +#define NXFONT_BITMAP_171 {0x50, 0x50, 0xa0, 0xa0, 0x50, 0x50} + +/* Logical not (172) */ +#define NXFONT_METRICS_172 {1, 7, 3, 1, 9, 0} +#define NXFONT_BITMAP_172 {0xfe, 0x02, 0x02} + +/* Hyphen (173) */ +#define NXFONT_METRICS_173 {1, 5, 1, 1, 10, 0} +#define NXFONT_BITMAP_173 {0xf8} + +/* Registered (174) */ +#define NXFONT_METRICS_174 {1, 6, 6, 1, 5, 0} +#define NXFONT_BITMAP_174 {0x78, 0xb4, 0xb4, 0xac, 0xac, 0x78} + +/* Macron (175) */ +#define NXFONT_METRICS_175 {1, 6, 1, 0, 4, 0} +#define NXFONT_BITMAP_175 {0xfc} + +/* Degree (176) */ +#define NXFONT_METRICS_176 {1, 3, 3, 0, 5, 0} +#define NXFONT_BITMAP_176 {0x40, 0xa0, 0x40} + +/* plus/minus (177) */ +#define NXFONT_METRICS_177 {1, 7, 7, 1, 7, 0} +#define NXFONT_BITMAP_177 {0x10, 0x10, 0xfe, 0x10, 0x10, 0x00, 0xfe} + +/* '2' superior (178) */ +#define NXFONT_METRICS_178 {1, 3, 5, 1, 5, 0} +#define NXFONT_BITMAP_178 {0xc0, 0x20, 0x60, 0x80, 0xe0} + +/* '3' superior (179) */ +#define NXFONT_METRICS_179 {1, 3, 5, 1, 5, 0} +#define NXFONT_BITMAP_179 {0xc0, 0x20, 0xc0, 0x20, 0xc0} + +/* Acute (180) */ +#define NXFONT_METRICS_180 {1, 3, 2, 2, 4, 0} +#define NXFONT_BITMAP_180 {0x60, 0x80} + +/* Mu (181) */ +#define NXFONT_METRICS_181 {1, 5, 9, 1, 7, 0} +#define NXFONT_BITMAP_181 {0x88, 0x88, 0x88, 0x88, 0x88, 0xd8, 0xa8, 0x80, 0x80} + +/* Paragraph (182) */ +#define NXFONT_METRICS_182 {1, 5, 11, 1, 5, 0} +#define NXFONT_BITMAP_182 {0x78, 0xe8, 0xe8, 0xe8, 0x68, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28} + +/* Centered period (183) */ +#define NXFONT_METRICS_183 {1, 1, 2, 2, 9, 0} +#define NXFONT_BITMAP_183 {0x80, 0x80} + +/* Cedilla (184) */ +#define NXFONT_METRICS_184 {1, 3, 2, 2, 14, 0} +#define NXFONT_BITMAP_184 {0x20, 0xc0} + +/* '1' superior (185) */ +#define NXFONT_METRICS_185 {1, 2, 5, 1, 5, 0} +#define NXFONT_BITMAP_185 {0x40, 0xc0, 0x40, 0x40, 0x40} + +/* Ord masculine (186) */ +#define NXFONT_METRICS_186 {1, 4, 5, 1, 5, 0} +#define NXFONT_BITMAP_186 {0x60, 0x90, 0x90, 0x90, 0x60} + +/* Right guillemot (187) */ +#define NXFONT_METRICS_187 {1, 4, 6, 1, 8, 0} +#define NXFONT_BITMAP_187 {0xa0, 0xa0, 0x50, 0x50, 0xa0, 0xa0} + +/* One quarter (188) */ +#define NXFONT_METRICS_188 {1, 8, 10, 1, 5, 0} +#define NXFONT_BITMAP_188 {0x42, 0xc4, 0x44, 0x48, 0x52, 0x16, 0x2a, 0x4f, 0x42, 0x80} + +/* One half (189) */ +#define NXFONT_METRICS_189 {1, 8, 10, 1, 5, 0} +#define NXFONT_BITMAP_189 {0x42, 0xc4, 0x44, 0x48, 0x56, 0x11, 0x22, 0x44, 0x47, 0x80} + +/* Three quarters (190) */ +#define NXFONT_METRICS_190 {1, 8, 10, 1, 5, 0} +#define NXFONT_BITMAP_190 {0xc2, 0x24, 0xc4, 0x28, 0xd2, 0x16, 0x2a, 0x4f, 0x42, 0x80} + +/* Upside down question mark (191) */ +#define NXFONT_METRICS_191 {1, 5, 9, 0, 7, 0} +#define NXFONT_BITMAP_191 {0x20, 0x20, 0x00, 0x20, 0x20, 0x60, 0x80, 0x80, 0x78} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {1, 6, 12, 1, 2, 0} +#define NXFONT_BITMAP_192 {0x60, 0x10, 0x00, 0x30, 0x30, 0x48, 0x48, 0x48, 0xfc, 0x84, 0x84, 0x84} + +/* 'A' acute (193) */ +#define NXFONT_METRICS_193 {1, 6, 12, 1, 2, 0} +#define NXFONT_BITMAP_193 {0x18, 0x20, 0x00, 0x30, 0x30, 0x48, 0x48, 0x48, 0xfc, 0x84, 0x84, 0x84} + +/* 'A' circumflex (194) */ +#define NXFONT_METRICS_194 {1, 6, 12, 1, 2, 0} +#define NXFONT_BITMAP_194 {0x10, 0x20, 0x00, 0x30, 0x30, 0x48, 0x48, 0x48, 0xfc, 0x84, 0x84, 0x84} + +/* 'A' tilde (195) */ +#define NXFONT_METRICS_195 {1, 6, 12, 1, 2, 0} +#define NXFONT_BITMAP_195 {0x34, 0x48, 0x00, 0x30, 0x30, 0x48, 0x48, 0x48, 0xfc, 0x84, 0x84, 0x84} + +/* 'A' dieresis (196) */ +#define NXFONT_METRICS_196 {1, 6, 12, 1, 2, 0} +#define NXFONT_BITMAP_196 {0x48, 0x48, 0x00, 0x30, 0x30, 0x48, 0x48, 0x48, 0xfc, 0x84, 0x84, 0x84} + +/* 'A'ring (197) */ +#define NXFONT_METRICS_197 {1, 6, 12, 1, 2, 0} +#define NXFONT_BITMAP_197 {0x30, 0x48, 0x48, 0x30, 0x30, 0x48, 0x48, 0x48, 0xfc, 0x84, 0x84, 0x84} + +/* 'AE' (198) */ +#define NXFONT_METRICS_198 {2, 9, 9, 1, 5, 0} +#define NXFONT_BITMAP_198 {0x0f, 0x80, 0x14, 0x00, 0x14, 0x00, 0x24, 0x00, 0x27, 0x80, 0x7c, 0x00,\ + 0x44, 0x00, 0x84, 0x00, 0x87, 0x80} + +/* 'C' cedilla (199) */ +#define NXFONT_METRICS_199 {1, 6, 11, 1, 5, 0} +#define NXFONT_BITMAP_199 {0x3c, 0x40, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40, 0x3c, 0x08, 0x30} + +/* 'E' grave (200) */ +#define NXFONT_METRICS_200 {1, 5, 12, 1, 2, 0} +#define NXFONT_BITMAP_200 {0xc0, 0x20, 0x00, 0xf8, 0x80, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80, 0xf8} + +/* 'E' acute (201) */ +#define NXFONT_METRICS_201 {1, 5, 12, 1, 2, 0} +#define NXFONT_BITMAP_201 {0x18, 0x20, 0x00, 0xf8, 0x80, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80, 0xf8} + +/* 'E' circumflex (202) */ +#define NXFONT_METRICS_202 {1, 5, 12, 1, 2, 0} +#define NXFONT_BITMAP_202 {0x20, 0x50, 0x00, 0xf8, 0x80, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80, 0xf8} + +/* 'E' dieresis (203) */ +#define NXFONT_METRICS_203 {1, 5, 12, 1, 2, 0} +#define NXFONT_BITMAP_203 {0x50, 0x50, 0x00, 0xf8, 0x80, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80, 0xf8} + +/* 'I' grave (204) */ +#define NXFONT_METRICS_204 {1, 3, 12, 0, 2, 0} +#define NXFONT_BITMAP_204 {0xc0, 0x20, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* 'I' acute (205) */ +#define NXFONT_METRICS_205 {1, 3, 12, 0, 2, 0} +#define NXFONT_BITMAP_205 {0x60, 0x80, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* 'I' circumflex (206) */ +#define NXFONT_METRICS_206 {1, 3, 12, 0, 2, 0} +#define NXFONT_BITMAP_206 {0x40, 0xa0, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* 'I' dieresis (207) */ +#define NXFONT_METRICS_207 {1, 3, 12, 0, 2, 0} +#define NXFONT_BITMAP_207 {0xa0, 0xa0, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* 'E' th (208) */ +#define NXFONT_METRICS_208 {1, 8, 9, 0, 5, 0} +#define NXFONT_BITMAP_208 {0x7c, 0x42, 0x41, 0x41, 0xf1, 0x41, 0x41, 0x42, 0x7c} + +/* 'N' tilde (209) */ +#define NXFONT_METRICS_209 {1, 7, 12, 1, 2, 0} +#define NXFONT_BITMAP_209 {0x34, 0x48, 0x00, 0x82, 0xc2, 0xe2, 0xa2, 0x92, 0x8a, 0x86, 0x86, 0x82} + +/* 'O' grave (210) */ +#define NXFONT_METRICS_210 {1, 7, 12, 1, 2, 0} +#define NXFONT_BITMAP_210 {0x30, 0x08, 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* 'O' acute (211) */ +#define NXFONT_METRICS_211 {1, 7, 12, 1, 2, 0} +#define NXFONT_BITMAP_211 {0x18, 0x20, 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* 'O' circumflex (212) */ +#define NXFONT_METRICS_212 {1, 7, 12, 1, 2, 0} +#define NXFONT_BITMAP_212 {0x10, 0x28, 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* 'O' tilde (213) */ +#define NXFONT_METRICS_213 {1, 7, 12, 1, 2, 0} +#define NXFONT_BITMAP_213 {0x34, 0x48, 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* 'O' dieresis (214) */ +#define NXFONT_METRICS_214 {1, 7, 12, 1, 2, 0} +#define NXFONT_BITMAP_214 {0x44, 0x44, 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* Multiply sign (215) */ +#define NXFONT_METRICS_215 {1, 7, 7, 1, 7, 0} +#define NXFONT_BITMAP_215 {0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82} + +/* 'O' slash (216) */ +#define NXFONT_METRICS_216 {1, 7, 9, 1, 5, 0} +#define NXFONT_BITMAP_216 {0x3a, 0x44, 0x8a, 0x8a, 0x92, 0xa2, 0xa2, 0x44, 0xb8} + +/*'U' grave (217) */ +#define NXFONT_METRICS_217 {1, 6, 12, 1, 2, 0} +#define NXFONT_BITMAP_217 {0x60, 0x10, 0x00, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x48, 0x30} + +/* 'U' acute (218) */ +#define NXFONT_METRICS_218 {1, 6, 12, 1, 2, 0} +#define NXFONT_BITMAP_218 {0x18, 0x20, 0x00, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x48, 0x30} + +/* 'U' circumflex (219) */ +#define NXFONT_METRICS_219 {1, 6, 12, 1, 2, 0} +#define NXFONT_BITMAP_219 {0x10, 0x28, 0x00, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x48, 0x30} + +/* 'U' dieresis (220) */ +#define NXFONT_METRICS_220 {1, 6, 12, 1, 2, 0} +#define NXFONT_BITMAP_220 {0x48, 0x48, 0x00, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x48, 0x30} + +/* 'Y' acute (221) */ +#define NXFONT_METRICS_221 {1, 7, 12, 0, 2, 0} +#define NXFONT_BITMAP_221 {0x18, 0x20, 0x00, 0x82, 0x82, 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10} + +/* 'T' horn (222) */ +#define NXFONT_METRICS_222 {1, 5, 9, 1, 5, 0} +#define NXFONT_BITMAP_222 {0x80, 0x80, 0xf0, 0x88, 0x88, 0x88, 0xf0, 0x80, 0x80} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {1, 5, 10, 1, 4, 0} +#define NXFONT_BITMAP_223 {0x60, 0x90, 0x90, 0xa0, 0xa0, 0x90, 0x88, 0x88, 0x88, 0xb0} + +/* 'a' grave (224) */ +#define NXFONT_METRICS_224 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_224 {0x60, 0x10, 0x00, 0x70, 0x88, 0x08, 0x78, 0x88, 0x88, 0x74} + +/* 'a' acute (225) */ +#define NXFONT_METRICS_225 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_225 {0x18, 0x20, 0x00, 0x70, 0x88, 0x08, 0x78, 0x88, 0x88, 0x74} + +/* 'a' circumflex (226) */ +#define NXFONT_METRICS_226 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_226 {0x20, 0x50, 0x00, 0x70, 0x88, 0x08, 0x78, 0x88, 0x88, 0x74} + +/* 'a' tilde (227) */ +#define NXFONT_METRICS_227 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_227 {0x68, 0x90, 0x00, 0x70, 0x88, 0x08, 0x78, 0x88, 0x88, 0x74} + +/* 'a' dieresis (228) */ +#define NXFONT_METRICS_228 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_228 {0x50, 0x50, 0x00, 0x70, 0x88, 0x08, 0x78, 0x88, 0x88, 0x74} + +/* a' ring (229) */ +#define NXFONT_METRICS_229 {1, 6, 11, 1, 3, 0} +#define NXFONT_BITMAP_229 {0x20, 0x50, 0x20, 0x00, 0x70, 0x88, 0x08, 0x78, 0x88, 0x88, 0x74} + +/* 'ae' (230) */ +#define NXFONT_METRICS_230 {1, 8, 7, 1, 7, 0} +#define NXFONT_BITMAP_230 {0x76, 0x89, 0x09, 0x7f, 0x88, 0x88, 0x77} + +/* 'c' cedilla (231) */ +#define NXFONT_METRICS_231 {1, 4, 9, 1, 7, 0} +#define NXFONT_BITMAP_231 {0x70, 0x80, 0x80, 0x80, 0x80, 0x80, 0x70, 0x20, 0xc0} + +/* 'e' grave (232) */ +#define NXFONT_METRICS_232 {1, 5, 10, 1, 4, 0} +#define NXFONT_BITMAP_232 {0x60, 0x10, 0x00, 0x70, 0x88, 0x88, 0xf8, 0x80, 0x80, 0x78} + +/* 'e' acute (233) */ +#define NXFONT_METRICS_233 {1, 5, 10, 1, 4, 0} +#define NXFONT_BITMAP_233 {0x18, 0x20, 0x00, 0x70, 0x88, 0x88, 0xf8, 0x80, 0x80, 0x78} + +/* 'e' circumflex (234) */ +#define NXFONT_METRICS_234 {1, 5, 10, 1, 4, 0} +#define NXFONT_BITMAP_234 {0x20, 0x50, 0x00, 0x70, 0x88, 0x88, 0xf8, 0x80, 0x80, 0x78} + +/* 'e' dieresis (235) */ +#define NXFONT_METRICS_235 {1, 5, 10, 1, 4, 0} +#define NXFONT_BITMAP_235 {0x50, 0x50, 0x00, 0x70, 0x88, 0x88, 0xf8, 0x80, 0x80, 0x78} + +/* 'i' grave (236) */ +#define NXFONT_METRICS_236 {1, 3, 10, 0, 4, 0} +#define NXFONT_BITMAP_236 {0xc0, 0x20, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* 'i' acute (237) */ +#define NXFONT_METRICS_237 {1, 3, 10, 0, 4, 0} +#define NXFONT_BITMAP_237 {0x60, 0x80, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* 'i' circumflex (238) */ +#define NXFONT_METRICS_238 {1, 3, 10, 0, 4, 0} +#define NXFONT_BITMAP_238 {0x40, 0xa0, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* 'i' dieresis (239) */ +#define NXFONT_METRICS_239 {1, 3, 10, 0, 4, 0} +#define NXFONT_BITMAP_239 {0xa0, 0xa0, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40} + +/* 'e' th (240) */ +#define NXFONT_METRICS_240 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_240 {0xd0, 0x20, 0x50, 0x10, 0x68, 0x84, 0x84, 0x84, 0x48, 0x30} + +/* 'n' tilde (241) */ +#define NXFONT_METRICS_241 {1, 5, 10, 1, 4, 0} +#define NXFONT_BITMAP_241 {0x68, 0x90, 0x00, 0xb0, 0xc8, 0x88, 0x88, 0x88, 0x88, 0x88} + +/* 'o' grave (242) */ +#define NXFONT_METRICS_242 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_242 {0x60, 0x10, 0x00, 0x30, 0x48, 0x84, 0x84, 0x84, 0x48, 0x30} + +/* 'o' acute (243) */ +#define NXFONT_METRICS_243 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_243 {0x18, 0x20, 0x00, 0x30, 0x48, 0x84, 0x84, 0x84, 0x48, 0x30} + +/* 'o' circumflex (244) */ +#define NXFONT_METRICS_244 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_244 {0x10, 0x28, 0x00, 0x30, 0x48, 0x84, 0x84, 0x84, 0x48, 0x30} + +/* 'o' tilde (245) */ +#define NXFONT_METRICS_245 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_245 {0x34, 0x48, 0x00, 0x30, 0x48, 0x84, 0x84, 0x84, 0x48, 0x30} + +/* 'o' dieresis (246) */ +#define NXFONT_METRICS_246 {1, 6, 10, 1, 4, 0} +#define NXFONT_BITMAP_246 {0x48, 0x48, 0x00, 0x30, 0x48, 0x84, 0x84, 0x84, 0x48, 0x30} + +/* Division sign (247) */ +#define NXFONT_METRICS_247 {1, 7, 7, 1, 7, 0} +#define NXFONT_BITMAP_247 {0x10, 0x10, 0x00, 0xfe, 0x00, 0x10, 0x10} + +/* 'o' slash (248) */ +#define NXFONT_METRICS_248 {1, 6, 7, 1, 7, 0} +#define NXFONT_BITMAP_248 {0x34, 0x48, 0x94, 0x94, 0xa4 0x48, 0xb0} + +/* 'u' grave (249) */ +#define NXFONT_METRICS_249 {1, 5, 10, 1, 4, 0} +#define NXFONT_BITMAP_249 {0xc0, 0x20, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x98, 0x68} + +/* 'u' acute (250) */ +#define NXFONT_METRICS_250 {1, 5, 10, 1, 4, 0} +#define NXFONT_BITMAP_250 {0x18, 0x20, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x98, 0x68} + +/* 'u' circumflex (251) */ +#define NXFONT_METRICS_251 {1, 5, 10, 1, 4, 0} +#define NXFONT_BITMAP_251 {0x20, 0x50, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x98, 0x68} + +/* 'u' dieresis (252) */ +#define NXFONT_METRICS_252 {1, 5, 10, 1, 4, 0} +#define NXFONT_BITMAP_252 {0x50, 0x50, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x98, 0x68} + +/* 'y' acute (253) */ +#define NXFONT_METRICS_253 {1, 5, 12, 1, 4, 0} +#define NXFONT_BITMAP_253 {0x18, 0x20, 0x00, 0x88, 0x88, 0x88, 0x50, 0x50, 0x20, 0x20, 0x40, 0xc0} + +/* 't' horn (254) */ +#define NXFONT_METRICS_254 {1, 6, 12, 1, 4, 0} +#define NXFONT_BITMAP_254 {0x80, 0x80, 0x80, 0xb8, 0xc4, 0x84, 0x84, 0x84, 0xc4, 0xb8, 0x80, 0x80} + +/* 'y' dieresis (255) */ +#define NXFONT_METRICS_255 {1, 5, 12, 1, 4, 0} +#define NXFONT_BITMAP_255 {0x50, 0x50, 0x00, 0x88, 0x88, 0x88, 0x50, 0x50, 0x20, 0x20, 0x40, 0xc0} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SANS23X27_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_sans28x37.h b/nuttx/graphics/nxfonts/nxfonts_sans28x37.h new file mode 100644 index 0000000000..f41ff30cf1 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_sans28x37.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_sans28x37.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Jose Pablo Carballo Gomez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SANS28X37_H +#define __GRAPHICS_NXFONTS_NXFONTS_SANS28X37_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SANS28X37 + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 37 +#define NXFONT_MAXWIDTH 28 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 6 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 2, 19, 2, 10, 0} +#define NXFONT_BITMAP_33 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x0, 0x0, 0xc0, 0xc0, 0xc0} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {1, 6, 6, 1, 10, 0} +#define NXFONT_BITMAP_34 {0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x44} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {2, 11, 17, 2, 12, 0} +#define NXFONT_BITMAP_35 {0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0x19, 0x80, 0xff, 0xe0, 0xff, 0xe0, 0x19, 0x80, 0x19, 0x80, 0x33, 0x0, 0x33, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0x33, 0x0, 0x33, 0x0, 0x66, 0x0, 0x66, 0x0, 0x66, 0x0} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {2, 11, 22, 1, 9, 0} +#define NXFONT_BITMAP_36 {0x6, 0x0, 0x6, 0x0, 0x1f, 0x80, 0x3f, 0xc0, 0x76, 0xe0, 0x66, 0x60, 0x66, 0x60, 0x66, 0x0, 0x76, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0xf, 0x80, 0x7, 0xc0, 0x6, 0xe0, 0x6, 0x60, 0xc6, 0x60, 0xc6, 0x60, 0xe6, 0xe0, 0x7f, 0xc0, 0x3f, 0x80, 0x6, 0x0, 0x6, 0x0} + +/* percent (37) */ +#define NXFONT_METRICS_37 {3, 19, 18, 1, 11, 0} +#define NXFONT_BITMAP_37 {0x0, 0x6, 0x0, 0x3c, 0xc, 0x0, 0x7e, 0xc, 0x0, 0xc3, 0x18, 0x0, 0xc3, 0x18, 0x0, 0xc3, 0x30, 0x0, 0xc3, 0x30, 0x0, 0x7e, 0x60, 0x0, 0x3c, 0x60, 0x0, 0x0, 0xc0, 0x0, 0x0, 0xc7, 0x80, 0x1, 0x8f, 0xc0, 0x1, 0x98, 0x60, 0x3, 0x18, 0x60, 0x3, 0x18, 0x60, 0x6, 0x18, 0x60, 0x6, 0xf, 0xc0, 0x4, 0x7, 0x80} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {2, 14, 18, 2, 11, 0} +#define NXFONT_BITMAP_38 {0xf, 0x0, 0x1f, 0x80, 0x39, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x19, 0x80, 0xf, 0x0, 0x1e, 0x0, 0x3f, 0x18, 0x73, 0x98, 0x61, 0xd8, 0xc0, 0xf0, 0xc0, 0x60, 0xc0, 0xf0, 0xe1, 0xd8, 0x7f, 0x9c, 0x1e, 0x0} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 2, 6, 2, 10, 0} +#define NXFONT_BITMAP_39 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x40} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 5, 24, 2, 10, 0} +#define NXFONT_BITMAP_40 {0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x60, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 5, 24, 1, 10, 0} +#define NXFONT_BITMAP_41 {0xc0, 0xc0, 0x60, 0x60, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x60, 0x60, 0xc0, 0xc0} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {1, 7, 7, 1, 10, 0} +#define NXFONT_BITMAP_42 {0x10, 0x10, 0xd6, 0x7c, 0x38, 0x6c, 0x44} + +/* plus (43) */ +#define NXFONT_METRICS_43 {2, 12, 12, 1, 16, 0} +#define NXFONT_BITMAP_43 {0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 2, 6, 2, 26, 0} +#define NXFONT_BITMAP_44 {0xc0, 0xc0, 0xc0, 0x40, 0x40, 0x80} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 6, 2, 1, 21, 0} +#define NXFONT_BITMAP_45 {0xfc, 0xfc} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 2, 3, 2, 26, 0} +#define NXFONT_BITMAP_46 {0xc0, 0xc0, 0xc0} + +/* slash (47) */ +#define NXFONT_METRICS_47 {1, 7, 19, 0, 10, 0} +#define NXFONT_BITMAP_47 {0x6, 0x4, 0xc, 0xc, 0x8, 0x18, 0x18, 0x10, 0x10, 0x30, 0x30, 0x20, 0x60, 0x60, 0x40, 0xc0, 0xc0, 0x80, 0x80} + +/* zero (48) */ +#define NXFONT_METRICS_48 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_48 {0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* one (49) */ +#define NXFONT_METRICS_49 {1, 6, 18, 2, 11, 0} +#define NXFONT_BITMAP_49 {0xc, 0xc, 0x1c, 0xfc, 0xfc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc} + +/* two (50) */ +#define NXFONT_METRICS_50 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_50 {0x1e, 0x0, 0x7f, 0x80, 0x61, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0xc0, 0x60, 0x0, 0xe0, 0x0, 0xc0, 0x1, 0xc0, 0x3, 0x80, 0xf, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x70, 0x0, 0xe0, 0x0, 0xc0, 0x0, 0xff, 0xe0, 0xff, 0xe0} + +/* three (51) */ +#define NXFONT_METRICS_51 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_51 {0x1f, 0x0, 0x7f, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x0, 0xc0, 0x1, 0x80, 0xf, 0x0, 0xf, 0xc0, 0x0, 0xc0, 0x0, 0x60, 0x0, 0x60, 0xc0, 0x60, 0xc0, 0xc0, 0x61, 0xc0, 0x7f, 0x80, 0x1f, 0x0} + +/* four (52) */ +#define NXFONT_METRICS_52 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_52 {0x1, 0x80, 0x3, 0x80, 0x3, 0x80, 0x7, 0x80, 0xf, 0x80, 0xd, 0x80, 0x19, 0x80, 0x39, 0x80, 0x31, 0x80, 0x61, 0x80, 0xe1, 0x80, 0xc1, 0x80, 0xff, 0xe0, 0xff, 0xe0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80} + +/* five (53) */ +#define NXFONT_METRICS_53 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_53 {0x7f, 0xc0, 0x7f, 0xc0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x7e, 0x0, 0x7f, 0x80, 0x71, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x60, 0x0, 0x60, 0xc0, 0xe0, 0xc0, 0xc0, 0xe1, 0xc0, 0x7f, 0x80, 0x1e, 0x0} + +/* six (54) */ +#define NXFONT_METRICS_54 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_54 {0xf, 0x0, 0x3f, 0xc0, 0x70, 0xc0, 0x60, 0x60, 0xe0, 0x60, 0xc0, 0x0, 0xc0, 0x0, 0xcf, 0x0, 0xdf, 0x80, 0xf1, 0xc0, 0xe0, 0xc0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x71, 0xc0, 0x7f, 0xc0, 0x1f, 0x0} + +/* seven (55) */ +#define NXFONT_METRICS_55 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_55 {0xff, 0xe0, 0xff, 0xe0, 0x0, 0xe0, 0x0, 0xc0, 0x1, 0x80, 0x1, 0x80, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0xc, 0x0, 0xc, 0x0, 0x1c, 0x0, 0x18, 0x0, 0x18, 0x0, 0x38, 0x0, 0x30, 0x0, 0x30, 0x0} + +/* eight (56) */ +#define NXFONT_METRICS_56 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_56 {0xe, 0x0, 0x3f, 0x80, 0x31, 0x80, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x31, 0x80, 0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0x60, 0xc0, 0x7f, 0xc0, 0x1f, 0x0} + +/* nine (57) */ +#define NXFONT_METRICS_57 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_57 {0x1f, 0x0, 0x7f, 0xc0, 0x71, 0xc0, 0xe0, 0xc0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x71, 0xe0, 0x7f, 0x60, 0x1e, 0x60, 0x0, 0x60, 0x0, 0xe0, 0xc0, 0xc0, 0xe1, 0xc0, 0x7f, 0x80, 0x1e, 0x0} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 2, 14, 2, 15, 0} +#define NXFONT_BITMAP_58 {0xc0, 0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 2, 17, 2, 15, 0} +#define NXFONT_BITMAP_59 {0xc0, 0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0x40, 0x40, 0x80} + +/* less (60) */ +#define NXFONT_METRICS_60 {2, 12, 12, 1, 16, 0} +#define NXFONT_BITMAP_60 {0x0, 0x30, 0x0, 0xf0, 0x3, 0xc0, 0xf, 0x0, 0x3c, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0x3c, 0x0, 0xf, 0x0, 0x3, 0xc0, 0x0, 0xf0, 0x0, 0x30} + +/* equal (61) */ +#define NXFONT_METRICS_61 {2, 10, 5, 2, 19, 0} +#define NXFONT_BITMAP_61 {0xff, 0xc0, 0xff, 0xc0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* greater (62) */ +#define NXFONT_METRICS_62 {2, 12, 12, 1, 16, 0} +#define NXFONT_BITMAP_62 {0xc0, 0x0, 0xf0, 0x0, 0x3c, 0x0, 0xf, 0x0, 0x3, 0xc0, 0x0, 0x70, 0x0, 0x70, 0x3, 0xc0, 0xf, 0x0, 0x3c, 0x0, 0xf0, 0x0, 0xc0, 0x0} + +/* question (63) */ +#define NXFONT_METRICS_63 {2, 10, 19, 1, 10, 0} +#define NXFONT_BITMAP_63 {0x1f, 0x0, 0x7f, 0x80, 0x71, 0xc0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x1, 0x80, 0x3, 0x80, 0x7, 0x0, 0x6, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0} + +/* at (64) */ +#define NXFONT_METRICS_64 {3, 22, 23, 2, 10, 0} +#define NXFONT_BITMAP_64 {0x0, 0xff, 0x0, 0x3, 0xff, 0xc0, 0xf, 0x1, 0xe0, 0x1c, 0x0, 0x70, 0x38, 0x0, 0x18, 0x30, 0x0, 0x18, 0x60, 0x73, 0xc, 0x60, 0xfb, 0xc, 0xc1, 0xc7, 0xc, 0xc3, 0x86, 0xc, 0xc3, 0x6, 0xc, 0xc6, 0x6, 0xc, 0xc6, 0xc, 0x1c, 0xc6, 0xc, 0x18, 0xc6, 0xc, 0x38, 0xe7, 0x1c, 0x70, 0x63, 0xf7, 0xe0, 0x71, 0xe3, 0x80, 0x38, 0x0, 0x0, 0x1c, 0x0, 0x0, 0xf, 0x3, 0x0, 0x7, 0xff, 0x0, 0x0, 0xfc, 0x0} + +/* A (65) */ +#define NXFONT_METRICS_65 {2, 15, 19, 1, 10, 0} +#define NXFONT_BITMAP_65 {0x3, 0x80, 0x3, 0x80, 0x6, 0xc0, 0x6, 0xc0, 0xc, 0x40, 0xc, 0x60, 0xc, 0x60, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x18, 0x3f, 0xf8, 0x3f, 0xf8, 0x60, 0xc, 0x60, 0xc, 0x60, 0xc, 0xc0, 0x6, 0xc0, 0x6, 0xc0, 0x6} + +/* B (66) */ +#define NXFONT_METRICS_66 {2, 14, 19, 2, 10, 0} +#define NXFONT_BITMAP_66 {0xff, 0xc0, 0xff, 0xf0, 0xc0, 0x70, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x30, 0xff, 0xe0, 0xff, 0xf0, 0xc0, 0x18, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0x1c, 0xc0, 0x78, 0xff, 0xf0, 0xff, 0xc0} + +/* C (67) */ +#define NXFONT_METRICS_67 {2, 15, 19, 1, 10, 0} +#define NXFONT_BITMAP_67 {0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0xe, 0x60, 0x6, 0xe0, 0x6, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x6, 0x60, 0x6, 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0} + +/* D (68) */ +#define NXFONT_METRICS_68 {2, 15, 19, 2, 10, 0} +#define NXFONT_BITMAP_68 {0xff, 0xc0, 0xff, 0xf0, 0xc0, 0x78, 0xc0, 0x1c, 0xc0, 0xc, 0xc0, 0xe, 0xc0, 0x6, 0xc0, 0x6, 0xc0, 0x6, 0xc0, 0x6, 0xc0, 0x6, 0xc0, 0x6, 0xc0, 0x6, 0xc0, 0xe, 0xc0, 0xc, 0xc0, 0x1c, 0xc0, 0x78, 0xff, 0xf0, 0xff, 0xc0} + +/* E (69) */ +#define NXFONT_METRICS_69 {2, 12, 19, 2, 10, 0} +#define NXFONT_BITMAP_69 {0xff, 0xf0, 0xff, 0xf0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xf0, 0xff, 0xf0} + +/* F (70) */ +#define NXFONT_METRICS_70 {2, 11, 19, 2, 10, 0} +#define NXFONT_BITMAP_70 {0xff, 0xe0, 0xff, 0xe0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* G (71) */ +#define NXFONT_METRICS_71 {2, 16, 19, 1, 10, 0} +#define NXFONT_BITMAP_71 {0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0xe, 0x60, 0x6, 0xe0, 0x6, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x7f, 0xc0, 0x7f, 0xc0, 0x3, 0xc0, 0x3, 0xe0, 0x3, 0x60, 0x7, 0x70, 0xf, 0x3c, 0x3f, 0x1f, 0xfb, 0x7, 0xe3} + +/* H (72) */ +#define NXFONT_METRICS_72 {2, 14, 19, 2, 10, 0} +#define NXFONT_BITMAP_72 {0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xff, 0xfc, 0xff, 0xfc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 2, 19, 3, 10, 0} +#define NXFONT_BITMAP_73 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* J (74) */ +#define NXFONT_METRICS_74 {2, 10, 19, 1, 10, 0} +#define NXFONT_BITMAP_74 {0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x7f, 0x80, 0x3f, 0x0} + +/* K (75) */ +#define NXFONT_METRICS_75 {2, 13, 19, 3, 10, 0} +#define NXFONT_BITMAP_75 {0xc0, 0x38, 0xc0, 0x70, 0xc0, 0xe0, 0xc1, 0xc0, 0xc3, 0x80, 0xc7, 0x0, 0xce, 0x0, 0xdc, 0x0, 0xfc, 0x0, 0xfe, 0x0, 0xe7, 0x0, 0xc3, 0x80, 0xc1, 0x80, 0xc1, 0xc0, 0xc0, 0xe0, 0xc0, 0x60, 0xc0, 0x70, 0xc0, 0x38, 0xc0, 0x18} + +/* L (76) */ +#define NXFONT_METRICS_76 {2, 11, 19, 2, 10, 0} +#define NXFONT_BITMAP_76 {0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xe0, 0xff, 0xe0} + +/* M (77) */ +#define NXFONT_METRICS_77 {3, 17, 19, 2, 10, 0} +#define NXFONT_BITMAP_77 {0xc0, 0x1, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xd8, 0xd, 0x80, 0xd8, 0xd, 0x80, 0xd8, 0xd, 0x80, 0xcc, 0x19, 0x80, 0xcc, 0x19, 0x80, 0xcc, 0x19, 0x80, 0xc6, 0x31, 0x80, 0xc6, 0x31, 0x80, 0xc6, 0x31, 0x80, 0xc3, 0x61, 0x80, 0xc3, 0x61, 0x80, 0xc3, 0x61, 0x80, 0xc1, 0xc1, 0x80, 0xc1, 0xc1, 0x80} + +/* N (78) */ +#define NXFONT_METRICS_78 {2, 14, 19, 2, 10, 0} +#define NXFONT_BITMAP_78 {0xe0, 0xc, 0xf0, 0xc, 0xf0, 0xc, 0xd8, 0xc, 0xdc, 0xc, 0xcc, 0xc, 0xce, 0xc, 0xc6, 0xc, 0xc7, 0xc, 0xc3, 0xc, 0xc3, 0x8c, 0xc1, 0x8c, 0xc1, 0xcc, 0xc0, 0xcc, 0xc0, 0xec, 0xc0, 0x6c, 0xc0, 0x3c, 0xc0, 0x3c, 0xc0, 0x1c} + +/* O (79) */ +#define NXFONT_METRICS_79 {2, 16, 19, 1, 10, 0} +#define NXFONT_BITMAP_79 {0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0xe, 0x60, 0x6, 0xe0, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xe0, 0x7, 0x60, 0x6, 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0} + +/* P (80) */ +#define NXFONT_METRICS_80 {2, 13, 19, 2, 10, 0} +#define NXFONT_BITMAP_80 {0xff, 0xe0, 0xff, 0xf0, 0xc0, 0x30, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x30, 0xff, 0xf0, 0xff, 0xe0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {2, 16, 19, 1, 10, 0} +#define NXFONT_BITMAP_81 {0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0xe, 0x60, 0x6, 0xe0, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xe0, 0x7, 0x60, 0xe6, 0x70, 0x7e, 0x3c, 0x1c, 0x1f, 0xfe, 0x7, 0xe7} + +/* R (82) */ +#define NXFONT_METRICS_82 {2, 13, 19, 2, 10, 0} +#define NXFONT_BITMAP_82 {0xff, 0xe0, 0xff, 0xf0, 0xc0, 0x30, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x30, 0xff, 0xf0, 0xff, 0xe0, 0xc0, 0x70, 0xc0, 0x30, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18} + +/* S (83) */ +#define NXFONT_METRICS_83 {2, 13, 19, 2, 10, 0} +#define NXFONT_BITMAP_83 {0xf, 0x80, 0x3f, 0xe0, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x0, 0xe0, 0x0, 0x7c, 0x0, 0x3f, 0x80, 0x7, 0xe0, 0x0, 0xf0, 0x0, 0x38, 0x0, 0x18, 0x0, 0x18, 0xc0, 0x18, 0xc0, 0x38, 0xf0, 0x70, 0x7f, 0xe0, 0x1f, 0x80} + +/* T (84) */ +#define NXFONT_METRICS_84 {2, 14, 19, 1, 10, 0} +#define NXFONT_BITMAP_84 {0xff, 0xfc, 0xff, 0xfc, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0} + +/* U (85) */ +#define NXFONT_METRICS_85 {2, 14, 19, 2, 10, 0} +#define NXFONT_BITMAP_85 {0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0x60, 0x18, 0x70, 0x38, 0x3f, 0xf0, 0xf, 0xc0} + +/* V (86) */ +#define NXFONT_METRICS_86 {2, 15, 19, 1, 10, 0} +#define NXFONT_BITMAP_86 {0xc0, 0x6, 0xc0, 0x6, 0xe0, 0xe, 0x60, 0xc, 0x70, 0x1c, 0x30, 0x18, 0x30, 0x18, 0x38, 0x38, 0x18, 0x30, 0x18, 0x30, 0x1c, 0x70, 0xc, 0x60, 0xc, 0x60, 0xe, 0xe0, 0x6, 0xc0, 0x6, 0xc0, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80} + +/* W (87) */ +#define NXFONT_METRICS_87 {3, 20, 19, 1, 10, 0} +#define NXFONT_BITMAP_87 {0xc0, 0x60, 0x30, 0xc0, 0x60, 0x30, 0xc0, 0x60, 0x30, 0xc0, 0xf0, 0x30, 0x60, 0xf0, 0x60, 0x61, 0x98, 0x60, 0x61, 0x98, 0x60, 0x61, 0x98, 0x60, 0x61, 0x98, 0x60, 0x31, 0x98, 0xc0, 0x33, 0xc, 0xc0, 0x33, 0xc, 0xc0, 0x33, 0xc, 0xc0, 0x1b, 0xd, 0x80, 0x1b, 0xd, 0x80, 0x1e, 0x7, 0x80, 0xe, 0x7, 0x0, 0xc, 0x3, 0x0, 0xc, 0x3, 0x0} + +/* X (88) */ +#define NXFONT_METRICS_88 {2, 15, 19, 1, 10, 0} +#define NXFONT_BITMAP_88 {0xc0, 0x6, 0xe0, 0xe, 0x70, 0x1c, 0x30, 0x18, 0x18, 0x30, 0x1c, 0x70, 0xe, 0xe0, 0x7, 0xc0, 0x3, 0x80, 0x3, 0x80, 0x7, 0xc0, 0xe, 0xe0, 0xc, 0x60, 0x1c, 0x70, 0x38, 0x38, 0x30, 0x18, 0x60, 0xc, 0xe0, 0xe, 0xc0, 0x6} + +/* Y (89) */ +#define NXFONT_METRICS_89 {2, 14, 19, 1, 10, 0} +#define NXFONT_BITMAP_89 {0xc0, 0xc, 0xe0, 0x1c, 0x60, 0x18, 0x70, 0x38, 0x30, 0x30, 0x38, 0x70, 0x18, 0x60, 0x1c, 0xe0, 0xc, 0xc0, 0xf, 0xc0, 0x7, 0x80, 0x7, 0x80, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {2, 13, 19, 1, 10, 0} +#define NXFONT_BITMAP_90 {0xff, 0xf8, 0xff, 0xf8, 0x0, 0x38, 0x0, 0x70, 0x0, 0xe0, 0x1, 0xc0, 0x1, 0xc0, 0x3, 0x80, 0x7, 0x0, 0x7, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x70, 0x0, 0x70, 0x0, 0xe0, 0x0, 0xff, 0xf8, 0xff, 0xf8} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 4, 24, 2, 10, 0} +#define NXFONT_BITMAP_91 {0xf0, 0xf0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf0, 0xf0} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {1, 8, 19, 0, 10, 0} +#define NXFONT_BITMAP_92 {0xc0, 0x40, 0x40, 0x60, 0x20, 0x20, 0x30, 0x10, 0x10, 0x10, 0x18, 0x8, 0x8, 0xc, 0x4, 0x4, 0x6, 0x2, 0x3} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 4, 24, 1, 10, 0} +#define NXFONT_BITMAP_93 {0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {2, 10, 9, 1, 10, 0} +#define NXFONT_BITMAP_94 {0xc, 0x0, 0xc, 0x0, 0x1e, 0x0, 0x12, 0x0, 0x33, 0x0, 0x61, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {2, 14, 2, 0, 32, 0} +#define NXFONT_BITMAP_95 {0xff, 0xfc, 0xff, 0xfc} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 5, 4, 1, 10, 0} +#define NXFONT_BITMAP_96 {0xc0, 0x60, 0x30, 0x18} + +/* a (97) */ +#define NXFONT_METRICS_97 {2, 11, 14, 1, 15, 0} +#define NXFONT_BITMAP_97 {0x1f, 0x0, 0x3f, 0x80, 0x61, 0xc0, 0x60, 0xc0, 0x0, 0xc0, 0x7, 0xc0, 0x3f, 0xc0, 0x78, 0xc0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0xe3, 0xc0, 0x7e, 0xe0, 0x3c, 0x60} + +/* b (98) */ +#define NXFONT_METRICS_98 {2, 11, 19, 2, 10, 0} +#define NXFONT_BITMAP_98 {0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xcf, 0x0, 0xdf, 0x80, 0xf1, 0xc0, 0xe0, 0xc0, 0xc0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0xf1, 0xc0, 0xdf, 0x80, 0xcf, 0x0} + +/* c (99) */ +#define NXFONT_METRICS_99 {2, 10, 14, 1, 15, 0} +#define NXFONT_BITMAP_99 {0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* d (100) */ +#define NXFONT_METRICS_100 {2, 11, 19, 1, 10, 0} +#define NXFONT_BITMAP_100 {0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x1e, 0x60, 0x3f, 0x60, 0x71, 0xe0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0x60, 0x60, 0xe0, 0x71, 0xe0, 0x3f, 0x60, 0x1e, 0x60} + +/* e (101) */ +#define NXFONT_METRICS_101 {2, 11, 14, 1, 15, 0} +#define NXFONT_BITMAP_101 {0xe, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xc0, 0x60, 0xc0, 0x60, 0xff, 0xe0, 0xff, 0xe0, 0xc0, 0x0, 0xc0, 0x0, 0x60, 0x60, 0x70, 0xe0, 0x3f, 0xc0, 0xf, 0x0} + +/* f (102) */ +#define NXFONT_METRICS_102 {1, 6, 19, 1, 10, 0} +#define NXFONT_BITMAP_102 {0x1c, 0x3c, 0x30, 0x30, 0x30, 0xfc, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* g (103) */ +#define NXFONT_METRICS_103 {2, 11, 19, 1, 15, 0} +#define NXFONT_BITMAP_103 {0x1e, 0x60, 0x3f, 0x60, 0x71, 0xe0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0x60, 0x60, 0xe0, 0x71, 0xe0, 0x3f, 0x60, 0x1e, 0x60, 0x0, 0x60, 0xc0, 0x60, 0xe0, 0xc0, 0x7f, 0xc0, 0x1f, 0x0} + +/* h (104) */ +#define NXFONT_METRICS_104 {2, 10, 19, 2, 10, 0} +#define NXFONT_BITMAP_104 {0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xce, 0x0, 0xdf, 0x80, 0xf1, 0x80, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 2, 19, 2, 10, 0} +#define NXFONT_BITMAP_105 {0xc0, 0xc0, 0xc0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* j (106) */ +#define NXFONT_METRICS_106 {1, 4, 24, 0, 10, 0} +#define NXFONT_BITMAP_106 {0x30, 0x30, 0x30, 0x0, 0x0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xe0} + +/* k (107) */ +#define NXFONT_METRICS_107 {2, 10, 19, 2, 10, 0} +#define NXFONT_BITMAP_107 {0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc1, 0x80, 0xc3, 0x80, 0xc7, 0x0, 0xce, 0x0, 0xdc, 0x0, 0xf8, 0x0, 0xfc, 0x0, 0xce, 0x0, 0xc6, 0x0, 0xc7, 0x0, 0xc3, 0x80, 0xc1, 0x80, 0xc1, 0xc0, 0xc0, 0xc0} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 2, 19, 2, 10, 0} +#define NXFONT_BITMAP_108 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* m (109) */ +#define NXFONT_METRICS_109 {2, 16, 14, 2, 15, 0} +#define NXFONT_BITMAP_109 {0xce, 0x3c, 0xff, 0x7e, 0xe3, 0xc7, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83} + +/* n (110) */ +#define NXFONT_METRICS_110 {2, 10, 14, 2, 15, 0} +#define NXFONT_BITMAP_110 {0xce, 0x0, 0xdf, 0x80, 0xf1, 0x80, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* o (111) */ +#define NXFONT_METRICS_111 {2, 11, 14, 1, 15, 0} +#define NXFONT_BITMAP_111 {0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* p (112) */ +#define NXFONT_METRICS_112 {2, 11, 19, 2, 15, 0} +#define NXFONT_BITMAP_112 {0xcf, 0x0, 0xdf, 0x80, 0xf1, 0xc0, 0xe0, 0xc0, 0xc0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0xf1, 0xc0, 0xdf, 0x80, 0xcf, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* q (113) */ +#define NXFONT_METRICS_113 {2, 11, 19, 1, 15, 0} +#define NXFONT_BITMAP_113 {0x1e, 0x60, 0x3f, 0x60, 0x71, 0xe0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0x60, 0x60, 0xe0, 0x71, 0xe0, 0x3f, 0x60, 0x1e, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60} + +/* r (114) */ +#define NXFONT_METRICS_114 {1, 6, 14, 2, 15, 0} +#define NXFONT_BITMAP_114 {0xcc, 0xdc, 0xf8, 0xf0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* s (115) */ +#define NXFONT_METRICS_115 {2, 10, 14, 1, 15, 0} +#define NXFONT_BITMAP_115 {0x3f, 0x0, 0x7f, 0x80, 0xe1, 0xc0, 0xc0, 0xc0, 0xc0, 0x0, 0xf8, 0x0, 0x7f, 0x0, 0xf, 0x80, 0x1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe1, 0xc0, 0x7f, 0x80, 0x3f, 0x0} + +/* t (116) */ +#define NXFONT_METRICS_116 {1, 6, 18, 1, 11, 0} +#define NXFONT_BITMAP_116 {0x30, 0x30, 0x30, 0x30, 0xfc, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x1c} + +/* u (117) */ +#define NXFONT_METRICS_117 {2, 10, 14, 2, 15, 0} +#define NXFONT_BITMAP_117 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x63, 0xc0, 0x7e, 0xc0, 0x1c, 0xc0} + +/* v (118) */ +#define NXFONT_METRICS_118 {2, 11, 14, 1, 15, 0} +#define NXFONT_BITMAP_118 {0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0x60, 0xc0, 0x60, 0xc0, 0x71, 0xc0, 0x31, 0x80, 0x31, 0x80, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0} + +/* w (119) */ +#define NXFONT_METRICS_119 {3, 18, 14, 0, 15, 0} +#define NXFONT_BITMAP_119 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0xe1, 0x80, 0x61, 0xe1, 0x80, 0x61, 0xe1, 0x80, 0x31, 0x23, 0x0, 0x33, 0x33, 0x0, 0x33, 0x33, 0x0, 0x1b, 0x36, 0x0, 0x1a, 0x16, 0x0, 0x1e, 0x1e, 0x0, 0xe, 0x1c, 0x0, 0xc, 0xc, 0x0, 0xc, 0xc, 0x0} + +/* x (120) */ +#define NXFONT_METRICS_120 {2, 10, 14, 1, 15, 0} +#define NXFONT_BITMAP_120 {0xc0, 0xc0, 0xe1, 0xc0, 0x61, 0x80, 0x33, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xc, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0} + +/* y (121) */ +#define NXFONT_METRICS_121 {2, 12, 19, 0, 15, 0} +#define NXFONT_BITMAP_121 {0xc0, 0x30, 0xc0, 0x30, 0x60, 0x30, 0x70, 0x60, 0x30, 0x60, 0x38, 0xe0, 0x18, 0xc0, 0x18, 0xc0, 0xd, 0x80, 0xd, 0x80, 0x7, 0x80, 0x7, 0x0, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0xc, 0x0, 0x3c, 0x0, 0x38, 0x0} + +/* z (122) */ +#define NXFONT_METRICS_122 {2, 10, 14, 1, 15, 0} +#define NXFONT_BITMAP_122 {0xff, 0xc0, 0xff, 0xc0, 0x1, 0x80, 0x3, 0x0, 0x7, 0x0, 0xe, 0x0, 0xc, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x30, 0x0, 0x60, 0x0, 0xe0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {1, 6, 24, 1, 10, 0} +#define NXFONT_BITMAP_123 {0xc, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0xc0, 0xc0, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0xc} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 1, 24, 2, 10, 0} +#define NXFONT_BITMAP_124 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 6, 24, 1, 10, 0} +#define NXFONT_BITMAP_125 {0xc0, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0xc, 0xc, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0xc0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {2, 10, 4, 2, 20, 0} +#define NXFONT_BITMAP_126 {0x70, 0xc0, 0xfc, 0xc0, 0xcf, 0xc0, 0xc3, 0x80} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 2, 19, 2, 15, 0} +#define NXFONT_BITMAP_161 {0xc0, 0xc0, 0xc0, 0x0, 0x0, 0x40, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* cent (162) */ +#define NXFONT_METRICS_162 {2, 10, 18, 1, 13, 0} +#define NXFONT_BITMAP_162 {0x1, 0x80, 0x1, 0x80, 0x1f, 0x0, 0x3f, 0x80, 0x73, 0xc0, 0x66, 0xc0, 0xc6, 0x0, 0xcc, 0x0, 0xcc, 0x0, 0xcc, 0x0, 0xd8, 0x0, 0xd8, 0x0, 0xd8, 0xc0, 0x71, 0xc0, 0x7f, 0x80, 0x3f, 0x0, 0x60, 0x0, 0x60, 0x0} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {2, 12, 18, 1, 11, 0} +#define NXFONT_BITMAP_163 {0x1f, 0x80, 0x3f, 0xe0, 0x70, 0x70, 0x60, 0x30, 0x60, 0x0, 0x70, 0x0, 0x30, 0x0, 0x18, 0x0, 0xff, 0x80, 0xff, 0x80, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x30, 0x0, 0x30, 0x0, 0x67, 0x30, 0xff, 0xf0, 0xf0, 0xe0} + +/* currency (164) */ +#define NXFONT_METRICS_164 {2, 11, 12, 1, 14, 0} +#define NXFONT_BITMAP_164 {0xc0, 0x60, 0xee, 0xe0, 0x7f, 0xc0, 0x31, 0x80, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x31, 0x80, 0x7f, 0xc0, 0xee, 0xe0, 0xc0, 0x60} + +/* yen (165) */ +#define NXFONT_METRICS_165 {2, 14, 18, 0, 11, 0} +#define NXFONT_BITMAP_165 {0xe0, 0x1c, 0x60, 0x18, 0x70, 0x38, 0x30, 0x30, 0x38, 0x70, 0x18, 0x60, 0x1c, 0xe0, 0xc, 0xc0, 0x3f, 0xf0, 0x3f, 0xf0, 0x3, 0x0, 0x3f, 0xf0, 0x3f, 0xf0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 2, 24, 2, 10, 0} +#define NXFONT_BITMAP_166 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* section (167) */ +#define NXFONT_METRICS_167 {2, 11, 24, 1, 10, 0} +#define NXFONT_BITMAP_167 {0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0x70, 0xc0, 0x38, 0x0, 0x1c, 0x0, 0x7e, 0x0, 0xe7, 0x0, 0xc3, 0x80, 0xc1, 0xc0, 0xc0, 0xc0, 0x60, 0x60, 0x70, 0x60, 0x38, 0x60, 0x1c, 0xc0, 0xf, 0x80, 0x7, 0x0, 0x3, 0x80, 0x61, 0xc0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 6, 2, 1, 11, 0} +#define NXFONT_BITMAP_168 {0xcc, 0xcc} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {3, 19, 19, 1, 10, 0} +#define NXFONT_BITMAP_169 {0x3, 0xf8, 0x0, 0xe, 0xe, 0x0, 0x30, 0x1, 0x80, 0x60, 0x0, 0xc0, 0x41, 0xf0, 0x40, 0xc3, 0x18, 0x60, 0x86, 0xc, 0x20, 0x84, 0x0, 0x20, 0x84, 0x0, 0x20, 0x84, 0x0, 0x20, 0x84, 0x0, 0x20, 0x86, 0xc, 0x20, 0xc3, 0x18, 0x60, 0x41, 0xf0, 0x40, 0x60, 0x0, 0xc0, 0x30, 0x1, 0x80, 0x18, 0x3, 0x0, 0xe, 0xe, 0x0, 0x3, 0xf8, 0x0} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {1, 7, 12, 1, 10, 0} +#define NXFONT_BITMAP_170 {0x78, 0xcc, 0xcc, 0x1c, 0x6c, 0xcc, 0xcc, 0xdc, 0x76, 0x0, 0xfe, 0xfe} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {2, 9, 8, 2, 18, 0} +#define NXFONT_BITMAP_171 {0x19, 0x80, 0x33, 0x0, 0x66, 0x0, 0xcc, 0x0, 0xcc, 0x0, 0x66, 0x0, 0x33, 0x0, 0x19, 0x80} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {2, 13, 8, 1, 19, 0} +#define NXFONT_BITMAP_172 {0xff, 0xf8, 0xff, 0xf8, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 6, 2, 1, 21, 0} +#define NXFONT_BITMAP_173 {0xfc, 0xfc} + +/* registered (174) */ +#define NXFONT_METRICS_174 {3, 18, 19, 1, 10, 0} +#define NXFONT_BITMAP_174 {0x7, 0xf8, 0x0, 0x1c, 0xe, 0x0, 0x30, 0x3, 0x0, 0x60, 0x1, 0x80, 0x43, 0xf0, 0x80, 0xc2, 0x18, 0xc0, 0x82, 0x8, 0x40, 0x82, 0x8, 0x40, 0x82, 0x8, 0x40, 0x82, 0x10, 0x40, 0x83, 0xf0, 0x40, 0x82, 0x20, 0x40, 0x82, 0x10, 0x40, 0xc2, 0x10, 0xc0, 0x42, 0x8, 0x80, 0x60, 0x1, 0x80, 0x30, 0x3, 0x0, 0x1c, 0xe, 0x0, 0x7, 0xf8, 0x0} + +/* macron (175) */ +#define NXFONT_METRICS_175 {1, 6, 2, 1, 11, 0} +#define NXFONT_BITMAP_175 {0xfc, 0xfc} + +/* degree (176) */ +#define NXFONT_METRICS_176 {1, 8, 7, 0, 11, 0} +#define NXFONT_BITMAP_176 {0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0x66, 0x3c} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {2, 12, 13, 1, 16, 0} +#define NXFONT_BITMAP_177 {0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x0, 0x0, 0xff, 0xf0, 0xff, 0xf0} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {1, 7, 10, 0, 11, 0} +#define NXFONT_BITMAP_178 {0x3c, 0x7e, 0xc6, 0x6, 0xc, 0x18, 0x30, 0x60, 0xfe, 0xfe} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {1, 7, 10, 0, 11, 0} +#define NXFONT_BITMAP_179 {0x7c, 0xfe, 0xc6, 0x6, 0x3c, 0x3c, 0x6, 0xc6, 0xfe, 0x7c} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 5, 4, 1, 10, 0} +#define NXFONT_BITMAP_180 {0x18, 0x30, 0x60, 0xc0} + +/* mu (181) */ +#define NXFONT_METRICS_181 {2, 10, 19, 2, 15, 0} +#define NXFONT_BITMAP_181 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0xe3, 0xc0, 0xfe, 0xc0, 0xdc, 0xc0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {2, 10, 24, 1, 10, 0} +#define NXFONT_BITMAP_182 {0x1f, 0xc0, 0x7f, 0xc0, 0x7d, 0x80, 0xfd, 0x80, 0xfd, 0x80, 0xfd, 0x80, 0xfd, 0x80, 0xfd, 0x80, 0xfd, 0x80, 0x7d, 0x80, 0x7d, 0x80, 0x3d, 0x80, 0xd, 0x80, 0xd, 0x80, 0xd, 0x80, 0xd, 0x80, 0xd, 0x80, 0xd, 0x80, 0xd, 0x80, 0xd, 0x80, 0xd, 0x80, 0xd, 0x80, 0xd, 0x80, 0xd, 0x80} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 2, 3, 2, 20, 0} +#define NXFONT_BITMAP_183 {0xc0, 0xc0, 0xc0} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 5, 6, 1, 28, 0} +#define NXFONT_BITMAP_184 {0x60, 0x70, 0x18, 0x18, 0xf8, 0x70} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 4, 10, 0, 11, 0} +#define NXFONT_BITMAP_185 {0x30, 0x30, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {1, 7, 12, 1, 10, 0} +#define NXFONT_BITMAP_186 {0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x0, 0xfe, 0xfe} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {2, 9, 8, 3, 18, 0} +#define NXFONT_BITMAP_187 {0xcc, 0x0, 0x66, 0x0, 0x33, 0x0, 0x19, 0x80, 0x19, 0x80, 0x33, 0x0, 0x66, 0x0, 0xcc, 0x0} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {3, 18, 18, 1, 11, 0} +#define NXFONT_BITMAP_188 {0x30, 0x18, 0x0, 0x30, 0x18, 0x0, 0xf0, 0x30, 0x0, 0xf0, 0x30, 0x0, 0x30, 0x60, 0x0, 0x30, 0x60, 0x0, 0x30, 0xc0, 0x0, 0x30, 0xc0, 0x0, 0x31, 0x83, 0x0, 0x31, 0x87, 0x0, 0x3, 0xf, 0x0, 0x3, 0xf, 0x0, 0x6, 0x1b, 0x0, 0x6, 0x33, 0x0, 0xc, 0x7f, 0xc0, 0xc, 0x7f, 0xc0, 0x18, 0x3, 0x0, 0x18, 0x3, 0x0} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {3, 18, 18, 1, 11, 0} +#define NXFONT_BITMAP_189 {0x30, 0x18, 0x0, 0x30, 0x18, 0x0, 0xf0, 0x30, 0x0, 0xf0, 0x30, 0x0, 0x30, 0x60, 0x0, 0x30, 0x60, 0x0, 0x30, 0xc0, 0x0, 0x30, 0xc0, 0x0, 0x31, 0x87, 0x80, 0x31, 0x8f, 0xc0, 0x3, 0x18, 0xc0, 0x3, 0x0, 0xc0, 0x6, 0x1, 0x80, 0x6, 0x3, 0x0, 0xc, 0x6, 0x0, 0xc, 0xc, 0x0, 0x18, 0x1f, 0xc0, 0x18, 0x1f, 0xc0} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {3, 19, 18, 0, 11, 0} +#define NXFONT_BITMAP_190 {0x7c, 0xc, 0x0, 0xfe, 0xc, 0x0, 0xc6, 0x18, 0x0, 0x6, 0x18, 0x0, 0x3c, 0x30, 0x0, 0x3c, 0x30, 0x0, 0x6, 0x60, 0x0, 0xc6, 0x60, 0x0, 0xfe, 0xc1, 0x80, 0x7c, 0xc3, 0x80, 0x1, 0x87, 0x80, 0x1, 0x87, 0x80, 0x3, 0xd, 0x80, 0x3, 0x19, 0x80, 0x6, 0x3f, 0xe0, 0x6, 0x3f, 0xe0, 0xc, 0x1, 0x80, 0xc, 0x1, 0x80} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {2, 10, 19, 1, 15, 0} +#define NXFONT_BITMAP_191 {0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0x18, 0x0, 0x38, 0x0, 0x70, 0x0, 0x60, 0x0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0xe3, 0x80, 0x7f, 0x80, 0x3e, 0x0} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {2, 15, 24, 1, 5, 0} +#define NXFONT_BITMAP_192 {0xc, 0x0, 0x6, 0x0, 0x3, 0x0, 0x1, 0x80, 0x0, 0x0, 0x3, 0x80, 0x3, 0x80, 0x6, 0xc0, 0x6, 0xc0, 0xc, 0x40, 0xc, 0x60, 0xc, 0x60, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x18, 0x3f, 0xf8, 0x3f, 0xf8, 0x60, 0xc, 0x60, 0xc, 0x60, 0xc, 0xc0, 0x6, 0xc0, 0x6, 0xc0, 0x6} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {2, 15, 24, 1, 5, 0} +#define NXFONT_BITMAP_193 {0x0, 0x60, 0x0, 0xc0, 0x1, 0x80, 0x3, 0x0, 0x0, 0x0, 0x3, 0x80, 0x3, 0x80, 0x6, 0xc0, 0x6, 0xc0, 0xc, 0x40, 0xc, 0x60, 0xc, 0x60, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x18, 0x3f, 0xf8, 0x3f, 0xf8, 0x60, 0xc, 0x60, 0xc, 0x60, 0xc, 0xc0, 0x6, 0xc0, 0x6, 0xc0, 0x6} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {2, 15, 24, 1, 5, 0} +#define NXFONT_BITMAP_194 {0x1, 0x80, 0x3, 0xc0, 0x6, 0x60, 0xc, 0x30, 0x0, 0x0, 0x3, 0x80, 0x3, 0x80, 0x6, 0xc0, 0x6, 0xc0, 0xc, 0x40, 0xc, 0x60, 0xc, 0x60, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x18, 0x3f, 0xf8, 0x3f, 0xf8, 0x60, 0xc, 0x60, 0xc, 0x60, 0xc, 0xc0, 0x6, 0xc0, 0x6, 0xc0, 0x6} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {2, 15, 23, 1, 6, 0} +#define NXFONT_BITMAP_195 {0x7, 0x10, 0xd, 0xb0, 0x8, 0xe0, 0x0, 0x0, 0x3, 0x80, 0x3, 0x80, 0x6, 0xc0, 0x6, 0xc0, 0xc, 0x40, 0xc, 0x60, 0xc, 0x60, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x18, 0x3f, 0xf8, 0x3f, 0xf8, 0x60, 0xc, 0x60, 0xc, 0x60, 0xc, 0xc0, 0x6, 0xc0, 0x6, 0xc0, 0x6} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {2, 15, 23, 1, 6, 0} +#define NXFONT_BITMAP_196 {0xc, 0x60, 0xc, 0x60, 0x0, 0x0, 0x0, 0x0, 0x3, 0x80, 0x3, 0x80, 0x6, 0xc0, 0x6, 0xc0, 0xc, 0x40, 0xc, 0x60, 0xc, 0x60, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x18, 0x3f, 0xf8, 0x3f, 0xf8, 0x60, 0xc, 0x60, 0xc, 0x60, 0xc, 0xc0, 0x6, 0xc0, 0x6, 0xc0, 0x6} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {2, 15, 24, 1, 5, 0} +#define NXFONT_BITMAP_197 {0x3, 0x80, 0x4, 0x40, 0x4, 0x40, 0x3, 0x80, 0x0, 0x0, 0x3, 0x80, 0x3, 0x80, 0x6, 0xc0, 0x6, 0xc0, 0xc, 0x40, 0xc, 0x60, 0xc, 0x60, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x18, 0x3f, 0xf8, 0x3f, 0xf8, 0x60, 0xc, 0x60, 0xc, 0x60, 0xc, 0xc0, 0x6, 0xc0, 0x6, 0xc0, 0x6} + +/* AE (198) */ +#define NXFONT_METRICS_198 {3, 21, 19, 1, 10, 0} +#define NXFONT_BITMAP_198 {0x3, 0xff, 0xf8, 0x3, 0xff, 0xf8, 0x6, 0x60, 0x0, 0x6, 0x60, 0x0, 0xc, 0x60, 0x0, 0xc, 0x60, 0x0, 0xc, 0x60, 0x0, 0x18, 0x60, 0x0, 0x18, 0x7f, 0xf8, 0x18, 0x7f, 0xf8, 0x30, 0x60, 0x0, 0x3f, 0xe0, 0x0, 0x3f, 0xe0, 0x0, 0x60, 0x60, 0x0, 0x60, 0x60, 0x0, 0x60, 0x60, 0x0, 0xc0, 0x60, 0x0, 0xc0, 0x7f, 0xf8, 0xc0, 0x7f, 0xf8} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {2, 15, 24, 1, 10, 0} +#define NXFONT_BITMAP_199 {0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0xe, 0x60, 0x6, 0xe0, 0x6, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x6, 0x60, 0x6, 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, 0x1, 0x80, 0x0, 0xc0, 0x0, 0xc0, 0x7, 0xc0, 0x3, 0x80} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {2, 12, 24, 2, 5, 0} +#define NXFONT_BITMAP_200 {0x30, 0x0, 0x18, 0x0, 0xc, 0x0, 0x6, 0x0, 0x0, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xf0, 0xff, 0xf0} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {2, 12, 24, 2, 5, 0} +#define NXFONT_BITMAP_201 {0x1, 0x80, 0x3, 0x0, 0x6, 0x0, 0xc, 0x0, 0x0, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xf0, 0xff, 0xf0} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {2, 12, 24, 2, 5, 0} +#define NXFONT_BITMAP_202 {0x6, 0x0, 0xf, 0x0, 0x19, 0x80, 0x30, 0xc0, 0x0, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xf0, 0xff, 0xf0} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {2, 12, 23, 2, 6, 0} +#define NXFONT_BITMAP_203 {0x18, 0xc0, 0x18, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xf0, 0xff, 0xf0} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {1, 5, 24, 1, 5, 0} +#define NXFONT_BITMAP_204 {0xc0, 0x60, 0x30, 0x18, 0x0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 5, 24, 2, 5, 0} +#define NXFONT_BITMAP_205 {0x18, 0x30, 0x60, 0xc0, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* Icircumflex (206) */ +#define NXFONT_METRICS_206 {1, 8, 24, 0, 5, 0} +#define NXFONT_BITMAP_206 {0x18, 0x3c, 0x66, 0xc3, 0x0, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {1, 6, 23, 1, 6, 0} +#define NXFONT_BITMAP_207 {0xcc, 0xcc, 0x0, 0x0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* Eth (208) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_208 {3, 18, 19, 0, 10, 0} +#define NXFONT_BITMAP_208 {0x1f, 0xf8, 0x0, 0x1f, 0xfe, 0x0, 0x18, 0xf, 0x0, 0x18, 0x3, 0x80, 0x18, 0x1, 0x80, 0x18, 0x1, 0xc0, 0x18, 0x0, 0xc0, 0x18, 0x0, 0xc0, 0xff, 0x80, 0xc0, 0xff, 0x80, 0xc0, 0x18, 0x0, 0xc0, 0x18, 0x0, 0xc0, 0x18, 0x0, 0xc0, 0x18, 0x1, 0xc0, 0x18, 0x1, 0x80, 0x18, 0x3, 0x80, 0x18, 0xf, 0x0, 0x1f, 0xfe, 0x0, 0x1f, 0xf8, 0x0} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {2, 14, 23, 2, 6, 0} +#define NXFONT_BITMAP_209 {0xe, 0x20, 0x1b, 0x60, 0x11, 0xc0, 0x0, 0x0, 0xe0, 0xc, 0xf0, 0xc, 0xf0, 0xc, 0xd8, 0xc, 0xdc, 0xc, 0xcc, 0xc, 0xce, 0xc, 0xc6, 0xc, 0xc7, 0xc, 0xc3, 0xc, 0xc3, 0x8c, 0xc1, 0x8c, 0xc1, 0xcc, 0xc0, 0xcc, 0xc0, 0xec, 0xc0, 0x6c, 0xc0, 0x3c, 0xc0, 0x3c, 0xc0, 0x1c} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {2, 16, 24, 1, 5, 0} +#define NXFONT_BITMAP_210 {0xc, 0x0, 0x6, 0x0, 0x3, 0x0, 0x1, 0x80, 0x0, 0x0, 0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0xe, 0x60, 0x6, 0xe0, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xe0, 0x7, 0x60, 0x6, 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {2, 16, 24, 1, 5, 0} +#define NXFONT_BITMAP_211 {0x0, 0x30, 0x0, 0x60, 0x0, 0xc0, 0x1, 0x80, 0x0, 0x0, 0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0xe, 0x60, 0x6, 0xe0, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xe0, 0x7, 0x60, 0x6, 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {2, 16, 24, 1, 5, 0} +#define NXFONT_BITMAP_212 {0x0, 0xc0, 0x1, 0xe0, 0x3, 0x30, 0x6, 0x18, 0x0, 0x0, 0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0xe, 0x60, 0x6, 0xe0, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xe0, 0x7, 0x60, 0x6, 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {2, 16, 23, 1, 6, 0} +#define NXFONT_BITMAP_213 {0x3, 0x88, 0x6, 0xd8, 0x4, 0x70, 0x0, 0x0, 0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0xe, 0x60, 0x6, 0xe0, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xe0, 0x7, 0x60, 0x6, 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {2, 16, 23, 1, 6, 0} +#define NXFONT_BITMAP_214 {0x6, 0x30, 0x6, 0x30, 0x0, 0x0, 0x0, 0x0, 0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0xe, 0x60, 0x6, 0xe0, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xe0, 0x7, 0x60, 0x6, 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {2, 13, 12, 0, 16, 0} +#define NXFONT_BITMAP_215 {0xc0, 0x18, 0x60, 0x30, 0x30, 0x60, 0x18, 0xc0, 0xd, 0x80, 0x7, 0x0, 0x7, 0x0, 0xd, 0x80, 0x18, 0xc0, 0x30, 0x60, 0x60, 0x30, 0xc0, 0x18} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {3, 18, 19, 0, 10, 0} +#define NXFONT_BITMAP_216 {0x3, 0xf0, 0xc0, 0xf, 0xfd, 0xc0, 0x1e, 0x1f, 0x80, 0x38, 0x7, 0x0, 0x30, 0xf, 0x0, 0x70, 0x1d, 0x80, 0x60, 0x39, 0x80, 0x60, 0x71, 0x80, 0x60, 0xe1, 0x80, 0x61, 0xc1, 0x80, 0x63, 0x81, 0x80, 0x67, 0x1, 0x80, 0x6e, 0x1, 0x80, 0x7c, 0x3, 0x80, 0x38, 0x3, 0x0, 0x38, 0x7, 0x0, 0x7e, 0x1e, 0x0, 0xef, 0xfc, 0x0, 0xc3, 0xf0, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {2, 14, 24, 2, 5, 0} +#define NXFONT_BITMAP_217 {0x18, 0x0, 0xc, 0x0, 0x6, 0x0, 0x3, 0x0, 0x0, 0x0, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0x60, 0x18, 0x70, 0x38, 0x3f, 0xf0, 0xf, 0xc0} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {2, 14, 24, 2, 5, 0} +#define NXFONT_BITMAP_218 {0x0, 0x60, 0x0, 0xc0, 0x1, 0x80, 0x3, 0x0, 0x0, 0x0, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0x60, 0x18, 0x70, 0x38, 0x3f, 0xf0, 0xf, 0xc0} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {2, 14, 24, 2, 5, 0} +#define NXFONT_BITMAP_219 {0x3, 0x0, 0x7, 0x80, 0xc, 0xc0, 0x18, 0x60, 0x0, 0x0, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0x60, 0x18, 0x70, 0x38, 0x3f, 0xf0, 0xf, 0xc0} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {2, 14, 23, 2, 6, 0} +#define NXFONT_BITMAP_220 {0x18, 0xc0, 0x18, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0x60, 0x18, 0x70, 0x38, 0x3f, 0xf0, 0xf, 0xc0} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {2, 14, 24, 1, 5, 0} +#define NXFONT_BITMAP_221 {0x0, 0x60, 0x0, 0xc0, 0x1, 0x80, 0x3, 0x0, 0x0, 0x0, 0xc0, 0xc, 0xe0, 0x1c, 0x60, 0x18, 0x70, 0x38, 0x30, 0x30, 0x38, 0x70, 0x18, 0x60, 0x1c, 0xe0, 0xc, 0xc0, 0xf, 0xc0, 0x7, 0x80, 0x7, 0x80, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {2, 13, 19, 2, 10, 0} +#define NXFONT_BITMAP_222 {0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xe0, 0xff, 0xf0, 0xc0, 0x30, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x30, 0xff, 0xf0, 0xff, 0xe0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {2, 10, 19, 3, 10, 0} +#define NXFONT_BITMAP_223 {0x1c, 0x0, 0x7f, 0x0, 0xe3, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc3, 0x0, 0xc7, 0x0, 0xce, 0x0, 0xcf, 0x0, 0xc3, 0x80, 0xc1, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0x80, 0xc3, 0x80, 0xcf, 0x0, 0xce, 0x0} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {2, 11, 19, 1, 10, 0} +#define NXFONT_BITMAP_224 {0x18, 0x0, 0xc, 0x0, 0x6, 0x0, 0x3, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x61, 0xc0, 0x60, 0xc0, 0x0, 0xc0, 0x7, 0xc0, 0x3f, 0xc0, 0x78, 0xc0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0xe3, 0xc0, 0x7e, 0xe0, 0x3c, 0x60} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {2, 11, 19, 1, 10, 0} +#define NXFONT_BITMAP_225 {0x1, 0x80, 0x3, 0x0, 0x6, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x61, 0xc0, 0x60, 0xc0, 0x0, 0xc0, 0x7, 0xc0, 0x3f, 0xc0, 0x78, 0xc0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0xe3, 0xc0, 0x7e, 0xe0, 0x3c, 0x60} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {2, 11, 19, 1, 10, 0} +#define NXFONT_BITMAP_226 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x61, 0x80, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x61, 0xc0, 0x60, 0xc0, 0x0, 0xc0, 0x7, 0xc0, 0x3f, 0xc0, 0x78, 0xc0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0xe3, 0xc0, 0x7e, 0xe0, 0x3c, 0x60} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_227 {0x1c, 0x40, 0x36, 0xc0, 0x23, 0x80, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x61, 0xc0, 0x60, 0xc0, 0x0, 0xc0, 0x7, 0xc0, 0x3f, 0xc0, 0x78, 0xc0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0xe3, 0xc0, 0x7e, 0xe0, 0x3c, 0x60} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_228 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x61, 0xc0, 0x60, 0xc0, 0x0, 0xc0, 0x7, 0xc0, 0x3f, 0xc0, 0x78, 0xc0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0xe3, 0xc0, 0x7e, 0xe0, 0x3c, 0x60} + +/* aring (229) */ +#define NXFONT_METRICS_229 {2, 11, 19, 1, 10, 0} +#define NXFONT_BITMAP_229 {0x6, 0x0, 0x9, 0x0, 0x9, 0x0, 0x6, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x61, 0xc0, 0x60, 0xc0, 0x0, 0xc0, 0x7, 0xc0, 0x3f, 0xc0, 0x78, 0xc0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0xe3, 0xc0, 0x7e, 0xe0, 0x3c, 0x60} + +/* ae (230) */ +#define NXFONT_METRICS_230 {3, 19, 14, 1, 15, 0} +#define NXFONT_BITMAP_230 {0x1f, 0xe, 0x0, 0x3f, 0xbf, 0x80, 0x61, 0xf1, 0xc0, 0x60, 0xe0, 0xc0, 0x0, 0xc0, 0x60, 0x7, 0xc0, 0x60, 0x3f, 0xff, 0xe0, 0x78, 0xff, 0xe0, 0xe0, 0xc0, 0x0, 0xc0, 0xc0, 0x0, 0xc1, 0xe0, 0x60, 0xe3, 0xf0, 0xe0, 0x7e, 0x3f, 0xc0, 0x3c, 0xf, 0x0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {2, 10, 19, 1, 15, 0} +#define NXFONT_BITMAP_231 {0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0, 0xc, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3e, 0x0, 0x1c, 0x0} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {2, 11, 19, 1, 10, 0} +#define NXFONT_BITMAP_232 {0x18, 0x0, 0xc, 0x0, 0x6, 0x0, 0x3, 0x0, 0x0, 0x0, 0xe, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xc0, 0x60, 0xc0, 0x60, 0xff, 0xe0, 0xff, 0xe0, 0xc0, 0x0, 0xc0, 0x0, 0x60, 0x60, 0x70, 0xe0, 0x3f, 0xc0, 0xf, 0x0} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {2, 11, 19, 1, 10, 0} +#define NXFONT_BITMAP_233 {0x3, 0x0, 0x6, 0x0, 0xc, 0x0, 0x18, 0x0, 0x0, 0x0, 0xe, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xc0, 0x60, 0xc0, 0x60, 0xff, 0xe0, 0xff, 0xe0, 0xc0, 0x0, 0xc0, 0x0, 0x60, 0x60, 0x70, 0xe0, 0x3f, 0xc0, 0xf, 0x0} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {2, 11, 19, 1, 10, 0} +#define NXFONT_BITMAP_234 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x61, 0x80, 0x0, 0x0, 0xe, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xc0, 0x60, 0xc0, 0x60, 0xff, 0xe0, 0xff, 0xe0, 0xc0, 0x0, 0xc0, 0x0, 0x60, 0x60, 0x70, 0xe0, 0x3f, 0xc0, 0xf, 0x0} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_235 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xc0, 0x60, 0xc0, 0x60, 0xff, 0xe0, 0xff, 0xe0, 0xc0, 0x0, 0xc0, 0x0, 0x60, 0x60, 0x70, 0xe0, 0x3f, 0xc0, 0xf, 0x0} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 5, 19, 0, 10, 0} +#define NXFONT_BITMAP_236 {0xc0, 0x60, 0x30, 0x18, 0x0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 5, 19, 1, 10, 0} +#define NXFONT_BITMAP_237 {0x18, 0x30, 0x60, 0xc0, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60} + +/* icircumflex (238) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_238 {1, 8, 19, 0, 10, 0} +#define NXFONT_BITMAP_238 {0x18, 0x3c, 0x66, 0xc3, 0x0, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 6, 18, 0, 11, 0} +#define NXFONT_BITMAP_239 {0xcc, 0xcc, 0x0, 0x0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* eth (240) */ +#define NXFONT_METRICS_240 {2, 11, 19, 1, 10, 0} +#define NXFONT_BITMAP_240 {0x60, 0x0, 0x39, 0x80, 0xe, 0x0, 0x1e, 0x0, 0x63, 0x0, 0x1f, 0x80, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {2, 10, 18, 2, 11, 0} +#define NXFONT_BITMAP_241 {0x38, 0x80, 0x6d, 0x80, 0x47, 0x0, 0x0, 0x0, 0xce, 0x0, 0xdf, 0x80, 0xf1, 0x80, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {2, 11, 19, 1, 10, 0} +#define NXFONT_BITMAP_242 {0x18, 0x0, 0xc, 0x0, 0x6, 0x0, 0x3, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {2, 11, 19, 1, 10, 0} +#define NXFONT_BITMAP_243 {0x3, 0x0, 0x6, 0x0, 0xc, 0x0, 0x18, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {2, 11, 19, 1, 10, 0} +#define NXFONT_BITMAP_244 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x61, 0x80, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_245 {0x1c, 0x40, 0x36, 0xc0, 0x23, 0x80, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {2, 11, 18, 1, 11, 0} +#define NXFONT_BITMAP_246 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0} + +/* divide (247) */ +#define NXFONT_METRICS_247 {2, 12, 12, 1, 16, 0} +#define NXFONT_BITMAP_247 {0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {2, 13, 14, 0, 15, 0} +#define NXFONT_BITMAP_248 {0xf, 0x98, 0x1f, 0xf8, 0x38, 0x70, 0x30, 0xe0, 0x71, 0xf0, 0x63, 0xb0, 0x63, 0x30, 0x66, 0x30, 0x6c, 0x30, 0x7c, 0x70, 0x38, 0x60, 0x70, 0xe0, 0xff, 0xc0, 0xcf, 0x80} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {2, 10, 19, 2, 10, 0} +#define NXFONT_BITMAP_249 {0x30, 0x0, 0x18, 0x0, 0xc, 0x0, 0x6, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x63, 0xc0, 0x7e, 0xc0, 0x1c, 0xc0} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {2, 10, 19, 2, 10, 0} +#define NXFONT_BITMAP_250 {0x3, 0x0, 0x6, 0x0, 0xc, 0x0, 0x18, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x63, 0xc0, 0x7e, 0xc0, 0x1c, 0xc0} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {2, 10, 19, 2, 10, 0} +#define NXFONT_BITMAP_251 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x61, 0x80, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x63, 0xc0, 0x7e, 0xc0, 0x1c, 0xc0} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {2, 10, 18, 2, 11, 0} +#define NXFONT_BITMAP_252 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x63, 0xc0, 0x7e, 0xc0, 0x1c, 0xc0} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {2, 12, 24, 0, 10, 0} +#define NXFONT_BITMAP_253 {0x0, 0xc0, 0x1, 0x80, 0x3, 0x0, 0x6, 0x0, 0x0, 0x0, 0xc0, 0x30, 0xc0, 0x30, 0x60, 0x30, 0x70, 0x60, 0x30, 0x60, 0x38, 0xe0, 0x18, 0xc0, 0x18, 0xc0, 0xd, 0x80, 0xd, 0x80, 0x7, 0x80, 0x7, 0x0, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0xc, 0x0, 0x3c, 0x0, 0x38, 0x0} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {2, 11, 24, 2, 10, 0} +#define NXFONT_BITMAP_254 {0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xcf, 0x0, 0xdf, 0x80, 0xf1, 0xc0, 0xe0, 0xc0, 0xc0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0xe0, 0xe0, 0xc0, 0xf1, 0xc0, 0xdf, 0x80, 0xcf, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {2, 12, 23, 0, 11, 0} +#define NXFONT_BITMAP_255 {0x19, 0x80, 0x19, 0x80, 0x0, 0x0, 0x0, 0x0, 0xc0, 0x30, 0xc0, 0x30, 0x60, 0x30, 0x70, 0x60, 0x30, 0x60, 0x38, 0xe0, 0x18, 0xc0, 0x18, 0xc0, 0xd, 0x80, 0xd, 0x80, 0x7, 0x80, 0x7, 0x0, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0xc, 0x0, 0x3c, 0x0, 0x38, 0x0} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SANS28X37_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_sans28x37b.h b/nuttx/graphics/nxfonts/nxfonts_sans28x37b.h new file mode 100755 index 0000000000..6f368056df --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_sans28x37b.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_sans28x37b.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Jose Pablo Carballo Gomez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SANS28X37B_H +#define __GRAPHICS_NXFONTS_NXFONTS_SANS28X37B_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SANS28X37B + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 37 +#define NXFONT_MAXWIDTH 28 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 6 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 3, 19, 2, 10, 0} +#define NXFONT_BITMAP_33 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0x0, 0x0, 0xe0, 0xe0, 0xe0} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {1, 5, 6, 2, 10, 0} +#define NXFONT_BITMAP_34 {0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x90} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {2, 12, 18, 1, 11, 0} +#define NXFONT_BITMAP_35 {0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0x7f, 0xf0, 0x7f, 0xf0, 0x19, 0x80, 0x19, 0x80, 0x19, 0x80, 0x19, 0x80, 0xff, 0xe0, 0xff, 0xe0, 0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x33, 0x0} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {2, 12, 21, 0, 10, 0} +#define NXFONT_BITMAP_36 {0x6, 0x0, 0x3f, 0x80, 0x7f, 0xe0, 0xf6, 0xe0, 0xe6, 0x70, 0xe6, 0x70, 0xf6, 0x0, 0x7e, 0x0, 0x3e, 0x0, 0xf, 0x0, 0x7, 0xc0, 0x7, 0xe0, 0x6, 0xf0, 0xe6, 0x70, 0xe6, 0x70, 0xe6, 0x70, 0xf6, 0xf0, 0x7f, 0xe0, 0x1f, 0xc0, 0x6, 0x0, 0x6, 0x0} + +/* percent (37) */ +#define NXFONT_METRICS_37 {3, 21, 18, 0, 11, 0} +#define NXFONT_BITMAP_37 {0x0, 0x7, 0x0, 0x3e, 0x7, 0x0, 0x7f, 0xe, 0x0, 0xe3, 0x8e, 0x0, 0xc1, 0x9c, 0x0, 0xc1, 0x9c, 0x0, 0xe3, 0xb8, 0x0, 0x7f, 0x38, 0x0, 0x3e, 0x70, 0x0, 0x0, 0x70, 0x0, 0x0, 0xe3, 0xe0, 0x0, 0xe7, 0xf0, 0x1, 0xce, 0x38, 0x1, 0xcc, 0x18, 0x3, 0x8c, 0x18, 0x3, 0x8e, 0x38, 0x7, 0x7, 0xf0, 0x7, 0x3, 0xe0} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {2, 16, 18, 1, 11, 0} +#define NXFONT_BITMAP_38 {0xf, 0x80, 0x1f, 0xc0, 0x3d, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x1d, 0xc0, 0xf, 0x80, 0x1f, 0x0, 0x3f, 0x9c, 0x7b, 0xdc, 0x71, 0xfc, 0xe0, 0xf8, 0xe0, 0x70, 0xe0, 0xf8, 0xf1, 0xfc, 0x7f, 0xce, 0x1f, 0x87} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 2, 6, 2, 10, 0} +#define NXFONT_BITMAP_39 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 6, 24, 1, 10, 0} +#define NXFONT_BITMAP_40 {0xc, 0x1c, 0x38, 0x38, 0x70, 0x70, 0x60, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x60, 0x70, 0x70, 0x38, 0x38, 0x1c, 0xc} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 6, 24, 1, 10, 0} +#define NXFONT_BITMAP_41 {0xc0, 0xe0, 0x70, 0x70, 0x38, 0x38, 0x18, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x18, 0x38, 0x38, 0x70, 0x70, 0xe0, 0xc0} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {1, 8, 7, 1, 10, 0} +#define NXFONT_BITMAP_42 {0x18, 0x18, 0xdb, 0xff, 0x3c, 0x66, 0x66} + +/* plus (43) */ +#define NXFONT_METRICS_43 {2, 12, 12, 1, 16, 0} +#define NXFONT_BITMAP_43 {0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 3, 6, 2, 26, 0} +#define NXFONT_BITMAP_44 {0xe0, 0xe0, 0xe0, 0x60, 0x60, 0xc0} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 7, 3, 0, 20, 0} +#define NXFONT_BITMAP_45 {0xfe, 0xfe, 0xfe} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 3, 3, 2, 26, 0} +#define NXFONT_BITMAP_46 {0xe0, 0xe0, 0xe0} + +/* slash (47) */ +#define NXFONT_METRICS_47 {1, 7, 19, 1, 10, 0} +#define NXFONT_BITMAP_47 {0x6, 0x6, 0x6, 0xc, 0xc, 0xc, 0x18, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x60, 0x60, 0x60, 0xc0, 0xc0, 0xc0} + +/* zero (48) */ +#define NXFONT_METRICS_48 {2, 12, 18, 0, 11, 0} +#define NXFONT_BITMAP_48 {0x1f, 0x80, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x70, 0xe0, 0x79, 0xe0, 0x3f, 0xc0, 0x1f, 0x80} + +/* one (49) */ +#define NXFONT_METRICS_49 {1, 7, 18, 2, 11, 0} +#define NXFONT_BITMAP_49 {0xe, 0xe, 0x1e, 0xfe, 0xfe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe} + +/* two (50) */ +#define NXFONT_METRICS_50 {2, 12, 18, 0, 11, 0} +#define NXFONT_BITMAP_50 {0x1f, 0x0, 0x7f, 0xc0, 0x71, 0xe0, 0xe0, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0x0, 0x70, 0x0, 0xe0, 0x1, 0xe0, 0x3, 0xc0, 0x7, 0x80, 0x1f, 0x0, 0x3c, 0x0, 0x78, 0x0, 0xf0, 0x0, 0xe0, 0x0, 0xff, 0xf0, 0xff, 0xf0} + +/* three (51) */ +#define NXFONT_METRICS_51 {2, 12, 18, 0, 11, 0} +#define NXFONT_BITMAP_51 {0x1f, 0x0, 0x7f, 0xc0, 0x71, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x0, 0xe0, 0x1, 0xc0, 0xf, 0x80, 0xf, 0xe0, 0x0, 0xe0, 0x0, 0x70, 0x0, 0x70, 0xe0, 0x70, 0xe0, 0xf0, 0x71, 0xe0, 0x7f, 0xe0, 0x1f, 0x80} + +/* four (52) */ +#define NXFONT_METRICS_52 {2, 12, 18, 0, 11, 0} +#define NXFONT_BITMAP_52 {0x1, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xc0, 0x7, 0xc0, 0xd, 0xc0, 0x1d, 0xc0, 0x19, 0xc0, 0x31, 0xc0, 0x71, 0xc0, 0x61, 0xc0, 0xe1, 0xc0, 0xff, 0xf0, 0xff, 0xf0, 0x1, 0xc0, 0x1, 0xc0, 0x1, 0xc0, 0x1, 0xc0} + +/* five (53) */ +#define NXFONT_METRICS_53 {2, 12, 18, 0, 11, 0} +#define NXFONT_BITMAP_53 {0x7f, 0xe0, 0x7f, 0xe0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x7f, 0x80, 0x7f, 0xc0, 0x71, 0xe0, 0x0, 0xe0, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0xe0, 0x70, 0xe0, 0xf0, 0xf1, 0xe0, 0x7f, 0xc0, 0x1f, 0x80} + +/* six (54) */ +#define NXFONT_METRICS_54 {2, 12, 18, 0, 11, 0} +#define NXFONT_BITMAP_54 {0xf, 0x80, 0x3f, 0xe0, 0x78, 0xe0, 0x70, 0x70, 0xe0, 0x70, 0xe0, 0x0, 0xe0, 0x0, 0xef, 0x0, 0xff, 0xc0, 0xf9, 0xe0, 0xf0, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x79, 0xe0, 0x3f, 0xc0, 0x1f, 0x80} + +/* seven (55) */ +#define NXFONT_METRICS_55 {2, 12, 18, 0, 11, 0} +#define NXFONT_BITMAP_55 {0xff, 0xf0, 0xff, 0xf0, 0x0, 0xf0, 0x0, 0xe0, 0x1, 0xc0, 0x1, 0xc0, 0x3, 0x80, 0x3, 0x80, 0x7, 0x0, 0x7, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1e, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x3c, 0x0, 0x38, 0x0, 0x38, 0x0} + +/* eight (56) */ +#define NXFONT_METRICS_56 {2, 12, 18, 0, 11, 0} +#define NXFONT_BITMAP_56 {0xf, 0x0, 0x3f, 0xc0, 0x39, 0xc0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x39, 0xc0, 0x1f, 0x80, 0x3f, 0xc0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x7f, 0xe0, 0x1f, 0x80} + +/* nine (57) */ +#define NXFONT_METRICS_57 {2, 12, 18, 0, 11, 0} +#define NXFONT_BITMAP_57 {0x1f, 0x80, 0x7f, 0xc0, 0x79, 0xe0, 0xf0, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xf0, 0xf0, 0x79, 0xf0, 0x7f, 0xf0, 0x1f, 0x70, 0x0, 0x70, 0x0, 0x70, 0xe0, 0xe0, 0xf3, 0xe0, 0x7f, 0xc0, 0x1f, 0x0} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 3, 14, 2, 15, 0} +#define NXFONT_BITMAP_58 {0xe0, 0xe0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0xe0, 0xe0} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 3, 17, 2, 15, 0} +#define NXFONT_BITMAP_59 {0xe0, 0xe0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0xe0, 0xe0, 0x60, 0x60, 0xc0} + +/* less (60) */ +#define NXFONT_METRICS_60 {2, 13, 12, 0, 16, 0} +#define NXFONT_BITMAP_60 {0x0, 0x38, 0x0, 0xf8, 0x3, 0xe0, 0xf, 0x80, 0x3e, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0x3e, 0x0, 0xf, 0x80, 0x3, 0xe0, 0x0, 0xf8, 0x0, 0x38} + +/* equal (61) */ +#define NXFONT_METRICS_61 {2, 10, 5, 2, 19, 0} +#define NXFONT_BITMAP_61 {0xff, 0xc0, 0xff, 0xc0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* greater (62) */ +#define NXFONT_METRICS_62 {2, 13, 12, 1, 16, 0} +#define NXFONT_BITMAP_62 {0xe0, 0x0, 0xf8, 0x0, 0x3e, 0x0, 0xf, 0x80, 0x3, 0xe0, 0x0, 0x78, 0x0, 0x78, 0x3, 0xe0, 0xf, 0x80, 0x3e, 0x0, 0xf8, 0x0, 0xe0, 0x0} + +/* question (63) */ +#define NXFONT_METRICS_63 {2, 11, 19, 2, 10, 0} +#define NXFONT_BITMAP_63 {0x1f, 0x80, 0x7f, 0xc0, 0x79, 0xe0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0x1, 0xc0, 0x3, 0xc0, 0x7, 0x80, 0x7, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0} + +/* at (64) */ +#define NXFONT_METRICS_64 {3, 22, 22, 1, 11, 0} +#define NXFONT_BITMAP_64 {0x1, 0xff, 0x0, 0x7, 0xff, 0xc0, 0xf, 0x81, 0xf0, 0x1e, 0x0, 0x78, 0x3c, 0x0, 0x38, 0x78, 0x7d, 0x9c, 0x70, 0xff, 0x9c, 0xf1, 0xc7, 0x1c, 0xe3, 0x87, 0x1c, 0xe3, 0xe, 0x1c, 0xe7, 0xe, 0x38, 0xe7, 0xc, 0x38, 0xe7, 0x1c, 0x70, 0xe7, 0x1c, 0x70, 0xe3, 0x9d, 0xe0, 0xf3, 0xff, 0xc0, 0x71, 0xf7, 0x0, 0x78, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x1f, 0x7, 0x0, 0xf, 0xff, 0x0, 0x3, 0xfc, 0x0} + +/* A (65) */ +#define NXFONT_METRICS_65 {2, 16, 19, 1, 10, 0} +#define NXFONT_BITMAP_65 {0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, 0x7, 0xe0, 0xe, 0x60, 0xe, 0x70, 0xe, 0x70, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x38, 0x1c, 0x38, 0x1c, 0x3f, 0xfc, 0x7f, 0xfe, 0x70, 0xe, 0x70, 0xe, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7} + +/* B (66) */ +#define NXFONT_METRICS_66 {2, 15, 19, 2, 10, 0} +#define NXFONT_BITMAP_66 {0xff, 0xe0, 0xff, 0xf8, 0xe0, 0x78, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x38, 0xff, 0xf0, 0xff, 0xf8, 0xe0, 0x1c, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0x1e, 0xe0, 0x7c, 0xff, 0xf8, 0xff, 0xe0} + +/* C (67) */ +#define NXFONT_METRICS_67 {2, 16, 19, 1, 10, 0} +#define NXFONT_BITMAP_67 {0x7, 0xf0, 0x1f, 0xfc, 0x3e, 0x3e, 0x78, 0xf, 0x70, 0x7, 0xf0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xf0, 0x7, 0x70, 0x7, 0x78, 0xf, 0x3e, 0x3e, 0x1f, 0xfc, 0x7, 0xf0} + +/* D (68) */ +#define NXFONT_METRICS_68 {2, 16, 19, 2, 10, 0} +#define NXFONT_BITMAP_68 {0xff, 0xe0, 0xff, 0xf8, 0xe0, 0x7c, 0xe0, 0x1e, 0xe0, 0xe, 0xe0, 0xf, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0xf, 0xe0, 0xe, 0xe0, 0x1e, 0xe0, 0x7c, 0xff, 0xf8, 0xff, 0xe0} + +/* E (69) */ +#define NXFONT_METRICS_69 {2, 13, 19, 2, 10, 0} +#define NXFONT_BITMAP_69 {0xff, 0xf0, 0xff, 0xf0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xf8, 0xff, 0xf8} + +/* F (70) */ +#define NXFONT_METRICS_70 {2, 12, 19, 2, 10, 0} +#define NXFONT_BITMAP_70 {0xff, 0xf0, 0xff, 0xf0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* G (71) */ +#define NXFONT_METRICS_71 {3, 17, 19, 1, 10, 0} +#define NXFONT_BITMAP_71 {0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3e, 0x3e, 0x0, 0x78, 0xf, 0x0, 0x70, 0x7, 0x0, 0xf0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x7f, 0x80, 0xe0, 0x7f, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xf0, 0x3, 0x80, 0x70, 0x7, 0x80, 0x78, 0xf, 0x80, 0x3e, 0x3f, 0x80, 0x1f, 0xfb, 0x80, 0x7, 0xf3, 0x80} + +/* H (72) */ +#define NXFONT_METRICS_72 {2, 15, 19, 2, 10, 0} +#define NXFONT_BITMAP_72 {0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xff, 0xfe, 0xff, 0xfe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 3, 19, 2, 10, 0} +#define NXFONT_BITMAP_73 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* J (74) */ +#define NXFONT_METRICS_74 {2, 11, 19, 1, 10, 0} +#define NXFONT_BITMAP_74 {0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x71, 0xe0, 0x7f, 0xc0, 0x3f, 0x80} + +/* K (75) */ +#define NXFONT_METRICS_75 {2, 14, 19, 2, 10, 0} +#define NXFONT_BITMAP_75 {0xe0, 0x3c, 0xe0, 0x78, 0xe0, 0xf0, 0xe1, 0xe0, 0xe3, 0xc0, 0xe7, 0x80, 0xef, 0x0, 0xfe, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xf7, 0x80, 0xe3, 0x80, 0xe1, 0xc0, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0x70, 0xe0, 0x78, 0xe0, 0x38, 0xe0, 0x3c} + +/* L (76) */ +#define NXFONT_METRICS_76 {2, 12, 19, 2, 10, 0} +#define NXFONT_BITMAP_76 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xf0, 0xff, 0xf0} + +/* M (77) */ +#define NXFONT_METRICS_77 {3, 19, 19, 2, 10, 0} +#define NXFONT_BITMAP_77 {0xe0, 0x0, 0xe0, 0xf0, 0x1, 0xe0, 0xf0, 0x1, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xfc, 0x7, 0xe0, 0xec, 0x6, 0xe0, 0xee, 0xe, 0xe0, 0xe6, 0xc, 0xe0, 0xe7, 0x1c, 0xe0, 0xe7, 0x1c, 0xe0, 0xe3, 0x18, 0xe0, 0xe3, 0xb8, 0xe0, 0xe3, 0xb8, 0xe0, 0xe1, 0xf0, 0xe0, 0xe1, 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* N (78) */ +#define NXFONT_METRICS_78 {2, 15, 19, 2, 10, 0} +#define NXFONT_BITMAP_78 {0xe0, 0xe, 0xf0, 0xe, 0xf0, 0xe, 0xf8, 0xe, 0xf8, 0xe, 0xfc, 0xe, 0xee, 0xe, 0xee, 0xe, 0xe7, 0xe, 0xe3, 0x8e, 0xe3, 0x8e, 0xe1, 0xce, 0xe0, 0xce, 0xe0, 0xee, 0xe0, 0x7e, 0xe0, 0x3e, 0xe0, 0x3e, 0xe0, 0x1e, 0xe0, 0xe} + +/* O (79) */ +#define NXFONT_METRICS_79 {3, 17, 19, 1, 10, 0} +#define NXFONT_BITMAP_79 {0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3e, 0x3e, 0x0, 0x78, 0xf, 0x0, 0x70, 0x7, 0x0, 0xf0, 0x7, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xf0, 0x7, 0x80, 0x70, 0x7, 0x0, 0x78, 0xf, 0x0, 0x3e, 0x3e, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* P (80) */ +#define NXFONT_METRICS_80 {2, 14, 19, 2, 10, 0} +#define NXFONT_BITMAP_80 {0xff, 0xe0, 0xff, 0xf8, 0xe0, 0x38, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x38, 0xff, 0xf8, 0xff, 0xf0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {3, 17, 20, 1, 10, 0} +#define NXFONT_BITMAP_81 {0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3e, 0x3e, 0x0, 0x78, 0xf, 0x0, 0x70, 0x7, 0x0, 0xf0, 0x7, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xf0, 0x27, 0x80, 0x70, 0x77, 0x0, 0x78, 0x3f, 0x0, 0x3e, 0x1e, 0x0, 0x1f, 0xfe, 0x0, 0x7, 0xf7, 0x0, 0x0, 0x2, 0x0} + +/* R (82) */ +#define NXFONT_METRICS_82 {2, 14, 19, 2, 10, 0} +#define NXFONT_BITMAP_82 {0xff, 0xe0, 0xff, 0xf8, 0xe0, 0x38, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x38, 0xff, 0xf8, 0xff, 0xf0, 0xe0, 0x78, 0xe0, 0x38, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c} + +/* S (83) */ +#define NXFONT_METRICS_83 {2, 14, 19, 2, 10, 0} +#define NXFONT_BITMAP_83 {0xf, 0xc0, 0x3f, 0xf0, 0x78, 0xf8, 0xf0, 0x38, 0xe0, 0x38, 0xe0, 0x0, 0xf0, 0x0, 0x7c, 0x0, 0x3f, 0xc0, 0x7, 0xf0, 0x0, 0xf8, 0x0, 0x3c, 0x0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xf8, 0xf8, 0x7f, 0xf0, 0x1f, 0xc0} + +/* T (84) */ +#define NXFONT_METRICS_84 {2, 15, 19, 0, 10, 0} +#define NXFONT_BITMAP_84 {0xff, 0xfe, 0xff, 0xfe, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80} + +/* U (85) */ +#define NXFONT_METRICS_85 {2, 15, 19, 2, 10, 0} +#define NXFONT_BITMAP_85 {0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xf0, 0x1e, 0x70, 0x1c, 0x7c, 0x7c, 0x3f, 0xf8, 0xf, 0xe0} + +/* V (86) */ +#define NXFONT_METRICS_86 {2, 16, 19, 1, 10, 0} +#define NXFONT_BITMAP_86 {0xe0, 0x7, 0xe0, 0x7, 0xf0, 0xf, 0x70, 0xe, 0x78, 0x1e, 0x38, 0x1c, 0x38, 0x1c, 0x3c, 0x3c, 0x1c, 0x38, 0x1c, 0x38, 0x1e, 0x78, 0xe, 0x70, 0xe, 0x70, 0xe, 0x70, 0x7, 0xe0, 0x7, 0xe0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0} + +/* W (87) */ +#define NXFONT_METRICS_87 {3, 21, 19, 1, 10, 0} +#define NXFONT_BITMAP_87 {0xe0, 0x70, 0x38, 0xe0, 0x70, 0x38, 0xe0, 0x70, 0x38, 0xe0, 0x70, 0x38, 0x70, 0xf8, 0x70, 0x70, 0xf8, 0x70, 0x70, 0xd8, 0x70, 0x71, 0xdc, 0x70, 0x31, 0xdc, 0x60, 0x39, 0xdc, 0xe0, 0x39, 0x8c, 0xe0, 0x3b, 0x8e, 0xe0, 0x1b, 0x8e, 0xc0, 0x1b, 0x8e, 0xc0, 0x1f, 0x7, 0xc0, 0x1f, 0x7, 0xc0, 0xe, 0x3, 0x80, 0xe, 0x3, 0x80, 0xe, 0x3, 0x80} + +/* X (88) */ +#define NXFONT_METRICS_88 {2, 16, 19, 1, 10, 0} +#define NXFONT_BITMAP_88 {0xe0, 0x7, 0xf0, 0xf, 0x78, 0x1e, 0x38, 0x1c, 0x1c, 0x38, 0xe, 0x70, 0xf, 0xf0, 0x7, 0xe0, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, 0xf, 0xf0, 0xe, 0x70, 0x1c, 0x38, 0x3c, 0x3c, 0x38, 0x1c, 0x70, 0xe, 0xf0, 0xf, 0xe0, 0x7} + +/* Y (89) */ +#define NXFONT_METRICS_89 {2, 15, 19, 1, 10, 0} +#define NXFONT_BITMAP_89 {0xe0, 0xe, 0xf0, 0xe, 0x70, 0x1c, 0x78, 0x1c, 0x38, 0x38, 0x3c, 0x38, 0x1c, 0x70, 0x1c, 0x70, 0xe, 0xe0, 0xe, 0xe0, 0x7, 0xc0, 0x7, 0xc0, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80} + +/* Z (90) */ +#define NXFONT_METRICS_90 {2, 14, 19, 1, 10, 0} +#define NXFONT_BITMAP_90 {0xff, 0xfc, 0xff, 0xfc, 0x0, 0x3c, 0x0, 0x78, 0x0, 0xf0, 0x1, 0xe0, 0x1, 0xe0, 0x3, 0xc0, 0x7, 0x80, 0x7, 0x80, 0xf, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x3c, 0x0, 0x38, 0x0, 0x78, 0x0, 0xf0, 0x0, 0xff, 0xfc, 0xff, 0xfc} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 5, 24, 1, 10, 0} +#define NXFONT_BITMAP_91 {0xf8, 0xf8, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf8, 0xf8} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {1, 7, 19, 0, 10, 0} +#define NXFONT_BITMAP_92 {0xc0, 0xc0, 0xc0, 0x60, 0x60, 0x60, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0xc, 0xc, 0xc, 0x6, 0x6, 0x6} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 5, 24, 2, 10, 0} +#define NXFONT_BITMAP_93 {0xf8, 0xf8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xf8, 0xf8} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {2, 11, 9, 1, 10, 0} +#define NXFONT_BITMAP_94 {0xe, 0x0, 0xe, 0x0, 0x1f, 0x0, 0x1b, 0x0, 0x3b, 0x80, 0x71, 0xc0, 0x71, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {2, 14, 2, 0, 32, 0} +#define NXFONT_BITMAP_95 {0xff, 0xfc, 0xff, 0xfc} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 6, 4, 1, 10, 0} +#define NXFONT_BITMAP_96 {0xe0, 0x70, 0x38, 0x1c} + +/* a (97) */ +#define NXFONT_METRICS_97 {2, 12, 14, 1, 15, 0} +#define NXFONT_BITMAP_97 {0x1f, 0x80, 0x3f, 0xc0, 0x71, 0xe0, 0x70, 0xe0, 0x0, 0xe0, 0x7, 0xe0, 0x3f, 0xe0, 0x7c, 0xe0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf3, 0xe0, 0x7f, 0xf0, 0x3e, 0x70} + +/* b (98) */ +#define NXFONT_METRICS_98 {2, 12, 19, 2, 10, 0} +#define NXFONT_BITMAP_98 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xef, 0x80, 0xff, 0xc0, 0xf9, 0xe0, 0xf0, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xf0, 0xe0, 0xf9, 0xe0, 0xff, 0xc0, 0xef, 0x80} + +/* c (99) */ +#define NXFONT_METRICS_99 {2, 11, 14, 1, 15, 0} +#define NXFONT_BITMAP_99 {0x1f, 0x80, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0x70, 0xe0, 0x79, 0xe0, 0x3f, 0xc0, 0x1f, 0x80} + +/* d (100) */ +#define NXFONT_METRICS_100 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_100 {0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x1f, 0x70, 0x3f, 0xf0, 0x79, 0xf0, 0x70, 0xf0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xf0, 0x79, 0xf0, 0x3f, 0xf0, 0x1f, 0x70} + +/* e (101) */ +#define NXFONT_METRICS_101 {2, 12, 14, 1, 15, 0} +#define NXFONT_BITMAP_101 {0xf, 0x0, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xff, 0xf0, 0xff, 0xf0, 0xe0, 0x0, 0xe0, 0x0, 0x70, 0x70, 0x78, 0xf0, 0x3f, 0xe0, 0xf, 0x80} + +/* f (102) */ +#define NXFONT_METRICS_102 {1, 7, 19, 1, 10, 0} +#define NXFONT_BITMAP_102 {0x1e, 0x3e, 0x38, 0x38, 0x38, 0xfe, 0xfe, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38} + +/* g (103) */ +#define NXFONT_METRICS_103 {2, 12, 19, 1, 15, 0} +#define NXFONT_BITMAP_103 {0x1f, 0x70, 0x3f, 0xf0, 0x79, 0xf0, 0x70, 0xf0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xf0, 0x79, 0xf0, 0x3f, 0xf0, 0x1f, 0x70, 0x0, 0x70, 0xe0, 0x70, 0xf0, 0xe0, 0x7f, 0xe0, 0x1f, 0x80} + +/* h (104) */ +#define NXFONT_METRICS_104 {2, 11, 19, 2, 10, 0} +#define NXFONT_BITMAP_104 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xef, 0x0, 0xff, 0xc0, 0xf1, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 3, 19, 2, 10, 0} +#define NXFONT_BITMAP_105 {0xe0, 0xe0, 0xe0, 0x0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* j (106) */ +#define NXFONT_METRICS_106 {1, 5, 24, 0, 10, 0} +#define NXFONT_BITMAP_106 {0x38, 0x38, 0x38, 0x0, 0x0, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xf8, 0xf0} + +/* k (107) */ +#define NXFONT_METRICS_107 {2, 11, 19, 2, 10, 0} +#define NXFONT_BITMAP_107 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe1, 0xc0, 0xe3, 0xc0, 0xe7, 0x80, 0xef, 0x0, 0xfe, 0x0, 0xfc, 0x0, 0xfe, 0x0, 0xef, 0x0, 0xe7, 0x0, 0xe7, 0x80, 0xe3, 0xc0, 0xe1, 0xc0, 0xe1, 0xe0, 0xe0, 0xe0} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 3, 19, 2, 10, 0} +#define NXFONT_BITMAP_108 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* m (109) */ +#define NXFONT_METRICS_109 {3, 17, 14, 2, 15, 0} +#define NXFONT_BITMAP_109 {0xef, 0x3e, 0x0, 0xff, 0xff, 0x0, 0xf3, 0xe7, 0x80, 0xe1, 0xc3, 0x80, 0xe1, 0xc3, 0x80, 0xe1, 0xc3, 0x80, 0xe1, 0xc3, 0x80, 0xe1, 0xc3, 0x80, 0xe1, 0xc3, 0x80, 0xe1, 0xc3, 0x80, 0xe1, 0xc3, 0x80, 0xe1, 0xc3, 0x80, 0xe1, 0xc3, 0x80, 0xe1, 0xc3, 0x80} + +/* n (110) */ +#define NXFONT_METRICS_110 {2, 11, 14, 2, 15, 0} +#define NXFONT_BITMAP_110 {0xef, 0x80, 0xff, 0xc0, 0xf1, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* o (111) */ +#define NXFONT_METRICS_111 {2, 12, 14, 1, 15, 0} +#define NXFONT_BITMAP_111 {0xf, 0x0, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x79, 0xe0, 0x3f, 0xc0, 0xf, 0x0} + +/* p (112) */ +#define NXFONT_METRICS_112 {2, 12, 19, 2, 15, 0} +#define NXFONT_BITMAP_112 {0xef, 0x80, 0xff, 0xc0, 0xf9, 0xe0, 0xf0, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xf0, 0xe0, 0xf9, 0xe0, 0xff, 0xc0, 0xef, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* q (113) */ +#define NXFONT_METRICS_113 {2, 12, 19, 1, 15, 0} +#define NXFONT_BITMAP_113 {0x1f, 0x70, 0x3f, 0xf0, 0x79, 0xf0, 0x70, 0xf0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xf0, 0x79, 0xf0, 0x3f, 0xf0, 0x1f, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70} + +/* r (114) */ +#define NXFONT_METRICS_114 {1, 7, 14, 2, 15, 0} +#define NXFONT_BITMAP_114 {0xee, 0xfe, 0xfe, 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* s (115) */ +#define NXFONT_METRICS_115 {2, 11, 14, 1, 15, 0} +#define NXFONT_BITMAP_115 {0x3f, 0x0, 0x7f, 0x80, 0xf3, 0xc0, 0xe1, 0xc0, 0xe0, 0x0, 0xfc, 0x0, 0x7f, 0x80, 0xf, 0xc0, 0x1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xe0, 0x7f, 0xc0, 0x3f, 0x80} + +/* t (116) */ +#define NXFONT_METRICS_116 {1, 7, 18, 1, 11, 0} +#define NXFONT_BITMAP_116 {0x38, 0x38, 0x38, 0x38, 0xfe, 0xfe, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x3e, 0x1e} + +/* u (117) */ +#define NXFONT_METRICS_117 {2, 11, 14, 2, 15, 0} +#define NXFONT_BITMAP_117 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0x73, 0xe0, 0x7e, 0xe0, 0x1c, 0xe0} + +/* v (118) */ +#define NXFONT_METRICS_118 {2, 12, 14, 1, 15, 0} +#define NXFONT_BITMAP_118 {0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x39, 0xc0, 0x39, 0xc0, 0x39, 0xc0, 0x1f, 0x80, 0x1f, 0x80, 0xf, 0x0, 0xf, 0x0, 0xf, 0x0} + +/* w (119) */ +#define NXFONT_METRICS_119 {3, 19, 14, 0, 15, 0} +#define NXFONT_BITMAP_119 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x60, 0xe0, 0xc0, 0x71, 0xf1, 0xc0, 0x71, 0xf1, 0xc0, 0x31, 0xb1, 0x80, 0x33, 0xb9, 0x80, 0x3b, 0xbb, 0x80, 0x1b, 0x1b, 0x0, 0x1f, 0x1f, 0x0, 0x1f, 0x1f, 0x0, 0xe, 0xe, 0x0, 0xe, 0xe, 0x0, 0xe, 0xe, 0x0} + +/* x (120) */ +#define NXFONT_METRICS_120 {2, 11, 14, 1, 15, 0} +#define NXFONT_BITMAP_120 {0xe0, 0xe0, 0xf1, 0xe0, 0x71, 0xc0, 0x3b, 0x80, 0x3f, 0x80, 0x1f, 0x0, 0xe, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x3b, 0x80, 0x7b, 0xc0, 0x71, 0xc0, 0xf1, 0xe0, 0xe0, 0xe0} + +/* y (121) */ +#define NXFONT_METRICS_121 {2, 13, 19, 1, 15, 0} +#define NXFONT_BITMAP_121 {0xe0, 0x38, 0xe0, 0x38, 0x70, 0x38, 0x78, 0x70, 0x38, 0x70, 0x3c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0xf, 0xc0, 0xf, 0xc0, 0x7, 0xc0, 0x7, 0x80, 0x3, 0x80, 0x3, 0x80, 0x7, 0x0, 0x7, 0x0, 0xe, 0x0, 0x3e, 0x0, 0x3c, 0x0} + +/* z (122) */ +#define NXFONT_METRICS_122 {2, 11, 14, 1, 15, 0} +#define NXFONT_BITMAP_122 {0xff, 0xe0, 0xff, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x7, 0x80, 0xf, 0x0, 0xe, 0x0, 0x1e, 0x0, 0x3c, 0x0, 0x38, 0x0, 0x70, 0x0, 0xf0, 0x0, 0xff, 0xe0, 0xff, 0xe0} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {1, 7, 24, 1, 10, 0} +#define NXFONT_BITMAP_123 {0xe, 0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x70, 0xe0, 0xe0, 0x70, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x1c, 0xe} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 2, 24, 3, 10, 0} +#define NXFONT_BITMAP_124 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 7, 24, 2, 10, 0} +#define NXFONT_BITMAP_125 {0xe0, 0x70, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x1c, 0xe, 0xe, 0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x70, 0xe0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {2, 11, 4, 1, 20, 0} +#define NXFONT_BITMAP_126 {0x78, 0xe0, 0xfe, 0xe0, 0xef, 0xe0, 0xe3, 0xc0} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 3, 19, 2, 15, 0} +#define NXFONT_BITMAP_161 {0xe0, 0xe0, 0xe0, 0x0, 0x0, 0x60, 0x60, 0x60, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* cent (162) */ +#define NXFONT_METRICS_162 {2, 11, 18, 1, 13, 0} +#define NXFONT_BITMAP_162 {0x1, 0x80, 0x1, 0x80, 0x1f, 0x80, 0x3f, 0xc0, 0x7b, 0xe0, 0x73, 0x60, 0xe3, 0x0, 0xe6, 0x0, 0xe6, 0x0, 0xe6, 0x0, 0xe6, 0x0, 0xec, 0x0, 0xec, 0xe0, 0x7d, 0xe0, 0x7f, 0xc0, 0x3f, 0x80, 0x18, 0x0, 0x18, 0x0} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {2, 13, 18, 1, 11, 0} +#define NXFONT_BITMAP_163 {0x1f, 0x80, 0x3f, 0xc0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x0, 0x78, 0x0, 0x38, 0x0, 0x1c, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x38, 0x0, 0x7f, 0x38, 0xff, 0xf8, 0xf1, 0xf0} + +/* currency (164) */ +#define NXFONT_METRICS_164 {2, 12, 12, 1, 14, 0} +#define NXFONT_BITMAP_164 {0xc0, 0x30, 0xef, 0x70, 0x7f, 0xe0, 0x39, 0xc0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x39, 0xc0, 0x7f, 0xe0, 0xef, 0x70, 0xc0, 0x30} + +/* yen (165) */ +#define NXFONT_METRICS_165 {2, 13, 18, 0, 11, 0} +#define NXFONT_BITMAP_165 {0xe0, 0x38, 0xe0, 0x38, 0x70, 0x70, 0x70, 0x70, 0x38, 0xe0, 0x38, 0xe0, 0x1d, 0xc0, 0x1d, 0xc0, 0x7f, 0xf0, 0x7f, 0xf0, 0x7, 0x0, 0x7f, 0xf0, 0x7f, 0xf0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 2, 24, 3, 10, 0} +#define NXFONT_BITMAP_166 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* section (167) */ +#define NXFONT_METRICS_167 {2, 12, 24, 1, 10, 0} +#define NXFONT_BITMAP_167 {0x1f, 0x80, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0x78, 0xe0, 0x3c, 0x0, 0x1e, 0x0, 0x7f, 0x0, 0xf7, 0x80, 0xe3, 0xc0, 0xe1, 0xe0, 0xe0, 0xe0, 0x70, 0x70, 0x78, 0x70, 0x3c, 0x70, 0x1e, 0xe0, 0xf, 0xc0, 0x7, 0x80, 0x3, 0xc0, 0x71, 0xe0, 0x70, 0xe0, 0x79, 0xe0, 0x3f, 0xc0, 0x1f, 0x80} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 7, 2, 1, 11, 0} +#define NXFONT_BITMAP_168 {0xee, 0xee} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {3, 19, 19, 0, 10, 0} +#define NXFONT_BITMAP_169 {0x1, 0xf0, 0x0, 0xf, 0xfe, 0x0, 0x1e, 0xf, 0x0, 0x38, 0x3, 0x80, 0x70, 0x1, 0xc0, 0x61, 0xf0, 0xc0, 0xe3, 0xb8, 0xe0, 0xc6, 0xc, 0x60, 0xc6, 0x0, 0x60, 0xc6, 0x0, 0x60, 0xc6, 0x0, 0x60, 0xc6, 0xc, 0x60, 0xe3, 0xb8, 0xe0, 0x61, 0xf0, 0xc0, 0x70, 0x1, 0xc0, 0x38, 0x3, 0x80, 0x1e, 0xf, 0x0, 0xf, 0xfe, 0x0, 0x1, 0xf0, 0x0} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {1, 8, 12, 1, 10, 0} +#define NXFONT_BITMAP_170 {0x7c, 0xfe, 0xc6, 0x1e, 0x7e, 0xe6, 0xc6, 0xff, 0x7b, 0x0, 0xff, 0xff} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {2, 10, 8, 1, 18, 0} +#define NXFONT_BITMAP_171 {0x1d, 0xc0, 0x3b, 0x80, 0x77, 0x0, 0xee, 0x0, 0xee, 0x0, 0x77, 0x0, 0x3b, 0x80, 0x1d, 0xc0} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {2, 12, 7, 1, 18, 0} +#define NXFONT_BITMAP_172 {0xff, 0xf0, 0xff, 0xf0, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 7, 3, 0, 20, 0} +#define NXFONT_BITMAP_173 {0xfe, 0xfe, 0xfe} + +/* registered (174) */ +#define NXFONT_METRICS_174 {3, 19, 19, 0, 10, 0} +#define NXFONT_BITMAP_174 {0x3, 0xf8, 0x0, 0xf, 0xfe, 0x0, 0x1c, 0xf, 0x0, 0x38, 0x3, 0x80, 0x73, 0xf9, 0xc0, 0x63, 0x1c, 0xc0, 0xe3, 0xc, 0xe0, 0xc3, 0xc, 0x60, 0xc3, 0x18, 0x60, 0xc3, 0xf0, 0x60, 0xc3, 0x30, 0x60, 0xc3, 0x18, 0x60, 0xe3, 0x18, 0x60, 0x63, 0xc, 0xe0, 0x70, 0x0, 0xc0, 0x38, 0x1, 0xc0, 0x1e, 0x3, 0x80, 0xf, 0xfe, 0x0, 0x3, 0xf8, 0x0} + +/* macron (175) */ +#define NXFONT_METRICS_175 {1, 7, 2, 1, 10, 0} +#define NXFONT_BITMAP_175 {0xfe, 0xfe} + +/* degree (176) */ +#define NXFONT_METRICS_176 {1, 8, 7, 0, 11, 0} +#define NXFONT_BITMAP_176 {0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0x66, 0x3c} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {2, 11, 13, 2, 16, 0} +#define NXFONT_BITMAP_177 {0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0x0, 0x0, 0xff, 0xe0, 0xff, 0xe0} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {1, 6, 10, 0, 11, 0} +#define NXFONT_BITMAP_178 {0x78, 0xfc, 0xcc, 0xc, 0x1c, 0x78, 0xe0, 0xc0, 0xfc, 0xfc} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {1, 6, 10, 0, 11, 0} +#define NXFONT_BITMAP_179 {0x78, 0xfc, 0xcc, 0xc, 0x38, 0x38, 0xc, 0xcc, 0xfc, 0x78} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 6, 4, 1, 10, 0} +#define NXFONT_BITMAP_180 {0x1c, 0x38, 0x70, 0xe0} + +/* mu (181) */ +#define NXFONT_METRICS_181 {2, 11, 19, 2, 15, 0} +#define NXFONT_BITMAP_181 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf3, 0xe0, 0xfe, 0xe0, 0xec, 0xe0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {2, 11, 24, 1, 10, 0} +#define NXFONT_BITMAP_182 {0xf, 0xe0, 0x3f, 0xe0, 0x7c, 0xc0, 0x7c, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0x7c, 0xc0, 0x7c, 0xc0, 0x3c, 0xc0, 0x1c, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 3, 3, 2, 20, 0} +#define NXFONT_BITMAP_183 {0xe0, 0xe0, 0xe0} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 6, 6, 1, 28, 0} +#define NXFONT_BITMAP_184 {0x70, 0x78, 0x1c, 0x1c, 0xfc, 0x78} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 4, 10, 1, 11, 0} +#define NXFONT_BITMAP_185 {0x30, 0x30, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {1, 8, 12, 1, 10, 0} +#define NXFONT_BITMAP_186 {0x3c, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e, 0x3c, 0x0, 0xff, 0xff} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {2, 10, 8, 1, 18, 0} +#define NXFONT_BITMAP_187 {0xee, 0x0, 0x77, 0x0, 0x3b, 0x80, 0x1d, 0xc0, 0x1d, 0xc0, 0x3b, 0x80, 0x77, 0x0, 0xee, 0x0} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {3, 17, 18, 1, 11, 0} +#define NXFONT_BITMAP_188 {0x30, 0x18, 0x0, 0x30, 0x18, 0x0, 0xf0, 0x30, 0x0, 0xf0, 0x30, 0x0, 0x30, 0x60, 0x0, 0x30, 0x60, 0x0, 0x30, 0xc0, 0x0, 0x30, 0xc0, 0x0, 0x31, 0x86, 0x0, 0x31, 0x8e, 0x0, 0x3, 0x1e, 0x0, 0x3, 0x1e, 0x0, 0x6, 0x36, 0x0, 0x6, 0x66, 0x0, 0xc, 0x7f, 0x80, 0xc, 0x7f, 0x80, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {2, 16, 18, 1, 11, 0} +#define NXFONT_BITMAP_189 {0x30, 0x18, 0x30, 0x18, 0xf0, 0x30, 0xf0, 0x30, 0x30, 0x60, 0x30, 0x60, 0x30, 0xc0, 0x30, 0xc0, 0x31, 0x9e, 0x31, 0xbf, 0x3, 0x33, 0x3, 0x3, 0x6, 0x7, 0x6, 0x1e, 0xc, 0x38, 0xc, 0x30, 0x18, 0x3f, 0x18, 0x3f} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {3, 17, 18, 1, 11, 0} +#define NXFONT_BITMAP_190 {0x78, 0x18, 0x0, 0xfc, 0x18, 0x0, 0xcc, 0x30, 0x0, 0xc, 0x30, 0x0, 0x38, 0x60, 0x0, 0x38, 0x60, 0x0, 0xc, 0xc0, 0x0, 0xcc, 0xc0, 0x0, 0xfd, 0x86, 0x0, 0x79, 0x8e, 0x0, 0x3, 0x1e, 0x0, 0x3, 0x1e, 0x0, 0x6, 0x36, 0x0, 0x6, 0x66, 0x0, 0xc, 0x7f, 0x80, 0xc, 0x7f, 0x80, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {2, 11, 19, 2, 15, 0} +#define NXFONT_BITMAP_191 {0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x3c, 0x0, 0x78, 0x0, 0x70, 0x0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf3, 0xc0, 0x7f, 0xc0, 0x3f, 0x0} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {2, 16, 24, 1, 5, 0} +#define NXFONT_BITMAP_192 {0xe, 0x0, 0x7, 0x0, 0x3, 0x80, 0x1, 0xc0, 0x0, 0x0, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, 0x7, 0xe0, 0xe, 0x60, 0xe, 0x70, 0xe, 0x70, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x38, 0x1c, 0x38, 0x1c, 0x3f, 0xfc, 0x7f, 0xfe, 0x70, 0xe, 0x70, 0xe, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {2, 16, 24, 1, 5, 0} +#define NXFONT_BITMAP_193 {0x0, 0x70, 0x0, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x0, 0x0, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, 0x7, 0xe0, 0xe, 0x60, 0xe, 0x70, 0xe, 0x70, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x38, 0x1c, 0x38, 0x1c, 0x3f, 0xfc, 0x7f, 0xfe, 0x70, 0xe, 0x70, 0xe, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {2, 16, 24, 1, 5, 0} +#define NXFONT_BITMAP_194 {0x1, 0xc0, 0x3, 0xe0, 0x7, 0x70, 0xe, 0x38, 0x0, 0x0, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, 0x7, 0xe0, 0xe, 0x60, 0xe, 0x70, 0xe, 0x70, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x38, 0x1c, 0x38, 0x1c, 0x3f, 0xfc, 0x7f, 0xfe, 0x70, 0xe, 0x70, 0xe, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {2, 16, 23, 1, 6, 0} +#define NXFONT_BITMAP_195 {0x7, 0x98, 0xf, 0xf8, 0xc, 0xf0, 0x0, 0x0, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, 0x7, 0xe0, 0xe, 0x60, 0xe, 0x70, 0xe, 0x70, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x38, 0x1c, 0x38, 0x1c, 0x3f, 0xfc, 0x7f, 0xfe, 0x70, 0xe, 0x70, 0xe, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {2, 16, 23, 1, 6, 0} +#define NXFONT_BITMAP_196 {0xe, 0x70, 0xe, 0x70, 0x0, 0x0, 0x0, 0x0, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, 0x7, 0xe0, 0xe, 0x60, 0xe, 0x70, 0xe, 0x70, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x38, 0x1c, 0x38, 0x1c, 0x3f, 0xfc, 0x7f, 0xfe, 0x70, 0xe, 0x70, 0xe, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {2, 16, 24, 1, 5, 0} +#define NXFONT_BITMAP_197 {0x3, 0xc0, 0x6, 0x60, 0x4, 0x20, 0x6, 0x60, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, 0x7, 0xe0, 0xe, 0x60, 0xe, 0x70, 0xe, 0x70, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x38, 0x1c, 0x38, 0x1c, 0x3f, 0xfc, 0x7f, 0xfe, 0x70, 0xe, 0x70, 0xe, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7} + +/* AE (198) */ +#define NXFONT_METRICS_198 {3, 22, 19, 1, 10, 0} +#define NXFONT_BITMAP_198 {0x3, 0xff, 0xf8, 0x3, 0xff, 0xf8, 0x7, 0x70, 0x0, 0x7, 0x70, 0x0, 0xe, 0x70, 0x0, 0xe, 0x70, 0x0, 0xe, 0x70, 0x0, 0x1c, 0x70, 0x0, 0x1c, 0x7f, 0xf0, 0x1c, 0x7f, 0xf0, 0x38, 0x70, 0x0, 0x38, 0x70, 0x0, 0x3f, 0xf0, 0x0, 0x7f, 0xf0, 0x0, 0x70, 0x70, 0x0, 0x70, 0x70, 0x0, 0xe0, 0x70, 0x0, 0xe0, 0x7f, 0xfc, 0xe0, 0x7f, 0xfc} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {2, 16, 24, 1, 10, 0} +#define NXFONT_BITMAP_199 {0x7, 0xf0, 0x1f, 0xfc, 0x3e, 0x3e, 0x78, 0xf, 0x70, 0x7, 0xf0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xf0, 0x7, 0x70, 0x7, 0x78, 0xf, 0x3e, 0x3e, 0x1f, 0xfc, 0x7, 0xf0, 0x3, 0xc0, 0x0, 0xe0, 0x0, 0xe0, 0x7, 0xe0, 0x3, 0xc0} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {2, 13, 24, 2, 5, 0} +#define NXFONT_BITMAP_200 {0x38, 0x0, 0x1c, 0x0, 0xe, 0x0, 0x7, 0x0, 0x0, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xf8, 0xff, 0xf8} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {2, 13, 24, 2, 5, 0} +#define NXFONT_BITMAP_201 {0x1, 0xc0, 0x3, 0x80, 0x7, 0x0, 0xe, 0x0, 0x0, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xf8, 0xff, 0xf8} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {2, 13, 24, 2, 5, 0} +#define NXFONT_BITMAP_202 {0x7, 0x0, 0xf, 0x80, 0x1d, 0xc0, 0x38, 0xe0, 0x0, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xf8, 0xff, 0xf8} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {2, 13, 23, 2, 6, 0} +#define NXFONT_BITMAP_203 {0x38, 0xe0, 0x38, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xf8, 0xff, 0xf8} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {1, 6, 24, 0, 5, 0} +#define NXFONT_BITMAP_204 {0xe0, 0x70, 0x38, 0x1c, 0x0, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 6, 24, 1, 5, 0} +#define NXFONT_BITMAP_205 {0x1c, 0x38, 0x70, 0xe0, 0x0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70} + +/* Icircumflex (206) - NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_206 {2, 9, 24, 0, 5, 0} +#define NXFONT_BITMAP_206 {0x1c, 0x0, 0x3e, 0x0, 0x77, 0x0, 0xe3, 0x80, 0x0, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {1, 7, 23, 0, 6, 0} +#define NXFONT_BITMAP_207 {0xee, 0xee, 0x0, 0x0, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38} + +/* Eth (208) - NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_208 {3, 19, 19, 0, 10, 0} +#define NXFONT_BITMAP_208 {0x1f, 0xfc, 0x0, 0x1f, 0xff, 0x0, 0x1c, 0xf, 0x80, 0x1c, 0x3, 0xc0, 0x1c, 0x1, 0xc0, 0x1c, 0x1, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0xff, 0xc0, 0xe0, 0xff, 0xc0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x1, 0xe0, 0x1c, 0x1, 0xc0, 0x1c, 0x3, 0xc0, 0x1c, 0xf, 0x80, 0x1f, 0xff, 0x0, 0x1f, 0xfc, 0x0} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {2, 15, 23, 2, 6, 0} +#define NXFONT_BITMAP_209 {0xf, 0x30, 0x1f, 0xf0, 0x19, 0xe0, 0x0, 0x0, 0xe0, 0xe, 0xf0, 0xe, 0xf0, 0xe, 0xf8, 0xe, 0xf8, 0xe, 0xfc, 0xe, 0xee, 0xe, 0xee, 0xe, 0xe7, 0xe, 0xe3, 0x8e, 0xe3, 0x8e, 0xe1, 0xce, 0xe0, 0xce, 0xe0, 0xee, 0xe0, 0x7e, 0xe0, 0x3e, 0xe0, 0x3e, 0xe0, 0x1e, 0xe0, 0xe} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {3, 17, 24, 1, 5, 0} +#define NXFONT_BITMAP_210 {0xe, 0x0, 0x0, 0x7, 0x0, 0x0, 0x3, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3e, 0x3e, 0x0, 0x78, 0xf, 0x0, 0x70, 0x7, 0x0, 0xf0, 0x7, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xf0, 0x7, 0x80, 0x70, 0x7, 0x0, 0x78, 0xf, 0x0, 0x3e, 0x3e, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {3, 17, 24, 1, 5, 0} +#define NXFONT_BITMAP_211 {0x0, 0x38, 0x0, 0x0, 0x70, 0x0, 0x0, 0xe0, 0x0, 0x1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3e, 0x3e, 0x0, 0x78, 0xf, 0x0, 0x70, 0x7, 0x0, 0xf0, 0x7, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xf0, 0x7, 0x80, 0x70, 0x7, 0x0, 0x78, 0xf, 0x0, 0x3e, 0x3e, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {3, 17, 24, 1, 5, 0} +#define NXFONT_BITMAP_212 {0x1, 0xc0, 0x0, 0x3, 0xe0, 0x0, 0x7, 0x70, 0x0, 0xe, 0x38, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3e, 0x3e, 0x0, 0x78, 0xf, 0x0, 0x70, 0x7, 0x0, 0xf0, 0x7, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xf0, 0x7, 0x80, 0x70, 0x7, 0x0, 0x78, 0xf, 0x0, 0x3e, 0x3e, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {3, 17, 23, 1, 6, 0} +#define NXFONT_BITMAP_213 {0x7, 0x98, 0x0, 0xf, 0xf8, 0x0, 0xc, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3e, 0x3e, 0x0, 0x78, 0xf, 0x0, 0x70, 0x7, 0x0, 0xf0, 0x7, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xf0, 0x7, 0x80, 0x70, 0x7, 0x0, 0x78, 0xf, 0x0, 0x3e, 0x3e, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {3, 17, 23, 1, 6, 0} +#define NXFONT_BITMAP_214 {0xe, 0x38, 0x0, 0xe, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3e, 0x3e, 0x0, 0x78, 0xf, 0x0, 0x70, 0x7, 0x0, 0xf0, 0x7, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xf0, 0x7, 0x80, 0x70, 0x7, 0x0, 0x78, 0xf, 0x0, 0x3e, 0x3e, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {2, 12, 12, 1, 16, 0} +#define NXFONT_BITMAP_215 {0x40, 0x20, 0xe0, 0x70, 0x70, 0xe0, 0x39, 0xc0, 0x1f, 0x80, 0xf, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x39, 0xc0, 0x70, 0xe0, 0xe0, 0x70, 0x40, 0x20} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {3, 19, 19, 0, 10, 0} +#define NXFONT_BITMAP_216 {0x3, 0xf8, 0x60, 0xf, 0xfe, 0xe0, 0x1f, 0x1f, 0xc0, 0x3c, 0x3, 0x80, 0x38, 0x7, 0x80, 0x78, 0xf, 0xc0, 0x70, 0x1d, 0xc0, 0x70, 0x39, 0xc0, 0x70, 0x71, 0xc0, 0x70, 0xe1, 0xc0, 0x71, 0xc1, 0xc0, 0x73, 0x81, 0xc0, 0x77, 0x1, 0xc0, 0x7e, 0x3, 0xc0, 0x3c, 0x3, 0x80, 0x3c, 0x7, 0x80, 0x7f, 0x1f, 0x0, 0xef, 0xfe, 0x0, 0xc3, 0xf8, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {2, 15, 24, 2, 5, 0} +#define NXFONT_BITMAP_217 {0xe, 0x0, 0x7, 0x0, 0x3, 0x80, 0x1, 0xc0, 0x0, 0x0, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xf0, 0x1e, 0x70, 0x1c, 0x7c, 0x7c, 0x3f, 0xf8, 0xf, 0xe0} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {2, 15, 24, 2, 5, 0} +#define NXFONT_BITMAP_218 {0x0, 0x70, 0x0, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x0, 0x0, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xf0, 0x1e, 0x70, 0x1c, 0x7c, 0x7c, 0x3f, 0xf8, 0xf, 0xe0} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {2, 15, 24, 2, 5, 0} +#define NXFONT_BITMAP_219 {0x3, 0x80, 0x7, 0xc0, 0xe, 0xe0, 0x1c, 0x70, 0x0, 0x0, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xf0, 0x1e, 0x70, 0x1c, 0x7c, 0x7c, 0x3f, 0xf8, 0xf, 0xe0} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {2, 15, 23, 2, 6, 0} +#define NXFONT_BITMAP_220 {0x1c, 0x70, 0x1c, 0x70, 0x0, 0x0, 0x0, 0x0, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xf0, 0x1e, 0x70, 0x1c, 0x7c, 0x7c, 0x3f, 0xf8, 0xf, 0xe0} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {2, 15, 24, 1, 5, 0} +#define NXFONT_BITMAP_221 {0x0, 0x70, 0x0, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x0, 0x0, 0xe0, 0xe, 0xf0, 0x1e, 0x70, 0x1c, 0x78, 0x3c, 0x38, 0x38, 0x3c, 0x78, 0x1c, 0x70, 0x1e, 0xf0, 0xe, 0xe0, 0xf, 0xe0, 0x7, 0xc0, 0x7, 0xc0, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {2, 14, 19, 2, 10, 0} +#define NXFONT_BITMAP_222 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xe0, 0xff, 0xf8, 0xe0, 0x38, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x38, 0xff, 0xf8, 0xff, 0xf0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {2, 11, 19, 2, 10, 0} +#define NXFONT_BITMAP_223 {0x1e, 0x0, 0x7f, 0x80, 0xf3, 0x80, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe3, 0x80, 0xef, 0x0, 0xef, 0x80, 0xe3, 0xc0, 0xe1, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xc0, 0xef, 0xc0, 0xef, 0x80} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_224 {0x1c, 0x0, 0xe, 0x0, 0x7, 0x0, 0x3, 0x80, 0x0, 0x0, 0x1f, 0x80, 0x3f, 0xc0, 0x71, 0xe0, 0x70, 0xe0, 0x0, 0xe0, 0x7, 0xe0, 0x3f, 0xe0, 0x7c, 0xe0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf3, 0xe0, 0x7f, 0xf0, 0x3e, 0x70} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_225 {0x1, 0xc0, 0x3, 0x80, 0x7, 0x0, 0xe, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x3f, 0xc0, 0x71, 0xe0, 0x70, 0xe0, 0x0, 0xe0, 0x7, 0xe0, 0x3f, 0xe0, 0x7c, 0xe0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf3, 0xe0, 0x7f, 0xf0, 0x3e, 0x70} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_226 {0x7, 0x0, 0xf, 0x80, 0x1d, 0xc0, 0x38, 0xe0, 0x0, 0x0, 0x1f, 0x80, 0x3f, 0xc0, 0x71, 0xe0, 0x70, 0xe0, 0x0, 0xe0, 0x7, 0xe0, 0x3f, 0xe0, 0x7c, 0xe0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf3, 0xe0, 0x7f, 0xf0, 0x3e, 0x70} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_227 {0x3c, 0xc0, 0x7f, 0xc0, 0x67, 0x80, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x3f, 0xc0, 0x71, 0xe0, 0x70, 0xe0, 0x0, 0xe0, 0x7, 0xe0, 0x3f, 0xe0, 0x7c, 0xe0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf3, 0xe0, 0x7f, 0xf0, 0x3e, 0x70} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {2, 12, 18, 1, 11, 0} +#define NXFONT_BITMAP_228 {0x39, 0xc0, 0x39, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x3f, 0xc0, 0x71, 0xe0, 0x70, 0xe0, 0x0, 0xe0, 0x7, 0xe0, 0x3f, 0xe0, 0x7c, 0xe0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf3, 0xe0, 0x7f, 0xf0, 0x3e, 0x70} + +/* aring (229) */ +#define NXFONT_METRICS_229 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_229 {0x7, 0x0, 0xd, 0x80, 0x8, 0x80, 0xd, 0x80, 0x7, 0x0, 0x1f, 0x80, 0x3f, 0xc0, 0x71, 0xe0, 0x70, 0xe0, 0x0, 0xe0, 0x7, 0xe0, 0x3f, 0xe0, 0x7c, 0xe0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf3, 0xe0, 0x7f, 0xf0, 0x3e, 0x70} + +/* ae (230) */ +#define NXFONT_METRICS_230 {3, 20, 14, 1, 15, 0} +#define NXFONT_BITMAP_230 {0x1f, 0x8f, 0x0, 0x3f, 0xff, 0xc0, 0x71, 0xf9, 0xe0, 0x70, 0xf0, 0xe0, 0x0, 0xe0, 0x70, 0x7, 0xe0, 0x70, 0x3f, 0xff, 0xf0, 0x7c, 0xff, 0xf0, 0xf0, 0xe0, 0x0, 0xe0, 0xe0, 0x0, 0xe1, 0xf0, 0x70, 0xf3, 0xf8, 0xf0, 0x7f, 0x3f, 0xe0, 0x3e, 0xf, 0x80} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {2, 11, 19, 1, 15, 0} +#define NXFONT_BITMAP_231 {0x1f, 0x80, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0x70, 0xe0, 0x79, 0xe0, 0x3f, 0xc0, 0x1f, 0x80, 0x1e, 0x0, 0x7, 0x0, 0x7, 0x0, 0x3f, 0x0, 0x1e, 0x0} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_232 {0x1c, 0x0, 0xe, 0x0, 0x7, 0x0, 0x3, 0x80, 0x0, 0x0, 0xf, 0x0, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xff, 0xf0, 0xff, 0xf0, 0xe0, 0x0, 0xe0, 0x0, 0x70, 0x70, 0x78, 0xf0, 0x3f, 0xe0, 0xf, 0x80} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_233 {0x3, 0x80, 0x7, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x0, 0x0, 0xf, 0x0, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xff, 0xf0, 0xff, 0xf0, 0xe0, 0x0, 0xe0, 0x0, 0x70, 0x70, 0x78, 0xf0, 0x3f, 0xe0, 0xf, 0x80} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_234 {0x7, 0x0, 0xf, 0x80, 0x1d, 0xc0, 0x38, 0xe0, 0x0, 0x0, 0xf, 0x0, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xff, 0xf0, 0xff, 0xf0, 0xe0, 0x0, 0xe0, 0x0, 0x70, 0x70, 0x78, 0xf0, 0x3f, 0xe0, 0xf, 0x80} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {2, 12, 18, 1, 11, 0} +#define NXFONT_BITMAP_235 {0x39, 0xc0, 0x39, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xff, 0xf0, 0xff, 0xf0, 0xe0, 0x0, 0xe0, 0x0, 0x70, 0x70, 0x78, 0xf0, 0x3f, 0xe0, 0xf, 0x80} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 6, 19, 0, 10, 0} +#define NXFONT_BITMAP_236 {0xe0, 0x70, 0x38, 0x1c, 0x0, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 6, 19, 1, 10, 0} +#define NXFONT_BITMAP_237 {0x1c, 0x38, 0x70, 0xe0, 0x0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70} + +/* icircumflex (238) - NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_238 {2, 9, 19, 0, 10, 0} +#define NXFONT_BITMAP_238 {0x1c, 0x0, 0x3e, 0x0, 0x77, 0x0, 0xe3, 0x80, 0x0, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 7, 18, 0, 11, 0} +#define NXFONT_BITMAP_239 {0xee, 0xee, 0x0, 0x0, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38} + +/* eth (240) */ +#define NXFONT_METRICS_240 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_240 {0x70, 0x0, 0x1d, 0xc0, 0x7, 0x0, 0x1f, 0x0, 0x61, 0x80, 0xf, 0xc0, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x79, 0xe0, 0x3f, 0xc0, 0xf, 0x0} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {2, 11, 19, 2, 10, 0} +#define NXFONT_BITMAP_241 {0x3c, 0xc0, 0x7f, 0xc0, 0x67, 0x80, 0x0, 0x0, 0x0, 0x0, 0xef, 0x80, 0xff, 0xc0, 0xf1, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_242 {0x1c, 0x0, 0xe, 0x0, 0x7, 0x0, 0x3, 0x80, 0x0, 0x0, 0xf, 0x0, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x79, 0xe0, 0x3f, 0xc0, 0xf, 0x0} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_243 {0x3, 0x80, 0x7, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x0, 0x0, 0xf, 0x0, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x79, 0xe0, 0x3f, 0xc0, 0xf, 0x0} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_244 {0xe, 0x0, 0x1f, 0x0, 0x3b, 0x80, 0x71, 0xc0, 0x0, 0x0, 0xf, 0x0, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x79, 0xe0, 0x3f, 0xc0, 0xf, 0x0} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {2, 12, 19, 1, 10, 0} +#define NXFONT_BITMAP_245 {0x3c, 0xc0, 0x7f, 0xc0, 0x67, 0x80, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x79, 0xe0, 0x3f, 0xc0, 0xf, 0x0} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {2, 12, 18, 1, 11, 0} +#define NXFONT_BITMAP_246 {0x39, 0xc0, 0x39, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x3f, 0xc0, 0x79, 0xe0, 0x70, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x79, 0xe0, 0x3f, 0xc0, 0xf, 0x0} + +/* divide (247) */ +#define NXFONT_METRICS_247 {2, 11, 12, 2, 16, 0} +#define NXFONT_BITMAP_247 {0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {2, 14, 14, 0, 15, 0} +#define NXFONT_BITMAP_248 {0x7, 0x8c, 0x1f, 0xfc, 0x3c, 0xf8, 0x38, 0x70, 0x70, 0xf8, 0x71, 0xf8, 0x73, 0xb8, 0x77, 0x38, 0x7e, 0x38, 0x7c, 0x38, 0x38, 0x70, 0x7c, 0xf0, 0xff, 0xe0, 0xc7, 0x80} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {2, 11, 19, 2, 10, 0} +#define NXFONT_BITMAP_249 {0x38, 0x0, 0x1c, 0x0, 0xe, 0x0, 0x7, 0x0, 0x0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0x73, 0xe0, 0x7e, 0xe0, 0x1c, 0xe0} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {2, 11, 19, 2, 10, 0} +#define NXFONT_BITMAP_250 {0x3, 0x80, 0x7, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0x73, 0xe0, 0x7e, 0xe0, 0x1c, 0xe0} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {2, 11, 19, 2, 10, 0} +#define NXFONT_BITMAP_251 {0xe, 0x0, 0x1f, 0x0, 0x3b, 0x80, 0x71, 0xc0, 0x0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0x73, 0xe0, 0x7e, 0xe0, 0x1c, 0xe0} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {2, 11, 18, 2, 11, 0} +#define NXFONT_BITMAP_252 {0x39, 0xc0, 0x39, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0x73, 0xe0, 0x7e, 0xe0, 0x1c, 0xe0} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {2, 13, 24, 1, 10, 0} +#define NXFONT_BITMAP_253 {0x0, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x7, 0x0, 0x0, 0x0, 0xe0, 0x38, 0xe0, 0x38, 0x70, 0x38, 0x78, 0x70, 0x38, 0x70, 0x3c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0xf, 0xc0, 0xf, 0xc0, 0x7, 0xc0, 0x7, 0x80, 0x3, 0x80, 0x3, 0x80, 0x7, 0x0, 0x7, 0x0, 0xe, 0x0, 0x3e, 0x0, 0x3c, 0x0} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {2, 12, 24, 2, 10, 0} +#define NXFONT_BITMAP_254 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xef, 0x80, 0xff, 0xc0, 0xf9, 0xe0, 0xf0, 0xe0, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xf0, 0xe0, 0xf9, 0xe0, 0xff, 0xc0, 0xef, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {2, 13, 23, 1, 11, 0} +#define NXFONT_BITMAP_255 {0x1c, 0xe0, 0x1c, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x38, 0xe0, 0x38, 0x70, 0x38, 0x78, 0x70, 0x38, 0x70, 0x3c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0xf, 0xc0, 0xf, 0xc0, 0x7, 0xc0, 0x7, 0x80, 0x3, 0x80, 0x3, 0x80, 0x7, 0x0, 0x7, 0x0, 0xe, 0x0, 0x3e, 0x0, 0x3c, 0x0} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SANS28X37B_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_sans39x48.h b/nuttx/graphics/nxfonts/nxfonts_sans39x48.h new file mode 100644 index 0000000000..62aaf1eb3f --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_sans39x48.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_serif39x48.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Jose Pablo Carballo Gomez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SERIF39X48_H +#define __GRAPHICS_NXFONTS_NXFONTS_SERIF39X48_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SERIF39X48 + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 48 +#define NXFONT_MAXWIDTH 39 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 9 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 3, 25, 4, 12, 0} +#define NXFONT_BITMAP_33 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x40, 0x40, 0x0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {1, 8, 8, 2, 14, 0} +#define NXFONT_BITMAP_34 {0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x42, 0x42} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {3, 17, 23, 1, 14, 0} +#define NXFONT_BITMAP_35 {0x3, 0x87, 0x0, 0x3, 0x87, 0x0, 0x3, 0x6, 0x0, 0x3, 0x6, 0x0, 0x7, 0xe, 0x0, 0x7, 0xe, 0x0, 0x7f, 0xff, 0x80, 0x7f, 0xff, 0x80, 0x7f, 0xff, 0x80, 0xe, 0x1c, 0x0, 0xe, 0x1c, 0x0, 0xc, 0x18, 0x0, 0x1c, 0x38, 0x0, 0x1c, 0x38, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0x38, 0x70, 0x0, 0x38, 0x70, 0x0, 0x30, 0x60, 0x0, 0x30, 0x60, 0x0, 0x70, 0xe0, 0x0, 0x70, 0xe0, 0x0} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {2, 16, 31, 1, 10, 0} +#define NXFONT_BITMAP_36 {0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0xf, 0xf0, 0x1f, 0xf8, 0x3d, 0xbc, 0x71, 0x8e, 0x71, 0x8e, 0xe1, 0x8e, 0xe1, 0x80, 0xe1, 0x80, 0x71, 0x80, 0x7d, 0x80, 0x3f, 0xc0, 0x1f, 0xf0, 0x7, 0xfc, 0x1, 0xfe, 0x1, 0x9e, 0x1, 0x8f, 0x1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0x71, 0x8e, 0x71, 0x8e, 0x3d, 0xbc, 0x3f, 0xf8, 0xf, 0xf0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80} + +/* percent (37) */ +#define NXFONT_METRICS_37 {4, 26, 24, 1, 13, 0} +#define NXFONT_BITMAP_37 {0x0, 0x0, 0x30, 0x0, 0x1f, 0x0, 0x70, 0x0, 0x7f, 0x80, 0x60, 0x0, 0x73, 0xc0, 0xe0, 0x0, 0xe0, 0xc0, 0xc0, 0x0, 0xc0, 0xe1, 0xc0, 0x0, 0xc0, 0xe1, 0x80, 0x0, 0xc0, 0xe3, 0x80, 0x0, 0xe0, 0xc3, 0x0, 0x0, 0x73, 0xc7, 0x0, 0x0, 0x7f, 0x86, 0x0, 0x0, 0x1f, 0xe, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1c, 0x3e, 0x0, 0x0, 0x18, 0x7f, 0x80, 0x0, 0x38, 0xf3, 0x80, 0x0, 0x30, 0xc1, 0xc0, 0x0, 0x71, 0xc0, 0xc0, 0x0, 0x61, 0xc0, 0xc0, 0x0, 0xe1, 0xc0, 0xc0, 0x0, 0xc0, 0xc1, 0xc0, 0x1, 0xc0, 0xe3, 0x80, 0x1, 0x80, 0x7f, 0x80, 0x3, 0x80, 0x3e, 0x0} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {3, 18, 23, 2, 14, 0} +#define NXFONT_BITMAP_38 {0x7, 0xc0, 0x0, 0xf, 0xe0, 0x0, 0x1e, 0x70, 0x0, 0x3c, 0x38, 0x0, 0x38, 0x38, 0x0, 0x38, 0x38, 0x0, 0x3c, 0x70, 0x0, 0x1e, 0xf0, 0x0, 0xf, 0xe0, 0x0, 0x7, 0xc0, 0x0, 0xf, 0x80, 0x0, 0x3f, 0xc0, 0x0, 0x79, 0xc7, 0x0, 0x70, 0xe7, 0x0, 0xe0, 0xf6, 0x0, 0xe0, 0x7e, 0x0, 0xe0, 0x3c, 0x0, 0xe0, 0x1c, 0x0, 0xf0, 0x3e, 0x0, 0x78, 0x7f, 0x0, 0x7f, 0xf7, 0x80, 0x3f, 0xe3, 0xc0, 0xf, 0x0, 0x0} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 3, 8, 2, 14, 0} +#define NXFONT_BITMAP_39 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x40} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 7, 31, 2, 13, 0} +#define NXFONT_BITMAP_40 {0x6, 0xc, 0xc, 0x18, 0x18, 0x38, 0x30, 0x70, 0x70, 0x70, 0x60, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x60, 0x70, 0x70, 0x70, 0x30, 0x38, 0x18, 0x18, 0xc, 0xc, 0x6} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 7, 31, 1, 13, 0} +#define NXFONT_BITMAP_41 {0xc0, 0x60, 0x60, 0x30, 0x30, 0x38, 0x18, 0x1c, 0x1c, 0x1c, 0xc, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xc, 0xc, 0x1c, 0x1c, 0x18, 0x18, 0x38, 0x30, 0x70, 0x60, 0x60, 0xc0} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {2, 10, 11, 1, 11, 0} +#define NXFONT_BITMAP_42 {0xc, 0x0, 0xc, 0x0, 0x4c, 0x80, 0xed, 0xc0, 0x7f, 0x80, 0x3f, 0x0, 0x1e, 0x0, 0x3f, 0x0, 0x73, 0x80, 0xe1, 0xc0, 0x40, 0x80} + +/* plus (43) */ +#define NXFONT_METRICS_43 {3, 17, 16, 1, 20, 0} +#define NXFONT_BITMAP_43 {0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 3, 9, 3, 33, 0} +#define NXFONT_BITMAP_44 {0xe0, 0xe0, 0xe0, 0xe0, 0x20, 0x60, 0x60, 0xc0, 0x80} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 8, 2, 1, 27, 0} +#define NXFONT_BITMAP_45 {0xff, 0xff} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 3, 4, 3, 33, 0} +#define NXFONT_BITMAP_46 {0xe0, 0xe0, 0xe0, 0xe0} + +/* slash (47) */ +#define NXFONT_METRICS_47 {2, 9, 24, 0, 13, 0} +#define NXFONT_BITMAP_47 {0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0x8, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* zero (48) */ +#define NXFONT_METRICS_48 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_48 {0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x3c, 0x78, 0x78, 0x3c, 0x70, 0x1c, 0x70, 0x1c, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x3c, 0x3c, 0x78, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* one (49) */ +#define NXFONT_METRICS_49 {1, 8, 24, 3, 13, 0} +#define NXFONT_BITMAP_49 {0x3, 0x7, 0x7, 0xf, 0x3f, 0xff, 0xff, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7} + +/* two (50) */ +#define NXFONT_METRICS_50 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_50 {0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x78, 0x3c, 0x70, 0x1c, 0xf0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x3c, 0x0, 0x78, 0x0, 0xf0, 0x3, 0xe0, 0x7, 0xc0, 0x1f, 0x0, 0x3c, 0x0, 0x78, 0x0, 0x70, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe} + +/* three (51) */ +#define NXFONT_METRICS_51 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_51 {0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x38, 0x38, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x0, 0x1c, 0x0, 0x38, 0x3, 0xf8, 0x3, 0xf0, 0x3, 0xf8, 0x0, 0x3c, 0x0, 0x1e, 0x0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0x70, 0x1c, 0x78, 0x3c, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* four (52) */ +#define NXFONT_METRICS_52 {2, 16, 24, 0, 13, 0} +#define NXFONT_BITMAP_52 {0x0, 0x18, 0x0, 0x38, 0x0, 0x78, 0x0, 0x78, 0x0, 0xf8, 0x1, 0xf8, 0x3, 0xb8, 0x3, 0xb8, 0x7, 0x38, 0xe, 0x38, 0xe, 0x38, 0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x70, 0x38, 0xe0, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38} + +/* five (53) */ +#define NXFONT_METRICS_53 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_53 {0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x70, 0x0, 0x70, 0x0, 0x77, 0xc0, 0x7f, 0xf0, 0x7f, 0xf8, 0x78, 0x7c, 0x70, 0x1c, 0x0, 0x1e, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0xe0, 0xe, 0xe0, 0x1e, 0xf0, 0x1c, 0x78, 0x7c, 0x7f, 0xf8, 0x3f, 0xf0, 0xf, 0x80} + +/* six (54) */ +#define NXFONT_METRICS_54 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_54 {0x3, 0xc0, 0xf, 0xf0, 0x1f, 0xf8, 0x3c, 0x38, 0x38, 0x1c, 0x70, 0x1c, 0x70, 0x0, 0x70, 0x0, 0x60, 0x0, 0xe3, 0xc0, 0xef, 0xf0, 0xff, 0xf8, 0xf8, 0x3c, 0xf0, 0x1c, 0xf0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0x60, 0xe, 0x70, 0xe, 0x70, 0x1c, 0x38, 0x3c, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* seven (55) */ +#define NXFONT_METRICS_55 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_55 {0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x18, 0x0, 0x38, 0x0, 0x70, 0x0, 0x70, 0x0, 0xe0, 0x0, 0xe0, 0x1, 0xc0, 0x1, 0xc0, 0x3, 0x80, 0x3, 0x80, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0} + +/* eight (56) */ +#define NXFONT_METRICS_56 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_56 {0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x38, 0x3c, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x78, 0x3c, 0x3c, 0x78, 0x1f, 0xf0, 0xf, 0xe0, 0x3f, 0xf8, 0x78, 0x3c, 0x70, 0x1c, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xf0, 0x1c, 0x78, 0x3c, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* nine (57) */ +#define NXFONT_METRICS_57 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_57 {0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x78, 0x7c, 0x70, 0x3c, 0xf0, 0x1c, 0xe0, 0x1e, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0x1e, 0xe0, 0x1e, 0x70, 0x3e, 0x7f, 0xfe, 0x3f, 0xee, 0xf, 0xce, 0x0, 0xe, 0x0, 0x1c, 0xe0, 0x1c, 0xf0, 0x3c, 0x78, 0x78, 0x3f, 0xf0, 0x3f, 0xe0, 0xf, 0x80} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 3, 18, 4, 19, 0} +#define NXFONT_BITMAP_58 {0xe0, 0xe0, 0xe0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 3, 22, 4, 20, 0} +#define NXFONT_BITMAP_59 {0xe0, 0xe0, 0xe0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0, 0x20, 0x60, 0x60, 0xc0, 0x80} + +/* less (60) */ +#define NXFONT_METRICS_60 {2, 16, 16, 2, 21, 0} +#define NXFONT_BITMAP_60 {0x0, 0x3, 0x0, 0xf, 0x0, 0x3f, 0x1, 0xfc, 0x7, 0xe0, 0x1f, 0x80, 0xfe, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xfe, 0x0, 0x1f, 0x80, 0x7, 0xe0, 0x1, 0xfc, 0x0, 0x7f, 0x0, 0xf, 0x0, 0x3} + +/* equal (61) */ +#define NXFONT_METRICS_61 {2, 15, 9, 2, 24, 0} +#define NXFONT_BITMAP_61 {0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe} + +/* greater (62) */ +#define NXFONT_METRICS_62 {2, 16, 16, 1, 21, 0} +#define NXFONT_BITMAP_62 {0xc0, 0x0, 0xf0, 0x0, 0xfe, 0x0, 0x3f, 0x80, 0x7, 0xe0, 0x1, 0xf8, 0x0, 0x7f, 0x0, 0xf, 0x0, 0xf, 0x0, 0x7f, 0x1, 0xf8, 0x7, 0xe0, 0x3f, 0x80, 0xfe, 0x0, 0xf0, 0x0, 0xc0, 0x0} + +/* question (63) */ +#define NXFONT_METRICS_63 {2, 14, 25, 2, 12, 0} +#define NXFONT_BITMAP_63 {0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x78, 0x38, 0x70, 0x1c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x38, 0x0, 0x70, 0x0, 0xe0, 0x1, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x0, 0x0, 0x0, 0x0, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80} + +/* at (64) */ +#define NXFONT_METRICS_64 {4, 29, 30, 1, 12, 0} +#define NXFONT_BITMAP_64 {0x0, 0x7, 0xc0, 0x0, 0x0, 0x3f, 0xf8, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x3, 0xf0, 0x3f, 0x80, 0x7, 0xc0, 0x7, 0xc0, 0xf, 0x0, 0x3, 0xe0, 0x1e, 0x0, 0x1, 0xe0, 0x1c, 0x0, 0x0, 0xf0, 0x38, 0xf, 0x8c, 0x70, 0x38, 0x1f, 0xdc, 0x38, 0x70, 0x3c, 0xfc, 0x38, 0x70, 0x70, 0x7c, 0x38, 0x60, 0xe0, 0x38, 0x18, 0xe0, 0xe0, 0x38, 0x18, 0xe1, 0xe0, 0x38, 0x18, 0xe1, 0xc0, 0x70, 0x38, 0xe1, 0xc0, 0x70, 0x38, 0xe1, 0xc0, 0x70, 0x70, 0xe1, 0xc0, 0xe0, 0x70, 0xe1, 0xe0, 0xe0, 0xe0, 0x70, 0xf3, 0xf3, 0xc0, 0x70, 0xff, 0x7f, 0x80, 0x78, 0x3e, 0x7f, 0x0, 0x3c, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0x3, 0xe0, 0x78, 0x0, 0x1, 0xff, 0xf8, 0x0, 0x0, 0x7f, 0xe0, 0x0} + +/* A (65) */ +#define NXFONT_METRICS_65 {3, 20, 25, 1, 12, 0} +#define NXFONT_BITMAP_65 {0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x3, 0x9c, 0x0, 0x3, 0x9c, 0x0, 0x3, 0x9c, 0x0, 0x7, 0x9e, 0x0, 0x7, 0xe, 0x0, 0x7, 0xe, 0x0, 0xf, 0xf, 0x0, 0xf, 0xf, 0x0, 0xe, 0x7, 0x0, 0x1e, 0x7, 0x80, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x3f, 0xff, 0xc0, 0x3c, 0x3, 0xc0, 0x38, 0x1, 0xc0, 0x78, 0x1, 0xe0, 0x78, 0x1, 0xe0, 0x70, 0x0, 0xe0, 0xf0, 0x0, 0xf0, 0xf0, 0x0, 0xf0} + +/* B (66) */ +#define NXFONT_METRICS_66 {3, 17, 25, 3, 12, 0} +#define NXFONT_BITMAP_66 {0xff, 0xf0, 0x0, 0xff, 0xfc, 0x0, 0xff, 0xfe, 0x0, 0xe0, 0x3e, 0x0, 0xe0, 0xf, 0x0, 0xe0, 0xf, 0x0, 0xe0, 0x7, 0x0, 0xe0, 0x7, 0x0, 0xe0, 0xf, 0x0, 0xe0, 0xe, 0x0, 0xe0, 0x3e, 0x0, 0xff, 0xfc, 0x0, 0xff, 0xfc, 0x0, 0xff, 0xfe, 0x0, 0xe0, 0x1f, 0x0, 0xe0, 0x7, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x7, 0x80, 0xe0, 0xf, 0x0, 0xff, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0xff, 0xf8, 0x0} + +/* C (67) */ +#define NXFONT_METRICS_67 {3, 20, 25, 2, 12, 0} +#define NXFONT_BITMAP_67 {0x1, 0xfc, 0x0, 0x7, 0xff, 0x0, 0xf, 0xff, 0x80, 0x1f, 0x7, 0xc0, 0x3c, 0x1, 0xe0, 0x38, 0x0, 0xe0, 0x70, 0x0, 0xf0, 0x70, 0x0, 0x70, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x70, 0xf0, 0x0, 0x70, 0x70, 0x0, 0xf0, 0x78, 0x0, 0xe0, 0x3c, 0x1, 0xe0, 0x3f, 0x7, 0xc0, 0x1f, 0xff, 0x80, 0x7, 0xfe, 0x0, 0x1, 0xf8, 0x0} + +/* D (68) */ +#define NXFONT_METRICS_68 {3, 18, 25, 3, 12, 0} +#define NXFONT_BITMAP_68 {0xff, 0xf0, 0x0, 0xff, 0xfc, 0x0, 0xff, 0xfe, 0x0, 0xe0, 0x1f, 0x0, 0xe0, 0xf, 0x0, 0xe0, 0x7, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x3, 0xc0, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x7, 0x80, 0xe0, 0xf, 0x0, 0xe0, 0x1e, 0x0, 0xff, 0xfe, 0x0, 0xff, 0xfc, 0x0, 0xff, 0xf0, 0x0} + +/* E (69) */ +#define NXFONT_METRICS_69 {3, 17, 25, 3, 12, 0} +#define NXFONT_BITMAP_69 {0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80} + +/* F (70) */ +#define NXFONT_METRICS_70 {2, 16, 25, 3, 12, 0} +#define NXFONT_BITMAP_70 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* G (71) */ +#define NXFONT_METRICS_71 {3, 22, 25, 1, 12, 0} +#define NXFONT_BITMAP_71 {0x0, 0xfe, 0x0, 0x3, 0xff, 0x80, 0xf, 0xff, 0xc0, 0x1f, 0x83, 0xf0, 0x3e, 0x0, 0xf0, 0x3c, 0x0, 0x78, 0x78, 0x0, 0x38, 0x70, 0x0, 0x38, 0xf0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0xf, 0xfc, 0xe0, 0xf, 0xfc, 0xe0, 0xf, 0xfc, 0xe0, 0x0, 0x1c, 0xf0, 0x0, 0x1c, 0x70, 0x0, 0x1c, 0x78, 0x0, 0x3c, 0x38, 0x0, 0x3c, 0x3c, 0x0, 0xfc, 0x1f, 0x1, 0xfc, 0xf, 0xff, 0xdc, 0x7, 0xff, 0x1c, 0x1, 0xfc, 0x1c} + +/* H (72) */ +#define NXFONT_METRICS_72 {3, 18, 25, 3, 12, 0} +#define NXFONT_BITMAP_72 {0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 3, 25, 3, 12, 0} +#define NXFONT_BITMAP_73 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* J (74) */ +#define NXFONT_METRICS_74 {2, 13, 25, 1, 12, 0} +#define NXFONT_BITMAP_74 {0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xf0, 0x78, 0x78, 0xf0, 0x7f, 0xf0, 0x3f, 0xe0, 0x1f, 0x80} + +/* K (75) */ +#define NXFONT_METRICS_75 {3, 20, 25, 3, 12, 0} +#define NXFONT_BITMAP_75 {0xe0, 0x3, 0xc0, 0xe0, 0x7, 0x80, 0xe0, 0xf, 0x0, 0xe0, 0x1e, 0x0, 0xe0, 0x3c, 0x0, 0xe0, 0x78, 0x0, 0xe0, 0xf0, 0x0, 0xe1, 0xe0, 0x0, 0xe3, 0xc0, 0x0, 0xe7, 0xc0, 0x0, 0xef, 0x80, 0x0, 0xff, 0xc0, 0x0, 0xff, 0xc0, 0x0, 0xf9, 0xe0, 0x0, 0xf0, 0xf0, 0x0, 0xe0, 0x70, 0x0, 0xe0, 0x78, 0x0, 0xe0, 0x3c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1e, 0x0, 0xe0, 0xf, 0x0, 0xe0, 0x7, 0x80, 0xe0, 0x3, 0xc0, 0xe0, 0x3, 0xe0, 0xe0, 0x1, 0xf0} + +/* L (76) */ +#define NXFONT_METRICS_76 {2, 14, 25, 3, 12, 0} +#define NXFONT_BITMAP_76 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc} + +/* M (77) */ +#define NXFONT_METRICS_77 {3, 21, 25, 3, 12, 0} +#define NXFONT_BITMAP_77 {0xf0, 0x0, 0x78, 0xf0, 0x0, 0x78, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xfc, 0x1, 0xf8, 0xfc, 0x1, 0xf8, 0xfc, 0x1, 0xf8, 0xec, 0x1, 0xb8, 0xee, 0x3, 0xb8, 0xee, 0x3, 0xb8, 0xe6, 0x3, 0x38, 0xe7, 0x7, 0x38, 0xe7, 0x7, 0x38, 0xe3, 0x6, 0x38, 0xe3, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0xe1, 0x8c, 0x38, 0xe1, 0xdc, 0x38, 0xe1, 0xdc, 0x38, 0xe0, 0xd8, 0x38, 0xe0, 0xf8, 0x38, 0xe0, 0xf8, 0x38, 0xe0, 0x70, 0x38, 0xe0, 0x70, 0x38} + +/* N (78) */ +#define NXFONT_METRICS_78 {3, 19, 25, 2, 12, 0} +#define NXFONT_BITMAP_78 {0xf0, 0x0, 0xe0, 0xf0, 0x0, 0xe0, 0xf8, 0x0, 0xe0, 0xfc, 0x0, 0xe0, 0xfc, 0x0, 0xe0, 0xfe, 0x0, 0xe0, 0xef, 0x0, 0xe0, 0xe7, 0x0, 0xe0, 0xe7, 0x80, 0xe0, 0xe3, 0xc0, 0xe0, 0xe3, 0xc0, 0xe0, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xe0, 0xe0, 0x78, 0xe0, 0xe0, 0x38, 0xe0, 0xe0, 0x3c, 0xe0, 0xe0, 0x1c, 0xe0, 0xe0, 0x1e, 0xe0, 0xe0, 0xf, 0xe0, 0xe0, 0x7, 0xe0, 0xe0, 0x7, 0xe0, 0xe0, 0x3, 0xe0, 0xe0, 0x1, 0xe0, 0xe0, 0x1, 0xe0} + +/* O (79) */ +#define NXFONT_METRICS_79 {3, 23, 25, 1, 12, 0} +#define NXFONT_BITMAP_79 {0x0, 0xfe, 0x0, 0x3, 0xff, 0x80, 0xf, 0xef, 0xe0, 0x1f, 0x1, 0xf0, 0x3e, 0x0, 0xf8, 0x3c, 0x0, 0x78, 0x78, 0x0, 0x3c, 0x70, 0x0, 0x1c, 0xf0, 0x0, 0x1e, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xf0, 0x0, 0x1e, 0xf0, 0x0, 0x1e, 0x78, 0x0, 0x3c, 0x3c, 0x0, 0x78, 0x3e, 0x0, 0xf8, 0x1f, 0x1, 0xf0, 0xf, 0xef, 0xe0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* P (80) */ +#define NXFONT_METRICS_80 {3, 17, 25, 3, 12, 0} +#define NXFONT_BITMAP_80 {0xff, 0xf8, 0x0, 0xff, 0xfe, 0x0, 0xff, 0xff, 0x0, 0xe0, 0xf, 0x0, 0xe0, 0x7, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x7, 0x80, 0xe0, 0xf, 0x0, 0xff, 0xff, 0x0, 0xff, 0xfe, 0x0, 0xff, 0xf8, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {3, 23, 26, 1, 12, 0} +#define NXFONT_BITMAP_81 {0x0, 0xfe, 0x0, 0x3, 0xff, 0x80, 0xf, 0xef, 0xe0, 0x1f, 0x1, 0xf0, 0x3e, 0x0, 0xf8, 0x3c, 0x0, 0x78, 0x78, 0x0, 0x3c, 0x70, 0x0, 0x1c, 0xf0, 0x0, 0x1e, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xf0, 0x0, 0x1e, 0xf0, 0x2, 0x1e, 0x78, 0x7, 0x3c, 0x3c, 0x7, 0xb8, 0x3e, 0x3, 0xf8, 0x1f, 0x1, 0xf0, 0xf, 0xef, 0xf8, 0x3, 0xff, 0xbc, 0x0, 0xfe, 0x1e, 0x0, 0x0, 0xc} + +/* R (82) */ +#define NXFONT_METRICS_82 {3, 19, 25, 3, 12, 0} +#define NXFONT_BITMAP_82 {0xff, 0xfc, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x80, 0xe0, 0x7, 0x80, 0xe0, 0x3, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x3, 0xc0, 0xe0, 0x3, 0x80, 0xe0, 0xf, 0x80, 0xff, 0xff, 0x0, 0xff, 0xfe, 0x0, 0xff, 0xff, 0x0, 0xe0, 0xf, 0x80, 0xe0, 0x7, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0xc0, 0xe0, 0x3, 0xc0, 0xe0, 0x3, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xe0} + +/* S (83) */ +#define NXFONT_METRICS_83 {3, 19, 25, 1, 12, 0} +#define NXFONT_BITMAP_83 {0x3, 0xf8, 0x0, 0xf, 0xfe, 0x0, 0x1f, 0xff, 0x0, 0x3c, 0xf, 0x80, 0x38, 0x3, 0xc0, 0x70, 0x1, 0xc0, 0x70, 0x1, 0xc0, 0x70, 0x0, 0x0, 0x78, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x1f, 0xf8, 0x0, 0x7, 0xff, 0x0, 0x0, 0x7f, 0x80, 0x0, 0xf, 0xc0, 0x0, 0x1, 0xe0, 0x0, 0x0, 0xe0, 0xe0, 0x0, 0xe0, 0xf0, 0x0, 0xe0, 0x70, 0x1, 0xe0, 0x78, 0x1, 0xc0, 0x3e, 0x7, 0xc0, 0x3f, 0xff, 0x80, 0xf, 0xfe, 0x0, 0x3, 0xf8, 0x0} + +/* T (84) */ +#define NXFONT_METRICS_84 {3, 19, 25, 0, 12, 0} +#define NXFONT_BITMAP_84 {0xff, 0xff, 0xe0, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xe0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0} + +/* U (85) */ +#define NXFONT_METRICS_85 {3, 18, 25, 3, 12, 0} +#define NXFONT_BITMAP_85 {0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xf0, 0x3, 0xc0, 0x78, 0x7, 0x80, 0x7c, 0xf, 0x80, 0x3f, 0xff, 0x0, 0x1f, 0xfe, 0x0, 0x3, 0xf0, 0x0} + +/* V (86) */ +#define NXFONT_METRICS_86 {3, 19, 25, 1, 12, 0} +#define NXFONT_BITMAP_86 {0xf0, 0x1, 0xe0, 0xf0, 0x1, 0xe0, 0xf0, 0x1, 0xe0, 0x70, 0x1, 0xc0, 0x78, 0x3, 0xc0, 0x78, 0x3, 0xc0, 0x38, 0x3, 0x80, 0x38, 0x3, 0x80, 0x3c, 0x7, 0x80, 0x1c, 0x7, 0x0, 0x1c, 0x7, 0x0, 0x1e, 0xf, 0x0, 0xe, 0xe, 0x0, 0xe, 0xe, 0x0, 0xf, 0xe, 0x0, 0x7, 0x1c, 0x0, 0x7, 0x1c, 0x0, 0x7, 0x9c, 0x0, 0x3, 0xb8, 0x0, 0x3, 0xb8, 0x0, 0x3, 0xb8, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {4, 29, 25, 1, 12, 0} +#define NXFONT_BITMAP_87 {0xf0, 0x7, 0x0, 0x78, 0xf0, 0x7, 0x0, 0x78, 0xf0, 0xf, 0x80, 0x78, 0x70, 0xf, 0x80, 0x70, 0x70, 0xf, 0x80, 0x70, 0x78, 0x1d, 0xc0, 0xf0, 0x78, 0x1d, 0xc0, 0xf0, 0x38, 0x1d, 0xc0, 0xe0, 0x38, 0x1d, 0xc0, 0xe0, 0x38, 0x38, 0xe0, 0xe0, 0x3c, 0x38, 0xe1, 0xe0, 0x1c, 0x38, 0xe1, 0xc0, 0x1c, 0x30, 0xe1, 0xc0, 0x1c, 0x70, 0x71, 0xc0, 0x1c, 0x70, 0x71, 0xc0, 0xe, 0x70, 0x73, 0x80, 0xe, 0xe0, 0x3b, 0x80, 0xe, 0xe0, 0x3b, 0x80, 0xe, 0xe0, 0x3b, 0x80, 0x7, 0xe0, 0x3f, 0x80, 0x7, 0xc0, 0x1f, 0x0, 0x7, 0xc0, 0x1f, 0x0, 0x7, 0xc0, 0x1f, 0x0, 0x3, 0x80, 0xe, 0x0, 0x3, 0x80, 0xe, 0x0} + +/* X (88) */ +#define NXFONT_METRICS_88 {3, 20, 25, 1, 12, 0} +#define NXFONT_BITMAP_88 {0xf8, 0x0, 0xf0, 0x78, 0x1, 0xe0, 0x3c, 0x3, 0xc0, 0x1c, 0x3, 0xc0, 0x1e, 0x7, 0x80, 0xf, 0x7, 0x0, 0xf, 0xf, 0x0, 0x7, 0x9e, 0x0, 0x3, 0x9c, 0x0, 0x3, 0xfc, 0x0, 0x1, 0xf8, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x3, 0x9c, 0x0, 0x7, 0x9e, 0x0, 0x7, 0xe, 0x0, 0xf, 0xf, 0x0, 0x1e, 0x7, 0x80, 0x1e, 0x7, 0x80, 0x3c, 0x3, 0xc0, 0x78, 0x1, 0xe0, 0x78, 0x1, 0xe0, 0xf0, 0x0, 0xf0} + +/* Y (89) */ +#define NXFONT_METRICS_89 {3, 21, 25, 0, 12, 0} +#define NXFONT_BITMAP_89 {0xf0, 0x0, 0x78, 0x78, 0x0, 0xf0, 0x78, 0x0, 0xe0, 0x3c, 0x1, 0xe0, 0x1c, 0x1, 0xc0, 0x1e, 0x3, 0xc0, 0xe, 0x7, 0x80, 0xf, 0x7, 0x80, 0x7, 0x8f, 0x0, 0x3, 0x8e, 0x0, 0x3, 0xde, 0x0, 0x1, 0xdc, 0x0, 0x1, 0xfc, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x70, 0x0, 0x0, 0x70, 0x0, 0x0, 0x70, 0x0, 0x0, 0x70, 0x0, 0x0, 0x70, 0x0, 0x0, 0x70, 0x0, 0x0, 0x70, 0x0, 0x0, 0x70, 0x0, 0x0, 0x70, 0x0, 0x0, 0x70, 0x0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {3, 18, 25, 1, 12, 0} +#define NXFONT_BITMAP_90 {0x7f, 0xff, 0xc0, 0x7f, 0xff, 0xc0, 0x7f, 0xff, 0xc0, 0x0, 0x7, 0x80, 0x0, 0xf, 0x80, 0x0, 0xf, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x78, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x3, 0xc0, 0x0, 0x7, 0x80, 0x0, 0x7, 0x80, 0x0, 0xf, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x78, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 6, 32, 2, 12, 0} +#define NXFONT_BITMAP_91 {0xfc, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xfc, 0xfc} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {2, 9, 24, 0, 13, 0} +#define NXFONT_BITMAP_92 {0xc0, 0x0, 0xc0, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x10, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x1, 0x80, 0x1, 0x80} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 6, 32, 1, 12, 0} +#define NXFONT_BITMAP_93 {0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {2, 12, 13, 1, 13, 0} +#define NXFONT_BITMAP_94 {0x6, 0x0, 0xf, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x19, 0x80, 0x19, 0x80, 0x39, 0xc0, 0x30, 0xc0, 0x70, 0xe0, 0x60, 0x60, 0x60, 0x60, 0xe0, 0x70, 0xc0, 0x30} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {3, 18, 2, 0, 41, 0} +#define NXFONT_BITMAP_95 {0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 6, 5, 1, 12, 0} +#define NXFONT_BITMAP_96 {0xe0, 0xf0, 0x70, 0x38, 0x1c} + +/* a (97) */ +#define NXFONT_METRICS_97 {2, 16, 18, 1, 19, 0} +#define NXFONT_BITMAP_97 {0xf, 0xe0, 0x3f, 0xf8, 0x3c, 0x78, 0x70, 0x3c, 0x70, 0x1c, 0x0, 0x1c, 0x0, 0x3c, 0x1, 0xfc, 0x1f, 0xfc, 0x7e, 0x1c, 0x78, 0x1c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xe0, 0x7c, 0x79, 0xfe, 0x7f, 0xdf, 0x3f, 0x8f} + +/* b (98) */ +#define NXFONT_METRICS_98 {2, 15, 25, 2, 12, 0} +#define NXFONT_BITMAP_98 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe3, 0xe0, 0xef, 0xf0, 0xff, 0xf8, 0xf8, 0x3c, 0xf0, 0x1c, 0xf0, 0x1e, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xf0, 0x1e, 0xf0, 0x1c, 0xfc, 0x3c, 0xff, 0xf8, 0xef, 0xf0, 0xe7, 0xe0} + +/* c (99) */ +#define NXFONT_METRICS_99 {2, 14, 18, 1, 19, 0} +#define NXFONT_BITMAP_99 {0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x38, 0x3c, 0x70, 0x1c, 0x70, 0x1c, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x1c, 0xe0, 0x1c, 0x70, 0x1c, 0x78, 0x38, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* d (100) */ +#define NXFONT_METRICS_100 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_100 {0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x7, 0xce, 0x1f, 0xee, 0x3f, 0xfe, 0x7c, 0x3e, 0x70, 0x1e, 0xf0, 0x1e, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xf0, 0x1e, 0xf0, 0x1e, 0x78, 0x3e, 0x7f, 0xfe, 0x3f, 0xee, 0xf, 0xce} + +/* e (101) */ +#define NXFONT_METRICS_101 {2, 15, 18, 2, 19, 0} +#define NXFONT_BITMAP_101 {0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x78, 0x3c, 0x70, 0x1c, 0xf0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xff, 0xfe, 0xff, 0xfe, 0xe0, 0x0, 0xe0, 0x0, 0xf0, 0xe, 0x70, 0x1e, 0x78, 0x3c, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* f (102) */ +#define NXFONT_METRICS_102 {1, 8, 25, 1, 12, 0} +#define NXFONT_BITMAP_102 {0xf, 0x1f, 0x3c, 0x38, 0x38, 0x38, 0x38, 0xff, 0xff, 0xff, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38} + +/* g (103) */ +#define NXFONT_METRICS_103 {2, 15, 25, 1, 19, 0} +#define NXFONT_BITMAP_103 {0x7, 0xce, 0x1f, 0xee, 0x3f, 0xfe, 0x7c, 0x3e, 0x70, 0x1e, 0xf0, 0x1e, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xf0, 0x1e, 0x70, 0x3e, 0x78, 0x3e, 0x3f, 0xfe, 0x1f, 0xee, 0x7, 0x8e, 0x0, 0xe, 0xe0, 0xe, 0xe0, 0x1c, 0xf0, 0x1c, 0x7c, 0x78, 0x3f, 0xf8, 0x1f, 0xe0} + +/* h (104) */ +#define NXFONT_METRICS_104 {2, 14, 25, 2, 12, 0} +#define NXFONT_BITMAP_104 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe3, 0xe0, 0xef, 0xf0, 0xff, 0xf8, 0xf8, 0x3c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 3, 25, 2, 12, 0} +#define NXFONT_BITMAP_105 {0xe0, 0xe0, 0xe0, 0xe0, 0x0, 0x0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* j (106) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_106 {1, 6, 32, 0, 12, 0} +#define NXFONT_BITMAP_106 {0x1c, 0x1c, 0x1c, 0x1c, 0x0, 0x0, 0x0, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x3c, 0xfc, 0xf8} + +/* k (107) */ +#define NXFONT_METRICS_107 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_107 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x78, 0xe0, 0xf0, 0xe1, 0xe0, 0xe3, 0xc0, 0xe7, 0x80, 0xef, 0x0, 0xff, 0x0, 0xff, 0x0, 0xfb, 0x80, 0xf3, 0xc0, 0xe1, 0xc0, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xe0, 0x78, 0xe0, 0x38, 0xe0, 0x3c, 0xe0, 0x1e} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 3, 25, 2, 12, 0} +#define NXFONT_BITMAP_108 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* m (109) */ +#define NXFONT_METRICS_109 {3, 23, 18, 2, 19, 0} +#define NXFONT_BITMAP_109 {0xe3, 0xc0, 0xf0, 0xef, 0xf3, 0xfc, 0xff, 0xf7, 0xfc, 0xf8, 0x7e, 0x1e, 0xf0, 0x3c, 0xe, 0xe0, 0x38, 0xe, 0xe0, 0x38, 0xe, 0xe0, 0x38, 0xe, 0xe0, 0x38, 0xe, 0xe0, 0x38, 0xe, 0xe0, 0x38, 0xe, 0xe0, 0x38, 0xe, 0xe0, 0x38, 0xe, 0xe0, 0x38, 0xe, 0xe0, 0x38, 0xe, 0xe0, 0x38, 0xe, 0xe0, 0x38, 0xe, 0xe0, 0x38, 0xe} + +/* n (110) */ +#define NXFONT_METRICS_110 {2, 14, 18, 2, 19, 0} +#define NXFONT_BITMAP_110 {0xe3, 0xe0, 0xef, 0xf8, 0xff, 0xf8, 0xf8, 0x3c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c} + +/* o (111) */ +#define NXFONT_METRICS_111 {2, 15, 18, 1, 19, 0} +#define NXFONT_BITMAP_111 {0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x78, 0x3c, 0x70, 0x1c, 0xf0, 0x1e, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xf0, 0x1e, 0x70, 0x1c, 0x78, 0x3c, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* p (112) */ +#define NXFONT_METRICS_112 {2, 15, 25, 2, 19, 0} +#define NXFONT_BITMAP_112 {0x3, 0xc0, 0xef, 0xf0, 0xff, 0xf8, 0xf8, 0x3c, 0xf0, 0x1c, 0xf0, 0x1e, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xf0, 0x1e, 0xf0, 0x1c, 0xf8, 0x3c, 0xff, 0xf8, 0xef, 0xf0, 0xe7, 0xe0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* q (113) */ +#define NXFONT_METRICS_113 {2, 15, 25, 1, 19, 0} +#define NXFONT_BITMAP_113 {0x7, 0xc0, 0x1f, 0xee, 0x3f, 0xfe, 0x7c, 0x3e, 0x70, 0x1e, 0xf0, 0x1e, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xf0, 0x1e, 0x70, 0x1e, 0x78, 0x3e, 0x3f, 0xfe, 0x1f, 0xee, 0xf, 0xce, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe} + +/* r (114) */ +#define NXFONT_METRICS_114 {1, 8, 18, 2, 19, 0} +#define NXFONT_BITMAP_114 {0xe7, 0xef, 0xff, 0xfc, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* s (115) */ +#define NXFONT_METRICS_115 {2, 13, 18, 2, 19, 0} +#define NXFONT_BITMAP_115 {0xf, 0x80, 0x3f, 0xe0, 0x7f, 0xe0, 0x70, 0xf0, 0xe0, 0x70, 0xe0, 0x0, 0x70, 0x0, 0x7e, 0x0, 0x3f, 0xc0, 0x7, 0xf0, 0x0, 0xf0, 0x0, 0x78, 0xe0, 0x38, 0xe0, 0x38, 0xf0, 0x70, 0x7f, 0xf0, 0x7f, 0xe0, 0x1f, 0x80} + +/* t (116) */ +#define NXFONT_METRICS_116 {1, 8, 22, 1, 15, 0} +#define NXFONT_BITMAP_116 {0x38, 0x38, 0x38, 0x38, 0xff, 0xff, 0xff, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x3c, 0x3f, 0x1f} + +/* u (117) */ +#define NXFONT_METRICS_117 {2, 14, 18, 2, 19, 0} +#define NXFONT_BITMAP_117 {0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xf0, 0x7c, 0x7f, 0xfc, 0x7f, 0xdc, 0x1f, 0x1c} + +/* v (118) */ +#define NXFONT_METRICS_118 {2, 15, 18, 0, 19, 0} +#define NXFONT_BITMAP_118 {0xe0, 0xe, 0xe0, 0xe, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0x7, 0xc0, 0x7, 0xc0, 0x3, 0x80, 0x3, 0x80} + +/* w (119) */ +#define NXFONT_METRICS_119 {3, 23, 18, 0, 19, 0} +#define NXFONT_BITMAP_119 {0xe0, 0x38, 0xe, 0xe0, 0x38, 0xe, 0x70, 0x7c, 0x1c, 0x70, 0x7c, 0x1c, 0x70, 0x6c, 0x1c, 0x38, 0xee, 0x1c, 0x38, 0xee, 0x38, 0x38, 0xee, 0x38, 0x38, 0xc6, 0x38, 0x18, 0xc6, 0x30, 0x1d, 0xc7, 0x70, 0x1d, 0xc7, 0x70, 0x1d, 0xc7, 0x70, 0xd, 0x83, 0x60, 0xf, 0x83, 0xe0, 0xf, 0x83, 0xe0, 0x7, 0x1, 0xc0, 0x7, 0x1, 0xc0} + +/* x (120) */ +#define NXFONT_METRICS_120 {2, 15, 18, 0, 19, 0} +#define NXFONT_BITMAP_120 {0xf0, 0x1e, 0x78, 0x1c, 0x38, 0x38, 0x3c, 0x70, 0x1c, 0x70, 0xe, 0xe0, 0xf, 0xe0, 0x7, 0xc0, 0x3, 0x80, 0x7, 0xc0, 0x7, 0xc0, 0xf, 0xe0, 0x1e, 0xe0, 0x1c, 0x70, 0x38, 0x78, 0x38, 0x38, 0x70, 0x1c, 0xf0, 0x1e} + +/* y (121) */ +#define NXFONT_METRICS_121 {2, 14, 25, 1, 19, 0} +#define NXFONT_BITMAP_121 {0xe0, 0x1c, 0xe0, 0x1c, 0xf0, 0x38, 0x70, 0x38, 0x70, 0x38, 0x70, 0x70, 0x38, 0x70, 0x38, 0x70, 0x38, 0xe0, 0x3c, 0xe0, 0x1c, 0xe0, 0x1d, 0xc0, 0x1d, 0xc0, 0xf, 0xc0, 0xf, 0x80, 0xf, 0x80, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x7c, 0x0, 0x78, 0x0, 0x70, 0x0} + +/* z (122) */ +#define NXFONT_METRICS_122 {2, 14, 18, 1, 19, 0} +#define NXFONT_BITMAP_122 {0x7f, 0xf8, 0x7f, 0xf8, 0x7f, 0xf8, 0x0, 0x78, 0x0, 0xf0, 0x0, 0xe0, 0x1, 0xc0, 0x3, 0xc0, 0x7, 0x80, 0x7, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x3c, 0x0, 0x78, 0x0, 0x70, 0x0, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {1, 8, 32, 1, 12, 0} +#define NXFONT_BITMAP_123 {0xf, 0x1f, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0x38, 0x70, 0xe0, 0xe0, 0x70, 0x38, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x1f, 0xf} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 2, 31, 3, 13, 0} +#define NXFONT_BITMAP_124 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 8, 32, 1, 12, 0} +#define NXFONT_BITMAP_125 {0xf0, 0xf8, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x1c, 0xe, 0x7, 0x7, 0xe, 0x1c, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0xf8, 0xf0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {2, 14, 6, 2, 22, 0} +#define NXFONT_BITMAP_126 {0x18, 0x0, 0x7c, 0xc, 0x7f, 0xc, 0xc7, 0xdc, 0xc1, 0xf8, 0x0, 0xf0} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 3, 25, 4, 19, 0} +#define NXFONT_BITMAP_161 {0xe0, 0xe0, 0xe0, 0xe0, 0x0, 0x0, 0x40, 0x40, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* cent (162) */ +#define NXFONT_METRICS_162 {2, 14, 25, 2, 16, 0} +#define NXFONT_BITMAP_162 {0x0, 0x20, 0x0, 0x60, 0x0, 0x40, 0x7, 0xe0, 0x1f, 0xf0, 0x3c, 0xf8, 0x78, 0xbc, 0x70, 0x9c, 0x70, 0x9c, 0xe1, 0x80, 0xe1, 0x0, 0xe1, 0x0, 0xe3, 0x0, 0xe3, 0x0, 0xe2, 0xc, 0xe2, 0x1c, 0x76, 0x1c, 0x7c, 0x3c, 0x3c, 0x78, 0x1f, 0xf0, 0xf, 0xe0, 0x8, 0x0, 0x18, 0x0, 0x10, 0x0, 0x10, 0x0} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_163 {0x3, 0xc0, 0xf, 0xf8, 0x1f, 0xfc, 0x3c, 0x3c, 0x78, 0x1e, 0x70, 0xe, 0x70, 0xe, 0x70, 0x0, 0x70, 0x0, 0x38, 0x0, 0x38, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xc, 0x0, 0xe, 0x0, 0xe, 0x0, 0xc, 0x0, 0x1c, 0x0, 0x18, 0x0, 0x38, 0x0, 0x73, 0x86, 0xff, 0xfe, 0xff, 0xfe, 0x60, 0x7c} + +/* currency (164) */ +#define NXFONT_METRICS_164 {2, 12, 13, 3, 19, 0} +#define NXFONT_BITMAP_164 {0xe6, 0x30, 0xff, 0xf0, 0x7f, 0xf0, 0x70, 0xe0, 0x60, 0x60, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0x60, 0x60, 0x70, 0xe0, 0x7f, 0xf0, 0xff, 0xf0, 0xe6, 0x30} + +/* yen (165) */ +#define NXFONT_METRICS_165 {2, 16, 24, 1, 13, 0} +#define NXFONT_BITMAP_165 {0xe0, 0x7, 0xe0, 0x7, 0x70, 0xe, 0x70, 0xe, 0x38, 0x1c, 0x38, 0x1c, 0x1c, 0x38, 0x1c, 0x38, 0xe, 0x70, 0xe, 0x70, 0x7, 0xe0, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x1, 0xc0, 0x1, 0xc0, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x1, 0xc0, 0x1, 0xc0, 0x1, 0xc0, 0x1, 0xc0, 0x1, 0xc0} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 2, 32, 3, 12, 0} +#define NXFONT_BITMAP_166 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* section (167) */ +#define NXFONT_METRICS_167 {2, 15, 32, 1, 12, 0} +#define NXFONT_BITMAP_167 {0x3, 0xc0, 0xf, 0xf0, 0x1f, 0xf8, 0x1c, 0x78, 0x38, 0x3c, 0x38, 0x1c, 0x38, 0x1c, 0x3c, 0x0, 0x1e, 0x0, 0x1f, 0x80, 0x3f, 0xe0, 0x71, 0xf0, 0xe0, 0xf8, 0xe0, 0x7c, 0xe0, 0x1c, 0xe0, 0x1e, 0x70, 0xe, 0x7c, 0xe, 0x3e, 0xe, 0x1f, 0x1c, 0xf, 0x9c, 0x3, 0xf8, 0x1, 0xf0, 0x0, 0xf0, 0x0, 0x78, 0x70, 0x38, 0x70, 0x38, 0x78, 0x38, 0x38, 0x70, 0x3f, 0xf0, 0x1f, 0xe0, 0x7, 0x80} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 8, 3, 1, 12, 0} +#define NXFONT_BITMAP_168 {0xe7, 0xe7, 0xe7} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {3, 24, 25, 0, 12, 0} +#define NXFONT_BITMAP_169 {0x0, 0xfe, 0x0, 0x3, 0xff, 0x80, 0x7, 0x1, 0xe0, 0xc, 0x0, 0x70, 0x18, 0x0, 0x18, 0x30, 0x7e, 0xc, 0x60, 0xff, 0x86, 0x61, 0xc1, 0xc6, 0xc3, 0x80, 0xc3, 0xc3, 0x0, 0x3, 0xc7, 0x0, 0x3, 0x86, 0x0, 0x1, 0x86, 0x0, 0x1, 0x86, 0x0, 0x1, 0x86, 0x0, 0x1, 0xc7, 0x0, 0x3, 0xc3, 0x80, 0xc3, 0x61, 0xe1, 0xc6, 0x60, 0xff, 0x86, 0x30, 0x3e, 0xc, 0x18, 0x0, 0x18, 0x1c, 0x0, 0x38, 0x7, 0x1, 0xe0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {2, 10, 15, 1, 12, 0} +#define NXFONT_BITMAP_170 {0x3f, 0x0, 0x77, 0x80, 0x61, 0x80, 0x1, 0x80, 0x7, 0x80, 0x7f, 0x80, 0xe1, 0x80, 0xc1, 0x80, 0xc3, 0x80, 0xe7, 0x80, 0x7d, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {2, 12, 9, 3, 23, 0} +#define NXFONT_BITMAP_171 {0x1c, 0x70, 0x38, 0xe0, 0x71, 0xc0, 0xe3, 0x80, 0xc3, 0x0, 0xe3, 0x80, 0x71, 0xc0, 0x38, 0xe0, 0x1c, 0x70} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {2, 16, 9, 1, 25, 0} +#define NXFONT_BITMAP_172 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 8, 2, 1, 27, 0} +#define NXFONT_BITMAP_173 {0xff, 0xff} + +/* registered (174) */ +#define NXFONT_METRICS_174 {3, 24, 25, 0, 12, 0} +#define NXFONT_BITMAP_174 {0x0, 0x7e, 0x0, 0x3, 0xff, 0x80, 0x7, 0x1, 0xe0, 0xc, 0x0, 0x70, 0x18, 0x0, 0x18, 0x30, 0x0, 0xc, 0x61, 0xff, 0x6, 0x61, 0xff, 0x86, 0xc1, 0x81, 0xc3, 0xc1, 0x80, 0xc3, 0xc1, 0x80, 0xc3, 0x81, 0x81, 0x81, 0x81, 0xff, 0x1, 0x81, 0xfc, 0x1, 0x81, 0x8e, 0x1, 0xc1, 0x86, 0x3, 0xc1, 0x83, 0x3, 0x61, 0x81, 0x86, 0x61, 0x81, 0xc6, 0x30, 0x0, 0xc, 0x18, 0x0, 0x18, 0x1c, 0x0, 0x38, 0x7, 0x1, 0xe0, 0x3, 0xff, 0x80, 0x0, 0x7e, 0x0} + +/* macron (175) */ +#define NXFONT_METRICS_175 {2, 9, 2, 1, 13, 0} +#define NXFONT_BITMAP_175 {0xff, 0x80, 0xff, 0x80} + +/* degree (176) */ +#define NXFONT_METRICS_176 {2, 9, 9, 2, 13, 0} +#define NXFONT_BITMAP_176 {0x3e, 0x0, 0x7f, 0x0, 0xe3, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xe3, 0x80, 0x7f, 0x0, 0x3e, 0x0} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {3, 17, 21, 1, 16, 0} +#define NXFONT_BITMAP_177 {0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {2, 9, 15, 1, 13, 0} +#define NXFONT_BITMAP_178 {0x1e, 0x0, 0x7f, 0x0, 0x63, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0x1, 0x80, 0x3, 0x0, 0x7, 0x0, 0x1e, 0x0, 0x38, 0x0, 0x70, 0x0, 0xe0, 0x0, 0xc0, 0x0, 0xff, 0x80, 0xff, 0x80} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {2, 9, 15, 1, 13, 0} +#define NXFONT_BITMAP_179 {0x3e, 0x0, 0x7f, 0x0, 0xe3, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x3, 0x80, 0xf, 0x0, 0xf, 0x0, 0x3, 0x80, 0x1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xe3, 0x80, 0x7f, 0x0, 0x3e, 0x0} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 7, 5, 3, 10, 0} +#define NXFONT_BITMAP_180 {0x1e, 0x3c, 0x38, 0x70, 0xe0} + +/* mu (181) */ +#define NXFONT_METRICS_181 {2, 14, 24, 2, 19, 0} +#define NXFONT_BITMAP_181 {0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xf0, 0x7c, 0xff, 0xfc, 0xff, 0xdc, 0xff, 0x1c, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {2, 16, 30, 1, 12, 0} +#define NXFONT_BITMAP_182 {0x7, 0xff, 0x1f, 0xff, 0x3f, 0x8c, 0x3f, 0x8c, 0x7f, 0x8c, 0x7f, 0x8c, 0xff, 0x8c, 0xff, 0x8c, 0xff, 0x8c, 0xff, 0x8c, 0x7f, 0x8c, 0x7f, 0x8c, 0x3f, 0x8c, 0x3f, 0x8c, 0x1f, 0x8c, 0x3, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 4, 4, 3, 22, 0} +#define NXFONT_BITMAP_183 {0x60, 0xf0, 0xf0, 0x60} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 7, 7, 2, 37, 0} +#define NXFONT_BITMAP_184 {0x18, 0x18, 0x3c, 0xe, 0x6, 0xce, 0x7c} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 5, 15, 2, 13, 0} +#define NXFONT_BITMAP_185 {0x18, 0x38, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {2, 10, 15, 1, 12, 0} +#define NXFONT_BITMAP_186 {0x1e, 0x0, 0x7f, 0x80, 0x61, 0x80, 0xe1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe1, 0xc0, 0x61, 0x80, 0x7f, 0x80, 0x1e, 0x0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {2, 12, 9, 3, 23, 0} +#define NXFONT_BITMAP_187 {0xe3, 0x80, 0x71, 0xc0, 0x38, 0xe0, 0x1c, 0x70, 0xc, 0x30, 0x1c, 0x70, 0x38, 0xe0, 0x71, 0xc0, 0xe3, 0x80} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {4, 25, 25, 1, 12, 0} +#define NXFONT_BITMAP_188 {0x0, 0x0, 0x30, 0x0, 0x18, 0x0, 0x70, 0x0, 0x38, 0x0, 0x60, 0x0, 0xf8, 0x0, 0xe0, 0x0, 0xf8, 0x1, 0xc0, 0x0, 0x18, 0x1, 0x80, 0x0, 0x18, 0x3, 0x80, 0x0, 0x18, 0x3, 0x0, 0x0, 0x18, 0x7, 0x0, 0x0, 0x18, 0xe, 0x0, 0x0, 0x18, 0xc, 0x0, 0x0, 0x18, 0x1c, 0x6, 0x0, 0x18, 0x18, 0xe, 0x0, 0x18, 0x38, 0x1e, 0x0, 0x18, 0x70, 0x3e, 0x0, 0x18, 0x60, 0x76, 0x0, 0x0, 0xe0, 0x66, 0x0, 0x1, 0xc0, 0xc6, 0x0, 0x1, 0x81, 0xc6, 0x0, 0x3, 0x83, 0x86, 0x0, 0x3, 0x3, 0xff, 0x80, 0x7, 0x3, 0xff, 0x80, 0x6, 0x0, 0x6, 0x0, 0xe, 0x0, 0x6, 0x0, 0xc, 0x0, 0x6, 0x0} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {4, 25, 25, 1, 12, 0} +#define NXFONT_BITMAP_189 {0x0, 0x0, 0x60, 0x0, 0x18, 0x0, 0xe0, 0x0, 0x38, 0x0, 0xc0, 0x0, 0xf8, 0x1, 0x80, 0x0, 0xf8, 0x3, 0x80, 0x0, 0x18, 0x3, 0x0, 0x0, 0x18, 0x6, 0x0, 0x0, 0x18, 0xe, 0x0, 0x0, 0x18, 0xc, 0x0, 0x0, 0x18, 0x1c, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x18, 0x38, 0x3c, 0x0, 0x18, 0x30, 0xff, 0x0, 0x18, 0x70, 0xc3, 0x80, 0x18, 0x61, 0x81, 0x80, 0x18, 0xc1, 0x81, 0x80, 0x1, 0xc0, 0x3, 0x80, 0x1, 0x80, 0x7, 0x0, 0x3, 0x80, 0xe, 0x0, 0x3, 0x0, 0x3c, 0x0, 0x6, 0x0, 0x70, 0x0, 0xe, 0x0, 0xe0, 0x0, 0xc, 0x1, 0xc0, 0x0, 0x1c, 0x1, 0xff, 0x80, 0x18, 0x1, 0xff, 0x80} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {4, 25, 24, 1, 13, 0} +#define NXFONT_BITMAP_190 {0x3e, 0x0, 0xe, 0x0, 0x7f, 0x0, 0xc, 0x0, 0x63, 0x80, 0x18, 0x0, 0xc1, 0x80, 0x38, 0x0, 0xc1, 0x80, 0x30, 0x0, 0x3, 0x80, 0x60, 0x0, 0xf, 0x0, 0xe0, 0x0, 0xf, 0x80, 0xc0, 0x0, 0x1, 0xc1, 0x80, 0x0, 0x0, 0xc3, 0x80, 0x0, 0xc0, 0xc3, 0x6, 0x0, 0xc0, 0xc7, 0xe, 0x0, 0x61, 0xce, 0x1e, 0x0, 0x7f, 0x8c, 0x3e, 0x0, 0x1e, 0x18, 0x76, 0x0, 0x0, 0x38, 0x66, 0x0, 0x0, 0x30, 0xc6, 0x0, 0x0, 0x61, 0xc6, 0x0, 0x0, 0xe3, 0x86, 0x0, 0x1, 0xc3, 0xff, 0x80, 0x1, 0x83, 0xff, 0x80, 0x3, 0x0, 0x6, 0x0, 0x7, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {2, 14, 25, 3, 19, 0} +#define NXFONT_BITMAP_191 {0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x0, 0x0, 0x0, 0x0, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x7, 0x80, 0x7, 0x0, 0xf, 0x0, 0x1e, 0x0, 0x3c, 0x0, 0x78, 0x0, 0x70, 0x0, 0xf0, 0x0, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xf0, 0x3c, 0x78, 0x78, 0x7f, 0xf0, 0x3f, 0xe0, 0x7, 0x80} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {3, 20, 31, 1, 6, 0} +#define NXFONT_BITMAP_192 {0x3, 0xc0, 0x0, 0x1, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x3, 0xfc, 0x0, 0x3, 0x9c, 0x0, 0x3, 0x9c, 0x0, 0x7, 0x9e, 0x0, 0x7, 0xe, 0x0, 0x7, 0xe, 0x0, 0xf, 0xf, 0x0, 0xe, 0xf, 0x0, 0xe, 0x7, 0x0, 0x1e, 0x7, 0x80, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x3f, 0xff, 0xc0, 0x3c, 0x3, 0xc0, 0x38, 0x1, 0xc0, 0x78, 0x1, 0xe0, 0x78, 0x1, 0xe0, 0x70, 0x0, 0xe0, 0xf0, 0x0, 0xf0, 0xf0, 0x0, 0xf0} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {3, 20, 31, 1, 6, 0} +#define NXFONT_BITMAP_193 {0x0, 0x3c, 0x0, 0x0, 0x78, 0x0, 0x0, 0x70, 0x0, 0x0, 0xe0, 0x0, 0x1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x3, 0xfc, 0x0, 0x3, 0x9c, 0x0, 0x3, 0x9c, 0x0, 0x7, 0x9e, 0x0, 0x7, 0xe, 0x0, 0x7, 0xe, 0x0, 0xf, 0xf, 0x0, 0xf, 0xf, 0x0, 0xe, 0x7, 0x0, 0x1e, 0x7, 0x80, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x3f, 0xff, 0xc0, 0x3c, 0x3, 0xc0, 0x78, 0x1, 0xc0, 0x78, 0x1, 0xe0, 0x78, 0x1, 0xe0, 0x70, 0x0, 0xe0, 0xf0, 0x0, 0xf0, 0xf0, 0x0, 0xf0} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {3, 20, 31, 1, 6, 0} +#define NXFONT_BITMAP_194 {0x0, 0x40, 0x0, 0x0, 0xe0, 0x0, 0x1, 0xf0, 0x0, 0x3, 0xb8, 0x0, 0x7, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x3, 0xfc, 0x0, 0x3, 0x9c, 0x0, 0x3, 0x9c, 0x0, 0x7, 0x9e, 0x0, 0x7, 0xe, 0x0, 0x7, 0xe, 0x0, 0xf, 0xf, 0x0, 0xf, 0xf, 0x0, 0xe, 0x7, 0x0, 0x1e, 0x7, 0x80, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x3f, 0xff, 0xc0, 0x3c, 0x3, 0xc0, 0x38, 0x1, 0xc0, 0x78, 0x1, 0xe0, 0x78, 0x1, 0xe0, 0x70, 0x0, 0xe0, 0xf0, 0x0, 0xf0, 0xf0, 0x0, 0xf0} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {3, 20, 30, 1, 7, 0} +#define NXFONT_BITMAP_195 {0x1, 0xc6, 0x0, 0x3, 0xfe, 0x0, 0x7, 0xfc, 0x0, 0x6, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x3, 0xfc, 0x0, 0x3, 0x9c, 0x0, 0x3, 0x9c, 0x0, 0x7, 0x9e, 0x0, 0x7, 0xe, 0x0, 0x7, 0xe, 0x0, 0xf, 0xf, 0x0, 0xf, 0xf, 0x0, 0xe, 0x7, 0x0, 0x1e, 0x7, 0x80, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x3f, 0xff, 0xc0, 0x3c, 0x3, 0xc0, 0x38, 0x1, 0xc0, 0x78, 0x1, 0xe0, 0x78, 0x1, 0xe0, 0x70, 0x0, 0xe0, 0xf0, 0x0, 0xf0, 0xf0, 0x0, 0xf0} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {3, 20, 30, 1, 7, 0} +#define NXFONT_BITMAP_196 {0x3, 0x9c, 0x0, 0x3, 0x9c, 0x0, 0x3, 0x9c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x3, 0xfc, 0x0, 0x3, 0x9c, 0x0, 0x3, 0x9c, 0x0, 0x7, 0x9e, 0x0, 0x7, 0xe, 0x0, 0x7, 0xe, 0x0, 0xf, 0xf, 0x0, 0xf, 0xf, 0x0, 0xe, 0x7, 0x0, 0x1e, 0x7, 0x80, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x3f, 0xff, 0xc0, 0x3c, 0x3, 0xc0, 0x38, 0x1, 0xc0, 0x78, 0x1, 0xe0, 0x78, 0x1, 0xe0, 0x70, 0x0, 0xe0, 0xf0, 0x0, 0xf0, 0xf0, 0x0, 0xf0} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {3, 20, 31, 1, 6, 0} +#define NXFONT_BITMAP_197 {0x0, 0xf0, 0x0, 0x1, 0x98, 0x0, 0x1, 0x8, 0x0, 0x1, 0x8, 0x0, 0x1, 0x98, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x3, 0xfc, 0x0, 0x3, 0x9c, 0x0, 0x3, 0x9c, 0x0, 0x7, 0x9e, 0x0, 0x7, 0xe, 0x0, 0x7, 0xe, 0x0, 0xf, 0xf, 0x0, 0xe, 0xf, 0x0, 0xe, 0x7, 0x0, 0x1e, 0x7, 0x80, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x3f, 0xff, 0xc0, 0x3c, 0x3, 0xc0, 0x38, 0x1, 0xc0, 0x78, 0x1, 0xe0, 0x78, 0x1, 0xe0, 0x70, 0x0, 0xe0, 0xf0, 0x0, 0xf0, 0xf0, 0x0, 0xf0} + +/* AE (198) */ +#define NXFONT_METRICS_198 {4, 29, 25, 1, 12, 0} +#define NXFONT_BITMAP_198 {0x0, 0x7f, 0xff, 0xf8, 0x0, 0x7f, 0xff, 0xf8, 0x0, 0xff, 0xff, 0xf8, 0x0, 0xe3, 0x80, 0x0, 0x1, 0xc3, 0x80, 0x0, 0x1, 0xc3, 0x80, 0x0, 0x3, 0xc3, 0x80, 0x0, 0x3, 0x83, 0x80, 0x0, 0x3, 0x83, 0x80, 0x0, 0x7, 0x83, 0x80, 0x0, 0x7, 0x3, 0x80, 0x0, 0x7, 0x3, 0xff, 0xf0, 0xf, 0x3, 0xff, 0xf0, 0xe, 0x3, 0xff, 0xf0, 0x1e, 0x3, 0x80, 0x0, 0x1f, 0xff, 0x80, 0x0, 0x1f, 0xff, 0x80, 0x0, 0x3f, 0xff, 0x80, 0x0, 0x38, 0x3, 0x80, 0x0, 0x78, 0x3, 0x80, 0x0, 0x78, 0x3, 0x80, 0x0, 0x70, 0x3, 0x80, 0x0, 0xf0, 0x3, 0xff, 0xf8, 0xe0, 0x3, 0xff, 0xf8, 0xe0, 0x3, 0xff, 0xf8} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {3, 20, 32, 2, 12, 0} +#define NXFONT_BITMAP_199 {0x1, 0xf8, 0x0, 0x7, 0xfe, 0x0, 0xf, 0xff, 0x80, 0x1f, 0x7, 0x80, 0x3c, 0x3, 0xc0, 0x78, 0x1, 0xe0, 0x70, 0x0, 0xe0, 0x70, 0x0, 0xe0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xf0, 0x0, 0x70, 0xf0, 0x0, 0x70, 0x70, 0x0, 0xf0, 0x70, 0x0, 0xe0, 0x78, 0x1, 0xe0, 0x3c, 0x3, 0xc0, 0x1f, 0x7, 0xc0, 0xf, 0xff, 0x80, 0x7, 0xfe, 0x0, 0x1, 0xf8, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x18, 0x0, 0x3, 0x38, 0x0, 0x1, 0xf0, 0x0} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {3, 17, 31, 3, 6, 0} +#define NXFONT_BITMAP_200 {0xf, 0x0, 0x0, 0x7, 0x80, 0x0, 0x3, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {3, 17, 31, 3, 6, 0} +#define NXFONT_BITMAP_201 {0x0, 0x78, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xe0, 0x0, 0x1, 0xc0, 0x0, 0x3, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {3, 17, 31, 3, 6, 0} +#define NXFONT_BITMAP_202 {0x0, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x3, 0xe0, 0x0, 0x7, 0x70, 0x0, 0xe, 0x38, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {3, 17, 30, 3, 7, 0} +#define NXFONT_BITMAP_203 {0x1c, 0x38, 0x0, 0x1c, 0x38, 0x0, 0x1c, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {1, 7, 31, 0, 6, 0} +#define NXFONT_BITMAP_204 {0xf0, 0x78, 0x38, 0x1c, 0xe, 0x0, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 7, 31, 2, 6, 0} +#define NXFONT_BITMAP_205 {0x1e, 0x3c, 0x38, 0x70, 0xe0, 0x0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70} + +/* Icircumflex (206) */ +#define NXFONT_METRICS_206 {2, 9, 31, 0, 6, 0} +#define NXFONT_BITMAP_206 {0x8, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0x77, 0x0, 0xe3, 0x80, 0x0, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {2, 9, 30, 0, 7, 0} +#define NXFONT_BITMAP_207 {0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0} + +/* Eth (208) */ +#define NXFONT_METRICS_208 {3, 21, 25, 0, 12, 0} +#define NXFONT_BITMAP_208 {0x1f, 0xfe, 0x0, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0xc0, 0x1c, 0x3, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xf0, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0x38, 0x1c, 0x0, 0x38, 0x1c, 0x0, 0x38, 0xff, 0xc0, 0x38, 0xff, 0xc0, 0x38, 0x1c, 0x0, 0x38, 0x1c, 0x0, 0x38, 0x1c, 0x0, 0x38, 0x1c, 0x0, 0x78, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0xf0, 0x1c, 0x0, 0xe0, 0x1c, 0x3, 0xc0, 0x1f, 0xff, 0xc0, 0x1f, 0xff, 0x80, 0x1f, 0xfe, 0x0} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {3, 19, 30, 2, 7, 0} +#define NXFONT_BITMAP_209 {0x1, 0xc6, 0x0, 0x3, 0xfe, 0x0, 0x7, 0xfc, 0x0, 0x6, 0x38, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x0, 0xe0, 0xf8, 0x0, 0xe0, 0xf8, 0x0, 0xe0, 0xfc, 0x0, 0xe0, 0xfc, 0x0, 0xe0, 0xfe, 0x0, 0xe0, 0xef, 0x0, 0xe0, 0xe7, 0x0, 0xe0, 0xe7, 0x80, 0xe0, 0xe3, 0xc0, 0xe0, 0xe3, 0xc0, 0xe0, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xe0, 0xe0, 0x78, 0xe0, 0xe0, 0x38, 0xe0, 0xe0, 0x3c, 0xe0, 0xe0, 0x1c, 0xe0, 0xe0, 0x1e, 0xe0, 0xe0, 0xf, 0xe0, 0xe0, 0x7, 0xe0, 0xe0, 0x7, 0xe0, 0xe0, 0x3, 0xe0, 0xe0, 0x1, 0xe0, 0xe0, 0x1, 0xe0} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {3, 23, 31, 1, 6, 0} +#define NXFONT_BITMAP_210 {0x0, 0xf0, 0x0, 0x0, 0x78, 0x0, 0x0, 0x38, 0x0, 0x0, 0x1c, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x3, 0xff, 0x80, 0xf, 0xff, 0xe0, 0x1f, 0x1, 0xf0, 0x3e, 0x0, 0xf8, 0x3c, 0x0, 0x78, 0x78, 0x0, 0x3c, 0x70, 0x0, 0x1c, 0x70, 0x0, 0x1c, 0xf0, 0x0, 0x1e, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xf0, 0x0, 0x1e, 0xf0, 0x0, 0x1e, 0x70, 0x0, 0x1c, 0x78, 0x0, 0x3c, 0x3c, 0x0, 0x78, 0x3e, 0x0, 0xf8, 0x1f, 0x1, 0xf0, 0xf, 0xff, 0xe0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {3, 23, 31, 1, 6, 0} +#define NXFONT_BITMAP_211 {0x0, 0xf, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x38, 0x0, 0x0, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x3, 0xff, 0x80, 0xf, 0xff, 0xe0, 0x1f, 0x1, 0xf0, 0x3e, 0x0, 0xf8, 0x3c, 0x0, 0x78, 0x78, 0x0, 0x3c, 0x70, 0x0, 0x1c, 0x70, 0x0, 0x1c, 0xf0, 0x0, 0x1e, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xf0, 0x0, 0x1e, 0xf0, 0x0, 0x1e, 0x70, 0x0, 0x1c, 0x78, 0x0, 0x3c, 0x3c, 0x0, 0x78, 0x3e, 0x0, 0xf8, 0x1f, 0x1, 0xf0, 0xf, 0xff, 0xe0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {3, 23, 31, 1, 6, 0} +#define NXFONT_BITMAP_212 {0x0, 0x10, 0x0, 0x0, 0x38, 0x0, 0x0, 0x7c, 0x0, 0x0, 0xee, 0x0, 0x1, 0xc7, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x3, 0xff, 0x80, 0xf, 0xff, 0xe0, 0x1f, 0x1, 0xf0, 0x3e, 0x0, 0xf8, 0x3c, 0x0, 0x78, 0x78, 0x0, 0x3c, 0x70, 0x0, 0x1c, 0x70, 0x0, 0x1c, 0xf0, 0x0, 0x1e, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xf0, 0x0, 0x1e, 0xf0, 0x0, 0x1e, 0x70, 0x0, 0x1c, 0x78, 0x0, 0x3c, 0x3c, 0x0, 0x78, 0x3e, 0x0, 0xf8, 0x1f, 0x1, 0xf0, 0xf, 0xff, 0xe0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {3, 23, 30, 1, 7, 0} +#define NXFONT_BITMAP_213 {0x0, 0x71, 0x80, 0x0, 0xff, 0x80, 0x1, 0xff, 0x0, 0x1, 0x8e, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x3, 0xff, 0x80, 0xf, 0xff, 0xe0, 0x1f, 0x1, 0xf0, 0x3e, 0x0, 0xf8, 0x3c, 0x0, 0x78, 0x78, 0x0, 0x3c, 0x70, 0x0, 0x1c, 0x70, 0x0, 0x1c, 0xf0, 0x0, 0x1e, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xf0, 0x0, 0x1e, 0xf0, 0x0, 0x1e, 0x70, 0x0, 0x1c, 0x78, 0x0, 0x3c, 0x3c, 0x0, 0x78, 0x3e, 0x0, 0xf8, 0x1f, 0x1, 0xf0, 0xf, 0xff, 0xe0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {3, 23, 29, 1, 8, 0} +#define NXFONT_BITMAP_214 {0x1, 0xc3, 0x80, 0x1, 0xc3, 0x80, 0x1, 0xc3, 0x80, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x3, 0xff, 0x80, 0xf, 0xff, 0xe0, 0x1f, 0x1, 0xf0, 0x3e, 0x0, 0xf8, 0x3c, 0x0, 0x78, 0x78, 0x0, 0x3c, 0x70, 0x0, 0x1c, 0x70, 0x0, 0x1c, 0xf0, 0x0, 0x1e, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xe0, 0x0, 0xe, 0xf0, 0x0, 0x1e, 0xf0, 0x0, 0x1e, 0x70, 0x0, 0x1c, 0x78, 0x0, 0x3c, 0x3c, 0x0, 0x78, 0x3e, 0x0, 0xf8, 0x1f, 0x1, 0xf0, 0xf, 0xff, 0xe0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {2, 15, 15, 2, 21, 0} +#define NXFONT_BITMAP_215 {0x40, 0x4, 0xe0, 0xe, 0xf0, 0x1e, 0x78, 0x3c, 0x3c, 0x78, 0x1f, 0xf0, 0xf, 0xe0, 0x7, 0xc0, 0x7, 0xc0, 0xf, 0xe0, 0x1e, 0xf0, 0x3c, 0x78, 0x78, 0x3c, 0xf0, 0x1e, 0x60, 0xc} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {3, 23, 25, 1, 12, 0} +#define NXFONT_BITMAP_216 {0x0, 0xfe, 0x6, 0x3, 0xff, 0x8c, 0xf, 0xff, 0xf8, 0x1f, 0x1, 0xf0, 0x3e, 0x0, 0xf8, 0x3c, 0x0, 0xf8, 0x78, 0x1, 0xbc, 0x70, 0x3, 0x1c, 0x70, 0x6, 0x1c, 0xf0, 0x6, 0x1e, 0xe0, 0xc, 0xe, 0xe0, 0x18, 0xe, 0xe0, 0x30, 0xe, 0xe0, 0x60, 0xe, 0xe0, 0xc0, 0xe, 0xe1, 0x80, 0x1e, 0xf3, 0x0, 0x1e, 0x76, 0x0, 0x1c, 0x7c, 0x0, 0x3c, 0x3c, 0x0, 0x78, 0x3e, 0x0, 0xf8, 0x3f, 0x1, 0xf0, 0x6f, 0xff, 0xe0, 0xc3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {3, 18, 31, 3, 6, 0} +#define NXFONT_BITMAP_217 {0x7, 0x80, 0x0, 0x3, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xf0, 0x3, 0xc0, 0x78, 0x7, 0x80, 0x7c, 0xf, 0x80, 0x3f, 0xff, 0x0, 0x1f, 0xfe, 0x0, 0x3, 0xf0, 0x0} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {3, 18, 31, 3, 6, 0} +#define NXFONT_BITMAP_218 {0x0, 0x78, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xe0, 0x0, 0x1, 0xc0, 0x0, 0x3, 0x80, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xf0, 0x3, 0xc0, 0x78, 0x7, 0x80, 0x7c, 0xf, 0x80, 0x3f, 0xff, 0x0, 0x1f, 0xfe, 0x0, 0x3, 0xf0, 0x0} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {3, 18, 31, 3, 6, 0} +#define NXFONT_BITMAP_219 {0x0, 0x40, 0x0, 0x0, 0xe0, 0x0, 0x1, 0xf0, 0x0, 0x3, 0xb8, 0x0, 0x7, 0x1c, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xf0, 0x3, 0xc0, 0x78, 0x7, 0x80, 0x7c, 0xf, 0x80, 0x3f, 0xff, 0x0, 0x1f, 0xfe, 0x0, 0x3, 0xf0, 0x0} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {3, 18, 30, 3, 7, 0} +#define NXFONT_BITMAP_220 {0xe, 0x1c, 0x0, 0xe, 0x1c, 0x0, 0xe, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xe0, 0x1, 0xc0, 0xf0, 0x3, 0xc0, 0x78, 0x7, 0x80, 0x7c, 0xf, 0x80, 0x3f, 0xff, 0x0, 0x1f, 0xfe, 0x0, 0x3, 0xf0, 0x0} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {3, 19, 31, 1, 6, 0} +#define NXFONT_BITMAP_221 {0x0, 0x3c, 0x0, 0x0, 0x78, 0x0, 0x0, 0x70, 0x0, 0x0, 0xe0, 0x0, 0x1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0xe0, 0xf0, 0x1, 0xe0, 0x70, 0x1, 0xc0, 0x78, 0x3, 0xc0, 0x38, 0x3, 0x80, 0x3c, 0x7, 0x80, 0x1c, 0xf, 0x0, 0x1e, 0xf, 0x0, 0xf, 0x1e, 0x0, 0x7, 0x1c, 0x0, 0x7, 0xbc, 0x0, 0x3, 0xb8, 0x0, 0x3, 0xf8, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {3, 17, 25, 3, 12, 0} +#define NXFONT_BITMAP_222 {0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xff, 0xf8, 0x0, 0xff, 0xfe, 0x0, 0xff, 0xff, 0x0, 0xe0, 0xf, 0x0, 0xe0, 0x7, 0x0, 0xe0, 0x7, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x3, 0x80, 0xe0, 0x7, 0x80, 0xe0, 0x7, 0x0, 0xe0, 0xf, 0x0, 0xff, 0xfe, 0x0, 0xff, 0xfc, 0x0, 0xff, 0xf8, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {2, 14, 25, 4, 12, 0} +#define NXFONT_BITMAP_223 {0xf, 0x80, 0x3f, 0xe0, 0x7f, 0xf0, 0x78, 0xf0, 0xf0, 0x78, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x78, 0xe0, 0xf0, 0xe3, 0xe0, 0xe3, 0xe0, 0xe3, 0xf0, 0xe0, 0x78, 0xe0, 0x3c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x38, 0xe0, 0x78, 0xe7, 0xf0, 0xe7, 0xe0, 0xe7, 0x80} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {2, 16, 25, 1, 12, 0} +#define NXFONT_BITMAP_224 {0xf, 0x0, 0x7, 0x80, 0x3, 0x80, 0x1, 0xc0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x3f, 0xf8, 0x3c, 0x7c, 0x70, 0x1c, 0x70, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0xfc, 0x1f, 0xfc, 0x7f, 0x9c, 0x78, 0x1c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xe0, 0x7c, 0x79, 0xfc, 0x7f, 0xdf, 0x3f, 0x8f} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {2, 16, 25, 1, 12, 0} +#define NXFONT_BITMAP_225 {0x0, 0xf0, 0x1, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x3f, 0xf8, 0x3c, 0x7c, 0x70, 0x1c, 0x70, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0xfc, 0x1f, 0xfc, 0x7f, 0x9c, 0x78, 0x1c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xe0, 0x7c, 0x78, 0xfc, 0x7f, 0xdf, 0x3f, 0x8f} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {2, 16, 25, 1, 12, 0} +#define NXFONT_BITMAP_226 {0x1, 0x0, 0x3, 0x80, 0x7, 0xc0, 0xe, 0xe0, 0x1c, 0x70, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x3f, 0xf8, 0x3c, 0x7c, 0x70, 0x1c, 0x70, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0xfc, 0x1f, 0xfc, 0x7f, 0x9c, 0x78, 0x1c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xe0, 0x7c, 0x78, 0xfc, 0x7f, 0xdf, 0x3f, 0x8f} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {2, 16, 24, 1, 13, 0} +#define NXFONT_BITMAP_227 {0x7, 0x18, 0xf, 0xf8, 0x1f, 0xf0, 0x18, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x3f, 0xf8, 0x3c, 0x7c, 0x70, 0x1c, 0x70, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0xfc, 0x1f, 0xfc, 0x7f, 0x9c, 0x78, 0x1c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xe0, 0x7c, 0x78, 0xfc, 0x7f, 0xdf, 0x3f, 0x8f} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {2, 16, 23, 1, 14, 0} +#define NXFONT_BITMAP_228 {0xe, 0x70, 0xe, 0x70, 0xe, 0x70, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x3f, 0xf8, 0x3c, 0xfc, 0x70, 0x1c, 0x70, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0xfc, 0x1f, 0xfc, 0x7f, 0x9c, 0x78, 0x1c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xe0, 0x7c, 0x79, 0xfc, 0x7f, 0xdf, 0x3f, 0x8f} + +/* aring (229) */ +#define NXFONT_METRICS_229 {2, 16, 25, 1, 12, 0} +#define NXFONT_BITMAP_229 {0x3, 0x80, 0x6, 0xc0, 0x4, 0x40, 0x4, 0x40, 0x6, 0xc0, 0x3, 0x80, 0x0, 0x0, 0xf, 0xe0, 0x3f, 0xf8, 0x3c, 0x7c, 0x70, 0x1c, 0x70, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0xfc, 0x1f, 0xfc, 0x7f, 0x9c, 0x78, 0x1c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xe0, 0x7c, 0x78, 0xfc, 0x7f, 0xdf, 0x3f, 0x8f} + +/* ae (230) */ +#define NXFONT_METRICS_230 {4, 26, 18, 1, 19, 0} +#define NXFONT_BITMAP_230 {0x7, 0xc0, 0xf8, 0x0, 0x1f, 0xf1, 0xfe, 0x0, 0x3c, 0x7f, 0x8f, 0x0, 0x70, 0x3e, 0x3, 0x80, 0x70, 0x1e, 0x3, 0x80, 0x0, 0x1c, 0x1, 0xc0, 0x0, 0x1c, 0x1, 0xc0, 0x0, 0xfc, 0x1, 0xc0, 0xf, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xff, 0xc0, 0x7e, 0x1f, 0xff, 0xc0, 0xf0, 0x1c, 0x0, 0x0, 0xe0, 0x1c, 0x1, 0xc0, 0xe0, 0x1e, 0x1, 0xc0, 0xe0, 0x7e, 0x3, 0x80, 0xf8, 0xf7, 0x8f, 0x0, 0x7f, 0xe7, 0xff, 0x0, 0x3f, 0x81, 0xfc, 0x0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {2, 14, 25, 1, 19, 0} +#define NXFONT_BITMAP_231 {0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x38, 0x38, 0x70, 0x1c, 0x70, 0x1c, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x1c, 0xe0, 0x1c, 0x70, 0x38, 0x78, 0x78, 0x3f, 0xf0, 0x1f, 0xe0, 0x7, 0x80, 0x3, 0x0, 0x3, 0x0, 0x7, 0x80, 0x1, 0xc0, 0x0, 0xc0, 0x19, 0xc0, 0xf, 0x80} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_232 {0x1e, 0x0, 0xf, 0x0, 0x7, 0x0, 0x3, 0x80, 0x1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc0, 0x1f, 0xf0, 0x3e, 0x78, 0x78, 0x1c, 0x70, 0x1c, 0xf0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xff, 0xfe, 0xff, 0xfe, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0xe, 0x70, 0xe, 0x78, 0x1c, 0x3c, 0x7c, 0x1f, 0xf0, 0xf, 0xe0} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_233 {0x1, 0xe0, 0x3, 0xc0, 0x3, 0x80, 0x7, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc0, 0x1f, 0xf0, 0x3c, 0x78, 0x78, 0x1c, 0x70, 0x1c, 0xf0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xff, 0xfe, 0xff, 0xfe, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0xe, 0x70, 0xe, 0x78, 0x1c, 0x3c, 0x7c, 0x1f, 0xf0, 0xf, 0xe0} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_234 {0x1, 0x0, 0x3, 0x80, 0x7, 0xc0, 0xe, 0xe0, 0x1c, 0x70, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc0, 0x1f, 0xf0, 0x3c, 0x78, 0x78, 0x1c, 0x70, 0x1c, 0xf0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xff, 0xfe, 0xff, 0xfe, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0xe, 0x70, 0xe, 0x78, 0x1c, 0x3c, 0x7c, 0x1f, 0xf0, 0x7, 0xc0} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {2, 15, 23, 1, 14, 0} +#define NXFONT_BITMAP_235 {0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc0, 0x1f, 0xf0, 0x3c, 0x78, 0x78, 0x1c, 0x70, 0x1c, 0xf0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xff, 0xfe, 0xff, 0xfe, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0xe, 0x70, 0xe, 0x78, 0x1c, 0x3c, 0x7c, 0x1f, 0xf0, 0x7, 0xc0} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 7, 25, 0, 12, 0} +#define NXFONT_BITMAP_236 {0xf0, 0x78, 0x38, 0x1c, 0xe, 0x0, 0x0, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 7, 25, 2, 12, 0} +#define NXFONT_BITMAP_237 {0x1e, 0x3c, 0x38, 0x70, 0xe0, 0x0, 0x0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70} + +/* icircumflex (238) */ +#define NXFONT_METRICS_238 {2, 9, 25, 0, 12, 0} +#define NXFONT_BITMAP_238 {0x8, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0x77, 0x0, 0xe3, 0x80, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 8, 23, 1, 14, 0} +#define NXFONT_BITMAP_239 {0xe7, 0xe7, 0xe7, 0x0, 0x0, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38} + +/* eth (240) */ +#define NXFONT_METRICS_240 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_240 {0x78, 0x40, 0x3c, 0xe0, 0x1f, 0xc0, 0xf, 0x80, 0x1f, 0x80, 0x3b, 0xc0, 0x11, 0xe0, 0x7, 0xf0, 0x1f, 0xf8, 0x3f, 0xf8, 0x78, 0x3c, 0x70, 0x1c, 0x70, 0x1c, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0x70, 0x1c, 0x70, 0x1c, 0x78, 0x3c, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {2, 14, 24, 2, 13, 0} +#define NXFONT_BITMAP_241 {0xe, 0x30, 0x1f, 0xf0, 0x3f, 0xe0, 0x31, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xc0, 0xef, 0xf0, 0xff, 0xf8, 0xf8, 0x3c, 0xf0, 0x1c, 0xf0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_242 {0x1e, 0x0, 0xf, 0x0, 0x7, 0x0, 0x3, 0x80, 0x1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x78, 0x3c, 0x70, 0x1c, 0x70, 0x1c, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0x70, 0x1c, 0x70, 0x1c, 0x78, 0x3c, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_243 {0x1, 0xe0, 0x3, 0xc0, 0x3, 0x80, 0x7, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x78, 0x3c, 0x70, 0x1c, 0x70, 0x1c, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0x70, 0x1c, 0x70, 0x1c, 0x78, 0x3c, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_244 {0x1, 0x0, 0x3, 0x80, 0x7, 0xc0, 0xe, 0xe0, 0x1c, 0x70, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x78, 0x3c, 0x70, 0x1c, 0x70, 0x1c, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0x70, 0x1c, 0x70, 0x1c, 0x78, 0x3c, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_245 {0xe, 0x30, 0x1f, 0xf0, 0x3f, 0xe0, 0x31, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x78, 0x3c, 0x70, 0x1c, 0x70, 0x1c, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0x70, 0x1c, 0x70, 0x1c, 0x78, 0x3c, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {2, 15, 23, 1, 14, 0} +#define NXFONT_BITMAP_246 {0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x78, 0x3c, 0x70, 0x1c, 0x70, 0x1c, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0x70, 0x1c, 0x70, 0x1c, 0x78, 0x3c, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* divide (247) */ +#define NXFONT_METRICS_247 {2, 15, 15, 2, 21, 0} +#define NXFONT_BITMAP_247 {0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {2, 16, 18, 2, 19, 0} +#define NXFONT_BITMAP_248 {0x7, 0xc3, 0x1f, 0xf6, 0x3f, 0xfc, 0x78, 0x78, 0x70, 0x1c, 0x70, 0x3c, 0xe0, 0x6e, 0xe0, 0xce, 0xe1, 0x8e, 0xe3, 0xe, 0xe6, 0xe, 0xec, 0xe, 0x78, 0x1c, 0x70, 0x1c, 0x38, 0x3c, 0x7f, 0xf8, 0xdf, 0xf0, 0x87, 0xc0} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {2, 14, 25, 2, 12, 0} +#define NXFONT_BITMAP_249 {0x1e, 0x0, 0xf, 0x0, 0x7, 0x0, 0x3, 0x80, 0x1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xe0, 0x3c, 0xf0, 0xfc, 0x7f, 0xfc, 0x3f, 0xdc, 0xf, 0x0} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {2, 14, 25, 2, 12, 0} +#define NXFONT_BITMAP_250 {0x1, 0xe0, 0x3, 0xc0, 0x3, 0x80, 0x7, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xe0, 0x3c, 0xf0, 0xfc, 0x7f, 0xfc, 0x3f, 0xdc, 0xf, 0x0} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {2, 14, 25, 2, 12, 0} +#define NXFONT_BITMAP_251 {0x1, 0x0, 0x3, 0x80, 0x7, 0xc0, 0xe, 0xe0, 0x1c, 0x70, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xe0, 0x3c, 0xf0, 0xfc, 0x7f, 0xfc, 0x3f, 0xdc, 0xf, 0x0} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {2, 14, 23, 2, 14, 0} +#define NXFONT_BITMAP_252 {0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xe0, 0x3c, 0xf0, 0xfc, 0x7f, 0xfc, 0x3f, 0xdc, 0xf, 0x0} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {2, 14, 32, 1, 12, 0} +#define NXFONT_BITMAP_253 {0x0, 0xf0, 0x1, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0x70, 0x38, 0x70, 0x38, 0x70, 0x38, 0x78, 0x70, 0x38, 0x70, 0x38, 0xf0, 0x3c, 0xe0, 0x1c, 0xe0, 0x1d, 0xc0, 0x1d, 0xc0, 0xf, 0xc0, 0xf, 0x80, 0xf, 0x80, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1e, 0x0, 0x7c, 0x0, 0x7c, 0x0, 0x70, 0x0} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {2, 15, 31, 2, 12, 0} +#define NXFONT_BITMAP_254 {0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe7, 0xe0, 0xef, 0xf0, 0xff, 0xf8, 0xf8, 0x3c, 0xf0, 0x1c, 0xf0, 0x1e, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xe0, 0xe, 0xf0, 0x1c, 0xf0, 0x1c, 0xf8, 0x3c, 0xff, 0xf8, 0xef, 0xf0, 0xe3, 0xc0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {2, 14, 30, 1, 14, 0} +#define NXFONT_BITMAP_255 {0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0x70, 0x38, 0x70, 0x38, 0x70, 0x78, 0x78, 0x70, 0x38, 0x70, 0x38, 0xf0, 0x3c, 0xe0, 0x1c, 0xe0, 0x1d, 0xc0, 0x1d, 0xc0, 0xf, 0xc0, 0xf, 0x80, 0xf, 0x80, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1e, 0x0, 0x7c, 0x0, 0x7c, 0x0, 0x70, 0x0} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SERIF39X48_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_sans40x49b.h b/nuttx/graphics/nxfonts/nxfonts_sans40x49b.h new file mode 100755 index 0000000000..d7a5e19ab5 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_sans40x49b.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_sans40x49b.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Jose Pablo Carballo Gomez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SANS40X49B_H +#define __GRAPHICS_NXFONTS_NXFONTS_SANS40X49B_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SANS40X49B + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 49 +#define NXFONT_MAXWIDTH 40 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 9 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 5, 25, 3, 12, 0} +#define NXFONT_BITMAP_33 {0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x0, 0x0, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {2, 11, 9, 2, 12, 0} +#define NXFONT_BITMAP_34 {0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0x60, 0xc0, 0x60, 0xc0} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {3, 18, 25, 0, 13, 0} +#define NXFONT_BITMAP_35 {0x3, 0xc7, 0x0, 0x3, 0xc7, 0x0, 0x3, 0x8f, 0x0, 0x3, 0x8f, 0x0, 0x7, 0x8f, 0x0, 0x7, 0x8e, 0x0, 0x7, 0x8e, 0x0, 0x7f, 0xff, 0xc0, 0x7f, 0xff, 0xc0, 0x7f, 0xff, 0xc0, 0x7f, 0xff, 0xc0, 0xf, 0x1c, 0x0, 0xe, 0x1c, 0x0, 0xe, 0x1c, 0x0, 0xe, 0x3c, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0x1c, 0x78, 0x0, 0x3c, 0x78, 0x0, 0x3c, 0x70, 0x0, 0x3c, 0x70, 0x0, 0x38, 0xf0, 0x0, 0x38, 0xf0, 0x0} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {2, 16, 28, 1, 12, 0} +#define NXFONT_BITMAP_36 {0x1, 0x80, 0x1, 0x80, 0xf, 0xf0, 0x3f, 0xfc, 0x7f, 0xfe, 0xfd, 0xbe, 0xf9, 0x9f, 0xf1, 0x9f, 0xf1, 0x8f, 0xf9, 0x80, 0xff, 0x80, 0x7f, 0xc0, 0x3f, 0xf0, 0xf, 0xfc, 0x1, 0xfe, 0x1, 0xff, 0x1, 0x9f, 0x1, 0x8f, 0xf1, 0x8f, 0xf1, 0x9f, 0xf9, 0x9f, 0x7f, 0xfe, 0x7f, 0xfe, 0x3f, 0xf8, 0x7, 0xe0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80} + +/* percent (37) */ +#define NXFONT_METRICS_37 {4, 26, 23, 1, 14, 0} +#define NXFONT_BITMAP_37 {0xe, 0x0, 0x30, 0x0, 0x3f, 0x80, 0x70, 0x0, 0x7f, 0xc0, 0x60, 0x0, 0x71, 0xc0, 0xe0, 0x0, 0xe0, 0xe0, 0xc0, 0x0, 0xe0, 0xe1, 0xc0, 0x0, 0xe0, 0xe3, 0x80, 0x0, 0xe0, 0xe3, 0x80, 0x0, 0x71, 0xc7, 0x0, 0x0, 0x7f, 0xc6, 0x0, 0x0, 0x3f, 0x8e, 0x0, 0x0, 0xe, 0xc, 0x1c, 0x0, 0x0, 0x1c, 0x7f, 0x0, 0x0, 0x18, 0xff, 0x80, 0x0, 0x38, 0xe3, 0x80, 0x0, 0x31, 0xc1, 0xc0, 0x0, 0x71, 0xc1, 0xc0, 0x0, 0x61, 0xc1, 0xc0, 0x0, 0xe1, 0xc1, 0xc0, 0x1, 0xc0, 0xe3, 0x80, 0x1, 0xc0, 0xff, 0x80, 0x3, 0x80, 0x7f, 0x0, 0x3, 0x0, 0x1c, 0x0} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {3, 20, 25, 2, 12, 0} +#define NXFONT_BITMAP_38 {0x3, 0xe0, 0x0, 0xf, 0xf8, 0x0, 0x1f, 0xfc, 0x0, 0x1f, 0xfc, 0x0, 0x1e, 0x3c, 0x0, 0x3e, 0x3c, 0x0, 0x3e, 0x3c, 0x0, 0x1f, 0x3c, 0x0, 0x1f, 0xf8, 0x0, 0xf, 0xf8, 0x0, 0xf, 0xf0, 0x0, 0xf, 0xe0, 0x0, 0x3f, 0xf1, 0xe0, 0x7f, 0xf1, 0xe0, 0x7c, 0xf9, 0xc0, 0xf8, 0xff, 0xc0, 0xf0, 0x7f, 0xc0, 0xf0, 0x3f, 0x80, 0xf0, 0x1f, 0x0, 0xf8, 0xf, 0x80, 0xfc, 0x3f, 0xc0, 0x7f, 0xff, 0xe0, 0x7f, 0xfb, 0xe0, 0x1f, 0xf1, 0xf0, 0x7, 0xc0, 0x0} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 4, 9, 2, 12, 0} +#define NXFONT_BITMAP_39 {0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x60, 0x60} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 8, 31, 1, 12, 0} +#define NXFONT_BITMAP_40 {0x7, 0xf, 0x1e, 0x1e, 0x3c, 0x3c, 0x38, 0x78, 0x78, 0x78, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf8, 0x78, 0x78, 0x78, 0x78, 0x3c, 0x3c, 0x1c, 0x1e, 0xe, 0xf, 0x7} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 8, 31, 1, 12, 0} +#define NXFONT_BITMAP_41 {0xe0, 0xf0, 0x78, 0x78, 0x3c, 0x3c, 0x1c, 0x1e, 0x1e, 0x1e, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0x1f, 0x1e, 0x1e, 0x1e, 0x1c, 0x3c, 0x3c, 0x38, 0x78, 0x70, 0xf0, 0xe0} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {2, 10, 11, 1, 13, 0} +#define NXFONT_BITMAP_42 {0xc, 0x0, 0xc, 0x0, 0x4c, 0x80, 0xed, 0xc0, 0xff, 0xc0, 0x7f, 0x80, 0x1e, 0x0, 0x3f, 0x0, 0x7f, 0x80, 0x73, 0x80, 0x21, 0x0} + +/* plus (43) */ +#define NXFONT_METRICS_43 {2, 16, 16, 1, 21, 0} +#define NXFONT_BITMAP_43 {0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 5, 11, 2, 32, 0} +#define NXFONT_BITMAP_44 {0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x18, 0x18, 0x38, 0x70, 0xe0, 0x80} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {2, 9, 5, 1, 25, 0} +#define NXFONT_BITMAP_45 {0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 5, 5, 2, 32, 0} +#define NXFONT_BITMAP_46 {0xf8, 0xf8, 0xf8, 0xf8, 0xf8} + +/* slash (47) */ +#define NXFONT_METRICS_47 {1, 8, 25, 0, 12, 0} +#define NXFONT_BITMAP_47 {0x3, 0x3, 0x3, 0x3, 0x6, 0x6, 0x6, 0xe, 0xc, 0xc, 0xc, 0x1c, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x70, 0x60, 0x60, 0x60, 0xc0, 0xc0, 0xc0} + +/* zero (48) */ +#define NXFONT_METRICS_48 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_48 {0xf, 0xe0, 0x1f, 0xf0, 0x3f, 0xf8, 0x7f, 0xfc, 0x7c, 0x7c, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0x7c, 0x7c, 0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xf0, 0xf, 0xe0} + +/* one (49) */ +#define NXFONT_METRICS_49 {2, 10, 23, 2, 14, 0} +#define NXFONT_BITMAP_49 {0x1, 0xc0, 0x3, 0xc0, 0x7, 0xc0, 0x1f, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0} + +/* two (50) */ +#define NXFONT_METRICS_50 {2, 16, 24, 1, 13, 0} +#define NXFONT_BITMAP_50 {0xf, 0xe0, 0x3f, 0xf8, 0x7f, 0xfc, 0x7f, 0xfe, 0xfc, 0x7e, 0xf8, 0x3f, 0xf8, 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0x0, 0x3f, 0x0, 0x3e, 0x0, 0x7e, 0x0, 0xfc, 0x1, 0xf8, 0x7, 0xf0, 0xf, 0xe0, 0x1f, 0x80, 0x3f, 0x0, 0x7e, 0x0, 0xfc, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + +/* three (51) */ +#define NXFONT_METRICS_51 {2, 16, 24, 1, 13, 0} +#define NXFONT_BITMAP_51 {0xf, 0xe0, 0x3f, 0xf8, 0x7f, 0xfc, 0x7f, 0xfc, 0xf8, 0x3e, 0xf0, 0x3e, 0xf0, 0x1e, 0xf0, 0x1e, 0x0, 0x3e, 0x0, 0x7c, 0x3, 0xf8, 0x3, 0xf0, 0x3, 0xfc, 0x0, 0x7e, 0x0, 0x3f, 0x0, 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xf0, 0x3f, 0xf8, 0x3e, 0x7f, 0xfe, 0x7f, 0xfc, 0x3f, 0xf8, 0xf, 0xe0} + +/* four (52) */ +#define NXFONT_METRICS_52 {2, 16, 24, 1, 13, 0} +#define NXFONT_BITMAP_52 {0x0, 0xf8, 0x0, 0xf8, 0x1, 0xf8, 0x3, 0xf8, 0x3, 0xf8, 0x7, 0xf8, 0xf, 0x78, 0xe, 0x78, 0x1e, 0x78, 0x1c, 0x78, 0x3c, 0x78, 0x78, 0x78, 0x70, 0x78, 0xf0, 0x78, 0xe0, 0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x78, 0x0, 0x78, 0x0, 0x78, 0x0, 0x78, 0x0, 0x78} + +/* five (53) */ +#define NXFONT_METRICS_53 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_53 {0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x38, 0x0, 0x78, 0x0, 0x78, 0x0, 0x78, 0x0, 0x7b, 0xe0, 0x7f, 0xf8, 0x7f, 0xfc, 0x7f, 0xfc, 0x78, 0x7e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x1e, 0x0, 0x1e, 0xf0, 0x3e, 0xf0, 0x3e, 0xf8, 0x7c, 0x7f, 0xfc, 0x7f, 0xf8, 0x3f, 0xf0, 0xf, 0xc0} + +/* six (54) */ +#define NXFONT_METRICS_54 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_54 {0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfe, 0x7c, 0x3e, 0x78, 0x1e, 0xf0, 0x0, 0xf0, 0x0, 0xf3, 0xe0, 0xf7, 0xf8, 0xff, 0xfc, 0xff, 0xfc, 0xfc, 0x7e, 0xf8, 0x3e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf8, 0x3e, 0x7c, 0x7c, 0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* seven (55) */ +#define NXFONT_METRICS_55 {2, 16, 24, 1, 13, 0} +#define NXFONT_BITMAP_55 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x1e, 0x0, 0x3e, 0x0, 0x3c, 0x0, 0x78, 0x0, 0xf8, 0x0, 0xf0, 0x1, 0xf0, 0x1, 0xe0, 0x3, 0xe0, 0x3, 0xc0, 0x7, 0xc0, 0x7, 0xc0, 0x7, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0} + +/* eight (56) */ +#define NXFONT_METRICS_56 {3, 17, 24, 0, 13, 0} +#define NXFONT_BITMAP_56 {0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3f, 0xfe, 0x0, 0x3e, 0x3e, 0x0, 0x7c, 0x1f, 0x0, 0x78, 0xf, 0x0, 0x78, 0xf, 0x0, 0x78, 0xf, 0x0, 0x7c, 0x1f, 0x0, 0x3e, 0x3e, 0x0, 0x1f, 0xfc, 0x0, 0x1f, 0xfc, 0x0, 0x3f, 0xfe, 0x0, 0x7c, 0x1f, 0x0, 0xf8, 0xf, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf8, 0xf, 0x80, 0x7e, 0x3f, 0x0, 0x7f, 0xfe, 0x0, 0x3f, 0xfe, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* nine (57) */ +#define NXFONT_METRICS_57 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_57 {0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x7f, 0xfc, 0x7c, 0x7c, 0xf8, 0x3e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf8, 0x3e, 0xfc, 0x7e, 0x7f, 0xfe, 0x7f, 0xfe, 0x3f, 0xde, 0x7, 0x9e, 0x0, 0x1e, 0x0, 0x1e, 0xf0, 0x3c, 0xf8, 0x7c, 0x7f, 0xf8, 0x7f, 0xf8, 0x1f, 0xf0, 0x7, 0xc0} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 5, 17, 3, 20, 0} +#define NXFONT_BITMAP_58 {0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 5, 23, 3, 20, 0} +#define NXFONT_BITMAP_59 {0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x18, 0x18, 0x38, 0x70, 0xe0, 0x80} + +/* less (60) */ +#define NXFONT_METRICS_60 {2, 16, 16, 1, 21, 0} +#define NXFONT_BITMAP_60 {0x0, 0x3, 0x0, 0x1f, 0x0, 0x7f, 0x3, 0xff, 0xf, 0xfe, 0x7f, 0xf8, 0xff, 0xc0, 0xfe, 0x0, 0xfe, 0x0, 0xff, 0xc0, 0x7f, 0xf0, 0xf, 0xfe, 0x3, 0xff, 0x0, 0x7f, 0x0, 0x1f, 0x0, 0x3} + +/* equal (61) */ +#define NXFONT_METRICS_61 {2, 15, 12, 2, 23, 0} +#define NXFONT_BITMAP_61 {0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe} + +/* greater (62) */ +#define NXFONT_METRICS_62 {2, 16, 16, 1, 21, 0} +#define NXFONT_BITMAP_62 {0xc0, 0x0, 0xf0, 0x0, 0xfe, 0x0, 0xff, 0xc0, 0x7f, 0xf0, 0x1f, 0xfe, 0x3, 0xff, 0x0, 0x7f, 0x0, 0x7f, 0x3, 0xff, 0x1f, 0xfe, 0x7f, 0xf0, 0xff, 0xc0, 0xfe, 0x0, 0xf0, 0x0, 0xc0, 0x0} + +/* question (63) */ +#define NXFONT_METRICS_63 {2, 16, 25, 2, 12, 0} +#define NXFONT_BITMAP_63 {0xf, 0xe0, 0x3f, 0xf8, 0x7f, 0xfc, 0x7f, 0xfe, 0xfc, 0x7e, 0xf8, 0x3f, 0xf8, 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0x0, 0x3f, 0x0, 0x7e, 0x0, 0xfe, 0x1, 0xfc, 0x1, 0xf8, 0x3, 0xe0, 0x3, 0xc0, 0x7, 0xc0, 0x7, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc0, 0x7, 0xc0, 0x7, 0xc0, 0x7, 0xc0, 0x7, 0xc0} + +/* at (64) */ +#define NXFONT_METRICS_64 {4, 29, 30, 1, 12, 0} +#define NXFONT_BITMAP_64 {0x0, 0xf, 0xe0, 0x0, 0x0, 0x7f, 0xfc, 0x0, 0x1, 0xff, 0xfe, 0x0, 0x3, 0xf0, 0x3f, 0x80, 0x7, 0xc0, 0x7, 0xc0, 0xf, 0x0, 0x3, 0xc0, 0x1e, 0x0, 0x1, 0xe0, 0x1c, 0x0, 0x0, 0xf0, 0x3c, 0x7, 0xdc, 0x70, 0x38, 0x1f, 0xfc, 0x70, 0x70, 0x3c, 0xfc, 0x38, 0x70, 0x78, 0x78, 0x38, 0xf0, 0xf0, 0x38, 0x38, 0xe0, 0xe0, 0x38, 0x38, 0xe1, 0xe0, 0x38, 0x38, 0xe1, 0xc0, 0x70, 0x78, 0xe1, 0xc0, 0x70, 0x70, 0xe1, 0xc0, 0x70, 0x70, 0xe1, 0xe0, 0xf0, 0xe0, 0xf1, 0xe1, 0xf1, 0xe0, 0x70, 0xff, 0xff, 0xc0, 0x78, 0x7f, 0x3f, 0x80, 0x38, 0x3e, 0x1e, 0x0, 0x3c, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xf, 0xf0, 0x3c, 0x0, 0x3, 0xff, 0xfc, 0x0, 0x1, 0xff, 0xfc, 0x0, 0x0, 0x7f, 0xe0, 0x0} + +/* A (65) */ +#define NXFONT_METRICS_65 {3, 22, 25, 0, 12, 0} +#define NXFONT_BITMAP_65 {0x0, 0xfc, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0xf, 0x87, 0x80, 0xf, 0x87, 0xc0, 0xf, 0x87, 0xc0, 0x1f, 0x3, 0xc0, 0x1f, 0x3, 0xe0, 0x1f, 0xff, 0xe0, 0x1f, 0xff, 0xe0, 0x3f, 0xff, 0xf0, 0x3f, 0xff, 0xf0, 0x3e, 0x1, 0xf0, 0x7c, 0x0, 0xf8, 0x7c, 0x0, 0xf8, 0xfc, 0x0, 0xfc, 0xf8, 0x0, 0x7c} + +/* B (66) */ +#define NXFONT_METRICS_66 {3, 19, 25, 3, 12, 0} +#define NXFONT_BITMAP_66 {0xff, 0xfc, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xf8, 0xf, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0xf, 0x80, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x7, 0xe0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0x80, 0xff, 0xfe, 0x0} + +/* C (67) */ +#define NXFONT_METRICS_67 {3, 21, 25, 1, 12, 0} +#define NXFONT_BITMAP_67 {0x1, 0xfe, 0x0, 0x7, 0xff, 0x80, 0xf, 0xff, 0xc0, 0x1f, 0xff, 0xe0, 0x3f, 0x87, 0xf0, 0x3e, 0x1, 0xf0, 0x7c, 0x1, 0xf8, 0x7c, 0x0, 0xf8, 0x7c, 0x0, 0xf8, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x7c, 0x0, 0xf8, 0x7c, 0x0, 0xf8, 0x7e, 0x1, 0xf8, 0x3e, 0x1, 0xf0, 0x3f, 0x87, 0xf0, 0x1f, 0xff, 0xe0, 0xf, 0xff, 0xc0, 0x7, 0xff, 0x80, 0x1, 0xfe, 0x0} + +/* D (68) */ +#define NXFONT_METRICS_68 {3, 21, 25, 2, 12, 0} +#define NXFONT_BITMAP_68 {0xff, 0xf8, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0xc0, 0xf8, 0xf, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xf0, 0xf8, 0x1, 0xf0, 0xf8, 0x1, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x1, 0xf8, 0xf8, 0x1, 0xf0, 0xf8, 0x3, 0xf0, 0xf8, 0x3, 0xe0, 0xf8, 0xf, 0xe0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x0, 0xff, 0xf8, 0x0} + +/* E (69) */ +#define NXFONT_METRICS_69 {3, 18, 25, 2, 12, 0} +#define NXFONT_BITMAP_69 {0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0} + +/* F (70) */ +#define NXFONT_METRICS_70 {2, 16, 25, 2, 12, 0} +#define NXFONT_BITMAP_70 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0} + +/* G (71) */ +#define NXFONT_METRICS_71 {3, 22, 25, 1, 12, 0} +#define NXFONT_BITMAP_71 {0x0, 0xff, 0x0, 0x3, 0xff, 0xc0, 0xf, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x1f, 0xc3, 0xf8, 0x3f, 0x0, 0xf8, 0x7e, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0xfc, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0xf, 0xfc, 0xf8, 0xf, 0xfc, 0xf8, 0xf, 0xfc, 0xf8, 0xf, 0xfc, 0xfc, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0x7e, 0x0, 0x7c, 0x7e, 0x0, 0xfc, 0x3f, 0x83, 0xfc, 0x3f, 0xff, 0xfc, 0x1f, 0xff, 0xdc, 0x7, 0xff, 0x9c, 0x3, 0xfe, 0x1c} + +/* H (72) */ +#define NXFONT_METRICS_72 {3, 19, 25, 2, 12, 0} +#define NXFONT_BITMAP_72 {0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 5, 25, 2, 12, 0} +#define NXFONT_BITMAP_73 {0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8} + +/* J (74) */ +#define NXFONT_METRICS_74 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_74 {0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xfc, 0x7e, 0xff, 0xfc, 0x7f, 0xfc, 0x3f, 0xf8, 0xf, 0xe0} + +/* K (75) */ +#define NXFONT_METRICS_75 {3, 20, 25, 2, 12, 0} +#define NXFONT_BITMAP_75 {0xf8, 0x7, 0xe0, 0xf8, 0x7, 0xe0, 0xf8, 0xf, 0xc0, 0xf8, 0x1f, 0x80, 0xf8, 0x3f, 0x0, 0xf8, 0x7e, 0x0, 0xf8, 0xfc, 0x0, 0xf8, 0xf8, 0x0, 0xf9, 0xf8, 0x0, 0xfb, 0xf0, 0x0, 0xff, 0xe0, 0x0, 0xff, 0xe0, 0x0, 0xff, 0xf0, 0x0, 0xff, 0xf0, 0x0, 0xff, 0xf8, 0x0, 0xfc, 0xfc, 0x0, 0xf8, 0x7e, 0x0, 0xf8, 0x7e, 0x0, 0xf8, 0x3f, 0x0, 0xf8, 0x1f, 0x80, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0xc0, 0xf8, 0x7, 0xe0, 0xf8, 0x3, 0xf0, 0xf8, 0x3, 0xf0} + +/* L (76) */ +#define NXFONT_METRICS_76 {2, 16, 25, 2, 12, 0} +#define NXFONT_BITMAP_76 {0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + +/* M (77) */ +#define NXFONT_METRICS_77 {3, 23, 25, 2, 12, 0} +#define NXFONT_BITMAP_77 {0xfe, 0x0, 0xfe, 0xfe, 0x0, 0xfe, 0xff, 0x1, 0xfe, 0xff, 0x1, 0xfe, 0xff, 0x1, 0xfe, 0xff, 0x1, 0xfe, 0xff, 0x83, 0xfe, 0xff, 0x83, 0xfe, 0xfb, 0x83, 0xbe, 0xfb, 0x83, 0xbe, 0xfb, 0xc7, 0xbe, 0xfb, 0xc7, 0xbe, 0xfb, 0xc7, 0xbe, 0xf9, 0xc7, 0x3e, 0xf9, 0xef, 0x3e, 0xf9, 0xef, 0x3e, 0xf9, 0xef, 0x3e, 0xf9, 0xef, 0x3e, 0xf8, 0xee, 0x3e, 0xf8, 0xfe, 0x3e, 0xf8, 0xfe, 0x3e, 0xf8, 0xfe, 0x3e, 0xf8, 0x7c, 0x3e, 0xf8, 0x7c, 0x3e, 0xf8, 0x7c, 0x3e} + +/* N (78) */ +#define NXFONT_METRICS_78 {3, 19, 25, 2, 12, 0} +#define NXFONT_BITMAP_78 {0xf8, 0x3, 0xe0, 0xfc, 0x3, 0xe0, 0xfc, 0x3, 0xe0, 0xfe, 0x3, 0xe0, 0xfe, 0x3, 0xe0, 0xff, 0x3, 0xe0, 0xff, 0x3, 0xe0, 0xff, 0x83, 0xe0, 0xff, 0xc3, 0xe0, 0xfb, 0xc3, 0xe0, 0xfb, 0xe3, 0xe0, 0xf9, 0xe3, 0xe0, 0xf9, 0xf3, 0xe0, 0xf8, 0xf3, 0xe0, 0xf8, 0xfb, 0xe0, 0xf8, 0x7b, 0xe0, 0xf8, 0x3f, 0xe0, 0xf8, 0x3f, 0xe0, 0xf8, 0x1f, 0xe0, 0xf8, 0x1f, 0xe0, 0xf8, 0xf, 0xe0, 0xf8, 0xf, 0xe0, 0xf8, 0x7, 0xe0, 0xf8, 0x7, 0xe0, 0xf8, 0x3, 0xe0} + +/* O (79) */ +#define NXFONT_METRICS_79 {3, 23, 25, 1, 12, 0} +#define NXFONT_BITMAP_79 {0x1, 0xff, 0x0, 0x7, 0xff, 0xc0, 0xf, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x3f, 0xc7, 0xf8, 0x3f, 0x1, 0xf8, 0x7e, 0x0, 0xfc, 0x7c, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0x7c, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0x7e, 0x0, 0xfc, 0x3f, 0x1, 0xf8, 0x3f, 0xc7, 0xf8, 0x1f, 0xff, 0xf0, 0xf, 0xff, 0xe0, 0x7, 0xff, 0xc0, 0x1, 0xff, 0x0} + +/* P (80) */ +#define NXFONT_METRICS_80 {3, 18, 25, 2, 12, 0} +#define NXFONT_BITMAP_80 {0xff, 0xf8, 0x0, 0xff, 0xfe, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x80, 0xf8, 0x1f, 0x80, 0xf8, 0xf, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0xf, 0xc0, 0xf8, 0x1f, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x0, 0xff, 0xfc, 0x0, 0xff, 0xf0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {3, 23, 26, 1, 12, 0} +#define NXFONT_BITMAP_81 {0x1, 0xff, 0x0, 0x7, 0xff, 0xc0, 0xf, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x3f, 0xc7, 0xf8, 0x3f, 0x1, 0xf8, 0x7e, 0x0, 0xfc, 0x7c, 0x0, 0x7c, 0xfc, 0x0, 0x7e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x2, 0x3e, 0xfc, 0x7, 0x3e, 0x7c, 0xf, 0xbc, 0x7e, 0xf, 0xfc, 0x3f, 0x7, 0xf8, 0x3f, 0xc3, 0xf0, 0x1f, 0xff, 0xf8, 0xf, 0xff, 0xfc, 0x7, 0xff, 0xfe, 0x1, 0xff, 0x3c, 0x0, 0x0, 0x18} + +/* R (82) */ +#define NXFONT_METRICS_82 {3, 19, 25, 2, 12, 0} +#define NXFONT_BITMAP_82 {0xff, 0xfe, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xf8, 0x7, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x7, 0xc0, 0xf8, 0xf, 0xc0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x80, 0xf8, 0xf, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xe0, 0xf8, 0x3, 0xe0} + +/* S (83) */ +#define NXFONT_METRICS_83 {3, 19, 25, 1, 12, 0} +#define NXFONT_BITMAP_83 {0x3, 0xf8, 0x0, 0xf, 0xfe, 0x0, 0x1f, 0xff, 0x0, 0x3f, 0xff, 0x80, 0x3e, 0x1f, 0x80, 0x7c, 0x7, 0xc0, 0x78, 0x7, 0xc0, 0x78, 0x3, 0xc0, 0x7c, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x3f, 0xfe, 0x0, 0x1f, 0xff, 0x80, 0x3, 0xff, 0xc0, 0x0, 0x3f, 0xc0, 0x0, 0x7, 0xe0, 0x0, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0x7c, 0x3, 0xe0, 0x7e, 0xf, 0xc0, 0x3f, 0xff, 0xc0, 0x1f, 0xff, 0x80, 0xf, 0xff, 0x0, 0x3, 0xf8, 0x0} + +/* T (84) */ +#define NXFONT_METRICS_84 {3, 19, 25, 0, 12, 0} +#define NXFONT_BITMAP_84 {0xff, 0xff, 0xe0, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xe0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0} + +/* U (85) */ +#define NXFONT_METRICS_85 {3, 19, 25, 2, 12, 0} +#define NXFONT_BITMAP_85 {0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xfc, 0x7, 0xe0, 0x7f, 0x1f, 0xc0, 0x7f, 0xff, 0xc0, 0x3f, 0xff, 0x80, 0x1f, 0xff, 0x0, 0x7, 0xfc, 0x0} + +/* V (86) */ +#define NXFONT_METRICS_86 {3, 20, 25, 1, 12, 0} +#define NXFONT_BITMAP_86 {0xf8, 0x1, 0xf0, 0xf8, 0x1, 0xf0, 0x7c, 0x3, 0xe0, 0x7c, 0x3, 0xe0, 0x7c, 0x3, 0xe0, 0x3c, 0x3, 0xc0, 0x3e, 0x7, 0xc0, 0x3e, 0x7, 0xc0, 0x1e, 0x7, 0x80, 0x1f, 0xf, 0x80, 0x1f, 0xf, 0x80, 0xf, 0xf, 0x0, 0xf, 0xf, 0x0, 0xf, 0xf, 0x0, 0x7, 0x9e, 0x0, 0x7, 0x9e, 0x0, 0x7, 0x9e, 0x0, 0x7, 0xfe, 0x0, 0x3, 0xfc, 0x0, 0x3, 0xfc, 0x0, 0x3, 0xfc, 0x0, 0x1, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x0, 0xf0, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {4, 29, 25, 1, 12, 0} +#define NXFONT_BITMAP_87 {0xf8, 0x1f, 0x81, 0xf8, 0xf8, 0x1f, 0x81, 0xf8, 0x78, 0x1f, 0x81, 0xf0, 0x78, 0x1f, 0x81, 0xf0, 0x78, 0x1f, 0x81, 0xf0, 0x7c, 0x3f, 0xc3, 0xe0, 0x7c, 0x3f, 0xc3, 0xe0, 0x7c, 0x3f, 0xc3, 0xe0, 0x3c, 0x3f, 0xc3, 0xe0, 0x3c, 0x39, 0xc3, 0xc0, 0x3e, 0x79, 0xe3, 0xc0, 0x3e, 0x79, 0xe7, 0xc0, 0x1e, 0x79, 0xe7, 0xc0, 0x1e, 0x79, 0xe7, 0x80, 0x1e, 0x70, 0xe7, 0x80, 0x1e, 0x70, 0xe7, 0x80, 0xf, 0xf0, 0xff, 0x0, 0xf, 0xf0, 0xff, 0x0, 0xf, 0xf0, 0xff, 0x0, 0xf, 0xe0, 0x7f, 0x0, 0x7, 0xe0, 0x7e, 0x0, 0x7, 0xe0, 0x7e, 0x0, 0x7, 0xe0, 0x7e, 0x0, 0x3, 0xc0, 0x3c, 0x0, 0x3, 0xc0, 0x3c, 0x0} + +/* X (88) */ +#define NXFONT_METRICS_88 {3, 20, 25, 1, 12, 0} +#define NXFONT_BITMAP_88 {0xfc, 0x3, 0xe0, 0x7e, 0x7, 0xe0, 0x7e, 0x7, 0xc0, 0x3f, 0xf, 0xc0, 0x1f, 0xf, 0x80, 0x1f, 0x9f, 0x0, 0xf, 0x9f, 0x0, 0xf, 0xbe, 0x0, 0x7, 0xfe, 0x0, 0x7, 0xfc, 0x0, 0x3, 0xfc, 0x0, 0x3, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x3, 0xf8, 0x0, 0x3, 0xfc, 0x0, 0x7, 0xfc, 0x0, 0x7, 0xfe, 0x0, 0xf, 0xbf, 0x0, 0x1f, 0x9f, 0x0, 0x1f, 0x1f, 0x80, 0x3f, 0xf, 0x80, 0x3e, 0xf, 0xc0, 0x7e, 0x7, 0xc0, 0xfc, 0x7, 0xe0, 0xfc, 0x3, 0xf0} + +/* Y (89) */ +#define NXFONT_METRICS_89 {3, 20, 25, 1, 12, 0} +#define NXFONT_BITMAP_89 {0xfc, 0x3, 0xf0, 0xfc, 0x3, 0xe0, 0x7e, 0x7, 0xe0, 0x3e, 0x7, 0xc0, 0x3f, 0xf, 0xc0, 0x3f, 0xf, 0x80, 0x1f, 0xf, 0x80, 0x1f, 0x9f, 0x0, 0xf, 0x9f, 0x0, 0xf, 0xfe, 0x0, 0x7, 0xfe, 0x0, 0x7, 0xfc, 0x0, 0x3, 0xfc, 0x0, 0x3, 0xf8, 0x0, 0x3, 0xf8, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {3, 17, 25, 1, 12, 0} +#define NXFONT_BITMAP_90 {0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0x0, 0xf, 0x80, 0x0, 0x1f, 0x80, 0x0, 0x3f, 0x0, 0x0, 0x7e, 0x0, 0x0, 0x7c, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xf8, 0x0, 0x3, 0xf0, 0x0, 0x3, 0xf0, 0x0, 0x7, 0xe0, 0x0, 0xf, 0xc0, 0x0, 0xf, 0x80, 0x0, 0x1f, 0x80, 0x0, 0x3f, 0x0, 0x0, 0x7e, 0x0, 0x0, 0x7e, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 8, 31, 2, 12, 0} +#define NXFONT_BITMAP_91 {0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0xff, 0xff} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {2, 9, 25, 0, 12, 0} +#define NXFONT_BITMAP_92 {0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x60, 0x0, 0x60, 0x0, 0x70, 0x0, 0x70, 0x0, 0x30, 0x0, 0x38, 0x0, 0x38, 0x0, 0x18, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0xc, 0x0, 0xc, 0x0, 0xe, 0x0, 0xe, 0x0, 0x6, 0x0, 0x7, 0x0, 0x7, 0x0, 0x3, 0x0, 0x3, 0x80, 0x3, 0x80, 0x1, 0x80, 0x1, 0x80} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 8, 31, 0, 12, 0} +#define NXFONT_BITMAP_93 {0xff, 0xff, 0xff, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xff, 0xff, 0xff} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {2, 14, 14, 2, 14, 0} +#define NXFONT_BITMAP_94 {0x7, 0x80, 0xf, 0xc0, 0xf, 0xc0, 0xf, 0xc0, 0x1f, 0xe0, 0x1f, 0xe0, 0x3c, 0xf0, 0x3c, 0xf0, 0x38, 0x70, 0x78, 0x78, 0x78, 0x78, 0x70, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {3, 18, 2, 0, 41, 0} +#define NXFONT_BITMAP_95 {0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 5, 5, 2, 12, 0} +#define NXFONT_BITMAP_96 {0xe0, 0xf0, 0x70, 0x78, 0x38} + +/* a (97) */ +#define NXFONT_METRICS_97 {2, 15, 18, 1, 19, 0} +#define NXFONT_BITMAP_97 {0xf, 0xf0, 0x3f, 0xfc, 0x7f, 0xfc, 0x7c, 0x3e, 0xf8, 0x1e, 0xf8, 0x1e, 0x0, 0xfe, 0xf, 0xfe, 0x3f, 0xfe, 0x7f, 0x1e, 0xf8, 0x1e, 0xf8, 0x1e, 0xf0, 0x3e, 0xf8, 0x7e, 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xde, 0x3f, 0x1e} + +/* b (98) */ +#define NXFONT_METRICS_98 {2, 16, 25, 2, 12, 0} +#define NXFONT_BITMAP_98 {0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf3, 0xf0, 0xf7, 0xfc, 0xff, 0xfc, 0xff, 0xfe, 0xfc, 0x3e, 0xf8, 0x1f, 0xf0, 0x1f, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0x1f, 0xf0, 0x1f, 0xf8, 0x3e, 0xff, 0xfe, 0xff, 0xfc, 0xf7, 0xf8, 0xf1, 0xf0} + +/* c (99) */ +#define NXFONT_METRICS_99 {2, 15, 18, 1, 19, 0} +#define NXFONT_BITMAP_99 {0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc, 0x7c, 0x3e, 0x78, 0x3e, 0xf0, 0x1e, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x1e, 0xf8, 0x1e, 0x7c, 0x3e, 0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xf8, 0x7, 0xe0} + +/* d (100) */ +#define NXFONT_METRICS_100 {2, 16, 25, 1, 12, 0} +#define NXFONT_BITMAP_100 {0x0, 0xf, 0x0, 0xf, 0x0, 0xf, 0x0, 0xf, 0x0, 0xf, 0x0, 0xf, 0x0, 0xf, 0xf, 0xcf, 0x1f, 0xef, 0x3f, 0xff, 0x7f, 0xff, 0x7c, 0x3f, 0xf8, 0x1f, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf8, 0x1f, 0x7c, 0x3f, 0x7f, 0xff, 0x3f, 0xef, 0x1f, 0xef, 0xf, 0x8f} + +/* e (101) */ +#define NXFONT_METRICS_101 {2, 16, 18, 1, 19, 0} +#define NXFONT_BITMAP_101 {0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0x7c, 0x3e, 0xf8, 0x1f, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0xf0, 0x0, 0xf8, 0x1e, 0x7c, 0x3e, 0x7f, 0xfc, 0x3f, 0xfc, 0x1f, 0xf0, 0x7, 0xc0} + +/* f (102) */ +#define NXFONT_METRICS_102 {2, 10, 25, 0, 12, 0} +#define NXFONT_BITMAP_102 {0x7, 0xc0, 0xf, 0xc0, 0x1f, 0xc0, 0x1f, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0} + +/* g (103) */ +#define NXFONT_METRICS_103 {2, 16, 25, 1, 19, 0} +#define NXFONT_BITMAP_103 {0xf, 0xcf, 0x1f, 0xef, 0x3f, 0xff, 0x7f, 0xff, 0x7c, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf8, 0x1f, 0xf8, 0x1f, 0x7c, 0x3f, 0x7f, 0xff, 0x3f, 0xff, 0x1f, 0xef, 0xf, 0xcf, 0x0, 0xf, 0xf8, 0x1f, 0xf8, 0x1f, 0x7e, 0x7e, 0x7f, 0xfe, 0x3f, 0xfc, 0xf, 0xf0} + +/* h (104) */ +#define NXFONT_METRICS_104 {2, 15, 25, 2, 12, 0} +#define NXFONT_BITMAP_104 {0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf1, 0xe0, 0xf7, 0xf8, 0xff, 0xfc, 0xff, 0xfc, 0xfc, 0x3e, 0xf8, 0x1e, 0xf8, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 4, 25, 2, 12, 0} +#define NXFONT_BITMAP_105 {0xf0, 0xf0, 0xf0, 0xf0, 0x0, 0x0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0} + +/* j (106) */ +#define NXFONT_METRICS_106 {1, 6, 32, 0, 12, 0} +#define NXFONT_BITMAP_106 {0x3c, 0x3c, 0x3c, 0x3c, 0x0, 0x0, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0xfc, 0xfc, 0xf8, 0xf8} + +/* k (107) */ +#define NXFONT_METRICS_107 {2, 15, 25, 2, 12, 0} +#define NXFONT_BITMAP_107 {0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x3e, 0xf0, 0x7c, 0xf0, 0xf8, 0xf1, 0xf0, 0xf3, 0xe0, 0xf7, 0xc0, 0xff, 0x80, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xe0, 0xff, 0xe0, 0xf9, 0xf0, 0xf1, 0xf0, 0xf0, 0xf8, 0xf0, 0x78, 0xf0, 0x7c, 0xf0, 0x3e, 0xf0, 0x3e} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 4, 25, 2, 12, 0} +#define NXFONT_BITMAP_108 {0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0} + +/* m (109) */ +#define NXFONT_METRICS_109 {3, 24, 18, 2, 19, 0} +#define NXFONT_BITMAP_109 {0xf1, 0xe0, 0xf8, 0xf7, 0xfb, 0xfe, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0x1f, 0xf8, 0x3e, 0xf, 0xf0, 0x3c, 0xf, 0xf0, 0x3c, 0xf, 0xf0, 0x3c, 0xf, 0xf0, 0x3c, 0xf, 0xf0, 0x3c, 0xf, 0xf0, 0x3c, 0xf, 0xf0, 0x3c, 0xf, 0xf0, 0x3c, 0xf, 0xf0, 0x3c, 0xf, 0xf0, 0x3c, 0xf, 0xf0, 0x3c, 0xf, 0xf0, 0x3c, 0xf} + +/* n (110) */ +#define NXFONT_METRICS_110 {2, 15, 18, 2, 19, 0} +#define NXFONT_BITMAP_110 {0xf1, 0xf0, 0xf7, 0xfc, 0xff, 0xfc, 0xff, 0xfe, 0xfc, 0x3e, 0xf8, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e} + +/* o (111) */ +#define NXFONT_METRICS_111 {3, 17, 18, 1, 19, 0} +#define NXFONT_BITMAP_111 {0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3f, 0xfe, 0x0, 0x7f, 0xff, 0x0, 0x7c, 0x1f, 0x0, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0x7c, 0x1f, 0x0, 0x7f, 0xff, 0x0, 0x3f, 0xfe, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* p (112) */ +#define NXFONT_METRICS_112 {2, 16, 25, 2, 19, 0} +#define NXFONT_BITMAP_112 {0xf1, 0xf0, 0xf7, 0xf8, 0xff, 0xfc, 0xff, 0xfe, 0xfc, 0x3e, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf8, 0x1f, 0xf8, 0x1f, 0xfc, 0x3e, 0xff, 0xfe, 0xff, 0xfc, 0xf7, 0xf8, 0xf1, 0xf0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0} + +/* q (113) */ +#define NXFONT_METRICS_113 {2, 16, 25, 1, 19, 0} +#define NXFONT_BITMAP_113 {0x7, 0xcf, 0x1f, 0xef, 0x3f, 0xff, 0x7f, 0xff, 0x7c, 0x3f, 0xf8, 0x1f, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf8, 0x1f, 0x7c, 0x3f, 0x7f, 0xff, 0x3f, 0xff, 0x3f, 0xef, 0xf, 0xcf, 0x0, 0xf, 0x0, 0xf, 0x0, 0xf, 0x0, 0xf, 0x0, 0xf, 0x0, 0xf, 0x0, 0xf} + +/* r (114) */ +#define NXFONT_METRICS_114 {2, 10, 18, 2, 19, 0} +#define NXFONT_BITMAP_114 {0xf0, 0xc0, 0xf3, 0xc0, 0xf7, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xfc, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0} + +/* s (115) */ +#define NXFONT_METRICS_115 {2, 16, 18, 1, 19, 0} +#define NXFONT_BITMAP_115 {0x7, 0xf0, 0x1f, 0xfc, 0x3f, 0xfe, 0x7c, 0x3e, 0x78, 0x1f, 0x78, 0x1f, 0x7c, 0x0, 0x7f, 0xc0, 0x3f, 0xf8, 0xf, 0xfe, 0x3, 0xff, 0x0, 0x3f, 0xf8, 0xf, 0xf8, 0xf, 0x7c, 0x1f, 0x7f, 0xfe, 0x3f, 0xfc, 0xf, 0xf0} + +/* t (116) */ +#define NXFONT_METRICS_116 {2, 9, 22, 1, 15, 0} +#define NXFONT_BITMAP_116 {0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3f, 0x80, 0x3f, 0x80, 0x1f, 0x80, 0xf, 0x80} + +/* u (117) */ +#define NXFONT_METRICS_117 {2, 15, 18, 2, 19, 0} +#define NXFONT_BITMAP_117 {0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf8, 0x3e, 0xf8, 0x7e, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0xde, 0x1f, 0x1e} + +/* v (118) */ +#define NXFONT_METRICS_118 {3, 17, 18, 0, 19, 0} +#define NXFONT_BITMAP_118 {0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0x7c, 0x1f, 0x0, 0x7c, 0x1f, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3e, 0x3e, 0x0, 0x1e, 0x3c, 0x0, 0x1e, 0x3c, 0x0, 0x1e, 0x3c, 0x0, 0xf, 0x78, 0x0, 0xf, 0x78, 0x0, 0xf, 0x78, 0x0, 0x7, 0xf0, 0x0, 0x7, 0xf0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xe0, 0x0, 0x3, 0xe0, 0x0} + +/* w (119) */ +#define NXFONT_METRICS_119 {4, 25, 18, 0, 19, 0} +#define NXFONT_BITMAP_119 {0xf8, 0x3e, 0xf, 0x80, 0xf8, 0x3e, 0xf, 0x80, 0x78, 0x3e, 0xf, 0x0, 0x7c, 0x3e, 0x1f, 0x0, 0x7c, 0x7f, 0x1f, 0x0, 0x3c, 0x7f, 0x1e, 0x0, 0x3c, 0x7f, 0x1e, 0x0, 0x3c, 0x77, 0x1e, 0x0, 0x3c, 0xf7, 0x9e, 0x0, 0x1e, 0xe3, 0xbc, 0x0, 0x1e, 0xe3, 0xbc, 0x0, 0x1e, 0xe3, 0xbc, 0x0, 0x1f, 0xe3, 0xfc, 0x0, 0xf, 0xc1, 0xf8, 0x0, 0xf, 0xc1, 0xf8, 0x0, 0xf, 0xc1, 0xf8, 0x0, 0x7, 0x80, 0xf0, 0x0, 0x7, 0x80, 0xf0, 0x0} + +/* x (120) */ +#define NXFONT_METRICS_120 {2, 16, 18, 1, 19, 0} +#define NXFONT_BITMAP_120 {0xf8, 0x1f, 0xfc, 0x3f, 0x7c, 0x3e, 0x3e, 0x7c, 0x3e, 0x78, 0x1f, 0xf8, 0xf, 0xf0, 0x7, 0xe0, 0x3, 0xc0, 0x7, 0xe0, 0xf, 0xe0, 0xf, 0xf0, 0x1f, 0xf8, 0x3e, 0x78, 0x3e, 0x7c, 0x7c, 0x3e, 0xfc, 0x3f, 0xf8, 0x1f} + +/* y (121) */ +#define NXFONT_METRICS_121 {2, 16, 25, 1, 19, 0} +#define NXFONT_BITMAP_121 {0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1e, 0x78, 0x3e, 0x7c, 0x3e, 0x7c, 0x3c, 0x3c, 0x3c, 0x3e, 0x7c, 0x3e, 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x1f, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7, 0xc0, 0x7, 0xc0, 0x7, 0xc0, 0xf, 0x80, 0x3f, 0x80, 0x3f, 0x0, 0x3f, 0x0, 0x3c, 0x0} + +/* z (122) */ +#define NXFONT_METRICS_122 {2, 14, 18, 1, 19, 0} +#define NXFONT_BITMAP_122 {0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0x0, 0xf8, 0x1, 0xf0, 0x3, 0xf0, 0x7, 0xe0, 0xf, 0xc0, 0x1f, 0x80, 0x1f, 0x0, 0x3e, 0x0, 0x7c, 0x0, 0xf8, 0x0, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {2, 9, 32, 2, 12, 0} +#define NXFONT_BITMAP_123 {0xf, 0x80, 0x1f, 0x80, 0x3f, 0x80, 0x3e, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x7c, 0x0, 0x78, 0x0, 0xe0, 0x0, 0x78, 0x0, 0x7c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3f, 0x80, 0x1f, 0x80, 0xf, 0x80} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 3, 31, 3, 12, 0} +#define NXFONT_BITMAP_124 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {2, 9, 32, 2, 12, 0} +#define NXFONT_BITMAP_125 {0xf8, 0x0, 0xfc, 0x0, 0xfe, 0x0, 0x3e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1f, 0x0, 0xf, 0x0, 0x3, 0x80, 0xf, 0x0, 0x1f, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xfe, 0x0, 0xfc, 0x0, 0xf8, 0x0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {2, 14, 6, 2, 26, 0} +#define NXFONT_BITMAP_126 {0x38, 0x0, 0x7e, 0xc, 0xff, 0x9c, 0xe7, 0xfc, 0xc1, 0xf8, 0x0, 0x70} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 5, 24, 2, 19, 0} +#define NXFONT_BITMAP_161 {0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x0, 0x0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8} + +/* cent (162) */ +#define NXFONT_METRICS_162 {2, 15, 24, 1, 16, 0} +#define NXFONT_BITMAP_162 {0x0, 0x20, 0x0, 0x20, 0x0, 0x60, 0x7, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfc, 0x7c, 0xbe, 0xf8, 0x9e, 0xf9, 0x9e, 0xf1, 0x80, 0xf1, 0x80, 0xf3, 0x0, 0xf3, 0x0, 0xf3, 0x1e, 0xfa, 0x1e, 0x7e, 0x3e, 0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xf0, 0xf, 0xc0, 0xc, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {3, 17, 24, 0, 13, 0} +#define NXFONT_BITMAP_163 {0x3, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3f, 0xfe, 0x0, 0x3f, 0xff, 0x0, 0x7e, 0x1f, 0x0, 0x7c, 0xf, 0x80, 0x7c, 0xf, 0x80, 0x7c, 0x7, 0x80, 0x7c, 0x0, 0x0, 0x7e, 0x0, 0x0, 0x3e, 0x0, 0x0, 0xff, 0xf0, 0x0, 0xff, 0xf0, 0x0, 0x1f, 0x0, 0x0, 0xf, 0x0, 0x0, 0xf, 0x0, 0x0, 0xf, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x3d, 0xe3, 0x0, 0x7f, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x0, 0x60, 0x7e, 0x0} + +/* currency (164) */ +#define NXFONT_METRICS_164 {2, 15, 15, 1, 18, 0} +#define NXFONT_BITMAP_164 {0xe0, 0xe, 0xf7, 0xde, 0xff, 0xfe, 0x7f, 0xfc, 0x3c, 0x78, 0x78, 0x3c, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x78, 0x3c, 0x3c, 0x78, 0x7f, 0xfc, 0xff, 0xfe, 0xf7, 0xde, 0xe0, 0xe} + +/* yen (165) */ +#define NXFONT_METRICS_165 {3, 18, 24, 0, 13, 0} +#define NXFONT_BITMAP_165 {0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0x7c, 0xf, 0x80, 0x3c, 0xf, 0x0, 0x1e, 0x1e, 0x0, 0x1e, 0x1e, 0x0, 0xf, 0x3c, 0x0, 0xf, 0x3c, 0x0, 0x7, 0xf8, 0x0, 0x7, 0xf8, 0x0, 0x3, 0xf0, 0x0, 0x1, 0xe0, 0x0, 0x3f, 0xff, 0x0, 0x3f, 0xff, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x3f, 0xff, 0x0, 0x3f, 0xff, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 3, 31, 3, 12, 0} +#define NXFONT_BITMAP_166 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} + +/* section (167) */ +#define NXFONT_METRICS_167 {2, 16, 32, 1, 12, 0} +#define NXFONT_BITMAP_167 {0xf, 0xf0, 0x1f, 0xf8, 0x3f, 0xf8, 0x7e, 0x7c, 0x7c, 0x3c, 0x7c, 0x3c, 0x7e, 0x0, 0x7f, 0x0, 0x3f, 0xc0, 0x1f, 0xe0, 0x3f, 0xf8, 0x7f, 0xfc, 0x71, 0xfe, 0xf0, 0xff, 0xf0, 0x3f, 0xf8, 0x1f, 0xfc, 0xf, 0x7f, 0xf, 0x7f, 0x9f, 0x3f, 0xfe, 0x1f, 0xf8, 0x7, 0xfc, 0x1, 0xfe, 0x0, 0x7e, 0x0, 0x3e, 0x78, 0x1e, 0x78, 0x1e, 0x7c, 0x3e, 0x3f, 0xfc, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {2, 10, 4, 0, 12, 0} +#define NXFONT_BITMAP_168 {0xf3, 0xc0, 0xf3, 0xc0, 0xf3, 0xc0, 0xf3, 0xc0} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {4, 26, 25, 0, 12, 0} +#define NXFONT_BITMAP_169 {0x0, 0x7f, 0x80, 0x0, 0x3, 0xff, 0xe0, 0x0, 0x7, 0x80, 0xf8, 0x0, 0x1f, 0x0, 0x3c, 0x0, 0x1c, 0x0, 0xe, 0x0, 0x38, 0x0, 0x7, 0x0, 0x70, 0x3f, 0x3, 0x0, 0x70, 0x7f, 0x83, 0x80, 0xe0, 0xf3, 0xc1, 0x80, 0xe1, 0xc0, 0xe1, 0xc0, 0xc1, 0xc0, 0xe0, 0xc0, 0xc3, 0x80, 0x0, 0xc0, 0xc3, 0x80, 0x0, 0xc0, 0xc3, 0x80, 0x0, 0xc0, 0xc3, 0x80, 0x0, 0xc0, 0xc1, 0xc0, 0xe0, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe0, 0xf3, 0xc3, 0x80, 0x60, 0x7f, 0x83, 0x80, 0x70, 0x3f, 0x7, 0x0, 0x38, 0x0, 0xe, 0x0, 0x1e, 0x0, 0x3c, 0x0, 0xf, 0x80, 0xf8, 0x0, 0x7, 0xff, 0xe0, 0x0, 0x1, 0xff, 0x80, 0x0} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {2, 9, 16, 1, 12, 0} +#define NXFONT_BITMAP_170 {0x3e, 0x0, 0x7f, 0x0, 0xe3, 0x80, 0xc3, 0x80, 0x1f, 0x80, 0x7f, 0x80, 0xf3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xff, 0x80, 0x7b, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {2, 12, 13, 3, 22, 0} +#define NXFONT_BITMAP_171 {0x8, 0x10, 0x18, 0x30, 0x38, 0x70, 0x78, 0xf0, 0xf1, 0xe0, 0xe1, 0xc0, 0xe1, 0xc0, 0xf1, 0xe0, 0xf9, 0xf0, 0x78, 0xf0, 0x38, 0x70, 0x18, 0x30, 0x8, 0x10} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {2, 16, 10, 1, 23, 0} +#define NXFONT_BITMAP_172 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0xf, 0x0, 0xf, 0x0, 0xf, 0x0, 0xf, 0x0, 0xf, 0x0, 0xf} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {2, 9, 5, 1, 25, 0} +#define NXFONT_BITMAP_173 {0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80} + +/* registered (174) */ +#define NXFONT_METRICS_174 {4, 26, 25, 0, 12, 0} +#define NXFONT_BITMAP_174 {0x0, 0xff, 0x80, 0x0, 0x3, 0xff, 0xe0, 0x0, 0x7, 0x80, 0xf8, 0x0, 0x1e, 0x0, 0x3c, 0x0, 0x1c, 0x0, 0xe, 0x0, 0x38, 0xff, 0x87, 0x0, 0x70, 0xff, 0xc3, 0x0, 0x70, 0xe1, 0xe3, 0x80, 0xe0, 0xe0, 0xe1, 0x80, 0xe0, 0xe0, 0xe1, 0x80, 0xc0, 0xe0, 0xe1, 0xc0, 0xc0, 0xe1, 0xc1, 0xc0, 0xc0, 0xff, 0x81, 0xc0, 0xc0, 0xff, 0x1, 0xc0, 0xc0, 0xe3, 0x81, 0xc0, 0xc0, 0xe3, 0xc1, 0xc0, 0xe0, 0xe1, 0xc1, 0x80, 0xe0, 0xe0, 0xe3, 0x80, 0x70, 0xe0, 0xf3, 0x80, 0x70, 0xe0, 0x77, 0x0, 0x38, 0x0, 0xe, 0x0, 0x1e, 0x0, 0x1c, 0x0, 0xf, 0x80, 0x78, 0x0, 0x7, 0xff, 0xe0, 0x0, 0x1, 0xff, 0x80, 0x0} + +/* macron (175) */ +#define NXFONT_METRICS_175 {2, 10, 3, 0, 13, 0} +#define NXFONT_BITMAP_175 {0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0} + +/* degree (176) */ +#define NXFONT_METRICS_176 {2, 9, 10, 2, 13, 0} +#define NXFONT_BITMAP_176 {0x3e, 0x0, 0x7f, 0x0, 0x63, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x7f, 0x0, 0x3e, 0x0} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {2, 16, 22, 1, 15, 0} +#define NXFONT_BITMAP_177 {0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {2, 10, 15, 0, 13, 0} +#define NXFONT_BITMAP_178 {0x3f, 0x0, 0x7f, 0x80, 0xf3, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0x1, 0xc0, 0x3, 0xc0, 0x7, 0x80, 0xf, 0x0, 0x3e, 0x0, 0x78, 0x0, 0x70, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {2, 10, 15, 0, 13, 0} +#define NXFONT_BITMAP_179 {0x1e, 0x0, 0x7f, 0x80, 0xf3, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0x3, 0xc0, 0xf, 0x80, 0xf, 0x80, 0x3, 0xc0, 0x1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xf3, 0xc0, 0x7f, 0x80, 0x3e, 0x0} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 6, 5, 4, 12, 0} +#define NXFONT_BITMAP_180 {0x3c, 0x78, 0x70, 0xe0, 0xe0} + +/* mu (181) */ +#define NXFONT_METRICS_181 {2, 15, 25, 2, 19, 0} +#define NXFONT_BITMAP_181 {0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf8, 0x3e, 0xf8, 0x7e, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xde, 0xf7, 0x9e, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {3, 17, 31, 0, 12, 0} +#define NXFONT_BITMAP_182 {0xf, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x3f, 0x8c, 0x0, 0x7f, 0x8c, 0x0, 0x7f, 0x8c, 0x0, 0xff, 0x8c, 0x0, 0xff, 0x8c, 0x0, 0xff, 0x8c, 0x0, 0xff, 0x8c, 0x0, 0xff, 0x8c, 0x0, 0x7f, 0x8c, 0x0, 0x7f, 0x8c, 0x0, 0x3f, 0x8c, 0x0, 0x3f, 0x8c, 0x0, 0xf, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x8c, 0x0} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 4, 5, 2, 21, 0} +#define NXFONT_BITMAP_183 {0x60, 0xf0, 0xf0, 0xf0, 0x60} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 7, 8, 2, 36, 0} +#define NXFONT_BITMAP_184 {0x30, 0x30, 0x30, 0x7c, 0x1e, 0xe, 0xfc, 0xf8} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 6, 15, 2, 13, 0} +#define NXFONT_BITMAP_185 {0x1c, 0x3c, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {2, 10, 16, 1, 12, 0} +#define NXFONT_BITMAP_186 {0x3f, 0x0, 0x7f, 0x80, 0x73, 0x80, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0x73, 0x80, 0x7f, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {2, 12, 12, 3, 22, 0} +#define NXFONT_BITMAP_187 {0x81, 0x0, 0xc1, 0x80, 0xe1, 0xc0, 0xf1, 0xe0, 0x78, 0xf0, 0x38, 0x70, 0x38, 0x70, 0x78, 0xf0, 0xf1, 0xe0, 0xe1, 0xc0, 0xc1, 0x80, 0x81, 0x0} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {4, 26, 24, 0, 13, 0} +#define NXFONT_BITMAP_188 {0x0, 0x0, 0x38, 0x0, 0x6, 0x0, 0x70, 0x0, 0x1e, 0x0, 0x70, 0x0, 0xfe, 0x0, 0xe0, 0x0, 0xfe, 0x1, 0xc0, 0x0, 0xe, 0x1, 0xc0, 0x0, 0xe, 0x3, 0x80, 0x0, 0xe, 0x3, 0x80, 0x0, 0xe, 0x7, 0x0, 0x0, 0xe, 0x7, 0x0, 0x0, 0xe, 0xe, 0x7, 0x0, 0xe, 0x1c, 0xf, 0x0, 0xe, 0x1c, 0x1f, 0x0, 0xe, 0x38, 0x1f, 0x0, 0x0, 0x38, 0x37, 0x0, 0x0, 0x70, 0x67, 0x0, 0x0, 0x70, 0xe7, 0x0, 0x0, 0xe0, 0xc7, 0x0, 0x1, 0xc1, 0x87, 0x0, 0x1, 0xc1, 0xff, 0xc0, 0x3, 0x81, 0xff, 0xc0, 0x3, 0x80, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {4, 25, 24, 1, 13, 0} +#define NXFONT_BITMAP_189 {0x0, 0x0, 0xe0, 0x0, 0xc, 0x1, 0xc0, 0x0, 0x1c, 0x1, 0xc0, 0x0, 0xfc, 0x3, 0x80, 0x0, 0xfc, 0x3, 0x80, 0x0, 0x1c, 0x7, 0x0, 0x0, 0x1c, 0xe, 0x0, 0x0, 0x1c, 0xe, 0x0, 0x0, 0x1c, 0x1c, 0x0, 0x0, 0x1c, 0x1c, 0x0, 0x0, 0x1c, 0x38, 0x7e, 0x0, 0x1c, 0x30, 0xff, 0x0, 0x1c, 0x71, 0xe7, 0x80, 0x1c, 0xe1, 0xc3, 0x80, 0x0, 0xe1, 0xc3, 0x80, 0x1, 0xc0, 0x7, 0x80, 0x1, 0xc0, 0xf, 0x0, 0x3, 0x80, 0x1e, 0x0, 0x7, 0x0, 0x3c, 0x0, 0x7, 0x0, 0x78, 0x0, 0xe, 0x0, 0xf0, 0x0, 0xe, 0x1, 0xff, 0x80, 0x1c, 0x1, 0xff, 0x80, 0x1c, 0x1, 0xff, 0x80} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {4, 25, 24, 1, 13, 0} +#define NXFONT_BITMAP_190 {0x3f, 0x0, 0x1c, 0x0, 0x7f, 0x80, 0x38, 0x0, 0xf3, 0xc0, 0x38, 0x0, 0xe1, 0xc0, 0x70, 0x0, 0xe1, 0xc0, 0xe0, 0x0, 0x3, 0xc0, 0xe0, 0x0, 0xf, 0x81, 0xc0, 0x0, 0xf, 0x81, 0xc0, 0x0, 0xf, 0xc3, 0x80, 0x0, 0x1, 0xc7, 0x0, 0x0, 0xe1, 0xc7, 0xe, 0x0, 0xe1, 0xce, 0x1e, 0x0, 0xf3, 0xce, 0x1e, 0x0, 0x7f, 0x9c, 0x3e, 0x0, 0x3f, 0x1c, 0x7e, 0x0, 0x0, 0x38, 0xee, 0x0, 0x0, 0x70, 0xce, 0x0, 0x0, 0x71, 0x8e, 0x0, 0x0, 0xe3, 0x8e, 0x0, 0x0, 0xe3, 0xff, 0x80, 0x1, 0xc3, 0xff, 0x80, 0x1, 0xc0, 0xe, 0x0, 0x3, 0x80, 0xe, 0x0, 0x3, 0x80, 0xe, 0x0} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {2, 16, 24, 1, 19, 0} +#define NXFONT_BITMAP_191 {0x3, 0xe0, 0x3, 0xe0, 0x3, 0xe0, 0x3, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xc0, 0x1f, 0x80, 0x3f, 0x80, 0x7f, 0x0, 0x7e, 0x0, 0xfc, 0x0, 0xf8, 0xf, 0xf8, 0xf, 0xf8, 0xf, 0xfc, 0x1f, 0x7e, 0x7f, 0x7f, 0xfe, 0x3f, 0xfe, 0x3f, 0xfc, 0xf, 0xf0} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {3, 22, 31, 0, 6, 0} +#define NXFONT_BITMAP_192 {0x3, 0xc0, 0x0, 0x1, 0xe0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x78, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0xf, 0x87, 0x80, 0xf, 0x87, 0xc0, 0xf, 0x87, 0xc0, 0x1f, 0x3, 0xc0, 0x1f, 0x3, 0xe0, 0x1f, 0xff, 0xe0, 0x1f, 0xff, 0xe0, 0x3f, 0xff, 0xf0, 0x3f, 0xff, 0xf0, 0x3e, 0x1, 0xf0, 0x7c, 0x0, 0xf8, 0x7c, 0x0, 0xf8, 0xfc, 0x0, 0xfc, 0xf8, 0x0, 0x7c} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {3, 22, 31, 0, 6, 0} +#define NXFONT_BITMAP_193 {0x0, 0xf, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x78, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0xf, 0x87, 0x80, 0xf, 0x87, 0xc0, 0xf, 0x87, 0xc0, 0x1f, 0x3, 0xc0, 0x1f, 0x3, 0xe0, 0x1f, 0xff, 0xe0, 0x1f, 0xff, 0xe0, 0x3f, 0xff, 0xf0, 0x3f, 0xff, 0xf0, 0x3e, 0x1, 0xf0, 0x7c, 0x0, 0xf8, 0x7c, 0x0, 0xf8, 0xfc, 0x0, 0xfc, 0xf8, 0x0, 0x7c} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {3, 22, 31, 0, 6, 0} +#define NXFONT_BITMAP_194 {0x0, 0x30, 0x0, 0x0, 0x78, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xce, 0x0, 0x3, 0x87, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0xf, 0x87, 0x80, 0xf, 0x87, 0xc0, 0xf, 0x87, 0xc0, 0x1f, 0x3, 0xc0, 0x1f, 0x3, 0xe0, 0x1f, 0xff, 0xe0, 0x1f, 0xff, 0xe0, 0x3f, 0xff, 0xf0, 0x3f, 0xff, 0xf0, 0x3e, 0x1, 0xf0, 0x7c, 0x0, 0xf8, 0x7c, 0x0, 0xf8, 0xfc, 0x0, 0xfc, 0xf8, 0x0, 0x7c} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {3, 22, 30, 0, 7, 0} +#define NXFONT_BITMAP_195 {0x0, 0xf1, 0x80, 0x1, 0xff, 0x80, 0x3, 0xff, 0x0, 0x3, 0x1e, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0xf, 0x87, 0x80, 0xf, 0x87, 0xc0, 0xf, 0x87, 0xc0, 0x1f, 0x3, 0xc0, 0x1f, 0x3, 0xe0, 0x1f, 0xff, 0xe0, 0x1f, 0xff, 0xe0, 0x3f, 0xff, 0xf0, 0x3f, 0xff, 0xf0, 0x3e, 0x1, 0xf0, 0x7c, 0x0, 0xf8, 0x7c, 0x0, 0xf8, 0xfc, 0x0, 0xfc, 0xf8, 0x0, 0x7c} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {3, 22, 31, 0, 6, 0} +#define NXFONT_BITMAP_196 {0x3, 0xcf, 0x0, 0x3, 0xcf, 0x0, 0x3, 0xcf, 0x0, 0x3, 0xcf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0xf, 0x87, 0x80, 0xf, 0x87, 0xc0, 0xf, 0x87, 0xc0, 0x1f, 0x3, 0xc0, 0x1f, 0x3, 0xe0, 0x1f, 0xff, 0xe0, 0x1f, 0xff, 0xe0, 0x3f, 0xff, 0xf0, 0x3f, 0xff, 0xf0, 0x3e, 0x1, 0xf0, 0x7c, 0x0, 0xf8, 0x7c, 0x0, 0xf8, 0xfc, 0x0, 0xfc, 0xf8, 0x0, 0x7c} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {3, 22, 31, 0, 6, 0} +#define NXFONT_BITMAP_197 {0x0, 0x78, 0x0, 0x0, 0xcc, 0x0, 0x0, 0x84, 0x0, 0x0, 0x84, 0x0, 0x0, 0xcc, 0x0, 0x0, 0x78, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x3, 0xff, 0x0, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0x7, 0xcf, 0x80, 0xf, 0x87, 0x80, 0xf, 0x87, 0xc0, 0xf, 0x87, 0xc0, 0x1f, 0x3, 0xc0, 0x1f, 0x3, 0xe0, 0x1f, 0xff, 0xe0, 0x1f, 0xff, 0xe0, 0x3f, 0xff, 0xf0, 0x3f, 0xff, 0xf0, 0x3e, 0x1, 0xf0, 0x7c, 0x0, 0xf8, 0x7c, 0x0, 0xf8, 0xfc, 0x0, 0xfc, 0xf8, 0x0, 0x7c} + +/* AE (198) */ +#define NXFONT_METRICS_198 {4, 31, 25, 0, 12, 0} +#define NXFONT_BITMAP_198 {0x0, 0xff, 0xff, 0xfc, 0x0, 0xff, 0xff, 0xfc, 0x0, 0xff, 0xff, 0xfc, 0x1, 0xff, 0xff, 0xfc, 0x1, 0xf3, 0xc0, 0x0, 0x1, 0xe3, 0xc0, 0x0, 0x3, 0xe3, 0xc0, 0x0, 0x3, 0xe3, 0xc0, 0x0, 0x3, 0xc3, 0xc0, 0x0, 0x7, 0xc3, 0xc0, 0x0, 0x7, 0xc3, 0xc0, 0x0, 0x7, 0xc3, 0xff, 0xf8, 0xf, 0x83, 0xff, 0xf8, 0xf, 0x83, 0xff, 0xf8, 0xf, 0x83, 0xff, 0xf8, 0x1f, 0x3, 0xc0, 0x0, 0x1f, 0xff, 0xc0, 0x0, 0x1f, 0xff, 0xc0, 0x0, 0x3f, 0xff, 0xc0, 0x0, 0x3f, 0xff, 0xc0, 0x0, 0x3e, 0x3, 0xc0, 0x0, 0x7c, 0x3, 0xff, 0xfe, 0x7c, 0x3, 0xff, 0xfe, 0xf8, 0x3, 0xff, 0xfe, 0xf8, 0x3, 0xff, 0xfe} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {3, 21, 32, 1, 12, 0} +#define NXFONT_BITMAP_199 {0x1, 0xfe, 0x0, 0x7, 0xff, 0x80, 0xf, 0xff, 0xc0, 0x1f, 0xff, 0xe0, 0x3f, 0x87, 0xf0, 0x3e, 0x1, 0xf0, 0x7c, 0x1, 0xf0, 0x7c, 0x0, 0xf8, 0x7c, 0x0, 0xf8, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x7c, 0x0, 0xf8, 0x7c, 0x0, 0xf8, 0x7e, 0x1, 0xf8, 0x3e, 0x1, 0xf0, 0x3f, 0x87, 0xf0, 0x1f, 0xff, 0xe0, 0xf, 0xff, 0xc0, 0x7, 0xff, 0x80, 0x1, 0xfc, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x1, 0xf8, 0x0, 0x1, 0xf0, 0x0} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {3, 18, 31, 2, 6, 0} +#define NXFONT_BITMAP_200 {0x1e, 0x0, 0x0, 0xf, 0x0, 0x0, 0x7, 0x80, 0x0, 0x3, 0xc0, 0x0, 0x1, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {3, 18, 31, 2, 6, 0} +#define NXFONT_BITMAP_201 {0x0, 0x78, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xe0, 0x0, 0x3, 0xc0, 0x0, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {3, 18, 31, 2, 6, 0} +#define NXFONT_BITMAP_202 {0x0, 0xc0, 0x0, 0x1, 0xe0, 0x0, 0x3, 0xf0, 0x0, 0x7, 0x38, 0x0, 0xe, 0x1c, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {3, 18, 31, 2, 6, 0} +#define NXFONT_BITMAP_203 {0x1e, 0x3c, 0x0, 0x1e, 0x3c, 0x0, 0x1e, 0x3c, 0x0, 0x1e, 0x3c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {1, 8, 31, 0, 6, 0} +#define NXFONT_BITMAP_204 {0xf0, 0x78, 0x3c, 0x1e, 0xf, 0x0, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 8, 31, 2, 6, 0} +#define NXFONT_BITMAP_205 {0xf, 0x1e, 0x3c, 0x78, 0xf0, 0x0, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8} + +/* Icircumflex (206) */ +#define NXFONT_METRICS_206 {2, 10, 31, 0, 6, 0} +#define NXFONT_BITMAP_206 {0xc, 0x0, 0x1e, 0x0, 0x3f, 0x0, 0x73, 0x80, 0xe1, 0xc0, 0x0, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {2, 10, 31, 0, 6, 0} +#define NXFONT_BITMAP_207 {0xf3, 0xc0, 0xf3, 0xc0, 0xf3, 0xc0, 0xf3, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0, 0x3e, 0x0} + +/* Eth (208) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_208 {3, 23, 25, 0, 12, 0} +#define NXFONT_BITMAP_208 {0x1f, 0xff, 0x80, 0x1f, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x1f, 0xff, 0xf8, 0x1f, 0x7, 0xf8, 0x1f, 0x0, 0xfc, 0x1f, 0x0, 0xfc, 0x1f, 0x0, 0x7c, 0x1f, 0x0, 0x7e, 0x1f, 0x0, 0x3e, 0x1f, 0x0, 0x3e, 0xff, 0xf0, 0x3e, 0xff, 0xf0, 0x3e, 0xff, 0xf0, 0x3e, 0x1f, 0x0, 0x3e, 0x1f, 0x0, 0x3e, 0x1f, 0x0, 0x7c, 0x1f, 0x0, 0x7c, 0x1f, 0x0, 0x7c, 0x1f, 0x0, 0xf8, 0x1f, 0x3, 0xf8, 0x1f, 0xff, 0xf0, 0x1f, 0xff, 0xf0, 0x1f, 0xff, 0xc0, 0x1f, 0xff, 0x80} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {3, 19, 30, 2, 7, 0} +#define NXFONT_BITMAP_209 {0x3, 0xc6, 0x0, 0x7, 0xfe, 0x0, 0xf, 0xfc, 0x0, 0xc, 0x78, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x3, 0xe0, 0xfc, 0x3, 0xe0, 0xfc, 0x3, 0xe0, 0xfe, 0x3, 0xe0, 0xfe, 0x3, 0xe0, 0xff, 0x3, 0xe0, 0xff, 0x3, 0xe0, 0xff, 0x83, 0xe0, 0xff, 0xc3, 0xe0, 0xfb, 0xc3, 0xe0, 0xfb, 0xe3, 0xe0, 0xf9, 0xe3, 0xe0, 0xf9, 0xf3, 0xe0, 0xf8, 0xf3, 0xe0, 0xf8, 0xfb, 0xe0, 0xf8, 0x7b, 0xe0, 0xf8, 0x3f, 0xe0, 0xf8, 0x3f, 0xe0, 0xf8, 0x1f, 0xe0, 0xf8, 0x1f, 0xe0, 0xf8, 0xf, 0xe0, 0xf8, 0xf, 0xe0, 0xf8, 0x7, 0xe0, 0xf8, 0x7, 0xe0, 0xf8, 0x3, 0xe0} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {3, 23, 31, 1, 6, 0} +#define NXFONT_BITMAP_210 {0x1, 0xe0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x78, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x7, 0xff, 0xc0, 0xf, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x3f, 0xc7, 0xf8, 0x3f, 0x1, 0xf8, 0x7e, 0x0, 0xfc, 0x7c, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0x7c, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0x7e, 0x0, 0xfc, 0x3f, 0x1, 0xf8, 0x3f, 0xc7, 0xf8, 0x1f, 0xff, 0xf0, 0xf, 0xff, 0xe0, 0x7, 0xff, 0xc0, 0x1, 0xff, 0x0} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {3, 23, 31, 1, 6, 0} +#define NXFONT_BITMAP_211 {0x0, 0x7, 0x80, 0x0, 0xf, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x78, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x7, 0xff, 0xc0, 0xf, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x3f, 0xc7, 0xf8, 0x3f, 0x1, 0xf8, 0x7e, 0x0, 0xfc, 0x7c, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0x7c, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0x7e, 0x0, 0xfc, 0x3f, 0x1, 0xf8, 0x3f, 0xc7, 0xf8, 0x1f, 0xff, 0xf0, 0xf, 0xff, 0xe0, 0x7, 0xff, 0xc0, 0x1, 0xff, 0x0} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {3, 23, 31, 1, 6, 0} +#define NXFONT_BITMAP_212 {0x0, 0x18, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x7e, 0x0, 0x0, 0xe7, 0x0, 0x1, 0xc3, 0x80, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x7, 0xff, 0xc0, 0xf, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x3f, 0xc7, 0xf8, 0x3f, 0x1, 0xf8, 0x7e, 0x0, 0xfc, 0x7c, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0x7c, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0x7e, 0x0, 0xfc, 0x3f, 0x1, 0xf8, 0x3f, 0xc7, 0xf8, 0x1f, 0xff, 0xf0, 0xf, 0xff, 0xe0, 0x7, 0xff, 0xc0, 0x1, 0xff, 0x0} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {3, 23, 30, 1, 7, 0} +#define NXFONT_BITMAP_213 {0x0, 0x78, 0xc0, 0x0, 0xff, 0xc0, 0x1, 0xff, 0x80, 0x1, 0x8f, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x7, 0xff, 0xc0, 0xf, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x3f, 0xc7, 0xf8, 0x3f, 0x1, 0xf8, 0x7e, 0x0, 0xfc, 0x7c, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0x7c, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0x7e, 0x0, 0xfc, 0x3f, 0x1, 0xf8, 0x3f, 0xc7, 0xf8, 0x1f, 0xff, 0xf0, 0xf, 0xff, 0xe0, 0x7, 0xff, 0xc0, 0x1, 0xff, 0x0} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {3, 23, 31, 1, 6, 0} +#define NXFONT_BITMAP_214 {0x1, 0xe7, 0x80, 0x1, 0xe7, 0x80, 0x1, 0xe7, 0x80, 0x1, 0xe7, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x7, 0xff, 0xc0, 0xf, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x3f, 0xc7, 0xf8, 0x3f, 0x1, 0xf8, 0x7e, 0x0, 0xfc, 0x7c, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0xf8, 0x0, 0x3e, 0x7c, 0x0, 0x7c, 0x7c, 0x0, 0x7c, 0x7e, 0x0, 0xfc, 0x3f, 0x1, 0xf8, 0x3f, 0xc7, 0xf8, 0x1f, 0xff, 0xf0, 0xf, 0xff, 0xe0, 0x7, 0xff, 0xc0, 0x1, 0xff, 0x0} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {2, 15, 16, 2, 21, 0} +#define NXFONT_BITMAP_215 {0x20, 0x8, 0x70, 0x1c, 0xf8, 0x3e, 0xfc, 0x7e, 0x7e, 0xfc, 0x3f, 0xf8, 0x1f, 0xf0, 0xf, 0xe0, 0xf, 0xe0, 0x1f, 0xf0, 0x3f, 0xf8, 0x7e, 0xfc, 0xfc, 0x7e, 0xf8, 0x3e, 0x70, 0x1c, 0x20, 0x8} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {3, 24, 25, 1, 12, 0} +#define NXFONT_BITMAP_216 {0x1, 0xff, 0x7, 0x7, 0xff, 0xce, 0xf, 0xff, 0xfc, 0x1f, 0xff, 0xf8, 0x3f, 0xc7, 0xf8, 0x3f, 0x0, 0xf8, 0x7e, 0x1, 0xfc, 0x7c, 0x3, 0xfc, 0x7c, 0x7, 0xbc, 0xf8, 0x7, 0x3e, 0xf8, 0xe, 0x3e, 0xf8, 0x1c, 0x3e, 0xf8, 0x38, 0x3e, 0xf8, 0x70, 0x3e, 0xf8, 0xe0, 0x3e, 0xf8, 0xe0, 0x3e, 0x7d, 0xc0, 0x7c, 0x7f, 0x80, 0x7c, 0x7f, 0x0, 0xfc, 0x3f, 0x1, 0xf8, 0x3f, 0xc7, 0xf8, 0x3f, 0xff, 0xf0, 0x3f, 0xff, 0xe0, 0x77, 0xff, 0xc0, 0xe1, 0xff, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {3, 19, 31, 2, 6, 0} +#define NXFONT_BITMAP_217 {0x7, 0x80, 0x0, 0x3, 0xc0, 0x0, 0x1, 0xe0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x78, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xfc, 0x7, 0xe0, 0x7f, 0x1f, 0xc0, 0x7f, 0xff, 0xc0, 0x3f, 0xff, 0x80, 0x1f, 0xff, 0x0, 0x7, 0xfc, 0x0} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {3, 19, 31, 2, 6, 0} +#define NXFONT_BITMAP_218 {0x0, 0x1e, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x78, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xfc, 0x7, 0xe0, 0x7f, 0x1f, 0xc0, 0x7f, 0xff, 0xc0, 0x3f, 0xff, 0x80, 0x1f, 0xff, 0x0, 0x7, 0xfc, 0x0} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {3, 19, 31, 2, 6, 0} +#define NXFONT_BITMAP_219 {0x0, 0x60, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xf8, 0x0, 0x3, 0x9c, 0x0, 0x7, 0xe, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xfc, 0x7, 0xe0, 0x7f, 0x1f, 0xc0, 0x7f, 0xff, 0xc0, 0x3f, 0xff, 0x80, 0x1f, 0xff, 0x0, 0x7, 0xfc, 0x0} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {3, 19, 31, 2, 6, 0} +#define NXFONT_BITMAP_220 {0xf, 0x1e, 0x0, 0xf, 0x1e, 0x0, 0xf, 0x1e, 0x0, 0xf, 0x1e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xf8, 0x3, 0xe0, 0xfc, 0x7, 0xe0, 0x7f, 0x1f, 0xc0, 0x7f, 0xff, 0xc0, 0x3f, 0xff, 0x80, 0x1f, 0xff, 0x0, 0x7, 0xfc, 0x0} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {3, 20, 31, 1, 6, 0} +#define NXFONT_BITMAP_221 {0x0, 0x1e, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x78, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x3, 0xf0, 0xfc, 0x3, 0xf0, 0x7e, 0x7, 0xe0, 0x3e, 0x7, 0xc0, 0x3f, 0xf, 0xc0, 0x3f, 0xf, 0x80, 0x1f, 0xf, 0x80, 0x1f, 0x9f, 0x0, 0xf, 0x9f, 0x0, 0xf, 0xfe, 0x0, 0x7, 0xfe, 0x0, 0x7, 0xfc, 0x0, 0x3, 0xfc, 0x0, 0x3, 0xf8, 0x0, 0x3, 0xf8, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {3, 18, 25, 2, 12, 0} +#define NXFONT_BITMAP_222 {0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xff, 0xf8, 0x0, 0xff, 0xfe, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x80, 0xf8, 0x1f, 0x80, 0xf8, 0xf, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0x7, 0xc0, 0xf8, 0xf, 0xc0, 0xf8, 0x1f, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x0, 0xff, 0xfe, 0x0, 0xff, 0xfc, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {3, 17, 25, 2, 12, 0} +#define NXFONT_BITMAP_223 {0xf, 0xc0, 0x0, 0x3f, 0xf0, 0x0, 0x7f, 0xfc, 0x0, 0xff, 0xfc, 0x0, 0xf8, 0x7e, 0x0, 0xf8, 0x3e, 0x0, 0xf0, 0x3e, 0x0, 0xf0, 0x3e, 0x0, 0xf0, 0x7c, 0x0, 0xf0, 0xfc, 0x0, 0xf1, 0xf8, 0x0, 0xf1, 0xfc, 0x0, 0xf1, 0xfe, 0x0, 0xf0, 0x7f, 0x0, 0xf0, 0x1f, 0x0, 0xf0, 0x1f, 0x80, 0xf0, 0xf, 0x80, 0xf0, 0xf, 0x80, 0xf0, 0xf, 0x80, 0xf0, 0x1f, 0x80, 0xf0, 0x3f, 0x0, 0xf1, 0xff, 0x0, 0xf1, 0xfe, 0x0, 0xf1, 0xfc, 0x0, 0xf1, 0xf0, 0x0} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_224 {0xf, 0x0, 0x7, 0x80, 0x3, 0x80, 0x1, 0xc0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x3f, 0xfc, 0x7f, 0xfc, 0x7c, 0x3e, 0xf8, 0x1e, 0xf8, 0x1e, 0x1, 0xfe, 0xf, 0xfe, 0x3f, 0xfe, 0x7f, 0x1e, 0xf8, 0x1e, 0xf0, 0x1e, 0xf0, 0x3e, 0xf8, 0x7e, 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xde, 0x3f, 0x1e} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_225 {0x0, 0x78, 0x0, 0xf0, 0x0, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x3f, 0xfc, 0x7f, 0xfc, 0x7c, 0x3e, 0xf8, 0x1e, 0xf8, 0x1e, 0x1, 0xfe, 0xf, 0xfe, 0x3f, 0xfe, 0x7f, 0x1e, 0xf8, 0x1e, 0xf0, 0x1e, 0xf0, 0x3e, 0xf8, 0x7e, 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xde, 0x3f, 0x1e} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_226 {0x1, 0x80, 0x3, 0xc0, 0x7, 0xe0, 0xe, 0x70, 0x1c, 0x38, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x3f, 0xfc, 0x7f, 0xfc, 0x7c, 0x3e, 0xf8, 0x1e, 0xf8, 0x1e, 0x1, 0xfe, 0xf, 0xfe, 0x3f, 0xfe, 0x7f, 0x1e, 0xf8, 0x1e, 0xf0, 0x1e, 0xf0, 0x3e, 0xf8, 0x7e, 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xde, 0x3f, 0x1e} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_227 {0x7, 0x8c, 0xf, 0xfc, 0x1f, 0xf8, 0x18, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x3f, 0xfc, 0x7f, 0xfc, 0x7c, 0x3e, 0xf8, 0x1e, 0xf8, 0x1e, 0x1, 0xfe, 0xf, 0xfe, 0x3f, 0xfe, 0x7f, 0x1e, 0xf8, 0x1e, 0xf0, 0x1e, 0xf0, 0x3e, 0xf8, 0x7e, 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xde, 0x3f, 0x1e} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {2, 15, 24, 1, 13, 0} +#define NXFONT_BITMAP_228 {0x1e, 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x3f, 0xfc, 0x7f, 0xfc, 0x7c, 0x3e, 0xf8, 0x1e, 0xf8, 0x1e, 0x1, 0xfe, 0xf, 0xfe, 0x3f, 0xfe, 0x7f, 0x1e, 0xf8, 0x1e, 0xf0, 0x1e, 0xf0, 0x3e, 0xf8, 0x7e, 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xde, 0x3f, 0x1e} + +/* aring (229) */ +#define NXFONT_METRICS_229 {2, 15, 25, 1, 12, 0} +#define NXFONT_BITMAP_229 {0x3, 0xc0, 0x6, 0x60, 0x4, 0x20, 0x4, 0x20, 0x6, 0x60, 0x3, 0xc0, 0x0, 0x0, 0xf, 0xf0, 0x3f, 0xfc, 0x7f, 0xfc, 0x7c, 0x3e, 0xf8, 0x1e, 0xf8, 0x1e, 0x1, 0xfe, 0xf, 0xfe, 0x3f, 0xfe, 0x7f, 0x1e, 0xf8, 0x1e, 0xf8, 0x1e, 0xf0, 0x3e, 0xf8, 0x7e, 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xde, 0x3f, 0x1e} + +/* ae (230) */ +#define NXFONT_METRICS_230 {4, 26, 19, 1, 18, 0} +#define NXFONT_BITMAP_230 {0x7, 0xe0, 0xf8, 0x0, 0x1f, 0xfb, 0xfe, 0x0, 0x3f, 0xff, 0xff, 0x0, 0x3f, 0xff, 0xff, 0x0, 0x7c, 0x3f, 0xf, 0x80, 0x78, 0x1e, 0x7, 0x80, 0x78, 0x1e, 0x7, 0xc0, 0x0, 0x3e, 0x7, 0xc0, 0x7, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xff, 0xc0, 0x7c, 0x1e, 0x0, 0x0, 0xf8, 0x1e, 0x0, 0x0, 0xf8, 0x1e, 0x7, 0xc0, 0xfc, 0x3f, 0xf, 0xc0, 0xff, 0xff, 0xff, 0x80, 0x7f, 0xf7, 0xff, 0x0, 0x3f, 0xe3, 0xfe, 0x0, 0xf, 0x81, 0xf8, 0x0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {2, 15, 25, 1, 19, 0} +#define NXFONT_BITMAP_231 {0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc, 0x7c, 0x3e, 0x78, 0x1e, 0xf8, 0x1e, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf8, 0x1e, 0xf8, 0x1e, 0x7c, 0x3e, 0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xf8, 0x7, 0xe0, 0x3, 0x0, 0x3, 0x0, 0x7, 0xc0, 0x0, 0xe0, 0x0, 0xe0, 0xf, 0xc0, 0xf, 0x80} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {2, 16, 25, 1, 12, 0} +#define NXFONT_BITMAP_232 {0xf, 0x0, 0x7, 0x80, 0x3, 0x80, 0x1, 0xc0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0x7c, 0x3e, 0xf8, 0x1e, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0xf0, 0x0, 0xf8, 0x1e, 0x7c, 0x3e, 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf0, 0x7, 0xc0} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {2, 16, 25, 1, 12, 0} +#define NXFONT_BITMAP_233 {0x0, 0x78, 0x0, 0xf0, 0x0, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x0, 0x0, 0x0, 0x0, 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0x7c, 0x3e, 0xf8, 0x1e, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0xf0, 0x0, 0xf8, 0x1e, 0x7c, 0x3e, 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf0, 0x7, 0xc0} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {2, 16, 25, 1, 12, 0} +#define NXFONT_BITMAP_234 {0x1, 0x80, 0x3, 0xc0, 0x7, 0xe0, 0xe, 0x70, 0x1c, 0x38, 0x0, 0x0, 0x0, 0x0, 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0x7c, 0x3e, 0xf8, 0x1e, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0xf0, 0x0, 0xf8, 0x1e, 0x7c, 0x3e, 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf0, 0x7, 0xc0} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {2, 16, 24, 1, 13, 0} +#define NXFONT_BITMAP_235 {0x1e, 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x0, 0x0, 0x0, 0x0, 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0x7c, 0x3e, 0xf8, 0x1e, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0xf0, 0x0, 0xf8, 0x1e, 0x7c, 0x3e, 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf0, 0x7, 0xc0} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 7, 25, 1, 12, 0} +#define NXFONT_BITMAP_236 {0xf0, 0x78, 0x38, 0x1c, 0xe, 0x0, 0x0, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 6, 25, 2, 12, 0} +#define NXFONT_BITMAP_237 {0x3c, 0x38, 0x70, 0x70, 0xe0, 0x0, 0x0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0} + +/* icircumflex (238) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_238 {2, 10, 25, 0, 12, 0} +#define NXFONT_BITMAP_238 {0xc, 0x0, 0x1e, 0x0, 0x3f, 0x0, 0x73, 0x80, 0xe1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0} + +/* idieresis (239) - NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_239 {2, 10, 24, 0, 13, 0} +#define NXFONT_BITMAP_239 {0xf3, 0xc0, 0xf3, 0xc0, 0xf3, 0xc0, 0xf3, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0x1e, 0x0} + +/* eth (240) */ +#define NXFONT_METRICS_240 {3, 17, 26, 1, 11, 0} +#define NXFONT_BITMAP_240 {0x30, 0x0, 0x0, 0x78, 0x20, 0x0, 0x7c, 0xf0, 0x0, 0x3f, 0xe0, 0x0, 0x1f, 0xc0, 0x0, 0x3f, 0xe0, 0x0, 0x73, 0xf0, 0x0, 0x21, 0xf8, 0x0, 0x7, 0xfc, 0x0, 0x1f, 0xfe, 0x0, 0x3f, 0xfe, 0x0, 0x7f, 0xff, 0x0, 0x7c, 0x1f, 0x0, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0xfc, 0x1f, 0x80, 0x7e, 0x3f, 0x0, 0x7f, 0xff, 0x0, 0x3f, 0xfe, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {2, 15, 24, 2, 13, 0} +#define NXFONT_BITMAP_241 {0xf, 0x18, 0x1f, 0xf8, 0x3f, 0xf0, 0x31, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xf3, 0xf0, 0xf7, 0xf8, 0xff, 0xfc, 0xff, 0xfe, 0xfc, 0x3e, 0xf8, 0x3e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {3, 17, 25, 1, 12, 0} +#define NXFONT_BITMAP_242 {0x7, 0x80, 0x0, 0x3, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xe0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3f, 0xfe, 0x0, 0x7f, 0xff, 0x0, 0x7c, 0x1f, 0x0, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0x7c, 0x1f, 0x0, 0x7f, 0xff, 0x0, 0x3f, 0xfe, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {3, 17, 25, 1, 12, 0} +#define NXFONT_BITMAP_243 {0x0, 0x78, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xe0, 0x0, 0x1, 0xc0, 0x0, 0x3, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3f, 0xfe, 0x0, 0x7f, 0xff, 0x0, 0x7c, 0x1f, 0x0, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0x7c, 0x1f, 0x0, 0x7f, 0xff, 0x0, 0x3f, 0xfe, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {3, 17, 25, 1, 12, 0} +#define NXFONT_BITMAP_244 {0x0, 0xc0, 0x0, 0x1, 0xe0, 0x0, 0x3, 0xf0, 0x0, 0x7, 0x38, 0x0, 0xe, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3f, 0xfe, 0x0, 0x7f, 0xff, 0x0, 0x7c, 0x1f, 0x0, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0x7c, 0x1f, 0x0, 0x7f, 0xff, 0x0, 0x3f, 0xfe, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {3, 17, 24, 1, 13, 0} +#define NXFONT_BITMAP_245 {0x7, 0x8c, 0x0, 0xf, 0xfc, 0x0, 0x1f, 0xf8, 0x0, 0x18, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3f, 0xfe, 0x0, 0x7f, 0xff, 0x0, 0x7c, 0x1f, 0x0, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0x7c, 0x1f, 0x0, 0x7f, 0xff, 0x0, 0x3f, 0xfe, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {3, 17, 24, 1, 13, 0} +#define NXFONT_BITMAP_246 {0x1e, 0x3c, 0x0, 0x1e, 0x3c, 0x0, 0x1e, 0x3c, 0x0, 0x1e, 0x3c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3f, 0xfe, 0x0, 0x7f, 0xff, 0x0, 0x7c, 0x1f, 0x0, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf0, 0x7, 0x80, 0xf8, 0xf, 0x80, 0xf8, 0xf, 0x80, 0x7c, 0x1f, 0x0, 0x7f, 0xff, 0x0, 0x3f, 0xfe, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xf0, 0x0} + +/* divide (247) */ +#define NXFONT_METRICS_247 {2, 16, 16, 1, 21, 0} +#define NXFONT_BITMAP_247 {0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0} + +/* oslash (248) - NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_248 {3, 21, 18, 0, 19, 0} +#define NXFONT_BITMAP_248 {0x1, 0xfc, 0x38, 0x7, 0xff, 0x70, 0xf, 0xff, 0xe0, 0x1f, 0xff, 0xc0, 0x1f, 0x8f, 0xc0, 0x3e, 0x7, 0xe0, 0x3e, 0xf, 0xe0, 0x3c, 0x1d, 0xe0, 0x3c, 0x39, 0xe0, 0x3c, 0x71, 0xe0, 0x3e, 0xe3, 0xe0, 0x3f, 0x83, 0xe0, 0x3f, 0x7, 0xe0, 0x1f, 0x8f, 0xc0, 0x1f, 0xff, 0xc0, 0x3f, 0xff, 0x80, 0x77, 0xff, 0x0, 0xe1, 0xfc, 0x0} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {2, 15, 25, 2, 12, 0} +#define NXFONT_BITMAP_249 {0x1e, 0x0, 0xf, 0x0, 0x7, 0x0, 0x3, 0x80, 0x1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf8, 0x3e, 0xf8, 0x7e, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0xde, 0x1f, 0x1e} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {2, 15, 25, 2, 12, 0} +#define NXFONT_BITMAP_250 {0x0, 0xf0, 0x1, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf8, 0x3e, 0xf8, 0x7e, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0xde, 0x1f, 0x1e} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {2, 15, 25, 2, 12, 0} +#define NXFONT_BITMAP_251 {0x3, 0x0, 0x7, 0x80, 0xf, 0xc0, 0x1c, 0xe0, 0x38, 0x70, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf8, 0x3e, 0xf8, 0x7e, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0xde, 0x1f, 0x1e} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {2, 15, 25, 2, 12, 0} +#define NXFONT_BITMAP_252 {0x3c, 0x78, 0x3c, 0x78, 0x3c, 0x78, 0x3c, 0x78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf8, 0x3e, 0xf8, 0x7e, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0xde, 0x1f, 0x1e} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {2, 16, 32, 1, 12, 0} +#define NXFONT_BITMAP_253 {0x0, 0x78, 0x0, 0xf0, 0x1, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0x78, 0x1e, 0x7c, 0x3e, 0x7c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3e, 0x78, 0x3e, 0x78, 0x1e, 0x78, 0x1f, 0xf0, 0x1f, 0xf0, 0xf, 0xf0, 0xf, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7, 0xc0, 0x7, 0xc0, 0x7, 0xc0, 0xf, 0x80, 0x3f, 0x80, 0x3f, 0x0, 0x3f, 0x0, 0x3c, 0x0} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {2, 16, 32, 2, 12, 0} +#define NXFONT_BITMAP_254 {0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf3, 0xf0, 0xf7, 0xfc, 0xff, 0xfe, 0xff, 0xfe, 0xfc, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf8, 0x1f, 0xf8, 0x1f, 0xfc, 0x3e, 0xff, 0xfe, 0xff, 0xfc, 0xf7, 0xf8, 0xf1, 0xf0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {2, 16, 31, 1, 13, 0} +#define NXFONT_BITMAP_255 {0x1e, 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0x78, 0x3e, 0x7c, 0x3e, 0x7c, 0x3c, 0x7c, 0x3c, 0x3e, 0x7c, 0x3e, 0x78, 0x3e, 0x78, 0x1e, 0x78, 0x1f, 0xf0, 0x1f, 0xf0, 0xf, 0xf0, 0xf, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7, 0xc0, 0x7, 0xc0, 0x7, 0xc0, 0xf, 0x80, 0x3f, 0x80, 0x3f, 0x0, 0x3f, 0x0, 0x3c, 0x0} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SANS40X49B_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_serif22x28b.h b/nuttx/graphics/nxfonts/nxfonts_serif22x28b.h new file mode 100644 index 0000000000..8f01ccf8c1 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_serif22x28b.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_serif22x28b.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Jose Pablo Carballo Gomez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SERIF22X28B_H +#define __GRAPHICS_NXFONTS_NXFONTS_SERIF22X28B_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SERIF22X28B + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 28 +#define NXFONT_MAXWIDTH 22 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 5 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 3, 13, 1, 8, 0} +#define NXFONT_BITMAP_33 {0x40, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x40, 0x40, 0x0, 0xe0, 0xe0, 0xe0} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {1, 6, 6, 2, 8, 0} +#define NXFONT_BITMAP_34 {0xcc, 0xcc, 0xcc, 0xcc, 0x88, 0x88} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {2, 10, 12, 0, 9, 0} +#define NXFONT_BITMAP_35 {0x19, 0x80, 0x19, 0x80, 0x19, 0x80, 0x7f, 0xc0, 0x7f, 0xc0, 0x33, 0x0, 0x33, 0x0, 0xff, 0x80, 0xff, 0x80, 0x66, 0x0, 0x66, 0x0, 0x66, 0x0} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {1, 8, 16, 0, 7, 0} +#define NXFONT_BITMAP_36 {0x18, 0x7e, 0xdb, 0xdb, 0xd8, 0xf8, 0x7c, 0x3e, 0x1f, 0x1f, 0x1b, 0xdb, 0xdb, 0x7e, 0x18, 0x18} + +/* percent (37) */ +#define NXFONT_METRICS_37 {2, 14, 13, 1, 8, 0} +#define NXFONT_BITMAP_37 {0x3c, 0x18, 0x77, 0xf0, 0xe2, 0x60, 0xe2, 0x40, 0xe4, 0xc0, 0xfd, 0x80, 0x73, 0x78, 0x6, 0xec, 0x6, 0xc4, 0xd, 0xc4, 0x19, 0xc8, 0x31, 0xf8, 0x30, 0xe0} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {2, 13, 13, 2, 8, 0} +#define NXFONT_BITMAP_38 {0x1e, 0x0, 0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x3a, 0x0, 0x1c, 0xf0, 0x3c, 0x60, 0x5e, 0x40, 0xcf, 0x80, 0xc7, 0x80, 0xe3, 0xc0, 0xff, 0xf8, 0x78, 0xf0} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 2, 6, 1, 8, 0} +#define NXFONT_BITMAP_39 {0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 5, 17, 1, 8, 0} +#define NXFONT_BITMAP_40 {0x8, 0x10, 0x30, 0x60, 0x60, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0x60, 0x60, 0x30, 0x10, 0x8} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 5, 17, 0, 8, 0} +#define NXFONT_BITMAP_41 {0x80, 0x40, 0x60, 0x30, 0x30, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0x30, 0x20, 0x60, 0x40, 0x80} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {1, 8, 9, 0, 8, 0} +#define NXFONT_BITMAP_42 {0x18, 0x18, 0xdb, 0xff, 0x3c, 0xff, 0xdb, 0x18, 0x18} + +/* plus (43) */ +#define NXFONT_METRICS_43 {2, 10, 10, 0, 11, 0} +#define NXFONT_BITMAP_43 {0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 4, 6, 0, 18, 0} +#define NXFONT_BITMAP_44 {0x70, 0x70, 0x70, 0x30, 0x60, 0xc0} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 5, 3, 0, 14, 0} +#define NXFONT_BITMAP_45 {0xf8, 0xf8, 0xf8} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 3, 3, 1, 18, 0} +#define NXFONT_BITMAP_46 {0xe0, 0xe0, 0xe0} + +/* slash (47) */ +#define NXFONT_METRICS_47 {1, 5, 13, 0, 8, 0} +#define NXFONT_BITMAP_47 {0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x20, 0x60, 0x60, 0x60, 0xc0, 0xc0, 0xc0} + +/* zero (48) */ +#define NXFONT_METRICS_48 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_48 {0x3c, 0x66, 0x67, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x66, 0x66, 0x3c} + +/* one (49) */ +#define NXFONT_METRICS_49 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_49 {0x1c, 0x3c, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x7f} + +/* two (50) */ +#define NXFONT_METRICS_50 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_50 {0x3c, 0x7e, 0xcf, 0x87, 0x7, 0x7, 0x6, 0xc, 0x18, 0x31, 0x63, 0xff, 0xff} + +/* three (51) */ +#define NXFONT_METRICS_51 {2, 9, 13, 0, 8, 0} +#define NXFONT_BITMAP_51 {0x3c, 0x0, 0x7e, 0x0, 0x8f, 0x0, 0x7, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0xf, 0x0, 0x7, 0x80, 0x3, 0x80, 0xc3, 0x0, 0xe6, 0x0, 0x7c, 0x0} + +/* four (52) */ +#define NXFONT_METRICS_52 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_52 {0xe, 0x1e, 0x1e, 0x2e, 0x2e, 0x4e, 0xce, 0x8e, 0xff, 0xff, 0xe, 0xe, 0xe} + +/* five (53) */ +#define NXFONT_METRICS_53 {2, 9, 13, 0, 8, 0} +#define NXFONT_BITMAP_53 {0x3f, 0x0, 0x3f, 0x0, 0x3e, 0x0, 0x40, 0x0, 0x78, 0x0, 0x7e, 0x0, 0x3f, 0x0, 0x7, 0x80, 0x3, 0x80, 0x3, 0x80, 0xc3, 0x0, 0xe6, 0x0, 0xfc, 0x0} + +/* six (54) */ +#define NXFONT_METRICS_54 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_54 {0x7, 0x1c, 0x38, 0x70, 0x60, 0xfc, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0x66, 0x3c} + +/* seven (55) */ +#define NXFONT_METRICS_55 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_55 {0xff, 0xff, 0xfe, 0x86, 0xc, 0xc, 0xc, 0x18, 0x18, 0x38, 0x30, 0x30, 0x70} + +/* eight (56) */ +#define NXFONT_METRICS_56 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_56 {0x3c, 0x66, 0xe3, 0xe3, 0xf6, 0x7c, 0x3c, 0x7e, 0xcf, 0xc7, 0xc3, 0xe7, 0x7e} + +/* nine (57) */ +#define NXFONT_METRICS_57 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_57 {0x3c, 0x66, 0xe7, 0xe7, 0xe7, 0xe7, 0x67, 0x3f, 0x7, 0x6, 0xe, 0x3c, 0xf0} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 3, 9, 1, 12, 0} +#define NXFONT_BITMAP_58 {0xe0, 0xe0, 0xe0, 0x0, 0x0, 0x0, 0xe0, 0xe0, 0xe0} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 4, 12, 0, 12, 0} +#define NXFONT_BITMAP_59 {0x70, 0x70, 0x70, 0x0, 0x0, 0x0, 0x70, 0x70, 0x70, 0x30, 0x60, 0xc0} + +/* less (60) */ +#define NXFONT_METRICS_60 {2, 9, 9, 1, 12, 0} +#define NXFONT_BITMAP_60 {0x3, 0x80, 0xf, 0x0, 0x3c, 0x0, 0xf0, 0x0, 0xc0, 0x0, 0xf0, 0x0, 0x3c, 0x0, 0xf, 0x0, 0x3, 0x80} + +/* equal (61) */ +#define NXFONT_METRICS_61 {2, 9, 6, 1, 13, 0} +#define NXFONT_BITMAP_61 {0xff, 0x80, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0xff, 0x80} + +/* greater (62) */ +#define NXFONT_METRICS_62 {2, 9, 9, 1, 12, 0} +#define NXFONT_BITMAP_62 {0xe0, 0x0, 0x78, 0x0, 0x1e, 0x0, 0x7, 0x80, 0x1, 0x80, 0x7, 0x80, 0x1e, 0x0, 0x78, 0x0, 0xe0, 0x0} + +/* question (63) */ +#define NXFONT_METRICS_63 {1, 7, 13, 1, 8, 0} +#define NXFONT_BITMAP_63 {0x7c, 0xce, 0xee, 0xee, 0x4e, 0xc, 0x18, 0x10, 0x10, 0x0, 0x38, 0x38, 0x38} + +/* at (64) */ +#define NXFONT_METRICS_64 {2, 15, 16, 1, 8, 0} +#define NXFONT_BITMAP_64 {0x3, 0xe0, 0xf, 0x38, 0x38, 0xc, 0x30, 0x4, 0x73, 0xb6, 0x67, 0x76, 0xe7, 0x76, 0xee, 0x66, 0xee, 0x66, 0xee, 0xec, 0xef, 0xfc, 0x67, 0xb8, 0x70, 0x0, 0x38, 0x0, 0x1e, 0x0, 0x7, 0xf0} + +/* A (65) */ +#define NXFONT_METRICS_65 {2, 14, 13, 0, 8, 0} +#define NXFONT_BITMAP_65 {0x3, 0x0, 0x3, 0x80, 0x7, 0x80, 0x5, 0xc0, 0xd, 0xc0, 0x8, 0xc0, 0x18, 0xe0, 0x10, 0x60, 0x1f, 0xf0, 0x30, 0x70, 0x20, 0x38, 0x60, 0x38, 0xf8, 0xfc} + +/* B (66) */ +#define NXFONT_METRICS_66 {2, 10, 13, 1, 8, 0} +#define NXFONT_BITMAP_66 {0xfe, 0x0, 0x73, 0x80, 0x71, 0xc0, 0x71, 0xc0, 0x71, 0xc0, 0x73, 0x80, 0x7e, 0x0, 0x73, 0x80, 0x71, 0xc0, 0x71, 0xc0, 0x71, 0xc0, 0x73, 0x80, 0xff, 0x0} + +/* C (67) */ +#define NXFONT_METRICS_67 {2, 12, 13, 1, 8, 0} +#define NXFONT_BITMAP_67 {0xf, 0x90, 0x38, 0xf0, 0x70, 0x70, 0x70, 0x30, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0x70, 0x0, 0x70, 0x30, 0x3c, 0xe0, 0xf, 0x80} + +/* D (68) */ +#define NXFONT_METRICS_68 {2, 12, 13, 1, 8, 0} +#define NXFONT_BITMAP_68 {0xff, 0x0, 0x71, 0xc0, 0x70, 0xe0, 0x70, 0x60, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x60, 0x70, 0xe0, 0x71, 0xc0, 0xff, 0x0} + +/* E (69) */ +#define NXFONT_METRICS_69 {2, 10, 13, 2, 8, 0} +#define NXFONT_BITMAP_69 {0xff, 0xc0, 0x70, 0xc0, 0x70, 0x40, 0x70, 0x0, 0x70, 0x0, 0x71, 0x0, 0x7f, 0x0, 0x71, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x40, 0x70, 0xc0, 0xff, 0xc0} + +/* F (70) */ +#define NXFONT_METRICS_70 {2, 10, 13, 2, 8, 0} +#define NXFONT_BITMAP_70 {0xff, 0xc0, 0x70, 0xc0, 0x70, 0x40, 0x70, 0x0, 0x70, 0x0, 0x71, 0x0, 0x7f, 0x0, 0x71, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0xf8, 0x0} + +/* G (71) */ +#define NXFONT_METRICS_71 {2, 13, 13, 1, 8, 0} +#define NXFONT_BITMAP_71 {0xf, 0x90, 0x38, 0xf0, 0x70, 0x70, 0x70, 0x30, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0xf8, 0xe0, 0x70, 0xe0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x38, 0xf0, 0xf, 0xc0} + +/* H (72) */ +#define NXFONT_METRICS_72 {2, 13, 13, 1, 8, 0} +#define NXFONT_BITMAP_72 {0xf8, 0xf8, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x7f, 0xf0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf9, 0xf8} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 5, 13, 1, 8, 0} +#define NXFONT_BITMAP_73 {0xf8, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* J (74) */ +#define NXFONT_METRICS_74 {1, 8, 15, 0, 8, 0} +#define NXFONT_BITMAP_74 {0x1f, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xee, 0xec, 0x78} + +/* K (75) */ +#define NXFONT_METRICS_75 {2, 12, 13, 2, 8, 0} +#define NXFONT_BITMAP_75 {0xf9, 0xf0, 0x70, 0xc0, 0x71, 0x80, 0x73, 0x0, 0x76, 0x0, 0x7c, 0x0, 0x7c, 0x0, 0x7e, 0x0, 0x77, 0x0, 0x77, 0x80, 0x73, 0xc0, 0x71, 0xe0, 0xf8, 0xf0} + +/* L (76) */ +#define NXFONT_METRICS_76 {2, 10, 13, 2, 8, 0} +#define NXFONT_BITMAP_76 {0xf8, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x40, 0x70, 0xc0, 0xff, 0xc0} + +/* M (77) */ +#define NXFONT_METRICS_77 {2, 15, 13, 2, 8, 0} +#define NXFONT_BITMAP_77 {0xf0, 0x1e, 0x70, 0x1c, 0x78, 0x3c, 0x78, 0x3c, 0x7c, 0x5c, 0x5c, 0x5c, 0x5e, 0xdc, 0x4e, 0x9c, 0x4f, 0x9c, 0x47, 0x1c, 0x47, 0x1c, 0x43, 0x1c, 0xe2, 0x3e} + +/* N (78) */ +#define NXFONT_METRICS_78 {2, 12, 13, 1, 8, 0} +#define NXFONT_BITMAP_78 {0xf0, 0x70, 0x78, 0x20, 0x78, 0x20, 0x7c, 0x20, 0x5e, 0x20, 0x4e, 0x20, 0x4f, 0x20, 0x47, 0xa0, 0x43, 0xa0, 0x43, 0xe0, 0x41, 0xe0, 0x40, 0xe0, 0xe0, 0xe0} + +/* O (79) */ +#define NXFONT_METRICS_79 {2, 13, 13, 1, 8, 0} +#define NXFONT_BITMAP_79 {0xf, 0x80, 0x38, 0xe0, 0x70, 0x70, 0x70, 0x70, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0x70, 0x70, 0x70, 0x70, 0x38, 0xe0, 0xf, 0x80} + +/* P (80) */ +#define NXFONT_METRICS_80 {2, 10, 13, 1, 8, 0} +#define NXFONT_BITMAP_80 {0xff, 0x0, 0x73, 0x80, 0x71, 0xc0, 0x71, 0xc0, 0x71, 0xc0, 0x73, 0x80, 0x7f, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0xf8, 0x0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {2, 13, 17, 1, 8, 0} +#define NXFONT_BITMAP_81 {0xf, 0x80, 0x38, 0xe0, 0x70, 0x70, 0x70, 0x70, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0x70, 0x70, 0x70, 0x70, 0x38, 0xe0, 0xf, 0x80, 0xf, 0x0, 0x7, 0x80, 0x3, 0xe0, 0x0, 0xf8} + +/* R (82) */ +#define NXFONT_METRICS_82 {2, 12, 13, 1, 8, 0} +#define NXFONT_BITMAP_82 {0xff, 0x0, 0x73, 0x80, 0x71, 0xc0, 0x71, 0xc0, 0x71, 0xc0, 0x73, 0x80, 0x7f, 0x0, 0x77, 0x0, 0x73, 0x80, 0x71, 0xc0, 0x71, 0xc0, 0x70, 0xe0, 0xf8, 0xf0} + +/* S (83) */ +#define NXFONT_METRICS_83 {2, 9, 13, 1, 8, 0} +#define NXFONT_BITMAP_83 {0x1e, 0x80, 0x63, 0x80, 0xe1, 0x80, 0xe0, 0x0, 0xf8, 0x0, 0x7c, 0x0, 0x3f, 0x0, 0xf, 0x80, 0x7, 0x80, 0x3, 0x80, 0xc3, 0x80, 0xe7, 0x0, 0xbc, 0x0} + +/* T (84) */ +#define NXFONT_METRICS_84 {2, 11, 13, 1, 8, 0} +#define NXFONT_BITMAP_84 {0xff, 0xe0, 0xce, 0x60, 0x8e, 0x20, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1f, 0x0} + +/* U (85) */ +#define NXFONT_METRICS_85 {2, 12, 13, 1, 8, 0} +#define NXFONT_BITMAP_85 {0xf8, 0xf0, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x60, 0x38, 0xc0, 0x1f, 0x80} + +/* V (86) */ +#define NXFONT_METRICS_86 {2, 14, 13, 0, 8, 0} +#define NXFONT_BITMAP_86 {0xfc, 0x7c, 0x78, 0x18, 0x38, 0x10, 0x3c, 0x30, 0x1c, 0x20, 0x1e, 0x60, 0x1e, 0x40, 0xe, 0xc0, 0xf, 0x80, 0x7, 0x80, 0x7, 0x0, 0x3, 0x0, 0x2, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {3, 18, 13, 1, 8, 0} +#define NXFONT_BITMAP_87 {0xfd, 0xf7, 0xc0, 0x79, 0xe1, 0x80, 0x38, 0xe1, 0x0, 0x3c, 0xe3, 0x0, 0x3c, 0xe2, 0x0, 0x1c, 0x72, 0x0, 0x1e, 0x76, 0x0, 0xe, 0x74, 0x0, 0xe, 0xbc, 0x0, 0xf, 0x3c, 0x0, 0x7, 0x3c, 0x0, 0x6, 0x18, 0x0, 0x6, 0x18, 0x0} + +/* X (88) */ +#define NXFONT_METRICS_88 {2, 14, 13, 0, 8, 0} +#define NXFONT_BITMAP_88 {0xf8, 0x78, 0x78, 0x30, 0x3c, 0x60, 0x1c, 0xc0, 0xf, 0x80, 0x7, 0x0, 0x7, 0x80, 0x7, 0xc0, 0xd, 0xc0, 0x18, 0xe0, 0x30, 0x70, 0x60, 0x78, 0xf0, 0xfc} + +/* Y (89) */ +#define NXFONT_METRICS_89 {2, 13, 13, 1, 8, 0} +#define NXFONT_BITMAP_89 {0xfc, 0x78, 0x78, 0x30, 0x38, 0x60, 0x3c, 0x40, 0x1e, 0xc0, 0xe, 0x80, 0xf, 0x80, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x1f, 0xc0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {2, 10, 13, 2, 8, 0} +#define NXFONT_BITMAP_90 {0xff, 0xc0, 0xc3, 0xc0, 0x83, 0x80, 0x7, 0x80, 0xf, 0x0, 0xe, 0x0, 0x1e, 0x0, 0x3c, 0x0, 0x38, 0x0, 0x78, 0x0, 0xf0, 0x40, 0xe0, 0xc0, 0xff, 0xc0} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 4, 16, 1, 8, 0} +#define NXFONT_BITMAP_91 {0xf0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf0} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {1, 5, 13, 0, 8, 0} +#define NXFONT_BITMAP_92 {0xc0, 0xc0, 0xc0, 0x60, 0x60, 0x60, 0x20, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 4, 16, 1, 8, 0} +#define NXFONT_BITMAP_93 {0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {1, 8, 7, 1, 8, 0} +#define NXFONT_BITMAP_94 {0x18, 0x18, 0x3c, 0x24, 0x66, 0xc3, 0xc3} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {2, 9, 2, 0, 23, 0} +#define NXFONT_BITMAP_95 {0xff, 0x80, 0xff, 0x80} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 5, 3, 0, 8, 0} +#define NXFONT_BITMAP_96 {0xe0, 0x70, 0x18} + +/* a (97) */ +#define NXFONT_METRICS_97 {1, 8, 9, 0, 12, 0} +#define NXFONT_BITMAP_97 {0x7c, 0xce, 0xce, 0x1e, 0x6e, 0xce, 0xce, 0xfe, 0x77} + +/* b (98) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_98 {2, 9, 13, 0, 8, 0} +#define NXFONT_BITMAP_98 {0xf0, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x76, 0x0, 0x7f, 0x0, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x0, 0x6e, 0x0} + +/* c (99) */ +#define NXFONT_METRICS_99 {1, 7, 9, 0, 12, 0} +#define NXFONT_BITMAP_99 {0x3e, 0x76, 0xe6, 0xe0, 0xe0, 0xe0, 0xe0, 0x76, 0x3c} + +/* d (100) */ +#define NXFONT_METRICS_100 {2, 9, 13, 0, 8, 0} +#define NXFONT_BITMAP_100 {0xf, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x37, 0x0, 0x7f, 0x0, 0xe7, 0x0, 0xe7, 0x0, 0xe7, 0x0, 0xe7, 0x0, 0xe7, 0x0, 0x77, 0x0, 0x3b, 0x80} + +/* e (101) */ +#define NXFONT_METRICS_101 {1, 7, 9, 0, 12, 0} +#define NXFONT_BITMAP_101 {0x3c, 0x76, 0xe6, 0xfe, 0xe0, 0xe0, 0xe0, 0x76, 0x3c} + +/* f (102) */ +#define NXFONT_METRICS_102 {1, 7, 13, 0, 8, 0} +#define NXFONT_BITMAP_102 {0x3e, 0x76, 0x76, 0x70, 0xfc, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* g (103) */ +#define NXFONT_METRICS_103 {2, 9, 13, 0, 12, 0} +#define NXFONT_BITMAP_103 {0x3f, 0x80, 0xe7, 0x0, 0xe7, 0x0, 0xe7, 0x0, 0xe6, 0x0, 0x78, 0x0, 0x60, 0x0, 0xfe, 0x0, 0xff, 0x80, 0xe3, 0x80, 0xc1, 0x80, 0xe3, 0x0, 0x7e, 0x0} + +/* h (104) */ +#define NXFONT_METRICS_104 {2, 10, 13, 0, 8, 0} +#define NXFONT_BITMAP_104 {0xf0, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x77, 0x0, 0x7f, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0xfb, 0xc0} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 5, 13, 0, 8, 0} +#define NXFONT_BITMAP_105 {0x60, 0x60, 0x60, 0x0, 0xf0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* j (106) -- NOTE: Xoffset should be -2, not 0. */ +#define NXFONT_METRICS_106 {1, 6, 17, 0, 8, 0} +#define NXFONT_BITMAP_106 {0x18, 0x18, 0x18, 0x0, 0x3c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xdc, 0xd8, 0x70} + +/* k (107) */ +#define NXFONT_METRICS_107 {2, 10, 13, 0, 8, 0} +#define NXFONT_BITMAP_107 {0xf0, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x73, 0x80, 0x73, 0x0, 0x76, 0x0, 0x7c, 0x0, 0x7c, 0x0, 0x7e, 0x0, 0x77, 0x0, 0x73, 0x80, 0xf7, 0xc0} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 5, 13, 0, 8, 0} +#define NXFONT_BITMAP_108 {0xf0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* m (109) */ +#define NXFONT_METRICS_109 {2, 15, 9, 0, 12, 0} +#define NXFONT_BITMAP_109 {0xf7, 0x38, 0x7b, 0xdc, 0x73, 0x9c, 0x73, 0x9c, 0x73, 0x9c, 0x73, 0x9c, 0x73, 0x9c, 0x73, 0x9c, 0xfb, 0xde} + +/* n (110) */ +#define NXFONT_METRICS_110 {2, 10, 9, 0, 12, 0} +#define NXFONT_BITMAP_110 {0xe7, 0x0, 0x7f, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0xfb, 0xc0} + +/* o (111) */ +#define NXFONT_METRICS_111 {1, 8, 9, 0, 12, 0} +#define NXFONT_BITMAP_111 {0x3c, 0x66, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x66, 0x3c} + +/* p (112) */ +#define NXFONT_METRICS_112 {2, 9, 13, 0, 12, 0} +#define NXFONT_BITMAP_112 {0xe6, 0x0, 0x7f, 0x0, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x7b, 0x0, 0x76, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0xf8, 0x0} + +/* q (113) */ +#define NXFONT_METRICS_113 {2, 9, 13, 0, 12, 0} +#define NXFONT_BITMAP_113 {0x39, 0x0, 0x77, 0x0, 0xe7, 0x0, 0xe7, 0x0, 0xe7, 0x0, 0xe7, 0x0, 0xe7, 0x0, 0x7f, 0x0, 0x37, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0xf, 0x80} + +/* r (114) */ +#define NXFONT_METRICS_114 {1, 7, 9, 0, 12, 0} +#define NXFONT_BITMAP_114 {0xee, 0x76, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* s (115) */ +#define NXFONT_METRICS_115 {1, 6, 9, 0, 12, 0} +#define NXFONT_BITMAP_115 {0x7c, 0xcc, 0xe4, 0xf0, 0x78, 0x3c, 0x9c, 0xcc, 0xf8} + +/* t (116) */ +#define NXFONT_METRICS_116 {1, 6, 11, 0, 10, 0} +#define NXFONT_BITMAP_116 {0x10, 0x30, 0xfc, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x74, 0x38} + +/* u (117) */ +#define NXFONT_METRICS_117 {2, 10, 9, 0, 12, 0} +#define NXFONT_BITMAP_117 {0xf7, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x7f, 0x80, 0x3d, 0xc0} + +/* v (118) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_118 {2, 10, 9, 0, 12, 0} +#define NXFONT_BITMAP_118 {0xfb, 0xc0, 0x71, 0x80, 0x79, 0x0, 0x3b, 0x0, 0x3b, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xc, 0x0, 0xc, 0x0} + +/* w (119) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_119 {2, 14, 9, 0, 12, 0} +#define NXFONT_BITMAP_119 {0xf7, 0x9c, 0x77, 0x18, 0x73, 0x90, 0x3b, 0xb0, 0x39, 0xa0, 0x1d, 0xe0, 0x1f, 0xe0, 0xc, 0xc0, 0xc, 0xc0} + +/* x (120) */ +#define NXFONT_METRICS_120 {2, 9, 9, 0, 12, 0} +#define NXFONT_BITMAP_120 {0xf3, 0x80, 0x73, 0x0, 0x7a, 0x0, 0x3c, 0x0, 0x1c, 0x0, 0x1e, 0x0, 0x37, 0x0, 0x67, 0x80, 0xe3, 0x80} + +/* y (121) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_121 {2, 10, 13, 0, 12, 0} +#define NXFONT_BITMAP_121 {0xfb, 0xc0, 0x71, 0x80, 0x79, 0x0, 0x3b, 0x0, 0x3a, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc8, 0x0, 0xd8, 0x0, 0xf0, 0x0} + +/* z (122) */ +#define NXFONT_METRICS_122 {1, 7, 9, 0, 12, 0} +#define NXFONT_BITMAP_122 {0xfe, 0xce, 0x8e, 0x1c, 0x38, 0x70, 0x72, 0xe6, 0xfe} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {1, 7, 17, 0, 8, 0} +#define NXFONT_BITMAP_123 {0x1e, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x1e} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 2, 16, 1, 8, 0} +#define NXFONT_BITMAP_124 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 7, 17, 1, 8, 0} +#define NXFONT_BITMAP_125 {0xf0, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0xc, 0x6, 0xc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0xf0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {1, 8, 4, 1, 14, 0} +#define NXFONT_BITMAP_126 {0x70, 0xf9, 0x9f, 0xe} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 3, 13, 1, 12, 0} +#define NXFONT_BITMAP_161 {0xe0, 0xe0, 0xe0, 0x0, 0x40, 0x40, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x40} + +/* cent (162) */ +#define NXFONT_METRICS_162 {1, 8, 13, 0, 10, 0} +#define NXFONT_BITMAP_162 {0x1, 0x3, 0x3e, 0x77, 0xef, 0xec, 0xd8, 0xd8, 0xf0, 0x73, 0x3e, 0x60, 0x40} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {2, 14, 13, 0, 8, 0} +#define NXFONT_BITMAP_163 {0x1f, 0x0, 0x3b, 0x0, 0x3b, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0xfe, 0x0, 0x38, 0x4, 0x38, 0x0, 0x30, 0x0, 0xf0, 0x80, 0xbf, 0x80, 0xef, 0x0} + +/* currency (164) */ +#define NXFONT_METRICS_164 {1, 8, 8, 0, 11, 0} +#define NXFONT_BITMAP_164 {0xdb, 0xff, 0x66, 0xc3, 0xc3, 0x66, 0xff, 0xdb} + +/* yen (165) */ +#define NXFONT_METRICS_165 {2, 9, 13, 0, 8, 0} +#define NXFONT_BITMAP_165 {0xfb, 0x80, 0x71, 0x0, 0x73, 0x0, 0x3a, 0x0, 0x3a, 0x0, 0x1c, 0x0, 0x7f, 0x0, 0x1c, 0x0, 0x7f, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x7f, 0x0} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 2, 16, 1, 8, 0} +#define NXFONT_BITMAP_166 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* section (167) */ +#define NXFONT_METRICS_167 {1, 7, 16, 1, 8, 0} +#define NXFONT_BITMAP_167 {0x3c, 0x66, 0x46, 0x60, 0x30, 0x78, 0xdc, 0xce, 0xe6, 0x76, 0x3c, 0x1c, 0xc, 0xc4, 0xcc, 0x78} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 6, 2, 0, 9, 0} +#define NXFONT_BITMAP_168 {0xcc, 0xcc} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {2, 13, 13, 1, 8, 0} +#define NXFONT_BITMAP_169 {0xf, 0x80, 0x38, 0xe0, 0x60, 0x30, 0x4f, 0xd0, 0xdc, 0xd8, 0x98, 0x48, 0x98, 0x8, 0x98, 0x8, 0xdc, 0xd8, 0x4f, 0x90, 0x60, 0x30, 0x38, 0xe0, 0xf, 0x80} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {1, 6, 8, 0, 8, 0} +#define NXFONT_BITMAP_170 {0x70, 0xd8, 0x38, 0xd8, 0xd8, 0xec, 0x0, 0xfc} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {2, 9, 7, 1, 13, 0} +#define NXFONT_BITMAP_171 {0x19, 0x80, 0x33, 0x0, 0x66, 0x0, 0xcc, 0x0, 0x66, 0x0, 0x33, 0x0, 0x19, 0x80} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {2, 9, 6, 1, 14, 0} +#define NXFONT_BITMAP_172 {0xff, 0x80, 0xff, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 5, 3, 0, 14, 0} +#define NXFONT_BITMAP_173 {0xf8, 0xf8, 0xf8} + +/* registered (174) */ +#define NXFONT_METRICS_174 {2, 13, 13, 1, 8, 0} +#define NXFONT_BITMAP_174 {0xf, 0x80, 0x38, 0xe0, 0x60, 0x30, 0x5f, 0x90, 0xcc, 0xd8, 0x8c, 0xc8, 0x8f, 0x88, 0x8d, 0x88, 0xcc, 0xd8, 0x5e, 0xf0, 0x60, 0x30, 0x38, 0xe0, 0xf, 0x80} + +/* macron (175) */ +#define NXFONT_METRICS_175 {1, 6, 1, 0, 9, 0} +#define NXFONT_BITMAP_175 {0xfc} + +/* degree (176) */ +#define NXFONT_METRICS_176 {1, 6, 5, 0, 8, 0} +#define NXFONT_BITMAP_176 {0x78, 0xcc, 0xcc, 0xcc, 0x78} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {1, 8, 11, 1, 10, 0} +#define NXFONT_BITMAP_177 {0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x0, 0xff, 0xff} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {1, 5, 8, 0, 8, 0} +#define NXFONT_BITMAP_178 {0x70, 0x98, 0x18, 0x30, 0x20, 0x40, 0xf8, 0xf0} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {1, 5, 8, 0, 8, 0} +#define NXFONT_BITMAP_179 {0x70, 0x98, 0x18, 0x70, 0x38, 0x18, 0x98, 0x70} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 5, 3, 0, 8, 0} +#define NXFONT_BITMAP_180 {0x38, 0x70, 0xc0} + +/* mu (181) */ +#define NXFONT_METRICS_181 {2, 10, 13, 0, 12, 0} +#define NXFONT_BITMAP_181 {0xf7, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x7f, 0x80, 0x7d, 0xc0, 0x60, 0x0, 0xe0, 0x0, 0xf0, 0x0, 0x60, 0x0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {2, 9, 17, 0, 8, 0} +#define NXFONT_BITMAP_182 {0x3f, 0x80, 0x7f, 0x80, 0xfb, 0x0, 0xfb, 0x0, 0xfb, 0x0, 0xfb, 0x0, 0x7b, 0x0, 0x3b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 3, 3, 1, 14, 0} +#define NXFONT_BITMAP_183 {0xe0, 0xe0, 0xe0} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 5, 4, 1, 21, 0} +#define NXFONT_BITMAP_184 {0x20, 0x18, 0x98, 0x70} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 6, 8, 0, 8, 0} +#define NXFONT_BITMAP_185 {0x30, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {1, 6, 8, 0, 8, 0} +#define NXFONT_BITMAP_186 {0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x0, 0xfc} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {2, 9, 7, 1, 13, 0} +#define NXFONT_BITMAP_187 {0xcc, 0x0, 0x66, 0x0, 0x33, 0x0, 0x19, 0x80, 0x33, 0x0, 0x66, 0x0, 0xcc, 0x0} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {2, 13, 13, 0, 8, 0} +#define NXFONT_BITMAP_188 {0x30, 0x60, 0xf0, 0xc0, 0x30, 0xc0, 0x31, 0x80, 0x31, 0x80, 0x33, 0x10, 0x33, 0x30, 0xfe, 0x70, 0x6, 0xb0, 0xd, 0xb0, 0xd, 0xf8, 0x18, 0x30, 0x18, 0x30} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {2, 13, 13, 0, 8, 0} +#define NXFONT_BITMAP_189 {0x30, 0x60, 0xf0, 0xc0, 0x30, 0xc0, 0x31, 0x80, 0x31, 0x80, 0x33, 0x70, 0x33, 0x98, 0xfe, 0x18, 0x6, 0x30, 0xc, 0x20, 0xc, 0x40, 0x18, 0xf8, 0x18, 0xf0} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {2, 13, 13, 0, 8, 0} +#define NXFONT_BITMAP_190 {0x70, 0x60, 0x98, 0xc0, 0x18, 0xc0, 0x71, 0x80, 0x39, 0x80, 0x1b, 0x10, 0x9b, 0x30, 0x76, 0x70, 0x6, 0xb0, 0xd, 0xb0, 0xd, 0xf8, 0x18, 0x30, 0x18, 0x30} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {1, 7, 13, 1, 12, 0} +#define NXFONT_BITMAP_191 {0x38, 0x38, 0x38, 0x0, 0x10, 0x10, 0x30, 0x60, 0xe4, 0xee, 0xee, 0xe6, 0x7c} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {2, 14, 17, 0, 4, 0} +#define NXFONT_BITMAP_192 {0xe, 0x0, 0x7, 0x0, 0x1, 0x80, 0x0, 0x0, 0x3, 0x0, 0x3, 0x80, 0x7, 0x80, 0x5, 0xc0, 0xd, 0xc0, 0x8, 0xc0, 0x18, 0xe0, 0x10, 0x60, 0x1f, 0xf0, 0x30, 0x70, 0x20, 0x38, 0x60, 0x38, 0xf8, 0xfc} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {2, 14, 17, 0, 4, 0} +#define NXFONT_BITMAP_193 {0x3, 0x80, 0x7, 0x0, 0xc, 0x0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x80, 0x7, 0x80, 0x5, 0xc0, 0xd, 0xc0, 0x8, 0xc0, 0x18, 0xe0, 0x10, 0x60, 0x1f, 0xf0, 0x30, 0x70, 0x20, 0x38, 0x60, 0x38, 0xf8, 0xfc} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {2, 14, 17, 0, 4, 0} +#define NXFONT_BITMAP_194 {0x3, 0x0, 0x7, 0x80, 0xc, 0xc0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x80, 0x7, 0x80, 0x5, 0xc0, 0xd, 0xc0, 0x8, 0xc0, 0x18, 0xe0, 0x10, 0x60, 0x1f, 0xf0, 0x30, 0x70, 0x20, 0x38, 0x60, 0x38, 0xf8, 0xfc} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {2, 14, 17, 0, 4, 0} +#define NXFONT_BITMAP_195 {0x6, 0x40, 0xf, 0xc0, 0x9, 0x80, 0x0, 0x0, 0x3, 0x0, 0x3, 0x80, 0x7, 0x80, 0x5, 0xc0, 0xd, 0xc0, 0x8, 0xc0, 0x18, 0xe0, 0x10, 0x60, 0x1f, 0xf0, 0x30, 0x70, 0x20, 0x38, 0x60, 0x38, 0xf8, 0xfc} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {2, 14, 16, 0, 5, 0} +#define NXFONT_BITMAP_196 {0xc, 0xc0, 0xc, 0xc0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x80, 0x7, 0x80, 0x5, 0xc0, 0xd, 0xc0, 0x8, 0xc0, 0x18, 0xe0, 0x10, 0x60, 0x1f, 0xf0, 0x30, 0x70, 0x20, 0x38, 0x60, 0x38, 0xf8, 0xfc} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {2, 14, 17, 0, 4, 0} +#define NXFONT_BITMAP_197 {0x7, 0x0, 0xd, 0x80, 0xd, 0x80, 0x7, 0x0, 0x3, 0x0, 0x3, 0x80, 0x7, 0x80, 0x5, 0xc0, 0xd, 0xc0, 0x8, 0xc0, 0x18, 0xe0, 0x10, 0x60, 0x1f, 0xf0, 0x30, 0x70, 0x20, 0x38, 0x60, 0x38, 0xf8, 0xfc} + +/* AE (198) */ +#define NXFONT_METRICS_198 {3, 17, 13, 0, 8, 0} +#define NXFONT_BITMAP_198 {0x7, 0xff, 0x80, 0x3, 0xe1, 0x80, 0x2, 0xe0, 0x80, 0x6, 0xe0, 0x0, 0x4, 0xe0, 0x0, 0xc, 0xe2, 0x0, 0x8, 0xfe, 0x0, 0x1f, 0xe2, 0x0, 0x10, 0xe0, 0x0, 0x30, 0xe0, 0x0, 0x20, 0xe0, 0x80, 0x60, 0xe1, 0x80, 0xf9, 0xff, 0x80} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {2, 12, 17, 1, 8, 0} +#define NXFONT_BITMAP_199 {0xf, 0x90, 0x38, 0xf0, 0x70, 0x70, 0x70, 0x30, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0x70, 0x0, 0x70, 0x30, 0x3c, 0xe0, 0xf, 0x80, 0x4, 0x0, 0x3, 0x0, 0x13, 0x0, 0xe, 0x0} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {2, 10, 17, 2, 4, 0} +#define NXFONT_BITMAP_200 {0x38, 0x0, 0x1c, 0x0, 0x6, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x70, 0xc0, 0x70, 0x40, 0x70, 0x0, 0x70, 0x0, 0x71, 0x0, 0x7f, 0x0, 0x71, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x40, 0x70, 0xc0, 0xff, 0xc0} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {2, 10, 17, 2, 4, 0} +#define NXFONT_BITMAP_201 {0xe, 0x0, 0x1c, 0x0, 0x30, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x70, 0xc0, 0x70, 0x40, 0x70, 0x0, 0x70, 0x0, 0x71, 0x0, 0x7f, 0x0, 0x71, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x40, 0x70, 0xc0, 0xff, 0xc0} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {2, 10, 17, 2, 4, 0} +#define NXFONT_BITMAP_202 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x70, 0xc0, 0x70, 0x40, 0x70, 0x0, 0x70, 0x0, 0x71, 0x0, 0x7f, 0x0, 0x71, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x40, 0x70, 0xc0, 0xff, 0xc0} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {2, 10, 16, 2, 5, 0} +#define NXFONT_BITMAP_203 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x70, 0xc0, 0x70, 0x40, 0x70, 0x0, 0x70, 0x0, 0x71, 0x0, 0x7f, 0x0, 0x71, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x40, 0x70, 0xc0, 0xff, 0xc0} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {1, 5, 17, 1, 4, 0} +#define NXFONT_BITMAP_204 {0xe0, 0x70, 0x18, 0x0, 0xf8, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 5, 17, 1, 4, 0} +#define NXFONT_BITMAP_205 {0x38, 0x70, 0xc0, 0x0, 0xf8, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* Icircumflex (206) */ +#define NXFONT_METRICS_206 {1, 6, 17, 1, 4, 0} +#define NXFONT_BITMAP_206 {0x30, 0x78, 0xcc, 0x0, 0xf8, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {1, 6, 16, 1, 5, 0} +#define NXFONT_BITMAP_207 {0xcc, 0xcc, 0x0, 0xf8, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* Eth (208) */ +#define NXFONT_METRICS_208 {2, 13, 13, 0, 8, 0} +#define NXFONT_BITMAP_208 {0x7f, 0x80, 0x38, 0xe0, 0x38, 0x70, 0x38, 0x30, 0x38, 0x38, 0x38, 0x38, 0xfe, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x30, 0x38, 0x70, 0x38, 0xe0, 0x7f, 0x80} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {2, 12, 17, 1, 4, 0} +#define NXFONT_BITMAP_209 {0xc, 0x80, 0x1f, 0x80, 0x13, 0x0, 0x0, 0x0, 0xf0, 0x70, 0x78, 0x20, 0x78, 0x20, 0x7c, 0x20, 0x5e, 0x20, 0x4e, 0x20, 0x4f, 0x20, 0x47, 0xa0, 0x43, 0xa0, 0x43, 0xe0, 0x41, 0xe0, 0x40, 0xe0, 0xe0, 0xe0} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {2, 13, 17, 1, 4, 0} +#define NXFONT_BITMAP_210 {0xe, 0x0, 0x7, 0x0, 0x1, 0x80, 0x0, 0x0, 0xf, 0x80, 0x38, 0xe0, 0x70, 0x70, 0x70, 0x70, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0x70, 0x70, 0x70, 0x70, 0x38, 0xe0, 0xf, 0x80} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {2, 13, 17, 1, 4, 0} +#define NXFONT_BITMAP_211 {0x3, 0x80, 0x7, 0x0, 0xc, 0x0, 0x0, 0x0, 0xf, 0x80, 0x38, 0xe0, 0x70, 0x70, 0x70, 0x70, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0x70, 0x70, 0x70, 0x70, 0x38, 0xe0, 0xf, 0x80} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {2, 13, 17, 1, 4, 0} +#define NXFONT_BITMAP_212 {0x6, 0x0, 0xf, 0x0, 0x19, 0x80, 0x0, 0x0, 0xf, 0x80, 0x38, 0xe0, 0x70, 0x70, 0x70, 0x70, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0x70, 0x70, 0x70, 0x70, 0x38, 0xe0, 0xf, 0x80} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {2, 13, 17, 1, 4, 0} +#define NXFONT_BITMAP_213 {0xc, 0x80, 0x1f, 0x80, 0x13, 0x0, 0x0, 0x0, 0xf, 0x80, 0x38, 0xe0, 0x70, 0x70, 0x70, 0x70, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0x70, 0x70, 0x70, 0x70, 0x38, 0xe0, 0xf, 0x80} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {2, 13, 16, 1, 5, 0} +#define NXFONT_BITMAP_214 {0x19, 0x80, 0x19, 0x80, 0x0, 0x0, 0xf, 0x80, 0x38, 0xe0, 0x70, 0x70, 0x70, 0x70, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0x70, 0x70, 0x70, 0x70, 0x38, 0xe0, 0xf, 0x80} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {2, 9, 8, 1, 12, 0} +#define NXFONT_BITMAP_215 {0xc1, 0x80, 0x63, 0x0, 0x36, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x36, 0x0, 0x63, 0x0, 0xc1, 0x80} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {2, 13, 15, 1, 7, 0} +#define NXFONT_BITMAP_216 {0x0, 0x60, 0xf, 0xc0, 0x38, 0xe0, 0x70, 0xb0, 0x71, 0xb0, 0xe1, 0x38, 0xe3, 0x38, 0xe2, 0x38, 0xe6, 0x38, 0xe4, 0x38, 0x6c, 0x70, 0x68, 0x70, 0x38, 0xe0, 0x1f, 0x80, 0x30, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {2, 12, 17, 1, 4, 0} +#define NXFONT_BITMAP_217 {0x1c, 0x0, 0xe, 0x0, 0x3, 0x0, 0x0, 0x0, 0xf8, 0xf0, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x60, 0x38, 0xc0, 0x1f, 0x80} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {2, 12, 17, 1, 4, 0} +#define NXFONT_BITMAP_218 {0x1, 0xc0, 0x3, 0x80, 0x6, 0x0, 0x0, 0x0, 0xf8, 0xf0, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x60, 0x38, 0xc0, 0x1f, 0x80} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {2, 12, 17, 1, 4, 0} +#define NXFONT_BITMAP_219 {0x6, 0x0, 0xf, 0x0, 0x19, 0x80, 0x0, 0x0, 0xf8, 0xf0, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x60, 0x38, 0xc0, 0x1f, 0x80} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {2, 12, 16, 1, 5, 0} +#define NXFONT_BITMAP_220 {0x19, 0x80, 0x19, 0x80, 0x0, 0x0, 0xf8, 0xf0, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x60, 0x38, 0xc0, 0x1f, 0x80} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {2, 13, 17, 1, 4, 0} +#define NXFONT_BITMAP_221 {0x0, 0xe0, 0x1, 0xc0, 0x3, 0x0, 0x0, 0x0, 0xfc, 0x78, 0x78, 0x30, 0x38, 0x60, 0x3c, 0x40, 0x1e, 0xc0, 0xe, 0x80, 0xf, 0x80, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x1f, 0xc0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {2, 10, 13, 1, 8, 0} +#define NXFONT_BITMAP_222 {0xf8, 0x0, 0x70, 0x0, 0x70, 0x0, 0x7f, 0x0, 0x73, 0x80, 0x71, 0xc0, 0x71, 0xc0, 0x71, 0xc0, 0x73, 0x80, 0x7f, 0x0, 0x70, 0x0, 0x70, 0x0, 0xf8, 0x0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {2, 9, 13, 0, 8, 0} +#define NXFONT_BITMAP_223 {0x1e, 0x0, 0x3b, 0x0, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x77, 0x0, 0x72, 0x0, 0x73, 0x0, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0xf7, 0x0} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_224 {0x70, 0x38, 0xc, 0x0, 0x7c, 0xce, 0xce, 0x1e, 0x6e, 0xce, 0xce, 0xfe, 0x77} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_225 {0xe, 0x1c, 0x30, 0x0, 0x7c, 0xce, 0xce, 0x1e, 0x6e, 0xce, 0xce, 0xfe, 0x77} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_226 {0x18, 0x3c, 0x66, 0x0, 0x7c, 0xce, 0xce, 0x1e, 0x6e, 0xce, 0xce, 0xfe, 0x77} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_227 {0x32, 0x7e, 0x4c, 0x0, 0x7c, 0xce, 0xce, 0x1e, 0x6e, 0xce, 0xce, 0xfe, 0x77} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {1, 8, 12, 0, 9, 0} +#define NXFONT_BITMAP_228 {0x66, 0x66, 0x0, 0x7c, 0xce, 0xce, 0x1e, 0x6e, 0xce, 0xce, 0xfe, 0x77} + +/* aring (229) */ +#define NXFONT_METRICS_229 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_229 {0x38, 0x6c, 0x6c, 0x38, 0x7c, 0xce, 0xce, 0x1e, 0x6e, 0xce, 0xce, 0xfe, 0x77} + +/* ae (230) */ +#define NXFONT_METRICS_230 {2, 12, 9, 0, 12, 0} +#define NXFONT_BITMAP_230 {0x7d, 0xe0, 0xe7, 0xb0, 0xc7, 0x30, 0xf, 0xf0, 0x7f, 0x0, 0xe7, 0x0, 0xc7, 0x0, 0xef, 0xb0, 0x79, 0xe0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {1, 7, 13, 0, 12, 0} +#define NXFONT_BITMAP_231 {0x3e, 0x76, 0xe6, 0xe0, 0xe0, 0xe0, 0xe0, 0x76, 0x3c, 0x10, 0xc, 0x4c, 0x38} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {1, 7, 13, 0, 8, 0} +#define NXFONT_BITMAP_232 {0x70, 0x38, 0xc, 0x0, 0x3c, 0x76, 0xe6, 0xfe, 0xe0, 0xe0, 0xe0, 0x76, 0x3c} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_233 {0x7, 0xe, 0x18, 0x0, 0x3c, 0x76, 0xe6, 0xfe, 0xe0, 0xe0, 0xe0, 0x76, 0x3c} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {1, 7, 13, 0, 8, 0} +#define NXFONT_BITMAP_234 {0x18, 0x3c, 0x66, 0x0, 0x3c, 0x76, 0xe6, 0xfe, 0xe0, 0xe0, 0xe0, 0x76, 0x3c} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {1, 7, 12, 0, 9, 0} +#define NXFONT_BITMAP_235 {0x66, 0x66, 0x0, 0x3c, 0x76, 0xe6, 0xfe, 0xe0, 0xe0, 0xe0, 0x76, 0x3c} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 5, 13, 0, 8, 0} +#define NXFONT_BITMAP_236 {0xe0, 0x70, 0x18, 0x0, 0xf0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 5, 13, 0, 8, 0} +#define NXFONT_BITMAP_237 {0x38, 0x70, 0xc0, 0x0, 0xf0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* icircumflex (238) */ +#define NXFONT_METRICS_238 {1, 6, 13, 0, 8, 0} +#define NXFONT_BITMAP_238 {0x30, 0x78, 0xcc, 0x0, 0xf0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 6, 12, 0, 9, 0} +#define NXFONT_BITMAP_239 {0xcc, 0xcc, 0x0, 0xf0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* eth (240) */ +#define NXFONT_METRICS_240 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_240 {0x60, 0x36, 0x38, 0x4c, 0x3e, 0x66, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x66, 0x3c} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {2, 10, 13, 0, 8, 0} +#define NXFONT_BITMAP_241 {0x19, 0x0, 0x3f, 0x0, 0x26, 0x0, 0x0, 0x0, 0xe7, 0x0, 0x7f, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0xfb, 0xc0} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_242 {0x70, 0x38, 0xc, 0x0, 0x3c, 0x66, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x66, 0x3c} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_243 {0x7, 0xe, 0x18, 0x0, 0x3c, 0x66, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x66, 0x3c} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_244 {0x18, 0x3c, 0x66, 0x0, 0x3c, 0x66, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x66, 0x3c} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {1, 8, 13, 0, 8, 0} +#define NXFONT_BITMAP_245 {0x32, 0x7e, 0x4c, 0x0, 0x3c, 0x66, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x66, 0x3c} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {1, 8, 12, 0, 9, 0} +#define NXFONT_BITMAP_246 {0x66, 0x66, 0x0, 0x3c, 0x66, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x66, 0x3c} + +/* divide (247) */ +#define NXFONT_METRICS_247 {1, 8, 8, 1, 12, 0} +#define NXFONT_BITMAP_247 {0x18, 0x18, 0x0, 0xff, 0xff, 0x0, 0x18, 0x18} + +/* oslash (248) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_248 {2, 10, 11, 0, 11, 0} +#define NXFONT_BITMAP_248 {0x0, 0x40, 0x1e, 0x80, 0x33, 0x0, 0x73, 0x80, 0x73, 0x80, 0x77, 0x80, 0x7b, 0x80, 0x71, 0x80, 0x33, 0x0, 0x5e, 0x0, 0x80, 0x0} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {2, 10, 13, 0, 8, 0} +#define NXFONT_BITMAP_249 {0x38, 0x0, 0x1c, 0x0, 0x6, 0x0, 0x0, 0x0, 0xf7, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x7f, 0x80, 0x3d, 0xc0} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {2, 10, 13, 0, 8, 0} +#define NXFONT_BITMAP_250 {0xe, 0x0, 0x1c, 0x0, 0x30, 0x0, 0x0, 0x0, 0xf7, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x7f, 0x80, 0x3d, 0xc0} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {2, 10, 13, 0, 8, 0} +#define NXFONT_BITMAP_251 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x0, 0x0, 0xf7, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x7f, 0x80, 0x3d, 0xc0} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {2, 10, 12, 0, 9, 0} +#define NXFONT_BITMAP_252 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0xf7, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x7f, 0x80, 0x3d, 0xc0} + +/* yacute (253) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_253 {2, 10, 17, 0, 8, 0} +#define NXFONT_BITMAP_253 {0x3, 0x80, 0x7, 0x0, 0xc, 0x0, 0x0, 0x0, 0xfb, 0xc0, 0x71, 0x80, 0x79, 0x0, 0x3b, 0x0, 0x3a, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0x8, 0x0, 0xd8, 0x0, 0xf0, 0x0} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {2, 9, 17, 0, 8, 0} +#define NXFONT_BITMAP_254 {0xf0, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x76, 0x0, 0x7f, 0x0, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x7b, 0x0, 0x76, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0xf8, 0x0} + +/* ydieresis (255) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_255 {2, 10, 16, 0, 9, 0} +#define NXFONT_BITMAP_255 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0xfb, 0xc0, 0x71, 0x80, 0x79, 0x0, 0x3b, 0x0, 0x3a, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0x8, 0x0, 0xd8, 0x0, 0xf0, 0x0} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SERIF22X28B_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_serif22x29.h b/nuttx/graphics/nxfonts/nxfonts_serif22x29.h new file mode 100644 index 0000000000..35d61ebe87 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_serif22x29.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_serif22x29.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Jose Pablo Carballo Gomez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SERIF22X29_H +#define __GRAPHICS_NXFONTS_NXFONTS_SERIF22X29_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SERIF22X29 + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 29 +#define NXFONT_MAXWIDTH 22 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 5 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 2, 13, 1, 9, 0} +#define NXFONT_BITMAP_33 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0x40, 0x40, 0x0, 0x0, 0xc0, 0xc0} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {1, 6, 4, 1, 9, 0} +#define NXFONT_BITMAP_34 {0xcc, 0xcc, 0xcc, 0x88} + +/* numbersign (35) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_35 {2, 12, 11, 0, 10, 0} +#define NXFONT_BITMAP_35 {0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0x7f, 0xf0, 0x19, 0x80, 0x19, 0x80, 0x19, 0x80, 0xff, 0xe0, 0x33, 0x0, 0x33, 0x0, 0x33, 0x0} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {1, 7, 16, 1, 8, 0} +#define NXFONT_BITMAP_36 {0x10, 0x7c, 0xd6, 0xd2, 0xd0, 0xf0, 0x78, 0x3c, 0x1c, 0x16, 0x16, 0x96, 0xd6, 0x7c, 0x10, 0x10} + +/* percent (37) */ +#define NXFONT_METRICS_37 {2, 13, 13, 1, 9, 0} +#define NXFONT_BITMAP_37 {0x38, 0x30, 0x6f, 0xe0, 0xc4, 0x40, 0xc4, 0x80, 0xcd, 0x80, 0xfb, 0x0, 0x72, 0x70, 0x6, 0xd8, 0xd, 0x88, 0x9, 0x88, 0x19, 0x98, 0x31, 0xf0, 0x20, 0xe0} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {2, 12, 13, 1, 9, 0} +#define NXFONT_BITMAP_38 {0x1c, 0x0, 0x32, 0x0, 0x32, 0x0, 0x32, 0x0, 0x34, 0x0, 0x19, 0xe0, 0x38, 0xc0, 0x6d, 0x80, 0xcf, 0x0, 0xc7, 0x0, 0xc7, 0x80, 0xed, 0xf0, 0x78, 0xe0} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 2, 4, 1, 9, 0} +#define NXFONT_BITMAP_39 {0xc0, 0xc0, 0xc0, 0x80} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 5, 17, 1, 9, 0} +#define NXFONT_BITMAP_40 {0x18, 0x30, 0x60, 0x60, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0x60, 0x60, 0x30, 0x18} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 5, 17, 1, 9, 0} +#define NXFONT_BITMAP_41 {0xc0, 0x60, 0x30, 0x30, 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, 0x30, 0x30, 0x60, 0xc0} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {1, 7, 7, 1, 9, 0} +#define NXFONT_BITMAP_42 {0x10, 0xd6, 0x54, 0x38, 0xd6, 0x92, 0x10} + +/* plus (43) */ +#define NXFONT_METRICS_43 {1, 8, 8, 1, 13, 0} +#define NXFONT_BITMAP_43 {0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 3, 5, 0, 20, 0} +#define NXFONT_BITMAP_44 {0x60, 0x60, 0x20, 0x60, 0xc0} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 5, 2, 0, 17, 0} +#define NXFONT_BITMAP_45 {0xf8, 0xf8} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 2, 2, 1, 20, 0} +#define NXFONT_BITMAP_46 {0xc0, 0xc0} + +/* slash (47) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_47 {1, 7, 17, 0, 9, 0} +#define NXFONT_BITMAP_47 {0x2, 0x2, 0x6, 0x4, 0xc, 0xc, 0x8, 0x18, 0x18, 0x10, 0x30, 0x30, 0x20, 0x60, 0x60, 0x40, 0xc0} + +/* zero (48) */ +#define NXFONT_METRICS_48 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_48 {0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x3c} + +/* one (49) */ +#define NXFONT_METRICS_49 {1, 6, 13, 2, 9, 0} +#define NXFONT_BITMAP_49 {0x30, 0x70, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0xfc} + +/* two (50) */ +#define NXFONT_METRICS_50 {1, 7, 13, 1, 9, 0} +#define NXFONT_BITMAP_50 {0x3c, 0x7e, 0xce, 0x86, 0x6, 0x6, 0xc, 0xc, 0x18, 0x30, 0x62, 0xfe, 0xfe} + +/* three (51) */ +#define NXFONT_METRICS_51 {1, 7, 13, 1, 9, 0} +#define NXFONT_BITMAP_51 {0x7c, 0xce, 0x86, 0x6, 0xc, 0x38, 0x3c, 0xe, 0x6, 0x6, 0x6, 0xcc, 0xf8} + +/* four (52) */ +#define NXFONT_METRICS_52 {1, 8, 13, 0, 9, 0} +#define NXFONT_BITMAP_52 {0x2, 0x6, 0xe, 0xe, 0x16, 0x26, 0x46, 0x46, 0xff, 0xff, 0x6, 0x6, 0x6} + +/* five (53) */ +#define NXFONT_METRICS_53 {1, 7, 13, 1, 9, 0} +#define NXFONT_BITMAP_53 {0x7e, 0x7c, 0xc0, 0xc0, 0xf0, 0x3c, 0xc, 0xe, 0x6, 0x6, 0xc, 0xdc, 0xf0} + +/* six (54) */ +#define NXFONT_METRICS_54 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_54 {0x7, 0x1c, 0x30, 0x60, 0x60, 0xfc, 0xc6, 0xc3, 0xc3, 0xc3, 0xe3, 0x76, 0x3c} + +/* seven (55) */ +#define NXFONT_METRICS_55 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_55 {0x7f, 0xff, 0x82, 0x6, 0x4, 0xc, 0xc, 0x8, 0x18, 0x18, 0x10, 0x30, 0x30} + +/* eight (56) */ +#define NXFONT_METRICS_56 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_56 {0x3c, 0x66, 0xc2, 0xe6, 0x7c, 0x38, 0x3c, 0x6e, 0xc7, 0xc3, 0xc3, 0x66, 0x3c} + +/* nine (57) */ +#define NXFONT_METRICS_57 {1, 8, 13, 1, 9, 0} +#define NXFONT_BITMAP_57 {0x3c, 0x6e, 0xc6, 0xc3, 0xc3, 0xc3, 0xe3, 0x7f, 0x36, 0x6, 0xc, 0x38, 0xe0} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 2, 9, 1, 13, 0} +#define NXFONT_BITMAP_58 {0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 3, 12, 0, 13, 0} +#define NXFONT_BITMAP_59 {0x60, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x60, 0x20, 0x60, 0xc0} + +/* less (60) */ +#define NXFONT_METRICS_60 {2, 9, 9, 1, 13, 0} +#define NXFONT_BITMAP_60 {0x1, 0x80, 0x7, 0x0, 0x1c, 0x0, 0x70, 0x0, 0xc0, 0x0, 0x70, 0x0, 0x1c, 0x0, 0x7, 0x0, 0x1, 0x80} + +/* equal (61) */ +#define NXFONT_METRICS_61 {2, 9, 5, 1, 15, 0} +#define NXFONT_BITMAP_61 {0xff, 0x80, 0xff, 0x80, 0x0, 0x0, 0xff, 0x80, 0xff, 0x80} + +/* greater (62) */ +#define NXFONT_METRICS_62 {2, 9, 9, 1, 13, 0} +#define NXFONT_BITMAP_62 {0xc0, 0x0, 0x70, 0x0, 0x1c, 0x0, 0x7, 0x0, 0x1, 0x80, 0x7, 0x0, 0x1c, 0x0, 0x70, 0x0, 0xc0, 0x0} + +/* question (63) */ +#define NXFONT_METRICS_63 {1, 6, 13, 1, 9, 0} +#define NXFONT_BITMAP_63 {0x78, 0x8c, 0xc4, 0xcc, 0xc, 0x18, 0x18, 0x30, 0x20, 0x20, 0x0, 0x30, 0x30} + +/* at (64) */ +#define NXFONT_METRICS_64 {2, 14, 16, 1, 9, 0} +#define NXFONT_BITMAP_64 {0x7, 0xe0, 0xe, 0x30, 0x38, 0x18, 0x30, 0x8, 0x63, 0xec, 0x67, 0xe4, 0xc6, 0x64, 0xcc, 0x64, 0xcc, 0xcc, 0xcc, 0xc8, 0xcd, 0xd8, 0x67, 0x70, 0x60, 0x0, 0x30, 0x0, 0x1c, 0x30, 0x7, 0xe0} + +/* A (65) */ +#define NXFONT_METRICS_65 {2, 13, 13, 1, 9, 0} +#define NXFONT_BITMAP_65 {0x2, 0x0, 0x7, 0x0, 0x7, 0x0, 0x5, 0x0, 0xd, 0x80, 0x9, 0x80, 0x19, 0xc0, 0x10, 0xc0, 0x1f, 0xc0, 0x30, 0xe0, 0x20, 0x60, 0x60, 0x70, 0xf0, 0xf8} + +/* B (66) */ +#define NXFONT_METRICS_66 {2, 10, 13, 2, 9, 0} +#define NXFONT_BITMAP_66 {0xff, 0x0, 0x63, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x63, 0x0, 0x7f, 0x80, 0x61, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x61, 0x80, 0xff, 0x0} + +/* C (67) */ +#define NXFONT_METRICS_67 {2, 11, 13, 1, 9, 0} +#define NXFONT_BITMAP_67 {0xf, 0x20, 0x30, 0xe0, 0x60, 0x60, 0x60, 0x20, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0x60, 0x0, 0x60, 0x60, 0x38, 0xc0, 0xf, 0x0} + +/* D (68) */ +#define NXFONT_METRICS_68 {2, 11, 13, 2, 9, 0} +#define NXFONT_BITMAP_68 {0xff, 0x0, 0x63, 0x80, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x60, 0xc0, 0x63, 0x80, 0xff, 0x0} + +/* E (69) */ +#define NXFONT_METRICS_69 {2, 9, 13, 1, 9, 0} +#define NXFONT_BITMAP_69 {0xff, 0x80, 0x61, 0x80, 0x60, 0x80, 0x60, 0x0, 0x60, 0x0, 0x61, 0x0, 0x7f, 0x0, 0x61, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x80, 0x61, 0x80, 0xff, 0x80} + +/* F (70) */ +#define NXFONT_METRICS_70 {2, 9, 13, 1, 9, 0} +#define NXFONT_BITMAP_70 {0xff, 0x80, 0x61, 0x80, 0x60, 0x80, 0x60, 0x0, 0x60, 0x0, 0x61, 0x0, 0x7f, 0x0, 0x61, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0xf0, 0x0} + +/* G (71) */ +#define NXFONT_METRICS_71 {2, 12, 13, 1, 9, 0} +#define NXFONT_BITMAP_71 {0xf, 0x20, 0x30, 0xe0, 0x60, 0x60, 0x60, 0x20, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0xf0, 0xc0, 0x60, 0xc0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x39, 0xc0, 0xf, 0x0} + +/* H (72) */ +#define NXFONT_METRICS_72 {2, 12, 13, 1, 9, 0} +#define NXFONT_BITMAP_72 {0xf0, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7f, 0xe0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0xf0} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 4, 13, 1, 9, 0} +#define NXFONT_BITMAP_73 {0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* J (74) */ +#define NXFONT_METRICS_74 {1, 6, 13, 0, 9, 0} +#define NXFONT_BITMAP_74 {0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xf0} + +/* K (75) */ +#define NXFONT_METRICS_75 {2, 12, 13, 1, 9, 0} +#define NXFONT_BITMAP_75 {0xf3, 0xe0, 0x61, 0x80, 0x63, 0x0, 0x66, 0x0, 0x6c, 0x0, 0x78, 0x0, 0x78, 0x0, 0x7c, 0x0, 0x6e, 0x0, 0x67, 0x0, 0x63, 0x80, 0x61, 0xc0, 0xf0, 0xf0} + +/* L (76) */ +#define NXFONT_METRICS_76 {2, 10, 13, 1, 9, 0} +#define NXFONT_BITMAP_76 {0xf0, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x40, 0x60, 0xc0, 0xff, 0xc0} + +/* M (77) */ +#define NXFONT_METRICS_77 {2, 14, 13, 1, 9, 0} +#define NXFONT_BITMAP_77 {0xe0, 0x1c, 0x70, 0x38, 0x70, 0x38, 0x78, 0x78, 0x58, 0x58, 0x58, 0xd8, 0x5c, 0xd8, 0x4c, 0x98, 0x4d, 0x98, 0x47, 0x18, 0x47, 0x18, 0x42, 0x18, 0xe2, 0x3c} + +/* N (78) */ +#define NXFONT_METRICS_78 {2, 12, 13, 1, 9, 0} +#define NXFONT_BITMAP_78 {0xe0, 0x70, 0x60, 0x20, 0x70, 0x20, 0x78, 0x20, 0x5c, 0x20, 0x4c, 0x20, 0x4e, 0x20, 0x47, 0x20, 0x43, 0xa0, 0x41, 0xe0, 0x40, 0xe0, 0x40, 0x60, 0xe0, 0x20} + +/* O (79) */ +#define NXFONT_METRICS_79 {2, 12, 13, 1, 9, 0} +#define NXFONT_BITMAP_79 {0xf, 0x0, 0x30, 0xc0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0xc0, 0xf, 0x0} + +/* P (80) */ +#define NXFONT_METRICS_80 {2, 9, 13, 1, 9, 0} +#define NXFONT_BITMAP_80 {0xff, 0x0, 0x63, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x63, 0x0, 0x7e, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0xf0, 0x0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {2, 12, 17, 1, 9, 0} +#define NXFONT_BITMAP_81 {0xf, 0x0, 0x30, 0xc0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0xc0, 0xf, 0x0, 0x6, 0x0, 0x3, 0x0, 0x1, 0xc0, 0x0, 0xf0} + +/* R (82) */ +#define NXFONT_METRICS_82 {2, 11, 13, 1, 9, 0} +#define NXFONT_BITMAP_82 {0xff, 0x0, 0x63, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x63, 0x0, 0x7e, 0x0, 0x6e, 0x0, 0x66, 0x0, 0x63, 0x0, 0x61, 0x80, 0x60, 0xc0, 0xf0, 0xe0} + +/* S (83) */ +#define NXFONT_METRICS_83 {1, 8, 13, 2, 9, 0} +#define NXFONT_BITMAP_83 {0x3a, 0x46, 0xc2, 0xc0, 0xe0, 0x78, 0x3c, 0xe, 0x7, 0x3, 0x83, 0xc6, 0xb8} + +/* T (84) */ +#define NXFONT_METRICS_84 {2, 10, 13, 1, 9, 0} +#define NXFONT_BITMAP_84 {0xff, 0xc0, 0xcc, 0xc0, 0x8c, 0x40, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0x1e, 0x0} + +/* U (85) */ +#define NXFONT_METRICS_85 {2, 11, 13, 2, 9, 0} +#define NXFONT_BITMAP_85 {0xf0, 0xe0, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x70, 0xc0, 0x39, 0x80, 0x1f, 0x0} + +/* V (86) */ +#define NXFONT_METRICS_86 {2, 13, 13, 0, 9, 0} +#define NXFONT_BITMAP_86 {0xf8, 0x78, 0x70, 0x30, 0x30, 0x20, 0x38, 0x20, 0x18, 0x60, 0x18, 0x40, 0x1c, 0x40, 0xc, 0xc0, 0xe, 0x80, 0x6, 0x80, 0x7, 0x80, 0x3, 0x0, 0x3, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {3, 18, 13, 0, 9, 0} +#define NXFONT_BITMAP_87 {0xf9, 0xe3, 0xc0, 0x70, 0xc1, 0x80, 0x30, 0xc1, 0x0, 0x38, 0xe1, 0x0, 0x18, 0x63, 0x0, 0x18, 0xe2, 0x0, 0x18, 0xe2, 0x0, 0x1d, 0xa6, 0x0, 0xd, 0x34, 0x0, 0xf, 0x3c, 0x0, 0xe, 0x38, 0x0, 0x6, 0x18, 0x0, 0x6, 0x18, 0x0} + +/* X (88) */ +#define NXFONT_METRICS_88 {2, 12, 13, 1, 9, 0} +#define NXFONT_BITMAP_88 {0xf0, 0x70, 0x70, 0x60, 0x38, 0xc0, 0x19, 0x80, 0xd, 0x0, 0xe, 0x0, 0x6, 0x0, 0xf, 0x0, 0x1b, 0x0, 0x11, 0x80, 0x31, 0xc0, 0x60, 0xe0, 0xf0, 0xf0} + +/* Y (89) */ +#define NXFONT_METRICS_89 {2, 12, 13, 1, 9, 0} +#define NXFONT_BITMAP_89 {0xf0, 0xf0, 0x70, 0x60, 0x30, 0xc0, 0x18, 0x80, 0x19, 0x0, 0xf, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0xf, 0x0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {2, 10, 13, 1, 9, 0} +#define NXFONT_BITMAP_90 {0x7f, 0xc0, 0x61, 0xc0, 0x41, 0x80, 0x3, 0x80, 0x7, 0x0, 0x6, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x30, 0x0, 0x70, 0x40, 0xe0, 0xc0, 0xff, 0xc0} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 4, 16, 2, 9, 0} +#define NXFONT_BITMAP_91 {0xf0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf0} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {1, 5, 13, 0, 9, 0} +#define NXFONT_BITMAP_92 {0x80, 0x80, 0xc0, 0x40, 0x60, 0x60, 0x20, 0x30, 0x30, 0x10, 0x18, 0x8, 0x8} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 4, 16, 0, 9, 0} +#define NXFONT_BITMAP_93 {0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {1, 7, 7, 1, 9, 0} +#define NXFONT_BITMAP_94 {0x10, 0x38, 0x28, 0x6c, 0x44, 0xc6, 0x82} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {2, 9, 2, 0, 24, 0} +#define NXFONT_BITMAP_95 {0xff, 0x80, 0xff, 0x80} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 4, 3, 0, 9, 0} +#define NXFONT_BITMAP_96 {0xc0, 0x60, 0x10} + +/* a (97) */ +#define NXFONT_METRICS_97 {1, 7, 9, 1, 13, 0} +#define NXFONT_BITMAP_97 {0x78, 0xc8, 0xcc, 0x1c, 0x6c, 0xcc, 0xcc, 0xfc, 0x66} + +/* b (98) */ +#define NXFONT_METRICS_98 {1, 8, 13, 0, 9, 0} +#define NXFONT_BITMAP_98 {0x60, 0xe0, 0x60, 0x60, 0x6e, 0x77, 0x63, 0x63, 0x63, 0x63, 0x63, 0x66, 0x5c} + +/* c (99) */ +#define NXFONT_METRICS_99 {1, 7, 9, 0, 13, 0} +#define NXFONT_BITMAP_99 {0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x66, 0x3c} + +/* d (100) */ +#define NXFONT_METRICS_100 {1, 8, 13, 0, 9, 0} +#define NXFONT_BITMAP_100 {0x6, 0xe, 0x6, 0x6, 0x3e, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x66, 0x3f} + +/* e (101) */ +#define NXFONT_METRICS_101 {1, 7, 9, 0, 13, 0} +#define NXFONT_BITMAP_101 {0x3c, 0x66, 0xc2, 0xfe, 0xc0, 0xc0, 0xc0, 0x66, 0x3c} + +/* f (102) */ +#define NXFONT_METRICS_102 {1, 6, 13, 0, 9, 0} +#define NXFONT_BITMAP_102 {0x1c, 0x34, 0x20, 0x60, 0xf8, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* g (103) */ +#define NXFONT_METRICS_103 {1, 8, 13, 0, 13, 0} +#define NXFONT_BITMAP_103 {0x3e, 0xcc, 0xc4, 0xc4, 0xcc, 0x78, 0x40, 0x7c, 0x7f, 0x83, 0xc1, 0xe2, 0x7c} + +/* h (104) */ +#define NXFONT_METRICS_104 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_104 {0x60, 0x0, 0xe0, 0x0, 0x60, 0x0, 0x60, 0x0, 0x66, 0x0, 0x6f, 0x0, 0x73, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0xf3, 0x80} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 4, 13, 0, 9, 0} +#define NXFONT_BITMAP_105 {0x60, 0x60, 0x0, 0x0, 0x60, 0xe0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* j (106) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_106 {1, 4, 17, 0, 9, 0} +#define NXFONT_BITMAP_106 {0x30, 0x30, 0x0, 0x0, 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xe0, 0xc0} + +/* k (107) */ +#define NXFONT_METRICS_107 {2, 10, 13, 0, 9, 0} +#define NXFONT_BITMAP_107 {0x60, 0x0, 0xe0, 0x0, 0x60, 0x0, 0x60, 0x0, 0x67, 0x0, 0x62, 0x0, 0x64, 0x0, 0x68, 0x0, 0x78, 0x0, 0x6c, 0x0, 0x6e, 0x0, 0x67, 0x0, 0xe3, 0xc0} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 4, 13, 0, 9, 0} +#define NXFONT_BITMAP_108 {0x60, 0xe0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* m (109) */ +#define NXFONT_METRICS_109 {2, 14, 9, 0, 13, 0} +#define NXFONT_BITMAP_109 {0x66, 0x30, 0xef, 0x78, 0x73, 0x98, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0xf7, 0xbc} + +/* n (110) */ +#define NXFONT_METRICS_110 {2, 9, 9, 0, 13, 0} +#define NXFONT_BITMAP_110 {0x66, 0x0, 0xef, 0x0, 0x73, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0xf3, 0x80} + +/* o (111) */ +#define NXFONT_METRICS_111 {1, 8, 9, 0, 13, 0} +#define NXFONT_BITMAP_111 {0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c} + +/* p (112) */ +#define NXFONT_METRICS_112 {1, 8, 13, 0, 13, 0} +#define NXFONT_BITMAP_112 {0x6e, 0xf7, 0x63, 0x63, 0x63, 0x63, 0x63, 0x76, 0x7c, 0x60, 0x60, 0x60, 0xf0} + +/* q (113) */ +#define NXFONT_METRICS_113 {1, 8, 13, 0, 13, 0} +#define NXFONT_BITMAP_113 {0x3e, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x66, 0x3e, 0x6, 0x6, 0x6, 0xf} + +/* r (114) */ +#define NXFONT_METRICS_114 {1, 6, 9, 0, 13, 0} +#define NXFONT_BITMAP_114 {0x6c, 0xec, 0x70, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* s (115) */ +#define NXFONT_METRICS_115 {1, 5, 9, 1, 13, 0} +#define NXFONT_BITMAP_115 {0x68, 0x98, 0xc8, 0xe0, 0x70, 0x38, 0x98, 0xc8, 0xb0} + +/* t (116) */ +#define NXFONT_METRICS_116 {1, 6, 11, 0, 11, 0} +#define NXFONT_BITMAP_116 {0x20, 0x60, 0xf8, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x74, 0x38} + +/* u (117) */ +#define NXFONT_METRICS_117 {2, 9, 9, 0, 13, 0} +#define NXFONT_BITMAP_117 {0xe7, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x77, 0x0, 0x3b, 0x80} + +/* v (118) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_118 {2, 9, 9, 0, 13, 0} +#define NXFONT_BITMAP_118 {0xf3, 0x80, 0x63, 0x0, 0x62, 0x0, 0x32, 0x0, 0x36, 0x0, 0x14, 0x0, 0x1c, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* w (119) */ +#define NXFONT_METRICS_119 {2, 13, 9, 0, 13, 0} +#define NXFONT_BITMAP_119 {0xe7, 0x38, 0x66, 0x30, 0x62, 0x60, 0x36, 0x60, 0x37, 0x60, 0x1d, 0x40, 0x1d, 0xc0, 0x8, 0x80, 0x8, 0x80} + +/* x (120) */ +#define NXFONT_METRICS_120 {2, 9, 9, 0, 13, 0} +#define NXFONT_BITMAP_120 {0xe1, 0x80, 0x63, 0x0, 0x36, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x36, 0x0, 0x63, 0x0, 0xc3, 0x80} + +/* y (121) */ +#define NXFONT_METRICS_121 {1, 8, 13, 0, 13, 0} +#define NXFONT_BITMAP_121 {0xf3, 0x63, 0x72, 0x32, 0x36, 0x1c, 0x1c, 0xc, 0x8, 0x18, 0x10, 0xf0, 0xe0} + +/* z (122) */ +#define NXFONT_METRICS_122 {1, 7, 9, 0, 13, 0} +#define NXFONT_BITMAP_122 {0xfe, 0xce, 0x8c, 0x18, 0x30, 0x30, 0x62, 0xe6, 0xfe} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {1, 7, 17, 1, 9, 0} +#define NXFONT_BITMAP_123 {0xe, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0xe} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 1, 13, 1, 9, 0} +#define NXFONT_BITMAP_124 {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 7, 17, 1, 9, 0} +#define NXFONT_BITMAP_125 {0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0xc, 0x6, 0xc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {2, 9, 4, 1, 15, 0} +#define NXFONT_BITMAP_126 {0x30, 0x0, 0x79, 0x80, 0xcf, 0x0, 0x6, 0x0} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 2, 13, 1, 13, 0} +#define NXFONT_BITMAP_161 {0xc0, 0xc0, 0x0, 0x0, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* cent (162) */ +#define NXFONT_METRICS_162 {1, 7, 14, 1, 11, 0} +#define NXFONT_BITMAP_162 {0x6, 0x4, 0x3c, 0x6e, 0xc8, 0xd8, 0xd0, 0xd0, 0xf0, 0x72, 0x7c, 0x40, 0xc0, 0x80} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {2, 10, 13, 0, 9, 0} +#define NXFONT_BITMAP_163 {0xf, 0x0, 0x19, 0x80, 0x19, 0x80, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x7e, 0x0, 0x18, 0x0, 0x18, 0x0, 0x10, 0x0, 0x78, 0x40, 0xbf, 0xc0, 0xe7, 0x80} + +/* currency (164) */ +#define NXFONT_METRICS_164 {2, 9, 7, 1, 12, 0} +#define NXFONT_BITMAP_164 {0xdd, 0x80, 0xf7, 0x80, 0x63, 0x0, 0x41, 0x0, 0x63, 0x0, 0xf7, 0x80, 0xdd, 0x80} + +/* yen (165) */ +#define NXFONT_METRICS_165 {1, 8, 13, 0, 9, 0} +#define NXFONT_BITMAP_165 {0xf7, 0x62, 0x62, 0x76, 0x34, 0x34, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x7e} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 1, 13, 1, 9, 0} +#define NXFONT_BITMAP_166 {0x80, 0x80, 0x80, 0x80, 0x80, 0x0, 0x0, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80} + +/* section (167) */ +#define NXFONT_METRICS_167 {1, 8, 16, 1, 9, 0} +#define NXFONT_BITMAP_167 {0x3c, 0x66, 0x66, 0x70, 0x38, 0x7c, 0x8e, 0xc7, 0xe3, 0x71, 0x3e, 0x1c, 0xe, 0x66, 0x66, 0x3c} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 5, 2, 0, 10, 0} +#define NXFONT_BITMAP_168 {0xd8, 0xd8} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {2, 13, 13, 1, 9, 0} +#define NXFONT_BITMAP_169 {0xf, 0x80, 0x30, 0x60, 0x40, 0x10, 0x47, 0x90, 0x88, 0x88, 0x90, 0x8, 0x90, 0x8, 0x90, 0x8, 0x88, 0x88, 0x47, 0x10, 0x40, 0x10, 0x30, 0x60, 0xf, 0x80} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {1, 5, 8, 0, 9, 0} +#define NXFONT_BITMAP_170 {0x60, 0x90, 0x10, 0x70, 0x90, 0xe8, 0x0, 0xf8} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {1, 8, 7, 1, 14, 0} +#define NXFONT_BITMAP_171 {0x11, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x11} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {2, 9, 5, 1, 15, 0} +#define NXFONT_BITMAP_172 {0xff, 0x80, 0xff, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 5, 2, 0, 17, 0} +#define NXFONT_BITMAP_173 {0xf8, 0xf8} + +/* registered (174) */ +#define NXFONT_METRICS_174 {2, 13, 13, 1, 9, 0} +#define NXFONT_BITMAP_174 {0xf, 0x80, 0x30, 0x60, 0x40, 0x10, 0x5f, 0x10, 0x88, 0x88, 0x88, 0x88, 0x8f, 0x8, 0x89, 0x8, 0x88, 0x88, 0x5c, 0xd0, 0x40, 0x10, 0x30, 0x60, 0xf, 0x80} + +/* macron (175) */ +#define NXFONT_METRICS_175 {1, 5, 2, 0, 10, 0} +#define NXFONT_BITMAP_175 {0xf8, 0xf8} + +/* degree (176) */ +#define NXFONT_METRICS_176 {1, 5, 5, 1, 9, 0} +#define NXFONT_BITMAP_176 {0x70, 0x88, 0x88, 0x88, 0x70} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {1, 8, 11, 1, 11, 0} +#define NXFONT_BITMAP_177 {0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x0, 0xff, 0xff} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {1, 5, 8, 0, 9, 0} +#define NXFONT_BITMAP_178 {0x70, 0x98, 0x18, 0x10, 0x20, 0x20, 0x40, 0xf8} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {1, 5, 8, 0, 9, 0} +#define NXFONT_BITMAP_179 {0x70, 0x88, 0x18, 0x70, 0x18, 0x8, 0x88, 0x70} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 4, 3, 0, 9, 0} +#define NXFONT_BITMAP_180 {0x30, 0x60, 0x80} + +/* mu (181) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_181 {2, 9, 13, 0, 13, 0} +#define NXFONT_BITMAP_181 {0xe7, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x77, 0x0, 0x7b, 0x80, 0x40, 0x0, 0x40, 0x0, 0x60, 0x0, 0x60, 0x0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {1, 7, 17, 1, 9, 0} +#define NXFONT_BITMAP_182 {0x3e, 0x74, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0x74, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 2, 2, 1, 16, 0} +#define NXFONT_BITMAP_183 {0xc0, 0xc0} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 4, 5, 1, 21, 0} +#define NXFONT_BITMAP_184 {0x20, 0x20, 0x10, 0xb0, 0x70} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 3, 8, 1, 9, 0} +#define NXFONT_BITMAP_185 {0x40, 0xc0, 0x40, 0x40, 0x40, 0x40, 0x40, 0xe0} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {1, 5, 8, 0, 9, 0} +#define NXFONT_BITMAP_186 {0x70, 0xd8, 0x88, 0x88, 0xd8, 0x70, 0x0, 0xf8} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {1, 8, 7, 1, 14, 0} +#define NXFONT_BITMAP_187 {0x88, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x88} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {2, 11, 13, 1, 9, 0} +#define NXFONT_BITMAP_188 {0x40, 0x80, 0xc1, 0x80, 0x41, 0x0, 0x43, 0x0, 0x46, 0x0, 0x44, 0x40, 0x4c, 0xc0, 0xe9, 0x40, 0x1b, 0x40, 0x32, 0x40, 0x27, 0xe0, 0x60, 0x40, 0x40, 0x40} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {2, 11, 13, 1, 9, 0} +#define NXFONT_BITMAP_189 {0x40, 0x80, 0xc1, 0x80, 0x41, 0x0, 0x43, 0x0, 0x46, 0x0, 0x45, 0xc0, 0x4e, 0x60, 0xe8, 0x60, 0x18, 0x40, 0x30, 0x80, 0x20, 0x80, 0x61, 0x0, 0x43, 0xe0} + +/* threequarters (190) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_190 {2, 13, 13, 0, 9, 0} +#define NXFONT_BITMAP_190 {0x70, 0x20, 0x88, 0x60, 0x18, 0x40, 0x70, 0xc0, 0x19, 0x80, 0x9, 0x10, 0x8b, 0x30, 0x72, 0x50, 0x6, 0xd0, 0xc, 0x90, 0x9, 0xf8, 0x18, 0x10, 0x10, 0x10} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {1, 6, 13, 1, 13, 0} +#define NXFONT_BITMAP_191 {0x30, 0x30, 0x0, 0x10, 0x10, 0x30, 0x60, 0x60, 0xc0, 0xcc, 0x8c, 0xc4, 0x78} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {2, 13, 17, 1, 5, 0} +#define NXFONT_BITMAP_192 {0x18, 0x0, 0xc, 0x0, 0x2, 0x0, 0x0, 0x0, 0x2, 0x0, 0x7, 0x0, 0x7, 0x0, 0x5, 0x0, 0xd, 0x80, 0x9, 0x80, 0x19, 0xc0, 0x10, 0xc0, 0x1f, 0xc0, 0x30, 0xe0, 0x20, 0x60, 0x60, 0x70, 0xf0, 0xf8} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {2, 13, 17, 1, 5, 0} +#define NXFONT_BITMAP_193 {0x0, 0xc0, 0x1, 0x80, 0x2, 0x0, 0x0, 0x0, 0x2, 0x0, 0x7, 0x0, 0x7, 0x0, 0x5, 0x0, 0xd, 0x80, 0x9, 0x80, 0x19, 0xc0, 0x10, 0xc0, 0x1f, 0xc0, 0x30, 0xe0, 0x20, 0x60, 0x60, 0x70, 0xf0, 0xf8} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {2, 13, 17, 1, 5, 0} +#define NXFONT_BITMAP_194 {0x2, 0x0, 0x7, 0x0, 0xd, 0x80, 0x0, 0x0, 0x2, 0x0, 0x7, 0x0, 0x7, 0x0, 0x5, 0x0, 0xd, 0x80, 0x9, 0x80, 0x19, 0xc0, 0x10, 0xc0, 0x1f, 0xc0, 0x30, 0xe0, 0x20, 0x60, 0x60, 0x70, 0xf0, 0xf8} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {2, 13, 17, 1, 5, 0} +#define NXFONT_BITMAP_195 {0xc, 0x80, 0x1f, 0x80, 0x13, 0x0, 0x0, 0x0, 0x2, 0x0, 0x7, 0x0, 0x7, 0x0, 0x5, 0x0, 0xd, 0x80, 0x9, 0x80, 0x19, 0xc0, 0x10, 0xc0, 0x1f, 0xc0, 0x30, 0xe0, 0x20, 0x60, 0x60, 0x70, 0xf0, 0xf8} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {2, 13, 16, 1, 6, 0} +#define NXFONT_BITMAP_196 {0xd, 0x80, 0xd, 0x80, 0x0, 0x0, 0x2, 0x0, 0x7, 0x0, 0x7, 0x0, 0x5, 0x0, 0xd, 0x80, 0x9, 0x80, 0x19, 0xc0, 0x10, 0xc0, 0x1f, 0xc0, 0x30, 0xe0, 0x20, 0x60, 0x60, 0x70, 0xf0, 0xf8} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {2, 13, 18, 1, 4, 0} +#define NXFONT_BITMAP_197 {0x6, 0x0, 0x9, 0x0, 0x9, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x7, 0x0, 0x7, 0x0, 0x5, 0x0, 0xd, 0x80, 0x9, 0x80, 0x19, 0xc0, 0x10, 0xc0, 0x1f, 0xc0, 0x30, 0xe0, 0x20, 0x60, 0x60, 0x70, 0xf0, 0xf8} + +/* AE (198) */ +#define NXFONT_METRICS_198 {2, 15, 13, 1, 9, 0} +#define NXFONT_BITMAP_198 {0xf, 0xfc, 0x7, 0x8c, 0x5, 0x84, 0x5, 0x80, 0xd, 0x80, 0x9, 0x88, 0x19, 0xf8, 0x1f, 0x88, 0x11, 0x80, 0x31, 0x80, 0x21, 0x82, 0x61, 0x86, 0xf7, 0xfe} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {2, 11, 17, 1, 9, 0} +#define NXFONT_BITMAP_199 {0xf, 0x20, 0x30, 0xe0, 0x60, 0x60, 0x60, 0x20, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0x60, 0x0, 0x60, 0x60, 0x38, 0xc0, 0xf, 0x0, 0x4, 0x0, 0x2, 0x0, 0x16, 0x0, 0xe, 0x0} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {2, 9, 17, 1, 5, 0} +#define NXFONT_BITMAP_200 {0x30, 0x0, 0x18, 0x0, 0x4, 0x0, 0x0, 0x0, 0xff, 0x80, 0x61, 0x80, 0x60, 0x80, 0x60, 0x0, 0x60, 0x0, 0x61, 0x0, 0x7f, 0x0, 0x61, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x80, 0x61, 0x80, 0xff, 0x80} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {2, 9, 17, 1, 5, 0} +#define NXFONT_BITMAP_201 {0x3, 0x0, 0x6, 0x0, 0x8, 0x0, 0x0, 0x0, 0xff, 0x80, 0x61, 0x80, 0x60, 0x80, 0x60, 0x0, 0x60, 0x0, 0x61, 0x0, 0x7f, 0x0, 0x61, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x80, 0x61, 0x80, 0xff, 0x80} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {2, 9, 17, 1, 5, 0} +#define NXFONT_BITMAP_202 {0x8, 0x0, 0x1c, 0x0, 0x36, 0x0, 0x0, 0x0, 0xff, 0x80, 0x61, 0x80, 0x60, 0x80, 0x60, 0x0, 0x60, 0x0, 0x61, 0x0, 0x7f, 0x0, 0x61, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x80, 0x61, 0x80, 0xff, 0x80} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {2, 9, 16, 1, 6, 0} +#define NXFONT_BITMAP_203 {0x36, 0x0, 0x36, 0x0, 0x0, 0x0, 0xff, 0x80, 0x61, 0x80, 0x60, 0x80, 0x60, 0x0, 0x60, 0x0, 0x61, 0x0, 0x7f, 0x0, 0x61, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x80, 0x61, 0x80, 0xff, 0x80} + +/* Igrave (204) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_204 {1, 6, 17, 0, 5, 0} +#define NXFONT_BITMAP_204 {0xc0, 0x60, 0x10, 0x0, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 6, 17, 1, 5, 0} +#define NXFONT_BITMAP_205 {0xc, 0x18, 0x20, 0x0, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* Icircumflex (206) */ +#define NXFONT_METRICS_206 {1, 5, 17, 1, 5, 0} +#define NXFONT_BITMAP_206 {0x20, 0x70, 0xd8, 0x0, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {1, 5, 16, 1, 6, 0} +#define NXFONT_BITMAP_207 {0xd8, 0xd8, 0x0, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* Eth (208) */ +#define NXFONT_METRICS_208 {2, 12, 13, 0, 9, 0} +#define NXFONT_BITMAP_208 {0x7f, 0x80, 0x31, 0xc0, 0x30, 0x60, 0x30, 0x60, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0x30, 0x60, 0x31, 0xc0, 0x7f, 0x80} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {2, 12, 17, 1, 5, 0} +#define NXFONT_BITMAP_209 {0xc, 0x80, 0x1f, 0x80, 0x13, 0x0, 0x0, 0x0, 0xe0, 0x70, 0x60, 0x20, 0x70, 0x20, 0x78, 0x20, 0x5c, 0x20, 0x4c, 0x20, 0x4e, 0x20, 0x47, 0x20, 0x43, 0xa0, 0x41, 0xe0, 0x40, 0xe0, 0x40, 0x60, 0xe0, 0x20} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {2, 12, 17, 1, 5, 0} +#define NXFONT_BITMAP_210 {0x30, 0x0, 0x18, 0x0, 0x4, 0x0, 0x0, 0x0, 0xf, 0x0, 0x30, 0xc0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0xc0, 0xf, 0x0} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {2, 12, 17, 1, 5, 0} +#define NXFONT_BITMAP_211 {0x0, 0xc0, 0x1, 0x80, 0x2, 0x0, 0x0, 0x0, 0xf, 0x0, 0x30, 0xc0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0xc0, 0xf, 0x0} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {2, 12, 17, 1, 5, 0} +#define NXFONT_BITMAP_212 {0x4, 0x0, 0xe, 0x0, 0x1b, 0x0, 0x0, 0x0, 0xf, 0x0, 0x30, 0xc0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0xc0, 0xf, 0x0} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {2, 12, 17, 1, 5, 0} +#define NXFONT_BITMAP_213 {0xc, 0x80, 0x1f, 0x80, 0x13, 0x0, 0x0, 0x0, 0xf, 0x0, 0x30, 0xc0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0xc0, 0xf, 0x0} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {2, 12, 16, 1, 6, 0} +#define NXFONT_BITMAP_214 {0x1b, 0x0, 0x1b, 0x0, 0x0, 0x0, 0xf, 0x0, 0x30, 0xc0, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0xc0, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0xc0, 0xf, 0x0} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {1, 8, 7, 1, 14, 0} +#define NXFONT_BITMAP_215 {0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {2, 12, 15, 1, 8, 0} +#define NXFONT_BITMAP_216 {0x0, 0x30, 0xf, 0x60, 0x30, 0xc0, 0x60, 0xe0, 0x61, 0xa0, 0xc3, 0x30, 0xc3, 0x30, 0xc6, 0x30, 0xcc, 0x30, 0xcc, 0x30, 0x58, 0x60, 0x70, 0x60, 0x30, 0xc0, 0x6f, 0x0, 0xc0, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {2, 11, 17, 2, 5, 0} +#define NXFONT_BITMAP_217 {0x30, 0x0, 0x18, 0x0, 0x4, 0x0, 0x0, 0x0, 0xf0, 0xe0, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x70, 0xc0, 0x39, 0x80, 0x1f, 0x0} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {2, 11, 17, 2, 5, 0} +#define NXFONT_BITMAP_218 {0x0, 0xc0, 0x1, 0x80, 0x2, 0x0, 0x0, 0x0, 0xf0, 0xe0, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x70, 0xc0, 0x39, 0x80, 0x1f, 0x0} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {2, 11, 17, 2, 5, 0} +#define NXFONT_BITMAP_219 {0x4, 0x0, 0xe, 0x0, 0x1b, 0x0, 0x0, 0x0, 0xf0, 0xe0, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x70, 0xc0, 0x39, 0x80, 0x1f, 0x0} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {2, 11, 16, 2, 6, 0} +#define NXFONT_BITMAP_220 {0x1b, 0x0, 0x1b, 0x0, 0x0, 0x0, 0xf0, 0xe0, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x60, 0x40, 0x70, 0xc0, 0x39, 0x80, 0x1f, 0x0} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {2, 12, 17, 1, 5, 0} +#define NXFONT_BITMAP_221 {0x0, 0xc0, 0x1, 0x80, 0x2, 0x0, 0x0, 0x0, 0xf0, 0xf0, 0x70, 0x60, 0x30, 0xc0, 0x18, 0x80, 0x19, 0x0, 0xf, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0xf, 0x0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {2, 9, 13, 1, 9, 0} +#define NXFONT_BITMAP_222 {0xf0, 0x0, 0x60, 0x0, 0x60, 0x0, 0x7f, 0x0, 0x63, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x63, 0x0, 0x7e, 0x0, 0x60, 0x0, 0x60, 0x0, 0xf0, 0x0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {1, 8, 13, 0, 9, 0} +#define NXFONT_BITMAP_223 {0x1c, 0x32, 0x63, 0x63, 0x66, 0x6e, 0x7c, 0x66, 0x63, 0x63, 0x6b, 0x6f, 0xee} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {1, 7, 13, 1, 9, 0} +#define NXFONT_BITMAP_224 {0xc0, 0x60, 0x10, 0x0, 0x78, 0xc8, 0xcc, 0x1c, 0x6c, 0xcc, 0xcc, 0xfc, 0x66} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {1, 7, 13, 1, 9, 0} +#define NXFONT_BITMAP_225 {0xc, 0x18, 0x20, 0x0, 0x78, 0xc8, 0xcc, 0x1c, 0x6c, 0xcc, 0xcc, 0xfc, 0x66} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {1, 7, 13, 1, 9, 0} +#define NXFONT_BITMAP_226 {0x10, 0x38, 0x6c, 0x0, 0x78, 0xc8, 0xcc, 0x1c, 0x6c, 0xcc, 0xcc, 0xfc, 0x66} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {1, 7, 13, 1, 9, 0} +#define NXFONT_BITMAP_227 {0x64, 0xfc, 0x98, 0x0, 0x78, 0xc8, 0xcc, 0x1c, 0x6c, 0xcc, 0xcc, 0xfc, 0x66} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {1, 7, 12, 1, 10, 0} +#define NXFONT_BITMAP_228 {0x6c, 0x6c, 0x0, 0x78, 0xc8, 0xcc, 0x1c, 0x6c, 0xcc, 0xcc, 0xfc, 0x66} + +/* aring (229) */ +#define NXFONT_METRICS_229 {1, 7, 14, 1, 8, 0} +#define NXFONT_BITMAP_229 {0x30, 0x48, 0x48, 0x30, 0x0, 0x78, 0xc8, 0xcc, 0x1c, 0x6c, 0xcc, 0xcc, 0xfc, 0x66} + +/* ae (230) */ +#define NXFONT_METRICS_230 {2, 11, 9, 0, 13, 0} +#define NXFONT_BITMAP_230 {0x7b, 0xc0, 0xce, 0x60, 0xcc, 0x20, 0x1f, 0xe0, 0x6c, 0x0, 0xcc, 0x0, 0xcc, 0x0, 0xfe, 0x60, 0x63, 0xc0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {1, 7, 13, 0, 13, 0} +#define NXFONT_BITMAP_231 {0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x10, 0x8, 0x58, 0x38} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {1, 7, 13, 0, 9, 0} +#define NXFONT_BITMAP_232 {0xc0, 0x60, 0x10, 0x0, 0x3c, 0x66, 0xc2, 0xfe, 0xc0, 0xc0, 0xc0, 0x66, 0x3c} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {1, 7, 13, 0, 9, 0} +#define NXFONT_BITMAP_233 {0x6, 0xc, 0x10, 0x0, 0x3c, 0x66, 0xc2, 0xfe, 0xc0, 0xc0, 0xc0, 0x66, 0x3c} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {1, 7, 13, 0, 9, 0} +#define NXFONT_BITMAP_234 {0x10, 0x38, 0x6c, 0x0, 0x3c, 0x66, 0xc2, 0xfe, 0xc0, 0xc0, 0xc0, 0x66, 0x3c} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {1, 7, 12, 0, 10, 0} +#define NXFONT_BITMAP_235 {0x6c, 0x6c, 0x0, 0x3c, 0x66, 0xc2, 0xfe, 0xc0, 0xc0, 0xc0, 0x66, 0x3c} + +/* igrave (236) -- NOTE: Xoffset should be -2, not 0. */ +#define NXFONT_METRICS_236 {1, 6, 13, 0, 9, 0} +#define NXFONT_BITMAP_236 {0xc0, 0x60, 0x10, 0x0, 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 6, 13, 0, 9, 0} +#define NXFONT_BITMAP_237 {0xc, 0x18, 0x20, 0x0, 0x60, 0xe0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* icircumflex (238) */ +#define NXFONT_METRICS_238 {1, 5, 13, 0, 9, 0} +#define NXFONT_BITMAP_238 {0x20, 0x70, 0xd8, 0x0, 0x60, 0xe0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 5, 12, 0, 10, 0} +#define NXFONT_BITMAP_239 {0xd8, 0xd8, 0x0, 0x60, 0xe0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* eth (240) */ +#define NXFONT_METRICS_240 {1, 8, 13, 0, 9, 0} +#define NXFONT_BITMAP_240 {0x60, 0x36, 0x38, 0x4c, 0x3e, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_241 {0x32, 0x0, 0x7e, 0x0, 0x4c, 0x0, 0x0, 0x0, 0x66, 0x0, 0xef, 0x0, 0x73, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0xf3, 0x80} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {1, 8, 13, 0, 9, 0} +#define NXFONT_BITMAP_242 {0x30, 0x18, 0x4, 0x0, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {1, 8, 13, 0, 9, 0} +#define NXFONT_BITMAP_243 {0x6, 0xc, 0x10, 0x0, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {1, 8, 13, 0, 9, 0} +#define NXFONT_BITMAP_244 {0x10, 0x38, 0x6c, 0x0, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {1, 8, 13, 0, 9, 0} +#define NXFONT_BITMAP_245 {0x32, 0x7e, 0x4c, 0x0, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {1, 8, 12, 0, 10, 0} +#define NXFONT_BITMAP_246 {0x6c, 0x6c, 0x0, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c} + +/* divide (247) */ +#define NXFONT_METRICS_247 {1, 8, 8, 1, 13, 0} +#define NXFONT_BITMAP_247 {0x18, 0x18, 0x0, 0xff, 0xff, 0x0, 0x18, 0x18} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {1, 8, 11, 0, 12, 0} +#define NXFONT_BITMAP_248 {0x1, 0x3f, 0x66, 0xcf, 0xcb, 0xdb, 0xd3, 0xf3, 0x66, 0x7c, 0xc0} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_249 {0x60, 0x0, 0x30, 0x0, 0x8, 0x0, 0x0, 0x0, 0xe7, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x77, 0x0, 0x3b, 0x80} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_250 {0x6, 0x0, 0xc, 0x0, 0x10, 0x0, 0x0, 0x0, 0xe7, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x77, 0x0, 0x3b, 0x80} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {2, 9, 13, 0, 9, 0} +#define NXFONT_BITMAP_251 {0x8, 0x0, 0x1c, 0x0, 0x36, 0x0, 0x0, 0x0, 0xe7, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x77, 0x0, 0x3b, 0x80} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {2, 9, 12, 0, 10, 0} +#define NXFONT_BITMAP_252 {0x36, 0x0, 0x36, 0x0, 0x0, 0x0, 0xe7, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x63, 0x0, 0x77, 0x0, 0x3b, 0x80} + +/* yacute (253) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_253 {1, 8, 17, 0, 9, 0} +#define NXFONT_BITMAP_253 {0x3, 0x6, 0x8, 0x0, 0xf3, 0x63, 0x72, 0x32, 0x36, 0x1c, 0x1c, 0xc, 0x8, 0x18, 0x10, 0xf0, 0xe0} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {1, 8, 17, 0, 9, 0} +#define NXFONT_BITMAP_254 {0x60, 0xe0, 0x60, 0x60, 0x6e, 0x77, 0x63, 0x63, 0x63, 0x63, 0x63, 0x76, 0x7c, 0x60, 0x60, 0x60, 0xf0} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {1, 8, 16, 0, 10, 0} +#define NXFONT_BITMAP_255 {0x36, 0x36, 0x0, 0xf3, 0x63, 0x72, 0x32, 0x36, 0x1c, 0x1c, 0xc, 0x8, 0x18, 0x10, 0xf0, 0xe0} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SERIF22X29_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_serif27x38b.h b/nuttx/graphics/nxfonts/nxfonts_serif27x38b.h new file mode 100755 index 0000000000..e6ecf19698 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_serif27x38b.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_serif27x38b.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Jose Pablo Carballo Gomez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SERIF27X38B_H +#define __GRAPHICS_NXFONTS_NXFONTS_SERIF27X38B_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SERIF27X38B + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 38 +#define NXFONT_MAXWIDTH 27 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 6 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 4, 17, 2, 11, 0} +#define NXFONT_BITMAP_33 {0x60, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x0, 0x0, 0x60, 0xf0, 0xf0, 0x60} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {1, 8, 8, 2, 11, 0} +#define NXFONT_BITMAP_34 {0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x42, 0x42} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {2, 12, 17, 0, 11, 0} +#define NXFONT_BITMAP_35 {0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0xc, 0xc0, 0x7f, 0xf0, 0x7f, 0xf0, 0x19, 0x80, 0x19, 0x80, 0x19, 0x80, 0x19, 0x80, 0xff, 0xe0, 0xff, 0xe0, 0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x33, 0x0} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {2, 10, 20, 1, 10, 0} +#define NXFONT_BITMAP_36 {0x8, 0x0, 0x8, 0x0, 0x3f, 0x0, 0x6b, 0x80, 0xe9, 0x80, 0xe9, 0x80, 0xf8, 0x80, 0x7c, 0x0, 0x7e, 0x0, 0x3f, 0x0, 0x1f, 0x80, 0xf, 0x80, 0xb, 0xc0, 0x89, 0xc0, 0xc9, 0xc0, 0xc9, 0x80, 0xeb, 0x80, 0x3e, 0x0, 0x8, 0x0, 0x8, 0x0} + +/* percent (37) */ +#define NXFONT_METRICS_37 {3, 17, 17, 1, 11, 0} +#define NXFONT_BITMAP_37 {0x1e, 0xc, 0x0, 0x3b, 0xfc, 0x0, 0x71, 0x18, 0x0, 0xe1, 0x30, 0x0, 0xe2, 0x30, 0x0, 0xe2, 0x60, 0x0, 0xf4, 0x60, 0x0, 0x78, 0xc0, 0x0, 0x0, 0xc0, 0x0, 0x1, 0x8f, 0x0, 0x1, 0x9d, 0x80, 0x3, 0x38, 0x80, 0x3, 0x70, 0x80, 0x6, 0x71, 0x0, 0x6, 0x71, 0x0, 0xc, 0x7a, 0x0, 0xc, 0x3c, 0x0} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {3, 17, 17, 1, 11, 0} +#define NXFONT_BITMAP_38 {0x3, 0xe0, 0x0, 0x6, 0x70, 0x0, 0xe, 0x30, 0x0, 0xe, 0x30, 0x0, 0xe, 0x70, 0x0, 0x7, 0xe0, 0x0, 0xf, 0xf, 0x80, 0x1f, 0x87, 0x0, 0x33, 0xc2, 0x0, 0x61, 0xe6, 0x0, 0xe1, 0xfc, 0x0, 0xe0, 0xf8, 0x0, 0xe0, 0x78, 0x0, 0xf0, 0x7c, 0x0, 0xf8, 0xff, 0x80, 0x7f, 0x9f, 0x0, 0x3f, 0xe, 0x0} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 3, 8, 2, 11, 0} +#define NXFONT_BITMAP_39 {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x40, 0x40} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 5, 21, 1, 11, 0} +#define NXFONT_BITMAP_40 {0x8, 0x18, 0x30, 0x30, 0x70, 0x60, 0x60, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x60, 0x60, 0x70, 0x30, 0x30, 0x18, 0x8} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 5, 21, 1, 11, 0} +#define NXFONT_BITMAP_41 {0x80, 0xc0, 0x60, 0x60, 0x30, 0x30, 0x30, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x30, 0x30, 0x30, 0x60, 0x60, 0xc0, 0x80} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {2, 10, 11, 1, 11, 0} +#define NXFONT_BITMAP_42 {0xc, 0x0, 0xc, 0x0, 0x4c, 0x80, 0xed, 0xc0, 0x7f, 0x80, 0x1e, 0x0, 0x7f, 0x80, 0xed, 0xc0, 0x4c, 0x80, 0xc, 0x0, 0xc, 0x0} + +/* plus (43) */ +#define NXFONT_METRICS_43 {2, 12, 12, 1, 16, 0} +#define NXFONT_BITMAP_43 {0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 4, 9, 1, 24, 0} +#define NXFONT_BITMAP_44 {0x60, 0xf0, 0xf0, 0x70, 0x30, 0x60, 0x60, 0xc0, 0x80} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 6, 3, 1, 20, 0} +#define NXFONT_BITMAP_45 {0xfc, 0xfc, 0xfc} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 4, 4, 1, 24, 0} +#define NXFONT_BITMAP_46 {0x60, 0xf0, 0xf0, 0x60} + +/* slash (47) */ +#define NXFONT_METRICS_47 {1, 7, 17, 0, 11, 0} +#define NXFONT_BITMAP_47 {0x6, 0x6, 0x4, 0xc, 0xc, 0x8, 0x18, 0x18, 0x10, 0x30, 0x30, 0x20, 0x60, 0x60, 0x40, 0xc0, 0xc0} + +/* zero (48) */ +#define NXFONT_METRICS_48 {2, 11, 17, 0, 11, 0} +#define NXFONT_BITMAP_48 {0xe, 0x0, 0x3b, 0x80, 0x31, 0x80, 0x71, 0xc0, 0x71, 0xc0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0x71, 0xc0, 0x71, 0xc0, 0x71, 0xc0, 0x31, 0x80, 0x3b, 0x80, 0xe, 0x0} + +/* one (49) */ +#define NXFONT_METRICS_49 {2, 9, 17, 2, 11, 0} +#define NXFONT_BITMAP_49 {0xc, 0x0, 0x3c, 0x0, 0xfc, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0xff, 0x80} + +/* two (50) */ +#define NXFONT_METRICS_50 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_50 {0x1e, 0x0, 0x3f, 0x0, 0x7f, 0x80, 0xc7, 0x80, 0x83, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x0, 0x7, 0x0, 0x6, 0x0, 0xc, 0x0, 0xc, 0x0, 0x18, 0x40, 0x30, 0x40, 0x7f, 0xc0, 0xff, 0xc0, 0xff, 0x80} + +/* three (51) */ +#define NXFONT_METRICS_51 {2, 11, 17, 0, 11, 0} +#define NXFONT_BITMAP_51 {0xf, 0x0, 0x3f, 0x80, 0x63, 0xc0, 0x41, 0xc0, 0x1, 0xc0, 0x3, 0x80, 0x7, 0x0, 0x1f, 0x0, 0x7, 0xc0, 0x1, 0xe0, 0x1, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x60, 0xe0, 0xf1, 0xc0, 0xfb, 0x80, 0x7e, 0x0} + +/* four (52) */ +#define NXFONT_METRICS_52 {2, 11, 17, 0, 11, 0} +#define NXFONT_BITMAP_52 {0x1, 0x80, 0x3, 0x80, 0x7, 0x80, 0x7, 0x80, 0xf, 0x80, 0x1b, 0x80, 0x33, 0x80, 0x33, 0x80, 0x63, 0x80, 0xc3, 0x80, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80} + +/* five (53) */ +#define NXFONT_METRICS_53 {2, 11, 17, 0, 11, 0} +#define NXFONT_BITMAP_53 {0x1f, 0xe0, 0x1f, 0xc0, 0x3f, 0xc0, 0x30, 0x0, 0x20, 0x0, 0x70, 0x0, 0x7f, 0x0, 0x7f, 0x80, 0x7f, 0xc0, 0x7, 0xc0, 0x1, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x60, 0xc0, 0xf1, 0x80, 0xfb, 0x80, 0x7e, 0x0} + +/* six (54) */ +#define NXFONT_METRICS_54 {2, 11, 17, 1, 11, 0} +#define NXFONT_BITMAP_54 {0x1, 0xe0, 0x7, 0x80, 0x1e, 0x0, 0x3c, 0x0, 0x38, 0x0, 0x78, 0x0, 0x77, 0x0, 0x7b, 0x80, 0xf1, 0xc0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0x71, 0xc0, 0x71, 0xc0, 0x3b, 0x80, 0x1e, 0x0} + +/* seven (55) */ +#define NXFONT_METRICS_55 {2, 11, 17, 0, 11, 0} +#define NXFONT_BITMAP_55 {0x3f, 0xe0, 0x7f, 0xe0, 0x7f, 0xc0, 0xc0, 0xc0, 0x81, 0x80, 0x1, 0x80, 0x3, 0x80, 0x3, 0x0, 0x3, 0x0, 0x7, 0x0, 0x6, 0x0, 0x6, 0x0, 0xe, 0x0, 0xe, 0x0, 0xc, 0x0, 0x1c, 0x0, 0x1c, 0x0} + +/* eight (56) */ +#define NXFONT_METRICS_56 {2, 11, 17, 0, 11, 0} +#define NXFONT_BITMAP_56 {0x1f, 0x0, 0x3b, 0x80, 0x71, 0xc0, 0x71, 0xc0, 0x71, 0xc0, 0x79, 0x80, 0x3b, 0x0, 0x3f, 0x0, 0x1f, 0x80, 0x37, 0xc0, 0x63, 0xc0, 0xe1, 0xe0, 0xe1, 0xe0, 0xe1, 0xe0, 0xf1, 0xc0, 0x7b, 0x80, 0x3e, 0x0} + +/* nine (57) */ +#define NXFONT_METRICS_57 {2, 11, 17, 0, 11, 0} +#define NXFONT_BITMAP_57 {0xe, 0x0, 0x3b, 0x80, 0x71, 0xc0, 0x71, 0xc0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0x71, 0xe0, 0x3b, 0xc0, 0x1f, 0xc0, 0x3, 0xc0, 0x3, 0x80, 0x7, 0x80, 0xf, 0x0, 0x3c, 0x0, 0xf0, 0x0} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 4, 12, 2, 16, 0} +#define NXFONT_BITMAP_58 {0x60, 0xf0, 0xf0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x60, 0xf0, 0xf0, 0x60} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 4, 17, 2, 16, 0} +#define NXFONT_BITMAP_59 {0x60, 0xf0, 0xf0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x60, 0xf0, 0xf0, 0x70, 0x30, 0x60, 0x60, 0xc0, 0x80} + +/* less (60) */ +#define NXFONT_METRICS_60 {2, 11, 12, 1, 16, 0} +#define NXFONT_BITMAP_60 {0x0, 0x60, 0x1, 0xe0, 0x7, 0xc0, 0x1f, 0x0, 0x3c, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0x3c, 0x0, 0x1f, 0x0, 0x7, 0xc0, 0x1, 0xe0, 0x0, 0x60} + +/* equal (61) */ +#define NXFONT_METRICS_61 {2, 11, 6, 1, 19, 0} +#define NXFONT_BITMAP_61 {0xff, 0xe0, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, 0xff, 0xe0} + +/* greater (62) */ +#define NXFONT_METRICS_62 {2, 11, 12, 1, 16, 0} +#define NXFONT_BITMAP_62 {0xc0, 0x0, 0xf0, 0x0, 0x7c, 0x0, 0x1f, 0x0, 0x7, 0x80, 0x0, 0xe0, 0x0, 0xe0, 0x7, 0x80, 0x1f, 0x0, 0x7c, 0x0, 0xf0, 0x0, 0xc0, 0x0} + +/* question (63) */ +#define NXFONT_METRICS_63 {2, 9, 17, 1, 11, 0} +#define NXFONT_BITMAP_63 {0x3e, 0x0, 0x6f, 0x0, 0xe7, 0x80, 0xe7, 0x80, 0x47, 0x80, 0x7, 0x80, 0xf, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x18, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x18, 0x0} + +/* at (64) */ +#define NXFONT_METRICS_64 {3, 20, 21, 1, 11, 0} +#define NXFONT_BITMAP_64 {0x0, 0x7c, 0x0, 0x3, 0xf7, 0x80, 0xf, 0x80, 0xc0, 0x1e, 0x0, 0x60, 0x3c, 0x0, 0x20, 0x38, 0x3b, 0x30, 0x70, 0xff, 0x10, 0x71, 0xe7, 0x10, 0xf1, 0xc7, 0x10, 0xe3, 0xc6, 0x10, 0xe3, 0x8e, 0x10, 0xe3, 0x8e, 0x30, 0xe3, 0x8e, 0x20, 0xf3, 0x9e, 0x60, 0xf1, 0xfe, 0xc0, 0x70, 0xf3, 0x80, 0x78, 0x0, 0x0, 0x38, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x7, 0x83, 0x0, 0x1, 0xfc, 0x0} + +/* A (65) */ +#define NXFONT_METRICS_65 {3, 17, 17, 0, 11, 0} +#define NXFONT_BITMAP_65 {0x1, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x3, 0xc0, 0x0, 0x3, 0xe0, 0x0, 0x3, 0xe0, 0x0, 0x6, 0xe0, 0x0, 0x6, 0xf0, 0x0, 0x4, 0x70, 0x0, 0xc, 0x70, 0x0, 0x8, 0x78, 0x0, 0x8, 0x38, 0x0, 0x1f, 0xf8, 0x0, 0x10, 0x3c, 0x0, 0x30, 0x3c, 0x0, 0x30, 0x1e, 0x0, 0x70, 0x1e, 0x0, 0xf8, 0x7f, 0x80} + +/* B (66) */ +#define NXFONT_METRICS_66 {2, 14, 17, 0, 11, 0} +#define NXFONT_BITMAP_66 {0xff, 0xc0, 0x3c, 0xf0, 0x3c, 0x78, 0x3c, 0x78, 0x3c, 0x78, 0x3c, 0x78, 0x3c, 0x70, 0x3c, 0xc0, 0x3f, 0xe0, 0x3c, 0x78, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x38, 0x3c, 0x78, 0xff, 0xe0} + +/* C (67) */ +#define NXFONT_METRICS_67 {2, 15, 17, 1, 11, 0} +#define NXFONT_BITMAP_67 {0x3, 0xf2, 0x1e, 0x3e, 0x3c, 0xe, 0x78, 0x6, 0x78, 0x2, 0xf0, 0x2, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0x78, 0x0, 0x78, 0x2, 0x3c, 0xe, 0x1f, 0x3c, 0x7, 0xf0} + +/* D (68) */ +#define NXFONT_METRICS_68 {2, 16, 17, 1, 11, 0} +#define NXFONT_BITMAP_68 {0xff, 0xe0, 0x3c, 0x78, 0x3c, 0x3c, 0x3c, 0x1e, 0x3c, 0x1e, 0x3c, 0xf, 0x3c, 0xf, 0x3c, 0xf, 0x3c, 0xf, 0x3c, 0xf, 0x3c, 0xf, 0x3c, 0xe, 0x3c, 0x1e, 0x3c, 0x1c, 0x3c, 0x3c, 0x3c, 0x78, 0xff, 0xe0} + +/* E (69) */ +#define NXFONT_METRICS_69 {2, 15, 17, 1, 11, 0} +#define NXFONT_BITMAP_69 {0xff, 0xfc, 0x3c, 0x1c, 0x3c, 0xc, 0x3c, 0x4, 0x3c, 0x4, 0x3c, 0x20, 0x3c, 0x20, 0x3c, 0x60, 0x3f, 0xe0, 0x3c, 0x60, 0x3c, 0x20, 0x3c, 0x20, 0x3c, 0x2, 0x3c, 0x2, 0x3c, 0x6, 0x3c, 0xe, 0xff, 0xfe} + +/* F (70) */ +#define NXFONT_METRICS_70 {2, 14, 17, 0, 11, 0} +#define NXFONT_BITMAP_70 {0xff, 0xfc, 0x3c, 0x1c, 0x3c, 0xc, 0x3c, 0x4, 0x3c, 0x4, 0x3c, 0x20, 0x3c, 0x20, 0x3c, 0x60, 0x3f, 0xe0, 0x3c, 0x60, 0x3c, 0x20, 0x3c, 0x20, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0xff, 0x0} + +/* G (71) */ +#define NXFONT_METRICS_71 {3, 17, 17, 1, 11, 0} +#define NXFONT_BITMAP_71 {0x3, 0xf2, 0x0, 0x1e, 0x3e, 0x0, 0x3c, 0xe, 0x0, 0x78, 0x6, 0x0, 0x78, 0x2, 0x0, 0xf0, 0x2, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x7f, 0x80, 0xf0, 0x1e, 0x0, 0xf0, 0x1e, 0x0, 0x78, 0x1e, 0x0, 0x78, 0x1e, 0x0, 0x38, 0x1e, 0x0, 0x1e, 0x1e, 0x0, 0x7, 0xf8, 0x0} + +/* H (72) */ +#define NXFONT_METRICS_72 {3, 18, 17, 0, 11, 0} +#define NXFONT_BITMAP_72 {0xff, 0x3f, 0xc0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0x3f, 0xff, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0xff, 0x3f, 0xc0} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 8, 17, 0, 11, 0} +#define NXFONT_BITMAP_73 {0xff, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0xff} + +/* J (74) */ +#define NXFONT_METRICS_74 {2, 11, 19, 0, 11, 0} +#define NXFONT_BITMAP_74 {0x1f, 0xe0, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0xe7, 0x80, 0xe7, 0x80, 0xe7, 0x0, 0xe7, 0x0, 0x3c, 0x0} + +/* K (75) */ +#define NXFONT_METRICS_75 {3, 18, 17, 0, 11, 0} +#define NXFONT_BITMAP_75 {0xff, 0x3f, 0x80, 0x3c, 0x1e, 0x0, 0x3c, 0x18, 0x0, 0x3c, 0x30, 0x0, 0x3c, 0x60, 0x0, 0x3c, 0xc0, 0x0, 0x3d, 0x80, 0x0, 0x3f, 0xc0, 0x0, 0x3f, 0xc0, 0x0, 0x3d, 0xe0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf8, 0x0, 0x3c, 0x7c, 0x0, 0x3c, 0x3e, 0x0, 0x3c, 0x1f, 0x0, 0x3c, 0xf, 0x80, 0xff, 0x1f, 0xc0} + +/* L (76) */ +#define NXFONT_METRICS_76 {2, 15, 17, 0, 11, 0} +#define NXFONT_BITMAP_76 {0xff, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x2, 0x3c, 0x6, 0x3c, 0xc, 0x3c, 0x1c, 0xff, 0xfc} + +/* M (77) */ +#define NXFONT_METRICS_77 {3, 21, 17, 1, 11, 0} +#define NXFONT_BITMAP_77 {0xfc, 0x1, 0xf8, 0x3c, 0x3, 0xe0, 0x3e, 0x3, 0xe0, 0x3e, 0x7, 0xe0, 0x2f, 0x5, 0xe0, 0x2f, 0xd, 0xe0, 0x27, 0x9, 0xe0, 0x27, 0x89, 0xe0, 0x27, 0x99, 0xe0, 0x23, 0x91, 0xe0, 0x23, 0xf1, 0xe0, 0x23, 0xf1, 0xe0, 0x21, 0xe1, 0xe0, 0x21, 0xe1, 0xe0, 0x20, 0xc1, 0xe0, 0x20, 0xc1, 0xe0, 0xf8, 0x7, 0xf8} + +/* N (78) */ +#define NXFONT_METRICS_78 {3, 17, 17, 0, 11, 0} +#define NXFONT_BITMAP_78 {0xf8, 0xf, 0x80, 0x7c, 0x7, 0x0, 0x3e, 0x2, 0x0, 0x3f, 0x2, 0x0, 0x3f, 0x82, 0x0, 0x2f, 0xc2, 0x0, 0x27, 0xe2, 0x0, 0x23, 0xe2, 0x0, 0x21, 0xf2, 0x0, 0x20, 0xfa, 0x0, 0x20, 0x7e, 0x0, 0x20, 0x3e, 0x0, 0x20, 0x1e, 0x0, 0x20, 0x1e, 0x0, 0x20, 0xe, 0x0, 0x60, 0x6, 0x0, 0xf8, 0x2, 0x0} + +/* O (79) */ +#define NXFONT_METRICS_79 {2, 16, 17, 1, 11, 0} +#define NXFONT_BITMAP_79 {0x7, 0xe0, 0x1c, 0x38, 0x38, 0x1c, 0x78, 0x1e, 0x70, 0xe, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0x70, 0xe, 0x78, 0x1e, 0x38, 0x1c, 0x1c, 0x38, 0x7, 0xe0} + +/* P (80) */ +#define NXFONT_METRICS_80 {2, 14, 17, 0, 11, 0} +#define NXFONT_BITMAP_80 {0xff, 0xe0, 0x3c, 0x78, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x78, 0x3f, 0xe0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0xff, 0x0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {3, 17, 22, 1, 11, 0} +#define NXFONT_BITMAP_81 {0x7, 0xe0, 0x0, 0x1c, 0x38, 0x0, 0x38, 0x1c, 0x0, 0x78, 0x1e, 0x0, 0x70, 0xe, 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xe, 0x0, 0x78, 0x1e, 0x0, 0x78, 0x1c, 0x0, 0x3c, 0x38, 0x0, 0x1f, 0xe0, 0x0, 0x7, 0xc0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xf0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x3f, 0x80} + +/* R (82) */ +#define NXFONT_METRICS_82 {2, 16, 17, 1, 11, 0} +#define NXFONT_BITMAP_82 {0xff, 0xe0, 0x3c, 0x78, 0x3c, 0x38, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x38, 0x3c, 0x70, 0x3f, 0xc0, 0x3d, 0xe0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0x78, 0x3c, 0x7c, 0x3c, 0x3c, 0x3c, 0x1e, 0xff, 0x1f} + +/* S (83) */ +#define NXFONT_METRICS_83 {2, 12, 17, 1, 11, 0} +#define NXFONT_BITMAP_83 {0x3f, 0xa0, 0x71, 0xe0, 0xe0, 0xe0, 0xe0, 0x60, 0xe0, 0x20, 0xf8, 0x0, 0x7e, 0x0, 0x7f, 0x80, 0x3f, 0xc0, 0xf, 0xe0, 0x7, 0xe0, 0x81, 0xf0, 0x80, 0xf0, 0xc0, 0xf0, 0xe0, 0xe0, 0xf9, 0xe0, 0xbf, 0x80} + +/* T (84) */ +#define NXFONT_METRICS_84 {2, 14, 17, 1, 11, 0} +#define NXFONT_BITMAP_84 {0xff, 0xfc, 0xe7, 0x9c, 0xc7, 0x8c, 0x87, 0x84, 0x87, 0x84, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x1f, 0xe0} + +/* U (85) */ +#define NXFONT_METRICS_85 {3, 17, 17, 0, 11, 0} +#define NXFONT_BITMAP_85 {0xff, 0xf, 0x80, 0x7e, 0x7, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x6, 0x0, 0x1e, 0x4, 0x0, 0x1f, 0xc, 0x0, 0x7, 0xf8, 0x0} + +/* V (86) */ +#define NXFONT_METRICS_86 {3, 17, 17, 0, 11, 0} +#define NXFONT_BITMAP_86 {0xff, 0x1f, 0x80, 0x3c, 0x6, 0x0, 0x3c, 0x4, 0x0, 0x1e, 0x4, 0x0, 0x1e, 0xc, 0x0, 0xf, 0x8, 0x0, 0xf, 0x18, 0x0, 0xf, 0x18, 0x0, 0x7, 0x90, 0x0, 0x7, 0xb0, 0x0, 0x3, 0xe0, 0x0, 0x3, 0xe0, 0x0, 0x3, 0xe0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {3, 24, 17, 0, 11, 0} +#define NXFONT_BITMAP_87 {0xff, 0x7f, 0x9f, 0x3c, 0x1e, 0x6, 0x3c, 0x1e, 0x4, 0x1e, 0xf, 0xc, 0x1e, 0x1f, 0x8, 0x1e, 0x1f, 0x18, 0xf, 0x17, 0x98, 0xf, 0x37, 0x90, 0xf, 0x27, 0xb0, 0x7, 0xe3, 0xb0, 0x7, 0xc3, 0xe0, 0x7, 0xc3, 0xe0, 0x3, 0xc1, 0xe0, 0x3, 0x81, 0xc0, 0x3, 0x81, 0xc0, 0x1, 0x0, 0x80, 0x1, 0x0, 0x80} + +/* X (88) */ +#define NXFONT_METRICS_88 {2, 16, 17, 1, 11, 0} +#define NXFONT_BITMAP_88 {0xff, 0x3f, 0x3e, 0xc, 0x1e, 0x8, 0x1f, 0x18, 0xf, 0x30, 0xf, 0xa0, 0x7, 0xe0, 0x3, 0xc0, 0x3, 0xe0, 0x3, 0xe0, 0x3, 0xf0, 0x6, 0xf0, 0xc, 0x78, 0x8, 0x7c, 0x18, 0x3c, 0x38, 0x3e, 0xfc, 0xff} + +/* Y (89) */ +#define NXFONT_METRICS_89 {3, 18, 17, 0, 11, 0} +#define NXFONT_BITMAP_89 {0xff, 0x8f, 0xc0, 0x3e, 0x3, 0x0, 0x1e, 0x2, 0x0, 0xf, 0x6, 0x0, 0xf, 0xc, 0x0, 0x7, 0x8c, 0x0, 0x7, 0x98, 0x0, 0x3, 0xd0, 0x0, 0x3, 0xf0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x7, 0xf8, 0x0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {2, 14, 17, 1, 11, 0} +#define NXFONT_BITMAP_90 {0xff, 0xf8, 0xe0, 0xf8, 0xc1, 0xf0, 0xc1, 0xf0, 0x83, 0xe0, 0x3, 0xc0, 0x7, 0xc0, 0x7, 0x80, 0xf, 0x80, 0xf, 0x0, 0x1e, 0x0, 0x3e, 0x4, 0x3c, 0x4, 0x7c, 0xc, 0x78, 0x1c, 0xf8, 0x3c, 0xff, 0xf8} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 5, 21, 1, 11, 0} +#define NXFONT_BITMAP_91 {0xf8, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xf8} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {1, 7, 17, 0, 11, 0} +#define NXFONT_BITMAP_92 {0xc0, 0xc0, 0x40, 0x60, 0x60, 0x20, 0x30, 0x30, 0x10, 0x18, 0x18, 0x8, 0xc, 0xc, 0x4, 0x6, 0x6} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 5, 21, 1, 11, 0} +#define NXFONT_BITMAP_93 {0xf8, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0xf8} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {1, 8, 10, 3, 11, 0} +#define NXFONT_BITMAP_94 {0x18, 0x18, 0x3c, 0x24, 0x66, 0x66, 0x66, 0xc3, 0xc3, 0x81} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {2, 12, 2, 0, 31, 0} +#define NXFONT_BITMAP_95 {0xff, 0xf0, 0xff, 0xf0} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 5, 4, 1, 11, 0} +#define NXFONT_BITMAP_96 {0xe0, 0x70, 0x30, 0x18} + +/* a (97) */ +#define NXFONT_METRICS_97 {2, 10, 12, 1, 16, 0} +#define NXFONT_BITMAP_97 {0x3e, 0x0, 0x77, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0x43, 0x80, 0xf, 0x80, 0x73, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0xc0, 0x71, 0x80} + +/* b (98) */ +#define NXFONT_METRICS_98 {2, 11, 17, 1, 11, 0} +#define NXFONT_BITMAP_98 {0xf0, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x77, 0x0, 0x7f, 0xc0, 0x71, 0xc0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x71, 0xc0, 0x7b, 0xc0, 0x67, 0x0} + +/* c (99) */ +#define NXFONT_METRICS_99 {2, 9, 12, 1, 16, 0} +#define NXFONT_BITMAP_99 {0x1e, 0x0, 0x73, 0x0, 0x73, 0x80, 0xe3, 0x80, 0xe1, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xf0, 0x0, 0x78, 0x80, 0x7f, 0x0, 0x1e, 0x0} + +/* d (100) */ +#define NXFONT_METRICS_100 {2, 12, 17, 1, 11, 0} +#define NXFONT_BITMAP_100 {0x1, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x1e, 0xe0, 0x7f, 0xe0, 0x71, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xe0, 0x71, 0xe0, 0x7e, 0xe0, 0x1c, 0x70} + +/* e (101) */ +#define NXFONT_METRICS_101 {2, 9, 12, 1, 16, 0} +#define NXFONT_BITMAP_101 {0x1e, 0x0, 0x73, 0x0, 0x73, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xff, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xf0, 0x0, 0x78, 0x80, 0x7f, 0x0, 0x1e, 0x0} + +/* f (102) */ +#define NXFONT_METRICS_102 {1, 8, 17, 1, 11, 0} +#define NXFONT_BITMAP_102 {0x1e, 0x33, 0x73, 0x70, 0x70, 0xfc, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* g (103) */ +#define NXFONT_METRICS_103 {2, 10, 17, 1, 16, 0} +#define NXFONT_BITMAP_103 {0x3e, 0xc0, 0x77, 0xc0, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x73, 0x0, 0x3e, 0x0, 0x60, 0x0, 0xe0, 0x0, 0xff, 0x80, 0xff, 0xc0, 0x7f, 0xc0, 0xc1, 0xc0, 0xc0, 0xc0, 0xe1, 0x80, 0x7f, 0x0} + +/* h (104) */ +#define NXFONT_METRICS_104 {2, 12, 17, 1, 11, 0} +#define NXFONT_BITMAP_104 {0xf0, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x73, 0xc0, 0x7f, 0xe0, 0x78, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0xf9, 0xf0} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 5, 17, 1, 11, 0} +#define NXFONT_BITMAP_105 {0x70, 0x70, 0x70, 0x0, 0x0, 0xf0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* j (106) - NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_106 {1, 7, 22, 0, 11, 0} +#define NXFONT_BITMAP_106 {0xe, 0xe, 0xe, 0x0, 0x0, 0x1e, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xce, 0xce, 0xcc, 0x78} + +/* k (107) */ +#define NXFONT_METRICS_107 {2, 13, 17, 1, 11, 0} +#define NXFONT_BITMAP_107 {0xf0, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x73, 0xf0, 0x70, 0xc0, 0x71, 0x80, 0x73, 0x0, 0x76, 0x0, 0x7e, 0x0, 0x7f, 0x0, 0x77, 0x80, 0x73, 0xc0, 0x71, 0xe0, 0x70, 0xf0, 0xfb, 0xf8} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 5, 17, 1, 11, 0} +#define NXFONT_BITMAP_108 {0xf0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* m (109) */ +#define NXFONT_METRICS_109 {3, 19, 12, 1, 16, 0} +#define NXFONT_BITMAP_109 {0xf3, 0xc7, 0x80, 0x77, 0xdf, 0xc0, 0x78, 0xf1, 0xc0, 0x70, 0xe1, 0xc0, 0x70, 0xe1, 0xc0, 0x70, 0xe1, 0xc0, 0x70, 0xe1, 0xc0, 0x70, 0xe1, 0xc0, 0x70, 0xe1, 0xc0, 0x70, 0xe1, 0xc0, 0x70, 0xe1, 0xc0, 0xf9, 0xf3, 0xe0} + +/* n (110) */ +#define NXFONT_METRICS_110 {2, 12, 12, 1, 16, 0} +#define NXFONT_BITMAP_110 {0xf3, 0xc0, 0x77, 0xe0, 0x78, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0xf9, 0xf0} + +/* o (111) */ +#define NXFONT_METRICS_111 {2, 11, 12, 1, 16, 0} +#define NXFONT_BITMAP_111 {0x1f, 0x0, 0x71, 0xc0, 0x71, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x71, 0xc0, 0x71, 0xc0, 0x1f, 0x0} + +/* p (112) */ +#define NXFONT_METRICS_112 {2, 12, 17, 1, 16, 0} +#define NXFONT_BITMAP_112 {0xe3, 0xc0, 0x77, 0xe0, 0x78, 0xe0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x78, 0xe0, 0x77, 0xe0, 0x73, 0x80, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0xfc, 0x0} + +/* q (113) */ +#define NXFONT_METRICS_113 {2, 12, 17, 1, 16, 0} +#define NXFONT_BITMAP_113 {0xe, 0x60, 0x3f, 0xe0, 0x71, 0xe0, 0x70, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x71, 0xe0, 0x7e, 0xe0, 0x1c, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x1, 0xf0} + +/* r (114) */ +#define NXFONT_METRICS_114 {2, 9, 12, 1, 16, 0} +#define NXFONT_BITMAP_114 {0xef, 0x0, 0x7f, 0x80, 0x73, 0x80, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0xf8, 0x0} + +/* s (115) */ +#define NXFONT_METRICS_115 {1, 8, 12, 1, 16, 0} +#define NXFONT_BITMAP_115 {0x3e, 0x66, 0xe2, 0xe0, 0xf8, 0x7c, 0x3e, 0x1f, 0x87, 0x87, 0xc6, 0xfc} + +/* t (116) */ +#define NXFONT_METRICS_116 {1, 8, 16, 0, 12, 0} +#define NXFONT_BITMAP_116 {0x8, 0x18, 0x38, 0x78, 0xff, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x3e, 0x1c} + +/* u (117) */ +#define NXFONT_METRICS_117 {2, 12, 12, 1, 16, 0} +#define NXFONT_BITMAP_117 {0xf1, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x71, 0xe0, 0x7e, 0xf0, 0x3c, 0xe0} + +/* v (118) */ +#define NXFONT_METRICS_118 {2, 12, 12, 0, 16, 0} +#define NXFONT_BITMAP_118 {0xfc, 0xf0, 0x70, 0x60, 0x78, 0x40, 0x38, 0xc0, 0x38, 0x80, 0x1c, 0x80, 0x1d, 0x80, 0x1f, 0x0, 0xf, 0x0, 0xf, 0x0, 0x6, 0x0, 0x6, 0x0} + +/* w (119) */ +#define NXFONT_METRICS_119 {3, 17, 12, 0, 16, 0} +#define NXFONT_BITMAP_119 {0xfd, 0xf7, 0x80, 0x78, 0xe3, 0x0, 0x38, 0xe3, 0x0, 0x38, 0xe2, 0x0, 0x3c, 0xe6, 0x0, 0x1d, 0x76, 0x0, 0x1d, 0x74, 0x0, 0x1f, 0x3c, 0x0, 0xe, 0x38, 0x0, 0xe, 0x38, 0x0, 0x4, 0x10, 0x0, 0x4, 0x10, 0x0} + +/* x (120) */ +#define NXFONT_METRICS_120 {2, 12, 12, 0, 16, 0} +#define NXFONT_BITMAP_120 {0xfc, 0xf0, 0x78, 0x60, 0x3c, 0xc0, 0x1d, 0x80, 0x1f, 0x0, 0xf, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x1b, 0xc0, 0x31, 0xc0, 0x61, 0xe0, 0xf3, 0xf0} + +/* y (121) */ +#define NXFONT_METRICS_121 {2, 12, 17, 0, 16, 0} +#define NXFONT_BITMAP_121 {0xfd, 0xf0, 0x78, 0x60, 0x38, 0x40, 0x38, 0xc0, 0x3c, 0x80, 0x1c, 0x80, 0x1d, 0x80, 0x1f, 0x0, 0xf, 0x0, 0xf, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x64, 0x0, 0xec, 0x0, 0xf8, 0x0, 0x70, 0x0} + +/* z (122) */ +#define NXFONT_METRICS_122 {2, 9, 12, 1, 16, 0} +#define NXFONT_BITMAP_122 {0xff, 0x80, 0xc7, 0x0, 0x8f, 0x0, 0x8e, 0x0, 0x1e, 0x0, 0x1c, 0x0, 0x3c, 0x0, 0x38, 0x0, 0x78, 0x80, 0x71, 0x80, 0xf1, 0x80, 0xff, 0x80} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {1, 7, 21, 1, 11, 0} +#define NXFONT_BITMAP_123 {0xe, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0xe} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 2, 22, 2, 11, 0} +#define NXFONT_BITMAP_124 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 7, 21, 1, 11, 0} +#define NXFONT_BITMAP_125 {0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xc, 0x6, 0xc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {2, 12, 6, 0, 16, 0} +#define NXFONT_BITMAP_126 {0x18, 0x0, 0x7e, 0x10, 0xff, 0x10, 0x8f, 0xf0, 0x87, 0xe0, 0x1, 0x80} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 4, 17, 2, 16, 0} +#define NXFONT_BITMAP_161 {0x60, 0xf0, 0xf0, 0x60, 0x0, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x60} + +/* cent (162) */ +#define NXFONT_METRICS_162 {2, 10, 18, 1, 13, 0} +#define NXFONT_BITMAP_162 {0x0, 0x80, 0x1, 0x80, 0x1, 0x0, 0x1f, 0x80, 0x73, 0xc0, 0x73, 0xc0, 0xe6, 0x80, 0xe4, 0x0, 0xe4, 0x0, 0xec, 0x0, 0xe8, 0x0, 0xf8, 0x0, 0x78, 0x80, 0x7f, 0x80, 0x3e, 0x0, 0x30, 0x0, 0x60, 0x0, 0x60, 0x0} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {2, 11, 17, 0, 11, 0} +#define NXFONT_BITMAP_163 {0xf, 0xc0, 0x1e, 0x60, 0x3c, 0xe0, 0x3c, 0xe0, 0x3c, 0x40, 0x1c, 0x0, 0x1c, 0x0, 0xff, 0x80, 0xff, 0x80, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0xc, 0x20, 0x7c, 0x60, 0xcf, 0xe0, 0xff, 0xe0, 0x73, 0xc0} + +/* currency (164) */ +#define NXFONT_METRICS_164 {2, 11, 12, 0, 13, 0} +#define NXFONT_BITMAP_164 {0xc0, 0x60, 0xee, 0xe0, 0x7f, 0xc0, 0x3b, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x71, 0xc0, 0x3b, 0x80, 0x7f, 0xc0, 0xee, 0xe0, 0xc0, 0x60} + +/* yen (165) */ +#define NXFONT_METRICS_165 {2, 14, 17, 0, 11, 0} +#define NXFONT_BITMAP_165 {0xfe, 0x7c, 0x38, 0x30, 0x3c, 0x20, 0x1c, 0x60, 0x1e, 0x40, 0xe, 0xc0, 0xf, 0x80, 0x7, 0x80, 0x7, 0x0, 0x1f, 0xc0, 0x7, 0x0, 0x1f, 0xc0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x1f, 0xc0} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 2, 22, 2, 11, 0} +#define NXFONT_BITMAP_166 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* section (167) */ +#define NXFONT_METRICS_167 {1, 7, 20, 2, 11, 0} +#define NXFONT_BITMAP_167 {0x3c, 0x6e, 0xce, 0xc6, 0xe0, 0x70, 0x78, 0x5c, 0x8e, 0x86, 0xc2, 0xe2, 0x74, 0x3c, 0x1c, 0xe, 0xc6, 0xe6, 0xec, 0x78} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 6, 2, 1, 12, 0} +#define NXFONT_BITMAP_168 {0xcc, 0xcc} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {3, 17, 17, 1, 11, 0} +#define NXFONT_BITMAP_169 {0x3, 0xe0, 0x0, 0xf, 0xf8, 0x0, 0x3c, 0x1e, 0x0, 0x30, 0x6, 0x0, 0x61, 0xf3, 0x0, 0x63, 0x33, 0x0, 0xc6, 0x11, 0x80, 0xc6, 0x1, 0x80, 0xc6, 0x1, 0x80, 0xc6, 0x1, 0x80, 0xc6, 0x1, 0x80, 0x63, 0x33, 0x0, 0x61, 0xe3, 0x0, 0x30, 0x6, 0x0, 0x3c, 0x1e, 0x0, 0xf, 0xf8, 0x0, 0x3, 0xe0, 0x0} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {1, 7, 10, 0, 11, 0} +#define NXFONT_BITMAP_170 {0x78, 0xdc, 0xc, 0x7c, 0xec, 0xcc, 0x7e, 0x0, 0xfe, 0xfe} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {2, 11, 10, 1, 17, 0} +#define NXFONT_BITMAP_171 {0xc, 0x60, 0x18, 0xc0, 0x31, 0x80, 0x73, 0x80, 0xe7, 0x0, 0xe7, 0x0, 0x73, 0x80, 0x31, 0x80, 0x18, 0xc0, 0xc, 0x60} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {2, 11, 7, 2, 19, 0} +#define NXFONT_BITMAP_172 {0xff, 0xe0, 0xff, 0xe0, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 6, 3, 1, 20, 0} +#define NXFONT_BITMAP_173 {0xfc, 0xfc, 0xfc} + +/* registered (174) */ +#define NXFONT_METRICS_174 {3, 17, 17, 1, 11, 0} +#define NXFONT_BITMAP_174 {0x3, 0xe0, 0x0, 0xf, 0xf8, 0x0, 0x3c, 0x1e, 0x0, 0x30, 0x6, 0x0, 0x67, 0xe3, 0x0, 0x63, 0x33, 0x0, 0xc3, 0x31, 0x80, 0xc3, 0x31, 0x80, 0xc3, 0xe1, 0x80, 0xc3, 0x61, 0x80, 0xc3, 0x31, 0x80, 0x63, 0x33, 0x0, 0x67, 0xbb, 0x0, 0x30, 0x6, 0x0, 0x3c, 0x1e, 0x0, 0xf, 0xf8, 0x0, 0x3, 0xe0, 0x0} + +/* macron (175) */ +#define NXFONT_METRICS_175 {1, 6, 1, 1, 13, 0} +#define NXFONT_BITMAP_175 {0xfc} + +/* degree (176) */ +#define NXFONT_METRICS_176 {1, 8, 7, 0, 11, 0} +#define NXFONT_BITMAP_176 {0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0x66, 0x3c} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {2, 12, 13, 1, 15, 0} +#define NXFONT_BITMAP_177 {0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x0, 0x0, 0xff, 0xf0, 0xff, 0xf0} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {1, 6, 10, 0, 11, 0} +#define NXFONT_BITMAP_178 {0x38, 0x7c, 0x8c, 0xc, 0x18, 0x10, 0x20, 0x40, 0xfc, 0xfc} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {1, 6, 10, 0, 11, 0} +#define NXFONT_BITMAP_179 {0x38, 0x7c, 0x8c, 0xc, 0x38, 0x1c, 0xc, 0x8c, 0xf8, 0x70} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 5, 4, 2, 11, 0} +#define NXFONT_BITMAP_180 {0x38, 0x70, 0x60, 0xc0} + +/* mu (181) */ +#define NXFONT_METRICS_181 {2, 12, 17, 1, 16, 0} +#define NXFONT_BITMAP_181 {0xf1, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x71, 0xe0, 0x7e, 0xf0, 0x6c, 0xe0, 0x60, 0x0, 0x60, 0x0, 0xe0, 0x0, 0xf0, 0x0, 0x60, 0x0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {2, 11, 22, 1, 11, 0} +#define NXFONT_BITMAP_182 {0x1f, 0xe0, 0x7f, 0xe0, 0x7e, 0x40, 0xfe, 0x40, 0xfe, 0x40, 0xfe, 0x40, 0xfe, 0x40, 0xfe, 0x40, 0xfe, 0x40, 0x7e, 0x40, 0x7e, 0x40, 0x1e, 0x40, 0x2, 0x40, 0x2, 0x40, 0x2, 0x40, 0x2, 0x40, 0x2, 0x40, 0x2, 0x40, 0x2, 0x40, 0x2, 0x40, 0x2, 0x40, 0x2, 0x40} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 3, 3, 1, 19, 0} +#define NXFONT_BITMAP_183 {0xe0, 0xe0, 0xe0} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 6, 6, 1, 28, 0} +#define NXFONT_BITMAP_184 {0x10, 0x30, 0x38, 0xc, 0x8c, 0x78} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 6, 10, 0, 11, 0} +#define NXFONT_BITMAP_185 {0x30, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {1, 7, 10, 0, 11, 0} +#define NXFONT_BITMAP_186 {0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x0, 0xfe, 0xfe} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {2, 11, 10, 1, 17, 0} +#define NXFONT_BITMAP_187 {0xc6, 0x0, 0x63, 0x0, 0x31, 0x80, 0x39, 0xc0, 0x1c, 0xe0, 0x1c, 0xe0, 0x39, 0xc0, 0x33, 0x80, 0x63, 0x0, 0xc6, 0x0} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {3, 17, 17, 0, 11, 0} +#define NXFONT_BITMAP_188 {0x30, 0x4, 0x0, 0xf0, 0xc, 0x0, 0x30, 0x18, 0x0, 0x30, 0x18, 0x0, 0x30, 0x30, 0x0, 0x30, 0x20, 0x0, 0x30, 0x60, 0x0, 0x30, 0x42, 0x0, 0x30, 0xc6, 0x0, 0xfc, 0x8e, 0x0, 0x1, 0x8e, 0x0, 0x1, 0x16, 0x0, 0x3, 0x36, 0x0, 0x6, 0x26, 0x0, 0x6, 0x7f, 0x80, 0xc, 0x6, 0x0, 0x8, 0x6, 0x0} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {3, 17, 17, 0, 11, 0} +#define NXFONT_BITMAP_189 {0x30, 0x4, 0x0, 0xf0, 0xc, 0x0, 0x30, 0x18, 0x0, 0x30, 0x18, 0x0, 0x30, 0x30, 0x0, 0x30, 0x20, 0x0, 0x30, 0x60, 0x0, 0x30, 0x47, 0x0, 0x30, 0xcf, 0x80, 0xfc, 0x91, 0x80, 0x1, 0x81, 0x80, 0x1, 0x3, 0x0, 0x3, 0x2, 0x0, 0x6, 0x4, 0x0, 0x6, 0x8, 0x0, 0xc, 0x1f, 0x80, 0x8, 0x1f, 0x80} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {3, 17, 17, 1, 11, 0} +#define NXFONT_BITMAP_190 {0x38, 0x4, 0x0, 0x7c, 0xc, 0x0, 0x8c, 0x18, 0x0, 0xc, 0x18, 0x0, 0x38, 0x30, 0x0, 0x1c, 0x20, 0x0, 0xc, 0x60, 0x0, 0x8c, 0x42, 0x0, 0xf8, 0xc6, 0x0, 0x71, 0xe, 0x0, 0x3, 0xe, 0x0, 0x2, 0x16, 0x0, 0x6, 0x36, 0x0, 0xc, 0x26, 0x0, 0xc, 0x7f, 0x80, 0x18, 0x6, 0x0, 0x10, 0x6, 0x0} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {2, 9, 17, 1, 16, 0} +#define NXFONT_BITMAP_191 {0xc, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x78, 0x0, 0xf0, 0x0, 0xf1, 0x0, 0xf3, 0x80, 0xf3, 0x80, 0x7b, 0x0, 0x3e, 0x0} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {3, 17, 22, 0, 6, 0} +#define NXFONT_BITMAP_192 {0x3, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x0, 0xc0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x3, 0xc0, 0x0, 0x3, 0xe0, 0x0, 0x3, 0xe0, 0x0, 0x6, 0xe0, 0x0, 0x6, 0xf0, 0x0, 0x4, 0x70, 0x0, 0xc, 0x70, 0x0, 0x8, 0x78, 0x0, 0x8, 0x38, 0x0, 0x1f, 0xf8, 0x0, 0x10, 0x3c, 0x0, 0x30, 0x3c, 0x0, 0x30, 0x1e, 0x0, 0x70, 0x1e, 0x0, 0xf8, 0x7f, 0x80} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {3, 17, 22, 0, 6, 0} +#define NXFONT_BITMAP_193 {0x0, 0xe0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x3, 0xc0, 0x0, 0x3, 0xe0, 0x0, 0x3, 0xe0, 0x0, 0x6, 0xe0, 0x0, 0x6, 0xf0, 0x0, 0x4, 0x70, 0x0, 0xc, 0x70, 0x0, 0x8, 0x78, 0x0, 0x8, 0x38, 0x0, 0x1f, 0xf8, 0x0, 0x10, 0x3c, 0x0, 0x30, 0x3c, 0x0, 0x30, 0x1e, 0x0, 0x70, 0x1e, 0x0, 0xf8, 0x7f, 0x80} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {3, 17, 22, 0, 6, 0} +#define NXFONT_BITMAP_194 {0x1, 0x80, 0x0, 0x3, 0xc0, 0x0, 0x6, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x3, 0xc0, 0x0, 0x3, 0xe0, 0x0, 0x3, 0xe0, 0x0, 0x6, 0xe0, 0x0, 0x6, 0xf0, 0x0, 0x4, 0x70, 0x0, 0xc, 0x70, 0x0, 0x8, 0x78, 0x0, 0x8, 0x38, 0x0, 0x1f, 0xf8, 0x0, 0x10, 0x3c, 0x0, 0x30, 0x3c, 0x0, 0x30, 0x1e, 0x0, 0x70, 0x1e, 0x0, 0xf8, 0x7f, 0x80} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {3, 17, 21, 0, 7, 0} +#define NXFONT_BITMAP_195 {0x3, 0x10, 0x0, 0x7, 0xe0, 0x0, 0x8, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x3, 0xc0, 0x0, 0x3, 0xe0, 0x0, 0x3, 0xe0, 0x0, 0x6, 0xe0, 0x0, 0x6, 0xf0, 0x0, 0x4, 0x70, 0x0, 0xc, 0x70, 0x0, 0x8, 0x78, 0x0, 0x8, 0x38, 0x0, 0x1f, 0xf8, 0x0, 0x10, 0x3c, 0x0, 0x30, 0x3c, 0x0, 0x30, 0x1e, 0x0, 0x70, 0x1e, 0x0, 0xf8, 0x7f, 0x80} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {3, 17, 21, 0, 7, 0} +#define NXFONT_BITMAP_196 {0x6, 0x60, 0x0, 0x6, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x3, 0xc0, 0x0, 0x3, 0xe0, 0x0, 0x3, 0xe0, 0x0, 0x6, 0xe0, 0x0, 0x6, 0xf0, 0x0, 0x4, 0x70, 0x0, 0xc, 0x70, 0x0, 0x8, 0x78, 0x0, 0x8, 0x38, 0x0, 0x1f, 0xf8, 0x0, 0x10, 0x3c, 0x0, 0x30, 0x3c, 0x0, 0x30, 0x1e, 0x0, 0x70, 0x1e, 0x0, 0xf8, 0x7f, 0x80} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {3, 17, 23, 0, 5, 0} +#define NXFONT_BITMAP_197 {0x1, 0x80, 0x0, 0x3, 0xc0, 0x0, 0x6, 0x60, 0x0, 0x6, 0x60, 0x0, 0x3, 0xc0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x3, 0xc0, 0x0, 0x3, 0xe0, 0x0, 0x3, 0xe0, 0x0, 0x6, 0xe0, 0x0, 0x6, 0xf0, 0x0, 0x4, 0x70, 0x0, 0xc, 0x70, 0x0, 0x8, 0x78, 0x0, 0x8, 0x38, 0x0, 0x1f, 0xf8, 0x0, 0x10, 0x3c, 0x0, 0x30, 0x3c, 0x0, 0x30, 0x1e, 0x0, 0x70, 0x1e, 0x0, 0xf8, 0x7f, 0x80} + +/* AE (198) */ +#define NXFONT_METRICS_198 {3, 23, 17, 0, 11, 0} +#define NXFONT_BITMAP_198 {0x1, 0xff, 0xfc, 0x0, 0x7c, 0x1c, 0x0, 0xfc, 0xc, 0x0, 0xbc, 0x4, 0x1, 0xbc, 0x4, 0x1, 0x3c, 0x20, 0x3, 0x3c, 0x20, 0x2, 0x3c, 0x60, 0x6, 0x3f, 0xe0, 0x7, 0xfc, 0x60, 0xc, 0x3c, 0x20, 0x8, 0x3c, 0x20, 0x18, 0x3c, 0x2, 0x10, 0x3c, 0x2, 0x30, 0x3c, 0x6, 0x70, 0x3c, 0xe, 0xf8, 0xff, 0xfe} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {2, 15, 23, 1, 11, 0} +#define NXFONT_BITMAP_199 {0x3, 0xf2, 0x1e, 0x3e, 0x3c, 0xe, 0x78, 0x6, 0x78, 0x2, 0xf0, 0x2, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0x78, 0x0, 0x78, 0x2, 0x3c, 0xe, 0x1f, 0x3c, 0x7, 0xf0, 0x1, 0x0, 0x3, 0x0, 0x3, 0x80, 0x0, 0xc0, 0x8, 0xc0, 0x7, 0x80} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {2, 15, 22, 1, 6, 0} +#define NXFONT_BITMAP_200 {0x7, 0x0, 0x3, 0x80, 0x1, 0x80, 0x0, 0xc0, 0x0, 0x0, 0xff, 0xfc, 0x3c, 0x1c, 0x3c, 0xc, 0x3c, 0x4, 0x3c, 0x4, 0x3c, 0x20, 0x3c, 0x20, 0x3c, 0x60, 0x3f, 0xe0, 0x3c, 0x60, 0x3c, 0x20, 0x3c, 0x20, 0x3c, 0x2, 0x3c, 0x2, 0x3c, 0x6, 0x3c, 0xe, 0xff, 0xfe} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {2, 15, 22, 1, 6, 0} +#define NXFONT_BITMAP_201 {0x1, 0xc0, 0x3, 0x80, 0x3, 0x0, 0x6, 0x0, 0x0, 0x0, 0xff, 0xfc, 0x3c, 0x1c, 0x3c, 0xc, 0x3c, 0x4, 0x3c, 0x4, 0x3c, 0x20, 0x3c, 0x20, 0x3c, 0x60, 0x3f, 0xe0, 0x3c, 0x60, 0x3c, 0x20, 0x3c, 0x20, 0x3c, 0x2, 0x3c, 0x2, 0x3c, 0x6, 0x3c, 0xe, 0xff, 0xfe} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {2, 15, 22, 1, 6, 0} +#define NXFONT_BITMAP_202 {0x3, 0x0, 0x7, 0x80, 0xc, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfc, 0x3c, 0x1c, 0x3c, 0xc, 0x3c, 0x4, 0x3c, 0x4, 0x3c, 0x20, 0x3c, 0x20, 0x3c, 0x60, 0x3f, 0xe0, 0x3c, 0x60, 0x3c, 0x20, 0x3c, 0x20, 0x3c, 0x2, 0x3c, 0x2, 0x3c, 0x6, 0x3c, 0xe, 0xff, 0xfe} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {2, 15, 21, 1, 7, 0} +#define NXFONT_BITMAP_203 {0xc, 0xc0, 0xc, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfc, 0x3c, 0x1c, 0x3c, 0xc, 0x3c, 0x4, 0x3c, 0x4, 0x3c, 0x20, 0x3c, 0x20, 0x3c, 0x60, 0x3f, 0xe0, 0x3c, 0x60, 0x3c, 0x20, 0x3c, 0x20, 0x3c, 0x2, 0x3c, 0x2, 0x3c, 0x6, 0x3c, 0xe, 0xff, 0xfe} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {1, 8, 22, 0, 6, 0} +#define NXFONT_BITMAP_204 {0x70, 0x38, 0x18, 0xc, 0x0, 0xff, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0xff} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 8, 22, 0, 6, 0} +#define NXFONT_BITMAP_205 {0xe, 0x1c, 0x18, 0x30, 0x0, 0xff, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0xff} + +/* Icircumflex (206) */ +#define NXFONT_METRICS_206 {1, 8, 22, 0, 6, 0} +#define NXFONT_BITMAP_206 {0x18, 0x3c, 0x66, 0x0, 0x0, 0xff, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0xff} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {1, 8, 21, 0, 7, 0} +#define NXFONT_BITMAP_207 {0x66, 0x66, 0x0, 0x0, 0xff, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0xff} + +/* Eth (208) */ +#define NXFONT_METRICS_208 {2, 16, 17, 1, 11, 0} +#define NXFONT_BITMAP_208 {0xff, 0xe0, 0x3c, 0x78, 0x3c, 0x3c, 0x3c, 0x1e, 0x3c, 0x1e, 0x3c, 0xf, 0x3c, 0xf, 0xff, 0x8f, 0xff, 0x8f, 0x3c, 0xf, 0x3c, 0xf, 0x3c, 0xe, 0x3c, 0x1e, 0x3c, 0x1c, 0x3c, 0x3c, 0x3c, 0x78, 0xff, 0xe0} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {3, 17, 22, 0, 6, 0} +#define NXFONT_BITMAP_209 {0x1, 0x88, 0x0, 0x3, 0xf0, 0x0, 0x4, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0xf, 0x80, 0x7c, 0x7, 0x0, 0x3e, 0x2, 0x0, 0x3f, 0x2, 0x0, 0x3f, 0x82, 0x0, 0x2f, 0xc2, 0x0, 0x27, 0xe2, 0x0, 0x23, 0xe2, 0x0, 0x21, 0xf2, 0x0, 0x20, 0xfa, 0x0, 0x20, 0x7e, 0x0, 0x20, 0x3e, 0x0, 0x20, 0x1e, 0x0, 0x20, 0xe, 0x0, 0x20, 0xe, 0x0, 0x60, 0x6, 0x0, 0xf8, 0x2, 0x0} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {2, 16, 22, 1, 6, 0} +#define NXFONT_BITMAP_210 {0x7, 0x0, 0x3, 0x80, 0x1, 0x80, 0x0, 0xc0, 0x0, 0x0, 0x7, 0xe0, 0x1e, 0x78, 0x3c, 0x3c, 0x78, 0x1e, 0x78, 0x1e, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0x78, 0x1e, 0x78, 0x1e, 0x3c, 0x3c, 0x1e, 0x78, 0x7, 0xe0} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {2, 16, 22, 1, 6, 0} +#define NXFONT_BITMAP_211 {0x0, 0x70, 0x0, 0xe0, 0x0, 0xc0, 0x1, 0x80, 0x0, 0x0, 0x7, 0xe0, 0x1e, 0x78, 0x3c, 0x3c, 0x78, 0x1e, 0x78, 0x1e, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0x78, 0x1e, 0x78, 0x1e, 0x3c, 0x3c, 0x1e, 0x78, 0x7, 0xe0} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {2, 16, 22, 1, 6, 0} +#define NXFONT_BITMAP_212 {0x1, 0x80, 0x3, 0xc0, 0x6, 0x60, 0x0, 0x0, 0x0, 0x0, 0x7, 0xe0, 0x1e, 0x78, 0x3c, 0x3c, 0x78, 0x1e, 0x78, 0x1e, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0x78, 0x1e, 0x78, 0x1e, 0x3c, 0x3c, 0x1e, 0x78, 0x7, 0xe0} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {2, 16, 22, 1, 6, 0} +#define NXFONT_BITMAP_213 {0x3, 0x10, 0x7, 0xe0, 0x8, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xe0, 0x1e, 0x78, 0x3c, 0x3c, 0x78, 0x1e, 0x78, 0x1e, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0x78, 0x1e, 0x78, 0x1e, 0x3c, 0x3c, 0x1e, 0x78, 0x7, 0xe0} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {2, 16, 21, 1, 7, 0} +#define NXFONT_BITMAP_214 {0xc, 0x60, 0xc, 0x60, 0x0, 0x0, 0x0, 0x0, 0x7, 0xe0, 0x1e, 0x78, 0x3c, 0x3c, 0x78, 0x1e, 0x78, 0x1e, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0x78, 0x1e, 0x78, 0x1e, 0x3c, 0x3c, 0x1e, 0x78, 0x7, 0xe0} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {2, 12, 12, 1, 16, 0} +#define NXFONT_BITMAP_215 {0xc0, 0x30, 0xe0, 0x70, 0x70, 0xe0, 0x39, 0xc0, 0x1f, 0x80, 0xf, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x39, 0xc0, 0x70, 0xe0, 0xe0, 0x70, 0xc0, 0x30} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {2, 16, 19, 1, 10, 0} +#define NXFONT_BITMAP_216 {0x0, 0x4, 0x7, 0xec, 0x1e, 0x78, 0x38, 0x1c, 0x78, 0x3e, 0x78, 0x3e, 0xf0, 0x6f, 0xf0, 0xcf, 0xf0, 0xcf, 0xf1, 0x8f, 0xf3, 0xf, 0xf3, 0xf, 0xf6, 0xf, 0x7c, 0x1e, 0x7c, 0x1e, 0x38, 0x1c, 0x3e, 0x78, 0x37, 0xe0, 0x60, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {3, 17, 22, 0, 6, 0} +#define NXFONT_BITMAP_217 {0x3, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x0, 0xc0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf, 0x80, 0x3e, 0x6, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x6, 0x0, 0x1e, 0x4, 0x0, 0x1f, 0x1c, 0x0, 0x7, 0xf8, 0x0} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {3, 17, 22, 0, 6, 0} +#define NXFONT_BITMAP_218 {0x0, 0x38, 0x0, 0x0, 0x70, 0x0, 0x0, 0x60, 0x0, 0x0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf, 0x80, 0x3e, 0x6, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x6, 0x0, 0x1e, 0x4, 0x0, 0x1f, 0x1c, 0x0, 0x7, 0xf8, 0x0} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {3, 17, 22, 0, 6, 0} +#define NXFONT_BITMAP_219 {0x0, 0x60, 0x0, 0x0, 0xf0, 0x0, 0x1, 0x98, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf, 0x80, 0x3e, 0x6, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x6, 0x0, 0x1e, 0x4, 0x0, 0x1f, 0x1c, 0x0, 0x7, 0xf8, 0x0} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {3, 17, 21, 0, 7, 0} +#define NXFONT_BITMAP_220 {0x3, 0x18, 0x0, 0x3, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf, 0x80, 0x3e, 0x6, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x2, 0x0, 0x3c, 0x6, 0x0, 0x1e, 0x4, 0x0, 0x1f, 0x1c, 0x0, 0x7, 0xf8, 0x0} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {3, 18, 23, 0, 5, 0} +#define NXFONT_BITMAP_221 {0x0, 0xe, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x18, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x8f, 0xc0, 0x3e, 0x3, 0x0, 0x1e, 0x2, 0x0, 0xf, 0x6, 0x0, 0xf, 0xc, 0x0, 0x7, 0x8c, 0x0, 0x7, 0x98, 0x0, 0x3, 0xd0, 0x0, 0x3, 0xf0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x7, 0xf8, 0x0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {2, 14, 17, 0, 11, 0} +#define NXFONT_BITMAP_222 {0xff, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3f, 0xe0, 0x3c, 0x78, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x78, 0x3f, 0xe0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0xff, 0x0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {2, 11, 17, 1, 11, 0} +#define NXFONT_BITMAP_223 {0x1f, 0x0, 0x39, 0x80, 0x71, 0xc0, 0x71, 0xc0, 0x71, 0xc0, 0x71, 0xc0, 0x73, 0x80, 0x77, 0x0, 0x73, 0x80, 0x71, 0xc0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xc0, 0xf3, 0x80} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_224 {0x38, 0x0, 0x1c, 0x0, 0xc, 0x0, 0x6, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x77, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0x43, 0x80, 0xf, 0x80, 0x73, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0xc0, 0x71, 0x80} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_225 {0xe, 0x0, 0x1c, 0x0, 0x18, 0x0, 0x30, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x77, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0x43, 0x80, 0xf, 0x80, 0x73, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0xc0, 0x71, 0x80} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_226 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x77, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0x43, 0x80, 0xf, 0x80, 0x73, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0xc0, 0x71, 0x80} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_227 {0x18, 0x80, 0x3f, 0x0, 0x46, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x77, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0x43, 0x80, 0xf, 0x80, 0x73, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0xc0, 0x71, 0x80} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {2, 10, 16, 1, 12, 0} +#define NXFONT_BITMAP_228 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x77, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0x43, 0x80, 0xf, 0x80, 0x73, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0xc0, 0x71, 0x80} + +/* aring (229) */ +#define NXFONT_METRICS_229 {2, 10, 18, 1, 10, 0} +#define NXFONT_BITMAP_229 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x33, 0x0, 0x1e, 0x0, 0xc, 0x0, 0x3e, 0x0, 0x77, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0x43, 0x80, 0xf, 0x80, 0x73, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe7, 0x80, 0xff, 0xc0, 0x71, 0x80} + +/* ae (230) */ +#define NXFONT_METRICS_230 {2, 15, 12, 1, 16, 0} +#define NXFONT_BITMAP_230 {0x3e, 0x78, 0x77, 0xcc, 0xe3, 0xce, 0x63, 0x8e, 0x3, 0x8e, 0x1f, 0xfe, 0x73, 0x80, 0xe3, 0x80, 0xe3, 0xc0, 0xe7, 0xe2, 0xfe, 0xfc, 0x7c, 0x78} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {2, 9, 18, 1, 16, 0} +#define NXFONT_BITMAP_231 {0x1e, 0x0, 0x73, 0x0, 0x73, 0x80, 0xe3, 0x80, 0xe1, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xf0, 0x0, 0x78, 0x80, 0x7f, 0x0, 0x1e, 0x0, 0x8, 0x0, 0x18, 0x0, 0x1c, 0x0, 0x6, 0x0, 0x46, 0x0, 0x3c, 0x0} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {2, 9, 17, 1, 11, 0} +#define NXFONT_BITMAP_232 {0x38, 0x0, 0x1c, 0x0, 0xc, 0x0, 0x6, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x0, 0x73, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xff, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xf0, 0x0, 0x78, 0x80, 0x7f, 0x0, 0x1e, 0x0} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {2, 9, 17, 1, 11, 0} +#define NXFONT_BITMAP_233 {0xe, 0x0, 0x1c, 0x0, 0x18, 0x0, 0x30, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x0, 0x73, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xff, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xf0, 0x0, 0x78, 0x80, 0x7f, 0x0, 0x1e, 0x0} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {2, 9, 17, 1, 11, 0} +#define NXFONT_BITMAP_234 {0x18, 0x0, 0x3c, 0x0, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x0, 0x73, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xff, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xf0, 0x0, 0x78, 0x80, 0x7f, 0x0, 0x1e, 0x0} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {2, 9, 16, 1, 12, 0} +#define NXFONT_BITMAP_235 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x0, 0x73, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xff, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xf0, 0x0, 0x78, 0x80, 0x7f, 0x0, 0x1e, 0x0} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 5, 17, 1, 11, 0} +#define NXFONT_BITMAP_236 {0xe0, 0x70, 0x30, 0x18, 0x0, 0xf0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 6, 17, 1, 11, 0} +#define NXFONT_BITMAP_237 {0x1c, 0x38, 0x30, 0x60, 0x0, 0xf0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* icircumflex (238) */ +#define NXFONT_METRICS_238 {1, 6, 17, 1, 11, 0} +#define NXFONT_BITMAP_238 {0x30, 0x78, 0xcc, 0x0, 0x0, 0xf0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 6, 16, 1, 12, 0} +#define NXFONT_BITMAP_239 {0xcc, 0xcc, 0x0, 0x0, 0xf0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xf8} + +/* eth (240) */ +#define NXFONT_METRICS_240 {2, 11, 17, 1, 11, 0} +#define NXFONT_BITMAP_240 {0x60, 0x0, 0x38, 0xc0, 0xf, 0x0, 0x1e, 0x0, 0x63, 0x0, 0x1f, 0x80, 0x7b, 0xc0, 0x71, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x71, 0xc0, 0x7b, 0xc0, 0x1f, 0x0} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {2, 12, 17, 1, 11, 0} +#define NXFONT_BITMAP_241 {0xc, 0x40, 0x1f, 0x80, 0x23, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf3, 0xc0, 0x77, 0xe0, 0x78, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0xf9, 0xf0} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {2, 11, 17, 1, 11, 0} +#define NXFONT_BITMAP_242 {0x1c, 0x0, 0xe, 0x0, 0x6, 0x0, 0x3, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x7b, 0xc0, 0x71, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x71, 0xc0, 0x7b, 0xc0, 0x1f, 0x0} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {2, 11, 17, 1, 11, 0} +#define NXFONT_BITMAP_243 {0x3, 0x80, 0x7, 0x0, 0x6, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x7b, 0xc0, 0x71, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x71, 0xc0, 0x7b, 0xc0, 0x1f, 0x0} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {2, 11, 17, 1, 11, 0} +#define NXFONT_BITMAP_244 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x7b, 0xc0, 0x71, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x71, 0xc0, 0x7b, 0xc0, 0x1f, 0x0} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {2, 11, 17, 1, 11, 0} +#define NXFONT_BITMAP_245 {0x18, 0x80, 0x3f, 0x0, 0x46, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x7b, 0xc0, 0x71, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x71, 0xc0, 0x7b, 0xc0, 0x1f, 0x0} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {2, 11, 16, 1, 12, 0} +#define NXFONT_BITMAP_246 {0x31, 0x80, 0x31, 0x80, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x7b, 0xc0, 0x71, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x71, 0xc0, 0x7b, 0xc0, 0x1f, 0x0} + +/* divide (247) */ +#define NXFONT_METRICS_247 {2, 12, 12, 1, 16, 0} +#define NXFONT_BITMAP_247 {0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {2, 11, 16, 1, 14, 0} +#define NXFONT_BITMAP_248 {0x0, 0x40, 0x0, 0x40, 0x1e, 0x80, 0x79, 0xc0, 0x71, 0xc0, 0xe2, 0xe0, 0xe2, 0xe0, 0xe4, 0xe0, 0xe4, 0xe0, 0xe8, 0xe0, 0xe8, 0xe0, 0x71, 0xc0, 0x7b, 0xc0, 0x3f, 0x0, 0x40, 0x0, 0x40, 0x0} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {2, 12, 17, 1, 11, 0} +#define NXFONT_BITMAP_249 {0x1c, 0x0, 0xe, 0x0, 0x6, 0x0, 0x3, 0x0, 0x0, 0x0, 0xf1, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x71, 0xe0, 0x7e, 0xf0, 0x3c, 0xe0} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {2, 12, 17, 1, 11, 0} +#define NXFONT_BITMAP_250 {0x7, 0x0, 0xe, 0x0, 0xc, 0x0, 0x18, 0x0, 0x0, 0x0, 0xf1, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x71, 0xe0, 0x7e, 0xf0, 0x3c, 0xe0} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {2, 12, 17, 1, 11, 0} +#define NXFONT_BITMAP_251 {0x6, 0x0, 0xf, 0x0, 0x19, 0x80, 0x0, 0x0, 0x0, 0x0, 0xf1, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x71, 0xe0, 0x7e, 0xf0, 0x3c, 0xe0} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {2, 12, 16, 1, 12, 0} +#define NXFONT_BITMAP_252 {0x19, 0x80, 0x19, 0x80, 0x0, 0x0, 0x0, 0x0, 0xf1, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x70, 0xe0, 0x71, 0xe0, 0x7e, 0xf0, 0x3c, 0xe0} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {2, 12, 22, 0, 11, 0} +#define NXFONT_BITMAP_253 {0x1, 0xc0, 0x3, 0x80, 0x3, 0x0, 0x6, 0x0, 0x0, 0x0, 0xfd, 0xf0, 0x78, 0x60, 0x38, 0x40, 0x38, 0xc0, 0x3c, 0x80, 0x1c, 0x80, 0x1d, 0x80, 0x1f, 0x0, 0xf, 0x0, 0xf, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x64, 0x0, 0xec, 0x0, 0xf8, 0x0, 0x70, 0x0} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {2, 12, 22, 1, 11, 0} +#define NXFONT_BITMAP_254 {0xf0, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x73, 0x80, 0x77, 0xe0, 0x7c, 0xe0, 0x78, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x78, 0xe0, 0x77, 0xe0, 0x73, 0x80, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0xfc, 0x0} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {2, 12, 21, 0, 12, 0} +#define NXFONT_BITMAP_255 {0x19, 0x80, 0x19, 0x80, 0x0, 0x0, 0x0, 0x0, 0xfd, 0xf0, 0x78, 0x60, 0x38, 0x40, 0x38, 0xc0, 0x3c, 0x80, 0x1c, 0x80, 0x1d, 0x80, 0x1f, 0x0, 0xf, 0x0, 0xf, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x64, 0x0, 0xec, 0x0, 0xf8, 0x0, 0x70, 0x0} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SERIF27X38B_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_serif29x37.h b/nuttx/graphics/nxfonts/nxfonts_serif29x37.h new file mode 100755 index 0000000000..11215e44e7 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_serif29x37.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_serif29x37.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Jose Pablo Carballo Gomez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SERIF29X37_H +#define __GRAPHICS_NXFONTS_NXFONTS_SERIF29X37_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SERIF29X37 + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 37 +#define NXFONT_MAXWIDTH 29 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 6 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 3, 17, 3, 11, 0} +#define NXFONT_BITMAP_33 {0x40, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x40, 0x40, 0x40, 0x40, 0x0, 0x0, 0x0, 0xc0, 0xc0} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {1, 6, 5, 1, 11, 0} +#define NXFONT_BITMAP_34 {0xcc, 0xcc, 0xcc, 0xcc, 0x88} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {2, 11, 17, 1, 11, 0} +#define NXFONT_BITMAP_35 {0x8, 0x80, 0x8, 0x80, 0x8, 0x80, 0x8, 0x80, 0x8, 0x80, 0x7f, 0xe0, 0x7f, 0xe0, 0x11, 0x0, 0x11, 0x0, 0x11, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0x22, 0x0, 0x22, 0x0, 0x22, 0x0, 0x22, 0x0, 0x22, 0x0} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {2, 11, 21, 0, 9, 0} +#define NXFONT_BITMAP_36 {0x4, 0x0, 0x4, 0x0, 0x3f, 0x0, 0x65, 0xc0, 0xc4, 0xc0, 0xc4, 0x40, 0xc4, 0x40, 0xe4, 0x0, 0x7c, 0x0, 0x1e, 0x0, 0x7, 0x80, 0x5, 0xc0, 0x4, 0xe0, 0x4, 0x60, 0x84, 0x60, 0x84, 0x60, 0xc4, 0xc0, 0xe5, 0xc0, 0x3f, 0x0, 0x4, 0x0, 0x4, 0x0} + +/* percent (37) */ +#define NXFONT_METRICS_37 {3, 17, 16, 1, 12, 0} +#define NXFONT_BITMAP_37 {0x1e, 0xc, 0x0, 0x33, 0xfc, 0x0, 0x61, 0x18, 0x0, 0xc1, 0x10, 0x0, 0xc1, 0x30, 0x0, 0xc2, 0x60, 0x0, 0xe4, 0x40, 0x0, 0x78, 0xc0, 0x0, 0x1, 0x8f, 0x0, 0x1, 0x19, 0x80, 0x3, 0x30, 0x80, 0x6, 0x60, 0x80, 0x4, 0x60, 0x80, 0xc, 0x61, 0x0, 0x18, 0x72, 0x0, 0x10, 0x3c, 0x0} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {3, 17, 17, 1, 11, 0} +#define NXFONT_BITMAP_38 {0x7, 0xc0, 0x0, 0x8, 0x60, 0x0, 0x18, 0x20, 0x0, 0x18, 0x20, 0x0, 0x18, 0x60, 0x0, 0xc, 0xc0, 0x0, 0xf, 0x9e, 0x0, 0x7, 0xc, 0x0, 0xf, 0x8, 0x0, 0x33, 0x88, 0x0, 0x61, 0x90, 0x0, 0xc0, 0xd0, 0x0, 0xc0, 0xe0, 0x0, 0xc0, 0x60, 0x0, 0xe0, 0xf0, 0x80, 0x7f, 0xbf, 0x0, 0x3e, 0xe, 0x0} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 2, 5, 2, 11, 0} +#define NXFONT_BITMAP_39 {0xc0, 0xc0, 0xc0, 0xc0, 0x80} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 6, 22, 1, 11, 0} +#define NXFONT_BITMAP_40 {0x4, 0x8, 0x10, 0x30, 0x20, 0x60, 0x60, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0x60, 0x20, 0x30, 0x10, 0x8, 0x4} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 6, 22, 1, 11, 0} +#define NXFONT_BITMAP_41 {0x80, 0x40, 0x20, 0x30, 0x10, 0x18, 0x18, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0x18, 0x18, 0x10, 0x30, 0x20, 0x40, 0x80} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {2, 9, 9, 2, 11, 0} +#define NXFONT_BITMAP_42 {0x1c, 0x0, 0x1c, 0x0, 0xc9, 0x80, 0xeb, 0x80, 0x1c, 0x0, 0xeb, 0x80, 0xc9, 0x80, 0x1c, 0x0, 0x1c, 0x0} + +/* plus (43) */ +#define NXFONT_METRICS_43 {2, 12, 12, 0, 16, 0} +#define NXFONT_BITMAP_43 {0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0xff, 0xf0, 0xff, 0xf0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 3, 5, 2, 26, 0} +#define NXFONT_BITMAP_44 {0xc0, 0xe0, 0x20, 0x60, 0xc0} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 6, 2, 0, 21, 0} +#define NXFONT_BITMAP_45 {0xfc, 0xfc} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 2, 2, 2, 26, 0} +#define NXFONT_BITMAP_46 {0xc0, 0xc0} + +/* slash (47) */ +#define NXFONT_METRICS_47 {2, 9, 21, 0, 11, 0} +#define NXFONT_BITMAP_47 {0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x3, 0x0, 0x2, 0x0, 0x6, 0x0, 0x6, 0x0, 0x4, 0x0, 0xc, 0x0, 0xc, 0x0, 0x8, 0x0, 0x18, 0x0, 0x18, 0x0, 0x10, 0x0, 0x30, 0x0, 0x30, 0x0, 0x60, 0x0, 0x60, 0x0, 0x40, 0x0, 0xc0, 0x0} + +/* zero (48) */ +#define NXFONT_METRICS_48 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_48 {0x1e, 0x0, 0x33, 0x0, 0x61, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe1, 0xc0, 0x61, 0x80, 0x61, 0x80, 0x33, 0x0, 0x1e, 0x0} + +/* one (49) */ +#define NXFONT_METRICS_49 {1, 8, 17, 2, 11, 0} +#define NXFONT_BITMAP_49 {0x8, 0x18, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff} + +/* two (50) */ +#define NXFONT_METRICS_50 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_50 {0x1c, 0x0, 0x7f, 0x0, 0x43, 0x80, 0x81, 0x80, 0x81, 0x80, 0x1, 0x80, 0x1, 0x80, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x4, 0x0, 0xc, 0x0, 0x18, 0x0, 0x30, 0x0, 0x60, 0x40, 0xff, 0xc0, 0xff, 0x80} + +/* three (51) */ +#define NXFONT_METRICS_51 {2, 9, 17, 1, 11, 0} +#define NXFONT_BITMAP_51 {0x1c, 0x0, 0x7e, 0x0, 0x47, 0x0, 0x83, 0x0, 0x83, 0x0, 0x6, 0x0, 0xc, 0x0, 0x1e, 0x0, 0x7, 0x0, 0x3, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0xc3, 0x0, 0xe6, 0x0, 0x78, 0x0} + +/* four (52) */ +#define NXFONT_METRICS_52 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_52 {0x3, 0x0, 0x7, 0x0, 0x7, 0x0, 0xb, 0x0, 0x1b, 0x0, 0x13, 0x0, 0x33, 0x0, 0x23, 0x0, 0x63, 0x0, 0x43, 0x0, 0xc3, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0} + +/* five (53) */ +#define NXFONT_METRICS_53 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_53 {0x1f, 0xc0, 0x1f, 0x80, 0x20, 0x0, 0x20, 0x0, 0x60, 0x0, 0x78, 0x0, 0x7e, 0x0, 0xf, 0x80, 0x3, 0x80, 0x1, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0xc1, 0x80, 0xe3, 0x80, 0x7e, 0x0} + +/* six (54) */ +#define NXFONT_METRICS_54 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_54 {0x3, 0xc0, 0xe, 0x0, 0x18, 0x0, 0x30, 0x0, 0x70, 0x0, 0x60, 0x0, 0xee, 0x0, 0xf3, 0x80, 0xc1, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xc0, 0x61, 0x80, 0x7b, 0x80, 0x1e, 0x0} + +/* seven (55) */ +#define NXFONT_METRICS_55 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_55 {0x7f, 0xc0, 0xff, 0xc0, 0xc0, 0xc0, 0x81, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x3, 0x0, 0x2, 0x0, 0x6, 0x0, 0x6, 0x0, 0x4, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0x18, 0x0, 0x18, 0x0} + +/* eight (56) */ +#define NXFONT_METRICS_56 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_56 {0x1e, 0x0, 0x33, 0x0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x73, 0x0, 0x3e, 0x0, 0x1e, 0x0, 0x3f, 0x0, 0x63, 0x80, 0x41, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe1, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* nine (57) */ +#define NXFONT_METRICS_57 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_57 {0x1e, 0x0, 0x77, 0x80, 0x61, 0x80, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0xc0, 0x73, 0xc0, 0x1d, 0x80, 0x1, 0x80, 0x3, 0x80, 0x3, 0x0, 0x6, 0x0, 0x1c, 0x0, 0xf0, 0x0} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 2, 11, 2, 17, 0} +#define NXFONT_BITMAP_58 {0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 3, 14, 2, 17, 0} +#define NXFONT_BITMAP_59 {0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xe0, 0x20, 0x60, 0xc0} + +/* less (60) */ +#define NXFONT_METRICS_60 {2, 11, 11, 1, 17, 0} +#define NXFONT_BITMAP_60 {0x0, 0x60, 0x1, 0xc0, 0x7, 0x0, 0x1c, 0x0, 0x70, 0x0, 0xc0, 0x0, 0x70, 0x0, 0x1c, 0x0, 0x7, 0x0, 0x1, 0xc0, 0x0, 0x60} + +/* equal (61) */ +#define NXFONT_METRICS_61 {2, 9, 5, 2, 20, 0} +#define NXFONT_BITMAP_61 {0xff, 0x80, 0xff, 0x80, 0x0, 0x0, 0xff, 0x80, 0xff, 0x80} + +/* greater (62) */ +#define NXFONT_METRICS_62 {2, 11, 11, 1, 17, 0} +#define NXFONT_BITMAP_62 {0xc0, 0x0, 0x70, 0x0, 0x1c, 0x0, 0x7, 0x0, 0x1, 0xc0, 0x0, 0x60, 0x1, 0xc0, 0x7, 0x0, 0x1c, 0x0, 0x70, 0x0, 0xc0, 0x0} + +/* question (63) */ +#define NXFONT_METRICS_63 {1, 8, 17, 2, 11, 0} +#define NXFONT_BITMAP_63 {0x7c, 0xc6, 0x83, 0xc3, 0xc3, 0x7, 0xe, 0xc, 0x1c, 0x18, 0x18, 0x10, 0x10, 0x0, 0x0, 0x30, 0x30} + +/* at (64) */ +#define NXFONT_METRICS_64 {3, 18, 20, 2, 11, 0} +#define NXFONT_BITMAP_64 {0x3, 0xf8, 0x0, 0xf, 0xe, 0x0, 0x1c, 0x3, 0x0, 0x38, 0x1, 0x80, 0x70, 0x0, 0x80, 0x60, 0xec, 0xc0, 0xe1, 0xfc, 0x40, 0xc3, 0x8c, 0x40, 0xc3, 0xc, 0x40, 0xc6, 0xc, 0x40, 0xc6, 0x18, 0x40, 0xc6, 0x18, 0xc0, 0xc6, 0x18, 0x80, 0xc6, 0x39, 0x80, 0x63, 0x7b, 0x0, 0x61, 0xde, 0x0, 0x30, 0x0, 0x0, 0x18, 0x0, 0x0, 0xe, 0xc, 0x0, 0x3, 0xf0, 0x0} + +/* A (65) */ +#define NXFONT_METRICS_65 {3, 17, 17, 0, 11, 0} +#define NXFONT_BITMAP_65 {0x0, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0x60, 0x0, 0x2, 0x60, 0x0, 0x2, 0x30, 0x0, 0x6, 0x30, 0x0, 0x4, 0x30, 0x0, 0x4, 0x18, 0x0, 0xc, 0x18, 0x0, 0xf, 0xf8, 0x0, 0x8, 0xc, 0x0, 0x18, 0xc, 0x0, 0x10, 0xc, 0x0, 0x10, 0x6, 0x0, 0x30, 0x6, 0x0, 0xfc, 0x1f, 0x80} + +/* B (66) */ +#define NXFONT_METRICS_66 {2, 14, 17, 1, 11, 0} +#define NXFONT_BITMAP_66 {0xff, 0xc0, 0x30, 0x70, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x30, 0x40, 0x3f, 0xe0, 0x30, 0x38, 0x30, 0x18, 0x30, 0xc, 0x30, 0xc, 0x30, 0xc, 0x30, 0x18, 0x30, 0x78, 0xff, 0xe0} + +/* C (67) */ +#define NXFONT_METRICS_67 {2, 14, 17, 1, 11, 0} +#define NXFONT_BITMAP_67 {0x7, 0xe4, 0x1c, 0x3c, 0x38, 0xc, 0x60, 0x4, 0x60, 0x4, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0x60, 0x0, 0x60, 0x4, 0x38, 0x8, 0x1e, 0x38, 0x7, 0xe0} + +/* D (68) */ +#define NXFONT_METRICS_68 {2, 15, 17, 1, 11, 0} +#define NXFONT_BITMAP_68 {0xff, 0xc0, 0x30, 0x70, 0x30, 0x38, 0x30, 0xc, 0x30, 0xc, 0x30, 0x6, 0x30, 0x6, 0x30, 0x6, 0x30, 0x6, 0x30, 0x6, 0x30, 0x6, 0x30, 0x6, 0x30, 0xc, 0x30, 0xc, 0x30, 0x38, 0x30, 0x70, 0xff, 0xc0} + +/* E (69) */ +#define NXFONT_METRICS_69 {2, 13, 17, 1, 11, 0} +#define NXFONT_BITMAP_69 {0xff, 0xf0, 0x30, 0x30, 0x30, 0x10, 0x30, 0x10, 0x30, 0x0, 0x30, 0x0, 0x30, 0x40, 0x30, 0x40, 0x3f, 0xc0, 0x30, 0x40, 0x30, 0x40, 0x30, 0x0, 0x30, 0x0, 0x30, 0x8, 0x30, 0x8, 0x30, 0x18, 0xff, 0xf8} + +/* F (70) */ +#define NXFONT_METRICS_70 {2, 12, 17, 1, 11, 0} +#define NXFONT_BITMAP_70 {0xff, 0xf0, 0x30, 0x30, 0x30, 0x10, 0x30, 0x10, 0x30, 0x0, 0x30, 0x0, 0x30, 0x20, 0x30, 0x20, 0x3f, 0xe0, 0x30, 0x20, 0x30, 0x20, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0xfc, 0x0} + +/* G (71) */ +#define NXFONT_METRICS_71 {2, 16, 17, 1, 11, 0} +#define NXFONT_BITMAP_71 {0x7, 0xe4, 0x1c, 0x3c, 0x38, 0xc, 0x60, 0x4, 0x60, 0x4, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x3f, 0xc0, 0xc, 0xc0, 0xc, 0x60, 0xc, 0x60, 0xc, 0x38, 0x1c, 0x1e, 0x38, 0x7, 0xe0} + +/* H (72) */ +#define NXFONT_METRICS_72 {3, 17, 17, 1, 11, 0} +#define NXFONT_BITMAP_72 {0xfc, 0x1f, 0x80, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x3f, 0xfe, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0xfc, 0x1f, 0x80} + +/* I (73) */ +#define NXFONT_METRICS_73 {1, 6, 17, 1, 11, 0} +#define NXFONT_BITMAP_73 {0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc} + +/* J (74) */ +#define NXFONT_METRICS_74 {2, 9, 17, 1, 11, 0} +#define NXFONT_BITMAP_74 {0x1f, 0x80, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0xc6, 0x0, 0xcc, 0x0, 0x78, 0x0} + +/* K (75) */ +#define NXFONT_METRICS_75 {2, 16, 17, 1, 11, 0} +#define NXFONT_BITMAP_75 {0xfc, 0x7e, 0x30, 0x18, 0x30, 0x30, 0x30, 0x60, 0x30, 0xc0, 0x31, 0x80, 0x33, 0x0, 0x3e, 0x0, 0x3f, 0x0, 0x33, 0x80, 0x31, 0xc0, 0x30, 0xe0, 0x30, 0x70, 0x30, 0x38, 0x30, 0x1c, 0x30, 0xe, 0xfc, 0x1f} + +/* L (76) */ +#define NXFONT_METRICS_76 {2, 13, 17, 1, 11, 0} +#define NXFONT_BITMAP_76 {0xfc, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x8, 0x30, 0x8, 0x30, 0x18, 0xff, 0xf8} + +/* M (77) */ +#define NXFONT_METRICS_77 {3, 21, 17, 1, 11, 0} +#define NXFONT_BITMAP_77 {0xf0, 0x0, 0xf8, 0x30, 0x0, 0xe0, 0x38, 0x1, 0x60, 0x38, 0x1, 0x60, 0x2c, 0x2, 0x60, 0x2c, 0x2, 0x60, 0x26, 0x2, 0x60, 0x26, 0x4, 0x60, 0x23, 0x4, 0x60, 0x23, 0x8, 0x60, 0x21, 0x88, 0x60, 0x21, 0x88, 0x60, 0x20, 0xd0, 0x60, 0x20, 0xd0, 0x60, 0x20, 0x60, 0x60, 0x20, 0x60, 0x60, 0xf8, 0x61, 0xf8} + +/* N (78) */ +#define NXFONT_METRICS_78 {2, 16, 17, 1, 11, 0} +#define NXFONT_BITMAP_78 {0xf0, 0x1f, 0x30, 0x4, 0x38, 0x4, 0x38, 0x4, 0x2c, 0x4, 0x26, 0x4, 0x26, 0x4, 0x23, 0x4, 0x21, 0x84, 0x21, 0x84, 0x20, 0xc4, 0x20, 0x64, 0x20, 0x64, 0x20, 0x34, 0x20, 0x1c, 0x20, 0x1c, 0xf8, 0xc} + +/* O (79) */ +#define NXFONT_METRICS_79 {2, 16, 17, 1, 11, 0} +#define NXFONT_BITMAP_79 {0x7, 0xe0, 0x1c, 0x38, 0x38, 0x1c, 0x60, 0x6, 0x60, 0x6, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0x60, 0x6, 0x60, 0x6, 0x38, 0x1c, 0x1c, 0x38, 0x7, 0xe0} + +/* P (80) */ +#define NXFONT_METRICS_80 {2, 13, 17, 1, 11, 0} +#define NXFONT_BITMAP_80 {0xff, 0xc0, 0x30, 0x70, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x30, 0x70, 0x3f, 0xc0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0xfc, 0x0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {2, 16, 22, 1, 11, 0} +#define NXFONT_BITMAP_81 {0x7, 0xe0, 0x1c, 0x38, 0x38, 0x1c, 0x60, 0x6, 0x60, 0x6, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0x60, 0x6, 0x60, 0x6, 0x38, 0x1c, 0x1c, 0x38, 0x7, 0xe0, 0x1, 0xc0, 0x0, 0xe0, 0x0, 0x70, 0x0, 0x38, 0x0, 0xf} + +/* R (82) */ +#define NXFONT_METRICS_82 {2, 15, 17, 1, 11, 0} +#define NXFONT_BITMAP_82 {0xff, 0xc0, 0x30, 0x70, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x30, 0x70, 0x3f, 0xc0, 0x33, 0x80, 0x31, 0x80, 0x30, 0xc0, 0x30, 0x60, 0x30, 0x70, 0x30, 0x38, 0x30, 0x1c, 0xfc, 0x1e} + +/* S (83) */ +#define NXFONT_METRICS_83 {2, 11, 17, 1, 11, 0} +#define NXFONT_BITMAP_83 {0x1e, 0x40, 0x63, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0xc0, 0x40, 0xe0, 0x0, 0x78, 0x0, 0x1e, 0x0, 0xf, 0x80, 0x3, 0xc0, 0x0, 0xe0, 0x0, 0x60, 0x80, 0x60, 0x80, 0x60, 0xc0, 0xc0, 0xf1, 0x80, 0x9e, 0x0} + +/* T (84) */ +#define NXFONT_METRICS_84 {2, 14, 17, 1, 11, 0} +#define NXFONT_BITMAP_84 {0xff, 0xfc, 0xc3, 0xc, 0x83, 0x4, 0x83, 0x4, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0xf, 0xc0} + +/* U (85) */ +#define NXFONT_METRICS_85 {2, 16, 17, 1, 11, 0} +#define NXFONT_BITMAP_85 {0xfc, 0x1f, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x8, 0x18, 0x8, 0x1c, 0x30, 0x7, 0xe0} + +/* V (86) */ +#define NXFONT_METRICS_86 {3, 17, 17, 0, 11, 0} +#define NXFONT_BITMAP_86 {0xfc, 0x1f, 0x80, 0x30, 0x6, 0x0, 0x30, 0x4, 0x0, 0x18, 0xc, 0x0, 0x18, 0x8, 0x0, 0x18, 0x8, 0x0, 0xc, 0x18, 0x0, 0xc, 0x10, 0x0, 0x6, 0x30, 0x0, 0x6, 0x20, 0x0, 0x6, 0x20, 0x0, 0x3, 0x60, 0x0, 0x3, 0x40, 0x0, 0x3, 0xc0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {3, 23, 17, 0, 11, 0} +#define NXFONT_BITMAP_87 {0xfc, 0x7e, 0x7e, 0x30, 0x18, 0x18, 0x30, 0x18, 0x10, 0x18, 0x18, 0x10, 0x18, 0x18, 0x30, 0x18, 0x2c, 0x20, 0xc, 0x2c, 0x20, 0xc, 0x2c, 0x60, 0x6, 0x4c, 0x60, 0x6, 0x4c, 0x40, 0x6, 0x46, 0x40, 0x3, 0x46, 0xc0, 0x3, 0x46, 0x80, 0x3, 0x87, 0x80, 0x1, 0x83, 0x80, 0x1, 0x83, 0x0, 0x1, 0x83, 0x0} + +/* X (88) */ +#define NXFONT_METRICS_88 {3, 18, 17, 0, 11, 0} +#define NXFONT_BITMAP_88 {0x7e, 0xf, 0x80, 0x1c, 0x6, 0x0, 0xe, 0xc, 0x0, 0x6, 0x8, 0x0, 0x3, 0x10, 0x0, 0x1, 0xa0, 0x0, 0x1, 0xc0, 0x0, 0x0, 0xc0, 0x0, 0x0, 0xe0, 0x0, 0x1, 0x70, 0x0, 0x2, 0x38, 0x0, 0x6, 0x18, 0x0, 0x4, 0xc, 0x0, 0x8, 0xe, 0x0, 0x18, 0x7, 0x0, 0x30, 0x3, 0x80, 0xfc, 0xf, 0xc0} + +/* Y (89) */ +#define NXFONT_METRICS_89 {2, 16, 17, 1, 11, 0} +#define NXFONT_BITMAP_89 {0xfc, 0x3f, 0x30, 0xc, 0x38, 0x8, 0x18, 0x18, 0x1c, 0x10, 0xc, 0x30, 0x6, 0x20, 0x6, 0x60, 0x3, 0x40, 0x3, 0xc0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x7, 0xe0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {2, 13, 17, 1, 11, 0} +#define NXFONT_BITMAP_90 {0xff, 0xf0, 0xc0, 0x70, 0x80, 0xe0, 0x80, 0xc0, 0x1, 0xc0, 0x3, 0x80, 0x3, 0x0, 0x7, 0x0, 0x6, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x18, 0x0, 0x38, 0x0, 0x30, 0x8, 0x70, 0x8, 0xe0, 0x18, 0xff, 0xf8} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 5, 21, 2, 11, 0} +#define NXFONT_BITMAP_91 {0xf8, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {1, 7, 17, 0, 11, 0} +#define NXFONT_BITMAP_92 {0xc0, 0xc0, 0x40, 0x60, 0x60, 0x20, 0x30, 0x30, 0x10, 0x18, 0x18, 0x8, 0xc, 0xc, 0x4, 0x6, 0x6} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 5, 21, 1, 11, 0} +#define NXFONT_BITMAP_93 {0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {2, 9, 9, 1, 11, 0} +#define NXFONT_BITMAP_94 {0x8, 0x0, 0x1c, 0x0, 0x14, 0x0, 0x36, 0x0, 0x22, 0x0, 0x63, 0x0, 0x41, 0x0, 0xc1, 0x80, 0x80, 0x80} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {2, 12, 2, 0, 31, 0} +#define NXFONT_BITMAP_95 {0xff, 0xf0, 0xff, 0xf0} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 5, 4, 1, 11, 0} +#define NXFONT_BITMAP_96 {0xc0, 0xe0, 0x70, 0x18} + +/* a (97) */ +#define NXFONT_METRICS_97 {2, 9, 12, 1, 16, 0} +#define NXFONT_BITMAP_97 {0x3e, 0x0, 0x67, 0x0, 0x63, 0x0, 0x3, 0x0, 0xf, 0x0, 0x3b, 0x0, 0x63, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xc7, 0x0, 0xfb, 0x0, 0x71, 0x80} + +/* b (98) */ +#define NXFONT_METRICS_98 {2, 11, 17, 0, 11, 0} +#define NXFONT_BITMAP_98 {0x30, 0x0, 0xf0, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x37, 0x0, 0x39, 0xc0, 0x30, 0xc0, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0xc0, 0x39, 0xc0, 0x2f, 0x0} + +/* c (99) */ +#define NXFONT_METRICS_99 {2, 9, 12, 1, 16, 0} +#define NXFONT_BITMAP_99 {0x1f, 0x0, 0x63, 0x80, 0x41, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x70, 0x80, 0x7f, 0x0, 0x1e, 0x0} + +/* d (100) */ +#define NXFONT_METRICS_100 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_100 {0x1, 0x80, 0x7, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1d, 0x80, 0x73, 0x80, 0x61, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x80, 0x7f, 0x80, 0x19, 0xc0} + +/* e (101) */ +#define NXFONT_METRICS_101 {2, 9, 12, 1, 16, 0} +#define NXFONT_BITMAP_101 {0x1e, 0x0, 0x63, 0x0, 0x41, 0x80, 0xc1, 0x80, 0xff, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x70, 0x80, 0x7f, 0x0, 0x1e, 0x0} + +/* f (102) */ +#define NXFONT_METRICS_102 {1, 7, 17, 0, 11, 0} +#define NXFONT_BITMAP_102 {0xe, 0x16, 0x30, 0x30, 0x30, 0xfe, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78} + +/* g (103) */ +#define NXFONT_METRICS_103 {2, 11, 18, 1, 16, 0} +#define NXFONT_BITMAP_103 {0x1e, 0xc0, 0x23, 0xc0, 0x61, 0x0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x33, 0x0, 0x3c, 0x0, 0x40, 0x0, 0x60, 0x0, 0x7f, 0x80, 0x3f, 0xc0, 0x40, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xe1, 0xc0, 0x7f, 0x0} + +/* h (104) */ +#define NXFONT_METRICS_104 {2, 12, 17, 0, 11, 0} +#define NXFONT_BITMAP_104 {0x30, 0x0, 0xf0, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x33, 0x80, 0x37, 0xc0, 0x38, 0xe0, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x78, 0xf0} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 4, 17, 1, 11, 0} +#define NXFONT_BITMAP_105 {0x60, 0x60, 0x0, 0x0, 0x0, 0x60, 0xe0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* j (106) - NOTE: Xoffset should be -2, not 0. */ +#define NXFONT_METRICS_106 {1, 6, 23, 0, 11, 0} +#define NXFONT_BITMAP_106 {0xc, 0xc, 0x0, 0x0, 0x0, 0xc, 0x1c, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xcc, 0xc8, 0x70} + +/* k (107) */ +#define NXFONT_METRICS_107 {2, 12, 17, 0, 11, 0} +#define NXFONT_BITMAP_107 {0x30, 0x0, 0xf0, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x33, 0xe0, 0x31, 0x80, 0x33, 0x0, 0x32, 0x0, 0x34, 0x0, 0x3c, 0x0, 0x36, 0x0, 0x37, 0x0, 0x33, 0x80, 0x31, 0xc0, 0x30, 0xe0, 0x79, 0xf0} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 5, 17, 0, 11, 0} +#define NXFONT_BITMAP_108 {0x30, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78} + +/* m (109) */ +#define NXFONT_METRICS_109 {3, 18, 12, 1, 16, 0} +#define NXFONT_BITMAP_109 {0x67, 0xe, 0x0, 0xef, 0x9f, 0x0, 0x71, 0xe3, 0x80, 0x60, 0xc1, 0x80, 0x60, 0xc1, 0x80, 0x60, 0xc1, 0x80, 0x60, 0xc1, 0x80, 0x60, 0xc1, 0x80, 0x60, 0xc1, 0x80, 0x60, 0xc1, 0x80, 0x60, 0xc1, 0x80, 0xf1, 0xe3, 0xc0} + +/* n (110) */ +#define NXFONT_METRICS_110 {2, 11, 12, 1, 16, 0} +#define NXFONT_BITMAP_110 {0x67, 0x0, 0xef, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0xf1, 0xe0} + +/* o (111) */ +#define NXFONT_METRICS_111 {2, 10, 12, 1, 16, 0} +#define NXFONT_BITMAP_111 {0x1e, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* p (112) */ +#define NXFONT_METRICS_112 {2, 10, 18, 1, 16, 0} +#define NXFONT_BITMAP_112 {0x6e, 0x0, 0xf3, 0x80, 0x61, 0x80, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x6e, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0xf0, 0x0} + +/* q (113) */ +#define NXFONT_METRICS_113 {2, 10, 18, 1, 16, 0} +#define NXFONT_BITMAP_113 {0x1d, 0x80, 0x73, 0x80, 0x61, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x61, 0x80, 0x73, 0x80, 0x1d, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x3, 0xc0} + +/* r (114) */ +#define NXFONT_METRICS_114 {1, 6, 12, 1, 16, 0} +#define NXFONT_BITMAP_114 {0x6c, 0xec, 0x70, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* s (115) */ +#define NXFONT_METRICS_115 {1, 8, 12, 1, 16, 0} +#define NXFONT_BITMAP_115 {0x3e, 0x46, 0xc2, 0xe0, 0x70, 0x7c, 0x1e, 0x7, 0x3, 0x83, 0xc6, 0xf8} + +/* t (116) */ +#define NXFONT_METRICS_116 {1, 7, 15, 0, 13, 0} +#define NXFONT_BITMAP_116 {0x10, 0x30, 0x70, 0xfe, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x1c} + +/* u (117) */ +#define NXFONT_METRICS_117 {2, 11, 12, 1, 16, 0} +#define NXFONT_BITMAP_117 {0xe1, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x71, 0xc0, 0x3e, 0xc0, 0x1c, 0xe0} + +/* v (118) */ +#define NXFONT_METRICS_118 {2, 11, 12, 0, 16, 0} +#define NXFONT_BITMAP_118 {0xf1, 0xe0, 0x60, 0xc0, 0x60, 0x80, 0x30, 0x80, 0x30, 0x80, 0x31, 0x0, 0x19, 0x0, 0x19, 0x0, 0x1a, 0x0, 0xe, 0x0, 0xe, 0x0, 0x4, 0x0} + +/* w (119) */ +#define NXFONT_METRICS_119 {3, 17, 12, 0, 16, 0} +#define NXFONT_BITMAP_119 {0xf1, 0xe7, 0x80, 0x60, 0xc3, 0x0, 0x60, 0xc2, 0x0, 0x30, 0xc2, 0x0, 0x30, 0xc2, 0x0, 0x31, 0x64, 0x0, 0x19, 0x64, 0x0, 0x1a, 0x64, 0x0, 0x1a, 0x28, 0x0, 0xe, 0x38, 0x0, 0xe, 0x38, 0x0, 0x4, 0x10, 0x0} + +/* x (120) */ +#define NXFONT_METRICS_120 {2, 11, 12, 1, 16, 0} +#define NXFONT_BITMAP_120 {0xf1, 0xe0, 0x60, 0xc0, 0x31, 0x80, 0x39, 0x0, 0x1a, 0x0, 0xc, 0x0, 0xe, 0x0, 0x1b, 0x0, 0x33, 0x80, 0x21, 0x80, 0x60, 0xc0, 0xf1, 0xe0} + +/* y (121) */ +#define NXFONT_METRICS_121 {2, 12, 18, 0, 16, 0} +#define NXFONT_BITMAP_121 {0x78, 0xf0, 0x30, 0x60, 0x30, 0x40, 0x18, 0x40, 0x18, 0x40, 0x18, 0x80, 0xc, 0x80, 0xc, 0x80, 0xd, 0x0, 0x7, 0x0, 0x7, 0x0, 0x2, 0x0, 0x6, 0x0, 0x4, 0x0, 0xc, 0x0, 0xc8, 0x0, 0xf0, 0x0, 0x60, 0x0} + +/* z (122) */ +#define NXFONT_METRICS_122 {1, 8, 12, 1, 16, 0} +#define NXFONT_BITMAP_122 {0xff, 0xc3, 0x86, 0xe, 0x1c, 0x18, 0x38, 0x30, 0x70, 0x61, 0xc3, 0xff} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {1, 8, 22, 1, 11, 0} +#define NXFONT_BITMAP_123 {0x7, 0xc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, 0x30, 0x20, 0xc0, 0x20, 0x30, 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xc, 0x7} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 2, 17, 1, 11, 0} +#define NXFONT_BITMAP_124 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 8, 22, 1, 11, 0} +#define NXFONT_BITMAP_125 {0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x8, 0xc, 0x4, 0x3, 0x4, 0xc, 0x8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {2, 11, 4, 1, 20, 0} +#define NXFONT_BITMAP_126 {0x38, 0x20, 0x7c, 0x60, 0xc7, 0xc0, 0x83, 0x80} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 3, 17, 3, 16, 0} +#define NXFONT_BITMAP_161 {0x60, 0x60, 0x0, 0x0, 0x0, 0x40, 0x40, 0x40, 0x40, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x40} + +/* cent (162) */ +#define NXFONT_METRICS_162 {2, 9, 16, 1, 14, 0} +#define NXFONT_BITMAP_162 {0x2, 0x0, 0x2, 0x0, 0xf, 0x0, 0x33, 0x80, 0x65, 0x80, 0xc4, 0x0, 0xc4, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xd0, 0x0, 0x70, 0x80, 0x71, 0x0, 0x3e, 0x0, 0x40, 0x0, 0x40, 0x0} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_163 {0xf, 0x0, 0x19, 0x80, 0x31, 0x80, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0xfc, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x78, 0x40, 0xbe, 0xc0, 0xe7, 0x80} + +/* currency (164) */ +#define NXFONT_METRICS_164 {2, 11, 12, 1, 13, 0} +#define NXFONT_BITMAP_164 {0xc0, 0x60, 0xee, 0xe0, 0x7f, 0xc0, 0x31, 0x80, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x31, 0x80, 0x7f, 0xc0, 0xee, 0xe0, 0xc0, 0x60} + +/* yen (165) */ +#define NXFONT_METRICS_165 {2, 14, 17, 0, 11, 0} +#define NXFONT_BITMAP_165 {0xf8, 0x7c, 0x70, 0x30, 0x30, 0x20, 0x18, 0x60, 0x18, 0x40, 0xc, 0xc0, 0xc, 0x80, 0x7, 0x80, 0x3, 0x0, 0x1f, 0xe0, 0x3, 0x0, 0x1f, 0xe0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0xf, 0xc0} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 2, 17, 2, 11, 0} +#define NXFONT_BITMAP_166 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* section (167) */ +#define NXFONT_METRICS_167 {1, 8, 20, 2, 11, 0} +#define NXFONT_BITMAP_167 {0x1c, 0x26, 0x46, 0x60, 0x70, 0x38, 0x3c, 0x4e, 0x87, 0x83, 0xc3, 0xe2, 0x74, 0x38, 0x1c, 0xe, 0x6, 0x62, 0x64, 0x38} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 6, 2, 1, 12, 0} +#define NXFONT_BITMAP_168 {0xcc, 0xcc} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {3, 17, 17, 1, 11, 0} +#define NXFONT_BITMAP_169 {0x7, 0xf0, 0x0, 0x1c, 0x1c, 0x0, 0x30, 0x6, 0x0, 0x61, 0xe3, 0x0, 0x47, 0x31, 0x0, 0xc4, 0x19, 0x80, 0x8c, 0x0, 0x80, 0x88, 0x0, 0x80, 0x88, 0x0, 0x80, 0x88, 0x0, 0x80, 0x8c, 0x0, 0x80, 0xc4, 0x19, 0x80, 0x47, 0x71, 0x0, 0x61, 0xc3, 0x0, 0x30, 0x6, 0x0, 0x1c, 0x1c, 0x0, 0x7, 0xf0, 0x0} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {1, 7, 9, 0, 11, 0} +#define NXFONT_BITMAP_170 {0x78, 0xcc, 0xc, 0x7c, 0xcc, 0xcc, 0x76, 0x0, 0xfe} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {2, 9, 10, 1, 17, 0} +#define NXFONT_BITMAP_171 {0x8, 0x80, 0x19, 0x80, 0x33, 0x0, 0x66, 0x0, 0xcc, 0x0, 0xcc, 0x0, 0x66, 0x0, 0x33, 0x0, 0x19, 0x80, 0x8, 0x80} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {2, 11, 7, 2, 20, 0} +#define NXFONT_BITMAP_172 {0xff, 0xe0, 0xff, 0xe0, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 6, 2, 0, 21, 0} +#define NXFONT_BITMAP_173 {0xfc, 0xfc} + +/* registered (174) */ +#define NXFONT_METRICS_174 {3, 17, 17, 1, 11, 0} +#define NXFONT_BITMAP_174 {0x7, 0xf0, 0x0, 0x1c, 0x1c, 0x0, 0x30, 0x6, 0x0, 0x67, 0xe3, 0x0, 0x42, 0x31, 0x0, 0xc2, 0x11, 0x80, 0x82, 0x10, 0x80, 0x82, 0x30, 0x80, 0x83, 0xe0, 0x80, 0x82, 0x40, 0x80, 0x82, 0x20, 0x80, 0xc2, 0x31, 0x80, 0x47, 0x19, 0x0, 0x60, 0x3, 0x0, 0x30, 0x6, 0x0, 0x1c, 0x1c, 0x0, 0x7, 0xf0, 0x0} + +/* macron (175) */ +#define NXFONT_METRICS_175 {1, 7, 2, 1, 12, 0} +#define NXFONT_BITMAP_175 {0xfe, 0xfe} + +/* degree (176) */ +#define NXFONT_METRICS_176 {1, 7, 7, 1, 11, 0} +#define NXFONT_BITMAP_176 {0x38, 0x44, 0x82, 0x82, 0x82, 0x44, 0x38} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {2, 10, 11, 2, 17, 0} +#define NXFONT_BITMAP_177 {0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {1, 6, 10, 0, 11, 0} +#define NXFONT_BITMAP_178 {0x38, 0x4c, 0x8c, 0xc, 0x8, 0x10, 0x30, 0x20, 0x44, 0xfc} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {1, 6, 10, 0, 11, 0} +#define NXFONT_BITMAP_179 {0x38, 0x4c, 0x8c, 0x8, 0x30, 0x8, 0xc, 0x8c, 0x88, 0x70} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 5, 4, 2, 11, 0} +#define NXFONT_BITMAP_180 {0x18, 0x38, 0x70, 0xc0} + +/* mu (181) */ +#define NXFONT_METRICS_181 {2, 11, 17, 1, 16, 0} +#define NXFONT_BITMAP_181 {0xe1, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x71, 0xc0, 0x7e, 0xc0, 0x5c, 0xe0, 0x40, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x40, 0x0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {2, 9, 21, 1, 11, 0} +#define NXFONT_BITMAP_182 {0x1f, 0x80, 0x39, 0x0, 0x79, 0x0, 0x79, 0x0, 0xf9, 0x0, 0xf9, 0x0, 0xf9, 0x0, 0x79, 0x0, 0x79, 0x0, 0x39, 0x0, 0x19, 0x0, 0x9, 0x0, 0x9, 0x0, 0x9, 0x0, 0x9, 0x0, 0x9, 0x0, 0x9, 0x0, 0x9, 0x0, 0x9, 0x0, 0x9, 0x0, 0x9, 0x0} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 2, 3, 2, 20, 0} +#define NXFONT_BITMAP_183 {0xc0, 0xc0, 0xc0} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 6, 6, 1, 28, 0} +#define NXFONT_BITMAP_184 {0x10, 0x30, 0x3c, 0xc, 0xcc, 0x78} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 5, 10, 1, 11, 0} +#define NXFONT_BITMAP_185 {0x20, 0x60, 0xa0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xf8} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {1, 7, 9, 0, 11, 0} +#define NXFONT_BITMAP_186 {0x38, 0x44, 0xc6, 0xc6, 0xc6, 0x44, 0x38, 0x0, 0xfe} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {2, 9, 10, 2, 17, 0} +#define NXFONT_BITMAP_187 {0x88, 0x0, 0xcc, 0x0, 0x66, 0x0, 0x33, 0x0, 0x19, 0x80, 0x19, 0x80, 0x33, 0x0, 0x66, 0x0, 0xcc, 0x0, 0x88, 0x0} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {2, 16, 17, 1, 11, 0} +#define NXFONT_BITMAP_188 {0x20, 0x18, 0x60, 0x18, 0xa0, 0x30, 0x20, 0x60, 0x20, 0x60, 0x20, 0xc0, 0x20, 0xc0, 0x21, 0x84, 0x23, 0xc, 0xfb, 0x1c, 0x6, 0x14, 0x6, 0x24, 0xc, 0x64, 0x18, 0x44, 0x18, 0xff, 0x30, 0x4, 0x30, 0x4} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {2, 15, 17, 1, 11, 0} +#define NXFONT_BITMAP_189 {0x20, 0x18, 0x60, 0x18, 0xa0, 0x30, 0x20, 0x60, 0x20, 0x60, 0x20, 0xc0, 0x20, 0xc0, 0x21, 0x9c, 0x23, 0x26, 0xfb, 0x46, 0x6, 0x6, 0x6, 0x4, 0xc, 0x8, 0x18, 0x18, 0x18, 0x10, 0x30, 0x22, 0x30, 0x7e} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {3, 17, 17, 0, 11, 0} +#define NXFONT_BITMAP_190 {0x38, 0xc, 0x0, 0x4c, 0xc, 0x0, 0x8c, 0x18, 0x0, 0x8, 0x30, 0x0, 0x30, 0x30, 0x0, 0x8, 0x60, 0x0, 0xc, 0x60, 0x0, 0x8c, 0xc2, 0x0, 0x89, 0x86, 0x0, 0x71, 0x8e, 0x0, 0x3, 0xa, 0x0, 0x3, 0x12, 0x0, 0x6, 0x32, 0x0, 0xc, 0x22, 0x0, 0xc, 0x7f, 0x80, 0x18, 0x2, 0x0, 0x18, 0x2, 0x0} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {1, 8, 17, 1, 16, 0} +#define NXFONT_BITMAP_191 {0xc, 0xc, 0x0, 0x0, 0x8, 0x8, 0x18, 0x18, 0x38, 0x30, 0x70, 0xe0, 0xc3, 0xc3, 0xc1, 0x63, 0x3e} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {3, 17, 22, 0, 6, 0} +#define NXFONT_BITMAP_192 {0xc, 0x0, 0x0, 0xe, 0x0, 0x0, 0x7, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0x60, 0x0, 0x2, 0x60, 0x0, 0x2, 0x30, 0x0, 0x6, 0x30, 0x0, 0x4, 0x30, 0x0, 0x4, 0x18, 0x0, 0xc, 0x18, 0x0, 0xf, 0xf8, 0x0, 0x8, 0xc, 0x0, 0x18, 0xc, 0x0, 0x10, 0xc, 0x0, 0x10, 0x6, 0x0, 0x30, 0x6, 0x0, 0xfc, 0x1f, 0x80} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {3, 17, 22, 0, 6, 0} +#define NXFONT_BITMAP_193 {0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x0, 0x70, 0x0, 0x0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0x60, 0x0, 0x2, 0x60, 0x0, 0x2, 0x30, 0x0, 0x6, 0x30, 0x0, 0x4, 0x30, 0x0, 0x4, 0x18, 0x0, 0xc, 0x18, 0x0, 0xf, 0xf8, 0x0, 0x8, 0xc, 0x0, 0x18, 0xc, 0x0, 0x10, 0xc, 0x0, 0x10, 0x6, 0x0, 0x30, 0x6, 0x0, 0xfc, 0x1f, 0x80} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {3, 17, 22, 0, 6, 0} +#define NXFONT_BITMAP_194 {0x1, 0x80, 0x0, 0x3, 0xc0, 0x0, 0x6, 0x60, 0x0, 0x4, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0x60, 0x0, 0x2, 0x60, 0x0, 0x2, 0x30, 0x0, 0x6, 0x30, 0x0, 0x4, 0x30, 0x0, 0x4, 0x18, 0x0, 0xc, 0x18, 0x0, 0xf, 0xf8, 0x0, 0x8, 0xc, 0x0, 0x18, 0xc, 0x0, 0x10, 0xc, 0x0, 0x10, 0x6, 0x0, 0x30, 0x6, 0x0, 0xfc, 0x1f, 0x80} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {3, 17, 21, 0, 7, 0} +#define NXFONT_BITMAP_195 {0x3, 0x20, 0x0, 0x7, 0xe0, 0x0, 0x4, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0x60, 0x0, 0x2, 0x60, 0x0, 0x2, 0x30, 0x0, 0x6, 0x30, 0x0, 0x4, 0x30, 0x0, 0x4, 0x18, 0x0, 0xc, 0x18, 0x0, 0xf, 0xf8, 0x0, 0x8, 0xc, 0x0, 0x18, 0xc, 0x0, 0x10, 0xc, 0x0, 0x10, 0x6, 0x0, 0x30, 0x6, 0x0, 0xfc, 0x1f, 0x80} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {3, 17, 21, 0, 7, 0} +#define NXFONT_BITMAP_196 {0x6, 0x60, 0x0, 0x6, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0x60, 0x0, 0x2, 0x60, 0x0, 0x2, 0x30, 0x0, 0x6, 0x30, 0x0, 0x4, 0x30, 0x0, 0x4, 0x18, 0x0, 0xc, 0x18, 0x0, 0xf, 0xf8, 0x0, 0x8, 0xc, 0x0, 0x18, 0xc, 0x0, 0x10, 0xc, 0x0, 0x10, 0x6, 0x0, 0x30, 0x6, 0x0, 0xfc, 0x1f, 0x80} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {3, 17, 23, 0, 5, 0} +#define NXFONT_BITMAP_197 {0x1, 0xc0, 0x0, 0x2, 0x20, 0x0, 0x2, 0x20, 0x0, 0x2, 0x20, 0x0, 0x1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0x60, 0x0, 0x2, 0x60, 0x0, 0x2, 0x30, 0x0, 0x6, 0x30, 0x0, 0x4, 0x30, 0x0, 0x4, 0x18, 0x0, 0xc, 0x18, 0x0, 0xf, 0xf8, 0x0, 0x8, 0xc, 0x0, 0x18, 0xc, 0x0, 0x10, 0xc, 0x0, 0x10, 0x6, 0x0, 0x30, 0x6, 0x0, 0xfc, 0x1f, 0x80} + +/* AE (198) */ +#define NXFONT_METRICS_198 {3, 21, 17, 0, 11, 0} +#define NXFONT_BITMAP_198 {0x3, 0xff, 0xf0, 0x0, 0xf0, 0x30, 0x1, 0xb0, 0x10, 0x1, 0x30, 0x10, 0x3, 0x30, 0x0, 0x2, 0x30, 0x0, 0x6, 0x30, 0x40, 0x4, 0x30, 0x40, 0x4, 0x3f, 0xc0, 0xc, 0x30, 0x40, 0xf, 0xf0, 0x40, 0x8, 0x30, 0x0, 0x18, 0x30, 0x0, 0x10, 0x30, 0x8, 0x30, 0x30, 0x8, 0x20, 0x30, 0x18, 0xf8, 0xff, 0xf8} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {2, 14, 23, 1, 11, 0} +#define NXFONT_BITMAP_199 {0x7, 0xe4, 0x1c, 0x3c, 0x38, 0xc, 0x60, 0x4, 0x60, 0x4, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0x60, 0x0, 0x60, 0x4, 0x38, 0x8, 0x1e, 0x38, 0x7, 0xe0, 0x1, 0x0, 0x3, 0x0, 0x3, 0xc0, 0x0, 0xc0, 0xc, 0xc0, 0x7, 0x80} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {2, 13, 22, 1, 6, 0} +#define NXFONT_BITMAP_200 {0x18, 0x0, 0x1c, 0x0, 0xe, 0x0, 0x3, 0x0, 0x0, 0x0, 0xff, 0xf0, 0x30, 0x30, 0x30, 0x10, 0x30, 0x10, 0x30, 0x0, 0x30, 0x0, 0x30, 0x40, 0x30, 0x40, 0x3f, 0xc0, 0x30, 0x40, 0x30, 0x40, 0x30, 0x0, 0x30, 0x0, 0x30, 0x8, 0x30, 0x8, 0x30, 0x18, 0xff, 0xf8} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {2, 13, 22, 1, 6, 0} +#define NXFONT_BITMAP_201 {0x0, 0x60, 0x0, 0xe0, 0x1, 0xc0, 0x3, 0x0, 0x0, 0x0, 0xff, 0xf0, 0x30, 0x30, 0x30, 0x10, 0x30, 0x10, 0x30, 0x0, 0x30, 0x0, 0x30, 0x40, 0x30, 0x40, 0x3f, 0xc0, 0x30, 0x40, 0x30, 0x40, 0x30, 0x0, 0x30, 0x0, 0x30, 0x8, 0x30, 0x8, 0x30, 0x18, 0xff, 0xf8} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {2, 13, 22, 1, 6, 0} +#define NXFONT_BITMAP_202 {0x6, 0x0, 0xf, 0x0, 0x19, 0x80, 0x10, 0x80, 0x0, 0x0, 0xff, 0xf0, 0x30, 0x30, 0x30, 0x10, 0x30, 0x10, 0x30, 0x0, 0x30, 0x0, 0x30, 0x40, 0x30, 0x40, 0x3f, 0xc0, 0x30, 0x40, 0x30, 0x40, 0x30, 0x0, 0x30, 0x0, 0x30, 0x8, 0x30, 0x8, 0x30, 0x18, 0xff, 0xf8} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {2, 13, 21, 1, 7, 0} +#define NXFONT_BITMAP_203 {0x19, 0x80, 0x19, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf0, 0x30, 0x30, 0x30, 0x10, 0x30, 0x10, 0x30, 0x0, 0x30, 0x0, 0x30, 0x40, 0x30, 0x40, 0x3f, 0xc0, 0x30, 0x40, 0x30, 0x40, 0x30, 0x0, 0x30, 0x0, 0x30, 0x8, 0x30, 0x8, 0x30, 0x18, 0xff, 0xf8} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {1, 7, 22, 0, 6, 0} +#define NXFONT_BITMAP_204 {0xc0, 0xe0, 0x70, 0x18, 0x0, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {1, 7, 22, 1, 6, 0} +#define NXFONT_BITMAP_205 {0x6, 0xe, 0x1c, 0x30, 0x0, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc} + +/* Icircumflex (206) */ +#define NXFONT_METRICS_206 {1, 6, 22, 1, 6, 0} +#define NXFONT_BITMAP_206 {0x30, 0x78, 0xcc, 0x84, 0x0, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {1, 6, 21, 1, 7, 0} +#define NXFONT_BITMAP_207 {0xcc, 0xcc, 0x0, 0x0, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc} + +/* Eth (208) */ +#define NXFONT_METRICS_208 {2, 16, 17, 0, 11, 0} +#define NXFONT_BITMAP_208 {0x7f, 0xe0, 0x18, 0x38, 0x18, 0x1c, 0x18, 0x6, 0x18, 0x6, 0x18, 0x3, 0x18, 0x3, 0xff, 0x3, 0xff, 0x3, 0x18, 0x3, 0x18, 0x3, 0x18, 0x3, 0x18, 0x6, 0x18, 0x6, 0x18, 0x1c, 0x18, 0x38, 0x7f, 0xe0} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {2, 16, 21, 1, 7, 0} +#define NXFONT_BITMAP_209 {0x3, 0x20, 0x7, 0xe0, 0x4, 0xc0, 0x0, 0x0, 0xf0, 0x1f, 0x30, 0x4, 0x38, 0x4, 0x38, 0x4, 0x2c, 0x4, 0x26, 0x4, 0x26, 0x4, 0x23, 0x4, 0x21, 0x84, 0x21, 0x84, 0x20, 0xc4, 0x20, 0x64, 0x20, 0x64, 0x20, 0x34, 0x20, 0x1c, 0x20, 0x1c, 0xf8, 0xc} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {2, 16, 22, 1, 6, 0} +#define NXFONT_BITMAP_210 {0xc, 0x0, 0xe, 0x0, 0x7, 0x0, 0x1, 0x80, 0x0, 0x0, 0x7, 0xe0, 0x1c, 0x38, 0x38, 0x1c, 0x60, 0x6, 0x60, 0x6, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0x60, 0x6, 0x60, 0x6, 0x38, 0x1c, 0x1c, 0x38, 0x7, 0xe0} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {2, 16, 22, 1, 6, 0} +#define NXFONT_BITMAP_211 {0x0, 0x30, 0x0, 0x70, 0x0, 0xe0, 0x1, 0x80, 0x0, 0x0, 0x7, 0xe0, 0x1c, 0x38, 0x38, 0x1c, 0x60, 0x6, 0x60, 0x6, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0x60, 0x6, 0x60, 0x6, 0x38, 0x1c, 0x1c, 0x38, 0x7, 0xe0} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {2, 16, 22, 1, 6, 0} +#define NXFONT_BITMAP_212 {0x1, 0x80, 0x3, 0xc0, 0x6, 0x60, 0x4, 0x20, 0x0, 0x0, 0x7, 0xe0, 0x1c, 0x38, 0x38, 0x1c, 0x60, 0x6, 0x60, 0x6, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0x60, 0x6, 0x60, 0x6, 0x38, 0x1c, 0x1c, 0x38, 0x7, 0xe0} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {2, 16, 21, 1, 7, 0} +#define NXFONT_BITMAP_213 {0x3, 0x20, 0x7, 0xe0, 0x4, 0xc0, 0x0, 0x0, 0x7, 0xe0, 0x1c, 0x38, 0x38, 0x1c, 0x60, 0x6, 0x60, 0x6, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0x60, 0x6, 0x60, 0x6, 0x38, 0x1c, 0x1c, 0x38, 0x7, 0xe0} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {2, 16, 21, 1, 7, 0} +#define NXFONT_BITMAP_214 {0x6, 0x60, 0x6, 0x60, 0x0, 0x0, 0x0, 0x0, 0x7, 0xe0, 0x1c, 0x38, 0x38, 0x1c, 0x60, 0x6, 0x60, 0x6, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0x60, 0x6, 0x60, 0x6, 0x38, 0x1c, 0x1c, 0x38, 0x7, 0xe0} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {2, 10, 9, 1, 18, 0} +#define NXFONT_BITMAP_215 {0xc0, 0xc0, 0x61, 0x80, 0x33, 0x0, 0x1e, 0x0, 0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x61, 0x80, 0xc0, 0xc0} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {2, 16, 19, 1, 10, 0} +#define NXFONT_BITMAP_216 {0x0, 0x4, 0x7, 0xe4, 0x1c, 0x38, 0x38, 0x1c, 0x60, 0x26, 0x60, 0x46, 0xc0, 0x43, 0xc0, 0x83, 0xc0, 0x83, 0xc1, 0x3, 0xc1, 0x3, 0xc2, 0x3, 0xc2, 0x3, 0x64, 0x6, 0x68, 0x6, 0x38, 0x1c, 0x1c, 0x38, 0x27, 0xe0, 0x20, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {2, 16, 22, 1, 6, 0} +#define NXFONT_BITMAP_217 {0x6, 0x0, 0x7, 0x0, 0x3, 0x80, 0x0, 0xc0, 0x0, 0x0, 0xfc, 0x1f, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x8, 0x18, 0x8, 0x1c, 0x30, 0x7, 0xe0} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {2, 16, 22, 1, 6, 0} +#define NXFONT_BITMAP_218 {0x0, 0x30, 0x0, 0x70, 0x0, 0xe0, 0x1, 0x80, 0x0, 0x0, 0xfc, 0x1f, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x8, 0x18, 0x8, 0x1c, 0x30, 0x7, 0xe0} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {2, 16, 22, 1, 6, 0} +#define NXFONT_BITMAP_219 {0x1, 0x80, 0x3, 0xc0, 0x6, 0x60, 0x4, 0x20, 0x0, 0x0, 0xfc, 0x1f, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x8, 0x18, 0x8, 0x1c, 0x30, 0x7, 0xe0} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {2, 16, 21, 1, 7, 0} +#define NXFONT_BITMAP_220 {0x6, 0x60, 0x6, 0x60, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x1f, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x30, 0x8, 0x18, 0x8, 0x1c, 0x30, 0x7, 0xe0} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {2, 16, 22, 1, 6, 0} +#define NXFONT_BITMAP_221 {0x0, 0x30, 0x0, 0x70, 0x0, 0xe0, 0x1, 0x80, 0x0, 0x0, 0xfc, 0x3f, 0x30, 0xc, 0x38, 0x8, 0x18, 0x18, 0x1c, 0x10, 0xc, 0x30, 0x6, 0x20, 0x6, 0x60, 0x3, 0x40, 0x3, 0xc0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x7, 0xe0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {2, 13, 17, 1, 11, 0} +#define NXFONT_BITMAP_222 {0xfc, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x3f, 0xc0, 0x30, 0x70, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x30, 0x70, 0x3f, 0xc0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0xfc, 0x0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_223 {0x1e, 0x0, 0x33, 0x0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x63, 0x0, 0x6c, 0x0, 0x67, 0x0, 0x63, 0x80, 0x61, 0x80, 0x61, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x6c, 0xc0, 0x6c, 0x80, 0xe7, 0x0} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {2, 9, 17, 1, 11, 0} +#define NXFONT_BITMAP_224 {0x60, 0x0, 0x70, 0x0, 0x38, 0x0, 0xc, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x67, 0x0, 0x63, 0x0, 0x3, 0x0, 0xf, 0x0, 0x3b, 0x0, 0x63, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xc7, 0x0, 0xfb, 0x0, 0x71, 0x80} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {2, 9, 17, 1, 11, 0} +#define NXFONT_BITMAP_225 {0x3, 0x0, 0x7, 0x0, 0xe, 0x0, 0x18, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x67, 0x0, 0x63, 0x0, 0x3, 0x0, 0xf, 0x0, 0x3b, 0x0, 0x63, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xc7, 0x0, 0xfb, 0x0, 0x71, 0x80} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {2, 9, 17, 1, 11, 0} +#define NXFONT_BITMAP_226 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x21, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x67, 0x0, 0x63, 0x0, 0x3, 0x0, 0xf, 0x0, 0x3b, 0x0, 0x63, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xc7, 0x0, 0xfb, 0x0, 0x71, 0x80} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {2, 9, 16, 1, 12, 0} +#define NXFONT_BITMAP_227 {0x32, 0x0, 0x7e, 0x0, 0x4c, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x67, 0x0, 0x63, 0x0, 0x3, 0x0, 0xf, 0x0, 0x3b, 0x0, 0x63, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xc7, 0x0, 0xfb, 0x0, 0x71, 0x80} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {2, 9, 16, 1, 12, 0} +#define NXFONT_BITMAP_228 {0x66, 0x0, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x67, 0x0, 0x63, 0x0, 0x3, 0x0, 0xf, 0x0, 0x3b, 0x0, 0x63, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xc7, 0x0, 0xfb, 0x0, 0x71, 0x80} + +/* aring (229) */ +#define NXFONT_METRICS_229 {2, 9, 18, 1, 10, 0} +#define NXFONT_BITMAP_229 {0x1c, 0x0, 0x22, 0x0, 0x22, 0x0, 0x22, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x67, 0x0, 0x63, 0x0, 0x3, 0x0, 0xf, 0x0, 0x3b, 0x0, 0x63, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xc7, 0x0, 0xfb, 0x0, 0x71, 0x80} + +/* ae (230) */ +#define NXFONT_METRICS_230 {2, 14, 12, 1, 16, 0} +#define NXFONT_BITMAP_230 {0x3c, 0xf0, 0x67, 0x98, 0x63, 0xc, 0x3, 0xc, 0xf, 0xfc, 0x3b, 0x0, 0x63, 0x0, 0xc3, 0x0, 0xc3, 0x0, 0xc7, 0x84, 0xfb, 0xf8, 0x70, 0xf0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {2, 9, 18, 1, 16, 0} +#define NXFONT_BITMAP_231 {0x1f, 0x0, 0x63, 0x80, 0x41, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x70, 0x80, 0x7f, 0x0, 0x1e, 0x0, 0x8, 0x0, 0x18, 0x0, 0x1e, 0x0, 0x6, 0x0, 0x66, 0x0, 0x3c, 0x0} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {2, 9, 17, 1, 11, 0} +#define NXFONT_BITMAP_232 {0x60, 0x0, 0x70, 0x0, 0x38, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x63, 0x0, 0x41, 0x80, 0xc1, 0x80, 0xff, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x70, 0x80, 0x7f, 0x0, 0x1e, 0x0} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {2, 9, 17, 1, 11, 0} +#define NXFONT_BITMAP_233 {0x3, 0x0, 0x7, 0x0, 0xe, 0x0, 0x18, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x63, 0x0, 0x41, 0x80, 0xc1, 0x80, 0xff, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x70, 0x80, 0x7f, 0x0, 0x1e, 0x0} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {2, 9, 17, 1, 11, 0} +#define NXFONT_BITMAP_234 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x21, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x63, 0x0, 0x41, 0x80, 0xc1, 0x80, 0xff, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x70, 0x80, 0x7f, 0x0, 0x1e, 0x0} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {2, 9, 16, 1, 12, 0} +#define NXFONT_BITMAP_235 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x63, 0x0, 0x41, 0x80, 0xc1, 0x80, 0xff, 0x80, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x70, 0x80, 0x7f, 0x0, 0x1e, 0x0} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 6, 17, 0, 11, 0} +#define NXFONT_BITMAP_236 {0xc0, 0xe0, 0x70, 0x18, 0x0, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 5, 17, 1, 11, 0} +#define NXFONT_BITMAP_237 {0x18, 0x38, 0x70, 0xc0, 0x0, 0x60, 0xe0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0} + +/* icircumflex (238) */ +#define NXFONT_METRICS_238 {1, 6, 17, 0, 11, 0} +#define NXFONT_BITMAP_238 {0x30, 0x78, 0xcc, 0x84, 0x0, 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 6, 16, 0, 12, 0} +#define NXFONT_BITMAP_239 {0xcc, 0xcc, 0x0, 0x0, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78} + +/* eth (240) */ +#define NXFONT_METRICS_240 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_240 {0xc0, 0x0, 0x71, 0x80, 0x1e, 0x0, 0x3c, 0x0, 0xc6, 0x0, 0x1f, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {2, 11, 16, 1, 12, 0} +#define NXFONT_BITMAP_241 {0x19, 0x0, 0x3f, 0x0, 0x26, 0x0, 0x0, 0x0, 0x67, 0x0, 0xef, 0x80, 0x71, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0xf1, 0xe0} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_242 {0x60, 0x0, 0x70, 0x0, 0x38, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_243 {0x3, 0x0, 0x7, 0x0, 0xe, 0x0, 0x18, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {2, 10, 17, 1, 11, 0} +#define NXFONT_BITMAP_244 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x21, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {2, 10, 16, 1, 12, 0} +#define NXFONT_BITMAP_245 {0x19, 0x0, 0x3f, 0x0, 0x26, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {2, 10, 16, 1, 12, 0} +#define NXFONT_BITMAP_246 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x73, 0x80, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x1e, 0x0} + +/* divide (247) */ +#define NXFONT_METRICS_247 {2, 10, 10, 1, 17, 0} +#define NXFONT_BITMAP_247 {0xc, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {2, 10, 14, 1, 15, 0} +#define NXFONT_BITMAP_248 {0x0, 0xc0, 0x1e, 0xc0, 0x73, 0x80, 0x63, 0x80, 0xc6, 0xc0, 0xc4, 0xc0, 0xcc, 0xc0, 0xc8, 0xc0, 0xd8, 0xc0, 0xd0, 0xc0, 0x71, 0x80, 0x73, 0x80, 0xde, 0x0, 0xc0, 0x0} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {2, 11, 17, 1, 11, 0} +#define NXFONT_BITMAP_249 {0x60, 0x0, 0x70, 0x0, 0x38, 0x0, 0xc, 0x0, 0x0, 0x0, 0xe1, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x71, 0xc0, 0x3e, 0xc0, 0x1c, 0xe0} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {2, 11, 17, 1, 11, 0} +#define NXFONT_BITMAP_250 {0x1, 0x80, 0x3, 0x80, 0x7, 0x0, 0xc, 0x0, 0x0, 0x0, 0xe1, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x71, 0xc0, 0x3e, 0xc0, 0x1c, 0xe0} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {2, 11, 17, 1, 11, 0} +#define NXFONT_BITMAP_251 {0xc, 0x0, 0x1e, 0x0, 0x33, 0x0, 0x21, 0x0, 0x0, 0x0, 0xe1, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x71, 0xc0, 0x3e, 0xc0, 0x1c, 0xe0} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {2, 11, 16, 1, 12, 0} +#define NXFONT_BITMAP_252 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe1, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x71, 0xc0, 0x3e, 0xc0, 0x1c, 0xe0} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {2, 11, 22, 0, 11, 0} +#define NXFONT_BITMAP_253 {0x1, 0x80, 0x3, 0x80, 0x7, 0x0, 0xc, 0x0, 0x0, 0x0, 0xf1, 0xe0, 0x60, 0xc0, 0x60, 0x80, 0x30, 0x80, 0x30, 0x80, 0x31, 0x0, 0x19, 0x0, 0x19, 0x0, 0x1a, 0x0, 0xe, 0x0, 0xe, 0x0, 0x4, 0x0, 0xc, 0x0, 0x8, 0x0, 0x18, 0x0, 0xf0, 0x0, 0xe0, 0x0} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {2, 10, 22, 1, 11, 0} +#define NXFONT_BITMAP_254 {0x60, 0x0, 0xe0, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x6e, 0x0, 0x73, 0x80, 0x61, 0x80, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x61, 0x80, 0x73, 0x80, 0x6e, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0xf0, 0x0} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {2, 11, 21, 0, 12, 0} +#define NXFONT_BITMAP_255 {0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf1, 0xe0, 0x60, 0xc0, 0x60, 0x80, 0x30, 0x80, 0x30, 0x80, 0x31, 0x0, 0x19, 0x0, 0x19, 0x0, 0x1a, 0x0, 0xe, 0x0, 0xe, 0x0, 0x4, 0x0, 0xc, 0x0, 0x8, 0x0, 0x18, 0x0, 0xf0, 0x0, 0xe0, 0x0} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SERIF29X37_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_serif38x48.h b/nuttx/graphics/nxfonts/nxfonts_serif38x48.h new file mode 100644 index 0000000000..68a9d723e2 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_serif38x48.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_serif38x48.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Jose Pablo Carballo Gomez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SERIF38X48_H +#define __GRAPHICS_NXFONTS_NXFONTS_SERIF38X48_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SERIF38X48 + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 48 +#define NXFONT_MAXWIDTH 38 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 8 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 4, 23, 3, 14, 0} +#define NXFONT_BITMAP_33 {0x60, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x0, 0x0, 0x60, 0xf0, 0xf0, 0x60} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {2, 9, 7, 2, 14, 0} +#define NXFONT_BITMAP_34 {0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x41, 0x0, 0x41, 0x0, 0x41, 0x0} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {2, 16, 23, 0, 14, 0} +#define NXFONT_BITMAP_35 {0x6, 0x18, 0x6, 0x18, 0x6, 0x18, 0x6, 0x18, 0x6, 0x18, 0x6, 0x18, 0x6, 0x18, 0x6, 0x18, 0x7f, 0xff, 0x7f, 0xff, 0xc, 0x30, 0xc, 0x30, 0xc, 0x30, 0xc, 0x30, 0xff, 0xfe, 0xff, 0xfe, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {2, 13, 28, 2, 12, 0} +#define NXFONT_BITMAP_36 {0x2, 0x0, 0x2, 0x0, 0xf, 0xc0, 0x3a, 0x70, 0x32, 0x38, 0x62, 0x18, 0x62, 0x8, 0x62, 0x8, 0x72, 0x0, 0x7a, 0x0, 0x3e, 0x0, 0x3f, 0x0, 0x1f, 0x80, 0x7, 0xc0, 0x3, 0xe0, 0x2, 0xf0, 0x2, 0x70, 0x2, 0x38, 0x2, 0x38, 0x82, 0x18, 0x82, 0x18, 0xc2, 0x38, 0xe2, 0x30, 0x72, 0x60, 0x1f, 0xc0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0} + +/* percent (37) */ +#define NXFONT_METRICS_37 {3, 23, 23, 2, 14, 0} +#define NXFONT_BITMAP_37 {0xf, 0x0, 0x40, 0x1d, 0x83, 0xc0, 0x38, 0xfc, 0x80, 0x70, 0x41, 0x80, 0x70, 0x43, 0x0, 0xe0, 0x42, 0x0, 0xe0, 0x46, 0x0, 0xe0, 0xc4, 0x0, 0xc0, 0x8c, 0x0, 0xc1, 0x88, 0x0, 0xc1, 0x18, 0x78, 0x66, 0x10, 0xec, 0x3c, 0x31, 0xc6, 0x0, 0x63, 0x82, 0x0, 0x43, 0x82, 0x0, 0xc7, 0x2, 0x0, 0x87, 0x2, 0x1, 0x87, 0x6, 0x1, 0x6, 0x4, 0x3, 0x6, 0xc, 0x2, 0x6, 0x8, 0x6, 0x3, 0x30, 0x4, 0x1, 0xe0} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {3, 23, 23, 2, 14, 0} +#define NXFONT_BITMAP_38 {0x0, 0xf8, 0x0, 0x1, 0x8c, 0x0, 0x3, 0xe, 0x0, 0x3, 0x6, 0x0, 0x7, 0x6, 0x0, 0x7, 0x6, 0x0, 0x7, 0xc, 0x0, 0x7, 0x8c, 0x0, 0x3, 0x98, 0x0, 0x3, 0xf1, 0xfc, 0x3, 0xc0, 0x70, 0x7, 0xc0, 0x60, 0x1d, 0xe0, 0x40, 0x38, 0xf0, 0xc0, 0x70, 0x70, 0x80, 0x60, 0x79, 0x80, 0xe0, 0x3f, 0x0, 0xe0, 0x1e, 0x0, 0xe0, 0xf, 0x0, 0xf0, 0x1f, 0x82, 0x78, 0x33, 0xfc, 0x7f, 0xe1, 0xf8, 0x1f, 0x80, 0xf0} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 3, 8, 1, 14, 0} +#define NXFONT_BITMAP_39 {0xe0, 0xe0, 0xe0, 0xe0, 0x40, 0x40, 0x40, 0x40} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 8, 28, 2, 14, 0} +#define NXFONT_BITMAP_40 {0x3, 0x6, 0xc, 0x18, 0x38, 0x30, 0x70, 0x70, 0x60, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x60, 0x70, 0x70, 0x30, 0x38, 0x18, 0xc, 0x6, 0x3} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 8, 28, 1, 14, 0} +#define NXFONT_BITMAP_41 {0xc0, 0x60, 0x30, 0x18, 0x1c, 0xc, 0xe, 0xe, 0x6, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0xe, 0xe, 0xc, 0x1c, 0x18, 0x30, 0x60, 0xc0} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {2, 12, 13, 2, 14, 0} +#define NXFONT_BITMAP_42 {0x6, 0x0, 0xf, 0x0, 0x6, 0x0, 0xc6, 0x30, 0xf6, 0xf0, 0x76, 0xe0, 0xf, 0x0, 0x76, 0xe0, 0xf6, 0xf0, 0xc6, 0x30, 0x6, 0x0, 0xf, 0x0, 0x6, 0x0} + +/* plus (43) */ +#define NXFONT_METRICS_43 {2, 16, 16, 1, 20, 0} +#define NXFONT_BITMAP_43 {0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0xff, 0xff, 0xff, 0xff, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 4, 7, 2, 33, 0} +#define NXFONT_BITMAP_44 {0x60, 0xf0, 0xf0, 0x70, 0x10, 0x20, 0x40} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 8, 2, 1, 28, 0} +#define NXFONT_BITMAP_45 {0xff, 0xff} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 4, 4, 2, 33, 0} +#define NXFONT_BITMAP_46 {0x60, 0xf0, 0xf0, 0x60} + +/* slash (47) */ +#define NXFONT_METRICS_47 {2, 10, 26, 0, 14, 0} +#define NXFONT_BITMAP_47 {0x0, 0xc0, 0x0, 0xc0, 0x1, 0x80, 0x1, 0x80, 0x3, 0x80, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0xe, 0x0, 0xc, 0x0, 0xc, 0x0, 0x1c, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x70, 0x0, 0x60, 0x0, 0x60, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* zero (48) */ +#define NXFONT_METRICS_48 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_48 {0x7, 0x80, 0x1c, 0xe0, 0x38, 0x70, 0x30, 0x30, 0x70, 0x38, 0x70, 0x38, 0x60, 0x18, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x18, 0x70, 0x38, 0x70, 0x38, 0x30, 0x30, 0x38, 0x70, 0x1c, 0xe0, 0x7, 0x80} + +/* one (49) */ +#define NXFONT_METRICS_49 {2, 9, 23, 4, 14, 0} +#define NXFONT_BITMAP_49 {0xc, 0x0, 0x1c, 0x0, 0x7c, 0x0, 0xdc, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0xff, 0x80} + +/* two (50) */ +#define NXFONT_METRICS_50 {2, 15, 23, 0, 14, 0} +#define NXFONT_BITMAP_50 {0x7, 0xe0, 0xf, 0xf0, 0x1c, 0xf8, 0x30, 0x3c, 0x20, 0x3c, 0x60, 0x1c, 0x40, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x18, 0x0, 0x38, 0x0, 0x30, 0x0, 0x60, 0x0, 0x60, 0x0, 0xc0, 0x1, 0x80, 0x3, 0x0, 0x6, 0x0, 0xc, 0x2, 0x18, 0x6, 0x3f, 0xfc, 0x7f, 0xf8, 0xff, 0xf8} + +/* three (51) */ +#define NXFONT_METRICS_51 {2, 12, 23, 2, 14, 0} +#define NXFONT_BITMAP_51 {0xf, 0x80, 0x3f, 0xc0, 0x61, 0xe0, 0xc0, 0xe0, 0x80, 0xe0, 0x0, 0xe0, 0x0, 0xc0, 0x0, 0xc0, 0x1, 0x80, 0x3, 0x0, 0x7, 0xc0, 0x1f, 0xe0, 0x1, 0xf0, 0x0, 0x70, 0x0, 0x70, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x70, 0x0, 0x60, 0xe0, 0xc0, 0xf3, 0x80, 0x7f, 0x0} + +/* four (52) */ +#define NXFONT_METRICS_52 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_52 {0x0, 0x60, 0x0, 0xe0, 0x0, 0xe0, 0x1, 0xe0, 0x1, 0x60, 0x3, 0x60, 0x6, 0x60, 0x4, 0x60, 0xc, 0x60, 0x18, 0x60, 0x10, 0x60, 0x30, 0x60, 0x60, 0x60, 0x40, 0x60, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60} + +/* five (53) */ +#define NXFONT_METRICS_53 {2, 13, 23, 1, 14, 0} +#define NXFONT_BITMAP_53 {0xf, 0xf8, 0x1f, 0xf0, 0x1f, 0xe0, 0x10, 0x0, 0x30, 0x0, 0x20, 0x0, 0x7e, 0x0, 0x7f, 0x80, 0x7f, 0xc0, 0x7, 0xe0, 0x1, 0xe0, 0x0, 0xf0, 0x0, 0x70, 0x0, 0x70, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x60, 0x0, 0x60, 0xe0, 0xc0, 0xf3, 0x80, 0x7e, 0x0} + +/* six (54) */ +#define NXFONT_METRICS_54 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_54 {0x0, 0x78, 0x1, 0xc0, 0x3, 0x80, 0xf, 0x0, 0x1e, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x78, 0x0, 0x70, 0x0, 0x73, 0xc0, 0xf7, 0xf0, 0xf8, 0x78, 0xe0, 0x38, 0xe0, 0x3c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0x70, 0x1c, 0x70, 0x18, 0x38, 0x38, 0x1c, 0x60, 0x7, 0xc0} + +/* seven (55) */ +#define NXFONT_METRICS_55 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_55 {0x3f, 0xfc, 0x7f, 0xfc, 0x60, 0x18, 0xc0, 0x18, 0x80, 0x38, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0xe0, 0x0, 0xc0, 0x0, 0xc0, 0x1, 0xc0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x7, 0x0, 0x6, 0x0} + +/* eight (56) */ +#define NXFONT_METRICS_56 {2, 13, 23, 2, 14, 0} +#define NXFONT_BITMAP_56 {0x1f, 0x80, 0x38, 0xe0, 0x70, 0x70, 0xe0, 0x30, 0xe0, 0x30, 0xe0, 0x30, 0xe0, 0x70, 0xf0, 0x60, 0x7c, 0xc0, 0x3f, 0x0, 0x1f, 0x80, 0xf, 0xc0, 0x1b, 0xe0, 0x71, 0xf0, 0x60, 0xf0, 0xe0, 0x78, 0xc0, 0x78, 0xc0, 0x38, 0xc0, 0x38, 0xe0, 0x38, 0x60, 0x70, 0x70, 0xe0, 0x1f, 0xc0} + +/* nine (57) */ +#define NXFONT_METRICS_57 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_57 {0x7, 0x80, 0x18, 0xe0, 0x30, 0x70, 0x70, 0x38, 0x60, 0x38, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xf0, 0x1c, 0x70, 0x1c, 0x78, 0x3c, 0x3e, 0xfc, 0xf, 0xb8, 0x0, 0x38, 0x0, 0x70, 0x0, 0x70, 0x0, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0xf, 0x0, 0x78, 0x0} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 4, 15, 2, 22, 0} +#define NXFONT_BITMAP_58 {0x60, 0xf0, 0xf0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0xf0, 0xf0, 0x60} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 4, 18, 2, 22, 0} +#define NXFONT_BITMAP_59 {0x60, 0xf0, 0xf0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0xf0, 0xf0, 0x70, 0x10, 0x20, 0x40} + +/* less (60) */ +#define NXFONT_METRICS_60 {2, 16, 18, 1, 19, 0} +#define NXFONT_BITMAP_60 {0x0, 0x1, 0x0, 0x7, 0x0, 0x1f, 0x0, 0x7c, 0x1, 0xf0, 0x7, 0xc0, 0x1f, 0x0, 0x7c, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0x7c, 0x0, 0x1f, 0x0, 0x7, 0xc0, 0x1, 0xf0, 0x0, 0x7c, 0x0, 0x1f, 0x0, 0x7, 0x0, 0x1} + +/* equal (61) */ +#define NXFONT_METRICS_61 {2, 16, 9, 1, 24, 0} +#define NXFONT_BITMAP_61 {0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff} + +/* greater (62) */ +#define NXFONT_METRICS_62 {2, 16, 18, 2, 19, 0} +#define NXFONT_BITMAP_62 {0x80, 0x0, 0xe0, 0x0, 0xf8, 0x0, 0x3e, 0x0, 0xf, 0x80, 0x3, 0xe0, 0x0, 0xf8, 0x0, 0x3e, 0x0, 0xf, 0x0, 0xf, 0x0, 0x3e, 0x0, 0xf8, 0x3, 0xe0, 0xf, 0x80, 0x3e, 0x0, 0xf8, 0x0, 0xe0, 0x0, 0x80, 0x0} + +/* question (63) */ +#define NXFONT_METRICS_63 {2, 11, 23, 2, 14, 0} +#define NXFONT_BITMAP_63 {0x1f, 0x0, 0x73, 0x80, 0xc1, 0xc0, 0xc1, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0x60, 0xe0, 0x1, 0xc0, 0x1, 0xc0, 0x1, 0x80, 0x3, 0x80, 0x3, 0x0, 0x6, 0x0, 0x4, 0x0, 0xc, 0x0, 0x8, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0x1e, 0x0, 0x1e, 0x0, 0xc, 0x0} + +/* at (64) */ +#define NXFONT_METRICS_64 {4, 27, 28, 2, 14, 0} +#define NXFONT_BITMAP_64 {0x0, 0x1f, 0xf0, 0x0, 0x0, 0xf8, 0x3c, 0x0, 0x1, 0xe0, 0x6, 0x0, 0x7, 0x80, 0x3, 0x0, 0xe, 0x0, 0x1, 0x80, 0x1c, 0x0, 0x0, 0xc0, 0x1c, 0x0, 0x0, 0xc0, 0x38, 0x7, 0x8c, 0x60, 0x70, 0x1f, 0x5c, 0x60, 0x70, 0x1c, 0x7c, 0x20, 0x70, 0x38, 0x38, 0x20, 0xe0, 0x70, 0x38, 0x20, 0xe0, 0x70, 0x30, 0x20, 0xe0, 0x70, 0x70, 0x20, 0xe0, 0xe0, 0x70, 0x60, 0xe0, 0xe0, 0x70, 0x40, 0xe0, 0xe0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe0, 0x80, 0x70, 0xe1, 0xe1, 0x80, 0x70, 0x77, 0x73, 0x0, 0x70, 0x3c, 0x3e, 0x0, 0x38, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x7, 0x80, 0x6, 0x0, 0x1, 0xf0, 0x3c, 0x0, 0x0, 0x7f, 0xf0, 0x0} + +/* A (65) */ +#define NXFONT_METRICS_65 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_65 {0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x70, 0x0, 0x0, 0x78, 0x0, 0x0, 0x78, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xdc, 0x0, 0x0, 0x9c, 0x0, 0x1, 0x8e, 0x0, 0x1, 0xe, 0x0, 0x3, 0xf, 0x0, 0x3, 0x7, 0x0, 0x2, 0x7, 0x0, 0x6, 0x7, 0x80, 0x6, 0x3, 0x80, 0xf, 0xff, 0xc0, 0xc, 0x3, 0xc0, 0x18, 0x1, 0xc0, 0x18, 0x1, 0xe0, 0x30, 0x1, 0xe0, 0x30, 0x0, 0xf0, 0x70, 0x0, 0xf0, 0xfc, 0x3, 0xfc} + +/* B (66) */ +#define NXFONT_METRICS_66 {3, 20, 23, 1, 14, 0} +#define NXFONT_BITMAP_66 {0xff, 0xfe, 0x0, 0x3e, 0xf, 0x80, 0x1c, 0x3, 0xc0, 0x1c, 0x1, 0xc0, 0x1c, 0x1, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x1, 0xe0, 0x1c, 0x1, 0xc0, 0x1c, 0x3, 0xc0, 0x1c, 0xf, 0x80, 0x1f, 0xfe, 0x0, 0x1c, 0x7, 0x80, 0x1c, 0x1, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xf0, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0xf0, 0x1c, 0x0, 0xe0, 0x1c, 0x1, 0xe0, 0x3e, 0x7, 0xc0, 0xff, 0xff, 0x0} + +/* C (67) */ +#define NXFONT_METRICS_67 {3, 20, 23, 1, 14, 0} +#define NXFONT_BITMAP_67 {0x1, 0xff, 0x10, 0x7, 0x83, 0xf0, 0xe, 0x0, 0xf0, 0x1c, 0x0, 0x70, 0x38, 0x0, 0x30, 0x38, 0x0, 0x30, 0x70, 0x0, 0x10, 0x70, 0x0, 0x10, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x70, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x10, 0x1c, 0x0, 0x30, 0xe, 0x0, 0x60, 0x7, 0x83, 0xc0, 0x1, 0xff, 0x0} + +/* D (68) */ +#define NXFONT_METRICS_68 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_68 {0xff, 0xfe, 0x0, 0x3e, 0x7, 0x80, 0x1c, 0x1, 0xc0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0x38, 0x1c, 0x0, 0x38, 0x1c, 0x0, 0x3c, 0x1c, 0x0, 0x3c, 0x1c, 0x0, 0x3c, 0x1c, 0x0, 0x3c, 0x1c, 0x0, 0x3c, 0x1c, 0x0, 0x3c, 0x1c, 0x0, 0x3c, 0x1c, 0x0, 0x38, 0x1c, 0x0, 0x38, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0xe0, 0x1c, 0x1, 0xc0, 0x3e, 0x7, 0x80, 0xff, 0xfe, 0x0} + +/* E (69) */ +#define NXFONT_METRICS_69 {3, 19, 23, 1, 14, 0} +#define NXFONT_BITMAP_69 {0xff, 0xff, 0xc0, 0x3e, 0x3, 0xc0, 0x1c, 0x0, 0xc0, 0x1c, 0x0, 0x40, 0x1c, 0x0, 0x40, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x3, 0x0, 0x1f, 0xff, 0x0, 0x1c, 0x3, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x60, 0x1c, 0x0, 0xc0, 0x3e, 0x3, 0xc0, 0xff, 0xff, 0xc0} + +/* F (70) */ +#define NXFONT_METRICS_70 {3, 17, 23, 1, 14, 0} +#define NXFONT_BITMAP_70 {0xff, 0xff, 0x80, 0x3e, 0x7, 0x80, 0x1c, 0x1, 0x80, 0x1c, 0x0, 0x80, 0x1c, 0x0, 0x80, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x2, 0x0, 0x1c, 0x2, 0x0, 0x1c, 0x6, 0x0, 0x1f, 0xfe, 0x0, 0x1c, 0x6, 0x0, 0x1c, 0x2, 0x0, 0x1c, 0x2, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x3e, 0x0, 0x0, 0xff, 0x80, 0x0} + +/* G (71) */ +#define NXFONT_METRICS_71 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_71 {0x1, 0xff, 0x30, 0x7, 0x87, 0xf0, 0xe, 0x0, 0xf0, 0x1c, 0x0, 0x70, 0x38, 0x0, 0x30, 0x38, 0x0, 0x30, 0x70, 0x0, 0x10, 0x70, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x3, 0xfc, 0xf0, 0x0, 0xf8, 0xf0, 0x0, 0x70, 0xf0, 0x0, 0x70, 0x70, 0x0, 0x70, 0x70, 0x0, 0x70, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x1c, 0x0, 0x70, 0xe, 0x0, 0x70, 0x7, 0x81, 0xe0, 0x1, 0xff, 0x80} + +/* H (72) */ +#define NXFONT_METRICS_72 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_72 {0xff, 0x87, 0xfc, 0x3e, 0x1, 0xf0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1f, 0xff, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0xe0, 0x3e, 0x1, 0xf0, 0xff, 0x87, 0xfc} + +/* I (73) */ +#define NXFONT_METRICS_73 {2, 9, 23, 1, 14, 0} +#define NXFONT_BITMAP_73 {0xff, 0x80, 0x3e, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0xff, 0x80} + +/* J (74) */ +#define NXFONT_METRICS_74 {2, 12, 23, 1, 14, 0} +#define NXFONT_BITMAP_74 {0x1f, 0xf0, 0x7, 0xc0, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0xc3, 0x80, 0xe3, 0x0, 0xe7, 0x0, 0x7c, 0x0} + +/* K (75) */ +#define NXFONT_METRICS_75 {3, 23, 23, 1, 14, 0} +#define NXFONT_BITMAP_75 {0xff, 0xc7, 0xf8, 0x3e, 0x1, 0xe0, 0x1c, 0x1, 0x80, 0x1c, 0x3, 0x0, 0x1c, 0x6, 0x0, 0x1c, 0xc, 0x0, 0x1c, 0x18, 0x0, 0x1c, 0x30, 0x0, 0x1c, 0x60, 0x0, 0x1c, 0xc0, 0x0, 0x1f, 0xc0, 0x0, 0x1f, 0xe0, 0x0, 0x1f, 0xf0, 0x0, 0x1e, 0x78, 0x0, 0x1c, 0x3c, 0x0, 0x1c, 0x1e, 0x0, 0x1c, 0xf, 0x0, 0x1c, 0x7, 0x80, 0x1c, 0x3, 0xc0, 0x1c, 0x1, 0xe0, 0x1c, 0x0, 0xf0, 0x3e, 0x0, 0xf8, 0xff, 0xc7, 0xfe} + +/* L (76) */ +#define NXFONT_METRICS_76 {3, 19, 23, 1, 14, 0} +#define NXFONT_BITMAP_76 {0xff, 0x80, 0x0, 0x3e, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x60, 0x1c, 0x0, 0xc0, 0x3e, 0x3, 0xc0, 0xff, 0xff, 0xc0} + +/* M (77) */ +#define NXFONT_METRICS_77 {4, 28, 23, 1, 14, 0} +#define NXFONT_BITMAP_77 {0xfc, 0x0, 0x7, 0xf0, 0x3e, 0x0, 0x7, 0xc0, 0x1e, 0x0, 0xf, 0x80, 0x1f, 0x0, 0xf, 0x80, 0x1f, 0x0, 0xb, 0x80, 0x17, 0x0, 0x1b, 0x80, 0x17, 0x80, 0x1b, 0x80, 0x13, 0x80, 0x33, 0x80, 0x13, 0xc0, 0x33, 0x80, 0x13, 0xc0, 0x23, 0x80, 0x11, 0xe0, 0x63, 0x80, 0x11, 0xe0, 0x63, 0x80, 0x10, 0xe0, 0xc3, 0x80, 0x10, 0xf0, 0xc3, 0x80, 0x10, 0x70, 0x83, 0x80, 0x10, 0x79, 0x83, 0x80, 0x10, 0x79, 0x3, 0x80, 0x10, 0x3d, 0x3, 0x80, 0x10, 0x3f, 0x3, 0x80, 0x10, 0x1e, 0x3, 0x80, 0x10, 0x1e, 0x3, 0x80, 0x38, 0xc, 0x7, 0xc0, 0xfe, 0xc, 0x1f, 0xf0} + +/* N (78) */ +#define NXFONT_METRICS_78 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_78 {0xf8, 0x1, 0xfc, 0x3c, 0x0, 0x70, 0x1e, 0x0, 0x20, 0x1f, 0x0, 0x20, 0x1f, 0x0, 0x20, 0x17, 0x80, 0x20, 0x13, 0xc0, 0x20, 0x13, 0xc0, 0x20, 0x11, 0xe0, 0x20, 0x10, 0xf0, 0x20, 0x10, 0xf8, 0x20, 0x10, 0x78, 0x20, 0x10, 0x3c, 0x20, 0x10, 0x1e, 0x20, 0x10, 0x1f, 0x20, 0x10, 0xf, 0x20, 0x10, 0x7, 0xa0, 0x10, 0x3, 0xe0, 0x10, 0x1, 0xe0, 0x10, 0x1, 0xe0, 0x10, 0x0, 0xe0, 0x38, 0x0, 0x60, 0xfe, 0x0, 0x20} + +/* O (79) */ +#define NXFONT_METRICS_79 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_79 {0x1, 0xfe, 0x0, 0x7, 0x87, 0x80, 0xe, 0x1, 0xc0, 0x1c, 0x0, 0xe0, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x1c, 0x0, 0xe0, 0xe, 0x1, 0xc0, 0x7, 0x87, 0x80, 0x1, 0xfe, 0x0} + +/* P (80) */ +#define NXFONT_METRICS_80 {3, 17, 23, 1, 14, 0} +#define NXFONT_BITMAP_80 {0xff, 0xf8, 0x0, 0x3c, 0x3e, 0x0, 0x1c, 0xf, 0x0, 0x1c, 0x7, 0x0, 0x1c, 0x7, 0x80, 0x1c, 0x3, 0x80, 0x1c, 0x3, 0x80, 0x1c, 0x3, 0x80, 0x1c, 0x7, 0x80, 0x1c, 0x7, 0x0, 0x1c, 0xf, 0x0, 0x1c, 0x3e, 0x0, 0x1f, 0xf0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x3e, 0x0, 0x0, 0xff, 0x80, 0x0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {3, 22, 29, 1, 14, 0} +#define NXFONT_BITMAP_81 {0x1, 0xfe, 0x0, 0x7, 0x87, 0x80, 0xe, 0x1, 0xc0, 0x1c, 0x0, 0xe0, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x1c, 0x0, 0xe0, 0xe, 0x1, 0xc0, 0x7, 0x87, 0x80, 0x1, 0xfe, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x3e, 0x0, 0x0, 0x1f, 0x0, 0x0, 0xf, 0x80, 0x0, 0x3, 0xe0, 0x0, 0x0, 0x7c} + +/* R (82) */ +#define NXFONT_METRICS_82 {3, 21, 23, 1, 14, 0} +#define NXFONT_BITMAP_82 {0xff, 0xf8, 0x0, 0x3c, 0x3e, 0x0, 0x1c, 0xf, 0x0, 0x1c, 0x7, 0x80, 0x1c, 0x7, 0x80, 0x1c, 0x3, 0x80, 0x1c, 0x3, 0x80, 0x1c, 0x3, 0x80, 0x1c, 0x7, 0x80, 0x1c, 0x7, 0x0, 0x1c, 0x1e, 0x0, 0x1f, 0xf8, 0x0, 0x1c, 0xf0, 0x0, 0x1c, 0x78, 0x0, 0x1c, 0x3c, 0x0, 0x1c, 0x3c, 0x0, 0x1c, 0x1e, 0x0, 0x1c, 0xf, 0x0, 0x1c, 0xf, 0x80, 0x1c, 0x7, 0x80, 0x1c, 0x3, 0xc0, 0x3e, 0x1, 0xe0, 0xff, 0x81, 0xf8} + +/* S (83) */ +#define NXFONT_METRICS_83 {2, 15, 23, 1, 14, 0} +#define NXFONT_BITMAP_83 {0x7, 0xe4, 0x1c, 0x3c, 0x38, 0x1c, 0x70, 0xc, 0x70, 0x4, 0x70, 0x6, 0x78, 0x0, 0x7c, 0x0, 0x3e, 0x0, 0x1f, 0x80, 0xf, 0xe0, 0x7, 0xf0, 0x1, 0xf8, 0x0, 0x7c, 0x0, 0x3e, 0x0, 0x1e, 0x80, 0xe, 0x80, 0xe, 0xc0, 0xe, 0xe0, 0xc, 0x70, 0x1c, 0x7c, 0x78, 0x67, 0xf0} + +/* T (84) */ +#define NXFONT_METRICS_84 {3, 19, 23, 1, 14, 0} +#define NXFONT_BITMAP_84 {0xff, 0xff, 0xe0, 0xf0, 0xe1, 0xe0, 0xc0, 0xe0, 0x60, 0xc0, 0xe0, 0x60, 0x80, 0xe0, 0x20, 0x80, 0xe0, 0x20, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe0, 0x0, 0x1, 0xf0, 0x0, 0x7, 0xfc, 0x0} + +/* U (85) */ +#define NXFONT_METRICS_85 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_85 {0xff, 0x81, 0xfc, 0x3e, 0x0, 0x70, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1e, 0x0, 0x60, 0xe, 0x0, 0x40, 0xf, 0x0, 0xc0, 0x7, 0xc3, 0x80, 0x1, 0xfe, 0x0} + +/* V (86) */ +#define NXFONT_METRICS_86 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_86 {0xff, 0x1, 0xfc, 0x7c, 0x0, 0x70, 0x3c, 0x0, 0x60, 0x1e, 0x0, 0x40, 0x1e, 0x0, 0xc0, 0xe, 0x0, 0xc0, 0xf, 0x0, 0x80, 0xf, 0x1, 0x80, 0x7, 0x1, 0x80, 0x7, 0x81, 0x0, 0x3, 0x83, 0x0, 0x3, 0xc3, 0x0, 0x3, 0xc2, 0x0, 0x1, 0xc6, 0x0, 0x1, 0xe6, 0x0, 0x0, 0xe4, 0x0, 0x0, 0xec, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x78, 0x0, 0x0, 0x78, 0x0, 0x0, 0x38, 0x0, 0x0, 0x30, 0x0, 0x0, 0x10, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {4, 31, 23, 1, 14, 0} +#define NXFONT_BITMAP_87 {0xff, 0x3f, 0xe0, 0xfe, 0x7c, 0xf, 0x80, 0x78, 0x3c, 0x7, 0x0, 0x30, 0x1c, 0x7, 0x80, 0x30, 0x1e, 0x7, 0x80, 0x60, 0x1e, 0x3, 0x80, 0x60, 0xe, 0x3, 0xc0, 0x60, 0xf, 0x3, 0xc0, 0xc0, 0x7, 0x3, 0xe0, 0xc0, 0x7, 0x87, 0xe0, 0xc0, 0x7, 0x86, 0xe1, 0x80, 0x3, 0x84, 0xf1, 0x80, 0x3, 0xcc, 0xf1, 0x80, 0x3, 0xcc, 0x73, 0x0, 0x1, 0xd8, 0x7b, 0x0, 0x1, 0xd8, 0x3b, 0x0, 0x1, 0xf8, 0x3e, 0x0, 0x0, 0xf0, 0x3e, 0x0, 0x0, 0xf0, 0x1c, 0x0, 0x0, 0xe0, 0x1c, 0x0, 0x0, 0x60, 0x1c, 0x0, 0x0, 0x60, 0x8, 0x0, 0x0, 0x40, 0x8, 0x0} + +/* X (88) */ +#define NXFONT_METRICS_88 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_88 {0xff, 0xc3, 0xfc, 0x3f, 0x0, 0xf0, 0x1f, 0x0, 0xe0, 0xf, 0x0, 0xc0, 0x7, 0x81, 0x80, 0x7, 0x83, 0x0, 0x3, 0xc6, 0x0, 0x1, 0xe6, 0x0, 0x1, 0xec, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x78, 0x0, 0x0, 0x78, 0x0, 0x0, 0x7c, 0x0, 0x0, 0xde, 0x0, 0x1, 0x9e, 0x0, 0x1, 0x8f, 0x0, 0x3, 0xf, 0x80, 0x6, 0x7, 0x80, 0xe, 0x3, 0xc0, 0xc, 0x3, 0xe0, 0x18, 0x1, 0xe0, 0x38, 0x1, 0xf0, 0xfe, 0x7, 0xfc} + +/* Y (89) */ +#define NXFONT_METRICS_89 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_89 {0xff, 0xc0, 0xfc, 0x3f, 0x0, 0x38, 0x1e, 0x0, 0x30, 0xf, 0x0, 0x60, 0xf, 0x80, 0xc0, 0x7, 0x80, 0x80, 0x3, 0xc1, 0x80, 0x3, 0xc3, 0x0, 0x1, 0xe3, 0x0, 0x0, 0xf6, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x7c, 0x0, 0x1, 0xff, 0x0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {3, 19, 23, 1, 14, 0} +#define NXFONT_BITMAP_90 {0x3f, 0xff, 0xe0, 0x38, 0x3, 0xc0, 0x60, 0x7, 0x80, 0x60, 0x7, 0x80, 0x40, 0xf, 0x0, 0x40, 0x1e, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x78, 0x0, 0x0, 0x78, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x3, 0xc0, 0x0, 0x3, 0xc0, 0x0, 0x7, 0x80, 0x0, 0xf, 0x0, 0x0, 0xf, 0x0, 0x20, 0x1e, 0x0, 0x20, 0x3c, 0x0, 0x60, 0x3c, 0x0, 0x60, 0x78, 0x1, 0xc0, 0xff, 0xff, 0xc0} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 7, 28, 3, 14, 0} +#define NXFONT_BITMAP_91 {0xfe, 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xfe} + +/* backslash (92) -- NOTE: Xoffset should be -2, not 0. */ +#define NXFONT_METRICS_92 {2, 13, 23, 0, 14, 0} +#define NXFONT_BITMAP_92 {0xc0, 0x0, 0xe0, 0x0, 0x60, 0x0, 0x70, 0x0, 0x30, 0x0, 0x38, 0x0, 0x18, 0x0, 0x1c, 0x0, 0xc, 0x0, 0xe, 0x0, 0x6, 0x0, 0x7, 0x0, 0x3, 0x0, 0x3, 0x80, 0x1, 0x80, 0x1, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0x60, 0x0, 0x70, 0x0, 0x30, 0x0, 0x38, 0x0, 0x18} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 7, 28, 1, 14, 0} +#define NXFONT_BITMAP_93 {0xfe, 0x1e, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0x1e, 0xfe} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {2, 13, 13, 1, 14, 0} +#define NXFONT_BITMAP_94 {0x7, 0x0, 0x7, 0x0, 0xf, 0x80, 0xd, 0x80, 0x18, 0xc0, 0x18, 0xc0, 0x30, 0x60, 0x30, 0x60, 0x70, 0x70, 0x60, 0x30, 0xe0, 0x38, 0xc0, 0x18, 0xc0, 0x18} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {3, 17, 2, 0, 40, 0} +#define NXFONT_BITMAP_95 {0xff, 0xff, 0x80, 0xff, 0xff, 0x80} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 7, 6, 1, 14, 0} +#define NXFONT_BITMAP_96 {0xc0, 0xe0, 0x70, 0x18, 0xc, 0x6} + +/* a (97) */ +#define NXFONT_METRICS_97 {2, 13, 15, 1, 22, 0} +#define NXFONT_BITMAP_97 {0x1f, 0x80, 0x31, 0xc0, 0x70, 0xe0, 0x70, 0xe0, 0x60, 0xe0, 0x3, 0xe0, 0xe, 0xe0, 0x18, 0xe0, 0x30, 0xe0, 0x60, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf2, 0xe8, 0x7e, 0xf8, 0x3c, 0x70} + +/* b (98) */ +#define NXFONT_METRICS_98 {2, 15, 23, 0, 14, 0} +#define NXFONT_BITMAP_98 {0x18, 0x0, 0xf8, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x39, 0xf0, 0x3b, 0xf8, 0x3c, 0x7c, 0x38, 0x1c, 0x38, 0x1e, 0x38, 0xe, 0x38, 0xe, 0x38, 0xe, 0x38, 0xe, 0x38, 0xe, 0x38, 0xc, 0x38, 0x1c, 0x38, 0x18, 0x3c, 0x70, 0xf, 0xe0} + +/* c (99) */ +#define NXFONT_METRICS_99 {2, 12, 15, 1, 22, 0} +#define NXFONT_BITMAP_99 {0xf, 0x80, 0x38, 0xc0, 0x70, 0xe0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0xe0, 0x10, 0x70, 0x30, 0x7c, 0x60, 0x3f, 0xc0, 0x1f, 0x0} + +/* d (100) */ +#define NXFONT_METRICS_100 {2, 15, 23, 1, 14, 0} +#define NXFONT_BITMAP_100 {0x0, 0x18, 0x0, 0xf8, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0xf, 0xb8, 0x18, 0xf8, 0x30, 0x78, 0x70, 0x38, 0x60, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xf0, 0x38, 0x70, 0x78, 0x78, 0xf8, 0x3f, 0xbe, 0xf, 0x30} + +/* e (101) */ +#define NXFONT_METRICS_101 {2, 12, 15, 1, 22, 0} +#define NXFONT_BITMAP_101 {0xf, 0x80, 0x39, 0xc0, 0x60, 0xe0, 0x60, 0x70, 0xc0, 0x70, 0xff, 0xf0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0xe0, 0x10, 0x70, 0x30, 0x7c, 0x60, 0x3f, 0xc0, 0xf, 0x0} + +/* f (102) */ +#define NXFONT_METRICS_102 {2, 12, 23, 0, 14, 0} +#define NXFONT_BITMAP_102 {0x3, 0xe0, 0x6, 0x70, 0xc, 0x70, 0xc, 0x30, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0xff, 0xc0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0xff, 0x80} + +/* g (103) */ +#define NXFONT_METRICS_103 {2, 14, 22, 1, 22, 0} +#define NXFONT_BITMAP_103 {0xf, 0xc0, 0x18, 0xfc, 0x30, 0x7c, 0x70, 0x30, 0x70, 0x30, 0x70, 0x30, 0x70, 0x30, 0x38, 0x70, 0x1c, 0xe0, 0xf, 0x80, 0x18, 0x0, 0x30, 0x0, 0x78, 0x0, 0x7f, 0xe0, 0x3f, 0xf8, 0x1f, 0xfc, 0x60, 0xc, 0xc0, 0xc, 0xc0, 0x1c, 0xf0, 0x38, 0x7f, 0xe0, 0x1f, 0x80} + +/* h (104) */ +#define NXFONT_METRICS_104 {2, 16, 23, 0, 14, 0} +#define NXFONT_BITMAP_104 {0x18, 0x0, 0xf8, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x39, 0xf0, 0x3b, 0xf8, 0x3e, 0x3c, 0x3c, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0xfe, 0x7f} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 7, 23, 1, 14, 0} +#define NXFONT_BITMAP_105 {0x38, 0x38, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xf8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xfe} + +/* j (106) -- NOTE: Xoffset should be -1, not 0. */ +#define NXFONT_METRICS_106 {1, 8, 30, 0, 14, 0} +#define NXFONT_BITMAP_106 {0x7, 0x7, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x1f, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0xc6, 0xec, 0x78} + +/* k (107) */ +#define NXFONT_METRICS_107 {2, 16, 23, 0, 14, 0} +#define NXFONT_BITMAP_107 {0x18, 0x0, 0xf8, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0xfe, 0x38, 0x70, 0x38, 0x60, 0x38, 0xc0, 0x39, 0x80, 0x3f, 0x0, 0x3e, 0x0, 0x3f, 0x0, 0x3b, 0x80, 0x39, 0xc0, 0x38, 0xe0, 0x38, 0xf0, 0x38, 0x78, 0x38, 0x3c, 0xfe, 0x7f} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 7, 23, 1, 14, 0} +#define NXFONT_BITMAP_108 {0x18, 0xf8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xfe} + +/* m (109) */ +#define NXFONT_METRICS_109 {4, 25, 15, 0, 22, 0} +#define NXFONT_BITMAP_109 {0x18, 0xf0, 0x78, 0x0, 0xfb, 0xf9, 0xfc, 0x0, 0x3e, 0x3f, 0x1e, 0x0, 0x3c, 0x1e, 0xe, 0x0, 0x38, 0x1c, 0xe, 0x0, 0x38, 0x1c, 0xe, 0x0, 0x38, 0x1c, 0xe, 0x0, 0x38, 0x1c, 0xe, 0x0, 0x38, 0x1c, 0xe, 0x0, 0x38, 0x1c, 0xe, 0x0, 0x38, 0x1c, 0xe, 0x0, 0x38, 0x1c, 0xe, 0x0, 0x38, 0x1c, 0xe, 0x0, 0x38, 0x1c, 0xe, 0x0, 0xfe, 0x7f, 0x3f, 0x80} + +/* n (110) */ +#define NXFONT_METRICS_110 {2, 16, 15, 0, 22, 0} +#define NXFONT_BITMAP_110 {0x18, 0xf0, 0xfb, 0xf8, 0x3c, 0x3c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0xfe, 0x7f} + +/* o (111) */ +#define NXFONT_METRICS_111 {2, 14, 15, 1, 22, 0} +#define NXFONT_BITMAP_111 {0x7, 0x80, 0x18, 0xe0, 0x30, 0x70, 0x70, 0x38, 0x60, 0x38, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0x70, 0x18, 0x70, 0x38, 0x38, 0x30, 0x1c, 0x60, 0x7, 0x80} + +/* p (112) */ +#define NXFONT_METRICS_112 {2, 15, 22, 0, 22, 0} +#define NXFONT_BITMAP_112 {0x19, 0xe0, 0xfb, 0xf8, 0x3c, 0x7c, 0x38, 0x1c, 0x38, 0x1e, 0x38, 0xe, 0x38, 0xe, 0x38, 0xe, 0x38, 0xe, 0x38, 0xe, 0x38, 0xc, 0x38, 0x1c, 0x3c, 0x18, 0x3e, 0x70, 0x3b, 0xc0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0xff, 0x0} + +/* q (113) */ +#define NXFONT_METRICS_113 {2, 15, 22, 1, 22, 0} +#define NXFONT_BITMAP_113 {0xf, 0xc8, 0x1c, 0x78, 0x30, 0x38, 0x70, 0x38, 0x60, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x38, 0xf0, 0x38, 0x70, 0x78, 0x78, 0xf8, 0x3f, 0xb8, 0x1f, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x1, 0xfe} + +/* r (114) */ +#define NXFONT_METRICS_114 {2, 10, 15, 1, 22, 0} +#define NXFONT_BITMAP_114 {0x19, 0x80, 0xfb, 0xc0, 0x3f, 0xc0, 0x3c, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0xfe, 0x0} + +/* s (115) */ +#define NXFONT_METRICS_115 {2, 10, 15, 1, 22, 0} +#define NXFONT_BITMAP_115 {0x3e, 0x80, 0x63, 0x80, 0xc1, 0x80, 0xc0, 0x80, 0xe0, 0x80, 0xf0, 0x0, 0x7c, 0x0, 0x3f, 0x0, 0xf, 0x80, 0x3, 0xc0, 0x81, 0xc0, 0x80, 0xc0, 0xc0, 0xc0, 0xe1, 0x80, 0xbf, 0x0} + +/* t (116) */ +#define NXFONT_METRICS_116 {2, 9, 19, 0, 18, 0} +#define NXFONT_BITMAP_116 {0x8, 0x0, 0x8, 0x0, 0x18, 0x0, 0x38, 0x0, 0xff, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x80, 0x3f, 0x0, 0x1c, 0x0} + +/* u (117) */ +#define NXFONT_METRICS_117 {2, 16, 15, 0, 22, 0} +#define NXFONT_BITMAP_117 {0xf8, 0x7c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x3c, 0x3c, 0x5c, 0x1f, 0xdf, 0xf, 0x8c} + +/* v (118) */ +#define NXFONT_METRICS_118 {2, 15, 15, 1, 22, 0} +#define NXFONT_BITMAP_118 {0xfe, 0x3e, 0x78, 0xc, 0x38, 0x8, 0x3c, 0x18, 0x1c, 0x18, 0x1c, 0x10, 0xe, 0x30, 0xe, 0x20, 0x7, 0x60, 0x7, 0x40, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0x80, 0x1, 0x80, 0x1, 0x0} + +/* w (119) */ +#define NXFONT_METRICS_119 {3, 21, 15, 1, 22, 0} +#define NXFONT_BITMAP_119 {0xfd, 0xfc, 0x78, 0x70, 0x70, 0x30, 0x70, 0x70, 0x30, 0x38, 0x30, 0x20, 0x38, 0x38, 0x60, 0x18, 0x38, 0x40, 0x1c, 0x78, 0x40, 0x1c, 0x5c, 0xc0, 0xc, 0xcc, 0x80, 0xe, 0x8f, 0x80, 0xf, 0x8f, 0x0, 0x7, 0x7, 0x0, 0x7, 0x7, 0x0, 0x3, 0x6, 0x0, 0x2, 0x2, 0x0} + +/* x (120) */ +#define NXFONT_METRICS_120 {2, 14, 15, 1, 22, 0} +#define NXFONT_BITMAP_120 {0xfc, 0xf8, 0x38, 0x60, 0x3c, 0xc0, 0x1c, 0x80, 0x1e, 0x80, 0xf, 0x0, 0x7, 0x0, 0x7, 0x80, 0xf, 0x80, 0xb, 0xc0, 0x19, 0xe0, 0x10, 0xe0, 0x30, 0x70, 0x60, 0x78, 0xf0, 0xfc} + +/* y (121) */ +#define NXFONT_METRICS_121 {2, 15, 22, 1, 22, 0} +#define NXFONT_BITMAP_121 {0xfe, 0x1e, 0x78, 0xc, 0x38, 0xc, 0x3c, 0x8, 0x1c, 0x18, 0x1e, 0x18, 0xe, 0x10, 0xe, 0x30, 0x7, 0x20, 0x7, 0x20, 0x3, 0xe0, 0x3, 0xc0, 0x1, 0xc0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x1, 0x0, 0x3, 0x0, 0x2, 0x0, 0x3e, 0x0, 0x7c, 0x0, 0x38, 0x0} + +/* z (122) */ +#define NXFONT_METRICS_122 {2, 13, 15, 1, 22, 0} +#define NXFONT_BITMAP_122 {0x7f, 0xf0, 0x60, 0xf0, 0x40, 0xe0, 0x41, 0xe0, 0x3, 0xc0, 0x3, 0x80, 0x7, 0x80, 0x7, 0x0, 0xe, 0x0, 0x1e, 0x0, 0x1c, 0x8, 0x38, 0x8, 0x78, 0x8, 0x70, 0x18, 0xff, 0xf0} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {1, 8, 28, 4, 14, 0} +#define NXFONT_BITMAP_123 {0xf, 0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x30, 0xe0, 0x30, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x18, 0x1c, 0xf} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 2, 23, 2, 14, 0} +#define NXFONT_BITMAP_124 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {1, 8, 28, 4, 14, 0} +#define NXFONT_BITMAP_125 {0xf0, 0x38, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xc, 0x7, 0xc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x18, 0x38, 0xf0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {2, 16, 4, 1, 26, 0} +#define NXFONT_BITMAP_126 {0x3e, 0x3, 0x7f, 0x87, 0xe1, 0xfe, 0xc0, 0x7c} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 4, 22, 3, 22, 0} +#define NXFONT_BITMAP_161 {0x60, 0xf0, 0xf0, 0x60, 0x0, 0x0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0xf0, 0xf0, 0xf0, 0x60} + +/* cent (162) */ +#define NXFONT_METRICS_162 {2, 12, 23, 2, 18, 0} +#define NXFONT_BITMAP_162 {0x0, 0x40, 0x0, 0x40, 0x0, 0x80, 0x0, 0x80, 0xf, 0x80, 0x38, 0xe0, 0x71, 0x70, 0x61, 0x70, 0xe1, 0x30, 0xc3, 0x0, 0xc2, 0x0, 0xc2, 0x0, 0xe6, 0x0, 0xe4, 0x0, 0x74, 0x10, 0x7c, 0x30, 0x3f, 0xe0, 0x1f, 0xc0, 0x1f, 0x0, 0x10, 0x0, 0x30, 0x0, 0x20, 0x0, 0x20, 0x0} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {2, 15, 23, 1, 14, 0} +#define NXFONT_BITMAP_163 {0x1, 0xf0, 0x3, 0x98, 0x6, 0x1c, 0x6, 0x1c, 0xe, 0x18, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xff, 0xe0, 0xff, 0xe0, 0xf, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x6, 0x0, 0x6, 0x2, 0x7e, 0x6, 0xc7, 0xfc, 0xcf, 0xf8, 0x78, 0xf0} + +/* currency (164) */ +#define NXFONT_METRICS_164 {2, 16, 17, 0, 17, 0} +#define NXFONT_BITMAP_164 {0xc7, 0xe3, 0xff, 0xff, 0x3e, 0x7c, 0x78, 0x1e, 0x70, 0xe, 0xe0, 0x7, 0xe0, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xe0, 0x7, 0xe0, 0x7, 0x70, 0xe, 0x78, 0x1e, 0x3e, 0x7c, 0xff, 0xff, 0xc7, 0xe3} + +/* yen (165) */ +#define NXFONT_METRICS_165 {3, 17, 23, 0, 14, 0} +#define NXFONT_BITMAP_165 {0xfe, 0x1f, 0x80, 0x78, 0x7, 0x0, 0x38, 0x6, 0x0, 0x3c, 0x4, 0x0, 0x1c, 0xc, 0x0, 0x1e, 0x8, 0x0, 0xe, 0x18, 0x0, 0xf, 0x10, 0x0, 0x7, 0x30, 0x0, 0x7, 0xa0, 0x0, 0x3, 0xe0, 0x0, 0x3, 0xc0, 0x0, 0x3f, 0xfe, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x3f, 0xfe, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x7, 0xf0, 0x0} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 2, 23, 2, 14, 0} +#define NXFONT_BITMAP_166 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* section (167) */ +#define NXFONT_METRICS_167 {2, 12, 28, 2, 14, 0} +#define NXFONT_BITMAP_167 {0x1f, 0x80, 0x31, 0xc0, 0x61, 0xc0, 0x61, 0xc0, 0x71, 0x80, 0x38, 0x0, 0x3c, 0x0, 0x1e, 0x0, 0xf, 0x0, 0x3f, 0x80, 0x63, 0xc0, 0xc1, 0xe0, 0xc0, 0xe0, 0xc0, 0x70, 0xe0, 0x30, 0x70, 0x30, 0x78, 0x30, 0x3c, 0x60, 0x1f, 0xc0, 0xf, 0x0, 0x7, 0x80, 0x3, 0xc0, 0x1, 0xc0, 0x18, 0xe0, 0x38, 0x60, 0x38, 0x60, 0x38, 0xc0, 0x1f, 0x80} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {2, 9, 3, 1, 16, 0} +#define NXFONT_BITMAP_168 {0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_169 {0x0, 0xfc, 0x0, 0x3, 0xff, 0x0, 0xe, 0x1, 0xc0, 0x18, 0x0, 0x60, 0x30, 0x0, 0x30, 0x60, 0x0, 0x18, 0x60, 0x7f, 0x18, 0xc1, 0xc7, 0xc, 0xc3, 0x83, 0xc, 0xc3, 0x1, 0xc, 0xc7, 0x0, 0xc, 0xc7, 0x0, 0xc, 0xc7, 0x0, 0xc, 0xc7, 0x0, 0xc, 0xc7, 0x80, 0xc, 0x43, 0x81, 0x18, 0x61, 0xe6, 0x18, 0x60, 0x7c, 0x30, 0x30, 0x0, 0x30, 0x18, 0x0, 0x60, 0xe, 0x1, 0xc0, 0x7, 0xff, 0x0, 0x1, 0xfc, 0x0} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {2, 9, 13, 0, 14, 0} +#define NXFONT_BITMAP_170 {0x3c, 0x0, 0x4e, 0x0, 0xc6, 0x0, 0xc6, 0x0, 0x1e, 0x0, 0x66, 0x0, 0xc6, 0x0, 0xc6, 0x0, 0xef, 0x80, 0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {2, 13, 13, 1, 23, 0} +#define NXFONT_BITMAP_171 {0x2, 0x8, 0x6, 0x18, 0xc, 0x30, 0x18, 0x60, 0x38, 0xe0, 0x71, 0xc0, 0xe3, 0x80, 0x71, 0xc0, 0x38, 0xe0, 0x18, 0x60, 0xc, 0x30, 0x6, 0x18, 0x2, 0x8} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {2, 16, 9, 1, 24, 0} +#define NXFONT_BITMAP_172 {0xff, 0xff, 0xff, 0xff, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 8, 2, 1, 28, 0} +#define NXFONT_BITMAP_173 {0xff, 0xff} + +/* registered (174) */ +#define NXFONT_METRICS_174 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_174 {0x0, 0xfe, 0x0, 0x3, 0xff, 0x0, 0xe, 0x1, 0xc0, 0x18, 0x0, 0x60, 0x30, 0x0, 0x30, 0x23, 0xfc, 0x18, 0x60, 0xc7, 0x18, 0xc0, 0xc3, 0xc, 0xc0, 0xc3, 0xc, 0xc0, 0xc3, 0xc, 0xc0, 0xc6, 0xc, 0xc0, 0xf8, 0xc, 0xc0, 0xdc, 0xc, 0xc0, 0xcc, 0xc, 0xc0, 0xce, 0xc, 0x40, 0xc6, 0x8, 0x60, 0xc7, 0x18, 0x23, 0xe3, 0xd0, 0x30, 0x0, 0x30, 0x18, 0x0, 0x60, 0xe, 0x1, 0xc0, 0x3, 0xff, 0x0, 0x0, 0xfc, 0x0} + +/* macron (175) */ +#define NXFONT_METRICS_175 {2, 10, 2, 0, 17, 0} +#define NXFONT_BITMAP_175 {0xff, 0xc0, 0xff, 0xc0} + +/* degree (176) */ +#define NXFONT_METRICS_176 {2, 10, 10, 1, 14, 0} +#define NXFONT_BITMAP_176 {0x1e, 0x0, 0x3f, 0x0, 0x61, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x80, 0x3f, 0x0, 0x1e, 0x0} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {2, 16, 20, 1, 17, 0} +#define NXFONT_BITMAP_177 {0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0xff, 0xff, 0xff, 0xff, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {2, 9, 14, 0, 14, 0} +#define NXFONT_BITMAP_178 {0x3c, 0x0, 0x4e, 0x0, 0x87, 0x0, 0x3, 0x0, 0x3, 0x0, 0x7, 0x0, 0x6, 0x0, 0xc, 0x0, 0x18, 0x0, 0x10, 0x0, 0x20, 0x0, 0x40, 0x80, 0xff, 0x0, 0xfe, 0x0} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {2, 9, 14, 0, 14, 0} +#define NXFONT_BITMAP_179 {0x3e, 0x0, 0x47, 0x0, 0x83, 0x0, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x3c, 0x0, 0x7, 0x0, 0x3, 0x80, 0x1, 0x80, 0x1, 0x80, 0xc1, 0x80, 0xe3, 0x0, 0x7e, 0x0} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 7, 6, 3, 14, 0} +#define NXFONT_BITMAP_180 {0x6, 0xe, 0x1c, 0x30, 0x60, 0xc0} + +/* mu (181) */ +#define NXFONT_METRICS_181 {2, 16, 22, 0, 22, 0} +#define NXFONT_BITMAP_181 {0xf8, 0x7c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x3c, 0x3c, 0x7c, 0x3f, 0xdf, 0x2f, 0x98, 0x20, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x20, 0x0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {2, 13, 29, 1, 14, 0} +#define NXFONT_BITMAP_182 {0x7, 0xf8, 0x1e, 0x20, 0x3e, 0x20, 0x7e, 0x20, 0x7e, 0x20, 0xfe, 0x20, 0xfe, 0x20, 0xfe, 0x20, 0xfe, 0x20, 0x7e, 0x20, 0x7e, 0x20, 0x3e, 0x20, 0x1e, 0x20, 0xe, 0x20, 0x2, 0x20, 0x2, 0x20, 0x2, 0x20, 0x2, 0x20, 0x2, 0x20, 0x2, 0x20, 0x2, 0x20, 0x2, 0x20, 0x2, 0x20, 0x2, 0x20, 0x2, 0x20, 0x2, 0x20, 0x2, 0x20, 0x2, 0x20, 0x2, 0x20} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 4, 4, 2, 26, 0} +#define NXFONT_BITMAP_183 {0x60, 0xf0, 0xf0, 0x60} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 6, 7, 2, 37, 0} +#define NXFONT_BITMAP_184 {0x20, 0x60, 0x78, 0x1c, 0xc, 0x1c, 0xf8} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {1, 6, 14, 2, 14, 0} +#define NXFONT_BITMAP_185 {0x30, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {2, 9, 13, 0, 14, 0} +#define NXFONT_BITMAP_186 {0x3e, 0x0, 0x63, 0x0, 0xc3, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xe1, 0x80, 0x63, 0x0, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {2, 13, 13, 2, 23, 0} +#define NXFONT_BITMAP_187 {0x82, 0x0, 0xc3, 0x0, 0x61, 0x80, 0x30, 0xc0, 0x38, 0xe0, 0x1c, 0x70, 0xe, 0x38, 0x1c, 0x70, 0x38, 0xe0, 0x30, 0xc0, 0x61, 0x80, 0xc3, 0x0, 0x82, 0x0} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {3, 22, 23, 2, 14, 0} +#define NXFONT_BITMAP_188 {0x30, 0x0, 0x60, 0xf0, 0x0, 0x60, 0x30, 0x0, 0xc0, 0x30, 0x1, 0xc0, 0x30, 0x1, 0x80, 0x30, 0x3, 0x0, 0x30, 0x3, 0x0, 0x30, 0x6, 0x0, 0x30, 0xe, 0x0, 0x30, 0xc, 0x10, 0x30, 0x18, 0x30, 0x30, 0x18, 0x70, 0x30, 0x30, 0x70, 0xfc, 0x60, 0xf0, 0x0, 0x61, 0xb0, 0x0, 0xc1, 0x30, 0x1, 0xc2, 0x30, 0x1, 0x86, 0x30, 0x3, 0xc, 0x30, 0x3, 0x1f, 0xfc, 0x6, 0x0, 0x30, 0xc, 0x0, 0x30, 0xc, 0x0, 0x30} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {3, 23, 23, 1, 14, 0} +#define NXFONT_BITMAP_189 {0x30, 0x0, 0xc0, 0xf0, 0x0, 0xc0, 0x30, 0x1, 0x80, 0x30, 0x3, 0x80, 0x30, 0x3, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0xc, 0x0, 0x30, 0x1c, 0x0, 0x30, 0x18, 0xf0, 0x30, 0x31, 0x38, 0x30, 0x32, 0x1c, 0x30, 0x60, 0xc, 0xfc, 0xe0, 0xc, 0x0, 0xc0, 0x1c, 0x1, 0x80, 0x18, 0x3, 0x80, 0x30, 0x3, 0x0, 0x60, 0x6, 0x0, 0x40, 0x6, 0x0, 0x80, 0xc, 0x1, 0x2, 0x18, 0x3, 0xfc, 0x18, 0x3, 0xf8} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {3, 24, 23, 0, 14, 0} +#define NXFONT_BITMAP_190 {0x3e, 0x0, 0x18, 0x47, 0x0, 0x18, 0x83, 0x0, 0x30, 0x3, 0x0, 0x70, 0x3, 0x0, 0x60, 0x6, 0x0, 0xc0, 0x3c, 0x0, 0xc0, 0x7, 0x1, 0x80, 0x3, 0x83, 0x80, 0x1, 0x83, 0x4, 0x1, 0x86, 0xc, 0xc1, 0x86, 0x1c, 0xe3, 0xc, 0x1c, 0x7e, 0x18, 0x3c, 0x0, 0x18, 0x6c, 0x0, 0x30, 0x4c, 0x0, 0x70, 0x8c, 0x0, 0x61, 0x8c, 0x0, 0xc3, 0xc, 0x0, 0xc7, 0xff, 0x1, 0x80, 0xc, 0x3, 0x0, 0xc, 0x3, 0x0, 0xc} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {2, 11, 22, 1, 22, 0} +#define NXFONT_BITMAP_191 {0x6, 0x0, 0xf, 0x0, 0xf, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x2, 0x0, 0x6, 0x0, 0x4, 0x0, 0xc, 0x0, 0x18, 0x0, 0x38, 0x0, 0x30, 0x0, 0x70, 0x0, 0x70, 0x0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0x70, 0x60, 0x70, 0x60, 0x39, 0xc0, 0x1f, 0x0} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {3, 22, 30, 1, 7, 0} +#define NXFONT_BITMAP_192 {0x6, 0x0, 0x0, 0x7, 0x0, 0x0, 0x3, 0x80, 0x0, 0x0, 0xc0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x70, 0x0, 0x0, 0x78, 0x0, 0x0, 0x78, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xdc, 0x0, 0x0, 0x9c, 0x0, 0x1, 0x8e, 0x0, 0x1, 0xe, 0x0, 0x3, 0xf, 0x0, 0x3, 0x7, 0x0, 0x2, 0x7, 0x0, 0x6, 0x7, 0x80, 0x6, 0x3, 0x80, 0xf, 0xff, 0xc0, 0xc, 0x3, 0xc0, 0x18, 0x1, 0xc0, 0x18, 0x1, 0xe0, 0x30, 0x1, 0xe0, 0x30, 0x0, 0xf0, 0x70, 0x0, 0xf0, 0xfc, 0x3, 0xfc} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {3, 22, 30, 1, 7, 0} +#define NXFONT_BITMAP_193 {0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x7, 0x0, 0x0, 0xc, 0x0, 0x0, 0x18, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x70, 0x0, 0x0, 0x78, 0x0, 0x0, 0x78, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xdc, 0x0, 0x0, 0x9c, 0x0, 0x1, 0x8e, 0x0, 0x1, 0xe, 0x0, 0x3, 0xf, 0x0, 0x3, 0x7, 0x0, 0x2, 0x7, 0x0, 0x6, 0x7, 0x80, 0x6, 0x3, 0x80, 0xf, 0xff, 0xc0, 0xc, 0x3, 0xc0, 0x18, 0x1, 0xc0, 0x18, 0x1, 0xe0, 0x30, 0x1, 0xe0, 0x30, 0x0, 0xf0, 0x70, 0x0, 0xf0, 0xfc, 0x3, 0xfc} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {3, 22, 30, 1, 7, 0} +#define NXFONT_BITMAP_194 {0x0, 0x30, 0x0, 0x0, 0x78, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xce, 0x0, 0x3, 0x3, 0x0, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x70, 0x0, 0x0, 0x78, 0x0, 0x0, 0x78, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xdc, 0x0, 0x0, 0x9c, 0x0, 0x1, 0x8e, 0x0, 0x1, 0xe, 0x0, 0x3, 0xf, 0x0, 0x3, 0x7, 0x0, 0x2, 0x7, 0x0, 0x6, 0x7, 0x80, 0x6, 0x3, 0x80, 0xf, 0xff, 0xc0, 0xc, 0x3, 0xc0, 0x18, 0x1, 0xc0, 0x18, 0x1, 0xe0, 0x30, 0x1, 0xe0, 0x30, 0x0, 0xf0, 0x70, 0x0, 0xf0, 0xfc, 0x3, 0xfc} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {3, 22, 28, 1, 9, 0} +#define NXFONT_BITMAP_195 {0x0, 0xe0, 0x80, 0x1, 0xf9, 0x80, 0x3, 0x3f, 0x0, 0x2, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x70, 0x0, 0x0, 0x78, 0x0, 0x0, 0x78, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xdc, 0x0, 0x0, 0x9c, 0x0, 0x1, 0x8e, 0x0, 0x1, 0xe, 0x0, 0x3, 0xf, 0x0, 0x3, 0x7, 0x0, 0x2, 0x7, 0x0, 0x6, 0x7, 0x80, 0x6, 0x3, 0x80, 0xf, 0xff, 0xc0, 0xc, 0x3, 0xc0, 0x18, 0x1, 0xc0, 0x18, 0x1, 0xe0, 0x30, 0x1, 0xe0, 0x30, 0x0, 0xf0, 0x70, 0x0, 0xf0, 0xfc, 0x3, 0xfc} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {3, 22, 28, 1, 9, 0} +#define NXFONT_BITMAP_196 {0x1, 0xc7, 0x0, 0x1, 0xc7, 0x0, 0x1, 0xc7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x70, 0x0, 0x0, 0x78, 0x0, 0x0, 0x78, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xdc, 0x0, 0x0, 0x9c, 0x0, 0x1, 0x8e, 0x0, 0x1, 0xe, 0x0, 0x3, 0xf, 0x0, 0x3, 0x7, 0x0, 0x2, 0x7, 0x0, 0x6, 0x7, 0x80, 0x6, 0x3, 0x80, 0xf, 0xff, 0xc0, 0xc, 0x3, 0xc0, 0x18, 0x1, 0xc0, 0x18, 0x1, 0xe0, 0x30, 0x1, 0xe0, 0x30, 0x0, 0xf0, 0x70, 0x0, 0xf0, 0xfc, 0x3, 0xfc} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {3, 22, 30, 1, 7, 0} +#define NXFONT_BITMAP_197 {0x0, 0x70, 0x0, 0x0, 0xf8, 0x0, 0x1, 0x8c, 0x0, 0x1, 0x4, 0x0, 0x1, 0x8c, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x78, 0x0, 0x0, 0x78, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xdc, 0x0, 0x0, 0x9c, 0x0, 0x1, 0x8e, 0x0, 0x1, 0xe, 0x0, 0x3, 0xf, 0x0, 0x3, 0x7, 0x0, 0x2, 0x7, 0x0, 0x6, 0x7, 0x80, 0x6, 0x3, 0x80, 0xf, 0xff, 0xc0, 0xc, 0x3, 0xc0, 0x18, 0x1, 0xc0, 0x18, 0x1, 0xe0, 0x30, 0x1, 0xe0, 0x30, 0x0, 0xf0, 0x70, 0x0, 0xf0, 0xfc, 0x3, 0xfc} + +/* AE (198) */ +#define NXFONT_METRICS_198 {4, 28, 23, 1, 14, 0} +#define NXFONT_BITMAP_198 {0x0, 0xff, 0xff, 0xe0, 0x0, 0x1f, 0x81, 0xe0, 0x0, 0x1f, 0x0, 0x60, 0x0, 0x37, 0x0, 0x20, 0x0, 0x37, 0x0, 0x20, 0x0, 0x67, 0x0, 0x0, 0x0, 0x67, 0x0, 0x0, 0x0, 0x47, 0x0, 0x80, 0x0, 0xc7, 0x0, 0x80, 0x0, 0xc7, 0x1, 0x80, 0x1, 0x87, 0x3, 0x80, 0x1, 0x87, 0xff, 0x80, 0x3, 0x7, 0x3, 0x80, 0x3, 0x7, 0x1, 0x80, 0x7, 0xff, 0x0, 0x80, 0x6, 0x7, 0x0, 0x80, 0xc, 0x7, 0x0, 0x0, 0xc, 0x7, 0x0, 0x10, 0x18, 0x7, 0x0, 0x10, 0x18, 0x7, 0x0, 0x30, 0x30, 0x7, 0x0, 0x60, 0x30, 0xf, 0x81, 0xe0, 0xfe, 0x3f, 0xff, 0xe0} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {3, 20, 30, 1, 14, 0} +#define NXFONT_BITMAP_199 {0x1, 0xff, 0x10, 0x7, 0x83, 0xf0, 0xe, 0x0, 0xf0, 0x1c, 0x0, 0x70, 0x38, 0x0, 0x30, 0x38, 0x0, 0x30, 0x70, 0x0, 0x10, 0x70, 0x0, 0x10, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x70, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x10, 0x1c, 0x0, 0x30, 0xe, 0x0, 0x60, 0x7, 0x83, 0xc0, 0x1, 0xff, 0x0, 0x0, 0x40, 0x0, 0x0, 0xc0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x1, 0xf0, 0x0} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {3, 19, 30, 1, 7, 0} +#define NXFONT_BITMAP_200 {0x3, 0x0, 0x0, 0x3, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x30, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xc0, 0x3e, 0x3, 0xc0, 0x1c, 0x0, 0xc0, 0x1c, 0x0, 0x40, 0x1c, 0x0, 0x40, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x3, 0x0, 0x1f, 0xff, 0x0, 0x1c, 0x3, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x60, 0x1c, 0x0, 0xc0, 0x3e, 0x3, 0xc0, 0xff, 0xff, 0xc0} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {3, 19, 30, 1, 7, 0} +#define NXFONT_BITMAP_201 {0x0, 0x6, 0x0, 0x0, 0xe, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x30, 0x0, 0x0, 0x60, 0x0, 0x0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xc0, 0x3e, 0x3, 0xc0, 0x1c, 0x0, 0xc0, 0x1c, 0x0, 0x40, 0x1c, 0x0, 0x40, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x3, 0x0, 0x1f, 0xff, 0x0, 0x1c, 0x3, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x60, 0x1c, 0x0, 0xc0, 0x3e, 0x3, 0xc0, 0xff, 0xff, 0xc0} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {3, 19, 30, 1, 7, 0} +#define NXFONT_BITMAP_202 {0x0, 0x30, 0x0, 0x0, 0x78, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xce, 0x0, 0x3, 0x3, 0x0, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xc0, 0x3e, 0x3, 0xc0, 0x1c, 0x0, 0xc0, 0x1c, 0x0, 0x40, 0x1c, 0x0, 0x40, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x3, 0x0, 0x1f, 0xff, 0x0, 0x1c, 0x3, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x60, 0x1c, 0x0, 0xc0, 0x3e, 0x3, 0xc0, 0xff, 0xff, 0xc0} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {3, 19, 28, 1, 9, 0} +#define NXFONT_BITMAP_203 {0x3, 0x8e, 0x0, 0x3, 0x8e, 0x0, 0x3, 0x8e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xc0, 0x3e, 0x3, 0xc0, 0x1c, 0x0, 0xc0, 0x1c, 0x0, 0x40, 0x1c, 0x0, 0x40, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x3, 0x0, 0x1f, 0xff, 0x0, 0x1c, 0x3, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x1, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x60, 0x1c, 0x0, 0xc0, 0x3e, 0x3, 0xc0, 0xff, 0xff, 0xc0} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {2, 9, 30, 1, 7, 0} +#define NXFONT_BITMAP_204 {0x60, 0x0, 0x70, 0x0, 0x38, 0x0, 0xc, 0x0, 0x6, 0x0, 0x3, 0x0, 0x0, 0x0, 0xff, 0x80, 0x3e, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0xff, 0x80} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {2, 9, 30, 1, 7, 0} +#define NXFONT_BITMAP_205 {0x1, 0x80, 0x3, 0x80, 0x7, 0x0, 0xc, 0x0, 0x18, 0x0, 0x30, 0x0, 0x0, 0x0, 0xff, 0x80, 0x3e, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0xff, 0x80} + +/* Icircumflex (206) */ +#define NXFONT_METRICS_206 {2, 10, 30, 1, 7, 0} +#define NXFONT_BITMAP_206 {0xc, 0x0, 0x1e, 0x0, 0x3f, 0x0, 0x73, 0x80, 0xc0, 0xc0, 0x80, 0x40, 0x0, 0x0, 0xff, 0x80, 0x3e, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0xff, 0x80} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {2, 9, 28, 1, 9, 0} +#define NXFONT_BITMAP_207 {0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x3e, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x3e, 0x0, 0xff, 0x80} + +/* Eth (208) */ +#define NXFONT_METRICS_208 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_208 {0xff, 0xfe, 0x0, 0x3e, 0x7, 0x80, 0x1c, 0x1, 0xc0, 0x1c, 0x0, 0xe0, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0x38, 0x1c, 0x0, 0x38, 0x1c, 0x0, 0x3c, 0x1c, 0x0, 0x3c, 0x1c, 0x0, 0x3c, 0xff, 0xc0, 0x3c, 0xff, 0xc0, 0x3c, 0x1c, 0x0, 0x3c, 0x1c, 0x0, 0x3c, 0x1c, 0x0, 0x38, 0x1c, 0x0, 0x38, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0x70, 0x1c, 0x0, 0xe0, 0x1c, 0x1, 0xc0, 0x3e, 0x7, 0x80, 0xff, 0xfe, 0x0} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {3, 22, 29, 1, 8, 0} +#define NXFONT_BITMAP_209 {0x0, 0xe0, 0x80, 0x1, 0xf9, 0x80, 0x3, 0x3f, 0x0, 0x2, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x1, 0xfc, 0x3c, 0x0, 0x70, 0x1e, 0x0, 0x20, 0x1f, 0x0, 0x20, 0x1f, 0x0, 0x20, 0x17, 0x80, 0x20, 0x13, 0xc0, 0x20, 0x13, 0xc0, 0x20, 0x11, 0xe0, 0x20, 0x10, 0xf0, 0x20, 0x10, 0xf8, 0x20, 0x10, 0x78, 0x20, 0x10, 0x3c, 0x20, 0x10, 0x1e, 0x20, 0x10, 0x1f, 0x20, 0x10, 0xf, 0x20, 0x10, 0x7, 0xa0, 0x10, 0x3, 0xe0, 0x10, 0x1, 0xe0, 0x10, 0x1, 0xe0, 0x10, 0x0, 0xe0, 0x38, 0x0, 0x60, 0xfe, 0x0, 0x20} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {3, 22, 30, 1, 7, 0} +#define NXFONT_BITMAP_210 {0x3, 0x0, 0x0, 0x3, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x30, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x7, 0x87, 0x80, 0xe, 0x1, 0xc0, 0x1c, 0x0, 0xe0, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x1c, 0x0, 0xe0, 0xe, 0x1, 0xc0, 0x7, 0x87, 0x80, 0x1, 0xfe, 0x0} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {3, 22, 30, 1, 7, 0} +#define NXFONT_BITMAP_211 {0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x7, 0x0, 0x0, 0xc, 0x0, 0x0, 0x18, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x7, 0x87, 0x80, 0xe, 0x1, 0xc0, 0x1c, 0x0, 0xe0, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x1c, 0x0, 0xe0, 0xe, 0x1, 0xc0, 0x7, 0x87, 0x80, 0x1, 0xfe, 0x0} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {3, 22, 30, 1, 7, 0} +#define NXFONT_BITMAP_212 {0x0, 0x30, 0x0, 0x0, 0x78, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xce, 0x0, 0x3, 0x3, 0x0, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x7, 0x87, 0x80, 0xe, 0x1, 0xc0, 0x1c, 0x0, 0xe0, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x1c, 0x0, 0xe0, 0xe, 0x1, 0xc0, 0x7, 0x87, 0x80, 0x1, 0xfe, 0x0} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {3, 22, 28, 1, 9, 0} +#define NXFONT_BITMAP_213 {0x0, 0xe0, 0x80, 0x1, 0xf9, 0x80, 0x3, 0x3f, 0x0, 0x2, 0xe, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x7, 0x87, 0x80, 0xe, 0x1, 0xc0, 0x1c, 0x0, 0xe0, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x1c, 0x0, 0xe0, 0xe, 0x1, 0xc0, 0x7, 0x87, 0x80, 0x1, 0xfe, 0x0} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {3, 22, 28, 1, 9, 0} +#define NXFONT_BITMAP_214 {0x1, 0xc7, 0x0, 0x1, 0xc7, 0x0, 0x1, 0xc7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x7, 0x87, 0x80, 0xe, 0x1, 0xc0, 0x1c, 0x0, 0xe0, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0xf0, 0x0, 0x3c, 0x70, 0x0, 0x38, 0x70, 0x0, 0x38, 0x38, 0x0, 0x70, 0x38, 0x0, 0x70, 0x1c, 0x0, 0xe0, 0xe, 0x1, 0xc0, 0x7, 0x87, 0x80, 0x1, 0xfe, 0x0} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {2, 16, 16, 1, 21, 0} +#define NXFONT_BITMAP_215 {0x40, 0x2, 0xe0, 0x7, 0x70, 0xe, 0x38, 0x1c, 0x1c, 0x38, 0xe, 0x70, 0x7, 0xe0, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, 0xe, 0x70, 0x1c, 0x38, 0x38, 0x1c, 0x70, 0xe, 0xe0, 0x7, 0x40, 0x2} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {3, 22, 27, 1, 12, 0} +#define NXFONT_BITMAP_216 {0x0, 0x0, 0x10, 0x0, 0x0, 0x30, 0x1, 0xfe, 0x60, 0x7, 0x87, 0xc0, 0xe, 0x1, 0xc0, 0x1c, 0x1, 0xe0, 0x38, 0x3, 0x70, 0x38, 0x2, 0x70, 0x70, 0x6, 0x38, 0x70, 0xc, 0x38, 0xf0, 0x8, 0x3c, 0xf0, 0x18, 0x3c, 0xf0, 0x30, 0x3c, 0xf0, 0x60, 0x3c, 0xf0, 0x40, 0x3c, 0xf0, 0xc0, 0x3c, 0xf0, 0x80, 0x3c, 0x71, 0x80, 0x38, 0x73, 0x0, 0x38, 0x3a, 0x0, 0x70, 0x3e, 0x0, 0x70, 0x1c, 0x0, 0xe0, 0x1e, 0x1, 0xc0, 0x37, 0x87, 0x80, 0x21, 0xfe, 0x0, 0x60, 0x0, 0x0, 0x40, 0x0, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {3, 22, 30, 1, 7, 0} +#define NXFONT_BITMAP_217 {0x0, 0xc0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x18, 0x0, 0x0, 0xc, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0xff, 0x81, 0xfc, 0x3e, 0x0, 0x70, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x60, 0x1e, 0x0, 0x60, 0xe, 0x0, 0x40, 0xf, 0x0, 0xc0, 0x7, 0xc3, 0x80, 0x1, 0xfe, 0x0} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {3, 22, 30, 1, 7, 0} +#define NXFONT_BITMAP_218 {0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x7, 0x0, 0x0, 0xc, 0x0, 0x0, 0x18, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0xff, 0x81, 0xfc, 0x3e, 0x0, 0x70, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x60, 0x1e, 0x0, 0x60, 0xe, 0x0, 0x40, 0xf, 0x0, 0xc0, 0x7, 0xc3, 0x80, 0x1, 0xfe, 0x0} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {3, 22, 30, 1, 7, 0} +#define NXFONT_BITMAP_219 {0x0, 0x18, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x7e, 0x0, 0x0, 0xe7, 0x0, 0x1, 0x81, 0x80, 0x1, 0x0, 0x80, 0x0, 0x0, 0x0, 0xff, 0x81, 0xfc, 0x3e, 0x0, 0x70, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x60, 0x1e, 0x0, 0x60, 0xe, 0x0, 0x40, 0xf, 0x0, 0xc0, 0x7, 0xc3, 0x80, 0x1, 0xfe, 0x0} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {3, 22, 28, 1, 9, 0} +#define NXFONT_BITMAP_220 {0x1, 0xc7, 0x0, 0x1, 0xc7, 0x0, 0x1, 0xc7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x81, 0xfc, 0x3e, 0x0, 0x70, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x20, 0x1c, 0x0, 0x60, 0x1e, 0x0, 0x60, 0xe, 0x0, 0x40, 0xf, 0x0, 0xc0, 0x7, 0xc3, 0x80, 0x1, 0xfe, 0x0} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {3, 22, 30, 1, 7, 0} +#define NXFONT_BITMAP_221 {0x0, 0x0, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x3, 0x80, 0x0, 0x6, 0x0, 0x0, 0xc, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0xfc, 0x3f, 0x0, 0x38, 0x1e, 0x0, 0x30, 0xf, 0x0, 0x60, 0xf, 0x80, 0xc0, 0x7, 0x80, 0x80, 0x3, 0xc1, 0x80, 0x3, 0xc3, 0x0, 0x1, 0xe3, 0x0, 0x0, 0xf6, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x7c, 0x0, 0x1, 0xff, 0x0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {3, 18, 23, 1, 14, 0} +#define NXFONT_BITMAP_222 {0xff, 0x80, 0x0, 0x3e, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1f, 0xfc, 0x0, 0x1c, 0x1f, 0x0, 0x1c, 0x7, 0x80, 0x1c, 0x3, 0x80, 0x1c, 0x3, 0xc0, 0x1c, 0x1, 0xc0, 0x1c, 0x1, 0xc0, 0x1c, 0x1, 0xc0, 0x1c, 0x3, 0xc0, 0x1c, 0x3, 0x80, 0x1c, 0x7, 0x80, 0x1c, 0x1f, 0x0, 0x1f, 0xfc, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x3e, 0x0, 0x0, 0xff, 0x80, 0x0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {2, 15, 23, 1, 14, 0} +#define NXFONT_BITMAP_223 {0x7, 0xc0, 0xc, 0x70, 0x18, 0x38, 0x18, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x30, 0x38, 0x60, 0x39, 0xc0, 0x38, 0x78, 0x38, 0x1c, 0x38, 0x1e, 0x38, 0xe, 0x38, 0xe, 0x38, 0xe, 0x38, 0xe, 0x38, 0xe, 0x3b, 0xc, 0x3b, 0x9c, 0x3b, 0x98, 0xf9, 0xf0} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {2, 13, 23, 1, 14, 0} +#define NXFONT_BITMAP_224 {0x18, 0x0, 0x1c, 0x0, 0xe, 0x0, 0x3, 0x0, 0x1, 0x80, 0x0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x31, 0xc0, 0x70, 0xe0, 0x70, 0xe0, 0x60, 0xe0, 0x3, 0xe0, 0xe, 0xe0, 0x18, 0xe0, 0x30, 0xe0, 0x60, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf2, 0xe8, 0x7e, 0xf8, 0x3c, 0x70} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {2, 13, 23, 1, 14, 0} +#define NXFONT_BITMAP_225 {0x0, 0xc0, 0x1, 0xc0, 0x3, 0x80, 0x6, 0x0, 0xc, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x31, 0xc0, 0x70, 0xe0, 0x70, 0xe0, 0x60, 0xe0, 0x3, 0xe0, 0xe, 0xe0, 0x18, 0xe0, 0x30, 0xe0, 0x60, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf2, 0xe8, 0x7e, 0xf8, 0x3c, 0x70} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {2, 13, 23, 1, 14, 0} +#define NXFONT_BITMAP_226 {0x6, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x39, 0xc0, 0x60, 0x60, 0x40, 0x20, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x31, 0xc0, 0x70, 0xe0, 0x70, 0xe0, 0x60, 0xe0, 0x3, 0xe0, 0xe, 0xe0, 0x18, 0xe0, 0x30, 0xe0, 0x60, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf2, 0xe8, 0x7e, 0xf8, 0x3c, 0x70} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {2, 13, 21, 1, 16, 0} +#define NXFONT_BITMAP_227 {0x1c, 0x10, 0x3e, 0x30, 0x63, 0xe0, 0x41, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x31, 0xc0, 0x70, 0xe0, 0x70, 0xe0, 0x60, 0xe0, 0x3, 0xe0, 0xe, 0xe0, 0x18, 0xe0, 0x30, 0xe0, 0x60, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf2, 0xe8, 0x7e, 0xf8, 0x3c, 0x70} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {2, 13, 21, 1, 16, 0} +#define NXFONT_BITMAP_228 {0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x31, 0xc0, 0x70, 0xe0, 0x70, 0xe0, 0x60, 0xe0, 0x3, 0xe0, 0xe, 0xe0, 0x18, 0xe0, 0x30, 0xe0, 0x60, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf2, 0xe8, 0x7e, 0xf8, 0x3c, 0x70} + +/* aring (229) */ +#define NXFONT_METRICS_229 {2, 13, 23, 1, 14, 0} +#define NXFONT_BITMAP_229 {0x7, 0x0, 0xf, 0x80, 0x18, 0xc0, 0x10, 0x40, 0x18, 0xc0, 0xf, 0x80, 0x7, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x31, 0xc0, 0x70, 0xe0, 0x70, 0xe0, 0x60, 0xe0, 0x3, 0xe0, 0xe, 0xe0, 0x18, 0xe0, 0x30, 0xe0, 0x60, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xf2, 0xe8, 0x7e, 0xf8, 0x3c, 0x70} + +/* ae (230) */ +#define NXFONT_METRICS_230 {3, 19, 15, 1, 22, 0} +#define NXFONT_BITMAP_230 {0x1f, 0x9f, 0x0, 0x31, 0xf9, 0xc0, 0x70, 0xe0, 0xc0, 0x70, 0xe0, 0xe0, 0x60, 0xe0, 0xe0, 0x3, 0xff, 0xe0, 0xe, 0xe0, 0x0, 0x18, 0xe0, 0x0, 0x30, 0xe0, 0x0, 0x60, 0xe0, 0x0, 0xe0, 0xe0, 0x20, 0xe1, 0xf0, 0x60, 0xf3, 0x78, 0xc0, 0x7e, 0x3f, 0x80, 0x3c, 0x1f, 0x0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {2, 12, 22, 1, 22, 0} +#define NXFONT_BITMAP_231 {0xf, 0x80, 0x38, 0xc0, 0x70, 0xe0, 0x60, 0xe0, 0xe0, 0x60, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0xe0, 0x10, 0x70, 0x30, 0x7c, 0x60, 0x3f, 0xc0, 0xf, 0x0, 0x4, 0x0, 0xc, 0x0, 0xf, 0x0, 0x3, 0x80, 0x1, 0x80, 0x3, 0x80, 0x1f, 0x0} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {2, 12, 23, 1, 14, 0} +#define NXFONT_BITMAP_232 {0x30, 0x0, 0x38, 0x0, 0x1c, 0x0, 0x6, 0x0, 0x3, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0xf, 0x80, 0x39, 0xc0, 0x60, 0xe0, 0x60, 0x70, 0xc0, 0x70, 0xff, 0xf0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0xe0, 0x10, 0x70, 0x30, 0x7c, 0x60, 0x3f, 0xc0, 0xf, 0x0} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {2, 12, 23, 1, 14, 0} +#define NXFONT_BITMAP_233 {0x1, 0x80, 0x3, 0x80, 0x7, 0x0, 0xc, 0x0, 0x18, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x80, 0x39, 0xc0, 0x60, 0xe0, 0x60, 0x70, 0xc0, 0x70, 0xff, 0xf0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0xe0, 0x10, 0x70, 0x30, 0x7c, 0x60, 0x3f, 0xc0, 0xf, 0x0} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {2, 12, 23, 1, 14, 0} +#define NXFONT_BITMAP_234 {0x6, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x39, 0xc0, 0x60, 0x60, 0x40, 0x20, 0x0, 0x0, 0x0, 0x0, 0xf, 0x80, 0x39, 0xc0, 0x60, 0xe0, 0x60, 0x70, 0xc0, 0x70, 0xff, 0xf0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0xe0, 0x10, 0x70, 0x30, 0x7c, 0x60, 0x3f, 0xc0, 0xf, 0x0} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {2, 12, 21, 1, 16, 0} +#define NXFONT_BITMAP_235 {0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x80, 0x39, 0xc0, 0x60, 0xe0, 0x60, 0x70, 0xc0, 0x70, 0xff, 0xf0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xe0, 0x0, 0xe0, 0x10, 0x70, 0x30, 0x7c, 0x60, 0x3f, 0xc0, 0xf, 0x0} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 7, 23, 1, 14, 0} +#define NXFONT_BITMAP_236 {0xc0, 0xe0, 0x70, 0x18, 0xc, 0x6, 0x0, 0x0, 0x18, 0xf8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xfe} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 7, 23, 1, 14, 0} +#define NXFONT_BITMAP_237 {0x6, 0xe, 0x1c, 0x30, 0x60, 0xc0, 0x0, 0x0, 0x18, 0xf8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xfe} + +/* icircumflex (238) */ +#define NXFONT_METRICS_238 {2, 10, 23, 0, 14, 0} +#define NXFONT_BITMAP_238 {0xc, 0x0, 0x1e, 0x0, 0x3f, 0x0, 0x73, 0x80, 0xc0, 0xc0, 0x80, 0x40, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0x7c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x7f, 0x0} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {2, 9, 21, 0, 16, 0} +#define NXFONT_BITMAP_239 {0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0x7c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x7f, 0x0} + +/* eth (240) */ +#define NXFONT_METRICS_240 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_240 {0x10, 0x0, 0x38, 0x0, 0x1c, 0x70, 0xf, 0xf0, 0xf, 0x0, 0x7f, 0x80, 0x31, 0xc0, 0x0, 0xe0, 0x7, 0xf0, 0x18, 0xf0, 0x30, 0x78, 0x70, 0x38, 0x60, 0x3c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0x70, 0x18, 0x70, 0x38, 0x38, 0x30, 0x1c, 0x60, 0x7, 0x80} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {2, 16, 21, 0, 16, 0} +#define NXFONT_BITMAP_241 {0xe, 0x8, 0x1f, 0x18, 0x31, 0xf0, 0x20, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x18, 0xf0, 0xfb, 0xf8, 0x3e, 0x3c, 0x3c, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0xfe, 0x7f} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_242 {0x18, 0x0, 0x1c, 0x0, 0xe, 0x0, 0x3, 0x0, 0x1, 0x80, 0x0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x80, 0x18, 0xe0, 0x30, 0x70, 0x70, 0x38, 0x60, 0x38, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0x70, 0x18, 0x70, 0x38, 0x38, 0x30, 0x1c, 0x60, 0x7, 0x80} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_243 {0x0, 0xc0, 0x1, 0xc0, 0x3, 0x80, 0x6, 0x0, 0xc, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x80, 0x18, 0xe0, 0x30, 0x70, 0x70, 0x38, 0x60, 0x38, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0x70, 0x18, 0x70, 0x38, 0x38, 0x30, 0x1c, 0x60, 0x7, 0x80} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_244 {0x3, 0x0, 0x7, 0x80, 0xf, 0xc0, 0x1c, 0xe0, 0x30, 0x30, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x7, 0x80, 0x18, 0xe0, 0x30, 0x70, 0x70, 0x38, 0x60, 0x38, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0x70, 0x18, 0x70, 0x38, 0x38, 0x30, 0x1c, 0x60, 0x7, 0x80} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {2, 14, 21, 1, 16, 0} +#define NXFONT_BITMAP_245 {0x1c, 0x10, 0x3e, 0x30, 0x63, 0xe0, 0x41, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x80, 0x18, 0xe0, 0x30, 0x70, 0x70, 0x38, 0x60, 0x38, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0x70, 0x18, 0x70, 0x38, 0x38, 0x30, 0x1c, 0x60, 0x7, 0x80} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {2, 14, 21, 1, 16, 0} +#define NXFONT_BITMAP_246 {0x38, 0xe0, 0x38, 0xe0, 0x38, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x80, 0x18, 0xe0, 0x30, 0x70, 0x70, 0x38, 0x60, 0x38, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0xe0, 0x1c, 0x70, 0x18, 0x70, 0x38, 0x38, 0x30, 0x1c, 0x60, 0x7, 0x80} + +/* divide (247) */ +#define NXFONT_METRICS_247 {2, 16, 17, 1, 20, 0} +#define NXFONT_BITMAP_247 {0x1, 0x80, 0x3, 0xc0, 0x3, 0xc0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x3, 0xc0, 0x3, 0xc0, 0x1, 0x80} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {2, 14, 21, 1, 19, 0} +#define NXFONT_BITMAP_248 {0x0, 0x18, 0x0, 0x10, 0x0, 0x30, 0x7, 0xa0, 0x18, 0xe0, 0x30, 0xf0, 0x70, 0xb8, 0x61, 0xb8, 0xe1, 0x1c, 0xe1, 0x1c, 0xe3, 0x1c, 0xe2, 0x1c, 0xe6, 0x1c, 0x74, 0x18, 0x74, 0x38, 0x3c, 0x30, 0x1c, 0x60, 0x1f, 0x80, 0x30, 0x0, 0x20, 0x0, 0x60, 0x0} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {2, 16, 23, 0, 14, 0} +#define NXFONT_BITMAP_249 {0xc, 0x0, 0xe, 0x0, 0x7, 0x0, 0x1, 0x80, 0x0, 0xc0, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x7c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x3c, 0x3c, 0x7c, 0x1f, 0xdf, 0xf, 0x98} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {2, 16, 23, 0, 14, 0} +#define NXFONT_BITMAP_250 {0x0, 0x60, 0x0, 0xe0, 0x1, 0xc0, 0x3, 0x0, 0x6, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x7c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x3c, 0x3c, 0x7c, 0x1f, 0xdf, 0xf, 0x98} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {2, 16, 23, 0, 14, 0} +#define NXFONT_BITMAP_251 {0x1, 0x80, 0x3, 0xc0, 0x7, 0xe0, 0xe, 0x70, 0x18, 0x18, 0x10, 0x8, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x7c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x3c, 0x3c, 0x7c, 0x1f, 0xdf, 0xf, 0x98} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {2, 16, 21, 0, 16, 0} +#define NXFONT_BITMAP_252 {0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x7c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x3c, 0x3c, 0x7c, 0x1f, 0xdf, 0xf, 0x98} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {2, 15, 30, 0, 14, 0} +#define NXFONT_BITMAP_253 {0x0, 0x18, 0x0, 0x38, 0x0, 0x70, 0x0, 0xc0, 0x1, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x1e, 0x78, 0xc, 0x38, 0xc, 0x3c, 0x8, 0x1c, 0x18, 0x1e, 0x18, 0xe, 0x10, 0xe, 0x30, 0x7, 0x20, 0x7, 0x20, 0x3, 0xe0, 0x3, 0xc0, 0x1, 0xc0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x2, 0x0, 0x3e, 0x0, 0x7c, 0x0, 0x38, 0x0} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {2, 15, 30, 0, 14, 0} +#define NXFONT_BITMAP_254 {0x18, 0x0, 0xf8, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x39, 0xf0, 0x3b, 0xf8, 0x3e, 0x7c, 0x3c, 0x1c, 0x38, 0x1e, 0x38, 0xe, 0x38, 0xe, 0x38, 0xe, 0x38, 0xe, 0x38, 0xe, 0x38, 0xc, 0x38, 0x1c, 0x3c, 0x18, 0x3e, 0x30, 0x3b, 0xe0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x0, 0xff, 0x0} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {2, 15, 28, 1, 16, 0} +#define NXFONT_BITMAP_255 {0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x1e, 0x78, 0xc, 0x38, 0xc, 0x3c, 0x8, 0x1c, 0x18, 0x1e, 0x18, 0xe, 0x10, 0xe, 0x30, 0x7, 0x20, 0x7, 0x20, 0x3, 0xe0, 0x3, 0xc0, 0x1, 0xc0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x1, 0x0, 0x3, 0x0, 0x2, 0x0, 0x3e, 0x0, 0x7c, 0x0, 0x38, 0x0} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SERIF38X48_H */ diff --git a/nuttx/graphics/nxfonts/nxfonts_serif38x49b.h b/nuttx/graphics/nxfonts/nxfonts_serif38x49b.h new file mode 100644 index 0000000000..70291a0457 --- /dev/null +++ b/nuttx/graphics/nxfonts/nxfonts_serif38x49b.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * graphics/nxfonts/nxfonts_serif38x49.h + * + * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved. + * Author: Jose Pablo Carballo Gomez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT} + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING} + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXFONTS_NXFONTS_SERIF38X49B_H +#define __GRAPHICS_NXFONTS_NXFONTS_SERIF38X49B_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Font ID */ + +#define NXFONT_ID FONTID_SERIF38X49B + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/* Maximum height and width of any glyph in the set */ + +#define NXFONT_MAXHEIGHT 49 +#define NXFONT_MAXWIDTH 38 + +/* The width of a space */ + +#define NXFONT_SPACEWIDTH 8 + +/* exclam (33) */ +#define NXFONT_METRICS_33 {1, 5, 23, 3, 14, 0} +#define NXFONT_BITMAP_33 {0x70, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x70, 0x70, 0x70, 0x70, 0x20, 0x20, 0x20, 0x20, 0x0, 0x0, 0x0, 0x70, 0xf8, 0xf8, 0xf8, 0x70} + +/* quotedbl (34) */ +#define NXFONT_METRICS_34 {2, 11, 11, 2, 14, 0} +#define NXFONT_BITMAP_34 {0x60, 0xc0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0xf1, 0xe0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, 0xc0} + +/* numbersign (35) */ +#define NXFONT_METRICS_35 {2, 16, 23, 0, 14, 0} +#define NXFONT_BITMAP_35 {0x3, 0xc, 0x3, 0xc, 0x7, 0x1c, 0x7, 0x1c, 0x6, 0x18, 0x6, 0x18, 0x7f, 0xff, 0x7f, 0xff, 0xe, 0x38, 0xc, 0x30, 0xc, 0x30, 0xc, 0x30, 0xc, 0x30, 0x1c, 0x70, 0xff, 0xfe, 0xff, 0xfe, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x38, 0xe0, 0x38, 0xe0, 0x30, 0xc0, 0x30, 0xc0} + +/* dollar (36) */ +#define NXFONT_METRICS_36 {2, 15, 28, 1, 12, 0} +#define NXFONT_BITMAP_36 {0x3, 0x0, 0x3, 0x0, 0xf, 0xe8, 0x3f, 0xf8, 0x73, 0x38, 0x63, 0x18, 0xe3, 0x8, 0xe3, 0x8, 0xf3, 0x0, 0xfb, 0x0, 0x7f, 0x0, 0x7f, 0x80, 0x3f, 0xe0, 0xf, 0xf0, 0x3, 0xf8, 0x3, 0xfc, 0x3, 0x7c, 0x83, 0x3e, 0x83, 0x1e, 0x83, 0x1e, 0xc3, 0x1c, 0xc3, 0x3c, 0xf3, 0x78, 0xff, 0xe0, 0x83, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0} + +/* percent (37) */ +#define NXFONT_METRICS_37 {3, 24, 23, 4, 14, 0} +#define NXFONT_BITMAP_37 {0x7, 0x80, 0x20, 0xf, 0xc0, 0xe0, 0x1e, 0x7f, 0xc0, 0x3c, 0x20, 0xc0, 0x7c, 0x21, 0x80, 0x78, 0x21, 0x80, 0xf8, 0x63, 0x0, 0xf0, 0x47, 0x0, 0xf0, 0xc6, 0x0, 0xf0, 0xce, 0x0, 0xf1, 0x8c, 0x3c, 0x7f, 0x18, 0x7e, 0x3c, 0x19, 0xf3, 0x0, 0x31, 0xe1, 0x0, 0x33, 0xc1, 0x0, 0x63, 0xc1, 0x0, 0xe7, 0xc3, 0x0, 0xc7, 0x82, 0x1, 0xc7, 0x86, 0x1, 0x87, 0x86, 0x3, 0x3, 0x8c, 0x3, 0x3, 0xf8, 0x6, 0x1, 0xe0} + +/* ampersand (38) */ +#define NXFONT_METRICS_38 {3, 22, 23, 2, 14, 0} +#define NXFONT_BITMAP_38 {0x1, 0xf0, 0x0, 0x3, 0xbc, 0x0, 0x7, 0x1e, 0x0, 0x7, 0xe, 0x0, 0xf, 0xe, 0x0, 0xf, 0xe, 0x0, 0xf, 0x8c, 0x0, 0x7, 0xd8, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xe0, 0xfc, 0x7, 0xf0, 0x70, 0x1d, 0xf0, 0x30, 0x39, 0xf8, 0x60, 0x70, 0xfc, 0x40, 0xf0, 0xfc, 0xc0, 0xf0, 0x7f, 0x80, 0xf8, 0x3f, 0x0, 0xf8, 0x1f, 0x80, 0xfc, 0x1f, 0xc0, 0xfe, 0x3f, 0xe4, 0x7f, 0xf3, 0xfc, 0x7f, 0xc1, 0xfc, 0x1f, 0x0, 0x78} + +/* quotesingle (39) */ +#define NXFONT_METRICS_39 {1, 4, 11, 2, 14, 0} +#define NXFONT_BITMAP_39 {0x60, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x60, 0x60, 0x60, 0x60} + +/* parenleft (40) */ +#define NXFONT_METRICS_40 {1, 8, 29, 2, 14, 0} +#define NXFONT_BITMAP_40 {0x3, 0x6, 0xc, 0x18, 0x18, 0x30, 0x30, 0x70, 0x60, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x60, 0x70, 0x30, 0x30, 0x18, 0x18, 0xc, 0x6, 0x3} + +/* parenright (41) */ +#define NXFONT_METRICS_41 {1, 8, 29, 0, 14, 0} +#define NXFONT_BITMAP_41 {0xc0, 0x60, 0x30, 0x18, 0x18, 0xc, 0xc, 0xe, 0x6, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0xe, 0xc, 0xc, 0x18, 0x18, 0x30, 0x60, 0xc0} + +/* asterisk (42) */ +#define NXFONT_METRICS_42 {2, 13, 14, 1, 14, 0} +#define NXFONT_BITMAP_42 {0x3, 0x0, 0x7, 0x0, 0x7, 0x0, 0xe7, 0x38, 0xf2, 0x78, 0x7a, 0xf0, 0xf, 0x80, 0xf, 0x80, 0x7a, 0xf0, 0xf2, 0x78, 0xe7, 0x38, 0x7, 0x0, 0x7, 0x0, 0x6, 0x0} + +/* plus (43) */ +#define NXFONT_METRICS_43 {2, 15, 15, 2, 22, 0} +#define NXFONT_BITMAP_43 {0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80} + +/* comma (44) */ +#define NXFONT_METRICS_44 {1, 6, 11, 1, 32, 0} +#define NXFONT_BITMAP_44 {0x38, 0x7c, 0x7c, 0x7c, 0x3c, 0xc, 0x8, 0x18, 0x30, 0x60, 0xc0} + +/* hyphen (45) */ +#define NXFONT_METRICS_45 {1, 8, 4, 1, 27, 0} +#define NXFONT_BITMAP_45 {0xff, 0xff, 0xff, 0xff} + +/* period (46) */ +#define NXFONT_METRICS_46 {1, 5, 5, 1, 32, 0} +#define NXFONT_BITMAP_46 {0x70, 0xf8, 0xf8, 0xf8, 0x70} + +/* slash (47) */ +#define NXFONT_METRICS_47 {2, 9, 25, 0, 12, 0} +#define NXFONT_BITMAP_47 {0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x4, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0xc0, 0x0, 0xc0, 0x0} + +/* zero (48) */ +#define NXFONT_METRICS_48 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_48 {0x7, 0x80, 0x1f, 0xe0, 0x1c, 0xe0, 0x38, 0x70, 0x78, 0x70, 0x78, 0x78, 0x78, 0x78, 0xf8, 0x7c, 0xf8, 0x7c, 0xf8, 0x7c, 0xf8, 0x7c, 0xf8, 0x7c, 0xf8, 0x7c, 0xf8, 0x7c, 0xf8, 0x7c, 0xf8, 0x7c, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x38, 0x70, 0x1c, 0xe0, 0xf, 0xc0, 0x7, 0x80} + +/* one (49) */ +#define NXFONT_METRICS_49 {2, 13, 23, 2, 14, 0} +#define NXFONT_BITMAP_49 {0x1, 0x80, 0x7, 0x80, 0x1f, 0x80, 0xff, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0x1f, 0xc0, 0xff, 0xf8} + +/* two (50) */ +#define NXFONT_METRICS_50 {2, 16, 23, 0, 14, 0} +#define NXFONT_BITMAP_50 {0x3, 0xc0, 0xf, 0xf0, 0x1f, 0xf8, 0x3f, 0xf8, 0x30, 0xfc, 0x60, 0x7c, 0x40, 0x7c, 0x0, 0x7c, 0x0, 0x78, 0x0, 0x78, 0x0, 0x78, 0x0, 0xf0, 0x0, 0xe0, 0x1, 0xc0, 0x1, 0x80, 0x3, 0x0, 0x7, 0x1, 0xe, 0x3, 0x1c, 0x6, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfc, 0xff, 0xfc} + +/* three (51) */ +#define NXFONT_METRICS_51 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_51 {0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf0, 0x30, 0xf8, 0x60, 0x78, 0x40, 0x78, 0x0, 0x78, 0x0, 0x70, 0x0, 0xc0, 0x3, 0xe0, 0xf, 0xf0, 0xf, 0xf8, 0x3, 0xf8, 0x0, 0xfc, 0x0, 0x7c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x60, 0x38, 0xf0, 0x38, 0xf8, 0x70, 0x7f, 0xc0, 0x1f, 0x0} + +/* four (52) */ +#define NXFONT_METRICS_52 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_52 {0x0, 0x70, 0x0, 0xf0, 0x0, 0xf0, 0x1, 0xf0, 0x3, 0xf0, 0x6, 0xf0, 0x6, 0xf0, 0xc, 0xf0, 0x18, 0xf0, 0x18, 0xf0, 0x30, 0xf0, 0x60, 0xf0, 0x60, 0xf0, 0xc0, 0xf0, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0} + +/* five (53) */ +#define NXFONT_METRICS_53 {2, 13, 23, 1, 14, 0} +#define NXFONT_BITMAP_53 {0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x30, 0x0, 0x30, 0x0, 0x20, 0x0, 0x3e, 0x0, 0x7f, 0x80, 0x7f, 0xe0, 0x7f, 0xf0, 0x7f, 0xf0, 0x3, 0xf8, 0x0, 0xf8, 0x0, 0x78, 0x0, 0x38, 0x0, 0x38, 0x0, 0x38, 0x60, 0x30, 0xf0, 0x30, 0xf8, 0x60, 0x7f, 0xc0, 0x1f, 0x0} + +/* six (54) */ +#define NXFONT_METRICS_54 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_54 {0x0, 0x1c, 0x0, 0xf0, 0x3, 0xc0, 0x7, 0x80, 0xf, 0x0, 0x1e, 0x0, 0x3e, 0x0, 0x3c, 0x0, 0x7c, 0x0, 0x7f, 0xe0, 0xfd, 0xf0, 0xf8, 0xf8, 0xf8, 0x78, 0xf8, 0x7c, 0xf8, 0x7c, 0xf8, 0x7c, 0xf8, 0x7c, 0x78, 0x7c, 0x78, 0x78, 0x78, 0x78, 0x38, 0x70, 0x1c, 0xe0, 0xf, 0xc0} + +/* seven (55) */ +#define NXFONT_METRICS_55 {2, 13, 23, 2, 14, 0} +#define NXFONT_BITMAP_55 {0x7f, 0xf8, 0x7f, 0xf8, 0xff, 0xf8, 0xff, 0xf8, 0xc0, 0x30, 0x80, 0x70, 0x80, 0x70, 0x0, 0x60, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xc0, 0x1, 0xc0, 0x1, 0xc0, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1c, 0x0} + +/* eight (56) */ +#define NXFONT_METRICS_56 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_56 {0xf, 0xe0, 0x3e, 0xf0, 0x3c, 0x78, 0x78, 0x78, 0x78, 0x38, 0x78, 0x38, 0x7c, 0x38, 0x7e, 0x70, 0x3f, 0xe0, 0x3f, 0x80, 0x1f, 0xc0, 0xf, 0xe0, 0x3f, 0xf0, 0x71, 0xf8, 0x70, 0xfc, 0xe0, 0x7c, 0xe0, 0x3c, 0xe0, 0x3c, 0xe0, 0x3c, 0xf0, 0x38, 0x78, 0x78, 0x7f, 0xf0, 0x1f, 0xc0} + +/* nine (57) */ +#define NXFONT_METRICS_57 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_57 {0xf, 0xc0, 0x1c, 0xe0, 0x38, 0x70, 0x78, 0x78, 0x78, 0x78, 0xf8, 0x78, 0xf8, 0x7c, 0xf8, 0x7c, 0xf8, 0x7c, 0xf8, 0x7c, 0x78, 0x7c, 0x7c, 0x7c, 0x3e, 0xfc, 0x1f, 0xf8, 0x0, 0xf8, 0x0, 0xf0, 0x1, 0xf0, 0x1, 0xe0, 0x3, 0xc0, 0x7, 0x80, 0xf, 0x0, 0x3c, 0x0, 0xe0, 0x0} + +/* colon (58) */ +#define NXFONT_METRICS_58 {1, 5, 16, 3, 21, 0} +#define NXFONT_BITMAP_58 {0x70, 0xf8, 0xf8, 0xf8, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x70, 0xf8, 0xf8, 0xf8, 0x70} + +/* semicolon (59) */ +#define NXFONT_METRICS_59 {1, 6, 22, 2, 21, 0} +#define NXFONT_BITMAP_59 {0x38, 0x7c, 0x7c, 0x7c, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x7c, 0x7c, 0x7c, 0x3c, 0xc, 0x8, 0x18, 0x30, 0x60, 0xc0} + +/* less (60) */ +#define NXFONT_METRICS_60 {2, 16, 15, 1, 22, 0} +#define NXFONT_BITMAP_60 {0x0, 0x3, 0x0, 0xf, 0x0, 0x7f, 0x1, 0xfc, 0xf, 0xe0, 0x3f, 0x80, 0xfc, 0x0, 0xf0, 0x0, 0xfc, 0x0, 0x3f, 0x80, 0xf, 0xe0, 0x1, 0xfc, 0x0, 0x7f, 0x0, 0xf, 0x0, 0x3} + +/* equal (61) */ +#define NXFONT_METRICS_61 {2, 15, 10, 2, 24, 0} +#define NXFONT_BITMAP_61 {0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe} + +/* greater (62) */ +#define NXFONT_METRICS_62 {2, 16, 15, 2, 22, 0} +#define NXFONT_BITMAP_62 {0xc0, 0x0, 0xf0, 0x0, 0xfe, 0x0, 0x3f, 0x80, 0x7, 0xf0, 0x1, 0xfc, 0x0, 0x3f, 0x0, 0xf, 0x0, 0x3f, 0x1, 0xfc, 0x7, 0xf0, 0x3f, 0x80, 0xfe, 0x0, 0xf0, 0x0, 0xc0, 0x0} + +/* question (63) */ +#define NXFONT_METRICS_63 {2, 12, 23, 2, 14, 0} +#define NXFONT_BITMAP_63 {0x3f, 0x0, 0x73, 0xc0, 0xe1, 0xe0, 0xe1, 0xf0, 0xf1, 0xf0, 0xf1, 0xf0, 0x61, 0xf0, 0x1, 0xe0, 0x1, 0xe0, 0x3, 0xc0, 0x3, 0x80, 0x3, 0x0, 0x6, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0xe, 0x0} + +/* at (64) */ +#define NXFONT_METRICS_64 {4, 26, 27, 2, 15, 0} +#define NXFONT_BITMAP_64 {0x0, 0x1f, 0xe0, 0x0, 0x0, 0xfc, 0x3c, 0x0, 0x3, 0xe0, 0xe, 0x0, 0x7, 0x80, 0x3, 0x0, 0xf, 0x0, 0x1, 0x0, 0x1e, 0x0, 0x1, 0x80, 0x3e, 0xf, 0x38, 0x80, 0x3c, 0x1f, 0xf8, 0xc0, 0x7c, 0x7c, 0xf8, 0x40, 0x78, 0x78, 0x78, 0x40, 0xf8, 0xf8, 0xf0, 0x40, 0xf8, 0xf0, 0xf0, 0x40, 0xf1, 0xf0, 0xf0, 0x40, 0xf1, 0xf0, 0xf0, 0x40, 0xf1, 0xe0, 0xf0, 0xc0, 0xf1, 0xe1, 0xe0, 0x80, 0xf1, 0xe1, 0xe1, 0x80, 0xf1, 0xe3, 0xe3, 0x0, 0x71, 0xf3, 0xe3, 0x0, 0x78, 0xfe, 0xfe, 0x0, 0x78, 0x78, 0x78, 0x0, 0x3c, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0xe, 0x0, 0x1, 0x80, 0x7, 0x80, 0x7, 0x0, 0x1, 0xe0, 0x3c, 0x0, 0x0, 0x3f, 0xe0, 0x0} + +/* A (65) */ +#define NXFONT_METRICS_65 {3, 21, 23, 1, 14, 0} +#define NXFONT_BITMAP_65 {0x0, 0x20, 0x0, 0x0, 0x60, 0x0, 0x0, 0x70, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x1, 0x7c, 0x0, 0x1, 0x7c, 0x0, 0x3, 0x3e, 0x0, 0x2, 0x3e, 0x0, 0x6, 0x3e, 0x0, 0x6, 0x1f, 0x0, 0x4, 0x1f, 0x0, 0xc, 0xf, 0x0, 0xf, 0xff, 0x80, 0x18, 0xf, 0x80, 0x18, 0x7, 0xc0, 0x10, 0x7, 0xc0, 0x30, 0x3, 0xe0, 0x30, 0x3, 0xe0, 0x70, 0x7, 0xf0, 0xfc, 0x1f, 0xf8} + +/* B (66) */ +#define NXFONT_METRICS_66 {3, 19, 23, 1, 14, 0} +#define NXFONT_BITMAP_66 {0xff, 0xfc, 0x0, 0x3f, 0x1f, 0x0, 0x1f, 0xf, 0x80, 0x1f, 0x7, 0xc0, 0x1f, 0x7, 0xc0, 0x1f, 0x7, 0xc0, 0x1f, 0x7, 0xc0, 0x1f, 0x7, 0xc0, 0x1f, 0x7, 0x80, 0x1f, 0xf, 0x80, 0x1f, 0x3e, 0x0, 0x1f, 0xfc, 0x0, 0x1f, 0xf, 0x80, 0x1f, 0x7, 0xc0, 0x1f, 0x7, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x3, 0xc0, 0x1f, 0x7, 0xc0, 0x3f, 0xf, 0x0, 0xff, 0xfc, 0x0} + +/* C (67) */ +#define NXFONT_METRICS_67 {3, 19, 23, 2, 14, 0} +#define NXFONT_BITMAP_67 {0x1, 0xfc, 0x20, 0x7, 0xff, 0x60, 0xf, 0x7, 0xe0, 0x1e, 0x1, 0xe0, 0x3c, 0x0, 0xe0, 0x7c, 0x0, 0x60, 0x7c, 0x0, 0x60, 0xf8, 0x0, 0x20, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x3c, 0x0, 0x20, 0x1e, 0x0, 0x60, 0xf, 0x81, 0xc0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* D (68) */ +#define NXFONT_METRICS_68 {3, 22, 23, 0, 14, 0} +#define NXFONT_BITMAP_68 {0xff, 0xfc, 0x0, 0x3f, 0xff, 0x80, 0x1f, 0x7, 0xe0, 0x1f, 0x1, 0xf0, 0x1f, 0x1, 0xf0, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xfc, 0x1f, 0x0, 0x7c, 0x1f, 0x0, 0x7c, 0x1f, 0x0, 0x7c, 0x1f, 0x0, 0x7c, 0x1f, 0x0, 0x7c, 0x1f, 0x0, 0x7c, 0x1f, 0x0, 0x7c, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x1, 0xf0, 0x1f, 0x1, 0xe0, 0x1f, 0x7, 0xc0, 0x3f, 0xff, 0x0, 0xff, 0xfc, 0x0} + +/* E (69) */ +#define NXFONT_METRICS_69 {3, 21, 23, 0, 14, 0} +#define NXFONT_BITMAP_69 {0xff, 0xff, 0xe0, 0x3f, 0xff, 0xe0, 0x1f, 0x0, 0xe0, 0x1f, 0x0, 0x60, 0x1f, 0x0, 0x60, 0x1f, 0x0, 0x20, 0x1f, 0x0, 0x20, 0x1f, 0x4, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0xc, 0x0, 0x1f, 0x1c, 0x0, 0x1f, 0xfc, 0x0, 0x1f, 0x1c, 0x0, 0x1f, 0xc, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0x0, 0x8, 0x1f, 0x0, 0x18, 0x1f, 0x0, 0x30, 0x1f, 0x0, 0x70, 0x1f, 0x1, 0xf0, 0x3f, 0xff, 0xe0, 0xff, 0xff, 0xe0} + +/* F (70) */ +#define NXFONT_METRICS_70 {3, 19, 23, 0, 14, 0} +#define NXFONT_BITMAP_70 {0xff, 0xff, 0xe0, 0x3f, 0xff, 0xe0, 0x1f, 0x0, 0xe0, 0x1f, 0x0, 0x60, 0x1f, 0x0, 0x60, 0x1f, 0x0, 0x20, 0x1f, 0x0, 0x20, 0x1f, 0x4, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0xc, 0x0, 0x1f, 0x1c, 0x0, 0x1f, 0xfc, 0x0, 0x1f, 0x1c, 0x0, 0x1f, 0xc, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x3f, 0x80, 0x0, 0xff, 0xe0, 0x0} + +/* G (71) */ +#define NXFONT_METRICS_71 {3, 22, 23, 2, 14, 0} +#define NXFONT_BITMAP_71 {0x1, 0xfc, 0x20, 0x7, 0xff, 0x60, 0xf, 0x7, 0xe0, 0x1e, 0x1, 0xe0, 0x3c, 0x0, 0xe0, 0x7c, 0x0, 0x60, 0x7c, 0x0, 0x60, 0xf8, 0x0, 0x20, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x1f, 0xfc, 0xf8, 0x7, 0xf0, 0xf8, 0x3, 0xe0, 0x7c, 0x3, 0xe0, 0x7c, 0x3, 0xe0, 0x3c, 0x3, 0xe0, 0x3e, 0x3, 0xe0, 0x1e, 0x7, 0xe0, 0xf, 0x8f, 0xe0, 0x3, 0xff, 0x0} + +/* H (72) */ +#define NXFONT_METRICS_72 {3, 24, 23, 0, 14, 0} +#define NXFONT_BITMAP_72 {0xff, 0xe7, 0xff, 0x3f, 0x81, 0xfc, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0xff, 0xf8, 0x1f, 0xff, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x3f, 0x81, 0xfc, 0xff, 0xe7, 0xff} + +/* I (73) */ +#define NXFONT_METRICS_73 {2, 11, 23, 1, 14, 0} +#define NXFONT_BITMAP_73 {0xff, 0xe0, 0x3f, 0x80, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0xff, 0xe0} + +/* J (74) */ +#define NXFONT_METRICS_74 {2, 15, 26, 0, 14, 0} +#define NXFONT_BITMAP_74 {0xf, 0xfe, 0x3, 0xf8, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x61, 0xf0, 0xf1, 0xf0, 0xf1, 0xf0, 0xf3, 0xe0, 0xe3, 0xe0, 0x7f, 0xc0, 0x1f, 0x0} + +/* K (75) */ +#define NXFONT_METRICS_75 {3, 24, 23, 1, 14, 0} +#define NXFONT_BITMAP_75 {0xff, 0xcf, 0xfc, 0x7f, 0x3, 0xe0, 0x3e, 0x1, 0xc0, 0x3e, 0x3, 0x80, 0x3e, 0x7, 0x0, 0x3e, 0xe, 0x0, 0x3e, 0x1c, 0x0, 0x3e, 0x38, 0x0, 0x3e, 0x70, 0x0, 0x3e, 0xe0, 0x0, 0x3f, 0xf0, 0x0, 0x3f, 0xf8, 0x0, 0x3f, 0xfc, 0x0, 0x3e, 0xfe, 0x0, 0x3e, 0x7f, 0x0, 0x3e, 0x3f, 0x80, 0x3e, 0x1f, 0xc0, 0x3e, 0xf, 0xe0, 0x3e, 0x7, 0xf0, 0x3e, 0x3, 0xf8, 0x3e, 0x1, 0xfc, 0x7f, 0x0, 0xfe, 0xff, 0xc3, 0xff} + +/* L (76) */ +#define NXFONT_METRICS_76 {3, 20, 23, 1, 14, 0} +#define NXFONT_BITMAP_76 {0xff, 0xe0, 0x0, 0x3f, 0x80, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x30, 0x1f, 0x0, 0x60, 0x1f, 0x0, 0xe0, 0x1f, 0x81, 0xe0, 0x3f, 0xff, 0xc0, 0xff, 0xff, 0xc0} + +/* M (77) */ +#define NXFONT_METRICS_77 {4, 28, 23, 1, 14, 0} +#define NXFONT_BITMAP_77 {0xff, 0x0, 0xf, 0xf0, 0x3f, 0x0, 0x1f, 0xc0, 0x1f, 0x80, 0x1f, 0x80, 0x1f, 0x80, 0x3f, 0x80, 0x17, 0xc0, 0x3f, 0x80, 0x17, 0xc0, 0x2f, 0x80, 0x17, 0xc0, 0x6f, 0x80, 0x13, 0xe0, 0x4f, 0x80, 0x13, 0xe0, 0xcf, 0x80, 0x13, 0xe0, 0xcf, 0x80, 0x11, 0xf0, 0x8f, 0x80, 0x11, 0xf1, 0x8f, 0x80, 0x10, 0xf9, 0xf, 0x80, 0x10, 0xfb, 0xf, 0x80, 0x10, 0xfb, 0xf, 0x80, 0x10, 0x7e, 0xf, 0x80, 0x10, 0x7e, 0xf, 0x80, 0x10, 0x7c, 0xf, 0x80, 0x10, 0x3c, 0xf, 0x80, 0x10, 0x3c, 0xf, 0x80, 0x10, 0x18, 0xf, 0x80, 0x38, 0x18, 0x1f, 0xc0, 0xfe, 0x18, 0x3f, 0xf0} + +/* N (78) */ +#define NXFONT_METRICS_78 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_78 {0xfe, 0x1, 0xfc, 0x7f, 0x0, 0x70, 0x3f, 0x80, 0x20, 0x1f, 0x80, 0x20, 0x1f, 0xc0, 0x20, 0x1f, 0xe0, 0x20, 0x17, 0xf0, 0x20, 0x13, 0xf8, 0x20, 0x11, 0xf8, 0x20, 0x11, 0xfc, 0x20, 0x10, 0xfe, 0x20, 0x10, 0x7f, 0x20, 0x10, 0x3f, 0x20, 0x10, 0x1f, 0xa0, 0x10, 0x1f, 0xe0, 0x10, 0xf, 0xe0, 0x10, 0x7, 0xe0, 0x10, 0x3, 0xe0, 0x10, 0x3, 0xe0, 0x10, 0x1, 0xe0, 0x10, 0x0, 0xe0, 0x38, 0x0, 0x60, 0xfe, 0x0, 0x20} + +/* O (79) */ +#define NXFONT_METRICS_79 {3, 21, 23, 2, 14, 0} +#define NXFONT_BITMAP_79 {0x1, 0xfc, 0x0, 0x7, 0xff, 0x0, 0xf, 0x8f, 0x80, 0x1e, 0x3, 0xc0, 0x3c, 0x1, 0xe0, 0x7c, 0x1, 0xf0, 0x78, 0x0, 0xf0, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0x78, 0x0, 0xf0, 0x7c, 0x1, 0xf0, 0x3c, 0x1, 0xe0, 0x1e, 0x3, 0xc0, 0xf, 0x8f, 0x80, 0x7, 0xff, 0x0, 0x1, 0xfc, 0x0} + +/* P (80) */ +#define NXFONT_METRICS_80 {3, 19, 23, 0, 14, 0} +#define NXFONT_BITMAP_80 {0xff, 0xfc, 0x0, 0x3f, 0x1f, 0x80, 0x1f, 0xf, 0xc0, 0x1f, 0x7, 0xc0, 0x1f, 0x7, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x7, 0xc0, 0x1f, 0x7, 0xc0, 0x1f, 0x1f, 0x80, 0x1f, 0xfe, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x3f, 0x80, 0x0, 0xff, 0xe0, 0x0} + +/* Q (81) */ +#define NXFONT_METRICS_81 {3, 22, 27, 2, 14, 0} +#define NXFONT_BITMAP_81 {0x1, 0xfc, 0x0, 0x7, 0xff, 0x0, 0xf, 0x8f, 0x80, 0x1e, 0x3, 0xc0, 0x3c, 0x1, 0xe0, 0x7c, 0x1, 0xf0, 0x78, 0x0, 0xf0, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0x7c, 0x1, 0xf0, 0x7c, 0x1, 0xf0, 0x3e, 0x3, 0xe0, 0x1f, 0x7, 0xc0, 0x7, 0xff, 0x0, 0x1, 0xfc, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x7f, 0x84, 0x0, 0x1f, 0xf8, 0x0, 0x7, 0xe0} + +/* R (82) */ +#define NXFONT_METRICS_82 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_82 {0xff, 0xfc, 0x0, 0x3f, 0x1f, 0x80, 0x1f, 0x7, 0xc0, 0x1f, 0x7, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x7, 0xe0, 0x1f, 0x7, 0xc0, 0x1f, 0x1f, 0x80, 0x1f, 0xfc, 0x0, 0x1f, 0x7e, 0x0, 0x1f, 0x3e, 0x0, 0x1f, 0x3f, 0x0, 0x1f, 0x1f, 0x80, 0x1f, 0x1f, 0x80, 0x1f, 0xf, 0xc0, 0x1f, 0x7, 0xe0, 0x1f, 0x7, 0xe0, 0x1f, 0x3, 0xf0, 0x3f, 0x81, 0xf8, 0xff, 0xe1, 0xfc} + +/* S (83) */ +#define NXFONT_METRICS_83 {2, 15, 23, 1, 14, 0} +#define NXFONT_BITMAP_83 {0xf, 0xc4, 0x38, 0x7c, 0x70, 0x3c, 0x70, 0x1c, 0xf0, 0xc, 0xf0, 0xc, 0xf8, 0x4, 0xfc, 0x0, 0xff, 0x0, 0x7f, 0xc0, 0x3f, 0xf0, 0x1f, 0xf8, 0xf, 0xfc, 0x3, 0xfc, 0x1, 0xfe, 0x80, 0x7e, 0x80, 0x3e, 0xc0, 0x1e, 0xc0, 0x1e, 0xe0, 0x1c, 0xf0, 0x1c, 0xf8, 0x38, 0x8f, 0xe0} + +/* T (84) */ +#define NXFONT_METRICS_84 {3, 19, 23, 1, 14, 0} +#define NXFONT_BITMAP_84 {0xff, 0xff, 0xe0, 0xf9, 0xf3, 0xe0, 0xe1, 0xf0, 0xe0, 0xc1, 0xf0, 0x60, 0x81, 0xf0, 0x20, 0x81, 0xf0, 0x20, 0x81, 0xf0, 0x20, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x1, 0xf0, 0x0, 0x3, 0xf8, 0x0, 0xf, 0xfe, 0x0} + +/* U (85) */ +#define NXFONT_METRICS_85 {3, 23, 23, 0, 14, 0} +#define NXFONT_BITMAP_85 {0xff, 0xe0, 0xfe, 0x3f, 0x80, 0x38, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0xf, 0x80, 0x30, 0xf, 0x80, 0x60, 0x7, 0xc0, 0xc0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* V (86) */ +#define NXFONT_METRICS_86 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_86 {0xff, 0xc3, 0xfc, 0x7f, 0x0, 0xf0, 0x3e, 0x0, 0x60, 0x3f, 0x0, 0x40, 0x1f, 0x0, 0xc0, 0x1f, 0x80, 0xc0, 0xf, 0x80, 0x80, 0xf, 0x81, 0x80, 0xf, 0xc1, 0x0, 0x7, 0xc1, 0x0, 0x7, 0xc3, 0x0, 0x3, 0xe2, 0x0, 0x3, 0xe6, 0x0, 0x3, 0xf6, 0x0, 0x1, 0xf4, 0x0, 0x1, 0xfc, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x70, 0x0, 0x0, 0x70, 0x0, 0x0, 0x20, 0x0, 0x0, 0x20, 0x0} + +/* W (87) */ +#define NXFONT_METRICS_87 {4, 32, 23, 0, 14, 0} +#define NXFONT_BITMAP_87 {0xff, 0xef, 0xff, 0x3f, 0x7f, 0x3, 0xf8, 0xe, 0x3f, 0x1, 0xf8, 0xc, 0x1f, 0x1, 0xf8, 0xc, 0x1f, 0x1, 0xf8, 0x8, 0x1f, 0x81, 0xfc, 0x18, 0xf, 0x81, 0xfc, 0x18, 0xf, 0x81, 0x7c, 0x10, 0xf, 0xc3, 0x7c, 0x30, 0x7, 0xc2, 0x7e, 0x30, 0x7, 0xc6, 0x3e, 0x20, 0x7, 0xe6, 0x3e, 0x60, 0x3, 0xe4, 0x3e, 0x60, 0x3, 0xec, 0x1f, 0x40, 0x3, 0xf8, 0x1f, 0xc0, 0x1, 0xf8, 0x1f, 0xc0, 0x1, 0xf8, 0xf, 0x80, 0x1, 0xf0, 0xf, 0x80, 0x0, 0xf0, 0xf, 0x80, 0x0, 0xe0, 0x7, 0x0, 0x0, 0xe0, 0x7, 0x0, 0x0, 0xe0, 0x7, 0x0, 0x0, 0x40, 0x2, 0x0} + +/* X (88) */ +#define NXFONT_METRICS_88 {3, 21, 23, 1, 14, 0} +#define NXFONT_BITMAP_88 {0xff, 0xcf, 0xe0, 0x7f, 0x3, 0x0, 0x3f, 0x2, 0x0, 0x1f, 0x86, 0x0, 0x1f, 0x84, 0x0, 0xf, 0xcc, 0x0, 0xf, 0xc8, 0x0, 0x7, 0xf8, 0x0, 0x3, 0xf0, 0x0, 0x3, 0xf0, 0x0, 0x1, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x1, 0xfc, 0x0, 0x1, 0x7c, 0x0, 0x3, 0x3e, 0x0, 0x2, 0x3f, 0x0, 0x6, 0x1f, 0x0, 0x4, 0x1f, 0x80, 0xc, 0xf, 0xc0, 0x8, 0xf, 0xc0, 0x18, 0x7, 0xe0, 0x38, 0x7, 0xf0, 0xfe, 0x3f, 0xf8} + +/* Y (89) */ +#define NXFONT_METRICS_89 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_89 {0xff, 0xc3, 0xfc, 0x7f, 0x0, 0xf0, 0x3f, 0x0, 0x60, 0x3f, 0x0, 0x60, 0x1f, 0x80, 0xc0, 0x1f, 0x80, 0x80, 0xf, 0xc1, 0x80, 0xf, 0xc3, 0x0, 0x7, 0xe3, 0x0, 0x3, 0xe6, 0x0, 0x3, 0xf4, 0x0, 0x1, 0xfc, 0x0, 0x1, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x1, 0xfc, 0x0, 0x7, 0xff, 0x0} + +/* Z (90) */ +#define NXFONT_METRICS_90 {3, 19, 23, 1, 14, 0} +#define NXFONT_BITMAP_90 {0x3f, 0xff, 0xc0, 0x7e, 0xf, 0x80, 0x78, 0x1f, 0x80, 0x70, 0x1f, 0x0, 0x60, 0x3f, 0x0, 0x40, 0x7e, 0x0, 0x0, 0x7e, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xf8, 0x0, 0x1, 0xf0, 0x0, 0x3, 0xf0, 0x0, 0x3, 0xe0, 0x0, 0x7, 0xe0, 0x0, 0x7, 0xc0, 0x0, 0xf, 0xc0, 0x20, 0x1f, 0x80, 0x20, 0x1f, 0x80, 0x60, 0x3f, 0x0, 0x60, 0x3f, 0x0, 0xe0, 0x7e, 0x1, 0xe0, 0x7e, 0x7, 0xc0, 0xff, 0xff, 0xc0} + +/* bracketleft (91) */ +#define NXFONT_METRICS_91 {1, 7, 28, 2, 14, 0} +#define NXFONT_BITMAP_91 {0xfe, 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xfe} + +/* backslash (92) */ +#define NXFONT_METRICS_92 {1, 8, 26, 0, 11, 0} +#define NXFONT_BITMAP_92 {0x80, 0xc0, 0xc0, 0xc0, 0x60, 0x60, 0x60, 0x60, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x18, 0xc, 0xc, 0xc, 0x4, 0x6, 0x6, 0x6, 0x3, 0x3, 0x3, 0x3} + +/* bracketright (93) */ +#define NXFONT_METRICS_93 {1, 7, 28, 1, 14, 0} +#define NXFONT_BITMAP_93 {0xfe, 0x1e, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0x1e, 0xfe} + +/* asciicircum (94) */ +#define NXFONT_METRICS_94 {2, 11, 13, 4, 14, 0} +#define NXFONT_BITMAP_94 {0xe, 0x0, 0xe, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1b, 0x0, 0x3b, 0x80, 0x3b, 0x80, 0x71, 0xc0, 0x71, 0xc0, 0x61, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0x60} + +/* underscore (95) */ +#define NXFONT_METRICS_95 {2, 16, 3, 0, 39, 0} +#define NXFONT_BITMAP_95 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + +/* grave (96) */ +#define NXFONT_METRICS_96 {1, 7, 6, 1, 14, 0} +#define NXFONT_BITMAP_96 {0xc0, 0xe0, 0x70, 0x38, 0xc, 0x2} + +/* a (97) */ +#define NXFONT_METRICS_97 {2, 14, 16, 1, 21, 0} +#define NXFONT_BITMAP_97 {0x1f, 0x80, 0x31, 0xe0, 0x70, 0xf0, 0x78, 0xf0, 0x78, 0xf0, 0x30, 0xf0, 0x1, 0xf0, 0x7, 0xf0, 0x1c, 0xf0, 0x38, 0xf0, 0x78, 0xf0, 0xf0, 0xf0, 0xf9, 0xf0, 0xff, 0xf4, 0x7e, 0xfc, 0x3c, 0x78} + +/* b (98) */ +#define NXFONT_METRICS_98 {3, 17, 22, 0, 15, 0} +#define NXFONT_BITMAP_98 {0xfc, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x78, 0x0, 0x3d, 0xfe, 0x0, 0x3f, 0xfe, 0x0, 0x3e, 0x1f, 0x0, 0x3c, 0x1f, 0x0, 0x3c, 0xf, 0x80, 0x3c, 0xf, 0x80, 0x3c, 0xf, 0x80, 0x3c, 0xf, 0x80, 0x3c, 0xf, 0x80, 0x3c, 0xf, 0x80, 0x3c, 0xf, 0x0, 0x3c, 0x1f, 0x0, 0x3e, 0x3e, 0x0, 0x37, 0xfc, 0x0, 0x21, 0xf0, 0x0} + +/* c (99) */ +#define NXFONT_METRICS_99 {2, 14, 16, 1, 21, 0} +#define NXFONT_BITMAP_99 {0x7, 0xf0, 0x1e, 0x78, 0x3c, 0x3c, 0x7c, 0x3c, 0x78, 0x18, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0x7c, 0x0, 0x3e, 0x18, 0x1f, 0xf0, 0xf, 0xe0} + +/* d (100) */ +#define NXFONT_METRICS_100 {2, 16, 22, 1, 15, 0} +#define NXFONT_BITMAP_100 {0x0, 0xfc, 0x0, 0x7c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0xf, 0xbc, 0x3f, 0xfc, 0x7c, 0x3c, 0x78, 0x3c, 0xf8, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0x78, 0x3c, 0x7c, 0x7e, 0x3f, 0xff, 0xf, 0xb8} + +/* e (101) */ +#define NXFONT_METRICS_101 {2, 14, 16, 0, 21, 0} +#define NXFONT_BITMAP_101 {0x7, 0xc0, 0x1e, 0xf0, 0x3c, 0x70, 0x78, 0x38, 0x78, 0x3c, 0xf8, 0x3c, 0xf8, 0x3c, 0xff, 0xfc, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0x78, 0x0, 0x7c, 0x0, 0x3e, 0x18, 0x1f, 0xf0, 0x7, 0xe0} + +/* f (102) */ +#define NXFONT_METRICS_102 {2, 12, 23, 0, 14, 0} +#define NXFONT_BITMAP_102 {0x7, 0xe0, 0x1e, 0x70, 0x1c, 0xf0, 0x3c, 0xf0, 0x3c, 0x60, 0x3c, 0x0, 0x3c, 0x0, 0xff, 0x80, 0xff, 0x80, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x7e, 0x0, 0xff, 0x0} + +/* g (103) */ +#define NXFONT_METRICS_103 {2, 14, 23, 1, 21, 0} +#define NXFONT_BITMAP_103 {0xf, 0xc0, 0x3d, 0xfc, 0x70, 0xfc, 0xf0, 0xf0, 0xf0, 0x78, 0xf0, 0x78, 0xf0, 0x78, 0xf0, 0x78, 0x78, 0xf8, 0x3f, 0xf0, 0x1f, 0xc0, 0x3c, 0x0, 0x60, 0x0, 0xe0, 0x0, 0xff, 0xe0, 0xff, 0xf8, 0x7f, 0xfc, 0x30, 0x3c, 0x60, 0x1c, 0xc0, 0xc, 0xe0, 0x1c, 0x7f, 0xf8, 0x1f, 0xe0} + +/* h (104) */ +#define NXFONT_METRICS_104 {3, 17, 22, 0, 15, 0} +#define NXFONT_BITMAP_104 {0xfc, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x78, 0x0, 0x3d, 0xfc, 0x0, 0x3f, 0xfe, 0x0, 0x3e, 0x3e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x7e, 0x3f, 0x0, 0xff, 0x7f, 0x80} + +/* i (105) */ +#define NXFONT_METRICS_105 {1, 8, 23, 0, 14, 0} +#define NXFONT_BITMAP_105 {0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x0, 0x0, 0xfc, 0x7c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x7e, 0xff} + +/* j (106) -- NOTE: Xoffset should be -2, not 0. */ +#define NXFONT_METRICS_106 {2, 10, 30, 0, 14, 0} +#define NXFONT_BITMAP_106 {0x1, 0x80, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0xf, 0xc0, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x63, 0xc0, 0xf3, 0xc0, 0xf3, 0x80, 0x77, 0x80, 0x3e, 0x0} + +/* k (107) */ +#define NXFONT_METRICS_107 {3, 18, 22, 0, 15, 0} +#define NXFONT_BITMAP_107 {0xfc, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x1f, 0x0, 0x3c, 0xe, 0x0, 0x3c, 0xc, 0x0, 0x3c, 0x18, 0x0, 0x3c, 0x30, 0x0, 0x3c, 0x60, 0x0, 0x3c, 0xc0, 0x0, 0x3d, 0xc0, 0x0, 0x3f, 0xe0, 0x0, 0x3d, 0xf0, 0x0, 0x3c, 0xf8, 0x0, 0x3c, 0x7c, 0x0, 0x3c, 0x3e, 0x0, 0x3c, 0x1f, 0x0, 0x7e, 0xf, 0x80, 0xff, 0x1f, 0xc0} + +/* l (108) */ +#define NXFONT_METRICS_108 {1, 8, 22, 0, 15, 0} +#define NXFONT_BITMAP_108 {0xfc, 0x7c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x7e, 0xff} + +/* m (109) */ +#define NXFONT_METRICS_109 {4, 26, 16, 0, 21, 0} +#define NXFONT_BITMAP_109 {0xfc, 0x78, 0x3c, 0x0, 0x7d, 0xfe, 0xfe, 0x0, 0x3f, 0x3f, 0x9f, 0x0, 0x3e, 0x3f, 0x1f, 0x0, 0x3e, 0x1e, 0xf, 0x0, 0x3c, 0x1e, 0xf, 0x0, 0x3c, 0x1e, 0xf, 0x0, 0x3c, 0x1e, 0xf, 0x0, 0x3c, 0x1e, 0xf, 0x0, 0x3c, 0x1e, 0xf, 0x0, 0x3c, 0x1e, 0xf, 0x0, 0x3c, 0x1e, 0xf, 0x0, 0x3c, 0x1e, 0xf, 0x0, 0x3c, 0x1e, 0xf, 0x0, 0x7e, 0x3f, 0x1f, 0x80, 0xff, 0x7f, 0xbf, 0xc0} + +/* n (110) */ +#define NXFONT_METRICS_110 {3, 17, 16, 0, 21, 0} +#define NXFONT_BITMAP_110 {0xfc, 0x78, 0x0, 0x7d, 0xfc, 0x0, 0x3f, 0x3e, 0x0, 0x3e, 0x1e, 0x0, 0x3e, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x7e, 0x3f, 0x0, 0xff, 0x7f, 0x80} + +/* o (111) */ +#define NXFONT_METRICS_111 {2, 14, 16, 1, 21, 0} +#define NXFONT_BITMAP_111 {0xf, 0xc0, 0x3c, 0xf0, 0x78, 0x78, 0x78, 0x78, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0x78, 0x78, 0x78, 0x78, 0x3c, 0xf0, 0xf, 0xc0} + +/* p (112) */ +#define NXFONT_METRICS_112 {3, 17, 23, 0, 21, 0} +#define NXFONT_BITMAP_112 {0xfc, 0xf8, 0x0, 0x7d, 0xfe, 0x0, 0x3f, 0x1f, 0x0, 0x3e, 0xf, 0x0, 0x3c, 0xf, 0x80, 0x3c, 0x7, 0x80, 0x3c, 0x7, 0x80, 0x3c, 0x7, 0x80, 0x3c, 0x7, 0x80, 0x3c, 0x7, 0x80, 0x3c, 0x7, 0x80, 0x3c, 0x7, 0x80, 0x3e, 0xf, 0x0, 0x3f, 0xf, 0x0, 0x3f, 0xfe, 0x0, 0x3c, 0xf8, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x7e, 0x0, 0x0, 0xff, 0x0, 0x0} + +/* q (113) */ +#define NXFONT_METRICS_113 {2, 16, 23, 1, 21, 0} +#define NXFONT_BITMAP_113 {0xf, 0xc4, 0x3e, 0xec, 0x7c, 0x3c, 0x78, 0x3c, 0xf8, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0x78, 0x3c, 0x78, 0x7c, 0x3f, 0xfc, 0xf, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x7e, 0x0, 0xff} + +/* r (114) */ +#define NXFONT_METRICS_114 {2, 13, 16, 1, 21, 0} +#define NXFONT_BITMAP_114 {0xfc, 0x70, 0x7c, 0xf8, 0x3f, 0xf8, 0x3f, 0x78, 0x3e, 0x30, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x7e, 0x0, 0xff, 0x0} + +/* s (115) */ +#define NXFONT_METRICS_115 {2, 10, 16, 1, 21, 0} +#define NXFONT_BITMAP_115 {0x1f, 0x40, 0x71, 0xc0, 0x60, 0xc0, 0xe0, 0xc0, 0xf0, 0x40, 0xfc, 0x0, 0x7f, 0x0, 0x7f, 0x80, 0x3f, 0x80, 0xf, 0xc0, 0x3, 0xc0, 0x81, 0xc0, 0xc1, 0xc0, 0xc1, 0xc0, 0xe3, 0x80, 0xbf, 0x0} + +/* t (116) */ +#define NXFONT_METRICS_116 {2, 10, 21, 0, 16, 0} +#define NXFONT_BITMAP_116 {0x4, 0x0, 0xc, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x3c, 0x0, 0x7f, 0x80, 0xff, 0x80, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x40, 0x3e, 0xc0, 0x3f, 0x80, 0x1e, 0x0} + +/* u (117) */ +#define NXFONT_METRICS_117 {3, 17, 16, 0, 21, 0} +#define NXFONT_BITMAP_117 {0xfc, 0x7e, 0x0, 0x7c, 0x3e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x3e, 0x0, 0x3e, 0x5f, 0x0, 0x1f, 0xdf, 0x80, 0x7, 0x8c, 0x0} + +/* v (118) */ +#define NXFONT_METRICS_118 {2, 15, 16, 0, 21, 0} +#define NXFONT_BITMAP_118 {0xff, 0x3e, 0x7c, 0xc, 0x3c, 0x8, 0x3e, 0x18, 0x1e, 0x10, 0x1f, 0x10, 0x1f, 0x30, 0xf, 0x20, 0xf, 0x20, 0x7, 0xe0, 0x7, 0xc0, 0x7, 0xc0, 0x3, 0x80, 0x3, 0x80, 0x1, 0x0, 0x1, 0x0} + +/* w (119) */ +#define NXFONT_METRICS_119 {3, 23, 16, 0, 21, 0} +#define NXFONT_BITMAP_119 {0xff, 0x7f, 0xbe, 0x7e, 0x3e, 0x1c, 0x3c, 0x1e, 0x8, 0x3e, 0x1e, 0x18, 0x1e, 0x1f, 0x10, 0x1f, 0x1f, 0x30, 0x1f, 0x3f, 0x30, 0xf, 0x2f, 0xa0, 0xf, 0xe7, 0xe0, 0x7, 0xe7, 0xc0, 0x7, 0xc7, 0xc0, 0x7, 0xc3, 0xc0, 0x3, 0x83, 0x80, 0x3, 0x83, 0x80, 0x1, 0x1, 0x0, 0x1, 0x1, 0x0} + +/* x (120) */ +#define NXFONT_METRICS_120 {2, 16, 16, 0, 21, 0} +#define NXFONT_BITMAP_120 {0xff, 0x3e, 0x7e, 0x18, 0x3e, 0x18, 0x1f, 0x30, 0x1f, 0x60, 0xf, 0xc0, 0xf, 0xc0, 0x7, 0xc0, 0x3, 0xe0, 0x3, 0xe0, 0x7, 0xf0, 0xd, 0xf8, 0x18, 0xf8, 0x18, 0x7c, 0x30, 0x7c, 0xfc, 0xff} + +/* y (121) */ +#define NXFONT_METRICS_121 {2, 15, 23, 0, 21, 0} +#define NXFONT_BITMAP_121 {0xff, 0xbe, 0x7e, 0xc, 0x3e, 0x8, 0x3e, 0x8, 0x1f, 0x18, 0x1f, 0x10, 0xf, 0x10, 0xf, 0xb0, 0xf, 0xa0, 0x7, 0xa0, 0x7, 0xe0, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x73, 0x0, 0xf3, 0x0, 0xf6, 0x0, 0xfe, 0x0, 0x78, 0x0} + +/* z (122) */ +#define NXFONT_METRICS_122 {2, 12, 16, 1, 21, 0} +#define NXFONT_BITMAP_122 {0xff, 0xf0, 0xe3, 0xf0, 0xc3, 0xe0, 0x87, 0xe0, 0x87, 0xc0, 0xf, 0x80, 0xf, 0x80, 0x1f, 0x0, 0x1f, 0x0, 0x3e, 0x0, 0x3e, 0x10, 0x7c, 0x10, 0x7c, 0x30, 0xf8, 0x30, 0xf8, 0xf0, 0xff, 0xf0} + +/* braceleft (123) */ +#define NXFONT_METRICS_123 {2, 10, 27, 1, 14, 0} +#define NXFONT_BITMAP_123 {0x7, 0xc0, 0xe, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x70, 0x0, 0xe0, 0x0, 0x70, 0x0, 0x38, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0xe, 0x0, 0x7, 0xc0} + +/* bar (124) */ +#define NXFONT_METRICS_124 {1, 2, 30, 3, 14, 0} +#define NXFONT_BITMAP_124 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* braceright (125) */ +#define NXFONT_METRICS_125 {2, 10, 27, 1, 14, 0} +#define NXFONT_BITMAP_125 {0xf8, 0x0, 0x1c, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0x7, 0x0, 0x3, 0x80, 0x1, 0xc0, 0x3, 0x80, 0x7, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1c, 0x0, 0xf8, 0x0} + +/* asciitilde (126) */ +#define NXFONT_METRICS_126 {2, 15, 8, 1, 21, 0} +#define NXFONT_BITMAP_126 {0x1c, 0x0, 0x3f, 0x0, 0x7f, 0x82, 0xff, 0xc6, 0x8f, 0xfe, 0x83, 0xfc, 0x1, 0xf8, 0x0, 0x70} + +/* exclamdown (161) */ +#define NXFONT_METRICS_161 {1, 5, 23, 3, 21, 0} +#define NXFONT_BITMAP_161 {0x70, 0xf8, 0xf8, 0xf8, 0x70, 0x0, 0x0, 0x0, 0x20, 0x20, 0x20, 0x20, 0x70, 0x70, 0x70, 0x70, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x70} + +/* cent (162) */ +#define NXFONT_METRICS_162 {2, 13, 25, 1, 17, 0} +#define NXFONT_BITMAP_162 {0x0, 0x8, 0x0, 0x8, 0x0, 0x18, 0x0, 0x10, 0x7, 0xf0, 0x1c, 0xe0, 0x38, 0xf0, 0x78, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0xf0, 0x80, 0xf1, 0x80, 0xf1, 0x0, 0xf3, 0x0, 0xf2, 0x0, 0xfa, 0x10, 0x7e, 0x30, 0x7f, 0xe0, 0x3f, 0xc0, 0xf, 0x0, 0x8, 0x0, 0x10, 0x0, 0x10, 0x0, 0x20, 0x0, 0x20, 0x0} + +/* sterling (163) */ +#define NXFONT_METRICS_163 {2, 16, 23, 1, 14, 0} +#define NXFONT_BITMAP_163 {0x0, 0xf0, 0x3, 0xfc, 0x7, 0x1e, 0xe, 0x1e, 0xe, 0x1e, 0x1e, 0xc, 0x1e, 0x0, 0x1e, 0x0, 0x1f, 0x0, 0xf, 0x0, 0xf, 0x0, 0x7f, 0xf0, 0x7f, 0xf0, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x37, 0x80, 0x7f, 0x1, 0xef, 0x3, 0xc7, 0x87, 0xc7, 0xff, 0xee, 0xfe, 0x7c, 0x7c} + +/* currency (164) */ +#define NXFONT_METRICS_164 {2, 14, 15, 1, 18, 0} +#define NXFONT_BITMAP_164 {0x60, 0x18, 0xf7, 0xbc, 0xff, 0xfc, 0x7f, 0xf8, 0x3c, 0xf0, 0x78, 0x78, 0x70, 0x38, 0x70, 0x38, 0x70, 0x38, 0x78, 0x78, 0x3c, 0xf0, 0x7f, 0xf8, 0xff, 0xfc, 0xf7, 0xbc, 0x60, 0x18} + +/* yen (165) */ +#define NXFONT_METRICS_165 {3, 18, 23, 1, 14, 0} +#define NXFONT_BITMAP_165 {0xff, 0x87, 0xc0, 0x3e, 0x3, 0x80, 0x3e, 0x3, 0x0, 0x1f, 0x3, 0x0, 0x1f, 0x6, 0x0, 0x1f, 0x86, 0x0, 0xf, 0x84, 0x0, 0xf, 0x8c, 0x0, 0x7, 0xc8, 0x0, 0x7, 0xd8, 0x0, 0x7, 0xd0, 0x0, 0x3, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x1f, 0xfc, 0x0, 0x3, 0xe0, 0x0, 0x1f, 0xfc, 0x0, 0x1f, 0xfc, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x3, 0xf0, 0x0, 0xf, 0xfc, 0x0} + +/* brokenbar (166) */ +#define NXFONT_METRICS_166 {1, 2, 30, 3, 14, 0} +#define NXFONT_BITMAP_166 {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0} + +/* section (167) */ +#define NXFONT_METRICS_167 {2, 12, 28, 2, 14, 0} +#define NXFONT_BITMAP_167 {0xf, 0x80, 0x18, 0xc0, 0x30, 0xe0, 0x71, 0xe0, 0x71, 0xe0, 0x78, 0xc0, 0x3c, 0x0, 0x3e, 0x0, 0x1f, 0x0, 0xf, 0x80, 0x3f, 0xc0, 0x63, 0xe0, 0xc1, 0xe0, 0xc0, 0xf0, 0xe0, 0x70, 0xf0, 0x30, 0x78, 0x30, 0x7c, 0x60, 0x3f, 0xc0, 0x1f, 0x80, 0x7, 0x80, 0x3, 0xc0, 0x31, 0xe0, 0x78, 0xe0, 0x78, 0xe0, 0x70, 0xc0, 0x31, 0x80, 0x1f, 0x0} + +/* dieresis (168) */ +#define NXFONT_METRICS_168 {1, 8, 4, 2, 15, 0} +#define NXFONT_BITMAP_168 {0x42, 0xe7, 0xe7, 0x42} + +/* copyright (169) */ +#define NXFONT_METRICS_169 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_169 {0x1, 0xfe, 0x0, 0x7, 0xff, 0x80, 0xf, 0x3, 0xc0, 0x1c, 0x0, 0xe0, 0x38, 0x0, 0x70, 0x30, 0xfe, 0x30, 0x71, 0xc7, 0x38, 0x63, 0x83, 0x18, 0xe7, 0x83, 0x1c, 0xc7, 0x0, 0xc, 0xc7, 0x0, 0xc, 0xc7, 0x0, 0xc, 0xc7, 0x0, 0xc, 0xc7, 0x80, 0xc, 0xc3, 0xc3, 0xc, 0xe3, 0xe6, 0x1c, 0x60, 0xfc, 0x18, 0x70, 0x0, 0x38, 0x38, 0x0, 0x70, 0x1c, 0x0, 0xe0, 0xf, 0x3, 0xc0, 0x7, 0xff, 0x80, 0x1, 0xfe, 0x0} + +/* ordfeminine (170) */ +#define NXFONT_METRICS_170 {2, 9, 14, 0, 14, 0} +#define NXFONT_BITMAP_170 {0x3c, 0x0, 0x66, 0x0, 0x67, 0x0, 0x67, 0x0, 0x1f, 0x0, 0x67, 0x0, 0xc7, 0x0, 0xc7, 0x0, 0xef, 0x80, 0x73, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0xff, 0x80} + +/* guillemotleft (171) */ +#define NXFONT_METRICS_171 {2, 14, 14, 2, 22, 0} +#define NXFONT_BITMAP_171 {0x2, 0x4, 0x6, 0xc, 0xe, 0x1c, 0x1c, 0x38, 0x38, 0x70, 0x70, 0xe0, 0xe1, 0xc0, 0xe1, 0xc0, 0x70, 0xe0, 0x38, 0x70, 0x1c, 0x38, 0xe, 0x1c, 0x6, 0xc, 0x2, 0x4} + +/* logicalnot (172) */ +#define NXFONT_METRICS_172 {2, 16, 9, 1, 25, 0} +#define NXFONT_BITMAP_172 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7} + +/* hyphen (173) */ +#define NXFONT_METRICS_173 {1, 8, 4, 1, 27, 0} +#define NXFONT_BITMAP_173 {0xff, 0xff, 0xff, 0xff} + +/* registered (174) */ +#define NXFONT_METRICS_174 {3, 22, 23, 2, 14, 0} +#define NXFONT_BITMAP_174 {0x1, 0xfe, 0x0, 0x7, 0xff, 0x80, 0xf, 0x3, 0xc0, 0x1c, 0x0, 0xe0, 0x38, 0x0, 0x70, 0x33, 0xfc, 0x30, 0x71, 0xce, 0x38, 0x60, 0xc7, 0x18, 0xe0, 0xc7, 0x1c, 0xc0, 0xc7, 0xc, 0xc0, 0xce, 0xc, 0xc0, 0xf8, 0xc, 0xc0, 0xdc, 0xc, 0xc0, 0xce, 0xc, 0xc0, 0xc6, 0xc, 0xe0, 0xc7, 0x1c, 0x61, 0xc3, 0x98, 0x73, 0xe3, 0xf8, 0x38, 0x0, 0x70, 0x1c, 0x0, 0xe0, 0xf, 0x3, 0xc0, 0x7, 0xff, 0x80, 0x1, 0xfe, 0x0} + +/* macron (175) */ +#define NXFONT_METRICS_175 {2, 9, 2, 1, 17, 0} +#define NXFONT_BITMAP_175 {0xff, 0x80, 0xff, 0x80} + +/* degree (176) */ +#define NXFONT_METRICS_176 {2, 9, 10, 2, 14, 0} +#define NXFONT_BITMAP_176 {0x1c, 0x0, 0x7f, 0x0, 0x63, 0x0, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0x63, 0x0, 0x7f, 0x0, 0x3c, 0x0} + +/* plusminus (177) */ +#define NXFONT_METRICS_177 {2, 15, 19, 2, 18, 0} +#define NXFONT_BITMAP_177 {0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x0, 0x0, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe} + +/* twosuperior (178) */ +#define NXFONT_METRICS_178 {2, 10, 14, 1, 14, 0} +#define NXFONT_BITMAP_178 {0x3e, 0x0, 0x7f, 0x0, 0xc7, 0x80, 0x83, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x0, 0x6, 0x0, 0xc, 0x0, 0x18, 0x0, 0x30, 0x40, 0x7f, 0xc0, 0xff, 0x80, 0xff, 0x80} + +/* threesuperior (179) */ +#define NXFONT_METRICS_179 {2, 9, 14, 1, 14, 0} +#define NXFONT_BITMAP_179 {0x1e, 0x0, 0x3f, 0x0, 0x67, 0x80, 0x43, 0x80, 0x3, 0x0, 0x6, 0x0, 0x1f, 0x0, 0x7, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0xc3, 0x80, 0xe7, 0x0, 0x7e, 0x0} + +/* acute (180) */ +#define NXFONT_METRICS_180 {1, 7, 6, 3, 14, 0} +#define NXFONT_BITMAP_180 {0x6, 0xe, 0x1c, 0x38, 0x60, 0x80} + +/* mu (181) */ +#define NXFONT_METRICS_181 {2, 16, 22, 2, 21, 0} +#define NXFONT_BITMAP_181 {0xf8, 0xfc, 0x78, 0x7c, 0x78, 0x3c, 0x78, 0x3c, 0x78, 0x3c, 0x78, 0x3c, 0x78, 0x3c, 0x78, 0x3c, 0x78, 0x3c, 0x78, 0x3c, 0x78, 0x3c, 0x78, 0x3c, 0x78, 0x7c, 0x7c, 0xfc, 0x7f, 0xbf, 0x5f, 0x38, 0x40, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0} + +/* paragraph (182) */ +#define NXFONT_METRICS_182 {2, 16, 29, 1, 14, 0} +#define NXFONT_BITMAP_182 {0xf, 0xff, 0x3f, 0xff, 0x3f, 0x8c, 0x7f, 0x8c, 0xff, 0x8c, 0xff, 0x8c, 0xff, 0x8c, 0xff, 0x8c, 0xff, 0x8c, 0xff, 0x8c, 0xff, 0x8c, 0x7f, 0x8c, 0x3f, 0x8c, 0x3f, 0x8c, 0xf, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c, 0x1, 0x8c} + +/* periodcentered (183) */ +#define NXFONT_METRICS_183 {1, 4, 4, 2, 24, 0} +#define NXFONT_BITMAP_183 {0x60, 0xf0, 0xf0, 0x60} + +/* cedilla (184) */ +#define NXFONT_METRICS_184 {1, 7, 7, 1, 37, 0} +#define NXFONT_BITMAP_184 {0x6, 0xc, 0x1c, 0xe, 0xc6, 0xee, 0x7c} + +/* onesuperior (185) */ +#define NXFONT_METRICS_185 {2, 9, 14, 0, 14, 0} +#define NXFONT_BITMAP_185 {0xc, 0x0, 0x7c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x1c, 0x0, 0xff, 0x80} + +/* ordmasculine (186) */ +#define NXFONT_METRICS_186 {2, 9, 14, 1, 14, 0} +#define NXFONT_BITMAP_186 {0x1c, 0x0, 0x77, 0x0, 0x63, 0x0, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0x63, 0x0, 0x77, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0xff, 0x80} + +/* guillemotright (187) */ +#define NXFONT_METRICS_187 {2, 14, 14, 1, 22, 0} +#define NXFONT_BITMAP_187 {0x81, 0x0, 0xc1, 0x80, 0xe1, 0xc0, 0x70, 0xe0, 0x38, 0x70, 0x1c, 0x38, 0xe, 0x1c, 0xe, 0x1c, 0x1c, 0x38, 0x38, 0x70, 0x70, 0xe0, 0xe1, 0xc0, 0xc1, 0x80, 0x81, 0x0} + +/* onequarter (188) */ +#define NXFONT_METRICS_188 {3, 23, 23, 0, 14, 0} +#define NXFONT_BITMAP_188 {0xc, 0x0, 0x8, 0x7c, 0x0, 0x18, 0x1c, 0x0, 0x30, 0x1c, 0x0, 0x30, 0x1c, 0x0, 0x60, 0x1c, 0x0, 0x60, 0x1c, 0x0, 0xc0, 0x1c, 0x1, 0x80, 0x1c, 0x1, 0x80, 0x1c, 0x3, 0xc, 0x1c, 0x6, 0x1c, 0x1c, 0x6, 0x3c, 0x1c, 0xc, 0x7c, 0xff, 0x98, 0xfc, 0x0, 0x18, 0xdc, 0x0, 0x31, 0x9c, 0x0, 0x63, 0x9c, 0x0, 0x63, 0x1c, 0x0, 0xc7, 0xfe, 0x1, 0xc7, 0xfe, 0x1, 0x80, 0x1c, 0x3, 0x0, 0x1c, 0x3, 0x0, 0x1c} + +/* onehalf (189) */ +#define NXFONT_METRICS_189 {3, 23, 23, 0, 14, 0} +#define NXFONT_BITMAP_189 {0xc, 0x0, 0x30, 0x7c, 0x0, 0x60, 0x1c, 0x0, 0x60, 0x1c, 0x0, 0xc0, 0x1c, 0x0, 0x80, 0x1c, 0x1, 0x80, 0x1c, 0x3, 0x0, 0x1c, 0x2, 0x0, 0x1c, 0x6, 0x0, 0x1c, 0xc, 0xf0, 0x1c, 0x19, 0xf8, 0x1c, 0x1b, 0x3c, 0x1c, 0x32, 0x1c, 0xff, 0xb0, 0x1c, 0x0, 0x60, 0x1c, 0x0, 0x60, 0x18, 0x0, 0xc0, 0x30, 0x1, 0x80, 0x60, 0x1, 0x80, 0xc0, 0x3, 0x1, 0x82, 0x6, 0x3, 0xfe, 0x6, 0x7, 0xfc, 0xc, 0xf, 0xfc} + +/* threequarters (190) */ +#define NXFONT_METRICS_190 {3, 22, 23, 1, 14, 0} +#define NXFONT_BITMAP_190 {0x1e, 0x0, 0x10, 0x3f, 0x0, 0x30, 0x67, 0x80, 0x60, 0x43, 0x80, 0x60, 0x3, 0x0, 0xc0, 0x6, 0x0, 0xc0, 0x1f, 0x1, 0x80, 0x7, 0x83, 0x0, 0x3, 0x83, 0x0, 0x3, 0x86, 0x18, 0x3, 0x8c, 0x38, 0xc3, 0x8c, 0x78, 0xe7, 0x18, 0xf8, 0x7e, 0x31, 0xf8, 0x0, 0x31, 0xb8, 0x0, 0x63, 0x38, 0x0, 0xc7, 0x38, 0x0, 0xc6, 0x38, 0x1, 0x8f, 0xfc, 0x3, 0x8f, 0xfc, 0x3, 0x0, 0x38, 0x6, 0x0, 0x38, 0x6, 0x0, 0x38} + +/* questiondown (191) */ +#define NXFONT_METRICS_191 {2, 12, 23, 2, 21, 0} +#define NXFONT_BITMAP_191 {0x7, 0x0, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x2, 0x0, 0x6, 0x0, 0xc, 0x0, 0x1c, 0x0, 0x3c, 0x0, 0x78, 0x0, 0x78, 0x0, 0xf8, 0x60, 0xf8, 0xf0, 0xf8, 0xf0, 0xf8, 0x70, 0x78, 0x70, 0x3c, 0xe0, 0x1f, 0xc0} + +/* Agrave (192) */ +#define NXFONT_METRICS_192 {3, 21, 30, 1, 7, 0} +#define NXFONT_BITMAP_192 {0x6, 0x0, 0x0, 0x7, 0x0, 0x0, 0x3, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x20, 0x0, 0x0, 0x60, 0x0, 0x0, 0x70, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x1, 0x7c, 0x0, 0x1, 0x7c, 0x0, 0x3, 0x3e, 0x0, 0x2, 0x3e, 0x0, 0x6, 0x3e, 0x0, 0x6, 0x1f, 0x0, 0x4, 0x1f, 0x0, 0xc, 0xf, 0x0, 0xf, 0xff, 0x80, 0x18, 0xf, 0x80, 0x18, 0x7, 0xc0, 0x10, 0x7, 0xc0, 0x30, 0x3, 0xe0, 0x30, 0x3, 0xe0, 0x70, 0x7, 0xf0, 0xfc, 0x1f, 0xf8} + +/* Aacute (193) */ +#define NXFONT_METRICS_193 {3, 21, 30, 1, 7, 0} +#define NXFONT_BITMAP_193 {0x0, 0x3, 0x0, 0x0, 0x7, 0x0, 0x0, 0xe, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x30, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x60, 0x0, 0x0, 0x70, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x1, 0x7c, 0x0, 0x1, 0x7c, 0x0, 0x3, 0x3e, 0x0, 0x2, 0x3e, 0x0, 0x6, 0x3e, 0x0, 0x6, 0x1f, 0x0, 0x4, 0x1f, 0x0, 0xc, 0xf, 0x0, 0xf, 0xff, 0x80, 0x18, 0xf, 0x80, 0x18, 0x7, 0xc0, 0x10, 0x7, 0xc0, 0x30, 0x3, 0xe0, 0x30, 0x3, 0xe0, 0x70, 0x7, 0xf0, 0xfc, 0x1f, 0xf8} + +/* Acircumflex (194) */ +#define NXFONT_METRICS_194 {3, 21, 30, 1, 7, 0} +#define NXFONT_BITMAP_194 {0x0, 0x60, 0x0, 0x0, 0xf0, 0x0, 0x1, 0xf8, 0x0, 0x1, 0x98, 0x0, 0x3, 0xc, 0x0, 0x2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x60, 0x0, 0x0, 0x70, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x1, 0x7c, 0x0, 0x1, 0x7c, 0x0, 0x3, 0x3e, 0x0, 0x2, 0x3e, 0x0, 0x6, 0x3e, 0x0, 0x6, 0x1f, 0x0, 0x4, 0x1f, 0x0, 0xc, 0xf, 0x0, 0xf, 0xff, 0x80, 0x18, 0xf, 0x80, 0x18, 0x7, 0xc0, 0x10, 0x7, 0xc0, 0x30, 0x3, 0xe0, 0x30, 0x3, 0xe0, 0x70, 0x7, 0xf0, 0xfc, 0x1f, 0xf8} + +/* Atilde (195) */ +#define NXFONT_METRICS_195 {3, 21, 29, 1, 8, 0} +#define NXFONT_BITMAP_195 {0x0, 0xc2, 0x0, 0x1, 0xf6, 0x0, 0x3, 0x7c, 0x0, 0x2, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x60, 0x0, 0x0, 0x70, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x1, 0x7c, 0x0, 0x1, 0x7c, 0x0, 0x3, 0x3e, 0x0, 0x2, 0x3e, 0x0, 0x6, 0x3e, 0x0, 0x6, 0x1f, 0x0, 0x4, 0x1f, 0x0, 0xc, 0xf, 0x0, 0xf, 0xff, 0x80, 0x18, 0xf, 0x80, 0x18, 0x7, 0xc0, 0x10, 0x7, 0xc0, 0x30, 0x3, 0xe0, 0x30, 0x3, 0xe0, 0x70, 0x7, 0xf0, 0xfc, 0x1f, 0xf8} + +/* Adieresis (196) */ +#define NXFONT_METRICS_196 {3, 21, 29, 1, 8, 0} +#define NXFONT_BITMAP_196 {0x1, 0x8, 0x0, 0x3, 0x9c, 0x0, 0x3, 0x9c, 0x0, 0x1, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x60, 0x0, 0x0, 0x70, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x1, 0x7c, 0x0, 0x1, 0x7c, 0x0, 0x3, 0x3e, 0x0, 0x2, 0x3e, 0x0, 0x6, 0x3e, 0x0, 0x6, 0x1f, 0x0, 0x4, 0x1f, 0x0, 0xc, 0xf, 0x0, 0xf, 0xff, 0x80, 0x18, 0xf, 0x80, 0x18, 0x7, 0xc0, 0x10, 0x7, 0xc0, 0x30, 0x3, 0xe0, 0x30, 0x3, 0xe0, 0x70, 0x7, 0xf0, 0xfc, 0x1f, 0xf8} + +/* Aring (197) */ +#define NXFONT_METRICS_197 {3, 21, 30, 1, 7, 0} +#define NXFONT_BITMAP_197 {0x0, 0xe0, 0x0, 0x1, 0xb0, 0x0, 0x3, 0x18, 0x0, 0x2, 0x8, 0x0, 0x3, 0x18, 0x0, 0x1, 0xb0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x70, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x1, 0xf8, 0x0, 0x1, 0x7c, 0x0, 0x1, 0x7c, 0x0, 0x3, 0x3e, 0x0, 0x2, 0x3e, 0x0, 0x6, 0x3e, 0x0, 0x6, 0x1f, 0x0, 0x4, 0x1f, 0x0, 0xc, 0xf, 0x0, 0xf, 0xff, 0x80, 0x18, 0xf, 0x80, 0x18, 0x7, 0xc0, 0x10, 0x7, 0xc0, 0x30, 0x3, 0xe0, 0x30, 0x3, 0xe0, 0x70, 0x7, 0xf0, 0xfc, 0x1f, 0xf8} + +/* AE (198) */ +#define NXFONT_METRICS_198 {4, 32, 23, 0, 14, 0} +#define NXFONT_BITMAP_198 {0x3, 0xff, 0xff, 0xfc, 0x0, 0xff, 0xff, 0xfc, 0x0, 0x63, 0xe0, 0x1c, 0x0, 0x63, 0xe0, 0xc, 0x0, 0xc3, 0xe0, 0xc, 0x0, 0xc3, 0xe0, 0x4, 0x1, 0x83, 0xe0, 0x4, 0x1, 0x83, 0xe0, 0x80, 0x3, 0x3, 0xe0, 0x80, 0x3, 0x3, 0xe1, 0x80, 0x2, 0x3, 0xe3, 0x80, 0x7, 0xff, 0xff, 0x80, 0x7, 0xff, 0xe3, 0x80, 0xc, 0x3, 0xe1, 0x80, 0xc, 0x3, 0xe0, 0x80, 0x18, 0x3, 0xe0, 0x80, 0x18, 0x3, 0xe0, 0x1, 0x38, 0x3, 0xe0, 0x3, 0x30, 0x3, 0xe0, 0x6, 0x70, 0x3, 0xe0, 0xe, 0x70, 0x3, 0xe0, 0x3e, 0xf8, 0x7, 0xff, 0xfc, 0xfe, 0x1f, 0xff, 0xfc} + +/* Ccedilla (199) */ +#define NXFONT_METRICS_199 {3, 19, 30, 2, 14, 0} +#define NXFONT_BITMAP_199 {0x1, 0xfc, 0x20, 0x7, 0xff, 0x60, 0xf, 0x7, 0xe0, 0x1e, 0x1, 0xe0, 0x3c, 0x0, 0xe0, 0x7c, 0x0, 0x60, 0x7c, 0x0, 0x60, 0xf8, 0x0, 0x20, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x3c, 0x0, 0x20, 0x1e, 0x0, 0x60, 0xf, 0x81, 0xc0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0, 0x0, 0x18, 0x0, 0x0, 0x30, 0x0, 0x0, 0x70, 0x0, 0x0, 0x38, 0x0, 0x3, 0x18, 0x0, 0x3, 0xb8, 0x0, 0x1, 0xf0, 0x0} + +/* Egrave (200) */ +#define NXFONT_METRICS_200 {3, 21, 30, 0, 7, 0} +#define NXFONT_BITMAP_200 {0x6, 0x0, 0x0, 0x7, 0x0, 0x0, 0x3, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xe0, 0x1f, 0x0, 0xe0, 0x1f, 0x0, 0x60, 0x1f, 0x0, 0x60, 0x1f, 0x0, 0x20, 0x1f, 0x0, 0x20, 0x1f, 0x4, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0xc, 0x0, 0x1f, 0x1c, 0x0, 0x1f, 0xfc, 0x0, 0x1f, 0x1c, 0x0, 0x1f, 0xc, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0x0, 0x8, 0x1f, 0x0, 0x18, 0x1f, 0x0, 0x30, 0x1f, 0x0, 0x70, 0x1f, 0x1, 0xf0, 0x3f, 0xff, 0xe0, 0xff, 0xff, 0xe0} + +/* Eacute (201) */ +#define NXFONT_METRICS_201 {3, 21, 30, 0, 7, 0} +#define NXFONT_BITMAP_201 {0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x7, 0x0, 0x0, 0xe, 0x0, 0x0, 0x18, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xe0, 0x1f, 0x0, 0xe0, 0x1f, 0x0, 0x60, 0x1f, 0x0, 0x60, 0x1f, 0x0, 0x20, 0x1f, 0x0, 0x20, 0x1f, 0x4, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0xc, 0x0, 0x1f, 0x1c, 0x0, 0x1f, 0xfc, 0x0, 0x1f, 0x1c, 0x0, 0x1f, 0xc, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0x0, 0x8, 0x1f, 0x0, 0x18, 0x1f, 0x0, 0x30, 0x1f, 0x0, 0x70, 0x1f, 0x1, 0xf0, 0x3f, 0xff, 0xe0, 0xff, 0xff, 0xe0} + +/* Ecircumflex (202) */ +#define NXFONT_METRICS_202 {3, 21, 30, 0, 7, 0} +#define NXFONT_BITMAP_202 {0x0, 0x30, 0x0, 0x0, 0x78, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xcc, 0x0, 0x1, 0x86, 0x0, 0x1, 0x2, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xe0, 0x1f, 0x0, 0xe0, 0x1f, 0x0, 0x60, 0x1f, 0x0, 0x60, 0x1f, 0x0, 0x20, 0x1f, 0x0, 0x20, 0x1f, 0x4, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0xc, 0x0, 0x1f, 0x1c, 0x0, 0x1f, 0xfc, 0x0, 0x1f, 0x1c, 0x0, 0x1f, 0xc, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0x0, 0x8, 0x1f, 0x0, 0x18, 0x1f, 0x0, 0x30, 0x1f, 0x0, 0x70, 0x1f, 0x1, 0xf0, 0x3f, 0xff, 0xe0, 0xff, 0xff, 0xe0} + +/* Edieresis (203) */ +#define NXFONT_METRICS_203 {3, 21, 29, 0, 8, 0} +#define NXFONT_BITMAP_203 {0x0, 0x84, 0x0, 0x1, 0xce, 0x0, 0x1, 0xce, 0x0, 0x0, 0x84, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xe0, 0x1f, 0x0, 0xe0, 0x1f, 0x0, 0x60, 0x1f, 0x0, 0x60, 0x1f, 0x0, 0x20, 0x1f, 0x0, 0x20, 0x1f, 0x4, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0xc, 0x0, 0x1f, 0x1c, 0x0, 0x1f, 0xfc, 0x0, 0x1f, 0x1c, 0x0, 0x1f, 0xc, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0x4, 0x0, 0x1f, 0x0, 0x8, 0x1f, 0x0, 0x18, 0x1f, 0x0, 0x30, 0x1f, 0x0, 0x70, 0x1f, 0x1, 0xf0, 0x3f, 0xff, 0xe0, 0xff, 0xff, 0xe0} + +/* Igrave (204) */ +#define NXFONT_METRICS_204 {2, 11, 30, 1, 7, 0} +#define NXFONT_BITMAP_204 {0xc0, 0x0, 0xe0, 0x0, 0x70, 0x0, 0x38, 0x0, 0xc, 0x0, 0x6, 0x0, 0x0, 0x0, 0xff, 0xe0, 0x3f, 0x80, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0xff, 0xe0} + +/* Iacute (205) */ +#define NXFONT_METRICS_205 {2, 12, 30, 1, 7, 0} +#define NXFONT_BITMAP_205 {0x0, 0x30, 0x0, 0x70, 0x0, 0xe0, 0x1, 0xc0, 0x3, 0x0, 0x6, 0x0, 0x0, 0x0, 0xff, 0xe0, 0x3f, 0x80, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0xff, 0xe0} + +/* Icircumflex (206) */ +#define NXFONT_METRICS_206 {2, 11, 30, 1, 7, 0} +#define NXFONT_BITMAP_206 {0x6, 0x0, 0xf, 0x0, 0x1f, 0x80, 0x19, 0x80, 0x30, 0xc0, 0x20, 0x40, 0x0, 0x0, 0xff, 0xe0, 0x3f, 0x80, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0xff, 0xe0} + +/* Idieresis (207) */ +#define NXFONT_METRICS_207 {2, 11, 29, 1, 8, 0} +#define NXFONT_BITMAP_207 {0x10, 0x80, 0x39, 0xc0, 0x39, 0xc0, 0x10, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, 0x3f, 0x80, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x3f, 0x80, 0xff, 0xe0} + +/* Eth (208) */ +#define NXFONT_METRICS_208 {3, 22, 23, 0, 14, 0} +#define NXFONT_BITMAP_208 {0xff, 0xfe, 0x0, 0x3f, 0xf, 0x80, 0x1f, 0x3, 0xe0, 0x1f, 0x1, 0xf0, 0x1f, 0x1, 0xf0, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xfc, 0x1f, 0x0, 0xfc, 0x1f, 0x0, 0xfc, 0xff, 0xf0, 0x7c, 0xff, 0xf0, 0x7c, 0xff, 0xf0, 0x7c, 0x1f, 0x0, 0x7c, 0x1f, 0x0, 0xfc, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x0, 0xf8, 0x1f, 0x1, 0xf0, 0x1f, 0x1, 0xe0, 0x1f, 0x3, 0xc0, 0x3f, 0xf, 0x80, 0x7f, 0xfe, 0x0} + +/* Ntilde (209) */ +#define NXFONT_METRICS_209 {3, 22, 29, 1, 8, 0} +#define NXFONT_BITMAP_209 {0x0, 0x61, 0x0, 0x0, 0xfb, 0x0, 0x1, 0xbe, 0x0, 0x1, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x1, 0xfc, 0x7f, 0x0, 0x70, 0x3f, 0x80, 0x20, 0x1f, 0x80, 0x20, 0x1f, 0xc0, 0x20, 0x1f, 0xe0, 0x20, 0x17, 0xf0, 0x20, 0x13, 0xf8, 0x20, 0x11, 0xf8, 0x20, 0x11, 0xfc, 0x20, 0x10, 0xfe, 0x20, 0x10, 0x7f, 0x20, 0x10, 0x3f, 0x20, 0x10, 0x1f, 0xa0, 0x10, 0x1f, 0xe0, 0x10, 0xf, 0xe0, 0x10, 0x7, 0xe0, 0x10, 0x3, 0xe0, 0x10, 0x3, 0xe0, 0x10, 0x1, 0xe0, 0x10, 0x0, 0xe0, 0x38, 0x0, 0x60, 0xfe, 0x0, 0x20} + +/* Ograve (210) */ +#define NXFONT_METRICS_210 {3, 21, 30, 2, 7, 0} +#define NXFONT_BITMAP_210 {0x6, 0x0, 0x0, 0x7, 0x0, 0x0, 0x3, 0x80, 0x0, 0x1, 0xc0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x7, 0xff, 0x0, 0xf, 0x8f, 0x80, 0x1e, 0x3, 0xc0, 0x3c, 0x1, 0xe0, 0x7c, 0x1, 0xf0, 0x78, 0x0, 0xf0, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0x78, 0x0, 0xf0, 0x7c, 0x1, 0xf0, 0x3c, 0x1, 0xe0, 0x1e, 0x3, 0xc0, 0xf, 0x8f, 0x80, 0x7, 0xff, 0x0, 0x1, 0xfc, 0x0} + +/* Oacute (211) */ +#define NXFONT_METRICS_211 {3, 21, 30, 2, 7, 0} +#define NXFONT_BITMAP_211 {0x0, 0x3, 0x80, 0x0, 0x7, 0x0, 0x0, 0xe, 0x0, 0x0, 0x18, 0x0, 0x0, 0x30, 0x0, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x7, 0xff, 0x0, 0xf, 0x8f, 0x80, 0x1e, 0x3, 0xc0, 0x3c, 0x1, 0xe0, 0x7c, 0x1, 0xf0, 0x78, 0x0, 0xf0, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0x78, 0x0, 0xf0, 0x7c, 0x1, 0xf0, 0x3c, 0x1, 0xe0, 0x1e, 0x3, 0xc0, 0xf, 0x8f, 0x80, 0x7, 0xff, 0x0, 0x1, 0xfc, 0x0} + +/* Ocircumflex (212) */ +#define NXFONT_METRICS_212 {3, 21, 30, 2, 7, 0} +#define NXFONT_BITMAP_212 {0x0, 0x30, 0x0, 0x0, 0x78, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xcc, 0x0, 0x1, 0x86, 0x0, 0x1, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x7, 0xff, 0x0, 0xf, 0x8f, 0x80, 0x1e, 0x3, 0xc0, 0x3c, 0x1, 0xe0, 0x7c, 0x1, 0xf0, 0x78, 0x0, 0xf0, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0x78, 0x0, 0xf0, 0x7c, 0x1, 0xf0, 0x3c, 0x1, 0xe0, 0x1e, 0x3, 0xc0, 0xf, 0x8f, 0x80, 0x7, 0xff, 0x0, 0x1, 0xfc, 0x0} + +/* Otilde (213) */ +#define NXFONT_METRICS_213 {3, 21, 29, 2, 8, 0} +#define NXFONT_BITMAP_213 {0x0, 0xc2, 0x0, 0x1, 0xf6, 0x0, 0x3, 0x7c, 0x0, 0x2, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x7, 0xff, 0x0, 0xf, 0x8f, 0x80, 0x1e, 0x3, 0xc0, 0x3c, 0x1, 0xe0, 0x7c, 0x1, 0xf0, 0x78, 0x0, 0xf0, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0x78, 0x0, 0xf0, 0x7c, 0x1, 0xf0, 0x3c, 0x1, 0xe0, 0x1e, 0x3, 0xc0, 0xf, 0x8f, 0x80, 0x7, 0xff, 0x0, 0x1, 0xfc, 0x0} + +/* Odieresis (214) */ +#define NXFONT_METRICS_214 {3, 21, 29, 2, 8, 0} +#define NXFONT_BITMAP_214 {0x0, 0x84, 0x0, 0x1, 0xce, 0x0, 0x1, 0xce, 0x0, 0x0, 0x84, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x7, 0xff, 0x0, 0xf, 0x8f, 0x80, 0x1e, 0x3, 0xc0, 0x3c, 0x1, 0xe0, 0x7c, 0x1, 0xf0, 0x78, 0x0, 0xf0, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0xf8, 0x0, 0xf8, 0x78, 0x0, 0xf0, 0x7c, 0x1, 0xf0, 0x3c, 0x1, 0xe0, 0x1e, 0x3, 0xc0, 0xf, 0x8f, 0x80, 0x7, 0xff, 0x0, 0x1, 0xfc, 0x0} + +/* multiply (215) */ +#define NXFONT_METRICS_215 {2, 15, 16, 2, 21, 0} +#define NXFONT_BITMAP_215 {0x40, 0x4, 0xe0, 0xe, 0xf0, 0x1e, 0x78, 0x3c, 0x3c, 0x78, 0x1e, 0xf0, 0xf, 0xe0, 0x7, 0xc0, 0x7, 0xc0, 0xf, 0xe0, 0x1e, 0xf0, 0x3c, 0x78, 0x78, 0x3c, 0xf0, 0x1e, 0xe0, 0xe, 0x40, 0x4} + +/* Oslash (216) */ +#define NXFONT_METRICS_216 {3, 21, 27, 2, 12, 0} +#define NXFONT_BITMAP_216 {0x0, 0x0, 0x30, 0x0, 0x0, 0x60, 0x1, 0xfc, 0x40, 0x7, 0x8f, 0xc0, 0xe, 0x3, 0x80, 0x1e, 0x1, 0xc0, 0x3c, 0x3, 0xe0, 0x7c, 0x6, 0xf0, 0x78, 0x4, 0xf0, 0xf8, 0xc, 0xf8, 0xf8, 0x18, 0xf8, 0xf8, 0x18, 0xf8, 0xf8, 0x30, 0xf8, 0xf8, 0x20, 0xf8, 0xf8, 0x60, 0xf8, 0xf8, 0xc0, 0xf8, 0xf8, 0x80, 0xf8, 0xf9, 0x80, 0xf8, 0x7b, 0x0, 0xf0, 0x7e, 0x1, 0xf0, 0x3e, 0x1, 0xe0, 0x1c, 0x3, 0xc0, 0xe, 0x7, 0x80, 0x1f, 0xfe, 0x0, 0x11, 0xf8, 0x0, 0x30, 0x0, 0x0, 0x60, 0x0, 0x0} + +/* Ugrave (217) */ +#define NXFONT_METRICS_217 {3, 23, 30, 0, 7, 0} +#define NXFONT_BITMAP_217 {0x0, 0xc0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x38, 0x0, 0x0, 0xc, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, 0xfe, 0x3f, 0x80, 0x38, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x30, 0xf, 0x80, 0x30, 0xf, 0x80, 0x60, 0x7, 0xc0, 0xc0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* Uacute (218) */ +#define NXFONT_METRICS_218 {3, 23, 30, 0, 7, 0} +#define NXFONT_BITMAP_218 {0x0, 0x0, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x3, 0x80, 0x0, 0x7, 0x0, 0x0, 0xc, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, 0xfe, 0x3f, 0x80, 0x38, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x30, 0xf, 0x80, 0x30, 0xf, 0x80, 0x60, 0x7, 0xc0, 0xc0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* Ucircumflex (219) */ +#define NXFONT_METRICS_219 {3, 23, 30, 0, 7, 0} +#define NXFONT_BITMAP_219 {0x0, 0xc, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x3f, 0x0, 0x0, 0x33, 0x0, 0x0, 0x61, 0x80, 0x0, 0x40, 0x80, 0x0, 0x0, 0x0, 0xff, 0xe0, 0xfe, 0x3f, 0x80, 0x38, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x30, 0xf, 0x80, 0x30, 0xf, 0x80, 0x60, 0x7, 0xc0, 0xc0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* Udieresis (220) */ +#define NXFONT_METRICS_220 {3, 23, 29, 0, 8, 0} +#define NXFONT_BITMAP_220 {0x0, 0x21, 0x0, 0x0, 0x73, 0x80, 0x0, 0x73, 0x80, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, 0xfe, 0x3f, 0x80, 0x38, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x10, 0x1f, 0x0, 0x30, 0xf, 0x80, 0x30, 0xf, 0x80, 0x60, 0x7, 0xc0, 0xc0, 0x3, 0xff, 0x80, 0x0, 0xfe, 0x0} + +/* Yacute (221) */ +#define NXFONT_METRICS_221 {3, 22, 30, 1, 7, 0} +#define NXFONT_BITMAP_221 {0x0, 0x0, 0xc0, 0x0, 0x1, 0xc0, 0x0, 0x3, 0x80, 0x0, 0x7, 0x0, 0x0, 0xc, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc3, 0xfc, 0x7f, 0x0, 0xf0, 0x3f, 0x0, 0x60, 0x3f, 0x0, 0x60, 0x1f, 0x80, 0xc0, 0x1f, 0x80, 0x80, 0xf, 0xc1, 0x80, 0xf, 0xc3, 0x0, 0x7, 0xe3, 0x0, 0x3, 0xe6, 0x0, 0x3, 0xf4, 0x0, 0x1, 0xfc, 0x0, 0x1, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x1, 0xfc, 0x0, 0x7, 0xff, 0x0} + +/* Thorn (222) */ +#define NXFONT_METRICS_222 {3, 19, 23, 0, 14, 0} +#define NXFONT_BITMAP_222 {0xff, 0xe0, 0x0, 0x3f, 0x80, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0xfe, 0x0, 0x1f, 0xf, 0x80, 0x1f, 0x7, 0xc0, 0x1f, 0x7, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x3, 0xe0, 0x1f, 0x7, 0xe0, 0x1f, 0x7, 0xc0, 0x1f, 0x1f, 0x80, 0x1f, 0xfe, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x3f, 0x80, 0x0, 0xff, 0xe0, 0x0} + +/* germandbls (223) */ +#define NXFONT_METRICS_223 {3, 17, 23, 0, 14, 0} +#define NXFONT_BITMAP_223 {0x3, 0xf0, 0x0, 0xe, 0x3c, 0x0, 0x1e, 0x3e, 0x0, 0x1c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1c, 0x0, 0x3c, 0x38, 0x0, 0x3c, 0xe0, 0x0, 0x3c, 0x3c, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x80, 0x3c, 0xf, 0x80, 0x3c, 0xf, 0x80, 0x3c, 0xf, 0x80, 0x3c, 0xf, 0x0, 0x3c, 0xf, 0x0, 0x3c, 0x1e, 0x0, 0xfc, 0x7c, 0x0} + +/* agrave (224) */ +#define NXFONT_METRICS_224 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_224 {0x30, 0x0, 0x38, 0x0, 0x1c, 0x0, 0xe, 0x0, 0x3, 0x0, 0x0, 0x80, 0x0, 0x0, 0x1f, 0x80, 0x31, 0xe0, 0x70, 0xf0, 0x78, 0xf0, 0x78, 0xf0, 0x30, 0xf0, 0x1, 0xf0, 0x7, 0xf0, 0x1c, 0xf0, 0x38, 0xf0, 0x78, 0xf0, 0xf0, 0xf0, 0xf9, 0xf0, 0xff, 0xf4, 0x7e, 0xfc, 0x3c, 0x78} + +/* aacute (225) */ +#define NXFONT_METRICS_225 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_225 {0x0, 0x30, 0x0, 0x70, 0x0, 0xe0, 0x1, 0xc0, 0x3, 0x0, 0x4, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x31, 0xe0, 0x70, 0xf0, 0x78, 0xf0, 0x78, 0xf0, 0x30, 0xf0, 0x1, 0xf0, 0x7, 0xf0, 0x1c, 0xf0, 0x38, 0xf0, 0x78, 0xf0, 0xf0, 0xf0, 0xf9, 0xf0, 0xff, 0xf4, 0x7e, 0xfc, 0x3c, 0x78} + +/* acircumflex (226) */ +#define NXFONT_METRICS_226 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_226 {0x3, 0x0, 0x7, 0x80, 0xf, 0xc0, 0xc, 0xc0, 0x18, 0x60, 0x10, 0x20, 0x0, 0x0, 0x1f, 0x80, 0x31, 0xe0, 0x70, 0xf0, 0x78, 0xf0, 0x78, 0xf0, 0x30, 0xf0, 0x1, 0xf0, 0x7, 0xf0, 0x1c, 0xf0, 0x38, 0xf0, 0x78, 0xf0, 0xf0, 0xf0, 0xf9, 0xf0, 0xff, 0xf4, 0x7e, 0xfc, 0x3c, 0x78} + +/* atilde (227) */ +#define NXFONT_METRICS_227 {2, 14, 22, 1, 15, 0} +#define NXFONT_BITMAP_227 {0xc, 0x20, 0x1f, 0x60, 0x37, 0xc0, 0x21, 0x80, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x31, 0xe0, 0x70, 0xf0, 0x78, 0xf0, 0x78, 0xf0, 0x30, 0xf0, 0x1, 0xf0, 0x7, 0xf0, 0x1c, 0xf0, 0x38, 0xf0, 0x78, 0xf0, 0xf0, 0xf0, 0xf9, 0xf0, 0xff, 0xf4, 0x7e, 0xfc, 0x3c, 0x78} + +/* adieresis (228) */ +#define NXFONT_METRICS_228 {2, 14, 22, 1, 15, 0} +#define NXFONT_BITMAP_228 {0x8, 0x40, 0x1c, 0xe0, 0x1c, 0xe0, 0x8, 0x40, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x31, 0xe0, 0x70, 0xf0, 0x78, 0xf0, 0x78, 0xf0, 0x30, 0xf0, 0x1, 0xf0, 0x7, 0xf0, 0x1c, 0xf0, 0x38, 0xf0, 0x78, 0xf0, 0xf0, 0xf0, 0xf9, 0xf0, 0xff, 0xf4, 0x7e, 0xfc, 0x3c, 0x78} + +/* aring (229) */ +#define NXFONT_METRICS_229 {2, 14, 25, 1, 12, 0} +#define NXFONT_BITMAP_229 {0x7, 0x0, 0xd, 0x80, 0x18, 0xc0, 0x10, 0x40, 0x18, 0xc0, 0xd, 0x80, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x31, 0xe0, 0x70, 0xf0, 0x78, 0xf0, 0x78, 0xf0, 0x30, 0xf0, 0x1, 0xf0, 0x7, 0xf0, 0x1c, 0xf0, 0x38, 0xf0, 0x78, 0xf0, 0xf0, 0xf0, 0xf9, 0xf0, 0xff, 0xf4, 0x7e, 0xfc, 0x3c, 0x78} + +/* ae (230) */ +#define NXFONT_METRICS_230 {3, 21, 16, 1, 21, 0} +#define NXFONT_BITMAP_230 {0x1f, 0x87, 0xc0, 0x31, 0xee, 0xe0, 0x70, 0xfc, 0x70, 0x78, 0xf8, 0x70, 0x78, 0xf8, 0x38, 0x30, 0xf8, 0x38, 0x1, 0xf8, 0x38, 0x7, 0xff, 0xf8, 0x1c, 0xf8, 0x0, 0x38, 0xf8, 0x0, 0x78, 0xfc, 0x0, 0xf8, 0xfc, 0x8, 0xf8, 0xfe, 0x18, 0xff, 0xff, 0xf0, 0x7e, 0x3f, 0xe0, 0x3c, 0xf, 0xc0} + +/* ccedilla (231) */ +#define NXFONT_METRICS_231 {2, 13, 23, 1, 21, 0} +#define NXFONT_BITMAP_231 {0x7, 0xe0, 0x1e, 0xf0, 0x3c, 0x78, 0x78, 0x78, 0x78, 0x30, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf8, 0x0, 0x78, 0x0, 0x78, 0x0, 0x3c, 0x30, 0x1f, 0xe0, 0xf, 0xc0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3, 0x80, 0x31, 0x80, 0x3b, 0x80, 0x1f, 0x0} + +/* egrave (232) */ +#define NXFONT_METRICS_232 {2, 14, 23, 0, 14, 0} +#define NXFONT_BITMAP_232 {0x30, 0x0, 0x38, 0x0, 0x1c, 0x0, 0xe, 0x0, 0x3, 0x0, 0x0, 0x80, 0x0, 0x0, 0x7, 0xc0, 0x1e, 0xf0, 0x3c, 0x70, 0x78, 0x38, 0x78, 0x3c, 0xf8, 0x3c, 0xf8, 0x3c, 0xff, 0xfc, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0x78, 0x0, 0x7c, 0x0, 0x3e, 0x18, 0x1f, 0xf0, 0x7, 0xe0} + +/* eacute (233) */ +#define NXFONT_METRICS_233 {2, 14, 23, 0, 14, 0} +#define NXFONT_BITMAP_233 {0x0, 0x18, 0x0, 0x38, 0x0, 0x70, 0x0, 0xe0, 0x1, 0x80, 0x2, 0x0, 0x0, 0x0, 0x7, 0xc0, 0x1e, 0xf0, 0x3c, 0x70, 0x78, 0x38, 0x78, 0x3c, 0xf8, 0x3c, 0xf8, 0x3c, 0xff, 0xfc, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0x78, 0x0, 0x7c, 0x0, 0x3e, 0x18, 0x1f, 0xf0, 0x7, 0xe0} + +/* ecircumflex (234) */ +#define NXFONT_METRICS_234 {2, 14, 23, 0, 14, 0} +#define NXFONT_BITMAP_234 {0x3, 0x0, 0x7, 0x80, 0xf, 0xc0, 0xc, 0xc0, 0x18, 0x60, 0x10, 0x20, 0x0, 0x0, 0x7, 0xc0, 0x1e, 0xf0, 0x3c, 0x70, 0x78, 0x38, 0x78, 0x3c, 0xf8, 0x3c, 0xf8, 0x3c, 0xff, 0xfc, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0x78, 0x0, 0x7c, 0x0, 0x3e, 0x18, 0x1f, 0xf0, 0x7, 0xe0} + +/* edieresis (235) */ +#define NXFONT_METRICS_235 {2, 14, 22, 0, 15, 0} +#define NXFONT_BITMAP_235 {0x4, 0x20, 0xe, 0x70, 0xe, 0x70, 0x4, 0x20, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc0, 0x1e, 0xf0, 0x3c, 0x70, 0x78, 0x38, 0x78, 0x3c, 0xf8, 0x3c, 0xf8, 0x3c, 0xff, 0xfc, 0xf8, 0x0, 0xf8, 0x0, 0xf8, 0x0, 0x78, 0x0, 0x7c, 0x0, 0x3e, 0x18, 0x1f, 0xf0, 0x7, 0xe0} + +/* igrave (236) */ +#define NXFONT_METRICS_236 {1, 8, 23, 0, 14, 0} +#define NXFONT_BITMAP_236 {0xc0, 0xe0, 0x70, 0x38, 0xc, 0x2, 0x0, 0xfc, 0x7c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x7e, 0xff} + +/* iacute (237) */ +#define NXFONT_METRICS_237 {1, 8, 23, 0, 14, 0} +#define NXFONT_BITMAP_237 {0x3, 0x7, 0xe, 0x1c, 0x30, 0x40, 0x0, 0xfc, 0x7c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x7e, 0xff} + +/* icircumflex (238) */ +#define NXFONT_METRICS_238 {1, 8, 23, 0, 14, 0} +#define NXFONT_BITMAP_238 {0x18, 0x3c, 0x7e, 0x66, 0xc3, 0x81, 0x0, 0xfc, 0x7c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x7e, 0xff} + +/* idieresis (239) */ +#define NXFONT_METRICS_239 {1, 8, 22, 0, 15, 0} +#define NXFONT_BITMAP_239 {0x42, 0xe7, 0xe7, 0x42, 0x0, 0x0, 0xfc, 0x7c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x7e, 0xff} + +/* eth (240) */ +#define NXFONT_METRICS_240 {2, 14, 22, 1, 15, 0} +#define NXFONT_BITMAP_240 {0x38, 0x30, 0x3e, 0xf8, 0xf, 0xf8, 0xff, 0x80, 0xfb, 0xc0, 0x61, 0xe0, 0xf, 0xf0, 0x3c, 0xf8, 0x78, 0x78, 0x78, 0x78, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0x78, 0x78, 0x78, 0x78, 0x3c, 0xf0, 0xf, 0xc0} + +/* ntilde (241) */ +#define NXFONT_METRICS_241 {3, 17, 22, 0, 15, 0} +#define NXFONT_BITMAP_241 {0x3, 0x8, 0x0, 0x7, 0xd8, 0x0, 0xd, 0xf0, 0x0, 0x8, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x78, 0x0, 0x7d, 0xfc, 0x0, 0x3f, 0x3e, 0x0, 0x3e, 0x1e, 0x0, 0x3e, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x7e, 0x3f, 0x0, 0xff, 0x7f, 0x80} + +/* ograve (242) */ +#define NXFONT_METRICS_242 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_242 {0x30, 0x0, 0x38, 0x0, 0x1c, 0x0, 0xe, 0x0, 0x3, 0x0, 0x0, 0x80, 0x0, 0x0, 0xf, 0xc0, 0x3c, 0xf0, 0x78, 0x78, 0x78, 0x78, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0x78, 0x78, 0x78, 0x78, 0x3c, 0xf0, 0xf, 0xc0} + +/* oacute (243) */ +#define NXFONT_METRICS_243 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_243 {0x0, 0x18, 0x0, 0x38, 0x0, 0x70, 0x0, 0xe0, 0x1, 0x80, 0x2, 0x0, 0x0, 0x0, 0xf, 0xc0, 0x3c, 0xf0, 0x78, 0x78, 0x78, 0x78, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0x78, 0x78, 0x78, 0x78, 0x3c, 0xf0, 0xf, 0xc0} + +/* ocircumflex (244) */ +#define NXFONT_METRICS_244 {2, 14, 23, 1, 14, 0} +#define NXFONT_BITMAP_244 {0x3, 0x0, 0x7, 0x80, 0xf, 0xc0, 0xc, 0xc0, 0x18, 0x60, 0x10, 0x20, 0x0, 0x0, 0xf, 0xc0, 0x3c, 0xf0, 0x78, 0x78, 0x78, 0x78, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0x78, 0x78, 0x78, 0x78, 0x3c, 0xf0, 0xf, 0xc0} + +/* otilde (245) */ +#define NXFONT_METRICS_245 {2, 14, 22, 1, 15, 0} +#define NXFONT_BITMAP_245 {0xc, 0x20, 0x1f, 0x60, 0x37, 0xc0, 0x21, 0x80, 0x0, 0x0, 0x0, 0x0, 0xf, 0xc0, 0x3c, 0xf0, 0x78, 0x78, 0x78, 0x78, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0x78, 0x78, 0x78, 0x78, 0x3c, 0xf0, 0xf, 0xc0} + +/* odieresis (246) */ +#define NXFONT_METRICS_246 {2, 14, 22, 1, 15, 0} +#define NXFONT_BITMAP_246 {0x8, 0x40, 0x1c, 0xe0, 0x1c, 0xe0, 0x8, 0x40, 0x0, 0x0, 0x0, 0x0, 0xf, 0xc0, 0x3c, 0xf0, 0x78, 0x78, 0x78, 0x78, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0x78, 0x78, 0x78, 0x78, 0x3c, 0xf0, 0xf, 0xc0} + +/* divide (247) */ +#define NXFONT_METRICS_247 {2, 14, 15, 2, 21, 0} +#define NXFONT_BITMAP_247 {0x3, 0x0, 0x7, 0x80, 0x7, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x7, 0x80, 0x7, 0x80, 0x3, 0x0} + +/* oslash (248) */ +#define NXFONT_METRICS_248 {2, 14, 22, 1, 18, 0} +#define NXFONT_BITMAP_248 {0x0, 0x8, 0x0, 0x18, 0x0, 0x18, 0xf, 0xf0, 0x3c, 0xf0, 0x78, 0x78, 0x78, 0x78, 0xf0, 0xfc, 0xf1, 0xbc, 0xf1, 0x3c, 0xf3, 0x3c, 0xf2, 0x3c, 0xf6, 0x3c, 0xfc, 0x3c, 0xf8, 0x3c, 0x78, 0x78, 0x78, 0x78, 0x3c, 0xf0, 0x6f, 0xc0, 0x60, 0x0, 0xc0, 0x0, 0x80, 0x0} + +/* ugrave (249) */ +#define NXFONT_METRICS_249 {3, 17, 23, 0, 14, 0} +#define NXFONT_BITMAP_249 {0x18, 0x0, 0x0, 0x1c, 0x0, 0x0, 0xe, 0x0, 0x0, 0x7, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x7e, 0x0, 0x7c, 0x3e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x3e, 0x0, 0x3e, 0x7f, 0x0, 0x1f, 0xdf, 0x80, 0x7, 0x8c, 0x0} + +/* uacute (250) */ +#define NXFONT_METRICS_250 {3, 17, 23, 0, 14, 0} +#define NXFONT_BITMAP_250 {0x0, 0xc, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x38, 0x0, 0x0, 0x70, 0x0, 0x0, 0xc0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x7e, 0x0, 0x7c, 0x3e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x3e, 0x0, 0x3e, 0x7f, 0x0, 0x1f, 0xdf, 0x80, 0x7, 0x8c, 0x0} + +/* ucircumflex (251) */ +#define NXFONT_METRICS_251 {3, 17, 23, 0, 14, 0} +#define NXFONT_BITMAP_251 {0x1, 0x80, 0x0, 0x3, 0xc0, 0x0, 0x7, 0xe0, 0x0, 0x6, 0x60, 0x0, 0xc, 0x30, 0x0, 0x8, 0x10, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x7e, 0x0, 0x7c, 0x3e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x3e, 0x0, 0x3e, 0x7f, 0x0, 0x1f, 0xdf, 0x80, 0x7, 0x8c, 0x0} + +/* udieresis (252) */ +#define NXFONT_METRICS_252 {3, 17, 22, 0, 15, 0} +#define NXFONT_BITMAP_252 {0x4, 0x20, 0x0, 0xe, 0x70, 0x0, 0xe, 0x70, 0x0, 0x4, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x7e, 0x0, 0x7c, 0x3e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x1e, 0x0, 0x3c, 0x3e, 0x0, 0x3e, 0x7f, 0x0, 0x1f, 0xdf, 0x80, 0x7, 0x8c, 0x0} + +/* yacute (253) */ +#define NXFONT_METRICS_253 {2, 15, 30, 0, 14, 0} +#define NXFONT_BITMAP_253 {0x0, 0xc, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x70, 0x0, 0xc0, 0x1, 0x0, 0x0, 0x0, 0xff, 0xbe, 0x7e, 0xc, 0x3e, 0x8, 0x3e, 0x8, 0x1f, 0x18, 0x1f, 0x10, 0xf, 0x10, 0xf, 0xb0, 0xf, 0xa0, 0x7, 0xa0, 0x7, 0xe0, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x73, 0x0, 0xf3, 0x0, 0xf6, 0x0, 0xfe, 0x0, 0x78, 0x0} + +/* thorn (254) */ +#define NXFONT_METRICS_254 {2, 15, 29, 1, 15, 0} +#define NXFONT_BITMAP_254 {0xfc, 0x0, 0x7c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0xe0, 0x3f, 0xf8, 0x3e, 0x7c, 0x3c, 0x3c, 0x3c, 0x3e, 0x3c, 0x1e, 0x3c, 0x1e, 0x3c, 0x1e, 0x3c, 0x1e, 0x3c, 0x1e, 0x3c, 0x1e, 0x3c, 0x1e, 0x3c, 0x3c, 0x3e, 0x3c, 0x3f, 0xf8, 0x3c, 0xe0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x7e, 0x0, 0xff, 0x0} + +/* ydieresis (255) */ +#define NXFONT_METRICS_255 {2, 15, 29, 0, 15, 0} +#define NXFONT_BITMAP_255 {0x4, 0x20, 0xe, 0x70, 0xe, 0x70, 0x4, 0x20, 0x0, 0x0, 0x0, 0x0, 0xff, 0xbe, 0x7e, 0xc, 0x3e, 0x8, 0x3e, 0x8, 0x1f, 0x18, 0x1f, 0x10, 0xf, 0x10, 0xf, 0xb0, 0xf, 0xa0, 0x7, 0xa0, 0x7, 0xe0, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x73, 0x0, 0xf3, 0x0, 0xf6, 0x0, 0xfe, 0x0, 0x78, 0x0} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXFONTS_NXFONTS_SERIF38X49B_H */ diff --git a/nuttx/graphics/nxglib/Make.defs b/nuttx/graphics/nxglib/Make.defs new file mode 100644 index 0000000000..240cdbd7cb --- /dev/null +++ b/nuttx/graphics/nxglib/Make.defs @@ -0,0 +1,93 @@ +############################################################################ +# graphics/nxglib/Make.defs +# +# Copyright (C) 2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +NXGLIB_ASRCS = + +SETP1_CSRCS = nxglib_setpixel_1bpp.c nxglib_setpixel_2bpp.c \ + nxglib_setpixel_4bpp.c + +SETP2_CSRCS = nxglib_setpixel_8bpp.c nxglib_setpixel_16bpp.c \ + nxglib_setpixel_24bpp.c nxglib_setpixel_32bpp.c + +RFILL1_CSRCS = nxglib_fillrectangle_1bpp.c nxglib_fillrectangle_2bpp.c \ + nxglib_fillrectangle_4bpp.c + +RFILL2_CSRCS = nxglib_fillrectangle_8bpp.c nxglib_fillrectangle_16bpp.c \ + nxglib_fillrectangle_24bpp.c nxglib_fillrectangle_32bpp.c + +RGET1_CSRCS = nxglib_getrectangle_1bpp.c nxglib_getrectangle_2bpp.c \ + nxglib_getrectangle_4bpp.c + +RGET2_CSRCS = nxglib_getrectangle_8bpp.c nxglib_getrectangle_16bpp.c \ + nxglib_getrectangle_24bpp.c nxglib_getrectangle_32bpp.c + +TFILL1_CSRCS = nxglib_filltrapezoid_1bpp.c nxglib_filltrapezoid_2bpp.c \ + nxglib_filltrapezoid_4bpp.c + +TFILL2_CSRCS = nxglib_filltrapezoid_8bpp.c nxglib_filltrapezoid_16bpp.c \ + nxglib_filltrapezoid_24bpp.c nxglib_filltrapezoid_32bpp.c + +RMOVE1_CSRCS = nxglib_moverectangle_1bpp.c nxglib_moverectangle_2bpp.c \ + nxglib_moverectangle_4bpp.c + +RMOVE2_CSRCS = nxglib_moverectangle_8bpp.c nxglib_moverectangle_16bpp.c \ + nxglib_moverectangle_24bpp.c nxglib_moverectangle_32bpp.c + +RCOPY1_CSRCS = nxglib_copyrectangle_1bpp.c nxglib_copyrectangle_2bpp.c \ + nxglib_copyrectangle_4bpp.c + +RCOPY2_CSRCS = nxglib_copyrectangle_8bpp.c nxglib_copyrectangle_16bpp.c \ + nxglib_copyrectangle_24bpp.c nxglib_copyrectangle_32bpp.c + +RECT_CSRCS = nxglib_rectcopy.c nxglib_rectoffset.c nxglib_vectoradd.c \ + nxglib_vectsubtract.c nxglib_rectadd.c nxglib_rectintersect.c \ + nxglib_intersecting.c nxglib_nonintersecting.c nxglib_rectunion.c \ + nxglib_rectinside.c nxglib_rectoverlap.c nxglib_rectsize.c nxglib_nullrect.c + +TRAP_CSRCS = nxglib_runoffset.c nxglib_runcopy.c \ + nxglib_trapoffset.c nxglib_trapcopy.c + +COLOR_CSRCS = nxglib_colorcopy.c nxglib_rgb2yuv.c nxglib_yuv2rgb.c + +DRAW_CSRCS = nxglib_splitline.c nxglib_circlepts.c nxglib_circletraps.c + +LCD_CSRCS = + +NXGLIB_CSRCS = \ + $(SETP1_CSRCS) $(SETP2_CSRCS) $(RFILL1_CSRCS) $(RFILL2_CSRCS) \ + $(RGET1_CSRCS) $(RGET2_CSRCS) $(TFILL1_CSRCS) $(TFILL2_CSRCS) \ + $(RMOVE1_CSRCS) $(RMOVE2_CSRCS) $(RCOPY1_CSRCS) $(RCOPY2_CSRCS) \ + $(RECT_CSRCS) $(TRAP_CSRCS) $(COLOR_CSRCS) $(DRAW_CSRCS) $(LCD_CSRCS) + diff --git a/nuttx/graphics/nxglib/Makefile.sources b/nuttx/graphics/nxglib/Makefile.sources new file mode 100644 index 0000000000..67f8defc31 --- /dev/null +++ b/nuttx/graphics/nxglib/Makefile.sources @@ -0,0 +1,175 @@ +############################################################################ +# graphics/nxglib/Makefile.sources +# +# Copyright (C) 2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs + +ifeq ($(NXGLIB_BITSPERPIXEL),1) +NXGLIB_SUFFIX := _1bpp +SETP_CSRC := nxglib_setpixel_1bpp.c +RFILL_CSRC := nxglib_fillrectangle_1bpp.c +RGET_CSRC := nxglib_getrectangle_1bpp.c +TFILL_CSRC := nxglib_filltrapezoid_1bpp.c +RMOVE_CSRC := nxglib_moverectangle_1bpp.c +RCOPY_CSRC := nxglib_copyrectangle_1bpp.c +endif +ifeq ($(NXGLIB_BITSPERPIXEL),2) +NXGLIB_SUFFIX := _2bpp +SETP_CSRC := nxglib_setpixel_2bpp.c +RFILL_CSRC := nxglib_fillrectangle_2bpp.c +RGET_CSRC := nxglib_getrectangle_2bpp.c +TFILL_CSRC := nxglib_filltrapezoid_2bpp.c +RMOVE_CSRC := nxglib_moverectangle_2bpp.c +RCOPY_CSRC := nxglib_copyrectangle_2bpp.c +endif +ifeq ($(NXGLIB_BITSPERPIXEL),4) +NXGLIB_SUFFIX := _4bpp +SETP_CSRC := nxglib_setpixel_4bpp.c +RFILL_CSRC := nxglib_fillrectangle_4bpp.c +RGET_CSRC := nxglib_getrectangle_4bpp.c +TFILL_CSRC := nxglib_filltrapezoid_4bpp.c +RMOVE_CSRC := nxglib_moverectangle_4bpp.c +RCOPY_CSRC := nxglib_copyrectangle_4bpp.c +endif +ifeq ($(NXGLIB_BITSPERPIXEL),8) +NXGLIB_SUFFIX := _8bpp +SETP_CSRC := nxglib_setpixel_8bpp.c +RFILL_CSRC := nxglib_fillrectangle_8bpp.c +RGET_CSRC := nxglib_getrectangle_8bpp.c +TFILL_CSRC := nxglib_filltrapezoid_8bpp.c +RMOVE_CSRC := nxglib_moverectangle_8bpp.c +RCOPY_CSRC := nxglib_copyrectangle_8bpp.c +endif +ifeq ($(NXGLIB_BITSPERPIXEL),16) +NXGLIB_SUFFIX := _16bpp +SETP_CSRC := nxglib_setpixel_16bpp.c +RFILL_CSRC := nxglib_fillrectangle_16bpp.c +RGET_CSRC := nxglib_getrectangle_16bpp.c +TFILL_CSRC := nxglib_filltrapezoid_16bpp.c +RMOVE_CSRC := nxglib_moverectangle_16bpp.c +RCOPY_CSRC := nxglib_copyrectangle_16bpp.c +endif +ifeq ($(NXGLIB_BITSPERPIXEL),24) +NXGLIB_SUFFIX := _24bpp +SETP_CSRC := nxglib_setpixel_24bpp.c +RFILL_CSRC := nxglib_fillrectangle_24bpp.c +RGET_CSRC := nxglib_getrectangle_24bpp.c +TFILL_CSRC := nxglib_filltrapezoid_24bpp.c +RMOVE_CSRC := nxglib_moverectangle_24bpp.c +RCOPY_CSRC := nxglib_copyrectangle_24bpp.c +endif +ifeq ($(NXGLIB_BITSPERPIXEL),32) +NXGLIB_SUFFIX := _32bpp +SETP_CSRC := nxglib_setpixel_32bpp.c +RFILL_CSRC := nxglib_fillrectangle_32bpp.c +RGET_CSRC := nxglib_getrectangle_32bpp.c +TFILL_CSRC := nxglib_filltrapezoid_32bpp.c +RMOVE_CSRC := nxglib_moverectangle_32bpp.c +RCOPY_CSRC := nxglib_copyrectangle_32bpp.c +endif + +CPPFLAGS += -DNXGLIB_BITSPERPIXEL=$(NXGLIB_BITSPERPIXEL) +CPPFLAGS += -DNXGLIB_SUFFIX=$(NXGLIB_SUFFIX) + +SETP_TMP = $(SETP_CSRC:.c=.i) +RFILL_TMP = $(RFILL_CSRC:.c=.i) +RGET_TMP = $(RGET_CSRC:.c=.i) +TFILL_TMP = $(TFILL_CSRC:.c=.i) +RMOVE_TMP = $(RMOVE_CSRC:.c=.i) +RCOPY_TMP = $(RCOPY_CSRC:.c=.i) + +GEN_CSRCS = $(SETP_CSRC) $(RFILL_CSRC) $(RGET_CSRC) $(TFILL_CSRC) $(RMOVE_CSRC) $(RCOPY_CSRC) + +ifeq ($(CONFIG_NX_LCDDRIVER),y) +BLITDIR = lcd +else +BLITDIR = fb +endif + +all: $(GEN_CSRCS) +.PHONY : clean distclean + +$(SETP_CSRC) : $(BLITDIR)/nxglib_setpixel.c nxglib_bitblit.h +ifneq ($(NXGLIB_BITSPERPIXEL),) + @$(call PREPROCESS, $(BLITDIR)/nxglib_setpixel.c, $(SETP_TMP)) + @cat $(SETP_TMP) | sed -e "/^#/d" >$@ + @rm -f $(SETP_TMP) +endif + +$(RFILL_CSRC) : $(BLITDIR)/nxglib_fillrectangle.c nxglib_bitblit.h +ifneq ($(NXGLIB_BITSPERPIXEL),) + @$(call PREPROCESS, $(BLITDIR)/nxglib_fillrectangle.c, $(RFILL_TMP)) + @cat $(RFILL_TMP) | sed -e "/^#/d" >$@ + @rm -f $(RFILL_TMP) +endif + +$(RGET_CSRC) : $(BLITDIR)/nxglib_getrectangle.c nxglib_bitblit.h +ifneq ($(NXGLIB_BITSPERPIXEL),) + @$(call PREPROCESS, $(BLITDIR)/nxglib_getrectangle.c, $(RGET_TMP)) + @cat $(RGET_TMP) | sed -e "/^#/d" >$@ + @rm -f $(RGET_TMP) +endif + +$(TFILL_CSRC) : $(BLITDIR)/nxglib_filltrapezoid.c nxglib_bitblit.h +ifneq ($(NXGLIB_BITSPERPIXEL),) + @$(call PREPROCESS, $(BLITDIR)/nxglib_filltrapezoid.c, $(TFILL_TMP)) + @cat $(TFILL_TMP) | sed -e "/^#/d" >$@ + @rm -f $(TFILL_TMP) +endif + +$(RMOVE_CSRC) : $(BLITDIR)/nxglib_moverectangle.c nxglib_bitblit.h +ifneq ($(NXGLIB_BITSPERPIXEL),) + @$(call PREPROCESS, $(BLITDIR)/nxglib_moverectangle.c, $(RMOVE_TMP)) + @cat $(RMOVE_TMP) | sed -e "/^#/d" >$@ + @rm -f $(RMOVE_TMP) +endif + +$(RCOPY_CSRC) : $(BLITDIR)/nxglib_copyrectangle.c nxglib_bitblit.h +ifneq ($(NXGLIB_BITSPERPIXEL),) + @$(call PREPROCESS, $(BLITDIR)/nxglib_copyrectangle.c, $(RCOPY_TMP)) + @cat $(RCOPY_TMP) | sed -e "/^#/d" >$@ + @rm -f $(RCOPY_TMP) +endif + +clean: + @rm -f *~ .*.swp *.i + +distclean: clean + @rm -f nxglib_setpixel_*bpp.c + @rm -f nxglib_fillrectangle_*bpp.c + @rm -f nxglib_getrectangle_*bpp.c + @rm -f nxglib_filltrapezoid_*bpp.c + @rm -f nxglib_moverectangle_*bpp.c + @rm -f nxglib_copyrectangle_*bpp.c diff --git a/nuttx/graphics/nxglib/fb/nxglib_copyrectangle.c b/nuttx/graphics/nxglib/fb/nxglib_copyrectangle.c new file mode 100644 index 0000000000..4ad792a4cb --- /dev/null +++ b/nuttx/graphics/nxglib/fb/nxglib_copyrectangle.c @@ -0,0 +1,179 @@ +/**************************************************************************** + * graphics/nxglib/fb/nxsglib_copyrectangle.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "nxglib_bitblit.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_copyrectangle_*bpp + * + * Descripton: + * Copy a rectangular bitmap image into the specific position in the + * framebuffer memory. + * + ****************************************************************************/ + +void NXGL_FUNCNAME(nxgl_copyrectangle,NXGLIB_SUFFIX) +(FAR struct fb_planeinfo_s *pinfo, FAR const struct nxgl_rect_s *dest, + FAR const void *src, FAR const struct nxgl_point_s *origin, + unsigned int srcstride) +{ + FAR const uint8_t *sline; + FAR uint8_t *dline; + unsigned int width; + unsigned int deststride; + unsigned int rows; + +#if NXGLIB_BITSPERPIXEL < 8 + FAR const uint8_t *sptr; + FAR uint8_t *dptr; + uint8_t leadmask; + uint8_t tailmask; + uint8_t mask; + int lnlen; +#endif + + /* Get the width of the framebuffer in bytes */ + + deststride = pinfo->stride; + + /* Get the dimensions of the rectange to fill: width in pixels, + * height in rows + */ + + width = dest->pt2.x - dest->pt1.x + 1; + rows = dest->pt2.y - dest->pt1.y + 1; + +#if NXGLIB_BITSPERPIXEL < 8 +# ifdef CONFIG_NX_PACKEDMSFIRST + + /* Get the mask for pixels that are ordered so that they pack from the + * MS byte down. + */ + + leadmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(dest->pt1.x))); + tailmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(dest->pt2.x-1))); +# else + /* Get the mask for pixels that are ordered so that they pack from the + * LS byte up. + */ + + leadmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(dest->pt1.x))); + tailmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(dest->pt1.x-1))); +# endif +#endif + + /* Then copy the image */ + + sline = (const uint8_t*)src + NXGL_SCALEX(dest->pt1.x - origin->x) + (dest->pt1.y - origin->y) * srcstride; + dline = pinfo->fbmem + dest->pt1.y * deststride + NXGL_SCALEX(dest->pt1.x); + + while (rows--) + { +#if NXGLIB_BITSPERPIXEL < 8 + /* Handle masking of the fractional initial byte */ + + mask = leadmask; + sptr = sline; + dptr = dline; + lnlen = width; + + if (lnlen > 1 && mask) + { + dptr[0] = (dptr[0] & ~mask) | (sptr[0] & mask); + mask = 0xff; + dptr++; + sptr++; + lnlen--; + } + + /* Handle masking of the fractional final byte */ + + mask &= tailmask; + if (lnlen > 0 && mask) + { + dptr[lnlen-1] = (dptr[lnlen-1] & ~mask) | (sptr[lnlen-1] & mask); + lnlen--; + } + + /* Handle all of the unmasked bytes in-between */ + + if (lnlen > 0) + { + NXGL_MEMCPY(dptr, sptr, lnlen); + } +#else + /* Copy the whole line */ + + NXGL_MEMCPY((NXGL_PIXEL_T*)dline, (NXGL_PIXEL_T*)sline, width); +#endif + dline += deststride; + sline += srcstride; + } +} diff --git a/nuttx/graphics/nxglib/fb/nxglib_fillrectangle.c b/nuttx/graphics/nxglib/fb/nxglib_fillrectangle.c new file mode 100644 index 0000000000..cb9483c989 --- /dev/null +++ b/nuttx/graphics/nxglib/fb/nxglib_fillrectangle.c @@ -0,0 +1,177 @@ +/**************************************************************************** + * graphics/nxglib/fb/nxglib_fillrectangle.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "nxglib_bitblit.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#ifndef NXGLIB_SUFFIX +# error "NXGLIB_SUFFIX must be defined before including this header file" +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_fillrectangle_*bpp + * + * Descripton: + * Fill a rectangle region in the framebuffer memory with a fixed color + * + ****************************************************************************/ + +void NXGL_FUNCNAME(nxgl_fillrectangle,NXGLIB_SUFFIX) + (FAR struct fb_planeinfo_s *pinfo, + FAR const struct nxgl_rect_s *rect, + NXGL_PIXEL_T color) +{ + FAR uint8_t *line; + unsigned int width; + unsigned int stride; + int rows; + +#if NXGLIB_BITSPERPIXEL < 8 + FAR uint8_t *dest; + uint8_t mpixel = NXGL_MULTIPIXEL(color); + uint8_t leadmask; + uint8_t tailmask; + uint8_t mask; + int lnlen; +#endif + + /* Get the width of the framebuffer in bytes */ + + stride = pinfo->stride; + + /* Get the dimensions of the rectange to fill in pixels */ + + width = rect->pt2.x - rect->pt1.x + 1; + rows = rect->pt2.y - rect->pt1.y + 1; + + /* Get the address of the first byte in the first line to write */ + + line = pinfo->fbmem + rect->pt1.y * stride + NXGL_SCALEX(rect->pt1.x); + +#if NXGLIB_BITSPERPIXEL < 8 +# ifdef CONFIG_NX_PACKEDMSFIRST + + /* Get the mask for pixels that are ordered so that they pack from the + * MS byte down. + */ + + leadmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(rect->pt1.x))); + tailmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(rect->pt2.x-1))); +# else + /* Get the mask for pixels that are ordered so that they pack from the + * LS byte up. + */ + + leadmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(rect->pt1.x))); + tailmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(rect->pt1.x-1))); +# endif +#endif + + /* Then fill the rectangle line-by-line */ + + while (rows-- > 0) + { +#if NXGLIB_BITSPERPIXEL < 8 + /* Handle masking of the fractional initial byte */ + + mask = leadmask; + dest = line; + lnlen = width; + + if (lnlen > 1 && mask) + { + dest[0] = (dest[0] & ~mask) | (mpixel & mask); + mask = 0xff; + dest++; + lnlen--; + } + + /* Handle masking of the fractional final byte */ + + mask &= tailmask; + if (lnlen > 0 && mask) + { + dest[lnlen-1] = (dest[lnlen-1] & ~mask) | (mpixel & mask); + lnlen--; + } + + /* Handle all of the unmasked bytes in-between */ + + if (lnlen > 0) + { + NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, lnlen); + } +#else + /* Draw the entire raster line */ + + NXGL_MEMSET(line, (NXGL_PIXEL_T)color, width); +#endif + line += stride; + } +} diff --git a/nuttx/graphics/nxglib/fb/nxglib_filltrapezoid.c b/nuttx/graphics/nxglib/fb/nxglib_filltrapezoid.c new file mode 100644 index 0000000000..7623bf84fc --- /dev/null +++ b/nuttx/graphics/nxglib/fb/nxglib_filltrapezoid.c @@ -0,0 +1,285 @@ +/**************************************************************************** + * graphics/nxglib/fb/nxglib_filltrapezoid.c + * + * Copyright (C) 2008-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "nxglib_bitblit.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#ifndef NXGLIB_SUFFIX +# error "NXGLIB_SUFFIX must be defined before including this header file" +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxglib_filltrapezoid_*bpp + * + * Descripton: + * Fill a trapezoidal region in the framebuffer memory with a fixed color. + * Clip the trapezoid to lie within a boundng box. This is useful for + * drawing complex shapes that can be broken into a set of trapezoids. + * + ****************************************************************************/ + +void NXGL_FUNCNAME(nxgl_filltrapezoid,NXGLIB_SUFFIX)( + FAR struct fb_planeinfo_s *pinfo, + FAR const struct nxgl_trapezoid_s *trap, + FAR const struct nxgl_rect_s *bounds, + NXGL_PIXEL_T color) +{ + unsigned int stride; + unsigned int width; + FAR uint8_t *dest; + FAR uint8_t *line; + int nrows; + b16_t x1; + b16_t x2; + nxgl_coord_t y1; + nxgl_coord_t y2; + b16_t dx1dy; + b16_t dx2dy; + +#if NXGLIB_BITSPERPIXEL < 8 + uint8_t mpixel = NXGL_MULTIPIXEL(color); + uint8_t mask; + int lnlen; +#endif + + /* Get the width of the framebuffer in bytes */ + + stride = pinfo->stride; + + /* Get the top run position and the number of rows to draw */ + + x1 = trap->top.x1; + x2 = trap->top.x2; + + /* Calculate the number of rows to render */ + + y1 = trap->top.y; + y2 = trap->bot.y; + nrows = y2 - y1 + 1; + + /* Calculate the slope of the left and right side of the trapezoid */ + + if (nrows > 1) + { + dx1dy = b16divi((trap->bot.x1 - x1), nrows - 1); + dx2dy = b16divi((trap->bot.x2 - x2), nrows - 1); + } + else + { + /* The trapezoid is a run! Use the average width. */ + + x1 = (x1 + trap->bot.x1) >> 1; + x2 = (x2 + trap->bot.x2) >> 1; + dx1dy = 0; + dx2dy = 0; + } + + /* Perform vertical clipping */ + + if (y1 < bounds->pt1.y) + { + /* Is the entire trapezoid "above" the clipping window? */ + + if (y2 < bounds->pt1.y) + { + /* Yes.. then do nothing */ + + return; + } + + /* Calculate the x values for the new top run */ + + int dy = bounds->pt1.y - y1; + x1 += dy * dx1dy; + x2 += dy * dx2dy; + + /* Clip and re-calculate the number of rows to render */ + + y1 = bounds->pt1.y; + nrows = y2 - y1 + 1; + } + + if (y2 > bounds->pt2.y) + { + /* Is the entire trapezoid "below" the clipping window? */ + + if (y1 > bounds->pt2.y) + { + /* Yes.. then do nothing */ + + return; + } + + /* Clip and re-calculate the number of rows to render */ + + y2 = bounds->pt2.y; + nrows = y2 - y1 + 1; + } + + /* Get the address of the first byte on the first line */ + + line = pinfo->fbmem + y1 * stride ; + + /* Then fill the trapezoid line-by-line */ + + while (nrows--) + { + int ix1; + int ix2; + + /* Handle the special case where the sides cross (as in an hourglass) */ + + if (x1 > x2) + { + b16_t tmp; + ngl_swap(x1, x2, tmp); + ngl_swap(dx1dy, dx2dy, tmp); + } + + /* Convert the positions to integer */ + + ix1 = b16toi(x1); + ix2 = b16toi(x2); + + /* Handle some corner cases where we draw nothing. Otherwise, we will + * always draw at least one pixel. + */ + + if (x1 <= x2 && ix2 >= bounds->pt1.x && ix1 <= bounds->pt2.x) + { + /* Get a clipped copies of the starting and ending X positions. This + * clipped truncates "down" and gives the quantized pixel holding the + * fractional X position + */ + + ix1 = ngl_clipl(ix1, bounds->pt1.x); + ix2 = ngl_clipr(ix2, bounds->pt2.x); + + /* Get the run length for the clipped row */ + + width = ix2 - ix1 + 1; + +#if NXGLIB_BITSPERPIXEL < 8 + /* Handle masking of the fractional initial byte */ + +#ifdef CONFIG_NX_PACKEDMSFIRST + mask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(ix1)); +#else + mask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(ix1))); +#endif + dest = line; + lnlen = width; + + if (lnlen > 1 && mask) + { + dest[0] = (dest[0] & ~mask) | (mpixel & mask); + mask = 0xff; + dest++; + lnlen--; + } + + /* Handle masking of the fractional final byte */ + +#ifdef CONFIG_NX_PACKEDMSFIRST + mask &= (uint8_t)(0xff << (8 - NXGL_REMAINDERX(ix2))); +#else + mask &= (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(ix2))); +#endif + if (lnlen > 0 && mask) + { + dest[lnlen-1] = (dest[lnlen-1] & ~mask) | (mpixel & mask); + lnlen--; + } + + /* Handle all of the unmasked bytes in-between */ + + if (lnlen > 0) + { + NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, lnlen); + } + +#else + /* Then draw the run from (line + ix1) to (line + ix2) */ + + dest = line + NXGL_SCALEX(ix1); + NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, width); +#endif + } + + /* Move to the start of the next line */ + + line += stride; + + /* Add the dx/dy value to get the run positions on the next row */ + + x1 += dx1dy; + x2 += dx2dy; + } +} diff --git a/nuttx/graphics/nxglib/fb/nxglib_getrectangle.c b/nuttx/graphics/nxglib/fb/nxglib_getrectangle.c new file mode 100644 index 0000000000..82e541ec54 --- /dev/null +++ b/nuttx/graphics/nxglib/fb/nxglib_getrectangle.c @@ -0,0 +1,201 @@ +/**************************************************************************** + * graphics/nxglib/fb/nxglib_getrectangle.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "nxglib_bitblit.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_lowresmemcpy + ****************************************************************************/ + +#if NXGLIB_BITSPERPIXEL < 8 +static inline void nxgl_lowresmemcpy(FAR uint8_t *dline, FAR const uint8_t *sline, + unsigned int width, + uint8_t leadmask, uint8_t tailmask) +{ + FAR const uint8_t *sptr; + FAR uint8_t *dptr; + uint8_t mask; + int lnlen; + + /* Handle masking of the fractional initial byte */ + + mask = leadmask; + sptr = sline; + dptr = dline; + lnlen = width; + + if (lnlen > 1 && mask) + { + dptr[0] = (dptr[0] & ~mask) | (sptr[0] & mask); + mask = 0xff; + dptr++; + sptr++; + lnlen--; + } + + /* Handle masking of the fractional final byte */ + + mask &= tailmask; + if (lnlen > 0 && mask) + { + dptr[lnlen-1] = (dptr[lnlen-1] & ~mask) | (sptr[lnlen-1] & mask); + lnlen--; + } + + /* Handle all of the unmasked bytes in-between */ + + if (lnlen > 0) + { + NXGL_MEMCPY(dptr, sptr, lnlen); + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_getrectangle_*bpp + * + * Descripton: + * Fetch a rectangular region from framebuffer memory. The source is + * expressed as a rectangle. + * + ****************************************************************************/ + +void NXGL_FUNCNAME(nxgl_getrectangle,NXGLIB_SUFFIX) +(FAR struct fb_planeinfo_s *pinfo, FAR const struct nxgl_rect_s *rect, + FAR void *dest, unsigned int deststride) +{ + FAR const uint8_t *sline; + FAR uint8_t *dline; + unsigned int width; + unsigned int fbstride; + unsigned int rows; + +#if NXGLIB_BITSPERPIXEL < 8 + uint8_t leadmask; + uint8_t tailmask; +#endif + + /* Get the width of the framebuffer in bytes */ + + fbstride = pinfo->stride; + + /* Get the dimensions of the rectange to copy: width in pixels, height + * in rows + */ + + width = rect->pt2.x - rect->pt1.x + 1; + rows = rect->pt2.y - rect->pt1.y + 1; + +#if NXGLIB_BITSPERPIXEL < 8 +# ifdef CONFIG_NX_PACKEDMSFIRST + + /* Get the mask for pixels that are ordered so that they pack from the + * MS byte down. + */ + + leadmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(rect->pt1.x))); + tailmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(rect->pt2.x-1))); +# else + /* Get the mask for pixels that are ordered so that they pack from the + * LS byte up. + */ + + leadmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(rect->pt1.x))); + tailmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(rect->pt1.x-1))); +# endif +#endif + + /* sline = address of the first pixel in the top row of the source in + * framebuffer memory + */ + + sline = pinfo->fbmem + rect->pt1.y * fbstride + NXGL_SCALEX(rect->pt1.x); + + /* dline = address of the first row pixel */ + + dline = (FAR uint8_t *)dest; + + /* Yes.. Copy the rectangle */ + + while (rows--) + { + /* Copy the row */ + +#if NXGLIB_BITSPERPIXEL < 8 + nxgl_lowresmemcpy(dline, sline, width, leadmask, tailmask); +#else + NXGL_MEMCPY(dline, sline, width); +#endif + /* Point to the next source/dest row below the current one */ + + dline += deststride; + sline += fbstride; + } +} diff --git a/nuttx/graphics/nxglib/fb/nxglib_moverectangle.c b/nuttx/graphics/nxglib/fb/nxglib_moverectangle.c new file mode 100644 index 0000000000..d8e52250ce --- /dev/null +++ b/nuttx/graphics/nxglib/fb/nxglib_moverectangle.c @@ -0,0 +1,252 @@ +/**************************************************************************** + * graphics/nxglib/fb/nxglib_moverectangle.c + * + * Copyright (C) 2008-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "nxglib_bitblit.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_lowresmemcpy + ****************************************************************************/ + +#if NXGLIB_BITSPERPIXEL < 8 +static inline void nxgl_lowresmemcpy(FAR uint8_t *dline, FAR const uint8_t *sline, + unsigned int width, + uint8_t leadmask, uint8_t tailmask) +{ + FAR const uint8_t *sptr; + FAR uint8_t *dptr; + uint8_t mask; + int lnlen; + + /* Handle masking of the fractional initial byte */ + + mask = leadmask; + sptr = sline; + dptr = dline; + lnlen = width; + + if (lnlen > 1 && mask) + { + dptr[0] = (dptr[0] & ~mask) | (sptr[0] & mask); + mask = 0xff; + dptr++; + sptr++; + lnlen--; + } + + /* Handle masking of the fractional final byte */ + + mask &= tailmask; + if (lnlen > 0 && mask) + { + dptr[lnlen-1] = (dptr[lnlen-1] & ~mask) | (sptr[lnlen-1] & mask); + lnlen--; + } + + /* Handle all of the unmasked bytes in-between */ + + if (lnlen > 0) + { + NXGL_MEMCPY(dptr, sptr, lnlen); + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_moverectangle_*bpp + * + * Descripton: + * Move a rectangular region from location to another in the + * framebuffer memory. The source is expressed as a rectangle; the + * destination position is expressed as a point corresponding to the + * translation of the upper, left-hand corner. + * + ****************************************************************************/ + +void NXGL_FUNCNAME(nxgl_moverectangle,NXGLIB_SUFFIX) +(FAR struct fb_planeinfo_s *pinfo, FAR const struct nxgl_rect_s *rect, + FAR struct nxgl_point_s *offset) +{ + FAR const uint8_t *sline; + FAR uint8_t *dline; + unsigned int width; + unsigned int stride; + unsigned int rows; + +#if NXGLIB_BITSPERPIXEL < 8 + uint8_t leadmask; + uint8_t tailmask; +#endif + + /* Get the width of the framebuffer in bytes */ + + stride = pinfo->stride; + + /* Get the dimensions of the rectange to fill: width in pixels, height + * in rows + */ + + width = rect->pt2.x - rect->pt1.x + 1; + rows = rect->pt2.y - rect->pt1.y + 1; + +#if NXGLIB_BITSPERPIXEL < 8 +# ifdef CONFIG_NX_PACKEDMSFIRST + + /* Get the mask for pixels that are ordered so that they pack from the + * MS byte down. + */ + + leadmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(rect->pt1.x))); + tailmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(rect->pt2.x-1))); +# else + /* Get the mask for pixels that are ordered so that they pack from the + * LS byte up. + */ + + leadmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(rect->pt1.x))); + tailmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(rect->pt1.x-1))); +# endif +#endif + + /* sline = address of the first pixel in the top row of the source in + * framebuffer memory + */ + + sline = pinfo->fbmem + rect->pt1.y * stride + NXGL_SCALEX(rect->pt1.x); + + /* dline = address of the first pixel in the top row of the destination + * in framebuffer memory. We get dline by subtract the offset from the + * source position. + */ + + dline = pinfo->fbmem + offset->y * stride + NXGL_SCALEX(offset->x); + + /* Case 1: Is the destination position above the displayed position? + * If the destination position is less then then the src address, then the + * destination is offset to a postion below (and or to the left) of the + * source in framebuffer memory. + */ + + if (offset->y < rect->pt1.y || + (offset->y < rect->pt1.y && offset->x <= rect->pt1.x)) + { + /* Yes.. Copy the rectangle from top down (i.e., adding the stride + * to move to the next, lower row) */ + + while (rows--) + { + /* Copy the row */ + +#if NXGLIB_BITSPERPIXEL < 8 + nxgl_lowresmemcpy(dline, sline, width, leadmask, tailmask); +#else + NXGL_MEMCPY(dline, sline, width); +#endif + /* Point to the next source/dest row below the current one */ + + dline += stride; + sline += stride; + } + } + + /* Case 2: No.. the destination position is above (or to the left of) + * the displayed source position + */ + + else + { + /* Adjust sline and dline to point to the bottom row (+1) of the + * source and destination rectangles in framebuffer memory. + */ + + unsigned int hoffset = rows * stride; + sline += hoffset; + dline += hoffset; + + /* Copy the rectangle from the bottom up (i.e., subtracting stride + * to re-position to the previous, higher row) + */ + + while (rows--) + { + /* Point to the next source/dest row above the current one */ + + dline -= stride; + sline -= stride; + + /* Copy the row */ + +#if NXGLIB_BITSPERPIXEL < 8 + nxgl_lowresmemcpy(dline, sline, width, leadmask, tailmask); +#else + NXGL_MEMCPY(dline, sline, width); +#endif + } + } +} diff --git a/nuttx/graphics/nxglib/fb/nxglib_setpixel.c b/nuttx/graphics/nxglib/fb/nxglib_setpixel.c new file mode 100644 index 0000000000..7079b7e573 --- /dev/null +++ b/nuttx/graphics/nxglib/fb/nxglib_setpixel.c @@ -0,0 +1,156 @@ +/**************************************************************************** + * graphics/nxglib/fb/nxglib_setpixel.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "nxglib_bitblit.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#ifndef NXGLIB_SUFFIX +# error "NXGLIB_SUFFIX must be defined before including this header file" +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_setpixel_*bpp + * + * Descripton: + * Draw a single pixel in frambuffer memory at the given position and with + * the given color. This is equivalent to nxgl_fillrectangle_*bpp() with + * a 1x1 rectangle but is more efficient. + * + ****************************************************************************/ + +void NXGL_FUNCNAME(nxgl_setpixel,NXGLIB_SUFFIX) + (FAR struct fb_planeinfo_s *pinfo, + FAR const struct nxgl_point_s *pos, + NXGL_PIXEL_T color) +{ + FAR uint8_t *dest; + +#if NXGLIB_BITSPERPIXEL < 8 + uint8_t shift; + uint8_t mask; +#else + FAR NXGL_PIXEL_T *pixel; +#endif + + /* Get the address of the first byte of the pixel to write */ + + dest = pinfo->fbmem + pos->y * pinfo->stride + NXGL_SCALEX(pos->x); + +#if NXGLIB_BITSPERPIXEL < 8 + + /* Shift the color into the proper position */ + +# ifdef CONFIG_NX_PACKEDMSFIRST + +#if NXGLIB_BITSPERPIXEL == 1 + shift = (7 - (pos->x & 7)); /* Shift is 0, 1, ... 7 */ + mask = (1 << shift); /* Mask is 0x01, 0x02, .. 0x80 */ + color <<= shift; /* Color is positioned under the mask */ +#elif NXGLIB_BITSPERPIXEL == 2 + shift = (6 - ((pos->x & 3) << 1)); /* Shift is 0, 2, 4, or 6 */ + mask = (3 << shift); /* Mask is 0x03, 0x0c, 0x30, or 0xc0 */ + color <<= shift; /* Color is positioned under the mask */ +#elif NXGLIB_BITSPERPIXEL == 4 + shift = (4 - ((pos->x & 1) << 2)); /* Shift is 0 or 4 */ + mask = (15 << shift); /* Mask is 0x0f or 0xf0 */ + color <<= shift; /* Color is positioned under the mask */ +#else +# error "Unsupport pixel depth" +#endif + +# else /* CONFIG_NX_PACKEDMSFIRST */ + +#if NXGLIB_BITSPERPIXEL == 1 + shift = (pos->x & 7); /* Shift is 0, 1, ... 7 */ + mask = (1 << shift); /* Mask is 0x01, 0x02, .. 0x80 */ + color <<= shift; /* Color is positioned under the mask */ +#elif NXGLIB_BITSPERPIXEL == 2 + shift = (pos->x & 3) << 1; /* Shift is 0, 2, 4, or 6 */ + mask = (3 << shift); /* Mask is 0x03, 0x0c, 0x30, or 0xc0 */ + color <<= shift; /* Color is positioned under the mask */ +#elif NXGLIB_BITSPERPIXEL == 4 + shift = (pos->x & 1) << 2; /* Shift is 0 or 4 */ + mask = (15 << shift); /* Mask is 0x0f or 0xf0 */ + color <<= shift; /* Color is positioned under the mask */ +#else +# error "Unsupport pixel depth" +#endif +#endif /* CONFIG_NX_PACKEDMSFIRST */ + + /* Handle masking of the fractional byte */ + + *dest = (*dest & ~mask) | (color & mask); +#else + + /* Write the pixel (proper alignment assumed) */ + + pixel = (FAR NXGL_PIXEL_T *)dest; + *pixel = color; +#endif +} diff --git a/nuttx/graphics/nxglib/lcd/nxglib_copyrectangle.c b/nuttx/graphics/nxglib/lcd/nxglib_copyrectangle.c new file mode 100644 index 0000000000..988b6cb944 --- /dev/null +++ b/nuttx/graphics/nxglib/lcd/nxglib_copyrectangle.c @@ -0,0 +1,141 @@ +/**************************************************************************** + * graphics/nxglib/lcd/nxsglib_copyrectangle.c + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "nxglib_bitblit.h" +#include "nxglib_copyrun.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_copyrectangle_*bpp + * + * Descripton: + * Copy a rectangular bitmap image into the specific position in the + * framebuffer memory. + * + ****************************************************************************/ + +void NXGL_FUNCNAME(nxgl_copyrectangle,NXGLIB_SUFFIX) +(FAR struct lcd_planeinfo_s *pinfo, FAR const struct nxgl_rect_s *dest, + FAR const void *src, FAR const struct nxgl_point_s *origin, + unsigned int srcstride) +{ + FAR const uint8_t *sline; + unsigned int ncols; + unsigned int row; + unsigned int xoffset; +#if NXGLIB_BITSPERPIXEL < 8 + unsigned int remainder; +#endif + + /* Get the dimensions of the rectange to fill: width in pixels, + * height in rows + */ + + ncols = dest->pt2.x - dest->pt1.x + 1; + + /* Set up to copy the image */ + + xoffset = dest->pt1.x - origin->x; + sline = (const uint8_t*)src + NXGL_SCALEX(xoffset) + (dest->pt1.y - origin->y) * srcstride; +#if NXGLIB_BITSPERPIXEL < 8 + remainder = NXGL_REMAINDERX(xoffset); +#endif + + /* Copy the image, one row at a time */ + + for (row = dest->pt1.y; row <= dest->pt2.y; row++) + { +#if NXGLIB_BITSPERPIXEL < 8 + /* if the source pixel is not aligned with a byte boundary, then we will + * need to copy the image data to the run buffer first. + */ + + if (remainder != 0) + { + NXGL_FUNCNAME(nxgl_copyrun,NXGLIB_SUFFIX)(sline, pinfo->buffer, remainder, ncols); + (void)pinfo->putrun(row, dest->pt1.x, pinfo->buffer, ncols); + } + else +#endif + { + /* The pixel data is byte aligned. Copy the image data directly from + * the image memory. + */ + + (void)pinfo->putrun(row, dest->pt1.x, sline, ncols); + } + + /* Then adjust the source pointer to refer to the next line in the source + * image. + */ + + sline += srcstride; + } +} diff --git a/nuttx/graphics/nxglib/lcd/nxglib_fillrectangle.c b/nuttx/graphics/nxglib/lcd/nxglib_fillrectangle.c new file mode 100644 index 0000000000..c1a30d66ff --- /dev/null +++ b/nuttx/graphics/nxglib/lcd/nxglib_fillrectangle.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * graphics/nxglib/lcd/nxglib_fillrectangle.c + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "nxglib_bitblit.h" +#include "nxglib_fillrun.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#ifndef NXGLIB_SUFFIX +# error "NXGLIB_SUFFIX must be defined before including this header file" +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_fillrectangle_*bpp + * + * Descripton: + * Fill a rectangle region in the LCD memory with a fixed color + * + ****************************************************************************/ + +void NXGL_FUNCNAME(nxgl_fillrectangle,NXGLIB_SUFFIX) + (FAR struct lcd_planeinfo_s *pinfo, + FAR const struct nxgl_rect_s *rect, + NXGL_PIXEL_T color) +{ + unsigned int ncols; + unsigned int row; + + /* Get the dimensions of the rectange to fill in pixels */ + + ncols = rect->pt2.x - rect->pt1.x + 1; + + /* Fill the run buffer with the selected color */ + + NXGL_FUNCNAME(nxgl_fillrun,NXGLIB_SUFFIX)((NXGLIB_RUNTYPE*)pinfo->buffer, color, ncols); + + /* Then fill the rectangle line-by-line */ + + for (row = rect->pt1.y; row <= rect->pt2.y; row++) + { + /* Draw the raster line at this row */ + + (void)pinfo->putrun(row, rect->pt1.x, pinfo->buffer, ncols); + } +} diff --git a/nuttx/graphics/nxglib/lcd/nxglib_filltrapezoid.c b/nuttx/graphics/nxglib/lcd/nxglib_filltrapezoid.c new file mode 100644 index 0000000000..3ba44b34a7 --- /dev/null +++ b/nuttx/graphics/nxglib/lcd/nxglib_filltrapezoid.c @@ -0,0 +1,259 @@ +/**************************************************************************** + * graphics/nxglib/lcd/nxglib_filltrapezoid.c + * + * Copyright (C) 2010-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "nxglib_bitblit.h" +#include "nxglib_fillrun.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#ifndef NXGLIB_SUFFIX +# error "NXGLIB_SUFFIX must be defined before including this header file" +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxglib_filltrapezoid_*bpp + * + * Descripton: + * Fill a trapezoidal region in the LCD memory with a fixed color. + * Clip the trapezoid to lie within a boundng box. This is useful for + * drawing complex shapes that can be broken into a set of trapezoids. + * + ****************************************************************************/ + +void NXGL_FUNCNAME(nxgl_filltrapezoid,NXGLIB_SUFFIX) + (FAR struct lcd_planeinfo_s *pinfo, + FAR const struct nxgl_trapezoid_s *trap, + FAR const struct nxgl_rect_s *bounds, + NXGL_PIXEL_T color) +{ + unsigned int ncols; + unsigned int topy; + unsigned int boty; + unsigned int row; + unsigned int botw; + b16_t topx1; + b16_t topx2; + b16_t botx1; + b16_t botx2; + b16_t dx1dy; + b16_t dx2dy; + int dy; + int ix1; + int ix2; + + /* Get the top run endpoints */ + + topx1 = trap->top.x1; + topx2 = trap->top.x2; + + /* Calculate the number of rows to render */ + + topy = trap->top.y; + boty = trap->bot.y; + + /* Get the bottom run endpoints */ + + botx1 = trap->bot.x1; + botx2 = trap->bot.x2; + + /* Calculate the slope of the left and right side of the trapezoid */ + + dy = boty - topy; + if (dy > 0) + { + dx1dy = b16divi((botx1 - topx1), dy); + dx2dy = b16divi((botx2 - topx2), dy); + } + else + { + /* The trapezoid is a run! Use the average width. */ + + topx1 = (topx1 + botx1) >> 1; + topx2 = (topx2 + botx2) >> 1; + botx1 = topx1; + botx2 = topx2; + dx1dy = 0; + dx2dy = 0; + } + + /* Perform vertical clipping */ + + if (topy < bounds->pt1.y) + { + /* Is the entire trapezoid "above" the clipping window? */ + + if (boty < bounds->pt1.y) + { + /* Yes.. then do nothing */ + + return; + } + + /* Calculate the x values for the new top run */ + + dy = bounds->pt1.y - topy; + topx1 += dy * dx1dy; + topx2 += dy * dx2dy; + + /* Clip the top row to render */ + + topy = bounds->pt1.y; + } + + if (boty > bounds->pt2.y) + { + /* Is the entire trapezoid "below" the clipping window? */ + + if (topy > bounds->pt2.y) + { + /* Yes.. then do nothing */ + + return; + } + + /* Calculate the x values for the new bottom run */ + + dy = boty - bounds->pt2.y; + botx1 -= dy * dx1dy; + botx2 -= dy * dx2dy; + + /* Clip the bottom row to render */ + + boty = bounds->pt2.y; + } + + /* Handle the special case where the sides cross (as in an hourglass) */ + + if (botx1 > botx2) + { + b16_t tmp; + ngl_swap(botx1, botx2, tmp); + } + + /* Fill the run buffer for the maximum run that we will need */ + + ix1 = b16toi(topx1); + ix1 = ngl_clipl(ix1, bounds->pt1.x); + ix2 = b16toi(topx2); + ix2 = ngl_clipr(ix2, bounds->pt2.x); + ncols = ix2 - ix1 + 1; + + ix1 = b16toi(botx1); + ix1 = ngl_clipl(ix1, bounds->pt1.x); + ix2 = b16toi(botx2); + ix2 = ngl_clipr(ix2, bounds->pt2.x); + botw = ix2 - ix1 + 1; + + if (ncols < botw) + { + ncols = botw; + } + + NXGL_FUNCNAME(nxgl_fillrun,NXGLIB_SUFFIX)((NXGLIB_RUNTYPE*)pinfo->buffer, color, ncols); + + /* Then fill the trapezoid row-by-row */ + + for (row = topy; row <= boty; row++) + { + /* Handle the special case where the sides cross (as in an hourglass) */ + + if (topx1 > topx2) + { + b16_t tmp; + ngl_swap(topx1, topx2, tmp); + ngl_swap(dx1dy, dx2dy, tmp); + } + + /* Convert the positions to integer and get the run width, clipping to + * fit within the bounding box. + */ + + ix1 = b16toi(topx1); + ix1 = ngl_clipl(ix1, bounds->pt1.x); + ix2 = b16toi(topx2); + ix2 = ngl_clipr(ix2, bounds->pt2.x); + + /* Handle some corner cases where we draw nothing. Otherwise, we will + * always draw at least one pixel. + */ + + if (ix1 <= ix2) + { + /* Then draw the run from ix1 to ix2 at row */ + + ncols = ix2 - ix1 + 1; + (void)pinfo->putrun(row, ix1, pinfo->buffer, ncols); + } + + /* Add the dx/dy value to get the run positions on the next row */ + + topx1 += dx1dy; + topx2 += dx2dy; + } +} diff --git a/nuttx/graphics/nxglib/lcd/nxglib_getrectangle.c b/nuttx/graphics/nxglib/lcd/nxglib_getrectangle.c new file mode 100644 index 0000000000..9318426ba1 --- /dev/null +++ b/nuttx/graphics/nxglib/lcd/nxglib_getrectangle.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * graphics/nxglib/lcd/nxglib_getrectangle.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "nxglib_bitblit.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_moverectangle_*bpp + * + * Descripton: + * Fetch a rectangular region from LCD GRAM memory. The source is + * expressed as a rectangle. + * + ****************************************************************************/ + +void NXGL_FUNCNAME(nxgl_getrectangle,NXGLIB_SUFFIX) +(FAR struct lcd_planeinfo_s *pinfo, FAR const struct nxgl_rect_s *rect, + FAR void *dest, unsigned int deststride) +{ + FAR uint8_t *dline; + unsigned int ncols; + unsigned int srcrow; + + /* Get the width of the rectange to move in pixels. */ + + ncols = rect->pt2.x - rect->pt1.x + 1; + + /* dline = address of the first row pixel */ + + dline = (FAR uint8_t *)dest; + + /* Copy the rectangle */ + + for (srcrow = rect->pt1.y; srcrow <= rect->pt2.y; srcrow++) + { + (void)pinfo->getrun(srcrow, rect->pt1.x, dline, ncols); + dline += deststride; + } +} diff --git a/nuttx/graphics/nxglib/lcd/nxglib_moverectangle.c b/nuttx/graphics/nxglib/lcd/nxglib_moverectangle.c new file mode 100644 index 0000000000..f82187ae3b --- /dev/null +++ b/nuttx/graphics/nxglib/lcd/nxglib_moverectangle.c @@ -0,0 +1,131 @@ +/**************************************************************************** + * graphics/nxglib/lcd/nxglib_moverectangle.c + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "nxglib_bitblit.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_moverectangle_*bpp + * + * Descripton: + * Move a rectangular region from location to another in the + * LCD memory. The source is expressed as a rectangle; the + * destination position is expressed as a point corresponding to the + * translation of the upper, left-hand corner. + * + ****************************************************************************/ + +void NXGL_FUNCNAME(nxgl_moverectangle,NXGLIB_SUFFIX) +(FAR struct lcd_planeinfo_s *pinfo, FAR const struct nxgl_rect_s *rect, + FAR struct nxgl_point_s *offset) +{ + unsigned int ncols; + unsigned int srcrow; + unsigned int destrow; + + /* Get the width of the rectange to move in pixels. */ + + ncols = rect->pt2.x - rect->pt1.x + 1; + + /* Case 1: The destination position (offset) is above the displayed + * position (rect) + */ + + if (offset->y < rect->pt1.y) + { + /* Copy the rectangle from top down */ + + for (srcrow = rect->pt1.y, destrow = offset->y; + srcrow <= rect->pt2.y; + srcrow++, destrow++) + { + (void)pinfo->getrun(srcrow, rect->pt1.x, pinfo->buffer, ncols); + (void)pinfo->putrun(destrow, offset->x, pinfo->buffer, ncols); + } + } + + /* Case 2: The destination position (offset) is below the displayed + * position (rect) + */ + + else + { + unsigned int dy = rect->pt2.y - rect->pt1.y; + + /* Copy the rectangle from the bottom up */ + + for (srcrow = rect->pt2.y, destrow = offset->y + dy; + srcrow >= rect->pt1.y; + srcrow--, destrow--) + { + (void)pinfo->getrun(srcrow, rect->pt1.x, pinfo->buffer, ncols); + (void)pinfo->putrun(destrow, offset->x, pinfo->buffer, ncols); + } + } +} diff --git a/nuttx/graphics/nxglib/lcd/nxglib_setpixel.c b/nuttx/graphics/nxglib/lcd/nxglib_setpixel.c new file mode 100644 index 0000000000..c5cff99a70 --- /dev/null +++ b/nuttx/graphics/nxglib/lcd/nxglib_setpixel.c @@ -0,0 +1,153 @@ +/**************************************************************************** + * graphics/nxglib/lcd/nxglib_setpixel.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "nxglib_bitblit.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#ifndef NXGLIB_SUFFIX +# error "NXGLIB_SUFFIX must be defined before including this header file" +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_setpixel_*bpp + * + * Descripton: + * Draw a single pixel in LCD memory at the given position and with the + * given color. This is equivalent to nxgl_fillrectangle_*bpp() with a 1x1 + * rectangle but is more efficient. + * + ****************************************************************************/ + +void NXGL_FUNCNAME(nxgl_setpixel,NXGLIB_SUFFIX) + (FAR struct lcd_planeinfo_s *pinfo, + FAR const struct nxgl_point_s *pos, + NXGL_PIXEL_T color) +{ +#if NXGLIB_BITSPERPIXEL < 8 + uint8_t shift; + uint8_t mask; + uint8_t pixel; + + /* Read the byte that contains the pixel to be changed */ + + (void)pinfo->getrun(pos->y, pos->x, &pixel, 8 / NXGLIB_BITSPERPIXEL); + + /* Shift the color into the proper position */ + +# ifdef CONFIG_NX_PACKEDMSFIRST + +#if NXGLIB_BITSPERPIXEL == 1 + shift = (7 - (pos->x & 7)); /* Shift is 0, 1, ... 7 */ + mask = (1 << shift); /* Mask is 0x01, 0x02, .. 0x80 */ + color <<= shift; /* Color is positioned under the mask */ +#elif NXGLIB_BITSPERPIXEL == 2 + shift = (6 - ((pos->x & 3) << 1)); /* Shift is 0, 2, 4, or 6 */ + mask = (3 << shift); /* Mask is 0x03, 0x0c, 0x30, or 0xc0 */ + color <<= shift; /* Color is positioned under the mask */ +#elif NXGLIB_BITSPERPIXEL == 4 + shift = (4 - ((pos->x & 1) << 2)); /* Shift is 0 or 4 */ + mask = (15 << shift); /* Mask is 0x0f or 0xf0 */ + color <<= shift; /* Color is positioned under the mask */ +#else +# error "Unsupport pixel depth" +#endif + +# else /* CONFIG_NX_PACKEDMSFIRST */ + +#if NXGLIB_BITSPERPIXEL == 1 + shift = (pos->x & 7); /* Shift is 0, 1, ... 7 */ + mask = (1 << shift); /* Mask is 0x01, 0x02, .. 0x80 */ + color <<= shift; /* Color is positioned under the mask */ +#elif NXGLIB_BITSPERPIXEL == 2 + shift = (pos->x & 3) << 1; /* Shift is 0, 2, 4, or 6 */ + mask = (3 << shift); /* Mask is 0x03, 0x0c, 0x30, or 0xc0 */ + color <<= shift; /* Color is positioned under the mask */ +#elif NXGLIB_BITSPERPIXEL == 4 + shift = (pos->x & 1) << 2; /* Shift is 0 or 4 */ + mask = (15 << shift); /* Mask is 0x0f or 0xf0 */ + color <<= shift; /* Color is positioned under the mask */ +#else +# error "Unsupport pixel depth" +#endif +#endif /* CONFIG_NX_PACKEDMSFIRST */ + + /* Handle masking of the fractional byte */ + + pixel = (pixel & ~mask) | (color & mask); + + /* Write the modified byte back to graphics memory */ + + (void)pinfo->putrun(pos->y, pos->x, (FAR uint8_t *)&pixel, 8 / NXGLIB_BITSPERPIXEL); +#else + /* Draw a single pixel at this position raster line at this row */ + + (void)pinfo->putrun(pos->y, pos->x, (FAR uint8_t *)&color, 1); +#endif +} diff --git a/nuttx/graphics/nxglib/nxglib_bitblit.h b/nuttx/graphics/nxglib/nxglib_bitblit.h new file mode 100644 index 0000000000..a737a06474 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_bitblit.h @@ -0,0 +1,208 @@ +/**************************************************************************** + * graphics/nxglib/nxglib_bitblit.h + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXGLIB_NXGLIB_BITBLIT_H +#define __GRAPHICS_NXGLIB_NXGLIB_BITBLIT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Make sure the bits-per-pixel value has been set by the includer of + * this header file. + */ + +#ifndef NXGLIB_BITSPERPIXEL +# error "NXGLIB_BITSPERPIXEL must be defined before including this header file" +#endif + +/* Set up bit blit macros for this BPP */ + +#if NXGLIB_BITSPERPIXEL == 1 + +# define NXGL_PIXELSHIFT 3 +# define NXGL_PIXELMASK 7 +# define NXGL_MULTIPIXEL(p) ((p) ? 0xff : 0x00) +# define NXGL_PIXEL_T uint8_t + +#elif NXGLIB_BITSPERPIXEL == 2 + +# define NXGL_PIXELSHIFT 2 +# define NXGL_PIXELMASK 3 +# define NXGL_MULTIPIXEL(p) ((uint8_t)(p) << 6 | (uint8_t)(p) << 4 | (uint8_t)(p) << 2 | (p)) +# define NXGL_PIXEL_T uint8_t + +#elif NXGLIB_BITSPERPIXEL == 4 + +# define NXGL_PIXELSHIFT 1 +# define NXGL_PIXELMASK 1 +# define NXGL_MULTIPIXEL(p) ((uint8_t)(p) << 4 | (p)) +# define NXGL_PIXEL_T uint8_t + +#elif NXGLIB_BITSPERPIXEL == 8 + +# define NXGL_SCALEX(x) (x) +# define NXGL_PIXEL_T uint8_t + +#elif NXGLIB_BITSPERPIXEL == 16 + +# define NXGL_SCALEX(x) ((x) << 1) +# define NXGL_PIXEL_T uint16_t + +#elif NXGLIB_BITSPERPIXEL == 24 + +# define NXGL_SCALEX(x) (((x) << 1) + (x)) +# define NXGL_PIXEL_T uint32_t + +#elif NXGLIB_BITSPERPIXEL == 32 + +# define NXGL_SCALEX(x) ((x) << 2) +# define NXGL_PIXEL_T uint32_t + +#endif + +#if NXGLIB_BITSPERPIXEL < 8 +# define NXGL_SCALEX(x) ((x) >> NXGL_PIXELSHIFT) +# define NXGL_REMAINDERX(x) ((x) & NXGL_PIXELMASK) +# define NXGL_ALIGNDOWN(x) ((x) & ~NXGL_PIXELMASK) +# define NXGL_ALIGNUP(x) (((x) + NXGL_PIXELMASK) & ~NXGL_PIXELMASK) + +# define NXGL_MEMSET(dest,value,width) \ + { \ + FAR uint8_t *_ptr = (FAR uint8_t*)(dest); \ + int _nby = NXGL_SCALEX(width); \ + while (_nby--) \ + { \ + *_ptr++ = (value); \ + } \ + } +# define NXGL_MEMCPY(dest,src,width) \ + { \ + FAR uint8_t *_dptr = (FAR uint8_t*)(dest); \ + FAR uint8_t *_sptr = (FAR uint8_t*)(src); \ + int _nby = NXGL_SCALEX(width); \ + while (_nby--) \ + { \ + *_dptr++ = *_sptr++; \ + } \ + } + +#elif NXGLIB_BITSPERPIXEL == 24 +# define NXGL_MEMSET(dest,value,width) \ + { \ + FAR uint8_t *_ptr = (FAR uint8_t*)(dest); \ + nxgl_coord_t _npix = (width); \ + while (_npix--) \ + { \ + *_ptr++ = (value); \ + *_ptr++ = (value) >> 8; \ + *_ptr++ = (value) >> 16; \ + } \ + } +# define NXGL_MEMCPY(dest,src,width) \ + { \ + FAR uint8_t *_dptr = (FAR uint8_t*)(dest); \ + FAR uint8_t *_sptr = (FAR uint8_t*)(src); \ + nxgl_coord_t _npix = (width); \ + while (_npix--) \ + { \ + *_dptr++ = *_sptr++; \ + *_dptr++ = *_sptr++; \ + *_dptr++ = *_sptr++; \ + } \ + } +#else +# define NXGL_MEMSET(dest,value,width) \ + { \ + FAR NXGL_PIXEL_T *_ptr = (FAR NXGL_PIXEL_T*)(dest); \ + nxgl_coord_t _npix = (width); \ + while (_npix--) \ + { \ + *_ptr++ = (value); \ + } \ + } +# define NXGL_MEMCPY(dest,src,width) \ + { \ + FAR NXGL_PIXEL_T *_dptr = (FAR NXGL_PIXEL_T*)(dest); \ + FAR NXGL_PIXEL_T *_sptr = (FAR NXGL_PIXEL_T*)(src); \ + nxgl_coord_t _npix = (width); \ + while (_npix--) \ + { \ + *_dptr++ = *_sptr++; \ + } \ + } +#endif + +/* Form a function name by concatenating two strings */ + +#define _NXGL_FUNCNAME(a,b) a ## b +#define NXGL_FUNCNAME(a,b) _NXGL_FUNCNAME(a,b) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXGLIB_NXGLIB_BITBLIT_H */ diff --git a/nuttx/graphics/nxglib/nxglib_circlepts.c b/nuttx/graphics/nxglib/nxglib_circlepts.c new file mode 100644 index 0000000000..a6d59280d7 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_circlepts.c @@ -0,0 +1,171 @@ +/**************************************************************************** + * graphics/nxglib/nxglib_circlepts.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Trigonometry */ + +#define SIN_0p0 0 /* sin(0) = 0 */ +#define COS_0p0 1 /* cos(0) = 1 */ +#define SIN_22p5 25080 /* sin(22.5) = 25080 / 65536 */ +#define COS_22p5 60547 /* cos(22.5) = 60547 / 65536 */ +#define SIN_45p0 46341 /* sin(45) = 46341 / 65536 */ +#define COS_45p0 SIN_45p0 /* cos(45) = sin(45) */ + +/* Named indices into the 16 circle points generated by nxgl_circlepts */ + +#define POINT_0p0 0 +#define POINT_22p5 1 +#define POINT_45p0 2 +#define POINT_67p5 3 +#define POINT_90p0 4 +#define POINT_112p5 5 +#define POINT_135p0 6 +#define POINT_157p5 7 +#define POINT_180p0 8 +#define POINT_202p5 9 +#define POINT_225p0 10 +#define POINT_247p5 11 +#define POINT_270p0 12 +#define POINT_292p5 13 +#define POINT_315p0 14 +#define POINT_337p5 15 +#define NCIRCLE_POINTS 16 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_circlepts + * + * Description: + * Given a description of a circle, return a set of 16 points on the + * circumference of the circle. These points may then be used by + * nx_drawcircle() or related APIs to draw a circle outline. + * + * Input parameters: + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * circle - A pointer the first entry in an array of 16 points where the + * circle points will be returned. + * + * Returned value: + * None + * + ****************************************************************************/ + +void nxgl_circlepts(FAR const struct nxgl_point_s *center, nxgl_coord_t radius, + FAR struct nxgl_point_s *circle) +{ + nxgl_coord_t xoffs; + nxgl_coord_t yoffs; + + /* 0, 90, 180, and 270 degrees are the easiest */ + + circle[POINT_0p0].x = center->x + radius; + circle[POINT_0p0].y = center->y; + circle[POINT_90p0].x = center->x; + circle[POINT_90p0].y = center->y + radius; + circle[POINT_180p0].x = center->x - radius; + circle[POINT_180p0].y = center->y; + circle[POINT_270p0].x = center->x; + circle[POINT_270p0].y = center->y - radius; + + /* Now 22.5, 67.5, 112.5, 157.5, 202.5, 247.5, 292.5, and 337.5 */ + + xoffs = b16toi(b16muli(COS_22p5, radius) + b16HALF); + yoffs = b16toi(b16muli(SIN_22p5, radius) + b16HALF); + + circle[POINT_22p5].x = center->x + xoffs; + circle[POINT_22p5].y = center->y + yoffs; + circle[POINT_157p5].x = center->x - xoffs; + circle[POINT_157p5].y = center->y + yoffs; + circle[POINT_202p5].x = center->x - xoffs; + circle[POINT_202p5].y = center->y - yoffs; + circle[POINT_337p5].x = center->x + xoffs; + circle[POINT_337p5].y = center->y - yoffs; + + circle[POINT_67p5].x = center->x + yoffs; + circle[POINT_67p5].y = center->y + xoffs; + circle[POINT_112p5].x = center->x - yoffs; + circle[POINT_112p5].y = center->y + xoffs; + circle[POINT_247p5].x = center->x - yoffs; + circle[POINT_247p5].y = center->y - xoffs; + circle[POINT_292p5].x = center->x + yoffs; + circle[POINT_292p5].y = center->y - xoffs; + + /* Finally, 45.0, 135.0, 225.0, 315.0 */ + + xoffs = b16toi(b16muli(COS_45p0, radius) + b16HALF); + + circle[POINT_45p0].x = center->x + xoffs; + circle[POINT_45p0].y = center->y + xoffs; + circle[POINT_135p0].x = center->x - xoffs; + circle[POINT_135p0].y = center->y + xoffs; + circle[POINT_225p0].x = center->x - xoffs; + circle[POINT_225p0].y = center->y - xoffs; + circle[POINT_315p0].x = center->x + xoffs; + circle[POINT_315p0].y = center->y - xoffs; +} diff --git a/nuttx/graphics/nxglib/nxglib_circletraps.c b/nuttx/graphics/nxglib/nxglib_circletraps.c new file mode 100644 index 0000000000..7c2cd1d7b5 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_circletraps.c @@ -0,0 +1,176 @@ +/**************************************************************************** + * graphics/nxglib/nxglib_circletraps.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Trigonometry */ + +#define SIN_0p0 0 /* sin(0) = 0 */ +#define COS_0p0 1 /* cos(0) = 1 */ +#define SIN_22p5 25080 /* sin(22.5) = 25080 / 65536 */ +#define COS_22p5 60547 /* cos(22.5) = 60547 / 65536 */ +#define SIN_45p0 46341 /* sin(45) = 46341 / 65536 */ +#define COS_45p0 SIN_45p0 /* cos(45) = sin(45) */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_circletraps + * + * Description: + * Given a description of a a circle, return 8 trapezoids that can be + * used to fill the circle by nx_fillcircle() and other interfaces. + * + * Input parameters: + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * circle - A pointer the first entry in an array of 8 trapezoids where + * the circle description will be returned. + * + * Returned value: + * None + * + ****************************************************************************/ + +void nxgl_circletraps(FAR const struct nxgl_point_s *center, nxgl_coord_t radius, + FAR struct nxgl_trapezoid_s *circle) +{ + nxgl_coord_t xoffs; + nxgl_coord_t yoffs; + + circle[0].top.x1 = itob16(center->x); + circle[0].top.x2 = circle[0].top.x1; + circle[0].top.y = center->y - radius; + + circle[7].bot.x1 = circle[0].top.x1; + circle[7].bot.x2 = circle[0].top.x1; + circle[7].bot.y = center->y + radius; + + circle[3].bot.x1 = itob16(center->x - radius); + circle[3].bot.x2 = itob16(center->x + radius); + circle[3].bot.y = center->y; + + circle[4].top.x1 = circle[3].bot.x1; + circle[4].top.x2 = circle[3].bot.x2; + circle[4].top.y = circle[3].bot.y; + + /* Now 22.5, 67.5, 112.5, 157.5, 202.5, 247.5, 292.5, and 337.5 */ + + xoffs = b16toi(b16muli(COS_22p5, radius) + b16HALF); + yoffs = b16toi(b16muli(SIN_22p5, radius) + b16HALF); + + circle[2].bot.x1 = itob16(center->x - xoffs); + circle[2].bot.x2 = itob16(center->x + xoffs); + circle[2].bot.y = center->y - yoffs; + + circle[3].top.x1 = circle[2].bot.x1; + circle[3].top.x2 = circle[2].bot.x2; + circle[3].top.y = circle[2].bot.y; + + circle[4].bot.x1 = circle[2].bot.x1; + circle[4].bot.x2 = circle[2].bot.x2; + circle[4].bot.y = center->y + yoffs; + + circle[5].top.x1 = circle[4].bot.x1; + circle[5].top.x2 = circle[4].bot.x2; + circle[5].top.y = circle[4].bot.y; + + circle[0].bot.x1 = itob16(center->x - yoffs); + circle[0].bot.x2 = itob16(center->x + yoffs); + circle[0].bot.y = center->y - xoffs; + + circle[1].top.x1 = circle[0].bot.x1; + circle[1].top.x2 = circle[0].bot.x2; + circle[1].top.y = circle[0].bot.y; + + circle[6].bot.x1 = circle[1].top.x1; + circle[6].bot.x2 = circle[1].top.x2; + circle[6].bot.y = center->y + xoffs; + + circle[7].top.x1 = circle[6].bot.x1; + circle[7].top.x2 = circle[6].bot.x2; + circle[7].top.y = circle[6].bot.y; + + /* Finally, 45.0, 135.0, 225.0, 315.0 */ + + xoffs = b16toi(b16muli(COS_45p0, radius) + b16HALF); + + circle[1].bot.x1 = itob16(center->x - xoffs); + circle[1].bot.x2 = itob16(center->x + xoffs); + circle[1].bot.y = center->y - xoffs; + + circle[2].top.x1 = circle[1].bot.x1; + circle[2].top.x2 = circle[1].bot.x2; + circle[2].top.y = circle[1].bot.y; + + circle[5].bot.x1 = circle[1].bot.x1; + circle[5].bot.x2 = circle[1].bot.x2; + circle[5].bot.y = center->y + xoffs; + + circle[6].top.x1 = circle[5].bot.x1; + circle[6].top.x2 = circle[5].bot.x2; + circle[6].top.y = circle[5].bot.y; +} diff --git a/nuttx/graphics/nxglib/nxglib_colorcopy.c b/nuttx/graphics/nxglib/nxglib_colorcopy.c new file mode 100644 index 0000000000..f99b995050 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_colorcopy.c @@ -0,0 +1,87 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_colorcopy.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_colorcopy + * + * Description: + * This is essentially memcpy for colors. This does very little for us + * other than hide all of the conditional compilation for planar colors + * in one place. + * + ****************************************************************************/ + +void nxgl_colorcopy(nxgl_mxpixel_t dest[CONFIG_NX_NPLANES], + const nxgl_mxpixel_t src[CONFIG_NX_NPLANES]) +{ + int i; + + for (i = 0; i < CONFIG_NX_NPLANES; i++) + { + dest[i] = src[i]; + } +} diff --git a/nuttx/graphics/nxglib/nxglib_copyrun.h b/nuttx/graphics/nxglib/nxglib_copyrun.h new file mode 100644 index 0000000000..b97372bf77 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_copyrun.h @@ -0,0 +1,346 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_copyrun.h + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXGLIB_NXGLIB_COPYRUN_H +#define __GRAPHICS_NXGLIB_NXGLIB_COPYRUN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_copyrun_*bpp + * + * Description: + * Copy a row from an image into run. + * + ****************************************************************************/ + +#if NXGLIB_BITSPERPIXEL == 1 +static inline void +nxgl_copyrun_1bpp(FAR const uint8_t *src, FAR uint8_t *dest, + unsigned int remainder, size_t npixels) +{ + uint8_t indata; + uint8_t outdata; + uint8_t nextdata; + unsigned int outpixels = 0; + + DEBUGASSERT(remainder > 0 && remainder < 8); + + /* Take only the first 8-remainder pixels from the first byte. + * remainder is number between 1 and 7 (not zero!) that represents + * the alignment of the pixel bits in the source. + */ + + indata = *src++; + +#ifdef CONFIG_NX_PACKEDMSFIRST + /* If CONFIG_NX_PACKEDMSFIRST is defined, then bits 0-(remainder-1) + * are carried over to the first pass through the loop. For + * example if remainder == 2: + * + * indata: xxAA AAAA maps to nextdata: AAAA AAxx + */ + + nextdata = (indata << remainder); + +#else + /* If CONFIG_NX_PACKEDMSFIRST is NOT defined, then bits (7-remainder)-7 + * are carried over to the first pass through the loop. For example + * if remainder == 2: + * + * indata: AAAA AAxx maps to nextdata: xxAA AAAA + */ + + nextdata = (indata >> remainder); + +#endif + + /* Loop until all pixels have been packed into the destination. Note: + * a outpixels increments by 8 so a few extra pixels will be packed on + * the output. This should not be an issue. + */ + + while (outpixels < npixels) + { + /* Get the next byte from the source */ + + indata = *src++; + outdata = nextdata; + + /* remainder is number between 1 and 7 (not zero!) that represents + * the alignment of the pixel bits in the source. + */ + +#ifdef CONFIG_NX_PACKEDMSFIRST + /* If CONFIG_NX_PACKEDMSFIRST is defined, then bits (7-remainder)-7 + * are carried over from that last pass through the loop. For + * example if remainder == 2: + * + * nextdata = AAAA AAxx - dest = AAAA AABB + * src = BBCC CCCC - nextdata = CCCC CCxx + */ + + outdata |= (indata >> (8 - remainder)); + nextdata = (indata << remainder); +#else + /* If CONFIG_NX_PACKEDMSFIRST is NOT defined, then bits 0-(remainder-1) + * are carried over from that last pass through the loop . For + * example if remainder == 2: + * + * nextdata = xxAA AAAA - dest = BBAA AAAA + * src = CCCC CCBB - nextdata = xxCC CCCC + */ + + outdata |= (indata << (8 - remainder)); + nextdata = (indata >> remainder); +#endif + + /* Transfer the byte to the run buffer */ + + *dest++ = outdata; + outpixels += 8; + } +} + +#elif NXGLIB_BITSPERPIXEL == 2 +static inline void +nxgl_copyrun_2bpp(FAR const uint8_t *src, FAR uint8_t *dest, + unsigned int remainder, size_t npixels) +{ + uint8_t indata; + uint8_t outdata; + uint8_t nextdata; + unsigned int outpixels = 0; + unsigned int shift; + + DEBUGASSERT(remainder > 0 && remainder < 4); + + /* Take only the first 8-(2*remainder) pixels from the first byte. + * remainder is number between 1 and 3 (not zero!) that represents + * the alignment of the pixel bits in the source. + */ + + indata = *src++; + shift = (remainder << 1); + +#ifdef CONFIG_NX_PACKEDMSFIRST + /* If CONFIG_NX_PACKEDMSFIRST is defined, then bits 0-(2*remainder-1) + * are carried over to the first pass through the loop. For + * example if remainder == 1: + * + * indata: xxAA AAAA maps to nextdata: AAAA AAxx + */ + + nextdata = (indata << shift); + +#else + /* If CONFIG_NX_PACKEDMSFIRST is NOT defined, then bits (7-2*remainder)-7 + * are carried over to the first pass through the loop. For example + * if remainder == 1: + * + * indata: AAAA AAxx maps to nextdata: xxAA AAAA + */ + + nextdata = (indata >> shift); + +#endif + + /* Loop until all pixels have been packed into the destination. Note: + * a outpixels increments by 8 so a few extra pixels will be packed on + * the output. This should not be an issue. + */ + + while (outpixels < npixels) + { + /* Get the next byte from the source */ + + indata = *src++; + outdata = nextdata; + + /* remainder is number between 1 and 3 (not zero!) that represents + * the alignment of the pixel bits in the source. + */ + +#ifdef CONFIG_NX_PACKEDMSFIRST + /* If CONFIG_NX_PACKEDMSFIRST is defined, then bits (7-2*remainder)-7 + * are carried over from that last pass through the loop. For example + * if remainder == 1: + * + * nextdata = AAAA AAxx - dest = AAAA AABB + * src = BBCC CCCC - nextdata = CCCC CCxx + */ + + outdata |= (indata >> (8 - shift)); + nextdata = (indata << shift); +#else + /* If CONFIG_NX_PACKEDMSFIRST is NOT defined, then bits 0-(2*remainder-1) + * are carried over from that last pass through the loop. For example + * if remainder == 1: + * + * nextdata = xxAA AAAA - dest = BBAA AAAA + * src = CCCC CCBB - nextdata = xxCC CCCC + */ + + outdata |= (indata << (8 - shift)); + nextdata = (indata >> shift); +#endif + + /* Transfer the byte to the run buffer */ + + *dest++ = outdata; + outpixels += 4; + } +} + +#elif NXGLIB_BITSPERPIXEL == 4 +static inline void +nxgl_copyrun_4bpp(FAR const uint8_t *src, FAR uint8_t *dest, + unsigned int remainder, size_t npixels) +{ + uint8_t indata; + uint8_t outdata; + uint8_t nextdata; + unsigned int outpixels = 0; + + DEBUGASSERT(remainder == 1); + + /* Take only the first 8-remainder pixels from the first byte. + * remainder is number between 1 and 3 (not zero!) that represents + * the alignment of the pixel bits in the source. + */ + + indata = *src++; + +#ifdef CONFIG_NX_PACKEDMSFIRST + /* If CONFIG_NX_PACKEDMSFIRST is defined, then bits 0-3 + * are carried over to the first pass through the loop. For + * example: + * + * indata: xxxx AAAA maps to nextdata: AAAA xxxx + */ + + nextdata = (indata << 4); + +#else + /* If CONFIG_NX_PACKEDMSFIRST is NOT defined, then bits 4-7 + * are carried over to the first pass through the loop. For example: + * + * indata: AAAA xxxx maps to nextdata: xxxx AAAA + */ + + nextdata = (indata >> 4); + +#endif + + /* Loop until all pixels have been packed into the destination. Note: + * a outpixels increments by 8 so a few extra pixels will be packed on + * the output. This should not be an issue. + */ + + while (outpixels < npixels) + { + /* Get the next byte from the source */ + + indata = *src++; + outdata = nextdata; + + /* remainder is number between 1 and 3 (not zero!) that represents + * the alignment of the pixel bits in the source. + */ + +#ifdef CONFIG_NX_PACKEDMSFIRST + /* If CONFIG_NX_PACKEDMSFIRST is defined, then bits 4-7 + * are carried over from that last pass through the loop (or are + * ignored initially. For example if remainder == 1: + * + * nextdata = AAAA xxxx - dest = AAAA BBBB + * src = BBBB CCCC - nextdata = CCCC xxxx + */ + + outdata |= (indata >> 4); + nextdata = (indata << 4); +#else + /* If CONFIG_NX_PACKEDMSFIRST is NOT defined, then bits 0-(remainder-1) + * are carried over from that last pass through the loop (or are + * ignored initially). For example if remainder == 2: + * + * nextdata = xxAA AAAA - dest = BBAA AAAA + * src = CCCC CCBB - nextdata = xxCC CCCC + */ + + outdata |= (indata << 4); + nextdata = (indata >> 4); +#endif + + /* Transfer the byte to the run buffer */ + + *dest++ = outdata; + outpixels += 2; + } +} +#endif +#endif /* __GRAPHICS_NXGLIB_NXGLIB_COPYRUN_H */ + + diff --git a/nuttx/graphics/nxglib/nxglib_fillrun.h b/nuttx/graphics/nxglib/nxglib_fillrun.h new file mode 100644 index 0000000000..b1d8a3a7fb --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_fillrun.h @@ -0,0 +1,196 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_fullrun.h + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXGLIB_NXGLIB_FILLRUN_H +#define __GRAPHICS_NXGLIB_NXGLIB_FILLRUN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#if NXGLIB_BITSPERPIXEL < 16 +# define NXGLIB_RUNTYPE uint8_t +#elif NXGLIB_BITSPERPIXEL == 16 +# define NXGLIB_RUNTYPE uint16_t +#else +# define NXGLIB_RUNTYPE uint32_t +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if NXGLIB_BITSPERPIXEL == 2 +static uint8_t g_wide_2bpp[4] = { 0x00, 0x55, 0xaa, 0xff }; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_fillrun_*bpp + * + * Description: + * fill a run with the specified color. + * + ****************************************************************************/ + +#if NXGLIB_BITSPERPIXEL == 1 +static inline void nxgl_fillrun_1bpp(FAR uint8_t *run, nxgl_mxpixel_t color, + size_t npixels) +{ + /* Get the number of bytes to fill */ + + unsigned int nbytes = (npixels + 7) >> 3; + + /* Get the value of the byte to fill */ + + uint8_t wide = (color & 1) != 0 ? 0xff : 0x00; + + /* Fill the run with the color (it is okay to run a fractional byte over + * the end) + */ + + memset(run, wide, nbytes); +} + +#elif NXGLIB_BITSPERPIXEL == 2 +static inline void nxgl_fillrun_2bpp(FAR uint8_t *run, nxgl_mxpixel_t color, + size_t npixels) +{ + /* Get the number of bytes to fill */ + + unsigned int nbytes = (npixels + 3) >> 2; + + /* Get the value of the byte to fill */ + + uint8_t wide = g_wide_2bpp[color & 3]; + + /* Fill the run with the color (it is okay to run a fractional byte over + * the end) + */ + + memset(run, wide, nbytes); +} + +#elif NXGLIB_BITSPERPIXEL == 4 +static inline void nxgl_fillrun_4bpp(FAR uint8_t *run, nxgl_mxpixel_t color, + size_t npixels) +{ + /* Get the number of bytes to fill */ + + unsigned int nbytes = (npixels + 1) >> 1; + + /* Get the value of the byte to fill */ + + uint8_t narrow = (uint8_t)color & 0x0f; + uint8_t wide = narrow | (narrow << 4); + + /* Fill the run with the color (it is okay to run a fractional byte over + * the end) + */ + + memset(run, wide, nbytes); +} + +#elif NXGLIB_BITSPERPIXEL == 8 +static inline void nxgl_fillrun_8bpp(FAR uint8_t *run, nxgl_mxpixel_t color, + size_t npixels) +{ + /* Fill the run with the color (it is okay to run a fractional byte overy the end */ + + memset(run, color, npixels); +} + +#elif NXGLIB_BITSPERPIXEL == 16 +static inline void nxgl_fillrun_16bpp(FAR uint16_t *run, nxgl_mxpixel_t color, + size_t npixels) +{ + /* Fill the run with the color (it is okay to run a fractional byte overy the end */ + + while (npixels-- > 0) + { + *run++ = (uint16_t)color; + } +} + +#elif NXGLIB_BITSPERPIXEL == 24 +static inline void nxgl_fillrun_24bpp(FAR uint32_t *run, nxgl_mxpixel_t color, size_t npixels) +{ + /* Fill the run with the color (it is okay to run a fractional byte overy the end */ +#warning "Assuming 24-bit color is not packed" + while (npixels-- > 0) + { + *run++ = (uint32_t)color; + } +} + +#elif NXGLIB_BITSPERPIXEL == 32 +static inline void nxgl_fillrun_32bpp(FAR uint32_t *run, nxgl_mxpixel_t color, size_t npixels) +{ + /* Fill the run with the color (it is okay to run a fractional byte overy the end */ + + while (npixels-- > 0) + { + *run++ = (uint32_t)color; + } +} +#else +# error "Unsupported value of NXGLIB_BITSPERPIXEL" +#endif +#endif /* __GRAPHICS_NXGLIB_NXGLIB_FILLRUN_H */ + + diff --git a/nuttx/graphics/nxglib/nxglib_intersecting.c b/nuttx/graphics/nxglib/nxglib_intersecting.c new file mode 100644 index 0000000000..c495a9e3d9 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_intersecting.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_intersecting.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_intersecting + * + * Description: + * Return true if the rectangles intersect. + * + ****************************************************************************/ + +bool nxgl_intersecting(FAR const struct nxgl_rect_s *rect1, + FAR const struct nxgl_rect_s *rect2) +{ + return ((rect1->pt2.x > rect2->pt1.x) && (rect1->pt2.y > rect2->pt1.y) && + (rect1->pt1.x < rect2->pt2.x) && (rect1->pt1.y < rect2->pt1.y)); +} diff --git a/nuttx/graphics/nxglib/nxglib_nonintersecting.c b/nuttx/graphics/nxglib/nxglib_nonintersecting.c new file mode 100644 index 0000000000..9cb2ec29c5 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_nonintersecting.c @@ -0,0 +1,151 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_rectnonintersecting.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_nonintersecting + * + * Description: + * Return the regions of rectangle rect 1 that do not intersect with + * rect2. This may be up to founr rectangles some of which may be + * degenerate (and can be picked off with nxgl_nullrect) + * + ****************************************************************************/ + +void nxgl_nonintersecting(FAR struct nxgl_rect_s result[4], + FAR const struct nxgl_rect_s *rect1, + FAR const struct nxgl_rect_s *rect2) +{ + struct nxgl_rect_s intersection; + + /* Get the intersection of the two rectangles */ + + nxgl_rectintersect(&intersection, rect1, rect2); + + /* Then return the four rectangles representing the regions NON included + * in the intersection. Some of these rectangles may be invalid (zero + * area), but those can be picked off using nxgl_nullrect() + * + * rect1.pt1 + * +-------------------------+ + * | rect2.pt1 | + * | int.pt1 | + * | +-------------------------+ + * | | | | + * | | | | + * +-------------------------+ | + * | rect1.pt2 | + * | int.pt2 | + * +-------------------------+ + * rect2.pt2 + * rect1.pt1 + * +-------------------------+ + * rect2.pt1 |int.pt1 | + * +---------+---------------+ | + * | | | | + * | | | | + * | | |int.pt2 | + * | +---------------+---------+ + * | | rect1.pt2 + * +-------------------------+ + * rect2.pt2 + * rect2.pt1 + * +-------------------------+ + * | rect1.pt1 | + * | int.pt1 | + * | +-------------------------+ + * | | | | + * | | | | + * | | | | + * +---------+---------------+ | + * | rect2.pt2 | + * | int.pt2 | + * +-------------------------+ + * rect1.pt2 + */ + + result[NX_TOP_NDX].pt1.x = rect1->pt1.x; + result[NX_TOP_NDX].pt1.y = rect1->pt1.y; + result[NX_TOP_NDX].pt2.x = rect1->pt2.x; + result[NX_TOP_NDX].pt2.y = intersection.pt1.y - 1; + + result[NX_BOTTOM_NDX].pt1.x = rect1->pt1.x; + result[NX_BOTTOM_NDX].pt1.y = intersection.pt2.y + 1; + result[NX_BOTTOM_NDX].pt2.x = rect1->pt2.x; + result[NX_BOTTOM_NDX].pt2.y = rect1->pt2.y; + + result[NX_LEFT_NDX].pt1.x = rect1->pt1.x; + result[NX_LEFT_NDX].pt1.y = intersection.pt1.y; + result[NX_LEFT_NDX].pt2.x = intersection.pt1.x - 1; + result[NX_LEFT_NDX].pt2.y = intersection.pt2.y; + + result[NX_RIGHT_NDX].pt1.x = intersection.pt2.x + 1; + result[NX_RIGHT_NDX].pt1.y = intersection.pt1.y; + result[NX_RIGHT_NDX].pt2.x = rect1->pt2.x; + result[NX_RIGHT_NDX].pt2.y = intersection.pt2.y; +} + + diff --git a/nuttx/graphics/nxglib/nxglib_nullrect.c b/nuttx/graphics/nxglib/nxglib_nullrect.c new file mode 100644 index 0000000000..26fc9e8d72 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_nullrect.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_nullrect.c + * + * Copyright (C) 2008-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_nullrect + * + * Description: + * Return true if the area of the retangle is <= 0. + * + ****************************************************************************/ + +bool nxgl_nullrect(FAR const struct nxgl_rect_s *rect) +{ + return (rect->pt1.x > rect->pt2.x || rect->pt1.y > rect->pt2.y); +} + diff --git a/nuttx/graphics/nxglib/nxglib_rectadd.c b/nuttx/graphics/nxglib/nxglib_rectadd.c new file mode 100644 index 0000000000..b53e6b04c6 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_rectadd.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_rectadd.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_rectadd + * + * Description: + * Return the rectangle that contains exactly two other rectanges. + * + ****************************************************************************/ + +void nxgl_rectadd(FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src1, + FAR const struct nxgl_rect_s *src2) +{ + dest->pt1.x = ngl_min(src1->pt1.x, src2->pt1.x); + dest->pt1.y = ngl_min(src1->pt1.y, src2->pt1.y); + dest->pt2.x = ngl_max(src1->pt2.x, src2->pt2.x); + dest->pt2.y = ngl_max(src1->pt2.y, src2->pt2.y); +} diff --git a/nuttx/graphics/nxglib/nxglib_rectcopy.c b/nuttx/graphics/nxglib/nxglib_rectcopy.c new file mode 100644 index 0000000000..998f5b716f --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_rectcopy.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_rectcopy.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_rectcopy + * + * Description: + * This is essentially memcpy for rectangles. We don't do structure + * assignements because some compilers are not good at that. + * + ****************************************************************************/ + +void nxgl_rectcopy(FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src) +{ + dest->pt1.x = src->pt1.x; + dest->pt1.y = src->pt1.y; + dest->pt2.x = src->pt2.x; + dest->pt2.y = src->pt2.y; +} diff --git a/nuttx/graphics/nxglib/nxglib_rectinside.c b/nuttx/graphics/nxglib/nxglib_rectinside.c new file mode 100644 index 0000000000..1c1f17a2e3 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_rectinside.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_rectinside.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_rectinside + * + * Description: + * Return true if the point pt lies within rect. + * + ****************************************************************************/ + +bool nxgl_rectinside(FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *pt) +{ + return (pt->x >= rect->pt1.x && pt->x <= rect->pt2.x && + pt->y >= rect->pt1.y && pt->y <= rect->pt2.y); +} diff --git a/nuttx/graphics/nxglib/nxglib_rectintersect.c b/nuttx/graphics/nxglib/nxglib_rectintersect.c new file mode 100644 index 0000000000..9616357104 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_rectintersect.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_rectintersect.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_rectintersect + * + * Description: + * Return the rectangle representing the intersection of the two rectangles. + * + ****************************************************************************/ + +void nxgl_rectintersect(FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src1, + FAR const struct nxgl_rect_s *src2) +{ + dest->pt1.x = ngl_max(src1->pt1.x, src2->pt1.x); + dest->pt1.y = ngl_max(src1->pt1.y, src2->pt1.y); + dest->pt2.x = ngl_min(src1->pt2.x, src2->pt2.x); + dest->pt2.y = ngl_min(src1->pt2.y, src2->pt2.y); +} diff --git a/nuttx/graphics/nxglib/nxglib_rectoffset.c b/nuttx/graphics/nxglib/nxglib_rectoffset.c new file mode 100644 index 0000000000..93481b0de5 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_rectoffset.c @@ -0,0 +1,87 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_rectoffset.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_rectoffset + * + * Description: + * Offset the rectangle position by the specified dx, dy values. + * + ****************************************************************************/ + +void nxgl_rectoffset(FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src, + nxgl_coord_t dx, nxgl_coord_t dy) +{ + dest->pt1.x = src->pt1.x + dx; + dest->pt1.y = src->pt1.y + dy; + dest->pt2.x = src->pt2.x + dx; + dest->pt2.y = src->pt2.y + dy; +} + + + diff --git a/nuttx/graphics/nxglib/nxglib_rectoverlap.c b/nuttx/graphics/nxglib/nxglib_rectoverlap.c new file mode 100644 index 0000000000..75d7a46411 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_rectoverlap.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_nulloverlap.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_rectoverlap + * + * Description: + * Return true if the two rectangles overlap + * + ****************************************************************************/ + +bool nxgl_rectoverlap(FAR struct nxgl_rect_s *rect1, + FAR struct nxgl_rect_s *rect2) +{ + /* The neither is wholly above, below, right, or left of the other, then + * the two rectangles overlap in some fashion. + */ + + return (rect1->pt1.x <= rect2->pt2.x) && /* false: rect1 is wholly to the right */ + (rect2->pt1.x <= rect1->pt2.x) && /* false: rect2 is wholly to the right */ + (rect1->pt1.y <= rect2->pt2.y) && /* false: rect1 is wholly below rect2 */ + (rect2->pt1.y <= rect1->pt2.y); /* false: rect2 is wholly below rect1 */ +} + diff --git a/nuttx/graphics/nxglib/nxglib_rectsize.c b/nuttx/graphics/nxglib/nxglib_rectsize.c new file mode 100644 index 0000000000..17a6c9214a --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_rectsize.c @@ -0,0 +1,81 @@ +/**************************************************************************** + * graphics/nxglib/nxglib_rectsize.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_rectsize + * + * Description: + * Return the size of the specified rectangle. + * + ****************************************************************************/ + +void nxgl_rectsize(FAR struct nxgl_size_s *size, + FAR const struct nxgl_rect_s *rect) +{ + size->w = rect->pt2.x - rect->pt1.x + 1; + size->h = rect->pt2.y - rect->pt1.y + 1; +} diff --git a/nuttx/graphics/nxglib/nxglib_rectunion.c b/nuttx/graphics/nxglib/nxglib_rectunion.c new file mode 100644 index 0000000000..8500c919cf --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_rectunion.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_rectunion.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_rectunion + * + * Description: + * Given two rectanges, src1 and src2, return the larger rectangle that + * contains both, dest. + * + ****************************************************************************/ + +void nxgl_rectunion(FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src1, + FAR const struct nxgl_rect_s *src2) +{ + dest->pt1.x = ngl_min(src1->pt1.x, src2->pt1.x); + dest->pt1.y = ngl_min(src1->pt1.y, src2->pt1.y); + dest->pt2.x = ngl_max(src1->pt2.x, src2->pt2.x); + dest->pt2.y = ngl_max(src1->pt2.y, src2->pt2.y); +} diff --git a/nuttx/graphics/nxglib/nxglib_rgb2yuv.c b/nuttx/graphics/nxglib/nxglib_rgb2yuv.c new file mode 100644 index 0000000000..c439c4fe00 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_rgb2yuv.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * graphics/color/nxglib_rgb2yuv.c + * + * Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#define b16_P0813 0x000014d0 /* 0.0813 */ +#define b16_P1140 0x00001d2f /* 0.1140 */ +#define b16_P1687 0x00002b30 /* 0.1687 */ +#define b16_P2990 0x00004c8b /* 0.2990 */ +#define b16_P3313 0x000054d0 /* 0.3313 */ +#define b16_P4187 0x00006b30 /* 0.4187 */ +#define b16_P5000 0x00008000 /* 0.5000 */ +#define b16_P5870 0x00009646 /* 0.5870 */ +#define b16_128P0 0x00800000 /* 128.0 */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_rgb2yuv + * + * Description: + * Convert 8-bit RGB triplet to 8-bit YUV triplet + * + ****************************************************************************/ + +void nxgl_rgb2yuv(uint8_t r, uint8_t g, uint8_t b, + uint8_t *y, uint8_t *u, uint8_t *v) +{ + /* Per the JFIF specification: + * + * Y = (0.2990 * R) + (0.5870 * G) + (0.1140 * B) + * U = 128 - (0.1687 * R) - (0.3313 * G) + (0.5000 * B) + * V = 128 + (0.5000 * R) - (0.4187 * G) - (0.0813 * B); + */ + + *y = (uint8_t)b16toi(b16muli(b16_P2990, r) + b16muli(b16_P5870, g) + b16muli(b16_P1140, b)); + *u = (uint8_t)b16toi(b16_128P0 - b16muli(b16_P1687, r) - b16muli(b16_P3313, g) + b16muli(b16_P5000, b)); + *v = (uint8_t)b16toi(b16_128P0 + b16muli(b16_P5000, r) - b16muli(b16_P4187, g) - b16muli(b16_P0813, b)); +} diff --git a/nuttx/graphics/nxglib/nxglib_runcopy.c b/nuttx/graphics/nxglib/nxglib_runcopy.c new file mode 100644 index 0000000000..4b5372f149 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_runcopy.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_runcopy.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_runcopy + * + * Description: + * This is essentially memcpy for runs. We don't do structure assignments + * because some compilers are not good at that. + * + ****************************************************************************/ + +void nxgl_runcopy(FAR struct nxgl_run_s *dest, FAR const struct nxgl_run_s *src) +{ + dest->x1 = src->x1; + dest->x2 = src->x2; + dest->y = src->y; +} diff --git a/nuttx/graphics/nxglib/nxglib_runoffset.c b/nuttx/graphics/nxglib/nxglib_runoffset.c new file mode 100644 index 0000000000..f66d736741 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_runoffset.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_runoffset.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_runoffset + * + * Description: + * Offset the run position by the specified (integer) dx, dy values. + * + ****************************************************************************/ + +void nxgl_runoffset(FAR struct nxgl_run_s *dest, + FAR const struct nxgl_run_s *src, + nxgl_coord_t dx, nxgl_coord_t dy) +{ + b16_t b16dx = itob16(dx); + dest->x1 = src->x1 + b16dx; + dest->x2 = src->x2 + b16dx; + dest->y = src->y + dy; +} diff --git a/nuttx/graphics/nxglib/nxglib_splitline.c b/nuttx/graphics/nxglib/nxglib_splitline.c new file mode 100644 index 0000000000..eff516db38 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_splitline.c @@ -0,0 +1,337 @@ +/**************************************************************************** + * graphics/nxglib/nxglib_splitline.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#define SMALL_SIN 1966 /* 1966/65536 = 0.03 */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_splitline + * + * Description: + * In the general case, a line with width can be represented as a + * parallelogram with a triangle at the top and bottom. Triangles and + * parallelograms are both degenerate versions of a trapeziod. This + * function breaks a wide line into triangles and trapezoids. This + * function also detects other degenerate cases: + * + * 1. If y1 == y2 then the line is horizontal and is better represented + * as a rectangle. + * 2. If x1 == x2 then the line is vertical and also better represented + * as a rectangle. + * 3. If the width of the line is 1, then there are no triangles at the + * top and bottome (this may also be the case if the width is narrow + * and the line is near vertical). + * 4. If the line is oriented is certain angles, it may consist only of + * the upper and lower triangles with no trapezoid in between. In + * this case, 3 trapezoids will be returned, but traps[1] will be + * degenerate. + * + * Input parameters: + * vector - A pointer to the vector described the line to be drawn. + * traps - A pointer to a array of trapezoids (size 3). + * rect - A pointer to a rectangle. + * + * Returned value: + * 0: Line successfully broken up into three trapezoids. Values in + * traps[0], traps[1], and traps[2] are valid. + * 1: Line successfully represented by one trapezoid. Value in traps[1] + * is valid. + * 2: Line successfully represented by one rectangle. Value in rect is + * valid + * <0: On errors, a negated errno value is returned. + * + ****************************************************************************/ + +int nxgl_splitline(FAR struct nxgl_vector_s *vector, + FAR struct nxgl_trapezoid_s *traps, + FAR struct nxgl_rect_s *rect, + nxgl_coord_t linewidth) +{ + struct nxgl_vector_s line; + nxgl_coord_t iheight; + nxgl_coord_t iwidth; + nxgl_coord_t iy; + nxgl_coord_t triheight; + nxgl_coord_t halfheight; + b16_t adjwidth; + b16_t xoffset; + b16_t halfoffset; + b16_t angle; + b16_t sinangle; + b16_t b16x; + + /* First, check the linewidth */ + + if (linewidth < 1) + { + return -EINVAL; + } + + /* Then make sure that the start position of the line is above the end + * position of the line... in raster order. + */ + + if (vector->pt1.y < vector->pt2.y) + { + /* Vector is already in raster order */ + + memcpy(&line, vector, sizeof(struct nxgl_vector_s)); + } + else if (vector->pt1.y > vector->pt2.y) + { + /* Swap the top and bottom */ + + line.pt1.x = vector->pt2.x; + line.pt1.y = vector->pt2.y; + line.pt2.x = vector->pt1.x; + line.pt2.y = vector->pt1.y; + } + else + { + /* First degenerate case: The line is horizontal. */ + + if (vector->pt1.x < vector->pt2.x) + { + rect->pt1.x = vector->pt1.x; + rect->pt2.x = vector->pt2.x; + } + else + { + rect->pt1.x = vector->pt2.x; + rect->pt2.x = vector->pt1.x; + } + + /* The height of the rectangle is the width of the line, half above + * and half below. + */ + + rect->pt1.y = vector->pt1.y - (linewidth >> 1); + rect->pt2.y = rect->pt1.y + linewidth - 1; + return 2; + } + + /* Check if the line is vertical */ + + if (line.pt1.x == line.pt2.x) + { + /* Second degenerate case: The line is vertical. */ + + rect->pt1.y = line.pt1.y; + rect->pt2.y = line.pt2.y; + + rect->pt1.x = line.pt1.x - (linewidth >> 1); + rect->pt2.x = rect->pt1.x + linewidth - 1; + return 2; + } + + /* The final degenerate case */ + + if (linewidth == 1) + { + /* A line of width 1 is basically a single parallelogram of width 1 */ + + traps[1].top.x1 = itob16(line.pt1.x); + traps[1].top.x2 = traps[1].top.x1; + traps[1].top.y = line.pt1.y; + + traps[1].bot.x1 = itob16(line.pt2.x); + traps[1].bot.x2 = traps[1].bot.x1; + traps[1].bot.y = line.pt2.y; + return 1; + } + + /* Okay, then what remains is interesting. + * + * iheight = |y2 - y1| + * iwidth = |x2 - x1| + */ + + iheight = line.pt2.y - line.pt1.y + 1; + if (line.pt1.x < line.pt2.x) + { + iwidth = line.pt2.x - line.pt1.x + 1; + } + else + { + iwidth = line.pt1.x - line.pt2.x + 1; + } + + /* Triangle height: linewidth * cosA + * Adjusted width: triheight / sinA + * X offset : linewidth * linewidth / adjusted line width + */ + + angle = b16atan2(itob16(iheight), itob16(iwidth)); + triheight = b16toi(linewidth * b16cos(angle) + b16HALF); + halfheight = (triheight >> 1); + + /* If the sine of the angle is tiny (i.e., the line is nearly horizontal), + * then we cannot compute the adjusted width. In this case, just use + * the width of the line bounding box. + */ + + sinangle = b16sin(angle); + if (sinangle < SMALL_SIN) + { + adjwidth = itob16(iwidth); + xoffset = 0; + } + else + { + adjwidth = b16divb16(itob16(linewidth), sinangle); + xoffset = itob16(linewidth * linewidth); + xoffset = b16divb16(xoffset, adjwidth); + } + + halfoffset = (xoffset >> 1); + + /* Return the top triangle (if there is one). NOTE that the horizontal + * (z) positions are represented with 16 bits of fraction. The vertical + * (y) positions, on the other hand, are integer. + */ + + if (triheight > 0) + { + if (line.pt1.x < line.pt2.x) + { + /* Line is going "south east" */ + + b16x = itob16(line.pt1.x) - halfoffset; + iy = line.pt1.y + halfheight; + + traps[0].top.x1 = b16x + xoffset; + traps[0].top.x2 = traps[0].top.x1; + traps[0].top.y = iy - triheight + 1; + traps[0].bot.x1 = b16x; + traps[0].bot.x2 = b16x + adjwidth - b16ONE; + traps[0].bot.y = iy; + + b16x = itob16(line.pt2.x) + halfoffset; + iy = line.pt2.y - halfheight; + + traps[2].top.x1 = b16x - adjwidth + b16ONE; + traps[2].top.x2 = b16x; + traps[2].top.y = iy; + traps[2].bot.x1 = b16x - xoffset; + traps[2].bot.x2 = traps[2].bot.x1; + traps[2].bot.y = iy + triheight - 1; + } + else + { + /* Line is going "south west" */ + + b16x = itob16(line.pt1.x) + halfoffset; + iy = line.pt1.y + halfheight; + + traps[0].top.x1 = b16x - xoffset; + traps[0].top.x2 = traps[0].top.x1; + traps[0].top.y = iy - triheight + 1; + traps[0].bot.x1 = b16x - adjwidth + b16ONE; + traps[0].bot.x2 = b16x; + traps[0].bot.y = iy; + + b16x = itob16(line.pt2.x) - halfoffset; + iy = line.pt2.y - halfheight; + + traps[2].top.x1 = b16x; + traps[2].top.x2 = b16x + adjwidth - b16ONE; + traps[2].top.y = iy; + traps[2].bot.x1 = b16x + xoffset; + traps[2].bot.x2 = traps[2].bot.x1; + traps[2].bot.y = iy + triheight - 1; + } + + /* The center parallelogram is the horizontal edge of each triangle. + * Note the minor inefficency: that horizontal edges are drawn twice. + */ + + traps[1].top.x1 = traps[0].bot.x1; + traps[1].top.x2 = traps[0].bot.x2; + traps[1].top.y = traps[0].bot.y; + + traps[1].bot.x1 = traps[2].top.x1; + traps[1].bot.x2 = traps[2].top.x2; + traps[1].bot.y = traps[2].top.y; + + return 0; + } + + /* The line is too vertical to have any significant triangular top or + * bottom. Just return the center parallelogram. + */ + + traps[1].top.x1 = itob16(line.pt1.x) - halfoffset; + traps[1].top.x2 = traps[1].top.x1 + adjwidth - 1; + traps[1].top.y = line.pt1.y; + + traps[1].bot.x1 = itob16(line.pt2.x) - halfoffset; + traps[1].bot.x2 = traps[1].bot.x1 + adjwidth - 1; + traps[1].bot.y = line.pt2.y; + return 1; +} diff --git a/nuttx/graphics/nxglib/nxglib_trapcopy.c b/nuttx/graphics/nxglib/nxglib_trapcopy.c new file mode 100644 index 0000000000..63bc0ecd81 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_trapcopy.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_trapcopy.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_trapcopy + * + * Description: + * This is essentially memcpy for trapezoids. We don't do structure + * assignments because some compilers are not good at that. + * + ****************************************************************************/ + +void nxgl_trapcopy(FAR struct nxgl_trapezoid_s *dest, + FAR const struct nxgl_trapezoid_s *src) +{ + nxgl_runcopy(&dest->top, &src->top); + nxgl_runcopy(&dest->bot, &src->bot); +} diff --git a/nuttx/graphics/nxglib/nxglib_trapoffset.c b/nuttx/graphics/nxglib/nxglib_trapoffset.c new file mode 100644 index 0000000000..872a310728 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_trapoffset.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_trapoffset.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_trapoffset + * + * Description: + * Offset the trapezoid position by the specified dx, dy values. + * + ****************************************************************************/ + +void nxgl_trapoffset(FAR struct nxgl_trapezoid_s *dest, + FAR const struct nxgl_trapezoid_s *src, + nxgl_coord_t dx, nxgl_coord_t dy) +{ + nxgl_runoffset(&dest->top, &src->top, dx, dy); + nxgl_runoffset(&dest->bot, &src->bot, dx, dy); +} diff --git a/nuttx/graphics/nxglib/nxglib_vectoradd.c b/nuttx/graphics/nxglib/nxglib_vectoradd.c new file mode 100644 index 0000000000..b206effa60 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_vectoradd.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_vectoradd.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_vectoradd + * + * Description: + * Add two 2x1 vectors and save the result to a third. + * + ****************************************************************************/ + +void nxgl_vectoradd(FAR struct nxgl_point_s *dest, + FAR const struct nxgl_point_s *v1, + FAR const struct nxgl_point_s *v2) +{ + dest->x = v1->x + v2->x; + dest->y = v1->y + v2->y; +} + + diff --git a/nuttx/graphics/nxglib/nxglib_vectsubtract.c b/nuttx/graphics/nxglib/nxglib_vectsubtract.c new file mode 100644 index 0000000000..81ffc86fb0 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_vectsubtract.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * graphics/nxglib/nxsglib_vectorsubtract.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_vectsubtract + * + * Description: + * Add subtract vector v2 from vector v1 and return the result in vector dest + * + ****************************************************************************/ + +void nxgl_vectsubtract(FAR struct nxgl_point_s *dest, + FAR const struct nxgl_point_s *v1, + FAR const struct nxgl_point_s *v2) +{ + dest->x = v1->x - v2->x; + dest->y = v1->y - v2->y; +} + + diff --git a/nuttx/graphics/nxglib/nxglib_yuv2rgb.c b/nuttx/graphics/nxglib/nxglib_yuv2rgb.c new file mode 100644 index 0000000000..9a3cb1f228 --- /dev/null +++ b/nuttx/graphics/nxglib/nxglib_yuv2rgb.c @@ -0,0 +1,102 @@ +/**************************************************************************** + * graphics/color/nxglib_yuv2rgb.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#define b16_P3441 0x0000581a /* 0.344147 */ +#define b16_P7141 0x0000b6d2 /* 0.714142 */ +#define b16_1P402 0x000166ea /* 1.402008 */ +#define b16_1P772 0x0001c5a2 /* 1.722003 */ +#define b16_128P0 0x00800000 /* 128.000000 */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxgl_yuv2rgb + * + * Description: + * Convert 8-bit RGB triplet to 8-bit YUV triplet + * + ****************************************************************************/ + +void nxgl_yuv2rgb(uint8_t y, uint8_t u, uint8_t v, + uint8_t *r, uint8_t *g, uint8_t *b) +{ + b16_t vm128 = itob16(v) - b16_128P0; + b16_t um128 = itob16(u) - b16_128P0; + + /* Per the JFIF specification: + * + * R = Y + 1.40200 * (V - 128.0) + * G = Y - 0.34414 * (U - 128.0) - 0.71414 * (V - 128.0) + * B = Y + 1.77200 * (U - 128.0) + */ + + *r = (uint8_t)b16toi(itob16(y) + b16muli(b16_1P402, vm128)); + *g = (uint8_t)b16toi(itob16(y) - b16muli(b16_P3441, um128) - b16muli(b16_P7141, vm128)); + *b = (uint8_t)b16toi(itob16(y) + b16muli(b16_1P772, um128)); +} diff --git a/nuttx/graphics/nxmu/Make.defs b/nuttx/graphics/nxmu/Make.defs new file mode 100644 index 0000000000..23bf8995bc --- /dev/null +++ b/nuttx/graphics/nxmu/Make.defs @@ -0,0 +1,48 @@ +############################################################################ +# graphics/nxmu/Make.defs +# +# Copyright (C) 2008, 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +NX_ASRCS = +NXAPI_CSRCS = nx_bitmap.c nx_closewindow.c nx_connect.c nx_disconnect.c \ + nx_eventhandler.c nx_eventnotify.c nx_fill.c nx_filltrapezoid.c \ + nx_getposition.c nx_getrectangle.c nx_kbdchin.c nx_kbdin.c nx_lower.c \ + nx_mousein.c nx_move.c nx_openwindow.c nx_raise.c \ + nx_releasebkgd.c nx_requestbkgd.c nx_setpixel.c nx_setsize.c \ + nx_setbgcolor.c nx_setposition.c nx_drawcircle.c nx_drawline.c \ + nx_fillcircle.c nx_block.c +NXMU_CSRCS = nxmu_constructwindow.c nxmu_kbdin.c nxmu_mouse.c \ + nxmu_openwindow.c nxmu_redrawreq.c nxmu_releasebkgd.c \ + nxmu_requestbkgd.c nxmu_reportposition.c nxmu_sendclient.c \ + nxmu_sendserver.c nxmu_sendwindow.c nxmu_semtake.c nxmu_server.c +NX_CSRCS = $(NXAPI_CSRCS) $(NXMU_CSRCS) diff --git a/nuttx/graphics/nxmu/nx_bitmap.c b/nuttx/graphics/nxmu/nx_bitmap.c new file mode 100644 index 0000000000..a86eda96ac --- /dev/null +++ b/nuttx/graphics/nxmu/nx_bitmap.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * graphics/nxmu/nx_bitmap.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "nxbe.h" +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_bitmap + * + * Description: + * Copy a rectangular region of a larger image into the rectangle in the + * specified window. + * + * Input Parameters: + * hwnd - The window that will receive the bitmap image + * dest - Describes the rectangular region on the display that will receive the + * the bit map. + * src - The start of the source image. + * origin - The origin of the upper, left-most corner of the full bitmap. + * Both dest and origin are in window coordinates, however, origin + * may lie outside of the display. + * stride - The width of the full source image in pixels. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_bitmap(NXWINDOW hwnd, FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, unsigned int stride) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_bitmap_s outmsg; + int i; + +#ifdef CONFIG_DEBUG + if (!wnd || !dest || !src || !origin) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Format the bitmap command */ + + outmsg.msgid = NX_SVRMSG_BITMAP; + outmsg.wnd = wnd; + outmsg.stride = stride; + + for (i = 0; i < CONFIG_NX_NPLANES; i++) + { + outmsg.src[i] = src[i]; + } + + outmsg.origin.x = origin->x; + outmsg.origin.y = origin->y; + nxgl_rectcopy(&outmsg.dest, dest); + + /* Forward the fill command to the server */ + + return nxmu_sendwindow(wnd, &outmsg, sizeof(struct nxsvrmsg_bitmap_s)); +} diff --git a/nuttx/graphics/nxmu/nx_block.c b/nuttx/graphics/nxmu/nx_block.c new file mode 100644 index 0000000000..2f069f0962 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_block.c @@ -0,0 +1,148 @@ +/**************************************************************************** + * graphics/nxmu/nx_block.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "nxbe.h" +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_block + * + * Description: + * This is callback will do to things: (1) any queue a 'blocked' callback + * to the window and then (2) block any further window messaging. + * + * The 'blocked' callback is the response from nx_block (or nxtk_block). + * Those blocking interfaces are used to assure that no further messages are + * are directed to the window. Receipt of the blocked callback signifies + * that (1) there are no further pending callbacks and (2) that the + * window is now 'defunct' and will receive no further callbacks. + * + * This callback supports coordinated destruction of a window in multi- + * user mode. In multi-use mode, the client window logic must stay + * intact until all of the queued callbacks are processed. Then the + * window may be safely closed. Closing the window prior with pending + * callbacks can lead to bad behavior when the callback is executed. + * + * Multiple user mode only! + * + * Input Parameters: + * wnd - The window to be blocked + * arg - An argument that will accompany the block messages (This is arg2 + * in the blocked callback). + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_block(NXWINDOW hwnd, FAR void *arg) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_blocked_s outmsg; + int ret = OK; + +#ifdef CONFIG_DEBUG + if (!hwnd) + { + errno = EINVAL; + return NULL; + } +#endif + + /* Ignore additional attempts to block messages (no errors reported) */ + + if (!NXBE_ISBLOCKED(wnd)) + { + /* Mark the window as blocked. This will stop all messages to the window + * (EXCEPT the NX_SVRMSG_BLOCKED). Blocking the messages before sending the + * blocked message is awkward but assures that no other messages sneak into + * the message queue before we can set the blocked state. + */ + + NXBE_SETBLOCKED(wnd); + + /* Send the message inicating that the window is blocked (and because of + * queue also that there are no additional queue messages for the window) + */ + + outmsg.msgid = NX_SVRMSG_BLOCKED; + outmsg.wnd = wnd; + outmsg.arg = arg; + + /* Send the window message via nxmu_sendserver (vs. nxmu_sendwindow) so + * that it will not be blocked. + */ + + ret = nxmu_sendserver(wnd->conn, &outmsg, sizeof(struct nxbe_window_s)); + } + + return ret; +} + diff --git a/nuttx/graphics/nxmu/nx_closewindow.c b/nuttx/graphics/nxmu/nx_closewindow.c new file mode 100644 index 0000000000..f9722fcd2a --- /dev/null +++ b/nuttx/graphics/nxmu/nx_closewindow.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * graphics/nxmu/nx_closewindow.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + +/**************************************************************************** + * Name: nx_closewindow + * + * Description: + * Destroy a window created by nx_openwindow. + * + * Input Parameters: + * wnd - The window to be destroyed + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_closewindow(NXWINDOW hwnd) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_closewindow_s outmsg; + + /* Request destruction of the window by the server */ + + outmsg.msgid = NX_SVRMSG_CLOSEWINDOW; + outmsg.wnd = wnd; + + return nxmu_sendserver(wnd->conn, &outmsg, sizeof(struct nxsvrmsg_closewindow_s)); +} + diff --git a/nuttx/graphics/nxmu/nx_connect.c b/nuttx/graphics/nxmu/nx_connect.c new file mode 100644 index 0000000000..4d91b54d5b --- /dev/null +++ b/nuttx/graphics/nxmu/nx_connect.c @@ -0,0 +1,220 @@ +/**************************************************************************** + * graphics/nxmu/nx_connect.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Each client is assigned a unique ID using the g_nxcid counter. That + * counter increments as each new counter is created and is* protected for + * thread safefy with g_nxlibsem. Note that these are the only global values + * in the NX implementation. This is because the client ID must be unique + * even across all server instances. + * + * NOTE: that client ID 0 is reserved for the server(s) themselves + */ + +static sem_t g_nxlibsem = { 1 }; +static uint32_t g_nxcid = 1; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_connectinstance + * + * Description: + * Open a connection from a client to the NX server. One one client + * connection is normally needed per thread as each connection can host + * multiple windows. + * + * NOTES: + * - This function returns before the connection is fully instantiated. + * it is necessary to wait for the connection event before using the + * returned handle. + * - Multiple instances of the NX server may run at the same time, + * each with different message queue names. + * + * Input Parameters: + * svrmqname - The name for the server incoming message queue + * + * Return: + * Success: A non-NULL handle used with subsequent NX accesses + * Failure: NULL is returned and errno is set appropriately + * + ****************************************************************************/ + +NXHANDLE nx_connectinstance(FAR const char *svrmqname) +{ + FAR struct nxfe_conn_s *conn; + struct nxsvrmsg_s outmsg; + char climqname[NX_CLIENT_MXNAMELEN]; + struct mq_attr attr; + int ret; + + /* Sanity checking */ + +#ifdef CONFIG_DEBUG + if (!svrmqname) + { + errno = EINVAL; + return NULL; + } +#endif + + /* Allocate the NX client structure */ + + conn = (FAR struct nxfe_conn_s *)zalloc(sizeof(struct nxfe_conn_s)); + if (!conn) + { + errno = ENOMEM; + goto errout; + } + + /* Create the client MQ name */ + + nxmu_semtake(&g_nxlibsem); + conn->cid = g_nxcid++; + nxmu_semgive(&g_nxlibsem); + + sprintf(climqname, NX_CLIENT_MQNAMEFMT, conn->cid); + + /* Open the client MQ for reading */ + + attr.mq_maxmsg = CONFIG_NX_MXCLIENTMSGS; + attr.mq_msgsize = NX_MXCLIMSGLEN; + attr.mq_flags = 0; + +#ifdef CONFIG_NX_BLOCKING + conn->crdmq = mq_open(climqname, O_RDONLY|O_CREAT, 0666, &attr); +#else + conn->crdmq = mq_open(climqname, O_RDONLY|O_CREAT|O_NONBLOCK, 0666, &attr); +#endif + if (conn->crdmq == (mqd_t)-1) + { + gdbg("mq_open(%s) failed: %d\n", climqname, errno); + goto errout_with_conn; + } + + /* Open the server MQ for writing */ + + attr.mq_maxmsg = CONFIG_NX_MXSERVERMSGS; + attr.mq_msgsize = NX_MXSVRMSGLEN; + attr.mq_flags = 0; + + conn->cwrmq = mq_open(svrmqname, O_WRONLY|O_CREAT, 0666, &attr); + if (conn->cwrmq == (mqd_t)-1) + { + gdbg("mq_open(%s) failed: %d\n", svrmqname, errno); + goto errout_with_rmq; + } + + /* Inform the server that this client exists */ + + outmsg.msgid = NX_SVRMSG_CONNECT; + outmsg.conn = conn; + + ret = nxmu_sendserver(conn, &outmsg, sizeof(struct nxsvrmsg_s)); + if (ret < 0) + { + gdbg("nxmu_sendserver failed: %d\n", errno); + goto errout_with_wmq; + } + +#if 0 + /* Now read until we get a response to this message. The server will + * respond with either (1) NX_CLIMSG_CONNECTED, in which case the state + * will change to NX_CLISTATE_CONNECTED, or (2) NX_CLIMSG_DISCONNECTED + * in which case, nx_message will fail with errno = EHOSTDOWN. + */ + + do + { + ret = nx_eventhandler((NXHANDLE)conn); + if (ret < 0) + { + gdbg("nx_message failed: %d\n", errno); + goto errout_with_wmq; + } + usleep(300000); + } + while (conn->state != NX_CLISTATE_CONNECTED); +#endif + return (NXHANDLE)conn; + +errout_with_wmq: + mq_close(conn->cwrmq); +errout_with_rmq: + mq_close(conn->crdmq); +errout_with_conn: + free(conn); +errout: + return NULL; +} + diff --git a/nuttx/graphics/nxmu/nx_disconnect.c b/nuttx/graphics/nxmu/nx_disconnect.c new file mode 100644 index 0000000000..48e1e9cc03 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_disconnect.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * graphics/nxmu/nx_disconnect.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_disconnect + * + * Description: + * Disconnect a client from the NX server and/or free resources reserved + * by nx_connect/nx_connectinstance. + * + * Input Parameters: + * handle - the handle returned by nx_connect + * + * Return: + * OK on success; ERROR on failure with the errno set appropriately. + * NOTE that handle will no long be valid upon return. + * + ****************************************************************************/ + +void nx_disconnect(NXHANDLE handle) +{ + FAR struct nxfe_conn_s *conn = (FAR struct nxfe_conn_s *)handle; + struct nxsvrmsg_s outmsg; + int ret; + + /* Inform the server that this client no longer exists */ + + outmsg.msgid = NX_SVRMSG_DISCONNECT; + outmsg.conn = conn; + + /* We will finish the teardown upon receipt of the DISCONNECTED message */ + + ret = nxmu_sendserver(conn, &outmsg, sizeof(struct nxsvrmsg_s)); + if (ret < 0) + { + gdbg("ERROR: nxmu_sendserver() returned %d\n", ret); + } +} + diff --git a/nuttx/graphics/nxmu/nx_drawcircle.c b/nuttx/graphics/nxmu/nx_drawcircle.c new file mode 100644 index 0000000000..5a0780e1a0 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_drawcircle.c @@ -0,0 +1,145 @@ +/**************************************************************************** + * graphics/nxmu/nx_drawcircle.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Named indices into the 16 circle points generated by nxgl_circlepts */ + +#define POINT_0p0 0 +#define POINT_22p5 1 +#define POINT_45p0 2 +#define POINT_67p5 3 +#define POINT_90p0 4 +#define POINT_112p5 5 +#define POINT_135p0 6 +#define POINT_157p5 7 +#define POINT_180p0 8 +#define POINT_202p5 9 +#define POINT_225p0 10 +#define POINT_247p5 11 +#define POINT_270p0 12 +#define POINT_292p5 13 +#define POINT_315p0 14 +#define POINT_337p5 15 +#define NCIRCLE_POINTS 16 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_drawcircle + * + * Description: + * Draw a circular outline using the specified line thickness and color. + * + * Input Parameters: + * hwnd - The window handle + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_drawcircle(NXWINDOW hwnd, FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, nxgl_coord_t width, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + struct nxgl_point_s pts[NCIRCLE_POINTS]; + FAR struct nxgl_vector_s vector; + int i; + int ret; + + /* Convert the circle to a set of 16 points */ + + nxgl_circlepts(center, radius, pts); + + /* Draw each pair of points as a vector */ + + for (i = POINT_0p0; i < POINT_337p5; i++) + { + vector.pt1.x = pts[i].x; + vector.pt1.y = pts[i].y; + vector.pt2.x = pts[i+1].x; + vector.pt2.y = pts[i+1].y; + ret = nx_drawline(hwnd, &vector, width, color); + if (ret != OK) + { + return ret; + } + } + + /* The final, closing vector is a special case */ + + vector.pt1.x = pts[POINT_337p5].x; + vector.pt1.y = pts[POINT_337p5].y; + vector.pt2.x = pts[POINT_0p0].x; + vector.pt2.y = pts[POINT_0p0].y; + return nx_drawline(hwnd, &vector, width, color); +} diff --git a/nuttx/graphics/nxmu/nx_drawline.c b/nuttx/graphics/nxmu/nx_drawline.c new file mode 100644 index 0000000000..0267d8058b --- /dev/null +++ b/nuttx/graphics/nxmu/nx_drawline.c @@ -0,0 +1,136 @@ +/**************************************************************************** + * graphics/nxmu/nx_drawline.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_drawline + * + * Description: + * Fill the specified line in the window with the specified color. This + * is simply a wrapper that uses nxgl_splitline() to break the line into + * trapezoids and then calls nx_filltrapezoid() to render the line. + * + * Input Parameters: + * hwnd - The window handle + * vector - Describes the line to be drawn + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_drawline(NXWINDOW hwnd, FAR struct nxgl_vector_s *vector, + nxgl_coord_t width, nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + struct nxgl_trapezoid_s trap[3]; + struct nxgl_rect_s rect; + int ret; + +#ifdef CONFIG_DEBUG + if (!hwnd || !vector || width < 1 || !color) + { + set_errno(EINVAL); + return ERROR; + } +#endif + + ret = nxgl_splitline(vector, trap, &rect, width); + switch (ret) + { + case 0: + ret = nx_filltrapezoid(hwnd, NULL, &trap[0], color); + if (ret == OK) + { + ret = nx_filltrapezoid(hwnd, NULL, &trap[1], color); + if (ret == OK) + { + ret = nx_filltrapezoid(hwnd, NULL, &trap[2], color); + } + } + break; + + case 1: + ret = nx_filltrapezoid(hwnd, NULL, &trap[1], color); + break; + + case 2: + ret = nx_fill(hwnd, &rect, color); + break; + + default: + set_errno(-ret); + return ERROR; + } + + return ret; +} diff --git a/nuttx/graphics/nxmu/nx_eventhandler.c b/nuttx/graphics/nxmu/nx_eventhandler.c new file mode 100644 index 0000000000..944bb12d11 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_eventhandler.c @@ -0,0 +1,260 @@ +/**************************************************************************** + * graphics/nxmu/nx_eventhandler.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_connected + * + * Description: + * The server has completed the connection and is ready. + * + ****************************************************************************/ + +static inline void nx_connected(FAR struct nxfe_conn_s *conn) +{ + DEBUGASSERT(conn->state == NX_CLISTATE_NOTCONNECTED); + conn->state = NX_CLISTATE_CONNECTED; +} + +/**************************************************************************** + * Name: nx_disconnected + ****************************************************************************/ + +static inline void nx_disconnected(FAR struct nxfe_conn_s *conn) +{ + /* Close the server and client MQs */ + + (void)mq_close(conn->cwrmq); + (void)mq_close(conn->crdmq); + + /* And free the client structure */ + + free(conn); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_eventhandler + * + * Description: + * The client code must call this function periodically to process + * incoming messages from the server. If CONFIG_NX_BLOCKING is defined, + * then this function not return until a server message is received. + * + * When CONFIG_NX_BLOCKING is not defined, the client must exercise + * caution in the looping to assure that it does not eat up all of + * the CPU bandwidth calling nx_eventhandler repeatedly. nx_eventnotify + * may be called to get a signal event whenever a new incoming server + * event is avaiable. + * + * Input Parameters: + * handle - the handle returned by nx_connect + * + * Return: + * OK: No errors occurred. If CONFIG_NX_BLOCKING is defined, then + * one or more server message was processed. + * ERROR: An error occurred and errno has been set appropriately. Of + * particular interest, it will return errno == EHOSTDOWN when the + * server is disconnected. After that event, the handle can no + * longer be used. + * + ****************************************************************************/ + +int nx_eventhandler(NXHANDLE handle) +{ + FAR struct nxfe_conn_s *conn = (FAR struct nxfe_conn_s *)handle; + struct nxsvrmsg_s *msg; + struct nxbe_window_s *wnd; + uint8_t buffer[NX_MXCLIMSGLEN]; + int nbytes; + + /* Get the next message from our incoming message queue */ + + do + { + nbytes = mq_receive(conn->crdmq, buffer, NX_MXCLIMSGLEN, 0); + if (nbytes < 0) + { + /* EINTR is not an error. The wait was interrupted by a signal and + * we just need to try reading again. + */ + + if (errno != EINTR) + { + if (errno == EAGAIN) + { + /* EAGAIN is not an error. It occurs because the MQ is opened with + * O_NONBLOCK and there is no message available now. + */ + + return OK; + } + else + { + gdbg("mq_receive failed: %d\n", errno); + return ERROR; + } + } + } + } + while (nbytes < 0); + + DEBUGASSERT(nbytes >= sizeof(struct nxclimsg_s)); + + /* Dispatch the message appropriately */ + + msg = (struct nxsvrmsg_s *)buffer; + gvdbg("Received msgid=%d\n", msg->msgid); + switch (msg->msgid) + { + case NX_CLIMSG_CONNECTED: + nx_connected(conn); + break; + + case NX_CLIMSG_DISCONNECTED: + nx_disconnected(conn); + errno = EHOSTDOWN; + return ERROR; + + case NX_CLIMSG_REDRAW: + { + FAR struct nxclimsg_redraw_s *redraw = (FAR struct nxclimsg_redraw_s *)buffer; + wnd = redraw->wnd; + DEBUGASSERT(wnd); + if (wnd->cb->redraw) + { + wnd->cb->redraw((NXWINDOW)wnd, &redraw->rect, redraw->more, wnd->arg); + } + } + break; + + case NX_CLIMSG_NEWPOSITION: + { + FAR struct nxclimsg_newposition_s *postn = (FAR struct nxclimsg_newposition_s *)buffer; + wnd = postn->wnd; + DEBUGASSERT(wnd); + if (wnd->cb->position) + { + wnd->cb->position((NXWINDOW)wnd, &postn->size, &postn->pos, &postn->bounds, wnd->arg); + } + } + break; + +#ifdef CONFIG_NX_MOUSE + case NX_CLIMSG_MOUSEIN: + { + FAR struct nxclimsg_mousein_s *mouse = (FAR struct nxclimsg_mousein_s *)buffer; + wnd = mouse->wnd; + DEBUGASSERT(wnd); + if (wnd->cb->mousein) + { + wnd->cb->mousein((NXWINDOW)wnd, &mouse->pos, mouse->buttons, wnd->arg); + } + } + break; +#endif + +#ifdef CONFIG_NX_KBD + case NX_CLIMSG_KBDIN: + { + FAR struct nxclimsg_kbdin_s *kbd = (FAR struct nxclimsg_kbdin_s *)buffer; + wnd = kbd->wnd; + DEBUGASSERT(wnd); + if (wnd->cb->kbdin) + { + wnd->cb->kbdin((NXWINDOW)wnd, kbd->nch, kbd->ch, wnd->arg); + } + } + break; +#endif + + case NX_CLIMSG_BLOCKED: + { + FAR struct nxclimsg_blocked_s *blocked = (FAR struct nxclimsg_blocked_s *)buffer; + wnd = blocked->wnd; + DEBUGASSERT(wnd); + if (wnd->cb->blocked) + { + wnd->cb->blocked((NXWINDOW)wnd, wnd->arg, blocked->arg); + } + } + break; + + default: + gdbg("Unrecognized message opcode: %d\n", ((FAR struct nxsvrmsg_s *)buffer)->msgid); + break; + } + + return OK; +} + diff --git a/nuttx/graphics/nxmu/nx_eventnotify.c b/nuttx/graphics/nxmu/nx_eventnotify.c new file mode 100644 index 0000000000..1892413618 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_eventnotify.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * graphics/nxmu/nx_eventnotify.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include "nxfe.h" + +#ifndef CONFIG_DISABLE_SIGNALS + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_eventnotify + * + * Description: + * Rather than calling nx_eventhandler periodically, the client may + * register to receive a signal when a server event is available. The + * client can then call nv_eventhandler() only when incoming events are + * available. + * + * Only one such event is issued. Upon receipt of the signal, if the client + * wishes further notifications, it must call nx_eventnotify again. + * + * Input Parameters: + * handle - the handle returned by nx_connect + * + * Return: + * OK: No errors occurred. If CONFIG_NX_BLOCKING is defined, then + * one or more server message was processed. + * ERROR: An error occurred and errno has been set appropriately + * + ****************************************************************************/ + +int nx_eventnotify(NXHANDLE handle, int signo) +{ + FAR struct nxfe_conn_s *conn = (FAR struct nxfe_conn_s *)handle; + struct sigevent se; + + se.sigev_notify = SIGEV_SIGNAL; + se.sigev_signo = signo; + se.sigev_value.sival_ptr = (FAR void *)handle; + + return mq_notify(conn->crdmq, &se); +} + +#endif /* CONFIG_DISABLE_SIGNALS */ diff --git a/nuttx/graphics/nxmu/nx_fill.c b/nuttx/graphics/nxmu/nx_fill.c new file mode 100644 index 0000000000..969acdace0 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_fill.c @@ -0,0 +1,116 @@ +/**************************************************************************** + * graphics/nxmu/nx_fill.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_fill + * + * Description: + * Fill the specified rectangle in the window with the specified color + * + * Input Parameters: + * hwnd - The window handle + * rect - The location to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_fill(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_fill_s outmsg; + +#ifdef CONFIG_DEBUG + if (!wnd || !rect || !color) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Format the fill command */ + + outmsg.msgid = NX_SVRMSG_FILL; + outmsg.wnd = wnd; + + nxgl_rectcopy(&outmsg.rect, rect); + nxgl_colorcopy(outmsg.color, color); + + /* Forward the fill command to the server */ + + return nxmu_sendwindow(wnd, &outmsg, sizeof(struct nxsvrmsg_fill_s)); +} diff --git a/nuttx/graphics/nxmu/nx_fillcircle.c b/nuttx/graphics/nxmu/nx_fillcircle.c new file mode 100644 index 0000000000..bfc1dc9e39 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_fillcircle.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * graphics/nxsu/nx_fillcircle.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#define NCIRCLE_TRAPS 8 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_fillcircle + * + * Description: + * Fill a circular region using the specified color. + * + * Input Parameters: + * hwnd - The window handle + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * color - The color to use to fill the circle. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_fillcircle(NXWINDOW hwnd, FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + FAR struct nxgl_trapezoid_s traps[NCIRCLE_TRAPS]; + int i; + int ret; + + /* Describe the circular region as a sequence of 8 trapezoids */ + + nxgl_circletraps(center, radius, traps); + + /* Then rend those trapezoids */ + + for (i = 0; i < NCIRCLE_TRAPS; i++) + { + ret = nx_filltrapezoid(hwnd, NULL, &traps[i], color); + if (ret != OK) + { + return ret; + } + } + return OK; +} diff --git a/nuttx/graphics/nxmu/nx_filltrapezoid.c b/nuttx/graphics/nxmu/nx_filltrapezoid.c new file mode 100644 index 0000000000..bf289179e0 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_filltrapezoid.c @@ -0,0 +1,142 @@ +/**************************************************************************** + * graphics/nxmu/nx_filltrapezoid.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_filltrapezoid + * + * Description: + * Fill the specified trapezoidal region in the window with the specified color + * + * Input Parameters: + * hwnd - The window handle + * clip - Clipping region (may be null) + * trap - The trapezoidal region to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_filltrapezoid(NXWINDOW hwnd, FAR const struct nxgl_rect_s *clip, + FAR const struct nxgl_trapezoid_s *trap, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_filltrapezoid_s outmsg; + int i; + + /* Some debug-only sanity checks */ + +#ifdef CONFIG_DEBUG + if (!wnd || !trap || !color) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Format the fill command */ + + outmsg.msgid = NX_SVRMSG_FILLTRAP; + outmsg.wnd = wnd; + + /* If no clipping window was provided, then use the size of the entire window */ + + if (clip) + { + nxgl_rectcopy(&outmsg.clip, clip); + } + else + { + nxgl_rectcopy(&outmsg.clip, &wnd->bounds); + } + + /* Copy the trapezod and the color into the message */ + + nxgl_trapcopy(&outmsg.trap, trap); + +#if CONFIG_NX_NPLANES > 1 + for (i = 0; i < CONFIG_NX_NPLANES; i++) +#else + i = 0; +#endif + { + outmsg.color[i] = color[i]; + } + + /* Forward the trapezoid fill command to the server */ + + return nxmu_sendwindow(wnd, &outmsg, sizeof(struct nxsvrmsg_filltrapezoid_s)); +} diff --git a/nuttx/graphics/nxmu/nx_getposition.c b/nuttx/graphics/nxmu/nx_getposition.c new file mode 100644 index 0000000000..06ad2c6aa0 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_getposition.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * graphics/nxmu/nx_getposition.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_getposition + * + * Description: + * Request the position and size information for the selected window. The + * values will be return asynchronously through the client callback function + * pointer. + * + * Input Parameters: + * hwnd - The window handle + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_getposition(NXWINDOW hwnd) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_getposition_s outmsg; + +#ifdef CONFIG_DEBUG + if (!wnd) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Request the size/position info. + * + * It is tempting to just take the positional information from the window + * structure that we have in our hands now. However, we need to run this through + * the server to keep things serialized. There might, for example, be a pending + * size/position change and, in that case, this function would return the + * wrong info. + */ + + outmsg.msgid = NX_SVRMSG_GETPOSITION; + outmsg.wnd = wnd; + + return nxmu_sendwindow(wnd, &outmsg, sizeof(struct nxsvrmsg_getposition_s)); +} diff --git a/nuttx/graphics/nxmu/nx_getrectangle.c b/nuttx/graphics/nxmu/nx_getrectangle.c new file mode 100644 index 0000000000..f32065129c --- /dev/null +++ b/nuttx/graphics/nxmu/nx_getrectangle.c @@ -0,0 +1,124 @@ +/**************************************************************************** + * graphics/nxmu/nx_getrectangle.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_getrectangle + * + * Description: + * Get the raw contents of graphic memory within a rectangular region. NOTE: + * Since raw graphic memory is returned, the returned memory content may be + * the memory of windows above this one and may not necessarily belong to + * this window unless you assure that this is the top window. + * + * Input Parameters: + * wnd - The window structure reference + * rect - The location to be copied + * plane - Specifies the color plane to get from. + * dest - The location to copy the memory region + * deststride - The width, in bytes, the the dest memory + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_getrectangle(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, + unsigned int plane, FAR uint8_t *dest, + unsigned int deststride) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_getrectangle_s outmsg; + +#ifdef CONFIG_DEBUG + if (!hwnd || !rect || !dest) + { + gvdbg("Invalid parameters\n"); + set_errno(EINVAL); + return ERROR; + } +#endif + + /* Format the fill command */ + + outmsg.msgid = NX_SVRMSG_GETRECTANGLE; + outmsg.wnd = wnd; + outmsg.plane = plane; + outmsg.dest = dest; + outmsg.deststride = deststride; + + nxgl_rectcopy(&outmsg.rect, rect); + + /* Forward the fill command to the server */ + + return nxmu_sendwindow(wnd, &outmsg, sizeof(struct nxsvrmsg_getrectangle_s)); +} diff --git a/nuttx/graphics/nxmu/nx_kbdchin.c b/nuttx/graphics/nxmu/nx_kbdchin.c new file mode 100644 index 0000000000..6c7019f513 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_kbdchin.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * graphics/nxmu/nx_kbdchin.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxfe.h" + +#ifdef CONFIG_NX_KBD + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_kbdchin + * + * Description: + * Used by a thread or interrupt handler that manages some kind of keypad + * hardware to report text information to the NX server. That text + * data will be routed by the NX server to the appropriate window client. + * + ****************************************************************************/ + +int nx_kbdchin(NXHANDLE handle, uint8_t ch) +{ + FAR struct nxfe_conn_s *conn = (FAR struct nxfe_conn_s *)handle; + struct nxsvrmsg_kbdin_s outmsg; + + /* Inform the server of the new keypad data */ + + outmsg.msgid = NX_SVRMSG_KBDIN; + outmsg.nch = 1; + outmsg.ch[0] = ch; + + return nxmu_sendserver(conn, &outmsg, sizeof(struct nxsvrmsg_kbdin_s)); +} + +#endif /* CONFIG_NX_KBD */ diff --git a/nuttx/graphics/nxmu/nx_kbdin.c b/nuttx/graphics/nxmu/nx_kbdin.c new file mode 100644 index 0000000000..b4b91298b4 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_kbdin.c @@ -0,0 +1,122 @@ +/**************************************************************************** + * graphics/nxmu/nx_kbdin.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include "nxfe.h" + +#ifdef CONFIG_NX_KBD + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_kbdin + * + * Description: + * Used by a thread or interrupt handler that manages some kind of keypad + * hardware to report text information to the NX server. That text + * data will be routed by the NX server to the appropriate window client. + * + ****************************************************************************/ + +int nx_kbdin(NXHANDLE handle, uint8_t nch, FAR const uint8_t *ch) +{ + FAR struct nxfe_conn_s *conn = (FAR struct nxfe_conn_s *)handle; + FAR struct nxsvrmsg_kbdin_s *outmsg; + int size; + int ret; + int i; + + /* Allocate a bigger message to account for the variable amount of character + * data. + */ + + size = sizeof(struct nxsvrmsg_kbdin_s) + nch - 1; + outmsg = (FAR struct nxsvrmsg_kbdin_s *)malloc(size); + if (!outmsg) + { + errno = ENOMEM; + return ERROR; + } + + /* Inform the server of the new keypad data */ + + outmsg->msgid = NX_SVRMSG_KBDIN; + outmsg->nch = nch; + + for (i = 0; i < nch; i++) + { + outmsg->ch[i] = ch[i]; + } + + ret = nxmu_sendserver(conn, outmsg, size); + + free(outmsg); + return ret; +} + +#endif /* CONFIG_NX_KBD */ diff --git a/nuttx/graphics/nxmu/nx_lower.c b/nuttx/graphics/nxmu/nx_lower.c new file mode 100644 index 0000000000..c9505ca49a --- /dev/null +++ b/nuttx/graphics/nxmu/nx_lower.c @@ -0,0 +1,98 @@ +/**************************************************************************** + * graphics/nxmu/nx_lower.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_raise + * + * Description: + * Lower the specified window to the bottom of the display. + * + * Input parameters: + * hwnd - the window to be lowered + * + * Returned value: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_lower(NXWINDOW hwnd) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_lower_s outmsg; + + /* Send the RAISE message */ + + outmsg.msgid = NX_SVRMSG_LOWER; + outmsg.wnd = wnd; + + return nxmu_sendwindow(wnd, &outmsg, sizeof(struct nxsvrmsg_lower_s)); +} + diff --git a/nuttx/graphics/nxmu/nx_mousein.c b/nuttx/graphics/nxmu/nx_mousein.c new file mode 100644 index 0000000000..e84278539c --- /dev/null +++ b/nuttx/graphics/nxmu/nx_mousein.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * graphics/nxmu/nx_mousein.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxfe.h" + +#ifdef CONFIG_NX_MOUSE + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_mousein + * + * Description: + * Used by a thread or interrupt handler that manages some kind of pointing + * hardware to report new positional data to the NX server. That positional + * data will be routed by the NX server to the appropriate window client. + * + ****************************************************************************/ + +int nx_mousein(NXHANDLE handle, nxgl_coord_t x, nxgl_coord_t y, uint8_t buttons) +{ + FAR struct nxfe_conn_s *conn = (FAR struct nxfe_conn_s *)handle; + struct nxsvrmsg_mousein_s outmsg; + + /* Inform the server that this client no longer exists */ + + outmsg.msgid = NX_SVRMSG_MOUSEIN; + outmsg.pt.x = x; + outmsg.pt.y = y; + outmsg.buttons = buttons; + + return nxmu_sendserver(conn, &outmsg, sizeof(struct nxsvrmsg_mousein_s)); +} + +#endif /* CONFIG_NX_MOUSE */ diff --git a/nuttx/graphics/nxmu/nx_move.c b/nuttx/graphics/nxmu/nx_move.c new file mode 100644 index 0000000000..c8d4d3dfde --- /dev/null +++ b/nuttx/graphics/nxmu/nx_move.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * graphics/nxmu/nx_move.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_move + * + * Description: + * Move a rectangular region within the window + * + * Input Parameters: + * hwnd - The window within which the move is to be done + * rect - Describes the rectangular region to move + * offset - The offset to move the region + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_move(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_move_s outmsg; + +#ifdef CONFIG_DEBUG + if (!wnd) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Format the fill command */ + + outmsg.msgid = NX_SVRMSG_MOVE; + outmsg.wnd = wnd; + outmsg.offset.x = offset->x; + outmsg.offset.y = offset->y; + + nxgl_rectcopy(&outmsg.rect, rect); + + /* Forward the fill command to the server */ + + return nxmu_sendwindow(wnd, &outmsg, sizeof(struct nxsvrmsg_move_s)); +} diff --git a/nuttx/graphics/nxmu/nx_openwindow.c b/nuttx/graphics/nxmu/nx_openwindow.c new file mode 100644 index 0000000000..2975e365a1 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_openwindow.c @@ -0,0 +1,131 @@ +/**************************************************************************** + * graphics/nxmu/nx_openwindow.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_openwindow + * + * Description: + * Create a new window. + * + * Input Parameters: + * handle - The handle returned by nx_connect + * cb - Callbacks used to process windo events + * arg - User provided value that will be returned with NX callbacks. + * + * Return: + * Success: A non-NULL handle used with subsequent NX accesses + * Failure: NULL is returned and errno is set appropriately + * + ****************************************************************************/ + +NXWINDOW nx_openwindow(NXHANDLE handle, FAR const struct nx_callback_s *cb, + FAR void *arg) +{ + FAR struct nxbe_window_s *wnd; + int ret; + +#ifdef CONFIG_DEBUG + if (!handle || !cb) + { + errno = EINVAL; + return NULL; + } +#endif + + /* Pre-allocate the window structure */ + + wnd = (FAR struct nxbe_window_s *)kzalloc(sizeof(struct nxbe_window_s)); + if (!wnd) + { + errno = ENOMEM; + return NULL; + } + + /* Then let nxfe_constructwindow do the rest */ + + ret = nxfe_constructwindow(handle, wnd, cb, arg); + if (ret < 0) + { + /* An error occurred, the window has been freed */ + + return NULL; + } + + /* Return the uninitialized window reference. Since the server + * serializes all operations, we can be assured that the window will + * be initialized before the first operation on the window. + */ + + return (NXWINDOW)wnd; +} + diff --git a/nuttx/graphics/nxmu/nx_raise.c b/nuttx/graphics/nxmu/nx_raise.c new file mode 100644 index 0000000000..4f51810f19 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_raise.c @@ -0,0 +1,98 @@ +/**************************************************************************** + * graphics/nxmu/nx_raise.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_raise + * + * Description: + * Bring the specified window to the top of the display. + * + * Input parameters: + * hwnd - the window to be raised + * + * Returned value: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_raise(NXWINDOW hwnd) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_raise_s outmsg; + + /* Send the RAISE message */ + + outmsg.msgid = NX_SVRMSG_RAISE; + outmsg.wnd = wnd; + + return nxmu_sendwindow(wnd, &outmsg, sizeof(struct nxsvrmsg_raise_s)); +} + diff --git a/nuttx/graphics/nxmu/nx_releasebkgd.c b/nuttx/graphics/nxmu/nx_releasebkgd.c new file mode 100644 index 0000000000..9725856633 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_releasebkgd.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * graphics/nxmu/nx_releasebkgd.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_releasebkgd + * + * Description: + * Release the background window previously acquired using nx_openbgwindow + * and return control of the background to NX. + * + * Input Parameters: + * hwnd - The handle returned (indirectly) by nx_requestbkgd + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_releasebkgd(NXWINDOW hwnd) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_releasebkgd_s outmsg; + +#ifdef CONFIG_DEBUG + if (!wnd) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Request access to the background window from the server */ + + outmsg.msgid = NX_SVRMSG_RELEASEBKGD; + return nxmu_sendserver(wnd->conn, &outmsg, sizeof(struct nxsvrmsg_releasebkgd_s)); +} + diff --git a/nuttx/graphics/nxmu/nx_requestbkgd.c b/nuttx/graphics/nxmu/nx_requestbkgd.c new file mode 100644 index 0000000000..c8f71ab2a6 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_requestbkgd.c @@ -0,0 +1,136 @@ +/**************************************************************************** + * graphics/nxmu/nx_requestbkgd.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_requestbkgd + * + * Description: + * NX normally controls a separate window called the background window. + * It repaints the window as necessary using only a solid color fill. The + * background window always represents the entire screen and is always + * below other windows. It is useful for an application to control the + * background window in the following conditions: + * + * - If you want to implement a windowless solution. The single screen + * can be used to creat a truly simple graphic environment. In this + * case, you should probably also de-select CONFIG_NX_MULTIUSER as well. + * - When you want more on the background than a solid color. For + * example, if you want an image in the background, or animations in the + * background, or live video, etc. + * + * This API only requests the handle of the background window. That + * handle will be returned asynchronously in a subsequent position and + * redraw callbacks. + * + * + * Cautions: + * - The following should never be called using the background window. + * They are guaranteed to cause severe crashes: + * + * nx_setposition, nx_setsize, nx_raise, nx_lower. + * + * - Neither nx_opengbwindow or nx_closebgwindow should be called more than + * once. Multiple instances of the background window are not supported. + * + * Input Parameters: + * handle - The handle returned by nx_connect + * cb - Callbacks to use for processing background window events + * arg - User provided argument (see nx_openwindow, nx_constructwindow) + * + * Return: + * OK: Success; ERROR of failure with errno set appropriately. + * + ****************************************************************************/ + +int nx_requestbkgd(NXHANDLE handle, FAR const struct nx_callback_s *cb, + FAR void *arg) +{ + FAR struct nxfe_conn_s *conn = (FAR struct nxfe_conn_s *)handle; + struct nxsvrmsg_requestbkgd_s outmsg; + +#ifdef CONFIG_DEBUG + if (!conn || !cb) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Request access to the background window from the server */ + + outmsg.msgid = NX_SVRMSG_REQUESTBKGD; + outmsg.conn = conn; + outmsg.cb = cb; + outmsg.arg = arg; + + return nxmu_sendserver(conn, &outmsg, sizeof(struct nxsvrmsg_requestbkgd_s)); +} + diff --git a/nuttx/graphics/nxmu/nx_setbgcolor.c b/nuttx/graphics/nxmu/nx_setbgcolor.c new file mode 100644 index 0000000000..63fca5f552 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_setbgcolor.c @@ -0,0 +1,109 @@ +/**************************************************************************** + * graphics/nxmu/nx_setbgcolor.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_setbgcolor + * + * Description: + * Set the color of the background + * + * Input Parameters: + * handle - The connection handle + * color - The color to use in the background + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_setbgcolor(NXHANDLE handle, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + FAR struct nxfe_conn_s *conn = (FAR struct nxfe_conn_s *)handle; + struct nxsvrmsg_setbgcolor_s outmsg; + +#ifdef CONFIG_DEBUG + if (!conn) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Format the fill command */ + + outmsg.msgid = NX_SVRMSG_SETBGCOLOR; + nxgl_colorcopy(outmsg.color, color); + + /* Forward the fill command to the server */ + + return nxmu_sendserver(conn, &outmsg, sizeof(struct nxsvrmsg_setbgcolor_s)); +} diff --git a/nuttx/graphics/nxmu/nx_setpixel.c b/nuttx/graphics/nxmu/nx_setpixel.c new file mode 100644 index 0000000000..57fc12cc6f --- /dev/null +++ b/nuttx/graphics/nxmu/nx_setpixel.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * graphics/nxmu/nx_setpixel.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_setpixel + * + * Description: + * Set a single pixel in the window to the specified color. This is simply + * a degenerate case of nx_fill(), but may be optimized in some architectures. + * + * Input Parameters: + * wnd - The window structure reference + * pos - The pixel location to be set + * col - The color to use in the set + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_setpixel(NXWINDOW hwnd, FAR const struct nxgl_point_s *pos, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_setpixel_s outmsg; + +#ifdef CONFIG_DEBUG + if (!wnd || !pos || !color) + { + set_errno(EINVAL); + return ERROR; + } +#endif + + /* Format the fill command */ + + outmsg.msgid = NX_SVRMSG_SETPIXEL; + outmsg.wnd = wnd; + outmsg.pos.x = pos->x; + outmsg.pos.y = pos->y; + + nxgl_colorcopy(outmsg.color, color); + + /* Forward the fill command to the server */ + + return nxmu_sendwindow(wnd, &outmsg, sizeof(struct nxsvrmsg_setpixel_s)); +} diff --git a/nuttx/graphics/nxmu/nx_setposition.c b/nuttx/graphics/nxmu/nx_setposition.c new file mode 100644 index 0000000000..75b33757a8 --- /dev/null +++ b/nuttx/graphics/nxmu/nx_setposition.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * graphics/nxmu/nx_setposition.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_setposition + * + * Description: + * Set the position and size for the selected window + * + * Input Parameters: + * hwnd - The window handle + * pos - The new position of the window + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_setposition(NXWINDOW hwnd, FAR const struct nxgl_point_s *pos) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_setposition_s outmsg; + +#ifdef CONFIG_DEBUG + if (!wnd || !pos) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Inform the server of the changed position */ + + outmsg.msgid = NX_SVRMSG_SETPOSITION; + outmsg.wnd = wnd; + outmsg.pos.x = pos->x; + outmsg.pos.y = pos->y; + + return nxmu_sendwindow(wnd, &outmsg, sizeof(struct nxsvrmsg_setposition_s)); +} diff --git a/nuttx/graphics/nxmu/nx_setsize.c b/nuttx/graphics/nxmu/nx_setsize.c new file mode 100644 index 0000000000..5f538bccca --- /dev/null +++ b/nuttx/graphics/nxmu/nx_setsize.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * graphics/nxmu/nx_setsize.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_setsize + * + * Description: + * Set the size of the selected window + * + * Input Parameters: + * hwnd - The window handle + * size - The new size of the window. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_setsize(NXWINDOW hwnd, FAR const struct nxgl_size_s *size) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + struct nxsvrmsg_setsize_s outmsg; + +#ifdef CONFIG_DEBUG + if (!wnd || !size) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Then inform the server of the changed position */ + + outmsg.msgid = NX_SVRMSG_SETSIZE; + outmsg.wnd = wnd; + outmsg.size.w = size->w; + outmsg.size.h = size->h; + + return nxmu_sendwindow(wnd, &outmsg, sizeof(struct nxsvrmsg_setsize_s)); +} diff --git a/nuttx/graphics/nxmu/nxfe.h b/nuttx/graphics/nxmu/nxfe.h new file mode 100644 index 0000000000..8b6a21ef48 --- /dev/null +++ b/nuttx/graphics/nxmu/nxfe.h @@ -0,0 +1,733 @@ +/**************************************************************************** + * graphics/nxmu/nxfe.h + * + * Copyright (C) 2008-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXMU_NXFE_H +#define __GRAPHICS_NXMU_NXFE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "nxbe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifdef CONFIG_DISABLE_MQUEUE +# error "Message queues are disabled(CONFIG_DISABLE_MQUEUE)" +#endif + +#ifndef CONFIG_NX_MXSERVERMSGS +# define CONFIG_NX_MXSERVERMSGS 32 /* Number of pending messages in server MQ */ +#endif + +#ifndef CONFIG_NX_MXCLIENTMSGS +# define CONFIG_NX_MXCLIENTMSGS 16 /* Number of pending messages in each client MQ */ +#endif + +/* Used to create unique client MQ name */ + +#define NX_CLIENT_MQNAMEFMT "/dev/nxc%d" +#define NX_CLIENT_MXNAMELEN (16) + +#define NX_MXSVRMSGLEN (64) /* Maximum size of a client->server command */ +#define NX_MXEVENTLEN (64) /* Maximum size of an event */ +#define NX_MXCLIMSGLEN (64) /* Maximum size of a server->client message */ + +/* Handy macros */ + +#define nxmu_semgive(sem) sem_post(sem) /* To match nxmu_semtake() */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Client/Connection structures *********************************************/ + +/* Client state */ + +enum nx_clistate_e +{ + NX_CLISTATE_NOTCONNECTED = 0, /* Waiting for server to acknowledge connection */ + NX_CLISTATE_CONNECTED, /* Connection established (normal state) */ + NX_CLISTATE_DISCONNECT_PENDING, /* Waiting for server to acknowledge disconnect */ +}; + +/* This structure represents a connection between the client and the server */ + +struct nxfe_conn_s +{ + /* This number uniquely identifies the client */ + + int cid; /* Client ID (CID) */ + uint8_t state; /* See enum nx_clistate_e */ + + /* These are only usable on the client side of the connection */ + + mqd_t crdmq; /* MQ to read from the server (may be non-blocking) */ + mqd_t cwrmq; /* MQ to write to the server (blocking) */ + + /* These are only usable on the server side of the connection */ + + mqd_t swrmq; /* MQ to write to the client */ +}; + +/* Server state structure ***************************************************/ + +/* This the server 'front-end' state structure */ + +struct nxfe_state_s +{ + /* The 'back-end' window status. Must be first so that instances of + * struct nxbe_state_s can be simply cast to an instance of struct + * nxfe_state_s + */ + + struct nxbe_state_s be; + + /* This is the server's connection to iself */ + + struct nxfe_conn_s conn; +}; + +/* Message IDs **************************************************************/ + +enum nxmsg_e +{ + /* Server-to-Client Messages **********************************************/ + + NX_CLIMSG_CONNECTED = 1, /* The server has completed the connection and is ready */ + NX_CLIMSG_DISCONNECTED, /* The server has disconnected */ + NX_CLIMSG_REDRAW, /* Re-draw the specified window */ + NX_CLIMSG_NEWPOSITION, /* New window size/position */ + NX_CLIMSG_MOUSEIN, /* New mouse positional data available for window */ + NX_CLIMSG_KBDIN, /* New keypad input available for window */ + NX_CLIMSG_BLOCKED, /* The window is blocked */ + + /* Client-to-Server Messages **********************************************/ + + NX_SVRMSG_CONNECT, /* Establish connection with new NX server client */ + NX_SVRMSG_DISCONNECT, /* Tear down connection with terminating client */ + NX_SVRMSG_OPENWINDOW, /* Create a new window */ + NX_SVRMSG_CLOSEWINDOW, /* Close an existing window */ + NX_SVRMSG_BLOCKED, /* The window is blocked */ + NX_SVRMSG_REQUESTBKGD, /* Open the background window */ + NX_SVRMSG_RELEASEBKGD, /* Release the background window */ + NX_SVRMSG_SETPOSITION, /* Window position has changed */ + NX_SVRMSG_SETSIZE, /* Window size has changed */ + NX_SVRMSG_GETPOSITION, /* Get the current window position and size */ + NX_SVRMSG_RAISE, /* Move the window to the top */ + NX_SVRMSG_LOWER, /* Move the window to the bottom */ + NX_SVRMSG_SETPIXEL, /* Set a single pixel in the window with a color */ + NX_SVRMSG_FILL, /* Fill a rectangle in the window with a color */ + NX_SVRMSG_GETRECTANGLE, /* Get a rectangular region in the window */ + NX_SVRMSG_FILLTRAP, /* Fill a trapezoidal region in the window with a color */ + NX_SVRMSG_MOVE, /* Move a rectangular region within the window */ + NX_SVRMSG_BITMAP, /* Copy a rectangular bitmap into the window */ + NX_SVRMSG_SETBGCOLOR, /* Set the color of the background */ + NX_SVRMSG_MOUSEIN, /* New mouse report from mouse client */ + NX_SVRMSG_KBDIN, /* New keyboard report from keyboard client */ +}; + +/* Message priorities -- they must all be at the same priority to assure + * FIFO execution. + */ + +#define NX_CLIMSG_PRIO 42 +#define NX_SVRMSG_PRIO 42 + +/* Server-to-Client Message Structures **************************************/ + +/* The generic message structure. All messages begin with this form. */ + +struct nxclimsg_s +{ + uint32_t msgid; /* Any of nxclimsg_e */ +}; + +/* The server is now connected */ + +struct nxclimsg_connected_s +{ + uint32_t msgid; /* NX_CLIMSG_REDRAW_CONNECTED */ +}; + +/* The server is now disconnected */ + +struct nxclimsg_disconnected_s +{ + uint32_t msgid; /* NX_CLIMSG_REDRAW_DISCONNECTED */ +}; + +/* This message is received when a requested window has been opened. If wnd is NULL + * then errorcode is the errno value that provides the explanation of the error. + */ + +struct nxclimsg_redraw_s +{ + uint32_t msgid; /* NX_CLIMSG_REDRAW */ + FAR struct nxbe_window_s *wnd; /* The handle to the window to redraw in */ + FAR struct nxgl_rect_s rect; /* The rectangle to be redrawn */ + bool more; /* true: more redraw messages follow */ +}; + +/* This message informs the client of the new size or position of the window */ + +struct nxclimsg_newposition_s +{ + uint32_t msgid; /* NX_CLIMSG_NEWPOSITION */ + FAR struct nxbe_window_s *wnd; /* The window whose position/size has changed */ + FAR struct nxgl_size_s size; /* The current window size */ + FAR struct nxgl_point_s pos; /* The current window position */ + FAR struct nxgl_rect_s bounds; /* Size of screen */ +}; + +/* This message reports a new mouse event to a particular window */ + +#ifdef CONFIG_NX_MOUSE +struct nxclimsg_mousein_s +{ + uint32_t msgid; /* NX_SVRMSG_MOUSEIN */ + FAR struct nxbe_window_s *wnd; /* The handle of window receiving mouse input */ + struct nxgl_point_s pos; /* Mouse X/Y position */ + uint8_t buttons; /* Mouse button set */ +}; +#endif + +/* This message reports a new keypad event to a particular window */ + +#ifdef CONFIG_NX_KBD +struct nxclimsg_kbdin_s +{ + uint32_t msgid; /* NX_CLIMSG_KBDIN */ + FAR struct nxbe_window_s *wnd; /* The handle of window receiving keypad input */ + uint8_t nch; /* Number of characters received */ + uint8_t ch[1]; /* Array of received characters */ +}; +#endif + +/* This messsage confirms that that all queued window messages have been + * flushed and that the all further window messages are blocked. + */ + +struct nxclimsg_blocked_s +{ + uint32_t msgid; /* NX_CLIMSG_BLOCKED */ + FAR struct nxbe_window_s *wnd; /* The window that is blocked */ + FAR void *arg; /* User argument */ +}; + +/* Client-to-Server Message Structures **************************************/ + +/* The generic message structure. All server messages begin with this form. Also + * messages that have no additional data fields use this structure. This includes: + * NX_SVRMSG_CONNECT and NX_SVRMSG_DISCONNECT. + */ + +struct nxsvrmsg_s /* Generic server message */ +{ + uint32_t msgid; /* One of enum nxsvrmsg_e */ + FAR struct nxfe_conn_s *conn; /* The specific connection sending the message */ +}; + +/* This message requests the server to create a new window */ + +struct nxsvrmsg_openwindow_s +{ + uint32_t msgid; /* NX_SVRMSG_OPENWINDOW */ + FAR struct nxbe_window_s *wnd; /* The pre-allocated window structure */ +}; + +/* This message informs the server that client wishes to close a window */ + +struct nxsvrmsg_closewindow_s +{ + uint32_t msgid; /* NX_SVRMSG_CLOSEWINDOW */ + FAR struct nxbe_window_s *wnd; /* The window to be closed */ +}; + +/* This messsage is just a marker that is queued and forwarded by the server + * (NX_CLIMSG_BLOCKED). Messages to the window were blocked just after this + * message was sent. Receipt of this message indicates both that the window + * blocked and that there are no further queued messages for the window. + */ + +struct nxsvrmsg_blocked_s +{ + uint32_t msgid; /* NX_SVRMSG_BLOCKED */ + FAR struct nxbe_window_s *wnd; /* The window that is blocked */ + FAR void *arg; /* User argument */ +}; + +/* This message requests the server to create a new window */ + +struct nxsvrmsg_requestbkgd_s +{ + uint32_t msgid; /* NX_SVRMSG_REQUESTBKGD */ + FAR struct nxfe_conn_s *conn; /* The specific connection sending the message */ + FAR const struct nx_callback_s *cb; /* Event handling callbacks */ + FAR void *arg; /* Client argument used with callbacks */ +}; + +/* This message informs the server that client wishes to close a window */ + +struct nxsvrmsg_releasebkgd_s +{ + uint32_t msgid; /* NX_SVRMSG_RELEASEBKGD */ +}; + +/* This message informs the server that the size or position of the window has changed */ + +struct nxsvrmsg_setposition_s +{ + uint32_t msgid; /* NX_SVRMSG_SETPOSITION */ + FAR struct nxbe_window_s *wnd; /* The window whose position/size has changed */ + FAR struct nxgl_point_s pos; /* The new window position */ +}; + +/* This message informs the server that the size or position of the window has changed */ + +struct nxsvrmsg_setsize_s +{ + uint32_t msgid; /* NX_SVRMSG_SETSIZE */ + FAR struct nxbe_window_s *wnd; /* The window whose position/size has changed */ + FAR struct nxgl_size_s size; /* The new window size */ +}; + +/* This message informs the server that the size or position of the window has changed */ + +struct nxsvrmsg_getposition_s +{ + uint32_t msgid; /* NX_SVRMSG_FETPOSITION */ + FAR struct nxbe_window_s *wnd; /* The window whose position/size has changed */ +}; + +/* This message informs the server to raise this window to the top of the display */ + +struct nxsvrmsg_raise_s +{ + uint32_t msgid; /* NX_SVRMSG_RAISE */ + FAR struct nxbe_window_s *wnd; /* The window to be raised */ +}; + +/* This message informs the server to lower this window to the bottom of the display */ + +struct nxsvrmsg_lower_s +{ + uint32_t msgid; /* NX_SVRMSG_LOWER */ + FAR struct nxbe_window_s *wnd; /* The window to be lowered */ +}; + +/* Set a single pixel in the window with a color */ + +struct nxsvrmsg_setpixel_s +{ + uint32_t msgid; /* NX_SVRMSG_SETPIXEL */ + FAR struct nxbe_window_s *wnd; /* The window to fill */ + struct nxgl_point_s pos; /* The position of the pixel in the window */ + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]; /* Color to use in the fill */ +}; + +/* Fill a rectangle in the window with a color */ + +struct nxsvrmsg_fill_s +{ + uint32_t msgid; /* NX_SVRMSG_FILL */ + FAR struct nxbe_window_s *wnd; /* The window to fill */ + struct nxgl_rect_s rect; /* The rectangle in the window to fill */ + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]; /* Color to use in the fill */ +}; + +/* Get a rectangular region from the the window */ + +struct nxsvrmsg_getrectangle_s +{ + uint32_t msgid; /* NX_SVRMSG_GETRECTANGLE */ + FAR struct nxbe_window_s *wnd; /* The window to get from */ + struct nxgl_rect_s rect; /* The rectangle in the window to get from */ + unsigned int plane; /* The plane number to read */ + FAR uint8_t *dest; /* Memory location in which to store the graphics data */ + unsigned int deststride; /* Width of the destination memory in bytes */ +}; + +/* Fill a trapezoidal region in the window with a color */ + +struct nxsvrmsg_filltrapezoid_s +{ + uint32_t msgid; /* NX_SVRMSG_FILLTRAP */ + FAR struct nxbe_window_s *wnd; /* The window to fill */ + FAR struct nxgl_rect_s clip; /* The clipping window */ + struct nxgl_trapezoid_s trap; /* The trapezoidal region in the window to fill */ + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]; /* Color to use in the fill */ +}; + +/* Move a rectangular region within the window */ + +struct nxsvrmsg_move_s +{ + uint32_t msgid; /* NX_SVRMSG_MOVE */ + FAR struct nxbe_window_s *wnd; /* The window within which the move is done */ + struct nxgl_rect_s rect; /* Describes the rectangular region to move */ + struct nxgl_point_s offset; /* The offset to move the region */ +}; + +/* Copy a rectangular bitmap into the window */ + +struct nxsvrmsg_bitmap_s +{ + uint32_t msgid; /* NX_SVRMSG_BITMAP */ + FAR struct nxbe_window_s *wnd; /* The window with will receive the bitmap image */ + struct nxgl_rect_s dest; /* Destination location of the bitmap in the window */ + FAR const void *src[CONFIG_NX_NPLANES]; /* The start of the source image. */ + struct nxgl_point_s origin; /* Offset into the source image data */ + unsigned int stride; /* The width of the full source image in pixels. */ +}; + +/* Set the color of the background */ + +struct nxsvrmsg_setbgcolor_s +{ + uint32_t msgid; /* NX_SVRMSG_SETBGCOLOR */ + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]; /* Color to use in the background */ +}; + +/* This message reports a new mouse event from a hardware controller attached to + * the server as a regular client (this message may have even been sent from an + * interrupt handler). + */ + +#ifdef CONFIG_NX_MOUSE +struct nxsvrmsg_mousein_s +{ + uint32_t msgid; /* NX_SVRMSG_MOUSEIN */ + struct nxgl_point_s pt; /* Mouse X/Y position */ + uint8_t buttons; /* Mouse button set */ +}; +#endif + +/* This message reports a new keyboard event from a hardware controller attached to + * some kind of keypad (this message may have even been sent from an + * interrupt handler). + */ + +#ifdef CONFIG_NX_KBD +struct nxsvrmsg_kbdin_s +{ + uint32_t msgid; /* NX_SVRMSG_KBDIN */ + uint8_t nch ; /* Number of characters received */ + uint8_t ch[1]; /* Array of received characters */ +}; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxfe_constructwindow + * + * Description: + * This function is the same a nx_openwindow EXCEPT that the client provides + * the window structure instance. nx_constructwindow will initialize the + * the pre-allocated window structure for use by NX. This function is + * provided in addition to nx_open window in order to support a kind of + * inheritance: The caller's window structure may include extensions that + * are not visible to NX. + * + * NOTE: wnd must have been allocated using malloc() (or related allocators) + * Once provided to nxfe_constructwindow() that memory is owned and managed + * by NX. On certain error conditions or when the window is closed, NX will + * free() the window. + * + * Input Parameters: + * handle - The handle returned by nx_connect + * wnd - The pre-allocated window structure. + * cb - Callbacks used to process window events + * arg - User provided value that will be returned with NX callbacks. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately. In the + * case of ERROR, NX will have dealloated the pre-allocated window. + * + ****************************************************************************/ + +EXTERN int nxfe_constructwindow(NXHANDLE handle, + FAR struct nxbe_window_s *wnd, + FAR const struct nx_callback_s *cb, + FAR void *arg); + +/**************************************************************************** + * Name: nxmu_semtake + * + * Description: + * Take the semaphore, handling EINTR wakeups. See the nxmu_semgive macro. + * + * Input Parameters: + * sem - the semaphore to be taken. + * + * Return: + * None + * + ****************************************************************************/ + +EXTERN void nxmu_semtake(sem_t *sem); + +/**************************************************************************** + * Name: nxmu_sendserver + * + * Description: + * Send a message to the server at NX_SVRMSG_PRIO priority + * + * Input Parameters: + * conn - A pointer to the server connection structure + * msg - A pointer to the message to send + * msglen - The length of the message in bytes. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxmu_sendserver(FAR struct nxfe_conn_s *conn, + FAR const void *msg, size_t msglen); + +/**************************************************************************** + * Name: nxmu_sendwindow + * + * Description: + * Send a message to the server detined for a specific window at + * NX_SVRMSG_PRIO priority + * + * Input Parameters: + * wnd - A pointer to the back-end window structure + * msg - A pointer to the message to send + * msglen - The length of the message in bytes. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxmu_sendwindow(FAR struct nxbe_window_s *wnd, FAR const void *msg, + size_t msglen); + +/**************************************************************************** + * Name: nxmu_sendclient + * + * Description: + * Send a message to the client at NX_CLIMSG_PRIO priority + * + * Input Parameters: + * conn - A pointer to the server connection structure + * msg - A pointer to the message to send + * msglen - The length of the message in bytes. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxmu_sendclient(FAR struct nxfe_conn_s *conn, + FAR const void *msg, size_t msglen); + +/**************************************************************************** + * Name: nxmu_openwindow + * + * Description: + * Create a new window. + * + * Input Parameters: + * be - The back-end status structure + * wnd - The pre-allocated window structure to be initialized [IN/OUT] + * + * Return: + * None + * + ****************************************************************************/ + +EXTERN void nxmu_openwindow(FAR struct nxbe_state_s *be, + FAR struct nxbe_window_s *wnd); + +/**************************************************************************** + * Name: nxmu_requestbkgd + * + * Description: + * Perform the server-side operation for the nx_requestbkgd operation: + * Give the client control of the background window connection and receipt + * of all background window callbacks. + * + * conn - The client containing connection information [IN] + * be - The server state structure [IN] + * cb - Callbacks used to process window events + * arg - User provided argument (see nx_openwindow, nx_constructwindow) + * + * Return: + * None + * + ****************************************************************************/ + +EXTERN void nxmu_requestbkgd(FAR struct nxfe_conn_s *conn, + FAR struct nxbe_state_s *be, + FAR const struct nx_callback_s *cb, + FAR void *arg); + +/**************************************************************************** + * Name: nxmu_releasebkgd + * + * Description: + * Release the background window previously acquired using nxmu_openbgwindow + * and return control of the background to NX. + * + * Input Parameters: + * fe - The front-end state structure + * + * Return: + * None + * + ****************************************************************************/ + +EXTERN void nxmu_releasebkgd(FAR struct nxfe_state_s *fe); + +/**************************************************************************** + * Name: nxfe_reportposition + * + * Descripton: + * Report the new size/position of the window. + * + ****************************************************************************/ + +EXTERN void nxfe_reportposition(FAR struct nxbe_window_s *wnd); + +/**************************************************************************** + * Name: nxfe_redrawreq + * + * Descripton: + * Request the client that has this window to redraw the rectangular region. + * + ****************************************************************************/ + +EXTERN void nxfe_redrawreq(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *rect); + +/**************************************************************************** + * Name: nxmu_mouseinit + * + * Description: + * Initialize with the mouse in the center of the display + * + ****************************************************************************/ + +#ifdef CONFIG_NX_MOUSE +EXTERN void nxmu_mouseinit(int x, int y); +#endif + +/**************************************************************************** + * Name: nxmu_mousereport + * + * Description: + * Report mouse position info to the specified window + * + * Input Parameters: + * wnd - The window to receive the mouse report + * + * Returned Value: + * 0: Mouse report sent; >0: Mouse report not sent; <0: An error occurred + * + ****************************************************************************/ + +#ifdef CONFIG_NX_MOUSE +EXTERN int nxmu_mousereport(struct nxbe_window_s *wnd); +#endif + +/**************************************************************************** + * Name: nxmu_mousein + * + * Description: + * New positional data has been received from the thread or interrupt + * handler that manages some kind of pointing hardware. Route that + * positional data to the appropriate window client. + * + ****************************************************************************/ + +#ifdef CONFIG_NX_MOUSE +EXTERN int nxmu_mousein(FAR struct nxfe_state_s *fe, + FAR const struct nxgl_point_s *pos, int button); +#endif + +/**************************************************************************** + * Name: nxmu_kbdin + * + * Descripton: + * New keyboard data has been received from the thread or interrupt + * handler that manages some kind of keyboard/keypad hardware. Route that + * positional data to the appropriate window client. + * + ****************************************************************************/ + +#ifdef CONFIG_NX_KBD +EXTERN void nxmu_kbdin(FAR struct nxfe_state_s *fe, uint8_t nch, FAR uint8_t *ch); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXMU_NXFE_H */ + diff --git a/nuttx/graphics/nxmu/nxmu_constructwindow.c b/nuttx/graphics/nxmu/nxmu_constructwindow.c new file mode 100644 index 0000000000..e5f6dcc9ab --- /dev/null +++ b/nuttx/graphics/nxmu/nxmu_constructwindow.c @@ -0,0 +1,137 @@ +/**************************************************************************** + * graphics/nxmu/nx_openwindow.c + * + * Copyright (C) 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxfe_constructwindow + * + * Description: + * This function is the same a nx_openwindow EXCEPT that the client provides + * the window structure instance. nx_constructwindow will initialize the + * the pre-allocated window structure for use by NX. This function is + * provided in addition to nx_open window in order to support a kind of + * inheritance: The caller's window structure may include extensions that + * are not visible to NX. + * + * NOTE: wnd must have been allocated using malloc() (or related allocators) + * Once provided to nxfe_constructwindow() that memory is owned and managed + * by NX. On certain error conditions or when the window is closed, NX will + * free() the window. + * + * Input Parameters: + * handle - The handle returned by nx_connect + * wnd - The pre-allocated window structure. + * cb - Callbacks used to process window events + * arg - User provided value that will be returned with NX callbacks. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately. In the + * case of ERROR, NX will have dealloated the pre-allocated window. + * + ****************************************************************************/ + +int nxfe_constructwindow(NXHANDLE handle, FAR struct nxbe_window_s *wnd, + FAR const struct nx_callback_s *cb, FAR void *arg) +{ + FAR struct nxfe_conn_s *conn = (FAR struct nxfe_conn_s *)handle; + struct nxsvrmsg_openwindow_s outmsg; + +#ifdef CONFIG_DEBUG + if (!wnd) + { + errno = EINVAL; + return ERROR; + } + + if (!conn || !cb) + { + free(wnd); + errno = EINVAL; + return ERROR; + } +#endif + + /* Setup only the connection structure, callbacks and client private data + * reference. The server will set everything else up. + */ + + wnd->conn = conn; + wnd->cb = cb; + wnd->arg = arg; + + /* Request initialization the new window from the server */ + + outmsg.msgid = NX_SVRMSG_OPENWINDOW; + outmsg.wnd = wnd; + + return nxmu_sendserver(conn, &outmsg, sizeof(struct nxsvrmsg_openwindow_s)); +} + diff --git a/nuttx/graphics/nxmu/nxmu_kbdin.c b/nuttx/graphics/nxmu/nxmu_kbdin.c new file mode 100644 index 0000000000..2c658009bc --- /dev/null +++ b/nuttx/graphics/nxmu/nxmu_kbdin.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * graphics/nxmu/nxmu_kbdin.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include "nxfe.h" + +#ifdef CONFIG_NX_KBD + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxmu_kbdin + * + * Descripton: + * New keyboard data has been received from the thread or interrupt + * handler that manages some kind of keyboard/keypad hardware. Route that + * positional data to the appropriate window client. + * + ****************************************************************************/ + +void nxmu_kbdin(FAR struct nxfe_state_s *fe, uint8_t nch, FAR uint8_t *ch) +{ + FAR struct nxclimsg_kbdin_s *outmsg; + int size; + int i; + + /* Allocate a bigger message to account for the variable amount of + * character data. + */ + + size = sizeof(struct nxclimsg_kbdin_s) + nch - 1; + outmsg = (FAR struct nxclimsg_kbdin_s *)malloc(size); + if (outmsg) + { + /* Give the keypad input only to the top child */ + + outmsg->msgid = NX_CLIMSG_KBDIN; + outmsg->wnd = fe->be.topwnd; + outmsg->nch = nch; + + for (i = 0; i < nch; i++) + { + outmsg->ch[i] = ch[i]; + } + + (void)nxmu_sendclient(fe->be.topwnd->conn, outmsg, size); + free(outmsg); + } +} + +#endif /* CONFIG_NX_KBD */ + diff --git a/nuttx/graphics/nxmu/nxmu_mouse.c b/nuttx/graphics/nxmu/nxmu_mouse.c new file mode 100644 index 0000000000..3ebe062d29 --- /dev/null +++ b/nuttx/graphics/nxmu/nxmu_mouse.c @@ -0,0 +1,215 @@ +/**************************************************************************** + * graphics/nxmu/nxmu__mouse.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include "nxfe.h" + +#ifdef CONFIG_NX_MOUSE + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct nxgl_point_s g_mpos; +static struct nxgl_point_s g_mrange; +static uint8_t g_mbutton; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxmu_mouseinit + * + * Description: + * Initialize with the mouse in the center of the display + * + ****************************************************************************/ + +void nxmu_mouseinit(int x, int y) +{ + g_mrange.x = x; + g_mrange.y = y; + g_mpos.x = x / 2; + g_mpos.y = y / 2; + g_mbutton = 0; +} + +/**************************************************************************** + * Name: nxmu_mousereport + * + * Description: + * Report mouse position info to the specified window + * + * Input Parameters: + * wnd - The window to receive the mouse report + * + * Returned Value: + * 0: Mouse report sent; >0: Mouse report not sent; <0: An error occurred + * + ****************************************************************************/ + +int nxmu_mousereport(struct nxbe_window_s *wnd) +{ + struct nxclimsg_mousein_s outmsg; + + /* Does this window support mouse callbacks? */ + + if (wnd->cb->mousein) + { + /* Yes.. Is the mouse position visible in this window? */ + + if (nxbe_visible(wnd, &g_mpos)) + { + /* Yes... Convert the mouse position to window relative + * coordinates and send it to the client + */ + + outmsg.msgid = NX_CLIMSG_MOUSEIN; + outmsg.wnd = wnd; + outmsg.buttons = g_mbutton; + nxgl_vectsubtract(&outmsg.pos, &g_mpos, &wnd->bounds.pt1); + + return nxmu_sendclient(wnd->conn, &outmsg, sizeof(struct nxclimsg_mousein_s)); + } + } + + /* No error occurred, but the mouse report was not sent */ + + return 1; +} + +/**************************************************************************** + * Name: nxmu_mousein + * + * Description: + * New positional data has been received from the thread or interrupt + * handler that manages some kind of pointing hardware. Route that + * positional data to the appropriate window client. + * + ****************************************************************************/ + +int nxmu_mousein(FAR struct nxfe_state_s *fe, + FAR const struct nxgl_point_s *pos, int buttons) +{ + struct nxbe_window_s *wnd; + nxgl_coord_t x = pos->x; + nxgl_coord_t y = pos->y; + int ret; + + /* Clip x and y to within the bounding rectangle */ + + if (x < 0) + { + x = 0; + } + else if (x >= g_mrange.x) + { + x = g_mrange.x - 1; + } + + if (y < 0) + { + y = 0; + } + else if (y >= g_mrange.y) + { + y = g_mrange.y - 1; + } + + /* Look any change in values */ + + if (x != g_mpos.x || y != g_mpos.y || buttons != g_mbutton) + { + /* Update the mouse value */ + + g_mpos.x = x; + g_mpos.y = y; + g_mbutton = buttons; + + /* Pick the window to receive the mouse event. Start with + * the top window and go down. Stop with the first window + * that gets the mouse report + */ + + for (wnd = fe->be.topwnd; wnd; wnd = wnd->below) + { + /* The background window normally has no callback structure + * (unless a client has taken control of the background via + * nx_requestbkgd()). + */ + + if (wnd->cb) + { + ret = nxmu_mousereport(wnd); + if (ret == 0) + { + break; + } + } + } + } + + return OK; +} + +#endif /* CONFIG_NX_MOUSE */ diff --git a/nuttx/graphics/nxmu/nxmu_openwindow.c b/nuttx/graphics/nxmu/nxmu_openwindow.c new file mode 100644 index 0000000000..4cd6e661ce --- /dev/null +++ b/nuttx/graphics/nxmu/nxmu_openwindow.c @@ -0,0 +1,113 @@ +/**************************************************************************** + * graphics/nxmu/nxmu_openwindow.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxmu_openwindow + * + * Description: + * Create a new window. + * + * Input Parameters: + * be - The back-end status structure + * wnd - The pre-allocated window structure to be initialized [IN/OUT] + * + * Return: + * None + * + ****************************************************************************/ + +void nxmu_openwindow(FAR struct nxbe_state_s *be, FAR struct nxbe_window_s *wnd) +{ + /* The window structure was allocated in nx_openwindow and all fields have + * been set to zero cb and conn which were initialized on the client side. + * On the server side, we need only initialize a few more the non zero fields + * and insert the new window at the top of the display. + */ + + wnd->be = be; + + /* Now, insert the new window at the top on the display. topwind is + * never NULL (it may point only at the background window, however) + */ + + wnd->above = NULL; + wnd->below = be->topwnd; + + be->topwnd->above = wnd; + be->topwnd = wnd; + + /* Report the initial size/position of the window to the client */ + + nxfe_reportposition(wnd); + + /* Provide the initial mouse settings to the client */ + +#ifdef CONFIG_NX_MOUSE + nxmu_mousereport(wnd); +#endif +} diff --git a/nuttx/graphics/nxmu/nxmu_redrawreq.c b/nuttx/graphics/nxmu/nxmu_redrawreq.c new file mode 100644 index 0000000000..32ca477a26 --- /dev/null +++ b/nuttx/graphics/nxmu/nxmu_redrawreq.c @@ -0,0 +1,93 @@ +/**************************************************************************** + * graphics/nxmu/nxmu_redrawreq.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxfe_redrawreq + * + * Descripton: + * Request the client that has this window to redraw the rectangular region. + * + ****************************************************************************/ + +void nxfe_redrawreq(FAR struct nxbe_window_s *wnd, FAR const struct nxgl_rect_s *rect) +{ + struct nxclimsg_redraw_s outmsg; + + outmsg.msgid = NX_CLIMSG_REDRAW; + outmsg.wnd = wnd; + outmsg.more = false; + nxgl_rectoffset(&outmsg.rect, rect, -wnd->bounds.pt1.x, -wnd->bounds.pt1.y); + + (void)nxmu_sendclient(wnd->conn, &outmsg, sizeof(struct nxclimsg_redraw_s)); +} + + diff --git a/nuttx/graphics/nxmu/nxmu_releasebkgd.c b/nuttx/graphics/nxmu/nxmu_releasebkgd.c new file mode 100644 index 0000000000..3d1f24b792 --- /dev/null +++ b/nuttx/graphics/nxmu/nxmu_releasebkgd.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * graphics/nxmu/nxmu_releasebkgd.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxmu_releasebkgd + * + * Description: + * Release the background window previously acquired using nxmu_openbgwindow + * and return control of the background to NX. + * + * Input Parameters: + * fe - The front-end state structure + * + * Return: + * None + * + ****************************************************************************/ + +void nxmu_releasebkgd(FAR struct nxfe_state_s *fe) +{ + FAR struct nxbe_state_s *be = &fe->be; + +#ifdef CONFIG_DEBUG + if (!fe) + { + return; + } +#endif + + /* Destroy the client window callbacks* and restore the server + * connection. + */ + + be->bkgd.cb = NULL; + be->bkgd.arg = NULL; + be->bkgd.conn = &fe->conn; + + /* Redraw the background window */ + + nxfe_redrawreq(&be->bkgd, &be->bkgd.bounds); +} + diff --git a/nuttx/graphics/nxmu/nxmu_reportposition.c b/nuttx/graphics/nxmu/nxmu_reportposition.c new file mode 100644 index 0000000000..f9b5f9dafa --- /dev/null +++ b/nuttx/graphics/nxmu/nxmu_reportposition.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * graphics/nxmu/nxmu_reportposition.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxfe_reportposition + * + * Descripton: + * Report the new size/position of the window. + * + ****************************************************************************/ + +void nxfe_reportposition(FAR struct nxbe_window_s *wnd) +{ + FAR struct nxclimsg_newposition_s outmsg; + int ret; + + /* Send the size/position info */ + + outmsg.msgid = NX_CLIMSG_NEWPOSITION; + outmsg.wnd = wnd; + outmsg.pos.x = wnd->bounds.pt1.x; + outmsg.pos.y = wnd->bounds.pt1.y; + + nxgl_rectsize(&outmsg.size, &wnd->bounds); + + /* Provide the background window bounding box which is the screen limits + * It must always have (0,0) as its origin + */ + + nxgl_rectcopy(&outmsg.bounds, &wnd->be->bkgd.bounds); + + /* And provide this to the client */ + + ret = nxmu_sendclient(wnd->conn, &outmsg, sizeof(struct nxclimsg_newposition_s)); + if (ret < 0) + { + gdbg("nxmu_sendclient failed: %d\n", errno); + } +} diff --git a/nuttx/graphics/nxmu/nxmu_requestbkgd.c b/nuttx/graphics/nxmu/nxmu_requestbkgd.c new file mode 100644 index 0000000000..0e69351e6f --- /dev/null +++ b/nuttx/graphics/nxmu/nxmu_requestbkgd.c @@ -0,0 +1,124 @@ +/**************************************************************************** + * graphics/nxmu/nxmu_requestbkgd.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxmu_requestbkgd + * + * Description: + * Perform the server-side operation for the nx_requestbkgd operation: + * Give the client control of the background window connection and receipt + * of all background window callbacks. + * + * conn - The client containing connection information [IN] + * be - The server state structure [IN] + * cb - Callbacks used to process window events + * arg - User provided argument (see nx_openwindow, nx_constructwindow) + * + * Return: + * None + * + ****************************************************************************/ + +void nxmu_requestbkgd(FAR struct nxfe_conn_s *conn, + FAR struct nxbe_state_s *be, + FAR const struct nx_callback_s *cb, + FAR void *arg) +{ +#ifdef CONFIG_DEBUG + if (!conn || !be || !cb) + { + errno = EINVAL; + } +#endif + + /* Set the client's callback vtable and and replace the server + * connection with the clients connection. + */ + + be->bkgd.cb = cb; + be->bkgd.arg = arg; + be->bkgd.conn = conn; + + /* Report the size/position of the background window to the client */ + + nxfe_reportposition((NXWINDOW)&be->bkgd); + + /* Redraw the background window */ + + nxfe_redrawreq(&be->bkgd, &be->bkgd.bounds); + + /* Provide the mouse settings */ + +#ifdef CONFIG_NX_MOUSE + nxmu_mousereport(&be->bkgd); +#endif +} + diff --git a/nuttx/graphics/nxmu/nxmu_semtake.c b/nuttx/graphics/nxmu/nxmu_semtake.c new file mode 100644 index 0000000000..10fd5bd4a6 --- /dev/null +++ b/nuttx/graphics/nxmu/nxmu_semtake.c @@ -0,0 +1,87 @@ +/**************************************************************************** + * graphics/nxmu/nxmu_semtake.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxmu_semtake + ****************************************************************************/ + +void nxmu_semtake(sem_t *sem) +{ + while (sem_wait(sem) != 0) + { + /* The only case that an error should occur here is if the wait was + * awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} diff --git a/nuttx/graphics/nxmu/nxmu_sendclient.c b/nuttx/graphics/nxmu/nxmu_sendclient.c new file mode 100644 index 0000000000..8b7f121042 --- /dev/null +++ b/nuttx/graphics/nxmu/nxmu_sendclient.c @@ -0,0 +1,112 @@ +/**************************************************************************** + * graphics/nxmu/nxmu_sendclient.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxmu_sendclient + * + * Description: + * Send a message to the client at NX_CLIMSG_PRIO priority + * + * Input Parameters: + * conn - A pointer to the server connection structure + * msg - A pointer to the message to send + * msglen - The length of the message in bytes. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxmu_sendclient(FAR struct nxfe_conn_s *conn, FAR const void *msg, + size_t msglen) +{ + int ret; + + /* Sanity checking */ + +#ifdef CONFIG_DEBUG + if (!conn || conn->swrmq) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Send the message to the client */ + + ret = mq_send(conn->swrmq, msg, msglen, NX_CLIMSG_PRIO); + if (ret < 0) + { + gdbg("mq_send failed: %d\n", errno); + } + + return ret; +} diff --git a/nuttx/graphics/nxmu/nxmu_sendserver.c b/nuttx/graphics/nxmu/nxmu_sendserver.c new file mode 100644 index 0000000000..7007b81da9 --- /dev/null +++ b/nuttx/graphics/nxmu/nxmu_sendserver.c @@ -0,0 +1,112 @@ +/**************************************************************************** + * graphics/nxmu/nxmu_sendserver.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxmu_sendserver + * + * Description: + * Send a message to the server at NX_SVRMSG_PRIO priority + * + * Input Parameters: + * conn - A pointer to the server connection structure + * msg - A pointer to the message to send + * msglen - The length of the message in bytes. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxmu_sendserver(FAR struct nxfe_conn_s *conn, FAR const void *msg, + size_t msglen) +{ + int ret; + + /* Sanity checking */ + +#ifdef CONFIG_DEBUG + if (!conn || conn->cwrmq) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Send the message to the server */ + + ret = mq_send(conn->cwrmq, msg, msglen, NX_SVRMSG_PRIO); + if (ret < 0) + { + gdbg("mq_send failed: %d\n", errno); + } + + return ret; +} diff --git a/nuttx/graphics/nxmu/nxmu_sendwindow.c b/nuttx/graphics/nxmu/nxmu_sendwindow.c new file mode 100644 index 0000000000..6f64ffff2c --- /dev/null +++ b/nuttx/graphics/nxmu/nxmu_sendwindow.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * graphics/nxmu/nxmu_sendserver.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxmu_sendwindow + * + * Description: + * Send a message to the server detined for a specific window at + * NX_SVRMSG_PRIO priority + * + * Input Parameters: + * wnd - A pointer to the back-end window structure + * msg - A pointer to the message to send + * msglen - The length of the message in bytes. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxmu_sendwindow(FAR struct nxbe_window_s *wnd, FAR const void *msg, + size_t msglen) +{ + int ret = OK; + + /* Sanity checking */ + +#ifdef CONFIG_DEBUG + if (!wnd || !wnd->conn) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Ignore messages destined to a blocked window (no errors reported) */ + + if (!NXBE_ISBLOCKED(wnd)) + { + /* Send the message to the server */ + + ret = nxmu_sendserver(wnd->conn, msg, msglen); + } + + return ret; +} diff --git a/nuttx/graphics/nxmu/nxmu_server.c b/nuttx/graphics/nxmu/nxmu_server.c new file mode 100644 index 0000000000..2730e0ea28 --- /dev/null +++ b/nuttx/graphics/nxmu/nxmu_server.c @@ -0,0 +1,530 @@ +/**************************************************************************** + * graphics/nxmu/nxmu_server.c + * + * Copyright (C) 2008-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxmu_disconnect + ****************************************************************************/ + +static inline void nxmu_disconnect(FAR struct nxfe_conn_s *conn) +{ + struct nxclimsg_disconnected_s outmsg; + int ret; + + /* Send the handshake message back to the client */ + + outmsg.msgid = NX_CLIMSG_DISCONNECTED; + + ret = nxmu_sendclient(conn, &outmsg, sizeof(struct nxclimsg_disconnected_s)); + if (ret < 0) + { + gdbg("nxmu_sendclient failed: %d\n", errno); + } + + /* Close the outgoing client message queue */ + + (void)mq_close(conn->swrmq); +} + +/**************************************************************************** + * Name: nxmu_connect + ****************************************************************************/ + +static inline void nxmu_connect(FAR struct nxfe_conn_s *conn) +{ + char mqname[NX_CLIENT_MXNAMELEN]; + struct nxclimsg_connected_s outmsg; + int ret; + + /* Create the client MQ name */ + + sprintf(mqname, NX_CLIENT_MQNAMEFMT, conn->cid); + + /* Open the client MQ -- this should have already been created by the client */ + + conn->swrmq = mq_open(mqname, O_WRONLY); + if (conn->swrmq == (mqd_t)-1) + { + gdbg("mq_open(%s) failed: %d\n", mqname, errno); + outmsg.msgid = NX_CLIMSG_DISCONNECTED; + } + + /* Send the handshake message back to the client */ + + outmsg.msgid = NX_CLIMSG_CONNECTED; + ret = nxmu_sendclient(conn, &outmsg, sizeof(struct nxclimsg_connected_s)); + if (ret < 0) + { + gdbg("nxmu_sendclient failed: %d\n", errno); + } +} + +/**************************************************************************** + * Name: nxmu_shutdown + ****************************************************************************/ + +static inline void nxmu_shutdown(FAR struct nxfe_state_s *fe) +{ + FAR struct nxbe_window_s *wnd; + + /* Inform all of the clients in the window list that the server is + * exit-ting. Notes: (1) that the following loop will probably attempt to + * disconnect clients multiple times because one client may have multiple + * windows: The first disconnect will fail; subsequent will return errors + * that are ignored. (2) The final window to be disconnected will be the + * background window, thus close all of the servers message queues. + */ + + for (wnd = fe->be.topwnd; wnd; wnd = wnd->below) + { + (void)nxmu_disconnect(wnd->conn); + } +} + +/**************************************************************************** + * Name: nxmu_blocked + ****************************************************************************/ + +static inline void nxmu_blocked(FAR struct nxbe_window_s *wnd, FAR void *arg) +{ + struct nxclimsg_blocked_s outmsg; + int ret; + + outmsg.msgid = NX_CLIMSG_BLOCKED; + outmsg.wnd = wnd; + outmsg.arg = arg; + + ret = nxmu_sendclient(wnd->conn, &outmsg, sizeof(struct nxclimsg_blocked_s)); + if (ret < 0) + { + gdbg("nxmu_sendclient failed: %d\n", errno); + } +} + +/**************************************************************************** + * Name: nxmu_setup + ****************************************************************************/ + +static inline int nxmu_setup(FAR const char *mqname, FAR NX_DRIVERTYPE *dev, + FAR struct nxfe_state_s *fe) +{ + struct mq_attr attr; + int ret; + + memset(fe, 0, sizeof(struct nxfe_state_s)); + + /* Configure the framebuffer/LCD device */ + + ret = nxbe_configure(dev, &fe->be); + if (ret < 0) + { + gdbg("nxbe_configure failed: %d\n", -ret); + errno = -ret; + return ERROR; + } + +#if CONFIG_FB_CMAP + ret = nxbe_colormap(dev); + if (ret < 0) + { + gdbg("nxbe_colormap failed: %d\n", -ret); + errno = -ret; + return ERROR; + } +#endif /* CONFIG_FB_CMAP */ + + /* Initialize the non-NULL elements of the server connection structure. + * Oddly, this strcture represents the connection between the server and + * itself. + * + * Open the incoming server MQ. The server receives messages on the + * background window's incoming message queue. + */ + + attr.mq_maxmsg = CONFIG_NX_MXSERVERMSGS; + attr.mq_msgsize = NX_MXSVRMSGLEN; + attr.mq_flags = 0; + + fe->conn.crdmq = mq_open(mqname, O_RDONLY|O_CREAT, 0666, &attr); + if (fe->conn.crdmq == (mqd_t)-1) + { + gdbg("mq_open(%s) failed: %d\n", mqname, errno); + return ERROR; /* mq_open sets errno */ + } + + /* NOTE that the outgoing client MQ (cwrmq) is not initialized. The + * background window never initiates messages. + */ + + /* Open the outgoing server MQ. This is used to send messages to the + * background window which will, of course, be received and handled by + * the server message loop. + */ + + fe->conn.swrmq = mq_open(mqname, O_WRONLY); + if (fe->conn.swrmq == (mqd_t)-1) + { + gdbg("mq_open(%s) failed: %d\n", mqname, errno); + mq_close(fe->conn.crdmq); + return ERROR; /* mq_open sets errno */ + } + + /* The server is now "connected" to itself via the background window */ + + fe->conn.state = NX_CLISTATE_CONNECTED; + + /* Initialize the non-NULL elements of the background window */ + + fe->be.bkgd.conn = &fe->conn; + fe->be.bkgd.be = (FAR struct nxbe_state_s*)fe; + + fe->be.bkgd.bounds.pt2.x = fe->be.vinfo.xres - 1; + fe->be.bkgd.bounds.pt2.y = fe->be.vinfo.yres - 1; + + /* Complete initialization of the server state structure. The + * window list contains only one element: The background window + * with nothing else above or below it + */ + + fe->be.topwnd = &fe->be.bkgd; + + /* Initialize the mouse position */ + +#ifdef CONFIG_NX_MOUSE + nxmu_mouseinit(fe->be.vinfo.xres, fe->be.vinfo.yres); +#endif + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_runinstance + * + * Description: + * This is the server entry point. It does not return; the calling thread + * is dedicated to supporting NX server. + * + * NOTE that multiple instances of the NX server may run at the same time, + * each with different callback and message queue names. + * + * Input Parameters: + * mqname - The name for the server incoming message queue + * dev - Vtable "object" of the framebuffer/LCD "driver" to use + * + * Return: + * This function usually does not return. If it does return, it will + * return ERROR and errno will be set appropriately. + * + ****************************************************************************/ + +int nx_runinstance(FAR const char *mqname, FAR NX_DRIVERTYPE *dev) +{ + struct nxfe_state_s fe; + FAR struct nxsvrmsg_s *msg; + uint8_t buffer[NX_MXSVRMSGLEN]; + int nbytes; + int ret; + + /* Initialization *********************************************************/ + + /* Sanity checking */ + +#ifdef CONFIG_DEBUG + if (!mqname || !dev) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Initialize and configure the server */ + + ret = nxmu_setup(mqname, dev, &fe); + if (ret < 0) + { + return ret; /* nxmu_setup sets errno */ + } + + /* Produce the initial, background display */ + + nxbe_redraw(&fe.be, &fe.be.bkgd, &fe.be.bkgd.bounds); + + /* Message Loop ***********************************************************/ + + /* Then loop forever processing incoming messages */ + + for (;;) + { + /* Receive the next server message */ + + nbytes = mq_receive(fe.conn.crdmq, buffer, NX_MXSVRMSGLEN, 0); + if (nbytes < 0) + { + if (errno != EINTR) + { + gdbg("mq_receive failed: %d\n", errno); + goto errout; /* mq_receive sets errno */ + } + continue; + } + + /* Dispatch the message appropriately */ + + DEBUGASSERT(nbytes >= sizeof(struct nxsvrmsg_s)); + msg = (FAR struct nxsvrmsg_s *)buffer; + + gvdbg("Received opcode=%d nbytes=%d\n", msg->msgid, nbytes); + switch (msg->msgid) + { + /* Messages sent from clients to the NX server *********************/ + + case NX_SVRMSG_CONNECT: /* Establish connection with new NX server client */ + { + FAR struct nxsvrmsg_s *connmsg = (FAR struct nxsvrmsg_s *)buffer; + nxmu_connect(connmsg->conn); + } + break; + + case NX_SVRMSG_DISCONNECT: /* Tear down connection with terminating client */ + { + FAR struct nxsvrmsg_s *disconnmsg = (FAR struct nxsvrmsg_s *)buffer; + nxmu_disconnect(disconnmsg->conn); + } + break; + + case NX_SVRMSG_OPENWINDOW: /* Create a new window */ + { + FAR struct nxsvrmsg_openwindow_s *openmsg = (FAR struct nxsvrmsg_openwindow_s *)buffer; + nxmu_openwindow(&fe.be, openmsg->wnd); + } + break; + + case NX_SVRMSG_CLOSEWINDOW: /* Close an existing window */ + { + FAR struct nxsvrmsg_closewindow_s *closemsg = (FAR struct nxsvrmsg_closewindow_s *)buffer; + nxbe_closewindow(closemsg->wnd); + } + break; + + case NX_SVRMSG_BLOCKED: /* Block messsages to a window */ + { + FAR struct nxsvrmsg_blocked_s *blocked = (FAR struct nxsvrmsg_blocked_s *)buffer; + nxmu_blocked(blocked->wnd, blocked->arg); + } + break; + + case NX_SVRMSG_REQUESTBKGD: /* Give access to the background window */ + { + FAR struct nxsvrmsg_requestbkgd_s *rqbgmsg = (FAR struct nxsvrmsg_requestbkgd_s *)buffer; + nxmu_requestbkgd(rqbgmsg->conn, &fe.be, rqbgmsg->cb, rqbgmsg->arg); + } + break; + + case NX_SVRMSG_RELEASEBKGD: /* End access to the background window */ + { + nxmu_releasebkgd(&fe); + } + break; + + case NX_SVRMSG_SETPOSITION: /* Change window position */ + { + FAR struct nxsvrmsg_setposition_s *setposmsg = (FAR struct nxsvrmsg_setposition_s *)buffer; + nxbe_setposition(setposmsg->wnd, &setposmsg->pos); + } + break; + + case NX_SVRMSG_SETSIZE: /* Change window size */ + { + FAR struct nxsvrmsg_setsize_s *setsizemsg = (FAR struct nxsvrmsg_setsize_s *)buffer; + nxbe_setsize(setsizemsg->wnd, &setsizemsg->size); + } + break; + + case NX_SVRMSG_GETPOSITION: /* Get the window size/position */ + { + FAR struct nxsvrmsg_getposition_s *getposmsg = (FAR struct nxsvrmsg_getposition_s *)buffer; + nxfe_reportposition(getposmsg->wnd); + } + break; + + case NX_SVRMSG_RAISE: /* Move the window to the top of the display */ + { + FAR struct nxsvrmsg_raise_s *raisemsg = (FAR struct nxsvrmsg_raise_s *)buffer; + nxbe_raise(raisemsg->wnd); + } + break; + + case NX_SVRMSG_LOWER: /* Lower the window to the bottom of the display */ + { + FAR struct nxsvrmsg_lower_s *lowermsg = (FAR struct nxsvrmsg_lower_s *)buffer; + nxbe_lower(lowermsg->wnd); + } + break; + + case NX_SVRMSG_SETPIXEL: /* Set a single pixel in the window with a color */ + { + FAR struct nxsvrmsg_setpixel_s *setmsg = (FAR struct nxsvrmsg_setpixel_s *)buffer; + nxbe_setpixel(setmsg->wnd, &setmsg->pos, setmsg->color); + } + break; + + case NX_SVRMSG_FILL: /* Fill a rectangular region in the window with a color */ + { + FAR struct nxsvrmsg_fill_s *fillmsg = (FAR struct nxsvrmsg_fill_s *)buffer; + nxbe_fill(fillmsg->wnd, &fillmsg->rect, fillmsg->color); + } + break; + + case NX_SVRMSG_GETRECTANGLE: /* Get a rectangular region from the window */ + { + FAR struct nxsvrmsg_getrectangle_s *getmsg = (FAR struct nxsvrmsg_getrectangle_s *)buffer; + nxbe_getrectangle(getmsg->wnd, &getmsg->rect, getmsg->plane, getmsg->dest, getmsg->deststride); + } + break; + + case NX_SVRMSG_FILLTRAP: /* Fill a trapezoidal region in the window with a color */ + { + FAR struct nxsvrmsg_filltrapezoid_s *trapmsg = (FAR struct nxsvrmsg_filltrapezoid_s *)buffer; + nxbe_filltrapezoid(trapmsg->wnd, &trapmsg->clip, &trapmsg->trap, trapmsg->color); + } + break; + case NX_SVRMSG_MOVE: /* Move a rectangular region within the window */ + { + FAR struct nxsvrmsg_move_s *movemsg = (FAR struct nxsvrmsg_move_s *)buffer; + nxbe_move(movemsg->wnd, &movemsg->rect, &movemsg->offset); + } + break; + + case NX_SVRMSG_BITMAP: /* Copy a rectangular bitmap into the window */ + { + FAR struct nxsvrmsg_bitmap_s *bmpmsg = (FAR struct nxsvrmsg_bitmap_s *)buffer; + nxbe_bitmap(bmpmsg->wnd, &bmpmsg->dest, bmpmsg->src, &bmpmsg->origin, bmpmsg->stride); + } + break; + + case NX_SVRMSG_SETBGCOLOR: /* Set the color of the background */ + { + FAR struct nxsvrmsg_setbgcolor_s *bgcolormsg = (FAR struct nxsvrmsg_setbgcolor_s *)buffer; + nxgl_colorcopy(fe.be.bgcolor, bgcolormsg->color); + nxbe_fill(&fe.be.bkgd, &fe.be.bkgd.bounds, bgcolormsg->color); + } + break; + +#ifdef CONFIG_NX_MOUSE + case NX_SVRMSG_MOUSEIN: /* New mouse report from mouse client */ + { + FAR struct nxsvrmsg_mousein_s *mousemsg = (FAR struct nxsvrmsg_mousein_s *)buffer; + nxmu_mousein(&fe, &mousemsg->pt, mousemsg->buttons); + } + break; +#endif +#ifdef CONFIG_NX_KBD + case NX_SVRMSG_KBDIN: /* New keyboard report from keyboard client */ + { + FAR struct nxsvrmsg_kbdin_s *kbdmsg = (FAR struct nxsvrmsg_kbdin_s *)buffer; + nxmu_kbdin(&fe, kbdmsg->nch, kbdmsg->ch); + } + break; +#endif + + /* Messages sent to the backgound window ***************************/ + + case NX_CLIMSG_REDRAW: /* Re-draw the background window */ + { + FAR struct nxclimsg_redraw_s *redraw = (FAR struct nxclimsg_redraw_s *)buffer; + DEBUGASSERT(redraw->wnd == &fe.be.bkgd); + gvdbg("Re-draw background rect={(%d,%d),(%d,%d)}\n", + redraw->rect.pt1.x, redraw->rect.pt1.y, + redraw->rect.pt2.x, redraw->rect.pt2.y); + nxbe_fill(&fe.be.bkgd, &redraw->rect, fe.be.bgcolor); + } + break; + + case NX_CLIMSG_MOUSEIN: /* Ignored */ + case NX_CLIMSG_KBDIN: + break; + + case NX_CLIMSG_CONNECTED: /* Shouldn't happen */ + case NX_CLIMSG_DISCONNECTED: + default: + gdbg("Unrecognized command: %d\n", msg->msgid); + break; + } + } + +errout: + nxmu_shutdown(&fe); + return OK; +} diff --git a/nuttx/graphics/nxsu/Make.defs b/nuttx/graphics/nxsu/Make.defs new file mode 100644 index 0000000000..d16fe549c0 --- /dev/null +++ b/nuttx/graphics/nxsu/Make.defs @@ -0,0 +1,44 @@ +############################################################################ +# graphics/nxsu/Make.defs +# +# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +NX_ASRCS = +NXAPI_CSRCS = nx_bitmap.c nx_close.c nx_closewindow.c nx_fill.c \ + nx_filltrapezoid.c nx_getposition.c nx_getrectangle.c nx_kbdchin.c \ + nx_kbdin.c nx_lower.c nx_mousein.c nx_move.c nx_open.c \ + nx_openwindow.c nx_raise.c nx_releasebkgd.c nx_requestbkgd.c \ + nx_setpixel.c nx_setsize.c nx_setbgcolor.c nx_setposition.c \ + nx_drawcircle.c nx_drawline.c nx_fillcircle.c +NXSU_CSRCS = nxsu_constructwindow.c nxsu_redrawreq.c nxsu_reportposition.c +NX_CSRCS = $(NXAPI_CSRCS) $(NXSU_CSRCS) diff --git a/nuttx/graphics/nxsu/nx_bitmap.c b/nuttx/graphics/nxsu/nx_bitmap.c new file mode 100644 index 0000000000..696b94afe0 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_bitmap.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * graphics/nxsu/nx_bitmap.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "nxbe.h" +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_bitmap + * + * Description: + * Copy a rectangular region of a larger image into the rectangle in the + * specified window. + * + * Input Parameters: + * hwnd - The window that will receive the bitmap image + * dest - Describes the rectangular region on the display that will receive the + * the bit map. + * src - The start of the source image. + * origin - The origin of the upper, left-most corner of the full bitmap. + * Both dest and origin are in window coordinates, however, origin + * may lie outside of the display. + * stride - The width of the full source image in pixels. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_bitmap(NXWINDOW hwnd, FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, unsigned int stride) +{ +#ifdef CONFIG_DEBUG + if (!hwnd || !dest || !src || !origin) + { + errno = EINVAL; + return ERROR; + } +#endif + + nxbe_bitmap((FAR struct nxbe_window_s *)hwnd, dest, src, origin, stride); + return OK; +} diff --git a/nuttx/graphics/nxsu/nx_close.c b/nuttx/graphics/nxsu/nx_close.c new file mode 100644 index 0000000000..a3fa9b74d2 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_close.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * graphics/nxsu/nx_close.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_close + * + * Description: + * Close the single user NX interface. nx_close is single-user equivalent + * of nx_disconnect. + * + * Input Parameters: + * handle - the handle returned by nx_open + * + * Return: + * None + * + ****************************************************************************/ + +void nx_close(NXHANDLE handle) +{ + free(handle); +} + diff --git a/nuttx/graphics/nxsu/nx_closewindow.c b/nuttx/graphics/nxsu/nx_closewindow.c new file mode 100644 index 0000000000..c5a2799eaf --- /dev/null +++ b/nuttx/graphics/nxsu/nx_closewindow.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * graphics/nxsu/nx_closewindow.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_closewindow + * + * Description: + * Destroy a window created by nx_openwindow. + * + * Input Parameters: + * wnd - The window to be destroyed + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_closewindow(NXWINDOW hwnd) +{ +#ifdef CONFIG_DEBUG + if (!hwnd) + { + errno = EINVAL; + return ERROR; + } +#endif + + nxbe_closewindow((FAR struct nxbe_window_s *)hwnd); + return OK; +} + diff --git a/nuttx/graphics/nxsu/nx_drawcircle.c b/nuttx/graphics/nxsu/nx_drawcircle.c new file mode 100644 index 0000000000..8d5c124549 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_drawcircle.c @@ -0,0 +1,145 @@ +/**************************************************************************** + * graphics/nxsu/nx_drawcircle.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Named indices into the 16 circle points generated by nxgl_circlepts */ + +#define POINT_0p0 0 +#define POINT_22p5 1 +#define POINT_45p0 2 +#define POINT_67p5 3 +#define POINT_90p0 4 +#define POINT_112p5 5 +#define POINT_135p0 6 +#define POINT_157p5 7 +#define POINT_180p0 8 +#define POINT_202p5 9 +#define POINT_225p0 10 +#define POINT_247p5 11 +#define POINT_270p0 12 +#define POINT_292p5 13 +#define POINT_315p0 14 +#define POINT_337p5 15 +#define NCIRCLE_POINTS 16 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_drawcircle + * + * Description: + * Draw a circular outline using the specified line thickness and color. + * + * Input Parameters: + * hwnd - The window handle + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_drawcircle(NXWINDOW hwnd, FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, nxgl_coord_t width, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + struct nxgl_point_s pts[NCIRCLE_POINTS]; + FAR struct nxgl_vector_s vector; + int i; + int ret; + + /* Convert the circle to a set of 16 points */ + + nxgl_circlepts(center, radius, pts); + + /* Draw each pair of points as a vector */ + + for (i = POINT_0p0; i < POINT_337p5; i++) + { + vector.pt1.x = pts[i].x; + vector.pt1.y = pts[i].y; + vector.pt2.x = pts[i+1].x; + vector.pt2.y = pts[i+1].y; + ret = nx_drawline(hwnd, &vector, width, color); + if (ret != OK) + { + return ret; + } + } + + /* The final, closing vector is a special case */ + + vector.pt1.x = pts[POINT_337p5].x; + vector.pt1.y = pts[POINT_337p5].y; + vector.pt2.x = pts[POINT_0p0].x; + vector.pt2.y = pts[POINT_0p0].y; + return nx_drawline(hwnd, &vector, width, color); +} diff --git a/nuttx/graphics/nxsu/nx_drawline.c b/nuttx/graphics/nxsu/nx_drawline.c new file mode 100644 index 0000000000..ca4ddaf188 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_drawline.c @@ -0,0 +1,136 @@ +/**************************************************************************** + * graphics/nxsu/nx_drawline.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_drawline + * + * Description: + * Fill the specified line in the window with the specified color. This + * is simply a wrapper that uses nxgl_splitline() to break the line into + * trapezoids and then calls nx_filltrapezoid() to render the line. + * + * Input Parameters: + * hwnd - The window handle + * vector - Describes the line to be drawn + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_drawline(NXWINDOW hwnd, FAR struct nxgl_vector_s *vector, + nxgl_coord_t width, nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + struct nxgl_trapezoid_s trap[3]; + struct nxgl_rect_s rect; + int ret; + +#ifdef CONFIG_DEBUG + if (!hwnd || !vector || width < 1 || !color) + { + set_errno(EINVAL); + return ERROR; + } +#endif + + ret = nxgl_splitline(vector, trap, &rect, width); + switch (ret) + { + case 0: + ret = nx_filltrapezoid(hwnd, NULL, &trap[0], color); + if (ret == OK) + { + ret = nx_filltrapezoid(hwnd, NULL, &trap[1], color); + if (ret == OK) + { + ret = nx_filltrapezoid(hwnd, NULL, &trap[2], color); + } + } + break; + + case 1: + ret = nx_filltrapezoid(hwnd, NULL, &trap[1], color); + break; + + case 2: + ret = nx_fill(hwnd, &rect, color); + break; + + default: + set_errno(-ret); + return ERROR; + } + + return ret; +} diff --git a/nuttx/graphics/nxsu/nx_fill.c b/nuttx/graphics/nxsu/nx_fill.c new file mode 100644 index 0000000000..9075f82c01 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_fill.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * graphics/nxsu/nx_fill.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_fill + * + * Description: + * Fill the specified rectangle in the window with the specified color + * + * Input Parameters: + * hwnd - The window handle + * rect - The location to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_fill(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ +#ifdef CONFIG_DEBUG + if (!hwnd || !rect || !color) + { + errno = EINVAL; + return ERROR; + } +#endif + + nxbe_fill((FAR struct nxbe_window_s *)hwnd, rect, color); + return 0; +} diff --git a/nuttx/graphics/nxsu/nx_fillcircle.c b/nuttx/graphics/nxsu/nx_fillcircle.c new file mode 100644 index 0000000000..12c47f80a1 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_fillcircle.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * graphics/nxmu/nx_fillcircle.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#define NCIRCLE_TRAPS 8 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_fillcircle + * + * Description: + * Fill a circular region using the specified color. + * + * Input Parameters: + * hwnd - The window handle + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * color - The color to use to fill the circle. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_fillcircle(NXWINDOW hwnd, FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + FAR struct nxgl_trapezoid_s traps[NCIRCLE_TRAPS]; + int i; + int ret; + + /* Describe the circular region as a sequence of 8 trapezoids */ + + nxgl_circletraps(center, radius, traps); + + /* Then rend those trapezoids */ + + for (i = 0; i < NCIRCLE_TRAPS; i++) + { + ret = nx_filltrapezoid(hwnd, NULL, &traps[i], color); + if (ret != OK) + { + return ret; + } + } + return OK; +} diff --git a/nuttx/graphics/nxsu/nx_filltrapezoid.c b/nuttx/graphics/nxsu/nx_filltrapezoid.c new file mode 100644 index 0000000000..869ce3e1a0 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_filltrapezoid.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * graphics/nxsu/nx_filltrapezoid.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_filltrapezoid + * + * Description: + * Fill the specified trapezoidal region in the window with the specified color + * + * Input Parameters: + * hwnd - The window handle + * clip - Clipping region (may be null) + * trap - The trapezoidal region to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_filltrapezoid(NXWINDOW hwnd, FAR const struct nxgl_rect_s *clip, + FAR const struct nxgl_trapezoid_s *trap, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ +#ifdef CONFIG_DEBUG + if (!hwnd || !trap || !color) + { + errno = EINVAL; + return ERROR; + } +#endif + + nxbe_filltrapezoid((FAR struct nxbe_window_s *)hwnd, clip, trap, color); + return OK; +} diff --git a/nuttx/graphics/nxsu/nx_getposition.c b/nuttx/graphics/nxsu/nx_getposition.c new file mode 100644 index 0000000000..8760d84c16 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_getposition.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * graphics/nxsu/nx_getposition.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_getposition + * + * Description: + * Request the position and size information for the selected window. The + * values will be return asynchronously through the client callback function + * pointer. + * + * Input Parameters: + * hwnd - The window handle + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_getposition(NXWINDOW hwnd) +{ +#ifdef CONFIG_DEBUG + if (!hwnd) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* This is very awkward since the requested values are available + * immediately in the window structure. However, this round about way of + * doing things makes the single user interface bug-for-bug compatible with + * the multi-user interface. + */ + + nxfe_reportposition((FAR struct nxbe_window_s *)hwnd); + return OK; +} diff --git a/nuttx/graphics/nxsu/nx_getrectangle.c b/nuttx/graphics/nxsu/nx_getrectangle.c new file mode 100644 index 0000000000..472ff4c6c5 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_getrectangle.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * graphics/nxsu/nx_getrectangle.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_getrectangle + * + * Description: + * Get the raw contents of graphic memory within a rectangular region. NOTE: + * Since raw graphic memory is returned, the returned memory content may be + * the memory of windows above this one and may not necessarily belong to + * this window unless you assure that this is the top window. + * + * Input Parameters: + * wnd - The window structure reference + * rect - The location to be copied + * plane - Specifies the color plane to get from. + * dest - The location to copy the memory region + * deststride - The width, in bytes, the the dest memory + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_getrectangle(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, + unsigned int plane, FAR uint8_t *dest, + unsigned int deststride) +{ +#ifdef CONFIG_DEBUG + if (!hwnd || !rect || !dest) + { + set_errno(EINVAL); + return ERROR; + } +#endif + + nxbe_getrectangle((FAR struct nxbe_window_s *)hwnd, rect, plane, + dest, deststride); + return OK; +} diff --git a/nuttx/graphics/nxsu/nx_kbdchin.c b/nuttx/graphics/nxsu/nx_kbdchin.c new file mode 100644 index 0000000000..7ecea5db95 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_kbdchin.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * graphics/nxsu/nx_kbdchin.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxfe.h" + +#ifdef CONFIG_NX_KBD + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_kbdchin + * + * Description: + * Used by a thread or interrupt handler that manages some kind of keypad + * hardware to report text information to the NX server. That text + * data will be routed by the NX server to the appropriate window client. + * + ****************************************************************************/ + +int nx_kbdchin(NXHANDLE handle, uint8_t ch) +{ + FAR struct nxfe_state_s *fe = (FAR struct nxfe_state_s *)handle; + FAR struct nxbe_window_s *wnd = fe->be.topwnd; + + /* Give the keypad event only to the top window (unless the top window + * is the background window). + */ + + if (wnd->cb->kbdin) + { + wnd->cb->kbdin(wnd, 1, &ch, wnd->arg); + } + return OK; +} + +#endif /* CONFIG_NX_KBD */ diff --git a/nuttx/graphics/nxsu/nx_kbdin.c b/nuttx/graphics/nxsu/nx_kbdin.c new file mode 100644 index 0000000000..9fc8460bdd --- /dev/null +++ b/nuttx/graphics/nxsu/nx_kbdin.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * graphics/nxsu/nx_kbdin.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxfe.h" + +#ifdef CONFIG_NX_KBD + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_kbdin + * + * Description: + * Used by a thread or interrupt handler that manages some kind of keypad + * hardware to report text information to the NX server. + * + ****************************************************************************/ + +int nx_kbdin(NXHANDLE handle, uint8_t nch, FAR const uint8_t *ch) +{ + FAR struct nxfe_state_s *fe = (FAR struct nxfe_state_s *)handle; + FAR struct nxbe_window_s *wnd = fe->be.topwnd; + + /* Give the keypad event only to the top window (unless the top child + * is the background window). + */ + + if (wnd->cb->kbdin) + { + wnd->cb->kbdin(wnd, nch, ch, wnd->arg); + } + return OK; +} + +#endif /* CONFIG_NX_KBD */ diff --git a/nuttx/graphics/nxsu/nx_lower.c b/nuttx/graphics/nxsu/nx_lower.c new file mode 100644 index 0000000000..dbfd278c41 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_lower.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * graphics/nxsu/nx_lower.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_raise + * + * Description: + * Lower the specified window to the bottom of the display. + * + * Input parameters: + * hwnd - the window to be lowered + * + * Returned value: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_lower(NXWINDOW hwnd) +{ +#ifdef CONFIG_DEBUG + if (!hwnd) + { + errno = EINVAL; + return ERROR; + } +#endif + + nxbe_lower((FAR struct nxbe_window_s *)hwnd); + return OK; +} + diff --git a/nuttx/graphics/nxsu/nx_mousein.c b/nuttx/graphics/nxsu/nx_mousein.c new file mode 100644 index 0000000000..bee4a22650 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_mousein.c @@ -0,0 +1,200 @@ +/**************************************************************************** + * graphics/nxsu/nx_mousein.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" + +#ifdef CONFIG_NX_MOUSE + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct nxgl_point_s g_mpos; +static struct nxgl_point_s g_mrange; +static uint8_t g_mbutton; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxsu_mouseinit + * + * Description: + * Initialize with the mouse in the center of the display + * + ****************************************************************************/ + +void nxsu_mouseinit(int x, int y) +{ + g_mrange.x = x; + g_mrange.y = y; + g_mpos.x = x / 2; + g_mpos.y = y / 2; + g_mbutton = 0; +} + +/**************************************************************************** + * Name: nxsu_mousereport + * + * Description: + * Report mouse position info to the specified window + * + * Input Parameters: + * wnd - The window to receive the mouse report + * + * Returned Value: + * 0: Mouse report sent; >0: Mouse report not sent; <0: An error occurred + * + ****************************************************************************/ + +int nxsu_mousereport(struct nxbe_window_s *wnd) +{ + struct nxgl_point_s relpos; + + /* Does this window support mouse callbacks? */ + + if (wnd->cb->mousein) + { + /* Yes.. Is the mouse position visible in this window? */ + + if (nxbe_visible(wnd, &g_mpos)) + { + /* Yes... Convert the mouse position to window relative coordinates */ + + nxgl_vectsubtract(&relpos, &g_mpos, &wnd->bounds.pt1); + wnd->cb->mousein((NXWINDOW)wnd, &relpos, g_mbutton, wnd->arg); + return OK; + } + } + + /* No error occurred, but the mouse report was not sent */ + + return 1; +} + +/**************************************************************************** + * Name: nx_mousein + * + * Description: + * Used by a thread or interrupt handler that manages some kind of pointing + * hardware to report new positional data to the NX server. That positional + * data will be routed by the NX server to the appropriate window client. + * + ****************************************************************************/ + +int nx_mousein(NXHANDLE handle, nxgl_coord_t x, nxgl_coord_t y, uint8_t buttons) +{ + FAR struct nxfe_state_s *fe = (FAR struct nxfe_state_s *)handle; + struct nxbe_window_s *wnd; + int ret; + + /* Clip x and y to within the bounding rectangle */ + + if (x < 0) + { + x = 0; + } + else if (x >= g_mrange.x) + { + x = g_mrange.x - 1; + } + + if (y < 0) + { + y = 0; + } + else if (y >= g_mrange.y) + { + y = g_mrange.y - 1; + } + + /* Look any change in values */ + + if (x != g_mpos.x || y != g_mpos.y || buttons != g_mbutton) + { + /* Update the mouse value */ + + g_mpos.x = x; + g_mpos.y = y; + g_mbutton = buttons; + + /* Pick the window to receive the mouse event. Start with + * the top window and go down. Step with the first window + * that gets the mouse report + */ + + for (wnd = fe->be.topwnd; wnd; wnd = wnd->below) + { + ret = nxsu_mousereport(wnd); + if (ret == 0) + { + break; + } + } + } + return OK; +} + +#endif /* CONFIG_NX_MOUSE */ diff --git a/nuttx/graphics/nxsu/nx_move.c b/nuttx/graphics/nxsu/nx_move.c new file mode 100644 index 0000000000..b16cf3525e --- /dev/null +++ b/nuttx/graphics/nxsu/nx_move.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * graphics/nxsu/nx_move.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_move + * + * Description: + * Move a rectangular region within the window + * + * Input Parameters: + * hwnd - The window within which the move is to be done + * rect - Describes the rectangular region to move + * offset - The offset to move the region + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_move(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset) +{ +#ifdef CONFIG_DEBUG + if (!hwnd) + { + errno = EINVAL; + return ERROR; + } +#endif + + nxbe_move((FAR struct nxbe_window_s *)hwnd, rect, offset); + return OK; +} diff --git a/nuttx/graphics/nxsu/nx_open.c b/nuttx/graphics/nxsu/nx_open.c new file mode 100644 index 0000000000..f5e07dc5ec --- /dev/null +++ b/nuttx/graphics/nxsu/nx_open.c @@ -0,0 +1,218 @@ +/**************************************************************************** + * graphics/nxsu/nx_open.c + * + * Copyright (C) 2008-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void nxsu_bkgdredraw(NXWINDOW hwnd, + FAR const struct nxgl_rect_s *rect, + bool more, FAR void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct nx_callback_s g_bkgdcb = +{ + nxsu_bkgdredraw, /* redraw */ + NULL /* position */ +#ifdef CONFIG_NX_MOUSE + , NULL /* mousein */ +#endif +#ifdef CONFIG_NX_KBD + , NULL /* my kbdin */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxsu_bkgdredraw + ****************************************************************************/ + +static void nxsu_bkgdredraw(NXWINDOW hwnd, + FAR const struct nxgl_rect_s *rect, + bool more, FAR void *arg) +{ + FAR struct nxbe_window_s *wnd = (FAR struct nxbe_window_s *)hwnd; + FAR struct nxbe_state_s *be = wnd->be; + + gvdbg("BG redraw rect={(%d,%d),(%d,%d)}\n", + rect->pt1.x, rect->pt1.y, rect->pt2.x, rect->pt2.y); + nxbe_fill(wnd, &wnd->bounds, be->bgcolor); +} + +/**************************************************************************** + * Name: nxsu_setup + ****************************************************************************/ + +static inline int nxsu_setup(FAR NX_DRIVERTYPE *dev, + FAR struct nxfe_state_s *fe) +{ + int ret; + + /* Configure the framebuffer device */ + + ret = nxbe_configure(dev, &fe->be); + if (ret < 0) + { + gdbg("nxbe_configure failed: %d\n", -ret); + errno = -ret; + return ERROR; + } + +#if CONFIG_FB_CMAP + ret = nxbe_colormap(dev); + if (ret < 0) + { + gdbg("nxbe_colormap failed: %d\n", -ret); + errno = -ret; + return ERROR; + } +#endif + + /* Initialize the non-NULL elements of the back-end structure window */ + /* Initialize the background window */ + + fe->be.bkgd.be = &fe->be; + fe->be.bkgd.cb = &g_bkgdcb; + + fe->be.bkgd.bounds.pt2.x = fe->be.vinfo.xres - 1; + fe->be.bkgd.bounds.pt2.y = fe->be.vinfo.yres - 1; + + /* Complete initialization of the server state structure. The + * window list contains only one element: The background window + * with nothing else above or below it + */ + + fe->be.topwnd = &fe->be.bkgd; + + /* Initialize the mouse position */ + +#ifdef CONFIG_NX_MOUSE + nxsu_mouseinit(fe->be.vinfo.xres, fe->be.vinfo.yres); +#endif + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_open + * + * Description: + * Create, initialize and return an NX handle for use in subsequent + * NX API calls. nx_open is the single user equivalent of nx_connect + * plus nx_run. + * + * Input Parameters: + * dev - Vtable "object" of the framebuffer/LCD "driver" to use + * + * Return: + * Success: A non-NULL handle used with subsequent NX accesses + * Failure: NULL is returned and errno is set appropriately + * + ****************************************************************************/ + +NXHANDLE nx_open(FAR NX_DRIVERTYPE *dev) +{ + FAR struct nxfe_state_s *fe; + int ret; + + /* Sanity checking */ + +#ifdef CONFIG_DEBUG + if (!dev) + { + errno = EINVAL; + return NULL; + } +#endif + + /* Allocate the NX state structure */ + + fe = (FAR struct nxfe_state_s *)zalloc(sizeof(struct nxfe_state_s)); + if (!fe) + { + errno = ENOMEM; + return NULL; + } + + /* Initialize and configure the server */ + + ret = nxsu_setup(dev, fe); + if (ret < 0) + { + return NULL; /* nxsu_setup sets errno */ + } + + /* Fill the initial background window */ + + nxbe_fill(&fe->be.bkgd, &fe->be.bkgd.bounds, fe->be.bgcolor); + return (NXHANDLE)fe; +} + diff --git a/nuttx/graphics/nxsu/nx_openwindow.c b/nuttx/graphics/nxsu/nx_openwindow.c new file mode 100644 index 0000000000..64f4ed76dd --- /dev/null +++ b/nuttx/graphics/nxsu/nx_openwindow.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * graphics/nxsu/nx_openwindow.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_openwindow + * + * Description: + * Create a new window. + * + * Input Parameters: + * handle - The handle returned by nx_connect + * cb - Callbacks used to process windo events + * arg - User provided value that will be returned with NX callbacks. + * + * Return: + * Success: A non-NULL handle used with subsequent NX accesses + * Failure: NULL is returned and errno is set appropriately + * + ****************************************************************************/ + +NXWINDOW nx_openwindow(NXHANDLE handle, FAR const struct nx_callback_s *cb, + FAR void *arg) +{ + FAR struct nxbe_window_s *wnd; + int ret; + +#ifdef CONFIG_DEBUG + if (!handle || !cb) + { + errno = EINVAL; + return NULL; + } +#endif + + /* Pre-allocate the window structure */ + + wnd = (FAR struct nxbe_window_s *)zalloc(sizeof(struct nxbe_window_s)); + if (!wnd) + { + errno = ENOMEM; + return NULL; + } + + /* Then let nxfe_constructwindow do the rest */ + + ret = nxfe_constructwindow(handle, wnd, cb, arg); + if (ret < 0) + { + /* An error occurred, the window has been freed */ + + return NULL; + } + + /* Return the initialized window reference */ + + return (NXWINDOW)wnd; +} + diff --git a/nuttx/graphics/nxsu/nx_raise.c b/nuttx/graphics/nxsu/nx_raise.c new file mode 100644 index 0000000000..cf4e38b64c --- /dev/null +++ b/nuttx/graphics/nxsu/nx_raise.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * graphics/nxsu/nx_raise.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_raise + * + * Description: + * Bring the specified window to the top of the display. + * + * Input parameters: + * hwnd - the window to be raised + * + * Returned value: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_raise(NXWINDOW hwnd) +{ +#ifdef CONFIG_DEBUG + if (!hwnd) + { + errno = EINVAL; + return ERROR; + } +#endif + + nxbe_raise((FAR struct nxbe_window_s *)hwnd); + return OK; +} + diff --git a/nuttx/graphics/nxsu/nx_releasebkgd.c b/nuttx/graphics/nxsu/nx_releasebkgd.c new file mode 100644 index 0000000000..b0cbbf5c16 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_releasebkgd.c @@ -0,0 +1,109 @@ +/**************************************************************************** + * graphics/nxsu/nx_releasebkgd.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_releasebkgd + * + * Description: + * Release the background window previously acquired using nx_openbgwindow + * and return control of the background to NX. + * + * Input Parameters: + * hwnd - The handle returned (indirectly) by nx_requestbkgd + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_releasebkgd(NXWINDOW hwnd) +{ + FAR struct nxbe_window_s *bkgd = (FAR struct nxbe_window_s *)hwnd; + +#ifdef CONFIG_DEBUG + if (!bkgd) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Restore the NX background window callbacks */ + + bkgd->cb = &g_bkgdcb; + bkgd->arg = NULL; + + /* Redraw the background window */ + + nxfe_redrawreq(bkgd, &bkgd->bounds); + return OK; +} + diff --git a/nuttx/graphics/nxsu/nx_requestbkgd.c b/nuttx/graphics/nxsu/nx_requestbkgd.c new file mode 100644 index 0000000000..5bd4554bc9 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_requestbkgd.c @@ -0,0 +1,155 @@ +/**************************************************************************** + * graphics/nxsu/nx_requestbkgd.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_requestbkgd + * + * Description: + * NX normally controls a separate window called the background window. + * It repaints the window as necessary using only a solid color fill. The + * background window always represents the entire screen and is always + * below other windows. It is useful for an application to control the + * background window in the following conditions: + * + * - If you want to implement a windowless solution. The single screen + * can be used to creat a truly simple graphic environment. In this + * case, you should probably also de-select CONFIG_NX_MULTIUSER as well. + * - When you want more on the background than a solid color. For + * example, if you want an image in the background, or animations in the + * background, or live video, etc. + * + * This API only requests the handle of the background window. That + * handle will be returned asynchronously in a subsequent position and + * redraw callbacks. + * + * Cautions: + * - The following should never be called using the background window. + * They are guaranteed to cause severe crashes: + * + * nx_setposition, nx_setsize, nx_raise, nx_lower. + * + * - Neither nx_opengbwindow or nx_closebgwindow should be called more than + * once. Multiple instances of the background window are not supported. + * + * Input Parameters: + * handle - The handle returned by nx_connect + * cb - Callbacks to use for processing background window events + * arg - User provided argument (see nx_openwindow, nx_constructwindow) + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_requestbkgd(NXHANDLE handle, FAR const struct nx_callback_s *cb, + FAR void *arg) +{ + FAR struct nxfe_state_s *fe = (FAR struct nxfe_state_s *)handle; + FAR struct nxbe_state_s *be = &fe->be; + +#ifdef CONFIG_DEBUG + if (!fe || !cb) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Replace the NX background windo callbacks with the client's callbacks */ + + be->bkgd.cb = cb; + be->bkgd.arg = arg; + + /* Report the size/position of the background window to the client */ + + nxfe_reportposition((NXWINDOW)&be->bkgd); + + /* Redraw the background window */ + + nxfe_redrawreq(&be->bkgd, &be->bkgd.bounds); + + /* Provide the mouse settings to the client */ + +#ifdef CONFIG_NX_MOUSE + nxsu_mousereport(&be->bkgd); +#endif + + /* In this single-user mode, we could return the background window + * handle here. However, we cannot do that in the multi-user case + * because that handle is known only to the server. Instead, the + * background window handle is returned to the client via a redraw + * callback. So we will do the same in the single-user case for + * compatibility. + */ + + return OK; +} + diff --git a/nuttx/graphics/nxsu/nx_setbgcolor.c b/nuttx/graphics/nxsu/nx_setbgcolor.c new file mode 100644 index 0000000000..d8c2159efa --- /dev/null +++ b/nuttx/graphics/nxsu/nx_setbgcolor.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * graphics/nxsu/nx_setbgcolor.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_setbgcolor + * + * Description: + * Set the color of the background + * + * Input Parameters: + * handle - The connection handle + * color - The color to use in the background + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_setbgcolor(NXHANDLE handle, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + FAR struct nxfe_state_s *fe = (FAR struct nxfe_state_s *)handle; + +#ifdef CONFIG_DEBUG + if (!fe) + { + errno = EINVAL; + return ERROR; + } +#endif + + nxgl_colorcopy(fe->be.bgcolor, color); + nxbe_fill(&fe->be.bkgd, &fe->be.bkgd.bounds, color); + return OK; +} diff --git a/nuttx/graphics/nxsu/nx_setpixel.c b/nuttx/graphics/nxsu/nx_setpixel.c new file mode 100644 index 0000000000..533e3b623c --- /dev/null +++ b/nuttx/graphics/nxsu/nx_setpixel.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * graphics/nxsu/nx_setpixel.c + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_setpixel + * + * Description: + * Set a single pixel in the window to the specified color. This is simply + * a degenerate case of nx_fill(), but may be optimized in some architectures. + * + * Input Parameters: + * wnd - The window structure reference + * pos - The pixel location to be set + * col - The color to use in the set + * + * Return: + * None + * + ****************************************************************************/ + +int nx_setpixel(NXWINDOW hwnd, FAR const struct nxgl_point_s *pos, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ +#ifdef CONFIG_DEBUG + if (!hwnd || !pos || !color) + { + errno = EINVAL; + return ERROR; + } +#endif + + nxbe_setpixel((FAR struct nxbe_window_s *)hwnd, pos, color); + return 0; +} diff --git a/nuttx/graphics/nxsu/nx_setposition.c b/nuttx/graphics/nxsu/nx_setposition.c new file mode 100644 index 0000000000..ed0e5e3f47 --- /dev/null +++ b/nuttx/graphics/nxsu/nx_setposition.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * graphics/nxsu/nx_setposition.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_setposition + * + * Description: + * Set the position and size for the selected window + * + * Input Parameters: + * hwnd - The window handle + * pos - The new position of the window + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_setposition(NXWINDOW hwnd, FAR const struct nxgl_point_s *pos) +{ +#ifdef CONFIG_DEBUG + if (!hwnd || !pos) + { + errno = EINVAL; + return ERROR; + } +#endif + + nxbe_setposition((FAR struct nxbe_window_s *)hwnd, pos); + return OK; +} diff --git a/nuttx/graphics/nxsu/nx_setsize.c b/nuttx/graphics/nxsu/nx_setsize.c new file mode 100644 index 0000000000..171e26faed --- /dev/null +++ b/nuttx/graphics/nxsu/nx_setsize.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * graphics/nxsu/nx_setsize.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_setsize + * + * Description: + * Set the size of the selected window + * + * Input Parameters: + * hwnd - The window handle + * size - The new size of the window. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_setsize(NXWINDOW hwnd, FAR const struct nxgl_size_s *size) +{ +#ifdef CONFIG_DEBUG + if (!hwnd || !size) + { + errno = EINVAL; + return ERROR; + } +#endif + + nxbe_setsize((FAR struct nxbe_window_s *)hwnd, size); + return OK; +} diff --git a/nuttx/graphics/nxsu/nxfe.h b/nuttx/graphics/nxsu/nxfe.h new file mode 100644 index 0000000000..59f5b7e61c --- /dev/null +++ b/nuttx/graphics/nxsu/nxfe.h @@ -0,0 +1,185 @@ +/**************************************************************************** + * graphics/nxsu/nxfe.h + * + * Copyright (C) 2008-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXSU_NXFE_H +#define __GRAPHICS_NXSU_NXFE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "nxbe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Server state structure ***************************************************/ + +/* This the server 'front-end' state structure. It is really the same + * as the back-end state, but we wrap the back-end state so that we can add + * things to the structure in the future + */ + +struct nxfe_state_s +{ + /* The 'back-end' window status. Must be first so that instances of + * struct nxbe_state_s can be simply cast to an instance of struct + * nxfe_state_s + */ + + struct nxbe_state_s be; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN const struct nx_callback_s g_bkgdcb; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxfe_constructwindow + * + * Description: + * This function is the same a nx_openwindow EXCEPT that the client provides + * the window structure instance. nx_constructwindow will initialize the + * the pre-allocated window structure for use by NX. This function is + * provided in addition to nx_open window in order to support a kind of + * inheritance: The caller's window structure may include extensions that + * are not visible to NX. + * + * NOTE: wnd must have been allocated using malloc() (or related allocators) + * Once provided to nxfe_constructwindow() that memory is owned and managed + * by NX. On certain error conditions or when the window is closed, NX will + * free() the window. + * + * Input Parameters: + * handle - The handle returned by nx_connect + * wnd - The pre-allocated window structure. + * cb - Callbacks used to process window events + * arg - User provided value that will be returned with NX callbacks. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately. In the + * case of ERROR, NX will have dealloated the pre-allocated window. + * + ****************************************************************************/ + +EXTERN int nxfe_constructwindow(NXHANDLE handle, + FAR struct nxbe_window_s *wnd, + FAR const struct nx_callback_s *cb, + FAR void *arg); + +/**************************************************************************** + * Name: nxfe_redrawreq + * + * Descripton: + * Request the client that has this window to redraw the rectangular region. + * + ****************************************************************************/ + +EXTERN void nxfe_redrawreq(FAR struct nxbe_window_s *wnd, + FAR const struct nxgl_rect_s *rect); + +/**************************************************************************** + * Name: nxfe_reportposition + * + * Descripton: + * Report the new size/position of the window. + * + ****************************************************************************/ + +EXTERN void nxfe_reportposition(FAR struct nxbe_window_s *wnd); + +/**************************************************************************** + * Name: nxmu_mouseinit + * + * Description: + * Initialize with the mouse in the center of the display + * + ****************************************************************************/ + +#ifdef CONFIG_NX_MOUSE +EXTERN void nxsu_mouseinit(int x, int y); +#endif + +/**************************************************************************** + * Name: nxmu_mousereport + * + * Description: + * Report mouse position info to the specified window + * + * Input Parameters: + * wnd - The window to receive the mouse report + * + * Returned Value: + * 0: Mouse report sent; >0: Mouse report not sent; <0: An error occurred + * + ****************************************************************************/ + +#ifdef CONFIG_NX_MOUSE +EXTERN int nxsu_mousereport(struct nxbe_window_s *wnd); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXSU_NXFE_H */ + diff --git a/nuttx/graphics/nxsu/nxsu_constructwindow.c b/nuttx/graphics/nxsu/nxsu_constructwindow.c new file mode 100644 index 0000000000..f812b3f839 --- /dev/null +++ b/nuttx/graphics/nxsu/nxsu_constructwindow.c @@ -0,0 +1,150 @@ +/**************************************************************************** + * graphics/nxsu/nx_openwindow.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxfe_constructwindow + * + * Description: + * This function is the same a nx_openwindow EXCEPT that the client provides + * the window structure instance. nx_constructwindow will initialize the + * the pre-allocated window structure for use by NX. This function is + * provided in addition to nx_open window in order to support a kind of + * inheritance: The caller's window structure may include extensions that + * are not visible to NX. + * + * NOTE: wnd must have been allocated using malloc() (or related allocators) + * Once provided to nxfe_constructwindow() that memory is owned and managed + * by NX. On certain error conditions or when the window is closed, NX will + * free() the window. + * + * Input Parameters: + * handle - The handle returned by nx_connect + * wnd - The pre-allocated window structure. + * cb - Callbacks used to process window events + * arg - User provided value that will be returned with NX callbacks. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately. In the + * case of ERROR, NX will have dealloated the pre-allocated window. + * + ****************************************************************************/ + +int nxfe_constructwindow(NXHANDLE handle, FAR struct nxbe_window_s *wnd, + FAR const struct nx_callback_s *cb, FAR void *arg) +{ + FAR struct nxfe_state_s *fe = (FAR struct nxfe_state_s *)handle; + FAR struct nxbe_state_s *be = &fe->be; + +#ifdef CONFIG_DEBUG + if (!wnd) + { + errno = EINVAL; + return ERROR; + } + + if (!fe || !cb) + { + free(wnd); + errno = EINVAL; + return ERROR; + } +#endif + + /* Initialize the window structure */ + + wnd->be = be; + wnd->cb = cb; + wnd->arg = arg; + + /* Insert the new window at the top on the display. topwnd is + * never NULL (it may point only at the background window, however) + */ + + wnd->above = NULL; + wnd->below = be->topwnd; + + be->topwnd->above = wnd; + be->topwnd = wnd; + + /* Report the initialize size/position of the window */ + + nxfe_reportposition((NXWINDOW)wnd); + + /* Provide the initial mouse settings */ + +#ifdef CONFIG_NX_MOUSE + nxsu_mousereport(wnd); +#endif + + return OK; +} + diff --git a/nuttx/graphics/nxsu/nxsu_redrawreq.c b/nuttx/graphics/nxsu/nxsu_redrawreq.c new file mode 100644 index 0000000000..9efa828a51 --- /dev/null +++ b/nuttx/graphics/nxsu/nxsu_redrawreq.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * graphics/nxsu/nxsu_redrawreq.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxfe_redrawreq + * + * Descripton: + * Request the client that has this window to redraw the rectangular region. + * + ****************************************************************************/ + +void nxfe_redrawreq(FAR struct nxbe_window_s *wnd, FAR const struct nxgl_rect_s *rect) +{ + struct nxgl_rect_s relrect; + +#ifdef CONFIG_DEBUG + if (!wnd) + { + return; + } +#endif + + if (wnd->cb->redraw) + { + /* Convert the frame rectangle to a window-relative rectangle */ + + nxgl_rectoffset(&relrect, rect, -wnd->bounds.pt1.x, -wnd->bounds.pt1.y); + + /* And request the redraw */ + + wnd->cb->redraw((NXWINDOW)wnd, &relrect, false, wnd->arg); + } +} + + diff --git a/nuttx/graphics/nxsu/nxsu_reportposition.c b/nuttx/graphics/nxsu/nxsu_reportposition.c new file mode 100644 index 0000000000..d87dac0f6b --- /dev/null +++ b/nuttx/graphics/nxsu/nxsu_reportposition.c @@ -0,0 +1,107 @@ +/**************************************************************************** + * graphics/nxsu/nxsu_reportposition.c + * + * Copyright (C) 2008-2009,2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include "nxfe.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxfe_reportposition + * + * Descripton: + * Report the new size/position of the window. + * + ****************************************************************************/ + +void nxfe_reportposition(FAR struct nxbe_window_s *wnd) +{ + FAR struct nxbe_state_s *be; + struct nxgl_size_s size; + +#ifdef CONFIG_DEBUG + if (!wnd) + { + return; + } +#endif + be = wnd->be; + + /* This is very awkward in single user mode, but at least it is compatible. + * with the way things are done in multiple user mode. + */ + + if (wnd->cb->position) + { + /* Get the size of the bounding rectangle */ + + nxgl_rectsize(&size, &wnd->bounds); + + /* And provide this to the client */ + + wnd->cb->position(wnd, &size, &wnd->bounds.pt1, &be->bkgd.bounds, wnd->arg); + } +} diff --git a/nuttx/graphics/nxtk/Make.defs b/nuttx/graphics/nxtk/Make.defs new file mode 100644 index 0000000000..cc744309f4 --- /dev/null +++ b/nuttx/graphics/nxtk/Make.defs @@ -0,0 +1,48 @@ +############################################################################ +# graphics/nxtk/Make.defs +# +# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +NXTK_ASRCS = +NXTKWIN_CSRCS = nxtk_openwindow.c nxtk_closewindow.c nxtk_getposition.c \ + nxtk_setposition.c nxtk_setsize.c nxtk_raise.c nxtk_lower.c \ + nxtk_fillwindow.c nxtk_getwindow.c nxtk_filltrapwindow.c \ + nxtk_movewindow.c nxtk_bitmapwindow.c nxtk_events.c \ + nxtk_setsubwindows.c nxtk_drawcirclewindow.c nxtk_drawlinewindow.c \ + nxtk_fillcirclewindow.c nxtk_block.c +NXTKTB_CSRCS = nxtk_opentoolbar.c nxtk_closetoolbar.c nxtk_filltoolbar.c \ + nxtk_gettoolbar.c nxtk_filltraptoolbar.c nxtk_movetoolbar.c \ + nxtk_bitmaptoolbar.c nxtk_drawcircletoolbar.c nxtk_drawlinetoolbar.c \ + nxtk_fillcircletoolbar.c nxtk_toolbarbounds.c +NXTK_CSRCS = $(NXTKWIN_CSRCS) $(NXTKTB_CSRCS) nxtk_subwindowclip.c \ + nxtk_containerclip.c nxtk_subwindowmove.c nxtk_drawframe.c diff --git a/nuttx/graphics/nxtk/nxtk_bitmaptoolbar.c b/nuttx/graphics/nxtk/nxtk_bitmaptoolbar.c new file mode 100644 index 0000000000..50bd5aff40 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_bitmaptoolbar.c @@ -0,0 +1,137 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_bitmaptoolbar.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_bitmaptoolbar + * + * Description: + * Copy a rectangular region of a larger image into the rectangle in the + * specified toolbar sub-window. + * + * Input Parameters: + * hfwnd - The sub-window twhose toolbar will receive the bitmap image + * dest - Describes the rectangular region on in the toolbar sub-window + * will receive the bit map. + * src - The start of the source image. + * origin - The origin of the upper, left-most corner of the full bitmap. + * Both dest and origin are in sub-window coordinates, however, the + * origin may lie outside of the sub-window display. + * stride - The width of the full source image in pixels. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_bitmaptoolbar(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, unsigned int stride) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + struct nxgl_point_s wndorigin; + struct nxgl_rect_s clipdest; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !dest || !src || !origin) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Clip the rectangle so that it lies within the sub-window bounds + * then move the rectangle to that it is relative to the containing + * window. + */ + + nxtk_subwindowclip(fwnd, &clipdest, dest, &fwnd->tbrect); + + /* Now, move the bitmap origin so that it is relative to the containing + * window, not the sub-window. + * + * Temporarily, position the origin in absolute screen coordinates + */ + + nxgl_vectoradd(&wndorigin, origin, &fwnd->tbrect.pt1); + + /* Then move the origin so that is relative to the containing window, not the + * client subwindow + */ + + nxgl_vectsubtract(&wndorigin, &wndorigin, &fwnd->wnd.bounds.pt1); + + /* Then copy the bitmap */ + + nx_bitmap((NXWINDOW)hfwnd, &clipdest, src, &wndorigin, stride); + return OK; +} diff --git a/nuttx/graphics/nxtk/nxtk_bitmapwindow.c b/nuttx/graphics/nxtk/nxtk_bitmapwindow.c new file mode 100644 index 0000000000..a439f5f797 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_bitmapwindow.c @@ -0,0 +1,137 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_bitmapwindow.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_bitmapwindow + * + * Description: + * Copy a rectangular region of a larger image into the rectangle in the + * specified client sub-window. + * + * Input Parameters: + * hfwnd The client sub0window that will receive the bitmap image + * dest - Describes the rectangular region on in the client sub-window + * will receive the bit map. + * src - The start of the source image. + * origin - The origin of the upper, left-most corner of the full bitmap. + * Both dest and origin are in sub-window coordinates, however, the + * origin may lie outside of the sub-window display. + * stride - The width of the full source image in pixels. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_bitmapwindow(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *dest, + FAR const void **src, + FAR const struct nxgl_point_s *origin, unsigned int stride) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + struct nxgl_point_s wndorigin; + struct nxgl_rect_s clipdest; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !dest || !src || !origin) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Clip the rectangle so that it lies within the sub-window bounds + * then move the rectangle to that it is relative to the containing + * window. + */ + + nxtk_subwindowclip(fwnd, &clipdest, dest, &fwnd->fwrect); + + /* Now, move the bitmap origin so that it is relative to the containing + * window, not the sub-window. + * + * Temporarily, position the origin in absolute screen coordinates + */ + + nxgl_vectoradd(&wndorigin, origin, &fwnd->fwrect.pt1); + + /* Then move the origin so that is relative to the containing window, not the + * client subwindow + */ + + nxgl_vectsubtract(&wndorigin, &wndorigin, &fwnd->wnd.bounds.pt1); + + /* Then copy the bitmap */ + + nx_bitmap((NXWINDOW)hfwnd, &clipdest, src, &wndorigin, stride); + return OK; +} diff --git a/nuttx/graphics/nxtk/nxtk_block.c b/nuttx/graphics/nxtk/nxtk_block.c new file mode 100644 index 0000000000..11baf7f4f4 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_block.c @@ -0,0 +1,109 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_block.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "nxfe.h" + +#ifdef CONFIG_NX_MULTIUSER + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_block + * + * Description: + * This is callback will do to things: (1) any queue a 'blocked' callback + * to the window and then (2) block any further window messaging. + * + * The 'blocked' callback is the response from nx_block (or nxtk_block). + * Those blocking interfaces are used to assure that no further messages are + * are directed to the window. Receipt of the blocked callback signifies + * that (1) there are no further pending callbacks and (2) that the + * window is now 'defunct' and will receive no further callbacks. + * + * This callback supports coordinated destruction of a window in multi- + * user mode. In multi-use mode, the client window logic must stay + * intact until all of the queued callbacks are processed. Then the + * window may be safely closed. Closing the window prior with pending + * callbacks can lead to bad behavior when the callback is executed. + * + * Multiple user mode only! + * + * Input Parameters: + * hfwnd - The window to be blocked + * arg - An argument that will accompany the block messages (This is arg2 + * in the blocked callback). + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_block(NXTKWINDOW hfwnd, FAR void *arg) +{ + return nx_block((NXWINDOW)hfwnd, arg); +} + +#endif /* CONFIG_NX_MULTIUSER */ diff --git a/nuttx/graphics/nxtk/nxtk_closetoolbar.c b/nuttx/graphics/nxtk/nxtk_closetoolbar.c new file mode 100644 index 0000000000..dff621a44f --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_closetoolbar.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_closetoolbar.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_closetoolbar + * + * Description: + * Create a tool bar at the top of the specified framed window + * + * Input Parameters: + * hfwnd - The handle returned by nxtk_openwindow + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_closetoolbar(NXTKWINDOW hfwnd) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + + /* Un-initialize the toolbar info */ + + fwnd->tbheight = 0; + fwnd->tbcb = NULL; + fwnd->tbarg = NULL; + + /* Calculate the new dimensions of the client window */ + + nxtk_setsubwindows(fwnd); + + /* Then redraw the entire window, even the client window must be + * redraw because it has changed its vertical position and size. + */ + + nxfe_redrawreq(&fwnd->wnd, &fwnd->wnd.bounds); + return OK; +} + diff --git a/nuttx/graphics/nxtk/nxtk_closewindow.c b/nuttx/graphics/nxtk/nxtk_closewindow.c new file mode 100644 index 0000000000..e921f669e0 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_closewindow.c @@ -0,0 +1,95 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_closewindow.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_closewindow + * + * Description: + * Close the window opened by nxtk_openwindow + * + * Input Parameters: + * hfwnd - The handle returned by nxtk_openwindow + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_closewindow(NXTKWINDOW hfwnd) +{ + return nx_closewindow((NXWINDOW)hfwnd); +} + diff --git a/nuttx/graphics/nxtk/nxtk_containerclip.c b/nuttx/graphics/nxtk/nxtk_containerclip.c new file mode 100644 index 0000000000..3671851f17 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_containerclip.c @@ -0,0 +1,122 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_containerclip.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_containerclip + * + * Description: + * We are given a 'src' rectangle in containing window, relative coordinates + * (i.e., (0,0) is the top left corner of the outer, containing window). + * This function will (1) clip that src rectangle so that it lies within + * the sub-window bounds, and then (2) move the rectangle to that it is + * relative to the sub-window (i.e., (0,0) is the top left corner of the + * sub-window). + * + * Input parameters: + * fwnd - The framed window to be used + * dest - The locaton to put the result + * src - The src rectangle in relative container-window coordinates + * bounds - The subwindow bounds in absolute screen coordinates. + * + * Returned value: + * None + * + ****************************************************************************/ + +void nxtk_containerclip(FAR struct nxtk_framedwindow_s *fwnd, + FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src, + FAR const struct nxgl_rect_s *bounds) +{ + struct nxgl_rect_s relbounds; + + /* The 'src' rectangle is relative to the containing window. Convert + * the sub-window to the same origin. + */ + + nxgl_rectoffset(&relbounds, bounds, -fwnd->wnd.bounds.pt1.x, + -fwnd->wnd.bounds.pt1.y); + + /* The interection then leaves the portion of the containing window that + * needs to be updated window that needs to be updated. + */ + + nxgl_rectintersect(dest, src, &relbounds); + + /* Offset this so that is relative to client subwindow origin */ + + nxgl_rectoffset(dest, dest, fwnd->wnd.bounds.pt1.x - bounds->pt1.x, + fwnd->wnd.bounds.pt1.y - bounds->pt1.y); +} diff --git a/nuttx/graphics/nxtk/nxtk_drawcircletoolbar.c b/nuttx/graphics/nxtk/nxtk_drawcircletoolbar.c new file mode 100644 index 0000000000..e9d9ca8ffb --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_drawcircletoolbar.c @@ -0,0 +1,145 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_drawcircletoolbar.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Named indices into the 16 circle points generated by nxgl_circlepts */ + +#define POINT_0p0 0 +#define POINT_22p5 1 +#define POINT_45p0 2 +#define POINT_67p5 3 +#define POINT_90p0 4 +#define POINT_112p5 5 +#define POINT_135p0 6 +#define POINT_157p5 7 +#define POINT_180p0 8 +#define POINT_202p5 9 +#define POINT_225p0 10 +#define POINT_247p5 11 +#define POINT_270p0 12 +#define POINT_292p5 13 +#define POINT_315p0 14 +#define POINT_337p5 15 +#define NCIRCLE_POINTS 16 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_drawcircletoolbar + * + * Description: + * Draw a circular outline using the specified line thickness and color. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow() + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_drawcircletoolbar(NXTKWINDOW hfwnd, FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, nxgl_coord_t width, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + struct nxgl_point_s pts[NCIRCLE_POINTS]; + FAR struct nxgl_vector_s vector; + int i; + int ret; + + /* Convert the circle to a set of 16 points */ + + nxgl_circlepts(center, radius, pts); + + /* Draw each pair of points as a vector */ + + for (i = POINT_0p0; i < POINT_337p5; i++) + { + vector.pt1.x = pts[i].x; + vector.pt1.y = pts[i].y; + vector.pt2.x = pts[i+1].x; + vector.pt2.y = pts[i+1].y; + ret = nxtk_drawlinetoolbar(hfwnd, &vector, width, color); + if (ret != OK) + { + return ret; + } + } + + /* The final, closing vector is a special case */ + + vector.pt1.x = pts[POINT_337p5].x; + vector.pt1.y = pts[POINT_337p5].y; + vector.pt2.x = pts[POINT_0p0].x; + vector.pt2.y = pts[POINT_0p0].y; + return nxtk_drawlinetoolbar(hfwnd, &vector, width, color); +} diff --git a/nuttx/graphics/nxtk/nxtk_drawcirclewindow.c b/nuttx/graphics/nxtk/nxtk_drawcirclewindow.c new file mode 100644 index 0000000000..f70c1c3515 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_drawcirclewindow.c @@ -0,0 +1,145 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_drawcirclewindow.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Named indices into the 16 circle points generated by nxgl_circlepts */ + +#define POINT_0p0 0 +#define POINT_22p5 1 +#define POINT_45p0 2 +#define POINT_67p5 3 +#define POINT_90p0 4 +#define POINT_112p5 5 +#define POINT_135p0 6 +#define POINT_157p5 7 +#define POINT_180p0 8 +#define POINT_202p5 9 +#define POINT_225p0 10 +#define POINT_247p5 11 +#define POINT_270p0 12 +#define POINT_292p5 13 +#define POINT_315p0 14 +#define POINT_337p5 15 +#define NCIRCLE_POINTS 16 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_drawcirclewindow + * + * Description: + * Draw a circular outline using the specified line thickness and color. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow() + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_drawcirclewindow(NXTKWINDOW hfwnd, FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, nxgl_coord_t width, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + struct nxgl_point_s pts[NCIRCLE_POINTS]; + FAR struct nxgl_vector_s vector; + int i; + int ret; + + /* Convert the circle to a set of 16 points */ + + nxgl_circlepts(center, radius, pts); + + /* Draw each pair of points as a vector */ + + for (i = POINT_0p0; i < POINT_337p5; i++) + { + vector.pt1.x = pts[i].x; + vector.pt1.y = pts[i].y; + vector.pt2.x = pts[i+1].x; + vector.pt2.y = pts[i+1].y; + ret = nxtk_drawlinewindow(hfwnd, &vector, width, color); + if (ret != OK) + { + return ret; + } + } + + /* The final, closing vector is a special case */ + + vector.pt1.x = pts[POINT_337p5].x; + vector.pt1.y = pts[POINT_337p5].y; + vector.pt2.x = pts[POINT_0p0].x; + vector.pt2.y = pts[POINT_0p0].y; + return nxtk_drawlinewindow(hfwnd, &vector, width, color); +} diff --git a/nuttx/graphics/nxtk/nxtk_drawframe.c b/nuttx/graphics/nxtk/nxtk_drawframe.c new file mode 100644 index 0000000000..91745b3236 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_drawframe.c @@ -0,0 +1,310 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_drawframe.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_drawframeside + ****************************************************************************/ + +static void nxtk_drawframeside(FAR struct nxtk_framedwindow_s *fwnd, + FAR const struct nxgl_rect_s *side, + FAR const struct nxgl_rect_s *bounds, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + struct nxgl_rect_s intersection; + nxgl_rectintersect(&intersection, side, bounds); + if (!nxgl_nullrect(&intersection)) + { + nx_fill((NXWINDOW)fwnd, &intersection, color); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_drawframe + * + * Description: + * Redraw the window frame. + * + * Input parameters: + * fwnd - the framed window whose frame needs to be re-drawn. This must + * have been previously created by nxtk_openwindow(). + * bounds - Only draw the ports of the frame within this bounding box. + * (window relative coordinates). + * + * Returned value: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_drawframe(FAR struct nxtk_framedwindow_s *fwnd, + FAR const struct nxgl_rect_s *bounds) +{ + struct nxgl_rect_s frame; + struct nxgl_size_s wndsize; + struct nxgl_size_s tbsize; + nxgl_coord_t thickness; + + /* Shiny edge: + * Thickness: 1 + * Color: CONFIG_NXTK_BORDERCOLOR3; + * Condition: CONFIG_NXTK_BORDERWIDTH > 2 + * Central part: + * Thickness: Varies with CONFIG_NXTK_BORDERWIDTH + * Color: CONFIG_NXTK_BORDERCOLOR1; + * Condition: CONFIG_NXTK_BORDERWIDTH > 0 + * Shadow part: + * Thickness: 1; + * Color: CONFIG_NXTK_BORDERCOLOR2; + * Condition: CONFIG_NXTK_BORDERWIDTH > 1 + */ + +#if CONFIG_NXTK_BORDERWIDTH > 2 + thickness = CONFIG_NXTK_BORDERWIDTH - 2; +#elif CONFIG_NXTK_BORDERWIDTH > 1 + thickness = CONFIG_NXTK_BORDERWIDTH - 1; +#else + thickness = CONFIG_NXTK_BORDERWIDTH; +#endif + + /* Get the size of the rectangle */ + + nxgl_rectsize(&wndsize, &fwnd->wnd.bounds); + nxgl_rectsize(&tbsize, &fwnd->tbrect); + + /* Draw the top ***********************************************************/ + +#if CONFIG_NXTK_BORDERWIDTH > 0 + frame.pt1.x = 0; + frame.pt2.x = wndsize.w - 1; + frame.pt1.y = 0; + + /* Draw the shiny edge */ + +#if CONFIG_NXTK_BORDERWIDTH > 2 + frame.pt2.y = 0; + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor3); + frame.pt1.y = 1; +#endif + + /* Draw the central part */ + + frame.pt2.y = frame.pt1.y + thickness - 1; + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor1); + + /* Draw a single line under the toolbar, color CONFIG_NXTK_BORDERCOLOR2 */ + +#if CONFIG_NXTK_BORDERWIDTH > 1 + frame.pt1.y += tbsize.h + thickness; + frame.pt2.y = frame.pt1.y; + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor2); +#endif + + /* Draw the bottom ********************************************************/ + +#if CONFIG_NXTK_BORDERWIDTH > 0 + frame.pt1.y = wndsize.h - CONFIG_NXTK_BORDERWIDTH; + + /* Draw the shiny edge */ + +#if CONFIG_NXTK_BORDERWIDTH > 2 + frame.pt2.y = frame.pt1.y; + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor3); + frame.pt1.y ++; +#endif + + /* Draw the central part */ + + frame.pt2.y = frame.pt1.y + thickness - 1; + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor1); + + /* Then a single line at the very bottom, Color: CONFIG_NXTK_BORDERCOLOR2 */ + +#if CONFIG_NXTK_BORDERWIDTH > 1 + frame.pt1.y = wndsize.h - 1; + frame.pt2.y = frame.pt1.y; + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor2); +#endif +#endif + + /* Draw left and right outer edges *****************************************/ + + /* Draw the shiny left out edge */ + +#if CONFIG_NXTK_BORDERWIDTH > 1 + frame.pt1.x = 0; + frame.pt1.y = 1; +#if CONFIG_NXTK_BORDERWIDTH > 2 + frame.pt2.x = frame.pt1.x; + frame.pt2.y = wndsize.h - 2; + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor3); +#endif + + /* Draw the shadowed right outer edge */ + + frame.pt1.x = wndsize.w - 1; + frame.pt2.x = frame.pt1.x; + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor2); +#endif + + /* Draw left and right central regions *************************************/ + +#if CONFIG_NXTK_BORDERWIDTH > 2 + frame.pt1.x = 1; + frame.pt1.y = 1; + frame.pt2.x = frame.pt1.x + thickness - 1; + frame.pt2.y = wndsize.h - 2; +#else + frame.pt1.x = 0; + frame.pt1.y = 0; + frame.pt2.x = frame.pt1.x + thickness - 1; + frame.pt2.y = wndsize.h - 1; +#endif + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor1); + +#if CONFIG_NXTK_BORDERWIDTH > 2 + frame.pt1.x = wndsize.w - thickness - 1; + frame.pt2.x = wndsize.w - 2; +#else + frame.pt1.x = wndsize.w - thickness; + frame.pt2.x = wndsize.w - 1; +#endif + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor1); +#endif + + /* Draw left and right inner sides *****************************************/ + /* This segment stops at the bottom of the toolbar. If there is a + * tool bar, then we have to continue this to the top of the display + * using g_bordercolor1 (see below) + */ + + /* Draw the shadowed left inner edge */ + +#if CONFIG_NXTK_BORDERWIDTH > 1 +#if CONFIG_NXTK_BORDERWIDTH > 2 + frame.pt1.x = thickness + 1; + frame.pt1.y = tbsize.h + thickness + 1; + frame.pt2.x = frame.pt1.x; + frame.pt2.y = wndsize.h - thickness - 2; +#else + frame.pt1.x = thickness; + frame.pt1.y = tbsize.h + thickness; + frame.pt2.x = frame.pt1.x; + frame.pt2.y = wndsize.h - thickness - 1; +#endif + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor2); + + /* Draw the shiny right inner edge */ + +#if CONFIG_NXTK_BORDERWIDTH > 2 + frame.pt1.x = wndsize.w - thickness - 2; + frame.pt2.x = frame.pt1.x; + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor3); +#endif +#endif + + /* Fix up the little line-seqments at the top inner edges that need to match + * the color of the toolbar. + */ + +#if CONFIG_NXTK_BORDERWIDTH > 1 + if (tbsize.h > 0) + { + /* Draw the right side */ + +#if CONFIG_NXTK_BORDERWIDTH > 2 + frame.pt1.x = thickness + 1; + frame.pt1.y = 1; + frame.pt2.x = frame.pt1.x; + frame.pt2.y = tbsize.h + thickness; +#else + frame.pt1.x = thickness; + frame.pt1.y = 0; + frame.pt2.x = frame.pt1.x; + frame.pt2.y = tbsize.h + thickness - 1; +#endif + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor1); + + /* Draw the left size */ + +#if CONFIG_NXTK_BORDERWIDTH > 2 + frame.pt1.x = wndsize.w - thickness - 2; + frame.pt2.x = frame.pt1.x; + nxtk_drawframeside(fwnd, &frame, bounds, g_bordercolor1); +#endif + } +#endif + + return OK; +} diff --git a/nuttx/graphics/nxtk/nxtk_drawlinetoolbar.c b/nuttx/graphics/nxtk/nxtk_drawlinetoolbar.c new file mode 100644 index 0000000000..4af8b37327 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_drawlinetoolbar.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_drawlinetoolbar.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_drawlinetoolbar + * + * Description: + * Fill the specified line in the toolbar sub-window with the specified + * color. This is simply a wrapper that uses nxgl_splitline() to break the + * line into trapezoids and then calls nxtk_filltrapwindow() to render the + * line. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow + * vector - Describes the line to be drawn + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_drawlinetoolbar(NXTKWINDOW hfwnd, FAR struct nxgl_vector_s *vector, + nxgl_coord_t width, nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) + +{ + struct nxgl_trapezoid_s trap[3]; + struct nxgl_rect_s rect; + int ret; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !vector || width < 1 || !color) + { + set_errno(EINVAL); + return ERROR; + } +#endif + + ret = nxgl_splitline(vector, trap, &rect, width); + switch (ret) + { + case 0: + ret = nxtk_filltraptoolbar(hfwnd, &trap[0], color); + if (ret == OK) + { + ret = nxtk_filltraptoolbar(hfwnd, &trap[1], color); + if (ret == OK) + { + ret = nxtk_filltraptoolbar(hfwnd, &trap[2], color); + } + } + break; + + case 1: + ret = nxtk_filltraptoolbar(hfwnd, &trap[1], color); + break; + + case 2: + ret = nxtk_filltoolbar(hfwnd, &rect, color); + break; + + default: + set_errno(EINVAL); + return ERROR; + } + + return ret; +} diff --git a/nuttx/graphics/nxtk/nxtk_drawlinewindow.c b/nuttx/graphics/nxtk/nxtk_drawlinewindow.c new file mode 100644 index 0000000000..2dfd7e8452 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_drawlinewindow.c @@ -0,0 +1,138 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_drawlinewindow.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_drawlinewindow + * + * Description: + * Fill the specified line in the window with the specified color. This + * is simply a wrapper that uses nxgl_splitline() to break the line into + * trapezoids and call calls nxtk_filltrapwindow() to render the line. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow + * vector - Describes the line to be drawn + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_drawlinewindow(NXTKWINDOW hfwnd, FAR struct nxgl_vector_s *vector, + nxgl_coord_t width, nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) + +{ + struct nxgl_trapezoid_s trap[3]; + struct nxgl_rect_s rect; + int ret; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !vector || width < 1 || !color) + { + set_errno(EINVAL); + return ERROR; + } +#endif + + ret = nxgl_splitline(vector, trap, &rect, width); + switch (ret) + { + case 0: + ret = nxtk_filltrapwindow(hfwnd, &trap[0], color); + if (ret == OK) + { + ret = nxtk_filltrapwindow(hfwnd, &trap[1], color); + if (ret == OK) + { + ret = nxtk_filltrapwindow(hfwnd, &trap[2], color); + } + } + break; + + case 1: + ret = nxtk_filltrapwindow(hfwnd, &trap[1], color); + break; + + case 2: + ret = nxtk_fillwindow(hfwnd, &rect, color); + break; + + default: + set_errno(EINVAL); + return ERROR; + } + + return ret; +} diff --git a/nuttx/graphics/nxtk/nxtk_events.c b/nuttx/graphics/nxtk/nxtk_events.c new file mode 100644 index 0000000000..33c50b7f90 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_events.c @@ -0,0 +1,297 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_events.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "nxtk_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void nxtk_redraw(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, + bool morem, FAR void *arg); +static void nxtk_position(NXWINDOW hwnd, FAR const struct nxgl_size_s *size, + FAR const struct nxgl_point_s *pos, + FAR const struct nxgl_rect_s *bounds, + FAR void *arg); +#ifdef CONFIG_NX_MOUSE +static void nxtk_mousein(NXWINDOW hwnd, FAR const struct nxgl_point_s *pos, + uint8_t buttons, FAR void *arg); +#endif +#ifdef CONFIG_NX_KBD +static void nxtk_kbdin(NXWINDOW hwnd, uint8_t nch, const uint8_t *ch, + FAR void *arg); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct nx_callback_s g_nxtkcb = +{ + nxtk_redraw, /* redraw */ + nxtk_position /* position */ +#ifdef CONFIG_NX_MOUSE + , nxtk_mousein /* mousein */ +#endif +#ifdef CONFIG_NX_KBD + , nxtk_kbdin /* kbdin */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_redraw + ****************************************************************************/ + +static void nxtk_redraw(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, + bool more, FAR void *arg) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hwnd; + struct nxgl_rect_s intersection; + + DEBUGASSERT(hwnd && rect && fwnd->fwcb); + + gvdbg("hwnd=%p rect={(%d,%d),(%d,%d)} more=%d\n", + hwnd, rect->pt1.x, rect->pt1.y, rect->pt2.x, rect->pt2.y, more); + + /* The incoming rectangle (rect) is relative to the containing window + * (i.e., (0,0) is the top left corner of the outer, containing window). + * If any part of the rectangle overlaps the client sub-window region, then + * forward the redraw callback. + */ + + if (fwnd->fwcb->redraw) + { + /* Clip the redraw rectangle so that it lies within the client sub-window + * bounds and move the rectangle to that it is relative to the client + * sub-window (i.e., (0,0) is the top left corner of the client sub-window). + */ + + nxtk_containerclip(fwnd, &intersection, rect, &fwnd->fwrect); + + gvdbg("fwrect intersection={(%d,%d),(%d,%d)}\n", + intersection.pt1.x, intersection.pt1.y, + intersection.pt2.x, intersection.pt2.y); + + if (!nxgl_nullrect(&intersection)) + { + fwnd->fwcb->redraw((NXTKWINDOW)fwnd, &intersection, false, fwnd->fwarg); + } + } + + /* If any part of the rectangle overlaps the client toolbar region, then + * forward the redraw callback. + */ + + if (fwnd->tbcb && fwnd->tbcb->redraw) + { + /* Clip the redraw rectangle so that it lies within the toolbar sub-window + * bounds and move the rectangle to that it is relative to the toolbar + * sub-window (i.e., (0,0) is the top left corner of the client sub-window). + */ + + nxtk_containerclip(fwnd, &intersection, rect, &fwnd->tbrect); + + gvdbg("tbrect intersection={(%d,%d),(%d,%d)}\n", + intersection.pt1.x, intersection.pt1.y, + intersection.pt2.x, intersection.pt2.y); + + if (!nxgl_nullrect(&intersection)) + { + fwnd->tbcb->redraw((NXTKWINDOW)fwnd, &intersection, false, fwnd->tbarg); + } + } + + /* Then draw the frame */ + + nxtk_drawframe(fwnd, rect); +} + +/**************************************************************************** + * Name: nxtk_position + ****************************************************************************/ + +static void nxtk_position(NXWINDOW hwnd, FAR const struct nxgl_size_s *size, + FAR const struct nxgl_point_s *pos, + FAR const struct nxgl_rect_s *bounds, + FAR void *arg) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hwnd; + struct nxgl_size_s subwindowsize; + + gvdbg("hwnd=%p size=(%d,%d) pos=(%d,%d) bounds={(%d,%d),(%d,%d)}\n", + hwnd, size->w, size->h, pos->x, pos->y, + bounds->pt1.x, bounds->pt1.y, bounds->pt2.x, bounds->pt2.y); + + /* Recalculate the dimensions of the toolbar and client windows */ + + nxtk_setsubwindows(fwnd); + + /* Report the size / position of the client sub-window */ + + if (fwnd->fwcb->position) + { + nxgl_rectsize(&subwindowsize, &fwnd->fwrect); + fwnd->fwcb->position((NXTKWINDOW)fwnd, &subwindowsize, + &fwnd->fwrect.pt1, bounds, fwnd->fwarg); + } + + /* Report the size / position of the toolbar sub-window */ + + if (fwnd->tbcb && fwnd->tbcb->position) + { + nxgl_rectsize(&subwindowsize, &fwnd->tbrect); + fwnd->tbcb->position((NXTKWINDOW)fwnd, &subwindowsize, + &fwnd->tbrect.pt1, bounds, fwnd->tbarg); + } +} + +/**************************************************************************** + * Name: nxtk_mousein + ****************************************************************************/ + +#ifdef CONFIG_NX_MOUSE +static void nxtk_mousein(NXWINDOW hwnd, FAR const struct nxgl_point_s *pos, + uint8_t buttons, FAR void *arg) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hwnd; + struct nxgl_point_s abspos; + struct nxgl_point_s relpos; + + /* Raise the window to the top if any mouse button was pressed or if auto-raise + * is configured. Do this before reporting the mouse event (because processing + * of the mouse event could change the ordering again). + */ + + /* REVISIT: This does not work correctly. In a scenario where (1) there are + * multiple queued touchscreen events and (2) the result of the first input + * was to switch windows, then this autoraise implementation will cause the + * window to revert to the previous window. Not good behavior. + */ + +#ifndef CONFIG_NX_MULTIUSER /* Queuing only happens in multi-user mode */ +#ifdef CONFIG_NXTK_AUTORAISE + if (fwnd->wnd.above != NULL) +#else + if (buttons != 0 && fwnd->wnd.above != NULL) +#endif + { + nx_raise((NXWINDOW)&fwnd->wnd); + } +#endif + + /* When we get here, the mouse position that we receive has already been + * offset by the window origin. Here we need to detect mouse events in + * the various regions of the windows: The toolbar, the client window, + * or the frame. And then offset the position accordingly. + */ + + /* The fwrect and tbrect boxes are both in absolute display coordinates. So + * the easiest thing to do is to restore the mouse position to absolute + * display coordiantes before making the comparisons and adjustments. + */ + + nxgl_vectoradd(&abspos, pos, &fwnd->wnd.bounds.pt1); + + /* Is the mouse position inside of the client window region? */ + + if (fwnd->fwcb->mousein && nxgl_rectinside(&fwnd->fwrect, &abspos)) + { + nxgl_vectsubtract(&relpos, &abspos, &fwnd->fwrect.pt1); + fwnd->fwcb->mousein((NXTKWINDOW)fwnd, &relpos, buttons, fwnd->fwarg); + } + + /* If the mouse position inside the toobar region? */ + + else if (fwnd->tbcb->mousein && nxgl_rectinside(&fwnd->tbrect, &abspos)) + { + nxgl_vectsubtract(&relpos, &abspos, &fwnd->tbrect.pt1); + fwnd->tbcb->mousein((NXTKWINDOW)fwnd, &relpos, buttons, fwnd->tbarg); + } +} +#endif + +/**************************************************************************** + * Name: nxtk_kbdin + ****************************************************************************/ + +#ifdef CONFIG_NX_KBD +static void nxtk_kbdin(NXWINDOW hwnd, uint8_t nch, const uint8_t *ch, + FAR void *arg) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hwnd; + + /* Only the client window gets keyboard input */ + + if (fwnd->fwcb->kbdin) + { + fwnd->fwcb->kbdin((NXTKWINDOW)fwnd, nch, ch, fwnd->fwarg); + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/nuttx/graphics/nxtk/nxtk_fillcircletoolbar.c b/nuttx/graphics/nxtk/nxtk_fillcircletoolbar.c new file mode 100644 index 0000000000..d0bb09edd2 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_fillcircletoolbar.c @@ -0,0 +1,115 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_fillcircletoolbar.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#define NCIRCLE_TRAPS 8 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_fillcircletoolbar + * + * Description: + * Fill a circular region using the specified color. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow() + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * color - The color to use to fill the circle. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_fillcircletoolbar(NXWINDOW hfwnd, FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + FAR struct nxgl_trapezoid_s traps[NCIRCLE_TRAPS]; + int i; + int ret; + + /* Describe the circular region as a sequence of 8 trapezoids */ + + nxgl_circletraps(center, radius, traps); + + /* Then rend those trapezoids */ + + for (i = 0; i < NCIRCLE_TRAPS; i++) + { + ret = nxtk_filltraptoolbar(hfwnd, &traps[i], color); + if (ret != OK) + { + return ret; + } + } + return OK; +} diff --git a/nuttx/graphics/nxtk/nxtk_fillcirclewindow.c b/nuttx/graphics/nxtk/nxtk_fillcirclewindow.c new file mode 100644 index 0000000000..34c9458650 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_fillcirclewindow.c @@ -0,0 +1,115 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_fillcirclewindow.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#define NCIRCLE_TRAPS 8 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_fillcirclewindow + * + * Description: + * Fill a circular region using the specified color. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow() + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * color - The color to use to fill the circle. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_fillcirclewindow(NXWINDOW hfwnd, FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + FAR struct nxgl_trapezoid_s traps[NCIRCLE_TRAPS]; + int i; + int ret; + + /* Describe the circular region as a sequence of 8 trapezoids */ + + nxgl_circletraps(center, radius, traps); + + /* Then rend those trapezoids */ + + for (i = 0; i < NCIRCLE_TRAPS; i++) + { + ret = nxtk_filltrapwindow(hfwnd, &traps[i], color); + if (ret != OK) + { + return ret; + } + } + return OK; +} diff --git a/nuttx/graphics/nxtk/nxtk_filltoolbar.c b/nuttx/graphics/nxtk/nxtk_filltoolbar.c new file mode 100644 index 0000000000..c39199e6a8 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_filltoolbar.c @@ -0,0 +1,116 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_filltoolbar.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_filltoolbar + * + * Description: + * Fill the specified rectangle in the client window with the specified color + * + * Input Parameters: + * hfwnd - The handle returned by nxtk_openwindow + * rect - The location within the toolbar window to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_filltoolbar(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + struct nxgl_rect_s fillrect; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !rect || !color) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Clip the rectangle so that it lies within the sub-window bounds + * then move the rectangle to that it is relative to the containing + * window. + */ + + nxtk_subwindowclip(fwnd, &fillrect, rect, &fwnd->tbrect); + + /* Then fill it */ + + return nx_fill((NXWINDOW)hfwnd, &fillrect, color); +} diff --git a/nuttx/graphics/nxtk/nxtk_filltraptoolbar.c b/nuttx/graphics/nxtk/nxtk_filltraptoolbar.c new file mode 100644 index 0000000000..1f04e9b43e --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_filltraptoolbar.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_filltraptoolbar.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_filltraptoolbar + * + * Description: + * Fill the specified rectangle in the toolbar with the specified color + * + * Input Parameters: + * hfwnd - The handle returned by nxtk_openwindow + * trap - The trapezoidal region to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_filltraptoolbar(NXTKWINDOW hfwnd, FAR const struct nxgl_trapezoid_s *trap, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + struct nxgl_rect_s relclip; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !trap || !color) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Perform the fill, clipping to the client window */ + + nxgl_rectoffset(&relclip, &fwnd->tbrect, -fwnd->wnd.bounds.pt1.x, -fwnd->wnd.bounds.pt1.y); + return nx_filltrapezoid((NXWINDOW)hfwnd, &relclip, trap, color); +} diff --git a/nuttx/graphics/nxtk/nxtk_filltrapwindow.c b/nuttx/graphics/nxtk/nxtk_filltrapwindow.c new file mode 100644 index 0000000000..c84c055f88 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_filltrapwindow.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_filltrapwindow.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_filltrapwindow + * + * Description: + * Fill the specified rectangle in the client window with the specified color + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow + * trap - The trapezoidal region to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_filltrapwindow(NXTKWINDOW hfwnd, FAR const struct nxgl_trapezoid_s *trap, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + struct nxgl_rect_s relclip; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !trap || !color) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Perform the fill, clipping to the client window */ + + nxgl_rectoffset(&relclip, &fwnd->fwrect, -fwnd->wnd.bounds.pt1.x, -fwnd->wnd.bounds.pt1.y); + return nx_filltrapezoid((NXWINDOW)hfwnd, &relclip, trap, color); +} diff --git a/nuttx/graphics/nxtk/nxtk_fillwindow.c b/nuttx/graphics/nxtk/nxtk_fillwindow.c new file mode 100644 index 0000000000..e971ce06bc --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_fillwindow.c @@ -0,0 +1,116 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_fillwindow.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_fillwindow + * + * Description: + * Fill the specified rectangle in the client window with the specified color + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow + * rect - The location within the client window to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_fillwindow(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + struct nxgl_rect_s fillrect; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !rect || !color) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Clip the rectangle so that it lies within the sub-window bounds + * then move the rectangle to that it is relative to the containing + * window. + */ + + nxtk_subwindowclip(fwnd, &fillrect, rect, &fwnd->fwrect); + + /* Then fill it */ + + return nx_fill((NXWINDOW)hfwnd, &fillrect, color); +} diff --git a/nuttx/graphics/nxtk/nxtk_getposition.c b/nuttx/graphics/nxtk/nxtk_getposition.c new file mode 100644 index 0000000000..e6cce60262 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_getposition.c @@ -0,0 +1,95 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_getposition.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_getposition + * + * Description: + * Request the position and size information for the selected framed window. + * The size/position for the client window and toolbar will be return + * asynchronously through the client callback function pointer. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_getposition(NXTKWINDOW hfwnd) +{ + return nx_getposition((NXWINDOW)hfwnd); +} diff --git a/nuttx/graphics/nxtk/nxtk_gettoolbar.c b/nuttx/graphics/nxtk/nxtk_gettoolbar.c new file mode 100644 index 0000000000..70adb0ccea --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_gettoolbar.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_gettoolbar.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_gettoolbar + * + * Description: + * Get the raw contents of graphic memory within a rectangular region. NOTE: + * Since raw graphic memory is returned, the returned memory content may be + * the memory of windows above this one and may not necessarily belong to + * this window unless you assure that this is the top window. + * + * Input Parameters: + * wnd - The window structure reference + * rect - The location to be copied + * plane - Specifies the color plane to get from. + * dest - The location to copy the memory region + * deststride - The width, in bytes, the the dest memory + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_gettoolbar(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *rect, + unsigned int plane, FAR uint8_t *dest, + unsigned int deststride) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + struct nxgl_rect_s getrect; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !rect || !dest) + { + gvdbg("Invalid parameters\n"); + set_errno(EINVAL); + return ERROR; + } +#endif + + /* Clip the rectangle so that it lies within the sub-window bounds + * then move the rectangle to that it is relative to the containing + * window. + */ + + nxtk_subwindowclip(fwnd, &getrect, rect, &fwnd->tbrect); + + /* Then get it */ + + return nx_getrectangle((NXWINDOW)hfwnd, &getrect, plane, dest, deststride); +} diff --git a/nuttx/graphics/nxtk/nxtk_getwindow.c b/nuttx/graphics/nxtk/nxtk_getwindow.c new file mode 100644 index 0000000000..121c7702af --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_getwindow.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_getwindow.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_getwindow + * + * Description: + * Get the raw contents of graphic memory within a rectangular region. NOTE: + * Since raw graphic memory is returned, the returned memory content may be + * the memory of windows above this one and may not necessarily belong to + * this window unless you assure that this is the top window. + * + * Input Parameters: + * wnd - The window structure reference + * rect - The location to be copied + * plane - Specifies the color plane to get from. + * dest - The location to copy the memory region + * deststride - The width, in bytes, the the dest memory + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_getwindow(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *rect, + unsigned int plane, FAR uint8_t *dest, + unsigned int deststride) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + struct nxgl_rect_s getrect; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !rect || !dest) + { + gvdbg("Invalid parameters\n"); + set_errno(EINVAL); + return ERROR; + } +#endif + + /* Clip the rectangle so that it lies within the sub-window bounds + * then move the rectangle to that it is relative to the containing + * window. + */ + + nxtk_subwindowclip(fwnd, &getrect, rect, &fwnd->fwrect); + + /* Then get it */ + + return nx_getrectangle((NXWINDOW)hfwnd, &getrect, plane, dest, deststride); +} diff --git a/nuttx/graphics/nxtk/nxtk_internal.h b/nuttx/graphics/nxtk/nxtk_internal.h new file mode 100644 index 0000000000..87a098845a --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_internal.h @@ -0,0 +1,220 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_internal.h + * + * Copyright (C) 2008-2009, 2011-1021 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __GRAPHICS_NXTK_NXTK_INTERNAL_H +#define __GRAPHICS_NXTK_NXTK_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include "nxbe.h" +#include "nxfe.h" + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This is the internal representation of the framed window object */ + +struct nxtk_framedwindow_s +{ + struct nxbe_window_s wnd; /* The raw NX window */ + + /* The toolbar region and callbacks */ + + nxgl_coord_t tbheight; + struct nxgl_rect_s tbrect; + FAR const struct nx_callback_s *tbcb; + FAR void *tbarg; + + /* Window data region and callbacks */ + + struct nxgl_rect_s fwrect; + FAR const struct nx_callback_s *fwcb; + FAR void *fwarg; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" { +#else +# define EXTERN extern +#endif + +/* That is the callback for the framed window */ + +extern FAR const struct nx_callback_s g_nxtkcb; + +/* Frame border colors */ + +extern nxgl_mxpixel_t g_bordercolor1[CONFIG_NX_NPLANES]; +extern nxgl_mxpixel_t g_bordercolor2[CONFIG_NX_NPLANES]; +extern nxgl_mxpixel_t g_bordercolor3[CONFIG_NX_NPLANES]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_setsubwindows + * + * Description: + * Give the window dimensions, border width, and toolbar height, + * calculate the new dimensions of the toolbar region and client window + * region + * + ****************************************************************************/ + +EXTERN void nxtk_setsubwindows(FAR struct nxtk_framedwindow_s *fwnd); + +/**************************************************************************** + * Name: nxtk_subwindowclip + * + * Description: + * Clip the src rectangle so that it lies within the sub-window bounds + * then move the rectangle to that it is relative to the containing + * window. + * + * Input parameters: + * fwnd - The framed window to be used + * dest - The locaton to put the result + * src - The src rectangle in relative sub-window coordinates + * bounds - The subwindow bounds in absolute screen coordinates. + * + * Returned value: + * None + * + ****************************************************************************/ + +EXTERN void nxtk_subwindowclip(FAR struct nxtk_framedwindow_s *fwnd, + FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src, + FAR const struct nxgl_rect_s *bounds); + +/**************************************************************************** + * Name: nxtk_containerclip + * + * Description: + * We are given a 'src' rectangle in containing window, relative coordinates + * (i.e., (0,0) is the top left corner of the outer, containing window). + * This function will (1) clip that src rectangle so that it lies within + * the sub-window bounds, and then (2) move the rectangle to that it is + * relative to the sub-window (i.e., (0,0) is the top left corner of the + * sub-window). + * + * Input parameters: + * fwnd - The framed window to be used + * dest - The locaton to put the result + * src - The src rectangle in relative container-window coordinates + * bounds - The subwindow bounds in absolute screen coordinates. + * + * Returned value: + * None + * + ****************************************************************************/ + +EXTERN void nxtk_containerclip(FAR struct nxtk_framedwindow_s *fwnd, + FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src, + FAR const struct nxgl_rect_s *bounds); + +/**************************************************************************** + * Name: nxtk_subwindowmove + * + * Description: + * Perform common clipping operations in preparatons for calling nx_move() + * + * Input Parameters: + * fwnd - The framed window within which the move is to be done. + * This must have been previously created by nxtk_openwindow(). + * destrect - The loccation to receive the clipped rectangle relative + * to containing window + * destoffset - The location to received the clipped offset. + * srcrect - Describes the rectangular region relative to the client + * sub-window to move relative to the sub-window + * srcoffset - The offset to move the region + * bounds - The subwindow bounds in absolute screen coordinates. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN void nxtk_subwindowmove(FAR struct nxtk_framedwindow_s *fwnd, + FAR struct nxgl_rect_s *destrect, + FAR struct nxgl_point_s *destoffset, + FAR const struct nxgl_rect_s *srcrect, + FAR const struct nxgl_point_s *srcoffset, + FAR const struct nxgl_rect_s *bounds); + +/**************************************************************************** + * Name: nxtk_drawframe + * + * Description: + * Redraw the window frame. + * + * Input parameters: + * fwnd - the framed window whose frame needs to be re-drawn. This must + * have been previously created by nxtk_openwindow(). + * bounds - Only draw the ports of the frame within this bounding box. + * (window relative coordinates). + * + * Returned value: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_drawframe(FAR struct nxtk_framedwindow_s *fwnd, + FAR const struct nxgl_rect_s *bounds); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __GRAPHICS_NXTK_NXTK_INTERNAL_H */ diff --git a/nuttx/graphics/nxtk/nxtk_lower.c b/nuttx/graphics/nxtk/nxtk_lower.c new file mode 100644 index 0000000000..256ed27dab --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_lower.c @@ -0,0 +1,95 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_lower.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_lower + * + * Description: + * Lower the window containing the specified client sub-window to the + * bottom of the display. + * + * Input parameters: + * hfwnd - the window to be lowered. This must have been previously created + * by nxtk_openwindow(). + * + * Returned value: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_lower(NXTKWINDOW hfwnd) +{ + return nx_lower((NXWINDOW)hfwnd); +} diff --git a/nuttx/graphics/nxtk/nxtk_movetoolbar.c b/nuttx/graphics/nxtk/nxtk_movetoolbar.c new file mode 100644 index 0000000000..088611382a --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_movetoolbar.c @@ -0,0 +1,119 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_movetoolbar.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_movetoolbar + * + * Description: + * Move a rectangular region within the toolbar sub-window of a framed window + * + * Input Parameters: + * hfwnd - The sub-window containing the toolbar within which the move is + * to be done. This must have been previously created by + * nxtk_openwindow(). + * rect - Describes the rectangular region relative to the toolbar + * sub-window to move + * offset - The offset to move the region + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_movetoolbar(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + struct nxgl_rect_s srcrect; + struct nxgl_point_s clipoffset; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !rect || !offset) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Make sure that both the source and dest rectangle lie within the + * toolbar sub-window + */ + + nxtk_subwindowmove(fwnd, &srcrect, &clipoffset, rect, offset, &fwnd->tbrect); + + /* Then move it within the toolbar window */ + + return nx_move((NXWINDOW)hfwnd, &srcrect, &clipoffset); +} diff --git a/nuttx/graphics/nxtk/nxtk_movewindow.c b/nuttx/graphics/nxtk/nxtk_movewindow.c new file mode 100644 index 0000000000..4c45c101c5 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_movewindow.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_movewindow.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_movewindow + * + * Description: + * Move a rectangular region within the client sub-window of a framed window + * + * Input Parameters: + * hfwnd - The client sub-window within which the move is to be done. + * This must have been previously created by nxtk_openwindow(). + * rect - Describes the rectangular region relative to the client + * sub-window to move + * offset - The offset to move the region + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_movewindow(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + struct nxgl_rect_s srcrect; + struct nxgl_point_s clipoffset; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !rect || !offset) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Make sure that both the source and dest rectangle lie within the + * client sub-window + */ + + nxtk_subwindowmove(fwnd, &srcrect, &clipoffset, rect, offset, &fwnd->fwrect); + + /* Then move it within the client window */ + + return nx_move((NXWINDOW)hfwnd, &srcrect, &clipoffset); +} diff --git a/nuttx/graphics/nxtk/nxtk_opentoolbar.c b/nuttx/graphics/nxtk/nxtk_opentoolbar.c new file mode 100644 index 0000000000..56ca941b8f --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_opentoolbar.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_opentoolbar.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_opentoolbar + * + * Description: + * Create a tool bar at the top of the specified framed window + * + * Input Parameters: + * hfwnd - The handle returned by nxtk_openwindow + * height - The request height of the toolbar in pixels + * cb - Callbacks used to process toolbar events + * arg - User provided value that will be returned with toolbar callbacks. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_opentoolbar(NXTKWINDOW hfwnd, nxgl_coord_t height, + FAR const struct nx_callback_s *cb, + FAR void *arg) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !cb) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Initialize the toolbar info */ + + fwnd->tbheight = height; + fwnd->tbcb = cb; + fwnd->tbarg = arg; + + /* Calculate the new dimensions of the toolbar and client windows */ + + nxtk_setsubwindows(fwnd); + + /* Then redraw the entire window, even the client window must be + * redrawn because it has changed its vertical position and size. + */ + + nxfe_redrawreq(&fwnd->wnd, &fwnd->wnd.bounds); + + /* Return the initialized toolbar reference */ + + return OK; +} + diff --git a/nuttx/graphics/nxtk/nxtk_openwindow.c b/nuttx/graphics/nxtk/nxtk_openwindow.c new file mode 100644 index 0000000000..0c77a68777 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_openwindow.c @@ -0,0 +1,160 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_openwindow.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +nxgl_mxpixel_t g_bordercolor1[CONFIG_NX_NPLANES] = +{ + CONFIG_NXTK_BORDERCOLOR1 +#if CONFIG_NX_NPLANES > 1 +# error "Multiple plane border colors not defined" +#endif +}; + +nxgl_mxpixel_t g_bordercolor2[CONFIG_NX_NPLANES] = +{ + CONFIG_NXTK_BORDERCOLOR2 +#if CONFIG_NX_NPLANES > 1 +# error "Multiple plane border colors not defined" +#endif +}; + +nxgl_mxpixel_t g_bordercolor3[CONFIG_NX_NPLANES] = +{ + CONFIG_NXTK_BORDERCOLOR3 +#if CONFIG_NX_NPLANES > 1 +# error "Multiple plane border colors not defined" +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_openwindow + * + * Description: + * Create a new, framed window. + * + * Input Parameters: + * handle - The handle returned by nx_connect + * cb - Callbacks used to process window events + * arg - User provided value that will be returned with NXTK callbacks. + * + * Return: + * Success: A non-NULL handle used with subsequent NXTK window accesses + * Failure: NULL is returned and errno is set appropriately + * + ****************************************************************************/ + +NXTKWINDOW nxtk_openwindow(NXHANDLE handle, + FAR const struct nx_callback_s *cb, + FAR void *arg) +{ + FAR struct nxtk_framedwindow_s *fwnd; + int ret; + +#ifdef CONFIG_DEBUG + if (!handle || !cb) + { + errno = EINVAL; + return NULL; + } +#endif + + /* Pre-allocate the window structure */ + + fwnd = (FAR struct nxtk_framedwindow_s *)kzalloc(sizeof(struct nxtk_framedwindow_s)); + if (!fwnd) + { + errno = ENOMEM; + return NULL; + } + + /* Initialize the window structure */ + + fwnd->fwcb = cb; + fwnd->fwarg = arg; + + /* Then let nxfe_constructwindow do the rest */ + + ret = nxfe_constructwindow(handle, &fwnd->wnd, &g_nxtkcb, NULL); + if (ret < 0) + { + /* An error occurred, the window has been freed */ + + return NULL; + } + + /* Return the initialized window reference */ + + return (NXTKWINDOW)fwnd; +} + diff --git a/nuttx/graphics/nxtk/nxtk_raise.c b/nuttx/graphics/nxtk/nxtk_raise.c new file mode 100644 index 0000000000..1e35f3ab2a --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_raise.c @@ -0,0 +1,95 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_raise.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_raise + * + * Description: + * Bring the window containing the specified client sub-window to the top + * of the display. + * + * Input parameters: + * hfwnd - the window to be raised. This must have been previously created + * by nxtk_openwindow(). + * + * Returned value: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_raise(NXTKWINDOW hfwnd) +{ + return nx_raise((NXWINDOW)hfwnd); +} diff --git a/nuttx/graphics/nxtk/nxtk_setposition.c b/nuttx/graphics/nxtk/nxtk_setposition.c new file mode 100644 index 0000000000..2a2a60665b --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_setposition.c @@ -0,0 +1,107 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_setposition.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_setposition + * + * Description: + * Set the position for the selected client window. This position does not + * include the offsets for the borders nor for any toolbar. Those offsets + * will be added in to set the full window position. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow + * pos - The new position of the client sub-window + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_setposition(NXTKWINDOW hfwnd, FAR const struct nxgl_point_s *pos) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + struct nxgl_point_s offset; + struct nxgl_point_s newpos; + + /* Calculate the offset that is requested and add that to the window origin. */ + + nxgl_vectsubtract(&offset, pos, &fwnd->fwrect.pt1); + nxgl_vectoradd(&newpos, &offset, &fwnd->wnd.bounds.pt1); + + /* Then set that position */ + + return nx_setposition((NXWINDOW)hfwnd, &newpos); +} diff --git a/nuttx/graphics/nxtk/nxtk_setsize.c b/nuttx/graphics/nxtk/nxtk_setsize.c new file mode 100644 index 0000000000..aeeebf1500 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_setsize.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_setsize.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_setsize + * + * Description: + * Set the size for the selected client window. This size does not + * include the sizes of the borders nor for any toolbar. Those sizes + * will be added in to set the full window size. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow + * size - The new size of the client sub-window. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_setsize(NXTKWINDOW hfwnd, FAR const struct nxgl_size_s *size) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + struct nxgl_size_s newsize; + +#ifdef CONFIG_DEBUG + if (!hfwnd || !size) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Add the sizes need for the toolbar and the borders */ + + newsize.w = size->w + 2 * CONFIG_NXTK_BORDERWIDTH; + newsize.h = size->h + fwnd->tbheight + 2 * CONFIG_NXTK_BORDERWIDTH; + + /* Then set the window size */ + + return nx_setsize((NXWINDOW)hfwnd, &newsize); +} diff --git a/nuttx/graphics/nxtk/nxtk_setsubwindows.c b/nuttx/graphics/nxtk/nxtk_setsubwindows.c new file mode 100644 index 0000000000..2510083610 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_setsubwindows.c @@ -0,0 +1,165 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_setsubwindows.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include "nxtk_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_setsubwindows + * + * Description: + * Give the window dimensions, border width, and toolbar height, + * calculate the new dimensions of the toolbar region and client window + * region + * + ****************************************************************************/ + +void nxtk_setsubwindows(FAR struct nxtk_framedwindow_s *fwnd) +{ + nxgl_coord_t fullheight; + nxgl_coord_t bdrheight = 0; + nxgl_coord_t tbtop = fwnd->wnd.bounds.pt1.y; + nxgl_coord_t tbheight = 0; + nxgl_coord_t fwtop = fwnd->wnd.bounds.pt1.y; + nxgl_coord_t fwheight = 0; + nxgl_coord_t fullwidth; + nxgl_coord_t bdrwidth; + nxgl_coord_t fwwidth; + nxgl_coord_t fwleft; + + /* Divide up the vertical dimension of the window */ + + fullheight = fwnd->wnd.bounds.pt2.y - fwnd->wnd.bounds.pt1.y + 1; + + /* Is it tall enough for a border? */ + + if (fullheight > 0) + { + /* Get the border height */ + + bdrheight = ngl_min(2 * CONFIG_NXTK_BORDERWIDTH, fullheight); + + /* Position the toolbar and client window just under the top border */ + +#if CONFIG_NXTK_BORDERWIDTH > 1 + tbtop += CONFIG_NXTK_BORDERWIDTH - 1; + fwtop = tbtop + 1; +#else + tbtop += CONFIG_NXTK_BORDERWIDTH; + fwtop = tbtop; +#endif + + /* Is it big enough for any part of the toolbar? */ + + if (fullheight > 2 * CONFIG_NXTK_BORDERWIDTH) + { + /* Yes.. get the height of the toolbar */ + + tbheight = fwnd->tbheight; + if (tbheight >= fullheight - bdrheight) + { + tbheight = fullheight - bdrheight; + } + else + { + /* And the client window gets whatever is left */ + + fwheight = fullheight - bdrheight - tbheight; + } + + /* Position the client window just under the toolbar */ + + fwtop += tbheight; + } + } + + /* Divide up the horizontal dimensions of the window */ + + fullwidth = fwnd->wnd.bounds.pt2.x - fwnd->wnd.bounds.pt1.x + 1; + bdrwidth = ngl_min(2 * CONFIG_NXTK_BORDERWIDTH, fullwidth); + fwwidth = fullwidth - bdrwidth; + fwleft = fwnd->wnd.bounds.pt1.x + bdrwidth / 2; + + /* Realize the positions/dimensions */ + + fwnd->tbrect.pt1.x = fwleft; + fwnd->tbrect.pt1.y = tbtop; + fwnd->tbrect.pt2.x = fwleft + fwwidth - 1; + fwnd->tbrect.pt2.y = tbtop + tbheight - 1; + + fwnd->fwrect.pt1.x = fwleft; + fwnd->fwrect.pt1.y = fwtop; + fwnd->fwrect.pt2.x = fwleft + fwwidth - 1; + fwnd->fwrect.pt2.y = fwtop + fwheight - 1; +} diff --git a/nuttx/graphics/nxtk/nxtk_subwindowclip.c b/nuttx/graphics/nxtk/nxtk_subwindowclip.c new file mode 100644 index 0000000000..4d453eecaf --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_subwindowclip.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_subwindowclip.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_subwindowclip + * + * Description: + * We are given a 'src' rectangle in sub-window, relative coordinates + * (i.e., (0,0) is the top left corner of the sub-window). This function + * will (1) clip that src rectangle so that it lies within the sub-window + * bounds, and then (2) move the rectangle to that it is relative to the + * containing window (i.e., (0,0) is the top left corner of the containing + * window). + * + * Input parameters: + * fwnd - The framed window to be used + * dest - The locaton to put the result + * src - The src rectangle in relative sub-window coordinates + * bounds - The subwindow bounds in absolute screen coordinates. + * + * Returned value: + * None + * + ****************************************************************************/ + +void nxtk_subwindowclip(FAR struct nxtk_framedwindow_s *fwnd, + FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src, + FAR const struct nxgl_rect_s *bounds) +{ + struct nxgl_rect_s tmp; + + /* Temporarily, position the src rectangle in absolute screen coordinates */ + + nxgl_rectoffset(&tmp, src, bounds->pt1.x, bounds->pt1.y); + + /* Clip the src rectangle to lie within the client window region */ + + nxgl_rectintersect(&tmp, &tmp, bounds); + + /* Then move the rectangle so that is relative to the containing window, not the + * client subwindow + */ + + nxgl_rectoffset(dest, &tmp, -fwnd->wnd.bounds.pt1.x, -fwnd->wnd.bounds.pt1.y); +} diff --git a/nuttx/graphics/nxtk/nxtk_subwindowmove.c b/nuttx/graphics/nxtk/nxtk_subwindowmove.c new file mode 100644 index 0000000000..ed6a264e73 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_subwindowmove.c @@ -0,0 +1,151 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_subwindowmove.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_subwindowmove + * + * Description: + * Perform common clipping operations in preparatons for calling nx_move() + * + * Input Parameters: + * fwnd - The framed window within which the move is to be done. + * This must have been previously created by nxtk_openwindow(). + * destrect - The loccation to receive the clipped rectangle relative + * to containing window + * destoffset - The location to received the clipped offset. + * srcrect - Describes the rectangular region relative to the client + * sub-window to move relative to the sub-window + * srcoffset - The offset to move the region + * bounds - The subwindow bounds in absolute screen coordinates. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +void nxtk_subwindowmove(FAR struct nxtk_framedwindow_s *fwnd, + FAR struct nxgl_rect_s *destrect, + FAR struct nxgl_point_s *destoffset, + FAR const struct nxgl_rect_s *srcrect, + FAR const struct nxgl_point_s *srcoffset, + FAR const struct nxgl_rect_s *bounds) +{ + struct nxgl_rect_s abssrc; + + /* Temporarily, position the src rectangle in absolute screen coordinates */ + + nxgl_rectoffset(&abssrc, srcrect, bounds->pt1.x, bounds->pt1.y); + + /* Clip the src rectangle to lie within the client window region */ + + nxgl_rectintersect(&abssrc, &abssrc, &fwnd->fwrect); + + /* Clip the offset so that the source rectangle does not move out of the + * the client sub-window. + */ + + destoffset->x = srcoffset->x; + if (destoffset->x < 0) + { + if (abssrc.pt1.x + destoffset->x < bounds->pt1.x) + { + destoffset->x = bounds->pt1.x - abssrc.pt1.x; + } + } + else if (abssrc.pt2.x + destoffset->x > bounds->pt2.x) + { + destoffset->x = bounds->pt2.x - abssrc.pt2.x; + } + + destoffset->y = srcoffset->y; + if (destoffset->y < 0) + { + if (abssrc.pt1.y + destoffset->y < bounds->pt1.y) + { + destoffset->y = bounds->pt1.y - abssrc.pt1.y; + } + } + else if (abssrc.pt2.y + destoffset->y > bounds->pt2.y) + { + destoffset->y = bounds->pt2.y - abssrc.pt2.y; + } + + + /* Then move the rectangle so that is relative to the containing window, not the + * client subwindow + */ + + nxgl_rectoffset(destrect, &abssrc, -fwnd->wnd.bounds.pt1.x, -fwnd->wnd.bounds.pt1.y); +} diff --git a/nuttx/graphics/nxtk/nxtk_toolbarbounds.c b/nuttx/graphics/nxtk/nxtk_toolbarbounds.c new file mode 100644 index 0000000000..ee49cb5044 --- /dev/null +++ b/nuttx/graphics/nxtk/nxtk_toolbarbounds.c @@ -0,0 +1,107 @@ +/**************************************************************************** + * graphics/nxtk/nxtk_toolbarbounds.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "nxfe.h" +#include "nxtk_internal.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_toolbarbounds + * + * Description: + * Return a bounding box that contains the toolbar in the coordinates of + * the containing, framed window. For example, the recturned origin + * (rect.pt1) is the offset toolbar in the framed window. + * + * NOTE: This function is unsafe in the case of the multi-user NX server + * where the width of the window may be being changed asynchronously! It + * may return the old size in this case. + * + * Input Parameters: + * hfwnd - The handle returned by nxtk_openwindow + * bounds - User provided location in which to return the bounding box. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nxtk_toolbarbounds(NXTKWINDOW hfwnd, FAR struct nxgl_rect_s *bounds) +{ + FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; + + DEBUGASSERT(hfwnd && bounds); + + /* Offset the rectangle by subtracting the current position of the window. */ + + nxgl_rectoffset(bounds, &fwnd->tbrect, + -fwnd->wnd.bounds.pt1.x, -fwnd->wnd.bounds.pt1.y); + return OK; +} + diff --git a/nuttx/include/arpa/inet.h b/nuttx/include/arpa/inet.h new file mode 100644 index 0000000000..7428c76f28 --- /dev/null +++ b/nuttx/include/arpa/inet.h @@ -0,0 +1,136 @@ +/**************************************************************************** + * include/arpa/inet.h + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_ARPA_INET_H +#define __INCLUDE_ARPA_INET_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ +/* Length of the string form for IP address (excludes NULL termination) */ + +#define INET_ADDRSTRLEN 16 + +/* Length of the string form for IPv6 address (excludes NULL termination) */ + +#define INET6_ADDRSTRLEN 46 + +/* This macro to convert a 16/32-bit constant values quantity from host byte + * order to network byte order. The 16-bit version of this macro is required + * for uIP: + * + * Author Adam Dunkels + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + */ + +#ifdef CONFIG_ENDIAN_BIG +# define HTONS(ns) (ns) +# define HTONL(nl) (nl) +#else +# define HTONS(ns) \ + (unsigned short) \ + (((((unsigned short)(ns)) & 0x00ff) << 8) | \ + ((((unsigned short)(ns)) >> 8) & 0x00ff)) +# define HTONL(nl) \ + (unsigned long) \ + (((((unsigned long)(nl)) & 0x000000ffUL) << 24) | \ + ((((unsigned long)(nl)) & 0x0000ff00UL) << 8) | \ + ((((unsigned long)(nl)) & 0x00ff0000UL) >> 8) | \ + ((((unsigned long)(nl)) & 0xff000000UL) >> 24)) +#endif + +#define NTOHS(hs) HTONS(hs) +#define NTOHL(hl) HTONL(hl) + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Functions to convert between nost and network byte ordering */ + +EXTERN uint32_t ntohl(uint32_t nl); +EXTERN uint16_t ntohs(uint16_t ns); +EXTERN uint32_t htonl(uint32_t hl); +EXTERN uint16_t htons(uint16_t hs); + +/* Functions to manipulate address representations */ + +EXTERN int inet_aton(FAR const char *cp, FAR struct in_addr *inp); +EXTERN in_addr_t inet_addr(FAR const char *cp); +EXTERN in_addr_t inet_network(FAR const char *cp); + +#ifdef CONFIG_CAN_PASS_STRUCTS +EXTERN FAR char *inet_ntoa(struct in_addr in); +EXTERN in_addr_t inet_lnaof(struct in_addr in); +EXTERN in_addr_t inet_netof(struct in_addr in); +#else +EXTERN FAR char *_inet_ntoa(in_addr_t in); +# define inet_ntoa(in) _inet_ntoa(in.s_addr); + +EXTERN in_addr_t _inet_lnaof(in_addr_t in); +# define inet_lnaof(in) _inet_lnaof(in.s_addr); + +EXTERN in_addr_t _inet_netof(in_addr_t in); +# define inet_netof(in) _inet_netof(in.s_addr); +#endif +EXTERN struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host); + +EXTERN int inet_pton(int af, FAR const char *src, FAR void *dst); +EXTERN const char *inet_ntop(int af, FAR const void *src, FAR char *dst, socklen_t size); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_ARPA_INET_H */ diff --git a/nuttx/include/assert.h b/nuttx/include/assert.h new file mode 100644 index 0000000000..89606b6f6a --- /dev/null +++ b/nuttx/include/assert.h @@ -0,0 +1,123 @@ +/**************************************************************************** + * include/assert.h + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_ASSERT_H +#define __INCLUDE_ASSERT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Macro Name: ASSERT, ASSERTCODE, et al. */ + +#undef ASSERT +#undef ASSERTCODE +#undef DEBUGASSERT +#undef PANIC + +#ifdef CONFIG_HAVE_FILENAME + +# define ASSERT(f) \ + { if (!(f)) up_assert((const uint8_t *)__FILE__, (int)__LINE__); } + +# define ASSERTCODE(f, code) \ + { if (!(f)) up_assert_code((const uint8_t *)__FILE__, (int)__LINE__, code); } + +# ifdef CONFIG_DEBUG +# define DEBUGASSERT(f) \ + { if (!(f)) up_assert((const uint8_t *)__FILE__, (int)__LINE__); } +# else +# define DEBUGASSERT(f) +# endif /* CONFIG_DEBUG */ + +# define PANIC(code) \ + up_assert_code((const uint8_t *)__FILE__, (int)__LINE__, (code)|0x8000) + +#else +# define ASSERT(f) \ + { if (!(f)) up_assert(); } + +# define ASSERTCODE(f, code) \ + { if (!(f)) up_assert_code(code); } + +# ifdef CONFIG_DEBUG +# define DEBUGASSERT(f) \ + { if (!(f)) up_assert(); } +# else +# define DEBUGASSERT(f) +# endif /* CONFIG_DEBUG */ + +# define PANIC(code) \ + up_assert_code((code)|0x8000) + +#endif + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#ifdef CONFIG_HAVE_FILENAME +EXTERN void up_assert(FAR const uint8_t *filename, int linenum); +EXTERN void up_assert_code(FAR const uint8_t *filename, int linenum, + int errcode); +#else +EXTERN void up_assert(void); +EXTERN void up_assert_code(int errcode); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_ASSERT_H */ diff --git a/nuttx/include/crc32.h b/nuttx/include/crc32.h new file mode 100644 index 0000000000..1dd6fff136 --- /dev/null +++ b/nuttx/include/crc32.h @@ -0,0 +1,83 @@ +/**************************************************************************** + * include/crc.h + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_CRC32_H +#define __INCLUDE_CRC32_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: crc32part + * + * Description: + * Continue CRC calculation on a part of the buffer. + * + ****************************************************************************/ + +EXTERN uint32_t crc32part(FAR const uint8_t *src, size_t len, + uint32_t crc32val); + +/**************************************************************************** + * Name: crc32 + * + * Description: + * Return a 32-bit CRC of the contents of the 'src' buffer, length 'len' + * + ****************************************************************************/ + +EXTERN uint32_t crc32(FAR const uint8_t *src, size_t len); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_CRC32_H */ diff --git a/nuttx/include/ctype.h b/nuttx/include/ctype.h new file mode 100644 index 0000000000..6959a44b18 --- /dev/null +++ b/nuttx/include/ctype.h @@ -0,0 +1,223 @@ +/**************************************************************************** + * include/ctype.h + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_CTYPE_H +#define __INCLUDE_CTYPE_H + +/* There is no consistent ctype implementation, just a smattering of + * functions. Individually, they are okay, but a more standard, data lookup + * approach would make more sense if used extensively. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Name: isspace + * + * Description: + * Checks for white-space characters. In the "C" and "POSIX" locales, + * these are: space, form-feed ('\f'), newline ('\n'), carriage return + * ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). + * + ****************************************************************************/ + +#define isspace(c) \ + ((c) == ' ' || (c) == '\t' || (c) == '\n' || \ + (c) == '\r' || (c) == '\f' || c== '\v') + +/**************************************************************************** + * Name: isascii + * + * Description: + * Checks whether c is a 7-bit unsigned char value that fits into the + * ASCII character set. + * + ****************************************************************************/ + +#define isascii(c) ((c) >= 0 && (c) <= 0x7f); + +/**************************************************************************** + * Name: isprint + * + * Description: + * Checks for a printable character (including space) + * + ****************************************************************************/ + +#define isprint(c) ((c) >= 0x20 && (c) < 0x7f) + +/**************************************************************************** + * Name: isgraph + * + * Description: + * Checks for a printable character (excluding space) + * + ****************************************************************************/ + +#define isgraph(c) ((c) > 0x20 && (c) < 0x7f) + +/**************************************************************************** + * Name: iscntrl + * + * Description: + * Checks for control character. + * + ****************************************************************************/ + +#define iscontrol(c) (!isprint(c)) + +/**************************************************************************** + * Name: islower + * + * Description: + * Checks for an lowercase letter. + * + ****************************************************************************/ + +#define islower(c) ((c) >= 'a' && (c) <= 'z') + +/**************************************************************************** + * Name: isupper + * + * Description: + * Checks for an uppercase letter. + * + ****************************************************************************/ + +#define isupper(c) ((c) >= 'A' && (c) <= 'Z') + +/**************************************************************************** + * Name: isalpha + * + * Description: + * Checks for an alphabetic character + * + ****************************************************************************/ + +#define isalpha(c) (islower(c) || isupper(c)) + +/**************************************************************************** + * Name: isdigit + * + * Description: + * ANSI standard isdigit implementation. + * + ****************************************************************************/ + +#define isdigit(c) ((c) >= '0' && (c) <= '9') + +/**************************************************************************** + * Name: isalnum + * + * Description: + * Checks for an alphanumeric character + * + ****************************************************************************/ + +#define isalnum(c) (isalpha(c) || isdigit(c)) + +/**************************************************************************** + * Name: ispunct + * + * Description: + * Checks for a printable character which is not a space or an + * alphanumeric character + * + ****************************************************************************/ + +#define ispunct(c) (isgraph(c) && !isalnum(c)) + +/**************************************************************************** + * Name: isxdigit + * + * Description: + * isxdigit() checks for a hexadecimal digits, i.e. one of {0-9,a-f,A-F} + * + ****************************************************************************/ + +#define isxdigit(c) \ + (((c) >= '0' && (c) <= '9') || \ + ((c) >= 'a' && (c) <= 'f') || \ + ((c) >= 'A' && (c) <= 'F')) + +/**************************************************************************** + * Name: toupper + * + * Description: + * toupper() converts the letter c to upper case, if possible. + * + ****************************************************************************/ + +#define toupper(c) \ + (((c) >= 'a' && (c) <= 'z') ? ((c) - 'a' + 'A') : (c)) + +/**************************************************************************** + * Name: tolower + * + * Description: + * tolower() converts the letter c to lower case, if possible. + * + ****************************************************************************/ + +#define tolower(c) \ + (((c) >= 'A' && (c) <= 'Z') ? ((c) - 'A' + 'a') : (c)) + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_CTYPE_H */ diff --git a/nuttx/include/cxx/cassert b/nuttx/include/cxx/cassert new file mode 100644 index 0000000000..b67592c2b5 --- /dev/null +++ b/nuttx/include/cxx/cassert @@ -0,0 +1,49 @@ +//*************************************************************************** +// include/cxx/cassert +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CASSERT +#define __INCLUDE_CXX_CASSERT + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +#endif // __INCLUDE_CXX_CASSERT diff --git a/nuttx/include/cxx/cctype b/nuttx/include/cxx/cctype new file mode 100644 index 0000000000..5d3b6dc701 --- /dev/null +++ b/nuttx/include/cxx/cctype @@ -0,0 +1,49 @@ +//*************************************************************************** +// include/cxx/cctype +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CCTYPE +#define __INCLUDE_CXX_CCTYPE + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +#endif // __INCLUDE_CXX_CCTYPE diff --git a/nuttx/include/cxx/cerrno b/nuttx/include/cxx/cerrno new file mode 100644 index 0000000000..59847df3ba --- /dev/null +++ b/nuttx/include/cxx/cerrno @@ -0,0 +1,49 @@ +//*************************************************************************** +// include/cxx/cerrno +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CERRNO +#define __INCLUDE_CXX_CERRNO + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +#endif // __INCLUDE_CXX_CERRNO diff --git a/nuttx/include/cxx/cfcntl b/nuttx/include/cxx/cfcntl new file mode 100644 index 0000000000..6907a53481 --- /dev/null +++ b/nuttx/include/cxx/cfcntl @@ -0,0 +1,57 @@ +//*************************************************************************** +// include/cxx/cfcntl +// +// Copyright (C) 2012 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CFCNTL +#define __INCLUDE_CXX_CFCNTL + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +namespace std +{ + using ::flock; + using ::creat; + using ::open; + using ::fcntl; +} + +#endif // __INCLUDE_CXX_CFCNTL diff --git a/nuttx/include/cxx/climits b/nuttx/include/cxx/climits new file mode 100644 index 0000000000..2cd543a0e5 --- /dev/null +++ b/nuttx/include/cxx/climits @@ -0,0 +1,49 @@ +//*************************************************************************** +// include/cxx/climits +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CLIMITS +#define __INCLUDE_CXX_CLIMITS + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +#endif // __INCLUDE_CXX_CLIMITS diff --git a/nuttx/include/cxx/cmath b/nuttx/include/cxx/cmath new file mode 100644 index 0000000000..7cb3a2109a --- /dev/null +++ b/nuttx/include/cxx/cmath @@ -0,0 +1,75 @@ +//*************************************************************************** +// include/cxx/cmath +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CMATH +#define __INCLUDE_CXX_CMATH + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +namespace std +{ + using ::acos; + using ::asin; + using ::atan; + using ::atan2; + using ::ceil; + using ::cos; + using ::cosh; + using ::exp; + using ::fabs; + using ::floor; + using ::fmod; + using ::frexp; + using ::ldexp; + using ::log; + using ::log10; + using ::modf; + using ::pow; + using ::sin; + using ::sinh; + using ::sqrt; + using ::tan; + using ::tanh; +} + +#endif // __INCLUDE_CXX_CMATH diff --git a/nuttx/include/cxx/csched b/nuttx/include/cxx/csched new file mode 100644 index 0000000000..262782888c --- /dev/null +++ b/nuttx/include/cxx/csched @@ -0,0 +1,74 @@ +//*************************************************************************** +// include/cxx/cfcntl +// +// Copyright (C) 2012 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CSCHED +#define __INCLUDE_CXX_CSCHED + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +namespace std +{ + using ::sched_param; + using ::task_init; + using ::task_activate; + using ::task_create; + using ::task_delete; + using ::task_restart; + using ::sched_setparam; + using ::sched_getparam; + using ::sched_setscheduler; + using ::sched_getscheduler; + using ::sched_get_priority_max; + using ::sched_get_priority_min; + using ::sched_rr_get_interval; + using ::sched_lock; + using ::sched_unlock; + using ::sched_lockcount; +#ifdef CONFIG_SCHED_INSTRUMENTATION + using ::sched_note_start; + using ::sched_note_stop; + using ::sched_note_switch; +#endif +} + +#endif // __INCLUDE_CXX_CSCHED diff --git a/nuttx/include/cxx/csignal b/nuttx/include/cxx/csignal new file mode 100644 index 0000000000..2303a864dd --- /dev/null +++ b/nuttx/include/cxx/csignal @@ -0,0 +1,72 @@ +//*************************************************************************** +// include/cxx/csignal +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CSIGNAL +#define __INCLUDE_CXX_CSIGNAL + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +namespace std +{ + using ::sigset_t; + using ::sigval; + using ::sigevent; + using ::siginfo; + using ::siginfo_t; + using ::sigaction; + using ::kill; + using ::sigemptyset; + using ::sigfillset; + using ::sigaddset; + using ::sigdelset; + using ::sigismember; + using ::sigaction; + using ::sigprocmask; + using ::sigpending; + using ::sigsuspend; + using ::sigwaitinfo; + using ::sigtimedwait; + using ::sigqueue; +} + +#endif // CSIGNAL_HEADER diff --git a/nuttx/include/cxx/cstdarg b/nuttx/include/cxx/cstdarg new file mode 100644 index 0000000000..4964f8e7c3 --- /dev/null +++ b/nuttx/include/cxx/cstdarg @@ -0,0 +1,49 @@ +//*************************************************************************** +// include/cxx/cstdarg +// +// Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CSTDARG +#define __INCLUDE_CXX_CSTDARG + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +#endif // __INCLUDE_CXX_CSTDARG diff --git a/nuttx/include/cxx/cstdbool b/nuttx/include/cxx/cstdbool new file mode 100644 index 0000000000..d2f0639d21 --- /dev/null +++ b/nuttx/include/cxx/cstdbool @@ -0,0 +1,49 @@ +//*************************************************************************** +// include/cxx/cstdbool +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CSTDBOOL +#define __INCLUDE_CXX_CSTDBOOL + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +#endif // __INCLUDE_CXX_CSTDBOOL diff --git a/nuttx/include/cxx/cstddef b/nuttx/include/cxx/cstddef new file mode 100644 index 0000000000..73dbcd526e --- /dev/null +++ b/nuttx/include/cxx/cstddef @@ -0,0 +1,81 @@ +//*************************************************************************** +// include/cxx/cstddef +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CCTYPE +#define __INCLUDE_CXX_CCTYPE + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include +#include + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +namespace std +{ + // Standard types + + using ::float32; +#ifndef CONFIG_HAVE_DOUBLE + using ::double_t; + using ::float64; +#else + using ::double_t; + using ::float64; +#endif + using ::mode_t; + using ::size_t; + using ::ssize_t; + using ::off_t; + using ::blksize_t; + using ::blkcnt_t; + using ::fpos_t; + using ::uid_t; + using ::gid_t; + using ::dev_t; + using ::ino_t; + using ::pid_t; + + using ::socklen_t; + using ::sa_family_t; +} + +#endif // __INCLUDE_CXX_CCTYPE diff --git a/nuttx/include/cxx/cstdint b/nuttx/include/cxx/cstdint new file mode 100644 index 0000000000..d662c5dc73 --- /dev/null +++ b/nuttx/include/cxx/cstdint @@ -0,0 +1,81 @@ +//*************************************************************************** +// include/cxx/cstdint +// +// Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CSTDINT +#define __INCLUDE_CXX_CSTDINT + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +namespace std +{ + using ::int8_t; + using ::int16_t; + using ::int32_t; + using ::int64_t; + using ::int_fast8_t; + using ::int_fast16_t; + using ::int_fast32_t; + using ::int_fast64_t; + using ::int_least8_t; + using ::int_least16_t; + using ::int_least32_t; + using ::int_least64_t; + using ::intmax_t; + using ::intptr_t; + using ::uint8_t; + using ::uint16_t; + using ::uint32_t; + using ::uint64_t; + using ::uint_fast8_t; + using ::uint_fast16_t; + using ::uint_fast32_t; + using ::uint_fast64_t; + using ::uint_least8_t; + using ::uint_least16_t; + using ::uint_least32_t; + using ::uint_least64_t; + using ::uintmax_t; + using ::uintptr_t; +} + +#endif // __INCLUDE_CXX_CSTDINT diff --git a/nuttx/include/cxx/cstdio b/nuttx/include/cxx/cstdio new file mode 100644 index 0000000000..900d429cb9 --- /dev/null +++ b/nuttx/include/cxx/cstdio @@ -0,0 +1,86 @@ +//*************************************************************************** +// include/cxx/cstdio +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CCTYPE +#define __INCLUDE_CXX_CCTYPE + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +namespace std +{ + using ::FILE; + using ::fpos_t; + using ::size_t; + using ::fclose; + using ::fflush; + using ::feof; + using ::ferror; + using ::fgetc; + using ::fgetpos; + using ::fgets; + using ::fopen; + using ::fprintf; + using ::fputc; + using ::fputs; + using ::fread; + using ::fseek; + using ::fsetpos; + using ::ftell; + using ::fwrite; + using ::gets; + using ::printf; + using ::puts; + using ::rename; + using ::sprintf; + using ::snprintf; + using ::ungetc; + using ::vprintf; + using ::vfprintf; + using ::vsprintf; + using ::vsnprintf; + using ::fdopen; + using ::statfs; +} + +#endif // __INCLUDE_CXX_CCTYPE diff --git a/nuttx/include/cxx/cstdlib b/nuttx/include/cxx/cstdlib new file mode 100644 index 0000000000..522f3fdb17 --- /dev/null +++ b/nuttx/include/cxx/cstdlib @@ -0,0 +1,84 @@ +//*************************************************************************** +// include/cxx/cstdlib +// +// Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CSTDLIB +#define __INCLUDE_CXX_CSTDLIB + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +namespace std +{ + using ::srand; + using ::rand; + +#ifndef CONFIG_DISABLE_ENIVRON + using ::getenv; + using ::putenv; + using ::clearenv; + using ::setenv; + using ::unsetenv; +#endif + + using ::exit; + using ::abort; +#ifdef CONFIG_SCHED_ATEXIT + using ::atexit; +#endif +#ifdef CONFIG_SCHED_ONEXIT + using ::on_exit; +#endif + + using ::strtol; + using ::strtod; + + using ::malloc; + using ::free; + using ::realloc; + using ::memalign; + using ::zalloc; + using ::calloc; + using ::mallinfo; +} + +#endif // __INCLUDE_CXX_CSTDLIB diff --git a/nuttx/include/cxx/cstring b/nuttx/include/cxx/cstring new file mode 100644 index 0000000000..84d98277d2 --- /dev/null +++ b/nuttx/include/cxx/cstring @@ -0,0 +1,85 @@ +//*************************************************************************** +// include/cxx/cstring +// +// Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CSTRING +#define __INCLUDE_CXX_CSTRING + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +namespace std +{ + using ::size_t; + + using ::strdup; + using ::strndup; + using ::strerror; + using ::strlen; + using ::strnlen; + using ::strcat; + using ::strncat; + using ::strcmp; + using ::strncmp; + using ::strcasecmp; + using ::strncasecmp; + using ::strcpy; + using ::strncpy; + using ::strpbrk; + using ::strchr; + using ::strrchr; + using ::strspn; + using ::strcspn; + using ::strstr; + using ::strcasestr; + using ::strtok; + using ::strtok_r; + + using ::memchr; + using ::memccpy; + using ::memcmp; + using ::memcpy; + using ::memmove; + using ::memset; +} + +#endif // __INCLUDE_CXX_CSTRING diff --git a/nuttx/include/cxx/ctime b/nuttx/include/cxx/ctime new file mode 100644 index 0000000000..3d3dfaec16 --- /dev/null +++ b/nuttx/include/cxx/ctime @@ -0,0 +1,71 @@ +//*************************************************************************** +// include/cxx/ctime +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CTIME +#define __INCLUDE_CXX_CTIME + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +namespace std +{ + using ::size_t; + using ::time_t; + using ::clockid_t; + using ::timer_t; + using ::timespec; + using ::timeval; + using ::tm; + using ::itimerspec; + using ::sigevent; + using ::clock_settime; + using ::clock_gettime; + using ::mktime; + using ::gmtime_r; + using ::timer_create; + using ::timer_delete; + using ::timer_settime; + using ::timer_gettime; + using ::timer_getoverrun; +} + +#endif // __INCLUDE_CXX_CTIME diff --git a/nuttx/include/cxx/cunistd b/nuttx/include/cxx/cunistd new file mode 100644 index 0000000000..2f0b712709 --- /dev/null +++ b/nuttx/include/cxx/cunistd @@ -0,0 +1,73 @@ +//*************************************************************************** +// include/cxx/cunistd +// +// Copyright (C) 2012 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __INCLUDE_CXX_CUNISTD +#define __INCLUDE_CXX_CUNISTD + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Namespace +//*************************************************************************** + +namespace std +{ + using ::getpid; + using ::_exit; + using ::sleep; + using ::usleep; + using ::close; + using ::dup; + using ::dup2; + using ::fsync; + using ::lseek; + using ::read; + using ::write; + using ::pipe; + using ::chdir; + using ::getcwd; + using ::unlink; + using ::rmdir; + using ::getopt; + using ::getoptargp; + using ::getopindgp; + using ::getoptoptp; +} + +#endif // __INCLUDE_CXX_CUNISTD diff --git a/nuttx/include/debug.h b/nuttx/include/debug.h new file mode 100644 index 0000000000..1f8c7d7caf --- /dev/null +++ b/nuttx/include/debug.h @@ -0,0 +1,632 @@ +/**************************************************************************** + * include/debug.h + * + * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_DEBUG_H +#define __INCLUDE_DEBUG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Debug macros to runtime filter the debug messages sent to the console. In + * general, there are four forms of the debug macros: + * + * [a-z]dbg() -- Outputs messages to the console similar to printf() except + * that the output is not buffered. The first character indicates the + * system system (e.g., n=network, f=filesystm, etc.). If the first + * character is missing (i.e., dbg()), then it is common. The common + * dbg() macro is enabled by CONFIG_DEBUG. Subystem debug requires an + * additional configuration setting to enable it (e.g., CONFIG_DEBUG_NET + * for the network, CONFIG_DEBUG_FS for the file syste, etc). + * + * In general, error messages and output of importance use [a-z]dbg(). + * [a-z]dbg() is implementation dependent but usually uses file descriptors. + * (that is a problem only because the interrupt task may have re- + * directed stdout). Therefore [a-z]dbg() should not be used in interrupt + * handlers. + * + * [a-z]vdbg() -- Identifcal to [a-z]dbg() except that it also requires that + * CONFIG_DEBUG_VERBOSE be defined. This is intended for general debug + * output that you would normally want to suppress. + * + * [a-z]lldbg() -- Identical to [a-z]dbg() except this is uses special + * interfaces provided by architecture-specific logic to talk directly + * to the underlying console hardware. If the architecture provides such + * logic, it should define CONFIG_ARCH_LOWPUTC. + * + * [a-z]lldbg() should not be used in normal code because the implementation + * probably disables interrupts and does things that are not consistent with + * good real-time performance. However, [a-z]lldbg() is particularly useful + * in low-level code where it is inappropriate to use file descriptors. For + * example, only [a-z]lldbg() should be used in interrupt handlers. + * + * [a-z]llvdbg() -- Identifcal to [a-z]lldbg() except that it also requires that + * CONFIG_DEBUG_VERBOSE be defined. This is intended for general debug + * output that you would normally want to suppress. + */ + +#ifdef CONFIG_HAVE_FUNCTIONNAME +# define EXTRA_FMT "%s: " +# define EXTRA_ARG ,__FUNCTION__ +#else +# define EXTRA_FMT +# define EXTRA_ARG +#endif + +/* Debug macros will differ depending upon if the toolchain supports + * macros with a variable number of arguments or not. + */ + +#ifdef CONFIG_CPP_HAVE_VARARGS + +/* Variable argument macros supported */ + +#ifdef CONFIG_DEBUG +# define dbg(format, arg...) \ + lib_rawprintf(EXTRA_FMT format EXTRA_ARG, ##arg) + +# ifdef CONFIG_ARCH_LOWPUTC +# define lldbg(format, arg...) \ + lib_lowprintf(EXTRA_FMT format EXTRA_ARG, ##arg) +# else +# define lldbg(x...) +# endif + +# ifdef CONFIG_DEBUG_VERBOSE +# define vdbg(format, arg...) \ + lib_rawprintf(EXTRA_FMT format EXTRA_ARG, ##arg) + +# ifdef CONFIG_ARCH_LOWPUTC +# define llvdbg(format, arg...) \ + lib_lowprintf(EXTRA_FMT format EXTRA_ARG, ##arg) +# else +# define llvdbg(x...) +# endif + +# else +# define vdbg(x...) +# define llvdbg(x...) +# endif + +#else /* CONFIG_DEBUG */ + +# define dbg(x...) +# define lldbg(x...) +# define vdbg(x...) +# define llvdbg(x...) + +#endif /* CONFIG_DEBUG */ + +/* Subsystem specific debug */ + +#ifdef CONFIG_DEBUG_MM +# define mdbg(format, arg...) dbg(format, ##arg) +# define mlldbg(format, arg...) lldbg(format, ##arg) +# define mvdbg(format, arg...) vdbg(format, ##arg) +# define mllvdbg(format, arg...) llvdbg(format, ##arg) +#else +# define mdbg(x...) +# define mlldbg(x...) +# define mvdbg(x...) +# define mllvdbg(x...) +#endif + +#ifdef CONFIG_DEBUG_SCHED +# define sdbg(format, arg...) dbg(format, ##arg) +# define slldbg(format, arg...) lldbg(format, ##arg) +# define svdbg(format, arg...) vdbg(format, ##arg) +# define sllvdbg(format, arg...) llvdbg(format, ##arg) +#else +# define sdbg(x...) +# define slldbg(x...) +# define svdbg(x...) +# define sllvdbg(x...) +#endif + +#ifdef CONFIG_DEBUG_PAGING +# define pgdbg(format, arg...) dbg(format, ##arg) +# define pglldbg(format, arg...) lldbg(format, ##arg) +# define pgvdbg(format, arg...) vdbg(format, ##arg) +# define pgllvdbg(format, arg...) llvdbg(format, ##arg) +#else +# define pgdbg(x...) +# define pglldbg(x...) +# define pgvdbg(x...) +# define pgllvdbg(x...) +#endif + +#ifdef CONFIG_DEBUG_DMA +# define dmadbg(format, arg...) dbg(format, ##arg) +# define dmalldbg(format, arg...) lldbg(format, ##arg) +# define dmavdbg(format, arg...) vdbg(format, ##arg) +# define dmallvdbg(format, arg...) llvdbg(format, ##arg) +#else +# define dmadbg(x...) +# define dmalldbg(x...) +# define dmavdbg(x...) +# define dmallvdbg(x...) +#endif + +#ifdef CONFIG_DEBUG_NET +# define ndbg(format, arg...) dbg(format, ##arg) +# define nlldbg(format, arg...) lldbg(format, ##arg) +# define nvdbg(format, arg...) vdbg(format, ##arg) +# define nllvdbg(format, arg...) llvdbg(format, ##arg) +#else +# define ndbg(x...) +# define nlldbg(x...) +# define nvdbg(x...) +# define nllvdbg(x...) +#endif + +#ifdef CONFIG_DEBUG_USB +# define udbg(format, arg...) dbg(format, ##arg) +# define ulldbg(format, arg...) lldbg(format, ##arg) +# define uvdbg(format, arg...) vdbg(format, ##arg) +# define ullvdbg(format, arg...) llvdbg(format, ##arg) +#else +# define udbg(x...) +# define ulldbg(x...) +# define uvdbg(x...) +# define ullvdbg(x...) +#endif + +#ifdef CONFIG_DEBUG_FS +# define fdbg(format, arg...) dbg(format, ##arg) +# define flldbg(format, arg...) lldbg(format, ##arg) +# define fvdbg(format, arg...) vdbg(format, ##arg) +# define fllvdbg(format, arg...) llvdbg(format, ##arg) +#else +# define fdbg(x...) +# define flldbg(x...) +# define fvdbg(x...) +# define fllvdbg(x...) +#endif + +#ifdef CONFIG_DEBUG_INPUT +# define idbg(format, arg...) dbg(format, ##arg) +# define illdbg(format, arg...) lldbg(format, ##arg) +# define ivdbg(format, arg...) vdbg(format, ##arg) +# define illvdbg(format, arg...) llvdbg(format, ##arg) +#else +# define idbg(x...) +# define illdbg(x...) +# define ivdbg(x...) +# define illvdbg(x...) +#endif + +#ifdef CONFIG_DEBUG_ANALOG +# define adbg(format, arg...) dbg(format, ##arg) +# define alldbg(format, arg...) lldbg(format, ##arg) +# define avdbg(format, arg...) vdbg(format, ##arg) +# define allvdbg(format, arg...) llvdbg(format, ##arg) +#else +# define adbg(x...) +# define alldbg(x...) +# define avdbg(x...) +# define allvdbg(x...) +#endif + +#ifdef CONFIG_DEBUG_GRAPHICS +# define gdbg(format, arg...) dbg(format, ##arg) +# define glldbg(format, arg...) lldbg(format, ##arg) +# define gvdbg(format, arg...) vdbg(format, ##arg) +# define gllvdbg(format, arg...) llvdbg(format, ##arg) +#else +# define gdbg(x...) +# define glldbg(x...) +# define gvdbg(x...) +# define gllvdbg(x...) +#endif + +#ifdef CONFIG_DEBUG_BINFMT +# define bdbg(format, arg...) dbg(format, ##arg) +# define blldbg(format, arg...) lldbg(format, ##arg) +# define bvdbg(format, arg...) vdbg(format, ##arg) +# define bllvdbg(format, arg...) llvdbg(format, ##arg) +#else +# define bdbg(x...) +# define blldbg(x...) +# define bvdbg(x...) +# define bllvdbg(x...) +#endif + +#ifdef CONFIG_DEBUG_LIB +# define ldbg(format, arg...) dbg(format, ##arg) +# define llldbg(format, arg...) lldbg(format, ##arg) +# define lvdbg(format, arg...) vdbg(format, ##arg) +# define lllvdbg(format, arg...) llvdbg(format, ##arg) +#else +# define ldbg(x...) +# define llldbg(x...) +# define lvdbg(x...) +# define lllvdbg(x...) +#endif + +#else /* CONFIG_CPP_HAVE_VARARGS */ + +/* Variable argument macros NOT supported */ + +#ifdef CONFIG_DEBUG +# ifndef CONFIG_ARCH_LOWPUTC +# define lldbg (void) +# endif +# ifndef CONFIG_DEBUG_VERBOSE +# define vdbg (void) +# define llvdbg (void) +# else +# ifndef CONFIG_ARCH_LOWPUTC +# define llvdbg (void) +# endif +# endif +#else +# define dbg (void) +# define lldbg (void) +# define vdbg (void) +# define llvdbg (void) +#endif + +/* Subsystem specific debug */ + +#ifdef CONFIG_DEBUG_MM +# define mdbg dbg +# define mlldbg lldbg +# define mvdbg vdbg +# define mllvdbg llvdbg +#else +# define mdbg (void) +# define mlldbg (void) +# define mvdbg (void) +# define mllvdbg (void) +#endif + +#ifdef CONFIG_DEBUG_SCHED +# define sdbg dbg +# define slldbg lldbg +# define svdbg vdbg +# define sllvdbg llvdbg +#else +# define sdbg (void) +# define slldbg (void) +# define svdbg (void) +# define sllvdbg (void) +#endif + +#ifdef CONFIG_DEBUG_PAGING +# define pgdbg dbg +# define pglldbg lldbg +# define pgvdbg vdbg +# define pgllvdbg llvdbg +#else +# define pgdbg (void) +# define pglldbg (void) +# define pgvdbg (void) +# define pgllvdbg (void) +#endif + +#ifdef CONFIG_DEBUG_DMA +# define dmadbg dbg +# define dmalldbg lldbg +# define dmavdbg vdbg +# define dmallvdbg llvdbg +#else +# define dmadbg (void) +# define dmalldbg (void) +# define dmavdbg (void) +# define dmallvdbg (void) +#endif + +#ifdef CONFIG_DEBUG_NET +# define ndbg dbg +# define nlldbg lldbg +# define nvdbg vdbg +# define nllvdbg llvdbg +#else +# define ndbg (void) +# define nlldbg (void) +# define nvdbg (void) +# define nllvdbg (void) +#endif + +#ifdef CONFIG_DEBUG_USB +# define udbg dbg +# define ulldbg lldbg +# define uvdbg vdbg +# define ullvdbg llvdbg +#else +# define udbg (void) +# define ulldbg (void) +# define uvdbg (void) +# define ullvdbg (void) +#endif + +#ifdef CONFIG_DEBUG_FS +# define fdbg dbg +# define flldbg lldbg +# define fvdbg vdbg +# define fllvdbg llvdbg +#else +# define fdbg (void) +# define flldbg (void) +# define fvdbg (void) +# define fllvdbg (void) +#endif + +#ifdef CONFIG_DEBUG_INPUT +# define idbg dbg +# define illdbg lldbg +# define ivdbg vdbg +# define illvdbg llvdbg +#else +# define idbg (void) +# define illdbg (void) +# define ivdbg (void) +# define illvdbg (void) +#endif + +#ifdef CONFIG_DEBUG_ANALOG +# define adbg dbg +# define alldbg lldbg +# define avdbg vdbg +# define allvdbg llvdbg +#else +# define adbg (void) +# define alldbg (void) +# define avdbg (void) +# define allvdbg (void) +#endif + +#ifdef CONFIG_DEBUG_GRAPHICS +# define gdbg dbg +# define glldbg lldbg +# define gvdbg vdbg +# define gllvdbg llvdbg +#else +# define gdbg (void) +# define glldbg (void) +# define gvdbg (void) +# define gllvdbg (void) +#endif + +#ifdef CONFIG_DEBUG_BINFMT +# define bdbg dbg +# define blldbg lldbg +# define bvdbg vdbg +# define bllvdbg llvdbg +#else +# define bdbg (void) +# define blldbg (void) +# define bvdbg (void) +# define bllvdbg (void) +#endif + +#ifdef CONFIG_DEBUG_LIB +# define ldbg dbg +# define llldbg lldbg +# define lvdbg vdbg +# define lllvdbg llvdbg +#else +# define ldbg (void) +# define llldbg (void) +# define lvdbg (void) +# define lllvdbg (void) +#endif + +#endif /* CONFIG_CPP_HAVE_VARARGS */ + +/* Buffer dumping macros do not depend on varargs */ + +#ifdef CONFIG_DEBUG +# define dbgdumpbuffer(m,b,n) lib_dumpbuffer(m,b,n) +# ifdef CONFIG_DEBUG_VERBOSE +# define vdbgdumpbuffer(m,b,n) lib_dumpbuffer(m,b,n) +# else +# define vdbgdumpbuffer(m,b,n) +# endif +#else +# define dbgdumpbuffer(m,b,n) +# define vdbgdumpbuffer(m,b,n) +# endif + +/* Subsystem specific debug */ + +#ifdef CONFIG_DEBUG_MM +# define mdbgdumpbuffer(m,b,n) dbgdumpbuffer(m,b,n) +# define mvdbgdumpbuffer(m,b,n) vdbgdumpbuffer(m,b,n) +#else +# define mdbgdumpbuffer(m,b,n) +# define mvdbgdumpbuffer(m,b,n) +#endif + +#ifdef CONFIG_DEBUG_SCHED +# define sdbgdumpbuffer(m,b,n) dbgdumpbuffer(m,b,n) +# define svdbgdumpbuffer(m,b,n) vdbgdumpbuffer(m,b,n) +#else +# define sdbgdumpbuffer(m,b,n) +# define svdbgdumpbuffer(m,b,n) +#endif + +#ifdef CONFIG_DEBUG_PAGING +# define pgdbgdumpbuffer(m,b,n) dbgdumpbuffer(m,b,n) +# define pgvdbgdumpbuffer(m,b,n) vdbgdumpbuffer(m,b,n) +#else +# define pgdbgdumpbuffer(m,b,n) +# define pgvdbgdumpbuffer(m,b,n) +#endif + +#ifdef CONFIG_DEBUG_DMA +# define dmadbgdumpbuffer(m,b,n) dbgdumpbuffer(m,b,n) +# define dmavdbgdumpbuffer(m,b,n) vdbgdumpbuffer(m,b,n) +#else +# define dmadbgdumpbuffer(m,b,n) +# define dmavdbgdumpbuffer(m,b,n) +#endif + +#ifdef CONFIG_DEBUG_NET +# define ndbgdumpbuffer(m,b,n) dbgdumpbuffer(m,b,n) +# define nvdbgdumpbuffer(m,b,n) vdbgdumpbuffer(m,b,n) +#else +# define ndbgdumpbuffer(m,b,n) +# define nvdbgdumpbuffer(m,b,n) +#endif + +#ifdef CONFIG_DEBUG_USB +# define udbgdumpbuffer(m,b,n) dbgdumpbuffer(m,b,n) +# define uvdbgdumpbuffer(m,b,n) vdbgdumpbuffer(m,b,n) +#else +# define udbgdumpbuffer(m,b,n) +# define uvdbgdumpbuffer(m,b,n) +#endif + +#ifdef CONFIG_DEBUG_FS +# define fdbgdumpbuffer(m,b,n) dbgdumpbuffer(m,b,n) +# define fvdbgdumpbuffer(m,b,n) vdbgdumpbuffer(m,b,n) +#else +# define fdbgdumpbuffer(m,b,n) +# define fvdbgdumpbuffer(m,b,n) +#endif + +#ifdef CONFIG_DEBUG_INPUT +# define idbgdumpbuffer(m,b,n) dbgdumpbuffer(m,b,n) +# define ivdbgdumpbuffer(m,b,n) vdbgdumpbuffer(m,b,n) +#else +# define idbgdumpbuffer(m,b,n) +# define ivdbgdumpbuffer(m,b,n) +#endif + +#ifdef CONFIG_DEBUG_GRAPHICS +# define gdbgdumpbuffer(m,b,n) dbgdumpbuffer(m,b,n) +# define gvdbgdumpbuffer(m,b,n) vdbgdumpbuffer(m,b,n) +#else +# define gdbgdumpbuffer(m,b,n) +# define gvdbgdumpbuffer(m,b,n) +#endif + +#ifdef CONFIG_DEBUG_BINFMT +# define bdbgdumpbuffer(m,b,n) dbgdumpbuffer(m,b,n) +# define bvdbgdumpbuffer(m,b,n) vdbgdumpbuffer(m,b,n) +#else +# define bdbgdumpbuffer(m,b,n) +# define bvdbgdumpbuffer(m,b,n) +#endif + +#ifdef CONFIG_DEBUG_LIB +# define ldbgdumpbuffer(m,b,n) dbgdumpbuffer(m,b,n) +# define lvdbgdumpbuffer(m,b,n) vdbgdumpbuffer(m,b,n) +#else +# define ldbgdumpbuffer(m,b,n) +# define lvdbgdumpbuffer(m,b,n) +#endif + +/**************************************************************************** + * Public Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* These low-level debug APIs are provided by the NuttX library. If the + * cross-compiler's pre-processor supports a variable number of macro + * arguments, then the macros below will map all debug statements to one + * or the other of the following. + */ + +EXTERN int lib_rawprintf(FAR const char *format, ...); + +#ifdef CONFIG_ARCH_LOWPUTC +EXTERN int lib_lowprintf(FAR const char *format, ...); +#endif + +/* Dump a buffer of data */ + +EXTERN void lib_dumpbuffer(FAR const char *msg, FAR const uint8_t *buffer, + unsigned int buflen); + +/* Enable or disable debug output */ + +#ifdef CONFIG_DEBUG_ENABLE +EXTERN void dbg_enable(bool enable); +#endif + +/* If the cross-compiler's pre-processor does not support variable length + * arguments, then these additional APIs will be built. + */ + +#ifndef CONFIG_CPP_HAVE_VARARGS +#ifdef CONFIG_DEBUG +EXTERN int dbg(const char *format, ...); + +# ifdef CONFIG_ARCH_LOWPUTC +EXTERN int lldbg(const char *format, ...); +# endif + +# ifdef CONFIG_DEBUG_VERBOSE +EXTERN int vdbg(const char *format, ...); + +# ifdef CONFIG_ARCH_LOWPUTC +EXTERN int llvdbg(const char *format, ...); +# endif +#endif +#endif /* CONFIG_DEBUG */ +#endif /* CONFIG_CPP_HAVE_VARARGS */ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_DEBUG_H */ diff --git a/nuttx/include/dirent.h b/nuttx/include/dirent.h new file mode 100644 index 0000000000..1eea999a12 --- /dev/null +++ b/nuttx/include/dirent.h @@ -0,0 +1,117 @@ +/**************************************************************************** + * include/dirent.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_DIRENT_H +#define __INCLUDE_DIRENT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* File type code for the d_type field in dirent struct. + * Note that because of the simplified filesystem organization + * of NuttX, an inode can be BOTH a file and a directory + */ + +#define DTYPE_FILE 0x01 +#define DTYPE_CHR 0x02 +#define DTYPE_BLK 0x04 +#define DTYPE_DIRECTORY 0x08 + +#define DIRENT_ISFILE(dtype) (((dtype) & DTYPE_FILE) != 0 ) +#define DIRENT_ISCHR(dtype) (((dtype) & DTYPE_CHR) != 0 ) +#define DIRENT_ISBLK(dtype) (((dtype) & DTYPE_BLK) != 0 ) +#define DIRENT_ISDIRECTORY(dtype) (((dtype) & DTYPE_DIRECTORY) != 0 ) + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* The POSIX specification requires that the caller of readdir_r provide + * storage "large enough for a dirent with the d_name member and an array + * of char containing at least {NAME_MAX} plus one elements. + */ + +struct dirent +{ + uint8_t d_type; /* type of file */ + char d_name[NAME_MAX+1]; /* filename */ +}; + +typedef void DIR; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* POSIX-like File System Interfaces */ + +EXTERN int closedir(FAR DIR *dirp); +EXTERN FAR DIR *opendir(FAR const char *path); +EXTERN FAR struct dirent *readdir(FAR DIR *dirp); +EXTERN int readdir_r(FAR DIR *dirp, FAR struct dirent *entry, + FAR struct dirent **result); +EXTERN void rewinddir(FAR DIR *dirp); +EXTERN void seekdir(FAR DIR *dirp, off_t loc); +EXTERN off_t telldir(FAR DIR *dirp); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_DIRENT_H */ diff --git a/nuttx/include/errno.h b/nuttx/include/errno.h new file mode 100644 index 0000000000..ba4dcbd049 --- /dev/null +++ b/nuttx/include/errno.h @@ -0,0 +1,369 @@ +/************************************************************************ + * include/errno.h + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +#ifndef __INCLUDE_ERRNO_H +#define __INCLUDE_ERRNO_H + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +/************************************************************************ + * Definitions + ************************************************************************/ + +/* Convenience/compatibility definition. + * + * For a flat, all kernel-mode build, the error can be read and written + * from all code using a simple pointer. + */ + +#ifndef CONFIG_NUTTX_KERNEL + +# define errno *get_errno_ptr() +# define set_errno(e) do { errno = (int)(e); } while (0) +# define get_errno(e) errno + +#else + +/* We doing separate user-/kernel-mode builds, then the errno has to be + * a little differently. In kernel-mode, the TCB errno value can still be + * read and written using a pointer. + */ + +#ifdef __KERNEL__ +# define errno *get_errno_ptr() +#else + +/* But in user-mode, the errno can only be read using the name 'errno'. + * The non-standard API set_errno() must be explicity be used from user- + * mode code in order to set the errno value. + */ + +# define errno get_errno() + +#endif /* __KERNEL__ */ +#endif /* CONFIG_NUTTX_KERNEL */ + +/* Definitions of error numbers and the string that would be + * returned by strerror(). + */ + +#define EPERM 1 +#define EPERM_STR "Operation not permitted" +#define ENOENT 2 +#define ENOENT_STR "No such file or directory" +#define ESRCH 3 +#define ESRCH_STR "No such process" +#define EINTR 4 +#define EINTR_STR "Interrupted system call" +#define EIO 5 +#define EIO_STR "I/O error" +#define ENXIO 6 +#define ENXIO_STR "No such device or address" +#define E2BIG 7 +#define E2BIG_STR "Arg list too long" +#define ENOEXEC 8 +#define ENOEXEC_STR "Exec format error" +#define EBADF 9 +#define EBADF_STR "Bad file number" +#define ECHILD 10 +#define ECHILD_STR "No child processes" +#define EAGAIN 11 +#define EWOULDBLOCK EAGAIN +#define EAGAIN_STR "Try again" +#define ENOMEM 12 +#define ENOMEM_STR "Out of memory" +#define EACCES 13 +#define EACCES_STR "Permission denied" +#define EFAULT 14 +#define EFAULT_STR "Bad address" +#define ENOTBLK 15 +#define ENOTBLK_STR "Block device required" +#define EBUSY 16 +#define EBUSY_STR "Device or resource busy" +#define EEXIST 17 +#define EEXIST_STR "File exists" +#define EXDEV 18 +#define EXDEV_STR "Cross-device link" +#define ENODEV 19 +#define ENODEV_STR "No such device" +#define ENOTDIR 20 +#define ENOTDIR_STR "Not a directory" +#define EISDIR 21 +#define EISDIR_STR "Is a directory" +#define EINVAL 22 +#define EINVAL_STR "Invalid argument" +#define ENFILE 23 +#define ENFILE_STR "File table overflow" +#define EMFILE 24 +#define EMFILE_STR "Too many open files" +#define ENOTTY 25 +#define ENOTTY_STR "Not a typewriter" +#define ETXTBSY 26 +#define ETXTBSY_STR "Text file busy" +#define EFBIG 27 +#define EFBIG_STR "File too large" +#define ENOSPC 28 +#define ENOSPC_STR "No space left on device" +#define ESPIPE 29 +#define ESPIPE_STR "Illegal seek" +#define EROFS 30 +#define EROFS_STR "Read-only file system" +#define EMLINK 31 +#define EMLINK_STR "Too many links" +#define EPIPE 32 +#define EPIPE_STR "Broken pipe" +#define EDOM 33 +#define EDOM_STR "Math argument out of domain of func" +#define ERANGE 34 +#define ERANGE_STR "Math result not representable" +#define EDEADLK 35 +#define EDEADLOCK EDEADLK +#define EDEADLK_STR "Resource deadlock would occur" +#define ENAMETOOLONG 36 +#define ENAMETOOLONG_STR "File name too long" +#define ENOLCK 37 +#define ENOLCK_STR "No record locks available" +#define ENOSYS 38 +#define ENOSYS_STR "Function not implemented" +#define ENOTEMPTY 39 +#define ENOTEMPTY_STR "Directory not empty" +#define ELOOP 40 +#define ELOOP_STR "Too many symbolic links encountered" +#define ENOMSG 42 +#define ENOMSG_STR "No message of desired type" +#define EIDRM 43 +#define EIDRM_STR "Identifier removed" +#define ECHRNG 44 +#define ECHRNG_STR "Channel number out of range" +#define EL2NSYNC 45 +#define EL2NSYNC_STR "Level 2 not synchronized" +#define EL3HLT 46 +#define EL3HLT_STR "Level 3 halted" +#define EL3RST 47 +#define EL3RST_STR "Level 3 reset" +#define ELNRNG 48 +#define ELNRNG_STR "Link number out of range" +#define EUNATCH 49 +#define EUNATCH_STR "Protocol driver not attached" +#define ENOCSI 50 +#define ENOCSI_STR "No CSI structure available" +#define EL2HLT 51 +#define EL2HLT_STR "Level 2 halted" +#define EBADE 52 +#define EBADE_STR "Invalid exchange" +#define EBADR 53 +#define EBADR_STR "Invalid request descriptor" +#define EXFULL 54 +#define EXFULL_STR "Exchange full" +#define ENOANO 55 +#define ENOANO_STR "No anode" +#define EBADRQC 56 +#define EBADRQC_STR "Invalid request code" +#define EBADSLT 57 +#define EBADSLT_STR "Invalid slot" +#define EBFONT 59 +#define EBFONT_STR "Bad font file format" +#define ENOSTR 60 +#define ENOSTR_STR "Device not a stream" +#define ENODATA 61 +#define ENODATA_STR "No data available" +#define ETIME 62 +#define ETIME_STR "Timer expired" +#define ENOSR 63 +#define ENOSR_STR "Out of streams resources" +#define ENONET 64 +#define ENONET_STR "Machine is not on the network" +#define ENOPKG 65 +#define ENOPKG_STR "Package not installed" +#define EREMOTE 66 +#define EREMOTE_STR "Object is remote" +#define ENOLINK 67 +#define ENOLINK_STR "Link has been severed" +#define EADV 68 +#define EADV_STR "Advertise error" +#define ESRMNT 69 +#define ESRMNT_STR "Srmount error" +#define ECOMM 70 +#define ECOMM_STR "Communication error on send" +#define EPROTO 71 +#define EPROTO_STR "Protocol error" +#define EMULTIHOP 72 +#define EMULTIHOP_STR "Multihop attempted" +#define EDOTDOT 73 +#define EDOTDOT_STR "RFS specific error" +#define EBADMSG 74 +#define EBADMSG_STR "Not a data message" +#define EOVERFLOW 75 +#define EOVERFLOW_STR "Value too large for defined data type" +#define ENOTUNIQ 76 +#define ENOTUNIQ_STR "Name not unique on network" +#define EBADFD 77 +#define EBADFD_STR "File descriptor in bad state" +#define EREMCHG 78 +#define EREMCHG_STR "Remote address changed" +#define ELIBACC 79 +#define ELIBACC_STR "Can not access a needed shared library" +#define ELIBBAD 80 +#define ELIBBAD_STR "Accessing a corrupted shared library" +#define ELIBSCN 81 +#define ELIBSCN_STR ".lib section in a.out corrupted" +#define ELIBMAX 82 +#define ELIBMAX_STR "Attempting to link in too many shared libraries" +#define ELIBEXEC 83 +#define ELIBEXEC_STR "Cannot exec a shared library directly" +#define EILSEQ 84 +#define EILSEQ_STR "Illegal byte sequence" +#define ERESTART 85 +#define ERESTART_STR "Interrupted system call should be restarted" +#define ESTRPIPE 86 +#define ESTRPIPE_STR "Streams pipe error" +#define EUSERS 87 +#define EUSERS_STR "Too many users" +#define ENOTSOCK 88 +#define ENOTSOCK_STR "Socket operation on non-socket" +#define EDESTADDRREQ 89 +#define EDESTADDRREQ_STR "Destination address required" +#define EMSGSIZE 90 +#define EMSGSIZE_STR "Message too long" +#define EPROTOTYPE 91 +#define EPROTOTYPE_STR "Protocol wrong type for socket" +#define ENOPROTOOPT 92 +#define ENOPROTOOPT_STR "Protocol not available" +#define EPROTONOSUPPORT 93 +#define EPROTONOSUPPORT_STR "Protocol not supported" +#define ESOCKTNOSUPPORT 94 +#define ESOCKTNOSUPPORT_STR "Socket type not supported" +#define EOPNOTSUPP 95 +#define EOPNOTSUPP_STR "Operation not supported on transport endpoint" +#define EPFNOSUPPORT 96 +#define EPFNOSUPPORT_STR "Protocol family not supported" +#define EAFNOSUPPORT 97 +#define EAFNOSUPPORT_STR "Address family not supported by protocol" +#define EADDRINUSE 98 +#define EADDRINUSE_STR "Address already in use" +#define EADDRNOTAVAIL 99 +#define EADDRNOTAVAIL_STR "Cannot assign requested address" +#define ENETDOWN 100 +#define ENETDOWN_STR "Network is down" +#define ENETUNREACH 101 +#define ENETUNREACH_STR "Network is unreachable" +#define ENETRESET 102 +#define ENETRESET_STR "Network dropped connection because of reset" +#define ECONNABORTED 103 +#define ECONNABORTED_STR "Software caused connection abort" +#define ECONNRESET 104 +#define ECONNRESET_STR "Connection reset by peer" +#define ENOBUFS 105 +#define ENOBUFS_STR "No buffer space available" +#define EISCONN 106 +#define EISCONN_STR "Transport endpoint is already connected" +#define ENOTCONN 107 +#define ENOTCONN_STR "Transport endpoint is not connected" +#define ESHUTDOWN 108 +#define ESHUTDOWN_STR "Cannot send after transport endpoint shutdown" +#define ETOOMANYREFS 109 +#define ETOOMANYREFS_STR "Too many references: cannot splice" +#define ETIMEDOUT 110 +#define ETIMEDOUT_STR "Connection timed out" +#define ECONNREFUSED 111 +#define ECONNREFUSED_STR "Connection refused" +#define EHOSTDOWN 112 +#define EHOSTDOWN_STR "Host is down" +#define EHOSTUNREACH 113 +#define EHOSTUNREACH_STR "No route to host" +#define EALREADY 114 +#define EALREADY_STR "Operation already in progress" +#define EINPROGRESS 115 +#define EINPROGRESS_STR "Operation now in progress" +#define ESTALE 116 +#define ESTALE_STR "Stale NFS file handle" +#define EUCLEAN 117 +#define EUCLEAN_STR "Structure needs cleaning" +#define ENOTNAM 118 +#define ENOTNAM_STR "Not a XENIX named type file" +#define ENAVAIL 119 +#define ENAVAIL_STR "No XENIX semaphores available" +#define EISNAM 120 +#define EISNAM_STR "Is a named type file" +#define EREMOTEIO 121 +#define EREMOTEIO_STR "Remote I/O error" +#define EDQUOT 122 +#define EDQUOT_STR "Quota exceeded" +#define ENOMEDIUM 123 +#define ENOMEDIUM_STR "No medium found" +#define EMEDIUMTYPE 124 +#define EMEDIUMTYPE_STR "Wrong medium type" + +/************************************************************************ + * Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Function Prototypes + ************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Return a pointer to the thread specific errno. NOTE: When doing a + * kernel-/user-mode build, this function can only be used within the + * kernel-mode space. + * + * In the user-mode space, set_errno() and get_errno() are always available, + * either as macros or via syscalls. + */ + +EXTERN FAR int *get_errno_ptr(void); + +#ifdef CONFIG_NUTTX_KERNEL +EXTERN void set_errno(int errcode); +EXTERN int get_errno(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_ERRNO_H */ diff --git a/nuttx/include/fcntl.h b/nuttx/include/fcntl.h new file mode 100644 index 0000000000..382c5be16b --- /dev/null +++ b/nuttx/include/fcntl.h @@ -0,0 +1,161 @@ +/******************************************************************************** + * include/fcntl.h + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +#ifndef __INCLUDE_FCNTL_H +#define __INCLUDE_FCNTL_H + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/* open flag settings for open() (and related APIs) */ + +#define O_RDONLY (1 << 0) /* Open for read access (only) */ +#define O_RDOK O_RDONLY /* Read access is permitted (non-standard) */ +#define O_WRONLY (1 << 1) /* Open for write access (only) */ +#define O_WROK O_WRONLY /* Write access is permitted (non-standard) */ +#define O_RDWR (O_RDOK|O_WROK) /* Open for both read & write access */ +#define O_CREAT (1 << 2) /* Create file/sem/mq object */ +#define O_EXCL (1 << 3) /* Name must not exist when opened */ +#define O_APPEND (1 << 4) /* Keep contents, append to end */ +#define O_TRUNC (1 << 5) /* Delete contents */ +#define O_NONBLOCK (1 << 6) /* Don't wait for data */ +#define O_NDELAY O_NONBLOCK /* Synonym for O_NONBLOCK */ +#define O_SYNC (1 << 7) /* Synchronize output on write */ +#define O_DSYNC O_SYNC /* Equivalent to OSYNC in NuttX */ +#define O_BINARY (1 << 8) /* Open the file in binary (untranslated) mode. */ + +/* Unsupported, but required open flags */ + +#define O_RSYNC 0 /* Synchronize input on read */ +#define O_ACCMODE 0 /* Required by POSIX */ +#define O_NOCTTY 0 /* Required by POSIX */ +#define O_TEXT 0 /* Open the file in text (translated) mode. */ + +/* This is the highest bit number used in the open flags bitset. Bits above + * this bit number may be used within NuttX for other, internal purposes. + */ + +#define _O_MAXBIT 8 + +/* fcntl() commands */ + +#define F_DUPFD 0 /* Duplicate a file descriptor */ +#define F_GETFD 1 /* Read the file descriptor flags */ +#define F_GETFL 2 /* Read the file status flags */ +#define F_GETLEASE 3 /* Indicates what type of lease is held on fd (linux) */ +#define F_GETLK 4 /* Check if we could place a lock */ +#define F_GETOWN 5 /* Get the pid receiving SIGIO and SIGURG signals for fd */ +#define F_GETSIG 6 /* Get the signal sent */ +#define F_NOTIFY 7 /* Provide notification when directory referred to by fd changes (linux)*/ +#define F_SETFD 8 /* Set the file descriptor flags to value */ +#define F_SETFL 9 /* Set the file status flags to the value */ +#define F_SETLEASE 10 /* Set or remove file lease (linux) */ +#define F_SETLK 11 /* Acquire or release a lock on range of bytes */ +#define F_SETLKW 12 /* Like F_SETLK, but wait for lock to become available */ +#define F_SETOWN 13 /* Set pid that will receive SIGIO and SIGURG signals for fd */ +#define F_SETSIG 14 /* Set the signal to be sent */ + +/* For posix fcntl() and lockf() */ + +#define F_RDLCK 0 /* Take out a read lease */ +#define F_WRLCK 1 /* Take out a write lease */ +#define F_UNLCK 2 /* Remove a lease */ + +/* close-on-exec flag for F_GETRL and F_SETFL */ + +#define FD_CLOEXEC 1 + +/* These are the notifications that can be received from F_NOTIFY (linux) */ + +#define DN_ACCESS 0 /* A file was accessed */ +#define DN_MODIFY 1 /* A file was modified */ +#define DN_CREATE 2 /* A file was created */ +#define DN_DELETE 3 /* A file was unlinked */ +#define DN_RENAME 4 /* A file was renamed */ +#define DN_ATTRIB 5 /* Attributes of a file were changed */ + +/******************************************************************************** + * Public Type Definitions + ********************************************************************************/ + +/* struct flock is the third argument for F_GETLK, F_SETLK and F_SETLKW */ + +struct flock +{ + int16_t l_type; /* Type of lock: F_RDLCK, F_WRLCK, F_UNLCK */ + int16_t l_whence; /* How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END */ + off_t l_start; /* Starting offset for lock */ + off_t l_len; /* Number of bytes to lock */ + pid_t l_pid; /* PID of process blocking our lock (F_GETLK only) */ +}; + +/******************************************************************************** + * Public Variables + ********************************************************************************/ + +/******************************************************************************** + * Public Function Prototypes + ********************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* POSIX-like File System Interfaces */ + +EXTERN int creat(const char *path, mode_t mode); +EXTERN int open(const char *path, int oflag, ...); +EXTERN int fcntl(int fd, int cmd, ...); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_FCNTL_H */ diff --git a/nuttx/include/fixedmath.h b/nuttx/include/fixedmath.h new file mode 100644 index 0000000000..4456361c76 --- /dev/null +++ b/nuttx/include/fixedmath.h @@ -0,0 +1,226 @@ +/**************************************************************************** + * include/fixedmath.h + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_FIXEDMATH_H +#define __INCLUDE_FIXEDMATH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/************************************************************************** + * Definitions + **************************************************************************/ + +/* Common numbers */ + +#define b8HUNDRED 0x6400 /* 100 */ +#define b8TEN 0x0a00 /* 10 */ +#define b8ONE 0x0100 /* 1 */ +#define b8HALF 0x0080 /* 0.5 */ +#define b8ONETENTH 0x001a /* 0.1 (acutally 0.1015625) */ +#define b8ONEHUNDRTH 0x0003 /* 0.01 (actualy 0.0117198765) */ +#define b8HALFPI 0x0192 /* 1.5703125 */ +#define b8PI 0x0324 /* 3.1406250 */ +#define b8TWOPI 0x0648 /* 6.2812500 */ + +#define b8MAX 0x7fff /* Max value of b8_t */ +#define ub8MAX 0xffff /* Max value of rb8_t */ +#define b8MIN 0x8000 /* Min value of b8_t */ +#define ub8MIN 0x0000 /* Min value of ub8_t */ + +#define b16THOUSAND 0x03e80000 /* 1000 */ +#define b16HUNDRED 0x00640000 /* 100 */ +#define b16TEN 0x000a0000 /* 10 */ +#define b16ONE 0x00010000 /* 1 */ +#define b16HALF 0x00008000 /* 0.5 */ +#define b16ONETENTH 0x0000199a /* 0.1 (actually 0.100006..) */ +#define b16ONEHUNDRTH 0x0000028f /* 0.01 (actually 0.0099945..) */ +#define b16ONETHOUSTH 0x00000042 /* 0.001 (actually 0.000100708..)*/ +#define b16HALFPI 0x0001921f /* 1.57078552246 */ +#define b16PI 0x0003243f /* 3.14158630371 */ +#define b16TWOPI 0x0006487b /* 6.28312683105 */ + +#define b16MAX 0x7fffffff /* Max value of b16_t */ +#define ub16MAX 0xffffffff /* Max value of ub16_t */ +#define b16MIN 0x80000000 /* Min value of b16_t */ +#define ub16MIN 0x00000000 /* Min value of ub16_t */ + +#define b32MILLION 0x000f424000000000 /* 1000000 */ +#define b32THOUSAND 0x000003e800000000 /* 1000 */ +#define b32HUNDRED 0x0000006400000000 /* 100 */ +#define b32TEN 0x0000000a00000000 /* 10 */ +#define b32ONE 0x0000000100000000 /* 1 */ +#define b32HALF 0x0000000080000000 /* 0.5 */ +#define b32ONETENTH 0x000000001999999a /* 0.1 */ +#define b32ONEHUNDRTH 0x00000000028f5c29 /* 0.01 */ +#define b32ONETHOUSTH 0x0000000000418937 /* 0.001 */ +#define b32ONETENTHOU 0x0000000000068db9 /* 0.0001 */ +#define b32HALFPI 0x00000001921eb9ff /* 1.57078134990 */ +#define b32PI 0x00000003243f6b4f /* 3.14159269980 */ +#define b32TWOPI 0x00000006487ae7fd /* 6.28312539984 */ + +#define b32MAX 0x7fffffffffffffff /* Max value of b16_t */ +#define ub32MAX 0xffffffffffffffff /* Max value of ub16_t */ +#define b32MIN 0x8000000000000000 /* Min value of b16_t */ +#define ub32MIN 0x0000000000000000 /* Min value of ub16_t */ + +/* Conversions between b16 and b8 *****************************************/ + +#define b8tob16(b) (((b16_t)(b)) << 8) +#define ub8toub16(b) (((ub16_t)(b)) << 8) +#define b16tob8(b) (b8_t)(((b)+0x0080)>>8) +#define ub16toub8(b) (ub8_t)(((b)+0x0080)>>8) + +#ifdef CONFIG_HAVE_LONG_LONG +# define b8tob32(b) (((b32_t)(b)) << 24) +# define ub8toub32(b) (((ub32_t)(b)) << 24) +# define b16tob32(b) (((b32_t)(b)) << 16) +# define ub16toub32(b) (((ub32_t)(b)) << 16) +# define b32tob16(b) (b16_t)(((b) + 0x0000000000008000)>>16) +# define ub32toub16(b) (ub16_t)(((b) + 0x0000000000008000)>>16) +# define b32tob8(b) (b8_t)(((b) + 0x0000000000000080)>>8) +#endif + +/* 16-bit values with 8 bits of precision *********************************/ + +/* Conversions */ + +#define b8toi(a) ((a) >> 8) /* Conversion to integer */ +#define itob8(i) (((b8_t)(i)) << 8) /* Conversion from integer */ +#define uitoub8(i) (((ub8_t)(i)) << 8) /* Conversion from unsigned integer */ +#define b8tof(b) (((float)b)/256.0) /* Conversion to float */ +#define ftob8(f) (b8_t)(((f)*256.0)) /* Conversion from float */ +#define b8trunc(a) ((a) & 0xff00) /* Truncate to integer b8 */ +#define b8round(a) (((a)+0x0080) & 0xff00) /* Round to integer b8 */ +#define b8frac(a) ((a) & 0x00ff) /* Take fractional part */ + +/* Operators */ + +#define ub8inv(b) (0x8000/((b)>>1)) /* Inversion (b8=b15/b7) */ +#define b8inv(b) (0x4000/((b)>>2)) /* Inversion (b8=b14/b6) */ +#define b8addb8(a,b) ((a)+(b)) /* Addition */ +#define b8addi(a,i) ((a)+itob8(i)) /* Add integer from b16 */ +#define b8subb8(a,b) ((a)-(b)) /* Subtraction */ +#define b8subi(a,i) ((a)-itob8(i)) /* Subtract integer from b8 */ +#define b8mulb8(a,b) b16tob8((b16_t)(a)*(b16_t)(b) /* Muliplication */ +#define ub8mulub8(a,b) ub16toub8((ub16_t)(a)*(ub16_t)(b) /* Muliplication */ +#define b8muli(a,i) ((a)*(i)) /* Simple multiplication by integer */ +#define b8sqr(a) b8mulb8(a,a) /* Square */ +#define ub8sqr(a) ub8mulub8(a,a) /* Square */ +#define b8divb8(a,b) b8tob16(a)/(b16_t)(b) /* Division */ +#define ub8divub8(a,b) ub8toub16(a)/(ub16_t)(b) /* Division */ +#define b8divi(a,i) ((a)/(i)) /* Simple division by integer */ +#define b8idiv(i,j) (((i)<<8)/j) /* Division of integer, b8 result */ + +/* 32-bit values with 16 bits of precision ********************************/ + +/* Conversions */ + +#define b16toi(a) ((a) >> 16) /* Conversion to integer */ +#define itob16(i) (((b16_t)(i)) << 16) /* Conversion from integer */ +#define uitoub16(i) (((ub16_t)(i)) << 16) /* Conversion from unsigned integer */ +#define b16tof(b) (((float)b)/65536.0) /* Conversion to float */ +#define ftob16(f) (b16_t)(((f)*65536.0)) /* Conversion from float */ +#define b16trunc(a) ((a) & 0xffff0000) /* Truncate to integer */ +#define b16round(a) (((a)+0x00008000) & 0xffff0000) +#define b16frac(a) ((a) & 0x0000ffff) /* Take fractional part */ + +/* Operators */ + +#define ub16inv(b) (0x80000000/((b)>>1)) /* Inversion (b16=b31/b15) */ +#define b16inv(b) (0x40000000/((b)>>2)) /* Inversion (b16=b30/b14) */ +#define b16addb16(a,b) ((a)+(b)) /* Addition */ +#define b16addi(a,i) ((a)+itob16(i)) /* Add integer to b16 */ +#define b16subb16(a,b) ((a)-(b)) /* Subtraction */ +#define b16subi(a,i) ((a)-itob16(i)) /* Subtract integer from b16 */ +#define b16muli(a,i) ((a)*(i)) /* Simple multiplication by integer */ +#define b16divi(a,i) ((a)/(i)) /* Simple division by integer*/ +#define b16idiv(i,j) (((i)<<16)/j) /* Division of integer, b16 result */ + +#ifdef CONFIG_HAVE_LONG_LONG +# define b16mulb16(a,b) b32tob16((b32_t)(a)*(b32_t)(b)) /* Muliplication */ +# define ub16mulub16(a,b) ub32toub16((ub32_t)(a)*(ub32_t)(b) +# define b16sqr(a) b16mulb16(a,a) /* Square */ +# define ub16sqr(a) ub16mulub16(a,a) /* Square */ +# define b16divb16(a,b) b16tob32(a)/(b32_t)(b) /* Division */ +# define ub16divub16(a,b) ub16toub32(a)/(ub32_t)(b) +#endif + +/************************************************************************** + * Public Types + **************************************************************************/ + +typedef int16_t b8_t; +typedef uint16_t ub8_t; +typedef int32_t b16_t; +typedef uint32_t ub16_t; +#ifdef CONFIG_HAVE_LONG_LONG +typedef int64_t b32_t; +typedef uint64_t ub32_t; +#endif + +/************************************************************************** + * Global Functions + **************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#ifndef CONFIG_HAVE_LONG_LONG +EXTERN b16_t b16mulb16(b16_t m1, b16_t m2); +EXTERN ub16_t ub16mulub16(ub16_t m1, ub16_t m2); +EXTERN b16_t b16sqr(b16_t a); +EXTERN ub16_t ub16sqr(ub16_t a); +EXTERN b16_t b16divb16(b16_t num, b16_t denom); +EXTERN ub16_t ub16divub16(ub16_t num, ub16_t denom); +#endif + +EXTERN b16_t b16sin(b16_t rad); +EXTERN b16_t b16cos(b16_t rad); +EXTERN b16_t b16atan2(b16_t y, b16_t x); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __INCLUDE_FIXEDMATH_H */ diff --git a/nuttx/include/inttypes.h b/nuttx/include/inttypes.h new file mode 100644 index 0000000000..caadbe5d16 --- /dev/null +++ b/nuttx/include/inttypes.h @@ -0,0 +1,190 @@ +/**************************************************************************** + * include/inttypes.h + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_INTTYPES_H +#define __INCLUDE_INTTYPES_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include /* for wchar_t */ + +/* Notes from www.opengroup.org: + * + * "The header shall include the header." + */ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* "The following macros shall be defined. Each expands to a character string + * literal containing a conversion specifier, possibly modified by a lengt + * modifier, suitable for use within the format argument of a formatted + * input/output function when converting the corresponding integer type. + * These macros have the general form of PRI (character string literals for + * the fprintf() and fwprintf() family of functions) or SCN (character string + * literals for the fscanf() and fwscanf() family of functions), followed by + * the conversion specifier, followed by a name corresponding to a similar + * type name in . In these names, N represents the width of the + * type as described in . For example, PRIdFAST32 can be used in a + * format string to print the value of an integer of type int_fast32_t. + * + * "The fprintf() macros for signed integers are: + * + * PRIdN + * PRIdLEASTN + * PRIdFASTN + * PRIdMAX + * PRIdPTR + * + * PRIiN + * PRIiLEASTN + * PRIiFASTN + * PRIiMAX + * PRIiPTR + * + * "The fprintf() macros for unsigned integers are: + * + * PRIoN + * PRIoLEASTN + * PRIoFASTN + * PRIoMAX + * PRIoPTR + * + * PRIuN + * PRIuLEASTN + * PRIuFASTN + * PRIuMAX + * PRIuPTR + * + * PRIxN + * PRIxLEASTN + * PRIxFASTN + * PRIxMAX + * PRIxPTR + * + * PRIXN + * PRIXLEASTN + * PRIXFASTN + * PRIXMAX + * PRIXPTR + * + * "The fscanf() macros for signed integers are: + * + * SCNdN + * SCNdLEASTN + * SCNdFASTN + * SCNdMAX + * SCNdPTR + * + * SCNiN + * SCNiLEASTN + * SCNiFASTN + * SCNiMAX + * SCNiPTR + * + * "The fscanf() macros for unsigned integers are: + * + * SCNoN + * SCNoLEASTN + * SCNoFASTN + * SCNoMAX + * SCNoPTR + * + * SCNuN + * SCNuLEASTN + * SCNuFASTN + * SCNuMAX + * SCNuPTR + * + * SCNxN + * SCNxLEASTN + * SCNxFASTN + * SCNxMAX + * SCNxPTR + * + * "For each type that the implementation provides in , the + * corresponding fprintf() and fwprintf() macros shall be defined and the + * corresponding fscanf() and fwscanf() macros shall be defined unless the + * implementation does not have a suitable modifier for the type. + */ + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/* "The header shall include a definition of at least the + * following type: + * + * imaxdiv_t + * Structure type that is the type of the value returned by the imaxdiv() + * function. + */ + +typedef void *imaxdiv_t; /* Dummy type since imaxdiv is not yet supported */ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* "The following shall be declared as functions and may also be defined as + * macros. Function prototypes shall be provided." + */ + +EXTERN intmax_t imaxabs(intmax_t); +EXTERN imaxdiv_t imaxdiv(intmax_t, intmax_t); +EXTERN intmax_t strtoimax(const char *, char **, int); +EXTERN uintmax_t strtoumax(const char *, char **, int); + +EXTERN intmax_t wcstoimax(const wchar_t *, wchar_t **, int); +EXTERN uintmax_t wcstoumax(const wchar_t *, wchar_t **, int); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_INTTYPES_H */ diff --git a/nuttx/include/libgen.h b/nuttx/include/libgen.h new file mode 100644 index 0000000000..e659483768 --- /dev/null +++ b/nuttx/include/libgen.h @@ -0,0 +1,66 @@ +/**************************************************************************** + * include/libgen.h + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_LIBGEN_H +#define __INCLUDE_LIBGEN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN char *basename(char *path); +EXTERN char *dirname(char *path); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_LIBGEN_H */ diff --git a/nuttx/include/limits.h b/nuttx/include/limits.h new file mode 100644 index 0000000000..056e2ada83 --- /dev/null +++ b/nuttx/include/limits.h @@ -0,0 +1,212 @@ +/******************************************************************************** + * include/limits.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +#ifndef __INCLUDE_LIMITS_H +#define __INCLUDE_LIMITS_H + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +/* Architecture specific limits */ + +#include + +/******************************************************************************** + * Pre-processor Definitions + ********************************************************************************/ +/* Default values for user configurable limits **********************************/ +/* Maximum number of bytes in a filename (not including terminating null). */ + +#ifndef CONFIG_NAME_MAX +# define CONFIG_NAME_MAX 32 +#endif + +/* Maximum number of bytes in a pathname, including the terminating null + * character. + */ + +#ifndef CONFIG_PATH_MAX +# if CONFIG_NAME_MAX < 64 +# define CONFIG_PATH_MAX (4*CONFIG_NAME_MAX + 1) +# else +# define CONFIG_PATH_MAX 256 +# endif +#endif + +/* Configurable limits required by POSIX **************************************** + * + * Required for all implementations: + * + * _POSIX_ARG_MAX Total length of string arguments + * _POSIX_CHILD_MAX Number of child tasks active + * _POSIX_LINK_MAX The number of links a file can have + * _POSIX_MAX_CANON Number bytes in TTY canonical input queue + * _POSIX_MAX_INPUT Number bytes in TTY canonical input queue + * _POSIX_NAME_MAX Number of bytes in a file or pathname component + * _POSIX_NGROUPS_MAX Number supplementary group IDs + * _POSIX_OPEN_MAX Number of files a task can have open at once + * _POSIX_PATH_MAX Number of bytes in a full pathname (including NULL) + * _POSIX_PIPE_BUF Number of bytes for atomic write into pipe + * _POSIX_SSIZE_MAX Largest filesystem write; also max value of ssize_t + * _POSIX_STREAM_MAX Number of std I/O streams open at once + * _POSIX_TZNAME_MAX Max number of bytes of a timezone name + * + * Required for sigqueue + * + * _POSIX_RTSIG_MAX Difference between SIGRTMIN and SIGRTMAX + * _POSIX_SIGQUEUE_MAX Max number signals a task can queue + * + * Required for POSIX timers + * + * _POSIX_DELAYTIMER_MAX Max number timer overruns + * _POSIX_TIMER_MAX Max number of timers per task + * _POSIX_CLOCKRES_MIN Clock resolution in nanoseconds + * + * Required for asynchronous I/O + * + * _POSIX_AIO_LISTIO_MAX Max number of AIOs in single listio call + * _POSIX_AIO_MAX Max number of simultaneous AIO operations + * + * Required for POSIX message passing + * + * _POSIX_MQ_OPEN_MAX Max number message queues task may open (mq_open) + * _POSIX_MQ_PRIO_MAX Max message priority (mq_send) + * + * Required for POSIX semaphores + * + * _POSIX_SEM_NSEMS_MAX Max number of open semaphores per task + * _POSIX_SEM_VALUE_MAX Max value a semaphore may have + */ + +#define _POSIX_ARG_MAX 4096 +#define _POSIX_CHILD_MAX 6 +#define _POSIX_LINK_MAX 8 +#define _POSIX_MAX_CANON 255 +#define _POSIX_MAX_INPUT 255 +#define _POSIX_NAME_MAX CONFIG_NAME_MAX +#define _POSIX_NGROUPS_MAX 0 +#define _POSIX_OPEN_MAX CONFIG_NFILE_DESCRIPTORS +#define _POSIX_PATH_MAX CONFIG_PATH_MAX +#define _POSIX_PIPE_BUF 512 +#define _POSIX_SSIZE_MAX INT_MAX +#define _POSIX_STREAM_MAX CONFIG_NFILE_STREAMS +#define _POSIX_TZNAME_MAX 3 + +/* Requred for sigqueue */ + +#define _POSIX_RTSIG_MAX 31 +#define _POSIX_SIGQUEUE_MAX 32 + +/* Required for POSIX timers. + * + * _POSIX_DELAYTIMER_MAX is the number of timer expiration overruns. + * + * _POSIX_TIMER_MAX is the per-process number of timers. + * + * _POSIX_CLOCKRES_MIN is the resolution of the CLOCK_REALTIME clock in nanoseconds. + * CLOCK_REALTIME is controlled by the NuttX system time. The default value is the + * system timer which has a resolution of 10 milliseconds. This default setting can + * be overridden by defining the clock interval in milliseconds as CONFIG_MSEC_PER_TICK + * in the board configuration file. + */ + +#define _POSIX_DELAYTIMER_MAX 32 +#define _POSIX_TIMER_MAX 32 + +#ifdef CONFIG_MSEC_PER_TICK +# define _POSIX_CLOCKRES_MIN ((CONFIG_MSEC_PER_TICK)*1000000) +#else +# define _POSIX_CLOCKRES_MIN (10*1000000) +#endif + +/* Required for asynchronous I/O */ + +#define _POSIX_AIO_LISTIO_MAX 2 +#define _POSIX_AIO_MAX 1 + +/* Required for POSIX message passing */ + +#define _POSIX_MQ_OPEN_MAX 8 +#define _POSIX_MQ_PRIO_MAX UCHAR_MAX + +/* Required for POSIX semaphores */ + +#define _POSIX_SEM_NSEMS_MAX INT_MAX +#define _POSIX_SEM_VALUE_MAX 0x7fff + +/* Actual limits. These values may be increased from the POSIX minimum + * values above or made indeterminate + */ + +#define ARG_MAX _POSIX_ARG_MAX +#define CHILD_MAX _POSIX_CHILD_MAX +#define LINK_MAX _POSIX_LINK_MAX +#define MAX_CANON _POSIX_MAX_CANON +#define MAX_INPUT _POSIX_MAX_INPUT +#define NAME_MAX _POSIX_NAME_MAX +#define NGROUPS_MAX _POSIX_NGROUPS_MAX +#define OPEN_MAX _POSIX_OPEN_MAX +#define PATH_MAX _POSIX_PATH_MAX +#define PIPE_BUF _POSIX_PIPE_BUF +#define SSIZE_MAX _POSIX_SSIZE_MAX +#define STREAM_MAX _POSIX_STREAM_MAX +#define TZNAME_MAX _POSIX_TZNAME_MAX + +#define RTSIG_MAX _POSIX_RTSIG_MAX +#define SIGQUEUE_MAX _POSIX_SIGQUEUE_MAX + +#define DELAYTIMER_MAX _POSIX_DELAYTIMER_MAX +#define TIMER_MAX _POSIX_TIMER_MAX +#define CLOCKRES_MIN _POSIX_CLOCKRES_MIN + +/* Required for asynchronous I/O */ + +#define AIO_LISTIO_MAX _POSIX_AIO_LISTIO_MAX +#define AIO_MAX _POSIX_AIO_MAX + +/* Required for POSIX message passing */ + +#define MQ_OPEN_MAX _POSIX_MQ_OPEN_MAX +#define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX + +/* Required for POSIX semaphores */ + +#define SEM_NSEMS_MAX _POSIX_SEM_NSEMS_MAX +#define SEM_VALUE_MAX _POSIX_SEM_VALUE_MAX + +#endif /* __INCLUDE_LIMITS_H */ diff --git a/nuttx/include/mqueue.h b/nuttx/include/mqueue.h new file mode 100644 index 0000000000..67dd5842d9 --- /dev/null +++ b/nuttx/include/mqueue.h @@ -0,0 +1,109 @@ +/******************************************************************************** + * include/mqueue.h + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +#ifndef __INCLUDE_MQUEUE_H +#define __INCLUDE_MQUEUE_H + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include +#include +#include "queue.h" + +/******************************************************************************** + * Compilations Switches + ********************************************************************************/ + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +#define MQ_NONBLOCK O_NONBLOCK + +/******************************************************************************** + * Global Type Declarations + ********************************************************************************/ + +/* Message queue attributes */ + +struct mq_attr +{ + size_t mq_maxmsg; /* Max number of messages in queue */ + size_t mq_msgsize; /* Max message size */ + unsigned mq_flags; /* Queue flags */ + size_t mq_curmsgs; /* Number of messages currently in queue */ +}; + +/* Message queue descriptor */ + +typedef FAR struct mq_des *mqd_t; + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Global Function Prototypes + ********************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN mqd_t mq_open(const char *mq_name, int oflags, ...); +EXTERN int mq_close(mqd_t mqdes ); +EXTERN int mq_unlink(const char *mq_name); +EXTERN int mq_send(mqd_t mqdes, const void *msg, size_t msglen, int prio); +EXTERN int mq_timedsend(mqd_t mqdes, const char *msg, size_t msglen, int prio, + const struct timespec *abstime); +EXTERN ssize_t mq_receive(mqd_t mqdes, void *msg, size_t msglen, int *prio); +EXTERN ssize_t mq_timedreceive(mqd_t mqdes, void *msg, size_t msglen, + int *prio, const struct timespec *abstime); +EXTERN int mq_notify(mqd_t mqdes, const struct sigevent *notification); +EXTERN int mq_setattr(mqd_t mqdes, const struct mq_attr *mq_stat, + struct mq_attr *oldstat); +EXTERN int mq_getattr(mqd_t mqdes, struct mq_attr *mq_stat); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_MQUEUE_H */ diff --git a/nuttx/include/net/ethernet.h b/nuttx/include/net/ethernet.h new file mode 100644 index 0000000000..afbbe56fab --- /dev/null +++ b/nuttx/include/net/ethernet.h @@ -0,0 +1,71 @@ +/**************************************************************************** + * include/net/ethernet.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NET_ETHERNET_H +#define __INCLUDE_NET_ETHERNET_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#define ETHER_ADDR_LEN 6 + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +struct ether_addr +{ + uint8_t ether_addr_octet[6]; /* 48-bit Ethernet address */ +}; + +struct ether_header +{ + uint8_t ether_dhost[ETHER_ADDR_LEN]; /* Destination Ethernet address */ + uint8_t ether_shost[ETHER_ADDR_LEN]; /* Source Ethernet address */ + uint16_t ether_type; /* Ethernet packet type*/ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __INCLUDE_NET_ETHERNET_H */ diff --git a/nuttx/include/net/if.h b/nuttx/include/net/if.h new file mode 100644 index 0000000000..e64b58563f --- /dev/null +++ b/nuttx/include/net/if.h @@ -0,0 +1,133 @@ +/******************************************************************************************* + * include/net/if.h + * + * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************************/ + +#ifndef __INCLUDE_NET_IF_H +#define __INCLUDE_NET_IF_H + +/******************************************************************************************* + * Included Files + *******************************************************************************************/ + +#include + +/******************************************************************************************* + * Pre-Processor Definitions + *******************************************************************************************/ + +/* Sizing parameters */ + +#define IFNAMSIZ 6 /* Older naming standard */ +#define IF_NAMESIZE 6 /* Newer naming standard */ +#define IFHWADDRLEN 6 + +/******************************************************************************************* + * Public Type Definitions + *******************************************************************************************/ + +/* This is the newer form if the I/F request structure that can be used with both IPv4 + * and IPv6. + */ + +struct lifreq +{ + char lifr_name[IFNAMSIZ]; /* Network device name (e.g. "eth0") */ + union + { + struct sockaddr_storage lifru_addr; /* IP Address */ + struct sockaddr_storage lifru_dstaddr; /* P-to-P Address */ + struct sockaddr_storage lifru_broadaddr; /* Broadcast address */ + struct sockaddr_storage lifru_netmask; /* Netmask */ + struct sockaddr lifru_hwaddr; /* MAC address */ + int lifru_count; /* Number of devices */ + int lifru_mtu; /* MTU size */ + } lifr_ifru; +}; + +#define lifr_addr lifr_ifru.lifru_addr /* IP address */ +#define lifr_dstaddr lifr_ifru.lifru_dstaddr /* P-to-P Address */ +#define lifr_broadaddr lifr_ifru.lifru_broadaddr /* Broadcast address */ +#define lifr_netmask lifr_ifru.lifru_netmask /* Interface net mask */ +#define lifr_hwaddr lifr_ifru.lifru_hwaddr /* MAC address */ +#define lifr_mtu lifr_ifru.lifru_mtu /* MTU */ +#define lifr_count lifr_ifru.lifru_count /* Number of devices */ + +/* This is the older I/F request that should only be used with IPv4. However, since + * NuttX only supports IPv4 or 6 (not both), we can force the older structure to + * be compatible when IPv6 is enabled. + */ + +#ifndef CONFIG_NET_IPv6 +struct ifreq +{ + char ifr_name[IFNAMSIZ]; /* Network device name (e.g. "eth0") */ + union + { + struct sockaddr ifru_addr; /* IP Address */ + struct sockaddr ifru_dstaddr; /* P-to-P Address */ + struct sockaddr ifru_broadaddr; /* Broadcast address */ + struct sockaddr ifru_netmask; /* Netmask */ + struct sockaddr ifru_hwaddr; /* MAC address */ + int ifru_count; /* Number of devices */ + int ifru_mtu; /* MTU size */ + } ifr_ifru; +}; + +#define ifr_addr ifr_ifru.ifru_addr /* IP address */ +#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* P-to-P Address */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* Broadcast address */ +#define ifr_netmask ifr_ifru.ifru_netmask /* Interface net mask */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_mtu ifr_ifru.ifru_mtu /* MTU */ +#define ifr_count ifr_ifru.ifru_count /* Number of devices */ + +#else /* CONFIG_NET_IPv6 */ + +#define ifreq lifreq /* Replace ifreq with lifreq */ +#define ifr_name lifr_name /* Network device name */ +#define ifr_addr lifr_ifru.lifru_addr /* IP address */ +#define ifr_dstaddr lifr_ifru.lifru_dstaddr /* P-to-P Address */ +#define ifr_broadaddr lifr_ifru.lifru_broadaddr /* Broadcast address */ +#define ifr_netmask lifr_ifru.lifru_netmask /* Interface net mask */ +#define ifr_hwaddr lifr_ifru.lifru_hwaddr /* MAC address */ +#define ifr_mtu lifr_ifru.lifru_mtu /* MTU */ +#define ifr_count lifr_ifru.lifru_count /* Number of devices */ + +#endif /* CONFIG_NET_IPv6 */ + +/******************************************************************************************* + * Public Function Prototypes + *******************************************************************************************/ + +#endif /* __INCLUDE_NET_IF_H */ diff --git a/nuttx/include/netinet/arp.h b/nuttx/include/netinet/arp.h new file mode 100644 index 0000000000..34cfc84a4c --- /dev/null +++ b/nuttx/include/netinet/arp.h @@ -0,0 +1,111 @@ +/**************************************************************************** + * include/netinet/arp.h + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NETINET_ARP_H +#define __INCLUDE_NETINET_ARP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Three ioctls are available on all PF_INET sockets, but only if the NuttX + * configuration CONFIG_NET_ARPIOCTLS is defined. Each ioctl takes a pointer + * to a 'struct arpreq' as its parameter. + */ + +#define SIOCSARP _ARPIOC(1) /* Set a ARP mapping */ +#define SIOCDARP _ARPIOC(2) /* Delete an ARP mapping */ +#define SIOCGARP _ARPIOC(3) /* Get an ARP mapping */ + +/* Values for the FLAGS field in struct arpreq */ + +#define ATF_COM 0x01 /* Lookup complete */ +#define ATF_PERM 0x02 /* Permanent entry */ +#define ATF_PUBL 0x04 /* Publish entry */ +#define ATF_USETRAILERS 0x10 /* Trailers requested */ +#define ATF_NETMASK 0x20 /* Use a netmask */ +#define ATF_DONTPUB 0x40 /* Don't answer */ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* All ARP ioctls take a pointer to a struct arpreq as their parameter: */ + +struct arpreq +{ + struct sockaddr arp_pa; /* Protocol address */ + struct sockaddr arp_ha; /* Hardware address */ + struct sockaddr arp_netmask; /* Netmask of protocol address */ + uint8_t arp_flags; /* Flags */ + uint8_t arp_dev[IFNAMSIZ+1]; /* Device name (zero terminated)*/ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* If CONFIG_NET_ARPIOCTLS is defined then the semi-standard ioctl commands + * described above are supported. If not, you can call the uIP ARP interfaces + * directly in a very non-standard way. See include/nuttx/net/uip/uip-arp.h for + * prototypes. + */ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NETINET_ARP_H */ diff --git a/nuttx/include/netinet/ether.h b/nuttx/include/netinet/ether.h new file mode 100644 index 0000000000..f11fef6dbf --- /dev/null +++ b/nuttx/include/netinet/ether.h @@ -0,0 +1,77 @@ +/**************************************************************************** + * include/netinet/ether.h + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NETINET_ETHER_H +#define __INCLUDE_NETINET_ETHER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN char *ether_ntoa(const struct ether_addr *addr); +EXTERN struct ether_addr *ether_aton(const char *asc); +EXTERN int ether_ntohost(char *hostname, const struct ether_addr *addr); +EXTERN int ether_hostton(const char *hostname, struct ether_addr *addr); +EXTERN int ether_line(const char *line, struct ether_addr *addr, char *hostname); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NETINET_ETHER_H */ diff --git a/nuttx/include/netinet/in.h b/nuttx/include/netinet/in.h new file mode 100644 index 0000000000..547dc0968b --- /dev/null +++ b/nuttx/include/netinet/in.h @@ -0,0 +1,155 @@ +/**************************************************************************** + * include/netinet/in.h + * + * Copyright (C) 2007, 2009-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NETINET_IP_H +#define __INCLUDE_NETINET_IP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Values for protocol argument to socket() */ + +#define IPPROTO_IP 0 /* Dummy protocol for TCP */ +#define IPPROTO_HOPOPTS 0 /* IPv6 Hop-by-Hop options. */ +#define IPPROTO_ICMP 1 /* Internet Control Message Protocol */ +#define IPPROTO_IGMP 2 /* Internet Group Management Protocol */ +#define IPPROTO_IPIP 4 /* IPIP tunnels (older KA9Q tunnels use 94) */ +#define IPPROTO_TCP 6 /* Transmission Control Protocol */ +#define IPPROTO_EGP 8 /* Exterior Gateway Protocol */ +#define IPPROTO_PUP 12 /* PUP protocol */ +#define IPPROTO_UDP 17 /* User Datagram Protocol */ +#define IPPROTO_IDP 22 /* XNS IDP protocol */ +#define IPPROTO_TP 29 /* SO Transport Protocol Class 4. */ +#define IPPROTO_DCCP 33 /* Datagram Congestion Control Protocol */ +#define IPPROTO_IPV6 41 /* IPv6-in-IPv4 tunnelling */ +#define IPPROTO_ROUTING 43 /* IPv6 routing header. */ +#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header. */ +#define IPPROTO_RSVP 46 /* Reservation Protocol. */ +#define IPPROTO_GRE 47 /* General Routing Encapsulation. */ +#define IPPROTO_ESP 50 /* Encapsulation Security Payload protocol */ +#define IPPROTO_AH 51 /* Authentication Header protocol */ +#define IPPROTO_ICMPV6 58 /* ICMPv6 */ +#define IPPROTO_NONE 59 /* IPv6 no next header. */ +#define IPPROTO_DSTOPTS 60 /* IPv6 destination options. */ +#define IPPROTO_MTP 92 /* Multicast Transport Protocol. */ +#define IPPROTO_ENCAP 98 /* Encapsulation Header. */ +#define IPPROTO_BEETPH 94 /* IP option pseudo header for BEET */ +#define IPPROTO_PIM 103 /* Protocol Independent Multicast */ +#define IPPROTO_COMP 108 /* Compression Header protocol */ +#define IPPROTO_SCTP 132 /* Stream Control Transport Protocol */ +#define IPPROTO_UDPLITE 136 /* UDP-Lite (RFC 3828) */ +#define IPPROTO_RAW 255 /* Raw IP packets */ + +/* Values used with SIOCSIFMCFILTER and SIOCGIFMCFILTER ioctl's */ + +#define MCAST_EXCLUDE 0 +#define MCAST_INCLUDE 1 + +/* Special values of in_addr_t */ + +#define INADDR_ANY ((in_addr_t)0x00000000) /* Address to accept any incoming messages */ +#define INADDR_BROADCAST ((in_addr_t)0xffffffff) /* Address to send to all hosts */ +#define INADDR_NONE ((in_addr_t)0xffffffff) /* Address indicating an error return */ +#define INADDR_LOOPBACK ((in_addr_t)0x7f000001) /* Inet 127.0.0.1. */ + +/* Special initializer for in6_addr_t */ + +#define IN6ADDR_ANY_INIT {{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}} +#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}}} + +/* struct in6_addr union selectors */ + +#define s6_addr in6_u.u6_addr8 +#define s6_addr16 in6_u.u6_addr16 +#define s6_addr32 in6_u.u6_addr32 + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* IPv4 Internet address */ + +typedef uint32_t in_addr_t; + +struct in_addr +{ + in_addr_t s_addr; /* Address (network byte order) */ +}; + +struct sockaddr_in +{ + sa_family_t sin_family; /* Address family: AF_INET */ + uint16_t sin_port; /* Port in network byte order */ + struct in_addr sin_addr; /* Internet address */ +}; + +/* IPv6 Internet address */ + +struct in6_addr +{ + union + { + uint8_t u6_addr8[16]; + uint16_t u6_addr16[8]; + uint32_t u6_addr32[4]; + } in6_u; +}; + +struct sockaddr_in6 +{ + sa_family_t sin_family; /* Address family: AF_INET */ + uint16_t sin_port; /* Port in network byte order */ + struct in6_addr sin6_addr; /* IPv6 internet address */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __INCLUDE_NETINET_IP_H */ diff --git a/nuttx/include/netinet/ip.h b/nuttx/include/netinet/ip.h new file mode 100644 index 0000000000..e2a6aaf4f1 --- /dev/null +++ b/nuttx/include/netinet/ip.h @@ -0,0 +1,54 @@ +/**************************************************************************** + * include/netinet/ip.h + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NETINET_IP_H +#define __INCLUDE_NETINET_IP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __INCLUDE_NETINET_IP_H */ diff --git a/nuttx/include/netinet/ip6.h b/nuttx/include/netinet/ip6.h new file mode 100644 index 0000000000..be16ae722c --- /dev/null +++ b/nuttx/include/netinet/ip6.h @@ -0,0 +1,54 @@ +/**************************************************************************** + * include/netinet/ip6.h + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NETINET_I6P_H +#define __INCLUDE_NETINET_I6P_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __INCLUDE_NETINET_I6P_H */ diff --git a/nuttx/include/nuttx/analog/adc.h b/nuttx/include/nuttx/analog/adc.h new file mode 100644 index 0000000000..873f5d9da7 --- /dev/null +++ b/nuttx/include/nuttx/analog/adc.h @@ -0,0 +1,225 @@ +/************************************************************************************ + * include/nuttx/analog/adc.h + * + * Copyright (C) 2011 Li Zhuoyi. All rights reserved. + * Author: Li Zhuoyi + * History: 0.1 2011-08-04 initial version + * 0.2 remove ao_read + * + * Derived from include/nuttx/can.h + * Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_ANALOG_ADC_H +#define __INCLUDE_NUTTX_ANALOG_ADC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Default configuration settings that may be overridden in the board configuration. + * file. The configured size is limited to 255 to fit into a uint8_t. + */ + +#if !defined(CONFIG_ADC_FIFOSIZE) +# define CONFIG_ADC_FIFOSIZE 8 +#elif CONFIG_ADC_FIFOSIZE > 255 +# undef CONFIG_ADC_FIFOSIZE +# define CONFIG_ADC_FIFOSIZE 255 +#endif + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +struct adc_msg_s +{ + uint8_t am_channel; /* The 8-bit ADC Channel */ + int32_t am_data; /* ADC convert result (4 bytes) */ +} __attribute__((__packed__)); + +struct adc_fifo_s +{ + sem_t af_sem; /* Counting semaphore */ + uint8_t af_head; /* Index to the head [IN] index in the circular buffer */ + uint8_t af_tail; /* Index to the tail [OUT] index in the circular buffer */ + /* Circular buffer of CAN messages */ + struct adc_msg_s af_buffer[CONFIG_ADC_FIFOSIZE]; +}; + +/* This structure defines all of the operations providd by the architecture specific + * logic. All fields must be provided with non-NULL function pointers by the + * caller of can_register(). + */ + +struct adc_dev_s; +struct adc_ops_s +{ + /* Reset the ADC device. Called early to initialize the hardware. This + * is called, before ao_setup() and on error conditions. + */ + + CODE void (*ao_reset)(FAR struct adc_dev_s *dev); + + /* Configure the ADC. This method is called the first time that the ADC + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching ADC interrupts. Interrupts + * are all disabled upon return. + */ + + CODE int (*ao_setup)(FAR struct adc_dev_s *dev); + + /* Disable the ADC. This method is called when the ADC device is closed. + * This method reverses the operation the setup method. + */ + + CODE void (*ao_shutdown)(FAR struct adc_dev_s *dev); + + /* Call to enable or disable RX interrupts */ + + CODE void (*ao_rxint)(FAR struct adc_dev_s *dev, bool enable); + + /* All ioctl calls will be routed through this method */ + + CODE int (*ao_ioctl)(FAR struct adc_dev_s *dev, int cmd, unsigned long arg); + +}; + +/* This is the device structure used by the driver. The caller of + * can_register() must allocate and initialize this structure. The + * calling logic need only set all fields to zero except: + * + * The elements of 'ad_ops', and 'ad_priv' + * + * The common logic will initialize all semaphores. + */ + +struct adc_dev_s +{ + uint8_t ad_ocount; /* The number of times the device has been opened */ + uint8_t ad_nrxwaiters; /* Number of threads waiting to enqueue a message */ + sem_t ad_closesem; /* Locks out new opens while close is in progress */ + sem_t ad_recvsem; /* Used to wakeup user waiting for space in ad_recv.buffer */ + struct adc_fifo_s ad_recv; /* Describes receive FIFO */ + const struct adc_ops_s *ad_ops; /* Arch-specific operations */ + void *ad_priv; /* Used by the arch-specific logic */ +}; + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/************************************************************************************ + * "Upper-Half" ADC Driver Interfaces + ************************************************************************************/ +/************************************************************************************ + * Name: adc_register + * + * Description: + * Register a ADC driver. This function binds an instance of a "lower half" ADC + * driver with the "upper half" ADC device and registers that device so that can + * be used by application code. + * + * Input parameters: + * path - The full path to the driver to be registers in the NuttX pseudo- + * filesystem. The recommended convention is to name all PWM drivers + * as "/dev/adc", "/dev/adc1", etc. where the driver path differs only + * in the "minor" number at the end of the device name. + * dev - A pointer to an instance of lower half ADC driver. This instance + * is bound to the upper half ADC driver and must persists as long as the + * upper half driver driver persists. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ************************************************************************************/ + +int adc_register(FAR const char *path, FAR struct adc_dev_s *dev); + +/************************************************************************************ + * Name: adc_receive + * + * Description: + * This function is called from the lower half, platform-specific ADC logic when + * new ADC sample data is available. + * + * Input Parameters: + * dev - The ADC device structure that was previously registered by adc_register() + * ch - And ID for the ADC channel number that generated the data + * data - The actualy converted data from the channel. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ************************************************************************************/ + +int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data); + +/************************************************************************************ + * Platform-Independent "Lower Half" ADC Driver Interfaces + ************************************************************************************/ +/************************************************************************************ + * Name: up_ads1255initialize + * + * Description: + * Initialize the TI ADS 125X lower half driver + * + ************************************************************************************/ + +FAR struct adc_dev_s *up_ads1255initialize(FAR struct spi_dev_s *spi, unsigned int devno); + +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_ANALOG_ADC_H */ diff --git a/nuttx/include/nuttx/analog/dac.h b/nuttx/include/nuttx/analog/dac.h new file mode 100644 index 0000000000..655fdbfcf6 --- /dev/null +++ b/nuttx/include/nuttx/analog/dac.h @@ -0,0 +1,212 @@ +/************************************************************************************ + * include/nuttx/analog/dac.h + * + * Copyright (C) 2011 Li Zhuoyi. All rights reserved. + * Author: Li Zhuoyi + * History: 0.1 2011-08-04 initial version + * + * Derived from include/nuttx/can.h + * + * Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_ANALOG_DAC_H +#define __INCLUDE_NUTTX_ANALOG_DAC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Default configuration settings that may be overridden in the board configuration. + * file. The configured size is limited to 255 to fit into a uint8_t. + */ + +#if !defined(CONFIG_DAC_FIFOSIZE) +# define CONFIG_DAC_FIFOSIZE 8 +#elif CONFIG_DAC_FIFOSIZE > 255 +# undef CONFIG_DAC_FIFOSIZE +# define CONFIG_DAC_FIFOSIZE 255 +#endif + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +struct dac_msg_s +{ + uint8_t am_channel; /* The 8-bit DAC Channel */ + int32_t am_data; /* DAC convert result (4 bytes) */ +}; + +struct dac_fifo_s +{ + sem_t af_sem; /* Counting semaphore */ + uint8_t af_head; /* Index to the head [IN] index in the circular buffer */ + uint8_t af_tail; /* Index to the tail [OUT] index in the circular buffer */ + /* Circular buffer of CAN messages */ + struct dac_msg_s af_buffer[CONFIG_DAC_FIFOSIZE]; +}; + +/* This structure defines all of the operations providd by the architecture specific + * logic. All fields must be provided with non-NULL function pointers by the + * caller of dac_register(). + */ + +struct dac_dev_s; +struct dac_ops_s +{ + /* Reset the DAC device. Called early to initialize the hardware. This + * is called, before ao_setup() and on error conditions. + */ + + CODE void (*ao_reset)(FAR struct dac_dev_s *dev); + + /* Configure the DAC. This method is called the first time that the DAC + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching DAC interrupts. Interrupts + * are all disabled upon return. + */ + + CODE int (*ao_setup)(FAR struct dac_dev_s *dev); + + /* Disable the DAC. This method is called when the DAC device is closed. + * This method reverses the operation the setup method. + */ + CODE void (*ao_shutdown)(FAR struct dac_dev_s *dev); + + /* Call to enable or disable TX interrupts */ + + CODE void (*ao_txint)(FAR struct dac_dev_s *dev, bool enable); + + /* This method will send one message on the DAC */ + + CODE int (*ao_send)(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg); + + /* All ioctl calls will be routed through this method */ + + CODE int (*ao_ioctl)(FAR struct dac_dev_s *dev, int cmd, unsigned long arg); + +}; + +/* This is the device structure used by the driver. The caller of + * dac_register() must allocate and initialize this structure. The + * calling logic need only set all fields to zero except: + * + * The elements of 'ad_ops', and 'ad_priv' + * + * The common logic will initialize all semaphores. + */ + +struct dac_dev_s +{ + uint8_t ad_ocount; /* The number of times the device has been opened */ + uint8_t ad_nchannel; /* Number of dac channel */ + sem_t ad_closesem; /* Locks out new opens while close is in progress */ + struct dac_fifo_s ad_xmit; /* Describes receive FIFO */ + const struct dac_ops_s *ad_ops; /* Arch-specific operations */ + void *ad_priv; /* Used by the arch-specific logic */ +}; + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/************************************************************************************ + * Name: dac_register + * + * Description: + * Register a dac driver. + * + * Input Parameters: + * path - The full path to the DAC device to be registered. This could be, as an + * example, "/dev/dac0" + * dev - An instance of the device-specific DAC interface + * + * Returned Value: + * Zero on success; A negated errno value on failure. + * + ************************************************************************************/ + +int dac_register(FAR const char *path, FAR struct dac_dev_s *dev); + +/************************************************************************************ + * Name: dac_txdone + * + * Description: + * Called from the DAC interrupt handler at the completion of a send operation. + * + * Input Parameters: + * dev - An instance of the device-specific DAC interface + * + * Return: + * OK on success; a negated errno on failure. + * + ************************************************************************************/ + +int dac_txdone(FAR struct dac_dev_s *dev); + +/************************************************************************************ + * DAC Initialization functions + * + * Architecture-specific versions will have prototypes in architect-specific header + * files. Common DAC implementations in drivers/analog will have prototypes listed + * below. + * + ************************************************************************************/ + +FAR struct dac_dev_s *up_ad5410initialize(FAR struct spi_dev_s *spi, unsigned int devno); + +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_ANALOG_DAC_H */ diff --git a/nuttx/include/nuttx/analog/pga11x.h b/nuttx/include/nuttx/analog/pga11x.h new file mode 100644 index 0000000000..8b04dee194 --- /dev/null +++ b/nuttx/include/nuttx/analog/pga11x.h @@ -0,0 +1,390 @@ +/**************************************************************************** + * include/nuttx/analog/pga11x.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * + * References: + * "PGA112, PGA113, PGA116, PGA117: Zerø-Drift PROGRAMMABLE GAIN AMPLIFIER + * with MUX", SBOS424B, March 2008, Revised September 2008, Texas + * Instruments Incorporated" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_ANALOG_PGA11X_H +#define __INCLUDE_NUTTX_ANALOG_PGA11X_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#if defined(CONFIG_ADC) && defined(CONFIG_ADC_PGA11X) + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* Prerequisites: + * CONFIG_ADC=y is needed to enable support for analog input devices + * + * CONFIG_ADC_PGA11X + * Enables support for the PGA11X driver (Needs CONFIG_ADC) + * CONFIG_PGA11X_SPIFREQUENCY + * SPI frequency. Default 1MHz + * CONFIG_PGA11X_DAISYCHAIN + * Use two PGA116/7's in Daisy Chain commands. + * CONFIG_PGA11X_SPIMODE + * SPI Mode. The specification says that the device operates in Mode 0 or + * Mode 3. But sometimes you need to tinker with this to get things to + * work correctly. Default: Mode 0 + * CONFIG_PGA11X_MULTIPLE + * Can be defined to support multiple PGA11X devices on board. Each + * device will require a customized SPI interface to distinguish them + * When SPI_SELECT is called with devid=SPIDEV_MUX. + * + * Other settings that effect the driver: + * CONFIG_SPI_OWNBUS -- If the PGA117 is enabled, this must be set to 'y' + * if the PGA117 is the only device on the SPI bus; + * CONFIG_DEBUG_SPI -- With CONFIG_DEBUG and CONFIG_DEBUG_VERBOSE, + * this will enable debug output from the PGA117 driver. + */ + +#ifndef CONFIG_PGA11X_SPIFREQUENCY +# define CONFIG_PGA11X_SPIFREQUENCY 1000000 +#endif + +#ifndef CONFIG_PGA11X_SPIMODE +# define CONFIG_PGA11X_SPIMODE SPIDEV_MODE0 +#endif + +/* PGA11x Commands **********************************************************/ +/* Write command Gain Selection Bits (PGA112/PGA113) + * + * the PGA112 and PGA116 provide binary gain selections (1, 2, 4, 8, 16, 32, + * 64, 128); the PGA113 and PGA117 provide scope gain selections (1, 2, 5, 10, + * 20, 50, 100, 200). + */ + +#define PGA11X_GAIN_1 (0) /* Gain=1: Scope Gain=1 */ +#define PGA11X_GAIN_2 (1) /* Gain=2: Scope Gain=2 */ +#define PGA11X_GAIN_4 (2) /* Gain=4: Scope Gain=5 */ +#define PGA11X_GAIN_5 (2) /* Gain=4: Scope Gain=5 */ +#define PGA11X_GAIN_8 (3) /* Gain=8: Scope Gain=10 */ +#define PGA11X_GAIN_10 (3) /* Gain=8: Scope Gain=10 */ +#define PGA11X_GAIN_16 (4) /* Gain=16: Scope Gain=20 */ +#define PGA11X_GAIN_20 (4) /* Gain=16: Scope Gain=20 */ +#define PGA11X_GAIN_32 (5) /* Gain=32: Scope Gain=50 */ +#define PGA11X_GAIN_50 (5) /* Gain=32: Scope Gain=50 */ +#define PGA11X_GAIN_64 (6) /* Gain=64: Scope Gain=100 */ +#define PGA11X_GAIN_100 (6) /* Gain=64: Scope Gain=100 */ +#define PGA11X_GAIN_128 (7) /* Gain=128: Scope Gain=200 */ +#define PGA11X_GAIN_200 (7) /* Gain=128: Scope Gain=200 */ + +/* Write command Mux Channel Selection Bits + * + * The PGA112/PGA113 have a two-channel input MUX; the PGA116/PGA117 have a + * 10-channel input MUX. + */ + +#define PGA11X_CHAN_VCAL (0) /* VCAL/CH0 */ +#define PGA11X_CHAN_CH0 (0) /* VCAL/CH0 */ +#define PGA11X_CHAN_CH1 (1) /* CH1 */ +#define PGA11X_CHAN_CH2 (2) /* CH2 (PGA116/PGA117 only) */ +#define PGA11X_CHAN_CH3 (3) /* CH3 (PGA116/PGA117 only) */ +#define PGA11X_CHAN_CH4 (4) /* CH4 (PGA116/PGA117 only) */ +#define PGA11X_CHAN_CH5 (5) /* CH5 (PGA116/PGA117 only) */ +#define PGA11X_CHAN_CH6 (6) /* CH6 (PGA116/PGA117 only) */ +#define PGA11X_CHAN_CH7 (7) /* CH7 (PGA116/PGA117 only) */ +#define PGA11X_CHAN_CH8 (8) /* CH8 (PGA116/PGA117 only) */ +#define PGA11X_CHAN_CH9 (9) /* CH9 (PGA116/PGA117 only) */ +#define PGA11X_CHAN_CAL1 (12) /* CAL1: connects to GND */ +#define PGA11X_CHAN_CAL2 (13) /* CAL2: connects to 0.9VCAL */ +#define PGA11X_CHAN_CAL3 (14) /* CAL3: connects to 0.1VCAL */ +#define PGA11X_CHAN_CAL4 (15) /* CAL4: connects to VREF */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Handle used to reference the particular PGA11X instance */ + +typedef FAR void *PGA11X_HANDLE; + +/* Settings for one device in a daisy-chain */ + +#ifdef CONFIG_PGA11X_DAISYCHAIN +struct pga11x_usettings_s +{ + uint8_t channel; /* See PGA11X_CHAN_* definitions */ + uint8_t gain; /* See PGA11X_GAIN_* definitions */ +}; +#endif + +/* These structures are used to encode gain and channel settings. This + * includes both devices in the case of a daisy-chained configuration. + * NOTE: This this logic is currently limited to only 2 devices in the + * daisy-chain. + */ + +struct pga11x_settings_s +{ +#ifndef CONFIG_PGA11X_DAISYCHAIN + uint8_t channel; /* See PGA11X_CHAN_* definitions */ + uint8_t gain; /* See PGA11X_GAIN_* definitions */ +#else + struct + { + uint8_t channel; /* See PGA11X_CHAN_* definitions */ + uint8_t gain; /* See PGA11X_GAIN_* definitions */ + } u1; + + struct + { + uint8_t channel; /* See PGA11X_CHAN_* definitions */ + uint8_t gain; /* See PGA11X_GAIN_* definitions */ + } u2; +#endif +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: pga11x_initialize + * + * Description: + * Initialize the PGA117 amplifier/multiplexer(s). + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * + * Returned Value: + * On success, a non-NULL opaque handle is returned; a NULL is returned + * on any failure. This handle may be used with the other PGA117 interface + * functions to control the multiplexer + * + ****************************************************************************/ + +EXTERN PGA11X_HANDLE pga11x_initialize(FAR struct spi_dev_s *spi); + +/**************************************************************************** + * Name: pga11x_select + * + * Description: + * Select an input channel and gain for all PGA11xs. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_select() configures + * both chips in the daisy-chain. pga11x_uselect() is provided to support + * configuring the parts in the daisychain independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * settings - New channel and gain settings + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +EXTERN int pga11x_select(PGA11X_HANDLE handle, + FAR const struct pga11x_settings_s *settings); + +/**************************************************************************** + * Name: pga11x_uselect + * + * Description: + * Select an input channel and gain for one PGA11x. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_uselect() configures + * one chips in the daisy-chain. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * pos - Position of the chip in the daisy chain (0 or 1) + * settings - New channel and gain settings + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_PGA11X_DAISYCHAIN +EXTERN int pga11x_uselect(PGA11X_HANDLE handle, int pos, + FAR const struct pga11x_usettings_s *settings); +#endif + +/**************************************************************************** + * Name: pga11x_read + * + * Description: + * Read from all PGA117 amplifier/multiplexers. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_read() reads from + * both chips in the daisy-chain. pga11x_uread() is provided to support + * accessing the parts independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * settings - Returned channel and gain settings + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +EXTERN int pga11x_read(PGA11X_HANDLE handle, + FAR struct pga11x_settings_s *settings); + +/**************************************************************************** + * Name: pga11x_uread + * + * Description: + * Read from one PGA117 amplifier/multiplexer. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_read() reads + * the parts independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * pos - Position of the chip in the daisy chain (0 or 1) + * settings - Returned channel and gain settings + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_PGA11X_DAISYCHAIN +EXTERN int pga11x_uread(PGA11X_HANDLE handle, int pos, + FAR struct pga11x_usettings_s *settings); +#endif + +/**************************************************************************** + * Name: pga11x_shutdown + * + * Description: + * Put all PGA11x;'s in shutdown down mode. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_shutdown() controls + * both chips in the daisy-chain. pga11x_ushutdown() is provided to + * control the parts independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +EXTERN int pga11x_shutdown(PGA11X_HANDLE handle); + +/**************************************************************************** + * Name: pga11x_ushutdown + * + * Description: + * Put one PGA11x in shutdown down mode. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_ushutdown() is + * provided to shutdown the parts independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * pos - Position of the chip in the daisy chain (0 or 1) + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_PGA11X_DAISYCHAIN +EXTERN int pga11x_ushutdown(PGA11X_HANDLE handle, int pos); +#endif + +/**************************************************************************** + * Name: pga11x_enable + * + * Description: + * Take all PGA11x's out of shutdown down mode. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_enable() controls + * both chips in the daisy-chain. pga11x_uenable() is provided to + * control the parts independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +EXTERN int pga11x_enable(PGA11X_HANDLE handle); + +/**************************************************************************** + * Name: pga11x_uenable + * + * Description: + * Take one PGA11x out of shutdown down mode. + * + * If CONFIG_PGA11X_DAISYCHAIN is defined, then pga11x_uenable() is + * provided to enable the parts independently. + * + * Input Parameters: + * spi - An SPI "bottom half" device driver instance + * pos - Position of the chip in the daisy chain (0 or 1) + * + * Returned Value: + * Zero on sucess; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_PGA11X_DAISYCHAIN +EXTERN int pga11x_uenable(PGA11X_HANDLE handle, int pos); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_ADC && CONFIG_ADC_PGA11X */ +#endif /* __INCLUDE_NUTTX_ANALOG_PGA11X_H */ diff --git a/nuttx/include/nuttx/arch.h b/nuttx/include/nuttx/arch.h new file mode 100644 index 0000000000..bf6be1ce08 --- /dev/null +++ b/nuttx/include/nuttx/arch.h @@ -0,0 +1,639 @@ +/**************************************************************************** + * include/nuttx/arch.h + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_ARCH_H +#define __INCLUDE_NUTTX_ARCH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef CODE void (*sig_deliver_t)(FAR _TCB *tcb); + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * These are standard interfaces that must be exported to the + * scheduler from architecture-specific code. + ****************************************************************************/ + +/**************************************************************************** + * Name: up_initialize + * + * Description: + * up_initialize will be called once during OS + * initialization after the basic OS services have been + * initialized. The architecture specific details of + * initializing the OS will be handled here. Such things as + * setting up interrupt service routines, starting the + * clock, and registering device drivers are some of the + * things that are different for each processor and hardware + * platform. + * + * up_initialize is called after the OS initialized but + * before the init process has been started and before the + * libraries have been initialized. OS services and driver + * services are available. + * + ****************************************************************************/ + +EXTERN void up_initialize(void); + +/**************************************************************************** + * Name: up_idle + * + * Description: + * up_idle() is the logic that will be executed + * when their is no other ready-to-run task. This is processor + * idle time and will continue until some interrupt occurs to + * cause a context switch from the idle task. + * + * Processing in this state may be processor-specific. e.g., + * this is where power management operations might be performed. + * + ****************************************************************************/ + +EXTERN void up_idle(void); + +/**************************************************************************** + * Name: up_initial_state + * + * Description: + * A new thread is being started and a new TCB + * has been created. This function is called to initialize + * the processor specific portions of the new TCB. + * + * This function must setup the intial architecture registers + * and/or stack so that execution will begin at tcb->start + * on the next context switch. + * + ****************************************************************************/ + +EXTERN void up_initial_state(FAR _TCB *tcb); + +/**************************************************************************** + * Name: up_create_stack + * + * Description: + * Allocate a stack for a new thread and setup + * up stack-related information in the TCB. + * + * The following TCB fields must be initialized: + * adj_stack_size: Stack size after adjustment for hardware, + * processor, etc. This value is retained only for debug + * purposes. + * stack_alloc_ptr: Pointer to allocated stack + * adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The + * initial value of the stack pointer. + * + * Inputs: + * tcb: The TCB of new task + * stack_size: The requested stack size. At least this much + * must be allocated. + * + ****************************************************************************/ + +#ifndef CONFIG_CUSTOM_STACK +EXTERN int up_create_stack(FAR _TCB *tcb, size_t stack_size); +#endif + +/**************************************************************************** + * Name: up_use_stack + * + * Description: + * Setup up stack-related information in the TCB + * using pre-allocated stack memory + * + * The following TCB fields must be initialized: + * adj_stack_size: Stack size after adjustment for hardware, + * processor, etc. This value is retained only for debug + * purposes. + * stack_alloc_ptr: Pointer to allocated stack + * adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The + * initial value of the stack pointer. + * + * Inputs: + * tcb: The TCB of new task + * stack_size: The allocated stack size. + * + ****************************************************************************/ + +#ifndef CONFIG_CUSTOM_STACK +EXTERN int up_use_stack(FAR _TCB *tcb, FAR void *stack, size_t stack_size); +#endif + +/**************************************************************************** + * Name: up_release_stack + * + * Description: + * A task has been stopped. Free all stack + * related resources retained int the defunct TCB. + * + ****************************************************************************/ + +#ifndef CONFIG_CUSTOM_STACK +EXTERN void up_release_stack(FAR _TCB *dtcb); +#endif + +/**************************************************************************** + * Name: up_unblock_task + * + * Description: + * A task is currently in an inactive task list + * but has been prepped to execute. Move the TCB to the + * ready-to-run list, restore its context, and start execution. + * + * This function is called only from the NuttX scheduling + * logic. Interrupts will always be disabled when this + * function is called. + * + * Inputs: + * tcb: Refers to the tcb to be unblocked. This tcb is + * in one of the waiting tasks lists. It must be moved to + * the ready-to-run list and, if it is the highest priority + * ready to run taks, executed. + * + ****************************************************************************/ + +EXTERN void up_unblock_task(FAR _TCB *tcb); + +/**************************************************************************** + * Name: up_block_task + * + * Description: + * The currently executing task at the head of + * the ready to run list must be stopped. Save its context + * and move it to the inactive list specified by task_state. + * + * This function is called only from the NuttX scheduling + * logic. Interrupts will always be disabled when this + * function is called. + * + * Inputs: + * tcb: Refers to a task in the ready-to-run list (normally + * the task at the head of the list). It most be + * stopped, its context saved and moved into one of the + * waiting task lists. It it was the task at the head + * of the ready-to-run list, then a context to the new + * ready to run task must be performed. + * task_state: Specifies which waiting task list should be + * hold the blocked task TCB. + * + ****************************************************************************/ + +EXTERN void up_block_task(FAR _TCB *tcb, tstate_t task_state); + +/**************************************************************************** + * Name: up_release_pending + * + * Description: + * When tasks become ready-to-run but cannot run because + * pre-emption is disabled, they are placed into a pending + * task list. This function releases and makes ready-to-run + * all of the tasks that have collected in the pending task + * list. This can cause a context switch if a new task is + * placed at the head of the ready to run list. + * + * This function is called only from the NuttX scheduling + * logic when pre-emptioni is re-enabled. Interrupts will + * always be disabled when this function is called. + * + ****************************************************************************/ + +EXTERN void up_release_pending(void); + +/**************************************************************************** + * Name: up_reprioritize_rtr + * + * Description: + * Called when the priority of a running or + * ready-to-run task changes and the reprioritization will + * cause a context switch. Two cases: + * + * 1) The priority of the currently running task drops and the next + * task in the ready to run list has priority. + * 2) An idle, ready to run task's priority has been raised above the + * the priority of the current, running task and it now has the + * priority. + * + * This function is called only from the NuttX scheduling + * logic. Interrupts will always be disabled when this + * function is called. + * + * Inputs: + * tcb: The TCB of the task that has been reprioritized + * priority: The new task priority + * + ****************************************************************************/ + +EXTERN void up_reprioritize_rtr(FAR _TCB *tcb, uint8_t priority); + +/**************************************************************************** + * Name: _exit + * + * Description: + * This function causes the currently executing task to cease + * to exist. This is a special case of task_delete() where the task to + * be deleted is the currently executing task. It is more complex because + * a context switch must be perform to the next ready to run task. + * + * Unlike other UP APIs, this function may be called directly from user + * programs in various states. The implementation of this function should + * disable interrupts before performing scheduling operations. + * + ****************************************************************************/ +/* Prototype is in unistd.h */ + +/**************************************************************************** + * Name: up_assert and up_assert_code + * + * Description: + * Assertions may be handled in an architecture-specific + * way. + * + ****************************************************************************/ +/* Prototype is in assert.h */ + +/**************************************************************************** + * Name: up_schedule_sigaction + * + * Description: + * This function is called by the OS when one or more + * signal handling actions have been queued for execution. + * The architecture specific code must configure things so + * that the 'igdeliver' callback is executed on the thread + * specified by 'tcb' as soon as possible. + * + * This function may be called from interrupt handling logic. + * + * This operation should not cause the task to be unblocked + * nor should it cause any immediate execution of sigdeliver. + * Typically, a few cases need to be considered: + * + * (1) This function may be called from an interrupt handler + * During interrupt processing, all xcptcontext structures + * should be valid for all tasks. That structure should + * be modified to invoke sigdeliver() either on return + * from (this) interrupt or on some subsequent context + * switch to the recipient task. + * (2) If not in an interrupt handler and the tcb is NOT + * the currently executing task, then again just modify + * the saved xcptcontext structure for the recipient + * task so it will invoke sigdeliver when that task is + * later resumed. + * (3) If not in an interrupt handler and the tcb IS the + * currently executing task -- just call the signal + * handler now. + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_SIGNALS +EXTERN void up_schedule_sigaction(FAR _TCB *tcb, sig_deliver_t sigdeliver); +#endif + +/**************************************************************************** + * Name: up_allocate_heap + * + * Description: + * The heap may be statically allocated by defining CONFIG_HEAP_BASE and + * CONFIG_HEAP_SIZE. If these are not defined, then this function will be + * called to dynamically set aside the heap region. + * + ****************************************************************************/ + +#ifndef CONFIG_HEAP_BASE +EXTERN void up_allocate_heap(FAR void **heap_start, size_t *heap_size); +#endif + +/**************************************************************************** + * Name: up_setpicbase, up_getpicbase + * + * Description: + * It NXFLAT external modules (or any other binary format that requires) + * PIC) are supported, then these macros must defined to (1) get or get + * the PIC base register value. These must be implemented with in-line + * assembly. + * + ****************************************************************************/ + +#ifndef CONFIG_PIC +# define up_setpicbase(picbase) +# define up_getpicbase(ppicbase) +#endif + +/**************************************************************************** + * Name: up_interrupt_context + * + * Description: + * Return true is we are currently executing in + * the interrupt handler context. + * + ****************************************************************************/ + +EXTERN bool up_interrupt_context(void); + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * On many architectures, there are three levels of interrupt enabling: (1) + * at the global level, (2) at the level of the interrupt controller, + * and (3) at the device level. In order to receive interrupts, they + * must be enabled at all three levels. + * + * This function implements enabling of the device specified by 'irq' + * at the interrupt controller level if supported by the architecture + * (irqrestore() supports the global level, the device level is hardware + * specific). + * + * Since this API is not supported on all architectures, it should be + * avoided in common implementations where possible. + * + ****************************************************************************/ + +#ifndef CONFIG_ARCH_NOINTC +EXTERN void up_enable_irq(int irq); +#endif + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * This function implements disabling of the device specified by 'irq' + * at the interrupt controller level if supported by the architecture + * (irqsave() supports the global level, the device level is hardware + * specific). + * + * Since this API is not supported on all architectures, it should be + * avoided in common implementations where possible. + * + ****************************************************************************/ + +#ifndef CONFIG_ARCH_NOINTC +EXTERN void up_disable_irq(int irq); +#endif + +/**************************************************************************** + * Name: up_prioritize_irq + * + * Description: + * Set the priority of an IRQ. + * + * Since this API is not supported on all architectures, it should be + * avoided in common implementations where possible. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_IRQPRIO +EXTERN int up_prioritize_irq(int irq, int priority); +#endif + +/**************************************************************************** + * Name: up_romgetc + * + * Description: + * In Harvard architectures, data accesses and instruction accesses occur + * on different busses, perhaps concurrently. All data accesses are + * performed on the data bus unless special machine instructions are + * used to read data from the instruction address space. Also, in the + * typical MCU, the available SRAM data memory is much smaller that the + * non-volatile FLASH instruction memory. So if the application requires + * many constant strings, the only practical solution may be to store + * those constant strings in FLASH memory where they can only be accessed + * using architecture-specific machine instructions. + * + * A similar case is where strings are retained in "external" memory such + * as EEPROM or serial FLASH. This case is similar only in that again + * special operations are required to obtain the string data; it cannot + * be accessed directly from a string pointer. + * + * If CONFIG_ARCH_ROMGETC is defined, then the architecture logic must + * export the function up_romgetc(). up_romgetc() will simply read one + * byte of data from the instruction space. + * + * If CONFIG_ARCH_ROMGETC, certain C stdio functions are effected: (1) + * All format strings in printf, fprintf, sprintf, etc. are assumed to + * lie in FLASH (string arguments for %s are still assumed to reside in + * SRAM). And (2), the string argument to puts and fputs is assumed to + * reside in FLASH. Clearly, these assumptions may have to modified for + * the particular needs of your environment. There is no "one-size-fits-all" + * solution for this problem. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_ROMGETC +EXTERN char up_romgetc(FAR const char *ptr); +#else +# define up_romgetc(ptr) (*ptr) +#endif + +/**************************************************************************** + * Name: up_mdelay and up_udelay + * + * Description: + * Some device drivers may require that the plaform-specific logic + * provide these timing loops for short delays. + * + ***************************************************************************/ + +EXTERN void up_mdelay(unsigned int milliseconds); +EXTERN void up_udelay(useconds_t microseconds); + +/**************************************************************************** + * Name: up_cxxinitialize + * + * Description: + * If C++ and C++ static constructors are supported, then this function + * must be provided by board-specific logic in order to perform + * initialization of the static C++ class instances. + * + * This function should then be called in the application-specific + * user_start logic in order to perform the C++ initialization. NOTE + * that no component of the core NuttX RTOS logic is involved; This + * function definition only provides the 'contract' between application + * specific C++ code and platform-specific toolchain support + * + ***************************************************************************/ + +#if defined(CONFIG_HAVE_CXX) && defined(CONFIG_HAVE_CXXINITIALIZE) +EXTERN void up_cxxinitialize(void); +#endif + +/**************************************************************************** + * These are standard interfaces that are exported by the OS + * for use by the architecture specific logic + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_process_timer + * + * Description: + * This function handles system timer events. + * The timer interrupt logic itself is implemented in the + * architecture specific code, but must call the following OS + * function periodically -- the calling interval must be + * MSEC_PER_TICK. + * + ****************************************************************************/ + +EXTERN void sched_process_timer(void); + +/**************************************************************************** + * Name: irq_dispatch + * + * Description: + * This function must be called from the achitecture- + * specific logic in order to dispatch an interrupt to + * the appropriate, registered handling logic. + * + ***************************************************************************/ + +EXTERN void irq_dispatch(int irq, FAR void *context); + +/**************************************************************************** + * Board-specific button interfaces exported by the board-specific logic + ****************************************************************************/ + +/**************************************************************************** + * Name: up_buttoninit + * + * Description: + * up_buttoninit() must be called to initialize button resources. After + * that, up_buttons() may be called to collect the current state of all + * buttons or up_irqbutton() may be called to register button interrupt + * handlers. + * + * NOTE: This interface may or may not be supported by board-specific + * logic. If the board supports button interfaces, then CONFIG_ARCH_BUTTONS + * will be defined. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_BUTTONS +EXTERN void up_buttoninit(void); +#endif + +/**************************************************************************** + * Name: up_buttons + * + * Description: + * After up_buttoninit() has been called, up_buttons() may be called to + * collect the state of all buttons. up_buttons() returns an 8-bit bit set + * with each bit associated with a button. A bit set to "1" means that the + * button is depressed; a bit set to "0" means that the button is released. + * The correspondence of the each button bit and physical buttons is board- + * specific. + * + * NOTE: This interface may or may not be supported by board-specific + * logic. If the board supports button interfaces, then CONFIG_ARCH_BUTTONS + * will be defined + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_BUTTONS +EXTERN uint8_t up_buttons(void); +#endif + +/**************************************************************************** + * Name: up_irqbutton + * + * Description: + * This function may be called to register an interrupt handler that will + * be called when a button is depressed or released. The ID value is a + * button enumeration value that uniquely identifies a button resource. + * The previous interrupt handler address is returned (so that it may + * restored, if so desired). + * + * NOTE: This interface may or may not be supported by board-specific + * logic. If the board supports any button interfaces, then + * CONFIG_ARCH_BUTTONS will be defined; If the board supports interrupt + * buttons, then CONFIG_ARCH_IRQBUTTONS will also be defined. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_IRQBUTTONS +EXTERN xcpt_t up_irqbutton(int id, xcpt_t irqhandler); +#endif + +/**************************************************************************** + * Debug interfaces exported by the architecture-specific logic + ****************************************************************************/ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Output one character on the console + * + ****************************************************************************/ + +EXTERN int up_putc(int ch); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_ARCH_H */ + diff --git a/nuttx/include/nuttx/ascii.h b/nuttx/include/nuttx/ascii.h new file mode 100644 index 0000000000..bfecff520f --- /dev/null +++ b/nuttx/include/nuttx/ascii.h @@ -0,0 +1,200 @@ +/**************************************************************************** + * include/nuttx/ascii.h + * ASCII Control Codes + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_ASCII_H +#define __INCLUDE_NUTTX_ASCII_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* All 7-bit ASCII codes */ + +#define ASCII_NUL 0x00 /* Null character (^@) */ +#define ASCII_SOH 0x01 /* Start of header (^A) */ +#define ASCII_STX 0x02 /* Start of tex (^B) */ +#define ASCII_ETX 0x03 /* End of text (^C) */ +#define ASCII_EOT 0x04 /* End of transmission (^D) */ +#define ASCII_ENQ 0x05 /* Enquiry (^E) */ +#define ASCII_ACK 0x06 /* Acknowledge (^F) */ +#define ASCII_BEL 0x07 /* Bell (^G) */ +#define ASCII_BS 0x08 /* Backspace (^H) */ +#define ASCII_TAB 0x09 /* Horizontal tab (^I) */ +#define ASCII_LF 0x0a /* Line Feed (^J) */ +#define ASCII_VT 0x0b /* Vertical tab(^K) */ +#define ASCII_FF 0x0c /* Form Feed (^L) */ +#define ASCII_CR 0x0d /* Carriage Return (^M) */ +#define ASCII_SO 0x0e /* Shift Out (^N) */ +#define ASCII_SI 0x0f /* Shift In (^O) */ + +#define ASCII_DLE 0x10 /* Data link escape (^P) */ +#define ASCII_DC1 0x11 /* XON (^Q) */ +#define ASCII_DC2 0x12 /* Device control 2, block-mode flow control (^R) */ +#define ASCII_DC3 0x13 /* XOFF (^S) */ +#define ASCII_DC4 0x14 /* Device control 4 (^T) */ +#define ASCII_NAK 0x15 /* Negative acknowledge (^U) */ +#define ASCII_SYN 0x16 /* Synchronous idle (^V) */ +#define ASCII_ETB 0x17 /* End transmission block(^W) */ +#define ASCII_CAN 0x18 /* Cancel line(^X) */ +#define ASCII_EM 0x19 /* End of medium(^Y) */ +#define ASCII_SUB 0x1a /* Substitute (^Z) */ +#define ASCII_ESC 0x1b /* Escape (^[) */ +#define ASCII_FS 0x1c /* File separator (^\) */ +#define ASCII_GS 0x1d /* Group separator (^]) */ +#define ASCII_RS 0x1e /* Record separator, block-mode terminator (^^) */ +#define ASCII_US 0x1f /* Unit separator (^_) */ + +#define ASCII_SPACE 0x20 /* Space ( ) */ +#define ASCII_EXCLAM 0x21 /* Exclamation mark (!) */ +#define ASCII_QUOTE 0x22 /* Quotation mark (") */ +#define ASCII_NUMBER 0x23 /* Number sign (#) */ +#define ASCII_HASH 0x23 /* Hash (#) */ +#define ASCII_DOLLAR 0x24 /* Dollar sign ($) */ +#define ASCII_PERCENT 0x25 /* Percent sign (%) */ +#define ASCII_AMPERSAND 0x26 /* Ampersand (&) */ +#define ASCII_RSQUOTE 0x27 /* Closing single quote (') */ +#define ASCII_APOSTROPHE 0x27 /* Apostrophe (') */ +#define ASCII_LPAREN 0x28 /* Opening parenthesis (() */ +#define ASCII_RPAREN 0x29 /* Closing parenthesis ()) */ +#define ASCII_ASTERISK 0x2a /* Asterisk (*) */ +#define ASCII_PLUS 0x2b /* Plus sign (+) */ +#define ASCII_COMMA 0x2c /* Comma (,) */ +#define ASCII_HYPHEN 0x2d /* Hyphen (-) */ +#define ASCII_DASH 0x2d /* Dash (-) */ +#define ASCII_MINUS 0x2d /* Minus sign (-) */ +#define ASCII_PERIOD 0x2e /* Period (.) */ +#define ASCII_SLASH 0x2f /* Forward Slash (/) */ +#define ASCII_DIVIDE 0x2f /* Divide (/) */ + +#define ASCII_0 0x30 /* Numbers */ +#define ASCII_1 0x31 /* " " */ +#define ASCII_2 0x32 /* " " */ +#define ASCII_3 0x33 /* " " */ +#define ASCII_4 0x34 /* " " */ +#define ASCII_5 0x35 /* " " */ +#define ASCII_6 0x36 /* " " */ +#define ASCII_7 0x37 /* " " */ +#define ASCII_8 0x38 /* " " */ +#define ASCII_9 0x39 /* " " */ +#define ASCII_COLON 0x3a /* Colon (:) */ +#define ASCII_SEMICOLON 0x3b /* Semicolon (;) */ +#define ASCII_LT 0x3c /* Less than (<) */ +#define ASCII_EQUAL 0x3d /* Equal (=) */ +#define ASCII_GT 0x3e /* Greater than (>) */ +#define ASCII_QUESTION 0x3f /* Question mark (?) */ + +#define ASCII_AT 0x40 /* At sign (@) */ +#define ASCII_A 0x41 /* Upper case letters */ +#define ASCII_B 0x42 /* " " " " " " */ +#define ASCII_C 0x43 /* " " " " " " */ +#define ASCII_D 0x44 /* " " " " " " */ +#define ASCII_E 0x45 /* " " " " " " */ +#define ASCII_F 0x46 /* " " " " " " */ +#define ASCII_G 0x47 /* " " " " " " */ +#define ASCII_H 0x48 /* " " " " " " */ +#define ASCII_I 0x49 /* " " " " " " */ +#define ASCII_J 0x4a /* " " " " " " */ +#define ASCII_K 0x4b /* " " " " " " */ +#define ASCII_L 0x4c /* " " " " " " */ +#define ASCII_M 0x4d /* " " " " " " */ +#define ASCII_N 0x4e /* " " " " " " */ +#define ASCII_O 0x4f /* " " " " " " */ + +#define ASCII_P 0x50 /* " " " " " " */ +#define ASCII_Q 0x51 /* " " " " " " */ +#define ASCII_R 0x52 /* " " " " " " */ +#define ASCII_S 0x53 /* " " " " " " */ +#define ASCII_T 0x54 /* " " " " " " */ +#define ASCII_U 0x55 /* " " " " " " */ +#define ASCII_V 0x56 /* " " " " " " */ +#define ASCII_W 0x57 /* " " " " " " */ +#define ASCII_X 0x58 /* " " " " " " */ +#define ASCII_Y 0x59 /* " " " " " " */ +#define ASCII_Z 0x5a /* " " " " " " */ +#define ASCII_LBRACKET 0x5b /* Left bracket ([) */ +#define ASCII_BACKSLASH 0x5c /* Back slash (\) */ +#define ASCII_RBRACKET 0x5d /* Right bracket (]) */ +#define ASCII_CARET 0x5c /* Caret (^) */ +#define ASCII_CIRCUMFLEX 0x5c /* Circumflex (^) */ +#define ASCII_UNDERSCORE 0x5f /* Underscore (_) */ + +#define ASCII_RSQUOT 0x60 /* Closing single quote */ +#define ASCII_a 0x61 /* Lower case letters */ +#define ASCII_b 0x62 /* " " " " " " */ +#define ASCII_c 0x63 /* " " " " " " */ +#define ASCII_d 0x64 /* " " " " " " */ +#define ASCII_e 0x65 /* " " " " " " */ +#define ASCII_f 0x66 /* " " " " " " */ +#define ASCII_g 0x67 /* " " " " " " */ +#define ASCII_h 0x68 /* " " " " " " */ +#define ASCII_i 0x69 /* " " " " " " */ +#define ASCII_j 0x6a /* " " " " " " */ +#define ASCII_k 0x6b /* " " " " " " */ +#define ASCII_l 0x6c /* " " " " " " */ +#define ASCII_m 0x6d /* " " " " " " */ +#define ASCII_n 0x6e /* " " " " " " */ +#define ASCII_o 0x6f /* " " " " " " */ + +#define ASCII_p 0x70 /* " " " " " " */ +#define ASCII_q 0x71 /* " " " " " " */ +#define ASCII_r 0x72 /* " " " " " " */ +#define ASCII_s 0x73 /* " " " " " " */ +#define ASCII_t 0x74 /* " " " " " " */ +#define ASCII_u 0x75 /* " " " " " " */ +#define ASCII_v 0x76 /* " " " " " " */ +#define ASCII_w 0x77 /* " " " " " " */ +#define ASCII_x 0x78 /* " " " " " " */ +#define ASCII_y 0x79 /* " " " " " " */ +#define ASCII_z 0x7a /* " " " " " " */ +#define ASCII_LBRACE 0x7b /* Left brace ({) */ +#define ASCII_VERTBAR 0x7c /* Vertical bar (|) */ +#define ASCII_PIPE 0x7c /* Pipe (|) */ +#define ASCII_RBRACE 0x7d /* Right brace (}) */ +#define ASCII_TILDE 0x7e /* Tilde (~) */ +#define ASCII_DEL 0x7f /* Delete (rubout) */ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __INCLUDE_NUTTX_ASCII_H */ diff --git a/nuttx/include/nuttx/binfmt.h b/nuttx/include/nuttx/binfmt.h new file mode 100644 index 0000000000..70beda3933 --- /dev/null +++ b/nuttx/include/nuttx/binfmt.h @@ -0,0 +1,209 @@ +/**************************************************************************** + * include/nuttx/binfmt.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_BINFMT_H +#define __INCLUDE_NUTTX_BINFMT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This describes the file to be loaded */ + +struct symtab_s; +struct binary_s +{ + /* Information provided to the loader to load and bind a module */ + + FAR const char *filename; /* Full path to the binary to be loaded */ + FAR const char **argv; /* Argument list */ + FAR const struct symtab_s *exports; /* Table of exported symbols */ + int nexports; /* The number of symbols in exports[] */ + + /* Information provided from the loader (if successful) describing the + * resources used by the loaded module. + */ + + main_t entrypt; /* Entry point into a program module */ + FAR void *ispace; /* Memory-mapped, I-space (.text) address */ + FAR struct dspace_s *dspace; /* Address of the allocated .data/.bss space */ + size_t isize; /* Size of the I-space region (needed for munmap) */ + size_t stacksize; /* Size of the stack in bytes (unallocated) */ +}; + +/* This describes one binary format handler */ + +struct binfmt_s +{ + FAR struct binfmt_s *next; /* Supports a singly-linked list */ + int (*load)(FAR struct binary_s *bin); /* Verify and load binary into memory */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: register_binfmt + * + * Description: + * Register a loader for a binary format + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +EXTERN int register_binfmt(FAR struct binfmt_s *binfmt); + +/**************************************************************************** + * Name: unregister_binfmt + * + * Description: + * Register a loader for a binary format + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +EXTERN int unregister_binfmt(FAR struct binfmt_s *binfmt); + +/**************************************************************************** + * Name: load_module + * + * Description: + * Load a module into memory, bind it to an exported symbol take, and + * prep the module for execution. + * + * Returned Value: + * This is an end-user function, so it follows the normal convention: + * Returns 0 (OK) on success. On failure, it returns -1 (ERROR) with + * errno set appropriately. + * + ****************************************************************************/ + +EXTERN int load_module(FAR struct binary_s *bin); + +/**************************************************************************** + * Name: unload_module + * + * Description: + * Unload a (non-executing) module from memory. If the module has + * been started (via exec_module), calling this will be fatal. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +EXTERN int unload_module(FAR const struct binary_s *bin); + +/**************************************************************************** + * Name: exec_module + * + * Description: + * Execute a module that has been loaded into memory by load_module(). + * + * Returned Value: + * This is an end-user function, so it follows the normal convention: + * Returns the PID of the exec'ed module. On failure, it.returns + * -1 (ERROR) and sets errno appropriately. + * + ****************************************************************************/ + +EXTERN int exec_module(FAR const struct binary_s *bin, int priority); + +/**************************************************************************** + * Name: exec + * + * Description: + * This is a convenience function that wraps load_ and exec_module into + * one call. + * + * Input Parameter: + * filename - Fulll path to the binary to be loaded + * argv - Argument list + * exports - Table of exported symbols + * nexports - The number of symbols in exports + * + * Returned Value: + * This is an end-user function, so it follows the normal convention: + * Returns the PID of the exec'ed module. On failure, it.returns + * -1 (ERROR) and sets errno appropriately. + * + ****************************************************************************/ + +EXTERN int exec(FAR const char *filename, FAR const char **argv, + FAR const struct symtab_s *exports, int nexports); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_BINFMT_H */ + diff --git a/nuttx/include/nuttx/can.h b/nuttx/include/nuttx/can.h new file mode 100644 index 0000000000..31d34478ec --- /dev/null +++ b/nuttx/include/nuttx/can.h @@ -0,0 +1,374 @@ +/************************************************************************************ + * include/nuttx/can.h + * + * Copyright (C) 2008, 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef _INCLUDE_NUTTX_CAN_H +#define _INCLUDE_NUTTX_CAN_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +#include + +#ifdef CONFIG_CAN + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* CONFIG_CAN - Enables CAN support (one or both of CONFIG_STM32_CAN1 or + * CONFIG_STM32_CAN2 must also be defined) + * CONFIG_CAN_EXTID - Enables support for the 29-bit extended ID. Default + * Standard 11-bit IDs. + * CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages. + * Default: 8 + * CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests. + * Default: 4 + * CONFIG_CAN_LOOPBACK - A CAN driver may or may not support a loopback + * mode for testing. If the driver does support loopback mode, the setting + * will enable it. (If the driver does not, this setting will have no effect). + */ + +/* Default configuration settings that may be overridden in the NuttX configuration + * file or in the board configuration file. The configured size is limited to 255 + * to fit into a uint8_t. + */ + +#if !defined(CONFIG_CAN_FIFOSIZE) +# define CONFIG_CAN_FIFOSIZE 8 +#elif CONFIG_CAN_FIFOSIZE > 255 +# undef CONFIG_CAN_FIFOSIZE +# define CONFIG_CAN_FIFOSIZE 255 +#endif + +#if !defined(CONFIG_CAN_NPENDINGRTR) +# define CONFIG_CAN_NPENDINGRTR 4 +#elif CONFIG_CAN_NPENDINGRTR > 255 +# undef CONFIG_CAN_NPENDINGRTR +# define CONFIG_CAN_NPENDINGRTR 255 +#endif + +/* Convenience macros */ + +#define dev_reset(dev) dev->cd_ops->co_reset(dev) +#define dev_setup(dev) dev->cd_ops->co_setup(dev) +#define dev_shutdown(dev) dev->cd_ops->co_shutdown(dev) +#define dev_txint(dev,enable) dev->cd_ops->co_txint(dev,enable) +#define dev_rxint(dev,enable) dev->cd_ops->co_rxint(dev,enable) +#define dev_ioctl(dev,cmd,arg) dev->cd_ops->co_ioctl(dev,cmd,arg) +#define dev_remoterequest(dev,id) dev->cd_ops->co_remoterequest(dev,id) +#define dev_send(dev,m) dev->cd_ops->co_send(dev,m) +#define dev_txready(dev) dev->cd_ops->co_txready(dev) +#define dev_txempty(dev) dev->cd_ops->co_txempty(dev) + +/* CAN message support */ + +#define CAN_MAXDATALEN 8 +#define CAN_MAX_MSGID 0x07ff +#define CAN_MAX_EXTMSGID 0x1fffffff + +#define CAN_MSGLEN(nbytes) (sizeof(struct can_msg_s) - CAN_MAXDATALEN + (nbytes)) + +/* Built-in ioctl commands + * + * CANIOCTL_RTR: Send the remote transmission request and wait for the response. + */ + +#define CANIOCTL_RTR 1 /* Argument is a reference to struct canioctl_rtr_s */ + +/* CANIOCTL_USER: Device specific ioctl calls can be supported with cmds greater + * than this value + */ + +#define CANIOCTL_USER 2 + +/************************************************************************************ + * Public Types + ************************************************************************************/ +/* CAN-message Format (without Extended ID suppport) + * + * One based CAN-message is represented with a maximum of 10 bytes. A message is + * composed of at least the first 2 bytes (when there are no data bytes present). + * + * Bytes 0-1: Hold a 16-bit value in host byte order + * Bits 0-3: Data Length Code (DLC) + * Bit 4: Remote Tranmission Request (RTR) + * Bits 5-15: The 11-bit CAN identifier + * + * Bytes 2-9: CAN data + * + * CAN-message Format (with Extended ID suppport) + * + * One CAN-message consists of a maximum of 13 bytes. A message is composed of at + * least the first 5 bytes (when there are no data bytes). + * + * Bytes 0-3: Hold 11- or 29-bit CAN ID in host byte order + * Byte 4: Bits 0-3: Data Length Code (DLC) + * Bit 4: Remote Tranmission Request (RTR) + * Bit 5: Extended ID indication + * Bits 6-7: Unused + * Bytes 5-12: CAN data + * + * The struct can_msg_s holds this information in a user-friendly, unpacked form. + * This is the form that is used at the read() and write() driver interfaces. The + * message structure is actually variable length -- the true length is given by + * the CAN_MSGLEN macro. + */ + +#ifdef CONFIG_CAN_EXTID +struct can_hdr_s +{ + uint32_t ch_id; /* 11- or 29-bit ID (3-bits unsed) */ + uint8_t ch_dlc : 4; /* 4-bit DLC */ + uint8_t ch_rtr : 1; /* RTR indication */ + uint8_t ch_extid : 1; /* Extended ID indication */ + uint8_t ch_unused : 2; /* Unused */ +} packed_struct; +#else +struct can_hdr_s +{ + uint16_t ch_dlc : 4; /* 4-bit DLC */ + uint16_t ch_rtr : 1; /* RTR indication */ + uint16_t ch_id : 11; /* 11-bit standard ID */ +} packed_struct; +#endif + +struct can_msg_s +{ + struct can_hdr_s cm_hdr; /* The CAN header */ + uint8_t cm_data[CAN_MAXDATALEN]; /* CAN message data (0-8 byte) */ +} packed_struct; + +/* This structure defines a CAN message FIFO. */ + +struct can_rxfifo_s +{ + sem_t rx_sem; /* Counting semaphore */ + uint8_t rx_head; /* Index to the head [IN] in the circular buffer */ + uint8_t rx_tail; /* Index to the tail [OUT] in the circular buffer */ + /* Circular buffer of CAN messages */ + struct can_msg_s rx_buffer[CONFIG_CAN_FIFOSIZE]; +}; + +struct can_txfifo_s +{ + sem_t tx_sem; /* Counting semaphore */ + uint8_t tx_head; /* Index to the head [IN] in the circular buffer */ + uint8_t tx_queue; /* Index to next message to send */ + uint8_t tx_tail; /* Index to the tail [OUT] in the circular buffer */ + /* Circular buffer of CAN messages */ + struct can_msg_s tx_buffer[CONFIG_CAN_FIFOSIZE]; +}; + +/* The following structure define the logic to handle one RTR message transaction */ + +struct can_rtrwait_s +{ + sem_t cr_sem; /* Wait for RTR response */ + uint16_t cr_id; /* The ID that is waited for */ + FAR struct can_msg_s *cr_msg; /* This is where the RTR reponse goes */ +}; + +/* This structure defines all of the operations providd by the architecture specific + * logic. All fields must be provided with non-NULL function pointers by the + * caller of can_register(). + */ + +struct can_dev_s; +struct can_ops_s +{ + /* Reset the CAN device. Called early to initialize the hardware. This + * is called, before co_setup() and on error conditions. + */ + + CODE void (*co_reset)(FAR struct can_dev_s *dev); + + /* Configure the CAN. This method is called the first time that the CAN + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching CAN interrupts. All CAN + * interrupts are disabled upon return. + */ + + CODE int (*co_setup)(FAR struct can_dev_s *dev); + + /* Disable the CAN. This method is called when the CAN device is closed. + * This method reverses the operation the setup method. + */ + + CODE void (*co_shutdown)(FAR struct can_dev_s *dev); + + /* Call to enable or disable RX interrupts */ + + CODE void (*co_rxint)(FAR struct can_dev_s *dev, bool enable); + + /* Call to enable or disable TX interrupts */ + + CODE void (*co_txint)(FAR struct can_dev_s *dev, bool enable); + + /* All ioctl calls will be routed through this method */ + + CODE int (*co_ioctl)(FAR struct can_dev_s *dev, int cmd, unsigned long arg); + + /* Send a remote request */ + + CODE int (*co_remoterequest)(FAR struct can_dev_s *dev, uint16_t id); + + /* This method will send one message on the CAN */ + + CODE int (*co_send)(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg); + + /* Return true if the CAN hardware can accept another TX message. */ + + CODE bool (*co_txready)(FAR struct can_dev_s *dev); + + /* Return true if all message have been sent. If for example, the CAN + * hardware implements FIFOs, then this would mean the transmit FIFO is + * empty. This method is called when the driver needs to make sure that + * all characters are "drained" from the TX hardware before calling co_shutdown(). + */ + + CODE bool (*co_txempty)(FAR struct can_dev_s *dev); +}; + +/* This is the device structure used by the driver. The caller of + * can_register() must allocate and initialize this structure. The + * calling logic need only set all fields to zero except: + * + * The elements of 'cd_ops', and 'cd_priv' + * + * The common logic will initialize all semaphores. + */ + +struct can_dev_s +{ + uint8_t cd_ocount; /* The number of times the device has been opened */ + uint8_t cd_npendrtr; /* Number of pending RTR messages */ + uint8_t cd_ntxwaiters; /* Number of threads waiting to enqueue a message */ + sem_t cd_closesem; /* Locks out new opens while close is in progress */ + sem_t cd_recvsem; /* Used to wakeup user waiting for space in cd_recv.buffer */ + struct can_txfifo_s cd_xmit; /* Describes transmit FIFO */ + struct can_rxfifo_s cd_recv; /* Describes receive FIFO */ + /* List of pending RTR requests */ + struct can_rtrwait_s cd_rtr[CONFIG_CAN_NPENDINGRTR]; + FAR const struct can_ops_s *cd_ops; /* Arch-specific operations */ + FAR void *cd_priv; /* Used by the arch-specific logic */ +}; + +/* Structures used with ioctl calls */ + +struct canioctl_rtr_s +{ + uint16_t ci_id; /* The 11-bit ID to use in the RTR message */ + FAR struct can_msg_s *ci_msg; /* The location to return the RTR response */ +}; + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Name: can_register + * + * Description: + * Register a CAN driver. + * + ************************************************************************************/ + +EXTERN int can_register(FAR const char *path, FAR struct can_dev_s *dev); + +/************************************************************************************ + * Name: can_receive + * + * Description: + * Called from the CAN interrupt handler when new read data is available + * + * Parameters: + * dev - The specifi CAN device + * hdr - The 16-bit CAN header + * data - An array contain the CAN data. + * + * Return: + * OK on success; a negated errno on failure. + * + ************************************************************************************/ + +EXTERN int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr, + FAR uint8_t *data); + +/************************************************************************************ + * Name: can_txdone + * + * Description: + * Called from the CAN interrupt handler at the completion of a send operation. + * + * Parameters: + * dev - The specifi CAN device + * hdr - The 16-bit CAN header + * data - An array contain the CAN data. + * + * Return: + * OK on success; a negated errno on failure. + * + ************************************************************************************/ + +EXTERN int can_txdone(FAR struct can_dev_s *dev); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* CONFIG_CAN */ +#endif /* _INCLUDE_NUTTX_CAN_H */ diff --git a/nuttx/include/nuttx/clock.h b/nuttx/include/nuttx/clock.h new file mode 100644 index 0000000000..952e0e5efc --- /dev/null +++ b/nuttx/include/nuttx/clock.h @@ -0,0 +1,251 @@ +/**************************************************************************** + * include/nuttx/clock.h + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef _INCLUDE_NUTTX_CLOCK_H +#define _INCLUDE_NUTTX_CLOCK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Pro-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* Efficient, direct access to OS global timer variables will be supported + * if the execution environment has direct access to kernel global data. + * The code in this execution context can access the kernel global data + * directly if: (1) this is an un-protected, non-kernel build, or (2) + * this code is being built for execution within the kernel. + */ + +#undef __HAVE_KERNEL_GLOBALS +#if !defined(CONFIG_NUTTX_KERNEL) || defined(__KERNEL__) +# define __HAVE_KERNEL_GLOBALS 1 +#else +# define __HAVE_KERNEL_GLOBALS 0 +#endif + +/* If CONFIG_SYSTEM_TIME64 is selected and the CPU supports long long types, + * then a 64-bit system time will be used. + */ + +#ifndef CONFIG_HAVE_LONG_LONG +# undef CONFIG_SYSTEM_TIME64 +#endif + +/* Timing constants *********************************************************/ + +#define NSEC_PER_SEC 1000000000 +#define USEC_PER_SEC 1000000 +#define MSEC_PER_SEC 1000 +#define DSEC_PER_SEC 10 +#define NSEC_PER_DSEC 100000000 +#define USEC_PER_DSEC 100000 +#define MSEC_PER_DSEC 100 +#define NSEC_PER_MSEC 1000000 +#define USEC_PER_MSEC 1000 +#define NSEC_PER_USEC 1000 + +/* The interrupt interval of the system timer is given by MSEC_PER_TICK. + * This is the expected number of milliseconds between calls from the + * processor-specific logic to sched_process_timer(). The default value + * of MSEC_PER_TICK is 10 milliseconds (100KHz). However, this default + * setting can be overridden by defining the interval in milliseconds as + * CONFIG_MSEC_PER_TICK in the board configuration file. + * + * The following calculations are only accurate when (1) there is no + * truncation involved and (2) the underlying system timer is an even + * multiple of milliseconds. If (2) is not true, you will probably want + * to redefine all of the following. + */ + +#ifdef CONFIG_MSEC_PER_TICK +# define MSEC_PER_TICK (CONFIG_MSEC_PER_TICK) +#else +# define MSEC_PER_TICK (10) +#endif + +#define TICK_PER_DSEC (MSEC_PER_DSEC / MSEC_PER_TICK) /* Truncates! */ +#define TICK_PER_SEC (MSEC_PER_SEC / MSEC_PER_TICK) /* Truncates! */ +#define NSEC_PER_TICK (MSEC_PER_TICK * NSEC_PER_MSEC) /* Exact */ +#define USEC_PER_TICK (MSEC_PER_TICK * USEC_PER_MSEC) /* Exact */ + +#define NSEC2TICK(nsec) (((nsec)+(NSEC_PER_TICK/2))/NSEC_PER_TICK) /* Rounds */ +#define USEC2TICK(usec) (((usec)+(USEC_PER_TICK/2))/USEC_PER_TICK) /* Rounds */ +#define MSEC2TICK(msec) (((msec)+(MSEC_PER_TICK/2))/MSEC_PER_TICK) /* Rounds */ +#define DSEC2TICK(dsec) MSEC2TICK((dsec)*MSEC_PER_DSEC) +#define SEC2TICK(sec) MSEC2TICK((sec)*MSEC_PER_SEC) + +#define TICK2NSEC(tick) ((tick)*NSEC_PER_TICK) /* Exact */ +#define TICK2USEC(tick) ((tick)*USEC_PER_TICK) /* Exact */ +#define TICK2MSEC(tick) ((tick)*MSEC_PER_TICK) /* Exact */ +#define TICK2DSEC(tick) (((tick)+(TICK_PER_DSEC/2))/TICK_PER_DSEC) /* Rounds */ +#define TICK2SEC(tick) (((tick)+(TICK_PER_SEC/2))/TICK_PER_SEC) /* Rounds */ + +/**************************************************************************** + * Global Data + ****************************************************************************/ + +#if !defined(CONFIG_DISABLE_CLOCK) + +/* Access to raw system clock ***********************************************/ +/* Direct access to the system timer/counter is supported only if (1) the + * system timer counter is available (i.e., we are not configured to use + * a hardware periodic timer), and (2) the execution environment has direct + * access to kernel global data + */ + +#if __HAVE_KERNEL_GLOBALS +# ifdef CONFIG_SYSTEM_TIME64 + +extern volatile uint64_t g_system_timer; +#define clock_systimer() (uint32_t)(g_system_timer & 0x00000000ffffffff) +#define clock_systimer64() g_system_timer + +# else + +extern volatile uint32_t g_system_timer; +#define clock_systimer() g_system_timer + +# endif +#endif + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Function: clock_synchronize + * + * Description: + * Synchronize the system timer to a hardware RTC. This operation is + * normally performed automatically by the system during clock + * initialization. However, the user may also need to explicitly re- + * synchronize the system timer to the RTC under certain conditions where + * the system timer is known to be in error. For example, in certain low- + * power states, the system timer may be stopped but the RTC will continue + * keep correct time. After recovering from such low-power state, this + * function should be called to restore the correct system time. + * + * Calling this function could result in system time going "backward" in + * time, especially with certain lower resolution RTC implementations. + * Time going backward could have bad consequences if there are ongoing + * timers and delays. So use this interface with care. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_RTC +EXTERN void clock_synchronize(void); +#endif + +/**************************************************************************** + * Function: clock_systimer + * + * Description: + * Return the current value of the 32-bit system timer counter. Indirect + * access to the system timer counter is required through this function if + * the execution environment does not have direct access to kernel global + * data + * + * Parameters: + * None + * + * Return Value: + * The current value of the system timer counter + * + * Assumptions: + * + ****************************************************************************/ + +#if !__HAVE_KERNEL_GLOBALS +# ifdef CONFIG_SYSTEM_TIME64 +# define clock_systimer() (uint32_t)(clock_systimer64() & 0x00000000ffffffff) +# else +EXTERN uint32_t clock_systimer(void); +# endif +#endif + +/**************************************************************************** + * Function: clock_systimer64 + * + * Description: + * Return the current value of the 64-bit system timer counter. Indirect + * access to the system timer counter is required through this function if + * the execution environment does not have direct access to kernel global + * data + * + * Parameters: + * None + * + * Return Value: + * The current value of the system timer counter + * + * Assumptions: + * + ****************************************************************************/ + +#if !__HAVE_KERNEL_GLOBALS && defined(CONFIG_SYSTEM_TIME64) +EXTERN uint64_t clock_systimer64(void); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* !CONFIG_DISABLE_CLOCK */ +#endif /* _INCLUDE_NUTTX_CLOCK_H */ diff --git a/nuttx/include/nuttx/compiler.h b/nuttx/include/nuttx/compiler.h new file mode 100644 index 0000000000..733d58eec6 --- /dev/null +++ b/nuttx/include/nuttx/compiler.h @@ -0,0 +1,448 @@ +/**************************************************************************** + * include/nuttx/compiler.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_COMPILER_H +#define __INCLUDE_NUTTX_COMPILER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* GCC-specific definitions *************************************************/ + +#ifdef __GNUC__ + +/* Pre-processor */ + +# define CONFIG_CPP_HAVE_VARARGS 1 /* Supports variable argument macros */ +# define CONFIG_CPP_HAVE_WARNING 1 /* Supports #warning */ + +/* Intriniscs */ + +# define CONFIG_HAVE_FUNCTIONNAME 1 /* Has __FUNCTION__ */ +# define CONFIG_HAVE_FILENAME 1 /* Has __FILE__ */ + +/* Attributes + * + * GCC supports weak symbols which can be used to reduce code size because + * unnecessary "weak" functions can be excluded from the link. + */ + +# ifndef __CYGWIN__ +# define CONFIG_HAVE_WEAKFUNCTIONS 1 +# define weak_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))); +# define weak_function __attribute__ ((weak)) +# define weak_const_function __attribute__ ((weak, __const__)) +# else +# undef CONFIG_HAVE_WEAKFUNCTIONS +# define weak_alias(name, aliasname) +# define weak_function +# define weak_const_function +#endif + +/* The noreturn attribute informs GCC that the function will not return. */ + +# define noreturn_function __attribute__ ((noreturn)) + +/* The packed attribute informs GCC that the stucture elements are packed, + * ignoring other alignment rules. + */ + +# define packed_struct __attribute__ ((packed)) + +/* GCC does not support the reentrant or naked attributes */ + +# define reentrant_function +# define naked_function + +/* GCC has does not use storage classes to qualify addressing */ + +# define FAR +# define NEAR +# define DSEG +# define CODE + +/* Handle cases where sizeof(int) is 16-bits, sizeof(long) is 32-bits, and + * pointers are 16-bits. + */ + +#if defined(__m32c__) +/* Select the small, 16-bit addressing model */ + +# define CONFIG_SMALL_MEMORY 1 + +/* Long and int are not the same size */ + +# define CONFIG_LONG_IS_NOT_INT 1 + +/* Pointers and int are the same size */ + +# undef CONFIG_PTR_IS_NOT_INT + +#elif defined(__AVR__) +/* Select the small, 16-bit addressing model */ + +# define CONFIG_SMALL_MEMORY 1 + +/* Long and int are not the same size */ + +# define CONFIG_LONG_IS_NOT_INT 1 + +/* Pointers and int are the same size */ + +# undef CONFIG_PTR_IS_NOT_INT + +/* Uses a 32-bit FAR pointer only from accessing data outside of the 16-bit + * data space. + */ + +# define CONFIG_HAVE_FARPOINTER 1 + +#elif defined(__mc68hc1x__) +/* Select the small, 16-bit addressing model */ + +# define CONFIG_SMALL_MEMORY 1 + +/* Normally, mc68hc1x code is compiled with the -mshort option + * which results in a 16-bit integer. If -mnoshort is defined + * then an integer is 32-bits. GCC will defined __INT__ accordingly: + */ + +# if __INT__ == 16 +/* int is 16-bits, long is 32-bits */ + +# define CONFIG_LONG_IS_NOT_INT 1 + +/* Pointers and int are the same size (16-bits) */ + +# undef CONFIG_PTR_IS_NOT_INT +#else +/* int and long are both 32-bits */ + +# undef CONFIG_LONG_IS_NOT_INT + +/* Pointers and int are NOT the same size */ + +# define CONFIG_PTR_IS_NOT_INT 1 +#endif + +#else +/* Select the large, 32-bit addressing model */ + +# undef CONFIG_SMALL_MEMORY + +/* Long and int are (probably) the same size (32-bits) */ + +# undef CONFIG_LONG_IS_NOT_INT + +/* Pointers and int are the same size (32-bits) */ + +# undef CONFIG_PTR_IS_NOT_INT +#endif + +/* GCC supports inlined functions */ + +# define CONFIG_HAVE_INLINE 1 + +/* GCC supports both types double and long long */ + +# define CONFIG_HAVE_DOUBLE 1 +# define CONFIG_HAVE_LONG_LONG 1 + +/* Structures and unions can be assigned and passed as values */ + +# define CONFIG_CAN_PASS_STRUCTS 1 + +/* SDCC-specific definitions ************************************************/ + +#elif defined(SDCC) + +/* Pre-processor */ + +# define CONFIG_CPP_HAVE_VARARGS 1 /* Supports variable argument macros */ +# define CONFIG_CPP_HAVE_WARNING 1 /* Supports #warning */ + +/* Intriniscs */ + +# define CONFIG_HAVE_FUNCTIONNAME 1 /* Has __FUNCTION__ */ +# define CONFIG_HAVE_FILENAME 1 /* Has __FILE__ */ + +/* Pragmas + * + * Disable warnings for unused function arguments */ + +# pragma disable_warning 85 + +/* Attributes + * + * SDCC does not support weak symbols */ + +# undef CONFIG_HAVE_WEAKFUNCTIONS +# define weak_alias(name, aliasname) +# define weak_function +# define weak_const_function + +/* SDCC does not support the noreturn or packed attributes */ + +# define noreturn_function +# define packed_struct + +/* SDCC does support "naked" function s*/ + +# define naked_function __naked + +/* The reentrant attribute informs SDCC that the function + * must be reentrant. In this case, SDCC will store input + * arguments on the stack to support reentrancy. + */ + +# define reentrant_function __reentrant + +/* It is assumed that the system is build using the small + * data model with storage defaulting to internal RAM. + * The NEAR storage class can also be used to address data + * in internal RAM; FAR can be used to address data in + * external RAM. + */ + +#if defined(__z80) || defined(__gbz80) +# define FAR +# define NEAR +# define CODE +# define DSEG +#else +# define FAR __xdata +# define NEAR __data +# define CODE __code +# if defined(SDCC_MODEL_SMALL) +# define DSEG __data +# else +# define DSEG __xdata +# endif +#endif + +/* Select small, 16-bit address model */ + +# define CONFIG_SMALL_MEMORY 1 + +/* Long and int are not the same size */ + +# define CONFIG_LONG_IS_NOT_INT 1 + +/* The generic pointer and int are not the same size + * (for some SDCC architectures) + */ + +#if !defined(__z80) && !defined(__gbz80) +# define CONFIG_PTR_IS_NOT_INT 1 +#endif + +/* SDCC does not support inline functions */ + +# undef CONFIG_HAVE_INLINE +# define inline + +/* SDCC does not support type long long or type double */ + +# undef CONFIG_HAVE_LONG_LONG +# undef CONFIG_HAVE_DOUBLE + +/* Structures and unions cannot be passed as values or used + * in assignments. + */ + +# undef CONFIG_CAN_PASS_STRUCTS + +/* Zilog-specific definitions ***********************************************/ + +#elif defined(__ZILOG__) + +/* At present, only the following Zilog compilers are recognized */ + +# if !defined(__ZNEO__) && !defined(__EZ8__) && !defined(__EZ80__) +# warning "Unrecognized Zilog compiler" +# endif + +/* Pre-processor */ + +# undef CONFIG_CPP_HAVE_VARARGS /* No variable argument macros */ +# undef CONFIG_CPP_HAVE_WARNING /* Does not support #warning */ + +/* Intrinsics */ + +# define CONFIG_HAVE_FUNCTIONNAME 1 /* Has __FUNCTION__ */ +# define CONFIG_HAVE_FILENAME 1 /* Has __FILE__ */ + +/* Attributes + * + * The Zilog compiler does not support weak symbols + */ + +# undef CONFIG_HAVE_WEAKFUNCTIONS +# define weak_alias(name, aliasname) +# define weak_function +# define weak_const_function + +/* The Zilog compiler does not support the noreturn, packed, or naked attributes */ + +# define noreturn_function +# define packed_struct +# define naked_function + +/* The Zilog compiler does not support the reentrant attribute */ + +# define reentrant_function + +/* Addressing. + * + * Z16F ZNEO: Far is 24-bits; near is 16-bits of address. + * The supported model is (1) all code on ROM, and (2) all data + * and stacks in external (far) RAM. + * Z8Encore!: Far is 16-bits; near is 8-bits of address. + * The supported model is (1) all code on ROM, and (2) all data + * and stacks in internal (far) RAM. + * Z8Acclaim: In Z80 mode, all pointers are 16-bits. In ADL mode, all pointers + * are 24 bits. + */ + +# if defined(__ZNEO__) +# define FAR _Far +# define NEAR _Near +# define DSEG _Far +# define CODE _Erom +# undef CONFIG_SMALL_MEMORY /* Select the large, 32-bit addressing model */ +# undef CONFIG_LONG_IS_NOT_INT /* Long and int are the same size */ +# undef CONFIG_PTR_IS_NOT_INT /* FAR pointers and int are the same size */ +# elif defined(__EZ8__) +# define FAR far +# define NEAR near +# define DSEG far +# define CODE rom +# define CONFIG_SMALL_MEMORY 1 /* Select small, 16-bit address model */ +# define CONFIG_LONG_IS_NOT_INT 1 /* Long and int are not the same size */ +# undef CONFIG_PTR_IS_NOT_INT /* FAR pointers and int are the same size */ +# elif defined(__EZ80__) +# define FAR +# define NEAR +# define DSEG +# define CODE +# undef CONFIG_SMALL_MEMORY /* Select the large, 32-bit addressing model */ +# define CONFIG_LONG_IS_NOT_INT 1 /* Long and int are not the same size */ +# ifdef CONFIG_EZ80_Z80MODE +# define CONFIG_PTR_IS_NOT_INT 1 /* Pointers and int are not the same size */ +# else +# undef CONFIG_PTR_IS_NOT_INT /* Pointers and int are the same size */ +# endif +# endif + +/* The Zilog compiler does not support inline functions */ + +# undef CONFIG_HAVE_INLINE +# define inline + +/* Older Zilog compilers support both types double and long long, but the size + * is 32-bits (same as long and single precision) so it is safer to say that + * they are not supported. Later versions are more ANSII compliant and + * simply do not support long long or double. + */ + +# undef CONFIG_HAVE_DOUBLE +# undef CONFIG_HAVE_LONG_LONG + +/* Structures and unions can be assigned and passed as values */ + +# define CONFIG_CAN_PASS_STRUCTS 1 + +/* Unknown compiler *********************************************************/ + +#else + +# undef CONFIG_CPP_HAVE_VARARGS +# undef CONFIG_CPP_HAVE_WARNING +# undef CONFIG_HAVE_FUNCTIONNAME +# undef CONFIG_HAVE_FILENAME +# undef CONFIG_HAVE_WEAKFUNCTIONS +# define weak_alias(name, aliasname) +# define weak_function +# define weak_const_function +# define noreturn_function +# define packed_struct +# define reentrant_function +# define naked_function + + +# define FAR +# define NEAR +# define DSEG +# define CODE + +# undef CONFIG_SMALL_MEMORY +# undef CONFIG_LONG_IS_NOT_INT +# undef CONFIG_PTR_IS_NOT_INT +# undef CONFIG_HAVE_INLINE +# define inline +# undef CONFIG_HAVE_LONG_LONG +# undef CONFIG_HAVE_DOUBLE +# undef CONFIG_CAN_PASS_STRUCTS + +#endif + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_COMPILER_H */ diff --git a/nuttx/include/nuttx/fb.h b/nuttx/include/nuttx/fb.h new file mode 100644 index 0000000000..ddff4edf8f --- /dev/null +++ b/nuttx/include/nuttx/fb.h @@ -0,0 +1,354 @@ +/**************************************************************************** + * include/nuttx/fb.h + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef _INCLUDE_NUTTX_FB_H +#define _INCLUDE_NUTTX_FB_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +/* Color format definitions. The pretty much define the color pixel processing + * organization of the video controller. + */ + +/* Monochrome Formats *******************************************************/ + +#define FB_FMT_Y1 0 /* BPP=1, monochrome */ +#define FB_FMT_Y4 1 /* BPP=4, 4-bit uncompressed greyscale */ +#define FB_FMT_Y8 2 /* BPP=8, 8-bit uncompressed greyscale */ +#define FB_FMT_Y16 3 /* BPP=16, 16-bit uncompressed greyscale */ +#define FB_FMT_GREY FB_FMT_Y8 /* BPP=8 */ +#define FB_FMT_Y800 FB_FMT_Y8 /* BPP=8 */ + +#define FB_ISMONO(f) ((f) >= FB_FMT_Y4) && (f) <= FB_FMT_Y16) + +/* RGB video formats ********************************************************/ + +/* Standard RGB */ + +#define FB_FMT_RGB1 FB_FMT_Y1 /* BPP=1 */ +#define FB_FMT_RGB4 4 /* BPP=4 */ +#define FB_FMT_RGB8 5 /* BPP=8 RGB palette index */ +#define FB_FMT_RGB8_332 6 /* BPP=8 R=3, G=3, B=2 */ +#define FB_FMT_RGB12_444 7 /* BPP=12 R=4, G=4, B=4 */ +#define FB_FMT_RGB16_555 8 /* BPP=16 R=5, G=5, B=5 (1 unused bit) */ +#define FB_FMT_RGB16_565 9 /* BPP=16 R=6, G=6, B=5 */ +#define FB_FMT_RGB24 10 /* BPP=24 */ +#define FB_FMT_RGB32 11 /* BPP=32 */ + +/* Run length encoded RGB */ + +#define FB_FMT_RGBRLE4 12 /* BPP=4 */ +#define FB_FMT_RGBRLE8 13 /* BPP=8 */ + +/* Raw RGB */ + +#define FB_FMT_RGBRAW 14 /* BPP=? */ + +/* Raw RGB with arbitrary sample packing within a pixel. Packing and precision + * of R, G and B components is determined by bit masks for each. + */ + +#define FB_FMT_RGBBTFLD16 15 /* BPP=16 */ +#define FB_FMT_RGBBTFLD24 16 /* BPP=24 */ +#define FB_FMT_RGBBTFLD32 17 /* BPP=32 */ +#define FB_FMT_RGBA16 18 /* BPP=16 Raw RGB with alpha */ +#define FB_FMT_RGBA32 19 /* BPP=32 Raw RGB with alpha */ + +/* Raw RGB with a transparency field. Layout is as for stanadard RGB at 16 and + * 32 bits per pixel but the msb in each pixel indicates whether the pixel is + * transparent or not. + */ + +#define FB_FMT_RGBT16 20 /* BPP=16 */ +#define FB_FMT_RGBT32 21 /* BPP=32 */ + +#define FB_ISRGB(f) ((f) >= FB_FMT_RGB1) && (f) <= FB_FMT_RGBT32) + +/* Packed YUV Formats *******************************************************/ + +#define FB_FMT_AYUV 22 /* BPP=32 Combined YUV and alpha */ +#define FB_FMT_CLJR 23 /* BPP=8 4 pixels packed into a uint32_t. + * YUV 4:1:1 with l< 8 bits per YUV sample */ +#define FB_FMT_CYUV 24 /* BPP=16 UYVY except that height is reversed */ +#define FB_FMT_IRAW 25 /* BPP=? Intel uncompressed YUV */ +#define FB_FMT_IUYV 26 /* BPP=16 Interlaced UYVY (line order + * 0,2,4,.., 1,3,5...) */ +#define FB_FMT_IY41 27 /* BPP=12 Interlaced Y41P (line order + * 0,2,4,.., 1,3,5...) */ +#define FB_FMT_IYU2 28 /* BPP=24 */ +#define FB_FMT_HDYC 29 /* BPP=16 UYVY except uses the BT709 color space */ +#define FB_FMT_UYVP 30 /* BPP=24? YCbCr 4:2:2, 10-bits per component in U0Y0V0Y1 order */ +#define FB_FMT_UYVY 31 /* BPP=16 YUV 4:2:2 */ +#define FB_FMT_UYNV FB_FMT_UYVY /* BPP=16 */ +#define FB_FMT_Y422 FB_FMT_UYVY /* BPP=16 */ +#define FB_FMT_V210 32 /* BPP=32 10-bit 4:2:2 YCrCb */ +#define FB_FMT_V422 33 /* BPP=16 Upside down version of UYVY */ +#define FB_FMT_V655 34 /* BPP=16? 16-bit YUV 4:2:2 */ +#define FB_FMT_VYUY 35 /* BPP=? ATI Packed YUV Data */ +#define FB_FMT_YUYV 36 /* BPP=16 YUV 4:2:2 */ +#define FB_FMT_YUY2 FB_FMT_YUYV /* BPP=16 YUV 4:2:2 */ +#define FB_FMT_YUNV FB_FMT_YUYV /* BPP=16 YUV 4:2:2 */ +#define FB_FMT_YVYU 37 /* BPP=16 YUV 4:2:2 */ +#define FB_FMT_Y41P 38 /* BPP=12 YUV 4:1:1 */ +#define FB_FMT_Y411 39 /* BPP=12 YUV 4:1:1 */ +#define FB_FMT_Y211 40 /* BPP=8 */ +#define FB_FMT_Y41T 41 /* BPP=12 Y41P LSB for transparency */ +#define FB_FMT_Y42T 42 /* BPP=16 UYVY LSB for transparency */ +#define FB_FMT_YUVP 43 /* BPP=24? YCbCr 4:2:2 Y0U0Y1V0 order */ + +#define FB_ISYUVPACKED(f) ((f) >= FB_FMT_AYUV) && (f) <= FB_FMT_YUVP) + +/* Packed Planar YUV Formats ************************************************/ + +#define FB_FMT_YVU9 44 /* BPP=9 8-bit Y followed by 8-bit 4x4 VU */ +#define FB_FMT_YUV9 45 /* BPP=9? */ +#define FB_FMT_IF09 46 /* BPP=9.5 YVU9 + 4x4 plane of delta relative to tframe. */ +#define FB_FMT_YV16 47 /* BPP=16 8-bit Y followed by 8-bit 2x1 VU */ +#define FB_FMT_YV12 48 /* BPP=12 8-bit Y followed by 8-bit 2x2 VU */ +#define FB_FMT_I420 49 /* BPP=12 8-bit Y followed by 8-bit 2x2 UV */ +#define FB_FMT_IYUV FB_FMT_I420 /* BPP=12 */ +#define FB_FMT_NV12 50 /* BPP=12 8-bit Y followed by an interleaved 2x2 UV */ +#define FB_FMT_NV21 51 /* BPP=12 NV12 with UV reversed */ +#define FB_FMT_IMC1 52 /* BPP=12 YV12 except UV planes ame stride as Y */ +#define FB_FMT_IMC2 53 /* BPP=12 IMC1 except UV lines interleaved at half stride boundaries */ +#define FB_FMT_IMC3 54 /* BPP=12 As IMC1 except that UV swapped */ +#define FB_FMT_IMC4 55 /* BPP=12 As IMC2 except that UV swapped */ +#define FB_FMT_CLPL 56 /* BPP=12 YV12 but including a level of indirection. */ +#define FB_FMT_Y41B 57 /* BPP=12? 4:1:1 planar. */ +#define FB_FMT_Y42B 58 /* BPP=16? YUV 4:2:2 planar. */ +#define FB_FMT_CXY1 59 /* BPP=12 */ +#define FB_FMT_CXY2 60 /* BPP=16 */ + +#define FB_ISYUVPLANAR(f) ((f) >= FB_FMT_AYUV) && (f) <= FB_FMT_YUVP) +#define FB_ISYUV(f) (FB_ISYUVPACKED(f) || FB_ISYUVPLANAR(f)) + +/* Hardware cursor control **************************************************/ + +#ifdef CONFIG_FB_HWCURSOR +#define FB_CUR_ENABLE 0x01 /* Enable the cursor */ +#define FB_CUR_SETIMAGE 0x02 /* Set the cursor image */ +#define FB_CUR_SETPOSITION 0x04 /* Set the position of the cursor */ +#define FB_CUR_SETSIZE 0x08 /* Set the size of the cursor */ +#define FB_CUR_XOR 0x10 /* Use XOR vs COPY ROP on image */ +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* If any dimension of the display exceeds 65,536 pixels, then the following + * type will need to change: + */ + +typedef uint16_t fb_coord_t; + +/* This structure describes the overall video controller */ + +struct fb_videoinfo_s +{ + uint8_t fmt; /* see FB_FMT_* */ + fb_coord_t xres; /* Horizontal resolution in pixel columns */ + fb_coord_t yres; /* Vertical resolution in pixel rows */ + uint8_t nplanes; /* Number of color planes supported */ +}; + +/* This structure describes one color plane. Some YUV formats may support + * up to 4 planes + */ + +struct fb_planeinfo_s +{ + FAR void *fbmem; /* Start of frame buffer memory */ + uint32_t fblen; /* Length of frame buffer memory in bytes */ + fb_coord_t stride; /* Length of a line in bytes */ + uint8_t bpp; /* Bits per pixel */ +}; + +/* On video controllers that support mapping of a pixel palette value + * to an RGB encoding, the following structure may be used to define + * that mapping. + */ + +#ifdef CONFIG_FB_CMAP +struct fb_cmap_s +{ + uint16_t first; /* Offset offset first color entry in tables */ + uint16_t len; /* Number of color entries in tables */ + + /* Tables of color component. Any may be NULL if not used */ + + uint8_t *red; /* Table of 8-bit red values */ + uint8_t *green; /* Table of 8-bit green values */ + uint8_t *blue; /* Table of 8-bit blue values */ +#ifdef CONFIG_FB_TRANSPARENCY + uint8_t *transp; /* Table of 8-bit transparency */ +#endif +}; +#endif + +/* If the video controller hardware supports a hardware cursor and + * that hardware cursor supports user-provided images, then the + * following structure may be used to provide the cursor image + */ + +#ifdef CONFIG_FB_HWCURSOR +#ifdef CONFIG_FB_HWCURSORIMAGE +struct fb_cursorimage_s +{ + fb_coord_t width; /* Width of the cursor image in pixels */ + fb_coord_t height /* Height of the curor image in pixels */ + const uint8_t *image; /* Pointer to image data */ +}; +#endif + +/* The following structure defines the cursor position/size */ + +struct fb_cursorpos_s +{ + fb_coord_t x; /* X position in pixels */ + fb_coord_t y; /* Y position in rows */ +}; + +/* If the hardware supports setting the cursor size, then this structure + * is used to provide the size. + */ + +#ifdef CONFIG_FB_HWCURSORSIZE +struct fb_cursorsize_s +{ + fb_coord_t h; /* Height in rows */ + fb_coord_t w; /* Width in pixels */ +}; +#endif + +/* The following is used to get the cursor attributes */ + +struct fb_cursorattrib_s +{ +#ifdef CONFIG_FB_HWCURSORIMAGE + uint8_t fmt; /* Video format of cursor */ +#endif + struct fb_cursorpos_s pos; /* Current cursor position */ +#ifdef CONFIG_FB_HWCURSORSIZE + struct fb_cursorsize_s mxsize; /* Maximum cursor size */ + struct fb_cursorsize_s size; /* Current size */ +#endif +}; + +struct fb_setcursor_s +{ + uint8_t flags; /* See FB_CUR_* definitions */ + struct fb_cursorpos_s pos; /* Cursor position */ +#ifdef CONFIG_FB_HWCURSORSIZE + struct fb_cursorsize_s size; /* Cursor size */ +#endif +#ifdef CONFIG_FB_HWCURSORIMAGE + struct fb_cursorimage_s img; /* Cursor image */ +#endif +}; +#endif + +/* The framebuffer "driver" under NuttX is not a driver at all, but simply + * a driver "object" that is accessed through the following vtable: + */ + +struct fb_vtable_s +{ + /* Get information about the video controller configuration and the configuration + * of each color plane. + */ + + int (*getvideoinfo)(FAR struct fb_vtable_s *vtable, FAR struct fb_videoinfo_s *vinfo); + int (*getplaneinfo)(FAR struct fb_vtable_s *vtable, int planeno, FAR struct fb_planeinfo_s *pinfo); + + /* The following are provided only if the video hardware supports RGB color mapping */ + +#ifdef CONFIG_FB_CMAP + int (*getcmap)(FAR struct fb_vtable_s *vtable, FAR struct fb_cmap_s *cmap); + int (*putcmap)(FAR struct fb_vtable_s *vtable, FAR const struct fb_cmap_s *cmap); +#endif + /* The following are provided only if the video hardware supports a hardware cursor */ + +#ifdef CONFIG_FB_HWCURSOR + int (*getcursor)(FAR struct fb_vtable_s *vtable, FAR struct fb_cursorattrib_s *attrib); + int (*setcursor)(FAR struct fb_vtable_s *vtable, FAR struct fb_setcursor_s *settings); +#endif +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: up_fbinitialize, up_fbuninitialize, up_fbgetvplane + * + * Description: + * If an architecture supports a framebuffer, then it must provide APIs + * to access the framebuffer as follows: + * + * up_fbinitialize - Initialize the framebuffer video hardware + * up_fbgetvplane - Return a a reference to the framebuffer object for + * the specified video plane. Most OSDs support + * multiple planes of video. + * up_fbuninitialize - Unitialize the framebuffer support + * + ***************************************************************************/ + +EXTERN int up_fbinitialize(void); +EXTERN FAR struct fb_vtable_s *up_fbgetvplane(int vplane); +EXTERN void fb_uninitialize(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* _INCLUDE_NUTTX_FB_H */ diff --git a/nuttx/include/nuttx/fs/dirent.h b/nuttx/include/nuttx/fs/dirent.h new file mode 100644 index 0000000000..8aad4242b8 --- /dev/null +++ b/nuttx/include/nuttx/fs/dirent.h @@ -0,0 +1,221 @@ +/**************************************************************************** + * include/nuttx/fs/dirent.h + * + * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_FS_DIRENT_H +#define __INCLUDE_NUTTX_FS_DIRENT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_NFS +# define DIRENT_NFS_MAXHANDLE 64 /* Maximum length of an NFSv3 file handle */ +# define DIRENT_NFS_VERFLEN 8 /* Length of the copy verifier */ +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The internal representation of type DIR is just a container for an inode + * reference, a position, a dirent structure, and file-system-specific + * information. + * + * For the root psuedo-file system, we need retain only the 'next' inode + * need for the next readdir() operation. We hold a reference on this + * inode so we know that it will persist until closedir is called. + */ + +struct fs_psuedodir_s +{ + struct inode *fd_next; /* The inode for the next call to readdir() */ +}; + +#ifndef CONFIG_DISABLE_MOUNTPOINT +#ifdef CONFIG_FS_FAT +/* For fat, we need to return the start cluster, current cluster, current + * sector and current directory index. + */ + +struct fs_fatdir_s +{ + off_t fd_startcluster; /* Start cluster number of the directory */ + off_t fd_currcluster; /* Current cluster number being read */ + off_t fd_currsector; /* Current sector being read */ + unsigned int fd_index; /* Current index of the directory entry to read */ +}; +#endif /* CONFIG_FS_FAT */ + +#ifdef CONFIG_FS_ROMFS +/* For ROMFS, we need to return the offset to the current and start positions + * of the directory entry being read + */ + +struct fs_romfsdir_s +{ + off_t fr_firstoffset; /* Offset to the first entry in the directory */ + off_t fr_curroffset; /* Current offset into the directory contents */ +}; +#endif /* CONFIG_FS_ROMFS */ + +#ifdef CONFIG_APPS_BINDIR +/* The apps/ pseudo bin/ directory. The state value is simply an index */ + +struct fs_binfsdir_s +{ + unsigned int fb_index; /* Index to the next named entry point */ +}; +#endif + +#ifdef CONFIG_FS_NXFFS +/* NXFFS is the tiny NuttX wear-leveling FLASH file system. The state value is + * the offset in FLASH memory to the next inode entry. + */ + +struct fs_nxffsdir_s +{ + off_t nx_offset; /* Offset to the next inode */ +}; +#endif + +#ifdef CONFIG_NFS +/* The NFS client file system */ + +struct nfsdir_s +{ + uint8_t nfs_fhsize; /* Length of the file handle */ + uint8_t nfs_fhandle[DIRENT_NFS_MAXHANDLE]; /* File handle (max size allocated) */ + uint8_t nfs_verifier[DIRENT_NFS_VERFLEN]; /* Cookie verifier */ + uint32_t nfs_cookie[2]; /* Cookie */ +}; +#endif + +#endif /* CONFIG_DISABLE_MOUNTPOINT */ + +struct fs_dirent_s +{ + /* This is the node that was opened by opendir. The type of the inode + * determines the way that the readdir() operations are performed. For the + * psuedo root psuedo-file system, it is also used to support rewind. + * + * We hold a reference on this inode so we know that it will persist until + * closedir() is called (although inodes linked to this inode may change). + */ + + struct inode *fd_root; + + /* At present, only mountpoints require special handling flags */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + unsigned int fd_flags; +#endif + + /* This keeps track of the current directory position for telldir */ + + off_t fd_position; + + /* Retained control information depends on the type of file system that + * provides is provides the mountpoint. Ideally this information should + * be hidden behind an opaque, file-system-dependent void *, but we put + * the private definitions in line here for now to reduce allocations. + */ + + union + { + /* Private data used by the built-in psuedo-file system */ + + struct fs_psuedodir_s psuedo; + + /* Private data used by other file systems */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT +#ifdef CONFIG_FS_FAT + struct fs_fatdir_s fat; +#endif +#ifdef CONFIG_FS_ROMFS + struct fs_romfsdir_s romfs; +#endif +#ifdef CONFIG_APPS_BINDIR + struct fs_binfsdir_s binfs; +#endif +#ifdef CONFIG_FS_NXFFS + struct fs_nxffsdir_s nxffs; +#endif +#ifdef CONFIG_NFS + struct nfsdir_s nfs; +#endif +#endif /* !CONFIG_DISABLE_MOUNTPOINT */ + } u; + + /* In any event, this the actual struct dirent that is returned by readdir */ + + struct dirent fd_dir; /* Populated when readdir is called */ +}; + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_FS_DIRENT_H */ + diff --git a/nuttx/include/nuttx/fs/fat.h b/nuttx/include/nuttx/fs/fat.h new file mode 100644 index 0000000000..f69bd85713 --- /dev/null +++ b/nuttx/include/nuttx/fs/fat.h @@ -0,0 +1,88 @@ +/**************************************************************************** + * include/nuttx/fs/fat.h + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_FS_FAT_H +#define __INCLUDE_NUTTX_FS_FAT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* File attribute bits in FAT directory entry */ + +#define FATATTR_READONLY 0x01 +#define FATATTR_HIDDEN 0x02 +#define FATATTR_SYSTEM 0x04 +#define FATATTR_VOLUMEID 0x08 +#define FATATTR_DIRECTORY 0x10 +#define FATATTR_ARCHIVE 0x20 + +#define FATATTR_LONGNAME \ + (FATATTR_READONLY|FATATTR_HIDDEN|FATATTR_SYSTEM|FATATTR_VOLUMEID) + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +typedef uint8_t fat_attrib_t; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Non-standard functions to get and set FAT file/directory attributes */ + +EXTERN int fat_getattrib(const char *path, fat_attrib_t *attrib); +EXTERN int fat_setattrib(const char *path, fat_attrib_t setbits, fat_attrib_t clearbits); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_FS_FAT_H */ diff --git a/nuttx/include/nuttx/fs/fs.h b/nuttx/include/nuttx/fs/fs.h new file mode 100644 index 0000000000..07d28597e8 --- /dev/null +++ b/nuttx/include/nuttx/fs/fs.h @@ -0,0 +1,753 @@ +/**************************************************************************** + * include/nuttx/fs/fs.h + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_FS_FS_H +#define __INCLUDE_NUTTX_FS_FS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/* This structure is provided by devices when they are registered with the + * system. It is used to call back to perform device specific operations. + */ + +struct file; +struct pollfd; + +struct file_operations +{ + /* The device driver open method differs from the mountpoint open method */ + + int (*open)(FAR struct file *filp); + + /* The following methods must be identical in signature and position because + * the struct file_operations and struct mountp_operations are treated like + * unions. + */ + + int (*close)(FAR struct file *filp); + ssize_t (*read)(FAR struct file *filp, FAR char *buffer, size_t buflen); + ssize_t (*write)(FAR struct file *filp, FAR const char *buffer, size_t buflen); + off_t (*seek)(FAR struct file *filp, off_t offset, int whence); + int (*ioctl)(FAR struct file *filp, int cmd, unsigned long arg); +#ifndef CONFIG_DISABLE_POLL + int (*poll)(FAR struct file *filp, struct pollfd *fds, bool setup); +#endif + + /* The two structures need not be common after this point */ +}; + +/* This structure provides information about the state of a block driver */ + +#ifndef CONFIG_DISABLE_MOUNTPOUNT +struct geometry +{ + bool geo_available; /* true: The device is vailable */ + bool geo_mediachanged; /* true: The media has changed since last query */ + bool geo_writeenabled; /* true: It is okay to write to this device */ + size_t geo_nsectors; /* Number of sectors on the device */ + size_t geo_sectorsize; /* Size of one sector */ +}; + +/* This structure is provided by block devices when they register with the + * system. It is used by file systems to perform filesystem transfers. It + * differs from the normal driver vtable in several ways -- most notably in + * that it deals in struct inode vs. struct filep. + */ + +struct inode; +struct block_operations +{ + int (*open)(FAR struct inode *inode); + int (*close)(FAR struct inode *inode); + ssize_t (*read)(FAR struct inode *inode, FAR unsigned char *buffer, + size_t start_sector, unsigned int nsectors); + ssize_t (*write)(FAR struct inode *inode, FAR const unsigned char *buffer, + size_t start_sector, unsigned int nsectors); + int (*geometry)(FAR struct inode *inode, FAR struct geometry *geometry); + int (*ioctl)(FAR struct inode *inode, int cmd, unsigned long arg); +}; + +/* This structure is provided by a filesystem to describe a mount point. + * Note that this structure differs from file_operations ONLY in the form of + * the open method. Once the file is opened, it can be accessed either as a + * struct file_operations or struct mountpt_operations + */ + +struct inode; +struct fs_dirent_s; +struct stat; +struct statfs; +struct mountpt_operations +{ + /* The mountpoint open method differs from the driver open method + * because it receives (1) the inode that contains the mountpoint + * private data, (2) the relative path into the mountpoint, and (3) + * information to manage privileges. + */ + + int (*open)(FAR struct file *filp, FAR const char *relpath, + int oflags, mode_t mode); + + /* The following methods must be identical in signature and position because + * the struct file_operations and struct mountp_operations are treated like + * unions. + */ + + int (*close)(FAR struct file *filp); + ssize_t (*read)(FAR struct file *filp, FAR char *buffer, size_t buflen); + ssize_t (*write)(FAR struct file *filp, FAR const char *buffer, size_t buflen); + off_t (*seek)(FAR struct file *filp, off_t offset, int whence); + int (*ioctl)(FAR struct file *filp, int cmd, unsigned long arg); + + /* The two structures need not be common after this point. The following + * are extended methods needed to deal with the unique needs of mounted + * file systems. + * + * Additional open-file-specific mountpoint operations: + */ + + int (*sync)(FAR struct file *filp); + + /* Directory operations */ + + int (*opendir)(FAR struct inode *mountpt, FAR const char *relpath, FAR struct fs_dirent_s *dir); + int (*closedir)(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); + int (*readdir)(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); + int (*rewinddir)(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); + + /* General volume-related mountpoint operations: */ + + int (*bind)(FAR struct inode *blkdriver, FAR const void *data, FAR void **handle); + int (*unbind)(FAR void *handle, FAR struct inode **blkdriver); + + int (*statfs)(FAR struct inode *mountpt, FAR struct statfs *buf); + + /* Operations on pathes */ + + int (*unlink)(FAR struct inode *mountpt, FAR const char *relpath); + int (*mkdir)(FAR struct inode *mountpt, FAR const char *relpath, mode_t mode); + int (*rmdir)(FAR struct inode *mountpt, FAR const char *relpath); + int (*rename)(FAR struct inode *mountpt, FAR const char *oldrelpath, FAR const char *newrelpath); + int (*stat)(FAR struct inode *mountpt, FAR const char *relpath, FAR struct stat *buf); + + /* NOTE: More operations will be needed here to support: disk usage stats + * file stat(), file attributes, file truncation, etc. + */ +}; +#endif /* CONFIG_DISABLE_MOUNTPOUNT */ + +/* These are the various kinds of operations that can be associated with + * an inode. + */ + +union inode_ops_u +{ + FAR const struct file_operations *i_ops; /* Driver operations for inode */ +#ifndef CONFIG_DISABLE_MOUNTPOUNT + FAR const struct block_operations *i_bops; /* Block driver operations */ + FAR const struct mountpt_operations *i_mops; /* Operations on a mountpoint */ +#endif +}; + +/* This structure represents one inode in the Nuttx psuedo-file system */ + +struct inode +{ + FAR struct inode *i_peer; /* Pointer to same level inode */ + FAR struct inode *i_child; /* Pointer to lower level inode */ + int16_t i_crefs; /* References to inode */ + uint16_t i_flags; /* Flags for inode */ + union inode_ops_u u; /* Inode operations */ +#ifdef CONFIG_FILE_MODE + mode_t i_mode; /* Access mode flags */ +#endif + FAR void *i_private; /* Per inode driver private data */ + char i_name[1]; /* Name of inode (variable) */ +}; +#define FSNODE_SIZE(n) (sizeof(struct inode) + (n)) + +/* This is the underlying representation of an open file. A file + * descriptor is an index into an array of such types. The type associates + * the file descriptor to the file state and to a set of inode operations. + */ + +struct file +{ + int f_oflags; /* Open mode flags */ + off_t f_pos; /* File position */ + FAR struct inode *f_inode; /* Driver interface */ + void *f_priv; /* Per file driver private data */ +}; + +/* This defines a list of files indexed by the file descriptor */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +struct filelist +{ + sem_t fl_sem; /* Manage access to the file list */ + int16_t fl_crefs; /* Reference count */ + struct file fl_files[CONFIG_NFILE_DESCRIPTORS]; +}; +#endif + +/* The following structure defines the list of files used for standard C I/O. + * Note that NuttX can support the standard C APIs without or without buffering + * + * When buffering us used, the following described the usage of the I/O buffer. + * The buffer can be used for reading or writing -- but not both at the same time. + * An fflush is implied between each change in directionof access. + * + * The field fs_bufread determines whether the buffer is being used for reading or + * for writing as fillows: + * + * BUFFER + * +----------------------+ <- fs_bufstart Points to the beginning of the buffer. + * | WR: Buffered data | WR: Start of buffered write data. + * | RD: Already read | RD: Start of already read data. + * +----------------------+ + * | WR: Available buffer | <- fs_bufpos Points to next byte: + * | RD: Read-ahead data | WR: End+1 of buffered write data. + * | | RD: Points to next char to return + * +----------------------+ + * | WR: Available | <- fs_bufread Top+1 of buffered read data + * | RD: Available | WR: =bufstart buffer used for writing. + * | | RD: Pointer to last buffered read char+1 + * +----------------------+ + * <- fs_bufend Points to end end of the buffer+1 + */ + +#if CONFIG_NFILE_STREAMS > 0 +struct file_struct +{ + int fs_filedes; /* File descriptor associated with stream */ + uint16_t fs_oflags; /* Open mode flags */ +#if CONFIG_NUNGET_CHARS > 0 + uint8_t fs_nungotten; /* The number of characters buffered for ungetc */ + unsigned char fs_ungotten[CONFIG_NUNGET_CHARS]; +#endif +#if CONFIG_STDIO_BUFFER_SIZE > 0 + sem_t fs_sem; /* For thread safety */ + pid_t fs_holder; /* Holder of sem */ + int fs_counts; /* Number of times sem is held */ + FAR unsigned char *fs_bufstart; /* Pointer to start of buffer */ + FAR unsigned char *fs_bufend; /* Pointer to 1 past end of buffer */ + FAR unsigned char *fs_bufpos; /* Current position in buffer */ + FAR unsigned char *fs_bufread; /* Pointer to 1 past last buffered read char. */ +#endif +}; + +struct streamlist +{ + int sl_crefs; /* Reference count */ + sem_t sl_sem; /* For thread safety */ + struct file_struct sl_streams[CONFIG_NFILE_STREAMS]; +}; +#endif /* CONFIG_NFILE_STREAMS */ + +/* Callback used by foreach_mountpoints to traverse all mountpoints in the + * pseudo-file system. + */ + +#ifndef CONFIG_DISABLE_MOUNTPOUNT +struct statfs; /* Forward reference */ +typedef int (*foreach_mountpoint_t)(FAR const char *mountpoint, + FAR struct statfs *statbuf, + FAR void *arg); +#endif + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* fs_inode.c ***************************************************************/ +/**************************************************************************** + * Name: fs_initialize + * + * Description: + * This is called from the OS initialization logic to configure the file + * system. + * + ****************************************************************************/ + +EXTERN void weak_function fs_initialize(void); + +/* fs_foreachmountpoint.c ***************************************************/ +/**************************************************************************** + * Name: foreach_mountpoint + * + * Description: + * Visit each mountpoint in the pseudo-file system. The traversal is + * terminated when the callback 'handler' returns a non-zero value, or when + * all of the mountpoints have been visited. + * + * This is just a front end "filter" to foreach_inode() that forwards only + * mountpoint inodes. It is intended to support the mount() command to + * when the mount command is used to enumerate mounts. + * + * NOTE 1: Use with caution... The psuedo-file system is locked throughout + * the traversal. + * NOTE 2: The search algorithm is recursive and could, in principle, use + * an indeterminant amount of stack space. This will not usually be a + * real work issue. + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_MOUNTPOUNT +EXTERN int foreach_mountpoint(foreach_mountpoint_t handler, FAR void *arg); +#endif + +/* fs_registerdriver.c ******************************************************/ +/**************************************************************************** + * Name: register_driver + * + * Description: + * Register a character driver inode the pseudo file system. + * + * Input parameters: + * path - The path to the inode to create + * fops - The file operations structure + * mode - inmode priviledges (not used) + * priv - Private, user data that will be associated with the inode. + * + * Returned Value: + * Zero on success (with the inode point in 'inode'); A negated errno + * value is returned on a failure (all error values returned by + * inode_reserve): + * + * EINVAL - 'path' is invalid for this operation + * EEXIST - An inode already exists at 'path' + * ENOMEM - Failed to allocate in-memory resources for the operation + * + ****************************************************************************/ + +EXTERN int register_driver(const char *path, + const struct file_operations *fops, + mode_t mode, void *priv); + +/* fs_registerblockdriver.c *************************************************/ +/**************************************************************************** + * Name: register_blockdriver + * + * Description: + * Register a block driver inode the pseudo file system. + * + * Input parameters: + * path - The path to the inode to create + * bops - The block driver operations structure + * mode - inmode priviledges (not used) + * priv - Private, user data that will be associated with the inode. + * + * Returned Value: + * Zero on success (with the inode point in 'inode'); A negated errno + * value is returned on a failure (all error values returned by + * inode_reserve): + * + * EINVAL - 'path' is invalid for this operation + * EEXIST - An inode already exists at 'path' + * ENOMEM - Failed to allocate in-memory resources for the operation + * + ****************************************************************************/ + +EXTERN int register_blockdriver(const char *path, + const struct block_operations *bops, + mode_t mode, void *priv); + +/* fs_unregisterdriver.c ****************************************************/ +/**************************************************************************** + * Name: unregister_driver + * + * Description: + * Remove the character driver inode at 'path' from the psuedo-file system + * + ****************************************************************************/ + +EXTERN int unregister_driver(const char *path); + +/* fs_unregisterblockdriver.c ***********************************************/ +/**************************************************************************** + * Name: unregister_blockdriver + * + * Description: + * Remove the block driver inode at 'path' from the psuedo-file system + * + ****************************************************************************/ + +EXTERN int unregister_blockdriver(const char *path); + +/* fs_open.c ****************************************************************/ +/**************************************************************************** + * Name: inode_checkflags + * + * Description: + * Check if the access described by 'oflags' is supported on 'inode' + * + ****************************************************************************/ + +EXTERN int inode_checkflags(FAR struct inode *inode, int oflags); + +/* fs_files.c ***************************************************************/ +/**************************************************************************** + * Name: files_alloclist + * + * Description: Allocate a list of files for a new task + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +EXTERN FAR struct filelist *files_alloclist(void); +#endif + +/**************************************************************************** + * Name: files_addreflist + * + * Description: + * Increase the reference count on a file list + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +EXTERN int files_addreflist(FAR struct filelist *list); +#endif + +/**************************************************************************** + * Name: files_releaselist + * + * Description: + * Release a reference to the file list + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +EXTERN int files_releaselist(FAR struct filelist *list); +#endif + +/**************************************************************************** + * Name: files_dup + * + * Description: + * Assign an inode to a specific files structure. This is the heart of + * dup2. + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +EXTERN int files_dup(FAR struct file *filep1, FAR struct file *filep2); +#endif + +/* fs_filedup.c *************************************************************/ +/**************************************************************************** + * Name: file_dup OR dup + * + * Description: + * Clone a file descriptor 'fd' to an arbitray descriptor number (any value + * greater than or equal to 'minfd'). If socket descriptors are + * implemented, then this is called by dup() for the case of file + * descriptors. If socket descriptors are not implemented, then this + * function IS dup(). + * + * This alternative naming is used when dup could operate on both file and + * socket descritors to avoid drawing unused socket support into the link. + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +EXTERN int file_dup(int fd, int minfd); +#endif + +/* fs_filedup2.c ************************************************************/ +/**************************************************************************** + * Name: file_dup2 OR dup2 + * + * Description: + * Clone a file descriptor to a specific descriptor number. If socket + * descriptors are implemented, then this is called by dup2() for the + * case of file descriptors. If socket descriptors are not implemented, + * then this function IS dup2(). + * + * This alternative naming is used when dup2 could operate on both file and + * socket descritors to avoid drawing unused socket support into the link. + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 +EXTERN int file_dup2(int fd1, int fd2); +#else +# define file_dup2(fd1, fd2) dup2(fd1, fd2) +#endif +#endif + +/* fs_openblockdriver.c *****************************************************/ +/**************************************************************************** + * Name: open_blockdriver + * + * Description: + * Return the inode of the block driver specified by 'pathname' + * + * Inputs: + * pathname - the full path to the block driver to be opened + * mountflags - if MS_RDONLY is not set, then driver must support write + * operations (see include/sys/mount.h) + * ppinode - address of the location to return the inode reference + * + * Return: + * Returns zero on success or a negated errno on failure: + * + * EINVAL - pathname or pinode is NULL + * ENOENT - No block driver of this name is registered + * ENOTBLK - The inode associated with the pathname is not a block driver + * EACCESS - The MS_RDONLY option was not set but this driver does not + * support write access + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +EXTERN int open_blockdriver(FAR const char *pathname, int mountflags, + FAR struct inode **ppinode); +#endif + +/* fs_closeblockdriver.c ****************************************************/ +/**************************************************************************** + * Name: close_blockdriver + * + * Description: + * Call the close method and release the inode + * + * Inputs: + * inode - reference to the inode of a block driver opened by open_blockdriver + * + * Return: + * Returns zero on success or a negated errno on failure: + * + * EINVAL - inode is NULL + * ENOTBLK - The inode is not a block driver + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +EXTERN int close_blockdriver(FAR struct inode *inode); +#endif + +/* fs_fdopen.c **************************************************************/ +/**************************************************************************** + * Name: fs_fdopen + * + * Description: + * This function does the core operations for fopen and fdopen. It is + * used by the OS to clone stdin, stdout, stderr + * + ****************************************************************************/ + +#if CONFIG_NFILE_STREAMS > 0 + +#ifndef __TCB_DEFINED__ +typedef struct _TCB _TCB; +#define __TCB_DEFINED__ +#endif + +EXTERN FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR _TCB *tcb); +#endif + +/* lib/stdio/lib_fflush.c **************************************************/ +/**************************************************************************** + * Name: lib_flushall + * + * Description: + * Called either (1) by the OS when a task exits, or (2) from fflush() + * when a NULL stream argument is provided. + * + ****************************************************************************/ + +#if CONFIG_NFILE_STREAMS > 0 +EXTERN int lib_flushall(FAR struct streamlist *list); +#endif + +/* drivers/dev_null.c *******************************************************/ +/**************************************************************************** + * Name: devnull_register + * + * Description: + * Register /dev/null + * + ****************************************************************************/ + +EXTERN void devnull_register(void); + +/* drivers/dev_zero.c *******************************************************/ +/**************************************************************************** + * Name: devzero_register + * + * Description: + * Register /dev/zero + * + ****************************************************************************/ + +EXTERN void devzero_register(void); + +/* drivers/loop.c ***********************************************************/ +/**************************************************************************** + * Name: losetup + * + * Description: + * Setup the loop device so that it exports the file referenced by 'filename' + * as a block device. + * + ****************************************************************************/ + +EXTERN int losetup(FAR const char *devname, FAR const char *filename, + uint16_t sectsize, off_t offset, bool readonly); + +/**************************************************************************** + * Name: loteardown + * + * Description: + * Undo the setup performed by losetup + * + ****************************************************************************/ + +EXTERN int loteardown(FAR const char *devname); + +/* drivers/bch/bchdev_register.c ********************************************/ +/**************************************************************************** + * Name: bchdev_register + * + * Description: + * Setup so that it exports the block driver referenced by 'blkdev' as a + * character device 'chardev' + * + ****************************************************************************/ + +EXTERN int bchdev_register(FAR const char *blkdev, FAR const char *chardev, + bool readonly); + +/* drivers/bch/bchdev_unregister.c ******************************************/ +/**************************************************************************** + * Name: bchdev_unregister + * + * Description: + * Unregister character driver access to a block device that was created + * by a previous call to bchdev_register(). + * + ****************************************************************************/ + +EXTERN int bchdev_unregister(FAR const char *chardev); + +/* Low level, direct access. NOTE: low-level access and character driver access + * are incompatible. One and only one access method should be implemented. + */ + +/* drivers/bch/bchlib_setup.c ***********************************************/ +/**************************************************************************** + * Name: bchlib_setup + * + * Description: + * Setup so that the block driver referenced by 'blkdev' can be accessed + * similar to a character device. + * + ****************************************************************************/ + +EXTERN int bchlib_setup(FAR const char *blkdev, bool readonly, + FAR void **handle); + +/* drivers/bch/bchlib_teardown.c ********************************************/ +/**************************************************************************** + * Name: bchlib_teardown + * + * Description: + * Setup so that the block driver referenced by 'blkdev' can be accessed + * similar to a character device. + * + ****************************************************************************/ + +EXTERN int bchlib_teardown(FAR void *handle); + +/* drivers/bch/bchlib_read.c ************************************************/ +/**************************************************************************** + * Name: bchlib_read + * + * Description: + * Read from the block device set-up by bchlib_setup as if it were a + * character device. + * + ****************************************************************************/ + +EXTERN ssize_t bchlib_read(FAR void *handle, FAR char *buffer, size_t offset, + size_t len); + +/* drivers/bch/bchlib_write.c ***********************************************/ +/**************************************************************************** + * Name: bchlib_write + * + * Description: + * Write to the block device set-up by bchlib_setup as if it were a + * character device. + * + ****************************************************************************/ + +EXTERN ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, + size_t offset, size_t len); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_FS_FS_H */ diff --git a/nuttx/include/nuttx/fs/ioctl.h b/nuttx/include/nuttx/fs/ioctl.h new file mode 100644 index 0000000000..19f29b1fb6 --- /dev/null +++ b/nuttx/include/nuttx/fs/ioctl.h @@ -0,0 +1,221 @@ +/**************************************************************************** + * include/nuttx/fs/ioctl.h + * + * Copyright (C) 2008, 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_FS_IOCTL_H +#define __INCLUDE_NUTTX_FS_IOCTL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* General ioctl definitions ************************************************/ +/* Each NuttX ioctl commands are uint16_t's consisting of an 8-bit type + * identifier and an 8-bit command number. All comman type identifiers are + * defined below: + */ + +#define _TIOCBASE (0x0100) /* Terminal I/O ioctl commands */ +#define _WDIOCBASE (0x0200) /* Watchdog driver ioctl commands */ +#define _FIOCBASE (0x0300) /* File system ioctl commands */ +#define _DIOCBASE (0x0400) /* Character driver ioctl commands */ +#define _BIOCBASE (0x0500) /* Block driver ioctl commands */ +#define _MTDIOCBASE (0x0600) /* MTD ioctl commands */ +#define _SIOCBASE (0x0700) /* Socket ioctl commands */ +#define _ARPIOCBASE (0x0800) /* ARP ioctl commands */ +#define _TSIOCBASE (0x0900) /* Touchscreen ioctl commands */ +#define _SNIOCBASE (0x0a00) /* Sensor ioctl commands */ +#define _ANIOCBASE (0x0b00) /* Analog (DAC/ADC) ioctl commands */ +#define _PWMIOCBASE (0x0c00) /* PWM ioctl commands */ +#define _CAIOCBASE (0x0d00) /* CDC/ACM ioctl commands */ +#define _BATIOCBASE (0x0e00) /* Battery driver ioctl commands */ +#define _QEIOCBASE (0x0f00) /* Quadrature encoder ioctl commands */ + +/* Macros used to manage ioctl commands */ + +#define _IOC_MASK (0x00ff) +#define _IOC_TYPE(cmd) ((cmd)&~_IOC_MASK) +#define _IOC_NR(cmd) ((cmd)&_IOC_MASK) + +#define _IOC(type,nr) ((type)|(nr)) + +/* Terminal I/O ioctl commands **********************************************/ + +#define _TIOCVALID(c) (_IOC_TYPE(c)==_TIOCBASE) +#define _TIOC(nr) _IOC(_TIOCBASE,nr) + +/* Terminal I/O IOCTL definitions are retained in tioctl.h */ + +#include + +/* Watchdog driver ioctl commands *******************************************/ + +#define _WDIOCVALID(c) (_IOC_TYPE(c)==_WDIOCBASE) +#define _WDIOC(nr) _IOC(_WDIOCBASE,nr) + +/* NuttX file system ioctl definitions **************************************/ + +#define _FIOCVALID(c) (_IOC_TYPE(c)==_FIOCBASE) +#define _FIOC(nr) _IOC(_FIOCBASE,nr) + +#define FIOC_MMAP _FIOC(0x0001) /* IN: Location to return address (void **) + * OUT: If media is directly acccesible, + * return (void*) base address + * of file + */ +#define FIOC_REFORMAT _FIOC(0x0002) /* IN: None + * OUT: None + */ +#define FIOC_OPTIMIZE _FIOC(0x0003) /* IN: None + * OUT: None + */ + +/* NuttX file system ioctl definitions **************************************/ + +#define _DIOCVALID(c) (_IOC_TYPE(c)==_DIOCBASE) +#define _DIOC(nr) _IOC(_DIOCBASE,nr) + +#define DIOC_GETPRIV _DIOC(0x0001) /* IN: Location to return handle (void **) + * OUT: Reference to internal data + * structure. May have a reference + * incremented. + */ +#define DIOC_RELPRIV _DIOC(0x0003) /* IN: None + * OUT: None, reference obtained by + * FIOC_GETPRIV released. + */ + +/* NuttX block driver ioctl definitions *************************************/ + +#define _BIOCVALID(c) (_IOC_TYPE(c)==_BIOCBASE) +#define _BIOC(nr) _IOC(_BIOCBASE,nr) + +#define BIOC_XIPBASE _BIOC(0x0001) /* Perform mapping to random access memory. + * IN: Pointer to pointer to void in + * which to received the XIP base. + * OUT: If media is directly acccesible, + * return (void*) base address + * of device memory */ +#define BIOC_PROBE _BIOC(0x0002) /* Re-probe and interface; check for media + * in the slot + * IN: None + * OUT: None (ioctl return value provides + * success/failure indication). */ +#define BIOC_EJECT _BIOC(0x0003) /* Eject/disable media in the slot + * IN: None + * OUT: None (ioctl return value provides + * success/failure indication). */ + +/* NuttX MTD driver ioctl definitions ***************************************/ + +#define _MTDIOCVALID(c) (_IOC_TYPE(c)==_MTDIOCBASE) +#define _MTDIOC(nr) _IOC(_MTDIOCBASE,nr) + +#define MTDIOC_GEOMETRY _MTDIOC(0x0001) /* IN: Pointer to write-able struct + * mtd_geometry_s in which to receive + * receive geometry data (see mtd.h) + * OUT: Geometry structure is populated + * with data for the MTD */ +#define MTDIOC_XIPBASE _MTDIOC(0x0002) /* IN: Pointer to pointer to void in + * which to received the XIP base. + * OUT: If media is directly acccesible, + * return (void*) base address + * of device memory */ +#define MTDIOC_BULKERASE _MTDIOC(0x0003) /* IN: None + * OUT: None */ + +/* NuttX ARP driver ioctl definitions (see netinet/arp.h) *******************/ + +#define _ARPIOCVALID(c) (_IOC_TYPE(c)==_ARPIOCBASE) +#define _ARPIOC(nr) _IOC(_ARPIOCBASE,nr) + +/* NuttX touchscreen ioctl definitions (see nuttx/input/touchscreen.h) ******/ + +#define _TSIOCVALID(c) (_IOC_TYPE(c)==_TSIOCBASE) +#define _TSIOC(nr) _IOC(_TSIOCBASE,nr) + +/* NuttX sensor ioctl definitions (see nuttx/sensor/xxx.h) ******************/ + +#define _SNIOCVALID(c) (_IOC_TYPE(c)==_SNIOCBASE) +#define _SNIOC(nr) _IOC(_SNIOCBASE,nr) + +/* NuttX PWM ioctl definitions (see nuttx/pwm.h) ***************************/ + +#define _PWMIOCVALID(c) (_IOC_TYPE(c)==_PWMIOCBASE) +#define _PWMIOC(nr) _IOC(_PWMIOCBASE,nr) + +/* NuttX USB CDC/ACM serial driver ioctl definitions ************************/ +/* (see nuttx/usb/cdcacm.h) */ + +#define _CAIOCVALID(c) (_IOC_TYPE(c)==_CAIOCBASE) +#define _CAIOC(nr) _IOC(_CAIOCBASE,nr) + +/* NuttX USB CDC/ACM serial driver ioctl definitions ************************/ +/* (see nuttx/power/battery.h) */ + +#define _BATIOCVALID(c) (_IOC_TYPE(c)==_BATIOCBASE) +#define _BATIOC(nr) _IOC(_BATIOCBASE,nr) + +/* NuttX Quadrature Encoder driver ioctol definitions ***********************/ +/* (see nuttx/power/battery.h) */ + +#define _QEIOCVALID(c) (_IOC_TYPE(c)==_QEIOCBASE) +#define _QEIOC(nr) _IOC(_QEIOCBASE,nr) + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_FS_IOCTL_H */ diff --git a/nuttx/include/nuttx/fs/mkfatfs.h b/nuttx/include/nuttx/fs/mkfatfs.h new file mode 100644 index 0000000000..ccf5b76037 --- /dev/null +++ b/nuttx/include/nuttx/fs/mkfatfs.h @@ -0,0 +1,145 @@ +/**************************************************************************** + * include/nuttx/fs/mkfatfs.h + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_FS_MKFATFS_H +#define __INCLUDE_NUTTX_FS_MKFATFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MKFATFS_DEFAULT_NFATS 2 /* 2: Default number of FATs */ +#define MKFATFS_DEFAULT_FATTYPE 0 /* 0: Autoselect FAT size */ +#define MKFATFS_DEFAULT_CLUSTSHIFT 0xff /* 0xff: Autoselect cluster size */ +#define MKFATFS_DEFAULT_VOLUMELABEL { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } +#define MKFATFS_DEFAULT_BKUPBOOT 0 /* 0: Determine sector number of the backup boot sector */ +#define MKFATFS_DEFAULT_ROOTDIRENTS 0 /* 0: Autoselect number of root directory entries */ +#define MKFATFS_DEFAULT_RSVDSECCOUNT 0 /* 0: Autoselect number reserved sectors (usually 32) */ +#define MKFATFS_DEFAULT_HIDSEC 0 /* No hidden sectors */ +#define MKFATFS_DEFAULT_VOLUMEID 0 /* No volume ID */ +#define MKFATFS_DEFAULT_NSECTORS 0 /* 0: Use all sectors on device */ + +#define FAT_FORMAT_INITIALIZER \ +{ \ + MKFATFS_DEFAULT_NFATS, \ + MKFATFS_DEFAULT_FATTYPE, \ + MKFATFS_DEFAULT_CLUSTSHIFT, \ + MKFATFS_DEFAULT_VOLUMELABEL, \ + MKFATFS_DEFAULT_BKUPBOOT, \ + MKFATFS_DEFAULT_ROOTDIRENTS, \ + MKFATFS_DEFAULT_RSVDSECCOUNT, \ + MKFATFS_DEFAULT_HIDSEC, \ + MKFATFS_DEFAULT_VOLUMEID, \ + MKFATFS_DEFAULT_NSECTORS \ +} + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* These are input parameters for the format. On return, these values may be + * overwritted with actual values used in the format. + */ + +struct fat_format_s +{ + uint8_t ff_nfats; /* Number of FATs */ + uint8_t ff_fattype; /* FAT size: 0 (autoselect), 12, 16, or 32 */ + uint8_t ff_clustshift; /* Log2 of sectors per cluster: 0-5, 0xff (autoselect) */ + uint8_t ff_volumelabel[11]; /* Volume label */ + uint16_t ff_backupboot; /* Sector number of the backup boot sector (0=use default)*/ + uint16_t ff_rootdirentries; /* Number of root directory entries */ + uint16_t ff_rsvdseccount; /* Reserved sectors */ + uint32_t ff_hidsec; /* Count of hidden sectors preceding fat */ + uint32_t ff_volumeid; /* FAT volume id */ + uint32_t ff_nsectors; /* Number of sectors from device to use: 0: Use all */ +}; + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: mkfatfs + * + * Description: + * Make a FAT file system image on the specified block device + * + * Inputs: + * pathname - the full path to a registered block driver + * fmt - Describes characteristics of the desired filesystem + * + * Return: + * Zero (OK) on success; -1 (ERROR) on failure with errno set appropriately: + * + * EINVAL - NULL block driver string, bad number of FATS in 'fmt', bad FAT + * size in 'fmt', bad cluster size in 'fmt' + * ENOENT - 'pathname' does not refer to anything in the filesystem. + * ENOTBLK - 'pathname' does not refer to a block driver + * EACCESS - block driver does not support write or geometry methods + * + * Assumptions: + * - The caller must assure that the block driver is not mounted and not in + * use when this function is called. The result of formatting a mounted + * device is indeterminate (but likely not good). + * + ****************************************************************************/ +EXTERN int mkfatfs(FAR const char *pathname, FAR struct fat_format_s *fmt); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_FS_MKFATFS_H */ diff --git a/nuttx/include/nuttx/fs/nfs.h b/nuttx/include/nuttx/fs/nfs.h new file mode 100644 index 0000000000..31f97bd63d --- /dev/null +++ b/nuttx/include/nuttx/fs/nfs.h @@ -0,0 +1,108 @@ +/**************************************************************************** + * include/nuttx/fs/nfs.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. + * Author: Jose Pablo Rojas Vargas + * + * Some of the content of this file was leveraged from OpenBSD: + * + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_FS_NFS_H +#define __INCLUDE_NUTTX_FS_NFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* NFS mount option flags */ + +#define NFSMNT_SOFT (1 << 0) /* Soft mount (hard is default) */ +#define NFSMNT_WSIZE (1 << 1) /* Set write size */ +#define NFSMNT_RSIZE (1 << 2) /* Set read size */ +#define NFSMNT_TIMEO (1 << 3) /* Set initial timeout */ +#define NFSMNT_RETRANS (1 << 4) /* Set number of request retries */ +#define NFSMNT_READDIRSIZE (1 << 5) /* Set readdir size */ + +/* Default PMAP port number to provide */ + +#define NFS_PMAPPORT 111 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct nfs_args +{ + uint8_t addrlen; /* Length of address */ + uint8_t sotype; /* Socket type */ + uint8_t flags; /* Flags, determines if following are valid: */ + uint8_t timeo; /* Time value in deciseconds (with NFSMNT_TIMEO) */ + uint8_t retrans; /* Times to retry send (with NFSMNT_RETRANS) */ + uint16_t wsize; /* Write size in bytes (with NFSMNT_WSIZE) */ + uint16_t rsize; /* Read size in bytes (with NFSMNT_RSIZE) */ + uint16_t readdirsize; /* readdir size in bytes (with NFSMNT_READDIRSIZE) */ + char *path; /* Server's path of the directory being mount */ + struct sockaddr_storage addr; /* File server address (requires 32-bit alignment) */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* _NFS_NFS_H */ diff --git a/nuttx/include/nuttx/fs/nxffs.h b/nuttx/include/nuttx/fs/nxffs.h new file mode 100644 index 0000000000..79c5b1d945 --- /dev/null +++ b/nuttx/include/nuttx/fs/nxffs.h @@ -0,0 +1,150 @@ +/**************************************************************************** + * include/nuttx/fs/nxffs.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_FS_NXFFS_H +#define __INCLUDE_NUTTX_FS_NXFFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* If the erased state of FLASH memory is anything other than 0xff, then this + * configuration should be provided. + */ + +#ifndef CONFIG_NXFFS_ERASEDSTATE +# define CONFIG_NXFFS_ERASEDSTATE 0xff +#endif + +#if CONFIG_NXFFS_ERASEDSTATE != 0xff && CONFIG_NXFFS_ERASEDSTATE != 0x00 +# error "CONFIG_NXFFS_ERASEDSTATE must be either 0x00 or 0xff" +#endif + +/* Don't bother trying to pack things closer together than this. */ + +#ifndef CONFIG_NXFFS_PACKTHRESHOLD +# define CONFIG_NXFFS_PACKTHRESHOLD 32 +#endif + +/* This is how big an inode name is permitted to be. */ + +#ifndef CONFIG_NXFFS_MAXNAMLEN +# define CONFIG_NXFFS_MAXNAMLEN 255 +#endif + +/* Clean-up can either mean packing files together toward the end of the file + * or, if file are deleted at the end of the file, clean up can simply mean + * erasing the end of FLASH memory so that it can be re-used again. However, + * doing this can also harm the life of the FLASH part because it can mean + * that the tail end of the FLASH is re-used too often. + * + * This threshold determines if/when it is worth erased the tail end of FLASH + * and making it available for re-use (and possible over-wear). + */ + +#ifndef CONFIG_NXFFS_TAILTHRESHOLD +# define CONFIG_NXFFS_TAILTHRESHOLD (8*1024) +#endif + +/* At present, only a single pre-allocated NXFFS volume is supported. This + * is because here can be only a single NXFFS volume mounted at any time. + * This has to do with the fact that we bind to an MTD driver (instead of a + * block driver) and bypass all of the normal mount operations. + */ + +#undef CONFIG_NXFSS_PREALLOCATED +#define CONFIG_NXFSS_PREALLOCATED 1 + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: nxffs_initialize + * + * Description: + * Initialize to provide NXFFS on an MTD interface + * + * Input Parameters: + * mtd - The MTD device that supports the FLASH interface. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +EXTERN int nxffs_initialize(FAR struct mtd_dev_s *mtd); + +/**************************************************************************** + * Name: nxffs_dump + * + * Description: + * Dump a summary of the contents of an NXFFS file system. CONFIG_DEBUG + * and CONFIG_DEBUG_FS must be enabled for this function to do anything. + * + * Input Parameters: + * mtd - The MTD device that provides the interface to NXFFS-formatted + * media. + * verbose - FALSE: only show errors + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +EXTERN int nxffs_dump(FAR struct mtd_dev_s *mtd, bool verbose); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_FS_NXFFS_H */ diff --git a/nuttx/include/nuttx/i2c.h b/nuttx/include/nuttx/i2c.h new file mode 100644 index 0000000000..b2238b1cf0 --- /dev/null +++ b/nuttx/include/nuttx/i2c.h @@ -0,0 +1,332 @@ +/**************************************************************************** + * include/nuttx/i2c.h + * + * Copyright(C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_I2C_H +#define __INCLUDE_NUTTX_I2C_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* I2C address calculation. Convert 7- and 10-bit address to 8-bit and + * 16-bit read/write address + */ + +#define I2C_READBIT 0x01 + +/* Conver 7- to 8-bit address */ + +#define I2C_ADDR8(a) ((a) << 1) +#define I2C_WRITEADDR8(a) I2C_ADDR8(a) +#define I2C_READADDR8(a) (I2C_ADDR8(a) | I2C_READBIT) + +/* Convert 10- to 16-bit address */ + +#define I2C_ADDR10H(a) (0xf0 | (((a) >> 7) & 0x06)) +#define I2C_ADDR10L(a) ((a) & 0xff) + +#define I2C_WRITEADDR10H(a) I2C_ADDR10H(a) +#define I2C_WRITEADDR10L(a) I2C_ADDR10L(a) + +#define I2C_READADDR10H(a) (I2C_ADDR10H(a) | I2C_READBIT) +#define I2C_READADDR10L(a) I2C_ADDR10L(a) + +/* Bit definitions for the flags field in struct i2c_ops_s */ + +#define I2C_M_READ 0x0001 /* read data, from slave to master */ +#define I2C_M_TEN 0x0002 /* ten bit address */ +#define I2C_M_NORESTART 0x0080 /* message should not begin with (re-)start of transfer */ + +/* Access macros */ + +/**************************************************************************** + * Name: I2C_SETFREQUENCY + * + * Description: + * Set the I2C frequency. This frequency will be retained in the struct + * i2c_dev_s instance and will be used with all transfers. Required. + * + * Input Parameters: + * dev - Device-specific state data + * frequency - The I2C frequency requested + * + * Returned Value: + * Returns the actual frequency selected + * + ****************************************************************************/ + +#define I2C_SETFREQUENCY(d,f) ((d)->ops->setfrequency(d,f)) + +/**************************************************************************** + * Name: I2C_SETADDRESS + * + * Description: + * Set the I2C slave address. This frequency will be retained in the struct + * i2c_dev_s instance and will be used with all transfers. Required. + * + * Input Parameters: + * dev - Device-specific state data + * address - The I2C slave address + * nbits - The number of address bits provided (7 or 10) + * + * Returned Value: + * Returns OK on success; a negated errno on failure. + * + ****************************************************************************/ + +#define I2C_SETADDRESS(d,a,n) ((d)->ops->setaddress(d,a,n)) + +/**************************************************************************** + * Name: I2C_SETOWNADDRESS + * + * Description: + * Set our own I2C address. Calling this function enables Slave mode and + * disables Master mode on given instance (note that I2C is a bus, where + * multiple masters and slave may be handled by one device driver). + * + * One may register callback to be notifyed about reception. During the + * slave mode reception, the function READ and WRITE must be used to + * to handle reads and writes from a master. + * + * Input Parameters: + * dev - Device-specific state data + * address - Our own slave address; If it is 0x00, then the device driver + * listens to general call + * nbits - The number of address bits provided (7 or 10) + * + * Returned Value: + * OK on valid address and if the same address has not been assigned + * to other existance sharing the same port. Otherwise ERROR is returned. + * + ****************************************************************************/ + +#define I2C_SETOWNADDRESS(d,a,n) ((d)->ops->setownaddress(d,a,n)) + +/**************************************************************************** + * Name: I2C_WRITE + * + * Description: + * Send a block of data on I2C using the previously selected I2C + * frequency and slave address. Each write operational will be an 'atomic' + * operation in the sense that any other I2C actions will be serialized + * and pend until this write completes. Required. + * + * Input Parameters: + * dev - Device-specific state data + * buffer - A pointer to the read-only buffer of data to be written to device + * buflen - The number of bytes to send from the buffer + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +#define I2C_WRITE(d,b,l) ((d)->ops->write(d,b,l)) + +/**************************************************************************** + * Name: I2C_READ + * + * Description: + * Receive a block of data from I2C using the previously selected I2C + * frequency and slave address. Each read operational will be an 'atomic' + * operation in the sense that any other I2C actions will be serialized + * and pend until this read completes. Required. + * + * Input Parameters: + * dev - Device-specific state data + * buffer - A pointer to a buffer of data to receive the data from the device + * buflen - The requested number of bytes to be read + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +#define I2C_READ(d,b,l) ((d)->ops->read(d,b,l)) + +/**************************************************************************** + * Name: I2C_WRITEREAD + * + * Description: + * Send a block of data on I2C using the previously selected I2C + * frequency and slave address, followed by restarted read access. + * It provides a convenient wrapper to the transfer function. + * + * Input Parameters: + * dev - Device-specific state data + * wbuffer - A pointer to the read-only buffer of data to be written to device + * wbuflen - The number of bytes to send from the buffer + * rbuffer - A pointer to a buffer of data to receive the data from the device + * rbuflen - The requested number of bytes to be read + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +#define I2C_WRITEREAD(d,wb,wl,rb,rl) ((d)->ops->writeread(d,wb,wl,rb,rl)) + +/**************************************************************************** + * Name: I2C_TRANSFER + * + * Description: + * Perform a sequence of I2C transfers, each transfer is started with a + * START and the final transfer is completed with a STOP. Each sequence + * will be an 'atomic' operation in the sense that any other I2C actions + * will be serialized and pend until this read completes. Optional. + * + * Input Parameters: + * dev - Device-specific state data + * msgs - A pointer to a set of message descriptors + * msgcount - The number of transfers to perform + * + * Returned Value: + * The number of transfers completed + * + ****************************************************************************/ + +#define I2C_TRANSFER(d,m,c) ((d)->ops->transfer(d,m,c)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The I2C vtable */ + +struct i2c_dev_s; +struct i2c_msg_s; +struct i2c_ops_s +{ + uint32_t (*setfrequency)(FAR struct i2c_dev_s *dev, uint32_t frequency); + int (*setaddress)(FAR struct i2c_dev_s *dev, int addr, int nbits); + int (*write)(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int buflen); + int (*read)(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen); +#ifdef CONFIG_I2C_WRITEREAD + int (*writeread)(FAR struct i2c_dev_s *inst, const uint8_t *wbuffer, int wbuflen, + uint8_t *rbuffer, int rbuflen); +#endif +#ifdef CONFIG_I2C_TRANSFER + int (*transfer)(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int count); +#endif +#ifdef CONFIG_I2C_SLAVE + int (*setownaddress)(FAR struct i2c_dev_s *dev, int addr, int nbits); + int (*registercallback)(FAR struct i2c_dev_s *dev, int (*callback)(void) ); +#endif +}; + +/* I2C transaction segment beginning with a START. A number of these can + * be transfered together to form an arbitrary sequence of write/read transfer + * to an I2C slave device. + */ + +struct i2c_msg_s +{ + uint16_t addr; /* Slave address */ + uint16_t flags; /* See I2C_M_* definitions */ + uint8_t *buffer; + int length; +}; + +/* I2C private data. This structure only defines the initial fields of the + * structure visible to the I2C client. The specific implementation may + * add additional, device specific fields after the vtable. + */ + +struct i2c_dev_s +{ + const struct i2c_ops_s *ops; /* I2C vtable */ +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: up_i2cinitialize + * + * Description: + * Initialize the selected I2C port. And return a unique instance of struct + * struct i2c_dev_s. This function may be called to obtain multiple + * instances of the interface, each of which may be set up with a + * different frequency and slave address. + * + * Input Parameter: + * Port number (for hardware that has mutiple I2C interfaces) + * + * Returned Value: + * Valid I2C device structre reference on succcess; a NULL on failure + * + ****************************************************************************/ + +EXTERN FAR struct i2c_dev_s *up_i2cinitialize(int port); + +/**************************************************************************** + * Name: up_i2cuninitialize + * + * Description: + * De-initialize the selected I2C port, and power down the device. + * + * Input Parameter: + * Device structure as returned by the up_i2cinitalize() + * + * Returned Value: + * OK on success, ERROR when internal reference count missmatch or dev + * points to invalid hardware device. + * + ****************************************************************************/ + +EXTERN int up_i2cuninitialize(FAR struct i2c_dev_s * dev); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __INCLUDE_NUTTX_I2C_H */ diff --git a/nuttx/include/nuttx/init.h b/nuttx/include/nuttx/init.h new file mode 100644 index 0000000000..ecdad702f5 --- /dev/null +++ b/nuttx/include/nuttx/init.h @@ -0,0 +1,82 @@ +/**************************************************************************** + * include/nuttx/init.h + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_INIT_H +#define __INCLUDE_NUTTX_INIT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Data + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* This entry point must be supplied by the application */ + +EXTERN int user_start(int argc, char *argv[]); + +/* Functions contained in os_task.c *****************************************/ + +EXTERN void os_start(void); /* OS entry point called by boot logic */ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_INIT_H */ diff --git a/nuttx/include/nuttx/input/ads7843e.h b/nuttx/include/nuttx/input/ads7843e.h new file mode 100644 index 0000000000..53aa2f227a --- /dev/null +++ b/nuttx/include/nuttx/input/ads7843e.h @@ -0,0 +1,172 @@ +/**************************************************************************** + * include/nuttx/input/ads7843e.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * Diego Sanchez + * + * References: + * "Touch Screen Controller, ADS7843," Burr-Brown Products from Texas + * Instruments, SBAS090B, September 2000, Revised May 2002" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_INPUT_ADS7843E_H +#define __INCLUDE_NUTTX_INPUT_ADS7843E_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#if defined(CONFIG_INPUT) && defined(CONFIG_INPUT_ADS7843E) + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* SPI Frequency. Default: 100KHz */ + +#ifndef CONFIG_ADS7843E_FREQUENCY +# define CONFIG_ADS7843E_FREQUENCY 100000 +#endif + +/* Maximum number of threads than can be waiting for POLL events */ + +#ifndef CONFIG_ADS7843E_NPOLLWAITERS +# define CONFIG_ADS7843E_NPOLLWAITERS 2 +#endif + +#ifndef CONFIG_ADS7843E_SPIMODE +# define CONFIG_ADS7843E_SPIMODE SPIDEV_MODE0 +#endif + +/* Check for some required settings. This can save the user a lot of time + * in getting the right configuration. + */ + +#ifdef CONFIG_DISABLE_SIGNALS +# error "Signals are required. CONFIG_DISABLE_SIGNALS must not be selected." +#endif + +#ifndef CONFIG_SCHED_WORKQUEUE +# error "Work queue support required. CONFIG_SCHED_WORKQUEUE must be selected." +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* A reference to a structure of this type must be passed to the ADS7843E + * driver. This structure provides information about the configuration + * of the TSB2007 and provides some board-specific hooks. + * + * Memory for this structure is provided by the caller. It is not copied + * by the driver and is presumed to persist while the driver is active. The + * memory must be writable because, under certain circumstances, the driver + * may modify frequency or X plate resistance values. + */ + +struct ads7843e_config_s +{ + /* Device characterization */ + + uint32_t frequency; /* SPI frequency */ + + /* If multiple ADS7843E devices are supported, then an IRQ number must + * be provided for each so that their interrupts can be distinguished. + */ + +#ifndef CONFIG_ADS7843E_MULTIPLE + int irq; /* IRQ number received by interrupt handler. */ +#endif + + /* IRQ/GPIO access callbacks. These operations all hidden behind + * callbacks to isolate the ADS7843E driver from differences in GPIO + * interrupt handling by varying boards and MCUs. If possible, + * interrupts should be configured on both rising and falling edges + * so that contact and loss-of-contact events can be detected. + * + * attach - Attach the ADS7843E interrupt handler to the GPIO interrupt + * enable - Enable or disable the GPIO interrupt + * clear - Acknowledge/clear any pending GPIO interrupt + * pendown - Return the state of the pen down GPIO input + */ + + int (*attach)(FAR struct ads7843e_config_s *state, xcpt_t isr); + void (*enable)(FAR struct ads7843e_config_s *state, bool enable); + void (*clear)(FAR struct ads7843e_config_s *state); + bool (*busy)(FAR struct ads7843e_config_s *state); + bool (*pendown)(FAR struct ads7843e_config_s *state); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: ads7843e_register + * + * Description: + * Configure the ADS7843E to use the provided SPI device instance. This + * will register the driver as /dev/inputN where N is the minor device + * number + * + * Input Parameters: + * dev - An SPI driver instance + * config - Persistent board configuration data + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +EXTERN int ads7843e_register(FAR struct spi_dev_s *dev, + FAR struct ads7843e_config_s *config, + int minor); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_INPUT && CONFIG_INPUT_ADS7843E */ +#endif /* __INCLUDE_NUTTX_INPUT_ADS7843E_H */ diff --git a/nuttx/include/nuttx/input/stmpe811.h b/nuttx/include/nuttx/input/stmpe811.h new file mode 100644 index 0000000000..cea54a34f3 --- /dev/null +++ b/nuttx/include/nuttx/input/stmpe811.h @@ -0,0 +1,785 @@ +/******************************************************************************************** + * include/nuttx/input/stmpe811.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "STMPE811 S-Touch® advanced resistive touchscreen controller with 8-bit + * GPIO expander," Doc ID 14489 Rev 6, CD00186725, STMicroelectronics" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_INPUT_STMPE811_H +#define __INCLUDE_NUTTX_INPUT_STMPE811_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include + +#include +#include + +#include + +#if defined(CONFIG_INPUT) && defined(CONFIG_INPUT_STMPE811) + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ +/* Configuration ****************************************************************************/ +/* Prerequisites: CONFIG_INPUT=y + * Other settings that effect the driver: CONFIG_DISABLE_POLL + * + * CONFIG_INPUT_STMPE811 + * Enables support for the STMPE811 driver (Needs CONFIG_INPUT) + * CONFIG_STMPE811_SPI + * Enables support for the SPI interface (not currenly supported) + * CONFIG_STMPE811_I2C + * Enables support for the I2C interface + * CONFIG_STMPE811_MULTIPLE + * Can be defined to support multiple STMPE811 devices on board. + * CONFIG_STMPE811_NPOLLWAITERS + * Maximum number of threads that can be waiting on poll() (ignored if + * CONFIG_DISABLE_POLL is set). + * CONFIG_STMPE811_TSC_DISABLE + * Disable driver touchscreen functionality. + * CONFIG_STMPE811_ADC_DISABLE + * Disable driver ADC functionality. + * CONFIG_STMPE811_GPIO_DISABLE + * Disable driver GPIO functionality. + * CONFIG_STMPE811_GPIOINT_DISABLE + * Disable driver GPIO interrupt functionlality (ignored if GPIO functionality is + * disabled). + * CONFIG_STMPE811_SWAPXY + * Reverse the meaning of X and Y to handle different LCD orientations. + * CONFIG_STMPE811_TEMP_DISABLE + * Disable driver temperature sensor functionality. + * CONFIG_STMPE811_REGDEBUG + * Enabled very low register-level debug output. Requires CONFIG_DEBUG. + * CONFIG_STMPE811_THRESHX and CONFIG_STMPE811_THRESHY + * STMPE811 touchscreen data comes in a a very high rate. New touch positions + * will only be reported when the X or Y data changes by these thresholds. + * This trades reduces data rate for some loss in dragging accuracy. The + * STMPE811 is configure for 12-bit values so the raw ranges are 0-4095. So + * for example, if your display is 320x240, then THRESHX=13 and THRESHY=17 + * would correspond to one pixel. Default: 12 + */ + +/* The STMPE811 interfaces with the target CPU via a I2C or SPI interface. The pin IN_1 + * allows the selection of interface protocol at reset state. + */ + +#if !defined(CONFIG_STMPE811_SPI) && !defined(CONFIG_STMPE811_I2C) +# error "One of CONFIG_STMPE811_SPI or CONFIG_STMPE811_I2C must be defined" +#endif + +#if defined(CONFIG_STMPE811_SPI) && defined(CONFIG_STMPE811_I2C) +# error "Only one of CONFIG_STMPE811_SPI or CONFIG_STMPE811_I2C can be defined" +#endif + +/* Maximum number of threads than can be waiting for POLL events */ + +#ifndef CONFIG_STMPE811_NPOLLWAITERS +# define CONFIG_STMPE811_NPOLLWAITERS 2 +#endif + +/* Check for some required settings. This can save the user a lot of time + * in getting the right configuration. + */ + +#ifdef CONFIG_STMPE811_I2C +# ifndef CONFIG_I2C +# error "CONFIG_I2C is required in the I2C support" +# endif +# ifndef CONFIG_I2C_TRANSFER +# error "CONFIG_I2C_TRANSFER is required in the I2C configuration" +# endif +#endif + +#ifdef CONFIG_DISABLE_SIGNALS +# error "Signals are required. CONFIG_DISABLE_SIGNALS must not be selected." +#endif + +#ifndef CONFIG_SCHED_WORKQUEUE +# error "Work queue support required. CONFIG_SCHED_WORKQUEUE must be selected." +#endif + +/* Thresholds */ + +#ifndef CONFIG_STMPE811_THRESHX +# define CONFIG_STMPE811_THRESHX 12 +#endif + +#ifndef CONFIG_STMPE811_THRESHY +# define CONFIG_STMPE811_THRESHY 12 +#endif + +/* Debug output */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_STMPE811_REGDEBUG +#endif + +/* I2C **************************************************************************************/ +/* STMPE811 Address: The STMPE811 may have 7-bit address 0x41 or 0x44, depending upon the + * state of the ADDR0 pin. + */ + +#define STMPE811_I2C_ADDRESS_MASK (0x78) /* Bits 3-7: Invariant part of STMPE811 address */ +#define STMPE811_I2C_ADDRESS (0x40) /* Bits 3-7: Always set at '0100 0xxR' */ +#define STMPE811_I2C_A1 (1 << 2) /* Bit 2: A1 */ +#define STMPE811_I2C_A0 (1 << 1) /* Bit 1: A0 */ +#define STMPE811_I2C_READ (1 << 0) /* Bit 0=1: Selects read operation */ +#define STMPE811_I2C_WRITE (0) /* Bit 0=0: Selects write operation */ + +/* I2C frequency */ + +#define STMPE811_I2C_MAXFREQUENCY 400000 /* 400KHz */ + +/* SPI **************************************************************************************/ +/* The device always operates in mode 0 */ + +#define STMPE811_SPI_MODE SPIDEV_MODE0 /* Mode 0 */ + +/* I2C frequency */ + +#define STMPE811_SPI_MAXFREQUENCY 1000000 /* 1MHz */ + +/* STMPE811 Registers ************************************************************************/ +/* Register Addresses */ + +#define STMPE811_CHIP_ID 0x00 /* Device identification (16-bit) */ +#define STMPE811_ID_VER 0x02 /* Revision number: 0x01=sample 0x03=final silicon */ +#define STMPE811_SYS_CTRL1 0x03 /* Reset control */ +#define STMPE811_SYS_CTRL2 0x04 /* Clock control */ +#define STMPE811_SPI_CFG 0x08 /* SPI interface configuration */ +#define STMPE811_INT_CTRL 0x09 /* Interrupt control register */ +#define STMPE811_INT_EN 0x0a /* Interrupt enable register */ +#define STMPE811_INT_STA 0x0b /* Interrupt status register */ +#define STMPE811_GPIO_EN 0x0c /* GPIO interrupt enable register */ +#define STMPE811_GPIO_INTSTA 0x0d /* GPIO interrupt status register */ +#define STMPE811_ADC_INTEN 0x0e /* ADC interrupt enable register */ +#define STMPE811_ADC_INTSTA 0x0f /* ADC interrupt status register */ +#define STMPE811_GPIO_SETPIN 0x10 /* GPIO set pin register */ +#define STMPE811_GPIO_CLRPIN 0x11 /* GPIO clear pin register */ +#define STMPE811_GPIO_MPSTA 0x12 /* GPIO monitor pin state register */ +#define STMPE811_GPIO_DIR 0x13 /* GPIO direction register */ +#define STMPE811_GPIO_ED 0x14 /* GPIO edge detect register */ +#define STMPE811_GPIO_RE 0x15 /* GPIO rising edge register */ +#define STMPE811_GPIO_FE 0x16 /* GPIO falling edge register */ +#define STMPE811_GPIO_AF 0x17 /* Alternate function register */ +#define STMPE811_ADC_CTRL1 0x20 /* ADC control */ +#define STMPE811_ADC_CTRL2 0x21 /* ADC control */ +#define STMPE811_ADC_CAPT 0x22 /* To initiate ADC data acquisition */ +#define STMPE811_ADC_DATACH(n) (0x30 + ((n) << 1)) /* ADC channel n (16-bit) */ +#define STMPE811_ADC_DATACH0 0x30 /* ADC channel 0 (16-bit) */ +#define STMPE811_ADC_DATACH1 0x32 /* ADC channel 1 (16_bit) */ +#define STMPE811_ADC_DATACH2 0x34 /* ADC channel 2 (16-bit) */ +#define STMPE811_ADC_DATACH3 0x36 /* ADC channel 3 (16-bit) */ +#define STMPE811_ADC_DATACH4 0x38 /* ADC channel 4 (16-bit) */ +#define STMPE811_ADC_DATACH5 0x3a /* ADC channel 5 (16-bit) */ +#define STMPE811_ADC_DATACH6 0x3c /* ADC channel 6 (16-bit) */ +#define STMPE811_ADC_DATACH7 0x3e /* ADC channel 7 (16-bit) */ +#define STMPE811_TSC_CTRL 0x40 /* 4-wire touchscreen controller setup */ +#define STMPE811_TSC_CFG 0x41 /* Touchscreen controller configuration */ +#define STMPE811_WDW_TRX 0x42 /* Window setup for top right X (16-bit) */ +#define STMPE811_WDW_TRY 0x44 /* Window setup for top right Y (16-bit) */ +#define STMPE811_WDW_BLX 0x46 /* Window setup for bottom left X (16-bit) */ +#define STMPE811_WDW_BLY 0x48 /* Window setup for bottom left Y (16-bit) */ +#define STMPE811_FIFO_TH 0x4a /* FIFO level to generate interrupt */ +#define STMPE811_FIFO_STA 0x4b /* Current status of FIFO */ +#define STMPE811_FIFO_SIZE 0x4c /* Current filled level of FIFO */ +#define STMPE811_TSC_DATAX 0x4d /* Data port for touchscreen (16-bit) */ +#define STMPE811_TSC_DATAY 0x4f /* Data port for touchscreen (16-bit) */ +#define STMPE811_TSC_DATAZ 0x51 /* Data port for touchscreen */ +#define STMPE811_TSC_DATAXYZ 0x52 /* Data port for touchscreen (32-bit) */ +#define STMPE811_TSC_FRACTIONZ 0x56 /* Touchscreen controller FRACTION_Z */ +#define STMPE811_TSC_DATA 0x57 /* Data port for touchscreen */ +#define STMPE811_TSC_IDRIVE 0x58 /* Touchscreen controller drive I */ +#define STMPE811_TSC_SHIELD 0x59 /* Touchscreen controller shield */ +#define STMPE811_TEMP_CTRL 0x60 /* Temperature sensor setup */ +#define STMPE811_TEMP_DATA 0x61 /* Temperature data access port */ +#define STMPE811_TEMP_TH 0x62 /* Threshold for temperature controlled interrupt */ + +/* Register bit definitions */ + +/* Device identification (16-bit) */ + +#define CHIP_ID 0x0811 + +/* Revision number: 0x01=sample 0x03=final silicon */ + +#define ID_VER_SAMPLE 0x01 +#define ID_VER_FINAL 0x03 + +/* Reset control */ + +#define SYS_CTRL1_HIBERNATE (1 << 0) /* Bit 0: Force the device into hibernation mode */ +#define SYS_CTRL1_SOFTRESET (1 << 1) /* Bit 1: Reset the STMPE811 */ + +/* Clock control */ + +#define SYS_CTRL2_ADC_OFF (1 << 0) /* Bit 0: Switch off clock to ADC */ +#define SYS_CTRL2_TSC_OFF (1 << 1) /* Bit 1: Switch off clock to touchscreen controller */ +#define SYS_CTRL2_GPIO_OFF (1 << 2) /* Bit 2: Switch off clock to GPIO */ +#define SYS_CTRL2_TS_OFF (1 << 3) /* Bit 3: Switch off clock to temperature sensor */ + +/* SPI interface configuration */ + +#define SPI_CFG_SPI_CLK_MOD0 (1 << 0) /* Bit 0: Value of SCAD/A0 pin at power-up reset */ +#define SPI_CFG_SPI_CLK_MOD1 (1 << 1) /* Bit 1: Value of SCAD/A0 pin at power-up reset */ +#define SPI_CFG_AUTO_INCR (1 << 2) /* Bit 2: Enable internally autoincremented addressing */ + +/* Interrupt control register */ + +#define INT_CTRL_GLOBAL_INT (1 << 0) /* Bit 0: Master interrupt enable */ +#define INT_CTRL_INT_TYPE (1 << 1) /* Bit 1: Type of interrupt signal. 1=edge */ +#define INT_CTRL_INT_POLARITY (1 << 2) /* Bit 2: Interrupt pin polarity. 1=active high */ + +/* Interrupt enable/status register */ + +#define INT_TOUCH_DET (1 << 0) /* Bit 0: Touch is detected */ +#define INT_FIFO_TH (1 << 1) /* Bit 1: FIFO is equal or above threshold value */ +#define INT_FIFO_OFLOW (1 << 2) /* Bit 2: FIFO is overflowed */ +#define INT_FIFO_FULL (1 << 3) /* Bit 3: FIFO is full */ +#define INT_FIFO_EMPTY (1 << 4) /* Bit 4: FIFO is empty */ +#define INT_TEMP_SENS (1 << 5) /* Bit 5: Temperature threshold triggering */ +#define INT_ADC (1 << 6) /* Bit 6: Any enabled ADC interrupts */ +#define INT_GPIO (1 << 7) /* Bit 7: Any enabled GPIO interrupts */ +#define INT_ALL 0xff + +/* GPIO interrupt enable/status register */ + +#define GPIO_INT(n) (1 << (n)) + +/* ADC interrupt enable/status register */ + +#define ADC_INT(n) (1 << (n)) + +/* GPIO set/clear/sta/dir/edge/rising/falling/af registers */ + +#define GPIO_PIN(n) (1 << (n)) +#define TSC_PIN_SET (0xf0) /* Pins 4-7: Used by touchscreen */ + +/* ADC control */ + +#define ADC_CTRL1_REF_SEL (1 << 1) /* Bit 1: Selects internal/external, 1=external */ +#define ADC_CTRL1_MOD_12B (1 << 3) /* Bit 3: Selects 10/12-bit ADC operation, 1=12-bit */ +#define ADC_CTRL1_SAMPLE_TIME_SHIFT (4) /* Bits 4-6: ADC conversion time in number of clock */ +#define ADC_CTRL1_SAMPLE_TIME_MASK (7 << ADC_CTRL1_SAMPLE_TIME_SHIFT) +# define ADC_CTRL1_SAMPLE_TIME_36 (0 << ADC_CTRL1_SAMPLE_TIME_SHIFT) +# define ADC_CTRL1_SAMPLE_TIME_44 (1 << ADC_CTRL1_SAMPLE_TIME_SHIFT) +# define ADC_CTRL1_SAMPLE_TIME_56 (2 << ADC_CTRL1_SAMPLE_TIME_SHIFT) +# define ADC_CTRL1_SAMPLE_TIME_64 (3 << ADC_CTRL1_SAMPLE_TIME_SHIFT) +# define ADC_CTRL1_SAMPLE_TIME_80 (4 << ADC_CTRL1_SAMPLE_TIME_SHIFT) +# define ADC_CTRL1_SAMPLE_TIME_96 (5 << ADC_CTRL1_SAMPLE_TIME_SHIFT) +# define ADC_CTRL1_SAMPLE_TIME_124 (6 << ADC_CTRL1_SAMPLE_TIME_SHIFT) + +/* ADC control */ + +#define ADC_CTRL2_ADC_FREQ_SHIFT (0) /* Bits 0-1: Selects the clock speed of ADC */ +#define ADC_CTRL2_ADC_FREQ_MASK (3 << ADC_CTRL2_ADC_FREQ_SHIFT) +# define ADC_CTRL2_ADC_FREQ_1p625 (0 << ADC_CTRL2_ADC_FREQ_SHIFT) /* 00: 1.625 MHz typ. */ +# define ADC_CTRL2_ADC_FREQ_3p25 (1 << ADC_CTRL2_ADC_FREQ_SHIFT) /* 01: 3.25 MHz typ. */ +# define ADC_CTRL2_ADC_FREQ_6.5 (2 << ADC_CTRL2_ADC_FREQ_SHIFT) /* 1x: 6.5 MHz typ. */ + +/* To initiate ADC data acquisition */ + +#define ADC_CAPT_CH(n) (1 << (n)) + +/* 4-wire touchscreen controller setup */ + +#define TSC_CTRL_EN (1 << 0) /* Bit 0: Enable TSC */ +#define TSC_CTRL_OP_MOD_SHIFT (1) /* Bits 1-3: TSC operating mode */ +#define TSC_CTRL_OP_MOD_MASK (7 << TSC_CTRL_OP_MOD_SHIFT) +# define TSC_CTRL_OP_MOD_XYZ (0 << TSC_CTRL_OP_MOD_SHIFT) /* 000: X, Y, Z acquisition */ +# define TSC_CTRL_OP_MOD_XY (1 << TSC_CTRL_OP_MOD_SHIFT) /* 001: X, Y only */ +# define TSC_CTRL_OP_MOD_X (2 << TSC_CTRL_OP_MOD_SHIFT) /* 010: X only */ +# define TSC_CTRL_OP_MOD_Y (3 << TSC_CTRL_OP_MOD_SHIFT) /* 011: Y only */ +# define TSC_CTRL_OP_MOD_Z (4 << TSC_CTRL_OP_MOD_SHIFT) /* 100: Z only */ +#define TSC_CTRL_TRACK_SHIFT (4) /* Bits 4-6: Tracking index */ +#define TSC_CTRL_TRACK_MASK (7 << TSC_CTRL_TRACK_SHIFT) +#define TSC_CTRL_TRACK_NONE (0 << TSC_CTRL_TRACK_SHIFT) +#define TSC_CTRL_TRACK_4 (1 << TSC_CTRL_TRACK_SHIFT) +#define TSC_CTRL_TRACK_8 (2 << TSC_CTRL_TRACK_SHIFT) +#define TSC_CTRL_TRACK_16 (3 << TSC_CTRL_TRACK_SHIFT) +#define TSC_CTRL_TRACK_32 (4 << TSC_CTRL_TRACK_SHIFT) +#define TSC_CTRL_TRACK_64 (5 << TSC_CTRL_TRACK_SHIFT) +#define TSC_CTRL_TRACK_92 (6 << TSC_CTRL_TRACK_SHIFT) +#define TSC_CTRL_TRACK_127 (7 << TSC_CTRL_TRACK_SHIFT) +#define TSC_CTRL_TSC_STA (1 << 7) /* Bit 7: TSC status. 1=touch detected */ + +/* Touchscreen controller configuration */ + +#define TSC_CFG_SETTLING_SHIFT (0) /* Bits 0-2: Panel driver settling time */ +#define TSC_CFG_SETTLING_MASK (7 << TSC_CFG_SETTLING_SHIFT) +# define TSC_CFG_SETTLING_10US (0 << TSC_CFG_SETTLING_SHIFT) +# define TSC_CFG_SETTLING_100US (1 << TSC_CFG_SETTLING_SHIFT) +# define TSC_CFG_SETTLING_500US (2 << TSC_CFG_SETTLING_SHIFT) +# define TSC_CFG_SETTLING_1MS (3 << TSC_CFG_SETTLING_SHIFT) +# define TSC_CFG_SETTLING_5MS (4 << TSC_CFG_SETTLING_SHIFT) +# define TSC_CFG_SETTLING_10MS (5 << TSC_CFG_SETTLING_SHIFT) +# define TSC_CFG_SETTLING_50MS (6 << TSC_CFG_SETTLING_SHIFT) +# define TSC_CFG_SETTLING_100MS (7 << TSC_CFG_SETTLING_SHIFT) +#define TSC_CFG_TOUCH_DELAY_SHIFT (3) /* Bits 3-5: Touch detect delay */ +#define TSC_CFG_TOUCH_DELAY_MASK (7 << TSC_CFG_TOUCH_DELAY_SHIFT) +# define TSC_CFG_TOUCH_DELAY_10US (0 << TSC_CFG_TOUCH_DELAY_SHIFT) +# define TSC_CFG_TOUCH_DELAY_50US (1 << TSC_CFG_TOUCH_DELAY_SHIFT) +# define TSC_CFG_TOUCH_DELAY_100US (2 << TSC_CFG_TOUCH_DELAY_SHIFT) +# define TSC_CFG_TOUCH_DELAY_500US (3 << TSC_CFG_TOUCH_DELAY_SHIFT) +# define TSC_CFG_TOUCH_DELAY_1MS (4 << TSC_CFG_TOUCH_DELAY_SHIFT) +# define TSC_CFG_TOUCH_DELAY_5MS (5 << TSC_CFG_TOUCH_DELAY_SHIFT) +# define TSC_CFG_TOUCH_DELAY_10MS (6 << TSC_CFG_TOUCH_DELAY_SHIFT) +# define TSC_CFG_TOUCH_DELAY_50MS (7 << TSC_CFG_TOUCH_DELAY_SHIFT) +#define TSC_CFG_AVE_CTRL_SHIFT (6) /* Bits 6-7: Average control */ +#define TSC_CFG_AVE_CTRL_MASK (3 << TSC_CFG_AVE_CTRL_SHIFT) +# define TSC_CFG_AVE_CTRL_1SAMPLE (0 << TSC_CFG_AVE_CTRL_SHIFT) +# define TSC_CFG_AVE_CTRL_2SAMPLES (1 << TSC_CFG_AVE_CTRL_SHIFT) +# define TSC_CFG_AVE_CTRL_4SAMPLES (2 << TSC_CFG_AVE_CTRL_SHIFT) +# define TSC_CFG_AVE_CTRL_8SAMPLES (3 << TSC_CFG_AVE_CTRL_SHIFT) + +/* Current status of FIFO */ + +#define FIFO_STA_FIFO_RESET (1 << 0) /* Bit 0: Resets FIFO. All data in FIFO are cleared */ +#define FIFO_STA_FIFO_TH_TRIG (1 << 4) /* Bit 0: 1 = FIFO size is at or beyond threshold */ +#define FIFO_STA_FIFO_EMPTY (1 << 5) /* Bit 0: FIFO is empty */ +#define FIFO_STA_FIFO_FULL (1 << 6) /* Bit 0: FIFO is full */ +#define FIFO_STA_FIFO_OFLOW (1 << 7) /* Bit 0: FIFO is overflow */ + +/* Touchscreen controller FRACTION_Z */ + +#define TSC_FRACTIONZ_MASK 0x07 + +/* Touchscreen controller drive I */ + +#define TSC_IDRIVE (1 << 0) /* Bit 0: MAX current on TSC driving channel */ +# define TSC_IDRIVE_20MA (0) /* 20mA typical, 35mA max */ +# define TSC_IDRIVE_50MA (1 << 0) /* 50mA typical, 80mA max */ + +/* Touchscreen controller shield */ + +#define TSC_SHIELD_YM (1 << 0) /* Bit 0: Ground Y- */ +#define TSC_SHIELD_YP (1 << 1) /* Bit 1: Ground Y+ */ +#define TSC_SHIELD_XM (1 << 2) /* Bit 2: Ground X- */ +#define TSC_SHIELD_XP (1 << 3) /* Bit 3: Ground X+ */ + +/* Temperature sensor setup */ + +#define TEMP_CTRL_ENABLE (1 << 0) /* Bit 0: Enable */ +#define TEMP_CTRL_ACQ (1 << 1) /* Bit 1: Acquire */ +#define TEMP_CTRL_ACQ_MOD (1 << 2) /* Bit 2: 0=once, 1=every 10MS */ +#define TEMP_CTRL_THRES_EN (1 << 3) /* Bit 3: Threshold enable */ +#define TEMP_CTRL_THRES_RANGE (1 << 4) /* Bit 4: temperature threshold enable, 0='>=' 1='<' */ + +/* GPIO Configuration ***********************************************************************/ +/* The STMPE811 GPIO interfaces take an 8-bit bit-encoded parameter to describe the GPIO pin. + * The following definitions describe the bit-encoding of that parameter. + * + * 7654 3210 + * ---- ---- + * DIRF VPPP + * + * Input Pins: 1IRF .PPP + * + * Output Pins: 0... VPPP + * + * Bits 7 is the pin direction. + */ + +#define STMPE811_GPIO_DIR (1 << 7) /* Bit7: Direction bit */ +#define STMPE811_GPIO_INPUT (1 << 7) /* Input pin (possibly interrupting) */ +#define STMPE811_GPIO_OUTPUT (0) /* Configure as in output */ + +/* Bit 6 indicates that the pin will generate an interrupt (inputs only) */ + +#define STMPE811_GPIO_IN (1 << 6) /* Bit 6: Input interrupting pin */ + +/* The bits 4-5 select the rising and/or the falling edge detection. */ + +#define STMPE811_GPIO_RISING (1 << 5) /* Bit 5: Input interrupting pin */ +#define STMPE811_GPIO_FALLING (1 << 4) /* Bit 4: Input interrupting pin */ + +/* Bit 3 is the initial value for output pins */ + +#define STMPE811_GPIO_VALUE (1 << 3) /* Bit 3: The initial value of an output pin */ +# define STMPE811_GPIO_ONE (1 << 3) /* Bit 3: The initial value is logic 1 */ +# define STMPE811_GPIO_ZERO (0) /* Bit 3: The initial value is logic 0 */ + +/* Bits 0-2 is the pin number */ + +#define STMPE811_GPIO_PIN_SHIFT (0) +#define STMPE811_GPIO_PIN_MASK (7 << STMPE811_GPIO_PIN_SHIFT) +# define STMPE811_GPIO_PIN0 (0 << STMPE811_GPIO_PIN_SHIFT) +# define STMPE811_GPIO_PIN1 (1 << STMPE811_GPIO_PIN_SHIFT) +# define STMPE811_GPIO_PIN2 (2 << STMPE811_GPIO_PIN_SHIFT) +# define STMPE811_GPIO_PIN3 (3 << STMPE811_GPIO_PIN_SHIFT) +# define STMPE811_GPIO_PIN4 (4 << STMPE811_GPIO_PIN_SHIFT) +# define STMPE811_GPIO_PIN5 (5 << STMPE811_GPIO_PIN_SHIFT) +# define STMPE811_GPIO_PIN6 (6 << STMPE811_GPIO_PIN_SHIFT) +# define STMPE811_GPIO_PIN7 (7 << STMPE811_GPIO_PIN_SHIFT) + +/******************************************************************************************** + * Public Types + ********************************************************************************************/ + +/* Form of the GPIO "interrupt handler" callback. Callbacks do not occur from an interrupt + * handler but rather from the context of the worker thread with interrupts enabled. + */ + +typedef void (*stmpe811_handler_t)(int pin); + +/* A reference to a structure of this type must be passed to the STMPE811 driver when the + * driver is instantiaed. This structure provides information about the configuration of the + * STMPE811 and provides some board-specific hooks. + * + * Memory for this structure is provided by the caller. It is not copied by the driver + * and is presumed to persist while the driver is active. The memory must be writable + * because, under certain circumstances, the driver may modify the frequency. + */ + +struct stmpe811_config_s +{ + /* Device characterization */ + +#ifdef CONFIG_STMPE811_I2C + uint8_t address; /* 7-bit I2C address (only bits 0-6 used) */ +#endif + uint32_t frequency; /* I2C or SPI frequency */ + + /* If multiple STMPE811 devices are supported, then an IRQ number must + * be provided for each so that their interrupts can be distinguished. + */ + +#ifdef CONFIG_STMPE811_MULTIPLE + int irq; /* IRQ number received by interrupt handler. */ +#endif + + /* These are the timing valuses for ADC CTRL1 and CTRL2. These values + * are only used if either the TSC or the ADC are enabled. These values + * determine the characteristics of sampling. + */ + +#if !defined(CONFIG_STMPE811_ADC_DISABLE) || !defined(CONFIG_STMPE811_TSC_DISABLE) + uint8_t ctrl1; /* Initialization value for ADC CTRL1 */ + uint8_t ctrl2; /* Initialization value for ADC CTRL1 */ +#endif + + /* IRQ/GPIO access callbacks. These operations all hidden behind + * callbacks to isolate the STMPE811 driver from differences in GPIO + * interrupt handling by varying boards and MCUs. + * + * attach - Attach the STMPE811 interrupt handler to the GPIO interrupt + * enable - Enable or disable the GPIO interrupt + * clear - Acknowledge/clear any pending GPIO interrupt + */ + + int (*attach)(FAR struct stmpe811_config_s *state, xcpt_t isr); + void (*enable)(FAR struct stmpe811_config_s *state, bool enable); + void (*clear)(FAR struct stmpe811_config_s *state); +}; + +/* Since the STMPE811 is a multi-function device, no functionality is assumed when the device + * is first created. Rather, a multi-step initialization is required. When + * stmpe811_instantiate is called, it returns a handle of the following type. That handle may + * then be used to enable a configure the STMPE811 functionality. + */ + +typedef FAR void *STMPE811_HANDLE; + +/******************************************************************************************** + * Public Function Prototypes + ********************************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/******************************************************************************************** + * Name: stmpe811_instantiate + * + * Description: + * Instantiate and configure the STMPE811 device driver to use the provided I2C or SPI + * device instance. + * + * Input Parameters: + * dev - An I2C or SPI driver instance + * config - Persistant board configuration data + * + * Returned Value: + * A non-zero handle is returned on success. This handle may then be used to configure + * the STMPE811 driver as necessary. A NULL handle value is returned on failure. + * + ********************************************************************************************/ + +#ifdef CONFIG_STMPE811_SPI +EXTERN STMPE811_HANDLE stmpe811_instantiate(FAR struct spi_dev_s *dev, + FAR struct stmpe811_config_s *config); +#else +EXTERN STMPE811_HANDLE stmpe811_instantiate(FAR struct i2c_dev_s *dev, + FAR struct stmpe811_config_s *config); +#endif + +/******************************************************************************************** + * Name: stmpe811_register + * + * Description: + * Enable TSC functionality. GPIO4-7 must be available. This function will register the + * touchsceen driver as /dev/inputN where N is the minor device number + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is returned to indicate + * the nature of the failure. + * + ********************************************************************************************/ + +#ifndef CONFIG_STMPE811_TSC_DISABLE +EXTERN int stmpe811_register(STMPE811_HANDLE handle, int minor); +#endif + +/******************************************************************************************** + * Name: stmpe811_gpioconfig + * + * Description: + * Configure an STMPE811 GPIO pin + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * pinconfig - Bit-encoded pin configuration + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is returned to indicate + * the nature of the failure. + * + ********************************************************************************************/ + +#ifndef CONFIG_STMPE811_GPIO_DISABLE +EXTERN int stmpe811_gpioconfig(STMPE811_HANDLE handle, uint8_t pinconfig); +#endif + +/******************************************************************************************** + * Name: stmpe811_gpiowrite + * + * Description: + * Set or clear the GPIO output + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * pinconfig - Bit-encoded pin configuration + * value = true: write logic '1'; false: write logic '0; + * + * Returned Value: + * None + * + ********************************************************************************************/ + +#ifndef CONFIG_STMPE811_GPIO_DISABLE +EXTERN void stmpe811_gpiowrite(STMPE811_HANDLE handle, uint8_t pinconfig, bool value); +#endif + +/******************************************************************************************** + * Name: stmpe811_gpioread + * + * Description: + * Set or clear the GPIO output + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * pinconfig - Bit-encoded pin configuration + * value - The location to return the state of the GPIO pin + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is returned to indicate + * the nature of the failure. + * + ********************************************************************************************/ + +#ifndef CONFIG_STMPE811_GPIO_DISABLE +EXTERN int stmpe811_gpioread(STMPE811_HANDLE handle, uint8_t pinconfig, bool *value); +#endif + +/******************************************************************************************** + * Name: stmpe811_gpioattach + * + * Description: + * Attach to a GPIO interrupt input pin and enable interrupts on the pin. Using the value + * NULL for the handler address will disable interrupts from the pin and detach the handler. + * + * NOTE: Callbacks do not occur from an interrupt handler but rather from the context + * of the worker thread with interrupts enabled. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * pinconfig - Bit-encoded pin configuration + * handler - The handler that will be called when the interrupt occurs. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is returned to indicate + * the nature of the failure. + * + ********************************************************************************************/ + +#if !defined(CONFIG_STMPE811_GPIO_DISABLE) && !defined(CONFIG_STMPE811_GPIOINT_DISABLE) +EXTERN int stmpe811_gpioattach(STMPE811_HANDLE handle, uint8_t pinconfig, + stmpe811_handler_t handler); +#endif + +/******************************************************************************************** + * Name: stmpe811_adcinitialize + * + * Description: + * Configure for ADC mode operation. Set overall ADC ADC timing that applies to all pins. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is returned to indicate + * the nature of the failure. + * + ********************************************************************************************/ + +#ifndef CONFIG_STMPE811_ADC_DISABLE +EXTERN int stmpe811_adcinitialize(STMPE811_HANDLE handle); +#endif + +/******************************************************************************************** + * Name: stmpe811_adcconfig + * + * Description: + * Configure a pin for ADC input. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * pin - The ADC pin number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is returned to indicate + * the nature of the failure. + * + ********************************************************************************************/ + +#ifndef CONFIG_STMPE811_ADC_DISABLE +EXTERN int stmpe811_adcconfig(STMPE811_HANDLE handle, int pin); +#endif + +/******************************************************************************************** + * Name: stmpe811_adcread + * + * Description: + * Read the converted analog input value from the select pin. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * pin - The ADC pin number + * + * Returned Value: + * The converted value (there is no error reporting mechanism). + * + ********************************************************************************************/ + +#ifndef CONFIG_STMPE811_ADC_DISABLE +EXTERN uint16_t stmpe811_adcread(STMPE811_HANDLE handle, int pin); +#endif + +/******************************************************************************************** + * Name: stmpe811_tempinitialize + * + * Description: + * Configure the temperature sensor. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is returned to indicate + * the nature of the failure. + * + ********************************************************************************************/ + +EXTERN int stmpe811_tempinitialize(STMPE811_HANDLE handle); + +/******************************************************************************************** + * Name: stmpe811_tempread + * + * Description: + * Configure the temperature sensor. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is returned to indicate + * the nature of the failure. + * + ********************************************************************************************/ + +EXTERN uint16_t stmpe811_tempread(STMPE811_HANDLE handle); + +/******************************************************************************************** + * Name: stmpe811_tempinterrupt + * + * Description: + * Configure the temperature sensor to sample the temperature periodically. + * Set the temperature threshold to generate an interrupt and notify + * to the client using the provide callback function pointer. + * + * Input Parameters: + * handle - The handle previously returned by stmpe811_instantiate + * threshold - The threshold temperature value + * direction - True: Generate an interrupt if the temperate exceeds the + * threshold value; False: Generate an interrupt if the + * temperature falls below the threshold value. + * callback - The client callback function that will be called when + * the termperature crosses the threshold. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is returned to indicate + * the nature of the failure. + * + ********************************************************************************************/ +/* Not implemented */ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_INPUT && CONFIG_INPUT_STMPE811 */ +#endif /* __INCLUDE_NUTTX_INPUT_STMPE811_H */ diff --git a/nuttx/include/nuttx/input/touchscreen.h b/nuttx/include/nuttx/input/touchscreen.h new file mode 100644 index 0000000000..04fc13dd72 --- /dev/null +++ b/nuttx/include/nuttx/input/touchscreen.h @@ -0,0 +1,180 @@ +/************************************************************************************ + * include/nuttx/input/touchscreen.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/* The TOUCHSCREEN driver exports a standard character driver interface. By + * convention, the touchscreen driver is registers as an input device at + * /dev/inputN where N uniquely identifies the driver instance. + * + * This header file documents the generic interface that all NuttX + * touchscreen devices must conform. It adds standards and conventions on + * top of the standard character driver interface. + */ + +#ifndef __INCLUDE_NUTTX_INPUT_TOUCHSCREEN_H +#define __INCLUDE_NUTTX_INPUT_TOUCHSCREEN_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +#ifdef CONFIG_INPUT + +/************************************************************************************ + * Pre-Processor Definitions + ************************************************************************************/ +/* IOCTL Commands *******************************************************************/ + +#define TSIOC_SETCALIB _TSIOC(0x0001) /* arg: Pointer to int calibration value */ +#define TSIOC_GETCALIB _TSIOC(0x0002) /* arg: Pointer to int calibration value */ +#define TSIOC_SETFREQUENCY _TSIOC(0x0003) /* arg: Pointer to uint32_t frequency value */ +#define TSIOC_GETFREQUENCY _TSIOC(0x0004) /* arg: Pointer to uint32_t frequency value */ + +/* Specific touchscreen drivers may support additional, device specific ioctal + * commands, beginning with this value: + */ + +#define TSIOC_USER 0x0005 /* Lowest, unused TSC ioctl command */ + +/* These definitions provide the meaning of all of the bits that may be + * reported in the struct touch_point_s flags. + */ + +#define TOUCH_DOWN (1 << 0) /* A new touch contact is established */ +#define TOUCH_MOVE (1 << 1) /* Movement occurred with previously reported contact */ +#define TOUCH_UP (1 << 2) /* The touch contact was lost */ +#define TOUCH_ID_VALID (1 << 3) /* Touch ID is uncertain */ +#define TOUCH_POS_VALID (1 << 4) /* Hardware provided a valid X/Y position */ +#define TOUCH_PRESSURE_VALID (1 << 5) /* Hardware provided a valid pressure */ +#define TOUCH_SIZE_VALID (1 << 6) /* Hardware provided a valid H/W contact size */ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/* This structure contains information about a single touch point. + * Positional units are device specific. + */ + +struct touch_point_s +{ + uint8_t id; /* Unique identifies contact; Same in all reports for the contact */ + uint8_t flags; /* See TOUCH_* definitions above */ + int16_t x; /* X coordinate of the touch point (uncalibrated) */ + int16_t y; /* Y coordinate of the touch point (uncalibrated) */ + int16_t h; /* Height of touch point (uncalibrated) */ + int16_t w; /* Width of touch point (uncalibrated) */ + uint16_t pressure; /* Touch pressure */ +}; + +/* The typical touchscreen driver is a read-only, input character device driver. + * the driver write() method is not supported and any attempt to open the + * driver in any mode other than read-only will fail. + * + * Data read from the touchscreen device consists only of touch events and + * touch sample data. This is reflected by struct touch_sample_s. This + * structure is returned by either the driver read method. + * + * On some devices, multiple touchpoints may be supported. So this top level + * data structure is a struct touch_sample_s that "contains" a set of touch + * points. Each touch point is managed individually using an ID that identifies + * a touch from first contact until the end of the contact. + */ + +struct touch_sample_s +{ + int npoints; /* The number of touch points in point[] */ + struct touch_point_s point[1]; /* Actual dimension is npoints */ +}; +#define SIZEOF_TOUCH_SAMPLE_S(n) (sizeof(struct touch_sample_s) + ((n)-1)*sizeof(struct touch_point_s)) + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: arch_tcinitialize + * + * Description: + * Each board that supports a touchscreen device must provide this function. + * This function is called by application-specific, setup logic to + * configure the touchscreen device. This function will register the driver + * as /dev/inputN where N is the minor device number. + * + * Input Parameters: + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +EXTERN int arch_tcinitialize(int minor); + +/**************************************************************************** + * Name: arch_tcuninitialize + * + * Description: + * Each board that supports a touchscreen device must provide this function. + * This function is called by application-specific, setup logic to + * uninitialize the touchscreen device. + * + * Input Parameters: + * None + * + * Returned Value: + * None. + * + ****************************************************************************/ + +EXTERN void arch_tcuninitialize(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_INPUT */ +#endif /* __INCLUDE_NUTTX_INPUT_TOUCHSCREEN_H */ diff --git a/nuttx/include/nuttx/input/tsc2007.h b/nuttx/include/nuttx/input/tsc2007.h new file mode 100644 index 0000000000..c3ddcef5e6 --- /dev/null +++ b/nuttx/include/nuttx/input/tsc2007.h @@ -0,0 +1,172 @@ +/**************************************************************************** + * include/nuttx/input/tsc2007.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "1.2V to 3.6V, 12-Bit, Nanopower, 4-Wire Micro TOUCH SCREEN CONTROLLER + * with I2C Interface," SBAS405A March 2007, Revised, March 2009, Texas + * Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* The TSC2007 is an analog interface circuit for a human interface touch + * screen device. All peripheral functions are controlled through the command + * byte and onboard state machines. + */ + +#ifndef __INCLUDE_NUTTX_INPUT_TSC2007_H +#define __INCLUDE_NUTTX_INPUT_TSC2007_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#if defined(CONFIG_INPUT) && defined(CONFIG_INPUT_TSC2007) + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* Maximum number of threads than can be waiting for POLL events */ + +#ifndef CONFIG_TSC2007_NPOLLWAITERS +# define CONFIG_TSC2007_NPOLLWAITERS 2 +#endif + +/* Check for some required settings. This can save the user a lot of time + * in getting the right configuration. + */ + +#ifndef CONFIG_I2C_TRANSFER +# error "CONFIG_I2C_TRANSFER is required in the I2C configuration" +#endif + +#ifdef CONFIG_DISABLE_SIGNALS +# error "Signals are required. CONFIG_DISABLE_SIGNALS must not be selected." +#endif + +#ifndef CONFIG_SCHED_WORKQUEUE +# error "Work queue support required. CONFIG_SCHED_WORKQUEUE must be selected." +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* A reference to a structure of this type must be passed to the TSC2007 + * driver. This structure provides information about the configuration + * of the TSB2007 and provides some board-specific hooks. + * + * Memory for this structure is provided by the caller. It is not copied + * by the driver and is presumed to persist while the driver is active. The + * memory must be writable because, under certain circumstances, the driver + * may modify frequency or X plate resistance values. + */ + +struct tsc2007_config_s +{ + /* Device characterization */ + + uint8_t address; /* 7-bit I2C address (only bits 0-6 used) */ + uint16_t rxplate; /* Calibrated X plate resistance */ + uint32_t frequency; /* I2C frequency */ + + /* If multiple TSC2007 devices are supported, then an IRQ number must + * be provided for each so that their interrupts can be distinguished. + */ + +#ifndef CONFIG_TSC2007_MULTIPLE + int irq; /* IRQ number received by interrupt handler. */ +#endif + + /* IRQ/GPIO access callbacks. These operations all hidden behind + * callbacks to isolate the TSC2007 driver from differences in GPIO + * interrupt handling by varying boards and MCUs. If possible, + * interrupts should be configured on both rising and falling edges + * so that contact and loss-of-contact events can be detected. + * + * attach - Attach the TSC2007 interrupt handler to the GPIO interrupt + * enable - Enable or disable the GPIO interrupt + * clear - Acknowledge/clear any pending GPIO interrupt + * pendown - Return the state of the pen down GPIO input + */ + + int (*attach)(FAR struct tsc2007_config_s *state, xcpt_t isr); + void (*enable)(FAR struct tsc2007_config_s *state, bool enable); + void (*clear)(FAR struct tsc2007_config_s *state); + bool (*pendown)(FAR struct tsc2007_config_s *state); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: tsc2007_register + * + * Description: + * Configure the TSC2007 to use the provided I2C device instance. This + * will register the driver as /dev/inputN where N is the minor device + * number + * + * Input Parameters: + * dev - An I2C driver instance + * config - Persistant board configuration data + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +EXTERN int tsc2007_register(FAR struct i2c_dev_s *dev, + FAR struct tsc2007_config_s *config, + int minor); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_INPUT && CONFIG_INPUT_TSC2007 */ +#endif /* __INCLUDE_NUTTX_INPUT_TSC2007_H */ diff --git a/nuttx/include/nuttx/irq.h b/nuttx/include/nuttx/irq.h new file mode 100644 index 0000000000..0bbb4a18c2 --- /dev/null +++ b/nuttx/include/nuttx/irq.h @@ -0,0 +1,94 @@ +/**************************************************************************** + * include/nuttx/irq.h + * + * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_IRQ_H +#define __INCLUDE_NUTTX_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +# define irq_detach(isr) irq_attach(isr, NULL) +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This struct defines the way the registers are stored */ + +#ifndef __ASSEMBLY__ +typedef int (*xcpt_t)(int irq, FAR void *context); +#endif + +/* Now include architecture-specific types */ + +#include + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN int irq_attach(int irq, xcpt_t isr); + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __INCLUDE_NUTTX_IRQ_H */ + diff --git a/nuttx/include/nuttx/kmalloc.h b/nuttx/include/nuttx/kmalloc.h new file mode 100644 index 0000000000..767809f882 --- /dev/null +++ b/nuttx/include/nuttx/kmalloc.h @@ -0,0 +1,114 @@ +/**************************************************************************** + * include/nuttx/kmalloc.h + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_KMALLOC_H +#define __INCLUDE_NUTTX_KMALLOC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#ifndef CONFIG_NUTTX_KERNEL +# include +# include +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef KMALLOC_EXTERN +#if defined(__cplusplus) +# define KMALLOC_EXTERN extern "C" +extern "C" { +#else +# define KMALLOC_EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* For a monolithic, kernel-mode NuttX build. Special allocators must be + * used. Otherwise, the standard allocators prototyped in stdlib.h may + * be used for both the kernel- and user-mode objects. + */ + +#ifndef CONFIG_NUTTX_KERNEL + +# define kmm_initialize(h,s) mm_initialize(h,s) +# define kmm_addregion(h,s) mm_addregion(h,s) +# define kmm_trysemaphore() mm_trysemaphore() +# define kmm_givesemaphore() mm_givesemaphore() + +# define kmalloc(s) malloc(s) +# define kzalloc(s) zalloc(s) +# define krealloc(p,s) realloc(p,s) +# define kfree(p) free(p) + +#else + +KMALLOC_EXTERN void kmm_initialize(FAR void *heap_start, size_t heap_size); +KMALLOC_EXTERN void kmm_addregion(FAR void *heapstart, size_t heapsize); +KMALLOC_EXTERN int kmm_trysemaphore(void); +KMALLOC_EXTERN void kmm_givesemaphore(void); + +KMALLOC_EXTERN FAR void *kmalloc(size_t); +KMALLOC_EXTERN FAR void *kzalloc(size_t); +KMALLOC_EXTERN FAR void *krealloc(FAR void*, size_t); +KMALLOC_EXTERN void kfree(FAR void*); + +#endif + +/* Functions defined in os_list.c *******************************************/ + +/* Handles memory freed from an interrupt handler */ + +KMALLOC_EXTERN void sched_free(FAR void *address); + +#undef KMALLOC_EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_KMALLOC_H */ diff --git a/nuttx/include/nuttx/lcd/lcd.h b/nuttx/include/nuttx/lcd/lcd.h new file mode 100644 index 0000000000..45eb03b0df --- /dev/null +++ b/nuttx/include/nuttx/lcd/lcd.h @@ -0,0 +1,219 @@ +/**************************************************************************** + * include/nuttx/lcd/lcd.h + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_LCD_H +#define __INCLUDE_NUTTX_LCD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Friendlier names */ + +#define LCD_FULL_OFF (0) +#define LCD_FULL_ON CONFIG_LCD_MAXPOWER + +#define LCD_MIN_CONTRAST (0) +#define LCD_MAX_CONTRAST CONFIG_LCD_MAXCONTRAST + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/* This structure describes one color plane. Some YUV formats may support + * up to 4 planes (although they probably wouldn't be used on LCD hardware). + * The framebuffer driver provides the video memory address in its + * corresponding fb_planeinfo_s structure. The LCD driver, instead, provides + * methods to transfer data to/from the LCD color plane. + */ + +struct lcd_planeinfo_s +{ + /* LCD Data Transfer ******************************************************/ + /* This method can be used to write a partial raster line to the LCD: + * + * row - Starting row to write to (range: 0 <= row < yres) + * col - Starting column to write to (range: 0 <= col <= xres-npixels) + * buffer - The buffer containing the run to be written to the LCD + * npixels - The number of pixels to write to the LCD + * (range: 0 < npixels <= xres-col) + */ + + int (*putrun)(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels); + + /* This method can be used to read a partial raster line from the LCD: + * + * row - Starting row to read from (range: 0 <= row < yres) + * col - Starting column to read read (range: 0 <= col <= xres-npixels) + * buffer - The buffer in which to return the run read from the LCD + * npixels - The number of pixels to read from the LCD + * (range: 0 < npixels <= xres-col) + */ + + int (*getrun)(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels); + + /* Plane color characteristics ********************************************/ + + /* This is working memory allocated by the LCD driver for each LCD device + * and for each color plane. This memory will hold one raster line of data. + * The size of the allocated run buffer must therefore be at least + * (bpp * xres / 8). Actual alignment of the buffer must conform to the + * bitwidth of the underlying pixel type. + * + * If there are multiple planes, they may share the same working buffer + * because different planes will not be operate on concurrently. However, + * if there are multiple LCD devices, they must each have unique run buffers. + */ + + uint8_t *buffer; + + /* This is the number of bits in one pixel. This may be one of {1, 2, 4, + * 8, 16, 24, or 32} unless support for one or more of those resolutions + * has been disabled. + */ + + uint8_t bpp; +}; + +/* This structure defines an LCD interface */ + +struct lcd_dev_s +{ + /* LCD Configuration ******************************************************/ + /* Get information about the LCD video controller configuration and the + * configuration of each LCD color plane. + */ + + int (*getvideoinfo)(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo); + int (*getplaneinfo)(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo); + + /* LCD RGB Mapping ********************************************************/ + /* The following are provided only if the video hardware supports RGB color + * mapping + */ + +#ifdef CONFIG_FB_CMAP + int (*getcmap)(FAR struct lcd_dev_s *dev, FAR struct fb_cmap_s *cmap); + int (*putcmap)(FAR struct lcd_dev_s *dev, + FAR const struct fb_cmap_s *cmap); +#endif + + /* Cursor Controls ********************************************************/ + /* The following are provided only if the video hardware supports a + * hardware cursor + */ + +#ifdef CONFIG_FB_HWCURSOR + int (*getcursor)(FAR struct lcd_dev_s *dev, + FAR struct fb_cursorattrib_s *attrib); + int (*setcursor)(FAR struct lcd_dev_s *dev, + FAR struct fb_setcursor_s *settings); +#endif + + /* LCD Specific Controls **************************************************/ + /* Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER: full + * on). On backlit LCDs, this setting may correspond to the backlight + * setting. + */ + + int (*getpower)(struct lcd_dev_s *dev); + + /* Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full + * on). On backlit LCDs, this setting may correspond to the backlight + * setting. + */ + + int (*setpower)(struct lcd_dev_s *dev, int power); + + /* Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST) */ + + int (*getcontrast)(struct lcd_dev_s *dev); + + /* Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST) */ + + int (*setcontrast)(struct lcd_dev_s *dev, unsigned int contrast); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: up_lcdinitialize, up_lcdgetdev, up_lcduninitialize + * + * Description: + * If an architecture supports a parallel or serial LCD, then it must + * provide APIs to access the LCD as follows: + * + * up_lcdinitialize - Initialize the LCD video hardware. The initial + * state of the LCD is fully initialized, display + * memory cleared, and the LCD ready to use, but with + * the power setting at 0 (full off). + * up_lcdgetdev - Return a a reference to the LCD object for + * the specified LCD. This allows support for + * multiple LCD devices. + * up_lcduninitialize - Unitialize the LCD support + * + ***************************************************************************/ + +EXTERN int up_lcdinitialize(void); +EXTERN FAR struct lcd_dev_s *up_lcdgetdev(int lcddev); +EXTERN void up_lcduninitialize(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_LCD_H */ diff --git a/nuttx/include/nuttx/lcd/mio283qt2.h b/nuttx/include/nuttx/lcd/mio283qt2.h new file mode 100644 index 0000000000..0ae1c5fd72 --- /dev/null +++ b/nuttx/include/nuttx/lcd/mio283qt2.h @@ -0,0 +1,149 @@ +/************************************************************************************** + * include/nuttx/lcd/mio283qt2.h + * + * Interface definition for the MI0283QT-2 LCD from Multi-Inno Technology Co., Ltd. + * This LCD is based on the Himax HX8347-D LCD controller. + + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_LCD_MIO283QT2_H +#define __INCLUDE_NUTTX_LCD_MIO283QT2_H + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +#include + +#ifdef CONFIG_LCD_MIO283QT2 + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ +/* Configuration **********************************************************************/ +/* CONFIG_LCD_MIO283QT2 - Enables support for the MIO283QT2-based LCD. + * CONFIG_LCD_NOGETRUN + * NX components need to know if it can read from the LCD or not. If reading from the + * LCD is supported then some graphic operations can be improved. Default: Supported + * CONFIG_LCD_LANDSCAPE - Define for 320x240 display "landscape" support. Default is + * this 320x240 "landscape" orientation. + * CONFIG_LCD_RLANDSCAPE - Define for 320x240 display "reverse landscape" support. + * Default is this 320x240 "landscape" orientation + * CONFIG_LCD_PORTRAIT - Define for 240x320 display "portrait" orientation support. + * Default is this 320x240 "landscape" orientation + * CONFIG_LCD_RPORTRAIT - Define for 240x320 display "reverse portrait" orientation + * support. Default is this 320x240 "landscape" orientation + */ + +/************************************************************************************** + * Public Types + **************************************************************************************/ + +/* This structure defines the interface to the LCD provided by the platform. The + * nature of this interface is hidden from the MIO283QT2 driver. + */ + +struct mio283qt2_lcd_s +{ + /* Interface to write to a MIO283QT2 register. + * + * - select Select the device (as necessary). The meaning of selecting (and + * and deselecting) is not defined. select() will be called before + * starting any sequence of operations. deselect() when that sequence + * of operations is complete. + * - deselect Deselect the device (as necessary) + * - index Set register index + * - read Read data from the LCD (auto-incrementing) + * - write Write data to the LCD (auto-incrementing) + * - backlight Set the backlight power level (0=OFF; CONFIG_LCD_MAXPOWER=MAX) + */ + + void (*select)(FAR struct mio283qt2_lcd_s *dev); + void (*deselect)(FAR struct mio283qt2_lcd_s *dev); + void (*index)(FAR struct mio283qt2_lcd_s *dev, uint8_t index); +#ifndef CONFIG_LCD_NOGETRUN + uint16_t (*read)(FAR struct mio283qt2_lcd_s *dev); +#endif + void (*write)(FAR struct mio283qt2_lcd_s *dev, uint16_t value); + void (*backlight)(FAR struct mio283qt2_lcd_s *dev, int power); + + /* platform-specific data may follow */ +}; + +/************************************************************************************** + * Public Data + **************************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************** + * Public Function Prototypes + **************************************************************************************/ + +/************************************************************************************** + * Name: mio283qt2_lcdinitialize + * + * Description: + * Initialize the LCD video hardware. The initial state of the LCD is fully + * initialized, display memory cleared, and the LCD ready to use, but with the power + * setting at 0 (full off). + * + **************************************************************************************/ + +EXTERN FAR struct lcd_dev_s *mio283qt2_lcdinitialize(FAR struct mio283qt2_lcd_s *lcd); + +/************************************************************************************** + * Name: mio283qt2_clear + * + * Description: + * This is a non-standard LCD interface. Because of the various rotations, clearing + * the display in the normal way by writing a sequences of runs that covers the + * entire display can be very slow. Here the display is cleared by simply setting + * all GRAM memory to the specified color. + * + **************************************************************************************/ + +EXTERN void mio283qt2_clear(FAR struct lcd_dev_s *dev, uint16_t color); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_LCD_MIO283QT2 */ +#endif /* __INCLUDE_NUTTX_LCD_MIO283QT2_H */ \ No newline at end of file diff --git a/nuttx/include/nuttx/lcd/nokia6100.h b/nuttx/include/nuttx/lcd/nokia6100.h new file mode 100644 index 0000000000..0fb52a40d5 --- /dev/null +++ b/nuttx/include/nuttx/lcd/nokia6100.h @@ -0,0 +1,141 @@ +/**************************************************************************** + * include/nuttx/lcd/nokia6100.h + * Application interface to the Nokia 6100 LCD display + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NOKIA6100_H +#define __INCLUDE_NUTTX_NOKIA6100_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Nokia 6100 Configuration Settings: + * + * CONFIG_NOKIA6100_SPIMODE - Controls the SPI mode + * CONFIG_NOKIA6100_FREQUENCY - Define to use a different bus frequency + * CONFIG_NOKIA6100_NINTERFACES - Specifies the number of physical Nokia + * 6100 devices that will be supported. + * CONFIG_NOKIA6100_BPP - Device supports 8, 12, and 16 bits per pixel. + * CONFIG_NOKIA6100_S1D15G10 - Selects the Epson S1D15G10 display controller + * CONFIG_NOKIA6100_PCF8833 - Selects the Phillips PCF8833 display controller + * CONFIG_NOKIA6100_BLINIT - Initial backlight setting + * + * The following may need to be tuned for your hardware: + * CONFIG_NOKIA6100_INVERT - Display inversion, 0 or 1, Default: 1 + * CONFIG_NOKIA6100_MY - Display row direction, 0 or 1, Default: 0 + * CONFIG_NOKIA6100_MX - Display column direction, 0 or 1, Default: 1 + * CONFIG_NOKIA6100_V - Display address direction, 0 or 1, Default: 0 + * CONFIG_NOKIA6100_ML - Display scan direction, 0 or 1, Default: 0 + * CONFIG_NOKIA6100_RGBORD - Display RGB order, 0 or 1, Default: 0 + * + * Required LCD driver settings: + * CONFIG_LCD_NOKIA6100 - Enable Nokia 6100 support + * CONFIG_LCD_MAXCONTRAST - must be 63 with the Epson controller and 127 with + * the Phillips controller. + * CONFIG_LCD_MAXPOWER - Maximum value of backlight setting. The backlight + * control is managed outside of the 6100 driver so this value has no + * meaning to the driver. Board-specific logic may place restrictions on + * this value. + */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/************************************************************************************** + * Name: nokia_lcdinitialize + * + * Description: + * Initialize the NOKIA6100 video hardware. The initial state of the LCD is fully + * initialized, display memory cleared, and the LCD ready to use, but with the power + * setting at 0 (full off == sleep mode). + * + * Input Parameters: + * + * spi - A reference to the SPI driver instance. + * devno - A value in the range of 0 throuh CONFIG_NOKIA6100_NINTERFACES-1. This + * allows support for multiple LCD devices. + * + * Returned Value: + * + * On success, this function returns a reference to the LCD object for the specified + * LCD. NULL is returned on any failure. + * + **************************************************************************************/ + +struct lcd_dev_s; /* see nuttx/lcd.h */ +struct spi_dev_s; /* see nuttx/spi.h */ +EXTERN FAR struct lcd_dev_s *nokia_lcdinitialize(FAR struct spi_dev_s *spi, unsigned int devno); + +/************************************************************************************** + * Name: nokia_backlight + * + * Description: + * The Nokia 6100 backlight is controlled by logic outside of the LCD assembly. This + * function must be provided by board specific logic to manage the backlight. This + * function will receive a power value (0: full off - CONFIG_LCD_MAXPOWER: full on) + * and should set the backlight accordingly. + * + **************************************************************************************/ + +EXTERN int nokia_backlight(unsigned int power); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_NOKIA6100_H */ diff --git a/nuttx/include/nuttx/lcd/p14201.h b/nuttx/include/nuttx/lcd/p14201.h new file mode 100644 index 0000000000..741d4f3de2 --- /dev/null +++ b/nuttx/include/nuttx/lcd/p14201.h @@ -0,0 +1,129 @@ +/**************************************************************************** + * include/nuttx/lcd/p14201.h + * Application interface to the RiT P14201 OLED driver + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_P14201_H +#define __INCLUDE_NUTTX_P14201_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* P14201 Configuration Settings: + * + * CONFIG_P14201_SPIMODE - Controls the SPI mode + * CONFIG_P14201_FREQUENCY - Define to use a different bus frequency + * CONFIG_P14201_NINTERFACES - Specifies the number of physical P14201 devices that + * will be supported. + * CONFIG_P14201_FRAMEBUFFER - If defined, accesses will be performed using an in-memory + * copy of the OLEDs GDDRAM. This cost of this buffer is 128 * 96 / 2 = 6Kb. If this + * is defined, then the driver will be fully functional. If not, then it will have the + * following limitations: + * + * - Reading graphics memory cannot be supported, and + * - All pixel writes must be aligned to byte boundaries. + * + * The latter limitation effectively reduces the 128x96 disply to 64x96. + * + * Required LCD driver settings: + * CONFIG_LCD_P14201 - Enable P14201 support + * CONFIG_LCD_MAXCONTRAST should be 255, but any value >0 and <=255 will be accepted. + * CONFIG_LCD_MAXPOWER must be 1 + * + * Required SPI driver settings: + * CONFIG_SPI_CMDDATA - Include support for cmd/data selection. + */ + +/* Some important "colors" */ + +#define RIT_Y4_BLACK 0x00 +#define RIT_Y4_WHITE 0x0f + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/************************************************************************************** + * Name: rit_initialize + * + * Description: + * Initialize the P14201 video hardware. The initial state of the OLED is fully + * initialized, display memory cleared, and the OLED ready to use, but with the power + * setting at 0 (full off == sleep mode). + * + * Input Parameters: + * + * spi - A reference to the SPI driver instance. + * devno - A value in the range of 0 throuh CONFIG_P14201_NINTERFACES-1. This allows + * support for multiple OLED devices. + * + * Returned Value: + * + * On success, this function returns a reference to the LCD object for the specified + * OLED. NULL is returned on any failure. + * + **************************************************************************************/ + +struct lcd_dev_s; /* see nuttx/lcd.h */ +struct spi_dev_s; /* see nuttx/spi.h */ +EXTERN FAR struct lcd_dev_s *rit_initialize(FAR struct spi_dev_s *spi, unsigned int devno); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_P14201_H */ diff --git a/nuttx/include/nuttx/lcd/ssd1289.h b/nuttx/include/nuttx/lcd/ssd1289.h new file mode 100644 index 0000000000..5a113c09f3 --- /dev/null +++ b/nuttx/include/nuttx/lcd/ssd1289.h @@ -0,0 +1,149 @@ +/************************************************************************************** + * include/nuttx/lcd/ssd1289.h + * Definitions for the Solomon Systech SSD1289 LCD controller + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: SSD1289, Rev 1.3, Apr 2007, Solomon Systech Limited + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_LCD_SSD1289_H +#define __INCLUDE_NUTTX_LCD_SSD1289_H + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +#include + +#ifdef CONFIG_LCD_SSD1289 + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ +/* Configuration **********************************************************************/ +/* CONFIG_LCD_SSD1289 - Enables support for the SSD1289-based LCD. + * CONFIG_LCD_NOGETRUN + * NX components need to know if it can read from the LCD or not. If reading from the + * LCD is supported then some graphic operations can be improved. Default: Supported + * CONFIG_LCD_LANDSCAPE - Define for 320x240 display "landscape" support. Default is + * this 320x240 "landscape" orientation. + * CONFIG_LCD_RLANDSCAPE - Define for 320x240 display "reverse landscape" support. + * Default is this 320x240 "landscape" orientation + * CONFIG_LCD_PORTRAIT - Define for 240x320 display "portrait" orientation support. + * Default is this 320x240 "landscape" orientation + * CONFIG_LCD_RPORTRAIT - Define for 240x320 display "reverse portrait" orientation + * support. Default is this 320x240 "landscape" orientation + */ + +/************************************************************************************** + * Public Types + **************************************************************************************/ + +/* This structure defines the interface to the LCD provided by the platform. The + * nature of this interface is hidden from the SSD1289 driver. + */ + +struct ssd1289_lcd_s +{ + /* Interface to write to a SSD1289 register. + * + * - select Select the device (as necessary). The meaning of selecting (and + * and deselecting) is not defined. select() will be called before + * starting any sequence of operations. deselect() when that sequence + * of operations is complete. + * - deselect Deselect the device (as necessary) + * - index Set register index + * - read Read data from the LCD (auto-incrementing) + * - write Write data to the LCD (auto-incrementing) + * - backlight Set the backlight power level (0=OFF; CONFIG_LCD_MAXPOWER=MAX) + */ + + void (*select)(FAR struct ssd1289_lcd_s *dev); + void (*deselect)(FAR struct ssd1289_lcd_s *dev); + void (*index)(FAR struct ssd1289_lcd_s *dev, uint8_t index); +#ifndef CONFIG_LCD_NOGETRUN + uint16_t (*read)(FAR struct ssd1289_lcd_s *dev); +#endif + void (*write)(FAR struct ssd1289_lcd_s *dev, uint16_t value); + void (*backlight)(FAR struct ssd1289_lcd_s *dev, int power); + + /* platform-specific data may follow */ +}; + +/************************************************************************************** + * Public Data + **************************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************** + * Public Function Prototypes + **************************************************************************************/ + +/************************************************************************************** + * Name: ssd1289_lcdinitialize + * + * Description: + * Initialize the LCD video hardware. The initial state of the LCD is fully + * initialized, display memory cleared, and the LCD ready to use, but with the power + * setting at 0 (full off). + * + **************************************************************************************/ + +EXTERN FAR struct lcd_dev_s *ssd1289_lcdinitialize(FAR struct ssd1289_lcd_s *lcd); + +/************************************************************************************** + * Name: ssd1289_clear + * + * Description: + * This is a non-standard LCD interface. Because of the various rotations, clearing + * the display in the normal way by writing a sequences of runs that covers the + * entire display can be very slow. Here the display is cleared by simply setting + * all GRAM memory to the specified color. + * + **************************************************************************************/ + +EXTERN void ssd1289_clear(FAR struct lcd_dev_s *dev, uint16_t color); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_LCD_SSD1289 */ +#endif /* __INCLUDE_NUTTX_LCD_SSD1289_H */ \ No newline at end of file diff --git a/nuttx/include/nuttx/lcd/ug-9664hswag01.h b/nuttx/include/nuttx/lcd/ug-9664hswag01.h new file mode 100644 index 0000000000..696005b5d0 --- /dev/null +++ b/nuttx/include/nuttx/lcd/ug-9664hswag01.h @@ -0,0 +1,158 @@ +/**************************************************************************** + * include/nuttx/lcd/ug-9664hswag01.h + * Driver for the Univision UG-9664HSWAG01 Display with the Solomon Systech + * SSD1305 LCD controller. + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_UG_9664HSWAG01_H +#define __INCLUDE_NUTTX_UG_9664HSWAG01_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* UG-9664HSWAG01 Configuration Settings: + * + * CONFIG_UG9664HSWAG01_SPIMODE - Controls the SPI mode + * CONFIG_UG9664HSWAG01_FREQUENCY - Define to use a different bus frequency + * CONFIG_UG9664HSWAG01_NINTERFACES - Specifies the number of physical + * UG-9664HSWAG01 devices that will be supported. NOTE: At present, this + * must be undefined or defined to be 1. + * CONFIG_UG9664HSWAG01_POWER + * If the hardware supports a controllable OLED a power supply, this + * configuration shold be defined. (See ug_power() below). + * CONFIG_LCD_UGDEBUG - Enable detailed UG-9664HSWAG01 debug output + * (CONFIG_DEBUG and CONFIG_VERBOSE must also be enabled). + * + * Required LCD driver settings: + * CONFIG_LCD_UG9664HSWAG01 - Enable UG-9664HSWAG01 support + * CONFIG_LCD_MAXCONTRAST should be 255, but any value >0 and <=255 will be accepted. + * CONFIG_LCD_MAXPOWER should be 2: 0=off, 1=dim, 2=normal + * + * Required SPI driver settings: + * CONFIG_SPI_CMDDATA - Include support for cmd/data selection. + */ + +/* Some important "colors" */ + +#define UG_Y1_BLACK 0 +#define UG_Y1_WHITE 1 + +/* Only three power settings are supported: */ + +#define UG_POWER_OFF 0 +#define UG_POWER_DIM 1 +#define UG_POWER_ON 2 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ug_initialize + * + * Description: + * Initialize the UG-9664HSWAG01 video hardware. The initial state of the + * OLED is fully initialized, display memory cleared, and the OLED ready + * to use, but with the power setting at 0 (full off == sleep mode). + * + * Input Parameters: + * + * spi - A reference to the SPI driver instance. + * devno - A value in the range of 0 through CONFIG_UG9664HSWAG01_NINTERFACES-1. + * This allows support for multiple OLED devices. + * + * Returned Value: + * + * On success, this function returns a reference to the LCD object for + * the specified OLED. NULL is returned on any failure. + * + ****************************************************************************/ + +struct lcd_dev_s; /* see nuttx/lcd.h */ +struct spi_dev_s; /* see nuttx/spi.h */ +EXTERN FAR struct lcd_dev_s *ug_initialize(FAR struct spi_dev_s *spi, unsigned int devno); + +/**************************************************************************** + * Name: ug_power + * + * Description: + * If the hardware supports a controllable OLED a power supply, this + * interface should be provided. It may be called by the driver to turn + * the OLED power on and off as needed. + * + * Input Parameters: + * + * devno - A value in the range of 0 throuh CONFIG_UG9664HSWAG01_NINTERFACES-1. + * This allows support for multiple OLED devices. + * on - true:turn power on, false: turn power off. + * + * Returned Value: + * None + * + **************************************************************************************/ + +#ifdef CONFIG_UG9664HSWAG01_POWER +EXTERN void ug_power(unsigned int devno, bool on); +#else +# define ug_power(a,b) +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_UG_9664HSWAG01_H */ diff --git a/nuttx/include/nuttx/lib.h b/nuttx/include/nuttx/lib.h new file mode 100644 index 0000000000..220af20304 --- /dev/null +++ b/nuttx/include/nuttx/lib.h @@ -0,0 +1,83 @@ +/**************************************************************************** + * include/nuttx/lib.h + * Non-standard, internal APIs available in lib/. + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_LIB_H +#define __INCLUDE_NUTTX_LIB_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Functions contained in lib_init.c ****************************************/ + +EXTERN void weak_function lib_initialize(void); +#if CONFIG_NFILE_STREAMS > 0 +EXTERN FAR struct streamlist *lib_alloclist(void); +EXTERN void lib_addreflist(FAR struct streamlist *list); +EXTERN void lib_releaselist(FAR struct streamlist *list); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __INCLUDE_NUTTX_LIB_H */ diff --git a/nuttx/include/nuttx/math.h b/nuttx/include/nuttx/math.h new file mode 100644 index 0000000000..84dbea6e03 --- /dev/null +++ b/nuttx/include/nuttx/math.h @@ -0,0 +1,63 @@ +/**************************************************************************** + * include/nuttx/math.h + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_MATH_H +#define __INCLUDE_NUTTX_MATH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* If CONFIG_ARCH_MATH_H is defined, then the top-level Makefile will copy + * this header file to include/math.h where it will become the system math.h + * header file. In this case, the architecture specific code must provide + * an arch//include/math.h file which will be included below: + */ + +#ifdef CONFIG_ARCH_MATH_H +# include +#endif + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __INCLUDE_NUTTX_MATH_H */ diff --git a/nuttx/include/nuttx/mm.h b/nuttx/include/nuttx/mm.h new file mode 100644 index 0000000000..cabab2619d --- /dev/null +++ b/nuttx/include/nuttx/mm.h @@ -0,0 +1,84 @@ +/**************************************************************************** + * include/nuttx/mm.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_MM_H +#define __INCLUDE_NUTTX_MM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Data + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Functions contained in mm_initialize.c ***********************************/ + +EXTERN void mm_initialize(FAR void *heap_start, size_t heap_size); +EXTERN void mm_addregion(FAR void *heapstart, size_t heapsize); + +/* Functions contained in mm_sem.c ******************************************/ + +EXTERN int mm_trysemaphore(void); +EXTERN void mm_givesemaphore(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_MM_H */ diff --git a/nuttx/include/nuttx/mmcsd.h b/nuttx/include/nuttx/mmcsd.h new file mode 100644 index 0000000000..819613ede1 --- /dev/null +++ b/nuttx/include/nuttx/mmcsd.h @@ -0,0 +1,107 @@ +/**************************************************************************** + * include/nuttx/mmcsd.h + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_MMCSD_H +#define __INCLUDE_NUTTX_MMCSD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: mmcsd_slotinitialize + * + * Description: + * Initialize one slot for operation using the MMC/SD interface + * + * Input Parameters: + * minor - The MMC/SD minor device number. The MMC/SD device will be + * registered as /dev/mmcsdN where N is the minor number + * dev - And instance of an MMC/SD interface. The MMC/SD hardware should + * be initialized and ready to use. + * + ****************************************************************************/ + +struct sdio_dev_s; /* See nuttx/sdio.h */ +EXTERN int mmcsd_slotinitialize(int minor, FAR struct sdio_dev_s *dev); + +/**************************************************************************** + * Name: mmcsd_spislotinitialize + * + * Description: + * Initialize one slot for operation using the SPI MMC/SD interface + * + * Input Parameters: + * minor - The MMC/SD minor device number. The MMC/SD device will be + * registered as /dev/mmcsdN where N is the minor number + * slotno - The slot number to use. This is only meaningful for architectures + * that support multiple MMC/SD slots. This value must be in the range + * {0, ..., CONFIG_MMCSD_NSLOTS}. + * spi - And instance of an SPI interface obtained by called + * up_spiinitialize() with the appropriate port number (see spi.h) + * + ****************************************************************************/ + +struct spi_dev_s; /* See nuttx/spi.h */ +EXTERN int mmcsd_spislotinitialize(int minor, int slotno, FAR struct spi_dev_s *spi); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_MMCSD_H */ diff --git a/nuttx/include/nuttx/mqueue.h b/nuttx/include/nuttx/mqueue.h new file mode 100644 index 0000000000..43c0aab6e0 --- /dev/null +++ b/nuttx/include/nuttx/mqueue.h @@ -0,0 +1,124 @@ +/**************************************************************************** + * include/nuttx/mqueue.h + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef ___INCLUDE_NUTTX_MQUEUE_H +#define ___INCLUDE_NUTTX_MQUEUE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#if CONFIG_MQ_MAXMSGSIZE > 0 + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Type Declarations + ****************************************************************************/ + +/* This structure defines a message queue */ + +struct mq_des; /* forward reference */ + +struct msgq_s +{ + FAR struct msgq_s *flink; /* Forward link to next message queue */ + sq_queue_t msglist; /* Prioritized message list */ + int16_t maxmsgs; /* Maximum number of messages in the queue */ + int16_t nmsgs; /* Number of message in the queue */ + int16_t nconnect; /* Number of connections to message queue */ + int16_t nwaitnotfull; /* Number tasks waiting for not full */ + int16_t nwaitnotempty; /* Number tasks waiting for not empty */ + uint8_t maxmsgsize; /* Max size of message in message queue */ + bool unlinked; /* true if the msg queue has been unlinked */ +#ifndef CONFIG_DISABLE_SIGNALS + FAR struct mq_des *ntmqdes; /* Notification: Owning mqdes (NULL if none) */ + pid_t ntpid; /* Notification: Receiving Task's PID */ + int ntsigno; /* Notification: Signal number */ + union sigval ntvalue; /* Notification: Signal value */ +#endif + char name[1]; /* Start of the queue name */ +}; + +typedef struct msgq_s msgq_t; + +#define SIZEOF_MQ_HEADER ((int)(((msgq_t*)NULL)->name)) + +/* This describes the message queue descriptor that is held in the + * task's TCB + */ + +struct mq_des +{ + FAR struct mq_des *flink; /* Forward link to next message descriptor */ + FAR msgq_t *msgq; /* Pointer to associated message queue */ + int oflags; /* Flags set when message queue was opened */ +}; + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_MQ_MAXMSGSIZE > 0 */ +#endif /* ___INCLUDE_NUTTX_MQUEUE_H */ + diff --git a/nuttx/include/nuttx/mtd.h b/nuttx/include/nuttx/mtd.h new file mode 100644 index 0000000000..5b955a45f4 --- /dev/null +++ b/nuttx/include/nuttx/mtd.h @@ -0,0 +1,229 @@ +/**************************************************************************** + * include/nuttx/mtd.h + * Memory Technology Device (MTD) interface + * + * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_MTD_H +#define __INCLUDE_NUTTX_MTD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Macros to hide implementation */ + +#define MTD_ERASE(d,s,n) ((d)->erase ? (d)->erase(d,s,n) : (-ENOSYS)) +#define MTD_BREAD(d,s,n,b) ((d)->bread ? (d)->bread(d,s,n,b) : (-ENOSYS)) +#define MTD_READ(d,s,n,b) ((d)->read ? (d)->read(d,s,n,b) : (-ENOSYS)) +#define MTD_BWRITE(d,s,n,b)((d)->bwrite ? (d)->bwrite(d,s,n,b) : (-ENOSYS)) +#define MTD_IOCTL(d,c,a) ((d)->ioctl ? (d)->ioctl(d,c,a) : (-ENOSYS)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The following defines the geometry for the device. It treats the device + * as though it where just an array of fixed size blocks. That is most likely + * not true, but the client will expect the device logic to do whatever is + * necessary to make it appear so. + */ + +struct mtd_geometry_s +{ + uint16_t blocksize; /* Size of one read/write block */ + uint16_t erasesize; /* Size of one erase blocks -- must be a multiple + * of blocksize. */ + size_t neraseblocks; /* Number of erase blocks */ +}; + +/* This structure defines the interface to a simple memory technology device. + * It will likely need to be extended in the future to support more complex + * devices. + */ + +struct mtd_dev_s +{ + /* The following methods operate on the MTD: */ + + /* Erase the specified erase blocks (units are erase blocks) */ + + int (*erase)(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks); + + /* Read/write from the specified read/write blocks */ + + ssize_t (*bread)(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR uint8_t *buffer); + ssize_t (*bwrite)(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, + FAR const uint8_t *buffer); + + /* Some devices may support byte oriented reads (optional). Most MTD devices + * are inherently block oriented so byte-oriented writing is not supported. It + * is recommended that low-level drivers not support read() if it requires + * buffering. + */ + + ssize_t (*read)(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes, + FAR uint8_t *buffer); + + /* Support other, less frequently used commands: + * - MTDIOC_GEOMETRY: Get MTD geometry + * - MTDIOC_XIPBASE: Convert block to physical address for eXecute-In-Place + * - MTDIOC_BULKERASE: Erase the entire device + * (see include/nuttx/fs/ioctl.h) + */ + + int (*ioctl)(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg); +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ftl_initialize + * + * Description: + * Initialize to provide a block driver wrapper around an MTD interface + * + * Input Parameters: + * minor - The minor device number. The MTD block device will be + * registered as as /dev/mtdblockN where N is the minor number. + * mtd - The MTD device that supports the FLASH interface. + * + ****************************************************************************/ + +EXTERN int ftl_initialize(int minor, FAR struct mtd_dev_s *mtd); + +/**************************************************************************** + * Name: flash_eraseall + * + * Description: + * Call a block driver with the MDIOC_BULKERASE ioctl command. This will + * cause the MTD driver to erase all of the flash. + * + ****************************************************************************/ + +EXTERN int flash_eraseall(FAR const char *driver); + +/**************************************************************************** + * Name: rammtd_initialize + * + * Description: + * Create and initialize a RAM MTD device instance. + * + * Input Parameters: + * start - Address of the beginning of the allocated RAM regions. + * size - The size in bytes of the allocated RAM region. + * + ****************************************************************************/ + +EXTERN FAR struct mtd_dev_s *rammtd_initialize(FAR uint8_t *start, size_t size); + +/**************************************************************************** + * Name: m25p_initialize + * + * Description: + * Create an initialized MTD device instance. MTD devices are not registered + * in the file system, but are created as instances that can be bound to + * other functions (such as a block or character driver front end). + * + ****************************************************************************/ + +EXTERN FAR struct mtd_dev_s *m25p_initialize(FAR struct spi_dev_s *dev); + +/**************************************************************************** + * Name: at45db_initialize + * + * Description: + * Create an initialized MTD device instance. MTD devices are not registered + * in the file system, but are created as instances that can be bound to + * other functions (such as a block or character driver front end). + * + ****************************************************************************/ + +EXTERN FAR struct mtd_dev_s *at45db_initialize(FAR struct spi_dev_s *dev); + +/**************************************************************************** + * Name: at24c_initialize + * + * Description: + * Create an initialized MTD device instance. MTD devices are not registered + * in the file system, but are created as instances that can be bound to + * other functions (such as a block or character driver front end). + * + ****************************************************************************/ + +EXTERN FAR struct mtd_dev_s *at24c_initialize(FAR struct i2c_dev_s *dev); + +/**************************************************************************** + * Name: sst25_initialize + * + * Description: + * Create an initialized MTD device instance. MTD devices are not registered + * in the file system, but are created as instances that can be bound to + * other functions (such as a block or character driver front end). + * + ****************************************************************************/ + +EXTERN FAR struct mtd_dev_s *sst25_initialize(FAR struct spi_dev_s *dev); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __INCLUDE_NUTTX_MTD_H */ diff --git a/nuttx/include/nuttx/net/cs89x0.h b/nuttx/include/nuttx/net/cs89x0.h new file mode 100644 index 0000000000..4b2a52a5c9 --- /dev/null +++ b/nuttx/include/nuttx/net/cs89x0.h @@ -0,0 +1,168 @@ +/**************************************************************************** + * include/nuttx/net/cs89x0.h + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_CS89x0_H +#define __INCLUDE_NUTTX_NET_CS89x0_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This structure returns driver statistics (if enabled) */ + +#ifdef CONFIG_C89x0_STATISTICS +struct cs89x0_statistics_s +{ + uint32_t tx_packets; + uint32_t tx_errors; + uint32_t tx_carriererrors; + uint32_t tx_heartbeaterrors; + uint32_t tx_windowerrors; + uint32_t tx_abortederrors; + uint32_t rx_missederrors; + uint32_t rx_packets; + uint32_t rx_errors; + uint32_t rx_lengtherrors; + uint32_t rx_crcerrors; + uint32_t rx_frameerrors; + uint32_t rx_dropped; + uint32_t rx_missederrors; + uint32_t collisions; +}; +#endif + +/* This structure encapsulates all state information for a single hardware + * interface. It includes values that must be provided by the user to in + * to describe details of the CS89x00 implementation on a particular board. + * An instance if this structure is passed to cs89x00 to instantiate the + * driver. + * + * This structure also includes internal driver state information that should + * be of no concern to the caller of cs89x0_initialize(). These fields must + * be zeroed. + */ + +struct cs89x0_driver_s +{ + /* User-provided CS89x00 platform-specific implementation details. The + * caller of cs89x0_initialize() must provide all of these values. + */ + + FAR void *cs_base; /* CS89x0 region base address */ +#ifdef CONFIG_CS89x0_MEMMODE + FAR void *cs_ppbase; /* CS89x0 page packet base address */ +#endif + uint8_t cs_irq; /* CS89x00 IRQ number */ + + /* Driver internal state fields. These must be zeroed by before the + * instance of this structure is passed to cs89x0_initialize + */ +#ifdef CONFIG_CS89x0_XMITEARLY + uint8_t txstart; /* Bits 6-7 of TxCMD controls Tx race */ +#endif + bool cs_memmode; /* true:memory mode false: I/O mode */ + bool cs_bifup; /* true:ifup false:ifdown */ + WDOG_ID cs_txpoll; /* TX poll timer */ + WDOG_ID cs_txtimeout; /* TX timeout timer */ +#ifdef CONFIG_CS89x0_XMITEARLY + uint32_t cs_txunderrun; /* Count of Tx underrun errors */ +#endif + + /* This holds the information visible to uIP/NuttX */ + + struct uip_driver_s cs_dev; /* Interface understood by uIP */ + + /* Driver statistics */ + +#ifdef CONFIG_C89x0_STATISTICS + struct cs89x0_statistics_s cs_stats; +#endif +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Function: cs89x0_initialize + * + * Description: + * Initialize the Ethernet driver + * + * Parameters: + * impl - decribes the implementation of the cs89x00 implementation. + * This reference is retained so so must remain stable throughout the + * life of the driver instance. + * devno - Identifies the device number. This must be a number between + * zero CONFIG_CS89x0_NINTERFACES and the same devno must not be + * initialized twice. The associated network device will be referred + * to with the name "eth" followed by this number (eth0, eth1, etc). + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +/* Initialize the CS89x0 chip and driver */ + +EXTERN int cs89x0_initialize(FAR const cs89x0_driver_s *cs89x0, int devno); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_NET_CS89x0_H */ diff --git a/nuttx/include/nuttx/net/enc28j60.h b/nuttx/include/nuttx/net/enc28j60.h new file mode 100644 index 0000000000..2507b1cf60 --- /dev/null +++ b/nuttx/include/nuttx/net/enc28j60.h @@ -0,0 +1,151 @@ +/**************************************************************************** + * include/nuttx/net/enc28j60.h + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_ENC28J60_H +#define __INCLUDE_NUTTX_NET_ENC28J60_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* ENC28J60 Configuration Settings: + * + * CONFIG_NET_ENC28J60 - Enabled ENC28J60 support + * CONFIG_ENC28J60_SPIMODE - Controls the SPI mode + * CONFIG_ENC28J60_FREQUENCY - Define to use a different bus frequency + * CONFIG_ENC28J60_NINTERFACES - Specifies the number of physical ENC28J60 + * devices that will be supported. + * CONFIG_ENC28J60_STATS - Collect network statistics + * CONFIG_ENC28J60_HALFDUPPLEX - Default is full duplex + */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This structure returns driver statistics (if enabled) */ + +#ifdef CONFIG_ENC28J60_STATS +struct enc_stats_s +{ + uint8_t maxpktcnt; /* Max. number of buffered RX packets */ + uint32_t txrequests; /* Number of TX packets queued */ + uint32_t txifs; /* TXIF completion events */ + uint32_t txabrts; /* TXIF completions with ESTAT.TXABRT */ + uint32_t txerifs; /* TXERIF error events */ + uint32_t txtimeouts; /* S/W detected TX timeouts */ + uint32_t pktifs; /* PKTIF RX completion events */ + uint32_t rxnotok; /* PKTIF without RXSTAT_OK */ + uint32_t rxpktlen; /* PKTIF with bad pktlen */ + uint32_t rxerifs; /* RXERIF error evernts */ +}; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Function: enc_initialize + * + * Description: + * Initialize the Ethernet driver. The ENC28J60 device is assumed to be + * in the post-reset state upon entry to this function. + * + * Parameters: + * spi - A reference to the platform's SPI driver for the ENC28J60 + * devno - If more than one ENC28J60 is supported, then this is the + * zero based number that identifies the ENC28J60; + * irq - The fully configured GPIO IRQ that ENC28J60 interrupts will be + * asserted on. This driver will attach and entable this IRQ. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +struct spi_dev_s; /* see nuttx/spi.h */ +EXTERN int enc_initialize(FAR struct spi_dev_s *spi, unsigned int devno, + unsigned int irq); + +/**************************************************************************** + * Function: enc_stats + * + * Description: + * Return accumulated ENC28J60 statistics. Statistics are cleared after + * being returned. + * + * Parameters: + * devno - If more than one ENC28J60 is supported, then this is the + * zero based number that identifies the ENC28J60; + * stats - The user-provided location to return the statistics. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_ENC28J60_STATS +EXTERN int enc_stats(unsigned int devno, struct enc_stats_s *stats); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_NET_ENC28J60_H */ diff --git a/nuttx/include/nuttx/net/ioctl.h b/nuttx/include/nuttx/net/ioctl.h new file mode 100644 index 0000000000..5bce5eaf1c --- /dev/null +++ b/nuttx/include/nuttx/net/ioctl.h @@ -0,0 +1,157 @@ +/**************************************************************************** + * include/nuttx/net/ioctl.h + * + * Copyright (C) 2007-2008, 2010-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_IOCTL_H +#define __INCLUDE_NUTTX_NET_IOCTL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include /* _SIOCBASE, etc. */ + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* These are ioctl commands to use with a socket FD. At present, commands + * are accepted only to set/get IP addresses, broadcast address, network + * masks, and hardware address, and a few others + */ + +#define _SIOCVALID(c) (_IOC_TYPE(c)==_SIOCBASE) +#define _SIOC(nr) _IOC(_SIOCBASE,nr) + +#define SIOCGIFADDR _SIOC(0x0001) /* Get IP address */ +#define SIOCSIFADDR _SIOC(0x0002) /* Set IP address */ +#define SIOCGIFDSTADDR _SIOC(0x0003) /* Get P-to-P address */ +#define SIOCSIFDSTADDR _SIOC(0x0004) /* Set P-to-P address */ +#define SIOCGIFBRDADDR _SIOC(0x0005) /* Get broadcast IP address */ +#define SIOCSIFBRDADDR _SIOC(0x0006) /* Set broadcast IP address */ +#define SIOCGIFNETMASK _SIOC(0x0007) /* Get network mask */ +#define SIOCSIFNETMASK _SIOC(0x0008) /* Set network mask */ +#define SIOCGIFMTU _SIOC(0x0009) /* Get MTU size */ +#define SIOCGIFHWADDR _SIOC(0x000a) /* Get hardware address */ +#define SIOCSIFHWADDR _SIOC(0x000b) /* Set hardware address */ +#define SIOCDIFADDR _SIOC(0x000c) /* Delete IP address */ +#define SIOCGIFCOUNT _SIOC(0x000d) /* Get number of devices */ + +#define SIOCGIPMSFILTER _SIOC(0x000e) /* Retrieve source filter addresses */ +#define SIOCSIPMSFILTER _SIOC(0x000f) /* Set source filter content */ + +/* Newer interface ioctls that use the struct lifreq. Can be used for + * both IPv4 and IPv6. + */ + +#define SIOCGLIFADDR SIOCGIFADDR /* Get IP address */ +#define SIOCSLIFADDR SIOCSIFADDR /* Set IP address */ +#define SIOCGLIFDSTADDR SIOCSIFDSTADDR /* Get P-to-P address */ +#define SIOCSLIFDSTADDR SIOCSIFDSTADDR /* Set P-to-P address */ +#define SIOCGLIFBRDADDR SIOCGIFBRDADDR /* Get broadcast IP address */ +#define SIOCSLIFBRDADDR SIOCSIFBRDADDR /* Set broadcast IP address */ +#define SIOCGLIFNETMASK SIOCGIFNETMASK /* Get network mask */ +#define SIOCSLIFNETMASK SIOCSIFNETMASK /* Set network mask */ +#define SIOCGLIFMTU SIOCGIFMTU /* Get MTU size */ + +/* Wireless ioctl commands **************************************************/ + +#define SIOCSIWCOMMIT _SIOC(0x0010) /* Commit pending changes to driver */ +#define SIOCGIWNAME _SIOC(0x0011) /* Get name of wireless protocol */ + +#define SIOCSIWNWID _SIOC(0x0012) /* Set network ID (pre-802.11) */ +#define SIOCGIWNWID _SIOC(0x0013) /* Get network ID (the cell) */ +#define SIOCSIWFREQ _SIOC(0x0014) /* Set channel/frequency (Hz) */ +#define SIOCGIWFREQ _SIOC(0x0015) /* Get channel/frequency (Hz) */ +#define SIOCSIWMODE _SIOC(0x0016) /* Set operation mode */ +#define SIOCGIWMODE _SIOC(0x0017) /* Get operation mode */ +#define SIOCSIWSENS _SIOC(0x0018) /* Set sensitivity (dBm) */ +#define SIOCGIWSENS _SIOC(0x0019) /* Get sensitivity (dBm) */ + +#define SIOCGIWRANGE _SIOC(0x001a) /* Get range of parameters */ +#define SIOCGIWPRIV _SIOC(0x001b) /* Get private ioctl interface info */ +#define SIOCGIWSTATS _SIOC(0x001c) /* Get wireless stats */ + +#define SIOCSIWSPY _SIOC(0x001d) /* Set spy addresses */ +#define SIOCGIWSPY _SIOC(0x001e) /* Get spy info (quality of link) */ +#define SIOCSIWTHRSPY _SIOC(0x001f) /* Set spy threshold (spy event) */ +#define SIOCGIWTHRSPY _SIOC(0x0020) /* Get spy threshold */ + +#define SIOCSIWAP _SIOC(0x0021) /* Set access point MAC addresses */ +#define SIOCGIWAP _SIOC(0x0022) /* Get access point MAC addresses */ +#define SIOCGIWAPLIST _SIOC(0x0023) /* Deprecated in favor of scanning */ +#define SIOCSIWSCAN _SIOC(0x0024) /* Trigger scanning (list cells) */ +#define SIOCGIWSCAN _SIOC(0x0025) /* Get scanning results */ + +#define SIOCSIWESSID _SIOC(0x0026) /* Set ESSID (network name) */ +#define SIOCGIWESSID _SIOC(0x0027) /* Get ESSID */ +#define SIOCSIWNICKN _SIOC(0x0028) /* Set node name/nickname */ +#define SIOCGIWNICKN _SIOC(0x0029) /* Get node name/nickname */ + +#define SIOCSIWRATE _SIOC(0x002a) /* Set default bit rate (bps) */ +#define SIOCGIWRATE _SIOC(0x002b) /* Get default bit rate (bps) */ +#define SIOCSIWRTS _SIOC(0x002c) /* Set RTS/CTS threshold (bytes) */ +#define SIOCGIWRTS _SIOC(0x002d) /* Get RTS/CTS threshold (bytes) */ +#define SIOCSIWFRAG _SIOC(0x002e) /* Set fragmentation thr (bytes) */ +#define SIOCGIWFRAG _SIOC(0x002f) /* Get fragmentation thr (bytes) */ +#define SIOCSIWTXPOW _SIOC(0x0030) /* Set transmit power (dBm) */ +#define SIOCGIWTXPOW _SIOC(0x0031) /* Get transmit power (dBm) */ +#define SIOCSIWRETRY _SIOC(0x0032) /* Set retry limits and lifetime */ +#define SIOCGIWRETRY _SIOC(0x0033) /* Get retry limits and lifetime */ + +#define SIOCSIWPOWER _SIOC(0x0034) /* Set Power Management settings */ +#define SIOCGIWPOWER _SIOC(0x0035) /* Get Power Management settings */ + +#define SIOCSIWGENIE _SIOC(0x0030) /* Set generic IE */ +#define SIOCGIWGENIE _SIOC(0x0031) /* Get generic IE */ + +#define SIOCSIWMLME _SIOC(0x0016) /* Request MLME operation */ + +#define SIOCSIWAUTH _SIOC(0x0032) /* Set authentication mode params */ +#define SIOCGIWAUTH _SIOC(0x0033) /* Get authentication mode params */ + +#define SIOCSIWENCODEEXT _SIOC(0x0034) /* Set encoding token & mode */ +#define SIOCGIWENCODEEXT _SIOC(0x0035) /* Get encoding token & mode */ + +#define SIOCSIWPMKSA _SIOC(0x0036) /* PMKSA cache operation */ + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __INCLUDE_NUTTX_NET_IOCTL_H */ diff --git a/nuttx/include/nuttx/net/mii.h b/nuttx/include/nuttx/net/mii.h new file mode 100644 index 0000000000..6a5fc6e896 --- /dev/null +++ b/nuttx/include/nuttx/net/mii.h @@ -0,0 +1,474 @@ +/**************************************************************************** + * include/nuttx/net/mii.h + * + * Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_MII_H +#define __INCLUDE_NUTTX_NET_MII_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* MII register offsets *****************************************************/ + +/* Common MII management registers. The IEEE 802.3 standard specifies a + * register set for controlling and gathering status from the PHY layer. The + * registers are collectively known as the MII Management registers and are + * detailed in Section 22.2.4 of the IEEE 802.3 specification. + */ + +#define MII_MCR 0x00 /* MII management control */ +#define MII_MSR 0x01 /* MII management status */ +#define MII_PHYID1 0x02 /* PHY ID 1 */ +#define MII_PHYID2 0x03 /* PHY ID 2 */ +#define MII_ADVERTISE 0x04 /* Auto-negotiation advertisement */ +#define MII_LPA 0x05 /* Auto-negotiation link partner base page ability */ +#define MII_EXPANSION 0x06 /* Auto-negotiation expansion */ +#define MII_NEXTPAGE 0x07 /* Auto-negotiation next page */ +#define MII_LPANEXTPAGE 0x08 /* Auto-negotiation link partner received next page */ +#define MII_MSCONTROL 0x09 /* Master/slave control register */ +#define MII_MSSTATUS 0x0a /* Master/slave status register */ +#define MII_PSECONTROL 0x0b /* PSE control register */ +#define MII_PSESTATUS 0x0c /* PSE status register */ +#define MII_MMDCONTROL 0x0d /* MMD access control register */ +#define MII_ESTATUS 0x0f /* Extended status register */ + +/* Extended Registers: Registers 16-31 may be used for vendor specific abilities */ + +/* National Semiconductor DP83840: 0x07-0x11, 0x14, 0x1a, 0x1d-0x1f reserved */ + +#define MII_DP83840_COUNTER 0x12 /* Disconnect counter */ +#define MII_DP83840_FCSCOUNTER 0x13 /* False carrier sense counter */ +#define MII_DP83840_NWAYTEST 0x14 /* N-way auto-neg test reg */ +#define MII_DP83840_RERRCOUNTER 0x15 /* Receive error counter */ +#define MII_DP83840_SREVISION 0x16 /* Silicon revision */ +#define MII_DP83840_LBRERROR 0x18 /* Loopback, bypass and receiver error */ +#define MII_DP83840_PHYADDR 0x19 /* PHY address */ +#define MII_DP83840_10BTSR 0x1b /* 10BASE-T status register */ +#define MII_DP83840_10BTCR 0x1c /* 10BASE-T configuration register */ + +/* National Semiconductor DP83848C: 0x8-0x15, 0x13, 0x1c reserved */ + +#define MII_DP83848C_PHYSTS 0x10 /* RO PHY Status Register */ +#define MII_DP83848C_MICR 0x11 /* RW MII Interrupt Control Register */ +#define MII_DP83848C_MISR 0x12 /* RO MII Interrupt Status Register */ +#define MII_DP83848C_FCSCR 0x14 /* RO False Carrier Sense Counter Register */ +#define MII_DP83848C_RECR 0x15 /* RO Receive Error Counter Register */ +#define MII_DP83848C_PCSR 0x16 /* RW PCS Sub-Layer Configuration and Status Register */ +#define MII_DP83848C_RBR 0x17 /* RW RMII and Bypass Register */ +#define MII_DP83848C_LEDCR 0x18 /* RW LED Direct Control Register */ +#define MII_DP83848C_PHYCR 0x19 /* RW PHY Control Register */ +#define MII_DP83848C_10BTSCR 0x1a /* RW 10Base-T Status/Control Register */ +#define MII_DP83848C_CDCTRL1 0x1b /* RW CD Test Control Register and BIST Extensions Register */ +#define MII_DP83848C_EDCR 0x1e /* RW Energy Detect */ + +/* Am79c874: 0x08-0x0f, 0x14, 0x16, 0x19-0x1f reserved */ + +#define MII_AM79C874_NPADVERTISE 0x07 /* Auto-negotiation next page advertisement */ +#define MII_AM79C874_MISCFEATURES 0x10 /* Miscellaneous features reg */ +#define MII_AM79C874_INTCS 0x11 /* Interrupt control/status */ +#define MII_AM79C874_DIAGNOSTIC 0x12 /* Diagnostic */ +#define MII_AM79C874_LOOPBACK 0x13 /* Power management/loopback */ +#define MII_AM79C874_MODEC 0x15 /* Mode control register */ +#define MII_AM79C874_DISCONNECT 0x17 /* Disconnect counter */ +#define MII_AM79C874_RCVERROR 0x18 /* Receive error counter */ + +/* Luminary LM3S6918 built-in PHY: 0x07-0x0f, 0x14-0x16, 0x19-0x1f reserved */ + +#define MII_LM3S_VSPECIFIC 0x10 /* Vendor-Specific */ +#define MII_LM3S_INTCS 0x11 /* Interrupt control/status */ +#define MII_LM3S_DIAGNOSTIC 0x12 /* Diagnostic */ +#define MII_LM3S_XCVRCONTROL 0x13 /* Transceiver Control */ +#define MII_LM3S_LEDCONFIG 0x17 /* LED Configuration */ +#define MII_LM3S_MDICONTROL 0x18 /* Ethernet PHY Management MDI/MDIX Control */ + +/* Micrel KS8721: 0x15, 0x1b, and 0x1f */ + +#define MII_KS8721_RXERCOUNTER 0x15 /* RXER counter */ +#define MII_KS8721_INTCS 0x1b /* Interrupt control/status register */ +#define MII_KS8721_10BTCR 0x1f /* 10BASE-TX PHY control register */ + +/* National Semiconductor DP83848C PHY Extended Registers */ + +#define MII_DP83848C_STS 0x10 /* Status Register */ +#define MII_DP83848C_MICR 0x11 /* MII Interrupt Control Register */ +#define MII_DP83848C_MISR 0x12 /* MII Interrupt Status Register */ +#define MII_DP83848C_FCSCR 0x14 /* False Carrier Sense Counter */ +#define MII_DP83848C_RECR 0x15 /* Receive Error Counter */ +#define MII_DP83848C_PCSR 0x16 /* PCS Sublayer Config. and Status */ +#define MII_DP83848C_RBR 0x17 /* RMII and Bypass Register */ +#define MII_DP83848C_LEDCR 0x18 /* LED Direct Control Register */ +#define MII_DP83848C_PHYCR 0x19 /* PHY Control Register */ +#define MII_DP83848C_10BTSCR 0x1a /* 10Base-T Status/Control Register */ +#define MII_DP83848C_CDCTRL1 0x1b /* CD Test Control and BIST Extens */ +#define MII_DP83848C_EDCR 0x1d /* Energy Detect Control Register */ + +/* SMSC LAN8720 PHY Extended Registers */ + +#define MII_LAN8720_REV 0x10 /* Silicon Revision Register */ +#define MII_LAN8720_MCSR 0x11 /* Mode Control/Status Register */ +#define MII_LAN8720_MODES 0x12 /* Special modes */ +#define MII_LAN8720_SECR 0x1a /* Symbol Error Counter Register */ +#define MII_LAN8720_CSIR 0x1b /* Control / Status Indicator Register */ +#define MII_LAN8720_SITC 0x1c /* Special Internal Testability Controls */ +#define MII_LAN8720_ISR 0x1d /* Interrupt Source Register */ +#define MII_LAN8720_IMR 0x1e /* Interrupt Mask Register */ +#define MII_LAN8720_SCSR 0x1f /* PHY Special Control/Status Register */ + +/* GMII */ + +#define GMII_MCR MII_MCR /* GMII management control */ +#define GMII_MSR MII_MSR /* GMII management status */ +#define GMII_PHYID1 MII_PHYID1 /* PHY ID 1 */ +#define GMII_PHYID2 MII_PHYID2 /* PHY ID 2 */ +#define GMII_ADVERTISE MII_ADVERTISE /* Auto-negotiation advertisement */ +#define GMII_LPA MII_LPA /* Auto-negotiation link partner base page ability */ +#define GMII_EXPANSION MII_EXPANSION /* Auto-negotiation expansion */ +#define GMII_NEXTPAGE MII_NEXTPAGE /* Auto-negotiation next page */ +#define GMII_LPANEXTPAGE MII_LPANEXTPAGE /* Auto-negotiation link partner received next page */ +#define GMII_CTRL1000 0x09 /* 1000BASE-T control */ +#define GMII_STAT1000 0x0a /* 1000BASE-T status */ +#define GMII_ESTATUS MII_ESTATUS /* Extended status register */ + +/* MII register bit settings ************************************************/ + +/* MII Control register bit definitions */ + +#define MII_MCR_UNIDIR (1 << 5) /* Bit 5: Unidirectional enable */ +#define MII_MCR_SPEED1000 (1 << 6) /* Bit 6: MSB of Speed (1000 reserved on 10/100) */ +#define MII_MCR_CTST (1 << 7) /* Bit 7: Enable collision test */ +#define MII_MCR_FULLDPLX (1 << 8) /* Bit 8: Full duplex */ +#define MII_MCR_ANRESTART (1 << 9) /* Bit 9: Restart auto negotiation */ +#define MII_MCR_ISOLATE (1 << 10) /* Bit 10: Electronically isolate PHY from MII */ +#define MII_MCR_PDOWN (1 << 11) /* Bit 11: Powerdown the PHY */ +#define MII_MCR_ANENABLE (1 << 12) /* Bit 12: Enable auto negotiation */ +#define MII_MCR_SPEED100 (1 << 13) /* Bit 13: Select 100Mbps */ +#define MII_MCR_LOOPBACK (1 << 14) /* Bit 14: Enable loopback mode */ +#define MII_MCR_RESET (1 << 15) /* Bit 15: PHY reset */ + +/* MII Status register bit definitions */ + +#define MII_MSR_EXTCAP (1 << 0) /* Bit 0: Extended register capability */ +#define MII_MSR_JABBERDETECT (1 << 1) /* Bit 1: Jabber detect */ +#define MII_MSR_LINKSTATUS (1 << 2) /* Bit 2: Link status */ +#define MII_MSR_ANEGABLE (1 << 3) /* Bit 3: Auto-negotiation able */ +#define MII_MSR_RFAULT (1 << 4) /* Bit 4: Remote fault */ +#define MII_MSR_ANEGCOMPLETE (1 << 5) /* Bit 5: Auto-negotiation complete */ +#define MII_MSR_MFRAMESUPPRESS (1 << 6) /* Bit 6: Management frame suppression */ +#define MII_MSR_ESTATEN (1 << 8) /* Bit 8: Extended Status in R15 */ +#define MII_MSR_100BASET2FULL (1 << 9) /* Bit 9: 100BASE-T2 half duplex able */ +#define MII_MSR_100BASET2HALF (1 << 10) /* Bit 10: 100BASE-T2 full duplex able */ +#define MII_MSR_10BASETXHALF (1 << 11) /* Bit 11: 10BASE-TX half duplex able */ +#define MII_MSR_10BASETXFULL (1 << 12) /* Bit 12: 10BASE-TX full duplex able */ +#define MII_MSR_100BASETXHALF (1 << 13) /* Bit 13: 100BASE-TX half duplex able */ +#define MII_MSR_100BASETXFULL (1 << 14) /* Bit 14: 100BASE-TX full duplex able */ +#define MII_MSR_100BASET4 (1 << 15) /* Bit 15: 100BASE-T4 able */ + +/* MII ID2 register bits */ + +#define MII_PHYID2_OUI 0xfc00 /* Bits 19-24 of OUI mask */ +#define MII_PHYID2_MODEL 0x03f0 /* Model number mask */ +#define MII_PHYID2_REV 0x000f /* Revision number mask */ + +/* Advertisement control register bit definitions */ + +#define MII_ADVERTISE_SELECT 0x001f /* Bits 0-4: Selector field */ +#define MII_ADVERTISE_CSMA (1 << 0) /* CSMA */ +#define MII_ADVERTISE_8023 (1 << 0) /* IEEE Std 802.3 */ +#define MII_ADVERTISE_8029 (2 << 0) /* IEEE Std 802.9 ISLAN-16T */ +#define MII_ADVERTISE_8025 (3 << 0) /* IEEE Std 802.5 */ +#define MII_ADVERTISE_1394 (4 << 0) /* IEEE Std 1394 */ +#define MII_ADVERTISE_10BASETXHALF (1 << 5) /* Bit 5: Try 10BASE-TX half duplex */ +#define MII_ADVERTISE_1000XFULL (1 << 5) /* Bit 5: Try 1000BASE-X full duplex */ +#define MII_ADVERTISE_10BASETXFULL (1 << 6) /* Bit 6: Try 10BASE-TX full duplex */ +#define MII_ADVERTISE_1000XHALF (1 << 6) /* Bit 6: Try 1000BASE-X half duplex */ +#define MII_ADVERTISE_100BASETXHALF (1 << 7) /* Bit 7: Try 100BASE-TX half duplex */ +#define MII_ADVERTISE_1000XPAUSE (1 << 7) /* Bit 7: Try 1000BASE-X pause */ +#define MII_ADVERTISE_100BASETXFULL (1 << 8) /* Bit 8: Try 100BASE-TX full duplex*/ +#define MII_ADVERTISE_1000XASYMPAU (1 << 8) /* Bit 8: Try 1000BASE-X asym pause */ +#define MII_ADVERTISE_100BASET4 (1 << 9) /* Bit 9: Try 100BASE-T4 */ +#define MII_ADVERTISE_FDXPAUSE (1 << 10) /* Bit 10: Try full duplex flow control */ +#define MII_ADVERTISE_ASYMPAUSE (1 << 11) /* Bit 11: Try asymetric pause */ +#define MII_ADVERTISE_RFAULT (1 << 13) /* Bit 13: Remote fault supported */ +#define MII_ADVERTISE_LPACK (1 << 14) /* Bit 14: Ack link partners response */ +#define MII_ADVERTISE_NXTPAGE (1 << 15) /* Bit 15: Next page enabled */ + +/* Link partner ability register bit definitions */ + +#define MII_LPA_SELECT 0x001f /* Bits 0-4: Link partner selector field */ +#define MII_LPA_CSMA (1 << 0) /* CSMA */ +#define MII_LPA_8023 (1 << 0) /* IEEE Std 802.3 */ +#define MII_LPA_8029 (2 << 0) /* IEEE Std 802.9 ISLAN-16T */ +#define MII_LPA_8025 (3 << 0) /* IEEE Std 802.5 */ +#define MII_LPA_1394 (4 << 0) /* IEEE Std 1394 */ +#define MII_LPA_10BASETXHALF (1 << 5) /* Bit 5: 10BASE-TX half duplex able */ +#define MII_LPA_1000XFULL (1 << 5) /* Bit 5: 1000BASE-X full-duplex able */ +#define MII_LPA_10BASETXFULL (1 << 6) /* Bit 6: 10BASE-TX full duplex able */ +#define MII_LPA_1000XHALF (1 << 6) /* Bit 6: 1000BASE-X half-duplex */ +#define MII_LPA_100BASETXHALF (1 << 7) /* Bit 7: 100BASE-TX half duplex able */ +#define MII_LPA_1000XPAUSE (1 << 7) /* Bit 7: 1000BASE-X pause able */ +#define MII_LPA_100BASETXFULL (1 << 8) /* Bit 8: 100BASE-TX full duplex able */ +#define MII_LPA_1000XASYMPAU (1 << 8) /* Bit 8: 1000BASE-X asym pause able */ +#define MII_LPA_100BASET4 (1 << 9) /* Bit 9: 100BASE-T4 able */ +#define MII_LPA_FDXPAUSE (1 << 10) /* Bit 10: Full duplex flow control able */ +#define MII_LPA_ASYMPAUSE (1 << 11) /* Bit 11: Asynchronous pause able */ +#define MII_LPA_RFAULT (1 << 13) /* Bit 13: Link partner remote fault request */ +#define MII_LPA_LPACK (1 << 14) /* Bit 14: Link partner acknowledgement */ +#define MII_LPA_NXTPAGE (1 << 15) /* Bit 15: Next page requested */ + +/* Link partner ability in next page format */ + +#define MII_LPANP_MESSAGE 0x07ff /* Bits 0-10: Link partner's message code */ +#define MII_LPANP_TOGGLE (1 << 11) /* Bit 11: Link partner toggle */ +#define MII_LPANP_LACK2 (1 << 12) /* Bit 12: Link partner can comply ACK */ +#define MII_LPANP_MSGPAGE (1 << 13) /* Bit 13: Link partner message page request */ +#define MII_LPANP_LPACK (1 << 14) /* Bit 14: Link partner acknowledgement */ +#define MII_LPANP_NXTPAGE (1 << 15) /* Bit 15: Next page requested */ + +/* MII Auto-negotiation expansion register bit definitions */ + +#define MII_EXPANSION_ANEGABLE (1 << 0) /* Bit 0: Link partner is auto-negotion able */ +#define MII_EXPANSION_PAGERECVD (1 << 1) /* Bit 1: New link code word in LPA ability reg */ +#define MII_EXPANSION_ENABLENPAGE (1 << 2) /* Bit 2: This enables npage words */ +#define MII_EXPANSION_NXTPAGEABLE (1 << 3) /* Bit 3: Link partner supports next page */ +#define MII_EXPANSION_PARFAULTS (1 << 4) /* Bit 4: Fault detected by parallel logic */ + +/* Auto-negotiation next page advertisement */ + +#define MII_NPADVERTISE_CODE 0x07ff /* Bits 0-10: message/un-formated code field */ +#define MII_NPADVERTISE_TOGGLE (1 << 11) /* Bit 11: Toggle */ +#define MII_NPADVERTISE_ACK2 (1 << 12) /* Bit 12: Acknowledgement 2 */ +#define MII_NPADVERTISE_MSGPAGE (1 << 13) /* Bit 13: Message page */ +#define MII_NPADVERTISE_NXTPAGE (1 << 15) /* Bit 15: Next page indication */ + +/* MII PHYADDR register bit definitions */ + +#define DP83840_PHYADDR_DUPLEX (1 << 7) +#define DP83840_PHYADDR_SPEED (1 << 6) + +/* National Semiconductor DP83848C ******************************************/ +/* DP83848C MII ID1/2 register bits */ + +#define MII_PHYID1_DP83848C 0x2000 /* ID1 value for DP83848C */ +#define MII_PHYID2_DP83848C 0x5c90 /* ID2 value for DP83848C */ + +/* RMII and Bypass Register (0x17) */ + +#define MII_RBR_ELAST_MASK 0x0003 /* Bits 0-1: Receive elasticity buffer */ +# define MII_RBR_ELAST_14 0x0000 /* 14 bit tolerance */ +# define MII_RBR_ELAST_2 0x0001 /* 2 bit tolerance */ +# define MII_RBR_ELAST_6 0x0002 /* 6 bit tolerance */ +# define MII_RBR_ELAST_10 0x0003 /* 10 bit tolerance */ +#define MII_RBR_RXUNFSTS (1 << 2) /* Bit 2: RX FIFO underflow */ +#define MII_RBR_RXOVFSTS (1 << 3) /* Bit 3: RX FIFO overflow */ +#define MII_RBR_RMIIREV10 (1 << 4) /* Bit 4: 0=RMIIv1.2 1-RMIIv1.0 */ +#define MII_RBR_RMIIMODE (1 << 5) /* Bit 5: 0=MII mode 1=RMII mode */ + +/* SMSC LAN8720 *************************************************************/ +/* SMSC LAN8720 MII ID1/2 register bits */ + +#define MII_PHYID1_LAN8720 0x0007 /* ID1 value for LAN8720 */ +#define MII_PHYID2_LAN8720 0xc0f1 /* ID2 value for LAN8720 */ + +/* Am79c874-specific register bit settings **********************************/ +/* Am79c874 MII ID1/2 register bits */ + +#define MII_PHYID1_AM79C874 0x0022 /* ID1 value for Am79c874 */ +#define MII_PHYID2_AM79C874 0x561b /* ID2 value for Am79c874 Rev B */ + +/* Am79c874 diagnostics register */ + +#define AM79C874_DIAG_RXLOCK (1 << 8) /* Bit 8: 1=Rcv PLL locked on */ +#define AM79C874_DIAG_RXPASS (1 << 9) /* Bit 9: 1=Operating in 100Base-X mode */ +#define AM79C874_DIAG_100MBPS (1 << 10) /* Bit 10: 1=ANEG result is 100Mbps */ +#define AM79C874_DIAG_FULLDPLX (1 << 11) /* Bit 11: 1=ANEG result is full duplex */ + +/* LM3S6918-specific register bit settings **********************************/ +/* LM3S6918 Vendor-Specific, address 0x10 */ + +#define LM3S_VSPECIFIC_RXCC (1 << 0) /* Bit 0: Receive Clock Control*/ +#define LM3S_VSPECIFIC_PCSBP (1 << 1) /* Bit 1: PCS Bypass */ +#define LM3S_VSPECIFIC_RVSPOL (1 << 4) /* Bit 4: Receive Data Polarity */ +#define LM3S_VSPECIFIC_APOL (1 << 5) /* Bit 5: Auto-Polarity Disable */ +#define LM3S_VSPECIFIC_NL10 (1 << 10) /* Bit 10: Natural Loopback Mode */ +#define LM3S_VSPECIFIC_SQEI (1 << 11) /* Bit 11: SQE Inhibit Testing */ +#define LM3S_VSPECIFIC_TXHIM (1 << 12) /* Bit 12: Transmit High Impedance Mode */ +#define LM3S_VSPECIFIC_INPOL (1 << 14) /* Bit 14: Interrupt Polarity Value*/ +#define LM3S_VSPECIFIC_RPTR (1 << 15) /* Bit 15: Repeater mode*/ + +/* LM3S6918 Interrupt Control/Status, address 0x11 */ + +#define LM3S_INTCS_ANEGCOMPINT (1 << 0) /* Bit 0: Auto-Negotiation Complete Interrupt */ +#define LM3S_INTCS_RFAULTINT (1 << 1) /* Bit 1: Remote Fault Interrupt */ +#define LM3S_INTCS_LSCHGINT (1 << 2) /* Bit 2: Link Status Change Interrupt */ +#define LM3S_INTCS_LPACKINT (1 << 3) /* Bit 3: LP Acknowledge Interrupt */ +#define LM3S_INTCS_PDFINT (1 << 4) /* Bit 4: Parallel Detection Fault Interrupt */ +#define LM3S_INTCS_PRXINT (1 << 5) /* Bit 5: Page Receive Interrupt */ +#define LM3S_INTCS_RXERINT (1 << 6) /* Bit 6: Receive Error Interrupt */ +#define LM3S_INTCS_JABBERINT (1 << 7) /* Bit 7: Jabber Event Interrupt */ +#define LM3S_INTCS_ANEGCOMPIE (1 << 8) /* Bit 8: Auto-Negotiation Complete Interrupt Enable */ +#define LM3S_INTCS_RFAULTIE (1 << 9) /* Bit 9: Remote Fault Interrupt Enable */ +#define LM3S_INTCS_LSCHGIE (1 << 10) /* Bit 10: Link Status Change Interrupt Enable */ +#define LM3S_INTCS_LPACKIE (1 << 11) /* Bit 11: LP Acknowledge Interrupt Enable */ +#define LM3S_INTCS_PDFIE (1 << 12) /* Bit 12: Parallel Detection Fault Interrupt Enable */ +#define LM3S_INTCS_PRXIE (1 << 13) /* Bit 13: Page Received Interrupt Enable */ +#define LM3S_INTCS_RXERIE (1 << 14) /* Bit 14: Receive Error Interrupt Enable */ +#define LM3S_INTCS_JABBERIE (1 << 15) /* Bit 15: Jabber Interrupt Enable */ + +/* LM3S6918 Diagnostic, address 0x12 */ + +#define LM3S_DIAGNOSTIC_RX_LOCK (1 << 8) /* Bit 8: Receive PLL Lock */ +#define LM3S_DIAGNOSTIC_RXSD (1 << 9) /* Bit 9: Receive Detection */ +#define LM3S_DIAGNOSTIC_RATE (1 << 10) /* Bit 10: Rate */ +#define LM3S_DIAGNOSTIC_DPLX (1 << 11) /* Bit 11: Duplex Mode */ +#define LM3S_DIAGNOSTIC_ANEGF (1 << 12) /* Bit 12: Auto-Negotiation Failure */ + +/* LM3S6918 Transceiver Control, address 0x13 */ + +#define LM3S_XCVRCONTROL_TXO_SHIFT 14 /* Bits 15-14: Transmit Amplitude Selection */ +#define LM3S_XCVRCONTROL_TXO_MASK (3 << LM3S_XCVRCONTROL_TXO_SHIFT) +#define LM3S_XCVRCONTROL_TXO_00DB (0 << LM3S_XCVRCONTROL_TXO_SHIFT) /* Gain 0.0dB of insertion loss */ +#define LM3S_XCVRCONTROL_TXO_04DB (1 << LM3S_XCVRCONTROL_TXO_SHIFT) /* Gain 0.4dB of insertion loss */ +#define LM3S_XCVRCONTROL_TXO_08DB (2 << LM3S_XCVRCONTROL_TXO_SHIFT) /* Gain 0.8dB of insertion loss */ +#define LM3S_XCVRCONTROL_TXO_12DB (3 << LM3S_XCVRCONTROL_TXO_SHIFT) /* Gain 1.2dB of insertion loss */ + +/* LM3S6918 LED Configuration, address 0x17 */ + +#define LM3S_LEDCONFIG_LED0_SHIFT (0) /* Bits 3-0: LED0 Source */ +#define LM3S_LEDCONFIG_LED0_MASK (0x0f << LM3S_LEDCONFIG_LED0_SHIFT) +#define LM3S_LEDCONFIG_LED0_LINKOK (0 << LM3S_LEDCONFIG_LED0_SHIFT) /* Link OK */ +#define LM3S_LEDCONFIG_LED0_RXTX (1 << LM3S_LEDCONFIG_LED0_SHIFT) /* RX or TX activity */ +#define LM3S_LEDCONFIG_LED0_100BASET (5 << LM3S_LEDCONFIG_LED0_SHIFT) /* 100BASE-TX mode */ +#define LM3S_LEDCONFIG_LED0_10BASET (6 << LM3S_LEDCONFIG_LED0_SHIFT) /* 10BASE-T mode */ +#define LM3S_LEDCONFIG_LED0_FDUPLEX (7 << LM3S_LEDCONFIG_LED0_SHIFT) /* Full duplex */ +#define LM3S_LEDCONFIG_LED0_OKRXTX (8 << LM3S_LEDCONFIG_LED0_SHIFT) /* Full duplex */ +#define LM3S_LEDCONFIG_LED1_SHIFT (4) /* Bits 7-4: LED1 Source */ +#define LM3S_LEDCONFIG_LED1_MASK (0x0f << LM3S_LEDCONFIG_LED1_SHIFT) +#define LM3S_LEDCONFIG_LED1_LINKOK (0 << LM3S_LEDCONFIG_LED1_SHIFT) /* Link OK */ +#define LM3S_LEDCONFIG_LED1_RXTX (1 << LM3S_LEDCONFIG_LED1_SHIFT) /* RX or TX activity */ +#define LM3S_LEDCONFIG_LED1_100BASET (5 << LM3S_LEDCONFIG_LED1_SHIFT) /* 100BASE-TX mode */ +#define LM3S_LEDCONFIG_LED1_10BASET (6 << LM3S_LEDCONFIG_LED1_SHIFT) /* 10BASE-T mode */ +#define LM3S_LEDCONFIG_LED1_FDUPLEX (7 << LM3S_LEDCONFIG_LED1_SHIFT) /* Full duplex */ +#define LM3S_LEDCONFIG_LED1_OKRXTX (8 << LM3S_LEDCONFIG_LED1_SHIFT) /* Full duplex */ + +/* LM3S6918 MDI/MDIX Control, address 0x18 */ + +#define LM3S_MDICONTROL_MDIXSD_SHIFT (0) /* Bits 3-0: Auto-Switching Seed */ +#define LM3S_MDICONTROL_MDIXSD_MASK (0x0f << LM3S_MDICONTROL_MDIXSD_SHIFT) +#define LM3S_MDICONTROL_MDIXCM (1 << 4) /* Bit 4: Auto-Switching Complete */ +#define LM3S_MDICONTROL_MDIX (1 << 5) /* Bit 5: Auto-Switching Configuration */ +#define LM3S_MDICONTROL_AUTOSW (1 << 6) /* Bit 6: Auto-Switching Enable */ +#define LM3S_MDICONTROL_PDMODE (1 << 7) /* Bit 7: Parallel Detection Mode */ + +/* KS8921-specific register bit settings ************************************/ +/* KS8921 MII Control register bit definitions (not in 802.3) */ + +#define KS8721_MCR_DISABXMT (1 << 0) /* Bit 0: Disable Transmitter */ + +/* KS8921 MII ID1/2 register bits */ + +#define MII_PHYID1_KS8721 0x0022 /* ID1 value for Micrel KS8721 */ +#define MII_PHYID2_KS8721 0x1619 /* ID2 value for Micrel KS8721 */ + +/* KS8921 RXER Counter -- 16-bit counter */ + +/* KS8921 Interrupt Control/Status Register */ + +#define KS8721_INTCS_LINKUP (1 << 0) /* Bit 0: Link up occurred */ +#define KS8721_INTCS_REMFAULT (1 << 1) /* Bit 1: Remote fault occurred */ +#define KS8721_INTCS_LINKDOWN (1 << 2) /* Bit 2: Link down occurred */ +#define KS8721_INTCS_LPACK (1 << 3) /* Bit 3: Link partner acknowlege occurred */ +#define KS8721_INTCS_PDFAULT (1 << 4) /* Bit 4: Parallel detect fault occurred */ +#define KS8721_INTCS_PGRCVD (1 << 5) /* Bit 5: Page received occurred */ +#define KS8721_INTCS_RXERR (1 << 6) /* Bit 6: Receive error occurred */ +#define KS8721_INTCS_JABBER (1 << 7) /* Bit 7: Jabber interrupt occurred */ +#define KS8721_INTCS_LINKUPE (1 << 8) /* Bit 8: Enable link up interrupt */ +#define KS8721_INTCS_REMFAULTE (1 << 9) /* Bit 9: Enable remote fault interrupt */ +#define KS8721_INTCS_LINKDOWNE (1 << 10) /* Bit 10: Enable link down interrupt */ +#define KS8721_INTCS_LPACKE (1 << 11) /* Bit 11: Enable link partner acknowldgement interrupt */ +#define KS8721_INTCS_PDFAULTE (1 << 12) /* Bit 12: Enable parallel detect fault interrupt */ +#define KS8721_INTCS_PGRCVDE (1 << 13) /* Bit 13: Enable page received interrupt */ +#define KS8721_INTCS_RXERRE (1 << 14) /* Bit 14: Enable receive error interrupt */ +#define KS8721_INTCS_JABBERE (1 << 15) /* Bit 15: Enable Jabber Interrupt */ + +/* KS8921 10BASE-TX PHY control register */ + +#define KS8721_10BTCR_BIT0 (1 << 0) /* Bit 0: xxx */ +#define KS8721_10BTCR_BIT1 (1 << 1) /* Bit 1: xxx */ +#define KS8721_10BTCR_MODE_SHIFT (2) /* Bits 2-4: Operation Mode Indication */ +#define KS8721_10BTCR_MODE_MASK (7 << KS8721_10BTCR_MODE_SHIFT) +# define KS8721_10BTCR_MODE_ANEG (0 << KS8721_10BTCR_MODE_SHIFT) /* Still in auto-negotiation */ +# define KS8721_10BTCR_MODE_10BTHD (1 << KS8721_10BTCR_MODE_SHIFT) /* 10BASE-T half-duplex */ +# define KS8721_10BTCR_MODE_100BTHD (2 << KS8721_10BTCR_MODE_SHIFT) /* 100BASE_t half-duplex */ +# define KS8721_10BTCR_MODE_DEFAULT (3 << KS8721_10BTCR_MODE_SHIFT) /* Default */ +# define KS8721_10BTCR_MODE_10BTFD (5 << KS8721_10BTCR_MODE_SHIFT) /* 10BASE-T full duplex */ +# define KS8721_10BTCR_MODE_100BTFD (6 << KS8721_10BTCR_MODE_SHIFT) /* 100BASE-T full duplex */ +# define KS8721_10BTCR_MODE_ISOLATE (7 << KS8721_10BTCR_MODE_SHIFT) /* PHY/MII isolate */ +#define KS8721_10BTCR_ISOLATE (1 << 5) /* Bit 5: PHY isolate */ +#define KS8721_10BTCR_PAUSE (1 << 6) /* Bit 6: Enable pause */ +#define KS8721_10BTCR_ANEGCOMP (1 << 7) /* Bit 7: Auto-negotiation complete */ +#define KS8721_10BTCR_JABBERE (1 << 8) /* Bit 8: Enable Jabber */ +#define KS8721_10BTCR_INTLVL (1 << 9) /* Bit 9: Interrupt level */ +#define KS8721_10BTCR_POWER (1 << 10) /* Bit 10: Power saving */ +#define KS8721_10BTCR_FORCE (1 << 11) /* Bit 11: Force link */ +#define KS8721_10BTCR_ENERGY (1 << 12) /* Bit 12: Energy detect */ +#define KS8721_10BTCR_PAIRSWAPD (1 << 13) /* Bit 13: Pairswap disable */ + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_NET_MII_H */ diff --git a/nuttx/include/nuttx/net/net.h b/nuttx/include/nuttx/net/net.h new file mode 100644 index 0000000000..b79dda755f --- /dev/null +++ b/nuttx/include/nuttx/net/net.h @@ -0,0 +1,295 @@ +/**************************************************************************** + * include/nuttx/net/net.h + * + * Copyright (C) 2007, 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_NET_H +#define __INCLUDE_NUTTX_NET_NET_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Socket descriptors are the index into the TCB sockets list, offset by the + * following amount. This offset is used to distinquish file descriptors from + * socket descriptors + */ + +#ifdef CONFIG_NFILE_DESCRIPTORS +# define __SOCKFD_OFFSET CONFIG_NFILE_DESCRIPTORS +#else +# define __SOCKFD_OFFSET 0 +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This defines a bitmap big enough for one bit for each socket option */ + +typedef uint16_t sockopt_t; + +/* This defines the storage size of a timeout value. This effects only + * range of supported timeout values. With an LSB in seciseconds, the + * 16-bit maximum of 65535 corresponds to 1 hr 49 min 13.5 sec at decisecond + * resolution. + */ + +typedef uint16_t socktimeo_t; + +/* This is the internal representation of a socket reference by a file + * descriptor. + */ + +struct socket +{ + int s_crefs; /* Reference count on the socket */ + uint8_t s_type; /* Protocol type: Only SOCK_STREAM or SOCK_DGRAM */ + uint8_t s_flags; /* See _SF_* definitions */ +#ifdef CONFIG_NET_SOCKOPTS + sockopt_t s_options; /* Selected socket options */ +#ifndef CONFIG_DISABLE_CLOCK + socktimeo_t s_rcvtimeo; /* Receive timeout value (in deciseconds) */ + socktimeo_t s_sndtimeo; /* Send timeout value (in deciseconds) */ +#endif +#endif + void *s_conn; /* Connection: struct uip_conn or uip_udp_conn */ +}; + +/* This defines a list of sockets indexed by the socket descriptor */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 +struct socketlist +{ + sem_t sl_sem; /* Manage access to the socket list */ + int16_t sl_crefs; /* Reference count */ + struct socket sl_sockets[CONFIG_NSOCKET_DESCRIPTORS]; +}; +#endif + +/* Callback from netdev_foreach() */ + +struct uip_driver_s; /* Forward reference. See nuttx/net/uip/uip-arch.h */ +typedef int (*netdev_callback_t)(FAR struct uip_driver_s *dev, void *arg); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* net_checksd.c *************************************************************/ +/* Check if the socket descriptor is valid for the provided TCB and if it + * supports the requested access. + */ + +EXTERN int net_checksd(int fd, int oflags); + +/* net_sockets.c *************************************************************/ +/* There interfaces are called only from OS scheduling and iniialization logic + * under sched/ + */ + +EXTERN void weak_function net_initialize(void); +EXTERN FAR struct socketlist *net_alloclist(void); +EXTERN int net_addreflist(FAR struct socketlist *list); +EXTERN int net_releaselist(FAR struct socketlist *list); + +/* Given a socket descriptor, return the underly NuttX-specific socket + * structure. + */ + +EXTERN FAR struct socket *sockfd_socket(int sockfd); + +/* socket.c ******************************************************************/ +/* socket using underlying socket structure */ + +EXTERN int psock_socket(int domain, int type, int protocol, + FAR struct socket *psock); + +/* net_close.c ***************************************************************/ +/* The standard close() operation redirects operations on socket descriptors + * to this function. + */ + +EXTERN int net_close(int sockfd); + +/* Performs the close operation on a socket instance */ + +EXTERN int psock_close(FAR struct socket *psock); + +/* net_close.c ***************************************************************/ +/* Performs the bind() operation on a socket instance */ + +EXTERN int psock_bind(FAR struct socket *psock, + FAR const struct sockaddr *addr, socklen_t addrlen); + +/* connect.c *****************************************************************/ +/* Performs the connect() operation on a socket instance */ + +EXTERN int psock_connect(FAR struct socket *psock, + FAR const struct sockaddr *addr, socklen_t addrlen); + +/* send.c ********************************************************************/ +/* Send using underlying socket structure */ + +EXTERN ssize_t psock_send(FAR struct socket *psock, const void *buf, + size_t len, int flags); + +/* sendto.c ******************************************************************/ +/* Sendto using underlying socket structure */ + +EXTERN ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags, FAR const struct sockaddr *to, + socklen_t tolen); + +/* recvfrom.c ****************************************************************/ +/* recvfrom using the underlying socket structure */ + +EXTERN ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, + size_t len, int flags,FAR struct sockaddr *from, + FAR socklen_t *fromlen); + +/* recv using the underlying socket structure */ + +#define psock_recv(psock,buf,len,flags) psock_recvfrom(psock,buf,len,flags,NULL,0) + +/* getsockopt.c **************************************************************/ +/* getsockopt using the underlying socket structure */ + +EXTERN int psock_getsockopt(FAR struct socket *psock, int level, int option, + FAR void *value, FAR socklen_t *value_len); + +/* setsockopt.c **************************************************************/ +/* setsockopt using the underlying socket structure */ + +EXTERN int psock_setsockopt(FAR struct socket *psock, int level, int option, + FAR const void *value, socklen_t value_len); + +/* net_ioctl.c ***************************************************************/ +/* The standard ioctl() operation redirects operations on socket descriptors + * to this function. + */ + +EXTERN int netdev_ioctl(int sockfd, int cmd, unsigned long arg); + +/* net_poll.c ****************************************************************/ +/* The standard poll() operation redirects operations on socket descriptors + * to this function. + */ + +#ifndef CONFIG_DISABLE_POLL +struct pollfd; /* Forward reference -- see poll.h */ +EXTERN int net_poll(int sockfd, struct pollfd *fds, bool setup); +#endif + +/* net_dup.c *****************************************************************/ +/* The standard dup() operation redirects operations on socket descriptors to + * this function + */ + +EXTERN int net_dup(int sockfd, int minsd); + +/* net_dup2.c ****************************************************************/ +/* The standard dup2() operation redirects operations on socket descriptors to + * this function (when both file and socket descriptors are supported) + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +EXTERN int net_dup2(int sockfd1, int sockfd2); +#else +# define net_dup2(sockfd1, sockfd2) dup2(sockfd1, sockfd2) +#endif + +/* net_clone.c ***************************************************************/ +/* Performs the low level, common portion of net_dup() and net_dup2() */ + +EXTERN int net_clone(FAR struct socket *psock1, FAR struct socket *psock2); + +/* net_vfcntl.c **************************************************************/ +/* Performs fcntl operations on socket */ + +EXTERN int net_vfcntl(int sockfd, int cmd, va_list ap); + +/* netdev-register.c *********************************************************/ +/* This function is called by network interface device drivers to inform the + * socket layer of their existence. This registration is necesary to support + * ioctl() operations on network devices to, for example, set MAC and IP + * addresses + */ + +EXTERN int netdev_register(FAR struct uip_driver_s *dev); + +/* netdev-unregister.c *********************************************************/ +/* Unregister a network device driver. */ + +EXTERN int netdev_unregister(FAR struct uip_driver_s *dev); + +/* net_foreach.c ************************************************************/ +/* Enumerates all registered network devices */ + +EXTERN int netdev_foreach(netdev_callback_t callback, void *arg); + +/* drivers/net/slip.c ******************************************************/ +/* Instantiate a SLIP network interface. */ + +#ifdef CONFIG_NET_SLIP +EXTERN int slip_initialize(int intf, const char *devname); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_NET */ +#endif /* __INCLUDE_NUTTX_NET_NET_H */ diff --git a/nuttx/include/nuttx/net/uip/uip-arch.h b/nuttx/include/nuttx/net/uip/uip-arch.h new file mode 100644 index 0000000000..9546de04eb --- /dev/null +++ b/nuttx/include/nuttx/net/uip/uip-arch.h @@ -0,0 +1,370 @@ +/**************************************************************************** + * include/nuttx/net/uip/uip-arch.h + * Defines architecture-specific device driver interfaces to uIP + * + * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Derived largely from portions of uIP with has a similar BSD-styple license: + * + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_UIP_UIP_ARCH_H +#define __INCLUDE_NUTTX_NET_UIP_UIP_ARCH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#ifdef CONFIG_NET_IGMP +# include +#endif + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This structure collects information that is specific to a specific network + * interface driver. If the hardware platform supports only a single instance + * of this structure. + */ + +struct uip_driver_s +{ + /* This link is used to maintain a single-linked list of ethernet drivers. + * Must be the first field in the structure due to blink type casting. + */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + FAR struct uip_driver_s *flink; + + /* This is the name of network device assigned when netdev_register was called. + * This name is only used to support socket ioctl lookups by device name + * Examples: "eth0" + */ + + char d_ifname[IFNAMSIZ]; +#endif + + /* Ethernet device identity */ + +#ifdef CONFIG_NET_ETHERNET + struct ether_addr d_mac; /* Device MAC address */ +#endif + + /* Network identity */ + + uip_ipaddr_t d_ipaddr; /* Host IP address assigned to the network interface */ + uip_ipaddr_t d_draddr; /* Default router IP address */ + uip_ipaddr_t d_netmask; /* Network subnet mask */ + + /* The d_buf array is used to hold incoming and outgoing packets. The device + * driver should place incoming data into this buffer. When sending data, + * the device driver should read the link level headers and the TCP/IP + * headers from this buffer. The size of the link level headers is + * configured by the UIP_LLH_LEN define. + * + * uIP will handle only a single buffer for both incoming and outgoing + * packets. However, the drive design may be concurrently send and + * filling separate, break-off buffers if CONFIG_NET_MULTIBUFFER is + * defined. That buffer management must be controlled by the driver. + */ + +#ifdef CONFIG_NET_MULTIBUFFER + uint8_t *d_buf; +#else + uint8_t d_buf[CONFIG_NET_BUFSIZE + CONFIG_NET_GUARDSIZE]; +#endif + + /* d_appdata points to the location where application data can be read from + * or written into a packet. + */ + + uint8_t *d_appdata; + + /* This is a pointer into d_buf where a user application may append + * data to be sent. + */ + + uint8_t *d_snddata; + +#ifdef CONFIG_NET_TCPURGDATA + /* This pointer points to any urgent TCP data that has been received. Only + * present if compiled with support for urgent data (CONFIG_NET_TCPURGDATA). + */ + + uint8_t *d_urgdata; + + /* Length of the (received) urgent data */ + + uint16_t d_urglen; +#endif + +/* The length of the packet in the d_buf buffer. + * + * Holds the length of the packet in the d_buf buffer. + * + * When the network device driver calls the uIP input function, + * d_len should be set to the length of the packet in the d_buf + * buffer. + * + * When sending packets, the device driver should use the contents of + * the d_len variable to determine the length of the outgoing + * packet. + */ + + uint16_t d_len; + + /* When d_buf contains outgoing xmit data, xmtlen is nonzero and represents + * the amount of appllcation data after d_snddata + */ + + uint16_t d_sndlen; + + /* IGMP group list */ + +#ifdef CONFIG_NET_IGMP + sq_queue_t grplist; +#endif + + /* Driver callbacks */ + + int (*d_ifup)(struct uip_driver_s *dev); + int (*d_ifdown)(struct uip_driver_s *dev); + int (*d_txavail)(struct uip_driver_s *dev); +#ifdef CONFIG_NET_IGMP + int (*d_addmac)(struct uip_driver_s *dev, FAR const uint8_t *mac); + int (*d_rmmac)(struct uip_driver_s *dev, FAR const uint8_t *mac); +#endif + + /* Drivers may attached device-specific, private information */ + + void *d_private; +}; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* uIP device driver functions + * + * These functions are used by a network device driver for interacting + * with uIP. + * + * Process an incoming packet. + * + * This function should be called when the device driver has received + * a packet from the network. The packet from the device driver must + * be present in the d_buf buffer, and the length of the packet + * should be placed in the d_len field. + * + * When the function returns, there may be an outbound packet placed + * in the d_buf packet buffer. If so, the d_len field is set to + * the length of the packet. If no packet is to be sent out, the + * d_len field is set to 0. + * + * The usual way of calling the function is presented by the source + * code below. + * + * dev->d_len = devicedriver_poll(); + * if(dev->d_len > 0) { + * uip_input(dev); + * if(dev->d_len > 0) { + * devicedriver_send(); + * } + * } + * + * Note: If you are writing a uIP device driver that needs ARP + * (Address Resolution Protocol), e.g., when running uIP over + * Ethernet, you will need to call the uIP ARP code before calling + * this function: + * + * #define BUF ((struct uip_eth_hdr *)&dev->d_buf[0]) + * dev->d_len = ethernet_devicedrver_poll(); + * if(dev->d_len > 0) { + * if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { + * uip_arp_ipin(); + * uip_input(dev); + * if(dev->d_len > 0) { + * uip_arp_out(); + * devicedriver_send(); + * } + * } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { + * uip_arp_arpin(); + * if(dev->d_len > 0) { + * devicedriver_send(); + * } + * } + */ + +extern void uip_input(struct uip_driver_s *dev); + +/* Polling of connections + * + * These functions will traverse each active uIP connection structure and + * perform appropriate operatios: uip_timer() will perform TCP timer + * operations (and UDP polling operations); uip_poll() will perform TCP + * and UDP polling operations. The CAN driver MUST implement logic to + * periodically call uip_timer(); uip_poll() may be called asychronously + * from the network driver can accept another outgoing packet. + * + * In both cases, these functions will call the provided callback function + * for every active connection. Polling will continue until all connections + * have been polled or until the user-suplied function returns a non-zero + * value (which it should do only if it cannot accept further write data). + * + * When the callback function is called, there may be an outbound packet + * waiting for service in the uIP packet buffer, and if so the d_len field + * is set to a value larger than zero. The device driver should then send + * out the packet. + * + * Example: + * int driver_callback(struct uip_driver_dev *dev) + * { + * if (dev->d_len > 0) + * { + * devicedriver_send(); + * return 1; <-- Terminates polling if necessary + * } + * return 0; + * } + * + * ... + * uip_poll(dev, driver_callback); + * + * Note: If you are writing a uIP device driver that needs ARP (Address + * Resolution Protocol), e.g., when running uIP over Ethernet, you will + * need to call the uip_arp_out() function in the callback function + * before sending the packet: + * + * int driver_callback(struct uip_driver_dev *dev) + * { + * if (dev->d_len > 0) + * { + * uip_arp_out(); + * devicedriver_send(); + * return 1; <-- Terminates polling if necessary + * } + * return 0; + * } + */ + +typedef int (*uip_poll_callback_t)(struct uip_driver_s *dev); +extern int uip_poll(struct uip_driver_s *dev, uip_poll_callback_t callback); +extern int uip_timer(struct uip_driver_s *dev, uip_poll_callback_t callback, int hsec); + +/* By defining UIP_ARCH_CHKSUM, the architecture can replace up_incr32 + * with hardware assisted solutions. + */ + +/* Carry out a 32-bit addition. + * + * op32 - A pointer to a 4-byte array representing a 32-bit + * integer in network byte order (big endian). This value may not + * be word aligned. The value pointed to by op32 is modified in place + * + * op16 - A 16-bit integer in host byte order. + */ + +extern void uip_incr32(uint8_t *op32, uint16_t op16); + +/* Calculate the Internet checksum over a buffer. + * + * The Internet checksum is the one's complement of the one's + * complement sum of all 16-bit words in the buffer. + * + * See RFC1071. + * + * Note: This function is not called in the current version of uIP, + * but future versions might make use of it. + * + * buf A pointer to the buffer over which the checksum is to be + * computed. + * + * len The length of the buffer over which the checksum is to + * be computed. + * + * Return: The Internet checksum of the buffer. + */ + +extern uint16_t uip_chksum(uint16_t *buf, uint16_t len); + +/* Calculate the IP header checksum of the packet header in d_buf. + * + * The IP header checksum is the Internet checksum of the 20 bytes of + * the IP header. + * + * Return: The IP header checksum of the IP header in the d_buf + * buffer. + */ + +extern uint16_t uip_ipchksum(struct uip_driver_s *dev); + +/* Calculate the TCP checksum of the packet in d_buf and d_appdata. + * + * The TCP checksum is the Internet checksum of data contents of the + * TCP segment, and a pseudo-header as defined in RFC793. + * + * Note: The d_appdata pointer that points to the packet data may + * point anywhere in memory, so it is not possible to simply calculate + * the Internet checksum of the contents of the d_buf buffer. + * + * Return: The TCP checksum of the TCP segment in d_buf and pointed + * to by d_appdata. + */ + +extern uint16_t uip_tcpchksum(struct uip_driver_s *dev); + +extern uint16_t uip_udpchksum(struct uip_driver_s *dev); +extern uint16_t uip_icmpchksum(struct uip_driver_s *dev, int len); + +#endif /* __INCLUDE_NUTTX_NET_UIP_UIP_ARCH_H */ + diff --git a/nuttx/include/nuttx/net/uip/uip-arp.h b/nuttx/include/nuttx/net/uip/uip-arp.h new file mode 100644 index 0000000000..ba704cc135 --- /dev/null +++ b/nuttx/include/nuttx/net/uip/uip-arp.h @@ -0,0 +1,262 @@ +/**************************************************************************** + * include/nuttx/net/uip/uip-arch.h + * Macros and definitions for the ARP module. + * + * Copyright (C) 2007, 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Derived from uIP with has a similar BSD-styple license: + * + * Author: Adam Dunkels + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_UIP_UIP_ARP_H +#define __INCLUDE_NUTTX_NET_UIP_UIP_ARP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Recognized values of the type bytes in the Ethernet header */ + +#define UIP_ETHTYPE_ARP 0x0806 +#define UIP_ETHTYPE_IP 0x0800 +#define UIP_ETHTYPE_IP6 0x86dd + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The Ethernet header -- 14 bytes. The first two fields are type 'struct + * ether_addr but are represented as a simple byte array here because + * some compilers refuse to pack 6 byte structures. + */ + +struct uip_eth_hdr +{ + uint8_t dest[6]; /* Ethernet destination address (6 bytes) */ + uint8_t src[6]; /* Ethernet source address (6 bytes) */ + uint16_t type; /* Type code (2 bytes) */ +}; + +/* One entry in the ARP table (volatile!) */ + +struct arp_entry +{ + in_addr_t at_ipaddr; /* IP address */ + struct ether_addr at_ethaddr; /* Hardware address */ + uint8_t at_time; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_NET_ARP +/**************************************************************************** + * Name: uip_arp_init + * + * Description: + * Initialize the ARP module. This function must be called before any of + * the other ARP functions. + * + ****************************************************************************/ + +EXTERN void uip_arp_init(void); + +/**************************************************************************** + * Name: uip_arp_ipin + * + * Description: + * The uip_arp_ipin() function should be called whenever an IP packet + * arrives from the Ethernet. This function refreshes the ARP table or + * inserts a new mapping if none exists. The function assumes that an + * IP packet with an Ethernet header is present in the d_buf buffer + * and that the length of the packet is in the d_len field. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ARP_IPIN +EXTERN void uip_arp_ipin(struct uip_driver_s *dev); +#else +# define uip_arp_ipin(dev) +#endif + +/**************************************************************************** + * Name: uip_arp_arpin + * + * Description: + * The uip_arp_arpin() should be called when an ARP packet is received + * by the Ethernet driver. This function also assumes that the + * Ethernet frame is present in the d_buf buffer. When the + * uip_arp_arpin() function returns, the contents of the d_buf + * buffer should be sent out on the Ethernet if the d_len field + * is > 0. + * + ****************************************************************************/ + +EXTERN void uip_arp_arpin(struct uip_driver_s *dev); + +/**************************************************************************** + * Name: uip_arp_arpin + * + * Description: + * The uip_arp_out() function should be called when an IP packet + * should be sent out on the Ethernet. This function creates an + * Ethernet header before the IP header in the d_buf buffer. The + * Ethernet header will have the correct Ethernet MAC destination + * address filled in if an ARP table entry for the destination IP + * address (or the IP address of the default router) is present. If no + * such table entry is found, the IP packet is overwritten with an ARP + * request and we rely on TCP to retransmit the packet that was + * overwritten. In any case, the d_len field holds the length of + * the Ethernet frame that should be transmitted. + * + ****************************************************************************/ + +EXTERN void uip_arp_out(struct uip_driver_s *dev); + +/**************************************************************************** + * Name: uip_arp_timer + * + * Description: + * This function performs periodic timer processing in the ARP module + * and should be called at regular intervals. The recommended interval + * is 10 seconds between the calls. It is responsible for flushing old + * entries in the ARP table. + * + ****************************************************************************/ + +EXTERN void uip_arp_timer(void); + +/**************************************************************************** + * Name: uip_arp_update + * + * Description: + * Add the IP/HW address mapping to the ARP table -OR- change the IP + * address of an existing association. + * + * Input parameters: + * pipaddr - Refers to an IP address uint16_t[2] in network order + * ethaddr - Refers to a HW address uint8_t[IFHWADDRLEN] + * + * Assumptions + * Interrupts are disabled + * + ****************************************************************************/ + +EXTERN void uip_arp_update(uint16_t *pipaddr, uint8_t *ethaddr); + +/**************************************************************************** + * Name: uip_arp_find + * + * Description: + * Find the ARP entry corresponding to this IP address. + * + * Input parameters: + * ipaddr - Refers to an IP address in network order + * + * Assumptions + * Interrupts are disabled; Returned value will become unstable when + * interrupts are re-enabled or if any other uIP APIs are called. + * + ****************************************************************************/ + +EXTERN struct arp_entry *uip_arp_find(in_addr_t ipaddr); + +/**************************************************************************** + * Name: uip_arp_delete + * + * Description: + * Remove an IP association from the ARP table + * + * Input parameters: + * ipaddr - Refers to an IP address in network order + * + * Assumptions + * Interrupts are disabled + * + ****************************************************************************/ + +#define uip_arp_delete(ipaddr) \ +{ \ + struct arp_entry *tabptr = uip_arp_find(ipaddr); \ + if (tabptr) \ + { \ + tabptr->at_ipaddr = 0; \ + } \ +} + +#else /* CONFIG_NET_ARP */ + +/* If ARP is disabled, stub out all ARP interfaces */ + +# define uip_arp_init() +# define uip_arp_ipin(dev) +# define uip_arp_arpin(dev) +# define uip_arp_out(dev) +# define uip_arp_timer() +# define uip_arp_update(pipaddr,ethaddr) +# define uip_arp_find(ipaddr) NULL +# define uip_arp_delete(ipaddr) + +#endif /* CONFIG_NET_ARP */ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_NET_UIP_UIP_ARP_H */ diff --git a/nuttx/include/nuttx/net/uip/uip-icmp.h b/nuttx/include/nuttx/net/uip/uip-icmp.h new file mode 100644 index 0000000000..27098d5d36 --- /dev/null +++ b/nuttx/include/nuttx/net/uip/uip-icmp.h @@ -0,0 +1,211 @@ +/**************************************************************************** + * include/nuttx/net/uip/uip-icmp.h + * Header file for the uIP ICMP stack. + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This logic was leveraged from uIP which also has a BSD-style license: + * + * Author Adam Dunkels + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_UIP_UIP_ICMP_H +#define __INCLUDE_NUTTX_NET_UIP_UIP_ICMP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* ICMP/ICMP6 definitions */ + +/* ICMP/ICMP6 Message Types */ + +#define ICMP_ECHO_REPLY 0 /* RFC 792 */ +#define ICMP_DEST_UNREACHABLE 3 /* RFC 792 */ +#define ICMP_SRC_QUENCH 4 /* RFC 792 */ +#define ICMP_REDIRECT 5 /* RFC 792 */ +#define ICMP_ALT_HOST_ADDRESS 6 +#define ICMP_ECHO_REQUEST 8 /* RFC 792 */ +#define ICMP_ROUTER_ADVERTISEMENT 9 /* RFC 1256 */ +#define ICMP_ROUTER_SOLICITATION 10 /* RFC 1256 */ +#define ICMP_TIME_EXCEEDED 11 /* RFC 792 */ +#define ICMP_PARAMETER_PROBLEM 12 +#define ICMP_TIMESTAMP_REQUEST 13 +#define ICMP_TIMESTAMP_REPLY 14 +#define ICMP_INFORMATION_REQUEST 15 +#define ICMP_INFORMATION_REPLY 16 +#define ICMP_ADDRESS_MASK_REQUEST 17 +#define ICMP_ADDRESS_MASK_REPLY 18 +#define ICMP_TRACEROUTE 30 +#define ICMP_CONVERSION_ERROR 31 +#define ICMP_MOBILE_HOST_REDIRECT 32 +#define ICMP_IPV6_WHEREAREYOU 33 +#define ICMP_IPV6_IAMHERE 34 +#define ICMP_MOBILE_REGIS_REQUEST 35 +#define ICMP_MOBILE_REGIS_REPLY 36 +#define ICMP_DOMAIN_NAME_REQUEST 37 +#define ICMP_DOMAIN_NAME_REPLY 38 +#define ICMP_SKIP_DISCOVERY_PROTO 39 +#define ICMP_PHOTURIS_SECURITY_FAIL 40 +#define ICMP_EXP_MOBILE_PROTO 41 /* RFC 4065 */ + +/* ICMP6 Message Types */ + +#define ICMP6_ECHO_REPLY 129 +#define ICMP6_ECHO_REQUEST 128 +#define ICMP6_NEIGHBOR_SOLICITATION 135 +#define ICMP6_NEIGHBOR_ADVERTISEMENT 136 + +#define ICMP6_FLAG_S (1 << 6) + +#define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1 +#define ICMP6_OPTION_TARGET_LINK_ADDRESS 2 + +/* Header sizes */ + +#define UIP_ICMPH_LEN 4 /* Size of ICMP header */ +#define UIP_IPICMPH_LEN (UIP_ICMPH_LEN + UIP_IPH_LEN) /* Size of IP + ICMP header */ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* The ICMP and IP headers */ + +struct uip_icmpip_hdr +{ +#ifdef CONFIG_NET_IPv6 + + /* IPv6 Ip header */ + + uint8_t vtc; /* Bits 0-3: version, bits 4-7: traffic class (MS) */ + uint8_t tcf; /* Bits 0-3: traffic class (LS), bits 4-7: flow label (MS) */ + uint16_t flow; /* 16-bit flow label (LS) */ + uint8_t len[2]; /* 16-bit Payload length */ + uint8_t proto; /* 8-bit Next header (same as IPv4 protocol field) */ + uint8_t ttl; /* 8-bit Hop limit (like IPv4 TTL field) */ + uip_ip6addr_t srcipaddr; /* 128-bit Source address */ + uip_ip6addr_t destipaddr; /* 128-bit Destination address */ + +#else /* CONFIG_NET_IPv6 */ + + /* IPv4 IP header */ + + uint8_t vhl; /* 8-bit Version (4) and header length (5 or 6) */ + uint8_t tos; /* 8-bit Type of service (e.g., 6=TCP) */ + uint8_t len[2]; /* 16-bit Total length */ + uint8_t ipid[2]; /* 16-bit Identification */ + uint8_t ipoffset[2]; /* 16-bit IP flags + fragment offset */ + uint8_t ttl; /* 8-bit Time to Live */ + uint8_t proto; /* 8-bit Protocol */ + uint16_t ipchksum; /* 16-bit Header checksum */ + uint16_t srcipaddr[2]; /* 32-bit Source IP address */ + uint16_t destipaddr[2]; /* 32-bit Destination IP address */ + +#endif /* CONFIG_NET_IPv6 */ + + /* ICMP header */ + + uint8_t type; /* Defines the format of the ICMP message */ + uint8_t icode; /* Further qualifies the ICMP messsage */ + uint16_t icmpchksum; /* Checksum of ICMP header and data */ + + /* Data following the ICMP header contains the data specific to the + * message type indicated by the Type and Code fields. + */ + +#ifndef CONFIG_NET_IPv6 + + /* ICMP_ECHO_REQUEST and ICMP_ECHO_REPLY data */ + + uint16_t id; /* Used to match requests with replies */ + uint16_t seqno; /* " " "" " " " " " " " " */ + +#else /* !CONFIG_NET_IPv6 */ + + /* ICMP6_ECHO_REQUEST and ICMP6_ECHO_REPLY data */ + + uint8_t flags; + uint8_t reserved1; + uint8_t reserved2; + uint8_t reserved3; + uint8_t icmp6data[16]; + uint8_t options[1]; + +#endif /* !CONFIG_NET_IPv6 */ +}; + +/* The structure holding the ICMP statistics that are gathered if + * CONFIG_NET_STATISTICS is defined. + */ + +#ifdef CONFIG_NET_STATISTICS +struct uip_icmp_stats_s +{ + uip_stats_t drop; /* Number of dropped ICMP packets */ + uip_stats_t recv; /* Number of received ICMP packets */ + uip_stats_t sent; /* Number of sent ICMP packets */ + uip_stats_t typeerr; /* Number of ICMP packets with a wrong type */ +}; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN int uip_ping(uip_ipaddr_t addr, uint16_t id, uint16_t seqno, uint16_t datalen, int dsecs); + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif /* __INCLUDE_NUTTX_NET_UIP_UIP_ICMP_H */ diff --git a/nuttx/include/nuttx/net/uip/uip-igmp.h b/nuttx/include/nuttx/net/uip/uip-igmp.h new file mode 100644 index 0000000000..8b6d79e619 --- /dev/null +++ b/nuttx/include/nuttx/net/uip/uip-igmp.h @@ -0,0 +1,258 @@ +/**************************************************************************** + * include/nuttx/net/uip/uip-igmp.h + * The definitions in this header file are intended only for internal use + * by the NuttX port of the uIP stack. + * + * Copyright (C) 2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * The NuttX implementation of IGMP was inspired by the IGMP add-on for the + * lwIP TCP/IP stack by Steve Reynolds: + * + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_UIP_UIP_IGMP_H +#define __INCLUDE_NUTTX_NET_UIP_UIP_IGMP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include +#include + +#ifdef CONFIG_NET_IGMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +# error "IGMP for IPv6 not supported" +#endif + +/* IGMP packet types */ + +#define IGMP_MEMBERSHIP_QUERY 0x11 /* Membership Query */ +#define IGMPv1_MEMBERSHIP_REPORT 0x12 /* IGMP Ver. 1 Membership Report */ +#define IGMPv2_MEMBERSHIP_REPORT 0x16 /* IGMP Ver. 2 Membership Report */ +#define IGMPv3_MEMBERSHIP_REPORT 0x22 /* IGMP Ver. 3 Membership Report */ +#define IGMP_LEAVE_GROUP 0x17 /* Leave Group */ + +/* Header sizes: + * + * UIP_IGMPH_LEN - Size of IGMP header in bytes + * UIP_IPIGMPH_LEN - Size of IP + Size of IGMP header + Size of router alert + */ + +#define UIP_IGMPH_LEN 8 +#define UIP_IPIGMPH_LEN (UIP_IGMPH_LEN + UIP_IPH_LEN + 4) + +/* Group flags */ + +#define IGMP_PREALLOCATED (1 << 0) +#define IGMP_LASTREPORT (1 << 1) +#define IGMP_IDLEMEMBER (1 << 2) +#define IGMP_SCHEDMSG (1 << 3) +#define IGMP_WAITMSG (1 << 4) + +#define SET_PREALLOCATED(f) do { (f) |= IGMP_PREALLOCATED; } while (0) +#define SET_LASTREPORT(f) do { (f) |= IGMP_LASTREPORT; } while (0) +#define SET_IDLEMEMBER(f) do { (f) |= IGMP_IDLEMEMBER; } while (0) +#define SET_SCHEDMSG(f) do { (f) |= IGMP_SCHEDMSG; } while (0) +#define SET_WAITMSG(f) do { (f) |= IGMP_WAITMSG; } while (0) + +#define CLR_PREALLOCATED(f) do { (f) &= ~IGMP_PREALLOCATED; } while (0) +#define CLR_LASTREPORT(f) do { (f) &= ~IGMP_LASTREPORT; } while (0) +#define CLR_IDLEMEMBER(f) do { (f) &= ~IGMP_IDLEMEMBER; } while (0) +#define CLR_SCHEDMSG(f) do { (f) &= ~IGMP_SCHEDMSG; } while (0) +#define CLR_WAITMSG(f) do { (f) &= ~IGMP_WAITMSG; } while (0) + +#define IS_PREALLOCATED(f) (((f) & IGMP_PREALLOCATED) != 0) +#define IS_LASTREPORT(f) (((f) & IGMP_LASTREPORT) != 0) +#define IS_IDLEMEMBER(f) (((f) & IGMP_IDLEMEMBER) != 0) +#define IS_SCHEDMSG(f) (((f) & IGMP_SCHEDMSG) != 0) +#define IS_WAITMSG(f) (((f) & IGMP_WAITMSG) != 0) + +#define IGMP_TTL 1 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* IGMPv2 packet structure as defined by RFC 2236. + * + * The Max Respone Time (maxresp) specifies the time limit for the + * corresponding report. The field has a resolution of 100 miliseconds, the + * value is taken directly. This field is meaningful only in Membership Query + * (0x11); in other messages it is set to 0 and ignored by the receiver. + */ + +struct uip_igmphdr_s +{ +#ifdef CONFIG_NET_IPv6 + + /* IPv6 Ip header */ + + uint8_t vtc; /* Bits 0-3: version, bits 4-7: traffic class (MS) */ + uint8_t tcf; /* Bits 0-3: traffic class (LS), bits 4-7: flow label (MS) */ + uint16_t flow; /* 16-bit flow label (LS) */ + uint8_t len[2]; /* 16-bit Payload length */ + uint8_t proto; /* 8-bit Next header (same as IPv4 protocol field) */ + uint8_t ttl; /* 8-bit Hop limit (like IPv4 TTL field) */ + uip_ip6addr_t srcipaddr; /* 128-bit Source address */ + uip_ip6addr_t destipaddr; /* 128-bit Destination address */ + +#else /* CONFIG_NET_IPv6 */ + + /* IPv4 IP header */ + + uint8_t vhl; /* 8-bit Version (4) and header length (6 with Router Alert) */ + uint8_t tos; /* 8-bit Type of service (e.g., 6=TCP) */ + uint8_t len[2]; /* 16-bit Total length */ + uint8_t ipid[2]; /* 16-bit Identification */ + uint8_t ipoffset[2]; /* 16-bit IP flags + fragment offset */ + uint8_t ttl; /* 8-bit Time to Live */ + uint8_t proto; /* 8-bit Protocol */ + uint16_t ipchksum; /* 16-bit Header checksum */ + uint16_t srcipaddr[2]; /* 32-bit Source IP address */ + uint16_t destipaddr[2]; /* 32-bit Destination IP address */ + +#endif /* CONFIG_NET_IPv6 */ + + /* Router Alert IP header option */ + + uint16_t ra[2]; + + /* IGMPv2 header: + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type | Max Resp Time | Checksum | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Group Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + uint8_t type; /* 8-bit IGMP packet type */ + uint8_t maxresp; /* 8-bit Max response time */ + uint16_t chksum; /* 16-bit Checksum */ + uint16_t grpaddr[2]; /* 32-bit Group address */ +}; + +#ifdef CONFIG_NET_STATISTICS +struct uip_igmp_stats_s +{ + uint32_t length_errors; + uint32_t chksum_errors; + uint32_t v1_received; + uint32_t joins; + uint32_t leaves; + uint32_t leave_sched; + uint32_t report_sched; + uint32_t poll_send; + uint32_t ucast_query; + uint32_t query_received; + uint32_t report_received; +}; + +# define IGMP_STATINCR(p) ((p)++) +#else +# define IGMP_STATINCR(p) +#endif + +/* This structure represents one group member. There is a list of groups + * for each device interface structure. + * + * There will be a group for the all systems group address but this + * will not run the state machine as it is used to kick off reports + * from all the other groups + */ + +typedef FAR struct wdog_s *WDOG_ID; +struct igmp_group_s +{ + struct igmp_group_s *next; /* Implements a singly-linked list */ + uip_ipaddr_t grpaddr; /* Group IP address */ + WDOG_ID wdog; /* WDOG used to detect timeouts */ + sem_t sem; /* Used to wait for message transmission */ + volatile uint8_t flags; /* See IGMP_ flags definitions */ + uint8_t msgid; /* Pending message ID (if non-zero) */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN uip_ipaddr_t g_allsystems; +EXTERN uip_ipaddr_t g_allrouters; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_igmpdevinit + * + * Description: + * Called when a new network device is registered to configure that device + * for IGMP support. + * + ****************************************************************************/ + +EXTERN void uip_igmpdevinit(struct uip_driver_s *dev); +EXTERN int igmp_joingroup(struct uip_driver_s *dev, FAR const struct in_addr *grpaddr); +EXTERN int igmp_leavegroup(struct uip_driver_s *dev, FAR const struct in_addr *grpaddr); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* CONFIG_NET_IGMP */ +#endif /* __INCLUDE_NUTTX_NET_UIP_UIP_IGMP_H */ diff --git a/nuttx/include/nuttx/net/uip/uip-ipopt.h b/nuttx/include/nuttx/net/uip/uip-ipopt.h new file mode 100644 index 0000000000..2d7393c028 --- /dev/null +++ b/nuttx/include/nuttx/net/uip/uip-ipopt.h @@ -0,0 +1,251 @@ +/************************************************************************************************************ + * include/nuttx/net/uip/uip-ipopt.h + * + * Defines values for the IP header options + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_UIP_UIP_IPOPT_H +#define __INCLUDE_NUTTX_NET_UIP_UIP_IPOPT_H + +/************************************************************************************************************ + * Included Files + ************************************************************************************************************/ + +#include + +/************************************************************************************************************ + * Pre-processor Definitions + ************************************************************************************************************/ + +/* IP Header Options: + * + * The basic 20-byte IP header can be extended by up to another 40 bytes + * (in units of 4 bytes) to provide IP options. The format of a single IP + * option is as follows: + * + * Single byte options: + * + * Type: 8-bits + * + * Multi-byte options: + * + * Type: 8-bits + * Length: 8-bits + * Pointer: 8-bits: + * Option Data: (depends on Length) + * + * The IP Option Type byte consists of the following subfields: + */ + +#define IPOPT_TYPE_OPTION_SHIFT (0) /* Bits 0-5: Option number*/ +#define IPOPT_TYPE_OPTION_MASK (0x1f << IPOPT_TYPE_OPTION_SHIFT) +# define IPOPT_TYPE_OPTION_END (0 << IPOPT_TYPE_OPTION_SHIFT) /* End of options list (RFC 791) */ +# define IPOPT_TYPE_OPTION_NOOP (1 << IPOPT_TYPE_OPTION_SHIFT) /* No operation (RFC 791) */ +# define IPOPT_TYPE_OPTION_SEC (2 << IPOPT_TYPE_OPTION_SHIFT) /* Security (RFC 791, 1108) */ +# define IPOPT_TYPE_OPTION_LSRR (3 << IPOPT_TYPE_OPTION_SHIFT) /* Loose source and record route (RFC 791) */ +# define IPOPT_TYPE_OPTION_TIMESTAMP (4 << IPOPT_TYPE_OPTION_SHIFT) /* Timestamp (RFC 781, 791) */ +# define IPOPT_TYPE_OPTION_EXTSEC (5 << IPOPT_TYPE_OPTION_SHIFT) /* Extended security (RFC 1108) */ +# define IPOPT_TYPE_OPTION_COMMSEC (6 << IPOPT_TYPE_OPTION_SHIFT) /* Commercial security */ +# define IPOPT_TYPE_OPTION_RR (7 << IPOPT_TYPE_OPTION_SHIFT) /* Record route (RFC 791) */ +# define IPOPT_TYPE_OPTION_SSID (8 << IPOPT_TYPE_OPTION_SHIFT) /* Stream ID (RFC 791, 1122) */ +# define IPOPT_TYPE_OPTION_SSRR (9 << IPOPT_TYPE_OPTION_SHIFT) /* Strict source and record route (RFC 791) */ +# define IPOPT_TYPE_OPTION_EXPMEAS (10 << IPOPT_TYPE_OPTION_SHIFT) /* Experimental measurement */ +# define IPOPT_TYPE_OPTION_MTUPROBE (11 << IPOPT_TYPE_OPTION_SHIFT) /* MTU Probe (RFC 1063) */ +# define IPOPT_TYPE_OPTION_MTUREPLY (12 << IPOPT_TYPE_OPTION_SHIFT) /* MTU Reply (RFC 1063) */ +# define IPOPT_TYPE_OPTION_EXPFC (13 << IPOPT_TYPE_OPTION_SHIFT) /* Experimental flow control */ +# define IPOPT_TYPE_OPTION_EXPAC (14 << IPOPT_TYPE_OPTION_SHIFT) /* Experimental access control */ +# define IPOPT_TYPE_OPTION_ENCODE (15 << IPOPT_TYPE_OPTION_SHIFT) /* ENCODE */ +# define IPOPT_TYPE_OPTION_IMITD (16 << IPOPT_TYPE_OPTION_SHIFT) /* IMI traffic descriptor */ +# define IPOPT_TYPE_OPTION_EXTIP (17 << IPOPT_TYPE_OPTION_SHIFT) /* Extended IP (RFC 1385) */ +# define IPOPT_TYPE_OPTION_TR (18 << IPOPT_TYPE_OPTION_SHIFT) /* Traceroute (RFC 1393) */ +# define IPOPT_TYPE_OPTION_ADDREXT (19 << IPOPT_TYPE_OPTION_SHIFT) /* Address extension (RFC 1475) */ +# define IPOPT_TYPE_OPTION_RA (20 << IPOPT_TYPE_OPTION_SHIFT) /* Router alert (RFC 2113) */ +# define IPOPT_TYPE_OPTION_SDBM (21 << IPOPT_TYPE_OPTION_SHIFT) /* Selective direct broadcast mode (RFC 1770) */ +# define IPOPT_TYPE_OPTION_DPS (23 << IPOPT_TYPE_OPTION_SHIFT) /* Dynamic packet state */ +# define IPOPT_TYPE_OPTION_UMP (24 << IPOPT_TYPE_OPTION_SHIFT) /* Upstream multicast packet */ +# define IPOPT_TYPE_OPTION_QS (25 << IPOPT_TYPE_OPTION_SHIFT) /* Quick start (RFC 4782) */ +# define IPOPT_TYPE_OPTION_EXP3692 (30 << IPOPT_TYPE_OPTION_SHIFT) /* RFC 3692-style experiment (RFC 4782) */ +#define IPOPT_TYPE_CLASS_SHIFT (5) /* Bits 5-6: Class */ +#define IPOPT_TYPE_CLASS_MASK (3 << IPOPT_TYPE_CLASS_SHIFT) +# define IPOPT_TYPE_CLASS_CTRL (0 << IPOPT_TYPE_CLASS_SHIFT) /* Control */ +# define IPOPT_TYPE_CLASS_MEASURE (2 << IPOPT_TYPE_CLASS_SHIFT) /* Debugging and measurement */ +#define IPOPT_TYPE_COPIED (1 << 7) /* Bit 7: IP layer must copy option to each fragment */ +#define IPOPT_TYPE_NOTCOPIED (0) + +/* IP Option encoding macros */ + +#define IPOPT_MKTYPE(copied,class,option) (copied|class|option) + +#define IPOPT_MKOPTION8(copied,class,option) \ + ((uint8_t)IPOPT_MKTYPE(copied,class,option)) +#define IPOPT_MKOPTION32(type,len,ptr,data) \ + ((uint32_t)(type) << 24 | (uint32_t)(len) << 16 | \ + (uint32_t)(ptr) << 8 | (uint32_t)(data)) + +/* Option Copy Class Length Description References + * ------ ---- ----- --------- ------------------------------------------------ + * 0 0 0 1 End of options list (RFC 791) + * 1 0 0 1 NOP (RFC 791 + * 2 1 0 11 Security (RFC 791, RFC 1108) + * 3 1 0 variable Loose Source Route (RFC 791) + * 4 0 2 variable Time stamp (RFC 781, RFC 791) + * 5 1 0 3-31 Extended Security (RFC 1108) + * 6 1 0 Commercial Security + * 7 0 0 variable Record Route (RFC 791) + * 8 1 0 4 Stream Identifier (RFC 791, RFC 1122) + * 9 1 0 variable Strict Source Route (RFC 791) + * 10 0 0 Experimental Measurement + * 11 0 0 4 MTU Probe (obsolete) (RFC 1063) + * 12 0 0 4 MTU Reply (obsolete) (RFC 1063) + * 13 1 2 Experimental Flow Control + * 14 1 0 Experimental Access Control + * 15 0 0 ENCODE + * 16 1 0 IMI Traffic Descriptor + * 17 1 0 variable Extended Internet Protocol (RFC 1385) + * 18 0 2 12 Traceroute (RFC 1393) + * 19 1 0 10 Address Extension (RFC 1475) + * 20 1 0 4 Router Alert (RFC 2113) + * 21 1 0 6-38 Selective Directed Broadcast Mode (RFC 1770) + * 22 1 0 + * 23 1 0 Dynamic Packet State + * 24 1 0 Upstream Multicast Packet + * 25 0 0 QS, Quick-Start (RFC 4782) + * 26 + * - + * 29 + * 30 0 0 EXP - RFC3692-style Experiment (RFC 4727) + * 30 0 2 EXP - RFC3692-style Experiment (RFC 4727) + * 30 1 0 EXP - RFC3692-style Experiment RFC 4727) + * 30 1 2 EXP - RFC3692-style Experiment (RFC 4727) + * 31 + */ + +#define IPOTR_END_LEN 1 +#define IPOPT_END_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_NOTCOPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_END) + +#define IPOTR_NOOP_LEN 1 +#define IPOPT_NOOP_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_NOTCOPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_NOOP) + +#define IPOPT_SEC_LEN 11 +#define IPOPT_SEC_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_SEC) + +#define IPOPT_LSRR_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_LSRR) + +#define IPOPT_TIMESTAMP_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_NOTCOPIED, IPOPT_TYPE_CLASS_MEASURE, IPOPT_TYPE_OPTION_TIMESTAMP) + +#define IPOPT_EXTSEC_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_EXTSEC) + +#define IPOPT_COMMSEC_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_COMMSEC) + +#define IPOPT_RR_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_NOTCOPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_RR) + +#define IPOPT_SSID_LEN 4 +#define IPOPT_SSID_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_SSID) + +#define IPOPT_SSRR_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_SSRR) +#define IPOPT_EXPMEAS_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_NOTCOPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_EXPMEAS) + +#define IPOPT_MTUPROBE_LEN 4 +#define IPOPT_MTUPROBE_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_NOTCOPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_MTUPROBE) + +#define IPOPT_MTUREPLY_LEN 4 +#define IPOPT_MTUREPLY_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_NOTCOPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_MTUREPLY) + +#define IPOPT_EXPFC_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_MEASURE, IPOPT_TYPE_OPTION_EXPFC) + +#define IPOPT_EXPAC_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_EXPAC) + +#define IPOPT_ENCODE_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_NOTCOPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_ENCODE) + +#define IPOPT_IMITD_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_IMITD) + +#define IPOPT_EXTIP_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_EXTIP) + +#define IPOPT_TR_LEN 12 +#define IPOPT_TR_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_NOTCOPIED, IPOPT_TYPE_CLASS_MEASURE, IPOPT_TYPE_OPTION_TR) + +#define IPOPT_ADDREXT_LEN 10 +#define IPOPT_ADDREXT_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_ADDREXT) + +#define IPOPT_RA_LEN 4 +#define IPOPT_RA_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_RA) +#define IPOPT_RA \ + IPOPT_MKOPTION32(IPOPT_RA_TYPE, 4, 0, 0) + +#define IPOPT_SDBM_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_SDBM) + +#define IPOPT_DPS_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_DPS) + +#define IPOPT_UMP_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_COPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_UMP) + +#define IPOPT_QS_TYPE \ + IPOPT_MKTYPE(IPOPT_TYPE_NOTCOPIED, IPOPT_TYPE_CLASS_CTRL, IPOPT_TYPE_OPTION_QS) + +/************************************************************************************************************ + * Public Type Definitions + ************************************************************************************************************/ + +/************************************************************************************************************ + * Public Data + ************************************************************************************************************/ + +/************************************************************************************************************ + * Public Function Prototypes + ************************************************************************************************************/ + +#endif /* __INCLUDE_NUTTX_NET_UIP_UIP_IPOPT_H */ diff --git a/nuttx/include/nuttx/net/uip/uip-tcp.h b/nuttx/include/nuttx/net/uip/uip-tcp.h new file mode 100644 index 0000000000..c3c800d7bd --- /dev/null +++ b/nuttx/include/nuttx/net/uip/uip-tcp.h @@ -0,0 +1,460 @@ +/**************************************************************************** + * include/nuttx/net/uip/uip-tcp.h + * Header file for the uIP TCP/IP stack. + * + * The uIP TCP/IP stack header file contains definitions for a number + * of C macros that are used by uIP programs as well as internal uIP + * structures, TCP/IP header structures and function declarations. + * + * Copyright (C) 2007, 2009-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This logic was leveraged from uIP which also has a BSD-style license: + * + * Author Adam Dunkels + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_UIP_UIP_TCP_H +#define __INCLUDE_NUTTX_NET_UIP_UIP_TCP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET_TCP + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* TCP definitions */ + +#define TCP_FIN 0x01 +#define TCP_SYN 0x02 +#define TCP_RST 0x04 +#define TCP_PSH 0x08 +#define TCP_ACK 0x10 +#define TCP_URG 0x20 +#define TCP_CTL 0x3f + +#define TCP_OPT_END 0 /* End of TCP options list */ +#define TCP_OPT_NOOP 1 /* "No-operation" TCP option */ +#define TCP_OPT_MSS 2 /* Maximum segment size TCP option */ + +#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */ + +/* The TCP states used in the struct uip_conn tcpstateflags field */ + +#define UIP_TS_MASK 0x0f /* Bits 0-3: TCP state */ +#define UIP_CLOSED 0x00 /* The connection is not in use and available */ +#define UIP_ALLOCATED 0x01 /* The connection is allocated, but not yet initialized */ +#define UIP_SYN_RCVD 0x02 +#define UIP_SYN_SENT 0x03 +#define UIP_ESTABLISHED 0x04 +#define UIP_FIN_WAIT_1 0x05 +#define UIP_FIN_WAIT_2 0x06 +#define UIP_CLOSING 0x07 +#define UIP_TIME_WAIT 0x08 +#define UIP_LAST_ACK 0x09 +#define UIP_STOPPED 0x10 /* Bit 4: stopped */ + /* Bit 5-7: Unused, but not available */ + +/* Flag bits in 16-bit flags+ipoffset IPv4 TCP header field */ + +#define UIP_TCPFLAG_RESERVED 0x8000 +#define UIP_TCPFLAG_DONTFRAG 0x4000 +#define UIP_TCPFLAG_MOREFRAGS 0x2000 + +/* TCP header sizes */ + +#define UIP_TCPH_LEN 20 /* Size of TCP header */ +#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + TCP header */ +#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* Representation of a uIP TCP connection. + * + * The uip_conn structure is used for identifying a connection. All + * but one field in the structure are to be considered read-only by an + * application. The only exception is the "private: field whos purpose + * is to let the application store application-specific state (e.g., + * file pointers) for the connection. + */ + +struct uip_driver_s; /* Forward reference */ +struct uip_callback_s; /* Forward reference */ +struct uip_backlog_s; /* Forward reference */ + +struct uip_conn +{ + dq_entry_t node; /* Implements a doubly linked list */ + uip_ipaddr_t ripaddr; /* The IP address of the remote host */ + uint16_t lport; /* The local TCP port, in network byte order */ + uint16_t rport; /* The remoteTCP port, in network byte order */ + uint8_t rcvseq[4]; /* The sequence number that we expect to + * receive next */ + uint8_t sndseq[4]; /* The sequence number that was last sent by us */ + uint16_t unacked; /* Number bytes sent but not yet ACKed */ + uint16_t mss; /* Current maximum segment size for the + * connection */ + uint16_t initialmss; /* Initial maximum segment size for the + * connection */ + uint8_t crefs; /* Reference counts on this instance */ + uint8_t sa; /* Retransmission time-out calculation state + * variable */ + uint8_t sv; /* Retransmission time-out calculation state + * variable */ + uint8_t rto; /* Retransmission time-out */ + uint8_t tcpstateflags; /* TCP state and flags */ + uint8_t timer; /* The retransmission timer (units: half-seconds) */ + uint8_t nrtx; /* The number of retransmissions for the last + * segment sent */ + + /* Read-ahead buffering. + * + * readahead - A singly linked list of type struct uip_readahead_s + * where the TCP/IP read-ahead data is retained. + */ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + sq_queue_t readahead; /* Read-ahead buffering */ +#endif + + /* Listen backlog support + * + * blparent - The backlog parent. If this connection is backlogged, + * this field will be non-null and will refer to the TCP connection + * structure in which this connection is backlogged. + * backlog - The pending connection backlog. If this connection is + * configured as a listener with backlog, then this refers to the + * struct uip_backlog_s tear-off structure that manages that backlog. + */ + +#ifdef CONFIG_NET_TCPBACKLOG + struct uip_conn *blparent; + struct uip_backlog_s *backlog; +#endif + + /* Application callbacks: + * + * Data transfer events are retained in 'list'. Event handlers in 'list' + * are called for events specified in the flags set within struct + * uip_callback_s + * + * When an callback is executed from 'list', the input flags are normally + * returned, however, the implementation may set one of the following: + * + * UIP_CLOSE - Gracefully close the current connection + * UIP_ABORT - Abort (reset) the current connection on an error that + * prevents UIP_CLOSE from working. + * + * And/Or set/clear the following: + * + * UIP_NEWDATA - May be cleared to indicate that the data was consumed + * and that no further process of the new data should be + * attempted. + * UIP_SNDACK - If UIP_NEWDATA is cleared, then UIP_SNDACK may be set + * to indicate that an ACK should be included in the response. + * (In UIP_NEWDATA is cleared bu UIP_SNDACK is not set, then + * dev->d_len should also be cleared). + */ + + struct uip_callback_s *list; + + /* accept() is called when the TCP logic has created a connection */ + + FAR void *accept_private; + int (*accept)(FAR struct uip_conn *listener, struct uip_conn *conn); + + /* connection_event() is called on any of the subset of connection-related events */ + + FAR void *connection_private; + void (*connection_event)(FAR struct uip_conn *conn, uint16_t flags); +}; + +/* The following structure is used to handle read-ahead buffering for TCP + * connection. When incoming TCP data is received while no application is + * listening for the data, that data will be retained in these read-ahead + * buffers so that no data is lost. + */ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 +struct uip_readahead_s +{ + sq_entry_t rh_node; /* Supports a singly linked list */ + uint16_t rh_nbytes; /* Number of bytes available in this buffer */ + uint8_t rh_buffer[CONFIG_NET_TCP_READAHEAD_BUFSIZE]; +}; +#endif + +/* Support for listen backlog: + * + * struct uip_blcontainer_s describes one backlogged connection + * struct uip_backlog_s is a "tear-off" describing all backlog for a + * listener connection + */ + +#ifdef CONFIG_NET_TCPBACKLOG +struct uip_blcontainer_s +{ + sq_entry_t bc_node; /* Implements a singly linked list */ + FAR struct uip_conn *bc_conn; /* Holds reference to the new connection structure */ +}; + +struct uip_backlog_s +{ + sq_queue_t bl_free; /* Implements a singly-linked list of free containers */ + sq_queue_t bl_pending; /* Implements a singly-linked list of pending connections */ +}; +#endif + +/* The structure holding the TCP/IP statistics that are gathered if + * CONFIG_NET_STATISTICS is defined. + */ + +#ifdef CONFIG_NET_STATISTICS +struct uip_tcp_stats_s +{ + uip_stats_t drop; /* Number of dropped TCP segments */ + uip_stats_t recv; /* Number of received TCP segments */ + uip_stats_t sent; /* Number of sent TCP segments */ + uip_stats_t chkerr; /* Number of TCP segments with a bad checksum */ + uip_stats_t ackerr; /* Number of TCP segments with a bad ACK number */ + uip_stats_t rst; /* Number of received TCP RST (reset) segments */ + uip_stats_t rexmit; /* Number of retransmitted TCP segments */ + uip_stats_t syndrop; /* Number of dropped SYNs due to too few + available connections */ + uip_stats_t synrst; /* Number of SYNs for closed ports triggering a RST */ +}; +#endif + +/* The TCP and IP headers */ + +struct uip_tcpip_hdr +{ +#ifdef CONFIG_NET_IPv6 + + /* IPv6 Ip header */ + + uint8_t vtc; /* Bits 0-3: version, bits 4-7: traffic class (MS) */ + uint8_t tcf; /* Bits 0-3: traffic class (LS), 4-bits: flow label (MS) */ + uint16_t flow; /* 16-bit flow label (LS) */ + uint8_t len[2]; /* 16-bit Payload length */ + uint8_t proto; /* 8-bit Next header (same as IPv4 protocol field) */ + uint8_t ttl; /* 8-bit Hop limit (like IPv4 TTL field) */ + uip_ip6addr_t srcipaddr; /* 128-bit Source address */ + uip_ip6addr_t destipaddr; /* 128-bit Destination address */ + +#else /* CONFIG_NET_IPv6 */ + + /* IPv4 IP header */ + + uint8_t vhl; /* 8-bit Version (4) and header length (5 or 6) */ + uint8_t tos; /* 8-bit Type of service (e.g., 6=TCP) */ + uint8_t len[2]; /* 16-bit Total length */ + uint8_t ipid[2]; /* 16-bit Identification */ + uint8_t ipoffset[2]; /* 16-bit IP flags + fragment offset */ + uint8_t ttl; /* 8-bit Time to Live */ + uint8_t proto; /* 8-bit Protocol */ + uint16_t ipchksum; /* 16-bit Header checksum */ + uint16_t srcipaddr[2]; /* 32-bit Source IP address */ + uint16_t destipaddr[2]; /* 32-bit Destination IP address */ + +#endif /* CONFIG_NET_IPv6 */ + + /* TCP header */ + + uint16_t srcport; + uint16_t destport; + uint8_t seqno[4]; + uint8_t ackno[4]; + uint8_t tcpoffset; + uint8_t flags; + uint8_t wnd[2]; + uint16_t tcpchksum; + uint8_t urgp[2]; + uint8_t optdata[4]; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* uIP application functions + * + * Functions used by an application running of top of uIP. This includes + * functions for opening and closing connections, sending and receiving + * data, etc. + * + * Find a free connection structure and allocate it for use. This is + * normally something done by the implementation of the socket() API + */ + +extern struct uip_conn *uip_tcpalloc(void); + +/* Allocate a new TCP data callback */ + +#define uip_tcpcallbackalloc(conn) uip_callbackalloc(&conn->list) +#define uip_tcpcallbackfree(conn,cb) uip_callbackfree(cb, &conn->list) + +/* Free a connection structure that is no longer in use. This should + * be done by the implementation of close() + */ + +extern void uip_tcpfree(struct uip_conn *conn); + +/* Bind a TCP connection to a local address */ + +#ifdef CONFIG_NET_IPv6 +extern int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in6 *addr); +#else +extern int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in *addr); +#endif + +/* This function implements the UIP specific parts of the standard + * TCP connect() operation: It connects to a remote host using TCP. + * + * This function is used to start a new connection to the specified + * port on the specied host. It uses the connection structure that was + * allocated by a preceding socket() call. It sets the connection to + * the SYN_SENT state and sets the retransmission timer to 0. This will + * cause a TCP SYN segment to be sent out the next time this connection + * is periodically processed, which usually is done within 0.5 seconds + * after the call to uip_tcpconnect(). + * + * This function is called from normal user level code. + */ + +#ifdef CONFIG_NET_IPv6 +extern int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in6 *addr); +#else +extern int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr); +#endif + +/* Start listening to the port bound to the specified TCP connection */ + +extern int uip_listen(struct uip_conn *conn); + +/* Stop listening to the port bound to the specified TCP connection */ + +extern int uip_unlisten(struct uip_conn *conn); + +/* Access to TCP read-ahead buffers */ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 +extern struct uip_readahead_s *uip_tcpreadaheadalloc(void); +extern void uip_tcpreadaheadrelease(struct uip_readahead_s *buf); +#endif /* CONFIG_NET_NTCP_READAHEAD_BUFFERS */ + +/* Backlog support */ + +#ifdef CONFIG_NET_TCPBACKLOG +/* APIs to create and terminate TCP backlog support */ + +extern int uip_backlogcreate(FAR struct uip_conn *conn, int nblg); +extern int uip_backlogdestroy(FAR struct uip_conn *conn); + +/* APIs to manage individual backlog actions */ + +extern int uip_backlogadd(FAR struct uip_conn *conn, FAR struct uip_conn *blconn); +#ifndef CONFIG_DISABLE_POLL +extern bool uip_backlogavailable(FAR struct uip_conn *conn); +#else +# define uip_backlogavailable(conn) (false); +#endif +extern FAR struct uip_conn *uip_backlogremove(FAR struct uip_conn *conn); +extern int uip_backlogdelete(FAR struct uip_conn *conn, FAR struct uip_conn *blconn); + +#else +# define uip_backlogcreate(conn,nblg) (-ENOSYS) +# define uip_backlogdestroy(conn) (-ENOSYS) +# define uip_backlogadd(conn,blconn) (-ENOSYS) +# define uip_backlogavailable(conn) (false); +# define uip_backlogremove(conn) (NULL) +#endif + +/* Tell the sending host to stop sending data. + * + * This function will close our receiver's window so that we stop + * receiving data for the current connection. + */ + +#define uip_stop(conn) ((conn)->tcpstateflags |= UIP_STOPPED) + +/* Find out if the current connection has been previously stopped with + * uip_stop(). + */ + +#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) + +/* Restart the current connection, if is has previously been stopped + * with uip_stop(). + * + * This function will open the receiver's window again so that we start + * receiving data for the current connection. + */ + +#define uip_restart(conn,f) \ + do { \ + (f) |= UIP_NEWDATA; \ + (conn)->tcpstateflags &= ~UIP_STOPPED; \ + } while(0) + +/* Get the initial maxium segment size (MSS) of the current + * connection. + */ + +#define uip_initialmss(conn) ((conn)->initialmss) + +/* Get the current maximum segment size that can be sent on the current + * connection. + * + * The current maxiumum segment size that can be sent on the connection is + * computed from the receiver's window and the MSS of the connection (which + * also is available by calling uip_initialmss()). + */ + +#define uip_mss(conn) ((conn)->mss) + +#endif /* CONFIG_NET_TCP */ +#endif /* __INCLUDE_NUTTX_NET_UIP_UIP_TCP_H */ diff --git a/nuttx/include/nuttx/net/uip/uip-udp.h b/nuttx/include/nuttx/net/uip/uip-udp.h new file mode 100644 index 0000000000..5eb7f17116 --- /dev/null +++ b/nuttx/include/nuttx/net/uip/uip-udp.h @@ -0,0 +1,206 @@ +/**************************************************************************** + * include/nuttx/net/uip/uip-udp.h + * Header file for the uIP UDP stack. + * + * The uIP UDP stack header file contains definitions for a number + * of C macros that are used by uIP programs as well as internal uIP + * structures, UDP header structures and function declarations. + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This logic was leveraged from uIP which also has a BSD-style license: + * + * Author Adam Dunkels + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_UIP_UIP_UDP_H +#define __INCLUDE_NUTTX_NET_UIP_UIP_UDP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Header sizes */ + +#define UIP_UDPH_LEN 8 /* Size of UDP header */ +#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP + UDP header */ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* Representation of a uIP UDP connection */ + +struct uip_driver_s; /* Forward reference */ +struct uip_callback_s; /* Forward reference */ +struct uip_udp_conn +{ + dq_entry_t node; /* Supports a doubly linked list */ + uip_ipaddr_t ripaddr; /* The IP address of the remote peer */ + uint16_t lport; /* The local port number in network byte order */ + uint16_t rport; /* The remote port number in network byte order */ + uint8_t ttl; /* Default time-to-live */ + uint8_t crefs; /* Reference counts on this instance */ + + /* Defines the list of UDP callbacks */ + + struct uip_callback_s *list; +}; + +/* The UDP and IP headers */ + +struct uip_udpip_hdr +{ +#ifdef CONFIG_NET_IPv6 + + /* IPv6 Ip header */ + + uint8_t vtc; /* Bits 0-3: version, bits 4-7: traffic class (MS) */ + uint8_t tcf; /* Bits 0-3: traffic class (LS), 4-bits: flow label (MS) */ + uint16_t flow; /* 16-bit flow label (LS) */ + uint8_t len[2]; /* 16-bit Payload length */ + uint8_t proto; /* 8-bit Next header (same as IPv4 protocol field) */ + uint8_t ttl; /* 8-bit Hop limit (like IPv4 TTL field) */ + uip_ip6addr_t srcipaddr; /* 128-bit Source address */ + uip_ip6addr_t destipaddr; /* 128-bit Destination address */ + +#else /* CONFIG_NET_IPv6 */ + + /* IPv4 header */ + + uint8_t vhl; /* 8-bit Version (4) and header length (5 or 6) */ + uint8_t tos; /* 8-bit Type of service (e.g., 6=TCP) */ + uint8_t len[2]; /* 16-bit Total length */ + uint8_t ipid[2]; /* 16-bit Identification */ + uint8_t ipoffset[2]; /* 16-bit IP flags + fragment offset */ + uint8_t ttl; /* 8-bit Time to Live */ + uint8_t proto; /* 8-bit Protocol */ + uint16_t ipchksum; /* 16-bit Header checksum */ + uint16_t srcipaddr[2]; /* 32-bit Source IP address */ + uint16_t destipaddr[2]; /* 32-bit Destination IP address */ + +#endif /* CONFIG_NET_IPv6 */ + + /* UDP header */ + + uint16_t srcport; + uint16_t destport; + uint16_t udplen; + uint16_t udpchksum; +}; + +/* The structure holding the UDP statistics that are gathered if + * CONFIG_NET_STATISTICS is defined. + */ + +#ifdef CONFIG_NET_STATISTICS +struct uip_udp_stats_s +{ + uip_stats_t drop; /* Number of dropped UDP segments */ + uip_stats_t recv; /* Number of recived UDP segments */ + uip_stats_t sent; /* Number of sent UDP segments */ + uip_stats_t chkerr; /* Number of UDP segments with a bad checksum */ +}; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* uIP application functions + * + * Functions used by an application running of top of uIP. This includes + * functions for opening and closing connections, sending and receiving + * data, etc. + * + * Find a free connection structure and allocate it for use. This is + * normally something done by the implementation of the socket() API + */ + +extern struct uip_udp_conn *uip_udpalloc(void); + +/* Allocate a new TCP data callback */ + +#define uip_udpcallbackalloc(conn) uip_callbackalloc(&conn->list) +#define uip_udpcallbackfree(conn,cb) uip_callbackfree(cb, &conn->list) + +/* Free a connection structure that is no longer in use. This should + * be done by the implementation of close() + */ + +extern void uip_udpfree(struct uip_udp_conn *conn); + +/* Bind a UDP connection to a local address */ + +#ifdef CONFIG_NET_IPv6 +extern int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in6 *addr); +#else +extern int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in *addr); +#endif + +/* This function sets up a new UDP connection. The function will + * automatically allocate an unused local port for the new + * connection. However, another port can be chosen by using the + * uip_udpbind() call, after the uip_udpconnect() function has been + * called. + * + * This function is called as part of the implementation of sendto + * and recvfrom. + * + * addr The address of the remote host. + */ + +#ifdef CONFIG_NET_IPv6 +extern int uip_udpconnect(struct uip_udp_conn *conn, const struct sockaddr_in6 *addr); +#else +extern int uip_udpconnect(struct uip_udp_conn *conn, const struct sockaddr_in *addr); +#endif + +/* Enable/disable UDP callbacks on a connection */ + +extern void uip_udpenable(struct uip_udp_conn *conn); +extern void uip_udpdisable(struct uip_udp_conn *conn); + +#endif /* __INCLUDE_NUTTX_NET_UIP_UIP_UDP_H */ diff --git a/nuttx/include/nuttx/net/uip/uip.h b/nuttx/include/nuttx/net/uip/uip.h new file mode 100644 index 0000000000..392793e68d --- /dev/null +++ b/nuttx/include/nuttx/net/uip/uip.h @@ -0,0 +1,568 @@ +/**************************************************************************** + * include/nuttx/net/uip/uip.h + * + * The uIP header file contains definitions for a number of C macros that + * are used by uIP programs as well as internal uIP structures and function + * declarations. + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This logic was leveraged from uIP which also has a BSD-style license: + * + * Author Adam Dunkels + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_UIP_UIP_H +#define __INCLUDE_NUTTX_NET_UIP_UIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#ifdef CONFIG_NET_NOINTS +# include +#endif + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The following flags may be set in the set of flags before calling the + * application callback. The UIP_ACKDATA, UIP_NEWDATA, and UIP_CLOSE flags + * may be set at the same time, whereas the others are mutualy exclusive. + * + * UIP_ACKDATA IN: Signifies that the outstanding data was acked and + * the application should send out new data instead + * of retransmitting the last data (TCP only) + * OUT: Input state must be preserved on output. + * UIP_NEWDATA IN: Set to indicate that the peer has sent us new data. + * OUT: Cleared (only) by the application logic to indicate + * that the new data was consumed, suppressing further + * attempts to process the new data. + * UIP_SNDACK IN: Not used; always zero + * OUT: Set by the application if the new data was consumed + * and an ACK should be sent in the response. (TCP only) + * UIP_REXMIT IN: Tells the application to retransmit the data that + * was last sent. (TCP only) + * OUT: Not used + * UIP_POLL IN: Used for polling the application. This is provided + * periodically from the drivers to support (1) timed + * operations, and (2) to check if the application has + * data that it wants to send + * OUT: Not used + * UIP_BACKLOG IN: There is a new connection in the backlog list set + * up by the listen() command. (TCP only) + * OUT: Not used + * UIP_CLOSE IN: The remote host has closed the connection, thus the + * connection has gone away. (TCP only) + * OUT: The application signals that it wants to close the + * connection. (TCP only) + * UIP_ABORT IN: The remote host has aborted the connection, thus the + * connection has gone away. (TCP only) + * OUT: The application signals that it wants to abort the + * connection. (TCP only) + * UIP_CONNECTED IN: We have got a connection from a remote host and have + * set up a new connection for it, or an active connection + * has been successfully established. (TCP only) + * OUT: Not used + * UIP_TIMEDOUT IN: The connection has been aborted due to too many + * retransmissions. (TCP only) + * OUT: Not used + * UIP_ECHOREPLY IN: An ICMP Echo Reply has been received. Used to support + * ICMP ping from applications. (ICMP only) + * OUT: Cleared (only) by the application logic to indicate + * that the reply was processed, suppressing further + * attempts to process the reply. + */ + +#define UIP_ACKDATA (1 << 0) +#define UIP_NEWDATA (1 << 1) +#define UIP_SNDACK (1 << 2) +#define UIP_REXMIT (1 << 3) +#define UIP_POLL (1 << 4) +#define UIP_BACKLOG (1 << 5) +#define UIP_CLOSE (1 << 6) +#define UIP_ABORT (1 << 7) +#define UIP_CONNECTED (1 << 8) +#define UIP_TIMEDOUT (1 << 9) +#define UIP_ECHOREPLY (1 << 10) + +#define UIP_CONN_EVENTS (UIP_CLOSE|UIP_ABORT|UIP_CONNECTED|UIP_TIMEDOUT) + +/* The buffer size available for user data in the d_buf buffer. + * + * This macro holds the available size for user data in the + * d_buf buffer. The macro is intended to be used for checking + * bounds of available user data. + * + * Example: + * + * snprintf(dev->d_appdata, UIP_APPDATA_SIZE, "%u\n", i); + */ + +#define UIP_APPDATA_SIZE (CONFIG_NET_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) + +#define UIP_PROTO_ICMP 1 +#define UIP_PROTO_IGMP 2 +#define UIP_PROTO_TCP 6 +#define UIP_PROTO_UDP 17 +#define UIP_PROTO_ICMP6 58 + +/* Header sizes */ + +#ifdef CONFIG_NET_IPv6 +# define UIP_IPH_LEN 40 /* Size of IP header */ +#else +# define UIP_IPH_LEN 20 /* Size of IP header */ +#endif + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* Representation of an IP address */ + +typedef in_addr_t uip_ip4addr_t; +typedef uint16_t uip_ip6addr_t[8]; + +#ifdef CONFIG_NET_IPv6 +typedef uip_ip6addr_t uip_ipaddr_t; +#else +typedef uip_ip4addr_t uip_ipaddr_t; +#endif + +/* The IP header */ + +struct uip_ip_hdr +{ +#ifdef CONFIG_NET_IPv6 + + /* IPv6 Ip header */ + + uint8_t vtc; /* Bits 0-3: version, bits 4-7: traffic class (MS) */ + uint8_t tcf; /* Bits 0-3: traffic class (LS), 4-bits: flow label (MS) */ + uint16_t flow; /* 16-bit flow label (LS) */ + uint8_t len[2]; /* 16-bit Payload length */ + uint8_t proto; /* 8-bit Next header (same as IPv4 protocol field) */ + uint8_t ttl; /* 8-bit Hop limit (like IPv4 TTL field) */ + uip_ip6addr_t srcipaddr; /* 128-bit Source address */ + uip_ip6addr_t destipaddr; /* 128-bit Destination address */ + +#else /* CONFIG_NET_IPv6 */ + + /* IPv4 IP header */ + + uint8_t vhl; /* 8-bit Version (4) and header length (5 or 6) */ + uint8_t tos; /* 8-bit Type of service (e.g., 6=TCP) */ + uint8_t len[2]; /* 16-bit Total length */ + uint8_t ipid[2]; /* 16-bit Identification */ + uint8_t ipoffset[2]; /* 16-bit IP flags + fragment offset */ + uint8_t ttl; /* 8-bit Time to Live */ + uint8_t proto; /* 8-bit Protocol */ + uint16_t ipchksum; /* 16-bit Header checksum */ + uint16_t srcipaddr[2]; /* 32-bit Source IP address */ + uint16_t destipaddr[2]; /* 32-bit Destination IP address */ + +#endif /* CONFIG_NET_IPv6 */ +}; + +/* Describes a uIP callback + * + * flink - Supports a singly linked list + * event - Provides the address of the callback function entry point. + * pvconn is a pointer to one of struct uip_conn or struct uip_udp_conn. + * priv - Holds a reference to application specific data that will + * provided + * flags - Set by the application to inform the uIP layer which flags + * are and are not handled by the callback. + */ + +struct uip_driver_s; /* Forward reference */ +struct uip_callback_s +{ + FAR struct uip_callback_s *flink; + uint16_t (*event)(struct uip_driver_s *dev, void *pvconn, void *pvpriv, uint16_t flags); + void *priv; + uint16_t flags; +}; + +/* Protocol-specific support */ + +#ifdef CONFIG_NET_TCP +# include +#endif +#ifdef CONFIG_NET_UDP +# include +#endif +#ifdef CONFIG_NET_ICMP +# include +#endif +#ifdef CONFIG_NET_IGMP +# include +#endif + +/* The structure holding the uIP statistics that are gathered if + * CONFIG_NET_STATISTICS is defined. + */ + +#ifdef CONFIG_NET_STATISTICS +struct uip_ip_stats_s +{ + uip_stats_t drop; /* Number of dropped packets at the IP layer */ + uip_stats_t recv; /* Number of received packets at the IP layer */ + uip_stats_t sent; /* Number of sent packets at the IP layer */ + uip_stats_t vhlerr; /* Number of packets dropped due to wrong + IP version or header length */ + uip_stats_t hblenerr; /* Number of packets dropped due to wrong + IP length, high byte */ + uip_stats_t lblenerr; /* Number of packets dropped due to wrong + IP length, low byte */ + uip_stats_t fragerr; /* Number of packets dropped since they + were IP fragments */ + uip_stats_t chkerr; /* Number of packets dropped due to IP + checksum errors */ + uip_stats_t protoerr; /* Number of packets dropped since they + were neither ICMP, UDP nor TCP */ +}; + +struct uip_stats +{ + struct uip_ip_stats_s ip; /* IP statistics */ + +#ifdef CONFIG_NET_ICMP + struct uip_icmp_stats_s icmp; /* ICMP statistics */ +#endif + +#ifdef CONFIG_NET_IGMP + struct uip_igmp_stats_s igmp; /* IGMP statistics */ +#endif + +#ifdef CONFIG_NET_TCP + struct uip_tcp_stats_s tcp; /* TCP statistics */ +#endif + +#ifdef CONFIG_NET_UDP + struct uip_udp_stats_s udp; /* UDP statistics */ +#endif +}; +#endif /* CONFIG_NET_STATISTICS */ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* This is the structure in which the statistics are gathered. */ + +#ifdef CONFIG_NET_STATISTICS +extern struct uip_stats uip_stat; +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* uIP initialization functions + * + * The uIP initialization functions are used for booting uIP. + * + * This function should be called at boot up to initilize the uIP + * TCP/IP stack. + */ + +extern void uip_initialize(void); + +/* This function may be used at boot time to set the initial ip_id.*/ + +extern void uip_setipid(uint16_t id); + +/* Critical section management. The NuttX configuration setting + * CONFIG_NET_NOINT indicates that uIP not called from the interrupt level. + * If CONFIG_NET_NOINTS is defined, then these will map to semaphore + * controls. Otherwise, it assumed that uIP will be called from interrupt + * level handling and these will map to interrupt enable/disable controls. + */ + +#ifdef CONFIG_NET_NOINTS + +/* Semaphore based locking for non-interrupt based logic. + * + * uip_lock_t -- Not used. Only for compatibility + * uip_lockinit() -- Initializes an underlying semaphore/mutex + * uip_lock() -- Takes the semaphore(). Implements a re-entrant mutex. + * uip_unlock() -- Gives the semaphore(). + * uip_lockedwait() -- Like pthread_cond_wait(); releases the semaphore + * momemtarily to wait on another semaphore() + */ + +typedef uint8_t uip_lock_t; /* Not really used */ + +extern void uip_lockinit(void); +extern uip_lock_t uip_lock(void); +extern void uip_unlock(uip_lock_t flags); +extern int uip_lockedwait(sem_t *sem); + +#else + +/* Enable/disable locking for interrupt based logic: + * + * uip_lock_t -- The processor specific representation of interrupt state. + * uip_lockinit() -- (Does not exist). + * uip_lock() -- Disables interrupts. + * uip_unlock() -- Conditionally restores interrupts. + * uip_lockedwait() -- Just wait for the semaphore. + */ + +# define uip_lock_t irqstate_t +# define uip_lockinit() +# define uip_lock() irqsave() +# define uip_unlock(f) irqrestore(f) +# define uip_lockedwait(s) sem_wait(s) + +#endif + +/* uIP application functions + * + * Functions used by an application running of top of uIP. This includes + * functions for opening and closing connections, sending and receiving + * data, etc. + */ + +/* Send data on the current connection. + * + * This function is used to send out a single segment of TCP + * data. Only applications that have been invoked by uIP for event + * processing can send data. + * + * The amount of data that actually is sent out after a call to this + * funcion is determined by the maximum amount of data TCP allows. uIP + * will automatically crop the data so that only the appropriate + * amount of data is sent. The function uip_mss() can be used to query + * uIP for the amount of data that actually will be sent. + * + * Note: This function does not guarantee that the sent data will + * arrive at the destination. If the data is lost in the network, the + * application will be invoked with the UIP_REXMIT flag set. The + * application will then have to resend the data using this function. + * + * data A pointer to the data which is to be sent. + * + * len The maximum amount of data bytes to be sent. + */ + +extern void uip_send(struct uip_driver_s *dev, const void *buf, int len); + +/* uIP convenience and converting functions. + * + * These functions can be used for converting between different data + * formats used by uIP. + * + * Construct an IP address from four bytes. + * + * This function constructs an IPv4 address in network byte order. + * + * addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the IPv4 address. + * addr0 The first octet of the IPv4 address. + * addr1 The second octet of the IPv4 address. + * addr2 The third octet of the IPv4 address. + * addr3 The forth octet of the IPv4 address. + */ + +#define uip_ipaddr(addr, addr0, addr1, addr2, addr3) \ + do { \ + addr = HTONL((addr0) << 24 | (addr1) << 16 | (addr2) << 8 | (addr3)); \ + } while(0) + +/* Convert an IPv4 address of the form uint16_t[2] to an in_addr_t */ + +#ifdef CONFIG_ENDIAN_BIG +# define uip_ip4addr_conv(addr) (((in_addr_t)((uint16_t*)addr)[0] << 16) | (in_addr_t)((uint16_t*)addr)[1]) +#else +# define uip_ip4addr_conv(addr) (((in_addr_t)((uint16_t*)addr)[1] << 16) | (in_addr_t)((uint16_t*)addr)[0]) +#endif + +/* Extract individual bytes from a 32-bit IPv4 IP address that is in network byte order */ + +#ifdef CONFIG_ENDIAN_BIG + /* Big-endian byte order: 11223344 */ + +# define ip4_addr1(ipaddr) (((ipaddr) >> 24) & 0xff) +# define ip4_addr2(ipaddr) (((ipaddr) >> 16) & 0xff) +# define ip4_addr3(ipaddr) (((ipaddr) >> 8) & 0xff) +# define ip4_addr4(ipaddr) ((ipaddr) & 0xff) +#else + /* Little endian byte order: 44223311 */ + +# define ip4_addr1(ipaddr) ((ipaddr) & 0xff) +# define ip4_addr2(ipaddr) (((ipaddr) >> 8) & 0xff) +# define ip4_addr3(ipaddr) (((ipaddr) >> 16) & 0xff) +# define ip4_addr4(ipaddr) (((ipaddr) >> 24) & 0xff) +#endif + +/* Construct an IPv6 address from eight 16-bit words. + * + * This function constructs an IPv6 address. + */ + +#define uip_ip6addr(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) \ + do { \ + ((uint16_t*)(addr))[0] = HTONS((addr0)); \ + ((uint16_t*)(addr))[1] = HTONS((addr1)); \ + ((uint16_t*)(addr))[2] = HTONS((addr2)); \ + ((uint16_t*)(addr))[3] = HTONS((addr3)); \ + ((uint16_t*)(addr))[4] = HTONS((addr4)); \ + ((uint16_t*)(addr))[5] = HTONS((addr5)); \ + ((uint16_t*)(addr))[6] = HTONS((addr6)); \ + ((uint16_t*)(addr))[7] = HTONS((addr7)); \ + } while(0) + +/* Copy an IP address to another IP address. + * + * Copies an IP address from one place to another. + * + * Example: + * + * uip_ipaddr_t ipaddr1, ipaddr2; + * + * uip_ipaddr(&ipaddr1, 192,16,1,2); + * uip_ipaddr_copy(&ipaddr2, &ipaddr1); + * + * dest The destination for the copy. + * src The source from where to copy. + */ + +#ifndef CONFIG_NET_IPv6 +# define uip_ipaddr_copy(dest, src) \ + do { \ + (dest) = (in_addr_t)(src); \ + } while(0) +# define uiphdr_ipaddr_copy(dest, src) \ + do { \ + ((uint16_t*)(dest))[0] = ((uint16_t*)(src))[0]; \ + ((uint16_t*)(dest))[1] = ((uint16_t*)(src))[1]; \ + } while(0) +#else /* !CONFIG_NET_IPv6 */ +# define uip_ipaddr_copy(dest, src) memcpy(&dest, &src, sizeof(uip_ip6addr_t)) +# define uiphdr_ipaddr_copy(dest, src) uip_ipaddr_copy(dest, src) +#endif /* !CONFIG_NET_IPv6 */ + +/* Compare two IP addresses + * + * Example: + * + * uip_ipaddr_t ipaddr1, ipaddr2; + * + * uip_ipaddr(&ipaddr1, 192,16,1,2); + * if(uip_ipaddr_cmp(ipaddr2, ipaddr1)) { + * printf("They are the same"); + * } + * + * addr1 The first IP address. + * addr2 The second IP address. + */ + +#ifndef CONFIG_NET_IPv6 +# define uip_ipaddr_cmp(addr1, addr2) (addr1 == addr2) +# define uiphdr_ipaddr_cmp(addr1, addr2) uip_ipaddr_cmp(uip_ip4addr_conv(addr1), uip_ip4addr_conv(addr2)) +#else /* !CONFIG_NET_IPv6 */ +# define uip_ipaddr_cmp(addr1, addr2) (memcmp(&addr1, &addr2, sizeof(uip_ip6addr_t)) == 0) +# define uiphdr_ipaddr_cmp(addr1, addr2) uip_ipaddr_cmp(addr, addr2) +#endif /* !CONFIG_NET_IPv6 */ + +/* Compare two IP addresses with netmasks + * + * Compares two IP addresses with netmasks. The masks are used to mask + * out the bits that are to be compared. + * + * Example: + * + * uip_ipaddr_t ipaddr1, ipaddr2, mask; + * + * uip_ipaddr(&mask, 255,255,255,0); + * uip_ipaddr(&ipaddr1, 192,16,1,2); + * uip_ipaddr(&ipaddr2, 192,16,1,3); + * if(uip_ipaddr_maskcmp(ipaddr1, ipaddr2, &mask)) + * { + * printf("They are the same"); + * } + * + * addr1 The first IP address. + * addr2 The second IP address. + * mask The netmask. + */ + +#ifndef CONFIG_NET_IPv6 +# define uip_ipaddr_maskcmp(addr1, addr2, mask) \ + (((in_addr_t)(addr1) & (in_addr_t)(mask)) == \ + ((in_addr_t)(addr2) & (in_addr_t)(mask))) +#else +extern bool uip_ipaddr_maskcmp(uip_ipaddr_t addr1, uip_ipaddr_t addr2, + uip_ipaddr_t mask); +#endif + +/* Mask out the network part of an IP address. + * + * Masks out the network part of an IP address, given the address and + * the netmask. + * + * Example: + * + * uip_ipaddr_t ipaddr1, ipaddr2, netmask; + * + * uip_ipaddr(&ipaddr1, 192,16,1,2); + * uip_ipaddr(&netmask, 255,255,255,0); + * uip_ipaddr_mask(&ipaddr2, &ipaddr1, &netmask); + * + * In the example above, the variable "ipaddr2" will contain the IP + * address 192.168.1.0. + * + * dest Where the result is to be placed. + * src The IP address. + * mask The netmask. + */ + +#define uip_ipaddr_mask(dest, src, mask) \ + do { \ + (in_addr_t)(dest) = (in_addr_t)(src) & (in_addr_t)(mask); \ + } while(0) + +#endif /* __INCLUDE_NUTTX_NET_UIP_UIP_H */ diff --git a/nuttx/include/nuttx/net/uip/uipopt.h b/nuttx/include/nuttx/net/uip/uipopt.h new file mode 100644 index 0000000000..4eff56fe85 --- /dev/null +++ b/nuttx/include/nuttx/net/uip/uipopt.h @@ -0,0 +1,314 @@ +/**************************************************************************** + * include/nuttx/net/uip/uipopt.h + * Configuration options for uIP. + * + * This file is used for tweaking various configuration options for + * uIP. You should make a copy of this file into one of your project's + * directories instead of editing this example "uipopt.h" file that + * comes with the uIP distribution. + * + * uIP is configured using the per-project configuration file + * uipopt.h. This file contains all compile-time options for uIP and + * should be tweaked to match each specific project. The uIP + * distribution contains a documented example "uipopt.h" that can be + * copied and modified for each project. + * + * Note: Most of the configuration options in the uipopt.h should not + * be changed, but rather the per-project defconfig file. + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This logic was leveraged from uIP which also has a BSD-style license: + * + * Author: Adam Dunkels + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_UIP_UIPOPT_H +#define __INCLUDE_NUTTX_NET_UIP_UIPOPT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* Layer 2 Configuration Options ********************************************/ + +/* The default data link layer for uIP is Ethernet. If CONFIG_NET_SLIP is + * defined in the NuttX header file, then SLIP will be supported. The basic + * differences between the SLIP and Ethernet configurations is that when SLIP + * is selected: + * + * - The link level header (that comes before the IP header) is omitted. + * - All MAC address processing is suppressed. + * - ARP is disabled. + * + * If CONFIG_NET_SLIP is not supported, then Ethernet will be used (there is + * no need to define anything special in the configuration file to use + * Ethernet -- it is the default). + * + * The "link level header" is the offset into the d_buf where the IP header + * can be found. For Ethernet, this should be set to 14. For SLIP, this + * should be set to 0. + */ + +#undef CONFIG_NET_ETHERNET +#undef CONFIG_NET_ARP + +#ifdef CONFIG_NET_SLIP +# ifdef CONFIG_NET_IPv6 +# error "SLIP is not implemented for IPv6" +# endif +# define UIP_LLH_LEN 0 +#else +# define CONFIG_NET_ETHERNET 1 +# define CONFIG_NET_ARP 1 +# define UIP_LLH_LEN 14 +#endif + +/* Layer 3/4 Configuration Options ******************************************/ + +/* IP configuration options */ + +/* The IP TTL (time to live) of IP packets sent by uIP. + * + * This should normally not be changed. + */ + +#define UIP_TTL 64 + +/* Turn on support for IP packet reassembly. + * + * uIP supports reassembly of fragmented IP packets. This features + * requires an additonal amount of RAM to hold the reassembly buffer + * and the reassembly code size is approximately 700 bytes. The + * reassembly buffer is of the same size as the d_buf buffer + * (configured by CONFIG_NET_BUFSIZE). + * + * Note: IP packet reassembly is not heavily tested. + */ + +#define UIP_REASSEMBLY 0 + +/* The maximum time an IP fragment should wait in the reassembly + * buffer before it is dropped. Units are deci-seconds, the range + * of the timer is 8-bits. + */ + +#define UIP_REASS_MAXAGE (20*10) /* 20 seconds */ + +/* Network drivers often receive packets with garbage at the end + * and are longer than the size of packet in the TCP header. The + * following "fudge" factor increases the size of the I/O buffering + * by a small amount to allocate slightly oversize packets. After + * receipt, the packet size will be chopped down to the size indicated + * in the TCP header. + */ + +#ifndef CONFIG_NET_GUARDSIZE +# define CONFIG_NET_GUARDSIZE 2 +#endif + +/* ICMP configuration options */ + +#if !defined(CONFIG_NET_ICMP) || defined(CONFIG_DISABLE_CLOCK) +# undef CONFIG_NET_ICMP_PING +#endif + +/* UDP configuration options */ + +/* The maximum amount of concurrent UDP connection, Default: 10 */ + +#ifndef CONFIG_NET_UDP_CONNS +# ifdef CONFIG_NET_UDP +# define CONFIG_NET_UDP_CONNS 10 +# else +# define CONFIG_NET_UDP_CONNS 0 +# endif +#endif + +/* The UDP maximum packet size. This is should not be to set to more + * than CONFIG_NET_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN. + */ + +#define UIP_UDP_MSS (CONFIG_NET_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN) + +/* TCP configuration options */ + +/* The maximum number of simultaneously open TCP connections. + * + * Since the TCP connections are statically allocated, turning this + * configuration knob down results in less RAM used. Each TCP + * connection requires approximatly 30 bytes of memory. + */ + +#ifndef CONFIG_NET_TCP_CONNS +# ifdef CONFIG_NET_TCP +# define CONFIG_NET_TCP_CONNS 10 +# else +# define CONFIG_NET_TCP_CONNS 0 +# endif +#endif + +/* The maximum number of simultaneously listening TCP ports. + * + * Each listening TCP port requires 2 bytes of memory. + */ + +#ifndef CONFIG_NET_MAX_LISTENPORTS +# define CONFIG_NET_MAX_LISTENPORTS 20 +#endif + +/* Define the maximum number of concurrently active UDP and TCP + * ports. This number must be greater than the number of open + * sockets in order to support multi-threaded read/write operations. + */ + +#ifndef CONFIG_NET_NACTIVESOCKETS +# define CONFIG_NET_NACTIVESOCKETS (CONFIG_NET_TCP_CONNS + CONFIG_NET_UDP_CONNS) +#endif + +/* The initial retransmission timeout counted in timer pulses. + * + * This should not be changed. + */ + +#define UIP_RTO 3 + +/* The maximum number of times a segment should be retransmitted + * before the connection should be aborted. + * + * This should not be changed. + */ + +#define UIP_MAXRTX 8 + +/* The maximum number of times a SYN segment should be retransmitted + * before a connection request should be deemed to have been + * unsuccessful. + * + * This should not need to be changed. + */ + +#define UIP_MAXSYNRTX 5 + +/* The TCP maximum segment size. This is should not be set to more + * than CONFIG_NET_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN. + */ + +#define UIP_TCP_MSS (CONFIG_NET_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) + +/* The size of the advertised receiver's window. + * + * Should be set low (i.e., to the size of the d_buf buffer) is the + * application is slow to process incoming data, or high (32768 bytes) + * if the application processes data quickly. + */ + +#ifndef CONFIG_NET_RECEIVE_WINDOW +# define CONFIG_NET_RECEIVE_WINDOW UIP_TCP_MSS +#endif + +/* How long a connection should stay in the TIME_WAIT state. + * + * This configiration option has no real implication, and it should be + * left untouched. Units: half second. + */ + +#define UIP_TIME_WAIT_TIMEOUT (60*2) + +/* ARP configuration options */ + +/* The size of the ARP table. + * + * This option should be set to a larger value if this uIP node will + * have many connections from the local network. + */ + +#ifndef CONFIG_NET_ARPTAB_SIZE +# define CONFIG_NET_ARPTAB_SIZE 8 +#endif + +/* The maxium age of ARP table entries measured in 10ths of seconds. + * + * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD + * default). + */ + +#define UIP_ARP_MAXAGE 120 + +/* General configuration options */ + +/* The size of the uIP packet buffer. + * + * The uIP packet buffer should not be smaller than 60 bytes, and does + * not need to be larger than 1500 bytes. Lower size results in lower + * TCP throughput, larger size results in higher TCP throughput. + */ + +#ifndef CONFIG_NET_BUFSIZE +# define CONFIG_NET_BUFSIZE 400 +#endif + +/* Number of TCP read-ahead buffers (may be zero) */ + +#ifndef CONFIG_NET_NTCP_READAHEAD_BUFFERS +# define CONFIG_NET_NTCP_READAHEAD_BUFFERS 4 +#endif + +/* The size of the TCP read buffer size */ + +#ifndef CONFIG_NET_TCP_READAHEAD_BUFSIZE +# define CONFIG_NET_TCP_READAHEAD_BUFSIZE UIP_TCP_MSS +#endif + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* Statistics datatype + * + * This typedef defines the dataype used for keeping statistics in + * uIP. + */ + +typedef uint16_t uip_stats_t; + +#endif /* __INCLUDE_NUTTX_NET_UIP_UIPOPT_H */ diff --git a/nuttx/include/nuttx/nx/nx.h b/nuttx/include/nuttx/nx/nx.h new file mode 100644 index 0000000000..153c34a3e5 --- /dev/null +++ b/nuttx/include/nuttx/nx/nx.h @@ -0,0 +1,904 @@ +/**************************************************************************** + * include/nuttx/nx/nx.h + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef _INCLUDE_NUTTX_NX_NX_H +#define _INCLUDE_NUTTX_NX_NX_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Default server MQ name used by nx_run() macro */ + +#define NX_DEFAULT_SERVER_MQNAME "/dev/nxs" + +/* Mouse button bits */ + +#define NX_MOUSE_NOBUTTONS 0x00 +#define NX_MOUSE_LEFTBUTTON 0x01 +#define NX_MOUSE_CENTERBUTTON 0x02 +#define NX_MOUSE_RIGHTBUTTON 0x04 + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* Configuration ************************************************************/ + +#ifndef CONFIG_NX_NPLANES +# define CONFIG_NX_NPLANES 1 /* Max number of color planes supported */ +#endif + +/* Check if the underlying graphic device supports read operations */ + +#if !defined(CONFIG_NX_WRITEONLY) && defined(CONFIG_NX_LCDDRIVER) && defined(CONFIG_LCD_NOGETRUN) +# define CONFIG_NX_WRITEONLY 1 +#endif + +/* Handles ******************************************************************/ + +/* The interface to the NX server is managed using a opaque handle: */ + +typedef FAR void *NXHANDLE; + +/* The interface to a specific window is managed using an opaque handle: */ + +typedef FAR void *NXWINDOW; + +/* NX server callbacks ******************************************************/ + +/* These define callbacks that must be provided to nx_openwindow. These + * callbacks will be invoked as part of the processing performed by + * nx_eventhandler() + */ + +struct nx_callback_s +{ + /************************************************************************** + * Name: redraw + * + * Descripton: + * NX requests that the client re-draw the portion of the window within + * with rectangle. + * + * Input Parameters: + * hwnd - Window handle + * rect - The rectangle that needs to be re-drawn (in window relative + * coordinates) + * more - true: More re-draw requests will follow + * arg - User provided argument (see nx_openwindow, nx_requestbkgd, + * nxtk_openwindow, or nxtk_opentoolbar) + * + * Returned Value: + * None + * + **************************************************************************/ + + void (*redraw)(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, + bool more, FAR void *arg); + + /************************************************************************** + * Name: position + * + * Descripton: + * The size or position of the window has changed (or the window was + * just created with zero size. + * + * Input Parameters: + * hwnd - Window handle + * size - The size of the window + * pos - The position of the upper left hand corner of the window on + * the overall display + * bounds - The bounding rectangle that the describes the entire + * display + * arg - User provided argument (see nx_openwindow, nx_requestbkgd, + * nxtk_openwindow, or nxtk_opentoolbar) + * + * Returned Value: + * None + * + **************************************************************************/ + + void (*position)(NXWINDOW hwnd, FAR const struct nxgl_size_s *size, + FAR const struct nxgl_point_s *pos, + FAR const struct nxgl_rect_s *bounds, + FAR void *arg); + + /************************************************************************** + * Name: mousein + * + * Descripton: + * New mouse data is available for the window. + * + * Input Parameters: + * hwnd - Window handle + * pos - The (x,y) position of the mouse + * buttons - See NX_MOUSE_* definitions + * arg - User provided argument (see nx_openwindow, nx_requestbkgd, + * nxtk_openwindow, or nxtk_opentoolbar) + * + * Returned Value: + * None + * + **************************************************************************/ + +#ifdef CONFIG_NX_MOUSE + void (*mousein)(NXWINDOW hwnd, FAR const struct nxgl_point_s *pos, + uint8_t buttons, FAR void *arg); +#endif + + /************************************************************************** + * Name: kbdin + * + * Descripton: + * New keyboard/keypad data is available for the window + * + * Input Parameters: + * hwnd - Window handle + * nch - The number of characters that are available in ch[] + * ch - The array of characters + * arg - User provided argument (see nx_openwindow, nx_requestbkgd, + * nxtk_openwindow, or nxtk_opentoolbar) + * + * Returned Value: + * None + * + **************************************************************************/ + +#ifdef CONFIG_NX_KBD + void (*kbdin)(NXWINDOW hwnd, uint8_t nch, FAR const uint8_t *ch, FAR void *arg); +#endif + + /************************************************************************** + * Name: blocked + * + * Descripton: + * This callback is the response from nx_block (or nxtk_block). Those + * blocking interfaces are used to assure that no further messages are + * directed to the window. Receipt of the blocked callback signifies + * that (1) there are no further pending callbacks and (2) that the + * window is now 'defunct' and will receive no further callbacks. + * + * This callback supports coordinated destruction of a window in multi- + * user mode. In multi-use mode, the client window logic must stay + * intact until all of the queued callbacks are processed. Then the + * window may be safely closed. Closing the window prior with pending + * callbacks can lead to bad behavior when the callback is executed. + * + * Input Parameters: + * hwnd - Window handle of the blocked window + * arg1 - User provided argument (see nx_openwindow, nx_requestbkgd, + * nxtk_openwindow, or nxtk_opentoolbar) + * arg2 - User provided argument (see nx_block or nxtk_block) + * + * Returned Value: + * None + * + **************************************************************************/ + +#ifdef CONFIG_NX_MULTIUSER + void (*blocked)(NXWINDOW hwnd, FAR void *arg1, FAR void *arg2); +#endif +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_runinstance (and nx_run macro) + * + * Description: + * This is the server entry point. It does not return; the calling thread + * is dedicated to supporting NX server. + * + * NOTE that multiple instances of the NX server may run at the same time, + * with different callback and message queue names. nx_run() is simply + * a macro that can be used when only one server instance is required. In + * that case, a default server name is used. + * + * Multiple user mode only! + * + * Input Parameters: + * mqname - The name for the server incoming message queue + * dev - Vtable "object" of the framebuffer "driver" to use + * + * Return: + * This function usually does not return. If it does return, it will + * return ERROR and errno will be set appropriately. + * + ****************************************************************************/ + +#ifdef CONFIG_NX_MULTIUSER +EXTERN int nx_runinstance(FAR const char *mqname, FAR NX_DRIVERTYPE *dev); +# define nx_run(dev) nx_runinstance(NX_DEFAULT_SERVER_MQNAME, dev) +#endif + +/**************************************************************************** + * Name:nx_connectinstance (and nx_connect macro) + * + * Description: + * Open a connection from a client to the NX server. One one client + * connection is normally needed per thread as each connection can host + * multiple windows. + * + * NOTES: + * - This function returns before the connection is fully instantiated. + * it is necessary to wait for the connection event before using the + * returned handle. + * - Multiple instances of the NX server may run at the same time, + * each with different message queue names. + * - nx_connect() is simply a macro that can be used when only one + * server instance is required. In that case, a default server name + * is used. + * + * Multiple user mode only! + * + * Input Parameters: + * svrmqname - The name for the server incoming message queue + * + * Return: + * Success: A non-NULL handle used with subsequent NX accesses + * Failure: NULL is returned and errno is set appropriately + * + ****************************************************************************/ + +#ifdef CONFIG_NX_MULTIUSER +EXTERN NXHANDLE nx_connectinstance(FAR const char *svrmqname); +# define nx_connect(cb) nx_connectinstance(NX_DEFAULT_SERVER_MQNAME) +#endif + +/**************************************************************************** + * Name: nx_open + * + * Description: + * Create, initialize and return an NX handle for use in subsequent + * NX API calls. nx_open is the single user equivalent of nx_connect + * plus nx_run. + * + * Single user mode only! + * + * Input Parameters: + * dev - Vtable "object" of the framebuffer/LCD "driver" to use + * cb - Callbacks used to process received NX server messages + * + * Return: + * Success: A non-NULL handle used with subsequent NX accesses + * Failure: NULL is returned and errno is set appropriately + * + ****************************************************************************/ + +#ifndef CONFIG_NX_MULTIUSER +EXTERN NXHANDLE nx_open(FAR NX_DRIVERTYPE *dev); +#endif + +/**************************************************************************** + * Name: nx_disconnect + * + * Description: + * Disconnect a client from the NX server and/or free resources reserved + * by nx_connect/nx_connectinstance. nx_disconnect is muliti-user equivalent + * of nx_close. + * + * Multiple user mode only! + * + * Input Parameters: + * handle - the handle returned by nx_connect + * + * Return: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_NX_MULTIUSER +EXTERN void nx_disconnect(NXHANDLE handle); +#endif + +/**************************************************************************** + * Name: nx_close + * + * Description: + * Close the single user NX interface. nx_close is single-user equivalent + * of nx_disconnect. + * + * Single user mode only! + * + * Input Parameters: + * handle - the handle returned by nx_open + * + * Return: + * None + * + ****************************************************************************/ + +#ifndef CONFIG_NX_MULTIUSER +EXTERN void nx_close(NXHANDLE handle); +#endif + +/**************************************************************************** + * Name: nx_eventhandler + * + * Description: + * The client code must call this function periodically to process + * incoming messages from the server. If CONFIG_NX_BLOCKING is defined, + * then this function not return until a server message is received. + * + * When CONFIG_NX_BLOCKING is not defined, the client must exercise + * caution in the looping to assure that it does not eat up all of + * the CPU bandwidth calling nx_eventhandler repeatedly. nx_eventnotify + * may be called to get a signal event whenever a new incoming server + * event is avaiable. + * + * Input Parameters: + * handle - the handle returned by nx_connect + * + * Return: + * OK: No errors occurred. If CONFIG_NX_BLOCKING is defined, then + * one or more server messages were processed. + * ERROR: An error occurred and errno has been set appropriately. Of + * particular interest, it will return errno == EHOSTDOWN when the + * server is disconnected. After that event, the handle can no + * longer be used. + * + ****************************************************************************/ + +#ifdef CONFIG_NX_MULTIUSER +EXTERN int nx_eventhandler(NXHANDLE handle); +#else +# define nx_eventhandler(handle) (OK) +#endif + +/**************************************************************************** + * Name: nx_eventnotify + * + * Description: + * Rather than calling nx_eventhandler periodically, the client may + * register to receive a signal when a server event is available. The + * client can then call nv_eventhandler() only when incoming events are + * available. + * + * Only one such event is issued. Upon receipt of the signal, if the client + * wishes further notifications, it must call nx_eventnotify again. + * + * Input Parameters: + * handle - the handle returned by nx_connect + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +#if defined(CONFIG_NX_MULTIUSER) && !defined(CONFIG_DISABLE_SIGNALS) +EXTERN int nx_eventnotify(NXHANDLE handle, int signo); +#else +# define nx_eventnotify(handle, signo) (OK) +#endif + +/**************************************************************************** + * Name: nx_openwindow + * + * Description: + * Create a new window. + * + * Input Parameters: + * handle - The handle returned by nx_connect or nx_open + * cb - Callbacks used to process window events + * arg - User provided value that will be returned with NX callbacks. + * + * Return: + * Success: A non-NULL handle used with subsequent NX accesses + * Failure: NULL is returned and errno is set appropriately + * + ****************************************************************************/ + +EXTERN NXWINDOW nx_openwindow(NXHANDLE handle, + FAR const struct nx_callback_s *cb, + FAR void *arg); + +/**************************************************************************** + * Name: nx_closewindow + * + * Description: + * Destroy a window created by nx_openwindow. + * + * Input Parameters: + * wnd - The window to be destroyed + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_closewindow(NXWINDOW hwnd); + +/**************************************************************************** + * Name: nx_block + * + * Description: + * This is callback will do to things: (1) any queue a 'blocked' callback + * to the window and then (2) block any further window messaging. + * + * The 'blocked' callback is the response from nx_block (or nxtk_block). + * Those blocking interfaces are used to assure that no further messages are + * are directed to the window. Receipt of the blocked callback signifies + * that (1) there are no further pending callbacks and (2) that the + * window is now 'defunct' and will receive no further callbacks. + * + * This callback supports coordinated destruction of a window in multi- + * user mode. In multi-use more, the client window logic must stay + * intact until all of the queued callbacks are processed. Then the + * window may be safely closed. Closing the window prior with pending + * callbacks can lead to bad behavior when the callback is executed. + * + * Multiple user mode only! + * + * Input Parameters: + * wnd - The window to be blocked + * arg - An argument that will accompany the block messages (This is arg2 + * in the blocked callback). + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +#ifdef CONFIG_NX_MULTIUSER +EXTERN int nx_block(NXWINDOW hwnd, FAR void *arg); +#endif + +/**************************************************************************** + * Name: nx_requestbkgd + * + * Description: + * NX normally controls a separate window called the background window. + * It repaints the window as necessary using only a solid color fill. The + * background window always represents the entire screen and is always + * below other windows. It is useful for an application to control the + * background window in the following conditions: + * + * - If you want to implement a windowless solution. The single screen + * can be used to creat a truly simple graphic environment. In this + * case, you should probably also de-select CONFIG_NX_MULTIUSER as well. + * - When you want more on the background than a solid color. For + * example, if you want an image in the background, or animations in the + * background, or live video, etc. + * + * This API only requests the handle of the background window. That + * handle will be returned asynchronously in a subsequent position and + * redraw callbacks. + * + * Cautions: + * - The following should never be called using the background window. + * They are guaranteed to cause severe crashes: + * + * nx_setposition, nx_setsize, nx_raise, nx_lower. + * + * - Neither nx_requestbkgd or nx_releasebkgd should be called more than + * once. Multiple instances of the background window are not supported. + * + * Input Parameters: + * handle - The handle returned by nx_connect + * cb - Callbacks to use for processing background window events + * arg - User provided value that will be returned with NX callbacks. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_requestbkgd(NXHANDLE handle, + FAR const struct nx_callback_s *cb, + FAR void *arg); + +/**************************************************************************** + * Name: nx_releasebkgd + * + * Description: + * Release the background window previously acquired using nx_openbgwindow + * and return control of the background to NX. + * + * Input Parameters: + * hwnd - The handle returned (indirectly) by nx_requestbkgd + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_releasebkgd(NXWINDOW hwnd); + +/**************************************************************************** + * Name: nx_getposition + * + * Description: + * Request the position and size information for the selected window. The + * values will be return asynchronously through the client callback function + * pointer. + * + * Input Parameters: + * hwnd - The window handle + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_getposition(NXWINDOW hwnd); + +/**************************************************************************** + * Name: nx_setposition + * + * Description: + * Set the position and size for the selected window + * + * Input Parameters: + * hwnd - The window handle + * pos - The new position of the window + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_setposition(NXWINDOW hwnd, FAR const struct nxgl_point_s *pos); + +/**************************************************************************** + * Name: nx_setsize + * + * Description: + * Set the size of the selected window + * + * Input Parameters: + * hwnd - The window handle + * size - The new size of the window. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_setsize(NXWINDOW hwnd, FAR const struct nxgl_size_s *size); + +/**************************************************************************** + * Name: nx_raise + * + * Description: + * Bring the specified window to the top of the display. + * + * Input parameters: + * hwnd - the window to be raised + * + * Returned value: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_raise(NXWINDOW hwnd); + +/**************************************************************************** + * Name: nx_lower + * + * Description: + * Lower the specified window to the bottom of the display. + * + * Input parameters: + * hwnd - the window to be lowered + * + * Returned value: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_lower(NXWINDOW hwnd); + +/**************************************************************************** + * Name: nx_setpixel + * + * Description: + * Set a single pixel in the window to the specified color. This is simply + * a degenerate case of nx_fill(), but may be optimized in some architectures. + * + * Input Parameters: + * wnd - The window structure reference + * pos - The pixel location to be set + * col - The color to use in the set + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_setpixel(NXWINDOW hwnd, FAR const struct nxgl_point_s *pos, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nx_fill + * + * Description: + * Fill the specified rectangle in the window with the specified color + * + * Input Parameters: + * hwnd - The window handle + * rect - The location to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_fill(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nx_getrectangle + * + * Description: + * Get the raw contents of graphic memory within a rectangular region. NOTE: + * Since raw graphic memory is returned, the returned memory content may be + * the memory of windows above this one and may not necessarily belong to + * this window unless you assure that this is the top window. + * + * Input Parameters: + * wnd - The window structure reference + * rect - The location to be copied + * plane - Specifies the color plane to get from. + * dest - The location to copy the memory region + * deststride - The width, in bytes, the the dest memory + * + * Input Parameters: + * hwnd - The window handle + * rect - The location to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_getrectangle(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, + unsigned int plane, FAR uint8_t *dest, + unsigned int deststride); + +/**************************************************************************** + * Name: nx_filltrapezoid + * + * Description: + * Fill the specified trapezoidal region in the window with the specified color + * + * Input Parameters: + * hwnd - The window handle + * clip - Clipping rectangle relative to window (may be null) + * trap - The trapezoidal region to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_filltrapezoid(NXWINDOW hwnd, FAR const struct nxgl_rect_s *clip, + FAR const struct nxgl_trapezoid_s *trap, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nx_drawline + * + * Description: + * Fill the specified line in the window with the specified color. This + * is simply a wrapper that uses nxgl_splitline() to break the line into + * trapezoids and then calls nx_filltrapezoid() to render the line. + * + * Input Parameters: + * hwnd - The window handle + * vector - Describes the line to be drawn + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_drawline(NXWINDOW hwnd, FAR struct nxgl_vector_s *vector, + nxgl_coord_t width, nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nx_drawcircle + * + * Description: + * Draw a circular outline using the specified line thickness and color. + * + * Input Parameters: + * hwnd - The window handle + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_drawcircle(NXWINDOW hwnd, FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, nxgl_coord_t width, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nx_fillcircle + * + * Description: + * Fill a circular region using the specified color. + * + * Input Parameters: + * hwnd - The window handle + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * color - The color to use to fill the circle + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_fillcircle(NXWINDOW hwnd, FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nx_setbgcolor + * + * Description: + * Set the color of the background + * + * Input Parameters: + * handle - The connection handle + * color - The color to use in the background + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +int nx_setbgcolor(NXHANDLE handle, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nx_move + * + * Description: + * Move a rectangular region within the window + * + * Input Parameters: + * hwnd - The window within which the move is to be done + * rect - Describes the rectangular region to move + * offset - The offset to move the region. The rectangular region will be + * moved so that the origin is translated by this amount. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_move(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset); + +/**************************************************************************** + * Name: nx_bitmap + * + * Description: + * Copy a rectangular region of a larger image into the rectangle in the + * specified window. + * + * Input Parameters: + * hwnd - The window that will receive the bitmap image + * dest - Describes the rectangular region on the display that will + * receive the bit map. + * src - The start of the source image. This is an array source + * images of size CONFIG_NX_NPLANES. + * origin - The origin of the upper, left-most corner of the full bitmap. + * Both dest and origin are in window coordinates, however, origin + * may lie outside of the display. + * stride - The width of the full source image in bytes. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nx_bitmap(NXWINDOW hwnd, FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, + unsigned int stride); + +/**************************************************************************** + * Name: nx_kbdin + * + * Description: + * Used by a thread or interrupt handler that manages some kind of keypad + * hardware to report text information to the NX server. That text + * data will be routed by the NX server to the appropriate window client. + * + ****************************************************************************/ + +#ifdef CONFIG_NX_KBD +EXTERN int nx_kbdchin(NXHANDLE handle, uint8_t ch); +EXTERN int nx_kbdin(NXHANDLE handle, uint8_t nch, FAR const uint8_t *ch); +#endif + +/**************************************************************************** + * Name: nx_mousein + * + * Description: + * Used by a thread or interrupt handler that manages some kind of pointing + * hardware to report new positional data to the NX server. That positional + * data will be routed by the NX server to the appropriate window client. + * + ****************************************************************************/ + +#ifdef CONFIG_NX_MOUSE +EXTERN int nx_mousein(NXHANDLE handle, nxgl_coord_t x, nxgl_coord_t y, uint8_t buttons); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* _INCLUDE_NUTTX_NX_NX_H */ + diff --git a/nuttx/include/nuttx/nx/nxconsole.h b/nuttx/include/nuttx/nx/nxconsole.h new file mode 100644 index 0000000000..6ff7192377 --- /dev/null +++ b/nuttx/include/nuttx/nx/nxconsole.h @@ -0,0 +1,367 @@ +/**************************************************************************** + * include/nuttx/nx/nxconsole.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NX_NXCONSOLE_H +#define __INCLUDE_NUTTX_NX_NXCONSOLE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#ifdef CONFIG_NXCONSOLE + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* Nx Console prerequistes */ + +#ifndef CONFIG_NX +# warning "NX is not enabled (CONFIG_NX) +#endif + +#ifndef CONFIG_NX_MULTIUSER +# warning "NX Console requires multi-user support (CONFIG_NX_MULTIUSER)" +#endif + +/* Nx Console configuration options: + * + * CONFIG_NXCONSOLE + * Enables building of the NxConsole driver. + * + * Output text/graphics options: + * + * CONFIG_NXCONSOLE_BPP + * Currently, NxConsole supports only a single pixel depth. This + * configuration setting must be provided to support that single pixel depth. + * Default: The smallest enabled pixel depth. (see CONFIG_NX_DISABLE_*BPP) + * CONFIG_NXCONSOLE_CURSORCHAR + * The bitmap code to use as the cursor. Default '_' + * CONFIG_NXCONSOLE_MXCHARS + * NxConsole needs to remember every character written to the console so + * that it can redraw the window. This setting determines the size of some + * internal memory allocations used to hold the character data. Default: 128. + * CONFIG_NXCONSOLE_CACHESIZE + * NxConsole supports caching of rendered fonts. This font caching is required + * for two reasons: (1) First, it improves text performance, but more + * importantly (2) it preserves the font memory. Since the NX server runs on + * a separate server thread, it requires that the rendered font memory persist + * until the server has a chance to render the font. (NOTE: There is still + * inherently a race condition in this!). Unfortunately, the font cache would + * be quite large if all fonts were saved. The CONFIG_NXCONSOLE_CACHESIZE setting + * will control the size of the font cache (in number of glyphs). Only that + * number of the most recently used glyphs will be retained. Default: 16. + * CONFIG_NXCONSOLE_LINESEPARATION + * This the space (in rows) between each row of test. Default: 0 + * CONFIG_NXCONSOLE_NOWRAP + * By default, lines will wrap when the test reaches the right hand side + * of the window. This setting can be defining to change this behavior so + * that the text is simply truncated until a new line is encountered. + * + * Input options: + * + * CONFIG_NXCONSOLE_NXKBDIN + * Take input from the NX keyboard input callback. By default, keyboard + * input is taken from stdin (/dev/console). If this option is set, then + * the interface nxcon_kbdin() is enabled. That interface may be driven + * by window callback functions so that keyboard input *only* goes to the + * top window. + * CONFIG_NXCONSOLE_KBDBUFSIZE + * If CONFIG_NXCONSOLE_NXKBDIN is enabled, then this value may be used to + * define the size of the per-window keyboard input buffer. Default: 16 + * CONFIG_NXCONSOLE_NPOLLWAITERS + * The number of threads that can be waiting for read data available. + * Default: 4 + */ + +/* Cursor character */ + +#ifndef CONFIG_NXCONSOLE_CURSORCHAR +# define CONFIG_NXCONSOLE_CURSORCHAR '_' +#endif + +/* The maximum number of characters that can be remembered */ + +#ifndef CONFIG_NXCONSOLE_MXCHARS +# define CONFIG_NXCONSOLE_MXCHARS 128 +#endif + +/* Font cache -- this is the number or pre-rendered font glyphs that can be + * remembered. + */ + +#ifndef CONFIG_NXCONSOLE_CACHESIZE +# define CONFIG_NXCONSOLE_CACHESIZE 16 +#endif + +/* Pixel depth */ + +#ifndef CONFIG_NXCONSOLE_BPP +# if !defined(CONFIG_NX_DISABLE_1BPP) +# define CONFIG_NXCONSOLE_BPP 1 +# elif !defined(CONFIG_NX_DISABLE_2BPP) +# define CONFIG_NXCONSOLE_BPP 2 +# elif !defined(CONFIG_NX_DISABLE_4BPP) +# define CONFIG_NXCONSOLE_BPP 4 +# elif !defined(CONFIG_NX_DISABLE_8BPP) +# define CONFIG_NXCONSOLE_BPP 8 +# elif !defined(CONFIG_NX_DISABLE_16BPP) +# define CONFIG_NXCONSOLE_BPP 16 +//#elif !defined(CONFIG_NX_DISABLE_24BPP) +//# define CONFIG_NXCONSOLE_BPP 24 +# elif !defined(CONFIG_NX_DISABLE_32BPP) +# define CONFIG_NXCONSOLE_BPP 32 +# else +# error "No pixel depth provided" +# endif +#endif + +/* Space (in rows) between lines */ + +#ifndef CONFIG_NXCONSOLE_LINESEPARATION +# define CONFIG_NXCONSOLE_LINESEPARATION 0 +#endif + +/* Input options */ + +#ifndef CONFIG_NX_KBD +# undef CONFIG_NXCONSOLE_NXKBDIN +#endif + +#ifdef CONFIG_NXCONSOLE_NXKBDIN + +# ifndef CONFIG_NXCONSOLE_KBDBUFSIZE +# define CONFIG_NXCONSOLE_KBDBUFSIZE 16 +# elif (CONFIG_NXCONSOLE_KBDBUFSIZE < 1) || (CONFIG_NXCONSOLE_KBDBUFSIZE > 255) +# error "CONFIG_NXCONSOLE_KBDBUFSIZE is out of range (1-255)" +# endif + +# ifndef CONFIG_NXCONSOLE_NPOLLWAITERS +# define CONFIG_NXCONSOLE_NPOLLWAITERS 4 +# endif + +#else +# undef CONFIG_NXCONSOLE_KBDBUFSIZE +# define CONFIG_NXCONSOLE_KBDBUFSIZE 0 +# define CONFIG_NXCONSOLE_NPOLLWAITERS 0 +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This is the handle that can be used to access the consoles */ + +typedef FAR void *NXCONSOLE; + +/* This structure describes the window and font characteristics */ + +struct nxcon_window_s +{ + nxgl_mxpixel_t wcolor[CONFIG_NX_NPLANES]; /* Window background color */ + nxgl_mxpixel_t fcolor[CONFIG_NX_NPLANES]; /* Font color */ + struct nxgl_size_s wsize; /* Window size */ + int fontid; /* The ID of the font to use */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" { +#else +# define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nx_register + * + * Description: + * Register a console device on a raw NX window. The device will be + * registered at /dev/nxconN where N is the provided minor number. + * + * Input Parameters: + * hwnd - A handle that will be used to access the window. The window must + * persist and this handle must be valid for the life of the NX console. + * wndo - Describes the window and font to be used. The information in + * this structure is copied and the original need not persist after + * nxtool_register() returns. + * minor - The device minor number + * + * Return: + * A non-NULL handle is returned on success. + * + ****************************************************************************/ + +EXTERN NXCONSOLE nx_register(NXWINDOW hwnd, FAR struct nxcon_window_s *wndo, + int minor); + +/**************************************************************************** + * Name: nxtk_register + * + * Description: + * Register a console device on a framed NX window. The device will be + * registered at /dev/nxconN where N is the provided minor number. + * + * Input Parameters: + * hfwnd - A handle that will be used to access the window. The window must + * persist and this handle must be valid for the life of the NX console. + * wndo - Describes the window and font to be used. The information in + * this structure is copied and the original need not persist after + * nxtool_register() returns. + * minor - The device minor number + * + * Return: + * A non-NULL handle is returned on success. + * + ****************************************************************************/ + +EXTERN NXCONSOLE nxtk_register(NXTKWINDOW hfwnd, + FAR struct nxcon_window_s *wndo, int minor); + +/**************************************************************************** + * Name: nxtool_register + * + * Description: + * Register a console device on a toolbar of a framed NX window. The + * device will be registered at /dev/nxconN where N is the provided minor + * number. + * + * Input Parameters: + * hfwnd - A handle that will be used to access the toolbar. The toolbar + * must persist and this handle must be valid for the life of the NX + * console. + * wndo - Describes the window and font to be used. The information in + * this structure is copied and the original need not persist after + * nxtool_register() returns. + * minor - The device minor number + * + * Return: + * A non-NULL handle is returned on success. + * + ****************************************************************************/ + +EXTERN NXCONSOLE nxtool_register(NXTKWINDOW hfwnd, + FAR struct nxcon_window_s *wndo, int minor); + +/**************************************************************************** + * Name: nxcon_unregister + * + * Description: + * Un-register to NX console device. + * + * Input Parameters: + * handle - A handle previously returned by nx_register, nxtk_register, or + * nxtool_register. + * + * Returned Value: + * None + * + ****************************************************************************/ + +EXTERN void nxcon_unregister(NXCONSOLE handle); + +/**************************************************************************** + * Name: nxcon_redraw + * + * Description: + * Re-draw a portion of the NX console. This function should be called + * from the appropriate window callback logic. + * + * Input Parameters: + * handle - A handle previously returned by nx_register, nxtk_register, or + * nxtool_register. + * rect - The rectangle that needs to be re-drawn (in window relative + * coordinates) + * more - true: More re-draw requests will follow + * + * Returned Value: + * None + * + ****************************************************************************/ + +EXTERN void nxcon_redraw(NXCONSOLE handle, FAR const struct nxgl_rect_s *rect, + bool more); + +/**************************************************************************** + * Name: nxcon_kbdin + * + * Description: + * This function should be driven by the window kbdin callback function + * (see nx.h). When the NxConsole is the top window and keyboard input is + * received on the top window, that window callback should be directed to + * this function. This function will buffer the keyboard data and may + * it available to the NxConsole as stdin. + * + * If CONFIG_NXCONSOLE_NXKBDIN is not selected, then the NxConsole will + * receive its input from stdin (/dev/console). This works great but + * cannot be shared between different windows. Chaos will ensue if you + * try to support multiple NxConsole windows without CONFIG_NXCONSOLE_NXKBDIN + * + * Input Parameters: + * handle - A handle previously returned by nx_register, nxtk_register, or + * nxtool_register. + * buffer - The array of characters + * buflen - The number of characters that are available in buffer[] + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_NXCONSOLE_NXKBDIN +EXTERN void nxcon_kbdin(NXCONSOLE handle, FAR const uint8_t *buffer, + uint8_t buflen); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* CONFIG_NXCONSOLE */ +#endif /* __INCLUDE_NUTTX_NX_NXCONSOLE_H */ diff --git a/nuttx/include/nuttx/nx/nxfonts.h b/nuttx/include/nuttx/nx/nxfonts.h new file mode 100644 index 0000000000..f1aecb9e5a --- /dev/null +++ b/nuttx/include/nuttx/nx/nxfonts.h @@ -0,0 +1,375 @@ +/**************************************************************************** + * include/nuttx/nx/nxfonts.h + * + * Copyright (C) 2008, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NX_NXFONTS_H +#define __INCLUDE_NUTTX_NX_NXFONTS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ +/* Select the default font. If no fonts are selected, then a compilation error + * is likely down the road. + */ + +/* Sans serif fonts */ + +#if defined(CONFIG_NXFONT_SANS23X27) /* The "legacy," tiny NuttX font */ +# define NXFONT_DEFAULT FONTID_SANS23X27 + +#elif defined(CONFIG_NXFONT_SANS17X22) +# define NXFONT_DEFAULT FONTID_SANS17X22 + +#elif defined(CONFIG_NXFONT_SANS20X26) +# define NXFONT_DEFAULT FONTID_SANS20X26 + +#elif defined(CONFIG_NXFONT_SANS22X29) +# define NXFONT_DEFAULT FONTID_SANS22X29 + +#elif defined(CONFIG_NXFONT_SANS28X37) +# define NXFONT_DEFAULT FONTID_SANS28X37 + +#elif defined(CONFIG_NXFONT_SANS39X48) +# define NXFONT_DEFAULT FONTID_SANS39X48 + +/* Sans serif bold fonts */ + +#elif defined(CONFIG_NXFONT_SANS17X23B) +# define NXFONT_DEFAULT FONTID_SANS17X23B + +#elif defined(CONFIG_NXFONT_SANS20X27B) +# define NXFONT_DEFAULT FONTID_SANS20X27B + +#elif defined(CONFIG_NXFONT_SANS22X29B) +# define NXFONT_DEFAULT FONTID_SANS22X29B + +#elif defined(CONFIG_NXFONT_SANS28X37B) +# define NXFONT_DEFAULT FONTID_SANS28X37B + +#elif defined(CONFIG_NXFONT_SANS40X49B) +# define NXFONT_DEFAULT FONTID_SANS40X49B + +/* Serif fonts */ + +#elif defined(CONFIG_NXFONT_SERIF22X29) +# define NXFONT_DEFAULT FONTID_SERIF22X29 + +#elif defined(CONFIG_NXFONT_SERIF29X37) +# define NXFONT_DEFAULT FONTID_SERIF29X37 + +#elif defined(CONFIG_NXFONT_SERIF38X48) +# define NXFONT_DEFAULT FONTID_SERIF38X48 + +/* Serif bold fonts */ + +#elif defined(CONFIG_NXFONT_SERIF22X28B) +# define NXFONT_DEFAULT FONTID_SERIF22X28B + +#elif defined(CONFIG_NXFONT_SERIF27X38B) +# define NXFONT_DEFAULT FONTID_SERIF27X38B + +#elif defined(CONFIG_NXFONT_SERIF38X49B) +# define NXFONT_DEFAULT FONTID_SERIF38X49B + +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Font IDs */ + +enum nx_fontid_e +{ + FONTID_DEFAULT = 0 /* The default font */ + +/* Sans Serif fonts */ + +#ifdef CONFIG_NXFONT_SANS17X22 + , FONTID_SANS17X22 = 14 /* The 17x22 sans serif font */ +#endif + +#ifdef CONFIG_NXFONT_SANS20X26 + , FONTID_SANS20X26 = 15 /* The 20x26 sans serif font */ +#endif + +#ifdef CONFIG_NXFONT_SANS23X27 + , FONTID_SANS23X27 = 1 /* The 23x27 sans serif font */ +#endif + +#ifdef CONFIG_NXFONT_SANS22X29 + , FONTID_SANS22X29 = 2 /* The 22x29 sans serif font */ +#endif + +#ifdef CONFIG_NXFONT_SANS28X37 + , FONTID_SANS28X37 = 3 /* The 28x37 sans serif font */ +#endif + +#ifdef CONFIG_NXFONT_SANS39X48 + , FONTID_SANS39X48 = 4 /* The 39x48 sans serif font */ +#endif + +/* Sans Serif bold fonts */ + +#ifdef CONFIG_NXFONT_SANS17X23B + , FONTID_SANS17X23B = 16 /* The 17x23 sans bold font */ +#endif + +#ifdef CONFIG_NXFONT_SANS20X27B + , FONTID_SANS20X27B = 17 /* The 20x27 sans bold font */ +#endif + +#ifdef CONFIG_NXFONT_SANS22X29B + , FONTID_SANS22X29B = 5 /* The 22x29 sans bold font */ +#endif + +#ifdef CONFIG_NXFONT_SANS28X37B + , FONTID_SANS28X37B = 6 /* The 28x37 sans bold font */ +#endif + +#ifdef CONFIG_NXFONT_SANS40X49B + , FONTID_SANS40X49B = 7 /* The 40x49 sans bold font */ +#endif + +/* Serif fonts */ + +#ifdef CONFIG_NXFONT_SERIF22X29 + , FONTID_SERIF22X29 = 8 /* The 22x29 serif font */ +#endif + +#ifdef CONFIG_NXFONT_SERIF29X37 + , FONTID_SERIF29X37 = 9 /* The 29x37 serif font */ +#endif + +#ifdef CONFIG_NXFONT_SERIF38X48 + , FONTID_SERIF38X48 = 10 /* The 38x48 serif font */ +#endif + +/* Serif bold fonts */ + +#ifdef CONFIG_NXFONT_SERIF22X28B + , FONTID_SERIF22X28B = 11 /* The 22x28 serif bold font */ +#endif + +#ifdef CONFIG_NXFONT_SERIF27X38B + , FONTID_SERIF27X38B = 12 /* The 27x38 serif bold font */ +#endif + +#ifdef CONFIG_NXFONT_SERIF38X49B + , FONTID_SERIF38X49B = 13 /* The 38x49 serif bold font */ +#endif +}; + +/* This structures provides the metrics for one glyph */ + +struct nx_fontmetric_s +{ + uint32_t stride : 3; /* Width of one font row in bytes */ + uint32_t width : 6; /* Width of the font in bits */ + uint32_t height : 6; /* Height of the font in rows */ + uint32_t xoffset : 6; /* Top, left-hand corner X-offset in pixels */ + uint32_t yoffset : 6; /* Top, left-hand corner y-offset in pixels */ + uint32_t unused : 5; +}; + +/* This structure binds the glyph metrics to the glyph bitmap */ + +struct nx_fontbitmap_s +{ + struct nx_fontmetric_s metric; /* Character metrics */ + FAR const uint8_t *bitmap; /* Pointer to the character bitmap */ +}; + +/* This structure describes one contiguous grouping of glyphs that + * can be described by an array starting with encoding 'first' and + * extending through (first + nchars - 1). + */ + +struct nx_fontset_s +{ + uint8_t first; /* First bitmap character code */ + uint8_t nchars; /* Number of bitmap character codes */ + FAR const struct nx_fontbitmap_s *bitmap; +}; + +/* This structure describes the overall metrics of the fontset */ + +struct nx_font_s +{ + uint8_t mxheight; /* Max height of one glyph in rows */ + uint8_t mxwidth; /* Max width of any glyph in pixels */ + uint8_t mxbits; /* Max number of bits per character code */ + uint8_t spwidth; /* The width of a space in pixels */ +}; + +/* Finally, this structure defines everything about the font set */ + +struct nx_fontpackage_s +{ + uint8_t id; /* The font ID */ + FAR const struct nx_font_s metrics; /* Font set metrics */ + FAR const struct nx_fontset_s font7; /* Fonts for 7-bit encoding */ +#if CONFIG_NXFONTS_CHARBITS >= 8 + FAR const struct nx_fontset_s font8; /* Fonts for 8-bit encoding */ +#endif +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" { +#else +# define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nxf_getfonthandle + * + * Description: + * Given a numeric font ID, return a handle that may be subsequently be + * used to access the font data sets. + * + * Input Parameters: + * fontid: Identifies the font set to get + * + ****************************************************************************/ + +EXTERN NXHANDLE nxf_getfonthandle(enum nx_fontid_e fontid); + +/**************************************************************************** + * Name: nxf_getfontset + * + * Description: + * Return information about the current font set + * + * Input Parameters: + * handle: A font handle previously returned by nxf_getfonthandle() + * + ****************************************************************************/ + +EXTERN FAR const struct nx_font_s *nxf_getfontset(NXHANDLE handle); + +/**************************************************************************** + * Name: nxf_getbitmap + * + * Description: + * Return font bitmap information for the selected character encoding. + * + * Input Parameters: + * handle: A font handle previously returned by nxf_getfonthandle() + * ch: Character code whose bitmap is requested + * + * Returned Value: + * An instance of struct nx_fontbitmap_s describing the glyph. + * + ****************************************************************************/ + +EXTERN FAR const struct nx_fontbitmap_s * + nxf_getbitmap(NXHANDLE handle, uint16_t ch); + +/**************************************************************************** + * Name: nxf_convert_*bpp + * + * Description: + * Convert the 1BPP font to a new pixel depth + * + * Input Parameters: + * dest - The destination buffer provided by the caller. + * height - The max height of the returned char in rows + * width - The max width of the returned char in pixels + * stride - The width of the destination buffer in bytes + * bm - Describes the character glyph to convert + * color - The color to use for '1' bits in the font bitmap + * (0 bits are transparent) + * + * Returned Value: + * OK on Success, ERROR: on failure with errno set appropriately. + * (never fails) + * + ****************************************************************************/ + +EXTERN int nxf_convert_1bpp(FAR uint8_t *dest, uint16_t height, + uint16_t width, uint16_t stride, + FAR const struct nx_fontbitmap_s *bm, + nxgl_mxpixel_t color); +EXTERN int nxf_convert_2bpp(FAR uint8_t *dest, uint16_t height, + uint16_t width, uint16_t stride, + FAR const struct nx_fontbitmap_s *bm, + nxgl_mxpixel_t color); +EXTERN int nxf_convert_4bpp(FAR uint8_t *dest, uint16_t height, + uint16_t width, uint16_t stride, + FAR const struct nx_fontbitmap_s *bm, + nxgl_mxpixel_t color); +EXTERN int nxf_convert_8bpp(FAR uint8_t *dest, uint16_t height, + uint16_t width, uint16_t stride, + FAR const struct nx_fontbitmap_s *bm, + nxgl_mxpixel_t color); +EXTERN int nxf_convert_16bpp(FAR uint16_t *dest, uint16_t height, + uint16_t width, uint16_t stride, + FAR const struct nx_fontbitmap_s *bm, + nxgl_mxpixel_t color); +EXTERN int nxf_convert_24bpp(FAR uint32_t *dest, uint16_t height, + uint16_t width, uint16_t stride, + FAR const struct nx_fontbitmap_s *bm, + nxgl_mxpixel_t color); +EXTERN int nxf_convert_32bpp(FAR uint32_t *dest, uint16_t height, + uint16_t width, uint16_t stride, + FAR const struct nx_fontbitmap_s *bm, + nxgl_mxpixel_t color); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_NX_NXFONTS_H */ diff --git a/nuttx/include/nuttx/nx/nxglib.h b/nuttx/include/nuttx/nx/nxglib.h new file mode 100644 index 0000000000..4dec400705 --- /dev/null +++ b/nuttx/include/nuttx/nx/nxglib.h @@ -0,0 +1,738 @@ +/**************************************************************************** + * include/nuttx/nx/nxglib.h + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NX_NXGLIB_H +#define __INCLUDE_NUTTX_NX_NXGLIB_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#ifdef CONFIG_NX_LCDDRIVER +# include +#else +# include +#endif + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_NX_NPLANES +# define CONFIG_NX_NPLANES 1 /* Max number of color planes supported */ +#endif + +/* Driver Selection *********************************************************/ +/* NX_DRIVERTYPE selects either the framebuffer or LCD driver; + * NX_PLANINFO_TYPE hides the difference in the framebuffer and LCD driver + * plane types. defines are used instead of a typedefs to avoid type + * mismatches. + */ + +#ifdef CONFIG_NX_LCDDRIVER +# define NX_DRIVERTYPE struct lcd_dev_s +# define NX_PLANEINFOTYPE struct lcd_planeinfo_s +#else +# define NX_DRIVERTYPE struct fb_vtable_s +# define NX_PLANEINFOTYPE struct fb_planeinfo_s +#endif + +/* NXGL Macros **************************************************************/ +/* Mnemonics for indices */ + +#define NX_TOP_NDX (0) +#define NX_LEFT_NDX (1) +#define NX_RIGHT_NDX (2) +#define NX_BOTTOM_NDX (3) + +/* Handy macros */ + +#define ngl_min(a,b) ((a) < (b) ? (a) : (b)) +#define ngl_max(a,b) ((a) > (b) ? (a) : (b)) +#define ngl_swap(a,b,t) do { t = a; a = b; b = t; } while (0) +#define ngl_clipl(a,mn) ((a) < (mn) ? (mn) : (a)) +#define ngl_clipr(a,mx) ((a) > (mx) ? (mx) : (a)) +#define ngl_clip(a,mx,mn) ((a) < (mn) ? (mn) : (a) > (mx) ? (mx) : (a)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Pixels *******************************************************************/ + +/* The size of graphics solutions can be reduced by disabling support for + * specific resolutions. One thing we can do, for example, is to select + * the smallest common pixel representation: + */ + +#if !defined(CONFIG_NX_DISABLE_32BPP) || !defined(CONFIG_NX_DISABLE_24BPP) +typedef uint32_t nxgl_mxpixel_t; +#elif !defined(CONFIG_NX_DISABLE_16BPP) +typedef uint16_t nxgl_mxpixel_t; +#else +typedef uint8_t nxgl_mxpixel_t; +#endif + +/* Graphics structures ******************************************************/ + +/* A given coordinate is limited to the screen height an width. If either + * of those values exceed 32,767 pixels, then the following will have to need + * to change: + */ + +typedef int16_t nxgl_coord_t; + +/* Describes a point on the display */ + +struct nxgl_point_s +{ + nxgl_coord_t x; /* X position, range: 0 to screen width - 1 */ + nxgl_coord_t y; /* Y position, range: 0 to screen height - 1 */ +}; + +/* Describes the size of a rectangular region */ + +struct nxgl_size_s +{ + nxgl_coord_t w; /* Width in pixels */ + nxgl_coord_t h; /* Height in rows */ +}; + +/* Describes a positioned rectangle on the display */ + +struct nxgl_rect_s +{ + struct nxgl_point_s pt1; /* Upper, left-hand corner */ + struct nxgl_point_s pt2; /* Lower, right-hand corner */ +}; + +/* Describes a vector starting at pt1 and extending throug pt2 */ + +struct nxgl_vector_s +{ + struct nxgl_point_s pt1; /* Start position */ + struct nxgl_point_s pt2; /* End position */ +}; + +/* Describes a run, i.e., a horizontal line. Note that the start/end positions + * have fractional precision. This is necessary for good joining of trapezoids + * when a more complex shape is decomposed into trapezoids + */ + +struct nxgl_run_s +{ + b16_t x1; /* Left X position, range: 0 to x2 */ + b16_t x2; /* Right X position, range: x1 to screen width - 1 */ + nxgl_coord_t y; /* Top Y position, range: 0 to screen height - 1 */ +}; + +/* Describes a horizontal trapezoid on the display in terms the run at the + * top of the trapezoid and the run at the bottom + */ + +struct nxgl_trapezoid_s +{ + struct nxgl_run_s top; /* Top run */ + struct nxgl_run_s bot; /* bottom run */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" { +#else +# define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Color conversons *********************************************************/ + +/**************************************************************************** + * Name: nxgl_rgb2yuv + * + * Description: + * Convert 8-bit RGB triplet to 8-bit YUV triplet + * + ****************************************************************************/ + +EXTERN void nxgl_rgb2yuv(uint8_t r, uint8_t g, uint8_t b, + uint8_t *y, uint8_t *u, uint8_t *v); + +/**************************************************************************** + * Name: nxgl_yuv2rgb + * + * Description: + * Convert 8-bit RGB triplet to 8-bit YUV triplet + * + ****************************************************************************/ + +EXTERN void nxgl_yuv2rgb(uint8_t y, uint8_t u, uint8_t v, + uint8_t *r, uint8_t *g, uint8_t *b); + +/* Rasterizers **************************************************************/ + +/**************************************************************************** + * Name: nxgl_setpixel_*bpp + * + * Descripton: + * Draw a single pixel in graphics memory at the given position and + * with the given color. This is equivalent to nxgl_fillrectangle_*bpp() + * with a 1x1 rectangle but is more efficient. + * + ****************************************************************************/ + +EXTERN void nxgl_setpixel_1bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_point_s *pos, + uint8_t color); +EXTERN void nxgl_setpixel_2bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_point_s *pos, + uint8_t color); +EXTERN void nxgl_setpixel_4bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_point_s *pos, + uint8_t color); +EXTERN void nxgl_setpixel_8bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_point_s *pos, + uint8_t color); +EXTERN void nxgl_setpixel_16bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_point_s *pos, + uint16_t color); +EXTERN void nxgl_setpixel_24bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_point_s *pos, + uint32_t color); +EXTERN void nxgl_setpixel_32bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_point_s *pos, + uint32_t color); + +/**************************************************************************** + * Name: nxgl_fillrectangle_*bpp + * + * Descripton: + * Fill a rectangle region in the graphics memory with a fixed color + * + ****************************************************************************/ + +EXTERN void nxgl_fillrectangle_1bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + uint8_t color); +EXTERN void nxgl_fillrectangle_2bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + uint8_t color); +EXTERN void nxgl_fillrectangle_4bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + uint8_t color); +EXTERN void nxgl_fillrectangle_8bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + uint8_t color); +EXTERN void nxgl_fillrectangle_16bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + uint16_t color); +EXTERN void nxgl_fillrectangle_24bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + uint32_t color); +EXTERN void nxgl_fillrectangle_32bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + uint32_t color); + +/**************************************************************************** + * Name: nxgl_getrectangle_*bpp + * + * Descripton: + * Fetch a rectangular region from graphics memory. The source is + * expressed as a rectangle. + * + ****************************************************************************/ + +EXTERN void nxgl_getrectangle_1bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR void *dest, unsigned int deststride); +EXTERN void nxgl_getrectangle_2bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR void *dest, unsigned int deststride); +EXTERN void nxgl_getrectangle_4bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR void *dest, unsigned int deststride); +EXTERN void nxgl_getrectangle_8bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR void *dest, unsigned int deststride); +EXTERN void nxgl_getrectangle_16bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR void *dest, unsigned int deststride); +EXTERN void nxgl_getrectangle_24bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR void *dest, unsigned int deststride); +EXTERN void nxgl_getrectangle_32bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR void *dest, unsigned int deststride); + +/**************************************************************************** + * Name: nxglib_filltrapezoid_*bpp + * + * Descripton: + * Fill a trapezoidal region in the graphics memory with a fixed color. + * Clip the trapezoid to lie within a boundng box. This is useful for + * drawing complex shapes that can be broken into a set of trapezoids. + * + ****************************************************************************/ + +EXTERN void nxgl_filltrapezoid_1bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_trapezoid_s *trap, + FAR const struct nxgl_rect_s *bounds, + uint8_t color); +EXTERN void nxgl_filltrapezoid_2bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_trapezoid_s *trap, + FAR const struct nxgl_rect_s *bounds, + uint8_t color); +EXTERN void nxgl_filltrapezoid_4bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_trapezoid_s *trap, + FAR const struct nxgl_rect_s *bounds, + uint8_t color); +EXTERN void nxgl_filltrapezoid_8bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_trapezoid_s *trap, + FAR const struct nxgl_rect_s *bounds, + uint8_t color); +EXTERN void nxgl_filltrapezoid_16bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_trapezoid_s *trap, + FAR const struct nxgl_rect_s *bounds, + uint16_t color); +EXTERN void nxgl_filltrapezoid_24bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_trapezoid_s *trap, + FAR const struct nxgl_rect_s *bounds, + uint32_t color); +EXTERN void nxgl_filltrapezoid_32bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_trapezoid_s *trap, + FAR const struct nxgl_rect_s *bounds, + uint32_t color); + +/**************************************************************************** + * Name: nxgl_moverectangle_*bpp + * + * Descripton: + * Move a rectangular region from location to another in the + * framebuffer/LCD memory. The source is expressed as a rectangle; the + * destination position is expressed as a point corresponding to the + * translation of the upper, left-hand corner. + * + ****************************************************************************/ + +EXTERN void nxgl_moverectangle_1bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR struct nxgl_point_s *offset); +EXTERN void nxgl_moverectangle_2bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR struct nxgl_point_s *offset); +EXTERN void nxgl_moverectangle_4bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR struct nxgl_point_s *offset); +EXTERN void nxgl_moverectangle_8bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR struct nxgl_point_s *offset); +EXTERN void nxgl_moverectangle_16bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR struct nxgl_point_s *offset); +EXTERN void nxgl_moverectangle_24bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR struct nxgl_point_s *offset); +EXTERN void nxgl_moverectangle_32bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *rect, + FAR struct nxgl_point_s *offset); + +/**************************************************************************** + * Name: nxgl_copyrectangle_*bpp + * + * Descripton: + * Copy a rectangular bitmap image into the specific position in the + * graphics memory. + * + ****************************************************************************/ + +EXTERN void nxgl_copyrectangle_1bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *dest, + FAR const void *src, + FAR const struct nxgl_point_s *origin, + unsigned int srcstride); +EXTERN void nxgl_copyrectangle_2bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *dest, + FAR const void *src, + FAR const struct nxgl_point_s *origin, + unsigned int srcstride); +EXTERN void nxgl_copyrectangle_4bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *dest, + FAR const void *src, + FAR const struct nxgl_point_s *origin, + unsigned int srcstride); +EXTERN void nxgl_copyrectangle_8bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *dest, + FAR const void *src, + FAR const struct nxgl_point_s *origin, + unsigned int srcstride); +EXTERN void nxgl_copyrectangle_16bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *dest, + FAR const void *src, + FAR const struct nxgl_point_s *origin, + unsigned int srcstride); +EXTERN void nxgl_copyrectangle_24bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *dest, + FAR const void *src, + FAR const struct nxgl_point_s *origin, + unsigned int srcstride); +EXTERN void nxgl_copyrectangle_32bpp(FAR NX_PLANEINFOTYPE *pinfo, + FAR const struct nxgl_rect_s *dest, + FAR const void *src, + FAR const struct nxgl_point_s *origin, + unsigned int srcstride); + +/**************************************************************************** + * Name: nxgl_rectcopy + * + * Description: + * This is essentially memcpy for rectangles. We don't do structure + * assignments because some compilers are not good at that. + * + ****************************************************************************/ + +EXTERN void nxgl_rectcopy(FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src); + +/**************************************************************************** + * Name: nxgl_rectoffset + * + * Description: + * Offset the rectangle position by the specified dx, dy values. + * + ****************************************************************************/ + +EXTERN void nxgl_rectoffset(FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src, + nxgl_coord_t dx, nxgl_coord_t dy); + +/**************************************************************************** + * Name: nxgl_vectoradd + * + * Description: + * Add two 2x1 vectors and save the result to a third. + * + ****************************************************************************/ + +EXTERN void nxgl_vectoradd(FAR struct nxgl_point_s *dest, + FAR const struct nxgl_point_s *v1, + FAR const struct nxgl_point_s *v2); + +/**************************************************************************** + * Name: nxgl_vectorsubtract + * + * Description: + * Add subtract vector v2 from vector v1 and return the result in vector dest + * + ****************************************************************************/ + +EXTERN void nxgl_vectsubtract(FAR struct nxgl_point_s *dest, + FAR const struct nxgl_point_s *v1, + FAR const struct nxgl_point_s *v2); + +/**************************************************************************** + * Name: nxgl_rectintersect + * + * Description: + * Return the rectangle representing the intersection of the two rectangles. + * + ****************************************************************************/ + +EXTERN void nxgl_rectintersect(FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src1, + FAR const struct nxgl_rect_s *src2); + +/**************************************************************************** + * Name: nxgl_intersecting + * + * Description: + * Return true if the rectangles intersect. + * + ****************************************************************************/ + +EXTERN bool nxgl_intersecting(FAR const struct nxgl_rect_s *rect1, + FAR const struct nxgl_rect_s *rect2); + +/**************************************************************************** + * Name: nxgl_rectadd + * + * Description: + * Return the rectangle that contains exactly two other rectanges. + * + ****************************************************************************/ + +EXTERN void nxgl_rectadd(FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src1, + FAR const struct nxgl_rect_s *src2); + +/**************************************************************************** + * Name: nxgl_rectunion + * + * Description: + * Given two rectanges, src1 and src2, return the larger rectangle that + * contains both, dest. + * + ****************************************************************************/ + +EXTERN void nxgl_rectunion(FAR struct nxgl_rect_s *dest, + FAR const struct nxgl_rect_s *src1, + FAR const struct nxgl_rect_s *src2); + +/**************************************************************************** + * Name: nxgl_nonintersecting + * + * Description: + * Return the regions of rectangle rect 1 that do not intersect with + * rect2. This will be four rectangles ,some of which may be + * degenerate (and can be picked off with nxgl_nullrect) + * + ****************************************************************************/ + +EXTERN void nxgl_nonintersecting(FAR struct nxgl_rect_s result[4], + FAR const struct nxgl_rect_s *rect1, + FAR const struct nxgl_rect_s *rect2); + +/**************************************************************************** + * Name: nxgl_rectoverlap + * + * Description: + * Return true if the two rectangles overlap + * + ****************************************************************************/ + +EXTERN bool nxgl_rectoverlap(FAR struct nxgl_rect_s *rect1, + FAR struct nxgl_rect_s *rect2); + +/**************************************************************************** + * Name: nxgl_rectinside + * + * Description: + * Return true if the point pt lies within rect. + * + ****************************************************************************/ + +EXTERN bool nxgl_rectinside(FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *pt); + +/**************************************************************************** + * Name: nxgl_rectsize + * + * Description: + * Return the size of the specified rectangle. + * + ****************************************************************************/ + +EXTERN void nxgl_rectsize(FAR struct nxgl_size_s *size, + FAR const struct nxgl_rect_s *rect); + +/**************************************************************************** + * Name: nxgl_nullrect + * + * Description: + * Return true if the area of the retangle is <= 0. + * + ****************************************************************************/ + +EXTERN bool nxgl_nullrect(FAR const struct nxgl_rect_s *rect); + +/**************************************************************************** + * Name: nxgl_runoffset + * + * Description: + * Offset the run position by the specified dx, dy values. + * + ****************************************************************************/ + +EXTERN void nxgl_runoffset(FAR struct nxgl_run_s *dest, + FAR const struct nxgl_run_s *src, + nxgl_coord_t dx, nxgl_coord_t dy); + +/**************************************************************************** + * Name: nxgl_runcopy + * + * Description: + * This is essentially memcpy for runs. We don't do structure assignments + * because some compilers are not good at that. + * + ****************************************************************************/ + +EXTERN void nxgl_runcopy(FAR struct nxgl_run_s *dest, + FAR const struct nxgl_run_s *src); + +/**************************************************************************** + * Name: nxgl_trapoffset + * + * Description: + * Offset the trapezoid position by the specified dx, dy values. + * + ****************************************************************************/ + +EXTERN void nxgl_trapoffset(FAR struct nxgl_trapezoid_s *dest, + FAR const struct nxgl_trapezoid_s *src, + nxgl_coord_t dx, nxgl_coord_t dy); + +/**************************************************************************** + * Name: nxgl_trapcopy + * + * Description: + * This is essentially memcpy for trapezoids. We don't do structure + * assignments because some compilers are not good at that. + * + ****************************************************************************/ + +EXTERN void nxgl_trapcopy(FAR struct nxgl_trapezoid_s *dest, + FAR const struct nxgl_trapezoid_s *src); + +/**************************************************************************** + * Name: nxgl_colorcopy + * + * Description: + * This is essentially memcpy for colors. This does very little for us + * other than hide all of the conditional compilation for planar colors + * in one place. + * + ****************************************************************************/ + +EXTERN void nxgl_colorcopy(nxgl_mxpixel_t dest[CONFIG_NX_NPLANES], + const nxgl_mxpixel_t src[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxgl_splitline + * + * Description: + * In the general case, a line with width can be represented as a + * parallelogram with a triangle at the top and bottom. Triangles and + * parallelograms are both degenerate versions of a trapeziod. This + * function breaks a wide line into triangles and trapezoids. This + * function also detects other degenerate cases: + * + * 1. If y1 == y2 then the line is horizontal and is better represented + * as a rectangle. + * 2. If x1 == x2 then the line is vertical and also better represented + * as a rectangle. + * 3. If the width of the line is 1, then there are no triangles at the + * top and bottome (this may also be the case if the width is narrow + * and the line is near vertical). + * 4. If the line is oriented is certain angles, it may consist only of + * the upper and lower triangles with no trapezoid in between. In + * this case, 3 trapezoids will be returned, but traps[1] will be + * degenerate. + * + * Input parameters: + * vector - A pointer to the vector described the line to be drawn. + * traps - A pointer to a array of trapezoids (size 3). + * rect - A pointer to a rectangle. + * + * Returned value: + * 0: Line successfully broken up into three trapezoids. Values in + * traps[0], traps[1], and traps[2] are valid. + * 1: Line successfully represented by one trapezoid. Value in traps[1] + * is valid. + * 2: Line successfully represented by one rectangle. Value in rect is + * valid + * <0: On errors, a negated errno value is returned. + * + ****************************************************************************/ + +EXTERN int nxgl_splitline(FAR struct nxgl_vector_s *vector, + FAR struct nxgl_trapezoid_s *traps, + FAR struct nxgl_rect_s *rect, + nxgl_coord_t linewidth); + +/**************************************************************************** + * Name: nxgl_circlepts + * + * Description: + * Given a description of a circle, return a set of 16 points on the + * circumference of the circle. These points may then be used by + * nx_drawcircle() or related APIs to draw a circle outline. + * + * Input parameters: + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * circle - A pointer the first entry in an array of 16 points where the + * circle points will be returned. + * + * Returned value: + * None + * + ****************************************************************************/ + +EXTERN void nxgl_circlepts(FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, + FAR struct nxgl_point_s *circle); + +/**************************************************************************** + * Name: nxgl_circletraps + * + * Description: + * Given a description of a a circle, return 8 trapezoids that can be + * used to fill the circle by nx_fillcircle() and other interfaces. + * + * Input parameters: + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * circle - A pointer the first entry in an array of 8 trapezoids where + * the circle description will be returned. + * + * Returned value: + * None + * + ****************************************************************************/ + +EXTERN void nxgl_circletraps(FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, + FAR struct nxgl_trapezoid_s *circle); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_NX_NXGLIB_H */ diff --git a/nuttx/include/nuttx/nx/nxtk.h b/nuttx/include/nuttx/nx/nxtk.h new file mode 100644 index 0000000000..60080e47fc --- /dev/null +++ b/nuttx/include/nuttx/nx/nxtk.h @@ -0,0 +1,713 @@ +/**************************************************************************** + * include/nuttx/nx/nxtk.h + * + * Copyright (C) 2008-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NX_NXTK_H +#define __INCLUDE_NUTTX_NX_NXTK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +#ifndef CONFIG_NXTK_BORDERWIDTH +# define CONFIG_NXTK_BORDERWIDTH 4 +#endif + +#ifndef CONFIG_NXTK_BORDERCOLOR1 +# if !defined(CONFIG_NX_DISABLE_32BPP) || !defined(CONFIG_NX_DISABLE_24BPP) +# define CONFIG_NXTK_BORDERCOLOR1 0x00a9a9a9 +# elif !defined(CONFIG_NX_DISABLE_16BPP) +# define CONFIG_NXTK_BORDERCOLOR1 0xad55 +# elif !defined(CONFIG_NX_DISABLE_4BPP) +# define CONFIG_NXTK_BORDERCOLOR1 6 +# else +# define CONFIG_NXTK_BORDERCOLOR1 'B' +# endif +#endif + +#ifndef CONFIG_NXTK_BORDERCOLOR2 +# if !defined(CONFIG_NX_DISABLE_32BPP) || !defined(CONFIG_NX_DISABLE_24BPP) +# define CONFIG_NXTK_BORDERCOLOR2 0x00696969 +# elif !defined(CONFIG_NX_DISABLE_16BPP) +# define CONFIG_NXTK_BORDERCOLOR2 0x6b4d +# elif !defined(CONFIG_NX_DISABLE_4BPP) +# define CONFIG_NXTK_BORDERCOLOR2 4 +# else +# define CONFIG_NXTK_BORDERCOLOR2 'b' +# endif +#endif + +#ifndef CONFIG_NXTK_BORDERCOLOR3 +# if !defined(CONFIG_NX_DISABLE_32BPP) || !defined(CONFIG_NX_DISABLE_24BPP) +# define CONFIG_NXTK_BORDERCOLOR3 0x00d9d9d9 +# elif !defined(CONFIG_NX_DISABLE_16BPP) +# define CONFIG_NXTK_BORDERCOLOR3 0xdedb +# elif !defined(CONFIG_NX_DISABLE_4BPP) +# define CONFIG_NXTK_BORDERCOLOR3 8 +# else +# define CONFIG_NXTK_BORDERCOLOR3 'S' +# endif +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This is the handle that can be used to access the window data region */ + +typedef FAR void *NXTKWINDOW; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" { +#else +# define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nxtk_openwindow + * + * Description: + * Create a new, framed window. + * + * Input Parameters: + * handle - The handle returned by nx_connect + * cb - Callbacks used to process window events + * arg - User provided value that will be returned with NXTK callbacks. + * + * Return: + * Success: A non-NULL handle used with subsequent NXTK window accesses + * Failure: NULL is returned and errno is set appropriately + * + ****************************************************************************/ + +EXTERN NXTKWINDOW nxtk_openwindow(NXHANDLE handle, + FAR const struct nx_callback_s *cb, + FAR void *arg); + +/**************************************************************************** + * Name: nxtk_closewindow + * + * Description: + * Close the window opened by nxtk_openwindow + * + * Input Parameters: + * hfwnd - The handle returned by nxtk_openwindow + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_closewindow(NXTKWINDOW hfwnd); + +/**************************************************************************** + * Name: nxtk_block + * + * Description: + * This is callback will do to things: (1) any queue a 'blocked' callback + * to the window and then (2) block any further window messaging. + * + * The 'blocked' callback is the response from nx_block (or nxtk_block). + * Those blocking interfaces are used to assure that no further messages are + * are directed to the window. Receipt of the blocked callback signifies + * that (1) there are no further pending callbacks and (2) that the + * window is now 'defunct' and will receive no further callbacks. + * + * This callback supports coordinated destruction of a window in multi- + * user mode. In multi-use mode, the client window logic must stay + * intact until all of the queued callbacks are processed. Then the + * window may be safely closed. Closing the window prior with pending + * callbacks can lead to bad behavior when the callback is executed. + * + * Multiple user mode only! + * + * Input Parameters: + * hfwnd - The window to be blocked + * arg - An argument that will accompany the block messages (This is arg2 + * in the blocked callback). + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +#ifdef CONFIG_NX_MULTIUSER +EXTERN int nxtk_block(NXTKWINDOW hfwnd, FAR void *arg); +#endif + +/**************************************************************************** + * Name: nxtk_getposition + * + * Description: + * Request the position and size information for the selected framed window. + * The size/position for the client window and toolbar will be returned + * asynchronously through the client callback function pointer. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_getposition(NXTKWINDOW hfwnd); + +/**************************************************************************** + * Name: nxtk_setposition + * + * Description: + * Set the position for the selected client window. This position does not + * include the offsets for the borders nor for any toolbar. Those offsets + * will be added in to set the full window position. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow + * pos - The new position of the client sub-window + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_setposition(NXTKWINDOW hfwnd, FAR const struct nxgl_point_s *pos); + +/**************************************************************************** + * Name: nxtk_setsize + * + * Description: + * Set the size for the selected client window. This size does not + * include the sizes of the borders nor for any toolbar. Those sizes + * will be added in to set the full window size. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow + * size - The new size of the client sub-window. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_setsize(NXTKWINDOW hfwnd, FAR const struct nxgl_size_s *size); + +/**************************************************************************** + * Name: nxtk_raise + * + * Description: + * Bring the window containing the specified client sub-window to the top + * of the display. + * + * Input parameters: + * hfwnd - the window to be raised. This must have been previously created + * by nxtk_openwindow(). + * + * Returned value: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_raise(NXTKWINDOW hfwnd); + +/**************************************************************************** + * Name: nxtk_lower + * + * Description: + * Lower the window containing the specified client sub-window to the + * bottom of the display. + * + * Input parameters: + * hfwnd - the window to be lowered. This must have been previously created + * by nxtk_openwindow(). + * + * Returned value: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_lower(NXTKWINDOW hfwnd); + +/**************************************************************************** + * Name: nxtk_fillwindow + * + * Description: + * Fill the specified rectangle in the client window with the specified color + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow + * rect - The location within the client window to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_fillwindow(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxtk_getwindow + * + * Description: + * Get the raw contents of graphic memory within a rectangular region. NOTE: + * Since raw graphic memory is returned, the returned memory content may be + * the memory of windows above this one and may not necessarily belong to + * this window unless you assure that this is the top window. + * + * Input Parameters: + * wnd - The window structure reference + * rect - The location to be copied + * plane - Specifies the color plane to get from. + * dest - The location to copy the memory region + * deststride - The width, in bytes, the the dest memory + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_getwindow(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *rect, + unsigned int plane, FAR uint8_t *dest, + unsigned int deststride); + +/**************************************************************************** + * Name: nxtk_filltrapwindow + * + * Description: + * Fill the specified trapezoid in the client window with the specified color + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow + * trap - The trapezoidal region to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_filltrapwindow(NXTKWINDOW hfwnd, + FAR const struct nxgl_trapezoid_s *trap, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxtk_drawlinewindow + * + * Description: + * Fill the specified line in the window with the specified color. This + * is simply a wrapper that uses nxgl_splitline() to break the line into + * trapezoids and then calls nxtk_filltrapwindow() to render the line. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow + * vector - Describes the line to be drawn + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_drawlinewindow(NXTKWINDOW hfwnd, + FAR struct nxgl_vector_s *vector, + nxgl_coord_t width, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxtk_drawcirclewindow + * + * Description: + * Draw a circular outline using the specified line thickness and color. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow() + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_drawcirclewindow(NXTKWINDOW hfwnd, + FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, nxgl_coord_t width, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxtk_fillcirclewindow + * + * Description: + * Fill a circular region using the specified color. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow() + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * color - The color to use to fill the circle + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_fillcirclewindow(NXWINDOW hfwnd, + FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxtk_movewindow + * + * Description: + * Move a rectangular region within the client sub-window of a framed window + * + * Input Parameters: + * hfwnd - The client sub-window within which the move is to be done. + * This must have been previously created by nxtk_openwindow(). + * rect - Describes the rectangular region relative to the client + * sub-window to move + * offset - The offset to move the region. The rectangular region will be + * moved so that the origin is translated by this amount. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_movewindow(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset); + +/**************************************************************************** + * Name: nxtk_bitmapwindow + * + * Description: + * Copy a rectangular region of a larger image into the rectangle in the + * specified client sub-window. + * + * Input Parameters: + * hfwnd The client sub0window that will receive the bitmap image + * dest - Describes the rectangular region on in the client sub-window + * will receive the bit map. + * src - The start of the source image(s). This is an array source + * images of size CONFIG_NX_NPLANES. + * origin - The origin of the upper, left-most corner of the full bitmap. + * Both dest and origin are in sub-window coordinates, however, the + * origin may lie outside of the sub-window display. + * stride - The width of the full source image in pixels. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_bitmapwindow(NXTKWINDOW hfwnd, + FAR const struct nxgl_rect_s *dest, + FAR const void **src, + FAR const struct nxgl_point_s *origin, + unsigned int stride); + +/**************************************************************************** + * Name: nxtk_opentoolbar + * + * Description: + * Create a tool bar at the top of the specified framed window + * + * Input Parameters: + * hfwnd - The handle returned by nxtk_openwindow + * height - The requested height of the toolbar in pixels + * cb - Callbacks used to process toolbar events + * arg - User provided value that will be returned with toolbar callbacks. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_opentoolbar(NXTKWINDOW hfwnd, nxgl_coord_t height, + FAR const struct nx_callback_s *cb, + FAR void *arg); + +/**************************************************************************** + * Name: nxtk_closetoolbar + * + * Description: + * Remove the tool bar at the top of the specified framed window + * + * Input Parameters: + * hfwnd - The handle returned by nxtk_openwindow + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_closetoolbar(NXTKWINDOW hfwnd); + +/**************************************************************************** + * Name: nxtk_toolbarbounds + * + * Description: + * Return a bounding box that contains the toolbar in the coordinates of + * the containing, framed window. For example, the recturned origin + * (rect.pt1) is the offset toolbar in the framed window. + * + * NOTE: This function is unsafe in the case of the multi-user NX server + * where the width of the window may be being changed asynchronously! It + * may return the old size in this case. + * + * Input Parameters: + * hfwnd - The handle returned by nxtk_openwindow + * bounds - User provided location in which to return the bounding box. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_toolbarbounds(NXTKWINDOW hfwnd, FAR struct nxgl_rect_s *bounds); + +/**************************************************************************** + * Name: nxtk_filltoolbar + * + * Description: + * Fill the specified rectangle in the toolbar sub-window with the specified color + * + * Input Parameters: + * hfwnd - The handle returned by nxtk_openwindow + * rect - The location within the toolbar window to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_filltoolbar(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *rect, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxtk_gettoolbar + * + * Description: + * Get the raw contents of graphic memory within a rectangular region. NOTE: + * Since raw graphic memory is returned, the returned memory content may be + * the memory of windows above this one and may not necessarily belong to + * this window unless you assure that this is the top window. + * + * Input Parameters: + * wnd - The window structure reference + * rect - The location to be copied + * plane - Specifies the color plane to get from. + * dest - The location to copy the memory region + * deststride - The width, in bytes, the the dest memory + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_gettoolbar(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *rect, + unsigned int plane, FAR uint8_t *dest, + unsigned int deststride); + +/**************************************************************************** + * Name: nxtk_filltraptoolbar + * + * Description: + * Fill the specified trapezoid in the toolbar sub-window with the specified color + * + * Input Parameters: + * hfwnd - The handle returned by nxtk_openwindow + * trap - The trapezoidal region to be filled + * color - The color to use in the fill + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_filltraptoolbar(NXTKWINDOW hfwnd, FAR const struct nxgl_trapezoid_s *trap, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxtk_drawlinetoolbar + * + * Description: + * Fill the specified line in the toolbar sub-window with the specified + * color. This is simply a wrapper that uses nxgl_splitline() to break the + * line into trapezoids and then calls nxtk_filltraptoolbar() to render the + * lines. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow + * vector - Describes the line to be drawn + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_drawlinetoolbar(NXTKWINDOW hfwnd, + FAR struct nxgl_vector_s *vector, + nxgl_coord_t width, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxtk_drawcircletoolbar + * + * Description: + * Draw a circular outline using the specified line thickness and color. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow() + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * width - The width of the line + * color - The color to use to fill the line + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_drawcircletoolbar(NXTKWINDOW hfwnd, + FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, nxgl_coord_t width, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxtk_fillcircletoolbar + * + * Description: + * Fill a circular region using the specified color. + * + * Input Parameters: + * hfwnd - The window handle returned by nxtk_openwindow() + * center - A pointer to the point that is the center of the circle + * radius - The radius of the circle in pixels. + * color - The color to use to fill the circle + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_fillcircletoolbar(NXWINDOW hfwnd, + FAR const struct nxgl_point_s *center, + nxgl_coord_t radius, + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +/**************************************************************************** + * Name: nxtk_movetoolbar + * + * Description: + * Move a rectangular region within the toolbar sub-window of a framed window + * + * Input Parameters: + * hfwnd - The sub-window containing the toolbar within which the move is + * to be done. This must have been previously created by + * nxtk_openwindow(). + * rect - Describes the rectangular region relative to the toolbar + * sub-window to move + * offset - The offset to move the region. The rectangular region will be + * moved so that the origin is translated by this amount. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_movetoolbar(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *rect, + FAR const struct nxgl_point_s *offset); + +/**************************************************************************** + * Name: nxtk_bitmaptoolbar + * + * Description: + * Copy a rectangular region of a larger image into the rectangle in the + * specified toolbar sub-window. + * + * Input Parameters: + * hfwnd - The sub-window twhose toolbar will receive the bitmap image + * dest - Describes the rectangular region on in the toolbar sub-window + * will receive the bit map. + * src - The start of the source image. + * origin - The origin of the upper, left-most corner of the full bitmap. + * Both dest and origin are in sub-window coordinates, however, the + * origin may lie outside of the sub-window display. + * stride - The width of the full source image in bytes. + * + * Return: + * OK on success; ERROR on failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int nxtk_bitmaptoolbar(NXTKWINDOW hfwnd, + FAR const struct nxgl_rect_s *dest, + FAR const void *src[CONFIG_NX_NPLANES], + FAR const struct nxgl_point_s *origin, + unsigned int stride); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_NX_NXTK_H */ diff --git a/nuttx/include/nuttx/nxflat.h b/nuttx/include/nuttx/nxflat.h new file mode 100644 index 0000000000..b6501522ef --- /dev/null +++ b/nuttx/include/nuttx/nxflat.h @@ -0,0 +1,264 @@ +/**************************************************************************** + * include/nuttx/nxflat.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NXFLAT_H +#define __INCLUDE_NUTTX_NXFLAT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This struct provides a desciption of the currently loaded instantiation + * of an nxflat binary. + */ + +struct nxflat_loadinfo_s +{ + /* Instruction Space (ISpace): This region contains the nxflat file header + * plus everything from the text section. Ideally, will have only one mmap'ed + * text section instance in the system for each module. + */ + + uint32_t ispace; /* Address where hdr/text is loaded */ + uint32_t entryoffs; /* Offset from ispace to entry point */ + uint32_t isize; /* Size of ispace. */ + + /* Data Space (DSpace): This region contains all information that in referenced + * as data (other than the stack which is separately allocated). There will be + * a unique instance of DSpace (and stack) for each instance of a process. + */ + + struct dspace_s *dspace; /* Allocated D-Space (data/bss/etc) */ + uint32_t datasize; /* Size of data segment in dspace */ + uint32_t bsssize; /* Size of bss segment in dspace */ + uint32_t stacksize; /* Size of stack (not allocated) */ + uint32_t dsize; /* Size of dspace (may be large than parts) */ + + /* This is temporary memory where relocation records will be loaded. */ + + uint32_t relocstart; /* Start of array of struct flat_reloc */ + uint16_t reloccount; /* Number of elements in reloc array */ + + /* File descriptors */ + + int filfd; /* Descriptor for the file being loaded */ + + /* This is a copy of the NXFLAT header (still in network order) */ + + struct nxflat_hdr_s header; +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * These are APIs exported by libnxflat (and may be used outside of NuttX): + ****************************************************************************/ + +/*********************************************************************** + * Name: nxflat_verifyheader + * + * Description: + * Given the header from a possible NXFLAT executable, verify that it + * is an NXFLAT executable. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ***********************************************************************/ + +EXTERN int nxflat_verifyheader(const struct nxflat_hdr_s *header); + +/*********************************************************************** + * Name: nxflat_init + * + * Description: + * This function is called to configure the library to process an NXFLAT + * program binary. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ***********************************************************************/ + +EXTERN int nxflat_init(const char *filename, + struct nxflat_loadinfo_s *loadinfo); + +/*********************************************************************** + * Name: nxflat_uninit + * + * Description: + * Releases any resources committed by nxflat_init(). This essentially + * undoes the actions of nxflat_init. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ***********************************************************************/ + +EXTERN int nxflat_uninit(struct nxflat_loadinfo_s *loadinfo); + +/*********************************************************************** + * Name: nxflat_load + * + * Description: + * Loads the binary specified by nxflat_init into memory, mapping + * the I-space executable regions, allocating the D-Space region, + * and inializing the data segment (relocation information is + * temporarily loaded into the BSS region. BSS will be cleared + * by nxflat_bind() after the relocation data has been processed). + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ***********************************************************************/ + +EXTERN int nxflat_load(struct nxflat_loadinfo_s *loadinfo); + +/*********************************************************************** + * Name: nxflat_read + * + * Description: + * Read 'readsize' bytes from the object file at 'offset' + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ***********************************************************************/ + +EXTERN int nxflat_read(struct nxflat_loadinfo_s *loadinfo, char *buffer, + int readsize, int offset); + +/*********************************************************************** + * Name: nxflat_bind + * + * Description: + * Bind the imported symbol names in the loaded module described by + * 'loadinfo' using the exported symbol values provided by 'symtab' + * After binding the module, clear the BSS region (which held the relocation + * data) in preparation for execution. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ***********************************************************************/ + +struct symtab_s; +EXTERN int nxflat_bind(FAR struct nxflat_loadinfo_s *loadinfo, + FAR const struct symtab_s *exports, int nexports); + +/*********************************************************************** + * Name: nxflat_unload + * + * Description: + * This function unloads the object from memory. This essentially + * undoes the actions of nxflat_load. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ***********************************************************************/ + +EXTERN int nxflat_unload(struct nxflat_loadinfo_s *loadinfo); + +/**************************************************************************** + * These are APIs used internally only by NuttX: + ****************************************************************************/ +/*********************************************************************** + * Name: nxflat_initialize + * + * Description: + * NXFLAT support is built unconditionally. However, it order to + * use this binary format, this function must be called during system + * format in order to register the NXFLAT binary format. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ***********************************************************************/ + +EXTERN int nxflat_initialize(void); + +/**************************************************************************** + * Name: nxflat_uninitialize + * + * Description: + * Unregister the NXFLAT binary loader + * + * Returned Value: + * None + * + ****************************************************************************/ + +EXTERN void nxflat_uninitialize(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_NXFLAT_H */ diff --git a/nuttx/include/nuttx/page.h b/nuttx/include/nuttx/page.h new file mode 100644 index 0000000000..2502e16eeb --- /dev/null +++ b/nuttx/include/nuttx/page.h @@ -0,0 +1,467 @@ +/**************************************************************************** + * include/nuttx/page.h + * This file defines interfaces used to support NuttX On-Demand Paging. + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_PAGE_H +#define __INCLUDE_NUTTX_PAGE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +# include +#endif + +#ifdef CONFIG_PAGING + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ +/* CONFIG_PAGING_PAGESIZE - The size of one managed page. This must be a + * value supported by the processor's memory management unit. The + * following may need to be extended to support additional page sizes at + * some point. + */ + +#if CONFIG_PAGING_PAGESIZE == 1024 +# define PAGESIZE 1024 +# define PAGESHIFT 10 +# define PAGEMASK 0x000003ff +#elif CONFIG_PAGING_PAGESIZE == 4096 +# define PAGESIZE 4096 +# define PAGESHIFT 12 +# define PAGEMASK 0x00000fff +#else +# error "Need extended definitions for CONFIG_PAGING_PAGESIZE" +#endif + +/* Alignment macros */ + +#define PG_ALIGNDOWN(addr) ((addr) & ~PAGEMASK) +#define PG_ALIGNUP(addr) (((addr) + PAGEMASK) & ~PAGEMASK) + +/* CONFIG_PAGING_NLOCKED - This is the number of locked pages in the memory + * map. The size of locked address region will then be given by + * PG_LOCKED_SIZE. These values applies to both physical and virtual memory + * regions. + */ + +#define PG_LOCKED_SIZE (CONFIG_PAGING_NLOCKED << PAGESHIFT) + +/* CONFIG_PAGING_LOCKED_P/VBASE - May be defined to determine the base + * address of the locked page regions (lowest in memory). If neither + * are defined, then this logic will be set the bases to CONFIG_DRAM_START + * and CONFIG_DRAM_VSTART (i.e., it assumes that the base address of the + * locked region is at the beginning of RAM). + * + * NOTE: In some architectures, it may be necessary to take some memory + * from the beginning of this region for vectors or for a page table. + * In such cases, either (1) CONFIG_PAGING_LOCKED_P/VBASE might take that + * into consideration to prevent overlapping the locked memory region + * and the system data at the beginning of SRAM, (2) you extend CONFIG_PAGING_NLOCKED + * include these pages at the beginning of memory and map let them be + * mapped read-only. + */ + +#if defined(CONFIG_PAGING_LOCKED_PBASE) && defined(CONFIG_PAGING_LOCKED_VBASE) +# define PG_LOCKED_PBASE CONFIG_PAGING_LOCKED_PBASE +# define PG_LOCKED_VBASE CONFIG_PAGING_LOCKED_VBASE +#else +# define PG_LOCKED_PBASE CONFIG_DRAM_START +# define PG_LOCKED_VBASE CONFIG_DRAM_VSTART +#endif + +#define PG_LOCKED_PEND (PG_LOCKED_PBASE + PG_LOCKED_SIZE) +#define PG_LOCKED_VEND (PG_LOCKED_VBASE + PG_LOCKED_SIZE) + +#if (PG_LOCKED_PBASE & PAGEMASK) != 0 || (PG_LOCKED_VBASE & PAGEMASK) != 0 +# error "Base address of the locked region is not page aligned" +#endif + +/* CONFIG_PAGING_NPPAGED - This is the number of physical pages available to + * support the paged text region. + * CONFIG_PAGING_NVPAGED - This actual size of the paged text region (in + * pages). This is also the number of virtual pages required to support + * the entire paged region. The on-demand paging feature is intended to + * support only the case where the virtual paged text area is much larger + * the available physical pages. Otherwise, why would you enable on-demand + * paging? + */ + +#if CONFIG_PAGING_NPPAGED >= CONFIG_PAGING_NVPAGED +# error "CONFIG_PAGING_NPPAGED must be less than CONFIG_PAGING_NVPAGED" +#endif + +/* The size of physical and virutal paged address regions will then be: */ + +#define PG_PAGED_PSIZE (CONFIG_PAGING_NPPAGED << PAGESHIFT) +#define PG_PAGED_VSIZE (CONFIG_PAGING_NVPAGED << PAGESHIFT) + +/* This positions the paging Read-Only text region. If the configuration + * did not override the default, the paged region will immediately follow + * the locked region. + */ + +#if defined(CONFIG_PAGING_LOCKED_PBASE) && defined(CONFIG_PAGING_LOCKED_VBASE) +# define PG_PAGED_PBASE CONFIG_PAGING_LOCKED_PBASE +# define PG_PAGED_VBASE CONFIG_PAGING_LOCKED_VBASE +#else +# define PG_PAGED_PBASE PG_LOCKED_PEND +# define PG_PAGED_VBASE PG_LOCKED_VEND +#endif + +#define PG_PAGED_PEND (PG_PAGED_PBASE + PG_PAGED_PSIZE) +#define PG_PAGED_VEND (PG_PAGED_VBASE + PG_PAGED_VSIZE) + +/* Size and description of the overall text section. The number of + * pages in the text section is the sum of the number of pages in + * both the locked and paged regions. The base of the text section + * is the base of the locked region. + */ + +#define PG_TEXT_NPPAGES (CONFIG_PAGING_NLOCKED + CONFIG_PAGING_NPPAGED) +#define PG_TEXT_NVPAGES (CONFIG_PAGING_NLOCKED + CONFIG_PAGING_NVPAGED) +#define PG_TEXT_PSIZE (PG_TEXT_NPPAGES << PAGESHIFT) +#define PG_TEXT_VSIZE (PG_TEXT_NVPAGES << PAGESHIFT) +#define PG_TEXT_PBASE PG_LOCKED_PBASE +#define PG_TEXT_VBASE PG_LOCKED_VBASE + +/* CONFIG_PAGING_NDATA - This is the number of data pages in the memory + * map. The data region will extend to the end of RAM unless overridden + * by a setting in the configuration file. + * + * NOTE: In some architectures, it may be necessary to take some memory + * from the end of RAM for page tables or other system usage. The + * configuration settings and linker directives must be cognizant of that: + * CONFIG_PAGING_NDATA should be defined to prevent the data region from + * extending all the way to the end of memory. + */ + +#define PG_RAM_PAGES (CONFIG_DRAM_SIZE >> PAGESHIFT) + +#ifdef CONFIG_PAGING_NDATA +# define PG_DATA_NPAGES CONFIG_PAGING_NDATA +#elif PG_RAM_PAGES > PG_TEXT_NPPAGES +# define PG_DATA_NPAGES (PG_RAM_PAGES - PG_TEXT_NPAGES) +#else +# error "Not enough memory for this page layout" +#endif + +#define PG_DATA_SIZE (PG_DATA_NPAGES << PAGESHIFT) + +/* This positions the Read/Write data region. If the configuration + * did not override the default, the paged region will immediately follow + * the paged region and will extend to the end of memory. + */ + +#if defined(CONFIG_PAGING_DATA_PBASE) && defined(CONFIG_PAGING_DATA_VBASE) +# define PG_DATA_PBASE CONFIG_PAGING_DATA_PBASE +# define PG_DATA_VBASE CONFIG_PAGING_DATA_VBASE +#else +# define PG_DATA_PBASE PG_LOCKED_PEND +# define PG_DATA_VBASE PG_LOCKED_VEND +#endif + +/* CONFIG_PAGING_DEFPRIO - The default, minimum priority of the page fill + * worker thread. The priority of the page fill work thread will be boosted + * boosted dynmically so that it matches the priority of the task on behalf + * of which it peforms the fill. This defines the minimum priority that + * will be used. Default: 50. + * CONFIG_PAGING_STACKSIZE - Defines the size of the allocated stack + * for the page fill worker thread. Default: 1024. + * CONFIG_PAGING_BLOCKINGFILL - The architecture specific up_fillpage() + * function may be blocking or non-blocking. If defined, this setting + * indicates that the up_fillpage() implementation will block until the + * transfer is completed. Default: Undefined (non-blocking). + * CONFIG_PAGING_WORKPERIOD - The page fill worker thread will wake periodically + * even if there is no mapping to do. This selection controls that wake-up + * period (in microseconds). This wake-up a failsafe that will handle any + * cases where a single is lost (that would really be a bug and shouldn't + * happen!) and also supports timeouts for case of non-blocking, asynchronous + * fills (see CONFIG_PAGING_TIMEOUT_TICKS). + * CONFIG_PAGING_TIMEOUT_TICKS - If defined, the implementation will monitor + * the (asynchronous) page fill logic. If the fill takes longer than this + * number if microseconds, then a fatal error will be declared. + * Default: No timeouts monitored. + */ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions -- Provided by common paging logic to architecture- + * specific logic. + ****************************************************************************/ + +/**************************************************************************** + * Name: pg_miss + * + * Description: + * This function is called from architecture-specific memory segmentation + * fault handling logic. This function will perform the following + * operations: + * + * 1) Sanity checking. + * - ASSERT if the currently executing task is the page fill worker + * thread. The page fill worker thread is how the the page fault + * is resolved and all logic associated with the page fill worker + * must be "locked" and always present in memory. + * 2) Block the currently executing task. + * - Call up_block_task() to block the task at the head of the ready- + * to-run list. This should cause an interrupt level context switch + * to the next highest priority task. + * - The blocked task will be marked with state TSTATE_WAIT_PAGEFILL + * and will be retained in the g_waitingforfill prioritized task + * list. + * 3) Boost the page fill worker thread priority. + * - Check the priority of the task at the head of the g_waitingforfill + * list. If the priority of that task is higher than the current + * priority of the page fill worker thread, then boost the priority + * of the page fill worker thread to that priority. + * 4) Signal the page fill worker thread. + * - Is there a page fill pending? If not then signal the worker + * thread to start working on the queued page fill requests. + * + * Input Parameters: + * None - The head of the ready-to-run list is assumed to be task that + * caused the exception. + * + * Returned Value: + * None - Either this function function succeeds or an assertion occurs. + * + * Assumptions: + * - It is assumed that this function is called from the level of an + * exception handler and that all interrupts are disabled. + * - It is assumed that currently executing task (the one at the head of + * the ready-to-run list) is the one that cause the fault. This will + * always be true unless the page fault occurred in an interrupt handler. + * Interrupt handling logic must always be present and "locked" into + * memory. + * - The chip-specific page fault exception handler has already verified + * that the exception did not occur from interrupt/exception handling + * logic. + * - As mentioned above, the task causing the page fault must not be the + * page fill worker thread because that is the only way to complete the + * page fill. + * + * NOTES: + * 1. One way to accomplish this would be a two pass link phase: + * - In the first phase, create a partially linked objected containing + * all interrupt/exception handling logic, the page fill worker thread + * plus all parts of the IDLE thread (which must always be available + * for execution). + * - All of the .text and .rodata sections of this partial link should + * be collected into a single section. + * - The second link would link the partially linked object along with + * the remaining object to produce the final binary. The linker + * script should position the "special" section so that it lies + * in a reserved, "non-swappable" region. + * + ****************************************************************************/ + +EXTERN void pg_miss(void); + +/**************************************************************************** + * Public Functions -- Provided by architecture-specific logic to common + * paging logic. + ****************************************************************************/ + +/**************************************************************************** + * Name: up_checkmapping() + * + * Description: + * The function up_checkmapping() returns an indication if the page fill + * still needs to performed or not. In certain conditions, the page fault + * may occur on several threads and be queued multiple times. This function + * will prevent the same page from be filled multiple times. + * + * Input Parameters: + * tcb - A reference to the task control block of the task that we believe + * needs to have a page fill. Architecture-specific logic can + * retrieve page fault information from the architecture-specific + * context information in this TCB and can consult processor resources + * (page tables or TLBs or ???) to determine if the fill still needs + * to be performed or not. + * + * Returned Value: + * This function will return true if the mapping is in place and false + * if the mapping is still needed. Errors encountered should be + * interpreted as fatal. + * + * Assumptions: + * - This function is called from the normal tasking context (but with + * interrupts disabled). The implementation must take whatever actions + * are necessary to assure that the operation is safe within this + * context. + * + ****************************************************************************/ + +EXTERN bool up_checkmapping(FAR _TCB *tcb); + +/**************************************************************************** + * Name: up_allocpage() + * + * Description: + * This architecture-specific function will set aside page in memory and map + * the page to its correct virtual address. Architecture-specific context + * information saved within the TCB will provide the function with the + * information needed to identify the virtual miss address. + * + * This function will return the allocated physical page address in vpage. + * The size of the underlying physical page is determined by the + * configuration setting CONFIG_PAGING_PAGESIZE. + * + * NOTE 1: This function must always return a page allocation. If all + * available pages are in-use (the typical case), then this function will + * select a page in-use, un-map it, and make it available. + * + * NOTE 2: If an in-use page is un-mapped, it may be necessary to flush the + * instruction cache in some architectures. + * + * NOTE 3: Allocating and filling a page is a two step process. up_allocpage() + * allocates the page, and up_fillpage() fills it with data from some non- + * volatile storage device. This distinction is made because up_allocpage() + * can probably be implemented in board-independent logic whereas up_fillpage() + * probably must be implemented as board-specific logic. + * + * NOTE 4: The initial mapping of vpage should be read-able and write- + * able (but not cached). No special actions will be required of + * up_fillpage() in order to write into this allocated page. + * + * Input Parameters: + * tcb - A reference to the task control block of the task that needs to + * have a page fill. Architecture-specific logic can retrieve page + * fault information from the architecture-specific context + * information in this TCB to perform the mapping. + * + * Returned Value: + * This function will return zero (OK) if the allocation was successful. + * A negated errno value may be returned if an error occurs. All errors, + * however, are fatal. + * + * Assumptions: + * - This function is called from the normal tasking context (but with + * interrupts disabled). The implementation must take whatever actions + * are necessary to assure that the operation is safe within this + * context. + * + ****************************************************************************/ + +EXTERN int up_allocpage(FAR _TCB *tcb, FAR void **vpage); + +/**************************************************************************** + * Name: up_fillpage() + * + * Description: + * After a page is allocated and mapped by up_allocpage(), the actual + * filling of the page with data from the non-volatile, must be performed + * by a separate call to the architecture-specific function, up_fillpage(). + * This function is non-blocking, it will start an asynchronous page fill. + * The common paging logic will provide a callback function, pg_callback, + * that will be called when the page fill is finished (or an error occurs). + * This callback is assumed to occur from an interrupt level when the + * device driver completes the fill operation. + * + * NOTE 1: Allocating and filling a page is a two step process. up_allocpage() + * allocates the page, and up_fillpage() fills it with data from some non- + * volatile storage device. This distinction is made because up_allocpage() + * can probably be implemented in board-independent logic whereas up_fillpage() + * probably must be implemented as board-specific logic. + * + * NOTE 2: The initial mapping of vpage will be read-able, write-able, + * but non-cacheable. No special actions will be required of + * up_fillpage() in order to write into this allocated page. If the + * virtual address maps to a text region, however, this function should + * remap the region so that is is read/execute only. It should be made + * cache-able in any case. + * + * Input Parameters: + * tcb - A reference to the task control block of the task that needs to + * have a page fill. Architecture-specific logic can retrieve page + * fault information from the architecture-specific context + * information in this TCB to perform the fill. + * pg_callbck - The function to be called when the page fill is complete. + * + * Returned Value: + * This function will return zero (OK) if the page fill was successfully + * started (the result of the page fill is passed to the callback function + * as the result argument). A negated errno value may be returned if an + * error occurs. All errors, however, are fatal. + * + * NOTE: -EBUSY has a special meaning. It is used internally to mean that + * the callback function has not executed. Therefore, -EBUSY should + * never be provided in the result argument of pg_callback. + * + * Assumptions: + * - This function is called from the normal tasking context (but + * interrupts siabled). The implementation must take whatever actions + * are necessary to assure that the operation is safe within this context. + * - Upon return, the caller will sleep waiting for the page fill callback + * to occur. The callback function will perform the wakeup. + * + ****************************************************************************/ + +#ifdef CONFIG_PAGING_BLOCKINGFILL +EXTERN int up_fillpage(FAR _TCB *tcb, FAR void *vpage); +#else +typedef void (*up_pgcallback_t)(FAR _TCB *tcb, int result); +EXTERN int up_fillpage(FAR _TCB *tcb, FAR void *vpage, up_pgcallback_t pg_callback); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_PAGING */ +#endif /* __INCLUDE_NUTTX_PAGE_H */ diff --git a/nuttx/include/nuttx/power/battery.h b/nuttx/include/nuttx/power/battery.h new file mode 100644 index 0000000000..5c341789fc --- /dev/null +++ b/nuttx/include/nuttx/power/battery.h @@ -0,0 +1,217 @@ +/**************************************************************************** + * include/nuttx/power/battery.h + * NuttX Battery Interfaces + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_POWER_BATTERY_H +#define __INCLUDE_NUTTX_POWER_BATTERY_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#ifdef CONFIG_BATTERY + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_BATTERY - Upper half battery driver support + * + * Specific, lower-half drivers will have other configuration requirements + * such as: + * + * CONFIG_I2C - I2C support *may* be needed + * CONFIG_I2C_MAX1704X - The MAX1704x driver must be explictly selected. + */ + +/* IOCTL Commands ***********************************************************/ +/* The upper-half battery driver provides a character driver "wrapper" + * around the lower-half battery driver that does all of the real work. + * Since there is no real data transfer to/or from a battery, all of the + * driver interaction is through IOCTIL commands. The IOCTL commands + * supported by the upper-half driver simply provide calls into the the + * lower half as summarized below: + * + * BATIOC_STATE - Return the current state of the battery (see + * enum battery_status_e). + * Input value: A pointer to type int. + * BATIOC_ONLINE - Return 1 if the battery is online; 0 if offline. + * Input value: A pointer to type bool. + * BATIOC_VOLTAGE - Return the current battery voltage. The returned value + * is a fixed preceision number in units of volts. + * Input value: A pointer to type b16_t. + * BATIOC_CAPACITY - Return the current battery capacity or State of Charge + * (SoC). The returned value is a fixed precision percentage of the + * batteries full capacity. + * Input value: A pointer to type b16_t. + */ + +#define BATIOC_STATE _BATIOC(0x0001) +#define BATIOC_ONLINE _BATIOC(0x0002) +#define BATIOC_VOLTAGE _BATIOC(0x0003) +#define BATIOC_CAPACITY _BATIOC(0x0004) + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* Battery status */ + +enum battery_status_e +{ + BATTERY_UNKNOWN = 0, /* Battery state is not known */ + BATTERY_IDLE, /* Not full, not charging, not discharging */ + BATTERY_FULL, /* Full, not discharging */ + BATTERY_CHARGING, /* Not full, charging */ + BATTERY_DISCHARGING /* Probably not full, discharging */ +}; + + /* This structure defines the lower half battery interface */ + +struct battery_dev_s; +struct battery_operations_s +{ + /* Return the current battery state (see enum battery_status_e) */ + + int (*state)(struct battery_dev_s *dev, int *status); + + /* Return true if the batter is online */ + + int (*online)(struct battery_dev_s *dev, bool *status); + + /* Current battery voltage */ + + int (*voltage)(struct battery_dev_s *dev, b16_t *value); + + /* Battery capacity */ + + int (*capacity)(struct battery_dev_s *dev, b16_t *value); +}; + +/* This structure defines the battery driver state structure */ + +struct battery_dev_s +{ + /* Fields required by the upper-half driver */ + + FAR const struct battery_operations_s *ops; /* Battery operations */ + sem_t batsem; /* Enforce mutually exclusive access */ + + /* Data fields specific to the lower-half driver may follow */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +/**************************************************************************** + * Name: battery_register + * + * Description: + * Register a lower half battery driver with the common, upper-half + * battery driver. + * + * Input parameters: + * devpath - The location in the pseudo-filesystem to create the driver. + * Recommended standard is "/dev/bat0", "/dev/bat1", etc. + * dev - An instance of the battery state structure . + * + * Returned value: + * Zero on success or a negated errno value on failure. + * + ****************************************************************************/ + +EXTERN int battery_register(FAR const char *devpath, + FAR struct battery_dev_s *dev); + +/**************************************************************************** + * Name: max1704x_initialize + * + * Description: + * Initialize the MAX1704x battery driver and return an instance of the + * lower_half interface that may be used with battery_register(); + * + * This driver requires: + * + * CONFIG_BATTERY - Upper half battery driver support + * CONFIG_I2C - I2C support + * CONFIG_I2C_MAX1704X - And the driver must be explictly selected. + * CONFIG_I2C_MAX17040 or CONFIG_I2C_MAX17041 - The driver must know which + * chip is on the board in order to scale the voltage correctly. + * + * Input Parameters: + * i2c - An instance of the I2C interface to use to communicate with the MAX1704x + * addr - The I2C address of the MAX1704x (Better be 0x36). + * frequency - The I2C frequency + * + * Returned Value: + * A pointer to the intialized battery driver instance. A NULL pointer + * is returned on a failure to initialize the MAX1704x lower half. + * + ****************************************************************************/ + +#if defined(CONFIG_I2C) && defined(CONFIG_I2C_MAX1704X) +struct i2c_dev_s; /* Forward reference */ + +EXTERN FAR struct battery_dev_s * + max1704x_initialize(FAR struct i2c_dev_s *i2c, uint8_t addr, uint32_t frequency); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_BATTERY */ +#endif /* __INCLUDE_NUTTX_POWER_BATTERY_H */ diff --git a/nuttx/include/nuttx/power/pm.h b/nuttx/include/nuttx/power/pm.h new file mode 100644 index 0000000000..86e23f090e --- /dev/null +++ b/nuttx/include/nuttx/power/pm.h @@ -0,0 +1,486 @@ +/**************************************************************************** + * include/nuttx/power/pm.h + * NuttX Power Management Interfaces + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ +/* Definition of terms. Various "sleep" and low power consumption states + * have various names and are sometimes used in conflicting ways. In the + * PM logic, we will use the following terminology: + * + * NORMAL - The normal, full power operating mode. + * IDLE - This is still basically normal operational mode, the system is, + * however, IDLE and some simple simple steps to reduce power + * consumption provided that they do not interfere with normal + * Operation. Simply dimming the a backlight might be an example + * somethat that would be done when the system is idle. + * STANDBY - Standby is a lower power consumption mode that may involve more + * extensive power management steps such has disabling clocking or + * setting the processor into reduced power consumption modes. In + * this state, the system should still be able to resume normal + * activity almost immediately. + * SLEEP - The lowest power consumption mode. The most drastic power + * reduction measures possible should be taken in this state. It + * may require some time to get back to normal operation from + * SLEEP (some MCUs may even require going through reset). + * + * State changes always proceed from higher to lower power usage: + * + * NORMAL->IDLE->STANDBY->SLEEP + * ^ | | | + * | V V V + * +-------+------+--------+ + */ + +#ifndef __INCLUDE_NUTTX_POWER_PM_H +#define __INCLUDE_NUTTX_POWER_PM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#ifdef CONFIG_PM + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_IDLE_CUSTOM. Some architectures support this definition. This, + * if defined, will allow you replace the default IDLE loop with your + * own, custom idle loop to support board-specific IDLE time power management + */ + +/* Time slices. The power management module collects activity counts in + * time slices. At the end of the time slice, the count accumulated during + * that interval is applied to an averaging algorithm to determine the + * activity level. + * + * CONFIG_PM_SLICEMS provides the duration of that time slice. Default: 100 + * Milliseconds + */ + +#ifndef CONFIG_PM_SLICEMS +# define CONFIG_PM_SLICEMS 100 /* Default is 100 msec */ +#endif + +/* The averaging algorithm is simply: Y = (An*X + SUM(Ai*Yi))/SUM(Aj), where + * i = 1..n-1 and j= 1..n, n is the length of the "memory", Ai is the + * weight applied to each value, and X is the current activity. These weights + * may be negative and a limited to the range of int16_t. + * + * CONFIG_PM_MEMORY provides the memory for the algorithm. Default: 2 + * CONFIG_PM_COEFn provides weight for each sample. Default: 1 + * + * Setting CONFIG_PM_MEMORY=1 disables all smoothing. + */ + +#ifndef CONFIG_PM_MEMORY +# define CONFIG_PM_MEMORY 2 +#endif + +#ifndef CONFIG_PM_MEMORY < 1 +# error "CONFIG_PM_MEMORY must be >= 1" +#endif + +#ifndef CONFIG_PM_COEFN +# define CONFIG_PM_COEFN 1 +#endif + +#if CONFIG_PM_MEMORY > 1 && !defined(CONFIG_PM_COEF1) +# define CONFIG_PM_COEF1 1 +#endif + +#if CONFIG_PM_MEMORY > 2 && !defined(CONFIG_PM_COEF2) +# define CONFIG_PM_COEF2 1 +#endif + +#if CONFIG_PM_MEMORY > 3 && !defined(CONFIG_PM_COEF3) +# define CONFIG_PM_COEF3 1 +#endif + +#if CONFIG_PM_MEMORY > 4 && !defined(CONFIG_PM_COEF4) +# define CONFIG_PM_COEF4 1 +#endif + +#if CONFIG_PM_MEMORY > 5 && !defined(CONFIG_PM_COEF5) +# define CONFIG_PM_COEF5 1 +#endif + +#if CONFIG_PM_MEMORY > 6 +# warning "This logic needs to be extended" +#endif + +/* State changes then occur when the weight activity account crosses + * threshold values for certain periods of time (time slice count). + * + * CONFIG_PM_xxxENTER_THRESH is the threshold value for entering state xxx. + * CONFIG_PM_xxxENTER_COUNT is the count for entering state xxx. + * + * Resuming to normal state, on the other hand, is usually immediate and + * controlled by wakeup conditions established by the platform. The PM + * module only recommends reduced power states. + */ + +#ifndef CONFIG_PM_IDLEENTER_THRESH +# define CONFIG_PM_IDLEENTER_THRESH 1 /* <=1: Essentially no activity */ +#endif + +#ifndef CONFIG_PM_IDLEEXIT_THRESH +# define CONFIG_PM_IDLEEXIT_THRESH 2 /* >=2: Active */ +#endif + +#if CONFIG_PM_IDLEENTER_THRESH >= CONFIG_PM_IDLEEXIT_THRESH +# error "Must have CONFIG_PM_IDLEENTER_THRESH < CONFIG_PM_IDLEEXIT_THRESH +#endif + +#ifndef CONFIG_PM_IDLEENTER_COUNT +# define CONFIG_PM_IDLEENTER_COUNT 30 /* Thirty IDLE slices to enter + * IDLE mode from normal + */ +#endif + +#ifndef CONFIG_PM_STANDBYENTER_THRESH +# define CONFIG_PM_STANDBYENTER_THRESH 1 /* <=1: Essentially no activity */ +#endif + +#ifndef CONFIG_PM_STANDBYEXIT_THRESH +# define CONFIG_PM_STANDBYEXIT_THRESH 2 /* >=2: Active */ +#endif + +#if CONFIG_PM_STANDBYENTER_THRESH >= CONFIG_PM_STANDBYEXIT_THRESH +# error "Must have CONFIG_PM_STANDBYENTER_THRESH < CONFIG_PM_STANDBYEXIT_THRESH +#endif + +#ifndef CONFIG_PM_STANDBYENTER_COUNT +# define CONFIG_PM_STANDBYENTER_COUNT 50 /* Fifty IDLE slices to enter + * STANDBY mode from IDLE + */ +#endif + +#ifndef CONFIG_PM_SLEEPENTER_THRESH +# define CONFIG_PM_SLEEPENTER_THRESH 1 /* <=1: Essentially no activity */ +#endif + +#ifndef CONFIG_PM_SLEEPEXIT_THRESH +# define CONFIG_PM_SLEEPEXIT_THRESH 2 /* >=2: Active */ +#endif + +#if CONFIG_PM_SLEEPENTER_THRESH >= CONFIG_PM_SLEEPEXIT_THRESH +# error "Must have CONFIG_PM_SLEEPENTER_THRESH < CONFIG_PM_SLEEPEXIT_THRESH +#endif + +#ifndef CONFIG_PM_SLEEPENTER_COUNT +# define CONFIG_PM_SLEEPENTER_COUNT 70 /* 70 IDLE slices to enter SLEEP + * mode from STANDBY + */ +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This enumeration provides all power management states. Receipt of the + * state indication is the state transition event. + */ + +enum pm_state_e +{ + PM_NORMAL = 0, /* Normal full power operating mode. If the driver is in + * a reduced power usage mode, it should immediately re- + * initialize for normal operatin. + * + * PM_NORMAL may be followed by PM_IDLE. + */ + PM_IDLE, /* Drivers will receive this state change if it is + * appropriate to enter a simple IDLE power state. This + * would include simple things such as reducing display back- + * lighting. The driver should be ready to resume normal + * activity instantly. + * + * PM_IDLE may be followed by PM_STANDBY or PM_NORMAL. + */ + PM_STANDBY, /* The system is entering standby mode. Standby is a lower + * power consumption mode that may involve more extensive + * power management steps such has disabling clocking or + * setting the processor into reduced power consumption + * modes. In this state, the system should still be able + * to resume normal activity almost immediately. + * + * PM_STANDBY may be followed PM_SLEEP or by PM_NORMAL + */ + PM_SLEEP, /* The system is entering deep sleep mode. The most drastic + * power reduction measures possible should be taken in this + * state. It may require some time to get back to normal + * operation from SLEEP (some MCUs may even require going + * through reset). + * + * PM_SLEEP may be following by PM_NORMAL + */ +}; + +/* This structure contain pointers callback functions in the driver. These + * callback functions can be used to provide power management information + * to the driver. + */ + +struct pm_callback_s +{ + struct sq_entry_s entry; /* Supports a singly linked list */ + + /************************************************************************** + * Name: prepare + * + * Description: + * Request the driver to prepare for a new power state. This is a + * warning that the system is about to enter into a new power state. The + * driver should begin whatever operations that may be required to enter + * power state. The driver may abort the state change mode by returning + * a non-zero value from the callback function + * + * Input Parameters: + * cb - Returned to the driver. The driver version of the callback + * strucure may include additional, driver-specific state + * data at the end of the structure. + * pmstate - Identifies the new PM state + * + * Returned Value: + * 0 (OK) means the event was successfully processed and that the driver + * is prepared for the PM state change. Non-zero means that the driver + * is not prepared to perform the tasks needed achieve this power setting + * and will cause the state change to be aborted. NOTE: The prepare + * method will also be recalled when reverting from lower back to higher + * power consumption modes (say because another driver refused a lower + * power state change). Drivers are not permitted to return non-zero + * values when reverting back to higher power consumption modes! + * + **************************************************************************/ + + int (*prepare)(FAR struct pm_callback_s *cb, enum pm_state_e pmstate); + + /************************************************************************** + * Name: notify + * + * Description: + * Notify the driver of new power state. This callback is called after + * all drivers have had the opportunity to prepare for the new power + * state. + * + * Input Parameters: + * cb - Returned to the driver. The driver version of the callback + * strucure may include additional, driver-specific state + * data at the end of the structure. + * pmstate - Identifies the new PM state + * + * Returned Value: + * None. The driver already agreed to transition to the low power + * consumption state when when it returned OK to the prepare() call. + * At that time it should have made all preprations necessary to enter + * the new state. Now the driver must make the state transition. + * + **************************************************************************/ + + void (*notify)(FAR struct pm_callback_s *cb, enum pm_state_e pmstate); +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +/**************************************************************************** + * Name: pm_initialize + * + * Description: + * This function is called by MCU-specific logic at power-on reset in + * order to provide one-time initialization the power management subystem. + * This function must be called *very* early in the intialization sequence + * *before* any other device drivers are initialized (since they may + * attempt to register with the power management subsystem). + * + * Input parameters: + * None. + * + * Returned value: + * None. + * + ****************************************************************************/ + +EXTERN void pm_initialize(void); + +/**************************************************************************** + * Name: pm_register + * + * Description: + * This function is called by a device driver in order to register to + * receive power management event callbacks. + * + * Input parameters: + * callbacks - An instance of struct pm_callback_s providing the driver + * callback functions. + * + * Returned value: + * Zero (OK) on success; otherwise a negater errno value is returned. + * + ****************************************************************************/ + +EXTERN int pm_register(FAR struct pm_callback_s *callbacks); + +/**************************************************************************** + * Name: pm_activity + * + * Description: + * This function is called by a device driver to indicate that it is + * performing meaningful activities (non-idle). This increment an activty + * count and/or will restart a idle timer and prevent entering reduced + * power states. + * + * Input Parameters: + * priority - Activity priority, range 0-9. Larger values correspond to + * higher priorities. Higher priority activity can prevent the system + * from entering reduced power states for a longer period of time. + * + * As an example, a button press might be higher priority activity because + * it means that the user is actively interacting with the device. + * + * Returned Value: + * None. + * + * Assumptions: + * This function may be called from an interrupt handler (this is the ONLY + * PM function that may be called from an interrupt handler!). + * + ****************************************************************************/ + +EXTERN void pm_activity(int priority); + +/**************************************************************************** + * Name: pm_checkstate + * + * Description: + * This function is called from the MCU-specific IDLE loop to monitor the + * the power management conditions. This function returns the "recommended" + * power management state based on the PM configuration and activity + * reported in the last sampling periods. The power management state is + * not automatically changed, however. The IDLE loop must call + * pm_changestate() in order to make the state change. + * + * These two steps are separated because the plaform-specific IDLE loop may + * have additional situational information that is not available to the + * the PM sub-system. For example, the IDLE loop may know that the + * battery charge level is very low and may force lower power states + * even if there is activity. + * + * NOTE: That these two steps are separated in time and, hence, the IDLE + * loop could be suspended for a long period of time between calling + * pm_checkstate() and pm_changestate(). The IDLE loop may need to make + * these calls atomic by either disabling interrupts until the state change + * is completed. + * + * Input Parameters: + * None + * + * Returned Value: + * The recommended power management state. + * + ****************************************************************************/ + +EXTERN enum pm_state_e pm_checkstate(void); + +/**************************************************************************** + * Name: pm_changestate + * + * Description: + * This function is used to platform-specific power managmeent logic. It + * will announce the power management power management state change to all + * drivers that have registered for power management event callbacks. + * + * Input Parameters: + * newstate - Identifies the new PM state + * + * Returned Value: + * 0 (OK) means that the callback function for all registered drivers + * returned OK (meaning that they accept the state change). Non-zero + * means that one of the drivers refused the state change. In this case, + * the system will revert to the preceding state. + * + * Assumptions: + * It is assumed that interrupts are disabled when this function is + * called. This function is probably called from the IDLE loop... the + * lowest priority task in the system. Changing driver power management + * states may result in renewed system activity and, as a result, can + * suspend the IDLE thread before it completes the entire state change + * unless interrupts are disabled throughout the state change. + * + ****************************************************************************/ + +EXTERN int pm_changestate(enum pm_state_e newstate); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Stubs + ****************************************************************************/ + +#else /* CONFIG_PM */ + +/* Stubbed out versions of all of PM interface functions that may be used to + * avoid so much conditional compilation in driver code when PM is disabled: + */ + +# define pm_initialize() +# define pm_register(cb) (0) +# define pm_activity(prio) +# define pm_checkstate() (0) +# define pm_changestate(state) + +#endif /* CONFIG_PM */ +#endif /* __INCLUDE_NUTTX_POWER_PM_H */ diff --git a/nuttx/include/nuttx/progmem.h b/nuttx/include/nuttx/progmem.h new file mode 100644 index 0000000000..ac5a659407 --- /dev/null +++ b/nuttx/include/nuttx/progmem.h @@ -0,0 +1,199 @@ +/**************************************************************************** + * include/nuttx/progmem.h + * + * Copyright(C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_PROGMEM_H +#define __INCLUDE_NUTTX_PROGMEM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_progmem_npages + * + * Description: + * Return number of pages + * + ****************************************************************************/ + +uint16_t up_progmem_npages(void); + +/**************************************************************************** + * Name: up_progmem_isuniform + * + * Description: + * Is program memory uniform or page size differs? + * + ****************************************************************************/ + +bool up_progmem_isuniform(void); + +/**************************************************************************** + * Name: up_progmem_pagesize + * + * Description: + * Return page size + * + ****************************************************************************/ + +uint16_t up_progmem_pagesize(uint16_t page); + +/**************************************************************************** + * Name: up_progmem_getpage + * + * Description: + * Address to page conversion + * + * Input Parameters: + * addr - Address without flash offet (aligned to page0) + * + * Returned Value: + * Page or negative value on error. The following errors are reported + * (errno is not set!): + * + * EFAULT: On invalid address + * + ****************************************************************************/ + +int up_progmem_getpage(uint32_t addr); + +/**************************************************************************** + * Name: up_progmem_erasepage + * + * Description: + * Erase selected page. + * + * Input Parameters: + * page - + * + * Returned Value: + * Page size or negative value on error. The following errors are reported + * (errno is not set!): + * + * EFAULT: On invalid page + * EIO: On unsuccessful erase + * EROFS: On access to write protected area + * EACCES: Insufficient permissions (read/write protected) + * EPERM: If operation is not permitted due to some other constraints + * (i.e. some internal block is not running etc.) + * + ****************************************************************************/ + +int up_progmem_erasepage(uint16_t page); + +/**************************************************************************** + * Name: up_progmem_ispageerased + * + * Description: + * Checks whether page is erased + * + * Input Parameters: + * page - + * + * Returned Value: + * Returns number of bytes written or negative value on error. If it + * returns zero then complete page is empty (erased). + * + * The following errors are reported (errno is not set!) + * EFAULT: On invalid page + * + ****************************************************************************/ + +int up_progmem_ispageerased(uint16_t page); + +/**************************************************************************** + * Name: up_progmem_write + * + * Description: + * Program data at given address + * + * Note: this function is not limited to single page and nor it requires + * the address be aligned inside the page boundaries. + * + * Input Parameters: + * addr - Address without flash offet (aligned to page0) + * buf - Pointer to buffer + * count - Number of bytes to write * + * + * Returned Value: + * Bytes written or negative value on error. The following errors are + * reported (errno is not set!) + * + * EINVAL: if count is not aligned with the flash boundaries (i.e. + * some MCU's require per half-word or even word access) + * EFAULT: On invalid address + * EIO: On unsuccessful write + * EROFS: On access to write protected area + * EACCES: Insufficient permissions (read/write protected) + * EPERM: If operation is not permitted due to some other constraints + * (i.e. some internal block is not running etc.) + * + ****************************************************************************/ + +int up_progmem_write(uint32_t addr, const void *buf, size_t count); + +/* TODO: Define the following functions and their options: + * - up_progmem_protect() + * - up_progmem_unprotect() + */ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_PROGMEM_H */ diff --git a/nuttx/include/nuttx/pthread.h b/nuttx/include/nuttx/pthread.h new file mode 100644 index 0000000000..2bdb883407 --- /dev/null +++ b/nuttx/include/nuttx/pthread.h @@ -0,0 +1,88 @@ +/**************************************************************************** + * include/nuttx/pthread.h + * Non-standard, NuttX-specific pthread-related declarations. + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_PTHREAD_H +#define __INCLUDE_NUTTX_PTHREAD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Default pthread attribute initializer */ + +#define PTHREAD_ATTR_INITIALIZER \ +{ \ + PTHREAD_STACK_DEFAULT, /* stacksize */ \ + PTHREAD_DEFAULT_PRIORITY, /* priority */ \ + SCHED_RR, /* policy */ \ + PTHREAD_EXPLICIT_SCHED, /* inheritsched */ \ +} + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Default pthread attributes (see sched/pthread_create.c). This global + * can only be shared within the kernel- or within the user- address space. + */ + +EXTERN pthread_attr_t g_default_pthread_attr; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_PTHREAD_H */ diff --git a/nuttx/include/nuttx/pwm.h b/nuttx/include/nuttx/pwm.h new file mode 100644 index 0000000000..69fa4fc4d9 --- /dev/null +++ b/nuttx/include/nuttx/pwm.h @@ -0,0 +1,306 @@ +/**************************************************************************** + * include/nuttx/pwm.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_PWM_H +#define __INCLUDE_NUTTX_PWM_H + +/* For the purposes of this driver, a PWM device is any device that generates + * periodic output pulses s of controlled frequency and pulse width. Such a + * device might be used, for example, to perform pulse-width modulated output or + * frequency/pulse-count modulated output (such as might be needed to control + * a stepper motor). + * + * The PWM driver is split into two parts: + * + * 1) An "upper half", generic driver that provides the comman PWM interface + * to application level code, and + * 2) A "lower half", platform-specific driver that implements the low-level + * timer controls to implement the PWM functionality. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +#include + +#ifdef CONFIG_PWM + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_PWM - Enables because PWM driver support + * CONFIG_PWM_PULSECOUNT - Some hardware will support generation of a fixed + * number of pulses. This might be used, for example to support a stepper + * motor. If the hardware will support a fixed pulse count, then this + * configuration should be set to enable the capability. + * CONFIG_DEBUG_PWM - If enabled (with CONFIG_DEBUG and, optionally, + * CONFIG_DEBUG_VERBOSE), this will generate output that can be use dto + * debug the PWM driver. + */ + +/* IOCTL Commands ***********************************************************/ +/* The PWM module uses a standard character driver framework. However, since + * the PWM driver is a device control interface and not a data transfer + * interface, the majority of the functionality is implemented in driver + * ioctl calls. The PWM ioctl commands are lised below: + * + * PWMIOC_SETCHARACTERISTICS - Set the characteristics of the next pulsed + * output. This command will neither start nor stop the pulsed output. + * It will either setup the configuration that will be used when the + * output is started; or it will change the characteristics of the pulsed + * output on the fly if the timer is already started. This command will + * set the PWM characteristics and return immediately. + * + * ioctl argument: A read-only reference to struct pwm_info_s that provides + * the characteristics of the pulsed output. + * + * PWMIOC_GETCHARACTERISTICS - Get the currently selected characteristics of + * the pulsed output (independent of whether the output is start or stopped). + * + * ioctl argument: A reference to struct pwm_info_s to recevie the + * characteristics of the pulsed output. + * + * PWMIOC_START - Start the pulsed output. The PWMIOC_SETCHARACTERISTICS + * command must have previously been sent. If CONFIG_PWM_PULSECOUNT is + * defined and the pulse count was configured to a non-zero value, then + * this ioctl call will, by default, block until the programmed pulse count + * completes. That default blocking behavior can be overridden by using + * the O_NONBLOCK flag when the PWM driver is opened. + * + * ioctl argument: None + * + * PWMIOC_STOP - Stop the pulsed output. This command will stop the PWM + * and return immediately. + * + * ioctl argument: None + */ + +#define PWMIOC_SETCHARACTERISTICS _PWMIOC(1) +#define PWMIOC_GETCHARACTERISTICS _PWMIOC(2) +#define PWMIOC_START _PWMIOC(3) +#define PWMIOC_STOP _PWMIOC(4) + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* This structure describes the characteristics of the pulsed output */ + +struct pwm_info_s +{ + uint32_t frequency; /* Frequency of the pulse train */ + ub16_t duty; /* Duty of the pulse train, "1"-to-"0" duration. + * Maximum: 65535/65536 (0x0000ffff) + * Minimum: 1/65536 (0x00000001) */ +#ifdef CONFIG_PWM_PULSECOUNT + uint32_t count; /* The number of pulse to generate. 0 means to + * generate an indefinite number of pulses */ +#endif +}; + +/* This structure is a set a callback functions used to call from the upper- + * half, generic PWM driver into lower-half, platform-specific logic that + * supports the low-level timer outputs. + */ + +struct pwm_lowerhalf_s; +struct pwm_ops_s +{ + /* This method is called when the driver is opened. The lower half driver + * should configure and initialize the device so that it is ready for use. + * It should not, however, output pulses until the start method is called. + */ + + CODE int (*setup)(FAR struct pwm_lowerhalf_s *dev); + + /* This method is called when the driver is closed. The lower half driver + * should stop pulsed output, free any resources, disable the timer hardware, and + * put the system into the lowest possible power usage state + */ + + CODE int (*shutdown)(FAR struct pwm_lowerhalf_s *dev); + + /* (Re-)initialize the timer resources and start the pulsed output. The + * start method should return an error if it cannot start the timer with + * the given parameter (frequency, duty, or optionally pulse count) + */ + +#ifdef CONFIG_PWM_PULSECOUNT + CODE int (*start)(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info, + FAR void *handle); +#else + CODE int (*start)(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info); +#endif + + /* Stop the pulsed output and reset the timer resources*/ + + CODE int (*stop)(FAR struct pwm_lowerhalf_s *dev); + + /* Lower-half logic may support platform-specific ioctl commands */ + + CODE int (*ioctl)(FAR struct pwm_lowerhalf_s *dev, + int cmd, unsigned long arg); +}; + +/* This structure is the generic form of state structure used by lower half + * timer driver. This state structure is passed to the pwm driver when the + * driver is initialized. Then, on subsequent callbacks into the lower half + * timer logic, this structure is provided so that the timer logic can + * maintain state information. + * + * Normally that timer logic will have its own, custom state structure + * that is simply cast to struct pwm_lowerhalf_s. In order to perform such casts, + * the initial fields of the custom state structure match the initial fields + * of the following generic PWM state structure. + */ + +struct pwm_lowerhalf_s +{ + /* The first field of this state structure must be a pointer to the PWM + * callback structure: + */ + + FAR const struct pwm_ops_s *ops; + + /* The custom timer state structure may include additional fields after + * the pointer to the PWM callback structure. + */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * "Upper-Half" PWM Driver Interfaces + ****************************************************************************/ +/**************************************************************************** + * Name: pwm_register + * + * Description: + * This function binds an instance of a "lower half" timer driver with the + * "upper half" PWM device and registers that device so that can be used + * by application code. + * + * When this function is called, the "lower half" driver should be in the + * reset state (as if the shutdown() method had already been called). + * + * Input parameters: + * path - The full path to the driver to be registers in the NuttX pseudo- + * filesystem. The recommended convention is to name all PWM drivers + * as "/dev/pwm0", "/dev/pwm1", etc. where the driver path differs only + * in the "minor" number at the end of the device name. + * dev - A pointer to an instance of lower half timer driver. This instance + * is bound to the PWM driver and must persists as long as the driver + * persists. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +EXTERN int pwm_register(FAR const char *path, FAR struct pwm_lowerhalf_s *dev); + +/**************************************************************************** + * Name: pwm_expired + * + * Description: + * If CONFIG_PWM_PULSECOUNT is defined and the pulse count was configured + * to a non-zero value, then the "upper half" driver will wait for the + * pulse count to expire. The sequence of expected events is as follows: + * + * 1. The upper half driver calls the start method, providing the lower + * half driver with the pulse train characteristics. If a fixed + * number of pulses is required, the 'count' value will be nonzero. + * 2. The lower half driver's start() methoc must verify that it can + * support the request pulse train (frequency, duty, AND pulse count). + * It it cannot, it should return an error. If the pulse count is + * non-zero, it should set up the hardware for that number of pulses + * and return success. NOTE: That is CONFIG_PWM_PULSECOUNT is + * defined, the start() method receives an additional parameter + * that must be used in this callback. + * 3. When the start() method returns success, the upper half driver + * will "sleep" until the pwm_expired method is called. + * 4. When the lower half detects that the pulse count has expired + * (probably through an interrupt), it must call the pwm_expired + * interface using the handle that was previously passed to the + * start() method + * + * Input parameters: + * handle - This is the handle that was provided to the lower-half + * start() method. + * + * Returned Value: + * None + * + * Assumptions: + * This function may be called from an interrupt handler. + * + ****************************************************************************/ + +#ifdef CONFIG_PWM_PULSECOUNT +EXTERN void pwm_expired(FAR void *handle); +#endif + +/**************************************************************************** + * Platform-Independent "Lower-Half" PWM Driver Interfaces + ****************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_PWM */ +#endif /* __INCLUDE_NUTTX_PWM_H */ diff --git a/nuttx/include/nuttx/ramdisk.h b/nuttx/include/nuttx/ramdisk.h new file mode 100644 index 0000000000..7d4017c119 --- /dev/null +++ b/nuttx/include/nuttx/ramdisk.h @@ -0,0 +1,99 @@ +/**************************************************************************** + * include/nuttx/ramdisk.h + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_RAMDISK_H +#define __INCLUDE_NUTTX_RAMDISK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: ramdisk_register or romdisk_register + * + * Description: + * Non-standard function to register a ramdisk or a romdisk + * + * Input Parmeters: + * minor: Selects suffix of device named /dev/ramN, N={1,2,3...} + * nsectors: Number of sectors on device + * sectize: The size of one sector + * writeenabled: true: can write to ram disk + * buffer: RAM disk backup memory + * + * Returned Valued: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_FS_WRITABLE +EXTERN int ramdisk_register(int minor, FAR uint8_t *buffer, uint32_t nsectors, + uint16_t sectize, bool writeenabled); +#define romdisk_register(m,b,n,s) ramdisk_register(m,b,n,s,0) +#else +EXTERN int romdisk_register(int minor, FAR uint8_t *buffer, uint32_t nsectors, + uint16_t sectize); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_RAMDISK_H */ diff --git a/nuttx/include/nuttx/ramlog.h b/nuttx/include/nuttx/ramlog.h new file mode 100644 index 0000000000..7831ea509c --- /dev/null +++ b/nuttx/include/nuttx/ramlog.h @@ -0,0 +1,208 @@ +/**************************************************************************** + * include/nuttx/ramlog.h + * The RAM logging driver + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ +/* The RAM logging driver is a driver that was intended to support debugging + * output (syslogging) when the normal serial output is not available. For + * example, if you are using a telnet or USB serial console, the debug + * output will get lost. + * + * The RAM logging driver is similar to a pipe in that it saves the + * debugging output in a FIFO in RAM. It differs from a pipe in numerous + * details as needed to support logging. + * + * This driver is built when CONFIG_RAMLOG is defined in the Nuttx + * configuration. + */ + +#ifndef __INCLUDE_NUTTX_RAMLOG_H +#define __INCLUDE_NUTTX_RAMLOG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifdef CONFIG_RAMLOG + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_RAMLOG - Enables the RAM logging feature + * CONFIG_RAMLOG_CONSOLE - Use the RAM logging device as a system console. + * If this feature is enabled (along with CONFIG_DEV_CONSOLE), then all + * console output will be re-directed to a circular buffer in RAM. This + * is useful, for example, if the only console is a Telnet console. Then + * in that case, console output from non-Telnet threads will go to the + * circular buffer and can be viewed using the NSH 'dmesg' command. + * CONFIG_RAMLOG_SYSLOG - Use the RAM logging device for the syslogging + * interface. If this feature is enabled (along with CONFIG_SYSLOG), + * then all debug output (only) will be re-directed to the circular + * buffer in RAM. This RAM log can be view from NSH using the 'dmesg' + * command. NOTE: Unlike the limited, generic character driver SYSLOG + * device, the RAMLOG *can* be used to generate debug output from interrupt + * level handlers. + * CONFIG_RAMLOG_NPOLLWAITERS - The number of threads than can be waiting + * for this driver on poll(). Default: 4 + * + * If CONFIG_RAMLOG_CONSOLE or CONFIG_RAMLOG_SYSLOG is selected, then the + * following may also be provided: + * + * CONFIG_RAMLOG_CONSOLE_BUFSIZE - Size of the console RAM log. Default: 1024 + */ + +#ifndef CONFIG_DEV_CONSOLE +# undef CONFIG_RAMLOG_CONSOLE +#endif + +#ifndef CONFIG_SYSLOG +# undef CONFIG_RAMLOG_SYSLOG +#endif + +#if defined(CONFIG_RAMLOG_SYSLOG) && !defined(CONFIG_SYSLOG_DEVPATH) +# define CONFIG_SYSLOG_DEVPATH "/dev/ramlog" +#endif + +#ifndef CONFIG_RAMLOG_NPOLLWAITERS +# define CONFIG_RAMLOG_NPOLLWAITERS 4 +#endif + +#ifndef CONFIG_SYSLOG +# undef CONFIG_RAMLOG_SYSLOG +#endif + +#ifndef CONFIG_RAMLOG_CONSOLE_BUFSIZE +# define CONFIG_RAMLOG_CONSOLE_BUFSIZE 1024 +#endif + +/* The normal behavior of the RAM log when used as a SYSLOG is to return + * end-of-file if there is no data in the RAM log (rather than blocking until + * data is available). That allows you to 'cat' the SYSLOG with no ill + * consequences. + */ + +#ifdef CONFIG_SYSLOG +# undef CONFIG_RAMLOG_NONBLOCKING +# define CONFIG_RAMLOG_NONBLOCKING 1 +#endif + +/* When used as a console or syslogging device, the RAM log will pre-pend + * line-feeds with carriage returns. + */ + +#if defined(CONFIG_RAMLOG_CONSOLE) || defined(CONFIG_RAMLOG_SYSLOG) +# undef CONFIG_RAMLOG_CRLF +# define CONFIG_RAMLOG_CRLF 1 +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +/**************************************************************************** + * Name: ramlog_register + * + * Description: + * Create the RAM logging device and register it at the specified path. + * Mostly likely this path will be /dev/console. + * + * This interface is not normally used but can be made available is + * someone just wants to tinker with the RAM log as a generic character + * device. Normally both CONFIG_RAMLOG_CONSOLE and CONFIG_RAMLOG_SYSLOG + * would be set (to capture all output in the log) -OR- just + * CONFIG_RAMLOG_SYSLOG would be set to capture debug output only + * in the log. + * + ****************************************************************************/ + +#if !defined(CONFIG_RAMLOG_CONSOLE) && !defined(CONFIG_RAMLOG_SYSLOG) +EXTERN int ramlog_register(FAR const char *devpath, FAR char *buffer, + size_t buflen); +#endif + +/**************************************************************************** + * Name: ramlog_consoleinit + * + * Description: + * Create the RAM logging device and register it at the specified path. + * Mostly likely this path will be /dev/console. + * + * If CONFIG_RAMLOG_SYSLOG is also defined, then the same RAM logging + * device is also registered at CONFIG_SYSLOG_DEVPATH + * + ****************************************************************************/ + +#ifdef CONFIG_RAMLOG_CONSOLE +EXTERN int ramlog_consoleinit(void); +#endif + +/**************************************************************************** + * Name: ramlog_sysloginit + * + * Description: + * Create the RAM logging device and register it at the specified path. + * Mostly likely this path will be CONFIG_SYSLOG_DEVPATH + * + * If CONFIG_RAMLOG_CONSOLE is also defined, then this functionality is + * performed when ramlog_consoleinit() is called. + * + ****************************************************************************/ + +#ifdef CONFIG_RAMLOG_SYSLOG +EXTERN int ramlog_sysloginit(void); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_RAMLOG */ +#endif /* __INCLUDE_NUTTX_RAMLOG_H */ diff --git a/nuttx/include/nuttx/regex.h b/nuttx/include/nuttx/regex.h new file mode 100644 index 0000000000..030823a6f6 --- /dev/null +++ b/nuttx/include/nuttx/regex.h @@ -0,0 +1,82 @@ +/**************************************************************************** + * include/nuttx/regex.h + * Non-standard, pattern-matching APIs available in lib/. + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_REGEX_H +#define __INCLUDE_NUTTX_REGEX_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: match + * + * Description: + * Simple shell-style filename pattern matcher written by Jef Poskanzer + * (See copyright notice in lib/lib_match.c). This pattern matcher only + * handles '?', '*' and '**', and multiple patterns separated by '|'. + * + * Returned Value: + * Returns 1 (match) or 0 (no-match). + * + ****************************************************************************/ + +EXTERN int match(const char *pattern, const char *string); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_REGEX_H */ diff --git a/nuttx/include/nuttx/rgbcolors.h b/nuttx/include/nuttx/rgbcolors.h new file mode 100644 index 0000000000..0f15d8158c --- /dev/null +++ b/nuttx/include/nuttx/rgbcolors.h @@ -0,0 +1,293 @@ +/**************************************************************************** + * include/nuttx/rgbcolors.h + * User-friendly RGB color definitions + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_RGBCOLOR_H +#define __INCLUDE_NUTTX_RGBCOLOR_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Color Creation and Conversion Macros *************************************/ +/* This macro creates RGB24 from 8:8:8 RGB */ + +#define RGBTO24(r,g,b) \ + ((uint32_t)((r) & 0xff) << 16 | (uint32_t)((g) & 0xff) << 8 | (uint32_t)((b) & 0xff)) + +/* And these macros perform the inverse transformation */ + +#define RBG24RED(rgb) (((rgb) >> 16) & 0xff) +#define RBG24GREEN(rgb) (((rgb) >> 8) & 0xff) +#define RBG24BLUE(rgb) ( (rgb) & 0xff) + +/* This macro creates RGB16 (5:6:5) from 8:8:8 RGB: + * + * R[7:3] -> RGB[15:11] + * G[7:2] -> RGB[10:5] + * B[7:3] -> RGB[4:0] + */ + +#define RGBTO16(r,g,b) \ + ((((uint16_t)(r) << 8) & 0xf800) | (((uint16_t)(g) << 3) & 0x07e0) | (((uint16_t)(b) >> 3) & 0x001f)) + +/* And these macros perform the inverse transformation */ + +#define RBG16RED(rgb) (((rgb) >> 8) & 0xf8) +#define RBG16GREEN(rgb) (((rgb) >> 3) & 0xfc) +#define RBG16BLUE(rgb) (((rgb) << 3) & 0xf8) + +/* This macro creates RGB8 (3:3:2) from 8:8:8 RGB */ + +#define RGBTO8(r,g,b) \ + ((((uint8_t)(r) << 5) & 0xe0) | (((uint8_t)(g) << 2) & 0x1c) | ((uint8_t)(b) & 0x03)) + +/* And these macros perform the inverse transformation */ + +#define RBG8RED(rgb) ( (rgb) & 0xe0) +#define RBG8GREEN(rgb) (((rgb) << 3) & 0xe0) +#define RBG8BLUE(rgb) (((rgb) << 6) & 0xc0) + +/* This macro converts RGB24 (8:8:8) to RGB16 (5:6:5): + * + * 00000000 RRRRRRRR BBBBBBBB GGGGGGGG -> RRRRRBBB BBBGGGGG + */ + +#define RGB24TO16(rgb24) \ + (((rgb24 >> 8) & 0xf800) | ((rgb24 >> 5) & 0x07e0) | ((rgb24 >> 3) & 0x001f)) + +/* This macro converts RGB16 (5:6:5) to RGB24 (8:8:8): + * + * RRRRRBBB BBBGGGGG -> 00000000 RRRRRRRR BBBBBBBB GGGGGGGG + */ + +#define RGB16TO24(rgb16) \ + (((rgb16 & 0xf800) << 8) | ((rgb16 & 0x07e0) << 5) | ((rgb16 & 0x001f) << 3)) + +/* Standard Color Definitions ***********************************************/ +/* RGB24-888: 00000000 RRRRRRRR GGGGGGGG BBBBBBBB */ + +#define RGB24_BLACK 0x00000000 +#define RGB24_WHITE 0x00ffffff + +#define RGB24_BLUE 0x000000ff +#define RGB24_GREEN 0x0000ff00 +#define RGB24_RED 0x00ff0000 + +#define RGB24_NAVY 0x00000080 +#define RGB24_DARKBLUE 0x0000008b +#define RGB24_DARKGREEN 0x00006400 +#define RGB24_DARKCYAN 0x00008b8b +#define RGB24_CYAN 0x0000ffff +#define RGB24_TURQUOISE 0x0040e0d0 +#define RGB24_INDIGO 0x004b0082 +#define RGB24_DARKRED 0x00800000 +#define RGB24_OLIVE 0x00808000 +#define RGB24_GRAY 0x00808080 +#define RGB24_SKYBLUE 0x0087ceeb +#define RGB24_BLUEVIOLET 0x008a2be2 +#define RGB24_LIGHTGREEN 0x0090ee90 +#define RGB24_DARKVIOLET 0x009400d3 +#define RGB24_YELLOWGREEN 0x009acd32 +#define RGB24_BROWN 0x00a52a2a +#define RGB24_DARKGRAY 0x00a9a9a9 +#define RGB24_SIENNA 0x00a0522d +#define RGB24_LIGHTBLUE 0x00add8e6 +#define RGB24_GREENYELLOW 0x00adff2f +#define RGB24_SILVER 0x00c0c0c0 +#define RGB24_LIGHTGREY 0x00d3d3d3 +#define RGB24_LIGHTCYAN 0x00e0ffff +#define RGB24_VIOLET 0x00ee82ee +#define RGB24_AZUR 0x00f0ffff +#define RGB24_BEIGE 0x00f5f5dc +#define RGB24_MAGENTA 0x00ff00ff +#define RGB24_TOMATO 0x00ff6347 +#define RGB24_GOLD 0x00ffd700 +#define RGB24_ORANGE 0x00ffa500 +#define RGB24_SNOW 0x00fffafa +#define RGB24_YELLOW 0x00ffff00 + +/* RGB16-565: RRRRRGGG GGGBBBBB */ + +#define RGB16_BLACK 0x0000 +#define RGB16_WHITE 0xffff + +#define RGB16_BLUE 0x001f +#define RGB16_GREEN 0x07e0 +#define RGB16_RED 0xf800 + +#define RGB16_NAVY 0x0010 +#define RGB16_DARKBLUE 0x0011 +#define RGB16_DARKGREEN 0x0320 +#define RGB16_DARKCYAN 0x0451 +#define RGB16_CYAN 0x07ff +#define RGB16_TURQUOISE 0x471a +#define RGB16_INDIGO 0x4810 +#define RGB16_DARKRED 0x8000 +#define RGB16_OLIVE 0x8400 +#define RGB16_GRAY 0x8410 +#define RGB16_SKYBLUE 0x867d +#define RGB16_BLUEVIOLET 0x895c +#define RGB16_LIGHTGREEN 0x9772 +#define RGB16_DARKVIOLET 0x901a +#define RGB16_YELLOWGREEN 0x9e66 +#define RGB16_BROWN 0xa145 +#define RGB16_DARKGRAY 0xad55 +#define RGB16_SIENNA 0xa285 +#define RGB16_LIGHTBLUE 0xaedc +#define RGB16_GREENYELLOW 0xafe5 +#define RGB16_SILVER 0xc618 +#define RGB16_LIGHTGREY 0xd69a +#define RGB16_LIGHTCYAN 0xe7ff +#define RGB16_VIOLET 0xec1d +#define RGB16_AZUR 0xf7ff +#define RGB16_BEIGE 0xf7bb +#define RGB16_MAGENTA 0xf81f +#define RGB16_TOMATO 0xfb08 +#define RGB16_GOLD 0xfea0 +#define RGB16_ORANGE 0xfd20 +#define RGB16_SNOW 0xffdf +#define RGB16_YELLOW 0xffe0 + +/* RGB12-444: RRRR GGGGBBBB */ + +#define RGB12_BLACK 0x0000 +#define RGB12_WHITE 0x0fff + +#define RGB12_BLUE 0x000f +#define RGB12_GREEN 0x00f0 +#define RGB12_RED 0x0f00 + +#define RGB12_NAVY 0x0008 +#define RGB12_DARKBLUE 0x0009 +#define RGB12_DARKGREEN 0x0060 +#define RGB12_DARKCYAN 0x0099 +#define RGB12_CYAN 0x00ff +#define RGB12_TURQUOISE 0x04ed +#define RGB12_INDIGO 0x0508 +#define RGB12_DARKRED 0x0800 +#define RGB12_OLIVE 0x0880 +#define RGB12_GRAY 0x0888 +#define RGB12_SKYBLUE 0x08df +#define RGB12_BLUEVIOLET 0x093e +#define RGB12_LIGHTGREEN 0x09f9 +#define RGB12_DARKVIOLET 0x090d +#define RGB12_YELLOWGREEN 0x0ad3 +#define RGB12_BROWN 0x0a33 +#define RGB12_DARKGRAY 0x0bbb +#define RGB12_SIENNA 0x0a53 +#define RGB12_LIGHTBLUE 0x0bee +#define RGB12_GREENYELLOW 0x0bf3 +#define RGB12_SILVER 0x0ccc +#define RGB12_LIGHTGREY 0x0ddd +#define RGB12_LIGHTCYAN 0x0eff +#define RGB12_VIOLET 0x0f8f +#define RGB12_AZUR 0x0fff +#define RGB12_BEIGE 0x0ffe +#define RGB12_MAGENTA 0x0f0f +#define RGB12_TOMATO 0x0f64 +#define RGB12_GOLD 0x0fd0 +#define RGB12_ORANGE 0x0fa0 +#define RGB12_SNOW 0x0fff +#define RGB12_YELLOW 0x0ff0 + +/* RGB8-332: RRRGGGBB (really not enough color resolution for the following) */ + +#define RGB8_BLACK 0x00 +#define RGB8_WHITE 0xff + +#define RGB8_BLUE 0x03 +#define RGB8_GREEN 0x1c +#define RGB8_RED 0xe0 +#define RGB8_NAVY 0x02 +#define RGB8_DARKBLUE 0x02 +#define RGB8_DARKGREEN 0x0c +#define RGB8_DARKCYAN 0x16 +#define RGB8_CYAN 0x1f +#define RGB8_TURQUOISE 0x5f +#define RGB8_INDIGO 0x62 +#define RGB8_DARKRED 0x80 +#define RGB8_OLIVE 0x90 +#define RGB8_GRAY 0x92 +#define RGB8_SKYBLUE 0x9f +#define RGB8_BLUEVIOLET 0xab +#define RGB8_LIGHTGREEN 0xbe +#define RGB8_DARKVIOLET 0x93 +#define RGB8_YELLOWGREEN 0x9d +#define RGB8_BROWN 0xa9 +#define RGB8_DARKGRAY 0xdb +#define RGB8_SIENNA 0xa9 +#define RGB8_LIGHTBLUE 0xdf +#define RGB8_GREENYELLOW 0xdd +#define RGB8_SILVER 0xd9 +#define RGB8_LIGHTGREY 0xd9 +#define RGB8_LIGHTCYAN 0xff +#define RGB8_VIOLET 0xf3 +#define RGB8_AZUR 0xff +#define RGB8_BEIGE 0xff +#define RGB8_MAGENTA 0xed +#define RGB8_TOMATO 0xfc +#define RGB8_GOLD 0xfc +#define RGB8_ORANGE 0xf8 +#define RGB8_SNOW 0xff +#define RGB8_YELLOW 0xfc + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __INCLUDE_NUTTX_RGBCOLOR_H */ diff --git a/nuttx/include/nuttx/rtc.h b/nuttx/include/nuttx/rtc.h new file mode 100644 index 0000000000..85dea1b4db --- /dev/null +++ b/nuttx/include/nuttx/rtc.h @@ -0,0 +1,283 @@ +/**************************************************************************** + * include/nuttx/rtc.h + * + * Copyright(C) 2011 Uros Platise. All rights reserved. + * Author: Uros Platise + * + * With extensions, modifications by: + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregroy Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_RTC_H +#define __INCLUDE_NUTTX_RTC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_RTC - Enables general support for a hardware RTC. Specific + * architectures may require other specific settings. + * + * CONFIG_RTC_DATETIME - There are two general types of RTC: (1) A simple + * battery backed counter that keeps the time when power is down, and (2) + * A full date / time RTC the provides the date and time information, often + * in BCD format. If CONFIG_RTC_DATETIME is selected, it specifies this + * second kind of RTC. In this case, the RTC is used to "seed" the normal + * NuttX timer and the NuttX system timer provides for higher resoution + * time. + * + * CONFIG_RTC_HIRES - If CONFIG_RTC_DATETIME not selected, then the simple, + * battery backed counter is used. There are two different implementations + * of such simple counters based on the time resolution of the counter: + * The typical RTC keeps time to resolution of 1 second, usually + * supporting a 32-bit time_t value. In this case, the RTC is used to + * "seed" the normal NuttX timer and the NuttX timer provides for higher + * resoution time. + * + * If CONFIG_RTC_HIRES is enabled in the NuttX configuration, then the + * RTC provides higher resolution time and completely replaces the system + * timer for purpose of date and time. + * + * CONFIG_RTC_FREQUENCY - If CONFIG_RTC_HIRES is defined, then the frequency + * of the high resolution RTC must be provided. If CONFIG_RTC_HIRES is + * not defined, CONFIG_RTC_FREQUENCY is assumed to be one. + * + * CONFIG_RTC_ALARM - Enable if the RTC hardware supports setting of an + * alarm. A callback function will be executed when the alarm goes off + */ + +#ifdef CONFIG_RTC_HIRES +# ifdef CONFIG_RTC_DATETIME +# error "CONFIG_RTC_HIRES and CONFIG_RTC_DATETIME are both defined" +# endif +# ifndef CONFIG_RTC_FREQUENCY +# error "CONFIG_RTC_FREQUENCY is required for CONFIG_RTC_HIRES" +# endif +#else +# ifndef CONFIG_RTC_FREQUENCY +# define CONFIG_RTC_FREQUENCY 1 +# endif +# if CONFIG_RTC_FREQUENCY != 1 +# error "The low resolution RTC must have frequency 1Hz" +# endif +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The form of an alarm callback */ + +typedef CODE void (*alarmcb_t)(void); + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* Variable determines the state of the RTC module. + * + * After initialization value is set to 'true' if RTC starts successfully. + * The value can be changed to false also during operation if RTC for + * some reason fails. + */ + +extern volatile bool g_rtc_enabled; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Name: up_rtcinitialize + * + * Description: + * Initialize the hardware RTC per the selected configuration. This function is + * called once during the OS initialization sequence + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +EXTERN int up_rtcinitialize(void); + +/************************************************************************************ + * Name: up_rtc_time + * + * Description: + * Get the current time in seconds. This is similar to the standard time() + * function. This interface is only required if the low-resolution RTC/counter + * hardware implementation selected. It is only used by the RTOS during + * intialization to set up the system time when CONFIG_RTC is set but neither + * CONFIG_RTC_HIRES nor CONFIG_RTC_DATETIME are set. + * + * Input Parameters: + * None + * + * Returned Value: + * The current time in seconds + * + ************************************************************************************/ + +#ifndef CONFIG_RTC_HIRES +EXTERN time_t up_rtc_time(void); +#endif + +/************************************************************************************ + * Name: up_rtc_gettime + * + * Description: + * Get the current time from the high resolution RTC clock/counter. This interface + * is only supported by the high-resolution RTC/counter hardware implementation. + * It is used to replace the system timer. + * + * Input Parameters: + * tp - The location to return the high resolution time value. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +#ifdef CONFIG_RTC_HIRES +EXTERN int up_rtc_gettime(FAR struct timespec *tp); +#endif + +/************************************************************************************ + * Name: up_rtc_getdatetime + * + * Description: + * Get the current date and time from the date/time RTC. This interface + * is only supported by the date/time RTC hardware implementation. + * It is used to replace the system timer. It is only used by the RTOS during + * intialization to set up the system time when CONFIG_RTC and CONFIG_RTC_DATETIME + * are selected (and CONFIG_RTC_HIRES is not). + * + * NOTE: Some date/time RTC hardware is capability of sub-second accuracy. That + * sub-second accuracy is lost in this interface. However, since the system time + * is reinitialized on each power-up/reset, there will be no timing inaccuracy in + * the long run. + * + * Input Parameters: + * tp - The location to return the high resolution time value. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +#ifdef CONFIG_RTC_DATETIME +EXTERN int up_rtc_getdatetime(FAR struct tm *tp); +#endif + +/************************************************************************************ + * Name: up_rtc_settime + * + * Description: + * Set the RTC to the provided time. All RTC implementations must be able to + * set their time based on a standard timespec. + * + * Input Parameters: + * tp - the time to use + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +EXTERN int up_rtc_settime(FAR const struct timespec *tp); + +/************************************************************************************ + * Name: up_rtc_setalarm + * + * Description: + * Set up an alarm. + * + * Input Parameters: + * tp - the time to set the alarm + * callback - the function to call when the alarm expires. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +EXTERN int up_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback); +#endif + +/************************************************************************************ + * Name: up_rtc_cancelalarm + * + * Description: + * Cancel a pending alarm alarm + * + * Input Parameters: + * none + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +EXTERN int up_rtc_cancelalarm(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_RTC_H */ diff --git a/nuttx/include/nuttx/rwbuffer.h b/nuttx/include/nuttx/rwbuffer.h new file mode 100644 index 0000000000..eb7861872d --- /dev/null +++ b/nuttx/include/nuttx/rwbuffer.h @@ -0,0 +1,192 @@ +/**************************************************************************** + * include/nuttx/rwbuffer.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_RWBUFFER_H +#define __INCLUDE_NUTTX_RWBUFFER_H + +/********************************************************************** + * Included Files + **********************************************************************/ + +#include + +#include +#include +#include +#include + +#if defined(CONFIG_FS_WRITEBUFFER) || defined(CONFIG_FS_READAHEAD) + +/********************************************************************** + * Pre-processor Definitions + **********************************************************************/ + +/********************************************************************** + * Public Types + **********************************************************************/ + +/* Data transfer callouts. These must be provided by the block driver + * logic in order to flush the write buffer when appropriate or to + * reload the read-ahead buffer, when appropriate. + */ + +typedef ssize_t (*rwbreload_t)(FAR void *dev, FAR uint8_t *buffer, + off_t startblock, size_t nblocks); +typedef ssize_t (*rwbflush_t)(FAR void *dev, FAR const uint8_t *buffer, + off_t startblock, size_t nblocks); + +/* This structure holds the state of the buffers. In typical usage, + * an instance of this structure is declared within each block driver + * status structure like: + * + * struct foo_dev_s + * { + * ... + * struct rwbuffer_s rwbuffer; + * ... + * }; + * + * Note that this supports buffering for multiple block devices or for + * multiple instances of same block device, because each rwbuffer instance + * supports independent buffering. + * + * A reference to the struct rwbuffer_s instance is then passed to each + * interface like: + * + * struct foo_dev_s *priv; + * ... + * ... [Setup blocksize, nblocks, dev, wrmaxblocks, wrflush, + * rhmaxblocks, rhreload] ... + * ret = rwb_initialize(&priv->rwbuffer); + */ + +struct rwbuffer_s +{ + /********************************************************************/ + /* These values must be provided by the user prior to calling + * rwb_initialize() + */ + + /* Supported geometry */ + + uint16_t blocksize; /* The size of one block */ + size_t nblocks; /* The total number blocks supported */ + FAR void *dev; /* Device state passed to callout functions */ + + /* Write buffer setup. If CONFIG_FS_WRITEBUFFER is defined, but you + * want read-ahead-only operation, (1) set wrmaxblocks to zero and do + * not use rwb_write(). + */ + +#ifdef CONFIG_FS_WRITEBUFFER + uint16_t wrmaxblocks; /* The number of blocks to buffer in memory */ + rwbflush_t wrflush; /* Callout to flush the write buffer */ +#endif + + /* Read-ahead buffer setup. If CONFIG_FS_READAHEAD is defined but you + * want write-buffer-only operation, then (1) set rhmaxblocks to zero and + * do not use rwb_read(). + */ + +#ifdef CONFIG_FS_READAHEAD + uint16_t rhmaxblocks; /* The number of blocks to buffer in memory */ + rwbreload_t rhreload; /* Callout to reload the read-ahead buffer */ +#endif + + /********************************************************************/ + /* The user should never modify any of the remaing fields */ + + /* This is the state of the write buffer */ + +#ifdef CONFIG_FS_WRITEBUFFER + sem_t wrsem; /* Enforces exclusive access to the write buffer */ + struct work_s work; /* Delayed work to flush buffer after adelay with no activity */ + uint8_t *wrbuffer; /* Allocated write buffer */ + uint16_t wrnblocks; /* Number of blocks in write buffer */ + off_t wrblockstart; /* First block in write buffer */ + off_t wrexpectedblock; /* Next block expected */ +#endif + + /* This is the state of the read-ahead buffer */ + +#ifdef CONFIG_FS_READAHEAD + sem_t rhsem; /* Enforces exclusive access to the write buffer */ + uint8_t *rhbuffer; /* Allocated read-ahead buffer */ + uint16_t rhnblocks; /* Number of blocks in read-ahead buffer */ + off_t rhblockstart; /* First block in read-ahead buffer */ +#endif +}; + +/********************************************************************** + * Global Variables + **********************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN EXTERN "C" +EXTERN "C" { +#else +#define EXTERN extern +#endif + +/********************************************************************** + * Global Function Prototypes + **********************************************************************/ + +/* Buffer initialization */ + +EXTERN int rwb_initialize(FAR struct rwbuffer_s *rwb); +EXTERN void rwb_uninitialize(FAR struct rwbuffer_s *rwb); + +/* Buffer transfers */ + +EXTERN ssize_t rwb_read(FAR struct rwbuffer_s *rwb, off_t startblock, + size_t blockcount, FAR uint8_t *rdbuffer); +EXTERN ssize_t rwb_write(FAR struct rwbuffer_s *rwb, + off_t startblock, size_t blockcount, + FAR const uint8_t *wrbuffer); +EXTERN int rwb_mediaremoved(FAR struct rwbuffer_s *rwb); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* CONFIG_FS_WRITEBUFFER || CONFIG_READAHEAD_BUFFER */ +#endif /* __INCLUDE_NUTTX_RWBUFFER_H */ diff --git a/nuttx/include/nuttx/sched.h b/nuttx/include/nuttx/sched.h new file mode 100644 index 0000000000..241af6210c --- /dev/null +++ b/nuttx/include/nuttx/sched.h @@ -0,0 +1,382 @@ +/******************************************************************************** + * include/nuttx/sched.h + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SCHED_H +#define __INCLUDE_NUTTX_SCHED_H + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/******************************************************************************** + * Pre-processor Definitions + ********************************************************************************/ + +/* Task Management Definitins ***************************************************/ + +/* This is the maximum number of times that a lock can be set */ + +#define MAX_LOCK_COUNT 127 + +/* Values for the _TCB flags flag bits */ + +#define TCB_FLAG_TTYPE_SHIFT (0) /* Bits 0-1: thread type */ +#define TCB_FLAG_TTYPE_MASK (3 << TCB_FLAG_TTYPE_SHIFT) +# define TCB_FLAG_TTYPE_TASK (0 << TCB_FLAG_TTYPE_SHIFT) /* Normal user task */ +# define TCB_FLAG_TTYPE_PTHREAD (1 << TCB_FLAG_TTYPE_SHIFT) /* User pthread */ +# define TCB_FLAG_TTYPE_KERNEL (2 << TCB_FLAG_TTYPE_SHIFT) /* Kernel thread */ +#define TCB_FLAG_NONCANCELABLE (1 << 2) /* Bit 2: Pthread is non-cancelable */ +#define TCB_FLAG_CANCEL_PENDING (1 << 3) /* Bit 3: Pthread cancel is pending */ +#define TCB_FLAG_ROUND_ROBIN (1 << 4) /* Bit 4: Round robin sched enabled */ + +/******************************************************************************** + * Global Type Definitions + ********************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* General Task Management Types ************************************************/ + +/* This is the type of the task_state field of the TCB. NOTE: the order and + * content of this enumeration is critical since there are some OS tables indexed + * by these values. The range of values is assumed to fit into a uint8_t in _TCB. + */ + +enum tstate_e +{ + TSTATE_TASK_INVALID = 0, /* INVALID - The TCB is uninitialized */ + TSTATE_TASK_PENDING, /* READY_TO_RUN - Pending preemption unlock */ + TSTATE_TASK_READYTORUN, /* READY-TO-RUN - But not running */ + TSTATE_TASK_RUNNING, /* READY_TO_RUN - And running */ + + TSTATE_TASK_INACTIVE, /* BLOCKED - Initialized but not yet activated */ + TSTATE_WAIT_SEM, /* BLOCKED - Waiting for a semaphore */ +#ifndef CONFIG_DISABLE_SIGNALS + TSTATE_WAIT_SIG, /* BLOCKED - Waiting for a signal */ +#endif +#ifndef CONFIG_DISABLE_MQUEUE + TSTATE_WAIT_MQNOTEMPTY, /* BLOCKED - Waiting for a MQ to become not empty. */ + TSTATE_WAIT_MQNOTFULL, /* BLOCKED - Waiting for a MQ to become not full. */ +#endif +#ifdef CONFIG_PAGING + TSTATE_WAIT_PAGEFILL, /* BLOCKED - Waiting for page fill */ +#endif + NUM_TASK_STATES /* Must be last */ +}; +typedef enum tstate_e tstate_t; + +/* The following definitions are determined by tstate_t */ + +#define FIRST_READY_TO_RUN_STATE TSTATE_TASK_READYTORUN +#define LAST_READY_TO_RUN_STATE TSTATE_TASK_RUNNING +#define FIRST_BLOCKED_STATE TSTATE_TASK_INACTIVE +#define LAST_BLOCKED_STATE (NUM_TASK_STATES-1) + +/* The following is the form of a thread start-up function */ + +typedef void (*start_t)(void); + +/* This is the entry point into the main thread of the task or into a created + * pthread within the task. + */ + +union entry_u +{ + pthread_startroutine_t pthread; + main_t main; +}; +typedef union entry_u entry_t; + +/* These is the types of the functions that are executed with exit() is called + * (if registered via atexit() on on_exit()). + */ + +#ifdef CONFIG_SCHED_ATEXIT +typedef void (*atexitfunc_t)(void); +#endif + +#ifdef CONFIG_SCHED_ONEXIT +typedef void (*onexitfunc_t)(int exitcode, FAR void *arg); +#endif + +/* POSIX Message queue */ + +typedef struct msgq_s msgq_t; + +/* The structure used to maintain environment variables */ + +#ifndef CONFIG_DISABLE_ENVIRON +struct environ_s +{ + unsigned int ev_crefs; /* Reference count used when environment + * is shared by threads */ + size_t ev_alloc; /* Number of bytes allocated in environment */ + char ev_env[1]; /* Environment strings */ +}; +typedef struct environ_s environ_t; +# define SIZEOF_ENVIRON_T(alloc) (sizeof(environ_t) + alloc - 1) +#endif + +/* This structure describes a reference counted D-Space region */ + +struct dspace_s +{ + uint32_t crefs; /* This is the number of pthreads that shared the + * the same D-Space */ + uint8_t region[1]; /* Beginning of the allocated region */ +}; + +#define SIZEOF_DSPACE_S(n) (sizeof(struct dspace_s) - 1 + (n)) + +/* This is the task control block (TCB) */ + +struct _TCB +{ + /* Fields used to support list management *************************************/ + + FAR struct _TCB *flink; /* link in DQ of TCBs */ + FAR struct _TCB *blink; + + /* Task Management Fields *****************************************************/ + + pid_t pid; /* This is the ID of the thread */ + start_t start; /* Thread start function */ + entry_t entry; /* Entry Point into the thread */ + +#ifdef CONFIG_SCHED_ATEXIT +# if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1 + atexitfunc_t atexitfunc[CONFIG_SCHED_ATEXIT_MAX]; +# else + atexitfunc_t atexitfunc; /* Called when exit is called. */ +# endif +#endif + +#ifdef CONFIG_SCHED_ONEXIT +# if defined(CONFIG_SCHED_ONEXIT_MAX) && CONFIG_SCHED_ONEXIT_MAX > 1 + onexitfunc_t onexitfunc[CONFIG_SCHED_ONEXIT_MAX]; + FAR void *onexitarg[CONFIG_SCHED_ONEXIT_MAX]; +# else + onexitfunc_t onexitfunc; /* Called when exit is called. */ + FAR void *onexitarg; /* The argument passed to the function */ +# endif +#endif + +#ifdef CONFIG_SCHED_WAITPID + sem_t exitsem; /* Support for waitpid */ + int *stat_loc; /* Location to return exit status */ +#endif + + uint8_t sched_priority; /* Current priority of the thread */ + +#ifdef CONFIG_PRIORITY_INHERITANCE +# if CONFIG_SEM_NNESTPRIO > 0 + uint8_t npend_reprio; /* Number of nested reprioritizations */ + uint8_t pend_reprios[CONFIG_SEM_NNESTPRIO]; +# endif + uint8_t base_priority; /* "Normal" priority of the thread */ +#endif + + uint8_t task_state; /* Current state of the thread */ + uint16_t flags; /* Misc. general status flags */ + int16_t lockcount; /* 0=preemptable (not-locked) */ + +#ifndef CONFIG_DISABLE_PTHREAD + FAR void *joininfo; /* Detach-able info to support join */ +#endif + +#if CONFIG_RR_INTERVAL > 0 + int timeslice; /* RR timeslice interval remaining */ +#endif + + /* Values needed to restart a task ********************************************/ + + uint8_t init_priority; /* Initial priority of the task */ + char *argv[CONFIG_MAX_TASK_ARGS+1]; /* Name+start-up parameters */ + +#ifndef CONFIG_DISABLE_ENVIRON + FAR environ_t *envp; /* Environment variables */ +#endif + + /* Stack-Related Fields *******************************************************/ + +#ifndef CONFIG_CUSTOM_STACK + size_t adj_stack_size; /* Stack size after adjustment */ + /* for hardware, processor, etc. */ + /* (for debug purposes only) */ + FAR void *stack_alloc_ptr; /* Pointer to allocated stack */ + /* Need to deallocate stack */ + FAR void *adj_stack_ptr; /* Adjusted stack_alloc_ptr for HW */ + /* The initial stack pointer value */ +#endif + + /* External Module Support ****************************************************/ + +#ifdef CONFIG_PIC + FAR struct dspace_s *dspace; /* Allocated area for .bss and .data */ +#endif + + /* POSIX Thread Specific Data *************************************************/ + +#if !defined(CONFIG_DISABLE_PTHREAD) && CONFIG_NPTHREAD_KEYS > 0 + FAR void *pthread_data[CONFIG_NPTHREAD_KEYS]; +#endif + + /* POSIX Semaphore Control Fields *********************************************/ + + sem_t *waitsem; /* Semaphore ID waiting on */ + + /* POSIX Signal Control Fields ************************************************/ + +#ifndef CONFIG_DISABLE_SIGNALS + sigset_t sigprocmask; /* Signals that are blocked */ + sigset_t sigwaitmask; /* Waiting for pending signals */ + sq_queue_t sigactionq; /* List of actions for signals */ + sq_queue_t sigpendingq; /* List of Pending Signals */ + sq_queue_t sigpendactionq; /* List of pending signal actions */ + sq_queue_t sigpostedq; /* List of posted signals */ + siginfo_t sigunbinfo; /* Signal info when task unblocked */ +#endif + + /* POSIX Named Message Queue Fields *******************************************/ + +#ifndef CONFIG_DISABLE_MQUEUE + sq_queue_t msgdesq; /* List of opened message queues */ + FAR msgq_t *msgwaitq; /* Waiting for this message queue */ +#endif + + /* Library related fields *****************************************************/ + + int pterrno; /* Current per-thread errno */ + + /* File system support ********************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + FAR struct filelist *filelist; /* Maps file descriptor to file */ +#endif + +#if CONFIG_NFILE_STREAMS > 0 + FAR struct streamlist *streams; /* Holds C buffered I/O info */ +#endif + + /* Network socket *************************************************************/ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + FAR struct socketlist *sockets; /* Maps file descriptor to file */ +#endif + + /* State save areas ***********************************************************/ + /* The form and content of these fields are processor-specific. */ + + struct xcptcontext xcp; /* Interrupt register save area */ + +#if CONFIG_TASK_NAME_SIZE > 0 + char name[CONFIG_TASK_NAME_SIZE]; /* Task name */ +#endif + +}; + +/* Certain other header files may also define this time to avoid circular header + * file inclusion issues. + */ + +#ifndef __TCB_DEFINED__ +typedef struct _TCB _TCB; +#define __TCB_DEFINED__ +#endif + +/* This is the callback type used by sched_foreach() */ + +typedef void (*sched_foreach_t)(FAR _TCB *tcb, FAR void *arg); + +#endif /* __ASSEMBLY__ */ + +/******************************************************************************** + * Global Function Prototypes + ********************************************************************************/ + +#ifndef __ASSEMBLY__ +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* TCB helpers */ + +EXTERN FAR _TCB *sched_self(void); + +/* File system helpers */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +EXTERN FAR struct filelist *sched_getfiles(void); +#if CONFIG_NFILE_STREAMS > 0 +EXTERN FAR struct streamlist *sched_getstreams(void); +#endif /* CONFIG_NFILE_STREAMS */ +#endif /* CONFIG_NFILE_DESCRIPTORS */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 +EXTERN FAR struct socketlist *sched_getsockets(void); +#endif /* CONFIG_NSOCKET_DESCRIPTORS */ + +/* sched_foreach will enumerate over each task and provide the + * TCB of each task to a user callback functions. Interrupts + * will be disabled throughout this enumeration! + */ + +EXTERN void sched_foreach(sched_foreach_t handler, FAR void *arg); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* __INCLUDE_NUTTX_SCHED_H */ diff --git a/nuttx/include/nuttx/scsi.h b/nuttx/include/nuttx/scsi.h new file mode 100644 index 0000000000..6d0aa5b209 --- /dev/null +++ b/nuttx/include/nuttx/scsi.h @@ -0,0 +1,1013 @@ +/**************************************************************************** + * include/nuttx/scsi.h + * + * Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "SCSI Primary Commands - 3 (SPC-3)," American National Standard + * for Information Technology, May 4, 2005 + * + * "SCSI Primary Commands - 4 (SPC-4)," American National Standard + * for Information Technology, July 19, 2008 + * + * "SCSI Block Commands -2 (SBC-2)," American National Standard + * for Information Technology, November 13, 2004 + * + * "SCSI Multimedia Commands - 3 (MMC-3)," American National Standard + * for Information Technology, November 12, 2001 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SCSI_H +#define __INCLUDE_NUTTX_SCSI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* SCSI commands ************************************************************/ + +#define SCSI_CMD_TESTUNITREADY 0x00 +#define SCSI_CMD_REZEROUNIT 0x01 +#define SCSI_CMD_REQUESTSENSE 0x03 +#define SCSI_CMD_FORMAT_UNIT 0x04 +#define SCSI_CMD_REASSIGNBLOCKS 0x07 +#define SCSI_CMD_READ6 0x08 +#define SCSI_CMD_WRITE6 0x0a +#define SCSI_CMD_SEEK6 0x0b +#define SCSI_CMD_SPACE6 0x11 +#define SCSI_CMD_INQUIRY 0x12 +#define SCSI_CMD_MODESELECT6 0x15 +#define SCSI_CMD_RESERVE6 0x16 +#define SCSI_CMD_RELEASE6 0x17 +#define SCSI_CMD_COPY 0x18 +#define SCSI_CMD_MODESENSE6 0x1a +#define SCSI_CMD_STARTSTOPUNIT 0x1b +#define SCSI_CMD_RECEIVEDIAGNOSTICRESULTS 0x1c +#define SCSI_CMD_SENDDIAGNOSTIC 0x1d +#define SCSI_CMD_PREVENTMEDIAREMOVAL 0x1e +#define SCSI_CMD_READFORMATCAPACITIES 0x23 +#define SCSI_CMD_READCAPACITY10 0x25 +#define SCSI_CMD_READ10 0x28 +#define SCSI_CMD_WRITE10 0x2a +#define SCSI_CMD_SEEK10 0x2b +#define SCSI_CMD_WRITEANDVERIFY 0x2e +#define SCSI_CMD_VERIFY10 0x2f +#define SCSI_CMD_SEARCHDATAHIGH 0x30 +#define SCSI_CMD_SEARCHDATAEQUAL 0x31 +#define SCSI_CMD_SEARCHDATALOW 0x32 +#define SCSI_CMD_SETLIMITS10 0x33 +#define SCSI_CMD_PREFETCH10 0x34 +#define SCSI_CMD_SYNCHCACHE10 0x35 +#define SCSI_CMD_LOCKCACHE 0x36 +#define SCSI_CMD_READDEFECTDATA10 0x37 +#define SCSI_CMD_COMPARE 0x39 +#define SCSI_CMD_COPYANDVERIFY 0x3a +#define SCSI_CMD_WRITEBUFFER 0x3b +#define SCSI_CMD_READBUFFER 0x3c +#define SCSI_CMD_READLONG10 0x3e +#define SCSI_CMD_WRITELONG10 0x3f +#define SCSI_CMD_CHANGEDEFINITION 0x40 +#define SCSI_CMD_WRITESAME10 0x41 +#define SCSI_CMD_LOGSELECT 0x4c +#define SCSI_CMD_LOGSENSE 0x4d +#define SCSI_CMD_XDWRITE10 0x50 +#define SCSI_CMD_XPWRITE10 0x51 +#define SCSI_CMD_XDREAD10 0x52 +#define SCSI_CMD_MODESELECT10 0x55 +#define SCSI_CMD_RESERVE10 0x56 +#define SCSI_CMD_RELEASE10 0x57 +#define SCSI_CMD_MODESENSE10 0x5a +#define SCSI_CMD_PERSISTENTRESERVEIN 0x5e +#define SCSI_CMD_PERSISTENTRESERVEOUT 0x5f +#define SCSI_CMD_32 0x7f +#define SCSI_CMD_XDWRITEEXTENDED 0x80 +#define SCSI_CMD_REBUILD 0x82 +#define SCSI_CMD_REGENERATE 0x82 +#define SCSI_CMD_EXTENDEDCOPY 0x83 +#define SCSI_CMD_COPYRESULTS 0x84 +#define SCSI_CMD_ACCESSCONTROLIN 0x86 +#define SCSI_CMD_ACCESSCONTROLOUT 0x87 +#define SCSI_CMD_READ16 0x88 +#define SCSI_CMD_WRITE16 0x8a +#define SCSI_CMD_READATTRIBUTE 0x8c +#define SCSI_CMD_WRITEATTRIBUTE 0x8d +#define SCSI_CMD_WRITEANDVERIFY16 0x8e +#define SCSI_CMD_PREFETCH16 0x90 +#define SCSI_CMD_SYNCHCACHE16 0x91 +#define SCSI_CMD_LOCKUNLOCKACACHE 0x92 +#define SCSI_CMD_WRITESAME16 0x93 +#define SCSI_CMD_READCAPACITY16 0x9e +#define SCSI_CMD_READLONG16 0x9e +#define SCSI_CMD_WRITELONG106 0x9f +#define SCSI_CMD_REPORTLUNS 0xa0 +#define SCSI_CMD_MAINTENANCEIN 0xa3 +#define SCSI_CMD_MAINTENANCEOUT 0xa4 +#define SCSI_CMD_MOVEMEDIUM 0xa5 +#define SCSI_CMD_MOVEMEDIUMATTACHED 0xa7 +#define SCSI_CMD_READ12 0xa8 +#define SCSI_CMD_WRITE12 0xaa +#define SCSI_CMD_READMEDIASERIALNUMBER 0xab +#define SCSI_CMD_WRITEANDVERIFY12 0xae +#define SCSI_CMD_VERIFY12 0xaf +#define SCSI_CMD_SETLIMITS12 0xb3 +#define SCSI_CMD_READELEMENTSTATUS 0xb4 +#define SCSI_CMD_READDEFECTDATA12 0xb7 +#define SCSI_CMD_REDUNDANCYGROUPIN 0xba +#define SCSI_CMD_REDUNDANCYGROUPOUT 0xbb +#define SCSI_CMD_SPAREIN 0xbc +#define SCSI_CMD_SPAREOUT 0xbd +#define SCSI_CMD_VOLUMESETIN 0xbe +#define SCSI_CMD_VOLUMESETOUT 0xbf + +/* Common SCSI KCQ values (sense Key/additional sense Code/ASC Qualifier) *** + * + * 0xnn0386 Write Fault Data Corruption + * 0xnn0500 Illegal request + * 0xnn0600 Unit attention + * 0xnn0700 Data protect + * 0xnn0800 LUN communication failure + * 0xnn0801 LUN communication timeout + * 0xnn0802 LUN communication parity error + * 0xnn0803 LUN communication CRC error + * 0xnn0900 vendor specific sense key + * 0xnn0901 servo fault + * 0xnn0904 head select fault + * 0xnn0a00 error log overflow + * 0xnn0b00 aborted command + * 0xnn0c00 write error + * 0xnn0c02 write error - auto-realloc failed + * 0xnn0e00 data miscompare + * 0xnn1200 address mark not founf for ID field + * 0xnn1400 logical block not found + * 0xnn1500 random positioning error + * 0xnn1501 mechanical positioning error + * 0xnn1502 positioning error detected by read of medium + * 0xnn2700 write protected + * 0xnn2900 POR or bus reset occurred + * 0xnn3101 format failed + * 0xnn3191 format corrupted + * 0xnn3201 defect list update error + * 0xnn3202 no spares available + * 0xnn3501 unspecified enclosure services failure + * 0xnn3700 parameter rounded + * 0xnn3d00 invalid bits in identify message + * 0xnn3e00 LUN not self-configured yet + * 0xnn4001 DRAM parity error + * 0xnn4002 DRAM parity error + * 0xnn4200 power-on or self-test failure + * 0xnn4c00 LUN failed self-configuration + * 0xnn5c00 RPL status change + * 0xnn5c01 spindles synchronized + * 0xnn5c02 spindles not synchronized + * 0xnn6500 voltage fault + * 0xnn8000 general firmware error + */ + +/* No sense KCQ values */ + +#define SCSI_KCQ_NOSENSE 0x000000 /* No error */ +#define SCSI_KCQ_PFATHRESHOLDREACHED 0x005c00 /* No sense - PFA threshold reached */ + +/* Soft error KCQ values */ + +#define SCSI_KCQSE_RWENOINDEX 0x010100 /* Recovered Write error - no index */ +#define SCSI_KCQSE_RECOVEREDNOSEEKCOMPLETION 0x010200 /* Recovered no seek completion */ +#define SCSI_KCQSE_RWEWRITEFAULT 0x010300 /* Recovered Write error - write fault */ +#define SCSI_KCQSE_TRACKFOLLOWINGERROR 0x010900 /* Track following error */ +#define SCSI_KCQSE_TEMPERATUREWARNING 0x010b01 /* Temperature warning */ +#define SCSI_KCQSE_RWEWARREALLOCATED 0x010c01 /* Recovered Write error with auto-realloc - reallocated */ +#define SCSI_KCQSE_RWERECOMMENDREASSIGN 0x010c03 /* Recovered Write error - recommend reassign */ +#define SCSI_KCQSE_RDWOEUSINGPREVLBI 0x011201 /* Recovered data without ECC using prev logical block ID */ +#define SCSI_KCQSE_RDWEUSINGPREVLBI 0x011202 /* Recovered data with ECC using prev logical block ID */ +#define SCSI_KCQSE_RECOVEREDRECORDNOTFOUND 0x011401 /* Recovered Record Not Found */ +#define SCSI_KCQSE_RWEDSME 0x011600 /* Recovered Write error - Data Sync Mark Error */ +#define SCSI_KCQSE_RWEDSEDATAREWRITTEN 0x011601 /* Recovered Write error - Data Sync Error - data rewritten */ +#define SCSI_KCQSE_RWEDSERECOMMENDREWRITE 0x011602 /* Recovered Write error - Data Sync Error - recommend rewrite */ +#define SCSI_KCQSE_RWEDSEDATAAUTOREALLOCATED 0x011603 /* Recovered Write error - Data Sync Error - data auto-reallocated */ +#define SCSI_KCQSE_RWEDSERECOMMENDREASSIGNMENT 0x011604 /* Recovered Write error - Data Sync Error - recommend reassignment */ +#define SCSI_KCQSE_RDWNECORRECTIONAPPLIED 0x011700 /* Recovered data with no error correction applied */ +#define SCSI_KCQSE_RREWITHRETRIES 0x011701 /* Recovered Read error - with retries */ +#define SCSI_KCQSE_RDUSINGPOSITIVEOFFSET 0x011702 /* Recovered data using positive offset */ +#define SCSI_KCQSE_RDUSINGNEGATIVEOFFSET 0x011703 /* Recovered data using negative offset */ +#define SCSI_KCQSE_RDUSINGPREVIOUSLBI 0x011705 /* Recovered data using previous logical block ID */ +#define SCSI_KCQSE_RREWOEAUTOREALLOCATED 0x011706 /* Recovered Read error - without ECC, auto reallocated */ +#define SCSI_KCQSE_RREWOERECOMMENDREASSIGN 0x011707 /* Recovered Read error - without ECC, recommend reassign */ +#define SCSI_KCQSE_RREWOERECOMMENDREWRITE 0x011708 /* Recovered Read error - without ECC, recommend rewrite */ +#define SCSI_KCQSE_RREWOEDATAREWRITTEN 0x011709 /* Recovered Read error - without ECC, data rewritten */ +#define SCSI_KCQSE_RREWE 0x011800 /* Recovered Read error - with ECC */ +#define SCSI_KCQSE_RDWEANDRETRIES 0x011801 /* Recovered data with ECC and retries */ +#define SCSI_KCQSE_RREWEAUTOREALLOCATED 0x011802 /* Recovered Read error - with ECC, auto reallocated */ +#define SCSI_KCQSE_RREWERECOMMENDREASSIGN 0x011805 /* Recovered Read error - with ECC, recommend reassign */ +#define SCSI_KCQSE_RDUSINGECCANDOFFSETS 0x011806 /* Recovered data using ECC and offsets */ +#define SCSI_KCQSE_RREWEDATAREWRITTEN 0x011807 /* Recovered Read error - with ECC, data rewritten */ +#define SCSI_KCQSE_DLNOTFOUND 0x011c00 /* Defect List not found */ +#define SCSI_KCQSE_PRIMARYDLNOTFOUND 0x011c01 /* Primary defect list not found */ +#define SCSI_KCQSE_GROWNDLNOTFOUND 0x011c02 /* Grown defect list not found */ +#define SCSI_KCQSE_PARTIALDLTRANSFERRED 0x011f00 /* Partial defect list transferred */ +#define SCSI_KCQSE_INTERNALTARGETFAILURE 0x014400 /* Internal target failure */ +#define SCSI_KCQSE_PFATHRESHOLDREACHED 0x015d00 /* PFA threshold reached */ +#define SCSI_KCQSE_PFATESTWARNING 0x015dff /* PFA test warning */ +#define SCSI_KCQSE_INTERNALLOGICFAILURE 0x018100 /* Internal logic failure */ + +/* Not Ready / Diagnostic Failure KCQ values */ + +#define SCSI_KCQNR_CAUSENOTREPORTABLE 0x020400 /* Not Ready - Cause not reportable. */ +#define SCSI_KCQNR_BECOMINGREADY 0x020401 /* Not Ready - becoming ready */ +#define SCSI_KCQNR_NEEDINITIALIZECOMMAND 0x020402 /* Not Ready - need initialize command (start unit) */ +#define SCSI_KCQNR_MANUALINTERVENTIONREQUIRED 0x020403 /* Not Ready - manual intervention required */ +#define SCSI_KCQNR_FORMATINPROGRESS 0x020404 /* Not Ready - format in progress */ +#define SCSI_KCQNR_SELFTESTINPROGRESS 0x020409 /* Not Ready - self-test in progress */ +#define SCSI_KCQNR_MEDIUMFORMATCORRUPTED 0x023100 /* Not Ready - medium format corrupted */ +#define SCSI_KCQNR_FORMATCOMMANDFAILED 0x023101 /* Not Ready - format command failed */ +#define SCSI_KCQNR_ESUNAVAILABLE 0x023502 /* Not Ready - enclosure services unavailable */ +#define SCSI_KCQNR_MEDIANOTPRESENT 0x023a00 /* Not Ready - media not present */ +#define SCSI_KCQDF_BRINGUPFAILORDEGRADEDMODE 0x024080 /* Diagnostic Failure - bring-up fail or degraded mode */ +#define SCSI_KCQDF_HARDDISKCONTROLLER 0x024081 /* Diagnostic Failure - Hard Disk Controller */ +#define SCSI_KCQDF_RAMMICROCODENOTLOADED 0x024085 /* Diagnostic Failure - RAM microcode not loaded */ +#define SCSI_KCQDF_RROCALIBRATION 0x024090 /* Diagnostic Failure - RRO Calibration */ +#define SCSI_KCQDF_CHANNELCALIBRATION 0x024091 /* Diagnostic Failure - Channel Calibration */ +#define SCSI_KCQDF_HEADLOAD 0x024092 /* Diagnostic Failure - Head Load */ +#define SCSI_KCQDF_WRITEAE 0x024093 /* Diagnostic Failure - Write AE */ +#define SCSI_KCQDF_12VOVERCURRENT 0x024094 /* Diagnostic Failure - 12V over current */ +#define SCSI_KCQDF_OTHERSPINDLEFAILURE 0x024095 /* Diagnostic Failure - Other spindle failure */ +#define SCSI_KCQDF_SELFRESET 0x0240b0 /* Diagnostic Failure - self-reset */ +#define SCSI_KCQDF_CONFIGNOTLOADED 0x024c00 /* Diagnostic Failure - config not loaded */ + +/* Medium error KCQ values */ + +#define SCSI_KCQME_WRITEFAULT 0x030300 /* Medium Error - write fault */ +#define SCSI_KCQME_WRITEFAULTAUTOREALLOCFAILED 0x030c02 /* Medium Error - write error - auto-realloc failed */ +#define SCSI_KCQME_WRITERTLIMITEXCEEDED 0x030cbb /* Medium Error - write recovery time limit exceeded */ +#define SCSI_KCQME_IDCRCERROR 0x031000 /* Medium Error - ID CRC error */ +#define SCSI_KCQME_UNRRE1 0x031100 /* Medium Error - unrecovered read error */ +#define SCSI_KCQME_READRETRIESEXHAUSTED 0x031101 /* Medium Error - read retries exhausted */ +#define SCSI_KCQME_ERRORTOOLONGTOCORRECT 0x031102 /* Medium Error - error too long to correct */ +#define SCSI_KCQME_UREAUTOREALLOCFAILED 0x031104 /* Medium Error - unrecovered read error - auto re-alloc failed */ +#define SCSI_KCQME_URERECOMMENDREASSIGN 0x03110b /* Medium Error - unrecovered read error - recommend reassign */ +#define SCSI_KCQME_READRTLIMITEXCEEDED 0x0311ff /* Medium Error - read recovery time limit exceeded */ +#define SCSI_KCQME_RECORDNOTFOUND 0x031401 /* Medium Error - record not found */ +#define SCSI_KCQME_DSME 0x031600 /* Medium Error - Data Sync Mark error */ +#define SCSI_KCQME_DSERECOMMENDREASSIGN 0x031604 /* Medium Error - Data Sync Error - recommend reassign */ +#define SCSI_KCQME_DLE 0x031900 /* Medium Error - defect list error */ +#define SCSI_KCQME_DLNOTAVAILABLE 0x031901 /* Medium Error - defect list not available */ +#define SCSI_KCQME_DLEINPRIMARYLIST 0x031902 /* Medium Error - defect list error in primary list */ +#define SCSI_KCQME_DLEINGROWNLIST 0x031903 /* Medium Error - defect list error in grown list */ +#define SCSI_KCQME_FEWERTHAN50PCTDLCOPIES 0x03190e /* Medium Error - fewer than 50% defect list copies */ +#define SCSI_KCQME_MEDIUMFORMATCORRUPTED 0x033100 /* Medium Error - medium format corrupted */ +#define SCSI_KCQME_FORMATCOMMANDFAILED 0x033101 /* Medium Error - format command failed */ +#define SCSI_KCQME_DATAAUTOREALLOCATED 0x038000 /* Medium Error - data auto-reallocated */ + +/* Hardware Error KCQ values */ + +#define SCSI_KCQHE_NOINDEXORSECTOR 0x040100 /* Hardware Error - no index or sector */ +#define SCSI_KCQHE_NOSEEKCOMPLETE 0x040200 /* Hardware Error - no seek complete */ +#define SCSI_KCQHE_WRITEFAULT 0x040300 /* Hardware Error - write fault */ +#define SCSI_KCQHE_COMMUNICATIONFAILURE 0x040800 /* Hardware Error - communication failure */ +#define SCSI_KCQHE_TRACKFOLLOWINGERROR 0x040900 /* Hardware Error - track following error */ +#define SCSI_KCQHE_UREINRESERVEDAREA 0x041100 /* Hardware Error - unrecovered read error in reserved area */ +#define SCSI_KCQHE_DSMEINRESERVEDAREA 0x041600 /* Hardware Error - Data Sync Mark error in reserved area */ +#define SCSI_KCQHE_DLE 0x041900 /* Hardware Error - defect list error */ +#define SCSI_KCQHE_DLEINPRIMARYLIST 0x041902 /* Hardware Error - defect list error in Primary List */ +#define SCSI_KCQHE_DLEINGROWNLIST 0x041903 /* Hardware Error - defect list error in Grown List */ +#define SCSI_KCQHE_REASSIGNFAILED 0x043100 /* Hardware Error - reassign failed */ +#define SCSI_KCQHE_NODEFECTSPAREAVAILABLE 0x043200 /* Hardware Error - no defect spare available */ +#define SCSI_KCQHE_UNSUPPORTEDENCLOSUREFUNCTION 0x043501 /* Hardware Error - unsupported enclosure function */ +#define SCSI_KCQHE_ESUNAVAILABLE 0x043502 /* Hardware Error - enclosure services unavailable */ +#define SCSI_KCQHE_ESTRANSFERFAILURE 0x043503 /* Hardware Error - enclosure services transfer failure */ +#define SCSI_KCQHE_ESREFUSED 0x043504 /* Hardware Error - enclosure services refused */ +#define SCSI_KCQHE_SELFTESTFAILED 0x043e03 /* Hardware Error - self-test failed */ +#define SCSI_KCQHE_UNABLETOUPDATESELFTEST 0x043e04 /* Hardware Error - unable to update self-test */ +#define SCSI_KCQHE_DMDIAGNOSTICFAIL 0x044080 /* Hardware Error - Degrade Mode. Diagnostic Fail */ +#define SCSI_KCQHE_DMHWERROR 0x044081 /* Hardware Error - Degrade Mode. H/W Error */ +#define SCSI_KCQHE_DMRAMMICROCODENOTLOADED 0x044085 /* Hardware Error - Degrade Mode. RAM microcode not loaded */ +#define SCSI_KCQHE_SEEKTESTFAILURE 0x044090 /* Hardware Error - seek test failure */ +#define SCSI_KCQHE_READWRITETESTFAILURE 0x0440a0 /* Hardware Error - read/write test failure */ +#define SCSI_KCQHE_DEVICESELFRESET 0x0440b0 /* Hardware Error - device self-reset */ +#define SCSI_KCQHE_COMPONENTMISMATCH 0x0440d0 /* Hardware Error - component mismatch */ +#define SCSI_KCQHE_INTERNALTARGETFAILURE 0x044400 /* Hardware Error - internal target failure */ +#define SCSI_KCQHE_INTERNALLOGICERROR 0x048100 /* Hardware Error - internal logic error */ +#define SCSI_KCQHE_COMMANDTIMEOUT 0x048200 /* Hardware Error - command timeout */ + +/* Illegal Request KCQ values */ + +#define SCSI_KCQIR_PARMLISTLENGTHERROR 0x051a00 /* Illegal Request - parm list length error */ +#define SCSI_KCQIR_INVALIDCOMMAND 0x052000 /* Illegal Request - invalid/unsupported command code */ +#define SCSI_KCQIR_LBAOUTOFRANGE 0x052100 /* Illegal Request - LBA out of range */ +#define SCSI_KCQIR_INVALIDFIELDINCBA 0x052400 /* Illegal Request - invalid field in CDB (Command Descriptor Block) */ +#define SCSI_KCQIR_INVALIDLUN 0x052500 /* Illegal Request - invalid LUN */ +#define SCSI_KCQIR_INVALIDFIELDSINPARMLIST 0x052600 /* Illegal Request - invalid fields in parm list */ +#define SCSI_KCQIR_PARAMETERNOTSUPPORTED 0x052601 /* Illegal Request - parameter not supported */ +#define SCSI_KCQIR_INVALIDPARMVALUE 0x052602 /* Illegal Request - invalid parm value */ +#define SCSI_KCQIR_IFPTHRESHOLDPARAMETER 0x052603 /* Illegal Request - invalid field parameter - threshold parameter */ +#define SCSI_KCQIR_INVALIDRELEASEOFPR 0x052604 /* Illegal Request - invalid release of persistent reservation */ +#define SCSI_KCQIR_IFPTMSFIRMWARETAG 0x052697 /* Illegal Request - invalid field parameter - TMS firmware tag */ +#define SCSI_KCQIR_IFPCHECKSUM 0x052698 /* Illegal Request - invalid field parameter - check sum */ +#define SCSI_KCQIR_IFPFIRMWARETAG 0x052699 /* Illegal Request - invalid field parameter - firmware tag */ +#define SCSI_KCQIR_COMMANDSEQUENCEERROR 0x052c00 /* Illegal Request - command sequence error */ +#define SCSI_KCQIR_UNSUPPORTEDENCLOSUREFUNCTION 0x053501 /* Illegal Request - unsupported enclosure function */ +#define SCSI_KCQIR_SAVINGPARMSNOTSUPPORTED 0x053900 /* Illegal Request - Saving parameters not supported */ +#define SCSI_KCQIR_INVALIDMESSAGE 0x054900 /* Illegal Request - invalid message */ +#define SCSI_KCQIR_MEDIALOADOREJECTFAILED 0x055300 /* Illegal Request - media load or eject failed */ +#define SCSI_KCQIR_UNLOADTAPEFAILURE 0x055301 /* Illegal Request - unload tape failure */ +#define SCSI_KCQIR_MEDIUMREMOVALPREVENTED 0x055302 /* Illegal Request - medium removal prevented */ +#define SCSI_KCQIR_SYSTEMRESOURCEFAILURE 0x055500 /* Illegal Request - system resource failure */ +#define SCSI_KCQIR_SYSTEMBUFFERFULL 0x055501 /* Illegal Request - system buffer full */ +#define SCSI_KCQIR_INSUFFICIENTRR 0x055504 /* Illegal Request - Insufficient Registration Resources */ + +/* Unit Attention KCQ values */ + +#define SCSI_KCQUA_NOTREADYTOTRANSITION 0x062800 /* Unit Attention - not-ready to ready transition (format complete) */ +#define SCSI_KCQUA_DEVICERESETOCCURRED 0x062900 /* Unit Attention - POR or device reset occurred */ +#define SCSI_KCQUA_POROCCURRED 0x062901 /* Unit Attention - POR occurred */ +#define SCSI_KCQUA_SCSIBUSRESETOCCURRED 0x062902 /* Unit Attention - SCSI bus reset occurred */ +#define SCSI_KCQUA_TARGETRESETOCCURRED 0x062903 /* Unit Attention - TARGET RESET occurred */ +#define SCSI_KCQUA_SELFINITIATEDRESETOCCURRED 0x062904 /* Unit Attention - self-initiated-reset occurred */ +#define SCSI_KCQUA_TRANSCEIVERMODECHANGETOSE 0x062905 /* Unit Attention - transceiver mode change to SE */ +#define SCSI_KCQUA_TRANSCEIVERMODECHANGETOLVD 0x062906 /* Unit Attention - transceiver mode change to LVD */ +#define SCSI_KCQUA_PARAMETERSCHANGED 0x062a00 /* Unit Attention - parameters changed */ +#define SCSI_KCQUA_MODEPARAMETERSCHANGED 0x062a01 /* Unit Attention - mode parameters changed */ +#define SCSI_KCQUA_LOGSELECTPARMSCHANGED 0x062a02 /* Unit Attention - log select parms changed */ +#define SCSI_KCQUA_RESERVATIONSPREEMPTED 0x062a03 /* Unit Attention - Reservations pre-empted */ +#define SCSI_KCQUA_RESERVATIONSRELEASED 0x062a04 /* Unit Attention - Reservations released */ +#define SCSI_KCQUA_REGISTRATIONSPREEMPTED 0x062a05 /* Unit Attention - Registrations pre-empted */ +#define SCSI_KCQUA_COMMANDSCLEARED 0x062f00 /* Unit Attention - commands cleared by another initiator */ +#define SCSI_KCQUA_OPERATINGCONDITIONSCHANGED 0x063f00 /* Unit Attention - target operating conditions have changed */ +#define SCSI_KCQUA_MICROCODECHANGED 0x063f01 /* Unit Attention - microcode changed */ +#define SCSI_KCQUA_CHANGEDOPERATINGDEFINITION 0x063f02 /* Unit Attention - changed operating definition */ +#define SCSI_KCQUA_INQUIRYPARAMETERSCHANGED 0x063f03 /* Unit Attention - inquiry parameters changed */ +#define SCSI_KCQUA_DEVICEIDENTIFIERCHANGED 0x063f05 /* Unit Attention - device identifier changed */ +#define SCSI_KCQUA_INVALIDAPMPARAMETERS 0x063f90 /* Unit Attention - invalid APM parameters */ +#define SCSI_KCQUA_WORLDWIDENAMEMISMATCH 0x063f91 /* Unit Attention - world-wide name mismatch */ +#define SCSI_KCQUA_PFATHRESHOLDREACHED 0x065d00 /* Unit Attention - PFA threshold reached */ +#define SCSI_KCQUA_PFATHRESHOLDEXCEEDED 0x065dff /* Unit Attention - PFA threshold exceeded */ + +/* Write Protect KCQ values */ + +#define SCSI_KCQWP_COMMANDNOTALLOWED 0x072700 /* Write Protect - command not allowed */ + +/* Aborted Command KCQ values */ + +#define SCSI_KCQAC_NOADDITIONALSENSECODE 0x0b0000 /* Aborted Command - no additional sense code */ +#define SCSI_KCQAC_SYNCDATATRANSFERERROR 0x0b1b00 /* Aborted Command - sync data transfer error (extra ACK) */ +#define SCSI_KCQAC_UNSUPPORTEDLUN 0x0b2500 /* Aborted Command - unsupported LUN */ +#define SCSI_KCQAC_ECHOBUFFEROVERWRITTEN 0x0b3f0f /* Aborted Command - echo buffer overwritten */ +#define SCSI_KCQAC_MESSAGEREJECTERROR 0x0b4300 /* Aborted Command - message reject error */ +#define SCSI_KCQAC_INTERNALTARGETFAILURE 0x0b4400 /* Aborted Command - internal target failure */ +#define SCSI_KCQAC_SELECTIONFAILURE 0x0b4500 /* Aborted Command - Selection/Reselection failure */ +#define SCSI_KCQAC_SCSIPARITYERROR 0x0b4700 /* Aborted Command - SCSI parity error */ +#define SCSI_KCQAC_INITIATORDETECTEDERRORECEIVED 0x0b4800 /* Aborted Command - initiator-detected error message received */ +#define SCSI_KCQAC_ILLEGALMESSAGE 0x0b4900 /* Aborted Command - inappropriate/illegal message */ +#define SCSI_KCQAC_DATAPHASEERROR 0x0b4b00 /* Aborted Command - data phase error */ +#define SCSI_KCQAC_OVERLAPPEDCOMMANDSATTEMPTED 0x0b4e00 /* Aborted Command - overlapped commands attempted */ +#define SCSI_KCQAC_LOOPINITIALIZATION 0x0b4f00 /* Aborted Command - due to loop initialization */ + +/* Other KCQ values: */ + +#define SCSO_KCQOTHER_MISCOMPARE 0x0e1d00 /* Miscompare - during verify byte check operation */ + +/* SSCSI Status Codes *******************************************************/ + +#define SCSI_STATUS_OK 0x00 /* OK */ +#define SCSI_STATUS_CHECKCONDITION 0x02 /* Check condition */ +#define SCSI_STATUS_CONDITIONMET 0x04 /* Condition met */ +#define SCSI_STATUS_BUSY 0x08 /* Busy */ +#define SCSI_STATUS_INTERMEDIATE 0x10 /* Intermediate */ +#define SCSI_STATUS_DATAOVERUNDERRUN 0x12 /* Data Under/Over Run? */ +#define SCSI_STATUS_INTERMEDIATECONDITIONMET 0x14 /* Intermediate - Condition met */ +#define SCSI_STATUS_RESERVATIONCONFLICT 0x18 /* Reservation conflict */ +#define SCSI_STATUS_COMMANDTERMINATED 0x22 /* Command terminated */ +#define SCSI_STATUS_QUEUEFULL 0x28 /* Queue (task set) full */ +#define SCSI_STATUS_ACAACTIVE 0x30 /* ACA active */ +#define SCSI_STATUS_TASKABORTED 0x40 /* Task aborted */ + +/* Definitions for selected SCSI commands ***********************************/ + +/* Inquiry */ + +#define SCSICMD_INQUIRYFLAGS_EVPD 0x01 /* Bit 0: EVPD */ + /* Bits 5-7: Peripheral Qualifier */ +#define SCSIRESP_INQUIRYPQ_CONNECTED 0x00 /* 000: Device is connected */ +#define SCSIRESP_INQUIRYPQ_NOTCONNECTED 0x20 /* 001: Device is NOT connected */ +#define SCSIRESP_INQUIRYPQ_NOTCAPABLE 0x60 /* 011: LUN not supported */ + /* Bits 0-4: Peripheral Device */ +#define SCSIRESP_INQUIRYPD_DIRECTACCESS 0x00 /* Direct-access block device */ +#define SCSIRESP_INQUIRYPD_SEQUENTIALACCESS 0x01 /* Sequential-access block device */ +#define SCSIRESP_INQUIRYPD_PRINTER 0x02 /* Printer device */ +#define SCSIRESP_INQUIRYPD_PROCESSOR 0x03 /* Processor device */ +#define SCSIRESP_INQUIRYPD_WRONCE 0x04 /* Write once device */ +#define SCSIRESP_INQUIRYPD_CDDVD 0x05 /* CD/DVD device */ +#define SCSIRESP_INQUIRYPD_SCANNER 0x06 /* Scanner device (obsolete) */ +#define SCSIRESP_INQUIRYPD_OPTICAL 0x07 /* Optical memory device */ +#define SCSIRESP_INQUIRYPD_MEDIUMCHANGER 0x08 /* Medium changer device (Jukebox) */ +#define SCSIRESP_INQUIRYPD_COMMUNICATIONS 0x09 /* Communications device (obsolete) */ +#define SCSIRESP_INQUIRYPD_STORAGEARRAY 0x0c /* Storage array controller device */ +#define SCSIRESP_INQUIRYPD_ENCLOSURESERVICES 0x0d /* Enclosure services device */ +#define SCSIRESP_INQUIRYPD_RBC 0x0e /* Simplified direct-access device */ +#define SCSIRESP_INQUIRYPD_OCRW 0x0f /* Optical reader/writer device */ +#define SCSIRESP_INQUIRYPD_BCC 0x10 /* Bridge controller commands */ +#define SCSIRESP_INQUIRYPD_OSD 0x11 /* Object-based storage device */ +#define SCSIRESP_INQUIRYPD_ADC 0x12 /* Automation/drive interface */ +#define SCSIRESP_INQUIRYPD_WKLU 0x1e /* Well-known logical unit */ +#define SCSIRESP_INQUIRYPD_UNKNOWN 0x1f /* Direct-access block device */ + +#define SCSIRESP_INQUIRYFLAGS1_RMB 0x80 /* Bit 7: RMB */ +#define SCSIRESP_INQUIRYFLAGS2_NORMACA 0x20 /* Bit 5: NormACA */ +#define SCSIRESP_INQUIRYFLAGS2_HISUP 0x10 /* Bit 4: HiSup */ +#define SCSIRESP_INQUIRYFLAGS2_FMTMASK 0x0f /* Bits 0-3: Response data format */ + +#define SCSIRESP_INQUIRYFLAGS3_SCCS 0x80 /* Bit 8: SCCS */ +#define SCSIRESP_INQUIRYFLAGS3_ACC 0x40 /* Bit 7: ACC */ +#define SCSIRESP_INQUIRYFLAGS3_TPGSMASK 0x30 /* Bits 4-5: TPGS */ +#define SCSIRESP_INQUIRYFLAGS3_3PC 0x08 /* Bit 3: 3PC */ +#define SCSIRESP_INQUIRYFLAGS3_PROTECT 0x01 /* Bit 0: Protect */ + +#define SCSIRESP_INQUIRYFLAGS4_BQUE 0x80 /* Bit 7: BQue */ +#define SCSIRESP_INQUIRYFLAGS4_ENCSERV 0x40 /* Bit 6: EncServ */ +#define SCSIRESP_INQUIRYFLAGS4_VS 0x20 /* Bit 5: VS */ +#define SCSIRESP_INQUIRYFLAGS4_MULTIP 0x10 /* Bit 4: MultIP */ +#define SCSIRESP_INQUIRYFLAGS4_MCHNGR 0x08 /* Bit 3: MChngr */ +#define SCSIRESP_INQUIRYFLAGS4_ADDR16 0x01 /* Bit 0: Addr16 */ + +#define SCSIRESP_INQUIRYFLAGS5_WBUS16 0x20 /* Bit 5: WBus16 */ +#define SCSIRESP_INQUIRYFLAGS5_SYNC 0x10 /* Bit 4: SYNC */ +#define SCSIRESP_INQUIRYFLAGS5_LINKED 0x08 /* Bit 3: LINKED */ +#define SCSIRESP_INQUIRYFLAGS5_CMDQUEUE 0x02 /* Bit 1: CmdQue */ +#define SCSIRESP_INQUIRYFLAGS5_VS 0x01 /* Bit 0: VS */ + +#define SCSIRESP_INQUIRYFLAGS6_CLOCKINGMASK 0xc0 /* Bits 2-3: Clocking */ +#define SCSIRESP_INQUIRYFLAGS6_QAS 0x02 /* Bit 1: QAS */ +#define SCSIRESP_INQUIRYFLAGS6_IUS 0x01 /* Bit 0: IUS */ + +/* Sense data */ +/* Sense data response codes */ + +#define SCSIRESP_SENSEDATA_CURRENTFIXED 0x70 /* Byte 1 is always the response code */ +#define SCSIRESP_SENSEDATA_DEFERREDFIXED 0x71 +#define SCSIRESP_SENSEDATA_CURRENTDESC 0x72 +#define SCSIRESP_SENSEDATA_DEFERREDDESC 0x73 + +#define SCSIRESP_SENSEDATA_RESPVALID 0x80 + +/* Fixed sense data flags */ + +#define SCSIRESP_SENSEDATA_FILEMARK 0x80 /* Bit 7: FileMark */ +#define SCSIRESP_SENSEDATA_EOM 0x40 /* Bit 6: EOM */ +#define SCSIRESP_SENSEDATA_ILI 0x20 /* Bit 5: ILI */ +#define SCSIRESP_SENSEDATA_SENSEKEYMASK 0x0f /* Bits 0-3: Sense key */ +#define SCSIRESP_SENSEDATA_NOSENSE 0x00 /* Nothing to be reported */ +#define SCSIRESP_SENSEDATA_RECOVEREDERROR 0x01 /* Successful after recovery action */ +#define SCSIRESP_SENSEDATA_NOTREADY 0x02 /* Logical unit is not accessible */ +#define SCSIRESP_SENSEDATA_MEDIUMERROR 0x03 /* Error posssibly caused by flaw in medium */ +#define SCSIRESP_SENSEDATA_HARDWAREERROR 0x04 /* Non-recoverable hardware error */ +#define SCSIRESP_SENSEDATA_ILLEGALREQUEST 0x05 /* Error in recived request */ +#define SCSIRESP_SENSEDATA_UNITATTENTION 0x06 /* Unit attention condition */ +#define SCSIRESP_SENSEDATA_DATAPROTECT 0x07 /* Action failed, medium protected */ +#define SCSIRESP_SENSEDATA_BLANKCHECK 0x08 /* Encountered blank media */ +#define SCSIRESP_SENSEDATA_VENDORSPECIFIC 0x09 /* Vendor specific condition */ +#define SCSIRESP_SENSEDATA_ABORTEDCOMMAND 0x0b /* Command was aborted */ + +#define SCSIRESP_SENSEDATA_KEYVALID 0x80 /* Sense-specific data valid */ + +/* Mode Select 6 */ + +#define SCSICMD_MODESELECT6_PF 0x10 /* Bit 4: PF */ +#define SCSICMD_MODESELECT6_SP 0x01 /* Bit 0: SP */ + +/* Mode Sense 6 */ + +#define SCSICMD_MODESENSE6_DBD 0x08 /* Bit 3: PF */ + +#define SCSICMD_MODESENSE_PCMASK 0xc0 /* Bits 6-7: Page control (PC) */ +#define SCSICMD_MODESENSE_PCCURRENT 0x00 /* Current values */ +#define SCSICMD_MODESENSE_PCCHANGEABLE 0x40 /* Changeable values */ +#define SCSICMD_MODESENSE_PCDEFAULT 0x80 /* Default values */ +#define SCSICMD_MODESENSE_PCSAVED 0xc0 /* Saved values */ +#define SCSICMD_MODESENSE_PGCODEMASK 0x3f /* Bits 0-5: Page code */ + +#define SCSICMD_MODESENSE6_PCDEFAULT 0x80 /* Default values */ + /* Direct-access device page codes */ +#define SCSIRESP_MODESENSE_PGCCODE_VENDOR 0x00 /* Vendor-specific */ +#define SCSIRESP_MODESENSE_PGCCODE_RWERROR 0x01 /* Read/Write error recovery mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_RECONNECT 0x02 /* Disconnect-reconnect mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_FORMATDEV 0x03 /* Format device mode page (obsolete) */ +#define SCSIRESP_MODESENSE_PGCCODE_RIGID 0x04 /* Rigid disk geometry mode page (obsolete) */ +#define SCSIRESP_MODESENSE_PGCCODE_FLEXIBLE 0x05 /* Flexible disk geometry mode page (obsolete) */ +#define SCSIRESP_MODESENSE_PGCCODE_VERIFY 0x07 /* Verify error recovery mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_CACHING 0x08 /* Caching mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_CONTROL 0x0a /* Control mode page (0x0a/0x00) */ +#define SCSIRESP_MODESENSE_PGCCODE_CONTROLEXT 0x0a /* Control extension mode page (0x0a/0x01) */ +#define SCSIRESP_MODESENSE_PGCCODE_MEDIUMTYPES 0x0b /* Medum types supported mode page (obsolete) */ +#define SCSIRESP_MODESENSE_PGCCODE_NP 0x0c /* Notch and partition mode page (obsolete) */ +#define SCSIRESP_MODESENSE_PGCCODE_XOR 0x10 /* XOR control mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_ES 0x14 /* Enclosure services mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_PSLUN 0x18 /* Protocol-specific LUN mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_PSPORT 0x19 /* Protocol-specific port mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_POWER 0x1a /* Power condition mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_IE 0x1c /* Informational exceptions control mode page (0x1c/0x00) */ +#define SCSIRESP_MODESENSE_PGCCODE_BC 0x1c /* Background control mode page (0x1c/0x01) */ +#define SCSIRESP_MODESENSE_PGCCODE_RETURNALL 0x3f /* Return all mode pages */ + /* Direct-access caching mode page */ +#define SCSIRESP_CACHINGMODEPG_PS 0x80 /* Byte 0, Bit 7: PS */ +#define SCSIRESP_CACHINGMODEPG_SPF 0x60 /* Byte 0, Bit 6: SPF */ +#define SCSIRESP_CACHINGMODEPG_IC 0x80 /* Byte 2, Bit 7: IC */ +#define SCSIRESP_CACHINGMODEPG_ABPF 0x40 /* Byte 2, Bit 6: ABPF */ +#define SCSIRESP_CACHINGMODEPG_CAP 0x20 /* Byte 2, Bit 5: CAP */ +#define SCSIRESP_CACHINGMODEPG_DISC 0x10 /* Byte 2, Bit 4: DISC */ +#define SCSIRESP_CACHINGMODEPG_SIZE 0x08 /* Byte 2, Bit 3: SIZE */ +#define SCSIRESP_CACHINGMODEPG_WCE 0x04 /* Byte 2, Bit 2: Write cache enable (WCE) */ +#define SCSIRESP_CACHINGMODEPG_MF 0x02 /* Byte 2, Bit 1: MF */ +#define SCSIRESP_CACHINGMODEPG_RCD 0x01 /* Byte 2, Bit 0: Read cache disable (RCD) */ + +#define SCSIRESP_MODEPARMHDR_DAPARM_WP 0x80 /* Bit 7: WP (Direct-access block devices only) */ +#define SCSIRESP_MODEPARMHDR_DAPARM_DBPFUA 0x10 /* Bit 4: DBOFUA (Direct-access block devices only) */ + +#define SCSIRESP_PAGEFMT_PS 0x80 /* Bit 7: PS */ +#define SCSIRESP_PAGEFMT_SPF 0x40 /* Bit 6: SPF */ +#define SCSIRESP_PAGEFMT_PGCODEMASK 0x3f /* Bits 0-5: Page code */ + +/* Prevent / Allow Medium Removal */ + +#define SCSICMD_PREVENTMEDIUMREMOVAL_TRANSPORT 0x01 /* Removal prohibited from data transport */ +#define SCSICMD_PREVENTMEDIUMREMOVAL_MCHANGER 0x02 /* Removal prohibited from medium changer */ + +/* Read format capacities */ + +#define SCIRESP_RDFMTCAPACITIES_UNFORMATED 0x01 /* Unformatted media */ +#define SCIRESP_RDFMTCAPACITIES_FORMATED 0x02 /* Formatted media */ +#define SCIRESP_RDFMTCAPACITIES_NOMEDIA 0x03 /* No media */ + +/* Read 6 */ + +#define SCSICMD_READ6_MSLBAMASK 0x1f + +/* Write 6 */ + +#define SCSICMD_WRITE6_MSLBAMASK 0x1f + +/* Mode Select 10 */ + +#define SCSICMD_MODESELECT10_PF 0x10 /* Bit 4: PF */ +#define SCSICMD_MODESELECT10_SP 0x01 /* Bit 0: SP */ + +/* Mode Sense 10 */ + +#define SCSICMD_MODESENSE10_LLBAA 0x10 /* Bit 4: LLBAA */ +#define SCSICMD_MODESENSE10_DBD 0x08 /* Bit 3: PF */ + +/* Read 10 */ + +#define SCSICMD_READ10FLAGS_RDPROTECTMASK 0xe0 +#define SCSICMD_READ10FLAGS_DPO 0x10 /* Disable Page Out */ +#define SCSICMD_READ10FLAGS_FUA 0x08 +#define SCSICMD_READ10FLAGS_FUANV 0x02 + +/* Write 10 */ + +#define SCSICMD_WRITE10FLAGS_WRPROTECTMASK 0xe0 +#define SCSICMD_WRITE10FLAGS_DPO 0x10 /* Disable Page Out */ +#define SCSICMD_WRITE10FLAGS_FUA 0x08 +#define SCSICMD_WRITE10FLAGS_FUANV 0x02 + +/* Verify 10 */ + +#define SCSICMD_VERIFY10_VRPROTECTMASK 0xe0 /* Byte 1: Bits 5-7: VRPROTECT */ +#define SCSICMD_VERIFY10_DPO 0x10 /* Byte 1: Bit 4: Disable Page Out (DPO) */ +#define SCSICMD_VERIFY10_BYTCHK 0x02 /* Byte 1: Bit 2: BytChk */ + +/* Read 12 */ + +#define SCSICMD_READ12FLAGS_RDPROTECTMASK 0xe0 +#define SCSICMD_READ12FLAGS_DPO 0x10 /* Disable Page Out */ +#define SCSICMD_READ12FLAGS_FUA 0x08 +#define SCSICMD_READ12FLAGS_FUANV 0x02 + +/* Write 12 */ + +#define SCSICMD_WRITE12FLAGS_WRPROTECTMASK 0xe0 +#define SCSICMD_WRITE12FLAGS_DPO 0x10 /* Disable Page Out */ +#define SCSICMD_WRITE12FLAGS_FUA 0x08 +#define SCSICMD_WRITE12FLAGS_FUANV 0x02 + +/* Verify 12 */ + +#define SCSICMD_VERIFY12_VRPROTECTMASK 0xe0 /* Byte 1: Bits 5-7: VRPROTECT */ +#define SCSICMD_VERIFY12_DPO 0x10 /* Byte 1: Bit 4: Disable Page Out (DPO) */ +#define SCSICMD_VERIFY12_BYTCHK 0x02 /* Byte 1: Bit 2: BytChk */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Format structures for selected SCSI primary commands */ + +#define SCSICMD_TESTUNITREADY_SIZEOF 6 + +struct scsicmd_requestsense_s +{ + uint8_t opcode; /* 0: 0x03 */ + uint8_t flags; /* 1: See SCSICMD_REQUESTSENSE_FLAGS_* */ + uint8_t reserved[2]; /* 2-3: Reserved */ + uint8_t alloclen; /* 4: Allocation length */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_REQUESTSENSE_SIZEOF 6 +#define SCSICMD_REQUESTSENSE_MSSIZEOF 12 /* MS-Windows REQUEST SENSE with cbw->cdblen == 12 */ + +struct scsiresp_fixedsensedata_s +{ + uint8_t code; /* 0: Response code See SCSIRESP_SENSEDATA_*FIXED defns */ + uint8_t obsolete; /* 1: */ + uint8_t flags; /* 2: See SCSIRESP_SENSEDATA_* definitions */ + uint8_t info[4]; /* 3-6: Information */ + uint8_t len; /* 7: Additional length */ + uint8_t cmdinfo[4]; /* 8-11: Command-specific information */ + uint8_t code2; /* 12: Additional sense code */ + uint8_t qual2; /* 13: Additional sense code qualifier */ + uint8_t fru; /* 14: Field replacement unit code */ + uint8_t key[3]; /* 15-17: Sense key specific */ + /* 18-: Additional bytes may follow */ +}; +#define SCSIRESP_FIXEDSENSEDATA_SIZEOF 18 /* Minimum size */ + +struct scscicmd_inquiry_s +{ + uint8_t opcode; /* 0: 0x12 */ + uint8_t flags; /* 1: See SCSICMD_INQUIRY_FLAGS_* */ + uint8_t pagecode; /* 2: Page code */ + uint8_t alloclen[2]; /* 3-4: Allocation length */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_INQUIRY_SIZEOF 6 + +struct scsiresp_inquiry_s +{ + /* Mandatory */ + + uint8_t qualtype; /* 0: Bits 5-7: Peripheral qualifier; Bits 0-4: Peripheral device type */ + uint8_t flags1; /* 1: See SCSIRESP_INQUIRY_FLAGS1_* */ + uint8_t version; /* 2: Version */ + uint8_t flags2; /* 3: See SCSIRESP_INQUIRY_FLAGS2_* */ + uint8_t len; /* 4: Additional length */ + uint8_t flags3; /* 5: See SCSIRESP_INQUIRY_FLAGS3_* */ + uint8_t flags4; /* 6: See SCSIRESP_INQUIRY_FLAGS4_* */ + uint8_t flags5; /* 7: See SCSIRESP_INQUIRY_FLAGS5_* */ + uint8_t vendorid[8]; /* 8-15: T10 Vendor Identification */ + uint8_t productid[16]; /* 16-31: Product Identification */ + uint8_t revision[4]; /* 32-35: Product Revision Level */ + + /* Optional */ + + uint8_t vendor[20]; /* 36-55: Vendor specific */ + uint8_t flags6; /* 56: See SCSIRESP_INQUIRY_FLAGS6_* */ + uint8_t reserved1; /* 57: Reserved */ + uint8_t version1[2]; /* 58-59: Version Descriptor 1 */ + uint8_t version2[2]; /* 60-61: Version Descriptor 2 */ + uint8_t version3[2]; /* 62-63: Version Descriptor 3 */ + uint8_t version4[2]; /* 64-65: Version Descriptor 4 */ + uint8_t version5[2]; /* 66-67: Version Descriptor 5 */ + uint8_t version6[2]; /* 68-69: Version Descriptor 6 */ + uint8_t version7[2]; /* 70-71: Version Descriptor 7 */ + uint8_t version8[2]; /* 72-73: Version Descriptor 8 */ + uint8_t reserved2[22]; /* 74-95: Reserved */ + /* 96-: Vendor-specific parameters may follow */ +}; +#define SCSIRESP_INQUIRY_SIZEOF 36 /* Minimum size */ + +struct scsicmd_modeselect6_s +{ + uint8_t opcode; /* 0x15 */ + uint8_t flags; /* 1: See SCSICMD_MODESELECT6_FLAGS_* */ + uint8_t reserved[2]; /* 2-3: Reserved */ + uint8_t plen; /* 4: Parameter list length */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_MODESELECT6_SIZEOF 6 + +struct scsicmd_modesense6_s +{ + uint8_t opcode; /* 0x1a */ + uint8_t flags; /* 1: See SCSICMD_MODESENSE6_FLAGS_* */ + uint8_t pcpgcode; /* 2: Bits 6-7: PC, bits 0-5: page code */ + uint8_t subpgcode; /* 3: subpage code */ + uint8_t alloclen; /* 4: Allocation length */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_MODESENSE6_SIZEOF 6 + +struct scsiresp_modeparameterhdr6_s +{ + uint8_t mdlen; /* 0: Mode data length */ + uint8_t type; /* 1: Medium type */ + uint8_t param; /* 2: Device-specific parameter */ + uint8_t bdlen; /* 3: Block descriptor length */ +}; +#define SCSIRESP_MODEPARAMETERHDR6_SIZEOF 4 + +struct scsiresp_blockdesc_s +{ + uint8_t density; /* 0: density code */ + uint8_t nblocks[3]; /* 1-3: Number of blocks */ + uint8_t reserved; /* 4: reserved */ + uint8_t blklen[3]; /* 5-7: Block len */ +}; +#define SCSIRESP_BLOCKDESC_SIZEOF 8 + +struct scsiresp_pageformat_s +{ + uint8_t pgcode; /* 0: See SCSIRESP_PAGEFMT_* definitions */ + uint8_t pglen; /* 1: Page length (n-1) */ + uint8_t parms[1]; /* 2-n: Mode parameters */ +}; + +struct scsiresp_subpageformat_s +{ + uint8_t pgcode; /* 0: See SCSIRESP_PAGEFMT_* definitions */ + uint8_t subpgcode; /* 1: sub-page code */ + uint8_t pglen[2]; /* 2-3: Page length (n-3) */ + uint8_t parms[1]; /* 4-n: Mode parameters */ +}; + +struct scsiresp_cachingmodepage_s +{ + uint8_t pgcode; /* 0: Bit 7: PS; Bit 6: SPF, Bits 0-5: page code == 8 */ + uint8_t len; /* 1: Page length (18) */ + uint8_t flags1; /* 2: See SCSIRESP_CACHINGMODEPG_* definitions */ + uint8_t priority; /* 3: Bits 4-7: Demand read retention priority; Bits 0-3: Write retention priority */ + uint8_t dpflen[2]; /* 4-5: Disable prefetch transfer length */ + uint8_t minpf[2]; /* 6-7: Minimum pre-fetch */ + uint8_t maxpf[2]; /* 8-9: Maximum pre-fetch */ + uint8_t maxpfc[2]; /* 10-11: Maximum pref-fetch ceiling */ + uint8_t flags2; /* 12: See SCSIRESP_CACHINGMODEPG_* definitions */ + uint8_t nsegments; /* 13: Number of cache segments */ + uint8_t segsize[2]; /* 14-15: Cache segment size */ + uint8_t reserved; /* 16: Reserved */ + uint8_t obsolete[3]; /* 17-19: Obsolete */ +}; + +/* Format structures for selected SCSI block commands */ + +struct scsicmd_read6_s +{ + uint8_t opcode; /* 0: 0x08 */ + uint8_t mslba; /* 1: Bits 5-7: reserved; Bits 0-6: MS Logical Block Address (LBA) */ + uint8_t lslba[2]; /* 2-3: LS Logical Block Address (LBA) */ + uint8_t xfrlen; /* 4: Transfer length (in contiguous logical blocks)*/ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_READ6_SIZEOF 6 + +struct scsicmd_write6_s +{ + uint8_t opcode; /* 0: 0x0a */ + uint8_t mslba; /* 1: Bits 5-7: reserved; Bits 0-6: MS Logical Block Address (LBA) */ + uint8_t lslba[2]; /* 2-3: LS Logical Block Address (LBA) */ + uint8_t xfrlen; /* 4: Transfer length (in contiguous logical blocks) */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_WRITE6_SIZEOF 6 + +struct scsicmd_startstopunit_s +{ + uint8_t opcode; /* 0: 0x1b */ + uint8_t immed; /* 1: Bits 2-7: Reserved, Bit 0: Immed */ + uint8_t reserved; /* 2: reserved */ + uint8_t pcm; /* 3: Bits 4-7: Reserved, Bits 0-3: Power condition modifier */ + uint8_t pc; /* 4: Bits 4-7: Power condition, Bit 2: NO_FLUSH, Bit 1: LOEJ, Bit 0: START */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_STARTSTOPUNIT_SIZEOF 6 + +struct scsicmd_preventmediumremoval_s +{ + uint8_t opcode; /* 0: 0x1e */ + uint8_t reserved[3]; /* 1-3: Reserved */ + uint8_t prevent; /* 4: Bits 2-7: Reserved, Bits 0:1: prevent */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_PREVENTMEDIUMREMOVAL_SIZEOF 6 + +struct scsicmd_readformatcapcacities_s +{ + uint8_t opcode; /* 0: 0x23 */ + uint8_t reserved[6]; /* 1-6: Reserved */ + uint8_t alloclen[2]; /* 7-8: Allocation length */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_READFORMATCAPACITIES_SIZEOF 10 + +struct scsiresp_readformatcapacities_s +{ + /* Current capacity header */ + + uint8_t reserved[3]; /* 0-2: Reserved */ + uint8_t listlen; /* 3: Capacity list length */ + + /* Current/Maximum Capacity Descriptor (actually a separate structure) */ + + uint8_t nblocks[4]; /* 4-7: Number of blocks */ + uint8_t type; /* 8: Bits 2-7: Reserved, Bits 0-1: Descriptor type */ + uint8_t blocklen[3]; /* 9-11: Block length */ +}; +#define SCSIRESP_READFORMATCAPACITIES_SIZEOF 12 +#define SCSIRESP_CURRCAPACITYDESC_SIZEOF 8 + +struct scsiresp_formattedcapacitydesc_s +{ + uint8_t nblocks[4]; /* 0-3: Number of blocks */ + uint8_t type; /* 4: Bits 2-7: Type, bits 0-1, reserved */ + uint8_t param[3]; /* 5-7: Type dependent parameter */ +}; +#define SCSIRESP_FORMATTEDCAPACITYDESC_SIZEOF 8 + +struct scsicmd_readcapacity10_s +{ + uint8_t opcode; /* 0: 0x25 */ + uint8_t reserved1; /* 1: Bits 1-7: Reserved, Bit 0: Obsolete */ + uint8_t lba[4]; /* 2-5: Logical block address (LBA) */ + uint8_t reserved2[2]; /* 6-7: Reserved */ + uint8_t pmi; /* 8: Bits 1-7 Reserved; Bit 0: PMI */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_READCAPACITY10_SIZEOF 10 + +struct scsiresp_readcapacity10_s +{ + uint8_t lba[4]; /* 0-3: Returned logical block address (LBA) */ + uint8_t blklen[4]; /* 4-7: Logical block length (in bytes) */ +}; +#define SCSIRESP_READCAPACITY10_SIZEOF 8 + +struct scsicmd_read10_s +{ + uint8_t opcode; /* 0: 0x28 */ + uint8_t flags; /* 1: See SCSICMD_READ10FLAGS_* */ + uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */ + uint8_t groupno; /* 6: Bits 5-7: reserved; Bits 0-6: group number */ + uint8_t xfrlen[2]; /* 7-8: Transfer length (in contiguous logical blocks) */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_READ10_SIZEOF 10 + +struct scsicmd_write10_s +{ + uint8_t opcode; /* 0: 0x2a */ + uint8_t flags; /* 1: See SCSICMD_WRITE10FLAGS_* */ + uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */ + uint8_t groupno; /* 6: Bits 5-7: reserved; Bits 0-6: group number */ + uint8_t xfrlen[2]; /* 7-8: Transfer length (in contiguous logical blocks) */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_WRITE10_SIZEOF 10 + +struct scsicmd_verify10_s +{ + uint8_t opcode; /* 0: 0x2f */ + uint8_t flags; /* 1: See SCSICMD_VERIFY10_* definitions */ + uint8_t lba[4]; /* 2-5: Logical block address (LBA) */ + uint8_t groupno; /* 6: Bit 7: restricted; Bits 5-6: Reserved, Bits 0-4: Group number */ + uint8_t len[2]; /* 7-8: Verification length (in blocks) */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_VERIFY10_SIZEOF 10 + +struct scsicmd_synchronizecache10_s +{ + uint8_t opcode; /* 0: 0x35 */ + uint8_t flags; /* 1: See SCSICMD_SYNCHRONIZECACHE10_* definitions */ + uint8_t lba[4]; /* 2-5: Logical block address (LBA) */ + uint8_t groupno; /* 6: Bit 7: restricted; Bits 5-6: Reserved, Bits 0-4: Group number */ + uint8_t len[2]; /* 7-8: Number of logical blocks */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_SYNCHRONIZECACHE10_SIZEOF 10 + +struct scsicmd_modeselect10_s +{ + uint8_t opcode; /* 0: 0x55 */ + uint8_t flags; /* 1: See SCSICMD_MODESELECT10_FLAGS_* */ + uint8_t reserved[5]; /* 2-6: Reserved */ + uint8_t parmlen[2]; /* 7-8: Parameter list length */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_MODESELECT10_SIZEOF 10 + +struct scsiresp_modeparameterhdr10_s +{ + uint8_t mdlen[2]; /* 0-1: Mode data length */ + uint8_t type; /* 2: Medium type */ + uint8_t param; /* 3: Device-specific parameter */ + uint8_t reserved[2]; /* 4-5: reserved */ + uint8_t bdlen[2]; /* 6-7: Block descriptor length */ +}; +#define SCSIRESP_MODEPARAMETERHDR10_SIZEOF 8 + +struct scsicmd_modesense10_s +{ + uint8_t opcode; /* O: 0x5a */ + uint8_t flags; /* 1: See SCSICMD_MODESENSE10_FLAGS_* */ + uint8_t pcpgcode; /* 2: Bits 6-7: PC, bits 0-5: page code */ + uint8_t subpgcode; /* 3: subpage code */ + uint8_t reserved[3]; /* 4-6: reserved */ + uint8_t alloclen[2]; /* 7-8: Allocation length */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_MODESENSE10_SIZEOF 10 + +struct scsicmd_readcapacity16_s +{ + uint8_t opcode; /* 0: 0x9e */ + uint8_t action; /* 1: Bits 5-7: Reserved, Bits 0-4: Service action */ + uint8_t lba[8]; /* 2-9: Logical block address (LBA) */ + uint8_t len[4]; /* 10-13: Allocation length */ + uint8_t reserved; /* 14: Reserved */ + uint8_t control; /* 15: Control */ +}; +#define SCSICMD_READCAPACITY16_SIZEOF 16 + +struct scsicmd_read12_s +{ + uint8_t opcode; /* 0: 0xa8 */ + uint8_t flags; /* 1: See SCSICMD_READ12FLAGS_* */ + uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */ + uint8_t xfrlen[4]; /* 6-9: Transfer length (in contiguous logical blocks) */ + uint8_t groupno; /* 10: Bit 7: restricted; Bits 5-6: reserved; Bits 0-6: group number */ + uint8_t control; /* 11: Control */ +}; +#define SCSICMD_READ12_SIZEOF 12 + +struct scsicmd_write12_s +{ + uint8_t opcode; /* 0: 0xaa */ + uint8_t flags; /* 1: See SCSICMD_WRITE12FLAGS_* */ + uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */ + uint8_t xfrlen[4]; /* 6-9: Transfer length (in contiguous logical blocks) */ + uint8_t groupno; /* 10: Bit 7: restricted; Bits 5-6: reserved; Bits 0-6: group number */ + uint8_t control; /* 11: Control */ +}; +#define SCSICMD_WRITE12_SIZEOF 12 + +struct scsicmd_verify12_s +{ + uint8_t opcode; /* 0: 0xaf */ + uint8_t flags; /* 1: See SCSICMD_VERIFY12_* definitions */ + uint8_t lba[4]; /* 2-5: Logical block address (LBA) */ + uint8_t len[4]; /* 6-9: Verification length */ + uint8_t groupno; /* 10: Bit 7: restricted; Bits 5-6: Reserved, Bits 0-4: Group number */ + uint8_t control; /* 11: Control */ +}; +#define SCSICMD_VERIFY12_SIZEOF 12 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_SCSI_H */ diff --git a/nuttx/include/nuttx/sdio.h b/nuttx/include/nuttx/sdio.h new file mode 100644 index 0000000000..10612db85f --- /dev/null +++ b/nuttx/include/nuttx/sdio.h @@ -0,0 +1,855 @@ +/**************************************************************************** + * include/nuttx/sdio.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SDIO_H +#define __INCLUDE_NUTTX_SDIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* SDIO events needed by the driver + * + * Wait events are used for event-waiting by SDIO_WAITENABLE and SDIO_EVENTWAIT + */ + +#define SDIOWAIT_CMDDONE (1 << 0) /* Bit 0: Command complete */ +#define SDIOWAIT_RESPONSEDONE (1 << 1) /* Bit 1: Response to command available */ +#define SDIOWAIT_TRANSFERDONE (1 << 2) /* Bit 2: Data transfer/DMA done */ +#define SDIOWAIT_TIMEOUT (1 << 3) /* Bit 3: Timeout */ +#define SDIOWAIT_ERROR (1 << 4) /* Bit 4: Some other error occurred */ + +#define SDIOWAIT_ALLEVENTS 0x1f + +/* Media events are used for enable/disable registered event callbacks */ + +#define SDIOMEDIA_EJECTED (1 << 0) /* Bit 0: Mmedia removed */ +#define SDIOMEDIA_INSERTED (1 << 1) /* Bit 1: Media inserted */ + +/* Commands are bit-encoded to provide as much information to the SDIO driver as + * possible in 32-bits. The encoding is as follows: + * + * ---- ---- ---- ---- ---T TTRR RRCC CCCC + * + * CCCCCC - Bits 0-5: 6-bit command index (Range 9-63) + * RRRR - Bits 6-9: 4-bit response code (R1, R1B, R2-5) + * TTT - Bits 10-12: Data transfer type + */ + +/* MMC, SD, SDIO Common Indices */ + +#define MMCSD_CMDIDX_SHIFT (0) +#define MMCSD_CMDIDX_MASK (0x3f << MMCSD_CMDIDX_SHIFT) +# define MMCSD_CMDIDX0 0 /* GO_IDLE_STATE: Resets all cards to idle state + * -Broadcast, no response */ +# define MMC_CMDIDX1 1 /* SEND_OP_COND: Sends capacity support information + * -Broadcast, R3 response, 31:0=OCR */ +# define MMCSD_CMDIDX2 2 /* ALL_SEND_CID + * -Broadcast, R2 response */ +# define MMC_CMDIDX3 3 /* SET_RELATIVE_ADDR + * -Addressed Command, R1 response 31:16=RCA */ +# define SD_CMDIDX3 3 /* SEND_RELATIVE_ADDR + * -Addressed Command, R6 response 31:16=RCA */ +# define MMCSD_CMDIDX4 4 /* SET_DSR + * -Broadcast command, no response 31:16=RCA */ +# define SDIO_CMDIDX5 5 /* SDIO_SEND_OP_COND + * -Addressed Command, R4 response 47:16=IO_OCR */ +# define MMCSD_CMDIDX6 6 /* HS_SWITCH: Checks switchable function */ +# define MMCSD_CMDIDX7 7 /* SELECT/DESELECT CARD + * -Addressed Command, R1 response 31:16=RCA */ +# define SD_CMDIDX8 8 /* IF_COND: Sends SD Memory Card interface condition + * R7 response */ +# define MMCSD_CMDIDX9 9 /* SEND_CSD: Asks card to send its card specific data (CSD) + * -Addressed Command, R2 response 31:16=RCA */ +# define MMCSD_CMDIDX10 10 /* SEND_CID: Asks card to send its card identification (CID) + * -Addressed Command, R2 response 31:16=RCA */ +# define MMC_CMDIDX11 11 /* READ_DAT_UNTIL_STOP + * -Addressed data transfer command, R1 response 31:0=DADR */ +# define MMCSD_CMDIDX12 12 /* STOP_TRANSMISSION: Forces the card to stop transmission + * -Addressed Command, R1b response */ +# define MMCSD_CMDIDX13 13 /* SEND_STATUS: Asks card to send its status register + * -Addressed Command, R1 response 31:16=RCA */ +# define MMCSD_CMDIDX14 14 /* HS_BUSTEST_READ: */ +# define MMCSD_CMDIDX15 15 /* GO_INACTIVE_STATE + * Addressed Command, Response 31:16=RCA */ +# define MMCSD_CMDIDX16 16 /* SET_BLOCKLEN: Sets a block length (in bytes) + * -Addressed Command, R1 response 31:0=BLEN */ +# define MMCSD_CMDIDX17 17 /* READ_SINGLE_BLOCK: Reads a block of the selected size + * -Addressed data transfer command, R1 response 31:0=DADR */ +# define MMCSD_CMDIDX18 18 /* READ_MULTIPLE_BLOCK: Continuously transfers blocks from card to host + * -Addressed data transfer command, R1 response 31:0=DADR */ +# define MMCSD_CMDIDX19 19 /* HS_BUSTEST_WRITE: */ +# define MMC_CMDIDX20 20 /* WRITE_DAT_UNTIL_STOP: (MMC) + * -Addressed data transfer command, R1 response 31:0=DADR R1 */ +# define MMC_CMDIDX23 23 /* SET_BLOCK_COUNT: (MMC) + * -Addressed command, R1 response 31:0=DADR */ +# define MMCSD_CMDIDX24 24 /* WRITE_BLOCK: Writes a block of the selected size + * -Addressed data transfer command, R1 response 31:0=DADR */ +# define MMCSD_CMDIDX25 25 /* WRITE_MULTIPLE_BLOCK: Continuously writes blocks of data + * -Addressed data transfer command, R1 response 31:0=DADR */ +# define MMCSD_CMDIDX26 26 /* PROGRAM_CID: (Manufacturers only) + * -Addressed data transfer command, R1 response */ +# define MMCSD_CMDIDX27 27 /* PROGRAM_CSD: Set programmable bits of the CSD + * -Addressed data transfer command, R1 response */ +# define MMCSD_CMDIDX28 28 /* SET_WRITE_PROT: Sets the write protection bit of group + * -Addressed Command, R1b response 31:0=DADR */ +# define MMCSD_CMDIDX29 29 /* CLR_WRITE_PROT: Clears the write protection bit of group + * -Addressed Command, R1b response 31:0=DADR */ +# define MMCSD_CMDIDX30 30 /* SEND_WRITE_PROT: Asks card to send state of write protection bits + * -Addressed data transfer command, R1 response 31:0=WADR */ +# define SD_CMDIDX32 32 /* ERASE_GRP_START: Sets address of first block to erase (SD) + * -Addressed Command, R1 response 31:0=DADR */ +# define SD_CMDIDX33 33 /* ERASE_GRP_END: Sets address of last block to erase (SD) + * -Addressed Command, R1 response 31:0=DADR */ +# define MMC_CMDIDX34 34 /* UNTAG_SECTOR: (MMC) + * -Addressed Command, R1 response 31:0=DADR */ +# define MMC_CMDIDX35 35 /* TAG_ERASE_GROUP_START: Sets address of first block to erase (MMC) + * -Addressed Command, R1 response 31:0=DADR */ +# define MMC_CMDIDX36 36 /* TAG_ERASE_GROUP_END: Sets address of last block to erase (MMC) + * -Addressed Command, R1 response 31:0=DADR */ +# define MMC_CMDIDX37 37 /* UNTAG_ERASE_GROUP: (MMC) + * -Addressed Command, R1 response 31:0=DADR */ +# define MMCSD_CMDIDX38 38 /* ERASE: Erases all previously selected write blocks + * -Addressed Command, R1b response */ +# define MMC_CMDIDX39 39 /* FAST_IO: (MMC) + * -Addressed Command, R4 response (Complex) */ +# define MMC_CMDIDX40 40 /* GO_IRQ_STATE: (MMC) + * -Broadcast command, R5 response */ +# define MMCSD_CMDIDX42 42 /* LOCK_UNLOCK: Used to Set/Reset the Password or lock/unlock card + * -Addressed data transfer command, R1b response */ +# define SD_CMDIDX55 55 /* APP_CMD: Tells card that the next command is an application specific command + * - Addressed Command, R1 response 31:16=RCA */ +# define MMCSD_CMDIDX56 56 /* GEN_CMD: Used transfer a block to or get block from card + * -Addressed data transfer command, R1 Response */ + +/* SD/SDIO APP commands (must be preceded by CMD55) */ + +# define SD_ACMDIDX6 6 /* SET_BUS_WIDTH: + * -Addressed Command, R1 response 1:0=BUSW */ +# define SD_ACMDIDX13 13 /* SD_STATUS: Send the SD Status + * -Addressed data transfer command, R1 response */ +# define SD_ACMDIDX18 18 /* SECURE_READ_MULTIPLE_BLOCK: */ +# define SD_ACMDIDX22 22 /* SEND_NUM_WR_BLOCKS: Send number of the errorfree blocks + * -Addressed data transfer command, R1 response */ +# define SD_ACMDIDX23 23 /* SET_WR_BLK_ERASE_COUNT: Set number blocks to erase before writing + * -Addressed Command, R1 response 22:0=NBLK */ +# define SD_ACMDIDX25 25 /* SECURE_WRITE_MULTIPLE_BLOCK: */ +# define SD_ACMDIDX38 38 /* SECURE_ERASE: */ +# define SD_ACMDIDX41 41 /* SD_SEND_OP_COND: Sends host capacity support information + * -Broadcast command, R3 response 31:0=OCR */ +# define SD_ACMDIDX42 42 /* SET_CLR_CARD_DETECT: Connect/disconnect pull-up resistor on CS + * Addressed Command, R1 response 0:0=CD */ +# define SD_ACMDIDX43 43 /* GET_MKB: */ +# define SD_ACMDIDX44 44 /* GET_MID: */ +# define SD_ACMDIDX45 45 /* SET_CER_RN1: */ +# define SD_ACMDIDX46 46 /* GET_CER_RN2: */ +# define SD_ACMDIDX47 47 /* SET_CER_RES2: */ +# define SD_ACMDIDX48 48 /* GET_CER_RES1/WRITE_MKB: */ +# define SD_ACMDIDX49 49 /* CHANGE_SECURE_AREA: */ +# define SD_ACMDIDX51 51 /* SEND_SCR: Reads the SD Configuration Register (SCR) + * Addressed data transfer command, R1 response */ +# define SDIO_ACMDIDX52 52 /* IO_RW_DIRECT: (SDIO only) + * -R5 response, 23:16=status 15:8=data */ +# define SDIO_ACMDIDX53 53 /* IO_RW_EXTENDED: (SDIO only) + * -R5 response, 23:16=status */ + +/* Response Encodings: + * + * xxxx xxxx xxxx xxxx OSMX XXRR RRCC CCCC + * + * x - Bit not used + * C - Bits 0-5: Command index + * R - Bits 6-9: Response type + * X - Bits 10-12: Data transfer type + * M - Bit 13: Multiple block transfer + * S - Bit 14: Stop data transfer + * O - Bit 15: Open drain + */ + +#define MMCSD_RESPONSE_SHIFT (6) +#define MMCSD_RESPONSE_MASK (15 << MMCSD_RESPONSE_SHIFT) +# define MMCSD_NO_RESPONSE (0) +# define MMCSD_R1_RESPONSE (1 << MMCSD_RESPONSE_SHIFT) /* 48-bit */ +# define MMCSD_R1B_RESPONSE (2 << MMCSD_RESPONSE_SHIFT) /* 48-bit */ +# define MMCSD_R2_RESPONSE (3 << MMCSD_RESPONSE_SHIFT) /* 128-bit */ +# define MMCSD_R3_RESPONSE (4 << MMCSD_RESPONSE_SHIFT) /* 48-bit */ +# define MMCSD_R4_RESPONSE (5 << MMCSD_RESPONSE_SHIFT) /* 48-bit */ +# define MMCSD_R5_RESPONSE (6 << MMCSD_RESPONSE_SHIFT) /* 48-bit */ +# define MMCSD_R6_RESPONSE (7 << MMCSD_RESPONSE_SHIFT) /* 48-bit */ +# define MMCSD_R7_RESPONSE (8 << MMCSD_RESPONSE_SHIFT) /* 48-bit */ + +/* Data Transfer Type */ + +#define MMCSD_DATAXFR_SHIFT (10) +#define MMCSD_DATAXFR_MASK (7 << MMCSD_DATAXFR_SHIFT) +# define MMCSD_DATAXFR (1 << MMCSD_DATAXFR_SHIFT) +# define MMCSD_STREAM (2 << MMCSD_DATAXFR_SHIFT) +# define MMCSD_WRXFR (4 << MMCSD_DATAXFR_SHIFT) + +# define MMCSD_NODATAXFR (0) +# define MMCSD_RDSTREAM (MMCSD_STREAM) +# define MMCSD_WRSTREAM (MMCSD_STREAM|MMCSD_WRXFR) +# define MMCSD_RDDATAXFR (MMCSD_DATAXFR) +# define MMCSD_WRDATAXFR (MMCSD_DATAXFR|MMCSD_WRXFR) + +#define MMCSD_MULTIBLOCK (1 << 13) +#define MMCSD_STOPXFR (1 << 14) + +/* Other options */ + +#define MMCSD_OPENDRAIN (1 << 15) + +/* Fully decorated MMC, SD, SDIO commands */ + +#define MMCSD_CMD0 (MMCSD_CMDIDX0 |MMCSD_NO_RESPONSE |MMCSD_NODATAXFR) +#define MMC_CMD1 (MMC_CMDIDX1 |MMCSD_R3_RESPONSE |MMCSD_NODATAXFR |MMCSD_OPENDRAIN) +#define MMCSD_CMD2 (MMCSD_CMDIDX2 |MMCSD_R2_RESPONSE |MMCSD_NODATAXFR) +#define MMC_CMD3 (MMC_CMDIDX3 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_CMD3 (SD_CMDIDX3 |MMCSD_R6_RESPONSE |MMCSD_NODATAXFR) +#define MMCSD_CMD4 (MMCSD_CMDIDX4 |MMCSD_NO_RESPONSE |MMCSD_NODATAXFR) +#define SDIO_CMD5 (SDIO_CMDIDX5 |MMCSD_R4_RESPONSE |MMCSD_NODATAXFR) +#define MMCSD_CMD6 (MMCSD_CMDIDX6 |MMCSD_R1_RESPONSE |MMCSD_RDDATAXFR) +#define MMCSD_CMD7S (MMCSD_CMDIDX7 |MMCSD_R1B_RESPONSE|MMCSD_NODATAXFR) +#define MMCSD_CMD7D (MMCSD_CMDIDX7 |MMCSD_NO_RESPONSE |MMCSD_NODATAXFR) /* No response when de-selecting card */ +#define SD_CMD8 (SD_CMDIDX8 |MMCSD_R7_RESPONSE |MMCSD_NODATAXFR) +#define MMCSD_CMD9 (MMCSD_CMDIDX9 |MMCSD_R2_RESPONSE |MMCSD_NODATAXFR) +#define MMCSD_CMD10 (MMCSD_CMDIDX10|MMCSD_R2_RESPONSE |MMCSD_NODATAXFR) +#define MMC_CMD11 (MMC_CMDIDX11 |MMCSD_R1_RESPONSE |MMCSD_RDSTREAM ) +#define MMCSD_CMD12 (MMCSD_CMDIDX12|MMCSD_R1B_RESPONSE|MMCSD_NODATAXFR |MMCSD_STOPXFR) +#define MMCSD_CMD13 (MMCSD_CMDIDX13|MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define MMCSD_CMD14 (MMCSD_CMDIDX14|MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define MMCSD_CMD15 (MMCSD_CMDIDX15|MMCSD_NO_RESPONSE |MMCSD_NODATAXFR) +#define MMCSD_CMD16 (MMCSD_CMDIDX16|MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define MMCSD_CMD17 (MMCSD_CMDIDX17|MMCSD_R1_RESPONSE |MMCSD_RDDATAXFR) +#define MMCSD_CMD18 (MMCSD_CMDIDX18|MMCSD_R1_RESPONSE |MMCSD_RDDATAXFR |MMCSD_MULTIBLOCK) +#define MMCSD_CMD19 (MMCSD_CMDIDX19|MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define MMC_CMD20 (MMC_CMDIDX20 |MMCSD_R1B_RESPONSE|MMCSD_WRSTREAM ) +#define MMC_CMD23 (MMC_CMDIDX23 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define MMCSD_CMD24 (MMCSD_CMDIDX24|MMCSD_R1_RESPONSE |MMCSD_WRDATAXFR) +#define MMCSD_CMD25 (MMCSD_CMDIDX25|MMCSD_R1_RESPONSE |MMCSD_WRDATAXFR |MMCSD_MULTIBLOCK) +#define MMCSD_CMD26 (MMCSD_CMDIDX26|MMCSD_R1_RESPONSE |MMCSD_WRDATAXFR) +#define MMCSD_CMD27 (MMCSD_CMDIDX27|MMCSD_R1_RESPONSE |MMCSD_WRDATAXFR) +#define MMCSD_CMD28 (MMCSD_CMDIDX28|MMCSD_R1B_RESPONSE|MMCSD_NODATAXFR) +#define MMCSD_CMD29 (MMCSD_CMDIDX29|MMCSD_R1B_RESPONSE|MMCSD_NODATAXFR) +#define MMCSD_CMD30 (MMCSD_CMDIDX30|MMCSD_R1_RESPONSE |MMCSD_RDDATAXFR) +#define SD_CMD32 (SD_CMDIDX32 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_CMD33 (SD_CMDIDX33 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define MMC_CMD34 (MMC_CMDIDX34 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define MMC_CMD35 (MMC_CMDIDX35 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define MMC_CMD36 (MMC_CMDIDX36 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define MMC_CMD37 (MMC_CMDIDX37 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define MMCSD_CMD38 (MMCSD_CMDIDX38|MMCSD_R1B_RESPONSE|MMCSD_NODATAXFR) +#define MMC_CMD39 (MMC_CMDIDX39 |MMCSD_R4_RESPONSE |MMCSD_NODATAXFR) +#define MMC_CMD40 (MMC_CMDIDX40 |MMCSD_R5_RESPONSE |MMCSD_NODATAXFR) +#define MMCSD_CMD42 (MMCSD_CMDIDX42|MMCSD_R1B_RESPONSE|MMCSD_WRDATAXFR) +#define SD_CMD55 (SD_CMDIDX55 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define MMCSD_CMD56 (MMCSD_CMDIDX56|MMCSD_R1_RESPONSE |MMCSD_RDDATAXFR) + +/* SD/SDIO APP commands (must be preceded by CMD55) */ + +#define SD_ACMD6 (SD_ACMDIDX6 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD13 (SD_ACMDIDX13 |MMCSD_R1_RESPONSE |MMCSD_RDDATAXFR) +#define SD_ACMD18 (SD_ACMDIDX18 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD22 (SD_ACMDIDX22 |MMCSD_R1_RESPONSE |MMCSD_RDDATAXFR) +#define SD_ACMD23 (SD_ACMDIDX23 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD25 (SD_ACMDIDX25 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD38 (SD_ACMDIDX38 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD41 (SD_ACMDIDX41 |MMCSD_R3_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD42 (SD_ACMDIDX42 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD43 (SD_ACMDIDX43 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD44 (SD_ACMDIDX44 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD45 (SD_ACMDIDX45 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD46 (SD_ACMDIDX46 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD47 (SD_ACMDIDX47 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD48 (SD_ACMDIDX48 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD49 (SD_ACMDIDX49 |MMCSD_R1_RESPONSE |MMCSD_NODATAXFR) +#define SD_ACMD51 (SD_ACMDIDX51 |MMCSD_R1_RESPONSE |MMCSD_RDDATAXFR) +#define SDIO_ACMD52 (SDIO_ACMDIDX52|MMCSD_R5_RESPONSE |MMCSD_NODATAXFR) +#define SDIO_ACMD53 (SDIO_ACMDIDX53|MMCSD_R5_RESPONSE |MMCSD_NODATAXFR) + +/**************************************************************************** + * Name: SDIO_LOCK + * + * Description: + * Lock/unlock the SDIO bus, preventing it from any other transaction + * while locked. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * state - TRUE/FALSE + * + * Returned Value: + * OK on success. + * + ****************************************************************************/ + +#define SDIO_LOCK(dev,state) ((dev)->lock(dev,state)) + +/**************************************************************************** + * Name: SDIO_RESET + * + * Description: + * Reset the SDIO controller. Undo all setup and initialization. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * + * Returned Value: + * None + * + ****************************************************************************/ + +#define SDIO_RESET(dev) ((dev)->reset(dev)) + +/**************************************************************************** + * Name: SDIO_STATUS + * + * Description: + * Get SDIO status. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Returns a bitset of status values (see SDIO_STATUS_* defines) + * + ****************************************************************************/ + +#define SDIO_STATUS(dev) ((dev)->status(dev)) + +/* SDIO status bits */ + +#define SDIO_STATUS_PRESENT 0x01 /* Bit 0=1: SDIO card present */ +#define SDIO_STATUS_WRPROTECTED 0x02 /* Bit 1=1: SDIO card write protected */ + +#define SDIO_PRESENT(dev) ((SDIO_STATUS(dev) & SDIO_STATUS_PRESENT) != 0) +#define SDIO_WRPROTECTED(dev) ((SDIO_STATUS(dev) & SDIO_STATUS_WRPROTECTED) != 0) + +/**************************************************************************** + * Name: SDIO_WIDEBUS + * + * Description: + * Called after change in Bus width has been selected (via ACMD6). Most + * controllers will need to perform some special operations to work + * correctly in the new bus mode. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * wide - true: wide bus (4-bit) bus mode enabled + * + * Returned Value: + * None + * + ****************************************************************************/ + +#define SDIO_WIDEBUS(dev,wide) ((dev)->widebus(dev,wide)) + +/**************************************************************************** + * Name: SDIO_CLOCK + * + * Description: + * Enable/disable SDIO clocking + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * rate - Specifies the clocking to use (see enum sdio_clock_e) + * + * Returned Value: + * None + * + ****************************************************************************/ + +#define SDIO_CLOCK(dev,rate) ((dev)->clock(dev,rate)) + +/**************************************************************************** + * Name: SDIO_ATTACH + * + * Description: + * Attach and prepare interrupts + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * + * Returned Value: + * OK on success; A negated errno on failure. + * + ****************************************************************************/ + +#define SDIO_ATTACH(dev) ((dev)->attach(dev)) + +/**************************************************************************** + * Name: SDIO_SENDCMD + * + * Description: + * Send the SDIO command + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * cmd - The command to send. See 32-bit command definitions above. + * arg - 32-bit argument required with some commands + * data - A reference to data required with some commands + * + * Returned Value: + * None + * + ****************************************************************************/ + +#define SDIO_SENDCMD(dev,cmd,arg) ((dev)->sendcmd(dev,cmd,arg)) + +/**************************************************************************** + * Name: SDIO_BLOCKLEN + * + * Description: + * Some hardward needs to be informed of the selected blocksize and the + * number of blocks. Others just work on the byte stream. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * blocklen - The selected block size. + * nblocks - The number of blocks to be transferred. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_BLOCKSETUP +# define SDIO_BLOCKSETUP(dev,blocklen,nblocks) ((dev)->blocksetup(dev,blocklen,nblocks)) +#else +# define SDIO_BLOCKSETUP(dev,blocklen,nblocks) +#endif + +/**************************************************************************** + * Name: SDIO_RECVSETUP + * + * Description: + * Setup hardware in preparation for data transfer from the card in non-DMA + * (interrupt driven mode). This method will do whatever controller setup + * is necessary. This would be called for SD memory just BEFORE sending + * CMD13 (SEND_STATUS), CMD17 (READ_SINGLE_BLOCK), CMD18 + * (READ_MULTIPLE_BLOCKS), ACMD51 (SEND_SCR), etc. Normally, SDIO_WAITEVENT + * will be called to receive the indication that the transfer is complete. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * buffer - Address of the buffer in which to receive the data + * nbytes - The number of bytes in the transfer + * + * Returned Value: + * Number of bytes sent on success; a negated errno on failure + * + ****************************************************************************/ + +#define SDIO_RECVSETUP(dev,buffer,nbytes) ((dev)->recvsetup(dev,buffer,nbytes)) + +/**************************************************************************** + * Name: SDIO_SENDSETUP + * + * Description: + * Setup hardware in preparation for data transfer from the card. This method + * will do whatever controller setup is necessary. This would be called + * for SD memory just AFTER sending CMD24 (WRITE_BLOCK), CMD25 + * (WRITE_MULTIPLE_BLOCK), ... and before SDIO_SENDDATA is called. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * buffer - Address of the buffer containing the data to send + * nbytes - The number of bytes in the transfer + * + * Returned Value: + * Number of bytes sent on success; a negated errno on failure + * + ****************************************************************************/ + +#define SDIO_SENDSETUP(dev,buffer,nbytes) ((dev)->sendsetup(dev,buffer,nbytes)) + +/**************************************************************************** + * Name: SDIO_CANCEL + * + * Description: + * Cancel the data transfer setup of SDIO_RECVSETUP, SDIO_SENDSETUP, + * SDIO_DMARECVSETUP or SDIO_DMASENDSETUP. This must be called to cancel + * the data transfer setup if, for some reason, you cannot perform the + * transfer. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * + * Returned Value: + * OK is success; a negated errno on failure + * + ****************************************************************************/ + +#define SDIO_CANCEL(dev) ((dev)->cancel(dev)) + +/**************************************************************************** + * Name: SDIO_WAITRESPONSE + * + * Description: + * Poll-wait for the response to the last command to be ready. This + * function should be called even after sending commands that have no + * response (such as CMD0) to make sure that the hardware is ready to + * receive the next command. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * cmd - The command that was sent. See 32-bit command definitions above. + * + * Returned Value: + * OK is success; a negated errno on failure + * + ****************************************************************************/ + +#define SDIO_WAITRESPONSE(dev,cmd) ((dev)->waitresponse(dev,cmd)) + +/**************************************************************************** + * Name: SDIO_RECVRx + * + * Description: + * Receive response to SDIO command. Only the critical payload is + * returned -- that is 32 bits for 48 bit status and 128 bits for 136 bit + * status. The driver implementation should verify the correctness of + * the remaining, non-returned bits (CRCs, CMD index, etc.). + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * Rx - Buffer in which to receive the response + * + * Returned Value: + * Number of bytes sent on success; a negated errno on failure. Here a + * failure means only a faiure to obtain the requested reponse (due to + * transport problem -- timeout, CRC, etc.). The implementation only + * assures that the response is returned intacta and does not check errors + * within the response itself. + * + ****************************************************************************/ + +#define SDIO_RECVR1(dev,cmd,R1) ((dev)->recvR1(dev,cmd,R1)) /* 48-bit */ +#define SDIO_RECVR2(dev,cmd,R2) ((dev)->recvR2(dev,cmd,R2)) /* 136-bit */ +#define SDIO_RECVR3(dev,cmd,R3) ((dev)->recvR3(dev,cmd,R3)) /* 48-bit */ +#define SDIO_RECVR4(dev,cmd,R4) ((dev)->recvR4(dev,cmd,R4)) /* 48-bit */ +#define SDIO_RECVR5(dev,cmd,R5) ((dev)->recvR5(dev,cmd,R5)) /* 48-bit */ +#define SDIO_RECVR6(dev,cmd,R6) ((dev)->recvR6(dev,cmd,R6)) /* 48-bit */ +#define SDIO_RECVR7(dev,cmd,R7) ((dev)->recvR7(dev,cmd,R7)) /* 48-bit */ + +/**************************************************************************** + * Name: SDIO_WAITENABLE + * + * Description: + * Enable/disable of a set of SDIO wait events. This is part of the + * the SDIO_WAITEVENT sequence. The set of to-be-waited-for events is + * configured before calling SDIO_EVENTWAIT. This is done in this way + * to help the driver to eliminate race conditions between the command + * setup and the subsequent events. + * + * The enabled events persist until either (1) SDIO_WAITENABLE is called + * again specifying a different set of wait events, or (2) SDIO_EVENTWAIT + * returns. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * eventset - A bitset of events to enable or disable (see SDIOWAIT_* + * definitions). 0=disable; 1=enable. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#define SDIO_WAITENABLE(dev,eventset) ((dev)->waitenable(dev,eventset)) + +/**************************************************************************** + * Name: SDIO_EVENTWAIT + * + * Description: + * Wait for one of the enabled events to occur (or a timeout). Note that + * all events enabled by SDIO_WAITEVENTS are disabled when SDIO_EVENTWAIT + * returns. SDIO_WAITEVENTS must be called again before SDIO_EVENTWAIT + * can be used again. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * timeout - Maximum time in milliseconds to wait. Zero means immediate + * timeout with no wait. The timeout value is ignored if + * SDIOWAIT_TIMEOUT is not included in the waited-for eventset. + * + * Returned Value: + * Event set containing the event(s) that ended the wait. Should always + * be non-zero. All events are disabled after the wait concludes. + * + ****************************************************************************/ + +#define SDIO_EVENTWAIT(dev,timeout) ((dev)->eventwait(dev,timeout)) + +/**************************************************************************** + * Name: SDIO_CALLBACKENABLE + * + * Description: + * Enable/disable of a set of SDIO callback events. This is part of the + * the SDIO callback sequence. The set of events is configured to enabled + * callbacks to the function provided in SDIO_REGISTERCALLBACK. + * + * Events are automatically disabled once the callback is performed and no + * further callback events will occur until they are again enabled by + * calling this methos. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * eventset - A bitset of events to enable or disable (see SDIOMEDIA_* + * definitions). 0=disable; 1=enable. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#define SDIO_CALLBACKENABLE(dev,eventset) ((dev)->callbackenable(dev,eventset)) + +/**************************************************************************** + * Name: SDIO_REGISTERCALLBACK + * + * Description: + * Register a callback that that will be invoked on any media status + * change. Callbacks should not be made from interrupt handlers, rather + * interrupt level events should be handled by calling back on the work + * thread. + * + * When this method is called, all callbacks should be disabled until they + * are enabled via a call to SDIO_CALLBACKENABLE + * + * Input Parameters: + * dev - Device-specific state data + * callback - The funtion to call on the media change + * arg - A caller provided value to return with the callback + * + * Returned Value: + * 0 on success; negated errno on failure. + * + ****************************************************************************/ + +#define SDIO_REGISTERCALLBACK(d,c,a) ((d)->registercallback(d,c,a)) + +/**************************************************************************** + * Name: SDIO_DMASUPPORTED + * + * Description: + * Return true if the hardware can support DMA + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * + * Returned Value: + * true if DMA is supported. + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_DMA +# define SDIO_DMASUPPORTED(dev) ((dev)->dmasupported(dev)) +#else +# define SDIO_DMASUPPORTED(dev) (false) +#endif + +/**************************************************************************** + * Name: SDIO_DMARECVSETUP + * + * Description: + * Setup to perform a read DMA. If the processor supports a data cache, + * then this method will also make sure that the contents of the DMA memory + * and the data cache are coherent. For read transfers this may mean + * invalidating the data cache. Upon return, DMA is enable and waiting. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * buffer - The memory to DMA from + * buflen - The size of the DMA transfer in bytes + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_DMA +# define SDIO_DMARECVSETUP(dev,buffer,len) ((dev)->dmarecvsetup(dev,buffer,len)) +#else +# define SDIO_DMARECVSETUP(dev,buffer,len) (-ENOSYS) +#endif + +/**************************************************************************** + * Name: SDIO_DMASENDSETUP + * + * Description: + * Setup to perform a write DMA. If the processor supports a data cache, + * then this method will also make sure that the contents of the DMA memory + * and the data cache are coherent. For write transfers, this may mean + * flushing the data cache. Upon return, DMA is enable and waiting. + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * buffer - The memory to DMA into + * buflen - The size of the DMA transfer in bytes + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_DMA +# define SDIO_DMASENDSETUP(dev,buffer,len) ((dev)->dmasendsetup(dev,buffer,len)) +#else +# define SDIO_DMASENDSETUP(dev,buffer,len) (-ENOSYS) +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Various clocking used by the SDIO driver */ + +enum sdio_clock_e +{ + CLOCK_SDIO_DISABLED = 0, /* Clock is disabled */ + CLOCK_IDMODE, /* Initial ID mode clocking (<400KHz) */ + CLOCK_MMC_TRANSFER, /* MMC normal operation clocking */ + CLOCK_SD_TRANSFER_1BIT, /* SD normal operation clocking (narrow 1-bit mode) */ + CLOCK_SD_TRANSFER_4BIT /* SD normal operation clocking (wide 4-bit mode) */ +}; + +/* Event set. A uint8_t is big enough to hold a set of 8-events. If more are + * needed, change this to a uint16_t. + */ + +typedef uint8_t sdio_eventset_t; + +/* This structure defines the interface between the NuttX SDIO + * driver and the chip- or board-specific SDIO interface. This + * interface is only used in architectures that support SDIO + * 1- or 4-bit data busses. For SDIO support this interface is + * registered with the NuttX SDIO driver by calling + * sdio_slotinitialize(). + */ + +struct sdio_dev_s +{ + /* See descriptions of each method in the access macros provided + * above. + */ + + /* Mutual exclusion */ + +#ifdef CONFIG_SDIO_MUXBUS + int (*lock)(FAR struct sdio_dev_s *dev, bool lock); +#endif + + /* Initialization/setup */ + + void (*reset)(FAR struct sdio_dev_s *dev); + uint8_t (*status)(FAR struct sdio_dev_s *dev); + void (*widebus)(FAR struct sdio_dev_s *dev, bool enable); + void (*clock)(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate); + int (*attach)(FAR struct sdio_dev_s *dev); + + /* Command/Status/Data Transfer */ + + int (*sendcmd)(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg); +#ifdef CONFIG_SDIO_BLOCKSETUP + void (*blocksetup)(FAR struct sdio_dev_s *dev, unsigned int blocklen, + unsigned int nblocks); +#endif + int (*recvsetup)(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, + size_t nbytes); + int (*sendsetup)(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer, + size_t nbytes); + int (*cancel)(FAR struct sdio_dev_s *dev); + + int (*waitresponse)(FAR struct sdio_dev_s *dev, uint32_t cmd); + int (*recvR1)(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *R1); + int (*recvR2)(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t R2[4]); + int (*recvR3)(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *R3); + int (*recvR4)(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *R4); + int (*recvR5)(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *R5); + int (*recvR6)(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *R6); + int (*recvR7)(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *R7); + + /* Event/Callback support */ + + void (*waitenable)(FAR struct sdio_dev_s *dev, sdio_eventset_t eventset); + sdio_eventset_t (*eventwait)(FAR struct sdio_dev_s *dev, uint32_t timeout); + void (*callbackenable)(FAR struct sdio_dev_s *dev, + sdio_eventset_t eventset); + int (*registercallback)(FAR struct sdio_dev_s *dev, + worker_t callback, void *arg); + + /* DMA. CONFIG_SDIO_DMA should be set if the driver supports BOTH DMA + * and non-DMA transfer modes. If the driver supports only one mode + * CONFIG_SDIO_DMA is not required. + */ + +#ifdef CONFIG_SDIO_DMA + bool (*dmasupported)(FAR struct sdio_dev_s *dev); + int (*dmarecvsetup)(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, + size_t buflen); + int (*dmasendsetup)(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer, + size_t buflen); +#endif +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __INCLUDE_NUTTX_SDIO_H */ diff --git a/nuttx/include/nuttx/sensors/lis331dl.h b/nuttx/include/nuttx/sensors/lis331dl.h new file mode 100644 index 0000000000..2e83dbe1f1 --- /dev/null +++ b/nuttx/include/nuttx/sensors/lis331dl.h @@ -0,0 +1,142 @@ +/**************************************************************************** + * include/nuttx/sensors/lis331dl.h + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * + * Authors: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** \file + * \author Uros Platise + * \brief ST LIS331DL I2C Device Driver + **/ + +#ifndef __INCLUDE_NUTTX_SENSORS_LIS331DL_H +#define __INCLUDE_NUTTX_SENSORS_LIS331DL_H + +#include +#include + +/************************************************************************************ + * Pre-Processor Declarations + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + + +/************************************************************************************ + * Public Data Types + ************************************************************************************/ + +struct lis331dl_dev_s; + +struct lis331dl_vector_s { + int8_t x, y, z; +}; + + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +/** Initialize ST LIS331DL Chip + * + * \param i2c I2C Device Structure + * \param address I2C Address of the proposed device + * \return Pointer to newly allocated ST LIS331DL structure or NULL on error with errno set. + * + * Possible errno as set by this function on error: + * - ENODEV: When device addressed on given address is not compatible or it is not a LIS331DL + * - EFAULT: When there is no device at given address. + * - EBUSY: When device is already addressed by other device driver (not yet supported by low-level driver) + **/ +EXTERN struct lis331dl_dev_s * lis331dl_init(struct i2c_dev_s * i2c, uint16_t address); + +/** Deinitialize ST LIS331DL Chip + * + * \param dev Device to LIS331DL device structure, as returned by the lis331dl_init() + * \return OK On success + * + **/ +EXTERN int lis331dl_deinit(struct lis331dl_dev_s * dev); + +/** Power up device, start conversion */ +EXTERN int lis331dl_powerup(struct lis331dl_dev_s * dev); + +/** Power down device, stop conversion */ +EXTERN int lis331dl_powerdown(struct lis331dl_dev_s * dev); + +/** Configure conversion + * + * \param dev Device to LIS331DL device structure + * \param full When set, range of [-9g, 9g] is selected, otherwise [-2g, +2g] + * \param fast When set, conversion operates at 400 Hz, otherwise at 100 Hz + * \return OK on success or errno is set + **/ +EXTERN int lis331dl_setconversion(struct lis331dl_dev_s * dev, bool full, bool fast); + +/** Get precision + * + * \return Precision of 1 LSB in terms of unit [mg] + **/ +EXTERN int lis331dl_getprecision(struct lis331dl_dev_s * dev); + +/** Get sample rate + * + * \return Sample rate in unit of [Hz] + **/ +EXTERN int lis331dl_getsamplerate(struct lis331dl_dev_s * dev); + +/** Get readings, updates internal data structure + * + * \param dev Device to LIS331DL device structure + * \return Ptr to vector acceleration [x,y,z] on success, or NULL on error with errno set. + * If data is not yet ready to be read from the LIS331 then errno is set to EAGAIN otherwise + * errno is set by I2C_TRANSFER(). + */ +EXTERN const struct lis331dl_vector_s * lis331dl_getreadings(struct lis331dl_dev_s * dev); + + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __INCLUDE_NUTTX_SENSORS_LIS331DL_H */ diff --git a/nuttx/include/nuttx/sensors/lm75.h b/nuttx/include/nuttx/sensors/lm75.h new file mode 100644 index 0000000000..d34509ada5 --- /dev/null +++ b/nuttx/include/nuttx/sensors/lm75.h @@ -0,0 +1,133 @@ +/**************************************************************************** + * include/nuttx/lm75.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __NUTTX_SENSORS_LM75_H +#define __NUTTX_SENSORS_LM75_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************ + * CONFIG_I2C - Enables support for I2C drivers + * CONFIG_I2C_LM75 - Enables support for the LM-75 driver + */ + +#define CONFIG_LM75_BASEADDR 0x48 + +/* IOCTL Commands ***********************************************************/ + +#define SNIOC_READCONF _SNIOC(0x0001) /* Arg: uint8_t* pointer */ +#define SNIOC_WRITECONF _SNIOC(0x0002) /* Arg: uint8_t value */ +#define SNIOC_SHUTDOWN _SNIOC(0x0003) /* Arg: None */ +#define SNIOC_POWERUP _SNIOC(0x0004) /* Arg: None */ +#define SNIOC_FAHRENHEIT _SNIOC(0x0005) /* Arg: None */ +#define SNIOC_CENTIGRADE _SNIOC(0x0006) /* Arg: None */ +#define SNIOC_READTHYS _SNIOC(0x0007) /* Arg: b16_t* pointer */ +#define SNIOC_WRITETHYS _SNIOC(0x0008) /* Arg: b16_t value */ +#define SNIOC_READTOS _SNIOC(0x0009) /* Arg: b16_t* pointer */ +#define SNIOC_WRITRETOS _SNIOC(0x000a) /* Arg: b16_t value */ + +/* LM-75 Register Definitions ***********************************************/ +/* LM-75 Registers addresses */ + +#define LM75_TEMP_REG 0x00 /* Temperature Register */ +#define LM75_CONF_REG 0x01 /* Configuration Register */ +#define LM75_THYS_REG 0x02 /* Temperature Register */ +#define LM75_TOS_REG 0x03 /* Over-temp Shutdown Threshold Register */ + +/* Configuration Register Bit Definitions */ + +#define LM75_CONF_SHUTDOWN (1 << 0) /* Bit 0: Put LM75 goes in low power shutdown mode */ +#define LM75_CONF_INTMODE (1 << 1) /* Bit 1: 0=Comparator 1=Interrupt mode */ +#define LM75_CONF_POLARITY (1 << 2) /* Bit 2: 0=O.S. Active low 1=active high */ +#define LM75_CONF_FAULTQ (3) /* Bits 3-4: # faults before setting O.S. */ + +/* NOTE: When temperature values are read, they are return as b16_t, fixed + * precision integer values (see include/fixedmath.h). + */ + +/**************************************************************************** + * Global Data + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: lm75_register + * + * Description: + * Register the LM-75 character device as 'devpath' + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/temp0" + * i2c - An instance of the I2C interface to use to communicate with LM75 + * addr - The I2C address of the LM-75. The base I2C address of the LM75 + * is 0x48. Bits 0-3 can be controlled to get 8 unique addresses from 0x48 + * through 0x4f. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +EXTERN int lm75_register(FAR const char *devpath, FAR struct i2c_dev_s *i2c, + uint8_t addr); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __NUTTX_SENSORS_LM75_H */ diff --git a/nuttx/include/nuttx/sensors/qencoder.h b/nuttx/include/nuttx/sensors/qencoder.h new file mode 100644 index 0000000000..d21fa12482 --- /dev/null +++ b/nuttx/include/nuttx/sensors/qencoder.h @@ -0,0 +1,180 @@ +/**************************************************************************** + * include/nuttx/qencoder.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __NUTTX_SENSORS_QENCODER_H +#define __NUTTX_SENSORS_QENCODER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifdef CONFIG_QENCODER + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************ + * CONFIG_QENCODER - Enables support for the quadrature encoder upper half + */ + +/* IOCTL Commands ***********************************************************/ +/* The Quadrature Encode module uses a standard character driver framework. + * However, since the driver is a devices control interface and not a data + * transfer interface, the majority of the functionality is implemented in + * driver ioctl calls. The PWM ioctal commands are lised below: + * + * QEIOC_POSITION - Get the current position from the encoder. + * Argument: int32_t pointer to the location to return the position. + * QEIOC_RESET - Reset the position to zero. + * Argument: None + */ + +#define QEIOC_POSITION _QEIOC(0x0001) /* Arg: int32_t* pointer */ +#define QEIOC_RESET _QEIOC(0x0002) /* Arg: None */ + +/* User defined ioctl cms should use QEIOC_USER like this: + * + * #define QEIOC_MYCMD1 _QEIOC(QEIOC_USER) + * #define QEIOC_MYCMD2 _QEIOC(QEIOC_USER+1) + * ... + */ + +#define QEIOC_USER 0x0003 + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* This is the vtable that is used to by the upper half quadrature encoder + * to call back into the lower half quadrature encoder. + */ + +struct qe_lowerhalf_s; +struct qe_ops_s +{ + /* This method is called when the driver is opened. The lower half driver + * should configure and initialize the device so that it is ready for use. + * The initial position value should be zero. + */ + + CODE int (*setup)(FAR struct qe_lowerhalf_s *lower); + + /* This method is called when the driver is closed. The lower half driver + * should stop data collection, free any resources, disable timer hardware, and + * put the system into the lowest possible power usage state + */ + + CODE int (*shutdown)(FAR struct qe_lowerhalf_s *lower); + + /* Return the current position measurement. */ + + CODE int (*position)(FAR struct qe_lowerhalf_s *lower, int32_t *pos); + + /* Reset the position measurement to zero. */ + + CODE int (*reset)(FAR struct qe_lowerhalf_s *lower); + + /* Lower-half logic may support platform-specific ioctl commands */ + + CODE int (*ioctl)(FAR struct qe_lowerhalf_s *lower, + int cmd, unsigned long arg); +}; + +/* This is the interface between the lower half quadrature encoder driver + * and the upper half quadrature encoder driver. A (device-specific) + * instance of this structure is passed to the upper-half driver when the + * quadrature encoder driver is registered. + * + * Normally that lower half logic will have its own, custom state structure + * that is simply cast to struct qe_lowerhalf_s. In order to perform such casts, + * the initial fields of the custom state structure match the initial fields + * of the following generic lower half state structure. + */ + +struct qe_lowerhalf_s +{ + /* The first field of this state structure must be a pointer to the lower- + * half callback structure: + */ + + FAR const struct qe_ops_s *ops; + + /* The custom timer state structure may include additional fields after + * the pointer to the callback structure. + */ + +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: qe_register + * + * Description: + * Register the Quadrature Encoder lower half device as 'devpath' + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/qe0" + * lower - An instance of the lower half interface + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +EXTERN int qe_register(FAR const char *devpath, FAR struct qe_lowerhalf_s *lower); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_QENCODER */ +#endif /* __NUTTX_SENSORS_QENCODER_H */ diff --git a/nuttx/include/nuttx/sercomm/msgb.h b/nuttx/include/nuttx/sercomm/msgb.h new file mode 100644 index 0000000000..64825c1eaa --- /dev/null +++ b/nuttx/include/nuttx/sercomm/msgb.h @@ -0,0 +1,176 @@ +#ifndef _MSGB_H +#define _MSGB_H + +/* (C) 2008-2010 by Harald Welte + * + * This source code is derivated from Osmocom-BB project and was + * relicensed as BSD with permission from original authors. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************/ + +#include +#include + +struct msgb { + struct llist_head list; + + /* the layer 1 header, if any */ + unsigned char *l1h; + /* the A-bis layer 2 header: OML, RSL(RLL), NS */ + unsigned char *l2h; + /* the layer 3 header. For OML: FOM; RSL: 04.08; GPRS: BSSGP */ + unsigned char *l3h; + + uint16_t data_len; + uint16_t len; + + unsigned char *head; /* start of buffer */ + unsigned char *tail; /* end of message */ + unsigned char *data; /* start of message */ + unsigned char _data[0]; +}; + +extern struct msgb *msgb_alloc(uint16_t size, const char *name); +extern void msgb_free(struct msgb *m); +extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg); +extern struct msgb *msgb_dequeue(struct llist_head *queue); +extern void msgb_reset(struct msgb *m); + +#define msgb_l1(m) ((void *)(m->l1h)) +#define msgb_l2(m) ((void *)(m->l2h)) +#define msgb_l3(m) ((void *)(m->l3h)) + +static inline unsigned int msgb_l1len(const struct msgb *msgb) +{ + return msgb->tail - (uint8_t *)msgb_l1(msgb); +} + +static inline unsigned int msgb_l2len(const struct msgb *msgb) +{ + return msgb->tail - (uint8_t *)msgb_l2(msgb); +} + +static inline unsigned int msgb_l3len(const struct msgb *msgb) +{ + return msgb->tail - (uint8_t *)msgb_l3(msgb); +} + +static inline unsigned int msgb_headlen(const struct msgb *msgb) +{ + return msgb->len - msgb->data_len; +} +static inline int msgb_tailroom(const struct msgb *msgb) +{ + return (msgb->head + msgb->data_len) - msgb->tail; +} +static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len) +{ + unsigned char *tmp = msgb->tail; + + /* we intentionally call cons_puts() here to display an allocation + * failure on the _other_ serial port (i.e. the one that doesn't + * have the HDLC layer on it */ + if (msgb_tailroom(msgb) < len) + cons_puts("msgb_tailroom insufficient!\n"); + + msgb->tail += len; + msgb->len += len; + return tmp; +} +static inline void msgb_put_u8(struct msgb *msgb, uint8_t word) +{ + uint8_t *space = msgb_put(msgb, 1); + space[0] = word & 0xFF; +} +static inline void msgb_put_u16(struct msgb *msgb, uint16_t word) +{ + uint8_t *space = msgb_put(msgb, 2); + space[0] = word >> 8 & 0xFF; + space[1] = word & 0xFF; +} +static inline void msgb_put_u32(struct msgb *msgb, uint32_t word) +{ + uint8_t *space = msgb_put(msgb, 4); + space[0] = word >> 24 & 0xFF; + space[1] = word >> 16 & 0xFF; + space[2] = word >> 8 & 0xFF; + space[3] = word & 0xFF; +} +static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int len) +{ + unsigned char *tmp = msgb->data; + msgb->data += len; + msgb->len -= len; + return tmp; +} +static inline uint8_t msgb_get_u8(struct msgb *msgb) +{ + uint8_t *space = msgb_get(msgb, 1); + return space[0]; +} +static inline uint16_t msgb_get_u16(struct msgb *msgb) +{ + uint8_t *space = msgb_get(msgb, 2); + return space[0] << 8 | space[1]; +} +static inline uint32_t msgb_get_u32(struct msgb *msgb) +{ + uint8_t *space = msgb_get(msgb, 4); + return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3]; +} +static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len) +{ + msgb->data -= len; + msgb->len += len; + return msgb->data; +} +static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len) +{ + msgb->len -= len; + return msgb->data += len; +} + +/* increase the headroom of an empty msgb, reducing the tailroom */ +static inline void msgb_reserve(struct msgb *msg, int len) +{ + msg->data += len; + msg->tail += len; +} + +static inline struct msgb *msgb_alloc_headroom(int size, int headroom, + const char *name) +{ + struct msgb *msg = msgb_alloc(size, name); + if (msg) + msgb_reserve(msg, headroom); + return msg; +} + +#endif /* _MSGB_H */ diff --git a/nuttx/include/nuttx/sercomm/sercomm.h b/nuttx/include/nuttx/sercomm/sercomm.h new file mode 100644 index 0000000000..54256b5a7d --- /dev/null +++ b/nuttx/include/nuttx/sercomm/sercomm.h @@ -0,0 +1,57 @@ +#ifndef _SERCOMM_H +#define _SERCOMM_H + +/* SERCOMM layer on UART1 (modem UART) */ + +#include + +#define SERCOMM_UART_NR 1 + +#define HDLC_FLAG 0x7E +#define HDLC_ESCAPE 0x7D + +#define HDLC_C_UI 0x03 +#define HDLC_C_P_BIT (1 << 4) +#define HDLC_C_F_BIT (1 << 4) + +/* a low sercomm_dlci means high priority. A high DLCI means low priority */ +enum sercomm_dlci { + SC_DLCI_HIGHEST = 0, + SC_DLCI_DEBUG = 4, + SC_DLCI_L1A_L23 = 5, + SC_DLCI_LOADER = 9, + SC_DLCI_CONSOLE = 10, + SC_DLCI_ECHO = 128, + _SC_DLCI_MAX +}; + +void sercomm_init(void); +int sercomm_initialized(void); + +/* User Interface: Tx */ + +/* user interface for transmitting messages for a given DLCI */ +void sercomm_sendmsg(uint8_t dlci, struct msgb *msg); +/* how deep is the Tx queue for a given DLCI */ +unsigned int sercomm_tx_queue_depth(uint8_t dlci); + +/* User Interface: Rx */ + +/* receiving messages for a given DLCI */ +typedef void (*dlci_cb_t)(uint8_t dlci, struct msgb *msg); +int sercomm_register_rx_cb(uint8_t dlci, dlci_cb_t cb); + +/* Driver Interface */ + +/* fetch one octet of to-be-transmitted serial data. returns 0 if no more data */ +int sercomm_drv_pull(uint8_t *ch); +/* the driver has received one byte, pass it into sercomm layer. + returns 1 in case of success, 0 in case of unrecognized char */ +int sercomm_drv_rx_char(uint8_t ch); + +static inline struct msgb *sercomm_alloc_msgb(unsigned int len) +{ + return msgb_alloc_headroom(len+4, 4, "sercomm_tx"); +} + +#endif /* _SERCOMM_H */ diff --git a/nuttx/include/nuttx/sercomm/sercomm_cons.h b/nuttx/include/nuttx/sercomm/sercomm_cons.h new file mode 100644 index 0000000000..11f66545c2 --- /dev/null +++ b/nuttx/include/nuttx/sercomm/sercomm_cons.h @@ -0,0 +1,10 @@ +#ifndef _SERCOMM_CONS_H +#define _SERCOMM_CONS_H + +/* how large buffers do we allocate? */ +#define SERCOMM_CONS_ALLOC 256 + +int sercomm_puts(const char *s); +int sercomm_putchar(int c); + +#endif /* _SERCOMM_CONS_H */ diff --git a/nuttx/include/nuttx/serial/serial.h b/nuttx/include/nuttx/serial/serial.h new file mode 100644 index 0000000000..67a7f9d992 --- /dev/null +++ b/nuttx/include/nuttx/serial/serial.h @@ -0,0 +1,306 @@ +/************************************************************************************ + * include/nuttx/serial/serial.h + * + * Copyright (C) 2007-2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SERIAL_SERIAL_H +#define __INCLUDE_NUTTX_SERIAL_SERIAL_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/* Maximum number of threads than can be waiting for POLL events */ + +#ifndef CONFIG_SERIAL_NPOLLWAITERS +# define CONFIG_SERIAL_NPOLLWAITERS 2 +#endif + +/* vtable access helpers */ + +#define uart_setup(dev) dev->ops->setup(dev) +#define uart_shutdown(dev) dev->ops->shutdown(dev) +#define uart_attach(dev) dev->ops->attach(dev) +#define uart_detach(dev) dev->ops->detach(dev) +#define uart_enabletxint(dev) dev->ops->txint(dev, true) +#define uart_disabletxint(dev) dev->ops->txint(dev, false) +#define uart_enablerxint(dev) dev->ops->rxint(dev, true) +#define uart_disablerxint(dev) dev->ops->rxint(dev, false) +#define uart_rxavailable(dev) dev->ops->rxavailable(dev) +#define uart_txready(dev) dev->ops->txready(dev) +#define uart_txempty(dev) dev->ops->txempty(dev) +#define uart_send(dev,ch) dev->ops->send(dev,ch) +#define uart_receive(dev,s) dev->ops->receive(dev,s) + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/* This structure defines one serial I/O buffer. The serial infrastructure will + * initialize the 'sem' field but all other fields must be initialized by the + * caller of uart_register(). + */ + +struct uart_buffer_s +{ + sem_t sem; /* Used to control exclusive access to the buffer */ + volatile int16_t head; /* Index to the head [IN] index in the buffer */ + volatile int16_t tail; /* Index to the tail [OUT] index in the buffer */ + int16_t size; /* The allocated size of the buffer */ + FAR char *buffer; /* Pointer to the allocated buffer memory */ +}; + +/* This structure defines all of the operations providd by the architecture specific + * logic. All fields must be provided with non-NULL function pointers by the + * caller of uart_register(). + */ + +struct uart_dev_s; +struct uart_ops_s +{ + /* Configure the UART baud, bits, parity, fifos, etc. This method is called + * the first time that the serial port is opened. For the serial console, + * this will occur very early in initialization; for other serial ports this + * will occur when the port is first opened. This setup does not include + * attaching or enabling interrupts. That portion of the UART setup is + * performed when the attach() method is called. + */ + + CODE int (*setup)(FAR struct uart_dev_s *dev); + + /* Disable the UART. This method is called when the serial port is closed. + * This method reverses the operation the setup method. NOTE that the serial + * console is never shutdown. + */ + + CODE void (*shutdown)(FAR struct uart_dev_s *dev); + + /* Configure the UART to operation in interrupt driven mode. This method is + * called when the serial port is opened. Normally, this is just after the + * the setup() method is called, however, the serial console may operate in + * a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled when by the attach method (unless the + * hardware supports multiple levels of interrupt enabling). The RX and TX + * interrupts are not enabled until the txint() and rxint() methods are called. + */ + + CODE int (*attach)(FAR struct uart_dev_s *dev); + + /* Detach UART interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called. The exception is + * the serial console which is never shutdown. + */ + + CODE void (*detach)(FAR struct uart_dev_s *dev); + + /* All ioctl calls will be routed through this method */ + + CODE int (*ioctl)(FAR struct file *filep, int cmd, unsigned long arg); + + /* Called (usually) from the interrupt level to receive one character from + * the UART. Error bits associated with the receipt are provided in the + * the return 'status'. + */ + + CODE int (*receive)(FAR struct uart_dev_s *dev, FAR unsigned int *status); + + /* Call to enable or disable RX interrupts */ + + CODE void (*rxint)(FAR struct uart_dev_s *dev, bool enable); + + /* Return true if the receive data is available */ + + CODE bool (*rxavailable)(FAR struct uart_dev_s *dev); + + /* This method will send one byte on the UART */ + + CODE void (*send)(FAR struct uart_dev_s *dev, int ch); + + /* Call to enable or disable TX interrupts */ + + CODE void (*txint)(FAR struct uart_dev_s *dev, bool enable); + + /* Return true if the tranmsit hardware is ready to send another byte. This + * is used to determine if send() method can be called. + */ + + CODE bool (*txready)(FAR struct uart_dev_s *dev); + + /* Return true if all characters have been sent. If for example, the UART + * hardware implements FIFOs, then this would mean the transmit FIFO is + * empty. This method is called when the driver needs to make sure that + * all characters are "drained" from the TX hardware. + */ + + CODE bool (*txempty)(FAR struct uart_dev_s *dev); +}; + +/* This is the device structure used by the driver. The caller of + * uart_register() must allocate and initialize this structure. The + * calling logic need only set all fields to zero except: + * + * 'isconsole', 'xmit.buffer', 'rcv.buffer', the elements + * of 'ops', and 'private' + * + * The common logic will initialize all semaphores. + */ + +struct uart_dev_s +{ + uint8_t open_count; /* Number of times the device has been opened */ + volatile bool xmitwaiting; /* true: User waiting for space in xmit.buffer */ + volatile bool recvwaiting; /* true: User waiting for data in recv.buffer */ + bool isconsole; /* true: This is the serial console */ + sem_t closesem; /* Locks out new open while close is in progress */ + sem_t xmitsem; /* Wakeup user waiting for space in xmit.buffer */ + sem_t recvsem; /* Wakeup user waiting for data in recv.buffer */ +#ifndef CONFIG_DISABLE_POLL + sem_t pollsem; /* Manages exclusive access to fds[] */ +#endif + struct uart_buffer_s xmit; /* Describes transmit buffer */ + struct uart_buffer_s recv; /* Describes receive buffer */ + FAR const struct uart_ops_s *ops; /* Arch-specific operations */ + FAR void *priv; /* Used by the arch-specific logic */ + + /* The following is a list if poll structures of threads waiting for + * driver events. The 'struct pollfd' reference for each open is also + * retained in the f_priv field of the 'struct file'. + */ + +#ifndef CONFIG_DISABLE_POLL + struct pollfd *fds[CONFIG_SERIAL_NPOLLWAITERS]; +#endif + + /* Terminal control flags */ + struct termios termios_s; + +}; +typedef struct uart_dev_s uart_dev_t; + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Name: uart_register + * + * Description: + * Register serial console and serial ports. + * + ************************************************************************************/ + +EXTERN int uart_register(FAR const char *path, FAR uart_dev_t *dev); + +/************************************************************************************ + * Name: uart_xmitchars + * + * Description: + * This function is called from the UART interrupt handler when an interrupt + * is received indicating that there is more space in the transmit FIFO. This + * function will send characters from the tail of the xmit buffer while the driver + * write() logic adds data to the head of the xmit buffer. + * + ************************************************************************************/ + +EXTERN void uart_xmitchars(FAR uart_dev_t *dev); + +/************************************************************************************ + * Name: uart_receivechars + * + * Description: + * This function is called from the UART interrupt handler when an interrupt + * is received indicating that are bytes available to be received. This + * function will add chars to head of receive buffer. Driver read() logic will take + * characters from the tail of the buffer. + * + ************************************************************************************/ + +EXTERN void uart_recvchars(FAR uart_dev_t *dev); + +/************************************************************************************ + * Name: uart_datareceived + * + * Description: + * This function is called from uart_recvchars when new serial data is place in + * the driver's circular buffer. This function will wake-up any stalled read() + * operations that are waiting for incoming data. + * + ************************************************************************************/ + +EXTERN void uart_datareceived(FAR uart_dev_t *dev); + +/************************************************************************************ + * Name: uart_datasent + * + * Description: + * This function is called from uart_xmitchars after serial data has been sent, + * freeing up some space in the driver's circular buffer. This function will + * wake-up any stalled write() operations that was waiting for space to buffer + * outgoing data. + * + ************************************************************************************/ + +EXTERN void uart_datasent(FAR uart_dev_t *dev); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_SERIAL_SERIAL_H */ diff --git a/nuttx/include/nuttx/serial/tioctl.h b/nuttx/include/nuttx/serial/tioctl.h new file mode 100644 index 0000000000..b309ff37ce --- /dev/null +++ b/nuttx/include/nuttx/serial/tioctl.h @@ -0,0 +1,218 @@ +/******************************************************************************************** + * include/nuttx/serial/tioctl.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ +/* This function should not be included directly. Rather, it should be included indirectly + * via include/nuttx/fs/ioctl.h. + */ + +#ifndef __INCLUDE_NUTTX_SERIAL_TIOCTL_H +#define __INCLUDE_NUTTX_SERIAL_TIOCTL_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ + +/* Get and Set Terminal Attributes (see termios.h) */ + +#define TCGETS _TIOC(0x0001) /* Get serial port settings: FAR struct termios* */ +#define TCSETS _TIOC(0x0002) /* Set serial port settings: FAR const struct termios* */ +#define TCSETSW _TIOC(0x0003) /* Drain output and set serial port settings: FAR const struct termios* */ +#define TCSETSF _TIOC(0x0004) /* Drain output, discard intput, and set serial port settings: FAR const struct termios* */ +#define TCGETA _TIOC(0x0005) /* See TCGETS: FAR struct termio* */ +#define TCSETA _TIOC(0x0006) /* See TCSETS: FAR const struct termio* */ +#define TCSETAW _TIOC(0x0007) /* See TCSETSF: FAR const struct termio* */ +#define TCSETAF _TIOC(0x0008) /* See TCSETSF: FAR const struct termio* */ + +/* Locking the termios structure */ + +#define TIOCGLCKTRMIOS _TIOC(0x0009) /* Get termios lock status: FAR struct termios* */ +#define TIOCSLCKTRMIOS _TIOC(0x000a) /* Set termios lock status: FAR const struct termios* */ + +/* Get and Set Window Size */ + +#define TIOCGWINSZ _TIOC(0x000b) /* Get window size: FAR struct winsize */ +#define TIOCSWINSZ _TIOC(0x000c) /* Set window size: FAR const struct winsize */ + +/* Send a break */ + +#define TCSBRK _TIOC(0x000d) /* Send a break: int */ +#define TCSBRKP _TIOC(0x000e) /* Send a POSIX break: int */ +#define TIOCSBRK _TIOC(0x000f) /* Turn break on: void */ +#define TIOCCBRK _TIOC(0x0010) /* Turn break off: void */ + +/* Software flow control */ + +#define TCXONC _TIOC(0x0011) /* Control flow control: int */ + +/* Buffer count and flushing */ + +#define TIOCINQ _TIOC(0x0012) /* Bytes in input buffer: int */ +#define TIOCOUTQ _TIOC(0x0013) /* Bytes in output buffer: int */ +#define TCFLSH _TIOC(0x0014) /* Flush: int */ + +/* Faking input */ + +#define TIOCSTI _TIOC(0x0015) /* Insert into input: const char */ + +/* Re-directing console output */ + +#define TIOCCONS _TIOC(0x0016) /* Re-direct console output to device: void */ + +/* Controlling TTY */ + +#define TIOCSCTTY _TIOC(0x0017) /* Make controlling TTY: int */ +#define TIOCNOTTY _TIOC(0x0018) /* Give up controllinog TTY: void */ + +/* Exclusive mode */ + +#define TIOCEXCL _TIOC(0x0019) /* Put TTY in exclusive mode: void */ +#define TIOCNXCL _TIOC(0x001a) /* Disable exclusive mode: void */ + +/* Line discipline */ + +#define TIOCGETD _TIOC(0x001b) /* Get line discipline: FAR int */ +#define TIOCSETD _TIOC(0x001c) /* Set line discipline: FAR const int */ + +/* Packet mode */ + +#define TIOCPKT _TIOC(0x001d) /* Control packet mode: FAR const int */ + +# define TIOCPKT_FLUSHREAD (1 << 0) /* The read queue for the terminal is flushed */ +# define TIOCPKT_FLUSHWRITE (1 << 1) /* The write queue for the terminal is flushed */ +# define TIOCPKT_STOP (1 << 2) /* Output to the terminal is stopped */ +# define TIOCPKT_START (1 << 3) /* Output to the terminal is restarted */ +# define TIOCPKT_DOSTOP (1 << 4) /* t_stopc is '^S' and t_startc is '^Q' */ +# define TIOCPKT_NOSTOP (1 << 5) /* The start and stop characters are not '^S/^Q' */ + +/* Modem control */ + +#define TIOCMGET _TIOC(0x001e) /* Get modem status bits: FAR int */ +#define TIOCMSET _TIOC(0x001f) /* Set modem status bits: FAR const int */ +#define TIOCMBIC _TIOC(0x0020) /* Clear modem bits: FAR const int */ +#define TIOCMBIS _TIOC(0x0021) /* Set modem bits: FAR const int */ + +# define TIOCM_LE (1 << 0) /* DSR (data set ready/line enable) */ +# define TIOCM_DTR (1 << 1) /* DTR (data terminal ready) */ +# define TIOCM_RTS (1 << 2) /* RTS (request to send) */ +# define TIOCM_ST (1 << 3) /* Secondary TXD (transmit) */ +# define TIOCM_SR (1 << 4) /* Secondary RXD (receive) */ +# define TIOCM_CTS (1 << 5) /* CTS (clear to send) */ +# define TIOCM_CAR (1 << 6) /* DCD (data carrier detect) */ +# define TIOCM_CD TIOCM_CAR +# define TIOCM_RNG (1 << 7) /* RNG (ring) */ +# define TIOCM_RI TIOCM_RNG +# define TIOCM_DSR (1 << 8) /* DSR (data set ready) */ + +/* TTY shutdown */ + +#define TIOCVHANGUP _TIOC(0x0022) /* Shutdown TTY: void */ + +/* Marking a line as local */ + +#define TIOCGSOFTCAR _TIOC(0x0023) /* Get software carrier flag: FAR int */ +#define TIOCSSOFTCAR _TIOC(0x0024) /* Set software carrier flag: FAR const int */ + +/* Get/set serial line info */ + +#define TIOCGSERIAL _TIOC(0x0025) /* Get serial line info: FAR struct serial_struct */ +#define TIOCSSERIAL _TIOC(0x0026) /* Set serial line info: FAR const struct serial_struct */ +#define TIOCSERGETLSR _TIOC(0x0027) /* Get line status register: FAR int */ + +/* Serial events */ + +#define TIOCMIWAIT _TIOC(0x0028) /* Wait for a change on serial input line(s): void */ +#define TIOCGICOUNT _TIOC(0x0029) /* Read serial port interrupt count: FAR struct serial_icounter_struct */ + +/* RS-485 Support */ + +#define TIOCSRS485 _TIOC(0x002a) /* Set RS485 mode, arg: pointer to struct serial_rs485 */ +#define TIOCGRS485 _TIOC(0x002b) /* Get RS485 mode, arg: pointer to struct serial_rs485 */ + +/* Debugging */ + +#define TIOCSERGSTRUCT _TIOC(0x002c) /* Get device TTY structure */ + +/* Definitions used in struct serial_rs485 (Linux compatible) */ + +#define SER_RS485_ENABLED (1 << 0) /* Enable/disble RS-485 support */ +#define SER_RS485_RTS_ON_SEND (1 << 1) /* Logic level for RTS pin when sending */ +#define SER_RS485_RTS_AFTER_SEND (1 << 2) /* Logic level for RTS pin after sent */ +#define SER_RS485_RX_DURING_TX (1 << 4) + +/******************************************************************************************** + * Public Type Definitions + ********************************************************************************************/ + +/* Used with TTY ioctls */ + +struct winsize +{ + uint16_t ws_row; + uint16_t ws_col; +/* uint16_t ws_xpixel; unused */ +/* uint16_t ws_ypixel; unused */ +}; + +/* Structure used with TIOCSRS485 and TIOCGRS485 (Linux compatible) */ + +struct serial_rs485 +{ + uint32_t flags; /* See SER_RS485_* definitions */ + uint32_t delay_rts_before_send; /* Delay before send (milliseconds) */ + uint32_t delay_rts_after_send; /* Delay after send (milliseconds) */ +}; + +/******************************************************************************************** + * Public Function Prototypes + ********************************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_SERIAL_TIOCTL_H */ diff --git a/nuttx/include/nuttx/serial/uart_16550.h b/nuttx/include/nuttx/serial/uart_16550.h new file mode 100644 index 0000000000..bc7ab8f951 --- /dev/null +++ b/nuttx/include/nuttx/serial/uart_16550.h @@ -0,0 +1,351 @@ +/************************************************************************************ + * include/nuttx/serial/uart_16550.h + * Serial driver for 16550 UART + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SERIAL_UART_16550_H +#define __INCLUDE_NUTTX_SERIAL_UART_16550_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#ifdef CONFIG_16550_UART + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* CONFIGURATION ********************************************************************/ + +/* Are any UARTs enabled? */ + +#undef HAVE_UART +#if defined(CONFIG_16550_UART0) || defined(CONFIG_16550_UART1) || \ + defined(CONFIG_16550_UART2) || defined(CONFIG_16550_UART3) +# define HAVE_UART 1 +#endif + +/* We need to be told the address increment between registers and the register bit + * width. + */ + +#ifndef CONFIG_16550_REGINCR +# error "CONFIG_16550_REGINCR not defined" +#endif + +#if CONFIG_16550_REGINCR != 1 && CONFIG_16550_REGINCR != 2 && CONFIG_16550_REGINCR != 4 +# error "CONFIG_16550_REGINCR not supported" +#endif + +#ifndef CONFIG_16550_REGWIDTH +# error "CONFIG_16550_REGWIDTH not defined" +#endif + +#if CONFIG_16550_REGWIDTH != 8 && CONFIG_16550_REGWIDTH != 16 && CONFIG_16550_REGWIDTH != 32 +# error "CONFIG_16550_REGWIDTH not supported" +#endif + +#ifndef CONFIG_16550_ADDRWIDTH +# error "CONFIG_16550_ADDRWIDTH not defined" +#endif + +#if CONFIG_16550_ADDRWIDTH != 8 && CONFIG_16550_ADDRWIDTH != 16 && CONFIG_16550_ADDRWIDTH != 32 +# error "CONFIG_16550_ADDRWIDTH not supported" +#endif + +/* If a UART is enabled, then its base address, clock, and IRQ must also be provided */ + +#ifdef CONFIG_16550_UART0 +# ifndef CONFIG_16550_UART0_BASE +# error "CONFIG_16550_UART0_BASE not provided" +# undef CONFIG_16550_UART0 +# endif +# ifndef CONFIG_16550_UART0_CLOCK +# error "CONFIG_16550_UART0_CLOCK not provided" +# undef CONFIG_16550_UART0 +# endif +# ifndef CONFIG_16550_UART0_IRQ +# error "CONFIG_16550_UART0_IRQ not provided" +# undef CONFIG_16550_UART0 +# endif +#endif + +#ifdef CONFIG_16550_UART1 +# ifndef CONFIG_16550_UART1_BASE +# error "CONFIG_16550_UART1_BASE not provided" +# undef CONFIG_16550_UART1 +# endif +# ifndef CONFIG_16550_UART1_CLOCK +# error "CONFIG_16550_UART1_CLOCK not provided" +# undef CONFIG_16550_UART1 +# endif +# ifndef CONFIG_16550_UART1_IRQ +# error "CONFIG_16550_UART1_IRQ not provided" +# undef CONFIG_16550_UART1 +# endif +#endif + +#ifdef CONFIG_16550_UART2 +# ifndef CONFIG_16550_UART2_BASE +# error "CONFIG_16550_UART2_BASE not provided" +# undef CONFIG_16550_UART2 +# endif +# ifndef CONFIG_16550_UART2_CLOCK +# error "CONFIG_16550_UART2_CLOCK not provided" +# undef CONFIG_16550_UART2 +# endif +# ifndef CONFIG_16550_UART2_IRQ +# error "CONFIG_16550_UART2_IRQ not provided" +# undef CONFIG_16550_UART2 +# endif +#endif + +#ifdef CONFIG_16550_UART3 +# ifndef CONFIG_16550_UART3_BASE +# error "CONFIG_16550_UART3_BASE not provided" +# undef CONFIG_16550_UART3 +# endif +# ifndef CONFIG_16550_UART3_CLOCK +# error "CONFIG_16550_UART3_CLOCK not provided" +# undef CONFIG_16550_UART3 +# endif +# ifndef CONFIG_16550_UART3_IRQ +# error "CONFIG_16550_UART3_IRQ not provided" +# undef CONFIG_16550_UART3 +# endif +#endif + +/* Is there a serial console? There should be at most one defined. It could be on + * any UARTn, n=0,1,2,3 + */ + +#if defined(CONFIG_UART0_SERIAL_CONSOLE) && defined(CONFIG_16550_UART0) +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# define HAVE_16550_CONSOLE 1 +#elif defined(CONFIG_UART1_SERIAL_CONSOLE) && defined(CONFIG_16550_UART1) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# define HAVE_16550_CONSOLE 1 +#elif defined(CONFIG_UART2_SERIAL_CONSOLE) && defined(CONFIG_16550_UART2) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# define HAVE_16550_CONSOLE 1 +#elif defined(CONFIG_UART3_SERIAL_CONSOLE) && defined(CONFIG_16550_UART3) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# define HAVE_16550_CONSOLE 1 +#else +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef HAVE_16550_CONSOLE +#endif + +/* Register offsets *****************************************************************/ + +#define UART_RBR_INCR 0 /* (DLAB =0) Receiver Buffer Register */ +#define UART_THR_INCR 0 /* (DLAB =0) Transmit Holding Register */ +#define UART_DLL_INCR 0 /* (DLAB =1) Divisor Latch LSB */ +#define UART_DLM_INCR 1 /* (DLAB =1) Divisor Latch MSB */ +#define UART_IER_INCR 1 /* (DLAB =0) Interrupt Enable Register */ +#define UART_IIR_INCR 2 /* Interrupt ID Register */ +#define UART_FCR_INCR 2 /* FIFO Control Register */ +#define UART_LCR_INCR 3 /* Line Control Register */ +#define UART_MCR_INCR 4 /* Modem Control Register */ +#define UART_LSR_INCR 5 /* Line Status Register */ +#define UART_MSR_INCR 6 /* Modem Status Register */ +#define UART_SCR_INCR 7 /* Scratch Pad Register */ + +#define UART_RBR_OFFSET (CONFIG_16550_REGINCR*UART_RBR_INCR) +#define UART_THR_OFFSET (CONFIG_16550_REGINCR*UART_THR_INCR) +#define UART_DLL_OFFSET (CONFIG_16550_REGINCR*UART_DLL_INCR) +#define UART_DLM_OFFSET (CONFIG_16550_REGINCR*UART_DLM_INCR) +#define UART_IER_OFFSET (CONFIG_16550_REGINCR*UART_IER_INCR) +#define UART_IIR_OFFSET (CONFIG_16550_REGINCR*UART_IIR_INCR) +#define UART_FCR_OFFSET (CONFIG_16550_REGINCR*UART_FCR_INCR) +#define UART_LCR_OFFSET (CONFIG_16550_REGINCR*UART_LCR_INCR) +#define UART_MCR_OFFSET (CONFIG_16550_REGINCR*UART_MCR_INCR) +#define UART_LSR_OFFSET (CONFIG_16550_REGINCR*UART_LSR_INCR) +#define UART_MSR_OFFSET (CONFIG_16550_REGINCR*UART_MSR_INCR) +#define UART_SCR_OFFSET (CONFIG_16550_REGINCR*UART_SCR_INCR) + +/* Register bit definitions *********************************************************/ + +/* RBR (DLAB =0) Receiver Buffer Register */ + +#define UART_RBR_MASK (0xff) /* Bits 0-7: Oldest received byte in RX FIFO */ + /* Bits 8-31: Reserved */ + +/* THR (DLAB =0) Transmit Holding Register */ + +#define UART_THR_MASK (0xff) /* Bits 0-7: Adds byte to TX FIFO */ + /* Bits 8-31: Reserved */ + +/* DLL (DLAB =1) Divisor Latch LSB */ + +#define UART_DLL_MASK (0xff) /* Bits 0-7: DLL */ + /* Bits 8-31: Reserved */ + +/* DLM (DLAB =1) Divisor Latch MSB */ + +#define UART_DLM_MASK (0xff) /* Bits 0-7: DLM */ + /* Bits 8-31: Reserved */ + +/* IER (DLAB =0) Interrupt Enable Register */ + +#define UART_IER_ERBFI (1 << 0) /* Bit 0: Enable received data available interrupt */ +#define UART_IER_ETBEI (1 << 1) /* Bit 1: Enable THR empty interrupt */ +#define UART_IER_ELSI (1 << 2) /* Bit 2: Enable receiver line status interrupt */ +#define UART_IER_EDSSI (1 << 3) /* Bit 3: Enable MODEM status interrupt */ + /* Bits 4-7: Reserved */ +#define UART_IER_ALLIE (0x0f) + +/* IIR Interrupt ID Register */ + +#define UART_IIR_INTSTATUS (1 << 0) /* Bit 0: Interrupt status (active low) */ +#define UART_IIR_INTID_SHIFT (1) /* Bits 1-3: Interrupt identification */ +#define UART_IIR_INTID_MASK (7 << UART_IIR_INTID_SHIFT) +# define UART_IIR_INTID_MSI (0 << UART_IIR_INTID_SHIFT) /* Modem Status */ +# define UART_IIR_INTID_THRE (1 << UART_IIR_INTID_SHIFT) /* THR Empty Interrupt */ +# define UART_IIR_INTID_RDA (2 << UART_IIR_INTID_SHIFT) /* Receive Data Available (RDA) */ +# define UART_IIR_INTID_RLS (3 << UART_IIR_INTID_SHIFT) /* Receiver Line Status (RLS) */ +# define UART_IIR_INTID_CTI (6 << UART_IIR_INTID_SHIFT) /* Character Time-out Indicator (CTI) */ + /* Bits 4-5: Reserved */ +#define UART_IIR_FIFOEN_SHIFT (6) /* Bits 6-7: RCVR FIFO interrupt */ +#define UART_IIR_FIFOEN_MASK (3 << UART_IIR_FIFOEN_SHIFT) + +/* FCR FIFO Control Register */ + +#define UART_FCR_FIFOEN (1 << 0) /* Bit 0: Enable FIFOs */ +#define UART_FCR_RXRST (1 << 1) /* Bit 1: RX FIFO Reset */ +#define UART_FCR_TXRST (1 << 2) /* Bit 2: TX FIFO Reset */ +#define UART_FCR_DMAMODE (1 << 3) /* Bit 3: DMA Mode Select */ + /* Bits 4-5: Reserved */ +#define UART_FCR_RXTRIGGER_SHIFT (6) /* Bits 6-7: RX Trigger Level */ +#define UART_FCR_RXTRIGGER_MASK (3 << UART_FCR_RXTRIGGER_SHIFT) +# define UART_FCR_RXTRIGGER_1 (0 << UART_FCR_RXTRIGGER_SHIFT) /* Trigger level 0 (1 character) */ +# define UART_FCR_RXTRIGGER_4 (1 << UART_FCR_RXTRIGGER_SHIFT) /* Trigger level 1 (4 characters) */ +# define UART_FCR_RXTRIGGER_8 (2 << UART_FCR_RXTRIGGER_SHIFT) /* Trigger level 2 (8 characters) */ +# define UART_FCR_RXTRIGGER_14 (3 << UART_FCR_RXTRIGGER_SHIFT) /* Trigger level 3 (14 characters) */ + +/* LCR Line Control Register */ + +#define UART_LCR_WLS_SHIFT (0) /* Bit 0-1: Word Length Select */ +#define UART_LCR_WLS_MASK (3 << UART_LCR_WLS_SHIFT) +# define UART_LCR_WLS_5BIT (0 << UART_LCR_WLS_SHIFT) +# define UART_LCR_WLS_6BIT (1 << UART_LCR_WLS_SHIFT) +# define UART_LCR_WLS_7BIT (2 << UART_LCR_WLS_SHIFT) +# define UART_LCR_WLS_8BIT (3 << UART_LCR_WLS_SHIFT) +#define UART_LCR_STB (1 << 2) /* Bit 2: Number of Stop Bits */ +#define UART_LCR_PEN (1 << 3) /* Bit 3: Parity Enable */ +#define UART_LCR_EPS (1 << 4) /* Bit 4: Even Parity Select */ +#define UART_LCR_STICKY (1 << 5) /* Bit 5: Stick Parity */ +#define UART_LCR_BRK (1 << 6) /* Bit 6: Break Control */ +#define UART_LCR_DLAB (1 << 7) /* Bit 7: Divisor Latch Access Bit (DLAB) */ + +/* MCR Modem Control Register */ + +#define UART_MCR_DTR (1 << 0) /* Bit 0: DTR Control Source for DTR output */ +#define UART_MCR_RTS (1 << 1) /* Bit 1: Control Source for RTS output */ +#define UART_MCR_OUT1 (1 << 2) /* Bit 2: Auxiliary user-defined output 1 */ +#define UART_MCR_OUT2 (1 << 3) /* Bit 3: Auxiliary user-defined output 2 */ +#define UART_MCR_LPBK (1 << 4) /* Bit 4: Loopback Mode Select */ + /* Bit 5-7: Reserved */ + +/* LSR Line Status Register */ + +#define UART_LSR_DR (1 << 0) /* Bit 0: Data Ready */ +#define UART_LSR_OE (1 << 1) /* Bit 1: Overrun Error */ +#define UART_LSR_PE (1 << 2) /* Bit 2: Parity Error */ +#define UART_LSR_FE (1 << 3) /* Bit 3: Framing Error */ +#define UART_LSR_BI (1 << 4) /* Bit 4: Break Interrupt */ +#define UART_LSR_THRE (1 << 5) /* Bit 5: Transmitter Holding Register Empty */ +#define UART_LSR_TEMT (1 << 6) /* Bit 6: Transmitter Empty */ +#define UART_LSR_RXFE (1 << 7) /* Bit 7: Error in RX FIFO (RXFE) */ + +/* SCR Scratch Pad Register */ + +#define UART_SCR_MASK (0xff) /* Bits 0-7: SCR data */ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +#if CONFIG_16550_REGWIDTH == 8 +typedef uint8_t uart_datawidth_t; +#elif CONFIG_16550_REGWIDTH == 16 +typedef uint16_t uart_datawidth_t; +#elif CONFIG_16550_REGWIDTH == 32 +typedef uint32_t uart_datawidth_t; +#endif + +#if CONFIG_16550_ADDRWIDTH == 8 +typedef uint8_t uart_addrwidth_t; +#elif CONFIG_16550_ADDRWIDTH == 16 +typedef uint16_t uart_addrwidth_t; +#elif CONFIG_16550_ADDRWIDTH == 32 +typedef uint32_t uart_addrwidth_t; +#endif + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: uart_getreg(), uart_putreg() + * + * Description: + * These functions must be provided by the processor-specific code in order to + * correctly access 16550 registers + * + ************************************************************************************/ + +extern uart_datawidth_t uart_getreg(uart_addrwidth_t base, unsigned int offset); +extern void uart_putreg(uart_addrwidth_t base, unsigned int offset, uart_datawidth_t value); + +#endif /* CONFIG_UART_16550 */ +#endif /* __INCLUDE_NUTTX_SERIAL_UART_16550_H */ diff --git a/nuttx/include/nuttx/spi.h b/nuttx/include/nuttx/spi.h new file mode 100644 index 0000000000..6448dc7c57 --- /dev/null +++ b/nuttx/include/nuttx/spi.h @@ -0,0 +1,446 @@ +/**************************************************************************** + * include/nuttx/spi.h + * + * Copyright(C) 2008-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SPI_H +#define __INCLUDE_NUTTX_SPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_SPI_OWNBUS - Set if there is only one active device on the SPI bus. + * No locking or SPI configuration will be performed. It is not necessary + * for clients to lock, re-configure, etc.. + * CONFIG_SPI_EXCHANGE - Driver supports a single exchange method + * (vs a recvblock() and sndblock ()methods). + * CONFIG_SPI_CMDDATA - Devices on the SPI bus require out-of-band support + * to distinguish command transfers from data transfers. Such devices + * will often support either 9-bit SPI (yech) or 8-bit SPI and a GPIO + * output that selects between command and data. + */ + +/* Access macros ************************************************************/ + +/**************************************************************************** + * Name: SPI_LOCK + * + * Description: + * On SPI busses where there are multiple devices, it will be necessary to + * lock SPI to have exclusive access to the busses for a sequence of + * transfers. The bus should be locked before the chip is selected. After + * locking the SPI bus, the caller should then also call the setfrequency, + * setbits, and setmode methods to make sure that the SPI is properly + * configured for the device. If the SPI buss is being shared, then it + * may have been left in an incompatible state. + * + * Input Parameters: + * dev - Device-specific state data + * lock - true: Lock spi bus, false: unlock SPI bus + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifndef CONFIG_SPI_OWNBUS +# define SPI_LOCK(d,l) (d)->ops->lock(d,l) +#else +# define SPI_LOCK(d,l) 0 +#endif + +/**************************************************************************** + * Name: SPI_SELECT + * + * Description: + * Enable/disable the SPI chip select. The implementation of this method + * must include handshaking: If a device is selected, it must hold off + * all other attempts to select the device until the device is deselected. + * Required. + * + * Input Parameters: + * dev - Device-specific state data + * devid - Identifies the device to select + * selected - true: slave selected, false: slave de-selected + * + * Returned Value: + * None + * + ****************************************************************************/ + +#define SPI_SELECT(d,id,s) ((d)->ops->select(d,id,s)) + +/**************************************************************************** + * Name: SPI_SETFREQUENCY + * + * Description: + * Set the SPI frequency. Required. + * + * Input Parameters: + * dev - Device-specific state data + * frequency - The SPI frequency requested + * + * Returned Value: + * Returns the actual frequency selected + * + ****************************************************************************/ + +#define SPI_SETFREQUENCY(d,f) ((d)->ops->setfrequency(d,f)) + +/**************************************************************************** + * Name: SPI_SETMODE + * + * Description: + * Set the SPI mode. Optional. See enum spi_mode_e for mode definitions. + * + * Input Parameters: + * dev - Device-specific state data + * mode - The SPI mode requested + * + * Returned Value: + * none + * + ****************************************************************************/ + +#define SPI_SETMODE(d,m) \ + do { if ((d)->ops->setmode) (d)->ops->setmode(d,m); } while (0) + +/**************************************************************************** + * Name: SPI_SETBITS + * + * Description: + * Set the number if bits per word. + * + * Input Parameters: + * dev - Device-specific state data + * nbits - The number of bits requests. + * If value is greater > 0 then it implies MSB first + * If value is below < 0, then it implies LSB first with -nbits + * + * Returned Value: + * none + * + ****************************************************************************/ + +#define SPI_SETBITS(d,b) \ + do { if ((d)->ops->setbits) (d)->ops->setbits(d,b); } while (0) + +/**************************************************************************** + * Name: SPI_STATUS + * + * Description: + * Get SPI/MMC status. Optional. + * + * Input Parameters: + * dev - Device-specific state data + * devid - Identifies the device to report status on + * + * Returned Value: + * Returns a bitset of status values (see SPI_STATUS_* defines) + * + ****************************************************************************/ + +#define SPI_STATUS(d,id) \ + ((d)->ops->status ? (d)->ops->status(d, id) : SPI_STATUS_PRESENT) + +/* SPI status bits -- Some dedicated for SPI MMC/SD support and may have no + * relationship to SPI other than needed by the SPI MMC/SD interface + */ + +#define SPI_STATUS_PRESENT 0x01 /* Bit 0=1: MMC/SD card present */ +#define SPI_STATUS_WRPROTECTED 0x02 /* Bit 1=1: MMC/SD card write protected */ + +/**************************************************************************** + * Name: SPI_CMDDATA + * + * Description: + * Some devices require and additional out-of-band bit to specify if the + * next word sent to the device is a command or data. This is typical, for + * example, in "9-bit" displays where the 9th bit is the CMD/DATA bit. + * This function provides selection of command or data. + * + * This "latches" the CMD/DATA state. It does not have to be called before + * every word is transferred; only when the CMD/DATA state changes. This + * method is required if CONFIG_SPI_CMDDATA is selected in the NuttX + * configuration + * + * Input Parameters: + * dev - Device-specific state data + * cmd - TRUE: The following word is a command; FALSE: the following words + * are data. + * + * Returned Value: + * OK unless an error occurs. Then a negated errno value is returned + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_CMDDATA +# define SPI_CMDDATA(d,id,cmd) ((d)->ops->cmddata(d,id,cmd)) +#endif + +/**************************************************************************** + * Name: SPI_SEND + * + * Description: + * Exchange one word on SPI. Required. + * + * Input Parameters: + * dev - Device-specific state data + * wd - The word to send. the size of the data is determined by the + * number of bits selected for the SPI interface. + * + * Returned Value: + * Received value + * + ****************************************************************************/ + +#define SPI_SEND(d,wd) ((d)->ops->send(d,(uint16_t)wd)) + +/**************************************************************************** + * Name: SPI_SNDBLOCK + * + * Description: + * Send a block of data on SPI. Required. + * + * Input Parameters: + * dev - Device-specific state data + * buffer - A pointer to the buffer of data to be sent + * nwords - the length of data to send from the buffer in number of words. + * The wordsize is determined by the number of bits-per-word + * selected for the SPI interface. If nbits <= 8, the data is + * packed into uint8_t's; if nbits >8, the data is packed into + * uint16_t's + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_EXCHANGE +# define SPI_SNDBLOCK(d,b,l) ((d)->ops->exchange(d,b,0,l)) +#else +# define SPI_SNDBLOCK(d,b,l) ((d)->ops->sndblock(d,b,l)) +#endif + +/**************************************************************************** + * Name: SPI_RECVBLOCK + * + * Description: + * Receive a block of data from SPI. Required. + * + * Input Parameters: + * dev - Device-specific state data + * buffer - A pointer to the buffer in which to recieve data + * nwords - the length of data that can be received in the buffer in number + * of words. The wordsize is determined by the number of bits- + * per-word selected for the SPI interface. If nbits <= 8, the + * data is packed into uint8_t's; if nbits >8, the data is packed + * into uint16_t's + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_EXCHANGE +# define SPI_RECVBLOCK(d,b,l) ((d)->ops->exchange(d,0,b,l)) +#else +# define SPI_RECVBLOCK(d,b,l) ((d)->ops->recvblock(d,b,l)) +#endif + +/**************************************************************************** + * Name: SPI_EXCHANGE + * + * Description: + * Exahange a block of data from SPI. Required. + * + * Input Parameters: + * dev - Device-specific state data + * txbuffer - A pointer to the buffer of data to be sent + * rxbuffer - A pointer to the buffer in which to recieve data + * nwords - the length of data that to be exchanged in units of words. + * The wordsize is determined by the number of bits-per-word + * selected for the SPI interface. If nbits <= 8, the data is + * packed into uint8_t's; if nbits >8, the data is packed into + * uint16_t's + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_EXCHANGE +# define SPI_EXCHANGE(d,t,r,l) ((d)->ops->exchange(d,t,r,l)) +#endif + +/**************************************************************************** + * Name: SPI_REGISTERCALLBACK + * + * Description: + * Register a callback that that will be invoked on any media status + * change (i.e, anything that would be reported differently by SPI_STATUS). + * Optional + * + * Input Parameters: + * dev - Device-specific state data + * callback - The funtion to call on the media change + * arg - A caller provided value to return with the callback + * + * Returned Value: + * 0 on success; negated errno on failure. + * + ****************************************************************************/ + +#define SPI_REGISTERCALLBACK(d,c,a) \ + ((d)->ops->registercallback ? (d)->ops->registercallback(d,c,a) : -ENOSYS) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The type of the media change callback function */ + +typedef void (*spi_mediachange_t)(FAR void *arg); + +/* If the board supports multiple SPI devices, this enumeration identifies + * which is selected or de-seleted. + */ + +enum spi_dev_e +{ + SPIDEV_NONE = 0, /* Not a valid value */ + SPIDEV_MMCSD, /* Select SPI MMC/SD device */ + SPIDEV_FLASH, /* Select SPI FLASH device */ + SPIDEV_ETHERNET, /* Select SPI ethernet device */ + SPIDEV_DISPLAY, /* Select SPI LCD/OLED display device */ + SPIDEV_WIRELESS, /* Select SPI Wireless device */ + SPIDEV_TOUCHSCREEN, /* Select SPI touchscreen device */ + SPIDEV_EXPANDER, /* Select SPI I/O expander device */ + SPIDEV_MUX /* Select SPI multiplexer device */ +}; + +/* Certain SPI devices may required differnt clocking modes */ + +enum spi_mode_e +{ + SPIDEV_MODE0 = 0, /* CPOL=0 CHPHA=0 */ + SPIDEV_MODE1, /* CPOL=0 CHPHA=1 */ + SPIDEV_MODE2, /* CPOL=1 CHPHA=0 */ + SPIDEV_MODE3 /* CPOL=1 CHPHA=1 */ +}; + +/* The SPI vtable */ + +struct spi_dev_s; +struct spi_ops_s +{ +#ifndef CONFIG_SPI_OWNBUS + int (*lock)(FAR struct spi_dev_s *dev, bool lock); +#endif + void (*select)(FAR struct spi_dev_s *dev, enum spi_dev_e devid, + bool selected); + uint32_t (*setfrequency)(FAR struct spi_dev_s *dev, uint32_t frequency); + void (*setmode)(FAR struct spi_dev_s *dev, enum spi_mode_e mode); + void (*setbits)(FAR struct spi_dev_s *dev, int nbits); + uint8_t (*status)(FAR struct spi_dev_s *dev, enum spi_dev_e devid); +#ifdef CONFIG_SPI_CMDDATA + int (*cmddata)(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd); +#endif + uint16_t (*send)(FAR struct spi_dev_s *dev, uint16_t wd); +#ifdef CONFIG_SPI_EXCHANGE + void (*exchange)(FAR struct spi_dev_s *dev, FAR const void *txbuffer, + FAR void *rxbuffer, size_t nwords); +#else + void (*sndblock)(FAR struct spi_dev_s *dev, FAR const void *buffer, + size_t nwords); + void (*recvblock)(FAR struct spi_dev_s *dev, FAR void *buffer, + size_t nwords); +#endif + int (*registercallback)(FAR struct spi_dev_s *dev, spi_mediachange_t callback, + void *arg); +}; + +/* SPI private data. This structure only defines the initial fields of the + * structure visible to the SPI client. The specific implementation may + * add additional, device specific fields + */ + +struct spi_dev_s +{ + const struct spi_ops_s *ops; +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: up_spiinitialize + * + * Description: + * Initialize the selected SPI port. + * + * Input Parameter: + * Port number (for hardware that has mutiple SPI interfaces) + * + * Returned Value: + * Valid SPI device structre reference on succcess; a NULL on failure + * + ****************************************************************************/ + +EXTERN FAR struct spi_dev_s *up_spiinitialize(int port); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __INCLUDE_NUTTX_SPI_H */ diff --git a/nuttx/include/nuttx/stdarg.h b/nuttx/include/nuttx/stdarg.h new file mode 100644 index 0000000000..45d16b2d1c --- /dev/null +++ b/nuttx/include/nuttx/stdarg.h @@ -0,0 +1,64 @@ +/**************************************************************************** + * include/nuttx/stdarg.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_STDARG_H +#define __INCLUDE_NUTTX_STDARG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* If CONFIG_ARCH_STDARG_H is defined, then the top-level Makefile will copy + * this header file to include/stdarg.h where it will become the system + * stdarg.h header file. In this case, the architecture specific code must + * provide an arch//include/math.h file which will be included + * below: + */ + +#ifdef CONFIG_ARCH_STDARG_H +# include +#endif + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __INCLUDE_NUTTX_STDARG_H */ diff --git a/nuttx/include/nuttx/streams.h b/nuttx/include/nuttx/streams.h new file mode 100644 index 0000000000..38ceb584c7 --- /dev/null +++ b/nuttx/include/nuttx/streams.h @@ -0,0 +1,295 @@ +/**************************************************************************** + * include/nuttx/streams.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef _INCLUDE_NUTTX_STREAMS_H +#define _INCLUDE_NUTTX_STREAMS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* These are the generic representations of a streams used by the NuttX */ + +struct lib_instream_s; +struct lib_outstream_s; + +typedef int (*lib_getc_t)(FAR struct lib_instream_s *this); +typedef void (*lib_putc_t)(FAR struct lib_outstream_s *this, int ch); +typedef int (*lib_flush_t)(FAR struct lib_outstream_s *this); + +struct lib_instream_s +{ + lib_getc_t get; /* Pointer to function to get one character */ + int nget; /* Total number of characters gotten. Written + * by get method, readable by user */ +}; + +struct lib_outstream_s +{ + lib_putc_t put; /* Pointer to function to put one character */ +#ifdef CONFIG_STDIO_LINEBUFFER + lib_flush_t flush; /* Pointer to function flush buffered characters */ +#endif + int nput; /* Total number of characters put. Written + * by put method, readable by user */ +}; + +/* These are streams that operate on a fixed-sized block of memory */ + +struct lib_meminstream_s +{ + struct lib_instream_s public; + FAR const char *buffer; /* Address of first byte in the buffer */ + int buflen; /* Size of the buffer in bytes */ +}; + +struct lib_memoutstream_s +{ + struct lib_outstream_s public; + FAR char *buffer; /* Address of first byte in the buffer */ + int buflen; /* Size of the buffer in bytes */ +}; + +/* These are streams that operate on a FILE */ + +struct lib_stdinstream_s +{ + struct lib_instream_s public; + FAR FILE *stream; +}; + +struct lib_stdoutstream_s +{ + struct lib_outstream_s public; + FAR FILE *stream; +}; + +/* These are streams that operate on a file descriptor */ + +struct lib_rawoutstream_s +{ + struct lib_outstream_s public; + int fd; +}; + +struct lib_rawinstream_s +{ + struct lib_instream_s public; + int fd; +}; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" +{ +#else +# define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_meminstream, lib_memoutstream + * + * Description: + * Initializes a stream for use with a fixed-size memory buffer. + * Defined in lib/lib_meminstream.c and lib/lib_memoutstream.c + * + * Input parameters: + * meminstream - User allocated, uninitialized instance of struct + * lib_meminstream_s to be initialized. + * memoutstream - User allocated, uninitialized instance of struct + * lib_memoutstream_s to be initialized. + * bufstart - Address of the beginning of the fixed-size memory buffer + * buflen - Size of the fixed-sized memory buffer in bytes + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +EXTERN void lib_meminstream(FAR struct lib_meminstream_s *meminstream, + FAR const char *bufstart, int buflen); +EXTERN void lib_memoutstream(FAR struct lib_memoutstream_s *memoutstream, + FAR char *bufstart, int buflen); + +/**************************************************************************** + * Name: lib_stdinstream, lib_stdoutstream + * + * Description: + * Initializes a stream for use with a FILE instance. + * Defined in lib/lib_stdinstream.c and lib/lib_stdoutstream.c + * + * Input parameters: + * stdinstream - User allocated, uninitialized instance of struct + * lib_stdinstream_s to be initialized. + * stdoutstream - User allocated, uninitialized instance of struct + * lib_stdoutstream_s to be initialized. + * stream - User provided stream instance (must have been opened for + * the correct access). + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +EXTERN void lib_stdinstream(FAR struct lib_stdinstream_s *stdinstream, + FAR FILE *stream); +EXTERN void lib_stdoutstream(FAR struct lib_stdoutstream_s *stdoutstream, + FAR FILE *stream); + +/**************************************************************************** + * Name: lib_rawinstream, lib_rawoutstream + * + * Description: + * Initializes a stream for use with a file descriptor. + * Defined in lib/lib_rawinstream.c and lib/lib_rawoutstream.c + * + * Input parameters: + * rawinstream - User allocated, uninitialized instance of struct + * lib_rawinstream_s to be initialized. + * rawoutstream - User allocated, uninitialized instance of struct + * lib_rawoutstream_s to be initialized. + * fd - User provided file/socket descriptor (must have been opened + * for the correct access). + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +EXTERN void lib_rawinstream(FAR struct lib_rawinstream_s *rawinstream, + int fd); +EXTERN void lib_rawoutstream(FAR struct lib_rawoutstream_s *rawoutstream, + int fd); + +/**************************************************************************** + * Name: lib_lowinstream, lib_lowoutstream + * + * Description: + * Initializes a stream for use with low-level, architecture-specific I/O. + * Defined in lib/lib_lowinstream.c and lib/lib_lowoutstream.c + * + * Input parameters: + * lowinstream - User allocated, uninitialized instance of struct + * lib_lowinstream_s to be initialized. + * lowoutstream - User allocated, uninitialized instance of struct + * lib_lowoutstream_s to be initialized. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_LOWGETC +EXTERN void lib_lowinstream(FAR struct lib_instream_s *lowinstream); +#endif +#ifdef CONFIG_ARCH_LOWPUTC +EXTERN void lib_lowoutstream(FAR struct lib_outstream_s *lowoutstream); +#endif + +/**************************************************************************** + * Name: lib_zeroinstream, lib_nullinstream, lib_nulloutstream + * + * Description: + * Initializes NULL streams: + * + * o The stream created by lib_zeroinstream will return an infinitely long + * stream of zeroes. Defined in lib/lib_zeroinstream.c + * o The stream created by lib_nullinstream will return only EOF. + * Defined in lib/lib_nullinstream.c + * o The stream created by lib_nulloutstream will write all data to the + * bit-bucket. Defined in lib/lib_nulloutstream.c + * + * Input parameters: + * zeroinstream - User allocated, uninitialized instance of struct + * lib_instream_s to be initialized. + * nullinstream - User allocated, uninitialized instance of struct + * lib_instream_s to be initialized. + * nulloutstream - User allocated, uninitialized instance of struct + * lib_outstream_s to be initialized. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +EXTERN void lib_zeroinstream(FAR struct lib_instream_s *zeroinstream); +EXTERN void lib_nullinstream(FAR struct lib_instream_s *nullinstream); +EXTERN void lib_nulloutstream(FAR struct lib_outstream_s *nulloutstream); + +/**************************************************************************** + * Name: lib_sylogstream + * + * Description: + * Initializes a stream for use with the configured syslog interface. + * + * Input parameters: + * lowoutstream - User allocated, uninitialized instance of struct + * lib_lowoutstream_s to be initialized. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +#ifdef CONFIG_SYSLOG +EXTERN void lib_syslogstream(FAR struct lib_outstream_s *stream); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* _INCLUDE_NUTTX_STREAMS_H */ diff --git a/nuttx/include/nuttx/symtab.h b/nuttx/include/nuttx/symtab.h new file mode 100644 index 0000000000..b302ab20a9 --- /dev/null +++ b/nuttx/include/nuttx/symtab.h @@ -0,0 +1,163 @@ +/**************************************************************************** + * include/nuttx/symtab.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SYMTAB_H +#define __INCLUDE_NUTTX_SYMTAB_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* struct symbtab_s describes one entry in the symbol table. A symbol table + * is a fixed size array of struct symtab_s. The information is intentionally + * minimal and supports only: + * + * 1. Function points as sym_values. Of other kinds of values need to be + * supported, then typing information would also need to be included in + * the structure. + * + * 2. Fixed size arrays. There is no explicit provisional for dyanamically + * adding or removing entries from the symbol table (realloc might be + * used for that purpose if needed). The intention is to support only + * fixed size arrays completely defined at compilation or link time. + */ + +struct symtab_s +{ + FAR const char *sym_name; /* A pointer to the symbol name string */ + FAR const void *sym_value; /* The value associated witht the string */ +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: symtab_findbyname + * + * Description: + * Find the symbol in the symbol table with the matching name. + * This version assumes that table is not ordered with respect to symbol + * name and, hence, access time will be linear with respect to nsyms. + * + * Returned Value: + * A reference to the symbol table entry if an entry with the matching + * name is found; NULL is returned if the entry is not found. + * + ****************************************************************************/ + +EXTERN FAR const struct symtab_s * +symtab_findbyname(FAR const struct symtab_s *symtab, + FAR const char *name, int nsyms); + +/**************************************************************************** + * Name: symtab_findorderedbyname + * + * Description: + * Find the symbol in the symbol table with the matching name. + * This version assumes that table ordered with respect to symbol name. + * + * Returned Value: + * A reference to the symbol table entry if an entry with the matching + * name is found; NULL is returned if the entry is not found. + * + ****************************************************************************/ + +EXTERN FAR const struct symtab_s * +symtab_findorderedbyname(FAR const struct symtab_s *symtab, + FAR const char *name, int nsyms); + +/**************************************************************************** + * Name: symtab_findbyvalue + * + * Description: + * Find the symbol in the symbol table whose value closest (but not greater + * than), the provided value. This version assumes that table is not ordered + * with respect to symbol name and, hence, access time will be linear with + * respect to nsyms. + * + * Returned Value: + * A reference to the symbol table entry if an entry with the matching + * name is found; NULL is returned if the entry is not found. + * + ****************************************************************************/ + +EXTERN FAR const struct symtab_s * +symtab_findbyvalue(FAR const struct symtab_s *symtab, + FAR void *value, int nsyms); + +/**************************************************************************** + * Name: symtab_findorderedbyvalue + * + * Description: + * Find the symbol in the symbol table whose value closest (but not greater + * than), the provided value. This version assumes that table is ordered + * with respect to symbol name. + * + * Returned Value: + * A reference to the symbol table entry if an entry with the matching + * name is found; NULL is returned if the entry is not found. + * + ****************************************************************************/ + +EXTERN FAR const struct symtab_s * +symtab_findorderedbyvalue(FAR const struct symtab_s *symtab, + FAR void *value, int nsyms); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_SYMTAB_H */ + diff --git a/nuttx/include/nuttx/syslog.h b/nuttx/include/nuttx/syslog.h new file mode 100644 index 0000000000..3c340d23a0 --- /dev/null +++ b/nuttx/include/nuttx/syslog.h @@ -0,0 +1,136 @@ +/**************************************************************************** + * include/nuttx/syslog.h + * The NuttX SYSLOGing interface + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SYSLOG_H +#define __INCLUDE_NUTTX_SYSLOG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_SYSLOG - Enables generic system logging features. + * CONFIG_SYSLOG_DEVPATH - The full path to the system logging device + * + * In addition, some SYSLOG device must also be enabled that will provide + * the syslog_putc() function. As of this writing, there are two SYSLOG + * devices avaiable: + * + * 1. A RAM SYSLOGing device that will log data into a circular buffer + * that can be dumped using the NSH dmesg command. This device is + * described in the include/nuttx/ramlog.h header file. + * + * 2. And a generic character device that may be used as the SYSLOG. The + * generic device interfaces are described in this file. A disadvantage + * of using the generic character device for the SYSLOG is that it + * cannot handle debug output generated from interrupt level handlers. + * + * CONFIG_SYSLOG_CHAR - Enable the generic character device for the SYSLOG. + * The full path to the SYSLOG device is provided by CONFIG_SYSLOG_DEVPATH. + * A valid character device must exist at this path. It will by opened + * by syslog_initialize. + * + * NOTE: No more than one SYSLOG device should be configured. + */ + +#ifndef CONFIG_SYSLOG +# undef CONFIG_SYSLOG_CHAR +#endif + +#if defined(CONFIG_SYSLOG_CHAR) && !defined(CONFIG_SYSLOG_DEVPATH) +# define CONFIG_SYSLOG_DEVPATH "/dev/ttyS1" +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +/**************************************************************************** + * Name: syslog_initialize + * + * Description: + * Initialize to use the character device (or file) at + * CONFIG_SYSLOG_DEVPATH as the SYSLOG sink. + * + * NOTE that this implementation excludes using a network connection as + * SYSLOG device. That would be a good extension. + * + ****************************************************************************/ + +#ifdef CONFIG_SYSLOG_CHAR +EXTERN int syslog_initialize(void); +#endif + +/**************************************************************************** + * Name: syslog_putc + * + * Description: + * This is the low-level system logging interface. The debugging/syslogging + * interfaces are lib_rawprintf() and lib_lowprinf(). The difference is + * the lib_rawprintf() writes to fd=1 (stdout) and lib_lowprintf() uses + * a lower level interface that works from interrupt handlers. This + * function is a a low-level interface used to implement lib_lowprintf(). + * + ****************************************************************************/ + +#ifdef CONFIG_SYSLOG +EXTERN int syslog_putc(int ch); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __INCLUDE_NUTTX_SYSLOG_H */ diff --git a/nuttx/include/nuttx/time.h b/nuttx/include/nuttx/time.h new file mode 100644 index 0000000000..58caa34301 --- /dev/null +++ b/nuttx/include/nuttx/time.h @@ -0,0 +1,120 @@ +/**************************************************************************** + * include/nuttx/time.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_TIME_H +#define __INCLUDE_NUTTX_TIME_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* If Gregorian time is not supported, then neither is Julian */ + +#ifndef CONFIG_GREGORIAN_TIME +# undef CONFIG_JULIAN_TIME +#else +# define JD_OF_EPOCH 2440588 /* Julian Date of noon, J1970 */ + +# ifdef CONFIG_JULIAN_TIME +# define GREG_DUTC -141427 /* Default is October 15, 1582 */ +# define GREG_YEAR 1582 +# define GREG_MONTH 10 +# define GREG_DAY 15 +# endif /* CONFIG_JULIAN_TIME */ +#endif /* !CONFIG_GREGORIAN_TIME */ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Function: clock_isleapyear + * + * Description: + * Return true if the specified year is a leap year + * + ****************************************************************************/ + +EXTERN int clock_isleapyear(int year); + +/**************************************************************************** + * Function: clock_daysbeforemonth + * + * Description: + * Get the number of days that occurred before the beginning of the month. + * + ****************************************************************************/ + +EXTERN int clock_daysbeforemonth(int month, bool leapyear); + +/**************************************************************************** + * Function: clock_calendar2utc + * + * Description: + * Calendar/UTC conversion based on algorithms from p. 604 + * of Seidelman, P. K. 1992. Explanatory Supplement to + * the Astronomical Almanac. University Science Books, + * Mill Valley. + * + ****************************************************************************/ + +EXTERN time_t clock_calendar2utc(int year, int month, int day); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_TIME_H */ diff --git a/nuttx/include/nuttx/usb/audio.h b/nuttx/include/nuttx/usb/audio.h new file mode 100644 index 0000000000..97c3ed6cb4 --- /dev/null +++ b/nuttx/include/nuttx/usb/audio.h @@ -0,0 +1,1618 @@ +/******************************************************************************************** + * include/nuttx/usb/audio.h + * Audio Device Class (ADC) definitions + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: This header file is based on information provided by the + * documents for the Audio v2.0 package: + * + * 1. Universal Serial Bus Device Class Definition for Audio Devices, Release + * 2.0, May 31, 2006, + * 2. Universal Serial Bus Device Class Definition for Audio Data Formats, + * Release 2.0, May 31, 2006 + * 3. Universal Serial Bus Device Class Definition for Terminal Types,\ + * Release 2.0, May 31, 2006, + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_USB_AUDIO_H +#define __INCLUDE_NUTTX_USB_AUDIO_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include +#include + +/******************************************************************************************** + * Preprocessor definitions + ********************************************************************************************/ +/* Device Descriptor + * + * Because audio functionality is always considered to reside at the interface level, this + * class specification does not define a specific audio device descriptor. For both composite + * devices and audio-only devices, the device descriptor must indicate that class information + * is to be found at the interface level. Therefore, the bDeviceClass, bDeviceSubClass and + * bDeviceProtocol fields of the device descriptor must contain the values 0xef, 0x02, and + * 0x01 respectively. + */ + +#define ADC_DEVICE_CLASS USB_CLASS_MISC +#define ADC_DEVICE_SUBCLASS 0x02 +#define ADC_DEVICE_PROTOCOL 0x01 + +/* Audio Interface Class Code (defined in usb.h) */ + +#define ADC_CLASS USB_CLASS_AUDIO + +/* Audio Interface Sub-class Codes */ + +#define ADC_SUBCLASS_UNDEF 0x00 /* Undefined */ +#define ADC_SUBCLASS_AUDIOCONTROL 0x01 /* Audio control */ +#define ADC_SUBCLASS_AUDIOSTREAMING 0x02 /* Audio streaming */ +#define ADC_SUBCLASS_MIDISTREAMING 0x03 /* MIDI streaming */ + +/* Audio Protocol Codes */ + +#define ADC_PROTOCOL_UNDEF 0x00 /* Undefined */ +#define ADC_PROTOCOLv20 0x20 /* IP version 2.0 */ +#define ADC_PROTOCOLv20_BCD 0x0200 /* IP version 2.0 (BCD) */ + +/* Interface Association Descriptor (IAD) */ + +#define ADC_IAD_CLASS ADC_CLASS +#define ADC_IAD_SUBCLASS ADC_SUBCLASS_UNDEF +#define ADC_IAD_PROTOCOL ADC_PROTOCOLv20 + +/* Standard AC Interface Descriptor */ + +#define ADC_ACIF_CLASS ADC_CLASS +#define ADC_ACIF_SUBCLASS ADC_SUBCLASS_AUDIOCONTROL +#define ADC_ACIF_PROTOCOL ADC_PROTOCOLv20 + +/* Standard AS Interface Descriptor */ + +#define ADC_ASIF_CLASS ADC_CLASS +#define ADC_ASIF_SUBCLASS ADC_SUBCLASS_AUDIOSTREAMING +#define ADC_ASIF_PROTOCOL ADC_PROTOCOLv20 + +/* Class-specific Descriptor Codes: */ + +#define ADC_CS_UNDEF 0x20 +#define ADC_CS_DEVICE 0x21 +#define ADC_CS_CONFIGURATION 0x22 +#define ADC_CS_STRING 0x23 +#define ADC_CS_INTERFACE 0x24 +#define ADC_CS_ENDPOINT 0x25 + +/* Audio Class-Specific AC Interface Descriptor Subtypes */ + +#define ADC_AC_UNDEF 0x00 +#define ADC_AC_HEADER 0x01 +#define ADC_AC_INPUT_TERMINAL 0x02 +#define ADC_AC_OUTPUT_TERMINAL 0x03 +#define ADC_AC_MIXER_UNIT 0x04 +#define ADC_AC_SELECTOR_UNIT 0x05 +#define ADC_AC_FEATURE_UNIT 0x06 +#define ADC_AC_EFFECT_UNIT 0x07 +#define ADC_AC_PROCESSING_UNIT 0x08 +#define ADC_AC_EXTENSION_UNIT 0x09 +#define ADC_AC_CLOCK_SOURCE 0x0a +#define ADC_AC_CLOCK_SELECTOR 0x0b +#define ADC_AC_CLOCK_MULTIPLIER 0x0c +#define ADC_AC_SAMPLERATE_CONVERTER 0x0d + +/* Audio Class-Specific AS Interface Descriptor Subtypes */ + +#define ADC_AS_UNDEF 0x00 +#define ADC_AS_GENERAL 0x01 +#define ADC_AS_FORMAT_TYPE 0x02 +#define ADC_AS_ENCODER 0x03 +#define ADC_AS_DECODER 0x04 + +/* Clock Source Descriptor Clock Types */ + +#define ADC_CLKSRC_EXTERNAL 0x00 /* External clock */ +#define ADC_CLKSRC_INTERNAL_FIXED 0x01 /* Internal fixed clock */ +#define ADC_CLKSRC_INTERNAL_VAR 0x02 /* Internal variable clock */ +#define ADC_CLKSRC_INTERNAL_PROG 0x03 /* Internal programmable clock */ + +/* Effect Unit Effect Types */ + +#define ADC_EFFECT_UNDEF 0x00 +#define ADC_EFFECT_PARAM_EQ_SECTION 0x01 +#define ADC_EFFECT_REVERBERATION 0x02 +#define ADC_EFFECT_MOD_DELAY 0x03 +#define ADC_EFFECT_DYN_RANGE_COMP 0x04 + +/* Processing Unit Process Types */ + +#define ADC_PROCESS_UNDEF 0x00 +#define ADC_PROCESS_UPDOWNMIX 0x01 +#define ADC_PROCESS_DOLBY_PROLOGIC 0x02 +#define ADC_PROCESS_STEREO_EXTENDER 0x03 + +/* Audio Class-Specific Endpoint Descriptor Subtypes */ + +#define ADC_EPTYPE_UNDEF 0x00 +#define ADC_EPTYPE_GENERAL 0x01 + +/* Audio Class-Specific Request Codes */ + +#define ADC_REQUEST_UNDEF 0x00 +#define ADC_REQUEST_CUR 0x01 +#define ADC_REQUEST_RANGE 0x02 +#define ADC_REQUEST_MEM 0x03 + +/* Encoder Type Codes */ + +#define ADC_ENCODER_UNDEF 0x00 +#define ADC_ENCODER_OTHER 0x01 +#define ADC_ENCODER_MPEG 0x02 +#define ADC_ENCODER_AC3 0x03 +#define ADC_ENCODER_WMA 0x04 +#define ADC_ENCODER_DTS 0x05 + +/* Decoder Type Codes */ + +#define ADC_DECODER_UNDEF 0x00 +#define ADC_DECODER_OTHER 0x01 +#define ADC_DECODER_MPEG 0x02 +#define ADC_DECODER_AC3 0x03 +#define ADC_DECODER_WMA 0x04 +#define ADC_DECODER_DTS 0x05 + +/* bmChannelConfig: a bitmap field that indicates which spatial locations + * are occupied by the channels present in the cluster. The bit allocations + * are as follows: + */ + +#define ADC_LOCATION_FL (1 << 0) /* Front Left */ +#define ADC_LOCATION_FR (1 << 1) /* Front Right */ +#define ADC_LOCATION_FC (1 << 2) /* Front Center */ +#define ADC_LOCATION_LFE (1 << 3) /* Low Frequency Effects */ +#define ADC_LOCATION_BL (1 << 4) /* Back Left */ +#define ADC_LOCATION_BR (1 << 5) /* Back Right */ +#define ADC_LOCATION_FLC (1 << 6) /* Front Left of Center */ +#define ADC_LOCATION_FRC (1 << 7) /* Front Right of Center */ +#define ADC_LOCATION_BC (1 << 8) /* Back Center */ +#define ADC_LOCATION_SL (1 << 9) /* Side Left */ +#define ADC_LOCATION_SR (1 << 10) /* Side Right */ +#define ADC_LOCATION_TC (1 << 11) /* Top Center */ +#define ADC_LOCATION_TFL (1 << 12) /* Top Front Left */ +#define ADC_LOCATION_TFC (1 << 13) /* Top Front Center */ +#define ADC_LOCATION_TFR (1 << 14) /* Top Front Right */ +#define ADC_LOCATION_TBL (1 << 15) /* Top Back Left */ +#define ADC_LOCATION_TBC (1 << 16) /* Top Back Center */ +#define ADC_LOCATION_TBR (1 << 17) /* Top Back Right */ +#define ADC_LOCATION_TFLC (1 << 18) /* Top Front Left of Center */ +#define ADC_LOCATION_TFRC (1 << 19) /* Top Front Right of Center */ +#define ADC_LOCATION_LLFE (1 << 20) /* Left Low Frequency Effects */ +#define ADC_LOCATION_RLFE (1 << 21) /* Right Low Frequency Effects */ +#define ADC_LOCATION_TSL (1 << 22) /* Top Side Left */ +#define ADC_LOCATION_TSR (1 << 23) /* Top Side Right */ +#define ADC_LOCATION BC (1 << 24) /* Bottom Center */ +#define ADC_LOCATION_BLC (1 << 25) /* Back Left of Center */ +#define ADC_LOCATION_BRC (1 << 26) /* Back Right of Center */ + /* Bits 27-30: Reserved */ +#define ADC_LOCATION_RD (1 << 31) /* Raw Data */ + +/* Audio Function Category Codes */ + +#define ADC_CATEGORY_UNDEF 0x00 /* Undefined */ +#define ADC_CATEGORY_SPEAKER 0x01 /* Desktop speaker */ +#define ADC_CATEGORY_THEATER 0x02 /* Home theater */ +#define ADC_CATEGORY_MICROPHONE 0x03 /* Microphone */ +#define ADC_CATEGORY_HEADSET 0x04 /* Headset */ +#define ADC_CATEGORY_TELEPHONE 0x05 /* Telephone */ +#define ADC_CATEGORY_CONVERTER 0x06 /* Converter */ +#define ADC_CATEGORY_RECORDER 0x07 /* Voice/Sound recorder */ +#define ADC_CATEGORY_IO_BOX 0x08 /* I/O box */ +#define ADC_CATEGORY_INSTRUMENT 0x09 /* Musical instrument */ +#define ADC_CATEGORY_PROAUDIO 0x0a /* Pro-audio */ +#define ADC_CATEGORY_AV 0x0b /* Audio/video */ +#define ADC_CATEGORY_CONTROL 0x0c /* Control panel */ +#define ADC_CATEGORY_OTHER 0xff + +/* Clock Source Control Selectors */ + +#define ADC_CS_CONTROL_UNDEF 0x00 +#define ADC_CS_CONTROL_SAM_FREQ 0x01 +#define ADC_CS_CONTROL_CLOCK_VALID 0x02 + +/* Clock Selector Control Selectors */ + +#define ADC_CX_CONTROL_UNDEF 0x00 +#define ADC_CX_CONTROL_CLOCKSEL 0x01 + +/* Clock Multiplier Control Selectors */ + +#define ADC_CM_CONTROL_UNDEF 0x00 +#define ADC_CM_CONTROL_NUMERATOR 0x01 +#define ADC_CM_CONTROL_DENOMINATOR 0x02 + +/* Terminal Control Selectors */ + +#define ADC_TE_CONTROL_UNDEF 0x00 +#define ADC_TE_CONTROL_COPY_PROTECT 0x01 +#define ADC_TE_CONTROL_CONNECTOR 0x02 +#define ADC_TE_CONTROL_OVERLOAD 0x03 +#define ADC_TE_CONTROL_CLUSTER 0x04 +#define ADC_TE_CONTROL_UNDERFLOW 0x05 +#define ADC_TE_CONTROL_OVERFLOW 0x06 +#define ADC_TE_CONTROL_LATENCY 0x07 + +/* Mixer Control Selectors */ + +#define ADC_MU_CONTROL_UNDEF 0x00 +#define ADC_MU_CONTROL_MIXER 0x01 +#define ADC_MU_CONTROL_CLUSTER 0x02 +#define ADC_MU_CONTROL_UNDERFLOW 0x03 +#define ADC_MU_CONTROL_OVERFLOW 0x04 +#define ADC_MU_CONTROL_LATENCY 0x05 + +/* Selector Control Selectors */ + +#define ADC_SU_CONTROL_UNDEF 0x00 +#define ADC_SU_CONTROL_SELECTOR 0x01 +#define ADC_SU_CONTROL_LATENCY 0x02 + +/* Feature Unit Control Selectors */ + +#define ADC_FU_CONTROL_UNDEF 0x00 +#define ADC_FU_CONTROL_MUTE 0x01 +#define ADC_FU_CONTROL_VOLUME 0x02 +#define ADC_FU_CONTROL_BASS 0x03 +#define ADC_FU_CONTROL_MID 0x04 +#define ADC_FU_CONTROL_TREBLE 0x05 +#define ADC_FU_CONTROL_EQUALIZER 0x06 +#define ADC_FU_CONTROL_AGC 0x07 +#define ADC_FU_CONTROL_DELAY 0x08 +#define ADC_FU_CONTROL_BASS_BOOST 0x09 +#define ADC_FU_CONTROL_LOUDNESS 0x0a +#define ADC_FU_CONTROL_INP_GAIN 0x0b +#define ADC_FU_CONTROL_INP_GAIN_PAD 0x0c +#define ADC_FU_CONTROL_PHASE_INVERT 0x0d +#define ADC_FU_CONTROL_UNDERFLOW 0x0e +#define ADC_FU_CONTROL_OVERFLOW 0x0f +#define ADC_FU_CONTROL_LATENCY 0x10 + +/* Parametric Equalizer Section Effect Unit Control Selectors */ + +#define ADC_PE_CONTROL_UNDEF 0x00 +#define ADC_PE_CONTROL_ENABLE 0x01 +#define ADC_PE_CONTROL_CENTERFREQ 0x02 +#define ADC_PE_CONTROL_QFACTOR 0x03 +#define ADC_PE_CONTROL_GAIN 0x04 +#define ADC_PE_CONTROL_UNDERFLOW 0x05 +#define ADC_PE_CONTROL_OVERFLOW 0x06 +#define ADC_PE_CONTROL_LATENCY 0x07 + +/* Reverberation Effect Unit Control Selectors */ + +#define ADC_RV_CONTROL_UNDEF 0x00 +#define ADC_RV_CONTROL_ENABLE 0x01 +#define ADC_RV_CONTROL_TYPE 0x02 +#define ADC_RV_CONTROL_LEVEL 0x03 +#define ADC_RV_CONTROL_TIME 0x04 +#define ADC_RV_CONTROL_FEEDBACK 0x05 +#define ADC_RV_CONTROL_PREDELAY 0x06 +#define ADC_RV_CONTROL_DENSITY 0x07 +#define ADC_RV_CONTROL_HF_ROLLOFF 0x08 +#define ADC_RV_CONTROL_UNDERFLOW 0x09 +#define ADC_RV_CONTROL_OVERFLOW 0x0a +#define ADC_RV_CONTROL_LATENCY 0x0b + +/* Modulation Delay Effect Unit Control Selectors */ + +#define ADC_MD_CONTROL_UNDEF 0x00 +#define ADC_MD_CONTROL_ENABLE 0x01 +#define ADC_MD_CONTROL_BALANCE 0x02 +#define ADC_MD_CONTROL_RATE 0x03 +#define ADC_MD_CONTROL_DEPTH 0x04 +#define ADC_MD_CONTROL_TIME 0x05 +#define ADC_MD_CONTROL_FEEDBACK 0x06 +#define ADC_MD_CONTROL_UNDERFLOW 0x07 +#define ADC_MD_CONTROL_OVERFLOW 0x08 +#define ADC_MD_CONTROL_LATENCY 0x09 + +/* Dynamic Range Compressor Effect Unit Control Selectors */ + +#define ADC_DR_CONTROL_UNDEF 0x00 +#define ADC_DR_CONTROL_ENABLE 0x01 +#define ADC_DR_CONTROL_COMP_RATE 0x02 +#define ADC_DR_CONTROL_MAXAMPL 0x03 +#define ADC_DR_CONTROL_THRESHOLD 0x04 +#define ADC_DR_CONTROL_ATTACK_TIME 0x05 +#define ADC_DR_CONTROL_RELEASE_TIME 0x06 +#define ADC_DR_CONTROL_UNDERFLOW 0x07 +#define ADC_DR_CONTROL_OVERFLOW 0x08 +#define ADC_DR_CONTROL_LATENCY 0x09 + +/* Up/Down-mix Processing Unit Control Selectors */ + +#define ADC_UD_CONTROL_UNDEF 0x00 +#define ADC_UD_CONTROL_ENABLE 0x01 +#define ADC_UD_CONTROL_MODE_SELECT 0x02 +#define ADC_UD_CONTROL_CLUSTER 0x03 +#define ADC_UD_CONTROL_UNDERFLOW 0x04 +#define ADC_UD_CONTROL_OVERFLOW 0x05 +#define ADC_UD_CONTROL_LATENCY 0x06 + +/* Dolby Prologic™ Processing Unit Control Selectors */ + +#define ADC_DP_CONTROL_UNDEF 0x00 +#define ADC_DP_CONTROL_ENABLE 0x01 +#define ADC_DP_CONTROL_MODE_SELECT 0x02 +#define ADC_DP_CONTROL_CLUSTER 0x03 +#define ADC_DP_CONTROL_UNDERFLOW 0x04 +#define ADC_DP_CONTROL_OVERFLOW 0x05 +#define ADC_DP_CONTROL_LATENCY 0x06 + +/* Stereo Extender Processing Unit Control Selectors */ + +#define ADC_STEXT_CONTROL_UNDEF 0x00 +#define ADC_STEXT_CONTROL_ENABLE 0x01 +#define ADC_STEXT_CONTROL_WIDTH 0x02 +#define ADC_STEXT_CONTROL_UNDERFLOW 0x03 +#define ADC_STEXT_CONTROL_OVERFLOW 0x04 +#define ADC_STEXT_CONTROL_LATENCY 0x05 + +/* Extension Unit Control Selectors */ + +#define ADC_XU_CONTROL_UNDEF 0x00 +#define ADC_XU_CONTROL_ENABLE 0x01 +#define ADC_XU_CONTROL_CLUSTER 0x02 +#define ADC_XU_CONTROL_UNDERFLOW 0x03 +#define ADC_XU_CONTROL_OVERFLOW 0x04 +#define ADC_XU_CONTROL_LATENCY 0x05 + +/* AudioStreaming Interface Control Selectors */ + +#define ADC_AS_CONTROL_UNDEF 0x00 +#define ADC_AS_CONTROL_ACT_ALT 0x01 +#define ADC_AS_CONTROL_VAL_ALT 0x02 +#define ADC_AS_CONTROL_AUDIO_FORMAT 0x03 + +/* Encoder Control Selectors */ + +#define ADC_EN_CONTROL_UNDEF 0x00 +#define ADC_EN_CONTROL_BIT_RATE 0x01 +#define ADC_EN_CONTROL_QUALITY 0x02 +#define ADC_EN_CONTROL_VBR 0x03 +#define ADC_EN_CONTROL_TYPE 0x04 +#define ADC_EN_CONTROL_UNDERFLOW 0x05 +#define ADC_EN_CONTROL_OVERFLOW 0x06 +#define ADC_EN_CONTROL_ENCODER_ERR 0x07 +#define ADC_EN_CONTROL_PARAM1 0x08 +#define ADC_EN_CONTROL_PARAM2 0x09 +#define ADC_EN_CONTROL_PARAM3 0x0a +#define ADC_EN_CONTROL_PARAM4 0x0b +#define ADC_EN_CONTROL_PARAM5 0x0c +#define ADC_EN_CONTROL_PARAM6 0x0d +#define ADC_EN_CONTROL_PARAM7 0x0e +#define ADC_EN_CONTROL_PARAM8 0x0f + +/* MPEG Decoder Control Selectors */ + +#define ADC_MPGD_CONTROL_UNDEF 0x00 +#define ADC_MPGD_CONTROL_DUAL_CHAN 0x01 +#define ADC_MPGD_CONTROL_2ND_STEREO 0x02 +#define ADC_MPGD_CONTROL_MULTILING 0x03 +#define ADC_MPGD_CONTROL_DYN_RANGE 0x04 +#define ADC_MPGD_CONTROL_SCALING 0x05 +#define ADC_MPGD_CONTROL_HILO_SCALE 0x06 +#define ADC_MPGD_CONTROL_UNDERFLOW 0x07 +#define ADC_MPGD_CONTROL_OVERFLOW 0x08 +#define ADC_MPGD_CONTROL_DECODE_ERR 0x09 + +/* AC-3 Decoder Control Selectors */ + +#define ADC_AC3D_CONTROL_UNDEF 0x00 +#define ADC_AC3D_CONTROL_MODE 0x01 +#define ADC_AC3D_CONTROL_DYN_RANGE 0x02 +#define ADC_AC3D_CONTROL_SCALING 0x03 +#define ADC_AC3D_CONTROL_HILO_SCALE 0x04 +#define ADC_AC3D_CONTROL_UNDERFLOW 0x05 +#define ADC_AC3D_CONTROL_OVERFLOW 0x06 +#define ADC_AC3D_CONTROL_DECODE_ERR 0x07 + +/* WMA Decoder Control Selectors */ + +#define ADC_WMAD_CONTROL_UNDEF 0x00 +#define ADC_WMAD_CONTROL_UNDERFLOW 0x01 +#define ADC_WMAD_CONTROL_OVERFLOW 0x02 +#define ADC_WMAD_CONTROL_DECODE_ERR 0x03 + +/* DTS Decoder Control Selectors */ + +#define ADC_DTSD_CONTROL_UNDEF 0x00 +#define ADC_DTSD_CONTROL_UNDERFLOW 0x01 +#define ADC_DTSD_CONTROL_OVERFLOW 0x02 +#define ADC_DTSD_CONTROL_DECODE_ERR 0x03 + +/* Endpoint Control Selectors */ + +#define ADC_EP_CONTROL_UNDEF 0x00 +#define ADC_EP_CONTROL_PITCH 0x01 +#define ADC_EP_CONTROL_OVERRUN 0x02 +#define ADC_EP_CONTROL_UNDERRUN 0x03 + +/* Encoder Error Codes */ + + /* <0: Reserved for vendor extensions */ +#define ADC_ENCODER_SUCCESS 0 /* No Error */ +#define ADC_ENCODER_ERROR_NOMEM 1 /* Out of Memory */ +#define ADC_ENCODER_ERROR_BW 2 /* Out of Bandwidth */ +#define ADC_ENCODER_ERROR_CYCLE 3 /* Out of Processing Cycles */ +#define ADC_ENCODER_ERROR_FRAME 4 /* General Format Frame Error */ +#define ADC_ENCODER_ERROR_TOOSMALL 5 /* Format Frame Too Small */ +#define ADC_ENCODER_ERROR_TOOBIG 6 /* Format Frame Too Large */ +#define ADC_ENCODER_ERROR_BADFORMAT 7 /* Bad Data Format */ +#define ADC_ENCODER_ERROR_NCHAN 8 /* Incorrect Number of Channels */ +#define ADC_ENCODER_ERROR_RATE 9 /* Incorrect Sampling Rate */ +#define ADC_ENCODER_ERROR_BITRATE 10 /* Unable to Meet Target Bitrate */ +#define ADC_ENCODER_ERROR_PARMS 11 /* Inconsistent Set of Parameters */ +#define ADC_ENCODER_ERROR_NOTREADY 12 /* Not Ready */ +#define ADC_ENCODER_ERROR_BUSY 13 /* Busy */ + /* >13: Reserved */ + +/* Format Type Codes */ + +#define ADC_FORMAT_TYPE_UNDEF 0x00 +#define ADC_FORMAT_TYPEI 0x01 +#define ADC_FORMAT_TYPEII 0x02 +#define ADC_FORMAT_TYPEIII 0x03 +#define ADC_FORMAT_TYPEIV 0x04 +#define ADC_FORMAT_EXT_TYPEI 0x81 +#define ADC_FORMAT_EXT_TYPEII 0x82 +#define ADC_FORMAT_EXT_TYPEIII 0x83 + +/* Audio Data Format Type I Bit Allocations */ + +#define ADC_FORMAT_TYPEI_PCM (1 << 0) +#define ADC_FORMAT_TYPEI_PCM8 (1 << 1) +#define ADC_FORMAT_TYPEI_IEEEFLOAT (1 << 2) +#define ADC_FORMAT_TYPEI_ALAW (1 << 3) +#define ADC_FORMAT_TYPEI_MULAW (1 << 4) +#define ADC_FORMAT_TYPEI_RAWDATA (1 << 31) + +/* Audio Data Format Type II Bit Allocations */ + +#define ADC_FORMAT_TYPEII_MPEG (1 << 0) +#define ADC_FORMAT_TYPEII_AC3 (1 << 1) +#define ADC_FORMAT_TYPEII_WMA (1 << 2) +#define ADC_FORMAT_TYPEII_DTS (1 << 3) +#define ADC_FORMAT_TYPEII_RAWDATA (1 << 31) + +/* Audio Data Format Type III Bit Allocations */ + + +#define ADC_FORMAT_TYPEIII_IEC61937_AC3 (1 << 0) +#define ADC_FORMAT_TYPEIII_IEC61937_MPEG1_L1 (1 << 1) +#define ADC_FORMAT_TYPEIII_IEC61937_MPEG1_L2_3 (1 << 1) +#define ADC_FORMAT_TYPEIII_IEC61937_MPEG2_NOEXT (1 << 2) +#define ADC_FORMAT_TYPEIII_IEC61937_MPEG2_EXT (1 << 3) +#define ADC_FORMAT_TYPEIII_IEC61937_MPEG2_AAC_ADTS (1 << 4) +#define ADC_FORMAT_TYPEIII_IEC61937_MPEG2_L1_LS (1 << 5) +#define ADC_FORMAT_TYPEIII_IEC61937_MPEG2_L2_3_LS (1 << 6) +#define ADC_FORMAT_TYPEIII_IEC61937_DTS-I (1 << 7) +#define ADC_FORMAT_TYPEIII_IEC61937_DTS-II (1 << 8) +#define ADC_FORMAT_TYPEIII_IEC61937_DTS-III (1 << 9) +#define ADC_FORMAT_TYPEIII_IEC61937_ATRAC (1 << 10) +#define ADC_FORMAT_TYPEIII_IEC61937_ATRAC2_3 (1 << 11) +#define ADC_FORMAT_TYPEIII_WMA (1 << 12) + +/* Audio Data Format Type IV Bit Allocations */ + +#define ADC_FORMAT_TYPEIV_PCM (1 << 0) +#define ADC_FORMAT_TYPEIV_PCM8 (1 << 1) +#define ADC_FORMAT_TYPEIV_IEEE_FLOAT (1 << 2) +#define ADC_FORMAT_TYPEIV_ALAW (1 << 3) +#define ADC_FORMAT_TYPEIV_MULAW (1 << 4) +#define ADC_FORMAT_TYPEIV_MPEG (1 << 5) +#define ADC_FORMAT_TYPEIV_AC3 (1 << 6) +#define ADC_FORMAT_TYPEIV_WMA (1 << 7) +#define ADC_FORMAT_TYPEIV_IEC61937_AC3 (1 << 8) +#define ADC_FORMAT_TYPEIV_IEC61937_MPEG1_L1 (1 << 9) +#define ADC_FORMAT_TYPEIV_IEC61937_MPEG1_L2_3 (1 << 10) +#define ADC_FORMAT_TYPEIV_IEC61937_MPEG2_NOEXT (1 << 10) +#define ADC_FORMAT_TYPEIV_IEC61937_MPEG2_EXT (1 << 11) +#define ADC_FORMAT_TYPEIV_IEC61937_MPEG2_AAC_ADTS (1 << 12) +#define ADC_FORMAT_TYPEIV_IEC61937_MPEG2_L1_LS (1 << 13) +#define ADC_FORMAT_TYPEIV_IEC61937_MPEG2_L2_3_LS (1 << 14) +#define ADC_FORMAT_TYPEIV_IEC61937_DTS-I (1 << 15) +#define ADC_FORMAT_TYPEIV_IEC61937_DTS-II (1 << 16) +#define ADC_FORMAT_TYPEIV_IEC61937_DTS-III (1 << 17) +#define ADC_FORMAT_TYPEIV_IEC61937_ATRAC (1 << 18) +#define ADC_FORMAT_TYPEIV_IEC61937_ATRAC2_3 (1 << 19) +#define ADC_FORMAT_TYPEIV_TYPE_III_WMA (1 << 20) +#define ADC_FORMAT_TYPEIV_IEC60958_PCM (1 << 21) + +/* Side Band Protocol Codes */ + +#define ADC_SIDEBAND_PROTOCOL_UNDEF 0x00 +#define ADC_PRES_TIMESTAMP_PROTOCOL 0x01 + +/* USB Terminal Types */ + +#define ADC_TERMINAL_UNDEF 0x0100 +#define ADC_TERMINAL_STREAMING 0x0101 +#define ADC_TERMINAL_VENDOR 0x01ff + +/* Input Terminal Types */ + +#define ADC_INTERM_UNDEF 0x0200 /* Undefined Type */ +#define ADC_INTERM_MIC 0x0201 /* A generic microhpone */ +#define ADC_INTERM_DESKTOP_MIC 0x0202 /* A desktop microphone */ +#define ADC_INTERM_PERSONAL_MIC 0x0203 /* Head-mounted or clip-on microphone */ +#define ADC_INTERM_OMNI_MIC 0x0204 /* Omni-directional microphone */ +#define ADC_INTERM_MIC_ARRAY 0x0205 /* Microphone array */ +#define ADC_INTERM_PROC_MIC_ARRAY 0x0206 /* Microphone array with signal processor */ + +/* Output Terminal Types */ + +#define ADC_OUTTERM_UNDEF 0x0300 /* Undefined Type */ +#define ADC_OUTTERM_SPEAKER 0x0301 /* Generic speakers */ +#define ADC_OUTTERM_HEADPHONES 0x0302 /* A head-mounted audio output device */ +#define ADC_OUTTERM_HEADDISPLAY 0x0303 /* Head Mounted Display Audio */ +#define ADC_OUTTERM_DESKTOP 0x0304 /* Desktop speaker */ +#define ADC_OUTTERM_ROOM 0x0305 /* Room speaker */ +#define ADC_OUTTERM_COMMS 0x0306 /* Communication speaker */ +#define ADC_OUTTERM_LOFREQ 0x0307 /* Low frequency effects speaker */ + +/* Bi-directional Terminal Types */ + +#define ADC_BIDITERM_UNDEF 0x0400 /* Undefined Type */ +#define ADC_BIDITERM_HANDSET 0x0401 /* Hand-held bi-directional audio device */ +#define ADC_BIDITERM_HEADSET 0x0402 /* Head-mounted bi-directional audio device */ +#define ADC_BIDITERM_SPEAKERPHONE 0x0403 /* Speakerphone, no echo reduction */ +#define ADC_BIDITERM_ECHOSUPPRESS 0x0404 /* Echo-suppressing speakerphone */ +#define ADC_BIDITERM_ECHOCANCEL 0x0405 /* Echo-canceling speakerphone */ + +/* Telephony Terminal Types */ + +#define ADC_TELETERM_UNDEF 0x0500 /* Undefined Type */ +#define ADC_TELETERM_PHONELINE 0x0501 /* Analog telephone line jack, an ISDN line, + * a proprietary PBX interface, or a wireless link */ +#define ADC_TELETERM_TELEPHONE 0x0502 /* Device can be used as a telephone */ +#define ADC_TELETERM_DOWNLINE 0x0503 /* Down Line Phone */ + +/* External Terminal Types */ + +#define ADC_EXTTERM_UNDEF 0x0600 /* Undefined Type */ +#define ADC_EXTTERM_ANALOG 0x0601 /* Generic analog connector */ +#define ADC_EXTTERM_DIGITAL 0x0602 /* Generic digital audio interface */ +#define ADC_EXTTERM_LINE 0x0603 /* Analog connector at standard line levels */ +#define ADC_EXTTERM_LEGACY 0x0604 /* Legacy audio line out connector */ +#define ADC_EXTTERM_SPDIF 0x0605 /* SPDIF interface */ +#define ADC_EXTTERM_1394DA 0x0606 /* 1394 DA stream */ +#define ADC_EXTTERM_1394DV 0x0607 /* 1394 DV stream soundtrack */ +#define ADC_EXTTERM_ADAT 0x0608 /* ADAT Lightpipe */ +#define ADC_EXTTERM_TDIF 0x0609 /* TDIF - Tascam Digital Interface */ +#define ADC_EXTTERM_MADI 0x060a /* MADI - Multi-channel Audio Digital Interface (AES) */ + +/* Embedded Function Terminal Types */ + +#define ADC_EMBEDTERM_UNDEF 0x0700 /* Undefined Type */ +#define ADC_EMBEDTERM_CALIBRATION 0x0701 /* Level Calibration Noise Source */ +#define ADC_EMBEDTERM_EQUALIZATION 0x0702 /* Equalization Noise */ +#define ADC_EMBEDTERM_CD 0x0703 /* CD player */ +#define ADC_EMBEDTERM_DAT 0x0704 /* Digital Audio Tape */ +#define ADC_EMBEDTERM_DCC 0x0705 /* Digital Compact Cassette */ +#define ADC_EMBEDTERM_COMPRESSED 0x0706 /* Compressed Audio Player */ +#define ADC_EMBEDTERM_TAPE 0x0707 /* Analog Audio Tape */ +#define ADC_EMBEDTERM_PHONOGRAPH 0x0708 /* Analog vinyl record player */ +#define ADC_EMBEDTERM_VCR 0x0709 /* Audio track of VCR */ +#define ADC_EMBEDTERM_VIDDISC 0x070a /* Audio track of VideoDisc player */ +#define ADC_EMBEDTERM_DVD 0x070b /* Audio track of DVD player */ +#define ADC_EMBEDTERM_TVTUNER 0x070c /* Audio track of TV tuner */ +#define ADC_EMBEDTERM_SATELLITE 0x070d /* Audio track of satellite receiver */ +#define ADC_EMBEDTERM_CABLETUNER 0x070e /* Audio track of cable tuner */ +#define ADC_EMBEDTERM_DSS 0x070f /* Audio track of DSS receiver */ +#define ADC_EMBEDTERM_RADIO 0x0710 /* AM/FM radio receiver */ +#define ADC_EMBEDTERM_TRANSMITTER 0x0711 /* AM/FM radio transmitter */ +#define ADC_EMBEDTERM_MULTITRACK 0x0712 /* A multi-track recording system */ +#define ADC_EMBEDTERM_SYNTHESIZER 0x0713 /* Synthesizer */ +#define ADC_EMBEDTERM_PIANO 0x0714 /* Piano */ +#define ADC_EMBEDTERM_GUITAR 0x0715 /* Guitar */ +#define ADC_EMBEDTERM_PERCUSSON 0x0716 /* Percussion Instrument */ +#define ADC_EMBEDTERM_INSTRUMENT 0x0717 /* Other Musical Instrument */ + +/******************************************************************************************** + * Public Types + ********************************************************************************************/ +/* Audio Channel Cluster Descriptor */ + +struct adc_cluster_desc_s +{ + uint8_t cl_nchan; /* 0: Number of logical channels in the cluster */ + uint8_t cl_config[4]; /* 1: The spatial location of the channels */ + uint8_t cl_names; /* 5: Index of name string of first channel */ +}; +#define USB_SIZEOF_ADC_CLUSTER_DESC 6 + +/* Class-specific AC Interface Descriptor */ + +struct adc_ac_ifdesc_s +{ + uint8_t ac_len; /* 0: Descriptor length (9)*/ + uint8_t ac_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t ac_subtype; /* 2: Descriptor sub-type (ADC_AC_HEADER) */ + uint8_t ac_adc[2]; /* 3: ADC spec version in BCD */ + uint8_t ac_category; /* 5: Category of audio function */ + uint8_t ac_totallen[2]; /* 6: Total length */ + uint8_t ac_controls; /* 8: Bits 0-1: Latency control; Bits 2-7 reserved */ +}; +#define USB_SIZEOF_ADC_AC_IFDESC 9 + +/* Clock Source Descriptor */ + +struct adc_clksrc_desc_s +{ + uint8_t cs_len; /* 0: Descriptor length (8)*/ + uint8_t cs_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t cs_subtype; /* 2: Descriptor sub-type (ADC_AC_CLOCK_SOURCE) */ + uint8_t cs_clockid; /* 3: Identifies clock source entity */ + uint8_t cs_attr; /* 4: Bits 0-1: CLKSRC type, D2: Clock synch'ed top SOF */ + uint8_t cs_controls; /* 5: Bits 0-1: Clock freq control, Bits 2-3: Clock valid control */ + uint8_t cs_termid; /* 6: ID of the terminal associated with the clock source */ + uint8_t cs_clksrc; /* 7: Clock source string index */ +}; +#define USB_SIZEOF_ADC_CLKSRC_DESC 8 + +/* Clock Selector Descriptor */ + +struct adc_clksel_desc_s +{ + uint8_t cl_len; /* 0: Descriptor length (7+npins)*/ + uint8_t cl_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t cl_subtype; /* 2: Descriptor sub-type (ADC_AC_CLOCK_SELECTOR) */ + uint8_t cl_clockid; /* 3: Identifies clock source entity */ + uint8_t cl_npins; /* 4: Number of input pins */ + uint8_t cl_variable[1]; /* 5-(5+npins-1): cl_csrcid, ID of clock input to pin n, n=1-npins */ + /* 5+npins: cl_controls: + * Bits 0-1: Clock selector controls, Bits 2-7: Reserved */ + /* 6+npins: cl_clksel + * Clock selector string index */ +}; + +#define cl_csrcid(n) cl_variable[(n)-1] +#define cl_controls(p) cl_variable[(p)->cl_npins] +#define cl_clksel(p) cl_variable[(p)->cl_npins+1] + +#define USB_SIZEOF_ADC_CLKSEL_DESC(npins) (7+(npins)) + +/* Clock Multiplier Descriptor */ + +struct adc_clkmult_desc_s +{ + uint8_t cm_len; /* 0: Descriptor length (7) */ + uint8_t cm_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t cm_subtype; /* 2: Descriptor sub-type (ADC_AC_CLOCK_MULTIPLIER) */ + uint8_t cm_clockid; /* 3: Identifies clock source entity */ + uint8_t cm_csrcid; /* 4: ID of clock input to list pin n */ + uint8_t cm_controls; /* 5: Bits 0-1: Clock numerator control, + * Bits 2-3: Clock denominator control */ + uint8_t cm_clkmult; /* 6: Index of clock multiplier name string */ +}; +#define USB_SIZEOF_ADC_CLKMULT_DESC 7 + +/* Input Terminal Descriptor */ + +struct adc_interm_desc_s +{ + uint8_t it_len; /* 0: Descriptor length (17) */ + uint8_t it_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t it_subtype; /* 2: Descriptor sub-type (ADC_AC_INPUT_TERMINAL) */ + uint8_t it_termid; /* 3: Identifies terminal in audio function */ + uint8_t it_termtype[2]; /* 4: Terminal type */ + uint8_t it_outterm; /* 6: ID of the associated output terminal */ + uint8_t it_csrcid; /* 7: ID of clock entity to which terminal is connected */ + uint8_t it_nchan; /* 8: Number of logical output channels */ + uint8_t it_config[4]; /* 9: The spatial location of the logical channels */ + uint8_t it_names; /* 13: Index of name string of first logical channel */ + uint8_t it_controls{2]; /* 14: Bits 0-1: Copy protect control, + * Bits 2-3: Converter control + * Bits 4-5: Overload control + * Bits 6-7: Cluster control + * Bits 8-9: Underflow control + * Bits 10-11: Overflow control + * Bits 12-15: Reserved */ + uint8_t it_interm; /* 16: Input terminal string index */ +}; +#define USB_SIZEOF_ADC_INTERM_DESC 17 + +/* Output Terminal Descriptor */ + +struct adc_outterm_desc_s +{ + uint8_t ot_len; /* 0: Descriptor length (12) */ + uint8_t ot_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t ot_subtype; /* 2: Descriptor sub-type (ADC_AC_OUTPUT_TERMINAL) */ + uint8_t ot_termid; /* 3: Identifies terminal in audio function */ + uint8_t ot_termtype[2]; /* 4: Terminal type */ + uint8_t ot_interm; /* 6: ID of the associated input terminal */ + uint8_t ot_srcid; /* 7: ID of unit/terminal to which terminal is connnected */ + uint8_t ot_csrcid; /* 8: ID of clock entity to whcih terminal is connected */ + uint8_t ot_controls{2]; /* 9: Bits 0-1: Copy protect control, + * Bits 2-3: Connector control + * Bits 4-5: Overload control + * Bits 6-7: Underflow control + * Bits 8-9: Overflow control + * Bits 10-15: Reserved */ + uint8_t ot_outterm; /* 11: Output terminal string index */ +}; +#define USB_SIZEOF_ADC_OUTTERM_DESC 12 + +/* Mixer Unit Descriptor */ + +struct adc_mixerunit_desc_s +{ + uint8_t mu_len; /* 0: Descriptor length (13+npins+nchan)*/ + uint8_t mu_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t mu_subtype; /* 2: Descriptor sub-type (ADC_AC_MIXER_UNIT) */ + uint8_t mu_unitid; /* 3: Identifies unit in audio function */ + uint8_t mu_npins; /* 4: Number of input pins of this unit */ + uint8_t mu_variable[1]; /* 5-(5+npins-1): mu_srcid[n] + * ID of clock input connected to pin n, n=1-npins */ + /* 5+npins: nchan=Number of logic output channels */ + /* 6+npins: config[4]=spatial location of channels */ + /* 10+npins: name=String index of first channel name */ + /* 11+npins+nchan: controls + * Bits 0-1: Cluster control + * Bits 2-3: Underflow control + * Bits 4-5: Overflow control + * Bits 6-7: Reserved */ + /* 12+npins+nchan: mixer=String index of mixer unit name */ +}; + +#define mu_srcid[n] mu_variable[(n)-1] +#define mu_nchan(p) mu_variable[(p)->mu_npins] +#define mu_controls(p) mu_variable[(p)->mu_npins+1] +#define mu_mixer(p) mu_variable[(p)->mu_npins+2] + +#define USB_SIZEOF_ADC_CLKSEL_DESC(npins,nchan) (13+(npins)+(nchan)) + +/* Selector Unit Descriptor */ + +struct adc_selunit_desc_s +{ + uint8_t su_len; /* 0: Descriptor length (7+npins) */ + uint8_t su_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t su_subtype; /* 2: Descriptor sub-type (ADC_AC_SELECTOR_UNIT) */ + uint8_t su_unitid; /* 3: Identifies unit in audio function */ + uint8_t su_npins; /* 4: Number of input pins of this unit */ + uint8_t su_vairable[1]; /* 5-(5+npins-1): su_srcid[n]=ID of unit/terminal input connected to + * pin n, n=1-npins */ + /* 5+npins: su_controls + * Bits 0-1: Selector control + * Bits 2-7: Reserved */ + /* 6+npins: su_selector=String index of selector unit name */ +}; + +#define su_srcid(n) su_srcid[(n)-1] +#define su_controls(p) su_srcid[(p)->su_npins+1] +#define su_selector(p) su_srcid[(p)->su_npins+2] + +#define USB_SIZEOF_ADC_SELUNIT_DESC(npins,nchan) (7+(npins)) + +/* Feature Unit Descriptor */ + +struct adc_featunit_desc_s +{ + uint8_t fu_len; /* 0: Descriptor length (6+4*(nchan+1)) */ + uint8_t fu_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t fu_subtype; /* 2: Descriptor sub-type (ADC_AC_FEATURE_UNIT) */ + uint8_t fu_unitid; /* 3: Identifies unit in audio function */ + uint8_t fu_srcid; /* 4: ID of unit/terminal to which unit is connected */ + uint8_t fu_variable[1]; /* 5-(5+4*nchan): fu_controls + * Controls for master channel n, n=0,..nchan, + * Bits 0-1: Mute control + * Bits 2-3: Volume control + * Bits 4-5: Bass control + * Bits 6-7: Mid control + * Bits 8-9: Treble control + * Bits 10-11: Graphic equalizer control + * Bits 12-13: Automatic gain control + * Bits 14-15: Delay control + * Bits 16-17: Bass boos control + * Bits 18-19: Loudness control + * Bits 20-21: Input gain control + * Bits 22-23: Input gain pad control + * Bits 24-25: Phase inverter control + * Bits 26-27: Underflow control + * Bits 28-29: Overflow control + * Bits 30-31: Reserved */ + /* 5+4*(nchan+1): feature=Strings index to feature unit name */ +}; + +#define fu_controls(n) fu_variable[4*(n)] +#define fu_feature(nchan) fu_variable[4*((nchan)+1] + +#define USB_SIZEOF_ADC_FEATUNIT_DESC(nchan) (6+4*((nchan)+1))) + +/* Sampling Rate Converter Descriptor */ + +struct adc_srconverter_desc_s +{ + uint8_t sr_len; /* 0: Descriptor length (8) */ + uint8_t sr_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t sr_subtype; /* 2: Descriptor sub-type (ADC_AC_SAMPLERATE_CONVERTER) */ + uint8_t sr_unitid; /* 3: Identifies unit in audio function */ + uint8_t sr_srcid; /* 4: ID of unit/terminal to which unit is connected */ + uint8_t sr_csrcinid; /* 5: ID of clock entity to which unit input is connected */ + uint8_t sr_csrcoutid; /* 6: ID of clock entity to which unit output is connected */ + uint8_t sr_converter; /* 7: String index to the name fo the SRC unit */ +}; +#define USB_SIZEOF_ADC_SRCCONVERTER_DESC (8) + +/* Common Effect Unit Descriptor */ + +struct adc_effectunit_desc_s +{ + uint8_t ef_len; /* 0: Descriptor length (16+4*nchan) */ + uint8_t ef_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t ef_subtype; /* 2: Descriptor sub-type (ADC_AC_EFFECT_UNIT) */ + uint8_t ef_unitid; /* 3: Identifies unit in audio function */ + uint8_t ef_eftype[2]; /* 4: Effect type */ + uint8_t ef_srcid; /* 6: ID of unit/terminal to which unit is connected */ + unit8_t ef_variable[1]; /* 7-(7+4*(nchan+1)): ef_controls[n] + * Controls for channel n, n=0,..,nchan + * Bits 0-31: Effect-specific allocation */ + /* 15+4*nchan: ef_effects=String index to the effect unit name */ +}; + +#define ef_controls(n) ef_controls[4*(n)] +#define ef_effects(nchan) ef_controls[4*(nchan)] + +#define USB_SIZEOF_ADC_EFFECTUNIT_DESC(nchan) (16+4*(nchsn)) + +/* Parametric Equalizer Section Effect Unit Descriptor + * + * ef_eftype = ADC_EFFECT_PARAM_EQ_SECTION + * ef_controls: + * Bits 0-1: Enable control + * Bits 2-3: Center frequency control + * Bits 4-5: Q factor control + * Bits 6-7: Gain control + * Bits 8-9: Underflow control + * Bits 10-11: Overflow control + * Bits 12-31: Reserved + * + * Reverberation Effect Unit Descriptor + * + * ef_eftype = ADC_EFFECT_REVERBERATION + * ef_controls: + * Bits 0-1: Enable control + * Bits 2-3: Type control + * Bits 4-5: Level control + * Bits 6-7: Time control + * Bits 8-9: Delay feedback control + * Bits 10-11: Pre-delay control + * Bits 12-13: Density control + * Bits 13-15: Hi-freq roll-off control + * Bits 16-17: Underflow control + * Bits 18-19: Overflow control + * Bits 20-31: Reserved + * + * Modulation Delay Effect Unit Descriptor + * + * ef_eftype = ADC_EFFECT_MOD_DELAY + * ef_controls: + * Bits 0-1: Enable control + * Bits 2-3: Balance control + * Bits 4-5: Rate control + * Bits 6-7: Depth control + * Bits 8-9: Time control + * Bits 10-11: Feedback level control + * Bits 12-13: Underflow control + * Bits 14-15: Overflow control + * Bits 16-31: Reserved + * + * Dynamic Range Compressor Effect Unit Descriptor + * + * ef_eftype = ADC_EFFECT_DYN_RANGE_COMP + * ef_controls: + * Bits 0-1: Enable control + * Bits 2-3: Compression control + * Bits 4-5: MaxAmpl control + * Bits 6-7: Threshold control + * Bits 8-9: Attack time control + * Bits 10-11: Release time control + * Bits 12-13: Underflow control + * Bits 14-15: Overflow control + * Bits 16-31: Reserved + */ + +/* Common Processing Unit Descriptor */ + +struct adc_procunit_desc_s +{ + uint8_t pu_len; /* 0: Descriptor length (17+npins+x) */ + uint8_t pu_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t pu_subtype; /* 2: Descriptor sub-type (ADC_AC_PROCESSING_UNIT) */ + uint8_t pu_unitid; /* 3: Identifies unit in audio function */ + uint8_t pu_putype[2]; /* 4: Processing unit type */ + uint8_t pu_npins; /* 6: Number of input pins of this unit */ + unit8_t pu_variable[1]; /* 7-(7+(npins11)): pu_srcid[n] + * ID of unit/terminal input is connected to, n=1,..,npins */ + /* 7+npins: pu_nchan: Number of logic output channels */ + /* 8+npins: pu_config: Spatial location of channels */ + /* 12+npins: pu_names: String index to first channel name */ + /* 13+npins: pu_controls + * Bits 0-1: Enable control + * Bits 2-15: Process-specific controls */ + /* 15+npins: pu_processing: String index to name of processing unit */ + /* 16+npins: pu_specific: Beginning of process-specific descriptor */ +}; + +#define pu_srcid(n) pu_variable[n] +#define pu_nchan(p) pu_variable[(Ip)->npins] +#define pu_config(p) pu_variable[(Ip)->npins+1] +#define pu_names(p) pu_variable[(Ip)->npins+5] +#define pu_controls(p) pu_variable[(Ip)->npins+6] +#define pu_processing(p) pu_variable[(Ip)->npins+8] +#define pu_specific(p) &pu_variable[(Ip)->npins+9] + +#define USB_SIZEOF_ADC_PROCUNIT_DESC(npins) (16+(npins)) + +/* Up/Down-mix Processing Unit Descriptor */ + +struct adc_updownunit_desc_s +{ + uint8_t ud_len; /* 0: Descriptor length (18+4*nmodes) */ + uint8_t ud_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t ud_subtype; /* 2: Descriptor sub-type (ADC_AC_PROCESSING_UNIT) */ + uint8_t ud_unitid; /* 3: Identifies unit in audio function */ + uint8_t ud_putype[2]; /* 4: Processing unit type (ADC_PROCESS_UPDOWNMIX) */ + uint8_t ud_npins; /* 6: Number of input pins of this unit (1) */ + unit8_t ud_srcid; /* 7: ID of unit/terminal input is connected to */ + uint8_t ud_nchan; /* 8: Number of logic output channels */ + uint8_t ud_config[4]; /* 9: Spatial location of channels */ + uint8_t ud_names; /* 13: String index to first channel name */ + uint8_t ud_controls[2]; /* 14: controls + * Bits 0-1: Enable control + * Bits 2-3; Mode select control + * Bits 4-5: Cluster control + * Bits 6-7: Underflow control + * Bits 8-9: Overflow control + * Bits 10-15 Reserved */ + uint8_t ud_processing; /* 16: String index to name of processing unit */ + uint8_t ud_nmodes; /* 17: Number of modes supported */ + uint8_t ud_modes[1]; /* 18-(18+4*(nmodes-1)): Active logical channels in mode n */ +}; + +#define USB_SIZEOF_ADC_UPDOWNUNIT_DESC(nmodes) (18+4(nmodes)) + +/* Dolby Prologic Processing Unit Descriptor */ + +struct adc_dolbyunit_desc_s +{ + uint8_t dp_len; /* 0: Descriptor length (18+4*nmodes) */ + uint8_t dp_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t dp_subtype; /* 2: Descriptor sub-type (ADC_AC_PROCESSING_UNIT) */ + uint8_t dp_unitid; /* 3: Identifies unit in audio function */ + uint8_t dp_putype[2]; /* 4: Processing unit type (ADC_PROCESS_DOLBY_PROLOGIC) */ + uint8_t dp_npins; /* 6: Number of input pins of this unit (1) */ + unit8_t dp_srcid; /* 7: ID of unit/terminal input is connected to */ + uint8_t dp_nchan; /* 8: Number of logic output channels */ + uint8_t dp_config[4]; /* 9: Spatial location of channels */ + uint8_t dp_names; /* 13: String index to first channel name */ + uint8_t dp_controls[2]; /* 14: controls + * Bits 0-1: Enable control + * Bits 2-3; Mode select control + * Bits 4-5: Cluster control + * Bits 6-7: Underflow control + * Bits 8-9: Overflow control + * Bits 10-15 Reserved */ + uint8_t dp_processing; /* 16: String index to name of processing unit */ + uint8_t dp_nmodes; /* 17: Number of modes supported */ + uint8_t dp_modes[1]; /* 18-(18+4*(nmodes-1)): Active logical channels in mode n */ +}; + +#define USB_SIZEOF_ADC_DOLBYUNIT_DESC(nmodes) (18+4(nmodes)) + +/* Stereo Extender Processing Unit Descriptor */ + +struct adc_stextunit_desc_s +{ + uint8_t st_len; /* 0: Descriptor length (17) */ + uint8_t st_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t st_subtype; /* 2: Descriptor sub-type (ADC_AC_PROCESSING_UNIT) */ + uint8_t st_unitid; /* 3: Identifies unit in audio function */ + uint8_t st_putype[2]; /* 4: Processing unit type (ADC_PROCESS_STEREO_EXTENDER) */ + uint8_t st_npins; /* 6: Number of input pins of this unit (1) */ + unit8_t st_srcid; /* 7: ID of unit/terminal input is connected to */ + uint8_t st_nchan; /* 8: Number of logic output channels */ + uint8_t st_config[4]; /* 9: Spatial location of channels */ + uint8_t st_names; /* 13: String index to first channel name */ + uint8_t st_controls[2]; /* 14: controls + * Bits 0-1: Enable control + * Bits 2-3; Width control + * Bits 4-5: Cluster control + * Bits 6-7: Underflow control + * Bits 8-9: Overflow control + * Bits 10-15 Reserved */ + uint8_t st_processing; /* 16: String index to name of processing unit */ +}; + +#define USB_SIZEOF_ADC_DOLBYUNIT_DESC(nmodes) (17) + +/* Extension Unit Descriptor */ + +struct adc_extunit_desc_s +{ + uint8_t xu_len; /* 0: Descriptor length (16+p) */ + uint8_t xu_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t xu_subtype; /* 2: Descriptor sub-type (ADC_AC_EXTENSION_UNIT) */ + uint8_t xu_unitid; /* 3: Identifies unit in audio function */ + uint8_t xu_extcode[2]; /* 4: Vendor-specific code identifying the extension unit */ + uint8_t xu_npins; /* 6: Number of input pins of this unit */ + uint8_t xu_variable[1]; /* 7-(7+(npins-1)): xu_srcid: ID of unit/terminal to which + * input pin n is connect, n=1,..,npins */ + /* 8+npins: xu_nchan: Number of logic output channels */ + /* 9+npins: xu_config: Spatial location of logical channels */ + /* 13+npins: xu_names: String index to first channel name */ + /* 14+npins: xu_controls: + * Bits 0-1: Enable control + * Bits 2-3: Cluster control + * Bits 4-5: Underflow control + * Bits 6-7: Overflow control */ + /* 15+np;ins: xu_extunit: String index to unit name */ +}; + +#define xu_srcid(n) xu_variable[n] +#define xu_nchan(p) xu_variable[(p)->xu_npins+1] +#define xu_config(p) xu_variable[(p)->xu_npins+2] +#define xu_names(p) xu_variable[(p)->xu_npins+6] +#define xu_controls(p) xu_variable[(p)->xu_npins+7] +#define xu_extunit(p) xu_variable[(p)->xu_npins+8] + +#define USB_SIZEOF_ADC_EXTUNIT_DESC(npins) (16+(npins)) + +/* Class-Specific AS Interface Descriptor */ + +struct adc_as_ifdesc_s +{ + uint8_t as_len; /* 0: Descriptor length (9)*/ + uint8_t as_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t as_subtype; /* 2: Descriptor sub-type (ADC_AS_GENERAL) */ + uint8_t as_terminal; /* 3: ID of connected terminal */ + uint8_t as_controls; /* 4: controls + * Bits 0-1: Active alternate setting control + * Bits 2-3: Valid alternate setting control + * Bits 4-7: Reserved */ + uint8_t as_format; /* 5: Format type of audio streaming interface */ + uint8_t as_formats[4]; /* 6: Supported audio datat formats */ + uint8_t as_nchan; /* 10: Number of physical channels in audo channel cluster */ + uint8_t as_config[4]; /* 11: Spatial location of channels */ + uint8_t as_names; /* 15: String index to name of first channel */ +}; + +#define USB_SIZEOF_ADC_AS_IFDESC 9 + +/* Encoder Descriptor */ + +struct adc_encoder_desc_s +{ + uint8_t as_len; /* 0: Descriptor length (21) */ + uint8_t as_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t as_subtype; /* 2: Descriptor sub-type (ADC_AS_ENCODER) */ + uint8_t as_encoderid; /* 3: Identifies the encoder within the interface */ + uint8_t as_encoder; /* 4: Identifies the encoder */ + uint8_t as_pad[3]; /* (there is an apparent error in the spec) */ + uint8_t as_controls[4]; /* 8: Controls + * Bits 2-3: Quality Control + * Bits 4-5: VBR Control + * Bits 6-7: Type Control + * Bits 8-9: Underflow Control + * Bits 10-11: Overflow Control + * Bits 12-13: Encoder Error Control + * Bits 14-15: Param1 Control + * Bits 16-17: Param2 Control + * Bits 18-19: Param3 Control + * Bits 20-21: Param4 Control + * Bits 22-23: Param5 Control + * Bits 24-25: Param6 Control + * Bits 26-27: Param7 Control + * Bits 28-20: Param8 Control + * Bits 30-31: Reserved */ + uint8_t as_param[8]; /* 12: String index of purpose of parameter n-1, n=1-8 */ + uint8_t as_encoder: /* 20: String index to the name of the encoder */ +}; + +#define USB_SIZEOF_ADC_ENCODER_DESC 21 + +/* MPEG Decoder Descriptor */ + +struct adc_mpeg_decoder_desc_s +{ + uint8_t md_len; /* 0: Descriptor length (10) */ + uint8_t md_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t md_subtype; /* 2: Descriptor sub-type (ADC_AS_DECODER) */ + uint8_t md_decoderid; /* 3: Identifies the decoder within the interface */ + uint8_t md_decoder; /* 4: Identifies the decoder (ADC_DECODER_MPEG) */ + uint8_t md_capabilities[2]; /* 5: MPEG capabilities + * Bits 0-2: Layer support + * Bit 0: Layer I + * Bit 1: Layer II + * Bit 2: Layer III + * Bit 3: MPEG-1 only. + * Bit 4: MPEG-1 dual-channel + * Bit 5: MPEG-2 second stereo + * Bit 6: MPEG-2 7.1 channel augmentation + * Bit 7: Adaptive multi-channel prediction + * Bits 8-9: MPEG-2 multilingual support + * 00 = Not supported + * 01 = Supported at Fs + * 10 = Reserved + * 11 = Supported at Fs and ½Fs. + * Bit 10: + * Bit 11-15: Reserved */ + uint8_t md_features; /* 7: MPEG features + * Bits 0-3: Reserved + * Bits 4-5 Internal dynamic range control + * 00 = not supported + * 01 = supported but not scalable + * 10 = scalable, common boost and cut scaling value + * 11 = scalable, separate boost and cut scaling value. + * Bits 6-7: Reserved */ + uint8_t md_controls; /* 8: Controls: + * Bits 0-1: Underflow control + * Bits 2-3: Overflow control + * Bits 4-5: Decoder error control + * Bits 6-7: Reserved */ + uint8_t md_decoder; /* 9: String index to the name of the decoder */ +}; + +#define USB_SIZEOF_ADC_MPEG_DECODER_DESC 10 + +/* AC-3 Decoder Descriptor */ + +struct adc_ac3_decoder_desc_s +{ + uint8_t ad_len; /* 0: Descriptor length (12) */ + uint8_t ad_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t ad_subtype; /* 2: Descriptor sub-type (ADC_AS_DECODER) */ + uint8_t ad_decoderid; /* 3: Identifies the decoder within the interface */ + uint8_t ad_decoder; /* 4: Identifies the decoder (ADC_DECODER_AC3) */ + uint8_t ad_id[4]; /* 5: Bitmap, 1=corresponding BSID mode supported */ + uint8_t ad_features; /* 7: MPEG features + * Bit 0: RF mode + * Bit 1: Line mode + * Bit 2: Custom0 mode + * Bit 3: Custom1 mode + * Bits 4-5 Internal dynamic range control + * 00 = not supported + * 01 = supported but not scalable + * 10 = scalable, common boost and cut scaling value + * 11 = scalable, separate boost and cut scaling value. + * Bits 6-7: Reserved */ + uint8_t ad_controls; /* 8: Controls: + * Bits 0-1: Underflow control + * Bits 2-3: Overflow control + * Bits 4-5: Decoder error control + * Bits 6-7: Reserved */ + uint8_t ad_decoder; /* 9: String index to the name of the decoder */ +}; + +#define USB_SIZEOF_ADC_AC3_DECODER_DESC 12 + +/* WMA Decoder Descriptor */ + +struct adc_wma_decoder_desc_s +{ + uint8_t wd_len; /* 0: Descriptor length (9) */ + uint8_t wd_type; /* 1: Descriptor type (ADC_CS_ENDPOINT) */ + uint8_t wd_subtype; /* 2: Descriptor sub-type (ADC_AS_DECODER) */ + uint8_t wd_decoderid; /* 3: Identifies the decoder within the interface */ + uint8_t wd_decoder; /* 4: Identifies the decoder (ADC_DECODER_WMA) */ + uint8_t wd_profile[2]; /* 5: WMA profile + * Bit 0: WMA profile 1, L1 + * Bit 1: WMA profile 2, L2 + * Bit 2: WMA profile 3, L3 + * Bit 3: WMA profile other, L + * Bit 4: WMA speech 1, S1 + * Bit 5: WMA speech 2, S2 + * Bit 6: WMAPro profile 1, M1 + * Bit 7: WMAPro profile 2, M2 + * Bit 8: WMAPro profile 3, M3 + * Bit 9: WMAPro profile other, M + * Bit 10: WMA lossless decoding is supported + * Bits 11-15: Reserved */ + uint8_t wd_controls; /* 7: Controls: + * Bits 0-1: Underflow control + * Bits 2-3: Overflow control + * Bits 4-5: Decoder error control + * Bits 6-7: Reserved */ + uint8_t wd_decoder; /* 9: String index to the name of the decoder */ +}; + +#define USB_SIZEOF_ADC_WMA_DECODER_DESC 9 + +/* DTS Decoder Descriptor */ + +struct adc_dts_decoder_desc_s +{ + uint8_t dd_len; /* 0: Descriptor length (8) */ + uint8_t dd_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t dd_subtype; /* 2: Descriptor sub-type (ADC_AS_DECODER) */ + uint8_t dd_decoderid; /* 3: Identifies the decoder within the interface */ + uint8_t dd_decoder; /* 4: Identifies the decoder (ADC_DECODER_DTS) */ + uint8_t dd_capabilities; /* 5: DTS capabilities + * Bit 0: Core + * Bit 1: Lossless + * Bit 2: LBR + * Bit 3: MultipleStreamMixing + * Bit 4: DualDecode + * Bits 5-7: Reserved */ + uint8_t dd_controls; /* 7: Controls: + * Bits 0-1: Underflow control + * Bits 2-3: Overflow control + * Bits 4-5: Decoder error control + * Bits 6-7: Reserved */ + uint8_t dd_decoder; /* 9: String index to the name of the decoder */ +}; + +#define USB_SIZEOF_ADC_DTS_DECODER_DESC 8 + +/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor */ + +struct adc_audio_epdesc_s +{ + uint8_t ae_len; /* 0: Descriptor length (8) */ + uint8_t ae_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t ae_subtype; /* 2: Descriptor sub-type (ADC_EPTYPE_GENERAL) */ + uint8_t ae_attr; /* 3: Attributes: Bit 7: MaxPacketsOnly */ + uint8_t ae_controls; /* 4 Controls + * Bits 0-1: Pitch control + * Bits 2-3: Data overrun control + * Bits 4-5: Data underrun control + * Bits 6-7: Reserved */ + uint8_t ae_units; /* 5: Lock delay units + * 0=undefined + * 1=milliseconds + * 2=Decoded PCM samples + * 2-255=Reserved */ + uint8_t ae_delay[2]; /* 6: Lock delay */ +}; + +#define USB_SIZEOF_ADC_AUDIO_EPDESC 8 + +/* Layout 1, Control CUR Parameter Block */ + +struct adc_l1_curparm_s +{ + uint8_t l1_cur; /* 0: Setting of the CUR attribute of the addressed control */ +}; + +#define USB_SIZEOF_ADC_LI_CURPARM 1 + +/* Layout 1, Control RANGE Parameter Block */ + +struct adc_l1_subrange_s packed_struct +{ + uint8_t l1_min; /* 0: MIN attribute */ + uint8_t l1_max; /* 1: MAX attribute */ + uint8_t l1_res; /* 2: RES attribute */ +}; + +struct adc_l1_rangeparm_s packed_struct +{ + uint8_t l1_nranges; /* 0: Number of sub-ranges */ + struct adc_l1_subrange_s l1_subrange[1]; +}; + +#define USB_SIZEOF_ADC_LI_RANGEPARM(nranges) (1+3*(nranges)) + +/* Layout 2, Control CUR Parameter Block */ + +struct adc_l2_curparm_s +{ + uint8_t l2_cur[2]; /* 0: Setting of the CUR attribute of the addressed control */ +}; + +#define USB_SIZEOF_ADC_L2_CURPARM 2 + +/* Layout 2, Control RANGE Parameter Block */ + +struct adc_l2_subrange_s +{ + uint8_t l2_min[2]; /* 0: MIN attribute */ + uint8_t l2_max[2]; /* 2: MAX attribute */ + uint8_t l2_res[2]; /* 4: RES attribute */ +}; + +struct adc_l2_rangeparm_s +{ + uint8_t l2_nranges[2]; /* 0: Number of sub-ranges */ + struct adc_l2_subrange_s l2_subrange[1]; +}; + +#define USB_SIZEOF_ADC_L2_RANGEPARM(nranges) (2+6*(nranges)) + +/* Layout 2, Control CUR Parameter Block */ + +struct adc_l3_curparm_s +{ + uint8_t l3_cur[4]; /* 0: Setting of the CUR attribute of the addressed control */ +}; + +#define USB_SIZEOF_ADC_L3_CURPARM 4 + +/* Layout 2, Control RANGE Parameter Block */ + +struct adc_l3_subrange_s +{ + uint8_t l3_min[4]; /* 0: MIN attribute */ + uint8_t l3_max[4]; /* 2: MAX attribute */ + uint8_t l3_res[4]; /* 4: RES attribute */ +}; + +struct adc_l3_rangeparm_s +{ + uint8_t l3_nranges[2]; /* 0: Number of sub-ranges */ + struct adc_l3_subrange_s l3_subrange[1]; +}; + +#define USB_SIZEOF_ADC_L3_RANGEPARM(nranges) (2+12*(nranges)) + +/* Cluster Control CUR Parameter Block */ + +struct adc_clustctrl_curparm_s +{ + uint8_t cc_nchan; /* 0: Number of logical channels */ + uint8_t cc_config[4]; /* 1: Spatial location of channels */ + uint8_t cc_names; /* 5: String index of first channel name */ +}; + +#define USB_SIZEOF_ADC_CLUSTCTRL_CURPARM 6 + +/* Cluster Control CUR Parameter Block */ + +struct adc_connctrl_curparm_s +{ + uint8_t cc_nchan; /* 0: Number of logical channels */ + uint8_t cc_config[4]; /* 1: Spatial location of channels */ + uint8_t cc_names; /* 5: String index of first channel name */ +}; + +#define USB_SIZEOF_ADC_CONNCTRL_CURPARM 6 + +/* Graphic Equalizer Control CUR Parameter Block */ + +struct adc_equalizer_curparm_s +{ + uint8_t eq_bands[4]; /* 0: A set bit indicates that the band is present */ + uint8_t eq_cur[[1]; /* 4: Setting for the band in bands bitset */ +}; + +#define USB_SIZEOF_ADC_CONNCTRL_CURPARM(nbands) (4+(nbands)) + +/* Graphic Equalizer Control RANGE Parameter Block */ + +struct adc_eq_subrange_s packed_struct +{ + uint8_t eq_min; /* 0: MIN attribute */ + uint8_t eq_max; /* 1: MAX attribute */ + uint8_t eq_res; /* 2: RES attribute */ +}; + +struct adc_equalizer_rangeparm_s packed_struct +{ + uint8_t eq_nranges; /* 0: Number of sub-ranges */ + struct adc_eq_subrange_s eq_subrange[1]; +}; + +#define USB_SIZEOF_ADC_EQUALIZER_RANGEPARM(nranges) (1+3*(nranges)) + +/* Valid Alternate Settings Control CUR Parameter Block */ + +struct adc_altsettings_curparm_s +{ + uint8_t as_nsettings; /* 0: Number of alternate settings */ + uint8_t as_settings[1]; /* 1-: Altnating setting n, n-1,..., nsettings */ +}; + +#define USB_SIZEOF_ADC_ALTSETTINGS_CURPARM(nsettings) (1+(nsettings)) + +/* High/Low Scaling Control CUR Parameter Block */ + +struct adc_hilo_curparm_s +{ + uint8_t hl_lo; /* 0: CUR value of the low level scaling control */ + uint8_t hl_hi; /* 0: CUR value of the high level scaling control */ +}; + +/* High/Low Scaling Control RANGE Parameter Block */ + +struct adc_hl_subrange_s packed_struct +{ + uint8_t hl_min; /* 0: MIN attribute */ + uint8_t hl_max; /* 1: MAX attribute */ + uint8_t hl_res; /* 2: RES attribute */ +}; + +struct adc_hilo_rangeparm_s packed_struct +{ + uint8_t hl_nranges[2]; /* 0: Number of sub-ranges */ + struct adc_hl_subrange_s hl_subrange[1]; +}; + +#define USB_SIZEOF_ADC_HILO_RANGEPARM(nranges) (2+3*(nranges)) + +/* Interrupt Data Message Format */ + +struct adc_int_message_s +{ + uint8_t im_info; /* 0: Bitmap + * Bit 0: Vender specific, + * Bit 1: Interface or endpoint + * Bits 2-7: Reserved */ + uint8_t im_attr; /* 1: The attribute that cause the interrupt */ + uint8_t im_value[2]; /* 2: CS is MS byte; CN or MCN in LS byte */ + uint8_t im_index[2]; /* 4: ID or zero in MS bytes; Interface or endpoint is LS byte */ +}; + +#define USB_SIZEOF_ADC_INT_MESSAGE 6 + +/* Type I Format Type Descriptor */ + +struct adc_t1_format_desc_s +{ + uint8_t t1_len; /* 0: Descriptor length (6) */ + uint8_t t1_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t t1_subtype; /* 2: Descriptor sub-type (ADC_AS_FORMAT_TYPE) */ + uint8_t t1_fmttype; /* 3: Identifies the format type (ADC_FORMAT_TYPEI) */ + uint8_t t1_size; /* 4: Number of bytes in one audio subslot, 1,2,3, or 4 */ + uint8_t fl_resolution; /* 5: Number of bits used from audio subslot */ +}; + +#define USB_SIZEOF_ADC_T1_FORMAT_DESC 6 + +/* Type II Format Type Descriptor */ + +struct adc_t2_format_desc_s +{ + uint8_t t2_len; /* 0: Descriptor length (8) */ + uint8_t t2_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t t2_subtype; /* 2: Descriptor sub-type (ADC_AS_FORMAT_TYPE) */ + uint8_t t2_fmttype; /* 3: Identifies the format type (ADC_FORMAT_TYPEII) */ + uint8_t t2_bitrate[2]; /* 4 Maximum number of bits per second */ + uint8_t t2_slotsperframe[2]; /* 6: Number of PCM audio slots in one encoded audio frame*/ +}; + +#define USB_SIZEOF_ADC_T2_FORMAT_DESC 8 + +/* Type III Format Type Descriptor */ + +struct adc_t3_format_desc_s +{ + uint8_t t3_len; /* 0: Descriptor length (6) */ + uint8_t t3_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t t3_subtype; /* 2: Descriptor sub-type (ADC_AS_FORMAT_TYPE) */ + uint8_t t3_fmttype; /* 3: Identifies the format type (ADC_FORMAT_TYPEIII) */ + uint8_t t3_size; /* 4: Number of bytes in one audio subslot (2) */ + uint8_t t3_resolution; /* 5: Number of bits used from audio subslot */ +}; + +#define USB_SIZEOF_ADC_T3_FORMAT_DESC 6 + +/* Type IV Format Type Descriptor */ + +struct adc_t4_format_desc_s +{ + uint8_t t4_len; /* 0: Descriptor length (4) */ + uint8_t t4_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t t4_subtype; /* 2: Descriptor sub-type (ADC_AS_FORMAT_TYPE) */ + uint8_t t4_fmttype; /* 3: Identifies the format type (ADC_FORMAT_TYPEIV) */ +}; + +#define USB_SIZEOF_ADC_T4_FORMAT_DESC 6 + +/* Extended Type I Format Type Descriptor */ + +struct adc_x1_format_desc_s +{ + uint8_t x1_len; /* 0: Descriptor length (8) */ + uint8_t x1_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t x1_subtype; /* 2: Descriptor sub-type (ADC_AS_FORMAT_TYPE) */ + uint8_t x1_fmttype; /* 3: Identifies the format type (ADC_FORMAT_EXT_TYPEI) */ + uint8_t x1_size; /* 4: Number of bytes in one audio subslo, 1,2,3, or 4 */ + uint8_t xl_resolution; /* 5: Number of bits used from audio subslot */ + uint8_t x1_hdrlen; /* 6: Size of packet header (in bytes) */ + uint8_t x1_ctrlsize; /* 7: Size of control channel words (in bytes) */ + uint8_t x1_sbproto; /* 8: Sideband protocol used in packet header and ctrl channel */ +}; + +#define USB_SIZEOF_ADC_X1_FORMAT_DESC 8 + +/* Extended Type II Format Type Descriptor */ + +struct adc_x2_format_desc_s +{ + uint8_t x2_len; /* 0: Descriptor length (10) */ + uint8_t x2_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t x2_subtype; /* 2: Descriptor sub-type (ADC_AS_FORMAT_TYPE) */ + uint8_t x2_fmttype; /* 3: Identifies the format type (ADC_FORMAT_TYPEII) */ + uint8_t x2_bitrate[2]; /* 4 Maximum number of bits per second */ + uint8_t x2_samperframe[2]; /* 6: Number of PCM audio samples in one encoded audio frame*/ + uint8_t x2_hdrlen; /* 8: Size of packet header (in bytes) */ + uint8_t x2_sbproto; /* 9: Sideband protocol used in packet header and ctrl channel */ +}; + +#define USB_SIZEOF_ADC_x2_FORMAT_DESC 10 + +/* Extended Type III Format Type Descriptor */ + +struct adc_x3_format_desc_s +{ + uint8_t x3_len; /* 0: Descriptor length (8) */ + uint8_t x3_type; /* 1: Descriptor type (ADC_CS_INTERFACE) */ + uint8_t x3_subtype; /* 2: Descriptor sub-type (ADC_AS_FORMAT_TYPE) */ + uint8_t x3_fmttype; /* 3: Identifies the format type (ADC_FORMAT_TYPEIII) */ + uint8_t x3_size; /* 4: Number of bytes in one audio subslot (2) */ + uint8_t x3_resolution; /* 5: Number of bits used from audio subslot */ + uint8_t x3_hdrlen; /* 6: Size of packet header (in bytes) */ + uint8_t x3_sbproto; /* 7: Sideband protocol used in packet header and ctrl channel */ +}; + +#define USB_SIZEOF_ADC_X3_FORMAT_DESC 8 + +/* Hi-Res Presentation TimeStamp Layout*/ + +struct adc_hires_timestamp_s +{ + uint8_t hr_flags; /* Bit32=valid */ + uint8_t hr_nsec[8]; /* Offset in nanoseconds from the beginning of the stream */ +}; + +/******************************************************************************************** + * Public Function Prototypes + ********************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" { +#else +# define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_USB_AUDIO_H */ diff --git a/nuttx/include/nuttx/usb/cdc.h b/nuttx/include/nuttx/usb/cdc.h new file mode 100755 index 0000000000..627dd77e3d --- /dev/null +++ b/nuttx/include/nuttx/usb/cdc.h @@ -0,0 +1,879 @@ +/******************************************************************************************** + * include/nuttx/usb/cdc.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: "Universal Serial Bus Class Definitions for Communication + * Devices," Version 1.1, January 19, 1999 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_USB_CDC_H +#define __INCLUDE_NUTTX_USB_CDC_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include + +/******************************************************************************************** + * Pre-processor Definitions + ********************************************************************************************/ +/* Device Class Codes ***********************************************************************/ +/* Table 14: Communication Device Class Code (see definition USB_CLASS_CDC in usb.h) */ +/* Table 18: Data Interface Class Code (see definition USB_CLASS_CDC_DATA in usb.h) */ + +/* Communication Inteface Class Codes *******************************************************/ +/* Table 15: Communication Interface Class Code */ + +#define CDC_CLASS_COMM 0x02 /* Communication Interface Class */ + +/* Communication Interface Sub-Class Codes **************************************************/ + +#define CDC_SUBCLASS_NONE 0x00 /* Reserved */ +#define CDC_SUBCLASS_DLC 0x01 /* Direct Line Control Model */ +#define CDC_SUBCLASS_ACM 0x02 /* Abstract Control Model */ +#define CDC_SUBCLASS_TCM 0x03 /* Telephone Control Model */ +#define CDC_SUBCLASS_MCM 0x04 /* Multi-Channel Control Model */ +#define CDC_SUBCLASS_CAPI 0x05 /* CAPI Control Model */ +#define CDC_SUBCLASS_ECM 0x06 /* Ethernet Networking Control Model */ +#define CDC_SUBCLASS_ATM 0x07 /* ATM Networking Control Model */ + /* 0x08-0x7f Reserved (future use) */ + /* 0x80-0xfe Reserved (vendor specific) */ +/* Communication Interface Class Protocol Codes ********************************************/ +/* Table 17: Communication Interface Class Control Protocol Codes */ + +#define CDC_PROTO_NONE 0x00 /* No class specific protocol required */ +#define CDC_PROTO_ATM 0x01 /* Common AT commands (also known as Hayes compatible”) */ + /* 0x02-0xfe Reserved (future use) */ +#define CDC_PROTO_VENDOR 0xff /* Vendor-specific */ + +/* Data Interface Sub-Class Codes ***********************************************************/ +/* None defined, should be zero */ + +#define CDC_DATA_SUBCLASS_NONE 0x00 + +/* Date Interface Class Protocol Codes ******************************************************/ +/* Table 19: Data Interface Class Protocol Codes */ + +#define CDC_DATA_PROTO_NONE 0x00 /* No class specific protocol required */ + /* 0x01-0x2f Reserved (future use) */ +#define CDC_DATA_PROTO_ISDN 0x30 /* Physical interface protocol for ISDN BRI */ +#define CDC_DATA_PROTO_HDLC 0x31 /* HDLC */ +#define CDC_DATA_PROTO_TRANSP 0x32 /* Transparent */ + /* 0x33-0x4f Reserved (future use) */ +#define CDC_DATA_PROTO_Q921M 0x50 /* Management protocol for Q.921 data link protocol */ +#define CDC_DATA_PROTO_Q921 0x51 /* Data link protocol for Q.931 */ +#define CDC_DATA_PROTO_Q921TM 0x52 /* TEI-multiplexor for Q.921 data link protocol */ + /* 0x53-0x8f Reserved (future use) */ +#define CDC_DATA_PROTO_V42BIS 0x90 /* Data compression procedures */ +#define CDC_DATA_PROTO_EUROISDN 0x91 /* Euro-ISDN protocol control */ +#define CDC_DATA_PROTO_V120 0x92 /* V.24 rate adaptation to ISDN */ +#define CDC_DATA_PROTO_CAPI 0x93 /* CAPI Commands */ + /* 0x94-0xfc Reserved (future use) */ +#define CDC_DATA_PROTO_HBD 0xfd /* Host based driver. */ +#define CDC_DATA_PROTO_PUFD 0xfe /* The protocol(s) are described using a Protocol Unit + * Functional Descriptors on Communication Class + * Interface. + */ +#define CDC_DATA_PROTO_VENDOR 0xff /* Vendor-specific */ + +/* Requests and Notifications ***************************************************************/ +/* Table 2: Requests, Direct Line Control Model */ + +#define DLC_SET_AUX_LINE_STATE 0x10 /* Request to connect or disconnect secondary jack from + * POTS circuit or CODEC, depending on hook state. + * (Optional). + */ +#define DLC_SET_HOOK_STATE 0x11 /* Select relay setting for on-hook, off-hook, and caller + * ID. (Required) + */ +#define DLC_PULSE_SETUP 0x12 /* Initiate pulse dialing preparation. (Optional). + */ +#define DLC_SEND_PULSE 0x13 /* Request number of make/break cycles to generate. + * (Optional) + */ +#define DLC_SET_PULSE_TIME 0x14 /* Setup value for time of make and break periods when + * pulse dialing. (Optional) + */ +#define DLC_RING_AUX_JACK 0x15 /* Request for a ring signal to be generated on secondary + * phone jack. (Optional) + */ +/* Table 3: Notifications, Direct Line Control Model */ + +#define DLC_AUX_JACK_HOOK_STATE 0x08 /* Indicates hook state of secondary device plugged + * into the auxiliary phone jack. (Optional) + */ +#define DLC_RING_DETECT 0x09 /* Message to notify host that ring voltage was + * detected on POTS interface. (Required) + */ +/* Table 4: Requests, Abstract Control Model */ + +#define ACM_SEND_COMMAND 0x00 /* Issues a command in the format of the supported + * control protocol. (Required) + */ +#define ACM_GET_RESPONSE 0x01 /* Requests a response in the format of the + * supported control protocol. (Required) + */ +#define ACM_SET_COMM_FEATURE 0x02 /* Controls the settings for a particular + * communication feature. (Optional) + */ +#define ACM_GET_COMM_FEATURE 0x03 /* Returns the current settings for the + * communication feature. (Optional) + */ +#define ACM_CLEAR_COMM_FEATURE 0x04 /* Clears the settings for a particular + * communication feature. (Optional) + */ +#define ACM_SET_LINE_CODING 0x20 /* Configures DTE rate, stop-bits, parity, and + * number-of-character bits. (Optional) + */ +#define ACM_GET_LINE_CODING 0x21 /* Requests current DTE rate, stop-bits, parity, and + * number-of-character bits. (Optional) + */ +#define ACM_SET_CTRL_LINE_STATE 0x22 /* RS-232 signal used to tell the DCE device the + * DTE device is now present. (Optional) + */ +#define ACM_SEND_BREAK 0x23 /* Sends special carrier + */ +/* Table 5: Notifications, Abstract Control Model */ + +#define ACM_NETWORK_CONNECTION 0x00 /* Notification to host of network connection status. + * (Optional) + */ +#define ACM_RESPONSE_AVAILABLE 0x01 /* Notification to host to issue a GET_ENCAPSULATED_RESPONSE + * request. (Required) + */ +#define ACM_SERIAL_STATE 0x20 /* Returns the current state of the carrier detect, DSR, + * break, and ring signal. (Optional) + */ +/* Table 6: Requests, Telephone Control Model */ + +#define TCM_SET_COMM_FEATURE 0x02 /* Used to set a unique communication feature, which is + * normally specific to a particular device. + * (Optional) + */ +#define TCM_GET_COMM_FEATURE 0x03 /* Returns the current settings for the communication + * feature. (Optional) + */ +#define TCM_CLEAR_COMM_FEATURE 0x04 /* Clears the settings for a particular communication + * feature. (Optional) + */ +#define TCM_SET_RINGER_PARMS 0x30 /* Configures the ringer for a telephone device. + * (Optional) + */ +#define TCM_GET_RINGER_PARMS 0x31 /* Gets the current ringer configuration for a telephone + * device. (Required) + */ +#define TCM_SET_OPERATION_PARMS 0x32 /* Configures the operational mode of the telephone. + * (Optional) + */ +#define TCM_GET_OPERATION_PARMS 0x33 /* Gets the current operational mode of the telephone. + * (Optional) + */ +#define TCM_SET_LINE_PARMS 0x34 /* Allows changing the current state of the line + * associated with the interface, providing basic call + * capabilities, such as dialing and answering calls. + * (Required) + */ +#define TCM_GET_LINE_PARMS 0x35 /* Gets current status of the line. (Required) + */ +#define TCM_DIAL_DIGITS 0x36 /* Dials digits on the network connection. (Required) + */ +/* Table 7: Notifications, Telephone Control Model */ + +#define TCM_CALL_STATE_CHANGE 0x28 /* DReports a state change on a call. (Required) + */ +#define TCM_LINE_STATE_CHANGE 0x29 /* DReports a state change on a line. (Optional) + */ +/* Table 8: Requests, Multi-Channel Model */ + +#define MCM_SET_UNIT_PARAM 0x37 /* Used to set a Unit specific parameter (Optional) + */ +#define MCM_GET_UNIT_PARAM 0x38 /* Used to retrieve a Unit specific parameter (Required) + */ +#define MCM_CLEAR_UNIT_PARAM 0x39 /* Used to set a Unit specific parameter to its default + * state. (Optional) + */ +/* Table 9: Request, CAPI Control Model */ + +#define CAPI_GET_PROFILE 0x3a /* Returns the implemented capabilities of the device + * (Required) + */ +/* Table 10: Requests, Ethernet Networking Control Model */ + +#define ECM_SEND_COMMAND 0x00 /* Issues a command in the format of the supported + * control protocol. The intent of this mechanism is + * to support networking devices (e.g., host-based + * cable modems) that require an additional vendor- + * defined interface for media specific hardware + * configuration and management. (Optional) + */ +#define ECM_GET_RESPONSE 0x01 /* equests a response in the format of the supported + * control protocol. + * (Optional) + */ +#define ECM_SET_MCAST_FILTERS 0x40 /* As applications are loaded and unloaded on the host, + * the networking transport will instruct the device’s MAC + * driver to change settings of the Networking device’s + * multicast filters. (Optional) + */ +#define ECM_SET_PM_PAT_FILTER 0x41 /* Some hosts are able to conserve energy and stay quiet + * in a “sleeping” state while not being used. USB + * Networking devices may provide special pattern filtering + * hardware that enables it to wake up the attached host + * on demand when something is attempting to contact the + * host (e.g., an incoming web browser connection). + * Primitives are needed in management plane to negotiate + * the setting of these special filters + * (Optional) + */ +#define ECM_GET_PM_PAT_FILTER 0x42 /* Retrieves the status of the above power management + * pattern filter setting + * (Optional) + */ +#define ECM_SET_PACKET_FILTER 0x43 /* Sets device filter for running a network analyzer + * application on the host machine (Required) + */ +#define ECM_GET_STATISTIC 0x44 /* Retrieves Ethernet device statistics such as frames + * transmitted, frames received, and bad frames received. + * (Optional) + */ +/* Table 11: Notifications, Ethernet Networking Control Model */ + +#define ECM_NETWORK_CONNECTION 0x00 /* Reports whether or not the physical layer (modem, + * Ethernet PHY, etc.) link is up. (Required) + */ +#define ECM_RESPONSE_AVAILABLE 0x01 /* Notification to host to issue a + * GET_ENCAPSULATED_RESPONSE request. (Optional) + */ +#define ECM_SPEED_CHANGE 0x2a /* Reports a change in upstream or downstream (Required) + */ +/* Table 12: Requests, ATM Networking Control Model */ + +#define ATM_SEND_COMMAND 0x00 /* Issues a command in the format of the supported control + * protocol. The intent of this mechanism is to support + * networking devices (e.g., host-based cable modems) + * that require an additional vendor-defined interface for + * media specific hardware configuration and + * management. (Optional) + */ +#define ATM_GET_RESPONSE 0x01 /* Requests a response in the format of the supported + * control protocol. (Optional) + */ +#define ATM_SET_DATA_FORMAT 0x50 /* Chooses which ATM data format will be exchanged + * between the host and the ATM Networking device. + * (Required) + */ +#define ATM_GET_DEV_STATISTICS 0x51 /* Retrieves global statistics from the ATM Networking + * device. (Required) + */ +#define ATM_SET_DEFAULT_VC 0x52 /* Pre-selects the VPI/VCI value for subsequent + * GetATMVCStatistics requests (Optional) + */ +#define ATM_GET_VC_STATISTICS 0x53 /* Retrieves statistics from the ATM Networking device for + * a particular VPI/VCI. (Optional) + */ +/* Table 13: Requests, Ethernet and ATM Networking Control Model */ + +#define ATM_NETWORK_CONNECTION 0x00 /* Reports whether or not the physical layer (modem, + * Ethernet PHY, etc.) link is up. (Required) + */ +#define ECM_NETWORK_CONNECTION ATM_NETWORK_CONNECTION +#define ATM_RESPONSE_AVAILABLE 0x01 /* Notification to host to issue a + * GET_ENCAPSULATED_RESPONSE request. (Optional) + */ +#define ECM_RESPONSE_AVAILABLE ATM_RESPONSE_AVAILABLE +#define ATM_SPEED_CHANGE 0x2a /* Reports a change in upstream or downstream speed of the + * networking device connection. (Required) + */ +#define ECM_SPEED_CHANGE ATM_SPEED_CHANGE + +/* Descriptors ******************************************************************************/ +/* Table 25: bDescriptor SubType in Functional Descriptors */ + +#define CDC_DSUBTYPE_HDR 0x00 /* Header Functional Descriptor, which marks the + * beginning of the concatenated set of functional + * descriptors for the interface. */ +#define CDC_DSUBTYPE_CALLMGMT 0x01 /* Call Management Functional Descriptor */ +#define CDC_DSUBTYPE_ACM 0x02 /* Abstract Control Management Functional Descriptor */ +#define CDC_DSUBTYPE_DLC 0x03 /* Direct Line Management Functional Descriptor */ +#define CDC_DSUBTYPE_TCMRINGER 0x04 /* Telephone Ringer Functional Descriptor */ +#define CDC_DSUBTYPE_TCMCALL 0x05 /* Telephone Call and Line State Reporting Capabilities + * Functional Descriptor. */ +#define CDC_DSUBTYPE_UNION 0x06 /* Union Functional descriptor */ +#define CDC_DSUBTYPE_COUNTRY 0x07 /* Country Selection Functional Descriptor */ +#define CDC_DSUBTYPE_TCMOPS 0x08 /* Telephone Operational Modes Functional Descriptor */ +#define CDC_DSUBTYPE_USBTERM 0x09 /* USB Terminal Functional Descriptor */ +#define CDC_DSUBTYPE_NETCHAN 0x0a /* Network Channel Terminal Descriptor */ +#define CDC_DSUBTYPE_PROTOUNIT 0x0b /* Protocol Unit Functional Descriptor */ +#define CDC_DSUBTYPE_EXTUNIT 0x0c /* Extension Unit Functional Descriptor */ +#define CDC_DSUBTYPE_MCM 0x0d /* Multi-Channel Management Functional Descriptor */ +#define CDC_DSUBTYPE_CAPI 0x0e /* CAPI Control Management Functional Descriptor */ +#define CDC_DSUBTYPE_ECM 0x0f /* Ethernet Networking Functional Descriptor */ +#define CDC_DSUBTYPE_ATM 0x10 /* ATM Networking Functional Descriptor */ + /* 0x11-0xff Reserved (future use) */ + +/* Table 42: Ethernet Statistics Capabilities */ + +#define ECMCAP_XMIT_OK (1 << 0) /* Frames transmitted without errors */ +#define ECMCAP_RVC_OK (1 << 1) /* Frames received without errors */ +#define ECMCAP_XMIT_ERROR (1 << 2) /* Frames not transmitted, or transmitted with errors */ +#define ECMCAP_RCV_ERROR (1 << 3) /* Frames received with errors that are not delivered + * to the USB host + */ +#define ECMCAP_RCV_NO_BUFFER (1 << 4) /* Frame missed, no buffers */ +#define ECMCAP_DIR_BYTES_XMIT (1 << 5) /* Directed bytes transmitted without errors */ +#define ECMCAP_DIR_FRAMES_XMIT (1 << 6) /* Directed frames transmitted without errors */ +#define ECMCAP_MCAST_BYTES_XMIT (1 << 7) /* Multicast bytes transmitted without errors */ +#define ECMCAP_MCAST_FRAMES_XMIT (1 << 8) /* Multicast frames transmitted without errors */ +#define ECMCAP_BCAST_BYTES_XMIT (1 << 9) /* Broadcast bytes transmitted without errors */ +#define ECMCAP_BCAST_FRAMES_XMIT (1 << 10) /* Broadcast frames transmitted without errors */ +#define ECMCAP_DIR_BYTES_RCV (1 << 11) /* Directed bytes received without errors */ +#define ECMCAP_DIR_FRAMES_RCV (1 << 12) /* Directed frames received without errors */ +#define ECMCAP_MCAST_BYTES_RCV (1 << 13) /* Multicast bytes received without errors */ +#define ECMCAP_MCAST_FRAMES_RCV (1 << 14) /* Multicast frames received without errors */ +#define ECMCAP_BCAST_BYTES_RCV (1 << 15) /* Broadcast bytes received without errors */ +#define ECMCAP_BCAST_FRAMES_RCV (1 << 16) /* Broadcast frames received without errors */ +#define ECMCAP_RCV_CRC_ERROR (1 << 17) /* Frames received with circular redundancy check + * (CRC) or frame check sequence (FCS) error + */ +#define ECMCAP_TRANSMIT_QUEUE_LENG (1 << 18) /* Length of transmit queue */ +#define ECMCAP_RCV_ERROR_ALIGNMENT (1 << 19) /* Frames received with alignment error */ +#define ECMCAP_XMIT_ONE_COLL (1 << 20) /* Frames transmitted with one collision */ +#define ECMCAP_XMIT_MORE_COLLS (1 << 21) /* Frames transmitted with more than one collision */ +#define ECMCAP_XMIT_DEFERRED (1 << 22) /* Frames transmitted after deferral */ +#define ECMCAP_XMIT_MAX_COLLS (1 << 23) /* Frames not transmitted due to collisions */ +#define ECMCAP_RCV_OVERRUN (1 << 24) /* Frames not received due to overrun */ +#define ECMCAP_XMIT_UNDERRUN (1 << 25) /* Frames not transmitted due to underrun */ +#define ECMCAP_XMIT_HB_FAILURE (1 << 26) /* Frames transmitted with heartbeat failure */ +#define ECMCAP_XMIT_TIMES_CRS_LOST (1 << 27) /* Times carrier sense signal lost during + * transmission + */ +#define ECMCAP_XMIT_LATE_COLLS (1 << 28) /* Late collisions detected */ + /* Bits 29-31 Resrved, Must be set to zero */ + +/* Table 47: Communication Feature Selector Codes */ + +#define FEATURE_ABSTRACT_STATE 0x01 /* Two bytes of data describing multiplexed state + * and idle state for this Abstract Model + * communications device + */ +#define FEATURE_COUNTRY_SETTING 0x02 /* Country code in hexadecimal format as defined in + * ISO 3166 + */ +/* Table 49: POTS Relay Configuration Values */ + +#define POTS_ON_HOOK 0x0000 +#define POTS_OFF_HOOK 0x0001 +#define POTS_SNOOPING 0x0002 + +/* Table 50: Line Coding Structure */ + +#define CDC_CHFMT_STOP1 0 /* One stop bit */ +#define CDC_CHFMT_STOP1p5 1 /* 1.5 stop bits */ +#define CDC_CHFMT_STOP2 2 /* 2 stop bits */ + +#define CDC_PARITY_NONE 0 /* No parity */ +#define CDC_PARITY_ODD 1 /* Odd parity */ +#define CDC_PARITY_EVEN 2 /* Even parity */ +#define CDC_PARITY_MARK 3 /* Mark parity */ +#define CDC_PARITY_SPACE 4 /* Space parity */ + +/* Table 51: Control Signal Bitmap Values for SetControlLineState */ + +#define CDC_DTE_PRESENT (1 << 0) /* Indicates to DCE if DTE is present or not. + * This signal corresponds to V.24 signal + * 108/2 and RS-232 signal DTR. + */ +#define CDC_ACTIVATE_CARRIER (1 << 1) /* Carrier control for half duplex modems. + * This signal corresponds to V.24 signal + * 105 and RS-232 signal RTS. + */ + +/* Table 58: Call State Value Definitions */ + +#define CDC_CALLST_IDLE 0x00 /* Call is idle */ +#define CDC_CALLST_DIAL 0x01 /* Typical dial tone */ +#define CDC_CALLST_INTDIAL 0x02 /* Interrupted dial tone */ +#define CDC_CALLST_DIALING 0x03 /* Dialing is in progress */ +#define CDC_CALLST_RINGBACK 0x04 /* Ringback */ +#define CDC_CALLST_CONNECTED 0x05 /* Connected */ +#define CDC_CALLSTINCOMING 0x06 /* Incoming call */ + +/* Table 62: Ethernet Packet Filter Bitmap */ + +#define PACKET_TYPE_PROMISCUOUS (1 << 0) +#define PACKET_TYPE_ALL_MULTICAST (1 << 1) +#define PACKET_TYPE_DIRECTED (1 << 2) +#define PACKET_TYPE_BROADCAST (1 << 3) +#define PACKET_TYPE_MULTICAST (1 << 4) + +/* Table 63: Ethernet Statistics Feature Selector Codes */ + +#define ECM_XMIT_OK 0x01 /* Frames transmitted without errors */ +#define ECM_RVC_OK 0x02 /* Frames received without errors */ +#define ECM_XMIT_ERROR 0x03 /* Frames not transmitted, or transmitted with errors */ +#define ECM_RCV_ERROR 0x04 /* Frames received with errors that are not delivered + * to the USB host + */ +#define ECM_RCV_NO_BUFFER 0x05 /* Frame missed, no buffers */ +#define ECM_DIR_BYTES_XMIT 0x06 /* Directed bytes transmitted without errors */ +#define ECM_DIR_FRAMES_XMIT 0x07 /* Directed frames transmitted without errors */ +#define ECM_MCAST_BYTES_XMIT 0x08 /* Multicast bytes transmitted without errors */ +#define ECM_MCAST_FRAMES_XMIT 0x09 /* Multicast frames transmitted without errors */ +#define ECM_BCAST_BYTES_XMIT 0x0a /* Broadcast bytes transmitted without errors */ +#define ECM_BCAST_FRAMES_XMIT 0x0b /* Broadcast frames transmitted without errors */ +#define ECM_DIR_BYTES_RCV 0x0c /* Directed bytes received without errors */ +#define ECM_DIR_FRAMES_RCV 0x0d /* Directed frames received without errors */ +#define ECM_MCAST_BYTES_RCV 0x0e /* Multicast bytes received without errors */ +#define ECM_MCAST_FRAMES_RCV 0x0f /* Multicast frames received without errors */ +#define ECM_BCAST_BYTES_RCV 0x10 /* Broadcast bytes received without errors */ +#define ECM_BCAST_FRAMES_RCV 0x11 /* Broadcast frames received without errors */ +#define ECM_RCV_CRC_ERROR 0x12 /* Frames received with circular redundancy check + * (CRC) or frame check sequence (FCS) error + */ +#define ECM_TRANSMIT_QUEUE_LENG 0x13 /* Length of transmit queue */ +#define ECM_RCV_ERROR_ALIGNMENT 0x14 /* Frames received with alignment error */ +#define ECM_XMIT_ONE_COLL 0x15 /* Frames transmitted with one collision */ +#define ECM_XMIT_MORE_COLLS 0x16 /* Frames transmitted with more than one collision */ +#define ECM_XMIT_DEFERRED 0x17 /* Frames transmitted after deferral */ +#define ECM_XMIT_MAX_COLLS 0x18 /* Frames not transmitted due to collisions */ +#define ECM_RCV_OVERRUN 0x19 /* Frames not received due to overrun */ +#define ECM_XMIT_UNDERRUN 0x1a /* Frames not transmitted due to underrun */ +#define ECM_XMIT_HB_FAILURE 0x1b /* Frames transmitted with heartbeat failure */ +#define ECM_XMIT_TIMES_CRS_LOST 0x1c /* Times carrier sense signal lost during + * transmission + */ +#define ECM_XMIT_LATE_COLLS 0x1d /* Late collisions detected */ + +/* Table 64: ATM Data Format */ + +#define ATM_FMT_TYPE1 1 /* Type 1 format: concatenated ATM cells */ +#define ATM_FMT_TYPE1 2 /* Type 2 format: ATM header template + concatenated ATM + * cell payloads + */ +#define ATM_FMT_TYPE1 3 /* Type 3 format: AAL 5 SDU */ + +/* Table 65: ATM Device Statistics Feature Selector Codes */ + +#define US_CELLS_SENT 0x01h /* The number of cells that have been sent + * upstream to the WAN link by the ATM layer. + */ +#define DS_CELLS_RECEIVED 0x02h /* The number of cells that have been received + * downstream from the WAN link by the ATM + * layer. + */ +#define DS_CELLS_USB_CONGESTION 0x03h /* The number of cells that have been received + * downstream from the WAN link by the ATM + * layer and discarded due to congestion on the + * USB link. + */ +#define DS_CELLS_AAL5_CRC_ERROR 0x04h /* The number of cells that have been received + * downstream from the WAN link by the ATM + * layer and discarded due to AAL5 CRC errors. + */ +#define DS_CELLS_HEC_ERROR 0x05h /* The number of cells that have been received + * downstream from the WAN link and discarded + * due to HEC errors in the cell header. + */ +#define DS_CELLS_HEC_ERROR_CORRECTED 0x06h /* The number of cells that have been received + * downstream from the WAN link and have + * been detected with HEC errors in the cell + * header and successfully corrected. + */ +/* Table 66: ATM VC Selector Codes */ + +#define VC_US_CELLS_SENT 0x01 /* The number of cells that have been sent upstream to + * the WAN link for the specified VPI/VCI since the + * device has been powered on or reset + */ +#define VC_DS_CELLS_RECEIVED 0x02 /* The number of cells that have been received + * downstream from the WAN link for the specified + * VPI/VCI since the device has been + * powered on or reset + */ +/* Notifications ****************************************************************************/ +/* Table 69: UART State Bitmap Values */ + +#define CDC_UART_RXCARRIER (1 << 0) /* bRxCarrier State of receiver carrier detection + * mechanism of device. This signal corresponds to + * V.24 signal 109 and RS-232 signal DCD. + */ +#define CDC_UART_TXCARRIER (1 << 1) /* bTxCarrier State of transmission carrier. This + * signal corresponds to V.24 signal 106 and RS-232 + * signal DSR. + */ +#define CDC_UART_BREAK (1 << 2) /* bBreak State of break detection mechanism of the + * device. + */ +#define CDC_UART_RING (1 << 3) /* bRingSignal State of ring signal detection of the + * device. + */ +#define CDC_UART_FRAMING (1 << 4) /* bFraming A framing error has occurred */ +#define CDC_UART_PARITY (1 << 5) /* bParity A parity error has occurred */ +#define CDC_UART_OVERRUN (1 << 6) /* bOverRun Received data has been discarded due to + * overrun in the device. + */ +/* Table 70: Call State Change Value Definitions */ + +#define CDC_CALLST_IDLE 0x01 /* Call has become idle */ +#define CDC_CALLST_DIALING 0x02 /* Dialing */ +#define CDC_CALLST_RINGBACK 0x03 /* Ringback, with an extra byte of data provided to + * describe the type of ringback signaling + */ +#define CDC_CALLST_CONNECTED 0x04 /* Connected, with an extra byte of data provided to + * describe the type of connection + */ +#define CDC_CALLST_INCOMING 0x05 /* Incoming Call, with the extra bytes of data */ + +/* Table 71: Line State Change Values */ + +#define CDC_LINEST_IDLE 0x0000 /* Line has become idle */ +#define CDC_LINEST_HOLD 0x0001 /* Line connected to hold position */ +#define CDC_LINEST_OFFHOOK 0x0002 /* Hook-switch has gone off hook */ +#define CDC_LINEST_ONHOOK 0x0003 /* Hook-switch has gone on hook */ + +/******************************************************************************************** + * Public Types + ********************************************************************************************/ + +/* Table 1: Data Class Protocol Wrapper */ + +struct cdc_protowrapper_s +{ + uint8_t size[2]; /* Size of wrapper in bytes */ + uint8_t dstproto; /* bDstProtocol, Destination protocol ID */ + uint8_t srcproto; /* bSrcProtocol, Source protocol ID */ + uint8_t data[1]; /* Data payload, actual size depends of size of the wrapper */ +}; + +/* Functional Descriptors *******************************************************************/ +/* Table 23: Functional Descriptor General Format */ + +struct cdc_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t data[1]; /* Function-specific data follows */ +}; + +/* Table 26: Class-Specific Descriptor Header Format */ + +struct cdc_hdr_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_HDR as defined in Table 25 */ + uint8_t cdc[2]; /* bcdCDC, USB Class Definitions for Communication Devices Specification release + * number in binary-coded decimal. + */ +}; +#define SIZEOF_HDR_FUNCDESC 5 + +/* Table 27: Call Management Functional Descriptor */ + +struct cdc_callmgmt_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_CALLMGMT as defined in Table 25 */ + uint8_t caps; /* bmCapabilities: Bit encoded */ + uint8_t ifno; /* bDataInterface, Interface number of Data Class interface + * optionally used for call management + */ +}; +#define SIZEOF_CALLMGMT_FUNCDESC 5 + +/* Table 28: Abstract Control Management Functional Descriptor */ + +struct cdc_acm_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_ACM as defined in Table 25 */ + uint8_t caps; /* bmCapabilities: Bit encoded */ +}; +#define SIZEOF_ACM_FUNCDESC 4 + +/* Table 29: Direct Line Management Functional Descriptor */ + +struct cdc_dlc_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_DLC as defined in Table 25 */ + uint8_t caps; /* bmCapabilities: Bit encoded */ +}; +#define SIZEOF_DLC_FUNCDESC 4 + +/* Table 30: Telephone Ringer Functional Descriptor */ + +struct cdc_tcmr_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_TCMRINGER as defined in Table 25 */ + uint8_t volsteps; /* bRingerVolSteps, Number of discrete steps in volume supported + * by the ringer. + */ + uint8_t npats; /* bNumRingerPatterns: Number of ringer patterns supported. */ +}; +#define SIZEOF_TCMR_FUNCDESC 5 + +/* Table 31: Telephone Operational Modes Functional Descriptor */ + +struct cdc_tcmops_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_TCMOPS as defined in Table 25 */ + uint8_t caps; /* bmCapabilities: Bit encoded */ +}; +#define SIZEOF_TCMOPS_FUNCDESC 4 + +/* Table 32: Telephone Call State Reporting Capabilities Descriptor */ + +struct cdc_tcmc_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_TCMCALL as defined in Table 25 */ + uint8_t caps; /* bmCapabilities: Bit encoded */ +}; +#define SIZEOF_TCMC_FUNCDESC 4 + +/* Table 33: Union Interface Functional Descriptor */ + +struct cdc_union_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_UNION as defined in Table 25 */ + uint8_t master; /* bMasterInterface: The interface number of the Communication or Data + * Class interface, designated as the master or controlling interface + * for the union + */ + uint8_t slave[1]; /* bSlaveInterfaceN: Interface number of N slave or associated + * interface in the union + */ +}; +#define SIZEOF_UNION_FUNCDESC(n) ((n)+4) + +/* Table 34: Country Selection Functional Descriptor */ + +struct cdc_country_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_COUNTRY as defined in Table 25 */ + uint8_t reldate; /* iCountryCodeRelDate: Index of a string giving the release date for the + * implemented ISO 3166 Country Codes + */ + uint16_t code[1]; /* wCountryCodeN: Country code in hexadecimal format as defined in ISO 3166, + * release date as specified in offset 3 for Nth country supported + */ +}; +#define SIZEOF_COUNTRY_FUNCDESC(n) (sizeof(uint16_t)*(n) + 4) + +/* Table 35: USB Terminal Functional Descriptor */ + +struct cdc_usbterm_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_USBTERM as defined in Table 25 */ + uint8_t id; /* bEntityId, Constant uniquely identifying the Terminal */ + uint8_t ifno; /* bInInterfaceNo, The input interface number of the associated + * USB interface + */ + uint8_t outif; /* bOutInterfaceNo, The output interface number of the associated + * USB interface + */ + uint8_t options; /* bmOptions, bit-encoded options */ + uint8_t child[1]; /* Nth ID of lower Terminal or Unit to which this Terminal is connected. */ +}; +#define SIZEOF_USBTERM_FUNCDESC(n) ((n)+7) + +/* Table 36: Network Channel Terminal Functional Descriptor */ + +struct cdc_netchan_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_NETCHAN as defined in Table 25 */ + uint8_t id; /* bEntityId, Constant uniquely identifying the Terminal */ + uint8_t name; /* iName, Index of string descriptor, describing the name of the Network + * Channel Terminal + */ + uint8_t index; /* bChannelIndex, The channel index of the associated network channel */ + uint8_t phyif; /* bPhysicalInterface, Type of physical interface */ +}; +#define SIZEOF_NETCHAN_FUNCDESC 7 + +/* Table 37: Protocol Unit Functional Descriptor */ + +struct cdc_protounit_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_PROTOUNIT as defined in Table 25 */ + uint8_t id; /* bEntityId, Constant uniquely identifying the Unit */ + uint8_t proto; /* bProtocol, Protocol code as defined in Table 19 */ + uint8_t child[1]; /* Nth ID of lower Terminal or Unit to which this Terminal is connected */ +}; +#define SIZEOF_PROTOUNIT_FUNCDESC(n) ((n)+5) + +/* Table 38: Extension Unit Functional Descriptor */ + +struct cdc_extunit_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_EXTUNIT as defined in Table 25 */ + uint8_t id; /* bEntityId, Constant uniquely identifying the Extension Unit */ + uint8_t code; /* bExtensionCode, Vendor specific code identifying the Extension Unit */ + uint8_t name; /* iName, Index of string descriptor, describing the name of the Extension Unit */ + uint8_t child[1]; /* Nth ID of lower Terminal or Unit to which this Terminal is connected */ +}; +#define SIZEOF_EXTUNIT_FUNCDESC(n) ((n)+6) + +/* Table 39: Multi-Channel Management Functional Descriptor */ + +struct cdc_mcm_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_MCM as defined in Table 25 */ + uint8_t caps; /* bmCapabilities: Bit encoded */ +}; +#define SIZEOF_MCM_FUNCDESC 4 + +/* Table 40: CAPI Control Management Functional Descriptor */ + +struct cdc_capi_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_CAPI as defined in Table 25 */ + uint8_t caps; /* bmCapabilities: Bit encoded */ +}; +#define SIZEOF_CAPI_FUNCDESC 4 + +/* Table 41: Ethernet Networking Functional Descriptor*/ + +struct cdc_ecm_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_ECM as defined in Table 25 */ + uint8_t mac; /* iMACAddress, Index of teh 48bit Ethernet MAC address string descriptor */ + uint8_t stats[4]; /* bmEthernetStatistics, Indicates which Ethernet statistics functions + * the device collects. See Table 42. + */ + uint8_t maxseg[2]; /* wMaxSegmentSize, The maximum segment size that the Ethernet device is + * capable of supporting. + */ + uint8_t nmcflts[2]; /* wNumberMCFilters, Contains the number of multicast filters that can be + * configured by the host. + */ + uint8_t npwrflts; /* bNumberPowerFilters, Contains the number of pattern filters that are + * available for causing wake-up of the host. + */ +}; +#define SIZEOF_ECM_FUNCDESC 13 + +/* Table 43: ATM Networking Functional Descriptor */ + +struct cdc_atm_funcdesc_s +{ + uint8_t size; /* bFunctionLength, Size of this descriptor */ + uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */ + uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_ATM as defined in Table 25 */ + uint8_t endid; /* iEndSystemIdentifier, Index of End System Identifier string descriptor */ + uint8_t datacaps; /* bmDataCapabilities, The ATM data types the device supports */ + uint8_t devstats; /* bmATMDeviceStatistics, Indicates which optional statistics functions the + * device collects. + */ + uint8_t mxseg2[2]; /* wType2MaxSegmentSize, The maximum segment size that the Type 2 device is + * capable of supporting. + */ + uint8_t mxseg3[2]; /* wType3MaxSegmentSize, The maximum segment size that the Type 3 device is + * capable of supporting + */ + uint8_t mxvc[2]; /* wMaxVC, The maximum number of simultaneous virtual circuits the device is + * capable of supporting + */ +}; +#define SIZEOF_CALLMGMT_FUNCDESC 12 + +/* Descriptor Data Structures ***************************************************************/ +/* Table 50: Line Coding Structure */ + +struct cdc_linecoding_s +{ + uint8_t baud[4]; /* dwDTERate, Data terminal rate, in bits per second */ + uint8_t stop; /* bCharFormat 0=1, 1=1.5, 2=2 stop bits */ + uint8_t parity; /* bParityType, 0=None, 1=Odd, 2=Even, 3=Mark, 4=Space */ + uint8_t nbits; /* bDataBits, Data bits (5,6,7,8, or 16) */ +}; +#define SIZEOF_CDC_LINECODING 7 + +/* Table 55: Line Status Information Structure */ + +struct cdc_linestatus_s +{ + uint8_t size[2]; /* wLength, Size of this structure, in bytes */ + uint8_t ringer[4]; /* dwRingerBitmap, Ringer Configuration bitmap for this line */ + uint8_t line[4]; /* dwLineState, Defines current state of the line */ + uint32_t call[1]; /* dwCallStateN, Defines current state of call N on the line */ +}; + +/* Table 60: Unit Parameter Structure */ + +struct cdc_unitparm_s +{ + uint8_t id; /* bEntityId, Unit ID */ + uint8_t index; /* bParameterIndex, A zero based value indicating Unit parameter index */ +}; + +/* Table 61: Power Management Pattern Filter Structure */ + +/* Notification Data Structures *************************************************************/ +/* Table 72: ConnectionSpeedChange Data Structure */ + +struct cdc_speedchange_s +{ + uint8_t us[4]; /* Contains the upstream bit rate, in bits per second */ + uint8_t ds[4]; /* Contains the downstream bit rate, in bits per second */ +}; + +#endif /* __INCLUDE_NUTTX_USB_CDC_H */ diff --git a/nuttx/include/nuttx/usb/cdcacm.h b/nuttx/include/nuttx/usb/cdcacm.h new file mode 100644 index 0000000000..307f2a5977 --- /dev/null +++ b/nuttx/include/nuttx/usb/cdcacm.h @@ -0,0 +1,417 @@ +/**************************************************************************** + * include/nuttx/usb/cdcacm.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_USB_CDCACM_H +#define __INCLUDE_NUTTX_USB_CDCACM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Preprocessor definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_CDCACM + * Enable compilation of the USB serial driver + * CONFIG_CDCACM_EP0MAXPACKET + * Endpoint 0 max packet size. Default 64. + * CONFIG_CDCACM_EPINTIN + * The logical 7-bit address of a hardware endpoint that supports + * interrupt IN operation. Default 2. + * CONFIG_CDCACM_EPINTIN_FSSIZE + * Max package size for the interrupt IN endpoint if full speed mode. + * Default 64. + * CONFIG_CDCACM_EPINTIN_HSSIZE + * Max package size for the interrupt IN endpoint if high speed mode. + * Default 64. + * CONFIG_CDCACM_EPBULKOUT + * The logical 7-bit address of a hardware endpoint that supports + * bulk OUT operation + * CONFIG_CDCACM_EPBULKOUT_FSSIZE + * Max package size for the bulk OUT endpoint if full speed mode. + * Default 64. + * CONFIG_CDCACM_EPBULKOUT_HSSIZE + * Max package size for the bulk OUT endpoint if high speed mode. + * Default 512. + * CONFIG_CDCACM_EPBULKIN + * The logical 7-bit address of a hardware endpoint that supports + * bulk IN operation + * CONFIG_CDCACM_EPBULKIN_FSSIZE + * Max package size for the bulk IN endpoint if full speed mode. + * Default 64. + * CONFIG_CDCACM_EPBULKIN_HSSIZE + * Max package size for the bulk IN endpoint if high speed mode. + * Default 512. + * CONFIG_CDCACM_NWRREQS and CONFIG_CDCACM_NRDREQS + * The number of write/read requests that can be in flight. + * CONFIG_CDCACM_NWRREQS includes write requests used for both the + * interrupt and bulk IN endpoints. Default 4. + * CONFIG_CDCACM_VENDORID and CONFIG_CDCACM_VENDORSTR + * The vendor ID code/string. Default 0x0525 and "NuttX" + * 0x0525 is the Netchip vendor and should not be used in any + * products. This default VID was selected for compatibility with + * the Linux CDC ACM default VID. + * CONFIG_CDCACM_PRODUCTID and CONFIG_CDCACM_PRODUCTSTR + * The product ID code/string. Default 0xa4a7 and "CDC/ACM Serial" + * 0xa4a7 was selected for compatibility with the Linux CDC ACM + * default PID. + * CONFIG_CDCACM_RXBUFSIZE and CONFIG_CDCACM_TXBUFSIZE + * Size of the serial receive/transmit buffers. Default 256. + */ + +/* EP0 max packet size */ + +#ifndef CONFIG_CDCACM_EP0MAXPACKET +# define CONFIG_CDCACM_EP0MAXPACKET 64 +#endif + +/* Endpoint number and size (in bytes) of the CDC serial device-to-host (IN) + * notification interrupt endpoint. + */ + +#ifndef CONFIG_CDCACM_EPINTIN +# define CONFIG_CDCACM_EPINTIN 2 +#endif + +#ifndef CONFIG_CDCACM_EPINTIN_FSSIZE +# define CONFIG_CDCACM_EPINTIN_FSSIZE 64 +#endif + +#ifndef CONFIG_CDCACM_EPINTIN_HSSIZE +# define CONFIG_CDCACM_EPINTIN_HSSIZE 64 +#endif + +/* Endpoint number and size (in bytes) of the CDC device-to-host (IN) data + * bulk endpoint. NOTE that difference sizes may be selected for full (FS) + * or high speed (HS) modes. + */ + +#ifndef CONFIG_CDCACM_EPBULKIN +# define CONFIG_CDCACM_EPBULKIN 3 +#endif + +#ifndef CONFIG_CDCACM_EPBULKIN_FSSIZE +# define CONFIG_CDCACM_EPBULKIN_FSSIZE 64 +#endif + +#ifndef CONFIG_CDCACM_EPBULKIN_HSSIZE +# define CONFIG_CDCACM_EPBULKIN_HSSIZE 512 +#endif + +/* Endpoint number and size (in bytes) of the CDC host-to-device (OUT) data + * bulk endpoint. NOTE that difference sizes may be selected for full (FS) + * or high speed (HS) modes. + */ + +#ifndef CONFIG_CDCACM_EPBULKOUT +# define CONFIG_CDCACM_EPBULKOUT 4 +#endif + +#ifndef CONFIG_CDCACM_EPBULKOUT_FSSIZE +# define CONFIG_CDCACM_EPBULKOUT_FSSIZE 64 +#endif + +#ifndef CONFIG_CDCACM_EPBULKOUT_HSSIZE +# define CONFIG_CDCACM_EPBULKOUT_HSSIZE 512 +#endif + +/* Number of requests in the write queue. This includes write requests used + * for both the interrupt and bulk IN endpoints. + */ + +#ifndef CONFIG_CDCACM_NWRREQS +# define CONFIG_CDCACM_NWRREQS 4 +#endif + +/* Number of requests in the read queue */ + +#ifndef CONFIG_CDCACM_NRDREQS +# define CONFIG_CDCACM_NRDREQS 4 +#endif + +/* TX/RX buffer sizes */ + +#ifndef CONFIG_CDCACM_RXBUFSIZE +# define CONFIG_CDCACM_RXBUFSIZE 256 +#endif + +#ifndef CONFIG_CDCACM_TXBUFSIZE +# define CONFIG_CDCACM_TXBUFSIZE 256 +#endif + +/* Vendor and product IDs and strings. The default is the Linux Netchip + * CDC ACM VID and PID. + */ + +#ifndef CONFIG_CDCACM_VENDORID +# define CONFIG_CDCACM_VENDORID 0x0525 +#endif + +#ifndef CONFIG_CDCACM_PRODUCTID +# define CONFIG_CDCACM_PRODUCTID 0xa4a7 +#endif + +#ifndef CONFIG_CDCACM_VENDORSTR +# define CONFIG_CDCACM_VENDORSTR "NuttX" +#endif + +#ifndef CONFIG_CDCACM_PRODUCTSTR +# define CONFIG_CDCACM_PRODUCTSTR "CDC ACM Serial" +#endif + +#undef CONFIG_CDCACM_SERIALSTR +#define CONFIG_CDCACM_SERIALSTR "0" + +#undef CONFIG_CDCACM_CONFIGSTR +#define CONFIG_CDCACM_CONFIGSTR "Bulk" + +/* USB Controller */ + +#ifndef CONFIG_USBDEV_SELFPOWERED +# define SELFPOWERED USB_CONFIG_ATT_SELFPOWER +#else +# define SELFPOWERED (0) +#endif + +#ifndef CONFIG_USBDEV_REMOTEWAKEUP +# define REMOTEWAKEUP USB_CONFIG_ATTR_WAKEUP +#else +# define REMOTEWAKEUP (0) +#endif + +#ifndef CONFIG_USBDEV_MAXPOWER +# define CONFIG_USBDEV_MAXPOWER 100 +#endif + +/* IOCTL Commands ***********************************************************/ +/* The USB serial driver will support a subset of the TIOC IOCTL commands + * defined in include/nuttx/serial/tioctl.h. This subset includes: + * + * CAICO_REGISTERCB + * Register a callback for serial event notification. Argument: + * cdcacm_callback_t. See cdcacm_callback_t type definition below. + * NOTE: The callback will most likely invoked at the interrupt level. + * The called back function should, therefore, limit its operations to + * invoking some kind of IPC to handle the serial event in some normal + * task environment. + * CAIOC_GETLINECODING + * Get current line coding. Argument: struct cdc_linecoding_s*. + * See include/nuttx/usb/cdc.h for structure definition. This IOCTL + * should be called to get the data associated with the + * CDCACM_EVENT_LINECODING event (see devent definition below). + * CAIOC_GETCTRLLINE + * Get control line status bits. Argument FAR int*. See + * include/nuttx/usb/cdc.h for bit definitions. This IOCTL should be + * called to get the data associated CDCACM_EVENT_CTRLLINE event (see event + * definition below). + * CAIOC_NOTIFY + * Send a serial state to the host via the Interrupt IN endpoint. + * Argument: int. This includes the current state of the carrier detect, + * DSR, break, and ring signal. See "Table 69: UART State Bitmap Values" + * and CDC_UART_definitions in include/nuttx/usb/cdc.h. + */ + +#define CAIOC_REGISTERCB _CAIOC(0x0001) +#define CAIOC_GETLINECODING _CAIOC(0x0002) +#define CAIOC_GETCTRLLINE _CAIOC(0x0003) +#define CAIOC_NOTIFY _CAIOC(0x0004) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" { +#else +# define EXTERN extern +#endif + +/* Reported serial events. Data is associated with CDCACM_EVENT_LINECODING + * and CDCACM_EVENT_CTRLLINE. The data may be obtained using CDCACM IOCTL + * commands described above. + * + * CDCACM_EVENT_LINECODING - See "Table 50: Line Coding Structure" and struct + * cdc_linecoding_s in include/nuttx/usb/cdc.h. + * CDCACM_EVENT_CTRLLINE - See "Table 51: Control Signal Bitmap Values for + * SetControlLineState" and definitions in include/nutt/usb/cdc.h + * CDCACM_EVENT_SENDBREAK - See Paragraph "6.2.15 SendBreak." This request + * sends special carrier modulation that generates an RS-232 style break. + */ + +enum cdcacm_event_e +{ + CDCACM_EVENT_LINECODING = 0, /* New line coding received from host */ + CDCACM_EVENT_CTRLLINE, /* New control line status received from host */ + CDCACM_EVENT_SENDBREAK /* Send break request received */ +}; + +typedef FAR void (*cdcacm_callback_t)(enum cdcacm_event_e event); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: board_cdcclassobject + * + * Description: + * If the CDC serial class driver is part of composite device, then + * board-specific logic must provide board_cdcclassobject(). In the simplest + * case, board_cdcclassobject() is simply a wrapper around cdcacm_classobject() + * that provides the correct device minor number. + * + * Input Parameters: + * classdev - The location to return the CDC serial class' device + * instance. + * + * Returned Value: + * 0 on success; a negated errno on failure + * + ****************************************************************************/ + +#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_CDCACM_COMPOSITE) +struct usbdevclass_driver_s; +EXTERN int board_cdcclassobject(FAR struct usbdevclass_driver_s **classdev); +#endif + +/**************************************************************************** + * Name: board_cdcuninitialize + * + * Description: + * Un-initialize the USB serial class driver. This is just an application- + * specific wrapper aboutn cdcadm_unitialize() that is called form the composite + * device logic. + * + * Input Parameters: + * classdev - The class driver instrance previously give to the composite + * driver by board_cdcclassobject(). + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_CDCACM_COMPOSITE) +struct usbdevclass_driver_s; +EXTERN void board_cdcuninitialize(FAR struct usbdevclass_driver_s *classdev); +#endif + +/**************************************************************************** + * Name: cdcacm_classobject + * + * Description: + * Register USB serial port (and USB serial console if so configured) and + * return the class object. + * + * Input Parameter: + * minor - Device minor number. E.g., minor 0 would correspond to + * /dev/ttyACM0. + * classdev - The location to return the CDC serial class' device + * instance. + * + * Returned Value: + * A pointer to the allocated class object (NULL on failure). + * + ****************************************************************************/ + +#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_CDCACM_COMPOSITE) +int cdcacm_classobject(int minor, FAR struct usbdevclass_driver_s **classdev); +#endif + +/**************************************************************************** + * Name: cdcacm_initialize + * + * Description: + * Register USB serial port (and USB serial console if so configured). + * + * Input Parameter: + * minor - Device minor number. E.g., minor 0 would correspond to + * /dev/ttyACM0. + * handle - An optional opaque reference to the CDC/ACM class object that + * may subsequently be used with cdcacm_uninitialize(). + * + * Returned Value: + * Zero (OK) means that the driver was successfully registered. On any + * failure, a negated errno value is retured. + * + ****************************************************************************/ + +#if !defined(CONFIG_USBDEV_COMPOSITE) || !defined(CONFIG_CDCACM_COMPOSITE) +EXTERN int cdcacm_initialize(int minor, FAR void **handle); +#endif + +/**************************************************************************** + * Name: cdcacm_uninitialize + * + * Description: + * Un-initialize the USB storage class driver. This function is used + * internally by the USB composite driver to unitialized the CDC/ACM + * driver. This same interface is available (with an untyped input + * parameter) when the CDC/ACM driver is used standalone. + * + * Input Parameters: + * There is one parameter, it differs in typing depending upon whether the + * CDC/ACM driver is an internal part of a composite device, or a standalone + * USB driver: + * + * classdev - The class object returned by board_cdcclassobject() or + * cdcacm_classobject() + * handle - The opaque handle represetning the class object returned by + * a previous call to cdcacm_initialize(). + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_CDCACM_COMPOSITE) +EXTERN void cdcacm_uninitialize(FAR struct usbdevclass_driver_s *classdev); +#else +EXTERN void cdcacm_uninitialize(FAR void *handle); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_USB_CDCACM_H */ diff --git a/nuttx/include/nuttx/usb/composite.h b/nuttx/include/nuttx/usb/composite.h new file mode 100644 index 0000000000..98f992bf35 --- /dev/null +++ b/nuttx/include/nuttx/usb/composite.h @@ -0,0 +1,186 @@ +/************************************************************************************ + * include/nuttx/usb/composite.h + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_USB_COMPOSITE_H +#define __INCLUDE_NUTTX_USB_COMPOSITE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_USBDEV_COMPOSITE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_USBDEV_COMPOSITE + * Enables USB composite device support + * CONFIG_CDCACM_COMPOSITE + * Configure the CDC serial driver as part of a composite driver + * (only if CONFIG_USBDEV_COMPOSITE is also defined) + * CONFIG_COMPOSITE_COMPOSITE + * Configure the mass storage driver as part of a composite driver + * (only if CONFIG_USBDEV_COMPOSITE is also defined) + * CONFIG_COMPOSITE_EP0MAXPACKET + * Max packet size for endpoint 0 + * CONFIG_COMPOSITE_VENDORID and CONFIG_COMPOSITE_VENDORSTR + * The vendor ID code/string + * CONFIG_COMPOSITE_PRODUCTID and CONFIG_COMPOSITE_PRODUCTSTR + * The product ID code/string + * CONFIG_COMPOSITE_SERIALSTR + * Device serial number string + * CONFIG_COMPOSITE_CONFIGSTR + * Configuration string + * CONFIG_COMPOSITE_VERSIONNO + * Interface version number. + */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: composite_initialize + * + * Description: + * Register USB composite device as configured. This function will call + * board-specific implementations in order to obtain the class objects for + * each of the members of the composite (see board_mscclassobject(), + * board_cdcclassobjec(), ...) + * + * Input Parameter: + * None + * + * Returned Value: + * A non-NULL "handle" is returned on success. This handle may be used + * later with composite_uninitialize() in order to removed the composite + * device. This handle is the (untyped) internal representation of the + * the class driver instance. + * + * NULL is returned on any failure. + * + ****************************************************************************/ + +EXTERN FAR void *composite_initialize(void); + +/**************************************************************************** + * Name: composite_uninitialize + * + * Description: + * Un-initialize the USB composite driver. The handle is the USB composite + * class' device object as was returned by composite_initialize(). This + * function will call board-specific implementations in order to free the + * class objects for each of the members of the composite (see + * board_mscuninitialize(), board_cdcuninitialize(), ...) + * + * Input Parameters: + * handle - The handle returned by a previous call to composite_initialize(). + * + * Returned Value: + * None + * + ***************************************************************************/ + +EXTERN void composite_uninitialize(FAR void *handle); + +/**************************************************************************** + * Name: composite_initialize + * + * Description: + * Register USB composite device as configured. This function will call + * board-specific implementations in order to obtain the class objects for + * each of the members of the composite (see board_mscclassobject(), + * board_cdcclassobjec(), ...) + * + * Input Parameter: + * None + * + * Returned Value: + * A non-NULL "handle" is returned on success. This handle may be used + * later with composite_uninitialize() in order to removed the composite + * device. This handle is the (untyped) internal representation of the + * the class driver instance. + * + * NULL is returned on any failure. + * + ****************************************************************************/ + +EXTERN FAR void *composite_initialize(void); + +/**************************************************************************** + * Name: composite_ep0submit + * + * Description: + * Members of the composite cannot send on EP0 directly because EP0 is + * is "owned" by the composite device. Instead, when configured as members + * of a composite device, those classes should call this method so that + * the composite device can send on EP0 onbehalf of the class. + * + ****************************************************************************/ + +struct usbdevclass_driver_s; +struct usbdev_s; +struct usbdev_req_s; + +EXTERN int composite_ep0submit(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev, + FAR struct usbdev_req_s *ctrlreq); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* CONFIG_USBDEV_COMPOSITE */ +#endif /* __INCLUDE_NUTTX_USB_COMPOSITE_H */ diff --git a/nuttx/include/nuttx/usb/hid.h b/nuttx/include/nuttx/usb/hid.h new file mode 100644 index 0000000000..5b83f08fc8 --- /dev/null +++ b/nuttx/include/nuttx/usb/hid.h @@ -0,0 +1,693 @@ +/**************************************************************************** + * include/nuttx/usb/hid.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * HID Universal Serial Bus (USB), Device Class Definition for Human + * Interface Devices (HID), Firmware Specification—6/27/01, Version + * 1.11. + * + * HuT Universal Serial Bus (USB), HID Usage Tables, 10/28/2004, Version + * 1.12 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_USB_HID_H +#define __INCLUDE_NUTTX_USB_HID_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Preprocessor definitions + ****************************************************************************/ + +/* Subclass and Protocol ****************************************************/ +/* Subclass codes (HID 4.2) */ + +#define USBHID_SUBCLASS_NONE 0 /* No subclass */ +#define USBHID_SUBCLASS_BOOTIF 1 /* Boot Interface Subclass */ + +/* A variety of protocols are supported HID devices. The protocol member of + * an Interface descriptor only has meaning if the subclass member declares + * that the device supports a boot interface, otherwise it is 0. (HID 4.3) + */ + +#define USBHID_PROTOCOL_NONE 0 +#define USBHID_PROTOCOL_KEYBOARD 1 +#define USBHID_PROTOCOL_MOUSE 2 + +/* Descriptor Requests ******************************************************/ +/* "When a Get_Descriptor(Configuration) request is issued, it returns the + * Configuration descriptor, all Interface descriptors, all Endpoint + * descriptors, and the HID descriptor for each interface." + */ + +/* Standard Requests (HID 7.1) + * GET_DESCRIPTOR (HID 7.1.1): + * + * bmRequestType (USB_REQ_DIR_IN | USB_REQ_TYPE_STANDARD | USB_REQ_RECIPIENT_INTERFACE) + * bRequest (USB_REQ_GETDESCRIPTOR) + * wValue Descriptor Type (MS) and Descriptor Index (LS) + * wIndex Interface Number + * wLength Descriptor Length + * Data Descriptor + * + * SET_DESCRIPTOR (HID 7.1.2): + * + * bmRequestType (USB_REQ_TYPE_STANDARD | USB_REQ_RECIPIENT_INTERFACE) + * bRequest (USB_REQ_SETDESCRIPTOR) + * wValue Descriptor Type (MS) and Descriptor Index (LS) + * wIndex Interface Number + * wLength Descriptor Length + * Data Descriptor + */ + +/* Class Descriptor Types (HID 7.1) */ + +#define USBHID_DESCTYPE_HID 0x21 /* HID */ +#define USBHID_DESCTYPE_REPORT 0x22 /* Report */ +#define USBHID_DESCTYPE_PHYSICAL 0x23 /* Physical descriptor */ + +/* Class-specific requests (HID 7.2) + * + * bmRequestType ( USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE) -or- + * (USB_REQ_DIR_IN | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE) + * bRequest Class-specific request + * wValue Varies according to request + * wIndex Varies according to request + * wLength Number of bytes to transfer in the data phase + * Data Data + */ + +#define USBHID_REQUEST_GETREPORT 0x01 +#define USBHID_REQUEST_GETIDLE 0x02 +#define USBHID_REQUEST_GETPROTOCOL 0x03 +#define USBHID_REQUEST_SETREPORT 0x09 +#define USBHID_REQUEST_SETIDLE 0x0a +#define USBHID_REQUEST_SETPROTOCOL 0x0b + +/* Report Type (MS byte of wValue for GET_REPORT) (HID 7.2.1) */ + +#define USBHID_REPORTTYPE_INPUT 0x01 +#define USBHID_REPORTTYPE_OUTPUT 0x02 +#define USBHID_REPORTTYPE_FEATURE 0x03 + +/* HID Descriptor ***********************************************************/ + +#define USBHID_COUNTRY_NONE 0x00 /* Not Supported */ +#define USBHID_COUNTRY_ARABIC 0x01 /* Arabic */ +#define USBHID_COUNTRY_BELGIAN 0x02 /* Belgian */ +#define USBHID_COUNTRY_CANADA 0x03 /* Canadian-Bilingual */ +#define USBHID_COUNTRY_CANADRFR 0x04 /* Canadian-French */ +#define USBHID_COUNTRY_CZECH 0x05 /* Czech Republic */ +#define USBHID_COUNTRY_DANISH 0x06 /* Danish */ +#define USBHID_COUNTRY_FINNISH 0x07 /* Finnish */ +#define USBHID_COUNTRY_FRENCH 0x08 /* French */ +#define USBHID_COUNTRY_GERMAN 0x09 /* German */ +#define USBHID_COUNTRY_GREEK 0x10 /* Greek */ +#define USBHID_COUNTRY_HEBREW 0x11 /* Hebrew */ +#define USBHID_COUNTRY_HUNGARY 0x12 /* Hungary */ +#define USBHID_COUNTRY_ISO 0x13 /* International (ISO) */ +#define USBHID_COUNTRY_ITALIAN 0x14 /* Italian */ +#define USBHID_COUNTRY_JAPAN 0x15 /* Japan (Katakana) */ +#define USBHID_COUNTRY_KOREAN 0x16 /* Korean */ +#define USBHID_COUNTRY_LATINAM 0x17 /* Latin American */ +#define USBHID_COUNTRY_DUTCH 0x18 /* Netherlands/Dutch */ +#define USBHID_COUNTRY_NORWEGIAN 0x19 /* Norwegian */ +#define USBHID_COUNTRY_PERSIAN 0x20 /* Persian (Farsi) */ +#define USBHID_COUNTRY_POLAND 0x21 /* Poland */ +#define USBHID_COUNTRY_PORTUGUESE 0x22 /* Portuguese */ +#define USBHID_COUNTRY_RUSSIA 0x23 /* Russia */ +#define USBHID_COUNTRY_SLOVAKIA 0x24 /* Slovakia */ +#define USBHID_COUNTRY_SPANISH 0x25 /* Spanish */ +#define USBHID_COUNTRY_SWEDISH 0x26 /* Swedish */ +#define USBHID_COUNTRY_SWISSFR 0x27 /* Swiss/French */ +#define USBHID_COUNTRY_SWISSGR 0x28 /* Swiss/German */ +#define USBHID_COUNTRY_SWITZERLAND 0x29 /* Switzerland */ +#define USBHID_COUNTRY_TAIWAN 0x30 /* Taiwan */ +#define USBHID_COUNTRY_TURKISHQ 0x31 /* Turkish-Q */ +#define USBHID_COUNTRY_UK 0x32 /* UK */ +#define USBHID_COUNTRY_US 0x33 /* US */ +#define USBHID_COUNTRY_YUGOSLAVIA 0x34 /* Yugoslavia */ +#define USBHID_COUNTRY_TURKISHF 0x35 /* Turkish-F */ + +/* HID report items */ + +#define USBHID_RPTITEM_SIZE_MASK 0x03 +# define USBHID_RPTITEM_SIZE_0 0x00 /* No data follows */ +# define USBHID_RPTITEM_SIZE_1 0x01 /* 1 byte of data follows */ +# define USBHID_RPTITEM_SIZE_2 0x02 /* 2 bytes of data follow */ +# define USBHID_RPTITEM_SIZE_4 0x03 /* 4 bytes of data follow */ +#define USBHID_RPTITEM_TYPE_MASK 0x0c +# define USBHID_RPTITEM_TYPE_MAIN 0x00 +# define USBHID_RPTITEM_TYPE_GLOBAL 0x04 +# define USBHID_RPTITEM_TYPE_LOCAL 0x08 +#define USBHID_RPTITEM_TAG_MASK 0xf0 + +/* Main Items (HID 6.2.2.4) */ + +#define USBHID_MAIN_CONSTANT (1 << 0) /* Constant(1) vs Data(0) */ +#define USBHID_MAIN_VARIABLE (1 << 1) /* Variable(1) vs Array(0) */ +#define USBHID_MAIN_RELATIVE (1 << 2) /* Relative(1) vs Absolute(0) */ +#define USBHID_MAIN_WRAP (1 << 3) /* Wrap(1) vs No Wrap(0) */ +#define USBHID_MAIN_NONLINEAR (1 << 4) /* Non Linear(1) vs Linear(0) */ +#define USBHID_MAIN_NOPREFERRED (1 << 5) /* No Preferred (1) vs Preferred State(0) */ +#define USBHID_MAIN_NULLSTATE (1 << 6) /* Null state(1) vs No Null position(0) */ +#define USBHID_MAIN_VOLATILE (1 << 7) /* Volatile(1) vs Non volatile(0) */ +#define USBHID_MAIN_BUFFEREDBYTES (1 << 8) /* Buffered Bytes(1) vs Bit Field(0) */ + +#define USBHID_MAIN_SIZE(pfx) ((pfx) & USBHID_RPTITEM_SIZE_MASK) +#define USBHID_MAIN_INPUT_PREFIX 0x80 +#define USBHID_MAIN_INPUT_CONSTANT USBHID_MAIN_CONSTANT +#define USBHID_MAIN_INPUT_VARIABLE USBHID_MAIN_VARIABLE +#define USBHID_MAIN_INPUT_RELATIVE USBHID_MAIN_RELATIVE +#define USBHID_MAIN_INPUT_WRAP USBHID_MAIN_WRAP +#define USBHID_MAIN_INPUT_NONLINEAR USBHID_MAIN_NONLINEAR +#define USBHID_MAIN_INPUT_NOPREFERRED USBHID_MAIN_NOPREFERRED +#define USBHID_MAIN_INPUT_NULLSTATE USBHID_MAIN_NULLSTATE +#define USBHID_MAIN_INPUT_BUFFEREDBYTES USBHID_MAIN_BUFFEREDBYTES + +#define USBHID_MAIN_OUTPUT_PREFIX 0x90 +#define USBHID_MAIN_OUTPUT_CONSTANT USBHID_MAIN_CONSTANT +#define USBHID_MAIN_OUTPUT_VARIABLE USBHID_MAIN_VARIABLE +#define USBHID_MAIN_OUTPUT_RELATIVE USBHID_MAIN_RELATIVE +#define USBHID_MAIN_OUTPUT_WRAP USBHID_MAIN_WRAP +#define USBHID_MAIN_OUTPUT_NONLINEAR USBHID_MAIN_NONLINEAR +#define USBHID_MAIN_OUTPUT_NOPREFERRED USBHID_MAIN_NOPREFERRED +#define USBHID_MAIN_OUTPUT_NULLSTATE USBHID_MAIN_NULLSTATE +#define USBHID_MAIN_OUTPUT_VOLATILE USBHID_MAIN_VOLATILE +#define USBHID_MAIN_OUTPUT_BUFFEREDBYTES USBHID_MAIN_BUFFEREDBYTES + +#define USBHID_MAIN_FEATURE_PREFIX 0xb0 +#define USBHID_MAIN_FEATURE_CONSTANT USBHID_MAIN_CONSTANT +#define USBHID_MAIN_FEATURE_VARIABLE USBHID_MAIN_VARIABLE +#define USBHID_MAIN_FEATURE_RELATIVE USBHID_MAIN_RELATIVE +#define USBHID_MAIN_FEATURE_WRAP USBHID_MAIN_WRAP +#define USBHID_MAIN_FEATURE_NONLINEAR USBHID_MAIN_NONLINEAR +#define USBHID_MAIN_FEATURE_NOPREFERRED USBHID_MAIN_NOPREFERRED +#define USBHID_MAIN_FEATURE_NULLSTATE USBHID_MAIN_NULLSTATE +#define USBHID_MAIN_FEATURE_VOLATILE USBHID_MAIN_VOLATILE +#define USBHID_MAIN_FEATURE_BUFFEREDBYTES USBHID_MAIN_BUFFEREDBYTES + +#define USBHID_MAIN_COLLECTION_PREFIX 0xa0 +#define USBHID_MAIN_COLLECTION_PHYSICAL 0x00 /* Physical (group of axes) */ +#define USBHID_MAIN_COLLECTION_APPL 0x01 /* Application (mouse, keyboard) */ +#define USBHID_MAIN_COLLECTION_LOGICAL 0x02 /* Logical (interrelated data) */ +#define USBHID_MAIN_COLLECTION_REPORT 0x03 /* Report */ +#define USBHID_MAIN_COLLECTION_ARRAY 0x04 /* Named Array */ +#define USBHID_MAIN_COLLECTION_SWITCH 0x05 /* Usage Switch */ +#define USBHID_MAIN_COLLECTION_MODIFIER 0x06 /* Usage Modifier */ + +#define USBHID_MAIN_ENDCOLLECTION_PREFIX 0xc0 + +/* Global Items (HID 6.2.2.7) */ + +#define USBHID_GLOBAL_SIZE(pfx) ((pfx) & USBHID_RPTITEM_SIZE_MASK) +#define USBHID_GLOBAL_USAGEPAGE_PREFIX 0x04 /* Usage Page */ +#define USBHID_GLOBAL_LOGICALMIN_PREFIX 0x14 /* Logical Minimum */ +#define USBHID_GLOBAL_LOGICALMAX_PREFIX 0x24 /* Logical Maximum */ +#define USBHID_GLOBAL_PHYSICALMIN_PREFIX 0x34 /* Physical Minimum */ +#define USBHID_GLOBAL_PHYSMICALAX_PREFIX 0x44 /* Physical Maximum */ +#define USBHID_GLOBAL_UNITEXP_PREFIX 0x54 /* Unit Exponent */ +#define USBHID_GLOBAL_UNIT_PREFIX 0x64 /* Unit */ +#define USBHID_GLOBAL_REPORTSIZE_PREFIX 0x74 /* Report Size */ +#define USBHID_GLOBAL_REPORTID_PREFIX 0x84 /* Report ID */ +#define USBHID_GLOBAL_REPORTCOUNT_PREFIX 0x94 /* Report Count */ +#define USBHID_GLOBAL_PUSH_PREFIX 0xa4 /* Push */ +#define USBHID_GLOBAL_POP_PREFIX 0xb4 /* Pop */ + +/* Local Items (HID 6.2.2.8) */ + +#define USBHID_LOCAL_SIZE(pfx) ((pfx) & USBHID_RPTITEM_SIZE_MASK) +#define USBHID_LOCAL_USAGE_PREFIX 0x08 /* Usage */ +#define USBHID_LOCAL_USAGEMIN_PREFIX 0x18 /* Usage Minimum */ +#define USBHID_LOCAL_USAGEMAX_PREFIX 0x28 /* Usage Maximum */ +#define USBHID_LOCAL_DESIGNATORIDX_PREFIX 0x38 /* Designator Index */ +#define USBHID_LOCAL_DESIGNATORMIN_PREFIX 0x48 /* Designator Minimum */ +#define USBHID_LOCAL_DESIGNATORMAX_PREFIX 0x58 /* Designator Maximum */ +#define USBHID_LOCAL_STRINGIDX_PREFIX 0x78 /* String Index */ +#define USBHID_LOCAL_STRINGMIN_PREFIX 0x88 /* String Minimum */ +#define USBHID_LOCAL_STRINGMAX_PREFIX 0x98 /* xx */ +#define USBHID_LOCAL_DELIMITER_PREFIX 0xa8 /*Delimiter */ + +/* Modifier Keys (HID 8.3) */ + +#define USBHID_MODIFER_LCTRL (1 << 0) /* Left Ctrl */ +#define USBHID_MODIFER_LSHIFT (1 << 1) /* Left Shift */ +#define USBHID_MODIFER_LALT (1 << 2) /* Left Alt */ +#define USBHID_MODIFER_LGUI (1 << 3) /* Left GUI */ +#define USBHID_MODIFER_RCTRL (1 << 4) /* Right Ctrl */ +#define USBHID_MODIFER_RSHIFT (1 << 5) /* Right Shift */ +#define USBHID_MODIFER_RALT (1 << 6) /* Right Alt */ +#define USBHID_MODIFER_RGUI (1 << 7) /* Right GUI */ + +/* Keyboard output report (1 byte) (HID B.1) */ + +#define USBHID_KBDOUT_NUMLOCK (1 << 0) +#define USBHID_KBDOUT_CAPSLOCK (1 << 1) +#define USBHID_KBDOUT_SCROLLLOCK (1 << 2) +#define USBHID_KBDOUT_COMPOSE (1 << 3) +#define USBHID_KBDOUT_KANA (1 << 4) + +/* Mouse input report (HID B.2) */ + +#define USBHID_MOUSEIN_BUTTON1 (1 << 0) +#define USBHID_MOUSEIN_BUTTON2 (1 << 1) +#define USBHID_MOUSEIN_BUTTON3 (1 << 2) + +/* Joystick input report (4 bytes) (HID D.1) */ + +#define USBHID_JSIN_HATSWITCH_SHIFT (0) +#define USBHID_JSIN_HATSWITCH_MASK (15 << USBHID_JSIN_HATSWITCH_SHIFT) +#define USBHID_JSIN_BUTTON1 (1 << 4) +#define USBHID_JSIN_BUTTON2 (1 << 5) +#define USBHID_JSIN_BUTTON3 (1 << 6) +#define USBHID_JSIN_BUTTON4 (1 << 7) + +/* Usage pages (HuT 3) */ + +#define USBHID_USAGE_PAGE_UNDEFINED 0x00 /* Undefined */ +#define USBHID_USAGE_PAGE_GENERIC_DCTRL 0x01 /* Generic Desktop Controls */ +#define USBHID_USAGE_PAGE_SIMCTRL 0x02 /* Simulation Controls */ +#define USBHID_USAGE_PAGE_VRCTRL 0x03 /* VR Controls */ +#define USBHID_USAGE_PAGE_SPORTCTRL 0x04 /* Sport Controls */ +#define USBHID_USAGE_PAGE_GAMECTRL 0x05 /* Game Controls */ +#define USBHID_USAGE_PAGE_GENERIC_DEVCTRL 0x06 /* Generic Device Controls */ +#define USBHID_USAGE_PAGE_KBD 0x07 /* Keyboard/Keypad */ +#define USBHID_USAGE_PAGE_LEDS 0x08 /* LEDs */ +#define USBHID_USAGE_PAGE_BUTTON 0x09 /* Button */ +#define USBHID_USAGE_PAGE_ORDINAL 0x0a /* Ordinal */ +#define USBHID_USAGE_PAGE_TELEPHONY 0x0b /* Telephony */ +#define USBHID_USAGE_PAGE_CONSUMER 0x0c /* Consumer */ +#define USBHID_USAGE_PAGE_DIGITIZER 0x0d /* Digitizer */ + /* 0x0e Reserved */ +#define USBHID_USAGE_PAGE_PIDPAGE 0x0f /* PID Page USB Physical Interface Device */ +#define USBHID_USAGE_PAGE_UNICODE 0x10 /* Unicode */ + /* 0x11-13 Reserved */ +#define USBHID_USAGE_PAGE_ALPHA_DISPLAY 0x14 /* Alphanumeric Display */ + /* 0x15-3f Reserved */ +#define USBHID_USAGE_PAGE_MEDICAL 0x40 /* Medical Instruments */ + /* 0x41-7f Reserved */ + /* 0x80-83 Monitor Devices */ + /* 0x84-87 Power Devices */ + /* 0x88-8b Reserved */ +#define USBHID_USAGE_PAGE_BARCODE_SCANNER 0x8c /* Bar Code Scanner page */ +#define USBHID_USAGE_PAGE_SCALE 0x8d /* Scale page */ +#define USBHID_USAGE_PAGE_MSR 0x8e /* Magnetic Stripe Reading (MSR) Devices */ +#define USBHID_USAGE_PAGE_POS 0x8f /* Point of Sale devices */ +#define USBHID_USAGE_PAGE_CAMERA_CTRL 0x90 /* Camera Control Page */ + +/* Generic Desktop Page Usage IDs (HuT 4) */ + +#define USBHID_DCTRLUSE_UNDEFINED 0x00 /* Undefined */ +#define USBHID_DCTRLUSE_POINTER 0x01 /* Pointer */ +#define USBHID_DCTRLUSE_MOUSE 0x02 /* Mouse */ + /* 0x03 Reserved */ +#define USBHID_DCTRLUSE_JOYSTICK 0x04 /* Joystick */ +#define USBHID_DCTRLUSE_GAMEPAD 0x05 /* Game Pad */ +#define USBHID_DCTRLUSE_KEYBOARD 0x06 /* Keyboard */ +#define USBHID_DCTRLUSE_KEYPAD 0x07 /* Keypad */ +#define USBHID_DCTRLUSE_MULTIAXIS 0x08 /* Multi-axis Controller */ +#define USBHID_DCTRLUSE_TABLET 0x09 /* Tablet PC System Controls */ + /* 0x0a-2f Reserved */ +#define USBHID_DCTRLUSE_X 0x30 /* X */ +#define USBHID_DCTRLUSE_Y 0x31 /* Y */ +#define USBHID_DCTRLUSE_Z 0x32 /* Z */ +#define USBHID_DCTRLUSE_RX 0x33 /* Rx */ +#define USBHID_DCTRLUSE_RY 0x34 /* Ry */ +#define USBHID_DCTRLUSE_RZ 0x35 /* Rz */ +#define USBHID_DCTRLUSE_SLIDER 0x36 /* Slider */ +#define USBHID_DCTRLUSE_DIAL 0x37 /* Dial */ +#define USBHID_DCTRLUSE_WHEEL 0x38 /* Wheel */ +#define USBHID_DCTRLUSE_HATSWITCH 0x39 /* Hat switch */ +#define USBHID_DCTRLUSE_COUNTED 0x3a /* Counted Buffer */ +#define USBHID_DCTRLUSE_BYTECOUNT 0x3b /* Byte Count */ +#define USBHID_DCTRLUSE_MOTION 0x3c /* Motion Wakeup */ +#define USBHID_DCTRLUSE_START 0x3d /* Start */ +#define USBHID_DCTRLUSE_SELECT 0x3e /* Select */ + /* 0x3f Reserved */ +#define USBHID_DCTRLUSE_VX 0x40 /* Vx */ +#define USBHID_DCTRLUSE_VY 0x41 /* Vy */ +#define USBHID_DCTRLUSE_VZ 0x42 /* Vz */ +#define USBHID_DCTRLUSE_VBRX 0x43 /* Vbrx */ +#define USBHID_DCTRLUSE_VBRY 0x44 /* Vbry */ +#define USBHID_DCTRLUSE_VBRZ 0x45 /* Vbrz */ +#define USBHID_DCTRLUSE_VNO 0x46 /* Vno */ +#define USBHID_DCTRLUSE_FEATURE 0x47 /* Feature Notification */ +#define USBHID_DCTRLUSE_RESOLUTION 0x48 /* Resolution Multiplier */ + /* 0x49-7f Reserved */ +#define USBHID_DCTRLUSE_CONTROL 0x80 /* System Control */ +#define USBHID_DCTRLUSE_POWERDOWN 0x81 /* System Power Down */ +#define USBHID_DCTRLUSE_SLEEP 0x82 /* System Sleep */ +#define USBHID_DCTRLUSE_WAKEUP 0x83 /* System Wake Up */ +#define USBHID_DCTRLUSE_CONTEXT_MENU 0x84 /* System Context Menu */ +#define USBHID_DCTRLUSE_MAIN_MENU 0x85 /* System Main Menu */ +#define USBHID_DCTRLUSE_APP_MENU 0x86 /* System App Menu */ +#define USBHID_DCTRLUSE_MENU_HELP 0x87 /* System Menu Help */ +#define USBHID_DCTRLUSE_MENU_EXIT 0x88 /* System Menu Exit */ +#define USBHID_DCTRLUSE_MENU_SELECT 0x89 /* System Menu Select */ +#define USBHID_DCTRLUSE_MENU_RIGHT 0x8a /* System Menu Right */ +#define USBHID_DCTRLUSE_MENU_LEFT 0x8b /* System Menu Left */ +#define USBHID_DCTRLUSE_MENU_UP 0x8c /* System Menu Up */ +#define USBHID_DCTRLUSE_MENU_DOWN 0x8d /* System Menu Down */ +#define USBHID_DCTRLUSE_COLD_RESTART 0x8e /* System Cold Restart */ +#define USBHID_DCTRLUSE_WARM_RESTART 0x8f /* System Warm Restart */ +#define USBHID_DCTRLUSE_DPAD_UP 0x90 /* D-pad Up */ +#define USBHID_DCTRLUSE_DPAD_DOWN 0x91 /* D-pad Down */ +#define USBHID_DCTRLUSE_DPAD_RIGHT 0x92 /* D-pad Right */ +#define USBHID_DCTRLUSE_DPAD_LEFT 0x93 /* D-pad Left */ + /* 0x94-9f Reserved */ +#define USBHID_DCTRLUSE_DOCK 0xa0 /* System Dock */ +#define USBHID_DCTRLUSE_UNDOCK 0xa1 /* System Undock */ +#define USBHID_DCTRLUSE_SETUP 0xa2 /* System Setup */ +#define USBHID_DCTRLUSE_BREAK 0xa3 /* System Break */ +#define USBHID_DCTRLUSE_DEBUG_BREAK 0xa4 /* System Debugger Break */ +#define USBHID_DCTRLUSE_APP_BREAK 0xa5 /* Application Break */ +#define USBHID_DCTRLUSE_APP_DEBUG_BREAK 0xa6 /* Application Debugger Break */ +#define USBHID_DCTRLUSE_MUTE 0xa7 /* System Speaker Mute */ +#define USBHID_DCTRLUSE_HIBERNATE 0xa8 /* System Hibernate */ + /* 0xa9-af Reserved */ +#define USBHID_DCTRLUSE_DISPLAY_INVERT 0xb0 /* System Display Invert */ +#define USBHID_DCTRLUSE_DISPALY_INTERNAL 0xb1 /* System Display Internal */ +#define USBHID_DCTRLUSE_DISPLAY_EXTERNAL 0xb2 /* System Display External */ +#define USBHID_DCTRLUSE_DISPLAY_BOTH 0xb3 /* System Display Both */ +#define USBHID_DCTRLUSE_DISPLAY_DUAL 0xb4 /* System Display Dual */ +#define USBHID_DCTRLUSE_DISPLAY_TOGGLE 0xb5 /* System Display Toggle Int/Ext */ +#define USBHID_DCTRLUSE_DISPLAY_SWAP 0xb6 /* System Display Swap */ +#define USBHID_DCTRLUSE_ 0xb7 /* System Display LCD Autoscale */ + /* 0xb8-ffff Reserved */ + +/* Keyboard usage IDs (HuT 10) */ + +#define USBHID_KBDUSE_NONE 0x00 /* Reserved (no event indicated) */ +#define USBHID_KBDUSE_ERRORROLLOVER 0x01 /* Keyboard ErrorRollOver */ +#define USBHID_KBDUSE_POSTFAIL 0x02 /* Keyboard POSTFail */ +#define USBHID_KBDUSE_ERRUNDEF 0x03 /* Keyboard ErrorUndefined */ +#define USBHID_KBDUSE_A 0x04 /* Keyboard a or A (B-Z follow) */ +#define USBHID_KBDUSE_1 0x1e /* Keyboard 1 (2-9 follow) */ +#define USBHID_KBDUSE_EXCLAM 0x1e /* Keyboard 1 and ! */ +#define USBHID_KBDUSE_AT 0x1f /* Keyboard 2 and @ */ +#define USBHID_KBDUSE_POUND 0x20 /* Keyboard 3 and # */ +#define USBHID_KBDUSE_DOLLAR 0x21 /* Keyboard 4 and $ */ +#define USBHID_KBDUSE_PERCENT 0x22 /* Keyboard 5 and % */ +#define USBHID_KBDUSE_CARAT 0x23 /* Keyboard 6 and ^ */ +#define USBHID_KBDUSE_AMPERSAND 0x24 /* Keyboard 7 and & */ +#define USBHID_KBDUSE_ASTERISK 0x25 /* Keyboard 8 and * */ +#define USBHID_KBDUSE_LPAREN 0x26 /* Keyboard 9 and ( */ +#define USBHID_KBDUSE_0 0x27 /* Keyboard 0 and ) */ +#define USBHID_KBDUSE_RPAREN 0x27 /* Keyboard 0 and ) */ +#define USBHID_KBDUSE_ENTER 0x28 /* Keyboard Return (ENTER) */ +#define USBHID_KBDUSE_ESCAPE 0x29 /* Keyboard ESCAPE */ +#define USBHID_KBDUSE_DELETE 0x2a /* Keyboard DELETE (Backspace) */ +#define USBHID_KBDUSE_TAB 0x2b /* Keyboard Tab */ +#define USBHID_KBDUSE_SPACE 0x2c /* Keyboard Spacebar */ +#define USBHID_KBDUSE_HYPHEN 0x2d /* Keyboard - and (underscore) */ +#define USBHID_KBDUSE_UNDERSCORE 0x2d /* Keyboard - and (underscore) */ +#define USBHID_KBDUSE_EQUAL 0x2e /* Keyboard = and + */ +#define USBHID_KBDUSE_PLUS 0x2e /* Keyboard = and + */ +#define USBHID_KBDUSE_LBRACKET 0x2f /* Keyboard [ and { */ +#define USBHID_KBDUSE_LBRACE 0x2f /* Keyboard [ and { */ +#define USBHID_KBDUSE_RBRACKET 0x30 /* Keyboard ] and } */ +#define USBHID_KBDUSE_RBRACE 0x30 /* Keyboard ] and } */ +#define USBHID_KBDUSE_BSLASH 0x31 /* Keyboard \ and | */ +#define USBHID_KBDUSE_VERTBAR 0x31 /* Keyboard \ and | */ +#define USBHID_KBDUSE_NONUSPOUND 0x32 /* Keyboard Non-US # and ~ */ +#define USBHID_KBDUSE_TILDE 0x32 /* Keyboard Non-US # and ~ */ +#define USBHID_KBDUSE_SEMICOLON 0x33 /* Keyboard ; and : */ +#define USBHID_KBDUSE_COLON 0x33 /* Keyboard ; and : */ +#define USBHID_KBDUSE_SQUOTE 0x34 /* Keyboard ' and " */ +#define USBHID_KBDUSE_DQUOUTE 0x34 /* Keyboard ' and " */ +#define USBHID_KBDUSE_GACCENT 0x35 /* Keyboard Grave Accent and Tilde */ +#define USBHID_KBDUSE_GTILDE 0x35 /* Keyboard Grave Accent and Tilde */ +#define USBHID_KBDUSE_COMMON 0x36 /* Keyboard , and < */ +#define USBHID_KBDUSE_LT 0x36 /* Keyboard , and < */ +#define USBHID_KBDUSE_PERIOD 0x37 /* Keyboard . and > */ +#define USBHID_KBDUSE_GT 0x37 /* Keyboard . and > */ +#define USBHID_KBDUSE_DIV 0x38 /* Keyboard / and ? */ +#define USBHID_KBDUSE_QUESTION 0x38 /* Keyboard / and ? */ +#define USBHID_KBDUSE_CAPSLOCK 0x39 /* Keyboard Caps Lock */ +#define USBHID_KBDUSE_F1 0x3a /* Keyboard F1 */ +#define USBHID_KBDUSE_F2 0x3b /* Keyboard F2 */ +#define USBHID_KBDUSE_F3 0x3c /* Keyboard F3 */ +#define USBHID_KBDUSE_F4 0x3d /* Keyboard F4 */ +#define USBHID_KBDUSE_F5 0x3e /* Keyboard F5 */ +#define USBHID_KBDUSE_F6 0x3f /* Keyboard F6 */ +#define USBHID_KBDUSE_F7 0x40 /* Keyboard F7 */ +#define USBHID_KBDUSE_F8 0x41 /* Keyboard F8 */ +#define USBHID_KBDUSE_F9 0x42 /* Keyboard F9 */ +#define USBHID_KBDUSE_F10 0x43 /* Keyboard F10 */ +#define USBHID_KBDUSE_F11 0x44 /* Keyboard F11 */ +#define USBHID_KBDUSE_F12 0x45 /* Keyboard F12 */ +#define USBHID_KBDUSE_PRINTSCN 0x46 /* Keyboard PrintScreen */ +#define USBHID_KBDUSE_SCROLLLOCK 0x47 /* Keyboard Scroll Lock */ +#define USBHID_KBDUSE_PAUSE 0x48 /* Keyboard Pause */ +#define USBHID_KBDUSE_INSERT 0x49 /* Keyboard Insert */ +#define USBHID_KBDUSE_HOME 0x4a /* Keyboard Home */ +#define USBHID_KBDUSE_PAGEUP 0x4b /* Keyboard PageUp */ +#define USBHID_KBDUSE_DELFWD 0x4c /* Keyboard Delete Forward */ +#define USBHID_KBDUSE_END 0x4d /* Keyboard End */ +#define USBHID_KBDUSE_PAGEDOWN 0x4e /* Keyboard PageDown */ +#define USBHID_KBDUSE_RIGHT 0x4f /* eyboard RightArrow */ +#define USBHID_KBDUSE_LEFT 0x50 /* Keyboard LeftArrow */ +#define USBHID_KBDUSE_DOWN 0x5a /* Keyboard DownArrow */ +#define USBHID_KBDUSE_UP 0x52 /* Keyboard UpArrow */ +#define USBHID_KBDUSE_KPDNUMLOCK 0x53 /* Keypad Num Lock and Clear */ +#define USBHID_KBDUSE_KPDNUMLOCKCLEAR 0x53 /* Keypad Num Lock and Clear */ +#define USBHID_KBDUSE_KPDDIV 0x54 /* Keypad / */ +#define USBHID_KBDUSE_KPDMUL 0x55 /* Keypad * */ +#define USBHID_KBDUSE_KPDHMINUS 0x56 /* Keypad - */ +#define USBHID_KBDUSE_KPDPLUS 0x57 /* Keypad + */ +#define USBHID_KBDUSE_KPDEMTER 0x58 /* Keypad ENTER */ +#define USBHID_KBDUSE_KPD1 0x59 /* Keypad 1 (2-9 follow) */ +#define USBHID_KBDUSE_KPDEND 0x59 /* Keypad 1 and End */ +#define USBHID_KBDUSE_KPDDOWN 0x5a /* Keypad 2 and Down Arrow */ +#define USBHID_KBDUSE_KPDPAGEDN 0x5b /* Keypad 3 and PageDn */ +#define USBHID_KBDUSE_KPDLEFT 0x5c /* Keypad 4 and Left Arrow */ +#define USBHID_KBDUSE_KPDRIGHT 0x5e /* Keypad 6 and Right Arrow */ +#define USBHID_KBDUSE_KPDHOME 0x5f /* Keypad 7 and Home */ +#define USBHID_KBDUSE_KPDUP 0x60 /* Keypad 8 and Up Arrow */ +#define USBHID_KBDUSE_KPDPAGEUP 0x61 /* Keypad 9 and PageUp */ +#define USBHID_KBDUSE_KPD0 0x62 /* Keypad 0 and Insert */ +#define USBHID_KBDUSE_KPDINSERT 0x62 /* Keypad 0 and Insert */ +#define USBHID_KBDUSE_KPDDECIMALPT 0x63 /* Keypad . and Delete */ +#define USBHID_KBDUSE_KPDDELETE 0x63 /* Keypad . and Delete */ +#define USBHID_KBDUSE_NONUSBSLASH 0x64 /* Keyboard Non-US \ and | */ +#define USBHID_KBDUSE_NONUSVERT 0x64 /* Keyboard Non-US \ and | */ +#define USBHID_KBDUSE_APPLICATION 0x65 /* Keyboard Application */ +#define USBHID_KBDUSE_POWER 0x66 /* Keyboard Power */ +#define USBHID_KBDUSE_KPDEQUAL 0x67 /* Keypad = */ +#define USBHID_KBDUSE_F13 0x68 /* Keyboard F13 */ +#define USBHID_KBDUSE_F14 0x69 /* Keyboard F14 */ +#define USBHID_KBDUSE_F15 0x6a /* Keyboard F15 */ +#define USBHID_KBDUSE_F16 0x6b /* Keyboard F16 */ +#define USBHID_KBDUSE_F17 0x6c /* Keyboard F17 */ +#define USBHID_KBDUSE_F18 0x6d /* Keyboard F18 */ +#define USBHID_KBDUSE_F19 0x6e /* Keyboard F19 */ +#define USBHID_KBDUSE_F20 0x6f /* Keyboard F20 */ +#define USBHID_KBDUSE_F21 0x70 /* Keyboard F21 */ +#define USBHID_KBDUSE_F22 0x71 /* Keyboard F22 */ +#define USBHID_KBDUSE_F23 0x72 /* Keyboard F23 */ +#define USBHID_KBDUSE_F24 0x73 /* Keyboard F24 */ +#define USBHID_KBDUSE_EXECUTE 0x74 /* Keyboard Execute */ +#define USBHID_KBDUSE_HELP 0x75 /* Keyboard Help */ +#define USBHID_KBDUSE_MENU 0x76 /* Keyboard Menu */ +#define USBHID_KBDUSE_SELECT 0x77 /* Keyboard Select */ +#define USBHID_KBDUSE_STOP 0x78 /* Keyboard Stop */ +#define USBHID_KBDUSE_AGAIN 0x79 /* Keyboard Again */ +#define USBHID_KBDUSE_UNDO 0x7a /* Keyboard Undo */ +#define USBHID_KBDUSE_CUT 0x7b /* Keyboard Cut */ +#define USBHID_KBDUSE_COPY 0x7c /* Keyboard Copy */ +#define USBHID_KBDUSE_PASTE 0x7d /* Keyboard Paste */ +#define USBHID_KBDUSE_FIND 0x7e /* Keyboard Find */ +#define USBHID_KBDUSE_MUTE 0x7f /* Keyboard Mute */ +#define USBHID_KBDUSE_VOLUP 0x80 /* Keyboard Volume Up */ +#define USBHID_KBDUSE_VOLDOWN 0x81 /* Keyboard Volume Down */ +#define USBHID_KBDUSE_LCAPSLOCK 0x82 /* Keyboard Locking Caps Lock */ +#define USBHID_KBDUSE_LNUMLOCK 0x83 /* Keyboard Locking Num Lock */ +#define USBHID_KBDUSE_LSCROLLLOCK 0x84 /* Keyboard Locking Scroll Lock */ +#define USBHID_KBDUSE_KPDCOMMA 0x85 /* Keypad Comma */ +#define USBHID_KBDUSE_KPDEQUALSIGN 0x86 /* Keypad Equal Sign */ +#define USBHID_KBDUSE_INTERNATIONAL1 0x87 /* Keyboard International 1 */ +#define USBHID_KBDUSE_INTERNATIONAL2 0x88 /* Keyboard International 2 */ +#define USBHID_KBDUSE_INTERNATIONAL3 0x89 /* Keyboard International 3 */ +#define USBHID_KBDUSE_INTERNATIONAL4 0x8a /* Keyboard International 4 */ +#define USBHID_KBDUSE_INTERNATIONAL5 0x8b /* Keyboard International 5 */ +#define USBHID_KBDUSE_INTERNATIONAL6 0x8c /* Keyboard International 6 */ +#define USBHID_KBDUSE_INTERNATIONAL7 0x8d /* Keyboard International 7 */ +#define USBHID_KBDUSE_INTERNATIONAL8 0x8e /* Keyboard International 8 */ +#define USBHID_KBDUSE_INTERNATIONAL9 0x8f /* Keyboard International 9 */ +#define USBHID_KBDUSE_LANG1 0x90 /* Keyboard LANG1 */ +#define USBHID_KBDUSE_LANG2 0x91 /* Keyboard LANG2 */ +#define USBHID_KBDUSE_LANG3 0x92 /* Keyboard LANG3 */ +#define USBHID_KBDUSE_LANG4 0x93 /* Keyboard LANG4 */ +#define USBHID_KBDUSE_LANG5 0x94 /* Keyboard LANG5 */ +#define USBHID_KBDUSE_LANG6 0x95 /* Keyboard LANG6 */ +#define USBHID_KBDUSE_LANG7 0x96 /* Keyboard LANG7 */ +#define USBHID_KBDUSE_LANG8 0x97 /* Keyboard LANG8 */ +#define USBHID_KBDUSE_LANG9 0x98 /* Keyboard LANG9 */ +#define USBHID_KBDUSE_ALTERASE 0x99 /* Keyboard Alternate Erase */ +#define USBHID_KBDUSE_SYSREQ 0x9a /* Keyboard SysReq/Attention */ +#define USBHID_KBDUSE_CANCEL 0x9b /* Keyboard Cancel */ +#define USBHID_KBDUSE_CLEAR 0x9c /* Keyboard Clear */ +#define USBHID_KBDUSE_PRIOR 0x9d /* Keyboard Prior */ +#define USBHID_KBDUSE_RETURN 0x9e /* Keyboard Return */ +#define USBHID_KBDUSE_SEPARATOR 0x9f /* Keyboard Separator */ +#define USBHID_KBDUSE_OUT 0xa0 /* Keyboard Out */ +#define USBHID_KBDUSE_OPER 0xa1 /* Keyboard Oper */ +#define USBHID_KBDUSE_CLEARAGAIN 0xa2 /* Keyboard Clear/Again */ +#define USBHID_KBDUSE_CLRSEL 0xa3 /* Keyboard CrSel/Props */ +#define USBHID_KBDUSE_EXSEL 0xa4 /* Keyboard ExSel */ +#define USBHID_KBDUSE_KPD00 0xb0 /* Keypad 00 */ +#define USBHID_KBDUSE_KPD000 0xb1 /* Keypad 000 */ +#define USBHID_KBDUSE_THOUSEPARATOR 0xb2 /* Thousands Separator */ +#define USBHID_KBDUSE_DECSEPARATOR 0xb3 /* Decimal Separator */ +#define USBHID_KBDUSE_CURRUNIT 0xb4 /* Currency Unit */ +#define USBHID_KBDUSE_CURRSUBUNIT 0xb5 /* Currency Sub-unit */ +#define USBHID_KBDUSE_KPDLPAREN 0xb6 /* Keypad ( */ +#define USBHID_KBDUSE_KPDRPAREN 0xb7 /* Keypad ) */ +#define USBHID_KBDUSE_KPDLBRACE 0xb8 /* Keypad { */ +#define USBHID_KBDUSE_KPDRBRACE 0xb9 /* Keypad } */ +#define USBHID_KBDUSE_KPDTAB 0xba /* Keypad Tab */ +#define USBHID_KBDUSE_KPDBACKSPACE 0xbb /* Keypad Backspace */ +#define USBHID_KBDUSE_KPDA 0xbc /* Keypad A (B-F follow) */ +#define USBHID_KBDUSE_KPDXOR 0xc2 /* Keypad XOR */ +#define USBHID_KBDUSE_KPDEXP 0xc3 /* Keypad ^ */ +#define USBHID_KBDUSE_KPDPERCENT 0xc4 /* Keypad % */ +#define USBHID_KBDUSE_KPDLT 0xc5 /* Keypad < */ +#define USBHID_KBDUSE_KPDGT 0xc6 /* Keypad > */ +#define USBHID_KBDUSE_KPDAMPERSAND 0xc7 /* Keypad & */ +#define USBHID_KBDUSE_KPDAND 0xc8 /* Keypad && */ +#define USBHID_KBDUSE_KPDVERT 0xc9 /* Keypad | */ +#define USBHID_KBDUSE_KPDOR 0xca /* Keypad || */ +#define USBHID_KBDUSE_KPDCOLON 0xcb /* Keypad : */ +#define USBHID_KBDUSE_KPDPOUND 0xcc /* Keypad # */ +#define USBHID_KBDUSE_KPDSPACE 0xcd /* Keypad Space */ +#define USBHID_KBDUSE_KPDAT 0xce /* Keypad @ */ +#define USBHID_KBDUSE_KPDEXCLAM 0xcf /* Keypad ! */ +#define USBHID_KBDUSE_KPDMEMSTORE 0xd0 /* Keypad Memory Store */ +#define USBHID_KBDUSE_KPDMEMRECALL 0xd1 /* Keypad Memory Recall */ +#define USBHID_KBDUSE_KPDMEMCLEAR 0xd2 /* Keypad Memory Clear */ +#define USBHID_KBDUSE_KPDMEMADD 0xd3 /* Keypad Memory Add */ +#define USBHID_KBDUSE_KPDMEMSUB 0xd4 /* Keypad Memory Subtract */ +#define USBHID_KBDUSE_KPDMEMMULT 0xd5 /* Keypad Memory Multiply */ +#define USBHID_KBDUSE_KPDMEMDIV 0xd6 /* Keypad Memory Divide */ +#define USBHID_KBDUSE_KPDPLUSMINUS 0xd7 /* Keypad +/- */ +#define USBHID_KBDUSE_KPDCLEAR 0xd8 /* Keypad Clear */ +#define USBHID_KBDUSE_KPDCLEARENTRY 0xd9 /* Keypad Clear Entry */ +#define USBHID_KBDUSE_KPDBINARY 0xda /* Keypad Binary */ +#define USBHID_KBDUSE_KPDOCTAL 0xdb /* Keypad Octal */ +#define USBHID_KBDUSE_KPDDECIMAL 0xdc /* Keypad Decimal */ +#define USBHID_KBDUSE_KPDHEXADECIMAL 0xdd /* Keypad Hexadecimal */ +#define USBHID_KBDUSE_LCTRL 0xe0 /* Keyboard LeftControl */ +#define USBHID_KBDUSE_LSHIFT 0xe1 /* Keyboard LeftShift */ +#define USBHID_KBDUSE_LALT 0xe2 /* Keyboard LeftAlt */ +#define USBHID_KBDUSE_LGUI 0xe3 /* Keyboard Left GUI */ +#define USBHID_KBDUSE_RCTRL 0xe4 /* Keyboard RightControl */ +#define USBHID_KBDUSE_RSHIFT 0xe5 /* Keyboard RightShift */ +#define USBHID_KBDUSE_RALT 0xe6 /* Keyboard RightAlt */ +#define USBHID_KBDUSE_RGUI 0xe7 /* Keyboard Right GUI*/ + +#define USBHID_KBDUSE_MAX 0xe7 + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* HID Descriptor (HID 6.2.1) ***********************************************/ + +struct usbhid_descriptor_s +{ + uint8_t len; /* Size of the HID descriptor */ + uint8_t type; /* HID descriptor type */ + uint8_t hid[2]; /* HID class specification release */ + uint8_t country; /* Country code */ + uint8_t ndesc; /* Number of descriptors (>=1) */ + uint8_t classdesc; /* Class descriptor type (See 7.1) */ + uint8_t desclen[2]; /* Size of the report descriptor */ + uint8_t optdesc; /* Type of optional descriptor */ + uint8_t optlen[2]; /* Size of the optional descriptor */ +}; + +/* Standard Reports *********************************************************/ +/* Keyboard input report (8 bytes) (HID B.1) */ + +struct usbhid_kbdreport_s +{ + uint8_t modifier; /* Modifier keys. See USBHID_MODIFIER_* definitions */ + uint8_t reserved; + uint8_t key[6]; /* Keycode 1-6 */ +}; + +/* Keyboard output report (1 byte) (HID B.1), see USBHID_KBDOUT_* definitions */ + +/* Mouse input report (HID B.2) */ + +struct usbhid_mousereport_s +{ + uint8_t buttons; /* See USBHID_MOUSEIN_* definitions */ + uint8_t xdisp; /* X displacement */ + uint8_t ydisp; /* y displacement */ + /* Device specific additional bytes may follow */ +}; + +/* Joystick input report (1 bytes) (HID D.1) */ + +struct usbhid_jsreport_s +{ + uint8_t xpos; /* X position */ + uint8_t ypos; /* X position */ + uint8_t buttons; /* See USBHID_JSIN_* definitions */ + uint8_t throttle; /* Throttle */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" { +#else +# define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_USB_HID_H */ diff --git a/nuttx/include/nuttx/usb/hid_parser.h b/nuttx/include/nuttx/usb/hid_parser.h new file mode 100644 index 0000000000..07e1e57657 --- /dev/null +++ b/nuttx/include/nuttx/usb/hid_parser.h @@ -0,0 +1,350 @@ +/**************************************************************************** + * include/nuttx/usb/hid_parser.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * + * Adapted from the LUFA Library: + * + * Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + * dean [at] fourwalledcubicle [dot] com, www.lufa-lib.org + * + * Permission to use, copy, modify, distribute, and sell this + * software and its documentation for any purpose is hereby granted + * without fee, provided that the above copyright notice appear in + * all copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_USB_HID_PARSER_H +#define __INCLUDE_NUTTX_USB_HID_PARSER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* CONFIG_HID_STATEDEPTH + * Constant indicating the maximum stack depth of the state table. A larger + * state table allows for more PUSH/POP report items to be nested, but + * consumes more memory. By default this is set to 2 levels (allowing non- + * nested PUSH items) but this can be overridden by defining + * CONFIG_HID_STATEDEPTH in the Nuttx config file. + * + * CONFIG_HID_USAGEDEPTH + * Constant indicating the maximum stack depth of the usage table. A larger + * usage table allows for more USAGE items to be indicated sequentially for + * REPORT COUNT entries of more than one, but requires more stack space. By + * default this is set to 8 levels (allowing for a report item with a count + * of 8) but this can be overridden by defining CONFIG_HID_USAGEDEPTH to + * in the Nuttx config file. + * + * CONFIG_HID_MAXCOLLECTIONS + * Constant indicating the maximum number of COLLECTION items (nested or + * unnested) that can be processed in the report item descriptor. A large + * value allows for more COLLECTION items to be processed, but consumes + * more memory. By default this is set to 10 collections, but this can be + * overridden by defining CONFIG_HID_MAXCOLLECTIONS in the Nuttx config file. + * + * CONFIG_HID_MAXITEMS + * Constant indicating the maximum number of report items (IN, OUT or + * FEATURE) that can be processed in the report item descriptor and stored + * in the user HID Report Info structure. A large value allows + * for more report items to be stored, but consumes more memory. By default + * this is set to 20 items, but this can be overridden by defining + * CONFIG_HID_MAXITEMS in the Nuttx config file. + * + * CONFIG_HID_MAXIDS + * Constant indicating the maximum number of unique report IDs that can be + * processed in the report item descriptor for the report size information + * array in the user HID Report Info structure. A large value allows for + * more report ID report sizes to be stored, but consumes more memory. By + * default this is set to 10 items, but this can be overridden by defining + * CONFIG_HID_MAXIDS in the Nuttx config file. Note that IN, OUT and FEATURE + * items sharing the same report ID consume only one size item in the array. + */ + +#ifndef CONFIG_HID_STATEDEPTH +# define CONFIG_HID_STATEDEPTH 2 +#endif + +#ifndef CONFIG_HID_USAGEDEPTH +# define CONFIG_HID_USAGEDEPTH 8 +#endif + +#ifndef CONFIG_HID_MAXCOLLECTIONS +# define CONFIG_HID_MAXCOLLECTIONS 10 +#endif + +#ifndef CONFIG_HID_MAXITEMS +# define CONFIG_HID_MAXITEMS 20 +#endif + +#ifndef CONFIG_HID_MAXIDS +# define CONFIG_HID_MAXIDS 10 +#endif + +/* HID report type indices */ + +#define HID_REPORT_ITEM_IN 0 +#define HID_REPORT_ITEM_OUT 1 +#define HID_REPORT_ITEM_FEATURE 2 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* HID Parser Report Item Min/Max Structure. Type define for an attribute + * with both minimum and maximum values (e.g. Logical Min/Max). + */ + +struct hid_range_s +{ + uint32_t min; /* Minimum value for the attribute */ + uint32_t max; /* Maximum value for the attribute */ +}; + +/* HID Parser Report Item Unit Structure. Type define for the Unit attributes + * of a report item. + */ + +struct hid_unit_t +{ + uint32_t type; /* Unit type (refer to HID spec for details) */ + uint8_t exponent; /* Unit exponent (refer to HID spec for details) */ +}; + +/* HID Parser Report Item Usage Structure. Type define for the Usage + * attributes of a report item. + */ + +struct hid_usage_t +{ + uint16_t page; /* Usage page of the report item */ + uint16_t usage; /* Usage of the report item */ +}; + +/* HID Parser Report Item Collection Path Structure. Type define for a + * COLLECTION object. Contains the collection attributes and a reference to + * the parent collection if any. + */ + +struct hid_collectionpath_s +{ + uint8_t type; /* Collection type (e.g. "Generic Desktop") */ + struct hid_usage_t usage; /* Collection usage */ + struct hid_collectionpath_s *parent; /* Reference to parent collection (NULL if root) */ +}; + +/* HID Parser Report Item Attributes Structure. Type define for all the data + * attributes of a report item, except flags. + */ + +struct hid_rptitem_attributes_s +{ + uint8_t bitsize; /* Size in bits of the report item's data */ + struct hid_usage_t usage; /* Usage of the report item */ + struct hid_unit_t unit; /* Unit type and exponent of the report item */ + struct hid_range_s logical; /* Logical minimum and maximum of the report item */ + struct hid_range_s physical; /* Physical minimum and maximum of the report item */ +}; + +/* HID Parser Report Item Details Structure. Type define for a report item + * (IN, OUT or FEATURE) layout attributes and other details. + */ + +struct hid_rptitem_s +{ + uint16_t bitoffset; /* Bit offset in IN, OUT or FEATURE report of the item */ + uint8_t type; /* Report item type */ + uint16_t flags; /* Item data flags */ + uint8_t id; /* Report ID this item belongs to (0 if only one report) */ + struct hid_collectionpath_s *collectionpath; /* Collection path of the item */ + struct hid_rptitem_attributes_s attrib; /* Report item attributes */ + uint32_t value; /* Current value of the report item */ + uint32_t previous; /* Previous value of the report item */ +}; + +/* HID Parser Report Size Structure. Type define for a report item size + * information structure, to retain the size of a device's reports by ID. + */ + +struct hid_rptsizeinfo_s +{ + uint8_t id; /* Report ID of the report within the HID interface */ + uint16_t size[3]; /* Number of bits in report type for the Report ID */ +}; + +/* HID Parser State Structure. Type define for a complete processed HID + * report, including all report item data and collections. + */ + +struct hid_rptinfo_s +{ + /* nitems is the number of report items stored in the report items array (rptitems[]). */ + + uint8_t nitems; + struct hid_rptitem_s items[CONFIG_HID_MAXITEMS]; + + /* All collection items, referenced by the report items. */ + + struct hid_collectionpath_s collectionpaths[CONFIG_HID_MAXCOLLECTIONS]; + + uint8_t nreports; /* Number of reports within the HID interface */ + struct hid_rptsizeinfo_s rptsize[CONFIG_HID_MAXIDS]; /* Report sizes for each report in the interface */ + uint16_t maxrptsize; /* Largest report that the attached device will generate, in bits */ + bool haverptid; /* Device has at least one REPORT ID in its HID report */ +}; + +/* Callback routine for the HID Report Parser. This callback must be + * implemented by the user code when the parser is used, to determine what + * report IN, OUT and FEATURE item's information is stored into the user + * struct hid_rptinfo_s structure. This can be used to filter only those + * items the application will be using, so that no RAM is wasted storing + * the attributes for report items which will never be referenced by the + * application. + * + * Input Parameters: + * item Pointer to the current report item for user checking. + * + * Returned value: + * Boolean true if the item should be stored into the struct hid_rptinfo_s + * structure, false if it should be ignored. + */ + +typedef bool (*hid_rptfilter_t)(FAR struct hid_rptitem_s *item); + +/**************************************************************************** + * Public Function Protoypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" { +#else +# define EXTERN extern +#endif + +/**************************************************************************** + * Name: hid_parsereport + * + * Description: + * Function to process a given HID report returned from an attached device, + * and store it into a given struct hid_rptinfo_s structure. + * + * Input Parameters: + * report Buffer containing the device's HID report table. + * rptlen Size in bytes of the HID report table. + * filter Callback function to decide if an item should be retained + * rptinfo Pointer to a struct hid_rptinfo_s instance for the parser output. + * + * Returned Value: + * Zero on success, otherwise a negated errno value. + ****************************************************************************/ + +EXTERN int hid_parsereport(FAR const uint8_t *report, int rptlen, + hid_rptfilter_t filter, + FAR struct hid_rptinfo_s *rptinfo); + +/**************************************************************************** + * Name: hid_getitem + * + * Description: + * Extracts the given report item's value out of the given HID report and + * places it into the value member of the report item's struct hid_rptitem_s + * structure. + * + * When called on a report with an item that exists in that report, this + * copies the report item's Value to it's previous element for easy + * checking to see if an item's value has changed before processing a + * report. If the given item does not exist in the report, the function + * does not modify the report item's data. + * + * Input Parameters + * report Buffer containing an IN or FEATURE report from an attached + * device. + * item Pointer to the report item of interest in a struct hid_rptinfo_s + * item array. + * + * Returned Value: + * Zero on success, otherwise a negated errno value. + * + ****************************************************************************/ + +EXTERN int hid_getitem(FAR const uint8_t *report, FAR struct hid_rptitem_s *item); + +/**************************************************************************** + * Name: hid_putitem + * + * Desription: + * Retrieves the given report item's value out of the value member of the + * report item's struct hid_rptitem_s structure and places it into the correct + * position in the HID report buffer. The report buffer is assumed to have + * the appropriate bits cleared before calling this function (i.e., the + * buffer should be explicitly cleared before report values are added). + * + * When called, this copies the report item's Value element to it's + * previous element for easy checking to see if an item's value has + * changed before sending a report. + * + * If the device has multiple HID reports, the first byte in the report is + * set to the report ID of the given item. + * + * Input Parameters: + * report Buffer holding the current OUT or FEATURE report data. + * item Pointer to the report item of interest in a struct hid_rptinfo_s + * item array. + * + ****************************************************************************/ + +#if 0 /* Not needed by host */ +EXTERN void hid_putitem(FAR uint8_t *report, FAR struct hid_rptitem_s *item); +#endif + +/**************************************************************************** + * Name: hid_reportsize + * + * Description: + * Retrieves the size of a given HID report in bytes from it's Report ID. + * + * InputParameters: + * rptinfo Pointer to a struct hid_rptinfo_s instance containing the parser output. + * id Report ID of the report whose size is to be retrieved. + * rpttype Type of the report whose size is to be determined, a valued from the + * HID_ReportItemTypes_t enum. + * + * Size of the report in bytes, or 0 if the report does not exist. + * + ****************************************************************************/ + +EXTERN size_t hid_reportsize(FAR struct hid_rptinfo_s *rptinfo, + uint8_t id, uint8_t rpttype); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + + +#endif /* __INCLUDE_NUTTX_USB_HID_PARSER_H */ diff --git a/nuttx/include/nuttx/usb/ohci.h b/nuttx/include/nuttx/usb/ohci.h new file mode 100644 index 0000000000..c5f15246b9 --- /dev/null +++ b/nuttx/include/nuttx/usb/ohci.h @@ -0,0 +1,459 @@ +/**************************************************************************** + * include/nuttx/usb/ohci.h + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: "OpenHCI Open Host Controller Interface Specification + * for USB," Release 1.0a, Compaq, Microsoft, National Semiconductor, + * September 14, 1999. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_USB_OHCI_H +#define __INCLUDE_NUTTX_USB_OHCI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register offsets *********************************************************/ +/* Control and status registers (section 7.1) */ + +#define OHCI_HCIREV_OFFSET 0x0000 /* HcRevision: Version of HCI specification */ +#define OHCI_CTRL_OFFSET 0x0004 /* HcControl: HC control */ +#define OHCI_CMDST_OFFSET 0x0008 /* HcCommandStatus: HC command status */ +#define OHCI_INTST_OFFSET 0x000c /* HcInterruptStatus: HC interrupt status */ +#define OHCI_INTEN_OFFSET 0x0010 /* HcInterruptEnable: HC interrupt enable */ +#define OHCI_INTDIS_OFFSET 0x0014 /* HcInterruptDisable: HC interrupt disable */ + +/* Memory pointer registers (section 7.2) */ + +#define OHCI_HCCA_OFFSET 0x0018 /* HcHCCA: HC communication area */ +#define OHCI_PERED_OFFSET 0x001c /* HcPeriodCurrentED: Current isoc or int endpoint desc */ +#define OHCI_CTRLHEADED_OFFSET 0x0020 /* HcControlHeadED: First EP desc in the control list */ +#define OHCI_CTRLED_OFFSET 0x0024 /* HcControlCurrentED: Current EP desc in the control list */ +#define OHCI_BULKHEADED_OFFSET 0x0028 /* HcBulkHeadED: First EP desc in the bulk list */ +#define OHCI_BULKED_OFFSET 0x002c /* HcBulkCurrentED: Current EP desc in the bulk list */ +#define OHCI_DONEHEAD_OFFSET 0x0030 /* HcDoneHead: Last transfer desc added to DONE queue */ + +/* Frame counter registers (section 7.3) */ + +#define OHCI_FMINT_OFFSET 0x0034 /* HcFmInterval: Bit time interval that would not cause overrun */ +#define OHCI_FMREM_OFFSET 0x0038 /* HcFmRemaining: Bit time remaining in current frame */ +#define OHCI_FMNO_OFFSET 0x003c /* HcFmNumber: Frame number counter */ +#define OHCI_PERSTART_OFFSET 0x0040 /* HcPeriodicStart: Time to start processing periodic list */ + +/* Root hub registers (section 7.4) */ + +#define OHCI_LSTHRES_OFFSET 0x0044 /* HcLSThreshold: Commit to transfer threshold */ +#define OHCI_RHDESCA_OFFSET 0x0048 /* HcRhDescriptorA: Describes root hub (part A) */ +#define OHCI_RHDESCB_OFFSET 0x004c /* HcRhDescriptorB: Describes root hub (part B) */ +#define OHCI_RHSTATUS_OFFSET 0x0050 /* HcRhStatus: Root hub status */ + +#define OHCI_MAX_RHPORT 15 /* Maximum number of OHCI root hub ports */ + +#define OHCI_RHPORTST_OFFSET(n) (0x0054+(((n)-1) << 2)) +#define OHCI_RHPORTST1_OFFSET 0x0054 /* HcRhPort1Status: Root hub port status 1 */ +#define OHCI_RHPORTST2_OFFSET 0x0058 /* HcRhPort2Status: Root hub port status 2 */ +#define OHCI_RHPORTST3_OFFSET 0x005c /* HcRhPort3Status: Root hub port status 3 */ +#define OHCI_RHPORTST4_OFFSET 0x0060 /* HcRhPort4Status: Root hub port status 4 */ +#define OHCI_RHPORTST5_OFFSET 0x0064 /* HcRhPort5Status: Root hub port status 5 */ +#define OHCI_RHPORTST6_OFFSET 0x0068 /* HcRhPort6Status: Root hub port status 6 */ +#define OHCI_RHPORTST7_OFFSET 0x006c /* HcRhPort7Status: Root hub port status 7 */ +#define OHCI_RHPORTST8_OFFSET 0x0070 /* HcRhPort8Status: Root hub port status 8 */ +#define OHCI_RHPORTST9_OFFSET 0x0074 /* HcRhPort9Status: Root hub port status 9 */ +#define OHCI_RHPORTST10_OFFSET 0x0078 /* HcRhPort10Status: Root hub port status 10 */ +#define OHCI_RHPORTST11_OFFSET 0x007c /* HcRhPort11Status: Root hub port status 11 */ +#define OHCI_RHPORTST12_OFFSET 0x0080 /* HcRhPort12Status: Root hub port status 12 */ +#define OHCI_RHPORTST13_OFFSET 0x0084 /* HcRhPort13Status: Root hub port status 13 */ +#define OHCI_RHPORTST14_OFFSET 0x0088 /* HcRhPort14Status: Root hub port status 14 */ +#define OHCI_RHPORTST15_OFFSET 0x008c /* HcRhPort15Status: Root hub port status 15 */ + +/* Register bit definitions *************************************************/ + +/* HcRevision: Version of HCI specification (7.1.1) */ + +#define OHCI_HCIREV_SHIFT (0) /* Bits 0-7: HCI spec version (BCD) */ +#define OHCI_HCIREV_MASK (0xff << OHCI_HCIREV_SHIFT) + +/* HcControl: HC control (7.1.2) */ + +#define OHCI_CTRL_CBSR (3 << 0) /* Bit 0: Control/bulk service ratio */ +#define OHCI_CTRL_PLE (1 << 2) /* Bit 1: Periodic list enable */ +#define OHCI_CTRL_IE (1 << 3) /* Bit 2: Isochronous enable */ +#define OHCI_CTRL_CLE (1 << 4) /* Bit 3: Control list enable */ +#define OHCI_CTRL_BLE (1 << 5) /* Bit 4: Bulk list enable */ +#define OHCI_CTRL_HCFS_SHIFT (6) /* Bits 6-7: Host controller functional state */ +#define OHCI_CTRL_HCFS_MASK (3 << OHCI_CTRL_HCFS_SHIFT) +# define OHCI_CTRL_HCFS_RESET (0 << OHCI_CTRL_HCFS_SHIFT) +# define OHCI_CTRL_HCFS_RESUME (1 << OHCI_CTRL_HCFS_SHIFT) +# define OHCI_CTRL_HCFS_OPER (2 << OHCI_CTRL_HCFS_SHIFT) +# define OHCI_CTRL_HCFS_SUSPEND (3 << OHCI_CTRL_HCFS_SHIFT) +#define OHCI_CTRL_IR (1 << 8) /* Bit 8: Interrupt routing */ +#define OHCI_CTRL_RWC (1 << 9) /* Bit 9: Remote wakeup connected */ +#define OHCI_CTRL_RWE (1 << 10) /* Bit 10: Remote wakeup enable */ + /* Bits 11-31: Reserved */ + +/* HcCommandStatus: HC command status (7.1.3) */ + +#define OHCI_CMDST_HCR (1 << 0) /* Bit 0: Host controller reset */ +#define OHCI_CMDST_CLF (1 << 1) /* Bit 1: Control list filled */ +#define OHCI_CMDST_BLF (1 << 2) /* Bit 2: Bulk list filled */ +#define OHCI_CMDST_OCR (1 << 3) /* Bit 3: Ownership change request */ + /* Bits 4-15: Reserved */ +#define OHCI_CMDST_SOC (3 << 16) /* Bit 16: Scheduling overrun count */ + /* Bits 17-31: Reserved */ + +/* HcInterruptStatus: HC interrupt status (7.1.4), + * HcInterruptEnable: HC interrupt enable (7.1.5), and + * HcInterruptDisable: HC interrupt disable (7.1.6) + */ + +#define OHCI_INT_SO (1 << 0) /* Bit 0: Scheduling overrun */ +#define OHCI_INT_WDH (1 << 1) /* Bit 1: Writeback done head */ +#define OHCI_INT_SF (1 << 2) /* Bit 2: Start of frame */ +#define OHCI_INT_RD (1 << 3) /* Bit 3: Resume detected */ +#define OHCI_INT_UE (1 << 4) /* Bit 4: Unrecoverable error */ +#define OHCI_INT_FNO (1 << 5) /* Bit 5: Frame number overflow */ +#define OHCI_INT_RHSC (1 << 6) /* Bit 6: Root hub status change */ + /* Bits 7-29: Reserved */ +#define OHCI_INT_OC (1 << 30) /* Bit 30: Ownership change */ +#define OHCI_INT_MIE (1 << 31) /* Bit 31: Master interrupt enable + * (Enable/disable only) */ +/* HcHCCA: HC communication area (7.2.1): + * + * 32-bits aligned to 256 byte boundary. + */ + +/* HcPeriodCurrentED: Current isoc or int endpoint desc (7.2.2), + * HcControlHeadED: First EP desc in the control list (7.2.3), + * HcControlCurrentED: Current EP desc in the control list (7.2.4), + * HcBulkHeadED: First EP desc in the bulk list (7.2.5), + * HcBulkCurrentED: Current EP desc in the bulk list (7.2.6), and + * HcDoneHead: Last transfer desc added to DONE queue (7.2.7): + * + * All 32-bits aligned to an 8-byte boundary + */ + +/* HcFmInterval: Bit time interval that would not cause overrun (7.3.1) */ + +#define OHCI_FMINT_FI_SHIFT (0) /* Bits 0-13: Frame interval */ +#define OHCI_FMINT_FI_MASK (0x3fff << OHCI_FMINT_FI_SHIFT) + /* Bits 14-15: Reserved */ +#define OHCI_FMINT_FSMPS_SHIFT (16) /* Bits 16-30: FS largest packet data */ +#define OHCI_FMINT_FSMPS_MASK (0x7fff << OHCI_FMINT_FSMPS_SHIFT) +#define OHCI_FMINT_FIT (1 << 31) /* Bit 31: Frame interval toggle */ + +/* HcFmRemaining: Bit time remaining in current frame (7.3.2) */ + +#define OHCI_FMREM_FR_SHIFT (0) /* Bits 0-13: Frame remaining */ +#define OHCI_FMREM_FR_MASK (0x3fff << OHCI_FMREM_FR_SHIFT) + /* Bits 16-30: Reserved */ +#define OHCI_FMINT_FRT (1 << 31) /* Bit 31: Frame remaining toggle */ + +/* HcFmNumber: Frame number counter (7.3.3) */ + +#define OHCI_FMNO_FI_SHIFT (0) /* Bits 0-15: Frame number */ +#define OHCI_FMNO_FI_MASK (0xffff << OHCI_FMINT_FI_SHIFT) + /* Bits 16-31: Reserved */ +/* HcPeriodicStart: Time to start processing periodic list (7.3.4) */ + +#define OHCI_PERSTART_SHIFT (0) /* Bits 0-13: Periodic start */ +#define OHCI_PERSTART_MASK (0x3fff << OHCI_PERSTART_SHIFT) + /* Bits 14-31: Reserved */ +/* HcLSThreshold: Commit to transfer threshold (7.3.5) */ + +#define OHCI_LSTHRES_SHIFT (0) /* Bits 0-11: LS threshold */ +#define OHCI_LSTHRES_MASK (0x0fff << OHCI_PERSTART_SHIFT) + /* Bits 12-31: Reserved */ +/* HcRhDescriptorN: Describes root hub (part A) (7.4.1) */ + +#define OHCI_RHDESCA_NDP_SHIFT (0) /* Bits 0-7: Number downstream ports */ +#define OHCI_RHDESCA_NDP_MASK (0xff << OHCI_RHDESCA_NDP_SHIFT) +#define OHCI_RHDESCA_PSM (1 << 8) /* Bit 8: Power switching mode */ +#define OHCI_RHDESCA_NPS (1 << 9) /* Bit 9: No power switching */ +#define OHCI_RHDESCA_DT (1 << 10) /* Bit 10: Device type */ +#define OHCI_RHDESCA_OCPM (1 << 11) /* Bit 11: Over current protection mode */ +#define OHCI_RHDESCA_NOCP (1 << 12) /* Bit 12: No over current protection */ + /* Bits 13-23: Reserved */ +#define OHCI_RHDESCA_POTPGT_SHIFT (24) /* Bits 24-31: Power on to power good time */ +#define OHCI_RHDESCA_POTPGT_MASK (0xff << OHCI_RHDESCA_POTPGT_SHIFT) + +/* HcRhDescriptorB: Describes root hub (part B) (7.4.2) */ + +#define OHCI_RHDESCB_DR_SHIFT (0) /* Bits 0-15: Device removable */ +#define OHCI_RHDESCB_DR_MASK (0xffff << OHCI_RHDESCB_DR_SHIFT) +# define OHCI_RHDESCB_ATTACHED(n) (1 << (OHCI_RHDESCB_DR_SHIFT+(n))) +#define OHCI_RHDESCB_PPCM_SHIFT (16) /* Bits 16-31: Port power control mask */ +#define OHCI_RHDESCB_PPCM_MASK (0xffff << OHCI_RHDESCB_PPCM_SHIFT) +# define OHCI_RHDESCB_POWERED(n) (1 << (OHCI_RHDESCB_DR_SHIFT+(n))) + +/* HcRhStatus: Root hub status (7.4.3) */ + +#define OHCI_RHSTATUS_LPS (1 << 0) /* Bit 0: Local power status (read)*/ +#define OHCI_RHSTATUS_CGP (1 << 0) /* Bit 0: Clear global power (write)*/ +#define OHCI_RHSTATUS_OCI (1 << 1) /* Bit 1: Over current indicator */ + /* Bits 2-14: Reserved */ +#define OHCI_RHSTATUS_DRWE (1 << 15) /* Bit 15: Device remote wakeup enable */ +#define OHCI_RHSTATUS_LPSC (1 << 16) /* Bit 16: Local power status change (read) */ +#define OHCI_RHSTATUS_SGP (1 << 16) /* Bit 16: Set global power (write) */ +#define OHCI_RHSTATUS_OCIC (1 << 17) /* Bit 17: Overcurrent indicator change */ + /* Bits 18-30: Reserved */ +#define OHCI_RHSTATUS_CRWE (1 << 31) /* Bit 31: Clear remote wakeup enable */ + +/* HcRhPortStatus: Root hub port status (7.4.4) */ + +#define OHCI_RHPORTST_CCS (1 << 0) /* Bit 0: Current connect status */ +#define OHCI_RHPORTST_PES (1 << 1) /* Bit 1: Port enable status */ +#define OHCI_RHPORTST_PSS (1 << 2) /* Bit 2: Port suspend status */ +#define OHCI_RHPORTST_POCI (1 << 3) /* Bit 3: Port over current indicator */ +#define OHCI_RHPORTST_PRS (1 << 4) /* Bit 4: Port reset status */ + /* Bits 5-7: Reserved */ +#define OHCI_RHPORTST_PPS (1 << 8) /* Bit 8: Port power status */ +#define OHCI_RHPORTST_LSDA (1 << 9) /* Bit 9: Low speed device attached */ + /* Bits 10-15: Reserved */ +#define OHCI_RHPORTST_CSC (1 << 16) /* Bit 16: Connect status change */ +#define OHCI_RHPORTST_PESC (1 << 17) /* Bit 17: Port enable status change */ +#define OHCI_RHPORTST_PSSC (1 << 18) /* Bit 18: Port suspend status change */ +#define OHCI_RHPORTST_OCIC (1 << 19) /* Bit 19: Port over current indicator change */ +#define OHCI_RHPORTST_PRSC (1 << 20) /* Bit 20: Port reset status change */ + /* Bits 21-31: Reserved */ + +/* Transfer Descriptors *****************************************************/ +/* Endpoint Descriptor Offsets (4.2.1) */ + +#define ED_CONTROL_OFFSET (0x00) /* ED status/control bits */ +#define ED_TAILP_OFFSET (0x04) /* TD Queue Tail Pointer (TailP) */ +#define ED_HEADP_OFFSET (0x08) /* TD Queue Head Pointer (HeadP) */ +#define ED_NEXTED_OFFSET (0x0c) /* Next Endpoint Descriptor (NextED) */ + +/* Endpoint Descriptor Bit Definitions (4.2.2) */ + +#define ED_CONTROL_FA_SHIFT (0) /* Bits 0-6: Function Address */ +#define ED_CONTROL_FA_MASK (0x7f << ED_CONTROL_FA_SHIFT) +#define ED_CONTROL_EN_SHIFT (7) /* Bits 7-10: Endpoint number */ +#define ED_CONTROL_EN_MASK (15 << ED_CONTROL_EN_SHIFT) +#define ED_CONTROL_D_SHIFT (11) /* Bits 11-12: Direction */ +#define ED_CONTROL_D_MASK (3 << ED_CONTROL_D_SHIFT) +# define ED_CONTROL_D_TD1 (0 << ED_CONTROL_D_SHIFT) /* Get direction from TD */ +# define ED_CONTROL_D_OUT (1 << ED_CONTROL_D_SHIFT) /* OUT */ +# define ED_CONTROL_D_IN (2 << ED_CONTROL_D_SHIFT) /* IN */ +# define ED_CONTROL_D_TD2 (3 << ED_CONTROL_D_SHIFT) /* Get direction from TD */ +#define ED_CONTROL_S (1 << 13) /* Bit 13: Speed (low) */ +#define ED_CONTROL_K (1 << 14) /* Bit 14: Skip */ +#define ED_CONTROL_F (1 << 15) /* Bit 15: Format (isochronous) */ +#define ED_CONTROL_MPS_SHIFT (16) /* Bits 16-26: Maximum packet size */ +#define ED_CONTROL_MPS_MASK (0x7ff << ED_CONTROL_MPS_SHIFT) + +#define ED_HEADP_ADDR_SHIFT (0) +#define ED_HEADP_ADDR_MASK 0xfffffff0 +#define ED_HEADP_H (1 << 0) /* Bit 0: Halted */ +#define ED_HEADP_C (1 << 1) /* Bit 1: Toggle carry */ + +/* General Transfer Descriptor Offsets (4.3.1) */ + +#define GTD_STATUS_OFFSET (0x00) /* TD status bits */ +#define GTD_CBP_OFFSET (0x04) /* Current Buffer Pointer (CBP) */ +#define GTD_NEXTTD_OFFSET (0x08) /* Next TD (NextTD) */ +#define GTD_BE_OFFSET (0x0c) /* Buffer End (BE) */ + +/* General Transfer Descriptor Bit Definitions */ + /* Bits 0-17: Reserved */ +#define GTD_STATUS_R (1 << 18) /* Bit 18: Buffer rounding */ +#define GTD_STATUS_DP_SHIFT (19) /* Bits 19-20: Direction/PID */ +#define GTD_STATUS_DP_MASK (3 << GTD_STATUS_DP_SHIFT) +# define GTD_STATUS_DP_SETUP (0 << GTD_STATUS_DP_SHIFT) /* To endpoint */ +# define GTD_STATUS_DP_OUT (1 << GTD_STATUS_DP_SHIFT) /* To endpoint */ +# define GTD_STATUS_DP_IN (2 << GTD_STATUS_DP_SHIFT) /* From endpoint */ +#define GTD_STATUS_DI_SHIFT (21) /* Bits 21-23: Delay input */ +#define GTD_STATUS_DI_MASK (7 << GTD_STATUS_DI_SHIFT) +#define GTD_STATUS_T_SHIFT (24) /* Bits 24-25: Data Toggle */ +#define GTD_STATUS_T_MASK (3 << GTD_STATUS_T_SHIFT) +# define GTD_STATUS_T_TOGGLE (0 << GTD_STATUS_T_SHIFT) +# define GTD_STATUS_T_DATA0 (2 << GTD_STATUS_T_SHIFT) +# define GTD_STATUS_T_DATA1 (3 << GTD_STATUS_T_SHIFT) +#define GTD_STATUS_EC_SHIFT (26) /* Bits 26-27: Error count */ +#define GTD_STATUS_EC_MASK (3 << GTD_STATUS_EC_SHIFT) +#define GTD_STATUS_CC_SHIFT (28) /* Bits 28-31: Condition code */ +#define GTD_STATUS_CC_MASK (15 << GTD_STATUS_CC_SHIFT) + +/* Isochronous Transfer Descriptor Offsets (4.3.2) */ + +#define ITD_STATUS_OFFSET (0x00) /* TD status bits */ +#define ITD_BP0_OFFSET (0x04) /* Buffer page 0 (BP0) */ +#define ITD_NEXTTD_OFFSET (0x08) /* Next TD (NextTD) */ +#define ITD_BE_OFFSET (0x0c) /* Buffer End (BE) */ + +#define ITD_NPSW (8) +#define ITD_PSW0_OFFSET (0x10) /* Offset0/PSW0 */ +#define ITD_PSW1_OFFSET (0x12) /* Offset1/PSW1 */ +#define ITD_PSW2_OFFSET (0x14) /* Offset2/PSW2 */ +#define ITD_PSW3_OFFSET (0x16) /* Offset3/PSW3 */ +#define ITD_PSW4_OFFSET (0x18) /* Offset4/PSW4 */ +#define ITD_PSW5_OFFSET (0x1a) /* Offset5/PSW5 */ +#define ITD_PSW6_OFFSET (0x1c) /* Offset6/PSW6 */ +#define ITD_PSW7_OFFSET (0x1e) /* Offset7/PSW7 */ + +/* Condition codes (Table 4-7) */ + +#define TD_CC_NOERROR 0x00 +#define TD_CC_CRC 0x01 +#define TD_CC_BITSTUFFING 0x02 +#define TD_CC_DATATOGGLEMISMATCH 0x03 +#define TD_CC_STALL 0x04 +#define TD_CC_DEVNOTRESPONDING 0x05 +#define TD_CC_PIDCHECKFAILURE 0x06 +#define TD_CC_UNEXPECTEDPID 0x07 +#define TD_CC_DATAOVERRUN 0x08 +#define TD_CC_DATAUNDERRUN 0x09 +#define TD_CC_BUFFEROVERRUN 0x0c +#define TD_CC_BUFFERUNDERRUN 0x0d +#define TD_CC_NOTACCESSED 0x0f + +/* Host Controller Communications Area Format (4.4.1) ***********************/ + +/* HccaInterrruptTable: 32x32-bit pointers to interrupt EDs */ + +#define HCCA_INTTBL_OFFSET (0x00) +#define HCCA_INTTBL_WSIZE (32) +#define HCCA_INTTBL_BSIZE (HCCA_INTTBL_WSIZE*4) + +/* HccaFrameNumber: Current frame number */ + +#define HCCA_FMNO_OFFSET (0x80) +#define HCCA_FMNO_BSIZE (2) + +/* HccaPad1: Zero when frame no. updated */ + +#define HCCA_PAD1_OFFSET (0x82) +#define HCCA_PAD1_BSIZE (2) + +/* HccaDoneHead: When the HC reaches the end of a frame and its deferred + * interrupt register is 0, it writes the current value of its HcDoneHead to + * this location and generates an interrupt. + */ + +#define HCCA_DONEHEAD_OFFSET (0x84) +#define HCCA_DONEHEAD_BSIZE (4) + +/* 0x88: 116 bytes reserved */ + +#define HCCA_RESERVED_OFFSET (0x88) +#define HCCA_RESERVED_BSIZE (116) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Endpoint Descriptor Offsets (4.2.1) */ + +struct ohci_ed_s +{ + volatile uint32_t ctrl; /* ED status/control bits */ + volatile uint32_t tailp; /* TD Queue Tail Pointer (TailP) */ + volatile uint32_t headp; /* TD Queue Head Pointer (HeadP) */ + volatile uint32_t nexted; /* Next Endpoint Descriptor (NextED) */ +}; + +/* General Transfer Descriptor (4.3.1) */ + +struct ohci_gtd_s +{ + volatile uint32_t ctrl; /* TD status/control bits */ + volatile uint32_t cbp; /* Current Buffer Pointer (CBP) */ + volatile uint32_t nexttd; /* Next TD (NextTD) */ + volatile uint32_t be; /* Buffer End (BE) */ +}; + +/* Isochronous Transfer Descriptor Offsets (4.3.2) */ + +struct ohci_itd_s +{ + volatile uint32_t ctrl; /* TD status/control bits */ + volatile uint32_t bp0; /* Buffer page 0 (BP0 */ + volatile uint32_t nexttd; /* Next TD (NextTD) */ + volatile uint32_t be; /* Buffer End (BE) */ + volatile uint16_t psw[ITD_NPSW]; /* Offset/PSW */ +}; + +/* Host Controller Communications Area Format (4.4.1) */ + +struct ohci_hcca_s +{ + /* HccaInterrruptTable: 32x32-bit pointers to interrupt EDs */ + + volatile uint32_t inttbl[HCCA_INTTBL_WSIZE]; + + /* HccaFrameNumber: Current frame number and + * HccaPad1: Zero when frame no. updated + */ + + volatile uint16_t fmno; + volatile uint16_t pad1; + + /* HccaDoneHead: When the HC reaches the end of a frame and its deferred + * interrupt register is 0, it writes the current value of its HcDoneHead to + * this location and generates an interrupt. + */ + + volatile uint32_t donehead; + volatile uint8_t reserved[HCCA_RESERVED_BSIZE]; + volatile uint32_t extra; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_USB_OHCI_H */ diff --git a/nuttx/include/nuttx/usb/pl2303.h b/nuttx/include/nuttx/usb/pl2303.h new file mode 100644 index 0000000000..4e755d10da --- /dev/null +++ b/nuttx/include/nuttx/usb/pl2303.h @@ -0,0 +1,91 @@ +/************************************************************************************ + * include/nuttx/usb/pl2303.h + * + * Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * NOTE: This interface was inspired by the Linux gadget interface by + * David Brownell. That work was very helpful in determining a usable + * partitioning of functionality between standard class drivers and various + * implementations of USB controller drivers. This work, however, does + * not derive directly from that work and is licensed differently. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef _INCLUDE_NUTTX_USB_PL2303_H +#define _INCLUDE_NUTTX_USB_PL2303_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + + /************************************************************************************ + * Public Data + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" +{ +#else +# define EXTERN extern +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: usbdev_serialinit + * + * Description: + * Register PL2303 USB serial port (and USB serial console if so configured). + * + ************************************************************************************/ + +EXTERN int usbdev_serialinitialize(int minor); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* _INCLUDE_NUTTX_USB_PL2303_H */ diff --git a/nuttx/include/nuttx/usb/storage.h b/nuttx/include/nuttx/usb/storage.h new file mode 100644 index 0000000000..4c4bf0066f --- /dev/null +++ b/nuttx/include/nuttx/usb/storage.h @@ -0,0 +1,131 @@ +/************************************************************************************ + * include/nuttx/usb/storage.h + * + * Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "Universal Serial Bus Mass Storage Class, Specification Overview," + * Revision 1.2, USB Implementer's Forum, June 23, 2003. + * + * "Universal Serial Bus Mass Storage Class, Bulk-Only Transport," + * Revision 1.0, USB Implementer's Forum, September 31, 1999. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_USB_STORAGE_H +#define __INCLUDE_NUTTX_USB_STORAGE_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Mass storage requests */ + +#define USBMSC_TYPE_SETUPIN (USB_DIR_IN|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE) +#define USBMSC_TYPE_SETUPOUT (USB_DIR_OUT|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE) + +#define USBMSC_REQ_MSRESET (0xff) /* Reset mass storage device and interface */ +#define USBMSC_REQ_GETMAXLUN (0xfe) /* Return number LUNs supported */ + +/* Mass storage subclass codes */ + +#define USBMSC_SUBCLASS_RBC (0x01) /* Reduced block commands (e.g., flash devices) */ +#define USBMSC_SUBCLASS_SFF1 (0x02) /* SFF-8020i/MMC-2 (ATAPI) (e.g., C/DVD) */ +#define USBMSC_SUBCLASS_QIC (0x03) /* QIC-157 (e.g., tape device) */ +#define USBMSC_SUBCLASS_UFI (0x04) /* e.g. floppy device */ +#define USBMSC_SUBCLASS_SFF2 (0x05) /* SFF-8070i (e.g. floppy disk) */ +#define USBMSC_SUBCLASS_SCSI (0x06) /* SCSI transparent */ + +/* Mass storage transport protocols */ + +#define USBMSC_PROTO_CBI0 (0x00) /* CBI transport with command completion interrupt */ +#define USBMSC_PROTO_CBI1 (0x01) /* CBI transport without command completion interrupt */ +#define USBMSC_PROTO_BULKONLY (0x50) /* Bulk only transport */ + +/* Common Block Wrapper (CBW) */ + +#define USBMSC_CBW_SIZEOF (31) +#define USBMSC_CBW_SIGNATURE (0x43425355) /* Little endian USBC */ +#define USBMSC_CBWFLAG_IN (0x80) /* Bit 7=1: Direction = IN */ + +#define USBMSC_MAXCDBLEN (16) /* Max length of SCSI Command Data Block */ + +/* Command Status Wrapper (CSW) */ + +#define USBMSC_CSW_SIZEOF (13) +#define USBMSC_CSW_SIGNATURE (0x53425355) /* Little endian 'USBS' */ +#define USBMSC_CSWSTATUS_PASS (0) +#define USBMSC_CSWSTATUS_FAIL (1) +#define USBMSC_CSWSTATUS_PHASEERROR (2) + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/* Command Block Wrapper (CBW) */ + +struct usbmsc_cbw_s +{ + uint8_t signature[4]; /* 'USBC' = 0x43425355 */ + uint8_t tag[4]; /* Depends on command id */ + uint8_t datlen[4]; /* Number of bytes that host expects to transfer */ + uint8_t flags; /* Bit 7: Direction=IN (other obsolete or reserved) */ + uint8_t lun; /* LUN (normally 0) */ + uint8_t cdblen; /* len of cdb[] */ + uint8_t cdb[USBMSC_MAXCDBLEN]; /* Command Data Block */ +}; + +/* Command Status Wrapper (CSW) */ + +struct usbmsc_csw_s +{ + uint8_t signature[4]; /* 'USBS' = 0x53425355 */ + uint8_t tag[4]; /* Same tag as original command */ + uint8_t residue[4]; /* Amount not transferred */ + uint8_t status; /* Status of transfer */ +}; + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#endif /* __INCLUDE_NUTTX_USB_STORAGE_H */ diff --git a/nuttx/include/nuttx/usb/usb.h b/nuttx/include/nuttx/usb/usb.h new file mode 100644 index 0000000000..74b1f6a954 --- /dev/null +++ b/nuttx/include/nuttx/usb/usb.h @@ -0,0 +1,416 @@ +/************************************************************************************ + * include/nuttx/usb/usb.h + * + * Copyright (C) 2008, 2009-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_USB_USB_H +#define __INCLUDE_NUTTX_USB_USB_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include + +/************************************************************************************ + * Preprocessor Definitions + ************************************************************************************/ +/* A packet identifier (PID) immediately follows the SYNC field of every USB packet. + * A PID consists of a four-bit packet type field followed by a four-bit check field + * USB Tokens (See Table 8-1 in the USB specification) + */ + +#define USB_PID_OUT_TOKEN (0x01) /* Tokens */ +#define USB_PID_IN_TOKEN (0x09) +#define USB_PID_SOF_TOKEN (0x05) +#define USB_PID_SETUP_TOKEN (0x0d) + +#define USB_PID_DATA0 (0x03) /* Data */ +#define USB_PID_DATA1 (0x0b) +#define USB_PID_DATA2 (0x07) +#define USB_PID_MDATA (0x0f) + +#define USB_PID_ACK (0x02) /* Handshake */ +#define USB_PID_NAK (0x0a) +#define USB_PID_STALL (0x0e) +#define USB_PID_NYET (0x06) + +#define USB_PID_PRE_TOKEN (0x0c) /* Special */ +#define USB_PID_ERR (0x0c) +#define USB_PID_SPLIT_TOKEN (0x08) +#define USB_PID_PING_TOKEN (0x04) +#define USB_PID_RESERVED (0x00) + +/* All 16-bit values must be little-endian */ + +#define MSBYTE(u16) ((u16) >> 8) /* Get MS byte from uint16_t */ +#define LSBYTE(u16) ((u16) & 0xff) /* Get LS byte from uint16_t */ + +#define GETUINT16(p) (((uint16_t)p[1]<<8)|(uint16_t)p[0]) +#define GETUINT32(p) (((uint32_t)p[3]<<24)|((uint32_t)p[2]<<16)|\ + ((uint32_t)p[1]<<8)|(uint32_t)p[0]) + +/* USB directions (in endpoint addresses) */ + +#define USB_DIR_MASK (0x80) +#define USB_EPNO_MASK (0x7f) +#define USB_DIR_OUT (0x00) /* host-to-device */ +#define USB_DIR_IN (0x80) /* device-to-host */ + +#define USB_EPNO(addr) ((addr) & USB_EPNO_MASK) +#define USB_EPOUT(addr) ((addr) | USB_DIR_OUT) +#define USB_EPIN(addr) ((addr) | USB_DIR_IN) +#define USB_ISEPIN(addr) (((addr) & USB_DIR_MASK) == USB_DIR_IN) +#define USB_ISEPOUT(addr) (((addr) & USB_DIR_MASK) == USB_DIR_OUT) + +/* Control Setup Packet. Byte 0 = Request type */ + +#define USB_REQ_DIR_MASK (1 << 7) /* Bit 7=1: Direction bit */ +#define USB_REQ_DIR_IN (1 << 7) /* Bit 7=1: Device-to-host */ +#define USB_REQ_DIR_OUT (0 << 7) /* Bit 7=0: Host-to-device */ + +#define USB_REQ_ISIN(type) (((type) & USB_REQ_DIR_MASK) != 0) +#define USB_REQ_ISOUT(type) (((type) & USB_REQ_DIR_MASK) == 0) + +#define USB_REQ_TYPE_SHIFT (5) /* Bits 5:6: Request type */ +# define USB_REQ_TYPE_MASK (3 << USB_REQ_TYPE_SHIFT) +# define USB_REQ_TYPE_STANDARD (0 << USB_REQ_TYPE_SHIFT) +# define USB_REQ_TYPE_CLASS (1 << USB_REQ_TYPE_SHIFT) +# define USB_REQ_TYPE_VENDOR (2 << USB_REQ_TYPE_SHIFT) + +#define USB_REQ_RECIPIENT_SHIFT (0) /* Bits 0:4: Recipient */ +#define USB_REQ_RECIPIENT_MASK (0x1f << USB_REQ_RECIPIENT_SHIFT) +# define USB_REQ_RECIPIENT_DEVICE (0 << USB_REQ_RECIPIENT_SHIFT) +# define USB_REQ_RECIPIENT_INTERFACE (1 << USB_REQ_RECIPIENT_SHIFT) +# define USB_REQ_RECIPIENT_ENDPOINT (2 << USB_REQ_RECIPIENT_SHIFT) +# define USB_REQ_RECIPIENT_OTHER (3 << USB_REQ_RECIPIENT_SHIFT) + +/* Control Setup Packet. Byte 1 = Standard Request Codes */ + +#define USB_REQ_GETSTATUS (0x00) +#define USB_REQ_CLEARFEATURE (0x01) +#define USB_REQ_SETFEATURE (0x03) +#define USB_REQ_SETADDRESS (0x05) +#define USB_REQ_GETDESCRIPTOR (0x06) +#define USB_REQ_SETDESCRIPTOR (0x07) +#define USB_REQ_GETCONFIGURATION (0x08) +#define USB_REQ_SETCONFIGURATION (0x09) +#define USB_REQ_GETINTERFACE (0x0a) +#define USB_REQ_SETINTERFACE (0x0b) +#define USB_REQ_SYNCHFRAME (0x0c) + +#define USB_REQ_SETENCRYPTION (0x0d) /* Wireless USB */ +#define USB_REQ_GETENCRYPTION (0x0e) +#define USB_REQ_SETHANDSHAKE (0x0f) +#define USB_REQ_GETHANDSHAKE (0x10) +#define USB_REQ_SETCONNECTION (0x11) +#define USB_REQ_SETSECURITYDATA (0x12) +#define USB_REQ_GETSECURITYDATA (0x13) +#define USB_REQ_SETWUSBDATA (0x14) +#define USB_REQ_LOOPBACKDATAWRITE (0x15) +#define USB_REQ_LOOPBACKDATAREAD (0x16) +#define USB_REQ_SETINTERFACEDS (0x17) + +/* USB feature values */ + +#define USB_FEATURE_ENDPOINTHALT 0 +#define USB_FEATURE_SELFPOWERED 0 +#define USB_FEATURE_REMOTEWAKEUP 1 +#define USB_FEATURE_TESTMODE 2 +#define USB_FEATURE_BATTERY 2 +#define USB_FEATURE_BHNPENABLE 3 +#define USB_FEATURE_WUSBDEVICE 3 +#define USB_FEATURE_AHNPSUPPORT 4 +#define USB_FEATURE_AALTHNPSUPPORT 5 +#define USB_FEATURE_DEBUGMODE 6 + +/* Generic descriptor header offsets */ + +#define USB_DESC_DESCLENOFFSET 0 +#define USB_DESC_DESCTYPEOFFSET 1 + +/* Descriptor types */ + +#define USB_DESC_TYPE_DEVICE (0x01) +#define USB_DESC_TYPE_CONFIG (0x02) +#define USB_DESC_TYPE_STRING (0x03) +#define USB_DESC_TYPE_INTERFACE (0x04) +#define USB_DESC_TYPE_ENDPOINT (0x05) +#define USB_DESC_TYPE_DEVICEQUALIFIER (0x06) +#define USB_DESC_TYPE_OTHERSPEEDCONFIG (0x07) +#define USB_DESC_TYPE_INTERFACEPOWER (0x08) +#define USB_DESC_TYPE_OTG (0x09) +#define USB_DESC_TYPE_DEBUG (0x0a) +#define USB_DESC_TYPE_INTERFACEASSOCIATION (0x0b) +#define USB_DESC_TYPE_SECURITY (0x0c) +#define USB_DESC_TYPE_KEY (0x0d) +#define USB_DESC_TYPE_ENCRYPTION_TYPE (0x0e) +#define USB_DESC_TYPE_BOS (0x0f) +#define USB_DESC_TYPE_DEVICECAPABILITY (0x10) +#define USB_DESC_TYPE_WIRELESS_ENDPOINTCOMP (0x11) +#define USB_DESC_TYPE_CSDEVICE (0x21) +#define USB_DESC_TYPE_CSCONFIG (0x22) +#define USB_DESC_TYPE_CSSTRING (0x23) +#define USB_DESC_TYPE_CSINTERFACE (0x24) +#define USB_DESC_TYPE_CSENDPOINT (0x25) + +/* Device and interface descriptor class codes */ + +#define USB_CLASS_PER_INTERFACE (0x00) +#define USB_CLASS_AUDIO (0x01) +#define USB_CLASS_CDC (0x02) +#define USB_CLASS_HID (0x03) +#define USB_CLASS_PHYSICAL (0x05) +#define USB_CLASS_STILL_IMAGE (0x06) +#define USB_CLASS_PRINTER (0x07) +#define USB_CLASS_MASS_STORAGE (0x08) +#define USB_CLASS_HUB (0x09) +#define USB_CLASS_CDC_DATA (0x0a) +#define USB_CLASS_CSCID (0x0b) +#define USB_CLASS_CONTENT_SEC (0x0d) +#define USB_CLASS_VIDEO (0x0e) +#define USB_CLASS_WIRELESS_CONTROLLER (0xe0) +#define USB_CLASS_MISC (0xef) +#define USB_CLASS_APP_SPEC (0xfe) +#define USB_CLASS_VENDOR_SPEC (0xff) + +/* Values for configuration descriptor attributes */ + +#define USB_CONFIG_ATTR_BATTERY (0x10) /* Battery powered */ +#define USB_CONFIG_ATTR_WAKEUP (0x20) /* Remote wakeup */ +#define USB_CONFIG_ATTR_SELFPOWER (0x40) /* Self-powered */ +#define USB_CONFIG_ATTR_ONE (0x80) /* Must be one */ + +/* Endpoint descriptor address */ + +#define USB_EP_ADDR_NUMBER_MASK (0x0f) +#define USB_EP_ADDR_DIR_MASK (0x80) + +/* Endpoint descriptor attributes */ + +#define USB_EP_ATTR_XFERTYPE_SHIFT (0) +#define USB_EP_ATTR_XFERTYPE_MASK (3 << USB_EP_ATTR_XFERTYPE_SHIFT) +# define USB_EP_ATTR_XFER_CONTROL (0 << USB_EP_ATTR_XFERTYPE_SHIFT) +# define USB_EP_ATTR_XFER_ISOC (1 << USB_EP_ATTR_XFERTYPE_SHIFT) +# define USB_EP_ATTR_XFER_BULK (2 << USB_EP_ATTR_XFERTYPE_SHIFT) +# define USB_EP_ATTR_XFER_INT (3 << USB_EP_ATTR_XFERTYPE_SHIFT) +#define USB_EP_ATTR_SYNC_SHIFT (2) +#define USB_EP_ATTR_SYNC_MASK (3 << USB_EP_ATTR_SYNC_SHIFT) +# define USB_EP_ATTR_NO_SYNC (0 << USB_EP_ATTR_SYNC_SHIFT) +# define USB_EP_ATTR_ASYNC (1 << USB_EP_ATTR_SYNC_SHIFT) +# define USB_EP_ATTR_ADAPTIVE (2 << USB_EP_ATTR_SYNC_SHIFT) +# define USB_EP_ATTR_SYNC (3 << USB_EP_ATTR_SYNC_SHIFT) +#define USB_EP_ATTR_USAGE_SHIFT (4) +#define USB_EP_ATTR_USAGE_MASK (3 << USB_EP_ATTR_USAGE_SHIFT) +# define USB_EP_ATTR_USAGE_DATA (0 << USB_EP_ATTR_USAGE_SHIFT) +# define USB_EP_ATTR_USAGE_FEEDBACK (1 << USB_EP_ATTR_USAGE_SHIFT) +# define USB_EP_ATTR_USAGE_IMPLICIT (2 << USB_EP_ATTR_USAGE_SHIFT) +#define USB_EP_ATTR_MAX_ADJUSTABLE (1 << 7) + +/* OTG Definitions */ + +/* OTG SET FEATURE Constants */ + +#define USBOTG_FEATURE_B_HNP_ENABLE 3 /* Enable B device to perform HNP */ +#define USBOTG_FEATURE_A_HNP_SUPPORT 4 /* A device supports HNP */ +#define USBOTG_FEATURE_A_ALT_HNP_SUPPORT 5 /* Another port on the A device supports HNP */ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/* This structure is used to send control requests to a USB device. */ + +struct usb_ctrlreq_s +{ + uint8_t type; /* Matches request type */ + uint8_t req; /* Matches request field */ + uint8_t value[2]; + uint8_t index[2]; + uint8_t len[2]; +}; +#define USB_SIZEOF_CTRLREQ 8 + +/* Generic descriptor */ + +struct usb_desc_s +{ + uint8_t len; /* Descriptor length */ + uint8_t type; /* Descriptor type */ +}; + +/* Device descriptor */ + +struct usb_devdesc_s +{ + uint8_t len; /* Descriptor length */ + uint8_t type; /* Descriptor type */ + uint8_t usb[2]; /* USB version */ + uint8_t classid; /* Device class */ + uint8_t subclass; /* Device sub-class */ + uint8_t protocol; /* Device protocol */ + uint8_t mxpacketsize; /* Max packet size (ep0) */ + uint8_t vendor[2]; /* Vendor ID */ + uint8_t product[2]; /* Product ID */ + uint8_t device[2]; /* Device ID */ + uint8_t imfgr; /* Manufacturer */ + uint8_t iproduct; /* Product */ + uint8_t serno; /* Serial number */ + uint8_t nconfigs; /* Number of configurations */ +}; +#define USB_SIZEOF_DEVDESC 18 + +/* Configuration descriptor */ + +struct usb_cfgdesc_s +{ + uint8_t len; /* Descriptor length */ + uint8_t type; /* Descriptor type */ + uint8_t totallen[2]; /* Total length */ + uint8_t ninterfaces; /* Number of interfaces */ + uint8_t cfgvalue; /* Configuration value */ + uint8_t icfg; /* Configuration */ + uint8_t attr; /* Attributes */ + uint8_t mxpower; /* Max power (mA/2) */ +}; +#define USB_SIZEOF_CFGDESC 9 + +struct usb_otherspeedconfigdesc_s +{ + uint8_t len; /* Descriptor length */ + uint8_t type; /* Descriptor type */ + uint8_t totallen[2]; /* Total length */ + uint8_t ninterfaces; /* Number of interfaces */ + uint8_t cfgvalue; /* Configuration value */ + uint8_t icfg; /* Configuration */ + uint8_t attr; /* Attributes */ + uint8_t mxpower; /* Max power (mA/2) */ +}; +#define USB_SIZEOF_OTHERSPEEDCONFIGDESC 9 + +/* String descriptor */ + +struct usb_strdesc_s +{ + uint8_t len; /* Descriptor length */ + uint8_t type; /* Descriptor type */ + uint8_t data[2]; +}; + +/* Interface descriptor */ + +struct usb_ifdesc_s +{ + uint8_t len; /* Descriptor length */ + uint8_t type; /* Descriptor type */ + uint8_t ifno; /* Interface number */ + uint8_t alt; /* Alternate setting */ + uint8_t neps; /* Number of endpoints */ + uint8_t classid; /* Interface class */ + uint8_t subclass; /* Interface sub-class */ + uint8_t protocol; /* Interface protocol */ + uint8_t iif; /* iInterface */ +}; +#define USB_SIZEOF_IFDESC 9 + +/* Endpoint descriptor */ + +struct usb_epdesc_s +{ + uint8_t len; /* Descriptor length */ + uint8_t type; /* Descriptor type */ + uint8_t addr; /* Endpoint address */ + uint8_t attr; /* Endpoint attributes */ + uint8_t mxpacketsize[2]; /* Maximum packet size */ + uint8_t interval; /* Interval */ +}; +#define USB_SIZEOF_EPDESC 7 + +struct usb_audioepdesc_s +{ + struct usb_epdesc_s ep; + uint8_t refresh; + uint8_t synchaddr; +}; +#define USB_SIZEOF_AUDIOEPDESC 9 + +/* Device qualifier descriptor */ + +struct usb_qualdesc_s +{ + uint8_t len; /* Descriptor length */ + uint8_t type; /* Descriptor type */ + uint8_t usb[2]; /* USB version */ + uint8_t classid; /* Qualifier class */ + uint8_t subclass; /* Qualifier sub-class */ + uint8_t protocol; /* Qualifier protocol */ + uint8_t mxpacketsize; /* Max packet size (ep0) */ + uint8_t nconfigs; /* Number of configurations */ + uint8_t reserved; +}; +#define USB_SIZEOF_QUALDESC 10 + +/* Interface association descriptor + * + * The Universal Serial Bus Specification, revision 2.0, does not support grouping + * more than one interface of a composite device within a single function. However, + * the USB Device Working Group (DWG) created USB device classes that allow for + * functions with multiple interfaces, and the USB Implementor's Forum issued an + * Engineering Change Notification (ECN) that defines a mechanism for grouping + * interfaces. + */ + +struct usb_iaddesc_s +{ + uint8_t len; /* Descriptor length */ + uint8_t type; /* Descriptor type */ + uint8_t firstif; /* Number of first interface of the function */ + uint8_t nifs; /* Number of interfaces associated with the function */ + uint8_t classid; /* Class code */ + uint8_t subclass; /* Sub-class code */ + uint8_t protocol; /* Protocol code */ + uint8_t ifunction; /* Index to string identifying the function */ +}; +#define USB_SIZEOF_IADDESC 8 + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#endif // __INCLUDE_NUTTX_USB_USB_H diff --git a/nuttx/include/nuttx/usb/usbdev.h b/nuttx/include/nuttx/usb/usbdev.h new file mode 100644 index 0000000000..89813cac96 --- /dev/null +++ b/nuttx/include/nuttx/usb/usbdev.h @@ -0,0 +1,362 @@ +/************************************************************************************ + * include/nuttx/usb/usbdev.h + * + * Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * NOTE: This interface was inspired by the Linux gadget interface by + * David Brownell. That work was very helpful in determining a usable + * partitioning of functionality between standard class drivers and various + * implementations of USB controller drivers. This work, however, does + * not derive directly from that work and is licensed differently. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef _INCLUDE_NUTTX_USB_USBDEV_H +#define _INCLUDE_NUTTX_USB_USBDEV_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Endpoint helpers *****************************************************************/ + +/* Configure endpoint, making it usable. The class driver may deallocate or re-use + * the 'desc' structure after returning: + * + * ep - the struct usbdev_ep_s instance obtained from allocep() + * desc - A struct usb_epdesc_s instance describing the endpoint + * last - true if this this last endpoint to be configured. Some hardware needs + * to take special action when all of the endpoints have been configured. + */ + +#define EP_CONFIGURE(ep,desc,last) (ep)->ops->configure(ep,desc,last) + +/* The endpoint will no longer be used */ + +#define EP_DISABLE(ep) (ep)->ops->disable(ep) + +/* Allocate/free I/O requests. Should not be called from interrupt processing! */ + +#define EP_ALLOCREQ(ep) (ep)->ops->allocreq(ep) +#define EP_FREEREQ(ep,req) (ep)->ops->freereq(ep,req) + +/* Allocate/free an I/O buffer. Should not be called from interrupt processing! */ + +#ifdef CONFIG_ARCH_USBDEV_DMA +# define EP_ALLOCBUFFER(ep,nb) (ep)->ops->alloc(ep,nb) +# define EP_FREEBUFFER(ep,buff) (ep)->ops->free(ep,buf) +#else +# define EP_ALLOCBUFFER(ep,nb) malloc(nb) +# define EP_FREEBUFFER(ep,buf) free(buf) +#endif + +/* Submit an I/O request to the endpoint */ + +#define EP_SUBMIT(ep,req) (ep)->ops->submit(ep,req) + +/* Cancel an I/O request previously sent to an endpoint */ + +#define EP_CANCEL(ep,req) (ep)->ops->cancel(ep,req) + +/* Stall or resume an endpoint */ + +#define EP_STALL(ep) (ep)->ops->stall(ep,false) +#define EP_RESUME(ep) (ep)->ops->stall(ep,true) + +/* USB Device Driver Helpers ********************************************************/ + +/* Allocate an endpoint: + * + * ep - 7-bit logical endpoint number (direction bit ignored). Zero means + * that any endpoint matching the other requirements will suffice. The + * assigned endpoint can be found in the eplog field. + * in - true: IN (device-to-host) endpoint requested + * eptype - Endpoint type. One of {USB_EP_ATTR_XFER_ISOC, USB_EP_ATTR_XFER_BULK, + * USB_EP_ATTR_XFER_INT} + */ + +#define DEV_ALLOCEP(dev,ep,in,type) (dev)->ops->allocep(dev,ep,in,type) + +/* Release an endpoint */ + +#define DEV_FREEEP(dev,ep) (dev)->ops->freeep(dev,ep) + +/* Returns the current frame number */ + +#define DEV_GETFRAME(dev) (dev)->ops->getframe(dev) + +/* Tries to wake up the host connected to this device */ + +#define DEV_WAKEUP(dev) (dev)->ops->wakeup(dev) + +/* Sets the device selfpowered feature */ + +#define DEV_SETSELFPOWERED(dev) (dev)->ops->selfpowered(dev,true) + +/* Clears the device selfpowered feature */ + +#define DEV_CLRSELFPOWERED(dev) (dev)->ops->selfpowered(dev, false) + +/* Software-controlled connect to USB host. All USB class drivers need to call + * DEV_CONNECT() when they are ready to be enumerated. That is, (1) initially when + * bound to the USB driver, and (2) after a USB reset. + */ + +#define DEV_CONNECT(dev) (dev)->ops->pullup ? (dev)->ops->pullup(dev,true) : -EOPNOTSUPP + +/* Software-controlled disconnect from USB host */ + +#define DEV_DISCONNECT(dev) (dev)->ops->pullup ? (dev)->ops->pullup(dev,false) : -EOPNOTSUPP + +/* USB Class Driver Helpers *********************************************************/ +/* All may be called from interupt handling logic except bind() and unbind() */ + +/* Invoked when the driver is bound to a USB device driver. */ + +#define CLASS_BIND(drvr,dev) (drvr)->ops->bind(drvr,dev) + +/* Invoked when the driver is unbound from a USB device driver */ + +#define CLASS_UNBIND(drvr,dev) (drvr)->ops->unbind(drvr,dev) + +/* Invoked after all transfers have been stopped, when the host is disconnected. */ + +#define CLASS_DISCONNECT(drvr,dev) (drvr)->ops->disconnect(drvr,dev) + +/* Invoked for ep0 control requests */ + +#define CLASS_SETUP(drvr,dev,ctrl,dataout,outlen) \ + (drvr)->ops->setup(drvr,dev,ctrl,dataout,outlen) + +/* Invoked on USB suspend. */ + +#define CLASS_SUSPEND(drvr,dev) \ + do { if ((drvr)->ops->suspend) (drvr)->ops->suspend(drvr,dev); } while (0) + +/* Invoked on USB resume */ + +#define CLASS_RESUME(drvr,dev) \ + do { if ((drvr)->ops->resume) (drvr)->ops->resume(drvr,dev); } while (0) + +/* Device speeds */ + +#define USB_SPEED_UNKNOWN 0 /* Transfer rate not yet set */ +#define USB_SPEED_LOW 1 /* USB 1.1 */ +#define USB_SPEED_FULL 2 /* USB 1.1 */ +#define USB_SPEED_HIGH 3 /* USB 2.0 */ +#define USB_SPEED_VARIABLE 4 /* Wireless USB 2.5 */ + +/* Request flags */ + +#define USBDEV_REQFLAGS_NULLPKT 1 /* Bit 0: Terminate w/short packet; null packet if necessary */ + /* Bits 1-7: Available */ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/* USB Controller Structures ********************************************************/ + +/* struct usbdev_req_s - describes one i/o request */ + +struct usbdev_ep_s; +struct usbdev_req_s +{ + uint8_t *buf; /* Call: Buffer used for data; Return: Unchanged */ + uint8_t flags; /* See USBDEV_REQFLAGS_* definitions */ + uint16_t len; /* Call: Total length of data in buf; Return: Unchanged */ + uint16_t xfrd; /* Call: zero; Return: Bytes transferred so far */ + int16_t result; /* Call: zero; Return: Result of transfer (O or -errno) */ + + /* Callback when the transfer completes */ + + void (*callback)(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req); + void *priv; /* Used only by callee */ +}; + +/* Endpoint-specific interface to USB controller hardware. */ + +struct usbdev_epops_s +{ + /* Configure/enable and disable endpoint */ + + int (*configure)(FAR struct usbdev_ep_s *ep, FAR const struct usb_epdesc_s *desc, + bool last); + int (*disable)(FAR struct usbdev_ep_s *ep); + + /* Allocate and free I/O requests */ + + FAR struct usbdev_req_s *(*allocreq)(FAR struct usbdev_ep_s *ep); + void (*freereq)(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req); + + /* Allocate and free I/O buffers */ + +#ifdef CONFIG_ARCH_USBDEV_DMA + FAR void *(*allocbuffer)(FAR struct usbdev_ep_s *ep, uint16_t nbytes); + void (*freebuffer)(FAR struct usbdev_ep_s *ep, FAR void *buf); +#endif + + /* Submit and cancel I/O requests */ + + int (*submit)(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req); + int (*cancel)(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req); + + /* Stall or resume an endpoint */ + + int (*stall)(FAR struct usbdev_ep_s *ep, bool resume); +}; + +/* Representation of one USB endpoint */ + +struct usbdev_ep_s +{ + const struct usbdev_epops_s *ops; /* Endpoint operations */ + uint8_t eplog; /* Logical endpoint address */ + uint16_t maxpacket; /* Maximum packet size for this endpoint */ + void *priv; /* For use by class driver */ +}; + +/* struct usbdev_s represents a usb device */ + +struct usbdev_s; +struct usbdev_ops_s +{ + /* Allocate and free endpoints */ + + FAR struct usbdev_ep_s *(*allocep)(FAR struct usbdev_s *dev, uint8_t epphy, + bool in, uint8_t eptype); + void (*freeep)(FAR struct usbdev_s *dev, FAR struct usbdev_ep_s *ep); + + /* Get the frame number from the last SOF */ + + int (*getframe)(FAR struct usbdev_s *dev); + + /* Hardware specific features */ + + int (*wakeup)(FAR struct usbdev_s *dev); + int (*selfpowered)(FAR struct usbdev_s *dev, bool selfpowered); + int (*pullup)(FAR struct usbdev_s *dev, bool enable); + + /* Device-specific I/O command support */ + + int (*ioctl)(FAR struct usbdev_s *dev, unsigned code, unsigned long param); +}; + +struct usbdev_s +{ + const struct usbdev_ops_s *ops; /* Access to hardware specific features */ + struct usbdev_ep_s *ep0; /* Endpoint zero */ + uint8_t speed; /* Current speed of the host connection */ + uint8_t dualspeed:1; /* 1:supports high and full speed operation */ +}; + +/* USB Device Class Implementations *************************************************/ + +struct usbdevclass_driver_s; +struct usbdevclass_driverops_s +{ + int (*bind)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); + void (*unbind)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); + int (*setup)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, size_t outlen); + void (*disconnect)(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); + void (*suspend)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); + void (*resume)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); +}; + +struct usbdevclass_driver_s +{ + const struct usbdevclass_driverops_s *ops; + uint8_t speed; /* Highest speed that the driver handles */ +}; + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" +{ +#else +# define EXTERN extern +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: usbdevclass_register + * + * Description: + * Register a USB device class driver. The class driver's bind() method will be + * called to bind it to a USB device driver. + * + ************************************************************************************/ + +EXTERN int usbdev_register(FAR struct usbdevclass_driver_s *driver); + +/************************************************************************************ + * Name: usbdev_unregister + * + * Description: + * Un-register usbdev class driver.If the USB device is connected to a USB host, + * it will first disconnect(). The driver is also requested to unbind() and clean + * up any device state, before this procedure finally returns. + * + ************************************************************************************/ + +EXTERN int usbdev_unregister(FAR struct usbdevclass_driver_s *driver); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* _INCLUDE_NUTTX_USB_USBDEV_H */ diff --git a/nuttx/include/nuttx/usb/usbdev_trace.h b/nuttx/include/nuttx/usb/usbdev_trace.h new file mode 100644 index 0000000000..ae8e13c3a4 --- /dev/null +++ b/nuttx/include/nuttx/usb/usbdev_trace.h @@ -0,0 +1,499 @@ +/**************************************************************************** + * include/nuttx/usb/usbdev_trace.h + * + * Copyright (C) 2008, 2009-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_USB_USBDEV_TRACE_H +#define __INCLUDE_NUTTX_USB_USBDEV_TRACE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Preprocessor definitions + ****************************************************************************/ + +/* Event encoding/decoding macros *******************************************/ + +#define TRACE_EVENT(id,data) ((uint16_t)(id)|(data)) +#define TRACE_ID(event) ((event)&0xff00) +#define TRACE_DATA(event) ((event)&0x00ff) + +/* Events ******************************************************************/ + +/* Event class IDs */ + +#define TRACE_INIT_ID (0x0000) /* Initialization events */ +#define TRACE_EP_ID (0x0100) /* Endpoint API calls */ +#define TRACE_DEV_ID (0x0200) /* USB device API calls */ +#define TRACE_CLASS_ID (0x0300) /* USB class driver API calls */ +#define TRACE_CLASSAPI_ID (0x0400) /* Other class driver system API calls */ +#define TRACE_CLASSSTATE_ID (0x0500) /* Track class driver state changes */ +#define TRACE_INTENTRY_ID (0x0600) /* Interrupt handler entry */ +#define TRACE_INTDECODE_ID (0x0700) /* Decoded interrupt event */ +#define TRACE_INTEXIT_ID (0x0800) /* Interrupt handler exit */ +#define TRACE_OUTREQQUEUED_ID (0x0900) /* Request queued for OUT endpoint */ +#define TRACE_INREQQUEUED_ID (0x0a00) /* Request queued for IN endpoint */ +#define TRACE_READ_ID (0x0b00) /* Read (OUT) action */ +#define TRACE_WRITE_ID (0x0c00) /* Write (IN) action */ +#define TRACE_COMPLETE_ID (0x0d00) /* Request completed */ +#define TRACE_DEVERROR_ID (0x0e00) /* USB controller driver error event */ +#define TRACE_CLSERROR_ID (0x0f00) /* USB class driver error event */ + +#define TRACE_NIDS 16 /* Cannot exceed bits in usbtrace_idset_t */ + +/* Bit settings for usbtrace_enable */ + +#define TRACE_ID2BIT(id) ((1) << ((id) >> 8)) +#define TRACE_INIT_BIT TRACE_ID2BIT(TRACE_INIT_ID) +#define TRACE_EP_BIT TRACE_ID2BIT(TRACE_EP_ID) +#define TRACE_DEV_BIT TRACE_ID2BIT(TRACE_DEV_ID) +#define TRACE_CLASS_BIT TRACE_ID2BIT(TRACE_CLASS_ID) +#define TRACE_CLASSAPI_BIT TRACE_ID2BIT(TRACE_CLASSAPI_ID) +#define TRACE_CLASSSTATE_BIT TRACE_ID2BIT(TRACE_CLASSSTATE_ID) +#define TRACE_INTENTRY_BIT TRACE_ID2BIT(TRACE_INTENTRY_ID) +#define TRACE_INTDECODE_BIT TRACE_ID2BIT(TRACE_INTDECODE_ID) +#define TRACE_INTEXIT_BIT TRACE_ID2BIT(TRACE_INTEXIT_ID) +#define TRACE_OUTREQQUEUED_BIT TRACE_ID2BIT(TRACE_OUTREQQUEUED_ID) +#define TRACE_INREQQUEUED_BIT TRACE_ID2BIT(TRACE_INREQQUEUED_ID) +#define TRACE_READ_BIT TRACE_ID2BIT(TRACE_READ_ID) +#define TRACE_WRITE_BIT TRACE_ID2BIT(TRACE_WRITE_ID) +#define TRACE_COMPLETE_BIT TRACE_ID2BIT(TRACE_COMPLETE_ID) +#define TRACE_DEVERROR_BIT TRACE_ID2BIT(TRACE_DEVERROR_ID) +#define TRACE_CLSERROR_BIT TRACE_ID2BIT(TRACE_CLSERROR_ID) +#define TRACE_ALLBITS ((usbtrace_idset_t)-1) + +/* Initialization events */ + +#define TRACE_DEVINIT TRACE_EVENT(TRACE_INIT_ID, 0x0001) +#define TRACE_DEVUNINIT TRACE_EVENT(TRACE_INIT_ID, 0x0002) +#define TRACE_DEVREGISTER TRACE_EVENT(TRACE_INIT_ID, 0x0003) +#define TRACE_DEVUNREGISTER TRACE_EVENT(TRACE_INIT_ID, 0x0004) + +/* API calls (see usbdev.h) */ + +#define TRACE_EPCONFIGURE TRACE_EVENT(TRACE_EP_ID, 0x0001) +#define TRACE_EPDISABLE TRACE_EVENT(TRACE_EP_ID, 0x0002) +#define TRACE_EPALLOCREQ TRACE_EVENT(TRACE_EP_ID, 0x0003) +#define TRACE_EPFREEREQ TRACE_EVENT(TRACE_EP_ID, 0x0004) +#define TRACE_EPALLOCBUFFER TRACE_EVENT(TRACE_EP_ID, 0x0005) +#define TRACE_EPFREEBUFFER TRACE_EVENT(TRACE_EP_ID, 0x0006) +#define TRACE_EPSUBMIT TRACE_EVENT(TRACE_EP_ID, 0x0007) +#define TRACE_EPCANCEL TRACE_EVENT(TRACE_EP_ID, 0x0008) +#define TRACE_EPSTALL TRACE_EVENT(TRACE_EP_ID, 0x0009) +#define TRACE_EPRESUME TRACE_EVENT(TRACE_EP_ID, 0x000a) + +#define TRACE_DEVALLOCEP TRACE_EVENT(TRACE_DEV_ID, 0x0001) +#define TRACE_DEVFREEEP TRACE_EVENT(TRACE_DEV_ID, 0x0002) +#define TRACE_DEVGETFRAME TRACE_EVENT(TRACE_DEV_ID, 0x0003) +#define TRACE_DEVWAKEUP TRACE_EVENT(TRACE_DEV_ID, 0x0004) +#define TRACE_DEVSELFPOWERED TRACE_EVENT(TRACE_DEV_ID, 0x0005) +#define TRACE_DEVPULLUP TRACE_EVENT(TRACE_DEV_ID, 0x0006) + +#define TRACE_CLASSBIND TRACE_EVENT(TRACE_CLASS_ID, 0x0001) +#define TRACE_CLASSUNBIND TRACE_EVENT(TRACE_CLASS_ID, 0x0002) +#define TRACE_CLASSDISCONNECT TRACE_EVENT(TRACE_CLASS_ID, 0x0003) +#define TRACE_CLASSSETUP TRACE_EVENT(TRACE_CLASS_ID, 0x0004) +#define TRACE_CLASSSUSPEND TRACE_EVENT(TRACE_CLASS_ID, 0x0005) +#define TRACE_CLASSRESUME TRACE_EVENT(TRACE_CLASS_ID, 0x0006) + +#define TRACE_CLASSRDCOMPLETE TRACE_EVENT(TRACE_CLASS_ID, 0x0007) +#define TRACE_CLASSWRCOMPLETE TRACE_EVENT(TRACE_CLASS_ID, 0x0008) + +#define TRACE_CLASSAPI(id) TRACE_EVENT(TRACE_CLASSAPI_ID, id) + +#define TRACE_CLASSSTATE(id) TRACE_EVENT(TRACE_CLASSSTATE_ID, id) + +/* USB device controller interrupt events. The 'id' is specific to the driver. + * Particular values for 'id' are unique for a given implementation of a + * controller driver + */ + +#define TRACE_INTENTRY(id) TRACE_EVENT(TRACE_INTENTRY_ID, id) +#define TRACE_INTDECODE(id) TRACE_EVENT(TRACE_INTDECODE_ID, id) +#define TRACE_INTEXIT(id) TRACE_EVENT(TRACE_INTEXIT_ID, id) + +/* Controller data transfer */ + +#define TRACE_OUTREQQUEUED(ep) TRACE_EVENT(TRACE_OUTREQQUEUED_ID, ep) +#define TRACE_INREQQUEUED(ep) TRACE_EVENT(TRACE_INREQQUEUED_ID, ep) +#define TRACE_READ(ep) TRACE_EVENT(TRACE_READ_ID, ep) +#define TRACE_WRITE(ep) TRACE_EVENT(TRACE_WRITE_ID, ep) +#define TRACE_COMPLETE(ep) TRACE_EVENT(TRACE_COMPLETE_ID, ep) + +/* USB device controller error events. The 'id' is specific to the driver. + * Particular values for 'id' are unique for a given implementation of a + * controller driver + */ + +#define TRACE_DEVERROR(id) TRACE_EVENT(TRACE_DEVERROR_ID, id) + +/* USB class driver error events. The 'id' is specific to the class driver, + * but common to all driver controller instances. + */ + +#define TRACE_CLSERROR(id) TRACE_EVENT(TRACE_CLSERROR_ID, id) + +/* USB Serial driver class events *******************************************/ +/* Used by both the CDC/ACM and the PL2303 serial class drivers */ +/* UART interface API calls */ + +#define USBSER_TRACECLASSAPI_SETUP 0x0001 +#define USBSER_TRACECLASSAPI_SHUTDOWN 0x0002 +#define USBSER_TRACECLASSAPI_ATTACH 0x0003 +#define USBSER_TRACECLASSAPI_DETACH 0x0004 +#define USBSER_TRACECLASSAPI_IOCTL 0x0005 +#define USBSER_TRACECLASSAPI_RECEIVE 0x0006 +#define USBSER_TRACECLASSAPI_RXINT 0x0007 +#define USBSER_TRACECLASSAPI_RXAVAILABLE 0x0008 +#define USBSER_TRACECLASSAPI_SEND 0x0009 +#define USBSER_TRACECLASSAPI_TXINT 0x000a +#define USBSER_TRACECLASSAPI_TXREADY 0x000b +#define USBSER_TRACECLASSAPI_TXEMPTY 0x000c + +/* Values of the class error ID used by the USB serial driver */ + +#define USBSER_TRACEERR_ALLOCCTRLREQ 0x0001 +#define USBSER_TRACEERR_ALLOCDEVSTRUCT 0x0002 +#define USBSER_TRACEERR_ALREADYCLOSED 0x0003 +#define USBSER_TRACEERR_ALREADYCONFIGURED 0x0004 +#define USBSER_TRACEERR_CONFIGIDBAD 0x0005 +#define USBSER_TRACEERR_CONFIGNONE 0x0006 +#define USBSER_TRACEERR_CONSOLEREGISTER 0x0007 +#define USBSER_TRACEERR_DEVREGISTER 0x0008 +#define USBSER_TRACEERR_EPRESPQ 0x0009 +#define USBSER_TRACEERR_GETUNKNOWNDESC 0x000a +#define USBSER_TRACEERR_INVALIDARG 0x000b +#define USBSER_TRACEERR_EP0NOTBOUND 0x000c +#define USBSER_TRACEERR_EPBULKINALLOCFAIL 0x000d +#define USBSER_TRACEERR_EPBULKINCONFIGFAIL 0x000e +#define USBSER_TRACEERR_EPBULKOUTALLOCFAIL 0x000f +#define USBSER_TRACEERR_EPINTINALLOCFAIL 0x0010 +#define USBSER_TRACEERR_EPINTINCONFIGFAIL 0x0011 +#define USBSER_TRACEERR_EPBULKOUTCONFIGFAIL 0x0012 +#define USBSER_TRACEERR_RDALLOCREQ 0x0013 +#define USBSER_TRACEERR_RDSHUTDOWN 0x0014 +#define USBSER_TRACEERR_RDSUBMIT 0x0015 +#define USBSER_TRACEERR_RDUNEXPECTED 0x0016 +#define USBSER_TRACEERR_REQRESULT 0x0017 +#define USBSER_TRACEERR_RXOVERRUN 0x0018 +#define USBSER_TRACEERR_SETUPNOTCONNECTED 0x0019 +#define USBSER_TRACEERR_SUBMITFAIL 0x001a +#define USBSER_TRACEERR_UARTREGISTER 0x001b +#define USBSER_TRACEERR_UARTUNREGISTER 0x001c +#define USBSER_TRACEERR_UNSUPPORTEDCTRLREQ 0x001d +#define USBSER_TRACEERR_UNSUPPORTEDCLASSREQ 0x001e +#define USBSER_TRACEERR_UNSUPPORTEDSTDREQ 0x001f +#define USBSER_TRACEERR_UNSUPPORTEDTYPE 0x0020 +#define USBSER_TRACEERR_WRALLOCREQ 0x0021 +#define USBSER_TRACEERR_WRSHUTDOWN 0x0022 +#define USBSER_TRACEERR_WRUNEXPECTED 0x0023 + +/* USB Storage driver class events ******************************************/ + +#define USBCOMPOSITE_TRACEERR_REQRESULT 0x0001 +#define USBCOMPOSITE_TRACEERR_ALLOCCTRLREQ 0x0002 +#define USBCOMPOSITE_TRACEERR_INVALIDARG 0x0003 +#define USBCOMPOSITE_TRACEERR_EP0NOTBOUND 0x0004 +#define COMPOSITE_TRACEERR_SETUPINVALIDARGS 0x0005 +#define COMPOSITE_TRACEERR_EP0NOTBOUND2 0x0006 +#define COMPOSITE_TRACEERR_GETUNKNOWNDESC 0x0007 +#define COMPOSITE_TRACEERR_UNSUPPORTEDSTDREQ 0x0008 +#define COMPOSITE_TRACEERR_EPRESPQ 0x0009 +#define USBCOMPOSITE_TRACEERR_ALLOCDEVSTRUCT 0x000a +#define USBCOMPOSITE_TRACEERR_CLASSOBJECT 0x000b +#define USBCOMPOSITE_TRACEERR_DEVREGISTER 0x000c +#define USBCOMPOSITE_TRACEERR_INVALIDARG 0x000d +#define USBCOMPOSITE_TRACEERR_INVALIDARG 0x000f +#define USBCOMPOSITE_TRACEERR_INVALIDARG 0x0010 +#define USBCOMPOSITE_TRACEERR_INVALIDARG 0x0011 + +/* USB Storage driver class events ******************************************/ + +/* State transitions */ + +#define USBMSC_CLASSSTATE_IDLECMDPARSE 0x0001 +#define USBMSC_CLASSSTATE_CMDPARSECMDFINISH 0x0002 +#define USBMSC_CLASSSTATE_CMDPARSECMDREAD6 0x0003 +#define USBMSC_CLASSSTATE_CMDPARSECMDREAD10 0x0004 +#define USBMSC_CLASSSTATE_CMDPARSECMDREAD12 0x0005 +#define USBMSC_CLASSSTATE_CMDPARSECMDWRITE6 0x0006 +#define USBMSC_CLASSSTATE_CMDPARSECMDWRITE10 0x0007 +#define USBMSC_CLASSSTATE_CMDPARSECMDWRITE12 0x0008 +#define USBMSC_CLASSSTATE_CMDREAD 0x0009 +#define USBMSC_CLASSSTATE_CMDREADCMDFINISH 0x000a +#define USBMSC_CLASSSTATE_CMDWRITE 0x000b +#define USBMSC_CLASSSTATE_CMDWRITECMDFINISH 0x000c +#define USBMSC_CLASSSTATE_CMDFINISHCMDSTATUS 0x000d +#define USBMSC_CLASSSTATE_CMDSTATUSIDLE 0x000e + +/* Values of the class error ID used by the USB storage driver */ + +#define USBMSC_TRACEERR_ALLOCCTRLREQ 0x0001 +#define USBMSC_TRACEERR_ALLOCDEVSTRUCT 0x0002 +#define USBMSC_TRACEERR_ALLOCIOBUFFER 0x0003 +#define USBMSC_TRACEERR_ALREADYCONFIGURED 0x0004 +#define USBMSC_TRACEERR_ALREADYUNINIT 0x0005 +#define USBMSC_TRACEERR_BADREQUEST 0x0006 +#define USBMSC_TRACEERR_BINDLUNINVALIDARGS2 0x0007 +#define USBMSC_TRACEERR_BINDLUNINVALIDARGS3 0x0008 +#define USBMSC_TRACEERR_BINDLUNINVALIDARGS4 0x0009 +#define USBMSC_TRACEERR_BINLUNINVALIDARGS1 0x000a +#define USBMSC_TRACEERR_BLKDRVEOPEN 0x000b +#define USBMSC_TRACEERR_CMDBADLUN 0x000c +#define USBMSC_TRACEERR_CMDFINISHRESIDUE 0x000d +#define USBMSC_TRACEERR_CMDFINISHRQEMPTY 0x000e +#define USBMSC_TRACEERR_CMDFINISHSHORTPKT 0x000f +#define USBMSC_TRACEERR_CMDFINISHSUBMIT 0x0010 +#define USBMSC_TRACEERR_CMDFINSHDIR 0x0011 +#define USBMSC_TRACEERR_CMDFINSHSUBMIT 0x0012 +#define USBMSC_TRACEERR_CMDPARSEWRREQLISTEMPTY 0x0013 +#define USBMSC_TRACEERR_CMDREADREADFAIL 0x0014 +#define USBMSC_TRACEERR_CMDREADSUBMIT 0x0015 +#define USBMSC_TRACEERR_CMDREADWRRQEMPTY 0x0016 +#define USBMSC_TRACEERR_CMDSTATUSRDREQLISTEMPTY 0x0017 +#define USBMSC_TRACEERR_CMDUNEVIOLATION 0x0018 +#define USBMSC_TRACEERR_CMDWRITERDSUBMIT 0x0019 +#define USBMSC_TRACEERR_CMDWRITERDRQEMPTY 0x001a +#define USBMSC_TRACEERR_CMDWRITEWRITEFAIL 0x001b +#define USBMSC_TRACEERR_CONFIGIDBAD 0x001c +#define USBMSC_TRACEERR_CONFIGNONE 0x001d +#define USBMSC_TRACEERR_DEFERREDRESPINVALIDARGS 0x001e +#define USBMSC_TRACEERR_DEFERREDRESPSTALLED 0x001f +#define USBMSC_TRACEERR_DEFERREDRESPSUBMIT 0x0020 +#define USBMSC_TRACEERR_DEVREGISTER 0x0021 +#define USBMSC_TRACEERR_DISCONNECTINVALIDARGS 0x0022 +#define USBMSC_TRACEERR_EP0NOTBOUND1 0x0023 +#define USBMSC_TRACEERR_EP0NOTBOUND2 0x0024 +#define USBMSC_TRACEERR_EP0NOTBOUND3 0x0025 +#define USBMSC_TRACEERR_EPBULKINALLOCFAIL 0x0026 +#define USBMSC_TRACEERR_EPBULKINCONFIGFAIL 0x0027 +#define USBMSC_TRACEERR_EPBULKOUTALLOCFAIL 0x0028 +#define USBMSC_TRACEERR_EPBULKOUTCONFIGFAIL 0x0029 +#define USBMSC_TRACEERR_EPRESPQ 0x002a +#define USBMSC_TRACEERR_EXPORTLUNSINVALIDARGS 0x002b +#define USBMSC_TRACEERR_GETMAXLUNNDX 0x002c +#define USBMSC_TRACEERR_GETUNKNOWNDESC 0x002d +#define USBMSC_TRACEERR_IDLERDREQLISTEMPTY 0x002e +#define USBMSC_TRACEERR_IDLERDSUBMIT 0x002f +#define USBMSC_TRACEERR_INQUIRYFLAGS 0x0030 +#define USBMSC_TRACEERR_INTERNALCONFUSION1 0x0031 +#define USBMSC_TRACEERR_INTERNALCONFUSION2 0x0032 +#define USBMSC_TRACEERR_INVALIDCBWCONTENT 0x0033 +#define USBMSC_TRACEERR_INVALIDCBWSIGNATURE 0x0034 +#define USBMSC_TRACEERR_INVALIDSTATE 0x0035 +#define USBMSC_TRACEERR_LUNALREADYBOUND 0x0036 +#define USBMSC_TRACEERR_LUNNOTBOUND 0x0037 +#define USBMSC_TRACEERR_MODEPAGEFLAGS 0x0038 +#define USBMSC_TRACEERR_MODESENSE10FLAGS 0x0039 +#define USBMSC_TRACEERR_MODESENSE6FLAGS 0x003a +#define USBMSC_TRACEERR_MSRESETNDX 0x003b +#define USBMSC_TRACEERR_NOGEOMETRY 0x003c +#define USBMSC_TRACEERR_NOTCONFIGURED 0x003d +#define USBMSC_TRACEERR_NOTREMOVABLE 0x003e +#define USBMSC_TRACEERR_PCSAVED 0x003f +#define USBMSC_TRACEERR_PHASEERROR1 0x0040 +#define USBMSC_TRACEERR_PHASEERROR2 0x0041 +#define USBMSC_TRACEERR_PHASEERROR3 0x0042 +#define USBMSC_TRACEERR_PREVENTMEDIUMREMOVALPREVENT 0x0043 +#define USBMSC_TRACEERR_RDALLOCREQ 0x0044 +#define USBMSC_TRACEERR_RDCOMPLETEINVALIDARGS 0x0045 +#define USBMSC_TRACEERR_RDCOMPLETERDSUBMIT 0x0046 +#define USBMSC_TRACEERR_RDSHUTDOWN 0x0047 +#define USBMSC_TRACEERR_RDSUBMIT 0x0048 +#define USBMSC_TRACEERR_RDUNEXPECTED 0x0049 +#define USBMSC_TRACEERR_READ10FLAGS 0x004a +#define USBMSC_TRACEERR_READ10LBARANGE 0x004b +#define USBMSC_TRACEERR_READ10MEDIANOTPRESENT 0x004c +#define USBMSC_TRACEERR_READ12FLAGS 0x004d +#define USBMSC_TRACEERR_READ12LBARANGE 0x004e +#define USBMSC_TRACEERR_READ12MEDIANOTPRESENT 0x004f +#define USBMSC_TRACEERR_READ6LBARANGE 0x0050 +#define USBMSC_TRACEERR_READ6MEDIANOTPRESENT 0x0051 +#define USBMSC_TRACEERR_READCAPACITYFLAGS 0x0052 +#define USBMSC_TRACEERR_REALLOCIOBUFFER 0x0053 +#define USBMSC_TRACEERR_REQRESULT 0x0054 +#define USBMSC_TRACEERR_SCSICMDCONTROL 0x0055 +#define USBMSC_TRACEERR_SETCONFIGINVALIDARGS 0x0056 +#define USBMSC_TRACEERR_SETUPINVALIDARGS 0x0057 +#define USBMSC_TRACEERR_SNDCSWFAIL 0x0058 +#define USBMSC_TRACEERR_SNDPHERROR 0x0059 +#define USBMSC_TRACEERR_SNDSTATUSSUBMIT 0x005a +#define USBMSC_TRACEERR_SYNCCACHEMEDIANOTPRESENT 0x005b +#define USBMSC_TRACEERR_THREADCREATE 0x005c +#define USBMSC_TRACEERR_TOOMANYLUNS 0x005d +#define USBMSC_TRACEERR_UNBINDINVALIDARGS 0x005e +#define USBMSC_TRACEERR_UNBINDLUNINVALIDARGS1 0x005f +#define USBMSC_TRACEERR_UNBINDLUNINVALIDARGS2 0x0060 +#define USBMSC_TRACEERR_UNINITIALIZEINVALIDARGS 0x0061 +#define USBMSC_TRACEERR_UNSUPPORTEDSTDREQ 0x0062 +#define USBMSC_TRACEERR_VERIFY10FLAGS 0x0063 +#define USBMSC_TRACEERR_VERIFY10LBARANGE 0x0064 +#define USBMSC_TRACEERR_VERIFY10MEDIANOTPRESENT 0x0065 +#define USBMSC_TRACEERR_VERIFY10NOBLOCKS 0x0066 +#define USBMSC_TRACEERR_VERIFY10READFAIL 0x0067 +#define USBMSC_TRACEERR_WRALLOCREQ 0x0068 +#define USBMSC_TRACEERR_SNDPHERROR 0x0069 +#define USBMSC_TRACEERR_WRCOMPLETEINVALIDARGS 0x006a +#define USBMSC_TRACEERR_WRITE10FLAGS 0x006b +#define USBMSC_TRACEERR_WRITE10LBARANGE 0x006c +#define USBMSC_TRACEERR_WRITE10MEDIANOTPRESENT 0x006d +#define USBMSC_TRACEERR_WRITE10READONLY 0x006e +#define USBMSC_TRACEERR_WRITE12FLAGS 0x006f +#define USBMSC_TRACEERR_WRITE12LBARANGE 0x0070 +#define USBMSC_TRACEERR_WRITE12MEDIANOTPRESENT 0x0071 +#define USBMSC_TRACEERR_WRITE12READONLY 0x0072 +#define USBMSC_TRACEERR_WRITE6LBARANGE 0x0073 +#define USBMSC_TRACEERR_WRITE6MEDIANOTPRESENT 0x0074 +#define USBMSC_TRACEERR_WRITE6READONLY 0x0075 +#define USBMSC_TRACEERR_WRSHUTDOWN 0x0076 +#define USBMSC_TRACEERR_WRUNEXPECTED 0x0077 +#define USBMSC_TRACEERR_UNSUPPORTEDTYPE 0x0078 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The reported trace information */ + +struct usbtrace_s +{ + uint16_t event; + uint16_t value; +}; + +/* Enumeration callback function signature */ + +typedef int (*trace_callback_t)(struct usbtrace_s *trace, void *arg); + +/* Bit mask input type for usbtrace_enable(). If TRACE_NIDS grows beyond + * 16, then this will have to be changed to uint32_t + */ + +typedef uint16_t usbtrace_idset_t; + +/* Print routine to use for usbdev_trprint() output */ + +typedef int (*trprintf_t)(const char *fmt, ...); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" { +#else +# define EXTERN extern +#endif + +/******************************************************************************* + * Name: usbtrace_enable + * + * Description: + * Enable/disable tracing per trace ID. The initial state is all IDs enabled. + * + * Input Parameters: + * idset - The bitset of IDs to be masked. TRACE_ALLIDS enables all IDS; zero + * masks all IDs. + * + * Returned Value: + * The previous idset value. + * + * Assumptions: + * - May be called from an interrupt handler + * + *******************************************************************************/ + +#if defined(CONFIG_USBDEV_TRACE) || (defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_USB)) +EXTERN usbtrace_idset_t usbtrace_enable(usbtrace_idset_t idset); +#else +# define usbtrace_enable(idset) +#endif + +/******************************************************************************* + * Name: usbtrace + * + * Description: + * Record a USB event (tracing must be enabled) + * + * Assumptions: + * May be called from an interrupt handler + * + *******************************************************************************/ + +#if defined(CONFIG_USBDEV_TRACE) || (defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_USB)) +EXTERN void usbtrace(uint16_t event, uint16_t value); +#else +# define usbtrace(event, value) +#endif + +/******************************************************************************* + * Name: usbtrace_enumerate + * + * Description: + * Enumerate all buffer trace data (will temporarily disable tracing) + * + * Assumptions: + * NEVER called from an interrupt handler + * + *******************************************************************************/ + +#ifdef CONFIG_USBDEV_TRACE +EXTERN int usbtrace_enumerate(trace_callback_t callback, void *arg); +#else +# define usbtrace_enumerate(event) +#endif + +/******************************************************************************* + * Name: usbtrace_trprint + * + * Description: + * Print the trace record using the supplied printing function + * + *******************************************************************************/ + +EXTERN void usbtrace_trprintf(trprintf_t trprintf, uint16_t event, uint16_t value); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_USB_USBDEV_TRACE_H */ diff --git a/nuttx/include/nuttx/usb/usbhost.h b/nuttx/include/nuttx/usb/usbhost.h new file mode 100644 index 0000000000..133fd4387a --- /dev/null +++ b/nuttx/include/nuttx/usb/usbhost.h @@ -0,0 +1,869 @@ +/************************************************************************************ + * include/nuttx/usb/usbhost.h + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "Universal Serial Bus Mass Storage Class, Specification Overview," + * Revision 1.2, USB Implementer's Forum, June 23, 2003. + * + * "Universal Serial Bus Mass Storage Class, Bulk-Only Transport," + * Revision 1.0, USB Implementer's Forum, September 31, 1999. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_USB_USBHOST_H +#define __INCLUDE_NUTTX_USB_USBHOST_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Name: CLASS_CREATE + * + * Description: + * This macro will call the create() method of struct usbhost_registry_s. The create() + * method is a callback into the class implementation. It is used to (1) create + * a new instance of the USB host class state and to (2) bind a USB host driver + * "session" to the class instance. Use of this create() method will support + * environments where there may be multiple USB ports and multiple USB devices + * simultaneously connected. + * + * Input Parameters: + * reg - The USB host class registry entry previously obtained from a call to + * usbhost_findclass(). + * drvr - An instance of struct usbhost_driver_s that the class implementation will + * "bind" to its state structure and will subsequently use to communicate with + * the USB host driver. + * id - In the case where the device supports multiple base classes, subclasses, or + * protocols, this specifies which to configure for. + * + * Returned Values: + * On success, this function will return a non-NULL instance of struct + * usbhost_class_s that can be used by the USB host driver to communicate with the + * USB host class. NULL is returned on failure; this function will fail only if + * the drvr input parameter is NULL or if there are insufficient resources to + * create another USB host class instance. + * + * Assumptions: + * If this function is called from an interrupt handler, it will be unable to + * allocate memory and CONFIG_USBHOST_NPREALLOC should be defined to be a value + * greater than zero specify a number of pre-allocated class structures. + * + ************************************************************************************/ + +#define CLASS_CREATE(reg, drvr, id) ((reg)->create(drvr, id)) + +/************************************************************************************ + * Name: CLASS_CONNECT + * + * Description: + * This macro will call the connect() method of struct usbhost_class_s. This + * method is a callback into the class implementation. It is used to provide the + * device's configuration descriptor to the class so that the class may initialize + * properly + * + * Input Parameters: + * class - The USB host class entry previously obtained from a call to create(). + * configdesc - A pointer to a uint8_t buffer container the configuration descripor. + * desclen - The length in bytes of the configuration descriptor. + * funcaddr - The USB address of the function containing the endpoint that EP0 + * controls + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * NOTE that the class instance remains valid upon return with a failure. It is + * the responsibility of the higher level enumeration logic to call + * CLASS_DISCONNECTED to free up the class driver resources. + * + * Assumptions: + * - This function is probably called on the same thread that called the driver + * enumerate() method. This function will *not* be called from an interrupt + * handler. + * - If this function returns an error, the USB host controller driver + * must call to DISCONNECTED method to recover from the error + * + ************************************************************************************/ + +#define CLASS_CONNECT(class,configdesc,desclen,funcaddr) \ + ((class)->connect(class,configdesc,desclen, funcaddr)) + +/************************************************************************************ + * Name: CLASS_DISCONNECTED + * + * Description: + * This macro will call the disconnected() method of struct usbhost_class_s. This + * method is a callback into the class implementation. It is used to inform the + * class that the USB device has been disconnected. + * + * Input Parameters: + * class - The USB host class entry previously obtained from a call to create(). + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +#define CLASS_DISCONNECTED(class) ((class)->disconnected(class)) + +/******************************************************************************* + * Name: DRVR_WAIT + * + * Description: + * Wait for a device to be connected or disconneced. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * connected - TRUE: Wait for device to be connected; FALSE: wait for device to + * be disconnected + * + * Returned Values: + * Zero (OK) is returned when a device in connected. This function will not + * return until either (1) a device is connected or (2) some failure occurs. + * On a failure, a negated errno value is returned indicating the nature of + * the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + *******************************************************************************/ + +#define DRVR_WAIT(drvr, connected) ((drvr)->wait(drvr,connected)) + +/************************************************************************************ + * Name: DRVR_ENUMERATE + * + * Description: + * Enumerate the connected device. As part of this enumeration process, + * the driver will (1) get the device's configuration descriptor, (2) + * extract the class ID info from the configuration descriptor, (3) call + * usbhost_findclass() to find the class that supports this device, (4) + * call the create() method on the struct usbhost_registry_s interface + * to get a class instance, and finally (5) call the connect() method + * of the struct usbhost_class_s interface. After that, the class is in + * charge of the sequence of operations. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +#define DRVR_ENUMERATE(drvr) ((drvr)->enumerate(drvr)) + +/************************************************************************************ + * Name: DRVR_EP0CONFIGURE + * + * Description: + * Configure endpoint 0. This method is normally used internally by the + * enumerate() method but is made available at the interface to support + * an external implementation of the enumeration logic. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * funcaddr - The USB address of the function containing the endpoint that EP0 + * controls + * mps (maxpacketsize) - The maximum number of bytes that can be sent to or + * received from the endpoint in a single data packet + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +#define DRVR_EP0CONFIGURE(drvr,funcaddr,mps) ((drvr)->ep0configure(drvr,funcaddr,mps)) + +/************************************************************************************ + * Name: DRVR_EPALLOC + * + * Description: + * Allocate and configure one endpoint. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * epdesc - Describes the endpoint to be allocated. + * ep - A memory location provided by the caller in which to receive the + * allocated endpoint desciptor. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +#define DRVR_EPALLOC(drvr,epdesc,ep) ((drvr)->epalloc(drvr,epdesc,ep)) + +/************************************************************************************ + * Name: DRVR_EPFREE + * + * Description: + * Free and endpoint previously allocated by DRVR_EPALLOC. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * ep - The endpint to be freed. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +#define DRVR_EPFREE(drvr,ep) ((drvr)->epfree(drvr,ep)) + +/************************************************************************************ + * Name: DRVR_ALLOC + * + * Description: + * Some hardware supports special memory in which request and descriptor data can + * be accessed more efficiently. This method provides a mechanism to allocate + * the request/descriptor memory. If the underlying hardware does not support + * such "special" memory, this functions may simply map to malloc. + * + * This interface was optimized under a particular assumption. It was assumed + * that the driver maintains a pool of small, pre-allocated buffers for descriptor + * traffic. NOTE that size is not an input, but an output: The size of the + * pre-allocated buffer is returned. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * buffer - The address of a memory location provided by the caller in which to + * return the allocated buffer memory address. + * maxlen - The address of a memory location provided by the caller in which to + * return the maximum size of the allocated buffer memory. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +#define DRVR_ALLOC(drvr,buffer,maxlen) ((drvr)->alloc(drvr,buffer,maxlen)) + +/************************************************************************************ + * Name: DRVR_FREE + * + * Description: + * Some hardware supports special memory in which request and descriptor data can + * be accessed more efficiently. This method provides a mechanism to free that + * request/descriptor memory. If the underlying hardware does not support + * such "special" memory, this functions may simply map to free(). + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * buffer - The address of the allocated buffer memory to be freed. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +#define DRVR_FREE(drvr,buffer) ((drvr)->free(drvr,buffer)) + +/************************************************************************************ + * Name: DRVR_IOALLOC + * + * Description: + * Some hardware supports special memory in which larger IO buffers can + * be accessed more efficiently. This method provides a mechanism to allocate + * the request/descriptor memory. If the underlying hardware does not support + * such "special" memory, this functions may simply map to malloc. + * + * This interface differs from DRVR_ALLOC in that the buffers are variable-sized. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * buffer - The address of a memory location provided by the caller in which to + * return the allocated buffer memory address. + * buflen - The size of the buffer required. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +#define DRVR_IOALLOC(drvr,buffer,buflen) ((drvr)->ioalloc(drvr,buffer,buflen)) + +/************************************************************************************ + * Name: DRVR_IOFREE + * + * Description: + * Some hardware supports special memory in which IO data can be accessed more + * efficiently. This method provides a mechanism to free that IO buffer + * memory. If the underlying hardware does not support such "special" memory, + * this functions may simply map to free(). + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * buffer - The address of the allocated buffer memory to be freed. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +#define DRVR_IOFREE(drvr,buffer) ((drvr)->iofree(drvr,buffer)) + +/************************************************************************************ + * Name: DRVR_CTRLIN and DRVR_CTRLOUT + * + * Description: + * Process a IN or OUT request on the control endpoint. These methods + * will enqueue the request and wait for it to complete. Only one transfer may be + * queued; Neither these methods nor the transfer() method can be called again + * until the control transfer functions returns. + * + * These are blocking methods; these functions will not return until the + * control transfer has completed. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * req - Describes the request to be sent. This request must lie in memory + * created by DRVR_ALLOC. + * buffer - A buffer used for sending the request and for returning any + * responses. This buffer must be large enough to hold the length value + * in the request description. buffer must have been allocated using DRVR_ALLOC. + * + * NOTE: On an IN transaction, req and buffer may refer to the same allocated + * memory. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +#define DRVR_CTRLIN(drvr,req,buffer) ((drvr)->ctrlin(drvr,req,buffer)) +#define DRVR_CTRLOUT(drvr,req,buffer) ((drvr)->ctrlout(drvr,req,buffer)) + +/************************************************************************************ + * Name: DRVR_TRANSFER + * + * Description: + * Process a request to handle a transfer descriptor. This method will + * enqueue the transfer request and rwait for it to complete. Only one transfer may + * be queued; Neither this method nor the ctrlin or ctrlout methods can be called + * again until this function returns. + * + * This is a blocking method; this functions will not return until the + * transfer has completed. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * ed - The IN or OUT endpoint descriptor for the device endpoint on which to + * perform the transfer. + * buffer - A buffer containing the data to be sent (OUT endpoint) or received + * (IN endpoint). buffer must have been allocated using DRVR_ALLOC + * buflen - The length of the data to be sent or received. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +#define DRVR_TRANSFER(drvr,ed,buffer,buflen) ((drvr)->transfer(drvr,ed,buffer,buflen)) + +/************************************************************************************ + * Name: DRVR_DISCONNECT + * + * Description: + * Called by the class when an error occurs and driver has been disconnected. + * The USB host driver should discard the handle to the class instance (it is + * stale) and not attempt any further interaction with the class driver instance + * (until a new instance is received from the create() method). The driver + * should not called the class' disconnected() method. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * + * Returned Values: + * None + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +#define DRVR_DISCONNECT(drvr) ((drvr)->disconnect(drvr)) + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/* This struct contains all of the information that is needed to associate a device + * this is connected via a USB port to a class. + */ + +struct usbhost_id_s +{ + uint8_t base; /* Base device class code (see USB_CLASS_* defines in usb.h) */ + uint8_t subclass; /* Sub-class, depends on base class. Eg., See USBMSC_SUBCLASS_* */ + uint8_t proto; /* Protocol, depends on base class. Eg., See USBMSC_PROTO_* */ + uint16_t vid; /* Vendor ID (for vendor/product specific devices) */ + uint16_t pid; /* Product ID (for vendor/product specific devices) */ +}; + +/* The struct usbhost_registry_s type describes information that is kept in the the + * USB host registry. USB host class implementations register this information so + * that USB host drivers can later find the class that matches the device that is + * connected to the USB port. + */ + +struct usbhost_driver_s; /* Forward reference to the driver state structure */ +struct usbhost_class_s; /* Forward reference to the class state structure */ +struct usbhost_registry_s +{ + /* This field is used to implement a singly-link registry structure. Because of + * the presence of this link, provides of structy usbhost_registry_s instances must + * provide those instances in write-able memory (RAM). + */ + + struct usbhost_registry_s *flink; + + /* This is a callback into the class implementation. It is used to (1) create + * a new instance of the USB host class state and to (2) bind a USB host driver + * "session" to the class instance. Use of this create() method will support + * environments where there may be multiple USB ports and multiple USB devices + * simultaneously connected (see the CLASS_CREATE() macro above). + */ + + FAR struct usbhost_class_s *(*create)(FAR struct usbhost_driver_s *drvr, + FAR const struct usbhost_id_s *id); + + /* This information uniquely identifies the USB host class implementation that + * goes with a specific USB device. + */ + + uint8_t nids; /* Number of IDs in the id[] array */ + FAR const struct usbhost_id_s *id; /* An array of ID info. Actual dimension is nids */ +}; + +/* struct usbhost_class_s provides access from the USB host driver to the USB host + * class implementation. + */ + +struct usbhost_class_s +{ + /* Provides the configuration descriptor to the class. The configuration + * descriptor contains critical information needed by the class in order to + * initialize properly (such as endpoint selections). + */ + + int (*connect)(FAR struct usbhost_class_s *class, FAR const uint8_t *configdesc, + int desclen, uint8_t funcaddr); + + /* This method informs the class that the USB device has been disconnected. */ + + int (*disconnected)(FAR struct usbhost_class_s *class); +}; + +/* This structure describes one endpoint. It is used as an input to the + * allocep() method. Most of this information comes from the endpoint + * descriptor. + */ + +struct usbhost_epdesc_s +{ + uint8_t addr; /* Endpoint address */ + bool in; /* Direction: true->IN */ + uint8_t funcaddr; /* USB address of function containing endpoint */ + uint8_t xfrtype; /* Transfer type. See SB_EP_ATTR_XFER_* in usb.h */ + uint8_t interval; /* Polling interval */ + uint16_t mxpacketsize; /* Max packetsize */ +}; + +/* This type represents one endpoint configured by the allocep() method. + * The actual form is know only internally to the USB host controller + * (for example, for an OHCI driver, this would probably be a pointer + * to an endpoint descriptor). + */ + +typedef FAR void *usbhost_ep_t; + +/* struct usbhost_driver_s provides access to the USB host driver from the + * USB host class implementation. + */ + +struct usbhost_driver_s +{ + /* Wait for a device to connect or disconnect. */ + + int (*wait)(FAR struct usbhost_driver_s *drvr, bool connected); + + /* Enumerate the connected device. As part of this enumeration process, + * the driver will (1) get the device's configuration descriptor, (2) + * extract the class ID info from the configuration descriptor, (3) call + * usbhost_findclass() to find the class that supports this device, (4) + * call the create() method on the struct usbhost_registry_s interface + * to get a class instance, and finally (5) call the connect() method + * of the struct usbhost_class_s interface. After that, the class is in + * charge of the sequence of operations. + */ + + int (*enumerate)(FAR struct usbhost_driver_s *drvr); + + /* Configure endpoint 0. This method is normally used internally by the + * enumerate() method but is made available at the interface to support + * an external implementation of the enumeration logic. + */ + + int (*ep0configure)(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, + uint16_t maxpacketsize); + + /* Allocate and configure an endpoint. */ + + int (*epalloc)(FAR struct usbhost_driver_s *drvr, + const FAR struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep); + int (*epfree)(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep); + + /* Some hardware supports special memory in which transfer descriptors can + * be accessed more efficiently. The following methods provide a mechanism + * to allocate and free the transfer descriptor memory. If the underlying + * hardware does not support such "special" memory, these functions may + * simply map to malloc and free. + * + * This interface was optimized under a particular assumption. It was assumed + * that the driver maintains a pool of small, pre-allocated buffers for descriptor + * traffic. NOTE that size is not an input, but an output: The size of the + * pre-allocated buffer is returned. + */ + + int (*alloc)(FAR struct usbhost_driver_s *drvr, + FAR uint8_t **buffer, FAR size_t *maxlen); + int (*free)(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer); + + /* Some hardware supports special memory in which larger IO buffers can + * be accessed more efficiently. This method provides a mechanism to allocate + * the request/descriptor memory. If the underlying hardware does not support + * such "special" memory, this functions may simply map to malloc. + * + * This interface differs from DRVR_ALLOC in that the buffers are variable-sized. + */ + + int (*ioalloc)(FAR struct usbhost_driver_s *drvr, + FAR uint8_t **buffer, size_t buflen); + int (*iofree)(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer); + + /* Process a IN or OUT request on the control endpoint. These methods + * will enqueue the request and wait for it to complete. Only one transfer may + * be queued; Neither these methods nor the transfer() method can be called again + * until the control transfer functions returns. + * + * These are blocking methods; these functions will not return until the + * control transfer has completed. + */ + + int (*ctrlin)(FAR struct usbhost_driver_s *drvr, + FAR const struct usb_ctrlreq_s *req, + FAR uint8_t *buffer); + int (*ctrlout)(FAR struct usbhost_driver_s *drvr, + FAR const struct usb_ctrlreq_s *req, + FAR const uint8_t *buffer); + + /* Process a request to handle a transfer descriptor. This method will + * enqueue the transfer request and wait for it to complete. Only one transfer may + * be queued; Neither this method nor the ctrlin or ctrlout methods can be called + * again until this function returns. + * + * This is a blocking method; this functions will not return until the + * transfer has completed. + */ + + int (*transfer)(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, + FAR uint8_t *buffer, size_t buflen); + + /* Called by the class when an error occurs and driver has been disconnected. + * The USB host driver should discard the handle to the class instance (it is + * stale) and not attempt any further interaction with the class driver instance + * (until a new instance is received from the create() method). + */ + + void (*disconnect)(FAR struct usbhost_driver_s *drvr); +}; + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: usbhost_registerclass + * + * Description: + * Register a USB host class implementation. The caller provides an instance of + * struct usbhost_registry_s that contains all of the information that will be + * needed later to (1) associate the USB host class implementation with a connected + * USB device, and (2) to obtain and bind a struct usbhost_class_s instance for + * the device. + * + * Input Parameters: + * class - An write-able instance of struct usbhost_registry_s that will be + * maintained in a registry. + * + * Returned Values: + * On success, this function will return zero (OK). Otherwise, a negated errno + * value is returned. + * + ************************************************************************************/ + +EXTERN int usbhost_registerclass(struct usbhost_registry_s *class); + +/************************************************************************************ + * Name: usbhost_findclass + * + * Description: + * Find a USB host class implementation previously registered by + * usbhost_registerclass(). On success, an instance of struct usbhost_registry_s + * will be returned. That instance will contain all of the information that will + * be needed to obtain and bind a struct usbhost_class_s instance for the device. + * + * Input Parameters: + * id - Identifies the USB device class that has connect to the USB host. + * + * Returned Values: + * On success this function will return a non-NULL instance of struct + * usbhost_registry_s. NULL will be returned on failure. This function can only + * fail if (1) id is NULL, or (2) no USB host class is registered that matches the + * device class ID. + * + ************************************************************************************/ + +EXTERN const struct usbhost_registry_s *usbhost_findclass(const struct usbhost_id_s *id); + +/**************************************************************************** + * Name: usbhost_storageinit + * + * Description: + * Initialize the USB host storage class. This function should be called + * be platform-specific code in order to initialize and register support + * for the USB host storage class. + * + * Input Parameters: + * None + * + * Returned Values: + * On success this function will return zero (OK); A negated errno value + * will be returned on failure. + * + ****************************************************************************/ + +EXTERN int usbhost_storageinit(void); + +/**************************************************************************** + * Name: usbhost_kbdinit + * + * Description: + * Initialize the USB storage HID keyboard class driver. This function + * should be called be platform-specific code in order to initialize and + * register support for the USB host HID keyboard class device. + * + * Input Parameters: + * None + * + * Returned Values: + * On success this function will return zero (OK); A negated errno value + * will be returned on failure. + * + ****************************************************************************/ + +EXTERN int usbhost_kbdinit(void); + +/**************************************************************************** + * Name: usbhost_wlaninit + * + * Description: + * Initialize the USB WLAN class driver. This function should be called + * be platform-specific code in order to initialize and register support + * for the USB host class device. + * + * Input Parameters: + * None + * + * Returned Values: + * On success this function will return zero (OK); A negated errno value + * will be returned on failure. + * + ****************************************************************************/ + +EXTERN int usbhost_wlaninit(void); + +/******************************************************************************* + * Name: usbhost_initialize + * + * Description: + * Initialize USB host device controller hardware. + * + * Input Parameters: + * controller -- If the device supports more than USB host controller, then + * this identifies which controller is being intialized. Normally, this + * is just zero. + * + * Returned Value: + * And instance of the USB host interface. The controlling task should + * use this interface to (1) call the wait() method to wait for a device + * to be connected, and (2) call the enumerate() method to bind the device + * to a class driver. + * + * Assumptions: + * - This function should called in the initialization sequence in order + * to initialize the USB device functionality. + * - Class drivers should be initialized prior to calling this function. + * Otherwise, there is a race condition if the device is already connected. + * + *******************************************************************************/ + +EXTERN FAR struct usbhost_driver_s *usbhost_initialize(int controller); + +/******************************************************************************* + * Name: usbhost_enumerate + * + * Description: + * This is a share-able implementation of most of the logic required by the + * driver enumerate() method. This logic within this method should be common + * to all USB host drivers. + * + * Enumerate the connected device. As part of this enumeration process, + * the driver will (1) get the device's configuration descriptor, (2) + * extract the class ID info from the configuration descriptor, (3) call + * usbhost_findclass() to find the class that supports this device, (4) + * call the create() method on the struct usbhost_registry_s interface + * to get a class instance, and finally (5) call the configdesc() method + * of the struct usbhost_class_s interface. After that, the class is in + * charge of the sequence of operations. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * funcaddr - The USB address of the function containing the endpoint that EP0 + * controls + * class - If the class driver for the device is successful located + * and bound to the driver, the allocated class instance is returned into + * this caller-provided memory location. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * - Only a single class bound to a single device is supported. + * - Called from a single thread so no mutual exclusion is required. + * - Never called from an interrupt handler. + * + *******************************************************************************/ + +EXTERN int usbhost_enumerate(FAR struct usbhost_driver_s *drvr, + uint8_t funcaddr, + FAR struct usbhost_class_s **class); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_USB_USBHOST_H */ diff --git a/nuttx/include/nuttx/usb/usbhost_trace.h b/nuttx/include/nuttx/usb/usbhost_trace.h new file mode 100644 index 0000000000..db263c40d1 --- /dev/null +++ b/nuttx/include/nuttx/usb/usbhost_trace.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * include/nuttx/usb/usbhost_trace.h + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_USB_USBHOST_TRACE_H +#define __INCLUDE_NUTTX_USB_USBHOST_TRACE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* NOTE: Trace debug capability has not been implemented for USB host. It + * should be a simple port of the USB device trace logic. But that has not + * yet been done. + */ + +/**************************************************************************** + * Preprocessor definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" { +#else +# define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_USB_USBHOST_TRACE_H */ diff --git a/nuttx/include/nuttx/usb/usbmsc.h b/nuttx/include/nuttx/usb/usbmsc.h new file mode 100644 index 0000000000..325c665c54 --- /dev/null +++ b/nuttx/include/nuttx/usb/usbmsc.h @@ -0,0 +1,259 @@ +/************************************************************************************ + * include/nuttx/usb/usbmsc.h + * + * Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * NOTE: This interface was inspired by the Linux gadget interface by + * David Brownell. That work was very helpful in determining a usable + * partitioning of functionality between standard class drivers and various + * implementations of USB controller drivers. This work, however, does + * not derive directly from that work and is licensed differently. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef _INCLUDE_NUTTX_USB_USBMSC_H +#define _INCLUDE_NUTTX_USB_USBMSC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + + /************************************************************************************ + * Public Data + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" +{ +#else +# define EXTERN extern +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: board_mscclassobject + * + * Description: + * If the mass storage class driver is part of composite device, then + * its instantiation and configuration is a multi-step, board-specific, + * process (See comments for usbmsc_configure below). In this case, + * board-specific logic must provide board_mscclassobject(). + * + * board_mscclassobject() is called from the composite driver. It must + * encapsulate the instantiation and configuration of the mass storage + * class and the return the mass storage device's class driver instance + * to the composite dirver. + * + * Input Parameters: + * classdev - The location to return the mass storage class' device + * instance. + * + * Returned Value: + * 0 on success; a negated errno on failure + * + ************************************************************************************/ + +#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_USBMSC_COMPOSITE) +struct usbdevclass_driver_s; +EXTERN int board_mscclassobject(FAR struct usbdevclass_driver_s **classdev); +#endif + +/**************************************************************************** + * Name: board_mscuninitialize + * + * Description: + * Un-initialize the USB storage class driver. This is just an application- + * specific wrapper aboutn usbmsc_unitialize() that is called form the composite + * device logic. + * + * Input Parameters: + * classdev - The class driver instrance previously give to the composite + * driver by board_mscclassobject(). + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_USBMSC_COMPOSITE) +struct usbdevclass_driver_s; +EXTERN void board_mscuninitialize(FAR struct usbdevclass_driver_s *classdev); +#endif + +/************************************************************************************ + * Name: usbmsc_configure + * + * Description: + * One-time initialization of the USB storage driver. The initialization + * sequence is as follows: + * + * 1. Call usbmsc_configure to perform one-time initialization specifying + * the number of luns. + * 2. Call usbmsc_bindlun to configure each supported LUN + * 3. Call usbmsc_exportluns when all LUNs are configured + * + * Input Parameters: + * nluns - the number of LUNs that will be registered + * handle - Location to return a handle that is used in other API calls. + * + * Returned Value: + * 0 on success; a negated errno on failure. The returned handle value is + * an untyped equivalent to the usbmsc_classobject() or board_mscclassobject(). + * + ************************************************************************************/ + +EXTERN int usbmsc_configure(unsigned int nluns, void **handle); + +/************************************************************************************ + * Name: usbmsc_bindlun + * + * Description: + * Bind the block driver specified by drvrpath to a USB storage LUN. + * + * Input Parameters: + * handle - The handle returned by a previous call to usbmsc_configure(). + * drvrpath - the full path to the block driver + * startsector - A sector offset into the block driver to the start of the + * partition on drvrpath (0 if no partitions) + * nsectors - The number of sectors in the partition (if 0, all sectors + * to the end of the media will be exported). + * lunno - the LUN to bind to + * + * Returned Value: + * 0 on success; a negated errno on failure. + * + ************************************************************************************/ + +EXTERN int usbmsc_bindlun(FAR void *handle, FAR const char *drvrpath, + unsigned int lunno, off_t startsector, size_t nsectors, + bool readonly); + +/************************************************************************************ + * Name: usbmsc_unbindlun + * + * Description: + * Un-bind the block driver for the specified LUN + * + * Input Parameters: + * handle - The handle returned by a previous call to usbmsc_configure(). + * lun - the LUN to unbind from + * + * Returned Value: + * 0 on success; a negated errno on failure. + * + ************************************************************************************/ + +EXTERN int usbmsc_unbindlun(FAR void *handle, unsigned int lunno); + +/************************************************************************************ + * Name: usbmsc_exportluns + * + * Description: + * After all of the LUNs have been bound, this function may be called in order to + * export those LUNs in the USB storage device. + * + * Input Parameters: + * handle - The handle returned by a previous call to usbmsc_configure(). + * + * Returned Value: + * 0 on success; a negated errno on failure + * + ************************************************************************************/ + +#if !defined(CONFIG_USBDEV_COMPOSITE) || !defined(CONFIG_USBMSC_COMPOSITE) +EXTERN int usbmsc_exportluns(FAR void *handle); +#endif + +/************************************************************************************ + * Name: usbmsc_classobject + * + * Description: + * Register USB mass storage device and return the class object. + * + * Input Parameters: + * classdev - The location to return the CDC serial class' device + * instance. + * + * Returned Value: + * 0 on success; a negated errno on failure + + * + ************************************************************************************/ + +#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_USBMSC_COMPOSITE) +struct usbdevclass_driver_s; +EXTERN int usbmsc_classobject(FAR void *handle, FAR struct usbdevclass_driver_s **classdev); +#endif + +/************************************************************************************ + * Name: usbmsc_uninitialize + * + * Description: + * Un-initialize the USB storage class driver. The handle is the USB MSC + * class' device object. This is the same value as returned by usbmsc_classobject + * (typed) or by usbmsc_configure (untyped). + * + * Input Parameters: + * handle - The handle returned by a previous call to usbmsc_configure() + * (or usbmsc_classobject()). + * + * Returned Value: + * None + * + ***********************************************************************************/ + +EXTERN void usbmsc_uninitialize(FAR void *handle); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* _INCLUDE_NUTTX_USB_USBMSC_H */ diff --git a/nuttx/include/nuttx/vt100.h b/nuttx/include/nuttx/vt100.h new file mode 100644 index 0000000000..a0254e88a6 --- /dev/null +++ b/nuttx/include/nuttx/vt100.h @@ -0,0 +1,250 @@ +/******************************************************************************************** + * include/nuttx/vt100.h + * VT100 Escape Sequences + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_VT100_H +#define __INCLUDE_NUTTX_VT100_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ + +#define VT100_SETNL {ASCII_ESC, '[', '2', '0', 'h'} /* Set new line mode */ +#define VT100_SETAPPL {ASCII_ESC, '[', '?', '1', 'h'} /* Set cursor key to application */ +#define VT100_SETCOL {ASCII_ESC, '[', '?', '3', 'h'} /* Set number of columns to 132 */ +#define VT100_SETSMOOTH {ASCII_ESC, '[', '?', '4', 'h'} /* Set smooth scrolling */ +#define VT100_SETREVSCRN {ASCII_ESC, '[', '?', '5', 'h'} /* Set reverse video on screen */ +#define VT100_SETORGREL {ASCII_ESC, '[', '?', '6', 'h'} /* Set origin to relative */ +#define VT100_SETWRAP {ASCII_ESC, '[', '?', '7', 'h'} /* Set auto-wrap mode */ +#define VT100_SETREP {ASCII_ESC, '[', '?', '8', 'h'} /* Set auto-repeat mode */ +#define VT100_SETINTER {ASCII_ESC, '[', '?', '9', 'h'} /* Set interlacing mode */ + +#define VT100_SETLF {ASCII_ESC, '[', '2', '0', 'l'} /* Set line feed mode */ +#define VT100_SETCURSOR {ASCII_ESC, '[', '?', '1', 'l'} /* Set cursor key to cursor */ +#define VT100_SETVT52 {ASCII_ESC, '[', '?', '2', 'l'} /* Set VT52 (versus ANSI) */ +#define VT100_RESETCOL {ASCII_ESC, '[', '?', '3', 'l'} /* Set number of columns to 80 */ +#define VT100_SETJUMP {ASCII_ESC, '[', '?', '4', 'l'} /* Set jump scrolling */ +#define VT100_SETNORMSCRN {ASCII_ESC, '[', '?', '5', 'l'} /* Set normal video on screen */ +#define VT100_SETORGABS {ASCII_ESC, '[', '?', '6', 'l'} /* Set origin to absolute */ +#define VT100_RESETWRAP {ASCII_ESC, '[', '?', '7', 'l'} /* Reset auto-wrap mode */ +#define VT100_RESETREP {ASCII_ESC, '[', '?', '8', 'l'} /* Reset auto-repeat mode */ +#define VT100_RESETINTER {ASCII_ESC, '[', '?', '9', 'l'} /* Reset interlacing mode */ + +#define VT100_ALTKEYPAD {ASCII_ESC, '='} /* Set alternate keypad mode */ +#define VT100_NUMKEYPAD {ASCII_ESC, '>'} /* Set numeric keypad mode */ + +#define VT100_SETUKG0 {ASCII_ESC, '(', 'A'} /* Set United Kingdom G0 character set */ +#define VT100_SETUKG1 {ASCII_ESC, ')', 'A'} /* Set United Kingdom G1 character set */ +#define VT100_SETUSG0 {ASCII_ESC, '(', 'B'} /* Set United States G0 character set */ +#define VT100_SETUSG1 {ASCII_ESC, ')', 'B'} /* Set United States G1 character set */ +#define VT100_SETSPECG0 {ASCII_ESC, '(', '0'} /* Set G0 special chars. & line set */ +#define VT100_SETSPECG1 {ASCII_ESC, ')', '0'} /* Set G1 special chars. & line set */ +#define VT100_SETALTG0 {ASCII_ESC, '(', '1'} /* Set G0 alternate character ROM */ +#define VT100_SETALTG1 {ASCII_ESC, ')', '1'} /* Set G1 alternate character ROM */ +#define VT100_SETALTSPECG0 {ASCII_ESC, '(', '2'} /* Set G0 alt char ROM and spec. graphics */ +#define VT100_SETALTSPECG1 {ASCII_ESC, ')', '2'} /* Set G1 alt char ROM and spec. graphics */ + +#define VT100_SETSS2 {ASCII_ESC, 'N'} /* Set single shift 2 */ +#define VT100_SETSS3 {ASCII_ESC, 'O'} /* Set single shift 3 */ + +#define VT100_MODESOFF {ASCII_ESC, '[', 'm'} /* Turn off character attributes */ +#define VT100_MODESOFF_ {ASCII_ESC, '[', '0', 'm'} /* Turn off character attributes */ +#define VT100_BOLD {ASCII_ESC, '[', '1', 'm'} /* Turn bold mode on */ +#define VT100_LOWINT {ASCII_ESC, '[', '2', 'm'} /* Turn low intensity mode on */ +#define VT100_UNDERLINE {ASCII_ESC, '[', '4', 'm'} /* Turn underline mode on */ +#define VT100_BLINK {ASCII_ESC, '[', '5', 'm'} /* Turn blinking mode on */ +#define VT100_REVERSE {ASCII_ESC, '[', '7', 'm'} /* Turn reverse video on */ +#define VT100_INVISIBLE {ASCII_ESC, '[', '8', 'm'} /* Turn invisible text mode on */ + +#define VT100_SETWIN(t,b) {ASCII_ESC, '[', (t), ';', (b), 'r'} /* Set top and bottom line#s of a window */ + +#define VT100_CURSORUP(n) {ASCII_ESC, '[', (n), 'A'} /* Move cursor up n lines */ +#define VT100_CURSORDN(n) {ASCII_ESC, '[', (n), 'B'} /* Move cursor down n lines */ +#define VT100_CURSORRT(n) {ASCII_ESC, '[', (n), 'C'} /* Move cursor right n lines */ +#define VT100_CURSORLF(n) {ASCII_ESC, '[', (n), 'D'} /* Move cursor left n lines */ +#define VT100_CURSORHOME {ASCII_ESC, '[', 'H'} /* Move cursor to upper left corner */ +#define VT100_CURSORHOME_ {ASCII_ESC, '[', ';', 'H'} /* Move cursor to upper left corner */ +#define VT100_CURSORPOS(v,h) {ASCII_ESC, '[', (v), ';', (h), 'H'} /* Move cursor to screen location v,h */ + +#define VT100_HVHOME {ASCII_ESC, '[', 'f'} /* Move cursor to upper left corner */ +#define VT100_HVHOME_ {ASCII_ESC, '[', ;', 'f'} /* Move cursor to upper left corner */ +#define VT100_HVPOS(v,h) {ASCII_ESC, '[', (v), ';', (h), 'f'} /* Move cursor to screen location v,h */ +#define VT100_INDEX {ASCII_ESC, 'D'} /* Move/scroll window up one line */ +#define VT100_REVINDEX {ASCII_ESC, 'M'} /* Move/scroll window down one line */ +#define VT100_NEXTLINE {ASCII_ESC, 'E'} /* Move to next line */ +#define VT100_SAVECURSOR {ASCII_ESC, '7'} /* Save cursor position and attributes */ +#define VT100_RESTORECURSOR {ASCII_ESC, '8'} /* Restore cursor position and attribute */ + +#define VT100_TABSET {ASCII_ESC, 'H'} /* Set a tab at the current column */ +#define VT100_TABCLR {ASCII_ESC, '[', 'g'} /* Clear a tab at the current column */ +#define VT100_TABCLR_ {ASCII_ESC, '[', '0', 'g'} /* Clear a tab at the current column */ +#define VT100_TABCLRALL {ASCII_ESC, '[', '3', 'g'} /* Clear all tabs */ + +#define VT100_DHTOP {ASCII_ESC, '#', '3'} /* Double-height letters, top half */ +#define VT100_DHBOT {ASCII_ESC, '#', '4'} /* Double-height letters, bottom hal */ +#define VT100_SWSH {ASCII_ESC, '#', '5'} /* Single width, single height letters */ +#define VT100_DWSH {ASCII_ESC, '#', '6'} /* Double width, single height letters */ + +#define VT100_CLEAREOL {ASCII_ESC, '[', 'K'} /* Clear line from cursor right */ +#define VT100_CLEAREOL_ {ASCII_ESC, '[', '0', 'K'} /* Clear line from cursor right */ +#define VT100_CLEARBOL {ASCII_ESC, '[', '1', 'K'} /* Clear line from cursor left */ +#define VT100_CLEARLINE {ASCII_ESC, '[', '2', 'K'} /* Clear entire line */ + +#define VT100_CLEAREOS {ASCII_ESC, '[', 'J'} /* Clear screen from cursor down */ +#define VT100_CLEAREOS_ {ASCII_ESC, '[', '0', 'J'} /* Clear screen from cursor down */ +#define VT100_CLEARBOS {ASCII_ESC, '[', '1', 'J'} /* Clear screen from cursor up */ +#define VT100_CLEARSCREEN {ASCII_ESC, '[', '2', 'J'} /* Clear entire screen */ + +#define VT100_DEVSTAT {ASCII_ESC, '5', 'n'} /* Device status report */ +#define VT100_TERMOK {ASCII_ESC, '0', 'n'} /* Response: terminal is OK */ +#define VT100_TERMNOK {ASCII_ESC, '3', 'n'} /* Response: terminal is not OK */ + +#define VT100_GETCURSOR {ASCII_ESC, '6', 'n'} /* Get cursor position */ +#define VT100_CURSORPOS {ASCII_ESC, (v), ';', (h), 'R'} /* Response: cursor is at v,h */ + +#define VT100_IDENT {ASCII_ESC, '[', 'c'} /* Identify what terminal type */ +#define VT100_IDENT_ {ASCII_ESC, '[', '0', 'c'} /* Identify what terminal type */ +#define VT100_GETTYPE {ASCII_ESC, '[', '?', '1', ';', (n), '0', 'c'} /* Response: terminal type code n */ + +#define VT100_RESET RIS {ASCII_ESC, 'c'} /* Reset terminal to initial state */ + +#define VT100_ALIGN {ASCII_ESC, '#', '8'} /* Screen alignment display */ +#define VT100_TESTPU {ASCII_ESC, '[', '2', ';', '1', 'y'} /* Confidence power up test */ +#define VT100_TESTLB {ASCII_ESC, '[', '2', ';', '2', 'y'} /* Confidence loopback test */ +#define VT100_TESTPUREP {ASCII_ESC, '[', '2', ';', '9', 'y'} /* Repeat power up test */ +#define VT100_TESTLBREP {ASCII_ESC, '[', '2', ';', '1', '0', 'y'} /* Repeat loopback test */ + +#define VT100_LEDSOFF {ASCII_ESC, '[', '0', 'q'} /* Turn off all four leds */ +#define VT100_LED1 {ASCII_ESC, '[', '1', 'q'} /* Turn on LED #1 */ +#define VT100_LED2 {ASCII_ESC, '[', '2', 'q'} /* Turn on LED #2 */ +#define VT100_LED3 {ASCII_ESC, '[', '3', 'q'} /* Turn on LED #3 */ +#define VT100_LED4 {ASCII_ESC, '[', '4', 'q'} /* Turn on LED #4 */ + +/* All codes below are for use in VT52 compatibility mode. */ + +#define VT52_SETANSI {ASCII_ESC, '<'} /* Enter/exit ANSI mode */ + +#define VT52_ALTKEYPAD {ASCII_ESC, '='} /* Enter alternate keypad mode */ +#define VT52_NUMKEYPAD {ASCII_ESC, '>'} /* Exit alternate keypad mode */ + +#define VT52_SETGR {ASCII_ESC, 'F'} /* Use special graphics character set */ +#define VT52_RESETGR {ASCII_ESC, 'G'} /* Use normal US/UK character set */ + +#define VT52_CURSORUP {ASCII_ESC, 'A'} /* Move cursor up one line */ +#define VT52_CURSORDN {ASCII_ESC, 'B'} /* Move cursor down one line */ +#define VT52_CURSORRT {ASCII_ESC, 'C'} /* Move cursor right one char */ +#define VT52_CURSORLF {ASCII_ESC, 'D'} /* Move cursor left one char */ +#define VT52_CURSORHOME {ASCII_ESC, 'H'} /* Move cursor to upper left corner */ +#define VT52_CURSORPOS(v,h) {ASCII_ESC, (v), (h)} /* Move cursor to v,h location */ +#define VT52_REVINDEX {ASCII_ESC, 'I'} /* Generate a reverse line-feed */ + +#define VT52_CLEAREOL {ASCII_ESC, 'K'} /* Erase to end of current line */ +#define VT52_CLEAREOS {ASCII_ESC, 'J'} /* Erase to end of screen */ + +#define VT52_IDENT {ASCII_ESC, 'Z'} /* dentify what the terminal is */ +#define VT52_IDENTRESP {ASCII_ESC, '/', 'Z'} /* Correct response to ident */ + +/* VT100 Special Key Codes + * + * These are sent from the terminal back to the computer when the particular + * key is pressed. Note that the numeric keypad keys send different codes + * in numeric mode than in alternate mode. + */ + +/* Function Keys */ + +#define VT100_PF1 {ASCII_ESC, 'O', 'P'} +#define VT100_PF2 {ASCII_ESC, 'O', 'Q'} +#define VT100_PF3 {ASCII_ESC, 'O', 'R'} +#define VT100_PF4 {ASCII_ESC, 'O', 'S'} + + +/* Arrow keys */ + +#define VT100_UP_RESET {ASCII_ESC, 'A'} +#define VT100_UP_SET {ASCII_ESC, 'O', 'A'} +#define VT100_DOWN_RESET {ASCII_ESC, 'B'} +#define VT100_DOWN_SET {ASCII_ESC, 'O', 'B'} +#define VT100_RIGHT_RESET {ASCII_ESC, 'C'} +#define VT100_RIGHT_SET {ASCII_ESC, 'O', 'C'} +#define VT100_LEFT_RESET {ASCII_ESC, 'D'} +#define VT100_LEFT_SET {ASCII_ESC, 'O', 'D'} + +/* Numeric Keypad Keys */ + +#define VT100_NUMERIC_0 {'0'} +#define VT100_ALT_0 {ASCII_ESC, 'O', 'p'} +#define VT100_NUMERIC_1 {'1'} +#define VT100_ALT_1 {ASCII_ESC, 'O', 'q'} +#define VT100_NUMERIC_2 {'2'} +#define VT100_ALT_2 {ASCII_ESC, 'O', 'r'} +#define VT100_NUMERIC_3 {'3'} +#define VT100_ALT_3 {ASCII_ESC, 'O', 's'} +#define VT100_NUMERIC_4 {'4'} +#define VT100_ALT_4 {ASCII_ESC, 'O', 't'} +#define VT100_NUMERIC_5 {'5'} +#define VT100_ALT_5 {ASCII_ESC, 'O', 'u'} +#define VT100_NUMERIC_6 {'6'} +#define VT100_ALT_6 {ASCII_ESC, 'O', 'v'} +#define VT100_NUMERIC_7 {'7'} +#define VT100_ALT_7 {ASCII_ESC, 'O', 'w'} +#define VT100_NUMERIC_8 {'8'} +#define VT100_ALT_8 {ASCII_ESC, 'O', 'x'} +#define VT100_NUMERIC_9 {'9', +#define VT100_ALT_9 {ASCII_ESC, 'O', 'y'} +#define VT100_NUMERIC_MINUS {'-'} +#define VT100_ALT_MINUS {ASCII_ESC, 'O', 'm'} +#define VT100_NUMERIC_COMMA {','} +#define VT100_ALT_COMMA {ASCII_ESC, 'O', 'l'} +#define VT100_NUMERIC_PERIOD {'.'} +#define VT100_ALT_PERIOD {ASCII_ESC, 'O', 'n'} +#define VT100_NUMERIC_ENTER {ASCII_CR} +#define VT100_ALT_ENTER {ASCII_ESC, 'O', 'M'} + +/******************************************************************************************** + * Public Data + ********************************************************************************************/ + +/******************************************************************************************** + * Public Function Prototypes + ********************************************************************************************/ + +#endif /* __INCLUDE_NUTTX_VT100_H */ diff --git a/nuttx/include/nuttx/watchdog.h b/nuttx/include/nuttx/watchdog.h new file mode 100755 index 0000000000..bcf8b1522f --- /dev/null +++ b/nuttx/include/nuttx/watchdog.h @@ -0,0 +1,293 @@ +/**************************************************************************** + * include/nuttx/watchdog.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_WATCHDOG_H +#define __INCLUDE_NUTTX_WATCHDOG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#ifdef CONFIG_WATCHDOG + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* IOCTL Commands ***********************************************************/ +/* The watchdog driver uses a standard character driver framework. However, + * since the watchdog driver is a device control interface and not a data + * transfer interface, the majority of the functionality is implemented in + * driver ioctl calls. The watchdog ioctl commands are lised below: + * + * These are detected and handled by the "upper half" watchdog timer driver. + * + * WDIOC_START - Start the watchdog timer + * Argument: Ignored + * WDIOC_STOP - Stop the watchdog timer + * Argument: Ignored + * WDIOC_GETSTATUS - Get the status of the watchdog timer. + * Argument: A writeable pointer to struct watchdog_status_s. + * WDIOC_SETTIMEOUT - Reset the watchdog timeout to this value + * Argument: A 32-bit timeout value in milliseconds. + * WDIOC_CAPTURE - Do not reset. Instead, called this handler. + * Argument: A pointer to struct watchdog_capture_s. + * WDIOC_KEEPALIVE - Reset the watchdog timer ("ping", "pet the dog"); + * Argument: Ignored + * + * These may be supported by certain "lower half" drivers + * + * WDIOC_MINTIME - Set the minimum ping time. If two keepalive ioctls + * are received within this time, a reset event will + * be generated. This feature should assume to be + * disabled after WDIOC_SETTIMEOUT. + * Argument: A 32-bit time value in milliseconds. + */ + +#define WDIOC_START _WDIOC(0x001) +#define WDIOC_STOP _WDIOC(0x002) +#define WDIOC_GETSTATUS _WDIOC(0x003) +#define WDIOC_SETTIMEOUT _WDIOC(0x004) +#define WDIOC_CAPTURE _WDIOC(0x005) +#define WDIOC_KEEPALIVE _WDIOC(0x006) + +#define WDIOC_MINTIME _WDIOC(0x080) + +/* Bit Settings *************************************************************/ +/* Bit settings for the struct watchdog_status_s flags field */ + +#define WDFLAGS_ACTIVE (1 << 0) /* 1=The watchdog timer is running */ +#define WDFLAGS_RESET (1 << 1) /* 1=Reset when the watchog timer expires */ +#define WDFLAGS_CAPTURE (1 << 2) /* 1=Call the user function when the + * watchdog timer expires */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* This is the type of the argument passed to the WDIOC_CAPTURE ioctl */ + +struct watchdog_capture_s +{ + CODE xcpt_t newhandler; /* The new watchdog capture handler */ + CODE xcpt_t oldhandler; /* The previous watchdog capture handler (if any) */ +}; + +/* This is the type of the argument passed to the WDIOC_GETSTATUS ioctl and + * and returned by the "lower half" getstatus() method. + */ + +struct watchdog_status_s +{ + uint32_t flags; /* See WDFLAGS_* definitions above */ + uint32_t timeout; /* The current timeout setting (in milliseconds) */ + uint32_t timeleft; /* Time left until the watchdog expiration + * (in milliseconds) */ +}; + +/* This structure provides the "lower-half" driver operations available to + * the "upper-half" driver. + */ + +struct watchdog_lowerhalf_s; +struct watchdog_ops_s +{ + /* Required methods ********************************************************/ + /* Start the watchdog timer, resetting the time to the current timeout */ + + CODE int (*start)(FAR struct watchdog_lowerhalf_s *lower); + + /* Stop the watchdog timer */ + + CODE int (*stop)(FAR struct watchdog_lowerhalf_s *lower); + + /* Optional methods ********************************************************/ + /* Reset the watchdog timer to the current timeout value, prevent any + * imminent watchdog timeouts. This is sometimes referred as "pinging" the + * watchdog timer or "petting the dog". + */ + + CODE int (*keepalive)(FAR struct watchdog_lowerhalf_s *lower); + + /* Get the current watchdog timer status */ + + CODE int (*getstatus)(FAR struct watchdog_lowerhalf_s *lower, + FAR struct watchdog_status_s *status); + + /* Set a new timeout value (and reset the watchdog timer) */ + + CODE int (*settimeout)(FAR struct watchdog_lowerhalf_s *lower, + uint32_t timeout); + + /* Don't reset on watchdog timer timeout; instead, call this user provider + * timeout handler. NOTE: Providing handler==NULL will restore the reset + * behavior. + */ + + CODE xcpt_t (*capture)(FAR struct watchdog_lowerhalf_s *lower, + CODE xcpt_t handler); + + /* Any ioctl commands that are not recognized by the "upper-half" driver + * are forwarded to the lower half driver through this method. + */ + + CODE int (*ioctl)(FAR struct watchdog_lowerhalf_s *lower, int cmd, + unsigned long arg); +}; + +/* This structure provides the publicly visible representation of the + * "lower-half" driver state structure. "lower half" drivers will have an + * internal structure definition that will be cast-compatible with this + * structure definitions. + */ + +struct watchdog_lowerhalf_s +{ + /* Publicly visible portion of the "lower-half" driver state structure. */ + + FAR const struct watchdog_ops_s *ops; /* Lower half operations */ + + /* The remainder of the structure is used by the "lower-half" driver + * for whatever state storage that it may need. + */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * "Upper-Half" Watchdog Driver Interfaces + ****************************************************************************/ +/**************************************************************************** + * Name: watchdog_register + * + * Description: + * This function binds an instance of a "lower half" watchdog driver with the + * "upper half" watchdog device and registers that device so that can be used + * by application code. + * + * When this function is called, the "lower half" driver should be in the + * disabled state (as if the stop() method had already been called). + * + * NOTE: Normally, this function would not be called by application code. + * Rather it is called indirectly through the architecture-specific + * interface up_wdginitialize() described below. + * + * Input parameters: + * dev path - The full path to the driver to be registers in the NuttX + * pseudo-filesystem. The recommended convention is to name all watchdog + * drivers as "/dev/watchdog0", "/dev/watchdog1", etc. where the driver + * path differs only in the "minor" number at the end of the device name. + * lower - A pointer to an instance of lower half watchdog driver. This + * instance is bound to the watchdog driver and must persists as long as + * the driver persists. + * + * Returned Value: + * On success, a non-NULL handle is returned to the caller. In the event + * of any failure, a NULL value is returned. + * + ****************************************************************************/ + +EXTERN FAR void *watchdog_register(FAR const char *path, + FAR struct watchdog_lowerhalf_s *lower); + +/**************************************************************************** + * Name: watchdog_unregister + * + * Description: + * This function can be called to disable and unregister the watchdog + * device driver. + * + * Input parameters: + * handle - This is the handle that was returned by watchdog_register() + * + * Returned Value: + * None + * + ****************************************************************************/ + +EXTERN void watchdog_unregister(FAR void *handle); + +/**************************************************************************** + * Platform-Independent "Lower-Half" Watchdog Driver Interfaces + ****************************************************************************/ + +/**************************************************************************** + * Architecture-specific Application Interfaces + ****************************************************************************/ + +/**************************************************************************** + * Name: up_wdginitialize() + * + * Description: + * Perform architecture-specific initialization of the Watchdog hardware. + * This interface should be provided by all configurations using + * to avoid exposed platform-dependent logic. + * + * At a minimum, this function should all watchdog_register() which is + * described above. + * + * Input parameters: + * None + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +EXTERN int up_wdginitialize(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_WATCHDOG */ +#endif /* __INCLUDE_NUTTX_WATCHDOG_H */ diff --git a/nuttx/include/nuttx/wireless/cc1101.h b/nuttx/include/nuttx/wireless/cc1101.h new file mode 100644 index 0000000000..9d6b2a6736 --- /dev/null +++ b/nuttx/include/nuttx/wireless/cc1101.h @@ -0,0 +1,464 @@ +/**************************************************************************** + * include/nuttx/wireless/cc1101.h + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * + * Authors: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** \file + * \author Uros Platise + * \brief Chipcon CC1101 Device Driver + **/ + +#ifndef __INCLUDE_NUTTX_WIRELESS_CC1101_H +#define __INCLUDE_NUTTX_WIRELESS_CC1101_H + +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Declarations + ****************************************************************************/ + +/* Present maximum packet length */ + +#define CC1101_PACKET_MAXTOTALLEN 63 +#define CC1101_PACKET_MAXDATALEN 61 + +/* + * General Purpose, Test Output Pin Options + */ + +/* CC1101 General Purpose Pins */ + +#define CC1101_PIN_GDO0 2 +#define CC1101_PIN_GDO1 1 +#define CC1101_PIN_GDO2 0 + +/* Associated to the RX FIFO: Asserts when RX FIFO is filled at or above + * the RX FIFO threshold. De-asserts when RX FIFO is drained below the + * same threshold. */ +#define CC1101_GDO_RXFIFO_THR 0x00 + +/* Associated to the RX FIFO: Asserts when RX FIFO is filled at or above + * the RX FIFO threshold or the end of packet is reached. De-asserts when + * the RX FIFO is empty. */ +#define CC1101_GDO_RXFIFO_THREND 0x01 + +/* Associated to the TX FIFO: Asserts when the TX FIFO is filled at or + * above the TX FIFO threshold. De-asserts when the TX FIFO is below the + * same threshold. */ +#define CC1101_GDO_TXFIFO_THR 0x02 + +/* Associated to the TX FIFO: Asserts when TX FIFO is full. De-asserts + * when the TX FIFO is drained below theTX FIFO threshold. */ +#define CC1101_GDO_TXFIFO_FULL 0x03 + +/* Asserts when the RX FIFO has overflowed. De-asserts when the FIFO has + * been flushed. */ +#define CC1101_GDO_RXFIFO_OVR 0x04 + +/* Asserts when the TX FIFO has underflowed. De-asserts when the FIFO is + * flushed. */ +#define CC1101_GDO_TXFIFO_UNR 0x05 + +/* Asserts when sync word has been sent / received, and de-asserts at the + * end of the packet. In RX, the pin will de-assert when the optional + * address check fails or the RX FIFO overflows. In TX the pin will + * de-assert if the TX FIFO underflows. */ +#define CC1101_GDO_SYNC 0x06 + +/* Asserts when a packet has been received with CRC OK. De-asserts when + * the first byte is read from the RX FIFO. */ +#define CC1101_GDO_PKTRCV_CRCOK 0x07 + +/* Preamble Quality Reached. Asserts when the PQI is above the programmed + * PQT value. */ +#define CC1101_GDO_PREAMBLE 0x08 + +/* Clear channel assessment. High when RSSI level is below threshold + * (dependent on the current CCA_MODE setting). */ +#define CC1101_GDO_CHCLEAR 0x09 + +/* Lock detector output. The PLL is in lock if the lock detector output + * has a positive transition or is constantly logic high. To check for + * PLL lock the lock detector output should be used as an interrupt for + * the MCU. */ +#define CC1101_GDO_LOCK 0x0A + +/* Serial Clock. Synchronous to the data in synchronous serial mode. + * In RX mode, data is set up on the falling edge by CC1101 when GDOx_INV=0. + * In TX mode, data is sampled by CC1101 on the rising edge of the serial + * clock when GDOx_INV=0. */ +#define CC1101_GDO_SSCLK 0x0B + +/* Serial Synchronous Data Output. Used for synchronous serial mode. */ +#define CC1101_GDO_SSDO 0x0C + +/* Serial Data Output. Used for asynchronous serial mode. */ +#define CC1101_GDO_ASDO 0x0D + +/* Carrier sense. High if RSSI level is above threshold. */ +#define CC1101_GDO_CARRIER 0x0E + +/* CRC_OK. The last CRC comparison matched. Cleared when entering or + * restarting RX mode. */ +#define CC1101_GDO_CRCOK 0x0F + +/* RX_HARD_DATA[1]. Can be used together with RX_SYMBOL_TICK for + * alternative serial RX output. */ +#define CC1101_GDO_RXOUT1 0x16 + +/* RX_HARD_DATA[0]. Can be used together with RX_SYMBOL_TICK for + * alternative serial RX output. */ +#define CC1101_GDO_RXOUT0 0x17 + +/* PA_PD. Note: PA_PD will have the same signal level in SLEEP and TX + * states. To control an external PA or RX/TX switch in applications + * where the SLEEP state is used it is recommended to use GDOx_CFGx=0x2F + * instead. */ +#define CC1101_GDO_PA_PD 0x1B + +/* LNA_PD. Note: LNA_PD will have the same signal level in SLEEP and RX + * states. To control an external LNA or RX/TX switch in applications + * where the SLEEP state is used it is recommended to use GDOx_CFGx=0x2F + * instead. */ +#define CC1101_GDO_LNA_PD 0x1C + +/* RX_SYMBOL_TICK. Can be used together with RX_HARD_DATA for alternative + * serial RX output. */ +#define CC1101_GDO_RXSYMTICK 0x1D + +#define CC1101_GDO_WOR_EVNT0 0x24 +#define CC1101_GDO_WOR_EVNT1 0x25 +#define CC1101_GDO_CLK32K 0x27 +#define CC1101_GDO_CHIP_RDYn 0x29 +#define CC1101_GDO_XOSC_STABLE 0x2B + +/* GDO0_Z_EN_N. When this output is 0, GDO0 is configured as input + * (for serial TX data). */ +#define CC1101_GDO_GDO0_Z_EN_N 0x2D + +/* High impedance (3-state). */ +#define CC1101_GDO_HIZ 0x2E + +/* HW to 0 (HW1 achieved by setting GDOx_INV=1). Can be used to control + * an external LNA/PA or RX/TX switch. */ +#define CC1101_GDO_HW 0x2F + +/* There are 3 GDO pins, but only one CLK_XOSC/n can be selected as an + * output at any time. If CLK_XOSC/n is to be monitored on one of the + * GDO pins, the other two GDO pins must be configured to values less + * than 0x30. The GDO0 default value is CLK_XOSC/192. To optimize RF + * performance, these signals should not be used while the radio is + * in RX or TX mode. */ +#define CC1101_GDO_CLK_XOSC1 0x30 +#define CC1101_GDO_CLK_XOSC1_5 0x31 +#define CC1101_GDO_CLK_XOSC2 0x32 +#define CC1101_GDO_CLK_XOSC3 0x33 +#define CC1101_GDO_CLK_XOSC4 0x34 +#define CC1101_GDO_CLK_XOSC6 0x35 +#define CC1101_GDO_CLK_XOSC8 0x36 +#define CC1101_GDO_CLK_XOSC12 0x37 +#define CC1101_GDO_CLK_XOSC16 0x38 +#define CC1101_GDO_CLK_XOSC24 0x39 +#define CC1101_GDO_CLK_XOSC32 0x3A +#define CC1101_GDO_CLK_XOSC48 0x3B +#define CC1101_GDO_CLK_XOSC64 0x3C +#define CC1101_GDO_CLK_XOSC96 0x3D +#define CC1101_GDO_CLK_XOSC128 0x3E +#define CC1101_GDO_CLK_XOSC192 0x3F + + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Data Types + ****************************************************************************/ + +struct cc1101_dev_s; + +/** The RF Settings includes only those fields required to configure + * the RF radio. Other configuration fields depended on this driver + * are configured by the cc1101_init(). + */ +struct c1101_rfsettings_s { + uint8_t FSCTRL1; /* Frequency synthesizer control. */ + uint8_t FSCTRL0; /* Frequency synthesizer control. */ + + uint8_t FREQ2; /* Frequency control word, high byte. */ + uint8_t FREQ1; /* Frequency control word, middle byte. */ + uint8_t FREQ0; /* Frequency control word, low byte. */ + + uint8_t MDMCFG4; /* Modem configuration. */ + uint8_t MDMCFG3; /* Modem configuration. */ + uint8_t MDMCFG2; /* Modem configuration. */ + uint8_t MDMCFG1; /* Modem configuration. */ + uint8_t MDMCFG0; /* Modem configuration. */ + + uint8_t DEVIATN; /* Modem deviation setting (when FSK modulation is enabled). */ + + /* GAP */ + + uint8_t FOCCFG; /* Frequency Offset Compensation Configuration. */ + + uint8_t BSCFG; /* Bit synchronization Configuration. */ + + uint8_t AGCCTRL2; /* AGC control. */ + uint8_t AGCCTRL1; /* AGC control. */ + uint8_t AGCCTRL0; /* AGC control. */ + + /* GAP */ + + uint8_t FREND1; /* Front end RX configuration. */ + uint8_t FREND0; /* Front end RX configuration. */ + + uint8_t FSCAL3; /* Frequency synthesizer calibration. */ + uint8_t FSCAL2; /* Frequency synthesizer calibration. */ + uint8_t FSCAL1; /* Frequency synthesizer calibration. */ + uint8_t FSCAL0; /* Frequency synthesizer calibration. */ + + /* REGULATORY LIMITS */ + + uint8_t CHMIN; /* Channel Range defintion MIN .. */ + uint8_t CHMAX; /* .. and MAX */ + uint8_t PAMAX; /* at given maximum output power */ + + /* Power Table, for ramp-up/down and ASK modulation defined for + * output power values as: + * PA = {-30, -20, -15, -10, -5, 0, 5, 10} [dBm] + */ + uint8_t PA[8]; +}; + + +/**************************************************************************** + * RF Configuration Database + ****************************************************************************/ + +EXTERN const struct c1101_rfsettings_s + +// \todo Recalculate ERP in maximum power level + +/* 868 MHz, GFSK, 100 kbps, ISM Region 1 (Europe only) + * + * ISM Region 1 (Europe) only, Band 868–870 MHz + * + * Frequency bands for non-specific short range devices in Europe: + * + * Frequency ERP Duty Cycle Bandwidth Remarks + * 868 – 868.6 MHz +14 dBm < 1% No limits + * 868.7 – 869.2 MHz +14 dBm < 0.1% No limits + * 869.3 – 869.4 MHz +10 dBm No limits < 25 kHz Appropriate access protocol required + * 869.4 – 869.65 MHz +27 dBm < 10% < 25 kHz Channels may be combined to one high speed channel + * 869.7 -870 MHz +7 dBm No limits No limits + * + * Frequency Band For License-Free Specific Applications in Europe + * + * Frequency Application ERP Duty Cycle Bandwidth + * 868.6 – 868.7 MHz Alarms +10 dBm < 0.1% 25 kHz(1) + * 869.2 – 869.25 MHz Social Alarms +10 dBm < 0.1% 25 kHz + * 869.25 – 869.3 MHz Alarms +10 dBm < 0.1% 25 kHz + * 869.65 -869.7 MHz Alarms +14 dBm < 10% 25 kHz + * 863 – 865 MHz Radio Microphones +10 dBm No limits 200 kHz + * 863 -865 MHz Wireless Audio Applications +10 dBm No limits 300 kHz + * + * Duty Cycle Limit Total On Time Maximum On Time of Minimum Off Time of + * Within One Hour One Transmission Two Transmission + * < 0.1% 3.6 seconds 0.72 seconds 0.72 seconds + * < 1% 36 seconds 3.6 seconds 1.8 seconds + * < 10% 360 seconds 36 seconds 3.6 seconds + * + * Reference: TI Application Report: swra048.pdf, May 2005 + * ISM-Band and Short Range Device Regulatory Compliance Overview + */ + cc1101_rfsettings_ISM1_868MHzGFSK100kbps, + + +/* 905 MHz, GFSK, 250 kbps, ISM Region 2 (America only) + * + * ISM Region 2 (America) only, Band 902–928 MHz + * + * Cordless phones 1 W + * Microwave ovens 750 W + * Industrial heaters 100 kW + * Military radar 1000 kW + */ + cc1101_rfsettings_ISM2_905MHzGFSK250kbps; + + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/** Initialize Chipcon CC1101 Chip. + * After initialization CC1101 is ready to listen, receive and transmit + * messages on the default channel 0 at given RF configuration. + * + * \param spi SPI Device Structure + * \param isrpin Select the CC1101_PIN_GDOx used to signal interrupts + * \param rfsettings Pointer to default RF Settings loaded at boot time. + * \return Pointer to newly allocated CC1101 structure or NULL on error with errno set. + * + * Possible errno as set by this function on error: + * - ENODEV: When device addressed is not compatible or it is not a CC1101 + * - EFAULT: When there is no device + * - ENOMEM: Out of kernel memory to allocate the device + * - EBUSY: When device is already addressed by other device driver (not yet supported by low-level driver) + **/ +EXTERN struct cc1101_dev_s * cc1101_init(struct spi_dev_s * spi, uint8_t isrpin, + uint32_t pinset, const struct c1101_rfsettings_s * rfsettings); + + +/** Deinitialize Chipcon CC1101 Chip + * + * \param dev Device to CC1101 device structure, as returned by the cc1101_init() + * \return OK On success + * + **/ +EXTERN int cc1101_deinit(struct cc1101_dev_s * dev); + + +/** Power up device, start conversion. \return Zero on success. */ +EXTERN int cc1101_powerup(struct cc1101_dev_s * dev); + +/** Power down device, stop conversion. \return Zero on success. */ +EXTERN int cc1101_powerdown(struct cc1101_dev_s * dev); + +/** Set Multi Purpose Output Function. \return Zero on success. */ +EXTERN int cc1101_setgdo(struct cc1101_dev_s * dev, uint8_t pin, uint8_t function); + +/** Set RF settings. Use one from the database above. */ +EXTERN int cc1101_setrf(struct cc1101_dev_s * dev, const struct c1101_rfsettings_s *settings); + +/** Set Channel. + * Note that regulatory check is made and sending may be prohibited. + * + * \retval 0 On success, sending and receiving is allowed. + * \retval 1 Only receive mode is allowed. + * \retval <0 On error. + */ +EXTERN int cc1101_setchannel(struct cc1101_dev_s * dev, uint8_t channel); + + +/** Set Output Power + * + * \param power Value from 0 - 8, where 0 means power off, and values + * from 1 .. 8 denote the following output power in dBm: + * {-30, -20, -15, -10, -5, 0, 5, 10} [dBm] + * + * If power is above the regulatory limit (defined by the RF settings) + * it is limited. + * + * \return Actual output power in range from 0..8. + */ +EXTERN uint8_t cc1101_setpower(struct cc1101_dev_s * dev, uint8_t power); + + +/** Convert RSSI as obtained from CC1101 to [dBm] */ +EXTERN int cc1101_calcRSSIdBm(int rssi); + + +/** Enter receive mode and wait for a packet. + * If transmission is in progress, receive mode is entered upon its + * completion. As long cc1101_idle() is not called, each transmission + * returns to receive mode. + * + * \param dev Device to CC1101 structure + * \return Zero on success. + */ +EXTERN int cc1101_receive(struct cc1101_dev_s * dev); + + +/** Read received packet + * + * If size of buffer is too small then the remaining part of data can + * be discarded by the driver. + * + * Packet contains raw data, including the two bytes: + * - RSSI and + * - LQI + * appended at the end of the message. + * + * To inquery about the data pending size you the following: + * - pass buf=NULL and size > 0, returns pending data packet size + * - pass buf=NULL and size = 0, returns maximum data packet size + * + * NOTE: messages length are typically defined by the MAC, transmit/ + * receive windows at some rate. + */ +EXTERN int cc1101_read(struct cc1101_dev_s * dev, uint8_t * buf, size_t size); + + +/** Write data to be send, using the cc1101_send() + * + * \param dev Device to CC1101 structure + * \param buf Pointer to data. + * \param size Size must be within limits, otherwise data is truncated. + * Present driver limitation supports a single cc1101_write() + * prioer cc1101_send() is called. + */ +EXTERN int cc1101_write(struct cc1101_dev_s * dev, const uint8_t * buf, size_t size); + + +/** Send data previously writtenusing cc1101_write() + * + * \param dev Device to CC1101 structure + * \return Zero on success. + */ +EXTERN int cc1101_send(struct cc1101_dev_s * dev); + + +/** Enter idle state (after reception and transmission completes). + * + * \return Zero on success. + */ +EXTERN int cc1101_idle(struct cc1101_dev_s * dev); + + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __ASSEMBLY__ */ +#endif /* __INCLUDE_NUTTX_WIRELESS_CC1101_H */ diff --git a/nuttx/include/nuttx/wqueue.h b/nuttx/include/nuttx/wqueue.h new file mode 100644 index 0000000000..dfd424c8dc --- /dev/null +++ b/nuttx/include/nuttx/wqueue.h @@ -0,0 +1,185 @@ +/**************************************************************************** + * include/nuttx/wqueue.h + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_WQUEUE_H +#define __INCLUDE_NUTTX_WQUEUE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Defines the work callback */ + +typedef void (*worker_t)(FAR void *arg); + +/* Defines one entry in the work queue. The user only needs this structure + * in order to declare instances of the work structure. Handling of all + * fields is performed by the work APIs + */ + +struct work_s +{ + struct dq_entry_s dq; /* Implements a doubly linked list */ + worker_t worker; /* Work callback */ + FAR void *arg; /* Callback argument */ + uint32_t qtime; /* Time work queued */ + uint32_t delay; /* Delay until work performed */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* The task ID of the worker thread */ + +EXTERN pid_t g_worker; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: work_queue + * + * Description: + * Queue work to be performed at a later time. All queued work will be + * performed on the worker thread of of execution (not the caller's). + * + * The work structure is allocated by caller, but completely managed by + * the work queue logic. The caller should never modify the contents of + * the work queue structure; the caller should not call work_queue() + * again until either (1) the previous work has been performed and removed + * from the queue, or (2) work_cancel() has been called to cancel the work + * and remove it from the work queue. + * + * Input parameters: + * work - The work structure to queue + * worker - The worker callback to be invoked. The callback will invoked + * on the worker thread of execution. + * arg - The argument that will be passed to the workder callback when + * int is invoked. + * delay - Delay (in clock ticks) from the time queue until the worker + * is invoked. Zero means to perform the work immediately. + * + * Returned Value: + * Zero on success, a negated errno on failure + * + ****************************************************************************/ + +EXTERN int work_queue(struct work_s *work, worker_t worker, FAR void *arg, uint32_t delay); + +/**************************************************************************** + * Name: work_cancel + * + * Description: + * Cancel previously queued work. This removes work from the work queue. + * After work has been canceled, it may be re-queue by calling work_queue() + * again. + * + * Input parameters: + * work - The previously queue work structure to cancel + * + * Returned Value: + * Zero on success, a negated errno on failure + * + ****************************************************************************/ + +EXTERN int work_cancel(struct work_s *work); + +/**************************************************************************** + * Name: work_signal + * + * Description: + * Signal the worker thread to process the work queue now. This function + * is used internally by the work logic but could also be used by the + * user to force an immediate re-assessment of pending work. + * + * Input parameters: + * None + * + * Returned Value: + * Zero on success, a negated errno on failure + * + ****************************************************************************/ + +#define work_signal() kill(g_worker, SIGWORK) + +/**************************************************************************** + * Name: work_available + * + * Description: + * Check if the work structure is available. + * + * Input parameters: + * None + * + * Returned Value: + * true if available; false if busy (i.e., there is still pending work). + * + ****************************************************************************/ + +#define work_available(work) ((work)->worker == NULL) + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __INCLUDE_NUTTX_WQUEUE_H */ diff --git a/nuttx/include/nxflat.h b/nuttx/include/nxflat.h new file mode 100644 index 0000000000..82e6678976 --- /dev/null +++ b/nuttx/include/nxflat.h @@ -0,0 +1,204 @@ +/**************************************************************************** + * include/nxflat.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NXFLAT_H +#define __INCLUDE_NXFLAT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NXFLAT_MAX_STRING_SIZE 64 /* Largest size of string (w/zterminator) */ +#define NXFLAT_MAGIC "NxFT" /* NXFLAT magic number */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * The NXFLAT file header + * + * The elements within this structure are stored in network order (i.e., + * ntohs() and ntohl() should be used to access fields within the + * header. + ****************************************************************************/ + +struct nxflat_hdr_s +{ + /* The "magic number" identifying the file type. This field should contain + * "NxFT". NOTE that there is no other versioning information other than + * this magic number. + */ + + char h_magic[4]; + + /* The following fields provide the memory map for the nxflat binary. + * + * h_entry - Offset to the first executable insruction from + * the beginning of the file. + * h_datastart - Offset to the beginning of the data segment from + * the beginning of the file. This field can also + * interpreted as the size of the ISpace segment. + * h_dataend - Offset to the end of the data segment from the + * beginning of the file. + * h_bssend - Offset to the end of bss segment from the beginning + * of the file. + * + * The text segment can be considered to be the contiguous (unrelocated) + * address space range from address zero through (but not including) + * h_datastart. + * + * The size of the data/bss segment includes (as a minimum) the data + * and bss regions (bss_end - data_start) as well as the size of the + * stack. At run time, this region will also include program arguments + * and environement variables. + * + * The bss segment is data_end through bss_end. + */ + + uint32_t h_entry; + uint32_t h_datastart; + uint32_t h_dataend; + uint32_t h_bssend; + + /* Size of stack, in bytes */ + + uint32_t h_stacksize; + + /* Relocation entries: + * + * h_relocstart - Offset to the beginning of an array of relocation + * records (struct nxflat_reloc). The offset is + * relative to the start of the file + */ + + uint32_t h_relocstart; /* Offset of relocation records */ + + /* Imported symbol table (NOTE no symbols are exported): + * + * h_importsymbols - Offset to the beginning of an array of imported + * symbol structures (struct nxflat_import_s). The + * h_importsymbols offset is relative to the + * beginning of the file. Each entry of the + * array contains an uint32_t offset (again from + * the beginning of the file) to the name of + * a symbol string. This string is null-terminated. + */ + + uint32_t h_importsymbols; /* Offset to list of imported symbols */ + + /* 16-bit counts + * + * h_reloccount - The number of relocation records in the arry + * h_importcount - The number of records in the h_importsymbols array. + */ + + uint16_t h_reloccount; /* Number of relocation records */ + uint16_t h_importcount; /* Number of imported symbols */ +}; + +/**************************************************************************** + * NXFLAT Relocation types. + * + * The relocation records are an array of the following type. + ****************************************************************************/ + +struct nxflat_reloc_s +{ + uint32_t r_info; /* Bit-encoded relocation info */ +}; + +/* Pack the type and the offset into one 32-bit value */ + +#define NXFLAT_RELOC(t,o) (((uint32_t)((t) & 3) << 30) | ((o) & 0x3fffffff)) + +/* The top three bits of the relocation info is the relocation type (see the + * NXFLAT_RELOC_TYPE_* definitions below. This is an unsigned value. + */ + +#define NXFLAT_RELOC_TYPE(r) ((uint32_t)(r) >> 30) + +/* The bottom 28 bits of the relocation info is the (non-negative) offset into + * the D-Space that needs the fixup. + */ + +#define NXFLAT_RELOC_OFFSET(r) ((uint32_t)(r) & 0x3fffffff) + +/* These are possible values for the relocation type: + * + * NXFLAT_RELOC_TYPE_REL32I Meaning: Object file contains a 32-bit offset + * into I-Space at the offset. + * Fixup: Add mapped I-Space address to the offset. + * NXFLAT_RELOC_TYPE_REL32D Meaning: Object file contains a 32-bit offset + * into D-Space at the offset. + * Fixup: Add allocated D-Space address to the + * offset. + * NXFLAT_RELOC_TYPE_REL32ID Meaning: Object file contains a 32-bit offset + * into I-Space at the offset that will + * unfortunately be references relative + * to the GOT + * Fixup: Add allocated the mapped I-Space + * address MINUS the allocated D-Space + * address to the offset. + */ + +#define NXFLAT_RELOC_TYPE_REL32I 0 +#define NXFLAT_RELOC_TYPE_REL32D 1 +#undef NXFLAT_RELOC_TYPE_REL32ID /* May not need */ +#define NXFLAT_RELOC_TYPE_NUM 2 /* Number of relocation types */ + +/**************************************************************************** + * NXFLAT Imported symbol type + * + * The imported symbols are an array of the following type. The fields + * in each element are stored in native machine order. + ****************************************************************************/ + +struct nxflat_import_s +{ + uint32_t i_funcname; /* Offset to name of imported function */ + uint32_t i_funcaddress; /* Resolved address of imported function */ +}; + +#endif /* __INCLUDE_NXFLAT_H */ diff --git a/nuttx/include/poll.h b/nuttx/include/poll.h new file mode 100644 index 0000000000..3bf4c4badd --- /dev/null +++ b/nuttx/include/poll.h @@ -0,0 +1,138 @@ +/**************************************************************************** + * include/poll.h + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_POLL_H +#define __INCLUDE_POLL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Poll event definitions: + * + * POLLIN + * Data other than high-priority data may be read without blocking. + * POLLRDNORM + * Normal data may be read without blocking. + * POLLRDBAND + * Priority data may be read without blocking. + * POLLPRI + * High priority data may be read without blocking. + * POLLOUT + * Normal data may be written without blocking. + * POLLWRNORM + * Equivalent to POLLOUT. + * POLLWRBAND + * Priority data may be written. + * POLLERR + * An error has occurred (revents only). + * POLLHUP + * Device has been disconnected (revents only). + * POLLNVAL + * Invalid fd member (revents only). + */ + +#define POLLIN (0x01) /* NuttX does not make priority distinctions */ +#define POLLRDNORM (0x01) +#define POLLRDBAND (0x01) +#define POLLPRI (0x01) + +#define POLLOUT (0x02) /* NuttX does not make priority distinctions */ +#define POLLWRNORM (0x02) +#define POLLWRBAND (0x02) + +#define POLLERR (0x04) +#define POLLHUP (0x08) +#define POLLNVAL (0x10) + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* The number of poll descriptors (required by poll() specification */ + +typedef unsigned int nfds_t; + +/* In the standard poll() definition, the size of the event set is 'short'. + * Here we pick the smallest storage element that will contain all of the + * poll events. + */ + +typedef uint8_t pollevent_t; + +/* This is the Nuttx variant of the standard pollfd structure. */ + +struct pollfd +{ + int fd; /* The descriptor being polled */ + sem_t *sem; /* Pointer to semaphore used to post output event */ + pollevent_t events; /* The input event flags */ + pollevent_t revents; /* The output event flags */ + FAR void *priv; /* For use by drivers */ +}; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +EXTERN int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_POLL_H */ diff --git a/nuttx/include/pthread.h b/nuttx/include/pthread.h new file mode 100644 index 0000000000..5a08f13b61 --- /dev/null +++ b/nuttx/include/pthread.h @@ -0,0 +1,407 @@ +/******************************************************************************** + * include/pthread.h + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +#ifndef __INCLUDE_PTHREAD_H +#define __INCLUDE_PTHREAD_H + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include /* Default settings */ +#include /* Compiler settings */ + +#include /* Needed for general types */ +#include /* C99 fixed width integer types */ +#include /* C99 boolean types */ +#include /* Needed for sem_t */ +#include /* Needed for sigset_t */ +#include /* Needed for struct timespec */ +#include /* For noreturn_function */ + +/******************************************************************************** + * Compilation Switches + ********************************************************************************/ + +/* Standard POSIX switches */ + +#ifndef _POSIX_THREADS +#define _POSIX_THREADS +#endif +#ifndef _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_ATTR_STACKSIZE +#endif + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/* Values for the process shared (pshared) attribute */ + +#define PTHREAD_PROCESS_PRIVATE 0 +#define PTHREAD_PROCESS_SHARED 1 + +/* Values for the mutext type attribute: + * + * PTHREAD_MUTEX_NORMAL: This type of mutex does not detect deadlock. A thread + * attempting to relock this mutex without first unlocking it will deadlock. + * Attempting to unlock a mutex locked by a different thread results in undefined + * behavior. Attempting to unlock an unlocked mutex results in undefined behavior. + * PTHREAD_MUTEX_ERRORCHECK + * This type of mutex provides error checking. A thread attempting to relock this + * mutex without first unlocking it will return with an error. A thread attempting + * to unlock a mutex which another thread has locked will return with an error. A + * thread attempting to unlock an unlocked mutex will return with an error. + * PTHREAD_MUTEX_RECURSIVE + * A thread attempting to relock this mutex without first unlocking it will succeed + * in locking the mutex. The relocking deadlock which can occur with mutexes of type + * PTHREAD_MUTEX_NORMAL cannot occur with this type of mutex. Multiple locks of this + * mutex require the same number of unlocks to release the mutex before another thread + * can acquire the mutex. A thread attempting to unlock a mutex which another thread + * has locked will return with an error. A thread attempting to unlock an unlocked + * mutex will return with an error. + * PTHREAD_MUTEX_DEFAULT + * An implementation is allowed to map this mutex to one of the other mutex types. + */ + +#ifdef CONFIG_MUTEX_TYPES +# define PTHREAD_MUTEX_NORMAL 0 +# define PTHREAD_MUTEX_ERRORCHECK 1 +# define PTHREAD_MUTEX_RECURSIVE 2 +# define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL +#endif + +/* Valid ranges for the pthread stacksize attribute */ + +#define PTHREAD_STACK_MIN CONFIG_PTHREAD_STACK_MIN +#define PTHREAD_STACK_DEFAULT CONFIG_PTHREAD_STACK_DEFAULT + +/* Values for the pthread inheritsched attribute */ + +#define PTHREAD_INHERIT_SCHED 0 +#define PTHREAD_EXPLICIT_SCHED 1 + +#define PTHREAD_PRIO_NONE 0 +#define PTHREAD_PRIO_INHERIT 1 +#define PTHREAD_PRIO_PROTECT 2 + +#define PTHREAD_DEFAULT_PRIORITY 100 + +/* Cancellation states returned by pthread_cancelstate() */ + +#define PTHREAD_CANCEL_ENABLE (0) +#define PTHREAD_CANCEL_DISABLE (1) + +/* Thread return value when a pthread is canceled */ + +#define PTHREAD_CANCELED ((FAR void*)ERROR) + +/* Used to initialize a pthread_once_t */ + +#define PTHREAD_ONCE_INIT (false) + +/* This is returned by pthread_wait. It must not match any errno in errno.h */ + +#define PTHREAD_BARRIER_SERIAL_THREAD 0x1000 + +/* Definitions to map some non-standard, BSD thread management interfaces to + * the non-standard Linux-like prctl() interface. Since these are simple + * mappings to prctl, they will return 0 sucess and -1 on failure with the + * err number in errno. This is an inconsistency with out pthread interfaces. + */ + +#define pthread_setname_np(thread, name) \ + prctl((int)PR_SET_NAME, (char*)name, (int)thread) + +#define pthread_getname_np(thread, name) \ + prctl((int)PR_GET_NAME, (char*)name, (int)thread) + +/******************************************************************************** + * Global Type Declarations + ********************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* pthread-specific types */ + +typedef int pthread_key_t; +typedef FAR void *pthread_addr_t; +typedef pthread_addr_t any_t; + +typedef pthread_addr_t (*pthread_startroutine_t)(pthread_addr_t); +typedef pthread_startroutine_t pthread_func_t; + +struct pthread_attr_s +{ + size_t stacksize; /* Size of the stack allocated for the pthead */ + int16_t priority; /* Priority of the pthread */ + uint8_t policy; /* Pthread scheduler policy */ + uint8_t inheritsched; /* Inherit parent prio/policy? */ +}; +typedef struct pthread_attr_s pthread_attr_t; + +typedef pid_t pthread_t; + +typedef int pthread_condattr_t; + +struct pthread_cond_s +{ + sem_t sem; +}; +typedef struct pthread_cond_s pthread_cond_t; +#define PTHREAD_COND_INITIALIZER {{0, 0xffff}} + +struct pthread_mutexattr_s +{ + uint8_t pshared; /* PTHREAD_PROCESS_PRIVATE or PTHREAD_PROCESS_SHARED */ +#ifdef CONFIG_MUTEX_TYPES + uint8_t type; /* Type of the mutex. See PTHREAD_MUTEX_* definitions */ +#endif +}; +typedef struct pthread_mutexattr_s pthread_mutexattr_t; + +struct pthread_mutex_s +{ + int pid; /* ID of the holder of the mutex */ + sem_t sem; /* Semaphore underlying the implementation of the mutex */ +#ifdef CONFIG_MUTEX_TYPES + uint8_t type; /* Type of the mutex. See PTHREAD_MUTEX_* definitions */ + int nlocks; /* The number of recursive locks held */ +#endif +}; +typedef struct pthread_mutex_s pthread_mutex_t; + +#ifdef CONFIG_MUTEX_TYPES +# define PTHREAD_MUTEX_INITIALIZER {0, SEM_INITIALIZER(1), PTHREAD_MUTEX_DEFAULT, 0} +#else +# define PTHREAD_MUTEX_INITIALIZER {0, SEM_INITIALIZER(1)} +#endif + +struct pthread_barrierattr_s +{ + int pshared; +}; +typedef struct pthread_barrierattr_s pthread_barrierattr_t; + +struct pthread_barrier_s +{ + sem_t sem; + unsigned int count; +}; +typedef struct pthread_barrier_s pthread_barrier_t; + +typedef bool pthread_once_t; + +/* Forware references */ + +struct sched_param; /* Defined in sched.h */ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Global Function Prototypes + ********************************************************************************/ + +/* Initializes a thread attributes object (attr) with default values for all of + * the individual attributes used by a given implementation. + */ + +EXTERN int pthread_attr_init(FAR pthread_attr_t *attr); + +/* An attributes object can be deleted when it is no longer needed. */ + +EXTERN int pthread_attr_destroy(pthread_attr_t *attr); + +/* Set or obtain the default scheduling algorithm */ + +EXTERN int pthread_attr_setschedpolicy(FAR pthread_attr_t *attr, int policy); +EXTERN int pthread_attr_getschedpolicy(FAR pthread_attr_t *attr, int *policy); +EXTERN int pthread_attr_setschedparam(FAR pthread_attr_t *attr, + FAR const struct sched_param *param); +EXTERN int pthread_attr_getschedparam(FAR pthread_attr_t *attr, + FAR struct sched_param *param); +EXTERN int pthread_attr_setinheritsched(FAR pthread_attr_t *attr, int inheritsched); +EXTERN int pthread_attr_getinheritsched(FAR const pthread_attr_t *attr, + FAR int *inheritsched); + +/* Set or obtain the default stack size */ + +EXTERN int pthread_attr_setstacksize(FAR pthread_attr_t *attr, long stacksize); +EXTERN int pthread_attr_getstacksize(FAR pthread_attr_t *attr, long *stackaddr); + +/* To create a thread object and runnable thread, a routine must be specified + * as the new thread's start routine. An argument may be passed to this + * routine, as an untyped address; an untyped address may also be returned as + * the routine's value. An attributes object may be used to specify details + * about the kind of thread being created. + */ + +EXTERN int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr, + pthread_startroutine_t startroutine, + pthread_addr_t arg); + +/* A thread object may be "detached" to specify that the return value and + * completion status will not be requested. + */ + +EXTERN int pthread_detach(pthread_t thread); + +/* A thread may terminate it's own execution or the execution of another + * thread. + */ + +EXTERN void pthread_exit(pthread_addr_t value) noreturn_function; +EXTERN int pthread_cancel(pthread_t thread); +EXTERN int pthread_setcancelstate(int state, FAR int *oldstate); +EXTERN void pthread_testcancel(void); + +/* A thread can await termination of another thread and retrieve the return + * value of the thread. + */ + +EXTERN int pthread_join(pthread_t thread, FAR pthread_addr_t *value); + +/* A thread may tell the scheduler that its processor can be made available. */ + +EXTERN void pthread_yield(void); + +/* A thread may obtain a copy of its own thread handle. */ + +#define pthread_self() ((pthread_t)getpid()) + +/* Compare two thread IDs. */ + +#define pthread_equal(t1,t2) (t1 == t2) + +/* Thread scheduling parameters */ + +EXTERN int pthread_getschedparam(pthread_t thread, FAR int *policy, + FAR struct sched_param *param); +EXTERN int pthread_setschedparam(pthread_t thread, int policy, + FAR const struct sched_param *param); +EXTERN int pthread_setschedprio(pthread_t thread, int prio); + +/* Thread-specific Data Interfaces */ + +EXTERN int pthread_key_create(FAR pthread_key_t *key, + CODE void (*destructor)(FAR void*)); +EXTERN int pthread_setspecific(pthread_key_t key, FAR void *value); +EXTERN FAR void *pthread_getspecific(pthread_key_t key); +EXTERN int pthread_key_delete(pthread_key_t key); + +/* Create, operate on, and destroy mutex attributes. */ + +EXTERN int pthread_mutexattr_init(FAR pthread_mutexattr_t *attr); +EXTERN int pthread_mutexattr_destroy(FAR pthread_mutexattr_t *attr); +EXTERN int pthread_mutexattr_getpshared(FAR pthread_mutexattr_t *attr, FAR int *pshared); +EXTERN int pthread_mutexattr_setpshared(FAR pthread_mutexattr_t *attr, int pshared); +#ifdef CONFIG_MUTEX_TYPES +EXTERN int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type); +EXTERN int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type); +#endif + +/* The following routines create, delete, lock and unlock mutexes. */ + +EXTERN int pthread_mutex_init(FAR pthread_mutex_t *mutex, FAR pthread_mutexattr_t *attr); +EXTERN int pthread_mutex_destroy(FAR pthread_mutex_t *mutex); +EXTERN int pthread_mutex_lock(FAR pthread_mutex_t *mutex); +EXTERN int pthread_mutex_trylock(FAR pthread_mutex_t *mutex); +EXTERN int pthread_mutex_unlock(FAR pthread_mutex_t *mutex); + +/* Operations on condition variables */ + +EXTERN int pthread_condattr_init(FAR pthread_condattr_t *attr); +EXTERN int pthread_condattr_destroy(FAR pthread_condattr_t *attr); + +/* A thread can create and delete condition variables. */ + +EXTERN int pthread_cond_init(FAR pthread_cond_t *cond, FAR pthread_condattr_t *attr); +EXTERN int pthread_cond_destroy(FAR pthread_cond_t *cond); + +/* A thread can signal to and broadcast on a condition variable. */ + +EXTERN int pthread_cond_broadcast(FAR pthread_cond_t *cond); +EXTERN int pthread_cond_signal(FAR pthread_cond_t *cond); + +/* A thread can wait for a condition variable to be signalled or broadcast. */ + +EXTERN int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex); + +/* A thread can perform a timed wait on a condition variable. */ + +EXTERN int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex, + FAR const struct timespec *abstime); + +/* Barrier attributes */ + +EXTERN int pthread_barrierattr_destroy(FAR pthread_barrierattr_t *attr); +EXTERN int pthread_barrierattr_init(FAR pthread_barrierattr_t *attr); +EXTERN int pthread_barrierattr_getpshared(FAR const pthread_barrierattr_t *attr, + FAR int *pshared); +EXTERN int pthread_barrierattr_setpshared(FAR pthread_barrierattr_t *attr, + int pshared); + +/* Barriers */ + +EXTERN int pthread_barrier_destroy(FAR pthread_barrier_t *barrier); +EXTERN int pthread_barrier_init(FAR pthread_barrier_t *barrier, + FAR const pthread_barrierattr_t *attr, + unsigned int count); +EXTERN int pthread_barrier_wait(FAR pthread_barrier_t *barrier); + +/* Pthread initialization */ + +EXTERN int pthread_once(FAR pthread_once_t *once_control, + CODE void (*init_routine)(void)); + +/* Pthread signal management APIs */ + +EXTERN int pthread_kill(pthread_t thread, int sig); +EXTERN int pthread_sigmask(int how, FAR const sigset_t *set, FAR sigset_t *oset); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_PTHREAD_H */ + diff --git a/nuttx/include/queue.h b/nuttx/include/queue.h new file mode 100644 index 0000000000..b5aa236904 --- /dev/null +++ b/nuttx/include/queue.h @@ -0,0 +1,129 @@ +/************************************************************************ + * include/queue.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +#ifndef __INCLUDE_QUEUE_H +#define __INCLUDE_QUEUE_H + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +#define sq_init(q) do { (q)->head = NULL; (q)->tail = NULL; } while (0) +#define dq_init(q) do { (q)->head = NULL; (q)->tail = NULL; } while (0) + +#define sq_next(p) ((p)->flink) +#define dq_next(p) ((p)->flink) +#define dq_prev(p) ((p)->blink) + +#define sq_empty(q) ((q)->head == NULL) +#define dq_empty(q) ((q)->head == NULL) + +#define sq_peek(q) ((q)->head) +#define dq_peek(q) ((q)->head) + +/************************************************************************ + * Global Type Declarations + ************************************************************************/ + +struct sq_entry_s +{ + FAR struct sq_entry_s *flink; +}; +typedef struct sq_entry_s sq_entry_t; + +struct dq_entry_s +{ + FAR struct dq_entry_s *flink; + FAR struct dq_entry_s *blink; +}; +typedef struct dq_entry_s dq_entry_t; + +struct sq_queue_s +{ + FAR sq_entry_t *head; + FAR sq_entry_t *tail; +}; +typedef struct sq_queue_s sq_queue_t; + +struct dq_queue_s +{ + FAR dq_entry_t *head; + FAR dq_entry_t *tail; +}; +typedef struct dq_queue_s dq_queue_t; + +/************************************************************************ + * Global Function Prototypes + ************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN void sq_addfirst(FAR sq_entry_t *node, sq_queue_t *queue); +EXTERN void dq_addfirst(FAR dq_entry_t *node, dq_queue_t *queue); +EXTERN void sq_addlast(FAR sq_entry_t *node, sq_queue_t *queue); +EXTERN void dq_addlast(FAR dq_entry_t *node, dq_queue_t *queue); +EXTERN void sq_addafter(FAR sq_entry_t *prev, FAR sq_entry_t *node, + sq_queue_t *queue); +EXTERN void dq_addafter(FAR dq_entry_t *prev, FAR dq_entry_t *node, + dq_queue_t *queue); +EXTERN void dq_addbefore(FAR dq_entry_t *next, FAR dq_entry_t *node, + dq_queue_t *queue); + +EXTERN FAR sq_entry_t *sq_remafter(FAR sq_entry_t *node, sq_queue_t *queue); +EXTERN void sq_rem(FAR sq_entry_t *node, sq_queue_t *queue); +EXTERN void dq_rem(FAR dq_entry_t *node, dq_queue_t *queue); +EXTERN FAR sq_entry_t *sq_remlast(sq_queue_t *queue); +EXTERN FAR dq_entry_t *dq_remlast(dq_queue_t *queue); +EXTERN FAR sq_entry_t *sq_remfirst(sq_queue_t *queue); +EXTERN FAR dq_entry_t *dq_remfirst(dq_queue_t *queue); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_QUEUE_H_ */ + diff --git a/nuttx/include/sched.h b/nuttx/include/sched.h new file mode 100644 index 0000000000..4494d8ef5d --- /dev/null +++ b/nuttx/include/sched.h @@ -0,0 +1,167 @@ +/******************************************************************************** + * include/sched.h + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +#ifndef __INCLUDE_SCHED_H +#define __INCLUDE_SCHED_H + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include + +/******************************************************************************** + * Pre-processor Definitions + ********************************************************************************/ + +/* Task Management Definitions **************************************************/ + +/* POSIX-like scheduling policies */ + +#define SCHED_FIFO 1 /* FIFO per priority scheduling policy */ +#define SCHED_RR 2 /* Round robin scheduling policy */ +#define SCHED_SPORADIC 3 /* Not supported */ +#define SCHED_OTHER 4 /* Not supported */ + +/* Pthread definitions **********************************************************/ + +#define PTHREAD_KEYS_MAX CONFIG_NPTHREAD_KEYS + +/* Non-standard Helper **********************************************************/ +/* One processor family supported by NuttX has a single, fixed hardware stack. + * That is the 8051 family. So for that family only, there is a variant form + * of task_create() that does not take a stack size parameter. The following + * helper macros are provided to work around the ugliness of that exception. + */ + +#ifndef CONFIG_CUSTOM_STACK +# define TASK_INIT(t,n,p,m,s,e,a) task_init(t,n,p,m,s,e,a) +# define TASK_CREATE(n,p,s,e,a) task_create(n,p,s,e,a) +#else +# define TASK_INIT(t,n,p,m,s,e,a) task_init(t,n,p,e,a) +# define TASK_CREATE(n,p,s,e,a) task_create(n,p,e,a) +#endif + +/******************************************************************************** + * Global Type Definitions + ********************************************************************************/ + +/* This is the POSIX-like scheduling parameter structure */ + +struct sched_param +{ + int sched_priority; +}; + +/******************************************************************************** + * Global Function Prototypes + ********************************************************************************/ + +#ifndef __ASSEMBLY__ +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Task Control Interfaces (non-standard) */ + +#ifndef CONFIG_CUSTOM_STACK +EXTERN int task_init(FAR _TCB *tcb, const char *name, int priority, + FAR uint32_t *stack, uint32_t stack_size, + main_t entry, const char *argv[]); +#else +EXTERN int task_init(FAR _TCB *tcb, const char *name, int priority, + main_t entry, const char *argv[]); +#endif +EXTERN int task_activate(FAR _TCB *tcb); +#ifndef CONFIG_CUSTOM_STACK +EXTERN int task_create(const char *name, int priority, int stack_size, + main_t entry, const char *argv[]); +#else +EXTERN int task_create(const char *name, int priority, + main_t entry, const char *argv[]); +#endif +EXTERN int task_delete(pid_t pid); +EXTERN int task_restart(pid_t pid); + +/* Task Scheduling Interfaces (based on POSIX APIs) */ + +EXTERN int sched_setparam(pid_t pid, const struct sched_param *param); +EXTERN int sched_getparam(pid_t pid, struct sched_param *param); +EXTERN int sched_setscheduler(pid_t pid, int policy, + const struct sched_param *param); +EXTERN int sched_getscheduler(pid_t pid); +EXTERN int sched_yield(void); +EXTERN int sched_get_priority_max(int policy); +EXTERN int sched_get_priority_min(int policy); +EXTERN int sched_rr_get_interval(pid_t pid, struct timespec *interval); + +/* Task Switching Interfaces (non-standard) */ + +EXTERN int sched_lock(void); +EXTERN int sched_unlock(void); +EXTERN int sched_lockcount(void); + +/* If instrumentation of the scheduler is enabled, then some outboard logic + * must provide the following interfaces. + */ + +#ifdef CONFIG_SCHED_INSTRUMENTATION + +EXTERN void sched_note_start(FAR _TCB *tcb); +EXTERN void sched_note_stop(FAR _TCB *tcb); +EXTERN void sched_note_switch(FAR _TCB *pFromTcb, FAR _TCB *pToTcb); + +#else +# define sched_note_start(t) +# define sched_note_stop(t) +# define sched_note_switch(t1, t2) +#endif /* CONFIG_SCHED_INSTRUMENTATION */ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* __INCLUDE_SCHED_H */ + diff --git a/nuttx/include/semaphore.h b/nuttx/include/semaphore.h new file mode 100644 index 0000000000..85214b9c20 --- /dev/null +++ b/nuttx/include/semaphore.h @@ -0,0 +1,132 @@ +/**************************************************************************** + * include/semaphore.h + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SEMAPHORE_H +#define __INCLUDE_SEMAPHORE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Declarations + ****************************************************************************/ + +/* This structure contains the holder of a semaphore */ + +#ifdef CONFIG_PRIORITY_INHERITANCE +struct semholder_s +{ +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + struct semholder_s *flink; /* Implements singly linked list */ +#endif + void *holder; /* Holder TCB (actual type is _TCB) */ + int16_t counts; /* Number of counts owned by this holder */ +}; + +#if CONFIG_SEM_PREALLOCHOLDERS > 0 +# define SEMHOLDER_INITIALIZER {NULL, NULL, 0} +#else +# define SEMHOLDER_INITIALIZER {NULL, 0} +#endif +#endif /* CONFIG_PRIORITY_INHERITANCE */ + +/* This is the generic semaphore structure. */ + +struct sem_s +{ + int16_t semcount; /* >0 -> Num counts available */ + /* <0 -> Num tasks waiting for semaphore */ +#ifdef CONFIG_PRIORITY_INHERITANCE + struct semholder_s hlist; /* List of holders of semaphore counts */ +#endif +}; +typedef struct sem_s sem_t; + +/* Initializers */ + +#ifdef CONFIG_PRIORITY_INHERITANCE +# define SEM_INITIALIZER(c) {(c), SEMHOLDER_INITIALIZER} +#else +# define SEM_INITIALIZER(c) {(c)} +#endif + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +/* Forward references needed by some prototypes */ + +struct timespec; /* Defined in time.h */ + +/* Counting Semaphore Interfaces (based on POSIX APIs) */ + +EXTERN int sem_init(FAR sem_t *sem, int pshared, unsigned int value); +EXTERN int sem_destroy(FAR sem_t *sem); +EXTERN FAR sem_t *sem_open(FAR const char *name, int oflag, ...); +EXTERN int sem_close(FAR sem_t *sem); +EXTERN int sem_unlink(FAR const char *name); +EXTERN int sem_wait(FAR sem_t *sem); +EXTERN int sem_timedwait(FAR sem_t *sem, + FAR const struct timespec *abstime); +EXTERN int sem_trywait(FAR sem_t *sem); +EXTERN int sem_post(FAR sem_t *sem); +EXTERN int sem_getvalue(FAR sem_t *sem, FAR int *sval); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_SEMAPHORE_H */ diff --git a/nuttx/include/signal.h b/nuttx/include/signal.h new file mode 100644 index 0000000000..02b2223430 --- /dev/null +++ b/nuttx/include/signal.h @@ -0,0 +1,238 @@ +/******************************************************************************** + * include/signal.h + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +#ifndef __INCLUDE_SIGNAL_H +#define __INCLUDE_SIGNAL_H + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include +#include + +#include +#include + +/******************************************************************************** + * Pre-processor Definitions + ********************************************************************************/ + +/* Signal set management definitions and macros. */ + +#define NULL_SIGNAL_SET ((sigset_t)0x00000000) +#define ALL_SIGNAL_SET ((sigset_t)0xffffffff) +#define MIN_SIGNO 0 +#define MAX_SIGNO 31 +#define GOOD_SIGNO(s) ((((unsigned)(s))<=MAX_SIGNO)) +#define SIGNO2SET(s) ((sigset_t)1 << (s)) + +/* All signals are "real time" signals */ + +#define SIGRTMIN 0 /* First real time signal */ +#define SIGRTMAX 31 /* Last real time signal */ + +/* A few of the real time signals are used within the OS. They have + * default values that can be overridden from the configuration file. The + * rest are all user signals: + */ + +#ifndef CONFIG_SIG_SIGUSR1 +#define SIGUSR1 0 /* User signal 1 */ +#else +#define SIGUSR1 CONFIG_SIG_SIGUSR1 +#endif + +#ifndef CONFIG_SIG_SIGUSR2 +#define SIGUSR2 1 /* User signal 2 */ +#else +#define SIGUSR2 CONFIG_SIG_SIGUSR2 +#endif + +#ifndef CONFIG_SIG_SIGALARM +#define SIGALRM 2 /* Default signal used with POSIX timers (used only */ + /* no other signal is provided) */ +#else +#define SIGALRM CONFIG_SIG_SIGALARM +#endif + +#ifndef CONFIG_DISABLE_PTHREAD +#ifndef CONFIG_SIG_SIGCONDTIMEDOUT +#define SIGCONDTIMEDOUT 3 /* Used in the implementation of pthread_cond_timedwait */ +#else +#define SIGCONDTIMEDOUT CONFIG_SIG_SIGCONDTIMEDOUT +#endif +#endif + +/* SIGWORK is used to wake up various internal, NuttX worker thread */ + +#if defined(CONFIG_SCHED_WORKQUEUE) || defined(CONFIG_PAGING) +#ifndef CONFIG_SIG_SIGWORK +#define SIGWORK 4 /* Used to wake up the work queue */ +#else +#define SIGWORK CONFIG_SIG_SIGWORK +#endif +#endif + +/* sigprocmask() "how" definitions. Only one of the following can be specified: */ + +#define SIG_BLOCK 1 /* Block the given signals */ +#define SIG_UNBLOCK 2 /* Unblock the given signals */ +#define SIG_SETMASK 3 /* Set the signal mask to the current set */ + +/* struct sigaction flag values */ + +#define SA_NOCLDSTOP 1 /* Do not generate SIGCHILD when + * children stop (ignored) */ +#define SA_SIGINFO 2 /* Invoke the signal-catching function + * with 3 args instead of 1 + * (always assumed) */ + +/* These are the possible values of the signfo si_code field */ + +#define SI_USER 0 /* Signal sent from kill, raise, or abort */ +#define SI_QUEUE 1 /* Signal sent from sigqueue */ +#define SI_TIMER 2 /* Signal is result of timer expiration */ +#define SI_ASYNCIO 3 /* Signal is the result of asynch IO completion */ +#define SI_MESGQ 4 /* Signal generated by arrival of a message on an */ + /* empty message queue */ + +/* Values for the sigev_notify field of struct sigevent */ + +#define SIGEV_NONE 0 /* No notification desired */ +#define SIGEV_SIGNAL 1 /* Notify via signal */ + +/* Special values of sigaction (all treated like NULL) */ + +#define SIG_ERR ((CODE void*)-1) +#define SIG_DFL ((CODE void*)0) +#define SIG_IGN ((CODE void*)0) + +/******************************************************************************** + * Global Type Declarations + ********************************************************************************/ + +/* This defines a set of 32 signals (numbered 0 through 31). */ + +typedef uint32_t sigset_t; /* Bit set of 32 signals */ + +/* This defines the type of the siginfo si_value field */ + +union sigval +{ + int sival_int; /* Integer value */ + FAR void *sival_ptr; /* Pointer value */ +}; + +/* This structure contains elements that define a queue signal. The following is + * used to attach a signal to a message queue to notify a task when a message is + * available on a queue + */ + +struct sigevent +{ + uint8_t sigev_notify; /* Notification method: SIGEV_SIGNAL or SIGEV_NONE */ + uint8_t sigev_signo; /* Notification signal */ + union sigval sigev_value; /* Data passed with notification */ +}; + +/* The following types is used to pass parameters to/from signal handlers */ + +struct siginfo +{ + uint8_t si_signo; /* Identifies signal */ + uint8_t si_code; /* Source: SI_USER, SI_QUEUE, SI_TIMER, SI_ASYNCIO, or SI_MESGQ */ + union sigval si_value; /* Data passed with signal */ +}; + +typedef struct siginfo siginfo_t; + +/* The following structure defines the action to take for given signal */ + +struct sigaction +{ + union + { + CODE void (*_sa_handler)(int); + CODE void (*_sa_sigaction)(int, FAR siginfo_t *, FAR void *); + } sa_u; + sigset_t sa_mask; + int sa_flags; +}; + +#define sa_handler sa_u._sa_handler +#define sa_sigaction sa_u._sa_sigaction + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Global Function Prototypes + ********************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN int kill(pid_t, int); +EXTERN int sigemptyset(FAR sigset_t *set); +EXTERN int sigfillset(FAR sigset_t *set); +EXTERN int sigaddset(FAR sigset_t *set, int signo); +EXTERN int sigdelset(FAR sigset_t *set, int signo); +EXTERN int sigismember(FAR const sigset_t *set, int signo); +EXTERN int sigaction(int sig, FAR const struct sigaction *act, FAR struct sigaction *oact); +EXTERN int sigprocmask(int how, FAR const sigset_t *set, FAR sigset_t *oset); +EXTERN int sigpending(FAR sigset_t *set); +EXTERN int sigsuspend(FAR const sigset_t *sigmask); +EXTERN int sigwaitinfo(FAR const sigset_t *set, FAR struct siginfo *value); +EXTERN int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *value, + FAR const struct timespec *timeout); +#ifdef CONFIG_CAN_PASS_STRUCTS +EXTERN int sigqueue(int pid, int signo, union sigval value); +#else +EXTERN int sigqueue(int pid, int signo, FAR void *sival_ptr); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_SIGNAL_H */ + diff --git a/nuttx/include/stdbool.h b/nuttx/include/stdbool.h new file mode 100644 index 0000000000..f112199124 --- /dev/null +++ b/nuttx/include/stdbool.h @@ -0,0 +1,89 @@ +/**************************************************************************** + * include/stdbool.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_STDBOOL_H +#define __INCLUDE_STDBOOL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_ARCH_STDBOOL_H +# include +#else +# include +# include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* bool, true, and false must be provided as macros so that they can be + * redefined by the application if necessary. + * + * NOTE: Under C99 'bool' is required to be defined to be the intrinsic type + * _Bool. However, in this NuttX context, we need backward compatibility + * to pre-C99 standards where _Bool is not an intrinsic type. Hence, we + * use _Bool8 as the underlying type. + */ + +#define bool _Bool8 +#define true 1 +#define false 0 + +#define __bool_true_false_are_defined 1 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* A byte is the smallest address memory element (at least in architectures + * that do not support bit banding). The requirement is only that type _Bool + * be large enough to hold the values 0 and 1. We select uint8_t to minimize + * the RAM footprint of the executable. + * + * NOTE: We can't actually define the type _Bool here. Under C99 _Bool is + * an intrinsic type and cannot be the target of a typedef. However, in this + * NuttX context, we also need backward compatibility to pre-C99 standards + * where _Bool is not an intrinsic type. We work around this by using _Bool8 + * as the underlying type. + */ + +typedef uint8_t _Bool8; + +#endif /* CONFIG_ARCH_STDBOOL_H */ +#endif /* __INCLUDE_STDBOOL_H */ diff --git a/nuttx/include/stddef.h b/nuttx/include/stddef.h new file mode 100644 index 0000000000..f08135bf78 --- /dev/null +++ b/nuttx/include/stddef.h @@ -0,0 +1,49 @@ +/**************************************************************************** + * include/stddef.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_STDDEF_H +#define __INCLUDE_STDDEF_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +#endif /* __INCLUDE_STDDEF_H */ diff --git a/nuttx/include/stdint.h b/nuttx/include/stdint.h new file mode 100644 index 0000000000..4c14d935ea --- /dev/null +++ b/nuttx/include/stdint.h @@ -0,0 +1,305 @@ +/**************************************************************************** + * include/stdint.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_STDINT_H +#define __INCLUDE_STDINT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_ARCH_STDINT_H +# include +#else +# include +# include +# include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Limits of exact-width integer types */ + +#define INT8_MIN 0x80 +#define INT8_MAX 0x7f +#define UINT8_MAX 0xff + +#define INT16_MIN 0x8000 +#define INT16_MAX 0x7fff +#define UINT16_MAX 0xffff + +#ifdef __INT24_DEFINED +# define INT24_MIN 0x800000 +# define INT24_MAX 0x7fffff +# define UINT24_MAX 0xffffff +#endif + +#define INT32_MIN 0x80000000 +#define INT32_MAX 0x7fffffff +#define UINT32_MAX 0xffffffff + +#ifdef __INT64_DEFINED +# define INT64_MIN 0x8000000000000000 +# define INT64_MAX 0x7fffffffffffffff +# define UINT64_MAX 0xffffffffffffffff +#endif + +/* Limits of minimum-width integer types */ + +#define INT8_LEASTN_MIN 0x80 +#define INT8_LEASTN_MAX 0x7f +#define UINT8_LEASTN_MAX 0xff + +#define INT16_LEASTN_MIN 0x8000 +#define INT16_LEASTN_MAX 0x7fff +#define UINT16_LEASTN_MAX 0xffff + +#ifdef __INT24_DEFINED +# define INT24_LEASTN_MIN 0x800000 +# define INT24_LEASTN_MAX 0x7fffff +# define UINT24_LEASTN_MAX 0xffffff +#endif + +#define INT32_LEASTN_MIN 0x80000000 +#define INT32_LEASTN_MAX 0x7fffffff +#define UINT32_LEASTN_MAX 0xffffffff + +#ifdef __INT64_DEFINED +# define INT64_LEASTN_MIN 0x8000000000000000 +# define INT64_LEASTN_MAX 0x7fffffffffffffff +# define UINT64_LEASTN_MAX 0xffffffffffffffff +#endif + +/* Limits of fastest minimum-width integer types */ + +#define INT8_FASTN_MIN 0x80 +#define INT8_FASTN_MAX 0x7f +#define UINT8_FASTN_MAX 0xff + +#define INT16_FASTN_MIN 0x8000 +#define INT16_FASTN_MAX 0x7fff +#define UINT16_FASTN_MAX 0xffff + +#ifdef __INT24_DEFINED +# define INT24_FASTN_MIN 0x800000 +# define INT24_FASTN_MAX 0x7fffff +# define UINT24_FASTN_MAX 0xffffff +#endif + +#define INT32_FASTN_MIN 0x80000000 +#define INT32_FASTN_MAX 0x7fffffff +#define UINT32_FASTN_MAX 0xffffffff + +#ifdef __INT64_DEFINED +# define INT64_FASTN_MIN 0x8000000000000000 +# define INT64_FASTN_MAX 0x7fffffffffffffff +# define UINT64_FASTN_MAX 0xffffffffffffffff +#endif + +/* Limits of integer types capable of holding object pointers */ + +#define INTPTR_MIN PTR_MIN +#define INTPTR_MAX PTR_MIN +#define UINTPTR_MAX UPTR_MAX + +/* Limits of greatest-width integer types */ + +#ifdef __INT64_DEFINED +# define INTMAX_MIN INT64_MIN +# define INTMAX_MAX INT64_MAX + +# define UINTMAX_MIN UINT64_MIN +# define UINTMAX_MAX UINT64_MAX +#else +# define INTMAX_MIN INT32_MIN +# define INTMAX_MAX INT32_MAX + +# define UINTMAX_MIN UINT32_MIN +# define UINTMAX_MAX UINT32_MAX +#endif + +/* Macros for minimum-width integer constant expressions */ + +#if 0 /* REVISIT: Depends on architecture specific implementation */ +#define INT8_C(x) x +#define INT16_C(x) x +#define INT32_C(x) x ## L +#define INT64_C(x) x ## LL + +#define UINT8_C(x) x +#define UINT16_C(x) x +#define UINT32_C(x) x ## UL +#define UINT64_C(x) x ## ULL +#endif + +/* Macros for greatest-width integer constant expressions */ + +#ifdef CONFIG_HAVE_LONG_LONG +# define INTMAX_C(x) x ## LL +# define UINTMAX_C(x) x ## ULL +#else +# define INTMAX_C(x) x ## L +# define UINTMAX_C(x) x ## UL +#endif + +/* Limits of Other Integer Types */ + +#if 0 +# define PTRDIFF_MIN +# define PTRDIFF_MAX +#endif + +#ifdef CONFIG_SMALL_MEMORY +# define SIZE_MAX 0xffff +#else +# define SIZE_MAX 0xffffffff +#endif + +#if 0 +# define WCHAR_MIN +# define WCHAR_MAX + +# define WINT_MIN +# define WINT_MAX +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Exact-width integer types. NOTE that these types are defined in + * architecture-specific logic with leading underscore character. This file + * typedef's these to the final name without the underscore character. This + * roundabout way of doings things allows the stdint.h to be removed from the + * include/ directory in the event that the user prefers to use the definitions + * provided by their toolchain header files. + */ + +typedef _int8_t int8_t; +typedef _uint8_t uint8_t; + +typedef _int16_t int16_t; +typedef _uint16_t uint16_t; + +#ifdef __INT24_DEFINED +typedef _int24_t int24_t; +typedef _uint24_t uint24_t; +#endif + +typedef _int32_t int32_t; +typedef _uint32_t uint32_t; + +#ifdef __INT64_DEFINED +typedef _int64_t int64_t; +typedef _uint64_t uint64_t; +#endif + +/* Minimum-width integer types */ + +typedef _int8_t int_least8_t; +typedef _uint8_t uint_least8_t; + +typedef _int16_t int_least16_t; +typedef _uint16_t uint_least16_t; + +#ifdef __INT24_DEFINED +typedef _int24_t int_least24_t; +typedef _uint24_t uint_least24_t; +#else +typedef _int32_t int_least24_t; +typedef _uint32_t uint_least24_t; +#endif + +typedef _int32_t int_least32_t; +typedef _uint32_t uint_least32_t; + +#ifdef __INT64_DEFINED +typedef _int64_t int_least64_t; +typedef _uint64_t uint_least64_t; +#endif + +/* Fastest minimum-width integer types */ + +typedef _int8_t int_fast8_t; +typedef _uint8_t uint_fast8_t; + +typedef int int_fast16_t; +typedef unsigned int uint_fast16_t; + +#ifdef __INT24_DEFINED +typedef _int24_t int_fast24_t; +typedef _uint24_t uint_fast24_t; +#else +typedef _int32_t int_fast24_t; +typedef _uint32_t uint_fast24_t; +#endif + +typedef _int32_t int_fast32_t; +typedef _uint32_t uint_fast32_t; + +#ifdef __INT64_DEFINED +typedef _int64_t int_fast64_t; +typedef _uint64_t uint_fast64_t; +#endif + +/* Integer types capable of holding object pointers */ + +typedef _intptr_t intptr_t; +typedef _uintptr_t uintptr_t; + +/* Some architectures support a FAR pointer which is larger then the normal + * (near) pointer + */ + +#ifdef CONFIG_HAVE_FARPOINTER +typedef _int_farptr_t int_farptr_t; +typedef _uint_farptr_t uint_farptr_t; +#endif + +/* Greatest-width integer types */ + +#ifdef __INT64_DEFINED +typedef _int64_t intmax_t; +typedef _uint64_t uintmax_t; +#else +typedef _int32_t intmax_t; +typedef _uint32_t uintmax_t; +#endif + +#endif /* CONFIG_ARCH_STDBOOL_H */ +#endif /* __INCLUDE_STDINT_H */ diff --git a/nuttx/include/stdio.h b/nuttx/include/stdio.h new file mode 100644 index 0000000000..82bf0eaf6d --- /dev/null +++ b/nuttx/include/stdio.h @@ -0,0 +1,150 @@ +/**************************************************************************** + * include/stdio.h + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_STDIO_H +#define __INCLUDE_STDIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* File System Definitions **************************************************/ + +/* File system error values *************************************************/ + +#define EOF (-1) + +/* The first three _iob entries are reserved for standard I/O */ + +#define stdin (&sched_getstreams()->sl_streams[0]) +#define stdout (&sched_getstreams()->sl_streams[1]) +#define stderr (&sched_getstreams()->sl_streams[2]) + +/* These APIs are not implemented and/or can be synthesized from + * supported APIs. + */ + +#define putc(c,s) fputc((c),(s)) +#define putchar(c) fputc(c, stdout) +#define getc(s) fgetc(s) +#define getchar() fgetc(stdin) +#define rewind(s) ((void)fseek((s),0,SEEK_SET)) + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* Streams */ + +typedef struct file_struct FILE; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* ANSI-like File System Interfaces */ + +EXTERN int fclose(FAR FILE *stream); +EXTERN int fflush(FAR FILE *stream); +EXTERN int feof(FAR FILE *stream); +EXTERN int ferror(FAR FILE *stream); +EXTERN int fileno(FAR FILE *stream); +EXTERN int fgetc(FAR FILE *stream); +EXTERN int fgetpos(FAR FILE *stream, FAR fpos_t *pos); +EXTERN char *fgets(FAR char *s, int n, FAR FILE *stream); +EXTERN FAR FILE *fopen(FAR const char *path, FAR const char *type); +EXTERN int fprintf(FAR FILE *stream, FAR const char *format, ...); +EXTERN int fputc(int c, FAR FILE *stream); +EXTERN int fputs(FAR const char *s, FAR FILE *stream); +EXTERN size_t fread(FAR void *ptr, size_t size, size_t n_items, FAR FILE *stream); +EXTERN int fseek(FAR FILE *stream, long int offset, int whence); +EXTERN int fsetpos(FAR FILE *stream, FAR fpos_t *pos); +EXTERN long ftell(FAR FILE *stream); +EXTERN size_t fwrite(FAR const void *ptr, size_t size, size_t n_items, FAR FILE *stream); +EXTERN FAR char *gets(FAR char *s); + +EXTERN int printf(const char *format, ...); +EXTERN int puts(FAR const char *s); +EXTERN int rename(FAR const char *oldpath, FAR const char *newpath); +EXTERN int sprintf(FAR char *buf, const char *format, ...); +EXTERN int asprintf (FAR char **ptr, const char *fmt, ...); +EXTERN int snprintf(FAR char *buf, size_t size, const char *format, ...); +EXTERN int sscanf(const char *buf, const char *fmt, ...); + +EXTERN int ungetc(int c, FAR FILE *stream); +EXTERN int vprintf(FAR const char *format, va_list ap); +EXTERN int vfprintf(FAR FILE *stream, const char *format, va_list ap); +EXTERN int vsprintf(FAR char *buf, const char *format, va_list ap); +EXTERN int avsprintf(FAR char **ptr, const char *fmt, va_list ap); +EXTERN int vsnprintf(FAR char *buf, size_t size, const char *format, va_list ap); +EXTERN int vsscanf(char *buf, const char *s, va_list ap); + +/* POSIX-like File System Interfaces */ + +EXTERN FAR FILE *fdopen(int fd, FAR const char *type); +EXTERN int statfs(FAR const char *path, FAR struct statfs *buf); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_STDIO_H */ diff --git a/nuttx/include/stdlib.h b/nuttx/include/stdlib.h new file mode 100644 index 0000000000..27696e0fae --- /dev/null +++ b/nuttx/include/stdlib.h @@ -0,0 +1,192 @@ +/**************************************************************************** + * include/stdlib.h + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_STDLIB_H +#define __INCLUDE_STDLIB_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* The C standard specifies two constants, EXIT_SUCCESS and + * EXIT_FAILURE, that may be passed to exit() to indicate + * successful or unsucessful termination, respectively. + */ + +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 + +/* The NULL pointer should be defined in this file but is currently defined + * in sys/types.h. + */ + +/* Maximum value returned by rand() */ + +#define MAX_RAND 32767 + +/* Integer expression whose value is the maximum number of bytes in a + * character specified by the current locale. + */ + +#define MB_CUR_MAX 1 + +/* The environ variable, normally 'extern char **environ;' is + * not implemented as a function call. However, get_environ_ptr() + * can be used in its place. + */ + +#ifndef CONFIG_DISABLE_ENIVRON +# define environ get_environ_ptr() +#endif + +/**************************************************************************** + * Global Type Definitions + ****************************************************************************/ + +struct mallinfo +{ + int arena; /* This is the total size of memory allocated + * for use by malloc in bytes. */ + int ordblks; /* This is the number of free (not in use) chunks */ + int mxordblk; /* Size of the largest free (not in use) chunk */ + int uordblks; /* This is the total size of memory occupied by + * chunks handed out by malloc. */ + int fordblks; /* This is the total size of memory occupied + * by free (not in use) chunks.*/ +}; + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Random number generation */ + +EXTERN void srand(unsigned int seed); +EXTERN int rand(void); + +/* Environment variable support */ + +#ifndef CONFIG_DISABLE_ENIVRON +EXTERN FAR char **get_environ_ptr( void ); +EXTERN FAR char *getenv(FAR const char *name); +EXTERN int putenv(FAR const char *string); +EXTERN int clearenv(void); +EXTERN int setenv(const char *name, const char *value, int overwrite); +EXTERN int unsetenv(const char *name); +#endif + +/* Process exit functions */ + +EXTERN void exit(int status) noreturn_function; +EXTERN void abort(void) noreturn_function; +#ifdef CONFIG_SCHED_ATEXIT +EXTERN int atexit(CODE void (*func)(void)); +#endif +#ifdef CONFIG_SCHED_ONEXIT +EXTERN int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg); +#endif + +/* String to binary conversions */ + +EXTERN long strtol(const char *, char **, int); +EXTERN unsigned long strtoul(const char *, char **, int); +#ifdef CONFIG_HAVE_LONG_LONG +EXTERN long long strtoll(const char *, char **, int); +EXTERN unsigned long long strtoull(const char *, char **, int); +#endif +EXTERN double_t strtod(const char *, char **); + +#define atoi(nptr) strtol((nptr), NULL, 10) +#define atol(nptr) strtol((nptr), NULL, 10) +#ifdef CONFIG_HAVE_LONG_LONG +#define atoll(nptr) strtoll((nptr), NULL, 10) +#endif +#define atof(nptr) strtod((nptr), NULL) + +/* Memory Management */ + +EXTERN FAR void *malloc(size_t); +EXTERN void free(FAR void*); +EXTERN FAR void *realloc(FAR void*, size_t); +EXTERN FAR void *memalign(size_t, size_t); +EXTERN FAR void *zalloc(size_t); +EXTERN FAR void *calloc(size_t, size_t); + +/* Misc */ + +EXTERN int abs(int j); +EXTERN long int labs(long int j); +#ifdef CONFIG_HAVE_LONG_LONG +EXTERN long long int llabs(long long int j); +#endif + +/* Sorting */ + +EXTERN void qsort(void *base, size_t nmemb, size_t size, + int(*compar)(const void *, const void *)); + +#ifdef CONFIG_CAN_PASS_STRUCTS +EXTERN struct mallinfo mallinfo(void); +#else +EXTERN int mallinfo(struct mallinfo *info); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_STDLIB_H */ diff --git a/nuttx/include/string.h b/nuttx/include/string.h new file mode 100644 index 0000000000..7aa028bfac --- /dev/null +++ b/nuttx/include/string.h @@ -0,0 +1,104 @@ +/**************************************************************************** + * include/string.h + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_STRING_H +#define __INCLUDE_STRING_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Compatibility definitions */ + +#ifndef CONFIG_ARCH_BZERO +# define bzero(s,n) (void)memset(s,0,n) +#endif + +#define bcopy(b1,b2,len) (void)memmove(b2,b1,len) + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN FAR char *strdup(FAR const char *s); +EXTERN FAR char *strndup(FAR const char *s, size_t size); +EXTERN FAR const char *strerror(int); +EXTERN size_t strlen(FAR const char *); +EXTERN size_t strnlen(FAR const char *, size_t); +EXTERN FAR char *strcat(FAR char *, FAR const char *); +EXTERN FAR char *strncat(FAR char *, FAR const char *, size_t); +EXTERN int strcmp(FAR const char *, FAR const char *); +EXTERN int strncmp(FAR const char *, FAR const char *, size_t); +EXTERN int strcasecmp(FAR const char *, FAR const char *); +EXTERN int strncasecmp(FAR const char *, FAR const char *, size_t); +EXTERN FAR char *strcpy(char *dest, FAR const char *src); +EXTERN FAR char *strncpy(char *, FAR const char *, size_t); +EXTERN FAR char *strpbrk(FAR const char *, FAR const char *); +EXTERN FAR char *strchr(FAR const char *s, int c); +EXTERN FAR char *strrchr(FAR const char *s, int c); +EXTERN size_t strspn(FAR const char *, FAR const char *); +EXTERN size_t strcspn(FAR const char *, FAR const char *); +EXTERN FAR char *strstr(FAR const char *, FAR const char *); +EXTERN FAR char *strcasestr(FAR const char *, FAR const char *); +EXTERN FAR char *strtok(FAR char *, FAR const char *); +EXTERN FAR char *strtok_r(FAR char *, FAR const char *, FAR char **); + +EXTERN FAR void *memchr(FAR const void *s, int c, size_t n); +EXTERN FAR void *memccpy(FAR void *s1, FAR const void *s2, int c, size_t n); +EXTERN int memcmp(FAR const void *s1, FAR const void *s2, size_t n); +EXTERN FAR void *memcpy(FAR void *dest, FAR const void *src, size_t n); +EXTERN FAR void *memmove(FAR void *dest, FAR const void *src, size_t count); +EXTERN FAR void *memset(FAR void *s, int c, size_t n); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __INCLUDE_STRING_H */ diff --git a/nuttx/include/sys/ioctl.h b/nuttx/include/sys/ioctl.h new file mode 100644 index 0000000000..3d1874869a --- /dev/null +++ b/nuttx/include/sys/ioctl.h @@ -0,0 +1,83 @@ +/**************************************************************************** + * include/sys/ioctl.h + * + * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_IOCTL_H +#define __INCLUDE_SYS_IOCTL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Get NuttX configuration and NuttX-specific IOCTL definitions */ + +#include +#include + +/* Include network ioctls info */ + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 +# include +#endif + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* ioctl() is a non-standard UNIX-like API */ + +EXTERN int ioctl(int fd, int req, unsigned long arg); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_SYS_IOCTL_H */ diff --git a/nuttx/include/sys/mman.h b/nuttx/include/sys/mman.h new file mode 100644 index 0000000000..ab847b97a6 --- /dev/null +++ b/nuttx/include/sys/mman.h @@ -0,0 +1,113 @@ +/**************************************************************************** + * include/sys/mman.h + * + * Copyright (C) 2008, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_MMAN_H +#define __INCLUDE_SYS_MMAN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Protections are chosen from these bits, OR'd together. NuttX does not + * support any of these, but are provided for source level compatibility + */ + +#define PROT_NONE 0x0 /* Page may not be accessed */ +#define PROT_READ 0x1 /* Page may be read */ +#define PROT_WRITE 0x2 /* Page may be written */ +#define PROT_EXEC 0x4 /* Page may be executed */ + +/* Sharing types -- ignored by NuttX. */ + +#define MAP_SHARED 0x00001 /* Share this mapping */ +#define MAP_PRIVATE 0x00002 /* Create a private copy-on-write mapping */ +#define MAP_TYPE 0x0000f /* Mask for type of mapping */ +#define MAP_FIXED 0x00010 /* Map to specified address exactly */ +#define MAP_FILE 0x00000 /* The mapping is backed by a file */ +#define MAP_ANONYMOUS 0x00020 /* The mapping is not backed by any file */ +#define MAP_ANON MAP_ANONYMOUS + +/* These are Linux-specific. */ + +#define MAP_GROWSDOWN 0x00100 /* Used to stack allocations */ +#define MAP_DENYWRITE 0x00800 /* Do not permit writes to file */ +#define MAP_EXECUTABLE 0x01000 /* Mark it as an executable */ +#define MAP_LOCKED 0x02000 /* Lock pages mapped into memory */ +#define MAP_NORESERVE 0x04000 /* Do not reserve swap space for this mapping */ +#define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables */ +#define MAP_NONBLOCK 0x10000 /* Do not block on IO */ + +/* Failure return */ + +#define MAP_FAILED ((void*)-1) + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN FAR void *mmap(FAR void *start, size_t length, int prot, int flags, + int fd, off_t offset); + +#ifdef CONFIG_FS_RAMMAP +EXTERN int munmap(FAR void *start, size_t length); +#else +# define munmap(start, length) +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_SYS_MMAN_H */ diff --git a/nuttx/include/sys/mount.h b/nuttx/include/sys/mount.h new file mode 100644 index 0000000000..194dec8ccd --- /dev/null +++ b/nuttx/include/sys/mount.h @@ -0,0 +1,77 @@ +/**************************************************************************** + * include/sys/mount.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_MOUNT_H +#define __INCLUDE_SYS_MOUNT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Mount flags */ + +#define MS_RDONLY 1 /* Mount file system read-only */ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN int mount(const char *source, const char *target, + const char *filesystemtype, unsigned long mountflags, + const void *data); +EXTERN int umount(const char *target); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_SYS_MOUNT_H */ diff --git a/nuttx/include/sys/prctl.h b/nuttx/include/sys/prctl.h new file mode 100644 index 0000000000..f1441a77a6 --- /dev/null +++ b/nuttx/include/sys/prctl.h @@ -0,0 +1,114 @@ +/**************************************************************************** + * include/sys/prctl.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_PRCTL_H +#define __INCLUDE_SYS_PRCTL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Supported prctl() commands. + * + * PR_SET_NAME + * Set the task (or thread) name for the thread whose ID is in required + * arg2 (int), using the value in the location pointed to by required arg1 + * (char*). The name can be up to CONFIG_TASK_NAME_SIZE long (including + * any null termination). The thread ID of 0 will set the name of the + * calling thread. As an example: + * + * prctl(PR_SET_NAME, "MyName", 0); + * + * PR_GET_NAME + * Return the task (or thread) name for the for the thread whose ID is + * optional arg2 (int), in the buffer pointed to by optional arg1 (char *). + * The buffer must be CONFIG_TASK_NAME_SIZE long (including any null + * termination). As an example: + * + * char myname[CONFIG_TASK_NAME_SIZE]; + * prctl(PR_GET_NAME, myname, 0); + */ + + #define PR_SET_NAME 1 + #define PR_GET_NAME 2 + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: prctl + * + * Description: + * prctl() is called with a first argument describing what to do (with + * values PR_* defined above) and with additional arguments depending on + * the specific command. + * + * Returned Value: + * The returned value may depend on the specific commnand. For PR_SET_NAME + * and PR_GET_NAME, the returned value of 0 indicates successful operation. + * On any failure, -1 is retruend and the errno value is set appropriately. + * + * EINVAL The value of 'option' is not recognized. + * EFAULT optional arg1 is not a valid address. + * ESRCH No task/thread can be found corresponding to that specified + * by optional arg1. + * + ****************************************************************************/ + +EXTERN int prctl(int option, ...); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_SYS_PRCTL_H */ diff --git a/nuttx/include/sys/select.h b/nuttx/include/sys/select.h new file mode 100644 index 0000000000..1ff074b6c4 --- /dev/null +++ b/nuttx/include/sys/select.h @@ -0,0 +1,121 @@ +/**************************************************************************** + * include/sys/select.h + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_SELECT_H +#define __INCLUDE_SYS_SELECT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Get the total number of descriptors that we will have to support */ + +#define __SELECT_NDESCRIPTORS (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS) + +/* We will use a 32-bit bitsets to represent the set of descriptors. How + * many uint32_t's do we need to span all descriptors? + */ + +#if __SELECT_NDESCRIPTORS <= 32 +# define __SELECT_NUINT32 1 +#elif __SELECT_NDESCRIPTORS <= 64 +# define __SELECT_NUINT32 2 +#elif __SELECT_NDESCRIPTORS <= 96 +# define __SELECT_NUINT32 3 +#elif __SELECT_NDESCRIPTORS <= 128 +# define __SELECT_NUINT32 4 +#elif __SELECT_NDESCRIPTORS <= 160 +# define __SELECT_NUINT32 5 +#elif __SELECT_NDESCRIPTORS <= 192 +# define __SELECT_NUINT32 6 +#elif __SELECT_NDESCRIPTORS <= 224 +# define __SELECT_NUINT32 7 +#elif __SELECT_NDESCRIPTORS <= 256 +# define __SELECT_NUINT32 8 +#else +# warning "Large fd_set needed" +#endif + +/* These macros map a file descripto to an index and bit number */ + +#define _FD_NDX(fd) ((fd) >> 5) +#define _FD_BIT(fd) ((fd) & 0x1f) + +/* Standard helper macros */ + +#define FD_CLR(fd,set) (((uint32_t*)(set))[_FD_NDX(fd)] &= ~(1 << _FD_BIT(fd))) +#define FD_SET(fd,set) (((uint32_t*)(set))[_FD_NDX(fd)] |= (1 << _FD_BIT(fd))) +#define FD_ISSET(fd,set) ((((uint32_t*)(set))[_FD_NDX(fd)] & (1 << _FD_BIT(fd))) != 0) +#define FD_ZERO(set) memset(set, 0, sizeof(fd_set)) + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +typedef uint32_t fd_set[__SELECT_NUINT32]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds, + FAR fd_set *exceptfds, FAR struct timeval *timeout); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* CONFIG_NFILE_DESCRIPTORS || CONFIG_NSOCKET_DESCRIPTORS */ +#endif /* __INCLUDE_SYS_SELECT_H */ diff --git a/nuttx/include/sys/socket.h b/nuttx/include/sys/socket.h new file mode 100644 index 0000000000..89ade941ff --- /dev/null +++ b/nuttx/include/sys/socket.h @@ -0,0 +1,234 @@ +/**************************************************************************** + * include/sys/socket.h + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_SOCKET_H +#define __INCLUDE_SYS_SOCKET_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* The socket()domain parameter specifies a communication domain; this selects + * the protocol family which will be used for communication. + */ + +/* Protocol families */ + +#define PF_UNSPEC 0 /* Protocol family unspecified */ +#define PF_UNIX 1 /* Local communication */ +#define PF_LOCAL 1 /* Local communication */ +#define PF_INET 2 /* IPv4 Internet protocols */ +#define PF_INET6 3 /* IPv6 Internet protocols */ +#define PF_IPX 4 /* IPX - Novell protocols */ +#define PF_NETLINK 5 /* Kernel user interface device */ +#define PF_X25 6 /* ITU-T X.25 / ISO-8208 protocol */ +#define PF_AX25 7 /* Amateur radio AX.25 protocol */ +#define PF_ATMPVC 8 /* Access to raw ATM PVCs */ +#define PF_APPLETALK 9 /* Appletalk */ +#define PF_PACKET 10 /* Low level packet interface */ + +/* Address families */ + +#define AF_UNSPEC PF_UNSPEC +#define AF_UNIX PF_UNIX +#define AF_LOCAL PF_LOCAL +#define AF_INET PF_INET +#define AF_INET6 PF_INET6 +#define AF_IPX PF_IPX +#define AF_NETLINK PF_NETLINK +#define AF_X25 PF_X25 +#define AF_AX25 PF_AX25 +#define AF_ATMPVC PF_ATMPVC +#define AF_APPLETALK PF_APPLETALK +#define AF_PACKET PF_PACKET + +/* The socket created by socket() has the indicated type, which specifies + * the communication semantics. + */ + +#define SOCK_STREAM 0 /* Provides sequenced, reliable, two-way, connection-based byte streams. + * An out-of-band data transmission mechanism may be supported. */ +#define SOCK_DGRAM 1 /* Supports datagrams (connectionless, unreliable messages of a fixed + * maximum length). */ +#define SOCK_SEQPACKET 2 /* Provides a sequenced, reliable, two-way connection-based data + * transmission path for datagrams of fixed maximum length; a consumer + * is required to read an entire packet with each read system call. */ +#define SOCK_RAW 3 /* Provides raw network protocol access. */ +#define SOCK_RDM 4 /* Provides a reliable datagram layer that does not guarantee ordering. */ +#define SOCK_PACKET 5 /* Obsolete and should not be used in new programs */ + +/* Bits in the FLAGS argument to `send', `recv', et al. These are the bits + * recognized by Linus, not all are supported by NuttX. + */ + +#define MSG_OOB 0x0001 /* Process out-of-band data. */ +#define MSG_PEEK 0x0002 /* Peek at incoming messages. */ +#define MSG_DONTROUTE 0x0004 /* Don't use local routing. */ +#define MSG_CTRUNC 0x0008 /* Control data lost before delivery. */ +#define MSG_PROXY 0x0010 /* Supply or ask second address. */ +#define MSG_TRUNC 0x0020 +#define MSG_DONTWAIT 0x0040 /* Enable nonblocking IO. */ +#define MSG_EOR 0x0080 /* End of record. */ +#define MSG_WAITALL 0x0100 /* Wait for a full request. */ +#define MSG_FIN 0x0200 +#define MSG_SYN 0x0400 +#define MSG_CONFIRM 0x0800 /* Confirm path validity. */ +#define MSG_RST 0x1000 +#define MSG_ERRQUEUE 0x2000 /* Fetch message from error queue. */ +#define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE. */ +#define MSG_MORE 0x8000 /* Sender will send more. */ + +/* Socket options */ + +#define SO_DEBUG 0 /* Enables recording of debugging information (get/set). + * arg: pointer to integer containing a boolean value */ +#define SO_ACCEPTCONN 1 /* Reports whether socket listening is enabled (get only). + * arg: pointer to integer containing a boolean value */ +#define SO_BROADCAST 2 /* Permits sending of broadcast messages (get/set). + * arg: pointer to integer containing a boolean value */ +#define SO_REUSEADDR 3 /* Allow reuse of local addresses (get/set) + * arg: pointer to integer containing a boolean value */ +#define SO_KEEPALIVE 4 /* Keeps connections active by enabling the periodic transmission + * of messages (get/set). + * arg: pointer to integer containing a boolean value */ +#define SO_LINGER 5 /* Lingers on a close() if data is present (get/set) + * arg: struct linger */ +#define SO_OOBINLINE 6 /* Leaves received out-of-band data (data marked urgent) inline + * (get/set) arg: pointer to integer containing a boolean value */ +#define SO_SNDBUF 7 /* Sets send buffer size. arg: integer value (get/set). */ +#define SO_RCVBUF 8 /* Sets receive buffer size. arg: integer value (get/set). */ +#define SO_ERROR 9 /* Reports and clears error status (get only). arg: returns + * an integer value */ +#define SO_TYPE 10 /* Reports the socket type (get only). return: int */ +#define SO_DONTROUTE 11 /* Requests that outgoing messages bypass standard routing (get/set) + * arg: pointer to integer containing a boolean value */ +#define SO_RCVLOWAT 12 /* Sets the minimum number of bytes to process for socket input + * (get/set). arg: integer value */ +#define SO_RCVTIMEO 13 /* Sets the timeout value that specifies the maximum amount of time + * an input function waits until it completes (get/set). + * arg: struct timeval */ +#define SO_SNDLOWAT 14 /* Sets the minimum number of bytes to process for socket output + * (get/set). arg: integer value */ +#define SO_SNDTIMEO 15 /* Sets the timeout value specifying the amount of time that an + * output function blocks because flow control prevents data from + * being sent(get/set). arg: struct timeval */ + +/* Protocol levels supported by get/setsockopt(): */ + +#define SOL_SOCKET 0 /* Only socket-level options supported */ + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + + /* sockaddr_storage structure. This structure must be (1) large enough to + * accommodate all supported protocol-specific address structures, and (2) + * aligned at an appropriate boundary so that pointers to it can be cast + * as pointers to protocol-specific address structures and used to access + * the fields of those structures without alignment problems + */ + +#ifdef CONFIG_NET_IPv6 +struct sockaddr_storage +{ + sa_family_t ss_family; /* Address family */ + char ss_data[18]; /* 18-bytes of address data */ +}; +#else +struct sockaddr_storage +{ + sa_family_t ss_family; /* Address family */ + char ss_data[14]; /* 14-bytes of address data */ +}; +#endif + +/* The sockaddr structure is used to define a socket address which is used + * in the bind(), connect(), getpeername(), getsockname(), recvfrom(), and + * sendto() functions. + */ + +struct sockaddr +{ + sa_family_t sa_family; /* Address family: See AF_* definitions */ + char sa_data[14]; /* 14-bytes of address data */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN int socket(int domain, int type, int protocol); +EXTERN int bind(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen); +EXTERN int connect(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen); + +EXTERN int listen(int sockfd, int backlog); +EXTERN int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); + +EXTERN ssize_t send(int sockfd, FAR const void *buf, size_t len, int flags); +EXTERN ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags, + FAR const struct sockaddr *to, socklen_t tolen); + +EXTERN ssize_t recv(int sockfd, FAR void *buf, size_t len, int flags); +EXTERN ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags, + FAR struct sockaddr *from, FAR socklen_t *fromlen); + +EXTERN int setsockopt(int sockfd, int level, int option, + FAR const void *value, socklen_t value_len); +EXTERN int getsockopt(int sockfd, int level, int option, + FAR void *value, FAR socklen_t *value_len); + +EXTERN int getsockname(int sockfd, FAR struct sockaddr *addr, + FAR socklen_t *addrlen); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_SYS_SOCKET_H */ diff --git a/nuttx/include/sys/sockio.h b/nuttx/include/sys/sockio.h new file mode 100644 index 0000000000..abfc2f562f --- /dev/null +++ b/nuttx/include/sys/sockio.h @@ -0,0 +1,120 @@ +/**************************************************************************** + * include/sys/sockio.h + * + * Copyright (C) 2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_SOCKIO_H +#define __INCLUDE_SYS_SOCKIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Get NuttX configuration and NuttX-specific network IOCTL definitions */ + +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#define IMSFNAMSIZ 8 + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + + /* RFC3678: IPv4 Options + * + * o ioctl() SIOCGIPMSFILTER: to retrieve the list of source addresses + * that comprise the source filter along with the current filter mode. + * + * o ioctl() SIOCSIPMSFILTER: to set or modify the source filter content + * (e.g., unicast source address list) or mode (exclude or include). + * + * Ioctl option Argument type + * ----------------------------- ---------------------- + * SIOCGIPMSFILTER struct ip_msfilter + * SIOCSIPMSFILTER struct ip_msfilter + * + * The imsf_fmode mode is a 32-bit integer that identifies the filter + * mode. The value of this field must be either MCAST_INCLUDE or + * MCAST_EXCLUDE, which are likewise defined in . + */ + +#if 0 /* REVISIT: Current NuttX implementation is non-standard. + * Lookup is by device name, not IP address. + */ + +struct ip_msfilter +{ + struct in_addr imsf_multiaddr; /* IP multicast address of group */ + struct in_addr imsf_interface; /* Local IP address of interface */ + uint32_t imsf_fmode; /* Filter mode */ +#ifdef CONFIG_NET_IGMPv3 + uint32_t imsf_numsrc; /* number of sources in src_list */ + struct in_addr imsf_slist[1]; /* start of source list */ +#endif +}; + +#else + +struct ip_msfilter +{ + char imsf_name[IMSFNAMSIZ]; /* Network device name, e.g., "eth0" */ + struct in_addr imsf_multiaddr; /* IP multicast address of group */ + uint32_t imsf_fmode; /* Filter mode */ +}; + +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_SYS_SOCKIO_H */ diff --git a/nuttx/include/sys/stat.h b/nuttx/include/sys/stat.h new file mode 100644 index 0000000000..1204b15aa6 --- /dev/null +++ b/nuttx/include/sys/stat.h @@ -0,0 +1,134 @@ +/**************************************************************************** + * include/sys/stat.h + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_STAT_H +#define __INCLUDE_SYS_STAT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* mode_t bit settings (most of these do not apply to Nuttx). This assumes + * that the full size of a mode_t is 16-bits. (However, mode_t must be size + * 'int' because it is promoted to size int when passed in varargs). + */ + +#define S_IXOTH 0000001 /* Permissions for others: RWX */ +#define S_IWOTH 0000002 +#define S_IROTH 0000004 +#define S_IRWXO 0000007 + +#define S_IXGRP 0000010 /* Group permissions: RWX */ +#define S_IWGRP 0000020 +#define S_IRGRP 0000040 +#define S_IRWXG 0000070 + +#define S_IXUSR 0000100 /* Owner permissions: RWX */ +#define S_IWUSR 0000200 +#define S_IRUSR 0000400 +#define S_IRWXU 0000700 + +#define S_ISVTX 0001000 /* "sticky" bit */ +#define S_ISGID 0002000 /* Set group ID bit */ +#define S_ISUID 0004000 /* Set UID bit */ + +#define S_IFIFO 0010000 /* File type bites */ +#define S_IFCHR 0020000 +#define S_IFDIR 0040000 +#define S_IFBLK 0060000 +#define S_IFREG 0100000 +#define S_IFLNK 0120000 +#define S_IFSOCK 0140000 +#define S_IFMT 0170000 + +/* File type macros that operate on an instance of mode_t */ + +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/* This is the simplified struct stat as returned by fstat(). This structure + * provides information about a specific file or directory in the file system. + */ + +struct stat +{ + mode_t st_mode; /* File type, atributes, and access mode bits */ + off_t st_size; /* Size of file/directory, in bytes */ + blksize_t st_blksize; /* Blocksize used for filesystem I/O */ + blkcnt_t st_blocks; /* Number of blocks allocated */ + time_t st_atime; /* Time of last access */ + time_t st_mtime; /* Time of last modification */ + time_t st_ctime; /* Time of last status change */ +}; + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN int mkdir(FAR const char *pathname, mode_t mode); +EXTERN int mkfifo(FAR const char *pathname, mode_t mode); +EXTERN int stat(const char *path, FAR struct stat *buf); +EXTERN int fstat(int fd, FAR struct stat *buf); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_SYS_STAT_H */ diff --git a/nuttx/include/sys/statfs.h b/nuttx/include/sys/statfs.h new file mode 100644 index 0000000000..70e963dd99 --- /dev/null +++ b/nuttx/include/sys/statfs.h @@ -0,0 +1,145 @@ +/**************************************************************************** + * include/sys/statfs.h + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_STATFS_H +#define __INCLUDE_SYS_STATFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* struct statfs file system types. */ + +#define ADFS_SUPER_MAGIC 0xadf5 +#define AFFS_SUPER_MAGIC 0xadff +#define BEFS_SUPER_MAGIC 0x42465331 +#define BFS_MAGIC 0x1badface +#define CIFS_MAGIC_NUMBER 0xff534d42 +#define CODA_SUPER_MAGIC 0x73757245 +#define COH_SUPER_MAGIC 0x012ff7b7 +#define CRAMFS_MAGIC 0x28cd3d45 +#define DEVFS_SUPER_MAGIC 0x1373 +#define EFS_SUPER_MAGIC 0x00414a53 +#define EXT_SUPER_MAGIC 0x137d +#define EXT2_OLD_SUPER_MAGIC 0xef51 +#define EXT2_SUPER_MAGIC 0xef53 +#define EXT3_SUPER_MAGIC 0xef53 +#define HFS_SUPER_MAGIC 0x4244 +#define HPFS_SUPER_MAGIC 0xf995e849 +#define HUGETLBFS_MAGIC 0x958458f6 +#define ISOFS_SUPER_MAGIC 0x9660 +#define JFFS2_SUPER_MAGIC 0x72b6 +#define JFS_SUPER_MAGIC 0x3153464a +#define MINIX_SUPER_MAGIC 0x137f /* orig. minix */ +#define MINIX_SUPER_MAGIC2 0x138f /* 30 char minix */ +#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 */ +#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2, 30 char names */ +#define MSDOS_SUPER_MAGIC 0x4d44 +#define NCP_SUPER_MAGIC 0x564c +#define NFS_SUPER_MAGIC 0x6969 +#define NTFS_SB_MAGIC 0x5346544e +#define OPENPROM_SUPER_MAGIC 0x9fa1 +#define PROC_SUPER_MAGIC 0x9fa0 +#define QNX4_SUPER_MAGIC 0x002f +#define REISERFS_SUPER_MAGIC 0x52654973 +#define ROMFS_MAGIC 0x7275 +#define SMB_SUPER_MAGIC 0x517B +#define SYSV2_SUPER_MAGIC 0x012ff7b6 +#define SYSV4_SUPER_MAGIC 0x012FF7B5 +#define TMPFS_MAGIC 0x01021994 +#define UDF_SUPER_MAGIC 0x15013346 +#define UFS_MAGIC 0x00011954 +#define USBDEVICE_SUPER_MAGIC 0x9fa2 +#define VXFS_SUPER_MAGIC 0xa501fcf5 +#define XENIX_SUPER_MAGIC 0x012ff7b4 +#define XFS_SUPER_MAGIC 0x58465342 +#define _XIAFS_SUPER_MAGIC 0x012fd16d + +/* NuttX specific file-systems */ + +#define BINFS_MAGIC 0x4242 +#define NXFFS_MAGIC 0x4747 + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +struct statfs +{ + uint32_t f_type; /* Type of filesystem (see definitions above) */ + size_t f_namelen; /* Maximum length of filenames */ + size_t f_bsize; /* Optimal block size for transfers */ + off_t f_blocks; /* Total data blocks in the file system of this size */ + off_t f_bfree; /* Free blocks in the file system */ + off_t f_bavail; /* Free blocks avail to non-superuser */ + off_t f_files; /* Total file nodes in the file system */ + off_t f_ffree; /* Free file nodes in the file system */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Inspired by Linux statfs() which was, in turn, inspired by + * the BSD statfs(). None of these implementations agree in the + * form of the struct statfs. + */ + +EXTERN int statfs(const char *path, struct statfs *buf); +EXTERN int fstatfs(int fd, struct statfs *buf); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_SYS_STATFS_H */ diff --git a/nuttx/include/sys/syscall.h b/nuttx/include/sys/syscall.h new file mode 100644 index 0000000000..57545beb7d --- /dev/null +++ b/nuttx/include/sys/syscall.h @@ -0,0 +1,398 @@ +/**************************************************************************** + * include/sys/syscall.h + * This file contains the system call numbers. + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_SYSCALL_H +#define __INCLUDE_SYS_SYSCALL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Reserve the first system calls for platform-specific usage if so + * configured. + */ + +#ifndef CONFIG_SYS_RESERVED +# define CONFIG_SYS_RESERVED (0) +#endif + +/* System call numbers + * + * These first system calls are supported regardless of the NuttX + * configuration + */ + +#define SYS__exit (CONFIG_SYS_RESERVED+0) +#define SYS_exit (CONFIG_SYS_RESERVED+1) +#define SYS_get_errno (CONFIG_SYS_RESERVED+2) +#define SYS_getpid (CONFIG_SYS_RESERVED+3) +#define SYS_sched_getparam (CONFIG_SYS_RESERVED+4) +#define SYS_sched_getscheduler (CONFIG_SYS_RESERVED+5) +#define SYS_sched_lock (CONFIG_SYS_RESERVED+6) +#define SYS_sched_lockcount (CONFIG_SYS_RESERVED+7) +#define SYS_sched_rr_get_interval (CONFIG_SYS_RESERVED+8) +#define SYS_sched_setparam (CONFIG_SYS_RESERVED+9) +#define SYS_sched_setscheduler (CONFIG_SYS_RESERVED+10) +#define SYS_sched_unlock (CONFIG_SYS_RESERVED+11) +#define SYS_sched_yield (CONFIG_SYS_RESERVED+12) +#define SYS_sem_close (CONFIG_SYS_RESERVED+13) +#define SYS_sem_destroy (CONFIG_SYS_RESERVED+14) +#define SYS_sem_open (CONFIG_SYS_RESERVED+15) +#define SYS_sem_post (CONFIG_SYS_RESERVED+16) +#define SYS_sem_trywait (CONFIG_SYS_RESERVED+17) +#define SYS_sem_unlink (CONFIG_SYS_RESERVED+18) +#define SYS_sem_wait (CONFIG_SYS_RESERVED+19) +#define SYS_set_errno (CONFIG_SYS_RESERVED+20) +#define SYS_task_create (CONFIG_SYS_RESERVED+21) +#define SYS_task_delete (CONFIG_SYS_RESERVED+22) +#define SYS_task_restart (CONFIG_SYS_RESERVED+23) +#define SYS_up_assert (CONFIG_SYS_RESERVED+24) +#define SYS_up_assert_code (CONFIG_SYS_RESERVED+25) +#define __SYS_atexit (CONFIG_SYS_RESERVED+26) + +/* The following can be individually enabled */ + +#ifdef CONFIG_SCHED_ATEXIT +# define SYS_atexit __SYS_atexit +# define __SYS_onexit (__SYS_atexit+1) +#else +# define __SYS_onexit __SYS_atexit +#endif + +#ifdef CONFIG_SCHED_ONEXIT +# define SYS_onexit __SYS_onexit +# define __SYS_waitpaid (__SYS_onexit+1) +#else +# define __SYS_waitpaid __SYS_onexit +#endif + +#ifdef CONFIG_SCHED_WAITPID +# define SYS_waitpid __SYS_waitpaid +# define __SYS_signals (__SYS_waitpaid+1) +#else +# define __SYS_signals __SYS_waitpaid +#endif + +/* The following are only defined is signals are supported in the NuttX + * configuration. + */ + +#ifndef CONFIG_DISABLE_SIGNALS +# define SYS_kill (__SYS_signals+0) +# define SYS_sigaction (__SYS_signals+1) +# define SYS_sigpending (__SYS_signals+2) +# define SYS_sigprocmask (__SYS_signals+3) +# define SYS_sigqueue (__SYS_signals+4) +# define SYS_sigsuspend (__SYS_signals+5) +# define SYS_sigtimedwait (__SYS_signals+6) +# define SYS_sigwaitinfo (__SYS_signals+7) +# define SYS_sleep (__SYS_signals+8) +# define SYS_usleep (__SYS_signals+9) +# define __SYS_clock (__SYS_signals+10) +#else +# define __SYS_clock __SYS_signals +#endif + +/* The following are only defined if the system clock is enabled in the + * NuttX configuration. + */ + +#ifndef CONFIG_DISABLE_CLOCK +# define SYS_clock_systimer (__SYS_clock+0) +# define SYS_clock_getres (__SYS_clock+1) +# define SYS_clock_gettime (__SYS_clock+2) +# define SYS_clock_settime (__SYS_clock+3) +# define SYS_gettimeofday (__SYS_clock+4) +# define __SYS_timers (__SYS_clock+5) +#else +# define __SYS_timers __SYS_clock +#endif + +/* The following are defined only if POSIX timers are supported */ + +#ifndef CONFIG_DISABLE_POSIX_TIMERS +# define SYS_timer_create (__SYS_timers+0) +# define SYS_timer_delete (__SYS_timers+1) +# define SYS_timer_getoverrun (__SYS_timers+2) +# define SYS_timer_gettime (__SYS_timers+3) +# define SYS_timer_settime (__SYS_timers+4) +# define __SYS_descriptors (__SYS_timers+5) +#else +# define __SYS_descriptors __SYS_timers +#endif + +/* The following are defined if either file or socket descriptor are + * enabled. + */ + +#ifndef CONFIG_NET +# undef CONFIG_NSOCKET_DESCRIPTORS +# define CONFIG_NSOCKET_DESCRIPTORS 0 +#endif + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 +# define SYS_close (__SYS_descriptors+0) +# define SYS_ioctl (__SYS_descriptors+1) +# define SYS_read (__SYS_descriptors+2) +# define SYS_write (__SYS_descriptors+3) +# ifndef CONFIG_DISABLE_POLL +# define SYS_poll (__SYS_descriptors+4) +# define SYS_select (__SYS_descriptors+5) +# define __SYS_filedesc (__SYS_descriptors+6) +# else +# define __SYS_filedesc (__SYS_descriptors+4) +# endif +#else +# define __SYS_filedesc __SYS_descriptors +#endif + +/* The following are defined if file descriptors are enabled */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +# define SYS_closedir (__SYS_filedesc+0) +# define SYS_dup (__SYS_filedesc+1) +# define SYS_dup2 (__SYS_filedesc+2) +# define SYS_fcntl (__SYS_filedesc+3) +# define SYS_lseek (__SYS_filedesc+4) +# define SYS_mkfifo (__SYS_filedesc+5) +# define SYS_mmap (__SYS_filedesc+6) +# define SYS_open (__SYS_filedesc+7) +# define SYS_opendir (__SYS_filedesc+8) +# define SYS_pipe (__SYS_filedesc+9) +# define SYS_readdir (__SYS_filedesc+10) +# define SYS_rewinddir (__SYS_filedesc+11) +# define SYS_seekdir (__SYS_filedesc+12) +# define SYS_stat (__SYS_filedesc+13) +# define SYS_statfs (__SYS_filedesc+14) +# define SYS_telldir (__SYS_filedesc+15) + +# if CONFIG_NFILE_STREAMS > 0 +# define SYS_fs_fdopen (__SYS_filedesc+16) +# define SYS_sched_getstreams (__SYS_filedesc+17) +# define __SYS_mountpoint (__SYS_filedesc+18) +# else +# define __SYS_mountpoint (__SYS_filedesc+16) +# endif + +# if !defined(CONFIG_DISABLE_MOUNTPOINT) +# define SYS_fsync (__SYS_mountpoint+0) +# define SYS_mkdir (__SYS_mountpoint+1) +# define SYS_mount (__SYS_mountpoint+2) +# define SYS_rename (__SYS_mountpoint+3) +# define SYS_rmdir (__SYS_mountpoint+4) +# define SYS_umount (__SYS_mountpoint+5) +# define SYS_unlink (__SYS_mountpoint+6) +# define __SYS_pthread (__SYS_mountpoint+7) +# else +# define __SYS_pthread __SYS_mountpoint +# endif + +#else +# define __SYS_pthread __SYS_filedesc +#endif + +/* The following are defined if pthreads are enabled */ + +#ifndef CONFIG_DISABLE_PTHREAD +# define SYS_pthread_barrier_destroy (__SYS_pthread+0) +# define SYS_pthread_barrier_init (__SYS_pthread+1) +# define SYS_pthread_barrier_wait (__SYS_pthread+2) +# define SYS_pthread_cancel (__SYS_pthread+3) +# define SYS_pthread_cond_broadcast (__SYS_pthread+4) +# define SYS_pthread_cond_destroy (__SYS_pthread+5) +# define SYS_pthread_cond_init (__SYS_pthread+6) +# define SYS_pthread_cond_signal (__SYS_pthread+7) +# define SYS_pthread_cond_wait (__SYS_pthread+8) +# define SYS_pthread_create (__SYS_pthread+9) +# define SYS_pthread_detach (__SYS_pthread+10) +# define SYS_pthread_exit (__SYS_pthread+11) +# define SYS_pthread_getschedparam (__SYS_pthread+12) +# define SYS_pthread_getspecific (__SYS_pthread+13) +# define SYS_pthread_join (__SYS_pthread+14) +# define SYS_pthread_key_create (__SYS_pthread+15) +# define SYS_pthread_key_delete (__SYS_pthread+16) +# define SYS_pthread_mutex_destroy (__SYS_pthread+17) +# define SYS_pthread_mutex_init (__SYS_pthread+18) +# define SYS_pthread_mutex_lock (__SYS_pthread+19) +# define SYS_pthread_mutex_trylock (__SYS_pthread+20) +# define SYS_pthread_mutex_unlock (__SYS_pthread+21) +# define SYS_pthread_once (__SYS_pthread+22) +# define SYS_pthread_setcancelstate (__SYS_pthread+23) +# define SYS_pthread_setschedparam (__SYS_pthread+24) +# define SYS_pthread_setschedprio (__SYS_pthread+25) +# define SYS_pthread_setspecific (__SYS_pthread+26) +# define SYS_pthread_yield (__SYS_pthread+27) + +# ifndef CONFIG_DISABLE_SIGNAL +# define SYS_pthread_cond_timedwait (__SYS_pthread+28) +# define SYS_pthread_kill (__SYS_pthread+29) +# define SYS_pthread_sigmask (__SYS_pthread+30) +# define __SYS_mqueue (__SYS_pthread+31) +# else +# define __SYS_mqueue (__SYS_pthread+28) +# endif + +#else +# define __SYS_mqueue __SYS_pthread +#endif + +/* The following are defined only if message queues are enabled */ + +#ifndef CONFIG_DISABLE_MQUEUE +# define SYS_mq_close (__SYS_mqueue+0) +# define SYS_mq_notify (__SYS_mqueue+1) +# define SYS_mq_open (__SYS_mqueue+2) +# define SYS_mq_receive (__SYS_mqueue+3) +# define SYS_mq_send (__SYS_mqueue+4) +# define SYS_mq_timedreceive (__SYS_mqueue+5) +# define SYS_mq_timedsend (__SYS_mqueue+6) +# define SYS_mq_unlink (__SYS_mqueue+7) +# define __SYS_environ (__SYS_mqueue+8) +#else +# define __SYS_environ __SYS_mqueue +#endif + +/* The following are defined only if environment variables are supported */ + +#ifndef CONFIG_DISABLE_ENVIRON +# define SYS_clearenv (__SYS_environ+0) +# define SYS_getenv (__SYS_environ+1) +# define SYS_putenv (__SYS_environ+2) +# define SYS_setenv (__SYS_environ+3) +# define SYS_unsetenv (__SYS_environ+4) +# define __SYS_network (__SYS_environ+5) +#else +# define __SYS_network __SYS_environ +#endif + +/* The following are defined only if networking AND sockets are supported */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET) +# define SYS_accept (__SYS_network+0) +# define SYS_bind (__SYS_network+1) +# define SYS_connect (__SYS_network+2) +# define SYS_getsockopt (__SYS_network+3) +# define SYS_listen (__SYS_network+4) +# define SYS_recv (__SYS_network+5) +# define SYS_recvfrom (__SYS_network+6) +# define SYS_send (__SYS_network+7) +# define SYS_sendto (__SYS_network+8) +# define SYS_setsockopt (__SYS_network+9) +# define SYS_socket (__SYS_network+10) +# define SYS_nnetsocket (__SYS_network+11) +#else +# define SYS_nnetsocket __SYS_network +#endif + +/* The following is defined only if CONFIG_TASK_NAME_SIZE > 0 */ + +#if CONFIG_TASK_NAME_SIZE > 0 +# define SYS_prctl (SYS_nnetsocket+0) +# define SYS_maxsyscall (SYS_nnetsocket+1) +#else +# define SYS_maxsyscall SYS_nnetsocket +#endif + +/* Note that the reported number of system calls does *NOT* include the + * architecture-specific system calls. If the "real" total is required, + * use SYS_maxsyscall. + */ + +#define SYS_nsyscalls (SYS_maxsyscall-CONFIG_SYS_RESERVED) + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* This is the union of all possible stub function types */ + +union syscall_stubfunc_u +{ + uintptr_t (*stub0)(void); + uintptr_t (*stub1)(uintptr_t parm1); + uintptr_t (*stub2)(uintptr_t parm1, uintptr_t parm2); + uintptr_t (*stub3)(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); + uintptr_t (*stub4)(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, + uintptr_t parm4); + uintptr_t (*stub5)(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, + uintptr_t parm4, uintptr_t parm5); + uintptr_t (*stub6)(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, + uintptr_t parm4, uintptr_t parm5, uintptr_t parm6); +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Stub lookup tables. Each table is indexed by the system call numbers + * defined above. Given the system call number, the corresponding entry in + * these tables describes how to call the stub dispatch function. + */ + +EXTERN const union syscall_stubfunc_u g_stublookup[SYS_nsyscalls]; +EXTERN const uint8_t g_stubnparms[SYS_nsyscalls]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __INCLUDE_SYS_SYSCALL_H */ + diff --git a/nuttx/include/sys/time.h b/nuttx/include/sys/time.h new file mode 100644 index 0000000000..75dfd72808 --- /dev/null +++ b/nuttx/include/sys/time.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * include/sys/time.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_TIME_H +#define __INCLUDE_SYS_TIME_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN int gettimeofday(struct timeval *tp, FAR void *tzp); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_SYS_TIME_H */ diff --git a/nuttx/include/sys/types.h b/nuttx/include/sys/types.h new file mode 100644 index 0000000000..6014b9b74d --- /dev/null +++ b/nuttx/include/sys/types.h @@ -0,0 +1,229 @@ +/**************************************************************************** + * include/sys/types.h + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_TYPES_H +#define __INCLUDE_SYS_TYPES_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Alternative values for type bool (for historic reasons) */ + +#ifndef TRUE +# define TRUE 1 +#endif +#ifndef FALSE +# define FALSE 0 +#endif + +/* NULL is usually defined in stddef.h (which includes this file) */ + +#ifndef NULL + /* SDCC is sensitive to NULL pointer type conversions */ +# ifdef SDCC +# define NULL (0) +# else +# define NULL ((void*)0) +# endif +#endif + +/* POSIX-like OS return values: */ + +#if !defined(__cplusplus) +# undef ERROR +# define ERROR -1 +#endif + +#undef OK +#define OK 0 + +/* HPUX-like MIN/MAX value */ + +#define PRIOR_RR_MIN 0 +#define PRIOR_RR_MAX 255 +#define PRIOR_FIFO_MIN 0 +#define PRIOR_FIFO_MAX 255 +#define PRIOR_OTHER_MIN 0 +#define PRIOR_OTHER_MAX 255 + +/* Scheduling Priorities. NOTE: Only the idle task can take + * the true minimum priority. */ + +#define SCHED_PRIORITY_MAX 255 +#define SCHED_PRIORITY_DEFAULT 100 +#define SCHED_PRIORITY_MIN 1 +#define SCHED_PRIORITY_IDLE 0 + +/**************************************************************************** + * Type Declarations + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Floating point types */ + +typedef float float32; +#ifndef CONFIG_HAVE_DOUBLE +typedef float double_t; +typedef float float64; +#else +typedef double double_t; +typedef double float64; +#endif + +/* Misc. scalar types */ + +/* mode_t is an integer type used for file attributes. mode_t needs + * to be at least 16-bits but, in fact must be sizeof(int) because it is + * pased via varargs. + */ + +typedef unsigned int mode_t; + +/* size_t is used for sizes of memory objects. + * ssize_t is used for a count of bytes or an error indication. + */ + +#ifdef CONFIG_SMALL_MEMORY +typedef uint16_t size_t; +typedef int16_t ssize_t; +#else +typedef uint32_t size_t; +typedef int32_t ssize_t; +#endif + +/* uid_t is used for user IDs + * gid_t is used for group IDs. + */ + +typedef int16_t uid_t; +typedef int16_t gid_t; + +/* dev_t is used for device IDs */ + +typedef uint16_t dev_t; + +/* ino_t is used for file serial numbers */ + +typedef uint16_t ino_t; + +/* pid_t is used for process IDs and process group IDs */ + +typedef int pid_t; + +/* id_t is a general identifier that can be used to contain at least a pid_t, + * uid_t, or gid_t. + */ + +typedef unsigned int id_t; + +/* Signed integral type of the result of subtracting two pointers */ + +typedef intptr_t ptrdiff_t; + +/* Wide, 16-bit character types. wchar_t is a built-in type in C++ and + * its declaration here may cause compilation errors on some compilers + * if -DCONFIG_WCHAR_BUILTIN is not included in the CXXFLAGS. + */ + +#ifndef CONFIG_WCHAR_BUILTIN +typedef uint16_t wchar_t; +#endif + +/* blkcnt_t and off_t are signed integer types. + * + * blkcnt_t is used for file block counts. + * off_t is used for file offsets and sizes. + * fpos_t is used for file positions. + * + * Hence, all should be independent of processor architecture. + */ + +typedef uint32_t blkcnt_t; +typedef int32_t off_t; +typedef off_t fpos_t; + +/* Large file versions */ + +#ifdef CONFIG_HAVE_LONG_LONG +typedef int64_t off64_t; +typedef int64_t fpos64_t; +#endif + +/* blksize_t is a signed integer value used for file block sizes */ + +typedef int16_t blksize_t; + +/* Network related */ + +typedef unsigned int socklen_t; +typedef uint16_t sa_family_t; + +/* Used for system times in clock ticks */ + +typedef uint32_t clock_t; + +/* The type useconds_t shall be an unsigned integer type capable of storing + * values at least in the range [0, 1000000]. The type suseconds_t shall be + * a signed integer type capable of storing values at least in the range + * [-1, 1000000]. + */ + +typedef uint32_t useconds_t; +typedef int32_t suseconds_t; + +/* Task entry point */ + +typedef int (*main_t)(int argc, char *argv[]); + +#endif + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#endif /* __INCLUDE_SYS_TYPES_H */ diff --git a/nuttx/include/sys/vfs.h b/nuttx/include/sys/vfs.h new file mode 100644 index 0000000000..8433893c35 --- /dev/null +++ b/nuttx/include/sys/vfs.h @@ -0,0 +1,61 @@ +/**************************************************************************** + * include/sys/vfs.h + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_VFS_H +#define __INCLUDE_SYS_VFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* sys/vfs.h is just an alternative location for the information in + * sys/statfs.h. + */ + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __INCLUDE_SYS_VFS_H */ diff --git a/nuttx/include/sys/wait.h b/nuttx/include/sys/wait.h new file mode 100644 index 0000000000..6af1e971e4 --- /dev/null +++ b/nuttx/include/sys/wait.h @@ -0,0 +1,118 @@ +/**************************************************************************** + * include/sys/wait.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_WAIT_H +#define __INCLUDE_SYS_WAIT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifdef CONFIG_SCHED_WAITPID + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* The following are provided for analysis of returned status values. + * Encoded is as follows as 2 bytes of info(MS) then two bytes of code (LS). + * Code: + * 0 - Child has exited, info is the exit code. + * Other values - Not implemented + */ + +#define WEXITSTATUS(s) (((s) >> 8) & 0xff)/* Return exit status */ + +#define WIFEXITED(s) (((s) & 0xff) == 0) /* True: Child exited normally */ +#define WIFCONTINUED(s) (false) /* True: Child has been continued */ +#define WIFSIGNALED(s) (false) /* True: Child exited due to uncaught signal */ +#define WIFSTOPPED(s) (false) /* True: Child is currently stopped */ +#define WSTOPSIG(s) (false) /* Return signal number that caused process to stop */ +#define WTERMSIG(s) (false) /* Return signal number that caused process to terminate */ + +/* The following symbolic constants are possible values for the options + * argument to waitpi(1) (1) and/or waitid() (2), + */ + +#define WCONTINUED (1 << 0) /* Status for child that has been continued (1)(2) */ +#define WNOHANG (1 << 1) /* Do not wait if status not available (1) */ +#define WUNTRACED (1 << 2) /* Report status of stopped child process (1) */ + +#define WEXITED (1 << 3) /* Wait for processes that have exited (2) */ +#define WSTOPPED (1 << 4) /* Status for child stopped on signal (2) */ +#define WNOHANG (1 << 5) /* Return immediately if there are no children (2) */ +#define WNOWAIT (1 << 6) /* Keep the process in a waitable state (2) */ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +enum idtype_e +{ + P_PID = 1, + P_GID = 2, + P_ALL = 3 +}; +typedef enum idtype_e idtype_t; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN pid_t wait(int *stat_loc); +EXTERN int waitid(idtype_t idtype, id_t id, siginfo_t *siginfo, int options); +EXTERN pid_t waitpid(pid_t pid, int *stat_loc, int options); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_SCHED_WAITPID */ +#endif /* __INCLUDE_SYS_WAIT_H */ diff --git a/nuttx/include/syscall.h b/nuttx/include/syscall.h new file mode 100644 index 0000000000..ae888e9c2b --- /dev/null +++ b/nuttx/include/syscall.h @@ -0,0 +1,71 @@ +/**************************************************************************** + * include/syscall.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYSCALL_H +#define __INCLUDE_SYSCALL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ +/* This is just a wrapper around sys/syscall.h and arch/syscall.h */ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_SYSCALL_H */ diff --git a/nuttx/include/termios.h b/nuttx/include/termios.h new file mode 100644 index 0000000000..e381814e3c --- /dev/null +++ b/nuttx/include/termios.h @@ -0,0 +1,302 @@ +/**************************************************************************** + * include/termios.h + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_TERMIOS_H +#define __INCLUDE_TERMIOS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Terminal input modes (c_iflag in the termios structure) */ + +#define BRKINT (1 << 0) /* Bit 0: Signal interrupt on break */ +#define ICRNL (1 << 1) /* Bit 1: Map CR to NL on input */ +#define IGNBRK (1 << 2) /* Bit 2: Ignore break condition */ +#define IGNCR (1 << 3) /* Bit 3: Ignore CR */ +#define IGNPAR (1 << 4) /* Bit 4: Ignore characters with parity errors */ +#define INLCR (1 << 5) /* Bit 5: Map NL to CR on input */ +#define INPCK (1 << 6) /* Bit 6: Enable input parity check */ +#define ISTRIP (1 << 7) /* Bit 7: Strip character */ +#define IUCLC (1 << 8) /* Bit 8: Map upper-case to lower-case on input (LEGACY) */ +#define IXANY (1 << 9) /* Bit 9: Enable any character to restart output */ +#define IXOFF (1 << 10) /* Bit 10: Enable start/stop input control */ +#define IXON (1 << 11) /* Bit 11: Enable start/stop output control */ +#define PARMRK (1 << 12) /* Bit 12: Mark parity errors */ + +/* Terminal output modes (c_oflag in the termios structure) */ + +#define OPOST (1 << 0) /* Bit 0: Post-process output */ +#define OLCUC (1 << 1) /* Bit 1: Map lower-case to upper-case on output (LEGACY) */ +#define ONLCR (1 << 2) /* Bit 2: Map NL to CR-NL on output */ +#define OCRNL (1 << 3) /* Bit 3: Map CR to NL on output */ +#define ONOCR (1 << 4) /* Bit 4: No CR output at column 0 */ +#define ONLRET (1 << 5) /* Bit 5: NL performs CR function */ +#define OFILL (1 << 6) /* Bit 6: Use fill characters for delay */ +#define NLDLY (1 << 7) /* Bit 7: Select newline delays: */ +# define NL0 (0 << 7) /* Newline character type 0 */ +# define NL1 (1 << 7) /* Newline character type 1 */ +#define CRDLY (3 << 8) /* Bits 8-9: Select carriage-return delays: */ +# define CR0 (0 << 8) /* Carriage-return delay type 0 */ +# define CR1 (1 << 8) /* Carriage-return delay type 1 */ +# define CR2 (2 << 8) /* Carriage-return delay type 2 */ +# define CR3 (3 << 8) /* Carriage-return delay type 3 */ +#define TABDLY (3 << 10) /* Bit 10-11: Select horizontal-tab delays: */ +# define TAB0 (0 << 10) /* Horizontal-tab delay type 0 */ +# define TAB1 (1 << 10) /* Horizontal-tab delay type 1 */ +# define TAB2 (2 << 10) /* Horizontal-tab delay type 2 */ +# define TAB3 (3 << 10) /* Expand tabs to spaces */ +#define BSDLY (1 << 12) /* Bit 12: Select backspace delays: */ +# define BS0 (0 << 12) /* Backspace-delay type 0 */ +# define BS1 (1 << 12) /* Backspace-delay type 1 */ +#define VTDLY (1 << 13) /* Bit 13: Select vertical-tab delays: */ +# define VT0 (0 << 13) /* Vertical-tab delay type 0 */ +# define VT1 (1 << 13) /* Vertical-tab delay type 1 */ +#define FFDLY (1 << 14) /* Bit 14: Select form-feed delays: */ +# define FF0 (0 << 14) /* Form-feed delay type 0 */ +# define FF1 (1 << 14) /* Form-feed delay type 1 */ + +/* Control Modes (c_cflag in the termios structure) */ + +#define CSIZE (3 << 0) /* Bits 0-1: Character size: */ +# define CS5 (0 << 0) /* 5 bits */ +# define CS6 (1 << 0) /* 6 bits */ +# define CS7 (2 << 0) /* 7 bits */ +# define CS8 (3 << 0) /* 8 bits */ +#define CSTOPB (1 << 2) /* Bit 2: Send two stop bits, else one */ +#define CREAD (1 << 3) /* Bit 3: Enable receiver */ +#define PARENB (1 << 4) /* Bit 4: Parity enable */ +#define PARODD (1 << 5) /* Bit 5: Odd parity, else even */ +#define HUPCL (1 << 6) /* Bit 6: Hang up on last close */ +#define CLOCAL (1 << 7) /* Bit 7: Ignore modem status lines */ + +/* Local Modes (c_lflag in the termios structure) */ + +#define ECHO (1 << 0) /* Bit 0: Enable echo */ +#define ECHOE (1 << 1) /* Bit 1: Echo erase character as error-correcting backspace */ +#define ECHOK (1 << 2) /* Bit 2: Echo KILL */ +#define ECHONL (1 << 3) /* Bit 3: Echo NL */ +#define ICANON (1 << 4) /* Bit 4: Canonical input (erase and kill processing) */ +#define IEXTEN (1 << 5) /* Bit 5: Enable extended input character processing */ +#define ISIG (1 << 6) /* Bit 6: Enable signals */ +#define NOFLSH (1 << 7) /* Bit 7: Disable flush after interrupt or quit */ +#define TOSTOP (1 << 8) /* Bit 8: Send SIGTTOU for background output */ +#define XCASE (1 << 9) /* Bit 9: Canonical upper/lower presentation (LEGACY) */ + +/* The following are subscript names for the termios c_cc array */ + +#define VEOF 0 /* Bit 0: EOF character (canonical mode) */ +#define VMIN VEOF /* Bit 0: MIN value (Non-canonical mode) */ +#define VEOL 1 /* Bit 1: EOL character (canonical mode) */ +#define VTIME VEOL /* Bit 1: TIME value (Non-canonical mode) */ +#define VERASE 2 /* Bit 2: ERASE character (canonical mode) */ +#define VINTR 3 /* Bit 3: INTR character */ +#define VKILL 4 /* Bit 4: KILL character (canonical mode) */ +#define VQUIT 5 /* Bit 5: QUIT character */ +#define VSTART 6 /* Bit 6: START character */ +#define VSTOP 7 /* Bit 7: STOP character */ +#define VSUSP 8 /* Bit 8: SUSP character */ +#define NCCS 9 /* Bit 9: Size of the array c_cc for control characters */ + +/* Baud Rate Selection. These are instances of type speed_t. Values of 38400 + * and below are specified by POSIX; values above 38400 are sometimes referred + * to as extended values and most values appear in most termios.h implementations. + * + * NOTE that is NuttX that the encoding of the speed_t values is simply the + * value of the baud itself. So this opens a window for non-portable abuse + * of the speed-related interfaces: The defined values should be used where- + * ever possible for reasons of portability. + */ + +#define B0 0 /* Hang up */ +#define B50 50 /* 50 baud */ +#define B75 75 /* 75 baud */ +#define B110 110 /* 110 baud */ +#define B134 134 /* 134.5 baud */ +#define B150 150 /* 150 baud */ +#define B200 200 /* 200 baud */ +#define B300 300 /* 300 baud */ +#define B600 600 /* 600 baud */ +#define B1200 1200 /* 1,200 baud */ +#define B1800 1800 /* 1,800 baud */ +#define B2400 2400 /* 2,400 baud */ +#define B4800 4800 /* 4,800 baud */ +#define B9600 9600 /* 9,600 baud */ +#define B19200 19200 /* 19,200 baud */ +#define B38400 38400 /* 38,400 baud */ + +#define B57600 57600 /* 57,600 baud */ +#define B115200 115200 /* 115,200 baud */ +#define B128000 128000 /* 128,000 baud */ +#define B230400 230400 /* 230,400 baud */ +#define B256000 256000 /* 256,000 baud */ +#define B460800 460800 /* 460,800 baud */ +#define B500000 500000 /* 500,000 baud */ +#define B576000 576000 /* 576,000 baud */ +#define B921600 921600 /* 921,600 baud */ +#define B1000000 1000000 /* 1,000,000 baud */ +#define B1152000 1152000 /* 1,152,000 baud */ +#define B1500000 1500000 /* 1,500,000 baud */ +#define B2000000 2000000 /* 2,000,000 baud */ +#define B2500000 2500000 /* 2,500,000 baud */ +#define B3000000 3000000 /* 3,000,000 baud */ + +/* Attribute Selection (used with tcsetattr()) */ + +#define TCSANOW 0 /* Change attributes immediately */ +#define TCSADRAIN 1 /* Change attributes when output has drained */ +#define TCSAFLUSH 2 /* Change attributes when output has drained; also flush pending input */ + +/* Line Control (used with tcflush()) */ + +#define TCIFLUSH 0 /* Flush pending input. Flush untransmitted output */ +#define TCIOFLUSH 1 /* Flush both pending input and untransmitted output */ +#define TCOFLUSH 2 /* Flush untransmitted output */ + +/* Constants for use with tcflow() */ + +#define TCIOFF 0 /* Transmit a STOP character, intended to suspend input data */ +#define TCION 1 /* Transmit a START character, intended to restart input data */ +#define TCOOFF 2 /* Suspend output */ +#define TCOON 3 /* Restart output */ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* Baud rate selection */ + +typedef uint32_t speed_t; /* Used for terminal baud rates */ + +/* Types used within the termios structure */ + +typedef uint16_t tcflag_t; /* Used for terminal modes */ +typedef int cc_t; /* Used for terminal special characters */ + +/* The termios structure */ + +struct termios +{ + /* Exposed fields defined by POSIX */ + + tcflag_t c_iflag; /* Input modes */ + tcflag_t c_oflag; /* Output modes */ + tcflag_t c_cflag; /* Control modes */ + tcflag_t c_lflag; /* Local modes */ + cc_t c_cc[NCCS]; /* Control chars */ + + /* Implementation specific fields. For portability reasons, these fields + * should not be accessed directly, but rather through only through the + * cf[set|get][o|i]speed() POSIX interfaces. + */ + + const speed_t c_speed; /* Input/output speed (non-POSIX)*/ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* The cfgetspeed() function is a non-POSIX function will extract the baud + * from the termios structure to which the termiosp argument points. NuttX + * does not control input/output baud independently. Both must be the same. + * The POSIX standard interfaces, cfigetispeed() and cfigetospeed() are + * supported by simply defining them to be cfgetspeed(). + */ + +EXTERN speed_t cfgetspeed(FAR const struct termios *termiosp); +#define cfgetispeed(termiosp) cfgetspeed(termiosp) +#define cfgetospeed(termiosp) cfgetspeed(termiosp) + +/* The cfsetspeed() function is a non-POSIX function that sets the baud + * stored in the structure pointed to by termiosp to speed. NuttX does + * not control input/output baud independently. Both must be the same. + * The POSIX standard interfaces, cfigetispeed() and cfigetospeed() are + * supported by simply defining them to be cfsetspeed(). + */ + +EXTERN int cfsetspeed(FAR struct termios *termiosp, speed_t speed); +#define cfsetispeed(termiosp,speed) cfsetspeed(termiosp,speed) +#define cfsetospeed(termiosp,speed) cfsetspeed(termiosp,speed) + +/* Wait for transmission of output */ + +EXTERN int tcdrain(int fd); + +/* Suspend or restart the transmission or reception of data */ + +EXTERN int tcflow(int fd, int action); + +/* Flush non-transmitted output data, non-read input data or both */ + +EXTERN int tcflush(int fd, int cmd); + +/* Get the parameters associated with the terminal */ + +EXTERN int tcgetattr(int fd, FAR struct termios *termiosp); + +/* Get process group ID for session leader for controlling terminal */ + +EXTERN pid_t tcgetsid(int fd); + +/* Send a "break" for a specific duration */ + +EXTERN int tcsendbreak(int fd, int duration); + +/* Set the parameters associated with the terminal */ + +EXTERN int tcsetattr(int fd, int options, FAR const struct termios *termiosp); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_TERMIOS_H */ diff --git a/nuttx/include/time.h b/nuttx/include/time.h new file mode 100644 index 0000000000..623f9afb27 --- /dev/null +++ b/nuttx/include/time.h @@ -0,0 +1,192 @@ +/******************************************************************************** + * include/time.h + * + * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +#ifndef __INCLUDE_TIME_H +#define __INCLUDE_TIME_H + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include + +/******************************************************************************** + * Pre-processor Definitions + ********************************************************************************/ + +/* Clock tick of the system (frequency Hz). + * + * NOTE: This symbolic name CLK_TCK has been removed from the standard. It is + * replaced with CLOCKS_PER_SEC. Both are defined here. + * + * The default value is 100Hz, but this default setting can be overridden by + * defining the clock interval in milliseconds as CONFIG_MSEC_PER_TICK in the + * board configuration file. + */ + +#ifdef CONFIG_MSEC_PER_TICK +# define CLK_TCK (1000/CONFIG_MSEC_PER_TICK) +# define CLOCKS_PER_SEC (1000/CONFIG_MSEC_PER_TICK) +#else +# define CLK_TCK (100) +# define CLOCKS_PER_SEC (100) +#endif + +/* CLOCK_REALTIME refers to the standard time source. For most implementations, + * the standard time source is the system timer interrupt. However, if the + * platform supports an RTC, then the standard time source will be the RTC + * for the clock_gettime() and clock_settime() interfaces (the system timer + * is still the time source for all of the interfaces). + */ + +#define CLOCK_REALTIME 0 + +/* If an RTC is supported, then the non-standard CLOCK_ACTIVETIME is also + * supported to manage time based on the system timer interrupt separately from + * the RTC. This may be necessary, for example, in certain cases where the + * system timer interrupt has been stopped in low power modes. + * + * CLOCK_ACTIVETIME is only recognized by clock_gettime() and clock_settime(). + */ + +#ifdef CONFIG_RTC +# define CLOCK_ACTIVETIME 1 +#else +# define CLOCK_ACTIVETIME CLOCK_REALTIME +#endif + +/* This is a flag that may be passed to the timer_settime() function */ + +#define TIMER_ABSTIME 1 + +/* Local time is the same as gmtime in this implementation */ + +#define localtime(c) gmtime(c) +#define localtime_r(c,r) gmtime_r(c,r) + +/******************************************************************************** + * Global Type Declarations + ********************************************************************************/ + +typedef uint32_t time_t; /* Holds time in seconds */ +typedef uint8_t clockid_t; /* Identifies one time base source */ +typedef FAR void *timer_t; /* Represents one POSIX timer */ + +struct timespec +{ + time_t tv_sec; /* Seconds */ + long tv_nsec; /* Nanoseconds */ +}; + +struct timeval +{ + time_t tv_sec; /* Seconds */ + long tv_usec; /* Microseconds */ +}; + +struct tm +{ + int tm_sec; /* second (0-61, allows for leap seconds) */ + int tm_min; /* minute (0-59) */ + int tm_hour; /* hour (0-23) */ + int tm_mday; /* day of the month (1-31) */ + int tm_mon; /* month (0-11) */ + int tm_year; /* years since 1900 */ +#if 0 /* not supported */ + int tm_wday; /* day of the week (0-6) */ + int tm_yday; /* day of the year (0-365) */ + int tm_isdst; /* non-0 if daylight savings time is in effect */ +#endif +}; + +/* Struct itimerspec is used to define settings for an interval timer */ + +struct itimerspec +{ + struct timespec it_value; /* First time */ + struct timespec it_interval; /* and thereafter */ +}; + +/* forward reference (defined in signal.h) */ + +struct sigevent; + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/* extern char *tznames[]; not supported */ + +/******************************************************************************** + * Global Function Prototypes + ********************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN clock_t clock(void); + +EXTERN int clock_settime(clockid_t clockid, const struct timespec *tp); +EXTERN int clock_gettime(clockid_t clockid, struct timespec *tp); +EXTERN int clock_getres(clockid_t clockid, struct timespec *res); + +EXTERN time_t mktime(const struct tm *tp); +EXTERN FAR struct tm *gmtime(FAR const time_t *timer); +EXTERN FAR struct tm *gmtime_r(FAR const time_t *timer, FAR struct tm *result); +EXTERN size_t strftime(char *s, size_t max, const char *format, const struct tm *tm); + +EXTERN time_t time(time_t *tloc); + +EXTERN int timer_create(clockid_t clockid, FAR struct sigevent *evp, FAR timer_t *timerid); +EXTERN int timer_delete(timer_t timerid); +EXTERN int timer_settime(timer_t timerid, int flags, FAR const struct itimerspec *value, + FAR struct itimerspec *ovalue); +EXTERN int timer_gettime(timer_t timerid, FAR struct itimerspec *value); +EXTERN int timer_getoverrun(timer_t timerid); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_TIME_H */ diff --git a/nuttx/include/unistd.h b/nuttx/include/unistd.h new file mode 100644 index 0000000000..e2ad6ff826 --- /dev/null +++ b/nuttx/include/unistd.h @@ -0,0 +1,179 @@ +/**************************************************************************** + * include/unistd.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_UNISTD_H +#define __INCLUDE_UNISTD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The number of functions that may be registerd to be called + * at program exit. + */ + +#define ATEXIT_MAX 1 + +/* Values for seeking */ + +#define SEEK_SET 0 /* From the start of the file */ +#define SEEK_CUR 1 /* From the current file offset */ +#define SEEK_END 2 /* From the end of the file */ + +/* Bit values for the second argument to access */ + +#define F_OK 0 /* Test existence */ +#define R_OK 1 /* Test read permission */ +#define W_OK 2 /* Test write permission */ +#define X_OK 4 /* Test execute permission */ + +/* POSIX feature set macros */ + +#define POSIX_VERSION +#undef _POSIX_SAVED_IDS +#undef _POSIX_JOB_CONTROL +#define _POSIX_REALTIME_SIGNALS 1 +#define _POSIX_MESSAGE_PASSING 1 +#undef _POSIX_MAPPED_FILES +#undef _POSIX_SHARED_MEMORY_OBJECTS +#define _POSIX_PRIORITY_SCHEDULING 1 +#define _POSIX_TIMERS +#undef _POSIX_MEMLOCK +#undef _POSIX_MEMLOCK_RANGE +#undef _POSIX_FSYNC +#define _POSIX_SYNCHRONIZED_IO +#undef _POSIX_ASYNCHRONOUS_IO +#undef _POSIX_PRIORITIZED_IO + +/* Execution time constants (not supported) */ + +#undef _POSIX_CHOWN_RESTRICTED +#undef _POSIX_NO_TRUNC +#undef _POSIX_VDISABLE + +#define _POSIX_SYNC_IO +#undef _POSIX_ASYNC_IO +#undef _POSIX_PRIO_IO + +#define fdatasync(f) fsync(f) + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Used by getopt (obviously NOT thread safe!). These variables cannot be + * accessed directly by an external NXFLAT module. In that case, accessor + * functions must be used. + */ + +#ifndef __NXFLAT__ +EXTERN FAR char *optarg; /* Optional argument following option */ +EXTERN int optind; /* Index into argv */ +EXTERN int optopt; /* unrecognized option character */ +#else +# define optarg (*(getoptargp())) +# define optind (*(getopindgp())) +# define optopt (*(getoptoptp())) +#endif + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/* Task Control Interfaces */ + +EXTERN pid_t getpid(void); +EXTERN void _exit(int status) noreturn_function; +EXTERN unsigned int sleep(unsigned int seconds); +EXTERN int usleep(useconds_t usec); + +/* File descriptor operations */ + +EXTERN int close(int fd); +EXTERN int dup(int fd); +EXTERN int dup2(int fd1, int fd2); +EXTERN int fsync(int fd); +EXTERN off_t lseek(int fd, off_t offset, int whence); +EXTERN ssize_t read(int fd, FAR void *buf, size_t nbytes); +EXTERN ssize_t write(int fd, FAR const void *buf, size_t nbytes); + +/* Special devices */ + +EXTERN int pipe(int filedes[2]); + +/* Working directory operations */ + +EXTERN int chdir(FAR const char *path); +EXTERN FAR char *getcwd(FAR char *buf, size_t size); + +/* File path operations */ + +EXTERN int unlink(FAR const char *pathname); +EXTERN int rmdir(FAR const char *pathname); + +/* Other */ + +EXTERN int getopt(int argc, FAR char *const argv[], FAR const char *optstring); + +/* Accessor functions intended for use only by external NXFLAT + * modules. The global variables optarg, optind, and optopt cannot + * be referenced directly from external modules. + */ + +EXTERN FAR char **getoptargp(void); /* Optional argument following option */ +EXTERN int *getopindgp(void); /* Index into argv */ +EXTERN int *getoptoptp(void); /* unrecognized option character */ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_UNISTD_H */ diff --git a/nuttx/include/wdog.h b/nuttx/include/wdog.h new file mode 100644 index 0000000000..3179c06a4b --- /dev/null +++ b/nuttx/include/wdog.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * include/wdog.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_WDOG_H +#define __INCLUDE_WDOG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Type Declarations + ****************************************************************************/ + +/* The arguments are passed as uint32_t values. For systems where the + * sizeof(pointer) < sizeof(uint32_t), the following union defines the + * alignment of the pointer within the uint32_t. For example, the SDCC + * MCS51 general pointer is 24-bits, but uint32_t is 32-bits (of course). + * + * For systems where sizeof(pointer) > sizeof(uint32_t), we will have to do + * some redesign. + */ + +union wdparm_u +{ + FAR void *pvarg; + FAR uint32_t *dwarg; +}; + +typedef union wdparm_u wdparm_t; + +/* This is the form of the function that is called when the + * watchdog function expires. Up to four parameters may be passed. + */ + +typedef CODE void (*wdentry_t)(int argc, uint32_t arg1, ...); + +/* Watchdog 'handle' */ + +typedef FAR struct wdog_s *WDOG_ID; + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN WDOG_ID wd_create(void); +EXTERN int wd_delete(WDOG_ID wdog); +EXTERN int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...); +EXTERN int wd_cancel(WDOG_ID wdog); +EXTERN int wd_gettime(WDOG_ID wdog); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* _WDOG_H_ */ diff --git a/nuttx/lib/Kconfig b/nuttx/lib/Kconfig new file mode 100644 index 0000000000..9e60201c2f --- /dev/null +++ b/nuttx/lib/Kconfig @@ -0,0 +1,113 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config STDIO_BUFFER_SIZE + int "C STDIO buffer size" + default 64 + ---help--- + Size of buffers using within the C buffered I/O interfaces. + (printf, putchar, fwrite, etc.). + +config STDIO_LINEBUFFER + bool "STDIO line buffering" + default y + ---help--- + Flush buffer I/O whenever a newline character is found in + the output data stream. + +config NUNGET_CHARS + int "Number unget() characters" + default 2 + ---help--- + Number of characters that can be buffered by ungetc() (Only if NFILE_STREAMS > 0) + +config CONFIG_LIB_HOMEDIR + string "Home directory" + default "/" + depends on !DISABLE_ENVIRON + ---help--- + The home directory to use with operations like such as 'cd ~' + +config HAVE_LIBM + bool "Architecture-specific libm.a" + default n + ---help--- + Architecture specific logic provides an implementation of libm.a + and a math.h header file that can be found at include/arch/math.h. + +config NOPRINTF_FIELDWIDTH + bool "Disable sprintf support fieldwidth" + default n + ---help--- + sprintf-related logic is a + little smaller if we do not support fieldwidthes + +config LIBC_FLOATINGPOINT + bool "Enable floating point in printf" + default n + ---help--- + By default, floating point + support in printf, sscanf, etc. is disabled. + +config ARCH_LOWPUTC + bool "Low-level console output" + default "y" + ---help--- + architecture supports low-level, boot time console output + +config ENABLE_ARCH_OPTIMIZED_FUN + bool "Enable arch optimized functions" + default n + ---help--- + Allow for architecture optimized implementations + + The architecture can provide optimized versions of the + following to improve system performance + + The architecture may provide custom versions of certain + standard header files: + config ARCH_MATH_H, CONFIG_ARCH_STDBOOL_H, CONFIG_ARCH_STDINT_H + +if ENABLE_ARCH_OPTIMIZED_FUN +config ARCH_MEMCPY + bool "memcpy" + default n + +config ARCH_MEMCMP + bool "memcmp" + default n + +config ARCH_MEMMOVE + bool "memmove" + default n + +config ARCH_MEMSET + bool "memset" + default n + +config ARCH_STRCMP + bool "strcmp" + default n + +config ARCH_STRCPY + bool "strcpy" + default n + +config ARCH_STRNCPY + bool "strncpy" + default n + +config ARCH_STRLEN + bool "strlen" + default n + +config ARCH_STRNLEN + bool "strlen" + default n + +config ARCH_BZERO + bool "bzero" + default n +endif diff --git a/nuttx/lib/Makefile b/nuttx/lib/Makefile new file mode 100644 index 0000000000..772c6f6a80 --- /dev/null +++ b/nuttx/lib/Makefile @@ -0,0 +1,162 @@ +############################################################################ +# lib/Makefile +# +# Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +########################################################################### + +-include $(TOPDIR)/Make.defs +include stdio/Make.defs +include stdlib/Make.defs +include unistd/Make.defs +include sched/Make.defs +include string/Make.defs +include pthread/Make.defs +include semaphore/Make.defs +include signal/Make.defs +include mqueue/Make.defs +include math/Make.defs +include net/Make.defs +include time/Make.defs +include libgen/Make.defs +include dirent/Make.defs +include termios/Make.defs +include queue/Make.defs +include misc/Make.defs + +ASRCS = +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +CSRCS = $(STDIO_SRCS) $(STDLIB_SRCS) $(UNISTD_SRCS) $(SCHED_SRCS) \ + $(STRING_SRCS) $(PTHREAD_SRCS) $(SEM_SRCS) $(SIG_SRCS) $(MQUEUE_SRCS) \ + $(MATH_SRCS) $(NET_SRCS) $(TIME_SRCS) $(LIBGEN_SRCS) \ + $(DIRENT_SRCS) $(TERMIOS_SRCS) \ + $(QUEUE_SRCS) $(MISC_SRCS) $(REGEX_SRCS) $(CRC_SRCS) $(DBG_SRCS) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ROOTDEPPATH = --dep-path . +STDIODEPPATH = --dep-path stdio +STDLIBDEPPATH = --dep-path stdlib +UNISTDDEPPATH = --dep-path unistd +SCHEDDEPPATH = --dep-path sched +STRINGDEPPATH = --dep-path string +PTHREADDEPPATH = --dep-path pthread +SEMDEPPATH = --dep-path semaphore +SIGDEPPATH = --dep-path signal +MQDEPPATH = --dep-path mqueue +MATHDEPPATH = --dep-path math +NETDEPPATH = --dep-path net +TIMEDEPPATH = --dep-path time +LIBGENDEPPATH = --dep-path libgen +DIRENTDEPPATH = --dep-path dirent +TERMIOSDEPPATH = --dep-path termios +QUEUEDEPPATH = --dep-path queue +MISCDEPPATH = --dep-path misc + +VPATH = stdio:stdlib:unistd:sched:string:pthread:semaphore:signal:mqueue +VPATH += :math:net:time:libgen:dirent:termios:queue:misc + +UBIN = libulib$(LIBEXT) +KBIN = libklib$(LIBEXT) +BIN = liblib$(LIBEXT) + +all: $(BIN) + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +ifneq ($(BIN),$(UBIN)) +.userlib: + @$(MAKE) $(UBIN) BIN=$(UBIN) TOPDIR=$(TOPDIR) EXTRADEFINES=$(EXTRADEFINES) + @touch .userlib + +$(UBIN): kclean .userlib +endif + +ifneq ($(BIN),$(KBIN)) +.kernlib: + @$(MAKE) $(KBIN) BIN=$(KBIN) TOPDIR=$(TOPDIR) EXTRADEFINES=$(EXTRADEFINES) + @touch .kernlib + +$(KBIN): uclean .kernlib +endif + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(STDIODEPPATH) $(STDLIBDEPPATH) \ + $(UNISTDDEPPATH) $(SCHEDDEPPATH) $(STRINGDEPPATH) $(PTHREADDEPPATH) \ + $(SEMDEPPATH) $(SIGDEPPATH) $(MQDEPPATH) $(MATHDEPPATH) $(NETDEPPATH) \ + $(TIMEDEPPATH) $(LIBGENDEPPATH) $(DIRENTDEPPATH) $(TERMIOSDEPPATH) \ + $(QUEUEDEPPATH) $(MISCDEPPATH) \ + $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +# Clean Targets: +# Clean user-mode temporary files (retaining the UBIN binary) + +uclean: +ifneq ($(OBJEXT),) + @( if [ -f .userlib ]; then rm -f *$(OBJEXT); fi ) +endif + @rm -f .userlib *~ .*.swp + +# Clean kernel-mode temporary files (retaining the KBIN binary) + +kclean: +ifneq ($(OBJEXT),) + @( if [ -f .kernlib ]; then rm -f *$(OBJEXT); fi ) +endif + @rm -f .kernlib *~ .*.swp + +# Really clean everything + +clean: uclean kclean + @rm -f $(BIN) $(UBIN) $(KBIN) *~ .*.swp + $(call CLEAN) + +# Deep clean -- removes all traces of the configuration + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/lib/README.txt b/nuttx/lib/README.txt new file mode 100644 index 0000000000..62e2fcce2e --- /dev/null +++ b/nuttx/lib/README.txt @@ -0,0 +1,47 @@ +lib +=== + +This directory contains numerous, small functions typically associated with +what you would expect to find in a standard C library. The sub-directories +in this directory contain standard interface that can be executed by user- +mode programs. + +Normally, NuttX is built with no protection and all threads running in kerne- +mode. In that model, there is no real architectural distinction between +what is a kernel-mode program and what is a user-mode program; the system is +more like on multi-threaded program that all runs in kernel-mode. + +But if the CONFIG_NUTTX_KERNEL option is selected, NuttX will be built into +distinct user-mode and kernel-mode sections. In that case, most of the +code in the nuttx/ directory will run in kernel-mode with with exceptions +of (1) the user-mode "proxies" found in syscall/proxies, and (2) the +standard C library functions found in this directory. In this build model, +it is critical to separate the user-mode OS interfaces in this way. + +Sub-Directories +=============== + +The files in the lib/ directory are organized (mostly) according which file +in the include/ directory provides the prototype for library functions. So +we have: + + libgen - libgen.h + math - math.h and fixedmath.h + mqueue - pthread.h + net - Various network-related header files: netinet/ether.h, arpa/inet.h + pthread - pthread.h + queue - queue.h + sched - sched.h + semaphore - semaphore.h + stdio - stdio.h + stdlib - stdlib.h + string - string.h + time - time.h + unistd - unistd.h + +There is also a misc/ subdirectory that contains various internal functions +and interfaces from header files that are too few to warrant their own sub- +directory: + + misc - Nonstandard "glue" logic, debug.h, crc32.h, dirent.h + diff --git a/nuttx/lib/dirent/Make.defs b/nuttx/lib/dirent/Make.defs new file mode 100644 index 0000000000..d9dc8c29b7 --- /dev/null +++ b/nuttx/lib/dirent/Make.defs @@ -0,0 +1,40 @@ +############################################################################ +# lib/dirent/Make.defs +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +DIRENT_SRCS = +ifneq ($(CONFIG_NFILE_DESCRIPTORS),0) +DIRENT_SRCS += lib_readdirr.c lib_telldir.c +endif + diff --git a/nuttx/lib/dirent/lib_readdirr.c b/nuttx/lib/dirent/lib_readdirr.c new file mode 100644 index 0000000000..47c5b9a7bd --- /dev/null +++ b/nuttx/lib/dirent/lib_readdirr.c @@ -0,0 +1,122 @@ +/**************************************************************************** + * lib/dirent/lib_readdirr.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: readdir_r + * + * Description: + * The readdir() function returns a pointer to a dirent + * structure representing the next directory entry in the + * directory stream pointed to by dir. It returns NULL on + * reaching the end-of-file or if an error occurred. + * + * Inputs: + * dirp -- An instance of type DIR created by a previous + * call to opendir(); + * entry -- The storage pointed to by entry must be large + * enough for a dirent with an array of char d_name + * members containing at least {NAME_MAX}+1 elements. + * result -- Upon successful return, the pointer returned + * at *result shall have the same value as the + * argument entry. Upon reaching the end of the directory + * stream, this pointer shall have the value NULL. + * + * Return: + * If successful, the readdir_r() function return s zero; + * otherwise, an error number is returned to indicate the + * error. + * + * EBADF - Invalid directory stream descriptor dir + * + ****************************************************************************/ + +int readdir_r(FAR DIR *dirp, FAR struct dirent *entry, + FAR struct dirent **result) +{ + struct dirent *tmp; + + /* NOTE: The following use or errno is *not* thread-safe */ + + set_errno(0); + tmp = readdir(dirp); + if (!tmp) + { + int error = get_errno(); + if (!error) + { + if (result) + { + *result = NULL; + } + return 0; + } + else + { + return error; + } + } + + if (entry) + { + memcpy(entry, tmp, sizeof(struct dirent)); + } + + if (result) + { + *result = entry; + } + return 0; +} + diff --git a/nuttx/lib/dirent/lib_telldir.c b/nuttx/lib/dirent/lib_telldir.c new file mode 100644 index 0000000000..3753b326e9 --- /dev/null +++ b/nuttx/lib/dirent/lib_telldir.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * lib/dirent/fs_telldir.c + * + * Copyright (C) 2007-2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: telldir + * + * Description: + * The telldir() function returns the current location + * associated with the directory stream dirp. + * + * Inputs: + * dirp -- An instance of type DIR created by a previous + * call to opendir(); + * + * Return: + * On success, the telldir() function returns the current + * location in the directory stream. On error, -1 is + * returned, and errno is set appropriately. + * + * EBADF - Invalid directory stream descriptor dir + * + ****************************************************************************/ + +off_t telldir(FAR DIR *dirp) +{ + struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp; + + if (!idir || !idir->fd_root) + { + set_errno(EBADF); + return (off_t)-1; + } + + /* Just return the current position */ + + return idir->fd_position; +} + diff --git a/nuttx/lib/lib_internal.h b/nuttx/lib/lib_internal.h new file mode 100644 index 0000000000..c3d9bfd18e --- /dev/null +++ b/nuttx/lib/lib_internal.h @@ -0,0 +1,199 @@ +/**************************************************************************** + * lib/lib_internal.h + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __LIB_LIB_INTERNAL_H +#define __LIB_LIB_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* This configuration directory is used in environment variable processing + * when we need to reference the user's home directory. There are no user + * directories in NuttX so, by default, this always refers to the root + * directory. + */ + +#ifndef CONFIG_LIB_HOMEDIR +# define CONFIG_LIB_HOMEDIR "/" +#endif + +/* If C std I/O buffering is not supported, then we don't need its semaphore + * protection. + */ + +#if CONFIG_STDIO_BUFFER_SIZE <= 0 +# define lib_sem_initialize(s) +# define lib_take_semaphore(s) +# define lib_give_semaphore(s) +#endif + +/* The NuttX C library an be build in two modes: (1) as a standard, C-libary + * that can be used by normal, user-space applications, or (2) as a special, + * kernel-mode C-library only used within the OS. If NuttX is not being + * built as separated kernel- and user-space modules, then only the first + * mode is supported. + */ + +#if defined(CONFIG_NUTTX_KERNEL) && defined(__KERNEL__) +# include +# define lib_malloc(s) kmalloc(s) +# define lib_zalloc(s) kzalloc(s) +# define lib_realloc(p,s) krealloc(p,s) +# define lib_free(p) kfree(p) +#else +# include +# define lib_malloc(s) malloc(s) +# define lib_zalloc(s) zalloc(s) +# define lib_realloc(p,s) realloc(p,s) +# define lib_free(p) free(p) +#endif + +#define LIB_BUFLEN_UNKNOWN INT_MAX + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* Debug output is initially disabled */ + +#ifdef CONFIG_DEBUG_ENABLE +extern bool g_dbgenable; +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Defined in lib_streamsem.c */ + +#if CONFIG_NFILE_STREAMS > 0 +extern void stream_semtake(FAR struct streamlist *list); +extern void stream_semgive(FAR struct streamlist *list); +#endif + +/* Defined in lib_libnoflush.c */ + +#ifdef CONFIG_STDIO_LINEBUFFER +extern int lib_noflush(FAR struct lib_outstream_s *this); +#endif + +/* Defined in lib_libsprintf.c */ + +extern int lib_sprintf(FAR struct lib_outstream_s *obj, + const char *fmt, ...); + +/* Defined lib_libvsprintf.c */ + +extern int lib_vsprintf(FAR struct lib_outstream_s *obj, + FAR const char *src, va_list ap); + +/* Defined lib_rawprintf.c */ + +extern int lib_rawvprintf(const char *src, va_list ap); + +/* Defined lib_lowprintf.c */ + +extern int lib_lowvprintf(const char *src, va_list ap); + +/* Defined in lib_dtoa.c */ + +#ifdef CONFIG_LIBC_FLOATINGPOINT +extern char *__dtoa(double d, int mode, int ndigits, + int *decpt, int *sign, char **rve); +#endif + +/* Defined in lib_libwrite.c */ + +extern ssize_t lib_fwrite(FAR const void *ptr, size_t count, FAR FILE *stream); + +/* Defined in lib_libfread.c */ + +extern ssize_t lib_fread(FAR void *ptr, size_t count, FAR FILE *stream); + +/* Defined in lib_libfflush.c */ + +extern ssize_t lib_fflush(FAR FILE *stream, bool bforce); + +/* Defined in lib_rdflush.c */ + +extern int lib_rdflush(FAR FILE *stream); + +/* Defined in lib_wrflush.c */ + +int lib_wrflush(FAR FILE *stream); + +/* Defined in lib_sem.c */ + +#if CONFIG_STDIO_BUFFER_SIZE > 0 +extern void lib_sem_initialize(FAR struct file_struct *stream); +extern void lib_take_semaphore(FAR struct file_struct *stream); +extern void lib_give_semaphore(FAR struct file_struct *stream); +#endif + +/* Defined in lib_libgetbase.c */ + +extern int lib_getbase(const char *nptr, const char **endptr); + +/* Defined in lib_skipspace.c */ + +extern void lib_skipspace(const char **pptr); + +/* Defined in lib_isbasedigit.c */ + +extern bool lib_isbasedigit(int ch, int base, int *value); + +/* Defined in lib_checkbase.c */ + +extern int lib_checkbase(int base, const char **pptr); + +#endif /* __LIB_LIB_INTERNAL_H */ diff --git a/nuttx/lib/libgen/Make.defs b/nuttx/lib/libgen/Make.defs new file mode 100644 index 0000000000..93214eadb3 --- /dev/null +++ b/nuttx/lib/libgen/Make.defs @@ -0,0 +1,37 @@ +############################################################################ +# lib/libgen/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +LIBGEN_SRCS = lib_basename.c lib_dirname.c + diff --git a/nuttx/lib/libgen/lib_basename.c b/nuttx/lib/libgen/lib_basename.c new file mode 100644 index 0000000000..5741d976a9 --- /dev/null +++ b/nuttx/lib/libgen/lib_basename.c @@ -0,0 +1,131 @@ +/**************************************************************************** + * lib/libgen/lib_basename.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static char g_retchar[2]; + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: basename + * + * Description: + * basename() extracts the filename component from a null-terminated + * pathname string. In the usual case, basename() returns the component + * following the final '/'. Trailing '/' characters are not counted as + * part of the pathname. + * + * If path does not contain a slash, basename() returns a copy of path. + * If path is the string "/", then basename() returns the string "/". If + * path is a NULL pointer or points to an empty string, then basename() + * return the string ".". + * + * basename() may modify the contents of path, so copies should be passed. + * basename() may return pointers to statically allocated memory which may + * be overwritten by subsequent calls. + * + * Parameter: + * path The null-terminated string referring to the path to be decomposed + * + * Return: + * On success the filename component of the path is returned. + * + ****************************************************************************/ + +char *basename(char *path) +{ + char *p; + int len; + int ch; + + /* Handle some corner cases */ + + if (!path || *path == '\0') + { + ch = '.'; + goto out_retchar; + } + + /* Check for trailing slash characters */ + + len = strlen(path); + while (path[len-1] == '/') + { + /* Remove trailing '/' UNLESS this would make a zero length string */ + if (len > 1) + { + path[len-1] = '\0'; + len--; + } + else + { + ch = '/'; + goto out_retchar; + } + } + + /* Get the address of the last '/' which is not at the end of the path and, + * therefor, must be just before the beginning of the filename component. + */ + + p = strrchr(path, '/'); + if (p) + { + return p + 1; + } + + /* There is no '/' in the path */ + + return path; + +out_retchar: + g_retchar[0] = ch; + g_retchar[1] = '\0'; + return g_retchar; +} diff --git a/nuttx/lib/libgen/lib_dirname.c b/nuttx/lib/libgen/lib_dirname.c new file mode 100644 index 0000000000..c416d8aca3 --- /dev/null +++ b/nuttx/lib/libgen/lib_dirname.c @@ -0,0 +1,144 @@ +/**************************************************************************** + * lib/libgen/lib_dirname.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static char g_retchar[2]; + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: dirname + * + * Description: + * dirname() extracts the directory component from a null-terminated + * pathname string. In the usual case, dirname() returns the string up + * to, but not including, the final '/'. Trailing '/' characters are not + * counted as part of the pathname. + * + * If path does not contain a slash, dirname() returns the string ".". If + * path is the string "/", then dirname() returns the string "/". If path + * is a NULL pointer or points to an empty string, then dirname() returns + * the string ".". + * + * dirname() may modify the contents of path, so copies should be passed. + * dirname() may return pointers to statically allocated memory which may + * be overwritten by subsequent calls. + * + * Parameter: + * path The null-terminated string referring to the path to be decomposed + * + * Return: + * On success the directory component of the path is returned. + * + ****************************************************************************/ + +char *dirname(char *path) +{ + char *p; + int len; + int ch; + + /* Handle some corner cases */ + + if (!path || *path == '\0') + { + ch = '.'; + goto out_retchar; + } + + /* Check for trailing slash characters */ + + len = strlen(path); + while (path[len-1] == '/') + { + /* Remove trailing '/' UNLESS this would make a zero length string */ + if (len > 1) + { + path[len-1] = '\0'; + len--; + } + else + { + ch = '/'; + goto out_retchar; + } + } + + /* Get the address of the last '/' which is not at the end of the path and, + * therefor, must be the end of the directory component. + */ + + p = strrchr(path, '/'); + if (p) + { + /* Handle the case where the only '/' in the string is the at the beginning + * of the path. + */ + + if (p == path) + { + ch = '/'; + goto out_retchar; + } + + /* No, the directory component is the substring before the '/'. */ + + *p = '\0'; + return path; + } + + /* There is no '/' in the path */ + + ch = '.'; + +out_retchar: + g_retchar[0] = ch; + g_retchar[1] = '\0'; + return g_retchar; +} diff --git a/nuttx/lib/math/Make.defs b/nuttx/lib/math/Make.defs new file mode 100644 index 0000000000..c3b0712989 --- /dev/null +++ b/nuttx/lib/math/Make.defs @@ -0,0 +1,37 @@ +############################################################################ +# lib/math/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +MATH_SRCS = lib_rint.c lib_fixedmath.c lib_b16sin.c lib_b16cos.c lib_b16atan2.c + diff --git a/nuttx/lib/math/lib_b16atan2.c b/nuttx/lib/math/lib_b16atan2.c new file mode 100644 index 0000000000..a396524517 --- /dev/null +++ b/nuttx/lib/math/lib_b16atan2.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * lib/math/lib_b16atan2.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define B16_C1 0x00000373 /* 0.013480470 */ +#define B16_C2 0x00000eb7 /* 0.057477314 */ +#define B16_C3 0x00001f0a /* 0.121239071 */ +#define B16_C4 0x00003215 /* 0.195635925 */ +#define B16_C5 0x0000553f /* 0.332994597 */ +#define B16_C6 0x00010000 /* 0.999995630 */ +#define B16_HALFPI 0x00019220 /* 1.570796327 */ +#define B16_PI 0x00032440 /* 3.141592654 */ + +#ifndef MAX +# define MAX(a,b) (a > b ? a : b) +#endif + +#ifndef MIN +# define MIN(a,b) (a < b ? a : b) +#endif + +#ifndef ABS +# define ABS(a) (a < 0 ? -a : a) +#endif + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: b16atan2 + * + * Description: + * atan2 calculates the arctangent of y/x. (Based on a algorithm I saw + * posted on the internet... now I have lost the link -- sorry). + * + ****************************************************************************/ + +b16_t b16atan2(b16_t y, b16_t x) +{ + b16_t t0; + b16_t t1; + b16_t t2; + b16_t t3; + + t2 = ABS(x); + t1 = ABS(y); + t0 = MAX(t2, t1); + t1 = MIN(t2, t1); + t2 = ub16inv(t0); + t2 = b16mulb16(t1, t2); + + t3 = b16mulb16(t2, t2); + t0 = - B16_C1; + t0 = b16mulb16(t0, t3) + B16_C2; + t0 = b16mulb16(t0, t3) - B16_C3; + t0 = b16mulb16(t0, t3) + B16_C4; + t0 = b16mulb16(t0, t3) - B16_C5; + t0 = b16mulb16(t0, t3) + B16_C6; + t2 = b16mulb16(t0, t2); + + t2 = (ABS(y) > ABS(x)) ? B16_HALFPI - t2 : t2; + t2 = (x < 0) ? B16_PI - t2 : t2; + t2 = (y < 0) ? -t2 : t2; + + return t2; +} diff --git a/nuttx/lib/math/lib_b16cos.c b/nuttx/lib/math/lib_b16cos.c new file mode 100644 index 0000000000..69cc610425 --- /dev/null +++ b/nuttx/lib/math/lib_b16cos.c @@ -0,0 +1,64 @@ +/**************************************************************************** + * lib/math/lib_b16cos.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: b16cos + ****************************************************************************/ + +b16_t b16cos(b16_t rad) +{ + /* Compute cosine: sin(rad + PI/2) = cos(rad) */ + + rad += b16HALFPI; + if (rad > b16PI) + { + rad -= b16TWOPI; + } + return b16sin(rad); +} diff --git a/nuttx/lib/math/lib_b16sin.c b/nuttx/lib/math/lib_b16sin.c new file mode 100644 index 0000000000..fc4b5e5663 --- /dev/null +++ b/nuttx/lib/math/lib_b16sin.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * lib/math/lib_b16sin.c + * + * Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define b16_P225 0x0000399a +#define b16_P405284735 0x000067c1 +#define b16_1P27323954 0x000145f3 + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: b16sin + * Ref: http://lab.polygonal.de/2007/07/18/fast-and-accurate-sinecosine-approximation/ + ****************************************************************************/ + +b16_t b16sin(b16_t rad) +{ + b16_t tmp1; + b16_t tmp2; + b16_t tmp3; + + /* Force angle into the good range */ + + if (rad < -b16PI) + { + rad += b16TWOPI; + } + else if (rad > b16PI) + { + rad -= b16TWOPI; + } + + /* tmp1 = 1.27323954 * rad + * tmp2 = .405284735 * rad * rad + */ + + + tmp1 = b16mulb16(b16_1P27323954, rad); + tmp2 = b16mulb16(b16_P405284735, b16sqr(rad)); + + if (rad < 0) + { + /* tmp3 = 1.27323954 * rad + .405284735 * rad * rad */ + + tmp3 = tmp1 + tmp2; + } + else + { + /* tmp3 = 1.27323954 * rad - 0.405284735 * rad * rad */ + + tmp3 = tmp1 - tmp2; + } + + /* tmp1 = tmp3*tmp3 */ + + tmp1 = b16sqr(tmp3); + if (tmp3 < 0) + { + /* tmp1 = tmp3 * -tmp3 */ + + tmp1 = -tmp1; + } + + /* Return sin = .225 * (tmp3 * (+/-tmp3) - tmp3) + tmp3 */ + + return b16mulb16(b16_P225, (tmp1 - tmp3)) + tmp3; +} diff --git a/nuttx/lib/math/lib_fixedmath.c b/nuttx/lib/math/lib_fixedmath.c new file mode 100644 index 0000000000..b20158dc85 --- /dev/null +++ b/nuttx/lib/math/lib_fixedmath.c @@ -0,0 +1,272 @@ +/**************************************************************************** + * lib/math/lib_fixedmath.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#ifndef CONFIG_HAVE_LONG_LONG + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Name: fixsign + ****************************************************************************/ + +static void fixsign(b16_t *parg1, b16_t *parg2, bool *pnegate) +{ + bool negate = false; + b16_t arg; + + arg = *parg1; + if (arg < 0) + { + *parg1 = -arg; + negate = true; + } + + arg = *parg2; + if (arg < 0) + { + *parg2 = -arg; + negate ^= true; + } + + *pnegate = negate; +} + +/**************************************************************************** + * Name: adjustsign + ****************************************************************************/ + +static b16_t adjustsign(b16_t result, bool negate) +{ + /* If the product is negative, then we overflowed */ + + if (result < 0) + { + if (result) + { + return b16MIN; + } + else + { + return b16MAX; + } + } + + /* correct the sign of the result */ + + if (negate) + { + return -result; + } + return result; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: b16mulb16 + ****************************************************************************/ + +b16_t b16mulb16(b16_t m1, b16_t m2) +{ + bool negate; + b16_t product; + + fixsign(&m1, &m2, &negate); + product = (b16_t)ub16mulub16((ub16_t)m1, (ub16_t)m2); + return adjustsign(product, negate); +} + +/**************************************************************************** + * Name: ub16mulub16 + **************************************************************************/ + +ub16_t ub16mulub16(ub16_t m1, ub16_t m2) +{ + /* Let: + * + * m1 = m1i*2**16 + m1f (b16) + * m2 = m2i*2**16 + m2f (b16) + * + * Then: + * + * m1*m2 = (m1i*m2i)*2**32 + (m1i*m2f + m2i*m1f)*2**16 + m1f*m2f (b32) + * = (m1i*m2i)*2**16 + (m1i*m2f + m2i*m1f) + m1f*m2f*2**-16 (b16) + * = a*2**16 + b + c*2**-16 + */ + + uint32_t m1i = ((uint32_t)m1 >> 16); + uint32_t m2i = ((uint32_t)m1 >> 16); + uint32_t m1f = ((uint32_t)m1 & 0x0000ffff); + uint32_t m2f = ((uint32_t)m2 & 0x0000ffff); + + return (m1i*m2i << 16) + m1i*m2f + m2i*m1f + (((m1f*m2f) + b16HALF) >> 16); +} + +/**************************************************************************** + * Name: b16divb16 + **************************************************************************/ + +b16_t b16sqr(b16_t a) +{ + b16_t sq; + + /* The result is always positive. Just take the absolute value */ + + if (a < 0) + { + a = -a; + } + + /* Overflow occurred if the result is negative */ + + sq = (b16_t)ub16sqr(a); + if (sq < 0) + { + sq = b16MAX; + } + return sq; +} + +/**************************************************************************** + * Name: b16divb16 + **************************************************************************/ + +ub16_t ub16sqr(ub16_t a) +{ + /* Let: + * + * m = mi*2**16 + mf (b16) + * + * Then: + * + * m*m = (mi*mi)*2**32 + 2*(m1*m2)*2**16 + mf*mf (b32) + * = (mi*mi)*2**16 + 2*(mi*mf) + mf*mf*2**-16 (b16) + */ + + uint32_t mi = ((uint32_t)a >> 16); + uint32_t mf = ((uint32_t)a & 0x0000ffff); + + return (mi*mi << 16) + (mi*mf << 1) + ((mf*mf + b16HALF) >> 16); +} + +/**************************************************************************** + * Name: b16divb16 + **************************************************************************/ + +b16_t b16divb16(b16_t num, b16_t denom) +{ + bool negate; + b16_t quotient; + + fixsign(&num, &denom, &negate); + quotient = (b16_t)ub16divub16((ub16_t)num, (ub16_t)denom); + return adjustsign(quotient, negate); +} + +/**************************************************************************** + * Name: ub16divub16 + **************************************************************************/ + +ub16_t ub16divub16(ub16_t num, ub16_t denom) +{ + uint32_t term1; + uint32_t numf; + uint32_t product; + + /* Let: + * + * num = numi*2**16 + numf (b16) + * den = deni*2**16 + denf (b16) + * + * Then: + * + * num/den = numi*2**16 / den + numf / den (b0) + * = numi*2**32 / den + numf*2**16 /den (b16) + */ + + /* Check for overflow in the first part of the quotient */ + + term1 = ((uint32_t)num & 0xffff0000) / denom; + if (term1 >= 0x00010000) + { + return ub16MAX; /* Will overflow */ + } + + /* Finish the division */ + + numf = num - term1 * denom; + term1 <<= 16; + product = term1 + (numf + (denom >> 1)) / denom; + + /* Check for overflow */ + + if (product < term1) + { + return ub16MAX; /* Overflowed */ + } + return product; +} + +#endif diff --git a/nuttx/lib/math/lib_rint.c b/nuttx/lib/math/lib_rint.c new file mode 100644 index 0000000000..b122870b81 --- /dev/null +++ b/nuttx/lib/math/lib_rint.c @@ -0,0 +1,135 @@ +/************************************************************ + * lib/math/lib_rint.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include +#include +#include + +/************************************************************ + * Definitions + ************************************************************/ + +/************************************************************ + * Private Type Declarations + ************************************************************/ + +/************************************************************ + * Private Function Prototypes + ************************************************************/ + +/********************************************************** + * Global Constant Data + **********************************************************/ + +/************************************************************ + * Global Variables + ************************************************************/ + +/********************************************************** + * Private Constant Data + **********************************************************/ + +/************************************************************ + * Private Variables + ************************************************************/ + +double_t rint(double_t x) +{ + double_t ret; + + /* If the current rounding mode rounds toward negative + * infinity, rint() is identical to floor(). If the current + * rounding mode rounds toward positive infinity, rint() is + * identical to ceil(). + */ + +#if defined(CONFIG_FP_ROUND_POSITIVE) && CONFIG_FP_ROUNDING_POSITIVE != 0 + + ret = ceil(x); + +#elif defined(CONFIG_FP_ROUND_NEGATIVE) && CONFIG_FP_ROUNDING_NEGATIVE != 0 + + ret = floor(x); + +#else + + /* In the default rounding mode (round to nearest), rint(x) is the + * integer nearest x with the additional stipulation that if + * |rint(x)-x|=1/2, then rint(x) is even. + */ + + long dwinteger = (long)x; + double_t fremainder = x - (double_t)dwinteger; + + if (x < 0.0) + { + /* fremainder should be in range 0 .. -1 */ + + if (fremainder == -0.5) + { + dwinteger = ((dwinteger+1)&~1); + } + else if (fremainder < -0.5) + { + dwinteger--; + } + } + else + { + /* fremainder should be in range 0 .. 1 */ + + if (fremainder == 0.5) + { + dwinteger = ((dwinteger+1)&~1); + } + else if (fremainder > 0.5) + { + dwinteger++; + } + } + + ret = (double_t)dwinteger; +#endif + + return ret; +} diff --git a/nuttx/lib/misc/Make.defs b/nuttx/lib/misc/Make.defs new file mode 100644 index 0000000000..8892f71e60 --- /dev/null +++ b/nuttx/lib/misc/Make.defs @@ -0,0 +1,50 @@ +############################################################################ +# lib/misc/Make.defs +# +# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +MISC_SRCS = lib_init.c lib_filesem.c + +ifneq ($(CONFIG_NFILE_DESCRIPTORS),0) +ifneq ($(CONFIG_NFILE_STREAMS),0) +MISC_SRCS += lib_streamsem.c +endif +endif + +REGEX_SRCS = lib_match.c + +CRC_SRCS = lib_crc32.c + +DBG_SRCS = lib_dbg.c lib_dumpbuffer.c + + diff --git a/nuttx/lib/misc/lib_crc32.c b/nuttx/lib/misc/lib_crc32.c new file mode 100644 index 0000000000..f851598e01 --- /dev/null +++ b/nuttx/lib/misc/lib_crc32.c @@ -0,0 +1,123 @@ +/************************************************************************************************ + * lib/misc/lib_crc32.c + * + * This file is a part of NuttX: + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * + * The logic in this file was developed by Gary S. Brown: + * + * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or code or tables + * extracted from it, as desired without restriction. + * + * First, the polynomial itself and its table of feedback terms. The polynomial is: + * + * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 + * + * Note that we take it "backwards" and put the highest-order term in the lowest-order bit. + * The X^32 term is "implied"; the LSB is the X^31 term, etc. The X^0 term (usually shown + * as "+1") results in the MSB being 1 + * + * Note that the usual hardware shift register implementation, which is what we're using + * (we're merely optimizing it by doing eight-bit chunks at a time) shifts bits into the + * lowest-order term. In our implementation, that means shifting towards the right. Why + * do we do it this way? Because the calculated CRC must be transmitted in order from + * highest-order term to lowest-order term. UARTs transmit characters in order from LSB + * to MSB. By storing the CRC this way we hand it to the UART in the order low-byte to + * high-byte; the UART sends each low-bit to hight-bit; and the result is transmission bit + * by bit from highest- to lowest-order term without requiring any bit shuffling on our + * part. Reception works similarly + * + * The feedback terms table consists of 256, 32-bit entries. Notes + * + * - The table can be generated at runtime if desired; code to do so is shown later. It + * might not be obvious, but the feedback terms simply represent the results of eight + * shift/xor operations for all combinations of data and CRC register values + * + * - The values must be right-shifted by eight bits by the updcrc logic; the shift must + * be u_(bring in zeroes). On some hardware you could probably optimize the shift in + * assembler by using byte-swap instructions polynomial $edb88320 + ************************************************************************************************/ + +/************************************************************************************************ + * Included Files + ************************************************************************************************/ + +#include +#include +#include + +/************************************************************************************************ + * Private Data + ************************************************************************************************/ + +static const uint32_t crc32_tab[] = +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +/************************************************************************************************ + * Public Functions + ************************************************************************************************/ +/************************************************************************************************ + * Name: crc32part + * + * Description: + * Continue CRC calculation on a part of the buffer. + * + ************************************************************************************************/ + +uint32_t crc32part(FAR const uint8_t *src, size_t len, uint32_t crc32val) +{ + size_t i; + + for (i = 0; i < len; i++) + { + crc32val = crc32_tab[(crc32val ^ src[i]) & 0xff] ^ (crc32val >> 8); + } + return crc32val; +} + +/************************************************************************************************ + * Name: crc32 + * + * Description: + * Return a 32-bit CRC of the contents of the 'src' buffer, length 'len' + * + ************************************************************************************************/ + +uint32_t crc32(FAR const uint8_t *src, size_t len) +{ + return crc32part(src, len, 0); +} diff --git a/nuttx/lib/misc/lib_dbg.c b/nuttx/lib/misc/lib_dbg.c new file mode 100644 index 0000000000..6f326bf4fc --- /dev/null +++ b/nuttx/lib/misc/lib_dbg.c @@ -0,0 +1,165 @@ +/**************************************************************************** + * lib/misc/lib_dbg.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* Debug output is initially disabled */ + +#ifdef CONFIG_DEBUG_ENABLE +bool g_dbgenable; +#endif + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dbg_enable + * + * Description: + * Enable or disable debug output. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_ENABLE +void dbg_enable(bool enable) +{ + g_dbgenable = enable; +} +#endif + +/**************************************************************************** + * Name: dbg, lldbg, vdbg + * + * Description: + * If the cross-compiler's pre-processor does not support variable + * length arguments, then these additional APIs will be built. + * + ****************************************************************************/ + +#ifndef CONFIG_CPP_HAVE_VARARGS +#ifdef CONFIG_DEBUG +int dbg(const char *format, ...) +{ + va_list ap; + int ret; + +#ifdef CONFIG_DEBUG_ENABLE + ret = 0; + if (g_dbgenable) +#endif + { + va_start(ap, format); + ret = lib_rawvprintf(format, ap); + va_end(ap); + } + + return ret; +} + +#ifdef CONFIG_ARCH_LOWPUTC +int lldbg(const char *format, ...) +{ + va_list ap; + int ret; + +#ifdef CONFIG_DEBUG_ENABLE + ret = 0; + if (g_dbgenable) +#endif + { + va_start(ap, format); + ret = lib_lowvprintf(format, ap); + va_end(ap); + } + + return ret; +} +#endif + +#ifdef CONFIG_DEBUG_VERBOSE +int vdbg(const char *format, ...) +{ + va_list ap; + int ret; + +#ifdef CONFIG_DEBUG_ENABLE + ret = 0; + if (g_dbgenable) +#endif + { + va_start(ap, format); + ret = lib_rawvprintf(format, ap); + va_end(ap); + } + + return ret; +} + +#ifdef CONFIG_ARCH_LOWPUTC +int llvdbg(const char *format, ...) +{ + va_list ap; + int ret; + +#ifdef CONFIG_DEBUG_ENABLE + ret = 0; + if (g_dbgenable) +#endif + { + va_start(ap, format); + ret = lib_lowvprintf(format, ap); + va_end(ap); + } + + return ret; +} +#endif /* CONFIG_ARCH_LOWPUTC */ +#endif /* CONFIG_DEBUG_VERBOSE */ +#endif /* CONFIG_DEBUG */ +#endif /* CONFIG_CPP_HAVE_VARARGS */ diff --git a/nuttx/lib/misc/lib_dumpbuffer.c b/nuttx/lib/misc/lib_dumpbuffer.c new file mode 100644 index 0000000000..1f1f54e8db --- /dev/null +++ b/nuttx/lib/misc/lib_dumpbuffer.c @@ -0,0 +1,129 @@ +/**************************************************************************** + * lib/misc/lib_dumpbuffer.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +/* Select the lowest level debug interface available */ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_ARCH_LOWPUTC +# define message(format, arg...) lib_lowprintf(format, ##arg) +# else +# define message(format, arg...) lib_rawprintf(format, ##arg) +# endif +#else +# ifdef CONFIG_ARCH_LOWPUTC +# define message lib_lowprintf +# else +# define message lib_rawprintf +# endif +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_dumpbuffer + * + * Description: + * Do a pretty buffer dump + * + ****************************************************************************/ + +void lib_dumpbuffer(FAR const char *msg, FAR const uint8_t *buffer, unsigned int buflen) +{ + int i, j, k; + + message("%s (%p):\n", msg, buffer); + for (i = 0; i < buflen; i += 32) + { + message("%04x: ", i); + for (j = 0; j < 32; j++) + { + k = i + j; + + if (j == 16) + { + message(" "); + } + + if (k < buflen) + { + message("%02x", buffer[k]); + } + else + { + message(" "); + } + } + + message(" "); + for (j = 0; j < 32; j++) + { + k = i + j; + + if (j == 16) + { + message(" "); + } + + if (k < buflen) + { + if (buffer[k] >= 0x20 && buffer[k] < 0x7f) + { + message("%c", buffer[k]); + } + else + { + message("."); + } + } + } + message("\n"); + } +} diff --git a/nuttx/lib/misc/lib_filesem.c b/nuttx/lib/misc/lib_filesem.c new file mode 100644 index 0000000000..e6a3fdb671 --- /dev/null +++ b/nuttx/lib/misc/lib_filesem.c @@ -0,0 +1,145 @@ +/************************************************************************ + * lib/misc/lib_filesem.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "lib_internal.h" + +#if CONFIG_STDIO_BUFFER_SIZE > 0 + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Data + ************************************************************************/ + +/************************************************************************ + * Global Functions + ************************************************************************/ + +/************************************************************************ + * lib_sem_initialize + ************************************************************************/ + +void lib_sem_initialize(FAR struct file_struct *stream) +{ + /* Initialize the LIB semaphore to one (to support one-at- + * a-time access to private data sets. + */ + + (void)sem_init(&stream->fs_sem, 0, 1); + + stream->fs_holder = -1; + stream->fs_counts = 0; +} + +/************************************************************************ + * lib_take_semaphore + ************************************************************************/ + +void lib_take_semaphore(FAR struct file_struct *stream) +{ + pid_t my_pid = getpid(); + + /* Do I already have the semaphore? */ + + if (stream->fs_holder == my_pid) + { + /* Yes, just increment the number of references that I have */ + + stream->fs_counts++; + } + else + { + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&stream->fs_sem) != 0) + { + /* The only case that an error should occr here is if + * the wait was awakened by a signal. + */ + + ASSERT(get_errno() == EINTR); + } + + /* We have it. Claim the stak and return */ + + stream->fs_holder = my_pid; + stream->fs_counts = 1; + } +} + +/************************************************************************ + * lib_give_semaphore + ************************************************************************/ + +void lib_give_semaphore(FAR struct file_struct *stream) +{ + pid_t my_pid = getpid(); + + /* I better be holding at least one reference to the semaphore */ + + ASSERT(stream->fs_holder == my_pid); + + /* Do I hold multiple references to the semphore */ + + if (stream->fs_counts > 1) + { + /* Yes, just release one count and return */ + + stream->fs_counts--; + } + else + { + /* Nope, this is the last reference I have */ + + stream->fs_holder = -1; + stream->fs_counts = 0; + ASSERT(sem_post(&stream->fs_sem) == 0); + } +} +#endif /* CONFIG_STDIO_BUFFER_SIZE */ diff --git a/nuttx/lib/misc/lib_init.c b/nuttx/lib/misc/lib_init.c new file mode 100644 index 0000000000..fb246b1ad3 --- /dev/null +++ b/nuttx/lib/misc/lib_init.c @@ -0,0 +1,207 @@ +/************************************************************ + * lib/misc/lib_init.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "lib_internal.h" + +/************************************************************ + * Definitions + ************************************************************/ + +/************************************************************ + * Private Variables + ************************************************************/ + +/************************************************************ + * Private Functions + ************************************************************/ + +/************************************************************ + * Public Functions + ************************************************************/ + +/************************************************************ + * lib_initialize + ************************************************************/ + +/* General library initialization hook */ + +void weak_const_function lib_initialize(void) +{ +} + +#if CONFIG_NFILE_STREAMS > 0 +/* The following function is called when a new TCB is allocated. It + * creates the streamlist instance that is stored in the TCB. + */ + +FAR struct streamlist *lib_alloclist(void) +{ + FAR struct streamlist *list; + list = (FAR struct streamlist*)lib_zalloc(sizeof(struct streamlist)); + if (list) + { + int i; + + /* Start with a reference count of one */ + + list->sl_crefs = 1; + + /* Initialize the list access mutex */ + + (void)sem_init(&list->sl_sem, 0, 1); + + /* Initialize each FILE structure */ + + for (i = 0; i < CONFIG_NFILE_STREAMS; i++) + { + /* Clear the IOB */ + + memset(&list->sl_streams[i], 0, sizeof(FILE)); + + /* Indicate not opened */ + + list->sl_streams[i].fs_filedes = -1; + + /* Initialize the stream semaphore to one to support one-at- + * a-time access to private data sets. + */ + + lib_sem_initialize(&list->sl_streams[i]); + } + } + return list; + +} + +/* This function is called when a TCB is closed (such as with + * pthread_create(). It increases the reference count on the stream + * list. + */ + +void lib_addreflist(FAR struct streamlist *list) +{ + if (list) + { + /* Increment the reference count on the list. + * NOTE: that we disable interrupts to do this + * (vs. taking the list semaphore). We do this + * because file cleanup operations often must be + * done from the IDLE task which cannot wait + * on semaphores. + */ + + register irqstate_t flags = irqsave(); + list->sl_crefs++; + irqrestore(flags); + } +} + +/* this function is called when a TCB is destroyed. Note that is + * does not close the file by release this inode. This happens + * separately when the file descriptor list is freed. + */ + +void lib_releaselist(FAR struct streamlist *list) +{ + int crefs; + if (list) + { + /* Decrement the reference count on the list. + * NOTE: that we disable interrupts to do this + * (vs. taking the list semaphore). We do this + * because file cleanup operations often must be + * done from the IDLE task which cannot wait + * on semaphores. + */ + + register irqstate_t flags = irqsave(); + crefs = --(list->sl_crefs); + irqrestore(flags); + + /* If the count decrements to zero, then there is no reference + * to the structure and it should be deallocated. Since there + * are references, it would be an error if any task still held + * a reference to the list's semaphore. + */ + + if (crefs <= 0) + { +#if CONFIG_STDIO_BUFFER_SIZE > 0 + int i; +#endif + /* Destroy the semaphore and release the filelist */ + + (void)sem_destroy(&list->sl_sem); + + /* Release each stream in the list */ + +#if CONFIG_STDIO_BUFFER_SIZE > 0 + for (i = 0; i < CONFIG_NFILE_STREAMS; i++) + { + /* Destroy the semaphore that protects the IO buffer */ + + (void)sem_destroy(&list->sl_streams[i].fs_sem); + + /* Release the IO buffer */ + if (list->sl_streams[i].fs_bufstart) + { + sched_free(list->sl_streams[i].fs_bufstart); + } + } +#endif + /* Finally, release the list itself */ + + sched_free(list); + } + } +} + +#endif /* CONFIG_NFILE_STREAMS */ + + diff --git a/nuttx/lib/misc/lib_match.c b/nuttx/lib/misc/lib_match.c new file mode 100644 index 0000000000..18e0632ec6 --- /dev/null +++ b/nuttx/lib/misc/lib_match.c @@ -0,0 +1,148 @@ +/**************************************************************************** + * lib/misc/lib_match.c - simple shell-style filename matcher + * + * Simple shell-style filename pattern matcher written by Jef Poskanzer + * This pattern matcher only handles '?', '*' and '**', and multiple + * patterns separated by '|'. + * + * Copyright © 1995,2000 by Jef Poskanzer . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: match_one + * + * Description: + * Does all of the work for one '|' delimited pattern + * + * Returned Value: + * Returns 1 (match) or 0 (no-match). + * + ****************************************************************************/ + +static int match_one(const char *pattern, int patlen, const char *string) +{ + const char *p; + int pl; + int i; + + for (p = pattern; p - pattern < patlen; p++, string++) + { + if (*p == '?' && *string != '\0') + { + continue; + } + + if (*p == '*') + { + p++; + if (*p == '*') + { + /* Double-wildcard matches anything. */ + + p++; + i = strlen(string); + } + else + { + /* Single-wildcard matches anything but slash. */ + + i = strcspn(string, "/"); + } + + pl = patlen - (p - pattern); + for (; i >= 0; i--) + { + if (match_one(p, pl, &(string[i]))) + { + return 1; + } + } + return 0; + } + + if (*p != *string) + { + return 0; + } + } + + if (*string == '\0') + { + return 1; + } + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: match + * + * Description: + * Simple shell-style filename pattern matcher written by Jef Poskanzer + * This pattern matcher only handles '?', '*' and '**', and multiple + * patterns separated by '|'. + * + * Returned Value: + * Returns 1 (match) or 0 (no-match). + * + ****************************************************************************/ + +int match(const char *pattern, const char *string) +{ + const char *or; + + for (;;) + { + or = strchr(pattern, '|'); + if (or == (char *)0) + { + return match_one(pattern, strlen(pattern), string); + } + + if (match_one(pattern, or - pattern, string)) + { + return 1; + } + + pattern = or + 1; + } +} + diff --git a/nuttx/lib/misc/lib_streamsem.c b/nuttx/lib/misc/lib_streamsem.c new file mode 100644 index 0000000000..3d86ab280e --- /dev/null +++ b/nuttx/lib/misc/lib_streamsem.c @@ -0,0 +1,90 @@ +/************************************************************************ + * lib/misc/lib_streamsem.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "lib_internal.h" + +/************************************************************************ + * Private types + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Public Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +void stream_semtake(FAR struct streamlist *list) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&list->sl_sem) != 0) + { + /* The only case that an error should occr here is if + * the wait was awakened by a signal. + */ + + ASSERT(get_errno() == EINTR); + } +} + +void stream_semgive(FAR struct streamlist *list) +{ + sem_post(&list->sl_sem); +} + + diff --git a/nuttx/lib/mqueue/Make.defs b/nuttx/lib/mqueue/Make.defs new file mode 100644 index 0000000000..cd2091e993 --- /dev/null +++ b/nuttx/lib/mqueue/Make.defs @@ -0,0 +1,39 @@ +############################################################################ +# lib/mqueue/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifneq ($(CONFIG_DISABLE_MQUEUE),y) +MQUEUE_SRCS = mq_setattr.c mq_getattr.c +endif + diff --git a/nuttx/lib/mqueue/mq_getattr.c b/nuttx/lib/mqueue/mq_getattr.c new file mode 100644 index 0000000000..005ec0f245 --- /dev/null +++ b/nuttx/lib/mqueue/mq_getattr.c @@ -0,0 +1,104 @@ +/************************************************************************ + * lib/mqueue/mq_getattr.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Function: mq_getattr + * + * Description: + * This functions gets status information and attributes + * associated with the specified message queue. + * + * Parameters: + * mqdes - Message queue descriptor + * mq_stat - Buffer in which to return attributes + * + * Return Value: + * 0 (OK) if attributes provided, -1 (ERROR) otherwise. + * + * Assumptions: + * + ************************************************************************/ + +int mq_getattr(mqd_t mqdes, struct mq_attr *mq_stat) +{ + int ret = ERROR; + + if (mqdes && mq_stat) + { + /* Return the attributes */ + + mq_stat->mq_maxmsg = mqdes->msgq->maxmsgs; + mq_stat->mq_msgsize = mqdes->msgq->maxmsgsize; + mq_stat->mq_flags = mqdes->oflags; + mq_stat->mq_curmsgs = mqdes->msgq->nmsgs; + + ret = OK; + } + + return ret; +} diff --git a/nuttx/lib/mqueue/mq_setattr.c b/nuttx/lib/mqueue/mq_setattr.c new file mode 100644 index 0000000000..5d82299fe7 --- /dev/null +++ b/nuttx/lib/mqueue/mq_setattr.c @@ -0,0 +1,118 @@ +/************************************************************************ + * lib/mqueue/mq_setattr.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include /* O_NONBLOCK */ +#include + +#include + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Function: mq_setattr + * + * Description: + * This function sets the attributes associated with the + * specified message queue "mqdes." Only the "O_NONBLOCK" + * bit of the "mq_flags" can be changed. + * + * If "oldstat" is non-null, mq_setattr() will store the + * previous message queue attributes at that location (just + * as would have been returned by mq_getattr()). + * + * Parameters: + * mqdes - Message queue descriptor + * mq_stat - New attributes + * oldstate - Old attributes + * + * Return Value: + * 0 (OK) if attributes are set successfully, otherwise + * -1 (ERROR). + * + * Assumptions: + * + ************************************************************************/ + +int mq_setattr(mqd_t mqdes, const struct mq_attr *mq_stat, + struct mq_attr *oldstat) +{ + int ret = ERROR; + + if (mqdes && mq_stat) + { + /* Return the attributes if so requested */ + + if (oldstat) + { + (void)mq_getattr(mqdes, oldstat); + } + + /* Set the new value of the O_NONBLOCK flag. */ + + mqdes->oflags = ((mq_stat->mq_flags & O_NONBLOCK) | + (mqdes->oflags & (~O_NONBLOCK))); + ret = OK; + } + + return ret; +} diff --git a/nuttx/lib/net/Make.defs b/nuttx/lib/net/Make.defs new file mode 100644 index 0000000000..94ac6db036 --- /dev/null +++ b/nuttx/lib/net/Make.defs @@ -0,0 +1,37 @@ +############################################################################ +# lib/net/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +NET_SRCS = lib_etherntoa.c lib_htons.c lib_htonl.c lib_inetaddr.c +NET_SRCS += lib_inetntoa.c lib_inetntop.c lib_inetpton.c diff --git a/nuttx/lib/net/lib_etherntoa.c b/nuttx/lib/net/lib_etherntoa.c new file mode 100644 index 0000000000..2535491833 --- /dev/null +++ b/nuttx/lib/net/lib_etherntoa.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * lib/net/lib_etherntoa.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ether_ntoa + * + * Description: + * The ether_ntoa() function converts the Ethernet host address addr given + * in network byte order to a string in standard hex-digits-and-colons + * notation. The string is returned in a statically allocated buffer, which + * subsequent calls will overwrite. + * + ****************************************************************************/ + +char *ether_ntoa(const struct ether_addr *addr) +{ + static char buffer[20]; + sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", + addr->ether_addr_octet[0], addr->ether_addr_octet[1], + addr->ether_addr_octet[2], addr->ether_addr_octet[3], + addr->ether_addr_octet[4], addr->ether_addr_octet[5]); + return buffer; +} diff --git a/nuttx/lib/net/lib_htonl.c b/nuttx/lib/net/lib_htonl.c new file mode 100644 index 0000000000..f43b525050 --- /dev/null +++ b/nuttx/lib/net/lib_htonl.c @@ -0,0 +1,68 @@ +/************************************************************ + * lib/net/lib_ntohl.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +#include +#include + +/************************************************************ + * Global Functions + ************************************************************/ + +uint32_t htonl(uint32_t hl) +{ +#ifdef CONFIG_ENDIAN_BIG + return hl; +#else + return (( (hl) >> 24) | + (((hl) >> 8) & 0x0000ff00) | + (((hl) << 8) & 0x00ff0000) | + ( (hl) << 24)); +#endif +} + +uint32_t ntohl(uint32_t nl) +{ +#ifdef CONFIG_ENDIAN_BIG + return nl; +#else + return htonl(nl); +#endif +} diff --git a/nuttx/lib/net/lib_htons.c b/nuttx/lib/net/lib_htons.c new file mode 100644 index 0000000000..66d736a33f --- /dev/null +++ b/nuttx/lib/net/lib_htons.c @@ -0,0 +1,65 @@ +/*************************************************************************** + * lib/net/lib_htons.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ***************************************************************************/ + +/*************************************************************************** + * Compilation Switches + ***************************************************************************/ + +/*************************************************************************** + * Included Files + ***************************************************************************/ + +#include + +#include +#include + +/*************************************************************************** + * Global Functions + ***************************************************************************/ + +uint16_t htons(uint16_t hs) +{ + return HTONS(hs); +} + +uint16_t ntohs(uint16_t ns) +{ +#ifdef CONFIG_ENDIAN_BIG + return ns; +#else + return htons(ns); +#endif +} diff --git a/nuttx/lib/net/lib_inetaddr.c b/nuttx/lib/net/lib_inetaddr.c new file mode 100644 index 0000000000..48b01d682f --- /dev/null +++ b/nuttx/lib/net/lib_inetaddr.c @@ -0,0 +1,74 @@ +/**************************************************************************** + * lib/net/lib_inetaddr.c + * + * Copyright (C) 2011 Yu Qiang. All rights reserved. + * Author: Yu Qiang + * + * This file is a part of NuttX: + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * name inet_addr + * + * Description: + * The inet_addr() function converts the string pointed to by cp, in the + * standard IPv4 dotted decimal notation, to an integer value suitable for + * use as an Internet address. + + ****************************************************************************/ + +in_addr_t inet_addr(FAR const char *cp) +{ + unsigned int a, b, c, d; + uint32_t result; + + sscanf(cp, "%u.%u.%u.%u", &a, &b, &c, &d); + result = a << 8; + result |= b; + result <<= 8; + result |= c; + result <<= 8; + result |= d; + return HTONL(result); +} diff --git a/nuttx/lib/net/lib_inetntoa.c b/nuttx/lib/net/lib_inetntoa.c new file mode 100644 index 0000000000..0f4fb61df6 --- /dev/null +++ b/nuttx/lib/net/lib_inetntoa.c @@ -0,0 +1,79 @@ +/**************************************************************************** + * lib/net/lib_inetntoa.c + * + * Copyright (C) 2007-2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#ifndef CONFIG_NET_IPv6 + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: inet_ntoa + * + * Description: + * The inet_ntoa() function converts the Internet host address in given in + * network byte order to a string in standard numbers-and-dots notation. + * The string is returned in a statically allocated buffer, which subsequent + * calls will overwrite. + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_PASS_STRUCTS +FAR char *inet_ntoa(struct in_addr in) +{ + static char buffer[INET_ADDRSTRLEN+2]; + FAR char *ptr = (FAR char*)&in.s_addr; + sprintf(buffer, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]); + return buffer; +} +#else +FAR char *_inet_ntoa(in_addr_t in) +{ + static char buffer[INET_ADDRSTRLEN+2]; + FAR char *ptr = (FAR char*)∈ + sprintf(buffer, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]); + return buffer; +} +#endif +#endif /* !CONFIG_NET_IPv6 */ + diff --git a/nuttx/lib/net/lib_inetntop.c b/nuttx/lib/net/lib_inetntop.c new file mode 100644 index 0000000000..dc6a2d0d79 --- /dev/null +++ b/nuttx/lib/net/lib_inetntop.c @@ -0,0 +1,202 @@ +/**************************************************************************** + * lib/net/lib_inetntop.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Includes some logic extracted from hwport_ftpd, written by Jaehyuk Cho + * which was released under the BSD license. + * + * Copyright (C) HWPORT.COM. All rights reserved. + * Author: JAEHYUK CHO + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: inet_ntop + * + * Description: + * The inet_ntop() function converts a numeric address into a text string + * suitable for presentation. + * + * Input Parameters: + * af - The af argument specifies the family of the address. This can be + * AF_INET or AF_INET6. + * src - The src argument points to a buffer holding an address of the + * specified type. The address must be in network byte order. + * dst - The dst argument points to a buffer where the function stores + * the resulting text string; it shall not be NULL. + * size - The size argument specifies the size of this buffer, which must + * be large enough to hold the text string (INET_ADDRSTRLEN + * characters for IPv4, INET6_ADDRSTRLEN characters for IPv6). + * + * Returned Value: + * inet_ntop() returns a pointer to the buffer containing the text string + * if the conversion succeeds. Otherwise, NULL is returned and the errno + * is set to indicate the error. There follow errno values may be set: + * + * EAFNOSUPPORT - The af argument is invalid. + * ENOSPC - The size of the inet_ntop() result buffer is inadequate + * + ****************************************************************************/ + +FAR const char *inet_ntop(int af, FAR const void *src, FAR char *dst, socklen_t size) +{ + int errval; +#ifndef CONFIG_NET_IPv6 + FAR char *ptr; + + DEBUGASSERT(src && dst); + + if (af != AF_INET) + { + errval = EAFNOSUPPORT; + goto errout; + } + + if (size < INET_ADDRSTRLEN) + { + errval = ENOSPC; + goto errout; + } + + ptr = (FAR char*)src; + sprintf(dst, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]); + return dst; +#else + FAR const struct in6_addr *in6_addr; + uint16_t warray[8]; + int offset; + int entry; + int count; + int maxentry; + int maxcount; + + DEBUGASSERT(src && dst); + + if (af != AF_INET6) + { + errval = EAFNOSUPPORT; + goto errout; + } + + if (size < INET6_ADDRSTRLEN) + { + errval = ENOSPC; + goto errout; + } + + in6_addr = (FAR const struct in6_addr *)src; + entry = -1; + maxentry = -1; + maxcount = 0; + offset = 0; + + while (offset < 8) + { + warray[offset] = ntohs(in6_addr->s6_addr16[offset]); + if (warray[offset] == 0) + { + entry = offset; + count = 1; + offset++; + + while (offset < 8) + { + warray[offset] = ntohs(in6_addr->s6_addr16[offset]); + if (warray[offset] != 0) + { + break; + } + offset++; + count++; + } + + if (count > maxcount) + { + maxentry = entry; + maxcount = count; + } + } + offset++; + } + + offset = 0; + dst[0] = '\0'; + + while (offset < 8) + { + if (offset == maxentry) + { + size -= snprintf(&dst[strlen(dst)], size, ":"); + offset += maxcount; + if (offset >= 8) + { + size -= snprintf(&dst[strlen(dst)], size, ":"); + } + } + else + { + if (offset > 0) + { + size -= snprintf(&dst[strlen(dst)], size, ":"); + } + + size -= snprintf(&dst[strlen(dst)], size, "%x", warray[offset]); + offset++; + } + } + + return dst; +#endif + +errout: + set_errno(errval); + memset(dst, 0, size); + return NULL; +} diff --git a/nuttx/lib/net/lib_inetpton.c b/nuttx/lib/net/lib_inetpton.c new file mode 100644 index 0000000000..5371cd3f21 --- /dev/null +++ b/nuttx/lib/net/lib_inetpton.c @@ -0,0 +1,338 @@ +/**************************************************************************** + * lib/net/lib_inetpton.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Includes some logic extracted from hwport_ftpd, written by Jaehyuk Cho + * which was released under the BSD license. + * + * Copyright (C) HWPORT.COM. All rights reserved. + * Author: JAEHYUK CHO + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: inet_pton + * + * Description: + * The inet_pton() function converts an address in its standard text + * presentation form into its numeric binary form. + * + * If the af argument of inet_pton() is AF_INET, the src string will be + * in the standard IPv4 dotted-decimal form: + * + * ddd.ddd.ddd.ddd + * + * where "ddd" is a one to three digit decimal number between 0 and 255. + * + * If the af argument of inet_pton() is AF_INET6, the src string will be in + * one of the following standard IPv6 text forms: + * + * 1. The preferred form is "x:x:x:x:x:x:x:x", where the 'x' s are the + * hexadecimal values of the eight 16-bit pieces of the address. Leading + * zeros in individual fields can be omitted, but there must be at least + * one numeral in every field. + * + * 2. A string of contiguous zero fields in the preferred form can be shown + * as "::". The "::" can only appear once in an address. Unspecified + * addresses ( "0:0:0:0:0:0:0:0" ) may be represented simply as "::". + * + * 3. A third form that is sometimes more convenient when dealing with a + * mixed environment of IPv4 and IPv6 nodes is "x:x:x:x:x:x:d.d.d.d", + * where the 'x' s are the hexadecimal values of the six high-order + * 16-bit pieces of the address, and the 'd' s are the decimal values + * of the four low-order 8-bit pieces of the address (standard IPv4 + * representation). + * + * Input Parameters: + * af - The af argument specifies the family of the address. This can be + * AF_INET or AF_INET6. + * src - The src argument points to the string being passed in. + * dst - The dst argument points to a numstr into which the function stores + * the numeric address; this must be large enough to hold the numeric + * address (32 bits for AF_INET, 128 bits for AF_INET6). + * + * Returned Value: + * The inet_pton() function returns 1 if the conversion succeeds, with the + * address pointed to by dst in network byte order. It will return 0 if the + * input is not a valid IPv4 dotted-decimal string or a valid IPv6 address + * string, or -1 with errno set to EAFNOSUPPOR] if the af argument is unknown. + * + ****************************************************************************/ + +int inet_pton(int af, FAR const char *src, FAR void *dst) +{ +#ifndef CONFIG_NET_IPv6 + size_t srcoffset; + size_t numoffset; + int value; + int ndots; + uint8_t ch; + char numstr[4]; + uint8_t *ip; + + DEBUGASSERT(src && dst); + + if (af != AF_INET) + { + set_errno(EAFNOSUPPORT); + return -1; + } + + (void)memset(dst, 0, sizeof(struct in_addr)); + + ip = (uint8_t *)dst; + srcoffset = 0; + numoffset = 0; + ndots = 0; + + for(;;) + { + ch = (uint8_t)src[srcoffset++]; + + if (ch == '.' || ch == '\0') + { + if (ch == '.' && ndots >= 4) + { + /* Too many dots */ + + break; + } + + if (numoffset <= 0) + { + /* Empty numeric string */ + + break; + } + + numstr[numoffset] = '\0'; + numoffset = 0; + + value = atoi(numstr); + if (value < 0 || value > 255) + { + /* Out of range value */ + + break; + } + + ip[ndots] = (uint8_t)value; + + if (ch == '\0') + { + if (ndots != 3) + { + /* Not enough dots */ + + break; + } + + /* Return 1 if the conversion succeeds */ + + return 1; + } + + ndots++; + } + else if (ch >= '0' && ch <= '9') + { + numstr[numoffset++] = ch; + if (numoffset >= 4) + { + /* Number is too long */ + + break; + } + } + else + { + /* Illegal character */ + + break; + } + } + + /* Return zero if there is any problem parsing the input */ + + return 0; +#else + size_t srcoffset; + size_t numoffset; + long value; + int nsep; + int nrsep; + uint8_t ch; + char numstr[5]; + uint8_t ip[sizeof(struct in6_addr)]; + uint8_t rip[sizeof(struct in6_addr)]; + bool rtime; + + DEBUGASSERT(src && dst); + + if (af != AF_INET6) + { + set_errno(EAFNOSUPPORT); + return -1; + } + + (void)memset(dst, 0, sizeof(struct in6_addr)); + + srcoffset = 0; + numoffset = 0; + nsep = 0; + nrsep = 0; + rtime = false; + + for(;;) + { + ch = (uint8_t)src[srcoffset++]; + + if (ch == ':' || ch == '\0') + { + if (ch == ':' && (nsep + nrsep) >= 8) + { + /* Too many separators */ + + break; + } + + if (ch != '\0' && numoffset <= 0) + { + /* Empty numeric string */ + + if (rtime && nrsep > 1) + { + /* dup simple */ + + break; + } + + numoffset = 0; + rtime = true; + continue; + } + + numstr[numoffset] = '\0'; + numoffset = 0; + + value = strtol(numstr, NULL, 16); + if (value < 0 || value > 0xffff) + { + /* Out of range value */ + + break; + } + + if (!rtime) + { + ip[(nsep << 1) + 0] = (uint8_t)((value >> 8) & 0xff); + ip[(nsep << 1) + 1] = (uint8_t)((value >> 0) & 0xff); + nsep++; + } + else + { + rip[(nrsep << 1) + 0] = (uint8_t)((value >> 8) & 0xff); + rip[(nrsep << 1) + 1] = (uint8_t)((value >> 0) & 0xff); + nrsep++; + } + + if (ch == '\0' /* || ch == '/' */) + { + if ((nsep <= 1 && nrsep <= 0) || + (nsep + nrsep) < 1 || + (nsep + nrsep) > 8) + { + /* Separator count problem */ + + break; + } + + if (nsep > 0) + { + memcpy(dst, &ip[0], nsep << 1); + } + + if (nrsep > 0) + { + memcpy(dst + (16 - (nrsep << 1)), &rip[0], nrsep << 1); + } + + /* Return 1 if the conversion succeeds */ + + return 1; + } + } + else if ((ch >= '0' && ch <= '9') || + (ch >= 'a' && ch <= 'f') || + (ch >= 'A' && ch <= 'F')) + { + numstr[numoffset++] = ch; + if (numoffset >= 5) + { + /* Numeric string is too long */ + + break; + } + } + else + { + /* Illegal character */ + + break; + } + } + + + /* Return zero if there is any problem parsing the input */ + + return 0; +#endif +} diff --git a/nuttx/lib/pthread/Make.defs b/nuttx/lib/pthread/Make.defs new file mode 100644 index 0000000000..47211f9b93 --- /dev/null +++ b/nuttx/lib/pthread/Make.defs @@ -0,0 +1,49 @@ +############################################################################ +# lib/pthread/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +PTHREAD_SRCS = pthread_attrinit.c pthread_attrdestroy.c \ + pthread_attrsetschedpolicy.c pthread_attrgetschedpolicy.c \ + pthread_attrsetinheritsched.c pthread_attrgetinheritsched.c \ + pthread_attrsetstacksize.c pthread_attrgetstacksize.c \ + pthread_attrsetschedparam.c pthread_attrgetschedparam.c \ + pthread_barrierattrinit.c pthread_barrierattrdestroy.c \ + pthread_barrierattrgetpshared.c pthread_barrierattrsetpshared.c \ + pthread_condattrinit.c pthread_condattrdestroy.c \ + pthread_mutexattrinit.c pthread_mutexattrdestroy.c \ + pthread_mutexattrgetpshared.c pthread_mutexattrsetpshared.c + +ifeq ($(CONFIG_MUTEX_TYPES),y) +PTHREAD_SRCS += pthread_mutexattrsettype.c pthread_mutexattrgettype.c +endif diff --git a/nuttx/lib/pthread/pthread_attrdestroy.c b/nuttx/lib/pthread/pthread_attrdestroy.c new file mode 100644 index 0000000000..fdadab7432 --- /dev/null +++ b/nuttx/lib/pthread/pthread_attrdestroy.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * lib/pthread/pthread_attrdestroy.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_attr_destroy + * + * Description: + * An attributes object can be deleted when it is no longer + * needed. + * + * Parameters: + * attr + * + * Return Value: + * 0 meaning success + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_attr_destroy(FAR pthread_attr_t *attr) +{ + int ret; + + sdbg("attr=0x%p\n", attr); + + if (!attr) + { + ret = EINVAL; + } + else + { + memset(attr, 0, sizeof(pthread_attr_t)); + ret = OK; + } + + sdbg("Returning %d\n", ret); + return ret; +} + + diff --git a/nuttx/lib/pthread/pthread_attrgetinheritsched.c b/nuttx/lib/pthread/pthread_attrgetinheritsched.c new file mode 100644 index 0000000000..c1b764faa3 --- /dev/null +++ b/nuttx/lib/pthread/pthread_attrgetinheritsched.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * lib/pthread/pthread_attrgetinheritsched.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_attr_getinheritsched + * + * Description: + * Report whether the scheduling info in the pthread + * attributes will be used or if the thread will + * inherit the properties of the parent. + * + * Parameters: + * attr + * inheritsched + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_attr_getinheritsched(FAR const pthread_attr_t *attr, + FAR int *inheritsched) +{ + int ret; + + sdbg("attr=0x%p inheritsched=0x%p\n", attr, inheritsched); + + if (!attr || !inheritsched) + { + ret = EINVAL; + } + else + { + *inheritsched = (int)attr->inheritsched; + ret = OK; + } + + sdbg("Returning %d\n", ret); + return ret; +} + + diff --git a/nuttx/lib/pthread/pthread_attrgetschedparam.c b/nuttx/lib/pthread/pthread_attrgetschedparam.c new file mode 100644 index 0000000000..fa456f61a4 --- /dev/null +++ b/nuttx/lib/pthread/pthread_attrgetschedparam.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * lib/pthread/pthread_attrgetschedparam.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_attr_getschedparam + * + * Description: + * + * Parameters: + * attr + * param + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_attr_getschedparam(FAR pthread_attr_t *attr, + FAR struct sched_param *param) +{ + int ret; + + sdbg("attr=0x%p param=0x%p\n", attr, param); + + if (!attr || !param) + { + ret = EINVAL; + } + else + { + param->sched_priority = attr->priority; + ret = OK; + } + + sdbg("Returning %d\n", ret); + return ret; +} + + + diff --git a/nuttx/lib/pthread/pthread_attrgetschedpolicy.c b/nuttx/lib/pthread/pthread_attrgetschedpolicy.c new file mode 100644 index 0000000000..b4f762b519 --- /dev/null +++ b/nuttx/lib/pthread/pthread_attrgetschedpolicy.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * lib/pthread/pthread_attrgetschedpolicy.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_attr_getschedpolicy + * + * Description: + * Obtain the scheduling algorithm attribute. + * + * Parameters: + * attr + * policy + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_attr_getschedpolicy(FAR pthread_attr_t *attr, int *policy) +{ + int ret; + + sdbg("attr=0x%p policy=0x%p\n", attr, policy); + + if (!attr || !policy) + { + ret = EINVAL; + } + else + { + *policy = attr->policy; + ret = OK; + } + + sdbg("Returning %d\n", ret); + return ret; +} diff --git a/nuttx/lib/pthread/pthread_attrgetstacksize.c b/nuttx/lib/pthread/pthread_attrgetstacksize.c new file mode 100644 index 0000000000..06e40b5fbe --- /dev/null +++ b/nuttx/lib/pthread/pthread_attrgetstacksize.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * lib/pthread/pthread_attrgetstacksize.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_attr_getstacksize + * + * Description: + * + * Parameters: + * attr + * stacksize + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_attr_getstacksize(FAR pthread_attr_t *attr, FAR long *stacksize) +{ + int ret; + + sdbg("attr=0x%p stacksize=0x%p\n", attr, stacksize); + + if (!stacksize) + { + ret = EINVAL; + } + else + { + *stacksize = attr->stacksize; + ret = OK; + } + + sdbg("Returning %d\n", ret); + return ret; +} + + diff --git a/nuttx/lib/pthread/pthread_attrinit.c b/nuttx/lib/pthread/pthread_attrinit.c new file mode 100644 index 0000000000..7df73e54b4 --- /dev/null +++ b/nuttx/lib/pthread/pthread_attrinit.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * lib/pthread/pthread_attrinit.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* Default pthread attributes (see included/nuttx/pthread.h). When configured + * to build separate kernel- and user-address spaces, this global is + * duplicated in each address spaced. This copy can only be shared within + * the user address space. + */ + +#if defined(CONFIG_NUTTX_KERNEL) && !defined(__KERNEL__) +pthread_attr_t g_default_pthread_attr = PTHREAD_ATTR_INITIALIZER; +#endif + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_attr_init + * + * Description: + * Initializes a thread attributes object (attr) with + * default values for all of the individual attributes + * used by a given implementation. + * + * Parameters: + * attr + * + * Return Value: + * 0 on success, otherwise an error number + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_attr_init(FAR pthread_attr_t *attr) +{ + int ret = OK; + + sdbg("attr=0x%p\n", attr); + if (!attr) + { + ret = ENOMEM; + } + else + { + /* Set the child thread priority to be the default + * priority. Set the child stack size to some arbitrary + * default value. + */ + + memcpy(attr, &g_default_pthread_attr, sizeof(pthread_attr_t)); + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/lib/pthread/pthread_attrsetinheritsched.c b/nuttx/lib/pthread/pthread_attrsetinheritsched.c new file mode 100644 index 0000000000..ebdc9b3e45 --- /dev/null +++ b/nuttx/lib/pthread/pthread_attrsetinheritsched.c @@ -0,0 +1,113 @@ +/**************************************************************************** + * lib/pthread/pthread_attrsetinheritsched.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_attr_setinheritsched + * + * Description: + * Indicate whether the scheduling info in the pthread + * attributes will be used or if the thread will + * inherit the properties of the parent. + * + * Parameters: + * attr + * policy + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_attr_setinheritsched(FAR pthread_attr_t *attr, + int inheritsched) +{ + int ret; + + sdbg("inheritsched=%d\n", inheritsched); + + if (!attr || + (inheritsched != PTHREAD_INHERIT_SCHED && + inheritsched != PTHREAD_EXPLICIT_SCHED)) + { + ret = EINVAL; + } + else + { + attr->inheritsched = (uint8_t)inheritsched; + ret = OK; + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/lib/pthread/pthread_attrsetschedparam.c b/nuttx/lib/pthread/pthread_attrsetschedparam.c new file mode 100644 index 0000000000..4f65bcd8cb --- /dev/null +++ b/nuttx/lib/pthread/pthread_attrsetschedparam.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * lib/pthread/pthread_attrsetschedparam.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_attr_setschedparam + * + * Description: + * + * Parameters: + * attr + * param + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_attr_setschedparam(FAR pthread_attr_t *attr, + FAR const struct sched_param *param) +{ + int ret; + + sdbg("attr=0x%p param=0x%p\n", attr, param); + + if (!attr || !param) + { + ret = EINVAL; + } + else + { + attr->priority = (short)param->sched_priority; + ret = OK; + } + sdbg("Returning %d\n", ret); + return ret; +} + + diff --git a/nuttx/lib/pthread/pthread_attrsetschedpolicy.c b/nuttx/lib/pthread/pthread_attrsetschedpolicy.c new file mode 100644 index 0000000000..b4b1fd0543 --- /dev/null +++ b/nuttx/lib/pthread/pthread_attrsetschedpolicy.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * lib/pthread/pthread_attrsetschedpolicy.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_attr_setschedpolicy + * + * Description: + * Set the scheduling algorithm attribute. + * + * Parameters: + * attr + * policy + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_attr_setschedpolicy(FAR pthread_attr_t *attr, int policy) +{ + int ret; + + sdbg("attr=0x%p policy=%d\n", attr, policy); + +#if CONFIG_RR_INTERVAL > 0 + if (!attr || (policy != SCHED_FIFO && policy != SCHED_RR)) +#else + if (!attr || policy != SCHED_FIFO ) +#endif + { + ret = EINVAL; + } + else + { + attr->policy = policy; + ret = OK; + } + + sdbg("Returning %d\n", ret); + return ret; +} diff --git a/nuttx/lib/pthread/pthread_attrsetstacksize.c b/nuttx/lib/pthread/pthread_attrsetstacksize.c new file mode 100644 index 0000000000..a2de8ac78d --- /dev/null +++ b/nuttx/lib/pthread/pthread_attrsetstacksize.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * lib/pthread/pthread_attrsetstacksize.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_attr_setstacksize + * + * Description: + * + * Parameters: + * attr + * stacksize + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_attr_setstacksize(FAR pthread_attr_t *attr, long stacksize) +{ + int ret; + + sdbg("attr=0x%p stacksize=%ld\n", attr, stacksize); + + if (!attr || stacksize < PTHREAD_STACK_MIN) + { + ret = EINVAL; + } + else + { + attr->stacksize = stacksize; + ret = OK; + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/lib/pthread/pthread_barrierattrdestroy.c b/nuttx/lib/pthread/pthread_barrierattrdestroy.c new file mode 100644 index 0000000000..7498bc4f23 --- /dev/null +++ b/nuttx/lib/pthread/pthread_barrierattrdestroy.c @@ -0,0 +1,102 @@ +/******************************************************************************** + * lib/pthread/pthread_barrierattrdestroy.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Function: pthread_barrierattr_destroy + * + * Description: + * The pthread_barrierattr_destroy() function will destroy a barrier attributes + * object. A destroyed attr attributes object can be reinitialized using + * pthread_barrierattr_init(); the results of otherwise referencing the object + * after it has been destroyed are undefined. + * + * Parameters: + * attr - barrier attributes to be destroyed. + * + * Return Value: + * 0 (OK) on success or EINVAL if attr is invalid. + * + * Assumptions: + * + ********************************************************************************/ + +int pthread_barrierattr_destroy(FAR pthread_barrierattr_t *attr) +{ + int ret = OK; + + if (!attr) + { + ret = EINVAL; + } + else + { + attr->pshared = PTHREAD_PROCESS_PRIVATE; + } + return ret; +} diff --git a/nuttx/lib/pthread/pthread_barrierattrgetpshared.c b/nuttx/lib/pthread/pthread_barrierattrgetpshared.c new file mode 100644 index 0000000000..f4b4f64c13 --- /dev/null +++ b/nuttx/lib/pthread/pthread_barrierattrgetpshared.c @@ -0,0 +1,101 @@ +/******************************************************************************** + * lib/pthread/pthread_barrierattrgetpshared.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Function: pthread_barrierattr_getpshared + * + * Description: + * The pthread_barrierattr_getpshared() function will obtain the value of the + * process-shared attribute from the attributes object referenced by attr. + * + * Parameters: + * attr - barrier attributes to be queried. + * pshared - the location to stored the current value of the pshared attribute. + * + * Return Value: + * 0 (OK) on success or EINVAL if either attr or pshared is invalid. + * + * Assumptions: + * + ********************************************************************************/ + +int pthread_barrierattr_getpshared(FAR const pthread_barrierattr_t *attr, FAR int *pshared) +{ + int ret = OK; + + if (!attr || !pshared) + { + ret = EINVAL; + } + else + { + *pshared = attr->pshared; + } + return ret; +} diff --git a/nuttx/lib/pthread/pthread_barrierattrinit.c b/nuttx/lib/pthread/pthread_barrierattrinit.c new file mode 100644 index 0000000000..47bbb8eb42 --- /dev/null +++ b/nuttx/lib/pthread/pthread_barrierattrinit.c @@ -0,0 +1,101 @@ +/******************************************************************************** + * lib/pthread/pthread_barrierattrinit.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Function: pthread_barrierattr_init + * + * Description: + * The pthread_barrierattr_init() function will initialize a barrier attribute + * object attr with the default value for all of the attributes defined by the + * implementation. + * + * Parameters: + * attr - barrier attributes to be initialized. + * + * Return Value: + * 0 (OK) on success or EINVAL if attr is invalid. + * + * Assumptions: + * + ********************************************************************************/ + +int pthread_barrierattr_init(FAR pthread_barrierattr_t *attr) +{ + int ret = OK; + + if (!attr) + { + ret = EINVAL; + } + else + { + attr->pshared = PTHREAD_PROCESS_PRIVATE; + } + return ret; +} diff --git a/nuttx/lib/pthread/pthread_barrierattrsetpshared.c b/nuttx/lib/pthread/pthread_barrierattrsetpshared.c new file mode 100644 index 0000000000..a982eea393 --- /dev/null +++ b/nuttx/lib/pthread/pthread_barrierattrsetpshared.c @@ -0,0 +1,111 @@ +/******************************************************************************** + * lib/pthread/pthread_barrierattrsetpshared.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Function: pthread_barrierattr_setpshared + * + * Description: + * The process-shared attribute is set to PTHREAD_PROCESS_SHARED to permit a + * barrier to be operated upon by any thread that has access to the memory where + * the barrier is allocated. If the process-shared attribute is + * PTHREAD_PROCESS_PRIVATE, the barrier can only be operated upon by threads + * created within the same process as the thread that initialized the barrier. + * If threads of different processes attempt to operate on such a barrier, the + * behavior is undefined. The default value of the attribute is + * PTHREAD_PROCESS_PRIVATE. + * + * Both constants PTHREAD_PROCESS_SHARED and PTHREAD_PROCESS_PRIVATE are defined + * in pthread.h. + * + * Parameters: + * attr - barrier attributes to be modified. + * pshared - the new value of the pshared attribute. + * + * Return Value: + * 0 (OK) on success or EINVAL if either attr is invalid or pshared is not one + * of PTHREAD_PROCESS_SHARED or PTHREAD_PROCESS_PRIVATE. + * + * Assumptions: + * + ********************************************************************************/ + +int pthread_barrierattr_setpshared(FAR pthread_barrierattr_t *attr, int pshared) +{ + int ret = OK; + + if (!attr || (pshared != PTHREAD_PROCESS_SHARED && pshared != PTHREAD_PROCESS_PRIVATE)) + { + ret = EINVAL; + } + else + { + attr->pshared = pshared; + } + return ret; +} diff --git a/nuttx/lib/pthread/pthread_condattrdestroy.c b/nuttx/lib/pthread/pthread_condattrdestroy.c new file mode 100644 index 0000000000..c55dcd4e3f --- /dev/null +++ b/nuttx/lib/pthread/pthread_condattrdestroy.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * lib/pthread/pthread_condattrdestroy.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_condattr_destroy + * + * Description: + * Operations on condition variable attributes + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_condattr_destroy(FAR pthread_condattr_t *attr) +{ + int ret = OK; + + sdbg("attr=0x%p\n", attr); + + if (!attr) + { + ret = EINVAL; + } + + sdbg("Returning %d\n", ret); + return ret; +} + + + diff --git a/nuttx/lib/pthread/pthread_condattrinit.c b/nuttx/lib/pthread/pthread_condattrinit.c new file mode 100644 index 0000000000..75f01a11b6 --- /dev/null +++ b/nuttx/lib/pthread/pthread_condattrinit.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * lib/pthread/pthread_condattrinit.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_condattr_init + * + * Description: + * Operations on condition variable attributes + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_condattr_init(FAR pthread_condattr_t *attr) +{ + int ret = OK; + + sdbg("attr=0x%p\n", attr); + + if (!attr) + { + ret = EINVAL; + } + else + { + *attr = 0; + } + + sdbg("Returning %d\n", ret); + return ret; +} + + diff --git a/nuttx/lib/pthread/pthread_mutexattrdestroy.c b/nuttx/lib/pthread/pthread_mutexattrdestroy.c new file mode 100644 index 0000000000..59e81528be --- /dev/null +++ b/nuttx/lib/pthread/pthread_mutexattrdestroy.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * lib/pthread/pthread_mutexattrdestroy.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_mutexattr_destroy + * + * Description: + * Destroy mutex attributes. + * + * Parameters: + * attr + * pshared + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutexattr_destroy(FAR pthread_mutexattr_t *attr) +{ + int ret = OK; + + sdbg("attr=0x%p\n", attr); + + if (!attr) + { + ret = EINVAL; + } + else + { + attr->pshared = 0; + } + + sdbg("Returning %d\n", ret); + return ret; +} diff --git a/nuttx/lib/pthread/pthread_mutexattrgetpshared.c b/nuttx/lib/pthread/pthread_mutexattrgetpshared.c new file mode 100644 index 0000000000..e5e09bbbe1 --- /dev/null +++ b/nuttx/lib/pthread/pthread_mutexattrgetpshared.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * lib/pthread/pthread_mutexattrgetpshared.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_mutexattr_getpshared + * + * Description: + * Get pshared mutex attribute. + * + * Parameters: + * attr + * pshared + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutexattr_getpshared(FAR pthread_mutexattr_t *attr, FAR int *pshared) +{ + int ret = OK; + + sdbg("attr=0x%p pshared=0x%p\n", attr, pshared); + + if (!attr || !pshared) + { + ret = EINVAL; + } + else + { + *pshared = attr->pshared; + } + + sdbg("Returning %d\n", ret); + return ret; +} diff --git a/nuttx/lib/pthread/pthread_mutexattrgettype.c b/nuttx/lib/pthread/pthread_mutexattrgettype.c new file mode 100644 index 0000000000..93cbe36019 --- /dev/null +++ b/nuttx/lib/pthread/pthread_mutexattrgettype.c @@ -0,0 +1,98 @@ +/**************************************************************************** + * lib/pthread/pthread_mutexattrgettype.c + * + * Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#ifdef CONFIG_MUTEX_TYPES + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_mutexattr_gettype + * + * Description: + * Return the mutex type from the mutex attributes. + * + * Parameters: + * attr - The mutex attributes to query + * type - Location to return the mutex type + * + * Return Value: + * 0, if the mutex type was successfully return in 'type', or + * EINVAL, if any NULL pointers provided. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) +{ + if (attr && type) + { + *type = attr->type; + return 0; + } + return EINVAL; +} + +#endif /* CONFIG_MUTEX_TYPES */ diff --git a/nuttx/lib/pthread/pthread_mutexattrinit.c b/nuttx/lib/pthread/pthread_mutexattrinit.c new file mode 100644 index 0000000000..729b0b8e14 --- /dev/null +++ b/nuttx/lib/pthread/pthread_mutexattrinit.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * lib/pthread/pthread_mutexattrinit.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_mutexattr_init + * + * Description: + * Create mutex attributes. + * + * Parameters: + * attr + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutexattr_init(FAR pthread_mutexattr_t *attr) +{ + int ret = OK; + + sdbg("attr=0x%p\n", attr); + + if (!attr) + { + ret = EINVAL; + } + else + { + attr->pshared = 0; +#ifdef CONFIG_MUTEX_TYPES + attr->type = PTHREAD_MUTEX_DEFAULT; +#endif + } + + sdbg("Returning %d\n", ret); + return ret; +} diff --git a/nuttx/lib/pthread/pthread_mutexattrsetpshared.c b/nuttx/lib/pthread/pthread_mutexattrsetpshared.c new file mode 100644 index 0000000000..752e9faa03 --- /dev/null +++ b/nuttx/lib/pthread/pthread_mutexattrsetpshared.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * lib/pthread/pthread_mutexattrsetpshared.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_mutexattr_setpshared + * + * Description: + * Set pshared mutex attribute. + * + * Parameters: + * attr + * pshared + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutexattr_setpshared(FAR pthread_mutexattr_t *attr, int pshared) +{ + int ret = OK; + + sdbg("attr=0x%p pshared=%d\n", attr, pshared); + + if (!attr || (pshared != 0 && pshared != 1)) + { + ret = EINVAL; + } + else + { + attr->pshared = pshared; + } + + sdbg("Returning %d\n", ret); + return ret; +} diff --git a/nuttx/lib/pthread/pthread_mutexattrsettype.c b/nuttx/lib/pthread/pthread_mutexattrsettype.c new file mode 100644 index 0000000000..e095dd70c3 --- /dev/null +++ b/nuttx/lib/pthread/pthread_mutexattrsettype.c @@ -0,0 +1,98 @@ +/**************************************************************************** + * lib/pthread/pthread_mutexattrsettype.c + * + * Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#ifdef CONFIG_MUTEX_TYPES + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_mutexattr_settype + * + * Description: + * Set the mutex type in the mutex attributes. + * + * Parameters: + * attr - The mutex attributes in which to set the mutex type. + * type - The mutex type value to set. + * + * Return Value: + * 0, if the mutex type was successfully set in 'attr', or + * EINVAL, if 'attr' is NULL or 'type' unrecognized. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) +{ + if (attr && type >= PTHREAD_MUTEX_NORMAL && type <= PTHREAD_MUTEX_RECURSIVE) + { + attr->type = type; + return OK; + } + return EINVAL; +} + +#endif /* CONFIG_MUTEX_TYPES */ diff --git a/nuttx/lib/queue/Make.defs b/nuttx/lib/queue/Make.defs new file mode 100644 index 0000000000..94e8125e7c --- /dev/null +++ b/nuttx/lib/queue/Make.defs @@ -0,0 +1,40 @@ +############################################################################ +# lib/queue/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +QUEUE_SRCS = sq_addlast.c sq_addfirst.c sq_addafter.c \ + sq_rem.c sq_remlast.c sq_remfirst.c sq_remafter.c + +QUEUE_SRCS += dq_addlast.c dq_addfirst.c dq_addafter.c dq_addbefore.c \ + dq_rem.c dq_remlast.c dq_remfirst.c diff --git a/nuttx/lib/queue/dq_addafter.c b/nuttx/lib/queue/dq_addafter.c new file mode 100644 index 0000000000..e9f0d9a3ec --- /dev/null +++ b/nuttx/lib/queue/dq_addafter.c @@ -0,0 +1,74 @@ +/************************************************************ + * lib/queue/dq_addafter.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +/************************************************************ + * Public Functions + ************************************************************/ + +/************************************************************ + * Name: dq_addafter + * + * Description: + * dq_addafter function adds 'node' after 'qqqq' in the + * 'queue.' + * + ************************************************************/ + +void dq_addafter(FAR dq_entry_t *prev, FAR dq_entry_t *node, + dq_queue_t *queue) +{ + if (!queue->head || prev == queue->tail) + { + dq_addlast(node, queue); + } + else + { + FAR dq_entry_t *next = prev->flink; + node->blink = prev; + node->flink = next; + next->blink = node; + prev->flink = node; + } +} diff --git a/nuttx/lib/queue/dq_addbefore.c b/nuttx/lib/queue/dq_addbefore.c new file mode 100644 index 0000000000..c49dff78b7 --- /dev/null +++ b/nuttx/lib/queue/dq_addbefore.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * lib/queue/dq_addbefore.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dq_addbefore + * + * Description: + * dq_addbefore adds 'node' before 'next' in 'queue' + * + ****************************************************************************/ + +void dq_addbefore(FAR dq_entry_t *next, FAR dq_entry_t *node, + dq_queue_t *queue) +{ + if (!queue->head || next == queue->head) + { + dq_addfirst(node, queue); + } + else + { + FAR dq_entry_t *prev = next->blink; + node->flink = next; + node->blink = prev; + prev->flink = node; + next->blink = node; + } +} diff --git a/nuttx/lib/queue/dq_addfirst.c b/nuttx/lib/queue/dq_addfirst.c new file mode 100644 index 0000000000..27da2c491c --- /dev/null +++ b/nuttx/lib/queue/dq_addfirst.c @@ -0,0 +1,74 @@ +/************************************************************ + * lib/queue/dq_addfirst.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +/************************************************************ + * Public Functions + ************************************************************/ + +/************************************************************ + * Name: dq_addfirst + * + * Description: + * dq_addfirst affs 'node' at the beginning of 'queue' + * + ************************************************************/ + +void dq_addfirst(FAR dq_entry_t *node, dq_queue_t *queue) +{ + node->blink = NULL; + node->flink = queue->head; + + if (!queue->head) + { + queue->head = node; + queue->tail = node; + } + else + { + queue->head->blink = node; + queue->head = node; + } +} + diff --git a/nuttx/lib/queue/dq_addlast.c b/nuttx/lib/queue/dq_addlast.c new file mode 100644 index 0000000000..c7a0609612 --- /dev/null +++ b/nuttx/lib/queue/dq_addlast.c @@ -0,0 +1,74 @@ +/************************************************************ + * lib/queue/dq_addlast.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +/************************************************************ + * Public Functions + ************************************************************/ + +/************************************************************ + * Name: dq_addlast + * + * Description + * dq_addlast adds 'node' to the end of 'queue' + * + ************************************************************/ + +void dq_addlast(FAR dq_entry_t *node, dq_queue_t *queue) +{ + node->flink = NULL; + node->blink = queue->tail; + + if (!queue->head) + { + queue->head = node; + queue->tail = node; + } + else + { + queue->tail->flink = node; + queue->tail = node; + } +} + diff --git a/nuttx/lib/queue/dq_rem.c b/nuttx/lib/queue/dq_rem.c new file mode 100644 index 0000000000..adf99efed2 --- /dev/null +++ b/nuttx/lib/queue/dq_rem.c @@ -0,0 +1,84 @@ +/************************************************************ + * lib/queue/dq_rem.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +/************************************************************ + * Public Functions + ************************************************************/ + +/************************************************************ + * Name: dq_rem + * + * Descripton: + * dq_rem removes 'node' from 'queue' + * + ************************************************************/ + +void dq_rem(FAR dq_entry_t *node, dq_queue_t *queue) +{ + FAR dq_entry_t *prev = node->blink; + FAR dq_entry_t *next = node->flink; + + if (!prev) + { + queue->head = next; + } + else + { + prev->flink = next; + } + + if (!next) + { + queue->tail = prev; + } + else + { + next->blink = prev; + } + + node->flink = NULL; + node->blink = NULL; +} + diff --git a/nuttx/lib/queue/dq_remfirst.c b/nuttx/lib/queue/dq_remfirst.c new file mode 100644 index 0000000000..c42f3f2cc5 --- /dev/null +++ b/nuttx/lib/queue/dq_remfirst.c @@ -0,0 +1,82 @@ +/************************************************************ + * lib/queue/dq_remfirst.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +/************************************************************ + * Public Functions + ************************************************************/ + +/************************************************************ + * Name: dq_remfirst + * + * Description: + * dq_remfirst removes 'node' from the head of 'queue' + * + ************************************************************/ + +FAR dq_entry_t *dq_remfirst(dq_queue_t *queue) +{ + FAR dq_entry_t *ret = queue->head; + + if (ret) + { + FAR dq_entry_t *next = ret->flink; + if (!next) + { + queue->head = NULL; + queue->tail = NULL; + } + else + { + queue->head = next; + next->blink = NULL; + } + + ret->flink = NULL; + ret->blink = NULL; + } + + return ret; +} + diff --git a/nuttx/lib/queue/dq_remlast.c b/nuttx/lib/queue/dq_remlast.c new file mode 100644 index 0000000000..6280a0e516 --- /dev/null +++ b/nuttx/lib/queue/dq_remlast.c @@ -0,0 +1,78 @@ +/**************************************************************************** + * lib/queue/dq_remlast.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/***************************************************(************************ + * Name: dq_remlast + * + * Description: + * dq_remlast removes the last entry from 'queue' + * + ****************************************************************************/ + +FAR dq_entry_t *dq_remlast(dq_queue_t *queue) +{ + FAR dq_entry_t *ret = queue->tail; + + if (ret) + { + FAR dq_entry_t *prev = ret->blink; + if (!prev) + { + queue->head = NULL; + queue->tail = NULL; + } + else + { + queue->tail = prev; + prev->flink = NULL; + } + + ret->flink = NULL; + ret->blink = NULL; + } + + return ret; +} + diff --git a/nuttx/lib/queue/sq_addafter.c b/nuttx/lib/queue/sq_addafter.c new file mode 100644 index 0000000000..05e1157fd4 --- /dev/null +++ b/nuttx/lib/queue/sq_addafter.c @@ -0,0 +1,71 @@ +/************************************************************ + * lib/queue/sq_addafter.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +/************************************************************ + * Public Functions + ************************************************************/ + +/************************************************************ + * Name: sq_addafter.c + * + * Description: + * The sq_addafter function adds 'node' after 'prev' in the + * 'queue.' + * + ************************************************************/ + +void sq_addafter(FAR sq_entry_t *prev, FAR sq_entry_t *node, + sq_queue_t *queue) +{ + if (!queue->head || prev == queue->tail) + { + sq_addlast(node, queue); + } + else + { + node->flink = prev->flink; + prev->flink = node; + } +} diff --git a/nuttx/lib/queue/sq_addfirst.c b/nuttx/lib/queue/sq_addfirst.c new file mode 100644 index 0000000000..8f55053d41 --- /dev/null +++ b/nuttx/lib/queue/sq_addfirst.c @@ -0,0 +1,67 @@ +/************************************************************ + * lib/queue/sq_addfirst.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +/************************************************************ + * Public Functions + ************************************************************/ + +/************************************************************ + * Name: sq_addfirst + * + * Description: + * The sq_addfirst function places the 'node' at the head + * of the 'queue' + * + ************************************************************/ + +void sq_addfirst(FAR sq_entry_t *node, sq_queue_t *queue) +{ + node->flink = queue->head; + if (!queue->head) + { + queue->tail = node; + } + queue->head = node; +} diff --git a/nuttx/lib/queue/sq_addlast.c b/nuttx/lib/queue/sq_addlast.c new file mode 100644 index 0000000000..15054a7033 --- /dev/null +++ b/nuttx/lib/queue/sq_addlast.c @@ -0,0 +1,72 @@ +/************************************************************ + * lib/queue/sq_addlast.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +/************************************************************ + * Public Functions + ************************************************************/ + +/************************************************************ + * Name: sq_addlast + * + * Description: + * The sq_addlast function places the 'node' at the tail of + * the 'queue' + ************************************************************/ + +void sq_addlast(FAR sq_entry_t *node, sq_queue_t *queue) +{ + node->flink = NULL; + if (!queue->head) + { + queue->head = node; + queue->tail = node; + } + else + { + queue->tail->flink = node; + queue->tail = node; + } +} + diff --git a/nuttx/lib/queue/sq_rem.c b/nuttx/lib/queue/sq_rem.c new file mode 100644 index 0000000000..972e8e1c32 --- /dev/null +++ b/nuttx/lib/queue/sq_rem.c @@ -0,0 +1,83 @@ +/************************************************************ + * lib/queue/sq_rem.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +/************************************************************ + * public Functions + ************************************************************/ + +/************************************************************ + * Name: sq_rem + * + * Description: + * sq_rem removes a 'node' for 'queue.' + * + ************************************************************/ + +void sq_rem(FAR sq_entry_t *node, sq_queue_t *queue) +{ + if (queue->head && node) + { + if (node == queue->head) + { + queue->head = node->flink; + if (node == queue->tail) + { + queue->tail = NULL; + } + } + else + { + FAR sq_entry_t *prev; + for(prev = (FAR sq_entry_t*)queue->head; + prev && prev->flink != node; + prev = prev->flink); + + if (prev) + { + sq_remafter(prev, queue); + } + } + } +} diff --git a/nuttx/lib/queue/sq_remafter.c b/nuttx/lib/queue/sq_remafter.c new file mode 100644 index 0000000000..781a2b6ad2 --- /dev/null +++ b/nuttx/lib/queue/sq_remafter.c @@ -0,0 +1,79 @@ +/************************************************************ + * lib/queue/sq_remafter.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +/************************************************************ + * Public Functions + ************************************************************/ + +/************************************************************ + * Name: + * + * Description: + * sq_remafter removes the entry following 'node; from the + * 'queue' Returns a reference to the removed entry. + * + ************************************************************/ + +FAR sq_entry_t *sq_remafter(FAR sq_entry_t *node, sq_queue_t *queue) +{ + FAR sq_entry_t *ret = node->flink; + if (queue->head && ret) + { + if (queue->tail == ret) + { + queue->tail = node; + node->flink = NULL; + } + else + { + node->flink = ret->flink; + } + + ret->flink = NULL; + } + + return ret; +} + diff --git a/nuttx/lib/queue/sq_remfirst.c b/nuttx/lib/queue/sq_remfirst.c new file mode 100644 index 0000000000..5a273ad6af --- /dev/null +++ b/nuttx/lib/queue/sq_remfirst.c @@ -0,0 +1,76 @@ +/************************************************************ + * lib/queue/sq_remfirst.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +/************************************************************ + * Public Functions + ************************************************************/ + +/************************************************************ + * Name: sq_remfirst + * + * Description: + * sq_remfirst function removes the first entry from + * 'queue' + * + ************************************************************/ + +FAR sq_entry_t *sq_remfirst(sq_queue_t *queue) +{ + FAR sq_entry_t *ret = queue->head; + + if (ret) + { + queue->head = ret->flink; + if (!queue->head) + { + queue->tail = NULL; + } + + ret->flink = NULL; + } + + return ret; +} + diff --git a/nuttx/lib/queue/sq_remlast.c b/nuttx/lib/queue/sq_remlast.c new file mode 100644 index 0000000000..a66c6bcbb7 --- /dev/null +++ b/nuttx/lib/queue/sq_remlast.c @@ -0,0 +1,87 @@ +/************************************************************ + * lib/queue/sq_remlast.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include + +/************************************************************ + * Public Functions + ************************************************************/ + +/************************************************************ + * Name: sq_remlast + * + * Description: + * Removes the last entry in a singly-linked queue. + * + ************************************************************/ + +FAR sq_entry_t *sq_remlast(sq_queue_t *queue) +{ + FAR sq_entry_t *ret = queue->tail; + + if (ret) + { + if (queue->head == queue->tail) + { + queue->head = NULL; + queue->tail = NULL; + } + else + { + FAR sq_entry_t *prev; + for(prev = queue->head; + prev && prev->flink != ret; + prev = prev->flink); + + if (prev) + { + prev->flink = NULL; + queue->tail = prev; + } + } + + ret->flink = NULL; + } + + return ret; +} diff --git a/nuttx/lib/sched/Make.defs b/nuttx/lib/sched/Make.defs new file mode 100644 index 0000000000..939cb983fa --- /dev/null +++ b/nuttx/lib/sched/Make.defs @@ -0,0 +1,38 @@ +############################################################################ +# lib/sched/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +SCHED_SRCS = sched_getprioritymax.c sched_getprioritymin.c + + diff --git a/nuttx/lib/sched/sched_getprioritymax.c b/nuttx/lib/sched/sched_getprioritymax.c new file mode 100644 index 0000000000..8be45d7100 --- /dev/null +++ b/nuttx/lib/sched/sched_getprioritymax.c @@ -0,0 +1,100 @@ +/************************************************************************ + * lib/sched/sched_getprioritymax.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: ched_get_priority_max + * + * Description: + * This function returns the value of the highest possible + * task priority for a specified scheduling policy. + * + * Inputs: + * policy - Scheduling policy requested. + * + * Return Value: + * The maximum priority value or -1 (ERROR) + * (errno is not set) + * + * Assumptions: + * + ************************************************************************/ + +int sched_get_priority_max(int policy) +{ + if (policy != SCHED_FIFO && policy != SCHED_RR) + { + return ERROR; + } + else + { + return SCHED_PRIORITY_MAX; + } +} diff --git a/nuttx/lib/sched/sched_getprioritymin.c b/nuttx/lib/sched/sched_getprioritymin.c new file mode 100644 index 0000000000..a590f1fc2e --- /dev/null +++ b/nuttx/lib/sched/sched_getprioritymin.c @@ -0,0 +1,100 @@ +/************************************************************************ + * lib/sched/sched_getprioritymin.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_get_priority_min + * + * Description: + * This function returns the value of the lowest possible + * task priority for a specified scheduling policy. + * + * Inputs: + * policy - Scheduling policy requested. + * + * Return Value: + * The minimum priority value or -1 (ERROR) + * (errno is not set) + * + * Assumptions: + * + ************************************************************************/ + +int sched_get_priority_min(int policy) +{ + if (policy != SCHED_FIFO && policy != SCHED_RR) + { + return ERROR; + } + else + { + return SCHED_PRIORITY_MIN; + } +} diff --git a/nuttx/lib/semaphore/Make.defs b/nuttx/lib/semaphore/Make.defs new file mode 100644 index 0000000000..996d320fea --- /dev/null +++ b/nuttx/lib/semaphore/Make.defs @@ -0,0 +1,36 @@ +############################################################################ +# lib/semaphore/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +SEM_SRCS = sem_init.c sem_getvalue.c diff --git a/nuttx/lib/semaphore/sem_getvalue.c b/nuttx/lib/semaphore/sem_getvalue.c new file mode 100644 index 0000000000..137eb90010 --- /dev/null +++ b/nuttx/lib/semaphore/sem_getvalue.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * lib/semaphore/sem_getvalue.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: sem_getvalue + * + * Description: + * This function updates the location referenced by 'sval' argument to + * have the value of the semaphore referenced by 'sem' without effecting + * the state of the semaphore. The updated value represents the actual + * semaphore value that occurred at some unspecified time during the call, + * but may not reflect the actual value of the semaphore when it is + * returned to the calling task. + * + * If 'sem' is locked, the value return by sem_getvalue() will either be + * zero or a negative number whose absolute value represents the number + * of tasks waiting for the semaphore. + * + * Parameters: + * sem - Semaphore descriptor + * sval - Buffer by which the value is returned + * + * Return Value: + * 0 (OK), or -1 (ERROR) if unsuccessful + * + * Assumptions: + * + ****************************************************************************/ + +int sem_getvalue(FAR sem_t *sem, FAR int *sval) +{ + if (sem && sval) + { + *sval = sem->semcount; + return OK; + } + else + { + set_errno(EINVAL); + return ERROR; + } +} diff --git a/nuttx/lib/semaphore/sem_init.c b/nuttx/lib/semaphore/sem_init.c new file mode 100644 index 0000000000..ea1c6e84ea --- /dev/null +++ b/nuttx/lib/semaphore/sem_init.c @@ -0,0 +1,124 @@ +/**************************************************************************** + * lib/sem/sem_init.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: sem_init + * + * Description: + * This function initializes the UNAMED semaphore sem. Following a + * successful call to sem_init(), the semaophore may be used in subsequent + * calls to sem_wait(), sem_post(), and sem_trywait(). The semaphore + * remains usable until it is destroyed. + * + * Only sem itself may be used for performing synchronization. The result + * of referring to copies of sem in calls to sem_wait(), sem_trywait(), + * sem_post(), and sem_destroy() is undefined. + * + * Parameters: + * sem - Semaphore to be initialized + * pshared - Process sharing (not used) + * value - Semaphore initialization value + * + * Return Value: + * 0 (OK), or -1 (ERROR) if unsuccessful. + * + * Assumptions: + * + ****************************************************************************/ + +int sem_init(FAR sem_t *sem, int pshared, unsigned int value) +{ + /* Verify that a semaphore was provided and the count is within the valid + * range. + */ + + if (sem && value <= SEM_VALUE_MAX) + { + /* Initialize the seamphore count */ + + sem->semcount = (int16_t)value; + + /* Initialize to support priority inheritance */ + +#ifdef CONFIG_PRIORITY_INHERITANCE +# if CONFIG_SEM_PREALLOCHOLDERS > 0 + sem->hlist.flink = NULL; +# endif + sem->hlist.holder = NULL; + sem->hlist.counts = 0; +#endif + return OK; + } + else + { + set_errno(EINVAL); + return ERROR; + } +} diff --git a/nuttx/lib/signal/Make.defs b/nuttx/lib/signal/Make.defs new file mode 100644 index 0000000000..0c66efa73f --- /dev/null +++ b/nuttx/lib/signal/Make.defs @@ -0,0 +1,40 @@ +############################################################################ +# lib/signal/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +SIG_SRCS = sig_emptyset.c sig_fillset.c sig_addset.c sig_delset.c sig_ismember.c +endif + + diff --git a/nuttx/lib/signal/sig_addset.c b/nuttx/lib/signal/sig_addset.c new file mode 100644 index 0000000000..af9463aac8 --- /dev/null +++ b/nuttx/lib/signal/sig_addset.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * lib/signal/sig_addset.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: sigaddset + * + * Description: + * This function adds the signal specified by signo to the signal set + * specified by set. + * + * Parameters: + * set - Signal set to add signal to + * signo - Signal to add + * + * Return Value: + * 0 (OK), or -1 (ERROR) if the signal number is invalid. + * + * Assumptions: + * + ****************************************************************************/ + +int sigaddset(FAR sigset_t *set, int signo) +{ + int ret = ERROR; + + /* Verify the signal */ + + if (GOOD_SIGNO(signo)) + { + /* Add the signal to the set */ + + *set |= SIGNO2SET(signo); + ret = OK; + } + + return ret; +} + diff --git a/nuttx/lib/signal/sig_delset.c b/nuttx/lib/signal/sig_delset.c new file mode 100644 index 0000000000..489c59afac --- /dev/null +++ b/nuttx/lib/signal/sig_delset.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * lib/signal/sig_delset.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: sigdelset + * + * Description: + * This function deletes the signal specified by signo from the signal + * set specified by the 'set' argument. + * + * Parameters: + * set - Signal set to delete the signal from + * signo - Signal to delete + * + * Return Value: + * 0 (OK), or -1 (ERROR) if the signal number is invalid. + * + * Assumptions: + * + ****************************************************************************/ + +int sigdelset(FAR sigset_t *set, int signo) +{ + int ret = ERROR; + + /* Verify the signal */ + + if (GOOD_SIGNO(signo)) + { + /* Delete the signal to the set */ + + *set &= ~SIGNO2SET(signo); + ret = OK; + } + + return ret; +} + diff --git a/nuttx/lib/signal/sig_emptyset.c b/nuttx/lib/signal/sig_emptyset.c new file mode 100644 index 0000000000..bfee588323 --- /dev/null +++ b/nuttx/lib/signal/sig_emptyset.c @@ -0,0 +1,88 @@ +/**************************************************************************** + * lib/signal/sig_emptyset.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: sigemptyset + * + * Description: + * This function initializes the signal set specified by set such that all + * signals are excluded. + * + * Parameters: + * set - Signal set to initalize + * + * Return Value: + * 0 (OK), or -1 (ERROR) if the signal set cannot be initialized. + * + * Assumptions: + * + ****************************************************************************/ + +int sigemptyset(FAR sigset_t *set) +{ + *set = NULL_SIGNAL_SET; + return OK; +} + diff --git a/nuttx/lib/signal/sig_fillset.c b/nuttx/lib/signal/sig_fillset.c new file mode 100644 index 0000000000..c660da0ad8 --- /dev/null +++ b/nuttx/lib/signal/sig_fillset.c @@ -0,0 +1,88 @@ +/**************************************************************************** + * lib/signal/sig_fillset.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Publics Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: sigfillset + * + * Description: + * This function initializes the signal set specified by set such that all + * signals are included. + * + * Parameters: + * set - Signal set to initalize + * + * Return Value: + * 0 (OK), or -1 (ERROR) if the signal set cannot be initialized. + * + * Assumptions: + * + ****************************************************************************/ + +int sigfillset(FAR sigset_t *set) +{ + *set = ALL_SIGNAL_SET; + return OK; +} + diff --git a/nuttx/lib/signal/sig_ismember.c b/nuttx/lib/signal/sig_ismember.c new file mode 100644 index 0000000000..88dc8d819b --- /dev/null +++ b/nuttx/lib/signal/sig_ismember.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * lib/signal/sig_ismember.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: sigismember + * + * Description: + * This function tests whether the signal specified by signo is a member + * of the set specified by set. + * + * Parameters: + * set - Signal set to test + * signo - Signal to test for + * + * Return Value: + * 1 (true), if the specified signal is a member of the set, + * 0 (OK or FALSE), if it is not, or + * -1 (ERROR) if the signal number is invalid. + * + * Assumptions: + * + ****************************************************************************/ + +int sigismember(FAR const sigset_t *set, int signo) +{ + int ret = ERROR; + + /* Verify the signal */ + + if (GOOD_SIGNO(signo)) + { + /* Check if the signal is in the set */ + + ret = ((*set & SIGNO2SET(signo)) != 0); + } + + return ret; +} + diff --git a/nuttx/lib/stdio/Make.defs b/nuttx/lib/stdio/Make.defs new file mode 100644 index 0000000000..ddccaca719 --- /dev/null +++ b/nuttx/lib/stdio/Make.defs @@ -0,0 +1,65 @@ +############################################################################ +# lib/stdio/Make.defs +# +# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +STDIO_SRCS = lib_fileno.c lib_printf.c lib_rawprintf.c lib_lowprintf.c \ + lib_sprintf.c lib_asprintf.c lib_snprintf.c lib_libsprintf.c \ + lib_vsprintf.c lib_avsprintf.c lib_vsnprintf.c lib_libvsprintf.c \ + lib_meminstream.c lib_memoutstream.c lib_lowinstream.c \ + lib_lowoutstream.c lib_zeroinstream.c lib_nullinstream.c \ + lib_nulloutstream.c lib_sscanf.c + +ifneq ($(CONFIG_NFILE_DESCRIPTORS),0) +STDIO_SRCS += lib_rawinstream.c lib_rawoutstream.c +ifneq ($(CONFIG_NFILE_STREAMS),0) +STDIO_SRCS += lib_fopen.c lib_fclose.c lib_fread.c lib_libfread.c lib_fseek.c \ + lib_ftell.c lib_fsetpos.c lib_fgetpos.c lib_fgetc.c lib_fgets.c \ + lib_gets.c lib_fwrite.c lib_libfwrite.c lib_fflush.c \ + lib_libflushall.c lib_libfflush.c lib_rdflush.c lib_wrflush.c \ + lib_fputc.c lib_puts.c lib_fputs.c lib_ungetc.c lib_vprintf.c \ + lib_fprintf.c lib_vfprintf.c lib_stdinstream.c lib_stdoutstream.c +endif +endif + +ifeq ($(CONFIG_SYSLOG),y) +STDIO_SRCS += lib_syslogstream.c +endif + +ifeq ($(CONFIG_LIBC_FLOATINGPOINT),y) +STDIO_SRCS += lib_dtoa.c +endif + +ifeq ($(CONFIG_STDIO_LINEBUFFER),y) +STDIO_SRCS += lib_libnoflush.c +endif diff --git a/nuttx/lib/stdio/lib_asprintf.c b/nuttx/lib/stdio/lib_asprintf.c new file mode 100644 index 0000000000..84aaafa462 --- /dev/null +++ b/nuttx/lib/stdio/lib_asprintf.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * lib/stdio/lib_asprintf.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: asprintf + * + * Description: + * This function is similar to sprintf, except that it dynamically + * allocates a string (as with malloc) to hold the output, instead of + * putting the output in a buffer you allocate in advance. The ptr + * argument should be the address of a char * object, and a successful + * call to asprintf stores a pointer to the newly allocated string at that + * location. + * + * Returned Value: + * The returned value is the number of characters allocated for the buffer, + * or less than zero if an error occurred. Usually this means that the buffer + * could not be allocated. + * + ****************************************************************************/ + +int asprintf (FAR char **ptr, const char *fmt, ...) +{ + va_list ap; + int ret; + + /* Let avsprintf do all of the work */ + + va_start(ap, fmt); + ret = avsprintf(ptr, fmt, ap); + va_end(ap); + + return ret; +} diff --git a/nuttx/lib/stdio/lib_avsprintf.c b/nuttx/lib/stdio/lib_avsprintf.c new file mode 100644 index 0000000000..8561b97c21 --- /dev/null +++ b/nuttx/lib/stdio/lib_avsprintf.c @@ -0,0 +1,146 @@ +/**************************************************************************** + * lib/stdio/lib_avsprintf.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: avsprintf + * + * Description: + * This function is similar to vsprintf, except that it dynamically + * allocates a string (as with malloc) to hold the output, instead of + * putting the output in a buffer you allocate in advance. The ptr + * argument should be the address of a char * object, and a successful + * call to avsprintf stores a pointer to the newly allocated string at that + * location. + * + * Returned Value: + * The returned value is the number of characters allocated for the buffer, + * or less than zero if an error occurred. Usually this means that the buffer + * could not be allocated. + * + ****************************************************************************/ + +int avsprintf(FAR char **ptr, const char *fmt, va_list ap) +{ + struct lib_outstream_s nulloutstream; + struct lib_memoutstream_s memoutstream; + FAR char *buf; + int nbytes; + + DEBUGASSERT(ptr && fmt); + + /* First, use a nullstream to get the size of the buffer. The number + * of bytes returned may or may not include the null terminator. + */ + + lib_nulloutstream(&nulloutstream); + nbytes = lib_vsprintf((FAR struct lib_outstream_s *)&nulloutstream, fmt, ap); + + /* Then allocate a buffer to hold that number of characters, adding one + * for the null terminator. + */ + + buf = (FAR char *)malloc(nulloutstream.nput + 1); + if (!buf) + { + return ERROR; + } + + /* Initialize a memory stream to write into the allocated buffer. The + * memory stream will reserve one byte at the end of the buffer for the + * null terminator and will not report this in the number of output bytes. + */ + + lib_memoutstream((FAR struct lib_memoutstream_s *)&memoutstream, + buf, nulloutstream.nput + 1); + + /* Then let lib_vsprintf do it's real thing */ + + nbytes = lib_vsprintf((FAR struct lib_outstream_s *)&memoutstream.public, fmt, ap); + + /* Return a pointer to the string to the caller. NOTE: the memstream put() + * method has already added the NUL terminator to the end of the string (not + * included in the nput count). + * + * Hmmm.. looks like the memory would be stranded if lib_vsprintf() returned + * an error. Does that ever happen? + */ + + DEBUGASSERT(nbytes < 0 || nbytes == nulloutstream.nput); + *ptr = buf; + return nbytes; +} diff --git a/nuttx/lib/stdio/lib_dtoa.c b/nuttx/lib/stdio/lib_dtoa.c new file mode 100644 index 0000000000..894af4f424 --- /dev/null +++ b/nuttx/lib/stdio/lib_dtoa.c @@ -0,0 +1,1537 @@ +/**************************************************************************** + * lib/stdio/lib_dtoa.c + * + * This file was ported to NuttX by Yolande Cates. + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef Unsigned_Shifts +# define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000; +#else +# define Sign_Extend(a,b) /* no-op */ +#endif + +#ifdef CONFIG_ENDIAN_BIG +# define word0(x) ((uint32_t *)&x)[0] +# define word1(x) ((uint32_t *)&x)[1] +#else +# define word0(x) ((uint32_t *)&x)[1] +# define word1(x) ((uint32_t *)&x)[0] +#endif + +#ifdef CONFIG_ENDIAN_BIG +# define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ + ((unsigned short *)a)[1] = (unsigned short)c, a++) +#else +# define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ + ((unsigned short *)a)[0] = (unsigned short)c, a++) +#endif + +#define Exp_shift 20 +#define Exp_shift1 20 +#define Exp_msk1 0x100000 +#define Exp_msk11 0x100000 +#define Exp_mask 0x7ff00000 +#define P 53 +#define Bias 1023 +#define IEEE_Arith +#define Emin (-1022) +#define Exp_1 0x3ff00000 +#define Exp_11 0x3ff00000 +#define Ebits 11 +#define Frac_mask 0xfffff +#define Frac_mask1 0xfffff +#define Ten_pmax 22 +#define Bletch 0x10 +#define Bndry_mask 0xfffff +#define Bndry_mask1 0xfffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 1 +#define Tiny0 0 +#define Tiny1 1 +#define Quick_max 14 +#define Int_max 14 +#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */ + +#define Kmax 15 + +#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ + y->wds*sizeof(long) + 2*sizeof(int)) + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +struct Bigint +{ + struct Bigint *next; + int k, maxwds, sign, wds; + unsigned long x[1]; +}; + +typedef struct Bigint Bigint; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static Bigint *freelist[Kmax + 1]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static Bigint *Balloc(int k) +{ + int x; + Bigint *rv; + + if ((rv = freelist[k])) + { + freelist[k] = rv->next; + } + else + { + x = 1 << k; + rv = (Bigint *)lib_malloc(sizeof(Bigint) + (x - 1) * sizeof(long)); + rv->k = k; + rv->maxwds = x; + } + rv->sign = rv->wds = 0; + return rv; +} + +static void Bfree(Bigint * v) +{ + if (v) + { + v->next = freelist[v->k]; + freelist[v->k] = v; + } +} + +/* multiply by m and add a */ + +static Bigint *multadd(Bigint * b, int m, int a) +{ + int i, wds; + unsigned long *x, y; +#ifdef Pack_32 + unsigned long xi, z; +#endif + Bigint *b1; + + wds = b->wds; + x = b->x; + i = 0; + do + { +#ifdef Pack_32 + xi = *x; + y = (xi & 0xffff) * m + a; + z = (xi >> 16) * m + (y >> 16); + a = (int)(z >> 16); + *x++ = (z << 16) + (y & 0xffff); +#else + y = *x * m + a; + a = (int)(y >> 16); + *x++ = y & 0xffff; +#endif + } + while (++i < wds); + if (a) + { + if (wds >= b->maxwds) + { + b1 = Balloc(b->k + 1); + Bcopy(b1, b); + Bfree(b); + b = b1; + } + b->x[wds++] = a; + b->wds = wds; + } + return b; +} + +static int hi0bits(unsigned long x) +{ + int k = 0; + + if (!(x & 0xffff0000)) + { + k = 16; + x <<= 16; + } + + if (!(x & 0xff000000)) + { + k += 8; + x <<= 8; + } + + if (!(x & 0xf0000000)) + { + k += 4; + x <<= 4; + } + + if (!(x & 0xc0000000)) + { + k += 2; + x <<= 2; + } + + if (!(x & 0x80000000)) + { + k++; + if (!(x & 0x40000000)) + { + return 32; + } + } + return k; +} + +static int lo0bits(unsigned long *y) +{ + int k; + unsigned long x = *y; + + if (x & 7) + { + if (x & 1) + { + return 0; + } + if (x & 2) + { + *y = x >> 1; + return 1; + } + *y = x >> 2; + return 2; + } + + k = 0; + if (!(x & 0xffff)) + { + k = 16; + x >>= 16; + } + + if (!(x & 0xff)) + { + k += 8; + x >>= 8; + } + + if (!(x & 0xf)) + { + k += 4; + x >>= 4; + } + + if (!(x & 0x3)) + { + k += 2; + x >>= 2; + } + + if (!(x & 1)) + { + k++; + x >>= 1; + if (!x & 1) + { + return 32; + } + } + *y = x; + return k; +} + +static Bigint *i2b(int i) +{ + Bigint *b; + + b = Balloc(1); + b->x[0] = i; + b->wds = 1; + return b; +} + +static Bigint *mult(Bigint * a, Bigint * b) +{ + Bigint *c; + int k, wa, wb, wc; + unsigned long carry, y, z; + unsigned long *x, *xa, *xae, *xb, *xbe, *xc, *xc0; +#ifdef Pack_32 + uint32_t z2; +#endif + + if (a->wds < b->wds) + { + c = a; + a = b; + b = c; + } + + k = a->k; + wa = a->wds; + wb = b->wds; + wc = wa + wb; + if (wc > a->maxwds) + { + k++; + } + c = Balloc(k); + for (x = c->x, xa = x + wc; x < xa; x++) + { + *x = 0; + } + xa = a->x; + xae = xa + wa; + xb = b->x; + xbe = xb + wb; + xc0 = c->x; +#ifdef Pack_32 + for (; xb < xbe; xb++, xc0++) + { + if ((y = *xb & 0xffff)) + { + x = xa; + xc = xc0; + carry = 0; + do + { + z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; + carry = z >> 16; + z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; + carry = z2 >> 16; + Storeinc(xc, z2, z); + } + while (x < xae); + *xc = carry; + } + if ((y = *xb >> 16)) + { + x = xa; + xc = xc0; + carry = 0; + z2 = *xc; + do + { + z = (*x & 0xffff) * y + (*xc >> 16) + carry; + carry = z >> 16; + Storeinc(xc, z, z2); + z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; + carry = z2 >> 16; + } + while (x < xae); + *xc = z2; + } + } +#else + for (; xb < xbe; xc0++) + { + if ((y = *xb++)) + { + x = xa; + xc = xc0; + carry = 0; + do + { + z = *x++ * y + *xc + carry; + carry = z >> 16; + *xc++ = z & 0xffff; + } + while (x < xae); + *xc = carry; + } + } +#endif + for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc); + c->wds = wc; + return c; +} + +static Bigint *p5s; + +static Bigint *pow5mult(Bigint * b, int k) +{ + Bigint *b1, *p5, *p51; + int i; + static int p05[3] = { 5, 25, 125 }; + + if ((i = k & 3)) + b = multadd(b, p05[i - 1], 0); + + if (!(k >>= 2)) + { + return b; + } + + if (!(p5 = p5s)) + { + /* first time */ + p5 = p5s = i2b(625); + p5->next = 0; + } + + for (;;) + { + if (k & 1) + { + b1 = mult(b, p5); + Bfree(b); + b = b1; + } + if (!(k >>= 1)) + { + break; + } + + if (!(p51 = p5->next)) + { + p51 = p5->next = mult(p5, p5); + p51->next = 0; + } + p5 = p51; + } + return b; +} + +static Bigint *lshift(Bigint * b, int k) +{ + int i, k1, n, n1; + Bigint *b1; + unsigned long *x, *x1, *xe, z; + +#ifdef Pack_32 + n = k >> 5; +#else + n = k >> 4; +#endif + k1 = b->k; + n1 = n + b->wds + 1; + for (i = b->maxwds; n1 > i; i <<= 1) + { + k1++; + } + b1 = Balloc(k1); + x1 = b1->x; + for (i = 0; i < n; i++) + { + *x1++ = 0; + } + x = b->x; + xe = x + b->wds; +#ifdef Pack_32 + if (k &= 0x1f) + { + k1 = 32 - k; + z = 0; + do + { + *x1++ = *x << k | z; + z = *x++ >> k1; + } + while (x < xe); + if ((*x1 = z)) + { + ++n1; + } + } +#else + if (k &= 0xf) + { + k1 = 16 - k; + z = 0; + do + { + *x1++ = ((*x << k) & 0xffff) | z; + z = *x++ >> k1; + } + while (x < xe); + if ((*x1 = z)) + { + ++n1; + } + } +#endif + else + do + { + *x1++ = *x++; + } + while (x < xe); + b1->wds = n1 - 1; + Bfree(b); + return b1; +} + +static int cmp(Bigint * a, Bigint * b) +{ + unsigned long *xa, *xa0, *xb, *xb0; + int i, j; + + i = a->wds; + j = b->wds; +#ifdef CONFIG_DEBUG_LIB + if (i > 1 && !a->x[i - 1]) + { + ldbg("cmp called with a->x[a->wds-1] == 0\n"); + } + if (j > 1 && !b->x[j - 1]) + { + ldbg("cmp called with b->x[b->wds-1] == 0\n"); + } +#endif + if (i -= j) + return i; + xa0 = a->x; + xa = xa0 + j; + xb0 = b->x; + xb = xb0 + j; + for (;;) + { + if (*--xa != *--xb) + return *xa < *xb ? -1 : 1; + if (xa <= xa0) + break; + } + return 0; +} + +static Bigint *diff(Bigint * a, Bigint * b) +{ + Bigint *c; + int i, wa, wb; + long borrow, y; /* We need signed shifts here. */ + unsigned long *xa, *xae, *xb, *xbe, *xc; +#ifdef Pack_32 + int32_t z; +#endif + + i = cmp(a, b); + if (!i) + { + c = Balloc(0); + c->wds = 1; + c->x[0] = 0; + return c; + } + if (i < 0) + { + c = a; + a = b; + b = c; + i = 1; + } + else + i = 0; + c = Balloc(a->k); + c->sign = i; + wa = a->wds; + xa = a->x; + xae = xa + wa; + wb = b->wds; + xb = b->x; + xbe = xb + wb; + xc = c->x; + borrow = 0; +#ifdef Pack_32 + do + { + y = (*xa & 0xffff) - (*xb & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*xa++ >> 16) - (*xb++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(xc, z, y); + } + while (xb < xbe); + while (xa < xae) + { + y = (*xa & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*xa++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(xc, z, y); + } +#else + do + { + y = *xa++ - *xb++ + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *xc++ = y & 0xffff; + } + while (xb < xbe); + while (xa < xae) + { + y = *xa++ + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *xc++ = y & 0xffff; + } +#endif + while (!*--xc) + wa--; + c->wds = wa; + return c; +} + +static Bigint *d2b(double d, int *e, int *bits) +{ + Bigint *b; + int de, i, k; + unsigned long *x, y, z; + +#ifdef Pack_32 + b = Balloc(1); +#else + b = Balloc(2); +#endif + x = b->x; + + z = word0(d) & Frac_mask; + word0(d) &= 0x7fffffff; /* clear sign bit, which we ignore */ + if ((de = (int)(word0(d) >> Exp_shift))) + z |= Exp_msk1; +#ifdef Pack_32 + if ((y = word1(d))) + { + if ((k = lo0bits(&y))) + { + x[0] = y | z << (32 - k); + z >>= k; + } + else + x[0] = y; + i = b->wds = (x[1] = z) ? 2 : 1; + } + else + { +#ifdef CONFIG_DEBUG_LIB + if (!z) + { + ldbg("Zero passed to d2b\n"); + } +#endif + k = lo0bits(&z); + x[0] = z; + i = b->wds = 1; + k += 32; + } +#else + if ((y = word1(d))) + { + if ((k = lo0bits(&y))) + if (k >= 16) + { + x[0] = y | ((z << (32 - k)) & 0xffff); + x[1] = z >> (k - 16) & 0xffff; + x[2] = z >> k; + i = 2; + } + else + { + x[0] = y & 0xffff; + x[1] = (y >> 16) | ((z << (16 - k)) & 0xffff); + x[2] = z >> k & 0xffff; + x[3] = z >> (k + 16); + i = 3; + } + else + { + x[0] = y & 0xffff; + x[1] = y >> 16; + x[2] = z & 0xffff; + x[3] = z >> 16; + i = 3; + } + } + else + { +#ifdef CONFIG_DEBUG_LIB + if (!z) + { + ldbg("Zero passed to d2b\n"); + } +#endif + k = lo0bits(&z); + if (k >= 16) + { + x[0] = z; + i = 0; + } + else + { + x[0] = z & 0xffff; + x[1] = z >> 16; + i = 1; + } + k += 32; + } + while (!x[i]) + --i; + b->wds = i + 1; +#endif + if (de) + { + *e = de - Bias - (P - 1) + k; + *bits = P - k; + } + else + { + *e = de - Bias - (P - 1) + 1 + k; +#ifdef Pack_32 + *bits = 32 * i - hi0bits(x[i - 1]); +#else + *bits = (i + 2) * 16 - hi0bits(x[i]); +#endif + } + return b; +} + +static const double tens[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22 +}; + +#ifdef IEEE_Arith +static const double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; +static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 }; + +# define n_bigtens 5 +#else +static const double bigtens[] = { 1e16, 1e32 }; +static const double tinytens[] = { 1e-16, 1e-32 }; + +# define n_bigtens 2 +#endif + +static int quorem(Bigint * b, Bigint * S) +{ + int n; + long borrow, y; + unsigned long carry, q, ys; + unsigned long *bx, *bxe, *sx, *sxe; +#ifdef Pack_32 + int32_t z; + uint32_t si, zs; +#endif + + n = S->wds; +#ifdef CONFIG_DEBUG_LIB + if (b->wds > n) + { + ldbg("oversize b in quorem\n"); + } +#endif + if (b->wds < n) + { + return 0; + } + sx = S->x; + sxe = sx + --n; + bx = b->x; + bxe = bx + n; + q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ +#ifdef CONFIG_DEBUG_LIB + if (q > 9) + { + ldbg("oversized quotient in quorem\n"); + } +#endif + if (q) + { + borrow = 0; + carry = 0; + do + { +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) * q + carry; + zs = (si >> 16) * q + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*bx >> 16) - (zs & 0xffff) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(bx, z, y); +#else + ys = *sx++ * q + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *bx++ = y & 0xffff; +#endif + } + while (sx <= sxe); + if (!*bxe) + { + bx = b->x; + while (--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + if (cmp(b, S) >= 0) + { + q++; + borrow = 0; + carry = 0; + bx = b->x; + sx = S->x; + do + { +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) + carry; + zs = (si >> 16) + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*bx >> 16) - (zs & 0xffff) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(bx, z, y); +#else + ys = *sx++ + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *bx++ = y & 0xffff; +#endif + } + while (sx <= sxe); + bx = b->x; + bxe = bx + n; + if (!*bxe) + { + while (--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + return q; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. + * + * Inspired by "How to Print Floating-Point Numbers Accurately" by + * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * 1. Rather than iterating, we use a simple numeric overestimate + * to determine k = floor(log10(d)). We scale relevant + * quantities using O(log2(k)) rather than O(k) multiplications. + * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't + * try to generate digits strictly left to right. Instead, we + * compute with fewer bits and propagate the carry if necessary + * when rounding the final digit up. This is often faster. + * 3. Under the assumption that input will be rounded nearest, + * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. + * That is, we allow equality in stopping tests when the + * round-nearest rule will give the same floating-point value + * as would satisfaction of the stopping test with strict + * inequality. + * 4. We remove common factors of powers of 2 from relevant + * quantities. + * 5. When converting floating-point integers less than 1e16, + * we use floating-point arithmetic rather than resorting + * to multiple-precision integers. + * 6. When asked to produce fewer than 15 digits, we first try + * to get by with floating-point arithmetic; we resort to + * multiple-precision integer arithmetic only if we cannot + * guarantee that the floating-point calculation has given + * the correctly rounded result. For k requested digits and + * "uniformly" distributed input, the probability is + * something like 10^(k-15) that we must resort to the int32_t + * calculation. + */ + +char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) +{ + /* Arguments ndigits, decpt, sign are similar to those of ecvt and fcvt; + * trailing zeros are suppressed from the returned string. If not null, *rve + * is set to point to the end of the return value. If d is +-Infinity or + * NaN, then *decpt is set to 9999. + * + * mode: 0 ==> shortest string that yields d when read in and rounded to + * nearest. 1 ==> like 0, but with Steele & White stopping rule; e.g. with + * IEEE P754 arithmetic , mode 0 gives 1e23 whereas mode 1 gives + * 9.999999999999999e22. 2 ==> max(1,ndigits) significant digits. This gives + * a return value similar to that of ecvt, except that trailing zeros are + * suppressed. 3 ==> through ndigits past the decimal point. This gives a + * return value similar to that from fcvt, except that trailing zeros are + * suppressed, and ndigits can be negative. 4-9 should give the same return + * values as 2-3, i.e., 4 <= mode <= 9 ==> same return as mode 2 + (mode & + * 1). These modes are mainly for debugging; often they run slower but + * sometimes faster than modes 2-3. 4,5,8,9 ==> left-to-right digit + * generation. 6-9 ==> don't try fast floating-point estimate (if + * applicable). + * + * Values of mode other than 0-9 are treated as mode 0. + * + * Sufficient space is allocated to the return value to hold the suppressed + * trailing zeros. */ + + int bbits, b2, b5, be, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0, + j, j_1, k, k0, k_check, leftright, m2, m5, s2, s5, spec_case = 0, try_quick; + long L; + int denorm; + unsigned long x; + Bigint *b, *b1, *delta, *mlo = NULL, *mhi, *S; + double d2, ds, eps; + char *s, *s0; + static Bigint *result; + static int result_k; + + if (result) + { + result->k = result_k; + result->maxwds = 1 << result_k; + Bfree(result); + result = 0; + } + + if (word0(d) & Sign_bit) + { + /* set sign for everything, including 0's and NaNs */ + *sign = 1; + word0(d) &= ~Sign_bit; /* clear sign bit */ + } + else + *sign = 0; + +#if defined(IEEE_Arith) +# ifdef IEEE_Arith + if ((word0(d) & Exp_mask) == Exp_mask) +#else + if (word0(d) == 0x8000) +#endif + { + /* Infinity or NaN */ + *decpt = 9999; + s = +#ifdef IEEE_Arith + !word1(d) && !(word0(d) & 0xfffff) ? "Infinity" : +#endif + "NaN"; + if (rve) + *rve = +#ifdef IEEE_Arith + s[3] ? s + 8 : +#endif + s + 3; + return s; + } +#endif + if (!d) + { + *decpt = 1; + s = "0"; + if (rve) + *rve = s + 1; + return s; + } + + b = d2b(d, &be, &bbits); + if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) + { + d2 = d; + word0(d2) &= Frac_mask1; + word0(d2) |= Exp_11; + + /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 log10(x) = log(x) / log(10) ~=~ + * log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) log10(d) = + * (i-Bias)*log(2)/log(10) + log10(d2) This suggests computing an + * approximation k to log10(d) by k = (i - Bias)*0.301029995663981 + ( + * (d2-1.5)*0.289529654602168 + 0.176091259055681 ); We want k to be too + * large rather than too small. The error in the first-order Taylor + * series approximation is in our favor, so we just round up the constant + * enough to compensate for any error in the multiplication of (i - Bias) + * by 0.301029995663981; since |i - Bias| <= 1077, and 1077 * 0.30103 * + * 2^-52 ~=~ 7.2e-14, adding 1e-13 to the constant term more than + * suffices. Hence we adjust the constant term to 0.1760912590558. (We + * could get a more accurate k by invoking log10, but this is probably + * not worthwhile.) */ + + i -= Bias; + denorm = 0; + } + else + { + /* d is denormalized */ + + i = bbits + be + (Bias + (P - 1) - 1); + x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32) + : word1(d) << (32 - i); + d2 = x; + word0(d2) -= 31 * Exp_msk1; /* adjust exponent */ + i -= (Bias + (P - 1) - 1) + 1; + denorm = 1; + } + ds = (d2 - 1.5) * 0.289529654602168 + 0.1760912590558 + i * 0.301029995663981; + k = (int)ds; + if (ds < 0. && ds != k) + k--; /* want k = floor(ds) */ + k_check = 1; + if (k >= 0 && k <= Ten_pmax) + { + if (d < tens[k]) + k--; + k_check = 0; + } + j = bbits - i - 1; + if (j >= 0) + { + b2 = 0; + s2 = j; + } + else + { + b2 = -j; + s2 = 0; + } + if (k >= 0) + { + b5 = 0; + s5 = k; + s2 += k; + } + else + { + b2 -= k; + b5 = -k; + s5 = 0; + } + if (mode < 0 || mode > 9) + mode = 0; + try_quick = 1; + if (mode > 5) + { + mode -= 4; + try_quick = 0; + } + leftright = 1; + switch (mode) + { + case 0: + case 1: + ilim = ilim1 = -1; + i = 18; + ndigits = 0; + break; + case 2: + leftright = 0; + /* no break */ + case 4: + if (ndigits <= 0) + ndigits = 1; + ilim = ilim1 = i = ndigits; + break; + case 3: + leftright = 0; + /* no break */ + case 5: + i = ndigits + k + 1; + ilim = i; + ilim1 = i - 1; + if (i <= 0) + i = 1; + } + j = sizeof(unsigned long); + for (result_k = 0; (signed)(sizeof(Bigint) - sizeof(unsigned long) + j) <= i; + j <<= 1) + result_k++; + result = Balloc(result_k); + s = s0 = (char *)result; + + if (ilim >= 0 && ilim <= Quick_max && try_quick) + { + + /* Try to get by with floating-point arithmetic. */ + + i = 0; + d2 = d; + k0 = k; + ilim0 = ilim; + ieps = 2; /* conservative */ + if (k > 0) + { + ds = tens[k & 0xf]; + j = k >> 4; + if (j & Bletch) + { + /* prevent overflows */ + j &= Bletch - 1; + d /= bigtens[n_bigtens - 1]; + ieps++; + } + for (; j; j >>= 1, i++) + if (j & 1) + { + ieps++; + ds *= bigtens[i]; + } + d /= ds; + } + else if ((j_1 = -k)) + { + d *= tens[j_1 & 0xf]; + for (j = j_1 >> 4; j; j >>= 1, i++) + if (j & 1) + { + ieps++; + d *= bigtens[i]; + } + } + if (k_check && d < 1. && ilim > 0) + { + if (ilim1 <= 0) + goto fast_failed; + ilim = ilim1; + k--; + d *= 10.; + ieps++; + } + eps = ieps * d + 7.; + word0(eps) -= (P - 1) * Exp_msk1; + if (ilim == 0) + { + S = mhi = 0; + d -= 5.; + if (d > eps) + goto one_digit; + if (d < -eps) + goto no_digits; + goto fast_failed; + } +#ifndef No_leftright + if (leftright) + { + /* Use Steele & White method of only generating digits needed. */ + eps = 0.5 / tens[ilim - 1] - eps; + for (i = 0;;) + { + L = (int)d; + d -= L; + *s++ = '0' + (int)L; + if (d < eps) + goto ret1; + if (1. - d < eps) + goto bump_up; + if (++i >= ilim) + break; + eps *= 10.; + d *= 10.; + } + } + else + { +#endif + /* Generate ilim digits, then fix them up. */ + eps *= tens[ilim - 1]; + for (i = 1;; i++, d *= 10.) + { + L = (int)d; + d -= L; + *s++ = '0' + (int)L; + if (i == ilim) + { + if (d > 0.5 + eps) + goto bump_up; + else if (d < 0.5 - eps) + { + while (*--s == '0'); + s++; + goto ret1; + } + break; + } + } +#ifndef No_leftright + } +#endif + fast_failed: + s = s0; + d = d2; + k = k0; + ilim = ilim0; + } + + /* Do we have a "small" integer? */ + + if (be >= 0 && k <= Int_max) + { + /* Yes. */ + ds = tens[k]; + if (ndigits < 0 && ilim <= 0) + { + S = mhi = 0; + if (ilim < 0 || d <= 5 * ds) + goto no_digits; + goto one_digit; + } + for (i = 1;; i++) + { + L = (int)(d / ds); + d -= L * ds; +#ifdef Check_FLT_ROUNDS + /* If FLT_ROUNDS == 2, L will usually be high by 1 */ + if (d < 0) + { + L--; + d += ds; + } +#endif + *s++ = '0' + (int)L; + if (i == ilim) + { + d += d; + if (d > ds || (d == ds && (L & 1))) + { + bump_up: + while (*--s == '9') + if (s == s0) + { + k++; + *s = '0'; + break; + } + ++*s++; + } + break; + } + if (!(d *= 10.)) + break; + } + goto ret1; + } + + m2 = b2; + m5 = b5; + mhi = mlo = 0; + if (leftright) + { + if (mode < 2) + { + i = denorm ? be + (Bias + (P - 1) - 1 + 1) : 1 + P - bbits; + } + else + { + j = ilim - 1; + if (m5 >= j) + m5 -= j; + else + { + s5 += j -= m5; + b5 += j; + m5 = 0; + } + if ((i = ilim) < 0) + { + m2 -= i; + i = 0; + } + } + b2 += i; + s2 += i; + mhi = i2b(1); + } + if (m2 > 0 && s2 > 0) + { + i = m2 < s2 ? m2 : s2; + b2 -= i; + m2 -= i; + s2 -= i; + } + if (b5 > 0) + { + if (leftright) + { + if (m5 > 0) + { + mhi = pow5mult(mhi, m5); + b1 = mult(mhi, b); + Bfree(b); + b = b1; + } + if ((j = b5 - m5)) + b = pow5mult(b, j); + } + else + b = pow5mult(b, b5); + } + S = i2b(1); + if (s5 > 0) + S = pow5mult(S, s5); + + /* Check for special case that d is a normalized power of 2. */ + + if (mode < 2) + { + if (!word1(d) && !(word0(d) & Bndry_mask) && word0(d) & Exp_mask) + { + /* The special case */ + b2 += Log2P; + s2 += Log2P; + spec_case = 1; + } + else + spec_case = 0; + } + + /* + * Arrange for convenient computation of quotients: shift left if + * necessary so divisor has 4 leading 0 bits. + * + * Perhaps we should just compute leading 28 bits of S once and for all + * and pass them and a shift to quorem, so it can do shifts and ors + * to compute the numerator for q. + */ +#ifdef Pack_32 + if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0x1f)) + i = 32 - i; +#else + if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0xf)) + i = 16 - i; +#endif + if (i > 4) + { + i -= 4; + b2 += i; + m2 += i; + s2 += i; + } + else if (i < 4) + { + i += 28; + b2 += i; + m2 += i; + s2 += i; + } + if (b2 > 0) + b = lshift(b, b2); + if (s2 > 0) + S = lshift(S, s2); + if (k_check) + { + if (cmp(b, S) < 0) + { + k--; + b = multadd(b, 10, 0); /* we botched the k estimate */ + if (leftright) + mhi = multadd(mhi, 10, 0); + ilim = ilim1; + } + } + if (ilim <= 0 && mode > 2) + { + if (ilim < 0 || cmp(b, S = multadd(S, 5, 0)) <= 0) + { + /* no digits, fcvt style */ + no_digits: + k = -1 - ndigits; + goto ret; + } + one_digit: + *s++ = '1'; + k++; + goto ret; + } + if (leftright) + { + if (m2 > 0) + mhi = lshift(mhi, m2); + + /* Compute mlo -- check for special case that d is a normalized power of + * 2. */ + + mlo = mhi; + if (spec_case) + { + mhi = Balloc(mhi->k); + Bcopy(mhi, mlo); + mhi = lshift(mhi, Log2P); + } + + for (i = 1;; i++) + { + dig = quorem(b, S) + '0'; + /* Do we yet have the shortest decimal string that will round to d? */ + j = cmp(b, mlo); + delta = diff(S, mhi); + j_1 = delta->sign ? 1 : cmp(b, delta); + Bfree(delta); +#ifndef ROUND_BIASED + if (j_1 == 0 && !mode && !(word1(d) & 1)) + { + if (dig == '9') + goto round_9_up; + if (j > 0) + dig++; + *s++ = dig; + goto ret; + } +#endif + if (j < 0 || (j == 0 && !mode +#ifndef ROUND_BIASED + && (!(word1(d) & 1)) +#endif + )) + { + if ((j_1 > 0)) + { + b = lshift(b, 1); + j_1 = cmp(b, S); + if ((j_1 > 0 || (j_1 == 0 && (dig & 1))) && dig++ == '9') + goto round_9_up; + } + *s++ = dig; + goto ret; + } + if (j_1 > 0) + { + if (dig == '9') + { /* possible if i == 1 */ + round_9_up: + *s++ = '9'; + goto roundoff; + } + *s++ = dig + 1; + goto ret; + } + *s++ = dig; + if (i == ilim) + break; + b = multadd(b, 10, 0); + if (mlo == mhi) + mlo = mhi = multadd(mhi, 10, 0); + else + { + mlo = multadd(mlo, 10, 0); + mhi = multadd(mhi, 10, 0); + } + } + } + else + for (i = 1;; i++) + { + *s++ = dig = quorem(b, S) + '0'; + if (i >= ilim) + break; + b = multadd(b, 10, 0); + } + + /* Round off last digit */ + + b = lshift(b, 1); + j = cmp(b, S); + if (j > 0 || (j == 0 && (dig & 1))) + { + roundoff: + while (*--s == '9') + if (s == s0) + { + k++; + *s++ = '1'; + goto ret; + } + ++*s++; + } + else + { + while (*--s == '0'); + s++; + } +ret: + Bfree(S); + if (mhi) + { + if (mlo && mlo != mhi) + Bfree(mlo); + Bfree(mhi); + } +ret1: + Bfree(b); + if (s == s0) + { /* don't return empty string */ + *s++ = '0'; + k = 0; + } + *s = 0; + *decpt = k + 1; + if (rve) + *rve = s; + return s0; +} diff --git a/nuttx/lib/stdio/lib_fclose.c b/nuttx/lib/stdio/lib_fclose.c new file mode 100644 index 0000000000..8cecb8af3c --- /dev/null +++ b/nuttx/lib/stdio/lib_fclose.c @@ -0,0 +1,154 @@ +/**************************************************************************** + * lib/stdio/lib_fclose.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fclose + * + * Description + * The fclose() function will flush the stream pointed to by stream + * (writing any buffered output data using lib_fflush()) and close the + * underlying file descriptor. + * + * Returned Value: + * Upon successful completion 0 is returned. Otherwise, EOF is returned + * and the global variable errno is set to indicate the error. In either + * case any further access (including another call to fclose()) to the + * stream results in undefined behaviour. + * + ****************************************************************************/ + +int fclose(FAR FILE *stream) +{ + int err = EINVAL; + int ret = ERROR; + int status; + + /* Verify that a stream was provided. */ + + if (stream) + { + /* Check that the underlying file descriptor corresponds to an an open + * file. + */ + + ret = OK; + if (stream->fs_filedes >= 0) + { + /* If the stream was opened for writing, then flush the stream */ + + if ((stream->fs_oflags & O_WROK) != 0) + { + ret = lib_fflush(stream, true); + err = errno; + } + + /* Close the underlying file descriptor and save the return status */ + + status = close(stream->fs_filedes); + + /* If close() returns an error but flush() did not then make sure + * that we return the close() error condition. + */ + + if (ret == OK) + { + ret = status; + err = errno; + } + } + +#if CONFIG_STDIO_BUFFER_SIZE > 0 + /* Destroy the semaphore */ + + sem_destroy(&stream->fs_sem); + + /* Release the buffer */ + + if (stream->fs_bufstart) + { + lib_free(stream->fs_bufstart); + } + + /* Clear the whole structure */ + + memset(stream, 0, sizeof(FILE)); +#else +#if CONFIG_NUNGET_CHARS > 0 + /* Reset the number of ungetc characters */ + + stream->fs_nungotten = 0; +#endif + /* Reset the flags */ + + stream->fs_oflags = 0; +#endif + /* Setting the fs_filedescriptor to -1 makes the stream available for reuse */ + + stream->fs_filedes = -1; + } + + /* On an error, reset the errno to the first error encountered and return + * EOF. + */ + + if (ret != OK) + { + set_errno(err); + return EOF; + } + + /* Return success */ + + return OK; +} + diff --git a/nuttx/lib/stdio/lib_fflush.c b/nuttx/lib/stdio/lib_fflush.c new file mode 100644 index 0000000000..e0278d0d25 --- /dev/null +++ b/nuttx/lib/stdio/lib_fflush.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * lib/stdio/lib_fflush.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fflush + * + * Description: + * The function fflush() forces a write of all user-space buffered data for + * the given output or update stream via the stream's underlying write + * function. The open status of the stream is unaffected. + * + * If the stream argument is NULL, fflush() flushes all open output streams. + * + * Return: + * OK on success EOF on failure (with errno set appropriately) + * + ****************************************************************************/ + +int fflush(FAR FILE *stream) +{ + /* Is the stream argument NULL? */ + + if (!stream) + { + /* Yes... then this is a request to flush all streams */ + + return lib_flushall(sched_getstreams()); + } + else if (lib_fflush(stream, true) != 0) + { + /* An error occurred during the flush AND/OR we were unable to flush all + * of the buffered write data. Return EOF on failure. + */ + + return EOF; + } + return OK; +} + diff --git a/nuttx/lib/stdio/lib_fgetc.c b/nuttx/lib/stdio/lib_fgetc.c new file mode 100644 index 0000000000..4e521e8403 --- /dev/null +++ b/nuttx/lib/stdio/lib_fgetc.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * lib/stdio/lib_fgetc.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/************************************************************************** + * Global Constant Data + **************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/************************************************************************** + * Private Constant Data + **************************************************************************/ + +/**************************************************************************** + * Private Variables + **************************************************************************/ + +/**************************************************************************** + * Global Functions + **************************************************************************/ + +/**************************************************************************** + * fgetc + **************************************************************************/ + +int fgetc(FAR FILE *stream) +{ + unsigned char ch; + ssize_t ret; + + ret = lib_fread(&ch, 1, stream); + if (ret > 0) + { + return ch; + } + else + { + return EOF; + } +} diff --git a/nuttx/lib/stdio/lib_fgetpos.c b/nuttx/lib/stdio/lib_fgetpos.c new file mode 100644 index 0000000000..af07f7387e --- /dev/null +++ b/nuttx/lib/stdio/lib_fgetpos.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * lib/stdio/lib_fgetpos.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fgetpos + * + * Description: + * fgetpos() function is an alternate interfaces equivalent to ftell(). + * It gets the current value of the file offset and store it in the location + * referenced by pos. On some non-UNIX systems an fpos_t object may be a + * complex object and fsetpos may be the only way to portably reposition a + * stream. + * + * Returned Value: + * Zero on succes; -1 on failure with errno set appropriately. + * + ****************************************************************************/ + +int fgetpos(FAR FILE *stream, FAR fpos_t *pos) +{ + long position; + +#if CONFIG_DEBUG + if (!stream || !pos) + { + set_errno(EINVAL); + return ERROR; + } +#endif + + position = ftell(stream); + if (position == -1) + { + return ERROR; + } + + *pos = (fpos_t)position; + return OK; +} diff --git a/nuttx/lib/stdio/lib_fgets.c b/nuttx/lib/stdio/lib_fgets.c new file mode 100644 index 0000000000..e84e031f9e --- /dev/null +++ b/nuttx/lib/stdio/lib_fgets.c @@ -0,0 +1,188 @@ +/**************************************************************************** + * lib/stdio/lib_fgets.c + * + * Copyright (C) 2007-2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Some environments may return CR as end-of-line, others LF, and others + * both. The logic here assumes either but not both. + */ + +#undef CONFIG_EOL_IS_CR +#undef CONFIG_EOL_IS_LF +#undef CONFIG_EOL_IS_BOTH_CRLF +#define CONFIG_EOL_IS_EITHER_CRLF 1 + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fgets + * + * Description: + * fgets() reads in at most one less than 'buflen' characters from stream + * and stores them into the buffer pointed to by 'buf'. Reading stops after + * an EOF or a newline. If a newline is read, it is stored into the + * buffer. A null terminator is stored after the last character in the + * buffer. + * + **************************************************************************/ + +char *fgets(FAR char *buf, int buflen, FILE *stream) +{ + int nch = 0; + + /* Sanity checks */ + + if (!stream || !buf || buflen < 1 || stream->fs_filedes < 0) + { + return NULL; + } + + if (buflen < 2) + { + *buf = '\0'; + return buf; + } + + /* Read characters until we have a full line. On each the loop we must + * be assured that there are two free bytes in the line buffer: One for + * the next character and one for the null terminator. + */ + + for(;;) + { + /* Get the next character */ + + int ch = fgetc(stream); + + /* Check for end-of-line. This is tricky only in that some + * environments may return CR as end-of-line, others LF, and + * others both. + */ + +#if defined(CONFIG_EOL_IS_LF) || defined(CONFIG_EOL_IS_BOTH_CRLF) + if (ch == '\n') +#elif defined(CONFIG_EOL_IS_CR) + if (ch == '\r') +#elif CONFIG_EOL_IS_EITHER_CRLF + if (ch == '\n' || ch == '\r') +#endif + { + /* The newline is stored in the buffer along with the null + * terminator. + */ + + buf[nch++] = '\n'; + buf[nch] = '\0'; + return buf; + } + + /* Check for end-of-file */ + + else if (ch == EOF) + { + /* End of file with no data? */ + + if (!nch) + { + /* Yes.. return NULL as the end of file mark */ + + return NULL; + } + else + { + /* Terminate the line */ + + buf[nch] = '\0'; + return buf; + } + } + + /* Otherwise, check if the character is printable and, if so, put the + * character in the line buffer + */ + + else if (isprint(ch)) + { + buf[nch++] = ch; + + /* Check if there is room for another character and the line's + * null terminator. If not then we have to end the line now. + */ + + if (nch + 1 >= buflen) + { + buf[nch] = '\0'; + return buf; + } + } + } +} + diff --git a/nuttx/lib/stdio/lib_fileno.c b/nuttx/lib/stdio/lib_fileno.c new file mode 100644 index 0000000000..ec25ce6d09 --- /dev/null +++ b/nuttx/lib/stdio/lib_fileno.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * lib/stdio/lib_fileno.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#if CONFIG_NFILE_STREAMS > 0 + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +int fileno(FAR FILE *stream) +{ + int ret = -1; + if (stream) + { + ret = stream->fs_filedes; + } + + if (ret < 0) + { + set_errno(EBADF); + return ERROR; + } + return ret; +} +#endif /* CONFIG_NFILE_STREAMS */ + diff --git a/nuttx/lib/stdio/lib_fopen.c b/nuttx/lib/stdio/lib_fopen.c new file mode 100644 index 0000000000..52e44c59de --- /dev/null +++ b/nuttx/lib/stdio/lib_fopen.c @@ -0,0 +1,299 @@ +/**************************************************************************** + * lib/stdio/lib_fopen.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +enum open_mode_e +{ + MODE_NONE = 0, /* No access mode determined */ + MODE_R, /* "r" or "rb" open for reading */ + MODE_W, /* "w" or "wb" open for writing, truncating or creating file */ + MODE_A, /* "a" or "ab" open for writing, appending to file */ + MODE_RPLUS, /* "r+", "rb+", or "r+b" open for update (reading and writing) */ + MODE_WPLUS, /* "w+", "wb+", or "w+b" open for update, truncating or creating file */ + MODE_APLUS, /* "a+", "ab+", or "a+b" open for update, appending to file */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_mode2oflags + ****************************************************************************/ + +static int lib_mode2oflags(FAR const char *mode) +{ + enum open_mode_e state; + int oflags; + + /* Verify that a mode string was provided. No error is */ + + if (!mode) + { + goto errout; + } + + /* Parse the mode string to determine the corresponding open flags */ + + state = MODE_NONE; + oflags = 0; + + for (; *mode; mode++) + { + switch (*mode) + { + /* Open for read access ("r", "r[+]", "r[b]", "r[b+]", or "r[+b]") */ + + case 'r' : + if (state == MODE_NONE) + { + /* Open for read access */ + + oflags = O_RDOK; + state = MODE_R; + } + else + { + goto errout; + } + break; + + /* Open for write access ("w", "w[+]", "w[b]", "w[b+]", or "w[+b]") */ + + case 'w' : + if (state == MODE_NONE) + { + /* Open for write access, truncating any existing file */ + + oflags = O_WROK|O_CREAT|O_TRUNC; + state = MODE_W; + } + else + { + goto errout; + } + break; + + /* Open for write/append access ("a", "a[+]", "a[b]", "a[b+]", or "a[+b]") */ + + case 'a' : + if (state == MODE_NONE) + { + /* Write to the end of the file */ + + oflags = O_WROK|O_CREAT|O_APPEND; + state = MODE_A; + } + else + { + goto errout; + } + break; + + /* Open for update access ("[r]+", "[rb]+]", "[r]+[b]", "[w]+", + * "[wb]+]", "[w]+[b]", "[a]+", "[ab]+]", "[a]+[b]") + */ + + case '+' : + switch (state) + { + case MODE_R: + { + /* Retain any binary mode selection */ + + oflags &= O_BINARY; + + /* Open for read/write access */ + + oflags |= O_RDWR; + state = MODE_RPLUS; + } + break; + + case MODE_W: + { + /* Retain any binary mode selection */ + + oflags &= O_BINARY; + + /* Open for write read/access, truncating any existing file */ + + oflags |= O_RDWR|O_CREAT|O_TRUNC; + state = MODE_WPLUS; + } + break; + + case MODE_A: + { + /* Retain any binary mode selection */ + + oflags &= O_BINARY; + + /* Read from the beginning of the file; write to the end */ + + oflags |= O_RDWR|O_CREAT|O_APPEND; + state = MODE_APLUS; + } + break; + + default: + goto errout; + break; + } + break; + + /* Open for binary access ("[r]b", "[r]b[+]", "[r+]b", "[w]b", + * "[w]b[+]", "[w+]b", "[a]b", "[a]b[+]", "[a+]b") + */ + + case 'b' : + if (state != MODE_NONE) + { + /* The file is opened in binary mode */ + + oflags |= O_BINARY; + } + else + { + goto errout; + } + break; + + /* Unrecognized or unsupported mode */ + + default: + goto errout; + break; + } + } + + return oflags; + +/* Both fopen and fdopen should fail with errno == EINVAL if the mode + * string is invalid. + */ + +errout: + set_errno(EINVAL); + return ERROR; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fdopen + ****************************************************************************/ + +FAR FILE *fdopen(int fd, FAR const char *mode) +{ + FAR FILE *ret = NULL; + int oflags; + + /* Map the open mode string to open flags */ + + oflags = lib_mode2oflags(mode); + if (oflags >= 0) + { + ret = fs_fdopen(fd, oflags, NULL); + } + + return ret; +} + +/**************************************************************************** + * Name: fopen + ****************************************************************************/ + +FAR FILE *fopen(FAR const char *path, FAR const char *mode) +{ + FAR FILE *ret = NULL; + int oflags; + int fd; + + /* Map the open mode string to open flags */ + + oflags = lib_mode2oflags(mode); + if (oflags < 0) + { + return NULL; + } + + /* Open the file */ + + fd = open(path, oflags, 0666); + + /* If the open was successful, then fdopen() the fil using the file + * desciptor returned by open. If open failed, then just return the + * NULL stream -- open() has already set the errno. + */ + + if (fd >= 0) + { + ret = fs_fdopen(fd, oflags, NULL); + if (!ret) + { + /* Don't forget to close the file descriptor if any other + * failures are reported by fdopen(). + */ + + (void)close(fd); + } + } + return ret; +} diff --git a/nuttx/lib/stdio/lib_fprintf.c b/nuttx/lib/stdio/lib_fprintf.c new file mode 100644 index 0000000000..a803de4bd0 --- /dev/null +++ b/nuttx/lib/stdio/lib_fprintf.c @@ -0,0 +1,93 @@ +/**************************************************************************** + * lib/stdio/lib_fprintf.c + * + * Copyright (C) 2007, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fprintf + ****************************************************************************/ + +int fprintf(FAR FILE *stream, FAR const char *fmt, ...) +{ + va_list ap; + int n; + + /* vfprintf into the stream */ + + va_start(ap, fmt); + n = vfprintf(stream, fmt, ap); + va_end(ap); + return n; +} diff --git a/nuttx/lib/stdio/lib_fputc.c b/nuttx/lib/stdio/lib_fputc.c new file mode 100644 index 0000000000..121161f102 --- /dev/null +++ b/nuttx/lib/stdio/lib_fputc.c @@ -0,0 +1,113 @@ +/**************************************************************************** + * lib/stdio/lib_fputc.c + * + * Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fputc + ****************************************************************************/ + +int fputc(int c, FAR FILE *stream) +{ + unsigned char buf = (unsigned char)c; + int ret; + + ret = lib_fwrite(&buf, 1, stream); + if (ret > 0) + { + /* Flush the buffer if a newline is output */ + +#ifdef CONFIG_STDIO_LINEBUFFER + if (c == '\n') + { + ret = lib_fflush(stream, true); + if (ret < 0) + { + return EOF; + } + } +#endif + return c; + } + else + { + return EOF; + } +} diff --git a/nuttx/lib/stdio/lib_fputs.c b/nuttx/lib/stdio/lib_fputs.c new file mode 100644 index 0000000000..2d6217d4aa --- /dev/null +++ b/nuttx/lib/stdio/lib_fputs.c @@ -0,0 +1,220 @@ +/**************************************************************************** + * lib/stdio/lib_fputs.c + * + * Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fputs + * + * Description: + * fputs() writes the string s to stream, without its trailing '\0'. + * + ****************************************************************************/ + +#if defined(CONFIG_ARCH_ROMGETC) +int fputs(FAR const char *s, FAR FILE *stream) +{ + int nput; + int ret; + char ch; + + /* Make sure that a string was provided. */ + +#ifdef CONFIG_DEBUG /* Most parameter checking is disabled if DEBUG is off */ + if (!s) + { + set_errno(EINVAL); + return EOF; + } +#endif + + /* Write the string. Loop until the null terminator is encountered */ + + for (nput = 0, ch = up_romgetc(s); ch; nput++, s++, ch = up_romgetc(s)) + { + /* Write the next character to the stream buffer */ + + ret = lib_fwrite(&ch, 1, stream); + if (ret <= 0) + { + return EOF; + } + + /* Flush the buffer if a newline was written to the buffer */ + +#ifdef CONFIG_STDIO_LINEBUFFER + if (ch == '\n') + { + ret = lib_fflush(stream, true); + if (ret < 0) + { + return EOF; + } + } +#endif + } + + return nput; +} + +#elif defined(CONFIG_STDIO_LINEBUFFER) +int fputs(FAR const char *s, FAR FILE *stream) +{ + int nput; + int ret; + + /* Make sure that a string was provided. */ + +#ifdef CONFIG_DEBUG /* Most parameter checking is disabled if DEBUG is off */ + if (!s) + { + set_errno(EINVAL); + return EOF; + } +#endif + + /* Write the string. Loop until the null terminator is encountered */ + + for (nput = 0; *s; nput++, s++) + { + /* Write the next character to the stream buffer */ + + ret = lib_fwrite(s, 1, stream); + if (ret <= 0) + { + return EOF; + } + + /* Flush the buffer if a newline was written to the buffer */ + + if (*s == '\n') + { + ret = lib_fflush(stream, true); + if (ret < 0) + { + return EOF; + } + } + } + + return nput; +} + +#else +int fputs(FAR const char *s, FAR FILE *stream) +{ + int ntowrite; + int nput; + + /* Make sure that a string was provided. */ + +#ifdef CONFIG_DEBUG /* Most parameter checking is disabled if DEBUG is off */ + if (!s) + { + set_errno(EINVAL); + return EOF; + } +#endif + + /* Get the length of the string. */ + + ntowrite = strlen(s); + if (ntowrite == 0) + { + return 0; + } + + /* Write the string */ + + nput = lib_fwrite(s, ntowrite, stream); + if (nput < 0) + { + return EOF; + } + return nput; +} +#endif diff --git a/nuttx/lib/stdio/lib_fread.c b/nuttx/lib/stdio/lib_fread.c new file mode 100644 index 0000000000..cc652fab72 --- /dev/null +++ b/nuttx/lib/stdio/lib_fread.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * lib/stdio/lib_fread.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fread + ****************************************************************************/ + +size_t fread(FAR void *ptr, size_t size, size_t n_items, FAR FILE *stream) +{ + size_t full_size = n_items * (size_t)size; + ssize_t bytes_read; + size_t items_read = 0; + + /* Write the data into the stream buffer */ + + bytes_read = lib_fread(ptr, full_size, stream); + if (bytes_read > 0) + { + /* Return the number of full items read */ + + items_read = bytes_read / size; + } + return items_read; +} + + diff --git a/nuttx/lib/stdio/lib_fseek.c b/nuttx/lib/stdio/lib_fseek.c new file mode 100644 index 0000000000..a68de79fe2 --- /dev/null +++ b/nuttx/lib/stdio/lib_fseek.c @@ -0,0 +1,138 @@ +/**************************************************************************** + * lib/stdio/lib_fseek.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fseek + * + * Description: + * The fseek() function sets the file position indicator for the stream + * pointed to by stream. The new position, measured in bytes, is obtained + * by adding offset bytes to the position specified by whence. If whence is + * set to SEEK_SET, SEEK_CUR, or SEEK_END, the offset is relative to the + * start of the file, the current position indicator, or end-of-file, + * respectively. A successful call to the fseek() function clears the + * end-of-file indicator for the stream and undoes any effects of the ungetc(3) + * function on the same stream. + * + * Returned Value: + * Zero on succes; -1 on failure with errno set appropriately. + * + ****************************************************************************/ + +int fseek(FAR FILE *stream, long int offset, int whence) +{ + #if CONFIG_STDIO_BUFFER_SIZE > 0 + /* Flush any valid read/write data in the buffer (also verifies stream) */ + + if (lib_rdflush(stream) < 0 || lib_wrflush(stream) < 0) + { + return ERROR; + } +#else + /* Verify that we were provided with a stream */ + + if (!stream) + { + set_errno(EBADF); + return ERROR; + } +#endif + + /* On success or failure, discard any characters saved by ungetc() */ + +#if CONFIG_NUNGET_CHARS > 0 + stream->fs_nungotten = 0; +#endif + + /* Perform the fseek on the underlying file descriptor */ + + return lseek(stream->fs_filedes, offset, whence) == (off_t)-1 ? ERROR : OK; +} + + diff --git a/nuttx/lib/stdio/lib_fsetpos.c b/nuttx/lib/stdio/lib_fsetpos.c new file mode 100644 index 0000000000..ad3e672300 --- /dev/null +++ b/nuttx/lib/stdio/lib_fsetpos.c @@ -0,0 +1,116 @@ +/**************************************************************************** + * lib/stdio/lib_fsetpos.c + * + * Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fsetpos + * + * Description: + * fsetpos() function is an alternate interfaces equivalent to fseek() + * (with whence set to SEEK_SET). It sets the current value of the file + * offset to value in the location referenced by pos. On some non-UNIX + * systems an fpos_t object may be a complex object and fsetpos may be the + * only way to portably reposition a stream. + * + * Returned Value: + * Zero on succes; -1 on failure with errno set appropriately. + * + ****************************************************************************/ + +int fsetpos(FAR FILE *stream, FAR fpos_t *pos) +{ +#if CONFIG_DEBUG + if (!stream || !pos) + { + set_errno(EINVAL); + return ERROR; + } +#endif + + return fseek(stream, (FAR off_t)*pos, SEEK_SET); +} diff --git a/nuttx/lib/stdio/lib_ftell.c b/nuttx/lib/stdio/lib_ftell.c new file mode 100644 index 0000000000..cd0e483687 --- /dev/null +++ b/nuttx/lib/stdio/lib_ftell.c @@ -0,0 +1,129 @@ +/**************************************************************************** + * lib/stdio/lib_ftell.c + * + * Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ftell + * + * Description: + * ftell() returns the current value of the file position indicator for the + * stream pointed to by stream. + * + * Returned Value: + * Zero on succes; -1 on failure with errno set appropriately. + * + ****************************************************************************/ + +long ftell(FAR FILE *stream) +{ + off_t position; + + /* Verify that we were provided with a stream */ + + if (!stream) + { + set_errno(EBADF); + return ERROR; + } + + /* Perform the lseek to the current position. This will not move the + * file pointer, but will return its current setting + */ + + position = lseek(stream->fs_filedes, 0, SEEK_CUR); + if (position != (off_t)-1) + { + return (long)position; + } + else + { + return ERROR; + } +} + + diff --git a/nuttx/lib/stdio/lib_fwrite.c b/nuttx/lib/stdio/lib_fwrite.c new file mode 100644 index 0000000000..1b7be2ce5c --- /dev/null +++ b/nuttx/lib/stdio/lib_fwrite.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * lib/stdio/lib_fwrite.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fwrite + ****************************************************************************/ + +size_t fwrite(FAR const void *ptr, size_t size, size_t n_items, FAR FILE *stream) +{ + size_t full_size = n_items * (size_t)size; + ssize_t bytes_written; + size_t items_written = 0; + + /* Write the data into the stream buffer */ + + bytes_written = lib_fwrite(ptr, full_size, stream); + if (bytes_written > 0) + { + /* Return the number of full items written */ + + items_written = bytes_written / size; + } + return items_written; +} diff --git a/nuttx/lib/stdio/lib_gets.c b/nuttx/lib/stdio/lib_gets.c new file mode 100644 index 0000000000..95a6b36ebf --- /dev/null +++ b/nuttx/lib/stdio/lib_gets.c @@ -0,0 +1,120 @@ +/**************************************************************************** + * lib/stdio/lib_gets.c + * + * Copyright (C) 2007-2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gets + * + * Description: + * gets() reads a line from stdin into the buffer pointed to by s until + * either a terminating newline or EOF, which it replaces with '\0'. No + * check for buffer overrun is performed + * + * This API should not be used because it is inherently unsafe. Consider + * using fgets which is safer and slightly more efficient. + * + **************************************************************************/ + +FAR char *gets(FAR char *s) +{ + /* gets is ALMOST the same as fgets using stdin and no length limit + * (hence, the unsafeness of gets). So let fgets do most of the work. + */ + + FAR char *ret = fgets(s, INT_MAX, stdin); + if (ret) + { + /* Another subtle difference from fgets is that gets replaces + * end-of-line markers with null terminators. We will do that as + * a second step (with some loss in performance). + */ + + int len = strlen(ret); + if (len > 0 && ret[len-1] == '\n') + { + ret[len-1] = '\0'; + } + } + + return ret; +} + diff --git a/nuttx/lib/stdio/lib_libdtoa.c b/nuttx/lib/stdio/lib_libdtoa.c new file mode 100644 index 0000000000..3bfe70aeaf --- /dev/null +++ b/nuttx/lib/stdio/lib_libdtoa.c @@ -0,0 +1,365 @@ +/**************************************************************************** + * lib/unistd/lib_libdtoa.c + * + * This file was ported to NuttX by Yolande Cates. + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAXEXP 308 + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static char* cvt(double value, int ndigits, int flags, char *sign, + int *decpt, int ch, int *length); +static int exponent(char *p0, int exp, int fmtch); + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cvt + ****************************************************************************/ + +static char* cvt(double value, int ndigits, int flags, char *sign, + int *decpt, int ch, int *length) +{ + int mode, dsgn; + char *digits, *bp, *rve; + + if (ch == 'f') + { + mode = 3; /* ndigits after the decimal point */ + } + else + { + /* To obtain ndigits after the decimal point for the 'e' and 'E' + * formats, round to ndigits + 1 significant figures. + */ + + if (ch == 'e' || ch == 'E') + { + ndigits++; + } + mode = 2; /* ndigits significant digits */ + } + + if (value < 0) + { + value = -value; + *sign = '-'; + } + else + { + *sign = '\000'; + } + + digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve); + if ((ch != 'g' && ch != 'G') || IS_ALTFORM(flags)) + { + /* Print trailing zeros */ + + bp = digits + ndigits; + if (ch == 'f') + { + if (*digits == '0' && value) + { + *decpt = -ndigits + 1; + } + bp += *decpt; + } + + if (value == 0) + { + /* kludge for __dtoa irregularity */ + + rve = bp; + } + + while (rve < bp) + { + *rve++ = '0'; + } + } + + *length = rve - digits; + return digits; +} + +/**************************************************************************** + * Name: exponent + ****************************************************************************/ + +static int exponent(FAR char *p0, int exp, int fmtch) +{ + FAR char *p; + FAR char *t; + char expbuf[MAXEXP]; + + p = p0; + *p++ = fmtch; + if (exp < 0) + { + exp = -exp; + *p++ = '-'; + } + else + { + *p++ = '+'; + } + + t = expbuf + MAXEXP; + if (exp > 9) + { + do + { + *--t = (exp % 10) + '0'; + } + while ((exp /= 10) > 9); + *--t = exp + '0'; + for (; t < expbuf + MAXEXP; *p++ = *t++); + } + else + { + *p++ = '0'; + *p++ = exp + '0'; + } + return (p - p0); +} + +/**************************************************************************** + * Name: lib_dtoa + * + * Description: + * This is part of lib_vsprintf(). It handles the floating point formats. + * + ****************************************************************************/ + +static void lib_dtoa(FAR struct lib_outstream_s *obj, int ch, int prec, + uint8_t flags, double _double) +{ + FAR char *cp; /* Handy char pointer (short term usage) */ + FAR char *cp_free = NULL; /* BIONIC: copy of cp to be freed after usage */ + char expstr[7]; /* Buffer for exponent string */ + char sign; /* Temporary negative sign for floats */ + int expt; /* Integer value of exponent */ + int expsize = 0; /* Character count for expstr */ + int ndig; /* Actual number of digits returned by cvt */ + int size; /* Size of converted field or string */ + int i; + + cp = cvt(_double, prec, flags, &sign, &expt, ch, &ndig); + cp_free = cp; + + if (ch == 'g' || ch == 'G') + { + /* 'g' or 'G' fmt */ + + if (expt <= -4 || expt > prec) + { + ch = (ch == 'g') ? 'e' : 'E'; + } + else + { + ch = 'g'; + } + } + + if (ch <= 'e') + { + /* 'e' or 'E' fmt */ + + --expt; + expsize = exponent(expstr, expt, ch); + size = expsize + ndig; + if (ndig > 1 || IS_ALTFORM(flags)) + { + ++size; + } + } + else if (ch == 'f') + { + /* f fmt */ + + if (expt > 0) + { + size = expt; + if (prec || IS_ALTFORM(flags)) + { + size += prec + 1; + } + } + else /* "0.X" */ + { + size = prec + 2; + } + } + else if (expt >= ndig) + { + /* fixed g fmt */ + + size = expt; + if (IS_ALTFORM(flags)) + { + ++size; + } + } + else + { + size = ndig + (expt > 0 ? 1 : 2 - expt); + } + + if (sign) + { + obj->put(obj, '-'); + } + + if (_double == 0) + { + /* kludge for __dtoa irregularity */ + + obj->put(obj, '0'); + if (expt < ndig || IS_ALTFORM(flags)) + { + obj->put(obj, '.'); + + i = ndig - 1; + while (i > 0) + { + obj->put(obj, '0'); + i--; + } + } + } + else if (expt <= 0) + { + obj->put(obj, '0'); + obj->put(obj, '.'); + + i = ndig; + while (i > 0) + { + obj->put(obj, *cp); + i--; + cp++; + } + } + else if (expt >= ndig) + { + i = ndig; + while (i > 0) + { + obj->put(obj, *cp); + i--; + cp++; + } + + i = expt - ndig; + while (i > 0) + { + obj->put(obj, '0'); + i--; + } + + if (IS_ALTFORM(flags)) + { + obj->put(obj, '.'); + } + } + else + { + /* print the integer */ + + i = expt; + while (i > 0) + { + obj->put(obj, *cp); + i--; + cp++; + } + + /* print the decimal place */ + + obj->put(obj, '.'); + + /* print the decimal */ + + i = ndig - expt; + while (i > 0) + { + obj->put(obj, *cp); + i--; + cp++; + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + diff --git a/nuttx/lib/stdio/lib_libfflush.c b/nuttx/lib/stdio/lib_libfflush.c new file mode 100644 index 0000000000..fb5a8768e9 --- /dev/null +++ b/nuttx/lib/stdio/lib_libfflush.c @@ -0,0 +1,196 @@ +/**************************************************************************** + * lib/stdio/lib_libfflush.c + * + * Copyright (C) 2007-2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_fflush + * + * Description: + * The function lib_fflush() forces a write of all user-space buffered data for + * the given output or update stream via the stream's underlying write + * function. The open status of the stream is unaffected. + * + * Parmeters: + * stream - the stream to flush + * bforce - flush must be complete. + * + * Return: + * ERROR on failure, otherwise the number of bytes remaining in the buffer. + * If bforce is set, then only the values ERROR and 0 will be returned. + * + ****************************************************************************/ + +ssize_t lib_fflush(FAR FILE *stream, bool bforce) +{ +#if CONFIG_STDIO_BUFFER_SIZE > 0 + FAR const unsigned char *src; + ssize_t bytes_written; + ssize_t nbuffer; + + /* Return EBADF if the file is not opened for writing */ + + if (stream->fs_filedes < 0 || (stream->fs_oflags & O_WROK) == 0) + { + set_errno(EBADF); + return ERROR; + } + + /* Make sure that we have exclusive access to the stream */ + + lib_take_semaphore(stream); + + /* Make sure that the buffer holds valid data */ + + if (stream->fs_bufpos != stream->fs_bufstart) + { + /* Make sure that the buffer holds buffered write data. We do not + * support concurrent read/write buffer usage. + */ + + if (stream->fs_bufread != stream->fs_bufstart) + { + /* The buffer holds read data... just return zero */ + + return 0; + } + + /* How many bytes of write data are used in the buffer now */ + + nbuffer = stream->fs_bufpos - stream->fs_bufstart; + + /* Try to write that amount */ + + src = stream->fs_bufstart; + do + { + /* Perform the write */ + + bytes_written = write(stream->fs_filedes, src, nbuffer); + if (bytes_written < 0) + { + lib_give_semaphore(stream); + return ERROR; + } + + /* Handle partial writes. fflush() must either return with + * an error condition or with the data successfully flushed + * from the buffer. + */ + + src += bytes_written; + nbuffer -= bytes_written; + } + while (bforce && nbuffer > 0); + + /* Reset the buffer position to the beginning of the buffer */ + + stream->fs_bufpos = stream->fs_bufstart; + + /* For the case of an incomplete write, nbuffer will be non-zero + * It will hold the number of bytes that were not written. + * Move the data down in the buffer to handle this (rare) case + */ + + while (nbuffer) + { + *stream->fs_bufpos++ = *src++; + --nbuffer; + } + } + + /* Restore normal access to the stream and return the number of bytes + * remaining in the buffer. + */ + + lib_give_semaphore(stream); + return stream->fs_bufpos - stream->fs_bufstart; +#else + /* Return no bytes remaining in the buffer */ + + return 0; +#endif +} + diff --git a/nuttx/lib/stdio/lib_libflushall.c b/nuttx/lib/stdio/lib_libflushall.c new file mode 100644 index 0000000000..8de0c33096 --- /dev/null +++ b/nuttx/lib/stdio/lib_libflushall.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * lib/stdio/lib_libflushall.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_flushall + * + * Description: + * Called either (1) by the OS when a task exits, or (2) from fflush() + * when a NULL stream argument is provided. + * + ****************************************************************************/ + +int lib_flushall(FAR struct streamlist *list) +{ + int lasterrno = OK; + int ret = OK; + + /* Make sure that there are streams associated with this thread */ + + if (list) + { + int i; + + /* Process each stream in the thread's stream list */ + + stream_semtake(list); + for (i = 0; i < CONFIG_NFILE_STREAMS; i++) + { + FILE *stream = &list->sl_streams[i]; + + /* If the stream is open (i.e., assigned a non-negative file + * descriptor) and opened for writing, then flush all of the pending + * write data in the stream. + */ + + if (stream->fs_filedes >= 0 && (stream->fs_oflags & O_WROK) != 0) + { + /* Flush the writable FILE */ + + if (lib_fflush(stream, true) != 0) + { + /* An error occurred during the flush AND/OR we were unable + * to flush all of the buffered write data. Return EOF on failure. + */ + + lasterrno = get_errno(); + ret = ERROR; + } + } + } + stream_semgive(list); + } + + /* If any flush failed, return that last failed flush */ + + if (ret != OK) + { + set_errno(lasterrno); + } + return ret; +} diff --git a/nuttx/lib/stdio/lib_libfread.c b/nuttx/lib/stdio/lib_libfread.c new file mode 100644 index 0000000000..4d402a42b4 --- /dev/null +++ b/nuttx/lib/stdio/lib_libfread.c @@ -0,0 +1,271 @@ +/**************************************************************************** + * lib/stdio/lib_libfread.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include /* for CONFIG_STDIO_BUFFER_SIZE */ + +#include +#include +#include +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_fread + ****************************************************************************/ + +ssize_t lib_fread(FAR void *ptr, size_t count, FAR FILE *stream) +{ + unsigned char *dest = (unsigned char*)ptr; + ssize_t bytes_read; + + /* Make sure that reading from this stream is allowed */ + + if (!stream || (stream->fs_oflags & O_RDOK) == 0) + { + set_errno(EBADF); + bytes_read = -1; + } + else + { + /* The stream must be stable until we complete the read */ + + lib_take_semaphore(stream); + +#if CONFIG_NUNGET_CHARS > 0 + /* First, re-read any previously ungotten characters */ + + while ((stream->fs_nungotten > 0) && (count > 0)) + { + /* Decrement the count of ungotten bytes to get an index */ + + stream->fs_nungotten--; + + /* Return the last ungotten byte */ + + *dest++ = stream->fs_ungotten[stream->fs_nungotten]; + + /* That's one less byte that we have to read */ + + count--; + } +#endif + +#if CONFIG_STDIO_BUFFER_SIZE > 0 + /* If the buffer is currently being used for write access, then + * flush all of the buffered write data. We do not support concurrent + * buffered read/write access. + */ + + if (lib_wrflush(stream) != 0) + { + return ERROR; + } + + /* Now get any other needed chars from the buffer or the file. */ + + while (count > 0) + { + /* Is there readable data in the buffer? */ + + while ((count > 0) && (stream->fs_bufpos < stream->fs_bufread)) + { + /* Yes, copy a byte into the user buffer */ + + *dest++ = *stream->fs_bufpos++; + count--; + } + + /* The buffer is empty OR we have already supplied the number of + * bytes requested in the read. Check if we need to read + * more from the file. + */ + + if (count > 0) + { + size_t buffer_available; + + /* We need to read more data into the buffer from the file */ + + /* Mark the buffer empty */ + + stream->fs_bufpos = stream->fs_bufread = stream->fs_bufstart; + + /* How much space is available in the buffer? */ + + buffer_available = stream->fs_bufend - stream->fs_bufread; + + /* Will the number of bytes that we need to read fit into + * the buffer space that is available? If the read size is + * larger than the buffer, then read some of the data + * directly into the user's buffer. + */ + + if (count > buffer_available) + { + bytes_read = read(stream->fs_filedes, dest, count); + if (bytes_read < 0) + { + /* An error occurred on the read */ + + goto err_out; + } + else if (bytes_read == 0) + { + /* We are at the end of the file */ + + goto short_read; + } + else + { + /* Some bytes were read. Adjust the dest pointer */ + + dest += bytes_read; + + /* Were all of the requested bytes read? */ + + if (bytes_read < count) + { + /* No. We must be at the end of file. */ + + goto short_read; + } + else + { + /* Yes. We are done. */ + + count = 0; + } + } + } + else + { + /* The number of bytes required to satisfy the read + * is less than or equal to the size of the buffer + * space that we have left. Read as much as we can + * into the buffer. + */ + + bytes_read = read(stream->fs_filedes, stream->fs_bufread, buffer_available); + if (bytes_read < 0) + { + /* An error occurred on the read */ + + goto err_out; + } + else if (bytes_read == 0) + { + /* We are at the end of the file */ + + goto short_read; + } + else + { + /* Some bytes were read */ + + stream->fs_bufread += bytes_read; + } + } + } + } +#else + /* Now get any other needed chars from the file. */ + + while (count > 0) + { + bytes_read = read(stream->fs_filedes, dest, count); + if (bytes_read < 0) + { + goto err_out; + } + else if (bytes_read == 0) + { + break; + } + else + { + dest += bytes_read; + count -= bytes_read; + } + } +#endif +#if CONFIG_STDIO_BUFFER_SIZE > 0 + short_read: +#endif + bytes_read = dest - (unsigned char*)ptr; + err_out: + lib_give_semaphore(stream); + } + return bytes_read; +} + diff --git a/nuttx/lib/stdio/lib_libfwrite.c b/nuttx/lib/stdio/lib_libfwrite.c new file mode 100644 index 0000000000..e2c35e3e99 --- /dev/null +++ b/nuttx/lib/stdio/lib_libfwrite.c @@ -0,0 +1,179 @@ +/**************************************************************************** + * lib/stdio/lib_libfwrite.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include /* for CONFIG_STDIO_BUFFER_SIZE */ + +#include +#include +#include +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_fwrite + ****************************************************************************/ + +ssize_t lib_fwrite(FAR const void *ptr, size_t count, FAR FILE *stream) +#if CONFIG_STDIO_BUFFER_SIZE > 0 +{ + FAR const unsigned char *start = ptr; + FAR const unsigned char *src = ptr; + ssize_t ret = ERROR; + unsigned char *dest; + + /* Make sure that writing to this stream is allowed */ + + if (!stream || (stream->fs_oflags & O_WROK) == 0) + { + set_errno(EBADF); + goto errout; + } + + /* Get exclusive access to the stream */ + + lib_take_semaphore(stream); + + /* If the buffer is currently being used for read access, then + * discard all of the read-ahead data. We do not support concurrent + * buffered read/write access. + */ + + if (lib_rdflush(stream) < 0) + { + goto errout_with_semaphore; + } + + /* Loop until all of the bytes have been buffered */ + + while (count > 0) + { + /* Determine the number of bytes left in the buffer */ + + size_t gulp_size = stream->fs_bufend - stream->fs_bufpos; + + /* Will the user data fit into the amount of buffer space + * that we have left? + */ + + if (gulp_size > count) + { + /* Yes, clip the gulp to the size of the user data */ + + gulp_size = count; + } + + /* Adjust the number of bytes remaining to be transferred + * on the next pass through the loop (might be zero). + */ + + count -= gulp_size; + + /* Transfer the data into the buffer */ + + for (dest = stream->fs_bufpos; gulp_size > 0; gulp_size--) + { + *dest++ = *src++; + } + stream->fs_bufpos = dest; + + /* Is the buffer full? */ + + if (dest >= stream->fs_bufend) + { + /* Flush the buffered data to the IO stream */ + + int bytes_buffered = lib_fflush(stream, false); + if (bytes_buffered < 0) + { + goto errout_with_semaphore; + } + } + } + + /* Return the number of bytes written */ + + ret = src - start; + +errout_with_semaphore: + lib_give_semaphore(stream); + +errout: + return ret; +} +#else +{ + return write(stream->fs_filedes, ptr, count); +} +#endif /* CONFIG_STDIO_BUFFER_SIZE */ + diff --git a/nuttx/lib/stdio/lib_libnoflush.c b/nuttx/lib/stdio/lib_libnoflush.c new file mode 100644 index 0000000000..e3b8911534 --- /dev/null +++ b/nuttx/lib/stdio/lib_libnoflush.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * lib/stdio/lib_libnoflush.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "lib_internal.h" + +#ifdef CONFIG_STDIO_LINEBUFFER + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_noflush + * + * Description: + * lib_noflush() provides a common, dummy flush method for output streams + * that are not flushable. Only used if CONFIG_STDIO_LINEBUFFER is selected. + * + * Return: + * Always returns OK + * + ****************************************************************************/ + +int lib_noflush(FAR struct lib_outstream_s *this) +{ + return OK; +} + +#endif /* CONFIG_STDIO_LINEBUFFER */ + diff --git a/nuttx/lib/stdio/lib_libsprintf.c b/nuttx/lib/stdio/lib_libsprintf.c new file mode 100644 index 0000000000..04d5477541 --- /dev/null +++ b/nuttx/lib/stdio/lib_libsprintf.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * lib/stdio/lib_libsprintf.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_sprintf + ****************************************************************************/ + +int lib_sprintf(FAR struct lib_outstream_s *obj, const char *fmt, ...) +{ + va_list ap; + int n; + + /* Let lib_vsprintf do the real work */ + + va_start(ap, fmt); + n = lib_vsprintf(obj, fmt, ap); + va_end(ap); + return n; +} diff --git a/nuttx/lib/stdio/lib_libvsprintf.c b/nuttx/lib/stdio/lib_libvsprintf.c new file mode 100644 index 0000000000..8d521c35e8 --- /dev/null +++ b/nuttx/lib/stdio/lib_libvsprintf.c @@ -0,0 +1,1593 @@ +/**************************************************************************** + * lib/stdio/lib_libvsprintf.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* If you have floating point but no fieldwidth, then use a fixed (but + * configurable) floating point precision. + */ + +#if defined(CONFIG_LIBC_FLOATINGPOINT) && \ + defined(CONFIG_NOPRINTF_FIELDWIDTH) && \ + !defined(CONFIG_LIBC_FIXEDPRECISION) +# define CONFIG_LIBC_FIXEDPRECISION 3 +#endif + +#define FLAG_SHOWPLUS 0x01 +#define FLAG_ALTFORM 0x02 +#define FLAG_HASDOT 0x04 +#define FLAG_HASASTERISKWIDTH 0x08 +#define FLAG_HASASTERISKTRUNC 0x10 +#define FLAG_LONGPRECISION 0x20 +#define FLAG_LONGLONGPRECISION 0x40 +#define FLAG_NEGATE 0x80 + +#define SET_SHOWPLUS(f) do (f) |= FLAG_SHOWPLUS; while (0) +#define SET_ALTFORM(f) do (f) |= FLAG_ALTFORM; while (0) +#define SET_HASDOT(f) do (f) |= FLAG_HASDOT; while (0) +#define SET_HASASTERISKWIDTH(f) do (f) |= FLAG_HASASTERISKWIDTH; while (0) +#define SET_HASASTERISKTRUNC(f) do (f) |= FLAG_HASASTERISKTRUNC; while (0) +#define SET_LONGPRECISION(f) do (f) |= FLAG_LONGPRECISION; while (0) +#define SET_LONGLONGPRECISION(f) do (f) |= FLAG_LONGLONGPRECISION; while (0) +#define SET_NEGATE(f) do (f) |= FLAG_NEGATE; while (0) + +#define CLR_SHOWPLUS(f) do (f) &= ~FLAG_SHOWPLUS; while (0) +#define CLR_ALTFORM(f) do (f) &= ~FLAG_ALTFORM; while (0) +#define CLR_HASDOT(f) do (f) &= ~FLAG_HASDOT; while (0) +#define CLR_HASASTERISKWIDTH(f) do (f) &= ~FLAG_HASASTERISKWIDTH; while (0) +#define CLR_HASASTERISKTRUNC(f) do (f) &= ~FLAG_HASASTERISKTRUNC; while (0) +#define CLR_LONGPRECISION(f) do (f) &= ~FLAG_LONGPRECISION; while (0) +#define CLR_LONGLONGPRECISION(f) do (f) &= ~FLAG_LONGLONGPRECISION; while (0) +#define CLR_NEGATE(f) do (f) &= ~FLAG_NEGATE; while (0) +#define CLR_SIGNED(f) do (f) &= ~(FLAG_SHOWPLUS|FLAG_NEGATE); while (0) + +#define IS_SHOWPLUS(f) (((f) & FLAG_SHOWPLUS) != 0) +#define IS_ALTFORM(f) (((f) & FLAG_ALTFORM) != 0) +#define IS_HASDOT(f) (((f) & FLAG_HASDOT) != 0) +#define IS_HASASTERISKWIDTH(f) (((f) & FLAG_HASASTERISKWIDTH) != 0) +#define IS_HASASTERISKTRUNC(f) (((f) & FLAG_HASASTERISKTRUNC) != 0) +#define IS_LONGPRECISION(f) (((f) & FLAG_LONGPRECISION) != 0) +#define IS_LONGLONGPRECISION(f) (((f) & FLAG_LONGLONGPRECISION) != 0) +#define IS_NEGATE(f) (((f) & FLAG_NEGATE) != 0) +#define IS_SIGNED(f) (((f) & (FLAG_SHOWPLUS|FLAG_NEGATE)) != 0) + +/* If CONFIG_ARCH_ROMGETC is defined, then it is assumed that the format + * string data cannot be accessed by simply de-referencing the format string + * pointer. This might be in the case in Harvard architectures where string + * data might be stored in instruction space or if string data were stored + * on some media like EEPROM or external serial FLASH. In all of these cases, + * string data has to be accessed indirectly using the architecture-supplied + * up_romgetc(). The following mechanisms attempt to make these different + * access methods indistinguishable in the following code. + * + * NOTE: It is assumed that string arguments for %s still reside in memory + * that can be directly accessed by de-referencing the string pointer. + */ + +#ifdef CONFIG_ARCH_ROMGETC +# define FMT_TOP ch = up_romgetc(src) /* Loop initialization */ +# define FMT_BOTTOM src++, ch = up_romgetc(src) /* Bottom of a loop */ +# define FMT_CHAR ch /* Access a character */ +# define FMT_NEXT src++; ch = up_romgetc(src) /* Advance to the next character */ +# define FMT_PREV src--; ch = up_romgetc(src) /* Backup to the previous character */ +#else +# define FMT_TOP /* Loop initialization */ +# define FMT_BOTTOM src++ /* Bottom of a loop */ +# define FMT_CHAR *src /* Access a character */ +# define FMT_NEXT src++ /* Advance to the next character */ +# define FMT_PREV src-- /* Backup to the previous character */ +#endif + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +enum +{ + FMT_RJUST = 0, /* Default */ + FMT_LJUST, + FMT_RJUST0, + FMT_CENTER +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Pointer to ASCII conversion */ + +#ifdef CONFIG_PTR_IS_NOT_INT +static void ptohex(FAR struct lib_outstream_s *obj, uint8_t flags, FAR void *p); +#ifndef CONFIG_NOPRINTF_FIELDWIDTH +static int getsizesize(uint8_t fmt, uint8_t flags, FAR void *p) +#endif /* CONFIG_NOPRINTF_FIELDWIDTH */ +#endif /* CONFIG_PTR_IS_NOT_INT */ + +/* Unsigned int to ASCII conversion */ + +static void utodec(FAR struct lib_outstream_s *obj, unsigned int n); +static void utohex(FAR struct lib_outstream_s *obj, unsigned int n, uint8_t a); +static void utooct(FAR struct lib_outstream_s *obj, unsigned int n); +static void utobin(FAR struct lib_outstream_s *obj, unsigned int n); +static void utoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, + uint8_t flags, unsigned int lln); + +#ifndef CONFIG_NOPRINTF_FIELDWIDTH +static void fixup(uint8_t fmt, FAR uint8_t *flags, int *n); +static int getusize(uint8_t fmt, uint8_t flags, unsigned int lln); +#endif + +/* Unsigned long int to ASCII conversion */ + +#ifdef CONFIG_LONG_IS_NOT_INT +static void lutodec(FAR struct lib_outstream_s *obj, unsigned long ln); +static void lutohex(FAR struct lib_outstream_s *obj, unsigned long ln, uint8_t a); +static void lutooct(FAR struct lib_outstream_s *obj, unsigned long ln); +static void lutobin(FAR struct lib_outstream_s *obj, unsigned long ln); +static void lutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, + uint8_t flags, unsigned long ln); +#ifndef CONFIG_NOPRINTF_FIELDWIDTH +static void lfixup(uint8_t fmt, FAR uint8_t *flags, long *ln); +static int getlusize(uint8_t fmt, FAR uint8_t flags, unsigned long ln); +#endif +#endif + +/* Unsigned long long int to ASCII conversions */ + +#ifdef CONFIG_HAVE_LONG_LONG +static void llutodec(FAR struct lib_outstream_s *obj, unsigned long long lln); +static void llutohex(FAR struct lib_outstream_s *obj, unsigned long long lln, uint8_t a); +static void llutooct(FAR struct lib_outstream_s *obj, unsigned long long lln); +static void llutobin(FAR struct lib_outstream_s *obj, unsigned long long lln); +static void llutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, + uint8_t flags, unsigned long long lln); +#ifndef CONFIG_NOPRINTF_FIELDWIDTH +static void llfixup(uint8_t fmt, FAR uint8_t *flags, FAR long long *lln); +static int getllusize(uint8_t fmt, FAR uint8_t flags, FAR unsigned long long lln); +#endif +#endif + +#ifndef CONFIG_NOPRINTF_FIELDWIDTH +static void prejustify(FAR struct lib_outstream_s *obj, uint8_t fmt, + uint8_t flags, int fieldwidth, int numwidth); +static void postjustify(FAR struct lib_outstream_s *obj, uint8_t fmt, + uint8_t flags, int fieldwidth, int numwidth); +#endif + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +static const char g_nullstring[] = "(null)"; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Include floating point functions */ + +#ifdef CONFIG_LIBC_FLOATINGPOINT +# include "stdio/lib_libdtoa.c" +#endif + +/**************************************************************************** + * Name: ptohex + ****************************************************************************/ + +#ifdef CONFIG_PTR_IS_NOT_INT +static void ptohex(FAR struct lib_outstream_s *obj, uint8_t flags, FAR void *p) +{ + union + { + uint32_t dw; + FAR void *p; + } u; + uint8_t bits; + + /* Check for alternate form */ + + if (IS_ALTFORM(flags)) + { + /* Prefix the number with "0x" */ + + obj->put(obj, '0'); + obj->put(obj, 'x'); + } + + u.dw = 0; + u.p = p; + + for (bits = 8*sizeof(void *); bits > 0; bits -= 4) + { + uint8_t nibble = (uint8_t)((u.dw >> (bits - 4)) & 0xf); + if (nibble < 10) + { + obj->put(obj, nibble + '0'); + } + else + { + obj->put(obj, nibble + 'a' - 10); + } + } +} + +/**************************************************************************** + * Name: getpsize + ****************************************************************************/ + +#ifndef CONFIG_NOPRINTF_FIELDWIDTH +static int getpsize(uint8_t flags, FAR void *p) +{ + struct lib_outstream_s nulloutstream; + lib_nulloutstream(&nulloutstream); + + ptohex(&nulloutstream, flags, p); + return nulloutstream.nput; +} + +#endif /* CONFIG_NOPRINTF_FIELDWIDTH */ +#endif /* CONFIG_PTR_IS_NOT_INT */ + +/**************************************************************************** + * Name: utodec + ****************************************************************************/ + +static void utodec(FAR struct lib_outstream_s *obj, unsigned int n) +{ + unsigned int remainder = n % 10; + unsigned int dividend = n / 10; + + if (dividend) + { + utodec(obj, dividend); + } + + obj->put(obj, (remainder + (unsigned int)'0')); +} + +/**************************************************************************** + * Name: utohex + ****************************************************************************/ + +static void utohex(FAR struct lib_outstream_s *obj, unsigned int n, uint8_t a) +{ + bool nonzero = false; + uint8_t bits; + + for (bits = 8*sizeof(unsigned int); bits > 0; bits -= 4) + { + uint8_t nibble = (uint8_t)((n >> (bits - 4)) & 0xf); + if (nibble || nonzero) + { + nonzero = true; + + if (nibble < 10) + { + obj->put(obj, nibble + '0'); + } + else + { + obj->put(obj, nibble + a - 10); + } + } + } + + if (!nonzero) + { + obj->put(obj, '0'); + } +} + +/**************************************************************************** + * Name: utooct + ****************************************************************************/ + +static void utooct(FAR struct lib_outstream_s *obj, unsigned int n) +{ + unsigned int remainder = n & 0x7; + unsigned int dividend = n >> 3; + + if (dividend) + { + utooct(obj, dividend); + } + + obj->put(obj, (remainder + (unsigned int)'0')); +} + +/**************************************************************************** + * Name: utobin + ****************************************************************************/ + +static void utobin(FAR struct lib_outstream_s *obj, unsigned int n) +{ + unsigned int remainder = n & 1; + unsigned int dividend = n >> 1; + + if (dividend) + { + utobin(obj, dividend); + } + + obj->put(obj, (remainder + (unsigned int)'0')); +} + +/**************************************************************************** + * Name: utoascii + ****************************************************************************/ + +static void utoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, uint8_t flags, unsigned int n) +{ + /* Perform the integer conversion according to the format specifier */ + + switch (fmt) + { + case 'd': + case 'i': + /* Signed base 10 */ + { +#ifdef CONFIG_NOPRINTF_FIELDWIDTH + if ((int)n < 0) + { + obj->put(obj, '-'); + n = (unsigned int)(-(int)n); + } + else if (IS_SHOWPLUS(flags)) + { + obj->put(obj, '+'); + } +#endif + /* Convert the unsigned value to a string. */ + + utodec(obj, n); + } + break; + + case 'u': + /* Unigned base 10 */ + { +#ifdef CONFIG_NOPRINTF_FIELDWIDTH + if (IS_SHOWPLUS(flags)) + { + obj->put(obj, '+'); + } +#endif + /* Convert the unsigned value to a string. */ + + utodec(obj, n); + } + break; + +#ifndef CONFIG_PTR_IS_NOT_INT + case 'p': +#endif + case 'x': + case 'X': + /* Hexadecimal */ + { + /* Check for alternate form */ + + if (IS_ALTFORM(flags)) + { + /* Prefix the number with "0x" */ + + obj->put(obj, '0'); + obj->put(obj, 'x'); + } + + /* Convert the unsigned value to a string. */ + + if (fmt == 'X') + { + utohex(obj, n, 'A'); + } + else + { + utohex(obj, n, 'a'); + } + } + break; + + case 'o': + /* Octal */ + { + /* Check for alternate form */ + + if (IS_ALTFORM(flags)) + { + /* Prefix the number with '0' */ + + obj->put(obj, '0'); + } + + /* Convert the unsigned value to a string. */ + + utooct(obj, n); + } + break; + + case 'b': + /* Binary */ + { + /* Convert the unsigned value to a string. */ + + utobin(obj, n); + } + break; + +#ifdef CONFIG_PTR_IS_NOT_INT + case 'p': +#endif + default: + break; + } +} + +/**************************************************************************** + * Name: fixup + ****************************************************************************/ + +#ifndef CONFIG_NOPRINTF_FIELDWIDTH +static void fixup(uint8_t fmt, FAR uint8_t *flags, FAR int *n) +{ + /* Perform the integer conversion according to the format specifier */ + + switch (fmt) + { + case 'd': + case 'i': + /* Signed base 10 */ + + if (*n < 0) + { + SET_NEGATE(*flags); + CLR_SHOWPLUS(*flags); + *n = -*n; + } + break; + + case 'u': + /* Unsigned base 10 */ + break; + + case 'p': + case 'x': + case 'X': + /* Hexadecimal */ + case 'o': + /* Octal */ + case 'b': + /* Binary */ + CLR_SIGNED(*flags); + break; + + default: + break; + } +} + +/**************************************************************************** + * Name: getusize + ****************************************************************************/ + +static int getusize(uint8_t fmt, uint8_t flags, unsigned int n) +{ + struct lib_outstream_s nulloutstream; + lib_nulloutstream(&nulloutstream); + + utoascii(&nulloutstream, fmt, flags, n); + return nulloutstream.nput; +} + +/**************************************************************************** + * Name: getdblsize + ****************************************************************************/ + +#ifdef CONFIG_LIBC_FLOATINGPOINT +static int getdblsize(uint8_t fmt, int trunc, uint8_t flags, double n) +{ + struct lib_outstream_s nulloutstream; + lib_nulloutstream(&nulloutstream); + + lib_dtoa(&nulloutstream, fmt, trunc, flags, n); + return nulloutstream.nput; +} +#endif +#endif /* CONFIG_NOPRINTF_FIELDWIDTH */ + +#ifdef CONFIG_LONG_IS_NOT_INT +/**************************************************************************** + * Name: lutodec + ****************************************************************************/ + +static void lutodec(FAR struct lib_outstream_s *obj, unsigned long n) +{ + unsigned int remainder = n % 10; + unsigned long dividend = n / 10; + + if (dividend) + { + lutodec(obj, dividend); + } + + obj->put(obj, (remainder + (unsigned int)'0')); +} + +/**************************************************************************** + * Name: lutohex + ****************************************************************************/ + +static void lutohex(FAR struct lib_outstream_s *obj, unsigned long n, uint8_t a) +{ + bool nonzero = false; + uint8_t bits; + + for (bits = 8*sizeof(unsigned long); bits > 0; bits -= 4) + { + uint8_t nibble = (uint8_t)((n >> (bits - 4)) & 0xf); + if (nibble || nonzero) + { + nonzero = true; + + if (nibble < 10) + { + obj->put(obj, nibble + '0'); + } + else + { + obj->put(obj, nibble + a - 10); + } + } + } + + if (!nonzero) + { + obj->put(obj, '0'); + } +} + +/**************************************************************************** + * Name: lutooct + ****************************************************************************/ + +static void lutooct(FAR struct lib_outstream_s *obj, unsigned long n) +{ + unsigned int remainder = n & 0x7; + unsigned long dividend = n >> 3; + + if (dividend) + { + lutooct(obj, dividend); + } + + obj->put(obj, (remainder + (unsigned int)'0')); +} + +/**************************************************************************** + * Name: lutobin + ****************************************************************************/ + +static void lutobin(FAR struct lib_outstream_s *obj, unsigned long n) +{ + unsigned int remainder = n & 1; + unsigned long dividend = n >> 1; + + if (dividend) + { + lutobin(obj, dividend); + } + + obj->put(obj, (remainder + (unsigned int)'0')); +} + +/**************************************************************************** + * Name: lutoascii + ****************************************************************************/ + +static void lutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, uint8_t flags, unsigned long ln) +{ + /* Perform the integer conversion according to the format specifier */ + + switch (fmt) + { + case 'd': + case 'i': + /* Signed base 10 */ + { +#ifdef CONFIG_NOPRINTF_FIELDWIDTH + if ((long)ln < 0) + { + obj->put(obj, '-'); + ln = (unsigned long)(-(long)ln); + } + else if (IS_SHOWPLUS(flags)) + { + obj->put(obj, '+'); + } +#endif + /* Convert the unsigned value to a string. */ + + lutodec(obj, ln); + } + break; + + case 'u': + /* Unigned base 10 */ + { +#ifdef CONFIG_NOPRINTF_FIELDWIDTH + if (IS_SHOWPLUS(flags)) + { + obj->put(obj, '+'); + } +#endif + /* Convert the unsigned value to a string. */ + + lutodec(obj, ln); + } + break; + + case 'x': + case 'X': + /* Hexadecimal */ + { + /* Check for alternate form */ + + if (IS_ALTFORM(flags)) + { + /* Prefix the number with "0x" */ + + obj->put(obj, '0'); + obj->put(obj, 'x'); + } + + /* Convert the unsigned value to a string. */ + + if (fmt == 'X') + { + lutohex(obj, ln, 'A'); + } + else + { + lutohex(obj, ln, 'a'); + } + } + break; + + case 'o': + /* Octal */ + { + /* Check for alternate form */ + + if (IS_ALTFORM(flags)) + { + /* Prefix the number with '0' */ + + obj->put(obj, '0'); + } + + /* Convert the unsigned value to a string. */ + + lutooct(obj, ln); + } + break; + + case 'b': + /* Binary */ + { + /* Convert the unsigned value to a string. */ + + lutobin(obj, ln); + } + break; + + case 'p': + default: + break; + } +} + +/**************************************************************************** + * Name: lfixup + ****************************************************************************/ + +#ifndef CONFIG_NOPRINTF_FIELDWIDTH +static void lfixup(uint8_t fmt, FAR uint8_t *flags, FAR long *ln) +{ + /* Perform the integer conversion according to the format specifier */ + + switch (fmt) + { + case 'd': + case 'i': + /* Signed base 10 */ + + if (*ln < 0) + { + SET_NEGATE(*flags); + CLR_SHOWPLUS(*flags); + *ln = -*ln; + } + break; + + case 'u': + /* Unsigned base 10 */ + break; + + case 'p': + case 'x': + case 'X': + /* Hexadecimal */ + case 'o': + /* Octal */ + case 'b': + /* Binary */ + CLR_SIGNED(*flags); + break; + + default: + break; + } +} + +/**************************************************************************** + * Name: getlusize + ****************************************************************************/ + +static int getlusize(uint8_t fmt, uint8_t flags, unsigned long ln) +{ + struct lib_outstream_s nulloutstream; + lib_nulloutstream(&nulloutstream); + + lutoascii(&nulloutstream, fmt, flags, ln); + return nulloutstream.nput; +} + +#endif /* CONFIG_NOPRINTF_FIELDWIDTH */ +#endif /* CONFIG_LONG_IS_NOT_INT */ + +#ifdef CONFIG_HAVE_LONG_LONG +/**************************************************************************** + * Name: llutodec + ****************************************************************************/ + +static void llutodec(FAR struct lib_outstream_s *obj, unsigned long long n) +{ + unsigned int remainder = n % 10; + unsigned long long dividend = n / 10; + + if (dividend) + { + llutodec(obj, dividend); + } + + obj->put(obj, (remainder + (unsigned int)'0')); +} + +/**************************************************************************** + * Name: llutohex + ****************************************************************************/ + +static void llutohex(FAR struct lib_outstream_s *obj, unsigned long long n, uint8_t a) +{ + bool nonzero = false; + uint8_t bits; + + for (bits = 8*sizeof(unsigned long long); bits > 0; bits -= 4) + { + uint8_t nibble = (uint8_t)((n >> (bits - 4)) & 0xf); + if (nibble || nonzero) + { + nonzero = true; + + if (nibble < 10) + { + obj->put(obj, (nibble + '0')); + } + else + { + obj->put(obj, (nibble + a - 10)); + } + } + } + + if (!nonzero) + { + obj->put(obj, '0'); + } +} + +/**************************************************************************** + * Name: llutooct + ****************************************************************************/ + +static void llutooct(FAR struct lib_outstream_s *obj, unsigned long long n) +{ + unsigned int remainder = n & 0x7; + unsigned long long dividend = n >> 3; + + if (dividend) + { + llutooct(obj, dividend); + } + + obj->put(obj, (remainder + (unsigned int)'0')); +} + +/**************************************************************************** + * Name: llutobin + ****************************************************************************/ + +static void llutobin(FAR struct lib_outstream_s *obj, unsigned long long n) +{ + unsigned int remainder = n & 1; + unsigned long long dividend = n >> 1; + + if (dividend) + { + llutobin(obj, dividend); + } + + obj->put(obj, (remainder + (unsigned int)'0')); +} + +/**************************************************************************** + * Name: llutoascii + ****************************************************************************/ + +static void llutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, uint8_t flags, unsigned long long lln) +{ + /* Perform the integer conversion according to the format specifier */ + + switch (fmt) + { + case 'd': + case 'i': + /* Signed base 10 */ + { +#ifdef CONFIG_NOPRINTF_FIELDWIDTH + if ((long long)lln < 0) + { + obj->put(obj, '-'); + lln = (unsigned long long)(-(long long)lln); + } + else if (IS_SHOWPLUS(flags)) + { + obj->put(obj, '+'); + } +#endif + /* Convert the unsigned value to a string. */ + + llutodec(obj, (unsigned long long)lln); + } + break; + + case 'u': + /* Unigned base 10 */ + { +#ifdef CONFIG_NOPRINTF_FIELDWIDTH + if (IS_SHOWPLUS(flags)) + { + obj->put(obj, '+'); + } +#endif + /* Convert the unsigned value to a string. */ + + llutodec(obj, (unsigned long long)lln); + } + break; + + case 'x': + case 'X': + /* Hexadecimal */ + { + /* Check for alternate form */ + + if (IS_ALTFORM(flags)) + { + /* Prefix the number with "0x" */ + + obj->put(obj, '0'); + obj->put(obj, 'x'); + } + + /* Convert the unsigned value to a string. */ + + if (fmt == 'X') + { + llutohex(obj, (unsigned long long)lln, 'A'); + } + else + { + llutohex(obj, (unsigned long long)lln, 'a'); + } + } + break; + + case 'o': + /* Octal */ + { + /* Check for alternate form */ + + if (IS_ALTFORM(flags)) + { + /* Prefix the number with '0' */ + + obj->put(obj, '0'); + } + + /* Convert the unsigned value to a string. */ + + llutooct(obj, (unsigned long long)lln); + } + break; + + case 'b': + /* Binary */ + { + /* Convert the unsigned value to a string. */ + + llutobin(obj, (unsigned long long)lln); + } + break; + + case 'p': + default: + break; + } +} + +/**************************************************************************** + * Name: llfixup + ****************************************************************************/ + +#ifndef CONFIG_NOPRINTF_FIELDWIDTH +static void llfixup(uint8_t fmt, FAR uint8_t *flags, FAR long long *lln) +{ + /* Perform the integer conversion according to the format specifier */ + + switch (fmt) + { + case 'd': + case 'i': + /* Signed base 10 */ + + if (*lln < 0) + { + SET_NEGATE(*flags); + CLR_SHOWPLUS(*flags); + *lln = -*lln; + } + break; + + case 'u': + /* Unsigned base 10 */ + break; + + case 'p': + case 'x': + case 'X': + /* Hexadecimal */ + case 'o': + /* Octal */ + case 'b': + /* Binary */ + CLR_SIGNED(*flags); + break; + + default: + break; + } +} + +/**************************************************************************** + * Name: getllusize + ****************************************************************************/ + +static int getllusize(uint8_t fmt, uint8_t flags, unsigned long long lln) +{ + struct lib_outstream_s nulloutstream; + lib_nulloutstream(&nulloutstream); + + + llutoascii(&nulloutstream, fmt, flags, lln); + return nulloutstream.nput; +} + +#endif /* CONFIG_NOPRINTF_FIELDWIDTH */ +#endif /* CONFIG_HAVE_LONG_LONG */ + +/**************************************************************************** + * Name: prejustify + ****************************************************************************/ + +#ifndef CONFIG_NOPRINTF_FIELDWIDTH +static void prejustify(FAR struct lib_outstream_s *obj, uint8_t fmt, + uint8_t flags, int fieldwidth, int numwidth) +{ + int i; + + switch (fmt) + { + default: + case FMT_RJUST: + if (IS_SIGNED(flags)) + { + numwidth++; + } + + for (i = fieldwidth - numwidth; i > 0; i--) + { + obj->put(obj, ' '); + } + + if (IS_NEGATE(flags)) + { + obj->put(obj, '-'); + } + else if (IS_SHOWPLUS(flags)) + { + obj->put(obj, '+'); + } + break; + + case FMT_RJUST0: + if (IS_NEGATE(flags)) + { + obj->put(obj, '-'); + numwidth++; + } + else if (IS_SHOWPLUS(flags)) + { + obj->put(obj, '+'); + numwidth++; + } + + for (i = fieldwidth - numwidth; i > 0; i--) + { + obj->put(obj, '0'); + } + break; + + case FMT_LJUST: + if (IS_NEGATE(flags)) + { + obj->put(obj, '-'); + } + else if (IS_SHOWPLUS(flags)) + { + obj->put(obj, '+'); + } + break; + } +} +#endif + +/**************************************************************************** + * Name: postjustify + ****************************************************************************/ + +#ifndef CONFIG_NOPRINTF_FIELDWIDTH +static void postjustify(FAR struct lib_outstream_s *obj, uint8_t fmt, + uint8_t flags, int fieldwidth, int numwidth) +{ + int i; + + /* Apply field justification to the integer value. */ + + switch (fmt) + { + default: + case FMT_RJUST: + case FMT_RJUST0: + break; + + case FMT_LJUST: + if (IS_SIGNED(flags)) + { + numwidth++; + } + + for (i = fieldwidth - numwidth; i > 0; i--) + { + obj->put(obj, ' '); + } + break; + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * lib/stdio/lib_vsprintf + ****************************************************************************/ + +int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list ap) +{ + FAR char *ptmp; +#ifndef CONFIG_NOPRINTF_FIELDWIDTH + int width; + int trunc; + uint8_t fmt; +#endif + uint8_t flags; +#ifdef CONFIG_ARCH_ROMGETC + char ch; +#endif + + for (FMT_TOP; FMT_CHAR; FMT_BOTTOM) + { + /* Just copy regular characters */ + + if (FMT_CHAR != '%') + { + /* Output the character */ + + obj->put(obj, FMT_CHAR); + + /* Flush the buffer if a newline is encountered */ + +#ifdef CONFIG_STDIO_LINEBUFFER + if (FMT_CHAR == '\n') + { + /* Should return an error on a failure to flush */ + + (void)obj->flush(obj); + } +#endif + /* Process the next character in the format */ + + continue; + } + + /* We have found a format specifier. Move past it. */ + + FMT_NEXT; + + /* Assume defaults */ + + flags = 0; +#ifndef CONFIG_NOPRINTF_FIELDWIDTH + fmt = FMT_RJUST; + width = 0; + trunc = 0; +#endif + + /* Process each format qualifier. */ + + for (; FMT_CHAR; FMT_BOTTOM) + { + /* Break out of the loop when the format is known. */ + + if (strchr("diuxXpobeEfgGlLsc%", FMT_CHAR)) + { + break; + } + + /* Check for left justification. */ + + else if (FMT_CHAR == '-') + { +#ifndef CONFIG_NOPRINTF_FIELDWIDTH + fmt = FMT_LJUST; +#endif + } + + /* Check for leading zero fill right justification. */ + + else if (FMT_CHAR == '0') + { +#ifndef CONFIG_NOPRINTF_FIELDWIDTH + fmt = FMT_RJUST0; +#endif + } +#if 0 + /* Center justification. */ + + else if (FMT_CHAR == '~') + { +#ifndef CONFIG_NOPRINTF_FIELDWIDTH + fmt = FMT_CENTER; +#endif + } +#endif + + else if (FMT_CHAR == '*') + { +#ifndef CONFIG_NOPRINTF_FIELDWIDTH + int value = va_arg(ap, int); + if (IS_HASDOT(flags)) + { + trunc = value; + SET_HASASTERISKTRUNC(flags); + } + else + { + width = value; + SET_HASASTERISKWIDTH(flags); + } +#endif + } + + /* Check for field width */ + + else if (FMT_CHAR >= '1' && FMT_CHAR <= '9') + { +#ifdef CONFIG_NOPRINTF_FIELDWIDTH + do + { + FMT_NEXT; + } + while (FMT_CHAR >= '0' && FMT_CHAR <= '9'); +#else + /* Accumulate the field width integer. */ + + int n = ((int)(FMT_CHAR)) - (int)'0'; + for (;;) + { + FMT_NEXT; + if (FMT_CHAR >= '0' && FMT_CHAR <= '9') + { + n = 10*n + (((int)(FMT_CHAR)) - (int)'0'); + } + else + { + break; + } + } + + if (IS_HASDOT(flags)) + { + trunc = n; + } + else + { + width = n; + } +#endif + /* Back up to the last digit. */ + + FMT_PREV; + } + + /* Check for a decimal point. */ + + else if (FMT_CHAR == '.') + { +#ifndef CONFIG_NOPRINTF_FIELDWIDTH + SET_HASDOT(flags); +#endif + } + + /* Check for leading plus sign. */ + + else if (FMT_CHAR == '+') + { + SET_SHOWPLUS(flags); + } + + /* Check for alternate form. */ + + else if (FMT_CHAR == '#') + { + SET_ALTFORM(flags); + } + } + + /* "%%" means that a literal '%' was intended (instead of a format + * specification). + */ + + if (FMT_CHAR == '%') + { + obj->put(obj, '%'); + continue; + } + + /* Check for the string format. */ + + if (FMT_CHAR == 's') + { + /* Just concatenate the string into the output */ + + ptmp = va_arg(ap, char *); + if (!ptmp) + { + ptmp = (char*)g_nullstring; + } + + while(*ptmp) + { + obj->put(obj, *ptmp); + ptmp++; + } + continue; + } + + /* Check for the character output */ + + else if (FMT_CHAR == 'c') + { + /* Just copy the character into the output. */ + + int n = va_arg(ap, int); + obj->put(obj, n); + continue; + } + + /* Check for the long long prefix. */ + + if (FMT_CHAR == 'L') + { + SET_LONGLONGPRECISION(flags); + FMT_NEXT; + } + else if (FMT_CHAR == 'l') + { + SET_LONGPRECISION(flags); + FMT_NEXT; + if (FMT_CHAR == 'l') + { + SET_LONGLONGPRECISION(flags); + FMT_NEXT; + } + } + + /* Handle integer conversions */ + + if (strchr("diuxXpob", FMT_CHAR)) + { +#ifdef CONFIG_HAVE_LONG_LONG + if (IS_LONGLONGPRECISION(flags) && FMT_CHAR != 'p') + { + long long lln; +#ifndef CONFIG_NOPRINTF_FIELDWIDTH + int lluwidth; +#endif + /* Extract the long long value. */ + + lln = va_arg(ap, long long); + +#ifdef CONFIG_NOPRINTF_FIELDWIDTH + /* Output the number */ + + llutoascii(obj, FMT_CHAR, flags, (unsigned long long)lln); +#else + /* Resolve sign-ness and format issues */ + + llfixup(FMT_CHAR, &flags, &lln); + + /* Get the width of the output */ + + lluwidth = getllusize(FMT_CHAR, flags, lln); + + /* Perform left field justification actions */ + + prejustify(obj, fmt, flags, width, lluwidth); + + /* Output the number */ + + llutoascii(obj, FMT_CHAR, flags, (unsigned long long)lln); + + /* Perform right field justification actions */ + + postjustify(obj, fmt, flags, width, lluwidth); +#endif + } + else +#endif /* CONFIG_HAVE_LONG_LONG */ +#ifdef CONFIG_LONG_IS_NOT_INT + if (IS_LONGPRECISION(flags) && FMT_CHAR != 'p') + { + long ln; +#ifndef CONFIG_NOPRINTF_FIELDWIDTH + int luwidth; +#endif + /* Extract the long value. */ + + ln = va_arg(ap, long); + +#ifdef CONFIG_NOPRINTF_FIELDWIDTH + /* Output the number */ + + lutoascii(obj, FMT_CHAR, flags, (unsigned long)ln); +#else + /* Resolve sign-ness and format issues */ + + lfixup(FMT_CHAR, &flags, &ln); + + /* Get the width of the output */ + + luwidth = getlusize(FMT_CHAR, flags, ln); + + /* Perform left field justification actions */ + + prejustify(obj, fmt, flags, width, luwidth); + + /* Output the number */ + + lutoascii(obj, FMT_CHAR, flags, (unsigned long)ln); + + /* Perform right field justification actions */ + + postjustify(obj, fmt, flags, width, luwidth); +#endif + } + else +#endif /* CONFIG_LONG_IS_NOT_INT */ +#ifdef CONFIG_PTR_IS_NOT_INT + if (FMT_CHAR == 'p') + { + void *p; +#ifndef CONFIG_NOPRINTF_FIELDWIDTH + int pwidth; +#endif + /* Extract the integer value. */ + + p = va_arg(ap, void *); + +#ifdef CONFIG_NOPRINTF_FIELDWIDTH + /* Output the pointer value */ + + ptohex(obj, flags, p); +#else + /* Resolve sign-ness and format issues */ + + lfixup(FMT_CHAR, &flags, &ln); + + /* Get the width of the output */ + + luwidth = getpsize(FMT_CHAR, flags, p); + + /* Perform left field justification actions */ + + prejustify(obj, fmt, flags, width, pwidth); + + /* Output the pointer value */ + + ptohex(obj, flags, p); + + /* Perform right field justification actions */ + + postjustify(obj, fmt, flags, width, pwidth); +#endif + } + else +#endif + { + int n; +#ifndef CONFIG_NOPRINTF_FIELDWIDTH + int uwidth; +#endif + /* Extract the long long value. */ + + n = va_arg(ap, int); + +#ifdef CONFIG_NOPRINTF_FIELDWIDTH + /* Output the number */ + + utoascii(obj, FMT_CHAR, flags, (unsigned int)n); +#else + /* Resolve sign-ness and format issues */ + + fixup(FMT_CHAR, &flags, &n); + + /* Get the width of the output */ + + uwidth = getusize(FMT_CHAR, flags, n); + + /* Perform left field justification actions */ + + prejustify(obj, fmt, flags, width, uwidth); + + /* Output the number */ + + utoascii(obj, FMT_CHAR, flags, (unsigned int)n); + + /* Perform right field justification actions */ + + postjustify(obj, fmt, flags, width, uwidth); +#endif + } + } + + /* Handle floating point conversions */ + +#ifdef CONFIG_LIBC_FLOATINGPOINT + else if (strchr("eEfgG", FMT_CHAR)) + { +#ifndef CONFIG_NOPRINTF_FIELDWIDTH + double dblval = va_arg(ap, double); + int dblsize; + + /* Get the width of the output */ + + dblsize = getdblsize(FMT_CHAR, trunc, flags, dblval); + + /* Perform left field justification actions */ + + prejustify(obj, fmt, flags, width, dblsize); + + /* Output the number */ + + lib_dtoa(obj, FMT_CHAR, trunc, flags, dblval); + + /* Perform right field justification actions */ + + postjustify(obj, fmt, flags, width, dblsize); +#else + /* Output the number with a fixed precision */ + + double dblval = va_arg(ap, double); + lib_dtoa(obj, FMT_CHAR, CONFIG_LIBC_FIXEDPRECISION, flags, dblval); +#endif + } +#endif /* CONFIG_LIBC_FLOATINGPOINT */ + } + + return obj->nput; +} + + diff --git a/nuttx/lib/stdio/lib_lowinstream.c b/nuttx/lib/stdio/lib_lowinstream.c new file mode 100644 index 0000000000..6dcc4a37e6 --- /dev/null +++ b/nuttx/lib/stdio/lib_lowinstream.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * lib/stdio/lib_lowinstream.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_ARCH_LOWGETC + +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lowinstream_getc + ****************************************************************************/ + +static int lowinstream_getc(FAR struct lib_instream_s *this) +{ + if (this && up_getc(ch) != EOF) + { + this->nget++; + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_lowinstream + * + * Description: + * Initializes a stream for use with low-level, architecture-specific I/O. + * + * Input parameters: + * lowoutstream - User allocated, uninitialized instance of struct + * lib_lowoutstream_s to be initialized. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_lowinstream(FAR struct lib_instream_s *stream) +{ + stream->get = lowinstream_getc; + stream->nget = 0; +} + +#endif /* CONFIG_ARCH_LOWGETC */ diff --git a/nuttx/lib/stdio/lib_lowoutstream.c b/nuttx/lib/stdio/lib_lowoutstream.c new file mode 100644 index 0000000000..726bd84d7d --- /dev/null +++ b/nuttx/lib/stdio/lib_lowoutstream.c @@ -0,0 +1,94 @@ +/**************************************************************************** + * lib/stdio/lib_lowoutstream.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_ARCH_LOWPUTC + +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lowoutstream_putc + ****************************************************************************/ + +static void lowoutstream_putc(FAR struct lib_outstream_s *this, int ch) +{ + if (this && up_putc(ch) != EOF) + { + this->nput++; + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_lowoutstream + * + * Description: + * Initializes a stream for use with low-level, architecture-specific I/O. + * + * Input parameters: + * lowoutstream - User allocated, uninitialized instance of struct + * lib_lowoutstream_s to be initialized. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_lowoutstream(FAR struct lib_outstream_s *stream) +{ + stream->put = lowoutstream_putc; +#ifdef CONFIG_STDIO_LINEBUFFER + stream->flush = lib_noflush; +#endif + stream->nput = 0; +} + +#endif /* CONFIG_ARCH_LOWPUTC */ diff --git a/nuttx/lib/stdio/lib_lowprintf.c b/nuttx/lib/stdio/lib_lowprintf.c new file mode 100644 index 0000000000..392ef2c6a8 --- /dev/null +++ b/nuttx/lib/stdio/lib_lowprintf.c @@ -0,0 +1,128 @@ +/**************************************************************************** + * lib/stdio/lib_lowprintf.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include "lib_internal.h" + +/* This interface can only be used from within the kernel */ + +#if !defined(CONFIG_NUTTX_KERNEL) || defined(__KERNEL__) + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_lowvprintf + ****************************************************************************/ + +#if defined(CONFIG_ARCH_LOWPUTC) || defined(CONFIG_SYSLOG) + +int lib_lowvprintf(const char *fmt, va_list ap) +{ + struct lib_outstream_s stream; + + /* Wrap the stdout in a stream object and let lib_vsprintf do the work. */ + +#ifdef CONFIG_SYSLOG + lib_syslogstream((FAR struct lib_outstream_s *)&stream); +#else + lib_lowoutstream((FAR struct lib_outstream_s *)&stream); +#endif + return lib_vsprintf((FAR struct lib_outstream_s *)&stream, fmt, ap); +} + +/**************************************************************************** + * Name: lib_lowprintf + ****************************************************************************/ + +int lib_lowprintf(const char *fmt, ...) +{ + va_list ap; + int ret; + +#ifdef CONFIG_DEBUG_ENABLE + ret = 0; + if (g_dbgenable) +#endif + { + va_start(ap, fmt); + ret = lib_lowvprintf(fmt, ap); + va_end(ap); + } + + return ret; +} + +#endif /* CONFIG_ARCH_LOWPUTC || CONFIG_SYSLOG */ +#endif /* __KERNEL__ */ diff --git a/nuttx/lib/stdio/lib_meminstream.c b/nuttx/lib/stdio/lib_meminstream.c new file mode 100644 index 0000000000..839e562199 --- /dev/null +++ b/nuttx/lib/stdio/lib_meminstream.c @@ -0,0 +1,97 @@ +/**************************************************************************** + * lib/stdio/lib_meminstream.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: meminstream_getc + ****************************************************************************/ + +static int meminstream_getc(FAR struct lib_instream_s *this) +{ + FAR struct lib_meminstream_s *mthis = (FAR struct lib_meminstream_s *)this; + int ret; + + if (this && this->nget < mthis->buflen) + { + ret = mthis->buffer[this->nget]; + this->nget++; + } + else + { + ret = EOF; + } + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_meminstream + * + * Description: + * Initializes a stream for use with a fixed-size memory buffer. + * + * Input parameters: + * meminstream - User allocated, uninitialized instance of struct + * lib_meminstream_s to be initialized. + * bufstart - Address of the beginning of the fixed-size memory buffer + * buflen - Size of the fixed-sized memory buffer in bytes + * + * Returned Value: + * None (meminstream initialized). + * + ****************************************************************************/ + +void lib_meminstream(FAR struct lib_meminstream_s *meminstream, + FAR const char *bufstart, int buflen) +{ + meminstream->public.get = meminstream_getc; + meminstream->public.nget = 0; /* Will be buffer index */ + meminstream->buffer = bufstart; /* Start of buffer */ + meminstream->buflen = buflen; /* Length of the buffer */ +} + + diff --git a/nuttx/lib/stdio/lib_memoutstream.c b/nuttx/lib/stdio/lib_memoutstream.c new file mode 100644 index 0000000000..007ab89763 --- /dev/null +++ b/nuttx/lib/stdio/lib_memoutstream.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * lib/stdio/lib_memoutstream.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: memoutstream_putc + ****************************************************************************/ + +static void memoutstream_putc(FAR struct lib_outstream_s *this, int ch) +{ + FAR struct lib_memoutstream_s *mthis = (FAR struct lib_memoutstream_s *)this; + + /* If this will not overrun the buffer, then write the character to the + * buffer. Not that buflen was pre-decremented when the stream was + * created so it is okay to write past the end of the buflen by one. + */ + + if (this && this->nput < mthis->buflen) + { + mthis->buffer[this->nput] = ch; + this->nput++; + mthis->buffer[this->nput] = '\0'; + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_memoutstream + * + * Description: + * Initializes a stream for use with a fixed-size memory buffer. + * + * Input parameters: + * memoutstream - User allocated, uninitialized instance of struct + * lib_memoutstream_s to be initialized. + * bufstart - Address of the beginning of the fixed-size memory buffer + * buflen - Size of the fixed-sized memory buffer in bytes + * + * Returned Value: + * None (memoutstream initialized). + * + ****************************************************************************/ + +void lib_memoutstream(FAR struct lib_memoutstream_s *memoutstream, + FAR char *bufstart, int buflen) +{ + memoutstream->public.put = memoutstream_putc; +#ifdef CONFIG_STDIO_LINEBUFFER + memoutstream->public.flush = lib_noflush; +#endif + memoutstream->public.nput = 0; /* Will be buffer index */ + memoutstream->buffer = bufstart; /* Start of buffer */ + memoutstream->buflen = buflen - 1; /* Save space for null terminator */ + memoutstream->buffer[0] = '\0'; /* Start with an empty string */ +} + + diff --git a/nuttx/lib/stdio/lib_nullinstream.c b/nuttx/lib/stdio/lib_nullinstream.c new file mode 100644 index 0000000000..271cba396f --- /dev/null +++ b/nuttx/lib/stdio/lib_nullinstream.c @@ -0,0 +1,78 @@ +/**************************************************************************** + * lib/stdio/lib_nullinstream.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int nullinstream_getc(FAR struct lib_instream_s *this) +{ + return EOF; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_nullinstream + * + * Description: + * Initializes a NULL stream. The initialized stream will will return only + * EOF. + * + * Input parameters: + * nullinstream - User allocated, uninitialized instance of struct + * lib_instream_s to be initialized. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_nullinstream(FAR struct lib_instream_s *nullinstream) +{ + nullinstream->get = nullinstream_getc; + nullinstream->nget = 0; +} + diff --git a/nuttx/lib/stdio/lib_nulloutstream.c b/nuttx/lib/stdio/lib_nulloutstream.c new file mode 100644 index 0000000000..520df459ea --- /dev/null +++ b/nuttx/lib/stdio/lib_nulloutstream.c @@ -0,0 +1,81 @@ +/**************************************************************************** + * lib/stdio/lib_nulloutstream.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void nulloutstream_putc(FAR struct lib_outstream_s *this, int ch) +{ + this->nput++; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_nulloutstream + * + * Description: + * Initializes a NULL streams. The initialized stream will write all data + * to the bit-bucket. + * + * Input parameters: + * nulloutstream - User allocated, uninitialized instance of struct + * lib_outstream_s to be initialized. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_nulloutstream(FAR struct lib_outstream_s *nulloutstream) +{ + nulloutstream->put = nulloutstream_putc; +#ifdef CONFIG_STDIO_LINEBUFFER + nulloutstream->flush = lib_noflush; +#endif + nulloutstream->nput = 0; +} + diff --git a/nuttx/lib/stdio/lib_printf.c b/nuttx/lib/stdio/lib_printf.c new file mode 100644 index 0000000000..50db06c475 --- /dev/null +++ b/nuttx/lib/stdio/lib_printf.c @@ -0,0 +1,109 @@ +/**************************************************************************** + * lib/stdio/lib_printf.c + * + * Copyright (C) 2007-2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/************************************************************************** + * Global Constant Data + **************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/************************************************************************** + * Private Constant Data + **************************************************************************/ + +/**************************************************************************** + * Private Variables + **************************************************************************/ + +/**************************************************************************** + * Global Functions + **************************************************************************/ + +/**************************************************************************** + * Name: printf + **************************************************************************/ + +int printf(const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); +#if CONFIG_NFILE_STREAMS > 0 + ret = vfprintf(stdout, fmt, ap); +#elif CONFIG_NFILE_DESCRIPTORS > 0 + ret = lib_rawvprintf(fmt, ap); +#elif defined(CONFIG_ARCH_LOWPUTC) + ret = lib_lowvprintf(fmt, ap); +#else +# ifdef CONFIG_CPP_HAVE_WARNING +# warning "printf has no data sink" +# endif + ret = 0; +#endif + va_end(ap); + + return ret; +} + diff --git a/nuttx/lib/stdio/lib_puts.c b/nuttx/lib/stdio/lib_puts.c new file mode 100644 index 0000000000..e63a63917f --- /dev/null +++ b/nuttx/lib/stdio/lib_puts.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * lib/stdio/lib_puts.c + * + * Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: puts + * + * Description: + * puts() writes the string s and a trailing newline to stdout. + * + ****************************************************************************/ + +int puts(FAR const char *s) +{ + FILE *stream = stdout; + int nwritten; + int nput = EOF; + int ret; + + /* Write the string (the next two steps must be atomic) */ + + lib_take_semaphore(stream); + + /* Write the string without its trailing '\0' */ + + nwritten = fputs(s, stream); + if (nwritten > 0) + { + /* Followed by a newline */ + + char newline = '\n'; + ret = lib_fwrite(&newline, 1, stream); + if (ret > 0) + { + nput = nwritten + 1; + + /* Flush the buffer after the newline is output. */ + +#ifdef CONFIG_STDIO_LINEBUFFER + ret = lib_fflush(stream, true); + if (ret < 0) + { + nput = EOF; + } +#endif + } + } + + lib_give_semaphore(stdout); + return nput; +} + diff --git a/nuttx/lib/stdio/lib_rawinstream.c b/nuttx/lib/stdio/lib_rawinstream.c new file mode 100644 index 0000000000..ead3116b4f --- /dev/null +++ b/nuttx/lib/stdio/lib_rawinstream.c @@ -0,0 +1,102 @@ +/**************************************************************************** + * lib/stdio/lib_rawinstream.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rawinstream_getc + ****************************************************************************/ + +static int rawinstream_getc(FAR struct lib_instream_s *this) +{ + FAR struct lib_rawinstream_s *rthis = (FAR struct lib_rawinstream_s *)this; + char ch; + + if (this && rthis->fd >= 0) + { + int nwritten; + do + { + nwritten = read(rthis->fd, &ch, 1); + if (nwritten == 1) + { + this->nget++; + return ch; + } + } + while (nwritten < 0 && get_errno() == EINTR); + } + + return EOF; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_rawinstream + * + * Description: + * Initializes a stream for use with a file descriptor. + * + * Input parameters: + * rawinstream - User allocated, uninitialized instance of struct + * lib_rawinstream_s to be initialized. + * fd - User provided file/socket descriptor (must have been opened + * for the correct access). + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_rawinstream(FAR struct lib_rawinstream_s *rawinstream, int fd) +{ + rawinstream->public.get = rawinstream_getc; + rawinstream->public.nget = 0; + rawinstream->fd = fd; +} + diff --git a/nuttx/lib/stdio/lib_rawoutstream.c b/nuttx/lib/stdio/lib_rawoutstream.c new file mode 100644 index 0000000000..ce9d33280e --- /dev/null +++ b/nuttx/lib/stdio/lib_rawoutstream.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * lib/stdio/lib_rawoutstream.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rawoutstream_putc + ****************************************************************************/ + +static void rawoutstream_putc(FAR struct lib_outstream_s *this, int ch) +{ + FAR struct lib_rawoutstream_s *rthis = (FAR struct lib_rawoutstream_s *)this; + char buffer = ch; + if (this && rthis->fd >= 0) + { + int nwritten; + do + { + nwritten = write(rthis->fd, &buffer, 1); + if (nwritten == 1) + { + this->nput++; + } + } + while (nwritten < 0 && get_errno() == EINTR); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_rawoutstream + * + * Description: + * Initializes a stream for use with a file descriptor. + * + * Input parameters: + * rawoutstream - User allocated, uninitialized instance of struct + * lib_rawoutstream_s to be initialized. + * fd - User provided file/socket descriptor (must have been opened + * for write access). + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_rawoutstream(FAR struct lib_rawoutstream_s *rawoutstream, int fd) +{ + rawoutstream->public.put = rawoutstream_putc; +#ifdef CONFIG_STDIO_LINEBUFFER + rawoutstream->public.flush = lib_noflush; +#endif + rawoutstream->public.nput = 0; + rawoutstream->fd = fd; +} + diff --git a/nuttx/lib/stdio/lib_rawprintf.c b/nuttx/lib/stdio/lib_rawprintf.c new file mode 100644 index 0000000000..19dfa895e1 --- /dev/null +++ b/nuttx/lib/stdio/lib_rawprintf.c @@ -0,0 +1,151 @@ +/**************************************************************************** + * lib/stdio/lib_rawprintf.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Some output destinations are only available from within the kernel */ + +#if defined(CONFIG_NUTTX_KERNEL) && !defined(__KERNEL__) +# undef CONFIG_SYSLOG +# undef CONFIG_ARCH_LOWPUTC +#endif + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_rawvprintf + ****************************************************************************/ + +int lib_rawvprintf(const char *fmt, va_list ap) +{ +#if defined(CONFIG_SYSLOG) + + struct lib_outstream_s stream; + + /* Wrap the low-level output in a stream object and let lib_vsprintf + * do the work. + */ + + lib_syslogstream((FAR struct lib_outstream_s *)&stream); + return lib_vsprintf((FAR struct lib_outstream_s *)&stream, fmt, ap); + +#elif CONFIG_NFILE_DESCRIPTORS > 0 + + struct lib_rawoutstream_s rawoutstream; + + /* Wrap the stdout in a stream object and let lib_vsprintf + * do the work. + */ + + lib_rawoutstream(&rawoutstream, 1); + return lib_vsprintf(&rawoutstream.public, fmt, ap); + +#elif defined(CONFIG_ARCH_LOWPUTC) + + struct lib_outstream_s stream; + + /* Wrap the low-level output in a stream object and let lib_vsprintf + * do the work. + */ + + lib_lowoutstream((FAR struct lib_outstream_s *)&stream); + return lib_vsprintf((FAR struct lib_outstream_s *)&stream, fmt, ap); + +#else + return 0; +#endif +} + +/**************************************************************************** + * Name: lib_rawprintf + ****************************************************************************/ + +int lib_rawprintf(const char *fmt, ...) +{ + va_list ap; + int ret; + +#ifdef CONFIG_DEBUG_ENABLE + ret = 0; + if (g_dbgenable) +#endif + { + va_start(ap, fmt); + ret = lib_rawvprintf(fmt, ap); + va_end(ap); + } + + return ret; +} diff --git a/nuttx/lib/stdio/lib_rdflush.c b/nuttx/lib/stdio/lib_rdflush.c new file mode 100644 index 0000000000..948dcce5da --- /dev/null +++ b/nuttx/lib/stdio/lib_rdflush.c @@ -0,0 +1,144 @@ +/**************************************************************************** + * lib/stdio/lib_rdflush.c + * + * Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_rdflush + * + * Description: + * Flush read data from the I/O buffer and adjust the file pointer to + * account for the unread data + * + ****************************************************************************/ + +#if CONFIG_STDIO_BUFFER_SIZE > 0 +int lib_rdflush(FAR FILE *stream) +{ + if (!stream) + { + set_errno(EBADF); + return ERROR; + } + + /* Get exclusive access to the stream */ + + lib_take_semaphore(stream); + + /* If the buffer is currently being used for read access, then discard all + * of the read-ahead data. We do not support concurrent buffered read/write + * access. + */ + + if (stream->fs_bufread != stream->fs_bufstart) + { + /* Now adjust the stream pointer to account for the read-ahead data that + * was not actually read by the user. + */ + +#if CONFIG_NUNGET_CHARS > 0 + off_t rdoffset = stream->fs_bufread - stream->fs_bufpos + stream->fs_nungotten; +#else + off_t rdoffset = stream->fs_bufread - stream->fs_bufpos; +#endif + /* Mark the buffer as empty (do this before calling fseek() because fseek() + * also calls this function). + */ + + stream->fs_bufpos = stream->fs_bufread = stream->fs_bufstart; +#if CONFIG_NUNGET_CHARS > 0 + stream->fs_nungotten = 0; +#endif + /* Then seek to the position corresponding to the last data read by the user */ + + if (fseek(stream, -rdoffset, SEEK_CUR) < 0) + { + lib_give_semaphore(stream); + return ERROR; + } + } + + lib_give_semaphore(stream); + return OK; +} +#endif /* CONFIG_STDIO_BUFFER_SIZE */ + diff --git a/nuttx/lib/stdio/lib_snprintf.c b/nuttx/lib/stdio/lib_snprintf.c new file mode 100644 index 0000000000..a4dcd399bd --- /dev/null +++ b/nuttx/lib/stdio/lib_snprintf.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * lib/stdio/lib_snprintf.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * sprintf + ****************************************************************************/ + +int snprintf(FAR char *buf, size_t size, const char *format, ...) +{ + struct lib_memoutstream_s memoutstream; + va_list ap; + int n; + + /* Initialize a memory stream to write to the buffer */ + + lib_memoutstream((FAR struct lib_memoutstream_s *)&memoutstream, buf, size); + + /* Then let lib_vsprintf do the real work */ + + va_start(ap, format); + n = lib_vsprintf((FAR struct lib_outstream_s *)&memoutstream.public, format, ap); + va_end(ap); + return n; +} diff --git a/nuttx/lib/stdio/lib_sprintf.c b/nuttx/lib/stdio/lib_sprintf.c new file mode 100644 index 0000000000..6de019cc5f --- /dev/null +++ b/nuttx/lib/stdio/lib_sprintf.c @@ -0,0 +1,95 @@ +/**************************************************************************** + * lib/stdio/lib_sprintf.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * sprintf + ****************************************************************************/ + +int sprintf (FAR char *buf, const char *fmt, ...) +{ + struct lib_memoutstream_s memoutstream; + va_list ap; + int n; + + /* Initialize a memory stream to write to the buffer */ + + lib_memoutstream((FAR struct lib_memoutstream_s *)&memoutstream, buf, LIB_BUFLEN_UNKNOWN); + + /* Then let lib_vsprintf do the real work */ + + va_start(ap, fmt); + n = lib_vsprintf((FAR struct lib_outstream_s *)&memoutstream.public, fmt, ap); + va_end(ap); + return n; +} diff --git a/nuttx/lib/stdio/lib_sscanf.c b/nuttx/lib/stdio/lib_sscanf.c new file mode 100644 index 0000000000..3430aa0a02 --- /dev/null +++ b/nuttx/lib/stdio/lib_sscanf.c @@ -0,0 +1,390 @@ +/**************************************************************************** + * lib/stdio/lib_sscanf.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define MAXLN 128 + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +int vsscanf(char *buf, const char *s, va_list ap); + +/************************************************************************** + * Global Constant Data + **************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/************************************************************************** + * Private Constant Data + **************************************************************************/ + +static const char spaces[] = " \t\n\r\f\v"; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Function: sscanf + * + * Description: + * ANSI standard sscanf implementation. + * + ****************************************************************************/ + +int sscanf(const char *buf, const char *fmt, ...) +{ + va_list ap; + int count; + + va_start(ap, fmt); + count = vsscanf((char*)buf, fmt, ap); + va_end(ap); + return count; +} + +/**************************************************************************** + * Function: vsscanf + * + * Description: + * ANSI standard vsscanf implementation. + * + ****************************************************************************/ +int vsscanf(char *buf, const char *s, va_list ap) +{ + int count; + int noassign; + int width; + int base = 10; + int lflag; + char *tv; + const char *tc; + char tmp[MAXLN]; + + lvdbg("vsscanf: buf=\"%s\" fmt=\"%s\"\n", buf, s); + + count = noassign = width = lflag = 0; + while (*s && *buf) + { + /* Skip over white space */ + + while (isspace(*s)) + { + s++; + } + + /* Check for a conversion specifier */ + + if (*s == '%') + { + lvdbg("vsscanf: Specifier found\n"); + + /* Check for qualifiers on the conversion specifier */ + s++; + for (; *s; s++) + { + lvdbg("vsscanf: Processing %c\n", *s); + + if (strchr("dibouxcsefg%", *s)) + { + break; + } + + if (*s == '*') + { + noassign = 1; + } + else if (*s == 'l' || *s == 'L') + { + lflag = 1; + } + else if (*s >= '1' && *s <= '9') + { + for (tc = s; isdigit(*s); s++); + strncpy(tmp, tc, s - tc); + tmp[s - tc] = '\0'; + width = atoi(tmp); + s--; + } + } + + /* Process %s: String conversion */ + + if (*s == 's') + { + lvdbg("vsscanf: Performing string conversion\n"); + + while (isspace(*buf)) + { + buf++; + } + + if (!width) + { + width = strcspn(buf, spaces); + } + + if (!noassign) + { + tv = va_arg(ap, char*); + strncpy(tv, buf, width); + tv[width] = '\0'; + } + buf += width; + } + + /* Process %c: Character conversion */ + + else if (*s == 'c') + { + lvdbg("vsscanf: Performing character conversion\n"); + + if (!width) + { + width = 1; + } + + if (!noassign) + { + tv = va_arg(ap, char*); + strncpy(tv, buf, width); + tv[width] = '\0'; + } + buf += width; + } + + /* Process %d, %o, %b, %x, %u: Various integer conversions */ + + else if (strchr("dobxu", *s)) + { + lvdbg("vsscanf: Performing integer conversion\n"); + + /* Skip over any white space before the integer string */ + + while (isspace(*buf)) + { + buf++; + } + + /* The base of the integer conversion depends on the specific + * conversion specification. + */ + + if (*s == 'd' || *s == 'u') + { + base = 10; + } + else if (*s == 'x') + { + base = 16; + } + else if (*s == 'o') + { + base = 8; + } + else if (*s == 'b') + { + base = 2; + } + + /* Copy the integer string into a temporary working buffer. */ + + if (!width) + { + if (isspace(*(s + 1)) || *(s + 1) == 0) + { + width = strcspn(buf, spaces); + } + else + { + width = strchr(buf, *(s + 1)) - buf; + } + } + + strncpy(tmp, buf, width); + tmp[width] = '\0'; + + lvdbg("vsscanf: tmp[]=\"%s\"\n", tmp); + + /* Perform the integer conversion */ + + buf += width; + if (!noassign) + { + int *pint = va_arg(ap, int*); +#ifdef SDCC + char *endptr; + int tmpint = strtol(tmp, &endptr, base); +#else + int tmpint = strtol(tmp, NULL, base); +#endif + lvdbg("vsscanf: Return %d to 0x%p\n", tmpint, pint); + *pint = tmpint; + } + } + + /* Process %f: Floating point conversion */ + + else if (*s == 'f') + { +#ifndef CONFIG_LIBC_FLOATINGPOINT + /* No floating point conversions */ + + void *pv = va_arg(ap, void*); + + lvdbg("vsscanf: Return 0.0 to %p\n", pv); + *((double_t*)pv) = 0.0; +#else + lvdbg("vsscanf: Performing floating point conversion\n"); + + /* Skip over any white space before the real string */ + + while (isspace(*buf)) + { + buf++; + } + + /* Copy the real string into a temporary working buffer. */ + + if (!width) + { + if (isspace(*(s + 1)) || *(s + 1) == 0) + { + width = strcspn(buf, spaces); + } + else + { + width = strchr(buf, *(s + 1)) - buf; + } + } + + strncpy(tmp, buf, width); + tmp[width] = '\0'; + buf += width; + + lvdbg("vsscanf: tmp[]=\"%s\"\n", tmp); + + /* Perform the floating point conversion */ + + if (!noassign) + { + /* strtod always returns a double */ +#ifdef SDCC + char *endptr; + double_t dvalue = strtod(tmp,&endptr); +#else + double_t dvalue = strtod(tmp, NULL); +#endif + void *pv = va_arg(ap, void*); + + lvdbg("vsscanf: Return %f to %p\n", dvalue, pv); + + /* But we have to check whether we need to return a + * float or a double. + */ + +#ifdef CONFIG_HAVE_DOUBLE + if (lflag) + { + *((double_t*)pv) = dvalue; + } + else +#endif + { + *((float*)pv) = (float)dvalue; + } + } +#endif + } + + if (!noassign) + { + count++; + } + + width = noassign = lflag = 0; + s++; + } + + /* Its is not a conversion specifier */ + + else + { + while (isspace(*buf)) + { + buf++; + } + + if (*s != *buf) + { + break; + } + else + { + s++; + buf++; + } + } + } + + return count; +} diff --git a/nuttx/lib/stdio/lib_stdinstream.c b/nuttx/lib/stdio/lib_stdinstream.c new file mode 100644 index 0000000000..d89b6b63a0 --- /dev/null +++ b/nuttx/lib/stdio/lib_stdinstream.c @@ -0,0 +1,94 @@ +/**************************************************************************** + * lib/stdio/lib_stdinstream.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stdinstream_getc + ****************************************************************************/ + +static int stdinstream_getc(FAR struct lib_instream_s *this) +{ + FAR struct lib_stdinstream_s *sthis = (FAR struct lib_stdinstream_s *)this; + if (this) + { + int ret = getc(sthis->stream); + if (ret != EOF) + { + this->nget++; + } + return ret; + } + return EOF; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_stdinstream + * + * Description: + * Initializes a stream for use with a FILE instance. + * + * Input parameters: + * stdinstream - User allocated, uninitialized instance of struct + * lib_stdinstream_s to be initialized. + * stream - User provided stream instance (must have been opened for + * read access). + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_stdinstream(FAR struct lib_stdinstream_s *stdinstream, + FAR FILE *stream) +{ + stdinstream->public.get = stdinstream_getc; + stdinstream->public.nget = 0; + stdinstream->stream = stream; +} + + diff --git a/nuttx/lib/stdio/lib_stdoutstream.c b/nuttx/lib/stdio/lib_stdoutstream.c new file mode 100644 index 0000000000..12e78ce53f --- /dev/null +++ b/nuttx/lib/stdio/lib_stdoutstream.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * lib/stdio/lib_stdoutstream.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stdoutstream_putc + ****************************************************************************/ + +static void stdoutstream_putc(FAR struct lib_outstream_s *this, int ch) +{ + FAR struct lib_stdoutstream_s *sthis = (FAR struct lib_stdoutstream_s *)this; + if (this) + { + if (putc(ch, sthis->stream) != EOF) + { + this->nput++; + } + } +} + +/**************************************************************************** + * Name: stdoutstream_flush + ****************************************************************************/ + +#if defined(CONFIG_STDIO_LINEBUFFER) && CONFIG_STDIO_BUFFER_SIZE > 0 +int stdoutstream_flush(FAR struct lib_outstream_s *this) +{ + FAR struct lib_stdoutstream_s *sthis = (FAR struct lib_stdoutstream_s *)this; + return lib_fflush(sthis->stream, true); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_stdoutstream + * + * Description: + * Initializes a stream for use with a FILE instance. + * + * Input parameters: + * stdoutstream - User allocated, uninitialized instance of struct + * lib_stdoutstream_s to be initialized. + * stream - User provided stream instance (must have been opened for + * write access). + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_stdoutstream(FAR struct lib_stdoutstream_s *stdoutstream, + FAR FILE *stream) +{ + /* Select the put operation */ + + stdoutstream->public.put = stdoutstream_putc; + + /* Select the correct flush operation. This flush is only called when + * a newline is encountered in the output stream. However, we do not + * want to support this line buffering behavior if the stream was + * opened in binary mode. In binary mode, the newline has no special + * meaning. + */ + +#ifdef CONFIG_STDIO_LINEBUFFER +#if CONFIG_STDIO_BUFFER_SIZE > 0 + if ((stream->fs_oflags & O_BINARY) == 0) + { + stdoutstream->public.flush = stdoutstream_flush; + } + else +#endif + { + stdoutstream->public.flush = lib_noflush; + } +#endif + + /* Set the number of bytes put to zero and remember the stream */ + + stdoutstream->public.nput = 0; + stdoutstream->stream = stream; +} + + diff --git a/nuttx/lib/stdio/lib_syslogstream.c b/nuttx/lib/stdio/lib_syslogstream.c new file mode 100644 index 0000000000..20c6165ca9 --- /dev/null +++ b/nuttx/lib/stdio/lib_syslogstream.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * lib/stdio/lib_syslogstream.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "lib_internal.h" + +#ifdef CONFIG_SYSLOG + +/**************************************************************************** + * Pre-processor definition + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: syslogstream_putc + ****************************************************************************/ + +static void syslogstream_putc(FAR struct lib_outstream_s *this, int ch) +{ + /* Write the character to the supported logging device */ + + (void)syslog_putc(ch); + this->nput++; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_syslogstream + * + * Description: + * Initializes a stream for use with the configured syslog interface. + * + * Input parameters: + * lowoutstream - User allocated, uninitialized instance of struct + * lib_lowoutstream_s to be initialized. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_syslogstream(FAR struct lib_outstream_s *stream) +{ + stream->put = syslogstream_putc; +#ifdef CONFIG_STDIO_LINEBUFFER + stream->flush = lib_noflush; +#endif + stream->nput = 0; +} + +#endif /* CONFIG_SYSLOG */ + + diff --git a/nuttx/lib/stdio/lib_ungetc.c b/nuttx/lib/stdio/lib_ungetc.c new file mode 100644 index 0000000000..73e5917295 --- /dev/null +++ b/nuttx/lib/stdio/lib_ungetc.c @@ -0,0 +1,121 @@ +/**************************************************************************** + * lib/stdio/lib_ungetc.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include "lib_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/************************************************************************** + * Global Constant Data + **************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/************************************************************************** + * Private Constant Data + **************************************************************************/ + +/**************************************************************************** + * Private Variables + **************************************************************************/ + +/**************************************************************************** + * Public Functions + **************************************************************************/ + +/**************************************************************************** + * Name: ungetc + **************************************************************************/ + +int ungetc(int c, FAR FILE *stream) +{ +#if CONFIG_NUNGET_CHARS > 0 + int nungotten; +#endif + + /* Stream must be open for read access */ + + if ((stream && stream->fs_filedes < 0) || + ((stream->fs_oflags & O_RDOK) == 0)) + { + set_errno(EBADF); + return EOF; + } + +#if CONFIG_NUNGET_CHARS > 0 + nungotten = stream->fs_nungotten; + if (stream->fs_nungotten < CONFIG_NUNGET_CHARS) + { + stream->fs_ungotten[nungotten] = c; + stream->fs_nungotten = nungotten + 1; + return c; + } + else +#endif + { + set_errno(ENOMEM); + return EOF; + } +} + diff --git a/nuttx/lib/stdio/lib_vfprintf.c b/nuttx/lib/stdio/lib_vfprintf.c new file mode 100644 index 0000000000..25c3954c08 --- /dev/null +++ b/nuttx/lib/stdio/lib_vfprintf.c @@ -0,0 +1,102 @@ +/**************************************************************************** + * lib/stdio/lib_vfprintf.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int vfprintf(FAR FILE *stream, FAR const char *fmt, va_list ap) +{ + struct lib_stdoutstream_s stdoutstream; + int n = ERROR; + + if (stream) + { + /* Wrap the stream in a stream object and let lib_vsprintf + * do the work. + */ + + lib_stdoutstream(&stdoutstream, stream); + + /* Hold the stream semaphore throughout the lib_vsprintf + * call so that this thread can get its entire message out + * before being pre-empted by the next thread. + */ + + lib_take_semaphore(stream); + n = lib_vsprintf(&stdoutstream.public, fmt, ap); + lib_give_semaphore(stream); + } + return n; +} diff --git a/nuttx/lib/stdio/lib_vprintf.c b/nuttx/lib/stdio/lib_vprintf.c new file mode 100644 index 0000000000..a2e31fa052 --- /dev/null +++ b/nuttx/lib/stdio/lib_vprintf.c @@ -0,0 +1,92 @@ +/**************************************************************************** + * lib/stdio/lib_vprintf.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +/************************************************************************** + * Global Constant Data + **************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/************************************************************************** + * Private Constant Data + **************************************************************************/ + +/**************************************************************************** + * Private Variables + **************************************************************************/ + +/**************************************************************************** + * Public Functions + **************************************************************************/ + +/**************************************************************************** + * Name: vprintf + **************************************************************************/ + +int vprintf(FAR const char *fmt, va_list ap) +{ + /* vfprintf into stdout */ + + return vfprintf(stdout, fmt, ap); +} + diff --git a/nuttx/lib/stdio/lib_vsnprintf.c b/nuttx/lib/stdio/lib_vsnprintf.c new file mode 100644 index 0000000000..da885977c7 --- /dev/null +++ b/nuttx/lib/stdio/lib_vsnprintf.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * lib/stdio/lib_vsnprintf.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vsnprintf + ****************************************************************************/ + +int vsnprintf(FAR char *buf, size_t size, const char *format, va_list ap) +{ + struct lib_memoutstream_s memoutstream; + int n; + + /* Initialize a memory stream to write to the buffer */ + + lib_memoutstream((FAR struct lib_memoutstream_s *)&memoutstream, buf, size); + + /* Then let lib_vsprintf do the real work */ + + n = lib_vsprintf((FAR struct lib_outstream_s *)&memoutstream.public, format, ap); + return n; +} diff --git a/nuttx/lib/stdio/lib_vsprintf.c b/nuttx/lib/stdio/lib_vsprintf.c new file mode 100644 index 0000000000..72a829a794 --- /dev/null +++ b/nuttx/lib/stdio/lib_vsprintf.c @@ -0,0 +1,92 @@ +/**************************************************************************** + * lib/stdio/lib_vsprintf.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vsprintf + ****************************************************************************/ + +int vsprintf(FAR char *dest, const char *src, va_list ap) +{ + struct lib_memoutstream_s memoutstream; + + /* Wrap the destination buffer in a stream object and let + * lib/stdio/lib_vsprintf do the work. + */ + + lib_memoutstream((FAR struct lib_memoutstream_s *)&memoutstream, dest, LIB_BUFLEN_UNKNOWN); + return lib_vsprintf((FAR struct lib_outstream_s *)&memoutstream.public, src, ap); +} diff --git a/nuttx/lib/stdio/lib_wrflush.c b/nuttx/lib/stdio/lib_wrflush.c new file mode 100644 index 0000000000..c16109515b --- /dev/null +++ b/nuttx/lib/stdio/lib_wrflush.c @@ -0,0 +1,116 @@ +/**************************************************************************** + * lib/stdio/lib_wrflush.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_wrflush + * + * Description: + * This is simply a version of fflush that does not report an error if + * the file is not open for writing. + * + ****************************************************************************/ + +int lib_wrflush(FAR FILE *stream) +{ + /* Verify that we were passed a valid (i.e., non-NULL) stream */ + +#if CONFIG_STDIO_BUFFER_SIZE > 0 + if (stream) + { + /* Verify that the stream is opened for writing... lib_fflush will + * return an error if it is called for a stream that is not opened for + * writing. + */ + + if ((stream->fs_oflags & O_WROK) == 0 || + lib_fflush(stream, true) == 0) + { + /* Return success if there is no buffered write data -- i.e., that + * the stream is not opened for writing or, if it is, that all of + * the buffered write data was successfully flushed. + */ + + return OK; + } + } + return ERROR; +#else + return stream ? OK : ERROR; +#endif +} diff --git a/nuttx/lib/stdio/lib_zeroinstream.c b/nuttx/lib/stdio/lib_zeroinstream.c new file mode 100644 index 0000000000..27655b5475 --- /dev/null +++ b/nuttx/lib/stdio/lib_zeroinstream.c @@ -0,0 +1,79 @@ +/**************************************************************************** + * lib/stdio/lib_zeroinstream.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int zeroinstream_getc(FAR struct lib_instream_s *this) +{ + this->nget++; + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_zeroinstream + * + * Description: + * Initializes a NULL stream. The initialized stream will return an + * infinitely long stream of zeroes. + * + * Input parameters: + * zeroinstream - User allocated, uninitialized instance of struct + * lib_instream_s to be initialized. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_zeroinstream(FAR struct lib_instream_s *zeroinstream) +{ + zeroinstream->get = zeroinstream_getc; + zeroinstream->nget = 0; +} + diff --git a/nuttx/lib/stdlib/Make.defs b/nuttx/lib/stdlib/Make.defs new file mode 100644 index 0000000000..3119ecda45 --- /dev/null +++ b/nuttx/lib/stdlib/Make.defs @@ -0,0 +1,38 @@ +############################################################################ +# lib/stdlib/Make.defs +# +# Copyright (C) 2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +STDLIB_SRCS = lib_abs.c lib_abort.c lib_imaxabs.c lib_labs.c lib_llabs.c \ + lib_rand.c lib_qsort.c + diff --git a/nuttx/lib/stdlib/lib_abort.c b/nuttx/lib/stdlib/lib_abort.c new file mode 100644 index 0000000000..84b6009500 --- /dev/null +++ b/nuttx/lib/stdlib/lib_abort.c @@ -0,0 +1,121 @@ +/************************************************************************ + * lib/stdlib/lib_abort.c + * + * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: Abort + * + * Description: + * The abort() first unblocks the SIGABRT signal, and then raises that + * signal for the calling process. This results in the abnormal + * termination of the process unless the SIGABRT signal is caught and + * the signal handler does not return. + * + * If the abort() function causes process termination, all open + * streams are closed and flushed. + * + * If the SIGABRT signal is ignored, or caught by a handler that + * returns, the abort() function will still terminate the process. + * It does this by restoring the default disposition for SIGABRT and + * then raising the signal for a second time. + * + * Input parameters: + * None + * + * Returned Value: + * This function does not return, + * + ************************************************************************/ + +void abort(void) +{ + /* NuttX does not support standard signal functionality (like the + * behavior of the SIGABRT signal). So no attempt is made to provide + * a conformant version of abort() at this time. This version does not + * signal the calling thread all. + * + * Note that pthread_exit() is called instead of exit(). That is because + * we do no know if abort was called from a pthread or a normal thread + * (we could find out, of course). If abort() is called from a non-pthread, + * then pthread_exit() should fail and fall back to call exit() anyway. + * + * If exit() is called (either below or via pthread_exit()), then exit() + * will flush and close all open files and terminate the thread. If this + * function was called from a pthread, then pthread_exit() will complete + * any joins, but will not flush or close any streams. + */ + +#ifdef CONFIG_DISABLE_PTHREAD + exit(EXIT_FAILURE); +#else + pthread_exit(NULL); +#endif +} diff --git a/nuttx/lib/stdlib/lib_abs.c b/nuttx/lib/stdlib/lib_abs.c new file mode 100644 index 0000000000..5c805d8579 --- /dev/null +++ b/nuttx/lib/stdlib/lib_abs.c @@ -0,0 +1,54 @@ +/************************************************************************ + * lib/stdlib/lib_abs.c + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +/************************************************************************ + * Global Functions + ************************************************************************/ + +int abs(int j) +{ + if (j < 0) + { + j = -j; + } + return j; +} diff --git a/nuttx/lib/stdlib/lib_imaxabs.c b/nuttx/lib/stdlib/lib_imaxabs.c new file mode 100644 index 0000000000..d16791b268 --- /dev/null +++ b/nuttx/lib/stdlib/lib_imaxabs.c @@ -0,0 +1,54 @@ +/************************************************************************ + * lib/stdlib//lib_abs.c + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +/************************************************************************ + * Global Functions + ************************************************************************/ + +intmax_t imaxabs(intmax_t j) +{ + if (j < 0) + { + j = -j; + } + return j; +} diff --git a/nuttx/lib/stdlib/lib_labs.c b/nuttx/lib/stdlib/lib_labs.c new file mode 100644 index 0000000000..c9d9c19351 --- /dev/null +++ b/nuttx/lib/stdlib/lib_labs.c @@ -0,0 +1,54 @@ +/************************************************************************ + * lib/stdlib/lib_labs.c + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +/************************************************************************ + * Global Functions + ************************************************************************/ + +long int labs(long int j) +{ + if (j < 0) + { + j = -j; + } + return j; +} diff --git a/nuttx/lib/stdlib/lib_llabs.c b/nuttx/lib/stdlib/lib_llabs.c new file mode 100644 index 0000000000..24e26e9e11 --- /dev/null +++ b/nuttx/lib/stdlib/lib_llabs.c @@ -0,0 +1,57 @@ +/************************************************************************ + * lib/stdlib/lib_llabs.c + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include +#include + +/************************************************************************ + * Global Functions + ************************************************************************/ + +#ifdef CONFIG_HAVE_LONG_LONG +long long int llabs(long long int j) +{ + if (j < 0) + { + j = -j; + } + return j; +} +#endif diff --git a/nuttx/lib/stdlib/lib_qsort.c b/nuttx/lib/stdlib/lib_qsort.c new file mode 100644 index 0000000000..13bca7499a --- /dev/null +++ b/nuttx/lib/stdlib/lib_qsort.c @@ -0,0 +1,238 @@ +/**************************************************************************** + * lib/stdlib/lib_qsort.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Leveraged from: + * + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ + +#define min(a, b) (a) < (b) ? a : b + +#define swapcode(TYPE, parmi, parmj, n) \ + { \ + long i = (n) / sizeof (TYPE); \ + register TYPE *pi = (TYPE *) (parmi); \ + register TYPE *pj = (TYPE *) (parmj); \ + do { \ + register TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ + } + +#define SWAPINIT(a, size) \ + swaptype = ((char *)a - (char *)0) % sizeof(long) || \ + size % sizeof(long) ? 2 : size == sizeof(long)? 0 : 1; + +#define swap(a, b) \ + if (swaptype == 0) \ + { \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b); \ + *(long *)(b) = t; \ + } \ + else \ + { \ + swapfunc(a, b, size, swaptype); \ + } + +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static inline void swapfunc(char *a, char *b, int n, int swaptype); +static inline char *med3(char *a, char *b, char *c, + int (*compar)(const void *, const void *)); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline void swapfunc(char *a, char *b, int n, int swaptype) +{ + if(swaptype <= 1) + { + swapcode(long, a, b, n) + } + else + { + swapcode(char, a, b, n) + } +} + +static inline char *med3(char *a, char *b, char *c, + int (*compar)(const void *, const void *)) +{ + return compar(a, b) < 0 ? + (compar(b, c) < 0 ? b : (compar(a, c) < 0 ? c : a )) + :(compar(b, c) > 0 ? b : (compar(a, c) < 0 ? a : c )); +} + +/**************************************************************************** + * Public Function + ****************************************************************************/ + +/**************************************************************************** + * Name: qsort + * + * Description: + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". + * + ****************************************************************************/ + +void qsort(void *base, size_t nmemb, size_t size, + int(*compar)(const void *, const void *)) +{ + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; + int d, r, swaptype, swap_cnt; + +loop: + SWAPINIT(base, size); + swap_cnt = 0; + if (nmemb < 7) + { + for (pm = (char *) base + size; pm < (char *) base + nmemb * size; pm += size) + { + for (pl = pm; pl > (char *) base && compar(pl - size, pl) > 0; pl -= size) + { + swap(pl, pl - size); + } + } + return; + } + + pm = (char *) base + (nmemb / 2) * size; + if (nmemb > 7) + { + pl = base; + pn = (char *) base + (nmemb - 1) * size; + if (nmemb > 40) + { + d = (nmemb / 8) * size; + pl = med3(pl, pl + d, pl + 2 * d, compar); + pm = med3(pm - d, pm, pm + d, compar); + pn = med3(pn - 2 * d, pn - d, pn, compar); + } + pm = med3(pl, pm, pn, compar); + } + swap(base, pm); + pa = pb = (char *) base + size; + + pc = pd = (char *) base + (nmemb - 1) * size; + for (;;) + { + while (pb <= pc && (r = compar(pb, base)) <= 0) + { + if (r == 0) + { + swap_cnt = 1; + swap(pa, pb); + pa += size; + } + pb += size; + } + while (pb <= pc && (r = compar(pc, base)) >= 0) + { + if (r == 0) + { + swap_cnt = 1; + swap(pc, pd); + pd -= size; + } + pc -= size; + } + + if (pb > pc) + { + break; + } + + swap(pb, pc); + swap_cnt = 1; + pb += size; + pc -= size; + } + + if (swap_cnt == 0) + { + /* Switch to insertion sort */ + + for (pm = (char *) base + size; pm < (char *) base + nmemb * size; pm += size) + { + for (pl = pm; pl > (char *) base && compar(pl - size, pl) > 0; pl -= size) + { + swap(pl, pl - size); + } + } + return; + } + + pn = (char *) base + nmemb * size; + r = min(pa - (char *)base, pb - pa); + vecswap(base, pb - r, r); + r = min(pd - pc, pn - pd - size); + vecswap(pb, pn - r, r); + + if ((r = pb - pa) > size) + { + qsort(base, r / size, size, compar); + } + + if ((r = pd - pc) > size) + { + /* Iterate rather than recurse to save stack space */ + base = pn - r; + nmemb = r / size; + goto loop; + } +} + diff --git a/nuttx/lib/stdlib/lib_rand.c b/nuttx/lib/stdlib/lib_rand.c new file mode 100644 index 0000000000..537bc1aaee --- /dev/null +++ b/nuttx/lib/stdlib/lib_rand.c @@ -0,0 +1,220 @@ +/************************************************************ + * lib/stdlib/lib_rand.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include +#include + +/************************************************************ + * Definitions + ************************************************************/ + +#ifndef CONFIG_LIB_RAND_ORDER +#define CONFIG_LIB_RAND_ORDER 1 +#endif + +/* Values needed by the random number generator */ + +#define RND1_CONSTK 470001 +#define RND1_CONSTP 999563 +#define RND2_CONSTK1 366528 +#define RND2_CONSTK2 508531 +#define RND2_CONSTP 998917 +#define RND3_CONSTK1 360137 +#define RND3_CONSTK2 519815 +#define RND3_CONSTK3 616087 +#define RND3_CONSTP 997783 + +#if CONFIG_LIB_RAND_ORDER == 1 +# define RND_CONSTP RND1_CONSTP +#elif CONFIG_LIB_RAND_ORDER == 2 +# define RND_CONSTP RND2_CONSTP +#else +# define RND_CONSTP RND3_CONSTP +#endif + +/************************************************************ + * Private Type Declarations + ************************************************************/ + +/************************************************************ + * Private Function Prototypes + ************************************************************/ + +static unsigned int nrand(unsigned int nLimit); +static double_t frand1(void); +#if (CONFIG_LIB_RAND_ORDER > 1) +static double_t frand2(void); +#if (CONFIG_LIB_RAND_ORDER > 2) +static double_t frand3(void); +#endif +#endif + +/********************************************************** + * Global Constant Data + **********************************************************/ + +/************************************************************ + * Global Variables + ************************************************************/ + +/********************************************************** + * Private Constant Data + **********************************************************/ + +/************************************************************ + * Private Variables + ************************************************************/ + +static unsigned long g_nRandInt1; +#if (CONFIG_LIB_RAND_ORDER > 1) +static unsigned long g_nRandInt2; +#if (CONFIG_LIB_RAND_ORDER > 2) +static unsigned long g_nRandInt3; +#endif +#endif + +/************************************************************ + * Private Functions + ************************************************************/ + +static unsigned int nrand(unsigned int nLimit) +{ + unsigned long nResult; + double_t fRatio; + + /* Loop to be sure a legal random number is generated */ + do { + + /* Get a random integer in the requested range */ +#if (CONFIG_LIB_RAND_ORDER == 1) + fRatio = frand1(); +#elif (CONFIG_LIB_RAND_ORDER == 2) + fRatio = frand2(); +#else + fRatio = frand3(); +#endif + + /* Then, produce the return-able value */ + nResult = (unsigned long)(((double_t)nLimit) * fRatio); + + } while (nResult >= (unsigned long)nLimit); + + return (unsigned int)nResult; + +} /* end nrand */ + +static double_t frand1(void) +{ + unsigned long nRandInt; + + /* First order congruential generator */ + nRandInt = (RND1_CONSTK * g_nRandInt1) % RND1_CONSTP; + g_nRandInt1 = nRandInt; + + /* Construct an floating point value in the range from 0.0 up to 1.0 */ + return ((double_t)nRandInt) / ((double_t)RND_CONSTP); + +} /* end frand */ + +#if (CONFIG_LIB_RAND_ORDER > 1) +static double_t frand2(void) +{ + unsigned long nRandInt; + + /* Second order congruential generator */ + nRandInt = (RND2_CONSTK1 * g_nRandInt1 + RND2_CONSTK2 * g_nRandInt2) % + RND2_CONSTP; + g_nRandInt2 = g_nRandInt1; + g_nRandInt1 = nRandInt; + + /* Construct an floating point value in the range from 0.0 up to 1.0 */ + return ((double_t)nRandInt) / ((double_t)RND_CONSTP); + +} /* end frand */ + +#if (CONFIG_LIB_RAND_ORDER > 2) +static double_t frand3(void) +{ + unsigned long nRandInt; + + /* Third order congruential generator */ + nRandInt = (RND3_CONSTK1 * g_nRandInt1 + RND3_CONSTK2 * g_nRandInt2 + + RND3_CONSTK2 * g_nRandInt3) % RND3_CONSTP; + g_nRandInt3 = g_nRandInt2; + g_nRandInt2 = g_nRandInt1; + g_nRandInt1 = nRandInt; + + /* Construct an floating point value in the range from 0.0 up to 1.0 */ + return ((double_t)nRandInt) / ((double_t)RND_CONSTP); + +} /* end frand */ +#endif +#endif + +/************************************************************ + * Public Functions + ************************************************************/ +/************************************************************ + * Function: srand, rand + ************************************************************/ + +void srand(unsigned int seed) +{ + g_nRandInt1 = seed; +#if (CONFIG_LIB_RAND_ORDER > 1) + g_nRandInt2 = seed; + (void)frand1(); +#if (CONFIG_LIB_RAND_ORDER > 2) + g_nRandInt3 = seed; + (void)frand2(); +#endif +#endif + +} /* end srand */ + +int rand(void) +{ + return (int)nrand(32768); + +} /* end rand */ + diff --git a/nuttx/lib/string/Make.defs b/nuttx/lib/string/Make.defs new file mode 100644 index 0000000000..86fdaba027 --- /dev/null +++ b/nuttx/lib/string/Make.defs @@ -0,0 +1,43 @@ +############################################################################ +# lib/string/Make.defs +# +# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +STRING_SRCS = lib_checkbase.c lib_isbasedigit.c lib_memset.c lib_memchr.c \ + lib_memccpy.c lib_memcpy.c lib_memcmp.c lib_memmove.c lib_skipspace.c \ + lib_strcasecmp.c lib_strcat.c lib_strchr.c lib_strcpy.c lib_strcmp.c \ + lib_strcspn.c lib_strdup.c lib_strerror.c lib_strlen.c lib_strnlen.c \ + lib_strncasecmp.c lib_strncat.c lib_strncmp.c lib_strncpy.c \ + lib_strndup.c lib_strcasestr.c lib_strpbrk.c lib_strrchr.c\ + lib_strspn.c lib_strstr.c lib_strtok.c lib_strtokr.c lib_strtol.c \ + lib_strtoll.c lib_strtoul.c lib_strtoull.c lib_strtod.c diff --git a/nuttx/lib/string/lib_checkbase.c b/nuttx/lib/string/lib_checkbase.c new file mode 100644 index 0000000000..bec131b5c7 --- /dev/null +++ b/nuttx/lib/string/lib_checkbase.c @@ -0,0 +1,115 @@ +/**************************************************************************** + * lib/string/lib_checkbase.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_checkbase + * + * Description: + * This is part of the strol() family implementation. This function checks + * the initial part of a string to see if it can determine the numeric + * base that is represented. + * + * Assumptions: + * *ptr points to the first, non-whitespace character in the string. + * + ****************************************************************************/ + +int lib_checkbase(int base, const char **pptr) +{ + const char *ptr = *pptr; + + /* Check for unspecified base */ + + if (!base) + { + /* Assume base 10 */ + + base = 10; + + /* Check for leading '0' - that would signify octal or hex (or binary) */ + + if (*ptr == '0') + { + /* Assume octal */ + + base = 8; + ptr++; + + /* Check for hexidecimal */ + + if ((*ptr == 'X' || *ptr == 'x') && + lib_isbasedigit(ptr[1], 16, NULL)) + { + base = 16; + ptr++; + } + } + } + + /* If it a hexidecimal representation, than discard any leading "0X" or "0x" */ + + else if (base == 16) + { + if (ptr[0] == '0' && (ptr[1] == 'X' || ptr[1] == 'x')) + { + ptr += 2; + } + } + + /* Return the updated pointer and base */ + + *pptr = ptr; + return base; +} + diff --git a/nuttx/lib/string/lib_isbasedigit.c b/nuttx/lib/string/lib_isbasedigit.c new file mode 100644 index 0000000000..26426e8213 --- /dev/null +++ b/nuttx/lib/string/lib_isbasedigit.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * lib/string/lib_isbasedigit.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_isbasedigit + * + * Description: + * Given an ASCII character, ch, and a base (1-36) do two + * things: 1) Determine if ch is a valid charcter, and 2) + * convert ch to its binary value. + * + ****************************************************************************/ + +bool lib_isbasedigit(int ch, int base, int *value) +{ + bool ret = false; + int tmp = 0; + + if (base <= 10) + { + if (ch >= '0' && ch <= base + '0' - 1) + { + tmp = ch - '0'; + ret = true; + } + } + else if (base <= 36) + { + if (ch >= '0' && ch <= '9') + { + tmp = ch - '0'; + ret = true; + } + else if (ch >= 'a' && ch <= 'a' + base - 11) + { + tmp = ch - 'a' + 10; + ret = true; + } + else if (ch >= 'A' && ch <= 'A' + base - 11) + { + tmp = ch - 'A' + 10; + ret = true; + } + } + + if (value) + { + *value = tmp; + } + return ret; +} + + diff --git a/nuttx/lib/string/lib_memccpy.c b/nuttx/lib/string/lib_memccpy.c new file mode 100644 index 0000000000..1f3dbb52dd --- /dev/null +++ b/nuttx/lib/string/lib_memccpy.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * lib/string/lib_memccpy.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + + +/**************************************************************************** + * Name: memccpy + * + * Description: + * The memccpy() function copies bytes from memory area s2 into s1, + * stopping after the first occurrence of byte c (converted to an unsigned + * char) is copied, or after n bytes are copied, whichever comes first. If + * copying takes place between objects that overlap, the behavior is + * undefined. + * + * Returned Value: + * The memccpy() function returns a pointer to the byte after the copy of c + * in s1, or a null pointer if c was not found in the first n bytes of s2. + * + ****************************************************************************/ + +FAR void *memccpy(FAR void *s1, FAR const void *s2, int c, size_t n) +{ + FAR unsigned char *pout = (FAR unsigned char*)s1; + FAR unsigned char *pin = (FAR unsigned char*)s2; + + /* Copy at most n bytes */ + + while (n-- > 0) + { + /* Copy one byte */ + + *pout = *pin++; + + /* Did we just copy the terminating byte c? */ + + if (*pout == (unsigned char)c) + { + /* Yes return a pointer to the byte after the copy of c into s1 */ + + return (FAR void *)pout; + } + + /* No increment to the next destination location */ + + pout++; + } + + /* C was not found in the first n bytes of s2 */ + + return NULL; +} diff --git a/nuttx/lib/string/lib_memchr.c b/nuttx/lib/string/lib_memchr.c new file mode 100644 index 0000000000..e0dec82700 --- /dev/null +++ b/nuttx/lib/string/lib_memchr.c @@ -0,0 +1,80 @@ +/**************************************************************************** + * lib/string/lib_memchr.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: memchr + * + * Description: + * The memchr() function locates the first occurrence of 'c' (converted to + * an unsigned char) in the initial 'n' bytes (each interpreted as + * unsigned char) of the object pointed to by s. + * + * Returned Value: + * The memchr() function returns a pointer to the located byte, or a null + * pointer if the byte does not occur in the object. + * + ****************************************************************************/ + +FAR void *memchr(FAR const void *s, int c, size_t n) +{ + FAR const unsigned char *p = (FAR const unsigned char *)s; + + if (s) + { + while (n--) + { + if (*p == (unsigned char)c) + { + return (FAR void *)p; + } + + p++; + } + } + + return NULL; +} diff --git a/nuttx/lib/string/lib_memcmp.c b/nuttx/lib/string/lib_memcmp.c new file mode 100644 index 0000000000..cd874a85e4 --- /dev/null +++ b/nuttx/lib/string/lib_memcmp.c @@ -0,0 +1,74 @@ +/************************************************************ + * lib/string/lib_memcmp.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include +#include +#include + +/************************************************************ + * Global Functions + ************************************************************/ + +#ifndef CONFIG_ARCH_MEMCMP +int memcmp(const void *s1, const void *s2, size_t n) +{ + unsigned char *p1 = (unsigned char *)s1; + unsigned char *p2 = (unsigned char *)s2; + + while (n-- > 0) + { + if (*p1 < *p2) + { + return -1; + } + else if (*p1 > *p2) + { + return 1; + } + + p1++; + p2++; + } + return 0; +} +#endif diff --git a/nuttx/lib/string/lib_memcpy.c b/nuttx/lib/string/lib_memcpy.c new file mode 100644 index 0000000000..3b62edbabd --- /dev/null +++ b/nuttx/lib/string/lib_memcpy.c @@ -0,0 +1,64 @@ +/**************************************************************************** + * lib/string/lib_memcpy.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: memcpy + ****************************************************************************/ + +#ifndef CONFIG_ARCH_MEMCPY +FAR void *memcpy(FAR void *dest, FAR const void *src, size_t n) +{ + FAR unsigned char *pout = (FAR unsigned char*)dest; + FAR unsigned char *pin = (FAR unsigned char*)src; + while (n-- > 0) *pout++ = *pin++; + return dest; +} +#endif diff --git a/nuttx/lib/string/lib_memmove.c b/nuttx/lib/string/lib_memmove.c new file mode 100644 index 0000000000..97bac99ed9 --- /dev/null +++ b/nuttx/lib/string/lib_memmove.c @@ -0,0 +1,72 @@ +/************************************************************ + * lib/string/lib_memmove.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include +#include +#include + +/************************************************************ + * Global Functions + ************************************************************/ + +#ifndef CONFIG_ARCH_MEMMOVE +void *memmove(void *dest, const void *src, size_t count) +{ + char *tmp, *s; + if (dest <= src) + { + tmp = (char*) dest; + s = (char*) src; + while (count--) + *tmp++ = *s++; + } + else + { + tmp = (char*) dest + count; + s = (char*) src + count; + while (count--) + *--tmp = *--s; + } + return dest; +} +#endif diff --git a/nuttx/lib/string/lib_memset.c b/nuttx/lib/string/lib_memset.c new file mode 100644 index 0000000000..f3a5497a9a --- /dev/null +++ b/nuttx/lib/string/lib_memset.c @@ -0,0 +1,59 @@ +/************************************************************ + * lib/string/lib_memset.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include +#include +#include + +/************************************************************ + * Global Functions + ************************************************************/ + +#ifndef CONFIG_ARCH_MEMSET +void *memset(void *s, int c, size_t n) +{ + unsigned char *p = (unsigned char*)s; + while (n-- > 0) *p++ = c; + return s; +} +#endif diff --git a/nuttx/lib/string/lib_skipspace.c b/nuttx/lib/string/lib_skipspace.c new file mode 100644 index 0000000000..826559efed --- /dev/null +++ b/nuttx/lib/string/lib_skipspace.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * lib/string/lib_skipspace.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_skipspace + * + * Description: + * Skip over leading whitespace + * + ****************************************************************************/ + +void lib_skipspace(const char **pptr) +{ + const char *ptr = *pptr; + while (isspace(*ptr)) ptr++; + *pptr = ptr; +} + + diff --git a/nuttx/lib/string/lib_strcasecmp.c b/nuttx/lib/string/lib_strcasecmp.c new file mode 100644 index 0000000000..ed5217831f --- /dev/null +++ b/nuttx/lib/string/lib_strcasecmp.c @@ -0,0 +1,65 @@ +/**************************************************************************** + * lib/string/lib_strcasecmp.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/**************************************************************************** + * Included Files + *****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Public Functions + *****************************************************************************/ + +#ifndef CONFIG_ARCH_STRCMP +int strcasecmp(const char *cs, const char *ct) +{ + int result; + for (;;) + { + if ((result = (int)toupper(*cs) - (int)toupper(*ct)) != 0 || !*cs) + { + break; + } + + cs++; + ct++; + } + return result; +} +#endif diff --git a/nuttx/lib/string/lib_strcasestr.c b/nuttx/lib/string/lib_strcasestr.c new file mode 100644 index 0000000000..23f0ab57e6 --- /dev/null +++ b/nuttx/lib/string/lib_strcasestr.c @@ -0,0 +1,134 @@ +/**************************************************************************** + * lib/string/lib_strstr.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use str source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions str binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer str + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static FAR char *strcasechr(FAR const char *s, int uc) +{ + register char ch; + + if (s) + { + for (; *s; s++) + { + ch = *s; + if (toupper(ch) == uc) + { + return (FAR char*)s; + } + } + } + + return NULL; +} + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +FAR char *strcasestr(FAR const char *str, FAR const char *substr) +{ + const char *candidate; /* Candidate in str with matching start character */ + char ch; /* First character of the substring */ + int len; /* The length of the substring */ + + /* Special case the empty substring */ + + len = strlen(substr); + ch = *substr; + + if (!ch) + { + /* We'll say that an empty substring matches at the beginning of + * the string + */ + + return (char*)str; + } + + /* Search for the substring */ + + candidate = str; + ch = toupper(ch); + + for (;;) + { + /* strcasechr() will return a pointer to the next occurrence of the + * character ch in the string (ignoring case) + */ + + candidate = strcasechr(candidate, ch); + if (!candidate || strlen(candidate) < len) + { + /* First character of the substring does not appear in the string + * or the remainder of the string is not long enough to contain the + * substring. + */ + + return NULL; + } + + /* Check if this is the beginning of a matching substring (ignoring case) */ + + if (strncasecmp(candidate, substr, len) == 0) + { + /* Yes.. return the pointer to the first occurrence of the matching + * substring. + */ + + return (char*)candidate; + } + + /* No, find the next candidate after this one */ + + candidate++; + } + + /* Won't get here, but some compilers might complain */ + + return NULL; +} + diff --git a/nuttx/lib/string/lib_strcat.c b/nuttx/lib/string/lib_strcat.c new file mode 100644 index 0000000000..2d12dd5a64 --- /dev/null +++ b/nuttx/lib/string/lib_strcat.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * lib/string/lib_strcat.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +#ifndef CONFIG_ARCH_STRCAT +char *strcat(char *dest, const char *src) +{ + char *ret = dest; + + dest += strlen(dest); + while (*src != '\0') + { + *dest++ = *src++; + } + *dest = '\0'; + + return ret; +} +#endif diff --git a/nuttx/lib/string/lib_strchr.c b/nuttx/lib/string/lib_strchr.c new file mode 100644 index 0000000000..ad72738620 --- /dev/null +++ b/nuttx/lib/string/lib_strchr.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * lib/string/lib_strchr.c + * + * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: strchr + * + * Description: + * The strchr() function locates the first occurrence of 'c' (converted to + * a char) in the string pointed to by 's'. The terminating null byte is + * considered to be part of the string. + * + * Returned Value: + * Upon completion, strchr() returns a pointer to the byte, or a null + * pointer if the byte was not found. + * + ****************************************************************************/ + +FAR char *strchr(FAR const char *s, int c) +{ + if (s) + { + for (; *s; s++) + { + if (*s == c) + { + return (FAR char *)s; + } + } + } + + return NULL; +} diff --git a/nuttx/lib/string/lib_strcmp.c b/nuttx/lib/string/lib_strcmp.c new file mode 100644 index 0000000000..1d78cb0495 --- /dev/null +++ b/nuttx/lib/string/lib_strcmp.c @@ -0,0 +1,59 @@ +/**************************************************************************** + * lib/string/lib_strcmp.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/**************************************************************************** + * Included Files + *****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Public Functions + *****************************************************************************/ + +#ifndef CONFIG_ARCH_STRCMP +int strcmp(const char *cs, const char *ct) +{ + register signed char result; + for (;;) + { + if ((result = *cs - *ct++) != 0 || !*cs++) + break; + } + return result; +} +#endif diff --git a/nuttx/lib/string/lib_strcpy.c b/nuttx/lib/string/lib_strcpy.c new file mode 100644 index 0000000000..774e155347 --- /dev/null +++ b/nuttx/lib/string/lib_strcpy.c @@ -0,0 +1,55 @@ +/************************************************************************ + * lib/string/lib_strcpy.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +/************************************************************************ + * Global Functions + ************************************************************************/ + +#ifndef CONFIG_ARCH_STRCPY +char *strcpy(char *dest, const char *src) +{ + char *tmp = dest; + while ((*dest++ = *src++) != '\0'); + return tmp; +} +#endif diff --git a/nuttx/lib/string/lib_strcspn.c b/nuttx/lib/string/lib_strcspn.c new file mode 100644 index 0000000000..b28f223431 --- /dev/null +++ b/nuttx/lib/string/lib_strcspn.c @@ -0,0 +1,67 @@ +/**************************************************************************** + * lib/string/lib_strcspn.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: strcspn + * + * Description: + * strspn() calculates the length of the initial segment of s which + * consists entirely of characters not in reject + * + ****************************************************************************/ + +size_t strcspn(const char *s, const char *reject) +{ + size_t i; + for (i = 0; s[i] && strchr(reject, s[i]) == NULL; i++); + return i; +} + diff --git a/nuttx/lib/string/lib_strdup.c b/nuttx/lib/string/lib_strdup.c new file mode 100644 index 0000000000..a353c629da --- /dev/null +++ b/nuttx/lib/string/lib_strdup.c @@ -0,0 +1,62 @@ +/************************************************************************ + * lib/string//lib_strdup.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +#include "lib_internal.h" + +/************************************************************************ + * Global Functions + ************************************************************************/ + +FAR char *strdup(const char *s) +{ + FAR char *news = NULL; + if (s) + { + news = (FAR char*)lib_malloc(strlen(s) + 1); + if (news) + { + strcpy(news, s); + } + } + return news; +} diff --git a/nuttx/lib/string/lib_strerror.c b/nuttx/lib/string/lib_strerror.c new file mode 100644 index 0000000000..580974fa6c --- /dev/null +++ b/nuttx/lib/string/lib_strerror.c @@ -0,0 +1,237 @@ +/************************************************************************ + * lib/string/lib_strerror.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Types + ************************************************************************/ + +struct errno_strmap_s +{ + uint8_t errnum; + const char *str; +}; + +/************************************************************************ + * Private Data + ************************************************************************/ + +/* This table maps all error numbers to descriptive strings. + * The only assumption that the code makes with regard to this + * this table is that it is ordered by error number. + * + * The size of this table is quite large. Its size can be + * reduced by eliminating some of the more obscure error + * strings. + */ + +static const struct errno_strmap_s g_errnomap[] = +{ + { EPERM, EPERM_STR }, + { ENOENT, ENOENT_STR }, + { ESRCH, ESRCH_STR }, + { EINTR, EINTR_STR }, + { EIO, EIO_STR }, + { ENXIO, ENXIO_STR }, + { E2BIG, E2BIG_STR }, + { ENOEXEC, ENOEXEC_STR }, + { EBADF, EBADF_STR }, + { ECHILD, ECHILD_STR }, + { EAGAIN, EAGAIN_STR }, + { ENOMEM, ENOMEM_STR }, + { EACCES, EACCES_STR }, + { EFAULT, EFAULT_STR }, + { ENOTBLK, ENOTBLK_STR }, + { EBUSY, EBUSY_STR }, + { EEXIST, EEXIST_STR }, + { EXDEV, EXDEV_STR }, + { ENODEV, ENODEV_STR }, + { ENOTDIR, ENOTDIR_STR }, + { EISDIR, EISDIR_STR }, + { EINVAL, EINVAL_STR }, + { ENFILE, ENFILE_STR }, + { EMFILE, EMFILE_STR }, + { ENOTTY, ENOTTY_STR }, + { ETXTBSY, ETXTBSY_STR }, + { EFBIG, EFBIG_STR }, + { ENOSPC, ENOSPC_STR }, + { ESPIPE, ESPIPE_STR }, + { EROFS, EROFS_STR }, + { EMLINK, EMLINK_STR }, + { EPIPE, EPIPE_STR }, + { EDOM, EDOM_STR }, + { ERANGE, ERANGE_STR }, + { EDEADLK, EDEADLK_STR }, + { ENAMETOOLONG, ENAMETOOLONG_STR }, + { ENOLCK, ENOLCK_STR }, + { ENOSYS, ENOSYS_STR }, + { ENOTEMPTY, ENOTEMPTY_STR }, + { ELOOP, ELOOP_STR }, + { ENOMSG, ENOMSG_STR }, + { EIDRM, EIDRM_STR }, + { ECHRNG, ECHRNG_STR }, + { EL2NSYNC, EL2NSYNC_STR }, + { EL3HLT, EL3HLT_STR }, + { EL3RST, EL3RST_STR }, + { ELNRNG, ELNRNG_STR }, + { EUNATCH, EUNATCH_STR }, + { ENOCSI, ENOCSI_STR }, + { EL2HLT, EL2HLT_STR }, + { EBADE, EBADE_STR }, + { EBADR, EBADR_STR }, + { EXFULL, EXFULL_STR }, + { ENOANO, ENOANO_STR }, + { EBADRQC, EBADRQC_STR }, + { EBADSLT, EBADSLT_STR }, + { EBFONT, EBFONT_STR }, + { ENOSTR, ENOSTR_STR }, + { ENODATA, ENODATA_STR }, + { ETIME, ETIME_STR }, + { ENOSR, ENOSR_STR }, + { ENONET, ENONET_STR }, + { ENOPKG, ENOPKG_STR }, + { EREMOTE, EREMOTE_STR }, + { ENOLINK, ENOLINK_STR }, + { EADV, EADV_STR }, + { ESRMNT, ESRMNT_STR }, + { ECOMM, ECOMM_STR }, + { EPROTO, EPROTO_STR }, + { EMULTIHOP, EMULTIHOP_STR }, + { EDOTDOT, EDOTDOT_STR }, + { EBADMSG, EBADMSG_STR }, + { EOVERFLOW, EOVERFLOW_STR }, + { ENOTUNIQ, ENOTUNIQ_STR }, + { EBADFD, EBADFD_STR }, + { EREMCHG, EREMCHG_STR }, + { ELIBACC, ELIBACC_STR }, + { ELIBBAD, ELIBBAD_STR }, + { ELIBSCN, ELIBSCN_STR }, + { ELIBMAX, ELIBMAX_STR }, + { ELIBEXEC, ELIBEXEC_STR }, + { EILSEQ, EILSEQ_STR }, + { ERESTART, ERESTART_STR }, + { ESTRPIPE, ESTRPIPE_STR }, + { EUSERS, EUSERS_STR }, + { ENOTSOCK, ENOTSOCK_STR }, + { EDESTADDRREQ, EDESTADDRREQ_STR }, + { EMSGSIZE, EMSGSIZE_STR }, + { EPROTOTYPE, EPROTOTYPE_STR }, + { ENOPROTOOPT, ENOPROTOOPT_STR }, + { EPROTONOSUPPORT, EPROTONOSUPPORT_STR }, + { ESOCKTNOSUPPORT, ESOCKTNOSUPPORT_STR }, + { EOPNOTSUPP, EOPNOTSUPP_STR }, + { EPFNOSUPPORT, EPFNOSUPPORT_STR }, + { EAFNOSUPPORT, EAFNOSUPPORT_STR }, + { EADDRINUSE, EADDRINUSE_STR }, + { EADDRNOTAVAIL, EADDRNOTAVAIL_STR }, + { ENETDOWN, ENETDOWN_STR }, + { ENETUNREACH, ENETUNREACH_STR }, + { ENETRESET, ENETRESET_STR }, + { ECONNABORTED, ECONNABORTED_STR }, + { ECONNRESET, ECONNRESET_STR }, + { ENOBUFS, ENOBUFS_STR }, + { EISCONN, EISCONN_STR }, + { ENOTCONN, ENOTCONN_STR }, + { ESHUTDOWN, ESHUTDOWN_STR }, + { ETOOMANYREFS, ETOOMANYREFS_STR }, + { ETIMEDOUT, ETIMEDOUT_STR }, + { ECONNREFUSED, ECONNREFUSED_STR }, + { EHOSTDOWN, EHOSTDOWN_STR }, + { EHOSTUNREACH, EHOSTUNREACH_STR }, + { EALREADY, EALREADY_STR }, + { EINPROGRESS, EINPROGRESS_STR }, + { ESTALE, ESTALE_STR }, + { EUCLEAN, EUCLEAN_STR }, + { ENOTNAM, ENOTNAM_STR }, + { ENAVAIL, ENAVAIL_STR }, + { EISNAM, EISNAM_STR }, + { EREMOTEIO, EREMOTEIO_STR }, + { EDQUOT, EDQUOT_STR }, + { ENOMEDIUM, ENOMEDIUM_STR }, + { EMEDIUMTYPE, EMEDIUMTYPE_STR } +}; + +#define NERRNO_STRS (sizeof(g_errnomap) / sizeof(struct errno_strmap_s)) + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: strerror + ************************************************************************/ + +const char *strerror(int errnum) +{ + int ndxlow = 0; + int ndxhi = NERRNO_STRS - 1; + int ndxmid; + + do + { + ndxmid = (ndxlow + ndxhi) >> 1; + if (errnum > g_errnomap[ndxmid].errnum) + { + ndxlow = ndxmid + 1; + } + else if (errnum < g_errnomap[ndxmid].errnum) + { + ndxhi = ndxmid - 1; + } + else + { + return g_errnomap[ndxmid].str; + } + } + while (ndxlow <= ndxhi); + return "Unknown error"; +} diff --git a/nuttx/lib/string/lib_strlen.c b/nuttx/lib/string/lib_strlen.c new file mode 100644 index 0000000000..ee964c1371 --- /dev/null +++ b/nuttx/lib/string/lib_strlen.c @@ -0,0 +1,55 @@ +/**************************************************************************** + * lib/string/lib_strlen.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +#ifndef CONFIG_ARCH_STRLEN +size_t strlen(const char *s) +{ + const char *sc; + for (sc = s; *sc != '\0'; ++sc); + return sc - s; +} +#endif diff --git a/nuttx/lib/string/lib_strncasecmp.c b/nuttx/lib/string/lib_strncasecmp.c new file mode 100644 index 0000000000..78b18a3fb8 --- /dev/null +++ b/nuttx/lib/string/lib_strncasecmp.c @@ -0,0 +1,70 @@ +/**************************************************************************** + * lib/string/lib_strncasecmp.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + *****************************************************************************/ + +/**************************************************************************** + * Included Files + *****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Global Functions + *****************************************************************************/ + +#ifndef CONFIG_ARCH_STRNCASECMP +int strncasecmp(const char *cs, const char *ct, size_t nb) +{ + int result = 0; + for (; nb > 0; nb--) + { + if ((result = (int)toupper(*cs) - (int)toupper(*ct)) != 0 || !*cs) + { + break; + } + + cs++; + ct++; + } + return result; +} +#endif diff --git a/nuttx/lib/string/lib_strncat.c b/nuttx/lib/string/lib_strncat.c new file mode 100644 index 0000000000..6b7d54f816 --- /dev/null +++ b/nuttx/lib/string/lib_strncat.c @@ -0,0 +1,62 @@ +/************************************************************ + * lib/string/lib_strncat.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include +#include +#include + +/************************************************************ + * Global Functions + ************************************************************/ + +#ifndef CONFIG_ARCH_STRNCAT +char *strncat(char *dest, const char *src, size_t n) +{ + char *ret = dest; + + dest += strlen(dest); + for (; n > 0 && *src != '\0' ; n--) + { + *dest++ = *src++; + } + *dest = '\0'; + + return ret; +} +#endif diff --git a/nuttx/lib/string/lib_strncmp.c b/nuttx/lib/string/lib_strncmp.c new file mode 100644 index 0000000000..147dfc5369 --- /dev/null +++ b/nuttx/lib/string/lib_strncmp.c @@ -0,0 +1,65 @@ +/**************************************************************************** + * lib/lib_strncmp.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + *****************************************************************************/ + +/**************************************************************************** + * Included Files + *****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Global Functions + *****************************************************************************/ + +#ifndef CONFIG_ARCH_STRNCMP +int strncmp(const char *cs, const char *ct, size_t nb) +{ + int result = 0; + for (; nb > 0; nb--) + { + if ((result = (int)*cs - (int)*ct++) != 0 || !*cs++) + { + break; + } + } + return result; +} +#endif diff --git a/nuttx/lib/string/lib_strncpy.c b/nuttx/lib/string/lib_strncpy.c new file mode 100644 index 0000000000..b5702cae21 --- /dev/null +++ b/nuttx/lib/string/lib_strncpy.c @@ -0,0 +1,57 @@ +/************************************************************ + * lib/string/lib_strncpy.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include +#include +#include + +/************************************************************ + * Global Functions + ************************************************************/ + +#ifndef CONFIG_ARCH_STRNCPY +char *strncpy(char *dest, const char *src, size_t n) +{ + char *ret = dest; /* Value to be returned */ + char *end = dest + n; /* End of dest buffer + 1 byte */ + + while ((*dest++ = *src++) != '\0' && dest != end); + return ret; +} +#endif diff --git a/nuttx/lib/string/lib_strndup.c b/nuttx/lib/string/lib_strndup.c new file mode 100644 index 0000000000..68b7c74c36 --- /dev/null +++ b/nuttx/lib/string/lib_strndup.c @@ -0,0 +1,93 @@ +/************************************************************************ + * lib/string//lib_strndup.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +#include "lib_internal.h" + +/************************************************************************ + * Global Functions + ************************************************************************/ +/************************************************************************ + * Name: strndup + * + * Description: + * The strndup() function is equivalent to the strdup() function, + * duplicating the provided 's' in a new block of memory allocated as + * if by using malloc(), with the exception being that strndup() copies + * at most 'size' plus one bytes into the newly allocated memory, + * terminating the new string with a NUL character. If the length of 's' + * is larger than 'size', only 'size' bytes will be duplicated. If + * 'size' is larger than the length of 's', all bytes in s will be + * copied into the new memory buffer, including the terminating NUL + * character. The newly created string will always be properly + * terminated. + * + ************************************************************************/ + +FAR char *strndup(FAR const char *s, size_t size) +{ + FAR char *news = NULL; + if (s) + { + /* Get the size of the new string = MIN(strlen(s), size) */ + + size_t allocsize = strlen(s); + if (allocsize > size) + { + allocsize = size; + } + + /* Allocate the new string, adding 1 for the NUL terminator */ + + news = (FAR char*)lib_malloc(allocsize + 1); + if (news) + { + /* Copy the string into the allocated memory and add a NUL + * terminator in any case. + */ + + memcpy(news, s, allocsize); + news[allocsize] = '\0'; + } + } + return news; +} diff --git a/nuttx/lib/string/lib_strnlen.c b/nuttx/lib/string/lib_strnlen.c new file mode 100644 index 0000000000..c2ffc248e6 --- /dev/null +++ b/nuttx/lib/string/lib_strnlen.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * lib/string/lib_strnlen.c + * + * This file is part of NuttX, contributed by Michael Hrabanek + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Michael Hrabanek + * + * Derives from the file lib/lib_strlen.c: + * + * Copyright (C) 2007, 2008, 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +#ifndef CONFIG_ARCH_STRNLEN +size_t strnlen(const char *s, size_t maxlen) +{ + const char *sc; + for (sc = s; maxlen != 0 && *sc != '\0'; maxlen--, ++sc); + return sc - s; +} +#endif diff --git a/nuttx/lib/string/lib_strpbrk.c b/nuttx/lib/string/lib_strpbrk.c new file mode 100644 index 0000000000..1340587750 --- /dev/null +++ b/nuttx/lib/string/lib_strpbrk.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * lib/string/lib_strpbrk.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use str source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions str binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer str + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +char *strpbrk(const char *str, const char *charset) +{ + /* Sanity checking */ + +#ifdef CONFIG_DEBUG + if (!str || !charset) + { + return NULL; + } +#endif + + /* Check each character in the string */ + + while (*str) + { + /* Check if the character from the string matches any character in the charset */ + + if (strchr(charset, *str) != NULL) + { + /* Yes, then this position must be the first occurrence in string */ + + return (char*)str; + } + + /* This character from the strings matches none of those in the charset. + * Try the next character from the string. + */ + + str++; + } + + /* We have looked at every character in the string, and none of them match any of + * the characters in charset. + */ + + return NULL; +} + diff --git a/nuttx/lib/string/lib_strrchr.c b/nuttx/lib/string/lib_strrchr.c new file mode 100644 index 0000000000..e89b26d523 --- /dev/null +++ b/nuttx/lib/string/lib_strrchr.c @@ -0,0 +1,68 @@ +/************************************************************************ + * lib/string/lib_strrchr.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +/************************************************************************ + * Global Functions + ************************************************************************/ + +/* The strrchr() function returns a pointer to the last + * occurrence of the character c in the string s. + */ + +char *strrchr(const char *s, int c) +{ + if (s) + { + const char *p = &s[strlen(s) - 1]; + for (; p >= s; p--) + { + if (*p == c) + { + return (char*)p; + } + } + } + + return NULL; +} + diff --git a/nuttx/lib/string/lib_strspn.c b/nuttx/lib/string/lib_strspn.c new file mode 100644 index 0000000000..e5cab9ad65 --- /dev/null +++ b/nuttx/lib/string/lib_strspn.c @@ -0,0 +1,66 @@ +/**************************************************************************** + * lib/string/lib_strspn.c + * + * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: strspn + * + * Description: + * strspn() calculates the length of the initial segment of s which + * consists entirely of characters in accept. + * + ****************************************************************************/ + +size_t strspn(const char *s, const char *accept) +{ + size_t i; + for (i = 0; s[i] && strchr(accept, s[i]) != NULL; i++); + return i; +} diff --git a/nuttx/lib/string/lib_strstr.c b/nuttx/lib/string/lib_strstr.c new file mode 100644 index 0000000000..27ca6e19bb --- /dev/null +++ b/nuttx/lib/string/lib_strstr.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * lib/string/lib_strstr.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use str source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions str binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer str + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +char *strstr(const char *str, const char *substr) +{ + const char *candidate; /* Candidate in str with matching start character */ + char ch; /* First character of the substring */ + int len; /* The length of the substring */ + + /* Special case the empty substring */ + + len = strlen(substr); + ch = *substr; + + if (!ch) + { + /* We'll say that an empty substring matches at the beginning of + * the string + */ + + return (char*)str; + } + + /* Search for the substring */ + + candidate = str; + for (;;) + { + /* strchr() will return a pointer to the next occurrence of the + * character ch in the string + */ + + candidate = strchr(candidate, ch); + if (!candidate || strlen(candidate) < len) + { + /* First character of the substring does not appear in the string + * or the remainder of the string is not long enough to contain the + * substring. + */ + + return NULL; + } + + /* Check if this is the beginning of a matching substring */ + + if (strncmp(candidate, substr, len) == 0) + { + return (char*)candidate; + } + + /* No, find the next candidate after this one */ + + candidate++; + } + + /* Won't get here, but some compilers might complain */ + + return NULL; +} + diff --git a/nuttx/lib/string/lib_strtod.c b/nuttx/lib/string/lib_strtod.c new file mode 100644 index 0000000000..86719c5105 --- /dev/null +++ b/nuttx/lib/string/lib_strtod.c @@ -0,0 +1,234 @@ +/**************************************************************************** + * lib/string/lib_strtod.c + * Convert string to double + * + * Copyright (C) 2002 Michael Ringgaard. All rights reserved. + * Copyright (C) 2006-2007 H. Peter Anvin. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +/* These are predefined with GCC, but could be issues for other compilers. If + * not defined, an arbitrary big number is put in for now. These should be + * added to nuttx/compiler for your compiler. + */ + +#if !defined(__DBL_MIN_EXP__) || !defined(__DBL_MAX_EXP__) +# ifdef CONFIG_CPP_HAVE_WARNING +# warning "Size of exponent is unknown" +# endif +# undef __DBL_MIN_EXP__ +# define __DBL_MIN_EXP__ (-1021) +# undef __DBL_MAX_EXP__ +# define __DBL_MAX_EXP__ (1024) +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline int is_real(double x) +{ + const double_t infinite = 1.0/0.0; + return (x < infinite) && (x >= -infinite); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/***************************************************(************************ + * Name: strtod + * + * Description: + * Convert a string to a double value + * + ****************************************************************************/ + +double_t strtod(const char *str, char **endptr) +{ + double_t number; + int exponent; + int negative; + char *p = (char *) str; + double p10; + int n; + int num_digits; + int num_decimals; + const double_t infinite = 1.0/0.0; + + /* Skip leading whitespace */ + + while (isspace(*p)) + { + p++; + } + + /* Handle optional sign */ + + negative = 0; + switch (*p) + { + case '-': + negative = 1; /* Fall through to increment position */ + case '+': + p++; + } + + number = 0.; + exponent = 0; + num_digits = 0; + num_decimals = 0; + + /* Process string of digits */ + + while (isdigit(*p)) + { + number = number * 10. + (*p - '0'); + p++; + num_digits++; + } + + /* Process decimal part */ + + if (*p == '.') + { + p++; + + while (isdigit(*p)) + { + number = number * 10. + (*p - '0'); + p++; + num_digits++; + num_decimals++; + } + + exponent -= num_decimals; + } + + if (num_digits == 0) + { + set_errno(ERANGE); + return 0.0; + } + + /* Correct for sign */ + + if (negative) + { + number = -number; + } + + /* Process an exponent string */ + + if (*p == 'e' || *p == 'E') + { + /* Handle optional sign */ + + negative = 0; + switch(*++p) + { + case '-': + negative = 1; /* Fall through to increment pos */ + case '+': + p++; + } + + /* Process string of digits */ + + n = 0; + while (isdigit(*p)) + { + n = n * 10 + (*p - '0'); + p++; + } + + if (negative) + { + exponent -= n; + } + else + { + exponent += n; + } + } + + if (exponent < __DBL_MIN_EXP__ || + exponent > __DBL_MAX_EXP__) + { + set_errno(ERANGE); + return infinite; + } + + /* Scale the result */ + + p10 = 10.; + n = exponent; + if (n < 0) n = -n; + while (n) + { + if (n & 1) + { + if (exponent < 0) + { + number /= p10; + } + else + { + number *= p10; + } + } + n >>= 1; + p10 *= p10; + } + + if (!is_real(number)) + { + set_errno(ERANGE); + } + + if (endptr) + { + *endptr = p; + } + + return number; +} + diff --git a/nuttx/lib/string/lib_strtok.c b/nuttx/lib/string/lib_strtok.c new file mode 100644 index 0000000000..bafa94853e --- /dev/null +++ b/nuttx/lib/string/lib_strtok.c @@ -0,0 +1,87 @@ +/**************************************************************************** + * lib/string/lib_strtok.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static char *g_saveptr = NULL; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: strtok + * + * Description: + * The strtok() function parses a string into a + * sequence of tokens. On the first call to strtok() the + * string to be parsed should be specified in 'str'. In + * each subsequent call that should parse the same string, + * 'str' should be NULL. + * + * The 'delim' argument specifies a set of characters that + * delimit the tokens in the parsed string. The caller + * may specify different strings in delim in successive + * calls that parse the same string. + * + * Each call to strtok() returns a pointer to a null- + * terminated string containing the next token. This + * string does not include the delimiting character. If + * no more tokens are found, strtok() returns NULL. + * + * A sequence of two or more contiguous delimiter + * characters in the parsed string is considered to be a + * single delimiter. Delimiter characters at the start or + * end of the string are ignored. The tokens returned by + * strtok() are always non-empty strings. + * + * Return + * strtok() returns a pointer to the next token, or NULL + * if there are no more tokens. + * + ****************************************************************************/ + +char *strtok(char *str, const char *delim) +{ + return strtok_r(str, delim, &g_saveptr); +} diff --git a/nuttx/lib/string/lib_strtokr.c b/nuttx/lib/string/lib_strtokr.c new file mode 100644 index 0000000000..366a318198 --- /dev/null +++ b/nuttx/lib/string/lib_strtokr.c @@ -0,0 +1,157 @@ +/**************************************************************************** + * lib/string/lib_strtokr.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: strtok_r + * + * Description: + * The strtok_r() function is a reentrant version strtok(). + * Like strtok(), it parses a string into a sequence of + * tokens. On the first call to strtok() the string to be + * parsed should be specified in 'str'. In each subsequent + * call that should parse the same string, 'str' should be + * NULL. + * + * The 'saveptr' argument is a pointer to a char * + * variable that is used internally by strtok_r() in + * order to maintain context between successive calls + * that parse the same string. + * + * On the first call to strtok_r(), 'str' should point to the + * string to be parsed, and the value of 'saveptr' is + * ignored. In subsequent calls, 'str' should be NULL, and + * saveptr should be unchanged since the previous call. + * + * The 'delim' argument specifies a set of characters that + * delimit the tokens in the parsed string. The caller + * may specify different strings in delim in successive + * calls that parse the same string. + * + * Each call to strtok_r() returns a pointer to a null- + * terminated string containing the next token. This + * string does not include the delimiting character. If + * no more tokens are found, strtok_r() returns NULL. + * + * A sequence of two or more contiguous delimiter + * characters in the parsed string is considered to be a + * single delimiter. Delimiter characters at the start or + * end of the string are ignored. The tokens returned by + * strtok() are always non-empty strings. + * + * Return + * strtok_r() returns a pointer to the next token, or NULL + * if there are no more tokens. + * + ****************************************************************************/ + +char *strtok_r(char *str, const char *delim, char **saveptr) +{ + char *pbegin; + char *pend = NULL; + + /* Decide if we are starting a new string or continuing from + * the point we left off. + */ + + if (str) + { + pbegin = str; + } + else if (saveptr && *saveptr) + { + pbegin = *saveptr; + } + else + { + return NULL; + } + + /* Find the beginning of the next token */ + + for (; + *pbegin && strchr(delim, *pbegin) != NULL; + pbegin++); + + /* If we are at the end of the string with nothing + * but delimiters found, then return NULL. + */ + + if (!*pbegin) + { + return NULL; + } + + /* Find the end of the token */ + + for (pend = pbegin + 1; + *pend && strchr(delim, *pend) == NULL; + pend++); + + + /* pend either points to the end of the string or to + * the first delimiter after the string. + */ + + if (*pend) + { + /* Turn the delimiter into a null terminator */ + + *pend++ = '\0'; + } + + /* Save the pointer where we left off and return the + * beginning of the token. + */ + + if (saveptr) + { + *saveptr = pend; + } + return pbegin; +} diff --git a/nuttx/lib/string/lib_strtol.c b/nuttx/lib/string/lib_strtol.c new file mode 100644 index 0000000000..4f69047934 --- /dev/null +++ b/nuttx/lib/string/lib_strtol.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * lib/string/lib_strtol.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: strtol + * + * Description: + * The strtol() function converts the initial part of the string in + * nptr to a long integer value according to the given base, which must be + * between 2 and 36 inclusive, or be the special value 0. + * + * Warning: does not check for integer overflow! + * + ****************************************************************************/ + +long strtol(const char *nptr, char **endptr, int base) +{ + unsigned long accum = 0; + bool negate = false; + + if (nptr) + { + /* Skip leading spaces */ + + lib_skipspace(&nptr); + + /* Check for leading + or - */ + + if (*nptr == '-') + { + negate = true; + nptr++; + } + else if (*nptr == '+') + { + nptr++; + } + + /* Get the unsigned value */ + + accum = strtoul(nptr, endptr, base); + + /* Correct the sign of the result */ + + if (negate) + { + return -(long)accum; + } + } + return (long)accum; +} + diff --git a/nuttx/lib/string/lib_strtoll.c b/nuttx/lib/string/lib_strtoll.c new file mode 100644 index 0000000000..9c730b4310 --- /dev/null +++ b/nuttx/lib/string/lib_strtoll.c @@ -0,0 +1,107 @@ +/**************************************************************************** + * lib/string/lib_strtoll.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "lib_internal.h" + +#ifdef CONFIG_HAVE_LONG_LONG + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: strtoll + * + * Description: + * The strtol() function converts the initial part of the string in + * nptr to a long long integer value according to the given base, which + * must be between 2 and 36 inclusive, or be the special value 0. + * + * Warning: does not check for integer overflow! + * + ****************************************************************************/ + +long long strtoll(const char *nptr, char **endptr, int base) +{ + unsigned long long accum = 0; + bool negate = false; + + if (nptr) + { + /* Skip leading spaces */ + + lib_skipspace(&nptr); + + /* Check for leading + or - */ + + if (*nptr == '-') + { + negate = true; + nptr++; + } + else if (*nptr == '+') + { + nptr++; + } + + /* Get the unsigned value */ + + accum = strtoull(nptr, endptr, base); + + /* Correct the sign of the result */ + + if (negate) + { + return -(long long)accum; + } + } + return (long long)accum; +} + +#endif + diff --git a/nuttx/lib/string/lib_strtoul.c b/nuttx/lib/string/lib_strtoul.c new file mode 100644 index 0000000000..2aacc7cea8 --- /dev/null +++ b/nuttx/lib/string/lib_strtoul.c @@ -0,0 +1,98 @@ +/**************************************************************************** + * /lib/string/lib_strtoul.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "lib_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: strtoul + * + * Description: + * The strtol() function converts the initial part of the string in + * nptr to a long unsigned integer value according to the given base, which + * must be between 2 and 36 inclusive, or be the special value 0. + * + * Warning: does not check for integer overflow! + * + ****************************************************************************/ + +unsigned long strtoul(const char *nptr, char **endptr, int base) +{ + unsigned long accum = 0; + int value; + + if (nptr) + { + /* Skip leading spaces */ + + lib_skipspace(&nptr); + + /* Check for unspecified base */ + + base = lib_checkbase(base, &nptr); + + /* Accumulate each "digit" */ + + while (lib_isbasedigit(*nptr, base, &value)) + { + accum = accum*base + value; + nptr++; + } + + /* Return the final pointer to the unused value */ + + if (endptr) + { + *endptr = (char *)nptr; + } + } + return accum; +} + diff --git a/nuttx/lib/string/lib_strtoull.c b/nuttx/lib/string/lib_strtoull.c new file mode 100644 index 0000000000..3341621481 --- /dev/null +++ b/nuttx/lib/string/lib_strtoull.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * /lib/string/lib_strtoull.c + * + * Copyright (C) 2009, 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +#include "lib_internal.h" + +#ifdef CONFIG_HAVE_LONG_LONG + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: strtoull + * + * Description: + * The strtol() function converts the initial part of the string in + * nptr to a long unsigned integer value according to the given base, which + * must be between 2 and 36 inclusive, or be the special value 0. + * + ****************************************************************************/ + +unsigned long long strtoull(const char *nptr, char **endptr, int base) +{ + unsigned long long accum = 0; + int value; + + if (nptr) + { + /* Skip leading spaces */ + + lib_skipspace(&nptr); + + /* Check for unspecified base */ + + base = lib_checkbase(base, &nptr); + + /* Accumulate each "digit" */ + + while (lib_isbasedigit(*nptr, base, &value)) + { + accum = accum*base + value; + nptr++; + } + + /* Return the final pointer to the unused value */ + + if (endptr) + { + *endptr = (char *)nptr; + } + } + return accum; +} +#endif + diff --git a/nuttx/lib/termios/Make.defs b/nuttx/lib/termios/Make.defs new file mode 100644 index 0000000000..c0a090bd55 --- /dev/null +++ b/nuttx/lib/termios/Make.defs @@ -0,0 +1,43 @@ +############################################################################ +# lib/misc/Make.defs +# +# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +TERMIOS_SRCS = + +ifneq ($(CONFIG_NFILE_DESCRIPTORS),0) + +TERMIOS_SRCS += lib_cfgetspeed.c lib_cfsetspeed.c lib_tcflush.c +TERMIOS_SRCS += lib_tcgetattr.c lib_tcsetattr.c + +endif diff --git a/nuttx/lib/termios/lib_cfgetspeed.c b/nuttx/lib/termios/lib_cfgetspeed.c new file mode 100644 index 0000000000..d7f0dc4736 --- /dev/null +++ b/nuttx/lib/termios/lib_cfgetspeed.c @@ -0,0 +1,93 @@ +/**************************************************************************** + * lib/termios/lib_cfgetspeed.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cfgetspeed + * + * Descripton: + * The cfgetspeed() function is a non-POSIX function will extract the baud + * from the termios structure to which the termiosp argument points. + * + * This function will return exactly the value in the termios data + * structure, without interpretation. + * + * NOTE 1: NuttX does not control input/output baud independently. Both + * must be the same. The POSIX standard interfaces, cfisetispeed() and + * cfisetospeed() are defined to be cfgetspeed() in termios.h. + * NOTE 2. In Nuttx, the speed_t is defined to be uint32_t and the baud + * encodings of termios.h are the actual baud values themselves. Therefore, + * any baud value may be returned here... not just those enumerated in + * termios.h + * + * Input Parameters: + * termiosp - The termiosp argument is a pointer to a termios structure. + * + * Returned Value: + * Encoded baud value from the termios structure. + * + ****************************************************************************/ + +speed_t cfgetspeed(FAR const struct termios *termiosp) +{ + DEBUGASSERT(termiosp); + return termiosp->c_speed; +} diff --git a/nuttx/lib/termios/lib_cfsetspeed.c b/nuttx/lib/termios/lib_cfsetspeed.c new file mode 100644 index 0000000000..bf9e660640 --- /dev/null +++ b/nuttx/lib/termios/lib_cfsetspeed.c @@ -0,0 +1,121 @@ +/**************************************************************************** + * lib/termios/lib_cfsetspeed.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cfsetspeed + * + * Descripton: + * The cfsetspeed() function is a non-POSIX function that sets the baud + * stored in the structure pointed to by termiosp to speed. + * + * There is no effect on the baud set in the hardware until a subsequent + * successful call to tcsetattr() on the same termios structure. + * + * NOTE 1: NuttX does not control input/output baud independently. Both + * must be the same. The POSIX standard interfaces, cfisetispeed() and + * cfisetospeed() are defined to be cfsetspeed() in termios.h. + * + * NOTE 3: A consequence of NOTE 1 is that you should never attempt to + * set the input and output baud to different values. + * + * Also, the following POSIX requirement cannot be supported: "If the input + * baud rate stored in the termios structure pointed to by termios_p is 0, + * the input baud rate given to the hardware will be the same as the output + * baud rate stored in the termios structure." + * + * NOTE 2. In Nuttx, the speed_t is defined to be uint32_t and the baud + * encodings of termios.h are the actual baud values themselves. Therefore, + * any baud value can be provided as the speed argument here. However, if + * you do so, your code will *NOT* be portable to other environments where + * speed_t is smaller and where the termios.h baud values are encoded! To + * avoid portability issues, use the baud definitions in termios.h! + * + * Linux, for example, would require this (also non-portable) sequence: + * + * cfsetispeed(termiosp, BOTHER); + * termiosp->c_ispeed = baud; + * + * cfsetospeed(termiosp, BOTHER); + * termiosp->c_ospeed = baud; + * + * Input Parameters: + * termiosp - The termiosp argument is a pointer to a termios structure. + * speed - The new input speed + * + * Returned Value: + * Baud is not checked... OK is always returned (this is non-standard + * behavior). + * + ****************************************************************************/ + +int cfsetspeed(FAR struct termios *termiosp, speed_t speed) +{ + FAR speed_t *speedp; + + DEBUGASSERT(termiosp); + + speedp = (FAR speed_t *)&termiosp->c_speed; + *speedp = speed; + + return OK; +} diff --git a/nuttx/lib/termios/lib_tcflush.c b/nuttx/lib/termios/lib_tcflush.c new file mode 100644 index 0000000000..338524bdda --- /dev/null +++ b/nuttx/lib/termios/lib_tcflush.c @@ -0,0 +1,88 @@ +/**************************************************************************** + * lib/termios/lib_tcflush.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tcflush + * + * Descripton: + * Function for flushing a terminal/serial device + * + * Input Parameters: + * fd - The 'fd' argument is an open file descriptor associated with a terminal. + * cmd - The TCFLSH ioctl argument. + * + * Returned Value: + * Upon successful completion, 0 is returned. Otherwise, -1 is returned and + * errno is set to indicate the error. + * + ****************************************************************************/ + +int tcflush(int fd, int cmd) +{ + return ioctl(fd, TCFLSH, (unsigned long)cmd); +} diff --git a/nuttx/lib/termios/lib_tcgetattr.c b/nuttx/lib/termios/lib_tcgetattr.c new file mode 100644 index 0000000000..500871d9ff --- /dev/null +++ b/nuttx/lib/termios/lib_tcgetattr.c @@ -0,0 +1,93 @@ +/**************************************************************************** + * lib/termios/lib_tcgetattr.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tcgetattr + * + * Descripton: + * The tcgetattr() function gets the parameters associated with the + * terminal referred to by 'fd' and stores them in the termios structure + * referenced by 'termiosp'. + * + * Input Parameters: + * fd - The 'fd' argument is an open file descriptor associated with a terminal. + * termiosp - The termiosp argument is a pointer to a termios structure. + * + * Returned Value: + * Upon successful completion, 0 is returned. Otherwise, -1 is returned and + * errno is set to indicate the error. The following errors may be reported: + * + * - EBADF: The 'fd' argument is not a valid file descriptor. + * - ENOTTY: The file associated with 'fd' is not a terminal. + * + ****************************************************************************/ + +int tcgetattr(int fd, FAR struct termios *termiosp) +{ + return ioctl(fd, TCGETS, (unsigned long)termiosp); +} diff --git a/nuttx/lib/termios/lib_tcsetattr.c b/nuttx/lib/termios/lib_tcsetattr.c new file mode 100644 index 0000000000..791b519c85 --- /dev/null +++ b/nuttx/lib/termios/lib_tcsetattr.c @@ -0,0 +1,122 @@ +/**************************************************************************** + * lib/termios/lib_tcsetattr.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tcsetattr + * + * Descripton: + * The tcsetattr() function sets the parameters associated with the + * terminal referred to by the open file descriptor 'fd' from the termios + * structure referenced by 'termiop' as follows: + * + * If 'options' is TCSANOW, the change will occur immediately. + * + * If 'options' is TCSADRAIN, the change will occur after all output + * written to 'fd' is transmitted. This function should be used when changing + * parameters that affect output. + * + * If 'options' is TCSAFLUSH, the change will occur after all + * output written to 'fd' is transmitted, and all input so far received but + * not read will be discarded before the change is made. + * + * The tcsetattr() function will return successfully if it was able to + * perform any of the requested actions, even if some of the requested + * actions could not be performed. It will set all the attributes that + * implementation supports as requested and leave all the attributes not + * supported by the implementation unchanged. If no part of the request + * can be honoured, it will return -1 and set errno to EINVAL. + * + * The effect of tcsetattr() is undefined if the value of the termios + * structure pointed to by 'termiop' was not derived from the result of + * a call to tcgetattr() on 'fd'; an application should modify only fields + * and flags defined by this specification between the call to tcgetattr() + * and tcsetattr(), leaving all other fields and flags unmodified. + * + * Returned Value: + * + * Upon successful completion, 0 is returned. Otherwise, -1 is returned + * and errno is set to indicate the error. The following errors may be + * reported: + * + * - EBADF: The 'fd' argument is not a valid file descriptor. + * - EINTR: A signal interrupted tcsetattr(). + * - EINVAL: The 'options' argument is not a supported value, or + * an attempt was made to change an attribute represented in the + * termios structure to an unsupported value. + * - ENOTTY: The file associated with 'fd' is not a terminal. + * + ****************************************************************************/ + +int tcsetattr(int fd, int options, FAR const struct termios *termiosp) +{ + if (options == TCSANOW) + { + return ioctl(fd, TCSETS, (unsigned long)termiosp); + } + return -ENOSYS; +} diff --git a/nuttx/lib/time/Make.defs b/nuttx/lib/time/Make.defs new file mode 100644 index 0000000000..d65ba50f61 --- /dev/null +++ b/nuttx/lib/time/Make.defs @@ -0,0 +1,37 @@ +############################################################################ +# lib/time/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +TIME_SRCS = lib_mktime.c lib_gmtime.c lib_gmtimer.c lib_strftime.c \ + lib_calendar2utc.c lib_daysbeforemonth.c lib_isleapyear.c lib_time.c diff --git a/nuttx/lib/time/lib_calendar2utc.c b/nuttx/lib/time/lib_calendar2utc.c new file mode 100644 index 0000000000..642e23568a --- /dev/null +++ b/nuttx/lib/time/lib_calendar2utc.c @@ -0,0 +1,209 @@ +/**************************************************************************** + * lib/time/lib_calendar2utc.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: clock_gregorian2utc, clock_julian2utc + * + * Description: + * UTC conversion routines. These conversions are based + * on algorithms from p. 604 of Seidelman, P. K. 1992. + * Explanatory Supplement to the Astronomical Almanac. + * University Science Books, Mill Valley. + * + ****************************************************************************/ + +#ifdef CONFIG_GREGORIAN_TIME +static time_t clock_gregorian2utc(int year, int month, int day) +{ + int temp; + + /* temp = (month - 14)/12; */ + + temp = (month <= 2 ? -1:0); + + return (1461*(year + 4800 + temp))/4 + + (367*(month - 2 - 12*temp))/12 + - (3*((year + 4900 + temp)/100))/4 + day - 32075; +} + +#ifdef CONFIG_JULIAN_TIME +static time_t clock_julian2utc(int year, int month, int day) +{ + return 367*year + - (7*(year + 5001 + (month-9)/7))/4 + + (275*month)/9 + + day + 1729777; +} +#endif /* CONFIG_JULIAN_TIME */ +#endif /* CONFIG_GREGORIAN_TIME */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: clock_calendar2utc + * + * Description: + * Calendar/UTC conversion based on algorithms from p. 604 + * of Seidelman, P. K. 1992. Explanatory Supplement to + * the Astronomical Almanac. University Science Books, + * Mill Valley. + * + ****************************************************************************/ + +#ifdef CONFIG_GREGORIAN_TIME +time_t clock_calendar2utc(int year, int month, int day) +{ + int dyear; +#ifdef CONFIG_JULIAN_TIME + bool isgreg; +#endif /* CONFIG_JULIAN_TIME */ + + /* Correct year & month ranges. Shift month into range 1-12 */ + + dyear = (month-1) / 12; + month -= 12 * dyear; + year += dyear; + + if (month < 1) + { + month += 12; + year -= 1; + } + +#ifdef CONFIG_JULIAN_TIME + /* Determine which calendar to use */ + + if (year > GREG_YEAR) + { + isgreg = true; + } + else if (year < GREG_YEAR) + { + isgreg = false; + } + else if (month > GREG_MONTH) + { + isgreg = true; + } + else if (month < GREG_MONTH) + { + isgreg = false; + } + else + { + isgreg = (day >= GREG_DAY); + } + + /* Calculate and return date */ + + if (isgreg) + { + return clock_gregorian2utc(year, month, day) - JD_OF_EPOCH; + } + else + { + return clock_julian2utc (year, month, day) - JD_OF_EPOCH; + } + +#else /* CONFIG_JULIAN_TIME */ + + return clock_gregorian2utc(year, month, day) - JD_OF_EPOCH; + +#endif /* CONFIG_JULIAN_TIME */ +} +#else + +/* A highly simplified version that only handles days in the time + * since Jan 1, 1970. + */ + +time_t clock_calendar2utc(int year, int month, int day) +{ + struct tm t; + + /* mktime can (kind of) do this */ + + t.tm_year = year; + t.tm_mon = month; + t.tm_mday = day; + t.tm_hour = 0; + t.tm_min = 0; + t.tm_sec = 0; + return mktime(&t); +} +#endif /* CONFIG_GREGORIAN_TIME */ + diff --git a/nuttx/lib/time/lib_daysbeforemonth.c b/nuttx/lib/time/lib_daysbeforemonth.c new file mode 100644 index 0000000000..4312adaba2 --- /dev/null +++ b/nuttx/lib/time/lib_daysbeforemonth.c @@ -0,0 +1,102 @@ +/**************************************************************************** + * lib/time/lib_daysbeforemonth.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +uint16_t g_daysbeforemonth[13] = +{ + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 +}; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: clock_daysbeforemonth + * + * Description: + * Get the number of days that occurred before the beginning of the month. + * + ****************************************************************************/ + +int clock_daysbeforemonth(int month, bool leapyear) +{ + int retval = g_daysbeforemonth[month]; + if (month >= 2 && leapyear) + { + retval++; + } + return retval; +} + + diff --git a/nuttx/lib/time/lib_gmtime.c b/nuttx/lib/time/lib_gmtime.c new file mode 100644 index 0000000000..7bce8391ed --- /dev/null +++ b/nuttx/lib/time/lib_gmtime.c @@ -0,0 +1,93 @@ +/**************************************************************************** + * lib/time/lib_gmtime.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/************************************************************************** + * Public Constant Data + **************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: gmtime + * + * Description: + * Similar to gmtime_r, but not thread-safe + * + ****************************************************************************/ + +struct tm *gmtime(const time_t *timer) +{ + static struct tm tm; + return gmtime_r(timer, &tm); +} + diff --git a/nuttx/lib/time/lib_gmtimer.c b/nuttx/lib/time/lib_gmtimer.c new file mode 100644 index 0000000000..146939e7a4 --- /dev/null +++ b/nuttx/lib/time/lib_gmtimer.c @@ -0,0 +1,355 @@ +/**************************************************************************** + * lib/time/lib_gmtimer.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define SEC_PER_MIN ((time_t)60) +#define SEC_PER_HOUR ((time_t)60 * SEC_PER_MIN) +#define SEC_PER_DAY ((time_t)24 * SEC_PER_HOUR) + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Calendar/UTC conversion routines */ + +static void clock_utc2calendar(time_t utc, int *year, int *month, int *day); +#ifdef CONFIG_GREGORIAN_TIME +static void clock_utc2gregorian (time_t jdn, int *year, int *month, int *day); + +#ifdef CONFIG_JULIAN_TIME +static void clock_utc2julian(time_t jdn, int *year, int *month, int *day); +#endif /* CONFIG_JULIAN_TIME */ +#endif /* CONFIG_GREGORIAN_TIME */ + +/************************************************************************** + * Public Constant Data + **************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: clock_calendar2utc, clock_gregorian2utc, + * and clock_julian2utc + * + * Description: + * Calendar to UTC conversion routines. These conversions + * are based on algorithms from p. 604 of Seidelman, P. K. + * 1992. Explanatory Supplement to the Astronomical + * Almanac. University Science Books, Mill Valley. + * + ****************************************************************************/ + +#ifdef CONFIG_GREGORIAN_TIME +static void clock_utc2calendar(time_t utc, int *year, int *month, int *day) +{ +#ifdef CONFIG_JULIAN_TIME + + if (utc >= GREG_DUTC) + { + clock_utc2gregorian(utc + JD_OF_EPOCH, year, month, day); + } + else + { + clock_utc2julian (utc + JD_OF_EPOCH, year, month, day); + } + +#else /* CONFIG_JULIAN_TIME */ + + clock_utc2gregorian(utc + JD_OF_EPOCH, year, month, day); + +#endif /* CONFIG_JULIAN_TIME */ +} + +static void clock_utc2gregorian(time_t jd, int *year, int *month, int *day) +{ + long l, n, i, j, d, m, y; + + l = jd + 68569; + n = (4*l) / 146097; + l = l - (146097*n + 3)/4; + i = (4000*(l+1))/1461001; + l = l - (1461*i)/4 + 31; + j = (80*l)/2447; + d = l - (2447*j)/80; + l = j/11; + m = j + 2 - 12*l; + y = 100*(n-49) + i + l; + + *year = y; + *month = m; + *day = d; +} + +#ifdef CONFIG_JULIAN_TIME + +static void clock_utc2julian(time_t jd, int *year, int *month, int *day) +{ + long j, k, l, n, d, i, m, y; + + j = jd + 1402; + k = (j-1)/1461; + l = j - 1461*k; + n = (l-1)/365 - l/1461; + i = l - 365*n + 30; + j = (80*i)/2447; + d = i - (2447*j)/80; + i = j/11; + m = j + 2 - 12*i; + y = 4*k + n + i - 4716; + + *year = y; + *month = m; + *day = d; +} + +#endif /* CONFIG_JULIAN_TIME */ +#else/* CONFIG_GREGORIAN_TIME */ + +/* Only handles dates since Jan 1, 1970 */ + +static void clock_utc2calendar(time_t days, int *year, int *month, int *day) +{ + int value; + int min; + int max; + int tmp; + bool leapyear; + + /* There is one leap year every four years, so we can get close with the + * following: + */ + + value = days / (4*365 + 1); /* Number of 4-years periods since the epoch*/ + days -= value * (4*365 + 1); /* Remaining days */ + value <<= 2; /* Years since the epoch */ + + /* Then we will brute force the next 0-3 years */ + + for (;;) + { + /* Is this year a leap year (we'll need this later too) */ + + leapyear = clock_isleapyear(value + 1970); + + /* Get the number of days in the year */ + + tmp = (leapyear ? 366 : 365); + + /* Do we have that many days? */ + + if (days >= tmp) + { + /* Yes.. bump up the year */ + + value++; + days -= tmp; + } + else + { + /* Nope... then go handle months */ + + break; + } + } + + /* At this point, value has the year and days has number days into this year */ + + *year = 1970 + value; + + /* Handle the month (zero based) */ + + min = 0; + max = 11; + + do + { + /* Get the midpoint */ + + value = (min + max) >> 1; + + /* Get the number of days that occurred before the beginning of the month + * following the midpoint. + */ + + tmp = clock_daysbeforemonth(value + 1, leapyear); + + /* Does the number of days before this month that equal or exceed the + * number of days we have remaining? + */ + + if (tmp > days) + { + /* Yes.. then the month we want is somewhere from 'min' and to the + * midpoint, 'value'. Could it be the midpoint? + */ + + tmp = clock_daysbeforemonth(value, leapyear); + if (tmp > days) + { + /* No... The one we want is somewhere between min and value-1 */ + + max = value - 1; + } + else + { + /* Yes.. 'value' contains the month that we want */ + + break; + } + } + else + { + /* No... The one we want is somwhere between value+1 and max */ + + min = value + 1; + } + + /* If we break out of the loop because min == max, then we want value + * to be equal to min == max. + */ + + value = min; + } + while (min < max); + + /* The selected month number is in value. Subtract the number of days in the + * selected month + */ + + days -= clock_daysbeforemonth(value, leapyear); + + /* At this point, value has the month into this year (zero based) and days has + * number of days into this month (zero based) + */ + + *month = value + 1; /* 1-based */ + *day = days + 1; /* 1-based */ +} + +#endif /* CONFIG_GREGORIAN_TIME */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: gmtime_r + * + * Description: + * Time conversion (based on the POSIX API) + * + ****************************************************************************/ + +FAR struct tm *gmtime_r(FAR const time_t *timer, FAR struct tm *result) +{ + time_t epoch; + time_t jdn; + int year; + int month; + int day; + int hour; + int min; + int sec; + + /* Get the seconds since the EPOCH */ + + epoch = *timer; + sdbg("timer=%d\n", (int)epoch); + + /* Convert to days, hours, minutes, and seconds since the EPOCH */ + + jdn = epoch / SEC_PER_DAY; + epoch -= SEC_PER_DAY * jdn; + + hour = epoch / SEC_PER_HOUR; + epoch -= SEC_PER_HOUR * hour; + + min = epoch / SEC_PER_MIN; + epoch -= SEC_PER_MIN * min; + + sec = epoch; + + sdbg("hour=%d min=%d sec=%d\n", + (int)hour, (int)min, (int)sec); + + /* Convert the days since the EPOCH to calendar day */ + + clock_utc2calendar(jdn, &year, &month, &day); + + sdbg("jdn=%d year=%d month=%d day=%d\n", + (int)jdn, (int)year, (int)month, (int)day); + + /* Then return the struct tm contents */ + + result->tm_year = (int)year - 1900; /* Relative to 1900 */ + result->tm_mon = (int)month - 1; /* zero-based */ + result->tm_mday = (int)day; /* one-based */ + result->tm_hour = (int)hour; + result->tm_min = (int)min; + result->tm_sec = (int)sec; + + return result; +} + diff --git a/nuttx/lib/time/lib_isleapyear.c b/nuttx/lib/time/lib_isleapyear.c new file mode 100644 index 0000000000..24d7d6153d --- /dev/null +++ b/nuttx/lib/time/lib_isleapyear.c @@ -0,0 +1,88 @@ +/**************************************************************************** + * lib/time/lib_isleapyear.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: clock_isleapyear + * + * Description: + * Return true if the specified year is a leap year + * + ****************************************************************************/ + +int clock_isleapyear(int year) +{ + return year % 400 ? (year % 100 ? (year % 4 ? 0 : 1) : 0) : 1; +} + diff --git a/nuttx/lib/time/lib_mktime.c b/nuttx/lib/time/lib_mktime.c new file mode 100644 index 0000000000..2e8cfc119e --- /dev/null +++ b/nuttx/lib/time/lib_mktime.c @@ -0,0 +1,141 @@ +/**************************************************************************** + * lib/time/lib_mktime.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: mktime + * + * Description: + * Time conversion (based on the POSIX API) + * + ****************************************************************************/ + +#ifdef CONFIG_GREGORIAN_TIME +time_t mktime(const struct tm *tp) +{ + time_t ret; + time_t jdn; + + /* Get the EPOCH-relative julian date from the calendar year, + * month, and date + */ + + jdn = clock_calendar2utc(tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday); + sdbg("jdn=%d tm_year=%d tm_mon=%d tm_mday=%d\n", + (int)jdn, tp->tm_year, tp->tm_mon, tp->tm_mday); + + /* Return the seconds into the julian day. */ + + ret = ((jdn*24 + tp->tm_hour)*60 + tp->tm_min)*60 + tp->tm_sec; + sdbg("ret=%d tm_hour=%d tm_min=%d tm_sec=%d\n", + (int)ret, tp->tm_hour, tp->tm_min, tp->tm_sec); + + return ret; +} +#else + +/* Simple version that only works for dates within a (relatively) small range + * from the epoch. It does not handle earlier days or longer days where leap + * seconds, etc. apply. + */ + +time_t mktime(const struct tm *tp) +{ + unsigned int days; + + /* Years since epoch in units of days (ignoring leap years). */ + + days = (tp->tm_year - 70) * 365; + + /* Add in the extra days for the leap years prior to the current year. */ + + days += (tp->tm_year - 69) >> 2; + + /* Add in the days up to the beginning of this month. */ + + days += (time_t)clock_daysbeforemonth(tp->tm_mon, clock_isleapyear(tp->tm_year + 1900)); + + /* Add in the days since the beginning of this month (days are 1-based). */ + + days += tp->tm_mday - 1; + + /* Then convert the seconds and add in hours, minutes, and seconds */ + + return ((days * 24 + tp->tm_hour) * 60 + tp->tm_min) * 60 + tp->tm_sec; +} +#endif /* CONFIG_GREGORIAN_TIME */ + diff --git a/nuttx/lib/time/lib_strftime.c b/nuttx/lib/time/lib_strftime.c new file mode 100644 index 0000000000..c1ac345ee0 --- /dev/null +++ b/nuttx/lib/time/lib_strftime.c @@ -0,0 +1,398 @@ +/**************************************************************************** + * lib/time/lib_strftime.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char * const g_abbrevmonthname[12] = +{ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +static const char * const g_monthname[12] = +{ + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: strftime + * + * Description: + * The strftime() function formats the broken-down time tm according to + * the format specification format and places the result in the character + * array s of size max. + * + * Ordinary characters placed in the format string are copied to s without + * conversion. Conversion specifications are introduced by a '%' charac- + * ter, and terminated by a conversion specifier character, and are + * replaced in s as follows: + * + * %b The abbreviated month name according to the current locale. + * %B The full month name according to the current locale. + * %C The century number (year/100) as a 2-digit integer. (SU) + * %d The day of the month as a decimal number (range 01 to 31). + * %e Like %d, the day of the month as a decimal number, but a leading + * zero is replaced by a space. + * %h Equivalent to %b. (SU) + * %H The hour as a decimal number using a 24-hour clock (range 00 to 23). + * %I The hour as a decimal number using a 12-hour clock (range 01 to 12). + * %j The day of the year as a decimal number (range 001 to 366). + * %k The hour (24-hour clock) as a decimal number (range 0 to 23); + * single digits are preceded by a blank. (See also %H.) (TZ) + * %l The hour (12-hour clock) as a decimal number (range 1 to 12); + * single digits are preceded by a blank. (See also %I.) (TZ) + * %m The month as a decimal number (range 01 to 12). + * %M The minute as a decimal number (range 00 to 59). + * %n A newline character. (SU) + * %p Either "AM" or "PM" according to the given time value, or the + * corresponding strings for the current locale. Noon is treated + * as "PM" and midnight as "AM". + * %P Like %p but in lowercase: "am" or "pm" or a corresponding string + * for the current locale. (GNU) + * %s The number of seconds since the Epoch, that is, since 1970-01-01 + * 00:00:00 UTC. (TZ) + * %S The second as a decimal number (range 00 to 60). (The range is + * up to 60 to allow for occasional leap seconds.) + * %t A tab character. (SU) + * %y The year as a decimal number without a century (range 00 to 99). + * %Y The year as a decimal number including the century. + * %% A literal '%' character. + * + * Returned Value: + * The strftime() function returns the number of characters placed in the + * array s, not including the terminating null byte, provided the string, + * including the terminating null byte, fits. Otherwise, it returns 0, + * and the contents of the array is undefined. + * + ****************************************************************************/ + +size_t strftime(char *s, size_t max, const char *format, const struct tm *tm) +{ + const char *str; + char *dest = s; + int chleft = max; + int value; + int len; + + while (*format && chleft > 0) + { + /* Just copy regular characters */ + + if (*format != '%') + { + *dest++ = *format++; + chleft--; + continue; + } + + /* Handle the format character */ + + format++; + len = 0; + + switch (*format++) + { + /* %a: A three-letter abbreviation for the day of the week. */ + /* %A: The full name for the day of the week. */ + + case 'a': + case 'A': + { + len = snprintf(dest, chleft, "Day"); /* Not supported */ + } + break; + + /* %h: Equivalent to %b */ + + case 'h': + + /* %b: The abbreviated month name according to the current locale. */ + + case 'b': + { + if (tm->tm_mon < 12) + { + str = g_abbrevmonthname[tm->tm_mon]; + len = snprintf(dest, chleft, "%s", str); + } + } + break; + + /* %B: The full month name according to the current locale. */ + + case 'B': + { + if (tm->tm_mon < 12) + { + str = g_monthname[tm->tm_mon]; + len = snprintf(dest, chleft, "%s", str); + } + } + break; + + /* %y: The year as a decimal number without a century (range 00 to 99). */ + + case 'y': + + /* %C: The century number (year/100) as a 2-digit integer. */ + + case 'C': + { + len = snprintf(dest, chleft, "%02d", tm->tm_year % 100); + } + break; + + /* %d: The day of the month as a decimal number (range 01 to 31). */ + + case 'd': + { + len = snprintf(dest, chleft, "%02d", tm->tm_mday); + } + break; + + /* %e: Like %d, the day of the month as a decimal number, but a leading + * zero is replaced by a space. + */ + + case 'e': + { + len = snprintf(dest, chleft, "%2d", tm->tm_mday); + } + break; + + /* %H: The hour as a decimal number using a 24-hour clock (range 00 to 23). */ + + case 'H': + { + len = snprintf(dest, chleft, "%02d", tm->tm_hour); + } + break; + + /* %I: The hour as a decimal number using a 12-hour clock (range 01 to 12). */ + + case 'I': + { + len = snprintf(dest, chleft, "%02d", tm->tm_hour % 12); + } + break; + + /* %j: The day of the year as a decimal number (range 001 to 366). */ + + case 'j': + { + if (tm->tm_mon < 12) + { + value = clock_daysbeforemonth(tm->tm_mon, clock_isleapyear(tm->tm_year)) + tm->tm_mday; + len = snprintf(dest, chleft, "%03d", value); + } + } + break; + + /* %k: The hour (24-hour clock) as a decimal number (range 0 to 23); + * single digits are preceded by a blank. + */ + + case 'k': + { + len = snprintf(dest, chleft, "%2d", tm->tm_hour); + } + break; + + /* %l: The hour (12-hour clock) as a decimal number (range 1 to 12); + * single digits are preceded by a blank. + */ + + case 'l': + { + len = snprintf(dest, chleft, "%2d", tm->tm_hour % 12); + } + break; + + /* %m: The month as a decimal number (range 01 to 12). */ + + case 'm': + { + len = snprintf(dest, chleft, "%02d", tm->tm_mon + 1); + } + break; + + /* %M: The minute as a decimal number (range 00 to 59). */ + + case 'M': + { + len = snprintf(dest, chleft, "%02d", tm->tm_min); + } + break; + + /* %n: A newline character. */ + + case 'n': + { + *dest = '\n'; + len = 1; + } + break; + + /* %p: Either "AM" or "PM" according to the given time value. */ + + case 'p': + { + if (tm->tm_hour >= 12) + { + str = "PM"; + } + else + { + str = "AM"; + } + len = snprintf(dest, chleft, "%s", str); + } + break; + + /* %P: Like %p but in lowercase: "am" or "pm" */ + + case 'P': + { + if (tm->tm_hour >= 12) + { + str = "pm"; + } + else + { + str = "am"; + } + len = snprintf(dest, chleft, "%s", str); + } + break; + + /* %s: The number of seconds since the Epoch, that is, since 1970-01-01 + * 00:00:00 UTC. + */ + + case 's': + { + len = snprintf(dest, chleft, "%d", mktime(tm)); + } + break; + + /* %S: The second as a decimal number (range 00 to 60). (The range is + * up to 60 to allow for occasional leap seconds.) + */ + + case 'S': + { + len = snprintf(dest, chleft, "%02d", tm->tm_sec); + } + break; + + /* %t: A tab character. */ + + case 't': + { + *dest = '\t'; + len = 1; + } + break; + + /* %Y: The year as a decimal number including the century. */ + + case 'Y': + { + len = snprintf(dest, chleft, "%04d", tm->tm_year + 1900); + } + break; + + /* %%: A literal '%' character. */ + + case '%': + { + *dest = '%'; + len = 1; + } + break; + } + + /* Update counts and pointers */ + + dest += len; + chleft -= len; + } + + return max - chleft; +} diff --git a/nuttx/lib/time/lib_time.c b/nuttx/lib/time/lib_time.c new file mode 100644 index 0000000000..02853132b0 --- /dev/null +++ b/nuttx/lib/time/lib_time.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * lib/time/lib_time.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#ifndef CONFIG_DISABLE_CLOCK + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: time + * + * Description: + * Get the current calendar time as a time_t object. The function returns + * this value, and if the argument is not a null pointer, the value is also + * set to the object pointed by tloc. + * + * Note that this function is just a thin wrapper around gettimeofday() + * and is provided for compatibility. gettimeofday() is the preffered way + * to obtain system time. + * + * Parameters: + * Pointer to an object of type time_t, where the time value is stored. + * Alternativelly, this parameter can be a null pointer, in which case the + * parameter is not used, but a time_t object is still returned by the + * function. + * + * Return Value: + * The current calendar time as a time_t object. If the argument is not + * a null pointer, the return value is the same as the one stored in the + * location pointed by the argument. + * + * If the function could not retrieve the calendar time, it returns a -1 + * value. + * + ****************************************************************************/ + +time_t time(time_t *tloc) +{ + struct timeval tp; + int ret; + + /* Get the current time from the system */ + + ret = gettimeofday(&tp, NULL); + if (ret == OK) + { + /* Return the seconds since the epoch */ + + if (tloc) + { + *tloc = tp.tv_sec; + } + + return tp.tv_sec; + } + + return (time_t)ERROR; +} + +#endif /* !CONFIG_DISABLE_CLOCK */ diff --git a/nuttx/lib/unistd/Make.defs b/nuttx/lib/unistd/Make.defs new file mode 100644 index 0000000000..90f1724062 --- /dev/null +++ b/nuttx/lib/unistd/Make.defs @@ -0,0 +1,42 @@ +############################################################################ +# lib/unistd/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +UNISTD_SRCS = lib_getopt.c lib_getoptargp.c lib_getoptindp.c lib_getoptoptp.c +ifneq ($(CONFIG_NFILE_DESCRIPTORS),0) +ifneq ($(CONFIG_DISABLE_ENVIRON),y) +UNISTD_SRCS += lib_chdir.c lib_getcwd.c +endif +endif + diff --git a/nuttx/lib/unistd/lib_chdir.c b/nuttx/lib/unistd/lib_chdir.c new file mode 100644 index 0000000000..f79b424ff0 --- /dev/null +++ b/nuttx/lib/unistd/lib_chdir.c @@ -0,0 +1,179 @@ +/**************************************************************************** + * lib/unistd/lib_chdir.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "lib_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON) + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _trimdir + ****************************************************************************/ + +#if 0 +static inline void _trimdir(char *path) +{ + /* Skip any trailing '/' characters (unless it is also the leading '/') */ + + int len = strlen(path) - 1; + while (len > 0 && path[len] == '/') + { + path[len] = '\0'; + len--; + } +} +#else +# define _trimdir(p) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: chdir + * + * Description: + * The chdir() function causes the directory named by the pathname pointed + * to by the 'path' argument to become the current working directory; that + * is, the starting point for path searches for pathnames not beginning + * with '/'. + * + * Input Parmeters: + * path - A pointer to a directory to use as the new current working + * directory + * + * Returned Value: + * 0(OK) on success; -1(ERROR) on failure with errno set appropriately: + * + * EACCES + * Search permission is denied for any component of the pathname. + * ELOOP + * A loop exists in symbolic links encountered during resolution of the + * 'path' argument OR more that SYMLOOP_MAX symbolic links in the + * resolution of the 'path' argument. + * ENAMETOOLONG + * The length of the path argument exceeds PATH_MAX or a pathname component + * is longer than NAME_MAX. + * ENOENT + * A component of 'path' does not name an existing directory or path is + * an empty string. + * ENOTDIR + * A component of the pathname is not a directory. + * + ****************************************************************************/ + +int chdir(FAR const char *path) +{ + struct stat buf; + char *oldpwd; + char *alloc; + int err; + int ret; + + /* Verify the input parameters */ + + if (!path) + { + err = ENOENT; + goto errout; + } + + /* Verify that 'path' refers to a directory */ + + ret = stat(path, &buf); + if (ret != 0) + { + err = ENOENT; + goto errout; + } + + /* Something exists here... is it a directory? */ + + if (!S_ISDIR(buf.st_mode)) + { + err = ENOTDIR; + goto errout; + } + + /* Yes, it is a directory. Remove any trailing '/' characters from the path */ + + _trimdir(path); + + /* Replace any preceding OLDPWD with the current PWD (this is to + * support 'cd -' in NSH) + */ + + sched_lock(); + oldpwd = getenv("PWD"); + if (!oldpwd) + { + oldpwd = CONFIG_LIB_HOMEDIR; + } + + alloc = strdup(oldpwd); /* kludge needed because environment is realloc'ed */ + setenv("OLDPWD", alloc, TRUE); + lib_free(alloc); + + /* Set the cwd to the input 'path' */ + + setenv("PWD", path, TRUE); + sched_unlock(); + return OK; + +errout: + set_errno(err); + return ERROR; +} +#endif /* CONFIG_NFILE_DESCRIPTORS && !CONFIG_DISABLE_ENVIRON */ diff --git a/nuttx/lib/unistd/lib_getcwd.c b/nuttx/lib/unistd/lib_getcwd.c new file mode 100644 index 0000000000..9bfa102fb6 --- /dev/null +++ b/nuttx/lib/unistd/lib_getcwd.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * lib/unistd/lib_getcwd.c + * + * Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "lib_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON) + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getwcd + * + * Description: + * getcwd() function places the absolute pathname of the current working + * directory in the array pointed to by 'buf', and returns 'buf.' The + * pathname copied to the array shall contain no components that are + * symbolic links. The 'size' argument is the size in bytes of the + * character array pointed to by the 'buf' argument. + * + * Input Parmeters: + * buf - a pointer to the location in which the current working directory + * pathaname is returned. + * size - The size in bytes avaiable at 'buf' + * + * Returned Value: + * Upon successful completion, getcwd() returns the 'buf' argument. + * Otherwise, getcwd() returns a null pointer and sets errno to indicate + * the error: + * + * EINVAL + * The 'size' argument is 0 or the 'buf' argument is NULL. + * ERANGE + * The size argument is greater than 0, but is smaller than the length + * of the currrent working directory pathname +1. + * EACCES + * Read or search permission was denied for a component of the pathname. + * ENOMEM + * Insufficient storage space is available. + * + ****************************************************************************/ + +FAR char *getcwd(FAR char *buf, size_t size) +{ + char *pwd; + + /* Verify input parameters */ + +#ifdef CONFIG_DEBUG + if (!buf || !size) + { + set_errno(EINVAL); + return NULL; + } +#endif + + /* If no working directory is defined, then default to the home directory */ + + pwd = getenv("PWD"); + if (!pwd) + { + pwd = CONFIG_LIB_HOMEDIR; + } + + /* Verify that the cwd will fit into the user-provided buffer */ + + if (strlen(pwd) + 1 > size) + { + set_errno(ERANGE); + return NULL; + } + + /* Copy the cwd to the user buffer */ + + strcpy(buf, pwd); + sched_unlock(); + return buf; +} +#endif /* CONFIG_NFILE_DESCRIPTORS && !CONFIG_DISABLE_ENVIRON */ diff --git a/nuttx/lib/unistd/lib_getopt.c b/nuttx/lib/unistd/lib_getopt.c new file mode 100644 index 0000000000..26a2c7fae4 --- /dev/null +++ b/nuttx/lib/unistd/lib_getopt.c @@ -0,0 +1,269 @@ +/**************************************************************************** + * lib/unistd/lib_getopt.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +FAR char *optarg; /* Optional argument following option */ +int optind = 1; /* Index into argv */ +int optopt = '?'; /* unrecognized option character */ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +static FAR char *g_optptr = NULL; +static bool g_binitialized = false; + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getopt + * + * Description: getopt() parses command-line arguments. Its arguments argc + * and argv are the argument count and array as passed to the main() + * function on program invocation. An element of argv that starts with + * '-' is an option element. The characters of this element (aside from + * the initial '-') are option characters. If getopt() is called repeatedly, + * it returns successively each of the option characters from each of the + * option elements. + * + * If getopt() finds another option character, it returns that character, + * updating the external variable optind and a static variable nextchar so + * that the next call to getopt() can resume the scan with the following + * option character or argv-element. + * + * If there are no more option characters, getopt() returns -1. Then optind + * is the index in argv of the first argv-element that is not an option. + * + * The 'optstring' argument is a string containing the legitimate option + * characters. If such a character is followed by a colon, this indicates + * that the option requires an argument. If an argument is required for an + * option so getopt() places a pointer to the following text in the same + * argv-element, or the text of the following argv-element, in optarg. + * + * NOTES: + * 1. opterr is not supported and this implementation of getopt() never + * printfs error messages. + * 2. getopt is NOT threadsafe! + * 3. This version of getopt() does not reset global variables until + * -1 is returned. As a result, your command line parsing loops + * must call getopt() repeatedly and continue to parse if other + * errors are returned ('?' or ':') until getopt() finally returns -1. + * (You can also set optind to -1 to force a reset). + * + * Return: If an option was successfully found, then getopt() returns the + * option character. If all command-line options have been parsed, then + * getopt() returns -1. If getopt() encounters an option character that + * was not in optstring, then '?' is returned. If getopt() encounters an + * option with a missing argument, then the return value depends on the + * first character in optstring: if it is ':', then ':' is returned; + * otherwise '?' is returned. + * + ****************************************************************************/ + +int getopt(int argc, FAR char *const argv[], FAR const char *optstring) +{ + if (argv && optstring && argc > 1) + { + int noarg_ret = '?'; + char *optchar; + + /* The inital value of optind is 1. If getopt() is called again in the + * program, optind must be reset to some value <= 1. + */ + + if (optind < 1 || !g_binitialized) + { + optind = 1; /* Skip over the program name */ + g_optptr = NULL; /* Start at the beginning of the first argument */ + g_binitialized = true; /* Now we are initialized */ + } + + /* If the first character of opstring s ':', then ':' is in the event of + * a missing argument. Otherwise '?' is returned. + */ + + if (*optstring == ':') + { + noarg_ret = ':'; + optstring++; + } + + /* Are we resuming in the middle, or at the end of a string of arguments? + * g_optptr == NULL means that we are started at the beginning of argv[optind]; + * *g_optptr == \0 means that we are starting at the beginning of optind+1 + */ + + while (!g_optptr || !*g_optptr) + { + /* We need to start at the beginning of the next argv. Check if we need + * to increment optind + */ + + if (g_optptr) + { + /* Yes.. Increment it and check for the case where where we have + * processed everything in the argv[] array. + */ + + optind++; + } + + /* Check for the end of the argument list */ + + g_optptr = argv[optind]; + if (!g_optptr) + { + /* There are no more arguments, we are finished */ + + g_binitialized = false; + return ERROR; + } + + /* We are starting at the beginning of argv[optind]. In this case, the + * first character must be '-' + */ + + if (*g_optptr != '-') + { + /* The argument does not start with '-', we are finished */ + + g_binitialized = false; + return ERROR; + } + + /* Skip over the '-' */ + + g_optptr++; + } + + /* Special case handling of "-" and "-:" */ + + if (!*g_optptr) + { + optopt = '\0'; /* We'll fix up g_optptr the next time we are called */ + return '?'; + } + + /* Handle the case of "-:" */ + + if (*g_optptr == ':') + { + optopt = ':'; + g_optptr++; + return '?'; + } + + /* g_optptr now points at the next option and it is not something crazy. + * check if the option is in the list of valid options. + */ + + optchar = strchr(optstring, *g_optptr); + if (!optchar) + { + /* No this character is not in the list of valid options */ + + optopt = *g_optptr; + g_optptr++; + return '?'; + } + + /* Yes, the character is in the list of valid options. Does it have an + * required argument? + */ + + if (optchar[1] != ':') + { + /* No, no arguments. Just return the character that we found */ + + g_optptr++; + return *optchar; + } + + /* Yes, it has a required argument. Is the required argument + * immediately after the command in this same argument? + */ + + if (g_optptr[1] != '\0') + { + /* Yes, return a pointer into the current argument */ + + optarg = &g_optptr[1]; + optind++; + g_optptr = NULL; + return *optchar; + } + + /* No.. is the optional argument the next argument in argv[] ? */ + + if (argv[optind+1] && *argv[optind+1] != '-') + { + /* Yes.. return that */ + + optarg = argv[optind+1]; + optind += 2; + g_optptr = NULL; + return *optchar; + } + + /* No argument was supplied */ + + optarg = NULL; + optopt = *optchar; + optind++; + return noarg_ret; + } + + g_binitialized = false; + return ERROR; +} diff --git a/nuttx/lib/unistd/lib_getoptargp.c b/nuttx/lib/unistd/lib_getoptargp.c new file mode 100644 index 0000000000..4a483c051b --- /dev/null +++ b/nuttx/lib/unistd/lib_getoptargp.c @@ -0,0 +1,73 @@ +/**************************************************************************** + * lib/unistd/lib_getoptargp.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getoptargp + * + * Description: + * Returns a pointer to optarg. This function is only used for external + * modules that need to access the base, global variable, optarg. + * + ****************************************************************************/ + +FAR char **getoptargp(void) +{ + return &optarg; +} + diff --git a/nuttx/lib/unistd/lib_getoptindp.c b/nuttx/lib/unistd/lib_getoptindp.c new file mode 100644 index 0000000000..002201aa94 --- /dev/null +++ b/nuttx/lib/unistd/lib_getoptindp.c @@ -0,0 +1,73 @@ +/**************************************************************************** + * lib/unistd/lib_getoptindp.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getoptindp + * + * Description: + * Returns a pointer to optind. This function is only used for external + * modules that need to access the base, global variable, optind. + * + ****************************************************************************/ + +int *getoptindp(void) +{ + return &optind; +} + diff --git a/nuttx/lib/unistd/lib_getoptoptp.c b/nuttx/lib/unistd/lib_getoptoptp.c new file mode 100644 index 0000000000..2214f2d141 --- /dev/null +++ b/nuttx/lib/unistd/lib_getoptoptp.c @@ -0,0 +1,73 @@ +/**************************************************************************** + * lib/unistd/lib_getoptoptp.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getoptoptp + * + * Description: + * Returns a pointer to optopt. This function is only used for external + * modules that need to access the base, global variable, optopt. + * + ****************************************************************************/ + +int *getoptoptp(void) +{ + return &optopt; +} + diff --git a/nuttx/libxx/Kconfig b/nuttx/libxx/Kconfig new file mode 100644 index 0000000000..4133a0ceb9 --- /dev/null +++ b/nuttx/libxx/Kconfig @@ -0,0 +1,27 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config HAVE_CXX + bool "Have C++ compiler" + default n + ---help--- + Toolchain supports C++ and CXX, CXXFLAGS, and COMPILEXX have been + defined in the configurations Make.defs file. + +config HAVE_CXXINITIALIZE + bool "Have C++ initialization" + default n + ---help--- + The platform-specific logic includes support for initialization + of static C++ instances for this architecture and for the selected + toolchain (via up_cxxinitialize()). + +config CXX_NEWLONG + bool "size_t is type long" + default n + ---help--- + size_t may be type long or type int. This matters for some + C++ library routines because the NuttX size_t might not have + the same underlying type as your toolchain's size_t. diff --git a/nuttx/libxx/Makefile b/nuttx/libxx/Makefile new file mode 100644 index 0000000000..f34a526000 --- /dev/null +++ b/nuttx/libxx/Makefile @@ -0,0 +1,80 @@ +############################################################################ +# libxx/Makefile +# +# Copyright (C) 2009 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +########################################################################### + +-include $(TOPDIR)/Make.defs + +ASRCS = +AOBJS = $(ASRCS:.S=$(OBJEXT)) +CSRCS = +COBJS = $(CSRCS:.c=$(OBJEXT)) +CXXSRCS = libxx_cxapurevirtual.cxx libxx_delete.cxx libxx_deletea.cxx \ + libxx_eabi_atexit.cxx libxx_new.cxx libxx_newa.cxx +CXXOBJS = $(CXXSRCS:.cxx=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) $(CXXSRCS) +OBJS = $(AOBJS) $(COBJS) $(CXXOBJS) + +BIN = liblibxx$(LIBEXT) + +all: $(BIN) + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(CXXOBJS): %$(OBJEXT): %.cxx + $(call COMPILEXX, $<, $@) + +$(BIN): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +.depend: Makefile $(SRCS) + @$(MKDEP) $(CXX) -- $(CXXFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f $(BIN) *~ .*.swp + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/libxx/README.txt b/nuttx/libxx/README.txt new file mode 100644 index 0000000000..6cf066f080 --- /dev/null +++ b/nuttx/libxx/README.txt @@ -0,0 +1,37 @@ +libxx/README.txt +^^^^^^^^^^^^^^^^ + +This directory contains a fragmentary C++ library that will allow +to build only the simplest of C++ applications. In the deeply +embedded world, that is probably all that is necessary. If you +have a need for more extensive C++ support, the following libraries +are recommended: + + - libstdc++ (part of GCC) + - STLport http://www.stlport.org/ + - uClibc++ http://cxx.uclibc.org/ + - uSTL http://ustl.sourceforge.net/ + +At present, only the following are supported here: + + - void *operator new(std::size_t nbytes); + - void operator delete(void* ptr); + - void operator delete[](void *ptr); + - void __cxa_pure_virtual(void); + - int __aeabi_atexit(void* object, void (*destroyer)(void*), void *dso_handle); + +operator new +------------ + + This operator should take a type of size_t. But size_t has an unknown underlying + type. In the nuttx sys/types.h header file, size_t is typed as uint32_t + (which is determined by architecture-specific logic). But the C++ + compiler may believe that size_t is of a different type resulting in + compilation errors in the operator. Using the underlying integer type + instead of size_t seems to resolve the compilation issues. Need to + REVISIT this. + + Once some C++ compilers, this will cause an error: + + Problem: "'operator new' takes size_t ('...') as first parameter" + Workaround: Add -fpermissive to the compilation flags diff --git a/nuttx/libxx/libxx_cxapurevirtual.cxx b/nuttx/libxx/libxx_cxapurevirtual.cxx new file mode 100644 index 0000000000..e8912558a5 --- /dev/null +++ b/nuttx/libxx/libxx_cxapurevirtual.cxx @@ -0,0 +1,69 @@ +//*************************************************************************** +// libxx/libxx_cxapurevirtual.cxx +// +// Copyright (C) 2009 2011 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Definitions +//*************************************************************************** + +//*************************************************************************** +// Private Data +//*************************************************************************** + +//*************************************************************************** +// Operators +//*************************************************************************** + +//*************************************************************************** +// Name: __cxa_pure_virtual +// +// Description: +// Crash when an un-implemented pure virtual function is called +// +//*************************************************************************** + +extern "C" +{ + void __cxa_pure_virtual(void) + { + PANIC(100); + } +} + diff --git a/nuttx/libxx/libxx_delete.cxx b/nuttx/libxx/libxx_delete.cxx new file mode 100644 index 0000000000..223a7bea90 --- /dev/null +++ b/nuttx/libxx/libxx_delete.cxx @@ -0,0 +1,62 @@ +//*************************************************************************** +// libxx/libxx_new.cxx +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include +#include + +//*************************************************************************** +// Definitions +//*************************************************************************** + +//*************************************************************************** +// Private Data +//*************************************************************************** + +//*************************************************************************** +// Operators +//*************************************************************************** + +//*************************************************************************** +// Name: delete +//*************************************************************************** + +void operator delete(void* ptr) +{ + free(ptr); +} diff --git a/nuttx/libxx/libxx_deletea.cxx b/nuttx/libxx/libxx_deletea.cxx new file mode 100644 index 0000000000..3c519bd2ce --- /dev/null +++ b/nuttx/libxx/libxx_deletea.cxx @@ -0,0 +1,62 @@ +//*************************************************************************** +// libxx/libxx_newa.cxx +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include +#include + +//*************************************************************************** +// Definitions +//*************************************************************************** + +//*************************************************************************** +// Private Data +//*************************************************************************** + +//*************************************************************************** +// Operators +//*************************************************************************** + +//*************************************************************************** +// Name: delete +//*************************************************************************** + +void operator delete[](void *ptr) +{ + free(ptr); +} diff --git a/nuttx/libxx/libxx_eabi_atexit.cxx b/nuttx/libxx/libxx_eabi_atexit.cxx new file mode 100644 index 0000000000..aa0ff6956c --- /dev/null +++ b/nuttx/libxx/libxx_eabi_atexit.cxx @@ -0,0 +1,83 @@ +//*************************************************************************** +// libxx/libxx_eabi_atexit.cxx +// +// Copyright (C) 2012 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include +#include + +//*************************************************************************** +// Definitions +//*************************************************************************** + +//*************************************************************************** +// Private Data +//*************************************************************************** + +extern "C" +{ + //************************************************************************* + // Public Data + //************************************************************************* + + void *__dso_handle = NULL; + + //************************************************************************* + // Public Functions + //************************************************************************* + + //************************************************************************* + // Name: __aeabi_atexit + // + // Description: + // Registers static object destructors. Normally atexit(f) should call + // __aeabi_atexit (NULL, f, NULL). But in the usage model here, static + // constructors are initialized at power up and are never destroyed + // because they have global scope and must persist for as long as the + // embedded device is powered on. + // + // Reference: + // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf + // + //************************************************************************* + + int __aeabi_atexit(void* object, void (*destroyer)(void*), void *dso_handle) + { + //return __cxa_atexit(destroyer, object, dso_handle); // 0 ? OK; non-0 ? failed } + return 0; + } +} diff --git a/nuttx/libxx/libxx_new.cxx b/nuttx/libxx/libxx_new.cxx new file mode 100644 index 0000000000..8ec725ca8b --- /dev/null +++ b/nuttx/libxx/libxx_new.cxx @@ -0,0 +1,102 @@ +//*************************************************************************** +// libxx/libxx_new.cxx +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include +#include +#include +#include + +//*************************************************************************** +// Definitions +//*************************************************************************** + +//*************************************************************************** +// Private Data +//*************************************************************************** + +//*************************************************************************** +// Operators +//*************************************************************************** + +//*************************************************************************** +// Name: new +// +// NOTE: +// This should take a type of size_t. But size_t has an unknown underlying +// type. In the nuttx sys/types.h header file, size_t is typed as uint32_t +// (which is determined by architecture-specific logic). But the C++ +// compiler may believe that size_t is of a different type resulting in +// compilation errors in the operator. Using the underlying integer type +// instead of size_t seems to resolve the compilation issues. Need to +// REVISIT this. +// +//*************************************************************************** + +//void *operator new(size_t nbytes) +#ifdef CONFIG_CXX_NEWLONG +void *operator new(unsigned long nbytes) +#else +void *operator new(unsigned int nbytes) +#endif +{ + // We have to allocate something + + if (nbytes < 1) + { + nbytes = 1; + } + + // Perform the allocation + + void *alloc = malloc(nbytes); + +#ifdef CONFIG_DEBUG + if (alloc == 0) + { + // Oh my.. we are required to return a valid pointer and + // we cannot throw an exception! We are bad. + + dbg("Failed to allocate\n"); + } +#endif + + // Return the allocated value + + return alloc; +} diff --git a/nuttx/libxx/libxx_newa.cxx b/nuttx/libxx/libxx_newa.cxx new file mode 100644 index 0000000000..855160c412 --- /dev/null +++ b/nuttx/libxx/libxx_newa.cxx @@ -0,0 +1,102 @@ +//*************************************************************************** +// libxx/libxx_newa.cxx +// +// Copyright (C) 2009 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include +#include +#include +#include + +//*************************************************************************** +// Definitions +//*************************************************************************** + +//*************************************************************************** +// Private Data +//*************************************************************************** + +//*************************************************************************** +// Operators +//*************************************************************************** + +//*************************************************************************** +// Name: new +// +// NOTE: +// This should take a type of size_t. But size_t has an unknown underlying +// type. In the nuttx sys/types.h header file, size_t is typed as uint32_t +// (which is determined by architecture-specific logic). But the C++ +// compiler may believe that size_t is of a different type resulting in +// compilation errors in the operator. Using the underlying integer type +// instead of size_t seems to resolve the compilation issues. Need to +// REVISIT this. +// +//*************************************************************************** + +//void *operator new[](size_t size) +#ifdef CONFIG_CXX_NEWLONG +void *operator new[](unsigned long nbytes) +#else +void *operator new[](unsigned int nbytes) +#endif +{ + // We have to allocate something + + if (nbytes < 1) + { + nbytes = 1; + } + + // Perform the allocation + + void *alloc = malloc(nbytes); + +#ifdef CONFIG_DEBUG + if (alloc == 0) + { + // Oh my.. we are required to return a valid pointer and + // we cannot throw an exception! We are bad. + + dbg("Failed to allocate\n"); + } +#endif + + // Return the allocated value + + return alloc; +} diff --git a/nuttx/mm/Kconfig b/nuttx/mm/Kconfig new file mode 100644 index 0000000000..000217dc5c --- /dev/null +++ b/nuttx/mm/Kconfig @@ -0,0 +1,26 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config MM_REGIONS + int "Number of memory regions" + default 1 + ---help--- + If the architecture includes multiple, non-contiguous regions of + memory to allocate from, this specifies the number of memory regions + that the memory manager must handle and enables the API + mm_addregion(start, end); + +config MM_SMALL + bool "Small memory model" + default n + ---help--- + Each memory allocation has a small allocation overhead. The size + of that overhead is normally determined by the "width" of the + address support by the MCU. MCUs that support 16-bit addressability + have smaller overhead than devices that support 32-bit addressability. + However, there are many MCUs that support 32-bit addressability *but* + have internal SRAM of size less than or equal to 64Kb. In this case, + CONFIG_MM_SMALL can be defined so that those MCUs will also benefit + from the smaller, 16-bit-based allocation overhead. diff --git a/nuttx/mm/Makefile b/nuttx/mm/Makefile new file mode 100644 index 0000000000..7e6eb68a75 --- /dev/null +++ b/nuttx/mm/Makefile @@ -0,0 +1,76 @@ +############################################################################ +# mm/Makefile +# +# Copyright (C) 2007 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ASRCS = +AOBJS = $(ASRCS:.S=$(OBJEXT)) +CSRCS = mm_initialize.c mm_sem.c mm_addfreechunk.c mm_size2ndx.c mm_shrinkchunk.c \ + mm_malloc.c mm_zalloc.c mm_calloc.c mm_realloc.c \ + mm_memalign.c mm_free.c mm_mallinfo.c +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = libmm$(LIBEXT) + +all: $(BIN) + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +.depend: Makefile $(SRCS) + @$(MKDEP) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f $(BIN) *~ .*.swp + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/mm/Makefile.test b/nuttx/mm/Makefile.test new file mode 100644 index 0000000000..63cab910e9 --- /dev/null +++ b/nuttx/mm/Makefile.test @@ -0,0 +1,64 @@ +############################################################################ +# mm/Makefile.test +# +# Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +SRCS = mm_test.c mm_initialize.c mm_sem.c mm_addfreechunk.c mm_size2ndx.c mm_shrinkchunk.c \ + mm_malloc.c mm_zalloc.c mm_calloc.c mm_realloc.c \ + mm_memalign.c mm_free.c mm_mallinfo.c +OBJS = $(SRCS:.c=.o1) + +LIBS = -lpthread -lc + +CC = gcc +LD = gcc + +DEFINES = -DMM_TEST=1 +WARNIGNS = -Wall -Wstrict-prototypes -Wshadow +CFLAGS = -g $(DEFINES) +LDFLAGS = + +BIN = ../mm_test + +all: $(BIN) + +$(OBJS): %.o1: %.c + @echo "Compiling $<" + $(CC) -c $(CFLAGS) $< -o $@ + +$(BIN): $(OBJS) + @echo "Linking {$(OBJS)} to produce $@" + $(LD) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ + +clean: + @rm -f $(BIN) *.o1 *~ diff --git a/nuttx/mm/mm_addfreechunk.c b/nuttx/mm/mm_addfreechunk.c new file mode 100644 index 0000000000..fdda3ed8d9 --- /dev/null +++ b/nuttx/mm/mm_addfreechunk.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * mm/mm_addfreechunk.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "mm_environment.h" +#include "mm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mm_addfreechunk + * + * Description: + * Add a free chunk to the node next. It is assumed that the caller holds + * the mm semaphore + * + ****************************************************************************/ + +void mm_addfreechunk(FAR struct mm_freenode_s *node) +{ + FAR struct mm_freenode_s *next; + FAR struct mm_freenode_s *prev; + + /* Convert the size to a nodelist index */ + + int ndx = mm_size2ndx(node->size); + + /* Now put the new node int the next */ + + for (prev = &g_nodelist[ndx], next = g_nodelist[ndx].flink; + next && next->size && next->size < node->size; + prev = next, next = next->flink); + + /* Does it go in mid next or at the end? */ + + prev->flink = node; + node->blink = prev; + node->flink = next; + + if (next) + { + /* The new node goes between prev and next */ + + next->blink = node; + } +} diff --git a/nuttx/mm/mm_calloc.c b/nuttx/mm/mm_calloc.c new file mode 100644 index 0000000000..576081a16b --- /dev/null +++ b/nuttx/mm/mm_calloc.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * mm/mm_calloc.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "mm_environment.h" +#include "mm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: calloc + * + * Descripton: + * calloc calculates the size of the allocation and calls zalloc + * + ****************************************************************************/ + +FAR void *calloc(size_t n, size_t elem_size) +{ + FAR void *ret = NULL; + + if (n > 0 && elem_size > 0) + { + ret = zalloc(n * elem_size); + } + + return ret; +} diff --git a/nuttx/mm/mm_environment.h b/nuttx/mm/mm_environment.h new file mode 100644 index 0000000000..70e611116a --- /dev/null +++ b/nuttx/mm/mm_environment.h @@ -0,0 +1,127 @@ +/**************************************************************************** + * mm/mm_environment.h + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __MM_MM_ENVIRONMENT_H +#define __MM_MM_ENVIRONMENT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* The platform configuratioin file will not be included when the memory + * manager is built for the host-based test harness. + */ + +#ifndef MM_TEST +# include +# include +# include +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Special definitions used when the memory mnager is built for the host- + * based test harness. + */ + +#ifdef MM_TEST + +/* Fake NuttX dependencies */ + +# define FAR /* Normally in compiler.h */ +# define CONFIG_CPP_HAVE_VARARGS 1 /* Normally in compiler.h */ +# define CONFIG_MM_REGIONS 2 /* Normally in config.h */ +# undef CONFIG_MM_SMALL /* Normally in config.h */ +# define CONFIG_CAN_PASS_STRUCTS 1 /* Normally in config.h */ +# undef CONFIG_SMALL_MEMORY /* Normally in config.h */ + +extern void mm_addregion(FAR void *heapstart, size_t heapsize); + +/* Use the real system errno */ + +# define mm_errno errno + +/* When built for the test harness, we change the names of the exported + * functions so that they do not collide with the host libc names. + */ + +# define malloc mm_malloc +# define memalign mm_memalign +# define realloc mm_realloc +# define zalloc mm_zalloc +# define calloc mm_calloc +# define free mm_free + +/* Use normal libc assertion functions */ + +# undef ASSERT +# define ASSERT(e) assert(e) +# undef DEBUGASSERT +# define DEBUGASSERT(e) assert(e) + +/* Debug macros are always on */ + +# define CONFIG_DEBUG + +# undef mdbg +# define mdbg(format, arg...) printf(format, ##arg) +# undef mvdg +# define mvdbg(format, arg...) printf(format, ##arg) + +#else +# define mm_errno get_errno() +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __MM_MM_ENVIRONMENT_H */ diff --git a/nuttx/mm/mm_free.c b/nuttx/mm/mm_free.c new file mode 100644 index 0000000000..b34b8a4593 --- /dev/null +++ b/nuttx/mm/mm_free.c @@ -0,0 +1,153 @@ +/**************************************************************************** + * mm/mm_free.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "mm_environment.h" +#include "mm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: free + * + * Description: + * Returns a chunk of memory into the list of free nodes, merging with + * adjacent free chunks if possible. + * + ****************************************************************************/ + +void free(FAR void *mem) +{ + FAR struct mm_freenode_s *node; + FAR struct mm_freenode_s *prev; + FAR struct mm_freenode_s *next; + + mvdbg("Freeing %p\n", mem); + + /* Protect against attempts to free a NULL reference */ + + if (!mem) + { + return; + } + + /* We need to hold the MM semaphore while we muck with the + * nodelist. + */ + + mm_takesemaphore(); + + /* Map the memory chunk into a free node */ + + node = (FAR struct mm_freenode_s *)((char*)mem - SIZEOF_MM_ALLOCNODE); + node->preceding &= ~MM_ALLOC_BIT; + + /* Check if the following node is free and, if so, merge it */ + + next = (FAR struct mm_freenode_s *)((char*)node + node->size); + if ((next->preceding & MM_ALLOC_BIT) == 0) + { + FAR struct mm_allocnode_s *andbeyond; + + /* Get the node following the next node (which will + * become the new next node). We know that we can never + * index past the tail chunk because it is always allocated. + */ + + andbeyond = (FAR struct mm_allocnode_s*)((char*)next + next->size); + + /* Remove the next node. There must be a predecessor, + * but there may not be a successor node. + */ + + DEBUGASSERT(next->blink); + next->blink->flink = next->flink; + if (next->flink) + { + next->flink->blink = next->blink; + } + + /* Then merge the two chunks */ + + node->size += next->size; + andbeyond->preceding = node->size | (andbeyond->preceding & MM_ALLOC_BIT); + next = (FAR struct mm_freenode_s *)andbeyond; + } + + /* Check if the preceding node is also free and, if so, merge + * it with this node + */ + + prev = (FAR struct mm_freenode_s *)((char*)node - node->preceding); + if ((prev->preceding & MM_ALLOC_BIT) == 0) + { + /* Remove the node. There must be a predecessor, but there may + * not be a successor node. + */ + + DEBUGASSERT(prev->blink); + prev->blink->flink = prev->flink; + if (prev->flink) + { + prev->flink->blink = prev->blink; + } + + /* Then merge the two chunks */ + + prev->size += node->size; + next->preceding = prev->size | (next->preceding & MM_ALLOC_BIT); + node = prev; + } + + /* Add the merged node to the nodelist */ + + mm_addfreechunk(node); + mm_givesemaphore(); +} diff --git a/nuttx/mm/mm_initialize.c b/nuttx/mm/mm_initialize.c new file mode 100644 index 0000000000..3a21d1759b --- /dev/null +++ b/nuttx/mm/mm_initialize.c @@ -0,0 +1,216 @@ +/**************************************************************************** + * mm/mm_initialize.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "mm_environment.h" +#include "mm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* This is the size of the heap provided to mm */ + +size_t g_heapsize; + +/* This is the first and last nodes of the heap */ + +FAR struct mm_allocnode_s *g_heapstart[CONFIG_MM_REGIONS]; +FAR struct mm_allocnode_s *g_heapend[CONFIG_MM_REGIONS]; + +#if CONFIG_MM_REGIONS > 1 +int g_nregions; +#endif + +/* All free nodes are maintained in a doubly linked list. This array + * provides some hooks into the list at various points to speed searches for + * free nodes. + */ + +FAR struct mm_freenode_s g_nodelist[MM_NNODES]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mm_initialize + * + * Description: + * This is an internal OS function called only at power-up boot time. + * + * Parameters: + * heapstart - Start of the initial heap region + * heapsize - Size of the initial heap region + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void mm_initialize(FAR void *heapstart, size_t heapsize) +{ + int i; + + mlldbg("Heap: start=%p size=%u\n", heapstart, heapsize); + + /* The following two lines have cause problems for some ZiLog compilers + * in the past. Life is easier if we just the suppress them for those + * tools. + */ + +#ifndef __ZILOG__ + CHECK_ALLOCNODE_SIZE; + CHECK_FREENODE_SIZE; +#endif + + /* Set up global variables */ + + g_heapsize = 0; + +#if CONFIG_MM_REGIONS > 1 + g_nregions = 0; +#endif + + /* Initialize the node array */ + + memset(g_nodelist, 0, sizeof(struct mm_freenode_s) * MM_NNODES); + for (i = 1; i < MM_NNODES; i++) + { + g_nodelist[i-1].flink = &g_nodelist[i]; + g_nodelist[i].blink = &g_nodelist[i-1]; + } + + /* Initialize the malloc semaphore to one (to support one-at- + * a-time access to private data sets). + */ + + mm_seminitialize(); + + /* Add the initial region of memory to the heap */ + + mm_addregion(heapstart, heapsize); +} + +/**************************************************************************** + * Name: mm_addregion + * + * Description: + * This function gives a region of contiguous memory to the memory manager + * + * Parameters: + * heapstart - Start of the heap region + * heapsize - Size of the heap region + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void mm_addregion(FAR void *heapstart, size_t heapsize) +{ + FAR struct mm_freenode_s *node; + uintptr_t heapbase; + uintptr_t heapend; +#if CONFIG_MM_REGIONS > 1 + int IDX = g_nregions; +#else +# define IDX 0 +#endif + + /* If the MCU handles wide addresses but the memory manager is configured + * for a small heap, then verify that the caller is not doing something + * crazy. + */ + +#if defined(CONFIG_MM_SMALL) && !defined(CONFIG_SMALL_MEMORY) + DEBUGASSERT(heapsize <= MMSIZE_MAX+1); +#endif + + /* Adjust the provide heap start and size so that they are both aligned + * with the MM_MIN_CHUNK size. + */ + + heapbase = MM_ALIGN_UP((uintptr_t)heapstart); + heapend = MM_ALIGN_DOWN((uintptr_t)heapstart + (uintptr_t)heapsize); + heapsize = heapend - heapbase; + + mlldbg("Region %d: base=%p size=%u\n", IDX+1, heapstart, heapsize); + + /* Add the size of this region to the total size of the heap */ + + g_heapsize += heapsize; + + /* Create two "allocated" guard nodes at the beginning and end of + * the heap. These only serve to keep us from allocating outside + * of the heap. + * + * And create one free node between the guard nodes that contains + * all available memory. + */ + + g_heapstart[IDX] = (FAR struct mm_allocnode_s *)heapbase; + g_heapstart[IDX]->size = SIZEOF_MM_ALLOCNODE; + g_heapstart[IDX]->preceding = MM_ALLOC_BIT; + + node = (FAR struct mm_freenode_s *)(heapbase + SIZEOF_MM_ALLOCNODE); + node->size = heapsize - 2*SIZEOF_MM_ALLOCNODE; + node->preceding = SIZEOF_MM_ALLOCNODE; + + g_heapend[IDX] = (FAR struct mm_allocnode_s *)(heapend - SIZEOF_MM_ALLOCNODE); + g_heapend[IDX]->size = SIZEOF_MM_ALLOCNODE; + g_heapend[IDX]->preceding = node->size | MM_ALLOC_BIT; + +#undef IDX + +#if CONFIG_MM_REGIONS > 1 + g_nregions++; +#endif + + /* Add the single, large free node to the nodelist */ + + mm_addfreechunk(node); +} diff --git a/nuttx/mm/mm_internal.h b/nuttx/mm/mm_internal.h new file mode 100644 index 0000000000..21cf253d7a --- /dev/null +++ b/nuttx/mm/mm_internal.h @@ -0,0 +1,243 @@ +/**************************************************************************** + * mm/mm_internal.h + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __MM_MM_INTERNAL_H +#define __MM_MM_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* If the MCU has a small (16-bit) address capability, then we will use + * a smaller chunk header that contains 16-bit size/offset information. + * We will also use the smaller header on MCUs with wider addresses if + * CONFIG_MM_SMALL is selected. This configuration is common with MCUs + * that have a large FLASH space, but only a tiny internal SRAM. + */ + +#ifdef CONFIG_SMALL_MEMORY + /* If the MCU has a small addressing capability, then for the smaller + * chunk header. + */ + +# undef CONFIG_MM_SMALL +# define CONFIG_MM_SMALL 1 +#endif + +/* Chunk Header Definitions *************************************************/ +/* These definitions define the characteristics of allocator + * + * MM_MIN_SHIFT is used to define MM_MIN_CHUNK. + * MM_MIN_CHUNK - is the smallest physical chunk that can + * be allocated. It must be at least a large as + * sizeof(struct mm_freenode_s). Larger values may + * improve performance slightly, but will waste memory + * due to quantization losses. + * + * MM_MAX_SHIFT is used to define MM_MAX_CHUNK + * MM_MAX_CHUNK is the largest, contiguous chunk of memory + * that can be allocated. It can range from 16-bytes to + * 4Gb. Larger values of MM_MAX_SHIFT can cause larger + * data structure sizes and, perhaps, minor performance + * losses. + */ + +#ifdef CONFIG_MM_SMALL +# define MM_MIN_SHIFT 4 /* 16 bytes */ +# define MM_MAX_SHIFT 15 /* 32 Kb */ +#else +# define MM_MIN_SHIFT 4 /* 16 bytes */ +# define MM_MAX_SHIFT 22 /* 4 Mb */ +#endif + +/* All other definitions derive from these two */ + +#define MM_MIN_CHUNK (1 << MM_MIN_SHIFT) +#define MM_MAX_CHUNK (1 << MM_MAX_SHIFT) +#define MM_NNODES (MM_MAX_SHIFT - MM_MIN_SHIFT + 1) + +#define MM_GRAN_MASK (MM_MIN_CHUNK-1) +#define MM_ALIGN_UP(a) (((a) + MM_GRAN_MASK) & ~MM_GRAN_MASK) +#define MM_ALIGN_DOWN(a) ((a) & ~MM_GRAN_MASK) + +/* An allocated chunk is distinguished from a free chunk by + * bit 31 of the 'preceding' chunk size. If set, then this is + * an allocated chunk. + */ + +#ifdef CONFIG_MM_SMALL +# define MM_ALLOC_BIT 0x8000 +#else +# define MM_ALLOC_BIT 0x80000000 +#endif +#define MM_IS_ALLOCATED(n) \ + ((int)((struct mm_allocnode_s*)(n)->preceding) < 0)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Determine the size of the chunk size/offset type */ + +#ifdef CONFIG_MM_SMALL + typedef uint16_t mmsize_t; +# define MMSIZE_MAX 0xffff +#else + typedef size_t mmsize_t; +# define MMSIZE_MAX SIZE_MAX +#endif + +/* This describes an allocated chunk. An allocated chunk is + * distinguished from a free chunk by bit 15/31 of the 'preceding' chunk + * size. If set, then this is an allocated chunk. + */ + +struct mm_allocnode_s +{ + mmsize_t size; /* Size of this chunk */ + mmsize_t preceding; /* Size of the preceding chunk */ +}; + +/* What is the size of the allocnode? */ + +#ifdef CONFIG_MM_SMALL +# define SIZEOF_MM_ALLOCNODE 4 +#else +# define SIZEOF_MM_ALLOCNODE 8 +#endif + +#define CHECK_ALLOCNODE_SIZE \ + DEBUGASSERT(sizeof(struct mm_allocnode_s) == SIZEOF_MM_ALLOCNODE) + +/* This describes a free chunk */ + +struct mm_freenode_s +{ + mmsize_t size; /* Size of this chunk */ + mmsize_t preceding; /* Size of the preceding chunk */ + FAR struct mm_freenode_s *flink; /* Supports a doubly linked list */ + FAR struct mm_freenode_s *blink; +}; + +/* What is the size of the freenode? */ + +#ifdef CONFIG_MM_SMALL +# ifdef CONFIG_SMALL_MEMORY +# define SIZEOF_MM_FREENODE 8 +# else +# define SIZEOF_MM_FREENODE 12 +# endif +#else +# define SIZEOF_MM_FREENODE 16 +#endif + +#define CHECK_FREENODE_SIZE \ + DEBUGASSERT(sizeof(struct mm_freenode_s) == SIZEOF_MM_FREENODE) + +/* Normally defined in stdlib.h */ + +#ifdef MM_TEST +struct mallinfo +{ + int arena; /* This is the total size of memory allocated + * for use by malloc in bytes. */ + int ordblks; /* This is the number of free (not in use) chunks */ + int mxordblk; /* Size of the largest free (not in use) chunk */ + int uordblks; /* This is the total size of memory occupied by + * chunks handed out by malloc. */ + int fordblks; /* This is the total size of memory occupied + * by free (not in use) chunks.*/ +}; +#endif + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* This is the size of the heap provided to mm */ + +extern size_t g_heapsize; + +/* This is the first and last nodes of the heap */ + +extern FAR struct mm_allocnode_s *g_heapstart[CONFIG_MM_REGIONS]; +extern FAR struct mm_allocnode_s *g_heapend[CONFIG_MM_REGIONS]; + +#if CONFIG_MM_REGIONS > 1 +extern int g_nregions; +#else +# define g_nregions 1 +#endif + +/* All free nodes are maintained in a doubly linked list. This + * array provides some hooks into the list at various points to + * speed searches for free nodes. + */ + +extern FAR struct mm_freenode_s g_nodelist[MM_NNODES]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef MM_TEST +FAR void *mm_malloc(size_t); +void mm_free(void*); +FAR void *mm_realloc(void*, size_t); +FAR void *mm_memalign(size_t, size_t); +FAR void *mm_zalloc(size_t); +FAR void *mm_calloc(size_t, size_t); +#ifdef CONFIG_CAN_PASS_STRUCTS +struct mallinfo mallinfo(void); +#else +int mallinfo(struct mallinfo *info); +#endif +#endif + +void mm_shrinkchunk(FAR struct mm_allocnode_s *node, size_t size); +void mm_addfreechunk(FAR struct mm_freenode_s *node); +int mm_size2ndx(size_t size); +void mm_seminitialize(void); +void mm_takesemaphore(void); +void mm_givesemaphore(void); +#ifdef MM_TEST +int mm_getsemaphore(void); +#endif + +#endif /* __MM_MM_INTERNAL_H */ diff --git a/nuttx/mm/mm_mallinfo.c b/nuttx/mm/mm_mallinfo.c new file mode 100644 index 0000000000..b725535d12 --- /dev/null +++ b/nuttx/mm/mm_mallinfo.c @@ -0,0 +1,146 @@ +/**************************************************************************** + * mm/mm_mallinfo.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "mm_environment.h" +#include "mm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mallinfo + * + * Description: + * mallinfo returns a copy of updated current mallinfo. + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_PASS_STRUCTS +struct mallinfo mallinfo(void) +#else +int mallinfo(struct mallinfo *info) +#endif +{ + struct mm_allocnode_s *node; + size_t mxordblk = 0; + int ordblks = 0; /* Number of non-inuse chunks */ + size_t uordblks = 0; /* Total allocated space */ + size_t fordblks = 0; /* Total non-inuse space */ +#if CONFIG_MM_REGIONS > 1 + int region; +#else +# define region 0 +#endif + +#ifdef CONFIG_CAN_PASS_STRUCTS + static struct mallinfo info; +#else + if (!info) + { + return ERROR; + } +#endif + + /* Visit each region */ + +#if CONFIG_MM_REGIONS > 1 + for (region = 0; region < g_nregions; region++) +#endif + { + /* Visit each node in the region */ + + for (node = g_heapstart[region]; + node < g_heapend[region]; + node = (struct mm_allocnode_s *)((char*)node + node->size)) + { + mvdbg("region=%d node=%p preceding=%p\n", region, node, node->preceding); + if (node->preceding & MM_ALLOC_BIT) + { + uordblks += node->size; + } + else + { + ordblks++; + fordblks += node->size; + if (node->size > mxordblk) + { + mxordblk = node->size; + } + } + } + + mvdbg("region=%d node=%p g_heapend=%p\n", region, node, g_heapend[region]); + DEBUGASSERT(node == g_heapend[region]); + uordblks += SIZEOF_MM_ALLOCNODE; /* account for the tail node */ + } +#undef region + + DEBUGASSERT(uordblks + fordblks == g_heapsize); + +#ifdef CONFIG_CAN_PASS_STRUCTS + info.arena = g_heapsize; + info.ordblks = ordblks; + info.mxordblk = mxordblk; + info.uordblks = uordblks; + info.fordblks = fordblks; + return info; +#else + info->arena = g_heapsize; + info->ordblks = ordblks; + info->mxordblk = mxordblk; + info->uordblks = uordblks; + info->fordblks = fordblks; + return OK; +#endif +} diff --git a/nuttx/mm/mm_malloc.c b/nuttx/mm/mm_malloc.c new file mode 100644 index 0000000000..8a21e73241 --- /dev/null +++ b/nuttx/mm/mm_malloc.c @@ -0,0 +1,201 @@ +/**************************************************************************** + * mm/mm_malloc.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Special definitions when we operate in the normal vs. the host-pc test + * environement. + */ + +#include + +#include "mm_environment.h" +#include "mm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef NULL +# define NULL ((void*)0) +#endif + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: malloc + * + * Description: + * Find the smallest chunk that satisfies the request. Take the memory from + * that chunk, save the remaining, smaller chunk (if any). + * + * 8-byte alignment of the allocated data is assured. + * + ****************************************************************************/ + +FAR void *malloc(size_t size) +{ + FAR struct mm_freenode_s *node; + void *ret = NULL; + int ndx; + + /* Handle bad sizes */ + + if (size <= 0) + { + return NULL; + } + + /* Adjust the size to account for (1) the size of the allocated node and + * (2) to make sure that it is an even multiple of our granule size. + */ + + size = MM_ALIGN_UP(size + SIZEOF_MM_ALLOCNODE); + + /* We need to hold the MM semaphore while we muck with the nodelist. */ + + mm_takesemaphore(); + + /* Get the location in the node list to start the search. Special case + * really big allocations + */ + + if (size >= MM_MAX_CHUNK) + { + ndx = MM_NNODES-1; + } + else + { + /* Convert the request size into a nodelist index */ + + ndx = mm_size2ndx(size); + } + + /* Search for a large enough chunk in the list of nodes. This list is + * ordered by size, but will have occasional zero sized nodes as we visit + * other g_nodelist[] entries. + */ + + for (node = g_nodelist[ndx].flink; + node && node->size < size; + node = node->flink); + + /* If we found a node with non-zero size, then this is one to use. Since + * the list is ordered, we know that is must be best fitting chunk + * available. + */ + + if (node) + { + FAR struct mm_freenode_s *remainder; + FAR struct mm_freenode_s *next; + size_t remaining; + + /* Remove the node. There must be a predecessor, but there may not be + * a successor node. + */ + + DEBUGASSERT(node->blink); + node->blink->flink = node->flink; + if (node->flink) + { + node->flink->blink = node->blink; + } + + /* Check if we have to split the free node into one of the allocated + * size and another smaller freenode. In some cases, the remaining + * bytes can be smaller (they may be SIZEOF_MM_ALLOCNODE). In that + * case, we will just carry the few wasted bytes at the end of the + * allocation. + */ + + remaining = node->size - size; + if (remaining >= SIZEOF_MM_FREENODE) + { + /* Get a pointer to the next node in physical memory */ + + next = (FAR struct mm_freenode_s*)(((char*)node) + node->size); + + /* Create the remainder node */ + + remainder = (FAR struct mm_freenode_s*)(((char*)node) + size); + remainder->size = remaining; + remainder->preceding = size; + + /* Adjust the size of the node under consideration */ + + node->size = size; + + /* Adjust the 'preceding' size of the (old) next node, preserving + * the allocated flag. + */ + + next->preceding = remaining | (next->preceding & MM_ALLOC_BIT); + + /* Add the remainder back into the nodelist */ + + mm_addfreechunk(remainder); + } + + /* Handle the case of an exact size match */ + + node->preceding |= MM_ALLOC_BIT; + ret = (void*)((char*)node + SIZEOF_MM_ALLOCNODE); + } + + mm_givesemaphore(); + mvdbg("Allocated %p, size %d\n", ret, size); + return ret; +} diff --git a/nuttx/mm/mm_memalign.c b/nuttx/mm/mm_memalign.c new file mode 100644 index 0000000000..87547c96bf --- /dev/null +++ b/nuttx/mm/mm_memalign.c @@ -0,0 +1,208 @@ +/**************************************************************************** + * mm/mm_memalign.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "mm_environment.h" +#include "mm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: memalign + * + * Description: + * memalign requests more than enough space from malloc, finds a region + * within that chunk that meets the alignment request and then frees any + * leading or trailing space. + * + * The alignment argument must be a power of two (not checked). 8-byte + * alignment is guaranteed by normal malloc calls. + * + ****************************************************************************/ + +FAR void *memalign(size_t alignment, size_t size) +{ + FAR struct mm_allocnode_s *node; + size_t rawchunk; + size_t alignedchunk; + size_t mask = (size_t)(alignment - 1); + size_t allocsize; + + /* If this requested alignement less than or equal to the natural alignment + * of malloc, then just let malloc do the work. + */ + + if (alignment <= MM_MIN_CHUNK) + { + return malloc(size); + } + + /* Adjust the size to account for (1) the size of the allocated node, (2) + * to make sure that it is an even multiple of our granule size, and to + * include the alignment amount. + * + * Notice that we increase the allocation size by twice the requested + * alignment. We do this so that there will be at least two valid + * alignment points within the allocated memory. + * + * NOTE: These are sizes given to malloc and not chunk sizes. They do + * not include SIZEOF_MM_ALLOCNODE. + */ + + size = MM_ALIGN_UP(size); /* Make multiples of our granule size */ + allocsize = size + 2*alignment; /* Add double full alignment size */ + + /* Then malloc that size */ + + rawchunk = (size_t)malloc(allocsize); + if (rawchunk == 0) + { + return NULL; + } + + /* We need to hold the MM semaphore while we muck with the chunks and + * nodelist. + */ + + mm_takesemaphore(); + + /* Get the node associated with the allocation and the next node after + * the allocation. + */ + + node = (FAR struct mm_allocnode_s*)(rawchunk - SIZEOF_MM_ALLOCNODE); + + /* Find the aligned subregion */ + + alignedchunk = (rawchunk + mask) & ~mask; + + /* Check if there is free space at the beginning of the aligned chunk */ + + if (alignedchunk != rawchunk) + { + FAR struct mm_allocnode_s *newnode; + FAR struct mm_allocnode_s *next; + size_t precedingsize; + + /* Get the node the next node after the allocation. */ + + next = (FAR struct mm_allocnode_s*)((char*)node + node->size); + + /* Make sure that there is space to convert the preceding mm_allocnode_s + * into an mm_freenode_s. I think that this should always be true + */ + + DEBUGASSERT(alignedchunk >= rawchunk + 8); + + newnode = (FAR struct mm_allocnode_s*)(alignedchunk - SIZEOF_MM_ALLOCNODE); + + /* Preceding size is full size of the new 'node,' including + * SIZEOF_MM_ALLOCNODE + */ + + precedingsize = (size_t)newnode - (size_t)node; + + /* If we were unlucky, then the alignedchunk can lie in such a position + * that precedingsize < SIZEOF_NODE_FREENODE. We can't let that happen + * because we are going to cast 'node' to struct mm_freenode_s below. + * This is why we allocated memory large enough to support two + * alignment points. In this case, we will simply use the second + * alignment point. + */ + + if (precedingsize < SIZEOF_MM_FREENODE) + { + alignedchunk += alignment; + newnode = (FAR struct mm_allocnode_s*)(alignedchunk - SIZEOF_MM_ALLOCNODE); + precedingsize = (size_t)newnode - (size_t)node; + } + + /* Set up the size of the new node */ + + newnode->size = (size_t)next - (size_t)newnode; + newnode->preceding = precedingsize | MM_ALLOC_BIT; + + /* Reduce the size of the original chunk and mark it not allocated, */ + + node->size = precedingsize; + node->preceding &= ~MM_ALLOC_BIT; + + /* Fix the preceding size of the next node */ + + next->preceding = newnode->size | (next->preceding & MM_ALLOC_BIT); + + /* Convert the newnode chunk size back into malloc-compatible size by + * subtracting the header size SIZEOF_MM_ALLOCNODE. + */ + + allocsize = newnode->size - SIZEOF_MM_ALLOCNODE; + + /* Add the original, newly freed node to the free nodelist */ + + mm_addfreechunk((FAR struct mm_freenode_s *)node); + + /* Replace the original node with the newlay realloaced, + * aligned node + */ + + node = newnode; + } + + /* Check if there is free space at the end of the aligned chunk */ + + if (allocsize > size) + { + /* Shrink the chunk by that much -- remember, mm_shrinkchunk wants + * internal chunk sizes that include SIZEOF_MM_ALLOCNODE, and not the + * malloc-compatible sizes that we have. + */ + + mm_shrinkchunk(node, size + SIZEOF_MM_ALLOCNODE); + } + + mm_givesemaphore(); + return (FAR void*)alignedchunk; +} diff --git a/nuttx/mm/mm_realloc.c b/nuttx/mm/mm_realloc.c new file mode 100644 index 0000000000..b449389958 --- /dev/null +++ b/nuttx/mm/mm_realloc.c @@ -0,0 +1,352 @@ +/**************************************************************************** + * mm/mm_realloc.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "mm_environment.h" +#include +#include "mm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: realloc + * + * Description: + * If the reallocation is for less space, then: + * + * (1) the current allocation is reduced in size + * (2) the remainder at the end of the allocation is returned to the + * free list. + * + * If the request is for more space and the current allocation can be + * extended, it will be extended by: + * + * (1) Taking the additional space from the following free chunk, or + * (2) Taking the additional space from the preceding free chunk. + * (3) Or both + * + * If the request is for more space but the current chunk cannot be + * extended, then malloc a new buffer, copy the data into the new buffer, + * and free the old buffer. + * + ****************************************************************************/ + +FAR void *realloc(FAR void *oldmem, size_t size) +{ + FAR struct mm_allocnode_s *oldnode; + FAR struct mm_freenode_s *prev; + FAR struct mm_freenode_s *next; + size_t oldsize; + size_t prevsize = 0; + size_t nextsize = 0; + FAR void *newmem; + + /* If oldmem is NULL, then realloc is equivalent to malloc */ + + if (!oldmem) + { + return malloc(size); + } + + /* If size is zero, then realloc is equivalent to free */ + + if (size <= 0) + { + free(oldmem); + return NULL; + } + + /* Adjust the size to account for (1) the size of the allocated node and + * (2) to make sure that it is an even multiple of our granule size. + */ + + size = MM_ALIGN_UP(size + SIZEOF_MM_ALLOCNODE); + + /* Map the memory chunk into an allocated node structure */ + + oldnode = (FAR struct mm_allocnode_s *)((FAR char*)oldmem - SIZEOF_MM_ALLOCNODE); + + /* We need to hold the MM semaphore while we muck with the nodelist. */ + + mm_takesemaphore(); + + /* Check if this is a request to reduce the size of the allocation. */ + + oldsize = oldnode->size; + if (size <= oldsize) + { + /* Handle the special case where we are not going to change the size + * of the allocation. + */ + + if (size < oldsize) + { + mm_shrinkchunk(oldnode, size); + } + + /* Then return the original address */ + + mm_givesemaphore(); + return oldmem; + } + + /* This is a request to increase the size of the allocation, Get the + * available sizes before and after the oldnode so that we can make the + * best decision + */ + + next = (FAR struct mm_freenode_s *)((FAR char*)oldnode + oldnode->size); + if ((next->preceding & MM_ALLOC_BIT) == 0) + { + nextsize = next->size; + } + + prev = (FAR struct mm_freenode_s *)((FAR char*)oldnode - (oldnode->preceding & ~MM_ALLOC_BIT)); + if ((prev->preceding & MM_ALLOC_BIT) == 0) + { + prevsize = prev->size; + } + + /* Now, check if we can extend the current allocation or not */ + + if (nextsize + prevsize + oldsize >= size) + { + size_t needed = size - oldsize; + size_t takeprev = 0; + size_t takenext = 0; + + /* Check if we can extend into the previous chunk and if the + * previous chunk is smaller than the next chunk. + */ + + if (prevsize > 0 && (nextsize >= prevsize || nextsize <= 0)) + { + /* Can we get everything we need from the previous chunk? */ + + if (needed > prevsize) + { + /* No, take the whole previous chunk and get the + * rest that we need from the next chunk. + */ + + takeprev = prevsize; + takenext = needed - prevsize; + } + else + { + /* Yes, take what we need from the previous chunk */ + + takeprev = needed; + takenext = 0; + } + + needed = 0; + } + + /* Check if we can extend into the next chunk and if we still need + * more memory. + */ + + if (nextsize > 0 && needed) + { + /* Can we get everything we need from the next chunk? */ + + if (needed > nextsize) + { + /* No, take the whole next chunk and get the rest that we + * need from the previous chunk. + */ + + takeprev = needed - nextsize; + takenext = nextsize; + } + else + { + /* Yes, take what we need from the previous chunk */ + + takeprev = 0; + takenext = needed; + } + } + + /* Extend into the previous free chunk */ + + newmem = oldmem; + if (takeprev) + { + FAR struct mm_allocnode_s *newnode; + + /* Remove the previous node. There must be a predecessor, but + * there may not be a successor node. + */ + + DEBUGASSERT(prev->blink); + prev->blink->flink = prev->flink; + if (prev->flink) + { + prev->flink->blink = prev->blink; + } + + /* Extend the node into the previous free chunk */ + + newnode = (FAR struct mm_allocnode_s *)((FAR char*)oldnode - takeprev); + + /* Did we consume the entire preceding chunk? */ + + if (takeprev < prevsize) + { + /* No.. just take what we need from the previous chunk and put + * it back into the free list + */ + + prev->size -= takeprev; + newnode->size = oldsize + takeprev; + newnode->preceding = prev->size | MM_ALLOC_BIT; + next->preceding = newnode->size | (next->preceding & MM_ALLOC_BIT); + + /* Return the previous free node to the nodelist (with the new size) */ + + mm_addfreechunk(prev); + + /* Now we want to return newnode */ + + oldnode = newnode; + } + else + { + /* Yes.. update its size (newnode->preceding is already set) */ + + newnode->size += oldsize; + newnode->preceding |= MM_ALLOC_BIT; + next->preceding = newnode->size | (next->preceding & MM_ALLOC_BIT); + } + + oldnode = newnode; + oldsize = newnode->size; + + /* Now we have to move the user contents 'down' in memory. memcpy should + * should be save for this. + */ + + newmem = (FAR void*)((FAR char*)newnode + SIZEOF_MM_ALLOCNODE); + memcpy(newmem, oldmem, oldsize - SIZEOF_MM_ALLOCNODE); + } + + /* Extend into the next free chunk */ + + if (takenext) + { + FAR struct mm_freenode_s *newnode; + FAR struct mm_allocnode_s *andbeyond; + + /* Get the chunk following the next node (which could be the tail + * chunk) + */ + + andbeyond = (FAR struct mm_allocnode_s*)((char*)next + nextsize); + + /* Remove the next node. There must be a predecessor, but there + * may not be a successor node. + */ + + DEBUGASSERT(next->blink); + next->blink->flink = next->flink; + if (next->flink) + { + next->flink->blink = next->blink; + } + + /* Extend the node into the next chunk */ + + oldnode->size = oldsize + takenext; + newnode = (FAR struct mm_freenode_s *)((char*)oldnode + oldnode->size); + + /* Did we consume the entire preceding chunk? */ + + if (takenext < nextsize) + { + /* No, take what we need from the next chunk and return it to + * the free nodelist. + */ + + newnode->size = nextsize - takenext; + newnode->preceding = oldnode->size; + andbeyond->preceding = newnode->size | (andbeyond->preceding & MM_ALLOC_BIT); + + /* Add the new free node to the nodelist (with the new size) */ + + mm_addfreechunk(newnode); + } + else + { + /* Yes, just update some pointers. */ + + andbeyond->preceding = oldnode->size | (andbeyond->preceding & MM_ALLOC_BIT); + } + } + + mm_givesemaphore(); + return newmem; + } + + /* The current chunk cannot be extended. Just allocate a new chunk and copy */ + + else + { + /* Allocate a new block. On failure, realloc must return NULL but + * leave the original memory in place. + */ + + mm_givesemaphore(); + newmem = (FAR void*)malloc(size); + if (newmem) + { + memcpy(newmem, oldmem, oldsize); + free(oldmem); + } + + return newmem; + } +} diff --git a/nuttx/mm/mm_sem.c b/nuttx/mm/mm_sem.c new file mode 100644 index 0000000000..19fff780b9 --- /dev/null +++ b/nuttx/mm/mm_sem.c @@ -0,0 +1,247 @@ +/**************************************************************************** + * mm/mm_sem.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "mm_environment.h" + +#include +#include +#include +#include + +#include "mm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Define the following to enable semaphore state monitoring */ +//#define MONITOR_MM_SEMAPHORE 1 + +#ifdef MONITOR_MM_SEMAPHORE +# ifdef CONFIG_DEBUG +# include +# define msemdbg dbg +# else +# define msemdbg printf +# endif +#else +# ifdef CONFIG_CPP_HAVE_VARARGS +# define msemdbg(x...) +# else +# define msemdbg (void) +# endif +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Mutually exclusive access to this data set is enforced with + * the following (un-named) semaphore. */ + +static sem_t g_mm_semaphore; +static pid_t g_holder; +static int g_counts_held; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mm_seminitialize + * + * Description: + * Initialize the MM mutex + * + ****************************************************************************/ + +void mm_seminitialize(void) +{ + /* Initialize the MM semaphore to one (to support one-at-a-time access to + * private data sets. + */ + + (void)sem_init(&g_mm_semaphore, 0, 1); + + g_holder = -1; + g_counts_held = 0; +} + +/**************************************************************************** + * Name: mm_trysemaphore + * + * Description: + * Try to take the MM mutex. This is called only from the OS in certain + * conditions when it is necessary to have exclusive access to the memory + * manager but it is impossible to wait on a semaphore (e.g., the idle + * process when it performs its background memory cleanup). + * + ****************************************************************************/ + +#ifndef MM_TEST +int mm_trysemaphore(void) +{ + pid_t my_pid = getpid(); + + /* Do I already have the semaphore? */ + + if (g_holder == my_pid) + { + /* Yes, just increment the number of references that I have */ + + g_counts_held++; + return OK; + } + else + { + /* Try to take the semaphore (perhaps waiting) */ + + if (sem_trywait(&g_mm_semaphore) != 0) + { + return ERROR; + } + + /* We have it. Claim the stak and return */ + + g_holder = my_pid; + g_counts_held = 1; + return OK; + } +} +#endif + +/**************************************************************************** + * Name: mm_takesemaphore + * + * Description: + * Take the MM mutex. This is the normal action before all memory + * management actions. + * + ****************************************************************************/ + +void mm_takesemaphore(void) +{ + pid_t my_pid = getpid(); + + /* Do I already have the semaphore? */ + + if (g_holder == my_pid) + { + /* Yes, just increment the number of references that I have */ + + g_counts_held++; + } + else + { + /* Take the semaphore (perhaps waiting) */ + + msemdbg("PID=%d taking\n", my_pid); + while (sem_wait(&g_mm_semaphore) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(mm_errno == EINTR); + } + + /* We have it. Claim the stake and return */ + + g_holder = my_pid; + g_counts_held = 1; + } + + msemdbg("Holder=%d count=%d\n", g_holder, g_counts_held); +} + +/**************************************************************************** + * Name: mm_givesemaphore + * + * Description: + * Release the MM mutex when it is not longer needed. + * + ****************************************************************************/ + +void mm_givesemaphore(void) +{ +#ifdef CONFIG_DEBUG + pid_t my_pid = getpid(); +#endif + + /* I better be holding at least one reference to the semaphore */ + + DEBUGASSERT(g_holder == my_pid); + + /* Do I hold multiple references to the semphore */ + + if (g_counts_held > 1) + { + /* Yes, just release one count and return */ + + g_counts_held--; + msemdbg("Holder=%d count=%d\n", g_holder, g_counts_held); + } + else + { + /* Nope, this is the last reference I have */ + + msemdbg("PID=%d giving\n", my_pid); + g_holder = -1; + g_counts_held = 0; + ASSERT(sem_post(&g_mm_semaphore) == 0); + } +} + +/**************************************************************************** + * Name: mm_getsemaphore + * + * Description: + * Return the current value of the MM semaphore (for test purposes only) + * + ****************************************************************************/ + +#ifdef MM_TEST +int mm_getsemaphore(void) +{ + int sval; + sem_getvalue(&g_mm_semaphore, &sval); + return sval; +} +#endif + diff --git a/nuttx/mm/mm_shrinkchunk.c b/nuttx/mm/mm_shrinkchunk.c new file mode 100644 index 0000000000..e538e43edb --- /dev/null +++ b/nuttx/mm/mm_shrinkchunk.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * mm/mm_shrinkchunk.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "mm_environment.h" +#include "mm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mm_shrinkchunk + * + * Description: + * Reduce the size of the chunk specified by the node structure to the + * specified size. this internal logic is used both from memalign to + * dispose of any trailing memory in the aligned allocation and also by + * realloc when there is a request to reduce the size of an allocation. + * + * NOTES: + * (1) size is the whole chunk size (payload and header) + * (2) the caller must hold the MM semaphore. + * + ****************************************************************************/ + +void mm_shrinkchunk(FAR struct mm_allocnode_s *node, size_t size) +{ + FAR struct mm_freenode_s *next; + + /* Get a reference to the next node */ + + next = (FAR struct mm_freenode_s*)((char*)node + node->size); + + /* Check if it is free */ + + if ((next->preceding & MM_ALLOC_BIT) == 0) + { + FAR struct mm_allocnode_s *andbeyond; + FAR struct mm_freenode_s *newnode; + + /* Get the chunk next the next node (which could be the tail chunk) */ + + andbeyond = (FAR struct mm_allocnode_s*)((char*)next + next->size); + + /* Remove the next node. There must be a predecessor, but there may + * not be a successor node. + */ + + DEBUGASSERT(next->blink); + next->blink->flink = next->flink; + if (next->flink) + { + next->flink->blink = next->blink; + } + + /* Create a new chunk that will hold both the next chunk and the + * tailing memory from the aligned chunk. + */ + + newnode = (FAR struct mm_freenode_s*)((char*)node + size); + + /* Set up the size of the new node */ + + newnode->size = next->size + node->size - size; + newnode->preceding = size; + node->size = size; + andbeyond->preceding = newnode->size | (andbeyond->preceding & MM_ALLOC_BIT); + + /* Add the new node to the freenodelist */ + + mm_addfreechunk(newnode); + } + + /* The next chunk is allocated. Try to free the end portion at the end + * chunk to be shrunk. + */ + + else if (node->size >= size + SIZEOF_MM_FREENODE) + { + FAR struct mm_freenode_s *newnode; + + /* Create a new chunk that will hold both the next chunk and the + * tailing memory from the aligned chunk. + */ + + newnode = (FAR struct mm_freenode_s*)((char*)node + size); + + /* Set up the size of the new node */ + + newnode->size = node->size - size; + newnode->preceding = size; + node->size = size; + next->preceding = newnode->size | MM_ALLOC_BIT; + + /* Add the new node to the freenodelist */ + + mm_addfreechunk(newnode); + } +} diff --git a/nuttx/mm/mm_size2ndx.c b/nuttx/mm/mm_size2ndx.c new file mode 100644 index 0000000000..b2a0a8e142 --- /dev/null +++ b/nuttx/mm/mm_size2ndx.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * mm/mm_size2ndx.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "mm_environment.h" +#include "mm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mm_size2ndx + * + * Description: + * Convert the size to a nodelist index. + * + ****************************************************************************/ + +int mm_size2ndx(size_t size) +{ + int ndx = 0; + + if (size >= MM_MAX_CHUNK) + { + return MM_NNODES-1; + } + + size >>= MM_MIN_SHIFT; + while (size > 1) + { + ndx++; + size >>= 1; + } + + return ndx; +} diff --git a/nuttx/mm/mm_test.c b/nuttx/mm/mm_test.c new file mode 100644 index 0000000000..b25a240958 --- /dev/null +++ b/nuttx/mm/mm_test.c @@ -0,0 +1,535 @@ +/************************************************************************ + * mm/mm_test.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include +#include + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/* Fake NuttX dependencies */ + +#define FAR +#define CONFIG_MM_REGIONS 2 +#undef CONFIG_MM_SMALL +#define CONFIG_CAN_PASS_STRUCTS 1 +#undef CONFIG_SMALL_MEMORY + +#include "mm_internal.h" + +/* Pre-processor Definitions */ + +#define TEST_HEAP1_SIZE 0x00080000 +#define TEST_HEAP2_SIZE 0x00080000 +#define NTEST_ALLOCS 32 + +/* #define STOP_ON_ERRORS do{}while(0) */ +#define STOP_ON_ERRORS exit(1) + +/************************************************************************ + * Private Data + ************************************************************************/ + +/* Test allocations */ + +static const int alloc_sizes[NTEST_ALLOCS] = +{ + 1024, 12, 962, 5692, 10254, 111, 9932, 601, + 222, 2746, 3, 124321, 68, 776, 6750, 852, + 4732, 28, 901, 480, 5011, 1536, 2011, 81647, + 646, 1646, 69179, 194, 2590, 7, 969, 70 +}; + +static const int realloc_sizes[NTEST_ALLOCS] = +{ + 18, 3088, 963, 123, 511, 11666, 3723, 42, + 9374, 1990, 1412, 6, 592, 4088, 11, 5040, + 8663, 91255, 28, 4346, 9172, 168, 229, 4734, + 59139, 221, 7830, 30421, 1666, 4, 812, 416 +}; + +static const int random1[NTEST_ALLOCS] = +{ + 20, 11, 3, 31, 9, 29, 7, 17, + 21, 2, 26, 18, 14, 25, 0, 10, + 27, 19, 22, 28, 8, 30, 12, 15, + 4, 1, 24, 6, 16, 13, 5, 23 +}; + +static const int random2[NTEST_ALLOCS] = +{ + 2, 19, 12, 23, 30, 11, 27, 4, + 20, 7, 0, 16, 28, 15, 5, 24, + 10, 17, 25, 31, 8, 29, 3, 26, + 9, 18, 22, 13, 1, 21, 14, 6 +}; + +static const int random3[NTEST_ALLOCS] = +{ + 8, 17, 3, 18, 26, 23, 30, 11, + 12, 22, 4, 20, 25, 10, 27, 1, + 29, 14, 19, 21, 0, 31, 7, 24, + 9, 15, 2, 28, 16, 6, 13, 5 +}; + +static const int alignment[NTEST_ALLOCS/2] = +{ + 128, 2048, 131072, 8192, 32, 32768, 16384 , 262144, + 512, 4096, 65536, 8, 64, 1024, 16, 4 +}; + +static void *allocs[NTEST_ALLOCS]; +static struct mallinfo alloc_info; +static unsigned int g_reportedheapsize = 0; +static unsigned int g_actualheapsize = 0; + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Name: mm_findinfreelist + ************************************************************************/ + +static int mm_findinfreelist(struct mm_freenode_s *node) +{ + struct mm_freenode_s *list; + + for(list = &g_nodelist[0]; + list; + list = list->flink) + { + if (list == node) + { + return 1; + } + } + + return 0; +} + +/************************************************************************ + * Name: mm_showchunkinfo + ************************************************************************/ + +static void mm_showchunkinfo(void) +{ + struct mm_allocnode_s *node; +#if CONFIG_MM_REGIONS > 1 + int region; +#else +# define region 0 +#endif + int found; + + printf(" CHUNK LIST:\n"); + + /* Visit each region */ + +#if CONFIG_MM_REGIONS > 1 + for (region = 0; region < g_nregions; region++) +#endif + { + /* Visit each node in each region */ + + for (node = g_heapstart[region]; + node < g_heapend[region]; + node = (struct mm_allocnode_s *)((char*)node + node->size)) + { + printf(" %p 0x%08x 0x%08x %s", + node, node->size, node->preceding & ~MM_ALLOC_BIT, + node->preceding & MM_ALLOC_BIT ? "Allocated" : "Free "); + found = mm_findinfreelist((struct mm_freenode_s *)node); + if (found && (node->preceding & MM_ALLOC_BIT) != 0) + { + printf(" Should NOT have been in free list\n"); + } + else if (!found && (node->preceding & MM_ALLOC_BIT) == 0) + { + printf(" SHOULD have been in free listT\n"); + } + else + { + printf(" OK\n"); + } + } + } +#undef region +} + +/************************************************************************ + * Name: mm_showfreelist + ************************************************************************/ + +static void mm_showfreelist(void) +{ + struct mm_freenode_s *prev; + struct mm_freenode_s *node; + int i = 0; + + printf(" FREE NODE LIST:\n"); + for(prev = NULL, node = &g_nodelist[0]; + node; + prev = node, node = node->flink) + { + /* Dump "fake" nodes in a different way */ + + if (node->size == 0) + { + printf(" [NODE %2d] %08x %08x %08x\n", + i, node->preceding, (int)node->flink, (int)node->blink); + i++; + } + else + { + printf(" %08x %08x %08x %08x %08x\n", + (int)node, node->size, node->preceding, (int)node->flink, (int)node->blink); + } + + /* Verify all backward links */ + + if (node->blink != prev) + { + fprintf(stderr, "Backward link is wrong: Is %p, should be %p\n", + node->blink, prev); + STOP_ON_ERRORS; + } + } +} + +/************************************************************************ + * Name: mm_showmallinfo + ************************************************************************/ + +static void mm_showmallinfo(void) +{ + int sval; + + mm_showchunkinfo(); + mm_showfreelist(); + alloc_info = mallinfo(); + printf(" mallinfo:\n"); + printf(" Total space allocated from system = %ld\n", + alloc_info.arena); + printf(" Number of non-inuse chunks = %ld\n", + alloc_info.ordblks); + printf(" Largest non-inuse chunk = %ld\n", + alloc_info.mxordblk); + printf(" Total allocated space = %ld\n", + alloc_info.uordblks); + printf(" Total non-inuse space = %ld\n", + alloc_info.fordblks); + + sval = mm_getsemaphore(); + if (sval != 1) + { + fprintf(stderr, "After mallinfo, semaphore count=%d, should be 1\n", sval); + STOP_ON_ERRORS; + } + + if (!g_reportedheapsize) + { + g_reportedheapsize = alloc_info.uordblks + alloc_info.fordblks; + if (g_reportedheapsize > g_actualheapsize + 16*CONFIG_MM_REGIONS || + g_reportedheapsize < g_actualheapsize -16*CONFIG_MM_REGIONS) + { + fprintf(stderr, "Total memory %d not close to uordlbks=%d + fordblks=%d = %d\n", + g_actualheapsize, alloc_info.uordblks, alloc_info.fordblks, g_reportedheapsize); + STOP_ON_ERRORS; + } + } + else if (alloc_info.uordblks + alloc_info.fordblks != g_reportedheapsize) + { + fprintf(stderr, "Total memory %d != uordlbks=%d + fordblks=%d\n", + g_reportedheapsize, alloc_info.uordblks, alloc_info.fordblks); + STOP_ON_ERRORS; + } +} + +/************************************************************************ + * Name: do_mallocs + ************************************************************************/ + +static void do_mallocs(void **mem, const int *size, const int *rand, + int n) +{ + int sval; + int i; + int j; + + for (i = 0; i < n; i++) + { + j = rand[i]; + if (!mem[j]) + { + printf("(%d)Allocating %d bytes\n", i, size[j]); + mem[j] = mm_malloc(size[j]); + printf("(%d)Memory allocated at %p\n", i, mem[j]); + if (mem[j] == NULL) + { + int allocsize = MM_ALIGN_UP(size[j] + SIZEOF_MM_ALLOCNODE); + fprintf(stderr, "(%d)malloc failed for allocsize=%d\n", i, allocsize); + if (allocsize > alloc_info.mxordblk) + { + fprintf(stderr, " Normal, largest free block is only %ld\n", alloc_info.mxordblk); + } + else + { + fprintf(stderr, " ERROR largest free block is %ld\n", alloc_info.mxordblk); + exit(1); + } + } + else + { + memset(mem[j], 0xAA, size[j]); + } + + sval = mm_getsemaphore(); + if (sval != 1) + { + fprintf(stderr, " After malloc semaphore count=%d, should be 1\n", sval); + STOP_ON_ERRORS; + } + + mm_showmallinfo(); + } + } +} + +/************************************************************************ + * Name: do_reallocs + ************************************************************************/ + +static void do_reallocs(void **mem, const int *oldsize, + const int *newsize, const int *rand, int n) +{ + int sval; + int i; + int j; + + for (i = 0; i < n; i++) + { + j = rand[i]; + printf("(%d)Re-allocating at %p from %d to %d bytes\n", + i, mem[j], oldsize[j], newsize[j]); + mem[j] = mm_realloc(mem[j], newsize[j]); + printf("(%d)Memory re-allocated at %p\n", i, mem[j]); + if (mem[j] == NULL) + { + int allocsize = MM_ALIGN_UP(newsize[j] + SIZEOF_MM_ALLOCNODE); + fprintf(stderr, "(%d)realloc failed for allocsize=%d\n", i, allocsize); + if (allocsize > alloc_info.mxordblk) + { + fprintf(stderr, " Normal, largest free block is only %ld\n", alloc_info.mxordblk); + } + else + { + fprintf(stderr, " ERROR largest free block is %ld\n", alloc_info.mxordblk); + exit(1); + } + } + else + { + memset(mem[j], 0x55, newsize[j]); + } + + sval = mm_getsemaphore(); + if (sval != 1) + { + fprintf(stderr, " After realloc semaphore count=%d, should be 1\n", sval); + STOP_ON_ERRORS; + } + + mm_showmallinfo(); + } +} + +/************************************************************************ + * Name: do_memaligns + ************************************************************************/ + +static void do_memaligns(void **mem, const int *size, const int *align, + const int *rand, int n) +{ + int sval; + int i; + int j; + + for (i = 0; i < n; i++) + { + j = rand[i]; + printf("(%d)Allocating %d bytes aligned to 0x%08x\n", + i, size[j], align[i]); + mem[j] = mm_memalign(align[i], size[j]); + printf("(%d)Memory allocated at %p\n", i, mem[j]); + if (mem[j] == NULL) + { + int allocsize = MM_ALIGN_UP(size[j] + SIZEOF_MM_ALLOCNODE) + 2*align[i]; + fprintf(stderr, "(%d)memalign failed for allocsize=%d\n", i, allocsize); + if (allocsize > alloc_info.mxordblk) + { + fprintf(stderr, " Normal, largest free block is only %ld\n", alloc_info.mxordblk); + } + else + { + fprintf(stderr, " ERROR largest free block is %ld\n", alloc_info.mxordblk); + exit(1); + } + } + else + { + memset(mem[j], 0x33, size[j]); + } + + sval = mm_getsemaphore(); + if (sval != 1) + { + fprintf(stderr, " After memalign semaphore count=%d, should be 1\n", sval); + STOP_ON_ERRORS; + } + + mm_showmallinfo(); + } +} + +/************************************************************************ + * Name: do_frees + ************************************************************************/ + +static void do_frees(void **mem, const int *size, const int *rand, int n) +{ + int sval; + int i; + int j; + + for (i = 0; i < n; i++) + { + j = rand[i]; + printf("(%d)Releasing memory at %p (size=%d bytes)\n", + i, mem[j], size[j]); + mm_free(mem[j]); + mem[j] = NULL; + + sval = mm_getsemaphore(); + if (sval != 1) + { + fprintf(stderr, " After free semaphore count=%d, should be 1\n", sval); + STOP_ON_ERRORS; + } + + mm_showmallinfo(); + } +} + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: main + ************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + void *heap1_base; + void *heap2_base; + int i, j; + + /* Allocate a heap */ + + printf("Allocating test heap #1 of %ldKb\n", TEST_HEAP1_SIZE/1024); + heap1_base = malloc(TEST_HEAP1_SIZE); + printf("Allocated heap1_base=%p\n", heap1_base); + if (heap1_base == 0) + { + fprintf(stderr, "Failed to allocate test heap #1\n"); + exit(1); + } + + printf("Allocating test heap #2 of %ldKb\n", TEST_HEAP2_SIZE/1024); + heap2_base = malloc(TEST_HEAP2_SIZE); + printf("Allocated heap2_base=%p\n", heap2_base); + if (heap2_base == 0) + { + fprintf(stderr, "Failed to allocate test heap #2\n"); + exit(1); + } + + /* Initialize the memory manager */ + + mm_initialize(heap1_base, TEST_HEAP1_SIZE); + g_actualheapsize = TEST_HEAP1_SIZE; + mm_showmallinfo(); + + mm_addregion(heap2_base, TEST_HEAP2_SIZE); + g_reportedheapsize = 0; + g_actualheapsize += TEST_HEAP2_SIZE; + mm_showmallinfo(); + + /* Allocate some memory */ + + do_mallocs(allocs, alloc_sizes, random1, NTEST_ALLOCS); + + /* Re-allocate the memory */ + + do_reallocs(allocs, alloc_sizes, realloc_sizes, random2, NTEST_ALLOCS); + + /* Release the memory */ + + do_frees(allocs, realloc_sizes, random3, NTEST_ALLOCS); + + /* Allocate aligned memory */ + + do_memaligns(allocs, alloc_sizes, alignment, random2, NTEST_ALLOCS/2); + do_memaligns(allocs, alloc_sizes, alignment, &random2[NTEST_ALLOCS/2], NTEST_ALLOCS/2); + + /* Release aligned memory */ + + do_frees(allocs, alloc_sizes, random1, NTEST_ALLOCS); + + /* Clean up and exit */ + + free(heap1_base); + free(heap2_base); + + printf("TEST COMPLETE\n"); + return 0; +} diff --git a/nuttx/mm/mm_zalloc.c b/nuttx/mm/mm_zalloc.c new file mode 100644 index 0000000000..075777d0c4 --- /dev/null +++ b/nuttx/mm/mm_zalloc.c @@ -0,0 +1,68 @@ +/**************************************************************************** + * mm/mm_zalloc.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "mm_environment.h" +#include "mm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: zalloc + * + * Description: + * zalloc calls malloc, then zeroes out the allocated chunk. + * + ****************************************************************************/ + +FAR void *zalloc(size_t size) +{ + FAR void *alloc = malloc(size); + if (alloc) + { + memset(alloc, 0, size); + } + + return alloc; +} diff --git a/nuttx/net/Kconfig b/nuttx/net/Kconfig new file mode 100644 index 0000000000..dc16150ba6 --- /dev/null +++ b/nuttx/net/Kconfig @@ -0,0 +1,271 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config NET + bool "Networking support" + default n + ---help--- + Enable or disable all network features + +if NET + +config NET_NOINTS + bool "Not interrupt driven" + default n + ---help--- + NET_NOINT indicates that uIP not called from the interrupt level. + If NET_NOINTS is defined, critical sections will be managed with semaphores; + Otherwise, it assumed that uIP will be called from interrupt level handling + and critical sections will be managed by enabling and disabling interrupts. + +config NET_MULTIBUFFER + bool "Use multiple device-side I/O buffers" + default n + ---help--- + Traditionally, uIP has used a single buffer for all incoming and + outgoing traffic. If this configuration is selected, then the + driver can manage multiple I/O buffers and can, for example, + be filling one input buffer while sending another output buffer. + Or, as another example, the driver may support queuing of concurrent + input/ouput and output transfers for better performance. + +config NET_IPv6 + bool "IPv6" + default n + ---help--- + Build in support for IPv6. Not fully implemented. + +config NSOCKET_DESCRIPTORS + int "Number of socket descriptor" + default 8 + ---help--- + Maximum number of socket descriptors per task/thread. + +config NET_NACTIVESOCKETS + int "Max socket operations" + ---help--- + Maximum number of concurrent socket operations (recv, send, etc.). + Default: NET_TCP_CONNS+NET_UCP_CONNS + +config NET_SOCKOPTS + bool "Socket options" + default n + ---help--- + Enable or disable support for socket options + +config NET_BUFSIZE + int "Network packet size" + default 562 if !NET_TCP && NET_UDP && !NET_SLIP + default 420 if NET_TCP && !NET_UDP && !NET_SLIP + default 296 if NET_SLIP + ---help--- + uIP buffer size. Default: 562 + +config NET_TCPURGDATA + bool "Urgent data" + default n + ---help--- + Determines if support for TCP urgent data notification should be + compiled in. Urgent data (out-of-band data) is a rarely used TCP feature + that is very seldom would be required. + +config NET_TCP + bool "TCP/IP Networking" + default n + ---help--- + TCP support on or off + +endif + +if NET_TCP +config NET_TCP_CONNS + int "Number of TCP/IP connections" + default 8 + ---help--- + Maximum number of TCP/IP connections (all tasks) + +config NET_MAX_LISTENPORTS + int "Number of listening ports" + default 20 + ---help--- + Maximum number of listening TCP/IP ports (all tasks). Default: 20 + +config NET_TCP_READAHEAD_BUFSIZE + bool "TCP/IP read-ahead buffer size" + default 562 + ---help--- + Size of TCP/IP read-ahead buffers + +config NET_NTCP_READAHEAD_BUFFERS + int "Number of TCP/IP read-ahead buffers" + default 8 + ---help--- + Number of TCP/IP read-ahead buffers (may be zero) + +config NET_TCPBACKLOG + bool "TCP/IP backlog support" + default n + ---help--- + Incoming connections pend in a backlog until accept() is called. + The size of the backlog is selected when listen() is called. + +endif + +config NET_UDP + bool "UDP Networking" + default n + depends on NET + ---help--- + Enable or disable UDP networking support. + +if NET_UDP +config NET_UDP_CHECKSUMS + bool "UDP checksums" + default n + ---help--- + Enable/disable UDP checksum support + +config NET_UDP_CONNS + int "Number of UDP sockets" + default 8 + ---help--- + The maximum amount of open concurrent UDP sockets + +config NET_BROADCAST + bool "UDP broadcast Rx support" + default n + ---help--- + Incoming UDP broadcast support + +endif + +config NET_ICMP + bool "ICMP networking support" + default n + depends on NET + ---help--- + Enable minimal ICMP support. Includes built-in support + for sending replies to received ECHO (ping) requests. + +if NET_ICMP +config NET_ICMP_PING + bool "ICMP ping interfaces" + default n + ---help--- + Provide interfaces to support application level support for + for sending ECHO (ping) requests and associating ECHO replies. + +config NET_PINGADDRCONF + bool "Ping address configuration" + default n + ---help--- + Use "ping" packet for setting IP address + +endif + +config NET_IGMP + bool "IGMPv2 clientsupport" + default n + depends on NET + ---help--- + Enable IGMPv2 client support. + +if NET_IGMP +config PREALLOC_IGMPGROUPS + int "Number of pre-allocated IGMP groups" + default 4 + ---help--- + Pre-allocated IGMP groups are used only if needed from interrupt + level group created (by the IGMP server). Default: 4. + +endif + +if NET + +config NET_STATISTICS + bool "Collect network statistics" + default n + ---help--- + uIP statistics on or off + +config NET_RECEIVE_WINDOW + int "Receive window size" + ---help--- + The size of the advertised receiver's window + +config NET_ARPTAB_SIZE + int "ARP table size" + default 16 + ---help--- + The size of the ARP table + +config NET_ARP_IPIN + bool "ARP address harvesting" + default n + ---help--- + Harvest IP/MAC address mappings from the ARP table + from incoming IP packets. + +config NET_MULTICAST + bool "Multi-cast Tx support" + default n + ---help--- + Outgoing multi-cast address support + +config NET_FWCACHE_SIZE + int "FW cache size" + ---help--- + Number of packets to remember when looking for duplicates + +config NET_SLIP + bool "SLIP support" + default n + ---help--- + Enables building of the SLIP driver. SLIP requires + at least one IP protocol selected and the following additional + network settings: NET_NOINTS and NET_MULTIBUFFER. + + NET_BUFSIZE *must* be set to 296. Other optional configuration + settings that affect the SLIP driver: NET_STATISTICS. + Default: Ethernet + + SLIP supports point-to-point IP communications over a serial port. + The default data link layer for uIP is Ethernet. If NET_SLIP is + defined in the NuttX configuration file, then SLIP will be supported. + The basic differences between the SLIP and Ethernet configurations is + that when SLIP is selected: + + * The link level header (that comes before the IP header) is omitted. + * All MAC address processing is suppressed. + * ARP is disabled. + + If NET_SLIP is not selected, then Ethernet will be used (there is + no need to define anything special in the configuration file to use + Ethernet -- it is the default). + +endif +if NET_SLIP + +config SLIP_NINTERFACES + int "Number of SLIP interfaces" + default 1 + ---help--- + Selects the number of physical SLIP + interfaces to support. + Default: 1 + +config SLIP_STACKSIZE + int "SLIP stack size" + default 2048 + ---help--- + Select the stack size of the SLIP RX and TX tasks. Default: 2048 + +config SLIP_DEFPRIO + int "SLIP priority" + default 128 + ---help--- + The priority of the SLIP RX and TX tasks. Default: 128 + +endif diff --git a/nuttx/net/Makefile b/nuttx/net/Makefile new file mode 100644 index 0000000000..506ef82138 --- /dev/null +++ b/nuttx/net/Makefile @@ -0,0 +1,123 @@ +############################################################################ +# net/Makefile +# +# Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ifeq ($(CONFIG_NET),y) + +# Basic networking support + +SOCK_ASRCS = +SOCK_CSRCS = bind.c connect.c getsockname.c recv.c recvfrom.c socket.c \ + sendto.c net_sockets.c net_close.c net_dup.c net_dup2.c net_clone.c \ + net_vfcntl.c + +# TCP/IP support + +ifeq ($(CONFIG_NET_TCP),y) +SOCK_CSRCS += send.c listen.c accept.c net_monitor.c +endif + +# Socket options + +ifeq ($(CONFIG_NET_SOCKOPTS),y) +SOCK_CSRCS += setsockopt.c getsockopt.c +ifneq ($(CONFIG_DISABLE_CLOCK),y) +SOCK_CSRCS += net_timeo.c net_dsec2timeval.c net_timeval2dsec.c +ifneq ($(CONFIG_NET_SLIP),y) +SOCK_CSRCS += net_arptimer.c +endif +endif +endif + +# Support for network access using streams + +ifneq ($(CONFIG_NFILE_STREAMS),0) +SOCK_CSRCS += net_checksd.c +endif + +# Support for operations on network devices + +NETDEV_ASRCS = +NETDEV_CSRCS = netdev_register.c netdev_ioctl.c net_poll.c netdev_txnotify.c \ + netdev_findbyname.c netdev_findbyaddr.c netdev_count.c \ + netdev_foreach.c netdev_unregister.c netdev_sem.c + +include uip/Make.defs +endif + +ASRCS = $(SOCK_ASRCS) $(NETDEV_ASRCS) $(UIP_ASRCS) +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +CSRCS = $(SOCK_CSRCS) $(NETDEV_CSRCS) $(UIP_CSRCS) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = libnet$(LIBEXT) + +VPATH = uip + +all: $(BIN) + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +.depend: Makefile $(SRCS) +ifeq ($(CONFIG_NET),y) + @$(MKDEP) --dep-path . --dep-path uip $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep +endif + @touch $@ + +depend: .depend + +clean: + @rm -f $(BIN) *~ .*.swp + @rm -f uip/*~ uip/.*.swp + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/net/accept.c b/nuttx/net/accept.c new file mode 100644 index 0000000000..07e3f983ef --- /dev/null +++ b/nuttx/net/accept.c @@ -0,0 +1,462 @@ +/**************************************************************************** + * net/accept.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET_TCP) + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "net_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct accept_s +{ + sem_t acpt_sem; /* Wait for interrupt event */ +#ifdef CONFIG_NET_IPv6 + FAR struct sockaddr_in6 *acpt_addr; /* Return connection adress */ +#else + FAR struct sockaddr_in *acpt_addr; /* Return connection adress */ +#endif + FAR struct uip_conn *acpt_newconn; /* The accepted connection */ + int acpt_result; /* The result of the wait */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: accept_tcpsender + * + * Description: + * Getting the sender's address from the UDP packet + * + * Parameters: + * conn - The newly accepted TCP connection + * pstate - the recvfrom state structure + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +#ifdef CONFIG_NET_IPv6 +static inline void accept_tcpsender(FAR struct uip_conn *conn, + FAR struct sockaddr_in6 *addr) +{ + if (addr) + { + addr->sin_family = AF_INET6; + addr->sin_port = conn->rport; + uip_ipaddr_copy(addr->sin6_addr.s6_addr, conn->ripaddr); + } +} +#else +static inline void accept_tcpsender(FAR struct uip_conn *conn, + FAR struct sockaddr_in *addr) +{ + if (addr) + { + addr->sin_family = AF_INET; + addr->sin_port = conn->rport; + uip_ipaddr_copy(addr->sin_addr.s_addr, conn->ripaddr); + } +} +#endif /* CONFIG_NET_IPv6 */ +#endif /* CONFIG_NET_TCP */ + +/**************************************************************************** + * Function: accept_interrupt + * + * Description: + * Receive interrupt level callbacks when connections occur + * + * Parameters: + * listener The conection stucture of the listener + * conn The connection stucture that was just accepted + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +static int accept_interrupt(struct uip_conn *listener, struct uip_conn *conn) +{ + struct accept_s *pstate = (struct accept_s *)listener->accept_private; + int ret = -EINVAL; + + if (pstate) + { + /* Get the connection address */ + + accept_tcpsender(conn, pstate->acpt_addr); + + /* Save the connection structure */ + + pstate->acpt_newconn = conn; + pstate->acpt_result = OK; + + /* There should be a reference of one on the new connection */ + + DEBUGASSERT(conn->crefs == 1); + + /* Wake-up the waiting caller thread */ + + sem_post(&pstate->acpt_sem); + + /* Stop any further callbacks */ + + listener->accept_private = NULL; + listener->accept = NULL; + ret = OK; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: accept + * + * Description: + * The accept function is used with connection-based socket types + * (SOCK_STREAM, SOCK_SEQPACKET and SOCK_RDM). It extracts the first + * connection request on the queue of pending connections, creates a new + * connected socket with mostly the same properties as 'sockfd', and + * allocates a new socket descriptor for the socket, which is returned. The + * newly created socket is no longer in the listening state. The original + * socket 'sockfd' is unaffected by this call. Per file descriptor flags + * are not inherited across an accept. + * + * The 'sockfd' argument is a socket descriptor that has been created with + * socket(), bound to a local address with bind(), and is listening for + * connections after a call to listen(). + * + * On return, the 'addr' structure is filled in with the address of the + * connecting entity. The 'addrlen' argument initially contains the size + * of the structure pointed to by 'addr'; on return it will contain the + * actual length of the address returned. + * + * If no pending connections are present on the queue, and the socket is + * not marked as non-blocking, accept blocks the caller until a connection + * is present. If the socket is marked non-blocking and no pending + * connections are present on the queue, accept returns EAGAIN. + * + * Parameters: + * sockfd The listening socket descriptior + * addr Receives the address of the connecting client + * addrlen Input: allocated size of 'addr', Return: returned size of 'addr' + * + * Returned Value: + * Returns -1 on error. If it succeeds, it returns a non-negative integer + * that is a descriptor for the accepted socket. + * + * EAGAIN or EWOULDBLOCK + * The socket is marked non-blocking and no connections are present to + * be accepted. + * EBADF + * The descriptor is invalid. + * ENOTSOCK + * The descriptor references a file, not a socket. + * EOPNOTSUPP + * The referenced socket is not of type SOCK_STREAM. + * EINTR + * The system call was interrupted by a signal that was caught before + * a valid connection arrived. + * ECONNABORTED + * A connection has been aborted. + * EINVAL + * Socket is not listening for connections. + * EMFILE + * The per-process limit of open file descriptors has been reached. + * ENFILE + * The system maximum for file descriptors has been reached. + * EFAULT + * The addr parameter is not in a writable part of the user address + * space. + * ENOBUFS or ENOMEM + * Not enough free memory. + * EPROTO + * Protocol error. + * EPERM + * Firewall rules forbid connection. + * + * Assumptions: + * + ****************************************************************************/ + +int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) +{ + FAR struct socket *psock = sockfd_socket(sockfd); + FAR struct socket *pnewsock; + FAR struct uip_conn *conn; + struct accept_s state; +#ifdef CONFIG_NET_IPv6 + FAR struct sockaddr_in6 *inaddr = (struct sockaddr_in6 *)addr; +#else + FAR struct sockaddr_in *inaddr = (struct sockaddr_in *)addr; +#endif + uip_lock_t save; + int newfd; + int err; + int ret; + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + /* It is not a valid socket description. Distinguish between the cases + * where sockfd is a just valid and when it is a valid file descriptor used + * in the wrong context. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + if ((unsigned int)sockfd < CONFIG_NFILE_DESCRIPTORS) + { + err = ENOTSOCK; + } + else +#endif + { + err = EBADF; + } + goto errout; + } + + /* We have a socket descriptor, but it is a stream? */ + + if (psock->s_type != SOCK_STREAM) + { + err = EOPNOTSUPP; + goto errout; + } + + /* Is the socket listening for a connection? */ + + if (!_SS_ISLISTENING(psock->s_flags)) + { + err = EINVAL; + goto errout; + } + + /* Verify that a valid memory block has been provided to receive the + * address + */ + + if (addr) + { +#ifdef CONFIG_NET_IPv6 + if (*addrlen < sizeof(struct sockaddr_in6)) +#else + if (*addrlen < sizeof(struct sockaddr_in)) +#endif + { + err = EBADF; + goto errout; + } + } + + /* Allocate a socket descriptor for the new connection now (so that it + * cannot fail later) + */ + + newfd = sockfd_allocate(0); + if (newfd < 0) + { + err = ENFILE; + goto errout; + } + + pnewsock = sockfd_socket(newfd); + if (!pnewsock) + { + err = ENFILE; + goto errout_with_socket; + } + + /* Check the backlog to see if there is a connection already pending for + * this listener. + */ + + save = uip_lock(); + conn = (struct uip_conn *)psock->s_conn; + +#ifdef CONFIG_NET_TCPBACKLOG + state.acpt_newconn = uip_backlogremove(conn); + if (state.acpt_newconn) + { + /* Yes... get the address of the connected client */ + + nvdbg("Pending conn=%p\n", state.acpt_newconn); + accept_tcpsender(state.acpt_newconn, inaddr); + } + + /* In general, this uIP-based implementation will not support non-blocking + * socket operations... except in a few cases: Here for TCP accept with backlog + * enabled. If this socket is configured as non-blocking then return EAGAIN + * if there is no pending connection in the backlog. + */ + + else if (_SS_ISNONBLOCK(psock->s_flags)) + { + err = EAGAIN; + goto errout_with_lock; + } + else +#endif + { + /* Set the socket state to accepting */ + + psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_ACCEPT); + + /* Perform the TCP accept operation */ + + /* Initialize the state structure. This is done with interrupts + * disabled because we don't want anything to happen until we + * are ready. + */ + + state.acpt_addr = inaddr; + state.acpt_newconn = NULL; + state.acpt_result = OK; + sem_init(&state.acpt_sem, 0, 0); + + /* Set up the callback in the connection */ + + conn->accept_private = (void*)&state; + conn->accept = accept_interrupt; + + /* Wait for the send to complete or an error to occur: NOTES: (1) + * uip_lockedwait will also terminate if a signal is received, (2) interrupts + * may be disabled! They will be re-enabled while the task sleeps and + * automatically re-enabled when the task restarts. + */ + + ret = uip_lockedwait(&state.acpt_sem); + + /* Make sure that no further interrupts are processed */ + + conn->accept_private = NULL; + conn->accept = NULL; + + sem_destroy(&state. acpt_sem); + + /* Set the socket state to idle */ + + psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); + + /* Check for a errors. Errors are signaled by negative errno values + * for the send length. + */ + + if (state.acpt_result != 0) + { + err = state.acpt_result; + goto errout_with_lock; + } + + /* If uip_lockedwait failed, then we were probably reawakened by a signal. In + * this case, uip_lockedwait will have set errno appropriately. + */ + + if (ret < 0) + { + err = -ret; + goto errout_with_lock; + } + } + + /* Initialize the socket structure and mark the socket as connected. + * (The reference count on the new connection structure was set in the + * interrupt handler). + */ + + pnewsock->s_type = SOCK_STREAM; + pnewsock->s_conn = state.acpt_newconn; + pnewsock->s_flags |= _SF_CONNECTED; + pnewsock->s_flags &= ~_SF_CLOSED; + + /* Begin monitoring for TCP connection events on the newly connected socket */ + + net_startmonitor(pnewsock); + uip_unlock(save); + return newfd; + +errout_with_lock: + uip_unlock(save); + +errout_with_socket: + sockfd_release(newfd); + +errout: + errno = err; + return ERROR; +} + +#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS && CONFIG_NET_TCP */ diff --git a/nuttx/net/bind.c b/nuttx/net/bind.c new file mode 100644 index 0000000000..da912e0172 --- /dev/null +++ b/nuttx/net/bind.c @@ -0,0 +1,197 @@ +/**************************************************************************** + * net/bind.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: psock_bind + * + * Description: + * bind() gives the socket 'psock' the local address 'addr'. 'addr' is + * 'addrlen' bytes long. Traditionally, this is called "assigning a name to + * a socket." When a socket is created with socket, it exists in a name + * space (address family) but has no name assigned. + * + * Parameters: + * psock Socket structure of the socket to bind + * addr Socket local address + * addrlen Length of 'addr' + * + * Returned Value: + * 0 on success; -1 on error with errno set appropriately + * + * EACCES + * The address is protected, and the user is not the superuser. + * EADDRINUSE + * The given address is already in use. + * EINVAL + * The socket is already bound to an address. + * ENOTSOCK + * psock is a descriptor for a file, not a socket. + * + * Assumptions: + * + ****************************************************************************/ + +int psock_bind(FAR struct socket *psock, const struct sockaddr *addr, + socklen_t addrlen) +{ +#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) +#ifdef CONFIG_NET_IPv6 + FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr; +#else + FAR const struct sockaddr_in *inaddr = (const struct sockaddr_in *)addr; +#endif +#endif + + int err; + int ret; + + /* Verify that the psock corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + err = ENOTSOCK; + goto errout; + } + + /* Verify that a valid address has been provided */ + +#ifdef CONFIG_NET_IPv6 + if (addr->sa_family != AF_INET6 || addrlen < sizeof(struct sockaddr_in6)) +#else + if (addr->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in)) +#endif + { + err = EBADF; + goto errout; + } + + /* Perform the binding depending on the protocol type */ + + switch (psock->s_type) + { +#ifdef CONFIG_NET_TCP + case SOCK_STREAM: + ret = uip_tcpbind(psock->s_conn, inaddr); + psock->s_flags |= _SF_BOUND; + break; +#endif + +#ifdef CONFIG_NET_UDP + case SOCK_DGRAM: + ret = uip_udpbind(psock->s_conn, inaddr); + break; +#endif + + default: + err = EBADF; + goto errout; + } + + /* Was the bind successful */ + + if (ret < 0) + { + err = -ret; + goto errout; + } + + return OK; + +errout: + *get_errno_ptr() = err; + return ERROR; +} + +/**************************************************************************** + * Function: bind + * + * Description: + * bind() gives the socket 'sockfd' the local address 'addr'. 'addr' is + * 'addrlen' bytes long. Traditionally, this is called "assigning a name to + * a socket." When a socket is created with socket, it exists in a name + * space (address family) but has no name assigned. + * + * Parameters: + * sockfd Socket descriptor of the socket to bind + * addr Socket local address + * addrlen Length of 'addr' + * + * Returned Value: + * 0 on success; -1 on error with errno set appropriately + * + * EACCES + * The address is protected, and the user is not the superuser. + * EADDRINUSE + * The given address is already in use. + * EBADF + * sockfd is not a valid descriptor. + * EINVAL + * The socket is already bound to an address. + * ENOTSOCK + * sockfd is a descriptor for a file, not a socket. + * + * Assumptions: + * + ****************************************************************************/ + +int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) +{ + /* Make the socket descriptor to the underlying socket structure */ + + FAR struct socket *psock = sockfd_socket(sockfd); + + /* Then let psock_bind do all of the work */ + + return psock_bind(psock, addr, addrlen); +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/connect.c b/nuttx/net/connect.c new file mode 100644 index 0000000000..fdbb34f55f --- /dev/null +++ b/nuttx/net/connect.c @@ -0,0 +1,591 @@ +/**************************************************************************** + * net/connect.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include + +#include +#include +#include + +#include +#include + +#include "net_internal.h" +#include "uip/uip_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +struct tcp_connect_s +{ + FAR struct uip_conn *tc_conn; /* Reference to TCP connection structure */ + FAR struct uip_callback_s *tc_cb; /* Reference to callback instance */ + sem_t tc_sem; /* Semaphore signals recv completion */ + int tc_result; /* OK on success, otherwise a negated errno. */ +}; +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +static inline int tcp_setup_callbacks(FAR struct socket *psock, + FAR struct tcp_connect_s *pstate); +static inline void tcp_teardown_callbacks(struct tcp_connect_s *pstate, int status); +static uint16_t tcp_connect_interrupt(struct uip_driver_s *dev, void *pvconn, + void *pvpriv, uint16_t flags); +#ifdef CONFIG_NET_IPv6 +static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in6 *inaddr); +#else +static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in *inaddr); +#endif +#endif /* CONFIG_NET_TCP */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: tcp_setup_callbacks + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +static inline int tcp_setup_callbacks(FAR struct socket *psock, + FAR struct tcp_connect_s *pstate) +{ + FAR struct uip_conn *conn = psock->s_conn; + int ret = -EBUSY; + + /* Initialize the TCP state structure */ + + (void)sem_init(&pstate->tc_sem, 0, 0); /* Doesn't really fail */ + pstate->tc_conn = conn; + pstate->tc_result = -EAGAIN; + + /* Set up the callbacks in the connection */ + + pstate->tc_cb = uip_tcpcallbackalloc(conn); + if (pstate->tc_cb) + { + /* Set up the connection "interrupt" handler */ + + pstate->tc_cb->flags = UIP_NEWDATA|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT|UIP_CONNECTED; + pstate->tc_cb->priv = (void*)pstate; + pstate->tc_cb->event = tcp_connect_interrupt; + + /* Set up the connection event monitor */ + + net_startmonitor(psock); + ret = OK; + } + return ret; +} +#endif /* CONFIG_NET_TCP */ + +/**************************************************************************** + * Name: tcp_teardown_callbacks + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +static inline void tcp_teardown_callbacks(struct tcp_connect_s *pstate, + int status) +{ + FAR struct uip_conn *conn = pstate->tc_conn; + + /* Make sure that no further interrupts are processed */ + + uip_tcpcallbackfree(conn, pstate->tc_cb); + + /* If we successfully connected, we will continue to monitor the connection + * state via callbacks. + */ + + if (status < 0) + { + /* Failed to connect. Stop the connection event monitor */ + + net_stopmonitor(conn); + } +} +#endif /* CONFIG_NET_TCP */ + +/**************************************************************************** + * Name: tcp_connect_interrupt + * + * Description: + * This function is called from the interrupt level to perform the actual + * connection operation via by the uIP layer. + * + * Parameters: + * dev The sructure of the network driver that caused the interrupt + * pvconn The connection structure associated with the socket + * flags Set of events describing why the callback was invoked + * + * Returned Value: + * The new flags setting + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +static uint16_t tcp_connect_interrupt(struct uip_driver_s *dev, void *pvconn, + void *pvpriv, uint16_t flags) +{ + struct tcp_connect_s *pstate = (struct tcp_connect_s *)pvpriv; + + nllvdbg("flags: %04x\n", flags); + + /* 'priv' might be null in some race conditions (?) */ + + if (pstate) + { + /* The following errors should be detected here (someday) + * + * ECONNREFUSED + * No one listening on the remote address. + * ENETUNREACH + * Network is unreachable. + * ETIMEDOUT + * Timeout while attempting connection. The server may be too busy + * to accept new connections. + */ + + /* UIP_CLOSE: The remote host has closed the connection + * UIP_ABORT: The remote host has aborted the connection + */ + + if ((flags & (UIP_CLOSE|UIP_ABORT)) != 0) + { + /* Indicate that remote host refused the connection */ + + pstate->tc_result = -ECONNREFUSED; + } + + /* UIP_TIMEDOUT: Connection aborted due to too many retransmissions. */ + + else if ((flags & UIP_TIMEDOUT) != 0) + { + /* Indicate that the remote host is unreachable (or should this be timedout?) */ + + pstate->tc_result = -ETIMEDOUT; + } + + /* UIP_CONNECTED: The socket is successfully connected */ + + else if ((flags & UIP_CONNECTED) != 0) + { + /* Indicate that the socket is no longer connected */ + + pstate->tc_result = OK; + } + + /* Otherwise, it is not an event of importance to us at the moment */ + + else + { + /* Drop data received in this state */ + + dev->d_len = 0; + return flags & ~UIP_NEWDATA; + } + + nllvdbg("Resuming: %d\n", pstate->tc_result); + + /* Stop further callbacks */ + + tcp_teardown_callbacks(pstate, pstate->tc_result); + + /* Wake up the waiting thread */ + + sem_post(&pstate->tc_sem); + } + + return flags; +} +#endif /* CONFIG_NET_TCP */ + +/**************************************************************************** + * Name: tcp_connect + * + * Description: + * Perform a TCP connection + * + * Parameters: + * psock A reference to the socket structure of the socket to be connected + * inaddr The address of the remote server to connect to + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +#ifdef CONFIG_NET_IPv6 +static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in6 *inaddr) +#else +static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in *inaddr) +#endif +{ + struct tcp_connect_s state; + uip_lock_t flags; + int ret = OK; + + /* Interrupts must be disabled through all of the following because + * we cannot allow the network callback to occur until we are completely + * setup. + */ + + flags = uip_lock(); + + /* Get the connection reference from the socket */ + + if (!psock->s_conn) /* Should always be non-NULL */ + { + ret = -EINVAL; + } + else + { + /* Perform the uIP connection operation */ + + ret = uip_tcpconnect(psock->s_conn, inaddr); + } + + if (ret >= 0) + { + /* Set up the callbacks in the connection */ + + ret = tcp_setup_callbacks(psock, &state); + if (ret >= 0) + { + /* Wait for either the connect to complete or for an error/timeout + * to occur. NOTES: (1) uip_lockedwait will also terminate if a signal + * is received, (2) interrupts may be disabled! They will be re- + * enabled while the task sleeps and automatically re-disabled + * when the task restarts. + */ + + ret = uip_lockedwait(&state.tc_sem); + + /* Uninitialize the state structure */ + + (void)sem_destroy(&state.tc_sem); + + /* If uip_lockedwait failed, recover the negated error (probably -EINTR) */ + + if (ret < 0) + { + ret = -errno; + } + else + { + /* If the wait succeeded, then get the new error value from + * the state structure + */ + + ret = state.tc_result; + } + + /* Make sure that no further interrupts are processed */ + + tcp_teardown_callbacks(&state, ret); + } + + /* Mark the connection bound and connected */ + + if (ret >= 0) + { + psock->s_flags |= (_SF_BOUND|_SF_CONNECTED); + } + } + + uip_unlock(flags); + return ret; +} +#endif /* CONFIG_NET_TCP */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: psock_connect + * + * Description: + * connect() connects the socket referred to by the structure 'psock' + * to the address specified by 'addr'. The addrlen argument specifies + * the size of 'addr'. The format of the address in 'addr' is + * determined by the address space of the socket 'psock'. + * + * If the socket 'psock' is of type SOCK_DGRAM then 'addr' is the address + * to which datagrams are sent by default, and the only address from which + * datagrams are received. If the socket is of type SOCK_STREAM or + * SOCK_SEQPACKET, this call attempts to make a connection to the socket + * that is bound to the address specified by 'addr'. + * + * Generally, connection-based protocol sockets may successfully connect() + * only once; connectionless protocol sockets may use connect() multiple + * times to change their association. Connectionless sockets may dissolve + * the association by connecting to an address with the sa_family member of + * sockaddr set to AF_UNSPEC. + * + * Parameters: + * psock Pointer to a socket structure initialized by psock_socket() + * addr Server address (form depends on type of socket) + * addrlen Length of actual 'addr' + * + * Returned Value: + * 0 on success; -1 on error with errno set appropriately + * + * EACCES, EPERM + * The user tried to connect to a broadcast address without having the + * socket broadcast flag enabled or the connection request failed + * because of a local firewall rule. + * EADDRINUSE + * Local address is already in use. + * EAFNOSUPPORT + * The passed address didn't have the correct address family in its + * sa_family field. + * EAGAIN + * No more free local ports or insufficient entries in the routing + * cache. + * EALREADY + * The socket is non-blocking and a previous connection attempt has + * not yet been completed. + * EBADF + * The file descriptor is not a valid index in the descriptor table. + * ECONNREFUSED + * No one listening on the remote address. + * EFAULT + * The socket structure address is outside the user's address space. + * EINPROGRESS + * The socket is non-blocking and the connection cannot be completed + * immediately. + * EINTR + * The system call was interrupted by a signal that was caught. + * EISCONN + * The socket is already connected. + * ENETUNREACH + * Network is unreachable. + * ENOTSOCK + * The file descriptor is not associated with a socket. + * ETIMEDOUT + * Timeout while attempting connection. The server may be too busy + * to accept new connections. + * + * Assumptions: + * + ****************************************************************************/ + +int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr, + socklen_t addrlen) +{ +#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) +#ifdef CONFIG_NET_IPv6 + FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr; +#else + FAR const struct sockaddr_in *inaddr = (const struct sockaddr_in *)addr; +#endif + int ret; +#endif + + int err; + + /* Verify that the psock corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + err = EBADF; + goto errout; + } + + /* Verify that a valid address has been provided */ + +#ifdef CONFIG_NET_IPv6 + if (addr->sa_family != AF_INET6 || addrlen < sizeof(struct sockaddr_in6)) +#else + if (addr->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in)) +#endif + { + err = EBADF; + goto errout; + } + + /* Perform the connection depending on the protocol type */ + + switch (psock->s_type) + { +#ifdef CONFIG_NET_TCP + case SOCK_STREAM: + { + /* Verify that the socket is not already connected */ + + if (_SS_ISCONNECTED(psock->s_flags)) + { + err = EISCONN; + goto errout; + } + + /* Its not ... connect it */ + + ret = tcp_connect(psock, inaddr); + if (ret < 0) + { + err = -ret; + goto errout; + } + } + break; +#endif + +#ifdef CONFIG_NET_UDP + case SOCK_DGRAM: + { + ret = uip_udpconnect(psock->s_conn, inaddr); + if (ret < 0) + { + err = -ret; + goto errout; + } + } + break; +#endif + + default: + err = EBADF; + goto errout; + } + + return OK; + +errout: + errno = err; + return ERROR; +} + +/**************************************************************************** + * Name: connect + * + * Description: + * connect() connects the socket referred to by the file descriptor 'sockfd' + * to the address specified by 'addr'. The addrlen argument specifies + * the size of 'addr'. The format of the address in 'addr' is + * determined by the address space of the socket 'sockfd'. + * + * If the socket 'sockfd' is of type SOCK_DGRAM then 'addr' is the address + * to which datagrams are sent by default, and the only address from which + * datagrams are received. If the socket is of type SOCK_STREAM or + * SOCK_SEQPACKET, this call attempts to make a connection to the socket + * that is bound to the address specified by 'addr'. + * + * Generally, connection-based protocol sockets may successfully connect() + * only once; connectionless protocol sockets may use connect() multiple + * times to change their association. Connectionless sockets may dissolve + * the association by connecting to an address with the sa_family member of + * sockaddr set to AF_UNSPEC. + * + * Parameters: + * sockfd Socket descriptor returned by socket() + * addr Server address (form depends on type of socket) + * addrlen Length of actual 'addr' + * + * Returned Value: + * 0 on success; -1 on error with errno set appropriately + * + * EACCES, EPERM + * The user tried to connect to a broadcast address without having the + * socket broadcast flag enabled or the connection request failed + * because of a local firewall rule. + * EADDRINUSE + * Local address is already in use. + * EAFNOSUPPORT + * The passed address didn't have the correct address family in its + * sa_family field. + * EAGAIN + * No more free local ports or insufficient entries in the routing + * cache. + * EALREADY + * The socket is non-blocking and a previous connection attempt has + * not yet been completed. + * EBADF + * The file descriptor is not a valid index in the descriptor table. + * ECONNREFUSED + * No one listening on the remote address. + * EFAULT + * The socket structure address is outside the user's address space. + * EINPROGRESS + * The socket is non-blocking and the connection cannot be completed + * immediately. + * EINTR + * The system call was interrupted by a signal that was caught. + * EISCONN + * The socket is already connected. + * ENETUNREACH + * Network is unreachable. + * ENOTSOCK + * The file descriptor is not associated with a socket. + * ETIMEDOUT + * Timeout while attempting connection. The server may be too busy + * to accept new connections. + * + * Assumptions: + * + ****************************************************************************/ + +int connect(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen) +{ + /* Get the underlying socket structure */ + + FAR struct socket *psock = sockfd_socket(sockfd); + + /* Then let psock_connect() do all of the work */ + + return psock_connect(psock, addr, addrlen); +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/getsockname.c b/nuttx/net/getsockname.c new file mode 100644 index 0000000000..c5cae2f3b3 --- /dev/null +++ b/nuttx/net/getsockname.c @@ -0,0 +1,218 @@ +/**************************************************************************** + * net/getsockname.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include +#include + +#include "net_internal.h" + +#ifdef CONFIG_NET + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: getsockname + * + * Description: + * The getsockname() function retrieves the locally-bound name of the + * specified socket, stores this address in the sockaddr structure pointed + * to by the 'addr' argument, and stores the length of this address in the + * object pointed to by the 'addrlen' argument. + * + * If the actual length of the address is greater than the length of the + * supplied sockaddr structure, the stored address will be truncated. + * + * If the socket has not been bound to a local name, the value stored in + * the object pointed to by address is unspecified. + * + * Parameters: + * sockfd Socket descriptor of socket [in] + * addr sockaddr structure to receive data [out] + * addrlen Length of sockaddr structure [in/out] + * + * Returned Value: + * On success, 0 is returned, the 'addr' argument points to the address + * of the socket, and the 'addrlen' argument points to the length of the + * address. Otherwise, -1 is returned and errno is set to indicate the error. + * Possible errno values that may be returned include: + * + * EBADF - The socket argument is not a valid file descriptor. + * EOPNOTSUPP - The operation is not supported for this socket's protocol. + * EINVAL - The socket has been shut down. + * + * Assumptions: + * + ****************************************************************************/ + +int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) +{ + FAR struct socket *psock = sockfd_socket(sockfd); + FAR struct uip_driver_s *dev; + +#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) +#ifdef CONFIG_NET_IPv6 + FAR struct sockaddr_in6 *outaddr = (FAR struct sockaddr_in6 *)addr; +#else + FAR struct sockaddr_in *outaddr = (FAR struct sockaddr_in *)addr; +#endif +#endif + + int err; + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + err = EBADF; + goto errout; + } + + /* Some sanity checking... Shouldn't need this on a buckled up embedded + * system (?) + */ + +#ifdef CONFIG_DEBUG + if (!addr || !addrlen) + { + err = EINVAL; + goto errout; + } +#endif + + /* Check if enough space has been provided for the full address */ + +#ifdef CONFIG_NET_IPv6 + if (*addrlen < sizeof(struct sockaddr_in6)) +#else + if (*addrlen < sizeof(struct sockaddr_in)) +#endif + { + /* This function is supposed to return the partial address if + * a smaller buffer has been provided. This support has not + * been implemented. + */ + + err = ENOSYS; + goto errout; + } + + /* Set the port number */ + + switch (psock->s_type) + { +#ifdef CONFIG_NET_TCP + case SOCK_STREAM: + { + struct uip_conn *tcp_conn = (struct uip_conn *)psock->s_conn; + outaddr->sin_port = tcp_conn->lport; /* Already in network byte order */ + } + break; +#endif + +#ifdef CONFIG_NET_UDP + case SOCK_DGRAM: + { + struct uip_udp_conn *udp_conn = (struct uip_udp_conn *)psock->s_conn; + outaddr->sin_port = udp_conn->lport; /* Already in network byte order */ + } + break; +#endif + + default: + err = EOPNOTSUPP; + goto errout; + } + + /* ISSUE: As of this writing, the socket/connection does not know its IP + * address. This is because the uIP design is only intended to support + * a single network device and, therefore, only the network device knows + * the IP address. + * + * Right now, we can just pick the first network device. But that may + * not work in the future. + */ + + netdev_semtake(); + dev = g_netdevices; + if (!dev) + { + netdev_semgive(); + err = EINVAL; + goto errout; + } + + /* Set the address family and the IP address */ + +#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) +#ifdef CONFIG_NET_IPv6 + outaddr->sin_family = AF_INET6; + memcpy(outaddr->sin6_addr.in6_u.u6_addr8, dev->d_ipaddr, 16); + *addrlen = sizeof(struct sockaddr_in6); +#else + outaddr->sin_family = AF_INET; + outaddr->sin_addr.s_addr = dev->d_ipaddr; + *addrlen = sizeof(struct sockaddr_in); +#endif +#endif + netdev_semgive(); + + /* Return success */ + + return OK; + +errout: + set_errno(err); + return ERROR; +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/getsockopt.c b/nuttx/net/getsockopt.c new file mode 100644 index 0000000000..c3afb29c9c --- /dev/null +++ b/nuttx/net/getsockopt.c @@ -0,0 +1,289 @@ +/**************************************************************************** + * net/getsockopt.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_SOCKOPTS) + +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: psock_getsockopt + * + * Description: + * getsockopt() retrieve thse value for the option specified by the + * 'option' argument for the socket specified by the 'psock' argument. If + * the size of the option value is greater than 'value_len', the value + * stored in the object pointed to by the 'value' argument will be silently + * truncated. Otherwise, the length pointed to by the 'value_len' argument + * will be modified to indicate the actual length of the'value'. + * + * The 'level' argument specifies the protocol level of the option. To + * retrieve options at the socket level, specify the level argument as + * SOL_SOCKET. + * + * See a complete list of values for the 'option' argument. + * + * Parameters: + * psock Socket structure of the socket to query + * level Protocol level to set the option + * option identifies the option to get + * value Points to the argument value + * value_len The length of the argument value + * + * Returned Value: + * + * EINVAL + * The specified option is invalid at the specified socket 'level' or the + * socket has been shutdown. + * ENOPROTOOPT + * The 'option' is not supported by the protocol. + * ENOTSOCK + * The 'psock' argument does not refer to a socket. + * ENOBUFS + * Insufficient resources are available in the system to complete the + * call. + * + * Assumptions: + * + ****************************************************************************/ + +int psock_getsockopt(FAR struct socket *psock, int level, int option, + FAR void *value, FAR socklen_t *value_len) +{ + int err; + + /* Verify that the socket option if valid (but might not be supported ) */ + + if (!_SO_GETVALID(option) || !value || !value_len) + { + err = EINVAL; + goto errout; + } + + /* Process the option */ + + switch (option) + { + /* The following options take a point to an integer boolean value. + * We will blindly report the bit here although the implementation + * is outside of the scope of getsockopt. + */ + + case SO_DEBUG: /* Enables recording of debugging information */ + case SO_BROADCAST: /* Permits sending of broadcast messages */ + case SO_REUSEADDR: /* Allow reuse of local addresses */ + case SO_KEEPALIVE: /* Keeps connections active by enabling the + * periodic transmission */ + case SO_OOBINLINE: /* Leaves received out-of-band data inline */ + case SO_DONTROUTE: /* Requests outgoing messages bypass standard routing */ + { + sockopt_t optionset; + + /* Verify that option is the size of an 'int'. Should also check + * that 'value' is properly aligned for an 'int' + */ + + if (*value_len < sizeof(int)) + { + err = EINVAL; + goto errout; + } + + /* Sample the current options. This is atomic operation and so + * should not require any special steps for thread safety. We + * this outside of the macro because you can never be sure what + * a macro will do. + */ + + optionset = psock->s_options; + *(int*)value = _SO_GETOPT(optionset, option); + *value_len = sizeof(int); + } + break; + + case SO_TYPE: /* Reports the socket type */ + { + /* Verify that option is the size of an 'int'. Should also check + * that 'value' is properly aligned for an 'int' + */ + + if (*value_len < sizeof(int)) + { + err = EINVAL; + goto errout; + } + + /* Return the socket type */ + + *(int*)value = psock->s_type; + *value_len = sizeof(int); + } + break; + + /* The following are valid only if the OS CLOCK feature is enabled */ + + case SO_RCVTIMEO: + case SO_SNDTIMEO: +#ifndef CONFIG_DISABLE_CLOCK + { + socktimeo_t timeo; + + /* Verify that option is the size of an 'int'. Should also check + * that 'value' is properly aligned for an 'int' + */ + + if (*value_len < sizeof(struct timeval)) + { + err = EINVAL; + goto errout; + } + + /* Get the timeout value. This is a atomic operation and should + * require no special operation. + */ + + if (option == SO_RCVTIMEO) + { + timeo = psock->s_rcvtimeo; + } + else + { + timeo = psock->s_sndtimeo; + } + + /* Then return the timeout value to the caller */ + + net_dsec2timeval(timeo, (struct timeval *)value); + *value_len = sizeof(struct timeval); + } + break; +#endif + + /* The following are not yet implemented */ + + case SO_ACCEPTCONN: /* Reports whether socket listening is enabled */ + case SO_LINGER: + case SO_SNDBUF: /* Sets send buffer size */ + case SO_RCVBUF: /* Sets receive buffer size */ + case SO_ERROR: /* Reports and clears error status. */ + case SO_RCVLOWAT: /* Sets the minimum number of bytes to input */ + case SO_SNDLOWAT: /* Sets the minimum number of bytes to output */ + + default: + err = ENOPROTOOPT; + goto errout; + } + return OK; + +errout: + set_errno(err); + return ERROR; +} + +/**************************************************************************** + * Function: getsockopt + * + * Description: + * getsockopt() retrieve thse value for the option specified by the + * 'option' argument for the socket specified by the 'sockfd' argument. If + * the size of the option value is greater than 'value_len', the value + * stored in the object pointed to by the 'value' argument will be silently + * truncated. Otherwise, the length pointed to by the 'value_len' argument + * will be modified to indicate the actual length of the'value'. + * + * The 'level' argument specifies the protocol level of the option. To + * retrieve options at the socket level, specify the level argument as + * SOL_SOCKET. + * + * See a complete list of values for the 'option' argument. + * + * Parameters: + * sockfd Socket descriptor of socket + * level Protocol level to set the option + * option identifies the option to get + * value Points to the argument value + * value_len The length of the argument value + * + * Returned Value: + * + * EBADF + * The 'sockfd' argument is not a valid socket descriptor. + * EINVAL + * The specified option is invalid at the specified socket 'level' or the + * socket has been shutdown. + * ENOPROTOOPT + * The 'option' is not supported by the protocol. + * ENOTSOCK + * The 'sockfd' argument does not refer to a socket. + * ENOBUFS + * Insufficient resources are available in the system to complete the + * call. + * + * Assumptions: + * + ****************************************************************************/ + +int getsockopt(int sockfd, int level, int option, void *value, socklen_t *value_len) +{ + FAR struct socket *psock; + + /* Get the underlying socket structure */ + /* Verify that the sockfd corresponds to valid, allocated socket */ + + psock = sockfd_socket(sockfd); + if (!psock || psock->s_crefs <= 0) + { + set_errno(EBADF); + return ERROR; + } + + /* Then let psock_getsockopt() do all of the work */ + + return psock_getsockopt(psock, level, option, value, value_len); +} + +#endif /* CONFIG_NET && CONFIG_NET_SOCKOPTS */ diff --git a/nuttx/net/listen.c b/nuttx/net/listen.c new file mode 100644 index 0000000000..bddb0ab080 --- /dev/null +++ b/nuttx/net/listen.c @@ -0,0 +1,149 @@ +/**************************************************************************** + * net/listen.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: listen + * + * Description: + * To accept connections, a socket is first created with socket(), a + * willingness to accept incoming connections and a queue limit for incoming + * connections are specified with listen(), and then the connections are + * accepted with accept(). The listen() call applies only to sockets of + * type SOCK_STREAM or SOCK_SEQPACKET. + * + * Parameters: + * sockfd Socket descriptor of the bound socket + * backlog The maximum length the queue of pending connections may grow. + * If a connection request arrives with the queue full, the client + * may receive an error with an indication of ECONNREFUSED or, + * if the underlying protocol supports retransmission, the request + * may be ignored so that retries succeed. + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned, and errno is set + * appropriately. + * + * EADDRINUSE + * Another socket is already listening on the same port. + * EBADF + * The argument 'sockfd' is not a valid descriptor. + * ENOTSOCK + * The argument 'sockfd' is not a socket. + * EOPNOTSUPP + * The socket is not of a type that supports the listen operation. + * + * Assumptions: + * + ****************************************************************************/ + +int listen(int sockfd, int backlog) +{ + FAR struct socket *psock = sockfd_socket(sockfd); + struct uip_conn *conn; + int err; + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + /* It is not a valid socket description. Distinguish between the cases + * where sockfd is a just invalid and when it is a valid file descriptor used + * in the wrong context. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + if ((unsigned int)sockfd < CONFIG_NFILE_DESCRIPTORS) + { + err = ENOTSOCK; + } + else +#endif + { + err = EBADF; + } + goto errout; + } + + /* Verify that the sockfd corresponds to a connected SOCK_STREAM */ + + conn = (struct uip_conn *)psock->s_conn; + if (psock->s_type != SOCK_STREAM || !psock->s_conn || conn->lport <= 0) + { + err = EOPNOTSUPP; + goto errout; + } + + /* Set up the backlog for this connection */ + +#ifdef CONFIG_NET_TCPBACKLOG + err = uip_backlogcreate(conn, backlog); + if (err < 0) + { + err = -err; + goto errout; + } +#endif + + /* Start listening to the bound port. This enables callbacks when accept() + * is called and enables poll()/select() logic. + */ + + uip_listen(conn); + psock->s_flags |= _SF_LISTENING; + return OK; + +errout: + errno = err; + return ERROR; +} + +#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/net/net_arptimer.c b/nuttx/net/net_arptimer.c new file mode 100644 index 0000000000..89db9f6562 --- /dev/null +++ b/nuttx/net/net_arptimer.c @@ -0,0 +1,134 @@ +/**************************************************************************** + * net/net_arptimer.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include +#include + +#include +#include + +#include "net_internal.h" + +#ifdef CONFIG_NET_ARP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* ARP timer interval = 10 seconds. CLK_TCK is the number of clock ticks + * per second + */ + +#define ARPTIMER_WDINTERVAL (10*CLK_TCK) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static WDOG_ID g_arptimer; /* ARP timer */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: arptimer_poll + * + * Description: + * Periodic timer handler. Called from the timer interrupt handler. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void arptimer_poll(int argc, uint32_t arg, ...) +{ + /* Call the ARP timer function every 10 seconds. */ + + uip_arp_timer(); + + /* Setup the watchdog timer again */ + + (void)wd_start(g_arptimer, ARPTIMER_WDINTERVAL, arptimer_poll, 0); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: arptimer_init + * + * Description: + * Initialized the 10 second timer that is need by uIP to age ARP + * associations + * + * Parameters: + * None + * + * Returned Value: + * None + * + * Assumptions: + * Called once at system initialization time + * + ****************************************************************************/ + +void arptimer_init(void) +{ + /* Create and start the ARP timer */ + + g_arptimer = wd_create(); + (void)wd_start(g_arptimer, ARPTIMER_WDINTERVAL, arptimer_poll, 0); +} + +#endif /* CONFIG_NET_ARP */ +#endif /* CONFIG_NET */ diff --git a/nuttx/net/net_checksd.c b/nuttx/net/net_checksd.c new file mode 100644 index 0000000000..3da3cea62f --- /dev/null +++ b/nuttx/net/net_checksd.c @@ -0,0 +1,88 @@ +/**************************************************************************** + * net/net_checksd.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_checksd + * + * Description: + * Check if the socket descriptor is valid for the provided TCB and if it + * supports the requested access. This trivial operation is part of the + * fdopen() operation when the fdopen() is performed on a socket descriptor. + * It simply performs some sanity checking before permitting the socket + * descriptor to be wrapped as a C FILE stream. + * + ****************************************************************************/ + +#if defined(CONFIG_NET) && CONFIG_NFILE_DESCRIPTORS > 0 +int net_checksd(int sd, int oflags) +{ + FAR struct socket *psock = sockfd_socket(sd); + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + nvdbg("No valid socket for sd: %d\n", sd); + return -EBADF; + } + + /* NOTE: We permit the socket FD to be "wrapped" in a stream as + * soon as the socket descriptor is created by socket(). Therefore + * (1) we don't care if the socket is connected yet, and (2) there + * are no access restrictions that can be enforced yet. + */ + + return OK; +} +#endif /* CONIG_NET && CONFIG_NFILE_DESCRIPTORS > 0 */ + diff --git a/nuttx/net/net_clone.c b/nuttx/net/net_clone.c new file mode 100644 index 0000000000..ada223484d --- /dev/null +++ b/nuttx/net/net_clone.c @@ -0,0 +1,119 @@ +/**************************************************************************** + * net/net_clone.c + * + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include + +#include + +#include "net_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: net_clone + * + * Description: + * Performs the low level, common portion of net_dup() and net_dup2() + * + ****************************************************************************/ + +int net_clone(FAR struct socket *psock1, FAR struct socket *psock2) +{ + uip_lock_t flags; + int ret = OK; + + /* Parts of this operation need to be atomic */ + + flags = uip_lock(); + + /* Duplicate the socket state */ + + psock2->s_type = psock1->s_type; /* Protocol type: Only SOCK_STREAM or SOCK_DGRAM */ + psock2->s_flags = psock1->s_flags; /* See _SF_* definitions */ +#ifdef CONFIG_NET_SOCKOPTS + psock2->s_options = psock1->s_options; /* Selected socket options */ +#endif +#ifndef CONFIG_DISABLE_CLOCK + psock2->s_rcvtimeo = psock1->s_rcvtimeo; /* Receive timeout value (in deciseconds) */ + psock2->s_sndtimeo = psock1->s_sndtimeo; /* Send timeout value (in deciseconds) */ +#endif + psock2->s_conn = psock1->s_conn; /* UDP or TCP connection structure */ + + /* Increment the reference count on the connection */ + + DEBUGASSERT(psock2->s_conn); + psock2->s_crefs = 1; /* One reference on the new socket itself */ + +#ifdef CONFIG_NET_TCP + if (psock2->s_type == SOCK_STREAM) + { + struct uip_conn *conn = psock2->s_conn; + DEBUGASSERT(conn->crefs > 0 && conn->crefs < 255); + conn->crefs++; + } + else +#endif +#ifdef CONFIG_NET_UDP + if (psock2->s_type == SOCK_DGRAM) + { + struct uip_udp_conn *conn = psock2->s_conn; + DEBUGASSERT(conn->crefs > 0 && conn->crefs < 255); + conn->crefs++; + } + else +#endif + { + ndbg("Unsupported type: %d\n", psock2->s_type); + ret = -EBADF; + } + + uip_unlock(flags); + return ret; +} + +#endif /* CONFIG_NET */ + + diff --git a/nuttx/net/net_close.c b/nuttx/net/net_close.c new file mode 100644 index 0000000000..dce87ba475 --- /dev/null +++ b/nuttx/net/net_close.c @@ -0,0 +1,330 @@ +/**************************************************************************** + * net/net_close.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include +#include +#include + +#include +#include + +#include "net_internal.h" +#include "uip/uip_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +struct tcp_close_s +{ + FAR struct socket *cl_psock; /* Reference to the TCP socket */ + FAR struct uip_callback_s *cl_cb; /* Reference to TCP callback instance */ + sem_t cl_sem; /* Semaphore signals disconnect completion */ +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: netclose_interrupt + * + * Description: + * Handle uIP callback events. + * + * Parameters: + * conn - uIP TCP connection structure + * + * Returned Value: + * None + * + * Assumptions: + * Called from normal user-level logic + * + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +static uint16_t netclose_interrupt(struct uip_driver_s *dev, void *pvconn, + void *pvpriv, uint16_t flags) +{ + struct tcp_close_s *pstate = (struct tcp_close_s *)pvpriv; + + nllvdbg("flags: %04x\n", flags); + + if (pstate) + { + /* UIP_CLOSE: The remote host has closed the connection + * UIP_ABORT: The remote host has aborted the connection + */ + + if ((flags & (UIP_CLOSE|UIP_ABORT)) != 0) + { + /* The disconnection is complete */ + + pstate->cl_cb->flags = 0; + pstate->cl_cb->priv = NULL; + pstate->cl_cb->event = NULL; + sem_post(&pstate->cl_sem); + nllvdbg("Resuming\n"); + } + else + { + /* Drop data received in this state and make sure that UIP_CLOSE + * is set in the response + */ + + dev->d_len = 0; + return (flags & ~UIP_NEWDATA) | UIP_CLOSE; + } + } + + return flags; +} +#endif /* CONFIG_NET_TCP */ + +/**************************************************************************** + * Function: netclose_disconnect + * + * Description: + * Break any current TCP connection + * + * Parameters: + * conn - uIP TCP connection structure + * + * Returned Value: + * None + * + * Assumptions: + * Called from normal user-level logic + * + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +static inline void netclose_disconnect(FAR struct socket *psock) +{ + struct tcp_close_s state; + uip_lock_t flags; + + /* Interrupts are disabled here to avoid race conditions */ + + flags = uip_lock(); + + /* Is the TCP socket in a connected state? */ + + if (_SS_ISCONNECTED(psock->s_flags)) + { + struct uip_conn *conn = (struct uip_conn*)psock->s_conn; + + /* Check for the case where the host beat us and disconnected first */ + + if (conn->tcpstateflags == UIP_ESTABLISHED) + { + /* Set up to receive TCP data event callbacks */ + + state.cl_cb = uip_tcpcallbackalloc(conn); + if (state.cl_cb) + { + state.cl_psock = psock; + sem_init(&state.cl_sem, 0, 0); + + state.cl_cb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT; + state.cl_cb->priv = (void*)&state; + state.cl_cb->event = netclose_interrupt; + + /* Notify the device driver of the availaibilty of TX data */ + + netdev_txnotify(&conn->ripaddr); + + /* Wait for the disconnect event */ + + (void)uip_lockedwait(&state.cl_sem); + + /* We are now disconnected */ + + sem_destroy(&state.cl_sem); + uip_tcpcallbackfree(conn, state.cl_cb); + } + } + } + + uip_unlock(flags); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: psock_close + * + * Description: + * Performs the close operation on a socket instance + * + * Parameters: + * psock Socket instance + * + * Returned Value: + * 0 on success; -1 on error with errno set appropriately. + * + * Assumptions: + * + ****************************************************************************/ + +int psock_close(FAR struct socket *psock) +{ + int err; + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + err = EBADF; + goto errout; + } + + /* We perform the uIP close operation only if this is the last count on the socket. + * (actually, I think the socket crefs only takes the values 0 and 1 right now). + */ + + if (psock->s_crefs <= 1) + { + /* Perform uIP side of the close depending on the protocol type */ + + switch (psock->s_type) + { +#ifdef CONFIG_NET_TCP + case SOCK_STREAM: + { + struct uip_conn *conn = psock->s_conn; + + /* Is this the last reference to the connection structure (there + * could be more if the socket was dup'ed. + */ + + if (conn->crefs <= 1) + { + /* Yes... free the connection structure */ + + uip_unlisten(conn); /* No longer accepting connections */ + netclose_disconnect(psock); /* Break any current connections */ + conn->crefs = 0; /* No more references on the connection */ + uip_tcpfree(conn); /* Free uIP resources */ + } + else + { + /* No.. Just decrement the reference count */ + + conn->crefs--; + } + } + break; +#endif + +#ifdef CONFIG_NET_UDP + case SOCK_DGRAM: + { + struct uip_udp_conn *conn = psock->s_conn; + + /* Is this the last reference to the connection structure (there + * could be more if the socket was dup'ed. + */ + + if (conn->crefs <= 1) + { + /* Yes... free the connection structure */ + + conn->crefs = 0; /* No more references on the connection */ + uip_udpfree(psock->s_conn); /* Free uIP resources */ + } + else + { + /* No.. Just decrement the reference count */ + + conn->crefs--; + } + } + break; +#endif + + default: + err = EBADF; + goto errout; + } + } + + /* Then release our reference on the socket structure containing the connection */ + + sock_release(psock); + return OK; + +errout: + errno = err; + return ERROR; +} + +/**************************************************************************** + * Function: net_close + * + * Description: + * Performs the close operation on socket descriptors + * + * Parameters: + * sockfd Socket descriptor of socket + * + * Returned Value: + * 0 on success; -1 on error with errno set appropriately. + * + * Assumptions: + * + ****************************************************************************/ + +int net_close(int sockfd) +{ + return psock_close(sockfd_socket(sockfd)); +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/net_dsec2timeval.c b/nuttx/net/net_dsec2timeval.c new file mode 100644 index 0000000000..c9d3aeb66f --- /dev/null +++ b/nuttx/net/net_dsec2timeval.c @@ -0,0 +1,80 @@ +/**************************************************************************** + * net/net_dsec2timeval.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) + +#include +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: net_dsec2timeval + * + * Description: + * Convert a decisecond timeout value to a struct timeval. Needed by + * getsockopt() to report timeout values. + * + * Parameters: + * dsec The decisecond value to convert + * tv The struct timeval to receive the converted value + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void net_dsec2timeval(uint16_t dsec, struct timeval *tv) +{ + uint16_t remainder; + tv->tv_sec = dsec / DSEC_PER_SEC; + remainder = dsec - tv->tv_sec * DSEC_PER_SEC; + tv->tv_usec = remainder * USEC_PER_DSEC; +} + +#endif /* CONFIG_NET && CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */ diff --git a/nuttx/net/net_dup.c b/nuttx/net/net_dup.c new file mode 100644 index 0000000000..8465b7ce44 --- /dev/null +++ b/nuttx/net/net_dup.c @@ -0,0 +1,149 @@ +/**************************************************************************** + * net/net_dup.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "net_internal.h" + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: net_dup + * + * Description: + * Clone a socket descriptor to an arbitray descriptor number. If file + * descriptors are implemented, then this is called by dup() for the case + * of socket file descriptors. If file descriptors are not implemented, + * then this function IS dup(). + * + ****************************************************************************/ + +int net_dup(int sockfd, int minsd) +{ + FAR struct socket *psock1 = sockfd_socket(sockfd); + FAR struct socket *psock2; + int sockfd2; + int err; + int ret; + + /* Make sure that the minimum socket descriptor is within the legal range. + * the minimum value we receive is relative to file descriptor 0; we need + * map it relative of the first socket descriptor. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + if (minsd >= CONFIG_NFILE_DESCRIPTORS) + { + minsd -= CONFIG_NFILE_DESCRIPTORS; + } + else + { + minsd = 0; + } +#endif + + /* Lock the scheduler throughout the following */ + + sched_lock(); + + /* Get the socket structure underlying sockfd */ + + psock1 = sockfd_socket(sockfd); + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock1 || psock1->s_crefs <= 0) + { + err = EBADF; + goto errout; + } + + /* Allocate a new socket descriptor */ + + sockfd2 = sockfd_allocate(minsd); + if (sockfd2 < 0) + { + err = ENFILE; + goto errout; + } + + /* Get the socket structure underlying the new descriptor */ + + psock2 = sockfd_socket(sockfd2); + if (!psock2) + { + err = ENOSYS; /* should not happen */ + goto errout; + } + + /* Duplicate the socket state */ + + ret = net_clone(psock1, psock2); + if (ret < 0) + { + err = -ret; + goto errout; + + } + + sched_unlock(); + return sockfd2; + +errout: + sched_unlock(); + errno = err; + return ERROR; +} + +#endif /* defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 */ + + diff --git a/nuttx/net/net_dup2.c b/nuttx/net/net_dup2.c new file mode 100644 index 0000000000..b27bb69675 --- /dev/null +++ b/nuttx/net/net_dup2.c @@ -0,0 +1,125 @@ +/**************************************************************************** + * net/net_dup2.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "net_internal.h" + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: net_dup2 + * + * Description: + * Clone a socket descriptor to an arbitray descriptor number. If file + * descriptors are implemented, then this is called by dup2() for the case + * of socket file descriptors. If file descriptors are not implemented, + * then this function IS dup2(). + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +int net_dup2(int sockfd1, int sockfd2) +#else +int dup2(int sockfd1, int sockfd2) +#endif +{ + FAR struct socket *psock1; + FAR struct socket *psock2; + int err; + int ret; + + /* Lock the scheduler throughout the following */ + + sched_lock(); + + /* Get the socket structures underly both descriptors */ + + psock1 = sockfd_socket(sockfd1); + psock2 = sockfd_socket(sockfd2); + + /* Verify that the sockfd1 and sockfd2 both refer to valid socket + * descriptors and that sockfd2 corresponds to allocated socket + */ + + if (!psock1 || !psock2 || psock1->s_crefs <= 0) + { + err = EBADF; + goto errout; + } + + /* If sockfd2 also valid, allocated socket, then we will have to + * close it! + */ + + if (psock2->s_crefs > 0) + { + net_close(sockfd2); + } + + /* Duplicate the socket state */ + + ret = net_clone(psock1, psock2); + if (ret < 0) + { + err = -ret; + goto errout; + } + + sched_unlock(); + return OK; + +errout: + sched_unlock(); + errno = err; + return ERROR; +} + +#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS > 0 */ + + diff --git a/nuttx/net/net_internal.h b/nuttx/net/net_internal.h new file mode 100644 index 0000000000..ed2f12aa75 --- /dev/null +++ b/nuttx/net/net_internal.h @@ -0,0 +1,237 @@ +/**************************************************************************** + * net/net_internal.h + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __NET_INTERNAL_H +#define __NET_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Definitions of 8-bit socket flags */ + + /* Bits 0-2: Socket state */ +#define _SF_IDLE 0x00 /* - There is no socket activity */ +#define _SF_ACCEPT 0x01 /* - Socket is waiting to accept a connection */ +#define _SF_RECV 0x02 /* - Waiting for recv action to complete */ +#define _SF_SEND 0x03 /* - Waiting for send action to complete */ +#define _SF_MASK 0x03 /* - Mask to isolate the above actions */ + +#define _SF_NONBLOCK 0x08 /* Bit 3: Don't block if no data (TCP/READ only) */ +#define _SF_LISTENING 0x10 /* Bit 4: SOCK_STREAM is listening */ +#define _SF_BOUND 0x20 /* Bit 5: SOCK_STREAM is bound to an address */ + /* Bits 6-7: Connection state */ +#define _SF_CONNECTED 0x40 /* Bit 6: SOCK_STREAM is connected */ +#define _SF_CLOSED 0x80 /* Bit 7: SOCK_STREAM was gracefully disconnected */ + +/* Connection state encoding: + * + * _SF_CONNECTED==1 && _SF_CLOSED==0 - the socket is connected + * _SF_CONNECTED==0 && _SF_CLOSED==1 - the socket was gracefully disconnected + * _SF_CONNECTED==0 && _SF_CLOSED==0 - the socket was rudely disconnected + */ + +/* Macro to manage the socket state and flags */ + +#define _SS_SETSTATE(s,f) (((s) & ~_SF_MASK) | (f)) +#define _SS_GETSTATE(s) ((s) & _SF_MASK) +#define _SS_ISBUSY(s) (_SS_GETSTATE(s) != _SF_IDLE) + +#define _SS_ISNONBLOCK(s) (((s) & _SF_NONBLOCK) != 0) +#define _SS_ISLISTENING(s) (((s) & _SF_LISTENING) != 0) +#define _SS_ISBOUND(s) (((s) & _SF_CONNECTED) != 0) +#define _SS_ISCONNECTED(s) (((s) & _SF_CONNECTED) != 0) +#define _SS_ISCLOSED(s) (((s) & _SF_CLOSED) != 0) + +/* This macro converts a socket option value into a bit setting */ + +#define _SO_BIT(o) (1 << (o)) + +/* These define bit positions for each socket option (see sys/socket.h) */ + +#define _SO_DEBUG _SO_BIT(SO_DEBUG) +#define _SO_ACCEPTCONN _SO_BIT(SO_ACCEPTCONN) +#define _SO_BROADCAST _SO_BIT(SO_BROADCAST) +#define _SO_REUSEADDR _SO_BIT(SO_REUSEADDR) +#define _SO_KEEPALIVE _SO_BIT(SO_KEEPALIVE) +#define _SO_LINGER _SO_BIT(SO_LINGER) +#define _SO_OOBINLINE _SO_BIT(SO_OOBINLINE) +#define _SO_SNDBUF _SO_BIT(SO_SNDBUF) +#define _SO_RCVBUF _SO_BIT(SO_RCVBUF) +#define _SO_ERROR _SO_BIT(SO_ERROR) +#define _SO_TYPE _SO_BIT(SO_TYPE) +#define _SO_DONTROUTE _SO_BIT(SO_DONTROUTE) +#define _SO_RCVLOWAT _SO_BIT(SO_RCVLOWAT) +#define _SO_RCVTIMEO _SO_BIT(SO_RCVTIMEO) +#define _SO_SNDLOWAT _SO_BIT(SO_SNDLOWAT) +#define _SO_SNDTIMEO _SO_BIT(SO_SNDTIMEO) + +/* This is the larget option value */ + +#define _SO_MAXOPT (15) + +/* Macros to set, test, clear options */ + +#define _SO_SETOPT(s,o) ((s) |= _SO_BIT(o)) +#define _SO_CLROPT(s,o) ((s) &= ~_SO_BIT(o)) +#define _SO_GETOPT(s,o) (((s) & _SO_BIT(o)) != 0) + +/* These are macros that can be used to determine if socket option code is + * valid (in range) and supported by API. + */ + +#define _SO_GETONLYSET (_SO_ACCEPTCONN|_SO_ERROR|_SO_TYPE) +#define _SO_GETONLY(o) ((_SO_BIT(o) & _SO_GETONLYSET) != 0) +#define _SO_GETVALID(o) (((unsigned int)(o)) <= _SO_MAXOPT) +#define _SO_SETVALID(o) ((((unsigned int)(o)) <= _SO_MAXOPT) && !_SO_GETONLY(o)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* List of registered ethernet device drivers */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 +extern struct uip_driver_s *g_netdevices; +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* net_sockets.c *************************************************************/ + +EXTERN int sockfd_allocate(int minsd); +EXTERN void sock_release(FAR struct socket *psock); +EXTERN void sockfd_release(int sockfd); +EXTERN FAR struct socket *sockfd_socket(int sockfd); + +/* net_connect.c *************************************************************/ + +#ifdef CONFIG_NET_TCP +EXTERN int net_startmonitor(FAR struct socket *psock); +EXTERN void net_stopmonitor(FAR struct uip_conn *conn); +#endif + +/* net_close.c ***************************************************************/ + +EXTERN int psock_close(FAR struct socket *psock); + +/* sockopt support ***********************************************************/ + +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) +EXTERN int net_timeo(uint32_t start_time, socktimeo_t timeo); +EXTERN socktimeo_t net_timeval2dsec(struct timeval *tv); +EXTERN void net_dsec2timeval(uint16_t dsec, struct timeval *tv); +#endif + +/* net_register.c ************************************************************/ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 +EXTERN void netdev_seminit(void); +EXTERN void netdev_semtake(void); +EXTERN void netdev_semgive(void); +#endif + +/* net_findbyname.c **********************************************************/ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 +EXTERN FAR struct uip_driver_s *netdev_findbyname(const char *ifname); +#endif + +/* net_findbyaddr.c **********************************************************/ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 +EXTERN FAR struct uip_driver_s *netdev_findbyaddr(const uip_ipaddr_t *raddr); +#endif + +/* net_txnotify.c ************************************************************/ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 +EXTERN void netdev_txnotify(const uip_ipaddr_t *raddr); +#endif + +/* net_count.c ***************************************************************/ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 +EXTERN int netdev_count(void); +#endif + +/* net_arptimer.c ************************************************************/ + +#ifdef CONFIG_NET_ARP +EXTERN void arptimer_init(void); +#else +# define arptimer_init() +#endif + +/* send.c ********************************************************************/ + +EXTERN ssize_t psock_send(FAR struct socket *psock, const void *buf, + size_t len, int flags); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* CONFIG_NET */ +#endif /* __NET_INTERNAL_H */ diff --git a/nuttx/net/net_monitor.c b/nuttx/net/net_monitor.c new file mode 100644 index 0000000000..4bdae4ccf3 --- /dev/null +++ b/nuttx/net/net_monitor.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * net/net_monitor.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) + +#include +#include +#include + +#include "net_internal.h" +#include "uip/uip_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void connection_event(struct uip_conn *conn, uint16_t flags); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: connection_event + * + * Description: + * Some connection related event has occurred + * + * Parameters: + * dev The sructure of the network driver that caused the interrupt + * conn The connection structure associated with the socket + * flags Set of events describing why the callback was invoked + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +static void connection_event(struct uip_conn *conn, uint16_t flags) +{ + FAR struct socket *psock = (FAR struct socket *)conn->connection_private; + + if (psock) + { + nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags); + + /* These loss-of-connection events may be reported: + * + * UIP_CLOSE: The remote host has closed the connection + * UIP_ABORT: The remote host has aborted the connection + * UIP_TIMEDOUT: Connection aborted due to too many retransmissions. + * + * And we need to set these two socket status bits appropriately: + * + * _SF_CONNECTED==1 && _SF_CLOSED==0 - the socket is connected + * _SF_CONNECTED==0 && _SF_CLOSED==1 - the socket was gracefully disconnected + * _SF_CONNECTED==0 && _SF_CLOSED==0 - the socket was rudely disconnected + */ + + if ((flags & UIP_CLOSE) != 0) + { + /* The peer gracefully closed the connection. Marking the + * connection as disconnected will suppress some subsequent + * ENOTCONN errors from receive. A graceful disconnection is + * not handle as an error but as an "end-of-file" + */ + + psock->s_flags &= ~_SF_CONNECTED; + psock->s_flags |= _SF_CLOSED; + } + else if ((flags & (UIP_ABORT|UIP_TIMEDOUT)) != 0) + { + /* The loss of connection was less than graceful. This will (eventually) + * be reported as an ENOTCONN error. + */ + + psock->s_flags &= ~(_SF_CONNECTED |_SF_CLOSED); + } + + /* UIP_CONNECTED: The socket is successfully connected */ + + else if ((flags & UIP_CONNECTED) != 0) + { + /* Indicate that the socket is now connected */ + + psock->s_flags |= _SF_CONNECTED; + psock->s_flags &= ~_SF_CLOSED; + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: net_startmonitor + * + * Description: + * Set up to receive TCP connection state changes for a given socket + * + * Input Parameters: + * psock - The socket of interest + * + * Returned Value: + * For now, this function always returns OK. + * + ****************************************************************************/ + +int net_startmonitor(FAR struct socket *psock) +{ + FAR struct uip_conn *conn = psock->s_conn; + + DEBUGASSERT(psock && conn); + + /* Set up to receive callbacks on connection-related events */ + + conn->connection_private = (void*)psock; + conn->connection_event = connection_event; + return OK; +} + +/**************************************************************************** + * Name: net_stopmonitor + * + * Description: + * Stop monitoring TCP connection changes for a given socket + * + * Input Parameters: + * conn - The TCP connection of interest + * + * Returned Value: + * None + * + ****************************************************************************/ + +void net_stopmonitor(FAR struct uip_conn *conn) +{ + DEBUGASSERT(conn); + + conn->connection_private = NULL; + conn->connection_event = NULL; +} + +#endif /* CONFIG_NET && CONFIG_NET_TCP */ diff --git a/nuttx/net/net_poll.c b/nuttx/net/net_poll.c new file mode 100644 index 0000000000..ca594c10fc --- /dev/null +++ b/nuttx/net/net_poll.c @@ -0,0 +1,354 @@ +/**************************************************************************** + * net/net_poll.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && !defined(CONFIG_DISABLE_POLL) + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "net_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Network polling can only be supported on TCP and only if read-ahead buffering + * is enabled (it could be supported on UDP as will if it also had read-ahead + * buffering. + */ + +#if !defined(CONFIG_DISABLE_POLL) && CONFIG_NSOCKET_DESCRIPTORS > 0 && \ + defined(CONFIG_NET_TCP) && CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 +# define HAVE_NETPOLL 1 +#else +# undef HAVE_NETPOLL +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: poll_interrupt + * + * Description: + * This function is called from the interrupt level to perform the actual + * TCP receive operation via by the uIP layer. + * + * Parameters: + * dev The structure of the network driver that caused the interrupt + * conn The connection structure associated with the socket + * flags Set of events describing why the callback was invoked + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#ifdef HAVE_NETPOLL +static uint16_t poll_interrupt(struct uip_driver_s *dev, FAR void *conn, + FAR void *pvpriv, uint16_t flags) +{ + FAR struct pollfd *fds = (FAR struct pollfd *)pvpriv; + + nllvdbg("flags: %04x\n", flags); + + /* 'priv' might be null in some race conditions (?) */ + + if (fds) + { + pollevent_t eventset = 0; + + /* Check for data or connection availability events. */ + + if ((flags & (UIP_NEWDATA|UIP_BACKLOG)) != 0) + { + eventset |= POLLIN & fds->events; + } + + /* A poll is a sign that we are free to send data. */ + + if ((flags & UIP_POLL) != 0) + { + eventset |= POLLOUT & fds->events; + } + + /* Check for a loss of connection events */ + + if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) + { + eventset |= (POLLERR|POLLHUP); + } + + if (eventset) + { + fds->revents |= eventset; + sem_post(fds->sem); + } + } + return flags; +} +#endif /* HAVE_NETPOLL */ + +/**************************************************************************** + * Function: net_pollsetup + * + * Description: + * Setup to monitor events on one TCP/IP socket + * + * Input Parameters: + * conn - The TCP/IP connection of interest + * fds - The structure describing the events to be monitored, OR NULL if + * this is a request to stop monitoring events. + * + * Returned Value: + * 0: Success; Negated errno on failure + * + ****************************************************************************/ + +#ifdef HAVE_NETPOLL +static inline int net_pollsetup(FAR struct socket *psock, struct pollfd *fds) +{ + FAR struct uip_conn *conn = psock->s_conn; + FAR struct uip_callback_s *cb; + uip_lock_t flags; + int ret; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (!conn || !fds) + { + return -EINVAL; + } +#endif + + /* Some of the following must be atomic */ + + flags = uip_lock(); + + /* Allocate a TCP/IP callback structure */ + + cb = uip_tcpcallbackalloc(conn); + if (!cb) + { + ret = -EBUSY; + goto errout_with_irq; + } + + /* Initialize the callbcack structure */ + + cb->flags = UIP_NEWDATA|UIP_BACKLOG|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT; + cb->priv = (FAR void *)fds; + cb->event = poll_interrupt; + + /* Save the nps reference in the poll structure for use at teardown as well */ + + fds->priv = (FAR void *)cb; + +#ifdef CONFIG_NET_TCPBACKLOG + /* Check for read data or backlogged connection availability now */ + + if (!sq_empty(&conn->readahead) || uip_backlogavailable(conn)) +#else + /* Check for read data availability now */ + + if (!sq_empty(&conn->readahead)) +#endif + { + fds->revents = fds->events & POLLIN; + if (fds->revents != 0) + { + /* If data is available now, the signal the poll logic */ + + sem_post(fds->sem); + } + } + uip_unlock(flags); + return OK; + +errout_with_irq: + uip_unlock(flags); + return ret; +} +#endif /* HAVE_NETPOLL */ + +/**************************************************************************** + * Function: net_pollteardown + * + * Description: + * Teardown monitoring of events on an TCP/IP socket + * + * Input Parameters: + * conn - The TCP/IP connection of interest + * + * Returned Value: + * 0: Success; Negated errno on failure + * + ****************************************************************************/ + +#ifdef HAVE_NETPOLL +static inline int net_pollteardown(FAR struct socket *psock, struct pollfd *fds) +{ + FAR struct uip_conn *conn = psock->s_conn; + FAR struct uip_callback_s *cb; + uip_lock_t flags; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (!conn || !fds->priv) + { + return -EINVAL; + } +#endif + + /* Recover the socket descriptor poll state info from the poll structure */ + + cb = (FAR struct uip_callback_s *)fds->priv; + if (cb) + { + /* Release the callback */ + + flags = uip_lock(); + uip_tcpcallbackfree(conn, cb); + uip_unlock(flags); + + /* Release the poll/select data slot */ + + fds->priv = NULL; + } + + return OK; +} +#endif /* HAVE_NETPOLL */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: net_poll + * + * Description: + * The standard poll() operation redirects operations on socket descriptors + * to this function. + * + * Input Parameters: + * fd - The socket descriptor of interest + * fds - The structure describing the events to be monitored, OR NULL if + * this is a request to stop monitoring events. + * setup - true: Setup up the poll; false: Teardown the poll + * + * Returned Value: + * 0: Success; Negated errno on failure + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +int net_poll(int sockfd, struct pollfd *fds, bool setup) +{ +#ifndef HAVE_NETPOLL + return -ENOSYS; +#else + FAR struct socket *psock; + int ret; + + /* Get the underlying socket structure and verify that the sockfd + * corresponds to valid, allocated socket + */ + + psock = sockfd_socket(sockfd); + if (!psock || psock->s_crefs <= 0) + { + ret = -EBADF; + goto errout; + } + +#ifdef CONFIG_NET_UDP + /* poll() not supported for UDP */ + + if (psock->s_type != SOCK_STREAM) + { + ret = -ENOSYS; + goto errout; + } +#endif + + /* Check if we are setting up or tearing down the poll */ + + if (setup) + { + /* Perform the TCP/IP poll() setup */ + + ret = net_pollsetup(psock, fds); + } + else + { + /* Perform the TCP/IP poll() teardown */ + + ret = net_pollteardown(psock, fds); + } + +errout: + return ret; +#endif /* HAVE_NETPOLL */ +} +#endif /* !CONFIG_DISABLE_POLL */ + +#endif /* CONFIG_NET && !CONFIG_DISABLE_POLL */ diff --git a/nuttx/net/net_sockets.c b/nuttx/net/net_sockets.c new file mode 100644 index 0000000000..81e48c1210 --- /dev/null +++ b/nuttx/net/net_sockets.c @@ -0,0 +1,313 @@ +/**************************************************************************** + * net/net_sockets.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 +static void _net_semtake(FAR struct socketlist *list) +{ + /* Take the semaphore (perhaps waiting) */ + + while (uip_lockedwait(&list->sl_sem) != 0) + { + /* The only case that an error should occr here is if + * the wait was awakened by a signal. + */ + + ASSERT(*get_errno_ptr() == EINTR); + } +} + +# define _net_semgive(list) sem_post(&list->sl_sem) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* This is called from the initialization logic to configure the socket layer */ + +void net_initialize(void) +{ + /* Initialize the uIP layer */ + + uip_initialize(); + + /* Initialize the socket layer */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + netdev_seminit(); +#endif + + /* Initialize the periodic ARP timer */ + + arptimer_init(); +} + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + +/* Allocate a list of files for a new task */ + +FAR struct socketlist *net_alloclist(void) +{ + FAR struct socketlist *list; + list = (FAR struct socketlist*)kzalloc(sizeof(struct socketlist)); + if (list) + { + /* Start with a reference count of one */ + + list->sl_crefs = 1; + + /* Initialize the list access mutex */ + + (void)sem_init(&list->sl_sem, 0, 1); + } + return list; +} + +/* Increase the reference count on a file list */ + +int net_addreflist(FAR struct socketlist *list) +{ + if (list) + { + /* Increment the reference count on the list. + * NOTE: that we disable interrupts to do this + * (vs. taking the list semaphore). We do this + * because file cleanup operations often must be + * done from the IDLE task which cannot wait + * on semaphores. + */ + + register uip_lock_t flags = uip_lock(); + list->sl_crefs++; + uip_unlock(flags); + } + return OK; +} + +/* Release a reference to the file list */ + +int net_releaselist(FAR struct socketlist *list) +{ + int crefs; + int ndx; + + if (list) + { + /* Decrement the reference count on the list. + * NOTE: that we disable interrupts to do this + * (vs. taking the list semaphore). We do this + * because file cleanup operations often must be + * done from the IDLE task which cannot wait + * on semaphores. + */ + + uip_lock_t flags = uip_lock(); + crefs = --(list->sl_crefs); + uip_unlock(flags); + + /* If the count decrements to zero, then there is no reference + * to the structure and it should be deallocated. Since there + * are references, it would be an error if any task still held + * a reference to the list's semaphore. + */ + + if (crefs <= 0) + { + /* Close each open socket in the list + * REVISIT: psock_close() will attempt to use semaphores. + * If we actually are in the IDLE thread, then could this cause + * problems? Probably not, if the task has exited and crefs is + * zero, then there probably could not be a contender for the + * semaphore. + */ + + for (ndx = 0; ndx < CONFIG_NSOCKET_DESCRIPTORS; ndx++) + { + FAR struct socket *psock = &list->sl_sockets[ndx]; + if (psock->s_crefs > 0) + { + (void)psock_close(psock); + } + } + + /* Destroy the semaphore and release the filelist */ + + (void)sem_destroy(&list->sl_sem); + sched_free(list); + } + } + return OK; +} + +int sockfd_allocate(int minsd) +{ + FAR struct socketlist *list; + int i; + + /* Get the socket list for this task/thread */ + + list = sched_getsockets(); + if (list) + { + /* Search for a socket structure with no references */ + + _net_semtake(list); + for (i = minsd; i < CONFIG_NSOCKET_DESCRIPTORS; i++) + { + /* Are there references on this socket? */ + + if (!list->sl_sockets[i].s_crefs) + { + /* No take the reference and return the index + an offset + * as the socket descriptor. + */ + + memset(&list->sl_sockets[i], 0, sizeof(struct socket)); + list->sl_sockets[i].s_crefs = 1; + _net_semgive(list); + return i + __SOCKFD_OFFSET; + } + } + _net_semgive(list); + } + + return ERROR; +} + +void sock_release(FAR struct socket *psock) +{ +#if CONFIG_DEBUG + if (psock) +#endif + { + /* Take the list semaphore so that there will be no accesses + * to this socket structure. + */ + + FAR struct socketlist *list = sched_getsockets(); + if (list) + { + /* Decrement the count if there the socket will persist + * after this. + */ + + _net_semtake(list); + if (psock && psock->s_crefs > 1) + { + psock->s_crefs--; + } + else + { + /* The socket will not persist... reset it */ + + memset(psock, 0, sizeof(struct socket)); + } + _net_semgive(list); + } + } +} + +void sockfd_release(int sockfd) +{ + /* Get the socket structure for this sockfd */ + + FAR struct socket *psock = sockfd_socket(sockfd); + + /* Get the socket structure for this sockfd */ + + if (psock) + { + sock_release(psock); + } +} + +FAR struct socket *sockfd_socket(int sockfd) +{ + FAR struct socketlist *list; + int ndx = sockfd - __SOCKFD_OFFSET; + + if (ndx >=0 && ndx < CONFIG_NSOCKET_DESCRIPTORS) + { + list = sched_getsockets(); + if (list) + { + return &list->sl_sockets[ndx]; + } + } + return NULL; +} + +#endif /* CONFIG_NSOCKET_DESCRIPTORS */ +#endif /* CONFIG_NET */ diff --git a/nuttx/net/net_timeo.c b/nuttx/net/net_timeo.c new file mode 100644 index 0000000000..c593c45c79 --- /dev/null +++ b/nuttx/net/net_timeo.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * net/net_timeo.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) + +#include +#include + +#include + +#include "net_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: net_timeo + * + * Description: + * Check if a timeout has elapsed. This can be called from a socket poll + * function to determine if a timeout has occurred. + * + * Parameters: + * start_time Timeout start time in system clock ticks + * timeout Timeout value in deciseconds. + * + * Returned Value: + * 0 (FALSE) if not timeout; 1 (TRUE) if timeout + * + * Assumptions: + * + ****************************************************************************/ + +int net_timeo(uint32_t start_time, socktimeo_t timeo) +{ + uint32_t timeo_ticks = DSEC2TICK(timeo); + uint32_t elapsed = clock_systimer() - start_time; + + if (elapsed >= timeo_ticks) + { + return TRUE; + } + return FALSE; +} + +#endif /* CONFIG_NET && CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */ + diff --git a/nuttx/net/net_timeval2dsec.c b/nuttx/net/net_timeval2dsec.c new file mode 100644 index 0000000000..4ca5ecb5f1 --- /dev/null +++ b/nuttx/net/net_timeval2dsec.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * net/net_timeval2dsec.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) + +#include +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: net_timeval2dsec + * + * Description: + * Convert a struct timeval to deciseconds. Needed by setsockopt() to + * save new timeout values. + * + * Parameters: + * tv The struct timeval to convert + * + * Returned Value: + * the converted value + * + * Assumptions: + * + ****************************************************************************/ + +socktimeo_t net_timeval2dsec(struct timeval *tv) +{ + return (uint16_t)(tv->tv_sec* DSEC_PER_SEC + tv->tv_usec / USEC_PER_DSEC); +} + +#endif /* CONFIG_NET && CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */ diff --git a/nuttx/net/net_vfcntl.c b/nuttx/net/net_vfcntl.c new file mode 100644 index 0000000000..7650264bf2 --- /dev/null +++ b/nuttx/net/net_vfcntl.c @@ -0,0 +1,234 @@ +/**************************************************************************** + * net/net_vfcntl.c + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include "net_internal.h" + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +int net_vfcntl(int sockfd, int cmd, va_list ap) +{ + FAR struct socket *psock = sockfd_socket(sockfd); + uip_lock_t flags; + int err = 0; + int ret = 0; + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + err = EBADF; + goto errout; + } + + /* Interrupts must be disabled in order to perform operations on socket structures */ + + flags = uip_lock(); + switch (cmd) + { + case F_DUPFD: + /* Return a new file descriptor which shall be the lowest numbered + * available (that is, not already open) file descriptor greater than + * or equal to the third argument, arg, taken as an integer of type + * int. The new file descriptor shall refer to the same open file + * description as the original file descriptor, and shall share any + * locks. The FD_CLOEXEC flag associated with the new file descriptor + * shall be cleared to keep the file open across calls to one of the + * exec functions. + */ + + { + ret = net_dup(sockfd, va_arg(ap, int)); + } + break; + + case F_GETFD: + /* Get the file descriptor flags defined in that are associated + * with the file descriptor fildes. File descriptor flags are associated + * with a single file descriptor and do not affect other file descriptors + * that refer to the same file. + */ + + case F_SETFD: + /* Set the file descriptor flags defined in , that are associated + * with fildes, to the third argument, arg, taken as type int. If the + * FD_CLOEXEC flag in the third argument is 0, the file shall remain open + * across the exec functions; otherwise, the file shall be closed upon + * successful execution of one of the exec functions. + */ + + err = ENOSYS; /* F_GETFD and F_SETFD not implemented */ + break; + + case F_GETFL: + /* Get the file status flags and file access modes, defined in , + * for the file description associated with fildes. The file access modes + * can be extracted from the return value using the mask O_ACCMODE, which is + * defined in . File status flags and file access modes are associated + * with the file description and do not affect other file descriptors that + * refer to the same file with different open file descriptions. + */ + + { + /* This summarizes the behavior of the NuttX/uIP sockets */ + + ret = O_RDWR | O_SYNC | O_RSYNC; + + /* TCP/IP sockets may also be non-blocking if read-ahead is enabled */ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + if (psock->s_type == SOCK_STREAM && _SS_ISNONBLOCK(psock->s_flags)) + { + ret |= O_NONBLOCK; + } +#endif + } + break; + + case F_SETFL: + /* Set the file status flags, defined in , for the file description + * associated with fildes from the corresponding bits in the third argument, + * arg, taken as type int. Bits corresponding to the file access mode and + * the file creation flags, as defined in , that are set in arg shall + * be ignored. If any bits in arg other than those mentioned here are changed + * by the application, the result is unspecified. + */ + + { + /* Non-blocking is the only configurable option. And it applies only to + * read operations on TCP/IP sockets when read-ahead is enabled. + */ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + int mode = va_arg(ap, int); + if (psock->s_type == SOCK_STREAM) + { + if ((mode & O_NONBLOCK) != 0) + { + psock->s_flags |= _SF_NONBLOCK; + } + else + { + psock->s_flags &= ~_SF_NONBLOCK; + } + } +#endif + } + break; + + case F_GETOWN: + /* If fildes refers to a socket, get the process or process group ID specified + * to receive SIGURG signals when out-of-band data is available. Positive values + * indicate a process ID; negative values, other than -1, indicate a process group + * ID. If fildes does not refer to a socket, the results are unspecified. + */ + + case F_SETOWN: + /* If fildes refers to a socket, set the process or process group ID specified + * to receive SIGURG signals when out-of-band data is available, using the value + * of the third argument, arg, taken as type int. Positive values indicate a + * process ID; negative values, other than -1, indicate a process group ID. If + * fildes does not refer to a socket, the results are unspecified. + */ + + case F_GETLK: + /* Get the first lock which blocks the lock description pointed to by the third + * argument, arg, taken as a pointer to type struct flock, defined in . + * The information retrieved shall overwrite the information passed to fcntl() in + * the structure flock. If no lock is found that would prevent this lock from being + * created, then the structure shall be left unchanged except for the lock type + * which shall be set to F_UNLCK. + */ + + case F_SETLK: + /* Set or clear a file segment lock according to the lock description pointed to + * by the third argument, arg, taken as a pointer to type struct flock, defined in + * . F_SETLK can establish shared (or read) locks (F_RDLCK) or exclusive + * (or write) locks (F_WRLCK), as well as to remove either type of lock (F_UNLCK). + * F_RDLCK, F_WRLCK, and F_UNLCK are defined in . If a shared or exclusive + * lock cannot be set, fcntl() shall return immediately with a return value of -1. + */ + + case F_SETLKW: + /* This command shall be equivalent to F_SETLK except that if a shared or exclusive + * lock is blocked by other locks, the thread shall wait until the request can be + * satisfied. If a signal that is to be caught is received while fcntl() is waiting + * for a region, fcntl() shall be interrupted. Upon return from the signal handler, + * fcntl() shall return -1 with errno set to [EINTR], and the lock operation shall + * not be done. + */ + + err = ENOSYS; /* F_GETOWN, F_SETOWN, F_GETLK, F_SETLK, F_SETLKW */ + break; + + default: + err = EINVAL; + break; + } + + uip_unlock(flags); + +errout: + if (err != 0) + { + errno = err; + return ERROR; + } + return ret; +} + +#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS > 0 */ + diff --git a/nuttx/net/netdev_count.c b/nuttx/net/netdev_count.c new file mode 100644 index 0000000000..17f0894da6 --- /dev/null +++ b/nuttx/net/netdev_count.c @@ -0,0 +1,102 @@ +/**************************************************************************** + * net/netdev_count.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +#include +#include + +#include + +#include "net_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Priviate Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: netdev_count + * + * Description: + * Return the number of network devices + * + * Parameters: + * None + * + * Returned Value: + * The number of network devices + * + * Assumptions: + * Called from normal user mode + * + ****************************************************************************/ + +int netdev_count(void) +{ + struct uip_driver_s *dev; + int ndev; + + netdev_semtake(); + for (dev = g_netdevices, ndev = 0; dev; dev = dev->flink, ndev++); + netdev_semgive(); + return ndev; +} + +#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/net/netdev_findbyaddr.c b/nuttx/net/netdev_findbyaddr.c new file mode 100644 index 0000000000..50a246f67e --- /dev/null +++ b/nuttx/net/netdev_findbyaddr.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * net/netdev_findbyaddr.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +#include +#include +#include +#include + +#include + +#include "net_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Priviate Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: netdev_maskcmp + ****************************************************************************/ + +static inline bool netdev_maskcmp(const uip_ipaddr_t *ipaddr, + const uip_ipaddr_t *raddr, + const uip_ipaddr_t *netmask) +{ +#ifndef CONFIG_NET_IPv6 + return (*ipaddr & *netmask) == (*raddr & *netmask); +#else +# warning "Not implemented for IPv6" + return false; +#endif +} + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: netdev_findbyaddr + * + * Description: + * Find a previously registered network device by matching a remote address + * with the subnet served by the device + * + * Parameters: + * raddr - Pointer to the remote address of a connection + * + * Returned Value: + * Pointer to driver on success; null on failure + * + * Assumptions: + * Called from normal user mode + * + ****************************************************************************/ + +FAR struct uip_driver_s *netdev_findbyaddr(const uip_ipaddr_t *raddr) +{ + struct uip_driver_s *dev; + + if (raddr) + { + netdev_semtake(); + for (dev = g_netdevices; dev; dev = dev->flink) + { + if (netdev_maskcmp(&dev->d_ipaddr, raddr, &dev->d_netmask)) + { + netdev_semgive(); + return dev; + } + } + netdev_semgive(); + } + return NULL; +} + +#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/net/netdev_findbyname.c b/nuttx/net/netdev_findbyname.c new file mode 100644 index 0000000000..a6ddf0452d --- /dev/null +++ b/nuttx/net/netdev_findbyname.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * net/netdev_findbyname.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +#include +#include + +#include + +#include "net_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Priviate Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: netdev_findbyname + * + * Description: + * Find a previously registered network device using its assigned + * network interface name + * + * Parameters: + * ifname The interface name of the device of interest + * + * Returned Value: + * Pointer to driver on success; null on failure + * + * Assumptions: + * Called from normal user mode + * + ****************************************************************************/ + +FAR struct uip_driver_s *netdev_findbyname(const char *ifname) +{ + struct uip_driver_s *dev; + if (ifname) + { + netdev_semtake(); + for (dev = g_netdevices; dev; dev = dev->flink) + { + if (strcmp(ifname, dev->d_ifname) == 0) + { + netdev_semgive(); + return dev; + } + } + netdev_semgive(); + } + return NULL; +} + +#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/net/netdev_foreach.c b/nuttx/net/netdev_foreach.c new file mode 100644 index 0000000000..f88444ad84 --- /dev/null +++ b/nuttx/net/netdev_foreach.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * net/netdev_foreach.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Priviate Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: netdev_foreach + * + * Description: + * Enumerate each registered network device. + * + * NOTE: netdev semaphore held throughout enumeration. + * + * Parameters: + * callback - Will be called for each registered device + * arg - User argument passed to callback() + * + * Returned Value: + * 0:Enumeration completed 1:Enumeration terminated early by callback + * + * Assumptions: + * Called from normal user mode + * + ****************************************************************************/ + +int netdev_foreach(netdev_callback_t callback, void *arg) +{ + struct uip_driver_s *dev; + int ret = 0; + + if (callback) + { + netdev_semtake(); + for (dev = g_netdevices; dev; dev = dev->flink) + { + if (callback(dev, arg) != 0) + { + ret = 1; + break; + } + } + netdev_semgive(); + } + return ret; +} + +#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/net/netdev_ioctl.c b/nuttx/net/netdev_ioctl.c new file mode 100644 index 0000000000..4b5876efa0 --- /dev/null +++ b/nuttx/net/netdev_ioctl.c @@ -0,0 +1,419 @@ +/**************************************************************************** + * net/netdev_ioctl.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#ifdef CONFIG_NET_IGMP +# include "sys/sockio.h" +# include "nuttx/net/uip/uip-igmp.h" +#endif + +#include "net_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +# define AF_INETX AF_INET6 +#else +# define AF_INETX AF_INET +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ioctl_getipaddr + * + * Description: + * Copy IP addresses from device structure to user memory. + * + * Input Parameters: + * outaddr - Pointer to the user-provided memory to receive the address. + * Actual type may be either 'struct sockaddr' (IPv4 only) or type + * 'struct sockaddr_storage' (both IPv4 and IPv6). + * inaddr - The source IP adress in the device structure. + * + ****************************************************************************/ + +static void ioctl_getipaddr(FAR void *outaddr, FAR const uip_ipaddr_t *inaddr) +{ +#ifdef CONFIG_NET_IPv6 + FAR struct sockaddr_in6 *dest = (FAR struct sockaddr_in6 *)outaddr; + dest->sin_family = AF_INET6; + dest->sin_port = 0; + memcpy(dest->sin6_addr.in6_u.u6_addr8, inaddr, 16); +#else + FAR struct sockaddr_in *dest = (FAR struct sockaddr_in *)outaddr; + dest->sin_family = AF_INET; + dest->sin_port = 0; + dest->sin_addr.s_addr = *inaddr; +#endif +} + +/**************************************************************************** + * Name: ioctl_setipaddr + * + * Description: + * Copy IP addresses from user memory into the device structure + * + * Input Parameters: + * outaddr - Pointer to the source IP address in the device structure. + * inaddr - Pointer to the user-provided memory to containing the new IP + * address. Actual type may be either 'struct sockaddr' (IPv4 only) or + * type 'struct sockaddr_storage' (both IPv4 and IPv6). + * + ****************************************************************************/ + +static void ioctl_setipaddr(FAR uip_ipaddr_t *outaddr, FAR const void *inaddr) +{ +#ifdef CONFIG_NET_IPv6 + FAR const struct sockaddr_in6 *src = (FAR const struct sockaddr_in6 *)inaddr; + memcpy(outaddr, src->sin6_addr.in6_u.u6_addr8, 16); +#else + FAR const struct sockaddr_in *src = (FAR const struct sockaddr_in *)inaddr; + *outaddr = src->sin_addr.s_addr; +#endif +} + +/**************************************************************************** + * Name: ioctl_ifup / ioctl_ifdown + * + * Description: + * Bring the interface up/down + * + ****************************************************************************/ + +static inline void ioctl_ifup(FAR struct uip_driver_s *dev) +{ + if (dev->d_ifup) + { + dev->d_ifup(dev); + } +} + +static inline void ioctl_ifdown(FAR struct uip_driver_s *dev) +{ + if (dev->d_ifdown) + { + dev->d_ifdown(dev); + } +} + +/**************************************************************************** + * Name: netdev_ioctl + * + * Description: + * Perform network device specific operations. + * + * Parameters: + * psock Socket structure + * dev Ethernet driver device structure + * cmd The ioctl command + * req The argument of the ioctl cmd + * + * Return: + * >=0 on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +static int netdev_ifrioctl(FAR struct socket *psock, int cmd, struct ifreq *req) +{ + FAR struct uip_driver_s *dev; + int ret = OK; + + nvdbg("cmd: %d\n", cmd); + + /* Find the network device associated with the device name + * in the request data. + */ + + dev = netdev_findbyname(req->ifr_name); + if (!dev) + { + ret = -EINVAL; + goto errout; + } + + /* Execute the command */ + + switch (cmd) + { + case SIOCGIFADDR: /* Get IP address */ + ioctl_getipaddr(&req->ifr_addr, &dev->d_ipaddr); + break; + + case SIOCSIFADDR: /* Set IP address */ + ioctl_ifdown(dev); + ioctl_setipaddr(&dev->d_ipaddr, &req->ifr_addr); + ioctl_ifup(dev); + break; + + case SIOCGIFDSTADDR: /* Get P-to-P address */ + ioctl_getipaddr(&req->ifr_dstaddr, &dev->d_draddr); + break; + + case SIOCSIFDSTADDR: /* Set P-to-P address */ + ioctl_setipaddr(&dev->d_draddr, &req->ifr_dstaddr); + break; + + case SIOCGIFNETMASK: /* Get network mask */ + ioctl_getipaddr(&req->ifr_addr, &dev->d_netmask); + break; + + case SIOCSIFNETMASK: /* Set network mask */ + ioctl_setipaddr(&dev->d_netmask, &req->ifr_addr); + break; + + case SIOCGIFMTU: /* Get MTU size */ + req->ifr_mtu = CONFIG_NET_BUFSIZE; + break; + + /* MAC address operations only make sense if Ethernet is supported */ + +#ifdef CONFIG_NET_ETHERNET + case SIOCGIFHWADDR: /* Get hardware address */ + req->ifr_hwaddr.sa_family = AF_INETX; + memcpy(req->ifr_hwaddr.sa_data, dev->d_mac.ether_addr_octet, IFHWADDRLEN); + break; + + case SIOCSIFHWADDR: /* Set hardware address -- will not take effect until ifup */ + req->ifr_hwaddr.sa_family = AF_INETX; + memcpy(dev->d_mac.ether_addr_octet, req->ifr_hwaddr.sa_data, IFHWADDRLEN); + break; +#endif + + case SIOCDIFADDR: /* Delete IP address */ + ioctl_ifdown(dev); + memset(&dev->d_ipaddr, 0, sizeof(uip_ipaddr_t)); + break; + + case SIOCGIFCOUNT: /* Get number of devices */ + req->ifr_count = netdev_count(); + ret = -ENOSYS; + break; + + case SIOCGIFBRDADDR: /* Get broadcast IP address */ + case SIOCSIFBRDADDR: /* Set broadcast IP address */ + ret = -ENOSYS; + break; + +#ifdef CONFIG_NET_ARPIOCTLS + case SIOCSARP: /* Set a ARP mapping */ + case SIOCDARP: /* Delete an ARP mapping */ + case SIOCGARP: /* Get an ARP mapping */ +# error "IOCTL Commands not implemented" +#endif + + default: + ret = -EINVAL; + break;; + } + +errout: + return ret; +} + +/**************************************************************************** + * Name: netdev_imsfioctl + * + * Description: + * Perform network device specific operations. + * + * Parameters: + * psock Socket structure + * dev Ethernet driver device structure + * cmd The ioctl command + * imsf The argument of the ioctl cmd + * + * Return: + * >=0 on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int netdev_imsfioctl(FAR struct socket *psock, int cmd, struct ip_msfilter *imsf) +{ + FAR struct uip_driver_s *dev; + int ret = OK; + + nvdbg("cmd: %d\n", cmd); + + /* Find the network device associated with the device name + * in the request data. + */ + + dev = netdev_findbyname(imsf->imsf_name); + if (!dev) + { + ret = -EINVAL; + goto errout; + } + + /* Execute the command */ + + switch (cmd) + { + case SIOCSIPMSFILTER: /* Set source filter content */ + { + if (imsf->imsf_fmode == MCAST_INCLUDE) + { + ret = igmp_joingroup(dev, &imsf->imsf_multiaddr); + } + else + { + DEBUGASSERT(imsf->imsf_fmode == MCAST_EXCLUDE); + ret = igmp_leavegroup(dev, &imsf->imsf_multiaddr); + } + } + break; + + case SIOCGIPMSFILTER: /* Retrieve source filter addresses */ + default: + ret = -EINVAL; + break; + } + +errout: + return ret; +} +#endif + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: netdev_ioctl + * + * Description: + * Perform network device specific operations. + * + * Parameters: + * sockfd Socket descriptor of device + * cmd The ioctl command + * req The argument of the ioctl cmd + * + * Return: + * >=0 on success (positive non-zero values are cmd-specific) + * On a failure, -1 is returned with errno set appropriately + * + * EBADF + * 'sockfd' is not a valid descriptor. + * EFAULT + * 'req' references an inaccessible memory area. + * EINVAL + * 'cmd' or 'req' is not valid. + * ENOTTY + * 'sockfd' is not associated with a network device. + * ENOTTY + * The specified request does not apply to the kind of object that the + * descriptor 'sockfd' references. + * + ****************************************************************************/ + +int netdev_ioctl(int sockfd, int cmd, unsigned long arg) +{ + FAR struct socket *psock = sockfd_socket(sockfd); + int ret; + + /* Check if this is a valid command. In all cases, arg is a pointer that has + * been cast to unsigned long. Verify that the value of the to-be-pointer is + * non-NULL. + */ + + if (!_SIOCVALID(cmd) || !arg) + { + ret = -EINVAL; + goto errout; + } + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + ret = -EBADF; + goto errout; + } + + /* Execute the command */ + + ret = netdev_ifrioctl(psock, cmd, (FAR struct ifreq*)arg); +#ifdef CONFIG_NET_IGMP + if (ret == -EINVAL) + { + ret = netdev_imsfioctl(psock, cmd, (FAR struct ip_msfilter*)arg); + } +#endif + + /* Check for success or failure */ + + if (ret >= 0) + { + return ret; + } + +/* On failure, set the errno and return -1 */ + +errout: + errno = -ret; + return ERROR; +} + +#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/net/netdev_register.c b/nuttx/net/netdev_register.c new file mode 100644 index 0000000000..31cf884e49 --- /dev/null +++ b/nuttx/net/netdev_register.c @@ -0,0 +1,149 @@ +/**************************************************************************** + * net/netdev_register.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#ifdef CONFIG_NET_SLIP +# define NETDEV_FORMAT "sl%d" +#else +# define NETDEV_FORMAT "eth%d" +#endif + +/**************************************************************************** + * Priviate Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static int g_next_devnum = 0; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* List of registered ethernet device drivers */ + +struct uip_driver_s *g_netdevices = NULL; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: netdev_register + * + * Description: + * Register a network device driver and assign a name to it so tht it can + * be found in subsequent network ioctl operations on the device. + * + * Parameters: + * dev - The device driver structure to register + * + * Returned Value: + * 0:Success; negated errno on failure + * + * Assumptions: + * Called during system initialization from normal user mode + * + ****************************************************************************/ + +int netdev_register(FAR struct uip_driver_s *dev) +{ + if (dev) + { + int devnum; + netdev_semtake(); + + /* Assign a device name to the interface */ + + devnum = g_next_devnum++; + snprintf(dev->d_ifname, IFNAMSIZ, NETDEV_FORMAT, devnum ); + + /* Add the device to the list of known network devices */ + + dev->flink = g_netdevices; + g_netdevices = dev; + + /* Configure the device for IGMP support */ + +#ifdef CONFIG_NET_IGMP + uip_igmpdevinit(dev); +#endif + netdev_semgive(); + +#ifdef CONFIG_NET_ETHERNET + nlldbg("Registered MAC: %02x:%02x:%02x:%02x:%02x:%02x as dev: %s\n", + dev->d_mac.ether_addr_octet[0], dev->d_mac.ether_addr_octet[1], + dev->d_mac.ether_addr_octet[2], dev->d_mac.ether_addr_octet[3], + dev->d_mac.ether_addr_octet[4], dev->d_mac.ether_addr_octet[5], + dev->d_ifname); +#else + nlldbg("Registered dev: %s\n", dev->d_ifname); +#endif + return OK; + } + return -EINVAL; +} + +#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/net/netdev_sem.c b/nuttx/net/netdev_sem.c new file mode 100644 index 0000000000..ba6299c62d --- /dev/null +++ b/nuttx/net/netdev_sem.c @@ -0,0 +1,178 @@ +/**************************************************************************** + * net/netdev_sem.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +#include + +#include +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define NO_HOLDER (pid_t)-1 + +/**************************************************************************** + * Priviate Types + ****************************************************************************/ + +/* There is at least on context in which recursive semaphores are required: + * When netdev_foreach is used with a telnet client, we will deadlock if we + * do not provide this capability. + */ + +struct netdev_sem_s +{ + sem_t sem; + pid_t holder; + unsigned int count; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +static struct netdev_sem_s g_devlock; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: netdev_seminit + * + * Description: + * Initialize the network device semaphore. + * + ****************************************************************************/ + +void netdev_seminit(void) +{ + sem_init(&g_devlock.sem, 0, 1); + g_devlock.holder = NO_HOLDER; + g_devlock.count = 0; +} + +/**************************************************************************** + * Function: netdev_semtake + * + * Description: + * Get exclusive access to the network device list. + * + ****************************************************************************/ + +void netdev_semtake(void) +{ + pid_t me = getpid(); + + /* Does this thread already hold the semaphore? */ + + if (g_devlock.holder == me) + { + /* Yes.. just increment the reference count */ + + g_devlock.count++; + } + else + { + /* No.. take the semaphore (perhaps waiting) */ + + while (uip_lockedwait(&g_devlock.sem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(errno == EINTR); + } + + /* Now this thread holds the semaphore */ + + g_devlock.holder = me; + g_devlock.count = 1; + } +} + +/**************************************************************************** + * Function: netdev_semtake + * + * Description: + * Release exclusive access to the network device list + * + ****************************************************************************/ + +void netdev_semgive(void) +{ + DEBUGASSERT(g_devlock.holder == getpid() && g_devlock.count > 0); + + /* If the count would go to zero, then release the semaphore */ + + if (g_devlock.count == 1) + { + /* We no longer hold the semaphore */ + + g_devlock.holder = NO_HOLDER; + g_devlock.count = 0; + sem_post(&g_devlock.sem); + } + else + { + /* We still hold the semaphore. Just decrement the count */ + + g_devlock.count--; + } +} + +#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/net/netdev_txnotify.c b/nuttx/net/netdev_txnotify.c new file mode 100644 index 0000000000..4cb705ea85 --- /dev/null +++ b/nuttx/net/netdev_txnotify.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * net/netdev_txnotify.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +#include +#include +#include +#include + +#include + +#include "net_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Priviate Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: netdev_txnotify + * + * Description: + * Notify the device driver that new TX data is available. + * + * Parameters: + * raddr - Pointer to the remote address to send the data + * + * Returned Value: + * None + * + * Assumptions: + * Called from normal user mode + * + ****************************************************************************/ + +void netdev_txnotify(const uip_ipaddr_t *raddr) +{ + /* Find the device driver that serves the subnet of the remote address */ + + struct uip_driver_s *dev = netdev_findbyaddr(raddr); + if (dev && dev->d_txavail) + { + /* Notify the device driver that new TX data is available. */ + + (void)dev->d_txavail(dev); + } +} + +#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/net/netdev_unregister.c b/nuttx/net/netdev_unregister.c new file mode 100644 index 0000000000..e1aec0e4d8 --- /dev/null +++ b/nuttx/net/netdev_unregister.c @@ -0,0 +1,159 @@ +/**************************************************************************** + * net/netdev_unregister.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#ifdef CONFIG_NET_SLIP +# define NETDEV_FORMAT "sl%d" +#else +# define NETDEV_FORMAT "eth%d" +#endif + +/**************************************************************************** + * Priviate Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: netdev_unregister + * + * Description: + * Unregister a network device driver. + * + * Parameters: + * dev - The device driver structure to un-register + * + * Returned Value: + * 0:Success; negated errno on failure + * + * Assumptions: + * Currently only called for USB networking devices when the device is + * physically removed from the slot + * + ****************************************************************************/ + +int netdev_unregister(FAR struct uip_driver_s *dev) +{ + struct uip_driver_s *prev; + struct uip_driver_s *curr; + + if (dev) + { + netdev_semtake(); + + /* Find the device in the list of known network devices */ + + for (prev = NULL, curr = g_netdevices; + curr && curr != dev; + prev = curr, curr = curr->flink); + + /* Remove the device to the list of known network devices */ + + if (curr) + { + /* Where was the entry */ + + if (prev) + { + /* The entry was in the middle or at the end of the list */ + + prev->flink = curr->flink; + } + else + { + /* The entry was at the beginning of the list */ + + g_netdevices = curr; + } + + curr->flink = NULL; + } + + netdev_semgive(); + +#ifdef CONFIG_NET_ETHERNET + nlldbg("Unregistered MAC: %02x:%02x:%02x:%02x:%02x:%02x as dev: %s\n", + dev->d_mac.ether_addr_octet[0], dev->d_mac.ether_addr_octet[1], + dev->d_mac.ether_addr_octet[2], dev->d_mac.ether_addr_octet[3], + dev->d_mac.ether_addr_octet[4], dev->d_mac.ether_addr_octet[5], + dev->d_ifname); +#else + nlldbg("Registered dev: %s\n", dev->d_ifname); +#endif + return OK; + } + + return -EINVAL; +} + +#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/net/recv.c b/nuttx/net/recv.c new file mode 100644 index 0000000000..1571a73773 --- /dev/null +++ b/nuttx/net/recv.c @@ -0,0 +1,77 @@ +/**************************************************************************** + * net/recv.c + * + * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: recv + * + * Description: + * The recv() call is identical to recvfrom() with a NULL from parameter. + * + * Parameters: + * sockfd Socket descriptor of socket + * buf Buffer to receive data + * len Length of buffer + * flags Receive flags + * + * Returned Value: + * (see recvfrom) + * + * Assumptions: + * + ****************************************************************************/ + +ssize_t recv(int sockfd, FAR void *buf, size_t len, int flags) +{ + return recvfrom(sockfd, buf, len, flags, NULL, 0); +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c new file mode 100644 index 0000000000..741cd4c727 --- /dev/null +++ b/nuttx/net/recvfrom.c @@ -0,0 +1,1308 @@ +/**************************************************************************** + * net/recvfrom.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_NET + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "net_internal.h" +#include "uip/uip_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define TCP_TIMEO 10 /* Deciseconds after data received before recv() returns */ + +#define UDPBUF ((struct uip_udpip_hdr *)&dev->d_buf[UIP_LLH_LEN]) +#define TCPBUF ((struct uip_tcpip_hdr *)&dev->d_buf[UIP_LLH_LEN]) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) +struct recvfrom_s +{ + FAR struct socket *rf_sock; /* The parent socket structure */ +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) + uint32_t rf_starttime; /* rcv start time for determining timeout */ +#endif + FAR struct uip_callback_s *rf_cb; /* Reference to callback instance */ + sem_t rf_sem; /* Semaphore signals recv completion */ + size_t rf_buflen; /* Length of receive buffer */ + char *rf_buffer; /* Pointer to receive buffer */ +#ifdef CONFIG_NET_IPv6 + FAR struct sockaddr_in6 *rf_from; /* Address of sender */ +#else + FAR struct sockaddr_in *rf_from; /* Address of sender */ +#endif + size_t rf_recvlen; /* The received length */ + int rf_result; /* OK:success, failure:negated errno */ +}; +#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: recvfrom_newdata + * + * Description: + * Copy the read data from the packet + * + * Parameters: + * dev The sructure of the network driver that caused the interrupt + * pstate recvfrom state structure + * + * Returned Value: + * The number of bytes taken from the packet. + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) +static size_t recvfrom_newdata(FAR struct uip_driver_s *dev, + FAR struct recvfrom_s *pstate) +{ + size_t recvlen; + + /* Get the length of the data to return */ + + if (dev->d_len > pstate->rf_buflen) + { + recvlen = pstate->rf_buflen; + } + else + { + recvlen = dev->d_len; + } + + /* Copy the new appdata into the user buffer */ + + memcpy(pstate->rf_buffer, dev->d_appdata, recvlen); + nllvdbg("Received %d bytes (of %d)\n", (int)recvlen, (int)dev->d_len); + + /* Update the accumulated size of the data read */ + + pstate->rf_recvlen += recvlen; + pstate->rf_buffer += recvlen; + pstate->rf_buflen -= recvlen; + + return recvlen; +} +#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */ + +/**************************************************************************** + * Function: recvfrom_newtcpdata + * + * Description: + * Copy the read data from the packet + * + * Parameters: + * dev The sructure of the network driver that caused the interrupt + * pstate recvfrom state structure + * + * Returned Value: + * None. + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +static inline void recvfrom_newtcpdata(FAR struct uip_driver_s *dev, + FAR struct recvfrom_s *pstate) +{ + /* Take as much data from the packet as we can */ + + size_t recvlen = recvfrom_newdata(dev, pstate); + + /* If there is more data left in the packet that we could not buffer, than + * add it to the read-ahead buffers. + */ + + if (recvlen < dev->d_len) + { +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + FAR struct uip_conn *conn = (FAR struct uip_conn *)pstate->rf_sock->s_conn; + FAR uint8_t *buffer = (FAR uint8_t *)dev->d_appdata + recvlen; + uint16_t buflen = dev->d_len - recvlen; + uint16_t nsaved; + + nsaved = uip_datahandler(conn, buffer, buflen); + + /* There are complicated buffering issues that are not addressed fully + * here. For example, what if up_datahandler() cannot buffer the + * remainder of the packet? In that case, the data will be dropped but + * still ACKed. Therefore it would not be resent. + * + * This is probably not an issue here because we only get here if the + * read-ahead buffers are empty and there would have to be something + * serioulsy wrong with the configuration not to be able to buffer a + * partial packet in this context. + */ + +#ifdef CONFIG_DEBUG_NET + if (nsaved < buflen) + { + ndbg("ERROR: packet data not saved (%d bytes)\n", buflen - nsaved); + } +#endif +#else + ndbg("ERROR: packet data lost (%d bytes)\n", dev->d_len - recvlen); +#endif + } + + /* Indicate no data in the buffer */ + + dev->d_len = 0; +} +#endif /* CONFIG_NET_TCP */ + +/**************************************************************************** + * Function: recvfrom_newudpdata + * + * Description: + * Copy the read data from the packet + * + * Parameters: + * dev The sructure of the network driver that caused the interrupt + * pstate recvfrom state structure + * + * Returned Value: + * None. + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#ifdef CONFIG_NET_UDP +static inline void recvfrom_newudpdata(FAR struct uip_driver_s *dev, + FAR struct recvfrom_s *pstate) +{ + /* Take as much data from the packet as we can */ + + (void)recvfrom_newdata(dev, pstate); + + /* Indicate no data in the buffer */ + + dev->d_len = 0; +} +#endif /* CONFIG_NET_TCP */ + +/**************************************************************************** + * Function: recvfrom_readahead + * + * Description: + * Copy the read data from the packet + * + * Parameters: + * dev The sructure of the network driver that caused the interrupt + * pstate recvfrom state structure + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#if defined(CONFIG_NET_TCP) && CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 +static inline void recvfrom_readahead(struct recvfrom_s *pstate) +{ + FAR struct uip_conn *conn = (FAR struct uip_conn *)pstate->rf_sock->s_conn; + FAR struct uip_readahead_s *readahead; + size_t recvlen; + + /* Check there is any TCP data already buffered in a read-ahead + * buffer. + */ + + do + { + /* Get the read-ahead buffer at the head of the list (if any) */ + + readahead = (struct uip_readahead_s *)sq_remfirst(&conn->readahead); + if (readahead) + { + /* We have a new buffer... transfer that buffered data into + * the user buffer. + * + * First, get the length of the data to transfer. + */ + + if (readahead->rh_nbytes > pstate->rf_buflen) + { + recvlen = pstate->rf_buflen; + } + else + { + recvlen = readahead->rh_nbytes; + } + + if (recvlen > 0) + { + /* Copy the read-ahead data into the user buffer */ + + memcpy(pstate->rf_buffer, readahead->rh_buffer, recvlen); + nllvdbg("Received %d bytes (of %d)\n", recvlen, readahead->rh_nbytes); + + /* Update the accumulated size of the data read */ + + pstate->rf_recvlen += recvlen; + pstate->rf_buffer += recvlen; + pstate->rf_buflen -= recvlen; + } + + /* If the read-ahead buffer is empty, then release it. If not, then + * we will have to move the data down and return the buffer to the + * front of the list. + */ + + if (recvlen < readahead->rh_nbytes) + { + readahead->rh_nbytes -= recvlen; + memcpy(readahead->rh_buffer, &readahead->rh_buffer[recvlen], + readahead->rh_nbytes); + sq_addfirst(&readahead->rh_node, &conn->readahead); + } + else + { + uip_tcpreadaheadrelease(readahead); + } + } + } + while (readahead && pstate->rf_buflen > 0); +} +#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */ + +/**************************************************************************** + * Function: recvfrom_timeout + * + * Description: + * Check for recvfrom timeout. + * + * Parameters: + * pstate recvfrom state structure + * + * Returned Value: + * TRUE:timeout FALSE:no timeout + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) +static int recvfrom_timeout(struct recvfrom_s *pstate) +{ + FAR struct socket *psock = 0; + socktimeo_t timeo = 0; + + /* If this is a TCP socket that has already received some data, + * than we will always use a short timeout. + */ + + if (pstate->rf_recvlen > 0) + { + /* Use the short timeout */ + + timeo = TCP_TIMEO; + } + + /* No.. check for a timeout configured via setsockopts(SO_RCVTIMEO). + * If none... we well let the read hang forever. + */ + + else + { + /* Get the socket reference from the private data */ + + psock = pstate->rf_sock; + if (psock) + { + timeo = psock->s_rcvtimeo; + } + } + + /* Is there an effective timeout? */ + + if (timeo) + { + /* Yes.. Check if the timeout has elapsed */ + + return net_timeo(pstate->rf_starttime, timeo); + } + + /* No timeout */ + + return FALSE; +} +#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */ +#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */ + +/**************************************************************************** + * Function: recvfrom_tcpsender + * + * Description: + * Getting the sender's address from the UDP packet + * + * Parameters: + * dev - The device driver data structure + * pstate - the recvfrom state structure + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +static inline void recvfrom_tcpsender(struct uip_driver_s *dev, struct recvfrom_s *pstate) +{ +#ifdef CONFIG_NET_IPv6 + FAR struct sockaddr_in6 *infrom = pstate->rf_from; +#else + FAR struct sockaddr_in *infrom = pstate->rf_from; +#endif + + if (infrom) + { + infrom->sin_family = AF_INET; + infrom->sin_port = TCPBUF->srcport; + +#ifdef CONFIG_NET_IPv6 + uip_ipaddr_copy(infrom->sin6_addr.s6_addr, TCPBUF->srcipaddr); +#else + uip_ipaddr_copy(infrom->sin_addr.s_addr, uip_ip4addr_conv(TCPBUF->srcipaddr)); +#endif + } +} +#endif + +/**************************************************************************** + * Function: recvfrom_tcpinterrupt + * + * Description: + * This function is called from the interrupt level to perform the actual + * TCP receive operation via by the uIP layer. + * + * Parameters: + * dev The structure of the network driver that caused the interrupt + * conn The connection structure associated with the socket + * flags Set of events describing why the callback was invoked + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn, + void *pvpriv, uint16_t flags) +{ + struct recvfrom_s *pstate = (struct recvfrom_s *)pvpriv; + + nllvdbg("flags: %04x\n", flags); + + /* 'priv' might be null in some race conditions (?) */ + + if (pstate) + { + /* If new data is available, then complete the read action. */ + + if ((flags & UIP_NEWDATA) != 0) + { + /* Copy the data from the packet (saving any unused bytes from the + * packet in the read-ahead buffer). + */ + + recvfrom_newtcpdata(dev, pstate); + + /* Save the sender's address in the caller's 'from' location */ + + recvfrom_tcpsender(dev, pstate); + + /* Indicate that the data has been consumed and that an ACK + * should be sent. + */ + + flags = (flags & ~UIP_NEWDATA) | UIP_SNDACK; + + /* If the user buffer has been filled, then we are finished. */ + + if (pstate->rf_buflen == 0) + { + nllvdbg("TCP resume\n"); + + /* The TCP receive buffer is full. Return now and don't allow + * any further TCP call backs. + */ + + pstate->rf_cb->flags = 0; + pstate->rf_cb->priv = NULL; + pstate->rf_cb->event = NULL; + + /* Wake up the waiting thread, returning the number of bytes + * actually read. + */ + + sem_post(&pstate->rf_sem); + } + + /* Reset the timeout. We will want a short timeout to terminate + * the TCP receive. + */ + +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) + pstate->rf_starttime = clock_systimer(); +#endif + } + + /* Check for a loss of connection. + * + * UIP_CLOSE: The remote host has closed the connection + * UIP_ABORT: The remote host has aborted the connection + * UIP_TIMEDOUT: Connection aborted due to too many retransmissions. + */ + + else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) + { + nllvdbg("error\n"); + + /* Stop further callbacks */ + + pstate->rf_cb->flags = 0; + pstate->rf_cb->priv = NULL; + pstate->rf_cb->event = NULL; + + /* If the peer gracefully closed the connection, then return zero + * (end-of-file). Otherwise, report a not-connected error + */ + + if ((flags & UIP_CLOSE) != 0) + { + pstate->rf_result = 0; + } + else + { + pstate->rf_result = -ENOTCONN; + } + + /* Wake up the waiting thread */ + + sem_post(&pstate->rf_sem); + } + + /* No data has been received -- this is some other event... probably a + * poll -- check for a timeout. + */ + +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) + else if (recvfrom_timeout(pstate)) + { + /* Yes.. the timeout has elapsed... do not allow any further + * callbacks + */ + + nllvdbg("TCP timeout\n"); + + pstate->rf_cb->flags = 0; + pstate->rf_cb->priv = NULL; + pstate->rf_cb->event = NULL; + + /* Report an error only if no data has been received */ + + if (pstate->rf_recvlen == 0) + { + /* Report the timeout error */ + + pstate->rf_result = -EAGAIN; + } + + /* Wake up the waiting thread, returning either the error -EAGAIN + * that signals the timeout event or the data received up to + * the point tht the timeout occured (no error). + */ + + sem_post(&pstate->rf_sem); + } +#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */ + } + return flags; +} +#endif /* CONFIG_NET_TCP */ + +/**************************************************************************** + * Function: recvfrom_udpsender + * + * Description: + * Getting the sender's address from the UDP packet + * + * Parameters: + * dev - The device driver data structure + * pstate - the recvfrom state structure + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#ifdef CONFIG_NET_UDP +static inline void recvfrom_udpsender(struct uip_driver_s *dev, struct recvfrom_s *pstate) +{ +#ifdef CONFIG_NET_IPv6 + FAR struct sockaddr_in6 *infrom = pstate->rf_from; +#else + FAR struct sockaddr_in *infrom = pstate->rf_from; +#endif + + if (infrom) + { + infrom->sin_family = AF_INET; + infrom->sin_port = UDPBUF->srcport; + +#ifdef CONFIG_NET_IPv6 + uip_ipaddr_copy(infrom->sin6_addr.s6_addr, UDPBUF->srcipaddr); +#else + uip_ipaddr_copy(infrom->sin_addr.s_addr, uip_ip4addr_conv(UDPBUF->srcipaddr)); +#endif + } +} +#endif + +/**************************************************************************** + * Function: recvfrom_udpinterrupt + * + * Description: + * This function is called from the interrupt level to perform the actual + * UDP receive operation via by the uIP layer. + * + * Parameters: + * dev The sructure of the network driver that caused the interrupt + * conn The connection structure associated with the socket + * flags Set of events describing why the callback was invoked + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#ifdef CONFIG_NET_UDP +static uint16_t recvfrom_udpinterrupt(struct uip_driver_s *dev, void *pvconn, + void *pvpriv, uint16_t flags) +{ + struct recvfrom_s *pstate = (struct recvfrom_s *)pvpriv; + + nllvdbg("flags: %04x\n", flags); + + /* 'priv' might be null in some race conditions (?) */ + + if (pstate) + { + /* If new data is available, then complete the read action. */ + + if ((flags & UIP_NEWDATA) != 0) + { + /* Copy the data from the packet */ + + recvfrom_newudpdata(dev, pstate); + + /* We are finished. */ + + nllvdbg("UDP done\n"); + + /* Don't allow any further UDP call backs. */ + + pstate->rf_cb->flags = 0; + pstate->rf_cb->priv = NULL; + pstate->rf_cb->event = NULL; + + /* Save the sender's address in the caller's 'from' location */ + + recvfrom_udpsender(dev, pstate); + + /* Indicate that the data has been consumed */ + + flags &= ~UIP_NEWDATA; + + /* Wake up the waiting thread, returning the number of bytes + * actually read. + */ + + sem_post(&pstate->rf_sem); + } + + /* No data has been received -- this is some other event... probably a + * poll -- check for a timeout. + */ + +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) + else if (recvfrom_timeout(pstate)) + { + /* Yes.. the timeout has elapsed... do not allow any further + * callbacks + */ + + nllvdbg("UDP timeout\n"); + + /* Stop further callbacks */ + + pstate->rf_cb->flags = 0; + pstate->rf_cb->priv = NULL; + pstate->rf_cb->event = NULL; + + /* Report a timeout error */ + + pstate->rf_result = -EAGAIN; + + /* Wake up the waiting thread */ + + sem_post(&pstate->rf_sem); + } +#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */ + } + return flags; +} +#endif /* CONFIG_NET_UDP */ + +/**************************************************************************** + * Function: recvfrom_init + * + * Description: + * Initialize the state structure + * + * Parameters: + * psock Pointer to the socket structure for the socket + * buf Buffer to receive data + * len Length of buffer + * pstate A pointer to the state structure to be initialized + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) +static void recvfrom_init(FAR struct socket *psock, FAR void *buf, size_t len, +#ifdef CONFIG_NET_IPv6 + FAR struct sockaddr_in6 *infrom, +#else + FAR struct sockaddr_in *infrom, +#endif + struct recvfrom_s *pstate) +{ + /* Initialize the state structure. */ + + memset(pstate, 0, sizeof(struct recvfrom_s)); + (void)sem_init(&pstate->rf_sem, 0, 0); /* Doesn't really fail */ + pstate->rf_buflen = len; + pstate->rf_buffer = buf; + pstate->rf_from = infrom; + + /* Set up the start time for the timeout */ + + pstate->rf_sock = psock; +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) + pstate->rf_starttime = clock_systimer(); +#endif +} + +/* The only uninitialization that has to be performed is destroying the + * semaphore. + */ + +#define recvfrom_uninit(s) sem_destroy(&(s)->rf_sem) + +#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */ + +/**************************************************************************** + * Function: recvfrom_result + * + * Description: + * Evaluate the result of the recv operations + * + * Parameters: + * result The result of the uip_lockedwait operation (may indicate EINTR) + * pstate A pointer to the state structure to be initialized + * + * Returned Value: + * The result of the recv operation with errno set appropriately + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) +static ssize_t recvfrom_result(int result, struct recvfrom_s *pstate) +{ + int save_errno = errno; /* In case something we do changes it */ + + /* Check for a error/timeout detected by the interrupt handler. Errors are + * signaled by negative errno values for the rcv length + */ + + if (pstate->rf_result < 0) + { + /* This might return EGAIN on a timeout or ENOTCONN on loss of + * connection (TCP only) + */ + + return pstate->rf_result; + } + + /* If uip_lockedwait failed, then we were probably reawakened by a signal. In + * this case, uip_lockedwait will have set errno appropriately. + */ + + if (result < 0) + { + return -save_errno; + } + + return pstate->rf_recvlen; +} +#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */ + +/**************************************************************************** + * Function: udp_recvfrom + * + * Description: + * Perform the recvfrom operation for a UDP SOCK_DGRAM + * + * Parameters: + * psock Pointer to the socket structure for the SOCK_DRAM socket + * buf Buffer to receive data + * len Length of buffer + * infrom INET ddress of source (may be NULL) + * + * Returned Value: + * On success, returns the number of characters sent. On error, + * -errno is returned (see recvfrom for list of errnos). + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_UDP +#ifdef CONFIG_NET_IPv6 +static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, + FAR struct sockaddr_in6 *infrom ) +#else +static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, + FAR struct sockaddr_in *infrom ) +#endif +{ + struct uip_udp_conn *conn = (struct uip_udp_conn *)psock->s_conn; + struct recvfrom_s state; + uip_lock_t save; + int ret; + + /* Perform the UDP recvfrom() operation */ + + /* Initialize the state structure. This is done with interrupts + * disabled because we don't want anything to happen until we + * are ready. + */ + + save = uip_lock(); + recvfrom_init(psock, buf, len, infrom, &state); + + /* Setup the UDP remote connection */ + + ret = uip_udpconnect(conn, NULL); + if (ret < 0) + { + goto errout_with_state; + } + + /* Set up the callback in the connection */ + + state.rf_cb = uip_udpcallbackalloc(conn); + if (state.rf_cb) + { + /* Set up the callback in the connection */ + + state.rf_cb->flags = UIP_NEWDATA|UIP_POLL; + state.rf_cb->priv = (void*)&state; + state.rf_cb->event = recvfrom_udpinterrupt; + + /* Enable the UDP socket */ + + uip_udpenable(conn); + + /* Wait for either the receive to complete or for an error/timeout to occur. + * NOTES: (1) uip_lockedwait will also terminate if a signal is received, (2) + * interrupts are disabled! They will be re-enabled while the task sleeps + * and automatically re-enabled when the task restarts. + */ + + ret = uip_lockedwait(&state. rf_sem); + + /* Make sure that no further interrupts are processed */ + + uip_udpdisable(conn); + uip_udpcallbackfree(conn, state.rf_cb); + ret = recvfrom_result(ret, &state); + } + else + { + ret = -EBUSY; + } + +errout_with_state: + uip_unlock(save); + recvfrom_uninit(&state); + return ret; +} +#endif /* CONFIG_NET_UDP */ + +/**************************************************************************** + * Function: tcp_recvfrom + * + * Description: + * Perform the recvfrom operation for a TCP/IP SOCK_STREAM + * + * Parameters: + * psock Pointer to the socket structure for the SOCK_DRAM socket + * buf Buffer to receive data + * len Length of buffer + * infrom INET ddress of source (may be NULL) + * + * Returned Value: + * On success, returns the number of characters sent. On error, + * -errno is returned (see recvfrom for list of errnos). + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +#ifdef CONFIG_NET_IPv6 +static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, + FAR struct sockaddr_in6 *infrom ) +#else +static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, + FAR struct sockaddr_in *infrom ) +#endif +{ + struct recvfrom_s state; + uip_lock_t save; + int ret; + + /* Initialize the state structure. This is done with interrupts + * disabled because we don't want anything to happen until we + * are ready. + */ + + save = uip_lock(); + recvfrom_init(psock, buf, len, infrom, &state); + + /* Handle any any TCP data already buffered in a read-ahead buffer. NOTE + * that there may be read-ahead data to be retrieved even after the + * socket has been disconnected. + */ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + recvfrom_readahead(&state); + + /* The default return value is the number of bytes that we just copied into + * the user buffer. We will return this if the socket has become disconnected + * or if the user request was completely satisfied with data from the readahead + * buffers. + */ + + ret = state.rf_recvlen; + +#else + /* Otherwise, the default return value of zero is used (only for the case + * where len == state.rf_buflen is zero). + */ + + ret = 0; +#endif + + /* Verify that the SOCK_STREAM has been and still is connected */ + + if (!_SS_ISCONNECTED(psock->s_flags)) + { + /* Was any data transferred from the readahead buffer after we were + * disconnected? If so, then return the number of bytes received. We + * will wait to return end disconnection indications the next time that + * recvfrom() is called. + * + * If no data was received (i.e., ret == 0 -- it will not be negative) + * and the connection was gracefully closed by the remote peer, then return + * success. If rf_recvlen is zero, the caller of recvfrom() will get an + * end-of-file indication. + */ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + if (ret <= 0 && !_SS_ISCLOSED(psock->s_flags)) +#else + if (!_SS_ISCLOSED(psock->s_flags)) +#endif + { + /* Nothing was previously received from the readahead buffers. + * The SOCK_STREAM must be (re-)connected in order to receive any + * additional data. + */ + + ret = -ENOTCONN; + } + } + + /* In general, this uIP-based implementation will not support non-blocking + * socket operations... except in a few cases: Here for TCP receive with read-ahead + * enabled. If this socket is configured as non-blocking then return EAGAIN + * if no data was obtained from the read-ahead buffers. + */ + + else +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + if (_SS_ISNONBLOCK(psock->s_flags)) + { + /* Return the number of bytes read from the read-ahead buffer if + * something was received (already in 'ret'); EGAIN if not. + */ + + if (ret <= 0) + { + /* Nothing was received */ + + ret = -EAGAIN; + } + } + + /* It is okay to block if we need to. If there is space to receive anything + * more, then we will wait to receive the data. Otherwise return the number + * of bytes read from the read-ahead buffer (already in 'ret'). + */ + + else +#endif + if (state.rf_buflen > 0) + { + struct uip_conn *conn = (struct uip_conn *)psock->s_conn; + + /* Set up the callback in the connection */ + + state.rf_cb = uip_tcpcallbackalloc(conn); + if (state.rf_cb) + { + state.rf_cb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT; + state.rf_cb->priv = (void*)&state; + state.rf_cb->event = recvfrom_tcpinterrupt; + + /* Wait for either the receive to complete or for an error/timeout to occur. + * NOTES: (1) uip_lockedwait will also terminate if a signal is received, (2) + * interrupts may be disabled! They will be re-enabled while the task sleeps + * and automatically re-enabled when the task restarts. + */ + + ret = uip_lockedwait(&state.rf_sem); + + /* Make sure that no further interrupts are processed */ + + uip_tcpcallbackfree(conn, state.rf_cb); + ret = recvfrom_result(ret, &state); + } + else + { + ret = -EBUSY; + } + } + + uip_unlock(save); + recvfrom_uninit(&state); + return (ssize_t)ret; +} +#endif /* CONFIG_NET_TCP */ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: psock_recvfrom + * + * Description: + * recvfrom() receives messages from a socket, and may be used to receive + * data on a socket whether or not it is connection-oriented. + * + * If from is not NULL, and the underlying protocol provides the source + * address, this source address is filled in. The argument fromlen + * initialized to the size of the buffer associated with from, and modified + * on return to indicate the actual size of the address stored there. + * + * Parameters: + * psock A pointer to a NuttX-specific, internal socket structure + * buf Buffer to receive data + * len Length of buffer + * flags Receive flags + * from Address of source (may be NULL) + * fromlen The length of the address structure + * + * Returned Value: + * On success, returns the number of characters sent. If no data is + * available to be received and the peer has performed an orderly shutdown, + * recv() will return 0. Othwerwise, on errors, -1 is returned, and errno + * is set appropriately: + * + * EAGAIN + * The socket is marked non-blocking and the receive operation would block, + * or a receive timeout had been set and the timeout expired before data + * was received. + * EBADF + * The argument sockfd is an invalid descriptor. + * ECONNREFUSED + * A remote host refused to allow the network connection (typically because + * it is not running the requested service). + * EFAULT + * The receive buffer pointer(s) point outside the process's address space. + * EINTR + * The receive was interrupted by delivery of a signal before any data were + * available. + * EINVAL + * Invalid argument passed. + * ENOMEM + * Could not allocate memory. + * ENOTCONN + * The socket is associated with a connection-oriented protocol and has + * not been connected. + * ENOTSOCK + * The argument sockfd does not refer to a socket. + * + * Assumptions: + * + ****************************************************************************/ + +ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, + int flags,FAR struct sockaddr *from, + FAR socklen_t *fromlen) +{ +#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) +#ifdef CONFIG_NET_IPv6 + FAR struct sockaddr_in6 *infrom = (struct sockaddr_in6 *)from; +#else + FAR struct sockaddr_in *infrom = (struct sockaddr_in *)from; +#endif +#endif + + ssize_t ret; + int err; + + /* Verify that non-NULL pointers were passed */ + +#ifdef CONFIG_DEBUG + if (!buf) + { + err = EINVAL; + goto errout; + } +#endif + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + err = EBADF; + goto errout; + } + + /* If a 'from' address has been provided, verify that it is large + * enough to hold this address family. + */ + + if (from) + { +#ifdef CONFIG_NET_IPv6 + if (*fromlen < sizeof(struct sockaddr_in6)) +#else + if (*fromlen < sizeof(struct sockaddr_in)) +#endif + { + err = EINVAL; + goto errout; + } + } + + /* Set the socket state to receiving */ + + psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_RECV); + + /* Perform the TCP/IP or UDP recv() operation */ + +#if defined(CONFIG_NET_UDP) && defined(CONFIG_NET_TCP) + if (psock->s_type == SOCK_STREAM) + { + ret = tcp_recvfrom(psock, buf, len, infrom); + } + else + { + ret = udp_recvfrom(psock, buf, len, infrom); + } +#elif defined(CONFIG_NET_TCP) + ret = tcp_recvfrom(psock, buf, len, infrom); +#elif defined(CONFIG_NET_UDP) + ret = udp_recvfrom(psock, buf, len, infrom); +#else + ret = -ENOSYS; +#endif + + /* Set the socket state to idle */ + + psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); + + /* Handle returned errors */ + + if (ret < 0) + { + err = -ret; + goto errout; + } + + /* Success return */ + + return ret; + +errout: + errno = err; + return ERROR; +} + +/**************************************************************************** + * Function: recvfrom + * + * Description: + * recvfrom() receives messages from a socket, and may be used to receive + * data on a socket whether or not it is connection-oriented. + * + * If from is not NULL, and the underlying protocol provides the source + * address, this source address is filled in. The argument fromlen + * initialized to the size of the buffer associated with from, and modified + * on return to indicate the actual size of the address stored there. + * + * Parameters: + * sockfd Socket descriptor of socket + * buf Buffer to receive data + * len Length of buffer + * flags Receive flags + * from Address of source (may be NULL) + * fromlen The length of the address structure + * + * Returned Value: + * On success, returns the number of characters sent. On error, + * -1 is returned, and errno is set appropriately: + * + * EAGAIN + * The socket is marked non-blocking and the receive operation would block, + * or a receive timeout had been set and the timeout expired before data + * was received. + * EBADF + * The argument sockfd is an invalid descriptor. + * ECONNREFUSED + * A remote host refused to allow the network connection (typically because + * it is not running the requested service). + * EFAULT + * The receive buffer pointer(s) point outside the process's address space. + * EINTR + * The receive was interrupted by delivery of a signal before any data were + * available. + * EINVAL + * Invalid argument passed. + * ENOMEM + * Could not allocate memory. + * ENOTCONN + * The socket is associated with a connection-oriented protocol and has + * not been connected. + * ENOTSOCK + * The argument sockfd does not refer to a socket. + * + * Assumptions: + * + ****************************************************************************/ + +ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags, + FAR struct sockaddr *from, FAR socklen_t *fromlen) +{ + FAR struct socket *psock; + + /* Get the underlying socket structure */ + + psock = sockfd_socket(sockfd); + + /* Then let psock_recvfrom() do all of the work */ + + return psock_recvfrom(psock, buf, len, flags, from, fromlen); +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/send.c b/nuttx/net/send.c new file mode 100644 index 0000000000..950b3fc0bc --- /dev/null +++ b/nuttx/net/send.c @@ -0,0 +1,596 @@ +/**************************************************************************** + * net/send.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_NET_ARP_IPIN +# include +#endif + +#include "net_internal.h" +#include "uip/uip_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define TCPBUF ((struct uip_tcpip_hdr *)&dev->d_buf[UIP_LLH_LEN]) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure holds the state of the send operation until it can be + * operated upon from the interrupt level. + */ + +struct send_s +{ + FAR struct socket *snd_sock; /* Points to the parent socket structure */ + FAR struct uip_callback_s *snd_cb; /* Reference to callback instance */ + sem_t snd_sem; /* Used to wake up the waiting thread */ + FAR const uint8_t *snd_buffer; /* Points to the buffer of data to send */ + size_t snd_buflen; /* Number of bytes in the buffer to send */ + ssize_t snd_sent; /* The number of bytes sent */ + uint32_t snd_isn; /* Initial sequence number */ + uint32_t snd_acked; /* The number of bytes acked */ +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) + uint32_t snd_time; /* last send time for determining timeout */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: send_timeout + * + * Description: + * Check for send timeout. + * + * Parameters: + * pstate send state structure + * + * Returned Value: + * TRUE:timeout FALSE:no timeout + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) +static inline int send_timeout(struct send_s *pstate) +{ + FAR struct socket *psock = 0; + + /* Check for a timeout configured via setsockopts(SO_SNDTIMEO). + * If none... we well let the send wait forever. + */ + + psock = pstate->snd_sock; + if (psock && psock->s_sndtimeo != 0) + { + /* Check if the configured timeout has elapsed */ + + return net_timeo(pstate->snd_time, psock->s_sndtimeo); + } + + /* No timeout */ + + return FALSE; +} +#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */ + +/**************************************************************************** + * Function: send_interrupt + * + * Description: + * This function is called from the interrupt level to perform the actual + * send operation when polled by the uIP layer. + * + * Parameters: + * dev The sructure of the network driver that caused the interrupt + * conn The connection structure associated with the socket + * flags Set of events describing why the callback was invoked + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +static uint16_t send_interrupt(struct uip_driver_s *dev, void *pvconn, + void *pvpriv, uint16_t flags) +{ + struct uip_conn *conn = (struct uip_conn*)pvconn; + struct send_s *pstate = (struct send_s *)pvpriv; + + nllvdbg("flags: %04x acked: %d sent: %d\n", + flags, pstate->snd_acked, pstate->snd_sent); + + /* If this packet contains an acknowledgement, then update the count of + * acknowldged bytes. + */ + + if ((flags & UIP_ACKDATA) != 0) + { + /* The current acknowledgement number number is the (relative) offset + * of the of the next byte needed by the receiver. The snd_isn is the + * offset of the first byte to send to the receiver. The difference + * is the number of bytes to be acknowledged. + */ + + pstate->snd_acked = uip_tcpgetsequence(TCPBUF->ackno) - pstate->snd_isn; + nllvdbg("ACK: acked=%d sent=%d buflen=%d\n", + pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen); + + /* Have all of the bytes in the buffer been sent and acknowledged? */ + + if (pstate->snd_acked >= pstate->snd_buflen) + { + /* Yes. Then pstate->snd_buflen should hold the number of bytes + * actually sent. + */ + + goto end_wait; + } + + /* No.. fall through to send more data if necessary */ + } + + /* Check if we are being asked to retransmit data */ + + else if ((flags & UIP_REXMIT) != 0) + { + /* Yes.. in this case, reset the number of bytes that have been sent + * to the number of bytes that have been ACKed. + */ + + pstate->snd_sent = pstate->snd_acked; + + /* Fall through to re-send data from the last that was ACKed */ + } + + /* Check for a loss of connection */ + + else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) + { + /* Report not connected */ + + nllvdbg("Lost connection\n"); + pstate->snd_sent = -ENOTCONN; + goto end_wait; + } + + /* Check if the outgoing packet is available (it may have been claimed + * by a sendto interrupt serving a different thread). + */ + +#if 0 /* We can't really support multiple senders on the same TCP socket */ + else if (dev->d_sndlen > 0) + { + /* Another thread has beat us sending data, wait for the next poll */ + + return flags; + } +#endif + + /* We get here if (1) not all of the data has been ACKed, (2) we have been + * asked to retransmit data, (3) the connection is still healthy, and (4) + * the outgoing packet is available for our use. In this case, we are + * now free to send more data to receiver -- UNLESS the buffer contains + * unprocessing incoming data. In that event, we will have to wait for the + * next polling cycle. + */ + + if ((flags & UIP_NEWDATA) == 0 && pstate->snd_sent < pstate->snd_buflen) + { + uint32_t seqno; + + /* Get the amount of data that we can send in the next packet */ + + uint32_t sndlen = pstate->snd_buflen - pstate->snd_sent; + if (sndlen > uip_mss(conn)) + { + sndlen = uip_mss(conn); + } + + /* Set the sequence number for this packet. NOTE: uIP updates + * sndseq on recept of ACK *before* this function is called. In that + * case sndseq will point to the next unacknowledge byte (which might + * have already been sent). We will overwrite the value of sndseq + * here before the packet is sent. + */ + + seqno = pstate->snd_sent + pstate->snd_isn; + nllvdbg("SEND: sndseq %08x->%08x\n", conn->sndseq, seqno); + uip_tcpsetsequence(conn->sndseq, seqno); + + /* Then set-up to send that amount of data. (this won't actually + * happen until the polling cycle completes). + */ + + uip_send(dev, &pstate->snd_buffer[pstate->snd_sent], sndlen); + + /* Check if the destination IP address is in the ARP table. If not, + * then the send won't actually make it out... it will be replaced with + * an ARP request. + * + * NOTE 1: This could an expensive check if there are a lot of entries + * in the ARP table. Hence, we only check on the first packet -- when + * snd_sent is zero. + * + * NOTE 2: If we are actually harvesting IP addresses on incomming IP + * packets, then this check should not be necessary; the MAC mapping + * should already be in the ARP table. + */ + +#if defined(CONFIG_NET_ETHERNET) && defined (CONFIG_NET_ARP_IPIN) + if (pstate->snd_sent != 0 || uip_arp_find(conn->ripaddr) != NULL) +#endif + { + /* Update the amount of data sent (but not necessarily ACKed) */ + + pstate->snd_sent += sndlen; + nllvdbg("SEND: acked=%d sent=%d buflen=%d\n", + pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen); + + /* Update the send time */ + +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) + pstate->snd_time = clock_systimer(); +#endif + } + } + + /* All data has been send and we are just waiting for ACK or re-transmit + * indications to complete the send. Check for a timeout. + */ + +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) + else if (send_timeout(pstate)) + { + /* Yes.. report the timeout */ + + nlldbg("SEND timeout\n"); + pstate->snd_sent = -ETIMEDOUT; + goto end_wait; + } +#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */ + + /* Continue waiting */ + + return flags; + +end_wait: + /* Do not allow any further callbacks */ + + pstate->snd_cb->flags = 0; + pstate->snd_cb->priv = NULL; + pstate->snd_cb->event = NULL; + + /* There are no outstanding, unacknowledged bytes */ + + conn->unacked = 0; + + /* Wake up the waiting thread */ + + sem_post(&pstate->snd_sem); + return flags; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: psock_send + * + * Description: + * The send() call may be used only when the socket is in a connected state + * (so that the intended recipient is known). The only difference between + * send() and write() is the presence of flags. With zero flags parameter, + * send() is equivalent to write(). Also, send(sockfd,buf,len,flags) is + * equivalent to sendto(sockfd,buf,len,flags,NULL,0). + * + * Parameters: + * psock And instance of the internal socket structure. + * buf Data to send + * len Length of data to send + * flags Send flags + * + * Returned Value: + * On success, returns the number of characters sent. On error, + * -1 is returned, and errno is set appropriately: + * + * EAGAIN or EWOULDBLOCK + * The socket is marked non-blocking and the requested operation + * would block. + * EBADF + * An invalid descriptor was specified. + * ECONNRESET + * Connection reset by peer. + * EDESTADDRREQ + * The socket is not connection-mode, and no peer address is set. + * EFAULT + * An invalid user space address was specified for a parameter. + * EINTR + * A signal occurred before any data was transmitted. + * EINVAL + * Invalid argument passed. + * EISCONN + * The connection-mode socket was connected already but a recipient + * was specified. (Now either this error is returned, or the recipient + * specification is ignored.) + * EMSGSIZE + * The socket type requires that message be sent atomically, and the + * size of the message to be sent made this impossible. + * ENOBUFS + * The output queue for a network interface was full. This generally + * indicates that the interface has stopped sending, but may be + * caused by transient congestion. + * ENOMEM + * No memory available. + * ENOTCONN + * The socket is not connected, and no target has been given. + * ENOTSOCK + * The argument s is not a socket. + * EOPNOTSUPP + * Some bit in the flags argument is inappropriate for the socket + * type. + * EPIPE + * The local end has been shut down on a connection oriented socket. + * In this case the process will also receive a SIGPIPE unless + * MSG_NOSIGNAL is set. + * + * Assumptions: + * + ****************************************************************************/ + +ssize_t psock_send(FAR struct socket *psock, const void *buf, size_t len, int flags) +{ + struct send_s state; + uip_lock_t save; + int err; + int ret = OK; + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + err = EBADF; + goto errout; + } + + /* If this is an un-connected socket, then return ENOTCONN */ + + if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags)) + { + err = ENOTCONN; + goto errout; + } + + /* Set the socket state to sending */ + + psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); + + /* Perform the TCP send operation */ + + /* Initialize the state structure. This is done with interrupts + * disabled because we don't want anything to happen until we + * are ready. + */ + + save = uip_lock(); + memset(&state, 0, sizeof(struct send_s)); + (void)sem_init(&state. snd_sem, 0, 0); /* Doesn't really fail */ + state.snd_sock = psock; /* Socket descriptor to use */ + state.snd_buflen = len; /* Number of bytes to send */ + state.snd_buffer = buf; /* Buffer to send from */ + + if (len > 0) + { + struct uip_conn *conn = (struct uip_conn*)psock->s_conn; + + /* Allocate resources to receive a callback */ + + state.snd_cb = uip_tcpcallbackalloc(conn); + if (state.snd_cb) + { + /* Get the initial sequence number that will be used */ + + state.snd_isn = uip_tcpgetsequence(conn->sndseq); + + /* There is no outstanding, unacknowledged data after this + * initial sequence number. + */ + + conn->unacked = 0; + + /* Update the initial time for calculating timeouts */ + +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) + state.snd_time = clock_systimer(); +#endif + /* Set up the callback in the connection */ + + state.snd_cb->flags = UIP_ACKDATA|UIP_REXMIT|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT; + state.snd_cb->priv = (void*)&state; + state.snd_cb->event = send_interrupt; + + /* Notify the device driver of the availaibilty of TX data */ + + netdev_txnotify(&conn->ripaddr); + + /* Wait for the send to complete or an error to occur: NOTES: (1) + * uip_lockedwait will also terminate if a signal is received, (2) interrupts + * may be disabled! They will be re-enabled while the task sleeps and + * automatically re-enabled when the task restarts. + */ + + ret = uip_lockedwait(&state. snd_sem); + + /* Make sure that no further interrupts are processed */ + + uip_tcpcallbackfree(conn, state.snd_cb); + } + } + + sem_destroy(&state. snd_sem); + uip_unlock(save); + + /* Set the socket state to idle */ + + psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); + + /* Check for a errors. Errors are signaled by negative errno values + * for the send length + */ + + if (state.snd_sent < 0) + { + err = state.snd_sent; + goto errout; + } + + /* If uip_lockedwait failed, then we were probably reawakened by a signal. In + * this case, uip_lockedwait will have set errno appropriately. + */ + + if (ret < 0) + { + err = -ret; + goto errout; + } + + /* Return the number of bytes actually sent */ + + return state.snd_sent; + +errout: + *get_errno_ptr() = err; + return ERROR; +} + +/**************************************************************************** + * Function: send + * + * Description: + * The send() call may be used only when the socket is in a connected state + * (so that the intended recipient is known). The only difference between + * send() and write() is the presence of flags. With zero flags parameter, + * send() is equivalent to write(). Also, send(sockfd,buf,len,flags) is + * equivalent to sendto(sockfd,buf,len,flags,NULL,0). + * + * Parameters: + * sockfd Socket descriptor of socket + * buf Data to send + * len Length of data to send + * flags Send flags + * + * Returned Value: + * On success, returns the number of characters sent. On error, + * -1 is returned, and errno is set appropriately: + * + * EAGAIN or EWOULDBLOCK + * The socket is marked non-blocking and the requested operation + * would block. + * EBADF + * An invalid descriptor was specified. + * ECONNRESET + * Connection reset by peer. + * EDESTADDRREQ + * The socket is not connection-mode, and no peer address is set. + * EFAULT + * An invalid user space address was specified for a parameter. + * EINTR + * A signal occurred before any data was transmitted. + * EINVAL + * Invalid argument passed. + * EISCONN + * The connection-mode socket was connected already but a recipient + * was specified. (Now either this error is returned, or the recipient + * specification is ignored.) + * EMSGSIZE + * The socket type requires that message be sent atomically, and the + * size of the message to be sent made this impossible. + * ENOBUFS + * The output queue for a network interface was full. This generally + * indicates that the interface has stopped sending, but may be + * caused by transient congestion. + * ENOMEM + * No memory available. + * ENOTCONN + * The socket is not connected, and no target has been given. + * ENOTSOCK + * The argument s is not a socket. + * EOPNOTSUPP + * Some bit in the flags argument is inappropriate for the socket + * type. + * EPIPE + * The local end has been shut down on a connection oriented socket. + * In this case the process will also receive a SIGPIPE unless + * MSG_NOSIGNAL is set. + * + * Assumptions: + * + ****************************************************************************/ + +ssize_t send(int sockfd, const void *buf, size_t len, int flags) +{ + return psock_send(sockfd_socket(sockfd), buf, len, flags); +} + +#endif /* CONFIG_NET && CONFIG_NET_TCP */ diff --git a/nuttx/net/sendto.c b/nuttx/net/sendto.c new file mode 100644 index 0000000000..320eacc195 --- /dev/null +++ b/nuttx/net/sendto.c @@ -0,0 +1,440 @@ +/**************************************************************************** + * net/sendto.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "net_internal.h" +#include "uip/uip_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct sendto_s +{ + FAR struct uip_callback_s *st_cb; /* Reference to callback instance */ + sem_t st_sem; /* Semaphore signals sendto completion */ + uint16_t st_buflen; /* Length of send buffer (error if <0) */ + const char *st_buffer; /* Pointer to send buffer */ + int st_sndlen; /* Result of the send (length sent or negated errno) */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: sendto_interrupt + * + * Description: + * This function is called from the interrupt level to perform the actual + * send operation when polled by the uIP layer. + * + * Parameters: + * dev The sructure of the network driver that caused the interrupt + * conn An instance of the UDP connection structure cast to void * + * pvpriv An instance of struct sendto_s cast to void* + * flags Set of events describing why the callback was invoked + * + * Returned Value: + * Modified value of the input flags + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#ifdef CONFIG_NET_UDP +static uint16_t sendto_interrupt(struct uip_driver_s *dev, void *conn, + void *pvpriv, uint16_t flags) +{ + struct sendto_s *pstate = (struct sendto_s *)pvpriv; + + nllvdbg("flags: %04x\n", flags); + if (pstate) + { + /* Check if the outgoing packet is available (it may have been claimed + * by a sendto interrupt serving a different thread -OR- if the output + * buffer currently contains unprocessed incoming data. In these cases + * we will just have to wait for the next polling cycle. + */ + + if (dev->d_sndlen > 0 || (flags & UIP_NEWDATA) != 0) + { + /* Another thread has beat us sending data or the buffer is busy, + * wait for the next polling cycle + */ + + return flags; + } + + /* It looks like we are good to send the data */ + + else + { + /* Copy the user data into d_snddata and send it */ + + uip_send(dev, pstate->st_buffer, pstate->st_buflen); + pstate->st_sndlen = pstate->st_buflen; + } + + /* Don't allow any further call backs. */ + + pstate->st_cb->flags = 0; + pstate->st_cb->priv = NULL; + pstate->st_cb->event = NULL; + + /* Wake up the waiting thread */ + + sem_post(&pstate->st_sem); + } + + return flags; +} +#endif + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: psock_sendto + * + * Description: + * If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET) + * socket, the parameters to and 'tolen' are ignored (and the error EISCONN + * may be returned when they are not NULL and 0), and the error ENOTCONN is + * returned when the socket was not actually connected. + * + * Parameters: + * psock A pointer to a NuttX-specific, internal socket structure + * buf Data to send + * len Length of data to send + * flags Send flags + * to Address of recipient + * tolen The length of the address structure + * + * Returned Value: + * On success, returns the number of characters sent. On error, + * -1 is returned, and errno is set appropriately: + * + * EAGAIN or EWOULDBLOCK + * The socket is marked non-blocking and the requested operation + * would block. + * EBADF + * An invalid descriptor was specified. + * ECONNRESET + * Connection reset by peer. + * EDESTADDRREQ + * The socket is not connection-mode, and no peer address is set. + * EFAULT + * An invalid user space address was specified for a parameter. + * EINTR + * A signal occurred before any data was transmitted. + * EINVAL + * Invalid argument passed. + * EISCONN + * The connection-mode socket was connected already but a recipient + * was specified. (Now either this error is returned, or the recipient + * specification is ignored.) + * EMSGSIZE + * The socket type requires that message be sent atomically, and the + * size of the message to be sent made this impossible. + * ENOBUFS + * The output queue for a network interface was full. This generally + * indicates that the interface has stopped sending, but may be + * caused by transient congestion. + * ENOMEM + * No memory available. + * ENOTCONN + * The socket is not connected, and no target has been given. + * ENOTSOCK + * The argument s is not a socket. + * EOPNOTSUPP + * Some bit in the flags argument is inappropriate for the socket + * type. + * EPIPE + * The local end has been shut down on a connection oriented socket. + * In this case the process will also receive a SIGPIPE unless + * MSG_NOSIGNAL is set. + * + * Assumptions: + * + ****************************************************************************/ + +ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags, FAR const struct sockaddr *to, + socklen_t tolen) +{ +#ifdef CONFIG_NET_UDP + FAR struct uip_udp_conn *conn; +#ifdef CONFIG_NET_IPv6 + FAR const struct sockaddr_in6 *into = (const struct sockaddr_in6 *)to; +#else + FAR const struct sockaddr_in *into = (const struct sockaddr_in *)to; +#endif + struct sendto_s state; + uip_lock_t save; + int ret; +#endif + int err; + + /* If to is NULL or tolen is zero, then this function is same as send (for + * connected socket types) + */ + + if (!to || !tolen) + { +#ifdef CONFIG_NET_TCP + return psock_send(psock, buf, len, flags); +#else + err = EINVAL; + goto errout; +#endif + } + + /* Verify that a valid address has been provided */ + +#ifdef CONFIG_NET_IPv6 + if (to->sa_family != AF_INET6 || tolen < sizeof(struct sockaddr_in6)) +#else + if (to->sa_family != AF_INET || tolen < sizeof(struct sockaddr_in)) +#endif + { + err = EBADF; + goto errout; + } + + /* Verify that the psock corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + err = EBADF; + goto errout; + } + + /* If this is a connected socket, then return EISCONN */ + + if (psock->s_type != SOCK_DGRAM) + { + err = EISCONN; + goto errout; + } + + /* Perform the UDP sendto operation */ + +#ifdef CONFIG_NET_UDP + /* Set the socket state to sending */ + + psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); + + /* Initialize the state structure. This is done with interrupts + * disabled because we don't want anything to happen until we + * are ready. + */ + + save = uip_lock(); + memset(&state, 0, sizeof(struct sendto_s)); + sem_init(&state.st_sem, 0, 0); + state.st_buflen = len; + state.st_buffer = buf; + + /* Setup the UDP socket */ + + conn = (struct uip_udp_conn *)psock->s_conn; + ret = uip_udpconnect(conn, into); + if (ret < 0) + { + uip_unlock(save); + err = -ret; + goto errout; + } + + /* Set up the callback in the connection */ + + state.st_cb = uip_udpcallbackalloc(conn); + if (state.st_cb) + { + state.st_cb->flags = UIP_POLL; + state.st_cb->priv = (void*)&state; + state.st_cb->event = sendto_interrupt; + + /* Enable the UDP socket */ + + uip_udpenable(conn); + + /* Notify the device driver of the availabilty of TX data */ + + netdev_txnotify(&conn->ripaddr); + + /* Wait for either the receive to complete or for an error/timeout to occur. + * NOTES: (1) uip_lockedwait will also terminate if a signal is received, (2) + * interrupts may be disabled! They will be re-enabled while the task sleeps + * and automatically re-enabled when the task restarts. + */ + + uip_lockedwait(&state.st_sem); + + /* Make sure that no further interrupts are processed */ + + uip_udpdisable(conn); + uip_udpcallbackfree(conn, state.st_cb); + } + uip_unlock(save); + + sem_destroy(&state.st_sem); + + /* Set the socket state to idle */ + + psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); + + /* Check for errors */ + + if (state.st_sndlen < 0) + { + err = -state.st_sndlen; + goto errout; + } + + /* Sucess */ + + return state.st_sndlen; +#else + err = ENOSYS; +#endif + +errout: + errno = err; + return ERROR; +} + +/**************************************************************************** + * Function: sendto + * + * Description: + * If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET) + * socket, the parameters to and 'tolen' are ignored (and the error EISCONN + * may be returned when they are not NULL and 0), and the error ENOTCONN is + * returned when the socket was not actually connected. + * + * Parameters: + * sockfd Socket descriptor of socket + * buf Data to send + * len Length of data to send + * flags Send flags + * to Address of recipient + * tolen The length of the address structure + * + * Returned Value: + * On success, returns the number of characters sent. On error, + * -1 is returned, and errno is set appropriately: + * + * EAGAIN or EWOULDBLOCK + * The socket is marked non-blocking and the requested operation + * would block. + * EBADF + * An invalid descriptor was specified. + * ECONNRESET + * Connection reset by peer. + * EDESTADDRREQ + * The socket is not connection-mode, and no peer address is set. + * EFAULT + * An invalid user space address was specified for a parameter. + * EINTR + * A signal occurred before any data was transmitted. + * EINVAL + * Invalid argument passed. + * EISCONN + * The connection-mode socket was connected already but a recipient + * was specified. (Now either this error is returned, or the recipient + * specification is ignored.) + * EMSGSIZE + * The socket type requires that message be sent atomically, and the + * size of the message to be sent made this impossible. + * ENOBUFS + * The output queue for a network interface was full. This generally + * indicates that the interface has stopped sending, but may be + * caused by transient congestion. + * ENOMEM + * No memory available. + * ENOTCONN + * The socket is not connected, and no target has been given. + * ENOTSOCK + * The argument s is not a socket. + * EOPNOTSUPP + * Some bit in the flags argument is inappropriate for the socket + * type. + * EPIPE + * The local end has been shut down on a connection oriented socket. + * In this case the process will also receive a SIGPIPE unless + * MSG_NOSIGNAL is set. + * + * Assumptions: + * + ****************************************************************************/ + +ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags, + FAR const struct sockaddr *to, socklen_t tolen) +{ + FAR struct socket *psock; + + /* Get the underlying socket structure */ + + psock = sockfd_socket(sockfd); + + /* And let psock_sendto do all of the work */ + + return psock_sendto(psock, buf, len, flags, to, tolen); +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/setsockopt.c b/nuttx/net/setsockopt.c new file mode 100644 index 0000000000..ad52ff53d0 --- /dev/null +++ b/nuttx/net/setsockopt.c @@ -0,0 +1,304 @@ +/**************************************************************************** + * net/setsockopt.c + * + * Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_SOCKOPTS) + +#include +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: psock_setsockopt + * + * Description: + * psock_setsockopt() sets the option specified by the 'option' argument, + * at the protocol level specified by the 'level' argument, to the value + * pointed to by the 'value' argument for the socket on the 'psock' argument. + * + * The 'level' argument specifies the protocol level of the option. To set + * options at the socket level, specify the level argument as SOL_SOCKET. + * + * See a complete list of values for the 'option' argument. + * + * Parameters: + * psock Socket structure of socket to operate on + * level Protocol level to set the option + * option identifies the option to set + * value Points to the argument value + * value_len The length of the argument value + * + * Returned Value: + * 0 on success; -1 on failure + * + * EDOM + * The send and receive timeout values are too big to fit into the + * timeout fields in the socket structure. + * EINVAL + * The specified option is invalid at the specified socket 'level' or the + * socket has been shut down. + * EISCONN + * The socket is already connected, and a specified option cannot be set + * while the socket is connected. + * ENOPROTOOPT + * The 'option' is not supported by the protocol. + * ENOTSOCK + * The 'sockfd' argument does not refer to a socket. + * ENOMEM + * There was insufficient memory available for the operation to complete. + * ENOBUFS + * Insufficient resources are available in the system to complete the + * call. + * + * Assumptions: + * + ****************************************************************************/ + +int psock_setsockopt(FAR struct socket *psock, int level, int option, + FAR const void *value, socklen_t value_len) +{ + uip_lock_t flags; + int err; + + /* Verify that the socket option if valid (but might not be supported ) */ + + if (!_SO_SETVALID(option) || !value) + { + err = EINVAL; + goto errout; + } + + /* Process the option */ + switch (option) + { + /* The following options take a point to an integer boolean value. + * We will blindly set the bit here although the implementation + * is outside of the scope of setsockopt. + */ + + case SO_DEBUG: /* Enables recording of debugging information */ + case SO_BROADCAST: /* Permits sending of broadcast messages */ + case SO_REUSEADDR: /* Allow reuse of local addresses */ + case SO_KEEPALIVE: /* Keeps connections active by enabling the + * periodic transmission */ + case SO_OOBINLINE: /* Leaves received out-of-band data inline */ + case SO_DONTROUTE: /* Requests outgoing messages bypass standard routing */ + { + int setting; + + /* Verify that option is the size of an 'int'. Should also check + * that 'value' is properly aligned for an 'int' + */ + + if (value_len != sizeof(int)) + { + err = EINVAL; + goto errout; + } + + /* Get the value. Is the option being set or cleared? */ + + setting = *(int*)value; + + /* Disable interrupts so that there is no conflict with interrupt + * level access to options. + */ + + flags = uip_lock(); + + /* Set or clear the option bit */ + + if (setting) + { + _SO_SETOPT(psock->s_options, option); + } + else + { + _SO_CLROPT(psock->s_options, option); + } + uip_unlock(flags); + } + break; + + /* The following are valid only if the OS CLOCK feature is enabled */ + + case SO_RCVTIMEO: + case SO_SNDTIMEO: +#ifndef CONFIG_DISABLE_CLOCK + { + socktimeo_t timeo; + + /* Verify that option is the size of an 'struct timeval'. */ + + if (value_len != sizeof(struct timeval)) + { + err = EINVAL; + goto errout; + } + + /* Get the timeout value */ + + timeo = net_timeval2dsec((struct timeval *)value); + + /* Save the timeout value */ + + if (option == SO_RCVTIMEO) + { + psock->s_rcvtimeo = timeo; + } + else + { + psock->s_sndtimeo = timeo; + } + + /* Set/clear the corresponding enable/disable bit */ + + if (timeo) + { + _SO_CLROPT(psock->s_options, option); + } + else + { + _SO_SETOPT(psock->s_options, option); + } + } + break; +#endif + + /* The following are not yet implemented */ + + case SO_LINGER: + case SO_SNDBUF: /* Sets send buffer size */ + case SO_RCVBUF: /* Sets receive buffer size */ + case SO_RCVLOWAT: /* Sets the minimum number of bytes to input */ + case SO_SNDLOWAT: /* Sets the minimum number of bytes to output */ + + /* There options are only valid when used with getopt */ + + case SO_ACCEPTCONN: /* Reports whether socket listening is enabled */ + case SO_ERROR: /* Reports and clears error status. */ + case SO_TYPE: /* Reports the socket type */ + + default: + err = ENOPROTOOPT; + goto errout; + } + return OK; + +errout: + set_errno(err); + return ERROR; +} + +/**************************************************************************** + * Function: setsockopt + * + * Description: + * setsockopt() sets the option specified by the 'option' argument, + * at the protocol level specified by the 'level' argument, to the value + * pointed to by the 'value' argument for the socket associated with the + * file descriptor specified by the 'sockfd' argument. + * + * The 'level' argument specifies the protocol level of the option. To set + * options at the socket level, specify the level argument as SOL_SOCKET. + * + * See a complete list of values for the 'option' argument. + * + * Parameters: + * sockfd Socket descriptor of socket + * level Protocol level to set the option + * option identifies the option to set + * value Points to the argument value + * value_len The length of the argument value + * + * Returned Value: + * 0 on success; -1 on failure + * + * EBADF + * The 'sockfd' argument is not a valid socket descriptor. + * EDOM + * The send and receive timeout values are too big to fit into the + * timeout fields in the socket structure. + * EINVAL + * The specified option is invalid at the specified socket 'level' or the + * socket has been shut down. + * EISCONN + * The socket is already connected, and a specified option cannot be set + * while the socket is connected. + * ENOPROTOOPT + * The 'option' is not supported by the protocol. + * ENOTSOCK + * The 'sockfd' argument does not refer to a socket. + * ENOMEM + * There was insufficient memory available for the operation to complete. + * ENOBUFS + * Insufficient resources are available in the system to complete the + * call. + * + * Assumptions: + * + ****************************************************************************/ + +int setsockopt(int sockfd, int level, int option, const void *value, socklen_t value_len) +{ + FAR struct socket *psock; + + /* Get the underlying socket structure */ + /* Verify that the sockfd corresponds to valid, allocated socket */ + + psock = sockfd_socket(sockfd); + if (!psock || psock->s_crefs <= 0) + { + set_errno(EBADF); + return ERROR; + } + + /* Then let psock_setockopt() do all of the work */ + + return psock_setsockopt(psock, level, option, value, value_len); +} + +#endif /* CONFIG_NET && CONFIG_NET_SOCKOPTS */ diff --git a/nuttx/net/socket.c b/nuttx/net/socket.c new file mode 100644 index 0000000000..a6befc5d74 --- /dev/null +++ b/nuttx/net/socket.c @@ -0,0 +1,286 @@ +/**************************************************************************** + * net/socket.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include +#include + +#include "net_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: psock_socket + * + * Description: + * socket() creates an endpoint for communication and returns a socket + * structure. + * + * Parameters: + * domain (see sys/socket.h) + * type (see sys/socket.h) + * protocol (see sys/socket.h) + * psock A pointer to a user allocated socket structure to be initialized. + * + * Returned Value: + * 0 on success; -1 on error with errno set appropriately + * + * EACCES + * Permission to create a socket of the specified type and/or protocol + * is denied. + * EAFNOSUPPORT + * The implementation does not support the specified address family. + * EINVAL + * Unknown protocol, or protocol family not available. + * EMFILE + * Process file table overflow. + * ENFILE + * The system limit on the total number of open files has been reached. + * ENOBUFS or ENOMEM + * Insufficient memory is available. The socket cannot be created until + * sufficient resources are freed. + * EPROTONOSUPPORT + * The protocol type or the specified protocol is not supported within + * this domain. + * + * Assumptions: + * + ****************************************************************************/ + +int psock_socket(int domain, int type, int protocol, FAR struct socket *psock) +{ + int err = ENFILE; + + /* Only PF_INET or PF_INET6 domains supported */ + +#ifdef CONFIG_NET_IPv6 + if ( domain != PF_INET6) +#else + if ( domain != PF_INET) +#endif + { + err = EAFNOSUPPORT; + goto errout; + } + + /* Only SOCK_STREAM and possible SOCK_DRAM are supported */ + +#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_UDP) + if ((type == SOCK_STREAM && protocol != 0 && protocol != IPPROTO_TCP) || + (type == SOCK_DGRAM && protocol != 0 && protocol != IPPROTO_UDP) || + (type != SOCK_STREAM && type != SOCK_DGRAM)) +#elif defined(CONFIG_NET_TCP) + if ((type == SOCK_STREAM && protocol != 0 && protocol != IPPROTO_TCP) || + (type != SOCK_STREAM)) +#elif defined(CONFIG_NET_UDP) + if ((type == SOCK_DGRAM && protocol != 0 && protocol != IPPROTO_UDP) || + (type != SOCK_DGRAM)) +#endif + { + err = EPROTONOSUPPORT; + goto errout; + } + + /* Everything looks good. Initialize the socket structure */ + /* Save the protocol type */ + + psock->s_type = type; + psock->s_conn = NULL; + + /* Allocate the appropriate connection structure. This reserves the + * the connection structure is is unallocated at this point. It will + * not actually be initialized until the socket is connected. + */ + + err = ENOMEM; /* Assume failure to allocate connection instance */ + switch (type) + { +#ifdef CONFIG_NET_TCP + case SOCK_STREAM: + { + /* Allocate the TCP connection structure and save in the new + * socket instance. + */ + + struct uip_conn *conn = uip_tcpalloc(); + if (conn) + { + /* Set the reference count on the connection structure. This + * reference count will be increment only if the socket is + * dup'ed + */ + + DEBUGASSERT(conn->crefs == 0); + psock->s_conn = conn; + conn->crefs = 1; + } + } + break; +#endif + +#ifdef CONFIG_NET_UDP + case SOCK_DGRAM: + { + /* Allocate the UDP connection structure and save in the new + * socket instance. + */ + + struct uip_udp_conn *conn = uip_udpalloc(); + if (conn) + { + /* Set the reference count on the connection structure. This + * reference count will be increment only if the socket is + * dup'ed + */ + + DEBUGASSERT(conn->crefs == 0); + psock->s_conn = conn; + conn->crefs = 1; + } + } + break; +#endif + + default: + break; + } + + /* Did we succesfully allocate some kind of connection structure? */ + + if (!psock->s_conn) + { + /* Failed to reserve a connection structure */ + + goto errout; /* With err == ENFILE or ENOMEM */ + } + + return OK; + +errout: + errno = err; + return ERROR; +} + +/**************************************************************************** + * Function: socket + * + * Description: + * socket() creates an endpoint for communication and returns a descriptor. + * + * Parameters: + * domain (see sys/socket.h) + * type (see sys/socket.h) + * protocol (see sys/socket.h) + * + * Returned Value: + * A non-negative socket descriptor on success; -1 on error with errno set + * appropriately. + * + * EACCES + * Permission to create a socket of the specified type and/or protocol + * is denied. + * EAFNOSUPPORT + * The implementation does not support the specified address family. + * EINVAL + * Unknown protocol, or protocol family not available. + * EMFILE + * Process file table overflow. + * ENFILE + * The system limit on the total number of open files has been reached. + * ENOBUFS or ENOMEM + * Insufficient memory is available. The socket cannot be created until + * sufficient resources are freed. + * EPROTONOSUPPORT + * The protocol type or the specified protocol is not supported within + * this domain. + * + * Assumptions: + * + ****************************************************************************/ + +int socket(int domain, int type, int protocol) +{ + FAR struct socket *psock; + int sockfd; + int ret; + + /* Allocate a socket descriptor */ + + sockfd = sockfd_allocate(0); + if (sockfd < 0) + { + set_errno(ENFILE); + return ERROR; + } + + /* Get the underlying socket structure */ + + psock = sockfd_socket(sockfd); + if (!psock) + { + set_errno(ENOSYS); /* should not happen */ + goto errout; + } + + /* Initialize the socket structure */ + + ret = psock_socket(domain, type, protocol, psock); + if (ret < 0) + { + /* Error already set by psock_socket() */ + + goto errout; + } + + return sockfd; + +errout: + sockfd_release(sockfd); + return ERROR; +} + +#endif /* CONFIG_NET */ + + diff --git a/nuttx/net/uip/Make.defs b/nuttx/net/uip/Make.defs new file mode 100644 index 0000000000..8bd8d18396 --- /dev/null +++ b/nuttx/net/uip/Make.defs @@ -0,0 +1,106 @@ +############################################################################ +# Make.defs +# +# Copyright (C) 2007, 2009-20010 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +UIP_ASRCS = +UIP_CSRCS = + +ifeq ($(CONFIG_NET),y) + +# Common IP source files + +UIP_CSRCS += uip_initialize.c uip_setipid.c uip_input.c uip_send.c \ + uip_poll.c uip_chksum.c uip_callback.c + +# Non-interrupt level support required? + +ifeq ($(CONFIG_NET_NOINTS),y) +UIP_CSRCS += uip_lock.c +endif + +# ARP supported is not provided for SLIP (Ethernet only) + +ifneq ($(CONFIG_NET_SLIP),y) +UIP_CSRCS += uip_arp.c uip_arptab.c +endif + +# IPv6-specific logic + +ifeq ($(CONFIG_NET_IPv6),y) +UIP_CSRCS += uip_neighbor.c +endif + +# TCP/IP source files + +ifeq ($(CONFIG_NET_TCP),y) + +UIP_CSRCS += uip_tcpconn.c uip_tcpseqno.c uip_tcppoll.c uip_tcptimer.c uip_tcpsend.c \ + uip_tcpinput.c uip_tcpappsend.c uip_listen.c uip_tcpcallback.c \ + uip_tcpreadahead.c uip_tcpbacklog.c + +endif + +# UDP source files + +ifeq ($(CONFIG_NET_UDP),y) + +UIP_CSRCS += uip_udpconn.c uip_udppoll.c uip_udpsend.c uip_udpinput.c \ + uip_udpcallback.c + +endif + +# ICMP source files + +ifeq ($(CONFIG_NET_ICMP),y) + +UIP_CSRCS += uip_icmpinput.c uip_igmppoll.c + +ifeq ($(CONFIG_NET_ICMP_PING),y) +ifneq ($(CONFIG_DISABLE_CLOCK),y) +UIP_CSRCS += uip_icmpping.c uip_icmppoll.c uip_icmpsend.c +endif +endif + +# IGMP source files + +ifeq ($(CONFIG_NET_IGMP),y) +UIP_CSRCS += uip_igmpgroup.c uip_igmpinit.c uip_igmpinput.c uip_igmpjoin.c \ + uip_igmpleave.c uip_igmpmsg.c uip_igmpsend.c uip_igmptimer.c \ + uip_mcastmac.c +endif + +endif +endif + + diff --git a/nuttx/net/uip/uip_arp.c b/nuttx/net/uip/uip_arp.c new file mode 100644 index 0000000000..c731ff0de3 --- /dev/null +++ b/nuttx/net/uip/uip_arp.c @@ -0,0 +1,431 @@ +/**************************************************************************** + * net/uip/uip_arp.c + * Implementation of the ARP Address Resolution Protocol. + * + * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Based on uIP which also has a BSD style license: + * + * Author: Adam Dunkels + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/* The Address Resolution Protocol ARP is used for mapping between IP + * addresses and link level addresses such as the Ethernet MAC + * addresses. ARP uses broadcast queries to ask for the link level + * address of a known IP address and the host which is configured with + * the IP address for which the query was meant, will respond with its + * link level address. + * + * Note: This ARP implementation only supports Ethernet. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#ifdef CONFIG_NET_ARP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +#define ARP_HWTYPE_ETH 1 + +#define RASIZE 4 /* Size of ROUTER ALERT */ + +#define ETHBUF ((struct uip_eth_hdr *)&dev->d_buf[0]) +#define ARPBUF ((struct arp_hdr_s *)&dev->d_buf[UIP_LLH_LEN]) +#define IPBUF ((struct arp_iphdr_s *)&dev->d_buf[UIP_LLH_LEN]) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* ARP header -- Size 28 bytes */ + +struct arp_hdr_s +{ + uint16_t ah_hwtype; /* 16-bit Hardware type (Ethernet=0x001) */ + uint16_t ah_protocol; /* 16-bit Protocol type (IP=0x0800) */ + uint8_t ah_hwlen; /* 8-bit Hardware address size (6) */ + uint8_t ah_protolen; /* 8-bit Procotol address size (4) */ + uint16_t ah_opcode; /* 16-bit Operation */ + uint8_t ah_shwaddr[6]; /* 48-bit Sender hardware address */ + uint16_t ah_sipaddr[2]; /* 32-bit Sender IP adress */ + uint8_t ah_dhwaddr[6]; /* 48-bit Target hardware address */ + uint16_t ah_dipaddr[2]; /* 32-bit Target IP address */ +}; + +/* IP header -- Size 20 or 24 bytes */ + +struct arp_iphdr_s +{ + uint8_t eh_vhl; /* 8-bit Version (4) and header length (5 or 6) */ + uint8_t eh_tos; /* 8-bit Type of service (e.g., 6=TCP) */ + uint8_t eh_len[2]; /* 16-bit Total length */ + uint8_t eh_ipid[2]; /* 16-bit Identification */ + uint8_t eh_ipoffset[2]; /* 16-bit IP flags + fragment offset */ + uint8_t eh_ttl; /* 8-bit Time to Live */ + uint8_t eh_proto; /* 8-bit Protocol */ + uint16_t eh_ipchksum; /* 16-bit Header checksum */ + uint16_t eh_srcipaddr[2]; /* 32-bit Source IP address */ + uint16_t eh_destipaddr[2]; /* 32-bit Destination IP address */ + uint16_t eh_ipoption[2]; /* (optional) */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Support for broadcast address */ + +static const struct ether_addr g_broadcast_ethaddr = + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; +static const uint16_t g_broadcast_ipaddr[2] = {0xffff, 0xffff}; + +/* Support for IGMP multicast addresses. + * + * Well-known ethernet multicast address: + * + * ADDRESS TYPE USAGE + * 01-00-0c-cc-cc-cc 0x0802 CDP (Cisco Discovery Protocol), VTP (Virtual Trunking Protocol) + * 01-00-0c-cc-cc-cd 0x0802 Cisco Shared Spanning Tree Protocol Address + * 01-80-c2-00-00-00 0x0802 Spanning Tree Protocol (for bridges) IEEE 802.1D + * 01-80-c2-00-00-02 0x0809 Ethernet OAM Protocol IEEE 802.3ah + * 01-00-5e-xx-xx-xx 0x0800 IPv4 IGMP Multicast Address + * 33-33-00-00-00-00 0x86DD IPv6 Neighbor Discovery + * 33-33-xx-xx-xx-xx 0x86DD IPv6 Multicast Address (RFC3307) + * + * The following is the first three octects of the IGMP address: + */ + +#if defined(CONFIG_NET_IGMP) && !defined(CONFIG_NET_IPv6) +static const uint8_t g_multicast_ethaddr[3] = {0x01, 0x00, 0x5e}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if defined(CONFIG_NET_DUMPARP) && defined(CONFIG_DEBUG) +static void uip_arp_dump(struct arp_hdr_s *arp) +{ + nlldbg(" HW type: %04x Protocol: %04x\n", + arp->ah_hwtype, arp->ah_protocol);\ + nlldbg(" HW len: %02x Proto len: %02x Operation: %04x\n", + arp->ah_hwlen, arp->ah_protolen, arp->ah_opcode); + nlldbg(" Sender MAC: %02x:%02x:%02x:%02x:%02x:%02x IP: %d.%d.%d.%d\n", + arp->ah_shwaddr[0], arp->ah_shwaddr[1], arp->ah_shwaddr[2], + arp->ah_shwaddr[3], arp->ah_shwaddr[4], arp->ah_shwaddr[5], + arp->ah_sipaddr[0] & 0xff, arp->ah_sipaddr[0] >> 8, + arp->ah_sipaddr[1] & 0xff, arp->ah_sipaddr[1] >> 8); + nlldbg(" Dest MAC: %02x:%02x:%02x:%02x:%02x:%02x IP: %d.%d.%d.%d\n", + arp->ah_dhwaddr[0], arp->ah_dhwaddr[1], arp->ah_dhwaddr[2], + arp->ah_dhwaddr[3], arp->ah_dhwaddr[4], arp->ah_dhwaddr[5], + arp->ah_dipaddr[0] & 0xff, arp->ah_dipaddr[0] >> 8, + arp->ah_dipaddr[1] & 0xff, arp->ah_dipaddr[1] >> 8); +} +#else +# define uip_arp_dump(arp) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* ARP processing for incoming IP packets + * + * This function should be called by the device driver when an IP packet has + * been received. The function will check if the address is in the ARP cache, + * and if so the ARP cache entry will be refreshed. If no ARP cache entry was + * found, a new one is created. + * + * This function expects an IP packet with a prepended Ethernet header in the + * d_buf[] buffer, and the length of the packet in the variable d_len. + */ + +#ifdef CONFIG_NET_ARP_IPIN +void uip_arp_ipin(struct uip_driver_s *dev) +{ + in_addr_t srcipaddr; + + /* Only insert/update an entry if the source IP address of the incoming IP + * packet comes from a host on the local network. + */ + + srcipaddr = uip_ip4addr_conv(IPBUF->eh_srcipaddr); + if (!uip_ipaddr_maskcmp(srcipaddr, dev->d_ipaddr, dev->d_netmask)) + { + uip_arp_update(IPBUF->eh_srcipaddr, ETHBUF->src); + } +} +#endif /* CONFIG_NET_ARP_IPIN */ + +/* ARP processing for incoming ARP packets. + * + * This function should be called by the device driver when an ARP + * packet has been received. The function will act differently + * depending on the ARP packet type: if it is a reply for a request + * that we previously sent out, the ARP cache will be filled in with + * the values from the ARP reply. If the incoming ARP packet is an ARP + * request for our IP address, an ARP reply packet is created and put + * into the d_buf[] buffer. + * + * When the function returns, the value of the field d_len + * indicates whether the device driver should send out a packet or + * not. If d_len is zero, no packet should be sent. If d_len is + * non-zero, it contains the length of the outbound packet that is + * present in the d_buf[] buffer. + * + * This function expects an ARP packet with a prepended Ethernet + * header in the d_buf[] buffer, and the length of the packet in the + * variable d_len. + */ + +void uip_arp_arpin(struct uip_driver_s *dev) +{ + struct arp_hdr_s *parp = ARPBUF; + in_addr_t ipaddr; + + if (dev->d_len < (sizeof(struct arp_hdr_s) + UIP_LLH_LEN)) + { + nlldbg("Too small\n"); + dev->d_len = 0; + return; + } + dev->d_len = 0; + + ipaddr = uip_ip4addr_conv(parp->ah_dipaddr); + switch(parp->ah_opcode) + { + case HTONS(ARP_REQUEST): + nllvdbg("ARP request for IP %04lx\n", (long)ipaddr); + + /* ARP request. If it asked for our address, we send out a reply. */ + + if (uip_ipaddr_cmp(ipaddr, dev->d_ipaddr)) + { + struct uip_eth_hdr *peth = ETHBUF; + + /* First, we register the one who made the request in our ARP + * table, since it is likely that we will do more communication + * with this host in the future. + */ + + uip_arp_update(parp->ah_sipaddr, parp->ah_shwaddr); + + parp->ah_opcode = HTONS(ARP_REPLY); + memcpy(parp->ah_dhwaddr, parp->ah_shwaddr, ETHER_ADDR_LEN); + memcpy(parp->ah_shwaddr, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN); + memcpy(peth->src, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN); + memcpy(peth->dest, parp->ah_dhwaddr, ETHER_ADDR_LEN); + + parp->ah_dipaddr[0] = parp->ah_sipaddr[0]; + parp->ah_dipaddr[1] = parp->ah_sipaddr[1]; + uiphdr_ipaddr_copy(parp->ah_sipaddr, &dev->d_ipaddr); + uip_arp_dump(parp); + + peth->type = HTONS(UIP_ETHTYPE_ARP); + dev->d_len = sizeof(struct arp_hdr_s) + UIP_LLH_LEN; + } + break; + + case HTONS(ARP_REPLY): + nllvdbg("ARP reply for IP %04lx\n", (long)ipaddr); + + /* ARP reply. We insert or update the ARP table if it was meant + * for us. + */ + + if (uip_ipaddr_cmp(ipaddr, dev->d_ipaddr)) + { + uip_arp_update(parp->ah_sipaddr, parp->ah_shwaddr); + } + break; + } +} + +/* Prepend Ethernet header to an outbound IP packet and see if we need + * to send out an ARP request. + * + * This function should be called before sending out an IP packet. The + * function checks the destination IP address of the IP packet to see + * what Ethernet MAC address that should be used as a destination MAC + * address on the Ethernet. + * + * If the destination IP address is in the local network (determined + * by logical ANDing of netmask and our IP address), the function + * checks the ARP cache to see if an entry for the destination IP + * address is found. If so, an Ethernet header is prepended and the + * function returns. If no ARP cache entry is found for the + * destination IP address, the packet in the d_buf[] is replaced by + * an ARP request packet for the IP address. The IP packet is dropped + * and it is assumed that they higher level protocols (e.g., TCP) + * eventually will retransmit the dropped packet. + * + * If the destination IP address is not on the local network, the IP + * address of the default router is used instead. + * + * When the function returns, a packet is present in the d_buf[] + * buffer, and the length of the packet is in the field d_len. + */ + +void uip_arp_out(struct uip_driver_s *dev) +{ + const struct arp_entry *tabptr = NULL; + struct arp_hdr_s *parp = ARPBUF; + struct uip_eth_hdr *peth = ETHBUF; + struct arp_iphdr_s *pip = IPBUF; + in_addr_t ipaddr; + in_addr_t destipaddr; + + /* Find the destination IP address in the ARP table and construct + * the Ethernet header. If the destination IP addres isn't on the + * local network, we use the default router's IP address instead. + * + * If not ARP table entry is found, we overwrite the original IP + * packet with an ARP request for the IP address. + */ + + /* First check if destination is a local broadcast. */ + + if (uiphdr_ipaddr_cmp(pip->eh_destipaddr, g_broadcast_ipaddr)) + { + memcpy(peth->dest, g_broadcast_ethaddr.ether_addr_octet, ETHER_ADDR_LEN); + } +#if defined(CONFIG_NET_IGMP) && !defined(CONFIG_NET_IPv6) + /* Check if the destination address is a multicast address + * + * - IPv4: multicast addresses lie in the class D group -- The address range + * 224.0.0.0 to 239.255.255.255 (224.0.0.0/4) + * + * - IPv6 multicast addresses are have the high-order octet of the + * addresses=0xff (ff00::/8.) + */ + + else if (NTOHS(pip->eh_destipaddr[0]) >= 0xe000 && + NTOHS(pip->eh_destipaddr[0]) <= 0xefff) + { + /* Build the well-known IPv4 IGMP ethernet address. The first + * three bytes are fixed; the final three variable come from the + * last three bytes of the IP address. + */ + + const uint8_t *ip = ((uint8_t*)pip->eh_destipaddr) + 1; + memcpy(peth->dest, g_multicast_ethaddr, 3); + memcpy(&peth->dest[3], ip, 3); + } +#endif + else + { + /* Check if the destination address is on the local network. */ + + destipaddr = uip_ip4addr_conv(pip->eh_destipaddr); + if (!uip_ipaddr_maskcmp(destipaddr, dev->d_ipaddr, dev->d_netmask)) + { + /* Destination address was not on the local network, so we need to + * use the default router's IP address instead of the destination + * address when determining the MAC address. + */ + + uip_ipaddr_copy(ipaddr, dev->d_draddr); + } + else + { + /* Else, we use the destination IP address. */ + + uip_ipaddr_copy(ipaddr, destipaddr); + } + + /* Check if we already have this destination address in the ARP table */ + + tabptr = uip_arp_find(ipaddr); + if (!tabptr) + { + nllvdbg("ARP request for IP %04lx\n", (long)ipaddr); + + /* The destination address was not in our ARP table, so we + * overwrite the IP packet with an ARP request. + */ + + memset(peth->dest, 0xff, ETHER_ADDR_LEN); + memset(parp->ah_dhwaddr, 0x00, ETHER_ADDR_LEN); + memcpy(peth->src, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN); + memcpy(parp->ah_shwaddr, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN); + + uiphdr_ipaddr_copy(parp->ah_dipaddr, &ipaddr); + uiphdr_ipaddr_copy(parp->ah_sipaddr, &dev->d_ipaddr); + + parp->ah_opcode = HTONS(ARP_REQUEST); + parp->ah_hwtype = HTONS(ARP_HWTYPE_ETH); + parp->ah_protocol = HTONS(UIP_ETHTYPE_IP); + parp->ah_hwlen = ETHER_ADDR_LEN; + parp->ah_protolen = 4; + uip_arp_dump(parp); + + peth->type = HTONS(UIP_ETHTYPE_ARP); + dev->d_len = sizeof(struct arp_hdr_s) + UIP_LLH_LEN; + return; + } + + /* Build an ethernet header. */ + + memcpy(peth->dest, tabptr->at_ethaddr.ether_addr_octet, ETHER_ADDR_LEN); + } + + /* Finish populating the ethernet header */ + + memcpy(peth->src, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN); + peth->type = HTONS(UIP_ETHTYPE_IP); + dev->d_len += UIP_LLH_LEN; +} + +#endif /* CONFIG_NET_ARP */ +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip_arptab.c b/nuttx/net/uip/uip_arptab.c new file mode 100644 index 0000000000..1a29f25df4 --- /dev/null +++ b/nuttx/net/uip/uip_arptab.c @@ -0,0 +1,257 @@ +/**************************************************************************** + * net/uip/uip_arptab.c + * Implementation of the ARP Address Resolution Protocol. + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Based originally on uIP which also has a BSD style license: + * + * Author: Adam Dunkels + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#ifdef CONFIG_NET_ARP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The table of known address mappings */ + +static struct arp_entry g_arptable[CONFIG_NET_ARPTAB_SIZE]; +static uint8_t g_arptime; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_arp_init + * + * Description: + * Initialize the ARP module. This function must be called before any of + * the other ARP functions. + * + ****************************************************************************/ + +void uip_arp_init(void) +{ + int i; + for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) + { + memset(&g_arptable[i].at_ipaddr, 0, sizeof(in_addr_t)); + } +} + +/**************************************************************************** + * Name: uip_arp_timer + * + * Description: + * This function performs periodic timer processing in the ARP module + * and should be called at regular intervals. The recommended interval + * is 10 seconds between the calls. It is responsible for flushing old + * entries in the ARP table. + * + ****************************************************************************/ + +void uip_arp_timer(void) +{ + struct arp_entry *tabptr; + int i; + + ++g_arptime; + for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) + { + tabptr = &g_arptable[i]; + if (tabptr->at_ipaddr != 0 && g_arptime - tabptr->at_time >= UIP_ARP_MAXAGE) + { + tabptr->at_ipaddr = 0; + } + } +} + +/**************************************************************************** + * Name: uip_arp_update + * + * Description: + * Add the IP/HW address mapping to the ARP table -OR- change the IP + * address of an existing association. + * + * Input parameters: + * pipaddr - Refers to an IP address uint16_t[2] + * ethaddr - Refers to a HW address uint8_t[IFHWADDRLEN] + * + * Assumptions + * Interrupts are disabled + * + ****************************************************************************/ + +void uip_arp_update(uint16_t *pipaddr, uint8_t *ethaddr) +{ + struct arp_entry *tabptr = NULL; + in_addr_t ipaddr = uip_ip4addr_conv(pipaddr); + int i; + + /* Walk through the ARP mapping table and try to find an entry to + * update. If none is found, the IP -> MAC address mapping is + * inserted in the ARP table. + */ + + for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) + { + tabptr = &g_arptable[i]; + + /* Only check those entries that are actually in use. */ + + if (tabptr->at_ipaddr != 0) + { + /* Check if the source IP address of the incoming packet matches + * the IP address in this ARP table entry. + */ + + if (uip_ipaddr_cmp(ipaddr, tabptr->at_ipaddr)) + { + /* An old entry found, update this and return. */ + + memcpy(tabptr->at_ethaddr.ether_addr_octet, ethaddr, ETHER_ADDR_LEN); + tabptr->at_time = g_arptime; + return; + } + } + } + + /* If we get here, no existing ARP table entry was found, so we create one. */ + + /* First, we try to find an unused entry in the ARP table. */ + + for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) + { + tabptr = &g_arptable[i]; + if (tabptr->at_ipaddr == 0) + { + break; + } + } + + /* If no unused entry is found, we try to find the oldest entry and + * throw it away. + */ + + if (i == CONFIG_NET_ARPTAB_SIZE) + { + uint8_t tmpage = 0; + int j = 0; + for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) + { + tabptr = &g_arptable[i]; + if (g_arptime - tabptr->at_time > tmpage) + { + tmpage = g_arptime - tabptr->at_time; + j = i; + } + } + i = j; + tabptr = &g_arptable[i]; + } + + /* Now, i is the ARP table entry which we will fill with the new + * information. + */ + + tabptr->at_ipaddr = ipaddr; + memcpy(tabptr->at_ethaddr.ether_addr_octet, ethaddr, ETHER_ADDR_LEN); + tabptr->at_time = g_arptime; +} + +/**************************************************************************** + * Name: uip_arp_find + * + * Description: + * Find the ARP entry corresponding to this IP address. + * + * Input parameters: + * ipaddr - Refers to an IP addressin network order + * + * Assumptions + * Interrupts are disabled; Returned value will become unstable when + * interrupts are re-enabled or if any other uIP APIs are called. + * + ****************************************************************************/ + +struct arp_entry *uip_arp_find(in_addr_t ipaddr) +{ + struct arp_entry *tabptr; + int i; + + for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) + { + tabptr = &g_arptable[i]; + if (uip_ipaddr_cmp(ipaddr, tabptr->at_ipaddr)) + { + return tabptr; + } + } + return NULL; +} + +#endif /* CONFIG_NET_ARP */ +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip_callback.c b/nuttx/net/uip/uip_callback.c new file mode 100644 index 0000000000..730aa7758c --- /dev/null +++ b/nuttx/net/uip/uip_callback.c @@ -0,0 +1,251 @@ +/**************************************************************************** + * net/uip/uip_callback.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) + +#include +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct uip_callback_s g_cbprealloc[CONFIG_NET_NACTIVESOCKETS]; +static FAR struct uip_callback_s *g_cbfreelist = NULL; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_callbackinit + * + * Description: + * Configure the pre-allocated callaback structures into a free list. + * This is called internally as part of uIP initialization and should not + * be accessed from the application or socket layer. + * + * Assumptions: + * This function is called with interrupts disabled. + * + ****************************************************************************/ + +void uip_callbackinit(void) +{ + int i; + for (i = 0; i < CONFIG_NET_NACTIVESOCKETS; i++) + { + g_cbprealloc[i].flink = g_cbfreelist; + g_cbfreelist = &g_cbprealloc[i]; + } +} + +/**************************************************************************** + * Function: uip_callbackalloc + * + * Description: + * Allocate a callback container from the free list. + * This is called internally as part of uIP initialization and should not + * be accessed from the application or socket layer. + * + * Assumptions: + * This function is called with interrupts disabled. + * + ****************************************************************************/ + +FAR struct uip_callback_s *uip_callbackalloc(FAR struct uip_callback_s **list) +{ + struct uip_callback_s *ret; + uip_lock_t save; + + /* Check the head of the free list */ + + save = uip_lock(); + ret = g_cbfreelist; + if (ret) + { + /* Remove the next instance from the head of the free list */ + + g_cbfreelist = ret->flink; + memset(ret, 0, sizeof(struct uip_callback_s)); + + /* Add the newly allocated instance to the head of the specified list */ + + if (list) + { + ret->flink = *list; + *list = ret; + } + else + { + ret->flink = NULL; + } + } +#ifdef CONFIG_DEBUG + else + { + nlldbg("Failed to allocate callback\n"); + } +#endif + + uip_unlock(save); + return ret; +} + +/**************************************************************************** + * Function: uip_callbackfree + * + * Description: + * Return a callback container to the free list. + * This is called internally as part of uIP initialization and should not + * be accessed from the application or socket layer. + * + * Assumptions: + * This function is called with interrupts disabled. + * + ****************************************************************************/ + +void uip_callbackfree(FAR struct uip_callback_s *cb, FAR struct uip_callback_s **list) +{ + FAR struct uip_callback_s *prev; + FAR struct uip_callback_s *curr; + uip_lock_t save; + + if (cb) + { + /* Find the callback structure in the connection's list */ + + save = uip_lock(); + if (list) + { + for (prev = NULL, curr = *list; + curr && curr != cb; + prev = curr, curr = curr->flink); + + /* Remove the structure from the connection's list */ + + if (curr) + { + if (prev) + { + prev->flink = cb->flink; + } + else + { + *list = cb->flink; + } + } + } + + /* Put the structure into the free list */ + + cb->flink = g_cbfreelist; + g_cbfreelist = cb; + uip_unlock(save); + } +} + +/**************************************************************************** + * Function: uip_callbackexecute + * + * Description: + * Execute a list of callbacks. + * This is called internally as part of uIP initialization and should not + * be accessed from the application or socket layer. + * + * Assumptions: + * This function is called with interrupts disabled. + * + ****************************************************************************/ + +uint16_t uip_callbackexecute(FAR struct uip_driver_s *dev, void *pvconn, + uint16_t flags, FAR struct uip_callback_s *list) +{ + FAR struct uip_callback_s *next; + uip_lock_t save; + + /* Loop for each callback in the list and while there are still events + * set in the flags set. + */ + + save = uip_lock(); + while (list && flags) + { + /* Save the pointer to the next callback in the lists. This is done + * because the callback action might delete the entry pointed to by + * list. + */ + + next = list->flink; + + /* Check if this callback handles any of the events in the flag set */ + + if (list->event && (flags & list->flags) != 0) + { + /* Yes.. perform the callback. Actions perform by the callback + * may delete the current list entry or add a new list entry to + * beginning of the list (which will be ignored on this pass) + */ + + nllvdbg("Call event=%p with flags=%04x\n", list->event, flags); + flags = list->event(dev, pvconn, list->priv, flags); + } + + /* Set up for the next time through the loop */ + + list = next; + } + + uip_unlock(save); + return flags; +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip_chksum.c b/nuttx/net/uip/uip_chksum.c new file mode 100644 index 0000000000..7a4eee7902 --- /dev/null +++ b/nuttx/net/uip/uip_chksum.c @@ -0,0 +1,230 @@ +/**************************************************************************** + * net/uip/uip_chksum.c + * + * Copyright (C) 2007-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define BUF ((struct uip_ip_hdr *)&dev->d_buf[UIP_LLH_LEN]) +#define ICMPBUF ((struct uip_icmpip_hdr *)&dev->d_buf[UIP_LLH_LEN]) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if !UIP_ARCH_CHKSUM +static uint16_t chksum(uint16_t sum, const uint8_t *data, uint16_t len) +{ + uint16_t t; + const uint8_t *dataptr; + const uint8_t *last_byte; + + dataptr = data; + last_byte = data + len - 1; + + while(dataptr < last_byte) + { + /* At least two more bytes */ + + t = (dataptr[0] << 8) + dataptr[1]; + sum += t; + if (sum < t) + { + sum++; /* carry */ + } + dataptr += 2; + } + + if (dataptr == last_byte) + { + t = (dataptr[0] << 8) + 0; + sum += t; + if (sum < t) + { + sum++; /* carry */ + } + } + + /* Return sum in host byte order. */ + + return sum; +} + +static uint16_t upper_layer_chksum(struct uip_driver_s *dev, uint8_t proto) +{ + struct uip_ip_hdr *pbuf = BUF; + uint16_t upper_layer_len; + uint16_t sum; + +#ifdef CONFIG_NET_IPv6 + upper_layer_len = (((uint16_t)(pbuf->len[0]) << 8) + pbuf->len[1]); +#else /* CONFIG_NET_IPv6 */ + upper_layer_len = (((uint16_t)(pbuf->len[0]) << 8) + pbuf->len[1]) - UIP_IPH_LEN; +#endif /* CONFIG_NET_IPv6 */ + + /* First sum pseudoheader. */ + + /* IP protocol and length fields. This addition cannot carry. */ + + sum = upper_layer_len + proto; + + /* Sum IP source and destination addresses. */ + + sum = chksum(sum, (uint8_t *)&pbuf->srcipaddr, 2 * sizeof(uip_ipaddr_t)); + + /* Sum TCP header and data. */ + + sum = chksum(sum, &dev->d_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_len); + + return (sum == 0) ? 0xffff : htons(sum); +} + +#ifdef CONFIG_NET_IPv6 +static uint16_t uip_icmp6chksum(struct uip_driver_s *dev) +{ + return upper_layer_chksum(dev, UIP_PROTO_ICMP6); +} +#endif /* CONFIG_NET_IPv6 */ + +#endif /* UIP_ARCH_CHKSUM */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Calculate the Internet checksum over a buffer. */ + +#if !UIP_ARCH_ADD32 +static inline void uip_carry32(uint8_t *sum, uint16_t op16) +{ + if (sum[2] < (op16 >> 8)) + { + ++sum[1]; + if (sum[1] == 0) + { + ++sum[0]; + } + } + + if (sum[3] < (op16 & 0xff)) + { + ++sum[2]; + if (sum[2] == 0) + { + ++sum[1]; + if (sum[1] == 0) + { + ++sum[0]; + } + } + } +} + +void uip_incr32(uint8_t *op32, uint16_t op16) +{ + op32[3] += (op16 & 0xff); + op32[2] += (op16 >> 8); + uip_carry32(op32, op16); +} + +#endif /* UIP_ARCH_ADD32 */ + +#if !UIP_ARCH_CHKSUM +uint16_t uip_chksum(uint16_t *data, uint16_t len) +{ + return htons(chksum(0, (uint8_t *)data, len)); +} + +/* Calculate the IP header checksum of the packet header in d_buf. */ + +#ifndef UIP_ARCH_IPCHKSUM +uint16_t uip_ipchksum(struct uip_driver_s *dev) +{ + uint16_t sum; + + sum = chksum(0, &dev->d_buf[UIP_LLH_LEN], UIP_IPH_LEN); + return (sum == 0) ? 0xffff : htons(sum); +} +#endif + +/* Calculate the TCP checksum of the packet in d_buf and d_appdata. */ + +uint16_t uip_tcpchksum(struct uip_driver_s *dev) +{ + return upper_layer_chksum(dev, UIP_PROTO_TCP); +} + +/* Calculate the UDP checksum of the packet in d_buf and d_appdata. */ + +#ifdef CONFIG_NET_UDP_CHECKSUMS +uint16_t uip_udpchksum(struct uip_driver_s *dev) +{ + return upper_layer_chksum(dev, UIP_PROTO_UDP); +} +#endif + +/* Calculate the checksum of the ICMP message */ + +#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) +uint16_t uip_icmpchksum(struct uip_driver_s *dev, int len) +{ + struct uip_icmpip_hdr *picmp = ICMPBUF; + return uip_chksum((uint16_t*)&picmp->type, len); +} +#endif + +#endif /* UIP_ARCH_CHKSUM */ + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip_icmpinput.c b/nuttx/net/uip/uip_icmpinput.c new file mode 100644 index 0000000000..cea2ae4fca --- /dev/null +++ b/nuttx/net/uip/uip_icmpinput.c @@ -0,0 +1,317 @@ +/**************************************************************************** + * net/uip/uip_icmpinput.c + * Handling incoming ICMP/ICMP6 input + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Adapted for NuttX from logic in uIP which also has a BSD-like license: + * + * Original author Adam Dunkels + * Copyright () 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include + +#include +#include +#include +#include + +#include "uip_internal.h" + +#ifdef CONFIG_NET_ICMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ICMPBUF ((struct uip_icmpip_hdr *)&dev->d_buf[UIP_LLH_LEN]) + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +#ifdef CONFIG_NET_ICMP_PING +struct uip_callback_s *g_echocallback = NULL; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_icmpinput + * + * Description: + * Handle incoming ICMP/ICMP6 input + * + * Parameters: + * dev - The device driver structure containing the received ICMP/ICMP6 + * packet + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_icmpinput(struct uip_driver_s *dev) +{ + struct uip_icmpip_hdr *picmp = ICMPBUF; + +#ifdef CONFIG_NET_STATISTICS + uip_stat.icmp.recv++; +#endif + +#ifndef CONFIG_NET_IPv6 + /* ICMPv4 processing code follows. */ + + /* ICMP echo (i.e., ping) processing. This is simple, we only change the + * ICMP type from ECHO to ECHO_REPLY and adjust the ICMP checksum before + * we return the packet. + */ + + if (picmp->type == ICMP_ECHO_REQUEST) + { + /* If we are configured to use ping IP address assignment, we use + * the destination IP address of this ping packet and assign it to + * ourself. + */ + +#ifdef CONFIG_NET_PINGADDRCONF + if (dev->d_ipaddr == 0) + { + dev->d_ipaddr = picmp->destipaddr; + } +#endif + + /* Change the ICMP type */ + + picmp->type = ICMP_ECHO_REPLY; + + /* Swap IP addresses. */ + + uiphdr_ipaddr_copy(picmp->destipaddr, picmp->srcipaddr); + uiphdr_ipaddr_copy(picmp->srcipaddr, &dev->d_ipaddr); + + /* Recalculate the ICMP checksum */ + +#if 0 + /* The slow way... sum over the ICMP message */ + + picmp->icmpchksum = 0; + picmp->icmpchksum = ~uip_icmpchksum(dev, (((uint16_t)picmp->len[0] << 8) | (uint16_t)picmp->len[1]) - UIP_IPH_LEN); + if (picmp->icmpchksum == 0) + { + picmp->icmpchksum = 0xffff; + } +#else + /* The quick way -- Since only the type has changed, just adjust the + * checksum for the change of type + */ + + if( picmp->icmpchksum >= HTONS(0xffff - (ICMP_ECHO_REQUEST << 8))) + { + picmp->icmpchksum += HTONS(ICMP_ECHO_REQUEST << 8) + 1; + } + else + { + picmp->icmpchksum += HTONS(ICMP_ECHO_REQUEST << 8); + } +#endif + + nllvdbg("Outgoing ICMP packet length: %d (%d)\n", + dev->d_len, (picmp->len[0] << 8) | picmp->len[1]); + +#ifdef CONFIG_NET_STATISTICS + uip_stat.icmp.sent++; + uip_stat.ip.sent++; +#endif + } + + /* If an ICMP echo reply is received then there should also be + * a thread waiting to received the echo response. + */ + +#ifdef CONFIG_NET_ICMP_PING + else if (picmp->type == ICMP_ECHO_REPLY && g_echocallback) + { + (void)uip_callbackexecute(dev, picmp, UIP_ECHOREPLY, g_echocallback); + } +#endif + + /* Otherwise the ICMP input was not processed */ + + else + { + nlldbg("Unknown ICMP cmd: %d\n", picmp->type); + goto typeerr; + } + + return; + +typeerr: +#ifdef CONFIG_NET_STATISTICS + uip_stat.icmp.typeerr++; + uip_stat.icmp.drop++; +#endif + dev->d_len = 0; + +#else /* !CONFIG_NET_IPv6 */ + + /* If we get a neighbor solicitation for our address we should send + * a neighbor advertisement message back. + */ + + if (picmp->type == ICMP6_NEIGHBOR_SOLICITATION) + { + if (uip_ipaddr_cmp(picmp->icmp6data, dev->d_ipaddr)) + { + if (picmp->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) + { + /* Save the sender's address in our neighbor list. */ + + uiphdr_neighbor_add(picmp->srcipaddr, &(picmp->options[2])); + } + + /* We should now send a neighbor advertisement back to where the + * neighbor solicication came from. + */ + + picmp->type = ICMP6_NEIGHBOR_ADVERTISEMENT; + picmp->flags = ICMP6_FLAG_S; /* Solicited flag. */ + + picmp->reserved1 = picmp->reserved2 = picmp->reserved3 = 0; + + uiphdr_ipaddr_copy(picmp->destipaddr, picmp->srcipaddr); + uiphdr_ipaddr_copy(picmp->srcipaddr, &dev->d_ipaddr); + picmp->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS; + picmp->options[1] = 1; /* Options length, 1 = 8 bytes. */ + memcpy(&(picmp->options[2]), &dev->d_mac, IFHWADDRLEN); + picmp->icmpchksum = 0; + picmp->icmpchksum = ~uip_icmp6chksum(dev); + } + else + { + goto drop; + } + } + else if (picmp->type == ICMP6_ECHO_REQUEST) + { + /* ICMP echo (i.e., ping) processing. This is simple, we only + * change the ICMP type from ECHO to ECHO_REPLY and update the + * ICMP checksum before we return the packet. + */ + + picmp->type = ICMP6_ECHO_REPLY; + + uiphdr_ipaddr_copy(picmp->destipaddr, picmp->srcipaddr); + uiphdr_ipaddr_copy(picmp->srcipaddr, &dev->d_ipaddr); + picmp->icmpchksum = 0; + picmp->icmpchksum = ~uip_icmp6chksum(dev); + } + + /* If an ICMP echo reply is received then there should also be + * a thread waiting to received the echo response. + */ + +#ifdef CONFIG_NET_ICMP_PING + else if (picmp->type == ICMP6_ECHO_REPLY && g_echocallback) + { + uint16_t flags = UIP_ECHOREPLY; + + if (g_echocallback) + { + /* Dispatch the ECHO reply to the waiting thread */ + + flags = uip_callbackexecute(dev, picmp, flags, g_echocallback); + } + + /* If the ECHO reply was not handled, then drop the packet */ + + if (flags == UIP_ECHOREPLY) + { + /* The ECHO reply was not handled */ + + goto drop; + } + } +#endif + + else + { + nlldbg("Unknown ICMP6 cmd: %d\n", picmp->type); + goto typeerr; + } + + nllvdbg("Outgoing ICMP6 packet length: %d (%d)\n", + dev->d_len, (picmp->len[0] << 8) | picmp->len[1]); + +#ifdef CONFIG_NET_STATISTICS + uip_stat.icmp.sent++; + uip_stat.ip.sent++; +#endif + return; + +typeerr: +#ifdef CONFIG_NET_STATISTICS + uip_stat.icmp.typeerr++; +#endif + +drop: +#ifdef CONFIG_NET_STATISTICS + uip_stat.icmp.drop++; +#endif + dev->d_len = 0; + +#endif /* !CONFIG_NET_IPv6 */ +} + +#endif /* CONFIG_NET_ICMP */ +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip_icmpping.c b/nuttx/net/uip/uip_icmpping.c new file mode 100644 index 0000000000..356187d099 --- /dev/null +++ b/nuttx/net/uip/uip_icmpping.c @@ -0,0 +1,379 @@ +/**************************************************************************** + * net/uip/uip_icmpping.c + * + * Copyright (C) 2008-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_ICMP) && \ + defined(CONFIG_NET_ICMP_PING) && !defined(CONFIG_DISABLE_CLOCK) + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "uip_internal.h" +#include "../net_internal.h" /* Should not include this! */ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ICMPBUF ((struct uip_icmpip_hdr *)&dev->d_buf[UIP_LLH_LEN]) +#define ICMPDAT (&dev->d_buf[UIP_LLH_LEN + sizeof(struct uip_icmpip_hdr)]) + +/* Allocate a new ICMP data callback */ + +#define uip_icmpcallbackalloc() uip_callbackalloc(&g_echocallback) +#define uip_icmpcallbackfree(cb) uip_callbackfree(cb, &g_echocallback) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct icmp_ping_s +{ + FAR struct uip_callback_s *png_cb; /* Reference to callback instance */ + + sem_t png_sem; /* Use to manage the wait for the response */ + uint32_t png_time; /* Start time for determining timeouts */ + uint32_t png_ticks; /* System clock ticks to wait */ + int png_result; /* 0: success; <0:negated errno on fail */ + uip_ipaddr_t png_addr; /* The peer to be ping'ed */ + uint16_t png_id; /* Used to match requests with replies */ + uint16_t png_seqno; /* IN: seqno to send; OUT: seqno recieved */ + uint16_t png_datlen; /* The length of data to send in the ECHO request */ + bool png_sent; /* true... the PING request has been sent */ +}; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: ping_timeout + * + * Description: + * Check for send timeout. + * + * Parameters: + * pstate - Ping state structure + * + * Returned Value: + * TRUE:timeout FALSE:no timeout + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +static inline int ping_timeout(struct icmp_ping_s *pstate) +{ + uint32_t elapsed = clock_systimer() - pstate->png_time; + if (elapsed >= pstate->png_ticks) + { + return TRUE; + } + return FALSE; +} + +/**************************************************************************** + * Function: ping_interrupt + * + * Description: + * This function is called from the interrupt level to perform the actual + * ECHO request and/or ECHO reply actions when polled by the uIP layer. + * + * Parameters: + * dev The structure of the network driver that caused the interrupt + * conn The received packet, cast to void * + * pvpriv An instance of struct icmp_ping_s cast to void* + * flags Set of events describing why the callback was invoked + * + * Returned Value: + * Modified value of the input flags + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +static uint16_t ping_interrupt(struct uip_driver_s *dev, void *conn, + void *pvpriv, uint16_t flags) +{ + struct icmp_ping_s *pstate = (struct icmp_ping_s *)pvpriv; + uint8_t *ptr; + int failcode = -ETIMEDOUT; + int i; + + nllvdbg("flags: %04x\n", flags); + if (pstate) + { + /* Check if this device is on the same network as the destination device. */ + + if (!uip_ipaddr_maskcmp(pstate->png_addr, dev->d_ipaddr, dev->d_netmask)) + { + /* Destination address was not on the local network served by this + * device. If a timeout occurs, then the most likely reason is + * that the destination address is not reachable. + */ + + nllvdbg("Not reachable\n"); + failcode = -ENETUNREACH; + } + else + { + /* Check if this is a ICMP ECHO reply. If so, return the sequence + * number to the caller. NOTE: We may not even have sent the + * requested ECHO request; this could have been the delayed ECHO + * response from a previous ping. + */ + + if ((flags & UIP_ECHOREPLY) != 0 && conn != NULL) + { + struct uip_icmpip_hdr *icmp = (struct uip_icmpip_hdr *)conn; + nlldbg("ECHO reply: id=%d seqno=%d\n", ntohs(icmp->id), ntohs(icmp->seqno)); + + if (ntohs(icmp->id) == pstate->png_id) + { + /* Consume the ECHOREPLY */ + + flags &= ~UIP_ECHOREPLY; + dev->d_len = 0; + + /* Return the result to the caller */ + + pstate->png_result = OK; + pstate->png_seqno = ntohs(icmp->seqno); + goto end_wait; + } + } + + /* Check: + * If the outgoing packet is available (it may have been claimed + * by a sendto interrupt serving a different thread + * -OR- + * If the output buffer currently contains unprocessed incoming + * data. + * -OR- + * If we have alread sent the ECHO request + * + * In the first two cases, we will just have to wait for the next + * polling cycle. + */ + + if (dev->d_sndlen <= 0 && /* Packet available */ + (flags & UIP_NEWDATA) == 0 && /* No incoming data */ + !pstate->png_sent) /* Request not sent */ + { + struct uip_icmpip_hdr *picmp = ICMPBUF; + + /* We can send the ECHO request now. + * + * Format the ICMP ECHO request packet + */ + + picmp->type = ICMP_ECHO_REQUEST; + picmp->icode = 0; +#ifndef CONFIG_NET_IPv6 + picmp->id = htons(pstate->png_id); + picmp->seqno = htons(pstate->png_seqno); +#else +# error "IPv6 ECHO Request not implemented" +#endif + /* Add some easily verifiable data */ + + for (i = 0, ptr = ICMPDAT; i < pstate->png_datlen; i++) + { + *ptr++ = i; + } + + /* Send the ICMP echo request. Note that d_sndlen is set to + * the size of the ICMP payload and does not include the size + * of the ICMP header. + */ + + nlldbg("Send ECHO request: seqno=%d\n", pstate->png_seqno); + + dev->d_sndlen = pstate->png_datlen + 4; + uip_icmpsend(dev, &pstate->png_addr); + pstate->png_sent = true; + return flags; + } + } + + /* Check if the selected timeout has elapsed */ + + if (ping_timeout(pstate)) + { + /* Yes.. report the timeout */ + + nlldbg("Ping timeout\n"); + pstate->png_result = failcode; + goto end_wait; + } + + /* Continue waiting */ + } + return flags; + +end_wait: + nllvdbg("Resuming\n"); + + /* Do not allow any further callbacks */ + + pstate->png_cb->flags = 0; + pstate->png_cb->priv = NULL; + pstate->png_cb->event = NULL; + + /* Wake up the waiting thread */ + + sem_post(&pstate->png_sem); + return flags; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_ping + * + * Description: + * Send a ECHO request and wait for the ECHO response + * + * Parameters: + * addr - The IP address of the peer to send the ICMP ECHO request to + * in network order. + * id - The ID to use in the ICMP ECHO request. This number should be + * unique; only ECHO responses with this matching ID will be + * processed (host order) + * seqno - The sequence number used in the ICMP ECHO request. NOT used + * to match responses (host order) + * dsecs - Wait up to this many deci-seconds for the ECHO response to be + * returned (host order). + * + * Return: + * seqno of received ICMP ECHO with matching ID (may be different + * from the seqno argument (may be a delayed response from an earlier + * ping with the same ID). Or a negated errno on any failure. + * + * Assumptions: + * Called from the user level with interrupts enabled. + * + ****************************************************************************/ + +int uip_ping(uip_ipaddr_t addr, uint16_t id, uint16_t seqno, + uint16_t datalen, int dsecs) +{ + struct icmp_ping_s state; + uip_lock_t save; + + /* Initialize the state structure */ + + sem_init(&state.png_sem, 0, 0); + state.png_ticks = DSEC2TICK(dsecs); /* System ticks to wait */ + state.png_result = -ENOMEM; /* Assume allocation failure */ + state.png_addr = addr; /* Address of the peer to be ping'ed */ + state.png_id = id; /* The ID to use in the ECHO request */ + state.png_seqno = seqno; /* The seqno to use int the ECHO request */ + state.png_datlen = datalen; /* The length of data to send in the ECHO request */ + state.png_sent = false; /* ECHO request not yet sent */ + + save = uip_lock(); + state.png_time = clock_systimer(); + + /* Set up the callback */ + + state.png_cb = uip_icmpcallbackalloc(); + if (state.png_cb) + { + state.png_cb->flags = UIP_POLL|UIP_ECHOREPLY; + state.png_cb->priv = (void*)&state; + state.png_cb->event = ping_interrupt; + state.png_result = -EINTR; /* Assume sem-wait interrupted by signal */ + + /* Notify the device driver of the availaibilty of TX data */ + + netdev_txnotify(&state.png_addr); + + /* Wait for either the full round trip transfer to complete or + * for timeout to occur. (1) uip_lockedwait will also terminate if a + * signal is received, (2) interrupts may be disabled! They will + * be re-enabled while the task sleeps and automatically + * re-enabled when the task restarts. + */ + + nlldbg("Start time: 0x%08x seqno: %d\n", state.png_time, seqno); + uip_lockedwait(&state.png_sem); + + uip_icmpcallbackfree(state.png_cb); + } + uip_unlock(save); + + /* Return the negated error number in the event of a failure, or the + * sequence number of the ECHO reply on success. + */ + + if (!state.png_result) + { + nlldbg("Return seqno=%d\n", state.png_seqno); + return (int)state.png_seqno; + } + else + { + nlldbg("Return error=%d\n", -state.png_result); + return state.png_result; + } +} + +#endif /* CONFIG_NET_ICMP && CONFIG_NET_ICMP_PING ... */ diff --git a/nuttx/net/uip/uip_icmppoll.c b/nuttx/net/uip/uip_icmppoll.c new file mode 100644 index 0000000000..ca1d684c01 --- /dev/null +++ b/nuttx/net/uip/uip_icmppoll.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * net/uip/uip_icmppoll.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) + +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_icmppoll + * + * Description: + * Poll a UDP "connection" structure for availability of TX data + * + * Parameters: + * dev - The device driver structure to use in the send operation + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_icmppoll(struct uip_driver_s *dev) +{ + /* Setup for the application callback */ + + dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPICMPH_LEN]; + dev->d_snddata = &dev->d_buf[UIP_LLH_LEN + UIP_IPICMPH_LEN]; + + dev->d_len = 0; + dev->d_sndlen = 0; + + /* Perform the application callback */ + + (void)uip_callbackexecute(dev, NULL, UIP_POLL, g_echocallback); +} + +#endif /* CONFIG_NET && CONFIG_NET_ICMP && CONFIG_NET_ICMP_PING */ diff --git a/nuttx/net/uip/uip_icmpsend.c b/nuttx/net/uip/uip_icmpsend.c new file mode 100644 index 0000000000..00c5bb9de7 --- /dev/null +++ b/nuttx/net/uip/uip_icmpsend.c @@ -0,0 +1,168 @@ +/**************************************************************************** + * net/uip/uip_icmpsend.c + * + * Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) + +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define ICMPBUF ((struct uip_icmpip_hdr *)&dev->d_buf[UIP_LLH_LEN]) + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_icmpsend + * + * Description: + * Setup to send an ICMP packet + * + * Parameters: + * dev - The device driver structure to use in the send operation + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_icmpsend(struct uip_driver_s *dev, uip_ipaddr_t *destaddr) +{ + struct uip_icmpip_hdr *picmp = ICMPBUF; + + if (dev->d_sndlen > 0) + { + /* The total length to send is the size of the application data plus + * the IP and ICMP headers (and, eventually, the ethernet header) + */ + + dev->d_len = dev->d_sndlen + UIP_IPICMPH_LEN; + + /* The total size of the data (for ICMP checksum calculation) includes + * the size of the ICMP header + */ + + dev->d_sndlen += UIP_ICMPH_LEN; + + /* Initialize the IP header. Note that for IPv6, the IP length field + * does not include the IPv6 IP header length. + */ + +#ifdef CONFIG_NET_IPv6 + + picmp->vtc = 0x60; + picmp->tcf = 0x00; + picmp->flow = 0x00; + picmp->len[0] = (dev->d_sndlen >> 8); + picmp->len[1] = (dev->d_sndlen & 0xff); + picmp->nexthdr = UIP_PROTO_ICMP; + picmp->hoplimit = UIP_TTL; + + uip_ipaddr_copy(picmp->srcipaddr, &dev->d_ipaddr); + uip_ipaddr_copy(picmp->destipaddr, destaddr); + +#else /* CONFIG_NET_IPv6 */ + + picmp->vhl = 0x45; + picmp->tos = 0; + picmp->len[0] = (dev->d_len >> 8); + picmp->len[1] = (dev->d_len & 0xff); + ++g_ipid; + picmp->ipid[0] = g_ipid >> 8; + picmp->ipid[1] = g_ipid & 0xff; + picmp->ipoffset[0] = UIP_TCPFLAG_DONTFRAG >> 8; + picmp->ipoffset[1] = UIP_TCPFLAG_DONTFRAG & 0xff; + picmp->ttl = UIP_TTL; + picmp->proto = UIP_PROTO_ICMP; + + uiphdr_ipaddr_copy(picmp->srcipaddr, &dev->d_ipaddr); + uiphdr_ipaddr_copy(picmp->destipaddr, destaddr); + + /* Calculate IP checksum. */ + + picmp->ipchksum = 0; + picmp->ipchksum = ~(uip_ipchksum(dev)); + +#endif /* CONFIG_NET_IPv6 */ + + /* Calculate the ICMP checksum. */ + + picmp->icmpchksum = 0; + picmp->icmpchksum = ~(uip_icmpchksum(dev, dev->d_sndlen)); + if (picmp->icmpchksum == 0) + { + picmp->icmpchksum = 0xffff; + } + + nllvdbg("Outgoing ICMP packet length: %d (%d)\n", + dev->d_len, (picmp->len[0] << 8) | picmp->len[1]); + +#ifdef CONFIG_NET_STATISTICS + uip_stat.icmp.sent++; + uip_stat.ip.sent++; +#endif + } +} + +#endif /* CONFIG_NET && CONFIG_NET_ICMP && CONFIG_NET_ICMP_PING */ diff --git a/nuttx/net/uip/uip_igmpgroup.c b/nuttx/net/uip/uip_igmpgroup.c new file mode 100755 index 0000000000..220de047e5 --- /dev/null +++ b/nuttx/net/uip/uip_igmpgroup.c @@ -0,0 +1,391 @@ +/**************************************************************************** + * net/uip/uip_igmpgroup.c + * IGMP group data structure management logic + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * The NuttX implementation of IGMP was inspired by the IGMP add-on for the + * lwIP TCP/IP stack by Steve Reynolds: + * + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "uip_internal.h" + +#ifdef CONFIG_NET_IGMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifdef CONFIG_NET_IPv6 +# error "IGMP for IPv6 not supported" +#endif + +#ifndef CONFIG_PREALLOC_IGMPGROUPS +# define CONFIG_PREALLOC_IGMPGROUPS 4 +#endif + +/* Debug ********************************************************************/ + +#undef IGMP_GRPDEBUG /* Define to enable detailed IGMP group debug */ + +#ifndef CONFIG_NET_IGMP +# undef IGMP_GRPDEBUG +#endif + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef IGMP_GRPDEBUG +# define grpdbg(format, arg...) ndbg(format, ##arg) +# define grplldbg(format, arg...) nlldbg(format, ##arg) +# define grpvdbg(format, arg...) nvdbg(format, ##arg) +# define grpllvdbg(format, arg...) nllvdbg(format, ##arg) +# else +# define grpdbg(x...) +# define grplldbg(x...) +# define grpvdbg(x...) +# define grpllvdbg(x...) +# endif +#else +# ifdef IGMP_GRPDEBUG +# define grpdbg ndbg +# define grplldbg nlldbg +# define grpvdbg nvdbg +# define grpllvdbg nllvdbg +# else +# define grpdbg (void) +# define grplldbg (void) +# define grpvdbg (void) +# define grpllvdbg (void) +# endif +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* malloc() cannot be called from an interrupt handler. To work around this, + * a small number of IGMP groups are preallocated just for use in interrupt + * handling logic. + */ + +#if CONFIG_PREALLOC_IGMPGROUPS > 0 +static struct igmp_group_s g_preallocgrps[CONFIG_PREALLOC_IGMPGROUPS]; +static FAR sq_queue_t g_freelist; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_grpalloc + * + * Description: + * Allocate a new group from heap memory. + * + * Assumptions: + * Calls malloc and so cannot be called from an interrupt handler. + * + ****************************************************************************/ + +static inline FAR struct igmp_group_s *uip_grpheapalloc(void) +{ + return (FAR struct igmp_group_s *)zalloc(sizeof(struct igmp_group_s)); +} + +/**************************************************************************** + * Name: uip_grpprealloc + * + * Description: + * Allocate a new group from the pre-allocated groups. + * + * Assumptions: + * This function should only be called from an interrupt handler (or with + * interrupts disabled). + * + ****************************************************************************/ + +#if CONFIG_PREALLOC_IGMPGROUPS > 0 +static inline FAR struct igmp_group_s *uip_grpprealloc(void) +{ + FAR struct igmp_group_s *group = (FAR struct igmp_group_s *)sq_remfirst(&g_freelist); + if (group) + { + memset(group, 0, sizeof(struct igmp_group_s)); + group->flags = IGMP_PREALLOCATED; + } + return group; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_grpinit + * + * Description: + * One-time initialization of group data. + * + * Assumptions: + * Called only during early boot phases (pre-multitasking). + * + ****************************************************************************/ + +void uip_grpinit(void) +{ + FAR struct igmp_group_s *group; + int i; + + grplldbg("Initializing\n"); + +#if CONFIG_PREALLOC_IGMPGROUPS > 0 + for (i = 0; i < CONFIG_PREALLOC_IGMPGROUPS; i++) + { + group = &g_preallocgrps[i]; + sq_addfirst((FAR sq_entry_t *)group, &g_freelist); + } +#endif +} + +/**************************************************************************** + * Name: uip_grpalloc + * + * Description: + * Allocate a new group from heap memory. + * + * Assumptions: + * May be called from either user or interrupt level processing. + * + ****************************************************************************/ + +FAR struct igmp_group_s *uip_grpalloc(FAR struct uip_driver_s *dev, + FAR const uip_ipaddr_t *addr) +{ + FAR struct igmp_group_s *group; + uip_lock_t flags; + + nllvdbg("addr: %08x dev: %p\n", *addr, dev); + if (up_interrupt_context()) + { +#if CONFIG_PREALLOC_IGMPGROUPS > 0 + grplldbg("Use a pre-allocated group entry\n"); + group = uip_grpprealloc(); +#else + grplldbg("Cannot allocate from interrupt handler\n"); + group = NULL; +#endif + } + else + { + grplldbg("Allocate from the heap\n"); + group = uip_grpheapalloc(); + } + grplldbg("group: %p\n", group); + + /* Check if we succesfully allocated a group structure */ + + if (group) + { + /* Initialize the non-zero elements of the group structure */ + + uip_ipaddr_copy(group->grpaddr, *addr); + sem_init(&group->sem, 0, 0); + + /* Initialize the group timer (but don't start it yet) */ + + group->wdog = wd_create(); + DEBUGASSERT(group->wdog); + + /* Interrupts must be disabled in order to modify the group list */ + + flags = uip_lock(); + + /* Add the group structure to the list in the device structure */ + + sq_addfirst((FAR sq_entry_t*)group, &dev->grplist); + uip_unlock(flags); + } + return group; +} + +/**************************************************************************** + * Name: uip_grpfind + * + * Description: + * Find an existing group. + * + * Assumptions: + * May be called from either user or interrupt level processing. + * + ****************************************************************************/ + +FAR struct igmp_group_s *uip_grpfind(FAR struct uip_driver_s *dev, + FAR const uip_ipaddr_t *addr) +{ + FAR struct igmp_group_s *group; + uip_lock_t flags; + + grplldbg("Searching for addr %08x\n", (int)*addr); + + /* We must disable interrupts because we don't which context we were + * called from. + */ + + flags = uip_lock(); + for (group = (FAR struct igmp_group_s *)dev->grplist.head; + group; + group = group->next) + { + grplldbg("Compare: %08x vs. %08x\n", group->grpaddr, *addr); + if (uip_ipaddr_cmp(group->grpaddr, *addr)) + { + grplldbg("Match!\n"); + break; + } + } + uip_unlock(flags); + return group; +} + +/**************************************************************************** + * Name: uip_grpallocfind + * + * Description: + * Find an existing group. If not found, create a new group for the + * address. + * + * Assumptions: + * May be called from either user or interrupt level processing. + * + ****************************************************************************/ + +FAR struct igmp_group_s *uip_grpallocfind(FAR struct uip_driver_s *dev, + FAR const uip_ipaddr_t *addr) +{ + FAR struct igmp_group_s *group = uip_grpfind(dev, addr); + + grplldbg("group: %p addr: %08x\n", group, (int)*addr); + if (!group) + { + group = uip_grpalloc(dev, addr); + } + grplldbg("group: %p\n", group); + return group; +} + +/**************************************************************************** + * Name: uip_grpfree + * + * Description: + * Release a previously allocated group. + * + * Assumptions: + * May be called from either user or interrupt level processing. + * + ****************************************************************************/ + +void uip_grpfree(FAR struct uip_driver_s *dev, FAR struct igmp_group_s *group) +{ + uip_lock_t flags; + + grplldbg("Free: %p flags: %02x\n", group, group->flags); + + /* Cancel the wdog */ + + flags = uip_lock(); + wd_cancel(group->wdog); + + /* Remove the group structure from the group list in the device structure */ + + sq_rem((FAR sq_entry_t*)group, &dev->grplist); + + /* Destroy the wait semapore */ + + (void)sem_destroy(&group->sem); + + /* Destroy the wdog */ + + wd_delete(group->wdog); + + /* Then release the group structure resources. Check first if this is one + * of the pre-allocated group structures that we will retain in a free list. + */ + +#if CONFIG_PREALLOC_IGMPGROUPS > 0 + if (IS_PREALLOCATED(group->flags)) + { + grplldbg("Put back on free list\n"); + sq_addlast((FAR sq_entry_t*)group, &g_freelist); + uip_unlock(flags); + } + else +#endif + { + /* No.. deallocate the group structure. Use sched_free() just in case + * this function is executing within an interrupt handler. + */ + + uip_unlock(flags); + grplldbg("Call sched_free()\n"); + sched_free(group); + } +} + +#endif /* CONFIG_NET_IGMP */ diff --git a/nuttx/net/uip/uip_igmpinit.c b/nuttx/net/uip/uip_igmpinit.c new file mode 100755 index 0000000000..7954e7b3e8 --- /dev/null +++ b/nuttx/net/uip/uip_igmpinit.c @@ -0,0 +1,122 @@ +/**************************************************************************** + * net/uip/uip_igmpinit.c + * IGMP initialization logic + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * The NuttX implementation of IGMP was inspired by the IGMP add-on for the + * lwIP TCP/IP stack by Steve Reynolds: + * + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "uip_internal.h" + +#ifdef CONFIG_NET_IGMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +# error "IGMP for IPv6 not supported" +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +uip_ipaddr_t g_allsystems; +uip_ipaddr_t g_allrouters; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_igmpinit + * + * Description: + * Perform one-time IGMP initialization. + * + ****************************************************************************/ + +void uip_igmpinit(void) +{ + nvdbg("IGMP initializing\n"); + + uip_ipaddr(g_allrouters, 224, 0, 0, 2); + uip_ipaddr(g_allsystems, 224, 0, 0, 1); + + /* Initialize the group allocation logic */ + + uip_grpinit(); +} + +/**************************************************************************** + * Name: uip_igmpdevinit + * + * Description: + * Called when a new network device is registered to configure that device + * for IGMP support. + * + ****************************************************************************/ + +void uip_igmpdevinit(struct uip_driver_s *dev) +{ + struct igmp_group_s *group; + + nvdbg("IGMP initializing dev %p\n", dev); + DEBUGASSERT(dev->grplist.head == NULL); + + /* Add the all systems address to the group */ + + group = uip_grpalloc(dev, &g_allsystems); + + /* Allow the IGMP messages at the MAC level */ + + uip_addmcastmac(dev, &g_allrouters); + uip_addmcastmac(dev, &g_allsystems); +} + +#endif /* CONFIG_NET_IGMP */ diff --git a/nuttx/net/uip/uip_igmpinput.c b/nuttx/net/uip/uip_igmpinput.c new file mode 100755 index 0000000000..5b4fbefa42 --- /dev/null +++ b/nuttx/net/uip/uip_igmpinput.c @@ -0,0 +1,280 @@ +/**************************************************************************** + * net/uip/uip_igminput.c + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * The NuttX implementation of IGMP was inspired by the IGMP add-on for the + * lwIP TCP/IP stack by Steve Reynolds: + * + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +#ifdef CONFIG_NET_IGMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IGMPBUF ((struct uip_igmphdr_s *)&dev->d_buf[UIP_LLH_LEN]) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_igmpinput + * + * Description: + * An IGMP packet has been received. + * + * ________________ + * | | + * | | + * | | + * | | + * +--------->| Non-Member |<---------+ + * | | | | + * | | | | + * | | | | + * | |________________| | + * | | | + * | leave group | join group | leave group + * | (stop timer, |(send report, | (send leave + * | send leave if | set flag, | if flag set) + * | flag set) | start timer) | + * ________|________ | ________|________ + * | |<---------+ | | + * | | | | + * | |<-------------------| | + * | | query received | | + * | Delaying Member | (start timer) | Idle Member | + * +---->| |------------------->| | + * | | | report received | | + * | | | (stop timer, | | + * | | | clear flag) | | + * | |_________________|------------------->|_________________| + * | query received | timer expired + * | (reset timer if | (send report, + * | Max Resp Time | set flag) + * | < current timer) | + * +-------------------+ + * + * NOTE: This is most likely executing from an interrupt handler. + * + ****************************************************************************/ + +void uip_igmpinput(struct uip_driver_s *dev) +{ + FAR struct igmp_group_s *group; + uip_ipaddr_t destipaddr; + uip_ipaddr_t grpaddr; + unsigned int ticks; + + nllvdbg("IGMP message: %04x%04x\n", IGMPBUF->destipaddr[1], IGMPBUF->destipaddr[0]); + + /* Verify the message length */ + + if (dev->d_len < UIP_LLH_LEN+UIP_IPIGMPH_LEN) + { + IGMP_STATINCR(uip_stat.igmp.length_errors); + nlldbg("Length error\n"); + return; + } + + /* Calculate and check the IGMP checksum */ + + if (uip_chksum((uint16_t*)&IGMPBUF->type, UIP_IGMPH_LEN) != 0) + { + IGMP_STATINCR(uip_stat.igmp.chksum_errors); + nlldbg("Checksum error\n"); + return; + } + + /* Find the group (or create a new one) using the incoming IP address*/ + + destipaddr = uip_ip4addr_conv(IGMPBUF->destipaddr); + group = uip_grpallocfind(dev, &destipaddr); + if (!group) + { + nlldbg("Failed to allocate/find group: %08x\n", destipaddr); + return; + } + + /* Now handle the message based on the IGMP message type */ + + switch (IGMPBUF->type) + { + case IGMP_MEMBERSHIP_QUERY: + /* RFC 2236, 2.2. ax Response Time + * "The Max Response Time field is meaningful only in Membership Query + * messages, and specifies the maximum allowed time before sending a + * responding report in units of 1/10 second. In all other messages, it + * is set to zero by the sender and ignored by receivers. + */ + + /* Check if the query was sent to all systems */ + + if (uip_ipaddr_cmp(destipaddr, g_allsystems)) + { + /* Yes... Now check the if this this is a general or a group + * specific query. + * + * RFC 2236, 2.1. Type + * There are two sub-types of Membership Query messages: + * - General Query, used to learn which groups have members on an + * attached network. + * - Group-Specific Query, used to learn if a particular group + * has any members on an attached network. + * + * RFC 2236, 2.4. Group Address + * "In a Membership Query message, the group address field is + * set to zero when sending a General Query, and set to the + * group address being queried when sending a Group-Specific + * Query." + */ + + if (IGMPBUF->grpaddr == 0) + { + FAR struct igmp_group_s *member; + + /* This is the general query */ + + nllvdbg("General multicast query\n"); + if (IGMPBUF->maxresp == 0) + { + IGMP_STATINCR(uip_stat.igmp.v1_received); + IGMPBUF->maxresp = 10; + + nlldbg("V1 not implemented\n"); + } + + IGMP_STATINCR(uip_stat.igmp.query_received); + for (member = (FAR struct igmp_group_s *)dev->grplist.head; + member; + member = member->next) + { + /* Skip over the all systems group entry */ + + if (!uip_ipaddr_cmp(member->grpaddr, g_allsystems)) + { + ticks = uip_decisec2tick((int)IGMPBUF->maxresp); + if (IS_IDLEMEMBER(member->flags) || + uip_igmpcmptimer(member, ticks)) + { + uip_igmpstartticks(member, ticks); + CLR_IDLEMEMBER(member->flags); + } + } + } + } + else /* if (IGMPBUF->grpaddr != 0) */ + { + nllvdbg("Group-specific multicast queury\n"); + + /* We first need to re-lookup the group since we used dest last time. + * Use the incoming IPaddress! + */ + + IGMP_STATINCR(uip_stat.igmp.ucast_query); + grpaddr = uip_ip4addr_conv(IGMPBUF->grpaddr); + group = uip_grpallocfind(dev, &grpaddr); + ticks = uip_decisec2tick((int)IGMPBUF->maxresp); + if (IS_IDLEMEMBER(group->flags) || uip_igmpcmptimer(group, ticks)) + { + uip_igmpstartticks(group, ticks); + CLR_IDLEMEMBER(group->flags); + } + } + } + + /* Not sent to all systems -- Unicast query */ + + else if (group->grpaddr != 0) + { + nllvdbg("Unitcast queury\n"); + IGMP_STATINCR(uip_stat.igmp.ucast_query); + + nlldbg("Query to a specific group with the group address as destination\n"); + + ticks = uip_decisec2tick((int)IGMPBUF->maxresp); + if (IS_IDLEMEMBER(group->flags) || uip_igmpcmptimer(group, ticks)) + { + uip_igmpstartticks(group, ticks); + CLR_IDLEMEMBER(group->flags); + } + } + break; + + case IGMPv2_MEMBERSHIP_REPORT: + { + nllvdbg("Membership report\n"); + + IGMP_STATINCR(uip_stat.igmp.report_received); + if (!IS_IDLEMEMBER(group->flags)) + { + /* This is on a specific group we have already looked up */ + + wd_cancel(group->wdog); + SET_IDLEMEMBER(group->flags); + CLR_LASTREPORT(group->flags); + } + } + break; + + default: + { + nlldbg("Unexpected msg %02x\n", IGMPBUF->type); + } + break; + } +} + +#endif /* CONFIG_NET_IGMP */ diff --git a/nuttx/net/uip/uip_igmpjoin.c b/nuttx/net/uip/uip_igmpjoin.c new file mode 100755 index 0000000000..eb6e888379 --- /dev/null +++ b/nuttx/net/uip/uip_igmpjoin.c @@ -0,0 +1,160 @@ +/**************************************************************************** + * net/uip/uip_igmpjoin.c + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * The NuttX implementation of IGMP was inspired by the IGMP add-on for the + * lwIP TCP/IP stack by Steve Reynolds: + * + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +#ifdef CONFIG_NET_IGMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: igmp_joingroup + * + * Description: + * Add the specified group address to the group. + * + * RFC 2236, 3. Protocol Description: + * + * "When a host joins a multicast group, it should immediately transmit + * an unsolicited Version 2 Membership Report for that group, in case it + * is the first member of that group on the network. To cover the + * possibility of the initial Membership Report being lost or damaged, + * it is recommended that it be repeated once or twice after short + * delays [Unsolicited Report Interval]. (A simple way to accomplish + * this is to send the initial Version 2 Membership Report and then act + * as if a Group-Specific Query was received for that group, and set a + * timer appropriately)." + * ________________ + * | | + * | | + * | | + * | | + * +--------->| Non-Member |<---------+ + * | | | | + * | | | | + * | | | | + * | |________________| | + * | | | + * | leave group | join group | leave group + * | (stop timer, |(send report, | (send leave + * | send leave if | set flag, | if flag set) + * | flag set) | start timer) | + * ________|________ | ________|________ + * | |<---------+ | | + * | | | | + * | |<-------------------| | + * | | query received | | + * | Delaying Member | (start timer) | Idle Member | + * +---->| |------------------->| | + * | | | report received | | + * | | | (stop timer, | | + * | | | clear flag) | | + * | |_________________|------------------->|_________________| + * | query received | timer expired + * | (reset timer if | (send report, + * | Max Resp Time | set flag) + * | < current timer) | + * +-------------------+ + * + * Assumptions: + * This function cannot be called from interrupt handling logic! + * + ****************************************************************************/ + +int igmp_joingroup(struct uip_driver_s *dev, FAR const struct in_addr *grpaddr) +{ + struct igmp_group_s *group; + + DEBUGASSERT(dev && grpaddr); + + /* Check if a this address is already in the group */ + + group = uip_grpfind(dev, &grpaddr->s_addr); + if (!group) + { + /* No... allocate a new entry */ + + nvdbg("Join to new group: %08x\n", grpaddr->s_addr); + group = uip_grpalloc(dev, &grpaddr->s_addr); + IGMP_STATINCR(uip_stat.igmp.joins); + + /* Send the Membership Report */ + + IGMP_STATINCR(uip_stat.igmp.report_sched); + uip_igmpwaitmsg(group, IGMPv2_MEMBERSHIP_REPORT); + + /* And start the timer at 10*100 msec */ + + uip_igmpstarttimer(group, 10); + + /* Add the group (MAC) address to the ether drivers MAC filter list */ + + uip_addmcastmac(dev, (FAR uip_ipaddr_t *)&grpaddr->s_addr); + return OK; + } + + /* Return EEXIST if the address is already a member of the group */ + + return -EEXIST; +} + +#endif /* CONFIG_NET_IGMP */ diff --git a/nuttx/net/uip/uip_igmpleave.c b/nuttx/net/uip/uip_igmpleave.c new file mode 100755 index 0000000000..7e2a31a196 --- /dev/null +++ b/nuttx/net/uip/uip_igmpleave.c @@ -0,0 +1,182 @@ +/**************************************************************************** + * net/uip/uip_igmpleave.c + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * The NuttX implementation of IGMP was inspired by the IGMP add-on for the + * lwIP TCP/IP stack by Steve Reynolds: + * + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +#ifdef CONFIG_NET_IGMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: igmp_leavegroup + * + * Description: + * Remove the specified group address to the group. + * + * RFC 2236, 3. Protocol Description: + * + * "When a host leaves a multicast group, if it was the last host to + * reply to a Query with a Membership Report for that group, it SHOULD + * send a Leave Group message to the all-routers multicast group + * (224.0.0.2). If it was not the last host to reply to a Query, it MAY + * send nothing as there must be another member on the subnet. This is + * an optimization to reduce traffic; a host without sufficient storage + * to remember whether or not it was the last host to reply MAY always + * send a Leave Group message when it leaves a group. Routers SHOULD + * accept a Leave Group message addressed to the group being left, in + * order to accommodate implementations of an earlier version of this + * standard. Leave Group messages are addressed to the all-routers + * group because other group members have no need to know that a host + * has left the group, but it does no harm to address the message to the + * group." + * + * ________________ + * | | + * | | + * | | + * | | + * +--------->| Non-Member |<---------+ + * | | | | + * | | | | + * | | | | + * | |________________| | + * | | | + * | leave group | join group | leave group + * | (stop timer, |(send report, | (send leave + * | send leave if | set flag, | if flag set) + * | flag set) | start timer) | + * ________|________ | ________|________ + * | |<---------+ | | + * | | | | + * | |<-------------------| | + * | | query received | | + * | Delaying Member | (start timer) | Idle Member | + * +---->| |------------------->| | + * | | | report received | | + * | | | (stop timer, | | + * | | | clear flag) | | + * | |_________________|------------------->|_________________| + * | query received | timer expired + * | (reset timer if | (send report, + * | Max Resp Time | set flag) + * | < current timer) | + * +-------------------+ + * + * Assumptions: + * This function cannot be called from interrupt handling logic! + * + ****************************************************************************/ + +int igmp_leavegroup(struct uip_driver_s *dev, FAR const struct in_addr *grpaddr) +{ + struct igmp_group_s *group; + uip_lock_t flags; + + DEBUGASSERT(dev && grpaddr); + + /* Find the entry corresponding to the address leaving the group */ + + group = uip_grpfind(dev, &grpaddr->s_addr); + ndbg("Leaving group: %p\n", group); + if (group) + { + /* Cancel the timer and discard any queued Membership Reports. Canceling + * the timer will prevent any new Membership Reports from being sent; + * clearing the flags will discard any pending Membership Reports that + * could interfere with the Leave Group. + */ + + flags = uip_lock(); + wd_cancel(group->wdog); + CLR_SCHEDMSG(group->flags); + CLR_WAITMSG(group->flags); + uip_unlock(flags); + + IGMP_STATINCR(uip_stat.igmp.leaves); + + /* Send a leave if the flag is set according to the state diagram */ + + if (IS_LASTREPORT(group->flags)) + { + ndbg("Schedule Leave Group message\n"); + IGMP_STATINCR(uip_stat.igmp.leave_sched); + uip_igmpwaitmsg(group, IGMP_LEAVE_GROUP); + } + + /* Free the group structure (state is now Non-Member */ + + uip_grpfree(dev, group); + + /* And remove the group address from the ethernet drivers MAC filter set */ + + uip_removemcastmac(dev, (FAR uip_ipaddr_t *)&grpaddr->s_addr); + return OK; + } + + /* Return ENOENT if the address is not a member of the group */ + + nvdbg("Return -ENOENT\n"); + return -ENOENT; +} + +#endif /* CONFIG_NET_IGMP */ diff --git a/nuttx/net/uip/uip_igmpmsg.c b/nuttx/net/uip/uip_igmpmsg.c new file mode 100755 index 0000000000..9ea3daa4eb --- /dev/null +++ b/nuttx/net/uip/uip_igmpmsg.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * net/uip/uip_igmpmgs.c + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * The NuttX implementation of IGMP was inspired by the IGMP add-on for the + * lwIP TCP/IP stack by Steve Reynolds: + * + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +#ifdef CONFIG_NET_IGMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_igmpschedmsg + * + * Description: + * Schedule a message to be send at the next driver polling interval. + * + * Assumptions: + * This function may be called in most any context. + * + ****************************************************************************/ + +void uip_igmpschedmsg(FAR struct igmp_group_s *group, uint8_t msgid) +{ + uip_lock_t flags; + + /* The following should be atomic */ + + flags = uip_lock(); + DEBUGASSERT(!IS_SCHEDMSG(group->flags)); + group->msgid = msgid; + SET_SCHEDMSG(group->flags); + uip_unlock(flags); +} + +/**************************************************************************** + * Name: uip_igmpwaitmsg + * + * Description: + * Schedule a message to be send at the next driver polling interval and + * block, waiting for the message to be sent. + * + * Assumptions: + * This function cannot be called from an interrupt handler (if you try it, + * uip_lockedwait will assert). + * + ****************************************************************************/ + +void uip_igmpwaitmsg(FAR struct igmp_group_s *group, uint8_t msgid) +{ + uip_lock_t flags; + + /* Schedule to send the message */ + + flags = uip_lock(); + DEBUGASSERT(!IS_WAITMSG(group->flags)); + SET_WAITMSG(group->flags); + uip_igmpschedmsg(group, msgid); + + /* Then wait for the message to be sent */ + + while (IS_SCHEDMSG(group->flags)) + { + /* Wait for the semaphore to be posted */ + + while (uip_lockedwait(&group->sem) != 0) + { + /* The only error that should occur from uip_lockedwait() is if + * the wait is awakened by a signal. + */ + + ASSERT(errno == EINTR); + } + } + + /* The message has been sent and we are no longer waiting */ + + CLR_WAITMSG(group->flags); + uip_unlock(flags); +} + +#endif /* CONFIG_NET_IGMP */ diff --git a/nuttx/net/uip/uip_igmppoll.c b/nuttx/net/uip/uip_igmppoll.c new file mode 100755 index 0000000000..cec2a5e1b7 --- /dev/null +++ b/nuttx/net/uip/uip_igmppoll.c @@ -0,0 +1,176 @@ +/**************************************************************************** + * net/uip/uip_igmppoll.c + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * The NuttX implementation of IGMP was inspired by the IGMP add-on for the + * lwIP TCP/IP stack by Steve Reynolds: + * + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +#ifdef CONFIG_NET_IGMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_schedsend + * + * Description: + * Construct the . + * + * Returned Value: + * Returns a non-zero value if a IGP message is sent. + * + * Assumptions: + * This function is called from the driver polling logic... probably within + * an interrupt handler. + * + ****************************************************************************/ + +static inline void uip_schedsend(FAR struct uip_driver_s *dev, FAR struct igmp_group_s *group) +{ + uip_ipaddr_t *dest; + + /* Check what kind of messsage we need to send. There are only two + * possibilities: + */ + + if (group->msgid == IGMPv2_MEMBERSHIP_REPORT) + { + dest = &group->grpaddr; + nllvdbg("Send IGMPv2_MEMBERSHIP_REPORT, dest=%08x flags=%02x\n", + *dest, group->flags); + IGMP_STATINCR(uip_stat.igmp.report_sched); + SET_LASTREPORT(group->flags); /* Remember we were the last to report */ + } + else + { + DEBUGASSERT(group->msgid == IGMP_LEAVE_GROUP); + dest = &g_allrouters; + nllvdbg("Send IGMP_LEAVE_GROUP, dest=%08x flags=%02x\n", + *dest, group->flags); + IGMP_STATINCR(uip_stat.igmp.leave_sched); + } + + /* Send the message */ + + uip_igmpsend(dev, group, dest); + + /* Indicate that the message has been sent */ + + CLR_SCHEDMSG(group->flags); + group->msgid = 0; + + /* If there is a thread waiting fore the message to be sent, wake it up */ + + if (IS_WAITMSG(group->flags)) + { + nllvdbg("Awakening waiter\n"); + sem_post(&group->sem); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_igmppoll + * + * Description: + * Poll the groups associated with the device to see if any IGMP messages + * are pending transfer. + * + * Returned Value: + * Returns a non-zero value if a IGP message is sent. + * + * Assumptions: + * This function is called from the driver polling logic... probably within + * an interrupt handler. + * + ****************************************************************************/ + +void uip_igmppoll(FAR struct uip_driver_s *dev) +{ + FAR struct igmp_group_s *group; + + nllvdbg("Entry\n"); + + /* Setup the poll operation */ + + dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPIGMPH_LEN]; + dev->d_snddata = &dev->d_buf[UIP_LLH_LEN + UIP_IPIGMPH_LEN]; + + dev->d_len = 0; + dev->d_sndlen = 0; + + /* Check each member of the group */ + + for (group = (FAR struct igmp_group_s *)dev->grplist.head; group; group = group->next) + { + /* Does this member have a pending outgoing message? */ + + if (IS_SCHEDMSG(group->flags)) + { + /* Yes, create the IGMP message in the driver buffer */ + + uip_schedsend(dev, group); + + /* Mark the message as sent and break out */ + + CLR_SCHEDMSG(group->flags); + break; + } + } +} +#endif /* CONFIG_NET_IGMP */ diff --git a/nuttx/net/uip/uip_igmpsend.c b/nuttx/net/uip/uip_igmpsend.c new file mode 100755 index 0000000000..21fc2beb03 --- /dev/null +++ b/nuttx/net/uip/uip_igmpsend.c @@ -0,0 +1,182 @@ +/**************************************************************************** + * net/uip/uip_igmpsend.c + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "uip_internal.h" + +#ifdef CONFIG_NET_IGMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Debug */ + +#undef IGMP_DUMPPKT /* Define to enable packet dump */ + +#ifndef CONFIG_DEBUG_NET +# undef IGMP_DUMPPKT +#endif + +#ifdef IGMP_DUMPPKT +# define igmp_dumppkt(b,n) lib_dumpbuffer("IGMP", (FAR const uint8_t*)(b), (n)) +#else +# define igmp_dumppkt(b,n) +#endif + +/* Buffer layout */ + +#define RASIZE (4) +#define IGMPBUF ((struct uip_igmphdr_s *)&dev->d_buf[UIP_LLH_LEN]) + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static uint16_t uip_igmpchksum(FAR uint8_t *buffer, int buflen) +{ + uint16_t sum = uip_chksum((FAR uint16_t*)buffer, buflen); + return sum ? sum : 0xffff; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_igmpsend + * + * Description: + * Sends an IGMP IP packet on a network interface. This function constructs + * the IP header and calculates the IP header checksum. + * + * Parameters: + * dev - The device driver structure to use in the send operation. + * group - Describes the multicast group member and identifies the message + * to be sent. + * destipaddr - The IP address of the recipient of the message + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_igmpsend(FAR struct uip_driver_s *dev, FAR struct igmp_group_s *group, + FAR uip_ipaddr_t *destipaddr) +{ + nllvdbg("msgid: %02x destipaddr: %08x\n", group->msgid, (int)*destipaddr); + + /* The total length to send is the size of the IP and IGMP headers and 4 + * bytes for the ROUTER ALERT (and, eventually, the ethernet header) + */ + + dev->d_len = UIP_IPIGMPH_LEN; + + /* The total size of the data is the size of the IGMP header */ + + dev->d_sndlen = UIP_IGMPH_LEN; + + /* Add the router alert option */ + + IGMPBUF->ra[0] = HTONS(IPOPT_RA >> 16); + IGMPBUF->ra[1] = HTONS(IPOPT_RA & 0xffff); + + /* Initialize the IPv4 header */ + + IGMPBUF->vhl = 0x46; /* 4->IP; 6->24 bytes */ + IGMPBUF->tos = 0; + IGMPBUF->len[0] = (dev->d_len >> 8); + IGMPBUF->len[1] = (dev->d_len & 0xff); + ++g_ipid; + IGMPBUF->ipid[0] = g_ipid >> 8; + IGMPBUF->ipid[1] = g_ipid & 0xff; + IGMPBUF->ipoffset[0] = UIP_TCPFLAG_DONTFRAG >> 8; + IGMPBUF->ipoffset[1] = UIP_TCPFLAG_DONTFRAG & 0xff; + IGMPBUF->ttl = IGMP_TTL; + IGMPBUF->proto = UIP_PROTO_IGMP; + + uiphdr_ipaddr_copy(IGMPBUF->srcipaddr, &dev->d_ipaddr); + uiphdr_ipaddr_copy(IGMPBUF->destipaddr, destipaddr); + + /* Calculate IP checksum. */ + + IGMPBUF->ipchksum = 0; + IGMPBUF->ipchksum = ~uip_igmpchksum((FAR uint8_t *)IGMPBUF, UIP_IPH_LEN + RASIZE); + + /* Set up the IGMP message */ + + IGMPBUF->type = group->msgid; + IGMPBUF->maxresp = 0; + uiphdr_ipaddr_copy(IGMPBUF->grpaddr, &group->grpaddr); + + /* Calculate the IGMP checksum. */ + + IGMPBUF->chksum = 0; + IGMPBUF->chksum = ~uip_igmpchksum(&IGMPBUF->type, UIP_IPIGMPH_LEN); + + IGMP_STATINCR(uip_stat.igmp.poll_send); + IGMP_STATINCR(uip_stat.ip.sent); + + nllvdbg("Outgoing IGMP packet length: %d (%d)\n", + dev->d_len, (IGMPBUF->len[0] << 8) | IGMPBUF->len[1]); + igmp_dumppkt(RA, UIP_IPIGMPH_LEN + RASIZE); +} + +#endif /* CONFIG_NET_IGMP */ diff --git a/nuttx/net/uip/uip_igmptimer.c b/nuttx/net/uip/uip_igmptimer.c new file mode 100755 index 0000000000..27e2f9ff05 --- /dev/null +++ b/nuttx/net/uip/uip_igmptimer.c @@ -0,0 +1,257 @@ +/**************************************************************************** + * net/uip/uip_igmptimer.c + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * The NuttX implementation of IGMP was inspired by the IGMP add-on for the + * lwIP TCP/IP stack by Steve Reynolds: + * + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +#ifdef CONFIG_NET_IGMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Debug ********************************************************************/ + +#undef IGMP_GTMRDEBUG /* Define to enable detailed IGMP group debug */ + +#ifndef CONFIG_NET_IGMP +# undef IGMP_GTMRDEBUG +#endif + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef IGMP_GTMRDEBUG +# define gtmrdbg(format, arg...) ndbg(format, ##arg) +# define gtmrlldbg(format, arg...) nlldbg(format, ##arg) +# define gtmrvdbg(format, arg...) nvdbg(format, ##arg) +# define gtmrllvdbg(format, arg...) nllvdbg(format, ##arg) +# else +# define gtmrdbg(x...) +# define gtmrlldbg(x...) +# define gtmrvdbg(x...) +# define gtmrllvdbg(x...) +# endif +#else +# ifdef IGMP_GTMRDEBUG +# define gtmrdbg ndbg +# define gtmrlldbg nlldbg +# define gtmrvdbg nvdbg +# define gtmrllvdbg nllvdbg +# else +# define gtmrdbg (void) +# define gtmrlldbg (void) +# define gtmrvdbg (void) +# define gtmrllvdbg (void) +# endif +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_igmptimeout + * + * Description: + * Timeout watchdog handler. + * + * Assumptions: + * This function is called from the wdog timer handler which runs in the + * context of the timer interrupt handler. + * + ****************************************************************************/ + +static void uip_igmptimeout(int argc, uint32_t arg, ...) +{ + FAR struct igmp_group_s *group; + + /* If the state is DELAYING_MEMBER then we send a report for this group */ + + nllvdbg("Timeout!\n"); + group = (FAR struct igmp_group_s *)arg; + DEBUGASSERT(argc == 1 && group); + + /* If the group exists and is no an IDLE MEMBER, then it must be a DELAYING + * member. Race conditions are avoided because (1) the timer is not started + * until after the first IGMPv2_MEMBERSHIP_REPORT during the join, and (2) + * the timer is canceled before sending the IGMP_LEAVE_GROUP during a leave. + */ + + if (!IS_IDLEMEMBER(group->flags)) + { + /* Schedule (and forget) the Membership Report. NOTE: + * Since we are executing from a timer interrupt, we cannot wait + * for the message to be sent. + */ + + IGMP_STATINCR(uip_stat.igmp.report_sched); + uip_igmpschedmsg(group, IGMPv2_MEMBERSHIP_REPORT); + + /* Also note: The Membership Report is sent at most two times becasue + * the timer is not reset here. Hmm.. does this mean that the group + * is stranded if both reports were lost? This is consistent with the + * RFC that states: "To cover the possibility of the initial Membership + * Report being lost or damaged, it is recommended that it be repeated + * once or twice after shortdelays [Unsolicited Report Interval]..." + */ + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_igmpstarttimer + * + * Description: + * Start the IGMP timer. + * + * Assumptions: + * This function may be called from most any context. + * + ****************************************************************************/ + +int uip_decisec2tick(int decisecs) +{ + /* Convert the deci-second comparison value to clock ticks. The CLK_TCK + * value is the number of clock ticks per second; decisecs argument is the + * maximum delay in 100's of milliseconds. CLK_TCK/10 is then the number + * of clock ticks in 100 milliseconds. + */ + + return CLK_TCK * decisecs / 10; +} + +/**************************************************************************** + * Name: uip_igmpstartticks and uip_igmpstarttimer + * + * Description: + * Start the IGMP timer with differing time units (ticks or deciseconds). + * + * Assumptions: + * This function may be called from most any context. + * + ****************************************************************************/ + +void uip_igmpstartticks(FAR struct igmp_group_s *group, int ticks) +{ + int ret; + + /* Start the timer */ + + gtmrlldbg("ticks: %d\n", ticks); + ret = wd_start(group->wdog, ticks, uip_igmptimeout, 1, (uint32_t)group); + DEBUGASSERT(ret == OK); +} + +void uip_igmpstarttimer(FAR struct igmp_group_s *group, uint8_t decisecs) +{ + /* Convert the decisec value to system clock ticks and start the timer. + * Important!! this should be a random timer from 0 to decisecs + */ + + gtmrdbg("decisecs: %d\n", decisecs); + uip_igmpstartticks(group, uip_decisec2tick(decisecs)); +} + +/**************************************************************************** + * Name: uip_igmpcmptimer + * + * Description: + * Compare the timer remaining on the watching timer to the deci-second + * value. If maxticks > ticks-remaining, then (1) cancel the timer (to + * avoid race conditions) and return true. + * + * Assumptions: + * This function may be called from most any context. If true is retuend + * then the caller must call uip_igmpstartticks() to restart the timer + * + ****************************************************************************/ + +bool uip_igmpcmptimer(FAR struct igmp_group_s *group, int maxticks) +{ + uip_lock_t flags; + int remaining; + + /* Disable interrupts so that there is no race condition with the actual + * timer expiration. + */ + + flags = uip_lock(); + + /* Get the timer remaining on the watchdog. A time of <= zero means that + * the watchdog was never started. + */ + + remaining = wd_gettime(group->wdog); + + /* A remaining time of zero means that the watchdog was never started + * or has already expired. That case should be covered in the following + * test as well. + */ + + gtmrdbg("maxticks: %d remaining: %d\n", maxticks, remaining); + if (maxticks > remaining) + { + /* Cancel the watchdog timer and return true */ + + wd_cancel(group->wdog); + uip_unlock(flags); + return true; + } + + uip_unlock(flags); + return false; +} + +#endif /* CONFIG_NET_IGMP */ diff --git a/nuttx/net/uip/uip_initialize.c b/nuttx/net/uip/uip_initialize.c new file mode 100644 index 0000000000..8839836c44 --- /dev/null +++ b/nuttx/net/uip/uip_initialize.c @@ -0,0 +1,155 @@ +/**************************************************************************** + * net/uip/uip_initialize.c + * + * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Adapted for NuttX from logic in uIP which also has a BSD-like license: + * + * Original author Adam Dunkels + * Copyright () 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* IP/TCP/UDP/ICMP statistics for all network interfaces */ + +#ifdef CONFIG_NET_STATISTICS +struct uip_stats uip_stat; +#endif + +/* Increasing number used for the IP ID field. */ + +uint16_t g_ipid; + +const uip_ipaddr_t g_alloneaddr = +#ifdef CONFIG_NET_IPv6 + {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; +#else + 0xffffffff; +#endif + +const uip_ipaddr_t g_allzeroaddr = +#ifdef CONFIG_NET_IPv6 + {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}; +#else + 0x00000000; +#endif + +/* Reassembly timer (units: deci-seconds) */ + +#if UIP_REASSEMBLY && !defined(CONFIG_NET_IPv6) +uint8_t uip_reasstmr; +#endif + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_initialize + * + * Description: + * Perform initialization of the uIP layer + * + * Parameters: + * None + * + * Return: + * None + * + ****************************************************************************/ + +void uip_initialize(void) +{ + /* Initialize the locking facility */ + + uip_lockinit(); + + /* Initialize callback support */ + + uip_callbackinit(); + + /* Initialize the listening port structures */ + +#ifdef CONFIG_NET_TCP + uip_listeninit(); + + /* Initialize the TCP/IP connection structures */ + + uip_tcpinit(); + + /* Initialize the TCP/IP read-ahead buffering */ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + uip_tcpreadaheadinit(); +#endif +#endif /* CONFIG_NET_TCP */ + + /* Initialize the UDP connection structures */ + +#ifdef CONFIG_NET_UDP + uip_udpinit(); +#endif + + /* Initialize IGMP support */ + +#ifdef CONFIG_NET_IGMP + uip_igmpinit(); +#endif +} +#endif /* CONFIG_NET */ + diff --git a/nuttx/net/uip/uip_input.c b/nuttx/net/uip/uip_input.c new file mode 100644 index 0000000000..878b351a70 --- /dev/null +++ b/nuttx/net/uip/uip_input.c @@ -0,0 +1,545 @@ +/**************************************************************************** + * netuip/uip_input.c + * The uIP TCP/IP stack code. + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Adapted for NuttX from logic in uIP which also has a BSD-like license: + * + * uIP is an implementation of the TCP/IP protocol stack intended for + * small 8-bit and 16-bit microcontrollers. + * + * uIP provides the necessary protocols for Internet communication, + * with a very small code footprint and RAM requirements - the uIP + * code size is on the order of a few kilobytes and RAM usage is on + * the order of a few hundred bytes. + * + * Original author Adam Dunkels + * Copyright () 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * uIP is a small implementation of the IP, UDP and TCP protocols (as + * well as some basic ICMP stuff). The implementation couples the IP, + * UDP, TCP and the application layers very tightly. To keep the size + * of the compiled code down, this code frequently uses the goto + * statement. While it would be possible to break the uip_input() + * function into many smaller functions, this would increase the code + * size because of the overhead of parameter passing and the fact that + * the optimier would not be as efficient. + * + * The principle is that we have a small buffer, called the d_buf, + * in which the device driver puts an incoming packet. The TCP/IP + * stack parses the headers in the packet, and calls the + * application. If the remote host has sent data to the application, + * this data is present in the d_buf and the application read the + * data from there. It is up to the application to put this data into + * a byte stream if needed. The application will not be fed with data + * that is out of sequence. + * + * If the application whishes to send data to the peer, it should put + * its data into the d_buf. The d_appdata pointer points to the + * first available byte. The TCP/IP stack will calculate the + * checksums, and fill in the necessary header fields and finally send + * the packet back to the peer. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_NET_IPv6 +# include "uip_neighbor.h" +#endif /* CONFIG_NET_IPv6 */ + +#include "uip_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Macros. */ + +#define BUF ((struct uip_ip_hdr *)&dev->d_buf[UIP_LLH_LEN]) +#define FBUF ((struct uip_ip_hdr *)&uip_reassbuf[0]) + +/* IP fragment re-assembly */ + +#define IP_MF 0x20 +#define UIP_REASS_BUFSIZE (CONFIG_NET_BUFSIZE - UIP_LLH_LEN) +#define UIP_REASS_FLAG_LASTFRAG 0x01 + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +#if UIP_REASSEMBLY && !defined(CONFIG_NET_IPv6) +static uint8_t uip_reassbuf[UIP_REASS_BUFSIZE]; +static uint8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; +static const uint8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; +static uint16_t uip_reasslen; +static uint8_t uip_reassflags; +#endif /* UIP_REASSEMBLY */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_reass + * + * Description: + * IP fragment reassembly: not well-tested. + * + * Assumptions: + * + ****************************************************************************/ + +#if UIP_REASSEMBLY && !defined(CONFIG_NET_IPv6) +static uint8_t uip_reass(void) +{ + struct uip_ip_hdr *pbuf = BUF; + struct uip_ip_hdr *pfbuf = FBUF; + uint16_t offset; + uint16_t len; + uint16_t i; + + /* If uip_reasstmr is zero, no packet is present in the buffer, so we + * write the IP header of the fragment into the reassembly + * buffer. The timer is updated with the maximum age. + */ + + if (!uip_reasstmr) + { + memcpy(uip_reassbuf, &pbuf->vhl, UIP_IPH_LEN); + uip_reasstmr = UIP_REASS_MAXAGE; + uip_reassflags = 0; + + /* Clear the bitmap. */ + + memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap)); + } + + /* Check if the incoming fragment matches the one currently present + * in the reasembly buffer. If so, we proceed with copying the + * fragment into the buffer. + */ + + if (uiphdr_addr_cmp(pbuf->srcipaddr, pfbuf->srcipaddr) && + uiphdr_addr_cmp(pbuf->destipaddr == pfbuf->destipaddr) && + pbuf->g_ipid[0] == pfbuf->g_ipid[0] && pbuf->g_ipid[1] == pfbuf->g_ipid[1]) + { + len = (pbuf->len[0] << 8) + pbuf->len[1] - (pbuf->vhl & 0x0f) * 4; + offset = (((pbuf->ipoffset[0] & 0x3f) << 8) + pbuf->ipoffset[1]) * 8; + + /* If the offset or the offset + fragment length overflows the + * reassembly buffer, we discard the entire packet. + */ + + if (offset > UIP_REASS_BUFSIZE || offset + len > UIP_REASS_BUFSIZE) + { + uip_reasstmr = 0; + goto nullreturn; + } + + /* Copy the fragment into the reassembly buffer, at the right offset. */ + + memcpy(&uip_reassbuf[UIP_IPH_LEN + offset], (char *)pbuf + (int)((pbuf->vhl & 0x0f) * 4), len); + + /* Update the bitmap. */ + + if (offset / (8 * 8) == (offset + len) / (8 * 8)) + { + /* If the two endpoints are in the same byte, we only update that byte. */ + + uip_reassbitmap[offset / (8 * 8)] |= + bitmap_bits[(offset / 8 ) & 7] & ~bitmap_bits[((offset + len) / 8 ) & 7]; + + } + else + { + /* If the two endpoints are in different bytes, we update the bytes + * in the endpoints and fill the stuff inbetween with 0xff. + */ + + uip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8 ) & 7]; + for (i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) + { + uip_reassbitmap[i] = 0xff; + } + uip_reassbitmap[(offset + len) / (8 * 8)] |= ~bitmap_bits[((offset + len) / 8 ) & 7]; + } + + /* If this fragment has the More Fragments flag set to zero, we know that + * this is the last fragment, so we can calculate the size of the entire + * packet. We also set the IP_REASS_FLAG_LASTFRAG flag to indicate that + * we have received the final fragment. + */ + + if ((pbuf->ipoffset[0] & IP_MF) == 0) + { + uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; + uip_reasslen = offset + len; + } + + /* Finally, we check if we have a full packet in the buffer. We do this + * by checking if we have the last fragment and if all bits in the bitmap + * are set. + */ + + if (uip_reassflags & UIP_REASS_FLAG_LASTFRAG) + { + /* Check all bytes up to and including all but the last byte in + * the bitmap. + */ + + for (i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) + { + if (uip_reassbitmap[i] != 0xff) + { + goto nullreturn; + } + } + + /* Check the last byte in the bitmap. It should contain just the + * right amount of bits. + */ + + if (uip_reassbitmap[uip_reasslen / (8 * 8)] != (uint8_t)~bitmap_bits[uip_reasslen / 8 & 7]) + { + goto nullreturn; + } + + /* If we have come this far, we have a full packet in the buffer, + * so we allocate a pbuf and copy the packet into it. We also reset + * the timer. + */ + + uip_reasstmr = 0; + memcpy(pbuf, pfbuf, uip_reasslen); + + /* Pretend to be a "normal" (i.e., not fragmented) IP packet from + * now on. + */ + + pbuf->ipoffset[0] = pbuf->ipoffset[1] = 0; + pbuf->len[0] = uip_reasslen >> 8; + pbuf->len[1] = uip_reasslen & 0xff; + pbuf->ipchksum = 0; + pbuf->ipchksum = ~(uip_ipchksum(dev)); + + return uip_reasslen; + } + } + +nullreturn: + return 0; +} +#endif /* UIP_REASSEMBLY */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_input + * + * Description: + * + * Assumptions: + * + ****************************************************************************/ + +void uip_input(struct uip_driver_s *dev) +{ + struct uip_ip_hdr *pbuf = BUF; + uint16_t iplen; + + /* This is where the input processing starts. */ + +#ifdef CONFIG_NET_STATISTICS + uip_stat.ip.recv++; +#endif + + /* Start of IP input header processing code. */ + +#ifdef CONFIG_NET_IPv6 + /* Check validity of the IP header. */ + + if ((pbuf->vtc & 0xf0) != 0x60) + { + /* IP version and header length. */ + +#ifdef CONFIG_NET_STATISTICS + uip_stat.ip.drop++; + uip_stat.ip.vhlerr++; +#endif + nlldbg("Invalid IPv6 version: %d\n", pbuf->vtc >> 4); + goto drop; + } +#else /* CONFIG_NET_IPv6 */ + /* Check validity of the IP header. */ + + if (pbuf->vhl != 0x45) + { + /* IP version and header length. */ + +#ifdef CONFIG_NET_STATISTICS + uip_stat.ip.drop++; + uip_stat.ip.vhlerr++; +#endif + nlldbg("Invalid IP version or header length: %02x\n", pbuf->vhl); + goto drop; + } +#endif /* CONFIG_NET_IPv6 */ + + /* Check the size of the packet. If the size reported to us in d_len is + * smaller the size reported in the IP header, we assume that the packet + * has been corrupted in transit. If the size of d_len is larger than the + * size reported in the IP packet header, the packet has been padded and + * we set d_len to the correct value. + */ + +#ifdef CONFIG_NET_IPv6 + /* The length reported in the IPv6 header is the length of the payload + * that follows the header. However, uIP uses the d_len variable for + * holding the size of the entire packet, including the IP header. For + * IPv4 this is not a problem as the length field in the IPv4 header + * contains the length of the entire packet. But for IPv6 we need to add + * the size of the IPv6 header (40 bytes). + */ + + iplen = (pbuf->len[0] << 8) + pbuf->len[1] + UIP_IPH_LEN; +#else + iplen = (pbuf->len[0] << 8) + pbuf->len[1]; +#endif /* CONFIG_NET_IPv6 */ + + if (iplen <= dev->d_len) + { + dev->d_len = iplen; + } + else + { + nlldbg("IP packet shorter than length in IP header\n"); + goto drop; + } + +#ifndef CONFIG_NET_IPv6 + /* Check the fragment flag. */ + + if ((pbuf->ipoffset[0] & 0x3f) != 0 || pbuf->ipoffset[1] != 0) + { +#if UIP_REASSEMBLY + dev->d_len = uip_reass(); + if (dev->d_len == 0) + { + goto drop; + } +#else /* UIP_REASSEMBLY */ +#ifdef CONFIG_NET_STATISTICS + uip_stat.ip.drop++; + uip_stat.ip.fragerr++; +#endif + nlldbg("IP fragment dropped\n"); + goto drop; +#endif /* UIP_REASSEMBLY */ + } +#endif /* CONFIG_NET_IPv6 */ + + /* If IP broadcast support is configured, we check for a broadcast + * UDP packet, which may be destined to us (even if there is no IP + * address yet assigned to the device as is the case when we are + * negotiating over DHCP for an address). + */ + +#if defined(CONFIG_NET_BROADCAST) && defined(CONFIG_NET_UDP) + if (pbuf->proto == UIP_PROTO_UDP && +#ifndef CONFIG_NET_IPv6 + uip_ipaddr_cmp(uip_ip4addr_conv(pbuf->destipaddr), g_alloneaddr)) +#else + uip_ipaddr_cmp(pbuf->destipaddr, g_alloneaddr)) +#endif + { + uip_udpinput(dev); + return; + } + + /* In most other cases, the device must be assigned a non-zero IP + * address. Another exception is when CONFIG_NET_PINGADDRCONF is + * enabled... + */ + + else +#endif +#ifdef CONFIG_NET_ICMP + if (uip_ipaddr_cmp(dev->d_ipaddr, g_allzeroaddr)) + { + /* If we are configured to use ping IP address configuration and + * hasn't been assigned an IP address yet, we accept all ICMP + * packets. + */ + +#if defined(CONFIG_NET_PINGADDRCONF) && !defined(CONFIG_NET_IPv6) + if (pbuf->proto == UIP_PROTO_ICMP) + { + nlldbg("Possible ping config packet received\n"); + uip_icmpinput(dev); + goto done; + } + else +#endif + { + nlldbg("No IP address assigned\n"); + goto drop; + } + } + + /* Check if the packet is destined for out IP address */ + else +#endif + { + /* Check if the packet is destined for our IP address. */ +#ifndef CONFIG_NET_IPv6 + if (!uip_ipaddr_cmp(uip_ip4addr_conv(pbuf->destipaddr), dev->d_ipaddr)) + { +#ifdef CONFIG_NET_STATISTICS + uip_stat.ip.drop++; +#endif + goto drop; + } +#else /* CONFIG_NET_IPv6 */ + /* For IPv6, packet reception is a little trickier as we need to + * make sure that we listen to certain multicast addresses (all + * hosts multicast address, and the solicited-node multicast + * address) as well. However, we will cheat here and accept all + * multicast packets that are sent to the ff02::/16 addresses. + */ + + if (!uip_ipaddr_cmp(pbuf->destipaddr, dev->d_ipaddr) && + pbuf->destipaddr[0] != 0xff02) + { +#ifdef CONFIG_NET_STATISTICS + uip_stat.ip.drop++; +#endif + goto drop; + } +#endif /* CONFIG_NET_IPv6 */ + } + +#ifndef CONFIG_NET_IPv6 + if (uip_ipchksum(dev) != 0xffff) + { + /* Compute and check the IP header checksum. */ + +#ifdef CONFIG_NET_STATISTICS + uip_stat.ip.drop++; + uip_stat.ip.chkerr++; +#endif + nlldbg("Bad IP checksum\n"); + goto drop; + } +#endif /* CONFIG_NET_IPv6 */ + + /* Everything looks good so far. Now process the incoming packet + * according to the protocol. + */ + + switch (pbuf->proto) + { +#ifdef CONFIG_NET_TCP + case UIP_PROTO_TCP: /* TCP input */ + uip_tcpinput(dev); + break; +#endif + +#ifdef CONFIG_NET_UDP + case UIP_PROTO_UDP: /* UDP input */ + uip_udpinput(dev); + break; +#endif + + /* Check for ICMP input */ + +#ifdef CONFIG_NET_ICMP +#ifndef CONFIG_NET_IPv6 + case UIP_PROTO_ICMP: /* ICMP input */ +#else + case UIP_PROTO_ICMP6: /* ICMP6 input */ +#endif + uip_icmpinput(dev); + break; +#endif + + /* Check for ICMP input */ + +#ifdef CONFIG_NET_IGMP +#ifndef CONFIG_NET_IPv6 + case UIP_PROTO_IGMP: /* IGMP input */ + uip_igmpinput(dev); + break; +#endif +#endif + + default: /* Unrecognized/unsupported protocol */ +#ifdef CONFIG_NET_STATISTICS + uip_stat.ip.drop++; + uip_stat.ip.protoerr++; +#endif + + nlldbg("Unrecognized IP protocol\n"); + goto drop; + } + + /* Return and let the caller do any actual transmission. */ + + return; + +drop: + dev->d_len = 0; +} +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip_internal.h b/nuttx/net/uip/uip_internal.h new file mode 100644 index 0000000000..eee99a2224 --- /dev/null +++ b/nuttx/net/uip/uip_internal.h @@ -0,0 +1,272 @@ +/**************************************************************************** + * net/uip/uip_internal.h + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This logic was leveraged from uIP which also has a BSD-style license: + * + * Author Adam Dunkels + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __UIP_INTERNAL_H +#define __UIP_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Public Macro Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern const uip_ipaddr_t g_alloneaddr; +extern const uip_ipaddr_t g_allzeroaddr; + +/* Increasing number used for the IP ID field. */ + +extern uint16_t g_ipid; + +/* Reassembly timer (units: deci-seconds) */ + +#if UIP_REASSEMBLY && !defined(CONFIG_NET_IPv6) +extern uint8_t uip_reasstmr; +#endif + +/* List of applications waiting for ICMP ECHO REPLY */ + +#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) +extern struct uip_callback_s *g_echocallback; +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Defined in uip_callback.c ************************************************/ + +EXTERN void uip_callbackinit(void); +EXTERN FAR struct uip_callback_s *uip_callbackalloc(struct uip_callback_s **list); +EXTERN void uip_callbackfree(FAR struct uip_callback_s *cb, struct uip_callback_s **list); +EXTERN uint16_t uip_callbackexecute(FAR struct uip_driver_s *dev, void *pvconn, + uint16_t flags, FAR struct uip_callback_s *list); + +#ifdef CONFIG_NET_TCP +/* Defined in uip_tcpconn.c *************************************************/ + +EXTERN void uip_tcpinit(void); +EXTERN struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf); +EXTERN struct uip_conn *uip_nexttcpconn(struct uip_conn *conn); +EXTERN struct uip_conn *uip_tcplistener(uint16_t portno); +EXTERN struct uip_conn *uip_tcpaccept(struct uip_tcpip_hdr *buf); + +/* Defined in uip_tcpseqno.c ************************************************/ + +EXTERN void uip_tcpsetsequence(FAR uint8_t *seqno, uint32_t value); +EXTERN uint32_t uip_tcpgetsequence(FAR uint8_t *seqno); +EXTERN uint32_t uip_tcpaddsequence(FAR uint8_t *seqno, uint16_t len); +EXTERN void uip_tcpinitsequence(FAR uint8_t *seqno); +EXTERN void uip_tcpnextsequence(void); + +/* Defined in uip_tcppoll.c *************************************************/ + +EXTERN void uip_tcppoll(struct uip_driver_s *dev, struct uip_conn *conn); + +/* Defined in uip_udptimer.c ************************************************/ + +EXTERN void uip_tcptimer(struct uip_driver_s *dev, struct uip_conn *conn, int hsec); + +/* Defined in uip_listen.c **************************************************/ + +EXTERN void uip_listeninit(void); +EXTERN bool uip_islistener(uint16_t port); +EXTERN int uip_accept(struct uip_driver_s *dev, struct uip_conn *conn, uint16_t portno); + +/* Defined in uip_tcpsend.c *************************************************/ + +EXTERN void uip_tcpsend(struct uip_driver_s *dev, struct uip_conn *conn, + uint16_t flags, uint16_t len); +EXTERN void uip_tcpreset(struct uip_driver_s *dev); +EXTERN void uip_tcpack(struct uip_driver_s *dev, struct uip_conn *conn, + uint8_t ack); + +/* Defined in uip_tcpappsend.c **********************************************/ + +EXTERN void uip_tcpappsend(struct uip_driver_s *dev, struct uip_conn *conn, + uint16_t result); +EXTERN void uip_tcprexmit(struct uip_driver_s *dev, struct uip_conn *conn, + uint16_t result); + +/* Defined in uip_tcpinput.c ************************************************/ + +EXTERN void uip_tcpinput(struct uip_driver_s *dev); + +/* Defined in uip_tcpcallback.c *********************************************/ + +EXTERN uint16_t uip_tcpcallback(FAR struct uip_driver_s *dev, + FAR struct uip_conn *conn, uint16_t flags); +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 +EXTERN uint16_t uip_datahandler(FAR struct uip_conn *conn, + FAR uint8_t *buffer, uint16_t nbytes); +#endif + +/* Defined in uip_tcpreadahead.c ********************************************/ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 +EXTERN void uip_tcpreadaheadinit(void); +EXTERN struct uip_readahead_s *uip_tcpreadaheadalloc(void); +EXTERN void uip_tcpreadaheadrelease(struct uip_readahead_s *buf); +#endif /* CONFIG_NET_NTCP_READAHEAD_BUFFERS */ + +#endif /* CONFIG_NET_TCP */ + +#ifdef CONFIG_NET_UDP +/* Defined in uip_udpconn.c *************************************************/ + +EXTERN void uip_udpinit(void); +EXTERN struct uip_udp_conn *uip_udpactive(struct uip_udpip_hdr *buf); +EXTERN struct uip_udp_conn *uip_nextudpconn(struct uip_udp_conn *conn); + +/* Defined in uip_udppoll.c *************************************************/ + +EXTERN void uip_udppoll(struct uip_driver_s *dev, struct uip_udp_conn *conn); + +/* Defined in uip_udpsend.c *************************************************/ + +EXTERN void uip_udpsend(struct uip_driver_s *dev, struct uip_udp_conn *conn); + +/* Defined in uip_udpinput.c ************************************************/ + +EXTERN void uip_udpinput(struct uip_driver_s *dev); + +/* Defined in uip_udpcallback.c *********************************************/ + +EXTERN void uip_udpcallback(struct uip_driver_s *dev, + struct uip_udp_conn *conn, uint16_t flags); +#endif /* CONFIG_NET_UDP */ + +#ifdef CONFIG_NET_ICMP +/* Defined in uip_icmpinput.c ***********************************************/ + +EXTERN void uip_icmpinput(struct uip_driver_s *dev); + +#ifdef CONFIG_NET_ICMP_PING +/* Defined in uip_icmpoll.c *************************************************/ + +EXTERN void uip_icmppoll(struct uip_driver_s *dev); + +/* Defined in uip_icmsend.c *************************************************/ + +EXTERN void uip_icmpsend(struct uip_driver_s *dev, uip_ipaddr_t *destaddr); + +#endif /* CONFIG_NET_ICMP_PING */ +#endif /* CONFIG_NET_ICMP */ + +#ifdef CONFIG_NET_IGMP +/* Defined in uip_igmpinit.c ************************************************/ + +EXTERN void uip_igmpinit(void); + +/* Defined in uip_igmpinput.c ***********************************************/ + +EXTERN void uip_igmpinput(struct uip_driver_s *dev); + +/* Defined in uip_igmpgroup.c ***********************************************/ + +EXTERN void uip_grpinit(void); +EXTERN FAR struct igmp_group_s *uip_grpalloc(FAR struct uip_driver_s *dev, + FAR const uip_ipaddr_t *addr); +EXTERN FAR struct igmp_group_s *uip_grpfind(FAR struct uip_driver_s *dev, + FAR const uip_ipaddr_t *addr); +EXTERN FAR struct igmp_group_s *uip_grpallocfind(FAR struct uip_driver_s *dev, + FAR const uip_ipaddr_t *addr); +EXTERN void uip_grpfree(FAR struct uip_driver_s *dev, + FAR struct igmp_group_s *group); + +/* Defined in uip_igmpmsg.c **************************************************/ + +EXTERN void uip_igmpschedmsg(FAR struct igmp_group_s *group, uint8_t msgid); +EXTERN void uip_igmpwaitmsg(FAR struct igmp_group_s *group, uint8_t msgid); + +/* Defined in uip_igmppoll.c *************************************************/ + +EXTERN void uip_igmppoll(FAR struct uip_driver_s *dev); + +/* Defined in up_igmpsend.c **************************************************/ + +EXTERN void uip_igmpsend(FAR struct uip_driver_s *dev, + FAR struct igmp_group_s *group, + FAR uip_ipaddr_t *dest); + +/* Defined in uip_igmptimer.c ************************************************/ + +EXTERN int uip_decisec2tick(int decisecs); +EXTERN void uip_igmpstartticks(FAR struct igmp_group_s *group, int ticks); +EXTERN void uip_igmpstarttimer(FAR struct igmp_group_s *group, uint8_t decisecs); +EXTERN bool uip_igmpcmptimer(FAR struct igmp_group_s *group, int maxticks); + +/* Defined in uip_mcastmac ***************************************************/ + +EXTERN void uip_addmcastmac(FAR struct uip_driver_s *dev, FAR uip_ipaddr_t *ip); +EXTERN void uip_removemcastmac(FAR struct uip_driver_s *dev, FAR uip_ipaddr_t *ip); + +#endif /* CONFIG_NET_IGMP */ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_NET */ +#endif /* __UIP_INTERNAL_H */ diff --git a/nuttx/net/uip/uip_listen.c b/nuttx/net/uip/uip_listen.c new file mode 100644 index 0000000000..5f867fef2d --- /dev/null +++ b/nuttx/net/uip/uip_listen.c @@ -0,0 +1,288 @@ +/**************************************************************************** + * net/uip/uip_listen.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * A direct leverage of logic from uIP which also has b BSD style license + * + * Author: Adam Dunkels + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include + +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The uip_listenports list all currently listening ports. */ + +static struct uip_conn *uip_listenports[CONFIG_NET_MAX_LISTENPORTS]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_findlistener + * + * Description: + * Return the connection listener for connections on this port (if any) + * + * Assumptions: + * Called at interrupt level + * + ****************************************************************************/ + +struct uip_conn *uip_findlistener(uint16_t portno) +{ + int ndx; + + /* Examine each connection structure in each slot of the listener list */ + + for (ndx = 0; ndx < CONFIG_NET_MAX_LISTENPORTS; ndx++) + { + /* Is this slot assigned? If so, does the connection have the same + * local port number? + */ + + struct uip_conn *conn = uip_listenports[ndx]; + if (conn && conn->lport == portno) + { + /* Yes.. we found a listener on this port */ + + return conn; + } + } + + /* No listener for this port */ + + return NULL; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_listeninit + * + * Description: + * Setup the listening data structures + * + * Assumptions: + * Called early in the inialization phase while the system is still + * single-threaded. + * + ****************************************************************************/ + +void uip_listeninit(void) +{ + int ndx; + for (ndx = 0; ndx < CONFIG_NET_MAX_LISTENPORTS; ndx++) + { + uip_listenports[ndx] = NULL; + } +} + +/**************************************************************************** + * Function: uip_unlisten + * + * Description: + * Stop listening to the port bound to the specified TCP connection + * + * Assumptions: + * Called from normal user code. + * + ****************************************************************************/ + +int uip_unlisten(struct uip_conn *conn) +{ + uip_lock_t flags; + int ndx; + int ret = -EINVAL; + + flags = uip_lock(); + for (ndx = 0; ndx < CONFIG_NET_MAX_LISTENPORTS; ndx++) + { + if (uip_listenports[ndx] == conn) + { + uip_listenports[ndx] = NULL; + ret = OK; + break; + } + } + + uip_unlock(flags); + return ret; +} + +/**************************************************************************** + * Function: uip_listen + * + * Description: + * Start listening to the port bound to the specified TCP connection + * + * Assumptions: + * Called from normal user code. + * + ****************************************************************************/ + +int uip_listen(struct uip_conn *conn) +{ + uip_lock_t flags; + int ndx; + int ret; + + /* This must be done with interrupts disabled because the listener table + * is accessed from interrupt level as well. + */ + + flags = uip_lock(); + + /* First, check if there is already a socket listening on this port */ + + if (uip_islistener(conn->lport)) + { + /* Yes, then we must refuse this request */ + + ret = -EADDRINUSE; + } + else + { + /* Otherwise, save a reference to the connection structure in the + * "listener" list. + */ + + ret = -ENOBUFS; /* Assume failure */ + + /* Search all slots until an available slot is found */ + + for (ndx = 0; ndx < CONFIG_NET_MAX_LISTENPORTS; ndx++) + { + /* Is the next slot available? */ + + if (!uip_listenports[ndx]) + { + /* Yes.. we found it */ + + uip_listenports[ndx] = conn; + ret = OK; + break; + } + } + } + + uip_unlock(flags); + return ret; +} + +/**************************************************************************** + * Function: uip_islistener + * + * Description: + * Return true is there is a listener for the specified port + * + * Assumptions: + * Called at interrupt level + * + ****************************************************************************/ + +bool uip_islistener(uint16_t portno) +{ + return uip_findlistener(portno) != NULL; +} + +/**************************************************************************** + * Function: uip_accept + * + * Description: + * Accept the new connection for the specified listening port. + * + * Assumptions: + * Called at interrupt level + * + ****************************************************************************/ + +int uip_accept(struct uip_driver_s *dev, struct uip_conn *conn, + uint16_t portno) +{ + struct uip_conn *listener; + int ret = ERROR; + + /* The interrupt logic has already allocated and initialized a TCP + * connection -- now check there if is an application in place to accept the + * connection. + */ + + listener = uip_findlistener(portno); + if (listener) + { + /* Yes, there is a listener. Is it accepting connections now? */ + + if (listener->accept) + { + /* Yes.. accept the connection */ + + ret = listener->accept(listener, conn); + } +#ifdef CONFIG_NET_TCPBACKLOG + else + { + /* Add the connection to the backlog and notify any threads that + * may be waiting on poll()/select() that the connection is available. + */ + + ret = uip_backlogadd(listener, conn); + if (ret == OK) + { + (void)uip_tcpcallback(dev, listener, UIP_BACKLOG); + } + } +#endif + } + return ret; +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip_lock.c b/nuttx/net/uip/uip_lock.c new file mode 100644 index 0000000000..0e770cef79 --- /dev/null +++ b/nuttx/net/uip/uip_lock.c @@ -0,0 +1,218 @@ +/**************************************************************************** + * net/uip/uip_lock.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#if defined(CONFIG_NET) && defined(CONFIG_NET_NOINTS) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NO_HOLDER (pid_t)-1 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static sem_t g_uipsem; +static pid_t g_holder = NO_HOLDER; +static unsigned int g_count = 0; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_takesem + * + * Description: + * Take the semaphore + * + ****************************************************************************/ + +static void uip_takesem(void) +{ + while (sem_wait(&g_uipsem) != 0) + { + /* The only case that an error should occur here is if the wait was + * awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_lockinit + * + * Description: + * Initialize the locking facility + * + ****************************************************************************/ + +void uip_lockinit(void) +{ + sem_init(&g_uipsem, 0, 1); +} + +/**************************************************************************** + * Function: uip_lock + * + * Description: + * Take the lock + * + ****************************************************************************/ + +uip_lock_t uip_lock(void) +{ + pid_t me = getpid(); + + /* Does this thread already hold the semaphore? */ + + if (g_holder == me) + { + /* Yes.. just increment the reference count */ + + g_count++; + } + else + { + /* No.. take the semaphore (perhaps waiting) */ + + uip_takesem(); + + /* Now this thread holds the semaphore */ + + g_holder = me; + g_count = 1; + } + + return 0; +} + +/**************************************************************************** + * Function: uip_unlock + * + * Description: + * Release the lock. + * + ****************************************************************************/ + +void uip_unlock(uip_lock_t flags) +{ + DEBUGASSERT(g_holder == getpid() && g_count > 0); + + /* If the count would go to zero, then release the semaphore */ + + if (g_count == 1) + { + /* We no longer hold the semaphore */ + + g_holder = NO_HOLDER; + g_count = 0; + sem_post(&g_uipsem); + } + else + { + /* We still hold the semaphore. Just decrement the count */ + + g_count--; + } +} + +/**************************************************************************** + * Function: uip_lockedwait + * + * Description: + * Atomically wait for sem while temporarily releasing g_uipsem. + * + ****************************************************************************/ + +int uip_lockedwait(sem_t *sem) +{ + pid_t me = getpid(); + unsigned int count; + irqstate_t flags; + int ret; + + flags = irqsave(); /* No interrupts */ + sched_lock(); /* No context switches */ + if (g_holder == me) + { + /* Release the uIP semaphore, remembering the count */ + + count = g_count; + g_holder = NO_HOLDER; + g_count = 0; + sem_post(&g_uipsem); + + /* Now take the semaphore */ + + ret = sem_wait(sem); + + /* Recover the uIP semaphore at the proper count */ + + uip_takesem(); + g_holder = me; + g_count = count; + } + else + { + ret = sem_wait(sem); + } + + sched_unlock(); + irqrestore(flags); + return ret; + } + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip_mcastmac.c b/nuttx/net/uip/uip_mcastmac.c new file mode 100755 index 0000000000..7795becab5 --- /dev/null +++ b/nuttx/net/uip/uip_mcastmac.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * net/uip/uip_mcastmac.c + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * The NuttX implementation of IGMP was inspired by the IGMP add-on for the + * lwIP TCP/IP stack by Steve Reynolds: + * + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "uip_internal.h" + +#ifdef CONFIG_NET_IGMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_mcastmac + * + * Description: + * Given an IP address (in network order), create a IGMP multicast MAC + * address. + * + ****************************************************************************/ + +static void uip_mcastmac(uip_ipaddr_t *ip, FAR uint8_t *mac) +{ + /* This mapping is from the IETF IN RFC 1700 */ + + mac[0] = 0x01; + mac[1] = 0x00; + mac[2] = 0x5e; + mac[3] = ip4_addr2(*ip) & 0x7f; + mac[4] = ip4_addr3(*ip); + mac[5] = ip4_addr4(*ip); + + nvdbg("IP: %08x -> MAC: %02x%02x%02x%02x%02x%02x\n", + *ip, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_addmcastmac + * + * Description: + * Add an IGMP MAC address to the device's MAC filter table. + * + ****************************************************************************/ + +void uip_addmcastmac(FAR struct uip_driver_s *dev, FAR uip_ipaddr_t *ip) +{ + uint8_t mcastmac[6]; + + nvdbg("Adding: IP %08x\n", *ip); + if (dev->d_addmac) + { + uip_mcastmac(ip, mcastmac); + dev->d_addmac(dev, mcastmac); + } +} + +/**************************************************************************** + * Name: uip_removemcastmac + * + * Description: + * Remove an IGMP MAC address from the device's MAC filter table. + * + ****************************************************************************/ + +void uip_removemcastmac(FAR struct uip_driver_s *dev, FAR uip_ipaddr_t *ip) +{ + uint8_t mcastmac[6]; + + nvdbg("Removing: IP %08x\n", *ip); + if (dev->d_rmmac) + { + uip_mcastmac(ip, mcastmac); + dev->d_rmmac(dev, mcastmac); + } +} + +#endif /* CONFIG_NET_IGMP */ diff --git a/nuttx/net/uip/uip_neighbor.c b/nuttx/net/uip/uip_neighbor.c new file mode 100644 index 0000000000..82fb9a845a --- /dev/null +++ b/nuttx/net/uip/uip_neighbor.c @@ -0,0 +1,162 @@ +/* + * uip_neighbor.c + * Database of link-local neighbors, used by IPv6 code and to be used by + * a future ARP code rewrite. + * + * Author: Adam Dunkels + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + */ + +#include +#include + +#include "uip_neighbor.h" + +#define MAX_TIME 128 + +#ifdef UIP_NEIGHBOR_CONF_ENTRIES +#define ENTRIES UIP_NEIGHBOR_CONF_ENTRIES +#else /* UIP_NEIGHBOR_CONF_ENTRIES */ +#define ENTRIES 8 +#endif /* UIP_NEIGHBOR_CONF_ENTRIES */ + +struct neighbor_entry +{ + uip_ipaddr_t ipaddr; + struct uip_neighbor_addr addr; + uint8_t time; +}; +static struct neighbor_entry entries[ENTRIES]; + +void uip_neighbor_init(void) +{ + int i; + + for(i = 0; i < ENTRIES; ++i) + { + entries[i].time = MAX_TIME; + } +} + +void uip_neighbor_periodic(void) +{ + int i; + + for(i = 0; i < ENTRIES; ++i) + { + if (entries[i].time < MAX_TIME) + { + entries[i].time++; + } + } +} + +void uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr) +{ + uint8_t oldest_time; + int oldest; + int i; + + nlldbg("Add neighbor: %02x:%02x:%02x:%02x:%02x:%02x\n", + addr->addr.ether_addr_octet[0], addr->addr.ether_addr_octet[1], + addr->addr.ether_addr_octet[2], addr->addr.ether_addr_octet[3], + addr->addr.ether_addr_octet[4], addr->addr.ether_addr_octet[5]); + + /* Find the first unused entry or the oldest used entry. */ + + oldest_time = 0; + oldest = 0; + for (i = 0; i < ENTRIES; ++i) + { + if (entries[i].time == MAX_TIME) + { + oldest = i; + break; + } + if (uip_ipaddr_cmp(entries[i].ipaddr, addr)) + { + oldest = i; + break; + } + if (entries[i].time > oldest_time) + { + oldest = i; + oldest_time = entries[i].time; + } + } + + /* Use the oldest or first free entry (either pointed to by the + * "oldest" variable). + */ + + entries[oldest].time = 0; + uip_ipaddr_copy(entries[oldest].ipaddr, ipaddr); + memcpy(&entries[oldest].addr, addr, sizeof(struct uip_neighbor_addr)); +} + +static struct neighbor_entry *find_entry(uip_ipaddr_t ipaddr) +{ + int i; + + for(i = 0; i < ENTRIES; ++i) + { + if (uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) + { + return &entries[i]; + } + } + return NULL; +} + +void uip_neighbor_update(uip_ipaddr_t ipaddr) +{ + struct neighbor_entry *e; + + e = find_entry(ipaddr); + if (e != NULL) + { + e->time = 0; + } +} + +struct uip_neighbor_addr *uip_neighbor_lookup(uip_ipaddr_t ipaddr) +{ + struct neighbor_entry *e; + + e = find_entry(ipaddr); + if (e != NULL) + { + nlldbg("Lookup neighbor: %02x:%02x:%02x:%02x:%02x:%02x\n", + e->addr.addr.ether_addr_octet[0], e->addr.addr.ether_addr_octet[1], + e->addr.addr.ether_addr_octet[2], e->addr.addr.ether_addr_octet[3], + e->addr.addr.ether_addr_octet[4], e->addr.addr.ether_addr_octet[5]); + + return &e->addr; + } + return NULL; +} diff --git a/nuttx/net/uip/uip_neighbor.h b/nuttx/net/uip/uip_neighbor.h new file mode 100644 index 0000000000..eac08f9382 --- /dev/null +++ b/nuttx/net/uip/uip_neighbor.h @@ -0,0 +1,61 @@ +/* net/uip/uip_neighbor.h + * Header file for database of link-local neighbors, used by IPv6 code and + * to be used by future ARP code. + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * A direct leverage of logic from uIP which also has b BSD style license + * + * Author: Adam Dunkels + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __UIP_NEIGHBOR_H__ +#define __UIP_NEIGHBOR_H__ + +#include +#include +#include + +struct uip_neighbor_addr +{ +#if UIP_NEIGHBOR_CONF_ADDRTYPE + UIP_NEIGHBOR_CONF_ADDRTYPE addr; +#else + struct ether_addr addr; +#endif +}; + +void uip_neighbor_init(void); +void uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr); +void uip_neighbor_update(uip_ipaddr_t ipaddr); +struct uip_neighbor_addr *uip_neighbor_lookup(uip_ipaddr_t ipaddr); +void uip_neighbor_periodic(void); + +#endif /* __UIP-NEIGHBOR_H__ */ diff --git a/nuttx/net/uip/uip_poll.c b/nuttx/net/uip/uip_poll.c new file mode 100644 index 0000000000..8c56e7bf6c --- /dev/null +++ b/nuttx/net/uip/uip_poll.c @@ -0,0 +1,353 @@ +/**************************************************************************** + * net/uip/uip_poll.c + * + * Copyright (C) 2007-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_pollicmp + * + * Description: + * Poll all UDP connections for available packets to send. + * + * Assumptions: + * This function is called from the CAN device driver and may be called from + * the timer interrupt/watchdog handle level. + * + ****************************************************************************/ + +#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) +static inline int uip_pollicmp(struct uip_driver_s *dev, uip_poll_callback_t callback) +{ + /* Perform the UDP TX poll */ + + uip_icmppoll(dev); + + /* Call back into the driver */ + + return callback(dev); +} +#endif /* CONFIG_NET_ICMP && CONFIG_NET_ICMP_PING */ + +/**************************************************************************** + * Function: uip_polligmp + * + * Description: + * Poll all UDP connections for available packets to send. + * + * Assumptions: + * This function is called from the CAN device driver and may be called from + * the timer interrupt/watchdog handle level. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static inline int uip_polligmp(struct uip_driver_s *dev, uip_poll_callback_t callback) +{ + /* Perform the UDP TX poll */ + + uip_igmppoll(dev); + + /* Call back into the driver */ + + return callback(dev); +} +#endif /* CONFIG_NET_IGMP */ + +/**************************************************************************** + * Function: uip_polludpconnections + * + * Description: + * Poll all UDP connections for available packets to send. + * + * Assumptions: + * This function is called from the CAN device driver and may be called from + * the timer interrupt/watchdog handle level. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_UDP +static int uip_polludpconnections(struct uip_driver_s *dev, + uip_poll_callback_t callback) +{ + struct uip_udp_conn *udp_conn = NULL; + int bstop = 0; + + /* Traverse all of the allocated UDP connections and perform the poll action */ + + while (!bstop && (udp_conn = uip_nextudpconn(udp_conn))) + { + /* Perform the UDP TX poll */ + + uip_udppoll(dev, udp_conn); + + /* Call back into the driver */ + + bstop = callback(dev); + } + + return bstop; +} +#endif /* CONFIG_NET_UDP */ + +/**************************************************************************** + * Function: uip_polltcpconnections + * + * Description: + * Poll all UDP connections for available packets to send. + * + * Assumptions: + * This function is called from the CAN device driver and may be called from + * the timer interrupt/watchdog handle level. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +static inline int uip_polltcpconnections(struct uip_driver_s *dev, + uip_poll_callback_t callback) +{ + struct uip_conn *conn = NULL; + int bstop = 0; + + /* Traverse all of the active TCP connections and perform the poll action */ + + while (!bstop && (conn = uip_nexttcpconn(conn))) + { + /* Perform the TCP TX poll */ + + uip_tcppoll(dev, conn); + + /* Call back into the driver */ + + bstop = callback(dev); + } + + return bstop; +} +#else +# define uip_polltcpconnections(dev, callback) (0) +#endif + +/**************************************************************************** + * Function: uip_polltcptimer + * + * Description: + * The TCP timer has expired. Update TCP timing state in each active, + * TCP connection. + * + * Assumptions: + * This function is called from the CAN device driver and may be called from + * the timer interrupt/watchdog handle level. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +static inline int uip_polltcptimer(struct uip_driver_s *dev, + uip_poll_callback_t callback, int hsec) +{ + struct uip_conn *conn = NULL; + int bstop = 0; + + /* Traverse all of the active TCP connections and perform the poll action */ + + while (!bstop && (conn = uip_nexttcpconn(conn))) + { + /* Perform the TCP timer poll */ + + uip_tcptimer(dev, conn, hsec); + + /* Call back into the driver */ + + bstop = callback(dev); + } + + return bstop; +} +#else +# define uip_polltcptimer(dev, callback, hsec) (0) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_poll + * + * Description: + * This function will traverse each active uIP connection structure and + * will perform TCP and UDP polling operations. uip_poll() may be called + * asychronously with the network drvier can accept another outgoing packet. + * + * This function will call the provided callback function for every active + * connection. Polling will continue until all connections have been polled + * or until the user-suplied function returns a non-zero value (which it + * should do only if it cannot accept further write data). + * + * When the callback function is called, there may be an outbound packet + * waiting for service in the uIP packet buffer, and if so the d_len field + * is set to a value larger than zero. The device driver should then send + * out the packet. + * + * Assumptions: + * This function is called from the CAN device driver and may be called from + * the timer interrupt/watchdog handle level. + * + ****************************************************************************/ + +int uip_poll(struct uip_driver_s *dev, uip_poll_callback_t callback) +{ + int bstop; + + /* Check for pendig IGMP messages */ + +#ifdef CONFIG_NET_IGMP + bstop = uip_polligmp(dev, callback); + if (!bstop) +#endif + { + /* Traverse all of the active TCP connections and perform the poll action */ + + bstop = uip_polltcpconnections(dev, callback); + if (!bstop) + { +#ifdef CONFIG_NET_UDP + /* Traverse all of the allocated UDP connections and perform the poll action */ + + bstop = uip_polludpconnections(dev, callback); + if (!bstop) +#endif + { +#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) + /* Traverse all of the tasks waiting to send an ICMP ECHO request */ + + bstop = uip_pollicmp(dev, callback); +#endif + } + } + } + + return bstop; +} + +/**************************************************************************** + * Function: uip_timer + * + * Description: + * These function will traverse each active uIP connection structure and + * perform TCP timer operations (and UDP polling operations). The Ethernet + * driver MUST implement logic to periodically call uip_timer(). + * + * This function will call the provided callback function for every active + * connection. Polling will continue until all connections have been polled + * or until the user-suplied function returns a non-zero value (which it + * should do only if it cannot accept further write data). + * + * When the callback function is called, there may be an outbound packet + * waiting for service in the uIP packet buffer, and if so the d_len field + * is set to a value larger than zero. The device driver should then send + * out the packet. + * + * Assumptions: + * This function is called from the CAN device driver and may be called from + * the timer interrupt/watchdog handle level. + * + ****************************************************************************/ + +int uip_timer(struct uip_driver_s *dev, uip_poll_callback_t callback, int hsec) +{ + int bstop; + + /* Increment the timer used by the IP reassembly logic */ + +#if UIP_REASSEMBLY + if (uip_reasstmr != 0 && uip_reasstmr < UIP_REASS_MAXAGE) + { + uip_reasstmr += hsec; + } +#endif /* UIP_REASSEMBLY */ + + /* Check for pendig IGMP messages */ + +#ifdef CONFIG_NET_IGMP + bstop = uip_polligmp(dev, callback); + if (!bstop) +#endif + { + /* Traverse all of the active TCP connections and perform the timer action */ + + bstop = uip_polltcptimer(dev, callback, hsec); + if (!bstop) + { + /* Traverse all of the allocated UDP connections and perform the poll action */ + +#ifdef CONFIG_NET_UDP + bstop = uip_polludpconnections(dev, callback); + if (!bstop) +#endif + { +#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) + /* Traverse all of the tasks waiting to send an ICMP ECHO request */ + + bstop = uip_pollicmp(dev, callback); +#endif + } + } + } + + return bstop; +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip_send.c b/nuttx/net/uip/uip_send.c new file mode 100644 index 0000000000..fd0f4f7da2 --- /dev/null +++ b/nuttx/net/uip/uip_send.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * net/uip/uip_send.c + * + * Copyright (C) 2007i, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Based in part on uIP which also has a BSD stylie license: + * + * Author: Adam Dunkels + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_send + * + * Description: + * Called from socket logic in response to a xmit or poll request from the + * the network interface driver. + * + * Assumptions: + * Called from the interrupt level or, at a mimimum, with interrupts + * disabled. + * + ****************************************************************************/ + +void uip_send(struct uip_driver_s *dev, const void *buf, int len) +{ + /* Some sanity checks -- note that the actually available length in the + * buffer is considerably less than CONFIG_NET_BUFSIZE. + */ + + if (dev && len > 0 && len < CONFIG_NET_BUFSIZE) + { + memcpy(dev->d_snddata, buf, len); + dev->d_sndlen = len; + } +} diff --git a/nuttx/net/uip/uip_setipid.c b/nuttx/net/uip/uip_setipid.c new file mode 100644 index 0000000000..f9d13cc9d7 --- /dev/null +++ b/nuttx/net/uip/uip_setipid.c @@ -0,0 +1,78 @@ +/**************************************************************************** + * net/uip/uip_setipid.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include + +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_setipid + * + * Description: + * This function may be used at boot time to set the initial ip_id. + * + * Assumptions: + * + ****************************************************************************/ + +void uip_setipid(uint16_t id) +{ + g_ipid = id; +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip_tcpappsend.c b/nuttx/net/uip/uip_tcpappsend.c new file mode 100644 index 0000000000..d8a1875034 --- /dev/null +++ b/nuttx/net/uip/uip_tcpappsend.c @@ -0,0 +1,215 @@ +/**************************************************************************** + * net/uip/uip_tcpappsend.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Adapted for NuttX from logic in uIP which also has a BSD-like license: + * + * Original author Adam Dunkels + * Copyright () 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) + +#include +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_tcpappsend + * + * Description: + * Handle application or TCP protocol response. If this function is called + * with dev->d_sndlen > 0, then this is an application attempting to send + * packet. + * + * Parameters: + * dev - The device driver structure to use in the send operation + * conn - The TCP connection structure holding connection information + * result - App result event sent + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_tcpappsend(struct uip_driver_s *dev, struct uip_conn *conn, + uint16_t result) +{ + /* Handle the result based on the application response */ + + nllvdbg("result: %04x d_sndlen: %d conn->unacked: %d\n", + result, dev->d_sndlen, conn->unacked); + + /* Check for connection aborted */ + + if ((result & UIP_ABORT) != 0) + { + dev->d_sndlen = 0; + conn->tcpstateflags = UIP_CLOSED; + nllvdbg("TCP state: UIP_CLOSED\n"); + + uip_tcpsend(dev, conn, TCP_RST | TCP_ACK, UIP_IPTCPH_LEN); + } + + /* Check for connection closed */ + + else if ((result & UIP_CLOSE) != 0) + { + conn->tcpstateflags = UIP_FIN_WAIT_1; + conn->unacked = 1; + conn->nrtx = 0; + nllvdbg("TCP state: UIP_FIN_WAIT_1\n"); + + dev->d_sndlen = 0; + uip_tcpsend(dev, conn, TCP_FIN | TCP_ACK, UIP_IPTCPH_LEN); + } + + /* None of the above */ + + else + { + /* If d_sndlen > 0, the application has data to be sent. */ + + if (dev->d_sndlen > 0) + { + /* Remember how much data we send out now so that we know + * when everything has been acknowledged. Just increment the amount + * of data sent. This will be needed in sequence number calculations + * and we know that this is not a re-tranmission. Retransmissions + * do not go through this path. + */ + + conn->unacked += dev->d_sndlen; + + /* The application cannot send more than what is allowed by the + * MSS (the minumum of the MSS and the available window). + */ + + DEBUGASSERT(dev->d_sndlen <= conn->mss); + } + + /* Then handle the rest of the operation just as for the rexmit case */ + + conn->nrtx = 0; + uip_tcprexmit(dev, conn, result); + } +} + +/**************************************************************************** + * Name: uip_tcprexmit + * + * Description: + * Handle application retransmission + * + * Parameters: + * dev - The device driver structure to use in the send operation + * conn - The TCP connection structure holding connection information + * result - App result event sent + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_tcprexmit(struct uip_driver_s *dev, struct uip_conn *conn, + uint16_t result) +{ + nllvdbg("result: %04x d_sndlen: %d conn->unacked: %d\n", + result, dev->d_sndlen, conn->unacked); + + dev->d_appdata = dev->d_snddata; + + /* If the application has data to be sent, or if the incoming packet had + * new data in it, we must send out a packet. + */ + + if (dev->d_sndlen > 0 && conn->unacked > 0) + { + /* We always set the ACK flag in response packets adding the length of + * the IP and TCP headers. + */ + + uip_tcpsend(dev, conn, TCP_ACK | TCP_PSH, dev->d_sndlen + UIP_TCPIP_HLEN); + } + + /* If there is no data to send, just send out a pure ACK if one is requested`. */ + + else if ((result & UIP_SNDACK) != 0) + { + uip_tcpsend(dev, conn, TCP_ACK, UIP_TCPIP_HLEN); + } + + /* There is nothing to do -- drop the packet */ + + else + { + dev->d_len = 0; + } +} +#endif /* CONFIG_NET && CONFIG_NET_TCP */ diff --git a/nuttx/net/uip/uip_tcpbacklog.c b/nuttx/net/uip/uip_tcpbacklog.c new file mode 100644 index 0000000000..459d543128 --- /dev/null +++ b/nuttx/net/uip/uip_tcpbacklog.c @@ -0,0 +1,403 @@ +/**************************************************************************** + * net/uip/uip_tcpbacklog.c + * + * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) && defined(CONFIG_NET_TCPBACKLOG) + +#include +#include +#include +#include +#include + +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_backlogcreate + * + * Description: + * Called from the listen() logic to setup the backlog as specified in the + * the listen arguments. + * + * Assumptions: + * Called from normal user code. Interrupts may be disabled. + * + ****************************************************************************/ + +int uip_backlogcreate(FAR struct uip_conn *conn, int nblg) +{ + FAR struct uip_backlog_s *bls = NULL; + FAR struct uip_blcontainer_s *blc; + uip_lock_t flags; + int size; + int offset; + int i; + + nllvdbg("conn=%p nblg=%d\n", conn, nblg); + +#ifdef CONFIG_DEBUG + if (!conn) + { + return -EINVAL; + } +#endif + + /* Then allocate the backlog as requested */ + + if (nblg > 0) + { + /* Align the list of backlog structures to 32-bit boundaries. This + * may be excessive on 24-16-bit address machines; and insufficient + * on 64-bit address machines -- REVISIT + */ + + offset = (sizeof(struct uip_backlog_s) + 3) & ~3; + + /* Then determine the full size of the allocation include the + * uip_backlog_s, a pre-allocated array of struct uip_blcontainer_s + * and alignement padding + */ + + size = offset + nblg * sizeof(struct uip_blcontainer_s); + + /* Then allocate that much */ + + bls = (FAR struct uip_backlog_s *)zalloc(size); + if (!bls) + { + nlldbg("Failed to allocate backlog\n"); + return -ENOMEM; + } + + /* Then add all of the pre-allocated containers to the free list */ + + blc = (FAR struct uip_blcontainer_s*)(((FAR uint8_t*)bls) + offset); + for (i = 0; i < nblg; i++) + { + sq_addfirst(&blc->bc_node, &bls->bl_free); + } + } + + /* Destroy any existing backlog (shouldn't be any) */ + + flags = uip_lock(); + uip_backlogdestroy(conn); + + /* Now install the backlog tear-off in the connection. NOTE that bls may + * actually be NULL if nblg is <= 0; In that case, we are disabling backlog + * support. Since interrupts are disabled, destroying the old backlog and + * replace it with the new is an atomic operation + */ + + conn->backlog = bls; + uip_unlock(flags); + return OK; +} + +/**************************************************************************** + * Function: uip_backlogdestroy + * + * Description: + * (1) Called from uip_tcpfree() whenever a connection is freed. + * (2) Called from uip_backlogcreate() to destroy any old backlog + * + * NOTE: This function may re-enter uip_tcpfree when a connection that + * is freed that has pending connections. + * + * Assumptions: + * The caller has disabled interrupts so that there can be no conflict + * with ongoing, interrupt driven activity + * + ****************************************************************************/ + +int uip_backlogdestroy(FAR struct uip_conn *conn) +{ + FAR struct uip_backlog_s *blg; + FAR struct uip_blcontainer_s *blc; + FAR struct uip_conn *blconn; + + nllvdbg("conn=%p\n", conn); + +#ifdef CONFIG_DEBUG + if (!conn) + { + return -EINVAL; + } +#endif + + /* Make sure that the connection has a backlog to be destroyed */ + + if (conn->backlog) + { + /* Remove the backlog structure reference from the connection */ + + blg = conn->backlog; + conn->backlog = NULL; + + /* Handle any pending connections in the backlog */ + + while ((blc = (FAR struct uip_blcontainer_s*)sq_remfirst(&blg->bl_pending)) != NULL) + { + blconn = blc->bc_conn; + if (blconn) + { + /* REVISIT -- such connections really need to be gracefully closed */ + + blconn->blparent = NULL; + blconn->backlog = NULL; + blconn->crefs = 0; + uip_tcpfree(blconn); + } + } + + /* Then free the entire backlog structure */ + + free(blg); + } + + return OK; +} + +/**************************************************************************** + * Function: uip_backlogadd + * + * Description: + * Called uip_listen when a new connection is made with a listener socket + * but when there is no accept() in place to receive the connection. This + * function adds the new connection to the backlog. + * + * Assumptions: + * Called from the interrupt level with interrupts disabled + * + ****************************************************************************/ + +int uip_backlogadd(FAR struct uip_conn *conn, FAR struct uip_conn *blconn) +{ + FAR struct uip_backlog_s *bls; + FAR struct uip_blcontainer_s *blc; + int ret = -EINVAL; + + nllvdbg("conn=%p blconn=%p\n", conn, blconn); + +#ifdef CONFIG_DEBUG + if (!conn) + { + return -EINVAL; + } +#endif + + bls = conn->backlog; + if (bls && blconn) + { + /* Allocate a container for the connection from the free list */ + + blc = (FAR struct uip_blcontainer_s *)sq_remfirst(&bls->bl_free); + if (!blc) + { + nlldbg("Failed to allocate container\n"); + ret = -ENOMEM; + } + else + { + /* Save the connection reference in the container and put the + * container at the end of the pending connection list (FIFO). + */ + + blc->bc_conn = blconn; + sq_addlast(&blc->bc_node, &bls->bl_pending); + ret = OK; + } + } + return ret; +} + +/**************************************************************************** + * Function: uip_backlogremove + * + * Description: + * Called from poll(). Before waiting for a new connection, poll will + * call this API to see if there are pending connections in the backlog. + * + * Assumptions: + * Called from normal user code, but with interrupts disabled, + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +bool uip_backlogavailable(FAR struct uip_conn *conn) +{ + return (conn && conn->backlog && !sq_empty(&conn->backlog->bl_pending)); +} +#endif + +/**************************************************************************** + * Function: uip_backlogremove + * + * Description: + * Called from accept(). Before waiting for a new connection, accept will + * call this API to see if there are pending connections in the backlog. + * + * Assumptions: + * Called from normal user code, but with interrupts disabled, + * + ****************************************************************************/ + +struct uip_conn *uip_backlogremove(FAR struct uip_conn *conn) +{ + FAR struct uip_backlog_s *bls; + FAR struct uip_blcontainer_s *blc; + FAR struct uip_conn *blconn = NULL; + +#ifdef CONFIG_DEBUG + if (!conn) + { + return NULL; + } +#endif + + bls = conn->backlog; + if (bls) + { + /* Remove the a container at the head of the pending connection list + * (FIFO) + */ + + blc = (FAR struct uip_blcontainer_s *)sq_remfirst(&bls->bl_pending); + if (blc) + { + /* Extract the connection reference from the container and put + * container in the free list + */ + + blconn = blc->bc_conn; + blc->bc_conn = NULL; + sq_addlast(&blc->bc_node, &bls->bl_free); + } + } + + nllvdbg("conn=%p, returning %p\n", conn, blconn); + return blconn; +} + +/**************************************************************************** + * Function: uip_backlogdelete + * + * Description: + * Called from uip_tcpfree() when a connection is freed that this also + * retained in the pending connectino list of a listener. We simply need + * to remove the defunct connecton from the list. + * + * Assumptions: + * Called from the interrupt level with interrupts disabled + * + ****************************************************************************/ + +int uip_backlogdelete(FAR struct uip_conn *conn, FAR struct uip_conn *blconn) +{ + FAR struct uip_backlog_s *bls; + FAR struct uip_blcontainer_s *blc; + FAR struct uip_blcontainer_s *prev; + + nllvdbg("conn=%p blconn=%p\n", conn, blconn); + +#ifdef CONFIG_DEBUG + if (!conn) + { + return -EINVAL; + } +#endif + + bls = conn->backlog; + if (bls) + { + /* Find the container hold the connection */ + + for (blc = (FAR struct uip_blcontainer_s *)sq_peek(&bls->bl_pending), prev = NULL; + blc; + prev = blc, blc = (FAR struct uip_blcontainer_s *)sq_next(&blc->bc_node)) + { + if (blc->bc_conn == blconn) + { + if (prev) + { + /* Remove the a container from the middle of the list of + * pending connections + */ + + (void)sq_remafter(&prev->bc_node, &bls->bl_pending); + } + else + { + /* Remove the a container from the head of the list of + * pending connections + */ + + (void)sq_remfirst(&bls->bl_pending); + } + + /* Put container in the free list */ + + blc->bc_conn = NULL; + sq_addlast(&blc->bc_node, &bls->bl_free); + return OK; + } + } + + nlldbg("Failed to find pending connection\n"); + return -EINVAL; + } + return OK; +} + +#endif /* CONFIG_NET && CONFIG_NET_TCP && CONFIG_NET_TCPBACKLOG */ diff --git a/nuttx/net/uip/uip_tcpcallback.c b/nuttx/net/uip/uip_tcpcallback.c new file mode 100644 index 0000000000..9ce8eb132a --- /dev/null +++ b/nuttx/net/uip/uip_tcpcallback.c @@ -0,0 +1,339 @@ +/**************************************************************************** + * net/uip/uip_tcpcallback.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) + +#include +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_readahead + * + * Description: + * Copy as much received data as possible into the readahead buffer + * + * Assumptions: + * This function is called at the interrupt level with interrupts disabled. + * + ****************************************************************************/ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 +static int uip_readahead(struct uip_readahead_s *readahead, uint8_t *buf, + int len) +{ + int available = CONFIG_NET_TCP_READAHEAD_BUFSIZE - readahead->rh_nbytes; + int recvlen = 0; + + if (len > 0 && available > 0) + { + /* Get the length of the data to buffer. */ + + if (len > available) + { + recvlen = available; + } + else + { + recvlen = len; + } + + /* Copy the new appdata into the read-ahead buffer */ + + memcpy(&readahead->rh_buffer[readahead->rh_nbytes], buf, recvlen); + readahead->rh_nbytes += recvlen; + } + return recvlen; +} +#endif + +/**************************************************************************** + * Function: uip_dataevent + * + * Description: + * Handle data that is not accepted by the application because there is no + * listener in place ready to receive the data. + * + * Assumptions: + * - The caller has checked that UIP_NEWDATA is set in flags and that is no + * other handler available to process the incoming data. + * - This function is called at the interrupt level with interrupts disabled. + * + ****************************************************************************/ + +static inline uint16_t +uip_dataevent(FAR struct uip_driver_s *dev, FAR struct uip_conn *conn, + uint16_t flags) +{ + uint16_t ret; + + /* Assume that we will ACK the data. The data will be ACKed if it is + * placed in the read-ahead buffer -OR- if it zero length + */ + + ret = (flags & ~UIP_NEWDATA) | UIP_SNDACK; + + /* Is there new data? With non-zero length? (Certain connection events + * can have zero-length with UIP_NEWDATA set just to cause an ACK). + */ + + if (dev->d_len > 0) + { +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + uint8_t *buffer = dev->d_appdata; + int buflen = dev->d_len; + uint16_t recvlen; +#endif + + nllvdbg("No listener on connection\n"); + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + /* Save as much data as possible in the read-ahead buffers */ + + recvlen = uip_datahandler(conn, buffer, buflen); + + /* There are several complicated buffering issues that are not addressed + * properly here. For example, what if we cannot buffer the entire + * packet? In that case, some data will be accepted but not ACKed. + * Therefore it will be resent and duplicated. Fixing this could be tricky. + */ + + if (recvlen < buflen) +#endif + { + /* There is no handler to receive new data and there are no free + * read-ahead buffers to retain the data -- drop the packet. + */ + + nllvdbg("Dropped %d bytes\n", dev->d_len); + + #ifdef CONFIG_NET_STATISTICS + uip_stat.tcp.syndrop++; + uip_stat.tcp.drop++; +#endif + /* Clear the UIP_SNDACK bit so that no ACK will be sent */ + + ret &= ~UIP_SNDACK; + } + } + + /* In any event, the new data has now been handled */ + + dev->d_len = 0; + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_tcpcallback + * + * Description: + * Inform the application holding the TCP socket of a change in state. + * + * Assumptions: + * This function is called at the interrupt level with interrupts disabled. + * + ****************************************************************************/ + +uint16_t uip_tcpcallback(struct uip_driver_s *dev, struct uip_conn *conn, + uint16_t flags) +{ + /* Preserve the UIP_ACKDATA, UIP_CLOSE, and UIP_ABORT in the response. + * These is needed by uIP to handle responses and buffer state. The + * UIP_NEWDATA indication will trigger the ACK response, but must be + * explicitly set in the callback. + */ + + uint16_t ret = flags; + + nllvdbg("flags: %04x\n", flags); + + /* Perform the data callback. When a data callback is executed from 'list', + * the input flags are normally returned, however, the implementation + * may set one of the following: + * + * UIP_CLOSE - Gracefully close the current connection + * UIP_ABORT - Abort (reset) the current connection on an error that + * prevents UIP_CLOSE from working. + * + * And/Or set/clear the following: + * + * UIP_NEWDATA - May be cleared to indicate that the data was consumed + * and that no further process of the new data should be + * attempted. + * UIP_SNDACK - If UIP_NEWDATA is cleared, then UIP_SNDACK may be set + * to indicate that an ACK should be included in the response. + * (In UIP_NEWDATA is cleared bu UIP_SNDACK is not set, then + * dev->d_len should also be cleared). + */ + + ret = uip_callbackexecute(dev, conn, flags, conn->list); + + /* There may be no new data handler in place at them moment that the new + * incoming data is received. If the new incoming data was not handled, then + * either (1) put the unhandled incoming data in the read-ahead buffer (if + * enabled) or (2) suppress the ACK to the data in the hope that it will + * be re-transmitted at a better time. + */ + + if ((ret & UIP_NEWDATA) != 0) + { + /* Data was not handled.. dispose of it appropriately */ + + ret = uip_dataevent(dev, conn, ret); + } + + /* Check if there is a connection-related event and a connection + * callback. + */ + + if (((flags & UIP_CONN_EVENTS) != 0) && conn->connection_event) + { + /* Perform the callback */ + + conn->connection_event(conn, flags); + } + + return ret; +} + +/**************************************************************************** + * Function: uip_datahandler + * + * Description: + * Handle data that is not accepted by the application. This may be called + * either (1) from the data receive logic if it cannot buffer the data, or + * (2) from the TCP event logic is there is no listener in place ready to + * receive the data. + * + * Input Parmeters: + * conn - A pointer to the TCP connection structure + * buffer - A pointer to the buffer to be copied to the read-ahead + * buffers + * buflen - The number of bytes to copy to the read-ahead buffer. + * + * Returned value: + * The number of bytes actually buffered. This could be less than 'nbytes' + * if there is insufficient buffering available. + * + * Assumptions: + * - The caller has checked that UIP_NEWDATA is set in flags and that is no + * other handler available to process the incoming data. + * - This function is called at the interrupt level with interrupts disabled. + * + ****************************************************************************/ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 +uint16_t uip_datahandler(FAR struct uip_conn *conn, FAR uint8_t *buffer, + uint16_t buflen) +{ + FAR struct uip_readahead_s *readahead1; + FAR struct uip_readahead_s *readahead2 = NULL; + uint16_t remaining; + uint16_t recvlen = 0; + + /* First, we need to determine if we have space to buffer the data. This + * needs to be verified before we actually begin buffering the data. We + * will use any remaining space in the last allocated readahead buffer + * plus as much one additional buffer. It is expected that the size of + * readahead buffers are tuned so that one full packet will always fit + * into one readahead buffer (for example if the buffer size is 420, then + * a readahead buffer of 366 will hold a full packet of TCP data). + */ + + readahead1 = (FAR struct uip_readahead_s*)conn->readahead.tail; + if ((readahead1 && + (CONFIG_NET_TCP_READAHEAD_BUFSIZE - readahead1->rh_nbytes) > buflen) || + (readahead2 = uip_tcpreadaheadalloc()) != NULL) + { + /* We have buffer space. Now try to append add as much data as possible + * to the last readahead buffer attached to this connection. + */ + + remaining = buflen; + if (readahead1) + { + recvlen = uip_readahead(readahead1, buffer, remaining); + if (recvlen > 0) + { + buffer += recvlen; + remaining -= recvlen; + } + } + + /* Do we need to buffer into the newly allocated buffer as well? */ + + if (readahead2) + { + readahead2->rh_nbytes = 0; + recvlen += uip_readahead(readahead2, buffer, remaining); + + /* Save the readahead buffer in the connection structure where + * it can be found with recv() is called. + */ + + sq_addlast(&readahead2->rh_node, &conn->readahead); + } + } + + nllvdbg("Buffered %d bytes (of %d)\n", recvlen, buflen); + return recvlen; +} +#endif /* CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 */ + +#endif /* CONFIG_NET && CONFIG_NET_TCP */ diff --git a/nuttx/net/uip/uip_tcpconn.c b/nuttx/net/uip/uip_tcpconn.c new file mode 100644 index 0000000000..c2b64ad898 --- /dev/null +++ b/nuttx/net/uip/uip_tcpconn.c @@ -0,0 +1,636 @@ +/**************************************************************************** + * net/uip/uip_tcpconn.c + * + * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Large parts of this file were leveraged from uIP logic: + * + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all uIP TCP connections. */ + +static struct uip_conn g_tcp_connections[CONFIG_NET_TCP_CONNS]; + +/* A list of all free TCP connections */ + +static dq_queue_t g_free_tcp_connections; + +/* A list of all connected TCP connections */ + +static dq_queue_t g_active_tcp_connections; + +/* Last port used by a TCP connection connection. */ + +static uint16_t g_last_tcp_port; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_selectport() + * + * Description: + * If the portnumber is zero; select an unused port for the connection. + * If the portnumber is non-zero, verify that no other connection has + * been created with this port number. + * + * Input Parameters: + * portno -- the selected port number in host order. Zero means no port + * selected. + * + * Return: + * 0 on success, negated errno on failure: + * + * EADDRINUSE + * The given address is already in use. + * EADDRNOTAVAIL + * Cannot assign requested address (unlikely) + * + * Assumptions: + * Interrupts are disabled + * + ****************************************************************************/ + +static int uip_selectport(uint16_t portno) +{ + if (portno == 0) + { + /* No local port assigned. Loop until we find a valid listen port number + * that is not being used by any other connection. NOTE the following loop + * is assumed to terminate but could not if all 32000-4096+1 ports are + * in used (unlikely). + */ + + do + { + /* Guess that the next available port number will be the one after + * the last port number assigned. + */ + portno = ++g_last_tcp_port; + + /* Make sure that the port number is within range */ + + if (g_last_tcp_port >= 32000) + { + g_last_tcp_port = 4096; + } + } + while (uip_tcplistener(htons(g_last_tcp_port))); + } + else + { + /* A port number has been supplied. Verify that no other TCP/IP + * connection is using this local port. + */ + + if (uip_tcplistener(portno)) + { + /* It is in use... return EADDRINUSE */ + + return -EADDRINUSE; + } + } + + /* Return the selected or verified port number */ + + return portno; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_tcpinit() + * + * Description: + * Initialize the TCP/IP connection structures. Called only once and only + * from the UIP layer at startup in normal user mode. + * + ****************************************************************************/ + +void uip_tcpinit(void) +{ + int i; + + /* Initialize the queues */ + + dq_init(&g_free_tcp_connections); + dq_init(&g_active_tcp_connections); + + /* Now initialize each connection structure */ + + for (i = 0; i < CONFIG_NET_TCP_CONNS; i++) + { + /* Mark the connection closed and move it to the free list */ + + g_tcp_connections[i].tcpstateflags = UIP_CLOSED; + dq_addlast(&g_tcp_connections[i].node, &g_free_tcp_connections); + } + + g_last_tcp_port = 1024; +} + +/**************************************************************************** + * Name: uip_tcpalloc() + * + * Description: + * Find a free TCP/IP connection structure and allocate it + * for use. This is normally something done by the implementation of the + * socket() API but is also called from the interrupt level when a TCP + * packet is received while "listening" + * + ****************************************************************************/ + +struct uip_conn *uip_tcpalloc(void) +{ + struct uip_conn *conn; + uip_lock_t flags; + + /* Because this routine is called from both interrupt level and + * and from user level, we have not option but to disable interrupts + * while accessing g_free_tcp_connections[]; + */ + + flags = uip_lock(); + + /* Return the entry from the head of the free list */ + + conn = (struct uip_conn *)dq_remfirst(&g_free_tcp_connections); + +#if 0 /* Revisit */ + /* Is the free list empty? */ + + if (!conn) + { + /* As a fallback, check for connection structures in the TIME_WAIT + * state. If no CLOSED connections are found, then take the oldest + */ + + struct uip_conn *tmp = g_active_tcp_connections.head; + while (tmp) + { + /* Is this connectin in the UIP_TIME_WAIT state? */ + + if (tmp->tcpstateflags == UIP_TIME_WAIT) + { + /* Is it the oldest one we have seen so far? */ + + if (!conn || tmp->timer > conn->timer) + { + /* Yes.. remember it */ + + conn = tmp; + } + } + + /* Look at the next active connection */ + + tmp = tmp->node.flink; + } + + /* If we found one, remove it from the active connection list */ + + dq_rem(&conn->node, &g_active_tcp_connections); + } +#endif + + uip_unlock(flags); + + /* Mark the connection allocated */ + + if (conn) + { + conn->tcpstateflags = UIP_ALLOCATED; + } + + return conn; +} + +/**************************************************************************** + * Name: uip_tcpfree() + * + * Description: + * Free a connection structure that is no longer in use. This should be + * done by the implementation of close() + * + ****************************************************************************/ + +void uip_tcpfree(struct uip_conn *conn) +{ +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + struct uip_readahead_s *readahead; +#endif + uip_lock_t flags; + + /* Because g_free_tcp_connections is accessed from user level and interrupt + * level, code, it is necessary to keep interrupts disabled during this + * operation. + */ + + DEBUGASSERT(conn->crefs == 0); + flags = uip_lock(); + + /* UIP_ALLOCATED means that that the connection is not in the active list + * yet. + */ + + if (conn->tcpstateflags != UIP_ALLOCATED) + { + /* Remove the connection from the active list */ + + dq_rem(&conn->node, &g_active_tcp_connections); + } + + /* Release any read-ahead buffers attached to the connection */ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + while ((readahead = (struct uip_readahead_s *)sq_remfirst(&conn->readahead)) != NULL) + { + uip_tcpreadaheadrelease(readahead); + } +#endif + + /* Remove any backlog attached to this connection */ + +#ifdef CONFIG_NET_TCPBACKLOG + if (conn->backlog) + { + uip_backlogdestroy(conn); + } + + /* If this connection is, itself, backlogged, then remove it from the + * parent connection's backlog list. + */ + + if (conn->blparent) + { + uip_backlogdelete(conn->blparent, conn); + } +#endif + + /* Mark the connection available and put it into the free list */ + + conn->tcpstateflags = UIP_CLOSED; + dq_addlast(&conn->node, &g_free_tcp_connections); + uip_unlock(flags); +} + +/**************************************************************************** + * Name: uip_tcpactive() + * + * Description: + * Find a connection structure that is the appropriate + * connection to be used with the provided TCP/IP header + * + * Assumptions: + * This function is called from UIP logic at interrupt level + * + ****************************************************************************/ + +struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf) +{ + struct uip_conn *conn = (struct uip_conn *)g_active_tcp_connections.head; + in_addr_t srcipaddr = uip_ip4addr_conv(buf->srcipaddr); + + while (conn) + { + /* Find an open connection matching the tcp input */ + + if (conn->tcpstateflags != UIP_CLOSED && + buf->destport == conn->lport && buf->srcport == conn->rport && + uip_ipaddr_cmp(srcipaddr, conn->ripaddr)) + { + /* Matching connection found.. break out of the loop and return a + * reference to it. + */ + + break; + } + + /* Look at the next active connection */ + + conn = (struct uip_conn *)conn->node.flink; + } + + return conn; +} + +/**************************************************************************** + * Name: uip_nexttcpconn() + * + * Description: + * Traverse the list of active TCP connections + * + * Assumptions: + * This function is called from UIP logic at interrupt level (or with + * interrupts disabled). + * + ****************************************************************************/ + +struct uip_conn *uip_nexttcpconn(struct uip_conn *conn) +{ + if (!conn) + { + return (struct uip_conn *)g_active_tcp_connections.head; + } + else + { + return (struct uip_conn *)conn->node.flink; + } +} + +/**************************************************************************** + * Name: uip_tcplistener() + * + * Description: + * Given a local port number (in network byte order), find the TCP + * connection that listens on this this port. + * + * Primary uses: (1) to determine if a port number is available, (2) to + * To idenfity the socket that will accept new connections on a local port. + * + ****************************************************************************/ + +struct uip_conn *uip_tcplistener(uint16_t portno) +{ + struct uip_conn *conn; + int i; + + /* Check if this port number is in use by any active UIP TCP connection */ + + for (i = 0; i < CONFIG_NET_TCP_CONNS; i++) + { + conn = &g_tcp_connections[i]; + if (conn->tcpstateflags != UIP_CLOSED && conn->lport == portno) + { + /* The portnumber is in use, return the connection */ + + return conn; + } + } + return NULL; +} + +/**************************************************************************** + * Name: uip_tcpaccept() + * + * Description: + * Called when uip_interupt matches the incoming packet with a connection + * in LISTEN. In that case, this function will create a new connection and + * initialize it to send a SYNACK in return. + * + * Assumptions: + * This function is called from UIP logic at interrupt level + * + ****************************************************************************/ + +struct uip_conn *uip_tcpaccept(struct uip_tcpip_hdr *buf) +{ + struct uip_conn *conn = uip_tcpalloc(); + if (conn) + { + /* Fill in the necessary fields for the new connection. */ + + conn->rto = UIP_RTO; + conn->timer = UIP_RTO; + conn->sa = 0; + conn->sv = 4; + conn->nrtx = 0; + conn->lport = buf->destport; + conn->rport = buf->srcport; + uip_ipaddr_copy(conn->ripaddr, uip_ip4addr_conv(buf->srcipaddr)); + conn->tcpstateflags = UIP_SYN_RCVD; + + uip_tcpinitsequence(conn->sndseq); + conn->unacked = 1; + + /* rcvseq should be the seqno from the incoming packet + 1. */ + + memcpy(conn->rcvseq, buf->seqno, 4); + + /* Initialize the list of TCP read-ahead buffers */ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + sq_init(&conn->readahead); +#endif + + /* And, finally, put the connection structure into the active list. + * Interrupts should already be disabled in this context. + */ + + dq_addlast(&conn->node, &g_active_tcp_connections); + } + return conn; +} + +/**************************************************************************** + * Name: uip_tcpbind() + * + * Description: + * This function implements the UIP specific parts of the standard TCP + * bind() operation. + * + * Return: + * 0 on success or -EADDRINUSE on failure + * + * Assumptions: + * This function is called from normal user level code. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in6 *addr) +#else +int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in *addr) +#endif +{ + uip_lock_t flags; + int port; + + /* Verify or select a local port */ + + flags = uip_lock(); + port = uip_selectport(ntohs(addr->sin_port)); + uip_unlock(flags); + + if (port < 0) + { + return port; + } + + /* Save the local address in the connection structure. Note that the requested + * local IP address is saved but not used. At present, only a single network + * interface is supported, the IP address is not of importance. + */ + + conn->lport = addr->sin_port; + +#if 0 /* Not used */ +#ifdef CONFIG_NET_IPv6 + uip_ipaddr_copy(conn->lipaddr, addr->sin6_addr.in6_u.u6_addr16); +#else + uip_ipaddr_copy(conn->lipaddr, addr->sin_addr.s_addr); +#endif +#endif + + return OK; +} + +/**************************************************************************** + * Name: uip_tcpconnect() + * + * Description: + * This function implements the UIP specific parts of the standard + * TCP connect() operation: It connects to a remote host using TCP. + * + * This function is used to start a new connection to the specified + * port on the specied host. It uses the connection structure that was + * allocated by a preceding socket() call. It sets the connection to + * the SYN_SENT state and sets the retransmission timer to 0. This will + * cause a TCP SYN segment to be sent out the next time this connection + * is periodically processed, which usually is done within 0.5 seconds + * after the call to uip_tcpconnect(). + * + * Assumptions: + * This function is called from normal user level code. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in6 *addr) +#else +int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr) +#endif +{ + uip_lock_t flags; + int port; + + /* The connection is expected to be in the UIP_ALLOCATED state.. i.e., + * allocated via up_tcpalloc(), but not yet put into the active connections + * list. + */ + + if (!conn || conn->tcpstateflags != UIP_ALLOCATED) + { + return -EISCONN; + } + + /* If the TCP port has not alread been bound to a local port, then select + * one now. + */ + + flags = uip_lock(); + port = uip_selectport(ntohs(conn->lport)); + uip_unlock(flags); + + if (port < 0) + { + return port; + } + + /* Initialize and return the connection structure, bind it to the port number */ + + conn->tcpstateflags = UIP_SYN_SENT; + uip_tcpinitsequence(conn->sndseq); + + conn->initialmss = conn->mss = UIP_TCP_MSS; + conn->unacked = 1; /* TCP length of the SYN is one. */ + conn->nrtx = 0; + conn->timer = 1; /* Send the SYN next time around. */ + conn->rto = UIP_RTO; + conn->sa = 0; + conn->sv = 16; /* Initial value of the RTT variance. */ + conn->lport = htons((uint16_t)port); + + /* The sockaddr port is 16 bits and already in network order */ + + conn->rport = addr->sin_port; + + /* The sockaddr address is 32-bits in network order. */ + + uip_ipaddr_copy(conn->ripaddr, addr->sin_addr.s_addr); + + /* Initialize the list of TCP read-ahead buffers */ + +#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 + sq_init(&conn->readahead); +#endif + + /* And, finally, put the connection structure into the active + * list. Because g_active_tcp_connections is accessed from user level and + * interrupt level, code, it is necessary to keep interrupts disabled during + * this operation. + */ + + flags = uip_lock(); + dq_addlast(&conn->node, &g_active_tcp_connections); + uip_unlock(flags); + + return OK; +} + +#endif /* CONFIG_NET && CONFIG_NET_TCP */ diff --git a/nuttx/net/uip/uip_tcpinput.c b/nuttx/net/uip/uip_tcpinput.c new file mode 100644 index 0000000000..5b40963b6b --- /dev/null +++ b/nuttx/net/uip/uip_tcpinput.c @@ -0,0 +1,839 @@ +/**************************************************************************** + * net/uip/uip_tcpinput.c + * Handling incoming TCP input + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Adapted for NuttX from logic in uIP which also has a BSD-like license: + * + * Original author Adam Dunkels + * Copyright () 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) + +#include +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define BUF ((struct uip_tcpip_hdr *)&dev->d_buf[UIP_LLH_LEN]) + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_tcpinput + * + * Description: + * Handle incoming TCP input + * + * Parameters: + * dev - The device driver structure containing the received TCP packet. + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_tcpinput(struct uip_driver_s *dev) +{ + struct uip_conn *conn = NULL; + struct uip_tcpip_hdr *pbuf = BUF; + uint16_t tmp16; + uint16_t flags; + uint8_t opt; + uint8_t result; + int len; + int i; + + dev->d_snddata = &dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN]; + dev->d_appdata = &dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN]; + +#ifdef CONFIG_NET_STATISTICS + uip_stat.tcp.recv++; +#endif + + /* Start of TCP input header processing code. */ + + if (uip_tcpchksum(dev) != 0xffff) + { + /* Compute and check the TCP checksum. */ + +#ifdef CONFIG_NET_STATISTICS + uip_stat.tcp.drop++; + uip_stat.tcp.chkerr++; +#endif + nlldbg("Bad TCP checksum\n"); + goto drop; + } + + /* Demultiplex this segment. First check any active connections. */ + + conn = uip_tcpactive(pbuf); + if (conn) + { + /* We found an active connection.. Check for the subsequent SYN + * arriving in UIP_SYN_RCVD state after the SYNACK packet was + * lost. To avoid other issues, reset any active connection + * where a SYN arrives in a state != UIP_SYN_RCVD. + */ + + if ((conn->tcpstateflags & UIP_TS_MASK) != UIP_SYN_RCVD && + (BUF->flags & TCP_CTL) == TCP_SYN) + { + goto reset; + } + else + { + goto found; + } + } + + /* If we didn't find and active connection that expected the packet, + * either (1) this packet is an old duplicate, or (2) this is a SYN packet + * destined for a connection in LISTEN. If the SYN flag isn't set, + * it is an old packet and we send a RST. + */ + + if ((pbuf->flags & TCP_CTL) == TCP_SYN) + { + /* This is a SYN packet for a connection. Find the connection + * listening on this port. + */ + + tmp16 = pbuf->destport; + if (uip_islistener(tmp16)) + { + /* We matched the incoming packet with a connection in LISTEN. + * We now need to create a new connection and send a SYNACK in + * response. + */ + + /* First allocate a new connection structure and see if there is any + * user application to accept it. + */ + + conn = uip_tcpaccept(pbuf); + if (conn) + { + /* The connection structure was successfully allocated. Now see if + * there is an application waiting to accept the connection (or at + * least queue it it for acceptance). + */ + + conn->crefs = 1; + if (uip_accept(dev, conn, tmp16) != OK) + { + /* No, then we have to give the connection back and drop the packet */ + + conn->crefs = 0; + uip_tcpfree(conn); + conn = NULL; + } + else + { + /* TCP state machine should move to the ESTABLISHED state only after + * it has received ACK from the host. This needs to be investigated + * further. + */ + + conn->tcpstateflags = UIP_ESTABLISHED; + } + } + + if (!conn) + { + /* Either (1) all available connections are in use, or (2) there is no + * application in place to accept the connection. We drop packet and hope that + * the remote end will retransmit the packet at a time when we + * have more spare connections or someone waiting to accept the connection. + */ + +#ifdef CONFIG_NET_STATISTICS + uip_stat.tcp.syndrop++; +#endif + nlldbg("No free TCP connections\n"); + goto drop; + } + + uip_incr32(conn->rcvseq, 1); + + /* Parse the TCP MSS option, if present. */ + + if ((pbuf->tcpoffset & 0xf0) > 0x50) + { + for (i = 0; i < ((pbuf->tcpoffset >> 4) - 5) << 2 ;) + { + opt = dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + i]; + if (opt == TCP_OPT_END) + { + /* End of options. */ + + break; + } + else if (opt == TCP_OPT_NOOP) + { + /* NOP option. */ + + ++i; + } + else if (opt == TCP_OPT_MSS && + dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i] == TCP_OPT_MSS_LEN) + { + /* An MSS option with the right option length. */ + + tmp16 = ((uint16_t)dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + i] << 8) | + (uint16_t)dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + i]; + conn->initialmss = conn->mss = + tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; + + /* And we are done processing options. */ + + break; + } + else + { + /* All other options have a length field, so that we easily + * can skip past them. + */ + + if (dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i] == 0) + { + /* If the length field is zero, the options are malformed + * and we don't process them further. + */ + + break; + } + i += dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i]; + } + } + } + + /* Our response will be a SYNACK. */ + + uip_tcpack(dev, conn, TCP_ACK | TCP_SYN); + return; + } + } + + /* This is (1) an old duplicate packet or (2) a SYN packet but with + * no matching listener found. Send RST packet in either case. + */ + +reset: + + /* We do not send resets in response to resets. */ + + if ((pbuf->flags & TCP_RST) != 0) + { + goto drop; + } + +#ifdef CONFIG_NET_STATISTICS + uip_stat.tcp.synrst++; +#endif + uip_tcpreset(dev); + return; + +found: + + flags = 0; + + /* We do a very naive form of TCP reset processing; we just accept + * any RST and kill our connection. We should in fact check if the + * sequence number of this reset is within our advertised window + * before we accept the reset. + */ + + if ((pbuf->flags & TCP_RST) != 0) + { + conn->tcpstateflags = UIP_CLOSED; + nlldbg("RESET - TCP state: UIP_CLOSED\n"); + + (void)uip_tcpcallback(dev, conn, UIP_ABORT); + goto drop; + } + + /* Calculated the length of the data, if the application has sent + * any data to us. + */ + + len = (pbuf->tcpoffset >> 4) << 2; + + /* d_len will contain the length of the actual TCP data. This is + * calculated by subtracting the length of the TCP header (in + * len) and the length of the IP header (20 bytes). + */ + + dev->d_len -= (len + UIP_IPH_LEN); + + /* First, check if the sequence number of the incoming packet is + * what we're expecting next. If not, we send out an ACK with the + * correct numbers in, unless we are in the SYN_RCVD state and + * receive a SYN, in which case we should retransmit our SYNACK + * (which is done further down). + */ + + if (!((((conn->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) && + ((pbuf->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))) || + (((conn->tcpstateflags & UIP_TS_MASK) == UIP_SYN_RCVD) && + ((pbuf->flags & TCP_CTL) == TCP_SYN)))) + { + if ((dev->d_len > 0 || ((pbuf->flags & (TCP_SYN | TCP_FIN)) != 0)) && + memcmp(pbuf->seqno, conn->rcvseq, 4) != 0) + { + uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN); + return; + } + } + + /* Next, check if the incoming segment acknowledges any outstanding + * data. If so, we update the sequence number, reset the length of + * the outstanding data, calculate RTT estimations, and reset the + * retransmission timer. + */ + + if ((pbuf->flags & TCP_ACK) != 0 && conn->unacked > 0) + { + uint32_t unackseq; + uint32_t ackseq; + + /* The next sequence number is equal to the current sequence + * number (sndseq) plus the size of the oustanding, unacknowledged + * data (unacked). + */ + + unackseq = uip_tcpaddsequence(conn->sndseq, conn->unacked); + + /* Get the sequence number of that has just been acknowledged by this + * incoming packet. + */ + + ackseq = uip_tcpgetsequence(pbuf->ackno); + + /* Check how many of the outstanding bytes have been acknowledged. For + * a most uIP send operation, this should always be true. However, + * the send() API sends data ahead when it can without waiting for + * the ACK. In this case, the 'ackseq' could be less than then the + * new sequence number. + */ + + if (ackseq <= unackseq) + { + /* Calculate the new number of oustanding, unacknowledged bytes */ + + conn->unacked = unackseq - ackseq; + } + else + { + /* What would it mean if ackseq > unackseq? The peer has ACKed + * more bytes than we think we have sent? Someone has lost it. + * Complain and reset the number of outstanding, unackowledged + * bytes + */ + + nlldbg("ERROR: ackseq[%08x] > unackseq[%08x]\n", ackseq, unackseq); + conn->unacked = 0; + } + + /* Update sequence number to the unacknowledge sequence number. If + * there is still outstanding, unacknowledged data, then this will + * be beyond ackseq. + */ + + nllvdbg("sndseq: %08x->%08x unackseq: %08x new unacked: %d\n", + conn->sndseq, ackseq, unackseq, conn->unacked); + uip_tcpsetsequence(conn->sndseq, ackseq); + + /* Do RTT estimation, unless we have done retransmissions. */ + + if (conn->nrtx == 0) + { + signed char m; + m = conn->rto - conn->timer; + + /* This is taken directly from VJs original code in his paper */ + + m = m - (conn->sa >> 3); + conn->sa += m; + if (m < 0) + { + m = -m; + } + + m = m - (conn->sv >> 2); + conn->sv += m; + conn->rto = (conn->sa >> 3) + conn->sv; + } + + /* Set the acknowledged flag. */ + + flags |= UIP_ACKDATA; + + /* Reset the retransmission timer. */ + + conn->timer = conn->rto; + } + + /* Do different things depending on in what state the connection is. */ + + switch (conn->tcpstateflags & UIP_TS_MASK) + { + /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not + * implemented, since we force the application to close when the + * peer sends a FIN (hence the application goes directly from + * ESTABLISHED to LAST_ACK). + */ + + case UIP_SYN_RCVD: + /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and + * we are waiting for an ACK that acknowledges the data we sent + * out the last time. Therefore, we want to have the UIP_ACKDATA + * flag set. If so, we enter the ESTABLISHED state. + */ + + if ((flags & UIP_ACKDATA) != 0) + { + conn->tcpstateflags = UIP_ESTABLISHED; + conn->unacked = 0; + nllvdbg("TCP state: UIP_ESTABLISHED\n"); + + flags = UIP_CONNECTED; + + if (dev->d_len > 0) + { + flags |= UIP_NEWDATA; + uip_incr32(conn->rcvseq, dev->d_len); + } + + dev->d_sndlen = 0; + result = uip_tcpcallback(dev, conn, flags); + uip_tcpappsend(dev, conn, result); + return; + } + + /* We need to retransmit the SYNACK */ + + if ((pbuf->flags & TCP_CTL) == TCP_SYN) + { + uip_tcpack(dev, conn, TCP_ACK | TCP_SYN); + return; + } + goto drop; + + case UIP_SYN_SENT: + /* In SYN_SENT, we wait for a SYNACK that is sent in response to + * our SYN. The rcvseq is set to sequence number in the SYNACK + * plus one, and we send an ACK. We move into the ESTABLISHED + * state. + */ + + if ((flags & UIP_ACKDATA) != 0 && (pbuf->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) + { + /* Parse the TCP MSS option, if present. */ + + if ((pbuf->tcpoffset & 0xf0) > 0x50) + { + for (i = 0; i < ((pbuf->tcpoffset >> 4) - 5) << 2 ;) + { + opt = dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + i]; + if (opt == TCP_OPT_END) + { + /* End of options. */ + + break; + } + else if (opt == TCP_OPT_NOOP) + { + /* NOP option. */ + + ++i; + } + else if (opt == TCP_OPT_MSS && + dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i] == TCP_OPT_MSS_LEN) + { + /* An MSS option with the right option length. */ + + tmp16 = + (dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + i] << 8) | + dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + i]; + conn->initialmss = + conn->mss = + tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; + + /* And we are done processing options. */ + + break; + } + else + { + /* All other options have a length field, so that we + * easily can skip past them. + */ + + if (dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i] == 0) + { + /* If the length field is zero, the options are + * malformed and we don't process them further. + */ + + break; + } + i += dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i]; + } + } + } + + conn->tcpstateflags = UIP_ESTABLISHED; + memcpy(conn->rcvseq, pbuf->seqno, 4); + nllvdbg("TCP state: UIP_ESTABLISHED\n"); + + uip_incr32(conn->rcvseq, 1); + conn->unacked = 0; + dev->d_len = 0; + dev->d_sndlen = 0; + result = uip_tcpcallback(dev, conn, UIP_CONNECTED | UIP_NEWDATA); + uip_tcpappsend(dev, conn, result); + return; + } + + /* Inform the application that the connection failed */ + + (void)uip_tcpcallback(dev, conn, UIP_ABORT); + + /* The connection is closed after we send the RST */ + + conn->tcpstateflags = UIP_CLOSED; + nllvdbg("Connection failed - TCP state: UIP_CLOSED\n"); + + /* We do not send resets in response to resets. */ + + if ((pbuf->flags & TCP_RST) != 0) + { + goto drop; + } + uip_tcpreset(dev); + return; + + case UIP_ESTABLISHED: + /* In the ESTABLISHED state, we call upon the application to feed + * data into the d_buf. If the UIP_ACKDATA flag is set, the + * application should put new data into the buffer, otherwise we are + * retransmitting an old segment, and the application should put that + * data into the buffer. + * + * If the incoming packet is a FIN, we should close the connection on + * this side as well, and we send out a FIN and enter the LAST_ACK + * state. We require that there is no outstanding data; otherwise the + * sequence numbers will be screwed up. + */ + + if ((pbuf->flags & TCP_FIN) != 0 && (conn->tcpstateflags & UIP_STOPPED) == 0) + { + if (conn->unacked > 0) + { + goto drop; + } + + /* Update the sequence number and indicate that the connection has + * been closed. + */ + + uip_incr32(conn->rcvseq, dev->d_len + 1); + flags |= UIP_CLOSE; + + if (dev->d_len > 0) + { + flags |= UIP_NEWDATA; + } + + (void)uip_tcpcallback(dev, conn, flags); + + conn->tcpstateflags = UIP_LAST_ACK; + conn->unacked = 1; + conn->nrtx = 0; + nllvdbg("TCP state: UIP_LAST_ACK\n"); + + uip_tcpsend(dev, conn, TCP_FIN | TCP_ACK, UIP_IPTCPH_LEN); + return; + } + + /* Check the URG flag. If this is set, the segment carries urgent + * data that we must pass to the application. + */ + + if ((pbuf->flags & TCP_URG) != 0) + { +#ifdef CONFIG_NET_TCPURGDATA + dev->d_urglen = (pbuf->urgp[0] << 8) | pbuf->urgp[1]; + if (dev->d_urglen > dev->d_len) + { + /* There is more urgent data in the next segment to come. */ + + dev->d_urglen = dev->d_len; + } + + uip_incr32(conn->rcvseq, dev->d_urglen); + dev->d_len -= dev->d_urglen; + dev->d_urgdata = dev->d_appdata; + dev->d_appdata += dev->d_urglen; + } + else + { + dev->d_urglen = 0; +#else /* CONFIG_NET_TCPURGDATA */ + dev->d_appdata = ((uint8_t*)dev->d_appdata) + ((pbuf->urgp[0] << 8) | pbuf->urgp[1]); + dev->d_len -= (pbuf->urgp[0] << 8) | pbuf->urgp[1]; +#endif /* CONFIG_NET_TCPURGDATA */ + } + + /* If d_len > 0 we have TCP data in the packet, and we flag this + * by setting the UIP_NEWDATA flag. If the application has stopped + * the dataflow using uip_stop(), we must not accept any data + * packets from the remote host. + */ + + if (dev->d_len > 0 && (conn->tcpstateflags & UIP_STOPPED) == 0) + { + flags |= UIP_NEWDATA; + } + + /* Check if the available buffer space advertised by the other end + * is smaller than the initial MSS for this connection. If so, we + * set the current MSS to the window size to ensure that the + * application does not send more data than the other end can + * handle. + * + * If the remote host advertises a zero window, we set the MSS to + * the initial MSS so that the application will send an entire MSS + * of data. This data will not be acknowledged by the receiver, + * and the application will retransmit it. This is called the + * "persistent timer" and uses the retransmission mechanim. + */ + + tmp16 = ((uint16_t)pbuf->wnd[0] << 8) + (uint16_t)pbuf->wnd[1]; + if (tmp16 > conn->initialmss || tmp16 == 0) + { + tmp16 = conn->initialmss; + } + conn->mss = tmp16; + + /* If this packet constitutes an ACK for outstanding data (flagged + * by the UIP_ACKDATA flag), we should call the application since it + * might want to send more data. If the incoming packet had data + * from the peer (as flagged by the UIP_NEWDATA flag), the + * application must also be notified. + * + * When the application is called, the d_len field + * contains the length of the incoming data. The application can + * access the incoming data through the global pointer + * d_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN + * bytes into the d_buf array. + * + * If the application wishes to send any data, this data should be + * put into the d_appdata and the length of the data should be + * put into d_len. If the application don't have any data to + * send, d_len must be set to 0. + */ + + if ((flags & (UIP_NEWDATA | UIP_ACKDATA)) != 0) + { + /* Clear sndlen and remember the size in d_len. The application + * may modify d_len and we will need this value later when we + * update the sequence number. + */ + + dev->d_sndlen = 0; + len = dev->d_len; + + /* Provide the packet to the application */ + + result = uip_tcpcallback(dev, conn, flags); + + /* If the application successfully handled the incoming data, + * then UIP_SNDACK will be set in the result. In this case, + * we need to update the sequence number. The ACK will be + * send by uip_tcpappsend(). + */ + + if ((result & UIP_SNDACK) != 0) + { + /* Update the sequence number using the saved length */ + + uip_incr32(conn->rcvseq, len); + } + + /* Send the response, ACKing the data or not, as appropriate */ + + uip_tcpappsend(dev, conn, result); + return; + } + goto drop; + + case UIP_LAST_ACK: + /* We can close this connection if the peer has acknowledged our + * FIN. This is indicated by the UIP_ACKDATA flag. + */ + + if ((flags & UIP_ACKDATA) != 0) + { + conn->tcpstateflags = UIP_CLOSED; + nllvdbg("UIP_LAST_ACK TCP state: UIP_CLOSED\n"); + + (void)uip_tcpcallback(dev, conn, UIP_CLOSE); + } + break; + + case UIP_FIN_WAIT_1: + /* The application has closed the connection, but the remote host + * hasn't closed its end yet. Thus we do nothing but wait for a + * FIN from the other side. + */ + + if (dev->d_len > 0) + { + uip_incr32(conn->rcvseq, dev->d_len); + } + + if ((pbuf->flags & TCP_FIN) != 0) + { + if ((flags & UIP_ACKDATA) != 0) + { + conn->tcpstateflags = UIP_TIME_WAIT; + conn->timer = 0; + conn->unacked = 0; + nllvdbg("TCP state: UIP_TIME_WAIT\n"); + } + else + { + conn->tcpstateflags = UIP_CLOSING; + nllvdbg("TCP state: UIP_CLOSING\n"); + } + + uip_incr32(conn->rcvseq, 1); + (void)uip_tcpcallback(dev, conn, UIP_CLOSE); + uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN); + return; + } + else if ((flags & UIP_ACKDATA) != 0) + { + conn->tcpstateflags = UIP_FIN_WAIT_2; + conn->unacked = 0; + nllvdbg("TCP state: UIP_FIN_WAIT_2\n"); + goto drop; + } + + if (dev->d_len > 0) + { + uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN); + return; + } + goto drop; + + case UIP_FIN_WAIT_2: + if (dev->d_len > 0) + { + uip_incr32(conn->rcvseq, dev->d_len); + } + + if ((pbuf->flags & TCP_FIN) != 0) + { + conn->tcpstateflags = UIP_TIME_WAIT; + conn->timer = 0; + nllvdbg("TCP state: UIP_TIME_WAIT\n"); + + uip_incr32(conn->rcvseq, 1); + (void)uip_tcpcallback(dev, conn, UIP_CLOSE); + uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN); + return; + } + + if (dev->d_len > 0) + { + uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN); + return; + } + goto drop; + + case UIP_TIME_WAIT: + uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN); + return; + + case UIP_CLOSING: + if ((flags & UIP_ACKDATA) != 0) + { + conn->tcpstateflags = UIP_TIME_WAIT; + conn->timer = 0; + nllvdbg("TCP state: UIP_TIME_WAIT\n"); + } + + default: + break; + } + +drop: + dev->d_len = 0; +} + +#endif /* CONFIG_NET && CONFIG_NET_TCP */ diff --git a/nuttx/net/uip/uip_tcppoll.c b/nuttx/net/uip/uip_tcppoll.c new file mode 100644 index 0000000000..29cb6d4b43 --- /dev/null +++ b/nuttx/net/uip/uip_tcppoll.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * net/uip/uip_tcppoll.c + * Poll for the availability of TCP TX data + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Adapted for NuttX from logic in uIP which also has a BSD-like license: + * + * Original author Adam Dunkels + * Copyright () 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) + +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_tcppoll + * + * Description: + * Poll a TCP connection structure for availability of TX data + * + * Parameters: + * dev - The device driver structure to use in the send operation + * conn - The TCP "connection" to poll for TX data + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_tcppoll(struct uip_driver_s *dev, struct uip_conn *conn) +{ + uint8_t result; + + /* Verify that the connection is established */ + + if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) + { + /* Set up for the callback */ + + dev->d_snddata = &dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN]; + dev->d_appdata = &dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN]; + + dev->d_len = 0; + dev->d_sndlen = 0; + + /* Perfom the callback */ + + result = uip_tcpcallback(dev, conn, UIP_POLL); + + /* Handle the callback response */ + + uip_tcpappsend(dev, conn, result); + } + else + { + /* Nothing to do for this connection */ + + dev->d_len = 0; + } +} + +#endif /* CONFIG_NET && CONFIG_NET_TCP */ diff --git a/nuttx/net/uip/uip_tcpreadahead.c b/nuttx/net/uip/uip_tcpreadahead.c new file mode 100644 index 0000000000..21ed58b99c --- /dev/null +++ b/nuttx/net/uip/uip_tcpreadahead.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * net/uip/uip_tcpreadahead.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) && (CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0) + +#include +#include + +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* These are the pre-allocated read-ahead buffers */ + +static struct uip_readahead_s g_buffers[CONFIG_NET_NTCP_READAHEAD_BUFFERS]; + +/* This is the list of available read-ahead buffers */ + +static sq_queue_t g_freebuffers; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_tcpreadaheadinit + * + * Description: + * Initialize the list of free read-ahead buffers + * + * Assumptions: + * Called once early initialization. + * + ****************************************************************************/ + +void uip_tcpreadaheadinit(void) +{ + int i; + + sq_init(&g_freebuffers); + for (i = 0; i < CONFIG_NET_NTCP_READAHEAD_BUFFERS; i++) + { + sq_addfirst(&g_buffers[i].rh_node, &g_freebuffers); + } +} + +/**************************************************************************** + * Function: uip_tcpreadaheadalloc + * + * Description: + * Allocate a TCP read-ahead buffer by taking a pre-allocated buffer from + * the free list. This function is called from TCP logic when new, + * incoming TCP data is received but there is no user logic recving the + * the data. Note: malloc() cannot be used because this function is + * called from interrupt level. + * + * Assumptions: + * Called from interrupt level with interrupts disabled. + * + ****************************************************************************/ + +struct uip_readahead_s *uip_tcpreadaheadalloc(void) +{ + return (struct uip_readahead_s*)sq_remfirst(&g_freebuffers); +} + +/**************************************************************************** + * Function: uip_tcpreadaheadrelease + * + * Description: + * Release a TCP read-ahead buffer by returning the buffer to the free list. + * This function is called from user logic after it is consumed the buffered + * data. + * + * Assumptions: + * Called from user logic BUT with interrupts disabled. + * + ****************************************************************************/ + +void uip_tcpreadaheadrelease(struct uip_readahead_s *buf) +{ + sq_addfirst(&buf->rh_node, &g_freebuffers); +} + +#endif /* CONFIG_NET && CONFIG_NET_TCP && CONFIG_NET_NTCP_READAHEAD_BUFFERS*/ diff --git a/nuttx/net/uip/uip_tcpsend.c b/nuttx/net/uip/uip_tcpsend.c new file mode 100644 index 0000000000..7051d76210 --- /dev/null +++ b/nuttx/net/uip/uip_tcpsend.c @@ -0,0 +1,369 @@ +/**************************************************************************** + * net/uip/uip_tcpsend.c + * + * Copyright (C) 2007-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Adapted for NuttX from logic in uIP which also has a BSD-like license: + * + * Original author Adam Dunkels + * Copyright () 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) + +#include +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define BUF ((struct uip_tcpip_hdr *)&dev->d_buf[UIP_LLH_LEN]) + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_tcpsendcomplete + * + * Description: + * Complete the final portions of the send operation. This function sets + * up IP header and computes the TCP checksum + * + * Parameters: + * dev - The device driver structure to use in the send operation + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +static void uip_tcpsendcomplete(struct uip_driver_s *dev) +{ + struct uip_tcpip_hdr *pbuf = BUF; + + pbuf->ttl = UIP_TTL; + +#ifdef CONFIG_NET_IPv6 + + /* For IPv6, the IP length field does not include the IPv6 IP header + * length. + */ + + pbuf->len[0] = ((dev->d_len - UIP_IPH_LEN) >> 8); + pbuf->len[1] = ((dev->d_len - UIP_IPH_LEN) & 0xff); + +#else /* CONFIG_NET_IPv6 */ + + pbuf->len[0] = (dev->d_len >> 8); + pbuf->len[1] = (dev->d_len & 0xff); + +#endif /* CONFIG_NET_IPv6 */ + + pbuf->urgp[0] = pbuf->urgp[1] = 0; + + /* Calculate TCP checksum. */ + + pbuf->tcpchksum = 0; + pbuf->tcpchksum = ~(uip_tcpchksum(dev)); + +#ifdef CONFIG_NET_IPv6 + + pbuf->vtc = 0x60; + pbuf->tcf = 0x00; + pbuf->flow = 0x00; + +#else /* CONFIG_NET_IPv6 */ + + pbuf->vhl = 0x45; + pbuf->tos = 0; + pbuf->ipoffset[0] = 0; + pbuf->ipoffset[1] = 0; + ++g_ipid; + pbuf->ipid[0] = g_ipid >> 8; + pbuf->ipid[1] = g_ipid & 0xff; + + /* Calculate IP checksum. */ + + pbuf->ipchksum = 0; + pbuf->ipchksum = ~(uip_ipchksum(dev)); + +#endif /* CONFIG_NET_IPv6 */ + + nllvdbg("Outgoing TCP packet length: %d (%d)\n", + dev->d_len, (pbuf->len[0] << 8) | pbuf->len[1]); + +#ifdef CONFIG_NET_STATISTICS + uip_stat.tcp.sent++; + uip_stat.ip.sent++; +#endif +} + +/**************************************************************************** + * Name: uip_tcpsendcommon + * + * Description: + * We're done with the input processing. We are now ready to send a reply + * Our job is to fill in all the fields of the TCP and IP headers before + * calculating the checksum and finally send the packet. + * + * Parameters: + * dev - The device driver structure to use in the send operation + * conn - The TCP connection structure holding connection information + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +static void uip_tcpsendcommon(struct uip_driver_s *dev, struct uip_conn *conn) +{ + struct uip_tcpip_hdr *pbuf = BUF; + + memcpy(pbuf->ackno, conn->rcvseq, 4); + memcpy(pbuf->seqno, conn->sndseq, 4); + + pbuf->proto = UIP_PROTO_TCP; + pbuf->srcport = conn->lport; + pbuf->destport = conn->rport; + + uiphdr_ipaddr_copy(pbuf->srcipaddr, &dev->d_ipaddr); + uiphdr_ipaddr_copy(pbuf->destipaddr, &conn->ripaddr); + + if (conn->tcpstateflags & UIP_STOPPED) + { + /* If the connection has issued uip_stop(), we advertise a zero + * window so that the remote host will stop sending data. + */ + + pbuf->wnd[0] = 0; + pbuf->wnd[1] = 0; + } + else + { + pbuf->wnd[0] = ((CONFIG_NET_RECEIVE_WINDOW) >> 8); + pbuf->wnd[1] = ((CONFIG_NET_RECEIVE_WINDOW) & 0xff); + } + + /* Finish the IP portion of the message, calculate checksums and send + * the message. + */ + + uip_tcpsendcomplete(dev); + +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_tcpsend + * + * Description: + * Setup to send a TCP packet + * + * Parameters: + * dev - The device driver structure to use in the send operation + * conn - The TCP connection structure holding connection information + * flags - flags to apply to the TCP header + * len - length of the message + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_tcpsend(struct uip_driver_s *dev, struct uip_conn *conn, + uint16_t flags, uint16_t len) +{ + struct uip_tcpip_hdr *pbuf = BUF; + + pbuf->flags = flags; + dev->d_len = len; + pbuf->tcpoffset = (UIP_TCPH_LEN / 4) << 4; + uip_tcpsendcommon(dev, conn); +} + +/**************************************************************************** + * Name: uip_tcpreset + * + * Description: + * Send a TCP reset (no-data) message + * + * Parameters: + * dev - The device driver structure to use in the send operation + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_tcpreset(struct uip_driver_s *dev) +{ + struct uip_tcpip_hdr *pbuf = BUF; + + uint16_t tmp16; + uint8_t seqbyte; + +#ifdef CONFIG_NET_STATISTICS + uip_stat.tcp.rst++; +#endif + + pbuf->flags = TCP_RST | TCP_ACK; + dev->d_len = UIP_IPTCPH_LEN; + pbuf->tcpoffset = 5 << 4; + + /* Flip the seqno and ackno fields in the TCP header. */ + + seqbyte = pbuf->seqno[3]; + pbuf->seqno[3] = pbuf->ackno[3]; + pbuf->ackno[3] = seqbyte; + + seqbyte = pbuf->seqno[2]; + pbuf->seqno[2] = pbuf->ackno[2]; + pbuf->ackno[2] = seqbyte; + + seqbyte = pbuf->seqno[1]; + pbuf->seqno[1] = pbuf->ackno[1]; + pbuf->ackno[1] = seqbyte; + + seqbyte = pbuf->seqno[0]; + pbuf->seqno[0] = pbuf->ackno[0]; + pbuf->ackno[0] = seqbyte; + + /* We also have to increase the sequence number we are + * acknowledging. If the least significant byte overflowed, we need + * to propagate the carry to the other bytes as well. + */ + + if (++(pbuf->ackno[3]) == 0) + { + if (++(pbuf->ackno[2]) == 0) + { + if (++(pbuf->ackno[1]) == 0) + { + ++(pbuf->ackno[0]); + } + } + } + + /* Swap port numbers. */ + + tmp16 = pbuf->srcport; + pbuf->srcport = pbuf->destport; + pbuf->destport = tmp16; + + /* Swap IP addresses. */ + + uiphdr_ipaddr_copy(pbuf->destipaddr, pbuf->srcipaddr); + uiphdr_ipaddr_copy(pbuf->srcipaddr, &dev->d_ipaddr); + + /* And send out the RST packet */ + + uip_tcpsendcomplete(dev); +} + +/**************************************************************************** + * Name: uip_tcpack + * + * Description: + * Send the SYN or SYNACK response. + * + * Parameters: + * dev - The device driver structure to use in the send operation + * conn - The TCP connection structure holding connection information + * ack - The ACK response to send + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_tcpack(struct uip_driver_s *dev, struct uip_conn *conn, uint8_t ack) +{ + struct uip_tcpip_hdr *pbuf = BUF; + + /* Save the ACK bits */ + + pbuf->flags = ack; + + /* We send out the TCP Maximum Segment Size option with our ack. */ + + pbuf->optdata[0] = TCP_OPT_MSS; + pbuf->optdata[1] = TCP_OPT_MSS_LEN; + pbuf->optdata[2] = (UIP_TCP_MSS) / 256; + pbuf->optdata[3] = (UIP_TCP_MSS) & 255; + dev->d_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN; + pbuf->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4; + + /* Complete the common portions of the TCP message */ + + uip_tcpsendcommon(dev, conn); +} + +#endif /* CONFIG_NET && CONFIG_NET_TCP */ diff --git a/nuttx/net/uip/uip_tcpseqno.c b/nuttx/net/uip/uip_tcpseqno.c new file mode 100755 index 0000000000..eab3a054a6 --- /dev/null +++ b/nuttx/net/uip/uip_tcpseqno.c @@ -0,0 +1,173 @@ +/**************************************************************************** + * net/uip/uip_tcpseqno.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Large parts of this file were leveraged from uIP logic: + * + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) + +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* g_tcpsequence is used to generate initial TCP sequence numbers */ + +static uint32_t g_tcpsequence; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_tcpsetsequence + * + * Description: + * Set the TCP/IP sequence number + * + * Assumptions: + * This function may called from the interrupt level + * + ****************************************************************************/ + +void uip_tcpsetsequence(FAR uint8_t *seqno, uint32_t value) +{ + /* Copy the sequence number in network (big-endian) order */ + + *seqno++ = value >> 24; + *seqno++ = (value >> 16) & 0xff; + *seqno++ = (value >> 8) & 0xff; + *seqno = value & 0xff; +} + +/**************************************************************************** + * Name: uip_tcpgetsequence + * + * Description: + * Get the TCP/IP sequence number + * + * Assumptions: + * This function may called from the interrupt level + * + ****************************************************************************/ + +uint32_t uip_tcpgetsequence(FAR uint8_t *seqno) +{ + uint32_t value; + + /* Combine the sequence number from network (big-endian) order */ + + value = (uint32_t)seqno[0] << 24 | + (uint32_t)seqno[1] << 16 | + (uint32_t)seqno[2] << 8 | + (uint32_t)seqno[3]; + return value; +} + +/**************************************************************************** + * Name: uip_tcpaddsequence + * + * Description: + * Add the length to get the next TCP sequence number. + * + * Assumptions: + * This function may called from the interrupt level + * + ****************************************************************************/ + +uint32_t uip_tcpaddsequence(FAR uint8_t *seqno, uint16_t len) +{ + return uip_tcpgetsequence(seqno) + (uint32_t)len; +} + +/**************************************************************************** + * Name: uip_tcpinitsequence + * + * Description: + * Set the (initial) the TCP/IP sequence number when a TCP connection is + * established. + * + * Assumptions: + * This function may called from the interrupt level + * + ****************************************************************************/ + +void uip_tcpinitsequence(FAR uint8_t *seqno) +{ + uip_tcpsetsequence(seqno, g_tcpsequence); +} + +/**************************************************************************** + * Name: uip_tcpnextsequence + * + * Description: + * Increment the TCP/IP sequence number + * + * Assumptions: + * This function is called from the interrupt level + * + ****************************************************************************/ + +void uip_tcpnextsequence(void) +{ + g_tcpsequence++; +} + +#endif /* CONFIG_NET && CONFIG_NET_TCP */ diff --git a/nuttx/net/uip/uip_tcptimer.c b/nuttx/net/uip/uip_tcptimer.c new file mode 100644 index 0000000000..c95376ab0c --- /dev/null +++ b/nuttx/net/uip/uip_tcptimer.c @@ -0,0 +1,250 @@ +/**************************************************************************** + * net/uip/uip_tcptimer.c + * Poll for the availability of TCP TX data + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Adapted for NuttX from logic in uIP which also has a BSD-like license: + * + * Original author Adam Dunkels + * Copyright () 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) + +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_tcptimer + * + * Description: + * Handle a TCP timer expiration for the provided TCP connection + * + * Parameters: + * dev - The device driver structure to use in the send operation + * conn - The TCP "connection" to poll for TX data + * hsed - The polling interval in halves of a second + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_tcptimer(struct uip_driver_s *dev, struct uip_conn *conn, int hsec) +{ + uint8_t result; + + dev->d_snddata = &dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN]; + dev->d_appdata = &dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN]; + + /* Increase the TCP sequence number */ + + uip_tcpnextsequence(); + + /* Reset the length variables. */ + + dev->d_len = 0; + dev->d_sndlen = 0; + + /* Check if the connection is in a state in which we simply wait + * for the connection to time out. If so, we increase the + * connection's timer and remove the connection if it times + * out. + */ + + if (conn->tcpstateflags == UIP_TIME_WAIT || conn->tcpstateflags == UIP_FIN_WAIT_2) + { + /* Increment the connection timer */ + + (conn->timer) += hsec; + if (conn->timer >= UIP_TIME_WAIT_TIMEOUT) + { + conn->tcpstateflags = UIP_CLOSED; + nllvdbg("TCP state: UIP_CLOSED\n"); + } + } + else if (conn->tcpstateflags != UIP_CLOSED) + { + /* If the connection has outstanding data, we increase the connection's + * timer and see if it has reached the RTO value in which case we + * retransmit. + */ + + if (conn->unacked > 0) + { + /* The connection has outstanding data */ + + if (conn->timer > hsec) + { + /* Will not yet decrement to zero */ + + conn->timer -= hsec; + } + else + { + /* Will decrement to zero */ + + conn->timer = 0; + + /* Should we close the connection? */ + + if (conn->nrtx == UIP_MAXRTX || + ((conn->tcpstateflags == UIP_SYN_SENT || + conn->tcpstateflags == UIP_SYN_RCVD) && + conn->nrtx == UIP_MAXSYNRTX)) + { + conn->tcpstateflags = UIP_CLOSED; + nllvdbg("TCP state: UIP_CLOSED\n"); + + /* We call uip_tcpcallback() with UIP_TIMEDOUT to + * inform the application that the connection has + * timed out. + */ + + result = uip_tcpcallback(dev, conn, UIP_TIMEDOUT); + + /* We also send a reset packet to the remote host. */ + + uip_tcpsend(dev, conn, TCP_RST | TCP_ACK, UIP_IPTCPH_LEN); + goto done; + } + + /* Exponential backoff. */ + + conn->timer = UIP_RTO << (conn->nrtx > 4 ? 4: conn->nrtx); + (conn->nrtx)++; + + /* Ok, so we need to retransmit. We do this differently + * depending on which state we are in. In ESTABLISHED, we + * call upon the application so that it may prepare the + * data for the retransmit. In SYN_RCVD, we resend the + * SYNACK that we sent earlier and in LAST_ACK we have to + * retransmit our FINACK. + */ + +#ifdef CONFIG_NET_STATISTICS + uip_stat.tcp.rexmit++; +#endif + switch(conn->tcpstateflags & UIP_TS_MASK) + { + case UIP_SYN_RCVD: + /* In the SYN_RCVD state, we should retransmit our + * SYNACK. + */ + + uip_tcpack(dev, conn, TCP_ACK | TCP_SYN); + goto done; + + case UIP_SYN_SENT: + /* In the SYN_SENT state, we retransmit out SYN. */ + + uip_tcpack(dev, conn, TCP_SYN); + goto done; + + case UIP_ESTABLISHED: + /* In the ESTABLISHED state, we call upon the application + * to do the actual retransmit after which we jump into + * the code for sending out the packet. + */ + + result = uip_tcpcallback(dev, conn, UIP_REXMIT); + uip_tcprexmit(dev, conn, result); + goto done; + + case UIP_FIN_WAIT_1: + case UIP_CLOSING: + case UIP_LAST_ACK: + /* In all these states we should retransmit a FINACK. */ + + uip_tcpsend(dev, conn, TCP_FIN | TCP_ACK, UIP_IPTCPH_LEN); + goto done; + } + } + } + + /* The connection does not have outstanding data */ + + else if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) + { + /* If there was no need for a retransmission, we poll the + * application for new data. + */ + + result = uip_tcpcallback(dev, conn, UIP_POLL); + uip_tcpappsend(dev, conn, result); + goto done; + } + } + + /* Nothing to be done */ + + dev->d_len = 0; + +done: + return; +} + +#endif /* CONFIG_NET && CONFIG_NET_TCP */ diff --git a/nuttx/net/uip/uip_udpcallback.c b/nuttx/net/uip/uip_udpcallback.c new file mode 100644 index 0000000000..f00c5e0f81 --- /dev/null +++ b/nuttx/net/uip/uip_udpcallback.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * net/uip/uip_udpcallback.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_UDP) + +#include +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_udpcallback + * + * Description: + * Inform the application holding the UDP socket of a change in state. + * + * Assumptions: + * This function is called at the interrupt level with interrupts disabled. + * + ****************************************************************************/ + +void uip_udpcallback(struct uip_driver_s *dev, struct uip_udp_conn *conn, + uint16_t flags) +{ + nllvdbg("flags: %04x\n", flags); + + /* Some sanity checking */ + + if (conn) + { + /* Perform the callback */ + + flags = uip_callbackexecute(dev, conn, flags, conn->list); + } +} + +#endif /* CONFIG_NET && CONFIG_NET_UDP */ diff --git a/nuttx/net/uip/uip_udpconn.c b/nuttx/net/uip/uip_udpconn.c new file mode 100644 index 0000000000..3c4ee5addb --- /dev/null +++ b/nuttx/net/uip/uip_udpconn.c @@ -0,0 +1,492 @@ +/**************************************************************************** + * net/uip/uip_udpconn.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Large parts of this file were leveraged from uIP logic: + * + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_UDP) + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all uIP UDP connections. */ + +struct uip_udp_conn g_udp_connections[CONFIG_NET_UDP_CONNS]; + +/* A list of all free UDP connections */ + +static dq_queue_t g_free_udp_connections; +static sem_t g_free_sem; + +/* A list of all allocated UDP connections */ + +static dq_queue_t g_active_udp_connections; + +/* Last port used by a UDP connection connection. */ + +static uint16_t g_last_udp_port; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _uip_semtake() and _uip_semgive() + * + * Description: + * Take/give semaphore + * + ****************************************************************************/ + +static inline void _uip_semtake(sem_t *sem) +{ + /* Take the semaphore (perhaps waiting) */ + + while (uip_lockedwait(sem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(*get_errno_ptr() == EINTR); + } +} + +#define _uip_semgive(sem) sem_post(sem) + +/**************************************************************************** + * Name: uip_find_conn() + * + * Description: + * Find the UDP connection that uses this local port number. Called only + * from user user level code, but with interrupts disabled. + * + ****************************************************************************/ + +static struct uip_udp_conn *uip_find_conn(uint16_t portno) +{ + int i; + + /* Now search each connection structure.*/ + + for (i = 0; i < CONFIG_NET_UDP_CONNS; i++) + { + if (g_udp_connections[ i ].lport == portno) + { + return &g_udp_connections[ i ]; + } + } + + return NULL; +} + +/**************************************************************************** + * Name: uip_selectport() + * + * Description: + * Select an unused port number. + * + * NOTE that in prinicple this function could fail if there is no available + * port number. There is no check for that case and it would actually + * in an infinite loop if that were the case. In this simple, small UDP + * implementation, it is reasonable to assume that that error cannot happen + * and that a port number will always be available. + * + * Input Parameters: + * None + * + * Return: + * Next available port number + * + ****************************************************************************/ + +static uint16_t uip_selectport(void) +{ + uint16_t portno; + + /* Find an unused local port number. Loop until we find a valid + * listen port number that is not being used by any other connection. + */ + + uip_lock_t flags = uip_lock(); + do + { + /* Guess that the next available port number will be the one after + * the last port number assigned. + */ + + ++g_last_udp_port; + + /* Make sure that the port number is within range */ + + if (g_last_udp_port >= 32000) + { + g_last_udp_port = 4096; + } + } + while (uip_find_conn(htons(g_last_udp_port))); + + /* Initialize and return the connection structure, bind it to the + * port number + */ + + portno = g_last_udp_port; + uip_unlock(flags); + + return portno; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_udpinit() + * + * Description: + * Initialize the UDP connection structures. Called once and only from + * the UIP layer. + * + ****************************************************************************/ + +void uip_udpinit(void) +{ + int i; + + /* Initialize the queues */ + + dq_init(&g_free_udp_connections); + dq_init(&g_active_udp_connections); + sem_init(&g_free_sem, 0, 1); + + for (i = 0; i < CONFIG_NET_UDP_CONNS; i++) + { + /* Mark the connection closed and move it to the free list */ + + g_udp_connections[i].lport = 0; + dq_addlast(&g_udp_connections[i].node, &g_free_udp_connections); + } + + g_last_udp_port = 1024; +} + +/**************************************************************************** + * Name: uip_udpalloc() + * + * Description: + * Alloc a new, uninitialized UDP connection structure. + * + ****************************************************************************/ + +struct uip_udp_conn *uip_udpalloc(void) +{ + struct uip_udp_conn *conn; + + /* The free list is only accessed from user, non-interrupt level and + * is protected by a semaphore (that behaves like a mutex). + */ + + _uip_semtake(&g_free_sem); + conn = (struct uip_udp_conn *)dq_remfirst(&g_free_udp_connections); + if (conn) + { + /* Make sure that the connection is marked as uninitialized */ + + conn->lport = 0; + } + _uip_semgive(&g_free_sem); + return conn; +} + +/**************************************************************************** + * Name: uip_udpfree() + * + * Description: + * Free a UDP connection structure that is no longer in use. This should be + * done by the implementation of close(). uip_udpdisable must have been + * previously called. + * + ****************************************************************************/ + +void uip_udpfree(struct uip_udp_conn *conn) +{ + /* The free list is only accessed from user, non-interrupt level and + * is protected by a semaphore (that behaves like a mutex). + */ + + DEBUGASSERT(conn->crefs == 0); + + _uip_semtake(&g_free_sem); + conn->lport = 0; + dq_addlast(&conn->node, &g_free_udp_connections); + _uip_semgive(&g_free_sem); +} + +/**************************************************************************** + * Name: uip_udpactive() + * + * Description: + * Find a connection structure that is the appropriate + * connection to be used withi the provided TCP/IP header + * + * Assumptions: + * This function is called from UIP logic at interrupt level + * + ****************************************************************************/ + +struct uip_udp_conn *uip_udpactive(struct uip_udpip_hdr *buf) +{ + struct uip_udp_conn *conn = (struct uip_udp_conn *)g_active_udp_connections.head; + + while (conn) + { + /* If the local UDP port is non-zero, the connection is considered + * to be used. If so, the local port number is checked against the + * destination port number in the received packet. If the two port + * numbers match, the remote port number is checked if the + * connection is bound to a remote port. Finally, if the + * connection is bound to a remote IP address, the source IP + * address of the packet is checked. + */ + + if (conn->lport != 0 && buf->destport == conn->lport && + (conn->rport == 0 || buf->srcport == conn->rport) && + (uip_ipaddr_cmp(conn->ripaddr, g_allzeroaddr) || + uip_ipaddr_cmp(conn->ripaddr, g_alloneaddr) || + uiphdr_ipaddr_cmp(buf->srcipaddr, &conn->ripaddr))) + { + /* Matching connection found.. return a reference to it */ + + break; + } + + /* Look at the next active connection */ + + conn = (struct uip_udp_conn *)conn->node.flink; + } + + return conn; +} + +/**************************************************************************** + * Name: uip_nextudpconn() + * + * Description: + * Traverse the list of allocated UDP connections + * + * Assumptions: + * This function is called from UIP logic at interrupt level (or with + * interrupts disabled). + * + ****************************************************************************/ + +struct uip_udp_conn *uip_nextudpconn(struct uip_udp_conn *conn) +{ + if (!conn) + { + return (struct uip_udp_conn *)g_active_udp_connections.head; + } + else + { + return (struct uip_udp_conn *)conn->node.flink; + } +} + +/**************************************************************************** + * Name: uip_udpbind() + * + * Description: + * This function implements the UIP specific parts of the standard UDP + * bind() operation. + * + * Assumptions: + * This function is called from normal user level code. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in6 *addr) +#else +int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in *addr) +#endif +{ + int ret = -EADDRINUSE; + uip_lock_t flags; + + /* Is the user requesting to bind to any port? */ + + if (!addr->sin_port) + { + /* Yes.. Find an unused local port number */ + + conn->lport = htons(uip_selectport()); + ret = OK; + } + else + { + /* Interrupts must be disabled while access the UDP connection list */ + + flags = uip_lock(); + + /* Is any other UDP connection bound to this port? */ + + if (!uip_find_conn(addr->sin_port)) + { + /* No.. then bind the socket to the port */ + + conn->lport = addr->sin_port; + ret = OK; + } + + uip_unlock(flags); + } + return ret; +} + +/**************************************************************************** + * Name: uip_udpconnect() + * + * Description: + * This function sets up a new UDP connection. The function will + * automatically allocate an unused local port for the new + * connection. However, another port can be chosen by using the + * uip_udpbind() call, after the uip_udpconnect() function has been + * called. + * + * uip_udpenable() must be called before the connection is made active (i.e., + * is eligible for callbacks. + * + * addr The address of the remote host. + * + * Assumptions: + * This function is called user code. Interrupts may be enabled. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +int uip_udpconnect(struct uip_udp_conn *conn, const struct sockaddr_in6 *addr) +#else +int uip_udpconnect(struct uip_udp_conn *conn, const struct sockaddr_in *addr) +#endif +{ + /* Has this address already been bound to a local port (lport)? */ + + if (!conn->lport) + { + /* No.. Find an unused local port number and bind it to the + * connection structure. + */ + + conn->lport = htons(uip_selectport()); + } + + /* Is there a remote port (rport) */ + + if (addr) + { + conn->rport = addr->sin_port; + uip_ipaddr_copy(conn->ripaddr, addr->sin_addr.s_addr); + } + else + { + conn->rport = 0; + uip_ipaddr_copy(conn->ripaddr, g_allzeroaddr); + } + + conn->ttl = UIP_TTL; + return OK; +} + +/**************************************************************************** + * Name: uip_udpenable() uip_udpdisable. + * + * Description: + * Enable/disable callbacks for the specified connection + * + * Assumptions: + * This function is called user code. Interrupts may be enabled. + * + ****************************************************************************/ + +void uip_udpenable(struct uip_udp_conn *conn) +{ + /* Add the connection structure to the active connectionlist. This list + * is modifiable from interrupt level, we we must disable interrupts to + * access it safely. + */ + + uip_lock_t flags = uip_lock(); + dq_addlast(&conn->node, &g_active_udp_connections); + uip_unlock(flags); +} + +void uip_udpdisable(struct uip_udp_conn *conn) +{ + /* Remove the connection structure from the active connectionlist. This list + * is modifiable from interrupt level, we we must disable interrupts to + * access it safely. + */ + + uip_lock_t flags = uip_lock(); + dq_rem(&conn->node, &g_active_udp_connections); + uip_unlock(flags); +} + +#endif /* CONFIG_NET && CONFIG_NET_UDP */ diff --git a/nuttx/net/uip/uip_udpinput.c b/nuttx/net/uip/uip_udpinput.c new file mode 100644 index 0000000000..456c34799b --- /dev/null +++ b/nuttx/net/uip/uip_udpinput.c @@ -0,0 +1,156 @@ +/**************************************************************************** + * net/uip/uip_udpinput.c + * Handling incoming UDP input + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Adapted for NuttX from logic in uIP which also has a BSD-like license: + * + * Original author Adam Dunkels + * Copyright () 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_UDP) + +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define UDPBUF ((struct uip_udpip_hdr *)&dev->d_buf[UIP_LLH_LEN]) + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_udpinput + * + * Description: + * Handle incoming UDP input + * + * Parameters: + * dev - The device driver structure containing the received UDP packet + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_udpinput(struct uip_driver_s *dev) +{ + struct uip_udp_conn *conn; + struct uip_udpip_hdr *pbuf = UDPBUF; + +#ifdef CONFIG_NET_STATISTICS + uip_stat.udp.recv++; +#endif + + /* UDP processing is really just a hack. We don't do anything to the UDP/IP + * headers, but let the UDP application do all the hard work. If the + * application sets d_sndlen, it has a packet to send. + */ + + dev->d_len -= UIP_IPUDPH_LEN; +#ifdef CONFIG_NET_UDP_CHECKSUMS + dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + if (pbuf->udpchksum != 0 && uip_udpchksum(dev) != 0xffff) + { +#ifdef CONFIG_NET_STATISTICS + uip_stat.udp.drop++; + uip_stat.udp.chkerr++; +#endif + nlldbg("Bad UDP checksum\n"); + dev->d_len = 0; + } + else +#endif + { + /* Demultiplex this UDP packet between the UDP "connections". */ + + conn = uip_udpactive(pbuf); + if (conn) + { + /* Setup for the application callback */ + + dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + dev->d_snddata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + dev->d_sndlen = 0; + + /* Perform the application callback */ + + uip_udpcallback(dev, conn, UIP_NEWDATA); + + /* If the application has data to send, setup the UDP/IP header */ + + if (dev->d_sndlen > 0) + { + uip_udpsend(dev, conn); + } + } + else + { + nlldbg("No listener on UDP port\n"); + dev->d_len = 0; + } + } + + return; +} + +#endif /* CONFIG_NET && CONFIG_NET_UDP */ diff --git a/nuttx/net/uip/uip_udppoll.c b/nuttx/net/uip/uip_udppoll.c new file mode 100644 index 0000000000..984566ed46 --- /dev/null +++ b/nuttx/net/uip/uip_udppoll.c @@ -0,0 +1,126 @@ +/**************************************************************************** + * net/uip/uip_udppoll.c + * Poll for the availability of UDP TX data + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Adapted for NuttX from logic in uIP which also has a BSD-like license: + * + * Original author Adam Dunkels + * Copyright () 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_UDP) + +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_udppoll + * + * Description: + * Poll a UDP "connection" structure for availability of TX data + * + * Parameters: + * dev - The device driver structure to use in the send operation + * conn - The UDP "connection" to poll for TX data + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_udppoll(struct uip_driver_s *dev, struct uip_udp_conn *conn) +{ + /* Verify that the UDP connection is valid */ + + if (conn->lport != 0) + { + /* Setup for the application callback */ + + dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + dev->d_snddata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + + dev->d_len = 0; + dev->d_sndlen = 0; + + /* Perform the application callback */ + + uip_udpcallback(dev, conn, UIP_POLL); + + /* If the application has data to send, setup the UDP/IP header */ + + if (dev->d_sndlen > 0) + { + uip_udpsend(dev, conn); + return; + } + } + + /* Make sure that d_len is zero meaning that there is nothing to be sent */ + + dev->d_len = 0; +} + +#endif /* CONFIG_NET && CONFIG_NET_UDP */ diff --git a/nuttx/net/uip/uip_udpsend.c b/nuttx/net/uip/uip_udpsend.c new file mode 100644 index 0000000000..1dc33bbd18 --- /dev/null +++ b/nuttx/net/uip/uip_udpsend.c @@ -0,0 +1,177 @@ +/**************************************************************************** + * net/uip/uip_udpsend.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Adapted for NuttX from logic in uIP which also has a BSD-like license: + * + * Original author Adam Dunkels + * Copyright () 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_UDP) + +#include + +#include +#include +#include + +#include "uip_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define UDPBUF ((struct uip_udpip_hdr *)&dev->d_buf[UIP_LLH_LEN]) + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_udpsend + * + * Description: + * Setup to send a UDP packet + * + * Parameters: + * dev - The device driver structure to use in the send operation + * conn - The UDP "connection" structure holding port information + * + * Return: + * None + * + * Assumptions: + * Called from the interrupt level or with interrupts disabled. + * + ****************************************************************************/ + +void uip_udpsend(struct uip_driver_s *dev, struct uip_udp_conn *conn) +{ + struct uip_udpip_hdr *pudpbuf = UDPBUF; + + if (dev->d_sndlen > 0) + { + /* The total lenth to send is the size of the application data plus + * the IP and UDP headers (and, eventually, the ethernet header) + */ + + dev->d_len = dev->d_sndlen + UIP_IPUDPH_LEN; + + /* Initialize the IP header. Note that for IPv6, the IP length field + * does not include the IPv6 IP header length. + */ + +#ifdef CONFIG_NET_IPv6 + + pudpbuf->vtc = 0x60; + pudpbuf->tcf = 0x00; + pudpbuf->flow = 0x00; + pudpbuf->len[0] = (dev->d_sndlen >> 8); + pudpbuf->len[1] = (dev->d_sndlen & 0xff); + pudpbuf->nexthdr = UIP_PROTO_UDP; + pudpbuf->hoplimit = conn->ttl; + + uip_ipaddr_copy(pudpbuf->srcipaddr, &dev->d_ipaddr); + uip_ipaddr_copy(pudpbuf->destipaddr, &conn->ripaddr); + +#else /* CONFIG_NET_IPv6 */ + + pudpbuf->vhl = 0x45; + pudpbuf->tos = 0; + pudpbuf->len[0] = (dev->d_len >> 8); + pudpbuf->len[1] = (dev->d_len & 0xff); + ++g_ipid; + pudpbuf->ipid[0] = g_ipid >> 8; + pudpbuf->ipid[1] = g_ipid & 0xff; + pudpbuf->ipoffset[0] = 0; + pudpbuf->ipoffset[1] = 0; + pudpbuf->ttl = conn->ttl; + pudpbuf->proto = UIP_PROTO_UDP; + + uiphdr_ipaddr_copy(pudpbuf->srcipaddr, &dev->d_ipaddr); + uiphdr_ipaddr_copy(pudpbuf->destipaddr, &conn->ripaddr); + + /* Calculate IP checksum. */ + + pudpbuf->ipchksum = 0; + pudpbuf->ipchksum = ~(uip_ipchksum(dev)); + +#endif /* CONFIG_NET_IPv6 */ + + /* Initialize the UDP header */ + + pudpbuf->srcport = conn->lport; + pudpbuf->destport = conn->rport; + pudpbuf->udplen = HTONS(dev->d_sndlen + UIP_UDPH_LEN); + +#ifdef CONFIG_NET_UDP_CHECKSUMS + /* Calculate UDP checksum. */ + + pudpbuf->udpchksum = 0; + pudpbuf->udpchksum = ~(uip_udpchksum(dev)); + if (pudpbuf->udpchksum == 0) + { + pudpbuf->udpchksum = 0xffff; + } +#else + pudpbuf->udpchksum = 0; +#endif + + nllvdbg("Outgoing UDP packet length: %d (%d)\n", + dev->d_len, (pudpbuf->len[0] << 8) | pudpbuf->len[1]); + +#ifdef CONFIG_NET_STATISTICS + uip_stat.udp.sent++; + uip_stat.ip.sent++; +#endif + } +} + +#endif /* CONFIG_NET && CONFIG_NET_UDP */ diff --git a/nuttx/sched/Kconfig b/nuttx/sched/Kconfig new file mode 100644 index 0000000000..f822736387 --- /dev/null +++ b/nuttx/sched/Kconfig @@ -0,0 +1,397 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config MSEC_PER_TICK + int "tick timer" + default 10 + ---help--- + The default system timer is 100Hz or MSEC_PER_TICK=10. This setting + may be defined to inform NuttX that the processor hardware is providing + system timer interrupts at some interrupt interval other than 10 msec. + +config RR_INTERVAL + int "round robin timeslice" + default 0 + ---help--- + The round robin timeslice will be set this number of milliseconds; + Round robin scheduling can be disabled by setting this value to zero. + +config SCHED_INSTRUMENTATION + bool "Monitor system performance" + default n + ---help--- + enables instrumentation in scheduler to monitor system performance. + +config TASK_NAME_SIZE + int "Maximum task name size" + default 32 + ---help--- + Spcifies that maximum size of a task name to save in the TCB. + Useful if scheduler instrumentation is selected. Set to zero to + disable. + +config JULIAN_TIME + bool "Enables Julian time conversions" + default n + ---help--- + Enables Julian time conversions + +config START_YEAR + int "start year" + default 2010 + +config START_MONTH + int "start month" + default 1 + +config START_DAY + int "start day" + default 1 + +config DEV_CONSOLE + bool "Enable /dev/console" + default y + ---help--- + Set if architecture-specific logic provides /dev/console. Enables + stdout, stderr, stdin. + +config DEV_LOWCONSOLE + bool "enable low-level serial console" + default n + ---help--- + Use the simple, low-level, write-only serial console driver (minimul support) + +config MUTEX_TYPES: + bool "Enable mutex types" + default n + ---help--- + Set to enable support for recursive and errorcheck mutexes. Enables + pthread_mutexattr_settype(). + +config PRIORITY_INHERITANCE + bool "Enable priority inheritance " + default n + ---help--- + Set to enable support for priority inheritance on mutexes and semaphores. + +config SEM_PREALLOCHOLDERS + int "Pre-allocated holders" + default 16 + depends on PRIORITY_INHERITANCE + ---help--- + This setting is only used if priority inheritance is enabled. + It defines the maximum number of different threads (minus one) that + can take counts on a semaphore with priority inheritance support. + This may be set to zero if priority inheritance is disabled OR if you + are only using semaphores as mutexes (only one holder) OR if no more + than two threads participate using a counting semaphore. + +config SEM_NNESTPRIO + int "Maximum number of higher priority threads" + default 16 + depends on PRIORITY_INHERITANCE + ---help--- + If priority inheritance is enabled, then this setting is the + maximum number of higher priority threads (minus 1) than can be + waiting for another thread to release a count on a semaphore. + This value may be set to zero if no more than one thread is + expected to wait for a semaphore. + +config FDCLONE_DISABLE + bool "Disable cloning of file descriptors" + default n + ---help--- + Disable cloning of all file descriptors + by task_create() when a new task is started. If set, all + files/drivers will appear to be closed in the new task. + +config FDCLONE_STDIO + bool "Disable clone file descriptors without stdio" + default n + ---help--- + Disable cloning of all but the first three file descriptors (stdin, + stdout, stderr) by task_create() when a new task is started. If set, + all files/drivers will appear to be closed in the new task except + for stdin, stdout, and stderr. + +config SDCLONE_DISABLE + bool "Disable cloning of socket descriptors" + default n + ---help--- + Disable cloning of all socket + desciptors by task_create() when a new task is started. If + set, all sockets will appear to be closed in the new task. + +config SCHED_WORKQUEUE + bool "Enable worker thread" + default n + ---help--- + Create a dedicated "worker" thread to handle delayed processing from interrupt + handlers. This feature is required for some drivers but, if there are no + complaints, can be safely disabled. The worker thread also performs + garbage collection -- completing any delayed memory deallocations from + interrupt handlers. If the worker thread is disabled, then that clean up will + be performed by the IDLE thread instead (which runs at the lowest of priority + and may not be appropriate if memory reclamation is of high priority). + +config SCHED_WORKPRIORITY + int "Worker thread priority" + default 192 + depends on SCHED_WORKQUEUE + ---help--- + The execution priority of the worker thread. Default: 192 + +config SCHED_WORKPERIOD + int "Worker thread period" + default 50000 + depends on SCHED_WORKQUEUE + ---help--- + How often the worker thread checks for work in units of microseconds. + Default: 50*1000 (50 MS). + +config SCHED_WORKSTACKSIZE + int "Worker thread stack size" + default 2048 + depends on SCHED_WORKQUEUE + ---help--- + The stack size allocated for the worker thread. Default: 2K. + +config SIG_SIGWORK + int "Worker thread wakeup signal" + default 4 + depends on SCHED_WORKQUEUE + ---help--- + The signal number that will be used to wake-up the worker thread. + Default: 4 + +config SCHED_WAITPID + bool "Enable waitpid() API" + default n + ---help--- + Enables the waitpid() API + +config SCHED_ATEXIT + bool "Enable atexit() API" + default n + ---help--- + Enables the atexit() API + +config SCHED_ATEXIT_MAX + int "Max number of atexit() functions" + default 1 + depends on SCHED_ATEXIT + ---help--- + By default if SCHED_ATEXIT is selected, only a single atexit() function + is supported. That number can be increased by defined this setting to + the number that you require. + +config SCHED_ONEXIT + bool "Enable on_exit() API" + default n + ---help--- + Enables the on_exit() API + +config SCHED_ONEXIT_MAX + int "Max number of on_exit() functions" + default 1 + depends on SCHED_ONEXIT + ---help--- + By default if SCHED_ONEXIT is selected, only a single on_exit() function + is supported. That number can be increased by defined this setting to the + number that you require. + +config DISABLE_OS_API + bool "Disable NuttX interfaces" + default n + ---help--- + The following can be used to disable categories of + APIs supported by the OS. If the compiler supports + weak functions, then it should not be necessary to + disable functions unless you want to restrict usage + of those APIs. + + There are certain dependency relationships in these + features. + + o mq_notify logic depends on signals to awaken tasks + waiting for queues to become full or empty. + o pthread_condtimedwait() depends on signals to wake + up waiting tasks. + +config DISABLE_CLOCK + bool "Disable clock interfaces" + depends on DISABLE_OS_API + default n + +config DISABLE_POSIX_TIMERS + bool "Disable POSIX timers" + depends on DISABLE_OS_API + default n + +config DISABLE_PTHREAD + bool "Disable pthread support" + depends on DISABLE_OS_API + default n + +config DISABLE_SIGNALS + bool "Disable signal support" + depends on DISABLE_OS_API + default n + +config DISABLE_MQUEUE + bool "Disable POSIX message queue support" + depends on DISABLE_OS_API + default n + +config DISABLE_MOUNTPOINT + bool "Disable support for mount points" + depends on DISABLE_OS_API + default n + +config DISABLE_ENVIRON + bool "Disable environment variable support" + depends on DISABLE_OS_API + default n + +config DISABLE_POLL + bool "Disable driver poll interfaces" + depends on DISABLE_OS_API + default n + +comment "Sizes of configurable things (0 disables)" + +config MAX_TASKS + int "Max tasks" + default 32 + ---help--- + The maximum number of simultaneously active tasks. This value must be + a power of two. + +config MAX_TASK_ARGS + int "Maximum number of task arguments" + default 4 + ---help--- + This controls the maximum number of of parameters that a task may + receive (i.e., maxmum value of 'argc') + +config NPTHREAD_KEYS + int "Number of pthread keys" + default 4 + ---help--- + The number of items of thread- + specific data that can be retained + +config NFILE_DESCRIPTORS + int "Max file descriptors" + default 16 + ---help--- + The maximum number of file + descriptors (one for each open) + +config NFILE_STREAMS + int "Max file streams" + default 16 + ---help--- + The maximum number of streams that can be fopen'ed + +config NAME_MAX + int "name max" + default 32 + ---help--- + The maximum size of a file name. + +config PREALLOC_MQ_MSGS + int "Pre-allocated messages" + default 32 + ---help--- + The number of pre-allocated message structures. The system manages + a pool of preallocated message structures to minimize dynamic allocations + +config MQ_MAXMSGSIZE + int "Maximum message size" + default 32 + ---help--- + Message structures are allocated with a fixed payload size given by this + setting (does not include other message structure overhead. + +config MAX_WDOGPARMS + int "max watchdog parms" + default 4 + ---help--- + Maximum number of parameters that + can be passed to a watchdog handler + +config PREALLOC_WDOGS + int "Pre-allocated watchdogs" + default 32 + ---help--- + The number of pre-allocated watchdog structures. The system manages a + pool of preallocated watchdog structures to minimize dynamic allocations + +config PREALLOC_TIMERS + int "Pre-allocated timers" + default 8 + ---help--- + The number of pre-allocated POSIX timer structures. The system manages a + pool of preallocated timer structures to minimize dynamic allocations. Set to + zero for all dynamic allocations. + +comment "Stack and heap information" + +config BOOT_RUNFROMFLASH + bool "boot run from flash" + default n + ---help--- + Some configurations support XIP operation from FLASH but must copy + initialized .data sections to RAM + +config BOOT_COPYTORAM + bool "boot copy to ram" + default n + ---help--- + Some configurations boot in FLASH + but copy themselves entirely into RAM for better performance. + +config CUSTOM_STACK + bool "Enable custom stack" + default n + ---help--- + The up_ implementation will handle all stack operations outside of the + nuttx model. This is necessary for certain architectures that have + have hardware stacks (such as the 8051 family). + +config STACK_POINTER + hex "The initial stack pointer" + ---help--- + The initial stack pointer (arm7tdmi only). + +config IDLETHREAD_STACKSIZE + int "Idle thread stack size" + default 1024 + ---help--- + The size of the initial stack used by the IDLE thread. The IDLE thread + is the thread that (1) performs the inital boot of the system up to the + point where user_start() is spawned, and (2) there after is the IDLE + thread that executes only when there is no other thread ready to run. + +config USERMAIN_STACKSIZE + int "Main thread stack size" + default 2048 + ---help--- + The size of the stack to allocate for the main user thread that begins at + the user_start() entry point. + +config PTHREAD_STACK_MIN + int "Minimum pthread stack size" + default 256 + ---help--- + Minimum pthread stack size + +config PTHREAD_STACK_DEFAULT + int "Default pthread stack size" + default 2048 + ---help--- + Default pthread stack size + diff --git a/nuttx/sched/Makefile b/nuttx/sched/Makefile new file mode 100644 index 0000000000..dfdc6f68b6 --- /dev/null +++ b/nuttx/sched/Makefile @@ -0,0 +1,216 @@ +############################################################################ +# sched/Makefile +# +# Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ASRCS = +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +MISC_SRCS = os_start.c os_bringup.c errno_getptr.c errno_get.c errno_set.c \ + sched_garbage.c sched_setupstreams.c sched_getfiles.c sched_getsockets.c \ + sched_getstreams.c sched_setupidlefiles.c sched_setuptaskfiles.c \ + sched_setuppthreadfiles.c sched_releasefiles.c + +TSK_SRCS = prctl.c task_create.c task_init.c task_setup.c task_activate.c \ + task_start.c task_delete.c task_deletecurrent.c task_exithook.c \ + task_restart.c exit.c getpid.c sched_addreadytorun.c \ + sched_removereadytorun.c sched_addprioritized.c sched_mergepending.c \ + sched_addblocked.c sched_removeblocked.c sched_free.c sched_gettcb.c \ + sched_verifytcb.c sched_releasetcb.c + +SCHED_SRCS = sched_setparam.c sched_setpriority.c sched_getparam.c \ + sched_setscheduler.c sched_getscheduler.c \ + sched_yield.c sched_rrgetinterval.c sched_foreach.c \ + sched_lock.c sched_unlock.c sched_lockcount.c sched_self.c + +ifeq ($(CONFIG_SCHED_ATEXIT),y) +SCHED_SRCS += atexit.c +endif + +ifeq ($(CONFIG_SCHED_ONEXIT),y) +SCHED_SRCS += on_exit.c +endif + +ifeq ($(CONFIG_PRIORITY_INHERITANCE),y) +SCHED_SRCS += sched_reprioritize.c +endif + +ifeq ($(CONFIG_SCHED_WAITPID),y) +SCHED_SRCS += sched_waitpid.c +endif + +ENV_SRCS = env_getenvironptr.c env_dup.c env_share.c env_release.c \ + env_findvar.c env_removevar.c \ + env_clearenv.c env_getenv.c env_putenv.c env_setenv.c env_unsetenv.c + +WDOG_SRCS = wd_initialize.c wd_create.c wd_start.c wd_cancel.c wd_delete.c \ + wd_gettime.c + +TIME_SRCS = sched_processtimer.c + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +TIME_SRCS += sleep.c usleep.c +endif + +CLOCK_SRCS = clock_initialize.c clock_settime.c clock_gettime.c clock_getres.c \ + clock_time2ticks.c clock_abstime2ticks.c clock_ticks2time.c \ + clock_gettimeofday.c clock_systimer.c + +SIGNAL_SRCS = sig_initialize.c \ + sig_action.c sig_procmask.c sig_pending.c sig_suspend.c \ + sig_kill.c sig_queue.c sig_waitinfo.c sig_timedwait.c \ + sig_findaction.c sig_allocatependingsigaction.c \ + sig_releasependingsigaction.c sig_unmaskpendingsignal.c \ + sig_removependingsignal.c sig_releasependingsignal.c sig_lowest.c \ + sig_mqnotempty.c sig_cleanup.c sig_received.c sig_deliver.c + +MQUEUE_SRCS = mq_open.c mq_close.c mq_unlink.c mq_send.c mq_timedsend.c\ + mq_sndinternal.c mq_receive.c mq_timedreceive.c mq_rcvinternal.c \ + mq_initialize.c mq_descreate.c mq_findnamed.c mq_msgfree.c mq_msgqfree.c + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +MQUEUE_SRCS += mq_waitirq.c +endif + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +MQUEUE_SRCS += mq_notify.c +endif + +PTHREAD_SRCS = pthread_create.c pthread_exit.c pthread_join.c pthread_detach.c \ + pthread_yield.c pthread_getschedparam.c pthread_setschedparam.c \ + pthread_mutexinit.c pthread_mutexdestroy.c \ + pthread_mutexlock.c pthread_mutextrylock.c pthread_mutexunlock.c \ + pthread_condinit.c pthread_conddestroy.c \ + pthread_condwait.c pthread_condsignal.c pthread_condbroadcast.c \ + pthread_barrierinit.c pthread_barrierdestroy.c pthread_barrierwait.c \ + pthread_cancel.c pthread_setcancelstate.c \ + pthread_keycreate.c pthread_setspecific.c pthread_getspecific.c pthread_keydelete.c \ + pthread_initialize.c pthread_completejoin.c pthread_findjoininfo.c \ + pthread_removejoininfo.c pthread_once.c pthread_setschedprio.c + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +PTHREAD_SRCS += pthread_condtimedwait.c pthread_kill.c pthread_sigmask.c +endif + +SEM_SRCS = sem_initialize.c sem_destroy.c sem_open.c sem_close.c sem_unlink.c \ + sem_wait.c sem_trywait.c sem_timedwait.c sem_post.c sem_findnamed.c + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +SEM_SRCS += sem_waitirq.c +endif + +ifeq ($(CONFIG_PRIORITY_INHERITANCE),y) +SEM_SRCS += sem_holder.c +endif + +ifneq ($(CONFIG_DISABLE_POSIX_TIMERS),y) +TIMER_SRCS = timer_initialize.c timer_create.c timer_delete.c timer_getoverrun.c \ + timer_gettime.c timer_settime.c timer_release.c +endif + +ifeq ($(CONFIG_SCHED_WORKQUEUE),y) +WORK_SRCS = work_thread.c work_queue.c work_cancel.c +endif + +ifeq ($(CONFIG_PAGING),y) +PGFILL_SRCS = pg_miss.c pg_worker.c +endif + +IRQ_SRCS = irq_initialize.c irq_attach.c irq_dispatch.c irq_unexpectedisr.c + +KMM_SRCS = kmm_initialize.c kmm_addregion.c kmm_semaphore.c \ + kmm_kmalloc.c kmm_kzalloc.c kmm_krealloc.c kmm_kfree.c + +CSRCS = $(MISC_SRCS) $(TSK_SRCS) $(SCHED_SRCS) $(WDOG_SRCS) $(TIME_SRCS) \ + $(SEM_SRCS) $(TIMER_SRCS) $(WORK_SRCS) $(PGFILL_SRCS) $(IRQ_SRCS) + +ifneq ($(CONFIG_DISABLE_CLOCK),y) +CSRCS += $(CLOCK_SRCS) +endif + +ifneq ($(CONFIG_DISABLE_PTHREAD),y) +CSRCS += $(PTHREAD_SRCS) +endif + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +CSRCS += $(SIGNAL_SRCS) +endif + +ifneq ($(CONFIG_DISABLE_MQUEUE),y) +CSRCS += $(MQUEUE_SRCS) +endif + +ifneq ($(CONFIG_DISABLE_ENVIRON),y) +CSRCS += $(ENV_SRCS) +endif + +ifeq ($(CONFIG_NUTTX_KERNEL),y) +CSRCS += $(KMM_SRCS) +endif + +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = libsched$(LIBEXT) + +all: $(BIN) + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +.depend: Makefile $(SRCS) + @$(MKDEP) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f $(BIN) *~ .*.swp + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/sched/atexit.c b/nuttx/sched/atexit.c new file mode 100644 index 0000000000..f7d81bec20 --- /dev/null +++ b/nuttx/sched/atexit.c @@ -0,0 +1,162 @@ +/**************************************************************************** + * sched/atexit.c + * + * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" + +#ifdef CONFIG_SCHED_ATEXIT + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: atexit + * + * Description: + * Registers a function to be called at program exit. + * The atexit() function registers the given function to be called + * at normal process termination, whether via exit or via return from + * the program's main(). + * + * NOTE: CONFIG_SCHED_ATEXIT must be defined to enable this function + * + * Limitiations in the current implementation: + * + * 1. Only a single atexit function can be registered unless + * CONFIG_SCHED_ATEXIT_MAX defines a larger number. + * 2. atexit functions are not inherited when a new task is + * created. + * + * Parameters: + * func - A pointer to the function to be called when the task exits. + * + * Return Value: + * Zero on success. Non-zero on failure. + * + ****************************************************************************/ + +int atexit(void (*func)(void)) +{ +#if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1 + _TCB *tcb = (_TCB*)g_readytorun.head; + int index; + int ret = ERROR; + + /* The following must be atomic */ + + if (func) + { + sched_lock(); + + /* Search for the first available slot. atexit() functions are registered + * from lower to higher arry indices; they must be called in the reverse + * order of registration when task exists, i.e., from higher to lower + * indices. + */ + + available = -1; + for (index = 0; index < CONFIG_SCHED_ATEXIT_MAX; index++) + { + if (!tcb->atexitfunc[index]) + { + tcb->atexitfunc[index] = func; + ret = OK; + break; + } + } + + sched_unlock(); + } + + return ret; +#else + _TCB *tcb = (_TCB*)g_readytorun.head; + int ret = ERROR; + + /* The following must be atomic */ + + sched_lock(); + if (func && !tcb->atexitfunc) + { + tcb->atexitfunc = func; + ret = OK; + } + + sched_unlock(); + return ret; +#endif +} + +#endif /* CONFIG_SCHED_ATEXIT */ + + diff --git a/nuttx/sched/clock_abstime2ticks.c b/nuttx/sched/clock_abstime2ticks.c new file mode 100644 index 0000000000..2d7f7f4806 --- /dev/null +++ b/nuttx/sched/clock_abstime2ticks.c @@ -0,0 +1,126 @@ +/******************************************************************************** + * clock_abstime2ticks.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include +#include "clock_internal.h" + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: clock_abstime2ticks + * + * Description: + * Convert an absolute timespec delay to system timer ticks. + * + * Parameters: + * clockid - The timing source to use in the conversion + * reltime - Convert this absolue time to system clock ticks. + * ticks - Return the converted number of ticks here. + * + * Return Value: + * OK on success; A non-zero error number on failure; + * + * Assumptions: + * Interrupts should be disabled so that the time is not changing during the + * calculation + * + ********************************************************************************/ + +int clock_abstime2ticks(clockid_t clockid, FAR const struct timespec *abstime, + FAR int *ticks) +{ + struct timespec currtime; + struct timespec reltime; + int ret; + + /* Convert the timespec to clock ticks. NOTE: Here we use internal knowledge + * that CLOCK_REALTIME is defined to be zero! + */ + + ret = clock_gettime(clockid, &currtime); + if (ret) + { + return EINVAL; + } + + /* The relative time to wait is the absolute time minus the current time. */ + + reltime.tv_nsec = (abstime->tv_nsec - currtime.tv_nsec); + reltime.tv_sec = (abstime->tv_sec - currtime.tv_sec); + + /* Check if we were supposed to borrow from the seconds to borrow from the + * seconds + */ + + if (reltime.tv_nsec < 0) + { + reltime.tv_nsec += NSEC_PER_SEC; + reltime.tv_sec -= 1; + } + + /* Convert this relative time into microseconds.*/ + + return clock_time2ticks(&reltime, ticks); +} diff --git a/nuttx/sched/clock_getres.c b/nuttx/sched/clock_getres.c new file mode 100644 index 0000000000..a76b14ab66 --- /dev/null +++ b/nuttx/sched/clock_getres.c @@ -0,0 +1,121 @@ +/************************************************************************ + * sched/clock_getres.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "clock_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/********************************************************************** + * Public Constant Data + **********************************************************************/ + +/************************************************************************ + * Public Variables + ************************************************************************/ + +/********************************************************************** + * Private Variables + **********************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: clock_getres + * + * Description: + * Clock Functions based on POSIX APIs + * + ************************************************************************/ + +int clock_getres(clockid_t clock_id, struct timespec *res) +{ + uint32_t time_res; + int ret = OK; + + sdbg("clock_id=%d\n", clock_id); + + /* Only CLOCK_REALTIME is supported */ + + if (clock_id != CLOCK_REALTIME) + { + sdbg("Returning ERROR\n"); + set_errno(EINVAL); + ret = ERROR; + } + else + { + /* Get the clock resolution in nanoseconds */ + + time_res = MSEC_PER_TICK * NSEC_PER_MSEC; + + /* And return this as a timespec. */ + + res->tv_sec = 0; + res->tv_nsec = time_res; + + sdbg("Returning res=(%d,%d) time_res=%d\n", + (int)res->tv_sec, (int)res->tv_nsec, + (int)time_res); + } + + return ret; +} diff --git a/nuttx/sched/clock_gettime.c b/nuttx/sched/clock_gettime.c new file mode 100644 index 0000000000..d6772dada9 --- /dev/null +++ b/nuttx/sched/clock_gettime.c @@ -0,0 +1,180 @@ +/************************************************************************ + * sched/clock_gettime.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "clock_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/********************************************************************** + * Public Constant Data + **********************************************************************/ + +/************************************************************************ + * Public Variables + ************************************************************************/ + +/********************************************************************** + * Private Variables + **********************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: clock_gettime + * + * Description: + * Clock Functions based on POSIX APIs + * + ************************************************************************/ + +int clock_gettime(clockid_t clock_id, struct timespec *tp) +{ +#ifdef CONFIG_SYSTEM_TIME64 + uint64_t msecs; + uint64_t secs; + uint64_t nsecs; +#else + uint32_t msecs; + uint32_t secs; + uint32_t nsecs; +#endif + int ret = OK; + + sdbg("clock_id=%d\n", clock_id); + DEBUGASSERT(tp != NULL); + + /* CLOCK_REALTIME - POSIX demands this to be present. This is the wall + * time clock. + */ + +#ifdef CONFIG_RTC + if (clock_id == CLOCK_REALTIME || clock_id == CLOCK_ACTIVETIME) +#else + if (clock_id == CLOCK_REALTIME) +#endif + { + /* Do we have a high-resolution RTC that can provie us with the time? */ + +#ifdef CONFIG_RTC_HIRES + if (g_rtc_enabled && clock_id != CLOCK_ACTIVETIME) + { + /* Yes.. Get the hi-resolution time from the RTC */ + + ret = up_rtc_gettime(tp); + } + else +#endif + { + /* Get the elapsed time since power up (in milliseconds) biased + * as appropriate. + */ + + msecs = MSEC_PER_TICK * (g_system_timer - g_tickbias); + + sdbg("msecs = %d g_tickbias=%d\n", + (int)msecs, (int)g_tickbias); + + /* Get the elapsed time in seconds and nanoseconds. */ + + secs = msecs / MSEC_PER_SEC; + nsecs = (msecs - (secs * MSEC_PER_SEC)) * NSEC_PER_MSEC; + + sdbg("secs = %d + %d nsecs = %d + %d\n", + (int)msecs, (int)g_basetime.tv_sec, + (int)nsecs, (int)g_basetime.tv_nsec); + + /* Add the base time to this. */ + + secs += (uint32_t)g_basetime.tv_sec; + nsecs += (uint32_t)g_basetime.tv_nsec; + + /* Handle carry to seconds. */ + + if (nsecs > NSEC_PER_SEC) + { + uint32_t dwCarrySecs = nsecs / NSEC_PER_SEC; + secs += dwCarrySecs; + nsecs -= (dwCarrySecs * NSEC_PER_SEC); + } + + /* And return the result to the caller. */ + + tp->tv_sec = (time_t)secs; + tp->tv_nsec = (long)nsecs; + } + + sdbg("Returning tp=(%d,%d)\n", (int)tp->tv_sec, (int)tp->tv_nsec); + } + else + { + sdbg("Returning ERROR\n"); + + errno = EINVAL; + ret = ERROR; + } + + return ret; +} diff --git a/nuttx/sched/clock_gettimeofday.c b/nuttx/sched/clock_gettimeofday.c new file mode 100644 index 0000000000..6437ef955d --- /dev/null +++ b/nuttx/sched/clock_gettimeofday.c @@ -0,0 +1,113 @@ +/**************************************************************************** + * sched/clock_gettimeofday.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "clock_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/************************************************************************** + * Public Constant Data + **************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gettimeofday + * + * Description: + * Get the current time + * + ****************************************************************************/ + +int gettimeofday(struct timeval *tp, void *tzp) +{ + struct timespec ts; + int ret; + +#ifdef CONFIG_DEBUG + if (!tp) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Let clock_gettime do most of the work */ + + ret = clock_gettime(CLOCK_REALTIME, &ts); + if (ret == OK) + { + /* Convert the struct timespec to a struct timeval */ + + tp->tv_sec = ts.tv_sec; + tp->tv_usec = ts.tv_nsec / NSEC_PER_USEC; + } + + return ret; +} diff --git a/nuttx/sched/clock_initialize.c b/nuttx/sched/clock_initialize.c new file mode 100644 index 0000000000..2e146bb475 --- /dev/null +++ b/nuttx/sched/clock_initialize.c @@ -0,0 +1,270 @@ +/**************************************************************************** + * sched/clock_initialize.c + * + * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_RTC +# include +#endif + +#include +#include +#include + +#include "clock_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Standard time definitions (in units of seconds) */ + +#define SEC_PER_MIN ((time_t)60) +#define SEC_PER_HOUR ((time_t)60 * SEC_PER_MIN) +#define SEC_PER_DAY ((time_t)24 * SEC_PER_HOUR) + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/************************************************************************** + * Public Constant Data + **************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +#ifdef CONFIG_SYSTEM_TIME64 +volatile uint64_t g_system_timer; +uint64_t g_tickbias; +#else +volatile uint32_t g_system_timer; +uint32_t g_tickbias; +#endif + +struct timespec g_basetime; + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/**************************************************************************** + * Name: clock_basetime + * + * Description: + * Get the initial time value from the best source available. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC +#if defined(CONFIG_RTC_DATETIME) +/* Initialize the system time using a broken out date/time structure */ + +static inline void clock_basetime(FAR struct timespec *tp) +{ + struct tm rtctime; + + /* Get the broken-out time from the date/time RTC. */ + + (void)up_rtc_getdatetime(&rtctime); + + /* And use the broken-out time to initialize the system time */ + + tp->tv_sec = mktime(&rtctime); + tp->tv_nsec = 0; +} + +#elif defined(CONFIG_RTC_HIRES) + +/* Initialize the system time using a high-resolution structure */ + +static inline void clock_basetime(FAR struct timespec *tp) +{ + /* Get the complete time from the hi-res RTC. */ + + (void)up_rtc_gettime(tp); +} + +#else + +/* Initialize the system time using seconds only */ + +static inline void clock_basetime(FAR struct timespec *tp) +{ + /* Get the seconds (only) from the lo-resolution RTC */ + + tp->tv_sec = up_rtc_time(); + tp->tv_nsec = 0; +} + +#endif /* CONFIG_RTC_HIRES */ +#else /* CONFIG_RTC */ + +static inline void clock_basetime(FAR struct timespec *tp) +{ + time_t jdn = 0; + + /* Get the EPOCH-relative julian date from the calendar year, + * month, and date + */ + + jdn = clock_calendar2utc(CONFIG_START_YEAR, CONFIG_START_MONTH, + CONFIG_START_DAY); + + /* Set the base time as seconds into this julian day. */ + + tp->tv_sec = jdn * SEC_PER_DAY; + tp->tv_nsec = 0; +} + +#endif /* CONFIG_RTC */ + +/**************************************************************************** + * Name: clock_inittime + * + * Description: + * Get the initial time value from the best source available. + * + ****************************************************************************/ + +static void clock_inittime(void) +{ + /* (Re-)initialize the time value to match the RTC*/ + + clock_basetime(&g_basetime); + g_system_timer = 0; + g_tickbias = 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: clock_initialize + * + * Description: + * Perform one-time initialization of the timing facilities. + * + ****************************************************************************/ + +void clock_initialize(void) +{ + /* Initialize the RTC hardware */ + +#ifdef CONFIG_RTC + up_rtcinitialize(); +#endif + + /* Initialize the time value to match the RTC */ + + clock_inittime(); +} + +/**************************************************************************** + * Name: clock_synchronize + * + * Description: + * Synchronize the system timer to a hardware RTC. This operation is + * normally performed automatically by the system during clock + * initialization. However, the user may also need to explicitly re- + * synchronize the system timer to the RTC under certain conditions where + * the system timer is known to be in error. For example, in certain low- + * power states, the system timer may be stopped but the RTC will continue + * keep correct time. After recovering from such low-power state, this + * function should be called to restore the correct system time. + * + * Calling this function could result in system time going "backward" in + * time, especially with certain lower resolution RTC implementations. + * Time going backward could have bad consequences if there are ongoing + * timers and delays. So use this interface with care. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_RTC +void clock_synchronize(void) +{ + irqstate_t flags; + + /* Re-initialize the time value to match the RTC */ + + flags = irqsave(); + clock_inittime(); + irqrestore(flags); +} +#endif + +/**************************************************************************** + * Name: clock_timer + * + * Description: + * This function must be called once every time the real time clock + * interrupt occurs. The interval of this clock interrupt must be + * MSEC_PER_TICK + * + ****************************************************************************/ + +void clock_timer(void) +{ + /* Increment the per-tick system counter */ + + g_system_timer++; +} diff --git a/nuttx/sched/clock_internal.h b/nuttx/sched/clock_internal.h new file mode 100644 index 0000000000..aba9723b63 --- /dev/null +++ b/nuttx/sched/clock_internal.h @@ -0,0 +1,91 @@ +/******************************************************************************** + * sched/clock_internal.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +#ifndef __SCHED_CLOCK_INTERNAL_H +#define __SCHED_CLOCK_INTERNAL_H + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include + +#include +#include + +/******************************************************************************** + * Pre-processor Definitions + ********************************************************************************/ +/* Configuration ************************************************************/ +/* If CONFIG_SYSTEM_TIME64 is selected and the CPU supports long long types, + * then a 64-bit system time will be used. + */ + +#ifndef CONFIG_HAVE_LONG_LONG +# undef CONFIG_SYSTEM_TIME64 +#endif + +/******************************************************************************** + * Public Type Definitions + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +#ifdef CONFIG_SYSTEM_TIME64 +extern uint64_t g_tickbias; +#else +extern uint32_t g_tickbias; +#endif + +extern struct timespec g_basetime; + +/******************************************************************************** + * Public Function Prototypes + ********************************************************************************/ + +void weak_function clock_initialize(void); +void weak_function clock_timer(void); + +int clock_abstime2ticks(clockid_t clockid, + FAR const struct timespec *abstime, + FAR int *ticks); +int clock_time2ticks(FAR const struct timespec *reltime, FAR int *ticks); +int clock_ticks2time(int ticks, FAR struct timespec *reltime); + +#endif /* __SCHED_CLOCK_INTERNAL_H */ diff --git a/nuttx/sched/clock_settime.c b/nuttx/sched/clock_settime.c new file mode 100644 index 0000000000..ce809aa114 --- /dev/null +++ b/nuttx/sched/clock_settime.c @@ -0,0 +1,149 @@ +/************************************************************************ + * sched/clock_settime.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +#include +#include "clock_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/********************************************************************** + * Public Constant Data + **********************************************************************/ + +/************************************************************************ + * Public Variables + ************************************************************************/ + +/********************************************************************** + * Private Variables + **********************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: clock_settime + * + * Description: + * Clock Functions based on POSIX APIs + * + ************************************************************************/ + +int clock_settime(clockid_t clock_id, FAR const struct timespec *tp) +{ + irqstate_t flags; + int ret = OK; + + sdbg("clock_id=%d\n", clock_id); + DEBUGASSERT(tp != NULL); + + /* CLOCK_REALTIME - POSIX demands this to be present. This is the wall + * time clock. + */ + +#ifdef CONFIG_RTC + if (clock_id == CLOCK_REALTIME || clock_id == CLOCK_ACTIVETIME) +#else + if (clock_id == CLOCK_REALTIME) +#endif + { + /* Interrupts are disabled here so that the in-memory time + * representation and the RTC setting will be as close as + * possible. + */ + + flags = irqsave(); + + /* Save the new base time. */ + + g_basetime.tv_sec = tp->tv_sec; + g_basetime.tv_nsec = tp->tv_nsec; + + /* Get the elapsed time since power up (in milliseconds) biased + * as appropriate. + */ + + g_tickbias = g_system_timer; + + /* Setup the RTC (lo- or high-res) */ + +#ifdef CONFIG_RTC + if (g_rtc_enabled && clock_id != CLOCK_ACTIVETIME) + { + up_rtc_settime(tp); + } +#endif + irqrestore(flags); + + sdbg("basetime=(%d,%d) tickbias=%d\n", + (int)g_basetime.tv_sec, (int)g_basetime.tv_nsec, + (int)g_tickbias); + } + else + { + sdbg("Returning ERROR\n"); + set_errno(EINVAL); + ret = ERROR; + } + + return ret; +} diff --git a/nuttx/sched/clock_systimer.c b/nuttx/sched/clock_systimer.c new file mode 100644 index 0000000000..33c16db949 --- /dev/null +++ b/nuttx/sched/clock_systimer.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * sched/clock_systimer.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "clock_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: clock_systimer + * + * Description: + * Return the current value of the 32-bit system timer counter + * + * Parameters: + * None + * + * Return Value: + * The current value of the system timer counter + * + * Assumptions: + * + ****************************************************************************/ + +#if !defined(clock_systimer) /* See nuttx/clock.h */ +uint32_t clock_systimer(void) +{ +#ifdef CONFIG_SYSTEM_TIME64 + return (uint32_t)(g_system_timer & 0x00000000ffffffff); +#else + return g_system_timer; +#endif +} +#endif + +/**************************************************************************** + * Name: clock_systimer64 + * + * Description: + * Return the current value of the 64-bit system timer counter + * + * Parameters: + * None + * + * Return Value: + * The current value of the system timer counter + * + * Assumptions: + * + ****************************************************************************/ + +#if !defined(clock_systimer) /* See nuttx/clock.h */ +#ifdef CONFIG_SYSTEM_TIME64 +uint64_t clock_systimer64(void) +{ + return g_system_timer; +} +#endif +#endif diff --git a/nuttx/sched/clock_ticks2time.c b/nuttx/sched/clock_ticks2time.c new file mode 100644 index 0000000000..fd300692d2 --- /dev/null +++ b/nuttx/sched/clock_ticks2time.c @@ -0,0 +1,94 @@ +/******************************************************************************** + * clock_ticks2time.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include "clock_internal.h" + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: clock_ticks2time + * + * Description: + * Convert the system time tick value to a relative time. + * + * Parameters: + * ticks - The number of system time ticks to convert. + * reltime - Return the converted system time here. + * + * Return Value: + * Always returns OK + * + * Assumptions: + * + ********************************************************************************/ + +int clock_ticks2time(int ticks, FAR struct timespec *reltime) +{ + int remainder; + + reltime->tv_sec = ticks / TICK_PER_SEC; + remainder = ticks - TICK_PER_SEC * reltime->tv_sec; + reltime->tv_nsec = remainder * NSEC_PER_TICK; + return OK; +} diff --git a/nuttx/sched/clock_time2ticks.c b/nuttx/sched/clock_time2ticks.c new file mode 100644 index 0000000000..383264d513 --- /dev/null +++ b/nuttx/sched/clock_time2ticks.c @@ -0,0 +1,102 @@ +/******************************************************************************** + * sched/clock_time2ticks.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include + +#include "clock_internal.h" + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: clock_time2ticks + * + * Description: + * Convert a timespec delay to system timer ticks. This function is suitable + * for calculating relative time delays and does not depend on the other + * clock_* logic. + * + * Parameters: + * reltime - Convert this relative time to system clock ticks. + * ticks - Return the converted number of ticks here. + * + * Return Value: + * Always returns OK + * + * Assumptions: + * + ********************************************************************************/ + +int clock_time2ticks(FAR const struct timespec *reltime, FAR int *ticks) +{ + int32_t relusec; + + /* Convert the relative time into microseconds.*/ + + relusec = reltime->tv_sec * USEC_PER_SEC + reltime->tv_nsec / NSEC_PER_USEC; + + /* Convert microseconds to clock ticks */ + + *ticks = relusec / USEC_PER_TICK; + return OK; +} diff --git a/nuttx/sched/env_clearenv.c b/nuttx/sched/env_clearenv.c new file mode 100644 index 0000000000..7fe97a911e --- /dev/null +++ b/nuttx/sched/env_clearenv.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * sched/env_clearenv.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: clearenv + * + * Description: + * The clearenv() function clears the environment of all name-value pairs + * and sets the value of the external variable environ to NULL. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * Not called from an interrupt handler + * + ****************************************************************************/ + +int clearenv(void) +{ + return env_release((FAR _TCB*)g_readytorun.head); +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_dup.c b/nuttx/sched/env_dup.c new file mode 100644 index 0000000000..0333484117 --- /dev/null +++ b/nuttx/sched/env_dup.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * sched/env_dup.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: env_dup + * + * Description: + * Copy the internal environment structure of a task. This is the action + * that is performed when a new task is created: The new task has a private, + * exact duplicate of the parent task's environment. + * + * Parameters: + * ptcb The tcb to receive the newly allocated copy of the parspecifiedent + * TCB's environment structure with reference count equal to one + * + * Return Value: + * zero on success + * + * Assumptions: + * Not called from an interrupt handler. + * + ****************************************************************************/ + +int env_dup(FAR _TCB *ptcb) +{ + int ret = OK; + if (!ptcb ) + { + ret = -EINVAL; + } + else + { + FAR _TCB *parent = (FAR _TCB*)g_readytorun.head; + environ_t *envp = NULL; + + /* Pre-emption must be disabled throughout the following because the + * environment may be shared. + */ + + sched_lock(); + + /* Does the parent task have an environment? */ + + if (parent->envp) + { + /* Yes..The parent task has an environment, duplicate it */ + + size_t envlen = parent->envp->ev_alloc; + envp = (environ_t*)kmalloc(SIZEOF_ENVIRON_T( envlen )); + if (!envp) + { + ret = -ENOMEM; + } + else + { + envp->ev_crefs = 1; + envp->ev_alloc = envlen; + memcpy( envp->ev_env, parent->envp->ev_env, envlen ); + } + } + + /* Save the cloned environment in the new TCB */ + + ptcb->envp = envp; + sched_unlock(); + } + + return ret; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_dupenv.c b/nuttx/sched/env_dupenv.c new file mode 100644 index 0000000000..32bf6a4334 --- /dev/null +++ b/nuttx/sched/env_dupenv.c @@ -0,0 +1,112 @@ +/**************************************************************************** + * eched/env_dupenv.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include + +#include + +#include "os_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dupenv + * + * Description: + * Copy the internal environment structure of a task. This is the action + * that is performed when a new task is created: The new task has a private, + * exact duplicate of the parent task's environment. + * + * Parameters: + * None + * + * Return Value: + * A pointer to a newly allocated copy of the specified TCB's environment + * structure with reference count equal to one. + * + * Assumptions: + * Not called from an interrupt handler. + * + ****************************************************************************/ + +FAR environ_t *dupenv(FAR _TCB *ptcb) +{ + environ_t *envp = NULL; + + /* Pre-emption must be disabled throughout the following because the + * environment may be shared. + */ + + sched_lock(); + + /* Does the parent task have an environment? */ + + if (ptcb->envp) + { + /* Yes..The parent task has an environment, duplicate it */ + + size_t envlen = ptcb->envp->ev_alloc + envp = (environ_t*)kmalloc(SIZEOF_ENVIRON_T( envlen )); + if (envp) + { + envp->ev_crefs = 1; + envp->ev_alloc = envlen; + memcmp( envp->ev_env, ptcb->envp->ev_env, envlen ); + } + } + + sched_unlock(); + return envp; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_findvar.c b/nuttx/sched/env_findvar.c new file mode 100644 index 0000000000..a8e94180c5 --- /dev/null +++ b/nuttx/sched/env_findvar.c @@ -0,0 +1,131 @@ +/**************************************************************************** + * sched/env_findvar.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: env_cmpname + ****************************************************************************/ + +static bool env_cmpname(const char *pszname, const char *peqname) +{ + /* Search until we find anything different in the two names */ + + for (; *pszname == *peqname; pszname++, peqname++); + + /* On sucess, pszname will end with '\0' and peqname with '=' */ + + if ( *pszname == '\0' && *peqname == '=' ) + { + return true; + } + + return false; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: env_findvar + * + * Description: + * Search the provided environment structure for the variable of the + * specified name. + * + * Parameters: + * envp The environment structre to be searched. + * pname The variable name to find + * + * Return Value: + * A pointer to the name=value string in the environment + * + * Assumptions: + * - Not called from an interrupt handler + * - Pre-emptions is disabled by caller + * + ****************************************************************************/ + +FAR char *env_findvar(environ_t *envp, const char *pname) +{ + char *ret = NULL; + + /* Verify input parameters */ + + if (envp && pname) + { + char *ptr; + char *end = &envp->ev_env[envp->ev_alloc]; + + /* Search for a name=value string with matching name */ + + for (ptr = envp->ev_env; + ptr < end && !env_cmpname( pname, ptr); + ptr += (strlen(ptr) + 1)); + + /* Check for success */ + + if (ptr < end) + { + ret = ptr; + } + } + + return ret; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_getenv.c b/nuttx/sched/env_getenv.c new file mode 100644 index 0000000000..ee8d798b1b --- /dev/null +++ b/nuttx/sched/env_getenv.c @@ -0,0 +1,135 @@ +/**************************************************************************** + * env_getenv.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getenv + * + * Description: + * The getenv() function searches the environment list for a string that + * matches the string pointed to by name. + * + * Parameters: + * name - The name of the variable to find. + * + * Return Value: + * The value of the valiable (read-only) or NULL on failure + * + * Assumptions: + * Not called from an interrupt handler + * + ****************************************************************************/ + +FAR char *getenv(const char *name) +{ + FAR _TCB *rtcb; + FAR environ_t *envp; + FAR char *pvar; + FAR char *pvalue = NULL; + int ret = OK; + + /* Verify that a string was passed */ + + if (!name) + { + ret = EINVAL; + goto errout; + } + + /* Get a reference to the thread-private environ in the TCB.*/ + + sched_lock(); + rtcb = (FAR _TCB*)g_readytorun.head; + envp = rtcb->envp; + + /* Check if the variable exists */ + + if ( !envp || (pvar = env_findvar(envp, name)) == NULL) + { + ret = ENOENT; + goto errout_with_lock; + } + + /* It does! Get the value sub-string from the name=value string */ + + pvalue = strchr(pvar, '='); + if (!pvalue) + { + /* The name=value string has no '=' This is a bug! */ + + ret = EINVAL; + goto errout_with_lock; + } + + /* Adjust the pointer so that it points to the value right after the '=' */ + + pvalue++; + sched_unlock(); + return pvalue; + +errout_with_lock: + sched_unlock(); +errout: + set_errno(ret); + return NULL; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_getenvironptr.c b/nuttx/sched/env_getenvironptr.c new file mode 100644 index 0000000000..25b09755b5 --- /dev/null +++ b/nuttx/sched/env_getenvironptr.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * env_getenvironptr.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include "os_internal.h" + +#undef get_environ_ptr + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: get_environ_ptr + * + * Description: + * Return a pointer to the thread specific environ variable. + * + * Parameters: + * None + * + * Return Value: + * A pointer to the per-thread environ variable. + * + * Assumptions: + * + ****************************************************************************/ + +FAR char **get_environ_ptr( void ) +{ +#if 1 + + /* Type of internal representation of environment is incompatible with + * char ** return value. + */ + + return NULL; + +#else + + /* Return a reference to the thread-private environ in the TCB.*/ + + FAR _TCB *ptcb = (FAR _TCB*)g_readytorun.head; + if (ptcb->envp) + { + return &ptcb->envp->ev_env; + } + else + { + return NULL; + } + +#endif +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_internal.h b/nuttx/sched/env_internal.h new file mode 100644 index 0000000000..a6205d6585 --- /dev/null +++ b/nuttx/sched/env_internal.h @@ -0,0 +1,95 @@ +/**************************************************************************** + * sched/env_internal.h + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __SCHED_ENV_INTERNAL_H +#define __SCHED_ENV_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#ifdef CONFIG_DISABLE_ENVIRON +# define env_dup(ptcb) (0) +# define env_share(ptcb) (0) +# define env_release(ptcb) (0) +#endif + +/**************************************************************************** + * Public Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#ifndef CONFIG_DISABLE_ENVIRON +/* functions used by the task/pthread creation and destruction logic */ + +EXTERN int env_dup(FAR _TCB *ptcb); +EXTERN int env_share(FAR _TCB *ptcb); +EXTERN int env_release(FAR _TCB *ptcb); + +/* functions used internally the environment handling logic */ + +EXTERN FAR char *env_findvar(environ_t *envp, const char *pname); +EXTERN int env_removevar(environ_t *envp, char *pvar); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __SCHED_ENV_INTERNAL_H */ + diff --git a/nuttx/sched/env_putenv.c b/nuttx/sched/env_putenv.c new file mode 100644 index 0000000000..ad00dd13df --- /dev/null +++ b/nuttx/sched/env_putenv.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * sched/env_putenv.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: putenv + * + * Description: + * The putenv() function adds or changes the value of environment variables. + * The argument string is of the form name=value. If name does not already + * exist in the environment, then string is added to the environment. If + * name does exist, then the value of name in the environment is changed to + * value. + * + * Parameters: + * name=value string describing the environment setting to add/modify + * + * Return Value: + * Zero on sucess + * + * Assumptions: + * Not called from an interrupt handler + * + ****************************************************************************/ + +int putenv(FAR const char *string) +{ + char *pname; + char *pequal; + int ret = OK; + + /* Verify that a string was passed */ + + if (!string) + { + ret = EINVAL; + goto errout; + } + + /* Parse the name=value string */ + + pname = strdup(string); + if (!pname) + { + ret = ENOMEM; + goto errout; + } + + pequal = strchr( pname, '='); + if (pequal) + { + /* Then let setenv do all of the work */ + + *pequal = '\0'; + ret = setenv(pname, pequal+1, TRUE); + } + + kfree(pname); + return ret; + +errout: + errno = ret; + return ERROR; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_release.c b/nuttx/sched/env_release.c new file mode 100644 index 0000000000..83e65dbb58 --- /dev/null +++ b/nuttx/sched/env_release.c @@ -0,0 +1,125 @@ +/**************************************************************************** + * sched/env_clearenv.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: env_release + * + * Description: + * The env_release() function clears the environment of all name-value + * pairs and sets the value of the external variable environ to NULL. + * + * Parameters: + * ptcb Identifies the TCB containing the environment structure + * + * Return Value: + * zero on success + * + * Assumptions: + * Not called from an interrupt handler + * + ****************************************************************************/ + +int env_release(FAR _TCB *ptcb) +{ + int ret = OK; + + if (!ptcb) + { + ret = -EINVAL; + } + else + { + FAR environ_t *envp; + + /* Examine the environ data in the TCB. Preemption is disabled because the + * the environment could be shared among threads. + */ + + sched_lock(); + envp = ptcb->envp; + if (ptcb->envp) + { + /* Check the reference count on the environment structure */ + + if ( envp->ev_crefs <= 1) + { + /* Decrementing the reference count will destroy the environment */ + + sched_free( envp ); /* plain free() should be fine here */ + } + else + { + /* The environment will persist after decrementing the reference + * count */ + + envp->ev_crefs--; + } + + /* In any case, the environment is no longer accessible on this thread */ + + ptcb->envp = NULL; + } + + sched_unlock(); + } + + return ret; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_removevar.c b/nuttx/sched/env_removevar.c new file mode 100644 index 0000000000..e96aa7a37c --- /dev/null +++ b/nuttx/sched/env_removevar.c @@ -0,0 +1,119 @@ +/**************************************************************************** + * sched/env_removevar.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: env_removevar + * + * Description: + * Remove the referenced name=value pair from the environment + * + * Parameters: + * envp The environment containing the name=value pair + * pvar A pointer to the name=value pair in the restroom + * + * Return Value: + * Zero on success + * + * Assumptions: + * - Not called from an interrupt handler + * - Caller has pre-emptions disabled + * - Caller will reallocate the environment structure to the correct size + * + ****************************************************************************/ + +int env_removevar(environ_t *envp, char *pvar) +{ + int ret = ERROR; + if (envp && pvar) + { + /* Verify that the pointer lies within the environment region */ + + int alloc = envp->ev_alloc; /* Size of the allocated environment */ + char *end = &envp->ev_env[alloc]; /* Pointer to the end+1 of the environment */ + + if (pvar >= envp->ev_env && pvar < end) + { + /* Set up for the removal */ + + int len = strlen(pvar) + 1; /* Length of name=value string to remove */ + char *src = &pvar[len]; /* Address of name=value string after */ + char *dest = pvar; /* Location to move the next string */ + int count = end - src; /* Number of bytes to move (might be zero) */ + + /* Move all of the environment strings after the removed one 'down.' + * this is inefficient, but robably not high duty. + */ + + while (count-- > 0) + { + *dest++ = *src++; + } + + /* Then set to the new allocation size. The caller is expected to + * call realloc at some point but we don't do that here because the + * caller may add more stuff to the environment. + */ + + envp->ev_alloc -= len; + ret = OK; + } + } + + return ret; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_setenv.c b/nuttx/sched/env_setenv.c new file mode 100644 index 0000000000..c186241ef2 --- /dev/null +++ b/nuttx/sched/env_setenv.c @@ -0,0 +1,208 @@ +/**************************************************************************** + * sched/env_setenv.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: setenv + * + * Description: + * The setenv() function adds the variable name to the environment with the + * specified 'value' if the varialbe 'name" does not exist. If the 'name' + * does exist in the environment, then its value is changed to 'value' if + * 'overwrite' is non-zero; if 'overwrite' is zero, then the value of name + * unaltered. + * + * Parameters: + * name - The name of the variable to change + * value - The new value of the variable + * overwrite - Replace any existing value if non-zero. + * + * Return Value: + * Zero on success + * + * Assumptions: + * Not called from an interrupt handler + * + ****************************************************************************/ + +int setenv(const char *name, const char *value, int overwrite) +{ + FAR _TCB *rtcb; + FAR environ_t *envp; + FAR char *pvar; + int varlen; + int ret = OK; + + /* Verify input parameter */ + + if (!name) + { + ret = EINVAL; + goto errout; + } + + /* if no value is provided, then this is the same as unsetenv (unless + * overwrite is false) + */ + + if (!value || *value == '\0') + { + /* If overwite is set then this is the same as unsetenv */ + + if (overwrite) + { + return unsetenv(name); + } + else + { + /* Otherwise, it is a request to remove a variable without altering it? */ + + return OK; + } + } + + /* Get a reference to the thread-private environ in the TCB.*/ + + sched_lock(); + rtcb = (FAR _TCB*)g_readytorun.head; + envp = rtcb->envp; + + /* Check if the variable alreay exists */ + + if ( envp && (pvar = env_findvar(envp, name)) != NULL) + { + /* It does! Do we have permission to overwrite the existing value? */ + + if (!overwrite) + { + /* No.. then just return success */ + + sched_unlock(); + return OK; + } + + /* Yes.. just remove the name=value pair from the environment. It will + * be added again below. Note that we are responsible for reallocating + * the environment buffer; this will happen below. + */ + + (void)env_removevar(envp, pvar); + } + + /* Get the size of the new name=value string. The +2 is for the '=' and for + * null terminator + */ + + varlen = strlen(name) + strlen(value) + 2; + + /* Then allocate or reallocate the environment buffer */ + + if (envp) + { + int alloc = envp->ev_alloc; + environ_t *tmp = (environ_t*)krealloc(envp, SIZEOF_ENVIRON_T(alloc + varlen)); + if (!tmp) + { + ret = ENOMEM; + goto errout_with_lock; + } + + envp = tmp; + envp->ev_alloc = alloc + varlen; + pvar = &envp->ev_env[alloc]; + } + else + { + envp = (environ_t*)kmalloc(SIZEOF_ENVIRON_T(varlen)); + if (!envp) + { + ret = ENOMEM; + goto errout_with_lock; + } + + envp->ev_crefs = 1; + envp->ev_alloc = varlen; + pvar = envp->ev_env; + } + + /* Now, put the new name=value string into the environment buffer */ + + sprintf(pvar, "%s=%s", name, value); + + /* Save the new environment pointer (it might have changed due to allocation or + * reallocation. + */ + + rtcb->envp = envp; + sched_unlock(); + return OK; + +errout_with_lock: + sched_unlock(); +errout: + errno = ret; + return ERROR; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_share.c b/nuttx/sched/env_share.c new file mode 100644 index 0000000000..5f37a02195 --- /dev/null +++ b/nuttx/sched/env_share.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * sched/env_share.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: env_share + * + * Description: + * Increment the reference count on the internal environment structure of + * a task. This is the action that is performed when a new pthread is + * created: The new pthread shares the environment with its parent. + * + * Parameters: + * ptcb The new TCB to receive the shared environment. + * + * Return Value: + * A pointer to a specified TCB's environment structure with an incremented + * reference count. + * + * Assumptions: + * Not called from an interrupt handler. + * + ****************************************************************************/ + +int env_share(FAR _TCB *ptcb) +{ + int ret = OK; + if (!ptcb) + { + ret = -EINVAL; + } + else + { + FAR _TCB *parent = (FAR _TCB*)g_readytorun.head; + environ_t *envp = parent->envp; + + /* Pre-emption must be disabled throughout the following because the + * environment is shared. + */ + + sched_lock(); + + /* Does the parent task have an environment? */ + + if (envp) + { + /* Yes.. increment the reference count on the environment */ + + envp->ev_crefs++; + } + + /* Then share the environment */ + + ptcb->envp = envp; + sched_unlock(); + } + + return ret; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_unsetenv.c b/nuttx/sched/env_unsetenv.c new file mode 100644 index 0000000000..52469fac9c --- /dev/null +++ b/nuttx/sched/env_unsetenv.c @@ -0,0 +1,138 @@ +/**************************************************************************** + * sched/env_unsetenv.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include + +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: unsetenv + * + * Description: + * The unsetenv() function deletes the variable name from the environment. + * + * Parameters: + * name - The name of the variable to delete + * + * Return Value: + * Zero on success + * + * Assumptions: + * Not called from an interrupt handler + * + ****************************************************************************/ + +int unsetenv(const char *name) +{ + FAR _TCB *rtcb; + FAR environ_t *envp; + FAR char *pvar; + int ret = OK; + + /* Verify input parameter */ + + if (!name) + { + ret = EINVAL; + goto errout; + } + + /* Get a reference to the thread-private environ in the TCB.*/ + + sched_lock(); + rtcb = (FAR _TCB*)g_readytorun.head; + envp = rtcb->envp; + + /* Check if the variable exists */ + + if ( envp && (pvar = env_findvar(envp, name)) != NULL) + { + int alloc; + environ_t *tmp; + + /* It does! Remove the name=value pair from the environment. */ + + (void)env_removevar(envp, pvar); + + /* Reallocate the new environment buffer */ + + alloc = envp->ev_alloc; + tmp = (environ_t*)krealloc(envp, SIZEOF_ENVIRON_T(alloc)); + if (!tmp) + { + ret = ENOMEM; + goto errout_with_lock; + } + + /* Save the new environment pointer (it might have changed due to reallocation. */ + + rtcb->envp = tmp; + } + + sched_unlock(); + return OK; + +errout_with_lock: + sched_unlock(); +errout: + errno = ret; + return ERROR; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/errno_get.c b/nuttx/sched/errno_get.c new file mode 100644 index 0000000000..cac041f64a --- /dev/null +++ b/nuttx/sched/errno_get.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * sched/errno_get.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#undef get_errno_ptr +#undef get_errno +#undef errno + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: get_errno + * + * Description: + * Return the value of the thread specific errno. This function is only + * intended to provide a mechanism for user-mode programs to get the + * thread-specific errno value. It is #define'd to the symbol errno in + * include/errno.h. + * + * Parameters: + * None + * + * Return Value: + * The current value of the thread specific errno. + * + * Assumptions: + * + ****************************************************************************/ + +int get_errno(void) +{ + return *get_errno_ptr(); +} + + diff --git a/nuttx/sched/errno_getptr.c b/nuttx/sched/errno_getptr.c new file mode 100644 index 0000000000..0b27768da8 --- /dev/null +++ b/nuttx/sched/errno_getptr.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * sched/errno_getptr.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include "os_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#undef get_errno_ptr +#undef errno + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static int g_irqerrno; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: get_errno_ptr + * + * Description: + * Return a pointer to the thread specific errno. + * + * Parameters: + * None + * + * Return Value: + * A pointer to the per-thread errno variable. + * + * Assumptions: + * + ****************************************************************************/ + +FAR int *get_errno_ptr(void) +{ + /* Check if this function was called from an interrupt handler. In that + * case, we have to do things a little differently to prevent the interrupt + * handler from modifying the tasks errno value. + */ + + if (!up_interrupt_context()) + { + /* We were called from the normal tasking context. Verify that the + * task at the head of the ready-to-run list is actually running. It + * may not be running during very brief times during context switching + * logic (see, for example, task_deletecurrent.c). + */ + + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + if (rtcb->task_state == TSTATE_TASK_RUNNING) + { + /* Yes.. the task is running normally. Return a reference to the + * thread-private errno in the TCB of the running task. + */ + + return &rtcb->pterrno; + } + } + + /* We were called either from (1) an interrupt handler or (2) from normally + * code but in an unhealthy state. In either event, do not permit access to + * the errno in the TCB of the task at the head of the ready-to-run list. + * Instead, use a separate errno just for interrupt handlers. Of course, this + * would have to change if we ever wanted to support nested interrupts or if + * we really cared about the stability of the errno during those "unhealthy + * states." + */ + + return &g_irqerrno; +} + + diff --git a/nuttx/sched/errno_set.c b/nuttx/sched/errno_set.c new file mode 100644 index 0000000000..eda680b64e --- /dev/null +++ b/nuttx/sched/errno_set.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * sched/errno_set.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#undef get_errno_ptr +#undef set_errno +#undef errno + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: set_errno + * + * Description: + * Set the value of the thread specific errno. This function is only + * intended to provide a mechanism for user-mode programs to set the + * thread-specific errno value. + * + * Parameters: + * errcode - The thread specific errno will be set to this error code value. + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void set_errno(int errcode) +{ + *get_errno_ptr() = errcode; +} + + diff --git a/nuttx/sched/exit.c b/nuttx/sched/exit.c new file mode 100644 index 0000000000..7e50c273cf --- /dev/null +++ b/nuttx/sched/exit.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * sched/exit.c + * + * Copyright (C) 2007-2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: exit + * + * Description: + * The exit() function causes normal process termination and the value of + * status & 0377 to be returned to the parent. + * + * All functions registered with atexit() and on_exit() are called, in the + * reverse order of their registration. + * + * All open streams are flushed and closed. + * + ****************************************************************************/ + +void exit(int status) +{ + _TCB *tcb = (_TCB*)g_readytorun.head; + + /* Only the lower 8-bits of status are used */ + + status &= 0xff; + + /* Perform common task termination logic */ + + task_exithook(tcb, status); + + /* Then "really" exit. Only the lower 8 bits of the exit status are used. */ + + _exit(status); +} diff --git a/nuttx/sched/getpid.c b/nuttx/sched/getpid.c new file mode 100644 index 0000000000..f41467d9fa --- /dev/null +++ b/nuttx/sched/getpid.c @@ -0,0 +1,85 @@ +/************************************************************************ + * sched/getpid.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: getpid + * + * Description: + * Get the task ID of the currently executing task. + * + ************************************************************************/ + +pid_t getpid(void) +{ + /* Return the task ID from the TCB at the head of the + * ready-to-run task list + */ + + return ((FAR _TCB*)g_readytorun.head)->pid; +} diff --git a/nuttx/sched/irq_attach.c b/nuttx/sched/irq_attach.c new file mode 100644 index 0000000000..3f27a05309 --- /dev/null +++ b/nuttx/sched/irq_attach.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * sched/irq_attach.c + * + * Copyright (C) 2007-2008, 2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "irq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: irq_attach + * + * Description: + * Configure the IRQ subsystem so that IRQ number 'irq' is dispatched to + * 'isr' + * + ****************************************************************************/ + +int irq_attach(int irq, xcpt_t isr) +{ +#if NR_IRQS > 0 + int ret = ERROR; + + if ((unsigned)irq < NR_IRQS) + { + irqstate_t state; + + /* If the new ISR is NULL, then the ISR is being detached. + * In this case, disable the ISR and direct any interrupts + * to the unexpected interrupt handler. + */ + + state = irqsave(); + if (isr == NULL) + { + /* Disable the interrupt if we can before detaching it. We might + * not be able to do this if: (1) the device does not have a + * centralized interrupt controller (so up_disable_irq() is not + * supported). Or (2) if the device has different number for vector + * numbers and IRQ numbers (in that case, we don't know the correct + * IRQ number to use to disable the interrupt). In those cases, the + * code will just need to be careful that it disables all interrupt + * sources before detaching from the interrupt vector. + */ + +#if !defined(CONFIG_ARCH_NOINTC) && !defined(CONFIG_ARCH_VECNOTIRQ) + up_disable_irq(irq); +#endif + /* Detaching the ISR really means re-attaching it to the + * unexpected exception handler. + */ + + isr = irq_unexpected_isr; + } + + /* Save the new ISR in the table. */ + + g_irqvector[irq] = isr; + irqrestore(state); + ret = OK; + } + + return ret; +#else + return OK; +#endif +} diff --git a/nuttx/sched/irq_dispatch.c b/nuttx/sched/irq_dispatch.c new file mode 100644 index 0000000000..1c39f59d13 --- /dev/null +++ b/nuttx/sched/irq_dispatch.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * sched/irq_dispatch.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "irq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: irq_dispatch + * + * Description: + * This function must be called from the achitecture-specific logic in + * order to dispatch an interrupt to the appropriate, registered handling + * logic. + * + ***************************************************************************/ + +void irq_dispatch(int irq, FAR void *context) +{ + xcpt_t vector; + + /* Perform some sanity checks */ + +#if NR_IRQS > 0 + if ((unsigned)irq >= NR_IRQS || g_irqvector[irq] == NULL) + { + vector = irq_unexpected_isr; + } + else + { + vector = g_irqvector[irq]; + } +#else + vector = irq_unexpected_isr; +#endif + + /* Then dispatch to the interrupt handler */ + + vector(irq, context); +} + diff --git a/nuttx/sched/irq_initialize.c b/nuttx/sched/irq_initialize.c new file mode 100644 index 0000000000..2053dcb833 --- /dev/null +++ b/nuttx/sched/irq_initialize.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * sched/irq_initialize.c + * + * Copyright (C) 2007-2008, 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "irq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +FAR xcpt_t g_irqvector[NR_IRQS+1]; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: irq_initialize + * + * Description: + * Configure the IRQ subsystem + * + ****************************************************************************/ + +void irq_initialize(void) +{ + int i; + + /* Point all interrupt vectors to the unexpected interrupt */ + + for (i = 0; i < NR_IRQS; i++) + { + g_irqvector[i] = irq_unexpected_isr; + } +} + diff --git a/nuttx/sched/irq_internal.h b/nuttx/sched/irq_internal.h new file mode 100644 index 0000000000..28411f64ff --- /dev/null +++ b/nuttx/sched/irq_internal.h @@ -0,0 +1,83 @@ +/**************************************************************************** + * sched/irq_internal.h + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __SCHED_IRQ_INTERNAL_H +#define __SCHED_IRQ_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Declarations + ****************************************************************************/ + +extern FAR xcpt_t g_irqvector[NR_IRQS+1]; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN void weak_function irq_initialize(void); +EXTERN int irq_unexpected_isr(int irq, FAR void *context); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __SCHED_IRQ_INTERNAL_H */ + diff --git a/nuttx/sched/irq_unexpectedisr.c b/nuttx/sched/irq_unexpectedisr.c new file mode 100644 index 0000000000..c0090ead4a --- /dev/null +++ b/nuttx/sched/irq_unexpectedisr.c @@ -0,0 +1,88 @@ +/**************************************************************************** + * sched/irq_unexpectedisr.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "os_internal.h" +#include "irq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: irq_unexpected_isr + * + * Description: + * An interrupt has been received for an IRQ that was never registered + * with the system. + * + ****************************************************************************/ + +int irq_unexpected_isr(int irq, FAR void *context) +{ + (void)irqsave(); + lldbg("irq: %d\n", irq); + PANIC(OSERR_UNEXPECTEDISR); + return OK; /* Won't get here */ +} diff --git a/nuttx/sched/kmm_addregion.c b/nuttx/sched/kmm_addregion.c new file mode 100644 index 0000000000..652367f5ae --- /dev/null +++ b/nuttx/sched/kmm_addregion.c @@ -0,0 +1,113 @@ +/************************************************************************ + * sched/kmm_addregion.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* This value is obtained from user_map.h */ + +#define KADDREGION(h,s) ((kmaddregion_t)CONFIG_USER_MMADDREGION)(h,s) + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef void (*kmaddregion_t)(FAR void*, size_t); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: kmm_addregion + * + * Description: + * This is a simple redirection to the user-space mm_addregion() + * function. + * + * Parameters: + * heap_start - Address of the beginning of the memory region + * heap_size - The size (in bytes) if the memory region. + * + * Return Value: + * None + * + * Assumptions: + * 1. mm_addregion() resides in user-space + * 2. The address of the user space mm_addregion() is provided in + * user_map.h + * 3. The user-space mm_addregion() is callable from kernel-space. + * + ************************************************************************/ + +void kmm_addregion(FAR void *heap_start, size_t heap_size) +{ + return KADDREGION(heap_start, heap_size); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/kmm_initialize.c b/nuttx/sched/kmm_initialize.c new file mode 100644 index 0000000000..6dd08951b1 --- /dev/null +++ b/nuttx/sched/kmm_initialize.c @@ -0,0 +1,113 @@ +/************************************************************************ + * sched/kmm_initialize.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* This value is obtained from user_map.h */ + +#define KINITIALIZE(h,s) ((kminitialize_t)CONFIG_USER_MMINIT)(h,s) + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef void (*kminitialize_t)(FAR void*, size_t); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: kmm_initialize + * + * Description: + * This is a simple redirection to the user-space mm_initialize() + * function. + * + * Parameters: + * heap_start - Address of the beginning of the (initial) memory region + * heap_size - The size (in bytes) if the (initial) memory region. + * + * Return Value: + * None + * + * Assumptions: + * 1. mm_initialize() resides in user-space + * 2. The address of the user space mm_initialize() is provided in + * user_map.h + * 3. The user-space mm_initialize() is callable from kernel-space. + * + ************************************************************************/ + +void kmm_initialize(FAR void *heap_start, size_t heap_size) +{ + return KINITIALIZE(heap_start, heap_size); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/kmm_kfree.c b/nuttx/sched/kmm_kfree.c new file mode 100644 index 0000000000..0f0eaa6c25 --- /dev/null +++ b/nuttx/sched/kmm_kfree.c @@ -0,0 +1,110 @@ +/************************************************************************ + * sched/kmm_kfree.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* This value is obtained from user_map.h */ + +#define KFREE(p) ((kfree_t)CONFIG_USER_FREE)(p) + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef void (*kfree_t)(FAR void *); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: kfree + * + * Description: + * This is a simple redirection to the user-space free() function. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * 1. free() resides in user-space + * 2. The address of the user space free() is provided in user_map.h + * 3. The user-space free() is callable from kernel-space. + * + ************************************************************************/ + +void kfree(FAR void *mem) +{ + return KFREE(mem); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/kmm_kmalloc.c b/nuttx/sched/kmm_kmalloc.c new file mode 100644 index 0000000000..5e34c157f4 --- /dev/null +++ b/nuttx/sched/kmm_kmalloc.c @@ -0,0 +1,110 @@ +/************************************************************************ + * sched/kmm_kmalloc.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* This value is obtained from user_map.h */ + +#define KMALLOC(s) ((kmalloc_t)CONFIG_USER_MALLOC)(s) + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef FAR void *(*kmalloc_t)(size_t); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: kmalloc + * + * Description: + * This is a simple redirection to the user-space malloc() function. + * + * Parameters: + * size - Size (in bytes) of the memory region to be allocated. + * + * Return Value: + * The address of the allocated memory (NULL on failure to allocate) + * + * Assumptions: + * 1. malloc() resides in user-space + * 2. The address of the user space malloc() is provided in user_map.h + * 3. The user-space malloc() is callable from kernel-space. + * + ************************************************************************/ + +FAR void *kmalloc(size_t size) +{ + return KMALLOC(size); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/kmm_krealloc.c b/nuttx/sched/kmm_krealloc.c new file mode 100644 index 0000000000..3d37265669 --- /dev/null +++ b/nuttx/sched/kmm_krealloc.c @@ -0,0 +1,111 @@ +/************************************************************************ + * sched/kmm_krealloc.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* This value is obtained from user_map.h */ + +#define KREALLOC(p,s) ((krealloc_t)CONFIG_USER_REALLOC)(p,s) + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef FAR void *(*krealloc_t)(FAR void*, size_t); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: krealloc + * + * Description: + * This is a simple redirection to the user-space realloc() function. + * + * Parameters: + * oldmem - The old memory allocated + * size - Size (in bytes) of the new memory region to be re-allocated. + * + * Return Value: + * The address of the re-allocated memory (NULL on failure to re-allocate) + * + * Assumptions: + * 1. realloc() resides in user-space + * 2. The address of the user space realloc() is provided in user_map.h + * 3. The user-space realloc() is callable from kernel-space. + * + ************************************************************************/ + +FAR void *krealloc(FAR void *oldmem, size_t size) +{ + return KREALLOC(oldmem, size); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/kmm_kzalloc.c b/nuttx/sched/kmm_kzalloc.c new file mode 100644 index 0000000000..42bcfcc0f5 --- /dev/null +++ b/nuttx/sched/kmm_kzalloc.c @@ -0,0 +1,110 @@ +/************************************************************************ + * sched/kmm_kzalloc.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* This value is obtained from user_map.h */ + +#define KZALLOC(s) ((kzalloc_t)CONFIG_USER_ZALLOC)(s) + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef FAR void *(*kzalloc_t)(size_t); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: kzalloc + * + * Description: + * This is a simple redirection to the user-space zalloc() function. + * + * Parameters: + * size - Size (in bytes) of the memory region to be allocated. + * + * Return Value: + * The address of the allocated memory (NULL on failure to allocate) + * + * Assumptions: + * 1. zalloc() resides in user-space + * 2. The address of the user space zalloc() is provided in user_map.h + * 3. The user-space zalloc() is callable from kernel-space. + * + ************************************************************************/ + +FAR void *kzalloc(size_t size) +{ + return KZALLOC(size); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/kmm_semaphore.c b/nuttx/sched/kmm_semaphore.c new file mode 100644 index 0000000000..7fce747b6f --- /dev/null +++ b/nuttx/sched/kmm_semaphore.c @@ -0,0 +1,140 @@ +/************************************************************************ + * sched/kmm_semaphore.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* These values are obtained from user_map.h */ + +#define KTRYSEMAPHORE() ((kmtrysemaphore_t) CONFIG_USER_MMTRYSEM )() +#define KGIVESEMAPHORE() ((kmgivesemaphore_t)CONFIG_USER_MMGIVESEM)() + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef int (*kmtrysemaphore_t)(void); +typedef void (*kmgivesemaphore_t)(void); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: kmm_trysemaphore + * + * Description: + * This is a simple redirection to the user-space mm_trysemaphore() + * function. + * + * Parameters: + * None + * + * Return Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * 1. mm_trysemaphore() resides in user-space + * 2. The address of the user space mm_trysemaphore() is provided in + * user_map.h + * 3. The user-space mm_semaphore() is callable from kernel-space. + * + ************************************************************************/ + +int kmm_trysemaphore(void) +{ + return KTRYSEMAPHORE(); +} + +/************************************************************************ + * Name: kmm_givesemaphore + * + * Description: + * This is a simple redirection to the user-space mm_givesemaphore() + * function. + * + * Parameters: + * None + * + * Return Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * 1. mm_givesemaphore() resides in user-space + * 2. The address of the user space mm_givesemaphore() is provided in + * user_map.h + * 3. The user-space mm_semaphore() is callable from kernel-space. + * + ************************************************************************/ + +void kmm_givesemaphore(void) +{ + KGIVESEMAPHORE(); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/mq_close.c b/nuttx/sched/mq_close.c new file mode 100644 index 0000000000..57780a8e6a --- /dev/null +++ b/nuttx/sched/mq_close.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * sched/mq_close.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "os_internal.h" +#include "mq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_desfree + * + * Description: + * Deallocate a message queue descriptor but returning it to the free list + * + * Inputs: + * mqdes - message queue descriptor to free + * + ****************************************************************************/ + +#define mq_desfree(mqdes) sq_addlast((FAR sq_entry_t*)mqdes, &g_desfree) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_close + * + * Description: + * This function is used to indicate that the calling task is finished + * with the specified message queued mqdes. The mq_close() deallocates + * any system resources allocated by the system for use by this task for + * its message queue. + * + * If the calling task has attached a notification to the message queue + * via this mqdes, this attachment will be removed and the message queue + * is available for another process to attach a notification. + * + * Parameters: + * mqdes - Message queue descriptor. + * + * Return Value: + * 0 (OK) if the message queue is closed successfully, + * otherwise, -1 (ERROR). + * + * Assumptions: + * - The behavior of a task that is blocked on either a mq_send() or + * mq_receive() is undefined when mq_close() is called. + * - The results of using this message queue descriptor after a successful + * return from mq_close() is undefined. + * + ****************************************************************************/ + +int mq_close(mqd_t mqdes) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR msgq_t *msgq; + irqstate_t saved_state; + int ret = ERROR; + + /* Verify the inputs */ + + if (mqdes) + { + sched_lock(); + + /* Remove the message descriptor from the current task's + * list of message descriptors. + */ + + sq_rem((FAR sq_entry_t*)mqdes, &rtcb->msgdesq); + + /* Find the message queue associated with the message descriptor */ + + msgq = mqdes->msgq; + + /* Check if the calling task has a notification attached to + * the message queue via this mqdes. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + if (msgq->ntmqdes == mqdes) + { + msgq->ntpid = INVALID_PROCESS_ID; + msgq->ntsigno = 0; + msgq->ntvalue.sival_int = 0; + msgq->ntmqdes = NULL; + } +#endif + + /* Decrement the connection count on the message queue. */ + + if (msgq->nconnect) + { + msgq->nconnect--; + } + + /* If it is no longer connected to any message descriptor and if the + * message queue has already been unlinked, then we can discard the + * message queue. + */ + + if (!msgq->nconnect && msgq->unlinked) + { + /* Remove the message queue from the list of all + * message queues + */ + + saved_state = irqsave(); + (void)sq_rem((FAR sq_entry_t*)msgq, &g_msgqueues); + irqrestore(saved_state); + + /* Then deallocate it (and any messages left in it) */ + + mq_msgqfree(msgq); + } + + /* Deallocate the message descriptor */ + + mq_desfree(mqdes); + + sched_unlock(); + ret = OK; + } + + return ret; +} + diff --git a/nuttx/sched/mq_descreate.c b/nuttx/sched/mq_descreate.c new file mode 100644 index 0000000000..14937888c5 --- /dev/null +++ b/nuttx/sched/mq_descreate.c @@ -0,0 +1,159 @@ +/**************************************************************************** + * sched/mq_descreate.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +#include "mq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_desalloc + * + * Description: + * Allocate a message queue descriptor. + * + * Inputs: + * None + * + * Return Value: + * Reference to the allocated mq descriptor. + * + ****************************************************************************/ + +static mqd_t mq_desalloc(void) +{ + mqd_t mqdes; + + /* Try to get the message descriptorfrom the free list */ + + mqdes = (mqd_t)sq_remfirst(&g_desfree); + + /* Check if we got one. */ + + if (!mqdes) + { + /* Add another block of message descriptors to the list */ + + mq_desblockalloc(); + + /* And try again */ + + mqdes = (mqd_t)sq_remfirst(&g_desfree); + } + + return mqdes; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_descreate + * + * Description: + * Create a message queue descriptor for the specified TCB + * + * Inputs: + * TCB - task that needs the descriptor. + * msgq - Named message queue containing the message + * oflags - access rights for the descriptor + * + * Return Value: + * On success, the message queue descriptor is returned. NULL is returned + * on a failure to allocate. + * + ****************************************************************************/ + +mqd_t mq_descreate(FAR _TCB* mtcb, FAR msgq_t* msgq, int oflags) +{ + mqd_t mqdes; + + /* Create a message queue descriptor for the TCB */ + + mqdes = mq_desalloc(); + if (mqdes) + { + /* Initialize the MQ descriptor */ + + memset(mqdes, 0, sizeof(struct mq_des)); + mqdes->msgq = msgq; + mqdes->oflags = oflags; + + /* And add it to the specified tasks's TCB */ + + sq_addlast((FAR sq_entry_t*)mqdes, &mtcb->msgdesq); + } + + return mqdes; +} diff --git a/nuttx/sched/mq_findnamed.c b/nuttx/sched/mq_findnamed.c new file mode 100644 index 0000000000..d23b81c5ed --- /dev/null +++ b/nuttx/sched/mq_findnamed.c @@ -0,0 +1,105 @@ +/************************************************************************ + * sched/mq_findnamed.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +#include "mq_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_findnamed + * + * Description: + * This function finds the named message queue with the specified name + * in the list of message queues. + * + * Inputs: + * mq_name - the name of the message queue to find + * + * Return Value: + * A reference to the matching named message queue structure (or NULL + * if none was found). + * + ************************************************************************/ + +FAR msgq_t *mq_findnamed(const char *mq_name) +{ + FAR msgq_t *msgq; + + /* Search the list of named message queues */ + + for (msgq = (FAR msgq_t*)g_msgqueues.head; (msgq); msgq = msgq->flink) + { + /* Break out of the lloop with a non-NULL msgq if the + * name matches. + */ + + if (!strcmp(mq_name, msgq->name)) + { + break; + } + } + + return msgq; +} diff --git a/nuttx/sched/mq_initialize.c b/nuttx/sched/mq_initialize.c new file mode 100644 index 0000000000..5b03a11201 --- /dev/null +++ b/nuttx/sched/mq_initialize.c @@ -0,0 +1,243 @@ +/************************************************************************ + * sched/mq_initialize.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include + +#include "mq_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/* This is a container for a list of message queue descriptors. */ + +struct mq_des_block_s +{ + sq_entry_t queue; + struct mq_des mqdes[NUM_MSG_DESCRIPTORS]; +}; + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/* This is a list of all opened message queues */ + +sq_queue_t g_msgqueues; + +/* The g_msgfree is a list of messages that are available for general + * use. The number of messages in this list is a system configuration + * item. + */ + +sq_queue_t g_msgfree; + +/* The g_msgfreeInt is a list of messages that are reserved for use by + * interrupt handlers. + */ + +sq_queue_t g_msgfreeirq; + +/* The g_desfree data structure is a list of message descriptors available + * to the operating system for general use. The number of messages in the + * pool is a constant. + */ + +sq_queue_t g_desfree; + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/* g_msgalloc is a pointer to the start of the allocated block of + * messages. + */ + +static mqmsg_t *g_msgalloc; + +/* g_msgfreeirqalloc is a pointer to the start of the allocated block of + * messages. + */ + +static mqmsg_t *g_msgfreeirqalloc; + +/* g_desalloc is a list of allocated block of message queue descriptors. */ + +static sq_queue_t g_desalloc; + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_msgblockalloc + * + * Description: + * Allocate a block of messages and place them on the free list. + * + * Inputs Parameters: + * queue + * + ************************************************************************/ + +static mqmsg_t *mq_msgblockalloc(sq_queue_t *queue, uint16_t nmsgs, + uint8_t alloc_type) +{ + mqmsg_t *mqmsgblock; + + /* The g_msgfree must be loaded at initialization time to hold the + * configured number of messages. + */ + + mqmsgblock = (mqmsg_t*)kmalloc(sizeof(mqmsg_t) * nmsgs); + if (mqmsgblock) + { + mqmsg_t *mqmsg = mqmsgblock; + int i; + + for (i = 0; i < nmsgs; i++) + { + mqmsg->type = alloc_type; + sq_addlast((FAR sq_entry_t*)mqmsg++, queue); + } + } + + return mqmsgblock; +} + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_initialize + * + * Description: + * This function initializes the messasge system. This function must + * be called early in the initialization sequence before any of the + * other message interfaces execute. + * + * Inputs: + * None + * + * Return Value: + * None + * + ************************************************************************/ + +void mq_initialize(void) +{ + /* Initialize the list of message queues */ + + sq_init(&g_msgqueues); + + /* Initialize the message free lists */ + + sq_init(&g_msgfree); + sq_init(&g_msgfreeirq); + sq_init(&g_desalloc); + + /* Allocate a block of messages for general use */ + + g_msgalloc = + mq_msgblockalloc(&g_msgfree, CONFIG_PREALLOC_MQ_MSGS, + MQ_ALLOC_FIXED); + + /* Allocate a block of messages for use exclusively by + * interrupt handlers + */ + + g_msgfreeirqalloc = + mq_msgblockalloc(&g_msgfreeirq, NUM_INTERRUPT_MSGS, + MQ_ALLOC_IRQ); + + /* Allocate a block of message queue descriptors */ + + mq_desblockalloc(); +} + +/************************************************************************ + * Name: mq_desblockalloc + * + * Description: + * Allocate a block of message descriptors and place them on the free + * list. + * + * Inputs: + * None + * + * Return Value: + * None + * + ************************************************************************/ + +void mq_desblockalloc(void) +{ + struct mq_des_block_s *mqdesblock; + + /* Allocate a block of message descriptors */ + + mqdesblock = (struct mq_des_block_s *)kmalloc(sizeof(struct mq_des_block_s)); + if (mqdesblock) + { + int i; + + /* Add the block to the list of allocated blocks (in case + * we ever need to reclaim the memory. + */ + + sq_addlast((FAR sq_entry_t*)&mqdesblock->queue, &g_desalloc); + + /* Then add each message queue descriptor to the free list */ + + for (i = 0; i < NUM_MSG_DESCRIPTORS; i++) + { + sq_addlast((FAR sq_entry_t*)&mqdesblock->mqdes[i], &g_desfree); + } + } +} + diff --git a/nuttx/sched/mq_internal.h b/nuttx/sched/mq_internal.h new file mode 100644 index 0000000000..6135bfaef3 --- /dev/null +++ b/nuttx/sched/mq_internal.h @@ -0,0 +1,183 @@ +/**************************************************************************** + * sched/mq_internal.h + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __SCHED_MQ_INTERNAL_H +#define __SCHED_MQ_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#if CONFIG_MQ_MAXMSGSIZE > 0 + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define MQ_MAX_BYTES CONFIG_MQ_MAXMSGSIZE +#define MQ_MAX_MSGS 16 +#define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX + +/* This defines the number of messages descriptors to allocate at each + * "gulp." + */ + +#define NUM_MSG_DESCRIPTORS 24 + +/* This defines the number of messages to set aside for exclusive use by + * interrupt handlers + */ + +#define NUM_INTERRUPT_MSGS 8 + +/**************************************************************************** + * Global Type Declarations + ****************************************************************************/ + +enum mqalloc_e +{ + MQ_ALLOC_FIXED = 0, /* pre-allocated; never freed */ + MQ_ALLOC_DYN, /* dynamically allocated; free when unused */ + MQ_ALLOC_IRQ /* Preallocated, reserved for interrupt handling */ +}; + +typedef enum mqalloc_e mqalloc_t; + +/* This structure describes one buffered POSIX message. */ + +struct mqmsg +{ + FAR struct mqmsg *next; /* Forward link to next message */ + uint8_t type; /* (Used to manage allocations) */ + uint8_t priority; /* priority of message */ +#if MQ_MAX_BYTES < 256 + uint8_t msglen; /* Message data length */ +#else + uint16_t msglen; /* Message data length */ +#endif + uint8_t mail[MQ_MAX_BYTES]; /* Message data */ +}; + +typedef struct mqmsg mqmsg_t; + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* This is a list of all opened message queues */ + +extern sq_queue_t g_msgqueues; + +/* The g_msgfree is a list of messages that are available for general use. + * The number of messages in this list is a system configuration item. + */ + +extern sq_queue_t g_msgfree; + +/* The g_msgfreeInt is a list of messages that are reserved for use by + * interrupt handlers. + */ + +extern sq_queue_t g_msgfreeirq; + +/* The g_desfree data structure is a list of message descriptors available + * to the operating system for general use. The number of messages in the + * pool is a constant. + */ + +extern sq_queue_t g_desfree; + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Functions defined in mq_initialize.c ************************************/ + +EXTERN void weak_function mq_initialize(void); +EXTERN void mq_desblockalloc(void); + +EXTERN mqd_t mq_descreate(FAR _TCB* mtcb, FAR msgq_t* msgq, int oflags); +EXTERN FAR msgq_t *mq_findnamed(const char *mq_name); +EXTERN void mq_msgfree(FAR mqmsg_t *mqmsg); +EXTERN void mq_msgqfree(FAR msgq_t *msgq); + +/* mq_waitirq.c ************************************************************/ + +EXTERN void mq_waitirq(FAR _TCB *wtcb, int errcode); + +/* mq_rcvinternal.c ********************************************************/ + +EXTERN int mq_verifyreceive(mqd_t mqdes, void *msg, size_t msglen); +EXTERN FAR mqmsg_t *mq_waitreceive(mqd_t mqdes); +EXTERN ssize_t mq_doreceive(mqd_t mqdes, mqmsg_t *mqmsg, void *ubuffer, + int *prio); + +/* mq_sndinternal.c ********************************************************/ + +EXTERN int mq_verifysend(mqd_t mqdes, const void *msg, size_t msglen, + int prio); +EXTERN FAR mqmsg_t *mq_msgalloc(void); +EXTERN int mq_waitsend(mqd_t mqdes); +EXTERN int mq_dosend(mqd_t mqdes, FAR mqmsg_t *mqmsg, const void *msg, + size_t msglen, int prio); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_MQ_MAXMSGSIZE > 0 */ +#endif /* __SCHED_MQ_INTERNAL_H */ + diff --git a/nuttx/sched/mq_msgfree.c b/nuttx/sched/mq_msgfree.c new file mode 100644 index 0000000000..91322fbf30 --- /dev/null +++ b/nuttx/sched/mq_msgfree.c @@ -0,0 +1,134 @@ +/************************************************************************ + * sched/mq_msgfree.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include "os_internal.h" +#include "mq_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_msgfree + * + * Description: + * The mq_msgfree function will return a message to the free pool of + * messages if it was a pre-allocated message. If the message was + * allocated dynamically it will be deallocated. + * + * Inputs: + * mqmsg - message to free + * + * Return Value: + * None + * + ************************************************************************/ + +void mq_msgfree(FAR mqmsg_t *mqmsg) +{ + irqstate_t saved_state; + + /* If this is a generally available pre-allocated message, + * then just put it back in the free list. + */ + + if (mqmsg->type == MQ_ALLOC_FIXED) + { + /* Make sure we avoid concurrent access to the free + * list from interrupt handlers. + */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)mqmsg, &g_msgfree); + irqrestore(saved_state); + } + + /* If this is a message pre-allocated for interrupts, + * then put it back in the correct free list. + */ + + else if (mqmsg->type == MQ_ALLOC_IRQ) + { + /* Make sure we avoid concurrent access to the free + * list from interrupt handlers. + */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)mqmsg, &g_msgfreeirq); + irqrestore(saved_state); + } + + /* Otherwise, deallocate it. Note: interrupt handlers + * will never deallocate messages because they will not + * received them. + */ + + else if (mqmsg->type == MQ_ALLOC_DYN) + { + sched_free(mqmsg); + } + else + { + PANIC(OSERR_BADMSGTYPE); + } +} diff --git a/nuttx/sched/mq_msgqfree.c b/nuttx/sched/mq_msgqfree.c new file mode 100644 index 0000000000..d7d87db3d8 --- /dev/null +++ b/nuttx/sched/mq_msgqfree.c @@ -0,0 +1,108 @@ +/************************************************************************ + * sched/mq_msgqfree.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include "mq_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_msgqfree + * + * Description: + * This function deallocates an initialized message queue + * structure. First, it deallocates all of the queued + * messages in the message Q. It is assumed that this + * message is fully unlinked and closed so that not thread + * will attempt access it while it is being deleted. + * + * Inputs: + * msgq - Named essage queue to be freed + * + * Return Value: + * None + * + ************************************************************************/ + +void mq_msgqfree(FAR msgq_t *msgq) +{ + FAR mqmsg_t *curr; + FAR mqmsg_t *next; + + /* Deallocate any stranded messages in the message queue. */ + + curr = (FAR mqmsg_t*)msgq->msglist.head; + while (curr) + { + /* Deallocate the message structure. */ + + next = curr->next; + mq_msgfree(curr); + curr = next; + } + + /* Then deallocate the message queue itself */ + + sched_free(msgq); +} diff --git a/nuttx/sched/mq_notify.c b/nuttx/sched/mq_notify.c new file mode 100644 index 0000000000..589bee312b --- /dev/null +++ b/nuttx/sched/mq_notify.c @@ -0,0 +1,211 @@ +/************************************************************************ + * sched/mq_notify.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "os_internal.h" +#include "mq_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_notify + * + * Description: + * If "notification" is not NULL, this function connects the task with + * the message queue such that the specified signal will be sent to the + * task whenever the message changes from empty to non-empty. Only one + * notification can be attached to a message queue. + * + * If "notification" is NULL, the attached notification is detached (if + * it was held by the calling task) and the queue is available to attach + * another notification. + * + * When the notification is sent to the registered process, its + * registration will be removed. The message queue will then be + * available for registration. + * + * Parameters: + * mqdes - Message queue descriptor + * notification - Real-time signal structure containing: + * sigev_notify - Should be SIGEV_SIGNAL (but actually ignored) + * sigev_signo - The signo to use for the notification + * sigev_value - Value associated with the signal + * + * Return Value: + * On success mq_notify() returns 0; on error, -1 is returned, with + * errno set to indicate the error. + * + * EBADF The descriptor specified in mqdes is invalid. + * EBUSY Another process has already registered to receive notification + * for this message queue. + * EINVAL sevp->sigev_notify is not one of the permitted values; or + * sevp->sigev_notify is SIGEV_SIGNAL and sevp->sigev_signo is not a + * valid signal number. + * ENOMEM + * Insufficient memory. + * + * Assumptions: + * + * POSIX Compatibility: + * int mq_notify(mqd_t mqdes, const struct sigevent *notification); + * + * The notification will be sent to the registered task even if another + * task is waiting for the message queue to become non-empty. This is + * inconsistent with the POSIX specification which says, "If a process + * has registered for notification of message a arrival at a message + * queue and some process is blocked in mq_receive() waiting to receive + * a message when a message arrives at the queue, the arriving message + * message shall satisfy mq_receive()... The resulting behavior is as if + * the message queue remains empty, and no notification shall be sent." + * + ************************************************************************/ + +int mq_notify(mqd_t mqdes, const struct sigevent *notification) +{ + _TCB *rtcb; + msgq_t *msgq; + int errval; + + /* Was a valid message queue descriptor provided? */ + + if (!mqdes) + { + /* No.. return EBADF */ + + errval = EBADF; + goto errout; + } + + /* Get a pointer to the message queue */ + + sched_lock(); + msgq = mqdes->msgq; + + /* Get the current process ID */ + + rtcb = (_TCB*)g_readytorun.head; + + /* Is there already a notification attached */ + + if (!msgq->ntmqdes) + { + /* No... Have we been asked to establish one? */ + + if (notification) + { + /* Yes... Was a valid signal number supplied? */ + + if (!GOOD_SIGNO(notification->sigev_signo)) + { + /* No... Return EINVAL */ + + errval = EINVAL; + goto errout; + } + + /* Yes... Assign it to the current task. */ + + msgq->ntvalue.sival_ptr = notification->sigev_value.sival_ptr; + msgq->ntsigno = notification->sigev_signo; + msgq->ntpid = rtcb->pid; + msgq->ntmqdes = mqdes; + } + } + + /* Yes... a notification is attached. Does this task own it? + * Is it trying to remove it? + */ + + else if ((msgq->ntpid != rtcb->pid) || (notification)) + { + /* This thread does not own the notification OR it is + * not trying to remove it. Return EBUSY. + */ + + errval = EBUSY; + goto errout; + } + else + { + /* Yes, the notification belongs to this thread. Allow the + * thread to detach the notification. + */ + + msgq->ntpid = INVALID_PROCESS_ID; + msgq->ntsigno = 0; + msgq->ntvalue.sival_ptr = NULL; + msgq->ntmqdes = NULL; + } + + sched_unlock(); + return OK; + +errout: + set_errno(errval); + sched_unlock(); + return ERROR; +} diff --git a/nuttx/sched/mq_open.c b/nuttx/sched/mq_open.c new file mode 100644 index 0000000000..5e1b9b1377 --- /dev/null +++ b/nuttx/sched/mq_open.c @@ -0,0 +1,236 @@ +/**************************************************************************** + * sched/mq_open.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "mq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_open + * + * Description: + * This function establish a connection between a named message queue and + * the calling task. After a successful call of mq_open(), the task can + * reference the message queue using the address returned by the call. The + * message queue remains usable until it is closed by a successful call to + * mq_close(). + * + * Parameters: + * mq_name - Name of the queue to open + * oflags - open flags + * Optional parameters. When the O_CREAT flag is specified, two optional + * parameters are expected: + * + * 1. mode_t mode (ignored), and + * 2. struct mq_attr *attr. The mq_maxmsg attribute + * is used at the time that the message queue is + * created to determine the maximum number of + * messages that may be placed in the message queue. + * + * Return Value: + * A message queue descriptor or -1 (ERROR) + * + * Assumptions: + * + ****************************************************************************/ + +mqd_t mq_open(const char *mq_name, int oflags, ...) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR msgq_t *msgq; + mqd_t mqdes = NULL; + va_list arg; /* Points to each un-named argument */ + mode_t mode; /* MQ creation mode parameter (ignored) */ + struct mq_attr *attr; /* MQ creation attributes */ + int namelen; /* Length of MQ name */ + + /* Make sure that a non-NULL name is supplied */ + + if (mq_name) + { + sched_lock(); + namelen = strlen(mq_name); + if (namelen > 0) + { + /* See if the message queue already exists */ + + msgq = mq_findnamed(mq_name); + if (msgq) + { + /* It does. Check if the caller wanted to create a new + * message queue with this name (i.e., O_CREAT|O_EXCL) + */ + + if ((oflags & O_CREAT) == 0 || (oflags & O_EXCL) == 0) + { + /* Create a message queue descriptor for the TCB */ + + mqdes = mq_descreate(rtcb, msgq, oflags); + if (mqdes) + { + /* Allow a new connection to the message queue */ + + msgq->nconnect++; + } + } + } + + /* It doesn't exist. Should we create one? */ + + else if ((oflags & O_CREAT) != 0) + { + /* Allocate memory for the new message queue. The size to + * allocate is the size of the msgq_t header plus the size + * of the message queue name+1. + */ + + msgq = (FAR msgq_t*)kzalloc(SIZEOF_MQ_HEADER + namelen + 1); + if (msgq) + { + /* Create a message queue descriptor for the TCB */ + + mqdes = mq_descreate(rtcb, msgq, oflags); + if (mqdes) + { + /* Set up to get the optional arguments needed to create + * a message queue. + */ + + va_start(arg, oflags); + mode = va_arg(arg, mode_t); + attr = va_arg(arg, struct mq_attr*); + + /* Initialize the new named message queue */ + + sq_init(&msgq->msglist); + if (attr) + { + msgq->maxmsgs = (int16_t)attr->mq_maxmsg; + if (attr->mq_msgsize <= MQ_MAX_BYTES) + { + msgq->maxmsgsize = (int16_t)attr->mq_msgsize; + } + else + { + msgq->maxmsgsize = MQ_MAX_BYTES; + } + } + else + { + msgq->maxmsgs = MQ_MAX_MSGS; + msgq->maxmsgsize = MQ_MAX_BYTES; + } + + msgq->nconnect = 1; +#ifndef CONFIG_DISABLE_SIGNALS + msgq->ntpid = INVALID_PROCESS_ID; +#endif + strcpy(msgq->name, mq_name); + + /* Add the new message queue to the list of + * message queues + */ + + sq_addlast((FAR sq_entry_t*)msgq, &g_msgqueues); + + /* Clean-up variable argument stuff */ + + va_end(arg); + } + else + { + /* Deallocate the msgq structure. Since it is + * uninitialized, mq_deallocate() is not used. + */ + + sched_free(msgq); + } + } + } + } + + sched_unlock(); + } + + if (mqdes == NULL) + { + return (mqd_t)ERROR; + } + else + { + return mqdes; + } +} diff --git a/nuttx/sched/mq_rcvinternal.c b/nuttx/sched/mq_rcvinternal.c new file mode 100644 index 0000000000..e80685e878 --- /dev/null +++ b/nuttx/sched/mq_rcvinternal.c @@ -0,0 +1,312 @@ +/**************************************************************************** + * sched/mq_rcvinternal.c + * + * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "mq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_verifyreceive + * + * Description: + * This is internal, common logic shared by both mq_receive and + * mq_timedreceive. This function verifies the input parameters that are + * common to both functions. + * + * Parameters: + * mqdes - Message Queue Descriptor + * msg - Buffer to receive the message + * msglen - Size of the buffer in bytes + * + * Return Value: + * One success, 0 (OK) is returned. On failure, -1 (ERROR) is returned and + * the errno is set appropriately: + * + * EPERM Message queue opened not opened for reading. + * EMSGSIZE 'msglen' was less than the maxmsgsize attribute of the message + * queue. + * EINVAL Invalid 'msg' or 'mqdes' + * + * Assumptions: + * + ****************************************************************************/ + +int mq_verifyreceive(mqd_t mqdes, void *msg, size_t msglen) +{ + /* Verify the input parameters */ + + if (!msg || !mqdes) + { + set_errno(EINVAL); + return ERROR; + } + + if ((mqdes->oflags & O_RDOK) == 0) + { + set_errno(EPERM); + return ERROR; + } + + if (msglen < (size_t)mqdes->msgq->maxmsgsize) + { + set_errno(EMSGSIZE); + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: mq_waitreceive + * + * Description: + * This is internal, common logic shared by both mq_receive and + * mq_timedreceive. This function waits for a message to be received on + * the specified message queue, removes the message from the queue, and + * returns it. + * + * Parameters: + * mqdes - Message queue descriptor + * + * Return Value: + * On success, a reference to the received message. If the wait was + * interrupted by a signal or a timeout, then the errno will be set + * appropriately and NULL will be returned. + * + * Assumptions: + * - The caller has provided all validity checking of the input parameters + * using mq_verifyreceive. + * - Interrupts should be disabled throughout this call. This is necessary + * because messages can be sent from interrupt level processing. + * - For mq_timedreceive, setting of the timer and this wait must be atomic. + * + ****************************************************************************/ + +FAR mqmsg_t *mq_waitreceive(mqd_t mqdes) +{ + FAR _TCB *rtcb; + FAR msgq_t *msgq; + FAR mqmsg_t *rcvmsg; + + /* Get a pointer to the message queue */ + + msgq = mqdes->msgq; + + /* Get the message from the head of the queue */ + + while ((rcvmsg = (FAR mqmsg_t*)sq_remfirst(&msgq->msglist)) == NULL) + { + /* The queue is empty! Should we block until there the above condition + * has been satisfied? + */ + + if ((mqdes->oflags & O_NONBLOCK) == 0) + { + /* Yes.. Block and try again */ + + rtcb = (FAR _TCB*)g_readytorun.head; + rtcb->msgwaitq = msgq; + msgq->nwaitnotempty++; + + set_errno(OK); + up_block_task(rtcb, TSTATE_WAIT_MQNOTEMPTY); + + /* When we resume at this point, either (1) the message queue + * is no longer empty, or (2) the wait has been interrupted by + * a signal. We can detect the latter case be examining the + * errno value (should be either EINTR or ETIMEDOUT). + */ + + if (get_errno() != OK) + { + break; + } + } + else + { + /* The queue was empty, and the O_NONBLOCK flag was set for the + * message queue description referred to by 'mqdes'. + */ + + set_errno(EAGAIN); + break; + } + } + + /* If we got message, then decrement the number of messages in + * the queue while we are still in the critical section + */ + + if (rcvmsg) + { + msgq->nmsgs--; + } + + return rcvmsg; +} + +/**************************************************************************** + * Name: mq_doreceive + * + * Description: + * This is internal, common logic shared by both mq_receive and + * mq_timedreceive. This function accepts the message obtained by + * mq_waitmsg, provides the message content to the user, notifies any + * threads that were waiting for the message queue to become non-full, + * and disposes of the message structure + * + * Parameters: + * mqdes - Message queue descriptor + * mqmsg - The message obtained by mq_waitmsg() + * ubuffer - The address of the user provided buffer to receive the message + * prio - The user-provided location to return the message priority. + * + * Return Value: + * Returns the length of the received message. This function does not fail. + * + * Assumptions: + * - The caller has provided all validity checking of the input parameters + * using mq_verifyreceive. + * - The user buffer, ubuffer, is known to be large enough to accept the + * largest message that an be sent on this message queue + * - Pre-emption should be disabled throughout this call. + * + ****************************************************************************/ + +ssize_t mq_doreceive(mqd_t mqdes, mqmsg_t *mqmsg, void *ubuffer, int *prio) +{ + FAR _TCB *btcb; + irqstate_t saved_state; + FAR msgq_t *msgq; + ssize_t rcvmsglen; + + /* Get the length of the message (also the return value) */ + + rcvmsglen = mqmsg->msglen; + + /* Copy the message into the caller's buffer */ + + memcpy(ubuffer, (const void*)mqmsg->mail, rcvmsglen); + + /* Copy the message priority as well (if a buffer is provided) */ + + if (prio) + { + *prio = mqmsg->priority; + } + + /* We are done with the message. Deallocate it now. */ + + mq_msgfree(mqmsg); + + /* Check if any tasks are waiting for the MQ not full event. */ + + msgq = mqdes->msgq; + if (msgq->nwaitnotfull > 0) + { + /* Find the highest priority task that is waiting for + * this queue to be not-full in g_waitingformqnotfull list. + * This must be performed in a critical section because + * messages can be sent from interrupt handlers. + */ + + saved_state = irqsave(); + for (btcb = (FAR _TCB*)g_waitingformqnotfull.head; + btcb && btcb->msgwaitq != msgq; + btcb = btcb->flink); + + /* If one was found, unblock it. NOTE: There is a race + * condition here: the queue might be full again by the + * time the task is unblocked + */ + + if (!btcb) + { + PANIC(OSERR_MQNOTFULLCOUNT); + } + else + { + btcb->msgwaitq = NULL; + msgq->nwaitnotfull--; + up_unblock_task(btcb); + } + + irqrestore(saved_state); + } + + /* Return the length of the message transferred to the user buffer */ + + return rcvmsglen; +} diff --git a/nuttx/sched/mq_receive.c b/nuttx/sched/mq_receive.c new file mode 100644 index 0000000000..7604334464 --- /dev/null +++ b/nuttx/sched/mq_receive.c @@ -0,0 +1,166 @@ +/************************************************************************ + * sched/mq_receive.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "mq_internal.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_receive + * + * Description: + * This function receives the oldest of the highest priority messages + * from the message queue specified by "mqdes." If the size of the + * buffer in bytes (msglen) is less than the "mq_msgsize" attribute of + * the message queue, mq_receive will return an error. Otherwise, the + * selected message is removed from the queue and copied to "msg." + * + * If the message queue is empty and O_NONBLOCK was not set, + * mq_receive() will block until a message is added to the message + * queue. If more than one task is waiting to receive a message, only + * the task with the highest priority that has waited the longest will + * be unblocked. + * + * If the queue is empty and O_NONBLOCK is set, ERROR will be returned. + * + * Parameters: + * mqdes - Message Queue Descriptor + * msg - Buffer to receive the message + * msglen - Size of the buffer in bytes + * prio - If not NULL, the location to store message priority. + * + * Return Value: + * One success, the length of the selected message in bytes is returned. + * On failure, -1 (ERROR) is returned and the errno is set appropriately: + * + * EAGAIN The queue was empty, and the O_NONBLOCK flag was set + * for the message queue description referred to by 'mqdes'. + * EPERM Message queue opened not opened for reading. + * EMSGSIZE 'msglen' was less than the maxmsgsize attribute of the + * message queue. + * EINTR The call was interrupted by a signal handler. + * EINVAL Invalid 'msg' or 'mqdes' + * + * Assumptions: + * + ************************************************************************/ + +ssize_t mq_receive(mqd_t mqdes, void *msg, size_t msglen, int *prio) +{ + FAR mqmsg_t *mqmsg; + irqstate_t saved_state; + ssize_t ret = ERROR; + + DEBUGASSERT(up_interrupt_context() == false); + + /* Verify the input parameters and, in case of an error, set + * errno appropriately. + */ + + if (mq_verifyreceive(mqdes, msg, msglen) != OK) + { + return ERROR; + } + + /* Get the next mesage from the message queue. We will disable + * pre-emption until we have completed the message received. This + * is not too bad because if the receipt takes a long time, it will + * be because we are blocked waiting for a message and pre-emption + * will be re-enabled while we are blocked + */ + + sched_lock(); + + /* Furthermore, mq_waitreceive() expects to have interrupts disabled + * because messages can be sent from interrupt level. + */ + + saved_state = irqsave(); + + /* Get the message from the message queue */ + + mqmsg = mq_waitreceive(mqdes); + irqrestore(saved_state); + + /* Check if we got a message from the message queue. We might + * not have a message if: + * + * - The message queue is empty and O_NONBLOCK is set in the mqdes + * - The wait was interrupted by a signal + */ + + if (mqmsg) + { + ret = mq_doreceive(mqdes, mqmsg, msg, prio); + } + + sched_unlock(); + return ret; +} diff --git a/nuttx/sched/mq_send.c b/nuttx/sched/mq_send.c new file mode 100644 index 0000000000..40628e924b --- /dev/null +++ b/nuttx/sched/mq_send.c @@ -0,0 +1,184 @@ +/**************************************************************************** + * sched/mq_send.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "mq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_send + * + * Description: + * This function adds the specificied message (msg) to the message queue + * (mqdes). The "msglen" parameter specifies the length of the message + * in bytes pointed to by "msg." This length must not exceed the maximum + * message length from the mq_getattr(). + * + * If the message queue is not full, mq_send() place the message in the + * message queue at the position indicated by the "prio" argrument. + * Messages with higher priority will be inserted before lower priority + * messages. The value of "prio" must not exceed MQ_PRIO_MAX. + * + * If the specified message queue is full and O_NONBLOCK is not set in the + * message queue, then mq_send() will block until space becomes available + * to the queue the message. + * + * If the message queue is full and O_NONBLOCK is set, the message is not + * queued and ERROR is returned. + * + * Parameters: + * mqdes - Message queue descriptor + * msg - Message to send + * msglen - The length of the message in bytes + * prio - The priority of the message + * + * Return Value: + * On success, mq_send() returns 0 (OK); on error, -1 (ERROR) + * is returned, with errno set to indicate the error: + * + * EAGAIN The queue was empty, and the O_NONBLOCK flag was set for the + * message queue description referred to by mqdes. + * EINVAL Either msg or mqdes is NULL or the value of prio is invalid. + * EPERM Message queue opened not opened for writing. + * EMSGSIZE 'msglen' was greater than the maxmsgsize attribute of the + * message queue. + * EINTR The call was interrupted by a signal handler. + * + * Assumptions/restrictions: + * + ****************************************************************************/ + +int mq_send(mqd_t mqdes, const void *msg, size_t msglen, int prio) +{ + FAR msgq_t *msgq; + FAR mqmsg_t *mqmsg = NULL; + irqstate_t saved_state; + int ret = ERROR; + + /* Verify the input parameters -- setting errno appropriately + * on any failures to verify. + */ + + if (mq_verifysend(mqdes, msg, msglen, prio) != OK) + { + return ERROR; + } + + /* Get a pointer to the message queue */ + + sched_lock(); + msgq = mqdes->msgq; + + /* Allocate a message structure: + * - Immediately if we are called from an interrupt handler. + * - Immediately if the message queue is not full, or + * - After successfully waiting for the message queue to become + * non-FULL. This would fail with EAGAIN, EINTR, or ETIMEOUT. + */ + + saved_state = irqsave(); + if (up_interrupt_context() || /* In an interrupt handler */ + msgq->nmsgs < msgq->maxmsgs || /* OR Message queue not full */ + mq_waitsend(mqdes) == OK) /* OR Successfully waited for mq not full */ + { + /* Allocate the message */ + + irqrestore(saved_state); + mqmsg = mq_msgalloc(); + } + else + { + /* We cannot send the message (and didn't even try to allocate it) + * because: + * - We are not in an interrupt handler AND + * - The message queue is full AND + * - When we tried waiting, the wait was unsuccessful. + */ + + irqrestore(saved_state); + } + + /* Check if we were able to get a message structure -- this can fail + * either because we cannot send the message (and didn't bother trying + * to allocate it) or because the allocation failed. + */ + + if (mqmsg) + { + /* Yes, perform the message send. */ + + ret = mq_dosend(mqdes, mqmsg, msg, msglen, prio); + } + + sched_unlock(); + return ret; +} + diff --git a/nuttx/sched/mq_sndinternal.c b/nuttx/sched/mq_sndinternal.c new file mode 100644 index 0000000000..51f8988756 --- /dev/null +++ b/nuttx/sched/mq_sndinternal.c @@ -0,0 +1,455 @@ +/**************************************************************************** + * sched/mq_send.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" +#ifndef CONFIG_DISABLE_SIGNALS +# include "sig_internal.h" +#endif +#include "mq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_verifysend + * + * Description: + * This is internal, common logic shared by both mq_send and mq_timesend. + * This function verifies the input parameters that are common to both + * functions. + * + * Parameters: + * mqdes - Message queue descriptor + * msg - Message to send + * msglen - The length of the message in bytes + * prio - The priority of the message + * + * Return Value: + * One success, 0 (OK) is returned. On failure, -1 (ERROR) is returned and + * the errno is set appropriately: + * + * EINVAL Either msg or mqdes is NULL or the value of prio is invalid. + * EPERM Message queue opened not opened for writing. + * EMSGSIZE 'msglen' was greater than the maxmsgsize attribute of the + * message queue. + * + * Assumptions: + * + ****************************************************************************/ + +int mq_verifysend(mqd_t mqdes, const void *msg, size_t msglen, int prio) +{ + /* Verify the input parameters */ + + if (!msg || !mqdes || prio < 0 || prio > MQ_PRIO_MAX) + { + set_errno(EINVAL); + return ERROR; + } + + if ((mqdes->oflags & O_WROK) == 0) + { + set_errno(EPERM); + return ERROR; + } + + if (msglen < 0 || msglen > (size_t)mqdes->msgq->maxmsgsize) + { + set_errno(EMSGSIZE); + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: mq_msgalloc + * + * Description: + * The mq_msgalloc function will get a free message for use by the + * operating system. The message will be allocated from the g_msgfree + * list. + * + * If the list is empty AND the message is NOT being allocated from the + * interrupt level, then the message will be allocated. If a message + * cannot be obtained, the operating system is dead and therefore cannot + * continue. + * + * If the list is empty AND the message IS being allocated from the + * interrupt level. This function will attempt to get a message from + * the g_msgfreeirq list. If this is unsuccessful, the calling interrupt + * handler will be notified. + * + * Inputs: + * None + * + * Return Value: + * A reference to the allocated msg structure. On a failure to allocate, + * this function PANICs. + * + ****************************************************************************/ + +FAR mqmsg_t *mq_msgalloc(void) +{ + FAR mqmsg_t *mqmsg; + irqstate_t saved_state; + + /* If we were called from an interrupt handler, then try to get the message + * from generally available list of messages. If this fails, then try the + * list of messages reserved for interrupt handlers + */ + + if (up_interrupt_context()) + { + /* Try the general free list */ + + mqmsg = (FAR mqmsg_t*)sq_remfirst(&g_msgfree); + if (!mqmsg) + { + /* Try the free list reserved for interrupt handlers */ + + mqmsg = (FAR mqmsg_t*)sq_remfirst(&g_msgfreeirq); + } + } + + /* We were not called from an interrupt handler. */ + + else + { + /* Try to get the message from the generally available free list. + * Disable interrupts -- we might be called from an interrupt handler. + */ + + saved_state = irqsave(); + mqmsg = (FAR mqmsg_t*)sq_remfirst(&g_msgfree); + irqrestore(saved_state); + + /* If we cannot a message from the free list, then we will have to allocate one. */ + + if (!mqmsg) + { + mqmsg = (FAR mqmsg_t *)kmalloc((sizeof (mqmsg_t))); + + /* Check if we got an allocated message */ + + if (mqmsg) + { + mqmsg->type = MQ_ALLOC_DYN; + } + + /* No? We are dead */ + + else + { + sdbg("Out of messages\n"); + PANIC((uint32_t)OSERR_OUTOFMESSAGES); + } + } + } + + return mqmsg; +} + +/**************************************************************************** + * Name: mq_waitsend + * + * Description: + * This is internal, common logic shared by both mq_send and mq_timesend. + * This function waits until the message queue is not full. + * + * Parameters: + * mqdes - Message queue descriptor + * + * Return Value: + * On success, mq_send() returns 0 (OK); on error, -1 (ERROR) is + * returned, with errno set to indicate the error: + * + * EAGAIN The queue was empty, and the O_NONBLOCK flag was set for the + * message queue description referred to by mqdes. + * EINTR The call was interrupted by a signal handler. + * ETIMEOUT A timeout expired before the message queue became non-full + * (mq_timedsend only). + * + * Assumptions/restrictions: + * - The caller has verified the input parameters using mq_verifysend(). + * - Interrupts are disabled. + * + ****************************************************************************/ + +int mq_waitsend(mqd_t mqdes) +{ + FAR _TCB *rtcb; + FAR msgq_t *msgq; + + /* Get a pointer to the message queue */ + + msgq = mqdes->msgq; + + /* Verify that the queue is indeed full as the caller thinks */ + + if (msgq->nmsgs >= msgq->maxmsgs) + { + /* Should we block until there is sufficient space in the + * message queue? + */ + + if ((mqdes->oflags & O_NONBLOCK) != 0) + { + /* No... We will return an error to the caller. */ + + set_errno(EAGAIN); + return ERROR; + } + + /* Yes... We will not return control until the message queue is + * available or we receive a signal or at timout occurs. + */ + + else + { + /* Loop until there are fewer than max allowable messages in the + * receiving message queue + */ + + while (msgq->nmsgs >= msgq->maxmsgs) + { + /* Block until the message queue is no longer full. + * When we are unblocked, we will try again + */ + + rtcb = (FAR _TCB*)g_readytorun.head; + rtcb->msgwaitq = msgq; + msgq->nwaitnotfull++; + + set_errno(OK); + up_block_task(rtcb, TSTATE_WAIT_MQNOTFULL); + + /* When we resume at this point, either (1) the message queue + * is no longer empty, or (2) the wait has been interrupted by + * a signal. We can detect the latter case be examining the + * errno value (should be EINTR or ETIMEOUT). + */ + + if (get_errno() != OK) + { + return ERROR; + } + } + } + } + return OK; +} + +/**************************************************************************** + * Name: mq_dosend + * + * Description: + * This is internal, common logic shared by both mq_send and mq_timesend. + * This function adds the specificied message (msg) to the message queue + * (mqdes). Then it notifies any tasks that were waiting for message + * queue notifications setup by mq_notify. And, finally, it awakens any + * tasks that were waiting for the message not empty event. + * + * Parameters: + * mqdes - Message queue descriptor + * msg - Message to send + * msglen - The length of the message in bytes + * prio - The priority of the message + * + * Return Value: + * This function always returns OK. + * + * Assumptions/restrictions: + * + ****************************************************************************/ + +int mq_dosend(mqd_t mqdes, FAR mqmsg_t *mqmsg, const void *msg, size_t msglen, int prio) +{ + FAR _TCB *btcb; + FAR msgq_t *msgq; + FAR mqmsg_t *next; + FAR mqmsg_t *prev; + irqstate_t saved_state; + + /* Get a pointer to the message queue */ + + sched_lock(); + msgq = mqdes->msgq; + + /* Construct the message header info */ + + mqmsg->priority = prio; + mqmsg->msglen = msglen; + + /* Copy the message data into the message */ + + memcpy((void*)mqmsg->mail, (const void*)msg, msglen); + + /* Insert the new message in the message queue */ + + saved_state = irqsave(); + + /* Search the message list to find the location to insert the new + * message. Each is list is maintained in ascending priority order. + */ + + for (prev = NULL, next = (FAR mqmsg_t*)msgq->msglist.head; + next && prio <= next->priority; + prev = next, next = next->next); + + /* Add the message at the right place */ + + if (prev) + { + sq_addafter((FAR sq_entry_t*)prev, (FAR sq_entry_t*)mqmsg, + &msgq->msglist); + } + else + { + sq_addfirst((FAR sq_entry_t*)mqmsg, &msgq->msglist); + } + + /* Increment the count of messages in the queue */ + + msgq->nmsgs++; + irqrestore(saved_state); + + /* Check if we need to notify any tasks that are attached to the + * message queue + */ + +#ifndef CONFIG_DISABLE_SIGNALS + if (msgq->ntmqdes) + { + /* Remove the message notification data from the message queue. */ + +#ifdef CONFIG_CAN_PASS_STRUCTS + union sigval value = msgq->ntvalue; +#else + void *sival_ptr = msgq->ntvalue.sival_ptr; +#endif + int signo = msgq->ntsigno; + int pid = msgq->ntpid; + + /* Detach the notification */ + + msgq->ntpid = INVALID_PROCESS_ID; + msgq->ntsigno = 0; + msgq->ntvalue.sival_int = 0; + msgq->ntmqdes = NULL; + + /* Queue the signal -- What if this returns an error? */ + +#ifdef CONFIG_CAN_PASS_STRUCTS + sig_mqnotempty(pid, signo, value); +#else + sig_mqnotempty(pid, signo, sival_ptr); +#endif + } +#endif + + /* Check if any tasks are waiting for the MQ not empty event. */ + + saved_state = irqsave(); + if (msgq->nwaitnotempty > 0) + { + /* Find the highest priority task that is waiting for + * this queue to be non-empty in g_waitingformqnotempty + * list. sched_lock() should give us sufficent protection since + * interrupts should never cause a change in this list + */ + + for (btcb = (FAR _TCB*)g_waitingformqnotempty.head; + btcb && btcb->msgwaitq != msgq; + btcb = btcb->flink); + + /* If one was found, unblock it */ + + if (!btcb) + { + PANIC(OSERR_MQNONEMPTYCOUNT); + } + else + { + btcb->msgwaitq = NULL; + msgq->nwaitnotempty--; + up_unblock_task(btcb); + } + } + + irqrestore(saved_state); + sched_unlock(); + return OK; +} + diff --git a/nuttx/sched/mq_timedreceive.c b/nuttx/sched/mq_timedreceive.c new file mode 100644 index 0000000000..0df904830c --- /dev/null +++ b/nuttx/sched/mq_timedreceive.c @@ -0,0 +1,303 @@ +/**************************************************************************** + * sched/mq_timedreceive.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "clock_internal.h" +#include "mq_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_rcvtimeout + * + * Description: + * This function is called if the timeout elapses before the message queue + * becomes non-empty. + * + * Parameters: + * argc - the number of arguments (should be 1) + * pid - the task ID of the task to wakeup + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void mq_rcvtimeout(int argc, uint32_t pid) +{ + FAR _TCB *wtcb; + irqstate_t saved_state; + + /* Disable interrupts. This is necessary because an interrupt handler may + * attempt to send a message while we are doing this. + */ + + saved_state = irqsave(); + + /* Get the TCB associated with this pid. It is possible that task may no + * longer be active when this watchdog goes off. + */ + + wtcb = sched_gettcb((pid_t)pid); + + /* It is also possible that an interrupt/context switch beat us to the + * punch and already changed the task's state. + */ + + if (wtcb && wtcb->task_state == TSTATE_WAIT_MQNOTEMPTY) + { + /* Restart with task with a timeout error */ + + mq_waitirq(wtcb, ETIMEDOUT); + } + + /* Interrupts may now be re-enabled. */ + + irqrestore(saved_state); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_timedreceive + * + * Description: + * This function receives the oldest of the highest priority messages from + * the message queue specified by "mqdes." If the size of the buffer in + * bytes (msglen) is less than the "mq_msgsize" attribute of the message + * queue, mq_timedreceive will return an error. Otherwise, the selected + * message is removed from the queue and copied to "msg." + * + * If the message queue is empty and O_NONBLOCK was not set, + * mq_timedreceive() will block until a message is added to the message + * queue (or until a timeout occurs). If more than one task is waiting + * to receive a message, only the task with the highest priority that has + * waited the longest will be unblocked. + * + * mq_timedreceive() behaves just like mq_receive(), except that if the + * queue is empty and the O_NONBLOCK flag is not enabled for the message + * queue description, then abstime points to a structure which specifies a + * ceiling on the time for which the call will block. This ceiling is an + * absolute timeout in seconds and nanoseconds since the Epoch (midnight + * on the morning of 1 January 1970). + * + * If no message is available, and the timeout has already expired by the + * time of the call, mq_timedreceive() returns immediately. + * + * Parameters: + * mqdes - Message Queue Descriptor + * msg - Buffer to receive the message + * msglen - Size of the buffer in bytes + * prio - If not NULL, the location to store message priority. + * abstime - the absolute time to wait until a timeout is declared. + * + * Return Value: + * One success, the length of the selected message in bytes is returned. + * On failure, -1 (ERROR) is returned and the errno is set appropriately: + * + * EAGAIN The queue was empty, and the O_NONBLOCK flag was set + * for the message queue description referred to by 'mqdes'. + * EPERM Message queue opened not opened for reading. + * EMSGSIZE 'msglen' was less than the maxmsgsize attribute of the + * message queue. + * EINTR The call was interrupted by a signal handler. + * EINVAL Invalid 'msg' or 'mqdes' or 'abstime' + * ETIMEDOUT The call timed out before a message could be transferred. + * + * Assumptions: + * + ****************************************************************************/ + +ssize_t mq_timedreceive(mqd_t mqdes, void *msg, size_t msglen, + int *prio, const struct timespec *abstime) +{ + WDOG_ID wdog; + FAR mqmsg_t *mqmsg; + irqstate_t saved_state; + int ret = ERROR; + + DEBUGASSERT(up_interrupt_context() == false); + + /* Verify the input parameters and, in case of an error, set + * errno appropriately. + */ + + if (mq_verifyreceive(mqdes, msg, msglen) != OK) + { + return ERROR; + } + + if (!abstime || abstime->tv_sec < 0 || abstime->tv_nsec > 1000000000) + { + set_errno(EINVAL); + return ERROR; + } + + /* Create a watchdog. We will not actually need this watchdog + * unless the queue is not empty, but we will reserve it up front + * before we enter the following critical section. + */ + + wdog = wd_create(); + if (!wdog) + { + set_errno(EINVAL); + return ERROR; + } + + /* Get the next mesage from the message queue. We will disable + * pre-emption until we have completed the message received. This + * is not too bad because if the receipt takes a long time, it will + * be because we are blocked waiting for a message and pre-emption + * will be re-enabled while we are blocked + */ + + sched_lock(); + + /* Furthermore, mq_waitreceive() expects to have interrupts disabled + * because messages can be sent from interrupt level. + */ + + saved_state = irqsave(); + + /* Check if the message queue is empty. If it is NOT empty, then we + * will not need to start timer. + */ + + if (mqdes->msgq->msglist.head == NULL) + { + int ticks; + + /* Convert the timespec to clock ticks. We must have interrupts + * disabled here so that this time stays valid until the wait begins. + */ + + int result = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); + + /* If the time has already expired and the message queue is empty, + * return immediately. + */ + + if (result == OK && ticks <= 0) + { + result = ETIMEDOUT; + } + + /* Handle any time-related errors */ + + if (result != OK) + { + set_errno(result); + irqrestore(saved_state); + sched_unlock(); + wd_delete(wdog); + return ERROR; + } + + /* Start the watchdog */ + + wd_start(wdog, ticks, (wdentry_t)mq_rcvtimeout, 1, getpid()); + } + + /* Get the message from the message queue */ + + mqmsg = mq_waitreceive(mqdes); + + /* Stop the watchdog timer (this is not harmful in the case where + * it was never started) + */ + + wd_cancel(wdog); + + /* We can now restore interrupts */ + + irqrestore(saved_state); + + /* Check if we got a message from the message queue. We might + * not have a message if: + * + * - The message queue is empty and O_NONBLOCK is set in the mqdes + * - The wait was interrupted by a signal + * - The watchdog timeout expired + */ + + if (mqmsg) + { + ret = mq_doreceive(mqdes, mqmsg, msg, prio); + } + + sched_unlock(); + wd_delete(wdog); + return ret; +} diff --git a/nuttx/sched/mq_timedsend.c b/nuttx/sched/mq_timedsend.c new file mode 100644 index 0000000000..745cc62725 --- /dev/null +++ b/nuttx/sched/mq_timedsend.c @@ -0,0 +1,319 @@ +/**************************************************************************** + * sched/mq_timedsend.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clock_internal.h" +#include "os_internal.h" +#include "mq_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_sndtimeout + * + * Description: + * This function is called if the timeout elapses before the message queue + * becomes non-full. + * + * Parameters: + * argc - the number of arguments (should be 1) + * pid - the task ID of the task to wakeup + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void mq_sndtimeout(int argc, uint32_t pid) +{ + FAR _TCB *wtcb; + irqstate_t saved_state; + + /* Disable interrupts. This is necessary because an interrupt handler may + * attempt to send a message while we are doing this. + */ + + saved_state = irqsave(); + + /* Get the TCB associated with this pid. It is possible that task may no + * longer be active when this watchdog goes off. + */ + + wtcb = sched_gettcb((pid_t)pid); + + /* It is also possible that an interrupt/context switch beat us to the + * punch and already changed the task's state. + */ + + if (wtcb && wtcb->task_state == TSTATE_WAIT_MQNOTFULL) + { + /* Restart with task with a timeout error */ + + mq_waitirq(wtcb, ETIMEDOUT); + } + + /* Interrupts may now be re-enabled. */ + + irqrestore(saved_state); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_send + * + * Description: + * This function adds the specificied message (msg) to the message queue + * (mqdes). The "msglen" parameter specifies the length of the message + * in bytes pointed to by "msg." This length must not exceed the maximum + * message length from the mq_getattr(). + * + * If the message queue is not full, mq_timedsend() place the message in the + * message queue at the position indicated by the "prio" argrument. + * Messages with higher priority will be inserted before lower priority + * messages. The value of "prio" must not exceed MQ_PRIO_MAX. + * + * If the specified message queue is full and O_NONBLOCK is not set in the + * message queue, then mq_timedsend() will block until space becomes available + * to the queue the message or a timeout occurs. + * + * mq_timedsend() behaves just like mq_send(), except that if the queue + * is full and the O_NONBLOCK flag is not enabled for the message queue + * description, then abstime points to a structure which specifies a + * ceiling on the time for which the call will block. This ceiling is an + * absolute timeout in seconds and nanoseconds since the Epoch (midnight + * on the morning of 1 January 1970). + * + * If the message queue is full, and the timeout has already expired by + * the time of the call, mq_timedsend() returns immediately. + * + * Parameters: + * mqdes - Message queue descriptor + * msg - Message to send + * msglen - The length of the message in bytes + * prio - The priority of the message + * abstime - the absolute time to wait until a timeout is decleared + * + * Return Value: + * On success, mq_send() returns 0 (OK); on error, -1 (ERROR) + * is returned, with errno set to indicate the error: + * + * EAGAIN The queue was empty, and the O_NONBLOCK flag was set for the + * message queue description referred to by mqdes. + * EINVAL Either msg or mqdes is NULL or the value of prio is invalid. + * EPERM Message queue opened not opened for writing. + * EMSGSIZE 'msglen' was greater than the maxmsgsize attribute of the + * message queue. + * EINTR The call was interrupted by a signal handler. + * + * Assumptions/restrictions: + * + ****************************************************************************/ + +int mq_timedsend(mqd_t mqdes, const char *msg, size_t msglen, int prio, + const struct timespec *abstime) +{ + WDOG_ID wdog; + FAR msgq_t *msgq; + FAR mqmsg_t *mqmsg = NULL; + irqstate_t saved_state; + int ret = ERROR; + + DEBUGASSERT(up_interrupt_context() == false); + + /* Verify the input parameters -- setting errno appropriately + * on any failures to verify. + */ + + if (mq_verifysend(mqdes, msg, msglen, prio) != OK) + { + return ERROR; + } + + if (!abstime || abstime->tv_sec < 0 || abstime->tv_nsec > 1000000000) + { + set_errno(EINVAL); + return ERROR; + } + + /* Get a pointer to the message queue */ + + msgq = mqdes->msgq; + + /* Create a watchdog. We will not actually need this watchdog + * unless the queue is full, but we will reserve it up front + * before we enter the following critical section. + */ + + wdog = wd_create(); + if (!wdog) + { + set_errno(EINVAL); + return ERROR; + } + + /* Allocate a message structure: + * - If we are called from an interrupt handler, or + * - If the message queue is not full, or + */ + + sched_lock(); + saved_state = irqsave(); + if (up_interrupt_context() || /* In an interrupt handler */ + msgq->nmsgs < msgq->maxmsgs) /* OR Message queue not full */ + { + /* Allocate the message */ + + irqrestore(saved_state); + mqmsg = mq_msgalloc(); + } + else + { + int ticks; + + /* We are not in an interupt handler and the message queue is full. + * set up a timed wait for the message queue to become non-full. + * + * Convert the timespec to clock ticks. We must have interrupts + * disabled here so that this time stays valid until the wait begins. + */ + + int result = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); + + /* If the time has already expired and the message queue is empty, + * return immediately. + */ + + if (result == OK && ticks <= 0) + { + result = ETIMEDOUT; + } + + /* Handle any time-related errors */ + + if (result != OK) + { + set_errno(result); + ret = ERROR; + } + + /* Start the watchdog and begin the wait for MQ not full */ + + if (result == OK) + { + /* Start the watchdog */ + + wd_start(wdog, ticks, (wdentry_t)mq_sndtimeout, 1, getpid()); + + /* And wait for the message queue to be non-empty */ + + ret = mq_waitsend(mqdes); + + /* This may return with an error and errno set to either EINTR + * or ETIMEOUT. Cancel the watchdog timer in any event. + */ + + wd_cancel(wdog); + } + + /* That is the end of the atomic operations */ + + irqrestore(saved_state); + + /* If any of the above failed, set the errno. Otherwise, there should + * be space for another message in the message queue. NOW we can allocate + * the message structure. + */ + + if (ret == OK) + { + mqmsg = mq_msgalloc(); + } + } + + /* Check if we were able to get a message structure -- this can fail + * either because we cannot send the message (and didn't bother trying + * to allocate it) or because the allocation failed. + */ + + if (mqmsg) + { + /* Yes, peform the message send. */ + + ret = mq_dosend(mqdes, mqmsg, msg, msglen, prio); + } + + sched_unlock(); + wd_delete(wdog); + return ret; +} + diff --git a/nuttx/sched/mq_unlink.c b/nuttx/sched/mq_unlink.c new file mode 100644 index 0000000000..1fa25dfa85 --- /dev/null +++ b/nuttx/sched/mq_unlink.c @@ -0,0 +1,146 @@ +/************************************************************************ + * sched.mq_unlink.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#include "mq_internal.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_unlink + * + * Description: + * This function removes the message queue named by "mq_name." If one + * or more tasks have the message queue open when mq_unlink() is called, + * removal of the message queue is postponed until all references to the + * message queue have been closed. + * + * Parameters: + * mq_name - Name of the message queue + * + * Return Value: + * None + * + * Assumptions: + * + ************************************************************************/ + +int mq_unlink(const char *mq_name) +{ + FAR msgq_t *msgq; + irqstate_t saved_state; + int ret = ERROR; + + /* Verify the input values */ + + if (mq_name) + { + sched_lock(); + + /* Find the named message queue */ + + msgq = mq_findnamed(mq_name); + if (msgq) + { + /* If it is no longer connected, then we can just + * discard the message queue now. + */ + + if (!msgq->nconnect) + { + /* Remove the message queue from the list of all + * message queues + */ + + saved_state = irqsave(); + (void)sq_rem((FAR sq_entry_t*)msgq, &g_msgqueues); + irqrestore(saved_state); + + /* Then deallocate it (and any messages left in it) */ + + mq_msgqfree(msgq); + } + + /* If the message queue is still connected to a message descriptor, + * then mark it for deletion when the last message descriptor is + * closed + */ + + else + { + msgq->unlinked = true; + } + + ret = OK; + } + + sched_unlock(); + } + + return ret; +} + diff --git a/nuttx/sched/mq_waitirq.c b/nuttx/sched/mq_waitirq.c new file mode 100644 index 0000000000..94a15df3c2 --- /dev/null +++ b/nuttx/sched/mq_waitirq.c @@ -0,0 +1,172 @@ +/**************************************************************************** + * sched/mq_waitirq.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_waitirq + * + * Description: + * This function is called when a signal or a timeout is received by a + * task that is waiting on a message queue -- either for a queue to + * becoming not full (on mq_send) or not empty (on mq_receive). + * + * Parameters: + * wtcb - A pointer to the TCB of the task that is waiting on a message + * queue, but has received a signal instead. + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void mq_waitirq(FAR _TCB *wtcb, int errcode) +{ + FAR msgq_t *msgq; + irqstate_t saved_state; + + /* Disable interrupts. This is necessary because an interrupt handler may + * attempt to send a message while we are doing this. + */ + + saved_state = irqsave(); + + /* It is possible that an interrupt/context switch beat us to the punch and + * already changed the task's state. NOTE: The operations within the if + * are safe because interrupts are always disabled with the msgwaitq, + * nwaitnotempty, and nwaitnotfull fields are modified. + */ + + if (wtcb->task_state == TSTATE_WAIT_MQNOTEMPTY || + wtcb->task_state == TSTATE_WAIT_MQNOTFULL) + { + /* Get the message queue associated with the waiter from the TCB */ + + msgq = wtcb->msgwaitq; +#ifdef CONFIG_DEBUG + if (!msgq) + { + /* In these states there must always be an associated message queue */ + + PANIC((uint32_t)OSERR_MQNOWAITER); + } +#endif + wtcb->msgwaitq = NULL; + + /* Decrement the count of waiters and cancel the wait */ + + if (wtcb->task_state == TSTATE_WAIT_MQNOTEMPTY) + { +#ifdef CONFIG_DEBUG + if (msgq->nwaitnotempty <= 0) + { + /* This state, there should be a positive, non-zero waiter + * count. + */ + + PANIC((uint32_t)OSERR_MQNONEMPTYCOUNT); + + } +#endif + msgq->nwaitnotempty--; + } + else + { +#ifdef CONFIG_DEBUG + if (msgq->nwaitnotfull <= 0) + { + /* This state, there should be a positive, non-zero waiter + * count. + */ + + PANIC((uint32_t)OSERR_MQNOTFULLCOUNT); + + } +#endif + msgq->nwaitnotfull--; + } + + /* Mark the errno value for the thread. */ + + wtcb->pterrno = errcode; + + /* Restart the task. */ + + up_unblock_task(wtcb); + } + + /* Interrupts may now be enabled. */ + + irqrestore(saved_state); +} + diff --git a/nuttx/sched/on_exit.c b/nuttx/sched/on_exit.c new file mode 100644 index 0000000000..5b8be5cd10 --- /dev/null +++ b/nuttx/sched/on_exit.c @@ -0,0 +1,171 @@ +/**************************************************************************** + * sched/on_exit.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" + +#ifdef CONFIG_SCHED_ONEXIT + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: on_exit + * + * Description: + * Registers a function to be called at program exit. + * The on_exit() function registers the given function to be called + * at normal process termination, whether via exit or via return from + * the program's main(). The function is passed the status argument + * given to the last call to exit and the arg argument from on_exit(). + * + * NOTE 1: This function comes from SunOS 4, but is also present in + * libc4, libc5 and glibc. It no longer occurs in Solaris (SunOS 5). + * Avoid this function, and use the standard atexit() instead. + * + * NOTE 2: CONFIG_SCHED_ONEXIT must be defined to enable this function + * + * Limitiations in the current implementation: + * + * 1. Only a single on_exit function can be registered unless + * CONFIG_SCHED_ONEXIT_MAX defines a larger number. + * 2. on_exit functions are not inherited when a new task is + * created. + * + * Parameters: + * func - A pointer to the function to be called when the task exits. + * arg - An argument that will be provided to the on_exit() function when + * the task exits. + * + * Return Value: + * Zero on success. Non-zero on failure. + * + ****************************************************************************/ + +int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg) +{ +#if defined(CONFIG_SCHED_ONEXIT_MAX) && CONFIG_SCHED_ONEXIT_MAX > 1 + _TCB *tcb = (_TCB*)g_readytorun.head; + int index; + int ret = ERROR; + + /* The following must be atomic */ + + if (func) + { + sched_lock(); + + /* Search for the first available slot. on_exit() functions are registered + * from lower to higher arry indices; they must be called in the reverse + * order of registration when task exists, i.e., from higher to lower + * indices. + */ + + available = -1; + for (index = 0; index < CONFIG_SCHED_ONEXIT_MAX; index++) + { + if (!tcb->onexitfunc[index]) + { + tcb->onexitfunc[index] = func; + tcb->onexitarg[index] = arg; + ret = OK; + break; + } + } + + sched_unlock(); + } + + return ret; +#else + _TCB *tcb = (_TCB*)g_readytorun.head; + int ret = ERROR; + + /* The following must be atomic */ + + sched_lock(); + if (func && !tcb->onexitfunc) + { + tcb->onexitfunc = func; + tcb->onexitarg = arg; + ret = OK; + } + + sched_unlock(); + return ret; +#endif +} + +#endif /* CONFIG_SCHED_ONEXIT */ + + diff --git a/nuttx/sched/os_bringup.c b/nuttx/sched/os_bringup.c new file mode 100644 index 0000000000..646f491583 --- /dev/null +++ b/nuttx/sched/os_bringup.c @@ -0,0 +1,186 @@ +/**************************************************************************** + * sched/os_bringup.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * With extensions by: + * + * Author: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "os_internal.h" +#ifdef CONFIG_PAGING +# include "pg_internal.h" +#endif +#ifdef CONFIG_SCHED_WORKQUEUE +# include "work_internal.h" +#endif +#ifdef CONFIG_BUILTIN_APP_START +# include "apps/apps.h" +#endif +#ifdef CONFIG_NUTTX_KERNEL +# include "arch/board/user_map.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* If NuttX is built as a separately compiled module, then the the header + * file should contain the address of the user module entry point. If not + * then the default entry point is user_start. + */ + +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_USER_ENTRYPOINT) +# define USER_ENTRYPOINT (main_t)CONFIG_USER_ENTRYPOINT +#else +# define USER_ENTRYPOINT user_start +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: os_bringup + * + * Description: + * Start all initial system tasks. This does the "system bring-up" after + * the conclusion of basic OS initialization. These initial system tasks + * may include: + * + * - pg_worker: The page-fault worker thread (only if CONFIG_PAGING is + * defined. + * - work_thread: The work thread. This general thread can be used to + * perform most any kind of queued work. Its primary + * function is to serve as the "bottom half" of device + * drivers. + * + * And the main application entry point. This may be one of two different + * symbols: + * + * - USER_ENTRYPOINT: This is the default entry point used for all of the + * example code in apps/examples. + * - CONFIG_BUILTIN_APP_START: The system can also be configured to start + * custom applications at however CONFIG_BUILTIN_APP_START + * is defined in the NuttX start-up file. + * + ****************************************************************************/ + +int os_bringup(void) +{ +#ifdef CONFIG_BUILTIN_APP_START + static const char *argv[3] = {NULL, "init", NULL}; +#endif + int init_taskid; + + /* Start the page fill worker kernel thread that will resolve page faults. + * This should always be the first thread started because it may have to + * resolve page faults in other threads + */ + +#ifdef CONFIG_PAGING + svdbg("Starting paging thread\n"); + + g_pgworker = KERNEL_THREAD("pgfill", CONFIG_PAGING_DEFPRIO, + CONFIG_PAGING_STACKSIZE, + (main_t)pg_worker, (const char **)NULL); + ASSERT(g_pgworker != ERROR); +#endif + + /* Start the worker thread that will serve as the device driver "bottom- + * half" and will perform misc garbage clean-up. + */ + +#ifdef CONFIG_SCHED_WORKQUEUE + svdbg("Starting worker thread\n"); + + g_worker = KERNEL_THREAD("work", CONFIG_SCHED_WORKPRIORITY, + CONFIG_SCHED_WORKSTACKSIZE, + (main_t)work_thread, (const char **)NULL); + ASSERT(g_worker != ERROR); +#endif + + /* Once the operating system has been initialized, the system must be + * started by spawning the user init thread of execution. This is the + * first user-mode thead. + */ + + svdbg("Starting init thread\n"); + +#ifdef CONFIG_BUILTIN_APP_START + /* Start the built-in named application, passing an "init" argument, so that + * application can distinguish different run-levels + */ + + init_taskid = exec_namedapp(CONFIG_BUILTIN_APP_START, argv); +#else + /* Start the default application at USER_ENTRYPOINT() */ + + init_taskid = TASK_CREATE("init", SCHED_PRIORITY_DEFAULT, + CONFIG_USERMAIN_STACKSIZE, + (main_t)USER_ENTRYPOINT, (const char **)NULL); +#endif + ASSERT(init_taskid != ERROR); + return OK; +} diff --git a/nuttx/sched/os_internal.h b/nuttx/sched/os_internal.h new file mode 100644 index 0000000000..13b8083cff --- /dev/null +++ b/nuttx/sched/os_internal.h @@ -0,0 +1,306 @@ +/**************************************************************************** + * sched/os_internal.h + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __SCHED_OS_INTERNAL_H +#define __SCHED_OS_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* OS CRASH CODES: All must lie in the range 0-99 */ + +enum os_crash_codes_e +{ + OSERR_NOERROR = 0, /* No error */ + OSERR_NOTIMPLEMENTED, /* Feature is not implemented */ + OSERR_INTERNAL, /* Internal logic error */ + OSERR_UNEXPECTEDISR, /* Received unexpected interrupt */ + OSERR_UNDEFINEDINSN, /* Undefined instruction */ + OSERR_ERREXCEPTION, /* Other CPU-detected errors */ + OSERR_OUTOFMEMORY, /* Insufficient memory */ + OSERR_OUTOFMESSAGES, /* Out of messages */ + OSERR_NOIDLETASK, /* There is no idle task */ + OSERR_MQNONEMPTYCOUNT, /* Expected waiter for non-empty queue */ + OSERR_MQNOTFULLCOUNT, /* Expected waiter for non-full queue */ + OSERR_MQNOWAITER, /* Expected a queue for the waiter */ + OSERR_BADWAITSEM, /* Already waiting for a semaphore */ + OSERR_BADMSGTYPE, /* Tried to free a bad message type */ + OSERR_FAILEDTOADDSIGNAL, /* Failed to add pending signal */ + OSERR_FAILEDTOREMOVESIGNAL, /* Failed to remove pending signal */ + OSERR_TIMEOUTNOTCB, /* Timed out, but not TCB registered */ + OSERR_NOPENDINGSIGNAL, /* Expected a signal to be pending */ + OSERR_BADDELETESTATE, /* Bad state in task deletion */ + OSERR_WDOGNOTFOUND, /* Active watchdog not found */ + OSERR_EXITFROMINTERRUPT, /* Interrupt code attempted to exit */ + OSERR_BADUNBLOCKSTATE, /* Attempt to unblock from bad state */ + OSERR_BADBLOCKSTATE, /* Attempt to block from bad state */ + OSERR_BADREPRIORITIZESTATE /* Attempt to reprioritize in bad state or priority */ +}; + +/* Special task IDS */ + +#define NULL_TASK_PROCESS_ID 0 +#define INVALID_PROCESS_ID 0 + +/* Although task IDs can take the (positive, non-zero) + * range of pid_t, the number of tasks that will be supported + * at any one time is (artificially) limited by the CONFIG_MAX_TASKS + * configuration setting. Limiting the number of tasks speeds certain + * OS functions (this is the only limitation in the number of + * tasks built into the design). + */ + +#define MAX_TASKS_MASK (CONFIG_MAX_TASKS-1) +#define PIDHASH(pid) ((pid) & MAX_TASKS_MASK) + +/* Stubs used when there are no file descriptors */ + +#if CONFIG_NFILE_DESCRIPTORS <= 0 && CONFIG_NSOCKET_DESCRIPTORS <= 0 +# define sched_setupidlefiles(t) (OK) +# define sched_setuptaskfiles(t) (OK) +# define sched_setuppthreadfiles(t) (OK) +# define sched_releasefiles(t) (OK) +#endif + +/* One processor family supported by NuttX has a single, fixed hardware stack. + * That is the 8051 family. So for that family only, there is a variant form + * of kernel_thread() that does not take a stack size parameter. The following + * helper macro is provided to work around the ugliness of that exception. + */ + +#ifndef CONFIG_CUSTOM_STACK +# define KERNEL_THREAD(n,p,s,e,a) kernel_thread(n,p,s,e,a) +#else +# define KERNEL_THREAD(n,p,s,e,a) kernel_thread(n,p,e,a) +#endif + +/* A more efficient ways to access the errno */ + +#define SET_ERRNO(e) \ + { _TCB *rtcb = _TCB*)g_readytorun.head; rtcb->pterrno = (e); } + +#define _SET_TCB_ERRNO(t,e) \ + { (t)->pterrno = (e); } + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* This structure defines the format of the hash table that + * is used to (1) determine if a task ID is unique, and (2) + * to map a process ID to its corresponding TCB. + */ + +struct pidhash_s +{ + FAR _TCB *tcb; + pid_t pid; +}; + +typedef struct pidhash_s pidhash_t; + +/* This structure defines an element of the g_tasklisttable[]. + * This table is used to map a task_state enumeration to the + * corresponding task list. + */ + +struct tasklist_s +{ + DSEG volatile dq_queue_t *list; /* Pointer to the task list */ + bool prioritized; /* true if the list is prioritized */ +}; + +typedef struct tasklist_s tasklist_t; + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* Declared in os_start.c ***************************************************/ + +/* The state of a task is indicated both by the task_state field of the TCB + * and by a series of task lists. All of these tasks lists are declared + * below. Although it is not always necessary, most of these lists are + * prioritized so that common list handling logic can be used (only the + * g_readytorun, the g_pendingtasks, and the g_waitingforsemaphore lists need + * to be prioritized). + */ + +/* This is the list of all tasks that are ready to run. The head of this + * list is the currently active task; the tail of this list is always the + * IDLE task. + */ + +extern volatile dq_queue_t g_readytorun; + +/* This is the list of all tasks that are ready-to-run, but cannot be placed + * in the g_readytorun list because: (1) They are higher priority than the + * currently active task at the head of the g_readytorun list, and (2) the + * currently active task has disabled pre-emption. + */ + +extern volatile dq_queue_t g_pendingtasks; + +/* This is the list of all tasks that are blocked waiting for a semaphore */ + +extern volatile dq_queue_t g_waitingforsemaphore; + +/* This is the list of all tasks that are blocked waiting for a signal */ + +#ifndef CONFIG_DISABLE_SIGNALS +extern volatile dq_queue_t g_waitingforsignal; +#endif + +/* This is the list of all tasks that are blocked waiting for a message + * queue to become non-empty. + */ + +#ifndef CONFIG_DISABLE_MQUEUE +extern volatile dq_queue_t g_waitingformqnotempty; +#endif + +/* This is the list of all tasks that are blocked waiting for a message + * queue to become non-full. + */ + +#ifndef CONFIG_DISABLE_MQUEUE +extern volatile dq_queue_t g_waitingformqnotfull; +#endif + +/* This is the list of all tasks that are blocking waiting for a page fill */ + +#ifdef CONFIG_PAGING +extern volatile dq_queue_t g_waitingforfill; +#endif + +/* This the list of all tasks that have been initialized, but not yet + * activated. NOTE: This is the only list that is not prioritized. + */ + +extern volatile dq_queue_t g_inactivetasks; + +/* This is the list of dayed memory deallocations that need to be handled + * within the IDLE loop. These deallocations get queued by sched_free() + * if the OS attempts to deallocate memory while it is within an interrupt + * handler. + */ + +extern volatile sq_queue_t g_delayeddeallocations; + +/* This is the value of the last process ID assigned to a task */ + +extern volatile pid_t g_lastpid; + +/* The following hash table is used for two things: + * + * 1. This hash table greatly speeds the determination of a new unique + * process ID for a task, and + * 2. Is used to quickly map a process ID into a TCB. + * + * It has the side effects of using more memory and limiting the number + * of tasks to CONFIG_MAX_TASKS. + */ + +extern pidhash_t g_pidhash[CONFIG_MAX_TASKS]; + +/* This is a table of task lists. This table is indexed by the task state + * enumeration type (tstate_t) and provides a pointer to the associated + * static task list (if there is one) as well as a boolean indication as to + * if the list is an ordered list or not. + */ + +extern const tasklist_t g_tasklisttable[NUM_TASK_STATES]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int os_bringup(void); +void task_start(void); +int task_schedsetup(FAR _TCB *tcb, int priority, start_t start, + main_t main); +int task_argsetup(FAR _TCB *tcb, FAR const char *name, FAR const char *argv[]); +void task_exithook(FAR _TCB *tcb, int status); +int task_deletecurrent(void); +#ifndef CONFIG_CUSTOM_STACK +int kernel_thread(FAR const char *name, int priority, int stack_size, + main_t entry, FAR const char *argv[]); +#else +int kernel_thread(FAR const char *name, int priority, main_t entry, + FAR const char *argv[]); +#endif +bool sched_addreadytorun(FAR _TCB *rtrtcb); +bool sched_removereadytorun(FAR _TCB *rtrtcb); +bool sched_addprioritized(FAR _TCB *newTcb, DSEG dq_queue_t *list); +bool sched_mergepending(void); +void sched_addblocked(FAR _TCB *btcb, tstate_t task_state); +void sched_removeblocked(FAR _TCB *btcb); +int sched_setpriority(FAR _TCB *tcb, int sched_priority); +#ifdef CONFIG_PRIORITY_INHERITANCE +int sched_reprioritize(FAR _TCB *tcb, int sched_priority); +#else +# define sched_reprioritize(tcb,sched_priority) sched_setpriority(tcb,sched_priority) +#endif +FAR _TCB *sched_gettcb(pid_t pid); +bool sched_verifytcb(FAR _TCB *tcb); + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 +int sched_setupidlefiles(FAR _TCB *tcb); +int sched_setuptaskfiles(FAR _TCB *tcb); +int sched_setuppthreadfiles(FAR _TCB *tcb); +#if CONFIG_NFILE_STREAMS > 0 +int sched_setupstreams(FAR _TCB *tcb); +#endif +int sched_releasefiles(FAR _TCB *tcb); +#endif + +int sched_releasetcb(FAR _TCB *tcb); +void sched_garbagecollection(void); + +#endif /* __SCHED_OS_INTERNAL_H */ diff --git a/nuttx/sched/os_start.c b/nuttx/sched/os_start.c new file mode 100644 index 0000000000..6cd508b8ca --- /dev/null +++ b/nuttx/sched/os_start.c @@ -0,0 +1,463 @@ +/**************************************************************************** + * sched/os_start.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" +#include "wd_internal.h" +#include "sem_internal.h" +#ifndef CONFIG_DISABLE_MQUEUE +# include "mq_internal.h" +#endif +#ifndef CONFIG_DISABLE_PTHREAD +# include "pthread_internal.h" +#endif +#include "clock_internal.h" +#include "timer_internal.h" +#include "irq_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* Task Lists ***************************************************************/ +/* The state of a task is indicated both by the task_state field of the TCB + * and by a series of task lists. All of these tasks lists are declared + * below. Although it is not always necessary, most of these lists are + * prioritized so that common list handling logic can be used (only the + * g_readytorun, the g_pendingtasks, and the g_waitingforsemaphore lists need + * to be prioritized). + */ + +/* This is the list of all tasks that are ready to run. The head of this + * list is the currently active task; the tail of this list is always the + * IDLE task. + */ + +volatile dq_queue_t g_readytorun; + +/* This is the list of all tasks that are ready-to-run, but cannot be placed + * in the g_readytorun list because: (1) They are higher priority than the + * currently active task at the head of the g_readytorun list, and (2) the + * currently active task has disabled pre-emption. + */ + +volatile dq_queue_t g_pendingtasks; + +/* This is the list of all tasks that are blocked waiting for a semaphore */ + +volatile dq_queue_t g_waitingforsemaphore; + +/* This is the list of all tasks that are blocked waiting for a signal */ + +#ifndef CONFIG_DISABLE_SIGNALS +volatile dq_queue_t g_waitingforsignal; +#endif + +/* This is the list of all tasks that are blocked waiting for a message + * queue to become non-empty. + */ + +#ifndef CONFIG_DISABLE_MQUEUE +volatile dq_queue_t g_waitingformqnotempty; +#endif + +/* This is the list of all tasks that are blocked waiting for a message + * queue to become non-full. + */ + +#ifndef CONFIG_DISABLE_MQUEUE +volatile dq_queue_t g_waitingformqnotfull; +#endif + +/* This is the list of all tasks that are blocking waiting for a page fill */ + +#ifdef CONFIG_PAGING +volatile dq_queue_t g_waitingforfill; +#endif + +/* This the list of all tasks that have been initialized, but not yet + * activated. NOTE: This is the only list that is not prioritized. + */ + +volatile dq_queue_t g_inactivetasks; + +/* This is the list of dayed memory deallocations that need to be handled + * within the IDLE loop. These deallocations get queued by sched_free() + * if the OS attempts to deallocate memory while it is within an interrupt + * handler. + */ + +volatile sq_queue_t g_delayeddeallocations; + +/* This is the value of the last process ID assigned to a task */ + +volatile pid_t g_lastpid; + +/* The following hash table is used for two things: + * + * 1. This hash table greatly speeds the determination of + * a new unique process ID for a task, and + * 2. Is used to quickly map a process ID into a TCB. + * It has the side effects of using more memory and limiting + * + * the number of tasks to CONFIG_MAX_TASKS. + */ + +pidhash_t g_pidhash[CONFIG_MAX_TASKS]; + +/* This is a table of task lists. This table is indexed by + * the task state enumeration type (tstate_t) and provides + * a pointer to the associated static task list (if there + * is one) as well as a boolean indication as to if the list + * is an ordered list or not. + */ + +const tasklist_t g_tasklisttable[NUM_TASK_STATES] = +{ + { NULL, false }, /* TSTATE_TASK_INVALID */ + { &g_pendingtasks, true }, /* TSTATE_TASK_PENDING */ + { &g_readytorun, true }, /* TSTATE_TASK_READYTORUN */ + { &g_readytorun, true }, /* TSTATE_TASK_RUNNING */ + { &g_inactivetasks, false }, /* TSTATE_TASK_INACTIVE */ + { &g_waitingforsemaphore, true } /* TSTATE_WAIT_SEM */ +#ifndef CONFIG_DISABLE_SIGNALS + , + { &g_waitingforsignal, false } /* TSTATE_WAIT_SIG */ +#endif +#ifndef CONFIG_DISABLE_MQUEUE + , + { &g_waitingformqnotempty, true }, /* TSTATE_WAIT_MQNOTEMPTY */ + { &g_waitingformqnotfull, true } /* TSTATE_WAIT_MQNOTFULL */ +#endif +#ifdef CONFIG_PAGING + , + { &g_waitingforfill, true } /* TSTATE_WAIT_PAGEFILL */ +#endif +}; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ +/* This is the task control block for this thread of execution. This thread + * of execution is the IDLE task. NOTE: the system boots into the IDLE + * task. The IDLE task spawns the user initialization task (user_start) and + * that user init task is responsible for bringing up the rest of the system + */ + +static FAR _TCB g_idletcb; + +/* This is the name of the idle task */ + +static FAR const char g_idlename[] = "Idle Task"; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: os_start + * + * Description: + * This function is called to initialize the operating system and to spawn + * the user initization thread of execution + * + ****************************************************************************/ + +void os_start(void) +{ + int i; + + slldbg("Entry\n"); + + /* Initialize all task lists */ + + dq_init(&g_readytorun); + dq_init(&g_pendingtasks); + dq_init(&g_waitingforsemaphore); +#ifndef CONFIG_DISABLE_SIGNALS + dq_init(&g_waitingforsignal); +#endif +#ifndef CONFIG_DISABLE_MQUEUE + dq_init(&g_waitingformqnotfull); + dq_init(&g_waitingformqnotempty); +#endif +#ifdef CONFIG_PAGING + dq_init(&g_waitingforfill); +#endif + dq_init(&g_inactivetasks); + sq_init(&g_delayeddeallocations); + + /* Initialize the logic that determine unique process IDs. */ + + g_lastpid = 0; + for (i = 0; i < CONFIG_MAX_TASKS; i++) + { + g_pidhash[i].tcb = NULL; + g_pidhash[i].pid = INVALID_PROCESS_ID; + } + + /* Assign the process ID of ZERO to the idle task */ + + g_pidhash[ PIDHASH(0)].tcb = &g_idletcb; + g_pidhash[ PIDHASH(0)].pid = 0; + + /* Initialize a TCB for this thread of execution. NOTE: The default + * value for most components of the g_idletcb are zero. The entire + * structure is set to zero. Then only the (potentially) non-zero + * elements are initialized. NOTE: The idle task is the only task in + * that has pid == 0 and sched_priority == 0. + */ + + bzero((void*)&g_idletcb, sizeof(_TCB)); + g_idletcb.task_state = TSTATE_TASK_RUNNING; + g_idletcb.entry.main = (main_t)os_start; + +#if CONFIG_TASK_NAME_SIZE > 0 + strncpy(g_idletcb.name, g_idlename, CONFIG_TASK_NAME_SIZE-1); + g_idletcb.argv[0] = g_idletcb.name; +#else + g_idletcb.argv[0] = (char*)g_idlename; +#endif /* CONFIG_TASK_NAME_SIZE */ + + /* Then add the idle task's TCB to the head of the ready to run list */ + + dq_addfirst((FAR dq_entry_t*)&g_idletcb, (FAR dq_queue_t*)&g_readytorun); + + /* Initialize the processor-specific portion of the TCB */ + + g_idletcb.flags = TCB_FLAG_TTYPE_KERNEL; + up_initial_state(&g_idletcb); + + /* Initialize the memory manager */ + +#ifndef CONFIG_HEAP_BASE + { + FAR void *heap_start; + size_t heap_size; + up_allocate_heap(&heap_start, &heap_size); + kmm_initialize(heap_start, heap_size); + } +#else + kmm_initialize((void*)CONFIG_HEAP_BASE, CONFIG_HEAP_SIZE); +#endif + + /* Initialize the interrupt handling subsystem (if included) */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (irq_initialize != NULL) +#endif + { + irq_initialize(); + } + + /* Initialize the watchdog facility (if included in the link) */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (wd_initialize != NULL) +#endif + { + wd_initialize(); + } + + /* Initialize the POSIX timer facility (if included in the link) */ + +#ifndef CONFIG_DISABLE_CLOCK +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (clock_initialize != NULL) +#endif + { + clock_initialize(); + } +#endif + +#ifndef CONFIG_DISABLE_POSIX_TIMERS +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (timer_initialize != NULL) +#endif + { + timer_initialize(); + } +#endif + + /* Initialize the signal facility (if in link) */ + +#ifndef CONFIG_DISABLE_SIGNALS +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (sig_initialize != NULL) +#endif + { + sig_initialize(); + } +#endif + + /* Initialize the semaphore facility. (if in link) */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (sem_initialize != NULL) +#endif + { + sem_initialize(); + } + + /* Initialize the named message queue facility (if in link) */ + +#ifndef CONFIG_DISABLE_MQUEUE +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (mq_initialize != NULL) +#endif + { + mq_initialize(); + } +#endif + + /* Initialize the thread-specific data facility (if in link) */ + +#ifndef CONFIG_DISABLE_PTHREAD +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (pthread_initialize != NULL) +#endif + { + pthread_initialize(); + } +#endif + + /* Initialize the file system (needed to support device drivers) */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (fs_initialize != NULL) +#endif + { + fs_initialize(); + } +#endif + + /* Initialize the network system */ + +#ifdef CONFIG_NET +#if 0 + if (net_initialize != NULL) +#endif + { + net_initialize(); + } +#endif + + /* The processor specific details of running the operating system + * will be handled here. Such things as setting up interrupt + * service routines and starting the clock are some of the things + * that are different for each processor and hardware platform. + */ + + up_initialize(); + + /* Initialize the C libraries (if included in the link). This + * is done last because the libraries may depend on the above. + */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (lib_initialize != NULL) +#endif + { + lib_initialize(); + } + + /* Create stdout, stderr, stdin */ + + (void)sched_setupidlefiles(&g_idletcb); + + /* Create initial tasks and bring-up the system */ + + (void)os_bringup(); + + /* When control is return to this point, the system is idle. */ + + sdbg("Beginning Idle Loop\n"); + for (;;) + { + /* Perform garbage collection (if it is not being done by the worker + * thread). This cleans-up memory de-allocations that were queued + * because they could not be freed in that execution context (for + * example, if the memory was freed from an interrupt handler). + */ + +#ifndef CONFIG_SCHED_WORKQUEUE + /* We must have exclusive access to the memory manager to do this + * BUT the idle task cannot wait on a semaphore. So we only do + * the cleanup now if we can get the semaphore -- this should be + * possible because if the IDLE thread is running, no other task is! + */ + + if (kmm_trysemaphore() == 0) + { + sched_garbagecollection(); + kmm_givesemaphore(); + } +#endif + + /* Perform any processor-specific idle state operations */ + + up_idle(); + } +} diff --git a/nuttx/sched/pg_internal.h b/nuttx/sched/pg_internal.h new file mode 100644 index 0000000000..e7bafcd91f --- /dev/null +++ b/nuttx/sched/pg_internal.h @@ -0,0 +1,126 @@ +/**************************************************************************** + * sched/pg_internal.h + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __SCHED_PG_INTERNAL_H +#define __SCHED_PG_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifdef CONFIG_PAGING + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Supply reasonable (but probably non-optimal) default settings if + * configuration items are omitted. + */ + +#ifndef CONFIG_PAGING_DEFPRIO +# define CONFIG_PAGING_DEFPRIO 50 +#endif + +#ifndef CONFIG_PAGING_WORKPERIOD +# define CONFIG_PAGING_WORKPERIOD (500*1000) /* 1/2 second */ +#endif + +#ifndef CONFIG_PAGING_STACKSIZE +# define CONFIG_PAGING_STACKSIZE CONFIG_IDLETHREAD_STACKSIZE +#endif + +#ifdef CONFIG_DISABLE_SIGNALS +# warning "Page fill support requires signals" +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY + +/* This is the task IDof the page fill worker thread. This value was set in + * os_start when the page fill worker thread was started. + */ + +extern pid_t g_pgworker; + +/* The page fill worker thread maintains a static variable called g_pftcb. + * If no page fill is in progress, g_pftcb will be NULL. Otherwise, g_pftcb + * will point to the TCB of the task which is receiving the fill that is + * in progess. + * + * NOTE: I think that this is the only state in which a TCB does not reside + * in some list. Here is it in limbo, outside of the normally queuing while + * the page file is in progress. Where here, it will be marked with + * TSTATE_TASK_INVALID. + */ + +extern FAR _TCB *g_pftcb; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: pg_worker + * + * Description: + * This is the entry point of the worker thread that performs the actual + * page file. + * + * Input parameters: + * argc, argv (not used) + * + * Returned Value: + * Does not return + * + ****************************************************************************/ + +int pg_worker(int argc, char *argv[]); + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_PAGING */ +#endif /* __SCHED_PG_INTERNAL_H */ diff --git a/nuttx/sched/pg_miss.c b/nuttx/sched/pg_miss.c new file mode 100644 index 0000000000..8a649a6d51 --- /dev/null +++ b/nuttx/sched/pg_miss.c @@ -0,0 +1,179 @@ +/**************************************************************************** + * sched/pg_miss.c + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#ifdef CONFIG_PAGING + +#include "os_internal.h" +#include "pg_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pg_miss + * + * Description: + * This function is called from architecture-specific memory segmentation + * fault handling logic. This function will perform the following + * operations: + * + * 1) Sanity checking. + * - ASSERT if the currently executing task is the page fill worker + * thread. The page fill worker thread is how the the page fault + * is resolved and all logic associated with the page fill worker + * must be "locked" and always present in memory. + * - ASSERT if an interrupt was executing at the time of the exception. + * 2) Block the currently executing task. + * - Call up_block_task() to block the task at the head of the ready- + * to-run list. This should cause an interrupt level context switch + * to the next highest priority task. + * - The blocked task will be marked with state TSTATE_WAIT_PAGEFILL + * and will be retained in the g_waitingforfill prioritized task + * list. + * 3) Boost the page fill worker thread priority. + * - Check the priority of the task at the head of the g_waitingforfill + * list. If the priority of that task is higher than the current + * priority of the page fill worker thread, then boost the priority + * of the page fill worker thread to that priority. + * 4) Signal the page fill worker thread. + * - Is there a page fill pending? If not then signal the worker + * thread to start working on the queued page fill requests. + * + * Input Parameters: + * None - The head of the ready-to-run list is assumed to be task that + * caused the exception. + * + * Returned Value: + * None - Either this function function succeeds or an assertion occurs. + * + * Assumptions: + * - It is assumed that this function is called from the level of an + * exception handler and that all interrupts are disabled. + * - It is assumed that currently executing task (the one at the head of + * the ready-to-run list) is the one that cause the fault. This will + * always be true unless the page fault occurred in an interrupt handler. + * Interrupt handling logic must always be present and "locked" into + * memory. + * - As mentioned above, the task causing the page fault must not be the + * page fill worker thread because that is the only way to complete the + * page fill. + * + * NOTES: + * 1. One way to accomplish this would be a two pass link phase: + * - In the first phase, create a partially linked objected containing + * all interrupt/exception handling logic, the page fill worker thread + * plus all parts of the IDLE thread (which must always be available + * for execution). + * - All of the .text and .rodata sections of this partial link should + * be collected into a single section. + * - The second link would link the partially linked object along with + * the remaining object to produce the final binary. The linker + * script should position the "special" section so that it lies + * in a reserved, "non-swappable" region. + * + ****************************************************************************/ + +void pg_miss(void) +{ + FAR _TCB *ftcb = (FAR _TCB*)g_readytorun.head; + FAR _TCB *wtcb; + + /* Sanity checking + * + * ASSERT if the currently executing task is the page fill worker thread. + * The page fill worker thread is how the the page fault is resolved and + * all logic associated with the page fill worker must be "locked" and + * always present in memory. + */ + + pglldbg("Blocking TCB: %p PID: %d\n", ftcb, ftcb->pid); + DEBUGASSERT(g_pgworker != ftcb->pid); + + /* Block the currently executing task + * - Call up_block_task() to block the task at the head of the ready- + * to-run list. This should cause an interrupt level context switch + * to the next highest priority task. + * - The blocked task will be marked with state TSTATE_WAIT_PAGEFILL + * and will be retained in the g_waitingforfill prioritized task list. + */ + + up_block_task(ftcb, TSTATE_WAIT_PAGEFILL); + + /* Boost the page fill worker thread priority. + * - Check the priority of the task at the head of the g_waitingforfill + * list. If the priority of that task is higher than the current + * priority of the page fill worker thread, then boost the priority + * of the page fill worker thread to that priority. + */ + + wtcb = sched_gettcb(g_pgworker); + DEBUGASSERT(wtcb != NULL); + + if (wtcb->sched_priority < ftcb->sched_priority) + { + /* Reprioritize the page fill worker thread */ + + pgllvdbg("New worker priority. %d->%d\n", + wtcb->sched_priority, ftcb->sched_priority); + sched_setpriority(wtcb, ftcb->sched_priority); + } + + /* Signal the page fill worker thread. + * - Is there a page fill pending? If not then signal the worker + * thread to start working on the queued page fill requests. + */ + + if (!g_pftcb) + { + pglldbg("Signaling worker. PID: %d\n", g_pgworker); + kill(g_pgworker, SIGWORK); + } +} + +#endif /* CONFIG_PAGING */ diff --git a/nuttx/sched/pg_worker.c b/nuttx/sched/pg_worker.c new file mode 100644 index 0000000000..4a18ec9a38 --- /dev/null +++ b/nuttx/sched/pg_worker.c @@ -0,0 +1,678 @@ +/**************************************************************************** + * sched/pg_worker.c + * Page fill worker thread implementation. + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "os_internal.h" +#include "pg_internal.h" + +#ifdef CONFIG_PAGING + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifdef CONFIG_DISABLE_SIGNALS +# warning "Signals needed by this function (CONFIG_DISABLE_SIGNALS=n)" +#endif + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* This is the task ID of the page fill worker thread. This value was set in + * os_start when the page fill worker thread was started. + */ + +pid_t g_pgworker; + +/* The page fill worker thread maintains a static variable called g_pftcb. + * If no fill is in progress, g_pftcb will be NULL. Otherwise, g_pftcb will + * point to the TCB of the task which is receiving the fill that is in progess. + * + * NOTE: I think that this is the only state in which a TCB does not reside + * in some list. Here is it in limbo, outside of the normally queuing while + * the page file is in progress. Where here, it will be marked with + * TSTATE_TASK_INVALID. + */ + +FAR _TCB *g_pftcb; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +#ifndef CONFIG_PAGING_BLOCKINGFILL + +/* When a page fill completes, the result of the fill is stored here. The + * value -EBUSY means that the page fill callback has not yet been received. + */ + +static int g_fillresult; + +/* A configurable timeout period (in clock ticks) may be select to detect + * page fill failures. + */ + +#ifdef CONFIG_PAGING_TIMEOUT_TICKS +status uint32_t g_starttime; +#endif +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pg_callback + * + * Description: + * This function is called from the architecture-specific, page fill logic + * when the page fill completes (with or without an error). A reference to + * this function was provided to up_fillpage(). The driver will provide + * the result of the fill as an argument. + * + * NOTE: pg_callback() must also be locked in memory. + * + * When pg_callback() is called, it will perform the following operations: + * + * - Verify that g_pftcb is non-NULL. + * - Find the higher priority between the task waiting for the fill to + * complete in g_pftcb and the task waiting at the head of the + * g_waitingforfill list. That will be the priority of he highest priority + * task waiting for a fill. + * - If this higher priority is higher than current page fill worker thread, + * then boost worker thread's priority to that level. Thus, the page fill + * worker thread will always run at the priority of the highest priority + * task that is waiting for a fill. + * - Signal the page fill worker thread. + * + * Input parameters: + * tcb - The TCB of the task that just received the fill. + * result - The result of the page fill operation. + * + * Returned Value: + * None + * + * Assumptions: + * Possibly executing in the context of a driver interrupt handler??? + * + ****************************************************************************/ + +#ifndef CONFIG_PAGING_BLOCKINGFILL +static void pg_callback(FAR _TCB *tcb, int result) +{ + /* Verify that g_pftcb is non-NULL */ + + pgllvdbg("g_pftcb: %p\n", g_pftcb); + if (g_pftcb) + { + FAR _TCB *htcb = (FAR _TCB *)g_waitingforfill.head; + FAR _TCB *wtcb = sched_gettcb(g_pgworker); + + /* Find the higher priority between the task waiting for the fill to + * complete in g_pftcb and the task waiting at the head of the + * g_waitingforfill list. That will be the priority of he highest + * priority task waiting for a fill. + */ + + int priority = g_pftcb->sched_priority; + if (htcb && priority < htcb->sched_priority) + { + priority = htcb->sched_priority; + } + + /* If this higher priority is higher than current page fill worker + * thread, then boost worker thread's priority to that level. Thus, + * the page fill worker thread will always run at the priority of + * the highest priority task that is waiting for a fill. + */ + + if (priority > wtcb->sched_priority) + { + pgllvdbg("New worker priority. %d->%d\n", + wtcb->sched_priority, priority); + sched_setpriority(wtcb, priority); + } + + /* Save the page fill result (don't permit the value -EBUSY) */ + + if (result == -EBUSY) + { + result = -ENOSYS; + } + + g_fillresult = result; + } + + /* Signal the page fill worker thread (in any event) */ + + pglldbg("Signaling worker. PID: %d\n", g_pgworker); + kill(g_pgworker, SIGWORK); +} +#endif + +/**************************************************************************** + * Name: pg_dequeue + * + * Description: + * Dequeue the next, highest priority TCB from the g_waitingforfill task + * list. Call up_checkmapping() see if the still needs to be performed + * for that task. In certain conditions, the page fault may occur on + * several threads for the same page and be queued multiple times. In this + * corner case, the blocked task will simply be restarted. + * + * This function will continue to examine g_waitingforfill until either + * (1) a task is found that still needs the page fill, or (2) the + * g_waitingforfill task list becomes empty. + * + * The result (NULL or a TCB pointer) will be returned in the global + * variable, g_pftcb. + * + * Input parameters: + * None + * + * Returned Value: + * If there are no further queue page fill operations to be performed, + * pg_dequeue() will return false. Otherwise, it will return + * true to that the full is in process (any errors will result in + * assertions and this function will not return). + * + * Assumptions: + * Executing in the context of the page fill worker thread with all + * interrupts disabled. + * + ****************************************************************************/ + +static inline bool pg_dequeue(void) +{ + /* Loop until either (1) the TCB of a task that requires a fill is found, OR + * (2) the g_watingforfill list becomes empty. + */ + + do + { + /* Remove the TCB from the head of the list (if any) */ + + g_pftcb = (FAR _TCB *)dq_remfirst((dq_queue_t*)&g_waitingforfill); + pgllvdbg("g_pftcb: %p\n", g_pftcb); + if (g_pftcb != NULL) + { + /* Call the architecture-specific function up_checkmapping() to see if + * the page fill still needs to be performed. In certain conditions, + * the page fault may occur on several threads for the same page and + * be queues multiple times. In this corner case, the blocked task will + * simply be restarted. + */ + + if (!up_checkmapping(g_pftcb)) + { + /* This page needs to be filled. pg_miss bumps up + * the priority of the page fill worker thread as each + * TCB is added to the g_waitingforfill list. So we + * may need to also drop the priority of the worker + * thread as the next TCB comes off of the list. + * + * If wtcb->sched_priority > CONFIG_PAGING_DEFPRIO, + * then the page fill worker thread is executing at + * an elevated priority that may be reduced. + * + * If wtcb->sched_priority > g_pftcb->sched_priority + * then the page fill worker thread is executing at + * a higher priority than is appropriate for this + * fill (this priority can get re-boosted by pg_miss() + * if a new higher priority fill is required). + */ + + FAR _TCB *wtcb = (FAR _TCB *)g_readytorun.head; + if (wtcb->sched_priority > CONFIG_PAGING_DEFPRIO && + wtcb->sched_priority > g_pftcb->sched_priority) + { + /* Don't reduce the priority of the page fill + * worker thread lower than the configured + * minimum. + */ + + int priority = g_pftcb->sched_priority; + if (priority < CONFIG_PAGING_DEFPRIO) + { + priority = CONFIG_PAGING_DEFPRIO; + } + + /* Reduce the priority of the page fill worker thread */ + + pgllvdbg("New worker priority. %d->%d\n", + wtcb->sched_priority, priority); + sched_setpriority(wtcb, priority); + } + + /* Return with g_pftcb holding the pointer to + * the TCB associated with task that requires the page fill. + */ + + return true; + } + + /* The page need by this task has already been mapped into the + * virtual address space -- just restart it. + */ + + pglldbg("Restarting TCB: %p\n", g_pftcb); + up_unblock_task(g_pftcb); + } + } + while (g_pftcb != NULL); + + return false; +} + +/**************************************************************************** + * Name: pg_startfill + * + * Description: + * Start a page fill operation on the thread whose TCB is at the head of + * of the g_waitingforfill task list. That is a prioritized list so that + * will be the highest priority task waiting for a page fill (in the event + * that are multiple tasks waiting for a page fill). + * + * This function may be called either (1) when the page fill worker thread + * is notified that there is a new page fill TCB in the g_waitingforfill + * prioritized list, or (2) when a page fill completes and there are more + * pages to be filled in g_waitingforfill list. + * + * Input parameters: + * None + * + * Returned Value: + * If there are no further queue page fill operations to be performed, + * pg_startfill() will return false. Otherwise, it will return + * true to that the full is in process (any errors will result in + * assertions and this function will not return). + * + * Assumptions: + * Executing in the context of the page fill worker thread with all + * interrupts disabled. + * + ****************************************************************************/ + +static inline bool pg_startfill(void) +{ + FAR void *vpage; + int result; + + /* Remove the TCB at the head of the g_waitfor fill list and check if there + * is any task waiting for a page fill. pg_dequeue will handle this (plus + * some cornercases) and will true if the next page TCB was successfully + * dequeued. + */ + + if (pg_dequeue()) + { + /* Call up_allocpage(tcb, &vpage). This architecture-specific function will + * set aside page in memory and map to virtual address (vpage). If all + * available pages are in-use (the typical case), this function will select + * a page in-use, un-map it, and make it available. + */ + + pgllvdbg("Call up_allocpage(%p)\n", g_pftcb); + result = up_allocpage(g_pftcb, &vpage); + DEBUGASSERT(result == OK); + + /* Start the fill. The exact way that the fill is started depends upon + * the nature of the architecture-specific up_fillpage() function -- Is it + * a blocking or a non-blocking call? + */ +#ifdef CONFIG_PAGING_BLOCKINGFILL + /* If CONFIG_PAGING_BLOCKINGFILL is defined, then up_fillpage is blocking + * call. In this case, up_fillpage() will accept only (1) a reference to + * the TCB that requires the fill. Architecture-specific context information + * within the TCB will be sufficient to perform the fill. And (2) the + * (virtual) address of the allocated page to be filled. The resulting + * status of the fill will be provided by return value from up_fillpage(). + */ + + pgllvdbg("Call up_fillpage(%p)\n", g_pftcb); + result = up_fillpage(g_pftcb, vpage); + DEBUGASSERT(result == OK); +#else + /* If CONFIG_PAGING_BLOCKINGFILL is defined, then up_fillpage is non-blocking + * call. In this case up_fillpage() will accept an additional argument: The page + * fill worker thread will provide a callback function, pg_callback. + * + * Calling up_fillpage will start an asynchronous page fill. pg_callback + * ill be called when the page fill is finished (or an error occurs). This + * This callback will probably from interrupt level. + */ + + pgllvdbg("Call up_fillpage(%p)\n", g_pftcb); + result = up_fillpage(g_pftcb, vpage, pg_callback); + DEBUGASSERT(result == OK); + + /* Save the time that the fill was started. These will be used to check for + * timeouts. + */ + +#ifdef CONFIG_PAGING_TIMEOUT_TICKS + g_starttime = clock_systimer(); +#endif + + /* Return and wait to be signaled for the next event -- the fill completion + * event. While the fill is in progress, other tasks may execute. If + * another page fault occurs during this time, the faulting task will be + * blocked, its TCB will be added (in priority order) to g_waitingforfill + * and the priority of the page worker task may be boosted. But no action + * will be taken until the current page fill completes. NOTE: The IDLE task + * must also be fully locked in memory. The IDLE task cannot be blocked. It + * the case where all tasks are blocked waiting for a page fill, the IDLE + * task must still be available to run. + */ +#endif /* CONFIG_PAGING_BLOCKINGFILL */ + + return true; + } + + pglldbg("Queue empty\n"); + return false; +} + +/**************************************************************************** + * Name: pg_alldone + * + * Description: + * Called by the page fill worker thread when all pending page fill + * operations have been completed and the g_waitingforfill list is empty. + * + * This functin will perform the following operations: + * + * - Set g_pftcb to NULL. + * - Restore the default priority of the page fill worker thread. + * + * Input parameters: + * None. + * + * Returned Value: + * None + * + * Assumptions: + * Executing in the context of the page fill worker thread with interrupts + * disabled. + * + ****************************************************************************/ + +static inline void pg_alldone(void) +{ + FAR _TCB *wtcb = (FAR _TCB *)g_readytorun.head; + g_pftcb = NULL; + pgllvdbg("New worker priority. %d->%d\n", + wtcb->sched_priority, CONFIG_PAGING_DEFPRIO); + sched_setpriority(wtcb, CONFIG_PAGING_DEFPRIO); +} + +/**************************************************************************** + * Name: pg_fillcomplete + * + * Description: + * Called by the page fill worker thread when a page fill completes. + * Either (1) in the non-blocking up_fillpage(), after the architecture- + * specific driver call the pg_callback() to wake up the page fill worker + * thread, or (2) after the blocking up_fillpage() returens (when + * CONFIG_PAGING_BLOCKINGFILL is defined). + * + * This function is just a dumb wrapper around up_unblocktask(). This + * function simply makes the task that just received the fill ready-to-run. + * + * Input parameters: + * None. + * + * Returned Value: + * None + * + * Assumptions: + * Executing in the context of the page fill worker thread with interrupts + * disabled. + * + ****************************************************************************/ + +static inline void pg_fillcomplete(void) +{ + /* Call up_unblocktask(g_pftcb) to make the task that just + * received the fill ready-to-run. + */ + + pglldbg("Restarting TCB: %p\n", g_pftcb); + up_unblock_task(g_pftcb); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: pg_worker + * + * Description: + * This is the page fill worker thread that performs pages fills for tasks + * that have received a pag fault and are blocked in the g_waitingforfill + * task queue. + * + * The page fill worker thread will be awakened on one of three conditions: + * - When signaled by pg_miss(), the page fill worker thread will be + * awakenend, or + * - if CONFIG_PAGING_BLOCKINGFILL is not defined, from pg_callback() + * after completing a page fill. + * - A configurable timeout with no activity. + * + * Input parameters: + * argc, argv (not used) + * + * Returned Value: + * Does not return + * + ****************************************************************************/ + +int pg_worker(int argc, char *argv[]) +{ + irqstate_t flags; + + /* Loop forever -- Notice that interrupts will be disable at all times that + * this thread runs. That is so that we con't lose signals or have + * asynchronous page faults. + * + * All interrupt logic as well as all page fill worker thread logic must + * be locked in memory. Therefore, keeping interrupts disabled here + * should prevent any concurrent page faults. Any page faults or page + * fill completions should occur while this thread sleeps. + */ + + pglldbg("Started\n"); + flags = irqsave(); + for (;;) + { + /* Wait awhile. We will wait here until either the configurable timeout + * elapses or until we are awakened by a signal (which terminates the + * usleep with an EINTR error). Note that interrupts will be re-enabled + * while this task sleeps. + * + * The timeout is a failsafe that will handle any cases where a single + * is lost (that would really be a bug and shouldn't happen!) and also + * supports timeouts for case of non-blocking, asynchronous fills. + */ + + usleep(CONFIG_PAGING_WORKPERIOD); + + /* The page fill worker thread will be awakened on one of three conditions: + * + * - When signaled by pg_miss(), the page fill worker thread will be awakenend, + * - if CONFIG_PAGING_BLOCKINGFILL is not defined, from pg_callback() + * after completing a page fill, or + * - On a configurable timeout expires with no activity. + * + * Interrupts are still disabled. + */ + +#ifndef CONFIG_PAGING_BLOCKINGFILL + /* For the non-blocking up_fillpage(), the page fill worker thread will detect + * that the page fill is complete when it is awakened with g_pftcb non-NULL + * and fill completion status from pg_callback. + */ + + if (g_pftcb != NULL) + { + /* If it is a real page fill completion event, then the result of the page + * fill will be in g_fillresult and will not be equal to -EBUSY. + */ + + if (g_fillresult != -EBUSY) + { + /* Any value other than OK, brings the system down */ + + ASSERT(g_fillresult == OK); + + /* Handle the successful page fill complete event by restarting the + * task that was blocked waiting for this page fill. + */ + + pglldbg("Restarting TCB: %p\n", g_pftcb); + up_unblock_task(g_pftcb);; + + /* Yes .. Start the next asynchronous fill. Check the return + * value to see a fill was actually started (false means that + * no fill was started). + */ + + pgllvdbg("Calling pg_startfill\n"); + if (!pg_startfill()) + { + /* No fill was started. This can mean only that all queued + * page fill actions have and been completed and there is + * nothing more to do. + */ + + pgllvdbg("Call pg_alldone()\n"); + pg_alldone(); + } + } + + /* If a configurable timeout period expires with no page fill completion + * event, then declare a failure. + */ + +#ifdef CONFIG_PAGING_TIMEOUT_TICKS + else + { + lldbg("Timeout!\n"); + ASSERT(clock_systimer() - g_starttime < CONFIG_PAGING_TIMEOUT_TICKS); + } +#endif + } + + /* Otherwise, this might be a page fill initiation event. When + * awakened from pg_miss(), no fill will be in progress and + * g_pftcb will be NULL. + */ + + else + { + /* Are there tasks blocked and waiting for a fill? If so, + * pg_startfill() will start the asynchronous fill (and set + * g_pftcb). + */ + + pgllvdbg("Calling pg_startfill\n"); + (void)pg_startfill(); + } +#else + /* Are there tasks blocked and waiting for a fill? Loop until all + * pending fills have been processed. + */ + + for (;;) + { + /* Yes .. Start the fill and block until the fill completes. + * Check the return value to see a fill was actually performed. + * (false means that no fill was perforemd). + */ + + pgllvdbg("Calling pg_startfill\n"); + if (!pg_startfill()) + { + /* Break out of the loop -- there is nothing more to do */ + + break; + } + + /* Handle the page fill complete event by restarting the + * task that was blocked waiting for this page fill. In the + * non-blocking fill case, the page fill worker thread will + * know that the page fill is complete when pg_startfill() + * returns true. + */ + + pgllvdbg("Restarting TCB: %p\n", g_pftcb); + up_unblock_task(g_pftcb);; + } + + /* All queued fills have been processed */ + + pgllvdbg("Call pg_alldone()\n"); + pg_alldone(); +#endif + } + + return OK; /* To keep some compilers happy */ +} +#endif /* CONFIG_PAGING */ diff --git a/nuttx/sched/prctl.c b/nuttx/sched/prctl.c new file mode 100644 index 0000000000..b340d0ec88 --- /dev/null +++ b/nuttx/sched/prctl.c @@ -0,0 +1,167 @@ +/************************************************************************ + * sched/prctl.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/**************************************************************************** + * Name: prctl + * + * Description: + * prctl() is called with a first argument describing what to do (with + * values PR_* defined above) and with additional arguments depending on + * the specific command. + * + * Returned Value: + * The returned value may depend on the specific commnand. For PR_SET_NAME + * and PR_GET_NAME, the returned value of 0 indicates successful operation. + * On any failure, -1 is retruend and the errno value is set appropriately. + * + * EINVAL The value of 'option' is not recognized. + * EFAULT optional arg1 is not a valid address. + * ESRCH No task/thread can be found corresponding to that specified + * by optional arg1. + * + ****************************************************************************/ + +int prctl(int option, ...) +{ + va_list ap; + int err; + + va_start(ap, option); + switch (option) + { + case PR_SET_NAME: + case PR_GET_NAME: +#if CONFIG_TASK_NAME_SIZE > 0 + { + /* Get the prctl arguments */ + + char *name = va_arg(ap, char *); + int pid = va_arg(ap, int); + FAR _TCB *tcb; + + /* Get the TCB associated with the PID (handling the special case of + * pid==0 meaning "this thread") + */ + + if (!pid) + { + tcb = (FAR _TCB *)g_readytorun.head; + } + else + { + tcb = sched_gettcb(pid); + } + + /* An invalid pid will be indicated by a NULL TCB returned from + * sched_gettcb() + */ + + if (!tcb) + { + sdbg("Pid does not correspond to a task: %d\n", pid); + err = ESRCH; + goto errout; + } + + /* A pointer to the task name storage must also be provided */ + + if (!name) + { + sdbg("No name provide\n"); + err = EFAULT; + goto errout; + } + + /* Now get or set the task name */ + + if (option == PR_SET_NAME) + { + /* tcb->name may not be null-terminated */ + + strncpy(tcb->name, name, CONFIG_TASK_NAME_SIZE); + } + else + { + /* The returned value will be null-terminated, truncating if necessary */ + + strncpy(name, tcb->name, CONFIG_TASK_NAME_SIZE-1); + name[CONFIG_TASK_NAME_SIZE-1] = '\0'; + } + } + break; +#else + sdbg("Option not enabled: %d\n", option); + err = ENOSYS; + goto errout; +#endif + + default: + sdbg("Unrecognized option: %d\n", option); + err = EINVAL; + goto errout; + } + + va_end(ap); + return OK; + +errout: + va_end(ap); + set_errno(err); + return ERROR; +} diff --git a/nuttx/sched/pthread_barrierdestroy.c b/nuttx/sched/pthread_barrierdestroy.c new file mode 100644 index 0000000000..40e8e875cb --- /dev/null +++ b/nuttx/sched/pthread_barrierdestroy.c @@ -0,0 +1,110 @@ +/******************************************************************************** + * sched/pthread_barriedestroy.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include +#include + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: pthread_barrier_destroy + * + * Description: + * The pthread_barrier_destroy() function destroys the barrier referenced by + * 'barrier' and releases any resources used by the barrier. The effect of + * subsequent use of the barrier is undefined until the barrier is + * reinitialized by another call to pthread_barrier_init(). The results are + * undefined if pthread_barrier_destroy() is called when any thread is blocked + * on the barrier, or if this function is called with an uninitialized barrier. + * + * Parameters: + * barrier - barrier to be destroyed. + * + * Return Value: + * 0 (OK) on success or on of the following error numbers: + * + * EBUSY The implementation has detected an attempt to destroy a barrier while + * it is in use. + * EINVAL The value specified by barrier is invalid. + * + * Assumptions: + * + ********************************************************************************/ + +int pthread_barrier_destroy(FAR pthread_barrier_t *barrier) +{ + int ret = OK; + + if (!barrier) + { + ret = EINVAL; + } + else + { + sem_destroy(&barrier->sem); + barrier->count = 0; + } + return ret; +} diff --git a/nuttx/sched/pthread_barrierinit.c b/nuttx/sched/pthread_barrierinit.c new file mode 100644 index 0000000000..73b974b180 --- /dev/null +++ b/nuttx/sched/pthread_barrierinit.c @@ -0,0 +1,122 @@ +/******************************************************************************** + * sched/pthread_barrieinit.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include +#include + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: pthread_barrier_init + * + * Description: + * The pthread_barrier_init() function allocates any resources required to use + * the barrier referenced by 'barrier' and initialized the barrier with the + * attributes referenced by attr. If attr is NULL, the default barrier + * attributes will be used. The results are undefined if pthread_barrier_init() + * is called when any thread is blocked on the barrier. The results are + * undefined if a barrier is used without first being initialized. The results + * are undefined if pthread_barrier_init() is called specifying an already + * initialized barrier. + * + * Parameters: + * barrier - the barrier to be initialized + * attr - barrier attributes to be used in the initialization. + * count - the count to be associated with the barrier. The count argument + * specifies the number of threads that must call pthread_barrier_wait() before + * any of them successfully return from the call. The value specified by + * count must be greater than zero. + * + * Return Value: + * 0 (OK) on success or on of the following error numbers: + * + * EAGAIN The system lacks the necessary resources to initialize another barrier. + * EINVAL The barrier reference is invalid, or the values specified by attr are + * invalid, or the value specified by count is equal to zero. + * ENOMEM Insufficient memory exists to initialize the barrier. + * EBUSY The implementation has detected an attempt to reinitialize a barrier + * while it is in use. + * + * Assumptions: + * + ********************************************************************************/ + +int pthread_barrier_init(FAR pthread_barrier_t *barrier, + FAR const pthread_barrierattr_t *attr, unsigned int count) +{ + int ret = OK; + + if (!barrier || count == 0) + { + ret = EINVAL; + } + else + { + sem_init(&barrier->sem, 0, 0); + barrier->count = count; + } + + return ret; +} diff --git a/nuttx/sched/pthread_barrierwait.c b/nuttx/sched/pthread_barrierwait.c new file mode 100644 index 0000000000..8ca8d17548 --- /dev/null +++ b/nuttx/sched/pthread_barrierwait.c @@ -0,0 +1,182 @@ +/******************************************************************************** + * sched/pthread_barrierwait.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: pthread_barrier_wait + * + * Description: + * The pthread_barrier_wait() function synchronizse participating threads at + * the barrier referenced by 'barrier'. The calling thread is blocked until + * the required number of threads have called pthread_barrier_wait() specifying + * the same 'barrier'. When the required number of threads have called + * pthread_barrier_wait() specifying the 'barrier', the constant + * PTHREAD_BARRIER_SERIAL_THREAD will be returned to one unspecified thread + * and zero will be returned to each of the remaining threads. At this point, + * the barrier will be reset to the state it had as a result of the most recent + * pthread_barrier_init() function that referenced it. + * + * The constant PTHREAD_BARRIER_SERIAL_THREAD is defined in pthread.h and its + * value must be distinct from any other value returned by pthread_barrier_wait(). + * + * The results are undefined if this function is called with an uninitialized + * barrier. + * + * If a signal is delivered to a thread blocked on a barrier, upon return from + * the signal handler the thread will resume waiting at the barrier if the barrier + * wait has not completed; otherwise, the thread will continue as normal from + * the completed barrier wait. Until the thread in the signal handler returns + * from it, it is unspecified whether other threads may proceed past the barrier + * once they have all reached it. + * + * A thread that has blocked on a barrier will not prevent any unblocked thread + * that is eligible to use the same processing resources from eventually making + * forward progress in its execution. Eligibility for processing resources will + * be determined by the scheduling policy. + * + * Parameters: + * barrier - the barrier to wait on + * + * Return Value: + * 0 (OK) on success or EINVAL if the barrier is not valid. + * + * Assumptions: + * + ********************************************************************************/ + +int pthread_barrier_wait(FAR pthread_barrier_t *barrier) +{ + int semcount; + int ret = OK; + + if (!barrier) + { + return EINVAL; + } + + /* Disable pre-emption throughout the following */ + + sched_lock(); + + /* Find out how many threads are already waiting at the barrier */ + + ret = sem_getvalue(&barrier->sem, &semcount); + if (ret != OK) + { + sched_unlock(); + return EINVAL; + } + + /* If the number of waiters would be equal to the count, then we are done */ + + if (1 - semcount >= barrier->count) + { + /* Free all of the waiting threads */ + + while (semcount < 0) + { + (void)sem_post(&barrier->sem); + (void)sem_getvalue(&barrier->sem, &semcount); + } + + /* Then return PTHREAD_BARRIER_SERIAL_THREAD to the final thread */ + + sched_unlock(); + return PTHREAD_BARRIER_SERIAL_THREAD; + } + else + { + /* Otherwise, this thread must wait as well */ + + while (sem_wait(&barrier->sem) != OK) + { + /* If the thread is awakened by a signal, just continue to wait */ + + int errornumber = get_errno(); + if (errornumber != EINTR) + { + /* If it is awakened by some other error, then there is a + * problem + */ + + sched_unlock(); + return errornumber; + } + } + + /* We will only get here when we are one of the N-1 threads that were + * waiting for the final thread at the barrier. We just need to return + * zero. + */ + + sched_unlock(); + return 0; + } +} diff --git a/nuttx/sched/pthread_cancel.c b/nuttx/sched/pthread_cancel.c new file mode 100644 index 0000000000..5e34eeabac --- /dev/null +++ b/nuttx/sched/pthread_cancel.c @@ -0,0 +1,148 @@ +/************************************************************************** + * sched/pthread_cancel.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************/ + +/************************************************************************** + * Included Files + **************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "os_internal.h" +#include "pthread_internal.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ + +/************************************************************************** + * Private Types + **************************************************************************/ + +/************************************************************************** + * Private Function Prototypes + **************************************************************************/ + +/************************************************************************** + * Global Variables + **************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/************************************************************************** + * Public Functions + **************************************************************************/ + +int pthread_cancel(pthread_t thread) +{ + _TCB *tcb; + + /* First, make sure that the handle references a valid thread */ + + if (!thread) + { + /* pid == 0 is the IDLE task. Callers cannot cancel the + * IDLE task. + */ + + return ESRCH; + } + + tcb = sched_gettcb((pid_t)thread); + if (!tcb) + { + /* The pid does not correspond to any known thread */ + + return ESRCH; + } + + /* Check to see if this thread has the non-cancelable bit set in its + * flags. Suppress context changes for a bit so that the flags are stable. + * (the flags should not change in interrupt handling. + */ + + sched_lock(); + if ((tcb->flags & TCB_FLAG_NONCANCELABLE) != 0) + { + /* Then we cannot cancel the thread now. Here is how this is + * supposed to work: + * + * "When cancelability is disabled, all cancels are held pending + * in the target thread until the thread changes the cancelability. + * When cancelability is deferred, all cancels are held pending in + * the target thread until the thread changes the cancelability, calls + * a function which is a cancellation point or calls pthread_testcancel(), + * thus creating a cancellation point. When cancelability is asynchronous, + * all cancels are acted upon immediately, interrupting the thread with its + * processing." + */ + + tcb->flags |= TCB_FLAG_CANCEL_PENDING; + sched_unlock(); + return OK; + } + + sched_unlock(); + + /* Check to see if the ID refers to ourselves.. this would be the + * same as pthread_exit(PTHREAD_CANCELED). + */ + + if (tcb == (_TCB*)g_readytorun.head) + { + pthread_exit(PTHREAD_CANCELED); + } + + /* Complete pending join operations */ + + (void)pthread_completejoin((pid_t)thread, PTHREAD_CANCELED); + + /* Then let pthread_delete do the real work */ + + task_delete((pid_t)thread); + return OK; +} + + diff --git a/nuttx/sched/pthread_completejoin.c b/nuttx/sched/pthread_completejoin.c new file mode 100644 index 0000000000..7c5191034b --- /dev/null +++ b/nuttx/sched/pthread_completejoin.c @@ -0,0 +1,231 @@ +/************************************************************************ + * sched/pthread_completejoin.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "pthread_internal.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_notifywaiters + * + * Description: + * Notify all other threads waiting in phread join for this thread's + * exit data. This must be done by the child at child thread + * destruction time. + * + ************************************************************************/ + +static bool pthread_notifywaiters(FAR join_t *pjoin) +{ + int ntasks_waiting; + int status; + + svdbg("pjoin=0x%p\n", pjoin); + + /* Are any tasks waiting for our exit value? */ + + status = sem_getvalue(&pjoin->exit_sem, &ntasks_waiting); + if (status == OK && ntasks_waiting < 0) + { + /* Set the data semaphore so that this thread will be + * awakened when all waiting tasks receive the data + */ + + (void)sem_init(&pjoin->data_sem, 0, (ntasks_waiting+1)); + + /* Post the semaphore to restart each thread that is waiting + * on the semaphore + */ + + do + { + status = pthread_givesemaphore(&pjoin->exit_sem); + if (status == OK) + { + status = sem_getvalue(&pjoin->exit_sem, &ntasks_waiting); + } + } + while (ntasks_waiting < 0 && status == OK); + + /* Now wait for all these restarted tasks to obtain the return + * value. + */ + + (void)pthread_takesemaphore(&pjoin->data_sem); + return true; + } + + return false; +} + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_completejoin + * + * Description: + * A thread has been terminated -- either by returning, calling + * pthread_exit(), or through pthread_cancel(). In any event, we must + * complete any pending join events. + * + * Parameters: + * exit_value + * + * Returned Value: + * OK unless there is no join information associated with the pid. + * This could happen, for example, if a task started with task_create() + * calls pthread_exit(). + * + * Assumptions: + * + ************************************************************************/ + +int pthread_completejoin(pid_t pid, FAR void *exit_value) +{ + FAR join_t *pjoin; + + svdbg("pid=%d exit_value=%p\n", pid, exit_value); + + /* First, find thread's structure in the private data set. */ + + (void)pthread_takesemaphore(&g_join_semaphore); + pjoin = pthread_findjoininfo(pid); + if (!pjoin) + { + sdbg("Could not find join info, pid=%d\n", pid); + (void)pthread_givesemaphore(&g_join_semaphore); + return ERROR; + } + else + { + bool waiters; + + /* Save the return exit value in the thread structure. */ + + pjoin->terminated = true; + pjoin->exit_value = exit_value; + + /* Notify waiters of the availability of the exit value */ + + waiters = pthread_notifywaiters(pjoin); + + /* If there are no waiters and if the thread is marked as detached. + * then discard the join information now. Otherwise, the pthread + * join logic will call pthread_destroyjoin() when all of the threads + * have sampled the exit value. + */ + + if (!waiters && pjoin->detached) + { + pthread_destroyjoin(pjoin); + } + + /* Giving the following semaphore will allow the waiters + * to call pthread_destroyjoin. + */ + + (void)pthread_givesemaphore(&g_join_semaphore); + } + + return OK; +} + +/************************************************************************ + * Name: pthread_destroyjoin + * + * Description: + * This is called from pthread_completejoin if the join info was + * detached or from pthread_join when the last waiting thread has + * received the thread exit info. + * + * Or it may never be called if the join info was never detached or if + * no thread ever calls pthread_join. In case, there is a memory leak! + * + * Assumptions: + * The caller holds g_join_semaphore + * + ************************************************************************/ + +void pthread_destroyjoin(FAR join_t *pjoin) +{ + sdbg("pjoin=0x%p\n", pjoin); + + /* Remove the join info from the set of joins */ + + (void)pthread_removejoininfo((pid_t)pjoin->thread); + + /* Destroy its semaphores */ + + (void)sem_destroy(&pjoin->data_sem); + (void)sem_destroy(&pjoin->exit_sem); + + /* And deallocate the pjoin structure */ + + sched_free(pjoin); +} + diff --git a/nuttx/sched/pthread_condbroadcast.c b/nuttx/sched/pthread_condbroadcast.c new file mode 100644 index 0000000000..05f4bb483b --- /dev/null +++ b/nuttx/sched/pthread_condbroadcast.c @@ -0,0 +1,145 @@ +/**************************************************************************** + * sched/pthread_condbroadcast.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_cond_broadcast + * + * Description: + * A thread broadcast on a condition variable. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_cond_broadcast(FAR pthread_cond_t *cond) +{ + int ret = OK; + int sval; + + sdbg("cond=0x%p\n", cond); + + if (!cond) + { + ret = EINVAL; + } + else + { + /* Disable pre-emption until all of the waiting threads have been + * restarted. This is necessary to assure that the sval behaves as + * expected in the following while loop + */ + + sched_lock(); + + /* Get the current value of the semaphore */ + + if (sem_getvalue((sem_t*)&cond->sem, &sval) != OK) + { + ret = EINVAL; + } + else + { + /* Loop until all of the waiting threads have been restarted. */ + + while (sval < 0) + { + /* If the value is less than zero (meaning that one or more + * thread is waiting), then post the condition semaphore. + * Only the highest priority waiting thread will get to execute + */ + + ret = pthread_givesemaphore((sem_t*)&cond->sem); + + /* Increment the semaphore count (as was done by the + * above post). + */ + + sval++; + } + } + + /* Now we can let the restarted threads run */ + + sched_unlock(); + } + + sdbg("Returning %d\n", ret); + return ret; +} + + diff --git a/nuttx/sched/pthread_conddestroy.c b/nuttx/sched/pthread_conddestroy.c new file mode 100644 index 0000000000..11292e6393 --- /dev/null +++ b/nuttx/sched/pthread_conddestroy.c @@ -0,0 +1,88 @@ +/**************************************************************************** + * sched/pthread_conddestroy.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include "pthread_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_cond_destroy + * + * Description: + * A thread can delete condition variables. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_cond_destroy(FAR pthread_cond_t *cond) +{ + int ret = OK; + + sdbg("cond=0x%p\n", cond); + + if (!cond) + { + ret = EINVAL; + } + + /* Destroy the semaphore contained in the structure */ + + else if (sem_destroy((sem_t*)&cond->sem) != OK) + { + ret = EINVAL; + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/sched/pthread_condinit.c b/nuttx/sched/pthread_condinit.c new file mode 100644 index 0000000000..e49bb86588 --- /dev/null +++ b/nuttx/sched/pthread_condinit.c @@ -0,0 +1,93 @@ +/**************************************************************************** + * sched/pthread_condinit.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_cond_init + * + * Description: + * A thread can create condition variables. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_cond_init(FAR pthread_cond_t *cond, FAR pthread_condattr_t *attr) +{ + int ret = OK; + + sdbg("cond=0x%p attr=0x%p\n", cond, attr); + + if (!cond) + { + ret = EINVAL; + } + + /* Initialize the semaphore contained in the condition structure + * with initial count = 0 + */ + + else if (sem_init((sem_t*)&cond->sem, 0, 0) != OK) + { + ret = EINVAL; + } + + sdbg("Returning %d\n", ret); + return ret; +} + + + diff --git a/nuttx/sched/pthread_condsignal.c b/nuttx/sched/pthread_condsignal.c new file mode 100644 index 0000000000..48ff4cf20e --- /dev/null +++ b/nuttx/sched/pthread_condsignal.c @@ -0,0 +1,137 @@ +/**************************************************************************** + * sched/pthread_condsignal.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_cond_signal + * + * Description: + * A thread can signal on a condition variable. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_cond_signal(FAR pthread_cond_t *cond) +{ + int ret = OK; + int sval; + + sdbg("cond=0x%p\n", cond); + + if (!cond) + { + ret = EINVAL; + } + else + { + /* Get the current value of the semaphore */ + + if (sem_getvalue((sem_t*)&cond->sem, &sval) != OK) + { + ret = EINVAL; + } + + /* If the value is less than zero (meaning that one or more + * thread is waiting), then post the condition semaphore. + * Only the highest priority waiting thread will get to execute + */ + + else + { + /* One of my objectives in this design was to make pthread_cond_signal + * usable from interrupt handlers. However, from interrupt handlers, + * you cannot take the associated mutex before signaling the condition. + * As a result, I think that there could be a race condition with + * the following logic which assumes that the if sval < 0 then the + * thread is waiting. Without the mutex, there is no atomic, protected + * operation that will guarantee this to be so. + */ + + sdbg("sval=%d\n", sval); + if (sval < 0) + { + sdbg("Signalling...\n"); + ret = pthread_givesemaphore((sem_t*)&cond->sem); + } + } + } + + sdbg("Returning %d\n", ret); + return ret; +} + + diff --git a/nuttx/sched/pthread_condtimedwait.c b/nuttx/sched/pthread_condtimedwait.c new file mode 100644 index 0000000000..25f86d813e --- /dev/null +++ b/nuttx/sched/pthread_condtimedwait.c @@ -0,0 +1,308 @@ +/**************************************************************************** + * sched/pthread_condtimedwait.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "pthread_internal.h" +#include "clock_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_condtimedout + * + * Description: + * This function is called if the timeout elapses before + * the condition is signaled. + * + * Parameters: + * argc - the number of arguments (should be 2) + * pid - the task ID of the task to wakeup + * signo - The signal to use to wake up the task + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void pthread_condtimedout(int argc, uint32_t pid, uint32_t signo) +{ +#ifdef CONFIG_CAN_PASS_STRUCTS + union sigval value; + + /* Send the specified signal to the specified task. */ + + value.sival_ptr = NULL; + (void)sigqueue((int)pid, (int)signo, value); +#else + (void)sigqueue((int)pid, (int)signo, NULL); +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_cond_timedwait + * + * Description: + * A thread can perform a timed wait on a condition variable. + * + * Parameters: + * cond - the condition variable to wait on + * mutex - the mutex that protects the condition variable + * abstime - wait until this absolute time + * + * Return Value: + * OK (0) on success; ERROR (-1) on failure with errno + * set appropriately. + * + * Assumptions: + * Timing is of resolution 1 msec, with +/-1 millisecond + * accuracy. + * + ****************************************************************************/ + +int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex, + FAR const struct timespec *abstime) +{ + WDOG_ID wdog; + int ticks; + int mypid = (int)getpid(); + irqstate_t int_state; + int ret = OK; + int status; + + sdbg("cond=0x%p mutex=0x%p abstime=0x%p\n", cond, mutex, abstime); + + /* Make sure that non-NULL references were provided. */ + + if (!cond || !mutex) + { + ret = EINVAL; + } + + /* Make sure that the caller holds the mutex */ + + else if (mutex->pid != mypid) + { + ret = EPERM; + } + + /* If no wait time is provided, this function degenerates to + * the same behavior as pthread_cond_wait(). + */ + + else if (!abstime) + { + ret = pthread_cond_wait(cond, mutex); + } + + else + { + /* Create a watchdog */ + + wdog = wd_create(); + if (!wdog) + { + ret = EINVAL; + } + else + { + sdbg("Give up mutex...\n"); + + /* We must disable pre-emption and interrupts here so that + * the time stays valid until the wait begins. This adds + * complexity because we assure that interrupts and + * pre-emption are re-enabled correctly. + */ + + sched_lock(); + int_state = irqsave(); + + /* Convert the timespec to clock ticks. We must disable pre-emption + * here so that this time stays valid until the wait begins. + */ + + ret = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); + if (ret) + { + /* Restore interrupts (pre-emption will be enabled when + * we fall through the if/then/else + */ + + irqrestore(int_state); + } + else + { + /* Check the absolute time to wait. If it is now or in the past, then + * just return with the timedout condition. + */ + + if (ticks <= 0) + { + /* Restore interrupts and indicate that we have already timed out. + * (pre-emption will be enabled when we fall through the + * if/then/else + */ + + irqrestore(int_state); + ret = ETIMEDOUT; + } + else + { + /* Give up the mutex */ + + mutex->pid = 0; + ret = pthread_givesemaphore((sem_t*)&mutex->sem); + if (ret) + { + /* Restore interrupts (pre-emption will be enabled when + * we fall through the if/then/else) + */ + + irqrestore(int_state); + } + else + { + /* Start the watchdog */ + + wd_start(wdog, ticks, (wdentry_t)pthread_condtimedout, + 2, (uint32_t)mypid, (uint32_t)SIGCONDTIMEDOUT); + + /* Take the condition semaphore. Do not restore interrupts + * until we return from the wait. This is necessary to + * make sure that the watchdog timer and the condition wait + * are started atomically. + */ + + status = sem_wait((sem_t*)&cond->sem); + + /* Did we get the condition semaphore. */ + + if (status != OK) + { + /* NO.. Handle the special case where the semaphore wait was + * awakened by the receipt of a signal -- presumably the + * signal posted by pthread_condtimedout(). + */ + + if (get_errno() == EINTR) + { + sdbg("Timedout!\n"); + ret = ETIMEDOUT; + } + else + { + ret = EINVAL; + } + } + + /* The interrupts stay disabled until after we sample the errno. + * This is because when debug is enabled and the console is used + * for debug output, then the errno can be altered by interrupt + * handling! (bad) + */ + + irqrestore(int_state); + } + + /* Reacquire the mutex (retaining the ret). */ + + sdbg("Re-locking...\n"); + status = pthread_takesemaphore((sem_t*)&mutex->sem); + if (!status) + { + mutex->pid = mypid; + } + else if (!ret) + { + ret = status; + } + } + + /* Re-enable pre-emption (It is expected that interrupts + * have already been re-enabled in the above logic) + */ + + sched_unlock(); + } + + /* We no longer need the watchdog */ + + wd_delete(wdog); + } + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/sched/pthread_condwait.c b/nuttx/sched/pthread_condwait.c new file mode 100644 index 0000000000..bf0164d2d6 --- /dev/null +++ b/nuttx/sched/pthread_condwait.c @@ -0,0 +1,137 @@ +/**************************************************************************** + * sched/pthread_condwait.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: int pthread_cond_wait + * + * Description: + * A thread can wait for a condition variable to be signalled or broadcast. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex) +{ + int ret; + + sdbg("cond=0x%p mutex=0x%p\n", cond, mutex); + + /* Make sure that non-NULL references were provided. */ + + if (!cond || !mutex) + { + ret = EINVAL; + } + + /* Make sure that the caller holds the mutex */ + + else if (mutex->pid != (int)getpid()) + { + ret = EPERM; + } + else + { + /* Give up the mutex */ + + sdbg("Give up mutex / take cond\n"); + + sched_lock(); + mutex->pid = 0; + ret = pthread_givesemaphore((sem_t*)&mutex->sem); + + /* Take the semaphore */ + + ret |= pthread_takesemaphore((sem_t*)&cond->sem); + sched_unlock(); + + /* Reacquire the mutex */ + + sdbg("Reacquire mutex...\n"); + ret |= pthread_takesemaphore((sem_t*)&mutex->sem); + if (!ret) + { + mutex->pid = getpid();; + } + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/sched/pthread_create.c b/nuttx/sched/pthread_create.c new file mode 100644 index 0000000000..5fdf3b88d8 --- /dev/null +++ b/nuttx/sched/pthread_create.c @@ -0,0 +1,435 @@ +/**************************************************************************** + * sched/pthread_create.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "os_internal.h" +#include "clock_internal.h" +#include "env_internal.h" +#include "pthread_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* Default pthread attributes */ + +pthread_attr_t g_default_pthread_attr = PTHREAD_ATTR_INITIALIZER; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/* This is the name for name-less pthreads */ + +static const char g_pthreadname[] = ""; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_argsetup + * + * Description: + * This functions sets up parameters in the Task Control Block (TCB) in + * preparation for starting a new thread. + * + * pthread_argsetup() is called from task_init() and task_start() to create + * a new task (with arguments cloned via strdup) or pthread_create() which + * has one argument passed by value (distinguished by the pthread boolean + * argument). + * + * Input Parameters: + * tcb - Address of the new task's TCB + * name - Name of the new task (not used) + * argv - A pointer to an array of input parameters. Up to + * CONFIG_MAX_TASK_ARG parameters may be provided. If fewer + * than CONFIG_MAX_TASK_ARG parameters are passed, the list + * should be terminated with a NULL argv[] value. If no + * parameters are required, argv may be NULL. + * + * Return Value: + * None + * + ****************************************************************************/ + +static void pthread_argsetup(FAR _TCB *tcb, pthread_addr_t arg) +{ + int i; + +#if CONFIG_TASK_NAME_SIZE > 0 + /* Copy the pthread name into the TCB */ + + strncpy(tcb->name, g_pthreadname, CONFIG_TASK_NAME_SIZE); + + /* Save the name as the first argument in the TCB */ + + tcb->argv[0] = tcb->name; +#else + /* Save the name as the first argument in the TCB */ + + tcb->argv[0] = (char *)g_pthreadname; +#endif /* CONFIG_TASK_NAME_SIZE */ + + /* For pthreads, args are strictly pass-by-value; that actual + * type wrapped by pthread_addr_t is unknown. + */ + + tcb->argv[1] = (char*)arg; + + /* Nullify the remaining, unused argument storage */ + + for (i = 2; i < CONFIG_MAX_TASK_ARGS+1; i++) + { + tcb->argv[i] = NULL; + } +} + +/**************************************************************************** + * Name: pthread_addjoininfo + * + * Description: + * Add a join_t to the local data set. + * + * Parameters: + * pjoin + * + * Return Value: + * None + * + * Assumptions: + * The caller has provided protection from re-entrancy. + * + ****************************************************************************/ + +static void pthread_addjoininfo(FAR join_t *pjoin) +{ + pjoin->next = NULL; + if (!g_pthread_tail) + { + g_pthread_head = pjoin; + } + else + { + g_pthread_tail->next = pjoin; + } + + g_pthread_tail = pjoin; +} + +/**************************************************************************** + * Name: pthread_start + * + * Description: + * This function is the low level entry point into the + * pthread + * + * Parameters: + * None + * + ****************************************************************************/ + +static void pthread_start(void) +{ + FAR _TCB *ptcb = (FAR _TCB*)g_readytorun.head; + FAR join_t *pjoin = (FAR join_t*)ptcb->joininfo; + pthread_addr_t exit_status; + + /* Sucessfully spawned, add the pjoin to our data set. + * Don't re-enable pre-emption until this is done. + */ + + (void)pthread_takesemaphore(&g_join_semaphore); + pthread_addjoininfo(pjoin); + (void)pthread_givesemaphore(&g_join_semaphore); + + /* Report to the spawner that we successfully started. */ + + pjoin->started = true; + (void)pthread_givesemaphore(&pjoin->data_sem); + + /* Pass control to the thread entry point. The argument is + * argv[1]. argv[0] (the thread name) and argv[2-4] are not made + * available to the pthread. + */ + + exit_status = (*ptcb->entry.pthread)((pthread_addr_t)ptcb->argv[1]); + + /* The thread has returned */ + + pthread_exit(exit_status); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_create + * + * Description: + * This function creates and activates a new thread with a specified + * attributes. + * + * Input Parameters: + * thread + * attr + * start_routine + * arg + * + * Returned value: + * OK (0) on success; a (non-negated) errno value on failure. The errno + * variable is not set. + * + ****************************************************************************/ + +int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr, + pthread_startroutine_t start_routine, pthread_addr_t arg) +{ + FAR _TCB *ptcb; + FAR join_t *pjoin; + int status; + int priority; +#if CONFIG_RR_INTERVAL > 0 + int policy; +#endif + pid_t pid; + + /* If attributes were not supplied, use the default attributes */ + + if (!attr) + { + attr = &g_default_pthread_attr; + } + + /* Allocate a TCB for the new task. */ + + ptcb = (FAR _TCB*)kzalloc(sizeof(_TCB)); + if (!ptcb) + { + return ENOMEM; + } + + /* Associate file descriptors with the new task */ + + status = sched_setuppthreadfiles(ptcb); + if (status != OK) + { + sched_releasetcb(ptcb); + return status; + } + + /* Share the parent's envionment */ + + (void)env_share(ptcb); + + /* Allocate a detachable structure to support pthread_join logic */ + + pjoin = (FAR join_t*)kzalloc(sizeof(join_t)); + if (!pjoin) + { + sched_releasetcb(ptcb); + return ENOMEM; + } + + /* Allocate the stack for the TCB */ + + status = up_create_stack(ptcb, attr->stacksize); + if (status != OK) + { + sched_releasetcb(ptcb); + sched_free(pjoin); + return ENOMEM; + } + + /* Should we use the priority and scheduler specified in the + * pthread attributes? Or should we use the current thread's + * priority and scheduler? + */ + + if (attr->inheritsched == PTHREAD_INHERIT_SCHED) + { + /* Get the priority for this thread. */ + + struct sched_param param; + status = sched_getparam(0, ¶m); + if (status == OK) + { + priority = param.sched_priority; + } + else + { + priority = SCHED_FIFO; + } + + /* Get the scheduler policy for this thread */ + +#if CONFIG_RR_INTERVAL > 0 + policy = sched_getscheduler(0); + if (policy == ERROR) + { + policy = SCHED_FIFO; + } +#endif + } + else + { + /* Use the priority and scheduler from the attributes */ + + priority = attr->priority; +#if CONFIG_RR_INTERVAL > 0 + policy = attr->policy; +#endif + } + + /* Mark this task as a pthread (this setting will be needed in + * task_schedsetup() when up_initial_state() is called. + */ + + ptcb->flags |= TCB_FLAG_TTYPE_PTHREAD; + + /* Initialize the task control block */ + + status = task_schedsetup(ptcb, priority, pthread_start, + (main_t)start_routine); + if (status != OK) + { + + sched_releasetcb(ptcb); + sched_free(pjoin); + return EBUSY; + } + + /* Configure the TCB for a pthread receiving on parameter + * passed by value + */ + + pthread_argsetup(ptcb, arg); + + /* Attach the join info to the TCB. */ + + ptcb->joininfo = (void*)pjoin; + + /* If round robin scheduling is selected, set the appropriate flag + * in the TCB. + */ + +#if CONFIG_RR_INTERVAL > 0 + if (policy == SCHED_RR) + { + ptcb->flags |= TCB_FLAG_ROUND_ROBIN; + ptcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; + } +#endif + + /* Get the assigned pid before we start the task (who knows what + * could happen to ptcb after this!). Copy this ID into the join structure + * as well. + */ + + pid = (int)ptcb->pid; + pjoin->thread = (pthread_t)pid; + + /* Initialize the semaphores in the join structure to zero. */ + + status = sem_init(&pjoin->data_sem, 0, 0); + if (status == OK) + { + status = sem_init(&pjoin->exit_sem, 0, 0); + } + + /* Activate the task */ + + sched_lock(); + if (status == OK) + { + status = task_activate(ptcb); + } + + if (status == OK) + { + /* Wait for the task to actually get running and to register + * its join_t + */ + + (void)pthread_takesemaphore(&pjoin->data_sem); + + /* Return the thread information to the caller */ + + if (thread) *thread = (pthread_t)pid; + if (!pjoin->started) status = ERROR; + + sched_unlock(); + (void)sem_destroy(&pjoin->data_sem); + } + else + { + sched_unlock(); + dq_rem((FAR dq_entry_t*)ptcb, (dq_queue_t*)&g_inactivetasks); + (void)sem_destroy(&pjoin->data_sem); + (void)sem_destroy(&pjoin->exit_sem); + sched_releasetcb(ptcb); + sched_free(pjoin); + return EIO; + } + + return OK; +} diff --git a/nuttx/sched/pthread_detach.c b/nuttx/sched/pthread_detach.c new file mode 100644 index 0000000000..a959d94b36 --- /dev/null +++ b/nuttx/sched/pthread_detach.c @@ -0,0 +1,137 @@ +/************************************************************************ + * sched/pthread_detach.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "pthread_internal.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_detach + * + * Description: + * A thread object may be "detached" to specify that the return value + * and completion status will not be requested. + * + * Parameters: + * thread + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ************************************************************************/ + +int pthread_detach(pthread_t thread) +{ + FAR join_t *pjoin; + int ret; + + sdbg("Thread=%d\n", thread); + + /* Find the entry associated with this pthread. */ + + (void)pthread_takesemaphore(&g_join_semaphore); + pjoin = pthread_findjoininfo((pid_t)thread); + if (!pjoin) + { + sdbg("Could not find thread entry\n"); + ret = EINVAL; + } + else + { + /* Has the thread already terminated? */ + + if (pjoin->terminated) + { + /* YES.. just remove the thread entry. */ + + pthread_destroyjoin(pjoin); + } + else + { + /* NO.. Just mark the thread as detached. It + * will be removed and deallocated when the + * thread exits + */ + + pjoin->detached = true; + } + + /* Either case is successful */ + + ret = OK; + } + + (void)pthread_givesemaphore(&g_join_semaphore); + + sdbg("Returning %d\n", ret); + return ret; +} diff --git a/nuttx/sched/pthread_exit.c b/nuttx/sched/pthread_exit.c new file mode 100644 index 0000000000..db51be78f7 --- /dev/null +++ b/nuttx/sched/pthread_exit.c @@ -0,0 +1,137 @@ +/************************************************************************ + * sched/pthread_exit.c + * + * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "pthread_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_exit + * + * Description: + * Terminate execution of a thread started with pthread_create. + * + * Parameters: + * exit_valie + * + * Returned Value: + * None + * + * Assumptions: + * + ************************************************************************/ + +void pthread_exit(FAR void *exit_value) +{ + int error_code = (int)((intptr_t)exit_value); + int status; + + sdbg("exit_value=%p\n", exit_value); + + /* Block any signal actions that would awaken us while were + * are performing the JOIN handshake. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + { + sigset_t set = ALL_SIGNAL_SET; + (void)sigprocmask(SIG_SETMASK, &set, NULL); + } +#endif + + /* Complete pending join operations */ + + status = pthread_completejoin(getpid(), exit_value); + if (status != OK) + { + /* Assume that the join completion failured because this + * not really a pthread. Exit by calling exit() to flush + * and close all file descriptors and calling atexit() + * functions. + */ + + if (error_code == EXIT_SUCCESS) + { + error_code = EXIT_FAILURE; + } + + exit(error_code); + } + + /* Then just exit, retaining all file descriptors and without + * calling atexit() functions. + */ + + _exit(error_code); +} + diff --git a/nuttx/sched/pthread_findjoininfo.c b/nuttx/sched/pthread_findjoininfo.c new file mode 100644 index 0000000000..584ed8f967 --- /dev/null +++ b/nuttx/sched/pthread_findjoininfo.c @@ -0,0 +1,101 @@ +/************************************************************************ + * pthread_findjoininfo.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +#include "pthread_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: thread_findjoininfo + * + * Description: + * Find a join_t to the local data set. + * + * Parameters: + * pid + * + * Return Value: + * None or pointer to the found entry. + * + * Assumptions: + * The caller has provided protection from re-entrancy. + * + ************************************************************************/ + +FAR join_t *pthread_findjoininfo(pid_t pid) +{ + FAR join_t *pjoin; + + /* Find the entry with the matching pid */ + + for (pjoin = g_pthread_head; + (pjoin && (pid_t)pjoin->thread != pid); + pjoin = pjoin->next); + + /* and return it */ + + return pjoin; +} + diff --git a/nuttx/sched/pthread_getschedparam.c b/nuttx/sched/pthread_getschedparam.c new file mode 100644 index 0000000000..c376fd4008 --- /dev/null +++ b/nuttx/sched/pthread_getschedparam.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * pthread_getschedparam.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + *****************************************************************************/ + +/**************************************************************************** + * Name: pthread_getschedparam + * + * Description: + * The pthread_getschedparam() functions will get the scheduling policy and + * parameters of threads. For SCHED_FIFO and SCHED_RR, the only required + * member of the sched_param structure is the priority sched_priority. + * + * The pthread_getschedparam() function will retrieve the scheduling + * policy and scheduling parameters for the thread whose thread ID is + * given by 'thread' and will store those values in 'policy' and 'param', + * respectively. The priority value returned from pthread_getschedparam() + * will be the value specified by the most recent pthread_setschedparam(), + * pthread_setschedprio(), or pthread_create() call affecting the target + * thread. It will not reflect any temporary adjustments to its priority + * (such as might result of any priority inheritance, for example). + * + * The policy parameter may have the value SCHED_FIFO, or SCHED_RR + * (SCHED_OTHER and SCHED_SPORADIC, in particular, are not supported). + * The SCHED_FIFO and SCHED_RR policies will have a single scheduling + * parameter, sched_priority. +* + * Parameters: + * thread - The ID of thread whose scheduling parameters will be queried. + * policy - The location to store the thread's scheduling policy. + * param - The location to store the thread's priority. + * + * Return Value: + * 0 if successful. Otherwise, the error code ESRCH if the value specified + * by thread does not refer to an existing thread. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_getschedparam(pthread_t thread, FAR int *policy, + FAR struct sched_param *param) +{ + int ret; + + sdbg("Thread ID=%d policy=0x%p param=0x%p\n", thread, policy, param); + + if (!policy || !param) + { + ret = EINVAL; + } + else + { + /* Get the schedparams of the thread. */ + + ret = sched_getparam((pid_t)thread, param); + if (ret != OK) + { + ret = EINVAL; + } + + /* Return the policy. */ + + *policy = sched_getscheduler((pid_t)thread); + if (*policy == ERROR) + { + ret = get_errno(); + } + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/sched/pthread_getspecific.c b/nuttx/sched/pthread_getspecific.c new file mode 100644 index 0000000000..eeead14fab --- /dev/null +++ b/nuttx/sched/pthread_getspecific.c @@ -0,0 +1,123 @@ +/************************************************************************ + * sched/pthread_getspecific.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#include "pthread_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_getspecific + * + * Description: + * The pthread_getspecific() function returns the value currently + * bound to the specified key on behalf of the calling thread. + * + * The effect of calling pthread_getspecific() with with a key value + * not obtained from pthread_create() or after a key has been deleted + * with pthread_key_delete() is undefined. + * + * Parameters: + * key = The data key to get or set + * + * Return Value: + * The function pthread_getspecific() returns the thread-specific data + * associated with the given key. If no thread specific data is + * associated with the key, then the value NULL is returned. + * + * EINVAL - The key value is invalid. + * + * Assumptions: + * + * POSIX Compatibility: + * - Both calling pthread_setspecific() and pthread_getspecific() + * may be called from a thread-specific data destructor + * function. + * + ************************************************************************/ + +FAR void *pthread_getspecific(pthread_key_t key) +{ +#if CONFIG_NPTHREAD_KEYS > 0 + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR void *ret = NULL; + + /* Check if the key is valid. */ + + if (key < g_pthread_num_keys) + { + /* Return the stored value. */ + + ret = rtcb->pthread_data[key]; + } + + return ret; +#else + return NULL; +#endif +} + diff --git a/nuttx/sched/pthread_initialize.c b/nuttx/sched/pthread_initialize.c new file mode 100644 index 0000000000..09db1d50ec --- /dev/null +++ b/nuttx/sched/pthread_initialize.c @@ -0,0 +1,198 @@ +/**************************************************************************** + * sched/pthread_initialize.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* This is the head of a private singly linked list. It + * is used to retain information about the spawned threads. + */ + +FAR join_t *g_pthread_head = NULL; +FAR join_t *g_pthread_tail = NULL; + +/* Mutually exclusive access to this data set is enforced with + * the following (un-named) semaphore. + */ + +sem_t g_join_semaphore; + +/* This keys track of the number of global keys that have been + * allocated. + */ + +uint8_t g_pthread_num_keys; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_initialize + * + * Description: + * This is an internal OS function called only at power-up boot time. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void pthread_initialize(void) +{ + /* Initialize some global variables */ + + g_pthread_head = NULL; + g_pthread_tail = NULL; + g_pthread_num_keys = 0; + + /* Initialize the join semaphore to one (to support one-at- + * a-time access to private data sets). + */ + + (void)sem_init(&g_join_semaphore, 0, 1); +} + +/**************************************************************************** + * Name: pthread_takesemaphore and pthread_givesemaphore + * + * Description: + * Support managed access to the private data sets. + * + * Parameters: + * None + * + * Return Value: + * 0 on success or an ERROR on failure with errno value set to EINVAL. + * Note that the errno EINTR is never returned by this function. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_takesemaphore(sem_t *sem) +{ + /* Verify input parameters */ + + if (sem) + { + /* Take the semaphore */ + + while (sem_wait(sem) != OK) + { + /* Handle the special case where the semaphore wait was + * awakened by the receipt of a signal. + */ + + if (get_errno() != EINTR) + { + set_errno(EINVAL); + return ERROR; + } + } + return OK; + } + else + { + /* NULL semaphore pointer! */ + + set_errno(EINVAL); + return ERROR; + } +} + +int pthread_givesemaphore(sem_t *sem) +{ + /* Verify input parameters */ + + if (sem) + { + /* Give the semaphore */ + + if (sem_post(sem) == OK) + { + return OK; + } + else + { + /* sem_post() reported an error */ + + set_errno(EINVAL); + return ERROR; + } + } + else + { + /* NULL semaphore pointer! */ + + set_errno(EINVAL); + return ERROR; + } +} + diff --git a/nuttx/sched/pthread_internal.h b/nuttx/sched/pthread_internal.h new file mode 100644 index 0000000000..ca70ab291b --- /dev/null +++ b/nuttx/sched/pthread_internal.h @@ -0,0 +1,133 @@ +/**************************************************************************** + * sched/pthread_internal.h + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __SCHED_PTHREAD_INTERNAL_H +#define __SCHED_PTHREAD_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Declarations + ****************************************************************************/ + +/* The following defines an entry in the pthread logic's local data set. + * Note that this structure is used to implemented a singly linked list. + * This structure is used (instead of, say, a binary search tree) because + * the data set will be searched using the pid as a key -- a process IDs will + * always be created in a montonically increasing fashion. + */ + +struct join_s +{ + FAR struct join_s *next; /* Implements link list */ + uint8_t crefs; /* Reference count */ + bool started; /* true: pthread started. */ + bool detached; /* true: pthread_detached'ed */ + bool terminated; /* true: detach'ed+exit'ed */ + pthread_t thread; /* Includes pid */ + sem_t exit_sem; /* Implements join */ + sem_t data_sem; /* Implements join */ + pthread_addr_t exit_value; /* Returned data */ + +}; + +typedef struct join_s join_t; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* This is the head of a private singly linked list. It is used to retain + * information about the spawned threads. + */ + +extern FAR join_t *g_pthread_head; +extern FAR join_t *g_pthread_tail; + +/* Mutually exclusive access to this data set is enforced with the following + * (un-named) semaphore. + */ + +extern sem_t g_join_semaphore; + +/* This keys track of the number of global keys that have been allocated. */ + +extern uint8_t g_pthread_num_keys; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN void weak_function pthread_initialize(void); +EXTERN int pthread_completejoin(pid_t pid, FAR void *exit_value); +EXTERN void pthread_destroyjoin(FAR join_t *pjoin); +EXTERN FAR join_t *pthread_findjoininfo(pid_t pid); +EXTERN int pthread_givesemaphore(sem_t *sem); +EXTERN FAR join_t *pthread_removejoininfo(pid_t pid); +EXTERN int pthread_takesemaphore(sem_t *sem); + +#ifdef CONFIG_MUTEX_TYPES +EXTERN int pthread_mutexattr_verifytype(int type); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __SCHED_PTHREAD_INTERNAL_H */ + diff --git a/nuttx/sched/pthread_join.c b/nuttx/sched/pthread_join.c new file mode 100644 index 0000000000..6a02af352e --- /dev/null +++ b/nuttx/sched/pthread_join.c @@ -0,0 +1,248 @@ +/**************************************************************************** + * pthread_join.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_join + * + * Description: + * A thread can await termination of another thread and retrieve the + * return value of the thread. + * + * Parameters: + * thread + * pexit_value + * + * Return Value: + * 0 if successful. Otherwise, one of the following error codes: + * + * EINVAL The value specified by thread does not refer to ajoinable + * thread. + * ESRCH No thread could be found corresponding to thatspecified by the + * given thread ID. + * EDEADLK A deadlock was detected or the value of thread specifies the + * calling thread. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value) +{ + FAR join_t *pjoin; + int ret; + + sdbg("thread=%d\n", thread); + + /* First make sure that this is not an attempt to join to + * ourself. + */ + + if ((pid_t)thread == getpid()) + { + return EDEADLK; + } + + /* Make sure no other task is mucking with the data structures + * while we are performing the following operations. NOTE: + * we can be also sure that pthread_exit() will not execute + * because it will also attempt to get this semaphore. + */ + + (void)pthread_takesemaphore(&g_join_semaphore); + + /* Find the join information associated with this thread. + * This can fail for one of three reasons: (1) There is no + * thread associated with 'thread,' (2) the thread is a task + * and does not have join information, or (3) the thread + * was detached and has exitted. + */ + + pjoin = pthread_findjoininfo((pid_t)thread); + if (!pjoin) + { + /* Determine what kind of error to return */ + + FAR _TCB *tcb = sched_gettcb((pthread_t)thread); + + sdbg("Could not find thread data\n"); + + /* Case (1) or (3) -- we can't tell which. Assume (3) */ + + if (!tcb) + { + ret = ESRCH; + } + + /* The thread is still active but has no join info. In that + * case, it must be a task and not a pthread. + */ + + else + { + ret = EINVAL; + } + + (void)pthread_givesemaphore(&g_join_semaphore); + } + else + { + /* We found the join info structure. Increment for the reference + * to the join structure that we have. This will keep things + * stable for we have to do + */ + + sched_lock(); + pjoin->crefs++; + + /* Check if the thread is still running. If not, then things are + * simpler. There are still race conditions to be concerned with. + * For example, there could be multiple threads executing in the + * 'else' block below when we enter! + */ + + if (pjoin->terminated) + { + sdbg("Thread has terminated\n"); + + /* Get the thread exit value from the terminated thread. */ + + if (pexit_value) + { + sdbg("exit_value=0x%p\n", pjoin->exit_value); + *pexit_value = pjoin->exit_value; + } + } + else + { + sdbg("Thread is still running\n"); + + /* Relinquish the data set semaphore. Since pre-emption is + * disabled, we can be certain that no task has the + * opportunity to run between the time we relinquish the + * join semaphore and the time that we wait on the thread exit + * semaphore. + */ + + (void)pthread_givesemaphore(&g_join_semaphore); + + /* Take the thread's thread exit semaphore. We will sleep here + * until the thread exits. We need to exercise caution because + * there could be multiple threads waiting here for the same + * pthread to exit. + */ + + (void)pthread_takesemaphore(&pjoin->exit_sem); + + /* The thread has exited! Get the thread exit value */ + + if (pexit_value) + { + *pexit_value = pjoin->exit_value; + sdbg("exit_value=0x%p\n", pjoin->exit_value); + } + + /* Post the thread's data semaphore so that the exitting thread + * will know that we have received the data. + */ + + (void)pthread_givesemaphore(&pjoin->data_sem); + + /* Retake the join semaphore, we need to hold this when + * pthread_destroyjoin is called. + */ + + (void)pthread_takesemaphore(&g_join_semaphore); + } + + /* Pre-emption is okay now. The logic still cannot be re-entered + * because we hold the join semaphore + */ + + sched_unlock(); + + /* Release our reference to the join structure and, if the reference + * count decrements to zero, deallocate the join structure. + */ + + if (--pjoin->crefs <= 0) + { + (void)pthread_destroyjoin(pjoin); + } + + (void)pthread_givesemaphore(&g_join_semaphore); + ret = OK; + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/sched/pthread_keycreate.c b/nuttx/sched/pthread_keycreate.c new file mode 100644 index 0000000000..7579e4c117 --- /dev/null +++ b/nuttx/sched/pthread_keycreate.c @@ -0,0 +1,135 @@ +/**************************************************************************** + * sched/pthread_keycreate.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_key_create + * + * Description: + * This function creates a thread-specific data key visible to all threads + * in the system. Although the same key value may be used by different + * threads, the values bound to the key by pthread_setspecific() are + * maintained on a per-thread basis and persist for the life of the calling + * thread. + * + * Upon key creation, the value NULL will be associated with the new key + * in all active threads. Upon thread creation, the value NULL will be + * associated with all defined keys in the new thread. + * + * Parameters: + * key = A pointer to the key to create. + * destructor = An optional destructor() function that may be associated + * with each key that is invoked when a thread exits. However, this + * argument is ignored in the current implementation. + * + * Return Value: + * If successful, the pthread_key_create() function will store the newly + * created key value at *key and return zero (OK). Otherwise, an error + * number will bereturned to indicate the error: + * + * EAGAIN - The system lacked sufficient resources to create another + * thread-specific data key, or the system-imposed limit on the total + * number of keys pers process {PTHREAD_KEYS_MAX} has been exceeded + * ENONMEM - Insufficient memory exists to create the key. + * + * Assumptions: + * + * POSIX Compatibility: + * - The present implementation ignores the destructor argument. + * + ****************************************************************************/ + +int pthread_key_create(FAR pthread_key_t *key, CODE void (*destructor)(void*)) +{ +#if CONFIG_NPTHREAD_KEYS > 0 + int ret = EAGAIN; + + /* Check if we have exceeded the system-defined number of keys. */ + + if (g_pthread_num_keys < PTHREAD_KEYS_MAX) + { + /* Return the key value */ + + *key = g_pthread_num_keys; + + /* Increment the count of global keys. */ + + g_pthread_num_keys++; + + /* Return success. */ + + ret = OK; + } + + return ret; +#else + return ENOSYS; +#endif +} diff --git a/nuttx/sched/pthread_keydelete.c b/nuttx/sched/pthread_keydelete.c new file mode 100644 index 0000000000..d55a448edd --- /dev/null +++ b/nuttx/sched/pthread_keydelete.c @@ -0,0 +1,96 @@ +/************************************************************************ + * sched/pthread_keydelete.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include + +#include "pthread_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_key_delete + * + * Description: + * This POSIX function should delete a thread-specific data key + * previously returned by pthread_key_create(). However, this function + * does nothing in the present implementation. + * + * Parameters: + * key = the key to delete + * + * Return Value: + * Always returns ENOSYSL. + * + * Assumptions: + * + * POSIX Compatibility: + * + ************************************************************************/ + +int pthread_key_delete(pthread_key_t key) +{ + return ENOSYS; +} + diff --git a/nuttx/sched/pthread_kill.c b/nuttx/sched/pthread_kill.c new file mode 100644 index 0000000000..5a1506c0c9 --- /dev/null +++ b/nuttx/sched/pthread_kill.c @@ -0,0 +1,95 @@ +/************************************************************************ + * sched/pthread_kill.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +/************************************************************************ + * Global Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_kill + * + * Description: + * The pthread_kill() system call can be used to send any signal to a + * thread. See kill() for further information as this is just a simple + * wrapper around the kill() function. + * + * Parameters: + * thread - The id of the thread to receive the signal. Only positive, + * non-zero values of 'thread' are supported. + * signo - The signal number to send. If 'signo' is zero, no signal is + * sent, but all error checking is performed. + * + * Return Value: + * On success the signal was send and zero is returned. On error one + * of the following error numbers is returned. + * + * EINVAL An invalid signal was specified. + * EPERM The thread does not have permission to send the + * signal to the target thread. + * ESRCH No thread could be found corresponding to that + * specified by the given thread ID + * ENOSYS Do not support sending signals to process groups. + * + * Assumptions: + * + ************************************************************************/ + +int pthread_kill(pthread_t thread, int signo) +{ + int ret; + + set_errno(EINVAL); + ret = kill((pid_t)thread, signo); + if (ret != OK) + { + ret = get_errno(); + } + + return ret; +} + + diff --git a/nuttx/sched/pthread_mutexdestroy.c b/nuttx/sched/pthread_mutexdestroy.c new file mode 100644 index 0000000000..f663585341 --- /dev/null +++ b/nuttx/sched/pthread_mutexdestroy.c @@ -0,0 +1,131 @@ +/**************************************************************************** + * sched/pthread_mutexdestroy.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutex_destroy + * + * Description: + * Destroy a mutex. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutex_destroy(FAR pthread_mutex_t *mutex) +{ + int ret = OK; + int status; + + sdbg("mutex=0x%p\n", mutex); + + if (!mutex) + { + ret = EINVAL; + } + else + { + /* Make sure the semaphore is stable while we make the following + * checks + */ + + sched_lock(); + + /* Is the semaphore available? */ + + if (mutex->pid != 0) + { + ret = EBUSY; + } + else + { + /* Destroy the semaphore */ + + status = sem_destroy((sem_t*)&mutex->sem); + if (status != OK) + { + ret = EINVAL; + } + } + + sched_unlock(); + } + + sdbg("Returning %d\n", ret); + return ret; +} diff --git a/nuttx/sched/pthread_mutexinit.c b/nuttx/sched/pthread_mutexinit.c new file mode 100644 index 0000000000..265f014e34 --- /dev/null +++ b/nuttx/sched/pthread_mutexinit.c @@ -0,0 +1,138 @@ +/**************************************************************************** + * sched/pthread_mutexinit.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutex_init + * + * Description: + * Create a mutex + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutex_init(FAR pthread_mutex_t *mutex, FAR pthread_mutexattr_t *attr) +{ + int pshared = 0; +#ifdef CONFIG_MUTEX_TYPES + uint8_t type = PTHREAD_MUTEX_DEFAULT; +#endif + int ret = OK; + int status; + + sdbg("mutex=0x%p attr=0x%p\n", mutex, attr); + + if (!mutex) + { + ret = EINVAL; + } + else + { + /* Were attributes specified? If so, use them */ + + if (attr) + { + pshared = attr->pshared; +#ifdef CONFIG_MUTEX_TYPES + type = attr->type; +#endif + } + + /* Indicate that the semaphore is not held by any thread. */ + + mutex->pid = 0; + + /* Initialize the mutex like a semaphore with initial count = 1 */ + + status = sem_init((sem_t*)&mutex->sem, pshared, 1); + if (status != OK) + { + ret = EINVAL; + } + + /* Set up attributes unique to the mutex type */ + +#ifdef CONFIG_MUTEX_TYPES + mutex->type = type; + mutex->nlocks = 0; +#endif + } + + sdbg("Returning %d\n", ret); + return ret; +} diff --git a/nuttx/sched/pthread_mutexlock.c b/nuttx/sched/pthread_mutexlock.c new file mode 100644 index 0000000000..7681d771a8 --- /dev/null +++ b/nuttx/sched/pthread_mutexlock.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * sched/pthread_mutexlock.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutex_lock + * + * Description: + * The mutex object referenced by mutex is locked by calling + * pthread_mutex_lock(). If the mutex is already locked, the calling thread + * blocks until the mutex becomes available. This operation returns with the + * mutex object referenced by mutex in the locked state with the calling + * thread as its owner. + * + * If the mutex type is PTHREAD_MUTEX_NORMAL, deadlock detection is not + * provided. Attempting to relock the mutex causes deadlock. If a thread + * attempts to unlock a mutex that it has not locked or a mutex which is + * unlocked, undefined behavior results. + * + * If the mutex type is PTHREAD_MUTEX_ERRORCHECK, then error checking is + * provided. If a thread attempts to relock a mutex that it has already + * locked, an error will be returned. If a thread attempts to unlock a + * mutex that it has not locked or a mutex which is unlocked, an error will + * be returned. + * + * If the mutex type is PTHREAD_MUTEX_RECURSIVE, then the mutex maintains + * the concept of a lock count. When a thread successfully acquires a mutex + * for the first time, the lock count is set to one. Every time a thread + * relocks this mutex, the lock count is incremented by one. Each time the + * thread unlocks the mutex, the lock count is decremented by one. When the + * lock count reaches zero, the mutex becomes available for other threads to + * acquire. If a thread attempts to unlock a mutex that it has not locked or + * a mutex which is unlocked, an error will be returned. + * + * If a signal is delivered to a thread waiting for a mutex, upon return + * from the signal handler the thread resumes waiting for the mutex as if + * it was not interrupted. + * + * Parameters: + * mutex - A reference to the mutex to be locked. + * + * Return Value: + * 0 on success or an errno value on failure. Note that the errno EINTR + * is never returned by pthread_mutex_lock(). + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutex_lock(FAR pthread_mutex_t *mutex) +{ + int mypid = (int)getpid(); + int ret = OK; + + sdbg("mutex=0x%p\n", mutex); + + if (!mutex) + { + ret = EINVAL; + } + else + { + /* Make sure the semaphore is stable while we make the following + * checks. This all needs to be one atomic action. + */ + + sched_lock(); + + /* Does this task already hold the semaphore? */ + + if (mutex->pid == mypid) + { + /* Yes.. Is this a recursive mutex? */ + +#ifdef CONFIG_MUTEX_TYPES + if (mutex->type == PTHREAD_MUTEX_RECURSIVE) + { + /* Yes... just increment the number of locks held and return success */ + + mutex->nlocks++; + } + else +#endif + { + /* No, then we would deadlock... return an error (default behavior + * is like PTHREAD_MUTEX_ERRORCHECK) + */ + + sdbg("Returning EDEADLK\n"); + ret = EDEADLK; + } + } + else + { + /* Take the semaphore */ + + ret = pthread_takesemaphore((sem_t*)&mutex->sem); + + /* If we succussfully obtained the semaphore, then indicate + * that we own it. + */ + + if (!ret) + { + mutex->pid = mypid; +#ifdef CONFIG_MUTEX_TYPES + mutex->nlocks = 1; +#endif + } + } + + sched_unlock(); + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/sched/pthread_mutextrylock.c b/nuttx/sched/pthread_mutextrylock.c new file mode 100644 index 0000000000..d88012b51c --- /dev/null +++ b/nuttx/sched/pthread_mutextrylock.c @@ -0,0 +1,147 @@ +/**************************************************************************** + * sched/pthread_mutextrylock.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutex_trylock + * + * Description: + * The function pthread_mutex_trylock() is identical to pthread_mutex_lock() + * except that if the mutex object referenced by mutex is currently locked + * (by any thread, including the current thread), the call returns immediately + * with the errno EBUSY. + * + * If a signal is delivered to a thread waiting for a mutex, upon return from + * the signal handler the thread resumes waiting for the mutex as if it was + * not interrupted. + * + * Parameters: + * mutex - A reference to the mutex to be locked. + * + * Return Value: + * 0 on success or an errno value on failure. Note that the errno EINTR + * is never returned by pthread_mutex_lock(). + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutex_trylock(FAR pthread_mutex_t *mutex) +{ + int ret = OK; + + sdbg("mutex=0x%p\n", mutex); + + if (!mutex) + { + ret = EINVAL; + } + else + { + /* Make sure the semaphore is stable while we make the following + * checks. This all needs to be one atomic action. + */ + + sched_lock(); + + /* Try to get the semaphore. */ + + if (sem_trywait((sem_t*)&mutex->sem) == OK) + { + /* If we succussfully obtained the semaphore, then indicate + * that we own it. + */ + + mutex->pid = (int)getpid(); + } + + /* Was it not available? */ + + else if (get_errno() == EAGAIN) + { + ret = EBUSY; + } + else + { + ret = EINVAL; + } + + sched_unlock(); + } + + sdbg("Returning %d\n", ret); + return ret; +} + + + diff --git a/nuttx/sched/pthread_mutexunlock.c b/nuttx/sched/pthread_mutexunlock.c new file mode 100644 index 0000000000..34846f9523 --- /dev/null +++ b/nuttx/sched/pthread_mutexunlock.c @@ -0,0 +1,164 @@ +/**************************************************************************** + * sched/pthread_mutexunlock.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutex_unlock + * + * Description: + * The pthread_mutex_unlock() function releases the mutex object referenced + * by mutex. The manner in which a mutex is released is dependent upon the + * mutex's type attribute. If there are threads blocked on the mutex object + * referenced by mutex when pthread_mutex_unlock() is called, resulting in + * the mutex becoming available, the scheduling policy is used to determine + * which thread shall acquire the mutex. (In the case of PTHREAD_MUTEX_RECURSIVE + * mutexes, the mutex becomes available when the count reaches zero and the + * calling thread no longer has any locks on this mutex). + * + * If a signal is delivered to a thread waiting for a mutex, upon return from + * the signal handler the thread resumes waiting for the mutex as if it was + * not interrupted. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutex_unlock(FAR pthread_mutex_t *mutex) +{ + int ret = OK; + + sdbg("mutex=0x%p\n", mutex); + + if (!mutex) + { + ret = EINVAL; + } + else + { + /* Make sure the semaphore is stable while we make the following + * checks. This all needs to be one atomic action. + */ + + sched_lock(); + + /* Does the calling thread own the semaphore? */ + + if (mutex->pid != (int)getpid()) + { + /* No... return an error (default behavior is like PTHREAD_MUTEX_ERRORCHECK) */ + + sdbg("Holder=%d returning EPERM\n", mutex->pid); + ret = EPERM; + } + + + /* Yes, the caller owns the semaphore.. Is this a recursive mutex? */ + +#ifdef CONFIG_MUTEX_TYPES + else if (mutex->type == PTHREAD_MUTEX_RECURSIVE && mutex->nlocks > 1) + { + /* This is a recursive mutex and we there are multiple locks held. Retain + * the mutex lock, just decrement the count of locks held, and return + * success. + */ + mutex->nlocks--; + } +#endif + + /* This is either a non-recursive mutex or is the outermost unlock of + * a recursive mutex. + */ + + else + { + /* Nullify the pid and lock count then post the semaphore */ + + mutex->pid = 0; +#ifdef CONFIG_MUTEX_TYPES + mutex->nlocks = 0; +#endif + ret = pthread_givesemaphore((sem_t*)&mutex->sem); + } + sched_unlock(); + } + + sdbg("Returning %d\n", ret); + return ret; +} + + diff --git a/nuttx/sched/pthread_once.c b/nuttx/sched/pthread_once.c new file mode 100644 index 0000000000..4133004729 --- /dev/null +++ b/nuttx/sched/pthread_once.c @@ -0,0 +1,128 @@ +/******************************************************************************** + * sched/pthread_once.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +/******************************************************************************** + * Pre-processor Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: pthread_once + * + * Description: + * The first call to pthread_once() by any thread with a given once_control, + * will call the init_routine with no arguments. Subsequent calls to + * pthread_once() with the same once_control will have no effect. On return + * from pthread_once(), init_routine will have completed. + * + * Parameters: + * once_control - Determines if init_routine should be called. once_control + * should be declared and intialized as follows: + * + * pthread_once_t once_control = PTHREAD_ONCE_INIT; + * + * PTHREAD_ONCE_INIT is defined in pthread.h + * init_routine - The initialization routine that will be called once. + * + * Return Value: + * 0 (OK) on success or EINVAL if either once_control or init_routine are + * invalid + * + * Assumptions: + * + ********************************************************************************/ + +int pthread_once(FAR pthread_once_t *once_control, + CODE void (*init_routine)(void)) +{ + /* Sanity checks */ + + if (once_control && init_routine) + { + /* Prohibit pre-emption while we test and set the once_control */ + + sched_lock(); + if (!*once_control) + { + *once_control = true; + + /* Call the init_routine with pre-emption enabled. */ + + sched_unlock(); + init_routine(); + return OK; + } + + /* The init_routine has already been called. Restore pre-emption and return */ + + sched_unlock(); + return OK; + } + + /* One of the two arguments is NULL */ + + return EINVAL; +} diff --git a/nuttx/sched/pthread_removejoininfo.c b/nuttx/sched/pthread_removejoininfo.c new file mode 100644 index 0000000000..defc029917 --- /dev/null +++ b/nuttx/sched/pthread_removejoininfo.c @@ -0,0 +1,137 @@ +/************************************************************************ + * sched/pthread_removejoininfo.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include "pthread_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_removejoininfo + * + * Description: + * Remove a join_t from the local data set. + * + * Parameters: + * pid + * + * Return Value: + * None or pointer to the found entry. + * + * Assumptions: + * The caller has provided protection from re-entrancy. + * + ************************************************************************/ + +FAR join_t *pthread_removejoininfo(pid_t pid) +{ + FAR join_t *prev; + FAR join_t *join; + + /* Find the entry with the matching pid */ + + for (prev = NULL, join = g_pthread_head; + (join && (pid_t)join->thread != pid); + prev = join, join = join->next); + + /* Remove it from the data set. */ + + /* First check if this is the entry at the head of the list. */ + + if (join) + { + if (!prev) + { + /* Check if this is the only entry in the list */ + + if (!join->next) + { + g_pthread_head = NULL; + g_pthread_tail = NULL; + } + + /* Otherwise, remove it from the head of the list */ + + else + { + g_pthread_head = join->next; + } + } + + /* It is not at the head of the list, check if it is at the tail. */ + + else if (!join->next) + { + g_pthread_tail = prev; + prev->next = NULL; + } + + /* No, remove it from the middle of the list. */ + + else + { + prev->next = join->next; + } + } + + return join; +} + diff --git a/nuttx/sched/pthread_setcancelstate.c b/nuttx/sched/pthread_setcancelstate.c new file mode 100644 index 0000000000..2c6bf3083e --- /dev/null +++ b/nuttx/sched/pthread_setcancelstate.c @@ -0,0 +1,131 @@ +/****************************************************************************************** + * pthread_setcancelstate.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************************/ + +/****************************************************************************************** + * Included Files + ******************************************************************************************/ + +#include +#include +#include "os_internal.h" + +/****************************************************************************************** + * Private Definitions + ******************************************************************************************/ + +/****************************************************************************************** + * Private Types + ******************************************************************************************/ + +/****************************************************************************************** + * Private Function Prototypes + ******************************************************************************************/ + +/****************************************************************************************** + * Global Variables + ******************************************************************************************/ + +/****************************************************************************************** + * Private Variables + ******************************************************************************************/ + +/****************************************************************************************** + * Private Functions + ******************************************************************************************/ + +/****************************************************************************************** + * Public Functions + ******************************************************************************************/ + +/****************************************************************************************** + * Name: pthread_setcancelstate + ******************************************************************************************/ + +int pthread_setcancelstate(int state, FAR int *oldstate) +{ + _TCB *tcb = (_TCB*)g_readytorun.head; + int ret = OK; + + /* Suppress context changes for a bit so that the flags are stable. (the + * flags should not change in interrupt handling). + */ + + sched_lock(); + + /* Return the current state if so requrested */ + + if (oldstate) + { + if ((tcb->flags & TCB_FLAG_NONCANCELABLE) != 0) + { + *oldstate = PTHREAD_CANCEL_DISABLE; + } + else + { + *oldstate = PTHREAD_CANCEL_ENABLE; + } + } + + /* Set the new cancellation state */ + + if (state == PTHREAD_CANCEL_ENABLE) + { + unsigned flags = tcb->flags; + + /* Clear the non-cancelable and cancel pending flags */ + + tcb->flags &= ~(TCB_FLAG_NONCANCELABLE|TCB_FLAG_CANCEL_PENDING); + + /* If the cancel was pending, then just exit as requested */ + + if (flags & TCB_FLAG_CANCEL_PENDING) + { + pthread_exit(PTHREAD_CANCELED); + } + } + else if (state == PTHREAD_CANCEL_DISABLE) + { + /* Set the non-cancelable state */ + + tcb->flags |= TCB_FLAG_NONCANCELABLE; + } + else + { + ret = EINVAL; + } + + sched_unlock(); + return ret; +} diff --git a/nuttx/sched/pthread_setschedparam.c b/nuttx/sched/pthread_setschedparam.c new file mode 100644 index 0000000000..019a7c7a5d --- /dev/null +++ b/nuttx/sched/pthread_setschedparam.c @@ -0,0 +1,142 @@ +/**************************************************************************** + * pthread_setschedparam.c + * + * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_setschedparam + * + * Description: + * The pthread_setschedparam() functions will set the scheduling policy + * and parameters of threads. For SCHED_FIFO and SCHED_RR, the only + * required member of the sched_param structure is the priority + * sched_priority. + * + * The pthread_setschedparam() function will set the scheduling policy + * and associated scheduling parameters for the thread whose thread ID + * is given by 'thread' to the policy and associated parameters provided + * in 'policy' and 'param', respectively. + * + * The policy parameter may have the value SCHED_FIFO, or SCHED_RR + * (SCHED_OTHER and SCHED_SPORADIC, in particular, are not supported). + * The SCHED_FIFO and SCHED_RR policies will have a single scheduling + * parameter, sched_priority. + * + * If the pthread_setschedparam() function fails, the scheduling parameters + * will not be changed for the target thread. + * + * Parameters: + * thread - The ID of thread whose scheduling parameters will be modified. + * policy - The new scheduling policy of the thread. Either SCHED_FIFO or + * SCHED_RR. SCHED_OTHER and SCHED_SPORADIC are not supported. + * param - Provides the new priority of the thread. + * + * Return Value: + * 0 if successful. Otherwise, an error code identifying the cause of the + * failure: + * + * EINVAL The value specified by 'policy' or one of the scheduling + * parameters associated with the scheduling policy 'policy' is + * invalid. + * ENOTSUP An attempt was made to set the policy or scheduling parameters + * to an unsupported value (SCHED_OTHER and SCHED_SPORADIC in + * particular are not supported) + * EPERM The caller does not have the appropriate permission to set either + * the scheduling parameters or the scheduling policy of the + * specified thread. Or, the implementation does not allow the + * application to modify one of the parameters to the value + * specified. + * ESRCH The value specified by thread does not refer to a existing thread. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_setschedparam(pthread_t thread, int policy, FAR const struct sched_param *param) +{ + int ret; + + sdbg("thread ID=%d policy=%d param=0x%p\n", thread, policy, param); + + /* Set the errno to some non-zero value (failsafe) */ + + set_errno(EINVAL); + + /* Let sched_setscheduler do all of the work */ + + ret = sched_setscheduler((pid_t)thread, policy, param); + if (ret != OK) + { + /* If sched_setscheduler() fails, return the errno */ + + ret = get_errno(); + } + + return ret; +} diff --git a/nuttx/sched/pthread_setschedprio.c b/nuttx/sched/pthread_setschedprio.c new file mode 100644 index 0000000000..a523b20ea4 --- /dev/null +++ b/nuttx/sched/pthread_setschedprio.c @@ -0,0 +1,120 @@ +/**************************************************************************** + * pthread_schedsetprio.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_setsetprio + * + * Description: + * The pthread_setschedprio() function sets the scheduling priority for the + * thread whose thread ID is given by 'thread' to the value given by 'prio'. + * If the thread_setschedprio() function fails, the scheduling priority + * of the target thread will not be changed. + * + * Inputs: + * thread - the thread ID of the task to reprioritize. + * prio - The new thread priority. The range of valid priority numbers is + * from SCHED_PRIORITY_MIN through SCHED_PRIORITY_MAX. + * + * Return Value: + * OK if successful, otherwise an error number. This function can + * fail for the following reasons: + * + * EINVAL - prio is out of range. + * ESRCH - thread ID does not correspond to any thread. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_setschedprio(pthread_t thread, int prio) +{ + struct sched_param param; + int ret; + + /* Set the errno to some non-zero value (failsafe) */ + + errno = EINVAL; + + /* Call sched_setparam() to change the priority */ + + param.sched_priority = prio; + ret = sched_setparam((pid_t)thread, ¶m); + if (ret != OK) + { + /* If sched_setparam() fails, return the errno */ + + ret = errno; + } + return ret; +} diff --git a/nuttx/sched/pthread_setspecific.c b/nuttx/sched/pthread_setspecific.c new file mode 100644 index 0000000000..33fb4aeeb4 --- /dev/null +++ b/nuttx/sched/pthread_setspecific.c @@ -0,0 +1,137 @@ +/**************************************************************************** + * sched/pthread_setspecific.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include "os_internal.h" +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_setspecific + * + * Description: + * The pthread_setspecific() function associates a thread- + * specific value with a key obtained via a previous call + * to pthread_key_create(). Different threads may bind + * different values to the same key. These values are + * typically pointers to blocks of dynamically allocated + * memory that have been reserved for use by the calling + * thread. + * + * The effect of calling pthread_setspecific() with + * with a key value not obtained from pthread_create() or + * after a key has been deleted with pthread_key_delete() + * is undefined. + * + * Parameters: + * key = The data key to get or set + * value = The value to bind to the key. + * + * Return Value: + * If successful, pthread_setspecific() will return zero (OK). + * Otherwise, an error number will be returned: + * + * ENOMEM - Insufficient memory exists to associate + * the value with the key. + * EINVAL - The key value is invalid. + * + * Assumptions: + * + * POSIX Compatibility: + * int pthread_setspecific(pthread_key_t key, void *value) + * void *pthread_getspecific(pthread_key_t key) + * + * - Both calling pthread_setspecific() and pthread_getspecific() + * may be called from a thread-specific data destructor + * function. + * + ****************************************************************************/ + +int pthread_setspecific(pthread_key_t key, FAR void *value) +{ +#if CONFIG_NPTHREAD_KEYS > 0 + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + int ret = EINVAL; + + /* Check if the key is valid. */ + + if (key < g_pthread_num_keys) + { + /* Store the data in the TCB. */ + + rtcb->pthread_data[key] = value; + + /* Return success. */ + + ret = OK; + } + + return ret; +#else + return ENOSYS; +#endif +} + diff --git a/nuttx/sched/pthread_sigmask.c b/nuttx/sched/pthread_sigmask.c new file mode 100644 index 0000000000..c66b8591c1 --- /dev/null +++ b/nuttx/sched/pthread_sigmask.c @@ -0,0 +1,107 @@ +/************************************************************************ + * sched/pthread_sigmask.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_sigmask + * + * Description: + * This function is a simple wrapper around sigprocmask(). + * See the sigprocmask() function description for further + * information. + * + * Parameters: + * how - How the signal mast will be changed: + * SIG_BLOCK - The resulting set is the union of + * the current set and the signal set + * pointed to by 'set'. + * SIG_UNBLOCK - The resulting set is the intersection + * of the current set and the complement + * of the signal set pointed to by 'set'. + * SIG_SETMASK - The resulting set is the signal set + * pointed to by 'set'. + * set - Location of the new signal mask + * oset - Location to store the old signal mask + * + * Return Value: + * 0 (OK) or EINVAL if how is invalid. + * + * Assumptions: + * + ************************************************************************/ + +int pthread_sigmask(int how, FAR const sigset_t *set, FAR sigset_t *oset) +{ + int ret = sigprocmask(how, set, oset); + if (ret != OK) + { + ret = EINVAL; + } + return ret; +} diff --git a/nuttx/sched/pthread_yield.c b/nuttx/sched/pthread_yield.c new file mode 100644 index 0000000000..c4535b9dbc --- /dev/null +++ b/nuttx/sched/pthread_yield.c @@ -0,0 +1,87 @@ +/************************************************************************ + * sched/pthread_yield.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_yield + * + * Description: + * A thread may tell the scheduler that its processor can be + * made available. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ************************************************************************/ + +void pthread_yield(void) +{ + (void)sched_yield(); +} diff --git a/nuttx/sched/sched_addblocked.c b/nuttx/sched/sched_addblocked.c new file mode 100644 index 0000000000..c0b80c8ac6 --- /dev/null +++ b/nuttx/sched/sched_addblocked.c @@ -0,0 +1,122 @@ +/************************************************************************ + * sched/sched_addblocked.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_addblocked + * + * Description: + * This function adds a TCB to one of the blocked state task lists as + * inferred from task_state. + * + * Inputs: + * btcb - Points to the TCB that is blocked + * task_state - identifies the state of the blocked task + * + * Return Value: + * None + * + * Assumptions: + * - The caller has established a critical section before + * calling this function. + * + ************************************************************************/ + +void sched_addblocked(FAR _TCB *btcb, tstate_t task_state) +{ + /* Make sure that we received a valid blocked state */ + + ASSERT(task_state >= FIRST_BLOCKED_STATE && + task_state <= LAST_BLOCKED_STATE); + + /* Add the TCB to the blocked task list associated with this state. + * First, determine if the task is to be added to a prioritized task + * list + */ + + if (g_tasklisttable[task_state].prioritized) + { + /* Add the task to a prioritized list */ + + sched_addprioritized(btcb, + (FAR dq_queue_t*)g_tasklisttable[task_state].list); + } + else + { + /* Add the task to a non-prioritized list */ + + dq_addlast((FAR dq_entry_t*)btcb, + (FAR dq_queue_t*)g_tasklisttable[task_state].list); + } + + /* Make sure the TCB's state corresponds to the list */ + + btcb->task_state = task_state; +} + diff --git a/nuttx/sched/sched_addprioritized.c b/nuttx/sched/sched_addprioritized.c new file mode 100644 index 0000000000..8f19a4731d --- /dev/null +++ b/nuttx/sched/sched_addprioritized.c @@ -0,0 +1,175 @@ +/************************************************************************ + * sched/sched_addprioritized.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "os_internal.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_addprioritized + * + * Description: + * This function adds a TCB to a prioritized TCB list. + * + * Inputs: + * tcb - Points to the TCB to add to the prioritized list + * list - Points to the prioritized list to add tcb to + * + * Return Value: + * true if the head of the list has changed. + * + * Assumptions: + * - The caller has established a critical section before + * calling this function (calling sched_lock() first is NOT + * a good idea -- use irqsave()). + * - The caller has already removed the input tcb from + * whatever list it was in. + * - The caller handles the condition that occurs if the + * the head of the task list is changed. + * - The caller must set the task_state field of the TCB to + * match the state associated with the list. + ************************************************************************/ + +bool sched_addprioritized(FAR _TCB *tcb, DSEG dq_queue_t *list) +{ + FAR _TCB *next; + FAR _TCB *prev; + uint8_t sched_priority = tcb->sched_priority; + bool ret = false; + + /* Lets do a sanity check before we get started. */ + + ASSERT(sched_priority >= SCHED_PRIORITY_MIN); + + /* Search the list to find the location to insert the new Tcb. + * Each is list is maintained in ascending sched_priority order. + */ + + for (next = (FAR _TCB*)list->head; + (next && sched_priority <= next->sched_priority); + next = next->flink); + + /* Add the tcb to the spot found in the list. Check if the tcb + * goes at the end of the list. NOTE: This could only happen if list + * is the g_pendingtasks list! + */ + + if (!next) + { + /* The tcb goes at the end of the list. */ + + prev = (FAR _TCB*)list->tail; + if (!prev) + { + /* Special case: The list is empty */ + + tcb->flink = NULL; + tcb->blink = NULL; + list->head = (FAR dq_entry_t*)tcb; + list->tail = (FAR dq_entry_t*)tcb; + ret = true; + } + else + { + /* The tcb goes at the end of a non-empty list */ + + tcb->flink = NULL; + tcb->blink = prev; + prev->flink = tcb; + list->tail = (FAR dq_entry_t*)tcb; + } + } + else + { + /* The tcb goes just before next */ + + prev = (FAR _TCB*)next->blink; + if (!prev) + { + /* Special case: Insert at the head of the list */ + + tcb->flink = next; + tcb->blink = NULL; + next->blink = tcb; + list->head = (FAR dq_entry_t*)tcb; + ret = true; + } + else + { + /* Insert in the middle of the list */ + + tcb->flink = next; + tcb->blink = prev; + prev->flink = tcb; + next->blink = tcb; + } + } + + return ret; +} + diff --git a/nuttx/sched/sched_addreadytorun.c b/nuttx/sched/sched_addreadytorun.c new file mode 100644 index 0000000000..f6117b6ffe --- /dev/null +++ b/nuttx/sched/sched_addreadytorun.c @@ -0,0 +1,149 @@ +/**************************************************************************** + * sched/sched_addreadytorun.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_addreadytorun + * + * Description: + * This function adds a TCB to the ready to run + * list. If the currently active task has preemption disabled + * and the new TCB would cause this task to be preempted, the + * new task is added to the g_pendingtasks list instead. The + * pending tasks will be made ready-to-run when preemption + * is unlocked. + * + * Inputs: + * btcb - Points to the blocked TCB that is ready-to-run + * + * Return Value: + * true if the currently active task (the head of the + * g_readytorun list) has changed. + * + * Assumptions: + * - The caller has established a critical section before + * calling this function (calling sched_lock() first is NOT + * a good idea -- use irqsave()). + * - The caller has already removed the input rtcb from + * whatever list it was in. + * - The caller handles the condition that occurs if the + * the head of the g_readytorun list is changed. + * + ****************************************************************************/ + +bool sched_addreadytorun(FAR _TCB *btcb) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + bool ret; + + /* Check if pre-emption is disabled for the current running task and if + * the new ready-to-run task would cause the current running task to be + * preempted. + */ + + if (rtcb->lockcount && rtcb->sched_priority < btcb->sched_priority) + { + /* Yes. Preemption would occur! Add the new ready-to-run task to the + * g_pendingtasks task list for now. + */ + + sched_addprioritized(btcb, (FAR dq_queue_t*)&g_pendingtasks); + btcb->task_state = TSTATE_TASK_PENDING; + ret = false; + } + + /* Otherwise, add the new task to the g_readytorun task list */ + + else if (sched_addprioritized(btcb, (FAR dq_queue_t*)&g_readytorun)) + { + /* Information the instrumentation logic that we are switching tasks */ + + sched_note_switch(rtcb, btcb); + + /* The new btcb was added at the head of the g_readytorun list. It + * is now to new active task! + */ + + ASSERT(!rtcb->lockcount && btcb->flink != NULL); + + btcb->task_state = TSTATE_TASK_RUNNING; + btcb->flink->task_state = TSTATE_TASK_READYTORUN; + ret = true; + } + else + { + /* The new btcb was added in the middle of the g_readytorun list */ + + btcb->task_state = TSTATE_TASK_READYTORUN; + ret = false; + } + + return ret; +} diff --git a/nuttx/sched/sched_foreach.c b/nuttx/sched/sched_foreach.c new file mode 100644 index 0000000000..1920945331 --- /dev/null +++ b/nuttx/sched/sched_foreach.c @@ -0,0 +1,84 @@ +/************************************************************************ + * sched/sched_foreach.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include "os_internal.h" + +/************************************************************************ + * Global Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_foreach + * + * Description: + * Enumerate over each task and provide the TCB of each + * task to a user callback functions. Interrupts will be + * disabled throughout this enumeration! + * + * Parameters: + * handler - The function to be called with the TCB of + * each task + * + * Return Value: + * None + * + * Assumptions: + * + ************************************************************************/ + +void sched_foreach(sched_foreach_t handler, FAR void *arg) +{ + irqstate_t flags = irqsave(); + int ndx; + + /* Verify that the PID is within range */ + + for (ndx = 0; ndx < CONFIG_MAX_TASKS; ndx++) + { + if (g_pidhash[ndx].tcb) + { + handler(g_pidhash[ndx].tcb, arg); + } + } + + irqrestore(flags); +} + + diff --git a/nuttx/sched/sched_free.c b/nuttx/sched/sched_free.c new file mode 100644 index 0000000000..4df77b109a --- /dev/null +++ b/nuttx/sched/sched_free.c @@ -0,0 +1,114 @@ +/************************************************************************ + * sched/sched_free.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_free + * + * Description: + * This function performs deallocations that the operating system may + * need to make. This special interface to free is used to handling + * corner cases where the operating system may have to perform + * deallocations from within an interrupt handler. + * + ************************************************************************/ + +void sched_free(FAR void *address) +{ + /* Check if this is an attempt to deallocate memory from an exception + * handler. If this function is called from the IDLE task, then we + * must have exclusive access to the memory manager to do this. + */ + + if (up_interrupt_context() || kmm_trysemaphore() != 0) + { + /* Yes.. Delay the deallocation until a more appropriate time. */ + + irqstate_t saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)address, (sq_queue_t*)&g_delayeddeallocations); + + /* Signal the worker thread that is has some clean up to do */ + +#ifdef CONFIG_SCHED_WORKQUEUE + work_signal(); +#endif + irqrestore(saved_state); + } + else + { + /* No.. just deallocate the memory now. */ + + kfree(address); + kmm_givesemaphore(); + } +} + diff --git a/nuttx/sched/sched_garbage.c b/nuttx/sched/sched_garbage.c new file mode 100644 index 0000000000..b8bec9399d --- /dev/null +++ b/nuttx/sched/sched_garbage.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * sched/sched_garbage.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "os_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: sched_garbagecollection + * + * Description: + * Clean-up memory de-allocations that we queued because they could not + * be freed in that execution context (for example, if the memory was freed + * from an interrupt handler). + * + * This logic may be called from the worker thread (see work_thread.c). + * If, however, CONFIG_SCHED_WORKQUEUE is not defined, then this logic will + * be called from the IDLE thread. It is less optimal for the garbage + * collection to be called from the IDLE thread because it runs at a very + * low priority and could cause false memory out conditions. + * + * Input parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void sched_garbagecollection(void) +{ + irqstate_t flags; + void *address; + + /* Test if the delayed deallocation queue is empty. No special protection + * is needed because this is an atomic test. + */ + + while (g_delayeddeallocations.head) + { + /* Remove the first delayed deallocation. This is not atomic and so + * we must disable interrupts around the queue operation. + */ + + flags = irqsave(); + address = (void*)sq_remfirst((FAR sq_queue_t*)&g_delayeddeallocations); + irqrestore(flags); + + /* Then deallocate it. */ + + if (address) + { + kfree(address); + } + } +} + diff --git a/nuttx/sched/sched_getfiles.c b/nuttx/sched/sched_getfiles.c new file mode 100644 index 0000000000..256b4cb6bc --- /dev/null +++ b/nuttx/sched/sched_getfiles.c @@ -0,0 +1,76 @@ +/************************************************************************ + * sched/sched_getfiles.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include +#include "os_internal.h" + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_getfiles + * + * Description: + * Return a pointer to the file list for this thread + * + * Parameters: + * None + * + * Return Value: + * A pointer to the errno. + * + * Assumptions: + * + ************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + +FAR struct filelist *sched_getfiles(void) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + return rtcb->filelist; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS */ diff --git a/nuttx/sched/sched_getparam.c b/nuttx/sched/sched_getparam.c new file mode 100644 index 0000000000..47eab49881 --- /dev/null +++ b/nuttx/sched/sched_getparam.c @@ -0,0 +1,146 @@ +/************************************************************************ + * sched/sched_getparam.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_getparam + * + * Description: + * This function gets the scheduling priority of the task + * specified by pid. + * + * Inputs: + * pid - the task ID of the task. If pid is zero, the priority + * of the calling task is returned. + * param - A structure whose member sched_priority is the integer + * priority. The task's priority is copied to the sched_priority + * element of this structure. + * + * Return Value: + * 0 (OK) if successful, otherwise -1 (ERROR). + * + * This function can fail if param is null or if pid does + * not correspond to any task. + * + * Assumptions: + * + ************************************************************************/ + +int sched_getparam (pid_t pid, struct sched_param * param) +{ + FAR _TCB *rtcb; + FAR _TCB *tcb; + int ret = OK; + + if (!param) + { + return ERROR; + } + + /* Check if the task to restart is the calling task */ + + rtcb = (FAR _TCB*)g_readytorun.head; + if ((pid == 0) || (pid == rtcb->pid)) + { + /* Return the priority if the calling task. */ + + param->sched_priority = (int)rtcb->sched_priority; + } + + /* Ths pid is not for the calling task, we will have to look it up */ + + else + { + /* Get the TCB associated with this pid */ + + sched_lock(); + tcb = sched_gettcb(pid); + if (!tcb) + { + /* This pid does not correspond to any known task */ + + ret = ERROR; + } + else + { + /* Return the priority of the task */ + + param->sched_priority = (int)tcb->sched_priority; + } + + sched_unlock(); + } + + return ret; +} + diff --git a/nuttx/sched/sched_getscheduler.c b/nuttx/sched/sched_getscheduler.c new file mode 100644 index 0000000000..5771e86ff4 --- /dev/null +++ b/nuttx/sched/sched_getscheduler.c @@ -0,0 +1,131 @@ +/************************************************************************ + * sched/sched_getscheduler.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_getscheduler + * + * Description: + * sched_getscheduler() returns the scheduling policy currently + * applied to the task identified by pid. If pid equals zero, the + * policy of the calling task will be retrieved. + * + * Inputs: + * pid - the task ID of the task to query. If pid is zero, the + * calling task is queried. + * + * Return Value: + * On success, sched_getscheduler() returns the policy for the task + * (either SCHED_FIFO or SCHED_RR). On error, ERROR (-1) is + * returned, and errno is set appropriately: + * + * ESRCH The task whose ID is pid could not be found. + * + * Assumptions: + * + ************************************************************************/ + +int sched_getscheduler(pid_t pid) +{ + _TCB *tcb; + + /* Verify that the pid corresponds to a real task */ + + if (!pid) + { + tcb = (_TCB*)g_readytorun.head; + } + else + { + tcb = sched_gettcb(pid); + } + + if (!tcb) + { + set_errno(ESRCH); + return ERROR; + } +#if CONFIG_RR_INTERVAL > 0 + else if ((tcb->flags & TCB_FLAG_ROUND_ROBIN) != 0) + { + return SCHED_RR; + } +#endif + else + { + return SCHED_FIFO; + } +} diff --git a/nuttx/sched/sched_getsockets.c b/nuttx/sched/sched_getsockets.c new file mode 100644 index 0000000000..cd499420fe --- /dev/null +++ b/nuttx/sched/sched_getsockets.c @@ -0,0 +1,77 @@ +/************************************************************************ + * sched/sched_getsockets.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include "os_internal.h" + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_getsockets + * + * Description: + * Return a pointer to the socket list for this thread + * + * Parameters: + * None + * + * Return Value: + * A pointer to the errno. + * + * Assumptions: + * + ************************************************************************/ + +FAR struct socketlist *sched_getsockets(void) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + return rtcb->sockets; +} + +#endif /* CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/sched/sched_getstreams.c b/nuttx/sched/sched_getstreams.c new file mode 100644 index 0000000000..f7c21ab4ca --- /dev/null +++ b/nuttx/sched/sched_getstreams.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * sched/sched_getstreams.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "os_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_getstreams + * + * Description: + * Return a pointer to the streams list for this thread + * + * Parameters: + * None + * + * Return Value: + * A pointer to the errno. + * + * Assumptions: + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 + +FAR struct streamlist *sched_getstreams(void) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + return rtcb->streams; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS && CONFIG_NFILE_STREAMS */ diff --git a/nuttx/sched/sched_gettcb.c b/nuttx/sched/sched_gettcb.c new file mode 100644 index 0000000000..1e50ef50f4 --- /dev/null +++ b/nuttx/sched/sched_gettcb.c @@ -0,0 +1,107 @@ +/**************************************************************************** + * sched/sched_gettcb.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_gettcb + * + * Description: + * Given a task ID, this function will return + * the a pointer to the corresponding TCB (or NULL if there + * is no such task ID). + * + ****************************************************************************/ + +FAR _TCB *sched_gettcb(pid_t pid) +{ + FAR _TCB *ret = NULL; + int hash_ndx; + + /* Verify that the PID is within range */ + + if (pid >= 0 ) + { + /* Get the hash_ndx associated with the pid */ + + hash_ndx = PIDHASH(pid); + + /* Verify that the correct TCB was found. */ + + if (pid == g_pidhash[hash_ndx].pid) + { + /* Return the TCB associated with this pid (if any) */ + + ret = g_pidhash[hash_ndx].tcb; + } + } + + /* Return the TCB. */ + + return ret; +} + diff --git a/nuttx/sched/sched_lock.c b/nuttx/sched/sched_lock.c new file mode 100644 index 0000000000..61a8a3bc8d --- /dev/null +++ b/nuttx/sched/sched_lock.c @@ -0,0 +1,110 @@ +/************************************************************************ + * sched/sched_lock.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include + +#include +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functionss + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_lock + * + * Description: + * This function disables context switching by disabling addition of + * new tasks to the g_readytorun task list. The task that calls this + * function will be the only task that is allowed to run until it + * either calls sched_unlock() (the appropriate number of times) or + * until it blocks itself. + * + * Inputs + * None + * + * Return Value: + * OK on success; ERROR on failure + * + ************************************************************************/ + +int sched_lock(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + + /* Check for some special cases: (1) rtcb may be NULL only during + * early boot-up phases, and (2) sched_lock() should have no + * effect if called from the interrupt level. + */ + + if (rtcb && !up_interrupt_context()) + { + ASSERT(rtcb->lockcount < MAX_LOCK_COUNT); + rtcb->lockcount++; + } + + return OK; +} diff --git a/nuttx/sched/sched_lockcount.c b/nuttx/sched/sched_lockcount.c new file mode 100644 index 0000000000..4dc7a82018 --- /dev/null +++ b/nuttx/sched/sched_lockcount.c @@ -0,0 +1,97 @@ +/************************************************************************ + * sched/sched_lockcount.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functionss + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_lockcount + * + * Description: + * This function returns the current value of the lockcount. If zero, + * pre-emption is enabled; if non-zero, this value indicates the number + * of times that sched_lock() has been called on this thread of + * execution. sched_unlock() will have to called that many times from + * this thread in order to re-enable pre-emption. + * + * Inputs: + * None + * + * Return Value: + * lockcount + * + ************************************************************************/ + +int sched_lockcount(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + return (int)rtcb->lockcount; +} + diff --git a/nuttx/sched/sched_mergepending.c b/nuttx/sched/sched_mergepending.c new file mode 100644 index 0000000000..71d575c233 --- /dev/null +++ b/nuttx/sched/sched_mergepending.c @@ -0,0 +1,177 @@ +/************************************************************************ + * sched/sched_mergepending.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "os_internal.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_mergepending + * + * Description: + * This function merges the prioritized g_pendingtasks list into the + * prioritized g_readytorun task list. + * + * Inputs: + * None + * + * Return Value: + * true if the head of the g_readytorun task list has changed. + * + * Assumptions: + * - The caller has established a critical section before + * calling this function (calling sched_lock() first is NOT + * a good idea -- use irqsave()). + * - The caller handles the condition that occurs if the + * the head of the sched_mergTSTATE_TASK_PENDINGs is changed. + * + ************************************************************************/ + +bool sched_mergepending(void) +{ + FAR _TCB *pndtcb; + FAR _TCB *pndnext; + FAR _TCB *rtrtcb; + FAR _TCB *rtrprev; + bool ret = false; + + /* Initialize the inner search loop */ + + rtrtcb = (FAR _TCB*)g_readytorun.head; + + /* Process every TCB in the g_pendingtasks list */ + + for (pndtcb = (FAR _TCB*)g_pendingtasks.head; pndtcb; pndtcb = pndnext) + { + pndnext = pndtcb->flink; + + /* Search the g_readytorun list to find the location to insert the + * new pndtcb. Each is list is maintained in ascending sched_priority + * order. + */ + + for (; + (rtrtcb && pndtcb->sched_priority <= rtrtcb->sched_priority); + rtrtcb = rtrtcb->flink); + + /* Add the pndtcb to the spot found in the list. Check if the + * pndtcb goes at the ends of the g_readytorun list. This would be + * error condition since the idle test must always be at the end of + * the g_readytorun list! + */ + + if (!rtrtcb) + { + PANIC(OSERR_NOIDLETASK); + } + else + { + /* The pndtcb goes just before rtrtcb */ + + rtrprev = rtrtcb->blink; + if (!rtrprev) + { + /* Special case: Inserting pndtcb at the head of the list */ + /* Inform the instrumentation layer that we are switching tasks */ + + sched_note_switch(rtrtcb, pndtcb); + + /* Then insert at the head of the list */ + + pndtcb->flink = rtrtcb; + pndtcb->blink = NULL; + rtrtcb->blink = pndtcb; + g_readytorun.head = (FAR dq_entry_t*)pndtcb; + rtrtcb->task_state = TSTATE_TASK_READYTORUN; + pndtcb->task_state = TSTATE_TASK_RUNNING; + ret = true; + } + else + { + /* Insert in the middle of the list */ + + pndtcb->flink = rtrtcb; + pndtcb->blink = rtrprev; + rtrprev->flink = pndtcb; + rtrtcb->blink = pndtcb; + pndtcb->task_state = TSTATE_TASK_READYTORUN; + } + } + + /* Set up for the next time through */ + + rtrtcb = pndtcb; + } + + /* Mark the input list empty */ + + g_pendingtasks.head = NULL; + g_pendingtasks.tail = NULL; + + return ret; +} diff --git a/nuttx/sched/sched_processtimer.c b/nuttx/sched/sched_processtimer.c new file mode 100644 index 0000000000..2224b7691d --- /dev/null +++ b/nuttx/sched/sched_processtimer.c @@ -0,0 +1,190 @@ +/************************************************************************ + * sched/sched_processtimer.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +#if CONFIG_RR_INTERVAL > 0 +# include +# include +#endif + +#include "os_internal.h" +#include "wd_internal.h" +#include "clock_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +static void sched_process_timeslice(void) +{ +#if CONFIG_RR_INTERVAL > 0 + _TCB *rtcb; + + /* Check if the currently executing task uses round robin + * scheduling. + */ + + rtcb = (_TCB*)g_readytorun.head; + if ((rtcb->flags & TCB_FLAG_ROUND_ROBIN) != 0) + { + /* Yes, check if decrementing the timeslice counter + * would cause the timeslice to expire + */ + + if (rtcb->timeslice <= 1) + { + /* Yes, Now check if the task has pre-emption disabled. + * If so, then we will freeze the timeslice count at + * the value until the next tick after pre-emption + * has been enabled. + */ + + if (!rtcb->lockcount) + { + /* Reset the timeslice in any case. */ + + rtcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; + + /* We know we are at the head of the ready to run + * prioritized list. We must be the highest priority + * task eligible for execution. Check the next task + * in the ready to run list. If it is the same + * priority, then we need to relinquish the CPU and + * give that task a shot. + */ + + if (rtcb->flink && + rtcb->flink->sched_priority >= rtcb->sched_priority) + { + /* Just resetting the task priority to its current + * value. This this will cause the task to be + * rescheduled behind any other tasks at the same + * priority. + */ + + up_reprioritize_rtr(rtcb, rtcb->sched_priority); + } + } + } + else + { + /* Decrement the timeslice counter */ + + rtcb->timeslice--; + } + } +#endif +} + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * System Timer Hooks + * + * These are standard interfaces that are exported by the OS + * for use by the architecture specific logic + * + ************************************************************************/ + +/************************************************************************ + * Name: sched_process_timer + * + * Description: + * This function handles system timer events. + * The timer interrupt logic itself is implemented in the + * architecture specific code, but must call the following OS + * function periodically -- the calling interval must be + * MSEC_PER_TICK + * + * Inputs: + * None + * + * Return Value: + * None + * + ************************************************************************/ + +void sched_process_timer(void) +{ + /* Increment the system time (if in the link) */ + +#ifndef CONFIG_DISABLE_CLOCK +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (clock_timer != NULL) +#endif + { + clock_timer(); + } +#endif + + /* Process watchdogs (if in the link) */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (wd_timer != NULL) +#endif + { + wd_timer(); + } + + /* Check if the currently executing task has exceeded its + * timeslice. + */ + + sched_process_timeslice(); +} diff --git a/nuttx/sched/sched_releasefiles.c b/nuttx/sched/sched_releasefiles.c new file mode 100644 index 0000000000..a3ef71af45 --- /dev/null +++ b/nuttx/sched/sched_releasefiles.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * sched/sched_releasefiles.c + * + * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_releasefiles + * + * Description: + * Release file resources attached to a TCB. This file may be called + * multiple times as a task exists. It will be called as early as possible + * to support proper closing of complex drivers that may need to wait + * on external events. + * + * Parameters: + * tcb - tcb of the new task. + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int sched_releasefiles(_TCB *tcb) +{ + if (tcb) + { +#if CONFIG_NFILE_DESCRIPTORS > 0 + /* Free the file descriptor list */ + + if (tcb->filelist) + { + files_releaselist(tcb->filelist); + tcb->filelist = NULL; + } + +#if CONFIG_NFILE_STREAMS > 0 + /* Free the stream list */ + + if (tcb->streams) + { + lib_releaselist(tcb->streams); + tcb->streams = NULL; + } +#endif /* CONFIG_NFILE_STREAMS */ +#endif /* CONFIG_NFILE_DESCRIPTORS */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + /* Free the file descriptor list */ + + if (tcb->sockets) + { + net_releaselist(tcb->sockets); + tcb->sockets = NULL; + } +#endif /* CONFIG_NSOCKET_DESCRIPTORS */ + } + + return OK; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS || CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/sched/sched_releasetcb.c b/nuttx/sched/sched_releasetcb.c new file mode 100644 index 0000000000..21837262d6 --- /dev/null +++ b/nuttx/sched/sched_releasetcb.c @@ -0,0 +1,181 @@ +/************************************************************************ + * sched/sched_releasetcb.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "os_internal.h" +#include "timer_internal.h" +#include "env_internal.h" + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_releasepid + * + * Description: When a task is destroyed, this function must + * be called to make its process ID available for re-use. + ************************************************************************/ + +static void sched_releasepid(pid_t pid) +{ + int hash_ndx = PIDHASH(pid); + + /* Make any pid associated with this hash available. Note: + * no special precautions need be taken here because the + * following action is atomic + */ + + g_pidhash[hash_ndx].tcb = NULL; + g_pidhash[hash_ndx].pid = INVALID_PROCESS_ID; +} + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_releasetcb + * + * Description: + * Free all resources contained in a TCB + * + * Parameters: + * None + * + * Return Value: + * OK on success; ERROR on failure + * + * Assumptions: + * Interrupts are disabled. + * + ************************************************************************/ + +int sched_releasetcb(FAR _TCB *tcb) +{ + int ret = OK; + int i; + + if (tcb) + { + /* Relase any timers that the task might hold. We do this + * before release the PID because it may still be trying to + * deliver signals (although interrupts are should be + * disabled here). + */ + +#ifndef CONFIG_DISABLE_POSIX_TIMERS +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (timer_deleteall != NULL) +#endif + { + timer_deleteall(tcb->pid); + } +#endif + + /* Release the task's process ID if one was assigned. PID + * zero is reserved for the IDLE task. The TCB of the IDLE + * task is never release so a value of zero simply means that + * the process ID was never allocated to this TCB. + */ + + if (tcb->pid) + { + sched_releasepid(tcb->pid); + } + + /* Delete the thread's stack if one has been allocated */ + +#ifndef CONFIG_CUSTOM_STACK + if (tcb->stack_alloc_ptr) + { + up_release_stack(tcb); + } +#endif + + /* Delete the tasks's allocated DSpace region (external modules only) */ + +#ifdef CONFIG_PIC + if (tcb->dspace) + { + if (tcb->dspace->crefs <= 1) + { + sched_free(tcb->dspace); + } + else + { + tcb->dspace->crefs--; + } + } +#endif + + /* Release command line arguments that were allocated for task + * start/re-start. + */ + + if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK) + { + for (i = 1; i < CONFIG_MAX_TASK_ARGS+1 && tcb->argv[i]; i++) + { + sched_free((FAR void*)tcb->argv[i]); + } + } + + /* Release any allocated file structures */ + + ret = sched_releasefiles(tcb); + + /* Release environment variables */ + + (void)env_release(tcb); + + /* And, finally, release the TCB itself */ + + sched_free(tcb); + } + + return ret; +} + diff --git a/nuttx/sched/sched_removeblocked.c b/nuttx/sched/sched_removeblocked.c new file mode 100644 index 0000000000..8d5a127d25 --- /dev/null +++ b/nuttx/sched/sched_removeblocked.c @@ -0,0 +1,111 @@ +/************************************************************************ + * sched/sched_removeblocked.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_removeblocked + * + * Description: + * This function removes a TCB from one of the blocked state task + * lists as inferred from the task_state inside the TCB. + * + * Inputs: + * btcb - Points to the TCB that is blocked + * + * Return Value: + * None + * + * Assumptions: + * - The caller has established a critical section before + * calling this function. + * + ************************************************************************/ + +void sched_removeblocked(FAR _TCB *btcb) +{ + tstate_t task_state = btcb->task_state; + + /* Make sure the TCB is in a valid blocked state */ + + ASSERT(task_state >= FIRST_BLOCKED_STATE && + task_state <= LAST_BLOCKED_STATE); + + /* Remove the TCB from the blocked task list associated + * with this state + */ + + dq_rem((FAR dq_entry_t*)btcb, (dq_queue_t*)g_tasklisttable[task_state].list); + + /* Make sure the TCB's state corresponds to not being in + * any list + */ + + btcb->task_state = TSTATE_TASK_INVALID; +} + diff --git a/nuttx/sched/sched_removereadytorun.c b/nuttx/sched/sched_removereadytorun.c new file mode 100644 index 0000000000..4982808e2b --- /dev/null +++ b/nuttx/sched/sched_removereadytorun.c @@ -0,0 +1,121 @@ +/**************************************************************************** + * shced/sched_removereadytorun.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_removereadytorun + * + * Description: + * This function removes a TCB from the ready to run list. + * + * Inputs: + * rtcb - Points to the TCB that is ready-to-run + * + * Return Value: + * true if the currently active task (the head of the + * g_readytorun list) has changed. + * + * Assumptions: + * - The caller has established a critical section before calling this + * function (calling sched_lock() first is NOT a good idea -- use irqsave()). + * - The caller handles the condition that occurs if the + * the head of the g_readytorun list is changed. + * + ****************************************************************************/ + +bool sched_removereadytorun(FAR _TCB *rtcb) +{ + bool ret = false; + + /* Check if the TCB to be removed is at the head of the ready to run list. + * In this case, we are removing the currently active task. + */ + + if (!rtcb->blink) + { + /* There must always be at least one task in the list (the idle task) */ + + ASSERT(rtcb->flink != NULL); + + /* Inform the instrumentation layer that we are switching tasks */ + + sched_note_switch(rtcb, rtcb->flink); + + rtcb->flink->task_state = TSTATE_TASK_RUNNING; + ret = true; + } + + /* Remove the TCB from the ready-to-run list */ + + dq_rem((FAR dq_entry_t*)rtcb, (dq_queue_t*)&g_readytorun); + + rtcb->task_state = TSTATE_TASK_INVALID; + return ret; +} diff --git a/nuttx/sched/sched_reprioritize.c b/nuttx/sched/sched_reprioritize.c new file mode 100644 index 0000000000..bd316ec752 --- /dev/null +++ b/nuttx/sched/sched_reprioritize.c @@ -0,0 +1,129 @@ +/**************************************************************************** + * sched/sched_reprioritize.c + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" + +#ifdef CONFIG_PRIORITY_INHERITANCE + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_reprioritize + * + * Description: + * This function sets the priority of a specified task. + * + * NOTE: Setting a task's priority to the same value has a similar effect + * to sched_yield() -- The task will be moved to after all other tasks + * with the same priority. + * + * Inputs: + * tcb - the TCB of task to reprioritize. + * sched_priority - The new task priority + * + * Return Value: + * On success, sched_setparam() returns 0 (OK). On error, -1 + * (ERROR) is returned, and errno is set appropriately. + * + * EINVAL The parameter 'param' is invalid or does not make sense for the + * current scheduling policy. + * EPERM The calling task does not have appropriate privileges. + * ESRCH The task whose ID is pid could not be found. + * + * Assumptions: + * + ****************************************************************************/ + +int sched_reprioritize(FAR _TCB *tcb, int sched_priority) +{ + /* This function is equivalent to sched_setpriority() BUT it also has the + * side effect of discarding all priority inheritance history. This is + * done only on explicit, user-initiated reprioritization. + */ + + int ret = sched_setpriority(tcb, sched_priority); + if (ret == 0) + { + /* Reset the base_priority -- the priority that the thread would return + * to once it posts the semaphore. + */ + + tcb->base_priority = (uint8_t)sched_priority; + + /* Discard any pending reprioritizations as well */ + +#if CONFIG_SEM_NNESTPRIO > 0 + tcb->npend_reprio = 0; +#endif + } + return ret; +} +#endif /* CONFIG_PRIORITY_INHERITANCE */ diff --git a/nuttx/sched/sched_rrgetinterval.c b/nuttx/sched/sched_rrgetinterval.c new file mode 100644 index 0000000000..961c58ec51 --- /dev/null +++ b/nuttx/sched/sched_rrgetinterval.c @@ -0,0 +1,157 @@ +/************************************************************************ + * sched/sched_rrgetinterval.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "os_internal.h" +#include "clock_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_rr_get_interval + * + * Description: + * sched_rr_get_interval() writes the timeslice interval for task + * identified by 'pid' into the timespec structure pointed to by + * 'interval.' If pid is zero, the timeslice for the calling process + * is written into 'interval. The identified process should be running + * under the SCHED_RRscheduling policy.' + * + * Inputs: + * pid - the task ID of the task. If pid is zero, the priority of the + * calling task is returned. + * interval - a structure used to return the time slice + * + * Return Value: + * On success, sched_rr_get_interval() returns OK (0). On error, + * ERROR (-1) is returned, and errno is set to: + * + * EFAULT -- Cannot copy to interval + * EINVAL Invalid pid. + * ENOSYS The system call is not yet implemented. + * ESRCH The process whose ID is pid could not be found. + * + * Assumptions: + * + ************************************************************************/ + +int sched_rr_get_interval(pid_t pid, struct timespec *interval) +{ +#if CONFIG_RR_INTERVAL > 0 + FAR _TCB *rrtcb; + + /* If pid is zero, the timeslice for the calling process is written + * into 'interval.' + */ + + if (!pid) + { + rrtcb = (FAR _TCB*)g_readytorun.head; + } + + /* Return a special error code on invalid PID */ + + else if (pid < 0) + { + set_errno(EINVAL); + return ERROR; + } + + /* Otherwise, lookup the TCB associated with this pid */ + + else + { + rrtcb = sched_gettcb(pid); + if (!rrtcb) + { + set_errno(ESRCH); + return ERROR; + } + } + + if (!interval) + { + set_errno(EFAULT); + return ERROR; + } + + /* Convert the timeslice value from ticks to timespec */ + + interval->tv_sec = CONFIG_RR_INTERVAL / MSEC_PER_SEC; + interval->tv_nsec = (CONFIG_RR_INTERVAL % MSEC_PER_SEC) * NSEC_PER_MSEC; + + return OK; +#else + set_errno(ENOSYS); + return ERROR; +#endif +} diff --git a/nuttx/sched/sched_self.c b/nuttx/sched/sched_self.c new file mode 100644 index 0000000000..9517e6306f --- /dev/null +++ b/nuttx/sched/sched_self.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * sched/sched_self.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_self + * + * Description: + * Return the current threads TCB. Basically, this function just wraps the + * head of the ready-to-run list and manages access to the TCB from outside + * of the sched/ sub-directory. + * + ****************************************************************************/ + +FAR _TCB *sched_self(void) +{ + return (FAR _TCB*)g_readytorun.head; +} + + diff --git a/nuttx/sched/sched_setparam.c b/nuttx/sched/sched_setparam.c new file mode 100644 index 0000000000..6ea4e8f74d --- /dev/null +++ b/nuttx/sched/sched_setparam.c @@ -0,0 +1,156 @@ +/**************************************************************************** + * sched/sched_setparam.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_setparam + * + * Description: + * This function sets the priority of a specified task. + * + * NOTE: Setting a task's priority to the same value has a similar effect + * to sched_yield() -- The task will be moved to after all other tasks + * with the same priority. + * + * Inputs: + * pid - the task ID of the task to reprioritize. If pid is zero, the + * priority of the calling task is changed. + * param - A structure whose member sched_priority is the integer priority. + * The range of valid priority numbers is from SCHED_PRIORITY_MIN + * through SCHED_PRIORITY_MAX. + * + * Return Value: + * On success, sched_setparam() returns 0 (OK). On error, -1 (ERROR) is + * returned, and errno is set appropriately. + * + * EINVAL The parameter 'param' is invalid or does not make sense for the + * current scheduling policy. + * EPERM The calling task does not have appropriate privileges. + * ESRCH The task whose ID is pid could not be found. + * + * Assumptions: + * + ****************************************************************************/ + +int sched_setparam(pid_t pid, const struct sched_param *param) +{ + FAR _TCB *rtcb; + FAR _TCB *tcb; + int ret; + + /* Verify that the requested priority is in the valid range */ + + if (!param) + { + errno = EINVAL; + return ERROR; + } + + /* Prohibit modifications to the head of the ready-to-run task + * list while adjusting the priority + */ + + sched_lock(); + + /* Check if the task to reprioritize is the calling task */ + + rtcb = (FAR _TCB*)g_readytorun.head; + if (pid == 0 || pid == rtcb->pid) + { + tcb = rtcb; + } + + /* The pid is not the calling task, we will have to search for it */ + + else + { + tcb = sched_gettcb(pid); + if (!tcb) + { + /* No task with this pid was found */ + + errno = ESRCH; + sched_unlock(); + return ERROR; + } + } + + /* Then perform the reprioritization */ + + ret = sched_reprioritize(tcb, param->sched_priority); + sched_unlock(); + return ret; +} diff --git a/nuttx/sched/sched_setpriority.c b/nuttx/sched/sched_setpriority.c new file mode 100644 index 0000000000..6aa0789eab --- /dev/null +++ b/nuttx/sched/sched_setpriority.c @@ -0,0 +1,233 @@ +/**************************************************************************** + * sched/sched_setpriority.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_setpriority + * + * Description: + * This function sets the priority of a specified task. + * + * NOTE: Setting a task's priority to the same value has a similar effect + * to sched_yield() -- The task will be moved to after all other tasks + * with the same priority. + * + * Inputs: + * tcb - the TCB of task to reprioritize. + * sched_priority - The new task priority + * + * Return Value: + * On success, sched_setparam() returns 0 (OK). On error, -1 (ERROR) is + * returned, and errno is set appropriately. + * + * EINVAL The parameter 'param' is invalid or does not make sense for the + * current scheduling policy. + * EPERM The calling task does not have appropriate privileges. + * ESRCH The task whose ID is pid could not be found. + * + * Assumptions: + * + ****************************************************************************/ + +int sched_setpriority(FAR _TCB *tcb, int sched_priority) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + tstate_t task_state; + irqstate_t saved_state; + + /* Verify that the requested priority is in the valid range */ + + if (sched_priority < SCHED_PRIORITY_MIN || + sched_priority > SCHED_PRIORITY_MAX) + { + errno = EINVAL; + return ERROR; + } + + /* We need to assure that there there is no interrupt activity while + * performing the following. + */ + + saved_state = irqsave(); + + /* There are four cases that must be considered: */ + + task_state = tcb->task_state; + switch (task_state) + { + /* CASE 1. The task is running or ready-to-run and a context switch + * may be caused by the re-prioritization + */ + + case TSTATE_TASK_RUNNING: + + /* A context switch will occur if the new priority of the running + * task becomes less than OR EQUAL TO the next highest priority + * ready to run task. + */ + + if (sched_priority <= tcb->flink->sched_priority) + { + /* A context switch will occur. */ + + up_reprioritize_rtr(tcb, (uint8_t)sched_priority); + } + + /* Otherwise, we can just change priority since it has no effect */ + + else + { + /* Change the task priority */ + + tcb->sched_priority = (uint8_t)sched_priority; + } + break; + + /* CASE 2. The task is running or ready-to-run and a context switch + * may be caused by the re-prioritization + */ + + case TSTATE_TASK_READYTORUN: + + /* A context switch will occur if the new priority of the ready-to + * run task is (strictly) greater than the current running task + */ + + if (sched_priority > rtcb->sched_priority) + { + /* A context switch will occur. */ + + up_reprioritize_rtr(tcb, (uint8_t)sched_priority); + } + + /* Otherwise, we can just change priority and re-schedule (since it + * have no other effect). + */ + + else + { + /* Remove the TCB from the ready-to-run task list */ + + ASSERT(!sched_removereadytorun(tcb)); + + /* Change the task priority */ + + tcb->sched_priority = (uint8_t)sched_priority; + + /* Put it back into the ready-to-run task list */ + + ASSERT(!sched_addreadytorun(tcb)); + } + break; + + /* CASE 3. The task is not in the ready to run list. Changing its + * Priority cannot effect the currently executing task. + */ + + default: + + /* CASE 3a. The task resides in a prioritized list. */ + + if (g_tasklisttable[task_state].prioritized) + { + /* Remove the TCB from the prioritized task list */ + + dq_rem((FAR dq_entry_t*)tcb, (FAR dq_queue_t*)g_tasklisttable[task_state].list); + + /* Change the task priority */ + + tcb->sched_priority = (uint8_t)sched_priority; + + /* Put it back into the prioritized list at the correct + * position + */ + + sched_addprioritized(tcb, (FAR dq_queue_t*)g_tasklisttable[task_state].list); + } + + /* CASE 3b. The task resides in a non-prioritized list. */ + + else + { + /* Just change the task's priority */ + + tcb->sched_priority = (uint8_t)sched_priority; + } + break; + } + + irqrestore(saved_state); + return OK; +} diff --git a/nuttx/sched/sched_setscheduler.c b/nuttx/sched/sched_setscheduler.c new file mode 100644 index 0000000000..7f7f345b41 --- /dev/null +++ b/nuttx/sched/sched_setscheduler.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * sched/sched_setscheduler.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "clock_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name:sched_setscheduler + * + * Description: + * sched_setscheduler() sets both the scheduling policy and the priority + * for the task identified by pid. If pid equals zero, the scheduler of + * the calling task will be set. The parameter 'param' holds the priority + * of the thread under the new policy. + * + * Inputs: + * pid - the task ID of the task to modify. If pid is zero, the calling + * task is modified. + * policy - Scheduling policy requested (either SCHED_FIFO or SCHED_RR) + * param - A structure whose member sched_priority is the new priority. + * The range of valid priority numbers is from SCHED_PRIORITY_MIN + * through SCHED_PRIORITY_MAX. + * + * Return Value: + * On success, sched_setscheduler() returns OK (zero). On error, ERROR + * (-1) is returned, and errno is set appropriately: + * + * EINVAL The scheduling policy is not one of the recognized policies. + * ESRCH The task whose ID is pid could not be found. + * + * Assumptions: + * + ****************************************************************************/ + +int sched_setscheduler(pid_t pid, int policy, + const struct sched_param *param) +{ + FAR _TCB *tcb; +#if CONFIG_RR_INTERVAL > 0 + irqstate_t saved_state; +#endif + int ret; + + /* Check for supported scheduling policy */ + +#if CONFIG_RR_INTERVAL > 0 + if (policy != SCHED_FIFO && policy != SCHED_RR) +#else + if (policy != SCHED_FIFO) +#endif + { + errno = EINVAL; + return ERROR; + } + + /* Check if the task to modify the calling task */ + + if (pid == 0 ) + { + pid = getpid(); + } + + /* Verify that the pid corresponds to a real task */ + + tcb = sched_gettcb(pid); + if (!tcb) + { + errno = ESRCH; + return ERROR; + } + + /* Prohibit any context switches while we muck with priority and scheduler + * settings. + */ + + sched_lock(); + +#if CONFIG_RR_INTERVAL > 0 + /* Further, disable timer interrupts while we set up scheduling policy. */ + + saved_state = irqsave(); + if (policy == SCHED_RR) + { + /* Set round robin scheduling */ + + tcb->flags |= TCB_FLAG_ROUND_ROBIN; + tcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; + } + else + { + /* Set FIFO scheduling */ + + tcb->flags &= ~TCB_FLAG_ROUND_ROBIN; + tcb->timeslice = 0; + } + + irqrestore(saved_state); +#endif + + /* Set the new priority */ + + ret = sched_reprioritize(tcb, param->sched_priority); + sched_unlock(); + + if (ret != OK) + { + return ERROR; + } + else + { + return OK; + } +} + diff --git a/nuttx/sched/sched_setupidlefiles.c b/nuttx/sched/sched_setupidlefiles.c new file mode 100644 index 0000000000..ae814e1a6e --- /dev/null +++ b/nuttx/sched/sched_setupidlefiles.c @@ -0,0 +1,148 @@ +/**************************************************************************** + * sched/sched_setupidlefiles.c + * + * Copyright (C) 2007-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_setupidlefiles + * + * Description: + * Configure the idle thread's TCB. + * + * Parameters: + * tcb - tcb of the idle task. + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int sched_setupidlefiles(FAR _TCB *tcb) +{ +#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_DEV_CONSOLE) + int fd; +#endif + + /* Allocate file descriptors for the TCB */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + tcb->filelist = files_alloclist(); + if (!tcb->filelist) + { + return -ENOMEM; + } +#endif + + /* Allocate socket descriptors for the TCB */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + tcb->sockets = net_alloclist(); + if (!tcb->sockets) + { + return -ENOMEM; + } +#endif + + /* Open stdin, dup to get stdout and stderr. This should always + * be the first file opened and, hence, should always get file + * descriptor 0. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_DEV_CONSOLE) + fd = open("/dev/console", O_RDWR); + if (fd == 0) + { + /* Successfully opened /dev/console as stdin (fd == 0) */ + + (void)file_dup2(0, 1); + (void)file_dup2(0, 2); + } + else + { + /* We failed to open /dev/console OR for some reason, we opened + * it and got some file descriptor other than 0. + */ + + if (fd > 0) + { + slldbg("Open /dev/console fd: %d\n", fd); + (void)close(fd); + } + else + { + slldbg("Failed to open /dev/console: %d\n", errno); + } + return -ENFILE; + } +#endif + + /* Allocate file/socket streams for the TCB */ + +#if CONFIG_NFILE_STREAMS > 0 + return sched_setupstreams(tcb); +#else + return OK; +#endif +} + +#endif /* CONFIG_NFILE_DESCRIPTORS || CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/sched/sched_setuppthreadfiles.c b/nuttx/sched/sched_setuppthreadfiles.c new file mode 100644 index 0000000000..648d9273ee --- /dev/null +++ b/nuttx/sched/sched_setuppthreadfiles.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * sched_setuppthreadfiles.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include + +#include "os_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_setuppthreadfiles + * + * Description: + * Configure a newly allocated TCB so that it will inherit file + * descriptors and streams from the parent pthread. + * + * Parameters: + * tcb - tcb of the new task. + * + * Return Value: + * OK (if an error were returned, it would need to be a non-negated + * errno value). + * + * Assumptions: + * + ****************************************************************************/ + +int sched_setuppthreadfiles(FAR _TCB *tcb) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + +#if CONFIG_NFILE_DESCRIPTORS > 0 + /* The child thread inherits the parent file descriptors */ + + tcb->filelist = rtcb->filelist; + files_addreflist(tcb->filelist); + +#endif /* CONFIG_NFILE_DESCRIPTORS */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + /* The child thread inherits the parent socket descriptors */ + + tcb->sockets = rtcb->sockets; + net_addreflist(tcb->sockets); + +#endif /* CONFIG_NSOCKET_DESCRIPTORS */ + +#if CONFIG_NFILE_STREAMS > 0 + /* The child thread inherits the parent streams */ + + tcb->streams = rtcb->streams; + lib_addreflist(tcb->streams); + +#endif /* CONFIG_NFILE_STREAMS */ + return OK; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS || CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/sched/sched_setupstreams.c b/nuttx/sched/sched_setupstreams.c new file mode 100644 index 0000000000..22895b0475 --- /dev/null +++ b/nuttx/sched/sched_setupstreams.c @@ -0,0 +1,98 @@ +/**************************************************************************** + * sched_setupstreams.c + * + * Copyright (C) 2007-2008, 2010-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +/* Make sure that there are file or socket descriptors in the system and + * that some number of streams have been configured. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 +#if CONFIG_NFILE_STREAMS > 0 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_setupstreams + * + * Description: + * Setup streams data structures that may be used for standard C buffered + * I/O with underlying socket or file desciptors + * + ****************************************************************************/ + +int sched_setupstreams(FAR _TCB *tcb) +{ + /* Allocate file streams for the TCB */ + + tcb->streams = lib_alloclist(); + if (tcb->streams) + { + /* fdopen to get the stdin, stdout and stderr streams. + * The following logic depends on the fact that the library + * layer will allocate FILEs in order. + * + * fd = 0 is stdin (read-only) + * fd = 1 is stdout (write-only, append) + * fd = 2 is stderr (write-only, append) + */ + + (void)fs_fdopen(0, O_RDONLY, tcb); + (void)fs_fdopen(1, O_WROK|O_CREAT, tcb); + (void)fs_fdopen(2, O_WROK|O_CREAT, tcb); + } + + return OK; +} + +#endif /* CONFIG_NFILE_STREAMS > 0 */ +#endif /* CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0*/ diff --git a/nuttx/sched/sched_setuptaskfiles.c b/nuttx/sched/sched_setuptaskfiles.c new file mode 100644 index 0000000000..7f754e1514 --- /dev/null +++ b/nuttx/sched/sched_setuptaskfiles.c @@ -0,0 +1,248 @@ +/**************************************************************************** + * sched/sched_setuptaskfiles.c + * + * Copyright (C) 2007-2008, 2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "os_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Determine how many file descriptors to clone. If CONFIG_FDCLONE_DISABLE + * is set, no file descriptors will be cloned. If CONFIG_FDCLONE_STDIO is + * set, only the first three descriptors (stdin, stdout, and stderr) will + * be cloned. Otherwise all file descriptors will be cloned. + */ + +#if defined(CONFIG_FDCLONE_STDIO) && CONFIG_NFILE_DESCRIPTORS > 3 +# define NFDS_TOCLONE 3 +#else +# define NFDS_TOCLONE CONFIG_NFILE_DESCRIPTORS +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_dupfiles + * + * Description: + * Duplicate parent task's file descriptors. + * + * Input Parameters: + * tcb - tcb of the new task. + * + * Return Value: + * None + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_FDCLONE_DISABLE) +static inline void sched_dupfiles(FAR _TCB *tcb) +{ + /* The parent task is the one at the head of the ready-to-run list */ + + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR struct file *parent; + FAR struct file *child; + int i; + + /* Duplicate the file descriptors. This will be either all of the + * file descriptors or just the first three (stdin, stdout, and stderr) + * if CONFIG_FDCLONE_STDIO is defined. NFSDS_TOCLONE is set + * accordingly above. + */ + + if (rtcb->filelist) + { + /* Get pointers to the parent and child task file lists */ + + parent = rtcb->filelist->fl_files; + child = tcb->filelist->fl_files; + + /* Check each file in the parent file list */ + + for (i = 0; i < NFDS_TOCLONE; i++) + { + /* Check if this file is opened by the parent. We can tell if + * if the file is open because it contain a reference to a non-NULL + * i-node structure. + */ + + if (parent[i].f_inode) + { + /* Yes... duplicate it for the child */ + + (void)files_dup(&parent[i], &child[i]); + } + } + } +} +#else /* CONFIG_NFILE_DESCRIPTORS && !CONFIG_FDCLONE_DISABLE */ +# define sched_dupfiles(tcb) +#endif /* CONFIG_NFILE_DESCRIPTORS && !CONFIG_FDCLONE_DISABLE */ + +/**************************************************************************** + * Name: sched_dupsockets + * + * Description: + * Duplicate the parent task's socket descriptors. + * + * Input Parameters: + * tcb - tcb of the new task. + * + * Return Value: + * None + * + ****************************************************************************/ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 && !defined(CONFIG_SDCLONE_DISABLE) +static inline void sched_dupsockets(FAR _TCB *tcb) +{ + /* The parent task is the one at the head of the ready-to-run list */ + + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR struct sockets *parent; + FAR struct sockets *child; + int i; + + /* Duplicate the socket descriptors of all sockets opened by the parent + * task. + */ + + if (rtcb->sockets) + { + /* Get pointers to the parent and child task socket lists */ + + parent = rtcb->sockets->sl_sockets; + child = tcb->sockets->sl_sockets; + + /* Check each socket in the parent socket list */ + + for (i = 0; i < CONFIG_NSOCKET_DESCRIPTORS; i++) + { + /* Check if this parent socket is allocated. We can tell if the + * socket is allocated because it will have a positive, non-zero + * reference count. + */ + + if (parent[i].s_crefs > 0) + { + /* Yes... duplicate it for the child */ + + (void)net_clone(&parent[i], &child[i]); + } + } + } +} +#else /* CONFIG_NSOCKET_DESCRIPTORS && !CONFIG_SDCLONE_DISABLE */ +# define sched_dupsockets(tcb) +#endif /* CONFIG_NSOCKET_DESCRIPTORS && !CONFIG_SDCLONE_DISABLE */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_setuptaskfiles + * + * Description: + * Configure a newly allocated TCB so that it will inherit + * file descriptors and streams from the parent task. + * + * Parameters: + * tcb - tcb of the new task. + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int sched_setuptaskfiles(FAR _TCB *tcb) +{ + /* Allocate file descriptors for the TCB */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + tcb->filelist = files_alloclist(); + if (!tcb->filelist) + { + return -ENOMEM; + } +#endif + + /* Allocate socket descriptors for the TCB */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + tcb->sockets = net_alloclist(); + if (!tcb->sockets) + { + return -ENOMEM; + } +#endif + + /* Duplicate the parent task's file descriptors */ + + sched_dupfiles(tcb); + + /* Duplicate the parent task's socket descriptors */ + + sched_dupsockets(tcb); + + /* Allocate file/socket streams for the new TCB */ + +#if CONFIG_NFILE_STREAMS > 0 + return sched_setupstreams(tcb); +#else + return OK; +#endif +} + +#endif /* CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0*/ diff --git a/nuttx/sched/sched_unlock.c b/nuttx/sched/sched_unlock.c new file mode 100644 index 0000000000..9a52e8358d --- /dev/null +++ b/nuttx/sched/sched_unlock.c @@ -0,0 +1,130 @@ +/************************************************************************ + * sched/sched_unlock.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functionss + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_unlock + * + * Description: + * This function decrements the preemption lock count. Typically this + * is paired with sched_lock() and concludes a critical section of + * code. Preemption will not be unlocked until sched_unlock() has + * been called as many times as sched_lock(). When the lockcount is + * decremented to zero, any tasks that were eligible to preempt the + * current task will execute. + * + ************************************************************************/ + +int sched_unlock(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + + /* Check for some special cases: (1) rtcb may be NULL only during + * early boot-up phases, and (2) sched_unlock() should have no + * effect if called from the interrupt level. + */ + + if (rtcb && !up_interrupt_context()) + { + /* Prevent context switches throughout the following */ + + irqstate_t flags = irqsave(); + + /* Decrement the preemption lock counter */ + + if (rtcb->lockcount) + { + rtcb->lockcount--; + } + + /* Check if the lock counter has decremented to zero. If so, + * then pre-emption has been re-enabled. + */ + + if (rtcb->lockcount <= 0) + { + rtcb->lockcount = 0; + + /* Release any ready-to-run tasks that have collected in + * g_pendingtasks. + */ + + if (g_pendingtasks.head) + { + up_release_pending(); + } + } + + irqrestore(flags); + } + return OK; +} diff --git a/nuttx/sched/sched_verifytcb.c b/nuttx/sched/sched_verifytcb.c new file mode 100644 index 0000000000..bcf097a5cc --- /dev/null +++ b/nuttx/sched/sched_verifytcb.c @@ -0,0 +1,86 @@ +/**************************************************************************** + * sched/ched_verifytcb.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_verifytcb + * + * Description: + * Return true if the tcb refers to an active task; false if it is a stale + * TCB handle. + * + ****************************************************************************/ + +bool sched_verifytcb(FAR _TCB *tcb) +{ + /* Return true if the PID hashes to this TCB. */ + + return tcb == g_pidhash[PIDHASH(tcb->pid)].tcb; +} + diff --git a/nuttx/sched/sched_waitpid.c b/nuttx/sched/sched_waitpid.c new file mode 100644 index 0000000000..e8e2f61a23 --- /dev/null +++ b/nuttx/sched/sched_waitpid.c @@ -0,0 +1,247 @@ +/***************************************************************************** + * sched/sched_waitpid.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/***************************************************************************** + * Included Files + *****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "os_internal.h" + +#ifdef CONFIG_SCHED_WAITPID /* Experimental */ + +/***************************************************************************** + * Private Functions + *****************************************************************************/ + +/***************************************************************************** + * Public Functions + *****************************************************************************/ + +/***************************************************************************** + * Name: sched_waitpid + * + * Description: + * + * The waitpid() functions will obtain status information pertaining to one + * of the caller's child processes. The waitpid() function will suspend + * execution of the calling thread until status information for one of the + * terminated child processes of the calling process is available, or until + * delivery of a signal whose action is either to execute a signal-catching + * function or to terminate the process. If more than one thread is suspended + * in waitpid() awaiting termination of the same process, exactly one thread + * will return the process status at the time of the target process + * termination. If status information is available prior to the call to + * waitpid(), return will be immediate. + * + * The pid argument specifies a set of child processes for which status is + * requested. The waitpid() function will only return the status of a child + * process from this set: + * + * - If pid is equal to (pid_t)-1, status is requested for any child process. + * In this respect, waitpid() is then equivalent to wait(). + * - If pid is greater than 0, it specifies the process ID of a single child + * process for which status is requested. + * - If pid is 0, status is requested for any child process whose process + * group ID is equal to that of the calling process. + * - If pid is less than (pid_t)-1, status is requested for any child process + * whose process group ID is equal to the absolute value of pid. + * + * The options argument is constructed from the bitwise-inclusive OR of zero + * or more of the following flags, defined in the header: + * + * WCONTINUED - The waitpid() function will report the status of any + * continued child process specified by pid whose status has not been + * reported since it continued from a job control stop. + * WNOHANG - The waitpid() function will not suspend execution of the + * calling thread if status is not immediately available for one of the + * child processes specified by pid. + * WUNTRACED - The status of any child processes specified by pid that are + * stopped, and whose status has not yet been reported since they stopped, + * will also be reported to the requesting process. + * + * If the calling process has SA_NOCLDWAIT set or has SIGCHLD set to + * SIG_IGN, and the process has no unwaited-for children that were + * transformed into zombie processes, the calling thread will block until all + * of the children of the process containing the calling thread terminate, and + * waitpid() will fail and set errno to ECHILD. + * + * If waitpid() returns because the status of a child process is available, + * these functions will return a value equal to the process ID of the child + * process. In this case, if the value of the argument stat_loc is not a + * null pointer, information will be stored in the location pointed to by + * stat_loc. The value stored at the location pointed to by stat_loc will be + * 0 if and only if the status returned is from a terminated child process + * that terminated by one of the following means: + * + * 1. The process returned 0 from main(). + * 2. The process called _exit() or exit() with a status argument of 0. + * 3. The process was terminated because the last thread in the process terminated. + * + * Regardless of its value, this information may be interpreted using the + * following macros, which are defined in and evaluate to + * integral expressions; the stat_val argument is the integer value pointed + * to by stat_loc. + * + * WIFEXITED(stat_val) - Evaluates to a non-zero value if status was + * returned for a child process that terminated normally. + * WEXITSTATUS(stat_val) - If the value of WIFEXITED(stat_val) is non-zero, + * this macro evaluates to the low-order 8 bits of the status argument + * that the child process passed to _exit() or exit(), or the value the + * child process returned from main(). + * WIFSIGNALED(stat_val) - Evaluates to a non-zero value if status was + * returned for a child process that terminated due to the receipt of a + * signal that was not caught (see ). + * WTERMSIG(stat_val) - If the value of WIFSIGNALED(stat_val) is non-zero, + * this macro evaluates to the number of the signal that caused the + * termination of the child process. + * WIFSTOPPED(stat_val) - Evaluates to a non-zero value if status was + * returned for a child process that is currently stopped. + * WSTOPSIG(stat_val) - If the value of WIFSTOPPED(stat_val) is non-zero, + * this macro evaluates to the number of the signal that caused the child + * process to stop. + * WIFCONTINUED(stat_val) - Evaluates to a non-zero value if status was + * returned for a child process that has continued from a job control stop. + * + * Parameters: + * pid - The task ID of the thread to waid for + * stat_loc - The location to return the exit status + * options - ignored + * + * Return Value: + * If waitpid() returns because the status of a child process is available, + * it will return a value equal to the process ID of the child process for + * which status is reported. + * + * If waitpid() returns due to the delivery of a signal to the calling + * process, -1 will be returned and errno set to EINTR. + * + * If waitpid() was invoked with WNOHANG set in options, it has at least + * one child process specified by pid for which status is not available, and + * status is not available for any process specified by pid, 0 is returned. + * + * Otherwise, (pid_t)-1 will be returned, and errno set to indicate the error: + * + * ECHILD - The process specified by pid does not exist or is not a child of + * the calling process, or the process group specified by pid does not exist + * or does not have any member process that is a child of the calling process. + * EINTR - The function was interrupted by a signal. The value of the location + * pointed to by stat_loc is undefined. + * EINVAL - The options argument is not valid. + * + * Assumptions: + * + *****************************************************************************/ + +/***************************************************************************/ +/* NOTE: This is a partially functional, experimental version of waitpid() */ +/***************************************************************************/ + +pid_t waitpid(pid_t pid, int *stat_loc, int options) +{ + _TCB *tcb = sched_gettcb(pid); + bool mystat; + int err; + int ret; + + /* Disable pre-emption so that nothing changes in the following tests */ + + sched_lock(); + if (!tcb) + { + err = ECHILD; + goto errout_with_errno; + } + + /* None of the options are supported */ + +#ifdef CONFIG_DEBUG + if (options != 0) + { + err = ENOSYS; + goto errout_with_errno; + } +#endif + + /* "If more than one thread is suspended in waitpid() awaiting termination of + * the same process, exactly one thread will return the process status at the + * time of the target process termination." Hmmm.. what do we return to the + * others? + */ + + if (stat_loc != NULL && tcb->stat_loc == NULL) + { + tcb->stat_loc = stat_loc; + mystat = true; + } + + /* Then wait for the task to exit */ + + ret = sem_wait(&tcb->exitsem); + if (ret < 0) + { + /* Unlock pre-emption and return the ERROR (sem_wait has already set + * the errno). Handle the awkward case of whether or not we need to + * nullify the stat_loc value. + */ + + if (mystat) + { + tcb->stat_loc = NULL; + } + + goto errout; + } + + /* On success, return the PID */ + + sched_unlock(); + return pid; + +errout_with_errno: + set_errno(err); +errout: + sched_unlock(); + return ERROR; +} + +#endif /* CONFIG_SCHED_WAITPID */ diff --git a/nuttx/sched/sched_yield.c b/nuttx/sched/sched_yield.c new file mode 100644 index 0000000000..b2e6493d0c --- /dev/null +++ b/nuttx/sched/sched_yield.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * sched/sched_yield.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_yield + * + * Description: + * This function forces the calling task to give up the CPU (only to other + * tasks at the same priority). + * + * Inputs: + * None + * + * Return Value: + * 0 (OK) or -1 (ERROR) (errno is not set) + * + * Assumptions: + * + ****************************************************************************/ + +int sched_yield(void) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + + /* This equivalent to just resetting the task priority to its current value + * since this will cause the task to be rescheduled behind any other tasks + * at the same priority. + */ + + return sched_setpriority(rtcb, rtcb->sched_priority); +} diff --git a/nuttx/sched/sem_close.c b/nuttx/sched/sem_close.c new file mode 100644 index 0000000000..169fc0448a --- /dev/null +++ b/nuttx/sched/sem_close.c @@ -0,0 +1,140 @@ +/**************************************************************************** + * sched/sem_close.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_close + * + * Description: + * This function is called to indicate that the calling task is finished + * with the specified named semaphore, 'sem'. The sem_close() deallocates + * any system resources allocated by the system for this named semaphore. + * + * If the semaphore has not been removed with a call to sem_unlink(), then + * sem_close() has no effect on the named semaphore. However, when the + * named semaphore has been fully unlinked, the semaphore will vanish when + * the last task closes it. + * + * Parameters: + * sem - semaphore descriptor + * + * Return Value: + * 0 (OK), or -1 (ERROR) if unsuccessful. + * + * Assumptions: + * - Care must be taken to avoid risking the deletion of a semaphore that + * another calling task has already locked. + * - sem_close must not be called for an un-named semaphore + * + ****************************************************************************/ + +int sem_close(FAR sem_t *sem) +{ + FAR nsem_t *psem; + int ret = ERROR; + + /* Verify the inputs */ + + if (sem) + { + sched_lock(); + + /* Search the list of named semaphores */ + + for (psem = (FAR nsem_t*)g_nsems.head; + ((psem) && (sem != &psem->sem)); + psem = psem->flink); + + /* Check if we found it */ + + if (psem) + { + /* Decrement the count of sem_open connections to this semaphore */ + + if (psem->nconnect) psem->nconnect--; + + /* If the semaphore is no long connected to any processes AND the + * semaphore was previously unlinked, then deallocate it. + */ + + if (!psem->nconnect && psem->unlinked) + { + dq_rem((FAR dq_entry_t*)psem, &g_nsems); + sched_free(psem); + } + ret = OK; + } + + sched_unlock(); + } + + return ret; +} diff --git a/nuttx/sched/sem_destroy.c b/nuttx/sched/sem_destroy.c new file mode 100644 index 0000000000..90a2b95ef7 --- /dev/null +++ b/nuttx/sched/sem_destroy.c @@ -0,0 +1,126 @@ +/**************************************************************************** + * lib/semaphore/sem_destroy.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "sem_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_destroy + * + * Description: + * This function is used to destroy the un-named semaphore indicated by + * 'sem'. Only a semaphore that was created using sem_init() may be + * destroyed using sem_destroy(); the effect of calling sem_destroy() with + * a named semaphore is undefined. The effect of subsequent use of the + * semaphore sem is undefined until sem is re-initialized by another call + * to sem_init(). + * + * The effect of destroying a semaphore upon which other processes are + * currently blocked is undefined. + * + * Parameters: + * sem - Semaphore to be destroyed. + * + * Return Value: + * 0 (OK), or -1 (ERROR) if unsuccessful. + * + * Assumptions: + * + ****************************************************************************/ + +int sem_destroy (FAR sem_t *sem) +{ + /* Assure a valid semaphore is specified */ + + if (sem) + { + /* There is really no particular action that we need + * take to destroy a semaphore. We will just reset + * the count to some reasonable value (1) and release + * ownership. + * + * Check if other threads are waiting on the semaphore. + * In this case, the behavior is undefined. We will: + * leave the count unchanged but still return OK. + */ + + if (sem->semcount >= 0) + { + sem->semcount = 1; + } + + /* Release holders of the semaphore */ + + sem_destroyholder(sem); + return OK; + } + else + { + errno = -EINVAL; + return ERROR; + } +} diff --git a/nuttx/sched/sem_findnamed.c b/nuttx/sched/sem_findnamed.c new file mode 100644 index 0000000000..bcba47a8ac --- /dev/null +++ b/nuttx/sched/sem_findnamed.c @@ -0,0 +1,100 @@ +/************************************************************************ + * sem_findnamed.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +#include "sem_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sem_findnamed + * + * Description: + * Search the g_nsems list to find the semaphore with the matching name. + * + * Parameters: + * name - semaphore name + * + * Return Value: + * Pointer to the semaphore or NULL if not found + * + ************************************************************************/ + +FAR nsem_t *sem_findnamed(const char *name) +{ + FAR nsem_t *psem; + + /* Search the list of named semaphores */ + + for (psem = (FAR nsem_t*)g_nsems.head; (psem); psem = psem->flink) + { + if (!strcmp(name, psem->name)) + { + break; + } + } + + return(psem); +} + diff --git a/nuttx/sched/sem_holder.c b/nuttx/sched/sem_holder.c new file mode 100644 index 0000000000..6003c563dc --- /dev/null +++ b/nuttx/sched/sem_holder.c @@ -0,0 +1,914 @@ +/**************************************************************************** + * sched/sem_holder.c + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" + +#ifdef CONFIG_PRIORITY_INHERITANCE + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_SEM_PREALLOCHOLDERS +# define CONFIG_SEM_PREALLOCHOLDERS 0 +#endif + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +typedef int (*holderhandler_t)(FAR struct semholder_s *pholder, + FAR sem_t *sem, FAR void *arg); + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/* Preallocated holder structures */ + +#if CONFIG_SEM_PREALLOCHOLDERS > 0 +static struct semholder_s g_holderalloc[CONFIG_SEM_PREALLOCHOLDERS]; +static FAR struct semholder_s *g_freeholders; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_allocholder + ****************************************************************************/ + +static inline FAR struct semholder_s *sem_allocholder(sem_t *sem) +{ + FAR struct semholder_s *pholder; + + /* Check if the "built-in" holder is being used. We have this built-in + * holder to optimize for the simplest case where semaphores are only + * used to implement mutexes. + */ + + if (!sem->hlist.holder) + { + pholder = &sem->hlist; + pholder->counts = 0; + } + else + { +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + pholder = g_freeholders; + if (pholder) + { + /* Remove the holder from the free list an put it into the semaphore's holder list */ + + g_freeholders = pholder->flink; + pholder->flink = sem->hlist.flink; + sem->hlist.flink = pholder; + + /* Make sure the initial count is zero */ + + pholder->counts = 0; + } + else +#else + pholder = NULL; +#endif + sdbg("Insufficient pre-allocated holders\n"); + } + + return pholder; +} + +/**************************************************************************** + * Name: sem_findholder + ****************************************************************************/ + +static FAR struct semholder_s *sem_findholder(sem_t *sem, FAR _TCB *htcb) +{ + FAR struct semholder_s *pholder; + + /* Try to find the holder in the list of holders associated with this semaphore */ + + pholder = &sem->hlist; +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + for (; pholder; pholder = pholder->flink) +#endif + { + if (pholder->holder == htcb) + { + /* Got it! */ + + return pholder; + } + } + + /* The holder does not appear in the list */ + + return NULL; +} + +/**************************************************************************** + * Name: sem_findorallocateholder + ****************************************************************************/ + +static inline FAR struct semholder_s *sem_findorallocateholder(sem_t *sem, FAR _TCB *htcb) +{ + FAR struct semholder_s *pholder = sem_findholder(sem, htcb); + if (!pholder) + { + pholder = sem_allocholder(sem); + } + + return pholder; +} + +/**************************************************************************** + * Name: sem_freeholder + ****************************************************************************/ + +static inline void sem_freeholder(sem_t *sem, FAR struct semholder_s *pholder) +{ +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + FAR struct semholder_s *curr; + FAR struct semholder_s *prev; +#endif + + /* Release the holder and counts */ + + pholder->holder = 0; + pholder->counts = 0; + +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + /* If this is the holder inside the semaphore, then do nothing more */ + + if (pholder != &sem->hlist) + { + /* Otherwise, search the list for the matching holder */ + + for (prev = &sem->hlist, curr = sem->hlist.flink; + curr && curr != pholder; + prev = curr, curr = curr->flink); + + if (curr) + { + /* Remove the holder from the list */ + + prev->flink = pholder->flink; + + /* And put it in the free list */ + + pholder->flink = g_freeholders; + g_freeholders = pholder; + } + } +#endif +} + +/**************************************************************************** + * Name: sem_foreachholder + ****************************************************************************/ + +static int sem_foreachholder(FAR sem_t *sem, holderhandler_t handler, FAR void *arg) +{ + FAR struct semholder_s *pholder = &sem->hlist; +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + FAR struct semholder_s *next; +#endif + int ret = 0; + +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + for (; pholder && ret == 0; pholder = next) +#endif + { +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + /* In case this holder gets deleted */ + + next = pholder->flink; +#endif + /* The initial "built-in" container may hold a NULL holder */ + + if (pholder->holder) + { + /* Call the handler */ + + ret = handler(pholder, sem, arg); + } + } + + return ret; +} + +/**************************************************************************** + * Name: sem_recoverholders + ****************************************************************************/ + +#if CONFIG_SEM_PREALLOCHOLDERS > 0 +static int sem_recoverholders(FAR struct semholder_s *pholder, FAR sem_t *sem, FAR void *arg) +{ + sem_freeholder(sem, pholder); + return 0; +} +#endif + +/**************************************************************************** + * Name: sem_boostholderprio + ****************************************************************************/ + +static int sem_boostholderprio(FAR struct semholder_s *pholder, + FAR sem_t *sem, FAR void *arg) +{ + FAR _TCB *htcb = (FAR _TCB *)pholder->holder; + FAR _TCB *rtcb = (FAR _TCB*)arg; + + /* Make sure that the thread is still active. If it exited without releasing + * its counts, then that would be a bad thing. But we can take no real + * action because we don't know know that the program is doing. Perhaps its + * plan is to kill a thread, then destroy the semaphore. + */ + + if (!sched_verifytcb(htcb)) + { + sdbg("TCB 0x%08x is a stale handle, counts lost\n", htcb); + sem_freeholder(sem, pholder); + } + +#if CONFIG_SEM_NNESTPRIO > 0 + + /* If the priority of the thread that is waiting for a count is greater than + * the base priority of the thread holding a count, then we may need to + * adjust the holder's priority now or later to that priority. + */ + + else if (rtcb->sched_priority > htcb->base_priority) + { + /* If the new priority is greater than the current, possibly already + * boosted priority of the holder thread, then we will have to raise + * the holder's priority now. + */ + + if (rtcb->sched_priority > htcb->sched_priority) + { + /* If the current priority has already been boosted, then add the + * boost priority to the list of restoration priorities. When the + * higher priority thread gets its count, then we need to revert + * to this saved priority, not to the base priority. + */ + + if (htcb->sched_priority > htcb->base_priority) + { + /* Save the current, boosted priority */ + + if (htcb->npend_reprio < CONFIG_SEM_NNESTPRIO) + { + htcb->pend_reprios[htcb->npend_reprio] = htcb->sched_priority; + htcb->npend_reprio++; + } + else + { + sdbg("CONFIG_SEM_NNESTPRIO exceeded\n"); + } + } + + /* Raise the priority of the holder of the semaphore. This + * cannot cause a context switch because we have preemption + * disabled. The task will be marked "pending" and the switch + * will occur during up_block_task() processing. + */ + + (void)sched_setpriority(htcb, rtcb->sched_priority); + } + else + { + /* The new priority is above the base priority of the holder, + * but not as high as its current working priority. Just put it + * in the list of pending restoration priorities so that when the + * higher priority thread gets its count, we can revert to this + * saved priority and not to the base priority. + */ + + htcb->pend_reprios[htcb->npend_reprio] = rtcb->sched_priority; + htcb->npend_reprio++; + } + } + +#else + /* If the priority of the thread that is waiting for a count is less than + * of equal to the priority of the thread holding a count, then do nothing + * because the thread is already running at a sufficient priority. + */ + + else if (rtcb->sched_priority > htcb->sched_priority) + { + /* Raise the priority of the holder of the semaphore. This + * cannot cause a context switch because we have preemption + * disabled. The task will be marked "pending" and the switch + * will occur during up_block_task() processing. + */ + + (void)sched_setpriority(htcb, rtcb->sched_priority); + } +#endif + + return 0; +} + +/**************************************************************************** + * Name: sem_verifyholder + ****************************************************************************/ + +#ifdef CONFIG_DEBUG +static int sem_verifyholder(FAR struct semholder_s *pholder, FAR sem_t *sem, FAR void *arg) +{ +#if 0 // Need to revisit this, but these assumptions seem to be untrue -- OR there is a bug??? + FAR _TCB *htcb = (FAR _TCB *)pholder->holder; + + /* Called after a semaphore has been released (incremented), the semaphore + * could is non-negative, and there is no thread waiting for the count. + * In this case, the priority of the holder should not be boosted. + */ + +#if CONFIG_SEM_NNESTPRIO > 0 + DEBUGASSERT(htcb->npend_reprio == 0); +#endif + DEBUGASSERT(htcb->sched_priority == htcb->base_priority); +#endif + return 0; +} +#endif + +/**************************************************************************** + * Name: sem_dumpholder + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_SEM_PHDEBUG) +static int sem_dumpholder(FAR struct semholder_s *pholder, FAR sem_t *sem, FAR void *arg) +{ +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + dbg(" %08x: %08x %08x %04x\n", + pholder, pholder->flink, pholder->holder, pholder->counts); +#else + dbg(" %08x: %08x %04x\n", pholder, pholder->holder, pholder->counts); +#endif + return 0; +} +#endif + +/**************************************************************************** + * Name: sem_restoreholderprio + ****************************************************************************/ + +static int sem_restoreholderprio(FAR struct semholder_s *pholder, FAR sem_t *sem, FAR void *arg) +{ + FAR _TCB *htcb = (FAR _TCB *)pholder->holder; +#if CONFIG_SEM_NNESTPRIO > 0 + FAR _TCB *stcb = (FAR _TCB *)arg; + int rpriority; + int i; + int j; +#endif + + /* Make sure that the thread is still active. If it exited without releasing + * its counts, then that would be a bad thing. But we can take no real + * action because we don't know know that the program is doing. Perhaps its + * plan is to kill a thread, then destroy the semaphore. + */ + + if (!sched_verifytcb(htcb)) + { + sdbg("TCB 0x%08x is a stale handle, counts lost\n", htcb); + sem_freeholder(sem, pholder); + } + + /* Was the priority of this thread boosted? If so, then drop its priority + * back to the correct level. + */ + + else if (htcb->sched_priority != htcb->base_priority) + { +#if CONFIG_SEM_NNESTPRIO > 0 + /* Are there other, pending priority levels to revert to? */ + + if (htcb->npend_reprio < 1) + { + /* No... the thread has only been boosted once. Reset all priorities + * back to the base priority. + */ + + DEBUGASSERT(htcb->sched_priority == stcb->sched_priority && htcb->npend_reprio == 0); + sched_reprioritize(htcb, htcb->base_priority); + } + + /* There are multiple pending priority levels. The thread's "boosted" + * priority could greater than or equal to "stcb->sched_priority" (it could be + * greater if its priority we boosted becuase it also holds another semaphore. + */ + + else if (htcb->sched_priority <= stcb->sched_priority) + { + /* The thread has been boosted to the same priority as the task + * that just received the count. We will simply reprioritized + * to the next highest priority that we have in rpriority. + */ + + /* Find the highest pending priority and remove it from the list */ + + for (i = 1, j = 0; i < htcb->npend_reprio; i++) + { + if (htcb->pend_reprios[i] > htcb->pend_reprios[j]) + { + j = i; + } + } + + /* Remove the highest priority pending priority from the list */ + + rpriority = htcb->pend_reprios[j]; + i = htcb->npend_reprio - 1; + if (i > 0) + { + htcb->pend_reprios[j] = htcb->pend_reprios[i]; + } + + htcb->npend_reprio = i; + + /* And apply that priority to the thread (while retaining the base_priority) */ + + sched_setpriority(htcb, rpriority); + } + else + { + /* The thread has been boosted to a higher priority than the task. The + * pending priority should be in he list (unless it was lost because of + * of list overflow). + * + * Search the list for the matching priority. + */ + + for (i = 0; i < htcb->npend_reprio; i++) + { + /* Does this pending priority match the priority of the thread + * that just received the count? + */ + + if (htcb->pend_reprios[i] == stcb->sched_priority) + { + /* Yes, remove it from the list */ + + j = htcb->npend_reprio - 1; + if (j > 0) + { + htcb->pend_reprios[i] = htcb->pend_reprios[j]; + } + htcb->npend_reprio = j; + break; + } + } + } +#else + /* There is no alternative restore priorities, drop the priority + * all the way back to the threads "base" priority. + */ + + sched_reprioritize(htcb, htcb->base_priority); +#endif + } + + return 0; +} + +/**************************************************************************** + * Name: sem_restoreholderprioA & B + ****************************************************************************/ + +static int sem_restoreholderprioA(FAR struct semholder_s *pholder, FAR sem_t *sem, FAR void *arg) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + if (pholder->holder != rtcb) + { + return sem_restoreholderprio(pholder, sem, arg); + } + + return 0; +} + +static int sem_restoreholderprioB(FAR struct semholder_s *pholder, FAR sem_t *sem, FAR void *arg) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + if (pholder->holder == rtcb) + { + (void)sem_restoreholderprio(pholder, sem, arg); + return 1; + } + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_initholders + * + * Description: + * Called from sem_initialize() to set up semaphore holder information. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void sem_initholders(void) +{ +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + int i; + + /* Put all of the pre-allocated holder structures into free list */ + + g_freeholders = g_holderalloc; + for (i = 0; i < (CONFIG_SEM_PREALLOCHOLDERS-1); i++) + { + g_holderalloc[i].flink = &g_holderalloc[i+1]; + } + g_holderalloc[CONFIG_SEM_PREALLOCHOLDERS-1].flink = NULL; +#endif +} + +/**************************************************************************** + * Name: sem_destroyholder + * + * Description: + * Called from sem_destroy() to handle any holders of a semaphore when + * it is destroyed. + * + * Parameters: + * sem - A reference to the semaphore being destroyed + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void sem_destroyholder(FAR sem_t *sem) +{ + /* It is an error is a semaphore is destroyed while there are any holders + * (except perhaps the thread releas the semaphore itself). Hmmm.. but + * we actually have to assume that the caller knows what it is doing because + * could have killed another thread that is the actual holder of the semaphore. + * We cannot make any assumptions about the state of the semaphore or the + * state of any of the holder threads. + * + * So just recover any stranded holders and hope the task knows what it is + * doing. + */ + +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + if (sem->hlist.holder || sem->hlist.flink) + { + sdbg("Semaphore destroyed with holders\n"); + (void)sem_foreachholder(sem, sem_recoverholders, NULL); + } +#else + if (sem->hlist.holder) + { + sdbg("Semaphore destroyed with holder\n"); + } + + sem->hlist.holder = NULL; +#endif +} + +/**************************************************************************** + * Name: sem_addholder + * + * Description: + * Called from sem_wait() when the calling thread obtains the semaphore + * + * Parameters: + * sem - A reference to the incremented semaphore + * + * Return Value: + * 0 (OK) or -1 (ERROR) if unsuccessful + * + * Assumptions: + * + ****************************************************************************/ + +void sem_addholder(FAR sem_t *sem) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR struct semholder_s *pholder; + + /* Find or allocate a container for this new holder */ + + pholder = sem_findorallocateholder(sem, rtcb); + if (pholder) + { + /* Then set the holder and increment the number of counts held by this holder */ + + pholder->holder = rtcb; + pholder->counts++; + } +} + +/**************************************************************************** + * Name: void sem_boostpriority(sem_t *sem) + * + * Description: + * + * + * Parameters: + * None + * + * Return Value: + * 0 (OK) or -1 (ERROR) if unsuccessful + * + * Assumptions: + * + ****************************************************************************/ + +void sem_boostpriority(FAR sem_t *sem) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + + /* Boost the priority of every thread holding counts on this semaphore + * that are lower in priority than the new thread that is waiting for a + * count. + */ + + (void)sem_foreachholder(sem, sem_boostholderprio, rtcb); +} + +/**************************************************************************** + * Name: sem_releaseholder + * + * Description: + * Called from sem_post() after a thread releases one count on the + * semaphore. + * + * Parameters: + * sem - A reference to the semaphore being posted + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void sem_releaseholder(FAR sem_t *sem) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR struct semholder_s *pholder; + + /* Find the container for this holder */ + + pholder = sem_findholder(sem, rtcb); + if (pholder && pholder->counts > 0) + { + /* Decrement the counts on this holder -- the holder will be freed + * later in sem_restorebaseprio. + */ + + pholder->counts--; + } +} + +/**************************************************************************** + * Name: sem_restorebaseprio + * + * Description: + * This function is called after the current running task releases a + * count on the semaphore. It will check if we need to drop the priority + * of any threads holding a count on the semaphore. Their priority could + * have been boosted while they held the count. + * + * Parameters: + * stcb - The TCB of the task that was just started (if any). If the + * post action caused a count to be given to another thread, then stcb + * is the TCB that received the count. Note, just because stcb received + * the count, it does not mean that it it is higher priority than other + * threads. + * sem - A reference to the semaphore being posted. + * - If the semaphore count is <0 then there are still threads waiting + * for a count. stcb should be non-null and will be higher priority + * than all of the other threads still waiting. + * - If it is ==0 then stcb refers to the thread that got the last count; + * no other threads are waiting. + * - If it is >0 then there should be no threads waiting for counts and + * stcb should be null. + * + * Return Value: + * 0 (OK) or -1 (ERROR) if unsuccessful + * + * Assumptions: + * The scheduler is locked. + * + ****************************************************************************/ + +void sem_restorebaseprio(FAR _TCB *stcb, FAR sem_t *sem) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR struct semholder_s *pholder; + + /* Check our assumptions */ + + DEBUGASSERT((sem->semcount > 0 && stcb == NULL) || + (sem->semcount <= 0 && stcb != NULL)); + + /* Perfom the following actions only if a new thread was given a count. */ + + if (stcb) + { + /* The currently executed thread should be the low priority + * thread that just posted the count and caused this action. + * However, we cannot drop the priority of the currently running + * thread -- becuase that will cause it to be suspended. + * + * So, do this in two passes. First, reprioritizing all holders + * except for the running thread. + */ + + (void)sem_foreachholder(sem, sem_restoreholderprioA, stcb); + + /* Now, find an reprioritize only the ready to run task */ + + (void)sem_foreachholder(sem, sem_restoreholderprioB, stcb); + } + + /* If there are no tasks waiting for available counts, then all holders + * should be at their base priority. + */ + +#ifdef CONFIG_DEBUG + else + { + (void)sem_foreachholder(sem, sem_verifyholder, NULL); + } +#endif + + /* In any case, the currently execuing task should have an entry in the + * list. Its counts were previously decremented; if it now holds no + * counts, then we need to remove it from the list of holders. + */ + + pholder = sem_findholder(sem, rtcb); + if (pholder) + { + /* When no more counts are held, remove the holder from the list. The + * count was decremented in sem_releaseholder. + */ + + if (pholder->counts <= 0) + { + sem_freeholder(sem, pholder); + } + } +} + +/**************************************************************************** + * Name: sem_canceled + * + * Description: + * Called from sem_waitirq() after a thread that was waiting for a semaphore + * count was awakened because of a signal and the semaphore wait has been + * canceled. This function restores the correct thread priority of each + * holder of the semaphore. + * + * Parameters: + * sem - A reference to the semaphore no longer being waited for + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_SIGNALS +void sem_canceled(FAR _TCB *stcb, FAR sem_t *sem) +{ + /* Check our assumptions */ + + DEBUGASSERT(sem->semcount <= 0); + + /* Adjust the priority of every holder as necessary */ + + (void)sem_foreachholder(sem, sem_restoreholderprio, stcb); +} +#endif + +/**************************************************************************** + * Name: sem_enumholders + * + * Description: + * Show information about threads currently waiting on this semaphore + * + * Parameters: + * sem - A reference to the semaphore + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_SEM_PHDEBUG) +void sem_enumholders(FAR sem_t *sem) +{ + (void)sem_foreachholder(sem, sem_dumpholder, NULL); +} +#endif + +/**************************************************************************** + * Name: sem_nfreeholders + * + * Description: + * Return the number of available holder containers. This is a good way + * to find out which threads are not calling sem_destroy. + * + * Parameters: + * sem - A reference to the semaphore + * + * Return Value: + * The number of available holder containers + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_SEM_PHDEBUG) +int sem_nfreeholders(void) +{ +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + FAR struct semholder_s *pholder; + int n; + + for (pholder = g_freeholders, n = 0; pholder; pholder = pholder->flink) n++; + return n; +#else + return 0; +#endif +} +#endif + +#endif /* CONFIG_PRIORITY_INHERITANCE */ diff --git a/nuttx/sched/sem_initialize.c b/nuttx/sched/sem_initialize.c new file mode 100644 index 0000000000..d8b402825a --- /dev/null +++ b/nuttx/sched/sem_initialize.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * schec/sem_initialize.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "sem_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* This is a list of dyanamically allocated named semaphores */ + +dq_queue_t g_nsems; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_initialize + * + * Description: + * The control structures for all semaphores may be initialized by calling + * sem_initialize(). This should be done once at poweron. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void sem_initialize(void) +{ + /* Initialize the queue of named semaphores */ + + dq_init(&g_nsems); + + /* Initialize holder structures needed to support priority inheritiance */ + + sem_initholders(); +} diff --git a/nuttx/sched/sem_internal.h b/nuttx/sched/sem_internal.h new file mode 100644 index 0000000000..434c551a4c --- /dev/null +++ b/nuttx/sched/sem_internal.h @@ -0,0 +1,131 @@ +/**************************************************************************** + * sched/sem_internal.h + * + * Copyright (C) 2007, 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __SCHED_SEM_INTERNAL_H +#define __SCHED_SEM_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Declarations + ****************************************************************************/ + +/* This is the named semaphore structure */ + +struct nsem_s +{ + FAR struct nsem_s *flink; /* Forward link */ + FAR struct nsem_s *blink; /* Backward link */ + uint16_t nconnect; /* Number of connections to semaphore */ + FAR char *name; /* Semaphore name (NULL if un-named) */ + bool unlinked; /* true if the semaphore has been unlinked */ + sem_t sem; /* The semaphore itself */ +}; + +typedef struct nsem_s nsem_t; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* This is a list of dyanamically allocated named semaphores */ + +extern dq_queue_t g_nsems; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Common semaphore logic */ + +EXTERN void weak_function sem_initialize(void); +EXTERN void sem_waitirq(FAR _TCB *wtcb, int errcode); +EXTERN FAR nsem_t *sem_findnamed(const char *name); + +/* Special logic needed only by priority inheritance to manage collections of + * holders of semaphores. + */ + +#ifdef CONFIG_PRIORITY_INHERITANCE +EXTERN void sem_initholders(void); +EXTERN void sem_destroyholder(FAR sem_t *sem); +EXTERN void sem_addholder(FAR sem_t *sem); +EXTERN void sem_boostpriority(FAR sem_t *sem); +EXTERN void sem_releaseholder(FAR sem_t *sem); +EXTERN void sem_restorebaseprio(FAR _TCB *stcb, FAR sem_t *sem); +# ifndef CONFIG_DISABLE_SIGNALS +EXTERN void sem_canceled(FAR _TCB *stcb, FAR sem_t *sem); +# else +# define sem_canceled(stcb, sem) +# endif +#else +# define sem_initholders() +# define sem_destroyholder(sem) +# define sem_addholder(sem) +# define sem_boostpriority(sem) +# define sem_releaseholder(sem) +# define sem_restorebaseprio(stcb,sem) +# define sem_canceled(stcb, sem) +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __SCHED_SEM_INTERNAL_H */ + diff --git a/nuttx/sched/sem_open.c b/nuttx/sched/sem_open.c new file mode 100644 index 0000000000..817c36b49b --- /dev/null +++ b/nuttx/sched/sem_open.c @@ -0,0 +1,209 @@ +/**************************************************************************** + * sched/sem_open.c + * + * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "sem_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_open + * + * Description: + * This function establishes a connection between named semaphores and a + * task. Following a call to sem_open() with the semaphore name, the task + * may reference the semaphore associated with name using the address + * returned by this call. The semaphore may be used in subsequent calls + * to sem_wait(), sem_trywait(), and sem_post(). The semaphore remains + * usable until the semaphore is closed by a successful call to sem_close(). + * + * If a task makes multiple calls to sem_open() with the same name, then + * the same semaphore address is returned (provided there have been no + * calls to sem_unlink()). + * + * Parameters: + * name - Semaphore name + * oflag - Semaphore creation options. This may either or both of the + * following bit settings. + * oflag = 0: Connect to the semaphore only if it already exists. + * oflag = O_CREAT: Connect to the semaphore if it exists, otherwise + * create the semaphore. + * oflag = O_CREAT|O_EXCL: Create a new semaphore + * unless one of this name already exists. + * Optional parameters. When the O_CREAT flag is specified, two optional + * parameters are expected: + * 1. mode_t mode (ignored), and + * 2. unsigned int value. This initial value of the semaphore. Valid + * initial values of the semaphore must be less than or equal to + * SEM_VALUE_MAX. + * + * Return Value: + * A pointer to sem_t or -1 (ERROR) if unsuccessful. + * + * Assumptions: + * + ****************************************************************************/ + +FAR sem_t *sem_open (FAR const char *name, int oflag, ...) +{ + int namelen; + FAR nsem_t *psem; + FAR sem_t *sem = (FAR sem_t*)ERROR; + va_list arg; /* Points to each un-named argument */ + mode_t mode; /* Creation mode parameter (ignored) */ + unsigned int value; /* Semaphore value parameter */ + + /* Make sure that a non-NULL name is supplied */ + + if (name) + { + /* The POSIX specification requires that the "check for the + * existence of a semaphore and the creation of the semaphore + * if it does not exist shall be atomic with respect to other + * processes executing sem_open()..." A simple sched_lock() + * should be sufficient to meet this requirement. + */ + + sched_lock(); + namelen = strlen(name); + if (namelen > 0) + { + /* See if the semaphore already exists */ + + psem = sem_findnamed(name); + if (psem) + { + /* It does. Check if the caller wanted to created + * a new semahore with this name. + */ + + if (!(oflag & O_CREAT) || !(oflag & O_EXCL)) + { + /* Allow a new connection to the semaphore */ + + psem->nconnect++; + sem = &psem->sem; + } + } + + /* It doesn't exist. Should we create one? */ + + else if ((oflag & O_CREAT) != 0) + { + /* Set up to get the optional arguments needed to create + * a message queue. + */ + + va_start(arg, oflag); + mode = va_arg(arg, mode_t); + value = va_arg(arg, unsigned int); + + /* Verify that a legal initial value was selected. */ + + if (value <= SEM_VALUE_MAX) + { + /* Allocate memory for the new semaphore */ + + psem = (FAR nsem_t*)kmalloc((sizeof(nsem_t) + namelen + 1)); + if (psem) + { + /* Initialize the named semaphore */ + + sem = &psem->sem; + sem_init(sem, 0, value); + + psem->nconnect = 1; + psem->unlinked = false; + psem->name = (FAR char*)psem + sizeof(nsem_t); + strcpy(psem->name, name); + + /* Add the new semaphore to the list of named + * semaphores + */ + + dq_addfirst((FAR dq_entry_t*)psem, &g_nsems); + } + + /* Clean-up variable argument stuff */ + + va_end(arg); + } + } + } + + sched_unlock(); + } + + return sem; +} + diff --git a/nuttx/sched/sem_post.c b/nuttx/sched/sem_post.c new file mode 100644 index 0000000000..b3780db1f6 --- /dev/null +++ b/nuttx/sched/sem_post.c @@ -0,0 +1,178 @@ +/**************************************************************************** + * sched/sem_post.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_post + * + * Description: + * When a task has finished with a semaphore, it will call sem_post(). + * This function unlocks the semaphore referenced by sem by performing the + * semaphore unlock operation on that semaphore. + * + * If the semaphore value resulting from this operation is positive, then + * no tasks were blocked waiting for the semaphore to become unlocked; the + * semaphore is simply incremented. + * + * If the value of the semaphore resulting from this operation is zero, + * then one of the tasks blocked waiting for the semaphore shall be + * allowed to return successfully from its call to sem_wait(). + * + * Parameters: + * sem - Semaphore descriptor + * + * Return Value: + * 0 (OK) or -1 (ERROR) if unsuccessful + * + * Assumptions: + * This function cannot be called from an interrupt handler. + * It assumes the currently executing task is the one that + * is performing the unlock. + * + ****************************************************************************/ + +int sem_post(FAR sem_t *sem) +{ + FAR _TCB *stcb = NULL; + int ret = ERROR; + irqstate_t saved_state; + + /* Make sure we were supplied with a valid semaphore. */ + + if (sem) + { + /* The following operations must be performed with interrupts + * disabled because sem_post() may be called from an interrupt + * handler. + */ + + saved_state = irqsave(); + + /* Perform the semaphore unlock operation. */ + + ASSERT(sem->semcount < SEM_VALUE_MAX); + sem_releaseholder(sem); + sem->semcount++; + + /* If the result of of semaphore unlock is non-positive, then + * there must be some task waiting for the semaphore. + */ + +#ifdef CONFIG_PRIORITY_INHERITANCE + /* Don't let it run until we complete the priority restoration + * steps. + */ + + sched_lock(); +#endif + if (sem->semcount <= 0) + { + /* Check if there are any tasks in the waiting for semaphore + * task list that are waiting for this semaphore. This is a + * prioritized list so the first one we encounter is the one + * that we want. + */ + + for (stcb = (FAR _TCB*)g_waitingforsemaphore.head; + (stcb && stcb->waitsem != sem); + stcb = stcb->flink); + + if (stcb) + { + /* It is, let the task take the semaphore */ + + stcb->waitsem = NULL; + + /* Restart the waiting task. */ + + up_unblock_task(stcb); + } + } + + /* Check if we need to drop the priority of any threads holding + * this semaphore. The priority could have been boosted while they + * held the semaphore. + */ + +#ifdef CONFIG_PRIORITY_INHERITANCE + sem_restorebaseprio(stcb, sem); + sched_unlock(); +#endif + ret = OK; + + /* Interrupts may now be enabled. */ + + irqrestore(saved_state); + } + + return ret; +} diff --git a/nuttx/sched/sem_timedwait.c b/nuttx/sched/sem_timedwait.c new file mode 100644 index 0000000000..6a47244068 --- /dev/null +++ b/nuttx/sched/sem_timedwait.c @@ -0,0 +1,286 @@ +/**************************************************************************** + * sched/sem_timedwait.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "clock_internal.h" +#include "sem_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_timeout + * + * Description: + * This function is called if the timeout elapses before the message queue + * becomes non-empty. + * + * Parameters: + * argc - the number of arguments (should be 1) + * pid - the task ID of the task to wakeup + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void sem_timeout(int argc, uint32_t pid) +{ + FAR _TCB *wtcb; + irqstate_t flags; + + /* Disable interrupts to avoid race conditions */ + + flags = irqsave(); + + /* Get the TCB associated with this pid. It is possible that + * task may no longer be active when this watchdog goes off. + */ + + wtcb = sched_gettcb((pid_t)pid); + + /* It is also possible that an interrupt/context switch beat us to the + * punch and already changed the task's state. + */ + + if (wtcb && wtcb->task_state == TSTATE_WAIT_SEM) + { + /* Cancel the semaphore wait */ + + sem_waitirq(wtcb, ETIMEDOUT); + } + + /* Interrupts may now be enabled. */ + + irqrestore(flags); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_timedwait + * + * Description: + * This function will lock the semaphore referenced by sem as in the + * sem_wait() function. However, if the semaphore cannot be locked without + * waiting for another process or thread to unlock the semaphore by + * performing a sem_post() function, this wait will be terminated when the + * specified timeout expires. + * + * The timeout will expire when the absolute time specified by abstime + * passes, as measured by the clock on which timeouts are based (that is, + * when the value of that clock equals or exceeds abstime), or if the + * absolute time specified by abstime has already been passed at the + * time of the call. + * + * Parameters: + * sem - Semaphore object + * abstime - The absolute time to wait until a timeout is declared. + * + * Return Value: + * One success, the length of the selected message in bytes.is + * returned. On failure, -1 (ERROR) is returned and the errno + * is set appropriately: + * + * EINVAL The sem argument does not refer to a valid semaphore. Or the + * thread would have blocked, and the abstime parameter specified + * a nanoseconds field value less than zero or greater than or + * equal to 1000 million. + * ETIMEDOUT The semaphore could not be locked before the specified timeout + * expired. + * EDEADLK A deadlock condition was detected. + * EINTR A signal interrupted this function. + * + ****************************************************************************/ + +int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) +{ + WDOG_ID wdog; + irqstate_t flags; + int ticks; + int err; + int ret = ERROR; + + DEBUGASSERT(up_interrupt_context() == false); + + /* Verify the input parameters and, in case of an error, set + * errno appropriately. + */ + +#ifdef CONFIG_DEBUG + if (!abstime || !sem) + { + err = EINVAL; + goto errout; + } +#endif + + /* Create a watchdog. We will not actually need this watchdog + * unless the the semaphore is unavailable, but we will reserve it up + * front before we enter the following critical section. + */ + + wdog = wd_create(); + if (!wdog) + { + err = ENOMEM; + goto errout; + } + + /* We will disable interrupts until we have completed the semaphore + * wait. We need to do this (as opposed to just disabling pre-emption) + * because there could be interrupt handlers that are asynchronoulsy + * posting semaphores and to prevent race conditions with watchdog + * timeout. This is not too bad because interrupts will be re- + * enabled while we are blocked waiting for the semaphore. + */ + + flags = irqsave(); + + /* Try to take the semaphore without waiting. */ + + ret = sem_trywait(sem); + if (ret == 0) + { + /* We got it! */ + + irqrestore(flags); + wd_delete(wdog); + return OK; + } + + /* We will have to wait for the semphore. Make sure that we were provided + * with a valid timeout. + */ + + if (abstime->tv_sec < 0 || abstime->tv_nsec > 1000000000) + { + err = EINVAL; + goto errout_disabled; + } + + /* Convert the timespec to clock ticks. We must have interrupts + * disabled here so that this time stays valid until the wait begins. + */ + + err = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); + + /* If the time has already expired return immediately. */ + + if (err == OK && ticks <= 0) + { + err = ETIMEDOUT; + goto errout_disabled; + } + + /* Handle any time-related errors */ + + if (err != OK) + { + goto errout_disabled; + } + + /* Start the watchdog */ + + err = OK; + wd_start(wdog, ticks, (wdentry_t)sem_timeout, 1, getpid()); + + /* Now perform the blocking wait */ + + ret = sem_wait(sem); + + /* Stop the watchdog timer */ + + wd_cancel(wdog); + + /* We can now restore interrupts and delete the watchdog */ + + irqrestore(flags); + wd_delete(wdog); + + /* We are either returning success or an error detected by sem_wait() + * or the timeout detected by sem_timeout(). The 'errno' value has + * been set appropriately by sem_wait() or sem_timeout() in those + * cases. + */ + + return ret; + +/* Error exits */ + +errout_disabled: + irqrestore(flags); + wd_delete(wdog); +errout: + set_errno(err); + return ERROR; +} diff --git a/nuttx/sched/sem_trywait.c b/nuttx/sched/sem_trywait.c new file mode 100644 index 0000000000..cbd8dae699 --- /dev/null +++ b/nuttx/sched/sem_trywait.c @@ -0,0 +1,142 @@ +/**************************************************************************** + * sched/sem_trywait.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_trywait + * + * Description: + * This function locks the specified semaphore only if the semaphore is + * currently not locked. Otherwise, it locks the semaphore. In either + * case, the call returns without blocking. + * + * Parameters: + * sem - the semaphore descriptor + * + * Return Value: + * 0 (OK) or -1 (ERROR) if unsuccessful. If this function returns -1 + * (ERROR),then the cause of the failure will be reported in "errno" as: + * + * EINVAL: Invalid attempt to get the semaphore + * EAGAIN: The semaphore is not available. + * + * Assumptions: + * + ****************************************************************************/ + +int sem_trywait(FAR sem_t *sem) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + irqstate_t saved_state; + int ret = ERROR; + + /* This API should not be called from interrupt handlers */ + + DEBUGASSERT(up_interrupt_context() == false) + + /* Assume any errors reported are due to invalid arguments. */ + + set_errno(EINVAL); + + if (sem) + { + /* The following operations must be performed with interrupts disabled + * because sem_post() may be called from an interrupt handler. + */ + + saved_state = irqsave(); + + /* Any further errors could only be occurred because the semaphore + * is not available. + */ + + set_errno(EAGAIN); + + /* If the semaphore is available, give it to the requesting task */ + + if (sem->semcount > 0) + { + /* It is, let the task take the semaphore */ + + sem->semcount--; + rtcb->waitsem = NULL; + ret = OK; + } + + /* Interrupts may now be enabled. */ + + irqrestore(saved_state); + } + + return ret; +} diff --git a/nuttx/sched/sem_unlink.c b/nuttx/sched/sem_unlink.c new file mode 100644 index 0000000000..6fe0115402 --- /dev/null +++ b/nuttx/sched/sem_unlink.c @@ -0,0 +1,140 @@ +/**************************************************************************** + * sched/sem_unlink.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_unlink + * + * Description: + * This function removes the semaphore named by the input parameter 'name.' + * If the semaphore named by 'name' is currently referenced by other task, + * the sem_unlink() will have no effect on the state of the semaphore. If + * one or more processes have the semaphore open when sem_unlink() is + * called, destruction of the semaphore will be postponed until all + * references to the semaphore have been destroyed by calls of sem_close(). + * + * Parameters: + * name - Semaphore name + * + * Return Value: + * 0 (OK), or -1 (ERROR) if unsuccessful. + * + * Assumptions: + * + ****************************************************************************/ + +int sem_unlink(FAR const char *name) +{ + FAR nsem_t *psem; + int ret = ERROR; + + /* Verify the input values */ + + if (name) + { + sched_lock(); + + /* Find the named semaphore */ + + psem = sem_findnamed(name); + + /* Check if the semaphore was found */ + + if (psem) + { + /* If the named semaphore was found and if there are no + * connects to it, then deallocate it + */ + + if (!psem->nconnect) + { + dq_rem((FAR dq_entry_t*)psem, &g_nsems); + sched_free(psem); + } + + /* If one or more process still has the semaphore open, + * then just mark it as unlinked. The unlinked semaphore will + * be deleted when the final process closes the semaphore. + */ + + else + { + psem->unlinked = true; + } + ret = OK; + } + + sched_unlock(); + } + + return ret; +} diff --git a/nuttx/sched/sem_wait.c b/nuttx/sched/sem_wait.c new file mode 100644 index 0000000000..9dfbaa6c39 --- /dev/null +++ b/nuttx/sched/sem_wait.c @@ -0,0 +1,216 @@ +/**************************************************************************** + * sched/sem_wait.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_wait + * + * Description: + * This function attempts to lock the semaphore referenced by 'sem'. If + * the semaphore value is (<=) zero, then the calling task will not return + * until it successfully acquires the lock. + * + * Parameters: + * sem - Semaphore descriptor. + * + * Return Value: + * 0 (OK), or -1 (ERROR) is unsuccessful + * If this function returns -1 (ERROR), then the cause of the failure will + * be reported in 'errno' as: + * - EINVAL: Invalid attempt to get the semaphore + * - EINTR: The wait was interrupted by the receipt of a signal. + * + * Assumptions: + * + ****************************************************************************/ + +int sem_wait(FAR sem_t *sem) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + int ret = ERROR; + irqstate_t saved_state; + + /* This API should not be called from interrupt handlers */ + + DEBUGASSERT(up_interrupt_context() == false) + + /* Assume any errors reported are due to invalid arguments. */ + + errno = EINVAL; + + if (sem) + { + /* The following operations must be performed with interrupts + * disabled because sem_post() may be called from an interrupt + * handler. + */ + + saved_state = irqsave(); + + /* Check if the lock is available */ + + if (sem->semcount > 0) + { + /* It is, let the task take the semaphore. */ + + sem->semcount--; + sem_addholder(sem); + rtcb->waitsem = NULL; + ret = OK; + } + + /* The semaphore is NOT available, We will have to block the + * current thread of execution. + */ + + else + { + /* First, verify that the task is not already waiting on a + * semaphore + */ + + if (rtcb->waitsem != NULL) + { + PANIC(OSERR_BADWAITSEM); + } + + /* Handle the POSIX semaphore (but don't set the owner yet) */ + + sem->semcount--; + + /* Save the waited on semaphore in the TCB */ + + rtcb->waitsem = sem; + + /* If priority inheritance is enabled, then check the priority of + * the holder of the semaphore. + */ + +#ifdef CONFIG_PRIORITY_INHERITANCE + /* Disable context switching. The following operations must be + * atomic with regard to the scheduler. + */ + + sched_lock(); + + /* Boost the priority of any threads holding a count on the + * semaphore. + */ + + sem_boostpriority(sem); +#endif + /* Add the TCB to the prioritized semaphore wait queue */ + + errno = 0; + up_block_task(rtcb, TSTATE_WAIT_SEM); + + /* When we resume at this point, either (1) the semaphore has been + * assigned to this thread of execution, or (2) the semaphore wait + * has been interrupted by a signal or a timeout. We can detect these + * latter cases be examining the errno value. + * + * In the event that the semaphore wait was interrupted by a signal or + * a timeout, certain semaphore clean-up operations have already been + * performed (see sem_waitirq.c). Specifically: + * + * - sem_canceled() was called to restore the priority of all threads + * that hold a reference to the semaphore, + * - The semaphore count was decremented, and + * - tcb->waitsem was nullifed. + * + * It is necesaary to do these things in sem_waitirq.c because a long + * time may elapse between the time that the signal was issued and + * this thread is awakened and this leaves a door open to several + * race conditions. + */ + + if (errno != EINTR && errno != ETIMEDOUT) + { + /* Not awakened by a signal or a timeout... We hold the semaphore */ + + sem_addholder(sem); + ret = OK; + } + +#ifdef CONFIG_PRIORITY_INHERITANCE + sched_unlock(); +#endif + } + + /* Interrupts may now be enabled. */ + + irqrestore(saved_state); + } + + return ret; +} diff --git a/nuttx/sched/sem_waitirq.c b/nuttx/sched/sem_waitirq.c new file mode 100644 index 0000000000..3d3af18de8 --- /dev/null +++ b/nuttx/sched/sem_waitirq.c @@ -0,0 +1,145 @@ +/**************************************************************************** + * sched/sem_waitirq.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "sem_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_waitirq + * + * Description: + * This function is called when a signal is received by a task that is + * waiting on a semaphore. According to the POSIX spec, "...the calling + * thread shall not return from the call to [sem_wait] until it either + * locks the semaphore or the call is interrupted by a signal." + * + * Parameters: + * wtcb - A pointer to the TCB of the task that is waiting on a + * semphaphore, but has received a signal or timeout instead. + * errcode - EINTR if the semaphore wait was awakened by a signal; + * ETIMEDOUT if awakened by a timeout + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void sem_waitirq(FAR _TCB *wtcb, int errcode) +{ + irqstate_t saved_state; + + /* Disable interrupts. This is necessary (unfortunately) because an + * interrupt handler may attempt to post the semaphore while we are + * doing this. + */ + + saved_state = irqsave(); + + /* It is possible that an interrupt/context switch beat us to the punch + * and already changed the task's state. + */ + + if (wtcb->task_state == TSTATE_WAIT_SEM) + { + sem_t *sem = wtcb->waitsem; + DEBUGASSERT(sem != NULL && sem->semcount < 0); + + /* Restore the correct priority of all threads that hold references + * to this semaphore. + */ + + sem_canceled(wtcb, sem); + + /* And increment the count on the semaphore. This releases the count + * that was taken by sem_post(). This count decremented the semaphore + * count to negative and caused the thread to be blocked in the first + * place. + */ + + sem->semcount++; + + /* Indicate that the semaphore wait is over. */ + + wtcb->waitsem = NULL; + + /* Mark the errno value for the thread. */ + + wtcb->pterrno = errcode; + + /* Restart the task. */ + + up_unblock_task(wtcb); + } + + /* Interrupts may now be enabled. */ + + irqrestore(saved_state); +} + diff --git a/nuttx/sched/sig_action.c b/nuttx/sched/sig_action.c new file mode 100644 index 0000000000..fef5f15586 --- /dev/null +++ b/nuttx/sched/sig_action.c @@ -0,0 +1,272 @@ +/**************************************************************************** + * sched/sig_action.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define COPY_SIGACTION(t,f) \ + { (t)->sa_sigaction = (f)->sa_sigaction; \ + (t)->sa_mask = (f)->sa_mask; \ + (t)->sa_flags = (f)->sa_flags; } + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sig_allocateaction + * + * Description: + * Allocate a new element for a sigaction queue + * + ****************************************************************************/ + +static FAR sigactq_t *sig_allocateaction(void) +{ + FAR sigactq_t *sigact; + + /* Try to get the signal action structure from the free list */ + + sigact = (FAR sigactq_t*)sq_remfirst(&g_sigfreeaction); + + /* Check if we got one. */ + + if (!sigact) + { + /* Add another block of signal actions to the list */ + + sig_allocateactionblock(); + + /* And try again */ + + sigact = (FAR sigactq_t*)sq_remfirst(&g_sigfreeaction); + if (!sigact) + { + PANIC(OSERR_OUTOFMEMORY); + } + } + + return sigact; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigaction + * + * Description: + * This function allows the calling process to examine and/or specify the + * action to be associated with a specific signal. + * + * The structure sigaction, used to describe an action to be taken, is + * defined to include the following members: + * + * - sa_u.sa_handler: Pointer to a signal-catching function + * - sa_u.sa_sigaction: Alternative form of the signal-catching function + * - sa_mask: An additional set of signals to be blocked during execution + * of a signal catching function + * - sa_flags. Special flags to affect the behavior of a signal. + * + * If the argument 'act' is not NULL, it points to a structure specifying + * the action to be associated with the specified signal. If the argument + * 'oact' is not NULL, the action previously associated with the signal + * is stored in the location pointed to by the argument 'oact.' + * + * When a signal is caught by a signal-catching function installed by + * sigaction() function, a new signal mask is calculated and installed for + * the duration of the signal-catching function. This mask is formed by + * taking the union of the current signal mask and the value of the + * sa_mask for the signal being delivered and then including the signal + * being delivered. If and when the user's signal handler returns, the + * original signal mask is restored. + * + * Once an action is installed for a specific signal, it remains installed + * until another action is explicitly requested by another call to sigaction(). + * + * Parameters: + * sig - Signal of interest + * act - Location of new handler + * oact - Location to store only handler + * + * Return Value: + * 0 (OK), or -1 (ERROR) if the signal number is invalid. + * (errno is not set) + * + * Assumptions: + * + * POSIX Compatibility: + * - Special values of sa_handler in the struct sigaction + * act input not handled (SIG_DFL, SIG_IGN). + * - All sa_flags in struct sigaction of act input are + * ignored (all treated like SA_SIGINFO). + * + ****************************************************************************/ + +int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *oact) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR sigactq_t *sigact; + int ret = ERROR; /* Assume failure */ + + /* Since sigactions can only be installed from the running thread of + * execution, no special precautions should be necessary. + */ + + /* Verify the signal */ + + if (GOOD_SIGNO(signo)) + { + ret = OK; /* Assume success */ + + /* Find the signal in the sigactionq */ + + sigact = sig_findaction(rtcb, signo); + + /* Return the old sigaction value if so requested */ + + if (oact) + { + if (sigact) + { + COPY_SIGACTION(oact, &sigact->act); + } + else + { + /* There isn't an old value */ + + oact->sa_u._sa_handler = NULL; + oact->sa_mask = NULL_SIGNAL_SET; + oact->sa_flags = 0; + } + } + + /* If no sigaction was found, but one is needed, then + * allocate one. + */ + + if (!sigact && act && act->sa_u._sa_handler) + { + sigact = sig_allocateaction(); + + /* An error has occurred if we could not allocate the sigaction */ + + if (!sigact) + { + ret = ERROR; + } + else + { + /* Put the signal number in the queue entry */ + + sigact->signo = (uint8_t)signo; + + /* Add the new sigaction to sigactionq */ + + sq_addlast((FAR sq_entry_t*)sigact, &rtcb->sigactionq); + } + } + + /* Set the new sigaction if so requested */ + + if ((sigact) && (act)) + { + /* Check if it is a request to install a new handler */ + + if (act->sa_u._sa_handler) + { + COPY_SIGACTION(&sigact->act, act); + } + + /* No.. It is a request to remove the old handler */ + + else + { + /* Remove the old sigaction from sigactionq */ + + sq_rem((FAR sq_entry_t*)sigact, &rtcb->sigactionq); + + /* And deallocate it */ + + sig_releaseaction(sigact); + } + } + } + + return ret; +} + +/**************************************************************************** + * Name: sig_releaseaction + * + * Description: + * Deallocate a sigaction Q entry + * + ****************************************************************************/ + +void sig_releaseaction(FAR sigactq_t *sigact) +{ + /* Just put it back on the free list */ + + sq_addlast((FAR sq_entry_t*)sigact, &g_sigfreeaction); +} diff --git a/nuttx/sched/sig_allocatependingsigaction.c b/nuttx/sched/sig_allocatependingsigaction.c new file mode 100644 index 0000000000..15d6470cae --- /dev/null +++ b/nuttx/sched/sig_allocatependingsigaction.c @@ -0,0 +1,137 @@ +/************************************************************************ + * sched/sig_allocatependingsigaction.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_allocatependingsigaction + * + * Description: + * Allocate a new element for the pending signal action queue + * + ************************************************************************/ + +FAR sigq_t *sig_allocatependingsigaction(void) +{ + FAR sigq_t *sigq; + irqstate_t saved_state; + + /* Check if we were called from an interrupt handler. */ + + if (up_interrupt_context()) + { + /* Try to get the pending signal action structure from the free list */ + + sigq = (FAR sigq_t*)sq_remfirst(&g_sigpendingaction); + + /* If so, then try the special list of structures reserved for + * interrupt handlers + */ + + if (!sigq) + { + sigq = (FAR sigq_t*)sq_remfirst(&g_sigpendingirqaction); + } + } + + /* If we were not called from an interrupt handler, then we are + * free to allocate pending signal action structures if necessary. */ + + else + { + /* Try to get the pending signal action structure from the free list */ + + saved_state = irqsave(); + sigq = (FAR sigq_t*)sq_remfirst(&g_sigpendingaction); + irqrestore(saved_state); + + /* Check if we got one. */ + + if (!sigq) + { + /* No...Try the resource pool */ + + if (!sigq) + { + sigq = (FAR sigq_t *)kmalloc((sizeof (sigq_t))); + } + + /* Check if we got an allocated message */ + + if (sigq) + { + sigq->type = SIG_ALLOC_DYN; + } + } + } + + return sigq; +} + diff --git a/nuttx/sched/sig_cleanup.c b/nuttx/sched/sig_cleanup.c new file mode 100644 index 0000000000..4dcc04f8be --- /dev/null +++ b/nuttx/sched/sig_cleanup.c @@ -0,0 +1,118 @@ +/************************************************************************ + * sched/sig_cleanup.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_cleanup + * + * Description: + * Deallocate all signal-related lists in a TCB. This function is + * called only at task deletion time. The caller is expected to have + * assured the critical section necessary to perform this action. + * + ************************************************************************/ + +void sig_cleanup(FAR _TCB *stcb) +{ + FAR sigactq_t *sigact; + FAR sigq_t *sigq; + FAR sigpendq_t *sigpend; + + /* Deallocate all entries in the list of signal actions */ + + while ((sigact = (FAR sigactq_t*)sq_remfirst(&stcb->sigactionq)) != NULL) + { + sig_releaseaction(sigact); + } + + /* Deallocate all entries in the list of pending signals */ + + while ((sigpend = (FAR sigpendq_t*)sq_remfirst(&stcb->sigpendingq)) != NULL) + { + sig_releasependingsignal(sigpend); + } + + /* Deallocate all entries in the list of pending signal actions */ + + while ((sigq = (FAR sigq_t*)sq_remfirst(&stcb->sigpendactionq)) != NULL) + { + sig_releasependingsigaction(sigq); + } + + /* Deallocate all entries in the list of posted signal actions */ + + while ((sigq = (FAR sigq_t*)sq_remfirst(&stcb->sigpostedq)) != NULL) + { + sig_releasependingsigaction(sigq); + } + + /* Misc. signal-related clean-up */ + + stcb->sigprocmask = ALL_SIGNAL_SET; + stcb->sigwaitmask = NULL_SIGNAL_SET; +} diff --git a/nuttx/sched/sig_deliver.c b/nuttx/sched/sig_deliver.c new file mode 100644 index 0000000000..a1297fbc28 --- /dev/null +++ b/nuttx/sched/sig_deliver.c @@ -0,0 +1,159 @@ +/**************************************************************************** + * sched/sig_deliver.c + * + * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sig_deliver + * + * Description: + * This function is called on the thread of execution of the signal + * receiving task. It processes all queued signals then returns. + * + ****************************************************************************/ + +void sig_deliver(FAR _TCB *stcb) +{ + FAR sigq_t *sigq; + FAR sigq_t *next; + sigset_t savesigprocmask; + irqstate_t saved_state; + int saved_errno; + + sched_lock(); + + /* Save the thread errno. When we finished dispatching the + * signal actions and resume the task, the errno value must + * be unchanged by the operation of the signal handling. In + * particular, the EINTR indication that says that the task + * was reawakened by a signal must be retained. + */ + + saved_errno = stcb->pterrno; + for (sigq = (FAR sigq_t*)stcb->sigpendactionq.head; (sigq); sigq = next) + { + next = sigq->flink; + sdbg("Sending signal sigq=0x%x\n", sigq); + + /* Remove the signal structure from the sigpendactionq and place it + * in the sigpostedq. NOTE: Since signals are processed one at a + * time, there should never be more than one signal in the sigpostedq + */ + + saved_state = irqsave(); + sq_rem((FAR sq_entry_t*)sigq, &(stcb->sigpendactionq)); + sq_addlast((FAR sq_entry_t*)sigq, &(stcb->sigpostedq)); + irqrestore(saved_state); + + /* Call the signal handler (unless the signal was cancelled) + * + * Save a copy of the old sigprocmask and install the new + * (temporary) sigprocmask. The new sigprocmask is the union + * of the current sigprocmask and the sa_mask for the signal being + * delivered plus the signal being delivered. + */ + + savesigprocmask = stcb->sigprocmask; + stcb->sigprocmask = savesigprocmask | sigq->mask | SIGNO2SET(sigq->info.si_signo); + + /* Deliver the signal */ + + (*sigq->action.sighandler)(sigq->info.si_signo, &sigq->info, NULL); + + /* Restore the original sigprocmask */ + + stcb->sigprocmask = savesigprocmask; + + /* Now, handle the (rare?) case where (a) a blocked signal was + * received while the signal handling executed but (b) restoring the + * original sigprocmask will unblock the signal. + */ + + sig_unmaskpendingsignal(); + + /* Remove the signal from the sigpostedq */ + + saved_state = irqsave(); + sq_rem((FAR sq_entry_t*)sigq, &(stcb->sigpostedq)); + irqrestore(saved_state); + + /* Then deallocate it */ + + sig_releasependingsigaction(sigq); + } + + stcb->pterrno = saved_errno; + sched_unlock(); +} + diff --git a/nuttx/sched/sig_findaction.c b/nuttx/sched/sig_findaction.c new file mode 100644 index 0000000000..4115332b64 --- /dev/null +++ b/nuttx/sched/sig_findaction.c @@ -0,0 +1,100 @@ +/************************************************************************ + * sched/sig_findaction.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_findaction + * + * Description: + * Allocate a new element for a signal queue + * + ************************************************************************/ + +FAR sigactq_t *sig_findaction(FAR _TCB *stcb, int signo) +{ + FAR sigactq_t *sigact = NULL; + + /* Verify the caller's sanity */ + + if (stcb) + { + /* Sigactions can only be assigned to the currently executing + * thread. So, a simple lock ought to give us sufficient + * protection. + */ + + sched_lock(); + + /* Seach the list for a sigaction on this signal */ + + for(sigact = (FAR sigactq_t*)stcb->sigactionq.head; + ((sigact) && (sigact->signo != signo)); + sigact = sigact->flink); + + sched_unlock(); + } + + return sigact; +} diff --git a/nuttx/sched/sig_initialize.c b/nuttx/sched/sig_initialize.c new file mode 100644 index 0000000000..966d818a16 --- /dev/null +++ b/nuttx/sched/sig_initialize.c @@ -0,0 +1,271 @@ +/************************************************************************ + * sched/sig_initialize.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/* The g_sigfreeaction data structure is a list of available signal + * action structures. + */ + +sq_queue_t g_sigfreeaction; + +/* The g_sigpendingaction data structure is a list of available pending + * signal action structures. + */ + +sq_queue_t g_sigpendingaction; + +/* The g_sigpendingirqaction is a list of available pending signal actions + * that are reserved for use by interrupt handlers. + */ + +sq_queue_t g_sigpendingirqaction; + +/* The g_sigpendingsignal data structure is a list of available pending + * signal structures. + */ + +sq_queue_t g_sigpendingsignal; + +/* The g_sigpendingirqsignal data structure is a list of available + * pending signal structures that are reserved for use by interrupt + * handlers. + */ + +sq_queue_t g_sigpendingirqsignal; + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/* g_sigactionalloc is a pointer to the start of the allocated blocks of + * signal actions. + */ + +static sigactq_t *g_sigactionalloc; + +/* g_sigpendingactionalloc is a pointer to the start of the allocated + * blocks of pending signal actions. + */ + +static sigq_t *g_sigpendingactionalloc; + +/* g_sigpendingirqactionalloc is a pointer to the start of the allocated + * block of pending signal actions. + */ + +static sigq_t *g_sigpendingirqactionalloc; + +/* g_sigpendingsignalalloc is a pointer to the start of the allocated + * blocks of pending signals. + */ + +static sigpendq_t *g_sigpendingsignalalloc; + +/* g_sigpendingirqsignalalloc is a pointer to the start of the allocated + * blocks of pending signals. + */ + +static sigpendq_t *g_sigpendingirqsignalalloc; + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +static sigq_t *sig_allocateblock(sq_queue_t *siglist, uint16_t nsigs, + uint8_t sigtype); +static sigpendq_t *sig_allocatependingsignalblock(sq_queue_t *siglist, + uint16_t nsigs, uint8_t sigtype); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_allocateblock + * + * Description: + * Allocate a block of pending signal actions and place them + * on the free list. + * + ************************************************************************/ + +static sigq_t *sig_allocateblock(sq_queue_t *siglist, uint16_t nsigs, + uint8_t sigtype) +{ + sigq_t *sigqalloc; + sigq_t *sigq; + int i; + + /* Allocate a block of pending signal actions */ + + sigqalloc = (sigq_t*)kmalloc((sizeof(sigq_t)) * nsigs); + + sigq = sigqalloc; + for (i = 0; i < nsigs; i++) + { + sigq->type = sigtype; + sq_addlast((FAR sq_entry_t*)sigq++, siglist); + } + + return sigqalloc; +} + +/************************************************************************ + * Name: sig_allocatependingsignalblock + * + * Description: + * Allocate a block of pending signal structures and place them on + * the free list. + * + ************************************************************************/ + +static sigpendq_t *sig_allocatependingsignalblock(sq_queue_t *siglist, + uint16_t nsigs, uint8_t sigtype) +{ + sigpendq_t *sigpendalloc; + sigpendq_t *sigpend; + int i; + + /* Allocate a block of pending signal structures */ + + sigpendalloc = + (sigpendq_t*)kmalloc((sizeof(sigpendq_t)) * nsigs); + + sigpend = sigpendalloc; + for (i = 0; i < nsigs; i++) + { + sigpend->type = sigtype; + sq_addlast((FAR sq_entry_t*)sigpend++, siglist); + } + + return sigpendalloc; +} + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_initialize + * + * Description: + * Perform one-time power-up initialization + * + ************************************************************************/ + +void sig_initialize(void) +{ + /* Initialize free lists */ + + sq_init(&g_sigfreeaction); + sq_init(&g_sigpendingaction); + sq_init(&g_sigpendingirqaction); + sq_init(&g_sigpendingsignal); + sq_init(&g_sigpendingirqsignal); + + /* Add a block of signal structures to each list */ + + g_sigpendingactionalloc = + sig_allocateblock(&g_sigpendingaction, + NUM_PENDING_ACTIONS, + SIG_ALLOC_FIXED); + + g_sigpendingirqactionalloc = + sig_allocateblock(&g_sigpendingirqaction, + NUM_PENDING_INT_ACTIONS, + SIG_ALLOC_IRQ); + + sig_allocateactionblock(); + + g_sigpendingsignalalloc = + sig_allocatependingsignalblock(&g_sigpendingsignal, + NUM_SIGNALS_PENDING, + SIG_ALLOC_FIXED); + + g_sigpendingirqsignalalloc = + sig_allocatependingsignalblock(&g_sigpendingirqsignal, + NUM_INT_SIGNALS_PENDING, + SIG_ALLOC_IRQ); +} + +/************************************************************************ + * Name: sig_allocateactionblock + * + * Description: + * Allocate a block of signal actions and place them + * on the free list. + * + ************************************************************************/ + +void sig_allocateactionblock(void) +{ + sigactq_t *sigact; + int i; + + /* Allocate a block of signal actions */ + + g_sigactionalloc = + (sigactq_t*)kmalloc((sizeof(sigactq_t)) * NUM_SIGNAL_ACTIONS); + + sigact = g_sigactionalloc; + for (i = 0; i < NUM_SIGNAL_ACTIONS; i++) + { + sq_addlast((FAR sq_entry_t*)sigact++, &g_sigfreeaction); + } +} diff --git a/nuttx/sched/sig_internal.h b/nuttx/sched/sig_internal.h new file mode 100644 index 0000000000..6c06417420 --- /dev/null +++ b/nuttx/sched/sig_internal.h @@ -0,0 +1,190 @@ +/**************************************************************************** + * sched/sig_internal.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __SCHED_SIG_INTERNAL_H +#define __SCHED_SIG_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* The following definition determines the number of signal structures to + * allocate in a block + */ + +#define NUM_SIGNAL_ACTIONS 16 +#define NUM_PENDING_ACTIONS 16 +#define NUM_PENDING_INT_ACTIONS 8 +#define NUM_SIGNALS_PENDING 16 +#define NUM_INT_SIGNALS_PENDING 8 + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +enum sigalloc_e +{ + SIG_ALLOC_FIXED = 0, /* pre-allocated; never freed */ + SIG_ALLOC_DYN, /* dynamically allocated; free when unused */ + SIG_ALLOC_IRQ /* Preallocated, reserved for interrupt handling */ +}; +typedef enum sigalloc_e sigalloc_t; + +/* The following defines the sigaction queue entry */ + +struct sigactq +{ + FAR struct sigactq *flink; /* Forward link */ + struct sigaction act; /* Sigaction data */ + uint8_t signo; /* Signal associated with action */ +}; +typedef struct sigactq sigactq_t; + +/* The following defines the queue structure within each TCB to hold pending + * signals received by the task. These are signals that cannot be processed + * because: (1) the task is not waiting for them, or (2) the task has no + * action associated with the signal. + */ + +struct sigpendq +{ + FAR struct sigpendq *flink; /* Forward link */ + siginfo_t info; /* Signal information */ + uint8_t type; /* (Used to manage allocations) */ +}; +typedef struct sigpendq sigpendq_t; + +/* The following defines the queue structure within each TCB to hold queued + * signal actions that need action by the task + */ + +struct sigq_s +{ + FAR struct sigq_s *flink; /* Forward link */ + union + { + void (*sighandler)(int signo, siginfo_t *info, void *context); + } action; /* Signal action */ + sigset_t mask; /* Additional signals to mask while the + * the signal-catching function executes */ + siginfo_t info; /* Signal information */ + uint8_t type; /* (Used to manage allocations) */ +}; +typedef struct sigq_s sigq_t; + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* The g_sigfreeaction data structure is a list of available signal action + * structures. + */ + +extern sq_queue_t g_sigfreeaction; + +/* The g_sigpendingaction data structure is a list of available pending + * signal action structures. + */ + +extern sq_queue_t g_sigpendingaction; + +/* The g_sigpendingirqaction is a list of available pending signal actions + * that are reserved for use by interrupt handlers. + */ + +extern sq_queue_t g_sigpendingirqaction; + +/* The g_sigpendingsignal data structure is a list of available pending + * signal structures. + */ + +extern sq_queue_t g_sigpendingsignal; + +/* The g_sigpendingirqsignal data structure is a list of available pending + * signal structures that are reserved for use by interrupt handlers. + */ + +extern sq_queue_t g_sigpendingirqsignal; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Internal signal-related interfaces ***************************************/ + +/* sig_intialize.c */ + +void weak_function sig_initialize(void); +void sig_allocateactionblock(void); + +/* sig_action.c */ + +void sig_releaseaction(FAR sigactq_t *sigact); + +/* sig_pending.c */ + +sigset_t sig_pendingset(FAR _TCB *stcb); + +/* In files of the same name */ + +FAR sigq_t *sig_allocatependingsigaction(void); +void sig_cleanup(FAR _TCB *stcb); +void sig_deliver(FAR _TCB *stcb); +FAR sigactq_t *sig_findaction(FAR _TCB *stcb, int signo); +int sig_lowest(FAR sigset_t *set); +#ifdef CONFIG_CAN_PASS_STRUCTS +int sig_mqnotempty(int tid, int signo, union sigval value); +#else +int sig_mqnotempty(int tid, int signo, FAR void *sival_ptr); +#endif +int sig_received(FAR _TCB *stcb, FAR siginfo_t *info); +void sig_releasependingsigaction(FAR sigq_t *sigq); +void sig_releasependingsignal(FAR sigpendq_t *sigpend); +FAR sigpendq_t *sig_removependingsignal(FAR _TCB *stcb, int signo); +void sig_unmaskpendingsignal(void); + +#endif /* __SCHED_SIG_INTERNAL_H */ diff --git a/nuttx/sched/sig_kill.c b/nuttx/sched/sig_kill.c new file mode 100644 index 0000000000..17921015fb --- /dev/null +++ b/nuttx/sched/sig_kill.c @@ -0,0 +1,135 @@ +/************************************************************************ + * sched/sig_kill.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Global Functions + ************************************************************************/ + +/************************************************************************ + * Name: kill + * + * Description: + * The kill() system call can be used to send any signal to any task. + * + * Limitation: Sending of signals to 'process groups' is not + * supported in NuttX + * + * Parameters: + * pid - The id of the task to receive the signal. The POSIX kill + * specification encodes process group information as zero and + * negative pid values. Only positive, non-zero values of pid are + * supported by this implementation. + * signo - The signal number to send. If signo is zero, no signal is + * sent, but all error checking is performed. + * + * Returned Value: + * On success (at least one signal was sent), zero is returned. On + * error, -1 is returned, and errno is set appropriately: + * + * EINVAL An invalid signal was specified. + * EPERM The process does not have permission to send the + * signal to any of the target processes. + * ESRCH The pid or process group does not exist. + * ENOSYS Do not support sending signals to process groups. + * + * Assumptions: + * + ************************************************************************/ + +int kill(pid_t pid, int signo) +{ + FAR _TCB *stcb; + siginfo_t info; + int ret = ERROR; + + /* We do not support sending signals to process groups */ + + if (pid <= 0) + { + errno = ENOSYS; + return ERROR; + } + + /* Make sure that the signal is valid */ + + if (!GOOD_SIGNO(signo)) + { + errno = EINVAL; + return ERROR; + } + + /* Keep things stationary through the following */ + + sched_lock(); + + /* Get the TCB of the receiving task */ + + stcb = sched_gettcb(pid); + sdbg("TCB=0x%08x signo=%d\n", stcb, signo); + if (!stcb) + { + errno = ESRCH; + sched_unlock(); + return ERROR; + } + + /* Create the siginfo structure */ + + info.si_signo = signo; + info.si_code = SI_USER; + info.si_value.sival_ptr = NULL; + + /* Send the signal */ + + ret = sig_received(stcb, &info); + sched_unlock(); + return ret; +} + + diff --git a/nuttx/sched/sig_lowest.c b/nuttx/sched/sig_lowest.c new file mode 100644 index 0000000000..f5654eb478 --- /dev/null +++ b/nuttx/sched/sig_lowest.c @@ -0,0 +1,91 @@ +/************************************************************************ + * sched/sig_lowest.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_lowest + * + * Description: + * Return the lowest signal number that is a member of a set of signals. + * + ************************************************************************/ + +int sig_lowest(sigset_t *set) +{ + int signo; + + for (signo = MIN_SIGNO; signo <= MAX_SIGNO; signo++) + { + if (sigismember(set, signo)) + { + return signo; + } + } + + return ERROR; +} diff --git a/nuttx/sched/sig_mqnotempty.c b/nuttx/sched/sig_mqnotempty.c new file mode 100644 index 0000000000..9a1fd7243b --- /dev/null +++ b/nuttx/sched/sig_mqnotempty.c @@ -0,0 +1,128 @@ +/**************************************************************************** + * sched/sig_mqnotempty.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functionss + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sig_mqnotempty + * + * Description: + * This function is equivalent to sigqueue(), but supports the messaging + * system's requirement to signal a task when a message queue becomes + * non-empty. It is identical to sigqueue(), except that it sets the + * si_code field in the siginfo structure to SI_MESGQ rather than SI_QUEUE. + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_PASS_STRUCTS +int sig_mqnotempty (int pid, int signo, union sigval value) +#else +int sig_mqnotempty (int pid, int signo, void *sival_ptr) +#endif +{ + FAR _TCB *stcb; + siginfo_t info; + int ret = ERROR; + + sched_lock(); + + /* Get the TCB of the receiving task */ + + stcb = sched_gettcb(pid); + +#ifdef CONFIG_CAN_PASS_STRUCTS + sdbg("TCB=%p signo=%d value=%d\n", stcb, signo, value.sival_int); +#else + sdbg("TCB=%p signo=%d sival_ptr=%p\n", stcb, signo, sival_ptr); +#endif + + /* Create the siginfo structure */ + + info.si_signo = signo; + info.si_code = SI_MESGQ; +#ifdef CONFIG_CAN_PASS_STRUCTS + info.si_value = value; +#else + info.si_value.sival_ptr = sival_ptr; +#endif + + /* Verify that we can perform the signalling operation */ + + if ((stcb) && (GOOD_SIGNO(signo))) + { + /* Process the receipt of the signal */ + + ret = sig_received(stcb, &info); + } + + sched_unlock(); + return ret; +} diff --git a/nuttx/sched/sig_pending.c b/nuttx/sched/sig_pending.c new file mode 100644 index 0000000000..eaabbff6b5 --- /dev/null +++ b/nuttx/sched/sig_pending.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * sched/sig_pending.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigpending + * + * Description: + * This function stores the returns the set of signals that are blocked + * for delivery and that are pending for the calling process in the space + * pointed to by set. + * + * Parameters: + * set - The location to return the pending signal set. + * + * Return Value: + * 0 (OK) or -1 (ERROR) + * + * Assumptions: + * + ****************************************************************************/ + +int sigpending(FAR sigset_t *set) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + int ret = ERROR; + + if (set) + { + *set = sig_pendingset(rtcb); + ret = OK; + } + + return ret; +} + +/**************************************************************************** + * Name: sig_pendingset + * + * Description: + * Convert the list of pending signals into a signal set + * + ****************************************************************************/ + +sigset_t sig_pendingset(FAR _TCB *stcb) +{ + sigset_t sigpendset; + FAR sigpendq_t *sigpend; + irqstate_t saved_state; + + sigpendset = NULL_SIGNAL_SET; + + saved_state = irqsave(); + for (sigpend = (FAR sigpendq_t*)stcb->sigpendingq.head; + (sigpend); sigpend = sigpend->flink) + { + sigaddset(&sigpendset, sigpend->info.si_signo); + } + + irqrestore(saved_state); + + return sigpendset; +} diff --git a/nuttx/sched/sig_procmask.c b/nuttx/sched/sig_procmask.c new file mode 100644 index 0000000000..c671595898 --- /dev/null +++ b/nuttx/sched/sig_procmask.c @@ -0,0 +1,180 @@ +/**************************************************************************** + * sched/sig_procmask.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigprocmask + * + * Description: + * This function allows the calling process to examine and/or change its + * signal mask. If the 'set' is not NULL, then it points to a set of + * signals to be used to change the currently blocked set. The value of + * 'how' indicates the manner in which the set is changed. + * + * If there any pending unblocked signals after the call to sigprocmask(), + * those signals will be delivered before sigprocmask() returns. + * + * If sigprocmask() fails, the signal mask of the process is not changed + * by this function call. + * + * Parameters: + * how - How the signal mast will be changed: + * SIG_BLOCK - The resulting set is the union of the current set + * and the signal set pointed to by 'set'. + * SIG_UNBLOCK - The resulting set is the intersection of the current + * set and the complement of the signal set pointed to + * by 'set'. + * SIG_SETMASK - The resulting set is the signal set pointed to by + * 'set'. + * set - Location of the new signal mask + * oset - Location to store the old signal mask + * + * Return Value: + * 0 (OK), or -1 (ERROR) if how is invalid. + * + * Assumptions: + * + ****************************************************************************/ + +int sigprocmask(int how, FAR const sigset_t *set, FAR sigset_t *oset) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + sigset_t oldsigprocmask; + irqstate_t saved_state; + int ret = OK; + + sched_lock(); + + /* Return the old signal mask if requested */ + + oldsigprocmask = rtcb->sigprocmask; + if (oset) + { + *oset = oldsigprocmask; + } + + /* Modify the current signal mask if so requested */ + + if (set) + { + /* Some of these operations are non-atomic. We need to protect + * ourselves from attempts to process signals from interrupts + */ + + saved_state = irqsave(); + + /* Okay, determine what we are supposed to do */ + + switch (how) + { + /* The resulting set is the union of the current set and the + * signal set pointed to by set. + */ + + case SIG_BLOCK: + rtcb->sigprocmask |= *set; + break; + + /* The resulting set is the intersection of the current set and + * the complement of the signal set pointed to by _set. + */ + + case SIG_UNBLOCK: + rtcb->sigprocmask &= ~(*set); + break; + + /* The resulting set is the signal set pointed to by set. */ + + case SIG_SETMASK: + rtcb->sigprocmask = *set; + break; + + default: + ret = ERROR; + break; + } + + irqrestore(saved_state); + + /* Now, process any pending signals that were just unmasked */ + + sig_unmaskpendingsignal(); + } + + sched_unlock(); + return ret; +} diff --git a/nuttx/sched/sig_queue.c b/nuttx/sched/sig_queue.c new file mode 100644 index 0000000000..dee1c798a2 --- /dev/null +++ b/nuttx/sched/sig_queue.c @@ -0,0 +1,159 @@ +/**************************************************************************** + * sched/sig_queue.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigqueue + * + * Description: + * This function sends the signal specified by signo with the signal + * parameter value to the process specified by pid. + * + * If the receiving process has the signal blocked via the sigprocmask, + * the signal will pend until it is unmasked. Only one pending signal (per + * signo) is retained. This is consistent with POSIX which states, "If + * a subsequent occurrence of a pending signal is generated, it is + * implementation defined as to whether the signal is delivered more than + * once." + * + * Parameters: + * pid - Process ID of task to receive signal + * signo - Signal number + * value - Value to pass to task with signal + * + * Return Value: + * On success (at least one signal was sent), zero is returned. On + * error, -1 is returned, and errno is set appropriately: + * + * EGAIN The limit of signals which may be queued has been reached. + * EINVAL sig was invalid. + * EPERM The process does not have permission to send the + * signal to the receiving process. + * ESRCH No process has a PID matching pid. + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_PASS_STRUCTS +int sigqueue (int pid, int signo, union sigval value) +#else +int sigqueue(int pid, int signo, void *sival_ptr) +#endif +{ + FAR _TCB *stcb; + siginfo_t info; + int ret = ERROR; + + /* Sanity checks */ + + if (!GOOD_SIGNO(signo)) + { + set_errno(EINVAL); + return ERROR; + } + + sched_lock(); + + /* Get the TCB of the receiving task */ + + stcb = sched_gettcb(pid); +#ifdef CONFIG_CAN_PASS_STRUCTS + sdbg("TCB=0x%08x signo=%d value=%d\n", stcb, signo, value.sival_int); +#else + sdbg("TCB=0x%08x signo=%d value=%p\n", stcb, signo, sival_ptr); +#endif + if (pid == 0 || !stcb) + { + set_errno(ESRCH); + sched_unlock(); + return ERROR; + } + + /* Create the siginfo structure */ + + info.si_signo = signo; + info.si_code = SI_QUEUE; +#ifdef CONFIG_CAN_PASS_STRUCTS + info.si_value = value; +#else + info.si_value.sival_ptr = sival_ptr; +#endif + + /* Send the signal */ + + ret = sig_received(stcb, &info); + sched_unlock(); + return ret; +} + diff --git a/nuttx/sched/sig_received.c b/nuttx/sched/sig_received.c new file mode 100644 index 0000000000..cf4d00165e --- /dev/null +++ b/nuttx/sched/sig_received.c @@ -0,0 +1,404 @@ +/************************************************************************ + * sched/sig_received.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "sem_internal.h" +#include "sig_internal.h" +#include "mq_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_queueaction + * + * Description: + * Queue a signal action for delivery to a task. + * + ************************************************************************/ + +static int sig_queueaction(FAR _TCB *stcb, siginfo_t *info) +{ + FAR sigactq_t *sigact; + FAR sigq_t *sigq; + irqstate_t saved_state; + int ret = OK; + + sched_lock(); + + /* Find the sigaction associated with this signal */ + + sigact = sig_findaction(stcb, info->si_signo); + + /* Check if a valid signal handler is available and if the signal is + * unblocked. NOTE: There is no default action. + */ + + if ((sigact) && (sigact->act.sa_u._sa_sigaction)) + { + /* Allocate a new element for the signal queue. NOTE: sig_allocatependingsigaction + * will force a system crash if it is unable to allocate memory for the + * signal data */ + + sigq = sig_allocatependingsigaction(); + if (!sigq) ret = ERROR; + else + { + /* Populate the new signal queue element */ + + sigq->action.sighandler = sigact->act.sa_u._sa_sigaction; + sigq->mask = sigact->act.sa_mask; + memcpy(&sigq->info, info, sizeof(siginfo_t)); + + /* Put it at the end of the pending signals list */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)sigq, &(stcb->sigpendactionq)); + irqrestore(saved_state); + } + } + + sched_unlock(); + return ret; +} + +/************************************************************************ + * Name: sig_findpendingsignal + * + * Description: + * Find a specified element in the pending signal list + * + ************************************************************************/ + +static FAR sigpendq_t *sig_findpendingsignal(FAR _TCB *stcb, int signo) +{ + FAR sigpendq_t *sigpend = NULL; + irqstate_t saved_state; + + /* Verify the caller's sanity */ + + if (stcb) + { + /* Pending sigals can be added from interrupt level. */ + + saved_state = irqsave(); + + /* Seach the list for a sigpendion on this signal */ + + for(sigpend = (FAR sigpendq_t*)stcb->sigpendingq.head; + (sigpend && sigpend->info.si_signo != signo); + sigpend = sigpend->flink); + irqrestore(saved_state); + } + + return sigpend; +} + +/************************************************************************ + * Name: sig_allocatependingsignal + * + * Description: + * Allocate a pending signal list entry + * + ************************************************************************/ + +static FAR sigpendq_t *sig_allocatependingsignal(void) +{ + FAR sigpendq_t *sigpend; + irqstate_t saved_state; + + /* Check if we were called from an interrupt handler. */ + + if (up_interrupt_context()) + { + /* Try to get the pending signal structure from the free list */ + + sigpend = (FAR sigpendq_t*)sq_remfirst(&g_sigpendingsignal); + if (!sigpend) + { + /* If no pending signal structure is available in the free list, + * then try the special list of structures reserved for + * interrupt handlers + */ + + sigpend = (FAR sigpendq_t*)sq_remfirst(&g_sigpendingirqsignal); + } + } + + /* If we were not called from an interrupt handler, then we are + * free to allocate pending action structures if necessary. */ + + else + { + /* Try to get the pending signal structure from the free list */ + + saved_state = irqsave(); + sigpend = (FAR sigpendq_t*)sq_remfirst(&g_sigpendingsignal); + irqrestore(saved_state); + + /* Check if we got one. */ + + if (!sigpend) + { + /* No... Allocate the pending signal */ + + if (!sigpend) + { + sigpend = (FAR sigpendq_t *)kmalloc((sizeof (sigpendq_t))); + } + + /* Check if we got an allocated message */ + + if (sigpend) + { + sigpend->type = SIG_ALLOC_DYN; + } + } + } + + return sigpend; +} + +/************************************************************************ + * Name: sig_addpendingsignal + * + * Description: + * Add the specified signal to the signal pending list. NOTE: This + * function will queue only one entry for each pending signal. This + * was done intentionally so that a run-away sender cannot consume + * all of memory. + * + ************************************************************************/ + +static FAR sigpendq_t *sig_addpendingsignal(FAR _TCB *stcb, + siginfo_t *info) +{ + FAR sigpendq_t *sigpend; + irqstate_t saved_state; + + /* Check if the signal is already pending */ + + sigpend = sig_findpendingsignal(stcb, info->si_signo); + if (sigpend) + { + /* The signal is already pending... retain only one copy */ + + memcpy(&sigpend->info, info, sizeof(siginfo_t)); + } + + /* No... There is nothing pending for this signo */ + + else + { + /* Allocate a new pending signal entry */ + + sigpend = sig_allocatependingsignal(); + if (sigpend) + { + /* Put the signal information into the allocated structure */ + + memcpy(&sigpend->info, info, sizeof(siginfo_t)); + + /* Add the structure to the pending signal list */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)sigpend, &stcb->sigpendingq); + irqrestore(saved_state); + } + } + + return sigpend; +} + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_received + * + * Description: + * All signals received the task (whatever the source) go through this + * function to be processed. This function is responsible for: + * + * - Determining if the signal is blocked. + * - Queuing and dispatching signal actions + * - Unblocking tasks that are waiting for signals + * - Queuing pending signals. + * + ************************************************************************/ + +int sig_received(FAR _TCB *stcb, siginfo_t *info) +{ + irqstate_t saved_state; + int ret = ERROR; + + sdbg("TCB=0x%08x signo=%d code=%d value=%d mask=%08x\n", + stcb, info->si_signo, info->si_code, + info->si_value.sival_int, stcb->sigprocmask); + + if (stcb && info) + { + ret = OK; + + /****************** MASKED SIGNAL HANDLING ******************/ + + /* Check if the signal is masked -- if it is, it will be added to the + * list of pending signals. + */ + + if (sigismember(&stcb->sigprocmask, info->si_signo)) + { + /* Check if the task is waiting for this pending signal. If so, + * then unblock it. This must be performed in a critical section + * because signals can be queued from the interrupt level. + */ + + saved_state = irqsave(); + if (stcb->task_state == TSTATE_WAIT_SIG && + sigismember(&stcb->sigwaitmask, info->si_signo)) + { + memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t)); + stcb->sigwaitmask = NULL_SIGNAL_SET; + up_unblock_task(stcb); + irqrestore(saved_state); + } + + /* Its not one we are waiting for... Add it to the list of pending + * signals. + */ + + else + { + irqrestore(saved_state); + if (!sig_addpendingsignal(stcb, info)) + { + PANIC(OSERR_FAILEDTOADDSIGNAL); + } + } + } + + /****************** UNMASKED SIGNAL HANDLING ******************/ + + else + { + /* Queue any sigaction's requested by this task. */ + + ret = sig_queueaction(stcb, info); + + /* Then schedule execution of the signal handling action on + * the recipients thread. + */ + + up_schedule_sigaction(stcb, sig_deliver); + + /* Check if the task is waiting for an unmasked signal. If so, + * then unblock it. This must be performed in a critical section + * because signals can be queued from the interrupt level. + */ + + saved_state = irqsave(); + if (stcb->task_state == TSTATE_WAIT_SIG) + { + memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t)); + stcb->sigwaitmask = NULL_SIGNAL_SET; + up_unblock_task(stcb); + } + irqrestore(saved_state); + + /* If the task neither was waiting for the signal nor had a signal + * handler attached to the signal, then the default action is + * simply to ignore the signal + */ + + /****************** OTHER SIGNAL HANDLING ******************/ + + /* If the task is blocked waiting for a semaphore, then that + * task must be unblocked when a signal is received. + */ + + if (stcb->task_state == TSTATE_WAIT_SEM) + { + sem_waitirq(stcb, EINTR); + } + + /* If the task is blocked waiting on a message queue, then that + * task must be unblocked when a signal is received. + */ + +#ifndef CONFIG_DISABLE_MQUEUE + if (stcb->task_state == TSTATE_WAIT_MQNOTEMPTY || + stcb->task_state == TSTATE_WAIT_MQNOTFULL) + { + mq_waitirq(stcb, EINTR); + } +#endif + } + } + + return ret; +} diff --git a/nuttx/sched/sig_releasependingsigaction.c b/nuttx/sched/sig_releasependingsigaction.c new file mode 100644 index 0000000000..69252f2840 --- /dev/null +++ b/nuttx/sched/sig_releasependingsigaction.c @@ -0,0 +1,120 @@ +/************************************************************************ + * sched/sig_releasependingsigaction.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_releasependingsigaction + * + * Description: + * Deallocate a pending signal action Q entry + * + ************************************************************************/ + +void sig_releasependingsigaction(FAR sigq_t *sigq) +{ + irqstate_t saved_state; + + /* If this is a generally available pre-allocated structyre, + * then just put it back in the free list. + */ + + if (sigq->type == SIG_ALLOC_FIXED) + { + /* Make sure we avoid concurrent access to the free + * list from interrupt handlers. */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)sigq, &g_sigpendingaction); + irqrestore(saved_state); + } + + /* If this is a message pre-allocated for interrupts, + * then put it back in the correct free list. + */ + + else if (sigq->type == SIG_ALLOC_IRQ) + { + /* Make sure we avoid concurrent access to the free + * list from interrupt handlers. */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)sigq, &g_sigpendingirqaction); + irqrestore(saved_state); + } + + /* Otherwise, deallocate it. Note: interrupt handlers + * will never deallocate signals because they will not + * receive them. + */ + + else if (sigq->type == SIG_ALLOC_DYN) + { + sched_free(sigq); + } +} diff --git a/nuttx/sched/sig_releasependingsignal.c b/nuttx/sched/sig_releasependingsignal.c new file mode 100644 index 0000000000..5b847bc644 --- /dev/null +++ b/nuttx/sched/sig_releasependingsignal.c @@ -0,0 +1,131 @@ +/************************************************************************ + * sched/sig_releasependingsignal.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_releasependingsignal + * + * Description: + * Deallocate a pending signal list entry + * + ************************************************************************/ + +void sig_releasependingsignal(FAR sigpendq_t *sigpend) +{ + irqstate_t saved_state; + + /* If this is a generally available pre-allocated structyre, + * then just put it back in the free list. + */ + + if (sigpend->type == SIG_ALLOC_FIXED) + { + /* Make sure we avoid concurrent access to the free + * list from interrupt handlers. + */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)sigpend, &g_sigpendingsignal); + irqrestore(saved_state); + } + + /* If this is a message pre-allocated for interrupts, + * then put it back in the correct free list. + */ + + else if (sigpend->type == SIG_ALLOC_IRQ) + { + /* Make sure we avoid concurrent access to the free + * list from interrupt handlers. + */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)sigpend, &g_sigpendingirqsignal); + irqrestore(saved_state); + } + + /* Otherwise, deallocate it. Note: interrupt handlers + * will never deallocate signals because they will not + * receive them. + */ + + else if (sigpend->type == SIG_ALLOC_DYN) + { + sched_free(sigpend); + } +} diff --git a/nuttx/sched/sig_removependingsignal.c b/nuttx/sched/sig_removependingsignal.c new file mode 100644 index 0000000000..c82bf983b9 --- /dev/null +++ b/nuttx/sched/sig_removependingsignal.c @@ -0,0 +1,115 @@ +/************************************************************************ + * sched/sig_removependingsignal.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_removependingsignal + * + * Description: + * Remove the specified signal from the signal pending list + * + ************************************************************************/ + +FAR sigpendq_t *sig_removependingsignal(FAR _TCB *stcb, int signo) +{ + FAR sigpendq_t *currsig; + FAR sigpendq_t *prevsig; + irqstate_t saved_state; + + saved_state = irqsave(); + + for (prevsig = NULL, currsig = (FAR sigpendq_t*)stcb->sigpendingq.head; + (currsig && currsig->info.si_signo != signo); + prevsig = currsig, currsig = currsig->flink); + + if (currsig) + { + if (prevsig) + { + sq_remafter((FAR sq_entry_t*)prevsig, &stcb->sigpendingq); + } + else + { + sq_remfirst(&stcb->sigpendingq); + } + } + + irqrestore(saved_state); + + return currsig; +} diff --git a/nuttx/sched/sig_suspend.c b/nuttx/sched/sig_suspend.c new file mode 100644 index 0000000000..09f47dee97 --- /dev/null +++ b/nuttx/sched/sig_suspend.c @@ -0,0 +1,180 @@ +/**************************************************************************** + * sched/sig_suspend.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigsuspend + * + * Description: + * + * The sigsuspend() function replaces the signal mask of the task with the + * set of signals pointed to by the argument 'set' and then suspends the + * process until delivery of a signal to the task. + * + * If the effect of the set argument is to unblock a pending signal, then + * no wait is performed. + * + * The original signal mask is restored when this function returns. + * + * Waiting for an empty signal set stops a task without freeing any + * resources. + * + * Parameters: + * set - signal mask to use while suspended. + * + * Return Value: + * -1 (ERROR) always + * + * Assumptions: + * + * POSIX Compatibility: + * int sigsuspend(const sigset_t *set); + * + * POSIX states that sigsuspend() "suspends the process until delivery of + * a signal whose action is either to execute a signal-catching function + * or to terminate the process." Only the deliver of a signal is required + * in the present implementation (even if the signal is ignored). + * + ****************************************************************************/ + +int sigsuspend(FAR const sigset_t *set) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + sigset_t intersection; + sigset_t saved_sigprocmask; + FAR sigpendq_t *sigpend; + irqstate_t saved_state; + int unblocksigno; + + /* Several operations must be performed below: We must determine if any + * signal is pending and, if not, wait for the signal. Since signals can + * be posted from the interrupt level, there is a race condition that + * can only be eliminated by disabling interrupts! + */ + + sched_lock(); /* Not necessary */ + saved_state = irqsave(); + + /* Check if there is a pending signal corresponding to one of the + * signals that will be unblocked by the new sigprocmask. + */ + + intersection = ~(*set) & sig_pendingset(rtcb); + if (intersection != NULL_SIGNAL_SET) + { + /* One or more of the signals in intersections is sufficient to cause + * us to not wait. Pick the lowest numbered signal and mark it not + * pending. + */ + + unblocksigno = sig_lowest(&intersection); + sigpend = sig_removependingsignal(rtcb, unblocksigno); + if (!sigpend) + { + PANIC(OSERR_FAILEDTOREMOVESIGNAL); + } + + sig_releasependingsignal(sigpend); + irqrestore(saved_state); + } + else + { + /* Its time to wait. Save a copy of the old sigprocmask and install + * the new (temporary) sigprocmask + */ + + saved_sigprocmask = rtcb->sigprocmask; + rtcb->sigprocmask = *set; + rtcb->sigwaitmask = NULL_SIGNAL_SET; + + /* And wait until one of the unblocked signals is posted */ + + up_block_task(rtcb, TSTATE_WAIT_SIG); + + /* We are running again, restore the original sigprocmask */ + + rtcb->sigprocmask = saved_sigprocmask; + irqrestore(saved_state); + + /* Now, handle the (rare?) case where (a) a blocked signal was received + * while the task was suspended but (b) restoring the original + * sigprocmask will unblock the signal. + */ + + sig_unmaskpendingsignal(); + } + + sched_unlock(); + return ERROR; +} diff --git a/nuttx/sched/sig_timedwait.c b/nuttx/sched/sig_timedwait.c new file mode 100644 index 0000000000..1b8dfd1620 --- /dev/null +++ b/nuttx/sched/sig_timedwait.c @@ -0,0 +1,334 @@ +/**************************************************************************** + * sched/sig_timedwait.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "sig_internal.h" +#include "clock_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* This is a special value of si_signo that means that it was the timeout + * that awakened the wait... not the receipt of a signal. + */ + +#define SIG_WAIT_TIMEOUT 0xff + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functionss + ****************************************************************************/ + +/**************************************************************************** + * Name: sig_timeout + * + * Description: + * A timeout elapsed while waiting for signals to be queued. + * + ****************************************************************************/ + +static void sig_timeout(int argc, uint32_t itcb) +{ + /* On many small machines, pointers are encoded and cannot be simply cast + * from uint32_t to _TCB*. The following union works around this + * (see wdogparm_t). This odd logic could be conditioned on + * CONFIG_CAN_CAST_POINTERS, but it is not too bad in any case. + */ + + union + { + FAR _TCB *wtcb; + uint32_t itcb; + } u; + + u.itcb = itcb; + + if (!u.wtcb) + { + PANIC(OSERR_TIMEOUTNOTCB); + } + + /* There may be a race condition -- make sure the task is + * still waiting for a signal + */ + + if (u.wtcb->task_state == TSTATE_WAIT_SIG) + { + u.wtcb->sigunbinfo.si_signo = SIG_WAIT_TIMEOUT; + u.wtcb->sigunbinfo.si_code = SI_TIMER; + u.wtcb->sigunbinfo.si_value.sival_int = 0; + up_unblock_task(u.wtcb); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigtimedwait + * + * Description: + * This function selects the pending signal set specified by the argument + * set. If multiple signals are pending in set, it will remove and return + * the lowest numbered one. If no signals in set are pending at the time + * of the call, the calling process will be suspended until one of the + * signals in set becomes pending, OR until the process is interrupted by + * an unblocked signal, OR until the time interval specified by timeout + * (if any), has expired. If timeout is NULL, then the timeout interval + * is forever. + * + * If the info argument is non-NULL, the selected signal number is stored + * in the si_signo member and the cause of the signal is store in the + * si_code emember. The content of si_value is only meaningful if the + * signal was generated by sigqueue(). + * + * The following values for si_code are defined in signal.h: + * SI_USER - Signal sent from kill, raise, or abort + * SI_QUEUE - Signal sent from sigqueue + * SI_TIMER - Signal is result of timer expiration + * SI_ASYNCIO - Signal is the result of asynch IO completion + * SI_MESGQ - Signal generated by arrival of a message on an + * empty message queue. + * + * Parameters: + * set - The pending signal set. + * info - The returned value + * timeout - The amount of time to wait + * + * Return Value: + * Signal number that cause the wait to be terminated, otherwise -1 (ERROR) + * is returned with errno set to either: + * + * EAGAIN - No signal specified by set was generated within the specified + * timeout period. + * EINTR - The wait was interrupted by an unblocked, caught signal. + * + * Assumptions: + * + ****************************************************************************/ + +int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info, + FAR const struct timespec *timeout) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + sigset_t intersection; + FAR sigpendq_t *sigpend; + WDOG_ID wdog; + irqstate_t saved_state; + int32_t waitticks; + int ret = ERROR; + + sched_lock(); /* Not necessary */ + + /* Several operations must be performed below: We must determine if any + * signal is pending and, if not, wait for the signal. Since signals can + * be posted from the interrupt level, there is a race condition that + * can only be eliminated by disabling interrupts! + */ + + saved_state = irqsave(); + + /* Check if there is a pending signal corresponding to one of the + * signals in the pending signal set argument. + */ + + intersection = *set & sig_pendingset(rtcb); + if (intersection != NULL_SIGNAL_SET) + { + /* One or more of the signals in intersections is sufficient to cause + * us to not wait. Pick the lowest numbered signal and mark it not + * pending. + */ + + sigpend = sig_removependingsignal(rtcb, sig_lowest(&intersection)); + if (!sigpend) + { + PANIC(OSERR_NOPENDINGSIGNAL); + } + + /* Return the signal info to the caller if so requested */ + + if (info) + { + memcpy(info, &sigpend->info, sizeof(struct siginfo)); + } + + /* Then dispose of the pending signal structure properly */ + + sig_releasependingsignal(sigpend); + irqrestore(saved_state); + + /* The return value is the number of the signal that awakened us */ + + ret = info->si_signo; + } + + /* We will have to wait for a signal to be posted to this task. */ + + else + { + /* Save the set of pending signals to wait for */ + + rtcb->sigwaitmask = *set; + + /* Check if we should wait for the timeout */ + + if (timeout) + { + /* Convert the timespec to milliseconds */ + + waitticks = MSEC2TICK(timeout->tv_sec * MSEC_PER_SEC + + timeout->tv_nsec / NSEC_PER_MSEC); + + /* Create a watchdog */ + + wdog = wd_create(); + if (wdog) + { + /* This little of nonsense is necessary for some + * processors where sizeof(pointer) < sizeof(uint32_t). + * see wdog.h. + */ + + wdparm_t wdparm; + wdparm.pvarg = (FAR void*)rtcb; + + /* Start the watchdog */ + + wd_start(wdog, waitticks, (wdentry_t)sig_timeout, 1, wdparm.dwarg); + + /* Now wait for either the signal or the watchdog */ + + up_block_task(rtcb, TSTATE_WAIT_SIG); + + /* We no longer need the watchdog */ + + wd_delete(wdog); + } + } + + /* No timeout, just wait */ + + else + { + /* And wait until one of the unblocked signals is posted */ + + up_block_task(rtcb, TSTATE_WAIT_SIG); + } + + /* We are running again, clear the sigwaitmask */ + + rtcb->sigwaitmask = NULL_SIGNAL_SET; + + /* When we awaken, the cause will be in the TCB. Get the signal number + * or timeout) that awakened us. + */ + + if (GOOD_SIGNO(rtcb->sigunbinfo.si_signo)) + { + /* We were awakened by a signal... but is it one of the signals that + * we were waiting for? + */ + + if (sigismember(set, rtcb->sigunbinfo.si_signo)) + { + /* Yes.. the return value is the number of the signal that + * awakened us. + */ + + ret = rtcb->sigunbinfo.si_signo; + } + else + { + /* No... then set EINTR and report an error */ + + set_errno(EINTR); + ret = ERROR; + } + } + else + { + /* Otherwise, we must have been awakened by the timeout. Set EGAIN + * and return an error. + */ + + DEBUGASSERT(rtcb->sigunbinfo.si_signo == SIG_WAIT_TIMEOUT); + set_errno(EAGAIN); + ret = ERROR; + } + + /* Return the signal info to the caller if so requested */ + + if (info) + { + memcpy(info, &rtcb->sigunbinfo, sizeof(struct siginfo)); + } + irqrestore(saved_state); + } + + sched_unlock(); + return ret; +} diff --git a/nuttx/sched/sig_unmaskpendingsignal.c b/nuttx/sched/sig_unmaskpendingsignal.c new file mode 100644 index 0000000000..a7bcc7a29b --- /dev/null +++ b/nuttx/sched/sig_unmaskpendingsignal.c @@ -0,0 +1,138 @@ +/************************************************************************ + * sched/sig_unmaskpendingsignal.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_unmaskpendingsignal + * + * Description: + * Based upon the current setting of the sigprocmask, this function + * unmasks and processes any pending signals. This function should + * be called whenever the sigprocmask is changed. + * + ************************************************************************/ + +void sig_unmaskpendingsignal(void) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + sigset_t unmaskedset; + FAR sigpendq_t *pendingsig; + int signo; + + /* Prohibit any context switches until we are done with this. + * We may still be performing signal operations from interrupt + * handlers, however, none of the pending signals that we + * are concerned with here should be effected. + */ + + sched_lock(); + + /* Get the set of pending signals that were just unmasked. The + * following operation should be safe because the sigprocmask + * can only be changed on this thread of execution. + */ + + unmaskedset = ~(rtcb->sigprocmask) & sig_pendingset(rtcb); + + /* Loop while there are unmasked pending signals to be processed. */ + + while (unmaskedset != NULL_SIGNAL_SET) + { + /* Pending signals will be processed from lowest numbered signal + * to highest + */ + + signo = sig_lowest(&unmaskedset); + if (signo != ERROR) + { + /* Remove the signal from the set of unmasked signals. NOTE: + * this implicitly assumes that only one instance for a given + * signal number is pending. + */ + + sigdelset(&unmaskedset, signo); + + /* Remove the pending signal from the list of pending signals */ + + if ((pendingsig = sig_removependingsignal(rtcb, signo)) != NULL) + { + /* If there is one, then process it like a normal signal */ + + sig_received(rtcb, &pendingsig->info); + + /* Then remove it from the pending signal list */ + + sig_releasependingsignal(pendingsig); + } + } + } + + sched_unlock(); +} + diff --git a/nuttx/sched/sig_waitinfo.c b/nuttx/sched/sig_waitinfo.c new file mode 100644 index 0000000000..0172ec47d9 --- /dev/null +++ b/nuttx/sched/sig_waitinfo.c @@ -0,0 +1,89 @@ +/**************************************************************************** + * sched/sig_waitinfo.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigwaitinfo + * + * Description: + * This function is equivalent to sigtimedwait with a NULL timeout + * parameter. + * + * Parameters: + * set - The pending signal set + * info - The returned value + * + * Return Value: + * Signal number that cause the wait to be terminated, otherwise -1 (ERROR) + * is returned. + * + * Assumptions: + * + ****************************************************************************/ + +int sigwaitinfo(FAR const sigset_t *set, FAR struct siginfo *info) +{ + return sigtimedwait(set, info, NULL); +} diff --git a/nuttx/sched/sleep.c b/nuttx/sched/sleep.c new file mode 100644 index 0000000000..03884a5b64 --- /dev/null +++ b/nuttx/sched/sleep.c @@ -0,0 +1,196 @@ +/**************************************************************************** + * sched/sleep.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +/**************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sleep + * + * Description: + * The sleep() function will cause the calling thread to be suspended from + * execution until either the number of real-time seconds specified by the + * argument 'seconds' has elapsed or a signal is delivered to the calling + * thread and its action is to invoke a signal-catching function or to + * terminate the process. The suspension time may be longer than requested + * due to the scheduling of other activity by the system. + * + * If a SIGALRM signal is generated for the calling process during + * execution of sleep() and if the SIGALRM signal is being ignored or + * blocked from delivery, it is unspecified whether sleep() returns + * when the SIGALRM signal is scheduled. If the signal is being blocked, it + * is also unspecified whether it remains pending after sleep() returns or + * it is discarded. + * + * If a SIGALRM signal is generated for the calling process during + * execution of sleep(), except as a result of a prior call to alarm(), + * and if the SIGALRM signal is not being ignored or blocked from delivery, + * it is unspecified whether that signal has any effect other than causing + * sleep() to return. + * + * If a signal-catching function interrupts sleep() and examines or changes + * either the time a SIGALRM is scheduled to be generated, the action + * associated with the SIGALRM signal, or whether the SIGALRM signal is + * blocked from delivery, the results are unspecified. + * + * If a signal-catching function interrupts sleep() and calls siglongjmp() + * or longjmp() to restore an environment saved prior to the sleep() call, + * the action associated with the SIGALRM signal and the time at which a + * SIGALRM signal is scheduled to be generated are unspecified. It is also + * unspecified whether the SIGALRM signal is blocked, unless the process' + * signal mask is restored as part of the environment. + * + * Implementations may place limitations on the granularity of timer values. + * For each interval timer, if the requested timer value requires a finer + * granularity than the implementation supports, the actual timer value will + * be rounded up to the next supported value. + * + * Interactions between sleep() and any of setitimer(), ualarm() or sleep() + * are unspecified. + * + * Parameters: + * seconds + * + * Returned Value: + * If sleep() returns because the requested time has elapsed, the value + * returned will be 0. If sleep() returns because of premature arousal due + * to delivery of a signal, the return value will be the "unslept" amount + * (the requested time minus the time actually slept) in seconds. + * + * Assumptions: + * + ****************************************************************************/ + +unsigned int sleep(unsigned int seconds) +{ + sigset_t set; + struct timespec ts; + struct siginfo value; + irqstate_t flags; + uint32_t start; + int32_t elapsed; + int32_t remaining = 0; + + /* Don't sleep if seconds == 0 */ + + if (seconds) + { + /* Set up for the sleep. Using the empty set means that we are not + * waiting for any particualar signal. However, any unmasked signal + * can still awaken sigtimedwait(). + */ + + (void)sigemptyset(&set); + ts.tv_sec = seconds; + ts.tv_nsec = 0; + + /* Interrupts are disabled around the following so that it is atomic */ + + flags = irqsave(); + + /* Get the current time then sleep for the requested time. + * sigtimedwait() cannot succeed. It should always return error with + * either (1) EAGAIN meaning that the timeout occurred, or (2) EINTR + * meaning that some other unblocked signal was caught. + */ + + start = clock_systimer(); + (void)sigtimedwait(&set, &value, &ts); + + /* Calculate the elapsed time (in clock ticks) when we wake up from the sleep. + * This is really only necessary if we were awakened from the sleep early + * due to the receipt of a signal. + */ + + elapsed = clock_systimer() - start; + irqrestore(flags); + + /* Get the remaining, un-waited seconds. Note that this calculation + * truncates the elapsed seconds in the division. We may have slept some + * fraction of a second longer than this! But if the calculation is less + * than the 'seconds', we certainly did not sleep for the complete + * requested interval. + */ + + remaining = (int32_t)seconds - elapsed / TICK_PER_SEC; + + /* Make sure that the elapsed time is non-negative (this should always + * be the case unless something exceptional happened while were we + * sleeping -- like the clock was reset or we went into a low power mode, + * OR if we had to wait a long time to run again after calling + * sigtimedwait() making 'elapsed' bigger than it should have been). + */ + + if (remaining < 0) + { + remaining = 0; + } + } + + return (unsigned int)remaining; +} diff --git a/nuttx/sched/task_activate.c b/nuttx/sched/task_activate.c new file mode 100644 index 0000000000..bae2856a1b --- /dev/null +++ b/nuttx/sched/task_activate.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * sched/task_activate.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_activate + * + * Description: + * This function activates tasks initialized by task_schedsetup(). Without + * activation, a task is ineligible for execution by the scheduler. + * + * Input Parameters: + * tcb - The TCB for the task for the task (same as the task_init argument). + * + * Return Value: + * Always returns OK + * + ****************************************************************************/ + +int task_activate(FAR _TCB *tcb) +{ + irqstate_t flags = irqsave(); + +#ifdef CONFIG_SCHED_INSTRUMENTATION + + /* Check if this is really a re-start */ + + if (tcb->task_state != TSTATE_TASK_INACTIVE) + { + /* Inform the instrumentation layer that the task + * has stopped + */ + + sched_note_stop(tcb); + } + + /* Inform the instrumentation layer that the task + * has started + */ + + sched_note_start(tcb); +#endif + + up_unblock_task(tcb); + irqrestore(flags); + return OK; +} diff --git a/nuttx/sched/task_create.c b/nuttx/sched/task_create.c new file mode 100644 index 0000000000..4d92c9bb07 --- /dev/null +++ b/nuttx/sched/task_create.c @@ -0,0 +1,269 @@ +/**************************************************************************** + * sched/task_create.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: thread_create + * + * Description: + * This function creates and activates a new thread of the specified type + * with a specified priority and returns its system-assigned ID. It is the + * internal, commn implementation of task_create() and kernel_thread(). + * See comments with task_create() for further information. + * + * Input Parameters: + * name - Name of the new task + * type - Type of the new task + * priority - Priority of the new task + * stack_size - size (in bytes) of the stack needed + * entry - Entry point of a new task + * arg - A pointer to an array of input parameters. Up to + * CONFIG_MAX_TASK_ARG parameters may be provided. If fewer + * than CONFIG_MAX_TASK_ARG parameters are passed, the list + * should be terminated with a NULL argv[] value. If no + * parameters are required, argv may be NULL. + * + * Return Value: + * Returns the non-zero process ID of the new task or ERROR if memory is + * insufficient or the task cannot be created. The errno will be set to + * indicate the nature of the error (always ENOMEM). + * + ****************************************************************************/ + +#ifndef CONFIG_CUSTOM_STACK +static int thread_create(const char *name, uint8_t type, int priority, + int stack_size, main_t entry, const char **argv) +#else +static int thread_create(const char *name, uint8_t type, int priority, + main_t entry, const char **argv) +#endif +{ + FAR _TCB *tcb; + pid_t pid; + int ret; + + /* Allocate a TCB for the new task. */ + + tcb = (FAR _TCB*)kzalloc(sizeof(_TCB)); + if (!tcb) + { + goto errout; + } + + /* Associate file descriptors with the new task */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + ret = sched_setuptaskfiles(tcb); + if (ret != OK) + { + goto errout_with_tcb; + } +#endif + + /* Clone the parent's task environment */ + + (void)env_dup(tcb); + + /* Allocate the stack for the TCB */ + +#ifndef CONFIG_CUSTOM_STACK + ret = up_create_stack(tcb, stack_size); + if (ret != OK) + { + goto errout_with_tcb; + } +#endif + + /* Mark the type of this thread (this setting will be needed in + * task_schedsetup() when up_initial_state() is called. + */ + + tcb->flags |= type; + + /* Initialize the task control block */ + + ret = task_schedsetup(tcb, priority, task_start, entry); + if (ret != OK) + { + goto errout_with_tcb; + } + + /* Setup to pass parameters to the new task */ + + (void)task_argsetup(tcb, name, argv); + + /* Get the assigned pid before we start the task */ + + pid = (int)tcb->pid; + + /* Activate the task */ + + ret = task_activate(tcb); + if (ret != OK) + { + dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks); + goto errout_with_tcb; + } + + return pid; + +errout_with_tcb: + sched_releasetcb(tcb); + +errout: + errno = ENOMEM; + return ERROR; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_create + * + * Description: + * This function creates and activates a new task with a specified + * priority and returns its system-assigned ID. + * + * The entry address entry is the address of the "main" function of the + * task. This function will be called once the C environment has been + * set up. The specified function will be called with four arguments. + * Should the specified routine return, a call to exit() will + * automatically be made. + * + * Note that four (and only four) arguments must be passed for the spawned + * functions. + * + * Input Parameters: + * name - Name of the new task + * priority - Priority of the new task + * stack_size - size (in bytes) of the stack needed + * entry - Entry point of a new task + * arg - A pointer to an array of input parameters. Up to + * CONFIG_MAX_TASK_ARG parameters may be provided. If fewer + * than CONFIG_MAX_TASK_ARG parameters are passed, the list + * should be terminated with a NULL argv[] value. If no + * parameters are required, argv may be NULL. + * + * Return Value: + * Returns the non-zero process ID of the new task or ERROR if memory is + * insufficient or the task cannot be created. The errno will be set to + * indicate the nature of the error (always ENOMEM). + * + ****************************************************************************/ + +#ifndef CONFIG_CUSTOM_STACK +int task_create(const char *name, int priority, + int stack_size, main_t entry, const char *argv[]) +#else +int task_create(const char *name, int priority, + main_t entry, const char *argv[]) +#endif +{ +#ifndef CONFIG_CUSTOM_STACK + return thread_create(name, TCB_FLAG_TTYPE_TASK, priority, stack_size, entry, argv); +#else + return thread_create(name, TCB_FLAG_TTYPE_TASK, priority, entry, argv); +#endif +} + +/**************************************************************************** + * Name: kernel_thread + * + * Description: + * This function creates and activates a kernel thread task with kernel- + * mode privileges. It is identical to task_create() except that it + * configures the newly started thread to run in kernel model. + * + * Input Parameters: + * (same as task_create()) + * + * Return Value: + * (same as task_create()) + * + ****************************************************************************/ + +#ifndef CONFIG_CUSTOM_STACK +int kernel_thread(const char *name, int priority, + int stack_size, main_t entry, const char *argv[]) +#else +int kernel_thread(const char *name, int priority, + main_t entry, const char *argv[]) +#endif +{ +#ifndef CONFIG_CUSTOM_STACK + return thread_create(name, TCB_FLAG_TTYPE_KERNEL, priority, stack_size, entry, argv); +#else + return thread_create(name, TCB_FLAG_TTYPE_KERNEL, priority, entry, argv); +#endif +} + diff --git a/nuttx/sched/task_delete.c b/nuttx/sched/task_delete.c new file mode 100644 index 0000000000..ea0e251db6 --- /dev/null +++ b/nuttx/sched/task_delete.c @@ -0,0 +1,194 @@ +/**************************************************************************** + * sched/task_delete.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#ifndef CONFIG_DISABLE_SIGNALS +# include "sig_internal.h" +#endif + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_delete + * + * Description: + * This function causes a specified task to cease to exist. Its stack and + * TCB will be deallocated. This function is the companion to task_create(). + * + * The logic in this function only deletes non-running tasks. If the 'pid' + * parameter refers to to the currently runing task, then processing is + * redirected to exit(). + * + * Control will still be returned to task_delete() after the exit() logic + * finishes. In fact, this function is the final function called all task + * termination sequences. Here are all possible exit scenarios: + * + * - pthread_exit(). Calls exit() + * - exit(). Calls _exit() + * - _exit(). Calls task_deletecurrent() making the currently running task + * non-running then calls task_delete() to terminate the non-running + * task. + * - task_delete() + * + * Inputs: + * pid - The task ID of the task to delete. A pid of zero + * signifies the calling task. + * + * Return Value: + * OK on success; or ERROR on failure + * + * This function can fail if the provided pid does not correspond to a + * task (errno is not set) + * + ****************************************************************************/ + +int task_delete(pid_t pid) +{ + FAR _TCB *rtcb; + FAR _TCB *dtcb; + irqstate_t saved_state; + int ret = ERROR; + + /* Check if the task to delete is the calling task */ + + rtcb = (FAR _TCB*)g_readytorun.head; + if (pid == 0 || pid == rtcb->pid) + { + /* If it is, then what we really wanted to do was exit. Note that we + * don't bother to unlock the TCB since it will be going away. + */ + + exit(EXIT_SUCCESS); + } + + /* Make sure the task does not become ready-to-run while we are futzing with + * its TCB by locking ourselves as the executing task. + */ + + sched_lock(); + + /* Find for the TCB associated with matching pid */ + + dtcb = sched_gettcb(pid); + if (!dtcb) + { + /* This pid does not correspond to any known task */ + + sched_unlock(); + return ERROR; + } + + /* Verify our internal sanity */ + + if (dtcb->task_state == TSTATE_TASK_RUNNING || + dtcb->task_state >= NUM_TASK_STATES) + { + sched_unlock(); + PANIC(OSERR_BADDELETESTATE); + } + + /* Perform common task termination logic (flushing streams, calling + * functions registered by at_exit/on_exit, etc.). We need to do + * this as early as possible so that higher level clean-up logic + * can run in a healthy tasking environment. + * + * In the case where the task exits via exit(), task_exithook() + * may be called twice. + * + * I suppose EXIT_SUCCESS is an appropriate return value??? + */ + + task_exithook(dtcb, EXIT_SUCCESS); + + /* Remove the task from the OS's tasks lists. */ + + saved_state = irqsave(); + dq_rem((FAR dq_entry_t*)dtcb, (dq_queue_t*)g_tasklisttable[dtcb->task_state].list); + dtcb->task_state = TSTATE_TASK_INVALID; + irqrestore(saved_state); + + /* At this point, the TCB should no longer be accessible to the system */ + + sched_unlock(); + + /* Since all tasks pass through this function as the final step in their + * exit sequence, this is an appropriate place to inform any instrumentation + * layer that the task no longer exists. + */ + + sched_note_stop(dtcb); + + /* Deallocate its TCB */ + + sched_releasetcb(dtcb); + return ret; +} + diff --git a/nuttx/sched/task_deletecurrent.c b/nuttx/sched/task_deletecurrent.c new file mode 100644 index 0000000000..77025f5e0a --- /dev/null +++ b/nuttx/sched/task_deletecurrent.c @@ -0,0 +1,140 @@ +/**************************************************************************** + * sched/task_deletecurrent.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include "os_internal.h" +#ifndef CONFIG_DISABLE_SIGNALS +# include "sig_internal.h" +#endif + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_delete + * + * Description: + * This function causes the currently running task (i.e., the task at the + * head of the ready-to-run list) to cease to exist. This is a part of + * the logic used to implement _exit(). The full implementation of _exit() + * is architecture-dependent. This function should never be called from + * normal user code, but only from the architecture-specific implementation + * of exit. + * + * Inputs: + * None + * + * Return Value: + * OK on success; or ERROR on failure + * + ****************************************************************************/ + +int task_deletecurrent(void) +{ + FAR _TCB *dtcb = (FAR _TCB*)g_readytorun.head; + FAR _TCB *rtcb; + + /* Remove the TCB of the current task from the ready-to-run list. A context + * switch will definitely be necessary -- that must be done by the + * architecture-specific logic. + * + * sched_removereadytorun will mark the task at the head of the ready-to-run + * with state == TSTATE_TASK_RUNNING + */ + + (void)sched_removereadytorun(dtcb); + rtcb = (FAR _TCB*)g_readytorun.head; + + /* We are not in a bad state -- the head of the ready to run task list + * does not correspond to the thread that is running. Disabling pre- + * emption on this TCB and marking the new ready-to-run task as not + * running (see, for example, get_errno_ptr()). + */ + + sched_lock(); + rtcb->task_state = TSTATE_TASK_READYTORUN; + + /* Move the TCB to the specified blocked task list and delete it */ + + sched_addblocked(dtcb, TSTATE_TASK_INACTIVE); + task_delete(dtcb->pid); + rtcb->task_state = TSTATE_TASK_RUNNING; + + /* If there are any pending tasks, then add them to the ready-to-run + * task list now + */ + + if (g_pendingtasks.head) + { + (void)sched_mergepending(); + } + + /* Now calling sched_unlock() should have no effect */ + + sched_unlock(); + return OK; +} + diff --git a/nuttx/sched/task_exithook.c b/nuttx/sched/task_exithook.c new file mode 100644 index 0000000000..63dc28aa05 --- /dev/null +++ b/nuttx/sched/task_exithook.c @@ -0,0 +1,288 @@ +/**************************************************************************** + * sched/task_exithook.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_atexit + * + * Description: + * Call any registerd atexit function(s) + * + ****************************************************************************/ + +#ifdef CONFIG_SCHED_ATEXIT +static inline void task_atexit(FAR _TCB *tcb) +{ +#if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1 + int index; + + /* Call each atexit function in reverse order of registration atexit() + * functions are registered from lower to higher arry indices; they must + * be called in the reverse order of registration when task exists, i.e., + * from higher to lower indices. + */ + + for (index = CONFIG_SCHED_ATEXIT_MAX-1; index >= 0; index--) + { + if (tcb->atexitfunc[index]) + { + /* Call the atexit function */ + + (*tcb->atexitfunc[index])(); + + /* Nullify the atexit function. task_exithook may be called more then + * once in most task exit scenarios. Nullifying the atext function + * pointer will assure that the callback is performed only once. + */ + + tcb->atexitfunc[index] = NULL; + } + } + +#else + if (tcb->atexitfunc) + { + /* Call the atexit function */ + + (*tcb->atexitfunc)(); + + /* Nullify the atexit function. task_exithook may be called more then + * once in most task exit scenarios. Nullifying the atext function + * pointer will assure that the callback is performed only once. + */ + + tcb->atexitfunc = NULL; + } +#endif +#else +# define task_atexit(tcb) +#endif + +/**************************************************************************** + * Name: task_onexit + * + * Description: + * Call any registerd on)exit function(s) + * + ****************************************************************************/ + +#ifdef CONFIG_SCHED_ONEXIT +static inline void task_onexit(FAR _TCB *tcb, int status) +{ +#if defined(CONFIG_SCHED_ONEXIT_MAX) && CONFIG_SCHED_ONEXIT_MAX > 1 + int index; + + /* Call each on_exit function in reverse order of registration. on_exit() + * functions are registered from lower to higher arry indices; they must + * be called in the reverse order of registration when task exists, i.e., + * from higher to lower indices. + */ + + for (index = CONFIG_SCHED_ONEXIT_MAX-1; index >= 0; index--) + { + if (tcb->onexitfunc[index]) + { + /* Call the on_exit function */ + + (*tcb->onexitfunc[index])(status, tcb->onexitarg[index]); + + /* Nullify the on_exit function. task_exithook may be called more then + * once in most task exit scenarios. Nullifying the atext function + * pointer will assure that the callback is performed only once. + */ + + tcb->onexitfunc[index] = NULL; + } + } +#else + if (tcb->onexitfunc) + { + /* Call the on_exit function */ + + (*tcb->onexitfunc)(status, tcb->onexitarg); + + /* Nullify the on_exit function. task_exithook may be called more then + * once in most task exit scenarios. Nullifying the on_exit function + * pointer will assure that the callback is performed only once. + */ + + tcb->onexitfunc = NULL; + } +#endif +#else +# define task_onexit(tcb,status) +#endif + +/**************************************************************************** + * Name: task_exitwakeup + * + * Description: + * Wakeup any tasks waiting for this task to exit + * + ****************************************************************************/ + +#ifdef CONFIG_SCHED_WAITPID +static inline void task_exitwakeup(FAR _TCB *tcb, int status) +{ + /* Wakeup any tasks waiting for this task to exit */ + + while (tcb->exitsem.semcount < 0) + { + /* "If more than one thread is suspended in waitpid() awaiting + * termination of the same process, exactly one thread will return + * the process status at the time of the target process termination." + * Hmmm.. what do we return to the others? + */ + + if (tcb->stat_loc) + { + *tcb->stat_loc = status << 8; + tcb->stat_loc = NULL; + } + + /* Wake up the thread */ + + sem_post(&tcb->exitsem); + } +} +#else +# define task_exitwakeup(tcb, status) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_hook + * + * Description: + * This function implements some of the internal logic of exit() and + * task_delete(). This function performs some cleanup and other actions + * required when a task exists: + * + * - All open streams are flushed and closed. + * - All functions registered with atexit() and on_exit() are called, in + * the reverse order of their registration. + * + * When called from exit(), the tcb still resides at the head of the ready- + * to-run list. The following logic is safe because we will not be + * returning from the exit() call. + * + * When called from task_delete() we are operating on a different thread; + * on the thread that called task_delete(). In this case, task_delete + * will have already removed the tcb from the ready-to-run list to prevent + * any further action on this task. + * + ****************************************************************************/ + +void task_exithook(FAR _TCB *tcb, int status) +{ + /* If exit function(s) were registered, call them now before we do any un- + * initialization. NOTE: In the case of task_delete(), the exit function + * will *not* be called on the thread execution of the task being deleted! + */ + + task_atexit(tcb); + + /* Call any registered on_exit function(s) */ + + task_onexit(tcb, status); + + /* Wakeup any tasks waiting for this task to exit */ + + task_exitwakeup(tcb, status); + + /* Flush all streams (File descriptors will be closed when + * the TCB is deallocated). + */ + +#if CONFIG_NFILE_STREAMS > 0 + (void)lib_flushall(tcb->streams); +#endif + + /* Free all file-related resources now. This gets called again + * just be be certain when the TCB is delallocated. However, we + * really need to close files as soon as possible while we still + * have a functioning task. + */ + + (void)sched_releasefiles(tcb); + + /* Deallocate anything left in the TCB's queues */ + +#ifndef CONFIG_DISABLE_SIGNALS + sig_cleanup(tcb); /* Deallocate Signal lists */ +#endif +} diff --git a/nuttx/sched/task_init.c b/nuttx/sched/task_init.c new file mode 100644 index 0000000000..31fc5ef70b --- /dev/null +++ b/nuttx/sched/task_init.c @@ -0,0 +1,154 @@ +/**************************************************************************** + * sched/task_init.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_init + * + * Description: + * This function initializes a Task Control Block (TCB) in preparation for + * starting a new thread. It performs a subset of the functionality of + * task_create() + * + * Unlike task_create(): + * 1. Allocate the TCB. The pre-allocated TCB is passed in the arguments. + * 2. Allocate the stack. The pre-allocated stack is passed in the arguments. + * 3. Activate the task. This must be done by calling task_activate(). + * + * Input Parameters: + * tcb - Address of the new task's TCB + * name - Name of the new task (not used) + * priority - Priority of the new task + * stack - Start of the pre-allocated stack + * stack_size - Size (in bytes) of the stack allocated + * entry - Application start point of the new task + * arg - A pointer to an array of input parameters. Up to + * CONFIG_MAX_TASK_ARG parameters may be provided. If fewer + * than CONFIG_MAX_TASK_ARG parameters are passed, the list + * should be terminated with a NULL argv[] value. If no + * parameters are required, argv may be NULL. + * + * Return Value: + * OK on success; ERROR on failure. (See task_schedsetup() for possible + * failure conditions). On failure, the caller is responsible for freeing + * the stack memory and for calling sched_releasetcb() to free the TCB + * (which could be in most any state). + * + ****************************************************************************/ + +#ifndef CONFIG_CUSTOM_STACK +int task_init(FAR _TCB *tcb, const char *name, int priority, + FAR uint32_t *stack, uint32_t stack_size, + main_t entry, const char *argv[]) +#else +int task_init(FAR _TCB *tcb, const char *name, int priority, + main_t entry, const char *argv[]) +#endif +{ + int ret; + + /* Associate file descriptors with the new task */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + if (sched_setuptaskfiles(tcb) != OK) + { + return ERROR; + } +#endif + + /* Clone the parent's task environment */ + + (void)env_dup(tcb); + + /* Configure the user provided stack region */ + +#ifndef CONFIG_CUSTOM_STACK + up_use_stack(tcb, stack, stack_size); +#endif + + /* Initialize the task control block */ + + ret = task_schedsetup(tcb, priority, task_start, entry); + if (ret == OK) + { + /* Setup to pass parameters to the new task */ + + (void)task_argsetup(tcb, name, argv); + } + + return ret; +} + diff --git a/nuttx/sched/task_restart.c b/nuttx/sched/task_restart.c new file mode 100644 index 0000000000..6d9b84917b --- /dev/null +++ b/nuttx/sched/task_restart.c @@ -0,0 +1,184 @@ +/**************************************************************************** + * sched/task_restart.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_restart + * + * Description: + * This function "restarts" a task. The task is first terminated and then + * reinitialized with same ID, priority, original entry point, stack size, + * and parameters it had when it was first started. + * + * Inputs: + * pid - The task ID of the task to delete. An ID of zero signifies the + * calling task. + * + * Return Value: + * OK on sucess; ERROR on failure. + * + * This function can fail if: + * (1) A pid of zero or the pid of the calling task is provided + * (functionality not implemented) + * (2) The pid is not associated with any task known to the system. + * + ****************************************************************************/ + +int task_restart(pid_t pid) +{ + FAR _TCB *rtcb; + FAR _TCB *tcb; + int status; + irqstate_t state; + + /* Make sure this task does not become ready-to-run while + * we are futzing with its TCB + */ + + sched_lock(); + + /* Check if the task to restart is the calling task */ + + rtcb = (FAR _TCB*)g_readytorun.head; + if ((pid == 0) || (pid == rtcb->pid)) + { + /* Not implemented */ + + return ERROR; + } + + /* We are restarting some other task than ourselves */ + + else + { + /* Find for the TCB associated with matching pid */ + + tcb = sched_gettcb(pid); + if (!tcb) + { + /* There is no TCB with this pid */ + + return ERROR; + } + + /* Remove the TCB from whatever list it is in. At this point, the + * TCB should no longer be accessible to the system + */ + + state = irqsave(); + dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)g_tasklisttable[tcb->task_state].list); + tcb->task_state = TSTATE_TASK_INVALID; + irqrestore(state); + + /* Deallocate anything left in the TCB's queues */ + + sig_cleanup(tcb); /* Deallocate Signal lists */ + + /* Reset the current task priority */ + + tcb->sched_priority = tcb->init_priority; + + /* Reset the base task priority and the number of pending reprioritizations */ + +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = tcb->init_priority; +# if CONFIG_SEM_NNESTPRIO > 0 + tcb->npend_reprio = 0; +# endif +#endif + + /* Re-initialize the processor-specific portion of the TCB + * This will reset the entry point and the start-up parameters + */ + + up_initial_state(tcb); + + /* Add the task to the inactive task list */ + + dq_addfirst((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks); + tcb->task_state = TSTATE_TASK_INACTIVE; + + /* Activate the task */ + + status = task_activate(tcb); + if (status != OK) + { + dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks); + sched_releasetcb(tcb); + return ERROR; + } + } + + sched_unlock(); + return OK; +} diff --git a/nuttx/sched/task_setup.c b/nuttx/sched/task_setup.c new file mode 100644 index 0000000000..a37fb165a6 --- /dev/null +++ b/nuttx/sched/task_setup.c @@ -0,0 +1,347 @@ +/**************************************************************************** + * sched/task_setup.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/* This is the name for un-named tasks */ + +static const char g_noname[] = ""; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int task_assignpid(FAR _TCB* tcb); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_assignpid + * + * Description: + * This function assigns the next unique task ID to a task. + * + * Inputs: + * tcb - TCB of task + * + * Return: + * OK on success; ERROR on failure (errno is not set) + * + ****************************************************************************/ + +static int task_assignpid(FAR _TCB *tcb) +{ + pid_t next_pid; + int hash_ndx; + int tries; + + /* Disable pre-emption. This should provide sufficient protection + * for the following operation. + */ + + (void)sched_lock(); + + /* We'll try every allowable pid */ + + for (tries = 0; tries < CONFIG_MAX_TASKS; tries++) + { + /* Get the next process ID candidate */ + + next_pid = ++g_lastpid; + + /* Verify that the next_pid is in the valid range */ + + if (next_pid <= 0) + { + g_lastpid = 1; + next_pid = 1; + } + + /* Get the hash_ndx associated with the next_pid */ + + hash_ndx = PIDHASH(next_pid); + + /* Check if there is a (potential) duplicate of this pid */ + + if (!g_pidhash[hash_ndx].tcb) + { + g_pidhash[hash_ndx].tcb = tcb; + g_pidhash[hash_ndx].pid = next_pid; + tcb->pid = next_pid; + (void)sched_unlock(); + return OK; + } + } + + /* If we get here, then the g_pidhash[] table is completely full. + * We cannot allow another task to be started. + */ + + (void)sched_unlock(); + return ERROR; +} + +/**************************************************************************** + * Name: task_dupdspace + * + * Description: + * When a new task or thread is created from a PIC module, then that + * module (probably) intends the task or thread to execute in the same + * D-Space. This function will duplicate the D-Space for that purpose. + * + * Parameters: + * tcb - The TCB of the new task. + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_PIC +static inline void task_dupdspace(FAR _TCB *tcb) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + if (rtcb->dspace != NULL) + { + /* Copy the D-Space structure reference and increment the reference + * count on the memory. The D-Space memory will persist until the + * last thread exits (see sched_releasetcb()). + */ + + tcb->dspace = rtcb->dspace; + tcb->dspace->crefs++; + } +} +#else +# define task_dupdspace(tcb) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_schedsetup + * + * Description: + * This functions initializes a Task Control Block (TCB) in preparation + * for starting a new thread. + * + * task_schedsetup() is called from task_init(), task_start(), and + * pthread_create(); + * + * Input Parameters: + * tcb - Address of the new task's TCB + * priority - Priority of the new task + * entry - Entry point of a new task + * main - Application start point of the new task + * type - Type of the new thread: task, pthread, or kernel thread + * + * Return Value: + * OK on success; ERROR on failure. + * + * This function can only failure is it is unable to assign a new, unique + * task ID to the TCB (errno is not set). + * + ****************************************************************************/ + +int task_schedsetup(FAR _TCB *tcb, int priority, start_t start, main_t main) +{ + int ret; + + /* Assign a unique task ID to the task. */ + + ret = task_assignpid(tcb); + if (ret == OK) + { + /* Save task priority and entry point in the TCB */ + + tcb->init_priority = (uint8_t)priority; + tcb->sched_priority = (uint8_t)priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = (uint8_t)priority; +#endif + tcb->start = start; + tcb->entry.main = main; + + /* exec() and pthread_create() inherit the signal mask of the + * parent thread. I suppose that task_create() should as well. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + (void)sigprocmask(SIG_SETMASK, NULL, &tcb->sigprocmask); +#endif + + /* Initialize the task state. It does not get a valid state + * until it is activated. + */ + + tcb->task_state = TSTATE_TASK_INVALID; + + /* Clone the parent tasks D-Space (if it was running PIC). This + * must be done before calling up_initial_state() so that the + * state setup will take the PIC address base into account. + */ + + task_dupdspace(tcb); + + /* Initialize the processor-specific portion of the TCB */ + + up_initial_state(tcb); + + /* Add the task to the inactive task list */ + + sched_lock(); + dq_addfirst((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks); + tcb->task_state = TSTATE_TASK_INACTIVE; + sched_unlock(); + } + + return ret; +} + +/**************************************************************************** + * Name: task_argsetup + * + * Description: + * This functions sets up parameters in the Task Control + * Block (TCB) in preparation for starting a new thread. + * + * task_argsetup() is called only from task_init() and + * task_start() to create a new task. Argumens are + * cloned via strdup. + * + * Input Parameters: + * tcb - Address of the new task's TCB + * name - Name of the new task (not used) + * argv - A pointer to an array of input parameters. + * Up to CONFIG_MAX_TASK_ARG parameters may be + * provided. If fewer than CONFIG_MAX_TASK_ARG + * parameters are passed, the list should be + * terminated with a NULL argv[] value. + * If no parameters are required, argv may be NULL. + * + * Return Value: + * OK + * + ****************************************************************************/ + +int task_argsetup(FAR _TCB *tcb, const char *name, const char *argv[]) +{ + int i; + +#if CONFIG_TASK_NAME_SIZE > 0 + /* Give a name to the unnamed tasks */ + + if (!name) + { + name = (char *)g_noname; + } + + /* Copy the name into the TCB */ + + strncpy(tcb->name, name, CONFIG_TASK_NAME_SIZE); + + /* Save the name as the first argument */ + + tcb->argv[0] = tcb->name; +#else + /* Save the name as the first argument */ + + tcb->argv[0] = (char *)g_noname; +#endif /* CONFIG_TASK_NAME_SIZE */ + + /* For tasks, the life of the argument must be as long as + * the life of the task and the arguments must be strings. + * So for tasks, we have to to dup the strings. + * + * The first NULL argument terminates the list of + * arguments. The argv pointer may be NULL if no + * parameters are passed. + */ + + i = 1; + if (argv) + { + for (; i < CONFIG_MAX_TASK_ARGS+1 && argv[i-1]; i++) + { + tcb->argv[i] = strdup(argv[i-1]); + } + } + + /* Nullify any unused argument storage */ + + for (; i < CONFIG_MAX_TASK_ARGS+1; i++) + { + tcb->argv[i] = NULL; + } + + return OK; +} diff --git a/nuttx/sched/task_start.c b/nuttx/sched/task_start.c new file mode 100644 index 0000000000..a9cc38dfcc --- /dev/null +++ b/nuttx/sched/task_start.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * sched/task_start.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_start + * + * Description: + * This function is the low level entry point into the main thread of + * execution of a task. It receives initial control when the task is + * started and calls main entry point of the newly started task. + * + * Inputs: + * None + * + * Return: + * None + * + ****************************************************************************/ + +void task_start(void) +{ + FAR _TCB *tcb = (FAR _TCB*)g_readytorun.head; + int argc; + + /* Count how many non-null arguments we are passing */ + + for (argc = 1; argc <= CONFIG_MAX_TASK_ARGS; argc++) + { + /* The first non-null argument terminates the list */ + + if (!tcb->argv[argc]) + { + break; + } + } + + /* Call the 'main' entry point passing argc and argv. If/when + * the task returns. + */ + + exit(tcb->entry.main(argc, tcb->argv)); +} diff --git a/nuttx/sched/timer_create.c b/nuttx/sched/timer_create.c new file mode 100644 index 0000000000..edfb010801 --- /dev/null +++ b/nuttx/sched/timer_create.c @@ -0,0 +1,237 @@ +/******************************************************************************** + * sched/timer_create.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_allocate + * + * Description: + * Allocate one POSIX timer and place it into the allocated timer list. + * + ********************************************************************************/ + +static struct posix_timer_s *timer_allocate(void) +{ + struct posix_timer_s *ret; + irqstate_t flags; + uint8_t pt_flags; + + /* Try to get a preallocated timer from the free list */ + +#if CONFIG_PREALLOC_TIMERS > 0 + flags = irqsave(); + ret = (struct posix_timer_s*)sq_remfirst((sq_queue_t*)&g_freetimers); + irqrestore(flags); + + /* Did we get one? */ + + if (ret) + { + pt_flags = PT_FLAGS_PREALLOCATED; + } + else +#endif + { + /* Allocate a new timer from the heap */ + + ret = (struct posix_timer_s*)kmalloc(sizeof(struct posix_timer_s)); + pt_flags = 0; + } + + /* If we have a timer, then put it into the allocated timer list */ + + if (ret) + { + /* Initialize the timer structure */ + + memset(ret, 0, sizeof(struct posix_timer_s)); + ret->pt_flags = pt_flags; + + /* And add it to the end of the list of allocated timers */ + + flags = irqsave(); + sq_addlast((sq_entry_t*)ret, (sq_queue_t*)&g_alloctimers); + irqrestore(flags); + } + + return ret; +} + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_create + * + * Description: + * The timer_create() function creates per-thread timer using the specified + * clock, clock_id, as the timing base. The timer_create() function returns, in + * the location referenced by timerid, a timer ID of type timer_t used to identify + * the timer in timer requests. This timer ID is unique until the timer is + * deleted. The particular clock, clock_id, is defined in . The timer + * whose ID is returned will be in a disarmed state upon return from + * timer_create(). + * + * The evp argument, if non-NULL, points to a sigevent structure. This structure + * is allocated by the called and defines the asynchronous notification to occur. + * If the evp argument is NULL, the effect is as if the evp argument pointed to + * a sigevent structure with the sigev_notify member having the value SIGEV_SIGNAL, + * the sigev_signo having a default signal number, and the sigev_value member + * having the value of the timer ID. + * + * Each implementation defines a set of clocks that can be used as timing bases + * for per-thread timers. All implementations shall support a clock_id of + * CLOCK_REALTIME. + * + * Parameters: + * clockid - Specifies the clock to use as the timing base. + * evp - Refers to a user allocated sigevent structure that defines the + * asynchronous notification. evp may be NULL (see above). + * timerid - The pre-thread timer created by the call to timer_create(). + * + * Return Value: + * If the call succeeds, timer_create() will return 0 (OK) and update the + * location referenced by timerid to a timer_t, which can be passed to the + * other per-thread timer calls. If an error occurs, the function will return + * a value of -1 (ERROR) and set errno to indicate the error. + * + * EAGAIN - The system lacks sufficient signal queuing resources to honor the + * request. + * EAGAIN - The calling process has already created all of the timers it is + * allowed by this implementation. + * EINVAL - The specified clock ID is not defined. + * ENOTSUP - The implementation does not support the creation of a timer attached + * to the CPU-time clock that is specified by clock_id and associated with a + * thread different thread invoking timer_create(). + * + * Assumptions: + * + ********************************************************************************/ + +int timer_create(clockid_t clockid, FAR struct sigevent *evp, FAR timer_t *timerid) +{ + struct posix_timer_s *ret; + WDOG_ID wdog; + + /* Sanity checks. Also, we support only CLOCK_REALTIME */ + + if (!timerid || clockid != CLOCK_REALTIME) + { + errno = EINVAL; + return ERROR; + } + + /* Allocate a watchdog to provide the underling CLOCK_REALTIME timer */ + + wdog = wd_create(); + if (!wdog) + { + errno = EAGAIN; + return ERROR; + } + + /* Allocate a timer instance to contain the watchdog */ + + ret = timer_allocate(); + if (!ret) + { + errno = EAGAIN; + return ERROR; + } + + /* Initialize the timer instance */ + + ret->pt_crefs = 1; + ret->pt_owner = getpid(); + ret->pt_delay = 0; + ret->pt_wdog = wdog; + + if (evp) + { + ret->pt_signo = evp->sigev_signo; +#ifdef CONFIG_CAN_PASS_STRUCTS + ret->pt_value = evp->sigev_value; +#else + ret->pt_value.sival_ptr = evp->sigev_value.sival_ptr; +#endif + } + else + { + ret->pt_signo = SIGALRM; + ret->pt_value.sival_ptr = ret; + } + + /* Return the timer */ + + *timerid = ret; + return OK; +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/timer_delete.c b/nuttx/sched/timer_delete.c new file mode 100644 index 0000000000..c497c414e4 --- /dev/null +++ b/nuttx/sched/timer_delete.c @@ -0,0 +1,106 @@ +/******************************************************************************** + * timer_delete.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include + +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_delete + * + * Description: + * The timer_delete() function deletes the specified timer, timerid, previously + * created by the timer_create() function. If the timer is armed when + * timer_delete() is called, the timer will be automatically disarmed before + * removal. The disposition of pending signals for the deleted timer is + * unspecified. + * + * Parameters: + * timerid - The per-thread timer, previously created by the call to + * timer_create(), to be deleted. + * + * Return Value: + * If the call succeeds, timer_create() will return 0 (OK). Otherwise, the + * function will return a value of -1 (ERROR) and set errno to indicate the + * error. + * + * EINVAL - The timer specified timerid is not valid. + * + * Assumptions: + * + ********************************************************************************/ + +int timer_delete(timer_t timerid) +{ + int ret = timer_release((FAR struct posix_timer_s *)timerid); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return OK; +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/timer_getoverrun.c b/nuttx/sched/timer_getoverrun.c new file mode 100644 index 0000000000..6d5a474652 --- /dev/null +++ b/nuttx/sched/timer_getoverrun.c @@ -0,0 +1,111 @@ +/******************************************************************************** + * timer_getoverrun.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include + +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_getoverrun + * + * Description: + * Only a single signal will be queued to the process for a given timer at any + * point in time. When a timer for which a signal is still pending expires, no + * signal will be queued, and a timer overrun will occur. When a timer + * expiration signal is delivered to or accepted by a process, if the + * implementation supports the Realtime Signals Extension, the + * timer_getoverrun() function will return the timer expiration overrun count for + * the specified timer. The overrun count returned contains the number of extra + * timer expirations that occurred between the time the signal was generated + * (queued) and when it was delivered or accepted, up to but not including an + * implementation-defined maximum of DELAYTIMER_MAX. If the number of such + * extra expirations is greater than or equal to DELAYTIMER_MAX, then the + * overrun count will be set to DELAYTIMER_MAX. The value returned by + * timer_getoverrun() will apply to the most recent expiration signal delivery + * or acceptance for the timer. If no expiration signal has been delivered + * for the timer, or if the Realtime Signals Extension is not supported, the + * return value of timer_getoverrun() is unspecified. + * + * Parameters: + * timerid - The pre-thread timer, previously created by the call to + * timer_create(), whose overrun count will be returned.. + * + * Return Value: + * If the timer_getoverrun() function succeeds, it will return the timer + * expiration overrun count as explained above. timer_getoverrun() will fail if: + * + * EINVAL - The timerid argument does not correspond to an ID returned by + * timer_create() but not yet deleted by timer_delete(). + * + * Assumptions: + * + ********************************************************************************/ + +int timer_getoverrun(timer_t timerid) +{ + errno = ENOSYS; + return ERROR; +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/timer_gettime.c b/nuttx/sched/timer_gettime.c new file mode 100644 index 0000000000..7598dbec5e --- /dev/null +++ b/nuttx/sched/timer_gettime.c @@ -0,0 +1,123 @@ +/******************************************************************************** + * timer_gettime.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include + +#include "clock_internal.h" +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_gettime + * + * Description: + * The timer_gettime() function will store the amount of time until the + * specified timer, timerid, expires and the reload value of the timer into the + * space pointed to by the value argument. The it_value member of this structure + * will contain the amount of time before the timer expires, or zero if the timer + * is disarmed. This value is returned as the interval until timer expiration, + * even if the timer was armed with absolute time. The it_interval member of + * value will contain the reload value last set by timer_settime(). + * + * Parameters: + * timerid - The pre-thread timer, previously created by the call to + * timer_create(), whose remaining time count will be returned.. + * + * Return Value: + * If the timer_gettime() succeeds, a value of 0 (OK) will be returned. + * If an error occurs, the value -1 (ERROR) will be returned, and errno set to + * indicate the error. + * + * EINVAL - The timerid argument does not correspond to an ID returned by + * timer_create() but not yet deleted by timer_delete(). + * + * Assumptions/Limitations: + * Due to the asynchronous operation of this function, the time reported + * by this function could be significantly more than that actual time + * remaining on the timer at any time. + * + ********************************************************************************/ + +int timer_gettime(timer_t timerid, FAR struct itimerspec *value) +{ + FAR struct posix_timer_s *timer = (FAR struct posix_timer_s *)timerid; + int ticks; + + if (!timer || !value) + { + set_errno(EINVAL); + return ERROR; + } + + /* Get the number of ticks before the underlying watchdog expires */ + + ticks = wd_gettime(timer->pt_wdog); + + /* Convert that to a struct timespec and return it */ + + (void)clock_ticks2time(ticks, &value->it_value); + (void)clock_ticks2time(timer->pt_last, &value->it_interval); + return OK; +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/timer_initialize.c b/nuttx/sched/timer_initialize.c new file mode 100644 index 0000000000..05980bb1a8 --- /dev/null +++ b/nuttx/sched/timer_initialize.c @@ -0,0 +1,168 @@ +/******************************************************************************** + * timer_initialize.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/* These are the preallocated times */ + +#if CONFIG_PREALLOC_TIMERS > 0 +static struct posix_timer_s g_prealloctimers[CONFIG_PREALLOC_TIMERS]; +#endif + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/* This is a list of free, preallocated timer structures */ + +#if CONFIG_PREALLOC_TIMERS > 0 +volatile sq_queue_t g_freetimers; +#endif + +/* This is a list of instantiated timer structures -- active and inactive. The + * timers are place on this list by timer_create() and removed from the list by + * timer_delete() or when the owning thread exits. + */ + +volatile sq_queue_t g_alloctimers; + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_initialize + * + * Description: + * Boot up configuration of the POSIX timer facility. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ********************************************************************************/ + +void weak_function timer_initialize(void) +{ +#if CONFIG_PREALLOC_TIMERS > 0 + int i; + + /* Place all of the pre-allocated timers into the free timer list */ + + sq_init((sq_queue_t*)&g_freetimers); + + for (i = 0; i < CONFIG_PREALLOC_TIMERS; i++) + { + g_prealloctimers[i].pt_flags = PT_FLAGS_PREALLOCATED; + sq_addlast((FAR sq_entry_t*)&g_prealloctimers[i], (FAR sq_queue_t*)&g_freetimers); + } +#endif + + /* Initialize the list of allocated timers */ + + sq_init((sq_queue_t*)&g_alloctimers); +} + +/******************************************************************************** + * Name: timer_deleteall + * + * Description: + * This function is called whenever a thread exits. Any timers owned by that + * thread are deleted as though called by timer_delete(). + * + * It is provided in this file so that it can be weakly defined but also, + * like timer_intitialize(), be brought into the link whenever the timer + * resources are referenced. + * + * Parameters: + * pid - the task ID of the thread that exitted + * + * Return Value: + * None + * + * Assumptions: + * + ********************************************************************************/ + +void weak_function timer_deleteall(pid_t pid) +{ + FAR struct posix_timer_s *timer; + FAR struct posix_timer_s *next; + irqstate_t flags; + + flags = irqsave(); + for (timer = (FAR struct posix_timer_s*)g_alloctimers.head; timer; timer = next) + { + next = timer->flink; + if (timer->pt_owner == pid) + { + timer_delete((timer_t)timer); + } + } + + irqrestore(flags); +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/timer_internal.h b/nuttx/sched/timer_internal.h new file mode 100644 index 0000000000..71dfb59a34 --- /dev/null +++ b/nuttx/sched/timer_internal.h @@ -0,0 +1,102 @@ +/******************************************************************************** + * timer_internal.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +#ifndef __SCHED_TIMER_INTERNAL_H +#define __SCHED_TIMER_INTERNAL_H + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include + +#include + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +#define PT_FLAGS_PREALLOCATED 0x01 /* Timer comes from a pool of preallocated timers */ + +/******************************************************************************** + * Public Types + ********************************************************************************/ + +/* This structure represents one POSIX timer */ + +struct posix_timer_s +{ + FAR struct posix_timer_s *flink; + + uint8_t pt_flags; /* See PT_FLAGS_* definitions */ + uint8_t pt_crefs; /* Reference count */ + uint8_t pt_signo; /* Notification signal */ + pid_t pt_owner; /* Creator of timer */ + int pt_delay; /* If non-zero, used to reset repetitive timers */ + int pt_last; /* Last value used to set watchdog */ + WDOG_ID pt_wdog; /* The watchdog that provides the timing */ + union sigval pt_value; /* Data passed with notification */ +}; + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/* This is a list of free, preallocated timer structures */ + +#if CONFIG_PREALLOC_TIMERS > 0 +extern volatile sq_queue_t g_freetimers; +#endif + +/* This is a list of instantiated timer structures -- active and inactive. The + * timers are place on this list by timer_create() and removed from the list by + * timer_delete() or when the owning thread exits. + */ + +extern volatile sq_queue_t g_alloctimers; + +/******************************************************************************** + * Public Function Prototypes + ********************************************************************************/ + +void weak_function timer_initialize(void); +void weak_function timer_deleteall(pid_t pid); +int timer_release(FAR struct posix_timer_s *timer); + +#endif /* __SCHED_TIMER_INTERNAL_H */ diff --git a/nuttx/sched/timer_release.c b/nuttx/sched/timer_release.c new file mode 100644 index 0000000000..ed83b5f53e --- /dev/null +++ b/nuttx/sched/timer_release.c @@ -0,0 +1,159 @@ +/******************************************************************************** + * timer_release.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include + +#include + +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_free + * + * Description: + * Remove the timer from the allocated timer list and free it or return it to + * the free list (depending on whether or not the timer is one of the + * preallocated timers) + * + ********************************************************************************/ + +static inline void timer_free(struct posix_timer_s *timer) +{ + irqstate_t flags; + + /* Remove the timer from the allocated list */ + + flags = irqsave(); + sq_rem((FAR sq_entry_t*)timer, (sq_queue_t*)&g_alloctimers); + + /* Return it to the free list if it is one of the preallocated timers */ + +#if CONFIG_PREALLOC_TIMERS > 0 + if ((timer->pt_flags & PT_FLAGS_PREALLOCATED) != 0) + { + sq_addlast((FAR sq_entry_t*)timer, (FAR sq_queue_t*)&g_freetimers); + irqrestore(flags); + } + else +#endif + { + /* Otherwise, return it to the heap */ + + irqrestore(flags); + sched_free(timer); + } +} + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_release + * + * Description: + * timer_release implements the heart of timer_delete. It is private to the + * the OS internals and differs only in that return value of 1 means that the + * timer was not actually deleted. + * + * Parameters: + * timer - The per-thread timer, previously created by the call to + * timer_create(), to be deleted. + * + * Return Value: + * If the call succeeds, timer_release() will return 0 (OK) or 1 (meaning that + * the timer is still valid). Otherwise, the function will return a negated errno: + * + * -EINVAL - The timer specified timerid is not valid. + * + ********************************************************************************/ + +int timer_release(FAR struct posix_timer_s *timer) +{ + /* Some sanity checks */ + + if (!timer) + { + return -EINVAL; + } + + /* Release one reference to timer. Don't delete the timer until the count + * would decrement to zero. + */ + + if (timer->pt_crefs > 1) + { + timer->pt_crefs--; + return 1; + } + + /* Free the underlying watchdog instance (the timer will be canceled by the + * watchdog logic before it is actually deleted) + */ + + (void)wd_delete(timer->pt_wdog); + + /* Release the timer structure */ + + timer_free(timer); + return OK; +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/timer_settime.c b/nuttx/sched/timer_settime.c new file mode 100644 index 0000000000..1814ba8988 --- /dev/null +++ b/nuttx/sched/timer_settime.c @@ -0,0 +1,397 @@ +/******************************************************************************** + * sched/timer_settime.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "os_internal.h" +#include "clock_internal.h" +#include "sig_internal.h" +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +static void inline timer_sigqueue(FAR struct posix_timer_s *timer); +static void inline timer_restart(FAR struct posix_timer_s *timer, uint32_t itimer); +static void timer_timeout(int argc, uint32_t itimer); + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_sigqueue + * + * Description: + * This function basically reimplements sigqueue() so that the si_code can + * be correctly set to SI_TIMER + * + * Parameters: + * timer - A reference to the POSIX timer that just timed out + * + * Return Value: + * None + * + * Assumptions: + * This function executes in the context of the watchod timer interrupt. + * + ********************************************************************************/ + +static void inline timer_sigqueue(FAR struct posix_timer_s *timer) +{ + FAR _TCB *tcb; + + /* Get the TCB of the receiving task */ + + tcb = sched_gettcb(timer->pt_owner); + if (tcb) + { + siginfo_t info; + + /* Create the siginfo structure */ + + info.si_signo = timer->pt_signo; + info.si_code = SI_TIMER; +#ifdef CONFIG_CAN_PASS_STRUCTS + info.si_value = timer->pt_value; +#else + info.si_value.sival_ptr = timer->pt_value.sival_ptr; +#endif + + /* Send the signal */ + + (void)sig_received(tcb, &info); + } +} + +/******************************************************************************** + * Name: timer_restart + * + * Description: + * If a periodic timer has been selected, then restart the watchdog. + * + * Parameters: + * timer - A reference to the POSIX timer that just timed out + * + * Return Value: + * None + * + * Assumptions: + * This function executes in the context of the watchod timer interrupt. + * + ********************************************************************************/ + +static void inline timer_restart(FAR struct posix_timer_s *timer, uint32_t itimer) +{ + /* If this is a repetitive timer, then restart the watchdog */ + + if (timer->pt_delay) + { + timer->pt_last = timer->pt_delay; + (void)wd_start(timer->pt_wdog, timer->pt_delay, (wdentry_t)timer_timeout, + 1, itimer); + } +} + +/******************************************************************************** + * Name: timer_timeout + * + * Description: + * This function is called if the timeout elapses before the condition is + * signaled. + * + * Parameters: + * argc - the number of arguments (should be 1) + * itimer - A reference to the POSIX timer that just timed out + * signo - The signal to use to wake up the task + * + * Return Value: + * None + * + * Assumptions: + * This function executes in the context of the watchod timer interrupt. + * + ********************************************************************************/ + +static void timer_timeout(int argc, uint32_t itimer) +{ +#ifndef CONFIG_CAN_PASS_STRUCTS + /* On many small machines, pointers are encoded and cannot be simply cast from + * uint32_t to _TCB*. The following union works around this (see wdogparm_t). + */ + + union + { + FAR struct posix_timer_s *timer; + uint32_t itimer; + } u; + + u.itimer = itimer; + + /* Send the specified signal to the specified task. Increment the reference + * count on the timer first so that will not be deleted until after the + * signal handler returns. + */ + + u.timer->pt_crefs++; + timer_sigqueue(u.timer); + + /* Release the reference. timer_release will return nonzero if the timer + * was not deleted. + */ + + if (timer_release(u.timer)) + { + /* If this is a repetitive timer, the restart the watchdog */ + + timer_restart(u.timer, itimer); + } +#else + /* (casting to uintptr_t first eliminates complaints on some architectures + * where the sizeof uint32_t is different from the size of a pointer). + */ + + FAR struct posix_timer_s *timer = (FAR struct posix_timer_s *)((uintptr_t)itimer); + + /* Send the specified signal to the specified task. Increment the reference + * count on the timer first so that will not be deleted until after the + * signal handler returns. + */ + + timer->pt_crefs++; + timer_sigqueue(timer); + + /* Release the reference. timer_release will return nonzero if the timer + * was not deleted. + */ + + if (timer_release(timer)) + { + /* If this is a repetitive timer, the restart the watchdog */ + + timer_restart(timer, itimer); + } +#endif +} + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_settime + * + * Description: + * The timer_settime() function sets the time until the next expiration of the + * timer specified by timerid from the it_value member of the value argument + * and arm the timer if the it_value member of value is non-zero. If the + * specified timer was already armed when timer_settime() is called, this call + * will reset the time until next expiration to the value specified. If the + * it_value member of value is zero, the timer will be disarmed. The effect + * of disarming or resetting a timer with pending expiration notifications is + * unspecified. + * + * If the flag TIMER_ABSTIME is not set in the argument flags, timer_settime() + * will behave as if the time until next expiration is set to be equal to the + * interval specified by the it_value member of value. That is, the timer will + * expire in it_value nanoseconds from when the call is made. If the flag + * TIMER_ABSTIME is set in the argument flags, timer_settime() will behave as + * if the time until next expiration is set to be equal to the difference between + * the absolute time specified by the it_value member of value and the current + * value of the clock associated with timerid. That is, the timer will expire + * when the clock reaches the value specified by the it_value member of value. + * If the specified time has already passed, the function will succeed and the + * expiration notification will be made. + * + * The reload value of the timer will be set to the value specified by the + * it_interval member of value. When a timer is armed with a non-zero + * it_interval, a periodic (or repetitive) timer is specified. + * + * Time values that are between two consecutive non-negative integer multiples + * of the resolution of the specified timer will be rounded up to the larger + * multiple of the resolution. Quantization error will not cause the timer to + * expire earlier than the rounded time value. + * + * If the argument ovalue is not NULL, the timer_settime() function will store, + * in the location referenced by ovalue, a value representing the previous + * amount of time before the timer would have expired, or zero if the timer was + * disarmed, together with the previous timer reload value. Timers will not + * expire before their scheduled time. + * + * Parameters: + * timerid - The pre-thread timer, previously created by the call to + * timer_create(), to be be set. + * flags - Specifie characteristics of the timer (see above) + * value - Specifies the timer value to set + * ovalue - A location in which to return the time remaining from the previous + * timer setting. (ignored) + * + * Return Value: + * If the timer_settime() succeeds, a value of 0 (OK) will be returned. + * If an error occurs, the value -1 (ERROR) will be returned, and errno set to + * indicate the error. + * + * EINVAL - The timerid argument does not correspond to an ID returned by + * timer_create() but not yet deleted by timer_delete(). + * EINVAL - A value structure specified a nanosecond value less than zero or + * greater than or equal to 1000 million, and the it_value member of that + * structure did not specify zero seconds and nanoseconds. + * + * Assumptions: + * + ********************************************************************************/ + +int timer_settime(timer_t timerid, int flags, FAR const struct itimerspec *value, + FAR struct itimerspec *ovalue) +{ + FAR struct posix_timer_s *timer = (FAR struct posix_timer_s *)timerid; + irqstate_t state; + int delay; + int ret = OK; + + /* Some sanity checks */ + + if (!timer || !value) + { + errno = EINVAL; + return ERROR; + } + + /* Disarm the timer (in case the timer was already armed when timer_settime() + * is called). + */ + + (void)wd_cancel(timer->pt_wdog); + + /* If the it_value member of value is zero, the timer will not be re-armed */ + + if (value->it_value.tv_sec <= 0 && value->it_value.tv_nsec <= 0) + { + return OK; + } + + /* Setup up any repititive timer */ + + if (value->it_interval.tv_sec > 0 || value->it_interval.tv_nsec > 0) + { + (void)clock_time2ticks(&value->it_interval, &timer->pt_delay); + } + else + { + timer->pt_delay = 0; + } + + /* We need to disable timer interrupts through the following section so + * that the system timer is stable. + */ + + state = irqsave(); + + /* Check if abstime is selected */ + + if ((flags & TIMER_ABSTIME) != 0) + { +#ifdef CONFIG_DISABLE_CLOCK + /* Absolute timing depends upon having access to clock functionality */ + + errno = ENOSYS; + return ERROR; +#else + /* Calculate a delay corresponding to the absolute time in 'value'. + * NOTE: We have internal knowledge the clock_abstime2ticks only + * returns an error if clockid != CLOCK_REALTIME. + */ + + (void)clock_abstime2ticks(CLOCK_REALTIME, &value->it_value, &delay); +#endif + } + else + { + /* Calculate a delay assuming that 'value' holds the relative time + * to wait. We have internal knowledge that clock_time2ticks always + * returns success. + */ + + (void)clock_time2ticks(&value->it_value, &delay); + } + + /* If the time is in the past or now, then set up the next interval + * instead (assuming a repititive timer). + */ + + if (delay <= 0) + { + delay = timer->pt_delay; + } + + /* Then start the watchdog */ + + + if (delay > 0) + { + timer->pt_last = delay; + ret = wd_start(timer->pt_wdog, delay, (wdentry_t)timer_timeout, + 1, (uint32_t)((uintptr_t)timer)); + } + + irqrestore(state); + return ret; +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/usleep.c b/nuttx/sched/usleep.c new file mode 100644 index 0000000000..21996d788b --- /dev/null +++ b/nuttx/sched/usleep.c @@ -0,0 +1,168 @@ +/**************************************************************************** + * sched/usleep.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usleep + * + * Description: + * The usleep() function will cause the calling thread to be suspended + * from execution until either the number of real-time microseconds + * specified by the argument 'usec' has elapsed or a signal is delivered + * to the calling thread. The suspension time may be longer than requested + * due to the scheduling of other activity by the system. + * + * The 'usec' argument must be less than 1,000,000. If the value of + * 'usec' is 0, then the call has no effect. + * + * If a SIGALRM signal is generated for the calling process during + * execution of usleep() and if the SIGALRM signal is being ignored or + * blocked from delivery, it is unspecified whether usleep() returns + * when the SIGALRM signal is scheduled. If the signal is being blocked, it + * is also unspecified whether it remains pending after usleep() returns or + * it is discarded. + * + * If a SIGALRM signal is generated for the calling process during + * execution of usleep(), except as a result of a prior call to alarm(), + * and if the SIGALRM signal is not being ignored or blocked from delivery, + * it is unspecified whether that signal has any effect other than causing + * usleep() to return. + * + * If a signal-catching function interrupts usleep() and examines or changes + * either the time a SIGALRM is scheduled to be generated, the action + * associated with the SIGALRM signal, or whether the SIGALRM signal is + * blocked from delivery, the results are unspecified. + * + * If a signal-catching function interrupts usleep() and calls siglongjmp() + * or longjmp() to restore an environment saved prior to the usleep() call, + * the action associated with the SIGALRM signal and the time at which a + * SIGALRM signal is scheduled to be generated are unspecified. It is also + * unspecified whether the SIGALRM signal is blocked, unless the process' + * signal mask is restored as part of the environment. + * + * Implementations may place limitations on the granularity of timer values. + * For each interval timer, if the requested timer value requires a finer + * granularity than the implementation supports, the actual timer value will + * be rounded up to the next supported value. + * + * Interactions between usleep() and any of the following are unspecified: + * + * nanosleep(), setitimer(), timer_create(), timer_delete(), timer_getoverrun(), + * timer_gettime(), timer_settime(), ualarm(), sleep() + + * Parameters: + * usec - the number of microseconds to wait. + * + * Returned Value: + * On successful completion, usleep() returns 0. Otherwise, it returns -1 + * and sets errno to indicate the error. + * + * Assumptions: + * + ****************************************************************************/ + +int usleep(useconds_t usec) +{ + sigset_t set; + struct timespec ts; + struct siginfo value; + int errval; + int ret = 0; + + if (usec) + { + /* Set up for the sleep. Using the empty set means that we are not + * waiting for any particualar signal. However, any unmasked signal + * can still awaken sigtimedwait(). + */ + + (void)sigemptyset(&set); + ts.tv_sec = usec / 1000000; + ts.tv_nsec = (usec % 1000000) * 1000; + + /* usleep is a simple application of sigtimedwait. */ + + ret = sigtimedwait(&set, &value, &ts); + + /* sigtimedwait() cannot succeed. It should always return error with + * either (1) EAGAIN meaning that the timeout occurred, or (2) EINTR + * meaning that some other unblocked signal was caught. + */ + + errval = errno; + DEBUGASSERT(ret < 0 && (errval == EAGAIN || errval == EINTR)); + if (errval == EAGAIN) + { + /* The timeout "error" is the normal, successful result */ + + ret = 0; + } + } + + return ret; +} diff --git a/nuttx/sched/wd_cancel.c b/nuttx/sched/wd_cancel.c new file mode 100644 index 0000000000..0bd59cf895 --- /dev/null +++ b/nuttx/sched/wd_cancel.c @@ -0,0 +1,165 @@ +/**************************************************************************** + * sched/wd_cancel.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "os_internal.h" +#include "wd_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wd_cancel + * + * Description: + * This function cancels a currently running watchdog timer. Watchdog + * timers may be canceled from the interrupt level. + * + * Parameters: + * wdid - ID of the watchdog to cancel. + * + * Return Value: + * OK or ERROR + * + * Assumptions: + * + ****************************************************************************/ + +int wd_cancel (WDOG_ID wdid) +{ + wdog_t *curr; + wdog_t *prev; + irqstate_t saved_state; + int ret = ERROR; + + /* Prohibit timer interactions with the timer queue until the + * cancellation is complete + */ + + saved_state = irqsave(); + + /* Make sure that the watchdog is initialed (non-NULL) and is still active */ + + if (wdid && wdid->active) + { + /* Search the g_wdactivelist for the target FCB. We can't use sq_rem + * to do this because there are additional operations that need to be + * done. + */ + + prev = NULL; + curr = (wdog_t*)g_wdactivelist.head; + + while((curr) && (curr != wdid)) + { + prev = curr; + curr = curr->next; + } + + /* Check if the watchdog was found in the list. If not, then an OS + * error has occurred because the watchdog is marked active! + */ + + if (!curr) + { + PANIC(OSERR_WDOGNOTFOUND); + } + else + { + /* If there is a watchdog in the timer queue after the one that + * is being canceled, then it inherits the remaining ticks. + */ + + if (curr->next) + { + curr->next->lag += curr->lag; + } + + /* Now, remove the watchdog from the timer queue */ + + if (prev) + { + (void)sq_remafter((FAR sq_entry_t*)prev, &g_wdactivelist); + } + else + { + (void)sq_remfirst(&g_wdactivelist); + } + wdid->next = NULL; + + /* Return success */ + + ret = OK; + } + + /* Mark the watchdog inactive */ + + wdid->active = false; + } + + irqrestore(saved_state); + return ret; +} diff --git a/nuttx/sched/wd_create.c b/nuttx/sched/wd_create.c new file mode 100644 index 0000000000..d86171bf7d --- /dev/null +++ b/nuttx/sched/wd_create.c @@ -0,0 +1,109 @@ +/**************************************************************************** + * sched/wd_create.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "wd_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wd_create + * + * Description: + * The wd_create function will create a watchdog by allocating it from the + * list of free watchdogs. + * + * Parameters: + * None + * + * Return Value: + * Pointer to watchdog (i.e., the watchdog ID), or NULL if insufficient + * watchdogs are available. + * + * Assumptions: + * + ****************************************************************************/ + +WDOG_ID wd_create (void) +{ + FAR wdog_t *wdog; + irqstate_t saved_state; + + saved_state = irqsave(); + wdog = (FAR wdog_t*)sq_remfirst(&g_wdfreelist); + irqrestore(saved_state); + + /* Indicate that the watchdog is not actively timing */ + + if (wdog) + { + wdog->next = NULL; + wdog->active = false; + } + + return (WDOG_ID)wdog; +} diff --git a/nuttx/sched/wd_delete.c b/nuttx/sched/wd_delete.c new file mode 100644 index 0000000000..16c123e139 --- /dev/null +++ b/nuttx/sched/wd_delete.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * sched/wd_delete.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "wd_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wd_delete + * + * Description: + * The wd_delete function will deallocate a watchdog by returning it to + * the free pool of watchdogs. The watchdog will be removed from the timer + * queue if has been started. + * + * Parameters: + * wdId - The watchdog ID to delete. This is actually a pointer to a + * watchdog structure. + * + * Return Value: + * Returns OK or ERROR + * + * Assumptions: + * The caller has assured that the watchdog is no longer in use. + * + ****************************************************************************/ + +int wd_delete(WDOG_ID wdId) +{ + irqstate_t saved_state; + + /* Verify that a valid watchdog was provided */ + + if (!wdId) + { + set_errno(EINVAL); + return ERROR; + } + + /* The following steps are atomic... the watchdog must not be active when + * it is being deallocated. + */ + + saved_state = irqsave(); + + /* Check if the watchdog has been started. */ + + if (wdId->active) + { + wd_cancel(wdId); + } + + /* Put the watchdog back on the free list */ + + sq_addlast((FAR sq_entry_t*)wdId, &g_wdfreelist); + irqrestore(saved_state); + + /* Return success */ + + return OK; +} diff --git a/nuttx/sched/wd_gettime.c b/nuttx/sched/wd_gettime.c new file mode 100644 index 0000000000..caa4825497 --- /dev/null +++ b/nuttx/sched/wd_gettime.c @@ -0,0 +1,118 @@ +/******************************************************************************** + * sched/wd_gettime.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************/ + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include + +#include "os_internal.h" +#include "wd_internal.h" + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Types + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: wd_gettime + * + * Description: + * This function returns the time remaining before the specified watchdog + * expires. + * + * Parameters: + * wdog = watchdog ID + * + * Return Value: + * The time in system ticks remaining until the watchdog time expires. Zero + * means either that wdog is not valid or that the wdog has already expired. + * + * Assumptions: + * + ********************************************************************************/ + +int wd_gettime(WDOG_ID wdog) +{ + irqstate_t flags; + + /* Verify the wdog */ + + flags = irqsave(); + if (wdog && wdog->active) + { + /* Traverse the watchdog list accumulating lag times until we find the wdog + * that we are looking for + */ + + wdog_t *curr; + int delay = 0; + + for (curr = (wdog_t*)g_wdactivelist.head; curr; curr = curr->next) + { + delay += curr->lag; + if (curr == wdog) + { + irqrestore(flags); + return delay; + } + } + } + + irqrestore(flags); + return 0; +} diff --git a/nuttx/sched/wd_initialize.c b/nuttx/sched/wd_initialize.c new file mode 100644 index 0000000000..db7aba5024 --- /dev/null +++ b/nuttx/sched/wd_initialize.c @@ -0,0 +1,135 @@ +/************************************************************************ + * sched/wd_initialize.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include + +#include "os_internal.h" +#include "wd_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/* The g_wdfreelist data structure is a singly linked list of watchdogs + * available to the system for delayed function use. + */ + +sq_queue_t g_wdfreelist; + +/* g_wdpool is a pointer to a list of pre-allocated watchdogs. The number + * of watchdogs in the pool is a configuration item. + */ + +FAR wdog_t *g_wdpool; + +/* The g_wdactivelist data structure is a singly linked list ordered by + * watchdog expiration time. When watchdog timers expire,the functions on + * this linked list are removed and the function is called. + */ + +sq_queue_t g_wdactivelist; + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: wd_initialize + * + * Description: + * This function initalized the watchdog data structures + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * This function must be called early in the initialization sequence + * before the timer interrupt is attached and before any watchdog + * services are used. + * + ************************************************************************/ + +void wd_initialize(void) +{ + /* Initialize the free watchdog list */ + + sq_init(&g_wdfreelist); + + /* The g_wdfreelist must be loaded at initialization time to hold the + * configured number of watchdogs. + */ + + g_wdpool = (FAR wdog_t*)kmalloc(sizeof(wdog_t) * CONFIG_PREALLOC_WDOGS); + if (g_wdpool) + { + FAR wdog_t *wdog = g_wdpool; + int i; + + for (i = 0; i < CONFIG_PREALLOC_WDOGS; i++) + { + sq_addlast((FAR sq_entry_t*)wdog++, &g_wdfreelist); + } + } + + /* The g_wdactivelist queue must be reset at initialization time. */ + + sq_init(&g_wdactivelist); +} diff --git a/nuttx/sched/wd_internal.h b/nuttx/sched/wd_internal.h new file mode 100644 index 0000000000..e63a8bdae4 --- /dev/null +++ b/nuttx/sched/wd_internal.h @@ -0,0 +1,119 @@ +/************************************************************************ + * sched/d_internal.h + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +#ifndef __SCHED_WD_INTERNAL_H +#define __SCHED_WD_INTERNAL_H + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include + +#include + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Public Type Declarations + ************************************************************************/ + +/* This is the watchdog structure. The WDOG_ID is a pointer to a + * watchdog structure. + */ + +struct wdog_s +{ + FAR struct wdog_s *next; /* Support for singly linked lists. */ + wdentry_t func; /* Function to execute when delay expires */ +#ifdef CONFIG_PIC + FAR void *picbase; /* PIC base address */ +#endif + int lag; /* Timer associated with the delay */ + bool active; /* true if the watchdog is actively timing */ + uint8_t argc; /* The number of parameters to pass */ + uint32_t parm[CONFIG_MAX_WDOGPARMS]; +}; +typedef struct wdog_s wdog_t; + +/************************************************************************ + * Public Variables + ************************************************************************/ + +/* The g_wdfreelist data structure is a singly linked list of watchdogs + * available to the system for delayed function use. + */ + +extern sq_queue_t g_wdfreelist; + +/* g_wdpool is a pointer to a list of pre-allocated watchdogs. The number + * of watchdogs in the pool is a configuration item. + */ + +extern FAR wdog_t *g_wdpool; + +/* The g_wdactivelist data structure is a singly linked list ordered by + * watchdog expiration time. When watchdog timers expire,the functions on + * this linked list are removed and the function is called. + */ + +extern sq_queue_t g_wdactivelist; + +/************************************************************************ + * Public Function Prototypes + ************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN void weak_function wd_initialize(void); +EXTERN void weak_function wd_timer(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __SCHED_WD_INTERNAL_H */ diff --git a/nuttx/sched/wd_start.c b/nuttx/sched/wd_start.c new file mode 100644 index 0000000000..2a69d131a0 --- /dev/null +++ b/nuttx/sched/wd_start.c @@ -0,0 +1,375 @@ +/**************************************************************************** + * sched/wd_start.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "wd_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +typedef void (*wdentry0_t)(int argc); +#if CONFIG_MAX_WDOGPARMS > 0 +typedef void (*wdentry1_t)(int argc, uint32_t arg1); +#endif +#if CONFIG_MAX_WDOGPARMS > 1 +typedef void (*wdentry2_t)(int argc, uint32_t arg1, uint32_t arg2); +#endif +#if CONFIG_MAX_WDOGPARMS > 2 +typedef void (*wdentry3_t)(int argc, uint32_t arg1, uint32_t arg2, + uint32_t arg3); +#endif +#if CONFIG_MAX_WDOGPARMS > 3 +typedef void (*wdentry4_t)(int argc, uint32_t arg1, uint32_t arg2, + uint32_t arg3, uint32_t arg4); +#endif + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wd_start + * + * Description: + * This function adds a watchdog to the timer queue. The specified + * watchdog function will be called from the interrupt level after the + * specified number of ticks has elapsed. Watchdog timers may be started + * from the interrupt level. + * + * Watchdog timers execute in the address enviroment that was in effect + * when wd_start() is called. + * + * Watchdog timers execute only once. + * + * To replace either the timeout delay or the function to be executed, + * call wd_start again with the same wdog; only the most recent wdStart() + * on a given watchdog ID has any effect. + * + * Parameters: + * wdog = watchdog ID + * delay = Delay count in clock ticks + * wdentry = function to call on timeout + * parm1..4 = parameters to pass to wdentry + * + * Return Value: + * OK or ERROR + * + * Assumptions: + * The watchdog routine runs in the context of the timer interrupt handler + * and is subject to all ISR restrictions. + * + ****************************************************************************/ + +int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...) +{ + va_list ap; + FAR wdog_t *curr; + FAR wdog_t *prev; + FAR wdog_t *next; + int32_t now; + irqstate_t saved_state; + int i; + + /* Verify the wdog */ + + if (!wdog || argc > CONFIG_MAX_WDOGPARMS || delay < 0) + { + set_errno(EINVAL); + return ERROR; + } + + /* Check if the watchdog has been started. If so, stop it. + * NOTE: There is a race condition here... the caller may receive + * the watchdog between the time that wd_start is called and + * the critical section is established. + */ + + saved_state = irqsave(); + if (wdog->active) + { + wd_cancel(wdog); + } + + /* Save the data in the watchdog structure */ + + wdog->func = wdentry; /* Function to execute when delay expires */ + up_getpicbase(&wdog->picbase); + wdog->argc = argc; + + va_start(ap, argc); + for (i = 0; i < argc; i++) + { + wdog->parm[i] = va_arg(ap, uint32_t); + } +#ifdef CONFIG_DEBUG + for (; i < CONFIG_MAX_WDOGPARMS; i++) + { + wdog->parm[i] = 0; + } +#endif + va_end(ap); + + /* Calculate delay+1, forcing the delay into a range that we can handle */ + + if (delay <= 0) + { + delay = 1; + } + else if (++delay <= 0) + { + delay--; + } + + /* Do the easy case first -- when the watchdog timer queue is empty. */ + + if (g_wdactivelist.head == NULL) + { + sq_addlast((FAR sq_entry_t*)wdog,&g_wdactivelist); + } + + /* There are other active watchdogs in the timer queue */ + + else + { + now = 0; + prev = curr = (FAR wdog_t*)g_wdactivelist.head; + + /* Advance to positive time */ + + while ((now += curr->lag) < 0 && curr->next) + { + prev = curr; + curr = curr->next; + } + + /* Advance past shorter delays */ + + while (now <= delay && curr->next) + { + prev = curr; + curr = curr->next; + now += curr->lag; + } + + /* Check if the new wdog must be inserted before the curr. */ + + if (delay < now) + { + /* The relative delay time is smaller or equal to the current delay + * time, so decrement the current delay time by the new relative + * delay time. + */ + + delay -= (now - curr->lag); + curr->lag -= delay; + + /* Insert the new watchdog in the list */ + + if (curr == (FAR wdog_t*)g_wdactivelist.head) + { + sq_addfirst((FAR sq_entry_t*)wdog, &g_wdactivelist); + } + else + { + sq_addafter((FAR sq_entry_t*)prev, (FAR sq_entry_t*)wdog, + &g_wdactivelist); + } + } + + /* The new watchdog delay time is greater than the curr delay time, + * so the new wdog must be inserted after the curr. This only occurs + * if the wdog is to be added to the end of the list. + */ + + else + { + delay -= now; + if (!curr->next) + { + sq_addlast((FAR sq_entry_t*)wdog, &g_wdactivelist); + } + else + { + next = curr->next; + next->lag -= delay; + sq_addafter((FAR sq_entry_t*)curr, (FAR sq_entry_t*)wdog, + &g_wdactivelist); + } + } + } + + /* Put the lag into the watchdog structure and mark it as active. */ + + wdog->lag = delay; + wdog->active = true; + + irqrestore(saved_state); + return OK; +} + +/**************************************************************************** + * Name: wd_timer + * + * Description: + * This function is called from the timer interrupt handler to determine + * if it is time to execute a watchdog function. If so, the watchdog + * function will be executed in the context of the timer interrupt handler. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void wd_timer(void) +{ + FAR wdog_t *wdog; + + /* Check if there are any active watchdogs to process */ + + if (g_wdactivelist.head) + { + /* There are. Decrement the lag counter */ + + --(((FAR wdog_t*)g_wdactivelist.head)->lag); + + /* Check if the watchdog at the head of the list is ready to run */ + + if (((FAR wdog_t*)g_wdactivelist.head)->lag <= 0) + { + /* Process the watchdog at the head of the list as well as any + * other watchdogs that became ready to run at this time + */ + + while (g_wdactivelist.head && + ((FAR wdog_t*)g_wdactivelist.head)->lag <= 0) + { + /* Remove the watchdog from the head of the list */ + + wdog = (FAR wdog_t*)sq_remfirst(&g_wdactivelist); + + /* If there is another watchdog behind this one, update its + * its lag (this shouldn't be necessary). + */ + + if (g_wdactivelist.head) + { + ((FAR wdog_t*)g_wdactivelist.head)->lag += wdog->lag; + } + + /* Indicate that the watchdog is no longer active. */ + + wdog->active = false; + + /* Execute the watchdog function */ + + up_setpicbase(wdog->picbase); + switch (wdog->argc) + { + default: +#ifdef CONFIG_DEBUG + PANIC(OSERR_INTERNAL); +#endif + case 0: + (*((wdentry0_t)(wdog->func)))(0); + break; + +#if CONFIG_MAX_WDOGPARMS > 0 + case 1: + (*((wdentry1_t)(wdog->func)))(1, wdog->parm[0]); + break; +#endif +#if CONFIG_MAX_WDOGPARMS > 1 + case 2: + (*((wdentry2_t)(wdog->func)))(2, + wdog->parm[0], wdog->parm[1]); + break; +#endif +#if CONFIG_MAX_WDOGPARMS > 2 + case 3: + (*((wdentry3_t)(wdog->func)))(3, + wdog->parm[0], wdog->parm[1], + wdog->parm[2]); + break; +#endif +#if CONFIG_MAX_WDOGPARMS > 3 + case 4: + (*((wdentry4_t)(wdog->func)))(4, + wdog->parm[0], wdog->parm[1], + wdog->parm[2] ,wdog->parm[3]); + break; +#endif + } + } + } + } +} diff --git a/nuttx/sched/work_cancel.c b/nuttx/sched/work_cancel.c new file mode 100644 index 0000000000..c277f024d2 --- /dev/null +++ b/nuttx/sched/work_cancel.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * sched/work_cancel.c + * + * Copyright (C) 2009-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "work_internal.h" + +#ifdef CONFIG_SCHED_WORKQUEUE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: work_cancel + * + * Description: + * Cancel previously queued work. This removes work from the work queue. + * After work has been canceled, it may be re-queue by calling work_queue() + * again. + * + * Input parameters: + * work - The previously queue work structure to cancel + * + * Returned Value: + * Zero on success, a negated errno on failure + * + ****************************************************************************/ + +int work_cancel(struct work_s *work) +{ + irqstate_t flags; + + DEBUGASSERT(work != NULL); + + /* Cancelling the work is simply a matter of removing the work structure + * from the work queue. This must be done with interrupts disabled because + * new work is typically added to the work queue from interrupt handlers. + */ + + flags = irqsave(); + if (work->worker != NULL) + { + DEBUGASSERT(work->dq.flink || (FAR dq_entry_t *)work == g_work.head); + DEBUGASSERT(work->dq.blink || (FAR dq_entry_t *)work == g_work.tail); + dq_rem((FAR dq_entry_t *)work, &g_work); + + work->worker = NULL; + } + + irqrestore(flags); + return OK; +} +#endif /* CONFIG_SCHED_WORKQUEUE */ diff --git a/nuttx/sched/work_internal.h b/nuttx/sched/work_internal.h new file mode 100644 index 0000000000..69b7bf5470 --- /dev/null +++ b/nuttx/sched/work_internal.h @@ -0,0 +1,112 @@ +/**************************************************************************** + * sched/work_internal.h + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __SCHED_WORK_INTERNAL_H +#define __SCHED_WORK_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifdef CONFIG_SCHED_WORKQUEUE + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_SCHED_WORKPRIORITY +# define CONFIG_SCHED_WORKPRIORITY 50 +#endif + +#ifndef CONFIG_SCHED_WORKPERIOD +# define CONFIG_SCHED_WORKPERIOD (50*1000) /* 50 milliseconds */ +#endif + +#ifndef CONFIG_SCHED_WORKSTACKSIZE +# define CONFIG_SCHED_WORKSTACKSIZE CONFIG_IDLETHREAD_STACKSIZE +#endif + +#ifdef CONFIG_DISABLE_SIGNALS +# warning "Worker thread support requires signals" +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* The queue of pending work */ + +extern struct dq_queue_s g_work; + +/* The task ID of the worker thread */ + +extern pid_t g_worker; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: work_thread + * + * Description: + * This is the main worker thread that performs actions placed on the work + * queue. It also performs periodic garbage collection (that is performed + * by the idle thread if CONFIG_SCHED_WORKQUEUE is not defined). + * + * Input parameters: + * argc, argv (not used) + * + * Returned Value: + * Does not return + * + ****************************************************************************/ + +int work_thread(int argc, char *argv[]); + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_SCHED_WORKQUEUE */ +#endif /* __SCHED_WORK_INTERNAL_H */ diff --git a/nuttx/sched/work_queue.c b/nuttx/sched/work_queue.c new file mode 100644 index 0000000000..beeac168dd --- /dev/null +++ b/nuttx/sched/work_queue.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * sched/work_queue.c + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "work_internal.h" + +#ifdef CONFIG_SCHED_WORKQUEUE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: work_queue + * + * Description: + * Queue work to be performed at a later time. All queued work will be + * performed on the worker thread of of execution (not the caller's). + * + * The work structure is allocated by caller, but completely managed by + * the work queue logic. The caller should never modify the contents of + * the work queue structure; the caller should not call work_queue() + * again until either (1) the previous work has been performed and removed + * from the queue, or (2) work_cancel() has been called to cancel the work + * and remove it from the work queue. + * + * Input parameters: + * work - The work structure to queue + * worker - The worker callback to be invoked. The callback will invoked + * on the worker thread of execution. + * arg - The argument that will be passed to the workder callback when + * int is invoked. + * delay - Delay (in clock ticks) from the time queue until the worker + * is invoked. Zero means to perform the work immediately. + * + * Returned Value: + * Zero on success, a negated errno on failure + * + ****************************************************************************/ + +int work_queue(struct work_s *work, worker_t worker, FAR void *arg, uint32_t delay) +{ + irqstate_t flags; + + DEBUGASSERT(work != NULL); + + /* First, initialize the work structure */ + + work->worker = worker; /* Work callback */ + work->arg = arg; /* Callback argument */ + work->delay = delay; /* Delay until work performed */ + + /* Now, time-tag that entry and put it in the work queue. This must be + * done with interrupts disabled. This permits this function to be called + * from with task logic or interrupt handlers. + */ + + flags = irqsave(); + work->qtime = clock_systimer(); /* Time work queued */ + dq_addlast((FAR dq_entry_t *)work, &g_work); + work_signal(); /* Wake up the worker thread */ + irqrestore(flags); + return OK; +} + +#endif /* CONFIG_SCHED_WORKQUEUE */ diff --git a/nuttx/sched/work_thread.c b/nuttx/sched/work_thread.c new file mode 100644 index 0000000000..fe14ae5e58 --- /dev/null +++ b/nuttx/sched/work_thread.c @@ -0,0 +1,215 @@ +/**************************************************************************** + * sched/work_thread.c + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "os_internal.h" +#include "work_internal.h" + +#ifdef CONFIG_SCHED_WORKQUEUE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* The queue of pending work */ + +struct dq_queue_s g_work; + +/* The task ID of the worker thread */ + +#ifdef CONFIG_SCHED_WORKQUEUE +pid_t g_worker; +#endif + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: work_thread + * + * Description: + * This is the main worker thread that performs actions placed on the work + * list. It also performs periodic garbage collection (that is performed + * by the idle thread if CONFIG_SCHED_WORKQUEUE is not defined). + * + * Input parameters: + * argc, argv (not used) + * + * Returned Value: + * Does not return + * + ****************************************************************************/ + +int work_thread(int argc, char *argv[]) +{ + volatile FAR struct work_s *work; + worker_t worker; + FAR void *arg; + uint32_t elapsed; + uint32_t remaining; + uint32_t next; + int usec; + irqstate_t flags; + + /* Loop forever */ + + usec = CONFIG_SCHED_WORKPERIOD; + flags = irqsave(); + for (;;) + { + /* Wait awhile to check the work list. We will wait here until either + * the time elapses or until we are awakened by a signal. + */ + + usleep(usec); + irqrestore(flags); + + /* First, perform garbage collection. This cleans-up memory de-allocations + * that were queued because they could not be freed in that execution + * context (for example, if the memory was freed from an interrupt handler). + * NOTE: If the work thread is disabled, this clean-up is performed by + * the IDLE thread (at a very, very lower priority). + */ + + sched_garbagecollection(); + + /* Then process queued work. We need to keep interrupts disabled while + * we process items in the work list. + */ + + next = CONFIG_SCHED_WORKPERIOD / USEC_PER_TICK; + flags = irqsave(); + work = (FAR struct work_s *)g_work.head; + while (work) + { + /* Is this work ready? It is ready if there is no delay or if + * the delay has elapsed. qtime is the time that the work was added + * to the work queue. It will always be greater than or equal to + * zero. Therefore a delay of zero will always execute immediately. + */ + + elapsed = clock_systimer() - work->qtime; + if (elapsed >= work->delay) + { + /* Remove the ready-to-execute work from the list */ + + (void)dq_rem((struct dq_entry_s *)work, &g_work); + + /* Extract the work description from the entry (in case the work + * instance by the re-used after it has been de-queued). + */ + + worker = work->worker; + arg = work->arg; + + /* Mark the work as no longer being queued */ + + work->worker = NULL; + + /* Do the work. Re-enable interrupts while the work is being + * performed... we don't have any idea how long that will take! + */ + + irqrestore(flags); + worker(arg); + + /* Now, unfortunately, since we re-enabled interrupts we don't + * know the state of the work list and we will have to start + * back at the head of the list. + */ + + flags = irqsave(); + work = (FAR struct work_s *)g_work.head; + } + else + { + /* This one is not ready.. will it be ready before the next + * scheduled wakeup interval? + */ + + remaining = elapsed - work->delay; + if (remaining < next) + { + /* Yes.. Then schedule to wake up when the work is ready */ + + next = remaining; + } + + /* Then try the next in the list. */ + + work = (FAR struct work_s *)work->dq.flink; + } + } + + /* Now calculate the microsecond delay we should wait */ + + usec = next * USEC_PER_TICK; + } + + return OK; /* To keep some compilers happy */ +} +#endif /* CONFIG_SCHED_WORKQUEUE */ diff --git a/nuttx/syscall/Kconfig b/nuttx/syscall/Kconfig new file mode 100644 index 0000000000..ae2bf31307 --- /dev/null +++ b/nuttx/syscall/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# diff --git a/nuttx/syscall/Makefile b/nuttx/syscall/Makefile new file mode 100644 index 0000000000..7ef1a46295 --- /dev/null +++ b/nuttx/syscall/Makefile @@ -0,0 +1,113 @@ +############################################################################ +# syscall/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +########################################################################### + +-include $(TOPDIR)/Make.defs +include proxies/Make.defs +include stubs/Make.defs + +MKSYSCALL = "$(TOPDIR)/tools/mksyscall$(EXEEXT)" +CSVFILE = "$(TOPDIR)/syscall/syscall.csv" + +STUB_SRCS += stub_lookup.c + +ASRCS = +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +PROXY_OBJS = $(PROXY_SRCS:.c=$(OBJEXT)) +STUB_OBJS = $(STUB_SRCS:.c=$(OBJEXT)) + +CSRCS = $(PROXY_SRCS) $(STUB_SRCS) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ROOTDEPPATH = --dep-path . +PROXYDEPPATH = --dep-path proxies +STUBDEPPATH = --dep-path stubs +VPATH = proxies:stubs + +BIN1 = libproxies$(LIBEXT) +BIN2 = libstubs$(LIBEXT) + +all: $(BIN1) $(BIN2) +.PHONY: context depend clean distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN1): $(PROXY_OBJS) + @( for obj in $(PROXY_OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +$(BIN2): $(STUB_OBJS) + @( for obj in $(STUB_OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(PROXYDEPPATH) $(STUBDEPPATH) \ + $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +$(MKSYSCALL): + @$(MAKE) -C $(TOPDIR)/tools -f Makefile.host mksyscall + +.context: syscall.csv + @(cd proxies; $(MKSYSCALL) -p $(CSVFILE);) + @(cd stubs; $(MKSYSCALL) -s $(CSVFILE);) + @touch $@ + +context: $(MKSYSCALL) .context + +clean: + @rm -f $(BIN1) $(BIN2) *~ .*.swp +ifneq ($(OBJEXT),) + @rm -f proxies/*$(OBJEXT) stubs/*$(OBJEXT) +endif + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend .context + @rm -f proxies/*.c stubs/*.c + +-include Make.dep + diff --git a/nuttx/syscall/README.txt b/nuttx/syscall/README.txt new file mode 100644 index 0000000000..0b77f50bfc --- /dev/null +++ b/nuttx/syscall/README.txt @@ -0,0 +1,143 @@ +syscall/README.txt +================== + +This directory supports a syscall layer from communication between a +monolithic, kernel-mode NuttX kernel and a separately built, user-mode +application set. + +With most MCUs, NuttX is built as a flat, single executable image +containing the NuttX RTOS along with all application code. The RTOS code +and the application run in the same address space and at the same kernel- +mode privileges. In order to exploit security features of certain +processors, an alternative build model is also supported: NuttX can +be built separately as a monolithic, kernel-mode module and the applications +can be added as a separately built, user-mode module. + +The syscall layer provided in this directory serves as the communication +layer from the user-mode application into the kernel-mode RTOS. The +switch from user-mode to kernel-mode is accomplished using software +interrupts (SWIs). SWIs are implemented differently and named differently +by different manufacturers but all work essentially the same: A special +instruction is executed in user-mode that causes a software generated +interrupt. The software generated interrupt is caught within the kernel +and handle in kernel-mode. + +Header Files +============ + +include/syscall.h + + This header file supports general access to SWI facilities. It is simply + a wrapper file that includes include/sys/syscall.h and + include/arch/syscall.h. + +include/sys/syscall.h + + The SWIs received by the kernel are distinguish by a code that identifies + how to process the SWI. This header file defines all such codes understood + by the NuttX kernel. + +include/arch/syscall.h (or arch//include/syscall.h) + + This header file is provided by the platform-specific logic and declares + (or defines) the mechanism for providing software interrupts on this + platform. The following functions must be declared (or defined) in this + header file: + + - SWI with SYS_ call number and one parameter + + uintptr_t sys_call0(unsigned int nbr); + + - SWI with SYS_ call number and one parameter + + uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1); + + - SWI with SYS_ call number and two parameters + + uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, uintptr_t parm2); + + - SWI with SYS_ call number and three parameters + + uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3); + + - SWI with SYS_ call number and four parameters + + uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, + uintptr_t parm3, uintptr_t parm4); + + - SWI with SYS_ call number and five parameters + + uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, + uintptr_t parm3, uintptr_t parm4, uintptr_t parm5); + + - SWI with SYS_ call number and six parameters + + uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, + uintptr_t parm3, uintptr_t parm4, uintptr_t parm5, + uintptr_t parm6); +Syscall Database +================ + +Sycall information is maintained in a database. That "database" is +implemented as a simple comma-separated-value file, syscall.csv. Most +spreadsheets programs will accept this format and can be used to maintain +the syscall database. + +The format of the CSV file for each line is: + + Field 1: Function name + Field 2: The header file that contains the function prototype + Field 3: Condition for compilation + Field 4: The type of function return value. + Field 5 - N+5: The type of each of the N formal parameters of the function + +Each type field has a format as follows: + + type name: + For all simpler types + formal type | actual type: + For array types where the form of the formal (eg. int parm[2]) + differs from the type of actual passed parameter (eg. int*). This + is necessary because you cannot do simple casts to array types. + formal type | union member actual type | union member fieldname: + A similar situation exists for unions. For example, the formal + parameter type union sigval -- You cannot cast a uintptr_t to + a union sigval, but you can cast to the type of one of the union + member types when passing the actual paramter. Similarly, we + cannot cast a union sigval to a uinptr_t either. Rather, we need + to cast a specific union member fieldname to uintptr_t. + +Auto-Generated Files +==================== + +Stubs and proxies for the sycalls are automatically generated from this CSV +database. Here the following definition is used: + + Proxy - A tiny bit of code that executes in the user space. A proxy + has exactly the same function prototype as does the "real" function + for which it proxies. However, it only serves to map the function + call into a syscall, marshaling all of the system call parameters + as necessary. + + Stub - Another tiny bit of code that executes within the NuttX kernel + that is used to map a software interrupt received by the kernel to + a kernel function call. The stubs receive the marshaled system + call data, and perform the actually kernel function call (in + kernel-mode) on behalf of the proxy function. + +Sub-Directories +=============== + + stubs - Autogenerated stub files are placed in this directory. + proxies - Autogenerated proxy files are placed in this directory. + +mksyscall +========= + + mksyscall is C program that is used used during the initial NuttX build + by the logic in the top-level syscall/ directory. Information about the + stubs and proxies is maintained in a comma separated value (CSV) file + in the syscall/ directory. The mksyscall program will accept this CVS + file as input and generate all of the required proxy or stub files as + output. See tools/README.txt for additional information. diff --git a/nuttx/syscall/proxies/Make.defs b/nuttx/syscall/proxies/Make.defs new file mode 100644 index 0000000000..abd6c01026 --- /dev/null +++ b/nuttx/syscall/proxies/Make.defs @@ -0,0 +1,37 @@ +############################################################################ +# syscall/proxies/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +PROXY_SRCS := ${shell cd proxies; ls *.c 2>/dev/null } + diff --git a/nuttx/syscall/stub_lookup.c b/nuttx/syscall/stub_lookup.c new file mode 100644 index 0000000000..9d6bf18aed --- /dev/null +++ b/nuttx/syscall/stub_lookup.c @@ -0,0 +1,272 @@ +/**************************************************************************** + * syscall/syscall_stublookup.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/* This will need to be extended if there are reserved syscall numbers */ + +#if CONFIG_CONFIG_SYS_RESERVED == 0 + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +/**************************************************************************** + * Stub Function Prototypes + ****************************************************************************/ + +/* These first system calls are supported regardless of the NuttX + * configuration + */ + +extern uintptr_t STUB__exit(uintptr_t parm1); +extern uintptr_t STUB_exit(uintptr_t parm1); +extern uintptr_t STUB_get_errno(void); +extern uintptr_t STUB_getpid(void); +extern uintptr_t STUB_sched_getparam(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_sched_getscheduler(uintptr_t parm1); +extern uintptr_t STUB_sched_lock(void); +extern uintptr_t STUB_sched_lockcount(void); +extern uintptr_t STUB_sched_rr_get_interval(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_sched_setparam(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_sched_setscheduler(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_sched_unlock(void); +extern uintptr_t STUB_sched_yield(void); +extern uintptr_t STUB_sem_close(uintptr_t parm1); +extern uintptr_t STUB_sem_destroy(uintptr_t parm1); +extern uintptr_t STUB_sem_open(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5, uintptr_t parm6); +extern uintptr_t STUB_sem_post(uintptr_t parm1); +extern uintptr_t STUB_sem_trywait(uintptr_t parm1); +extern uintptr_t STUB_sem_unlink(uintptr_t parm1); +extern uintptr_t STUB_sem_wait(uintptr_t parm1); +extern uintptr_t STUB_set_errno(uintptr_t parm1); +extern uintptr_t STUB_task_create(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5); +extern uintptr_t STUB_task_delete(uintptr_t parm1); +extern uintptr_t STUB_task_restart(uintptr_t parm1); +extern uintptr_t STUB_up_assert(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_up_assert_code(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); + +/* The following can be individually enabled */ + +extern uintptr_t STUB_atexit(uintptr_t parm1); +extern uintptr_t STUB_waitpid(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); + +/* The following are only defined is signals are supported in the NuttX + * configuration. + */ + +extern uintptr_t STUB_kill(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_sigaction(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_sigpending(uintptr_t parm1); +extern uintptr_t STUB_sigprocmask(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_sigqueue(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_sigsuspend(uintptr_t parm1); +extern uintptr_t STUB_sigtimedwait(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_sigwaitinfo(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_sleep(uintptr_t parm1); +extern uintptr_t STUB_usleep(uintptr_t parm1); + +/* The following are only defined if the system clock is enabled in the + * NuttX configuration. + */ + +extern uintptr_t STUB_clock_systimer(void); +extern uintptr_t STUB_clock_getres(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_clock_gettime(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_clock_settime(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_gettimeofday(uintptr_t parm1, uintptr_t parm2); + +/* The following are defined only if POSIX timers are supported */ + +extern uintptr_t STUB_timer_create(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_timer_delete(uintptr_t parm1); +extern uintptr_t STUB_timer_getoverrun(uintptr_t parm1); +extern uintptr_t STUB_timer_gettime(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_timer_settime(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4); + +/* The following are defined if either file or socket descriptor are + * enabled. + */ + +extern uintptr_t STUB_close(uintptr_t parm1); +extern uintptr_t STUB_ioctl(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_poll(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_read(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_select(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5); +extern uintptr_t STUB_write(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); + +/* The following are defined if file descriptors are enabled */ + +extern uintptr_t STUB_closedir(uintptr_t parm1); +extern uintptr_t STUB_dup(uintptr_t parm1); +extern uintptr_t STUB_dup2(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_fcntl(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5, uintptr_t parm6); +extern uintptr_t STUB_lseek(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_mkfifo(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_mmap(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5, uintptr_t parm6); +extern uintptr_t STUB_open(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5, uintptr_t parm6); +extern uintptr_t STUB_opendir(uintptr_t parm1); +extern uintptr_t STUB_pipe(uintptr_t parm1); +extern uintptr_t STUB_readdir(uintptr_t parm1); +extern uintptr_t STUB_rewinddir(uintptr_t parm1); +extern uintptr_t STUB_seekdir(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_stat(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_statfs(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_telldir(uintptr_t parm1); + +extern uintptr_t STUB_fs_fdopen(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_sched_getstreams(void); + +extern uintptr_t STUB_fsync(uintptr_t parm1); +extern uintptr_t STUB_mkdir(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_mount(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5); +extern uintptr_t STUB_rename(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_rmdir(uintptr_t parm1); +extern uintptr_t STUB_umount(uintptr_t parm1); +extern uintptr_t STUB_unlink(uintptr_t parm1); + +/* The following are defined if pthreads are enabled */ + +extern uintptr_t STUB_pthread_barrier_destroy(uintptr_t parm1); +extern uintptr_t STUB_pthread_barrier_init(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_pthread_barrier_wait(uintptr_t parm1); +extern uintptr_t STUB_pthread_cancel(uintptr_t parm1); +extern uintptr_t STUB_pthread_cond_broadcast(uintptr_t parm1); +extern uintptr_t STUB_pthread_cond_destroy(uintptr_t parm1); +extern uintptr_t STUB_pthread_cond_init(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_pthread_cond_signal(uintptr_t parm1); +extern uintptr_t STUB_pthread_cond_wait(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_pthread_create(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4); +extern uintptr_t STUB_pthread_detach(uintptr_t parm1); +extern uintptr_t STUB_pthread_exit(uintptr_t parm1); +extern uintptr_t STUB_pthread_getschedparam(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_pthread_getspecific(uintptr_t parm1); +extern uintptr_t STUB_pthread_join(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_pthread_key_create(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_pthread_key_delete(uintptr_t parm1); +extern uintptr_t STUB_pthread_mutex_destroy(uintptr_t parm1); +extern uintptr_t STUB_pthread_mutex_init(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_pthread_mutex_lock(uintptr_t parm1); +extern uintptr_t STUB_pthread_mutex_trylock(uintptr_t parm1); +extern uintptr_t STUB_pthread_mutex_unlock(uintptr_t parm1); +extern uintptr_t STUB_pthread_once(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_pthread_setcancelstate(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_pthread_setschedparam(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_pthread_setschedprio(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_pthread_setspecific(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_pthread_yield(void); + +extern uintptr_t STUB_pthread_cond_timedwait(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_pthread_kill(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_pthread_sigmask(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); + +/* The following are defined only if message queues are enabled */ + +extern uintptr_t STUB_mq_close(uintptr_t parm1); +extern uintptr_t STUB_mq_notify(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_mq_open(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5, uintptr_t parm6); +extern uintptr_t STUB_mq_receive(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4); +extern uintptr_t STUB_mq_send(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4); +extern uintptr_t STUB_mq_timedreceive(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5); +extern uintptr_t STUB_mq_timedsend(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5); +extern uintptr_t STUB_mq_unlink(uintptr_t parm1); + +/* The following are defined only if environment variables are supported */ + +extern uintptr_t STUB_clearenv(void); +extern uintptr_t STUB_getenv(uintptr_t parm1); +extern uintptr_t STUB_putenv(uintptr_t parm1); +extern uintptr_t STUB_setenv(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_unsetenv(uintptr_t parm1); + +/* The following are defined only if networking AND sockets are supported */ + +extern uintptr_t STUB_accept(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_bind(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_connect(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); +extern uintptr_t STUB_getsockopt(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5); +extern uintptr_t STUB_listen(uintptr_t parm1, uintptr_t parm2); +extern uintptr_t STUB_recv(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4); +extern uintptr_t STUB_recvfrom(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5, uintptr_t parm6); +extern uintptr_t STUB_send(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4); +extern uintptr_t STUB_sendto(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5, uintptr_t parm6); +extern uintptr_t STUB_setsockopt(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5); +extern uintptr_t STUB_socket(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3); + +/* The following is defined only if CONFIG_TASK_NAME_SIZE > 0 */ + +extern uintptr_t STUB_prctl(uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Stub lookup tables. Each table is indexed by the system call numbers + * defined above. Given the system call number, the corresponding entry in + * these tables describes how to call the stub dispatch function. + */ + +const union syscall_stubfunc_u g_stublookup[SYS_nsyscalls] = +{ +# undef STUB_LOOKUP1 +# define STUB_LOOKUP1(n,p) (union syscall_stubfunc_u)p +# undef STUB_LOOKUP +# define STUB_LOOKUP(n,p) , (union syscall_stubfunc_u)p +# include "stub_lookup.h" +}; + +const uint8_t g_stubnparms[SYS_nsyscalls] = +{ +# undef STUB_LOOKUP1 +# define STUB_LOOKUP1(n,p) n +# undef STUB_LOOKUP +# define STUB_LOOKUP(n,p) , n +# include "stub_lookup.h" +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* CONFIG_CONFIG_SYS_RESERVED */ diff --git a/nuttx/syscall/stub_lookup.h b/nuttx/syscall/stub_lookup.h new file mode 100644 index 0000000000..9b4a928144 --- /dev/null +++ b/nuttx/syscall/stub_lookup.h @@ -0,0 +1,268 @@ +/**************************************************************************** + * syscall/stub_lookup.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* STUB_LOOKUP must be defined before including this file. + * + * These first system calls are supported regardless of the NuttX + * configuration + */ + +STUB_LOOKUP1(1, STUB__exit) /* SYS__exit */ +STUB_LOOKUP(1, STUB_exit) /* SYS_exit */ +STUB_LOOKUP(0, STUB_get_errno) /* SYS_get_errno */ +STUB_LOOKUP(0, STUB_getpid) /* SYS_getpid */ +STUB_LOOKUP(2, STUB_sched_getparam) /* SYS_sched_getparam */ +STUB_LOOKUP(1, STUB_sched_getscheduler) /* SYS_sched_getscheduler */ +STUB_LOOKUP(0, STUB_sched_lock) /* SYS_sched_lock */ +STUB_LOOKUP(0, STUB_sched_lockcount) /* SYS_sched_lockcount */ +STUB_LOOKUP(2, STUB_sched_rr_get_interval) /* SYS_sched_rr_get_interval */ +STUB_LOOKUP(2, STUB_sched_setparam) /* SYS_sched_setparam */ +STUB_LOOKUP(3, STUB_sched_setscheduler) /* SYS_sched_setscheduler */ +STUB_LOOKUP(0, STUB_sched_unlock) /* SYS_sched_unlock */ +STUB_LOOKUP(0, STUB_sched_yield) /* SYS_sched_yield */ +STUB_LOOKUP(1, STUB_sem_close) /* SYS_sem_close */ +STUB_LOOKUP(2, STUB_sem_destroy) /* SYS_sem_destroy */ +STUB_LOOKUP(6, STUB_sem_open) /* SYS_sem_open */ +STUB_LOOKUP(1, STUB_sem_post) /* SYS_sem_post */ +STUB_LOOKUP(1, STUB_sem_trywait) /* SYS_sem_trywait */ +STUB_LOOKUP(1, STUB_sem_unlink) /* SYS_sem_unlink */ +STUB_LOOKUP(1, STUB_sem_wait) /* SYS_sem_wait */ +STUB_LOOKUP(1, STUB_set_errno) /* SYS_set_errno */ +STUB_LOOKUP(5, STUB_task_create) /* SYS_task_create */ +STUB_LOOKUP(1, STUB_task_delete) /* SYS_task_delete */ +STUB_LOOKUP(1, STUB_task_restart) /* SYS_task_restart */ +STUB_LOOKUP(2, STUB_up_assert) /* SYS_up_assert */ +STUB_LOOKUP(3, STUB_up_assert_code) /* SYS_up_assert_code */ + +/* The following can be individually enabled */ + +#ifdef CONFIG_SCHED_ATEXIT + STUB_LOOKUP(1, STUB_atexit) /* SYS_atexit */ +#endif + +#ifdef CONFIG_SCHED_ONEXIT + STUB_LOOKUP(2, STUB_onexit) /* SYS_onexit */ +#endif + +#ifdef CONFIG_SCHED_WAITPID + STUB_LOOKUP(3, STUB_waitpid) /* SYS_waitpid */ +#endif + +/* The following are only defined is signals are supported in the NuttX + * configuration. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + STUB_LOOKUP(2, STUB_kill) /* SYS_kill */ + STUB_LOOKUP(3, STUB_sigaction) /* SYS_sigaction */ + STUB_LOOKUP(1, STUB_sigpending) /* SYS_sigpending */ + STUB_LOOKUP(3, STUB_sigprocmask) /* SYS_sigprocmask */ + STUB_LOOKUP(3, STUB_sigqueue) /* SYS_sigqueue */ + STUB_LOOKUP(1, STUB_sigsuspend) /* SYS_sigsuspend */ + STUB_LOOKUP(3, STUB_sigtimedwait) /* SYS_sigtimedwait */ + STUB_LOOKUP(2, STUB_sigwaitinfo) /* SYS_sigwaitinfo */ + STUB_LOOKUP(1, STUB_sleep) /* SYS_sleep */ + STUB_LOOKUP(1, STUB_usleep) /* SYS_usleep */ +#endif + +/* The following are only defined if the system clock is enabled in the + * NuttX configuration. + */ + +#ifndef CONFIG_DISABLE_CLOCK + STUB_LOOKUP(0, STUB_clock_systimer) /* SYS_clock_systimer */ + STUB_LOOKUP(2, STUB_clock_getres) /* SYS_clock_getres */ + STUB_LOOKUP(2, STUB_clock_gettime) /* SYS_clock_gettime */ + STUB_LOOKUP(2, STUB_clock_settime) /* SYS_clock_settime */ + STUB_LOOKUP(2, STUB_gettimeofday) /* SYS_gettimeofday */ +#endif + +/* The following are defined only if POSIX timers are supported */ + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + STUB_LOOKUP(3, STUB_timer_create) /* SYS_timer_create */ + STUB_LOOKUP(1, STUB_timer_delete) /* SYS_timer_delete */ + STUB_LOOKUP(1, STUB_timer_getoverrun) /* SYS_timer_getoverrun */ + STUB_LOOKUP(2, STUB_timer_gettime) /* SYS_timer_gettime */ + STUB_LOOKUP(4, STUB_timer_settime) /* SYS_timer_settime */ +#endif + +/* The following are defined if either file or socket descriptor are + * enabled. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + STUB_LOOKUP(1, STUB_close) /* SYS_close */ + STUB_LOOKUP(3, STUB_ioctl) /* SYS_ioctl */ + STUB_LOOKUP(3, STUB_read) /* SYS_read */ + STUB_LOOKUP(3, STUB_write) /* SYS_write */ +# ifndef CONFIG_DISABLE_POLL + STUB_LOOKUP(3, STUB_poll) /* SYS_poll */ + STUB_LOOKUP(5, STUB_select) /* SYS_select */ +# endif +#endif + +/* The following are defined if file descriptors are enabled */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + STUB_LOOKUP(1, STUB_closedir) /* SYS_closedir */ + STUB_LOOKUP(1, STUB_dup) /* SYS_dup */ + STUB_LOOKUP(2, STUB_dup2) /* SYS_dup2 */ + STUB_LOOKUP(6, STUB_fcntl) /* SYS_fcntl */ + STUB_LOOKUP(3, STUB_lseek) /* SYS_lseek */ + STUB_LOOKUP(2, STUB_mkfifo) /* SYS_mkfifo */ + STUB_LOOKUP(6, STUB_mmap) /* SYS_mmap */ + STUB_LOOKUP(6, STUB_open) /* SYS_open */ + STUB_LOOKUP(1, STUB_opendir) /* SYS_opendir */ + STUB_LOOKUP(1, STUB_pipe) /* SYS_pipe */ + STUB_LOOKUP(1, STUB_readdir) /* SYS_readdir */ + STUB_LOOKUP(1, STUB_rewinddir) /* SYS_rewinddir */ + STUB_LOOKUP(2, STUB_seekdir) /* SYS_seekdir */ + STUB_LOOKUP(2, STUB_stat) /* SYS_stat */ + STUB_LOOKUP(2, STUB_statfs) /* SYS_statfs */ + STUB_LOOKUP(1, STUB_telldir) /* SYS_telldir */ + +# if CONFIG_NFILE_STREAMS > 0 + STUB_LOOKUP(3, STUB_fs_fdopen) /* SYS_fs_fdopen */ + STUB_LOOKUP(0, STUB_sched_getstreams) /* SYS_sched_getstreams */ +#endif + +# if !defined(CONFIG_DISABLE_MOUNTPOINT) + STUB_LOOKUP(1, STUB_fsync) /* SYS_fsync */ + STUB_LOOKUP(2, STUB_mkdir) /* SYS_mkdir */ + STUB_LOOKUP(5, STUB_mount) /* SYS_mount */ + STUB_LOOKUP(2, STUB_rename) /* SYS_rename */ + STUB_LOOKUP(1, STUB_rmdir) /* SYS_rmdir */ + STUB_LOOKUP(1, STUB_umount) /* SYS_umount */ + STUB_LOOKUP(1, STUB_unlink) /* SYS_unlink */ +# endif +#endif + +/* The following are defined if pthreads are enabled */ + +#ifndef CONFIG_DISABLE_PTHREAD + STUB_LOOKUP(1, STUB_pthread_barrier_destroy) /* SYS_pthread_barrier_destroy */ + STUB_LOOKUP(3, STUB_pthread_barrier_init) /* SYS_pthread_barrier_init */ + STUB_LOOKUP(1, STUB_pthread_barrier_wait) /* SYS_pthread_barrier_wait */ + STUB_LOOKUP(1, STUB_pthread_cancel) /* SYS_pthread_cancel */ + STUB_LOOKUP(1, STUB_pthread_cond_broadcast) /* SYS_pthread_cond_broadcast */ + STUB_LOOKUP(1, STUB_pthread_cond_destroy) /* SYS_pthread_cond_destroy */ + STUB_LOOKUP(2, STUB_pthread_cond_init) /* SYS_pthread_cond_init */ + STUB_LOOKUP(1, STUB_pthread_cond_signal) /* SYS_pthread_cond_signal */ + STUB_LOOKUP(2, STUB_pthread_cond_wait) /* SYS_pthread_cond_wait */ + STUB_LOOKUP(4, STUB_pthread_create) /* SYS_pthread_create */ + STUB_LOOKUP(1, STUB_pthread_detach) /* SYS_pthread_detach */ + STUB_LOOKUP(1, STUB_pthread_exit) /* SYS_pthread_exit */ + STUB_LOOKUP(3, STUB_pthread_getschedparam) /* SYS_pthread_getschedparam */ + STUB_LOOKUP(1, STUB_pthread_getspecific) /* SYS_pthread_getspecific */ + STUB_LOOKUP(2, STUB_pthread_join) /* SYS_pthread_join */ + STUB_LOOKUP(2, STUB_pthread_key_create) /* SYS_pthread_key_create */ + STUB_LOOKUP(1, STUB_pthread_key_delete) /* SYS_pthread_key_delete */ + STUB_LOOKUP(1, STUB_pthread_mutex_destroy) /* SYS_pthread_mutex_destroy */ + STUB_LOOKUP(2, STUB_pthread_mutex_init) /* SYS_pthread_mutex_init */ + STUB_LOOKUP(1, STUB_pthread_mutex_lock) /* SYS_pthread_mutex_lock */ + STUB_LOOKUP(1, STUB_pthread_mutex_trylock) /* SYS_pthread_mutex_trylock */ + STUB_LOOKUP(1, STUB_pthread_mutex_unlock) /* SYS_pthread_mutex_unlock */ + STUB_LOOKUP(2, STUB_pthread_once) /* SYS_pthread_once */ + STUB_LOOKUP(2, STUB_pthread_setcancelstate) /* SYS_pthread_setcancelstate */ + STUB_LOOKUP(3, STUB_pthread_setschedparam) /* SYS_pthread_setschedparam */ + STUB_LOOKUP(2, STUB_pthread_setschedprio) /* SYS_pthread_setschedprio */ + STUB_LOOKUP(2, STUB_pthread_setspecific) /* SYS_pthread_setspecific */ + STUB_LOOKUP(0, STUB_pthread_yield) /* SYS_pthread_yield */ +# ifndef CONFIG_DISABLE_SIGNAL + STUB_LOOKUP(3, STUB_pthread_cond_timedwait) /* SYS_pthread_cond_timedwait */ + STUB_LOOKUP(2, STUB_pthread_kill) /* SYS_pthread_kill */ + STUB_LOOKUP(3, STUB_pthread_sigmask) /* SYS_pthread_sigmask */ +# endif +#endif + +/* The following are defined only if message queues are enabled */ + +#ifndef CONFIG_DISABLE_MQUEUE + STUB_LOOKUP(1, STUB_mq_close) /* SYS_mq_close */ + STUB_LOOKUP(2, STUB_mq_notify) /* SYS_mq_notify */ + STUB_LOOKUP(6, STUB_mq_open) /* SYS_mq_open */ + STUB_LOOKUP(4, STUB_mq_receive) /* SYS_mq_receive */ + STUB_LOOKUP(4, STUB_mq_send) /* SYS_mq_send */ + STUB_LOOKUP(5, STUB_mq_timedreceive) /* SYS_mq_timedreceive */ + STUB_LOOKUP(5, STUB_mq_timedsend) /* SYS_mq_timedsend */ + STUB_LOOKUP(1, STUB_mq_unlink) /* SYS_mq_unlink */ +#endif + +/* The following are defined only if environment variables are supported */ + +#ifndef CONFIG_DISABLE_ENVIRON + STUB_LOOKUP(0, STUB_clearenv) /* SYS_clearenv */ + STUB_LOOKUP(1, STUB_getenv) /* SYS_getenv */ + STUB_LOOKUP(1, STUB_putenv) /* SYS_putenv */ + STUB_LOOKUP(3, STUB_setenv) /* SYS_setenv */ + STUB_LOOKUP(1, STUB_unsetenv) /* SYS_unsetenv */ +#endif + +/* The following are defined only if networking AND sockets are supported */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET) + STUB_LOOKUP(3, STUB_accept) /* SYS_accept */ + STUB_LOOKUP(3, STUB_bind) /* SYS_bind */ + STUB_LOOKUP(3, STUB_connect) /* SYS_connect */ + STUB_LOOKUP(5, STUB_getsockopt) /* SYS_getsockopt */ + STUB_LOOKUP(2, STUB_listen) /* SYS_listen */ + STUB_LOOKUP(4, STUB_recv) /* SYS_recv */ + STUB_LOOKUP(6, STUB_recvfrom) /* SYS_recvfrom */ + STUB_LOOKUP(4, STUB_send) /* SYS_send */ + STUB_LOOKUP(6, STUB_sendto) /* SYS_sendto */ + STUB_LOOKUP(5, STUB_setsockopt) /* SYS_setsockopt */ + STUB_LOOKUP(3, STUB_socket) /* SYS_socket */ +#endif + +/* The following is defined only if CONFIG_TASK_NAME_SIZE > 0 */ + +#if CONFIG_TASK_NAME_SIZE > 0 + STUB_LOOKUP(5, STUB_prctl) /* SYS_prctl */ +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + diff --git a/nuttx/syscall/stubs/Make.defs b/nuttx/syscall/stubs/Make.defs new file mode 100644 index 0000000000..10d10c08a2 --- /dev/null +++ b/nuttx/syscall/stubs/Make.defs @@ -0,0 +1,38 @@ +############################################################################ +# syscall/stubs/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +STUB_SRCS := ${shell cd stubs; ls *.c 2>/dev/null } + + diff --git a/nuttx/syscall/syscall.csv b/nuttx/syscall/syscall.csv new file mode 100644 index 0000000000..22b45df9da --- /dev/null +++ b/nuttx/syscall/syscall.csv @@ -0,0 +1,142 @@ +"_exit","unistd.h","","void","int" +"accept","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","int","int","struct sockaddr*","socklen_t*" +"atexit","stdlib.h","defined(CONFIG_SCHED_ATEXIT)","int","void (*)(void)" +"bind","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","int","int","FAR const struct sockaddr*","socklen_t" +"clearenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int" +"clock_getres","time.h","!defined(CONFIG_DISABLE_CLOCK)","int","clockid_t","struct timespec*" +"clock_gettime","time.h","!defined(CONFIG_DISABLE_CLOCK)","int","clockid_t","struct timespec*" +"clock_settime","time.h","!defined(CONFIG_DISABLE_CLOCK)","int","clockid_t","const struct timespec*" +"close","unistd.h","CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0","int","int" +"closedir","dirent.h","CONFIG_NFILE_DESCRIPTORS > 0","int","FAR DIR*" +"connect","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","int","int","FAR const struct sockaddr*","socklen_t" +"dup","unistd.h","CONFIG_NFILE_DESCRIPTORS > 0","int","int" +"dup2","unistd.h","CONFIG_NFILE_DESCRIPTORS > 0","int","int","int" +"exit","stdlib.h","","void","int" +"fcntl","fcntl.h","CONFIG_NFILE_DESCRIPTORS > 0","int","int","int","..." +"fs_fdopen","nuttx/fs/fs.h","CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0","FAR struct file_struct*","int","int","FAR _TCB*" +"fsync","unistd.h","CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)","int","int" +"get_errno","errno.h","","int" +"getenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","FAR char*","FAR const char*" +"getpid","unistd.h","","pid_t" +"getsockopt","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","int","int","int","int","FAR void*","FAR socklen_t*" +"gettimeofday","sys/time.h","!defined(CONFIG_DISABLE_CLOCK)","int","struct timeval*","FAR void*" +"ioctl","sys/ioctl.h","CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0","int","int","int","unsigned long" +"kill","signal.h","!defined(CONFIG_DISABLE_SIGNALS)","int","pid_t","int" +"listen","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","int","int","int" +"lseek","unistd.h","CONFIG_NFILE_DESCRIPTORS > 0","off_t","int","off_t","int" +"mkdir","sys/stat.h","CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char*","mode_t" +"mkfifo","sys/stat.h","CONFIG_NFILE_DESCRIPTORS > 0","int","FAR const char*","mode_t" +"mmap","sys/mman.h","CONFIG_NFILE_DESCRIPTORS > 0","FAR void*","FAR void*","size_t","int","int","int","off_t" +"mount","sys/mount.h","CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)","int","const char*","const char*","const char*","unsigned long","const void*" +"mq_close","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","mqd_t" +"mq_notify","mqueue.h","!defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_MQUEUE)","int","mqd_t","const struct sigevent*" +"mq_open","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","mqd_t","const char*","int","..." +"mq_receive","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","ssize_t","mqd_t","void*","size_t","int*" +"mq_send","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","mqd_t","const void*","size_t","int" +"mq_timedreceive","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","ssize_t","mqd_t","void*","size_t","int*","const struct timespec*" +"mq_timedsend","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","mqd_t","const char*","size_t","int","const struct timespec*" +"mq_unlink","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","const char*" +"on_exit","stdlib.h","defined(CONFIG_SCHED_ONEXIT)","int","CODE void (*func)(int, FAR void *)","FAR void *" +"open","fcntl.h","CONFIG_NFILE_DESCRIPTORS > 0","int","const char*","int","..." +"opendir","dirent.h","CONFIG_NFILE_DESCRIPTORS > 0","FAR DIR*","FAR const char*" +"pipe","unistd.h","CONFIG_NFILE_DESCRIPTORS > 0","int","int [2]|int*" +"prctl", sys/prctl.h, "CONFIG_TASK_NAME_SIZE > 0","int","int","..." +"clock_systimer","nuttx/clock.h","!defined(CONFIG_DISABLE_CLOCK)","uint32_t" +"poll","poll.h","!defined(CONFIG_DISABLE_POLL) && (CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0)","int","FAR struct pollfd*","nfds_t","int" +"pthread_barrier_destroy","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_barrier_t*" +"pthread_barrier_init","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_barrier_t*","FAR const pthread_barrierattr_t*","unsigned int" +"pthread_barrier_wait","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_barrier_t*" +"pthread_cancel","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t" +"pthread_cond_broadcast","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t*" +"pthread_cond_destroy","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t*" +"pthread_cond_init","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t*","FAR pthread_condattr_t*" +"pthread_cond_signal","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t*" +"pthread_cond_timedwait","pthread.h","!defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t*","FAR pthread_mutex_t*","FAR const struct timespec*" +"pthread_cond_wait","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t*","FAR pthread_mutex_t*" +"pthread_create","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_t*","FAR pthread_attr_t*","pthread_startroutine_t","pthread_addr_t" +"pthread_detach","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t" +"pthread_exit","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","void","pthread_addr_t" +"pthread_getschedparam","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t","FAR int*","FAR struct sched_param*" +"pthread_getspecific","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","FAR void*","pthread_key_t" +"pthread_join","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t","FAR pthread_addr_t*" +"pthread_key_create","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_key_t*","CODE void (*)(FAR void*)" +"pthread_key_delete","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_key_t" +"pthread_kill","pthread.h","!defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t","int" +"pthread_mutex_destroy","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_mutex_t*" +"pthread_mutex_init","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_mutex_t*","FAR pthread_mutexattr_t*" +"pthread_mutex_lock","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_mutex_t*" +"pthread_mutex_trylock","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_mutex_t*" +"pthread_mutex_unlock","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_mutex_t*" +"pthread_once","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_once_t*","CODE void (*)(void)" +"pthread_setcancelstate","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","int","FAR int*" +"pthread_setschedparam","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t","int","FAR const struct sched_param*" +"pthread_setschedprio","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t","int" +"pthread_setspecific","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_key_t","FAR void*" +"pthread_sigmask","pthread.h","!defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD)","int","int","FAR const sigset_t*","FAR sigset_t*" +"pthread_yield","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","void" +"putenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int","FAR const char*" +"read","unistd.h","CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0","ssize_t","int","FAR void*","size_t" +"readdir","dirent.h","CONFIG_NFILE_DESCRIPTORS > 0","FAR struct dirent*","FAR DIR*" +"recv","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","ssize_t","int","FAR void*","size_t","int" +"recvfrom","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","ssize_t","int","FAR void*","size_t","int","FAR struct sockaddr*","FAR socklen_t*" +"rename","stdio.h","CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char*","FAR const char*" +"rewinddir","dirent.h","CONFIG_NFILE_DESCRIPTORS > 0","void","FAR DIR*" +"rmdir","unistd.h","CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char*" +"sched_getparam","sched.h","","int","pid_t","struct sched_param*" +"sched_getscheduler","sched.h","","int","pid_t" +"sched_getstreams","nuttx/sched.h","CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0","FAR struct streamlist*" +"sched_lock","sched.h","","int" +"sched_lockcount","sched.h","","int32_t" +"sched_rr_get_interval","sched.h","","int","pid_t","struct timespec*" +"sched_setparam","sched.h","","int","pid_t","const struct sched_param*" +"sched_setscheduler","sched.h","","int","pid_t","int","const struct sched_param*" +"sched_unlock","sched.h","","int" +"sched_yield","sched.h","","int" +"seekdir","dirent.h","CONFIG_NFILE_DESCRIPTORS > 0","void","FAR DIR*","off_t" +"select","sys/select.h","!defined(CONFIG_DISABLE_POLL) && (CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0)","int","int","FAR fd_set*","FAR fd_set*","FAR fd_set*","FAR struct timeval*" +"sem_close","semaphore.h","","int","FAR sem_t*" +"sem_destroy","semaphore.h","","int","FAR sem_t*" +"sem_open","semaphore.h","","FAR sem_t*","FAR const char*","int","..." +"sem_post","semaphore.h","","int","FAR sem_t*" +"sem_trywait","semaphore.h","","int","FAR sem_t*" +"sem_unlink","semaphore.h","","int","FAR const char*" +"sem_wait","semaphore.h","","int","FAR sem_t*" +"send","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","ssize_t","int","FAR const void*","size_t","int" +"sendto","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","ssize_t","int","FAR const void*","size_t","int","FAR const struct sockaddr*","socklen_t" +"set_errno","errno.h","","void","int" +"setenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int","const char*","const char*","int" +"setsockopt","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","int","int","int","int","FAR const void*","socklen_t" +"sigaction","signal.h","!defined(CONFIG_DISABLE_SIGNALS)","int","int","FAR const struct sigaction*","FAR struct sigaction*" +"sigpending","signal.h","!defined(CONFIG_DISABLE_SIGNALS)","int","FAR sigset_t*" +"sigprocmask","signal.h","!defined(CONFIG_DISABLE_SIGNALS)","int","int","FAR const sigset_t*","FAR sigset_t*" +"sigqueue","signal.h","!defined(CONFIG_DISABLE_SIGNALS)","int","int","int","union sigval|FAR void *|sival_ptr" +"sigsuspend","signal.h","!defined(CONFIG_DISABLE_SIGNALS)","int","FAR const sigset_t*" +"sigtimedwait","signal.h","!defined(CONFIG_DISABLE_SIGNALS)","int","FAR const sigset_t*","FAR struct siginfo*","FAR const struct timespec*" +"sigwaitinfo","signal.h","!defined(CONFIG_DISABLE_SIGNALS)","int","FAR const sigset_t*","FAR struct siginfo*" +"sleep","unistd.h","!defined(CONFIG_DISABLE_SIGNALS)","unsigned int","unsigned int" +"socket","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","int","int","int","int" +"stat","sys/stat.h","CONFIG_NFILE_DESCRIPTORS > 0","int","const char*","FAR struct stat*" +#"statfs","stdio.h","","int","FAR const char*","FAR struct statfs*" +"statfs","sys/statfs.h","CONFIG_NFILE_DESCRIPTORS > 0","int","const char*","struct statfs*" +"task_create","sched.h","","int","const char*","int","int","main_t","const char* []|const char**" +#"task_create","sched.h","","int","const char*","int","main_t","const char* []|const char**" +"task_delete","sched.h","","int","pid_t" +"task_restart","sched.h","","int","pid_t" +"telldir","dirent.h","CONFIG_NFILE_DESCRIPTORS > 0","off_t","FAR DIR*" +"timer_create","time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","clockid_t","FAR struct sigevent*","FAR timer_t*" +"timer_delete","time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","timer_t" +"timer_getoverrun","time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","timer_t" +"timer_gettime","time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","timer_t","FAR struct itimerspec*" +"timer_settime","time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","timer_t","int","FAR const struct itimerspec*","FAR struct itimerspec*" +"umount","sys/mount.h","CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)","int","const char*" +"unlink","unistd.h","CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char*" +"unsetenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int","const char*" +"up_assert","assert.h","","void","FAR const uint8_t*","int" +#"up_assert","assert.h","","void" +"up_assert_code","assert.h","","void","FAR const uint8_t*","int","int" +#"up_assert_code","assert.h","","void","int" +"usleep","unistd.h","!defined(CONFIG_DISABLE_SIGNALS)","void","useconds_t" +#"wait","sys/wait.h","","pid_t","int*" +#"waitid","sys/wait.h","","int","idtype_t","id_t id","siginfo_t*","int" +"waitpid","sys/wait.h","defined(CONFIG_SCHED_WAITPID)","pid_t","pid_t","int*","int" +"write","unistd.h","CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0","ssize_t","int","FAR const void*","size_t" diff --git a/nuttx/tools/Makefile.export b/nuttx/tools/Makefile.export new file mode 100644 index 0000000000..fa2909972a --- /dev/null +++ b/nuttx/tools/Makefile.export @@ -0,0 +1,67 @@ +############################################################################ +# Makefile.export +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +include $(TOPDIR)/.config +include $(EXPORTDIR)/Make.defs + +ifdef ARCHSCRIPT +LDPATH = ${shell echo "$(ARCHSCRIPT)" | sed -e "s/^-T[ ]*//g"} +LDNAME = ${shell basename ${LDPATH}} +LDDIR = ${shell dirname ${LDPATH}} +endif +ARCHSUBDIR = "arch/$(CONFIG_ARCH)/src" +ARCHDIR ="$(TOPDIR)/$(ARCHSUBDIR)" + +all: $(EXPORTDIR)/makeinfo.sh +default: all +.PHONY: clean + +$(EXPORTDIR)/makeinfo.sh: $(TOPDIR)/.config $(EXPORTDIR)/Make.defs + @echo "#!/bin/bash" > $(EXPORTDIR)/makeinfo.sh + @echo "" >> $(EXPORTDIR)/makeinfo.sh + @echo "ARCHSUBDIR=\"$(ARCHSUBDIR)\"" >> $(EXPORTDIR)/makeinfo.sh + @echo "ARCHDIR=\"$(ARCHDIR)\"" >> $(EXPORTDIR)/makeinfo.sh +ifdef ARCHSCRIPT + @echo "LDNAME=\"$(LDNAME)\"" >> $(EXPORTDIR)/makeinfo.sh + @echo "LDDIR=\"$(LDDIR)\"" >> $(EXPORTDIR)/makeinfo.sh + @echo "LDPATH=\"$(LDPATH)\"" >> $(EXPORTDIR)/makeinfo.sh +endif + @echo "ARCHCFLAGS=\"$(ARCHCFLAGS) $(ARCHCPUFLAGS)\"" >> $(EXPORTDIR)/makeinfo.sh + @echo "ARCHCXXFLAGS=\"$(ARCHCXXFLAGS) $(ARCHCPUFLAGS)\"" >> $(EXPORTDIR)/makeinfo.sh + @echo "CROSSDEV=\"$(CROSSDEV)\"" >> $(EXPORTDIR)/makeinfo.sh + @chmod 755 $(EXPORTDIR)/makeinfo.sh + +clean: + @rm -f $(EXPORTDIR)/makeinfo.sh diff --git a/nuttx/tools/Makefile.host b/nuttx/tools/Makefile.host new file mode 100644 index 0000000000..cf421aa3bf --- /dev/null +++ b/nuttx/tools/Makefile.host @@ -0,0 +1,72 @@ +############################################################################ +# Makefile.host +# +# Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +all: mkconfig mkversion mksyscall bdf-converter +default: mkconfig mksyscall +.PHONY: clean + +# Add CFLAGS=-g on the make command line build debug versions + +CFLAGS = -O2 -Wall -I. + +# mkconfig - Convert a .config file into a C config.h file + +mkconfig: mkconfig.c cfgparser.c + @gcc $(CFLAGS) -o mkconfig mkconfig.c cfgparser.c + +# cmpconfig - Compare the contents of two configuration files + +cmpconfig: cmpconfig.c + @gcc $(CFLAGS) -o cmpconfig cmpconfig.c + +# mkversion - Convert a .version file into a C version.h file + +mkversion: mkconfig.c cfgparser.c + @gcc $(CFLAGS) -o mkversion mkversion.c cfgparser.c + +# mksyscall - Convert a CSV file into syscall stubs and proxies + +mksyscall: mksyscall.c + @gcc $(CFLAGS) -o mksyscall mksyscall.c + +# bdf-converter - Converts a BDF font to the NuttX font format + +bdf-converter: bdf-converter.c + @gcc $(CFLAGS) -o bdf-converter bdf-converter.c + +clean: + @rm -f *.o *.a *~ .*.swp + @rm -f mkconfig mksyscall mkversion bdf-converter + @rm -f mkconfig.exe mksyscall.exe mkversion.exe bdf-converter.exe diff --git a/nuttx/tools/README.txt b/nuttx/tools/README.txt new file mode 100755 index 0000000000..39128fa1b0 --- /dev/null +++ b/nuttx/tools/README.txt @@ -0,0 +1,316 @@ +tools/README.txt +^^^^^^^^^^^^^^^^ + +This README file addresses the contents of the NuttX tools/ directory. + +The tools/ directory contains miscellaneous scripts and host C programs +that are necessary parts of the the NuttX build system. These files +include: + +README.txt + + This file + +configure.sh + + This is a bash script that is used to configure NuttX for a given + target board. See configs/README.txt or Documentation/NuttxPortingGuide.html + for a description of how to configure NuttX with this script. + +mkconfig.c, cfgparser.c, and cfgparser.h + + These are Cs file that are used to build mkconfig program. The mkconfig + program is used during the initial NuttX build. + + When you configure NuttX, you will copy a configuration file called .config + in the top level NuttX directory (See configs/README.txt or + Documentation/NuttxPortingGuide.html). The first time you make NuttX, + the top-level makefile will build the mkconfig executable from mkconfig.c + (using Makefile.host). The top-level Makefile will then execute the + mkconfig program to convert the .config file in the top level directory + into include/nuttx/config.h. config.h is a another version of the + NuttX configuration that can be included by C files. + +cmdconfig.c + + This C file can be used to build a utility for comparing two NuttX + configuration files. + +mkexport.sh and Makefile.export + + These implement part of the top-level Makefile's 'export' target. That + target will bundle up all of the NuttX libraries, header files, and the + startup object into an export-able, binary NuttX distribution. The + Makefile.export is used only by the mkexport.sh script to parse out + options from the top-level Make.defs file. + +mkversion.c, cfgparser.c, and cfgparser.h + + This is C file that is used to build mkversion program. The mkversion + program is used during the initial NuttX build. + + When you build NuttX there should be a version file called .version in + the top level NuttX directory (See Documentation/NuttxPortingGuide.html). + The first time you make NuttX, the top-level makefile will build th + mkversion executable from mkversion.c (using Makefile.host). The top- + level Makefile will then execute the mkversion program to convert the + .version file in the top level directory into include/nuttx/version.h. + version.h provides version information that can be included by C files. + +mksyscall.c + + This is a C file that is used to build mksyscall program. The mksyscall + program is used during the initial NuttX build by the logic in the top- + level syscall/ directory. + + If you build NuttX as a separately compiled, monolithic kernel and separate + applications, then there is a syscall layer that is used to get from the + user application space to the NuttX kernel space. In the user application + "proxies" for each of the kernel functions are provided. The proxies have + the same function signature as the kernel function, but only execute a + system call. + + Within the kernel, there are "stubs" for each of the system calls. The + stubs receive the marshalled system call data, and perform the actually + kernel function call (in kernel-mode) on behalf of the proxy function. + + Information about the stubs and proxies is maintained in a comma separated + value (CSV) file in the syscall/ directory. The mksyscall program will + accept this CVS file as input and generate all of the required proxy or + stub files as output. See syscall/README.txt for additonal information. + +pic32mx + + This directory contains build tools used only for PIC32MX platforms + +bdf-convert.c + + This C file is used to build the bdf-converter program. The bdf-converter + program be used to convert fonts in Bitmap Distribution Format (BDF) + into fonts that can be used in the NX graphics system. + + Below are general instructions for creating and installing a new font + in the NX graphic system: + + 1. Locate a font in BDF format, + 2. Use the bdf-converter program to convert the BDF font to the NuttX + font format. This will result in a C header file containing + defintions. That header file should be installed at, for example, + graphics/nxfonts/nxfonts_myfont.h. + + Create a new NuttX configuration variable. For example, suppose + you define the following variable: CONFIG_NXFONT_MYFONT. Then + you would need to: + + 3. Define CONFIG_NXFONT_MYFONT=y in your NuttX configuration file. + + A font ID number has to be assigned for each new font. The font ID + is defined in the file include/nuttx/nx/nxfonts.h. Those definitions + have to be extended to support your new font. Look at how the font ID + enabled by CONFIG_NXFONT_SANS23X27 is defined and add an ID for your + new font in a similar fashion: + + 4. include/nuttx/nx/nxfonts.h. Add you new font as a possible system + default font: + + #if defined(CONFIG_NXFONT_SANS23X27) + # define NXFONT_DEFAULT FONTID_SANS23X27 + #elif defined(CONFIG_NXFONT_MYFONT) + # define NXFONT_DEFAULT FONTID_MYFONT + #endif + + Then define the actual font ID. Make sure that the font ID value + is unique: + + enum nx_fontid_e + { + FONTID_DEFAULT = 0 /* The default font */ + #ifdef CONFIG_NXFONT_SANS23X27 + , FONTID_SANS23X27 = 1 /* The 23x27 sans serif font */ + #endif + #ifdef CONFIG_NXFONT_MYFONT + , FONTID_MYFONT = 2 /* My shiny, new font */ + #endif + ... + + New Add the font to the NX build system. There are several files that + you have to modify to to this. Look how the build system uses the + font CONFIG_NXFONT_SANS23X27 for examaples: + + 5. nuttx/graphics/Makefile. This file needs logic to auto-generate + a C source file from the header file that you generated with the + the bdf-converter program. Notice NXFONTS_FONTID=2; this must be + set to the same font ID value that you defined in the + include/nuttx/nx/nxfonts.h file. + + genfontsources: + ifeq ($(CONFIG_NXFONT_SANS23X27),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=1 EXTRADEFINES=$(EXTRADEFINES) + endif + ifeq ($(CONFIG_NXFONT_MYFONT),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=2 EXTRADEFINES=$(EXTRADEFINES) + endif + + 6. nuttx/graphics/nxfonts/Make.defs. Set the make variable NXFSET_CSRCS. + NXFSET_CSRCS determines the name of the font C file to build when + NXFONTS_FONTID=2: + + ifeq ($(CONFIG_NXFONT_SANS23X27),y) + NXFSET_CSRCS += nxfonts_bitmaps_sans23x27.c + endif + ifeq ($(CONFIG_NXFONT_MYFONT),y) + NXFSET_CSRCS += nxfonts_bitmaps_myfont.c + endif + + 7. nuttx/graphics/nxfonts/Makefile.sources. This is the Makefile used + in step 5 that will actually generate the font C file. So, given + your NXFONTS_FONTID=2, it needs to determine a prefix to use for + auto-generated variable and function names and (again) the name of + the autogenerated file to create (this must be the same name that + was used in nuttx/graphics/nxfonts/Make.defs): + + ifeq ($(NXFONTS_FONTID),1) + NXFONTS_PREFIX := g_sans23x27_ + GEN_CSRC = nxfonts_bitmaps_sans23x27.c + endif + ifeq ($(NXFONTS_FONTID),2) + NXFONTS_PREFIX := g_myfont_ + GEN_CSRC = nxfonts_bitmaps_myfont.c + endif + + 8. graphics/nxfonts/nxfonts_bitmaps.c. This is the file that contains + the generic font structures. It is used as a "template" file by + nuttx/graphics/nxfonts/Makefile.sources to create your customized + font data set. + + #if NXFONTS_FONTID == 1 + # include "nxfonts_sans23x27.h" + #elif NXFONTS_FONTID == 2 + # include "nxfonts_myfont.h" + #else + # error "No font ID specified" + #endif + + Where nxfonts_myfont.h is the NuttX font file that we generated in + step 2 using the bdf-converter tool. + + 9. graphics/nxfonts/nxfonts_getfont.c. Finally, we need to extend the + logic that does the run-time font lookups so that can find our new + font. The lookup function is NXHANDLE nxf_getfonthandle(enum nx_fontid_e fontid). + The new font information needs to be added to data structures used by + that function: + + #ifdef CONFIG_NXFONT_SANS23X27 + extern const struct nx_fontpackage_s g_sans23x27_package; + #endif + #ifdef CONFIG_NXFONT_MYFONT + extern const struct nx_fontpackage_s g_myfont_package; + #endif + + static FAR const struct nx_fontpackage_s *g_fontpackages[] = + { + #ifdef CONFIG_NXFONT_SANS23X27 + &g_sans23x27_package, + #endif + #ifdef CONFIG_NXFONT_MYFONT + &g_myfont_package, + #endif + NULL + }; + +Makefile.host + + This is the makefile that is used to make the mkconfig program from + the mkconfig.c C file, the cmpconfig program from cmpconfig.c C file + the mkversion program from the mkconfig.c C file, or the mksyscall + program from the mksyscall.c file. Usage: + + cd tools/ + make -f Makefile.host + +mkromfsimg.sh + + This script may be used to automate the generate of a ROMFS file system + image. It accepts an rcS script "template" and generates and image that + may be mounted under /etc in the NuttX pseudo file system. + +mkdeps.sh +mknulldeps.sh + + NuttX uses the GCC compilers capabilities to create Makefile dependencies. + The bash script mkdeps.sh is used to run GCC in order to create the + dependencies. If a NuttX configuration uses the GCC toolchain, its Make.defs + file (see configs/README.txt) will include a line like: + + MKDEP = $(TOPDIR)/tools/mkdeps.sh + + If the NuttX configuration does not use a GCC compatible toolchain, then + it cannot use the dependencies and instead it uses mknulldeps.sh: + + MKDEP = $(TOPDIR)/tools/mknulldeps.sh + + The mknulldeps.sh is a stub script that does essentially nothing. + +define.sh + + Different compilers have different conventions for specifying pre- + processor definitions on the compiler command line. This bash + script allows the build system to create create command line definitions + without concern for the particular compiler in use. + +incdir.sh + + Different compilers have different conventions for specifying lists + of include file paths on the the compiler command line. This bash + script allows the build system to create include file paths without + concern for the particular compiler in use. + +link.sh +winlink.sh +unlink.sh + + Different file system have different capabilities for symbolic links. + Some windows file systems have no native support for symbolic links. + Cygwin running under windows has special links built in that work with + all cygwin tools. However, they do not work when Windows native tools + are used with cygwin. In that case something different must be done. + + If you are building under Linux or under cygwin with a cygwin tool + chain, then your Make.defs file may have definitions like the + following: + + DIRLINK = $(TOPDIR)/tools/link.sh + DIRUNLINK = (TOPDIR)/tools/unlink.sh + + The first definition is not always present because link.sh is the + default. link.sh is a bash script that performs a normal, Linux-style + symbolic link; unlink.sh is a do-it-all unlinking script. + + But if you are building under cygwin using a Windows native toolchain, + then you will need something like the following in you Make.defs file: + + DIRLINK = $(TOPDIR)/tools/winlink.sh + DIRUNLINK = (TOPDIR)/tools/unlink.sh + + winlink.sh will copy the whole directory instead of linking it. + + NOTE: I have been told that some NuttX users have been able to build + successfully using the GnuWin32 tools and modifying the link.sh + script so that it uses the NTFS mklink command. But I have never + tried that + +mkimage.sh + + The creates a downloadable image as needed with the rrload bootloader. + +indent.sh + + This script can be used to indent .c and .h files in a manner similar + to my coding NuttX coding style. It doesn't do a really good job, + however (see the comments at the top of the indent.sh file). + +zipme.sh + + I use this script to create the nuttx-xx.yy.tar.gz tarballs for + release on SourceForge. It is handy because it also does the + kind of clean that you need to do to make a clean code release. diff --git a/nuttx/tools/bdf-converter.c b/nuttx/tools/bdf-converter.c new file mode 100644 index 0000000000..b32209fcf6 --- /dev/null +++ b/nuttx/tools/bdf-converter.c @@ -0,0 +1,675 @@ +/**************************************************************************** + * tools/bdf-converter.c + * + * Copyright (C) 2011 NX Engineering, S.A., All rights reserved. + * Author: Jose Pablo Carballo Gomez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * Based one the "Glyph Bitmap Distribution Format (BDF) Specification", + * Version 2.2, by Adobe Systems Incorporated. + * + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* +#define VERBOSE +#define DBG +*/ + +// BDF Specification Version 2.2: +// This version lifts the restriction on line length. In this version, the new +// maximum length of a value of the type string is 65535 characters, and hence +// lines may now be at least this long. + +#define BDF_MAX_LINE_LENGTH 65535 + +/* Ranges of 7-bit and 8-bit fonts */ + +#define NXFONT_MIN7BIT 33 +#define NXFONT_MAX7BIT 126 + +#define NXFONT_MIN8BIT 161 +#define NXFONT_MAX8BIT 255 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This structure holds information about a glyph */ + +typedef struct glyphinfo_s +{ + char *name; /* Name for they glyph */ + int encoding; /* The Adobe Standard Encoding value */ + int dw_x0; /* Width in x of the vector indicating + * the position of the next glyph's origin + * relative to the origin of this glyph */ + int dw_y0; /* Width in y of the vector indicating + * the position of the next glyph's origin + * relative to the origin of this glyph */ + int bb_w; /* The width of the black pixels in x */ + int bb_h; /* The height of the black pixels in y */ + int bb_x_off; /* X displacement of the lower left corner + * of the bitmap from origin 0 */ + int bb_y_off; /* Y displacement of the lower left corner + * of the bitmap from origin 0 */ + uint64_t *bitmap; /* Hexadecimal data for the character bitmap */ +} glyphinfo_t; + +/* This structures provides the metrics for one glyph */ + +typedef struct nx_fontmetric_s +{ + uint32_t stride : 3; /* Width of one font row in bytes */ + uint32_t width : 6; /* Width of the font in bits */ + uint32_t height : 6; /* Height of the font in rows */ + uint32_t xoffset : 6; /* Top, left-hand corner X-offset in pixels */ + uint32_t yoffset : 6; /* Top, left-hand corner y-offset in pixels */ + uint32_t unused : 5; +} nx_fontmetric_t; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: trimLine + * + * Description: + * Trims the line removing space characters at the front and at the end + * of the line. + * + * Input Parameters: + * line - The line to trim + * + ****************************************************************************/ +static void trimLine(char *line) +{ + char *str; + str = line; + char *strEnd; + for (strEnd = str + strlen(str) - 1; + strEnd >= str && isspace((int)(*strEnd)); + strEnd--); + *(strEnd + 1) = 0; +} + +/**************************************************************************** + * Name: bdf_parseIntLine + * + * Description: + * Parses a line containing a BDF property followed by integers. It will + * ignore the first token that corresponds to the property name. + * + * Input Parameters: + * line - A line with a BDF property followed by integers, i.e.: + * "FONTBOUNDINGBOX 8 13 0 -2" + * count - How many integers are specified by the BDF property. In the + * example above, count = 4. + * info - A pointer to memory provided by the caller in which to + * return the array of integers. For the example above: + * info[0] = 8 + * info[1] = 13 + * info[2] = 0 + * info[3] = -2 + * + ****************************************************************************/ +static void bdf_parseintline(char *line, unsigned int count, int *info) +{ + char *str, *token, *saveptr1; + str = line; + + /* Ignore the key */ + + token = (char *)strtok_r(str, " ", &saveptr1); + + while ((token = (char *)strtok_r(NULL, " ", &saveptr1)) && count--) + { + *(info++) = atoi(token); + } +} + +/**************************************************************************** + * Name: bdf_printglyphinfo + * + * Description: + * Prints the information available for a glyph. + * + * Input Parameters: + * ginfo - A glyphinfo_t struct with the glyph's information. + * + ****************************************************************************/ +#ifdef DBG +static void bdf_printglyphinfo(const glyphinfo_t *ginfo) +{ + printf("NAME = %s\n", ginfo->name); + printf("ENCODING = %d\n", ginfo->encoding); + printf("DW_X0 = %d\n", ginfo->dw_x0); + printf("DW_Y0 = %d\n", ginfo->dw_y0); + printf("BB_W = %d\n", ginfo->bb_w); + printf("BB_H = %d\n", ginfo->bb_h); + printf("BB_X_OFF = %d\n", ginfo->bb_x_off); + printf("BB_Y_OFF = %d\n", ginfo->bb_y_off); + int i; + for (i = 0; i < ginfo->bb_h; i++) + { + printf("BITMAP[%d] = %x\n", i, ginfo->bitmap[i]); + } +} +#endif /* DBG */ + +/**************************************************************************** + * Name: bdf_printnxmetricinfo + * + * Description: + * Prints the information available for a glyph's metric in the NX + * graphics system. + * + * Input Parameters: + * info - A nx_fontmetric_t struct with the glyph's information. + * + ****************************************************************************/ +#ifdef DBG +static void bdf_printnxmetricinfo(const nx_fontmetric_t *info) +{ + printf("STRIDE = %d\n", info->stride); + printf("WIDTH = %d\n", info->width); + printf("HEIGHT = %d\n", info->height); + printf("XOFFSET = %d\n", info->xoffset); + printf("YOFFSET = %d\n", info->yoffset); +} +#endif /* DBG */ + +/**************************************************************************** + * Name: bdf_getglyphinfo + * + * Description: + * Obtains the information for an individual glyph. The BDF properties + * taken into account are: + * - ENCODING + * - DWIDTH + * - BBX + * BDF properties ignored: + * - SWIDTH + * - SWIDTH1 + * - DWIDTH1 + * - VVECTOR + * + * Input Parameters: + * file - The input file stream pointing to the first line of the + * glyph's information (right after STARTCHAR). + * ginfo - A glyphinfo_t struct to fill with the glyph's information. + * + ****************************************************************************/ +static void bdf_getglyphinfo(FILE *file, glyphinfo_t *ginfo) +{ + char line[BDF_MAX_LINE_LENGTH]; + char lineCopy[BDF_MAX_LINE_LENGTH]; + char *str, *token, *saveptr1; + bool done; + + done = false; + + while(fgets(line, BDF_MAX_LINE_LENGTH, file) != NULL && !done) + { + trimLine(line); + strcpy(lineCopy, line); + str = line; + + while ((token = (char *)strtok_r(str, " ", &saveptr1))) + { + + /* ENCODING information */ + + if(strcmp(token, "ENCODING") == 0) + { + token = (char *)strtok_r(NULL, " ", &saveptr1); + ginfo->encoding = atoi(token); + } + + /* DWIDTH information */ + + if(strcmp(token, "DWIDTH") == 0) + { + token = (char *)strtok_r(NULL, " ", &saveptr1); + ginfo->dw_x0 = atoi(token); + token = (char *)strtok_r(NULL, " ", &saveptr1); + ginfo->dw_y0 = atoi(token); + } + + /* BBX information */ + + else if(strcmp(token, "BBX") == 0) + { + int bbxinfo[4]; + bdf_parseintline(lineCopy, 4, bbxinfo); + ginfo->bb_w = bbxinfo[0]; + ginfo->bb_h = bbxinfo[1]; + ginfo->bb_x_off = bbxinfo[2]; + ginfo->bb_y_off = bbxinfo[3]; + + /* This is the last BDF property of interest*/ + + done = true; + } + + str = NULL; + } + + } +} + +/**************************************************************************** + * Name: bdf_getglyphbitmap + * + * Description: + * Obtains the character bitmap information for an individual glyph. + * + * Input Parameters: + * file - The input file stream pointing to the first line of the + * glyph's bitmap (right after BITMAP). + * ginfo - A glyphinfo_t struct to fill with the glyph's bitmap. + * + ****************************************************************************/ +static void bdf_getglyphbitmap(FILE *file, glyphinfo_t *ginfo) +{ + char line[BDF_MAX_LINE_LENGTH]; + uint64_t *bitmap; + bool readingbitmap; + + bitmap = ginfo->bitmap; + readingbitmap = true; + + while (readingbitmap) + { + if (fgets(line, BDF_MAX_LINE_LENGTH, file) != NULL) + { + trimLine(line); + + if(strcmp(line, "ENDCHAR") == 0) + { + readingbitmap = false; + } + else + { + char *endptr; + *bitmap = strtoul(line, &endptr, 16); + bitmap++; + } + + } + else + { + /* error condition */ + + readingbitmap = false; + } + + } +} + +/**************************************************************************** + * Name: bdf_getstride + * + * Description: + * Obtains the stride for an individual glyph. The stride is the width + * of one glyph's bitmap row in bytes. + * + * Input Parameters: + * ginfo - A glyphinfo_t struct with the glyph's information. + * stride - A pointer to memory provided by the caller in which to + * return the stride. + * + ****************************************************************************/ +static void bdf_getstride(glyphinfo_t *ginfo, uint32_t *stride) +{ + *stride = (ginfo->bb_w % 8 == 0) ? ginfo->bb_w / 8 : ginfo->bb_w / 8 + 1; +} + +/**************************************************************************** + * Name: bdf_printoutput + * + * Description: + * Prints to the output stream the information of an individual glyph in + * the NuttX font format. + * + * Input Parameters: + * out - The output stream. + * ginfo - A glyphinfo_t struct with the glyph's information. + * nxmetric - A nx_fontmetric_t struct with the glyph's information. + * + ****************************************************************************/ +static void bdf_printoutput(FILE *out, + glyphinfo_t *ginfo, + nx_fontmetric_t *nxmetric) +{ + + /* Only interested in the 7 and 8 bit ranges */ + + if ((ginfo->encoding >= NXFONT_MIN7BIT && + ginfo->encoding <= NXFONT_MAX7BIT) || + (ginfo->encoding >= NXFONT_MIN8BIT && + ginfo->encoding <= NXFONT_MAX8BIT)) + { + + /* Glyph general info */ + + if (ginfo->bb_x_off < 0) + { + fprintf(out, + "/* %s (%d) -- NOTE: Xoffset should be %d, not 0. */\n", + ginfo->name, + ginfo->encoding, + ginfo->bb_x_off); + } + else + { + fprintf(out, "/* %s (%d) */\n", ginfo->name, ginfo->encoding); + } + + /* Glyph metrics */ + + fprintf(out, + "#define NXFONT_METRICS_%d {%d, %d, %d, %d, %d, 0}\n", + ginfo->encoding, + nxmetric->stride, + nxmetric->width, + nxmetric->height, + nxmetric->xoffset, + nxmetric->yoffset); + + /* Glyph bitmap */ + + fprintf(out, "#define NXFONT_BITMAP_%d {", ginfo->encoding); + int i, j; + for (i = 0; i < ginfo->bb_h - 1; i++) + { + for (j = 1; j <= nxmetric->stride; j++) + { + int nxbyteoffset; + uint8_t nxbyte = 0; + uint64_t tempbitmap = ginfo->bitmap[i]; + + /* Get the next byte */ + + nxbyteoffset = (nxmetric->stride - j) * 8; + nxbyte = (uint8_t)(tempbitmap >> nxbyteoffset); + fprintf(out, "0x%x, ", nxbyte); + } + } + + /* Different behavior for the last bitmap */ + + for (j = 1; j <= nxmetric->stride; j++) + { + int nxbyteoffset; + uint8_t nxbyte = 0; + uint64_t tempbitmap = ginfo->bitmap[i]; + + /* Get the next byte */ + + nxbyteoffset = (nxmetric->stride - j) * 8; + nxbyte = (uint8_t)(tempbitmap >> nxbyteoffset); + + if (j == nxmetric->stride) + { + fprintf(out, "0x%x}\n", nxbyte); + } + else + { + fprintf(out, "0x%x, ", nxbyte); + } + } + + fprintf(out, "\n"); + } + +} + +/**************************************************************************** + * Main + ****************************************************************************/ + +int main(int argc, char **argv) +{ + FILE *file, *out; + char line[BDF_MAX_LINE_LENGTH]; + char lineCopy[BDF_MAX_LINE_LENGTH]; + char *str, *token, *saveptr1; + char *input, *output; + + /* FONTBOUNDINGBOX properties*/ + + int fbb_x = 0; + int fbb_y = 0; + int fbb_x_off = 0; + int fbb_y_off = 0; + + /* Input BDF file */ + + input = argv[1]; + + if (input == NULL) + { + printf("%s: no input file\n", argv[0]); + exit(0); + } + + file = fopen(input, "r"); + + if (file == NULL) + { + printf("%s: error opening file %s\n", argv[0], input); + exit(0); + } + else + { +#ifdef VERBOSE + printf("Opening \"%s\"\n", input); +#endif /* VERBOSE */ + } + + /* Output file */ + if (argv[2]) + { + output = argv[2]; + } + else + { + output = "nxfonts_myfont.h"; + } + + out = fopen(output, "w"); + + if (out == NULL) + { + printf("%s: error opening file %s\n", argv[0], output); + fclose(file); + exit(0); + } + else + { + while (fgets(line, BDF_MAX_LINE_LENGTH, file) != NULL) + { + +#ifdef DBG + printf("--\n"); +#endif /* DBG */ + + // Save a copy of the line + + strcpy(lineCopy,line); + + // Clean it + + trimLine(line); + str = line; + + while ((token = (char *)strtok_r(str, " ", &saveptr1))) + { + + /* FONTBOUNDINGBOX - Global font information */ + + if (strcmp(token, "FONTBOUNDINGBOX") == 0) + { + int fbbinfo[4]; + bdf_parseintline(lineCopy, 4, fbbinfo); + fbb_x = fbbinfo[0]; + fbb_y = fbbinfo[1]; + fbb_x_off = fbbinfo[2]; + fbb_y_off = fbbinfo[3]; + + /* Print FONTBOUNDINGBOX information */ + + fprintf(out, "/* Maximum height and width of any"); + fprintf(out, " glyph in the set */\n\n"); + fprintf(out, "#define NXFONT_MAXHEIGHT %d\n", fbb_y); + fprintf(out, "#define NXFONT_MAXWIDTH %d\n\n", fbb_x); + } + + /* STARTCHAR - Individual glyph information */ + + if (strcmp(token, "STARTCHAR") == 0) + { + glyphinfo_t ginfo; + + /* Glyph name */ + + ginfo.name = (char *)strtok_r(NULL, " ", &saveptr1); + +#ifdef VERBOSE + printf("Processing glyph: %s\n", ginfo.name); +#endif /* VERBOSE */ + + /* Glyph information: + * ENCODING + * DWIDTH + * BBX + */ + ginfo.encoding = 0; + ginfo.dw_x0 = 0; + ginfo.dw_y0 = 0; + ginfo.bb_w = 0; + ginfo.bb_h = 0; + ginfo.bb_x_off = 0; + ginfo.bb_y_off = 0; + bdf_getglyphinfo(file, &ginfo); + + /* Glyph bitmap */ + + ginfo.bitmap = malloc(sizeof(uint64_t) * ginfo.bb_h); + bdf_getglyphbitmap(file, &ginfo); + +#ifdef DBG + bdf_printglyphinfo(&ginfo); +#endif /* DBG */ + + /* Convert to nxfonts */ + + nx_fontmetric_t nxmetric; + uint32_t stride; + bdf_getstride(&ginfo, &stride); + nxmetric.stride = stride; + nxmetric.width = ginfo.bb_w; + nxmetric.height = ginfo.bb_h; + + /* The NuttX font format does not support + * negative X offsets. */ + + if (ginfo.bb_x_off < 0) + { + nxmetric.xoffset = 0; + printf("%s: ignoring negative x offset for " + "glyph '%s' (%d)\n", + argv[0], + ginfo.name, + ginfo.encoding); + } + else + { + nxmetric.xoffset = ginfo.bb_x_off; + } + + nxmetric.yoffset = fbb_y + fbb_y_off - + ginfo.bb_y_off - ginfo.bb_h; + + +#ifdef DBG + bdf_printnxmetricinfo(&nxmetric); +#endif /* DBG */ + + /* The space (32) character is treated differently */ + + if (ginfo.encoding == 32) + { + fprintf(out, "/* The width of a space */\n\n"); + fprintf(out, "#define NXFONT_SPACEWIDTH %d\n\n", ginfo.dw_x0); + } + else + { + bdf_printoutput(out, &ginfo, &nxmetric); + } + + /* Free memory */ + + free(ginfo.bitmap); + + } + + str = NULL; + } + + } + fclose(file); + fclose(out); + + /* The End */ + + printf("Generated \"%s\"\n", output); + + } + + return EXIT_SUCCESS; +} diff --git a/nuttx/tools/cfgparser.c b/nuttx/tools/cfgparser.c new file mode 100644 index 0000000000..655fac5739 --- /dev/null +++ b/nuttx/tools/cfgparser.c @@ -0,0 +1,168 @@ +/**************************************************************************** + * tools/cfgpaser.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "cfgparser.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +char line[LINESIZE+1]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static char *skip_space(char *ptr) +{ + while (*ptr && isspace((int)*ptr)) ptr++; + return ptr; +} + +static char *find_name_end(char *ptr) +{ + while (*ptr && (isalnum((int)*ptr) || *ptr == '_')) ptr++; + return ptr; +} + +static char *find_value_end(char *ptr) +{ + while (*ptr && !isspace((int)*ptr)) + { + if (*ptr == '"') + { + do ptr++; while (*ptr && *ptr != '"'); + if (*ptr) ptr++; + } + else + { + do ptr++; while (*ptr && !isspace((int)*ptr) && *ptr != '"'); + } + } + return ptr; +} + +static char *read_line(FILE *stream) +{ + char *ptr; + + for (;;) + { + line[LINESIZE] = '\0'; + if (!fgets(line, LINESIZE, stream)) + { + return NULL; + } + else + { + ptr = skip_space(line); + if (*ptr && *ptr != '#' && *ptr != '\n') + { + return ptr; + } + } + } +} + +static void parse_line(char *ptr, char **varname, char **varval) +{ + *varname = ptr; + *varval = NULL; + + ptr = find_name_end(ptr); + if (*ptr && *ptr != '=') + { + *ptr = '\0'; + ptr = skip_space(ptr + 1); + } + + if (*ptr == '=') + { + *ptr = '\0'; + ptr = skip_space(ptr + 1); + if (*ptr) + { + *varval = ptr; + ptr = find_value_end(ptr); + *ptr = '\0'; + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void parse_file(FILE *stream) +{ + char *varname; + char *varval; + char *ptr; + + do + { + ptr = read_line(stream); + if (ptr) + { + parse_line(ptr, &varname, &varval); + if (varname) + { + if (!varval || strcmp(varval, "n") == 0) + { + printf("#undef %s\n", varname); + } + else if (strcmp(varval, "y") == 0) + { + printf("#define %s 1\n", varname); + } + else + { + printf("#define %s %s\n", varname, varval); + } + } + } + } + while (ptr); +} diff --git a/nuttx/tools/cfgparser.h b/nuttx/tools/cfgparser.h new file mode 100644 index 0000000000..02de42928b --- /dev/null +++ b/nuttx/tools/cfgparser.h @@ -0,0 +1,64 @@ +/**************************************************************************** + * tools/cfgpaser.h + * + * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __TOOLS_CFGPARSER_H +#define __TOOLS_CFGPARSER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define LINESIZE ( PATH_MAX > 256 ? PATH_MAX : 256 ) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern char line[LINESIZE+1]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +extern void parse_file(FILE *stream); + +#endif /* __TOOLS_CFGPARSER_H */ diff --git a/nuttx/tools/cmpconfig.c b/nuttx/tools/cmpconfig.c new file mode 100644 index 0000000000..2958acdc78 --- /dev/null +++ b/nuttx/tools/cmpconfig.c @@ -0,0 +1,328 @@ +/**************************************************************************** + * tools/cmpconfig.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct variable_s +{ + struct variable_s *flink; + char *var; + char *val; + char storage[1]; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void show_usage(const char *progname) +{ + fprintf(stderr, "USAGE: %s \n", progname); + exit(EXIT_FAILURE); +} + +static char *skip_space(char *ptr) +{ + while (*ptr && isspace((int)*ptr)) ptr++; + return ptr; +} + +static char *read_line(FILE *stream, char *line, int len) +{ + char *ptr; + + for (;;) + { + line[len-1] = '\0'; + if (!fgets(line, len, stream)) + { + return NULL; + } + else + { + ptr = skip_space(line); + if (*ptr && *ptr != '#' && *ptr != '\n') + { + return ptr; + } + } + } +} + +static char *find_name_end(char *ptr) +{ + while (*ptr && (isalnum((int)*ptr) || *ptr == '_')) ptr++; + return ptr; +} + +static char *find_value_end(char *ptr) +{ + while (*ptr && !isspace((int)*ptr)) + { + if (*ptr == '"') + { + do ptr++; while (*ptr && *ptr != '"'); + if (*ptr) ptr++; + } + else + { + do ptr++; while (*ptr && !isspace((int)*ptr) && *ptr != '"'); + } + } + return ptr; +} + +static void parse_line(char *ptr, char **varname, char **varval) +{ + *varname = ptr; + *varval = NULL; + + ptr = find_name_end(ptr); + if (*ptr && *ptr != '=') + { + *ptr = '\0'; + ptr = skip_space(ptr + 1); + } + + if (*ptr == '=') + { + *ptr = '\0'; + ptr = skip_space(ptr + 1); + if (*ptr) + { + *varval = ptr; + ptr = find_value_end(ptr); + *ptr = '\0'; + } + } +} + +static void parse_file(FILE *stream, struct variable_s **list) +{ + char line[10242]; + struct variable_s *curr; + struct variable_s *prev; + struct variable_s *next; + char *varname; + char *varval; + char *ptr; + + do + { + ptr = read_line(stream, line, 1024); + if (ptr) + { + parse_line(ptr, &varname, &varval); + if (!varval || strcmp(varval, "n") == 0) + { + continue; + } + + if (varname) + { + int varlen = strlen(varname) + 1; + int vallen = 0; + + if (varval) + { + vallen = strlen(varval) + 1; + } + + curr = (struct variable_s *)malloc(sizeof(struct variable_s) + varlen + vallen - 1); + if (curr) + { + curr->var = &curr->storage[0]; + strcpy(curr->var, varname); + + curr->val = NULL; + if (varval) + { + curr->val = &curr->storage[varlen]; + strcpy(curr->val, varval); + } + } + + prev = 0; + next = *list; + while (next && strcmp(next->var, curr->var) <= 0) + { + prev = next; + next = next->flink; + } + + if (prev) + { + prev->flink = curr; + } + else + { + *list = curr; + } + curr->flink = next; + } + } + } + while (ptr); +} + +static void compare_variables(struct variable_s *list1, struct variable_s *list2) +{ + char *varval1; + char *varval2; + + while (list1 || list2) + { + if (list1 && list1->val) + { + varval1 = list1->val; + } + else + { + varval1 = ""; + } + + if (list2 && list2->val) + { + varval2 = list2->val; + } + else + { + varval2 = ""; + } + + if (!list1) + { + printf("file1:\n"); + printf("file2: %s=%s\n\n", list2->var, varval2); + list2 = list2->flink; + } + else if (!list2) + { + printf("file1: %s=%s\n", list1->var, varval1); + printf("file2:\n\n"); + list1 = list1->flink; + } + else + { + int result = strcmp(list1->var, list2->var); + if (result < 0) + { + printf("file1: %s=%s\n", list1->var, varval1); + printf("file2:\n\n"); + list1 = list1->flink; + } + else if (result > 0) + { + printf("file1:\n"); + printf("file2: %s=%s\n\n", list2->var, varval2); + list2 = list2->flink; + } + else + { + int result = strcmp(varval1, varval2); + if (result != 0) + { + printf("file1: %s=%s\n", list1->var, varval1); + printf("file2: %s=%s\n\n", list2->var, varval2); + } + + list1 = list1->flink; + list2 = list2->flink; + } + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + struct variable_s *list1 = 0; + struct variable_s *list2 = 0; + FILE *stream1; + FILE *stream2; + + if (argc != 3) + { + fprintf(stderr, "Unexpected number of arguments: %d\n\n", argc); + show_usage(argv[0]); + } + + stream1 = fopen(argv[1], "r"); + if (!stream1) + { + fprintf(stderr, "Failed to open %s for reading: %s\n\n", + argv[1], strerror(errno)); + show_usage(argv[0]); + } + + stream2 = fopen(argv[2], "r"); + if (!stream2) + { + fprintf(stderr, "Failed to open %s for reading: %s\n\n", + argv[2], strerror(errno)); + show_usage(argv[0]); + } + + parse_file(stream1, &list1); + parse_file(stream2, &list2); + + fclose(stream1); + fclose(stream2); + + printf("Comparing:\n\n"); + printf(" file1 = %s\n", argv[1]); + printf(" file2 = %s\n\n", argv[2]); + compare_variables(list1, list2); + return EXIT_SUCCESS; +} diff --git a/nuttx/tools/configure.sh b/nuttx/tools/configure.sh new file mode 100755 index 0000000000..3aaed06817 --- /dev/null +++ b/nuttx/tools/configure.sh @@ -0,0 +1,174 @@ +#!/bin/bash +# configure.sh +# +# Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +WD=`pwd` +TOPDIR="${WD}/.." +USAGE=" + +USAGE: ${0} [-d] [-a ] / + +Where: + is the name of the board in the configs directory + is the name of the board configuration sub-directory + is the path to the apps/ directory, relative to the nuttx directory + +" + +# Parse command arguments + +unset boardconfig +unset appdir + +while [ ! -z "$1" ]; do + case "$1" in + -d ) + set -x + ;; + -h ) + echo "$USAGE" + exit 0 + ;; + -a ) + shift + appdir=$1 + ;; + *) + if [ ! -z "${boardconfig}" ]; then + echo "" + echo " defined twice" + echo "$USAGE" + exit 1 + fi + boardconfig=$1 + ;; + esac + shift +done + +# Sanity checking + +if [ -z "${boardconfig}" ]; then + echo "" + echo "Missing argument" + echo "$USAGE" + exit 2 +fi + +configpath=${TOPDIR}/configs/${boardconfig} +if [ ! -d "${configpath}" ]; then + echo "Directory ${configpath} does not exist. Options are:" + echo "" + echo "Select one of the following options for :" + configlist=`find ${TOPDIR}/configs -name defconfig` + for defconfig in $configlist; do + config=`dirname $defconfig | sed -e "s,${TOPDIR}/configs/,,g"` + echo " $config" + done + echo "" + echo "$USAGE" + exit 3 +fi + +if [ ! -r "${configpath}/Make.defs" ]; then + echo "File ${configpath}/Make.defs does not exist" + exit 4 +fi + +if [ ! -r "${configpath}/setenv.sh" ]; then + echo "File ${configpath}/setenv.sh does not exist" + exit 5 +fi + +if [ ! -r "${configpath}/defconfig" ]; then + echo "File ${configpath}/defconfig does not exist" + exit 6 +fi + +# Check for the apps/ dir in the usual place if appdir was not provided + +if [ -z "${appdir}" ]; then + + # Check for a version file + + unset CONFIG_VERSION_STRING + if [ -x "${TOPDIR}/.version" ]; then + . "${TOPDIR}/.version" + fi + + # Check for an unversioned apps/ directory + + if [ -d "${TOPDIR}/../apps" ]; then + appdir="../apps" + + else + # Check for a versioned apps/ directory + + if [ -d "${TOPDIR}/../apps-${CONFIG_VERSION_STRING}" ]; then + appdir="../apps-${CONFIG_VERSION_STRING}" + fi + fi +fi + +# Okay... setup the configuration + +install -C "${configpath}/Make.defs" "${TOPDIR}/." || \ + { echo "Failed to copy ${configpath}/Make.defs" ; exit 7 ; } +install -C "${configpath}/setenv.sh" "${TOPDIR}/." || \ + { echo "Failed to copy ${configpath}/setenv.sh" ; exit 8 ; } +chmod 755 "${TOPDIR}/setenv.sh" +install -C "${configpath}/defconfig" "${TOPDIR}/.configX" || \ + { echo "Failed to copy ${configpath}/defconfig" ; exit 9 ; } + +# Copy option appconfig + +if [ ! -z "${appdir}" ]; then + if [ ! -r "${configpath}/appconfig" ]; then + echo "NOTE: No readable appconfig file found in ${configpath}" + else + install -C "${configpath}/appconfig" "${TOPDIR}/${appdir}/.config" || \ + { echo "Failed to copy ${configpath}/appconfig" ; exit 10 ; } + + echo "" >> "${TOPDIR}/.configX" + echo "# Application configuration" >> "${TOPDIR}/.configX" + echo "" >> "${TOPDIR}/.configX" + echo "CONFIG_APPS_DIR=\"$appdir\"" >> "${TOPDIR}/.configX" + fi +fi + +# install the final .configX only if it differs from any existing +# .config file. + +install -C "${TOPDIR}/.configX" "${TOPDIR}/.config" +rm -f "${TOPDIR}/.configX" + diff --git a/nuttx/tools/define.sh b/nuttx/tools/define.sh new file mode 100755 index 0000000000..8b2b0e364c --- /dev/null +++ b/nuttx/tools/define.sh @@ -0,0 +1,224 @@ +#!/bin/bash +# tools/define.sh +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# Handle command line options +# + +progname=$0 +wintool=n +usage="USAGE: $progname [-w] [-d] [-l] [-h] [=val1] [[=val2] [[=val3] ...]]" +advice="Try '$progname -h' for more information" + +while [ ! -z "$1" ]; do + case $1 in + -d ) + set -x + ;; + -w ) + wintool=y + ;; + -h ) + echo "$progname is a tool for flexible generation of command line pre-processor" + echo "definitions arguments for a variety of diffent compilers in a variety of" + echo "compilation environments" + echo "" + echo $usage + echo "" + echo "Where:" + echo " " + echo " The full path to your compiler" + echo " [ ..." + echo " A list of pre-preprocesser variable names to be defind." + echo " [=val1] [=val2] [=val3]" + echo " optional values to be assigned to each pre-processor variable." + echo " If not supplied, the variable will be defined with no explicit value." + echo " -w" + echo " The compiler is a Windows native tool and requires Windows" + echo " style pathnames like C:\\Program Files" + echo " -d" + echo " Enable script debug" + ;; + * ) + break; + ;; + esac + shift +done + +ccpath=$1 +shift +varlist=$@ + +if [ -z "$ccpath" ]; then + echo "Missing compiler path" + echo $usage + echo $advice + exit 1 +fi + +if [ -z "$varlist" ]; then + echo "Missing definition list" + echo $usage + echo $advice + exit 1 +fi + +# +# Most compilers support CFLAG options like '-D' to add pre-processor +# variable defintions. Some (like the Zilog tools), do not. This script +# makes the selection of pre-processor definitions compiler independent. +# +# Below are all known compiler names (as found in the config/*/*/Make.defs +# files). If a new compiler is used that has some unusual syntax, then +# additional logic needs to be added to this file. +# +# NAME Syntax +# $(CROSSDEV)gcc -D -D -D ... +# sdcc -D -D -D ... +# $(ZDSBINDIR)/ez8cc.exe -define: -define: -define: ... +# $(ZDSBINDIR)/zneocc.exe -define: -define: -define: ... +# $(ZDSBINDIR)/ez80cc.exe -define: -define: -define: ... +# +os=`uname -o 2>/dev/null || echo "Other"` + +# +# Let's assume that all GCC compiler paths contain the string gcc and +# no non-GCC compiler pathes include this substring +# +gcc=`echo $ccpath | grep gcc` +sdcc=`echo $ccpath | grep sdcc` + +if [ "X$os" = "XCygwin" ]; then + # + # We can treat Cygwin native toolchains just like Linux native + # toolchains in the Linux. Let's assume: + # 1. GCC or SDCC are the only possible Cygwin native compilers + # 2. If this is a Window native GCC version, then -w provided + # on the command line (wintool=y) + + if [ -z "$gcc" -a -z "$sdcc" ]; then + # + # Not GCC or SDCC, must be Windows native + # + compiler=`cygpath -u "$ccpath"` + else + if [ "X$wintool" == "Xy" ]; then + # + # It is a native GCC or SDCC compiler + # + compiler=`cygpath -u "$ccpath"` + else + # + # GCC or SDCC and not for Windows + # + compiler="$ccpath" + fi + fi +else + # + # Otherwise, we must be in a Linux environment where there are + # only Linux native toolchains + # + compiler="$ccpath" +fi +exefile=`basename "$compiler"` + +# Check for some well known, non-GCC Windows native tools that require +# a special output format as well as special paths + +if [ "X$exefile" = "Xez8cc.exe" -o "X$exefile" = "Xzneocc.exe" -o "X$exefile" = "Xez80cc.exe" ]; then + fmt=define +else + fmt=std +fi + +# Now process each directory in the directory list + +unset response +for vardef in $varlist; do + + varname=`echo $vardef | cut -d'=' -f1` + varvalue=`echo $vardef | cut -d'=' -f2` + + # Handle the output depending on if there is a value for the variable or not + + if [ -z "$varvalue" ]; then + + # Handle the output using the selected format + + if [ "X$fmt" = "Xdefine" ]; then + # Treat the first definition differently + + if [ -z "$response" ]; then + response="-define:"$varname + else + response=$response" -define:$varname" + fi + else + # Treat the first definition differently + + if [ -z "$response" ]; then + response=-D$varname + else + response=$response" -D$varname" + fi + fi + else + + # Handle the output using the selected format + + if [ "X$fmt" = "Xdefine" ]; then + # Treat the first definition differently + + if [ -z "$response" ]; then + response="-define:"$varname=$varvalue + else + response=$response" -define:$varname=$varvalue" + fi + else + # Treat the first definition differently + + if [ -z "$response" ]; then + response=-D$varname=$varvalue + else + response=$response" -D$varname=$varvalue" + fi + fi + fi +done + +echo $response + + diff --git a/nuttx/tools/incdir.sh b/nuttx/tools/incdir.sh new file mode 100755 index 0000000000..be6a1d07a7 --- /dev/null +++ b/nuttx/tools/incdir.sh @@ -0,0 +1,211 @@ +#!/bin/bash +# tools/incdir.sh +# +# Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# Handle command line options + +progname=$0 +wintool=n +usage="USAGE: $progname [-w] [-d] [-h] [ [ ...]]" +advice="Try '$progname -h' for more information" + +while [ ! -z "$1" ]; do + case $1 in + -d ) + set -x + ;; + -w ) + wintool=y + ;; + -h ) + echo "$progname is a tool for flexible generation of include path arguments for a" + echo "variety of different compilers in a variety of compilation environments" + echo "" + echo $usage + echo "" + echo "Where:" + echo " " + echo " The full path to your compiler" + echo " [ [ ...]]" + echo " A list of include directories" + echo " -w" + echo " The compiler is a Windows native tool and requires Windows" + echo " style pathnames like C:\\Program Files" + echo " -d" + echo " Enable script debug" + ;; + * ) + break; + ;; + esac + shift +done + +ccpath=$1 +shift +dirlist=$@ + +if [ -z "$ccpath" ]; then + echo "Missing compiler path" + echo $usage + echo $advice + exit 1 +fi + +if [ -z "$dirlist" ]; then + echo "Missing include directory list" + echo $usage + echo $advice + exit 1 +fi + +# +# Most compilers support CFLAG options like '-I' to add include +# file header paths. Some (like the Zilog tools), do not. This script +# makes the selection of header file paths compiler independent. +# +# Below are all known compiler names (as found in the config/*/*/Make.defs +# files). If a new compiler is used that has some unusual syntax, then +# additional logic needs to be added to this file. +# +# NAME Syntax +# $(CROSSDEV)gcc -I -I -I ... +# sdcc -I -I -I ... +# $(ZDSBINDIR)/ez8cc.exe -usrinc:':::...` +# $(ZDSBINDIR)/zneocc.exe -usrinc:':::...` +# $(ZDSBINDIR)/ez80cc.exe -usrinc:':::...` +# +# Furthermore, just to make matters more difficult, with Windows based +# toolchains, we have to use the full windows-style paths to the header +# files. + +os=`uname -o 2>/dev/null || echo "Other"` + +# Let's assume that all GCC compiler paths contain the string gcc or +# g++ and no non-GCC compiler pathes include these substrings + +gcc=`echo $ccpath | grep gcc` +if [ -z "${gcc}" ]; then + gcc=`echo $ccpath | grep g++` +fi + +sdcc=`echo $ccpath | grep sdcc` + +if [ "X$os" = "XCygwin" ]; then + # We can treat Cygwin native toolchains just like Linux native + # toolchains in the Linux. Let's assume: + # 1. GCC or SDCC are the only possible Cygwin native compilers + # 2. If this is a Window native GCC version, then -w must be + # provided on the command line (wintool=y) + + if [ -z "$gcc" -a -z "$sdcc" ]; then + # Not GCC or SDCC, must be Windows native + windows=yes + compiler=`cygpath -u "$ccpath"` + else + if [ "X$wintool" == "Xy" ]; then + # It is a native GCC or SDCC compiler + windows=yes + compiler=`cygpath -u "$ccpath"` + else + # GCC or SDCC and not for Windows + windows=no + compiler="$ccpath" + fi + fi +else + # Otherwise, we must be in a Linux environment where there are + # only Linux native toolchains + windows=no + compiler="$ccpath" +fi +exefile=`basename "$compiler"` + +# Check for some well known, non-GCC Windows native tools that require +# a special output format as well as special paths + +if [ "X$exefile" = "Xez8cc.exe" -o "X$exefile" = "Xzneocc.exe" -o "X$exefile" = "Xez80cc.exe" ]; then + fmt=userinc +else + fmt=std +fi + +# Now process each directory in the directory list + +unset response +for dir in $dirlist; do + + # Verify that the include directory exists + + if [ ! -d $dir ]; then + echo "Include path '$dir' does not exist" + echo $showusage + exit 1 + fi + + # Check if the path needs to be extended for Windows-based tools under Cygwin + + if [ "X$windows" = "Xyes" ]; then + path=`cygpath -w $dir` + else + path=$dir + fi + + # Handle the output using the selected format + + if [ "X$fmt" = "Xuserinc" ]; then + # Treat the first directory differently + + if [ -z "$response" ]; then + response="-usrinc:'"$path + else + response=$response":$path" + fi + else + # Treat the first directory differently + + if [ -z "$response" ]; then + response=-I\"$path\" + else + response=$response" -I\"$path\"" + fi + fi +done + +if [ "X$fmt" = "Xuserinc" ]; then + response=$response"'" +fi + +echo $response + + diff --git a/nuttx/tools/indent.sh b/nuttx/tools/indent.sh new file mode 100755 index 0000000000..938502e0f9 --- /dev/null +++ b/nuttx/tools/indent.sh @@ -0,0 +1,85 @@ +#!/bin/sh +############################################################################ +# tools/indent.sh +# +# Copyright (C) 2008, 2010 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ +# +# This script uses the Linux 'indent' utility to re-format C source files +# to match the coding style that I use. It differs from my coding style in that +# +# - I normally put the trailing */ of a multi-line comment on a separate line, +# - I usually align things vertically (like '=' in assignments), +# - indent puts a bogus blank line at the top of the file, +# - I don't like the way it handles nested conditional compilation intermixed with code. +# + +# Constants + +options="-nbad -bap -bbb -nbbo -nbc -bl -bl2 -bls -nbs -cbi2 -ncdw -nce -ci2 -cli0 -cp40 -ncs -nbfda -nbfde -di1 -nfc1 -fca -i2 -l80 -lp -ppi2 -lps -npcs -pmt -nprs -npsl -saf -sai -sbi2 -saw -sc -sob -nss -nut" + +usage="USAGE: $0 " + +# Inputs + +infile=$1 +outfile=$2 + +# Verify inputs + +if [ -z "$infile" ]; then + echo "Missing " + echo $usage + exit 1 +fi + +if [ ! -r $infile ]; then + echo "Readable $infile does not exist" + exit 1 +fi + +if [ -z "$outfile" ]; then + echo "Missing " + echo $usage + exit 1 +fi + +if [ -f $outfile ]; then + echo "Removing old $outfile" + rm $outfile || { echo "Failed to remove $outfile" ; exit 1 ; } +fi + +# Perform the indentation + +indent $options $infile -o $outfile + + diff --git a/nuttx/tools/link.sh b/nuttx/tools/link.sh new file mode 100755 index 0000000000..7927d65c83 --- /dev/null +++ b/nuttx/tools/link.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################ +# tools/link.sh +# +# Copyright (C) 2008 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ +#set -x + +src=$1 +dest=$2 + +# Verify that arguments were provided + +if [ -z "${src}" -o -z "${dest}" ]; then + echo "Missing src and/or dest arguments" + exit 1 +fi + +# Check if something already exists at the destination path replace it with +# the new link (which might be different). Note that we check for the +# the link (-h) before we check for existence (-e) because a bad link will +# report that it does not exist. + +if [ -h "${dest}" ]; then + rm -f "${dest}" +else + + # If the path exists and is a directory that contains the "fake link" + # mark, then treat it like a soft link (i.e., remove the directory) + + if [ -d "${dest}" -a -f "${dest}/.fakelnk" ]; then + rm -rf "${dest}" + else + + # Does anything exist at the destination path? + + if [ -e "${dest}" ]; then + + # It is something else (like a file) or directory that does + # not contain the "fake link" mark + + echo "${dest} already exists but is not a symbolic link" + exit 1 + fi + fi +fi + +# Verify that a directory exists at the source path + +if [ ! -d "${src}" ]; then + echo "No directory at ${src}" + exit 1 +fi + +# Create the soft link + +ln -s "${src}" "${dest}" || \ + { echo "Failed to create link: $dest" ; exit 1 ; } diff --git a/nuttx/tools/mkconfig.c b/nuttx/tools/mkconfig.c new file mode 100644 index 0000000000..97e2a9c34c --- /dev/null +++ b/nuttx/tools/mkconfig.c @@ -0,0 +1,264 @@ +/**************************************************************************** + * tools/mkconfig.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "cfgparser.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define DEFCONFIG ".config" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + static inline char *getfilepath(const char *name) +{ + snprintf(line, PATH_MAX, "%s/" DEFCONFIG, name); + line[PATH_MAX] = '\0'; + return strdup(line); +} + +static void show_usage(const char *progname) +{ + fprintf(stderr, "USAGE: %s \n", progname); + exit(1); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + char *filepath; + FILE *stream; + + if (argc != 2) + { + fprintf(stderr, "Unexpected number of arguments\n"); + show_usage(argv[0]); + } + + filepath = getfilepath(argv[1]); + if (!filepath) + { + fprintf(stderr, "getfilepath failed\n"); + exit(2); + } + + stream = fopen(filepath, "r"); + if (!stream) + { + fprintf(stderr, "open %s failed: %s\n", filepath, strerror(errno)); + exit(3); + } + + printf("/* config.h -- Autogenerated! Do not edit. */\n\n"); + printf("#ifndef __INCLUDE_NUTTX_CONFIG_H\n"); + printf("#define __INCLUDE_NUTTX_CONFIG_H\n\n"); + printf("/* Architecture-specific options *************************/\n\n"); + parse_file(stream); + printf("\n/* Sanity Checks *****************************************/\n\n"); + printf("/* If this is an NXFLAT, external build, then make sure that\n"); + printf(" * NXFLAT support is enabled in the base code.\n"); + printf(" */\n\n"); + printf("#if defined(__NXFLAT__) && !defined(CONFIG_NXFLAT)\n"); + printf("# error \"NXFLAT support not enabled in this configuration\"\n"); + printf("#endif\n\n"); + printf("/* NXFLAT requires PIC support in the TCBs. */\n\n"); + printf("#if defined(CONFIG_NXFLAT)\n"); + printf("# undef CONFIG_PIC\n"); + printf("# define CONFIG_PIC 1\n"); + printf("#endif\n\n"); + printf("/* Binary format support is disabled if no binary formats are\n"); + printf(" * configured (at present, NXFLAT is the only supported binary.\n"); + printf(" * format).\n"); + printf(" */\n\n"); + printf("#if !defined(CONFIG_NXFLAT)\n"); + printf("# undef CONFIG_BINFMT_DISABLE\n"); + printf("# define CONFIG_BINFMT_DISABLE 1\n"); + printf("#endif\n\n"); + printf("/* The correct way to disable RR scheduling is to set the\n"); + printf(" * timeslice to zero.\n"); + printf(" */\n\n"); + printf("#ifndef CONFIG_RR_INTERVAL\n"); + printf("# define CONFIG_RR_INTERVAL 0\n"); + printf("#endif\n\n"); + printf("/* The correct way to disable filesystem supuport is to set the\n"); + printf(" * number of file descriptors to zero.\n"); + printf(" */\n\n"); + printf("#ifndef CONFIG_NFILE_DESCRIPTORS\n"); + printf("# define CONFIG_NFILE_DESCRIPTORS 0\n"); + printf("#endif\n\n"); + printf("/* If a console is selected, then make sure that there are\n"); + printf(" * resources for 3 file descriptors and, if any streams are\n"); + printf(" * selected, also for 3 file streams.\n"); + printf(" */\n\n"); + printf("#ifdef CONFIG_DEV_CONSOLE\n"); + printf("# if CONFIG_NFILE_DESCRIPTORS < 3\n"); + printf("# undef CONFIG_NFILE_DESCRIPTORS\n"); + printf("# define CONFIG_NFILE_DESCRIPTORS 3\n"); + printf("# endif\n\n"); + printf("# if CONFIG_NFILE_STREAMS > 0 && CONFIG_NFILE_STREAMS < 3\n"); + printf("# undef CONFIG_NFILE_STREAMS\n"); + printf("# define CONFIG_NFILE_STREAMS 3\n"); + printf("# endif\n\n"); + printf("/* If no console is selected, then disable all console devices */\n\n"); + printf("#else\n"); + printf("# undef CONFIG_DEV_LOWCONSOLE\n"); + printf("# undef CONFIG_RAMLOG_CONSOLE\n"); + printf("# undef CONFIG_CDCACM_CONSOLE\n"); + printf("# undef CONFIG_PL2303_CONSOLE\n"); + printf("#endif\n\n"); + printf("/* If priority inheritance is disabled, then do not allocate any\n"); + printf(" * associated resources.\n"); + printf(" */\n\n"); + printf("#if !defined(CONFIG_PRIORITY_INHERITANCE) || !defined(CONFIG_SEM_PREALLOCHOLDERS)\n"); + printf("# undef CONFIG_SEM_PREALLOCHOLDERS\n"); + printf("# define CONFIG_SEM_PREALLOCHOLDERS 0\n"); + printf("#endif\n\n"); + printf("#if !defined(CONFIG_PRIORITY_INHERITANCE) || !defined(CONFIG_SEM_NNESTPRIO)\n"); + printf("# undef CONFIG_SEM_NNESTPRIO\n"); + printf("# define CONFIG_SEM_NNESTPRIO 0\n"); + printf("#endif\n\n"); + printf("/* If no file descriptors are configured, then make certain no\n"); + printf(" * streams are configured either.\n"); + printf(" */\n\n"); + printf("#if CONFIG_NFILE_DESCRIPTORS == 0\n"); + printf("# undef CONFIG_NFILE_STREAMS\n"); + printf("# define CONFIG_NFILE_STREAMS 0\n"); + printf("#endif\n\n"); + printf("/* There must be at least one memory region. */\n\n"); + printf("#ifndef CONFIG_MM_REGIONS\n"); + printf("# define CONFIG_MM_REGIONS 1\n"); + printf("#endif\n\n"); + printf("/* If no file streams are configured, then make certain that buffered I/O\n"); + printf(" * support is disabled\n"); + printf(" */\n\n"); + printf("#if CONFIG_NFILE_STREAMS == 0\n"); + printf("# undef CONFIG_STDIO_BUFFER_SIZE\n"); + printf("# define CONFIG_STDIO_BUFFER_SIZE 0\n"); + printf("#endif\n\n"); + printf("/* We are building a kernel version of the C library, then some user-space features\n"); + printf(" * need to be disabled\n"); + printf(" */\n\n"); + printf("#if defined(CONFIG_NUTTX_KERNEL) && defined(__KERNEL__)\n"); + printf("# undef CONFIG_STDIO_BUFFER_SIZE\n"); + printf("# define CONFIG_STDIO_BUFFER_SIZE 0\n"); + printf("# undef CONFIG_NUNGET_CHARS\n"); + printf("# define CONFIG_NUNGET_CHARS 0\n"); + printf("#endif\n\n"); + printf("/* If no standard C buffered I/O is not supported, then line-oriented buffering\n"); + printf(" * cannot be supported.\n"); + printf(" */\n\n"); + printf("#if CONFIG_STDIO_BUFFER_SIZE == 0\n"); + printf("# undef CONFIG_STDIO_LINEBUFFER\n"); + printf("#endif\n\n"); + printf("/* If the maximum message size is zero, then we assume that message queues\n"); + printf(" * support should be disabled\n"); + printf(" */\n\n"); + printf("#if CONFIG_MQ_MAXMSGSIZE <= 0 && !defined(CONFIG_DISABLE_MQUEUE)\n"); + printf("# define CONFIG_DISABLE_MQUEUE 1\n"); + printf("#endif\n\n"); + printf("/* If mountpoint support in not included, then no filesystem can be supported */\n\n"); + printf("#ifdef CONFIG_DISABLE_MOUNTPOINT\n"); + printf("# undef CONFIG_FS_FAT\n"); + printf("# undef CONFIG_FS_ROMFS\n"); + printf("# undef CONFIG_FS_NXFFS\n"); + printf("# undef CONFIG_APPS_BINDIR\n"); + printf("# undef CONFIG_NFS\n"); + printf("#endif\n\n"); + printf("/* Check if any readable and writable filesystem (OR USB storage) is supported */\n\n"); + printf("#undef CONFIG_FS_READABLE\n"); + printf("#undef CONFIG_FS_WRITABLE\n"); + printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_FS_ROMFS) || defined(CONFIG_USBMSC) || \\\n"); + printf(" defined(CONFIG_FS_NXFFS) || defined(CONFIG_APPS_BINDIR) || defined(CONFIG_NFS)\n"); + printf("# define CONFIG_FS_READABLE 1\n"); + printf("#endif\n\n"); + printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_USBMSC) || defined(CONFIG_FS_NXFFS) || \\\n"); + printf(" defined(CONFIG_NFS)\n"); + printf("# define CONFIG_FS_WRITABLE 1\n"); + printf("#endif\n\n"); + printf("/* There can be no network support with no socket descriptors */\n\n"); + printf("#if CONFIG_NSOCKET_DESCRIPTORS <= 0\n"); + printf("# undef CONFIG_NET\n"); + printf("#endif\n\n"); + printf("/* Conversely, if there is no network support, there is no need for\n"); + printf(" * socket descriptors\n"); + printf(" */\n\n"); + printf("#ifndef CONFIG_NET\n"); + printf("# undef CONFIG_NSOCKET_DESCRIPTORS\n"); + printf("# define CONFIG_NSOCKET_DESCRIPTORS 0\n"); + printf("#endif\n\n"); + printf("/* Protocol support can only be provided on top of basic network support */\n\n"); + printf("#ifndef CONFIG_NET\n"); + printf("# undef CONFIG_NET_TCP\n"); + printf("# undef CONFIG_NET_UDP\n"); + printf("# undef CONFIG_NET_ICMP\n"); + printf("#endif\n\n"); + printf("/* NFS client can only be provided on top of UDP network support */\n\n"); + printf("#if !defined(CONFIG_NET) || !defined(CONFIG_NET_UDP)\n"); + printf("# undef CONFIG_NFS\n"); + printf("#endif\n\n"); + printf("/* Verbose debug and sub-system debug only make sense if debug is enabled */\n\n"); + printf("#ifndef CONFIG_DEBUG\n"); + printf("# undef CONFIG_DEBUG_VERBOSE\n"); + printf("# undef CONFIG_DEBUG_SCHED\n"); + printf("# undef CONFIG_DEBUG_MM\n"); + printf("# undef CONFIG_DEBUG_PAGING\n"); + printf("# undef CONFIG_DEBUG_DMA\n"); + printf("# undef CONFIG_DEBUG_FS\n"); + printf("# undef CONFIG_DEBUG_LIB\n"); + printf("# undef CONFIG_DEBUG_BINFMT\n"); + printf("# undef CONFIG_DEBUG_NET\n"); + printf("# undef CONFIG_DEBUG_USB\n"); + printf("# undef CONFIG_DEBUG_GRAPHICS\n"); + printf("# undef CONFIG_DEBUG_GPIO\n"); + printf("# undef CONFIG_DEBUG_STACK\n"); + printf("#endif\n\n"); + printf("#endif /* __INCLUDE_NUTTX_CONFIG_H */\n"); + fclose(stream); + return 0; +} diff --git a/nuttx/tools/mkdeps.sh b/nuttx/tools/mkdeps.sh new file mode 100755 index 0000000000..6d83f2ca01 --- /dev/null +++ b/nuttx/tools/mkdeps.sh @@ -0,0 +1,196 @@ +#!/bin/bash +############################################################################ +# tools/mkdeps.sh +# +# Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Usage: + +show_usage () +{ + echo "" + echo "$progname [OPTIONS] CC -- CFLAGS -- file [file [file...]]" + echo "" + echo "Where:" + echo " CC" + echo " A variable number of arguments that define how to execute the compiler" + echo " CFLAGS" + echo " The compiler compilation flags" + echo " file" + echo " One or more C files whose dependencies will be checked. Each file is expected" + echo " to reside in the current directory unless --dep-path is provided on the command line" + echo "" + echo "And [OPTIONS] include:" + echo " --dep-debug" + echo " Enable script debug" + echo " --dep-path " + echo " Do not look in the current directory for the file. Instead, look in to see" + echo " if the file resides there. --dep-path may be used multiple times to specify" + echo " multiple alternative location" + echo " --winpaths " + echo " CC generates dependency lists using Windows paths (e.g., C:\blablah\blabla). This" + echo " switch instructs the script to use 'cygpath' to convert the Windows paths to Cygwin" + echo " paths" + echo " --help" + echo " Shows this message and exits" + exit 1 +} + +dodep () +{ + unset fullpath + if [ -z "$altpath" ]; then + if [ -r $1 ]; then + fullpath=$1 + else + echo "# ERROR: No readable file at $1" + show_usage + fi + else + for path in $altpath; do + tmppath=$path/$1 + if [ -r $tmppath ]; then + fullpath=$tmppath + break; + fi + done + if [ -z "$fullpath" ]; then + echo "# ERROR: No readable file for $1 found at any location" + show_usage + fi + fi + + $cc -M $cflags $fullpath || \ + ( echo "# ERROR: $cc -M $cflags $fullpath FAILED"; exit 4; ) +} + +unset cc +unset cflags +unset files +unset args +unset altpath +winpaths=n +unset topdir + +# Accumulate CFLAGS up to "--" +progname=$0 +while [ ! -z "$1" ]; do + case $1 in + -- ) + cc=$cflags + cflags=$args + args= + ;; + --dep-debug ) + if [ -z "$args" ]; then + set -x + else + args="$args $1" + fi + ;; + --dep-path ) + if [ -z "$args" ]; then + shift + altpath="$altpath $1" + else + args="$args $1" + fi + ;; + --winpaths ) + if [ -z "$args" ]; then + shift + winpaths=y + topdir=$1 + else + args="$args $1" + fi + ;; + --help ) + show_usage + ;; + *) + args="$args $1" + ;; + esac + shift +done +files=$args + +if [ -z "$cc" ]; then + echo "ERROR: No compiler specified" + show_usage + exit 1 +fi + +if [ -z "$files" ]; then + # Don't report an error -- this happens normally in some configurations + echo "# No files specified for dependency generataion" + exit 0 +fi + +# Check if this compiler generates Cygwin/Linux paths or Windows paths + +if [ "X${winpaths}" = "Xy" ]; then + # We will have to parse and modify each dependency (yech) + # Make sure a valid TOPDIR argument was provided + + if [ -z "$topdir" -o ! -d $topdir ]; then + echo " not specified or does not exist: $topdir" + show_usage + exit 1 + fi + + # Get the top dir expressed like the Windows GCC would use it, except + # with forward slashs + + wtopdir=`cygpath -w ${topdir} | sed -e "s,\\\\\\,/,g"` + + # Then get the dependency and perform conversions on it to make it + # palatable to the Cygwin make. This is probably not sufficiently + # general to work on all platforms (like if your disk is not C:). + + for file in $files ; do + dodep $file | sed -e "s,\\\,/,g" -e "s,${wtopdir},${topdir},g" \ + -e "s,/ ,\\\ ,g" -e "s,c:/,/cygdrive/c/,g" \ + -e "s,/$,\\\,g" + done +else + # For normal Cygwin/Linux GCC, the dependency paths are in the + # correct form and can simply be echoed on stdout + + for file in $files ; do + dodep $file + done +fi + diff --git a/nuttx/tools/mkexport.sh b/nuttx/tools/mkexport.sh new file mode 100755 index 0000000000..7ddeae6993 --- /dev/null +++ b/nuttx/tools/mkexport.sh @@ -0,0 +1,327 @@ +#!/bin/bash +# tools/mkexport.sh +# +# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# TODO: +# 1. This script assumes the host archiver ar may not be appropriate for +# non-GCC toolchains +# 2. For the kernel build, the user libriars should be built into some +# libuser.a. The list of user libraries would have to accepted with +# some new argument, perhaps -u. + +# Get the input parameter list + +USAGE="USAGE: $0 [-d] [-z] [-w|wy|wn] -t [-x ] -l \"lib1 [lib2 [lib3 ...]]\"" +unset TOPDIR +unset LIBLIST +unset TGZ +WINTOOL=n +LIBEXT=.a + +while [ ! -z "$1" ]; do + case $1 in + -d ) + set -x + ;; + -l ) + shift + LIBLIST=$1 + ;; + -wy ) + WINTOOL=y + ;; + -w | -wn ) + WINTOOL=n + ;; + -t ) + shift + TOPDIR=$1 + ;; + -x ) + shift + LIBEXT=$1 + ;; + -z ) + TGZ=y + ;; + -h ) + echo $USAGE + exit 0 + ;; + * ) + echo "Unrecognized argument: $1" + echo $USAGE + exit 1 + ;; + esac + shift +done + +# Check arguments + +if [ -z "${TOPDIR}" -o -z "${LIBLIST}" ]; then + echo "MK: Missing required arguments" + echo $USAGE + exit 1 +fi + +if [ ! -d "${TOPDIR}" ]; then + echo "MK: Directory ${TOPDIR} does not exist" + exit 1 +fi + +# Get the version string + +if [ ! -f "${TOPDIR}/.version" ]; then + echo "MK: File ${TOPDIR}/.version does not exist" + exit 1 +fi + +source "${TOPDIR}/.version" +if [ ! -z "${CONFIG_VERSION_STRING}" -a "${CONFIG_VERSION_STRING}" != "0.0" ]; then + VERSION="-${CONFIG_VERSION_STRING}" +fi + +# Create the export directory + +EXPORTSUBDIR="nuttx-export${VERSION}" +EXPORTDIR="${TOPDIR}/${EXPORTSUBDIR}" + +# If the export directory already exists, then remove it and create a new one + +if [ -d "${EXPORTDIR}" ]; then + echo "MK: Removing old export directory" + rm -rf "${EXPORTDIR}" +fi + +# Remove any possible previous results + +rm -f "${EXPORTDIR}.tar" +rm -f "${EXPORTDIR}.zip" +rm -f "${EXPORTDIR}.tar.gz" + +# Create the export directory and some of its subdirectories + +mkdir "${EXPORTDIR}" || { echo "MK: 'mkdir ${EXPORTDIR}' failed"; exit 1; } +mkdir "${EXPORTDIR}/startup" || { echo "MK: 'mkdir ${EXPORTDIR}/startup' failed"; exit 1; } +mkdir "${EXPORTDIR}/libs" || { echo "MK: 'mkdir ${EXPORTDIR}/libs' failed"; exit 1; } +mkdir "${EXPORTDIR}/build" || { echo "MK: 'mkdir ${EXPORTDIR}/build' failed"; exit 1; } +mkdir "${EXPORTDIR}/arch" || { echo "MK: 'mkdir ${EXPORTDIR}/arch' failed"; exit 1; } + +# Verify that we have a Make.defs file. + +if [ ! -f "${TOPDIR}/Make.defs" ]; then + echo "MK: Directory ${TOPDIR}/Make.defs does not exist" + exit 1 +fi + +# Copy the Make.defs files, but disable windows path conversions + +grep -v "WINTOOL[ \t]*=[ \t]y" "${TOPDIR}/Make.defs" > "${EXPORTDIR}/Make.defs" + +# Extract information from the Make.defs file. A Makefile can do this best + +make -C "${TOPDIR}/tools" -f Makefile.export TOPDIR="${TOPDIR}" EXPORTDIR="${EXPORTDIR}" +source "${EXPORTDIR}/makeinfo.sh" +rm -f "${EXPORTDIR}/makeinfo.sh" +rm -f "${EXPORTDIR}/Make.defs" + +# Verify the build info that we got from makeinfo.sh + +if [ ! -d "${ARCHDIR}" ]; then + echo "MK: Directory ${ARCHDIR} does not exist" + exit 1 +fi + +# Is there a linker script in this configuration? + +if [ ! -z "${LDPATH}" ]; then + + # Apparently so. Verify that the script exists + + if [ ! -f "${LDPATH}" ]; then + echo "MK: File ${LDPATH} does not exist" + exit 1 + fi + + # Copy the linker script + + cp -p "${LDPATH}" "${EXPORTDIR}/build/." || \ + { echo "MK: cp ${LDPATH} failed"; exit 1; } +fi + +# Save the compilation options + +echo "ARCHCFLAGS = ${ARCHCFLAGS}" >"${EXPORTDIR}/build/Make.defs" +echo "ARCHCXXFLAGS = ${ARCHCXXFLAGS}" >>"${EXPORTDIR}/build/Make.defs" + +# Copy the NuttX include directory (retaining attributes and following symbolic links) + +cp -LR -p "${TOPDIR}/include" "${EXPORTDIR}/." || \ + { echo "MK: 'cp ${TOPDIR}/include' failed"; exit 1; } +find "${EXPORTDIR}/include" -name .svn | xargs rm -rf + +# Copy the startup object file(s) + +make -C ${ARCHDIR} export_head TOPDIR=${TOPDIR} EXPORT_DIR="${EXPORTDIR}" + +# Copy architecture-specific header files into the arch export sub-directory. +# This is tricky because each architecture does things in a little different +# way. +# +# First copy any header files in the architecture src/ sub-directory (some +# architectures keep all of the header files there, some a few, and others +# none + +cp -f "${ARCHDIR}"/*.h "${EXPORTDIR}"/arch/. 2>/dev/null + +# Then look a list of possible places where other architecture-specific +# header files might be found. If those places exist (as directories or +# as symbolic links to directories, then copy the header files from +# those directories into the EXPORTDIR + +ARCH_HDRDIRS="arm armv7-m avr avr32 board common chip mips32" +for hdir in $ARCH_HDRDIRS; do + + # Does the directory (or symbolic link) exist? + + if [ -d "${ARCHDIR}/${hdir}" -o -h "${ARCHDIR}/${hdir}" ]; then + + # Yes.. create a export sub-directory of the same name + + mkdir "${EXPORTDIR}/arch/${hdir}" || \ + { echo "MK: 'mkdir ${EXPORTDIR}/arch/${hdir}' failed"; exit 1; } + + # Then copy the header files (only) into the new directory + + cp -f "${ARCHDIR}"/${hdir}/*.h "${EXPORTDIR}"/arch/${hdir}/. 2>/dev/null + + # One architecture has low directory called "chip" that holds the + # header files + + if [ -d "${ARCHDIR}/${hdir}/chip" ]; then + + # Yes.. create a export sub-directory of the same name + + mkdir "${EXPORTDIR}/arch/${hdir}/chip" || \ + { echo "MK: 'mkdir ${EXPORTDIR}/arch/${hdir}/chip' failed"; exit 1; } + + # Then copy the header files (only) into the new directory + + cp -f "${ARCHDIR}"/${hdir}/chip/*.h "${EXPORTDIR}"/arch/${hdir}/chip/. 2>/dev/null + fi + fi +done + +# Copy OS internal header files as well. They are used by some architecture- +# specific header files. + +mkdir "${EXPORTDIR}/arch/os" || \ + { echo "MK: 'mkdir ${EXPORTDIR}/arch/${hdir}/chip' failed"; exit 1; } +cp -f "${TOPDIR}"/sched/*.h "${EXPORTDIR}"/arch/os/. 2>/dev/null + +# Add the board library to the list of libraries + +if [ -f "${ARCHDIR}/board/libboard${LIBEXT}" ]; then + LIBLIST="${LIBLIST} ${ARCHSUBDIR}/board/libboard${LIBEXT}" +fi + +# Then process each library + +AR=${CROSSDEV}ar +for lib in ${LIBLIST}; do + if [ ! -f "${TOPDIR}/${lib}" ]; then + echo "MK: Library ${TOPDIR}/${lib} does not exist" + exit 1 + fi + + # Get some shorter names for the library + + libname=`basename ${lib} ${LIBEXT}` + shortname=`echo ${libname} | sed -e "s/^lib//g"` + + # Copy the application library unmodified + + if [ "X${libname}" = "Xlibapps" ]; then + cp -p "${TOPDIR}/${lib}" "${EXPORTDIR}/libs/." || \ + { echo "MK: cp ${TOPDIR}/${lib} failed"; exit 1; } + else + + # Create a temporary directory and extract all of the objects there + # Hmmm.. this probably won't work if the archiver is not 'ar' + + mkdir "${EXPORTDIR}/tmp" || \ + { echo "MK: 'mkdir ${EXPORTDIR}/tmp' failed"; exit 1; } + cd "${EXPORTDIR}/tmp" || \ + { echo "MK: 'cd ${EXPORTDIR}/tmp' failed"; exit 1; } + if [ "X${WINTOOL}" = "Xy" ]; then + WLIB=`cygpath -w "${TOPDIR}/${lib}"` + ${AR} x "${WLIB}" + else + ${AR} x "${TOPDIR}/${lib}" + fi + + # Rename each object file (to avoid collision when they are combined) + # and add the file to libnuttx + + for file in `ls`; do + mv "${file}" "${shortname}-${file}" + if [ "X${WINTOOL}" = "Xy" ]; then + WLIB=`cygpath -w "${EXPORTDIR}/libs/libnuttx${LIBEXT}"` + ${AR} rcs "${WLIB}" "${shortname}-${file}" + else + ${AR} rcs "${EXPORTDIR}/libs/libnuttx${LIBEXT}" "${shortname}-${file}" + fi + done + + cd "${TOPDIR}" || \ + { echo "MK: 'cd ${TOPDIR}' failed"; exit 1; } + rm -rf "${EXPORTDIR}/tmp" + fi +done + +# Now tar up the whole export directory + +cd "${TOPDIR}" || \ + { echo "MK: 'cd ${TOPDIR}' failed"; exit 1; } + +if [ "X${TGZ}" = "Xy" ]; then + tar cvf "${EXPORTSUBDIR}.tar" "${EXPORTSUBDIR}" 1>/dev/null 2>&1 + gzip -f "${EXPORTSUBDIR}.tar" +else + zip -r "${EXPORTSUBDIR}.zip" "${EXPORTSUBDIR}" 1>/dev/null 2>&1 +fi + +# Clean up after ourselves + +rm -rf "${EXPORTSUBDIR}" diff --git a/nuttx/tools/mkimage.sh b/nuttx/tools/mkimage.sh new file mode 100755 index 0000000000..f64dfde854 --- /dev/null +++ b/nuttx/tools/mkimage.sh @@ -0,0 +1,289 @@ +#!/bin/bash +# +# File: mkimage.sh +# +# Copyright (C) 2002 RidgeRun, Inc. +# Author: RidgeRun, Inc +# - Adapted for the Cadenux environment, 9-6-02, Gregory Nutt +# - Added --EAddr option, 6-18-03, Gregory Nutt +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 675 Mass Ave, Cambridge, MA 02139, USA. +# +######################################################## +# Description: +# ----------- +# Scenario #1 +# ----------- +# This utility was developed by RidgeRun for the +# purpose of converting a standard binary executable +# image (such as ELF) into a special format (RR +# format) suitable for quick downloads to the target +# TI925 RidgeRun Bootloader (rrload). The image is +# produced by constructing a special header which is +# then tacked onto the front of the supplied binary +# image. The resulting binary image is smaller than +# what would normally be encountered with traditional +# download formats (such as SREC or uuencoded; both +# ascii based). The special header at the front of the +# image is used to guide the target's rrload (a +# booloader developed by RidgeRun Inc). The header +# data contains a field representing the total byte +# count of the binary data following the header as +# well as a field that indicates the load address of +# run image. Additionally, a field exists in the +# header which indicates the image's entry point which +# could be called by the bootloader to invoked the +# just downloaded program. +# ----------- +# Scenario #2 +# ----------- +# If the supplied image is not a standard binary +# executagle image then that is ok too, a header is +# constructed and tacked onto the front of the supplied +# binary data forming the new binary image (in rr format). +# In this case the EntryAddr is set to 0xFFFFFFFF by +# default and the LoadAddr is set to 0x00000000 by +# default unless otherwise indicated by command line +# arguments -LEntry and -LAddr which if used are assumed +# to be in hexidecimal units. +# +# ----------- +# Scenario #3 +# ----------- +# +# Read/Write file system (like JFFS) that will not +# work if rrload stores a 20 byte header at the beginning +# of the flashed component image +# +# mkimage [--NoHeader ] +# +# Usage: +# mkimage [--LAddr h] [--EAddr h] [--NoHeader] +# +# Examples: +# $ mkimage linux linux.rr +# ..or.. +# $ mkimage -LAddr 10008000 -EAddr 10008000 vmlinux vmlinux.rr +# ..or.. +# $ mkimage --NoHeader fileSys.gz fileSys.gz.rr +# ..or.. +# $ mkimage --LAddr A00 fileSys.gz fileSys.gz.rr +# ..or.. +# $ mkimage --LAddr A00 fileSys.gz fileSys.gz.rr +# ^ +# | +# Assumed hex units. +# Please omit the +# leading "0x". +######################################################## + +if [ $# -lt 2 ] ; then + echo "Error: missing argument" + echo "Usage: mkimage [--Prefix prefix] [--LAddr n] [--EAddr n] [--NoHeader] " + exit 1 +fi + +# Pleae Note the following formatting inconsistency. +# (Sorry, for now this is necessary) +LoadAddr="00000000" # Note: hex val *without* proceeding "0x" +EntryAddr="0xFFFFFFFF" # Note: hex val *with* procedding "0x" + +unset prefix +Header="y" +LAddrSupplied="n" +EAddrSupplied="n" +compress="n" + +while [ $# -gt 0 ] ; do + case "$1" in + --Prefix) + shift; + prefix="$1" + shift + ;; + --LAddr ) + shift + LoadAddr="$1" + # Next, make the supplied LAddr exactly 8 hex chars long. + LoadAddr="0000000${LoadAddr}" + LoadAddr=$(echo $LoadAddr | sed -e "s/^.*\(........\)$/\1/g") + LAddrSupplied="y" + shift + ;; + --EAddr ) + shift + EntryAddr="$1" + # Next, make the supplied LEntry exactly 8 hex chars long. + EntryAddr="0000000${EntryAddr}" + EntryAddr=$(echo $EntryAddr | sed -e "s/^.*\(........\)$/\1/g") + EntryAddr=0x$EntryAddr + EAddrSupplied="y" + shift + ;; + --NoHeader ) + Header="n" + shift + ;; + --compress ) + compress="y" + shift + ;; + *) + break + ;; + esac +done + +if [ ! $# -eq 2 ] ; then + echo "Error: invalid argument set." + echo "Usage: mkimage [--LAddr h] " + exit 1 +fi + +binary=$1.stripped +outbin=$2 + +cp $1 $binary +FileTypeExec=$(${prefix}objdump -f $binary 2>/dev/null | egrep "EXEC_P") + +if [ ! -z "$FileTypeExec" ] ; then + + # ----------- + # Scenario #1 + # ----------- + # We have an executable style binary (like ELF, etc). + # So... + # --------------------------------- + # Next | Create the binary image data. + # --------------------------------- + ${prefix}strip ${binary} + ${prefix}objcopy -S -O binary $binary ${binary}.binary + # --------------------------------- + # Next | Create compress image if requested + # --------------------------------- + image_file=${binary}.binary + if [ "$compress" = "y" ] ; then + gzip -f -9 -c ${binary}.binary > ${binary}.binary.gz + image_file=${binary}.binary.gz + fi + # --------------------------------- + # Next | Create the header information (ascii) needed + # | by the TI925 bootloader. This includes the + # | load address, entry address and byte count of + # | the binary executable data which will follow it. + # --------------------------------- + if [ "$LAddrSupplied" = "n" ] ; then + # Next, Since LoadAddr not already supplied by user we'll + # derive it by consulting the binary executable file. + LoadAddr=$(${prefix}objdump -h ${binary} | grep " 0 \.") + LoadAddr=$(echo $LoadAddr | cut -d' ' -f4) # eight hex chars + fi + if [ "$EAddrSupplied" = "n" ] ; then + # Next, Since EntryAddr not already supplied by user we'll + # derive it by consulting the binary executable file. + EntryAddr=$(${prefix}objdump -f ${binary} | grep -i "start") + EntryAddr=$(echo $EntryAddr | cut -d' ' -f3) # eight hex chars + fi + # Next, Compute byte length of binary portion. + numBytes=$(wc --bytes $image_file) + numBytes=$(echo $numBytes | cut -d' ' -f1) + numBytes=$(echo 16o $numBytes p | dc) # converts to hex. + # Next, make the numBytes string exactly 8 hex chars long. + numBytes="0000000${numBytes}" + numBytes=$(echo $numBytes | sed -e "s/^.*\(........\)$/\1/g") + # --------------------------------- + # Next | Combine the ascii header information + # | with the binary image to make the + # | final downloadable *mostly* binary + # | image. + # --------------------------------- + rm -f ${outbin} + echo ">LoadAddr :0x${LoadAddr}" >> ${outbin} + if [ "${Header}" = "y" ]; then + echo ">EntryAddr:${EntryAddr}" >> ${outbin} + else + echo ">NoHeader" >> ${outbin} + fi + echo ">NumBytes :0x${numBytes}" >> ${outbin} + cat $image_file >> ${outbin} + # --------------------------------- + # Cleanup and exit + # --------------------------------- + rm -f ${binary}.binary $image_file + exit 0 + +else + + # ----------- + # Scenario #2 + # ----------- + # Just a binary image but not a standard executable + # style binary (like ELF, etc). Might be a compressed + # filesystem image, etc. + # So... + # --------------------------------- + # Next | Create the header information (ascii) needed + # | by the TI925 bootloader. This includes the + # | load address, entry address and byte count of + # | the binary file which will follow it. + # --------------------------------- + # | Create compress image if requested + # --------------------------------- + # + image_file=${binary} + if [ "$compress" = "y" ] ; then + gzip -f -9 -c ${image_file} > ${image_file}.gz + image_file=${image_file}.gz + fi + # + # Note: The LoadAddr and EntryAddr are already established + # for us at this point, but we will need to compute the + # byte length of binary portion next. + # + numBytes=$(wc --bytes ${image_file}) + numBytes=$(echo $numBytes | cut -d' ' -f1) + numBytes=$(echo 16o $numBytes p | dc) # converts to hex. + # Next, make the numBytes string exactly 8 hex chars long. + numBytes="0000000${numBytes}" + numBytes=$(echo $numBytes | sed -e "s/^.*\(........\)$/\1/g") + # + # --------------------------------- + # Next | Combine the ascii header information + # | with the binary image to make the + # | final downloadable *mostly* binary + # | image. + # --------------------------------- + # + rm -f ${outbin} + echo ">LoadAddr :0x${LoadAddr}" >> ${outbin} + if [ ${Header} = "y" ]; then + echo ">EntryAddr:${EntryAddr}" >> ${outbin} + else + echo ">NoHeader" >> ${outbin} + fi + echo ">NumBytes :0x${numBytes}" >> ${outbin} + cat ${image_file} >> ${outbin} + # --------------------------------- + # Cleanup and exit + # --------------------------------- + rm -f ${image_file}.gz + exit 0 +fi diff --git a/nuttx/tools/mknulldeps.sh b/nuttx/tools/mknulldeps.sh new file mode 100755 index 0000000000..6dc3e9635b --- /dev/null +++ b/nuttx/tools/mknulldeps.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# tools/mknulldeps.sh +# +# Copyright (C) 2008 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +echo "# The selected toolchain does not support dependency generation" \ No newline at end of file diff --git a/nuttx/tools/mkromfsimg.sh b/nuttx/tools/mkromfsimg.sh new file mode 100755 index 0000000000..b628d24196 --- /dev/null +++ b/nuttx/tools/mkromfsimg.sh @@ -0,0 +1,261 @@ +#!/bin/bash +############################################################################ +# tools/mkromfsimg.sh +# +# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Environmental stuff + +wd=`pwd` +workingdir=$wd/img +rcsfile=rcS +rcstemplate=$rcsfile.template +romfsimg=romfs.img +headerfile=nsh_romfsimg.h + +# Get the input parameters + +topdir=$1 +usage="USAGE: $0 " + +if [ -z "$topdir" -o ! -d "$topdir" ]; then + echo "The full path to the NuttX base directory must be provided on the command line" + echo $usage + exit 1 +fi + +# Extract all values from the .config in the $topdir that contains all of the NuttX +# configuration settings. The .config file was intended to be include-able by makefiles +# and source-able by scripts. Unfortunately,there are too many syntactic differents +# to make that practical + +if [ ! -r $topdir/.config ]; then + echo "No readable file at $topdir/.config" + echo "Has NuttX been configured?" + exit 1 +fi + +romfsetc=`grep CONFIG_NSH_ROMFSETC= $topdir/.config | cut -d'=' -f2` +disablempt=`grep CONFIG_DISABLE_MOUNTPOINT= $topdir/.config | cut -d'=' -f2` +disablescript=`grep CONFIG_NSH_DISABLESCRIPT= $topdir/.config | cut -d'=' -f2` +ndescriptors=`grep CONFIG_NFILE_DESCRIPTORS= $topdir/.config | cut -d'=' -f2` +devconsole=`grep CONFIG_DEV_CONSOLE= $topdir/.config | cut -d'=' -f2` +romfs=`grep CONFIG_FS_ROMFS= $topdir/.config | cut -d'=' -f2` +romfsmpt=`grep CONFIG_NSH_ROMFSMOUNTPT= $topdir/.config | cut -d'=' -f2` +initscript=`grep CONFIG_NSH_INITSCRIPT= $topdir/.config | cut -d'=' -f2` +romfsdevno=`grep CONFIG_NSH_ROMFSDEVNO= $topdir/.config | cut -d'=' -f2` +romfssectsize=`grep CONFIG_NSH_ROMFSSECTSIZE= $topdir/.config | cut -d'=' -f2` +fatfs=`grep CONFIG_FS_FAT= $topdir/.config | cut -d'=' -f2` +fatdevno=`grep CONFIG_NSH_FATDEVNO= $topdir/.config | cut -d'=' -f2` +fatsectsize=`grep CONFIG_NSH_FATSECTSIZE= $topdir/.config | cut -d'=' -f2` +fatnsectors=`grep CONFIG_NSH_FATNSECTORS= $topdir/.config | cut -d'=' -f2` +fatmpt=`grep CONFIG_NSH_FATMOUNTPT= $topdir/.config | cut -d'=' -f2` + +# The following settings are required for general ROMFS support +# +# Mountpoint support must be enabled + +if [ "X$disablempt" = "Xy" ]; then + echo "Mountpoint support is required for this feature" + echo "Set CONFIG_DISABLE_MOUNTPOINT=n to continue" + exit 1 +fi + +# Scripting support must be enabled + +if [ "X$disablescript" = "Xy" ]; then + echo "NSH scripting support is required for this feature" + echo "Set CONFIG_NSH_DISABLESCRIPT=n to continue" + exit 1 +fi + +# We need at least 2 file descriptors 1 for the ROMFS mount and one for +# FAT mount performed in rcS. That still wouldn't be enough to to do much +# with NSH + +if [ -z "$ndescriptors" -o "$ndescriptors" -lt 2 ]; then + echo "No file descriptors have been allocated" + if [ "X$devconsole" = "Xy" ]; then + echo "Set CONFIG_NFILE_DESCRIPTORS to value greater than 4" + else + echo "Set CONFIG_NFILE_DESCRIPTORS to value greater than 1" + fi + exit 1 +fi + +# If a console is enabled, then three more file descriptors are required +# for stdin, stdout, and stderr + +if [ "X$devconsole" = "Xy" -a "$ndescriptors" -lt 5 ]; then + echo "Insufficient file descriptors have been allocated" + echo "Set CONFIG_NFILE_DESCRIPTORS to value greater than 4" +fi + +# ROMFS support is required, of course + +if [ "X$romfs" != "Xy" ]; then + echo "ROMFS support is disabled in the NuttX configuration" + echo "Set CONFIG_FS_ROMFS=y to continue" + exit 0 +fi + +# The options in the default rcS.template also require FAT FS support + +if [ "X$fatfs" != "Xy" ]; then + echo "FAT FS support is disabled in the NuttX configuration" + echo "Set CONFIG_FS_FAT=y to continue" + exit 0 +fi + +# Verify that genromfs has been installed + +genromfs -h 1>/dev/null 2>&1 || { \ + echo "Host executable genromfs not available in PATH"; \ + echo "You may need to download in from http://romfs.sourceforge.net/"; \ + exit 1; \ +} + +# Supply defaults for all un-defined ROMFS settings + +if [ -z "$romfsmpt" ]; then + romfsmpt="/etc" +fi +if [ -z "$initscript" ]; then + initscript="init.d/rcS" +fi +if [ -z "$romfsdevno" ]; then + romfsdevno=0 +fi +if [ -z "$romfssectsize" ]; then + romfssectsize=64 +fi + +# Supply defaults for all un-defined FAT FS settings + +if [ -z "$fatdevno" ]; then + fatdevno=1 +fi +if [ -z "$fatsectsize" ]; then + fatsectsize=512 +fi +if [ -z "$fatnsectors" ]; then + fatnsectors=1024 +fi +if [ -z "$fatmpt" ]; then + fatmpt="/tmp" +fi + +# Verify the mountpoint. Verify that it is an absolute path but not /, /dev, +# /., /./*, /.., or /../* + +if [ ${romfsmpt:0:1} != "\"" ]; then + echo "CONFIG_NSH_ROMFSMOUNTPT must be a string" + echo "Change it so that it is enclosed in quotes." + exit 1 +fi + +uromfsmpt=`echo $romfsmpt | sed -e "s/\"//g"` + +if [ ${uromfsmpt:0:1} != "/" ]; then + echo "CONFIG_NSH_ROMFSMOUNTPT must be an absolute path in the target FS" + echo "Change it so that it begins with the character '/'. Eg. /etc" + exit 1 +fi + +tmpdir=$uromfsmpt +while [ ${tmpdir:0:1} == "/" ]; do + tmpdir=${tmpdir:1} +done + +if [ -z "$tmpdir" -o "X$tmpdir" = "Xdev" -o "X$tmpdir" = "." -o \ + ${tmpdir:0:2} = "./" -o "X$tmpdir" = ".." -o ${tmpdir:0:3} = "../" ]; then + echo "Invalid CONFIG_NSH_ROMFSMOUNTPT selection." + exit 1 +fi + +# Verify that the path to the init file is a relative path and not ., ./*, .., or ../* + +if [ ${initscript:0:1} != "\"" ]; then + echo "CONFIG_NSH_INITSCRIPT must be a string" + echo "Change it so that it is enclosed in quotes." + exit 1 +fi + +uinitscript=`echo $initscript | sed -e "s/\"//g"` + +if [ ${uinitscript:0:1} == "/" ]; then + echo "CONFIG_NSH_INITSCRIPT must be an relative path in under $romfsmpt" + echo "Change it so that it begins with the character '/'. Eg. init.d/rcS. " + exit 1 +fi + +if [ "X$uinitscript" = "." -o ${uinitscript:0:2} = "./" -o \ + "X$uinitscript" = ".." -o ${uinitscript:0:3} = "../" ]; then + echo "Invalid CONFIG_NSH_INITSCRIPT selection. Must not begin with . or .." + exit 1 +fi + +# Create a working directory + +rm -rf $workingdir || { echo "Failed to remove the old $workingdir"; exit 1; } +mkdir -p $workingdir || { echo "Failed to created the new $workingdir"; exit 1; } + +# Create the rcS file from the rcS.template + +if [ ! -r $rcstemplate ]; then + echo "$rcstemplete does not exist" + rmdir $workingdir + exit 1 +fi + +cat $rcstemplate | \ + sed -e "s,XXXMKRDMINORXXX,$fatdevno,g" | \ + sed -e "s,XXMKRDSECTORSIZEXXX,$fatsectsize,g" | \ + sed -e "s,XXMKRDBLOCKSXXX,$fatnsectors,g" | \ + sed -e "s,XXXRDMOUNTPOUNTXXX,$fatmpt,g" >$rcsfile + +# And install it at the specified relative location + +install -D --mode=0755 $rcsfile $workingdir/$uinitscript || \ + { echo "Failed to install $rcsfile at $workingdir/$uinitscript"; rm -f $rcsfile; exit 1; } +rm -f $rcsfile + +# Now we are ready to make the ROMFS image + +genromfs -f $romfsimg -d $workingdir -V "NSHInitVol" || { echo "genromfs failed" ; exit 1 ; } +rm -rf $workingdir || { echo "Failed to remove the old $workingdir"; exit 1; } + +# And, finally, create the header file + +xxd -i $romfsimg >$headerfile || { echo "xxd of $< failed" ; rm -f $romfsimg; exit 1 ; } +rm -f $romfsimg diff --git a/nuttx/tools/mksyscall.c b/nuttx/tools/mksyscall.c new file mode 100644 index 0000000000..a8f2cf99b7 --- /dev/null +++ b/nuttx/tools/mksyscall.c @@ -0,0 +1,831 @@ +/**************************************************************************** + * tools/mksyscall.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define LINESIZE (PATH_MAX > 256 ? PATH_MAX : 256) + +#define MAX_FIELDS 16 +#define MAX_PARMSIZE 128 +#define NAME_INDEX 0 +#define HEADER_INDEX 1 +#define COND_INDEX 2 +#define RETTYPE_INDEX 3 +#define PARM1_INDEX 4 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static bool g_debug; +static bool g_inline; +static char g_line[LINESIZE+1]; +static char g_parm[MAX_FIELDS][MAX_PARMSIZE]; +static FILE *g_stubstream; +static int g_lineno; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static char *skip_space(char *ptr) +{ + while (*ptr && isspace(*ptr)) ptr++; + return ptr; +} + +static char *read_line(FILE *stream) +{ + char *ptr; + + for (;;) + { + g_line[LINESIZE] = '\0'; + if (!fgets(g_line, LINESIZE, stream)) + { + return NULL; + } + else + { + g_lineno++; + if (g_debug) + { + printf("Line: %s\n", g_line); + } + + ptr = skip_space(g_line); + if (*ptr && *ptr != '#' && *ptr != '\n') + { + return ptr; + } + } + } +} + +static char *copy_parm(char *src, char *dest) +{ + char *start = src; + int i; + + for (i = 0; i < MAX_PARMSIZE; i++) + { + if (*src == '"') + { + *dest = '\0'; + return src; + } + else if (*src == '\n' || *src == '\0') + { + fprintf(stderr, "%d: Unexpected end of line: \"%s\"\n", g_lineno, start); + exit(4); + } + else + { + *dest++ = *src++; + } + } + + fprintf(stderr, "%d: Parameter too long: \"%s\"\n", g_lineno, start); + exit(3); +} + +static char *find_parm(char *ptr) +{ + char *start = ptr; + + if (*ptr != '"') + { + fprintf(stderr, "%d: I'm confused: \"%s\"\n", g_lineno, start); + exit(5); + } + ptr++; + + ptr = skip_space(ptr); + if (*ptr == '\n' || *ptr == '\0') + { + return NULL; + } + else if (*ptr != ',') + { + fprintf(stderr, "%d: Expected ',': \"%s\"\n", g_lineno, start); + exit(6); + } + ptr++; + + ptr = skip_space(ptr); + if (*ptr != '"') + { + fprintf(stderr, "%d: Expected \": \"%s\"\n", g_lineno, start); + exit(7); + } + ptr++; + + return ptr; +} + +static int parse_csvline(char *ptr) +{ + int nparms; + int i; + + /* Format "arg1","arg2","arg3",... Spaces will be tolerated outside of the + * quotes. Any initial spaces have already been skipped so the first thing + * should be '"'. + */ + + if (*ptr != '"') + { + fprintf(stderr, "%d: Bad line: \"%s\"\n", g_lineno, g_line); + exit(2); + } + + ptr++; + nparms = 0; + + do + { + ptr = copy_parm(ptr, &g_parm[nparms][0]); + nparms++; + ptr = find_parm(ptr); + } + while (ptr); + + if (g_debug) + { + printf("Parameters: %d\n", nparms); + for (i = 0; i < nparms; i++) + { + printf(" Parm%d: \"%s\"\n", i+1, g_parm[i]); + } + } + return nparms; +} + +static bool is_vararg(const char *type, int index, int nparms) +{ + if (strcmp(type,"...") == 0) + { + if (index != (nparms-1)) + { + fprintf(stderr, "%d: ... is not the last in the argument list\n", g_lineno); + exit(11); + } + else if (nparms < 2) + { + fprintf(stderr, "%d: Need one parameter before ...\n", g_lineno); + exit(14); + } + return true; + } + return false; +} + +static bool is_union(const char *type) +{ + return (strncmp(type,"union", 5) == 0); +} + +static const char *check_funcptr(const char *type) +{ + const char *str = strstr(type,"(*)"); + if (str) + { + return str + 2; + } + return NULL; +} + +static const char *check_array(const char *type) +{ + const char *str = strchr(type, '['); + if (str) + { + return str; + } + return NULL; +} + +static void print_formalparm(FILE *stream, const char *argtype, int parmno) +{ + const char *part2; + int len; + + /* Function pointers and array formal parameter types are a little more work */ + + if ((part2 = check_funcptr(argtype)) != NULL || (part2 = check_array(argtype)) != NULL) + { + len = part2 - argtype; + (void)fwrite(argtype, 1, len, stream); + fprintf(stream, "parm%d%s", parmno, part2); + } + else + { + fprintf(stream, "%s parm%d", argtype, parmno); + } +} + +static void get_formalparmtype(const char *arg, char *formal) +{ + /* The formal parm type is a pointer to everything up to the first'|' (or + * the end of the string if there is no '|' in the type description). + */ + + while (*arg != '|' && *arg != '\0') + { + *formal++ = *arg++; + } + *formal = '\0'; +} + +static void get_actualparmtype(const char *arg, char *actual) +{ + const char *pstart = strchr(arg,'|'); + if (pstart) + { + /* The actual parameter type starts after the '|' */ + + pstart++; + } + else + { + /* The actual parameter is the same as the formal parameter + * at starts at the beginning of the type string. + */ + + pstart = arg; + } + + /* The actual parm type is a pointer to everything up to the next '|' (or + * the end of the string if there is no '|' in the type description). + */ + + while (*pstart != '|' && *pstart != '\0') + { + *actual++ = *pstart++; + } + *actual = '\0'; +} + +static void get_fieldname(const char *arg, char *fieldname) +{ + char *pactual = strchr(arg,'|'); + char *pstart; + + if (pactual) + { + /* The actual parameter type starts after the '|' */ + + pactual++; + pstart = strchr(pactual,'|'); + if (pstart) + { + /* The fieldname is everything past the second '|' to the end of the string */ + + pstart++; + strncpy(fieldname, pstart, MAX_PARMSIZE); + return; + } + } + + fprintf(stderr, "%d: Missing union fieldname: %s\n", g_lineno, arg); + exit(15); +} + +static FILE *open_proxy(void) +{ + char filename[MAX_PARMSIZE+10]; + FILE *stream; + + snprintf(filename, MAX_PARMSIZE+9, "PROXY_%s.c", g_parm[NAME_INDEX]); + filename[MAX_PARMSIZE+9] = '\0'; + + stream = fopen(filename, "w"); + if (stream == NULL) + { + fprintf(stderr, "Failed to open %s: %s\n", filename, strerror(errno)); + exit(10); + } + return stream; +} + +static void generate_proxy(int nparms) +{ + FILE *stream = open_proxy(); + char formal[MAX_PARMSIZE]; + char fieldname[MAX_PARMSIZE]; + bool bvarargs = false; + int nformal; + int nactual; + int i; + + /* Generate "up-front" information, include correct header files */ + + fprintf(stream, "/* Auto-generated %s proxy file -- do not edit */\n\n", g_parm[NAME_INDEX]); + fprintf(stream, "#include \n"); + + /* Does this function have a variable number of parameters? If so then the + * final parameter type will be encoded as "..." + */ + + if (is_vararg(g_parm[PARM1_INDEX+nparms-1], nparms-1, nparms)) + { + nformal = nparms-1; + bvarargs = true; + fprintf(stream, "#include \n"); + } + else + { + nformal = nparms; + } + + fprintf(stream, "#include <%s>\n", g_parm[HEADER_INDEX]); + fprintf(stream, "#include \n\n"); + + if (g_parm[COND_INDEX][0] != '\0') + { + fprintf(stream, "#if %s\n\n", g_parm[COND_INDEX]); + } + + /* Generate the function definition that matches standard function prototype */ + + fprintf(stream, "%s %s(", g_parm[RETTYPE_INDEX], g_parm[NAME_INDEX]); + + /* Generate the formal parameter list */ + + if (nformal <= 0) + { + fprintf(stream, "void"); + } + else + { + for (i = 0; i < nformal; i++) + { + /* The formal and actual parameter types may be encoded.. extra the + * formal parameter type. + */ + + get_formalparmtype(g_parm[PARM1_INDEX+i], formal); + + /* Arguments after the first must be separated from the preceding + * parameter with a comma. + */ + + if (i > 0) + { + fprintf(stream, ", "); + } + print_formalparm(stream, formal, i+1); + } + } + + /* Handle the end of the formal parameter list */ + + if (bvarargs) + { + fprintf(stream, ", ...)\n{\n"); + + /* Get parm variables .. some from the parameter list and others from + * the varargs. + */ + + if (nparms < 7) + { + fprintf(stream, " va_list ap;\n"); + for (i = nparms; i < 7; i++) + { + fprintf(stream, " uintptr_t parm%d;\n", i); + } + + fprintf(stream, "\n va_start(ap, parm%d);\n", nparms-1); + for (i = nparms; i < 7; i++) + { + fprintf(stream, " parm%d = va_arg(ap, uintptr_t);\n", i); + } + fprintf(stream, " va_end(ap);\n\n"); + } + } + else + { + fprintf(stream, ")\n{\n"); + } + + /* Generate the system call. Functions that do not return or return void + * are special cases. + */ + + nactual = bvarargs ? 6 : nparms; + if (strcmp(g_parm[RETTYPE_INDEX], "void") == 0) + { + fprintf(stream, " (void)sys_call%d(", nactual); + } + else + { + fprintf(stream, " return (%s)sys_call%d(", g_parm[RETTYPE_INDEX], nactual); + } + + /* Create the parameter list with the matching types. The first parameter + * is always the syscall number. + */ + + fprintf(stream, "(unsigned int)SYS_%s", g_parm[NAME_INDEX]); + + for (i = 0; i < nactual; i++) + { + /* Is the parameter a union member */ + + if (i < nparms && is_union(g_parm[PARM1_INDEX+i])) + { + /* Then we will have to pick a field name that can be cast to a + * uintptr_t. There probably should be some error handling here + * to catch the case where the fieldname was not supplied. + */ + + get_fieldname(g_parm[PARM1_INDEX+i], fieldname); + fprintf(stream, ", (uintptr_t)parm%d.%s", i+1, fieldname); + } + else + { + fprintf(stream, ", (uintptr_t)parm%d", i+1); + } + } + + /* Handle the tail end of the function. */ + + fprintf(stream, ");\n}\n\n"); + if (g_parm[COND_INDEX][0] != '\0') + { + fprintf(stream, "#endif /* %s */\n", g_parm[COND_INDEX]); + } + + fclose(stream); +} + +static FILE *open_stub(void) +{ + if (g_inline) + { + if (!g_stubstream) + { + g_stubstream = fopen("STUB.h", "w"); + if (g_stubstream == NULL) + { + fprintf(stderr, "Failed to open STUB.h: %s\n", strerror(errno)); + exit(9); + } + fprintf(g_stubstream, "/* Autogenerated STUB header file */\n\n"); + fprintf(g_stubstream, "#ifndef __STUB_H\n"); + fprintf(g_stubstream, "#define __STUB_H\n\n"); + } + + return g_stubstream; + } + else + { + char filename[MAX_PARMSIZE+8]; + FILE *stream; + + snprintf(filename, MAX_PARMSIZE+7, "STUB_%s.c", g_parm[NAME_INDEX]); + filename[MAX_PARMSIZE+7] = '\0'; + + stream = fopen(filename, "w"); + if (stream == NULL) + { + fprintf(stderr, "Failed to open %s: %s\n", filename, strerror(errno)); + exit(9); + } + return stream; + } +} + +static void stub_close(FILE *stream) +{ + if (!g_inline) + { + fclose(stream); + } +} + +static void generate_stub(int nparms) +{ + FILE *stream = open_stub(); + char formal[MAX_PARMSIZE]; + char actual[MAX_PARMSIZE]; + int i; + int j; + + /* Generate "up-front" information, include correct header files */ + + fprintf(stream, "/* Auto-generated %s stub file -- do not edit */\n\n", g_parm[0]); + fprintf(stream, "#include \n"); + fprintf(stream, "#include \n"); + fprintf(stream, "#include <%s>\n\n", g_parm[HEADER_INDEX]); + + if (g_parm[COND_INDEX][0] != '\0') + { + fprintf(stream, "#if %s\n\n", g_parm[COND_INDEX]); + } + + /* Generate the function definition that matches standard function prototype */ + + if (g_inline) + { + fprintf(stream, "static inline "); + } + fprintf(stream, "uintptr_t STUB_%s(", g_parm[NAME_INDEX]); + + /* Generate the formal parameter list. A function received no parameters is a special case. */ + + if (nparms <= 0) + { + fprintf(stream, "void"); + } + else + { + for (i = 0; i < nparms; i++) + { + /* Treat the first argument in the list differently from the others.. + * It does not need a comma before it. + */ + + if (i > 0) + { + /* Check for a variable number of arguments */ + + if (is_vararg(g_parm[PARM1_INDEX+i], i, nparms)) + { + /* Always receive six arguments in this case */ + + for (j = i+1; j <= 6; j++) + { + fprintf(stream, ", uintptr_t parm%d", j); + } + } + else + { + fprintf(stream, ", uintptr_t parm%d", i+1); + } + } + else + { + fprintf(stream, "uintptr_t parm%d", i+1); + } + } + } + fprintf(stream, ")\n{\n"); + + /* Then call the proxied function. Functions that have no return value are + * a special case. + */ + + if (strcmp(g_parm[RETTYPE_INDEX], "void") == 0) + { + fprintf(stream, " %s(", g_parm[NAME_INDEX]); + } + else + { + fprintf(stream, " return (uintptr_t)%s(", g_parm[NAME_INDEX]); + } + + /* The pass all of the system call parameters, casting to the correct type + * as necessary. + */ + + for (i = 0; i < nparms; i++) + { + /* Get the formal type of the parameter, and get the type that we + * actually have to cast to. For example for a formal type like 'int parm[]' + * we have to cast the actual parameter to 'int*'. The worst is a union + * type like 'union sigval' where we have to cast to (union sigval)((FAR void *)parm) + * -- Yech. + */ + + get_formalparmtype(g_parm[PARM1_INDEX+i], formal); + get_actualparmtype(g_parm[PARM1_INDEX+i], actual); + + /* Treat the first argument in the list differently from the others.. + * It does not need a comma before it. + */ + + if (i > 0) + { + /* Check for a variable number of arguments */ + + if (is_vararg(actual, i, nparms)) + { + /* Always pass six arguments */ + + for (j = i+1; j <=6; j++) + { + fprintf(stream, ", parm%d", j); + } + } + else + { + if (is_union(formal)) + { + fprintf(stream, ", (%s)((%s)parm%d)", formal, actual, i+1); + } + else + { + fprintf(stream, ", (%s)parm%d", actual, i+1); + } + } + } + else + { + if (is_union(formal)) + { + fprintf(stream, "(%s)((%s)parm%d)", formal, actual, i+1); + } + else + { + fprintf(stream, "(%s)parm%d",actual, i+1); + } + } + } + + /* Tail end of the function. If the proxied function has no return + * value, just return zero (OK). + */ + + if (strcmp(g_parm[RETTYPE_INDEX], "void") == 0) + { + fprintf(stream, ");\n return 0;\n}\n\n"); + } + else + { + fprintf(stream, ");\n}\n\n"); + } + + if (g_parm[COND_INDEX][0] != '\0') + { + fprintf(stream, "#endif /* %s */\n", g_parm[COND_INDEX]); + } + stub_close(stream); +} + +static void show_usage(const char *progname) +{ + fprintf(stderr, "USAGE: %s [-p|s|i] \n\n", progname); + fprintf(stderr, "Where:\n\n"); + fprintf(stderr, "\t-p : Generate proxies\n"); + fprintf(stderr, "\t-s : Generate stubs\n"); + fprintf(stderr, "\t-i : Generate proxies as static inline functions\n"); + exit(1); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + char *csvpath; + bool proxies = false; + FILE *stream; + char *ptr; + int ch; + + /* Parse command line options */ + + g_debug = false; + g_inline = false; + + while ((ch = getopt(argc, argv, ":dps")) > 0) + { + switch (ch) + { + case 'd' : + g_debug = true; + break; + + case 'p' : + proxies = true; + break; + + case 's' : + proxies = false; + break; + + case 'i' : + g_inline = true; + break; + + case '?' : + fprintf(stderr, "Unrecognized option: %c\n", optopt); + show_usage(argv[0]); + + case ':' : + fprintf(stderr, "Missing option argument, option: %c\n", optopt); + show_usage(argv[0]); + + break; + fprintf(stderr, "Unexpected option: %c\n", ch); + show_usage(argv[0]); + } + } + + if (optind >= argc) + { + fprintf(stderr, "Missing \n"); + show_usage(argv[0]); + } + + csvpath = argv[optind]; + if (++optind < argc) + { + fprintf(stderr, "Unexpected garbage at the end of the line\n"); + show_usage(argv[0]); + } + + /* Open the CSV file */ + + stream= fopen(csvpath, "r"); + if (!stream) + { + fprintf(stderr, "open %s failed: %s\n", csvpath, strerror(errno)); + exit(3); + } + + /* Process each line in the CVS file */ + + while ((ptr = read_line(stream)) != NULL) + { + /* Parse the line from the CVS file */ + + int nargs = parse_csvline(ptr); + if (nargs < PARM1_INDEX) + { + fprintf(stderr, "Only %d arguments found: %s\n", nargs, g_line); + exit(8); + } + + if (proxies) + { + generate_proxy(nargs - PARM1_INDEX); + } + else + { + g_stubstream = NULL; + generate_stub(nargs - PARM1_INDEX); + if (g_stubstream != NULL) + { + fprintf(g_stubstream, "\n#endif /* __STUB_H */\n"); + fclose(g_stubstream); + } + } + } + + /* Close the CSV file */ + + fclose(stream); + return 0; +} diff --git a/nuttx/tools/mkversion.c b/nuttx/tools/mkversion.c new file mode 100644 index 0000000000..f2086d13a5 --- /dev/null +++ b/nuttx/tools/mkversion.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * tools/mkversion.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "cfgparser.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define DEFCONFIG ".version" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + static inline char *getfilepath(const char *name) +{ + snprintf(line, PATH_MAX, "%s/" DEFCONFIG, name); + line[PATH_MAX] = '\0'; + return strdup(line); +} + +static void show_usage(const char *progname) +{ + fprintf(stderr, "USAGE: %s \n", progname); + exit(1); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + char *filepath; + FILE *stream; + + if (argc != 2) + { + fprintf(stderr, "Unexpected number of arguments\n"); + show_usage(argv[0]); + } + + filepath = getfilepath(argv[1]); + if (!filepath) + { + fprintf(stderr, "getfilepath failed\n"); + exit(2); + } + + stream= fopen(filepath, "r"); + if (!stream) + { + fprintf(stderr, "open %s failed: %s\n", filepath, strerror(errno)); + exit(3); + } + + printf("/* version.h -- Autogenerated! Do not edit. */\n\n"); + printf("#ifndef __INCLUDE_NUTTX_VERSION_H\n"); + printf("#define __INCLUDE_NUTTX_VERSION_H\n\n"); + parse_file(stream); + printf("\n#define CONFIG_VERSION ((CONFIG_VERSION_MAJOR << 8) | (CONFIG_VERSION_MINOR))\n\n"); + printf("#endif /* __INCLUDE_NUTTX_VERSION_H */\n"); + fclose(stream); + return 0; +} diff --git a/nuttx/tools/pic32mx/Makefile b/nuttx/tools/pic32mx/Makefile new file mode 100644 index 0000000000..040cf58cc8 --- /dev/null +++ b/nuttx/tools/pic32mx/Makefile @@ -0,0 +1,51 @@ +############################################################################ +# tools/pic32mx//Makefile +# +# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +all: mkpichex +default: mkpichex +.PHONY: clean + +# Add CFLAGS=-g on the make command line to build debug versions + +CFLAGS = -O2 -Wall -I. + +# mkpichex - Convert virtual addresses in nuttx.hex to physical addresses + +mkconfig: mkpichex.c mkpichex.c + @gcc $(CFLAGS) -o mkpichex mkpichex.c + +clean: + @rm -f *.o *.a *~ .*.swp + @rm -f mkpichex mkpichex.exe diff --git a/nuttx/tools/pic32mx/mkpichex.c b/nuttx/tools/pic32mx/mkpichex.c new file mode 100644 index 0000000000..14fefdb8c6 --- /dev/null +++ b/nuttx/tools/pic32mx/mkpichex.c @@ -0,0 +1,315 @@ +/**************************************************************************** + * tools/pic32mx//mkpichex.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAX_LINE 1024 + +/* Line offsets */ + +#define START_OFFSET 0 +#define LEN_OFFSET 1 +#define ADDR_OFFSET (LEN_OFFSET + 2) +#define TYPE_OFFSET (ADDR_OFFSET + 4) +#define PAYLOAD_OFFSET (TYPE_OFFSET + 2) +#define CHKSUM_OFFSET(n) (PAYLOAD_OFFSET+2*(n)) + +/* Record types: + * + * 00, data record, contains data and 16-bit address. The format described + * above. + * 01, End Of File record, a file termination record. No data. Has to be + * the last line of the file, only one per file permitted. Usually + * ':00000001FF'. Originally the End Of File record could contain a + * start address for the program being loaded, e.g. :00AB2F0125 + * would make a jump to address AB2F. This was convenient when programs + * were loaded from punched paper tape. + * 02, Extended Segment Address Record, segment-base address. Used when 16 + * bits are not enough, identical to 80x86 real mode addressing. The + * address specified by the 02 record is multiplied by 16 (shifted 4 + * bits left) and added to the subsequent 00 record addresses. This + * allows addressing of up to a megabyte of address space. The address + * field of this record has to be 0000, the byte count is 02 (the segment + * is 16-bit). The least significant hex digit of the segment address is + * always 0. + * 03, Start Segment Address Record. For 80x86 processors, it specifies the + * initial content of the CS:IP registers. The address field is 0000, the + * byte count is 04, the first two bytes are the CS value, the latter two + * are the IP value. + * 04, Extended Linear Address Record, allowing for fully 32 bit addressing. + * The address field is 0000, the byte count is 02. The two data bytes + * represent the upper 16 bits of the 32 bit address, when combined with + * the address of the 00 type record. + * 05, Start Linear Address Record. The address field is 0000, the byte + * count is 04. The 4 data bytes represent the 32-bit value loaded into + * the EIP register of the 80386 and higher CPU. + */ + +#define TYPE_DATA 0 +#define TYPE_EOF 1 +#define TYPE_EXTSEG 2 +#define TYPE_STARTSEG 3 +#define TYPE_EXTLIN 4 +#define TYPE_STARTLIN 5 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct hex_s +{ + unsigned char len; /* Length of the data payload */ + unsigned char type; /* Record type */ + unsigned short addr; /* Lower 16-bit address */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static char line[MAX_LINE+1]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline char *getfilepath(const char *path, const char *name, const char *extension) +{ + snprintf(line, MAX_LINE, "%s/%s.%s", path, name, extension); + line[MAX_LINE] = '\0'; + return strdup(line); +} + +static void show_usage(const char *progname) +{ + fprintf(stderr, "USAGE: %s \n", progname); + exit(1); +} + +static unsigned char get4(char hex) +{ + if (hex >= '0' && hex <= '9') + { + return hex - '0'; + } + else if (hex >= 'a' && hex <= 'f') + { + return hex - 'a' + 10; + } + else if (hex >= 'A' && hex <= 'F') + { + return hex - 'A' + 10; + } + + fprintf(stderr, "Bad hex character code: %s\n", line); + exit(2); +} + +static unsigned char get8(const char *ptr) +{ + return get4(ptr[0]) << 4 | get4(ptr[1]); +} + +static unsigned short get16(const char *ptr) +{ + return (unsigned short)get8(&ptr[0]) << 8 | (unsigned short)get8(&ptr[2]); +} + +static int parse_line(struct hex_s *hexline) +{ + /* :LLAAAATT... */ + + if (line[START_OFFSET] != ':') + { + fprintf(stderr, "Bad start code: %s\n", line); + return 1; + } + + hexline->len = get8(&line[LEN_OFFSET]); + hexline->addr = get16(&line[ADDR_OFFSET]); + hexline->type = get8(&line[TYPE_OFFSET]); + return 0; +} + +#if 0 +static unsigned char checksum(chksum_ndx) +{ + int chksum = 0; + int ndx; + + for (ndx = 1; ndx < chksum_ndx; ndx += 2) + { + chksum += (int)get8(&line[ndx]); + } + return (unsigned char)((-chksum) & 0xff); +} +#endif + +static void adjust_extlin(struct hex_s *hexline) +{ + unsigned short segment; + int chksum; + + /* Make sure that the payload is exactly 2 bytes */ + + if (hexline->len != 2) + { + fprintf(stderr, "Bad length on extended segment address record\n"); + fprintf(stderr, " %s", line); + } + + /* And the address field is supposed to be zero */ + + if (hexline->addr != 0) + { + fprintf(stderr, "Bad address on extended segment address record\n"); + fprintf(stderr, " %s", line); + } + + /* Decode the 2 byte payload */ + + segment = get16(&line[PAYLOAD_OFFSET]); + + /* Convert the address to a 29-bit physical address */ + + segment &= 0x1fff; + + /* Recalculate the checksum and make sure that there is a null terminator + * Since len=2, addr=0, type=4, the is a trivial calculation. + */ + + chksum = (-(segment + (segment >> 8) + 6)) & 0xff; + + /* Then create the new output record */ + + snprintf(line, MAX_LINE-PAYLOAD_OFFSET, ":02000004%04X%02X\n", segment, chksum); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + struct hex_s hexline; + char *srcfile; + char *destfile; + FILE *src; + FILE *dest; + + if (argc != 2) + { + fprintf(stderr, "Unexpected number of arguments\n"); + show_usage(argv[0]); + } + + srcfile = getfilepath(argv[1], "nuttx", "hex"); + if (!srcfile) + { + fprintf(stderr, "getfilepath failed\n"); + exit(2); + } + + destfile = getfilepath(argv[1], "nuttx", "tmp"); + if (!destfile) + { + fprintf(stderr, "getfilepath failed\n"); + exit(2); + } + + src = fopen(srcfile, "r"); + if (!src) + { + fprintf(stderr, "open %s failed: %s\n", srcfile, strerror(errno)); + exit(3); + } + + dest = fopen(destfile, "w"); + if (!dest) + { + fprintf(stderr, "open %s failed: %s\n", destfile, strerror(errno)); + exit(3); + } + + /* Read each line from the source file */ + + while (fgets(line, MAX_LINE, src) != NULL) + { + if (parse_line(&hexline)) + { + fprintf(stderr, "Failed to parse line\n"); + exit(1); + } + + /* Adjust 'Extended Segment Address Records'. */ + + if (hexline.type == TYPE_EXTLIN) + { + adjust_extlin(&hexline); + } + fputs(line, dest); + } + + fclose(src); + fclose(dest); + + /* Remove the original nuttx.hex file */ + + if (remove(srcfile) != 0) + { + fprintf(stderr, "Failed to remove the old '%s'\n", srcfile); + + } + + /* Rename the new nuttx.tmp file to nuttx.hex */ + + if (rename(destfile, srcfile) != 0) + { + fprintf(stderr, "Failed to rename '%s' to '%s'\n", destfile, srcfile); + } + + return 0; +} diff --git a/nuttx/tools/unlink.sh b/nuttx/tools/unlink.sh new file mode 100755 index 0000000000..47079f0852 --- /dev/null +++ b/nuttx/tools/unlink.sh @@ -0,0 +1,70 @@ +#!/bin/bash +############################################################################ +# tools/unlink.sh +# +# Copyright (C) 2008 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +link=$1 + +# Verify that arguments were provided + +if [ -z "${link}" ]; then + echo "Missing link argument" + exit 1 +fi + +# Check if something already exists at the link path + +if [ -e "${link}" ]; then + + # Yes, is it a symbolic link? If so, then remove it + + if [ -h "${link}" ]; then + rm -f "${link}" + else + + # If the path is a directory and contains the "fake link" mark, then + # treat it like a soft link (i.e., remove the directory) + + if [ -d "${link}" -a -f "${link}/.fakelnk" ]; then + rm -rf "${link}" + else + + # It is something else (like a file) or directory that does + # not contain the "fake link" mark + + echo "${link} already exists but is not a symbolic link" + exit 1 + fi + fi +fi \ No newline at end of file diff --git a/nuttx/tools/version.sh b/nuttx/tools/version.sh new file mode 100755 index 0000000000..7cad7ee032 --- /dev/null +++ b/nuttx/tools/version.sh @@ -0,0 +1,135 @@ +#!/bin/bash +# version.sh +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +WD=`pwd` + +# Get command line parameters + +USAGE="USAGE: $0 [-d|-h] [-b build] -v " +ADVICE="Try '$0 -h' for more information" + +unset VERSION +unset BUILD +unset OUTFILE + +while [ ! -z "$1" ]; do + case $1 in + -b ) + shift + BUILD=$1 + ;; + -d ) + set -x + ;; + -v ) + shift + VERSION=$1 + ;; + -h ) + echo "$0 is a tool for generation of proper version files for the NuttX build" + echo "" + echo $USAGE + echo "" + echo "Where:" + echo " -d" + echo " Enable script debug" + echo " -h" + echo " show this help message and exit" + echo " -v " + echo " The NuttX version number expressed a major and minor number separated" + echo " by a period" + echo " " + echo " The full path to the version file to be created" + exit 0 + ;; + * ) + break; + ;; + esac + shift +done + +OUTFILE=$1 + +# Make sure we know what is going on + +if [ -z ${VERSION} ] ; then + echo "Missing versioning information" + echo $USAGE + echo $ADVICE + exit 1 +fi + +if [ -z ${OUTFILE} ] ; then + echo "Missing path to the output file" + echo $USAGE + echo $ADVICE + exit 1 +fi + +# Get the major and minor version numbers + +MAJOR=`echo ${VERSION} | cut -d'.' -f1` +if [ "X${MAJOR}" = "X${VERSION}" ]; then + echo "Missing minor version number" + echo $USAGE + echo $ADVICE + exit 2 +fi +MINOR=`echo ${VERSION} | cut -d'.' -f2` + +# Get SVN information (if not provided on the command line) + +if [ -z "${BUILD}" ]; then + SVNINFO=`svn info 2>/dev/null | fgrep 'Revision:'` + if [ -z "${SVNINFO}" ]; then + echo "SVN version information is not available" + exit 3 + fi + BUILD=`echo ${SVNINFO} | cut -d' ' -f2` + if [ -z "${BUILD}" ]; then + echo "SVN build information not found" + exit 4 + fi +fi + +# Write a version file into the NuttX directoy. The syntax of file is such that it +# may be sourced by a bash script or included by a Makefile. + +echo "#!/bin/bash" >${OUTFILE} +echo "" >>${OUTFILE} +echo "CONFIG_VERSION_STRING=\"${VERSION}\"" >>${OUTFILE} +echo "CONFIG_VERSION_MAJOR=${MAJOR}" >>${OUTFILE} +echo "CONFIG_VERSION_MINOR=${MINOR}" >>${OUTFILE} +echo "CONFIG_VERSION_BUILD=${BUILD}" >>${OUTFILE} diff --git a/nuttx/tools/winlink.sh b/nuttx/tools/winlink.sh new file mode 100755 index 0000000000..c081cee35f --- /dev/null +++ b/nuttx/tools/winlink.sh @@ -0,0 +1,102 @@ +#!/bin/bash +############################################################################ +# tools/winlink.sh +# +# Copyright (C) 2008 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ +# +# NuttX uses symbolic links to configure platform-specific directories into +# the build system. This works great except for when a Windows native +# toolchain is used in a Cygwin environment. In that case, symbolic +# links do not work correctly when accessed from the Windows native toolchain; +# rather, just look link files with the extension .lnk +# +# In this environment, the build system will work around this using this script +# as a replacement for the 'ln' command. This scrpt will simply copy the +# directory into the expected positiion. +# +#set -x + +src=$1 +dest=$2 + +# Verify that arguments were provided + +if [ -z "${src}" -o -z "${dest}" ]; then + echo "Missing src and/or dest arguments" + exit 1 +fi + +# Check if something already exists at the destination path replace it with +# the new link (which might be different). Note that we check for the +# the link (-h) before we check for existence (-e) because a bad link will +# report that it does not exist. + +if [ -h "${dest}" ]; then + rm -f "${dest}" +else + + # If the path exists and is a directory that contains the "fake link" + # mark, then treat it like a soft link (i.e., remove the directory) + + if [ -d "${dest}" -a -f "${dest}/.fakelnk" ]; then + rm -rf "${dest}" + else + + # Does anything exist at the destination path? + + if [ -e "${dest}" ]; then + + # It is something else (like a file) or directory that does + # not contain the "fake link" mark + + echo "${dest} already exists but is not a symbolic link" + exit 1 + fi + fi +fi + + +# Verify that a directory exists at the source path + +if [ ! -d "${src}" ]; then + echo "No directory at ${src}" + exit 1 +fi + +# Copy the directory + +cp -a "${src}" "${dest}" || \ + { echo "Failed to create link: $dest" ; rm -rf ${dest} ; exit 1 ; } +touch "${dest}/.fakelnk" || \ + { echo "Failed to touch ${dest}/.fakelnk" ; rm -rf ${dest} ; exit 1 ; } + diff --git a/nuttx/tools/zipme.sh b/nuttx/tools/zipme.sh new file mode 100755 index 0000000000..a10beaaab4 --- /dev/null +++ b/nuttx/tools/zipme.sh @@ -0,0 +1,178 @@ +#!/bin/bash +# zipme.sh +# +# Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +#set -x + +WD=`pwd` +VERSION=$1 + +TAR="tar cvf" +ZIP=gzip + +# Make sure we know what is going on + +if [ -z ${VERSION} ] ; then + echo "You must supply a version like xx.yy as a parameter" + exit 1; +fi + +# Find the directory we were executed from and were we expect to +# see the directories to tar up + +MYNAME=`basename $0` + +if [ -x ${WD}/${MYNAME} ] ; then + TRUNKDIR="${WD}/../.." +else + if [ -x ${WD}/tools/${MYNAME} ] ; then + TRUNKDIR="${WD}/.." + else + if [ -x ${WD}/nuttx-${VERSION}/tools/${MYNAME} ] ; then + TRUNKDIR="${WD}" + else + echo "You must cd into the NUTTX directory to execute this script." + exit 1 + fi + fi +fi + +# Get the NuttX directory names and the path to the parent directory + +NUTTX=${TRUNKDIR}/nuttx-${VERSION} +APPDIR=${TRUNKDIR}/apps-${VERSION} + +# Make sure that the versioned directory exists + +if [ ! -d ${TRUNKDIR} ]; then + echo "Directory ${TRUNKDIR} does not exist" + exit 1 +fi + +cd ${TRUNKDIR} || \ + { echo "Failed to cd to ${TRUNKDIR}" ; exit 1 ; } + +if [ ! -d nuttx-${VERSION} ] ; then + echo "Directory ${TRUNKDIR}/nuttx-${VERSION} does not exist!" + exit 1 +fi + +if [ ! -d apps-${VERSION} ] ; then + echo "Directory ${TRUNKDIR}/apps-${VERSION} does not exist!" + exit 1 +fi + +# Create the versioned tarball names + +NUTTX_TARNAME=nuttx-${VERSION}.tar +APPS_TARNAME=apps-${VERSION}.tar +NUTTX_ZIPNAME=${NUTTX_TARNAME}.gz +APPS_ZIPNAME=${APPS_TARNAME}.gz + +# Prepare the nuttx directory -- Remove editor garbage + +find ${TRUNKDIR} -name '*~' -exec rm -f '{}' ';' || \ + { echo "Removal of emacs garbage failed!" ; exit 1 ; } +find ${TRUNKDIR} -name '*.swp' -exec rm -f '{}' ';' || \ + { echo "Removal of VI garbage failed!" ; exit 1 ; } + +# Make sure that versioned copies of the certain files are in place + +cd ${NUTTX}/Documentation || \ + { echo "Failed to cd to ${NUTTX}/Documentation" ; exit 1 ; } + +cp -f ../TODO TODO.txt +cp -f ../ChangeLog ChangeLog.txt + +# Write a version file into the NuttX directoy. The syntax of file is such that it +# may be sourced by a bash script or included by a Makefile. + +VERSIONSH=${NUTTX}/tools/version.sh +if [ ! -x "${VERSIONSH}" ]; then + echo "No executable script was found at: ${VERSIONSH}" + exit 1 +fi +${VERSIONSH} -v ${VERSION} ${NUTTX}/.version || \ + { echo "${VERSIONSH} failed"; cat ${NUTTX}/.version; exit 1; } +chmod 755 ${NUTTX}/.version + +# Perform a full clean for the distribution + +cd ${TRUNKDIR} || \ + { echo "Failed to cd to ${TRUNKDIR}" ; exit 1 ; } + +make -C ${NUTTX} distclean + +# Remove any previous tarballs + +if [ -f ${NUTTX_TARNAME} ] ; then + echo "Removing ${TRUNKDIR}/${NUTTX_TARNAME}" + rm -f ${NUTTX_TARNAME} || \ + { echo "rm ${NUTTX_TARNAME} failed!" ; exit 1 ; } +fi + +if [ -f ${NUTTX_ZIPNAME} ] ; then + echo "Removing ${TRUNKDIR}/${NUTTX_ZIPNAME}" + rm -f ${NUTTX_ZIPNAME} || \ + { echo "rm ${NUTTX_ZIPNAME} failed!" ; exit 1 ; } +fi + +if [ -f ${APPS_TARNAME} ] ; then + echo "Removing ${TRUNKDIR}/${APPS_TARNAME}" + rm -f ${APPS_TARNAME} || \ + { echo "rm ${APPS_TARNAME} failed!" ; exit 1 ; } +fi + +if [ -f ${APPS_ZIPNAME} ] ; then + echo "Removing ${TRUNKDIR}/${APPS_ZIPNAME}" + rm -f ${APPS_ZIPNAME} || \ + { echo "rm ${APPS_ZIPNAME} failed!" ; exit 1 ; } +fi + +# Then tar and zip-up the directories + +cd ${TRUNKDIR} || \ + { echo "Failed to cd to ${TRUNKDIR}" ; exit 1 ; } + +${TAR} ${NUTTX_TARNAME} nuttx-${VERSION} || \ + { echo "tar of ${NUTTX_TARNAME} failed!" ; exit 1 ; } +${ZIP} ${NUTTX_TARNAME} || \ + { echo "zip of ${NUTTX_TARNAME} failed!" ; exit 1 ; } + +${TAR} ${APPS_TARNAME} apps-${VERSION} || \ + { echo "tar of ${APPS_TARNAME} failed!" ; exit 1 ; } +${ZIP} ${APPS_TARNAME} || \ + { echo "zip of ${APPS_TARNAME} failed!" ; exit 1 ; } + +cd ${NUTTX} +